From cfa07613d837783553c0b38c8a251ee81367f720 Mon Sep 17 00:00:00 2001 From: svcmobrel-release Date: Fri, 27 Sep 2024 12:48:49 -0700 Subject: [PATCH] Updating prebuilts and/or headers e69802011573f0178bf178e270e2645bf7f62df8 - optee_src_build.sh d15f50688485e11293e0d0bd66d73655e79f7718 - nvcommon_build.sh 79e468b5eb3da5dfc49e4d5027cff370177d9699 - optee/tegra234-optee.dts c8e0513c06b701ddb65f4524dded76abdf77647c - optee/optee_os/Makefile 8b3eaf0d1f2e980508aac43f9391b7650d628a35 - optee/optee_os/.clang-format 96558a7a79bf90ebde8720b0087c9c578efa981b - optee/optee_os/.checkpatch.conf f0e65c7d69a4cdd4ca654f479018b5d319c49485 - optee/optee_os/MAINTAINERS d2eb09f40476bdbbdbfa709b1cc0cc80c873f0ee - optee/optee_os/CHANGELOG.md 6bf9bd872a69d8c13e8dcac71fac8d094646251d - optee/optee_os/README.md 3a608e255399bb5cf2302bb52e533d81c469ecce - optee/optee_os/LICENSE.NVIDIA 370d68b1c9485f254e7c701c31e3c74fd16cacd7 - optee/optee_os/LICENSE 25ecfc13bc9b5205cb9db1ffb015fa973c8a754b - optee/optee_os/typedefs.checkpatch a7d5f5139d7b9b81a37f26931af0c4922afdaa69 - optee/optee_os/keys/default_ta.pem 4ec1a9b7d2f64d94ccdaa889afe2cba025e5b33b - optee/optee_os/keys/default.pem 739a223e693f30815eb57c7b1bdae6bc5e2c8028 - optee/optee_os/lib/libunw/unwind_arm32.c 7a5d43bd6596d563ed816f9c1422b44e0b5a1b26 - optee/optee_os/lib/libunw/unwind_riscv.c aa98ee7f2f58e8d9487aef8238db499ea48e9bf7 - optee/optee_os/lib/libunw/unwind_arm64.c 04ec37249588b61e2dfa9cd7874a618b1f27bddd - optee/optee_os/lib/libunw/include/unw/unwind.h be4c6a3071f47d6d836b24e210bc1d446aa9afcc - optee/optee_os/lib/libdl/dlfcn.c 902b546a61d836961ed0f5fe348b564b0583755a - optee/optee_os/lib/libdl/include/dlfcn.h 34cd5767e5498e0e9fbc3ea30953dbb7a30cc6f6 - optee/optee_os/lib/libmbedtls/mbedtls/BUGS.md 23318adb490dc06c5a2e3ec6619ef9ccb2751594 - optee/optee_os/lib/libmbedtls/mbedtls/SECURITY.md c15664798564c531febb48552a2c5b37843e833e - optee/optee_os/lib/libmbedtls/mbedtls/SUPPORT.md 36296c1c4e8e0d763476423778c44dbc04b50bd4 - optee/optee_os/lib/libmbedtls/mbedtls/.uncrustify.cfg b6d56304e5d93a8359613c2c00dd9360ef825323 - optee/optee_os/lib/libmbedtls/mbedtls/README.md 673fcd822394bfa34159701cc14750fea1a03f35 - optee/optee_os/lib/libmbedtls/mbedtls/ChangeLog 2b8b815229aa8a61e483fb4ba0588b8b6c491890 - optee/optee_os/lib/libmbedtls/mbedtls/LICENSE fc289e09626931286b47247438179e2e37b56f5f - optee/optee_os/lib/libmbedtls/mbedtls/CONTRIBUTING.md d44e3c3b56f9fdcb029f34d00b948afd4d6e45e7 - optee/optee_os/lib/libmbedtls/mbedtls/library/version.c 4c895118edfa4ee419cc7796b5185536917ec939 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_client.c 7770ce4815a1ba16ea28e17fc5c528e27440e789 - optee/optee_os/lib/libmbedtls/mbedtls/library/check_crypto_config.h e4ef78ff1d50ef8cadd19f1505ff94f1dac62093 - optee/optee_os/lib/libmbedtls/mbedtls/library/md5.c e5be29bd80ac40ecaad6bcc41abb658bd1c695ca - optee/optee_os/lib/libmbedtls/mbedtls/library/hash_info.h bcdd5b1c541c7197c9ae80b7b41de32ae5b2ad65 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_debug_helpers.h 1dd82643f69b90a342121c72e599b6c3ed613d26 - optee/optee_os/lib/libmbedtls/mbedtls/library/ecdsa.c d1961d06c288f65b5fc6fb506b4a2631b7947227 - optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_mod.h b6638d76665125ba505e4beda15943c8a4b75a8d - optee/optee_os/lib/libmbedtls/mbedtls/library/entropy_poll.h 16359a21196d6070404f14d38f5aef727f2167e1 - optee/optee_os/lib/libmbedtls/mbedtls/library/threading.c fe734580e467840b9b4afa0716fd6e3ffd4942e7 - optee/optee_os/lib/libmbedtls/mbedtls/library/ecjpake.c 5c96237b70f097ac411154f9c56dc1e6bf3b8689 - optee/optee_os/lib/libmbedtls/mbedtls/library/pem.c e3d039b0374d156fb2acf43a47ca8f553955e544 - optee/optee_os/lib/libmbedtls/mbedtls/library/dhm.c 98cd71c1713713bbb6cd199be758b8592a27c42d - optee/optee_os/lib/libmbedtls/mbedtls/library/padlock.c b29e0ceb0e7c97ce7824a79a6fc154dcdf35bca0 - optee/optee_os/lib/libmbedtls/mbedtls/library/ecp.c 84eb33b63afb20735abd67e33ced56e1e69173b9 - optee/optee_os/lib/libmbedtls/mbedtls/library/chachapoly.c 6ee8cc29349d39a34b172357c2d5da549d315813 - optee/optee_os/lib/libmbedtls/mbedtls/library/pk_wrap.c 7271c82b848fda7b11750274f46664ba6a7f7ab0 - optee/optee_os/lib/libmbedtls/mbedtls/library/entropy.c 7d92089bbd60045d1caf07e02223ac6b8e1708cf - optee/optee_os/lib/libmbedtls/mbedtls/library/bn_mul.h 03d4e38794009d4be0452dc243665f871a6025b1 - optee/optee_os/lib/libmbedtls/mbedtls/library/ctr_drbg.c 78f1b75306d2a679d87a1dbcd73cb656c5410cc9 - optee/optee_os/lib/libmbedtls/mbedtls/library/x509_crt.c 01bc4944a27e202656ef9f1fdde863fb9e4de3e3 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls.c 8c9f2ee60d829ece04a767a04a4ef06de9d72139 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_cache.c d95ae27168cedfdd598f6a92654ac3c00f3b67f0 - optee/optee_os/lib/libmbedtls/mbedtls/library/error.c b24a27e4ce8b259ccc9eea73e1bfbd492f70bb99 - optee/optee_os/lib/libmbedtls/mbedtls/library/pkcs7.c 6a234d07608722c41590614b9f0ec2b5e88e7339 - optee/optee_os/lib/libmbedtls/mbedtls/library/padlock.h 739a5f1f19451ca406d2e52b8eec849c62eb53a8 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_ciphersuites.c 99e0a239c9f19e14cf6ce18a3840fb2fca404713 - optee/optee_os/lib/libmbedtls/mbedtls/library/hmac_drbg.c ce8fff546c26c2f14d68f3d3fcf9f20a14c115ce - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_invasive.h 4af04f83c979b6ced3e680a2fa590ac6036c49c9 - optee/optee_os/lib/libmbedtls/mbedtls/library/oid.c e165b12c049a63c601126933df86ac7788533c80 - optee/optee_os/lib/libmbedtls/mbedtls/library/version_features.c eaf09cc7765dd62d5217d239db5866ef14cbbcc5 - optee/optee_os/lib/libmbedtls/mbedtls/library/nist_kw.c f33d29752d62bd5be5b94ab27abcb2c62bfae415 - optee/optee_os/lib/libmbedtls/mbedtls/library/sha256.c b3f01220df7e01b622c4d903e9c40c6cb3203ec7 - optee/optee_os/lib/libmbedtls/mbedtls/library/platform.c ff7a9b66046c0de1a36bcd7c09a2307fb860aeb4 - optee/optee_os/lib/libmbedtls/mbedtls/library/aes.c ff5f51be79458657afcb92b173c63f15e725652a - optee/optee_os/lib/libmbedtls/mbedtls/library/net_sockets.c d9581ba9d5255971f4d9e85adcc8e255e3690af9 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_ticket.c 6e68dbefe68f198625ac005ee1030684626f677e - optee/optee_os/lib/libmbedtls/mbedtls/library/constant_time_internal.h 7727cc53f6d74155b26ee8b5998bf3747bc8697e - optee/optee_os/lib/libmbedtls/mbedtls/library/platform_util.c 3b9243735cc374f8ade3dfa5579640b6911d38a3 - optee/optee_os/lib/libmbedtls/mbedtls/library/chacha20.c 90e90cf98195b7b842e4fe3560dc3af0b98576fe - optee/optee_os/lib/libmbedtls/mbedtls/library/ecp_invasive.h 8404b765bfb0f3d07acd2403655c41357841fbd8 - optee/optee_os/lib/libmbedtls/mbedtls/library/lmots.h 6b031e72d28b388ec56568fb16dbfcd3b49b23df - optee/optee_os/lib/libmbedtls/mbedtls/library/pk.c 15644378eab950e066a06564db258eb38a5628c4 - optee/optee_os/lib/libmbedtls/mbedtls/library/sha512.c 0c28525180d3b52933a129728b8ca9c7b45685ef - optee/optee_os/lib/libmbedtls/mbedtls/library/aesce.h 119003e69094f7f58c5f7b7c8297712eb1c066a6 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_misc.h 19d6760fd47f19624204d669e96410c6f2de2cc8 - optee/optee_os/lib/libmbedtls/mbedtls/library/x509_create.c bb141273d9cc4967730f58c9df9ccf52ebce1c5d - optee/optee_os/lib/libmbedtls/mbedtls/library/cipher.c cba8732c79a4b1f77acfaa6e407abf1f883b1424 - optee/optee_os/lib/libmbedtls/mbedtls/library/pkparse.c 5bd7a8da938d48cedd9875f261fb6189b284d407 - optee/optee_os/lib/libmbedtls/mbedtls/library/x509_crl.c 6732bbddb23ffdbd9f0a76ab9b2c259133fb61a9 - optee/optee_os/lib/libmbedtls/mbedtls/library/x509_csr.c edebd5be7d3d6f1d67ed39ee288f6152cf28ade3 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_debug_helpers_generated.c 1eea4712651b9bbf77f83ce725f1a932493f8894 - optee/optee_os/lib/libmbedtls/mbedtls/library/x509.c baf14771ebe0476dbe644e7bfcc8d62b21c5713f - optee/optee_os/lib/libmbedtls/mbedtls/library/asn1parse.c 5fa68d30e7d3c6a0d10bccf0826c15fc0e9d38a9 - optee/optee_os/lib/libmbedtls/mbedtls/library/pkwrite.c 4509f6798e2fca09d888f42f2ce9ee2da001c307 - optee/optee_os/lib/libmbedtls/mbedtls/library/alignment.h 4a9d15ec9dfd5b5f325d8f087f7190d64edc097e - optee/optee_os/lib/libmbedtls/mbedtls/library/constant_time_invasive.h db65452086da8483b9d6b915fb70a40b948545c3 - optee/optee_os/lib/libmbedtls/mbedtls/library/lms.c 53415759da55cbb415f71e3ebfde42e38a068a50 - optee/optee_os/lib/libmbedtls/mbedtls/library/pkwrite.h 23f18586a432d734114ed496a5c353a1650035f6 - optee/optee_os/lib/libmbedtls/mbedtls/library/asn1write.c 3639af0ef05f1a45d10b37194fa545d2b9bcf993 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_client.h 3ca7167353009560f76e6956baa3bf4b34a563cd - optee/optee_os/lib/libmbedtls/mbedtls/library/md.c 4107f08bc1470b4cf703bd702bd458b67a329e79 - optee/optee_os/lib/libmbedtls/mbedtls/library/aesce.c dc62d3c0502a13a522b51dde3a39f8d9c9f6da3c - optee/optee_os/lib/libmbedtls/mbedtls/library/base64.c 0607553e84acf3ad608f42db5a86151053e21e4b - optee/optee_os/lib/libmbedtls/mbedtls/library/des.c a0955ccbdbfb3c22ecbca9a8f91ed5a3a1e775a3 - optee/optee_os/lib/libmbedtls/mbedtls/library/constant_time.c ce3bfca0ba9327f83686dc6d74a2170ecb14d4ae - optee/optee_os/lib/libmbedtls/mbedtls/library/pkcs5.c 8b9d26205c5224da0964b29edd7a45821daf96db - optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_mod.c e1c3d2e229393412977b04c76cf8c86a4821ea07 - optee/optee_os/lib/libmbedtls/mbedtls/library/gcm.c d90aa1bf42c16ceb4870ae7a3d3678fa4b01fd9d - optee/optee_os/lib/libmbedtls/mbedtls/library/hkdf.c a6c1c10394f80d236c7a242ceaccc0ac6414fe44 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_cookie.c 14353e3414b814893557982d985a03ed8d687abf - optee/optee_os/lib/libmbedtls/mbedtls/library/bignum.c 4ba4b18dcb3a60651d24555a1125a9c2d226af5a - optee/optee_os/lib/libmbedtls/mbedtls/library/x509write_crt.c 85c379cc812b43e8436af3a12ddf9d96cd2ae282 - optee/optee_os/lib/libmbedtls/mbedtls/library/cipher_wrap.c d974cb499431b226552b0132e29b52d624dbf598 - optee/optee_os/lib/libmbedtls/mbedtls/library/hash_info.c 47ddc30fc88488fb374094fa2eceba8e6fad4138 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_keys.h 8628488e4ae680019e691313853788e572480181 - optee/optee_os/lib/libmbedtls/mbedtls/library/aria.c 246d2c4b6bcd2bc5d8caa3c647b4849dbde31334 - optee/optee_os/lib/libmbedtls/mbedtls/library/pk_wrap.h 4b81ddd5a55b6605b66c2ef896883cbd83513d12 - optee/optee_os/lib/libmbedtls/mbedtls/library/lmots.c eb190023507c8a4e75925189905512116ee2ff9b - optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_mod_raw.h 2293962f77728a8f33e100aed92d7766a1a2bc57 - optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_mod_raw.c 71d11dea6aa1fca13aaaddd6c4c9a53dd0a6d243 - optee/optee_os/lib/libmbedtls/mbedtls/library/ecp_curves.c 67958d1e91e6df087bcc331a433b33985307df71 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_server.c 6c0519e9add157846123cb46d3dcb2e90afdb0e4 - optee/optee_os/lib/libmbedtls/mbedtls/library/md_wrap.h 1c1eacc97bf0cef27c7814ef8505fa0698c5ba6b - optee/optee_os/lib/libmbedtls/mbedtls/library/common.h 6c39e72e1686552144f2e5d1bb7e61b35c9f24d4 - optee/optee_os/lib/libmbedtls/mbedtls/library/timing.c b5af70ad6da2f4b68ec723d1f31dac17e99bbce8 - optee/optee_os/lib/libmbedtls/mbedtls/library/rsa_alt_helpers.h 7a9dfd9eb3ad4b72c8eabba544aa22bad1b76b82 - optee/optee_os/lib/libmbedtls/mbedtls/library/entropy_poll.c 2e2d37262a4fcf868902f0d8cc7dd769edebdf07 - optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_mod_raw_invasive.h 783f3d68843e641b6aae9942ecf5ee71d880e87c - optee/optee_os/lib/libmbedtls/mbedtls/library/poly1305.c 154a942dbce1fc3eda40ac948f9052a7b64031ed - optee/optee_os/lib/libmbedtls/mbedtls/library/aesni.h 92e4737de82118950ee187100f82cea0f21892b8 - optee/optee_os/lib/libmbedtls/mbedtls/library/sha1.c 4ebf29fb2f2de150df473f3205cbe65f24187d71 - optee/optee_os/lib/libmbedtls/mbedtls/library/pkcs12.c 2a42128d6600aa5ac94c8fa8e33eae58294b9979 - optee/optee_os/lib/libmbedtls/mbedtls/library/aesni.c 50947d3bdc6828a91c5cc87e98ddfad59819b8da - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_client.c a107e54f6aa27c409eca764bbbb57b5076f1d8f7 - optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_core.h 35fd3ec54ab25ba897c90670e275a02b663398fa - optee/optee_os/lib/libmbedtls/mbedtls/library/rsa.c e38a083f5ceeadc8bb63d1affc622d269e051df1 - optee/optee_os/lib/libmbedtls/mbedtls/library/camellia.c 7742da57b8a202b800bbfd228d11ace043e9ff53 - optee/optee_os/lib/libmbedtls/mbedtls/library/ecp_internal_alt.h 08102e4b89e44c02f731eed0e96c6253be58a28a - optee/optee_os/lib/libmbedtls/mbedtls/library/debug.c a1bd10348d84bfb7b7403501fe8ac18c43a5d0bd - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_msg.c c6bb15185e97b9cce4be1b0f1b717c66e7629f85 - optee/optee_os/lib/libmbedtls/mbedtls/library/cmac.c 7eba3b8d085ec63deef34ad378d6ff0dfb8772c6 - optee/optee_os/lib/libmbedtls/mbedtls/library/memory_buffer_alloc.c e1f466c89d96a92b9a5a8ff9e8057b43819ea576 - optee/optee_os/lib/libmbedtls/mbedtls/library/cipher_wrap.h d73c9a1f19fa01faff542a4d4883ee8ea65ca3b4 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_generic.c e3c7fb464c5949f48b961879ae6086786aee3139 - optee/optee_os/lib/libmbedtls/mbedtls/library/ecdh.c 321c43f4130cc3549c34cea35c3bacf190fdd1c1 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls12_client.c b78ab9253ba70b0daf12c1a340d86e30e18af87b - optee/optee_os/lib/libmbedtls/mbedtls/library/ripemd160.c 94dc6df926a5508e2768a3fd5548f5b3fdce5137 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_keys.c 0ac5b7484872759c4f5fbbadc274e323bec14f04 - optee/optee_os/lib/libmbedtls/mbedtls/library/ccm.c 013516f2c5b13515271831f3074dd8483f46a008 - optee/optee_os/lib/libmbedtls/mbedtls/library/rsa_alt_helpers.c d44df335d6040133dd34dc6618136bdc05e3d041 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls12_server.c 65cfbaeb638274d06bb384b2cfffe7a71c327566 - optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_core.c 3efd049c3efff8626c1bb0e3cbf8d805a1cab499 - optee/optee_os/lib/libmbedtls/mbedtls/library/x509write_csr.c 2fa6f5794a2b39f61736225acdc1e506d5e34fc4 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pkcs7.h d1365ec3dcc0d0019b4fad3b9d493349e31f3cc6 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/bignum.h 77a20bc7000287fff180917229509526e46281a1 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/legacy_or_psa.h b5694fa3505daeb7573dd758bd6b653c0de1afc9 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/platform_util.h 3f7ababa154ed97e00cc354a85dd6dfb01bf191a - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/asn1.h 3a7b764d7fb3eda659a0a40d859cb8c11189711f - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/base64.h 964ae1d8e907f310ba4305e2e2fe5eb420e1d44e - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pkcs12.h 83fa40eedddc46f115ecd2b7d694ec480a7c3877 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_cache.h 66a2f6f275b96497eff585c81cf3ed51789cad81 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/platform.h a3c459aa9af3e2b93c623fe18df065d29a669438 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/sha512.h 4d297428c707305b537f3a980013fe78d0402f15 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/debug.h 5fea2e00b7e30a8e8af9dbb928580820ed60a923 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/cmac.h 61cf33a4be261e8b301912b2c000b65663d808dd - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/asn1write.h 3a2eeab85a1baae2bdb391b5533fdecc2a0234a7 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/oid.h 9c535b705238b7772d94d641b302c7f6ccf530e3 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/x509_csr.h 2dcb2e9392425e97aadc4ef0ea9d89d98101190b - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/aes.h dcad3cd68a858d8be40a59270c12554638d3ae73 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/timing.h 17807a5ea8b97b81929fb3617c8fd6d3fd9b5c17 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecdsa.h 7725757926d55789561f174d43a2bb3c559ba3b1 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/x509_crl.h dc30308e03eccc8a141cfe512ac21d04fc4044ac - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/hmac_drbg.h 600cf785bb5f196b192156e07c54ed60119dcb70 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pem.h 680032e2aefe4768ded08425cbc436df6a7063fd - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/psa_util.h 75a2ca90c8514886cb71aefea93b50682fa8a097 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecp.h 6c5cdf212852e356a6d6b59217c19724f9b8a67c - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl.h 88ed65ff99b7a98bdc81116adf4b3cf3b93c3698 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/mbedtls_config.h af055530f86c36845b6cc259e1b5ac2d76a06595 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_ciphersuites.h 5f769959d10aaa928ab2ea49c53683aa7ab446ec - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ccm.h 165d31572d6623a93a30cba0e29da8219f645381 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/threading.h e388025ddb055c304c2192546aaba27fdf13a6f6 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/md.h c1326c4315382c22d36653a2218259f0213e79e6 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/rsa.h 268fc8231ff7d8492dddbfcad58509e0c1674dda - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_cookie.h ac851218aae0791fad561743509193cab88ecc7d - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/sha1.h 1dad42f86d7f7f6757aae9d148fcc01da828b685 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/des.h 84a7c437cb483895988e6c99b5d813fe9cd41b20 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/private_access.h a39c918b9088d3613c149ac45fa6846b8b9e9718 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/version.h 3e3b30db9e4ed323b2f09885bc5d72d553f4af69 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/platform_time.h 290f0392f61186fcf279c42c7af4c748ffdc1077 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ripemd160.h ab6e31829204b25841aa43a557116e39893507b9 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/x509_crt.h 07d8d6633e32f1d7eae45458f894d16e26b7bb56 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/gcm.h 5b7567b30cde9c7af7e07081004a6de7b6da1677 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/chacha20.h 76ef7f16b918ace41a80bab34517b9e1a3bd849a - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pkcs5.h 9f154acc5f1403d57d4e320fc9ab07cafb77b92c - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/nist_kw.h 69e6f5b121e0db62e1e09066bf65e6672e159171 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/config_psa.h 40e4f413f90a3bd0d2707181246aa1f826afed34 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/md5.h 02b2014b160fc815ac10e66428c5a91782d5bc75 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ctr_drbg.h 71cbb1524e95b09856e4292aa796972a65fc2c5e - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/compat-2.x.h bc30314856f913a9bb357c98e82512e2c87fba26 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/check_config.h 56f7cb406aad762ab2e4c9da9fb921f2ed50ff52 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/sha256.h e0cbaac26e5e75327639bdb8c9bbbde147ae7bc3 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/cipher.h ef896f03a4a70fb9f7d571c6407a45ae7c966628 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/build_info.h c5e0f50fa94d537bd48d372d258c986a6a5898ef - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/camellia.h ae94188698121fe0a337e5d7488a1177ba1356d0 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/error.h 2e197e5112b78be40dab23f5ec9ca26f0b7d508f - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/constant_time.h 9f316a2285bbcbbf1359c2ee62b07f0c779242ed - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecdh.h 283e1b401def7ba93ffd27b4951d234c38422f93 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/lms.h 062b24a18b2cef0cd22397570e2d20193bcd2828 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/hkdf.h 155e9ba5f70b0b71503c8a74f18c4ce05e606d6a - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/poly1305.h f7246ab94041815719a72b69676254de11372fe7 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_ticket.h 4f2a63b8c6d3b8d031455f1f23858eaca5fa2866 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/aria.h 25ab17cb92e38c8a12e0a3092d597ff5051ae123 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/x509.h dde4b8c94d7b2068edbc221843a8844aac09d597 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pk.h 2ae504202c3cdb2e397d0585366a20df46740d1a - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/chachapoly.h 4db5552e53a6e7b6f6f53186024695937a440891 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecjpake.h 00722750ae0ad09c5bcb00a4d7475f7a04c6e85f - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/entropy.h 5bc0f0200458b7ec76e2ac5d91b388fa9bb5de43 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/memory_buffer_alloc.h 995fefdf01e797568c300e32af0640ed5a752a0a - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/net_sockets.h db57e0e1844cb5bfe2f2ccb5d4777a86ca46cbc1 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/dhm.h dee3c667186591ed2aaadc40dd7dcacc58d59153 - optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_platform.h df1c30dcd3e39f02ac914b9e5ce58ffe854645a9 - optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_config.h b40b450cd5591203be962595eb2d2ac3460f14c3 - optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_extra.h a6362ed70348246bf4991cc563a8b4afbbb4fe1d - optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_builtin_primitives.h e75b044cb8e16e09cc751c08581aa4a438ecb3ed - optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_sizes.h b4d90f0647f47fa5d3cf20b6a95526b657611c3d - optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_driver_common.h 466672cb252e250e358e3bd653aef09078264614 - optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_builtin_composites.h 7e8e95004150031806caf80fe1ca8acd7cebceb5 - optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_types.h e4b5bd933df2cac806539b80a680ce33fc0f3171 - optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_struct.h 838afa1cf1cde025164212d9144103902a3a8ad4 - optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_driver_contexts_primitives.h e0437efb823b29d8680400d8a77274c18a66ade6 - optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_compat.h ea264bd84d15599d077e90945753dd0ae96e1c9f - optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_values.h 9c07dd65a273431dda589f00c3df456995718771 - optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto.h d36849352ac5ca4d1bdb3a43ffd6b7a8d6f5fef4 - optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_se_driver.h 66c6c3e45cb8b148263fb036fde8a9d9d525abcd - optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_driver_contexts_composites.h 34712c06411d1a00ae58d2857f73d33892be0ef7 - optee/optee_os/lib/libmbedtls/include/mbedtls_config_uta.h a44f5dc58a410538389a74b4cd2fc016b826f839 - optee/optee_os/lib/libmbedtls/include/mbedtls_config_kernel.h 61a92d97bc038e1636f35968f5a75f708383e065 - optee/optee_os/lib/libmbedtls/include/aes_alt.h b68da531ca86368d8d211961616d067dca104cf2 - optee/optee_os/lib/libmbedtls/core/aes_cbc.c 1e3080bd5db0189b057a3f4fa1d45dae9ce59c72 - optee/optee_os/lib/libmbedtls/core/des_ecb.c 53cec4289bac3bbe8e4fc0ebac55b3071878d7db - optee/optee_os/lib/libmbedtls/core/hash.c 89b5b1b09c6141ce6cae83b42b24106dbf5d19d7 - optee/optee_os/lib/libmbedtls/core/sm2-dsa.c 2475b97d485b317cc088b6d1b3842d0bb9e4bd07 - optee/optee_os/lib/libmbedtls/core/aes.c 7cf5fb5fdbffcf6f9ad1ffefde20cb30eb66d58f - optee/optee_os/lib/libmbedtls/core/sm2-kep.c a86c6c8bf63ea21ef2492f49cbc071f2f23a1d35 - optee/optee_os/lib/libmbedtls/core/mbed_helpers.c 3eb60b38bd9b87944a242c659ad68d8aaa8e220f - optee/optee_os/lib/libmbedtls/core/aes_ctr.c 3a1838593a7cbf67a1966456b9e4e441e14368ea - optee/optee_os/lib/libmbedtls/core/aes_ecb.c 7d7d3c3b185a01f15e64f2b4815b1f604ed06cb7 - optee/optee_os/lib/libmbedtls/core/mbed_helpers.h 4be86702d2f54b1d3c9fa62c47c1c16e8f9a5210 - optee/optee_os/lib/libmbedtls/core/sm2-pke.h 9eac1bef00d42cb5d29355da4ff216ab65029708 - optee/optee_os/lib/libmbedtls/core/des3_ecb.c 03091ed4d6dc54646fb16556db614135ab3b3128 - optee/optee_os/lib/libmbedtls/core/bignum.c 7c72db258e4db9095f0efed76d97590d49db1025 - optee/optee_os/lib/libmbedtls/core/ecc.c 12ba008130153663cb6542e80dcdb00d3a09d35c - optee/optee_os/lib/libmbedtls/core/hmac.c bc4a14352a35d7f28ca65fda6e4625eaad768ef2 - optee/optee_os/lib/libmbedtls/core/sm2-pke.c 95257f1b9669bd55e715296a5db0520dfef94dfa - optee/optee_os/lib/libmbedtls/core/des3_cbc.c e5f2f25d4125ec02f8b75e88014c122601fee192 - optee/optee_os/lib/libmbedtls/core/rsa.c 44c09d4b791e9fc7eb12c3090186b990a05f4484 - optee/optee_os/lib/libmbedtls/core/cmac.c 27d0d017d652207089357343fefde8822d574a56 - optee/optee_os/lib/libmbedtls/core/tomcrypt.c 4a3549fe50b6596fa95703bdad942578f79ff095 - optee/optee_os/lib/libmbedtls/core/des_cbc.c 78d30d0ba985e6d4114a2163f83194e58c30ad9b - optee/optee_os/lib/libmbedtls/core/dh.c 98b5b0189cbb8c50b0e303790d23dbf9681647cc - optee/optee_os/lib/libmbedtls/core/sm2-dsa.h 61ba39ae5f3db7e446666d29227a87474f4a6117 - optee/optee_os/lib/libutee/tee_socket_pta.c 6a2bd30d6d4442e50515c09a081afd22562e62a8 - optee/optee_os/lib/libutee/base64.h 8e021ba886ee4c9113f7e5f943eff836e70d9c62 - optee/optee_os/lib/libutee/tee_api_arith_mpi.c 077681c818e3003b52065a80dbacbd498dff6b29 - optee/optee_os/lib/libutee/tee_api_private.h 8fa85961841aca5f32b051d7c2137dce6048c90a - optee/optee_os/lib/libutee/trace_ext.c 756eb32d34c8adc8518381acb1da0e71abfc07c9 - optee/optee_os/lib/libutee/assert.c 2f5ffed76f45e88e6a21f21030600fdf1485141c - optee/optee_os/lib/libutee/tee_api.c dc820097b9daaecdbebb44d2745b59ab6c868b3c - optee/optee_os/lib/libutee/user_ta_entry_compat.c de26a71b90cb412c9efc752727836f54fb1d95b9 - optee/optee_os/lib/libutee/tee_api_objects.c 2a8949363bf9be408cbddf09c072982132988ffc - optee/optee_os/lib/libutee/abort.c 505da116e55bfaee3c94a6db710ef70a860f9bf1 - optee/optee_os/lib/libutee/tcb.c b4d75c22cea319de57b7d095ce76316fa38d1506 - optee/optee_os/lib/libutee/base64.c 9389ec3691da465689f9ef3c7e4a843bdad07389 - optee/optee_os/lib/libutee/tee_tcpudp_socket.c 0fb276adf148a0417f0f9fd329ccf1c340b3c582 - optee/optee_os/lib/libutee/tee_api_property.c 45c1ba4438be0ecfb4d4bca51534640836b8c995 - optee/optee_os/lib/libutee/tee_api_panic.c bc9153018927868009fb5a5e6df2a409ecb13f4c - optee/optee_os/lib/libutee/tee_system_pta.c b1398a9a37ee47f2718169316310a4a16c61166c - optee/optee_os/lib/libutee/tee_uuid_from_str.c cd3c2b81c2fa7237a975213bafcf7ac4e67ff177 - optee/optee_os/lib/libutee/tee_socket_private.h 681df366c32f67cc5a24341f7b96e459d68b2b2e - optee/optee_os/lib/libutee/tee_api_operations.c b9209dd75181e9d8ea1f62de22f752dc82097d5d - optee/optee_os/lib/libutee/user_ta_entry.c 07b4cbc455efb89b2f41b5d8b5b7d58008497abf - optee/optee_os/lib/libutee/arch/riscv/utee_syscalls_rv.S b1ff8027d8f72d6043aefff12c169937335d77c2 - optee/optee_os/lib/libutee/arch/arm/utee_syscalls_a32.S 137080dcbc697e48f567709fe3fda2528f5d40fa - optee/optee_os/lib/libutee/arch/arm/utee_syscalls_a64.S 16e0dc83cf08600fd769832ff1d21611782da066 - optee/optee_os/lib/libutee/arch/arm/gprof/gprof_pta.c 2e2b03efa22c915b6ab0a59c54793e918ae83560 - optee/optee_os/lib/libutee/arch/arm/gprof/gprof_pta.h a2170433362124e5401cea1cf6f4dafaca653856 - optee/optee_os/lib/libutee/arch/arm/gprof/gmon.h 1a3e524ad810227480d10b0d8426c780c85328bb - optee/optee_os/lib/libutee/arch/arm/gprof/gprof.c be6fc3000484b65889ef0ddf1e7a926e364575a8 - optee/optee_os/lib/libutee/arch/arm/gprof/gmon_out.h 5e23b121b492913159ac492c975bc689fe4fe9d5 - optee/optee_os/lib/libutee/include/utee_syscalls.h d6461788cfe9c7fa1812938fccf00428981ca21f - optee/optee_os/lib/libutee/include/pta_rtc.h e3514bd732b3d0be323aae77cdfcbfb736b42fdb - optee/optee_os/lib/libutee/include/tee_internal_api.h aa09af74960113ccd4fb8827d07e4b9140aacf8f - optee/optee_os/lib/libutee/include/arm_user_sysreg.h d6494aea8b2d08af66c5b03901a962d4c23afa5c - optee/optee_os/lib/libutee/include/pta_secstor_ta_mgmt.h 083e406c1b8993f6c0226bf312fcd140b1bc2cc4 - optee/optee_os/lib/libutee/include/pta_imx_digprog.h 989a3f3ba297d8913c040b838c9cab1a5103308f - optee/optee_os/lib/libutee/include/pta_attestation.h 1f3e231e2e68ce744bb262619fadfdb1e8f137a9 - optee/optee_os/lib/libutee/include/tee_arith_internal.h faeceac8862bbe02c984a8839b1e1cae06319dba - optee/optee_os/lib/libutee/include/pta_rng.h c4e212610ccdc55f55421917a843a5b8ddb567c2 - optee/optee_os/lib/libutee/include/pta_imx_ocotp.h c603b51b2bfba8baa7cb2c4dfbaaa421d9461207 - optee/optee_os/lib/libutee/include/tee_api_defines_extensions.h 8981169f89ce2d195a17112b676bb8552d21ad4c - optee/optee_os/lib/libutee/include/tee_api.h 62fdcf80906b4877ba0a4d22e69a0c75e98e8b9b - optee/optee_os/lib/libutee/include/pta_imx_manufacturing_protection.h ce4bc2d3ed7f6c3ecb68a1f98a7f368f7369a286 - optee/optee_os/lib/libutee/include/utee_syscalls_asm.S 80eb8b37eb87886d40dc390c74bfae90f83ea208 - optee/optee_os/lib/libutee/include/pta_socket.h aff5768a908441b37ad3a28350e0b0f6bf0007b0 - optee/optee_os/lib/libutee/include/tee_api_defines.h 9155ede1378206e1762eb2696d1589cb2b620ee6 - optee/optee_os/lib/libutee/include/utee_types.h 591d4ed947e32e0c72a95a7a2514221f1cf9490d - optee/optee_os/lib/libutee/include/pta_gprof.h f6b88edde49c7f79eebc0c3f861b6f19ff685fd1 - optee/optee_os/lib/libutee/include/tee_udpsocket.h 987521c6dd87009f2cad24c545048d20baad76e5 - optee/optee_os/lib/libutee/include/pta_jetson_user_key.h 398b00b2fdfc1d0dd1987e95722a21a6de7413bc - optee/optee_os/lib/libutee/include/pta_device.h 0311b7bfd98a444eeef7c7c89d4e942a84ea6787 - optee/optee_os/lib/libutee/include/tee_ta_api.h 9c2c1f4769d19646dfe1493dfaa1007b8c538af0 - optee/optee_os/lib/libutee/include/rng_pta_client.h 4c169dffab3432c000d70fe610898278c4568483 - optee/optee_os/lib/libutee/include/user_ta_header.h f5d83909e5071e2affc98fc56ac4b941e00ef03a - optee/optee_os/lib/libutee/include/pta_apdu.h 8572ff4140b947a4e4a4b5752d8265fe1ea5b348 - optee/optee_os/lib/libutee/include/pta_scmi_client.h aa7d01574e3506e0ee2f42cdb251145908b75381 - optee/optee_os/lib/libutee/include/elf.h ebea83d32048f9808bd31f5e2dabc5c0314057bb - optee/optee_os/lib/libutee/include/__tee_ipsocket.h bfd21882753009a9bff306c49ea3d6ba0a27715d - optee/optee_os/lib/libutee/include/pta_stm32mp_bsec.h 47e7cf8af6ad09392aa45b94e88e4cc07e54520e - optee/optee_os/lib/libutee/include/tee_syscall_numbers.h 5ca4833e2188ae7c12e8b39f0448c7f3627571c7 - optee/optee_os/lib/libutee/include/__tee_tcpsocket_defines.h ef91d0380fcc7f9a3bb92041f649b2756d3f1282 - optee/optee_os/lib/libutee/include/elf_common.h 34686e9ef3d016d68cb94ca12b860c89349b5eca - optee/optee_os/lib/libutee/include/__tee_tcpsocket_defines_extensions.h f5e7435c16a3b97874cafc61dd32e3e448ea9b79 - optee/optee_os/lib/libutee/include/pta_jetson_ftpm_helper.h f06afef5b0c60b95525e92a721eb9bcfcf6e6d3a - optee/optee_os/lib/libutee/include/remoteproc_pta.h 793d80272b98715200cd83435c35de534049b96e - optee/optee_os/lib/libutee/include/__tee_isocket_defines.h 5d2f8542dbd85a819207cf9201d5c104d1f45799 - optee/optee_os/lib/libutee/include/arm64_user_sysreg.h 4bfb3666782f62ba34d4645501617d1f4b424a98 - optee/optee_os/lib/libutee/include/riscv_user_sysreg.h 5a4c5c4386df019b937e53bdfca5e05bf5f10921 - optee/optee_os/lib/libutee/include/pta_invoke_tests.h 24acf5f9664ccd81af1147a5e2f875e5a303d97a - optee/optee_os/lib/libutee/include/pta_system.h 8ddaf3ec29e785a63a8b8ba266c13abdce68c125 - optee/optee_os/lib/libutee/include/elf32.h 7812d9a6cf27c9c8cb718a2a8824323576ccaf38 - optee/optee_os/lib/libutee/include/tee_api_compat.h 0f06e417dc0b4434790db823616a67697a157404 - optee/optee_os/lib/libutee/include/__tee_udpsocket_defines.h dfe89d4404a213f5751887db149a30135cd07f9a - optee/optee_os/lib/libutee/include/pta_scp03.h f5bd9efbf15469a7a654c4063b66c9cfa7ce476f - optee/optee_os/lib/libutee/include/pta_stats.h f4adab9015698b3a5ad156216c44340a86567794 - optee/optee_os/lib/libutee/include/link.h 5e08d24c95ed9a2dbbcf69ef3896898ad97abc8a - optee/optee_os/lib/libutee/include/tee_internal_api_extensions.h 9a9e2018f6c94451408a11cb0c0be264353a3c7f - optee/optee_os/lib/libutee/include/pta_imx_dek_blob.h ed871d9884b5e4c5c7801d8dfc5f77f30d79d4ec - optee/optee_os/lib/libutee/include/tee_tcpsocket.h 41b79406ff05bc4d3528fca688813e7f88e7d135 - optee/optee_os/lib/libutee/include/tee_isocket.h 1ee95d67db99aa4b7dab212672290e1dcf51e1e6 - optee/optee_os/lib/libutee/include/tee_api_types.h 16a82e5d6e02952d5d445df9b95c3d540e9aaa4b - optee/optee_os/lib/libutee/include/utee_defines.h 0914ffb8eea917ca32ddfd5e9d1e07b08242a132 - optee/optee_os/lib/libutee/include/elf64.h fd26dac1d8ff0a59b77021c57b346cf0d9767c1f - optee/optee_os/lib/libutee/include/pta_widevine.h d84b15deba3ac3edfa192902098d7b012e19893c - optee/optee_os/lib/libutee/include/k3/otp_keywriting_ta.h 69389cffd2f2392d520b42fb8a877d88184eb7ce - optee/optee_os/lib/libutils/isoc/fputc.c 3c0076665f570bb3894f7975c7af19546b24b949 - optee/optee_os/lib/libutils/isoc/stack_check.c adf5b4c7851eccb3ab23eaa51e2c67aaea646dba - optee/optee_os/lib/libutils/isoc/ispunct.c 44884a714f6031d8c9899eda446ab6bd902d63bc - optee/optee_os/lib/libutils/isoc/bget.doc 3871de5c02c34257cb8c03aea71c406eca1389eb - optee/optee_os/lib/libutils/isoc/isupper.c 3072e334c9965c360ee485346541f37b1cade0ce - optee/optee_os/lib/libutils/isoc/strndup.c 9bef02b228d5d11a675a74e974644af7f91dc6ec - optee/optee_os/lib/libutils/isoc/iscntrl.c b2a87efad81c7fc35f3f17a1507b650945a64089 - optee/optee_os/lib/libutils/isoc/fputs.c 486e4ec67949ba32eb52d521355b28c032ea31d4 - optee/optee_os/lib/libutils/isoc/fp.c a426f426e3093d41ca84adcdf9eefd3d37354379 - optee/optee_os/lib/libutils/isoc/isspace.c 3849e364a583d8e2a6b06c73b88cbff340651414 - optee/optee_os/lib/libutils/isoc/isdigit.c fbbd10cc345ddfe50e1ca5ec8a2e936b5cfe396a - optee/optee_os/lib/libutils/isoc/toupper.c 15d9b02b2f680e631dc3cb4acb612c5051534577 - optee/optee_os/lib/libutils/isoc/snprintf.c e50bee77ddab437d58aec0c7d06ad8e70066d752 - optee/optee_os/lib/libutils/isoc/isgraph.c f3a4dd8bf719bba595428ad39e580b4bdb83c0f2 - optee/optee_os/lib/libutils/isoc/isprint.c 05dba8367bdb83c45ecf37dc4146c37431fb7b40 - optee/optee_os/lib/libutils/isoc/bget_malloc.c aae0aea5aeb4c700916f3a0cb796958a066f2033 - optee/optee_os/lib/libutils/isoc/islower.c 07859d16a6f156a7b7d53976c3ea35d8c181c050 - optee/optee_os/lib/libutils/isoc/strdup.c bdba22e240af00ccb765dec28ab938c5e3619bd3 - optee/optee_os/lib/libutils/isoc/isalpha.c 465dccda5f6216b5156acdf8d97692de7a6bc618 - optee/optee_os/lib/libutils/isoc/tolower.c 66446d12deb5b2f6768b0037c5cd7f6bda49c01a - optee/optee_os/lib/libutils/isoc/fwrite.c afbd6bbf47f8aceef9ce91f60a65246aa8579e52 - optee/optee_os/lib/libutils/isoc/write.c 29a7857f6999a06d58d700ca9bd712c157595adc - optee/optee_os/lib/libutils/isoc/isxdigit.c fd0766e5127d24a75662d988de4c18f5686b3020 - optee/optee_os/lib/libutils/isoc/isalnum.c 08ed68e1c3fcaca243143f636c99d7b1c7c325bf - optee/optee_os/lib/libutils/isoc/sprintf.c cc419cf9b3049ca5a067f8efc8b87fb21d16cc17 - optee/optee_os/lib/libutils/isoc/bget.h d7303541082db306fa6b0447bd5aca62f4cb8169 - optee/optee_os/lib/libutils/isoc/bget.c bd92a4e902b8f071cb08e11be594c2cc03b13e0b - optee/optee_os/lib/libutils/isoc/qsort.c 013f93c8f430036a391ce8954024b19664a7bfda - optee/optee_os/lib/libutils/isoc/arch/riscv/setjmp_rv.S dbc715c45b8998c5276e4a7f3dfc71bd81a03947 - optee/optee_os/lib/libutils/isoc/arch/arm/setjmp_a64.S 24bfedc4ffd1c78df045ab1c725bd811b0531bee - optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_ldivmod_a32.S 30211cfa366caf873a7801a7ac8e5828d0518b42 - optee/optee_os/lib/libutils/isoc/arch/arm/setjmp_a32.S 99b85b897d6a461c3fa3c1f9bd54fb771c45ae5c - optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_softfloat.c 6a325e1881f32b8ca7c74367132e75f9318aff08 - optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_ldivmod.c 0519b9fc5474ccc5a5e50b508e05aa1d81b33c3b - optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_divmod.c 4d6df8e998067ae07c67580b5f7f261238c7cdb6 - optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_divmod_a32.S 0f25fedd6c6f397a39b1254cce305242fe230e0b - optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_shift.c eea63204ff2fd371e116939e14a504bd9d17de4c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/README.html 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 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 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 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 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 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 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 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 2e201e03147cc253f93e31812b6cc1fa19c54acc - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftLeft128.c 1a1af8af29ddb0214656df304b31583e97bbe044 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_le_quiet.c 2a8c469188ac72f1647a4e23121d6baab2f46881 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_i64_r_minMag.c b390f4671e459aa98a5e6eba67989a524df502c6 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackToF128.c ed1a42257f7a11ddfb2896bb3db8fa6b6b799910 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_add.c cc9936a7e89313dabf987a759166c6b627c5697f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_f128M.c 5aa2d29c4f2ecefdd83adab4927c2dba794a0a43 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_f128.c 04822aab5f0c58ebdfca756670ddbddf4524258b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_add.c a44f15f379846d39821c025d6b7afe2f94cb4411 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_sqrt.c c62a95ceba02a10b8f43ebf0b1621e6a814f07ad - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToF128.c 321d4491ee122d9ff20f50a5fd4708eec3a9bbc4 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addCarryM.c 67a5f98ae9f74d18b7c83f145618185127a93260 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJam128Extra.c c0e3f7568f5ce015eb6724ca13dcdebf3846138f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_i32.c 23659a34fd66f6a163767159d9191aece60e9833 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_f64.c b8189771723e965a9e94712bfa8135b04f844af1 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackMToI64.c 3f17bb81a05b30c928c6f3dcbd9d6c33f6dd808b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_eq.c 039cc691a2609fb90724786e7ed7be17b006803f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_i32_r_minMag.c 74978af5148ccce4ca51465a934e52d8ff03fb9a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_f32.c ddf3732777273f55557aa33c85aaea98c3017a0d - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToExtF80.c c3d4d8448c3e622688342aa49d892b84716125a5 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_eq128.c bf60482d7a8c7573451dd9d358a4f59882b4ecd8 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_sub.c e0f5d8c33a9db5f50d0fc16b09808a48a8b052b5 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul128MTo256M.c 62e6926f729011d5c3aa3af610ce0b916b919eb4 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_rem.c 0fb28e0101aaab0bd33ae51a05e4b522cea887b3 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_ui64.c 25066beb2f05f436d718c8073ec11ad550f53ef1 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mulAddF64.c 1fb366479cad4034726000f4f22cdbcdcb95a4c0 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_roundToInt.c c87f6f4eb78569c01e3fd0c6caed99232b37a378 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_extF80.c f81c603cb90e956ee8dde34149ac6bd684d4c70a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_lt_quiet.c 2fc25c51a836eb30d5a0215659d5fd8b4dbda2e8 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_lt.c 1d4036336aa49d6961f510e234caf45cba50d995 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_ui64_r_minMag.c 2af1a8917871bcc8c0560e709aa28418d004c97e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_i64_r_minMag.c d64953149b1077f8e6d0848e2fd5506136e6f2d6 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_add.c 71d3ef74fe02e7fe6891e4db41241c5b2e615643 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_extF80M.c 4189613b8730aaff62a01f6254b071b9fd3c8cb6 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_f32.c a091e47127bd1311d2cd2b78353ee99ddfc54100 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftLeftM.c fb72828cc90ce8ac0bb436552fbd39bee0f11d35 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_f128M.c 7fbcbd3346af638125a977564bb94e3a4112db4c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subMagsF64.c 73e3351f07e2c7c7d591555895c25042a56c82fd - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_le.c 28ed562132fa508b794485f84e37ffebf0f45c03 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_f128M.c e5f8702f5072f781a5b4ef72c7ec4db154d75965 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_invalidF128M.c d11f89d0268036c5e2190b2001b08b46df5a1496 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_mul.c 3e0d54c15411c2c997b29fa7132f305ba0986d0c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_ui64_r_minMag.c a04e210c7ba96d0c982f31acdc218a4a63b5326d - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_div.c cc614514257c6b0a721ebfbf2f2eb22e764e75e4 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightM.c 39e684d513bd8e1bc18146fe5b6b41ca6abfb889 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_ui64_r_minMag.c 993bf55183ee975278a5e4c34e658f6f7bd3702e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_sub.c 5f3d886dc9c8533c8093c13f3b4242c66ba17e5a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_ui32_r_minMag.c 4e4a329eebd8c7675a57c1b06f75ff4ac326b2e1 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_tryPropagateNaNExtF80M.c f02ad3fb3c3e82d60532e677d475a578ecdf6a1d - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addExtF80M.c d2e10d43888a0af127c80ebb29261c8c424b217e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_f128M.c 7749e3a634b0f7cb154a734be194e52d612310c5 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_sub128.c 3314b591c37fbe10125dd1047b564db3968c7246 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_isSignalingNaN.c f7e21606f0f60046e7ed31a99520969bf3cff7c5 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subM.c 61342ccf516ad5891a6f2eb1980d37329501ea4e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_le.c 2355160c0a3526eb32abd1d54fb01083a1fbe18a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_countLeadingZeros32.c 5d919ea71a15f028ff7b85cd73d9543cbe322b06 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackMToF128M.c f815fd87ebd1c160aa9ddb1c232c1de58da01072 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_ui32.c 876085f70200480ee30305fa6463d7c6504e7e77 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftLeftM.c dd1f8b3669ce1b87360bd05963ce288acfd9f386 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mulAddF128.c 29d181916bd52d0effa525808e4e4564f56b5ed3 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subMagsF128.c 9b35552cd723623625c63511e14b0e559d678f4f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normExtF80SigM.c df4f91f5c1ef40d1eaec328ca6b879bf095951a7 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_eq_signaling.c 9611fba0e534169527d66900db62b107e96b8e2a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_roundToInt.c 27897b3a3e2b0f5cfd67ca737c35af7cc360c3cf - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_ui64.c 2211257786a567ae6daea47fa4ddd31c0339d328 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_add256M.c 89e1c8f8d93bed98125ee2c0e27f4ad4b87f5f9e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_ui64.c 0d9fe463bfee7b28f85650d68588f7fb47358282 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_lt_quiet.c b37dddeca4634f2e81fadc1fe8c9ec9f9643c56c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_ui32.c e5c280ffda9fadc7cf51f4e49ba880138473c188 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_sqrt.c b6e5c30069ee1bfdeb29301eb988d9b5ef1e6fd7 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_remStepMBy32.c 672608ed7c1150531f5d4e2b3aa274de76f24f44 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_extF80.c 04b228218122ee8f024959ef831393289d417e7e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_extF80M.c 97688d5996165455b0ead5c1973e36b6d096c21f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackMToUI64.c 71874d6de8e801c14005d5b1f68170c3c6c6baba - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_lt_quiet.c 9fbd0b33c76b78481c512902dc4d9a0d67f4f210 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_i32_r_minMag.c 3ad627bba48b5bb63c11c5e86c0081d283f4a13c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackToExtF80.c e0d12d5167bae0c40dc2ee4e8eb79ccb7d7f8709 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToF32.c 082138b2e89a050296984be3e3d195746735edfa - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToF64.c db04e48a5c823e4f060cc56187b01cbb89ee1afc - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_mul.c 03ee79d8d396bc6778c8bd477647f5e7b2035214 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_f32.c 6de7ad17814ec3532d2cc20927580d8cb52c44de - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mulAddF128M.c a6ea63bd09a37c67ab0db5c7378603bc343f7c4a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_lt_quiet.c a4bba6333e9a92cef62ff68ef528240c29173398 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_extF80.c cddf72a19a53f1cc1e2077dbf7e9269f0ba5cf16 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_rem.c d7dec92efc7a7503386861fc8a67b770c78d50fd - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_lt_quiet.c bbb2e442ce63abe6d694eab84ce821e2ec210522 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_lt128.c b48f6bd306c3509038d6c4d283bc189d517d3b4f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_f128.c eed7248a2360c629c3dc0b39a7b019c718c1f8f8 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_roundToInt.c d594421c568958d475a5939b2bc14c195493768f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_le_quiet.c c7030401c4589ebe4ca9df47cdf4473be706e9c8 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_div.c 016a9e65ca19c7f5d3561d54a3fcbddfb6a310ee - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftLeft64To96M.c 9fb6f1767a51f28d28e6af39ffaedc9883363298 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_i32_r_minMag.c 2cbd145a4e3465e12bfd47dc4a52fd75c4e0b427 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_i32_r_minMag.c b28464c7ae4ca7eb7416555259cf21f36e3906ba - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul64To128M.c c04c45b92e29225e1d2e3decc3dfc108ae63b093 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_ui32.c ef40011bbd21ac40df712f0f16dc844ee06aa453 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_add.c f394231a827adbe842d2249d968ff138ad99c20b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normSubnormalF32Sig.c 9783f22f581b7feca4f86660b538b214dd32b129 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam256M.c 4042678da076368eb21bb4ded888e17dd2109b55 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_f64.c f5755b53bfa3d4ada8ed3be7b2e264ca31c83e9b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_sqrt.c 0020d431a9fe3314ba42c1dafe946fbd2ef7e606 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_f32.c f1663c2acfcb26909b23e18b18c43a4aecee1908 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_extF80.c bc52a98da5add09bb146c15a8cc1e524e1e36989 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_f128.c 73f1f3cdf7a70d4d02ddd5d73f8198482d373296 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_f128M.c 47e7b19a3c969e8c6acf899992a2b3dc02ee894f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRight128.c 6772aca13808c91d5fbc62b23e65a9aba99df8ef - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addF128M.c 84791d4f50e8187197aeca69dbef6a333d167fc1 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_f32.c 5e4ff4edf1d3a006c61ca3098f1919088d42dd66 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_isSignalingNaN.c 289aeaf52ea847d12eab9ab91e1b080ae5cc4774 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_mulAdd.c 4dbe7ada2eae098c62ec673be2cb2452390c0a78 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_f128.c 467dcd8f83fcddef3d3402ebcc2c08822c68621e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_compare128M.c 68c9d3e3654c5107bd58185d3632d6e8c4b04687 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_approxRecip32_1.c 6a29d35180197bb865f52b54695f07430e3e06db - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_mul.c c32eb171afa353fe6d96c9fcc1b6bc9116ba3237 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_sub.c 1d30d31c5765c77e617b9969b778019b60c4b1bd - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_i64.c 3166b1b25c791f37186ac5ace33c6369720cd72d - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_f32.c 20b550200dc22a4995a52f7bb20f8177c851d08b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_le_quiet.c 8c11bd928370bc41568ae3c44ed648224268134b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackMToExtF80M.c 622a359dab67eedd5448775dc3204d4f48039034 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_i64.c 757e08593f768490c92840e212583a4ec63dbbf9 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackToF64.c e6b71c319835a3d037818d3ca0d1468b2dd3c325 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_ui64.c bbe0db256dda63763f1a09d9af66cfbfa51c69f6 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_le.c 3e4e1cde87c7d37013c4665489e22a5e653b9e75 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_i32_r_minMag.c 0db18e1a005858944af9123bb29580ebac102bac - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_i64_r_minMag.c 0f29c869a8f46f705f24531b2826deabe579032f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_extF80M.c 809dcde66eb6eff4e7af6a71ab240cdae5c11097 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam128Extra.c 3155ae7f402b23659c4ff5e89bd77c5599ee23e0 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToI32.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 6eb4a2a36946f25f5528e564a0391b709127224b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_eq.c e14e58254cc0fe0ce4710d073c7a4c41961df960 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_mulAdd.c 644f4fb69b6d67725a586cb47755d4472694dc54 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_sqrt.c 188a513a8b2102d97b435bddcaa70a13422fd36b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_ui32_r_minMag.c 64b0e4b0e7bb5d8073e937068421026aa213bb57 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_isSignalingNaN.c fb78669ac8ebe25845bdac20fd3007ac6ed6e254 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_sqrt.c 49a30ac92f2823400a43a7b0789def54eac5d67e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_mul.c 39eaa261c0332f55f617941b8bf51f30dfa288bb - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_f128.c ea9e18329087b88e680a9b0e1dc3f73d78ffc97b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normSubnormalF128SigM.c 20cc97dd02d91a85b8d58ab1373f550058a5a4ce - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_f32.c f3c0c6bf5032a3f329e5637aa49336a98dc365f1 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_rem.c d5160582645bf346bf920e38f896596319da591b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_eq.c 54fed28ecc0bb163f71b7d5f47c960063b16f0f0 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_i32.c c9372c8b60f9e67962d30179a0595294d74953a2 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_mulAdd.c 60cccf04237a9a059b26075b3bc4742662905190 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_f64.c 6504b9481457cfd6e39a69e7066fe09ffbbdb258 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_div.c acd11d468d7a20b0e4381a8b7168e186b7d49d4b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_le.c 60a64ea74aeaa87b706af4f0c880e551d68ee8f6 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addMagsF32.c 6b7125daba8bb60ca3e2db6c38bf5cbc5df906ea - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToUI32.c 3fef81240caee61991a4a7c3ffa8e6d6e2e8066b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_sub.c 5d1495da9f0d75aa3f5fa75b43c5edbc95dc1ae9 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_f64.c 7bed7a39e5684ce23986346806ce19c0a2d198a4 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_i32.c b4f539877d9b40f21099ed92d2e18a9f57f28566 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_eq.c 623ab3fb8b679ac1b86f7c366eb192d128358f16 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam128.c a473fd92baf36ab51a725b665f964a7a082f4eb3 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_le_quiet.c 4cc27ddd980713ad95fd12a90c077df01999893f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_i32.c 5158c6ca5efcc7ee5067415f6df5988c4b3645ed - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam32.c 25ad3859febf3093e91de0392cb0d7c98d3e9dcd - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_ui32.c a8cd508101d5d02ae58933c2b91b0638fe9ce308 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_extF80M.c 7a1740bacdd6fbf37b3e9ad6b304b772722041c2 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_extF80M.c a5d1d8aa31fb5646e96d1f889729bd9eb7867e9a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_countLeadingZeros64.c ea2befd81aa697654bc1baf2a7da10508ae8b9ce - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_roundToInt.c 6ee82c2c62f3442cc1c0b2e9ef6b0b85da32cf3c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_lt.c ff0afa5079cd15008d3d3386ac73d3b62a0c4d79 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_negXM.c 73622cf9aea053c968f1922c8a206030cab025a9 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_f128.c 6c279773b785568a5567bfe33f5a6082265b9efb - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_eq.c 3c7d728ab8fa5d0e345c67d53f5335d672d8fd5a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_i32.c fd6492962962b16aeabef92ff9542da4aae05f26 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToUI64.c 4cc44bf1f32b533112fceaf74f2116052c251f45 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_lt.c 28af646437af4de6033b2176542a5d805636323e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam64.c 6ba3f71a3a306c79f58d469163b33f810aa8faa8 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftNormSigF128M.c ebd71c72d17dd55dc010988fcc223aeb9679ee6f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_mul.c 5bddd155904f96e1af61acc11b87973856d66810 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_sub.c 3088c598cdb456e47e280fd0bc369fb0d5e6d2f9 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_i64_r_minMag.c de37f2fef538ee89236273ac956585b2d58a15ab - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul64ByShifted32To128.c 9cd0d76126fdd8add379caa20c766668256efb6e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_eq_signaling.c a91c926882ae26c3a59dc8885fabc6e86ce9465e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJamM.c 6e91b9e38753aa8aa2094b6b40b596796bd11b3d - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subMagsExtF80.c 62cbafb0d4719707254e3021383d31fd007b3971 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_invalidExtF80M.c e550bcef98e4bc5091eac085dd5972d58c2bab09 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul128To256M.c 61fb9da8313a688f608a43d8aa36ac9861c74c75 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addMagsF128.c 920cf94c441178943a1442a168fb4649cfe755d2 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normSubnormalF128Sig.c 019af317356453e7119ac20be4c98c0a1c83f8af - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToI64.c d0375fd187a2ec8138e6a29c04afb951176c31bb - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam64Extra.c a56defbdfcb63c086c83b3754d2848c2d67b561c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJamM.c 57500b9bade8439c0c3f06cbb999f6ba13952ad9 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_f64.c 6f034e453e9efaa8477ac48fed5ff48d6320f99a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_isNaNF128M.c 260bca4ccf486c140c36950f988253e30be3f9e2 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_ui64_r_minMag.c 5547439bc882d6cb17257578b63ed5dea9e85ad3 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_i32_r_minMag.c 97a45958e5ea33d1fed598272e527b7f72a9d8ee - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightM.c 136777686e7e2c7b3decdc75d9cb9e0f802b4dec - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_ui32_r_minMag.c 7edbff34e15aeda6b14e5e01fa34a2e4ec230d88 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_countLeadingZeros8.c b971ed0265436f05a8f8f5eb8653de23e49747f1 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_f32.c 5adc627cc2a4ed39719943fac8c29517f3d39bbe - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_f32.c 440066ddfc6cb2460e07a86d2552d5aa6978ca47 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_compare96M.c 7c39994169fccf5700f2fe944d8b94d912a07723 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_roundToInt.c 5bd19e6fff94dd11976e8f78f6ef8b9af01d33d2 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_div.c d724729fe9aff2647d82d44cf7c98ef024550f4c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_ui32_r_minMag.c 7233f7a2c75705b0b4173168df45777f969cae96 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_eq_signaling.c 5cd984d2fe4bfa79945c464d200d7b17d205b475 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackMToExtF80M.c 0ac05f3c78dd89e1084687237ede90311fc758d6 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normSubnormalF64Sig.c 1a5d352e9bacfa36ecd8ef231155053713acece0 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_mul.c 32ee0bb66ee86e9f4d4f49c23487905e3e09715e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_rem.c 60f8ae03f26507e95f988d859c2a779d957c4efa - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_extF80.c 9cdcb1720d52c0b09ac2ab14aab047bfe940304a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_ui32_r_minMag.c f79c163815f902511ac25f8f5a391149043a846b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_f64.c 02501e2df1729d1c331ab6288158859f5302a791 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_ui32.c bb4b86c5d78b77f1babf89d73c262ab3e47b6832 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_f128.c e9570bb5907e357489fdf310d629201fb63fe691 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_sub.c add3de1ad7693fb4a2a5453483938b93b287e275 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackToF32.c dd00b7472e373b2a72b05389fd8c595c9e688831 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_extF80.c 80f53f88a6f924eaf40e9f79955bdfff87f72d14 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_i64.c 0fa1c7015b7c39efbe07d739a03f2a83b85745b8 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_compareNonnormExtF80M.c 33dedf42e83eb53f8ce20395143a01a73b412457 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_sub256M.c 70a0a4dddf509479def6ff905d493e6a50c1bacd - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_sqrt.c bf81966f25644611be0129d9ef8aaf0f5c6da21e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_ui32.c 35820af43505df9a372d4e74e3f0550a3af9a249 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_eq.c 7aeebb299243e2d857eef25300233d709662a1be - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addMagsF64.c c42aa8ca5eb2a847874b705199b3033ae8fc00ee - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_le.c 495735b890e1bebb53e4e2cef50ffda57a242662 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJam64.c 83db5e18b844bed794c0f1690aa2aa28ed93e4dd - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_ui64.c c8fa83b76113c38831b0a21b4b6359fe6976b133 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_lt_quiet.c 3d89aeb6e7880b1152564ff98fac17e80a4beab4 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_mulAdd.c 23a84b7f28ce5a2345b3d037ccc8f2707163d262 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_lt.c 06c8f4bcf358da5b2930df117ecc0f2324a59b3f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightExtendM.c 359da64e36a5f411cf383e3fd0f83a248a1dd066 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_f64.c 8fd3330c1a032cc7c4a7ad995996169ac7f0805d - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_ui64_r_minMag.c 58782db3382eb567580f7105c6c8d88dd1a6fc67 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_i64.c f06279e2d0e5d4a308a35ce0eae73d18ff2b0ad1 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_ui64_r_minMag.c e4be027468e7ee598e8835dfe5c58692978be102 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addComplCarryM.c 6ab2cbbff35bbae58c14a90419c2dd153b667063 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addM.c 9c753ee79b20998c7b9c420d50cd9ca84b18a3f4 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_le.c 2d988cd65efb881d8f5103b71c9f6b121121ef6d - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_i32.c c5fd85ea4a5cf0a00edfc6cb66cf20b3e7100062 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_eq_signaling.c c50d86d027171a9f2481e8f7c1cb4308f1cf1d3a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_i64.c 1aff280581ce3e0a033ebdb2257a5095804f4a18 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_isSignalingNaN.c c425d403c3b3dfaed940888bca06384b967e8e5e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_i64_r_minMag.c 12d0070692fad1189770f55c41aab025bee462a7 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_f128M.c d688f7a888e0e7b33a166af94044edc80100754e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_le128.c 1843081e5eaa9f77ccd80c3cba04e650ceee756b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul128By32.c 63a8a8dcae334e46b7fbc7ebc687e8d6c011fb7a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addMagsExtF80.c 5728e535d2903cca9e9558dddf7a571e606a385e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_div.c 2679177fa989374186316764ed9a90c42e38edd7 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_le_quiet.c e33d236ac36ab3726429718fa699498e908afb21 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_i64_r_minMag.c 0529a095355f150e35063942c7aec7276033842d - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_add.c d586657c54173f413fa72807b84027e1beeb6234 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_approxRecipSqrt32_1.c 327934b641bc5a6a891fd19aab7b9f0363952a0c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_extF80M.c 641b01960569783533397d0ed1cdbb00695a3578 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subMagsF32.c 1e172d64c3dbd60e0e9ffcbcc7a0225702f04848 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackMToF128M.c 14119b8fcb0828e0621f0d1c0b3130721abcf3a8 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mulAddF32.c fc451ef01165565a1d593b0e2572eb8e37aa72a3 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/softfloat_state.c 0f3d7b35ae34828864a226e8b123484e88b8cd13 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_extF80.c 9a156cc904d7427a794de20f093bdff4a44cc12f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_sub1XM.c 3c754eb220ded3a7e9c82cb01c7ed8adc2144452 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_lt.c 4802d692dda23c6bdb15e682f8895eaa2e02a824 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_lt.c e6ad1063b924e4b96a1801d49b960b3d8534342e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_rem.c badda43bf474995d00db78fe6ae6b40268e9f90f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_f64.c c841c237414b6697fc42f3a261082257cec7dbec - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_add.c 9e7235e0ad3872a7b6f005a0203e63508f11eaab - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_eq_signaling.c d5a7b42551a9289e11b502dcd611101098d47502 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_f128M.c 625d048386528b1c63a19813ace77ab7484e1876 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_tryPropagateNaNF128M.c 0ef83486a7270a31dab5ced482dfaec14b9a5b4f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_ui64.c dda54df5d890a969ba663a54ceae83c6492d7866 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_le_quiet.c faf4056d360eb6faeccac416f54caa2a1a8bae9a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_i64.c 8a4a364a4b4f144bc47fb5e28144cfe82dd3b585 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normSubnormalExtF80Sig.c 345b454a7bf01265db26b15ff80f98692e81fc5f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_div.c 684615f62d1f460768c6b9cf951bbe7d82b7aa4e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_extF80M.c d3cdaf7ed2016c9f9764a514ec05b2dd6f86fc85 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJam64Extra.c fab91920cf859d0f22562a98eea05a843806e70e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_ui32_r_minMag.c a05a89d48fe8216f0fa0babd342a60249c72cef2 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_eq_signaling.c 01cd4ad4fff8805cc5bf43533b1576d7e170925b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_rem.c 890504face9da670bb9338c6587d893fd632819b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJam128.c 7db7c6e3e7ed45f7c7ed16ea6935cc7fdba73da3 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul64To128.c a8129c9fa34f996b39adef2e0620dd63b5ab655e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_roundToInt.c 784083a6783d1d5de48e4b5a95ccb43b8103bfff - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNF64UI.c 74a3e6c966c47167bebd7abdfb17797124ee9279 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNF32UI.c f58e104619733d72884d1de3ce89eedacb671595 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/specialize.h d8fc85a2746e3c31e70de675027af01735ba105f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_extF80UIToCommonNaN.c 52bc24f91ee7846596274fb2b29654539fd3fa00 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToF128M.c 2c9f36c79b5d80fe13893b8c9b9f9c94273c1c95 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_f32UIToCommonNaN.c 52fee0fd73c94d2e2f5a21a55f082e1963b1569b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_f128MToCommonNaN.c 8c5a81c2b54db7d09ea4a08a43171c7f9ed3cbe7 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToExtF80UI.c b6b8b672735a45d7c495bf8af1fa94d1c8e6556c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToF128UI.c 7c65ad2301cc6e79aa3392bdb9010a7ce81b0c38 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_f64UIToCommonNaN.c 868cee0046c6b1426f45136804fd662b030f263e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/f128M_isSignalingNaN.c 67e0a5407af29f70e8a1cd10563b7aaec9ccbcdb - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNExtF80UI.c 94e7fa32804e73cff91d5bfa140aebbbb55fe6cb - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNExtF80M.c 4a66a4eaba41707a706d22a724ff5853260d070c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/extF80M_isSignalingNaN.c 7e3b18d1139373153529a43d88c469da845d393b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToExtF80M.c 70de120b27bf3bf6917bf2a9536aad6fe8536358 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToF64UI.c 7d5189099e205be2e0420013770668fb8b96e133 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_f128UIToCommonNaN.c 35b37030a4086b22b7974082589b33ca07ccc8bb - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToF32UI.c b0822433062f48471e106e268f79f079d1a1cd55 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNF128M.c 7dc9295fddc66cd74761fa03a90c65985b964c08 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/softfloat_raiseFlags.c 302b57e7a9ad056c7936806892309cb4de6ffc96 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNF128UI.c 1c390c99fc7405c9a44b4117383cce7de291c13e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_extF80MToCommonNaN.c 3b6c666fa3fd1fcdb96504690f34db6740d85b2f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/include/softfloat_types.h 1afdc66c33767a868d162893776bf6d3ba9f1247 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/include/primitiveTypes.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 8450fc5ca89f94b128b1d1d4608903ffd0de498b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/include/internals.h 93bd291166335a88ca0721d5beaebd9599a2475e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNF64UI.c 5e2ab65ab8c5b830b547afdfac8b72c1a7b193f5 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNF32UI.c ade8c323e356c3e70af2424ed9e2ca0ccabc68c5 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/specialize.h d8fc85a2746e3c31e70de675027af01735ba105f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_extF80UIToCommonNaN.c 52bc24f91ee7846596274fb2b29654539fd3fa00 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToF128M.c 2c9f36c79b5d80fe13893b8c9b9f9c94273c1c95 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_f32UIToCommonNaN.c 52fee0fd73c94d2e2f5a21a55f082e1963b1569b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_f128MToCommonNaN.c 8c5a81c2b54db7d09ea4a08a43171c7f9ed3cbe7 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToExtF80UI.c b6b8b672735a45d7c495bf8af1fa94d1c8e6556c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToF128UI.c 7c65ad2301cc6e79aa3392bdb9010a7ce81b0c38 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_f64UIToCommonNaN.c 868cee0046c6b1426f45136804fd662b030f263e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/f128M_isSignalingNaN.c 67e0a5407af29f70e8a1cd10563b7aaec9ccbcdb - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNExtF80UI.c 94e7fa32804e73cff91d5bfa140aebbbb55fe6cb - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNExtF80M.c 4a66a4eaba41707a706d22a724ff5853260d070c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/extF80M_isSignalingNaN.c 7e3b18d1139373153529a43d88c469da845d393b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToExtF80M.c 70de120b27bf3bf6917bf2a9536aad6fe8536358 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToF64UI.c 7d5189099e205be2e0420013770668fb8b96e133 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_f128UIToCommonNaN.c 35b37030a4086b22b7974082589b33ca07ccc8bb - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToF32UI.c 3b12a5a00c5ee315f9665165cc0160e7e4e7b946 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNF128M.c 7dc9295fddc66cd74761fa03a90c65985b964c08 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/softfloat_raiseFlags.c cc1a5d99c9f6833e79108373c21162c7fb65a742 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNF128UI.c 1c390c99fc7405c9a44b4117383cce7de291c13e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_extF80MToCommonNaN.c 75e9aa350d3aae45b151a9bbe2f6e70ccad11c7f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/doc/SoftFloat.html 90d2bc9a9afc3396f0a2271c1d79a76287c2516a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/doc/SoftFloat-history.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 5fbd70f4fe7a023e3b9c3c6997b0cc042bec58d8 - optee/optee_os/lib/libutils/isoc/include/inttypes.h b61508c5b2e6fa2f5e16faf66b4ea52d273b2767 - optee/optee_os/lib/libutils/isoc/include/assert.h b704c2144f4058cc83eff91c732a965487af7f2f - optee/optee_os/lib/libutils/isoc/include/signal.h 2f1e8ef53989a85982945a254710d877d86ddab0 - optee/optee_os/lib/libutils/isoc/include/malloc.h 7146a287e1507a73b42aa6ae46d72881a5b318a8 - optee/optee_os/lib/libutils/isoc/include/stdlib.h 44f78c63d935ad93ce68039331f214dcc699f6e1 - optee/optee_os/lib/libutils/isoc/include/stdint.h 1b5da4e5962171c39a2b4762a169e12e50dd6641 - optee/optee_os/lib/libutils/isoc/include/stdio.h eb700f736fea47a51c03069d099ff492d566f45b - optee/optee_os/lib/libutils/isoc/include/time.h e83da5f07c33bc84bb291affe6480214bb4e6f9a - optee/optee_os/lib/libutils/isoc/include/ctype.h e7fdba9acf2bc6ddc6d25cd852eeff72855d143d - optee/optee_os/lib/libutils/isoc/include/limits.h 9edc066dbedabb03c6479c2dfc962125c09207b5 - optee/optee_os/lib/libutils/isoc/include/memory.h d107150611ad4db054a4c134a03cb4072e5b978f - optee/optee_os/lib/libutils/isoc/include/strings.h f1ba2ffbb8b80c3d2c8baf5ad09f2d1883ccc95e - optee/optee_os/lib/libutils/isoc/include/wchar.h 15ec9c6af06bd04877ce230bac8bfa3ce26a23e9 - optee/optee_os/lib/libutils/isoc/include/unistd.h c6501a452dfc56db99d454ab6785417f3fd2049c - optee/optee_os/lib/libutils/isoc/include/setjmp.h 8629e94b3bc7a9b628d559492f6859405e065233 - optee/optee_os/lib/libutils/isoc/include/string.h e646420d5133d287b223a251d711caef5077d8aa - optee/optee_os/lib/libutils/isoc/include/sys/cdefs.h 04b7e694a49520ea266a7acc30e79a4d5d015854 - optee/optee_os/lib/libutils/isoc/include/sys/fcntl.h ea09b9213223627399f059ff48bc083ac9652a96 - optee/optee_os/lib/libutils/isoc/include/sys/queue.h f39fd14f91c4f1b1a6c2636a7abfaa0cad378a37 - optee/optee_os/lib/libutils/isoc/include/sys/types.h 5a9624425bf1040b1f7f44f5391b07f0f54eb969 - optee/optee_os/lib/libutils/isoc/newlib/strstr.c 5f94025cb7d772e0b69eb04008405feb9ef86a0c - optee/optee_os/lib/libutils/isoc/newlib/strlen.c 5c1c0c4053502cfc23acb11a61aef64e6a9f7383 - optee/optee_os/lib/libutils/isoc/newlib/strcpy.c afd073d96ce316d15f065f34576779bf31b11b4a - optee/optee_os/lib/libutils/isoc/newlib/strtok_r.c ffc219c3a21638f7e62d3b658ee6c4a3dad8e628 - optee/optee_os/lib/libutils/isoc/newlib/strncmp.c 108514868e87a312a98be4104fdfa5f0b689a956 - optee/optee_os/lib/libutils/isoc/newlib/memcmp.c 5604c3647615806cbfd5068d684f1127272226c0 - optee/optee_os/lib/libutils/isoc/newlib/str-two-way.h ca1b181d9d51ccd041f7a54adb83afacde6591b7 - optee/optee_os/lib/libutils/isoc/newlib/bcmp.c b1d845daf20cc5443488f37fac3559c721bcfb45 - optee/optee_os/lib/libutils/isoc/newlib/memcpy.c 4536b43b4035e668869db96685c3e398be901a40 - optee/optee_os/lib/libutils/isoc/newlib/strtoul.c 0800e9eb716a2e65ba7a95b2fbd873749abb41ec - optee/optee_os/lib/libutils/isoc/newlib/strcmp.c 6054fbc2e1ca96c1f5291cab671fc90d7ce00fa5 - optee/optee_os/lib/libutils/isoc/newlib/memchr.c f4be3b2ac744128b112751c273f2850ec6277a45 - optee/optee_os/lib/libutils/isoc/newlib/abs.c ad3617f14072481d06acd4c17903f9eaf3301223 - optee/optee_os/lib/libutils/isoc/newlib/memmove.c 811f31f56bd454989b15ad39bd9201411a4971f2 - optee/optee_os/lib/libutils/isoc/newlib/memset.c e0298efe1346c7206253a9f0f174acc71479f134 - optee/optee_os/lib/libutils/isoc/newlib/strchr.c 3eaef3643d7bc2740a34226b2b66dca0fd662558 - optee/optee_os/lib/libutils/isoc/newlib/strrchr.c 2424e0252f73a9e6fea420e9f7f2967538d56444 - optee/optee_os/lib/libutils/isoc/newlib/_ansi.h c62c5a7633896186fdfc21ab5992c569d0b93d28 - optee/optee_os/lib/libutils/isoc/newlib/strnlen.c f78df3e9bb90074ab9ac143f5e62bed8c2557796 - optee/optee_os/lib/libutils/isoc/newlib/strncpy.c 89ebb1873af1f851bc8fc67e813f81eb6a676a2c - optee/optee_os/lib/libutils/ext/consttime_memcmp.c ce50432f4d5515d5ce9fb398b5098b9c0ec12c38 - optee/optee_os/lib/libutils/ext/pthread_stubs.c 6bff861d7ee6d2d199bf849da8673bc2f7644a81 - optee/optee_os/lib/libutils/ext/mempool.c 47c2201804ad35107c694730f37c017ee288ee01 - optee/optee_os/lib/libutils/ext/fault_mitigation.c eeaf7cbef43d983ce60db9ac8731767dc6bbf22b - optee/optee_os/lib/libutils/ext/nex_strdup.c 53a0650d0e1a37aefbb511bb3f422ca162180c36 - optee/optee_os/lib/libutils/ext/strlcpy.c ffad6974fa755ea998a6801173ebf69647d8e204 - optee/optee_os/lib/libutils/ext/memzero_explicit.c 20e3e9705f80898b933d3708b6c1b4133ffa949b - optee/optee_os/lib/libutils/ext/trace.c 8d6b22214c57ad89d47fbf50c9d2a28ec11c2951 - optee/optee_os/lib/libutils/ext/snprintk.c 7a501727fe2d0e89ac822ec9ecfc06ac9387eb69 - optee/optee_os/lib/libutils/ext/strlcat.c ece984c44b615c403bcea03f8d97fec4569856f1 - optee/optee_os/lib/libutils/ext/arch/riscv/atomic_rv.S 9744e9d7926714ea8ced25857ff8db9a0b12cff5 - optee/optee_os/lib/libutils/ext/arch/riscv/mcount_rv.S fcd9b20bfb493ed1ef33987681cef3c072605105 - optee/optee_os/lib/libutils/ext/arch/arm/mcount_a32.S 3c9419abbdb07dffd661757f2b8acbc0c49e971b - optee/optee_os/lib/libutils/ext/arch/arm/memtag.c 7249fff01b1ca0cec36cca67bec4a1395ee4224f - optee/optee_os/lib/libutils/ext/arch/arm/atomic_a32.S 527c3d07f4d854cb770425c1d1bb43d87d25a622 - optee/optee_os/lib/libutils/ext/arch/arm/aeabi_unwind.c c76559d831152142d5a0612b9a2ba8988ead0414 - optee/optee_os/lib/libutils/ext/arch/arm/auxval.c adf6c7b011707e03c48439a6a7de0b07e91d5e59 - optee/optee_os/lib/libutils/ext/arch/arm/mcount_a64.S ff0eea4f25438d8836034710afb20c6ff62d9805 - optee/optee_os/lib/libutils/ext/arch/arm/atomic_a64.S e0f599207b28b33bf06b5e1c02b650d0e1a2d7c5 - optee/optee_os/lib/libutils/ext/include/trace_levels.h 0e9c096815b105d29d59a8cfadaaeb5e7a3b7998 - optee/optee_os/lib/libutils/ext/include/arm64_bti.S 5d1943eba944ecd7ffb277b76460ab47a379f73f - optee/optee_os/lib/libutils/ext/include/memtag.h 84039f2a7ab7966f95cf82f76639cb60c3d8f17c - optee/optee_os/lib/libutils/ext/include/util.h 2896ec82cb868e5f5d1b8338aba45f9490c96419 - optee/optee_os/lib/libutils/ext/include/asm.S 8aef0ea1cd59799ea3f9b89eb12d8ad5f9482b68 - optee/optee_os/lib/libutils/ext/include/speculation_barrier.h 93a77e57894a180ceb9cbf485c96b316b0223286 - optee/optee_os/lib/libutils/ext/include/string_ext.h af2b6927c92cd80ffae87a12bf87645f43748dd8 - optee/optee_os/lib/libutils/ext/include/atomic.h 70ac170a6c79b30435a4b8fef9cf7e98ea61e9a9 - optee/optee_os/lib/libutils/ext/include/printk.h 6d52c01d26b5f87893d70ca173d1fd712d53f4a5 - optee/optee_os/lib/libutils/ext/include/confine_array_index.h 1439d0e682d301147076a8f0ef733acb0d21d451 - optee/optee_os/lib/libutils/ext/include/riscv.S caef86fc6055f0c19ce5e5429996c4a422645a3b - optee/optee_os/lib/libutils/ext/include/trace.h b049afe67cfa21b37d9733a47ac95b142b1bbf55 - optee/optee_os/lib/libutils/ext/include/fault_mitigation.h d0fd7d83680885f9a71f56435b92b078f79e14df - optee/optee_os/lib/libutils/ext/include/mempool.h 296cc431c36cb1c06ef0965e569bb8f0028aaa86 - optee/optee_os/lib/libutils/ext/include/bitstring.h ce8e8d219a06d536dfb044bd004db98fd595d438 - optee/optee_os/lib/libutils/ext/include/stdlib_ext.h 0c4e420d80821bc2e9d1c85cb5488cdba9b2dfb0 - optee/optee_os/lib/libutils/ext/include/config.h cb245d42df602e376891d86e4a5bc7e4adf563ed - optee/optee_os/lib/libutils/ext/include/compiler.h 603efb52be462838f3f8f8f5ddb20258ac30f353 - optee/optee_os/lib/libutils/ext/include/types_ext.h cb974d6f302fc21a6380a7a8d4e86e824279e6f5 - optee/optee_os/lib/libutils/ext/ftrace/ftrace.c d252604ab38468dc215d8fff7e20420e53adb60d - optee/optee_os/lib/libutils/ext/ftrace/ftrace.h 76a908634bfe89773fd70c57fd77d712c4bc89ee - optee/optee_os/scripts/sign_encrypt.py 57eab194acd3e07adfaba6438695da8c79d0d289 - optee/optee_os/scripts/ts_bin_to_c.py 570bf1d2a225e0124496bc57c287ff0991fd023a - optee/optee_os/scripts/gen_stmm_hex.py ab4324da2d6fb92edbcaa95bc23911ed63e4514d - optee/optee_os/scripts/arm32_sysreg.py 08b1957d02a5f8fb853138fa4b3f2b8b04f8d847 - optee/optee_os/scripts/update_changelog.py d302da149f2f0d0b11b9c365bf3add51a131b8a9 - optee/optee_os/scripts/gen_ldelf_hex.py edc01ccf3e16f1a4bdb1908f57a4722d3bfa203a - optee/optee_os/scripts/checkpatch.sh e13049cc7ecc4774a0b40b42d6a72617f540db8d - optee/optee_os/scripts/bin_to_c.py bd6f1fe3cc1334b262bfbcf3d1b4b2f98bda0d3d - optee/optee_os/scripts/checkpatch_inc.sh ffaf1fbbaa6d01cecaeae7d8ce75f8315240228d - optee/optee_os/scripts/pem_to_pub_c.py 31f300bb6c5a381759d5e2a3b54e42039be66dd5 - optee/optee_os/scripts/sign_helper_kms.py c92fcf555467abe77b88cea98e805eaa6eca5462 - optee/optee_os/scripts/gen_ld_sects.py b1241b7d0c39f88fb4382637396901002f682b69 - optee/optee_os/scripts/gen_tee_bin.py 6d38439ab83fa8f0869ae12e569bbd89074aea8b - optee/optee_os/scripts/symbolize.py 24ab5b3587dac3d8b99136338a79a57b38027da9 - optee/optee_os/scripts/mem_usage.py 1119399c06c6d97111c710e321f7317d2d67df3a - optee/optee_os/scripts/ftrace_format.py 44102438f54e075418710993095e3d5b5f0cec54 - optee/optee_os/scripts/gen_compile_commands.py f8bce245ce0b6610d39e02928e25307a5b6cc818 - optee/optee_os/scripts/print_tee_hash.py 718761702d374076e980d8684a032e9543d4e0e4 - optee/optee_os/scripts/sign_rproc_fw.py e6692bdad99dbf466f146fe7169981ae542eb6cd - optee/optee_os/scripts/get_maintainer.py d28afa9fcae64f65d207dc150f051b7c609bbe32 - optee/optee_os/scripts/derive_rpmb_key.py ff71ab8e19870db30e4a8fba666168c645f37126 - optee/optee_os/scripts/tee_bin_parser.py f38c4636b6798cab2823555649a59b72061b756b - optee/optee_os/ldelf/ldelf.ld.S d7ed8b2b8bca2a9b7b2b50e4c5ef3533b96cbe02 - optee/optee_os/ldelf/ta_elf.h db3db1aeff618f5696eb16e7076b63464784267e - optee/optee_os/ldelf/syscalls_asm.S ecc193b3d2a051728bc5d4e5841c8bdc021b6d35 - optee/optee_os/ldelf/sys.c a270591f1efb8037df1d1369287b15f5f2964e0c - optee/optee_os/ldelf/start_a32.S c5d1a1d261c8bada5f949335bffe29a029d03e05 - optee/optee_os/ldelf/syscalls_a32.S d875d1a5979daa09b5b535d0a3f040c86a60f078 - optee/optee_os/ldelf/start_rv64.S 139e3f4826e35954af3c3bfe5112f11c1bd0db62 - optee/optee_os/ldelf/syscalls_rv.S 16e361c79bd359473a90bde00b493ca4182cc975 - optee/optee_os/ldelf/ftrace.c 87d8438d725c689049dabad1a58459a5efaaef0a - optee/optee_os/ldelf/dl.c cb079ab7bac5d488cf5375c1b028130bcb2c7997 - optee/optee_os/ldelf/sys.h 29a349fad517b13af907e7705113c3831dccd9e9 - optee/optee_os/ldelf/syscalls_a64.S af3868e37b5f97fafb0a1843478916e687050325 - optee/optee_os/ldelf/ftrace.h f133be54ea11df978fa33a5afe3a2d8ed8c8f035 - optee/optee_os/ldelf/pauth.h 0a9f8943d795fd8edd10c5cc7c83baab9970b012 - optee/optee_os/ldelf/ta_elf_rel.c 9201638e87d7051478eaabddd7ca1d9054f35f5f - optee/optee_os/ldelf/tlsdesc_rel_a64.S 4b036af7eee80c9d1402b0b1dcd09cab729a7a9b - optee/optee_os/ldelf/pauth.c d733071f9aa144e7310fba8dee83b811398327e8 - optee/optee_os/ldelf/ta_elf.c 13ded24e6da6026069baf1c4dd3159b6410f5308 - optee/optee_os/ldelf/start_a64.S 611d7981c55b4c62f5b13677c04a314e1a2f3218 - optee/optee_os/ldelf/dl.h 2450caf3ccde56f97078cfabd0a6378472ae1a23 - optee/optee_os/ldelf/main.c e753e305779ac38002c5db612439fd95d3e9a20d - optee/optee_os/ldelf/include/ldelf_syscalls.h 9d6a14f727a55f4691af8e78834e23c243a1be39 - optee/optee_os/ldelf/include/ldelf.h 1c8f13cf72490970da6d19a7a3d3c06f18770f07 - optee/optee_os/core/lib/libfdt/fdt_wip.c 78de4be67ce92f5b90ff1ab89c2ba46a1a34da7d - optee/optee_os/core/lib/libfdt/fdt_ro.c 966e9a4b174cc33c3ba6126614b919ca0bfd09e4 - optee/optee_os/core/lib/libfdt/fdt_overlay.c ed2772a8c2274cf02551a2a21cfbc33a7d81c2dd - optee/optee_os/core/lib/libfdt/fdt_rw.c a6759c569917866b44961c88629ae4f3f07ea686 - optee/optee_os/core/lib/libfdt/README.license 0da7a6ee0118d32ca78e772cbf5a81f0cd62af9a - optee/optee_os/core/lib/libfdt/fdt.c e01b7a0052b837a4650f2c9ac75ad38c40edc583 - optee/optee_os/core/lib/libfdt/fdt_empty_tree.c e5657b776e8466d0d7c9578591d9c2ef45ef2799 - optee/optee_os/core/lib/libfdt/fdt_strerror.c fd3af5baadbf42cca01d1a438cc826ae85a21f97 - optee/optee_os/core/lib/libfdt/fdt_sw.c 5ac5dba57124ad85911a67c10cf941f08ae861bd - optee/optee_os/core/lib/libfdt/libfdt_internal.h 55fc5d2ffcba07e29948822d0b12e4bf5546b8b8 - optee/optee_os/core/lib/libfdt/fdt_addresses.c 265155048eb725a03c49a45a27f322ca6f3dfe6b - optee/optee_os/core/lib/libfdt/include/fdt.h c90d25bb7b217171ad9437ee0bc8d4e0c5c7f4d3 - optee/optee_os/core/lib/libfdt/include/libfdt_env.h 7cf2619336867b335fe8f3c919607242477ccfa0 - optee/optee_os/core/lib/libfdt/include/libfdt.h cc088246b745446e2d222bd1c5219334f1c8a430 - optee/optee_os/core/lib/libtomcrypt/mpi_desc.c ef50fbda210143489722c5c073b049220aee69ce - optee/optee_os/core/lib/libtomcrypt/cbc.c bf7cfd733029fd500704f55382b02cd8fba1b84e - optee/optee_os/core/lib/libtomcrypt/hash.c 5a1e99eeb7282f69b7e7cbd68a0f514644c4d2eb - optee/optee_os/core/lib/libtomcrypt/x25519.c f38de7925c7043b9c008b228fe88f291f90fe671 - optee/optee_os/core/lib/libtomcrypt/sha3_accel.c 422469b123ee31fdd517259a2ff73fe03da28d95 - optee/optee_os/core/lib/libtomcrypt/ed25519.c 181064609b067d38f551f69dcacc2d7a6ee4c249 - optee/optee_os/core/lib/libtomcrypt/sm2-dsa.c bc5761862d3f2bdc223bbd894e1edffc89db0614 - optee/optee_os/core/lib/libtomcrypt/aes.c 627ba519b1c58c51f6ba86d4c3efcf948e497db9 - optee/optee_os/core/lib/libtomcrypt/sm2-kep.c 36ca35680a4370d4f993961371d80d2e7b777458 - optee/optee_os/core/lib/libtomcrypt/acipher_helpers.h 466eb4dd083c77261b455c56dfb3036243b0992e - optee/optee_os/core/lib/libtomcrypt/sha1_accel.c 191319cf67c91dac0437c501694f9973ada49045 - optee/optee_os/core/lib/libtomcrypt/xts.c 5d3683701305265a319ea23c3053100dc9ae0bfa - optee/optee_os/core/lib/libtomcrypt/gcm.c f11a282fb43eece165553ab1545b7035b44ebe24 - optee/optee_os/core/lib/libtomcrypt/ecc.c a2ecdde9b88869f00656b532502bf2e1c9c778bf - optee/optee_os/core/lib/libtomcrypt/shake.c 2fc6c08d346f75feec7f1c1633ccf1ddc1ac7736 - optee/optee_os/core/lib/libtomcrypt/hmac.c b1d9c45ed1f78bc67c1bf788fd2478f835b86f80 - optee/optee_os/core/lib/libtomcrypt/aes_accel.c 9197499a951acd6f4952270e28672de2d04696ca - optee/optee_os/core/lib/libtomcrypt/ctr.c f2db1584836afadf8108bc4068ada599727f3a85 - optee/optee_os/core/lib/libtomcrypt/sm2-pke.c 2680c6505dd66000230072a984d24a8085db27d0 - optee/optee_os/core/lib/libtomcrypt/dsa.c 7f870de527ffa71429d8016fd5b6800110e56460 - optee/optee_os/core/lib/libtomcrypt/rsa.c ac9a9648fe065d77e8a07c0f153c16784b90b675 - optee/optee_os/core/lib/libtomcrypt/cmac.c bd085d21425692efa0737d43fe957bf83da73e8c - optee/optee_os/core/lib/libtomcrypt/des2_key.h a53dd03d8ef444dc1ee628dd000ca066984be89d - optee/optee_os/core/lib/libtomcrypt/sha256_accel.c db10215efa57b04d6d0c2259256832c69da9d405 - optee/optee_os/core/lib/libtomcrypt/tomcrypt.c e6002d6bda94d5566d0598b73957a79863fc5869 - optee/optee_os/core/lib/libtomcrypt/dh.c 99aa558ed75d6462b266bdab24faa189c03b4563 - optee/optee_os/core/lib/libtomcrypt/ccm.c a001afe7f955e43839c5e0d73be3db5db77d94d3 - optee/optee_os/core/lib/libtomcrypt/ecb.c 72b382fc200ec2a39395f48c821d263bb827cd3c - optee/optee_os/core/lib/libtomcrypt/sha512_accel.c 999e42770e9ee014be2004a0f9ce41d08a2002ac - optee/optee_os/core/lib/libtomcrypt/include/tomcrypt_mp.h 5c28c3c8b5fdb83a197148d44816e8b005affa3e - optee/optee_os/core/lib/libtomcrypt/include/tomcrypt_init.h ed9c10d0285b377accb1e2494f6286e154bed777 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_macros.h d86162251e3b48c30f090b3d893a17106c1b59d3 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_mac.h 4e5b33b2454acbfaa9b2ab42a0a03fcabc598d30 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt.h 941fea915f92af82307b36234f5ce179c0fd3025 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_argchk.h c4d8079f35569279e5f30da5d4666d1a145c29e1 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_pkcs.h 47a31bfd38f96720df80f298c98d96cb435b3ad3 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_cfg.h 6e3431e86381584751e3fe17d1f783454fad2f52 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_misc.h 23b6ced88dc0c3124f432f3017aba8b385df4866 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_hash.h 44976f48c4f37ff61e8b03ca839b1a65f273117f - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_pk.h b024a3e54d8b78ef88bc56740995d089836bfc81 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_cipher.h 2e713c6c463faaebb4e01472732e51d74aa5b185 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_arm_neon.h 6603ac9ecc182ac6407d2a5bdd90f3baa4552f58 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_private.h 4cdf5186a0f57233bdeac68a7db9e2e488806fd7 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_custom.h 49b2782b96dbf7d798398be0b39ba922e5a21bf1 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_math.h 660c8803aeecea2223f2075be243bfdf24187599 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_prng.h 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 b27bb0657c7accb0df147f4bf193b12933a9d970 - optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_done.c 224913f37550084d0b6a11c46a674e2560b9f6de - optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_memory_multi.c c987048ee653d7b9e528924cd4ea2041d81ffbd3 - optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_memory.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 8151c66fd55cb82b2e4252f211a7d14de20599e1 - optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_test.c f86f622ff3761a9086d7779d77559eddf2774ece - optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_memory.c b8c88d3152a2d9384baf86c1ec61ebb26f13660f - optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_done.c ac3fb83b5d619e067782a032452e215cc2ccc3b4 - optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_memory_multi.c 114da72cefd715009a772baebd50f69a3237da72 - optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_init.c bbf18f6d75557cfdbb5aec0cb00e3df605536d68 - optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_file.c a3529bef5d5ca05f194021b998a1d7ba5fdec700 - optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_process.c 6f1f256d9e8a6ee6660406b43866a0dd79fbd255 - optee/optee_os/core/lib/libtomcrypt/src/mac/poly1305/poly1305_memory_multi.c 86f1332253c798f3fdfa01762ed1c64949a69794 - optee/optee_os/core/lib/libtomcrypt/src/mac/poly1305/poly1305_test.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 5e2fa3a8a8b8c0d38d74aa0bab4d4cc206166453 - optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_memory.c a081274e2f9dcc2ed96ec2a4db00ededed0ec9e8 - optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_test.c 7314b670b2c1a382ba1017ccd3b3806fe451aad6 - optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_memory_multi.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 daee17f76d3539a02d8567dc943b2b3217098786 - optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_file.c 5a792633cf4c62bb31894bcce5bb07e78763b88e - optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_process.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 9b028196ee6d1b9299d41bc2c6d66cacd1011ed3 - optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_memory.c 5c61eca352761007c4111cf83cabf66f712cb67c - optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_process.c 78be422e4801b343c32f4a4574075488109af2e0 - optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_memory_multi.c de921bd15503ba513e2979be7113493b8c679ac9 - optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_init.c 7ec5d863f61666d818632fd057c4fe9bc1a879f0 - optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_done.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 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 208bbe5ced04c13eb0e1d3b24e76f5c81345cd04 - optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2smac_memory_multi.c 93f44519ebb2341e9ca27ec077a77a455641dba9 - optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2bmac_memory.c 9bf71a86a4483d4e404521f696f591017b261b9e - optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2bmac_test.c 361ba0aee5e365c0c0cb186cb4aefdac17289943 - optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2bmac.c e29b12ee69c044ee575a389f95878c7498a62af9 - optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2smac.c 420e593df278e8c4bce349965dc185a1654e27b7 - optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2bmac_file.c 7ef84ee8949eea9fb48ef217f1c8ff24f6adf1d7 - optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2smac_test.c 13a4a399570926073872b210027dc5539d30d44e - optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2smac_memory.c 539c06612340597abac186f272ceeec032082a08 - optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_shift_xor.c 0e00b9ac2e143fc27c3122a3f3d9bc87d8282076 - optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_process.c 1336042d04c7dd5b0ee965be9d037bf654049339 - optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_test.c 0371334e645562a86984c83f6257967f26cf1464 - optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_done.c fd77eaabb5a5ffddd12e2f91920bd8e657aaff2f - optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_ntz.c 74a84dcfca09518e42ab725a717c8aedc0fb9f84 - optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_memory_multi.c eb8f24748a3fbff1fabe0be3ce91f76ace71528b - optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_init.c 4a8d8ec6fb7faf70d806473ae0d8a3d1c9d3cc5d - optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_file.c 21ade96dad372a77d13f421cc9c1f8d2290e239c - optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_memory.c af7e5ec699439a45de3f29a72e6779709ebce7ac - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_encrypt.c 16d4c4b33c5e68749766312b86e074433514c453 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_ntz.c 727b4d190bb993d395c276fdc4b6772e7507af6f - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_decrypt_verify_memory.c 93e89b145ff46fcae1c653ee70c2061ac539e737 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_done_encrypt.c 87188dae93ef2263dd1baa4207faf5551bf57bff - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_decrypt.c 9874e24493855b4ccab70b0ff538125c23e3515b - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_init.c 83f9d3b22b6bd8960fde8524bcd094d2fd1bad6b - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_test.c 069dc6544fea4923f5ffc9ed6cb508d1e3be4b16 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/s_ocb_done.c 4c0669699a2b11b52aacda4fd2c617d5695da4c1 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_shift_xor.c fb2baeda2808e719b2543a5bf4e92e86c5a8475f - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_encrypt_authenticate_memory.c 5fd053c692f154fa517d1a66afac3bf88a666dc1 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_done_decrypt.c 00df47ac677f1c073e872b02d89d034defae3198 - optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_setiv_rfc7905.c a1a4e685352d4984fd5d49522bcd50c4492ea66c - optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_init.c 0af7bc735a8720e5b936a261204b1aa73a0943f5 - optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_memory.c 9de6e2171df8c3c6a974888bfde2f9333e56e12a - optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_done.c 2d89b89d0738d4db5b761d40f9cd02510f413933 - optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_test.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 559a51a7d6a1d21918f5908f788bb294acf88bee - optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_decrypt.c 5cc80740578579a16d394fdd144d7d71daabfa35 - optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_add_aad.c 9eb480ccdf51a957a9391e17f2740e53048dd90a - optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_add_aad.c f8f818328098018b9bc6836915dbfc34bafbf574 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_reset.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 e045e646861478e232fea83658bd42d37547f4fb - optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_done.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 782a71b6b10b0305491529ce9963ace0c26a38f6 - optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_test.c 8f82752538241e4f3c3f48ccdb5bf6fd41d7e889 - optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_decrypt.c 30473a74f19214129f69b8b067d6d2d5a87a7364 - optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_addheader.c cf42e3ab0129e2962618a2b9b261e9ea20e0bcf2 - optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_encrypt.c c5f08bda970ba7d30ff7bee44fda96f5e6515caf - optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_init.c 3199f0f705460b9182e1e9b543e800f7d26b305b - optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_decrypt_verify_memory.c f60e6c18f07779e8b066581926c51522a92069d6 - optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_done.c 633dfd755ba58507be81b2d70c2d483d28ca9597 - optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_encrypt_authenticate_memory.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 f162118759bca19c0f87c3807df85b6373ae5644 - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_add_iv.c 6799d4d2d91f4e12e8d866fd920ae847eb66d5e6 - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_add_aad.c cf505805e8a15d2a7e342491371d6f38a799f8e3 - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_mult_h.c 60ead8187339abc082c6fb5cfa8ca4a07d5bd3d1 - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_mult_h_arm_ce.c 19aceaaa2254b78b3210d81efdb82d2909a5edbe - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_test.c 7b1c5747593a58fdf9669888bd86df7718579054 - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_memory.c d071d7e805d688ccaaf2b3f8c3b7bc5d68bbba1e - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_process.c 9dd030615b3a2c6b70c7e24dc125673f88550909 - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_gf_mult.c 38d9de8caef78490c170d9f138c49db6374e6a02 - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_done.c ce658863c830e150ad4cc3c3bf741b91dfa68c6c - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_encrypt_last.c 9b663e83c3004ebe1725ad851bde5f946c0e6150 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_encrypt_authenticate_memory.c 650667de1f0e3d2308872cf4537ae49498239261 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_decrypt_last.c 7d45e3754a326d8386f2e536d6baa81554378581 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_decrypt_verify_memory.c df0f2138b4cb5a037739e226490a0d08bd268048 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_decrypt.c 7c091098e78cd1fb572b8b2e843ac04d30099719 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_add_aad.c d3aff516bc303de0bedf794c42305bb770b41629 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_int_ntz.c 487cb958837ebcf06f92ef604fb17b4a495bbd64 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_test.c 5de251abffe4c5d5eea6c9deb2b5a3dd7c128147 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_int_xor_blocks.c 4dd6870aa2c7606e90a94d802fa383dd8515b825 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_encrypt.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 4a0d52f29c5da69ba1248de543b53f80f00f0358 - optee/optee_os/core/lib/libtomcrypt/src/modes/ecb/ecb_done.c 2f93fc0a9e1afdf93c263f75675e15d9aae63cf6 - optee/optee_os/core/lib/libtomcrypt/src/modes/ecb/ecb_encrypt.c a0941ac3c7a39107c7f3049a9ce6b7cc3d120c58 - optee/optee_os/core/lib/libtomcrypt/src/modes/ecb/ecb_decrypt.c a1361518be72e5f0a2c22cf2e99afc5155c64421 - optee/optee_os/core/lib/libtomcrypt/src/modes/ecb/ecb_start.c ad10e437f618657cf5b5e3ffc20fb6c5219a6db8 - optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_process.c 3e8b2b92ce4faeef2ac7282bb0e58253ed01bc41 - optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_encrypt.c 6166a8f10c3d96dd48d974f0c420288c79faaeed - optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_done.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 89b75f314fad2f247f3c02a8d043c69822182beb - optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_decrypt.c 6343e513ad46501c7b3c7dc039c8b246ea927590 - optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_getiv.c 6186f3e377626cce35518099044023ede1954ee7 - optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_start.c 75a66324c9304c63a62bc2a97fbc8ea51df97255 - optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_encrypt.c 85a32e2be465b69f7a4132892ad684cbcd8ea293 - optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_test.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 3dea7eb14320987637e14b812e161c7efa873b76 - optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_mult_x.c a2a2185a5cbe8319ecd9e65dbb720317d63814ad - optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_decrypt.c 41b01b20223d2bb66ac8f419cf6f8435c9867f86 - optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_encrypt.c ad7cdbcaef35b7db424ce95e64bf87baf2f4164a - optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_setiv.c cf8ba7e0b9c7428652d258729d7790277015c181 - optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_start.c 2140195d11a6c4c204d39ed215e9600018bd23cf - optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_done.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 06cbb137bfc9d209674f552805083aeb3ae1516e - optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_test_mode.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 747a817bfdd38ce834a9198f1e176c1fe227b3bd - optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_setiv.c 4a3b1b9453c09f7842de157e91770af0c0ed7415 - optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_decrypt.c 9e461ccf05f3b82c258302f4a3eb873038978a89 - optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_start.c e6d6ea2e6d96293a8daf46f6c0748936ccc3527b - optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_encrypt.c 7d9c7698b787a53e3bd28940cdd444746994860b - optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_encrypt.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 3a750d0cc44888f039a609e54a400af43310abcd - optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_decrypt.c a5a54f70612eca541d03a7a560aba8cdff0b4df3 - optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_getiv.c 56f1ea6d8684edf6bbfc6e96fec03f21f3ec7879 - optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_done.c b03f3351e97f9628fb7921eda85ae3f0b0534156 - optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_encrypt.c c9abd410a11d44eb94910ab6d95bafc4e75fcbe7 - optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_getiv.c cf2740b0fb974b94f1cc08890920c5e95f703310 - optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_done.c 2997b2353ddb192f89b3ec278ad91cdc8d7f2b62 - optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_setiv.c 0303400a05e16078ca1944029c36280472d79869 - optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_test.c ee5c9c1fd94d09694078522a5a470058f1aa78ea - optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_decrypt.c 265e8429da2df62461fd0b313a0120c58034bd0b - optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_start.c eb172f92954aa6843672b7d7bc9707f7448bc1c4 - optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_getiv.c 207351014a29ed0dce3fcaa0898b5c563262e0e1 - optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_decrypt.c 4ec1b143f43bb9aac8d870e9bad201ea008c17c3 - optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_start.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 f5dfcba990f115b494ccd95e958582ca983bfb31 - optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_setiv.c e618ce5c3d8409cf47b68ba9621e64262846a123 - optee/optee_os/core/lib/libtomcrypt/src/prngs/sprng.c 4b6959d31d2cd9d600c17adca9edd2b7fbb70bb8 - optee/optee_os/core/lib/libtomcrypt/src/prngs/fortuna.c 65bdd642447c1d4dfc26f0f35958f0e1f9dbf51b - optee/optee_os/core/lib/libtomcrypt/src/prngs/yarrow.c b1696e891350ceb540ac60bc6d4fc5601ae109b1 - optee/optee_os/core/lib/libtomcrypt/src/prngs/chacha20.c 0175635dc4f43317153da8fa639515156755da5c - optee/optee_os/core/lib/libtomcrypt/src/prngs/sober128.c 91b049316fd473eb33d4807d7b5aaa9a00844a82 - optee/optee_os/core/lib/libtomcrypt/src/prngs/rc4.c 94ca15102c5937a658d63a00e39be8d7ce0a25fe - optee/optee_os/core/lib/libtomcrypt/src/prngs/rng_make_prng.c 9931d364f7feeae167aaad25aabc387977444f87 - optee/optee_os/core/lib/libtomcrypt/src/prngs/rng_get_bytes.c 02474538dadafba33694c8ecab5fc2e6d00a7281 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/khazad.c 48cdd948011ecd3e9298f56dce531d60ede7608d - optee/optee_os/core/lib/libtomcrypt/src/ciphers/idea.c 398a2df01e72511a00c4fd56ef10ba61c9e08ae4 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/kseed.c 461cbf82c045454db297fe16c3c478c4cde8fadd - optee/optee_os/core/lib/libtomcrypt/src/ciphers/noekeon.c c870397dc946312c9c0304e8f132b1fe87eb18c3 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/tea.c 819970a30ad279c10add699d9bb08c1023039bbc - optee/optee_os/core/lib/libtomcrypt/src/ciphers/anubis.c e28e47ef72883f05ef629df3d495fddfda0372f9 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/skipjack.c 60505e6a888a893c8edf9d6065362453230d0d78 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/des.c d48e4087de75284fb9aa215069515ac90849dd5f - optee/optee_os/core/lib/libtomcrypt/src/ciphers/serpent.c 06e4fcdd40cc84f756e818ffb70a63da8066c7a1 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/kasumi.c b0f8a843a280133fbab3d261ce7a7486c5f20bb2 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/cast5.c 9748ebff9d560f59b42bb6c8c1dedc71dccbc225 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/rc2.c 4e35739fffcd60f1f9971113810a08c7c7fb114e - optee/optee_os/core/lib/libtomcrypt/src/ciphers/camellia.c cfc7412e0fbe23e14536db6836f3da2102c02e06 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/xtea.c 9d2d04084cdc6c4c56cec3479af1ccb74619fe42 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/rc5.c 783f175a7e6e630e954aa409e43cc67a854e2921 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/blowfish.c 0e87ea79442a67dec4fad902f2df7a827f1c233f - optee/optee_os/core/lib/libtomcrypt/src/ciphers/rc6.c 840013cf542fd64a45cdea8afb965f8aa0e51df8 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/multi2.c 4a6bb1fb9b2eed818cf6aebf8d6fc78f108db521 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/twofish/twofish.c b6e57c2661c58975ca885c612932e68bfeb45d9e - optee/optee_os/core/lib/libtomcrypt/src/ciphers/twofish/twofish_tab.c 48a4a60cd68d5143a1998139b830ee8fa7e56faf - optee/optee_os/core/lib/libtomcrypt/src/ciphers/aes/aes_tab.c 4d6e2810b820eb2b29529f2bb429d35841b3bdd5 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/aes/aes.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 82aa1b04a2ce5276fd516e96169dc1b0c2432bb6 - optee/optee_os/core/lib/libtomcrypt/src/hashes/md5.c 3c19181cce8bd461cc6a736ec3f3940ec737bcdd - optee/optee_os/core/lib/libtomcrypt/src/hashes/rmd160.c 1767c79b4e8637fd2636ed3e5d54dcd37cebae04 - optee/optee_os/core/lib/libtomcrypt/src/hashes/tiger.c 699622196fe40d368c4aa87afa335085d2d7cbd8 - optee/optee_os/core/lib/libtomcrypt/src/hashes/md2.c 17750b4d62fad12b1ae16ef01a8ffa2cac05fe1a - optee/optee_os/core/lib/libtomcrypt/src/hashes/sha3.c 50f0d32cf7879499990c4ec792546db1e812dfaf - optee/optee_os/core/lib/libtomcrypt/src/hashes/md4.c f0e38b2df179903a5c62a5d1223c27d9468f2b55 - optee/optee_os/core/lib/libtomcrypt/src/hashes/sha3_test.c a24770ddff20aa047ca6e50ed3b40f67fb229213 - optee/optee_os/core/lib/libtomcrypt/src/hashes/rmd256.c f7476e6db75e35d781ab4d7ac8fbbb76133f2158 - optee/optee_os/core/lib/libtomcrypt/src/hashes/blake2s.c c4e009d4708e3b97b2d83467411f582076ec374b - optee/optee_os/core/lib/libtomcrypt/src/hashes/sha1.c 436cc2c14c7f7f513d234253ebce325da3441faf - optee/optee_os/core/lib/libtomcrypt/src/hashes/blake2b.c bbb1244d51ea6efa2a0d6fd5ff5d1a6b507eb3cb - optee/optee_os/core/lib/libtomcrypt/src/hashes/rmd128.c c991e82af32c3fd33d4ca7f63a43c46aaa3a8af5 - optee/optee_os/core/lib/libtomcrypt/src/hashes/rmd320.c 63de08d2a37229f4bc2e4138db49d71e7f5786d0 - optee/optee_os/core/lib/libtomcrypt/src/hashes/chc/chc.c 5c4268acde331fa5dfc75643f9edc2c04189e29c - optee/optee_os/core/lib/libtomcrypt/src/hashes/whirl/whirl.c d4fe8714b77fd3ad07260899bc8b5307e2d44e68 - optee/optee_os/core/lib/libtomcrypt/src/hashes/whirl/whirltab.c 18123fb06342b70d7c8af10d2c72fd07b75e1d2c - optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha384.c f25a1dad013d500b85f3eef3b3570f30a88b8937 - optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha256.c 91834258fd0a291b0c2e8b5a43b6bd8f7278bca6 - optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha512_256.c 3ff874c5735dc5e5d895621a56ed2a379f35f3fa - optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha512.c 3b7138b66d581516a8dd7568842636ce576e8f33 - optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha512_224.c 3d396867f33dd56b9cb7f66e66c902badeee4bfc - optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha224.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 2f7b628448c81541c1e80e9cd8cd61e1489736f8 - optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_ivctr32.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 76550dd06cbcff27a2d8ac4d8f8ef0428da2a4ba - optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_memory.c a1c69b888c2662b3db2c4343318cfed05ce1a262 - optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_test.c 19529a1c91610536d1f56e09d8f7f0c1c44ed1fb - optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_ivctr64.c 95e2d29cf4201f1cc469997b0aef539883229f02 - optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_crypt.c 408fed5f27e4bb531ec7c18c4ea4b85e1b3e25b4 - optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_keystream.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 e554ce2b664e1b21e037000eab5b05a464e2f913 - optee/optee_os/core/lib/libtomcrypt/src/stream/rc4/rc4_test.c 43f7927b89b648f1b642bbe96a30329482a96706 - optee/optee_os/core/lib/libtomcrypt/src/stream/rc4/rc4_stream_memory.c 0370402bb2b440618f27fff3e9a7d3e2219a348e - optee/optee_os/core/lib/libtomcrypt/src/stream/rc4/rc4_stream.c d7ddc63403a0836fcb998d8a80e1d253aad3fac4 - optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_ivctr64.c b8a013b428ced9671422b507d6833d25312bd823 - optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_test.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 c1487e9b5be5b8d3a2662a6e37a477cf5c86bb8f - optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_setup.c e8f1fb8eb2b962abfef86027594a70a50023e9d9 - optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/xsalsa20_memory.c 5d403e317c9deb62133d017412250702a48683d9 - optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_crypt.c a4f8195e9e117c1053f0272b7b26bc835bdc5337 - optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_done.c 51497c0e6a261a2ebe26056565149049e7154e05 - optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/xsalsa20_setup.c 1e3ea925d7df004fe7994bcedc4d5e0d9551c09d - optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_keystream.c cc60780ba62cc198b8657fb2994150ebdbd9aabd - optee/optee_os/core/lib/libtomcrypt/src/stream/sosemanuk/sosemanuk_test.c 51e23c33fc2f379b97fdbb9128414859204e00a4 - optee/optee_os/core/lib/libtomcrypt/src/stream/sosemanuk/sosemanuk.c 15c26663221b68b94b5e2f66b93c1b4468d6b956 - optee/optee_os/core/lib/libtomcrypt/src/stream/sosemanuk/sosemanuk_memory.c 7c4f40cf2659b91a59b92ee79867fc47b44affe1 - optee/optee_os/core/lib/libtomcrypt/src/stream/sober128/sober128tab.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 ff214c34d15c197a91a236c37775d89e959c1bec - optee/optee_os/core/lib/libtomcrypt/src/stream/sober128/sober128_test.c 6adfd2c5e4b416a65be0e9e7d0b6a24c1a3589d1 - optee/optee_os/core/lib/libtomcrypt/src/misc/adler32.c f4059601bb534681d08bbf29b543f5bc37d29267 - optee/optee_os/core/lib/libtomcrypt/src/misc/zeromem.c 746776871c1d225104237b1021e530a23d5c1fd0 - optee/optee_os/core/lib/libtomcrypt/src/misc/compare_testvector.c 5c187006ec54c463347d528d5671b8e92f9b762b - optee/optee_os/core/lib/libtomcrypt/src/misc/copy_or_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 ff2dcdde770c5904024d8bd59763632a301e9790 - optee/optee_os/core/lib/libtomcrypt/src/misc/burn_stack.c ad0c66e6a4431f567b49915d01f026888538f63e - optee/optee_os/core/lib/libtomcrypt/src/misc/error_to_string.c c2fa3c8655b71dc36a48c5aa409c9ed586f9c8d0 - optee/optee_os/core/lib/libtomcrypt/src/misc/base32/base32_encode.c f5d1d5c1f347ba72d7eecf6995812bd9b0443efc - optee/optee_os/core/lib/libtomcrypt/src/misc/base32/base32_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 d0feb5c364be991806af64380cd3a6e5d7062ab3 - optee/optee_os/core/lib/libtomcrypt/src/misc/bcrypt/bcrypt.c 80d8a64decdaeb241abf260380e42f406eb7e132 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_unregister_hash.c 18b723be741bf36e94966af24f7f0da9fa256f26 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_constants.c 0090a8c4b12094134c7e3fcdd6c82cd26327c271 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_prng.c 082f0d654b13f0b93cbe1d28f01726941f0bac78 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_all_hashes.c abb752921991a5264ecf76f92d09589c9477d1d6 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_sizes.c 20925129239360b39ed195a0d8b6b99d59b890f2 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash_oid.c 1221efc9a518048e34fe881a93fe5c765524f34e - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_unregister_prng.c d15ddf5b26ce2f13c726a540479ac62355bc4ab3 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_prng_is_valid.c 9e47537140b5988fba0847120d3e311f83085ac8 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_hash_descriptor.c 70ff3cb0ee05909a347b56392e40b79171d1d3ce - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_unregister_cipher.c 6809767adc93fcb15bd91fdd9e99a6264937a6ef - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_all_ciphers.c d92b5cc31e60e6581ee77b6e9780353b967e8321 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt.c 994a86f2bda5d048c5755b0e7819184195f24ce9 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_cipher.c 28e1308aa1d2f79105cf6aedb36a9ea1664e3567 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_prng_descriptor.c 474440e2037216fed3c26f124fd92a96e2bf51d8 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_argchk.c 81f55ffa10b11eb901eb4a3e44acce81c2582f84 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash.c 5c81f4d8d18f6544665cf9385fabb100324f2323 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_cipher_any.c f1821b4e1d8e159fc9eebb3c49abfe0f6eef8da9 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_cipher_id.c a98c18ecdba584f662232ca582bb88b502daee55 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_fsa.c 26a169c33ea38516c1421f536f7bbeeb2983f01c - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_hash_is_valid.c 23eb56683e5cb3b2a6203532f2261e1146584ee2 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_cipher_is_valid.c c261fdd28c1198d33aeccd35a7728d324671e3b1 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_hash.c 34b218af0b0d226b125bb51da3c2016bcde2eb62 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_inits.c c22b0f36bb603c5a4cc0e043d1fc84ed5615c82a - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_cipher_descriptor.c 209b907a121df459daa08c8ab473adaedc01f56b - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_ltc_mp_descriptor.c 07ad1815506e2a82911ec0c3fbb9dbe66466efde - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_prng_rng_descriptor.c 96342e249d7c747d11849bf1a4a2cfa99139134f - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash_any.c 233015470408b5b2e38773c5b1127762f545a856 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_prng.c dd27864633e7f1746e256cc07e47437bbbb4bc97 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_all_prngs.c d4220e04397554fa19428f3ff33ebc5b80d93d7d - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash_id.c 63d0675dee46f130dd505b9ef11305f66b51d5ef - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_cipher.c eb9ee827d87cbf5ee6013ea99a318a0e5c477a57 - optee/optee_os/core/lib/libtomcrypt/src/misc/base64/base64_encode.c b4f980accf155a8df885c69266a8b2154992181a - optee/optee_os/core/lib/libtomcrypt/src/misc/base64/base64_decode.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 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 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 5e2328959d1d9fa3dfe651bc8390f56e97cfeeb9 - optee/optee_os/core/lib/libtomcrypt/src/misc/pbes/pbes.c 8ea5fa890004eae1957192d67e017a2f68ad820f - optee/optee_os/core/lib/libtomcrypt/src/misc/pbes/pbes1.c e0622cab6f654c9d78768c0037a71e91c7c904d8 - optee/optee_os/core/lib/libtomcrypt/src/misc/pbes/pbes2.c 6b7496efa00caecdbe62a0a85ac0ac8b7a637d57 - optee/optee_os/core/lib/libtomcrypt/src/misc/ssh/ssh_decode_sequence_multi.c 4a0a598b182902b1813bb584ef6dd3ae446d0c70 - optee/optee_os/core/lib/libtomcrypt/src/misc/ssh/ssh_encode_sequence_multi.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 cbc194b08bb465a7b3cea249824712fda8857789 - optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_import.c f2e15ff205094f5a30ffd289282806adf3bfa02c - optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_import_x509.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 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 9e8045a9b7b85a4fd345a8606dda5a4529102a84 - optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_import_raw.c 8d59b1b306078e34f08e267a5aa226debdf7551d - optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_import_x509.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 d06add7d54e686364cb1d56bc5c23a69c71597c3 - optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_import.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 3c7f07f8405b9f895d89a3ea2090632df8c19cc8 - optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_make_key.c bca50dcf7601a449f350e48f0db458f6e0377f15 - optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_export.c f527339cc3a30c2b3135771f132f79c94331a0d8 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_import_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 cf05860092837c42f574e893b097a13b3374da04 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c b818e0a65fbcb65e56211555e7979eb98ece81a0 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_export_point.c 966e686fb8e1225167a2e3a7c6df50b0540fa9c6 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_points.c 3e64593819f63544e4b0a5e7d7aca57eb34eade6 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_ansi_x963_import.c 5b57ce74997f89ba8f1107d442aca33bb2dc01e4 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_import.c fbe398aee3a10e7dcb094e86282410752aa1a8b7 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_set_curve_internal.c df15dd31ef7691042508e5eb5a7963483113cfc1 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_encrypt_key.c a5205a7b0f315b2ebe0a2ced975772f8a1057571 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_is_point_at_infinity.c d8f5cf749289d6a9c685c94b34909b764e1d7689 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_import_x509.c 1c00b1e26aaf1253c27c4f23b98535e45a041610 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_shared_secret.c 280c3e6ecb5e86ef00f694afb173a251ce58babc - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_find_curve.c 015e8b1e8df2b67df5666581c49ed3b443a17ebd - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_export.c 8149696ce9b92edc4b72e701857542c66a19265d - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc.c 1a11b95c51b4280fc073baaebd5f749bf0b623c0 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.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 0287f0fa69106c0067f42dcf123ce01e29d98031 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c 1860b05d1e6d84e49e6bde6665be70d81cc9c8a1 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_get_size.c 4204640f642d5ddb2df36d5eb318b13aed778172 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_map.c 450bf440ad3be5053c0d9c6d7926d5cdcd9714be - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_is_point.c b482130a4f79e28597bcb38ab42cff07c19787a6 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_set_curve.c 450616e20f9d56c11a1adb892a3645a93741b105 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_verify_key.c 6b5a515a99122e80c6c6b9aa06a86e21ee73b3fa - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_get_oid_str.c c5c1644f8bcfb94a1e9dc96faf3657ba2ebb4266 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_ssh_ecdsa_encode_name.c f03fb73a557258c6ea41d3193cd6bd750a62245e - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_verify_hash.c 4703d1e4bec1f70e5e1b17f15db6ee3a4046b47c - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_sizes.c b51764d8bd42b7561f41b8a977e021f720d461f6 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c bf20409e528c89116d228521a61e12ec29b6b8e5 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_make_key.c 42aa854ffcb3552db4fb57796569ea830db3d9e1 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_import_openssl.c bc4963f87689adb59ace0786a7b43d6a677b8512 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_import_pkcs8.c c8932926feb1db7458a4121747277fbf302deca4 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod_timing.c 96db40ce102160544ab24dfd2a14926461815e18 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_set_key.c 1fb03ce919d517f2cdd83c378d731a39ff656df8 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_recover_key.c 257ac82c33135561dfe7b5c7edecb5a2d0cdf7e1 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_free.c f547d958caecd824b0b17b1355530bcc788c20ca - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_shared_secret.c 2893671ff36eba57509da1721ac9e5cf8567b6db - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_generate_pqg.c 272952cb667172cf8fba5e852b5b8147d03f3534 - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_make_key.c a55666907f63f401c00cfa793eac033bc2226339 - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_sign_hash.c 0803f50e230a9797701852fd02cdc9821544fa74 - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_encrypt_key.c b6d3f3a6c24debd170f1ec62a74d682113250cff - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_free.c 5dc0463320e60a8062e4bb3b76301bfbb72227a5 - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_import.c 4b2dbab5e2aa90bd324218ea5674fef8777f8473 - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_export.c bb5f98cabbead6be93d785dcc286f45498d5c0c9 - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_set.c b2e238370d7a369638a2b76d7c64b726f3eb53eb - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_decrypt_key.c 3b82a4885c17b3d11eae9d1f870da34e6cae9f0f - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_set_pqg_dsaparam.c b0a3bbbaf6fb172cc402a25cfd4114abb554850c - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_generate_key.c fa3c683b57ff8087a2fd90fb5c6accf72d63ffd8 - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_verify_key.c 7da5513cb4e6ebca0d19c35d74509deb172ebac6 - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_verify_hash.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 952b34bccc6c1b05ad9de3bcddb1cca3b46b4e58 - optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_generate_key.c e304ed0a492309f8b0055a4e147f87970fdf38bc - optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_export.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 a1886213cc203cfe7e6ef49271838e7d967f53bd - optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_free.c ec26e921ae1e3e3d36d45dc1e9485f2ce7793529 - optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_set.c 3f0628db016f76777bae6ec89728511a7cb6cfa5 - optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh.c fb90bf4aa59ee4d6f4371b1ed062a7efdf83462e - optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_set_pg_dhparam.c af78940c2ff22884837509d7ba94f767ac3af81e - optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_import.c 9765d9c7ad353767665e26aa27114aed5064b9d5 - optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_encode.c f804f75c30cacbad97b14cac9f9603f27f4ee67f - optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_encode.c 7a444c752e2d4df2d1384ce8f9a56dff42a02347 - optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c 7bb1feddfc1ba6fcb69cb4ef537c5a0dfafb8d1e - optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c fa6b0f40cef3e152cec36c4ccd8d895e10dc60ca - optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_i2osp.c 2d5bca5df73d8684673df1d6ab38bae6f25cd304 - optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c 7e7beaf2f29e72101e3ff7ff9cde8d32af8b6305 - optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_os2ip.c f97b4369ca4a6cee89a277cd05e60345fcc88377 - optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c 357e06818540426a6b09b30b6265482454ba9342 - optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.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 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 fde5cba0f1fbdcfa0af606a17b90c2ece77fdfee - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/x509/x509_decode_subject_public_key_info.c 2e7715416f0b9b81765354e9b71ac389bc674bdb - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/x509/x509_encode_subject_public_key_info.c 2e24598b6fabfaad933446c87bd5a064a275e144 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c e9d1241660244c310419ea1378b9ae323a7ac61d - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_length_asn1_identifier.c 5ae066c005e04dc7f013a783713675e77547f565 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_length_asn1_length.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 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 aedf07da8f7d1b98991abe3e3e74d0760c207630 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_multi.c 16be383d4118fcac43cee6cf8550a7b4027ace1e - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_ex.c c5977a968d09b999595cf145d3429a62599ca661 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_free.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 36b1d4df09d77914a9621e323848927e19b9e482 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_length_sequence.c 3547f3191ec66412dcb8347be374eca128c03c11 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_shrink.c ca146db1227ca30261685565e96aad77b75b5577 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c 24de714f216931c3f599fc8d1e2deb86c21b847d - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_decode_bit_string.c df1aa22c0a11a444fa3e307b084eb35b6d651a88 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_encode_raw_bit_string.c 291e2e946e23e0e29c802af28ecfb68aa74a3179 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_length_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 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 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 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 4ab4dd3b5bbbb87afcfc52966eb024bb4d0c8234 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/generalizedtime/der_length_generalizedtime.c 52132cd7a799e297b872a524bda661601b33e5a3 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/generalizedtime/der_decode_generalizedtime.c e50711035dcfcaa4d0c1fc32f433be0aa8d98689 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/generalizedtime/der_encode_generalizedtime.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 715c09b19bbef0a9d89511be2ba47db3eb184457 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utf8/der_length_utf8_string.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 ddc24ebe07f30aff933f0dcacceca877f7a8c912 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/ia5/der_length_ia5_string.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 f65972e7e1e35ea9bf3c750f6d2fbd3c22de8df1 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/boolean/der_length_boolean.c 2c41e8e870f523500c8fb60f9d88b90dd079c9ab - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/boolean/der_decode_boolean.c b85ec531d4f44b87eb3be27290a2aaddc246d62b - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/boolean/der_encode_boolean.c cdc82def06cef9eb373fb549f277544af32d2d40 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/integer/der_length_integer.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 13994ec081d65c83c2a411ecce60211f79aa7f8a - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utctime/der_encode_utctime.c 9d6bf8a3d490c881c022ec153b9dfd96d4798be1 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utctime/der_length_utctime.c 5c2277093dc1c4f2d6b877f924200805c950e697 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utctime/der_decode_utctime.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 8eedec47a421b47090137b1e2da8eb203fdef911 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/custom_type/der_encode_custom_type.c cdbe2378f68d5da22b7a94428334cb11343dd5ff - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/custom_type/der_length_custom_type.c 6dc60f80f7af76c0a1b5992f03ddea0435b439ec - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/custom_type/der_decode_custom_type.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 979846f85b72946ff810edf5eafeca166d4283fd - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_sign_hash.c 47347830be6ee382ced26f00e0be055570804c49 - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_sign_saltlen_get.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 9a424e42fb17d230990378f002faa44cd171738f - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_make_key.c 01b964e18bfa23b2d17ae36580bb114f096fb07c - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c 071f6f93d133ca61acdffd03ca03180bd812032b - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_export.c 11826b990bf085ee0676611201c6a738ee4bff48 - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_verify_hash.c 38f5811d94e0c86e4215591ed40917dbde19a7f8 - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_encrypt_key.c 87a49a80c12d41e8594da7524050eba34e5f96f0 - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_import_x509.c a47196953806fe0b060f66e17a9f5c26db46a788 - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_key.c 9f43d136949b104d186b32b4e272ab71212d140b - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_import_pkcs8.c 32efc4a6c51bd46b2e5123cff17d55cc8560d582 - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_import.c 131a94c18f4c6d67111f71772ce64e30b214b7c6 - optee/optee_os/core/lib/libtomcrypt/src/pk/ec25519/ec25519_crypto_ctx.c 344a33caba6182cfa38c93b69be392fdb85ac4c9 - optee/optee_os/core/lib/libtomcrypt/src/pk/ec25519/tweetnacl.c bbaf6a67e160f4064a99efb50a56e264bcd9722d - optee/optee_os/core/lib/libtomcrypt/src/pk/ec25519/ec25519_export.c 406b6b0422373c9c2a3c3f85df960bd5fd4134d8 - optee/optee_os/core/lib/libtomcrypt/src/pk/ec25519/ec25519_import_pkcs8.c 4107a71b931755873657a1db5c1d361d3baad0e5 - optee/optee_os/core/lib/libtomcrypt/src/math/radix_to_bin.c 0519f4dfb1ed6bcad6119da63132e2cb99a1ed77 - optee/optee_os/core/lib/libtomcrypt/src/math/ltm_desc.c 2ca00d67d4090191db790a545cd86d609c5678eb - optee/optee_os/core/lib/libtomcrypt/src/math/gmp_desc.c 9974963705cf2ee6ede4a5f04102ba8237fe707e - optee/optee_os/core/lib/libtomcrypt/src/math/tfm_desc.c 64535e883ae11fec86629844a95e9c1d7f02a486 - optee/optee_os/core/lib/libtomcrypt/src/math/rand_prime.c 6eb1e1c16c036e2717dc3ab41e98acde07da53a8 - optee/optee_os/core/lib/libtomcrypt/src/math/rand_bn.c 829f687603d1caba9543ddddb56af948b6a6369e - optee/optee_os/core/lib/libtomcrypt/src/math/multi.c 5a3aef9006609eab6327112f5508e2991e7a678e - optee/optee_os/core/lib/libtomcrypt/src/math/fp/ltc_ecc_fp_mulmod.c eb37e780cdfe0dbafb29c0fa8629125c6e19bd6a - optee/optee_os/core/lib/zlib/adler32.c edf93d4bfb11950ac75aade2faf0bf05d0aaff47 - optee/optee_os/core/lib/zlib/zutil.h ce569e81ab26f5eb8d922b18be6561af7876c4e8 - optee/optee_os/core/lib/zlib/zconf.h 5121bcf9ae9f1eb58b39c4debbc5931e5be16434 - optee/optee_os/core/lib/zlib/inffast.c 47e5da9b88163c7194af9b7b6a17fb46ca08b009 - optee/optee_os/core/lib/zlib/inflate.h 341003df806d2bcfcbd194fc3f9da99919b918a9 - optee/optee_os/core/lib/zlib/inffast.h 8770ab43c9050b824c646f6e6cee8b3c0628cbda - optee/optee_os/core/lib/zlib/inffixed.h 1e0b1438feffed910661d48b2b793a5f7c308f06 - optee/optee_os/core/lib/zlib/zutil.c 00b226f75f6beab393031f6893b2868c707d0d0c - optee/optee_os/core/lib/zlib/inftrees.c 206b2054814df6c3f42f29c045d584c6a25c462f - optee/optee_os/core/lib/zlib/inflate.c 4192c931405d13fabed42ec8725255502d35fbcc - optee/optee_os/core/lib/zlib/zlib.h 8139ab5dd86e53ccbde7ba4e78200db4cd79f9a9 - optee/optee_os/core/lib/zlib/inftrees.h 36c4f51e48f8320621c5739dd2ee69ef0d973a21 - optee/optee_os/core/lib/zlib/gzguts.h 79b1451ee0197c749cd4f07450ed2d374f1c3cee - optee/optee_os/core/lib/scmi-server/scmi_server.c 619aa8e61beb89b2df060ca24485432e8269b5fd - optee/optee_os/core/lib/scmi-server/include/optee_scmi.h c05559286b41f00c3815a047a26e80df6785a42b - optee/optee_os/core/mm/core_mmu.c 129dfa30ed6d0f01fa944600085cfb54b0dae9a0 - optee/optee_os/core/mm/mobj.c 7f4fbb1dbd7b0a4a78f67b449a3ec8ed6e2289b2 - optee/optee_os/core/mm/tee_mm.c fbf52bc1a50fae147acaeca0138d7dc640a88275 - optee/optee_os/core/mm/pgt_cache.c 73be8d9cc10ccf4ecc646ab51ec17b8bbb51177c - optee/optee_os/core/mm/fobj.c e7f04184eddb0da4969adfcbd5dd4a378d087fca - optee/optee_os/core/mm/vm.c 4c81a53362b3a07b1dabb5a197f0e3ec26117bee - optee/optee_os/core/mm/file.c 62bea91954c0b60ce398bcc52950deef1311beb8 - optee/optee_os/core/pta/device.c b137817eff91658d19d1a479dee6a84dda10ccbc - optee/optee_os/core/pta/attestation.c 3ea15c610f4ecba8788d1055a06e13c3b6aeea5f - optee/optee_os/core/pta/scp03.c 4b7b26064a5527653817507ced6b5d36e09d75dd - optee/optee_os/core/pta/rtc.c 14015171ba8ab23dce63f6011ecd0899f08137c1 - optee/optee_os/core/pta/hwrng.c 4e1b614df9067b7a1f2158f1d5111c1925483f9b - optee/optee_os/core/pta/apdu.c 6a748b8c571c2b207c9db79b56b491192bf22379 - optee/optee_os/core/pta/gprof.c a479d607c3f4dcbca4d5d1e9797340ef6e59131d - optee/optee_os/core/pta/scmi.c b07d570bacd753a4f6c4ddd3730017971f2f9d85 - optee/optee_os/core/pta/widevine.c 8f532c3b41d08bdbee29cdf99e831e9a5652bd71 - optee/optee_os/core/pta/system.c 6284c967a1103f26724ff4dfe45af409bfbbf948 - optee/optee_os/core/pta/secstor_ta_mgmt.c c8f8fa8bd161af69f46889e90966bef0ad018b68 - optee/optee_os/core/pta/stats.c 4c4029f19bf83df309ffd54d9d525c327ff8a7c7 - optee/optee_os/core/pta/tegra/jetson_ftpm_helper_pta.c f04e7c33a8c114fd563d57de4d069c6cebd01e0f - optee/optee_os/core/pta/tegra/jetson_user_key_pta.c 9f086ff5817b522588e0b043af390b20bc659347 - optee/optee_os/core/pta/tegra/jetson_t234_decrypt_cpubl_payload.c 186b949fc854bc97be7883a0f85300a6113bce2c - optee/optee_os/core/pta/tegra/jetson_t194_decrypt_cpubl_payload.c 169bda07f69b89df46b79e7a085d3fc44595d2ec - optee/optee_os/core/pta/tegra/include/jetson_decrypt_cpubl_payload.h c527ed81dee9ab0a7262d28f7a7318bfb152c4da - optee/optee_os/core/pta/tegra/include/jetson_user_key_pta_ftpm.h 434dbf013ffa6633ede1816527dfb82782c3db0d - optee/optee_os/core/pta/tegra/include/jetson_user_key_pta_compute_cmac.h 8c32652450144f8d62ba455a35cede26cedf44c3 - optee/optee_os/core/pta/tests/fs_htree.c 598beefd2c0b1d1ed3caf79b7ee3f6fd4315b410 - optee/optee_os/core/pta/tests/mutex.c 58a21a5d072a642b4650c67cc299e210a254d9fb - optee/optee_os/core/pta/tests/dt_driver_test.c 9d5f604852b526c4c03348962f3d622ead341452 - optee/optee_os/core/pta/tests/invoke.c 773d0fc2245c86d75271917a6eef93910cd5a5f2 - optee/optee_os/core/pta/tests/misc.h a27586aab31e93cb9ce669c13e202c989d6f3e00 - optee/optee_os/core/pta/tests/lockdep.c 1828d31f10e6236e1f4f6c98f71f34b61827f092 - optee/optee_os/core/pta/tests/misc.c b939d0c32959ac65dafe67f6019699ab4f194d94 - optee/optee_os/core/pta/tests/aes_perf.c f76d93f72808e78fe854329128254e40a8ae64ef - optee/optee_os/core/pta/imx/digprog.c 9c77709e56621860013c067a19359bd3f2fb621c - optee/optee_os/core/pta/imx/manufacturing_protection.c 1141e0df408fb0977880fbd63e8a1575a2a81e8d - optee/optee_os/core/pta/imx/ocotp.c fc52da8f6cfc83dc3606768cd703affc8029c2df - optee/optee_os/core/pta/imx/dek_blob.c 5b825d9894d2ed56396b487aaa3d994d6860b837 - optee/optee_os/core/pta/k3/otp.c 83d3b7f9616db0d5e42b621f55691ec5d505b4dc - optee/optee_os/core/pta/stm32mp/bsec_pta.c 8e4201b982761ca70f6155537299a9fbcdd9555e - optee/optee_os/core/pta/stm32mp/rproc_pub_key.h e3cc7102b54ea2bb07693ad42f9497a44a93df51 - optee/optee_os/core/pta/stm32mp/remoteproc_pta.c 5d347d3376095cbc05c1ae47cb6d4ac6f74ef5b5 - optee/optee_os/core/pta/bcm/sotp.c 3a98f4eae781f4b50887b79395cb6cefbf957df3 - optee/optee_os/core/pta/bcm/gpio.c 92265a3a661a4862d09043e5c3ed8787895b4d23 - optee/optee_os/core/pta/bcm/bnxt.c 8accf96a33e318180c18fd79729c3476c4e4a567 - optee/optee_os/core/pta/bcm/hwrng.c c53ce6db2d7519d9bd08c02472fe525fbb768a6c - optee/optee_os/core/pta/bcm/elog.c 1d96880636f5a98568edf08f68e5e4b38291da17 - optee/optee_os/core/pta/bcm/wdt.c 565af249a8ad523f04c21a52b091bb00f021d43d - optee/optee_os/core/tee/tee_cryp_utl.c 792b545f3897e6cf80b0b561c1f99382c02dafe1 - optee/optee_os/core/tee/tee_nvme_rpmb_fs.c 791192c3a090ffefe53650af896cb341e30c6552 - optee/optee_os/core/tee/tee_rpmb_fs.c 40a7130c87b8874c0ff3df4ba6d7ac5ecc7010a1 - optee/optee_os/core/tee/socket.c 3be470d597c40bff1ed4641b735cb7fef3dce6eb - optee/optee_os/core/tee/tee_ree_state.c e8ee3f02aee406877da4da3ff36dacb130cfab40 - optee/optee_os/core/tee/tee_time_generic.c a2028063632c8857bed15d993063a7fd353ee9c0 - optee/optee_os/core/tee/tee_cryp_hkdf.c a1f3d00831693e2b21465993a0b88230998270fd - optee/optee_os/core/tee/fs_htree.c 8462217cd1216cdeb47261930203db704ccd4ed7 - optee/optee_os/core/tee/tee_svc.c 0cdf747942eaeec2f670e600d773b8d1143cc2e8 - optee/optee_os/core/tee/tee_fs_key_manager.c 5be8cb39c5a5a4e02648d219b3f67eacc9868f36 - optee/optee_os/core/tee/tee_ree_fs.c 53578bdbeb3107e8113102750cbc8d8861701bf8 - optee/optee_os/core/tee/tee_pobj.c 3264e7dee283facb91122a3be3a91c34300d49dd - optee/optee_os/core/tee/tee_svc_cryp.c bbd20680e1d41ecf7f806411c32f0eac33c860f9 - optee/optee_os/core/tee/tee_supp_plugin_rpc.c 8fabba1dda1dee9af15b514f65afdae49ba948ff - optee/optee_os/core/tee/tadb.c dc4bbc967130baa858c0d97bb72c8d16aeb961d8 - optee/optee_os/core/tee/entry_std.c fc58bf53b6b42bf286bd64683b86c6d31dc3a517 - optee/optee_os/core/tee/tee_cryp_concat_kdf.c 4ca9c10d9b17380efab8d45d2de31948c98a16e5 - optee/optee_os/core/tee/tee_ta_enc_manager.c e59e39dfb4986541318ae84e47f44e52afa20b12 - optee/optee_os/core/tee/tee_fs_rpc.c a1202328842c81639257318e2047a9e13b1802c0 - optee/optee_os/core/tee/uuid.c dd81c49e2b9da8f822e7246d08cecde9f28fc2a7 - optee/optee_os/core/tee/tee_cryp_pbkdf2.c 4c03723f4ad981f468207f5a6437352c5c87b0db - optee/optee_os/core/tee/tee_svc_storage.c ee7b25818bd52227343d7f45f5ef5f725be9a89b - optee/optee_os/core/tee/tee_obj.c d18ce49edc69a8027687b7b43c5d4d36c33cfac3 - optee/optee_os/core/tee/fs_dirfile.c c62767343baa3f2bbf0bb384fa1feee2ff2784c5 - optee/optee_os/core/arch/riscv/mm/core_mmu_arch.c a67134011a6bba88ca1207fbcbfe628c0ac0b4ba - optee/optee_os/core/arch/riscv/mm/tlb_helpers_rv.S 4065c59874a936748d321924f558ea342fae8947 - optee/optee_os/core/arch/riscv/tee/entry_fast.c a141eda98aea803a64ff9542fcd8a574020b418a - optee/optee_os/core/arch/riscv/plat-virt/platform_config.h 159322372864ce9f888c412d5d39c84fda99e290 - optee/optee_os/core/arch/riscv/plat-virt/main.c 5f83776d0c7ce64d6d01df485fd353b7d1d20699 - optee/optee_os/core/arch/riscv/include/sbi.h 56bd7d4c065fb5932029bbc17b96d59a42f34270 - optee/optee_os/core/arch/riscv/include/riscv.h 1223e5cd29f4984ecabe36e78efe63b42f2bb84d - optee/optee_os/core/arch/riscv/include/riscv_macros.S aaf4ec0db08de01b5e8012ce949710f9dcf0f993 - optee/optee_os/core/arch/riscv/include/encoding.h f90a39605a177515f57172f8bfcac31468bec502 - optee/optee_os/core/arch/riscv/include/mm/generic_ram_layout.h fd17c38c386b15bdb4e87b47c4a2fbc2a66e8171 - optee/optee_os/core/arch/riscv/include/mm/core_mmu_arch.h 291fa9f4f92f4c42ffc5713f505e357cd3d7e9c1 - optee/optee_os/core/arch/riscv/include/tee/optee_abi.h 3e29f4f935b7151c6a16978c5c3d956c8b1d3be2 - optee/optee_os/core/arch/riscv/include/tee/teeabi_opteed.h 5eaa1cef4d6a42985aca8a8308f4f1f732ce71b0 - optee/optee_os/core/arch/riscv/include/tee/teeabi_opteed_macros.h b66cd21c1e374e71627820cd3c2a6621a7212f89 - optee/optee_os/core/arch/riscv/include/tee/entry_fast.h 0c4cbba16aac1f17267a36ecda588756cfd3277c - optee/optee_os/core/arch/riscv/include/kernel/clint.h d331fbb22fc7d3164c7b2d0ba55f2fec013d9cf4 - optee/optee_os/core/arch/riscv/include/kernel/thread_private_arch.h 8cc637a0b1fa21930752c33d1cc58d647bc81179 - optee/optee_os/core/arch/riscv/include/kernel/arch_scall.h 826a1d5fe853d5d25e39ce6e66d577e479b11016 - optee/optee_os/core/arch/riscv/include/kernel/stmm_sp.h 9fe08ff654da68413ec097e684cf2d6a39de3b56 - optee/optee_os/core/arch/riscv/include/kernel/misc_arch.h b3be5129fb98824666e9dbe5734dd1f811ab97d4 - optee/optee_os/core/arch/riscv/include/kernel/cache_helpers_arch.h 359cfc0da1c4cc03f466ebe78020a796e736dd55 - optee/optee_os/core/arch/riscv/include/kernel/user_access_arch.h 0152544509ec093752ad771824add96b3ed7a04c - optee/optee_os/core/arch/riscv/include/kernel/tee_l2cc_mutex.h e363a3270c54efb0764aceaa2210b94a552269b1 - optee/optee_os/core/arch/riscv/include/kernel/tlb_helpers.h b7fa8ca503a4c669510829a0aa242d662cb674f7 - optee/optee_os/core/arch/riscv/include/kernel/delay_arch.h 9ff069cbffd055e8fc24029279eafec7c295b34a - optee/optee_os/core/arch/riscv/include/kernel/secure_partition.h f9ad119abcc0fb84ce214fa4cc0d9f507c860d7f - optee/optee_os/core/arch/riscv/include/kernel/thread_arch.h f4d75a0309e2040dbb1ca13717a13dfa6be01e03 - optee/optee_os/core/arch/riscv/plat-spike/kern.ld.S fbcbb1531e4e70ea9aad7289c3cda3efc1eed54f - optee/optee_os/core/arch/riscv/plat-spike/platform_config.h 944299de7735a170cb3eccd15eec91c07a5e7672 - optee/optee_os/core/arch/riscv/plat-spike/main.c 359b98fad7ce1225b5fb675394acb32df9e74380 - optee/optee_os/core/arch/riscv/plat-spike/drivers/htif.h 558db749b68778acc836e96fc170bc823ab0e441 - optee/optee_os/core/arch/riscv/plat-spike/drivers/htif.c 09e09dcb96e69d3d3ea89c3997d9340fe33f53da - optee/optee_os/core/arch/riscv/kernel/semihosting_rv.S 53456fe6fd16922b93fddbb3e177d68557843d5d - optee/optee_os/core/arch/riscv/kernel/tee_time_rdtime.c b163d4b03cb454500769933734d6cfc2f5b50155 - optee/optee_os/core/arch/riscv/kernel/entry.S ef752dba0afbc3441defa0ce7f596275e4eacdf6 - optee/optee_os/core/arch/riscv/kernel/idle.c de03d1758884a3e0e0f7ea910139d312790963d1 - optee/optee_os/core/arch/riscv/kernel/arch_scall_rv.S 6543d720eb1111ece07baa5ef24e17f5166c3c66 - optee/optee_os/core/arch/riscv/kernel/thread_rv.S b3ad33b5f5481b84a1a568cfec88d6bce78f4e40 - optee/optee_os/core/arch/riscv/kernel/thread_optee_abi.c 137070765c0c55bc0ad0e2a1c59919088ed69e85 - optee/optee_os/core/arch/riscv/kernel/arch_scall.c 0f43c49d2273009469484b2cc76a2b941e4d9d68 - optee/optee_os/core/arch/riscv/kernel/cache_helpers_rv.S d7ea3b838aae7c777e6db63f192267e50bf10cec - optee/optee_os/core/arch/riscv/kernel/sbi_console.c 7c20c3e99ed3f34f87513b8b6648ce62062805f3 - optee/optee_os/core/arch/riscv/kernel/thread_optee_abi_rv.S 937e79d309f828a69b64d6998e80595aa1eea7b5 - optee/optee_os/core/arch/riscv/kernel/abort.c 9fc8bce83666ebb14ca70e1a2140db274ba5f0c1 - optee/optee_os/core/arch/riscv/kernel/thread_arch.c 848daa8b88efcef6b41ae9cd1598e5aa1d24574d - optee/optee_os/core/arch/riscv/kernel/asm-defines.c 0de310d21aaf90056a2327f208ed61a659cf483f - optee/optee_os/core/arch/riscv/kernel/sbi.c df7133315b272219ed0615fbcd0b9f2770f8c32d - optee/optee_os/core/arch/riscv/kernel/unwind_rv.c 7f1c0c47cf8d4455d3bb56977982a34a008a7fbe - optee/optee_os/core/arch/riscv/kernel/spinlock.S 6309bad6a7c50cedfe6901944f520790b07f26b1 - optee/optee_os/core/arch/riscv/kernel/kern.ld.S f3714d71c5a47d36649c0a35563b87efce775068 - optee/optee_os/core/arch/riscv/kernel/boot.c 4e0482b88d52f8a7d6adf974d0e5015f13872f65 - optee/optee_os/core/arch/arm/plat-rcar/hw_rng.c 15d328d6ef35c2f6a4c4f5a69f4eb2a571802c1c - optee/optee_os/core/arch/arm/plat-rcar/romapi_call.S 29cb5b650192d2e9a8bc4b01921c70539825e413 - optee/optee_os/core/arch/arm/plat-rcar/romapi.c 9ca9f50ac43c9276ee67375c8e915f0827e349d9 - optee/optee_os/core/arch/arm/plat-rcar/core_pos_a64.S b713d037582ce7c9f21402a91665b067ed931ff7 - optee/optee_os/core/arch/arm/plat-rcar/rcar.h f8a2662937d568146b977cdedf2e268e5b1f6b6e - optee/optee_os/core/arch/arm/plat-rcar/romapi.h e5ec049ffef670a29b7cade4d9d9f96abef549f6 - optee/optee_os/core/arch/arm/plat-rcar/platform_config.h d99c2594d96797d631564d55d1cec73d69073a16 - optee/optee_os/core/arch/arm/plat-rcar/main.c 105fcd115c8f37f13c3f1617c6e564dce1a1a50f - optee/optee_os/core/arch/arm/plat-stm32mp1/reset.S 41fc0d480726ccac287c2341b62956a102d2b134 - optee/optee_os/core/arch/arm/plat-stm32mp1/boot_api.h 166fbca392a757857b207b6a39177ebdae48c2a1 - optee/optee_os/core/arch/arm/plat-stm32mp1/stm32_util.h 4cd706376b2b8e9f29529251f6e8dd0f97b45a2d - optee/optee_os/core/arch/arm/plat-stm32mp1/link_dummies_paged.c 7a02cc2b686285ca057686052ccf437bc2441e81 - optee/optee_os/core/arch/arm/plat-stm32mp1/scmi_server.c b2bae4d35241a08ab393a13a463719aacabe7159 - optee/optee_os/core/arch/arm/plat-stm32mp1/shared_resources.c 5b41538b0faeb38ba559f5e71fc8c7fb4b808593 - optee/optee_os/core/arch/arm/plat-stm32mp1/platform_config.h ee9a76fa832621b03cd35d4e26d326eb11e278aa - optee/optee_os/core/arch/arm/plat-stm32mp1/plat_tzc400.c 92c2966c3109fd535677e7f5a34fd89106328ea6 - optee/optee_os/core/arch/arm/plat-stm32mp1/main.c 8e7e39483872171d059e87be0b70594fb8a2abaf - optee/optee_os/core/arch/arm/plat-stm32mp1/pm/psci.c a1238faa3df41c0c66412e3b032255e1cd4988eb - optee/optee_os/core/arch/arm/plat-stm32mp1/scripts/stm32image.py 0c65b2a9483053f11245b70f723294b6d32fea5e - optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_syscfg.h af1241bfcd71e1d8950df5ee76e9cd120d9a67e8 - optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.h f1cfb11d1e643d8118b07e9de2b36797b20c4cc2 - optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.c 6f513d1b2ba687dd8a5d3d5b3942d070b8475b3f - optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_syscfg.c 0a5b02ff39cea084c1bafb0169edd9f4a643592b - optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.h a3ac99fd762c9216188d37d084dd70008fbe1199 - optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_etzpc.h 8e140261281a08779ff3209432e4170bf4ea066b - optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c 4e92814caf4d208f3424697ce4a54cbceba75632 - optee/optee_os/core/arch/arm/plat-stm32mp1/nsec-service/stm32mp1_svc_setup.c 536663cb01d75d67a4021fe8314c5ae79909dbd8 - optee/optee_os/core/arch/arm/plat-stm32mp1/nsec-service/stm32mp1_smc.h e7ec6cb3b0018db5664ccd87d3ab1529e5d5713e - optee/optee_os/core/arch/arm/plat-stm32mp1/nsec-service/bsec_svc.h d335d9bb50b2453d365ca88f3f18520fdd0a1086 - optee/optee_os/core/arch/arm/plat-stm32mp1/nsec-service/bsec_svc.c 81eaad1a97f464cb81867fe716edddc6a94c14a2 - optee/optee_os/core/arch/arm/plat-sam/platform_sama7g5.c b04aabae313af1ab007337548c8d3c3340147467 - optee/optee_os/core/arch/arm/plat-sam/sam_sfr.c 05ae55b82f1b86db41cd5dec856b760b9cbac2db - optee/optee_os/core/arch/arm/plat-sam/sam_sfr.h 6bb95a72f4df9441141153c1f593d952cdbd5088 - optee/optee_os/core/arch/arm/plat-sam/platform_sama5d2.c 9e03ab42551128401c4786a75250b1db1cd4922d - optee/optee_os/core/arch/arm/plat-sam/sam_pl310.c c85debf71cacdc0e53e262424984cec5fece885f - optee/optee_os/core/arch/arm/plat-sam/sama5d2.h 66bba258091108cedb62f43234a3e9fa874dbd85 - optee/optee_os/core/arch/arm/plat-sam/matrix.h c6124d9de9443cdbc216ffbbe7eaa083e321867e - optee/optee_os/core/arch/arm/plat-sam/matrix.c d452ceba090437688ae1658171bcda10e43263b4 - optee/optee_os/core/arch/arm/plat-sam/tz_matrix.h 087ee14fbb7d4606fe2f1b748c159783d18a6ec5 - optee/optee_os/core/arch/arm/plat-sam/scmi_server.c cb565968e3bdcd440dd373b4b88bd1e995c64e08 - optee/optee_os/core/arch/arm/plat-sam/sama7g5.h e41104fa5f74b992b4dbd859dd2a1b4b3b2bb913 - optee/optee_os/core/arch/arm/plat-sam/freq.c 48e145a8a02773f53e3afc68f9d44f1aab5f8be5 - optee/optee_os/core/arch/arm/plat-sam/platform_config.h 51975d5a6d4516cacb42fd70885043c1f8b6fbf1 - optee/optee_os/core/arch/arm/plat-sam/pm/psci.c 0dfa109395fbc4b3c968756ccf16d0e1d8cef554 - optee/optee_os/core/arch/arm/plat-sam/nsec-service/sm_platform_handler.c c11e25489752cfc848301693c08dff59b589ed3f - optee/optee_os/core/arch/arm/plat-sam/nsec-service/smc_ids.h 49dbe1b862ab1676a3186ddc9f6c7650820902d7 - optee/optee_os/core/arch/arm/plat-totalcompute/platform_config.h d07921192fb4097f0da3129fcfc442229f93154f - optee/optee_os/core/arch/arm/plat-totalcompute/main.c 00e4e12466db95649e17c7dce132fd03e23b837c - optee/optee_os/core/arch/arm/plat-totalcompute/fdts/optee_sp_manifest.dts 46a2594f3aa4681ffd83538ff397c8e3bf3974ca - optee/optee_os/core/arch/arm/plat-rockchip/grf.h 384be00889fd82aa785e7d07fa9f819c764557c4 - optee/optee_os/core/arch/arm/plat-rockchip/platform.h 82976a1c26f0098dc91782fdd667476feac53253 - optee/optee_os/core/arch/arm/plat-rockchip/platform_px30.c 24c8244ba3044caed1943ad05138413c6db6ab2e - optee/optee_os/core/arch/arm/plat-rockchip/platform_rk322x.c e8c669f6cd515061ddc1fac878644149427040c8 - optee/optee_os/core/arch/arm/plat-rockchip/psci_rk322x.c 7993e64e5bfd2d72ce89ef822b3a49a1381e8c69 - optee/optee_os/core/arch/arm/plat-rockchip/platform.c 1853ca66ab2f40919fcb69448e1b866eb2bc9e4b - optee/optee_os/core/arch/arm/plat-rockchip/core_pos_a32.S 971d879311868f34f4ebf712ba6de5f9f0ea6f35 - optee/optee_os/core/arch/arm/plat-rockchip/plat_init.S de4933508c95b4cc044fec515f190d8ff6ebfdc0 - optee/optee_os/core/arch/arm/plat-rockchip/common.h b74b363d6e2a566d4a03278aaacaf9391d505a44 - optee/optee_os/core/arch/arm/plat-rockchip/cru.h 5c98cb66829c84f0e07676a8a66b6883c782b877 - optee/optee_os/core/arch/arm/plat-rockchip/platform_rk3399.c 86e640e06414afd26ad833d31867572408fd251a - optee/optee_os/core/arch/arm/plat-rockchip/platform_config.h 4d0bc50554ebec63e6fb62a4772b77b82ec501cd - optee/optee_os/core/arch/arm/plat-rockchip/main.c a1a353aa32ebd77dd5c2966ff38e024d0e8938bb - optee/optee_os/core/arch/arm/plat-k3/platform_config.h 882cb529fe6df1cf2eed27c1d61be5069bf860a6 - optee/optee_os/core/arch/arm/plat-k3/main.c 6a4aeba37a7be60d63bfeff66846d3a0c9cfa796 - optee/optee_os/core/arch/arm/plat-k3/drivers/sa2ul_rng.c 167f0568d280c4eaa824b31126105d0f2a0d3f89 - optee/optee_os/core/arch/arm/plat-k3/drivers/ti_sci_protocol.h 96e780127fe944086f4e057b31baea9b2fa125e2 - optee/optee_os/core/arch/arm/plat-k3/drivers/sec_proxy.h 31bc4f9734a7ba434af482766846ba6cfc120a82 - optee/optee_os/core/arch/arm/plat-k3/drivers/sa2ul.c 7e9288bc18f6a5ae30fd66d3f04abd5a43971250 - optee/optee_os/core/arch/arm/plat-k3/drivers/ti_sci.h 2020136e5c1ef325c92bc319ebb5f582d8d1b447 - optee/optee_os/core/arch/arm/plat-k3/drivers/sa2ul.h 259f0d13481825cf2b56b06524f54b93aaf8abeb - optee/optee_os/core/arch/arm/plat-k3/drivers/sec_proxy.c 08166357e31dfc2ba303f00ae83b8bb6cfb13c3f - optee/optee_os/core/arch/arm/plat-k3/drivers/ti_sci.c 4210a13d7617d8becb16ca879152a64ba12e99a5 - optee/optee_os/core/arch/arm/dts/sama5d2.dtsi abbe0e5a7c63995c207b1995649e3a6ed6b4221a - optee/optee_os/core/arch/arm/dts/stm32mp15xc.dtsi d6dbda8b14af74b3a63db810c4c4ed53bfb097bc - optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcom-som.dtsi 80e5d5425cd21aaac73665beba3aa827a985f10e - optee/optee_os/core/arch/arm/dts/stm32mp13-pinctrl.dtsi d23af59b64d5380f6f9c8ca37a1a5b1af3e9f93c - optee/optee_os/core/arch/arm/dts/at91-sama5d27_som1_ek.dts 41aa3da18dcb49b316aefc9ad5eed7dc2664dabc - optee/optee_os/core/arch/arm/dts/stm32mp157c-ev1.dts 23b592b2e03dead1636f2110cd64531ec92bf807 - optee/optee_os/core/arch/arm/dts/stm32mp133.dtsi 6785fab64335569d7bd355648ab3eea10428ba95 - optee/optee_os/core/arch/arm/dts/stm32mp135f-dk.dts 6ed7397e2751cabb21fc7e87b53983b9117d2e26 - optee/optee_os/core/arch/arm/dts/sama5d2-pinfunc.h ff54b38797ff11d07b4812b54de0c54381e5c944 - optee/optee_os/core/arch/arm/dts/stm32mp255.dtsi ed24a9b0089183c2059975547510395e1e35c43f - optee/optee_os/core/arch/arm/dts/stm32mp257f-ev1-ca35tdcid-rif.dtsi 361479ac7684841706aca2fdb4c3d2c9f8e0e13e - optee/optee_os/core/arch/arm/dts/stm32mp15xxac-pinctrl.dtsi 409d4ed71faffbe877746442e5f91e568dc7df1e - optee/optee_os/core/arch/arm/dts/stm32mp25xxai-pinctrl.dtsi c801e4c35f00786835f0cd63b71559a146086866 - optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcor-io1v8.dtsi ed30a800e2e2a388fbecc51158b47a9cc3921038 - optee/optee_os/core/arch/arm/dts/stm32mp157c-dk2.dts d631d38e887afb5747ac43a31fbfa52feff971c1 - optee/optee_os/core/arch/arm/dts/fsl-lx2160a.dtsi 731b9a6acef7c38b916dc026ccdb6d9fab7a7528 - optee/optee_os/core/arch/arm/dts/stm32mp25-pinctrl.dtsi db15a31ad3135aacca1c525a09c102593c0f1bfb - optee/optee_os/core/arch/arm/dts/stm32mp157a-dk1-scmi.dts 6c18e9690a909c9b4898d1d609cdf3874e22d19a - optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcor-avenger96.dtsi d26bbcf985b7523a6af715be4feb22233be74ba5 - optee/optee_os/core/arch/arm/dts/stm32mp15xxaa-pinctrl.dtsi fb4be0e25bdca79fcf443034897f81e669e42d88 - optee/optee_os/core/arch/arm/dts/fsl-lx2160a-qds.dts 642045067c7bfc99b19f317cb3af060f111d3f58 - optee/optee_os/core/arch/arm/dts/stm32mp131.dtsi 0c1276612681bf9f22517513242e678c22551542 - optee/optee_os/core/arch/arm/dts/stm32mp153.dtsi 8b0ff69354da1ce17daa0d18c67f38fdd3bcdd7c - optee/optee_os/core/arch/arm/dts/stm32mp135.dtsi fad0980d9bf80c0fc0a8dc20548c3d6d65a9c4ee - optee/optee_os/core/arch/arm/dts/stm32mp257.dtsi 414473317258a6e6a9fe63c8f9b0125faf78845b - optee/optee_os/core/arch/arm/dts/stm32mp253.dtsi d8011a03e68d20864da688cd4e37f5f00fceb92c - optee/optee_os/core/arch/arm/dts/stm32mp15xx-dkx.dtsi cc1a5787a5c707145c1d43a2dafde4081469219f - optee/optee_os/core/arch/arm/dts/stm32mp15-pinctrl.dtsi e793accc60529af1c41651063de57ef9cd0a0b5e - optee/optee_os/core/arch/arm/dts/stm32mp157a-dhcor-avenger96.dts af297633ee1dd3ddc9a4e06782e0390214b9c3dd - optee/optee_os/core/arch/arm/dts/stm32mp251.dtsi c07147cb14bc871e069f3be8248fc2c79e311949 - optee/optee_os/core/arch/arm/dts/stm32mp15xxad-pinctrl.dtsi 6f054373484e9a7e6b398ac064c824e838b666e0 - optee/optee_os/core/arch/arm/dts/at91-sama7g54_ek.dts 1985ea8670dc7c7937541f6b2da9c30c41ee000d - optee/optee_os/core/arch/arm/dts/at91-sama5d27_wlsom1.dtsi 62934ca38185da79af035ba4a82f62ae3a33f4ac - optee/optee_os/core/arch/arm/dts/hikey.dts e4fa73abdd45e453c0b16f0617ff2e73f505c20d - optee/optee_os/core/arch/arm/dts/stm32mp25xc.dtsi 9d307000551e74012b0ab3eecedcce5e21315f12 - optee/optee_os/core/arch/arm/dts/stm32mp25xxal-pinctrl.dtsi 28f113e9a075bf7903cddddaacfda1cbe77f6947 - optee/optee_os/core/arch/arm/dts/stm32mp151.dtsi ce82c06ac99261e680a62585d80c90e9dfe941fb - optee/optee_os/core/arch/arm/dts/stm32mp157c-dhcom-pdk2.dts 9d307000551e74012b0ab3eecedcce5e21315f12 - optee/optee_os/core/arch/arm/dts/stm32mp25xxak-pinctrl.dtsi ad3b5f3ede872c44e014eb6ca5a69329195968a6 - optee/optee_os/core/arch/arm/dts/at91-sama5d27_wlsom1_ek.dts 676f90d7c25eb035af4475d83d6e355f07ac0634 - optee/optee_os/core/arch/arm/dts/embedded_dtb_test.dts d7230a1568081b9a39b151bbe38f188691b2b84b - optee/optee_os/core/arch/arm/dts/fsl-lx2160a-rdb.dts b90fd277b20c2235559780745427fce254204eb5 - optee/optee_os/core/arch/arm/dts/sama7g5-pinfunc.h e4c09d7943a625db6187d1b74f0990a9918b7663 - optee/optee_os/core/arch/arm/dts/dt_driver_test.dtsi c8ec256ae55cb6c849aa51624b9974259884b159 - optee/optee_os/core/arch/arm/dts/at91-sama5d2_xplained.dts e4fa73abdd45e453c0b16f0617ff2e73f505c20d - optee/optee_os/core/arch/arm/dts/stm32mp25xf.dtsi 0740af056d7271572901b9dc8ed2822af6546c20 - optee/optee_os/core/arch/arm/dts/stm32mp13xc.dtsi 8275c3486f497663a76c22d5ef4895c0c6ef6721 - optee/optee_os/core/arch/arm/dts/stm32mp157c-ed1-scmi.dts 9dea507c72c9eec09336578711a432b198478a56 - optee/optee_os/core/arch/arm/dts/at91-sama5d27_som1.dtsi e4418357621a953d3e4b62676dcd52da1e958777 - optee/optee_os/core/arch/arm/dts/stm32mp157a-dk1.dts 0740af056d7271572901b9dc8ed2822af6546c20 - optee/optee_os/core/arch/arm/dts/stm32mp13xf.dtsi ce5455a1f2afa724bbdec2b0c14f79a6bed0b1e4 - optee/optee_os/core/arch/arm/dts/stm32mp257f-ev1.dts bceeab3e2319f80b613c6ccaefc42154a2d76148 - optee/optee_os/core/arch/arm/dts/stm32mp157c-ev1-scmi.dts 1b30098b442b7f3ded006ca7b7e80e963cc9fc6f - optee/optee_os/core/arch/arm/dts/stm32mp157c-dk2-scmi.dts 9f93f18baccbb7718af6c571e70dfecb3529b694 - optee/optee_os/core/arch/arm/dts/stm32mp15xxab-pinctrl.dtsi b318d72ed3eee6e4bd7d8ecdb5b1eba8dfc31f89 - optee/optee_os/core/arch/arm/dts/stm32mp157.dtsi 5af1e6fee13bee69410732af10981f063661c519 - optee/optee_os/core/arch/arm/dts/stm32mp157c-ed1.dts 0cc38427ae1b225d88d000f9438b7cc34e883b30 - optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcom-pdk2.dtsi 6cec48599b2381a43a302f390c48d557ba064697 - optee/optee_os/core/arch/arm/dts/sama7g5.dtsi 0f41a6ee8e489bec0d79a976edb540945506d498 - optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcor-som.dtsi 9c453b2fc11aaa02877de7f09472e5d5fd74cbea - optee/optee_os/core/arch/arm/mm/mobj_ffa.c 864e848f1defa3de1e5572ca3d95b4e44792d0f8 - optee/optee_os/core/arch/arm/mm/core_mmu.c 0800ed2cdb60a7e006e239b48c9a13db03283eb9 - optee/optee_os/core/arch/arm/mm/mobj_dyn_shm.c feeeaeae7f26fdd8673fba9c1c90c5997766aad6 - optee/optee_os/core/arch/arm/mm/core_mmu_lpae.c 57677b0d6e625b07083889d81e304b9c700c5c13 - optee/optee_os/core/arch/arm/mm/tee_pager.c e6f86e9d7f1972ae55f5ca9938620da5246c59b8 - optee/optee_os/core/arch/arm/mm/sp_mem.c 48384d9c72c1c7a6dd5c2b5395d330221188e699 - optee/optee_os/core/arch/arm/mm/core_mmu_v7.c ac0abfb473091ac6c14804be7ef4894e137990ee - optee/optee_os/core/arch/arm/plat-mediatek/platform_config.h 4af0e09221ce2161556eec932ee5c97df9943156 - optee/optee_os/core/arch/arm/plat-mediatek/main.c e1fca0dd2d7d34c4bab110dfb24010cbd1538b8d - optee/optee_os/core/arch/arm/tee/entry_fast.c df18a9464597e6dbc2844ec1e5d735db00c74f37 - optee/optee_os/core/arch/arm/tee/svc_cache.c 176317554a2541fa4a9d6504dbe52227bdcb5083 - optee/optee_os/core/arch/arm/tee/cache.c 6631e40f0ad62f389ac0fc0c59e142b9313bb246 - optee/optee_os/core/arch/arm/plat-aspeed/core_pos_a32.S c2a044439dfe43a71ae10d3b6dac3011aa488674 - optee/optee_os/core/arch/arm/plat-aspeed/platform_ast2600.c 70fb1d819f629339d313a83ea0f8efa6e4fa80ca - optee/optee_os/core/arch/arm/plat-aspeed/platform_ast2700.c b8d3a5d517e206505803d023df167bb48a6eacb5 - optee/optee_os/core/arch/arm/plat-aspeed/platform_config.h 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 194b1c2efb4a1b60d27d88813f6317cca0a978ce - optee/optee_os/core/arch/arm/plat-tegra/platform_config.h d448b3370e0f8e7cbe52eefd2d149899a6ab0860 - optee/optee_os/core/arch/arm/plat-tegra/main.c 390b45a60cc4219e64e58f0ca0ea2890dc31a351 - optee/optee_os/core/arch/arm/plat-vexpress/vendor_props.c 178685f16c79b3f0dd48d1b8fb551d428ab67b68 - optee/optee_os/core/arch/arm/plat-vexpress/juno_core_pos_a32.S cbbb4b7ba94d66daba35e4e8de0e1ea8f3975534 - optee/optee_os/core/arch/arm/plat-vexpress/juno_core_pos_a64.S 00d480f375e00da8a39d12face3416dc339d7205 - optee/optee_os/core/arch/arm/plat-vexpress/platform_config.h baaed900d9ea88c65994dfc76dbe982ffbbfb5ad - optee/optee_os/core/arch/arm/plat-vexpress/main.c c043a9411306559a982b5d09ae419821ff026bd0 - optee/optee_os/core/arch/arm/plat-uniphier/kern.ld.S 11ce785f6bdd56fdc8b32c6c2174a9b49b96b230 - optee/optee_os/core/arch/arm/plat-uniphier/platform_config.h 2c699c471ccb146cc88b3899204cbdd9d4fd82d6 - optee/optee_os/core/arch/arm/plat-uniphier/main.c 1cea08afcf4cab7bbff31ea3666c5360c4c03498 - optee/optee_os/core/arch/arm/include/arm32_macros_cortex_a9.S 236e177873dbb765f512f6690ca9df800109edb4 - optee/optee_os/core/arch/arm/include/arm64.h c24a0141912421b79a8ecb62ec4ee5d10c8f5d11 - optee/optee_os/core/arch/arm/include/arm32.h 55298b41d3e8800e2aeebd746e9e1371142fbd6e - optee/optee_os/core/arch/arm/include/smccc.h 12dc0bca72b62cb9e340cb631b2cbab3bf9b26fc - optee/optee_os/core/arch/arm/include/arm64_macros.S ff294f026e09453cbd1ffb3cbc764befc573676c - optee/optee_os/core/arch/arm/include/arm32_macros.S 33a023b2aefc347327909bc18584a5a7f7c96d5f - optee/optee_os/core/arch/arm/include/arm.h 6f4f3bf783228669c7e3f15094154e9affc48745 - optee/optee_os/core/arch/arm/include/optee_ffa.h ef7bffd960c06d3d1f3248123500188bfb08cd13 - optee/optee_os/core/arch/arm/include/pta_stmm.h 4a7c4dda42996356c37cb094d4908f62d0ab1bd4 - optee/optee_os/core/arch/arm/include/ffa.h 33da86787f5ed31b247e1b8f9b33f6e4346fe53f - optee/optee_os/core/arch/arm/include/mm/generic_ram_layout.h 79775424a3d2afb3c555a91a210974e20db667ca - optee/optee_os/core/arch/arm/include/mm/core_mmu_arch.h 36508e4fbdf66e9683c7425ff68edf20b89d4243 - optee/optee_os/core/arch/arm/include/tee/entry_fast.h 4771b6a98c18654bdf73d522fbadb6ba28acb94f - optee/optee_os/core/arch/arm/include/sm/teesmc_opteed.h b99db7102beabc3103377efbcd2cb4f144d615f6 - optee/optee_os/core/arch/arm/include/sm/watchdog_smc.h 913aa87cc293d3fcebd5bb787ee5da1e8af74be2 - optee/optee_os/core/arch/arm/include/sm/std_smc.h f98998e892ec280bcd9da125164c5462995da079 - optee/optee_os/core/arch/arm/include/sm/teesmc_opteed_macros.h d135a39b3545929f32e6c75c5c6ee45eb44e5a30 - optee/optee_os/core/arch/arm/include/sm/optee_smc.h c3cff2cbe62224e1869a92e1b246525bab44944c - optee/optee_os/core/arch/arm/include/sm/pm.h 28cac67ced3db8dcaccca1fe953dde17f3401ba9 - optee/optee_os/core/arch/arm/include/sm/psci.h eb652901568dbd1107a5a134f53d5741b458f453 - optee/optee_os/core/arch/arm/include/sm/sm.h 52885058120498a8199e4cb48f05ed7a3e6ed510 - optee/optee_os/core/arch/arm/include/kernel/thread_private_arch.h b3b756fb7bc39e3f2db4127b0ae7461715f6b08b - optee/optee_os/core/arch/arm/include/kernel/spmc_sp_handler.h daca510172fc09d7f8395b9e4700f1e76edd9629 - optee/optee_os/core/arch/arm/include/kernel/thread_spmc.h 34937789ac227f638211cfec7cb102dcffe2e120 - optee/optee_os/core/arch/arm/include/kernel/tz_ssvce_def.h 2360143179a1f2cfd4a3cbbbc03448bb6790d698 - optee/optee_os/core/arch/arm/include/kernel/arch_scall.h b95d779051d2b0e70152491dc1046ef721584d7a - optee/optee_os/core/arch/arm/include/kernel/stmm_sp.h 2cb8761a88828b0812171b4a8fb7fc6338baa169 - optee/optee_os/core/arch/arm/include/kernel/misc_arch.h 59802332e69d96bb3641667a395d02f3c2fcd82f - optee/optee_os/core/arch/arm/include/kernel/cache_helpers_arch.h 621b56388a4696754f95b4599e1822d9a34a412c - optee/optee_os/core/arch/arm/include/kernel/vfp.h bcf79acc39a9f4ce8fdd50e3929bba0bceaf33aa - optee/optee_os/core/arch/arm/include/kernel/user_access_arch.h 9723fb1cc272c7203c2e914cc6186ae2098e80bf - optee/optee_os/core/arch/arm/include/kernel/tee_l2cc_mutex.h 524a5a3c2a8e9d1c2d5a74c054a5465f28328abf - optee/optee_os/core/arch/arm/include/kernel/tz_proc_def.h 787920f87e2f8f5b90ab5a7dbb652cdcac005aa8 - optee/optee_os/core/arch/arm/include/kernel/tlb_helpers.h bd02afc86bd0e2a2d5b96382da5b08872e3704b3 - optee/optee_os/core/arch/arm/include/kernel/delay_arch.h ccc12fd93eb51399e2102d7549c3460ce011b98e - optee/optee_os/core/arch/arm/include/kernel/tz_ssvce_pl310.h 88697bcdf5234c2ad97597d4455f819c4c13797e - optee/optee_os/core/arch/arm/include/kernel/secure_partition.h c36bfdcd6ad5e85e7f084678b7dc5595db7639ae - optee/optee_os/core/arch/arm/include/kernel/thread_arch.h 9397b11c32fdff7d6f2fb9203459b016a3dc0861 - optee/optee_os/core/arch/arm/include/crypto/ghash-ce-core.h c020f068ad8593457e743ff0430d6a3cd685e142 - optee/optee_os/core/arch/arm/include/scmi/scmi_server.h 6c637d1038773281e56bbbd0e1381510508531cd - optee/optee_os/core/arch/arm/plat-synquacer/rng_pta.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 63b965066fdfe0c218542a9cc90635f1177300d8 - optee/optee_os/core/arch/arm/plat-synquacer/main.c dd54ce3d620f2b22180ef201aeecf74b5b4480ad - optee/optee_os/core/arch/arm/plat-rzg/platform_config.h 8c4023604f9a8209cc2f3fbc55da146ee176f62e - optee/optee_os/core/arch/arm/plat-rzg/main.c 435d5321e6d484c095ede7a5b320ec92fddb3025 - optee/optee_os/core/arch/arm/plat-bcm/bcm_elog.c 3d4f18ba7a9634be9a46f900264cb0132fd65654 - optee/optee_os/core/arch/arm/plat-bcm/bcm_elog.h db3ddcb5c48ff30c64e8b561ed5300400d67bca1 - optee/optee_os/core/arch/arm/plat-bcm/crc32.c 92cb86eafac038fc02be252efc14c3e3316f27af - optee/optee_os/core/arch/arm/plat-bcm/crc32.h 0b99d0c7135e7f0002ef7a51d63461307e66203b - optee/optee_os/core/arch/arm/plat-bcm/platform_config.h 43a45ac90d01fd0045318dc972f78f0bf1b526ba - optee/optee_os/core/arch/arm/plat-bcm/main.c d15ae1ce071edbfc8d4d4de7c944cb1d8712136e - optee/optee_os/core/arch/arm/sm/sm.c 0fbfd45981f9512d688a49c32add4297540c689e - optee/optee_os/core/arch/arm/sm/pm_a32.S bbd1df35108340d6d4e6179926681fb794f8ce12 - optee/optee_os/core/arch/arm/sm/sm_private.h 9421c26b6ce38f1d5da0e2f431afc0cab732f0e6 - optee/optee_os/core/arch/arm/sm/std_smc.c 79b02c9017b471e73d8c11acc7f91278ec851f2b - optee/optee_os/core/arch/arm/sm/pm.c 615d9401894c37dec5e5ebe9bcdb678df854564e - optee/optee_os/core/arch/arm/sm/psci-helper.S 45960371e7a1224c4d067ff3c172952b7d616998 - optee/optee_os/core/arch/arm/sm/sm_a32.S 8a9cd4bad5748dac76110944be1fb3442e98b2f6 - optee/optee_os/core/arch/arm/sm/psci.c e2b43db2de0208697b4c88f2f0562d58a4b0b2fb - optee/optee_os/core/arch/arm/plat-d02/platform_config.h 64f5feb8d512291b20a4f975aaf809383b8501f9 - optee/optee_os/core/arch/arm/plat-d02/main.c 2a0bf39e0ef3f1dfa764058f0142b54a53a92006 - optee/optee_os/core/arch/arm/plat-ti/api_monitor_index_a9.h ec14532de7ea2afbf4bb14220372faf052e0d77c - optee/optee_os/core/arch/arm/plat-ti/sm_platform_handler_a9.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 188877287aafc257998231f234a1a79a4886c0af - optee/optee_os/core/arch/arm/plat-ti/a9_plat_init.S f185f9e1ea859d9f4233cffc8c78fcbe72e4c090 - optee/optee_os/core/arch/arm/plat-ti/platform_config.h 9925b7637fef70a5a09336acc3facf8f32a968cc - optee/optee_os/core/arch/arm/plat-ti/main.c 608a97cee50965f940169862e6754dd17612fadf - optee/optee_os/core/arch/arm/plat-ti/api_monitor_index_a15.h 8fa033ec5237e06aef907c0f641f208388793c26 - optee/optee_os/core/arch/arm/plat-poplar/hi3798cv200.h d4139567b62848e1c43b6759cd767e034e10db73 - optee/optee_os/core/arch/arm/plat-poplar/platform_config.h 65c024516806f7b43dd1ecc361e617bb25fa8a7a - optee/optee_os/core/arch/arm/plat-poplar/main.c da5b397448c96664ff0d89282edbecf39150b736 - optee/optee_os/core/arch/arm/kernel/generic_timer.c 8ebc782c56e8a49cbb1a1842f396de645f1f46a7 - optee/optee_os/core/arch/arm/kernel/cache_helpers_a32.S 96a20985eac7f15b591f72bdd3a413deab7bed66 - optee/optee_os/core/arch/arm/kernel/thread_spmc.c 6fd7aa6291ba867b69684437a7dd5bb5a7bf35f0 - optee/optee_os/core/arch/arm/kernel/tee_time_arm_cntpct.c cfe9209c0f08602f20df8752df4016c257305627 - optee/optee_os/core/arch/arm/kernel/vfp.c 170f9fade8d4cfd3805f2aa2383b7f3d358507df - optee/optee_os/core/arch/arm/kernel/idle.c 0dafbe192d55bfc13650b4d9b06857d1b515e38d - optee/optee_os/core/arch/arm/kernel/cache_helpers_a64.S 99dbd4c6ced9d21fbf6db2c3e7c6755d8c6bce28 - optee/optee_os/core/arch/arm/kernel/vfp_a32.S 07324ee362ff4d159fdf6bce6b0b02e8e78b88c4 - optee/optee_os/core/arch/arm/kernel/arch_scall.c a3d562edc0d696f64d77e9c96d86c9a88451b5a1 - optee/optee_os/core/arch/arm/kernel/vfp_private.h 5e41ac280fa605fa56477c6e9667c7421ae832c1 - optee/optee_os/core/arch/arm/kernel/thread_optee_smc_a64.S d347c9bafe24140b9717de8891d9659b01333e07 - optee/optee_os/core/arch/arm/kernel/arch_scall_a32.S 4ee8f8d86109824375f2cc97d335f68da3fdaa62 - optee/optee_os/core/arch/arm/kernel/tlb_helpers_a64.S c591321644c6fd32d600a9a797daf4cdc48647d2 - optee/optee_os/core/arch/arm/kernel/spin_lock_a64.S fd41f03a86b219928984dc3153a10bd5702fcca3 - optee/optee_os/core/arch/arm/kernel/spmc_sp_handler.c a0adb6240ef123f1b7a7d5c06d1f43bbe84ab420 - optee/optee_os/core/arch/arm/kernel/stmm_sp.c b4d64fa787d883488032c460e9bdd9219c8b7e6b - optee/optee_os/core/arch/arm/kernel/link_dummy.ld ab6654f9a53a145c7e2bc78923bed0bc0657bfe3 - optee/optee_os/core/arch/arm/kernel/thread_a64.S d5860b562cc073c556bae2a7af9a7e1eb58a120f - optee/optee_os/core/arch/arm/kernel/thread_optee_smc_a32.S f5f53c7818eac3cb9a438d50e42b970aa59256a0 - optee/optee_os/core/arch/arm/kernel/virtualization.c 3bc11c7750b18f421431d5d75da90d8db8f968e8 - optee/optee_os/core/arch/arm/kernel/entry_a64.S af8d99e369132adac450a89f4b07fbbada85156d - optee/optee_os/core/arch/arm/kernel/misc_a64.S 4100714c5da0ab3a043f026f768aa0f42963f0f7 - optee/optee_os/core/arch/arm/kernel/link_dummies_paged.c dee3ef20e88a64d3e5c6a703b7e499cf302b0d3e - optee/optee_os/core/arch/arm/kernel/abort.c 7926173ef40ab1dffbd3b48ff3aa6da3fc04408c - optee/optee_os/core/arch/arm/kernel/asm-defines.c 24e1db339b48a73b6aaafcfca9047c7855896faf - optee/optee_os/core/arch/arm/kernel/rpc_io_i2c.c da59d8db4ac8cd365ffd09d040ddc2a6ecab1d06 - optee/optee_os/core/arch/arm/kernel/thread_optee_smc.c cff200d2106d26baf930f16e6caa8634adebbe08 - optee/optee_os/core/arch/arm/kernel/vfp_a64.S 8430d6b00cd4f9685acc4a7635286460c6c6656b - optee/optee_os/core/arch/arm/kernel/entry_a32.S f41ca1e85c2faac131a78224385cef504fa5fb20 - optee/optee_os/core/arch/arm/kernel/tlb_helpers_a32.S 5ccfc6d56a72745aa30a58576530f6a552424dd9 - optee/optee_os/core/arch/arm/kernel/secure_partition.c 44470d3e7b9cdbed041ae13408e647edc645aa74 - optee/optee_os/core/arch/arm/kernel/misc_a32.S 8e7f44c940c10653f99ce491cc9ee014042dd270 - optee/optee_os/core/arch/arm/kernel/tz_ssvce_pl310_a32.S 4eb9e4b6f2b6b8f595acf22a683d831fee0ef40f - optee/optee_os/core/arch/arm/kernel/unwind_private.h b5ebdeae94cfe7fd7a32f0be15e8a28b230cd175 - optee/optee_os/core/arch/arm/kernel/tee_l2cc_mutex.c db8f47350612f3b8a6329c86401fdd3f68deea35 - optee/optee_os/core/arch/arm/kernel/timer_a64.c 9447a2f925a8c4a712433747c0b99e00733645d3 - optee/optee_os/core/arch/arm/kernel/semihosting_a64.S 63ea63ab5d506208970d6f5b8738ee82850aefe3 - optee/optee_os/core/arch/arm/kernel/unwind_arm32.c 9d0bd8480809254b743bf3d766efe7c3cdc70034 - optee/optee_os/core/arch/arm/kernel/kern.ld.S af2646c2f7bed754eace205139dfe421ab8bd3a5 - optee/optee_os/core/arch/arm/kernel/thread_a32.S 288600f47bcdb1589b53bf9f9679cd62fc048b35 - optee/optee_os/core/arch/arm/kernel/thread.c 599bd7fb683e3e1c0eddc71e66e5eb979e8e7c28 - optee/optee_os/core/arch/arm/kernel/spin_lock_a32.S 9e422c03938a8b32edd015a653d5dac29880a5e2 - optee/optee_os/core/arch/arm/kernel/unwind_arm64.c d6c09e6c39b889a25fcb82340f1725f9d0427d59 - optee/optee_os/core/arch/arm/kernel/arch_scall_a64.S 429869efe81ea182c117279b62d84611f6c67d9e - optee/optee_os/core/arch/arm/kernel/thread_spmc_a64.S 4d984b5505df1222904d25ec03a4521297c86119 - optee/optee_os/core/arch/arm/kernel/boot.c 85841b19544e59c0896f7c344b4695e129135d4e - optee/optee_os/core/arch/arm/kernel/link_dummies_init.c 43dcd40dee8c1bca63526b7590768c430e2b9eb4 - optee/optee_os/core/arch/arm/plat-corstone1000/platform_config.h a2bbb6d8467a57da3e214024d754db8c39773688 - optee/optee_os/core/arch/arm/plat-corstone1000/main.c eba718605aa45932a4b80632aa65d8cb35dc2b22 - optee/optee_os/core/arch/arm/plat-versal/platform_config.h bfcf05746b3abe951fa87eae66701a8f965aa611 - optee/optee_os/core/arch/arm/plat-versal/main.c 095caecf26786efe69779aab593c67447f44b9c2 - optee/optee_os/core/arch/arm/plat-ls/plat_init.S f413d0ba2e04b6ef2802475a9132687b2f19237a - optee/optee_os/core/arch/arm/plat-ls/platform_config.h 13868e401113be9ac3e66fcf65079f44ea2bacc5 - optee/optee_os/core/arch/arm/plat-ls/main.c 94a132cb905aa39756cd3bd0c4cd0bb955893219 - optee/optee_os/core/arch/arm/plat-amlogic/platform_config.h c361b974a831b2e73783b393d9d3893180fcd1af - optee/optee_os/core/arch/arm/plat-amlogic/main.c b1793c2149008cfc5c242a3fbbfcdfecfb082b4b - optee/optee_os/core/arch/arm/plat-amlogic/scripts/aml_bin2img.py 2399244b8020942c1b3a3cb924194e8770560051 - optee/optee_os/core/arch/arm/plat-sunxi/plat_init.S eaa619f9de58ee047ca541b4c238b2afb5b83b6a - optee/optee_os/core/arch/arm/plat-sunxi/psci.c 4e93d8d25766b05b285896a4944c227f8b4da442 - optee/optee_os/core/arch/arm/plat-sunxi/platform_config.h e88f1ed007545a2d9bad93b2b4339ad8b3495d1c - optee/optee_os/core/arch/arm/plat-sunxi/main.c bf4be1dd46e6278e5b9b8b6a40b710d90007d915 - optee/optee_os/core/arch/arm/plat-hisilicon/hi3519av100_plat_init.S 92415c6775326559b08df1d2a9976b3e1ebb0a72 - optee/optee_os/core/arch/arm/plat-hisilicon/psci.c 012cc9cc5cd4d1213266d657558cd6c1fb998e1f - optee/optee_os/core/arch/arm/plat-hisilicon/platform_config.h 1e0932868e4fc72946b4b12a3650c383dcdd7a79 - optee/optee_os/core/arch/arm/plat-hisilicon/hi3519av100.h a8c72f869ba4905a042677386935fe5f89594db8 - optee/optee_os/core/arch/arm/plat-hisilicon/main.c 2d7ce0ada1137b16132294b438cf80dc592fc2d2 - optee/optee_os/core/arch/arm/plat-stm32mp2/stm32mp_pm.c 409ab7028ed4877a9e66ce00a6aa0f1f0facd611 - optee/optee_os/core/arch/arm/plat-stm32mp2/stm32_util.h 1dbd06a7324f258effac9a8ef4ac5baf9c426440 - optee/optee_os/core/arch/arm/plat-stm32mp2/platform_config.h 46b98d93bcfa1a298f80c25b710f13f434f751e8 - optee/optee_os/core/arch/arm/plat-stm32mp2/stm32mp_pm.h 0597459671a071898baca88cd6fd4c7319cb6e7f - optee/optee_os/core/arch/arm/plat-stm32mp2/main.c 6bad30092b6947c38cd0dcc571b822356d63152e - optee/optee_os/core/arch/arm/plat-zynqmp/platform_config.h 00aa4ae9cc5e6bc0ee8dc057986548b31545f5ed - optee/optee_os/core/arch/arm/plat-zynqmp/main.c 0fce490355fabf44c68c3e70a54be1e01f9c097a - optee/optee_os/core/arch/arm/plat-marvell/platform_config.h af9cccac94bc9f4624a345c140c5b6e92cc1cbf6 - 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 9f34e39f67ff62c0eb53b7758b4bb2acdc47c228 - optee/optee_os/core/arch/arm/plat-marvell/cn10k/core_pos.S 9899b78e83cfa336552e36d0be06113de438bf15 - optee/optee_os/core/arch/arm/plat-hikey/hikey_peripherals.h 4957879ea142b46fd1ace368df87de82c90f5e5f - optee/optee_os/core/arch/arm/plat-hikey/spi_test.c 11fa51fa797eb2a0ed5a79b96c4c48ab77451fc9 - optee/optee_os/core/arch/arm/plat-hikey/platform_config.h a3ca539721787ac30ecbe03305f389325b894ff1 - optee/optee_os/core/arch/arm/plat-hikey/main.c f59a39b271b322f5bdd6baebdedb3ef701a78b02 - optee/optee_os/core/arch/arm/crypto/sha3_armv8a_ce_a64.S 9c1f14fdc223c00af03fe8b922a520419b7fd0b9 - optee/optee_os/core/arch/arm/crypto/sha1_armv8a_ce.c afc997b206bbdc6c60cd9f08308b7b53832eac0b - optee/optee_os/core/arch/arm/crypto/aes_modes_armv8a_ce_a64.S d857b4b442486f2ac052ee687cb6d6f424843433 - optee/optee_os/core/arch/arm/crypto/sha512_armv8a_ce.c fb5f716381766749999f0032bf39f39bf88af12e - optee/optee_os/core/arch/arm/crypto/aes_modes_armv8a_ce_a32.S cb5a3413393627c5fb4626c2315e2e12bf01abf1 - optee/optee_os/core/arch/arm/crypto/ghash-ce-core_a32.S 02305ae36a17490cecdc906c0970e8625ea9e6a1 - optee/optee_os/core/arch/arm/crypto/sm4_armv8a_neon.c 45797af469d803907920fecce84f86fbe684a40c - optee/optee_os/core/arch/arm/crypto/sha3_armv8a_ce.c 1ab432ea10e0e0edf03b0ce17bb5277fea163578 - optee/optee_os/core/arch/arm/crypto/sha256_armv8a_ce.c 6e006d07e0e25f49c5af73e0e522f6f97963275c - optee/optee_os/core/arch/arm/crypto/sm4_armv8a_aese_a64.S 933f5b3256795b2ffea6b7b93d75365f865599b3 - optee/optee_os/core/arch/arm/crypto/sha1_armv8a_ce_a32.S 182b52f83f99ae6bbfa5098b2a3b2018194acde0 - optee/optee_os/core/arch/arm/crypto/ghash-ce-core_a64.S 2da4cbb016071dacfbbd7c99799a27ad6d8c56a7 - optee/optee_os/core/arch/arm/crypto/sha512_armv8a_ce_a64.S 0b84c15b4796a2a23a095ae2d6d037677510760a - optee/optee_os/core/arch/arm/crypto/sha256_armv8a_ce_a64.S bb50a2e7fffd5945ce8214bf57ad9d55135b46c0 - optee/optee_os/core/arch/arm/crypto/sm3_armv8a_ce.c 2c3ba8b73e012b48da6c8ff12c635f8fa109e5a8 - optee/optee_os/core/arch/arm/crypto/aes_armv8a_ce.c 47012ceb6af70d59a7666ca551814aa811efe9e8 - optee/optee_os/core/arch/arm/crypto/sm4_armv8a_ce.h ad9a80c4d43acd03ae5d27e14df6dfee3abc4e05 - optee/optee_os/core/arch/arm/crypto/sha256_armv8a_ce_a32.S 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 cf714bfd8657a2fff8112b3b94d7e476d51e2e60 - optee/optee_os/core/arch/arm/crypto/sm4_armv8a_ce_a64.S 56e9da14883d74e8eca3a4c7737185590cf14c08 - optee/optee_os/core/arch/arm/crypto/sha1_armv8a_ce_a64.S 0c1913711dd52b93cfe5d2d476a3a050a5bae97d - optee/optee_os/core/arch/arm/crypto/aes-gcm-ce.c 09cb511f6b571c162ae284911b5af9c702dd5130 - optee/optee_os/core/arch/arm/crypto/aes_armv8a_ce.h 0cd13267dd6db52ed1ff3742dcb7adb15bdff8cd - optee/optee_os/core/arch/arm/crypto/sm4_armv8a_ce.c 55fee8bf238c661a2f59118cbea5d8fca29471f3 - optee/optee_os/core/arch/arm/plat-zynq7k/plat_init.S e8a97315a58b289054e1f3fb5418cba746b5633e - optee/optee_os/core/arch/arm/plat-zynq7k/platform_smc.h 8694a8f4be2551b1bf8f1abcb17284a8b202e5af - optee/optee_os/core/arch/arm/plat-zynq7k/platform_config.h 8ec4ce70677e98cc80e5c401bf9640ec0fee3b83 - optee/optee_os/core/arch/arm/plat-zynq7k/main.c fd20baae7413cd701b88ba6dfeb2a294a9eeb452 - optee/optee_os/core/arch/arm/plat-stm/rng_support.c bdd38a0220aac82b0aafa97e8f1993cb27e0ac1f - optee/optee_os/core/arch/arm/plat-stm/tz_a9init.S 784a5cea3b2741f04facdeaf7bfac0e093630875 - optee/optee_os/core/arch/arm/plat-stm/platform_config.h 445f45675057a9e6f1aaab83895215595ae65915 - optee/optee_os/core/arch/arm/plat-stm/main.c 1b82881f2b80531fc7743309c38c8e9370969ef1 - optee/optee_os/core/arch/arm/plat-rzn1/rzn1_tz.h 776215d1f8598a5514e759d70ae400a8101f835a - optee/optee_os/core/arch/arm/plat-rzn1/a7_plat_init.S 48ef8147e12f826d7e87c67d7c12e3932d317546 - optee/optee_os/core/arch/arm/plat-rzn1/sm_platform_handler.c 245d63c49ace44a4319be3f8b9882e520bf67448 - optee/optee_os/core/arch/arm/plat-rzn1/psci.c 2ecc2eb6bff695c5b86aba9d1b07e0edcef5ab75 - optee/optee_os/core/arch/arm/plat-rzn1/platform_config.h c9a02f7b7f7b87ffbcb1b4817f13f0a9ce102e7a - optee/optee_os/core/arch/arm/plat-rzn1/rzn1_regauth.h efb02131d3016042f019eb5255aea2a304f26d44 - optee/optee_os/core/arch/arm/plat-rzn1/main.c 1362e6bff2c7739808fe60425baeb2fadc816d16 - optee/optee_os/core/arch/arm/plat-sprd/console.c 43ecf7e39e7a28c27b7b79a3615e3614939834bf - optee/optee_os/core/arch/arm/plat-sprd/platform_config.h ff3678a750adfc1d8371ccec9e74da720682f3c6 - optee/optee_os/core/arch/arm/plat-sprd/main.c 7a47d9b9d80c3ff0539ada4663d95c9e7bdac984 - optee/optee_os/core/arch/arm/plat-imx/tzc380.c 33c6bb81805293647a9e56f5a1c069e159c98217 - optee/optee_os/core/arch/arm/plat-imx/imx_pl310.c 8f2a801bfab0d2fb53487c8d7dca3be221530eae - optee/optee_os/core/arch/arm/plat-imx/imx.h 576710aa6118eebca00bfa8024c4f48ad57b89ec - optee/optee_os/core/arch/arm/plat-imx/a7_plat_init.S adedaaade5c7177a170c74433b126fb1bd75463b - optee/optee_os/core/arch/arm/plat-imx/sm_platform_handler.c 658c3b177340e2efe74ac7cfe5a0c688aeadf90d - optee/optee_os/core/arch/arm/plat-imx/imx_pl310.h 19f7be18a342945b17601d7b48c613ea1468eaa2 - optee/optee_os/core/arch/arm/plat-imx/a9_plat_init.S 13e40fd4f55de4dc5467690339cf670d76621be0 - optee/optee_os/core/arch/arm/plat-imx/imx-common.c 584afcf20fad8029781743589f1d8b888d4d7edf - optee/optee_os/core/arch/arm/plat-imx/platform_config.h 29532130fde10f9c8426ef28f98f4c500de5e004 - optee/optee_os/core/arch/arm/plat-imx/imx-regs.h 130bb1cd7a5b0a7a3b471a004449a211455bdd4e - optee/optee_os/core/arch/arm/plat-imx/main.c be59b37f3baf5d18ad949415e77e4c09a1a2ebb3 - optee/optee_os/core/arch/arm/plat-imx/config/imx6sl.h 93a6155f6f294fddb38ac1947f5dce49d68f71d5 - optee/optee_os/core/arch/arm/plat-imx/config/imx6sx.h 2d95ab53312d29b23061b747e96c695708612d8d - optee/optee_os/core/arch/arm/plat-imx/config/imx6qdlsolo.h 6c0a9e819b3e4b156c47a4761eef280bcfd0ab2f - optee/optee_os/core/arch/arm/plat-imx/config/imx6sll.h 7df27071dbcbeb1f977a02e17445136fa22a3749 - optee/optee_os/core/arch/arm/plat-imx/registers/imx7-crm.h 3931a5db91c6b50993dba75c296966e3e9416994 - optee/optee_os/core/arch/arm/plat-imx/registers/imx7ulp-crm.h f44811ad0707fbcbcb20271e209f14481ae12b31 - optee/optee_os/core/arch/arm/plat-imx/registers/imx6.h 9976e7cbeeb2ff5f852c838ecc82e62f85555b72 - optee/optee_os/core/arch/arm/plat-imx/registers/imx8m.h 46dc26d459e4a5adb2a904c7f6b4c5ef4546ab75 - optee/optee_os/core/arch/arm/plat-imx/registers/imx8m-crm.h 1a557c230d0c95aeb775b8f02c4a5294b829132e - optee/optee_os/core/arch/arm/plat-imx/registers/imx7ulp.h b355b4bb04068d735c1faa8039e1ade0d88d60d2 - optee/optee_os/core/arch/arm/plat-imx/registers/imx6-crm.h 0ab3222c89bd29af45b6838cb1126597ea378f7f - optee/optee_os/core/arch/arm/plat-imx/registers/imx8ulp.h e8e364071825472444c0223168929efe4a9385d2 - optee/optee_os/core/arch/arm/plat-imx/registers/imx93.h f93579c365bf08fb597488903040c0b92041517d - optee/optee_os/core/arch/arm/plat-imx/registers/imx8q.h 55f6aaaf23e460dbfd791e81c80dd5de5d3bfbfa - optee/optee_os/core/arch/arm/plat-imx/registers/imx8ulp-crm.h 845f9ec3fb38a2456492626af9b5dfe8f583bfec - optee/optee_os/core/arch/arm/plat-imx/registers/imx7.h 443dd0395348c2b831b9ea34e1d0df567e22dfa4 - optee/optee_os/core/arch/arm/plat-imx/registers/imx6-dcp.h e0bd5cc425555563f9b9428c5ab4088ab77dca2d - optee/optee_os/core/arch/arm/plat-nuvoton/platform_config.h b5eab9ec78f6d28b2c8c130ef28fb357b65f5235 - optee/optee_os/core/arch/arm/plat-nuvoton/main.c b3d21a1017a2f66d52d2f6da7f671715aba08021 - optee/optee_os/core/arch/arm/plat-rpi3/platform_config.h ec372362de1d4e3528e6ba2db82b0c9a6949239b - optee/optee_os/core/arch/arm/plat-rpi3/main.c ca3077b3f16c93f5d5350d4b21c08770138bc3af - optee/optee_os/core/arch/arm/plat-d06/core_pos_a64.S ef651043e13845e8c87166c7f7c63c304bad4336 - optee/optee_os/core/arch/arm/plat-d06/platform_config.h f3bb0c06c205574018197b20b6b28b4b4d95e9bb - optee/optee_os/core/arch/arm/plat-d06/main.c fa6b95e58563f8332731f989e0d1bca1fffbbac4 - optee/optee_os/core/include/optee_rpc_cmd.h 88da2be579e9631f960e2e446fde123208299e46 - optee/optee_os/core/include/gen-asm-defines.h 6cd050c7ddd4d5c1022f00bf74e621a0a04818df - optee/optee_os/core/include/scattered_array.h 230b6235c3972d7ad25e31b52d8dd6e446d170b7 - optee/optee_os/core/include/optee_msg.h fe35bcb23450f547f7b098c1dc83a86e94884a96 - optee/optee_os/core/include/rng_support.h 5f4af7ab7f5e65ed9a75fdef46311017a029b9b8 - optee/optee_os/core/include/initcall.h d507db96fbda840a8a7615c35c15fa3cd392b7ad - optee/optee_os/core/include/console.h 129133eb0ba4e4b73eaf1d84710e580b22e10009 - optee/optee_os/core/include/spi.h 5c27242ef89ad221fbf7dc967d4227bb1210f3c5 - optee/optee_os/core/include/ta_pub_key.h 17854fd3bc11a0554f93349178a5ebde2df45a21 - optee/optee_os/core/include/io.h 1cdb9baa31ff97e081376c5efb6ab5476a90fd9e - optee/optee_os/core/include/keep.h 804d76c5793756bf65288f5d87b37716fc8a2a27 - optee/optee_os/core/include/signed_hdr.h dcd9135e8790bfdbf7e925e8e5c9d421b5e89041 - optee/optee_os/core/include/dt-bindings/pinctrl/stm32-pinfunc.h 19bb520476cff77efd84b0106f690c4dd972bd63 - optee/optee_os/core/include/dt-bindings/regulator/active-semi,8945a-regulator.h 51c769451ca1c189b2b01b45473d6fb93157a4f2 - optee/optee_os/core/include/dt-bindings/regulator/st,stm32mp15-regulator.h 4c0440a1ff7d6b4704a914a7c2ad8192fa6e3c63 - optee/optee_os/core/include/dt-bindings/regulator/st,stm32mp13-regulator.h 6f7d303afc4981c5aaf8ae4eedae611976aa5b7e - optee/optee_os/core/include/dt-bindings/reset/stm32mp1-resets.h 75e3b85cfb7663af28a4aeabd71f5d9171713d1b - optee/optee_os/core/include/dt-bindings/reset/stm32mp13-resets.h c09a35772e7498a4ece6515946754488ec651860 - optee/optee_os/core/include/dt-bindings/interrupt-controller/irq.h 8bbae85d2c9ec2416cc28a15f3d8e79d19c9847c - optee/optee_os/core/include/dt-bindings/interrupt-controller/arm-gic.h 2d0e795df5e3ef26343c50b0371d892d062942b6 - optee/optee_os/core/include/dt-bindings/clock/at91.h 11cb6c3b8996e757f9d20becbf83d65d9da3497e - optee/optee_os/core/include/dt-bindings/clock/stm32mp13-clks.h 700be76cdd56cf4beca99964e8bef7679ca119a4 - optee/optee_os/core/include/dt-bindings/clock/stm32mp13-clksrc.h c82fd3d48caa51f67f6bb71f5637c491c8869afb - optee/optee_os/core/include/dt-bindings/clock/stm32mp1-clks.h a70bccff932cfe66485a89fd2fa7a4365f265e12 - optee/optee_os/core/include/dt-bindings/firewall/stm32mp25-rif.h f79b5f2ced860b24f63fd994d127216b28a39fd8 - optee/optee_os/core/include/dt-bindings/firewall/stm32mp25-rifsc.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 23149233a025ca8a0b84821b398694bbf0bfdf4e - optee/optee_os/core/include/dt-bindings/iio/adc/at91-sama5d2_adc.h 9eea9ced1442cf0f623a3e71799533baf44cd8ce - optee/optee_os/core/include/dt-bindings/gpio/stm32mp_gpio.h 736b382bd5ae6f63e95b0ec473a146ffe182294e - optee/optee_os/core/include/dt-bindings/gpio/atmel,piobu.h f0ee73ec026d62a1125c4410ba4a0a72b924d09f - optee/optee_os/core/include/dt-bindings/gpio/gpio.h 1e7ab5294d740390ffb703e0912f612c043e1ce3 - optee/optee_os/core/include/dt-bindings/dma/at91.h bf573306daa40e7d3a9a2d47afdb08f99e78b3a7 - optee/optee_os/core/include/dt-bindings/rtc/rtc-stm32.h c15642cd88cddd72322e27f38fb29ca150a0b99e - optee/optee_os/core/include/mm/vm.h 152f0ce018b49d6fc2b0b320f82c1b29e25cad29 - optee/optee_os/core/include/mm/core_memprot.h c97a01f7bba80935fcbf2dafe9e946d43c247e1b - optee/optee_os/core/include/mm/sp_mem.h 6d521abcb9da5acc5abe3d8e3bd7d39f79d32075 - optee/optee_os/core/include/mm/pgt_cache.h 7478c95b4ec03b37de3abbfa9a8a6f526c19e4c9 - optee/optee_os/core/include/mm/core_mmu.h 30b8bfeb037aa430b36a9d62a9d906834dcf8903 - optee/optee_os/core/include/mm/fobj.h 4f1bf0f7dbc04b954ec0408e786fe257c4ac6b0c - optee/optee_os/core/include/mm/mobj.h 3ab7ecf667fa906a144379998f686f44c83c2394 - optee/optee_os/core/include/mm/file.h 816a10ca244ab70efbf0059722455fd3f006211e - optee/optee_os/core/include/mm/tee_mm.h 208482cdefa0c15d6a3c7f325a33799eba7160e0 - optee/optee_os/core/include/mm/tee_pager.h d49b92eae62339ee11a9bc33e9de868b864333ea - optee/optee_os/core/include/mm/tee_mmu_types.h 86d731fbc4dec94afb6d508b95a533f7d47c3485 - optee/optee_os/core/include/tee/tee_supp_plugin_rpc.h 1308f358a4a299c363fc1ff9d4449995132b18c1 - optee/optee_os/core/include/tee/tee_ta_enc_manager.h 59f15f82c6b72fdca29ff7d5492653a84202aa93 - optee/optee_os/core/include/tee/tee_cryp_utl.h a99d6817471b82716d363a37e72fd6a6eadf42a9 - optee/optee_os/core/include/tee/cache.h 128881dfa00d0a1df793f816382efaa4e9d9bcce - optee/optee_os/core/include/tee/tee_fs.h 18a016ad9187e9e46b9b4758e73fadd9a375bbc3 - optee/optee_os/core/include/tee/tee_svc_cryp.h 0d89839cb1cbe5cc90c8acdb64ce5eaa35474503 - optee/optee_os/core/include/tee/tee_fs_rpc.h 053be96056cb04167009eb9368f7a8afc6dfaa5c - optee/optee_os/core/include/tee/tee_ree_state.h 6d690cb2041bea9138c24294d54a4d77aad41aff - optee/optee_os/core/include/tee/tee_cryp_hkdf.h abea67617b2ab0ac70350ff3fe67b738eaa3645d - optee/optee_os/core/include/tee/uuid.h b1c5d8f39981550bb0c40e7175bce5057378e3d0 - optee/optee_os/core/include/tee/entry_std.h cf47b8057c9b037363f5a4bc50e424c35f2e3f92 - optee/optee_os/core/include/tee/tadb.h 6950b4690d1bf6ed1c32bc5bb06c44fbe39a29c7 - optee/optee_os/core/include/tee/tee_svc_storage.h a90a966755ea02bf958fe6e492dda2d298e80403 - optee/optee_os/core/include/tee/tee_pobj.h 310b549683246f2258017d58572e9ab296981ec9 - optee/optee_os/core/include/tee/tee_fs_key_manager.h 0ac5827ea6d593ab3ff7382f2ee79d2be03fd2ae - optee/optee_os/core/include/tee/tee_cryp_concat_kdf.h d7019362eb2c68e0692df4fa18c0cea06919e3f1 - optee/optee_os/core/include/tee/tee_cryp_pbkdf2.h d517b1e0bd1ffceea1229d891891f62fa512b539 - optee/optee_os/core/include/tee/tee_svc.h 1c154159486140e838e057c58caf72c4a3b7d1b4 - optee/optee_os/core/include/tee/svc_cache.h e825068e0bf9924af7215f4327bef758ff1f815f - optee/optee_os/core/include/tee/fs_dirfile.h 01a38ef0fc64d28f2ea1e65966093196abe543f5 - optee/optee_os/core/include/tee/tee_obj.h 97cfacaf0101f86f6d7edc4a3a3ff67110792801 - optee/optee_os/core/include/tee/fs_htree.h ee6cb7826fbd60a90595fcc4962e428c46610b5b - optee/optee_os/core/include/drivers/stm32mp_dt_bindings.h 40c07075659d9321c0d0bf90cc0c2a567e4f070c - optee/optee_os/core/include/drivers/stm32_etzpc.h d9e6e80aa5d27c1fcf9c1edc4895e62394b0d4d4 - optee/optee_os/core/include/drivers/versal_nvm.h 58ddebbef8bd6c594d871fb476d88a5f9831153d - optee/optee_os/core/include/drivers/ls_sec_mon.h 91b6d3c752a3d89e785356b8589c47726ff68d98 - optee/optee_os/core/include/drivers/zynqmp_csudma.h 511feb397f8a383b92c4d238c9639c0ff2f6b5e1 - optee/optee_os/core/include/drivers/stm32_uart.h cca1719ab46702da66faa45ee2e674cbf56e0936 - optee/optee_os/core/include/drivers/zynqmp_csu_puf.h 996e4e71228a955032f4422f1857fc86adeef560 - optee/optee_os/core/include/drivers/mvebu_uart.h c8ca68f41b1afee076215f931ae25f18f2ffdf32 - optee/optee_os/core/include/drivers/serial8250_uart.h b1d5544ff4f3ab0503a7b7403cafc67a0893bc29 - optee/optee_os/core/include/drivers/tzc400.h ba6f897176895794b2c32406a85d56460b869a02 - optee/optee_os/core/include/drivers/bcm_sotp.h d6e344ad9b81930944052a2aa7439fea4f98e7a3 - optee/optee_os/core/include/drivers/imx_sc_api.h 2ddfccba77effaf40a1b9a0ccc978bdfd8162d7b - optee/optee_os/core/include/drivers/atmel_rstc.h 5a5250f891c8e3fd01fe97da71d746ab170d70f8 - optee/optee_os/core/include/drivers/zynqmp_efuse.h 2862b25eeafb9f6e676ed83d48581638899573d9 - optee/optee_os/core/include/drivers/caam_extension.h 7cd32050e290fd4a576185a57e4ee3deac99984a - optee/optee_os/core/include/drivers/versal_gpio.h 631cc4ec89ffe0c7e2eb61ef0c441a265c1cff11 - optee/optee_os/core/include/drivers/versal_pm.h e134f758ab7ac37003823e6518be9ab1ec171e88 - optee/optee_os/core/include/drivers/lpc_uart.h ee4402299d8587fe8e625421815d09e610917439 - optee/optee_os/core/include/drivers/stm32_remoteproc.h e82a2ed50b41b1008781a3fc944bc32366f9eb02 - optee/optee_os/core/include/drivers/imx_wdog.h 04f9993ffd5c2f798953978835626f7d91793c27 - optee/optee_os/core/include/drivers/zynqmp_pm.h 345ebf6d5dc2948c7a760d3cdf168f3461f36cf4 - optee/optee_os/core/include/drivers/imx_ocotp.h ed0702ba8e49ca5d2b8fde5b754911bdd2120b71 - optee/optee_os/core/include/drivers/imx_i2c.h 7861330159692f9f887f6ab44a547cbe1f3f24dd - optee/optee_os/core/include/drivers/sp805_wdt.h abea729d88bd897be58ed6c9534b6d37cf914d57 - optee/optee_os/core/include/drivers/zynqmp_csu.h e5f12caa0c11061b91eac6b6165657e68158cc84 - optee/optee_os/core/include/drivers/ls_gpio.h 72846a719bd42c01c0f3fba621809252fa7e6aca - optee/optee_os/core/include/drivers/imx_uart.h f7944ca30772475a66c4f8ff168470477e282d19 - optee/optee_os/core/include/drivers/i2c.h 0957985db83d64a10b0b4d453a89e517f1162217 - optee/optee_os/core/include/drivers/wdt.h 5a4750980a258bf284a226cd8646a4d9a4f20486 - optee/optee_os/core/include/drivers/imx_mu.h f4951939c2d41480ee8077883f4e3f9634c9ddd8 - optee/optee_os/core/include/drivers/regulator.h acdcb0f0430baed3d90047cd49aec102e6dffc4e - optee/optee_os/core/include/drivers/cdns_uart.h e5581364847f5fd4af18e00895e96feae66c2dc8 - optee/optee_os/core/include/drivers/rtc.h adc8eb02c13ad66bb1e3be9c024aed644b40d9f5 - optee/optee_os/core/include/drivers/bcm_hwrng.h 54f6572933ae458e1115bd8d43337c0955900239 - optee/optee_os/core/include/drivers/atmel_shdwc.h 2ee9ec2b7a82e5db03c61a7ebdaccf200365ef19 - optee/optee_os/core/include/drivers/scmi.h bf5353223f3ff261e30e843cf6810e7da7985b3a - optee/optee_os/core/include/drivers/semihosting_console.h bbd9f402bd751cfe638fb2585b52d940de3cd704 - optee/optee_os/core/include/drivers/stm32_tamp.h 9faff0556c12ea1887a80ebbfb60c2634048a51d - optee/optee_os/core/include/drivers/serial.h a2a83ef6478b6f51f852629efe31b59304ed79ce - optee/optee_os/core/include/drivers/imx_snvs.h c74b30cd58a799ad95ea9d8bb96bc87c362f4912 - optee/optee_os/core/include/drivers/stm32_rif.h 793f688738ed5e21251d77bdb463baae3fbf9d0a - optee/optee_os/core/include/drivers/hi16xx_uart.h 4dccf4b5a3f384b716473dd5f22fe88e62e69454 - optee/optee_os/core/include/drivers/pl011.h 044cf7b8b0ceb07ad4609f53ced52b569babfad3 - optee/optee_os/core/include/drivers/stih_asc.h d2608b476c0a3e6772cbc28ea1b2b555091784fc - optee/optee_os/core/include/drivers/atmel_rtc.h 209a9de5a95c149ed87d06209a00416aca6bdf59 - optee/optee_os/core/include/drivers/versal_puf.h c52233fb46f4ad3050a806e473cfd2f936f6b53f - optee/optee_os/core/include/drivers/scif.h f53a2a41bd93c15bcdbd21f59b7580157c370051 - optee/optee_os/core/include/drivers/ls_dspi.h 9f095079d511b5d789cac4b93714a3f09b75f4b7 - optee/optee_os/core/include/drivers/scmi-msg.h daff84d47d1e712ea0390efbdef06fcd3fadaebc - optee/optee_os/core/include/drivers/stm32_i2c.h 988feb107f388f0e02ddd78e2887e84a221e0839 - optee/optee_os/core/include/drivers/ns16550.h 6110fa3ecbd1bb7185abcee753303ad1090d1aca - optee/optee_os/core/include/drivers/ls_i2c.h 0ae76ea5b86bea63251e635eee1a0eb79682d8b5 - optee/optee_os/core/include/drivers/amlogic_uart.h e6927231b7845a9e7e71687a8b104775b431807c - optee/optee_os/core/include/drivers/bcm_gpio.h 121789edb4cf9b2797d850a0cb4a0ab1059814ed - optee/optee_os/core/include/drivers/nvmem.h 90f5cecf44f1353954b9f509e72380c23dae5481 - optee/optee_os/core/include/drivers/zynqmp_csu_aes.h 8f00fe24571b769a4046de9ec9733504c4f9aa4a - optee/optee_os/core/include/drivers/hfic.h 95ea00a994106d233112cdafcbbdecbf43efe8b1 - optee/optee_os/core/include/drivers/stpmic1.h a74eeaca5f6fc6a32f24486af30eb3bed2a377a5 - optee/optee_os/core/include/drivers/stm32_vrefbuf.h 1a127ceb7473cce35868a0e3b6fb6c0fe09f67a0 - optee/optee_os/core/include/drivers/atmel_saic.h 62c0202bb311d341e9df9d92d2a63e249d112b97 - optee/optee_os/core/include/drivers/clk_dt.h 01e3e3b8a4910f25dfdfdd865b70e885b8eb5151 - optee/optee_os/core/include/drivers/versal_mbox.h 58d82325f216b80a9bf970807e4c42339bb5b193 - optee/optee_os/core/include/drivers/pl061_gpio.h 5a47d280fbbdebc8b4b8220b9c0be960a7e80966 - optee/optee_os/core/include/drivers/stm32_iwdg.h 0858c735ecd0b0f69511c80da83b88cb428ae108 - optee/optee_os/core/include/drivers/versal_sha3_384.h 406ff8e0cfe26a1e6e63621ffa9ac1176426c376 - optee/optee_os/core/include/drivers/tegra_combined_uart.h f0a3ee94f6f4b5e982ec8cee6d771f396e5aa1ee - optee/optee_os/core/include/drivers/clk.h a33c92d997da4b5500e761f99997e9ae7747e0dc - optee/optee_os/core/include/drivers/sprd_uart.h 6c1691ca8fd41135a8d571021414095918e1ddae - optee/optee_os/core/include/drivers/stpmic1_regulator.h e0b56498b27d3bd08d540168b77b98051f90ed82 - optee/optee_os/core/include/drivers/stm32mp13_regulator_iod.h be006782da2caa19f262b37496195eb6654f9576 - optee/optee_os/core/include/drivers/stm32_gpio.h 7f3ef46e25244f20b8ad05b4953dc9bdc01db532 - optee/optee_os/core/include/drivers/stm32mp13_rcc.h 1e350e5217c7c9547170036a21103a9c8bd25c69 - optee/optee_os/core/include/drivers/cbmem_console.h f6c06a7e3d38d67183bbde4814b1b4fc68226fda - optee/optee_os/core/include/drivers/stm32_shared_io.h a534a04c75f7b25a685f14b9a9c4ad5bc1ce215a - optee/optee_os/core/include/drivers/pl022_spi.h c35d53480ece3d50dbd7ebc42aaaec3952ce010a - optee/optee_os/core/include/drivers/rstctrl.h 08d26cdf94c5c5ac4238ecbe1fe7920162d98c63 - optee/optee_os/core/include/drivers/stm32_bsec.h ef27ccc40f8a3475cc86c8746c95720ec0b5a9ee - optee/optee_os/core/include/drivers/stm32mp1_rcc.h a4463c93ac3eedb1207d208b410182b2aa7be43d - optee/optee_os/core/include/drivers/atmel_uart.h f79ce31669141d007d3d46c0510c83271a074888 - optee/optee_os/core/include/drivers/zynqmp_huk.h 5b966c643d05fffd950b8cc2875b441e6bc9938f - optee/optee_os/core/include/drivers/gic.h f0ed3b98bd6633f74dab58757059ac11933671ea - optee/optee_os/core/include/drivers/pinctrl.h 17e4e2d1b983087461bfcc4bbfbd70e8b3ae1dac - optee/optee_os/core/include/drivers/ls_sfp.h 573aef790439e7f8668bf6d5be663c9504f9273a - optee/optee_os/core/include/drivers/tzc380.h 2a38bd2d5a0cebf403be03fa37429bd62e7a05cb - optee/optee_os/core/include/drivers/plic.h a244838f90d18ae96bf58df83a82d4723e5e109c - optee/optee_os/core/include/drivers/gpio.h 33ea27d3d7b5742a187f56005a3c9ef39258ca2a - optee/optee_os/core/include/drivers/pm/sam/atmel_pm.h e00827b01eb60bbc2838dc0177a8fba77754c4a3 - optee/optee_os/core/include/drivers/tegra/tegra_se_keyslot.h 2ceae52c37cb480b625927a556e6deb4689ced3a - optee/optee_os/core/include/drivers/tegra/tegra_fuse.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 4fc3e6c0473a8f822f3bcaaa66f3f668625884d2 - optee/optee_os/core/include/drivers/tegra/tegra_se_kdf.h 129d940801fe4b67f12bbd828bc01928ccd0b626 - optee/optee_os/core/include/drivers/sam/at91_ddr.h c1ef23d7109f9ca715be1cbe858cd914f69a163f - optee/optee_os/core/include/drivers/imx/dcp.h 01ae4874fa40f1573c4604c8bc580b524346c9e7 - optee/optee_os/core/include/drivers/bcm/bnxt.h 9580dfe1f16580758041e227e65811d04ca384b6 - optee/optee_os/core/include/kernel/lockdep.h 47bae777ab0439c6c5f650a64c7eda7938bc750e - optee/optee_os/core/include/kernel/trace_ta.h f4f803096be84380cf2c48dce52aaf855b3ab2d0 - optee/optee_os/core/include/kernel/mutex.h 7c41d260656d83bc3cb2f1504f1ab5305e787c72 - optee/optee_os/core/include/kernel/virtualization.h c1f5708a89345bd1d1e59c0998656cb1b410984d - optee/optee_os/core/include/kernel/cache_helpers.h 08718b75d19035055180740c78363d96b950f76f - optee/optee_os/core/include/kernel/scall.h ff1ad215df335bbc1bf5a8365c96c64746e4388d - optee/optee_os/core/include/kernel/refcount.h 7454568aad694133ddcefc1c65ffc1a6b8f06f0f - optee/optee_os/core/include/kernel/ldelf_loader.h 00b49554c88edc39e0bea14f007188c859e0b7fb - optee/optee_os/core/include/kernel/thread.h 2d5870c0a7b942b4325b6c466fee777e6d9663df - optee/optee_os/core/include/kernel/mutex_pm_aware.h 828549ba13cdf97222d005e03793bddd388afb02 - optee/optee_os/core/include/kernel/tee_common.h de2778b5ee55508a8a54df96e419cb482f563b30 - optee/optee_os/core/include/kernel/semihosting.h e813ebd4165bad56ac4e83aa96bfb64404ff86cf - optee/optee_os/core/include/kernel/nv_counter.h 1836e525384f0bcf97d7ccf701668c6c0c4f43df - optee/optee_os/core/include/kernel/ldelf_syscalls.h 4d33576f2922c7d3f23cca65c93c8069cc665e38 - optee/optee_os/core/include/kernel/tee_misc.h 72ac22282aa32da2fc27ec02fac1ec0e5e4b433f - optee/optee_os/core/include/kernel/huk_subkey.h 641871b38417b1213428160e9c0d378ac082b3ab - optee/optee_os/core/include/kernel/dt_driver.h 854c7104502755ee6babaf7af37ea75618f7c6f9 - optee/optee_os/core/include/kernel/boot.h a614bf9bad94e38d4c27aad6b7cb71b21f02be3f - optee/optee_os/core/include/kernel/tee_time.h c5127403e01dde874dd5af239caa97296d0e8695 - optee/optee_os/core/include/kernel/user_mode_ctx_struct.h a7d6eb26cc4a919d59beb0de50ca14f3bdaeba81 - optee/optee_os/core/include/kernel/tee_common_otp.h e4719588b0cc670eee34fbf59d8d50f39cdbdc45 - optee/optee_os/core/include/kernel/thread_private.h 2071ef11bd6c92008e3267688dcec4614ce898c2 - optee/optee_os/core/include/kernel/abort.h 482af27dd67588f4f1d2d4a5cd17c50bd645df49 - optee/optee_os/core/include/kernel/chip_services.h cd624668c9f76defe8e05e3cc7547bd27128a5b2 - optee/optee_os/core/include/kernel/user_ta.h 625040376d7bc280e4dffbe23e77e046dbf40e2d - optee/optee_os/core/include/kernel/asan.h abaea6379087b38a14691b6be5fe6356a055a37c - optee/optee_os/core/include/kernel/dt.h c39885dc2548b8d6723071bcc766bb513e3ef78b - optee/optee_os/core/include/kernel/user_mode_ctx.h 2c04a3ad84fb1354bc98a83a02b34baaa2aeeb85 - optee/optee_os/core/include/kernel/transfer_list.h f16062ce2b71d0032aafbbca0b6622522111e156 - optee/optee_os/core/include/kernel/delay.h f79653070916157aa62f38869870204765305d74 - optee/optee_os/core/include/kernel/rpc_io_i2c.h ed3147f55cf57484f6b235d33d44b7ac008321e7 - optee/optee_os/core/include/kernel/panic.h f2ab69b044d5bcce9b58ca8ccb79b83d50b5fb70 - optee/optee_os/core/include/kernel/notif.h 2aaa4829d6e477b28a49aa4b15858e4d58528c38 - optee/optee_os/core/include/kernel/wait_queue.h b9ebf51c4e2cb9b094423a70588cbd6eda7efbba - optee/optee_os/core/include/kernel/pseudo_ta.h 55b39e185d6756ef7e18929f99a9c6f0e15332ae - optee/optee_os/core/include/kernel/ts_store.h 736c236f73c04985ca81ea10c2f261fd06c44707 - optee/optee_os/core/include/kernel/pm.h 590c3ba3b3785bd1b70f32788080caa459b55454 - optee/optee_os/core/include/kernel/tpm.h fdc42f8632716f2e930ccadebc2ba52fc85242a2 - optee/optee_os/core/include/kernel/user_access.h 8b22ed423b1b8e85f58048dd7072053fa9f0af4c - optee/optee_os/core/include/kernel/callout.h 5bb3a8cd5160f07a93fd9293957242604e679291 - optee/optee_os/core/include/kernel/misc.h 812a74ab18019aba6f14d3f06de6ceb0f03686f7 - optee/optee_os/core/include/kernel/early_ta.h 2233249756e47fc006e8a04186fa12757b84dba7 - optee/optee_os/core/include/kernel/embedded_ts.h f809853f7dafcd931003f4f03ec346a85a86d1a3 - optee/optee_os/core/include/kernel/handle.h 06984aa4db6e47ec48c82a3fe7b24147ffa3ca19 - optee/optee_os/core/include/kernel/spinlock.h f508df7c418ee1d26a9ac0b7bb9c02efaa95109f - optee/optee_os/core/include/kernel/unwind.h 23cec14e03085b7156a4095bb04eb95c3a096653 - optee/optee_os/core/include/kernel/timer.h 446e9f32d38a7ba8ba794474ba9d448c9c711994 - optee/optee_os/core/include/kernel/linker.h 92070cefa4d439c716c037e108416492f5d11ee0 - optee/optee_os/core/include/kernel/tee_ta_manager.h 92febe612c6bcab059b9309fc4c2d7d2c2c18e01 - optee/optee_os/core/include/kernel/interrupt.h 6633a78968c544109666de89e07ebbbb7624c4cd - optee/optee_os/core/include/kernel/msg_param.h 21af0145ee2a642abfe64f32b0618a6acb283781 - optee/optee_os/core/include/kernel/ts_manager.h 1b397670d3a135238d76ac0e6dd9cbe5095e6ecc - optee/optee_os/core/include/crypto/sm2-kdf.h 951fb0d4a44684edd5dea57f9af4dc3bfe63d7b7 - optee/optee_os/core/include/crypto/crypto_se.h 3c37642b6f4bfefdcae5a1697faef8aa2b82b756 - optee/optee_os/core/include/crypto/crypto_accel.h eef0ead7045789d8587d0a0a470491a3138a9c3b - optee/optee_os/core/include/crypto/internal_aes-gcm.h 66960122dabaed2d352fcd0a703454038d12f387 - optee/optee_os/core/include/crypto/crypto_impl.h 302739e8b28cdc82ad0a5c9b26de42e9dd0e73f0 - optee/optee_os/core/include/crypto/crypto.h 89ce33aaddb1581c98d889695b695d3f91d1abac - optee/optee_os/core/drivers/stm32_shared_io.c 5b608ade5b6d8d262288fdc49165d0e0fb72f72b - optee/optee_os/core/drivers/imx_lpuart.c f2395342fb43346befc286959fa01114b0ff28e2 - optee/optee_os/core/drivers/versal_mbox.c 1f8114767f04f10575e9d516120b9e8004560045 - optee/optee_os/core/drivers/zynqmp_csudma.c 6c4db16c8b3b5b7946f42531edaed3c24d4d07b0 - optee/optee_os/core/drivers/atmel_trng.c a9e721b1faeb4865248d3c188b56278116a3185f - optee/optee_os/core/drivers/pl061_gpio.c 9629633ef9a1ec9606d960053dd7705e7179d502 - optee/optee_os/core/drivers/pl011.c 060e285588ec6082bcbf7f3b3c1907b0a98eb75c - optee/optee_os/core/drivers/semihosting_console.c b195778e8106f48ecbe971f404a484cf3cb43d6c - optee/optee_os/core/drivers/widevine_huk.c 576097eeaf883a6a69e86b88a2364c3cd06450eb - optee/optee_os/core/drivers/stm32_uart.c 9203d1e334c03870efbb1296fc2b9151c8971267 - optee/optee_os/core/drivers/imx_sc_api.c 23020b20bb1b040dadd8e1d454b4d5a5b6229b09 - optee/optee_os/core/drivers/atmel_rstc.c 033052ada215ccb3f67e6643ef12c4b5665f0448 - optee/optee_os/core/drivers/atmel_shdwc_a32.S 1a2ee2977ed079a1526806d298af2550d23ec1c3 - optee/optee_os/core/drivers/stm32mp15_huk.c fb0a553d5a6fdc9f6c00930976fae0be73b27535 - optee/optee_os/core/drivers/ls_i2c.c 22d95a3e938617774e29f89760c65f77f932f148 - optee/optee_os/core/drivers/ls_gpio.c 1427572daefd0b1d7949a5bf943320c3ce4b9733 - optee/optee_os/core/drivers/imx_ocotp.c 09898d9b6b3ce2ff6bfaca61a6b13f0b9cd4efab - optee/optee_os/core/drivers/tzc400.c 707867f2731e424b641a7ec3409ee954fb610f37 - optee/optee_os/core/drivers/tzc380.c ba938d917edc42fd1e53f93a707cc9ff5ff45686 - optee/optee_os/core/drivers/scif.c 59a9c4ca5b114eddb0dbe6e37771eb8d04954d41 - optee/optee_os/core/drivers/atmel_wdt.c 2897acd81f2d1a3996adb59bd9dec1f0000f919c - optee/optee_os/core/drivers/versal_puf.c f6e601063c224f648486bed923c509cb27a5d5cc - optee/optee_os/core/drivers/sp805_wdt.c 9f608bd36d7697b68b44c50cf8070bcfa4c872c0 - optee/optee_os/core/drivers/imx_rngb.c 514313602dfb100842f336c91efef495a658b3a9 - optee/optee_os/core/drivers/stih_asc.c e14a90f2bcf9018fa5a0467d3681cb66d3f43369 - optee/optee_os/core/drivers/atmel_piobu.c b234794403be1c10b3977fc742799919f7b5d16e - optee/optee_os/core/drivers/ls_sfp.c 23eed3a3d72852b8eda78fe73dfa5b7f7e5cb44d - optee/optee_os/core/drivers/zynqmp_huk.c 9fbe74cf959bf2b80b39c4cf5ff6d4cc0ed64759 - optee/optee_os/core/drivers/tegra_combined_uart.c 740e5cd3acbeb54e5e8bc8cce81aba50e2593a5d - optee/optee_os/core/drivers/bcm_hwrng.c d727565a02416f45a77d93a9d363380f5f38ad79 - optee/optee_os/core/drivers/imx_scu.c 7ca34a8edb3c18eb51fa80927c8cf4f9ec8cca24 - optee/optee_os/core/drivers/plic.c 52c9fd38c2174bf6f84138c477cbee17c48cbded - optee/optee_os/core/drivers/bcm_sotp.c c96f731961fc579a4966cae12e597d72c1ed06f3 - optee/optee_os/core/drivers/atmel_uart.c 7f6538800a647267da6f019328e5814cc7c1cbf5 - optee/optee_os/core/drivers/imx_csu.c 47509d9c897d567527308698b101326d495b6f43 - optee/optee_os/core/drivers/versal_pm.c 9c0fffe583ce8197aac49fa87c158bec166776ec - optee/optee_os/core/drivers/stm32_tamp.c 0c949972e03559a0168bc9e5b75be1c0fc00320f - optee/optee_os/core/drivers/atmel_shdwc.c 52d39e5794d051ab27898621b9ad9ad78caca1bc - optee/optee_os/core/drivers/ns16550.c 42b41e7d6dba7a7d9a97f8a296aa72adc0a42be5 - optee/optee_os/core/drivers/lpc_uart.c 29302475f05ea928763d589f7149ac31fb251bc6 - optee/optee_os/core/drivers/zynqmp_csu_puf.c 63f40f459d11f83bfa729e6bcaa98cd8d785d176 - optee/optee_os/core/drivers/stm32_rng.c 285a03d5b9f6657a5a74f219b40e639aac379b41 - optee/optee_os/core/drivers/zynqmp_csu_aes.c e60b8921f76cb3ed026a112e561330bac6d39693 - optee/optee_os/core/drivers/stm32_i2c.c 9a6399d3b9a2944a5cfebf5b6c67e29dc97474e5 - optee/optee_os/core/drivers/pl022_spi.c 8c9bd89348d37d78be7efd291fc5f9279a62093d - optee/optee_os/core/drivers/cbmem_console.c 04ff6a848f0dd5e16fb7fd76e95ce39785601df1 - optee/optee_os/core/drivers/mvebu_uart.c ddf2c0a622b6f91a81ac09e02fbca99d48e19dca - optee/optee_os/core/drivers/atmel_saic.c 2127927945e603116f83b2815f785f5b3daa9cd0 - optee/optee_os/core/drivers/imx_ele.c 45fe58e31faea84f641347c7bd70e426567d781b - optee/optee_os/core/drivers/serial8250_uart.c 1320b4d29ffd0a7d76b3bca9ca5b46c18addcc96 - optee/optee_os/core/drivers/ls_dspi.c 360698584af5e09cf3bab225cf66053d658552b6 - optee/optee_os/core/drivers/imx_wdog.c 90ef3f7cef8ca0b5ea51d6514433067919d92331 - optee/optee_os/core/drivers/versal_trng.c 453275821dbd497ee05f6e25f01e69a4a0e96732 - optee/optee_os/core/drivers/xiphera_trng.c 488329789386ed718c577ec619a4315c61bfad80 - optee/optee_os/core/drivers/imx_i2c.c 5ab383a1f35751f76041e860257e0e0a3c2589d9 - optee/optee_os/core/drivers/versal_gpio.c 37dd20ab884cd41cc9d03a23df71144b0b97a765 - optee/optee_os/core/drivers/stpmic1.c 336c2f714f6f3c8267473f821b95e998a63e3cd1 - optee/optee_os/core/drivers/versal_sha3_384.c 54a609280735c84a28f8d94cc34c03b2316634fe - optee/optee_os/core/drivers/versal_huk.c 0cdb9912f3a35cdd9d52951d5f489087f96d327b - optee/optee_os/core/drivers/amlogic_uart.c 5e0cb642d735a12ab5988ae85b3a92aa9ffef6f3 - optee/optee_os/core/drivers/hi16xx_rng.c 236e360ae321cce536a289ebec4b6424211b595d - optee/optee_os/core/drivers/gic.c 72c106642fd5baba523177b44cceb0e2dd268bb5 - optee/optee_os/core/drivers/zynqmp_pm.c e26dcea60a7bdcf95acd06bb25f806e8b4d3d9ff - optee/optee_os/core/drivers/bcm_gpio.c 15006081e89bc8300728779c6253899a10614a9b - optee/optee_os/core/drivers/imx_caam.c 8d04ceb536a6bf4d80820154070d8c7c642edb42 - optee/optee_os/core/drivers/sprd_uart.c c6562bca735f2354108d76425eb80d1786bc60f4 - optee/optee_os/core/drivers/atmel_tcb.c 0a0c075afc9d78481d4d5e31b27ffeb5b2268fd3 - optee/optee_os/core/drivers/stm32_gpio.c 095d526f4c1187395f09dc20e28b5250754c1797 - optee/optee_os/core/drivers/atmel_rtc.c 8294666cb76a8dde2dc2f1155586de082381312b - optee/optee_os/core/drivers/hi16xx_uart.c f8a2cf16ad82a5a58a932430f4155678097f4ef4 - optee/optee_os/core/drivers/ls_sec_mon.c a5bf3dc83db9f97617b33e477a531942b3e75d81 - optee/optee_os/core/drivers/stm32_etzpc.c 58426138a9216b6f14a2fe1b3d3cd6250525b28b - optee/optee_os/core/drivers/hisi_trng.c c22ba5f5ef7f6a34235ad0d658510c6825b62d2e - optee/optee_os/core/drivers/stm32_iwdg.c 99907094047bf316222d7f0af9b7b043693a92fd - optee/optee_os/core/drivers/imx_uart.c 5aeb71fa00b57da2074319687b417f8cfce19043 - optee/optee_os/core/drivers/hfic.c 5f7af6748259588f30732bd198cada68ea449968 - optee/optee_os/core/drivers/versal_nvm.c 2ace80614760dbbe872200c0405c3e28fe6a5880 - optee/optee_os/core/drivers/cdns_uart.c 530fee444603ac95a1d3b87bca6a175a250b92f8 - optee/optee_os/core/drivers/stm32_bsec.c 4c9d2cdbfc272ae7e69a1bea5dd20c454eb958e2 - optee/optee_os/core/drivers/smccc_trng.c fed0f01a801201479250f34692013a5bdd4225ca - optee/optee_os/core/drivers/dra7_rng.c 138292dd3d320deb98c7243cfdb71918c02e2afe - optee/optee_os/core/drivers/imx_snvs.c b8c4ff65271508ceb0b46a94201aa3f0315e3558 - optee/optee_os/core/drivers/pinctrl/pinctrl.c 2cb2f913ef3999b884c98aef82fd8307f3d69169 - optee/optee_os/core/drivers/pinctrl/atmel_pio.c d0a8fc04ba4bcf51aebf34a8ac8691193668dd78 - optee/optee_os/core/drivers/wdt/watchdog_sm.c 11ae5906c65655bea1e0310e78fe9a2cd6f87709 - optee/optee_os/core/drivers/wdt/watchdog.c dec5d60dc6ea7b921fa5ed12484476228a08c0d4 - optee/optee_os/core/drivers/regulator/regulator_dt.c 8787994f69f69e02e156488324426826b16a27ed - optee/optee_os/core/drivers/regulator/regulator.c 04332d5beb8ff3dc39195861bc9ccb54f641b015 - optee/optee_os/core/drivers/regulator/stm32_vrefbuf.c 12f730c1d7f9187a40d66c3b90615e9c0e971d19 - optee/optee_os/core/drivers/regulator/stm32mp13_regulator_iod.c 1e600f477768bc97699dab081ae2d93d11d7ea47 - optee/optee_os/core/drivers/regulator/regulator_fixed.c 525682464b93345fd90c046fdce25d6f677a4f4a - optee/optee_os/core/drivers/regulator/regulator_gpio.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 399fa3fd4b68a0c3ca446add566a9e832be98b0a - optee/optee_os/core/drivers/pm/sam/at91_pm.c 4af2105f9cb20e8151aae7f9f5b9343f9c80cc2e - optee/optee_os/core/drivers/pm/sam/pm_resume.S 7cae1c15dfe3d06ef928dd5eefa14a4aec1f9d6a - optee/optee_os/core/drivers/pm/imx/gpcv2.c 676549817f71135f3b0178c78c523c84b12e5082 - optee/optee_os/core/drivers/pm/imx/local.h 2b8c1f4839c1e5b0efe66bec52afdc1f63c37726 - optee/optee_os/core/drivers/pm/imx/src.c e675276b10ee4b5f7b2b67729fbb657d4c4c9522 - optee/optee_os/core/drivers/pm/imx/psci.c aef7b491a53e52047bf7dd3c9150eae717ecc458 - optee/optee_os/core/drivers/tegra/t234/tegra_fuse.c 6dde88cf82c01c28a6eb27bbb5520cd326e117a6 - optee/optee_os/core/drivers/tegra/t234/tegra_se_map_device.c 01aeb814d645694dbb3a7b6cba73a8dbdb00b2c5 - optee/optee_os/core/drivers/tegra/t234/tegra_rpmb.c 2fe53582494ad0c999f05bc6bb867f0515c2fe87 - optee/optee_os/core/drivers/tegra/t234/tegra_se_aes_rng.c 657b7a4a56f717718f15b36f8e647d6aa3c85e81 - optee/optee_os/core/drivers/tegra/t234/include/tegra_se_ccc.h d0c05c35bf7b3a14be8f22ef4a1aadbe280144bb - optee/optee_os/core/drivers/tegra/t234/include/tegra_se_ccc_errno.h bb5f09ed357b48f6a968eb465e43988280e2a5a2 - optee/optee_os/core/drivers/tegra/t234/crypto/tegra_driver_hash.c 2aec9a4db595681f9bd4907d81cf0244c992b8a8 - optee/optee_os/core/drivers/tegra/t194/tegra_fuse.c c67e3cfb2ca9a5fa42769943cc7e64cd190651af - optee/optee_os/core/drivers/tegra/t194/tegra_se_aes.c e09c85691a66c623638973ebd587a1986680786d - optee/optee_os/core/drivers/tegra/t194/tegra_se_rng1.c 3b96618ecaf4ddecb14a6af70d8f80d32724299d - optee/optee_os/core/drivers/tegra/t194/tegra_se_mgnt.c 59b8fddcab1c4118b35c29a98d2e68efe471715a - optee/optee_os/core/drivers/tegra/t194/tegra_rpmb.c 88ee29ff327c35524c79fd85e9c71ffff90df695 - optee/optee_os/core/drivers/tegra/t194/include/tegra_se_mgnt.h 17ddfcb103fb3b6272fb935b6ffcf6c9277d809e - optee/optee_os/core/drivers/tegra/common/tegra_driver_se.c 174f41f9f1e928f7ec63d51501a4cec4655cdba2 - optee/optee_os/core/drivers/tegra/common/tegra_driver_fuse.c 7f9f2a7e263e7cf21f1f3f2a249d984671a196c0 - optee/optee_os/core/drivers/tegra/common/tegra_driver_srv_intf.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 db6b2d8179fcbc42da79480d5ee5d0ee046b8459 - optee/optee_os/core/drivers/tegra/common/tegra_driver_rng1.c 542a320020446e6712e8518616780ed091faf0de - optee/optee_os/core/drivers/tegra/common/include/tegra_driver_rng1.h 3a4cc745a837a9ffdf0c17d7ae2bea7f54161d79 - optee/optee_os/core/drivers/tegra/common/include/tegra_driver_fuse.h 1ed70b78a41a680b9fd609b2756145e19af309e6 - optee/optee_os/core/drivers/tegra/common/include/tegra_driver_srv_intf.h 352d6c58d195d5c44b8e06c006e713fe506dc77e - optee/optee_os/core/drivers/tegra/common/include/tegra_driver_common.h 4ee2de7e913868ad183b6f5459e97292199bac93 - optee/optee_os/core/drivers/tegra/common/include/tegra_driver_se.h 0f8548c5da8a36282a4683b4cbe749a21cd08cb9 - optee/optee_os/core/drivers/remoteproc/stm32_remoteproc.c 758385879c9afaea1eb9f1b85e07def0dadde420 - optee/optee_os/core/drivers/nvmem/nvmem_huk.c 00216a3e7662c8e93065826fcc5b9d1a08a3a0d4 - optee/optee_os/core/drivers/nvmem/nvmem.c 5c85e3f66b00f377246a021e0206af4ca134af19 - optee/optee_os/core/drivers/nvmem/atmel_sfc.c f7988928ec7527a764000f09149daab97a93ae98 - optee/optee_os/core/drivers/nvmem/nvmem_die_id.c ad920986e4bc0e99a570d96563a8fd651d98e5c6 - optee/optee_os/core/drivers/firewall/stm32_rif.c 1fe13991952d6bbc693b33615e294315900f9522 - optee/optee_os/core/drivers/firewall/stm32_rifsc.c 9c919e1b7826c8bad2ba459cc8cd4ce0035a8c45 - optee/optee_os/core/drivers/clk/clk_dt.c 497491c5aa9f4b7533a2de992b9c5ae414f45cb3 - optee/optee_os/core/drivers/clk/clk.c 2f5ae6ad224c7a1ce0808c19972c7e819292c0dd - optee/optee_os/core/drivers/clk/clk-stm32mp13.c df9d03048fb6affa7b0eb30f116f370f8194db93 - optee/optee_os/core/drivers/clk/clk-stm32mp15.c 1432346fe6a161fe80162595b76f60e63689f1d2 - optee/optee_os/core/drivers/clk/clk-stm32-core.c 98169c49a2b31260fbbbbe0a0394251d9b62cc4f - optee/optee_os/core/drivers/clk/fixed_clk.c c8f48d30481a1983d8c5991574a486ed83ebef49 - optee/optee_os/core/drivers/clk/clk-stm32-core.h 6e8872e62a9bcb7b22bd63c492045b8e3610c851 - optee/optee_os/core/drivers/clk/sam/sama5d2_clk.c 48f146dde6d5ca943dbc1c3d3e909da6c816cb42 - optee/optee_os/core/drivers/clk/sam/at91_peripheral.c b101367d257bc9abab7f6653946a5290c6beb2f0 - optee/optee_os/core/drivers/clk/sam/at91_pmc.h 18acdc71569e2a780d0476642f03bc85218be532 - optee/optee_os/core/drivers/clk/sam/at91_plldiv.c 530a8ac463371dd1e9b7fa1c1ca9e30c7958808b - optee/optee_os/core/drivers/clk/sam/at91_system.c fe1488b5f2e77d0468227c7cfc2a30712d2b529c - optee/optee_os/core/drivers/clk/sam/sama7g5_clk.c 7b04bf02eb44efee1878613f81656fd5acf46b86 - optee/optee_os/core/drivers/clk/sam/at91_generated.c c99eceb036f865d8c6c2df48b7dd402af247fd34 - optee/optee_os/core/drivers/clk/sam/at91_programmable.c c1c10c6ffec3be99f161ce8c6e467efd939ff7d4 - optee/optee_os/core/drivers/clk/sam/at91_utmi.c 13078eaf7868f4a2a4dcd703d8eadc76630f1b3d - optee/optee_os/core/drivers/clk/sam/at91_usb.c e90a1c0ffe8e8d869859768ddc4f978630f52990 - optee/optee_os/core/drivers/clk/sam/at91_pll.c 3cc6160c3ae52400111c85d3c4ce08d787630856 - optee/optee_os/core/drivers/clk/sam/at91_i2s_mux.c 1cf0a55892076fb8587178bf570a91ba7a2ba82a - optee/optee_os/core/drivers/clk/sam/at91_main.c 12cb9cf9414303b0fe7c636c24a94b413fcbbf24 - optee/optee_os/core/drivers/clk/sam/at91_master.c 3e57a61dcae8fc7e3b0a9ef6fa21b454f0a6ab99 - optee/optee_os/core/drivers/clk/sam/at91_sckc.c 1050ecd58ec5f9140571e29544df45407324d89c - optee/optee_os/core/drivers/clk/sam/at91_audio_pll.c 8771db99eec65c3ff322515b835e8bda8f4ebe4d - optee/optee_os/core/drivers/clk/sam/phy-sama7-utmi-clk.c 92fb0755687c8983cedc51f140de48967a4f16a6 - optee/optee_os/core/drivers/clk/sam/clk-sam9x60-pll.c 2b9eb96b9e23c5b50710c6cb81e630ded5600812 - optee/optee_os/core/drivers/clk/sam/at91_clk.h 8cd3321b319b3e9c1131a8ccb02eaa043ff64f3d - optee/optee_os/core/drivers/clk/sam/at91_pmc.c 152f3551f54e3ee176d8a09bd21b8692d3d34ae0 - optee/optee_os/core/drivers/clk/sam/at91_h32mx.c 67bb3144d0d145d7b6f806fe9f77c21ee007c9c0 - optee/optee_os/core/drivers/rstctrl/stm32_rstctrl.c 6ea97a6c89fdbbb425562f878dd045fd6f626046 - optee/optee_os/core/drivers/rstctrl/rstctrl.c 15a98472af569d660b8ba57d3e4515f74ad49743 - optee/optee_os/core/drivers/scmi-msg/clock.c a5fb58a50b0ccc0dde34d6fa91b0b03c5e0ca554 - optee/optee_os/core/drivers/scmi-msg/voltage_domain.c 13ed9520d3f452a3b5919a38066b702cc2f31c5b - optee/optee_os/core/drivers/scmi-msg/reset_domain.c 33be09787080f4627f5fdc10d7378880994ded05 - optee/optee_os/core/drivers/scmi-msg/entry.c 93be063666a6a98dd1fa8f45bba0c3ca91136171 - optee/optee_os/core/drivers/scmi-msg/voltage_domain.h c85de6ce4c133bc5d968be70c2b068b613042d31 - optee/optee_os/core/drivers/scmi-msg/clock_generic.c b6dc570c20e25ebbb69c815e65c4e3a77f6cf00d - optee/optee_os/core/drivers/scmi-msg/reset_domain.h cf9d967498746a73d9d033a11d89d20a95631dc6 - optee/optee_os/core/drivers/scmi-msg/base.c 0faefd362396637c831c3c6823053228443f5778 - optee/optee_os/core/drivers/scmi-msg/smt.c 1420d3d8ef64053f5b6cbf009539fd6ddddf6e95 - optee/optee_os/core/drivers/scmi-msg/common.h fbee23ad24545aea0bd9fd6ae6b67e9acc2ef16f - optee/optee_os/core/drivers/scmi-msg/base.h 189d1a32fdc699c67e4da64ae26380a2b3facd66 - optee/optee_os/core/drivers/scmi-msg/clock.h ac6217df4e25acd1b996d379ee7dc022ea03e8a8 - optee/optee_os/core/drivers/scmi-msg/shm_msg.c d103d5da1feea200154f02a82697d86c6294c0f4 - optee/optee_os/core/drivers/i2c/atmel_i2c.c 7da841080f45a989a835a1fec30f6aa50d847b10 - optee/optee_os/core/drivers/i2c/i2c.c 34825682d3731dc9ea51680257ae795e76a288f2 - optee/optee_os/core/drivers/imx/dcp/dcp_huk.c 590ea022b10a9c7283c5ffc2433de61c90148fb2 - optee/optee_os/core/drivers/imx/dcp/dcp_utils.c 0d6b0a14fd3b05ba3c8c21eb1a895e8e3ba465e4 - optee/optee_os/core/drivers/imx/dcp/dcp.c 2b2febd277aeda9813289b22b87000c559b8e4d8 - optee/optee_os/core/drivers/imx/dcp/include/local.h 2086f64aaa2a6e6c7903ab74de13c177b978297d - optee/optee_os/core/drivers/imx/dcp/include/dcp_utils.h 536893e1752c9cfee18bc1228f09fa04c0971db1 - optee/optee_os/core/drivers/imx/mu/imx_mu_8ulp.c 975a25a6b342dfc2b466f157acaf11910eb0c3b3 - optee/optee_os/core/drivers/imx/mu/imx_mu_platform.h 1ba75e71228b378cb3c43d6ba87f3d11140b855b - optee/optee_os/core/drivers/imx/mu/imx_mu.c 555963669dcfbb957e415c040be083676f914c2e - optee/optee_os/core/drivers/imx/mu/imx_mu_8q.c a7009131f76447718645c703ed1373bd329a4528 - optee/optee_os/core/drivers/bnxt/bnxt_fw.c 49865544561297dc1688131470c0baaa35112a86 - optee/optee_os/core/drivers/bnxt/bnxt.c 7651789fc830ed002efb38c51f34bda32a3e8e46 - optee/optee_os/core/drivers/bnxt/bnxt_images.c 289d35c3f71ddb7a5f121fb6723e63538130bb47 - optee/optee_os/core/drivers/gpio/gpio.c 0167f0613b4286349c7403ea6c9a7dfe0a322533 - optee/optee_os/core/drivers/crypto/aspeed/hace_ast2600.c ecc8a0a2fa12870fc85783fb7f60d717f6bf40d5 - optee/optee_os/core/drivers/crypto/aspeed/hace_ast2600.h 2702c09d55cbed00cd7326d5d6e35b12126fbe96 - optee/optee_os/core/drivers/crypto/aspeed/crypto_ast2600.c 828360f1fe0d8cb9892dd9b467df8cf52e119eea - optee/optee_os/core/drivers/crypto/versal/ipi.c 098e2cd056d7c0109c48e1c0fe7fa13577cdd79e - optee/optee_os/core/drivers/crypto/versal/authenc.c af9a8f5b582e42214ef925abde8ba38ad8bf8763 - optee/optee_os/core/drivers/crypto/versal/ecc.c 0c3d0695339eaa6535604758e28d42e1177c52cd - optee/optee_os/core/drivers/crypto/versal/rsa.c a7d7f00d8287e6bad7ec81709ec0463d5f483dcb - optee/optee_os/core/drivers/crypto/versal/include/ipi.h e2ede389a1c5a24403439cd397bc8a69fc16ac0d - optee/optee_os/core/drivers/crypto/se050/session.c 374c26b225f2311ce209fecac1317c2566d76f5b - optee/optee_os/core/drivers/crypto/se050/adaptors/include/se050.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 4732906bb4ca33cb409bd901b0c94c24a26055a4 - optee/optee_os/core/drivers/crypto/se050/adaptors/include/se050_user_apis.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 3238acd7dd2e169621bbe8ab9e9f93372f6b111b - optee/optee_os/core/drivers/crypto/se050/adaptors/utils/scp_config.c ad754aaaf0b0850065a9e68027ee82642a44e817 - optee/optee_os/core/drivers/crypto/se050/adaptors/utils/info.c 6e42bccb8cc7140adefd2baee2a8f2b2c9757348 - optee/optee_os/core/drivers/crypto/se050/adaptors/utils/utils.c 05b8cb927ce8c6dc6b2c3391b71366cf1b9dfc89 - optee/optee_os/core/drivers/crypto/se050/glue/user.c 75e0506e1992b38a38a83d6805b15b095924a783 - optee/optee_os/core/drivers/crypto/se050/glue/i2c.c 64681be01124b403991ca09721e4e6c6e023b72e - optee/optee_os/core/drivers/crypto/se050/glue/i2c_imx.c c0ffc8ba7635af755f6bc8dabf96b142cd473202 - optee/optee_os/core/drivers/crypto/se050/glue/i2c_stm32.c bc9e0c1bff88a8c8a8b844d676d9ac9d76658357 - optee/optee_os/core/drivers/crypto/se050/glue/include/i2c_native.h 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 ddc645a154efbbe06890e01fc9d2e8456eba3849 - optee/optee_os/core/drivers/crypto/se050/core/apdu.c 2bfc19e0e0e85d9305249130e474588e60b28f37 - optee/optee_os/core/drivers/crypto/se050/core/cipher.c 432313af00fe913874dd57175755d4c140cc0f23 - optee/optee_os/core/drivers/crypto/se050/core/ecc.c acd04d6ec81f1e8fcd19581e8e7d194f372b861d - optee/optee_os/core/drivers/crypto/se050/core/ctr.c 07804a4e636cd6a530a1ed8a87a523615ece79b7 - optee/optee_os/core/drivers/crypto/se050/core/storage.c cde6ea6e53f00b5a9bd70d2d430f7380e0136efd - optee/optee_os/core/drivers/crypto/se050/core/rsa.c 77ac6992ffdbc505fd3b8113c9335ea835c5f6c1 - optee/optee_os/core/drivers/crypto/se050/core/include/se050_cipher_algorithms.h 1a9e16344dbc4eb636d939a82a556a5d286c7dd9 - optee/optee_os/core/drivers/crypto/hisilicon/hisi_qm.c 5385e76fe8f2e229eb77cffd4ae238c21c482293 - optee/optee_os/core/drivers/crypto/hisilicon/hpre_main.c e06579463785ebd66688b38bd65af92ef788947f - optee/optee_os/core/drivers/crypto/hisilicon/include/hpre_main.h 757cdaf6c60a48e7779b7da7052b35ccf8c09382 - optee/optee_os/core/drivers/crypto/hisilicon/include/hisi_qm.h 601b922f3c15a1c4d5abb05d995f5735c1e356b9 - optee/optee_os/core/drivers/crypto/stm32/stm32_cryp.h 2f3ab4f2cb6b5d01d0b5e7842bed6baf91e5d182 - optee/optee_os/core/drivers/crypto/stm32/stm32_saes.h 8199d52c7baf643957c32674f889260cf2341dbb - optee/optee_os/core/drivers/crypto/stm32/authenc.c b5f0d8262b85306d730358c44941245a067cb25a - optee/optee_os/core/drivers/crypto/stm32/stm32_saes.c fcbed8594a9eb90a38465eb15df80cdbf4a1deb5 - optee/optee_os/core/drivers/crypto/stm32/cipher.c fb67584aabc078f87f6267ea7306f830e0e46064 - optee/optee_os/core/drivers/crypto/stm32/stm32_cryp.c b179d07b90bf70b2ed08a34fbf03c9294d1a205b - optee/optee_os/core/drivers/crypto/stm32/common.h efb3950cfa10b5ba1a647d083e5aa06e6a5378e8 - optee/optee_os/core/drivers/crypto/caam/caam_ctrl.c 3961eb920e409de78ae8d214ce44f802b27a379c - optee/optee_os/core/drivers/crypto/caam/caam_jr.c e50b088ae52c3e7016bce9511e39b1adfa3f0b4a - optee/optee_os/core/drivers/crypto/caam/caam_desc.c 699a8346a6775299a19d00eda00fa748fe04892d - optee/optee_os/core/drivers/crypto/caam/caam_rng.c 5abf9725310659d557245e78b391f46a589f065a - optee/optee_os/core/drivers/crypto/caam/caam_pwr.c df4f77213b909b92241663307cddf6ab6f950c8c - optee/optee_os/core/drivers/crypto/caam/caam_key.c f3959046a0ae29e21707eb07d7635232d3412a6e - optee/optee_os/core/drivers/crypto/caam/caam_sm.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 ae43fe99412d31c2f21f732a6798cda49fa12d3d - optee/optee_os/core/drivers/crypto/caam/hal/imx_8m/hal_clk.c e2251ce08c70bf59c08a56cd48659683536708df - optee/optee_os/core/drivers/crypto/caam/hal/imx_8m/registers/ctrl_regs.h 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 dc2680e783f647bce21513453573f8f426d9ae8d - optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/hal_clk_mx6.c a8796a5f28445049f810dd2b2cf6bd4700d39090 - optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/hal_clk_mx7.c fee09baaa8fd82c62ecca9d059220329bb51e466 - optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/registers/ctrl_regs.h 75e141d842a44be2fc54fc9aa3d6233d43786cf8 - optee/optee_os/core/drivers/crypto/caam/hal/common/hal_cfg_dt.c aad80d84aafe3253f980f8e72ad014fa860f51ac - optee/optee_os/core/drivers/crypto/caam/hal/common/hal_jr.c bbed4e39b9bcd1f945beda876fda141a02a74f4b - optee/optee_os/core/drivers/crypto/caam/hal/common/hal_ctrl.c 8db1294f384bce6384f85139c546c8efbb4fe62c - optee/optee_os/core/drivers/crypto/caam/hal/common/hal_rng.c b16e31abdbe671ee4a824e1bb701902be03edb0d - optee/optee_os/core/drivers/crypto/caam/hal/common/hal_sm.c 62b95ec89eb5763cd260f23face8cdb73f51bc9e - optee/optee_os/core/drivers/crypto/caam/hal/common/hal_cfg.c e7c18e488182d4bf3c8c821885db52c980fb5f7a - optee/optee_os/core/drivers/crypto/caam/hal/common/registers/version_regs.h 1061deddc2311407d8fa66dfe6df6e9c74ffda39 - 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 79bf2c681239bff0327007e0823aa9bc43f46ae5 - optee/optee_os/core/drivers/crypto/caam/hal/common/registers/sm_regs.h 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 7bbd78ddb18f062b0ee9521f445979c6acb2ee1e - optee/optee_os/core/drivers/crypto/caam/hal/imx_8ulp/hal_clk.c dc66e73bb6be55941cae77b073fdaab8d4badfc5 - optee/optee_os/core/drivers/crypto/caam/hal/imx_8ulp/registers/ctrl_regs.h 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 05f90a24f3fbacc399604028453c4885f1e107f0 - optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/hal_rng.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 aa940d1d85879826ef54d8a93ceac16d8134c9f9 - optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/registers/ctrl_regs.h 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 ad05613f64dba65f1576f358f3d0ad0182e393f3 - optee/optee_os/core/drivers/crypto/caam/hal/ls/hal_clk.c db232940b3c2f122c53b11e6dec5e70c5ec347d8 - optee/optee_os/core/drivers/crypto/caam/hal/ls/registers/ctrl_regs.h 1c222211eb56c4447e53ae06851aeb468c7423c1 - optee/optee_os/core/drivers/crypto/caam/acipher/caam_ecc.c b344e97a5a51b3bc2f8cb52dcc2fe9adbdaa3e02 - optee/optee_os/core/drivers/crypto/caam/acipher/caam_dh.c f677ba67d639efb7e1d7aebdc1a4b96eca37fa2f - optee/optee_os/core/drivers/crypto/caam/acipher/local.h 809e7d9d1c8018be4c447fa948a3954dbd7738ab - optee/optee_os/core/drivers/crypto/caam/acipher/caam_prime_rsa.c 7b9390d54de54fa7f6778b6a73a75799cb97fe1f - optee/optee_os/core/drivers/crypto/caam/acipher/caam_math.c eca8db4225df0c60977968141451b3500fd30eda - optee/optee_os/core/drivers/crypto/caam/acipher/caam_dsa.c 91c843a382b813a556a3192e3b89d4f6e2330afe - optee/optee_os/core/drivers/crypto/caam/acipher/caam_prime_dsa.c 3be0a9dac0a7d29db56b054f58f8483795177eb6 - optee/optee_os/core/drivers/crypto/caam/acipher/caam_rsa.c 981c3652730c78df0fa0ab1841ce939ae699d9f9 - optee/optee_os/core/drivers/crypto/caam/cipher/caam_cipher.c b1050722e24889ba59c987cb274897949dcd39a7 - optee/optee_os/core/drivers/crypto/caam/cipher/local.h 7c67490b6b2e00a9435c568bac2bbee4069ccc38 - 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 240eae18f54b7ba6f442845afea7c4b916b911f8 - optee/optee_os/core/drivers/crypto/caam/hash/caam_hash_mac.c d8824580f4b1889d9a23ddd2047c3b102b9e7a17 - optee/optee_os/core/drivers/crypto/caam/hash/local.h 731f10c0a7fe34860f0d1d21271b01a8a378b1a9 - optee/optee_os/core/drivers/crypto/caam/hash/caam_hash.c 0a5a24f76cbb0ec22c85016a7db24bb4694e66cc - optee/optee_os/core/drivers/crypto/caam/mp/caam_mp.c 2f780d7215aa1c23b998dfe17edabba1d0f4b1f9 - optee/optee_os/core/drivers/crypto/caam/include/caam_acipher.h eb20c569c7f68eb8f8a1eb16eb82c24a8ac4cd9b - optee/optee_os/core/drivers/crypto/caam/include/caam_jr.h 912d6553b392b20581d016f9eba91479662d6062 - optee/optee_os/core/drivers/crypto/caam/include/caam_blob.h 1f43c71456b997c24eb44cfb6ce30f4558931b42 - optee/optee_os/core/drivers/crypto/caam/include/caam_utils_status.h d43f75ad0f55131ccce9ec1aa4ca58872a8fc8b7 - optee/optee_os/core/drivers/crypto/caam/include/caam_desc_defines.h 3cefd9acd10d65bb6c61f2e0aec31f43e48f6abb - optee/optee_os/core/drivers/crypto/caam/include/caam_utils_mem.h f782be2c739055bbdf95842d912e891293d0c1fb - optee/optee_os/core/drivers/crypto/caam/include/caam_hal_rng.h bc18f3fc396e705bd01c6d443fa911800700bb8d - optee/optee_os/core/drivers/crypto/caam/include/caam_hal_ctrl.h 631d3ce5a38c82b07ae1a14ee6b6cb5ef95d32ba - optee/optee_os/core/drivers/crypto/caam/include/caam_status.h 2ffbbb6180a3ba5fcc49f2958836e6391a2c7375 - optee/optee_os/core/drivers/crypto/caam/include/caam_hash.h 3831fd7967d2e9a71b3b958e87a4dc3f1eb38261 - optee/optee_os/core/drivers/crypto/caam/include/caam_hal_sm.h 898dd496c1a8f25b592f261d9d13a74d3873ff7e - optee/optee_os/core/drivers/crypto/caam/include/caam_pwr.h a1083a9ff0bc9f8b3c8fbd60ea263a88488951a3 - optee/optee_os/core/drivers/crypto/caam/include/caam_desc_helper.h 7c8acb595959705bbf481d1ffcdda173637dccbf - optee/optee_os/core/drivers/crypto/caam/include/caam_mp.h f60708cc4c84df857fc20cdef0710a388ecd56f8 - optee/optee_os/core/drivers/crypto/caam/include/caam_io.h 74a055714e2db637adc0291d19cea1c02974e030 - optee/optee_os/core/drivers/crypto/caam/include/caam_hal_clk.h ee68dcf290038d3ebad07beabb3517b5860bc3f5 - optee/optee_os/core/drivers/crypto/caam/include/caam_utils_delay.h 7be3b8463755df707782bdaee0ed26c692c0f32b - optee/optee_os/core/drivers/crypto/caam/include/caam_jr_status.h aedd672ed034e8265f35ebab812a5af4135e94d2 - optee/optee_os/core/drivers/crypto/caam/include/caam_rng.h 7e8b656ec0076e7092003e5db98cbed4ea9a458b - optee/optee_os/core/drivers/crypto/caam/include/caam_trace.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 b6481ab7a2c7318250e4e38c57291ffa69016129 - optee/optee_os/core/drivers/crypto/caam/include/caam_sm.h d23a06ce5206f043b33f8ee8d4e6bfd62d8bb981 - optee/optee_os/core/drivers/crypto/caam/include/caam_types.h 8266a0db8e50af51f61dbe0ad34e4c4f30dbfc1a - optee/optee_os/core/drivers/crypto/caam/include/caam_key.h 0d6de8f72472e2554ab7666852ac52a37175465f - optee/optee_os/core/drivers/crypto/caam/include/caam_utils_sgt.h 547857b357f6594d407d46fcab2f93fa7074d3cd - optee/optee_os/core/drivers/crypto/caam/include/caam_common.h 42cc84af73a8980ed1e51aac57b7ac2bfe8ea567 - optee/optee_os/core/drivers/crypto/caam/include/caam_hal_cfg.h 3a804ad72278dc57b300a9df498d00db63fcefb6 - optee/optee_os/core/drivers/crypto/caam/include/caam_utils_dmaobj.h cfa13823918f625810c9958b6499358d179c8960 - optee/optee_os/core/drivers/crypto/caam/include/caam_desc_ccb_defines.h eb43fbde76dd94674bb94f9d314b9c0246403ac0 - optee/optee_os/core/drivers/crypto/caam/blob/caam_blob.c 5d2441d5350d00687dd8e35d19f42faedbb632ee - optee/optee_os/core/drivers/crypto/caam/blob/caam_dek.c 0f4455a2b7723d3cc63f4f0d0623d29b0363b39a - optee/optee_os/core/drivers/crypto/caam/utils/utils_status.c a5f84b35d9776908441db01241d508dfe83a3347 - optee/optee_os/core/drivers/crypto/caam/utils/utils_dmaobj.c 06d77bc7f344869783912b109cd485ef4e8590ad - optee/optee_os/core/drivers/crypto/caam/utils/utils_mem.c a34c25f439fb74912fddf47fac4b0295ba1effa6 - optee/optee_os/core/drivers/crypto/caam/utils/utils_sgt_v1.c 130800ee65979019cc2117d690340aaa75cd92a9 - optee/optee_os/core/drivers/crypto/caam/utils/utils_sgt.c dc70d7f20e3b0430b6dd2fe0dd0261c929d3db6a - optee/optee_os/core/drivers/crypto/caam/utils/utils_delay.c 7c483d7465e733ab3503e26d161daafaa25755be - optee/optee_os/core/drivers/crypto/caam/utils/utils_sgt_v2.c bb297b79a3f0cc6cb59b1a18f8d19242c9fc12b7 - optee/optee_os/core/drivers/crypto/crypto_api/drvcrypt.c a6e4483d1fd80f6f7f23a89a9e1ead0fbfcf65d9 - optee/optee_os/core/drivers/crypto/crypto_api/mac/mac.c d235d21c1de200d48e91b12063eb2f8f1caf0881 - optee/optee_os/core/drivers/crypto/crypto_api/acipher/local.h 38819ea8744620f296d47e0b1cab78567242c9fc - optee/optee_os/core/drivers/crypto/crypto_api/acipher/rsassa.c 46947c70982d23fe999c5a70666a676833b13725 - optee/optee_os/core/drivers/crypto/crypto_api/acipher/ecc.c 013e32cb9018761e86ee0b8b5d19b5c2089902db - optee/optee_os/core/drivers/crypto/crypto_api/acipher/rsamgf.c 979dd11c468df335b342654f7263949e51d1535a - optee/optee_os/core/drivers/crypto/crypto_api/acipher/dsa.c 7ac822e6fdd1cdb08537631b7e8a3a823a0af57e - optee/optee_os/core/drivers/crypto/crypto_api/acipher/rsa.c 1e295f6ab5c32f104ea23abb3978af44f64547bf - optee/optee_os/core/drivers/crypto/crypto_api/acipher/dh.c 8ddc0db04f5251ffd3c0beb7d3947298685d5cf4 - optee/optee_os/core/drivers/crypto/crypto_api/cipher/cipher.c 5104681db824caa455d34ffcb91e6bad1b8afad7 - optee/optee_os/core/drivers/crypto/crypto_api/oid/hash_oid.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 622acb83b02d0d5e1f8cc107df2871c1d99220b5 - optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_math.h f8f01711239d5a9fc6ece9f19e40d2f805b04c3a - optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_authenc.h b70e470e5e716917b0983224109234da6d526139 - optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_asn1_oid.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 8a2b361dc6d53a49514314969ea94af861314241 - optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt.h bd9d68e0b833479e5a83ac90bbb55776791434c0 - optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_acipher.h 30d67ef67cd36d0794f2055d1705d14905f3ab0b - optee/optee_os/core/drivers/crypto/crypto_api/authenc/authenc.c 3502395b082081a4c3f6e68c5f0774a90715d7bd - optee/optee_os/core/drivers/crypto/crypto_api/math/modulus.c b1b96d68d4bf3e82a538f91afea8b87b5c0f43f6 - optee/optee_os/core/drivers/rtc/rtc.c 843216e2097db39b59f4ed88b5f4422475008878 - optee/optee_os/core/tests/notif_test_wd.c 22edc57cadee3b6787489b0d44956d4bbeec2ab6 - optee/optee_os/core/tests/ftmn_boot_tests.c 95db84ed2db1edad93dd163e910a57e8a493e1af - optee/optee_os/core/kernel/ubsan.c a81400384a7af050ce6655fe6cbce6764c11336c - optee/optee_os/core/kernel/tee_misc.c 3eab63aa13442a732d757c7b98dcbf84c5ca5782 - optee/optee_os/core/kernel/notif.c 1beba0db1ff1f826641fd640ce1927e68758f838 - optee/optee_os/core/kernel/early_ta.c 0a4f43b4d4ae6202abe451e4d5b89b295b6c69ab - optee/optee_os/core/kernel/nv_counter.c c150b4e1f0b0906ce608d1354af8d0a722da86e7 - optee/optee_os/core/kernel/dt_driver.c 3f6a42889e84d4b674901b0cc5d83f5146e84506 - optee/optee_os/core/kernel/trace_ext.c 816e78200c8dc67e4942dc7453e0b3244e3b2aea - optee/optee_os/core/kernel/dt.c 9ac56717aa2a733944a03a9646b90bc16d817535 - optee/optee_os/core/kernel/mutex.c aeea2000adf22742f11bf2f37577da2d641ba9ff - optee/optee_os/core/kernel/ldelf_syscalls.c 2434b4d3b027cbf76b22f7245fd1764390bfe3a1 - optee/optee_os/core/kernel/user_access.c 309c59c03e9e9577dff0819b23e420d73280278b - optee/optee_os/core/kernel/refcount.c 7be1928ee7e34f7f47f52b99bce43e0024f06a44 - optee/optee_os/core/kernel/assert.c 417bc2dbf92f6a481e18233c7237d492361f4106 - optee/optee_os/core/kernel/panic.c 44103fc460d59f0a919bb3c07cf1944aa91ae2f4 - optee/optee_os/core/kernel/tee_time.c 8b3381928033ddd7c37a99aad2e60a229fbcdbd6 - optee/optee_os/core/kernel/embedded_ts.c 9975d02cd73795987cd451389809dfce9a902e9b - optee/optee_os/core/kernel/user_mode_ctx.c d259aa482d7c511f3d52cfeaa64953ad08d56223 - optee/optee_os/core/kernel/ree_fs_ta.c 28790afb155662f972fbd11f4d06c6baf1c54260 - optee/optee_os/core/kernel/pseudo_ta.c cabaa99807cb88c99fde2bd61eeb6768e35983e3 - optee/optee_os/core/kernel/console.c fd81d6b6ad33c46f7627aeb1afb49530b9c36898 - optee/optee_os/core/kernel/ldelf_loader.c 221e610e4adbc3cd9e97867d9d1ae548a818fdfd - optee/optee_os/core/kernel/ts_manager.c 93124514b7ec652f01b26753e0fbe172e526412c - optee/optee_os/core/kernel/tpm.c 55966f5406e5879e4b98143e47868368d9247225 - optee/optee_os/core/kernel/callout.c f31d663584038d598520283f7cea7ff093871a2d - optee/optee_os/core/kernel/tee_time_ree.c 94e2c0c379ce289434664a0320006df2fbae034b - optee/optee_os/core/kernel/msg_param.c 892e55c191245007f2bf20567c307871cd426060 - optee/optee_os/core/kernel/interrupt.c e0f7be46eb2d862733bba0c834997c6d4203d425 - optee/optee_os/core/kernel/pm.c a26e6665b04355864f7f98807e57d6d4d568fc63 - optee/optee_os/core/kernel/notif_default.c bf3cb1de7bd749b2628925f3a1b32fa1b6085826 - optee/optee_os/core/kernel/transfer_list.c 98fd2892161b2b537e6e91e8e7c6f6a59c55de82 - optee/optee_os/core/kernel/semihosting.c 76b1d45323c31ed6bd5987d7d7400d15d4832eee - optee/optee_os/core/kernel/delay.c ed43b747e9e9f2732be9fde2e036575eb84fbae0 - optee/optee_os/core/kernel/scall.c 9323261c4542f4f78ce0668852a81df361a9953e - optee/optee_os/core/kernel/initcall.c de1675480ef4043349e0bc3875749598f8092a54 - optee/optee_os/core/kernel/show_conf.c 693a3b47871398f69679ce69211649fcf704261b - optee/optee_os/core/kernel/asan.c 1392391e0dc7cfbd68e9b5738cb0b747ed13ab29 - optee/optee_os/core/kernel/wait_queue.c bccabf562ac6d81f8c7d94841b23d160fb1a48ac - optee/optee_os/core/kernel/tee_ta_manager.c 7aeef825f355d2436dc4fd47d92ca857decaa195 - optee/optee_os/core/kernel/spin_lock_debug.c 21449d26573f5cefed595f37780b901b7b937304 - optee/optee_os/core/kernel/mutex_lockdep.h 813e8ed14c578b5b735b29cae3bbb42af9f03a58 - optee/optee_os/core/kernel/handle.c 1b0bede72d10c96c528f188c6afdecf4306b97bf - optee/optee_os/core/kernel/secstor_ta.c 8abe5fcfb8a632e1c77c0e0f92bbc0414f1e2857 - optee/optee_os/core/kernel/mutex_lockdep.c 1962b8040874d00636c9541f532f3ee5b2ef4f16 - optee/optee_os/core/kernel/scattered_array.c 2a1975e7689ec6a1b519c0301e47924240440878 - optee/optee_os/core/kernel/thread.c 6e6b6a100da1286e715cf135ad873d4bf9063715 - optee/optee_os/core/kernel/user_ta.c 02448f355229caa2a32a4411c3198eb084395320 - optee/optee_os/core/kernel/lockdep.c f4b199a80f0476f43f34060f72493f81a289748e - optee/optee_os/core/kernel/otp_stubs.c f7c65c67d04a7829967fe1b8c657314f645a5ab9 - optee/optee_os/core/kernel/huk_subkey.c 2bfc17f9e38fa5fd9c637a5cd1ddcce6300ced48 - optee/optee_os/core/crypto/rng_fortuna.c 6ee664faf892cf6eb54780694431dbc599714a4c - optee/optee_os/core/crypto/aes-gcm-sw.c 5e7555e339aca88d6573eef4844fe96171e073ef - optee/optee_os/core/crypto/sm4.c e73ae6d522f149d7ffc117d3f026bd44fcd262c0 - optee/optee_os/core/crypto/aes-cts.c 057545a9e027cdd9daa7be1500acbb767b134a5a - optee/optee_os/core/crypto/rng_hw.c d5a046c4f72b832688b7ba9a347dc8aaa9da47cf - optee/optee_os/core/crypto/sm3.c 8136a818dce4a27b5d4375a2ed743707222337cd - optee/optee_os/core/crypto/crypto.c 135fa97faba70e8a9e76d02ac418349f734e5971 - optee/optee_os/core/crypto/sm3-hmac.c 5e36787d311129f8c3649eed00a7bc54de3dc471 - optee/optee_os/core/crypto/sm4-xts.c 7b6658854eec61d103f730922493a99440ca594d - optee/optee_os/core/crypto/sm4-cbc.c be1aa6aee3798fdc77ebc0a6b37bf5a80fc3baee - optee/optee_os/core/crypto/sm4-ctr.c e68ca1aeee7c839ed6427892eba453b827fe73a5 - optee/optee_os/core/crypto/sm4-ecb.c ed4f8a199dfc091202a84e729efc08be8166e573 - optee/optee_os/core/crypto/sm3.h a730ddd73aac7bf7e2f4530cb84b4139920cc30e - optee/optee_os/core/crypto/sm4_accel.c 8f248f23b28edaaa10678438d9965c0cb94c6a48 - optee/optee_os/core/crypto/aes-gcm-ghash-tbl.c 35204fa717049aa26af2abef06d5466dd22b09a0 - optee/optee_os/core/crypto/sm3-hash.c 7c5fada22f5c639a3b8aef284822d484e1a0c7ae - optee/optee_os/core/crypto/cbc-mac.c 82c796645d5446d81b6013ad6338920da67f8ee6 - optee/optee_os/core/crypto/sm4.h 8616cfea725a82c1c4544264382e782985f9d153 - optee/optee_os/core/crypto/aes-gcm.c 3c8f23a338eea10aca5682c64d8a12902fc433f5 - optee/optee_os/core/crypto/sm2-kdf.c 4a9aec205bda6db9f341b00e62940610c4e3e728 - optee/optee_os/core/crypto/signed_hdr.c 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 048e947aac490abffbce35e24ad1bfc69bc5ac83 - optee/optee_os/ta/pkcs11/include/pkcs11_ta.h 9f912a950243969c9bd8bcd1a3f8a7672a7c8ef4 - optee/optee_os/ta/pkcs11/src/pkcs11_token.h 9bf2174cd5400ba8a556261a46c0aea1a5f0504e - optee/optee_os/ta/pkcs11/src/processing.h 8a63bd474856b01d14303d306048e3981ddf19c4 - optee/optee_os/ta/pkcs11/src/entry.c 0f72c03b0ed1543181e76fad7ef7b4fc1b5c5219 - optee/optee_os/ta/pkcs11/src/object.c f6be4d7e2f874ba52219afaf071f4367deb9836e - optee/optee_os/ta/pkcs11/src/processing_ec.c 5d4af2af14cf8c06a09e6cd0d5d40a28c60b9fa7 - optee/optee_os/ta/pkcs11/src/processing_symm.c aee16d7bf1c5d2a0c39c6a5112cec71f528421b3 - optee/optee_os/ta/pkcs11/src/user_ta_header_defines.h ae9d768bd9244e2db1ccbd555c05eb4b9e3eac14 - optee/optee_os/ta/pkcs11/src/processing.c 0e3dca0597af48781c952400ea4ecad857110eef - optee/optee_os/ta/pkcs11/src/serializer.h e1a1a97f5050d21eae952c8db75322333235309a - optee/optee_os/ta/pkcs11/src/sanitize_object.c aaff008a064e973b8f57ec40853d5935a7fd36cd - optee/optee_os/ta/pkcs11/src/pkcs11_helpers.h 9d7de06484bf080c9fb9d2922ea6a4d808edce81 - optee/optee_os/ta/pkcs11/src/sanitize_object.h 03548923ad53ebeb43856bb7cee45d24b899dbce - optee/optee_os/ta/pkcs11/src/pkcs11_attributes.c 114f7df1ed43dd70f8b8de1604d73c0be609664c - optee/optee_os/ta/pkcs11/src/processing_asymm.c 84f772fd6ba20b3e261cde79ea54a10da7f542dc - optee/optee_os/ta/pkcs11/src/pkcs11_token.c 894d688c805cbbca2bde46ae5dfcf38092d7e8dd - optee/optee_os/ta/pkcs11/src/attributes.h ed1904bbe93d945ae27a1c8a5fceb6eeeb5e9135 - optee/optee_os/ta/pkcs11/src/token_capabilities.c 26dc92427964930f69b616be7c77b90da4bcb8df - optee/optee_os/ta/pkcs11/src/object.h 2cdc8362b15bac1a4efd183cdb7f8eb495875a65 - optee/optee_os/ta/pkcs11/src/pkcs11_helpers.c dd669facb02254f0bc7ea46368aa8a0b4a91b373 - optee/optee_os/ta/pkcs11/src/handle.c 8c9b1335779fc8cc85d4a9057276dc5b237c3c41 - optee/optee_os/ta/pkcs11/src/attributes.c 5f8de729864d1ad926d2f9ec4ef37e8ff38ceb70 - optee/optee_os/ta/pkcs11/src/serializer.c 4b7dbda490ed1c5ac55d3357b440a8f012c647d5 - optee/optee_os/ta/pkcs11/src/persistent_token.c a199684d2e257ba2568ad8c8d6788b9e4e8abcab - optee/optee_os/ta/pkcs11/src/token_capabilities.h 9740a8f2cd4228a931861239615d6f0565541730 - optee/optee_os/ta/pkcs11/src/handle.h 9e799d40bc5157fad91180105d091bf81c2695ab - optee/optee_os/ta/pkcs11/src/processing_digest.c 8b6c55e93d111035599141cb97c51bd50631817c - optee/optee_os/ta/pkcs11/src/processing_aes.c 1db1e2fc44c7afd4cfa93f2b32750e814aeff77b - optee/optee_os/ta/pkcs11/src/pkcs11_attributes.h 0aa2868227123053da7d9368bc3640a839d4e682 - optee/optee_os/ta/pkcs11/src/processing_rsa.c 6ce862868db1d139be88ffc2fa433b9f85a089dd - optee/optee_os/ta/remoteproc/Makefile e9c8b0e7823787c4fa84725f41a45595f8ad8309 - optee/optee_os/ta/remoteproc/include/ta_remoteproc.h c6760c67a37a18f9055ec466b20753434d64e9f0 - optee/optee_os/ta/remoteproc/src/remoteproc_core.c c1f49c2292f12b9f1ec2111a6cdae3e2e1834afd - optee/optee_os/ta/remoteproc/src/elf_parser.h e9b100254cc04ff146b7b63d2b5481f702007507 - optee/optee_os/ta/remoteproc/src/elf_parser.c e492697cf2d2e97abde9c2175b8d72f598868312 - optee/optee_os/ta/remoteproc/src/user_ta_header_defines.h cc0a07d6f59b29a9ec0e01f5ca6a378b3d445248 - optee/optee_os/ta/avb/Makefile db8e85c91fed835a1d918c50afc26d97eccc131e - optee/optee_os/ta/avb/entry.c 78100b9031d82bc62fe38e0650f780d2c18f2f5b - optee/optee_os/ta/avb/user_ta_header_defines.h 04d61d12d0b618ec98f1f36f7aac7e7f6a0bada7 - optee/optee_os/ta/avb/include/ta_avb.h f4be3da6e57a11e1c68fa2328f442963bf259f0c - optee/optee_os/ta/arch/riscv/ta.ld.S 47eac8b54f94d5d5a52a43ad5554f4e4c3f7ae62 - optee/optee_os/ta/arch/arm/ta.ld.S 44f007aca97998b425d27b7af67779c039d4d8d7 - optee/optee_os/ta/arch/arm/ta_entry_a32.S 50fac4ba9aede25524155ad8cd8cdd905f195a87 - optee/optee_os/ta/trusted_keys/entry.c b28af208dabadef396024e4007f36154699e975b - optee/optee_os/ta/trusted_keys/user_ta_header_defines.h 8ff25744520aea7259967d34911798667d2cf6fd - optee/optee_os/ta/trusted_keys/include/trusted_keys.h 857d0e9eef00f7eecbb7f9eecedfae0ab2cd3366 - optee/optee_os/prebuilt/t234/libcommon_crypto.a 1764bfc2b32f604e3b3b7d735ce13aebfbd84d74 - optee/optee_test/Makefile 30a64b524a40d63d6e6f97698875a98100706c59 - optee/optee_test/LICENSE.md 1677c508f843daf45fcf3a1e8c23dacf24f2f222 - optee/optee_test/README.md 9f9d1e370fe395412ffa6a5bc7d21a13586d1551 - optee/optee_test/typedefs.checkpatch 72d26f74f4c2afb8675278b599c37c055eeeee59 - optee/optee_test/scripts/file_to_c.py d178f675a81f53b7e725d270b25fadc6b064d6f8 - optee/optee_test/scripts/checkpatch.sh 3bef832a16e054c84c76c9efc89b3948ce5b0589 - optee/optee_test/scripts/rsp_to_gcm_test.py 0545607f4b3fd8f7d31fa40ceddfabc907bfb06b - optee/optee_test/scripts/aes_gcm_test.py c6f2d858387614cd7e1ba883db5977638bbcfd55 - optee/optee_test/host/supp_plugin/Makefile c035f30f1e5286ab496634f87b76fca573244cec - optee/optee_test/host/supp_plugin/test_supp_plugin.c fa35e416cf42119ff66e1a064a4d5db8c785118e - optee/optee_test/host/supp_plugin/include/test_supp_plugin.h 1c0d518167dbd004a55feb971308505c53869a40 - optee/optee_test/host/xtest/sock_server.h 9af5cc1bb69f89b1501ceba2daea681936af8889 - optee/optee_test/host/xtest/ffa_spmc_1000.c 99e8b9a2f56ea25f5ff71ba126a28d51208cb2f6 - optee/optee_test/host/xtest/clear_storage.c 0e4e675b01c2f3a1bf1ed7ff6630b17fd4f0861b - optee/optee_test/host/xtest/Makefile c546d1c8398ea1f2a5718cc966c2abeca418dad3 - optee/optee_test/host/xtest/xtest_main.c 24ba696e706583a4a4a94d7c43e8c31d986c47d0 - optee/optee_test/host/xtest/symm_cipher_perf.c 97f93f7703f25e42f830363a054f94fa70106e3f - optee/optee_test/host/xtest/xtest_test.h 3203c2511c56b80cf0757ce40aff2627e1589f54 - optee/optee_test/host/xtest/regression_5000.c b8ec54c51ef808cf8e681d82cc13d6c180380a2c - optee/optee_test/host/xtest/xtest_uuid_helpers.c d9f2461c2a9d755472e666b2c5b60fe21ae7f431 - optee/optee_test/host/xtest/regression_8100.c 27d3681d1dde596e9363305f28906b4b8e53e1f3 - optee/optee_test/host/xtest/crypto_common.h d4e67633393e1eafbf02639e218f430a71cb978d - optee/optee_test/host/xtest/xtest_helpers.c 12ca0aa8361d1e3bdbf54e11e288ca087745ce14 - optee/optee_test/host/xtest/benchmark_1000.c 1049f2d88d1a17c10c65e55629e4d86b0f182367 - optee/optee_test/host/xtest/regression_1000.c 66930a95666bc4c78d83c2cb4c087aa37a4d42b0 - optee/optee_test/host/xtest/regression_4000_data.h aeb9e6f5f8382411a15b0321473fd05148890a09 - optee/optee_test/host/xtest/pkcs11_1000.h a611cff7cdaf3b04d87eef15c299048990ec3ea1 - optee/optee_test/host/xtest/xtest_helpers.h 9e020836d511e6e309f374901ad228d82443e779 - optee/optee_test/host/xtest/hash_perf.c 4e533d0531c352071ee236302dab1c2fed2068d6 - optee/optee_test/host/xtest/install_ta.h 6074430df45012584a40484c4ed72373bcbbe599 - optee/optee_test/host/xtest/benchmark_2000.c 52b11c0af213c40771048607e3da5eb5943e0d98 - optee/optee_test/host/xtest/regression_2000.c f3517bebcb21463533c4004d029833eaf5cde12f - optee/optee_test/host/xtest/xtest_uuid_helpers.h e1fb4f35907beabaf3b0dbe646b45d64d4aa5d03 - optee/optee_test/host/xtest/stats.h 01ce700dbb77213e51c372e4e6dc61082d7da4fe - optee/optee_test/host/xtest/regression_8000.c 79632869b30c8dc171f607ff89baa306b89fdc11 - optee/optee_test/host/xtest/aes_gcm_counter_overflow_test_decrypt.h 0edc9005d19339ab2a94dd1fa3749336bfe9b774 - optee/optee_test/host/xtest/asym_perf.c bdea22513e96e2e87438e6fedf846a8fa6b3cf98 - optee/optee_test/host/xtest/clear_storage.h 16276b9d01ba73bf3bb21cb41ff264f3d0126d20 - optee/optee_test/host/xtest/sock_server.c d5fc61a73a10975c5945aa67296797824b64b8b4 - optee/optee_test/host/xtest/rand_stream.c 4cc77b90af91e615a64ae04893fdffa7939db84c - optee/optee_test/host/xtest/LICENSE 4b76e6786bed1ae8da806d21ac567198a5bebdd8 - optee/optee_test/host/xtest/rand_stream.h 1f18023df5bcdb1bd566f84860dff7f4c5fa0bb1 - optee/optee_test/host/xtest/regression_6000.c 3b971536fd7cabeefba193938f8e1fd76ca56831 - optee/optee_test/host/xtest/pkcs11_1000.c 80a9b9f4795682feb072795a92f15c630eefa57d - optee/optee_test/host/xtest/sdp_basic.h 89d308baa51ac6c6fdc1128a98ebcaf98652b24f - optee/optee_test/host/xtest/sdp_basic.c 4ed1b27140db56a58e598a1d47e2eee729363f6c - optee/optee_test/host/xtest/xtest_test.c 55594d7bf611c68c77fc65b917fe860c4cc0654e - optee/optee_test/host/xtest/regression_4000.c 14686c51c1e1fc99b03e351c11aed2874aee799d - optee/optee_test/host/xtest/install_ta.c da6d39a1f11c2a83cb0e37cccd9ef44979bd3d8c - optee/optee_test/host/xtest/stats.c 68d3a5e5deb31ba074b1848cf8e1ab7b3ee6606a - optee/optee_test/host/xtest/regression_4100.c cf936c5da248d096b5c90cc9c6c3b4b278794e84 - optee/optee_test/host/xtest/aes_gcm_counter_overflow_test_encrypt.h aa6291df45558c38403e3272c86920d0441aace1 - optee/optee_test/host/xtest/include/uapi/linux/arm_ffa_user.h dd01f2d86e9e0e0a15aab712c3828f76e4c6e2fc - optee/optee_test/host/xtest/adbg/include/adbg.h 877fc553d7b1b08364cb1189bf4cdc3b6cf3c0e6 - optee/optee_test/host/xtest/adbg/src/security_utils_hex.c e62cdf03f6bf82c09ca10f285a951c1018bbe70d - optee/optee_test/host/xtest/adbg/src/adbg_log.c 825ea0288d353fbf26dd5cb0e56be8db4e7bf245 - optee/optee_test/host/xtest/adbg/src/adbg_enum.c bef73e2c136bf2a04bc8cf33b2052afac83535c1 - optee/optee_test/host/xtest/adbg/src/adbg_case.c 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 4f57fda84526a6b64ecc3eccc008e18b97fc3523 - optee/optee_test/host/xtest/adbg/src/security_utils_hex.h e6ac80b711f1a44d2eb77e1c618fe7f3270205be - optee/optee_test/host/xtest/nist/186-2ecdsatestvectors.h 99f104f79f66a659ea913d475077f7503b8a1c51 - optee/optee_test/host/xtest/nist/186-3dsatestvectors.h a8012c439058a9ab645990d2efcd10447bc34324 - optee/optee_test/host/xtest/nist/ecccdhtestvectors.h baf0c6e02b9300a37bd4409628cea730d71faa5f - optee/optee_test/host/xtest/gp/TEE_DataStorage_API.xsl 35ce411007e4e624913b8da87f51325be763d65d - optee/optee_test/host/xtest/gp/prepare_suite.sh d00562756b00f6607632030c58bbd3576f7c13aa - optee/optee_test/host/xtest/gp/TEE_Internal_API.xsl 78e225e2b8581d7bd917bf1c007f4fee5b1d088b - optee/optee_test/host/xtest/gp/TEE_Crypto_API.xsl 488980fe7c4d8999c8466da403ef5b2811727e7d - optee/optee_test/host/xtest/gp/TEE_TimeArithm_API.xsl 39dbed853b87d4a916b95de14d5e23a8f434bfb2 - optee/optee_test/host/xtest/gp/TEE.xsl be52e9104f2b38176beb182c8e36ecc119bb5eb1 - optee/optee_test/host/xtest/gp/include/xml_datastorage_api.h 53fb592b76fe82621b4c212f07b0555b4d40992a - optee/optee_test/host/xtest/gp/include/xml_internal_api.h 7b0cf45da16221e265fbd01221f541b851cb9e21 - optee/optee_test/host/xtest/gp/include/xml_client_api.h 45865ac02ab8782763d078613beaf33dce452445 - optee/optee_test/host/xtest/gp/include/xml_timearithm_api.h 392440db195c83fb488b7829e6ec09d994c95319 - optee/optee_test/host/xtest/gp/include/xml_crypto_api.h 01305480c8ecffffa5e19202e81c3611f714ff21 - optee/optee_test/host/xtest/gp/include/xml_common_api.h 705d65243c1e46af9f9642bb84f45b2daeff957f - optee/optee_test/host/xtest/gp/patches/0008-TEE.xml.patch 496f8635c2c0110849cb7e095423e036dae754ec - optee/optee_test/host/xtest/gp/patches/0014-Pass-upper-32-bits-of-TEE_PropSetHandle-in-value.b.patch 4f9aca322840391a171d320f3e9d5976b257fa41 - optee/optee_test/host/xtest/gp/patches/0006-TTA_TCF-fix-CmdTEEGetPropertyA-_withoutEnum.patch cc1ccad0b05569188be42a4e6fad9069b9b44d05 - optee/optee_test/host/xtest/gp/patches/0011-TEE_Crypto_API.xml.patch c85d2439e6af14cf1845341a721831d294e94e35 - optee/optee_test/host/xtest/gp/patches/0016-TEE_Crypto_API.xml.patch 34223b3e49b6b18b8bf88abf784fac10a0648a10 - optee/optee_test/host/xtest/gp/patches/0015-Enable-compatibility-with-TEE-Internal-Core-API-v1.1.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 c834f47f97dd115566b874fa7e4a6d40d064d939 - optee/optee_test/host/xtest/gp/patches/0013-Disable-Invoke_GetTAPersistentTimeNotSet_and_SetTAPe.patch 4436ae2a8726be665c4adbc30899d7dbcf721afd - optee/optee_test/host/xtest/gp/patches/0002-TTAs-add-files-needed-to-compile.patch 0c86f63bc803a23617fb13ba1479108edaf5dac5 - optee/optee_test/host/xtest/gp/patches/0009-TEE_Internal_API.xml.patch 93fe519236e63a82aec4fa2e267aa9c10a9cf3e2 - optee/optee_test/host/xtest/gp/patches/0007-TTAs-revert-to-v1.1-types.patch 146a6228e298272ab7e73778962df356d9198311 - optee/optee_test/host/xtest/gp/patches/0010-TEE_DataStorage_API.xml.patch cbc872e82c403faa84376db8efc78150338e2693 - optee/optee_test/host/xtest/gp/patches/0004-TTA_Arithmetical-patch.patch 5bdbfb7c09b73b8ee3f012bb4c05c5655a2e426c - optee/optee_test/host/xtest/gp/patches/0012-TTA_TCF-remove-TEE_MemMove-from-CmdTEEGetPropertyAsX.patch 89bb7582daae987e60e094aebfd5b2b073e9ac62 - optee/optee_test/cert/my.conf 1f75eacaea5baa5f8ecd35d3c8df7e746c3f73a9 - optee/optee_test/cert/mid.srl 6b932b1ab7b3565ddb4557b31b13ff823577f997 - optee/optee_test/cert/my.csr 6f108292e83a3a3555b56add6fba6bfc75bb1d03 - optee/optee_test/cert/my.key ca513a618e76b7425f4f1350e90c7b74d4778eac - optee/optee_test/cert/my.crt 5870a0a431a6e7fd1fb251ada8f25d58c79a762a - optee/optee_test/cert/mid.csr c858311b53e86391299c5bc0c30a39801b3893a3 - optee/optee_test/cert/mid.ext 4c8bd2753f58de91b618d71902216b93834e1b18 - optee/optee_test/cert/ca.key c1c1370410a6251da1f2a65d4bb6799b6695ae46 - optee/optee_test/cert/mid.crt f11ba7468488761597018fef555faaa8dcf0049f - optee/optee_test/cert/ca.crt cf7626a2e6fdd3e5cd2455117e6ff59e38cc3a99 - optee/optee_test/cert/mid.key 93503a34df30013f6f47e50cde65662d3e5d3a8c - optee/optee_test/cert/mid.conf 9162a5682d5d26b3df6021cc646498709aadc3e9 - optee/optee_test/cert/ca.srl eaa886f698fec46167f30ea7abbd0c72881e3e9c - optee/optee_test/ta/Makefile 494d296fe7e6b7bc0f500a343c6a33cf9f0b05a3 - optee/optee_test/ta/top_level_subkey.bin 525fc4d0105b2261ed118a2d96d2cbf71cba2432 - optee/optee_test/ta/top_level_subkey.pem d9a4193c1df764fc72c7e49efeeb550f84c6dcb0 - optee/optee_test/ta/identity_subkey2.bin 2f0deec19c000366d2fd6d627f9b4363213eef7a - optee/optee_test/ta/mid_level_subkey.bin 8890459880f4ef0eb20f8a28b727540e789f07a3 - optee/optee_test/ta/identity_subkey2.pem 5d45a78f116ff6a6a5ce6227b1dd705d86a1a640 - optee/optee_test/ta/mid_level_subkey.pem 192ebe9f6d76a6b9d3938a69c72663ef7b627fff - optee/optee_test/ta/os_test_lib/Makefile b0992bc9d242a926b54b8162b36f7f219c278624 - optee/optee_test/ta/os_test_lib/os_test_lib.c 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 5558acac0905fc8f55ec7451c6cafff4654c532c - optee/optee_test/ta/large/Makefile 3231e66bc961e72de9759c2d801cf7e081611183 - optee/optee_test/ta/large/ta_entry.c 04b692b46b7c145c2fe975bb20250626d9e5680e - optee/optee_test/ta/large/include/user_ta_header_defines.h 78c0f90194587f8ec4696ed9937eab82bd2d6102 - optee/optee_test/ta/large/include/ta_large.h 6902d41cad5e1a7fdd792070ee6fe09543fd0a36 - optee/optee_test/ta/miss/Makefile 63727dbe77411a56de4384f2647ac604df1bb77e - optee/optee_test/ta/miss/ta_entry.c 17584ab846d09d2e11a0c62ee9c12f7eb00a89f2 - optee/optee_test/ta/miss/ta_miss.c e8cc80687d4a1d454c124c0288798e280142a723 - optee/optee_test/ta/miss/include/ta_miss_test.h 7577f16d52d892d26d2aba97100c391696f1b4e0 - optee/optee_test/ta/miss/include/user_ta_header_defines.h dfc1e1eb35732695271ed55f42d20a4f3d65dd85 - optee/optee_test/ta/socket/Makefile e1b35b65fffd182965ab59d513da17f3bc2cb637 - optee/optee_test/ta/socket/ta_entry.c 7caf8e51e601aad92bfa2080fd1d462af34a690f - optee/optee_test/ta/socket/include/user_ta_header_defines.h 60c71c4fd9746b52eff3180768cadfb42246ad63 - optee/optee_test/ta/socket/include/ta_socket.h 159ab9161f614e0e78c7ed8ad589b1da7dc49313 - optee/optee_test/ta/tpm_log_test/Makefile f041af378514b0adb83e13683c439bdfda633a38 - optee/optee_test/ta/tpm_log_test/ta_entry.c 071de3ab826aea3082b54036a436e42d20e5e829 - optee/optee_test/ta/tpm_log_test/include/ta_tpm_log_test.h 15979122b263375291e30ed248816c707e51aa9d - optee/optee_test/ta/tpm_log_test/include/user_ta_header_defines.h 05d9586c179dfa463023108f57186c397f67b168 - optee/optee_test/ta/tpm_log_test/include/ta_tpm_log.h 3762c8d8188b6fd5c0e0216aa0dfbc1a81c33bd4 - optee/optee_test/ta/sdp_basic/Makefile 3e89b728bfdb79e36b4831135f52d8907cc6b6ba - 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 3e93b929b783566f5933da6daf3bf178b60f0ac9 - optee/optee_test/ta/sims_keepalive/Makefile 63727dbe77411a56de4384f2647ac604df1bb77e - optee/optee_test/ta/sims_keepalive/ta_entry.c 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 e3deb7bd3c13099679c0218b2daabc17547fb2aa - optee/optee_test/ta/supp_plugin/Makefile 615513981a90fabad2bd36d67b4ece7b3e63bfe6 - optee/optee_test/ta/supp_plugin/ta_entry.c a6d7b87593d95249d1adf41e1ed2855be8557092 - optee/optee_test/ta/supp_plugin/include/ta_supp_plugin.h 97d8481ac3b8dd32d148d69acc3da07308fb759a - optee/optee_test/ta/supp_plugin/include/user_ta_header_defines.h 62093428f73279ad6337e6b83de79cdc9638aa07 - optee/optee_test/ta/sims/Makefile a2d1207a964e7c839176e0c9beb333de1aa5114d - optee/optee_test/ta/sims/ta_entry.c b27b844ff53c4ce9ea4b37becfc73759661121c9 - optee/optee_test/ta/sims/ta_sims.c 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 56e682b335cbdbb4b053f31838a28d596ea0dbf5 - optee/optee_test/ta/subkey2/Makefile 3484bf8a9bd48d0fd2c66b682574dcbd80ae59e7 - optee/optee_test/ta/subkey2/ta_entry.c d1217850bdabdc5c5f402556a4dd76a32af19d03 - optee/optee_test/ta/subkey2/include/user_ta_header_defines.h 786d2761de772f9af4885b058126e8596a16e194 - optee/optee_test/ta/subkey2/include/ta_subkey2.h f22bc5e3e7d42fae8b515ed89e6d52e14853097d - optee/optee_test/ta/crypt/arith_taf.c 707f95e800674bd769a22f4b05b0f86bde9bdda0 - optee/optee_test/ta/crypt/Makefile 0205269ec12a07945fa15e1f01beacd396129c02 - optee/optee_test/ta/crypt/ta_entry.c 89299c5c290be38d0509309892bd9bf67946a552 - optee/optee_test/ta/crypt/sha2_impl.c 0f5728bb87da64faea76a4d60859ffc6ee7cfb0e - optee/optee_test/ta/crypt/seed_rng_taf.c 6d536756fbdc5623379b5c8c68b3383c6c3c7535 - optee/optee_test/ta/crypt/aes_impl.c 2f8d16642c23418d96eae0799cdbb319adae9bd2 - optee/optee_test/ta/crypt/aes_taf.c cda695cd368148125b67d4b5049b4b5e44f19d4d - optee/optee_test/ta/crypt/sha2_taf.c 71541fecba370d8d5d888ff889cc55a649e0f6e3 - optee/optee_test/ta/crypt/handle.c 59232c5714af3b17dab86effad8c4adcdc6193ec - optee/optee_test/ta/crypt/mbedtls_taf.c 62f575dd691dc4df07cd85b6aaf381bb1fa129df - optee/optee_test/ta/crypt/handle.h ae237aa24606ab8442252be914264ebc32acb3f1 - optee/optee_test/ta/crypt/derive_key_taf.c 08792d69cd8404668362c47a42015e3ed15a03e2 - optee/optee_test/ta/crypt/cryp_taf.c bece95c11da1deff583de5cccb73aeb047b13bb3 - optee/optee_test/ta/crypt/include/seed_rng_taf.h 65726ede28ff3980980f0786f73da00bf00f7adf - optee/optee_test/ta/crypt/include/aes_impl.h f922975017d8e69cf55d924ad3475f48207c778c - optee/optee_test/ta/crypt/include/sha2_taf.h e39b6697e3f099db9e9210630f403279d821b01d - optee/optee_test/ta/crypt/include/user_ta_header_defines.h 751a9eda488bdee96dd4666819f86792eb94e63c - optee/optee_test/ta/crypt/include/mbedtls_taf.h d6094f43aff3a5e99b1b4916e6f0616f4b506c4e - optee/optee_test/ta/crypt/include/ta_crypt.h dedb18c14d2c13ecb2666beff2d43a1c6f2b1f4c - optee/optee_test/ta/crypt/include/derive_key_taf.h 971b7e4384dfd449056d2d98600938baaa13b45c - optee/optee_test/ta/crypt/include/arith_taf.h 81c28b5d39b57c60583003aa3b19d4e9355be3e8 - optee/optee_test/ta/crypt/include/aes_taf.h 59bb92661052957ededa8bf444418db0f792e5df - optee/optee_test/ta/crypt/include/sha2_impl.h 98b131e0650e8848c202b367de6afd9713234b23 - optee/optee_test/ta/crypt/include/cryp_taf.h 0b8f95e1cc815a73f1913f8b1cd1199b86afd777 - optee/optee_test/ta/os_test_lib_dl/Makefile 34655a75cdbf9b1cf1a0f475a835630aa77d76ad - optee/optee_test/ta/os_test_lib_dl/os_test_lib_dl.c 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 403faf3efbd2a187981acd30a58067dcb43d4d2f - optee/optee_test/ta/concurrent/Makefile b33588442f2691e00ae34677fee3503279ec4251 - optee/optee_test/ta/concurrent/ta_entry.c 81d9fc2603da64f6aca629d4c1f6152ce40f4299 - optee/optee_test/ta/concurrent/include/ta_concurrent.h b203b24b6fb092d32555949aece3d104a945d314 - optee/optee_test/ta/concurrent/include/user_ta_header_defines.h 545a9527a5a59df10e9fc50f958bf567149bb8b6 - optee/optee_test/ta/include/ta_storage.h 3777dde2c0aee5f993ddf5f6e2899d578554736d - optee/optee_test/ta/storage2/Makefile fd20f8c7b48682f3cb154209d193c38ef5fa8afa - optee/optee_test/ta/storage2/ta_entry.c 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 969daad84d451c2beaaeb0205d361045b135c899 - optee/optee_test/ta/create_fail_test/Makefile 327bcd861d17179ed6eec837ae40d93f6d4d5171 - optee/optee_test/ta/create_fail_test/ta_entry.c f8ff5608bd441c5bb14ba4e0d1ac825036c0be26 - optee/optee_test/ta/create_fail_test/include/ta_create_fail_test.h 28f22d74fc72b507d9530a7788812714f4ccd2be - optee/optee_test/ta/create_fail_test/include/user_ta_header_defines.h a7891e77ba72a13303bee70e3469d5b66c4dd0ff - optee/optee_test/ta/storage_benchmark/Makefile 126f0a0f43f2045ed64ac151420ff2750039cae6 - optee/optee_test/ta/storage_benchmark/ta_entry.c 1c896a32ab658f67fe2c2469efab67c781d40d17 - optee/optee_test/ta/storage_benchmark/benchmark.c 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 350b57d8d13e85db59890347995fb8b25902941d - optee/optee_test/ta/storage_benchmark/include/storage_benchmark.h 49c2d5872d9a41ded424776ddde01ab79ca78988 - optee/optee_test/ta/crypto_perf/Makefile 12f72f4f686c7e5c42580ed7eae7c3687d07bfa6 - optee/optee_test/ta/crypto_perf/ta_entry.c 76173f317d8ec7c0d93c8e416222325635b95a68 - optee/optee_test/ta/crypto_perf/ta_crypto_perf.c cbdc030bb470e5a4955e3e9156033676053db836 - optee/optee_test/ta/crypto_perf/include/user_ta_header_defines.h 080c319338a6832c33fc4980075e44db13d22020 - optee/optee_test/ta/crypto_perf/include/ta_crypto_perf.h bef96027f5481438c3532aa395fb391799d91bfb - optee/optee_test/ta/crypto_perf/include/ta_crypto_perf_priv.h 305e7a10ae0489f83dfe773f06b47ad314bb9771 - optee/optee_test/ta/concurrent_large/Makefile c5741796e6b99090e6fd99dc03a6bbcfe6871028 - optee/optee_test/ta/concurrent_large/ta_entry.c 6fc98a616100591a9ba17fe01d8cd7f30c449420 - optee/optee_test/ta/concurrent_large/include/user_ta_header_defines.h 51f374f9df753de95e0ee8a082c29395bed8625a - optee/optee_test/ta/concurrent_large/include/ta_concurrent_large.h 19e490a77411c75a67b54eb0684edc9dc35f7192 - optee/optee_test/ta/bti_test/Makefile 9752d870fbaca8ae7c1554096be6f228b5a0efaf - optee/optee_test/ta/bti_test/ta_entry.c 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 e00637d3dc4e177f4693a591711c655a84f82c6e - optee/optee_test/ta/os_test/Makefile f99e6541faaf5c1e883528d5a9a247c9a404ad5b - optee/optee_test/ta/os_test/ta_entry.c c845f1bef062d33dd7e59d0647155b05ef5ed6ac - optee/optee_test/ta/os_test/attestation.c f99ecd7a7d1466b6ae095553f19b144a3b5e05a6 - optee/optee_test/ta/os_test/cxx_tests_c.c a4ae385c460bad98c3f1bb74e4cd6d78a3d1c569 - optee/optee_test/ta/os_test/cxx_tests.cpp 0821f97bb6d0e672f229f163d91a44db3b3cfc21 - optee/optee_test/ta/os_test/pauth_a64.S 30c95077d893a72f6dd6f25698b9e3c4c90c7173 - optee/optee_test/ta/os_test/ta_arm_pauth.c 7c34f62620b2c3cf1e435dc2f06b5bc695a0ffca - optee/optee_test/ta/os_test/init.c 81b48e32f421e3809c799370e7d5a84be82e4007 - optee/optee_test/ta/os_test/test_float_subj.c 4b24fec7bb0779f54df830b2accd4589c58ee714 - optee/optee_test/ta/os_test/test_float_subj.h 9474cf4fc4a3b252db66bceae94a0d1af55032a0 - optee/optee_test/ta/os_test/os_test.c 0455da7d426f2d9c91e8d1f0ceedcbcdc25b7e63 - optee/optee_test/ta/os_test/cxx_tests.h 8e61b08c2d218f799c0ceb8531677adaf702b81c - optee/optee_test/ta/os_test/include/os_test.h c250edae8e50b81ddc7f2d82b74533be8ce36484 - optee/optee_test/ta/os_test/include/user_ta_header_defines.h 5925bcc4d74e66a2c9ac214c3afb53d3a2c40385 - optee/optee_test/ta/os_test/include/tb_asserts.h f61b829b0f8774e078f535f9dcb469a402aab63f - optee/optee_test/ta/os_test/include/ta_os_test.h ef669e3a5af86a9d7433680efe47e7475ebae840 - optee/optee_test/ta/os_test/include/testframework.h 0fc4efc474f17406466b3a01708a70604c4bf90a - optee/optee_test/ta/os_test/include/tb_macros.h c0f2b4917d2e7e2c64767ce20c51277d030da95e - optee/optee_test/ta/os_test/include/init.h ab190ed1cbd92987955bd1b18cf1125760e00235 - optee/optee_test/ta/subkey1/Makefile e98d28dd7d955c5f1430b86d1f9fa9a293f2c6a5 - optee/optee_test/ta/subkey1/ta_entry.c 3ef18fee5ed3f12595bcae5cd670e9b614bddccb - optee/optee_test/ta/subkey1/include/user_ta_header_defines.h fccce5046748bb0a2c4bf866d2ee4099789327e9 - optee/optee_test/ta/subkey1/include/ta_subkey1.h a29dec4b78281324f1e479a7648b636feef1d163 - optee/optee_test/ta/storage/Makefile 7e3e9ed670136ea79aa56b6e986e2b795074cc8f - optee/optee_test/ta/storage/ta_entry.c a2575f658d20bade8d2751a438a3881dec9506ba - optee/optee_test/ta/storage/storage.c cbcf995c4fce7f48869248f9f3bf912195d4873e - optee/optee_test/ta/storage/include/user_ta_header_defines.h 470456cae0c3f509a24f5ec3678881a672b863c7 - optee/optee_test/ta/storage/include/storage.h 96b12ede29af7df11c0b54a3d3924599f9ad0de4 - optee/optee_test/ta/enc_fs/include/enc_fs_key_manager_test.h db39d7c16208c8b18547c18b524c4d4d8d8533a6 - optee/optee_test/ta/rpc_test/Makefile 28e50e4d884a51351b0454dcf8971ea8619becb2 - optee/optee_test/ta/rpc_test/ta_entry.c 100bd8db89d7d506ba95afa1adf59c093bee623b - optee/optee_test/ta/rpc_test/ta_rpc.c daf6f0380173f9c72cb5ab411c7e145635102403 - optee/optee_test/ta/rpc_test/include/ta_rpc.h bb5b31def49e12cb5ca13946631064fdab7f3ce1 - optee/optee_test/ta/rpc_test/include/user_ta_header_defines.h 5a06508a48d77c9bc4d4483f2c1064bc11547f17 - optee/optee_test/ta/rpc_test/include/ta_rpc_test.h 6c873429bc677416677c5807645bf161215865df - optee/optee_client/Makefile 1d22df2514ce91279fc9fd16270cf6b0ced2e65a - optee/optee_client/Android.bp 1be3a93bb56c46ee4d4693b47ddd7c4c5487ffd3 - optee/optee_client/README.md a7d910ff308216f427e9a4776d72cfe84e2915ad - optee/optee_client/LICENSE c9b3bb5ab0a3d0252ed93cfc3578e3991ee2b994 - optee/optee_client/typedefs.checkpatch d064a25e20d345a05792931a265ee41e75706c88 - optee/optee_client/tee-supplicant/Makefile f24b5d7b4681f11f33d735e96c6193f040d61420 - optee/optee_client/tee-supplicant/src/rpmb.c eb428488f05ca6049614557e2a89abbe531b1e24 - optee/optee_client/tee-supplicant/src/sha2.c ea069507eb088c8be58fd316e1182d94fdcfffb6 - optee/optee_client/tee-supplicant/src/optee_msg_supplicant.h 5387e1fcf4e95d497b72ee814d729c4c90adb740 - optee/optee_client/tee-supplicant/src/plugin.h 435831cff86e23874de21d77aa2acd2e2847e629 - optee/optee_client/tee-supplicant/src/tee_supplicant.h 2eeff0bb8ad1aaf5594e87a9faa9b9bffa63ee8f - optee/optee_client/tee-supplicant/src/plugin.c b738d8b04995c56175826db5cbaca1ed21e079ad - optee/optee_client/tee-supplicant/src/teec_ta_load.c f5b0fdcf3343c38ff2495f438044546952d538e2 - optee/optee_client/tee-supplicant/src/tee_supp_fs.c a5f3a0cb9e4309400c0c22dc574de3c8eef67a65 - optee/optee_client/tee-supplicant/src/nvme_rpmb.h 945a945fa92b85f4b7003123e4ef27a588bdc2bd - optee/optee_client/tee-supplicant/src/hmac_sha2.c bed7d31fece3711cc20a9418d51d24ef7fe3391b - optee/optee_client/tee-supplicant/src/prof.c 8fbfe192d68bdb1e126598cb730e7c11f511960d - optee/optee_client/tee-supplicant/src/hmac_sha2.h 946a1750a3bd2cb7ee8a0934d7df7849d1649aee - optee/optee_client/tee-supplicant/src/__tee_ipsocket.h 721aca20ceeacd1648d0f7204c85f69b282fe101 - optee/optee_client/tee-supplicant/src/__tee_tcpsocket_defines.h 593518d07f2abcdc15942f188796aaa0bb12d4c6 - optee/optee_client/tee-supplicant/src/__tee_tcpsocket_defines_extensions.h a80eb6caf9c8732d74f0fc4c329a4222995ec6c8 - optee/optee_client/tee-supplicant/src/__tee_isocket_defines.h a16a80d873293f74d73baf53721eb5019ded25cf - optee/optee_client/tee-supplicant/src/tee_socket.c d6dd587b4421a742de3144b103342789681958a4 - optee/optee_client/tee-supplicant/src/teec_ta_load.h 2b4e00ad1b9e0f3a5e7c2efbef6591de41a0e409 - optee/optee_client/tee-supplicant/src/sha2.h df8821ae52abffd9ffd2d962078fd715185513d4 - optee/optee_client/tee-supplicant/src/tee_supplicant.c b81a505561be6982f3eea681e266827c8236583c - optee/optee_client/tee-supplicant/src/__tee_udpsocket_defines.h f17cf7d08bb300eb71cf0b2ca503f505c269e761 - optee/optee_client/tee-supplicant/src/tee_socket.h f1107acfa97784e2a91a1a393dd6198fc4a4a222 - optee/optee_client/tee-supplicant/src/prof.h 1f145b8b2fe3882017290f627f46dfc328a7c144 - optee/optee_client/tee-supplicant/src/handle.c 4a38f4ea1eea116c78d27b03a2cbfb92f8ea3a97 - optee/optee_client/tee-supplicant/src/tee_supp_fs.h 9763ee4354d75e34559e80fe8dda7bb158c4c5d0 - optee/optee_client/tee-supplicant/src/handle.h 07af4053379b51e5d33dda8ac2eda2181ae23a02 - optee/optee_client/tee-supplicant/src/nvme_rpmb.c f04b1790f669de1573516dc81fe3f4eefcb59c1f - optee/optee_client/tee-supplicant/src/rpmb.h d6e6c51b13d0f6f61ae51ff3da8b8f51b3ac433e - optee/optee_client/scripts/checkpatch_inc.sh 5f5e044fbbcd7b4262c4d4405cac9dc8115b9bd6 - optee/optee_client/libteec/Makefile a5fbbcfc0214db8015e94fc05998f548c339e1ab - optee/optee_client/libteec/teec.pc.in c6e011ef6751f07449bffe9fd19006a15b8624b5 - optee/optee_client/libteec/include/tee_client_api_extensions.h 43da45835976c93e70ec5ad1ed02b891a0dbe000 - optee/optee_client/libteec/include/tee_plugin_method.h 668dfffd684890e7dd9bedbfd635db0df9af35d8 - optee/optee_client/libteec/include/teec_trace.h a3e6eec2b0c6f60ab6995f2b082b866bda6a808c - optee/optee_client/libteec/include/tee_client_api.h 16cd3b045e35ef0e65b2c33238b2b59f62255883 - optee/optee_client/libteec/src/tee_client_api.c d842563e16728b8e4b8e70f1fd7522598235d843 - optee/optee_client/libteec/src/teec_trace.c 15278a332dd772f0c91e486e562d10ba1b9cb6df - optee/optee_client/libteec/src/linux/tee.h c2eeeb99eea300a1748db00f9803a548f2282c49 - optee/optee_client/libteeacl/Makefile 1cf357b019b2533237bef65ce240ef9e7d0d77b2 - optee/optee_client/libteeacl/teeacl.pc.in ee867d9d7bddd079e18e86b614ddb0951d3a79ce - optee/optee_client/libteeacl/include/teeacl.h 3842833a20a863d971c8d33f5e101ccc77e88c62 - optee/optee_client/libteeacl/src/group.c d44856b3c2e641d34dc08c44aa14df8111f0f2a0 - optee/optee_client/libteeacl/src/tee_uuid.c 94dc6f25362ba38974deb9290b3ea1460569ff71 - optee/optee_client/libckteec/Makefile f25fe667d7155f39694414e63dac8d54adb5e264 - optee/optee_client/libckteec/include/pkcs11_ta.h cbd1cf1d939303ee17050057c176ddb7498b1598 - optee/optee_client/libckteec/include/pkcs11.h 7d66a5a9955374f577b36eda3684c254841edbda - optee/optee_client/libckteec/include/ck_debug.h e640a280681f076f112beee518ea1adff965c818 - optee/optee_client/libckteec/src/local_utils.h 3d1d16bc8a998c7382d0e5deb177e421613cbdb9 - optee/optee_client/libckteec/src/pkcs11_token.h 28f837a80c95ceb3f72437386993f46469f861e9 - optee/optee_client/libckteec/src/serialize_ck.h 48b8562a4200b00fe6382797789d8e694186c620 - optee/optee_client/libckteec/src/invoke_ta.h a36127385f3d497598291e167cfc4147e48861ed - optee/optee_client/libckteec/src/pkcs11_processing.h 4a7c34adbc6006ef9230bb1919ca520891b9823a - optee/optee_client/libckteec/src/invoke_ta.c 04e59fc9b03985ed9c71fb751bcf60dc050aa517 - optee/optee_client/libckteec/src/ck_helpers.c 0db1379449cb2cdae53a7b480a402e8c43457431 - optee/optee_client/libckteec/src/serializer.h 53de33af06e51fb21fe2f24c2c0665a45baeb3b8 - optee/optee_client/libckteec/src/ck_helpers.h 66ad3fbe5639477f5ef0f50c0a87bb825db643aa - optee/optee_client/libckteec/src/pkcs11_token.c 27cd49c5be59123275b6d2d23f61956cd86846c0 - optee/optee_client/libckteec/src/pkcs11_processing.c a4b2b6fc00af2b337386db3fc110f54709a248bb - optee/optee_client/libckteec/src/serializer.c d38060ba408bececaceffc5392363c4255e064a3 - optee/optee_client/libckteec/src/serialize_ck.c 145e33a2859354e90473957df5bdd430b63f437c - optee/optee_client/libckteec/src/pkcs11_api.c f88324eb36dec1f8579a56f5e446475ced59b52d - optee/optee_client/libckteec/src/ck_debug.c 2a0b9b82ad279a7127d4fb8fa2c4c4bb0bbfb62e - optee/optee_client/ci/Dockerfile.debian 874f552974cb3d5f17a63dd2ba50582a28e2d28e - optee/optee_client/ci/Dockerfile.ubuntu acd8d0f397cd4e0ffdc9aed50f3f91fcf357822b - optee/optee_client/libseteec/Makefile 2219ff4dd85f1c6a0ee11024a1834c7d17124a79 - optee/optee_client/libseteec/include/se_tee.h eb52a5aa690916e1cdb6e9d58fd746762ac03bbc - optee/optee_client/libseteec/src/se.c f5d83909e5071e2affc98fc56ac4b941e00ef03a - optee/optee_client/libseteec/src/pta_apdu.h dfe89d4404a213f5751887db149a30135cd07f9a - optee/optee_client/libseteec/src/pta_scp03.h fbddcc56f1918f9c27f657f1e527b77f9a94382d - optee/optee_client/prebuilt/libuuid.a 3eb30c4c0069f3a45e46ea616d1bfaa9c81dcf95 - optee/optee_client/prebuilt/uuid.pc f946a4e57b4901f5733debd6aec83a809534f9cd - optee/optee_client/prebuilt/include/uuid.h bf52776d687b57bc5e886b2f4e7a0f7ece62b0b7 - optee/samples/Makefile b2def2faca96323618fae5d302c50260bccb869e - optee/samples/LICENSE 2f700b45a00530a528bbd7086b22444f8a91ea96 - optee/samples/cpubl-payload-dec/Makefile ea49cce3ddf319882d8e400806f6a761de306ce7 - optee/samples/cpubl-payload-dec/LICENSE 3945bd127a3cab935cd8b206bdc6bfbabd07e020 - optee/samples/cpubl-payload-dec/ta/Makefile c37254b292d303cab4ab95c06ce5cbc3adc72b5a - optee/samples/cpubl-payload-dec/ta/entry.c 135be83f6d1ba5b8793d6127420fe3b879424531 - optee/samples/cpubl-payload-dec/ta/user_ta_header_defines.h 22e887e40458255171cfad715a9c477826fa3cfb - optee/samples/cpubl-payload-dec/ta/include/ta_cpubl_dec.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 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 6d3ac3cebb74c4f088accfac2d48654ea788769b - optee/samples/luks-srv/host/tool/gen_luks_passphrase/example.sh fa3f0583c33f15560475d2899643217e9b8bdedd - optee/samples/luks-srv/ta/Makefile 9198ad9d0108d1f0c5411e43cfcdbbb011dc6ddd - optee/samples/luks-srv/ta/user_ta_header_defines.h 7dcf0c69657674d5c8d84f037993856ccdabf784 - optee/samples/luks-srv/ta/luks_srv_ta.c 80db8ae67e3a08227b8feeb7c71d80c97e620988 - optee/samples/luks-srv/ta/include/luks_srv_ta.h b534b3c1b0a9fc7ea3c6a3ecc9d4a7182a66f022 - optee/samples/ms-tpm-20-ref/.clang-format 56cea4315ced27989bf4993b5ebb6f5123222c3b - optee/samples/ms-tpm-20-ref/SECURITY.md 9fcc9b4c93fd85452b4b1a3c89afe4d598d545df - optee/samples/ms-tpm-20-ref/README.md e12c4ff9f6d12441b1b697d24c4b8b6923b2fb08 - optee/samples/ms-tpm-20-ref/.travis.yml bbf046fa124b7c4632ae2631e9059507a72a3d2a - optee/samples/ms-tpm-20-ref/LICENSE 13c6e4813b3e9761d334db45a93cef59b96cde02 - optee/samples/ms-tpm-20-ref/CppProperties.json 10937e6af19c7747e93a8367c3ce6953f2c09b6e - optee/samples/ms-tpm-20-ref/CONTRIBUTING.md 7cd6e55737ca672c343962a688186bc665f41898 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/README.md df67ed7bc549a84f8ff8a5de0d3d096a6e2bbd48 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/Makefile 6d3239af75e740ae509ca8b2e0d51b584f3465a5 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/Makefile 3f229d45d7d2ce7e5d7e46e12377af9165e6c361 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/user_ta_header_defines.h 1bce5759e31235d9c5bdba21dd91adaa428fc3f0 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/fTPM.c 8a3ff6f0fbf400d5960a0b9e29100a2f0c257cce - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/lib/mbedtls_ltc/user_custom.h 53e682c13d0856ad3840af92efef4f69ce2e1d61 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/fTPM.h ea9d25b54a0bfb6a2f2919629390ac2f1a7cd709 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/fTPM_event_log_private.h f0e69701b65f4b4bf75a97838a5784c8b96377eb - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/fTPM_event_log.h eca8429d573b1efe6aabb85e729081ecd232cd9c - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/fTPM_helpers.h d265a8bc723bc221914fe71eecf809497317402b - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/Wolf/TpmToWolfMath.h 1abdd3758b52641bc84ab63597b351aec39dd45b - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/Wolf/user_settings.h 369f00bc9361a2d2471b00bbf96c1ba518e645b3 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/Wolf/TpmToWolfSym.h 2a43b3beb22e372a4284450764b201c24f4e7f97 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/Wolf/TpmToWolfHash.h 376c946270a22a79f5ae90cbbd3efeb4b6a0b5f4 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/PlatformData.c 9c1182d6fbfc09acdb617e2c6e644e7bc7add570 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/Unique.c 87d59c28e82a41130b6d7f9a8a36c75e1b750a0c - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/NVMem.c c9349c1d5329a5100adce5dcc24d234c9bdcaa61 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/fTPM_event_log.c b59bde7a93e1cc1855b209291ae236fbffcdedbf - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/Cancel.c d8d1e1184b822d904eceda19ad720da371cefc24 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/PowerPlat.c 79c38e67602cae65ee67146a13518eeed36f2bf8 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/EventLogPrint.c 7c5cb20afa4a0e569b22aec797fabdb2f30552bd - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/PPPlat.c 52663f93a5790e3ca64daed728e5491847136e5e - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/AdminPPI.c 13ac1a0dcd262678d94da7a3b86856a3a3851361 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/fTPM_helpers.c 283a4b88a1e84f5ef741d4f4d4fde82d9407ca55 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/Entropy.c d5d1030b42d4d34b5b1384aa182b441c909f4df5 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/EPS.c 411c14cd40d0d71d28c13f52c3911e5a8c411b2e - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/Clock.c 61e1c6504462645f5064ea9dc434804a824a5075 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/RunCommand.c d7201b197b3e91e981077abb03ae2827b42a9b63 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/LocalityPlat.c 46c4a6540314c172068f6dc8fffe1f467861b7d6 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/DebugHelpers.c 963be460c3847e12f66b652610ba0bc3281f4bf4 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/PlatformACT.c d9b2bbfdaceb0f02c468ede7e0b05fe5a8aa50f4 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/NvAdmin.c b493c94195fe836564fb88852ba0fea97814ca6c - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/include/Platform.h b5b9fbb93586419230ff8d1ec018285878ad46c2 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/include/Admin.h 82113c01765d59f6759fd977d625e6444fd75572 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/include/PlatformData.h f7c1239e5dea6bb93130c66ed56ce33485985ed3 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/include/Platform_fp.h 62105e5307c3636450c1864348a5d5d35b63660f - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/reference/RuntimeSupport.c cd7e6c680ef80aab7901ba9978c4afd5a7e52a63 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/reference/include/bool.h 2706d6092917100fd8117a9d5c315e7862629748 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/reference/include/TpmProfile.h 5bc59f1069c9183079f5bfaa521e4398048fb2a4 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/reference/include/VendorString.h e6eb4da02d48333abbca49a31090610423fa06d0 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/reference/include/TpmSal.h 468436d93e40d0fc852d4e86920fbc68718c929b - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/reference/include/RuntimeSupport.h 65607068ebad388e1a689ac6e701b0b45e02c5a3 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/ta_prod_signing_scripts/generate_digest.py 14fb1121df155d6da96d7a1d6351b9fcf47a0af5 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/ta_prod_signing_scripts/README.md e643f090d5cbaaa3dd73f87fd32aa7bb079e776e - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/ta_prod_signing_scripts/stitch_ta.py a7aeff0addca9724f945178d6857a4d5b254de77 - optee/samples/ms-tpm-20-ref/Samples/TPMCmd-DeviceID/build-tpmsimulator-deviceid 32b6f41f8cb17695fa4e40dcdb5a13bcefb7d93e - optee/samples/ms-tpm-20-ref/Samples/TPMCmd-DeviceID/Platform/src/EPS.c e855760eaf75328c77fc714300151c27ce864ec3 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/USB_Hookup.jpg 10c3fd48393c33d4510c403bde7a91efbf05666c - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/microUSB_Hookup.jpg 3f8d0256d18033e053779e7864508daa371797a9 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/.mxproject 0206b31f994b247b4ef78e829cdc3fbfec23dd97 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/mx.scratch 8086602309481b27c6586f824f4783f514c027d0 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/.project 17bc2133944d7885da66070c51191d5c4c7a86ce - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Nucleo-L476RG.elf.launch 77f371cf9bdfbd2ee243ceb2d60dfc4f734095a6 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/STM32L476RG_FLASH.ld e40037acef5ee9515273d568d4fa1f7d7c2dfb98 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Nucleo-L476RG.pdf 96cf2e3a3a7fe535463d74a9e77bdd6eff9e544e - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/.cproject 8f3874f3592022902246b887ff77ba3dafe8988d - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Nucleo-L476RG.ioc 20bd88d6e69c5795823fcabe4faf5f97189eab7d - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/usbd_desc.c d866ccd9ea216a89eb9d539b9a9df43b83b1c7cd - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/system_stm32l4xx.c efe613f6cfea1253034d36d8f9eb0a3885a72b51 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/stm32l4xx_it.c e82acf04a1cad0a297e5cfc954c31a504c3c53e6 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/stm32l4xx_hal_msp.c 6d604522f0cef3bff34a64eb9e500cdce25b5d57 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/usbd_cdc_if.c c1db06ecec983da549ee3a8ae57154b2460f8d4f - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/usbd_conf.c 16d1db972ccab86a0e8c0aca69dfb400853b139d - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/usb_device.c 55729e915ad655e9e16d0d30c7699bef97c14a99 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/main.c f8423beb4a536d57e5aa0c948599c0c8feb00a9e - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c c766b5449c964208e6c0301ca2f558902b8b9528 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc/usbd_cdc.h ab94a34d9ab12695aebd8fa8466ade808f27e929 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c 3b25e71498a2311c71b3919166ecf09dc5141b1e - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c 9a2873d30abe93eeb862acfe28f3590a9a6f06b7 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c 60317c715b32cdb43f4f23b57141868055ea4589 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_def.h f2e11c0c40d6e621c683638444082ccb2cd1e404 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ioreq.h ae9cd8bf67b36f59b68abe1006f6e621b3097871 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_core.h 10fec4a5fea35ec45db039d5a366c3b6a4dfdc47 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ctlreq.h 03bd0280d262095dfc54880a3beebc7e8d1cd238 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/usbd_conf.h 75b6204210b1d2d7bc133c477e55b55ab886553d - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/stm32l4xx_it.h 29fa5f1155f4b6471a344eb19184bb023e939cbf - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/main.h f2d077bd5409d6fd6fe3992c5cb64c6f4632d217 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/stm32l4xx_hal_conf.h 97a7710fdcc32282cbf75739e2b1afaff643e09f - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/usbd_cdc_if.h c20ba1d07bb19091580f77d81b3ef95b0b843914 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/usbd_desc.h b1f85fda09c5bd2d09cea7044da1fe04616da066 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/usb_device.h 25392a40719c25b125bb4abc1c9105228b153444 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/.settings/com.atollic.truestudio.debug.hardware_device.prefs 988b68517c27704d1f464138322cb3e7ef94c005 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/.settings/language.settings.xml a19a363124b0fdc91c783bf67234bfd09ec1c211 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/.settings/org.eclipse.cdt.managedbuilder.core.prefs 72ad8c891c625eccc2ed488d63e73685b36bb7de - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/startup/startup_stm32l476xx.s 7b273c6190dd31db4d1f5091bb46a780eed2f065 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rtc.c 6905470e6a40b7909609c5a5e902c0efcae29c17 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rcc_ex.c b31f07cb494c120315b086a52a662d098943fb56 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_gpio.c 4dbd5f4ac87a7b6ac1d550a567e59f1238f7d026 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_tim.c 54204b942a2710a64b6ba0c30b84e1b3b52dae74 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash_ex.c 622a5ea51bdb8c062e8e889f4b71bf6482fa5264 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pwr_ex.c 12784369e6124301623660326aeffa81593b036a - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_usb.c 4dda1150337631a2d17123634e05b782a5668b04 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rtc_ex.c 25ec312cbb302ca24cf9e909df42265a12821a78 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_dma.c 2b8ea417236425866c81e285a0ab18d04783b587 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_i2c_ex.c b167ca16a9d80ffe8bdffec69454d740bf0117bc - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_uart_ex.c 5f07fe6dad1130b6ee4df5a184ac8b0226619cd6 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_tim_ex.c 7e7baefb69d9a62f7684c185a9fb3ddd83500a39 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_cortex.c df06884b75649ad21d7110e12ab4de41f1e9eb4c - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash.c a15fdfad695b08ee5b822074ff541cf712f2c39b - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_dma_ex.c da703e39e170c4cb94dfa998f3f1ffa29d80d699 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal.c 36599a4da2f2d80c6e6ac0220385ee433b03e54f - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rng.c 4516770dad8099473586dfb47cf5cc4cf85dbecc - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_uart.c e926d3bdc7e3bf71bb7539ea30ea292b92d7ffe3 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pcd_ex.c 70c187cc31e577582b15c93b82183a02ae1e45c4 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rcc.c a049a3b8f2c1bbc893531c3dec916646bc42443c - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pcd.c b241444200a682980fe3e6bec522da4e967a170a - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash_ramfunc.c 1e88ee4f8bd2b1617b9d2523943dd1e6acb23dcc - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pwr.c 296985473134d81cdcee7e324c2d47a069390872 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_i2c.c da4c5dc66fa19f1a2dea73d7aa3e81597b676dcc - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_tim.h 76daccf26f1c1119f653377547eebb3aead3ae9a - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pcd.h 3f9db9098124b6d4bf658a9ff358a93525f658b0 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rng.h eeefa20586b1afc75301a9c1a9fa51984bf8e5be - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_def.h 85ce004e873496c1eacf6087a2b3c82652c2f87c - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash_ex.h cc2961929d2d137935b8d36ce4d073c22ecb6d0a - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_tim_ex.h ef09ef096f9aea54c52b3f8643d4a2de8caefd08 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_usb.h 7d01a2e45f24933398c321ebf63ab167f6681b98 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_cortex.h 2905f1d5f33236d983b4c332990276c9e1bb5521 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash.h 05b58c53586df1d7b41ae67ee282455482c2467d - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_dma.h 7a1f93772829c677cd79a5c7d91c49a0d414bfb8 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_gpio.h 66a329dbf83da1d835ef3a2056ff37b30cc34c2a - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_dma_ex.h 7cae377cfa95e6bca50a18ebe16d4ecc325278df - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pcd_ex.h cde58e7973942b2d9f6fddaa266fff01a9f39a9b - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rcc.h d87d95f0dce5fc06196437a894acb9c5d4f02f95 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rcc_ex.h a737f1820b6165f725d7549f95775b4d21c6767f - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_i2c_ex.h ee193c30ba73303f2644de840804e121c4a9a4ea - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rtc.h c98c6c63fac3bcc2cdeac550828e9bf253b0aa5d - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal.h dffe5c55f2b819f9601130a43806007a1746359b - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_gpio_ex.h 06a183a5b3a97fb5a3ccdfeae53c776cfb650a04 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash_ramfunc.h b93c1179f456734f5977ee7fde296795f371dfaf - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pwr_ex.h ced33137d14e602db17d8caf629ada93528ee8a8 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_uart.h 54e67e3be92290f9e6457f2f91c04bbc7099ea48 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pwr.h 5de56cbae29e353bad3c38d9081a059eface1630 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rtc_ex.h d79b95f004663f145e964ff6cb145e92a36e9652 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_uart_ex.h 4e41e93110701a53f7bc809136a4ab0649de3413 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_i2c.h c23c26b4a5705dfa36703ea8b6c5f40dffd8ab7f - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h 16b99b227562ccb1354b33482c354c1812123013 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cm4.h 3fea94e10d135f6717a70f8d1e199b010baa7f08 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cm0plus.h 9f5c937feac2936c1cf0ced43722f527a1531ca2 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_sc000.h 6c2c8dba3fe5460a7310efae010a5b7937025aa1 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/cmsis_armcc_V6.h e0a1f1bbe188023d261188754e1dc59c781fb565 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/cmsis_gcc.h 70a7d2f8ffcfbebc2f39f3cdb5ef701e081a6e92 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cmInstr.h e68945e0faf5ee8d1f027d7e8be3b4c321028e39 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cm3.h 0186b62597ed4f4804e7b81abd3b598e6c2bd555 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/cmsis_armcc.h bcb11dcd98c7ba42403d991919032dde3049b364 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/arm_math.h c93167da8e8344f98d9b28f27a857a1d41a10530 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/arm_const_structs.h 3d909ef05e1c328dbc138a1b906e914b968239ed - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cmSimd.h c6f03caabac7d0b08fed7d09ee6db8b6f2093853 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cm7.h c87716fe24718015c2d01cf913480c92e3b0b4b3 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cmFunc.h 441239dec598474dc7ab14b7283195c7f649a3c1 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cm0.h 90061e5e149725c682eb80978b557fd388191f24 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_sc300.h 0a94a9650bfc5345f574fb23a10d495f06735cd9 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/arm_common_tables.h bcaf73ba929b494e9c3f2993e975bb7de3fbff2e - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Device/ST/STM32L4xx/Include/stm32l4xx.h 5d6591e31b6229f63fd06eb0de8724554b4b44f0 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Device/ST/STM32L4xx/Include/system_stm32l4xx.h 8f94380a70fb6a2a723ab7278572292ae274e564 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Device/ST/STM32L4xx/Include/stm32l476xx.h dc8595af01c9444a2c541182900bf2b0fb28b819 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/.mxproject a52f7d5678ac81e61ec37b727b6292b6369b0caa - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Nucleo-L4A6RG.ioc 3985a4fde219680c1e17e341acd59488439dcfde - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/mx.scratch ece39ffdce43f997fdf2dd55d74017f38603c617 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/.project cda727dead5740c98700cc1fd4ad37858a6f0320 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Nucleo-L4A6RG.pdf 4afdcaa4fef2feb33d218e6d2388e3f3b3838203 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Nucleo-L4A6RG.elf.launch 3f8bc8936a633424641eab00ba651f076d380035 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/STM32L4A6RG_FLASH.ld 44ea1cb0eee4d33fe6e691653cea4a32e74e87f0 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/.cproject 20bd88d6e69c5795823fcabe4faf5f97189eab7d - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/usbd_desc.c d866ccd9ea216a89eb9d539b9a9df43b83b1c7cd - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/system_stm32l4xx.c 65f7e0f37508e288cec330f92d477098d2ff4c82 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/stm32l4xx_it.c c28cb48bd43bb7b4c492078ab1dc6f494bfdba2a - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/stm32l4xx_hal_msp.c 6d604522f0cef3bff34a64eb9e500cdce25b5d57 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/usbd_cdc_if.c c1db06ecec983da549ee3a8ae57154b2460f8d4f - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/usbd_conf.c 16d1db972ccab86a0e8c0aca69dfb400853b139d - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/usb_device.c 40579596ad18cd876b59233ace09918e6c93fc64 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/main.c f8423beb4a536d57e5aa0c948599c0c8feb00a9e - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c c766b5449c964208e6c0301ca2f558902b8b9528 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc/usbd_cdc.h ab94a34d9ab12695aebd8fa8466ade808f27e929 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c 3b25e71498a2311c71b3919166ecf09dc5141b1e - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c 9a2873d30abe93eeb862acfe28f3590a9a6f06b7 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c 60317c715b32cdb43f4f23b57141868055ea4589 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_def.h f2e11c0c40d6e621c683638444082ccb2cd1e404 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ioreq.h ae9cd8bf67b36f59b68abe1006f6e621b3097871 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_core.h 10fec4a5fea35ec45db039d5a366c3b6a4dfdc47 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ctlreq.h 03bd0280d262095dfc54880a3beebc7e8d1cd238 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/usbd_conf.h 984804b6ff3ca103ce3abb97027764ede06f0b28 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/stm32l4xx_it.h 9d1ea64fa5998b911cc7f5af6cec6ddbf4fc8f9a - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/main.h b90b9552c0a39dbb50871b7d2d0487c31ab43c23 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/stm32l4xx_hal_conf.h 97a7710fdcc32282cbf75739e2b1afaff643e09f - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/usbd_cdc_if.h c20ba1d07bb19091580f77d81b3ef95b0b843914 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/usbd_desc.h 715d5dee9ff492cfad346512f7d1d53801e4f445 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/usb_device.h 2393e776dd333dae85dc34f806ad87b6e55aaff1 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/.settings/com.atollic.truestudio.debug.hardware_device.prefs 988b68517c27704d1f464138322cb3e7ef94c005 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/.settings/language.settings.xml a19a363124b0fdc91c783bf67234bfd09ec1c211 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/.settings/org.eclipse.cdt.managedbuilder.core.prefs 3ae4b06f79f30f7f8aa7cb36e8911765333cf94e - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/startup/startup_stm32l4a6xx.s 7b273c6190dd31db4d1f5091bb46a780eed2f065 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rtc.c 6905470e6a40b7909609c5a5e902c0efcae29c17 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rcc_ex.c b31f07cb494c120315b086a52a662d098943fb56 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_gpio.c 4dbd5f4ac87a7b6ac1d550a567e59f1238f7d026 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_tim.c 54204b942a2710a64b6ba0c30b84e1b3b52dae74 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash_ex.c 622a5ea51bdb8c062e8e889f4b71bf6482fa5264 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pwr_ex.c 12784369e6124301623660326aeffa81593b036a - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_usb.c 4dda1150337631a2d17123634e05b782a5668b04 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rtc_ex.c 25ec312cbb302ca24cf9e909df42265a12821a78 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_dma.c 2b8ea417236425866c81e285a0ab18d04783b587 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_i2c_ex.c b167ca16a9d80ffe8bdffec69454d740bf0117bc - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_uart_ex.c 5f07fe6dad1130b6ee4df5a184ac8b0226619cd6 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_tim_ex.c 7e7baefb69d9a62f7684c185a9fb3ddd83500a39 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_cortex.c df06884b75649ad21d7110e12ab4de41f1e9eb4c - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash.c a15fdfad695b08ee5b822074ff541cf712f2c39b - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_dma_ex.c da703e39e170c4cb94dfa998f3f1ffa29d80d699 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal.c 36599a4da2f2d80c6e6ac0220385ee433b03e54f - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rng.c 4516770dad8099473586dfb47cf5cc4cf85dbecc - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_uart.c e926d3bdc7e3bf71bb7539ea30ea292b92d7ffe3 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pcd_ex.c 70c187cc31e577582b15c93b82183a02ae1e45c4 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rcc.c a049a3b8f2c1bbc893531c3dec916646bc42443c - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pcd.c b241444200a682980fe3e6bec522da4e967a170a - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash_ramfunc.c 1e88ee4f8bd2b1617b9d2523943dd1e6acb23dcc - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pwr.c 296985473134d81cdcee7e324c2d47a069390872 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_i2c.c da4c5dc66fa19f1a2dea73d7aa3e81597b676dcc - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_tim.h 76daccf26f1c1119f653377547eebb3aead3ae9a - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pcd.h 3f9db9098124b6d4bf658a9ff358a93525f658b0 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rng.h eeefa20586b1afc75301a9c1a9fa51984bf8e5be - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_def.h 85ce004e873496c1eacf6087a2b3c82652c2f87c - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash_ex.h cc2961929d2d137935b8d36ce4d073c22ecb6d0a - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_tim_ex.h ef09ef096f9aea54c52b3f8643d4a2de8caefd08 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_usb.h 7d01a2e45f24933398c321ebf63ab167f6681b98 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_cortex.h 2905f1d5f33236d983b4c332990276c9e1bb5521 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash.h 05b58c53586df1d7b41ae67ee282455482c2467d - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_dma.h 7a1f93772829c677cd79a5c7d91c49a0d414bfb8 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_gpio.h 66a329dbf83da1d835ef3a2056ff37b30cc34c2a - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_dma_ex.h 7cae377cfa95e6bca50a18ebe16d4ecc325278df - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pcd_ex.h cde58e7973942b2d9f6fddaa266fff01a9f39a9b - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rcc.h d87d95f0dce5fc06196437a894acb9c5d4f02f95 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rcc_ex.h a737f1820b6165f725d7549f95775b4d21c6767f - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_i2c_ex.h ee193c30ba73303f2644de840804e121c4a9a4ea - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rtc.h c98c6c63fac3bcc2cdeac550828e9bf253b0aa5d - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal.h dffe5c55f2b819f9601130a43806007a1746359b - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_gpio_ex.h 06a183a5b3a97fb5a3ccdfeae53c776cfb650a04 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash_ramfunc.h b93c1179f456734f5977ee7fde296795f371dfaf - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pwr_ex.h ced33137d14e602db17d8caf629ada93528ee8a8 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_uart.h 54e67e3be92290f9e6457f2f91c04bbc7099ea48 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pwr.h 5de56cbae29e353bad3c38d9081a059eface1630 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rtc_ex.h d79b95f004663f145e964ff6cb145e92a36e9652 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_uart_ex.h 4e41e93110701a53f7bc809136a4ab0649de3413 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_i2c.h c23c26b4a5705dfa36703ea8b6c5f40dffd8ab7f - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h 16b99b227562ccb1354b33482c354c1812123013 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cm4.h 3fea94e10d135f6717a70f8d1e199b010baa7f08 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cm0plus.h 9f5c937feac2936c1cf0ced43722f527a1531ca2 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_sc000.h 6c2c8dba3fe5460a7310efae010a5b7937025aa1 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/cmsis_armcc_V6.h e0a1f1bbe188023d261188754e1dc59c781fb565 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/cmsis_gcc.h 70a7d2f8ffcfbebc2f39f3cdb5ef701e081a6e92 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cmInstr.h e68945e0faf5ee8d1f027d7e8be3b4c321028e39 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cm3.h 0186b62597ed4f4804e7b81abd3b598e6c2bd555 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/cmsis_armcc.h bcb11dcd98c7ba42403d991919032dde3049b364 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/arm_math.h c93167da8e8344f98d9b28f27a857a1d41a10530 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/arm_const_structs.h 3d909ef05e1c328dbc138a1b906e914b968239ed - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cmSimd.h c6f03caabac7d0b08fed7d09ee6db8b6f2093853 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cm7.h c87716fe24718015c2d01cf913480c92e3b0b4b3 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cmFunc.h 441239dec598474dc7ab14b7283195c7f649a3c1 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cm0.h 90061e5e149725c682eb80978b557fd388191f24 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_sc300.h 0a94a9650bfc5345f574fb23a10d495f06735cd9 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/arm_common_tables.h bcaf73ba929b494e9c3f2993e975bb7de3fbff2e - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Device/ST/STM32L4xx/Include/stm32l4xx.h 0f852853d184800034247a5d0050de2038777c65 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Device/ST/STM32L4xx/Include/stm32l4a6xx.h 5d6591e31b6229f63fd06eb0de8724554b4b44f0 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Device/ST/STM32L4xx/Include/system_stm32l4xx.h 85e7e51a25b2016e19b43a83b81346b96db2098c - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/syscalls.c 9d4edc03b07fb9a306f35477b2a45b832a0b66ba - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/include/PlatformData.h fe5b2785e65fcf188d1d792ffd7c6fc9c70e9e7f - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/include/prototypes/Platform_fp.h af14794f057b0fe6e08f9ff6dff3f0984e2cc237 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/PlatformData.c 2ed430e9572654a9f6a7d1c1de12420cc48fcbe4 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/Unique.c 7f88737cf8bf4c13e5bf0e728c99ecd1ec2eac82 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/NVMem.c c1fce976f4e44378a135909f67cc1ef149b461c1 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/Cancel.c 6cc02291ef841cd08ee3118ea5c136fb69c5ee46 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/PowerPlat.c b9b1622090e7b69eda0c3f496ef773e397a0e0f5 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/PPPlat.c a1acb654a01f63360985c13e32deb69a3606c39e - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/Entropy.c c063491490aa3f9157ea6d4880a3bb5648095413 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/Clock.c 3d94e64861a183a21778f017d310208436cb95a2 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/RunCommand.c 7dabb6c802903adc4edfa6e0ba4b894cf0ffd4de - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/LocalityPlat.c bb9a6b6f33159fa31c2e47ad133c70f5e77d3d39 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/TPMDevice/include/TpmDevice.h a2564dc3ec0abc5d2445670de944311b40bfb514 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/TPMDevice/include/StmUtil.h d7040d40a32ff98b1198bae412d846d457bd6a4b - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/TPMDevice/include/user_settings.h bce98e24be98537929f371316db2f2801c152ed8 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/TPMDevice/src/StmUtil.c ddf299e517d5b6ad1395c4106f50d0261d7a26c5 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/TPMDevice/src/TpmDevice.c 1afb5b61a4b2c034a07aad4f5e11c78d9b1f0412 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/VCOM/VCOM-TPM.sln 507bf667be23c5916dad43a004b8cc0f97f4ed50 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/VCOM/VCOM-TPM/VCOM-TPM.cpp 6b81e4587698e6857f4814dce4b4d0391a2e8766 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/VCOM/VCOM-TPM/VCOM-TPM.vcxproj 57c8c0f47d2168b6955706ef677c467b7368a98b - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/VCOM/VCOM-TPM/targetver.h 6a0dc513f9c01293d6cdbe167f765c5b5f4d5e83 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/VCOM/VCOM-TPM/VCOM-TPM.vcxproj.filters 74f86a73a25ac67fc34a014747a6efeb3d44e1fa - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/VCOM/VCOM-TPM/stdafx.h 5310225c6b795c683cf6f10a15abceae11332937 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/VCOM/VCOM-TPM/stdafx.cpp f9b4aae1684da7aaee3611a970f76f38a46d52a2 - optee/samples/ms-tpm-20-ref/TPMCmd/flags.m4 0204b212240ca16f5e60f43b0a30b2697f77d183 - optee/samples/ms-tpm-20-ref/TPMCmd/simulator.sln 1cd01c0cf4c4a66ec725a1f0fccca2350024844d - optee/samples/ms-tpm-20-ref/TPMCmd/Makefile.am 194cc98738c13d785c82704c6fc8e0ed0bcc99e2 - optee/samples/ms-tpm-20-ref/TPMCmd/bootstrap 90c98d16825e38e3e8c730857334eb3678940874 - optee/samples/ms-tpm-20-ref/TPMCmd/configure.ac dabc6f784df969fbda726a380436cc15b3ae3a54 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/Tpm.vcxproj.filters 1767e2e5744eb1166945e42a8b4c345bf876c401 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/Tpm.vcxproj 6134fd9595a0db3004b3200ab2754e6060a9e613 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/X509.h 731ef0324c0883b40649fa1ce81f85f6c6f64e7b - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/swap.h d80e69a62cc5bc30321acc8ba40916ae6c11bac9 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/KdfTestData.h 09c046895d104e84270b38f51a580a571d067e37 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TableMarshalTypes.h f03b22a486395fb8481df3912c4beb5814cbd117 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Tpm.h cfb478e72c88b38989a79c857ca529c96cb05a26 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CommandAttributeData.h 0bee8bdd2a0e7cec942ab1ffe4f5a5a0819f3204 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Commands.h 58e518b99239ed12b3b9d18225645004fc7416d0 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/HandleProcess.h 0b3bdd77473b5c674385a4de1fb1ba806385ffa2 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/ACT.h 3cdb1b7e18bf92a0a11db7ba7bd87f76f7c62157 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CryptHash.h 5ee1c6c70f36b1a98a1c09e82db86bdfb94d6bd6 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/SelfTest.h 5c7992298c480a370df9665518ec6dbae0de0602 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CryptSym.h 6690e48f59d84a65cb431aedc4ff04060ce0390d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/NV.h 48323efd0b877a90ca646e264addeeed14adc169 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TpmProfile.h 04a11a40106e32d1a2c327ed2ee76d52f1fac338 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TpmAlgorithmDefines.h 040719da4c629d01698b06072537878d1ea7d2b9 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Marshal.h 6a410f835b221a8130b8be5650395d9faba6072a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CommandAttributes.h 7cbe82bc9668a6dba6a469b42f3d0b942f0520f4 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TableMarshal.h a11f6a872439861a933474fe412a0427c0730fe1 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TpmBuildSwitches.h 5d1d9bf90c4bd7e98673e597da72ba2f3b9bca93 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/BnValues.h ed8716500b6fa3680567484cef4705f9a874e365 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TpmASN1.h 94aa65d7ce788d652472e56c424a45e7769dbcc2 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/GpMacros.h c5f4ed58f4082b8a06c2dea39618e8fb10454877 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/PRNG_TestVectors.h bdb13a835cd51676ea457d951ca7433dbc57eab5 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CompilerDependencies.h 58c4efd7565cb517e7ab2c25a966cab710d92663 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/VendorString.h 144f3bb0c333db82f37ff9d5fccf48dc4fab0f41 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/SupportLibraryFunctionPrototypes_fp.h bafcf4a000318fac0009b809ac2bf9a70cf9c791 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/LibSupport.h f69660e465a1480bd79a1f8cf16f80352a60a7ef - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Global.h d2108a7734eec6c0e66394d3c12a50150c04ac3d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Capabilities.h f249cb73e1800699c831824f77261a2ec96eae6e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/EccTestData.h 09d85312988cbf36c3dd26e95988b816d1873095 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TableMarshalDefines.h b38f19b0bed0f5f71f2da37145d05356d0dc94d6 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CryptRand.h 5adbbfd2ff8e8dee66469ce1ce6f2d285589c6d0 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CryptRsa.h efc8b2228515d82aea4ea093d4cab20a7d249f7f - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TpmError.h 18af239d7a28f416247aa8dd6e9ecf28141a0c89 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/SymmetricTestData.h 6d0f1fb0d0f3b2a8d19f1ce046869d30150fce09 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CommandDispatchData.h c3b8d078373237d8e7f138c67b4f382b40517192 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TpmTypes.h 7e6987419dcd3d08639dfd3e91a8c57fd9872b5a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/BaseTypes.h cc0a6421806e68997e500be631aa81828521ec2d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CommandDispatcher.h 70fda7df3afa9fd65627182e71265908467556af - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CryptTest.h 29a46309c3fb01be084d8e8951eb7901dde603a0 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/SymmetricTest.h 23b7e6271c380c8e85532c40b58f8224ffbb6d82 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/MinMax.h 3b05494bbc0dc8e939e8026e84571fff9e472617 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TPMB.h bae04f0ac0d19fc1461941fea785027bcb9dad6e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/OIDs.h b18d3976f439634cb05a45561819d0b9b4d73098 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CryptEcc.h 11b48254afade03ed20f8c729f3892f435436345 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/InternalRoutines.h fd18d2b01b63b618061ff8f370e2033b8c4dea10 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/HashTestData.h ca5a553f1de3616fbf5052b6c38342e00959ff12 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/RsaTestData.h dc6d2d41f9734e7709dfc69708fc6287a3622925 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ossl/TpmToOsslHash.h 6e52cb65b5558ad2766ed1b90d74c6c67b8e1e73 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ossl/TpmToOsslSym.h 8f4370cfcc34bb136a67d12a14149d9cf9f60d13 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ossl/TpmToOsslMath.h 4f5f2c13cc24a386e4bbd872b04e28b04c23750f - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/StartAuthSession_fp.h 0c232e0f1f0a3ffbb6252b7dcc284e0eb5816e65 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/HierarchyChangeAuth_fp.h a3c777b5e458806ba068d57d179e56d85752ecb0 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyCounterTimer_fp.h f8c1f6beaff3089603dbb43f6bfbe4bced35471b - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/MAC_fp.h 426dee6a25a2583b6247df858ff7964ef871b9a9 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/FirmwareRead_fp.h 0a390598326789930752b0a4eb4eeca9534919ac - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToOsslSupport_fp.h 87c144583176739ed4827270dbc6b9d3abd5e813 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_Event_fp.h c0addab72ad3020cfff53f078df316c064e7cc1d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/X509_RSA_fp.h 68e113f085c014c63f20b6a810267fb29992b4dd - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/EventSequenceComplete_fp.h d4738948505e602dfd25c30c2d2127f169469349 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToOsslMath_fp.h 1e20b1d0983d33cd549b8720837621ef325c250b - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ECDH_KeyGen_fp.h 4ba84b2df817a6524144f53ad70869d329891eed - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Commit_fp.h d81b55f0818fc590e22d0091bb1d5e39562ee877 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/_TPM_Init_fp.h 033c9057731df5494aa445d61a4886cccfd01e58 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PropertyCap_fp.h a4fbdeaa426df1653196174226b6b48afe347c43 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_Read_fp.h d0e86324b120265b5227e7cf729d89e4c2768bf5 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ECC_Decrypt_fp.h 872ea306826581c94a3901d981a4e343c3c357f8 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyAuthorize_fp.h 00fc2ade3a5dc5ddd4221acf56cf8d9972c88224 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ECC_Parameters_fp.h 39d4dcf44ec35f860980866e35e51cfa327029c5 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Sign_fp.h e3e0bfa681c313b42f930b39cb3706c12188f7fb - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/IoBuffers_fp.h 9becf531f45281cd080d8ad3140178b7011db42c - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/_TPM_Hash_End_fp.h fe5b4ced7121524a956e7e2a8779f95b254062c5 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/EncryptDecrypt_fp.h 8ef2616ae42cfc6341c39bfc7d5c9e251fa4123e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/VerifySignature_fp.h f81667c844095ebcbde3be4b80103fb2411ccf0e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToWolfSupport_fp.h 263799522ef3ff9d6677847e2d97fdb59aa3744c - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/HashSequenceStart_fp.h 10cd33e9e84c65659b05a614fe22885bbb0b5576 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmASN1_fp.h c079447cd9518a4638372c0f5063406242518cbb - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyAuthorizeNV_fp.h f60fac38469c28712e358afb8d737112e7c8462e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Shutdown_fp.h ce280d1906b146f860d0548256feb7020cd26383 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_Allocate_fp.h 300bf426a8fb3f09d3f7536ed32dacb0bd9c4628 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ObjectChangeAuth_fp.h cd7e7991d07683dfac8d62da427618dd0b1bc1e1 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_SetBits_fp.h 21253e9f491e5c3aa9285fc9b5ead280258b2349 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptEccKeyExchange_fp.h 4568199cccb437653f262a20a4ea2790cc2ece54 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptPrime_fp.h f27e1a7967e61ef8bf65bd75de47cc20c76e6109 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/X509_spt_fp.h 8fb75dbf117c7fb587355b323ad006c34e9bdf1d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CreateLoaded_fp.h d7c909486a97798ffe4f88811bdde662f1efbb2c - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyPassword_fp.h 06772c3dacd56547129c09c8f9f6df1379a19fdb - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Clear_fp.h ab94632d4ded278cb4f2ea153cc8f08f9422224f - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptHash_fp.h f97a3facaa3598f5623f6b88e79c27b8d291adbe - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/RsaKeyCache_fp.h b5051ade5493dc76c56085d8dedd7ba18165b13d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_Extend_fp.h efa6e3cd6c13f77fcdd2f0324b56f4bef02a7aff - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyTemplate_fp.h 0cc1fd2ec5abeb0f1e845c49aaa160d4e68a85a1 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/EC_Ephemeral_fp.h 7761e46cea834947efcaf77d4bd95b35090d4f8a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ContextSave_fp.h 8e49bb3ca7117e6e780bab45db67db0ead9c5ca2 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TestParms_fp.h 300b61a4e1ef2d90038d34101216bb4f4f438d57 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyPhysicalPresence_fp.h 356266471ea0cd56744fa25a7f491dd297962e09 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/IncrementalSelfTest_fp.h 4d86f90ac8d6bbf2bce7ad8624c1dc2b3bf5dcdc - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmSizeChecks_fp.h 7b4a1bba6d26a63e4053870aefe57a5a989c9ade - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/_TPM_Hash_Data_fp.h d04a57074c5a6696f79ce639e9c000f5afdda980 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/RSA_Encrypt_fp.h 60a578ecc4a1311da2cb2d314599e50eda98ce20 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ClockSet_fp.h 0e48f14c10cf6cce68174a223525dc0d4881c586 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyGetDigest_fp.h 079dd0f1840e22baed846c9e02ebe113c11b5cc0 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ChangePPS_fp.h 4496b790b236610306f95697b6d469d62f55c0de - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CertifyX509_fp.h 7c4c000d51e015f75eed6d80280e1775c39f389d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NvReserved_fp.h 46313fe32eab76dd78587ec08d8197ceecd05aeb - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptSelfTest_fp.h 6a189ce8aa6a78a130802b206df376563a9bef79 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SequenceComplete_fp.h f451b90022116d27da1d8daa055a756cfd2c7433 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ECC_Encrypt_fp.h 8137948f4115d2d4d54323a472d93d4ec6fa4d50 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/GetCapability_fp.h f36fa0be0029ba31ccb3df0c3708912eda650857 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Import_fp.h d31443ea45f0f2036bb833bb61864921aba958e8 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Create_fp.h c459ecbfa01a1793393632af787ef0449d5c3409 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptDes_fp.h e062efc91d99f491e381087a02b61db9dc73fdf2 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToWolfDesSupport_fp.h 74c9451a504f6cf1c95ca2d65b544d5c2fd05271 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyNameHash_fp.h f2718ee13d5cf19fc376ce3c4832f2b01aa99516 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/DA_fp.h fe973ac240eb632c90e84f8da86116fbbd38d2c6 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SelfTest_fp.h 9a38584e2a30c9b5500393ce93e9818dda8f5d72 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyLocality_fp.h e6492c7ec627a702d359ea6ae8794969f786c692 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_spt_fp.h 070f1d957fa166d1382a794efa2a8c20d939d5f7 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyCpHash_fp.h fdaf877c881d86c0f02329d28429fad0f8307ff7 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/RSA_Decrypt_fp.h 44ddd229666c154957ee9376cf1e97248f1e34b8 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Manufacture_fp.h 0fdbef88eafe31c268daa16552451e6bf681fdef - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ACT_SetTimeout_fp.h c82c8ae619c5d23244bef504b7fea485ccb9a91d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/GetTime_fp.h 9a33da54fde72510b33d0294d27b8cad4580dc27 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Session_fp.h 991c478c0252e36dd9106ee335303bc77a90966d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SequenceUpdate_fp.h 914d7b438c78e8a7242539c0cbfe573751cd7c47 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToLtcMath_fp.h 3e5aed256a4e7a1fda0a90fcfe86ec3531bbcb43 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Quote_fp.h a3f4d21d0c5c06d44cab05bec5bf92983bafc3fd - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CreatePrimary_fp.h 3c2afbef3c046c3160a4ea2edd1140f5d954b71f - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Hash_fp.h f74b75d1e6ff70241553a77c88f91d61c4a26ec2 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ChangeEPS_fp.h cb1eec55cf276e26c8975988e7a423c33ac5f10f - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Duplicate_fp.h 1fe54f80c4cb8cce2fe745633c3010c7bd74dfe7 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptEccMain_fp.h 245146b2f725f65a40c489a792047786a96128b3 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Policy_spt_fp.h 7bc81e20a06653013e4acbf2174985473486bac9 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Hierarchy_fp.h 06d4cfb6780878c42481e4a77c5308cfafca5837 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Load_fp.h f74d147bc6c976470de0070c75351df3aa04b120 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SetCommandCodeAuditStatus_fp.h 5304584889d4d650f0af1712e0a977aa2ea0f5be - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/EncryptDecrypt2_fp.h 5a4039d7f94ae60ce02866c46425571dfb8006e2 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/AC_spt_fp.h e9a553efde26f94f58686193a7e6008b733519da - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptCmac_fp.h f1ba19c3c43065642a6af8fa5895220506394517 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToLtcDesSupport_fp.h af0ede8240131c95b2285547640960087becef7b - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Ticket_fp.h f5b68b2634bec606fd5bd4eec855bc0ab5bd210d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Entity_fp.h f4427b665d78cdc3834335573899fbb6350ccfd1 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/LoadExternal_fp.h fdc545be48642a8de20e4fd3b7d30084222ea399 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_Read_fp.h 225763ffa0645413e5a490914ecd7a9de8f99a50 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/GetTestResult_fp.h 3c59906bb8361d9498ea673335e88b92361d6f18 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/AC_GetCapability_fp.h bbd8c64c38105cbd75fce5e356241e0d42b3dbc6 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_SetAuthPolicy_fp.h 932e66bb1587712ac42bed734b088921f4f6f911 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyPCR_fp.h 1a5420f04ea7e3e726390dd2ff1bff61fd988102 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyNV_fp.h 87d27972c3bc15584593dd37d0ef50f0c73cfcfb - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ResponseCodeProcessing_fp.h 9667984e3855fc027a45cfb981949f64b2a980a2 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_SetAuthValue_fp.h 765379d25d1438de22351a96a9820bf9f67c6369 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_Increment_fp.h 6c1fb57a8caea7622cc7cda8dbd7418164257de4 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicySigned_fp.h 54c2a1e796afe1f9a817b5e36aee8e51edb67faa - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Policy_AC_SendSelect_fp.h 185e4f5e8e6ec8bc7c973a7e77db33409494980f - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/DictionaryAttackParameters_fp.h f6d26035cccaae7afe8b836b2985803184981afc - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToLtcSupport_fp.h 9e0e5f492375fcc68e65dad4a397b231a504cb60 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Object_spt_fp.h fea4b12eaff5c6e50481a9887b53037725a2b164 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SetAlgorithmSet_fp.h 906c4e6e7787dcc7647de13894175b9b8c78c94a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Handle_fp.h 7f1299d217585c2efab081499e77f630a0080127 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NvDynamic_fp.h 71ed6694c0ef2f14696a671067200c134221da42 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Marshal_fp.h be6e44fe64124ec47e14bf135c7237b8480639c4 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/BnMemory_fp.h 062e68dbb60c05523086cfe239dbfeeb8fb00b47 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TableDrivenMarshal_fp.h ffe4657deebfe157a4a2ee653cedf9bcb8fa2aa2 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/MAC_Start_fp.h 615b75cd87214bebe2493a06d39fc014fd87a003 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyCommandCode_fp.h 7a31af2eae74a929f10edfcc4c24a5da80259da6 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToOsslDesSupport_fp.h ff21254543ae6a56beeb71d3af23f8ca5af1c641 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Context_spt_fp.h 1f07c1a9db3fbb122f8ea251ebdd8594b931316d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptEccCrypt_fp.h 4f57f936b4064fc13f7b608cb7931359c8248413 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Certify_fp.h 2530b56f366d5693bd4b9788364595dd64ef8bb1 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/StirRandom_fp.h bd088f3ed8a49ffeb79779805d7fe8f5fe429e6d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptPrimeSieve_fp.h 809a441e0cd662f3edc35bb48c71b70fa4de923a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/FieldUpgradeStart_fp.h fc5fd2f87d6c7a171ac18ad6e702315be926ff5f - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Attest_spt_fp.h 8e12dde0d8b6a4a6df5111e1cb35070963a9c1ab - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/FlushContext_fp.h 8b01720df595ad116744109fe662ac1041ef2d17 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyAuthValue_fp.h 26d0cc4fbdb4c876f246cd35c500de0df11d004a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyDuplicationSelect_fp.h 3b1f567f4eec7189eeb071adccba7008432b2f1d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/AlgorithmCap_fp.h 194c22bd1d2268c21271034395c6e5c7f3456317 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/HMAC_fp.h 4eb345137b18f67c6d6a92362de243a4470b189f - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyNvWritten_fp.h 3c4776d65fe50a6b4f993be0274bfc9af6a3788f - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ClockRateAdjust_fp.h b6d95fc4fb41098675bf252b54fd9f70e151396a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_fp.h 398b220fbfcc188a24581dbdc0233f38cf46da65 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ReadPublic_fp.h 5f3c95f7f2d37e876472a869c5744b9f2836586b - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_UndefineSpaceSpecial_fp.h cd64ef63467eebced0395ccae4075ca03b9b477a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_Certify_fp.h 1cb2a688416c6bbadc8f136f5cd7ba4f41e6a908 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CertifyCreation_fp.h 189603b73c164917c3ad6da3e57d43795df47e49 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmFail_fp.h 181d669752be56b7d098c0e2b997e83bbf4e3463 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToMbedtlsSupport_fp.h 50d60105aeb491c363fb7fc71af8f6d184a8ddb0 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SessionProcess_fp.h 342bfded66f61b70aeb3d6535cb587da5c084190 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Startup_fp.h 657d7a2f6be74009fd6ba71259a0ba9db9a5f9b4 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptRsa_fp.h 30e2baf658cea26efa3f65366091f18add1dd3e2 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_ChangeAuth_fp.h 70caac4f95082012db4c203616bedd8902a33e1b - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PP_Commands_fp.h 705c42624a99f8a50f98e73d8e689dfb980e2353 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_Extend_fp.h 62167537419cf517ebecbeef3a3f5a0c1022339e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ZGen_2Phase_fp.h 423a70459c7a42197b1022dc4985f46533df4f9c - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PP_fp.h 0db82ff3316ed8f8a4f35ac28136f4534cdf8ada - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_Reset_fp.h 4b3379ea7110dd195658a8bea5a69f015634fa2a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToMbedtlsMath_fp.h 4014e8a2dee7e34d380f54a9f63e57eb084c7e38 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyTicket_fp.h 33f109b5abdbba662dcfd9adba3ee83d6f5761c7 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToWolfMath_fp.h 3eaadf88924cb87a0f87197e56d730d10aa4bcea - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/AC_Send_fp.h e2bab6b783da540ebed7c7744c2ab12f96de3a6c - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/X509_ECC_fp.h 9208541836c9bd37a1ecf8b8da894d2d06caa429 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ContextLoad_fp.h 3a2df2a3ba359f45c72afc5477feaeb04c040911 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptSym_fp.h e1a70369cd10c91bfa80cabac0164abae4071c00 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptUtil_fp.h bcca270ebd95b6c36bb026701c1fc6e10554269c - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/AlgorithmTests_fp.h 64aa9231cb6f99292517ddf87646f4ec58112fae - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/BnMath_fp.h 1dc8a1b1ee77cdaad11ae24d7c9e233a1aa179ad - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/GetRandom_fp.h d91913b01b764e0449460491497eebbf88f9f916 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SetPrimaryPolicy_fp.h 3fa7b7eff4068d80739c460f99deaaeb38dcbfbd - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_Write_fp.h 1f5d61b4bc666bc9e2c7a2b2340981780b1d5621 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/GetSessionAuditDigest_fp.h da0cc9b12038fa5755653d91b6af905656867d8c - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ACT_spt_fp.h cb593754e54997bfec26b244337da487832a169d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Bits_fp.h 966a94c84420a6e831b2345e42c2a1b5208935ca - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicySecret_fp.h daf655f7f9d8e642540ae12f919a65c9e3272999 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Time_fp.h 8c79c59ab5b57268d7b68edae092db9e1da1b272 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Object_fp.h fc302c9e27b645c41806d3e0314fa5af086ba321 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CommandAudit_fp.h d7ac37a61726d7e3b2733f8b704489a828207d79 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/EncryptDecrypt_spt_fp.h 5c6bef2af8c42ced4e3549272d93b6d9a7abbb4e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Locality_fp.h 94e53599dcb7a66ec20387e0622c76308ffa7518 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CommandCodeAttributes_fp.h e78e7c727698052ba6fd837e2274a99ea439623f - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/HMAC_Start_fp.h d688bd13f2834c070a6436dc0eb7a8ef69968ef1 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/DictionaryAttackLockReset_fp.h eeda26581cdae3c60f7b85d412d6e722fa1cca1d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptEccSignature_fp.h 18ec7d3e9e1a2b6819d68862aa501f87cf313e57 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_ReadLock_fp.h 1fee483125e847c0c6a692a5d8bcced1cfd2f968 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/GetCommandAuditDigest_fp.h 65f6077d8ce98912da5a797f9cb1a618663f987e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyRestart_fp.h ff4177b6562723e9391aa6c1cee96acdbd5f54e5 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ActivateCredential_fp.h 6a98f30011aab15ae4a3e2f4a5f18a678003d64f - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ReadClock_fp.h dff750cbe8395a88e93634e511dc2c2ff71d28ae - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/MathOnByteBuffers_fp.h b9702a44eb11019d3a4ec6675ce4e38e67221d9a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ExecCommand_fp.h 06199d37140facc7d34c4897130d896fa683bf3a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/FieldUpgradeData_fp.h 46dae84767e488ee05b03d268bf0077488f135fb - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Vendor_TCG_Test_fp.h 966015a1f338b6ce76df6dd119a899c8dd5193a0 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Unseal_fp.h 0a1f40864a1114ba7310efa53eec36ff9ff0d0c3 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/EvictControl_fp.h 6c15358e6e765bb1709933086621bc6de87c8324 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Power_fp.h e4c92fb55cb82f8c0c8bee37aa8e6bfc27414535 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ClearControl_fp.h a3044ccd6ff15c5f98f7e3e928bd21ece990f192 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_ReadPublic_fp.h 385303ab908baf98f40aaa1773f283a2eaf47fdf - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyOR_fp.h 81fa16e20941dcace05e6e8cd07213fc49a61045 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Response_fp.h 1e6063cb8570108a24316b1d0b0a19f8d3fbfe8e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ECDH_ZGen_fp.h 294a8c44266ef8fe51719e7f4aa2431c106efa4c - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_UndefineSpace_fp.h bda7a075bd3ac2b5484c7ab74c9a1149331b1606 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/BnConvert_fp.h cd0104a0d1225c54870a961051303400679e6f18 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/_TPM_Hash_Start_fp.h 5bbc5c70ebc57d409d90c3429cd56b9b5ba41bc7 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Rewrap_fp.h 4614c9b4ac558792b4bca4a00db55929090dcb8a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/HierarchyControl_fp.h c334eea2de454d94ebf0fcb31d0a0abd4478e222 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Memory_fp.h 9df5275bee6405837a4e152739b4caab9caf9708 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_GlobalWriteLock_fp.h 4cee80ce92fd1c8adb25144bd0e41b0e9cdbbec1 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_WriteLock_fp.h b432f0167cfc07f57f8eefe34ae9d371f0e65f1c - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/MakeCredential_fp.h 9e65c289c6e006611fd88114375bf5d690b38d37 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_DefineSpace_fp.h 0295a03af3062947bf7f4b6b8630449aa099ab2c - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CommandDispatcher_fp.h a306f5aa9c06af0466100491598149650dfdaaa7 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptRand_fp.h ba809abff8c2bbeab31d3bf32837b04784fa1b5a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptSmac_fp.h 83f5aa1e09b5cf7f7e9c963a04924be2d387ea46 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ltc/TpmToLtcHash.h 9ac20ce300cd3be129fa297a4a163f3fa3f1eba0 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ltc/TpmToLtcMath.h 7c782bef7fc2962fd03c896be5358aac325fa276 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ltc/TpmToLtcSym.h 48edc2e51ce501d43db4723d8322b229fc0eda1f - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ltc/LtcSettings.h 18938ceb070982017d5632c8111ccec6d8717bbd - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Mbedtls/TpmToMbedtlsSym.h 392bc93b6983659b99c8b56b15805a38ac333db2 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Mbedtls/TpmToMbedtlsMath.h ff17ddc4c85292ce6f01b76548e25b0a98419666 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Mbedtls/TpmToMbedtlsHash.h 64aad5263d919aa145dffc96a4941c942d70691b - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Wolf/TpmToWolfMath.h 21b31bbdb64ac04aa1f112c364cb48c84dec6d73 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Wolf/user_settings.h 618c984b216712a3ed059461036bb34c4833c38e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Wolf/TpmToWolfSym.h 11cc83c54cb1323456bd8f3b0cb56de7a5ea6952 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Wolf/TpmToWolfHash.h ce4065d5dbc369ef2260cfa2e091a9cdbad8ffc6 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptDes.c 8b5eeb7ff5530df4bddc9efe348fd45d8609c6bb - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/BnMath.c 87697819416bc9f6b5f4eb7971686f0d03d6cb80 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/AlgorithmTests.c 3fdc1e98645d29e1259c89193310a10565e0c381 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/RsaKeyCache.c 4958b5f51bffdefa5547f7e727a876d9490fe9be - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/Ticket.c 3a3ddfe5fe7f68485fa4470ee618469d5d1fb33e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptEccKeyExchange.c 6ed45ed0c56d83ef758a7f2c862927bdf71b156a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptPrimeSieve.c b5d37ef8c950f8a169f5a9ef1e7b4328d2899401 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptSmac.c 9d5ee1ec8336ff2b940ec56b380b95b98f41a104 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptRand.c d34cd17447bc01028977a012463d65f135f96fcd - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptUtil.c b1a8ebaef50f97ee33ecae24d5edc0aa580c8ed7 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptSym.c 447f5d6341ed6ada7a8f30e830eb7464046b8e5c - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/PrimeData.c 368e618850636f255e9e57c0b139dcddf82af1e3 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptSelfTest.c 3a9e9a081c926caf63db37bffb80cda40c21ec2a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptEccCrypt.c 1401ef177f3e3bd7de55d6e5f0f8cf2e3ee71cf0 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/BnConvert.c e81147da24030ba21f12edaf9d1917661c163be5 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/BnMemory.c 8cc48da41f271b6527a5855300cccd7c4094b96e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptEccData.c 9b79ff2b06c224c971f1e1e048045cf767db0830 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptCmac.c 4b29d8a36dc33ffc4d29ebc5fa799d6d99007ba4 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptHash.c 22eb0ea9add313f80a3ec949c2178c80c14bea52 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptPrime.c c68e7e9e168486bd7ee10b85712f8cbd28c8c2c9 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptRsa.c 0ffb452a1717483aabfe47a9eeb7b99ac06ded4e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptEccSignature.c 61b0cd7757e3673f4054a6b67be5df89fa6c78e8 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptEccMain.c 54022276bfb56c330602829897c3fd1950feb456 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/ossl/TpmToOsslSupport.c 08b72177479e566714d6fef52816fe3b32322152 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/ossl/TpmToOsslMath.c 480e6f783ba16658f88981764ffe2f9218ba8f83 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/ossl/TpmToOsslDesSupport.c aa003ed14dfbd14f15c33f8c85d2f780947c7624 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/ltc/TpmToLtcDesSupport.c efd79a528de091dba68dffefc751a0a688423b93 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/ltc/TpmToLtcMath.c 9c1b3604bbf2860b0d80a657410e2a029adba6a1 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/ltc/TpmToLtcSupport.c 57d49fcf7d7e75f0f36db31891f577fe559dfd9a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/Mbedtls/TpmToMbedtlsMath.c 4368ae6f39b8b331277add014bbff034b940d525 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/Mbedtls/Mbedtls_mpi_Ltc_desc.c 4613687d53030af00a6b329a71087cd94acb5f11 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/Mbedtls/TpmToMbedtlsSupport.c b0a0e725f466c5f614f8bda31e08f9a919f12fb1 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/wolf/TpmToWolfMath.c 3af0edffcca6f089325ee30b97c2fb94e3b291bb - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/wolf/TpmToWolfDesSupport.c 8eb628b011385e5d70d3cfde68069f665ad56e51 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/wolf/TpmToWolfSupport.c f030593dac7c1db3e6e839d0e1d7d0ac8945970c - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/wolf/wolfssl.vcxproj 466691e67c12dd9a679781b63234956dcaceba1d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/X509/TpmASN1.c 04b37d6adbf120e357ccb4678e380a1802931de0 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/X509/X509_spt.c 5c354c7223a81d7915882b573c56d94861eb2696 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/X509/X509_ECC.c 77b2c67dc99cf0e49e4cbabc22dc9acadf309708 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/X509/X509_RSA.c 46bab656e2cbbcf766c84d400690e11877f8a515 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/main/ExecCommand.c 0334c584b4a788c6fa56ca81ee53716501df41b1 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/main/CommandDispatcher.c eafaa29ba3e6f0cec01550636783df940a842bab - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/main/SessionProcess.c 82f676616d720a25d5644ecc7960b7eeff0389d5 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/TpmFail.c ef0426dabd8f706a78db06b58f8068b38ea9168a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/MathOnByteBuffers.c 0b4b574b83e692740b0c4e5d62635fa967d01e85 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Marshal.c 2c65acd9bd5f6337e5abd55c998395192cea06e2 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/ResponseCodeProcessing.c 38de6a36d2444e1ed0f3bee1d4fa5751c01943fc - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/TpmSizeChecks.c 58ee288becbef146b8dd5c5429f456388af332ef - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/PropertyCap.c efb8e8833bd517b3b9385257aed75aeb07b5c4ae - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Entity.c 20cbfa127bd4687094564ecd2ba0d71c11785b92 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/CommandCodeAttributes.c 42ba5fa4090f7900b93f25610272c5d2744f92fc - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Bits.c d1f11e405396fc8a356db922fe2cb0c8f654fafa - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/TableMarshalData.c 1ba30fb3845df79d51ee779b4eed9d9b7d1a3746 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Memory.c 94ba9200336a7684a6fa85ec99615753998935fb - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Global.c 9fce7edfb51de4c44936f9d5f46af956fd8e86ce - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Manufacture.c 40037ba43bb2780caab6c9320b9428a9e50c179e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/AlgorithmCap.c 6e7dea780558ebfdd0b1668661ac43fd7e876dc6 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Handle.c b80579004bf66d76c34c31b4fe0ba65e1a34eb8a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/IoBuffers.c 36be33ce745c22699c4e2c5fe1eb19df4deac267 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Locality.c 5d749f54ac223562addbb57a4b3ece73eb25b9c4 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Power.c f8b98f1215fd1f432f6e12fc63cc39e8bdd8be20 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Response.c f117763dee48fbe30eec672134d8f4c747362762 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/TableDrivenMarshal.c ebbf99f5b71a40e2dcb3b0718428993ceb092ea7 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/PCR.c ec1d7790053a5109933da61c97434e47e326bd4f - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/Object.c 74b6eb8868ae67779b9cd920d12e7566d91ee613 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/PP.c 6f80821c4cecac735c594a05787bbed9e95b3079 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/NvReserved.c 391883c2c03bebc1ae73eaf4532d5329e15efbeb - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/NvDynamic.c 8f0cc6cde494e0e8e21ea01a914f39d3f98bf4ff - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/Time.c c8236f84f180f2a66e475945307c6aab4e482bcd - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/CommandAudit.c 8d9c13452adc813895f72f470b65117e0e51db1d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/Hierarchy.c 26ddeedbe4bc042989c17d41b3103a7de8ac1aa6 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/Session.c e04ffaaa0b2a9a182d315f2296f0f850fb06f440 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/DA.c 956f4eb8bf2f4bf527b634e5a10d21044d4a92e7 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/DA/DictionaryAttackLockReset.c 5b5d449bdc2e71ff8057f449d9e5d1ec8e1da5c3 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/DA/DictionaryAttackParameters.c e877361fbd9ab03f37548f2b969f26c1e5d1a986 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/CommandAudit/SetCommandCodeAuditStatus.c 49d503f437be88abb3f8fe4e3843e150d3cbae80 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/ECDH_ZGen.c 4c9c1d8f06b9befc1dd89a87aa787db5a447a776 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/ECDH_KeyGen.c 36c60811874f45b8d6a79f79937c751c30988a07 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/ECC_Parameters.c 0b8899ea87e95427aceea6603379cd4e0ae8dd48 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/EC_Ephemeral.c 49f8fe178b8e7a87b01c6859413053a68c12cda7 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/ECC_Decrypt.c 9711def3ae76eb059ae7e10b3cbc85227c5d666a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/ECC_Encrypt.c 748f01adc89b2fe04ba4a8ac53d4bf345cc57c50 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/RSA_Decrypt.c c2c0552d7494c97ddf408939c954951b1dc3033e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/RSA_Encrypt.c 44fb9d7637a41f76fd3105365c223cca6d5bde79 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/ZGen_2Phase.c f523d6e9f92f556eb67c7192a4a212dcd21cb783 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/Unseal.c 1270d2675a052e452604abf21ae7d1e7ce9f055b - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/MakeCredential.c 96d90b66981dcfa3e2a05c0cbecbf34b91a65e14 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/Load.c 1bca8c7f48e122b595f81ecb428b54ea1dc50742 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/ActivateCredential.c f020bb04aae416aeb7c1189d6ed5c79fb0a6e345 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/ObjectChangeAuth.c 5d5beaf98ae2e96ed9e9c00ab6ea26a57c78204e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/Object_spt.c c09f0b9df15e12662d6ad78a68444a67bbdca8eb - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/CreateLoaded.c 310b0898c923667f453d165e0a9926eb8d346a6f - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/Create.c 64d5919c672dfc44fc10b7b069c2c866cabe82ac - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/LoadExternal.c c3b9c77f50fb64add3975acb54afcb9419a522c3 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/ReadPublic.c cabe90d3a0189bba8f0ec6be382ecb611e56d766 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/AttachedComponent/AC_GetCapability.c cf6f2db7011f13d73a939be1a73a566edb53c5a0 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/AttachedComponent/AC_spt.c 8a5d00c0ff144f96ffef9e3e2ca6fdf521a138cb - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/AttachedComponent/Policy_AC_SendSelect.c fbaae98602eedfa517257f018c3ba4cb424d9315 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/AttachedComponent/AC_Send.c 973173f0edfcf6ab2d80e4380b6bb78bf08119a9 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Context/ContextSave.c 96b1b4082707dddfd7fe52922b12ec510b3fca8a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Context/FlushContext.c 551606340bbbbd796441854729786c2c94a53f9c - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Context/ContextLoad.c 4c3fc77c75e0b5742471eeb110d6e6fabcb65731 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Context/EvictControl.c 733767778ac50dbd49ae6b97c045e5b0cc37046f - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Context/Context_spt.c 09e831c6316eb9fcc1350c6072797e7c9c2aa283 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Misc/SetAlgorithmSet.c 4fe85236b0efdf18eeab5b29cc23556f0279c206 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Misc/PP_Commands.c e7a9e652bb4ac5e85c8e1db3d4e360db21571d1c - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Session/PolicyRestart.c 5bacab95011862392ab50c7063fbd39a71e4e1f1 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Session/StartAuthSession.c 68daa6c7c87031c44832452db4f633ccfefa061a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Startup/Shutdown.c 19dadc62f6dd24fbe1617b47f8643ede9afbb6d8 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Startup/Startup.c a85083fd1766596d284bfcda7878062e4f848d31 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Testing/IncrementalSelfTest.c 043f05cbf29aaea72976bafa119fe4c6ea52947d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Testing/SelfTest.c a04e1f890e0dc85c03762a0f93da8933cf72eeb8 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Testing/GetTestResult.c 39cef4fdd45cfae84dfe0b10421a8d22e48040bd - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/Attest_spt.c c5b487407768a4cc47ce3e439229365023ba38c7 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/GetSessionAuditDigest.c 06e3406314f390af840548aa1e2bffa1500d0f38 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/CertifyX509.c 39d8048f7d7f6324dede76816b9cdce1895eda8a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/GetCommandAuditDigest.c cccb8929c774f62ace8cc0f950b76aabc02e3f0c - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/Quote.c 7c3924284378b21001f6120874f7286b08bcab70 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/GetTime.c 0581c121a0ffb4b5516cb531fe622ce94df07d53 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/CertifyCreation.c f7ef52b7fc3e51ac574ad1711265b80fae74a4b4 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/Certify.c 60025cb0327048a1655b2293a91790ea95968b89 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_ReadPublic.c 9b707597db32549caed72d79d4348286c2c8c84d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_UndefineSpaceSpecial.c 9b54b8fc55f8ee130f13641cba871c467c2f6539 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_DefineSpace.c ff8f74e23cf6637980a1019ff15003dafaf84a91 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_Increment.c bb0a22e25778627d4f64d217c94007571f56ead0 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_Read.c b41bf18cd2dfd6937ebd33df85106bbd74c13966 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_UndefineSpace.c 34b1f44147ff14e1982afaf5ad498c710d71c461 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_Write.c 0f132292bc781aa375c73d7cc156d5ae2296885a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_ChangeAuth.c 4018d34a03f1542e2e6e07fc3c885b9a7151709c - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_Extend.c 9dce4f4ece8e8dc71a031b70d4772c43260808bf - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_spt.c 274e0fef208e3559e364558f2505ab960c569d05 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_GlobalWriteLock.c 7b599ffb429ad0c3f2893a1435dc227ffbdf9450 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_WriteLock.c d5100f5da31705c1061b5c4fe009738a90d6991d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_ReadLock.c 328ae9a3a794b68bb003885fe34eea037f074d2e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_Certify.c b16f3b8589cb0d5de3ede0e38c3df9566439dfc7 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_SetBits.c 1195dda2bfef5b2f0ebf5d9dd0c1483e693feb73 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Ecdaa/Commit.c 83b2aab8bfa4d8152b836dc79e649d2f9df8b428 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Vendor/Vendor_TCG_Test.c ba06c2bbc967f489c0ef81a52ffd5bc61d854b10 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/HierarchyControl.c f3ad6beabba99f2d302804f9e4040e30edbd168d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/SetPrimaryPolicy.c 3c6a9b5585e15ed5d931d520b13f18d3cf7a6427 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/Clear.c 2c0105db6fabf84cd5e1264af61fbcf8ca44ee4e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/ChangePPS.c 3b58be2b254ce73d0a09c4f40181e757b5801583 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/CreatePrimary.c 7c066a0b22f5047720515190002981c2bb4f8559 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/ChangeEPS.c e40fdd1540746ada2ef6193fcfef5264945f440c - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/HierarchyChangeAuth.c fb72b54a400108f311ba215a95647b182ec390ab - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/ClearControl.c 0cd97f9c3068ce2beeec5cdbe59a35195b92f647 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Symmetric/HMAC.c ed64e70b14016b3e27d91724d8fb78a86c84492c - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Symmetric/MAC.c bbf716723d7949b6ad949afb4c82e74f200e8c24 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Symmetric/Hash.c a30e4e882bab65b23bad83718f0df3a86be8b240 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Symmetric/EncryptDecrypt.c c41a91e8a169399e5c3daf950f1903d22ec91757 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Symmetric/EncryptDecrypt_spt.c 40161da967ed914f228a3aab5100d896da33824d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Symmetric/EncryptDecrypt2.c 73735fc467c6d10ff8de1c9bd2fd6048cceabb71 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/Policy_spt.c 48b353b2ebd17849912faca615aa97d50d2141b8 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyGetDigest.c 40cf33b0b774dae8c6ccb5d65405a7e54903e4c9 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicySigned.c 1e23cd2245b273f4e2d7c559727c9b160b0477e5 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyLocality.c 8705b3a606961e1b05c0d5dd32765309a325ed52 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyCounterTimer.c 932ed2d5107b414d84be1be9a2a851f4e4e8b347 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicySecret.c a05c262c1e6127b2a49b9489b60850b35762bd26 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyCommandCode.c 753243158f166cb485c6e7a3471c6b4b028c68d3 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyNameHash.c aab6431ac9d4fcce238593514a9cbadf4b9215ef - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyOR.c 88c03c37cfbed2aff36dfbcf94b95177d54762fe - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyPCR.c 588a8d77a584bacab70eb45e8653cc26182caa9b - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyNvWritten.c 1bfef4dab67e4efb29fa68b09e96d2627fad2be6 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyTemplate.c d0a42a69ce9e7024add491c99d63f917623c341d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyAuthValue.c 866b4da196d99d410685d625146c5262614a1057 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyTicket.c dcaa8cea72af93d8c5f3d8a57089f1fd72ed3e74 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyCpHash.c 7a3b44021510f326081fdbe1076c06ab481e2a97 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyDuplicationSelect.c 68f8914ab2417a723a81d1d2b51282e8487cd768 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyPassword.c ffb4fc98afe39eaf79abbe1a21e1f9cb4f142d9a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyPhysicalPresence.c ded5971153e324b8b4f6aa95db951d09de1b2ecd - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyAuthorizeNV.c f961c5947f92e32233dc32e62249202b2cd07570 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyAuthorize.c 19218fe30830606f6ec36f65abfa5e6dc61a2d12 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyNV.c 5286c36046943f4d9666a1f20f762f249903529a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_Event.c b85eb5bb0cb8d3c1f3f066d6592d520c64a30028 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_Read.c 1723fd5edd58d258867ce07a1e6cb192a9134684 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_Reset.c 567fcf447739ce658f12b708c9e630adac2c02a1 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_SetAuthValue.c 85b8105ca22c96106141ea7ca062c4f3b55f288b - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_Allocate.c 2f0d5d80986eab6a2f480f5a119aa292574a5c43 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_SetAuthPolicy.c 1936c8a82923b6cf455ae9a32086f8b47e9fcec5 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_Extend.c 131c53ad4309da75d2d0c0fc48b42eb85ab892a5 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/HashHMAC/SequenceComplete.c 4998afedc6c5beb0fa299bee383dfe91fbc7de4b - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/HashHMAC/MAC_Start.c 1d73e64673af7532369bdea0b79d8b3b9c2809a2 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/HashHMAC/HMAC_Start.c 182701b3fd417d0a2f45bf6e0b05851de8424950 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/HashHMAC/SequenceUpdate.c 6a557c5edff08e22d2de7967bfb737a1a26634e6 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/HashHMAC/EventSequenceComplete.c 2c67c87e19679660cdb2f8d32954da97e14f8079 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/HashHMAC/HashSequenceStart.c 2be8b39f7a4a7cf50977aa0ac7b44554f06e29df - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Duplication/Import.c bb1c1c731518c7698413695ba8d8e16627303ea2 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Duplication/Rewrap.c 93626622fb78f36fff350c70113da9af69da76fa - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Duplication/Duplicate.c 77c7e04182e899c143665ccc8d47f7ec8205b288 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Random/GetRandom.c fbfe1dd32c3d5e790448ead7346654838dc3e482 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Random/StirRandom.c 1d02ad4911a3717f8c16a00147f895e042001df2 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Capability/TestParms.c 705d003f4eda4e14d5adc59e0dbd61083645812b - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Capability/GetCapability.c e9fb4d674523f5fa0950178867220d9afdc21e6e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/FieldUpgrade/FirmwareRead.c ac9421f2de85e45f1fdacc55df00ee912f582661 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/FieldUpgrade/FieldUpgradeStart.c c5d528a495db164b7eeba279c3408a6e5864080b - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/FieldUpgrade/FieldUpgradeData.c fcf83214d3f3c1296dc883a93dc91e189c82b88e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Signature/VerifySignature.c 523dab0ff81bc5d2333604b81b8c655a72fb5957 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Signature/Sign.c dcc4083b045cf3765b91c539f299216534cd07b3 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/ClockTimer/ACT_SetTimeout.c b85fab62d41638b1960347ab5db0f5c04cc40b48 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/ClockTimer/ReadClock.c 36dc3efeecfa5aa7c6ea85f3634adb5d15a3be00 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/ClockTimer/ClockSet.c fdc898681b4fb8c7223334448233c6e83fa470a6 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/ClockTimer/ClockRateAdjust.c 578761745c2b6d96650e066060a08eeedafe6de7 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/ClockTimer/ACT_spt.c a68f1d79f27d6415a6946a5cad9f997591b471bf - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/events/_TPM_Init.c c4e81a39b2206a46fdfcb4d7bbf14ee4307489c1 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/events/_TPM_Hash_Data.c d209bee5b5913f0b761575695c8511fe6722f515 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/events/_TPM_Hash_End.c 6a0f30c4781067b8428260fe466e5d6e8d808842 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/events/_TPM_Hash_Start.c 29c82ba9ec61627d639ba195206aae5986b6d713 - optee/samples/ms-tpm-20-ref/TPMCmd/Platform/platform.vcxproj 7aaa3dd88ec8382f37bf795db6b66041ec21d6b6 - optee/samples/ms-tpm-20-ref/TPMCmd/Platform/platform.vcxproj.filters 28d350e18f1aef2b1a498f6a3c4d6b6fc4801e16 - optee/samples/ms-tpm-20-ref/TPMCmd/Platform/include/PlatformClock.h e6bb9513e4249c3ac0a989c5fd7bfb903d289620 - optee/samples/ms-tpm-20-ref/TPMCmd/Platform/include/Platform.h 96a84654a7f17be4142d2be731b34f75a98ed392 - optee/samples/ms-tpm-20-ref/TPMCmd/Platform/include/PlatformACT.h 6bb582b72adaf604087fb29ed50662e4022c3ccc - optee/samples/ms-tpm-20-ref/TPMCmd/Platform/include/PlatformData.h 3981e6d6dadaa8e8d24d15a406bf689b056f0417 - optee/samples/ms-tpm-20-ref/TPMCmd/Platform/include/prototypes/Platform_fp.h d290d3667f6beb284f0939e9bb8de8e5f791ae65 - optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/PlatformData.c 48252f45915ed083a6bac0596f3f735e790030ff - optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/Unique.c a0db60df8165e3f3d2b061e5d016e276436ac491 - optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/NVMem.c 840342229d7c6e58ac57152754601a3bc71ba600 - optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/Cancel.c bb85408dbeab5098eb77aa2313d4b28c1d50c029 - optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/PowerPlat.c f3feb56e3c38c94f33efddfc87b0a0c57195b8f5 - optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/PPPlat.c 2d34f6fdc0779ace9b29380650859eb2dc9beb3b - optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/Entropy.c d0b4a5d97e521e77f766897886f80c684d758eab - optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/Clock.c 5dd2e2afbb7b708d9bc585d6c7a1263fe5e3e6cc - optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/RunCommand.c 913caab5748d7a733058680722290dd4cbaa18a6 - optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/LocalityPlat.c 8904b7172e9c95bf5ccca723413a69488c1eb920 - optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/DebugHelpers.c 8fa7666caa7a84f328f87f9a9dbebd3c9388c8a5 - optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/PlatformACT.c 2db3c7ae60b9a166c0d001451a16c623a1182ded - optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/simulator.vcxproj 97dd5b29b67f302ad063523d539990c19123b90a - optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/include/TpmTcpProtocol.h b3c67c071ec064771e077773cb203d881499a063 - optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/include/prototypes/Simulator_fp.h adbc8328158bfbac3794e5bd132d5ea0304dbcd2 - optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/src/tpmsim.service ed0d9f117bda9b562ce47f09fa526466ea647130 - optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/src/TPMCmds.c d7bd32e37a53264b6ec8ebcf3b41f087652c4d3d - optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/src/TPMCmdp.c 922b6cdcf8fe2c2afbea87d499eba8234873cbb8 - optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/src/TcpServer.c 5a493d9124d00ded9800ae107ba167c72c9056ad - optee/samples/ftpm-helper/Makefile 7522d5293f83744f086728d6cd38c877fe39a3ad - optee/samples/ftpm-helper/README.md 96da5d9fe175e882abdd919aa1c4bd9a2def2f06 - optee/samples/ftpm-helper/LICENSE 5dbb2cb40501d442a50453c79e55f6fe7aa642c9 - optee/samples/ftpm-helper/host/Makefile 4ebeba0c52d359825b26ffad5fd456d1c43277d8 - optee/samples/ftpm-helper/host/ftpm_helper_ca.c 05ab08f5221f05e94520ed9495423d026bcd5460 - optee/samples/ftpm-helper/host/tool/odm_ekb_gen.py 44dd5efe74224613ae3361b5288d5f4fbbffb808 - optee/samples/ftpm-helper/host/tool/ftpm_manufacturer_ca_sign_sid_csr.sh 46d7267ff5f2e40f0cb402b89ccef57708c6ce05 - optee/samples/ftpm-helper/host/tool/ftpm_manufacturer_ca_sign_sid_csr.py ffaf17771c52fb326d9298929500e7cad003d933 - optee/samples/ftpm-helper/host/tool/ftpm_manufacturer_gen_ek_csr.sh e3f3060340f290f4b9ac80f0bfef98636605414c - optee/samples/ftpm-helper/host/tool/ftpm_offline_provisioning_verify.sh 6040c09f6e07731353cde2f79647f9b37019012c - optee/samples/ftpm-helper/host/tool/ftpm_manufacturer_ca_simulator.py ddb11390ea289ff539c833fcd9849d0bf81106b2 - optee/samples/ftpm-helper/host/tool/ftpm_test_local_attestation.sh 58f17af47d0dd8ec7ec3e5a0a4cfcc10da119248 - optee/samples/ftpm-helper/host/tool/ftpm_manufacturer_gen_ek_csr_tool.py 17aa9eb1d7d6989dee35a50bb30d873f45ab053f - optee/samples/ftpm-helper/host/tool/kdk_gen.py 18d61e2198cfc4965ec932ad1751e98ea619bffe - optee/samples/ftpm-helper/host/tool/oem_ekb_gen.py fe950095be80ba8e01f91fc8db3c98d64f2ce7b3 - optee/samples/ftpm-helper/host/tool/ftpm_device_provision.sh cce78a2db51c264b884b2e53c7605556e4651318 - optee/samples/ftpm-helper/host/tool/ftpm_manufacturer_ca_simulator.sh 22dcd0ebfce77a7abdceaa85dadfbd5151814ef4 - optee/samples/ftpm-helper/host/tool/lib/silicon_id_csr.py 68063b7cdc77b6f03971c9b479950603d395e530 - optee/samples/ftpm-helper/host/tool/lib/ftpm_ek.py 2989d9817b1d1ee76139b1bf780f937af2721fe3 - optee/samples/ftpm-helper/host/tool/lib/aes_drbg.py 79c7dece1ab210876510b24cf9a18ec129a93693 - optee/samples/ftpm-helper/host/tool/lib/ftpm_ek_csr.py 2b3f0a1315886edf3fe2969e88e4f709914c2ea1 - optee/samples/ftpm-helper/host/tool/conf/ftpm_i_ca_sim.config ab33fbbfb23ed4c0687e915bd88cc7b568b319d1 - optee/samples/ftpm-helper/host/tool/conf/ftpm_root_ca_sim.config 174230a84516fd6fc4c6dfa553bfba136df35489 - optee/samples/ftpm-helper/ta/Makefile 6442bb99b6d3029526133a362a0838012c051149 - optee/samples/ftpm-helper/ta/user_ta_header_defines.h a521701086a719a903d80697a572009e501ffb6b - optee/samples/ftpm-helper/ta/ftpm_helper_ta.c 680c8e7491b86f42fa79551446d38294fae5bd5e - optee/samples/ftpm-helper/ta/include/ftpm_helper_ta.h 9eebaea6c013cd863161f00430bf4b6a154813a6 - optee/samples/pkcs11-sample/Makefile fc4fb84dcbf00b04fcc91f516aedd701350aed89 - optee/samples/pkcs11-sample/LICENSE a7f13b06bf4c5eb0669cf42f2632c2b235262393 - optee/samples/pkcs11-sample/host/Makefile b7cb007727b4c2e482d77fcb1a3c7834caf80fbd - optee/samples/pkcs11-sample/host/pkcs11_sample_ca.c 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 52056059ceb33df8556122c574b98bbaf33f9599 - optee/samples/hwkey-agent/host/tool/gen_ekb/gen_ekb.py db9d139cadc808f2be7926b333651ef7b0cb09f8 - optee/samples/hwkey-agent/host/tool/gen_ekb/README 31660a5c7c817d388aa60d8e7425a54d0faa3241 - optee/samples/hwkey-agent/host/tool/gen_ekb/example.sh 5054796c29272096d67dbf4fa7453f9bfa3ad280 - optee/samples/hwkey-agent/ta/Makefile 01a5ebf5ecbf58a06002ad10b902e18d78d452d8 - optee/samples/hwkey-agent/ta/user_ta_header_defines.h 52fd37078d752fb17a039afd148a99a6f90c57b7 - optee/samples/hwkey-agent/ta/hwkey_agent_ta.c f1652fd24c49bf7be742b2e2081280bcd33d2ddd - optee/samples/hwkey-agent/ta/include/hwkey_agent_ta.h Change-Id: I7f9c4c6848e7f71b2bb2306d144056cd7c5173f9 --- commitFile.txt | 3815 +++ nvcommon_build.sh | 58 + optee/atf_and_optee_README.txt | 131 + optee/optee_client/.github/workflows/ci.yml | 51 + .../optee_client/.github/workflows/stales.yml | 27 + optee/optee_client/Android.bp | 294 + optee/optee_client/CMakeLists.txt | 49 + optee/optee_client/CMakeToolchain.txt | 3 + optee/optee_client/LICENSE | 27 + optee/optee_client/Makefile | 175 + optee/optee_client/README.md | 10 + optee/optee_client/ci/Dockerfile.debian | 21 + optee/optee_client/ci/Dockerfile.ubuntu | 30 + optee/optee_client/config.mk | 73 + 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 | 1707 ++ .../libckteec/src/pkcs11_processing.h | 139 + .../optee_client/libckteec/src/pkcs11_token.c | 863 + .../optee_client/libckteec/src/pkcs11_token.h | 59 + .../optee_client/libckteec/src/serialize_ck.c | 836 + .../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 | 59 + 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/libteeacl/teeacl.pc.in | 12 + optee/optee_client/libteec/CMakeLists.txt | 76 + optee/optee_client/libteec/Makefile | 63 + .../libteec/include/tee_client_api.h | 583 + .../include/tee_client_api_extensions.h | 57 + .../libteec/include/tee_plugin_method.h | 20 + .../optee_client/libteec/include/teec_trace.h | 147 + optee/optee_client/libteec/src/linux/tee.h | 417 + .../optee_client/libteec/src/tee_client_api.c | 954 + optee/optee_client/libteec/src/teec_trace.c | 141 + optee/optee_client/libteec/teec.pc.in | 13 + optee/optee_client/optee_client.device.mk | 18 + optee/optee_client/prebuilt/include/uuid.h | 123 + optee/optee_client/prebuilt/libuuid.a | Bin 0 -> 60704 bytes optee/optee_client/prebuilt/uuid.pc | 10 + optee/optee_client/scripts/checkpatch_inc.sh | 49 + .../tee-supplicant/CMakeLists.txt | 115 + optee/optee_client/tee-supplicant/Makefile | 104 + .../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 | 1032 + .../tee-supplicant/src/tee_supplicant.h | 59 + .../tee-supplicant/src/teec_ta_load.c | 172 + .../tee-supplicant/src/teec_ta_load.h | 52 + optee/optee_client/typedefs.checkpatch | 80 + optee/optee_os/.checkpatch.conf | 13 + optee/optee_os/.clang-format | 150 + 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 | 455 + optee/optee_os/.github/workflows/stales.yml | 27 + optee/optee_os/CHANGELOG.md | 1795 ++ optee/optee_os/LICENSE | 45 + optee/optee_os/LICENSE.NVIDIA | 141 + optee/optee_os/MAINTAINERS | 344 + optee/optee_os/Makefile | 129 + optee/optee_os/README.md | 7 + optee/optee_os/core/arch/arm/arm.mk | 455 + .../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 | 652 + .../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/at91-sama7g54_ek.dts | 958 + .../core/arch/arm/dts/dt_driver_test.dtsi | 55 + .../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 | 1391 ++ 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 | 1238 + .../core/arch/arm/dts/sama7g5-pinfunc.h | 927 + optee/optee_os/core/arch/arm/dts/sama7g5.dtsi | 1219 + .../core/arch/arm/dts/stm32mp13-pinctrl.dtsi | 55 + .../core/arch/arm/dts/stm32mp131.dtsi | 643 + .../core/arch/arm/dts/stm32mp133.dtsi | 7 + .../core/arch/arm/dts/stm32mp135.dtsi | 24 + .../core/arch/arm/dts/stm32mp135f-dk.dts | 481 + .../core/arch/arm/dts/stm32mp13xc.dtsi | 34 + .../core/arch/arm/dts/stm32mp13xf.dtsi | 34 + .../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 + .../arch/arm/dts/stm32mp157a-dk1-scmi.dts | 18 + .../core/arch/arm/dts/stm32mp157a-dk1.dts | 38 + .../arch/arm/dts/stm32mp157c-dhcom-pdk2.dts | 29 + .../arch/arm/dts/stm32mp157c-dk2-scmi.dts | 18 + .../core/arch/arm/dts/stm32mp157c-dk2.dts | 107 + .../arch/arm/dts/stm32mp157c-ed1-scmi.dts | 27 + .../core/arch/arm/dts/stm32mp157c-ed1.dts | 425 + .../arch/arm/dts/stm32mp157c-ev1-scmi.dts | 17 + .../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 | 746 + .../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 + .../core/arch/arm/dts/stm32mp25-pinctrl.dtsi | 7 + .../core/arch/arm/dts/stm32mp251.dtsi | 243 + .../core/arch/arm/dts/stm32mp253.dtsi | 17 + .../core/arch/arm/dts/stm32mp255.dtsi | 9 + .../core/arch/arm/dts/stm32mp257.dtsi | 9 + .../dts/stm32mp257f-ev1-ca35tdcid-rif.dtsi | 139 + .../core/arch/arm/dts/stm32mp257f-ev1.dts | 32 + .../core/arch/arm/dts/stm32mp25xc.dtsi | 8 + .../core/arch/arm/dts/stm32mp25xf.dtsi | 8 + .../arch/arm/dts/stm32mp25xxai-pinctrl.dtsi | 81 + .../arch/arm/dts/stm32mp25xxak-pinctrl.dtsi | 69 + .../arch/arm/dts/stm32mp25xxal-pinctrl.dtsi | 69 + optee/optee_os/core/arch/arm/include/arm.h | 272 + 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 | 545 + .../core/arch/arm/include/arm64_macros.S | 183 + .../arch/arm/include/crypto/ghash-ce-core.h | 43 + optee/optee_os/core/arch/arm/include/ffa.h | 378 + .../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 | 47 + .../core/arch/arm/include/kernel/misc_arch.h | 20 + .../arm/include/kernel/secure_partition.h | 100 + .../arch/arm/include/kernel/spmc_sp_handler.h | 54 + .../core/arch/arm/include/kernel/stmm_sp.h | 197 + .../arch/arm/include/kernel/tee_l2cc_mutex.h | 51 + .../arch/arm/include/kernel/thread_arch.h | 465 + .../arm/include/kernel/thread_private_arch.h | 259 + .../arch/arm/include/kernel/thread_spmc.h | 78 + .../arch/arm/include/kernel/tlb_helpers.h | 51 + .../arch/arm/include/kernel/tz_proc_def.h | 96 + .../arch/arm/include/kernel/tz_ssvce_def.h | 128 + .../arch/arm/include/kernel/tz_ssvce_pl310.h | 26 + .../arm/include/kernel/user_access_arch.h | 28 + .../core/arch/arm/include/kernel/vfp.h | 106 + .../core/arch/arm/include/mm/core_mmu_arch.h | 232 + .../arch/arm/include/mm/generic_ram_layout.h | 184 + .../core/arch/arm/include/optee_ffa.h | 184 + .../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 | 89 + optee/optee_os/core/arch/arm/include/sm/sm.h | 145 + .../core/arch/arm/include/sm/std_smc.h | 43 + .../core/arch/arm/include/sm/teesmc_opteed.h | 120 + .../arm/include/sm/teesmc_opteed_macros.h | 13 + .../core/arch/arm/include/sm/watchdog_smc.h | 81 + 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 | 591 + .../core/arch/arm/kernel/arch_scall.c | 154 + .../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 | 174 + optee/optee_os/core/arch/arm/kernel/boot.c | 1740 ++ .../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 | 898 + .../optee_os/core/arch/arm/kernel/entry_a64.S | 762 + .../core/arch/arm/kernel/generic_timer.c | 68 + 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 | 268 + .../core/arch/arm/kernel/link_dummies_init.c | 31 + .../core/arch/arm/kernel/link_dummies_paged.c | 55 + .../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 | 1960 ++ .../core/arch/arm/kernel/semihosting_a64.S | 17 + .../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 | 1285 + optee/optee_os/core/arch/arm/kernel/stmm_sp.c | 1135 + optee/optee_os/core/arch/arm/kernel/sub.mk | 88 + .../core/arch/arm/kernel/tee_l2cc_mutex.c | 136 + .../arch/arm/kernel/tee_time_arm_cntpct.c | 71 + optee/optee_os/core/arch/arm/kernel/thread.c | 1198 + .../core/arch/arm/kernel/thread_a32.S | 990 + .../core/arch/arm/kernel/thread_a64.S | 1336 + .../core/arch/arm/kernel/thread_optee_smc.c | 709 + .../arch/arm/kernel/thread_optee_smc_a32.S | 255 + .../arch/arm/kernel/thread_optee_smc_a64.S | 257 + .../core/arch/arm/kernel/thread_spmc.c | 2398 ++ .../core/arch/arm/kernel/thread_spmc_a64.S | 219 + .../optee_os/core/arch/arm/kernel/timer_a64.c | 62 + .../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 | 235 + .../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 | 621 + optee/optee_os/core/arch/arm/mm/core_mmu.c | 239 + .../optee_os/core/arch/arm/mm/core_mmu_lpae.c | 1381 ++ optee/optee_os/core/arch/arm/mm/core_mmu_v7.c | 828 + .../optee_os/core/arch/arm/mm/mobj_dyn_shm.c | 472 + optee/optee_os/core/arch/arm/mm/mobj_ffa.c | 767 + optee/optee_os/core/arch/arm/mm/sp_mem.c | 337 + optee/optee_os/core/arch/arm/mm/sub.mk | 24 + 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 | 49 + .../core/arch/arm/plat-aspeed/core_pos_a32.S | 16 + .../arch/arm/plat-aspeed/platform_ast2600.c | 102 + .../arch/arm/plat-aspeed/platform_ast2700.c | 37 + .../arch/arm/plat-aspeed/platform_config.h | 41 + .../optee_os/core/arch/arm/plat-aspeed/sub.mk | 3 + .../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 | 44 + 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 | 78 + .../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 | 39 + .../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 | 30 + .../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 | 24 + optee/optee_os/core/arch/arm/plat-d06/sub.mk | 3 + .../optee_os/core/arch/arm/plat-hikey/conf.mk | 65 + .../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 | 540 + .../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 | 51 + optee/optee_os/core/arch/arm/plat-imx/imx.h | 53 + .../core/arch/arm/plat-imx/imx_pl310.c | 131 + .../core/arch/arm/plat-imx/imx_pl310.h | 15 + optee/optee_os/core/arch/arm/plat-imx/link.mk | 9 + optee/optee_os/core/arch/arm/plat-imx/main.c | 122 + .../core/arch/arm/plat-imx/platform_config.h | 59 + .../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 | 167 + .../arch/arm/plat-imx/registers/imx7-crm.h | 112 + .../core/arch/arm/plat-imx/registers/imx7.h | 79 + .../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 | 67 + .../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 | 20 + .../optee_os/core/arch/arm/plat-imx/tzc380.c | 102 + optee/optee_os/core/arch/arm/plat-k3/conf.mk | 37 + .../core/arch/arm/plat-k3/drivers/sa2ul.c | 153 + .../core/arch/arm/plat-k3/drivers/sa2ul.h | 16 + .../core/arch/arm/plat-k3/drivers/sa2ul_rng.c | 161 + .../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 | 496 + .../core/arch/arm/plat-k3/drivers/ti_sci.h | 193 + .../arm/plat-k3/drivers/ti_sci_protocol.h | 452 + optee/optee_os/core/arch/arm/plat-k3/main.c | 107 + .../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 | 131 + optee/optee_os/core/arch/arm/plat-ls/main.c | 221 + .../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 + .../arch/arm/plat-marvell/cn10k/core_pos.S | 15 + .../core/arch/arm/plat-marvell/conf.mk | 169 + .../core/arch/arm/plat-marvell/main.c | 117 + .../arch/arm/plat-marvell/otx2/core_pos.S | 16 + .../arch/arm/plat-marvell/platform_config.h | 160 + .../core/arch/arm/plat-marvell/sub.mk | 10 + .../core/arch/arm/plat-mediatek/conf.mk | 92 + .../core/arch/arm/plat-mediatek/main.c | 43 + .../arch/arm/plat-mediatek/platform_config.h | 130 + .../core/arch/arm/plat-mediatek/sub.mk | 2 + .../core/arch/arm/plat-nuvoton/conf.mk | 41 + .../core/arch/arm/plat-nuvoton/main.c | 103 + .../arch/arm/plat-nuvoton/platform_config.h | 25 + .../core/arch/arm/plat-nuvoton/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 | 46 + .../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 | 98 + .../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 | 162 + .../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 | 50 + .../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 | 109 + .../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 | 138 + optee/optee_os/core/arch/arm/plat-sam/freq.c | 48 + .../optee_os/core/arch/arm/plat-sam/matrix.c | 280 + .../optee_os/core/arch/arm/plat-sam/matrix.h | 86 + .../nsec-service/sm_platform_handler.c | 51 + .../arch/arm/plat-sam/nsec-service/smc_ids.h | 22 + .../arch/arm/plat-sam/nsec-service/sub.mk | 3 + .../core/arch/arm/plat-sam/platform_config.h | 112 + .../core/arch/arm/plat-sam/platform_sama5d2.c | 792 + .../core/arch/arm/plat-sam/platform_sama7g5.c | 937 + .../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_os/core/arch/arm/plat-sam/sama7g5.h | 338 + .../core/arch/arm/plat-sam/scmi_server.c | 1054 + optee/optee_os/core/arch/arm/plat-sam/sub.mk | 10 + .../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 | 52 + .../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 | 143 + .../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 | 413 + .../plat-stm32mp1/drivers/stm32mp1_etzpc.h | 156 + .../arm/plat-stm32mp1/drivers/stm32mp1_pmic.c | 797 + .../arm/plat-stm32mp1/drivers/stm32mp1_pmic.h | 51 + .../arm/plat-stm32mp1/drivers/stm32mp1_pwr.c | 291 + .../arm/plat-stm32mp1/drivers/stm32mp1_pwr.h | 45 + .../plat-stm32mp1/drivers/stm32mp1_syscfg.c | 199 + .../plat-stm32mp1/drivers/stm32mp1_syscfg.h | 51 + .../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 | 576 + .../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 | 123 + .../arch/arm/plat-stm32mp1/platform_config.h | 241 + .../core/arch/arm/plat-stm32mp1/pm/psci.c | 277 + .../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 | 904 + .../arm/plat-stm32mp1/scripts/stm32image.py | 140 + .../arch/arm/plat-stm32mp1/shared_resources.c | 755 + .../core/arch/arm/plat-stm32mp1/stm32_util.h | 332 + .../core/arch/arm/plat-stm32mp1/sub.mk | 12 + .../core/arch/arm/plat-stm32mp2/conf.mk | 77 + .../core/arch/arm/plat-stm32mp2/main.c | 144 + .../arch/arm/plat-stm32mp2/platform_config.h | 108 + .../core/arch/arm/plat-stm32mp2/stm32_util.h | 25 + .../core/arch/arm/plat-stm32mp2/stm32mp_pm.c | 98 + .../core/arch/arm/plat-stm32mp2/stm32mp_pm.h | 35 + .../core/arch/arm/plat-stm32mp2/sub.mk | 4 + .../optee_os/core/arch/arm/plat-sunxi/conf.mk | 45 + .../optee_os/core/arch/arm/plat-sunxi/main.c | 179 + .../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 | 73 + .../arch/arm/plat-synquacer/platform_config.h | 33 + .../core/arch/arm/plat-synquacer/rng_pta.c | 360 + .../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 | 168 + .../optee_os/core/arch/arm/plat-tegra/link.mk | 13 + .../optee_os/core/arch/arm/plat-tegra/main.c | 49 + .../arch/arm/plat-tegra/platform_config.h | 14 + .../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 | 126 + .../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 | 40 + .../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 | 51 + .../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 | 117 + .../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 | 173 + .../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 | 271 + .../arch/arm/plat-vexpress/platform_config.h | 158 + .../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 | 217 + .../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 | 110 + .../arch/arm/plat-zynqmp/platform_config.h | 103 + .../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 | 362 + 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 | 21 + .../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 | 253 + .../include/kernel/thread_private_arch.h | 125 + .../arch/riscv/include/kernel/tlb_helpers.h | 18 + .../riscv/include/kernel/user_access_arch.h | 29 + .../arch/riscv/include/mm/core_mmu_arch.h | 153 + .../riscv/include/mm/generic_ram_layout.h | 191 + .../optee_os/core/arch/riscv/include/riscv.h | 400 + .../core/arch/riscv/include/riscv_macros.S | 78 + optee/optee_os/core/arch/riscv/include/sbi.h | 71 + optee/optee_os/core/arch/riscv/include/sub.mk | 1 + .../core/arch/riscv/include/tee/entry_fast.h | 34 + .../core/arch/riscv/include/tee/optee_abi.h | 705 + .../arch/riscv/include/tee/teeabi_opteed.h | 111 + .../riscv/include/tee/teeabi_opteed_macros.h | 14 + optee/optee_os/core/arch/riscv/kernel/abort.c | 394 + .../core/arch/riscv/kernel/arch_scall.c | 84 + .../core/arch/riscv/kernel/arch_scall_rv.S | 63 + .../core/arch/riscv/kernel/asm-defines.c | 98 + optee/optee_os/core/arch/riscv/kernel/boot.c | 181 + .../core/arch/riscv/kernel/cache_helpers_rv.S | 62 + optee/optee_os/core/arch/riscv/kernel/entry.S | 299 + optee/optee_os/core/arch/riscv/kernel/idle.c | 15 + .../optee_os/core/arch/riscv/kernel/kern.ld.S | 278 + optee/optee_os/core/arch/riscv/kernel/link.mk | 143 + optee/optee_os/core/arch/riscv/kernel/sbi.c | 80 + .../core/arch/riscv/kernel/sbi_console.c | 48 + .../core/arch/riscv/kernel/semihosting_rv.S | 22 + .../core/arch/riscv/kernel/spinlock.S | 42 + optee/optee_os/core/arch/riscv/kernel/sub.mk | 31 + .../core/arch/riscv/kernel/tee_time_rdtime.c | 51 + .../core/arch/riscv/kernel/thread_arch.c | 693 + .../core/arch/riscv/kernel/thread_optee_abi.c | 715 + .../arch/riscv/kernel/thread_optee_abi_rv.S | 223 + .../core/arch/riscv/kernel/thread_rv.S | 326 + .../core/arch/riscv/kernel/unwind_rv.c | 29 + .../core/arch/riscv/mm/core_mmu_arch.c | 770 + optee/optee_os/core/arch/riscv/mm/sub.mk | 10 + .../core/arch/riscv/mm/tlb_helpers_rv.S | 31 + .../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 | 22 + .../core/arch/riscv/plat-spike/sub.mk | 3 + .../core/arch/riscv/plat-virt/conf.mk | 44 + .../optee_os/core/arch/riscv/plat-virt/main.c | 42 + .../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 | 247 + .../optee_os/core/arch/riscv/tee/entry_fast.c | 316 + optee/optee_os/core/arch/riscv/tee/sub.mk | 2 + optee/optee_os/core/core.mk | 177 + optee/optee_os/core/crypto.mk | 319 + optee/optee_os/core/crypto/aes-cts.c | 258 + .../optee_os/core/crypto/aes-gcm-ghash-tbl.c | 144 + optee/optee_os/core/crypto/aes-gcm-sw.c | 143 + optee/optee_os/core/crypto/aes-gcm.c | 547 + optee/optee_os/core/crypto/cbc-mac.c | 248 + optee/optee_os/core/crypto/crypto.c | 955 + 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 | 112 + optee/optee_os/core/crypto/sm3.c | 320 + 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 | 481 + optee/optee_os/core/drivers/atmel_rstc.c | 94 + optee/optee_os/core/drivers/atmel_rtc.c | 329 + optee/optee_os/core/drivers/atmel_saic.c | 341 + optee/optee_os/core/drivers/atmel_shdwc.c | 234 + optee/optee_os/core/drivers/atmel_shdwc_a32.S | 79 + optee/optee_os/core/drivers/atmel_tcb.c | 204 + optee/optee_os/core/drivers/atmel_trng.c | 122 + optee/optee_os/core/drivers/atmel_uart.c | 104 + optee/optee_os/core/drivers/atmel_wdt.c | 398 + 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 | 2748 +++ .../optee_os/core/drivers/clk/clk-stm32mp15.c | 1569 ++ optee/optee_os/core/drivers/clk/clk.c | 548 + optee/optee_os/core/drivers/clk/clk_dt.c | 217 + 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 | 280 + .../core/drivers/clk/sam/at91_generated.c | 194 + .../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 | 307 + .../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 | 293 + .../optee_os/core/drivers/clk/sam/at91_pmc.h | 289 + .../core/drivers/clk/sam/at91_programmable.c | 165 + .../optee_os/core/drivers/clk/sam/at91_sckc.c | 70 + .../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 | 193 + .../core/drivers/clk/sam/clk-sam9x60-pll.c | 520 + .../core/drivers/clk/sam/phy-sama7-utmi-clk.c | 85 + .../core/drivers/clk/sam/sama5d2_clk.c | 612 + .../core/drivers/clk/sam/sama7g5_clk.c | 1580 ++ optee/optee_os/core/drivers/clk/sam/sub.mk | 13 + 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 | 523 + .../drivers/crypto/caam/acipher/caam_dsa.c | 806 + .../drivers/crypto/caam/acipher/caam_ecc.c | 911 + .../drivers/crypto/caam/acipher/caam_math.c | 125 + .../crypto/caam/acipher/caam_prime_dsa.c | 758 + .../crypto/caam/acipher/caam_prime_rsa.c | 869 + .../drivers/crypto/caam/acipher/caam_rsa.c | 1712 ++ .../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/caam_dek.c | 119 + .../core/drivers/crypto/caam/blob/sub.mk | 4 + .../core/drivers/crypto/caam/caam_ctrl.c | 205 + .../core/drivers/crypto/caam/caam_desc.c | 164 + .../core/drivers/crypto/caam/caam_jr.c | 688 + .../core/drivers/crypto/caam/caam_key.c | 752 + .../core/drivers/crypto/caam/caam_pwr.c | 183 + .../core/drivers/crypto/caam/caam_rng.c | 603 + .../core/drivers/crypto/caam/caam_sm.c | 181 + .../drivers/crypto/caam/cipher/caam_cipher.c | 901 + .../crypto/caam/cipher/caam_cipher_mac.c | 825 + .../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 | 215 + .../drivers/crypto/caam/hal/common/hal_cfg.c | 100 + .../crypto/caam/hal/common/hal_cfg_dt.c | 137 + .../drivers/crypto/caam/hal/common/hal_ctrl.c | 270 + .../drivers/crypto/caam/hal/common/hal_jr.c | 246 + .../drivers/crypto/caam/hal/common/hal_rng.c | 162 + .../drivers/crypto/caam/hal/common/hal_sm.c | 220 + .../caam/hal/common/registers/jr_regs.h | 72 + .../caam/hal/common/registers/rng_regs.h | 121 + .../caam/hal/common/registers/sm_regs.h | 53 + .../caam/hal/common/registers/version_regs.h | 80 + .../drivers/crypto/caam/hal/common/sub.mk | 10 + .../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 | 44 + .../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 | 29 + .../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 | 350 + .../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 | 747 + .../crypto/caam/include/caam_desc_helper.h | 567 + .../crypto/caam/include/caam_hal_cfg.h | 76 + .../crypto/caam/include/caam_hal_clk.h | 19 + .../crypto/caam/include/caam_hal_ctrl.h | 108 + .../drivers/crypto/caam/include/caam_hal_jr.h | 139 + .../crypto/caam/include/caam_hal_rng.h | 57 + .../drivers/crypto/caam/include/caam_hal_sm.h | 127 + .../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_key.h | 155 + .../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_sm.h | 73 + .../drivers/crypto/caam/include/caam_status.h | 29 + .../drivers/crypto/caam/include/caam_trace.h | 357 + .../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 | 28 + .../core/drivers/crypto/caam/mp/caam_mp.c | 408 + .../core/drivers/crypto/caam/mp/sub.mk | 3 + .../optee_os/core/drivers/crypto/caam/sub.mk | 17 + .../core/drivers/crypto/caam/utils/sub.mk | 9 + .../drivers/crypto/caam/utils/utils_delay.c | 20 + .../drivers/crypto/caam/utils/utils_dmaobj.c | 1415 ++ .../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 | 90 + .../crypto_api/include/drvcrypt_acipher.h | 273 + .../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 + .../core/drivers/crypto/hisilicon/hisi_qm.c | 898 + .../core/drivers/crypto/hisilicon/hpre_main.c | 326 + .../crypto/hisilicon/include/hisi_qm.h | 271 + .../crypto/hisilicon/include/hpre_main.h | 39 + .../core/drivers/crypto/hisilicon/sub.mk | 4 + .../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 | 109 + .../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 | 90 + .../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 | 372 + .../core/drivers/crypto/stm32/cipher.c | 377 + .../core/drivers/crypto/stm32/common.h | 38 + .../core/drivers/crypto/stm32/crypto.mk | 21 + .../core/drivers/crypto/stm32/stm32_cryp.c | 1337 + .../core/drivers/crypto/stm32/stm32_cryp.h | 78 + .../core/drivers/crypto/stm32/stm32_saes.c | 1432 ++ .../core/drivers/crypto/stm32/stm32_saes.h | 68 + .../optee_os/core/drivers/crypto/stm32/sub.mk | 4 + optee/optee_os/core/drivers/crypto/sub.mk | 15 + .../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 + .../core/drivers/firewall/stm32_rif.c | 138 + .../core/drivers/firewall/stm32_rifsc.c | 561 + optee/optee_os/core/drivers/firewall/sub.mk | 2 + optee/optee_os/core/drivers/gic.c | 1079 + optee/optee_os/core/drivers/gpio/gpio.c | 71 + optee/optee_os/core/drivers/gpio/sub.mk | 1 + optee/optee_os/core/drivers/hfic.c | 98 + optee/optee_os/core/drivers/hi16xx_rng.c | 100 + optee/optee_os/core/drivers/hi16xx_uart.c | 141 + optee/optee_os/core/drivers/hisi_trng.c | 95 + optee/optee_os/core/drivers/i2c/atmel_i2c.c | 366 + 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 | 84 + .../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 | 175 + optee/optee_os/core/drivers/imx_ele.c | 559 + 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 | 207 + 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 | 614 + 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 | 121 + optee/optee_os/core/drivers/nvmem/atmel_sfc.c | 129 + optee/optee_os/core/drivers/nvmem/nvmem.c | 77 + .../core/drivers/nvmem/nvmem_die_id.c | 62 + optee/optee_os/core/drivers/nvmem/nvmem_huk.c | 62 + optee/optee_os/core/drivers/nvmem/sub.mk | 4 + .../optee_os/core/drivers/pinctrl/atmel_pio.c | 248 + optee/optee_os/core/drivers/pinctrl/pinctrl.c | 138 + optee/optee_os/core/drivers/pinctrl/sub.mk | 2 + optee/optee_os/core/drivers/pl011.c | 251 + optee/optee_os/core/drivers/pl022_spi.c | 509 + optee/optee_os/core/drivers/pl061_gpio.c | 217 + optee/optee_os/core/drivers/plic.c | 284 + optee/optee_os/core/drivers/pm/imx/gpcv2.c | 50 + optee/optee_os/core/drivers/pm/imx/local.h | 49 + optee/optee_os/core/drivers/pm/imx/psci.c | 138 + optee/optee_os/core/drivers/pm/imx/src.c | 86 + optee/optee_os/core/drivers/pm/imx/sub.mk | 3 + 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 | 2 + .../core/drivers/regulator/regulator.c | 492 + .../core/drivers/regulator/regulator_dt.c | 413 + .../core/drivers/regulator/regulator_fixed.c | 184 + .../core/drivers/regulator/regulator_gpio.c | 300 + .../core/drivers/regulator/stm32_vrefbuf.c | 390 + .../regulator/stm32mp13_regulator_iod.c | 297 + optee/optee_os/core/drivers/regulator/sub.mk | 6 + .../drivers/remoteproc/stm32_remoteproc.c | 388 + optee/optee_os/core/drivers/remoteproc/sub.mk | 1 + optee/optee_os/core/drivers/rstctrl/rstctrl.c | 50 + .../core/drivers/rstctrl/stm32_rstctrl.c | 235 + 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 + .../core/drivers/scmi-msg/clock_generic.c | 223 + 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 | 8 + .../core/drivers/scmi-msg/voltage_domain.c | 409 + .../core/drivers/scmi-msg/voltage_domain.h | 135 + .../core/drivers/semihosting_console.c | 68 + 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 | 140 + 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 | 956 + optee/optee_os/core/drivers/stm32_etzpc.c | 348 + optee/optee_os/core/drivers/stm32_gpio.c | 984 + optee/optee_os/core/drivers/stm32_i2c.c | 1702 ++ optee/optee_os/core/drivers/stm32_iwdg.c | 414 + optee/optee_os/core/drivers/stm32_rng.c | 750 + 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 | 196 + optee/optee_os/core/drivers/stm32mp15_huk.c | 220 + optee/optee_os/core/drivers/stpmic1.c | 1027 + optee/optee_os/core/drivers/sub.mk | 101 + .../common/include/tegra_driver_common.h | 14 + .../tegra/common/include/tegra_driver_fuse.h | 64 + .../tegra/common/include/tegra_driver_rng1.h | 21 + .../tegra/common/include/tegra_driver_se.h | 46 + .../common/include/tegra_driver_srv_intf.h | 53 + .../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 | 228 + .../drivers/tegra/common/tegra_driver_rng1.c | 80 + .../drivers/tegra/common/tegra_driver_se.c | 69 + .../tegra/common/tegra_driver_srv_intf.c | 144 + optee/optee_os/core/drivers/tegra/sub.mk | 9 + .../tegra/t194/include/tegra_se_mgnt.h | 64 + optee/optee_os/core/drivers/tegra/t194/sub.mk | 8 + .../core/drivers/tegra/t194/tegra_fuse.c | 99 + .../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 + .../tegra/t234/crypto/tegra_driver_hash.c | 105 + .../drivers/tegra/t234/include/tegra_se_ccc.h | 66 + .../tegra/t234/include/tegra_se_ccc_errno.h | 63 + optee/optee_os/core/drivers/tegra/t234/sub.mk | 8 + .../core/drivers/tegra/t234/tegra_fuse.c | 104 + .../core/drivers/tegra/t234/tegra_rpmb.c | 103 + .../drivers/tegra/t234/tegra_se_aes_rng.c | 265 + .../drivers/tegra/t234/tegra_se_map_device.c | 85 + .../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 | 74 + optee/optee_os/core/drivers/widevine_huk.c | 64 + 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/console.h | 57 + optee/optee_os/core/include/crypto/crypto.h | 425 + .../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 | 27 + .../optee_os/core/include/drivers/atmel_rtc.h | 22 + .../core/include/drivers/atmel_saic.h | 46 + .../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 | 55 + .../core/include/drivers/cbmem_console.h | 13 + .../optee_os/core/include/drivers/cdns_uart.h | 43 + optee/optee_os/core/include/drivers/clk.h | 261 + optee/optee_os/core/include/drivers/clk_dt.h | 110 + optee/optee_os/core/include/drivers/gic.h | 59 + optee/optee_os/core/include/drivers/gpio.h | 222 + optee/optee_os/core/include/drivers/hfic.h | 11 + .../core/include/drivers/hi16xx_uart.h | 26 + optee/optee_os/core/include/drivers/i2c.h | 344 + 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 | 31 + .../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 | 74 + 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 | 67 + optee/optee_os/core/include/drivers/nvmem.h | 193 + optee/optee_os/core/include/drivers/pinctrl.h | 176 + 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 + optee/optee_os/core/include/drivers/plic.h | 18 + .../core/include/drivers/pm/sam/atmel_pm.h | 69 + .../optee_os/core/include/drivers/regulator.h | 329 + optee/optee_os/core/include/drivers/rstctrl.h | 231 + 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 | 411 + optee/optee_os/core/include/drivers/scmi.h | 30 + .../include/drivers/semihosting_console.h | 23 + optee/optee_os/core/include/drivers/serial.h | 48 + .../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 | 202 + .../core/include/drivers/stm32_etzpc.h | 77 + .../core/include/drivers/stm32_gpio.h | 61 + .../optee_os/core/include/drivers/stm32_i2c.h | 284 + .../core/include/drivers/stm32_iwdg.h | 29 + .../core/include/drivers/stm32_remoteproc.h | 70 + .../optee_os/core/include/drivers/stm32_rif.h | 224 + .../core/include/drivers/stm32_shared_io.h | 29 + .../core/include/drivers/stm32_tamp.h | 56 + .../core/include/drivers/stm32_uart.h | 45 + .../core/include/drivers/stm32_vrefbuf.h | 20 + .../core/include/drivers/stm32mp13_rcc.h | 1879 ++ .../include/drivers/stm32mp13_regulator_iod.h | 23 + .../core/include/drivers/stm32mp1_rcc.h | 577 + .../include/drivers/stm32mp_dt_bindings.h | 26 + optee/optee_os/core/include/drivers/stpmic1.h | 244 + .../core/include/drivers/stpmic1_regulator.h | 57 + .../core/include/drivers/tegra/tegra_fuse.h | 48 + .../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 | 72 + .../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 | 195 + .../include/dt-bindings/clock/stm32mp1-clks.h | 277 + .../dt-bindings/clock/stm32mp13-clks.h | 236 + .../dt-bindings/clock/stm32mp13-clksrc.h | 384 + .../core/include/dt-bindings/dma/at91.h | 57 + .../dt-bindings/firewall/stm32mp25-rif.h | 92 + .../dt-bindings/firewall/stm32mp25-rifsc.h | 173 + .../include/dt-bindings/gpio/atmel,piobu.h | 50 + .../core/include/dt-bindings/gpio/gpio.h | 42 + .../include/dt-bindings/gpio/stm32mp_gpio.h | 18 + .../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 | 42 + .../regulator/st,stm32mp15-regulator.h | 29 + .../dt-bindings/reset/stm32mp1-resets.h | 124 + .../dt-bindings/reset/stm32mp13-resets.h | 101 + .../core/include/dt-bindings/rtc/rtc-stm32.h | 14 + optee/optee_os/core/include/gen-asm-defines.h | 12 + optee/optee_os/core/include/initcall.h | 133 + optee/optee_os/core/include/io.h | 304 + 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 | 105 + .../core/include/kernel/cache_helpers.h | 45 + optee/optee_os/core/include/kernel/callout.h | 134 + .../core/include/kernel/chip_services.h | 12 + optee/optee_os/core/include/kernel/delay.h | 71 + optee/optee_os/core/include/kernel/dt.h | 457 + .../optee_os/core/include/kernel/dt_driver.h | 283 + optee/optee_os/core/include/kernel/early_ta.h | 18 + .../core/include/kernel/embedded_ts.h | 37 + optee/optee_os/core/include/kernel/handle.h | 52 + .../optee_os/core/include/kernel/huk_subkey.h | 66 + .../optee_os/core/include/kernel/interrupt.h | 544 + .../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 | 83 + optee/optee_os/core/include/kernel/mutex.h | 105 + .../core/include/kernel/mutex_pm_aware.h | 43 + optee/optee_os/core/include/kernel/notif.h | 171 + .../optee_os/core/include/kernel/nv_counter.h | 15 + optee/optee_os/core/include/kernel/panic.h | 42 + optee/optee_os/core/include/kernel/pm.h | 175 + .../optee_os/core/include/kernel/pseudo_ta.h | 99 + 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 + .../core/include/kernel/semihosting.h | 23 + optee/optee_os/core/include/kernel/spinlock.h | 155 + .../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 | 175 + optee/optee_os/core/include/kernel/tee_time.h | 21 + optee/optee_os/core/include/kernel/thread.h | 399 + .../core/include/kernel/thread_private.h | 93 + optee/optee_os/core/include/kernel/timer.h | 34 + optee/optee_os/core/include/kernel/tpm.h | 51 + optee/optee_os/core/include/kernel/trace_ta.h | 20 + .../core/include/kernel/transfer_list.h | 157 + .../optee_os/core/include/kernel/ts_manager.h | 84 + optee/optee_os/core/include/kernel/ts_store.h | 89 + optee/optee_os/core/include/kernel/unwind.h | 30 + .../core/include/kernel/user_access.h | 189 + .../core/include/kernel/user_mode_ctx.h | 34 + .../include/kernel/user_mode_ctx_struct.h | 62 + optee/optee_os/core/include/kernel/user_ta.h | 73 + .../core/include/kernel/virtualization.h | 147 + .../optee_os/core/include/kernel/wait_queue.h | 64 + optee/optee_os/core/include/mm/core_memprot.h | 142 + optee/optee_os/core/include/mm/core_mmu.h | 698 + 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 | 321 + 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 | 120 + .../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 | 100 + 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 | 158 + optee/optee_os/core/include/tee/fs_htree.h | 177 + 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 | 122 + .../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 | 54 + .../optee_os/core/include/tee/tee_ree_state.h | 36 + .../core/include/tee/tee_supp_plugin_rpc.h | 18 + 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 | 67 + .../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 | 285 + optee/optee_os/core/kernel/assert.c | 29 + optee/optee_os/core/kernel/callout.c | 188 + optee/optee_os/core/kernel/console.c | 181 + optee/optee_os/core/kernel/delay.c | 77 + optee/optee_os/core/kernel/dt.c | 744 + optee/optee_os/core/kernel/dt_driver.c | 914 + optee/optee_os/core/kernel/early_ta.c | 63 + optee/optee_os/core/kernel/embedded_ts.c | 223 + optee/optee_os/core/kernel/handle.c | 100 + optee/optee_os/core/kernel/huk_subkey.c | 112 + optee/optee_os/core/kernel/initcall.c | 66 + optee/optee_os/core/kernel/interrupt.c | 352 + optee/optee_os/core/kernel/ldelf_loader.c | 477 + optee/optee_os/core/kernel/ldelf_syscalls.c | 612 + optee/optee_os/core/kernel/lockdep.c | 513 + optee/optee_os/core/kernel/msg_param.c | 149 + optee/optee_os/core/kernel/mutex.c | 490 + 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 | 138 + optee/optee_os/core/kernel/notif_default.c | 97 + optee/optee_os/core/kernel/nv_counter.c | 17 + optee/optee_os/core/kernel/otp_stubs.c | 61 + optee/optee_os/core/kernel/panic.c | 92 + optee/optee_os/core/kernel/pm.c | 145 + optee/optee_os/core/kernel/pseudo_ta.c | 422 + optee/optee_os/core/kernel/ree_fs_ta.c | 822 + 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/semihosting.c | 169 + 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 | 66 + optee/optee_os/core/kernel/tee_misc.c | 139 + optee/optee_os/core/kernel/tee_ta_manager.c | 1133 + optee/optee_os/core/kernel/tee_time.c | 43 + optee/optee_os/core/kernel/tee_time_ree.c | 36 + optee/optee_os/core/kernel/thread.c | 695 + optee/optee_os/core/kernel/tpm.c | 166 + optee/optee_os/core/kernel/trace_ext.c | 69 + optee/optee_os/core/kernel/transfer_list.c | 591 + 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 | 332 + optee/optee_os/core/kernel/user_mode_ctx.c | 29 + optee/optee_os/core/kernel/user_ta.c | 532 + optee/optee_os/core/kernel/wait_queue.c | 210 + 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 | 220 + 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 | 782 + 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 | 208 + .../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 | 155 + .../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 | 23 + .../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 | 226 + 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 | 2598 ++ optee/optee_os/core/mm/file.c | 209 + optee/optee_os/core/mm/fobj.c | 818 + optee/optee_os/core/mm/mobj.c | 544 + optee/optee_os/core/mm/pgt_cache.c | 873 + optee/optee_os/core/mm/sub.mk | 9 + optee/optee_os/core/mm/tee_mm.c | 395 + optee/optee_os/core/mm/vm.c | 1355 ++ optee/optee_os/core/pta/apdu.c | 88 + optee/optee_os/core/pta/attestation.c | 802 + 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/device.c | 105 + optee/optee_os/core/pta/gprof.c | 184 + optee/optee_os/core/pta/hwrng.c | 80 + optee/optee_os/core/pta/imx/dek_blob.c | 137 + optee/optee_os/core/pta/imx/digprog.c | 32 + .../core/pta/imx/manufacturing_protection.c | 125 + optee/optee_os/core/pta/imx/ocotp.c | 75 + optee/optee_os/core/pta/imx/sub.mk | 4 + 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 | 246 + 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 | 234 + optee/optee_os/core/pta/stm32mp/bsec_pta.c | 301 + .../core/pta/stm32mp/remoteproc_pta.c | 356 + .../optee_os/core/pta/stm32mp/rproc_pub_key.h | 16 + optee/optee_os/core/pta/stm32mp/sub.mk | 2 + optee/optee_os/core/pta/sub.mk | 31 + optee/optee_os/core/pta/system.c | 399 + .../include/jetson_decrypt_cpubl_payload.h | 78 + .../jetson_user_key_pta_compute_cmac.h | 10 + .../tegra/include/jetson_user_key_pta_ftpm.h | 25 + .../core/pta/tegra/jetson_ftpm_helper_pta.c | 768 + .../tegra/jetson_t194_decrypt_cpubl_payload.c | 226 + .../tegra/jetson_t234_decrypt_cpubl_payload.c | 312 + .../core/pta/tegra/jetson_user_key_pta.c | 1163 + optee/optee_os/core/pta/tegra/sub.mk | 12 + optee/optee_os/core/pta/tests/aes_perf.c | 221 + .../optee_os/core/pta/tests/dt_driver_test.c | 767 + optee/optee_os/core/pta/tests/fs_htree.c | 627 + 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 | 8 + optee/optee_os/core/pta/widevine.c | 182 + optee/optee_os/core/sub.mk | 90 + optee/optee_os/core/tee/entry_std.c | 604 + optee/optee_os/core/tee/fs_dirfile.c | 394 + optee/optee_os/core/tee/fs_htree.c | 937 + optee/optee_os/core/tee/socket.c | 280 + optee/optee_os/core/tee/sub.mk | 54 + optee/optee_os/core/tee/tadb.c | 796 + 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 | 217 + optee/optee_os/core/tee/tee_fs_key_manager.c | 276 + optee/optee_os/core/tee/tee_fs_rpc.c | 219 + optee/optee_os/core/tee/tee_nvme_rpmb_fs.c | 3023 +++ optee/optee_os/core/tee/tee_obj.c | 86 + optee/optee_os/core/tee/tee_pobj.c | 210 + optee/optee_os/core/tee/tee_ree_fs.c | 1108 + optee/optee_os/core/tee/tee_ree_state.c | 23 + optee/optee_os/core/tee/tee_rpmb_fs.c | 3127 +++ optee/optee_os/core/tee/tee_supp_plugin_rpc.c | 91 + optee/optee_os/core/tee/tee_svc.c | 1016 + optee/optee_os/core/tee/tee_svc_cryp.c | 4791 ++++ optee/optee_os/core/tee/tee_svc_storage.c | 931 + optee/optee_os/core/tee/tee_ta_enc_manager.c | 65 + optee/optee_os/core/tee/tee_time_generic.c | 136 + optee/optee_os/core/tee/uuid.c | 48 + optee/optee_os/core/tests/ftmn_boot_tests.c | 208 + optee/optee_os/core/tests/notif_test_wd.c | 128 + optee/optee_os/core/tests/sub.mk | 2 + optee/optee_os/keys/default.pem | 27 + optee/optee_os/keys/default_ta.pem | 1 + optee/optee_os/ldelf/dl.c | 38 + optee/optee_os/ldelf/dl.h | 16 + optee/optee_os/ldelf/ftrace.c | 129 + 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 | 187 + 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 | 2016 ++ optee/optee_os/ldelf/ta_elf.h | 153 + 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 | 60 + 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 | 104 + 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 | 144 + optee/optee_os/lib/libmbedtls/core/ecc.c | 548 + optee/optee_os/lib/libmbedtls/core/hash.c | 244 + optee/optee_os/lib/libmbedtls/core/hmac.c | 174 + .../lib/libmbedtls/core/mbed_helpers.c | 33 + .../lib/libmbedtls/core/mbed_helpers.h | 31 + optee/optee_os/lib/libmbedtls/core/rsa.c | 817 + 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 | 33 + optee/optee_os/lib/libmbedtls/core/tomcrypt.c | 15 + .../optee_os/lib/libmbedtls/include/aes_alt.h | 12 + .../include/mbedtls_config_kernel.h | 136 + .../libmbedtls/include/mbedtls_config_uta.h | 75 + .../lib/libmbedtls/mbedtls/.uncrustify.cfg | 252 + optee/optee_os/lib/libmbedtls/mbedtls/BUGS.md | 20 + .../lib/libmbedtls/mbedtls/CONTRIBUTING.md | 91 + .../optee_os/lib/libmbedtls/mbedtls/ChangeLog | 5527 +++++ optee/optee_os/lib/libmbedtls/mbedtls/LICENSE | 202 + .../optee_os/lib/libmbedtls/mbedtls/README.md | 320 + .../lib/libmbedtls/mbedtls/SECURITY.md | 137 + .../lib/libmbedtls/mbedtls/SUPPORT.md | 16 + optee/optee_os/lib/libmbedtls/mbedtls/dco.txt | 37 + .../libmbedtls/mbedtls/include/mbedtls/aes.h | 634 + .../libmbedtls/mbedtls/include/mbedtls/aria.h | 357 + .../libmbedtls/mbedtls/include/mbedtls/asn1.h | 649 + .../mbedtls/include/mbedtls/asn1write.h | 375 + .../mbedtls/include/mbedtls/base64.h | 94 + .../mbedtls/include/mbedtls/bignum.h | 1106 + .../mbedtls/include/mbedtls/build_info.h | 153 + .../mbedtls/include/mbedtls/camellia.h | 315 + .../libmbedtls/mbedtls/include/mbedtls/ccm.h | 531 + .../mbedtls/include/mbedtls/chacha20.h | 214 + .../mbedtls/include/mbedtls/chachapoly.h | 354 + .../mbedtls/include/mbedtls/check_config.h | 1108 + .../mbedtls/include/mbedtls/cipher.h | 1207 + .../libmbedtls/mbedtls/include/mbedtls/cmac.h | 252 + .../mbedtls/include/mbedtls/compat-2.x.h | 58 + .../mbedtls/include/mbedtls/config_psa.h | 866 + .../mbedtls/include/mbedtls/constant_time.h | 46 + .../mbedtls/include/mbedtls/ctr_drbg.h | 578 + .../mbedtls/include/mbedtls/debug.h | 312 + .../libmbedtls/mbedtls/include/mbedtls/des.h | 397 + .../libmbedtls/mbedtls/include/mbedtls/dhm.h | 984 + .../libmbedtls/mbedtls/include/mbedtls/ecdh.h | 453 + .../mbedtls/include/mbedtls/ecdsa.h | 681 + .../mbedtls/include/mbedtls/ecjpake.h | 309 + .../libmbedtls/mbedtls/include/mbedtls/ecp.h | 1341 + .../mbedtls/include/mbedtls/entropy.h | 291 + .../mbedtls/include/mbedtls/error.h | 212 + .../libmbedtls/mbedtls/include/mbedtls/gcm.h | 382 + .../libmbedtls/mbedtls/include/mbedtls/hkdf.h | 136 + .../mbedtls/include/mbedtls/hmac_drbg.h | 446 + .../mbedtls/include/mbedtls/legacy_or_psa.h | 215 + .../libmbedtls/mbedtls/include/mbedtls/lms.h | 452 + .../mbedtls/include/mbedtls/mbedtls_config.h | 7 + .../libmbedtls/mbedtls/include/mbedtls/md.h | 588 + .../libmbedtls/mbedtls/include/mbedtls/md5.h | 202 + .../include/mbedtls/memory_buffer_alloc.h | 154 + .../mbedtls/include/mbedtls/net_sockets.h | 303 + .../mbedtls/include/mbedtls/nist_kw.h | 178 + .../libmbedtls/mbedtls/include/mbedtls/oid.h | 655 + .../libmbedtls/mbedtls/include/mbedtls/pem.h | 172 + .../libmbedtls/mbedtls/include/mbedtls/pk.h | 1052 + .../mbedtls/include/mbedtls/pkcs12.h | 117 + .../mbedtls/include/mbedtls/pkcs5.h | 136 + .../mbedtls/include/mbedtls/pkcs7.h | 253 + .../mbedtls/include/mbedtls/platform.h | 472 + .../mbedtls/include/mbedtls/platform_time.h | 68 + .../mbedtls/include/mbedtls/platform_util.h | 207 + .../mbedtls/include/mbedtls/poly1305.h | 180 + .../mbedtls/include/mbedtls/private_access.h | 32 + .../mbedtls/include/mbedtls/psa_util.h | 397 + .../mbedtls/include/mbedtls/ripemd160.h | 148 + .../libmbedtls/mbedtls/include/mbedtls/rsa.h | 1149 + .../libmbedtls/mbedtls/include/mbedtls/sha1.h | 231 + .../mbedtls/include/mbedtls/sha256.h | 210 + .../mbedtls/include/mbedtls/sha512.h | 220 + .../libmbedtls/mbedtls/include/mbedtls/ssl.h | 5335 ++++ .../mbedtls/include/mbedtls/ssl_cache.h | 176 + .../include/mbedtls/ssl_ciphersuites.h | 549 + .../mbedtls/include/mbedtls/ssl_cookie.h | 118 + .../mbedtls/include/mbedtls/ssl_ticket.h | 193 + .../mbedtls/include/mbedtls/threading.h | 117 + .../mbedtls/include/mbedtls/timing.h | 106 + .../mbedtls/include/mbedtls/version.h | 90 + .../libmbedtls/mbedtls/include/mbedtls/x509.h | 485 + .../mbedtls/include/mbedtls/x509_crl.h | 196 + .../mbedtls/include/mbedtls/x509_crt.h | 1187 + .../mbedtls/include/mbedtls/x509_csr.h | 337 + .../libmbedtls/mbedtls/include/psa/crypto.h | 4697 ++++ .../include/psa/crypto_builtin_composites.h | 219 + .../include/psa/crypto_builtin_primitives.h | 114 + .../mbedtls/include/psa/crypto_compat.h | 165 + .../mbedtls/include/psa/crypto_config.h | 133 + .../include/psa/crypto_driver_common.h | 56 + .../psa/crypto_driver_contexts_composites.h | 163 + .../psa/crypto_driver_contexts_primitives.h | 117 + .../mbedtls/include/psa/crypto_extra.h | 2141 ++ .../mbedtls/include/psa/crypto_platform.h | 103 + .../mbedtls/include/psa/crypto_se_driver.h | 1395 ++ .../mbedtls/include/psa/crypto_sizes.h | 1173 + .../mbedtls/include/psa/crypto_struct.h | 558 + .../mbedtls/include/psa/crypto_types.h | 465 + .../mbedtls/include/psa/crypto_values.h | 2763 +++ .../lib/libmbedtls/mbedtls/library/aes.c | 2178 ++ .../lib/libmbedtls/mbedtls/library/aesce.c | 411 + .../lib/libmbedtls/mbedtls/library/aesce.h | 116 + .../lib/libmbedtls/mbedtls/library/aesni.c | 800 + .../lib/libmbedtls/mbedtls/library/aesni.h | 166 + .../libmbedtls/mbedtls/library/alignment.h | 520 + .../lib/libmbedtls/mbedtls/library/aria.c | 1003 + .../libmbedtls/mbedtls/library/asn1parse.c | 506 + .../libmbedtls/mbedtls/library/asn1write.c | 481 + .../lib/libmbedtls/mbedtls/library/base64.c | 277 + .../lib/libmbedtls/mbedtls/library/bignum.c | 2773 +++ .../libmbedtls/mbedtls/library/bignum_core.c | 871 + .../libmbedtls/mbedtls/library/bignum_core.h | 767 + .../libmbedtls/mbedtls/library/bignum_mod.c | 434 + .../libmbedtls/mbedtls/library/bignum_mod.h | 481 + .../mbedtls/library/bignum_mod_raw.c | 306 + .../mbedtls/library/bignum_mod_raw.h | 464 + .../mbedtls/library/bignum_mod_raw_invasive.h | 46 + .../lib/libmbedtls/mbedtls/library/bn_mul.h | 1072 + .../lib/libmbedtls/mbedtls/library/camellia.c | 1056 + .../lib/libmbedtls/mbedtls/library/ccm.c | 729 + .../lib/libmbedtls/mbedtls/library/chacha20.c | 509 + .../libmbedtls/mbedtls/library/chachapoly.c | 492 + .../mbedtls/library/check_crypto_config.h | 101 + .../lib/libmbedtls/mbedtls/library/cipher.c | 1622 ++ .../libmbedtls/mbedtls/library/cipher_wrap.c | 2346 ++ .../libmbedtls/mbedtls/library/cipher_wrap.h | 145 + .../lib/libmbedtls/mbedtls/library/cmac.c | 1079 + .../lib/libmbedtls/mbedtls/library/common.h | 167 + .../mbedtls/library/constant_time.c | 1042 + .../mbedtls/library/constant_time_internal.h | 363 + .../mbedtls/library/constant_time_invasive.h | 51 + .../lib/libmbedtls/mbedtls/library/ctr_drbg.c | 893 + .../lib/libmbedtls/mbedtls/library/debug.c | 389 + .../lib/libmbedtls/mbedtls/library/des.c | 1054 + .../lib/libmbedtls/mbedtls/library/dhm.c | 726 + .../lib/libmbedtls/mbedtls/library/ecdh.c | 697 + .../lib/libmbedtls/mbedtls/library/ecdsa.c | 879 + .../lib/libmbedtls/mbedtls/library/ecjpake.c | 1259 + .../lib/libmbedtls/mbedtls/library/ecp.c | 3622 +++ .../libmbedtls/mbedtls/library/ecp_curves.c | 5960 +++++ .../mbedtls/library/ecp_internal_alt.h | 299 + .../libmbedtls/mbedtls/library/ecp_invasive.h | 187 + .../lib/libmbedtls/mbedtls/library/entropy.c | 732 + .../libmbedtls/mbedtls/library/entropy_poll.c | 239 + .../libmbedtls/mbedtls/library/entropy_poll.h | 76 + .../lib/libmbedtls/mbedtls/library/error.c | 879 + .../lib/libmbedtls/mbedtls/library/gcm.c | 1168 + .../libmbedtls/mbedtls/library/hash_info.c | 123 + .../libmbedtls/mbedtls/library/hash_info.h | 101 + .../lib/libmbedtls/mbedtls/library/hkdf.c | 173 + .../libmbedtls/mbedtls/library/hmac_drbg.c | 645 + .../lib/libmbedtls/mbedtls/library/lmots.c | 825 + .../lib/libmbedtls/mbedtls/library/lmots.h | 323 + .../lib/libmbedtls/mbedtls/library/lms.c | 783 + .../lib/libmbedtls/mbedtls/library/md.c | 973 + .../lib/libmbedtls/mbedtls/library/md5.c | 434 + .../lib/libmbedtls/mbedtls/library/md_wrap.h | 81 + .../mbedtls/library/memory_buffer_alloc.c | 757 + .../libmbedtls/mbedtls/library/net_sockets.c | 712 + .../lib/libmbedtls/mbedtls/library/nist_kw.c | 687 + .../lib/libmbedtls/mbedtls/library/oid.c | 885 + .../lib/libmbedtls/mbedtls/library/padlock.c | 167 + .../lib/libmbedtls/mbedtls/library/padlock.h | 120 + .../lib/libmbedtls/mbedtls/library/pem.c | 633 + .../lib/libmbedtls/mbedtls/library/pk.c | 960 + .../lib/libmbedtls/mbedtls/library/pk_wrap.c | 1617 ++ .../lib/libmbedtls/mbedtls/library/pk_wrap.h | 168 + .../lib/libmbedtls/mbedtls/library/pkcs12.c | 454 + .../lib/libmbedtls/mbedtls/library/pkcs5.c | 569 + .../lib/libmbedtls/mbedtls/library/pkcs7.c | 785 + .../lib/libmbedtls/mbedtls/library/pkparse.c | 1528 ++ .../lib/libmbedtls/mbedtls/library/pkwrite.c | 538 + .../lib/libmbedtls/mbedtls/library/pkwrite.h | 108 + .../lib/libmbedtls/mbedtls/library/platform.c | 414 + .../mbedtls/library/platform_util.c | 221 + .../lib/libmbedtls/mbedtls/library/poly1305.c | 504 + .../libmbedtls/mbedtls/library/ripemd160.c | 498 + .../lib/libmbedtls/mbedtls/library/rsa.c | 2588 ++ .../mbedtls/library/rsa_alt_helpers.c | 459 + .../mbedtls/library/rsa_alt_helpers.h | 220 + .../lib/libmbedtls/mbedtls/library/sha1.c | 489 + .../lib/libmbedtls/mbedtls/library/sha256.c | 939 + .../lib/libmbedtls/mbedtls/library/sha512.c | 1108 + .../libmbedtls/mbedtls/library/ssl_cache.c | 423 + .../mbedtls/library/ssl_ciphersuites.c | 2058 ++ .../libmbedtls/mbedtls/library/ssl_client.c | 999 + .../libmbedtls/mbedtls/library/ssl_client.h | 34 + .../libmbedtls/mbedtls/library/ssl_cookie.c | 390 + .../mbedtls/library/ssl_debug_helpers.h | 90 + .../library/ssl_debug_helpers_generated.c | 225 + .../lib/libmbedtls/mbedtls/library/ssl_misc.h | 2769 +++ .../lib/libmbedtls/mbedtls/library/ssl_msg.c | 5917 +++++ .../libmbedtls/mbedtls/library/ssl_ticket.c | 546 + .../lib/libmbedtls/mbedtls/library/ssl_tls.c | 9695 ++++++++ .../mbedtls/library/ssl_tls12_client.c | 3600 +++ .../mbedtls/library/ssl_tls12_server.c | 4341 ++++ .../mbedtls/library/ssl_tls13_client.c | 3064 +++ .../mbedtls/library/ssl_tls13_generic.c | 1627 ++ .../mbedtls/library/ssl_tls13_invasive.h | 35 + .../mbedtls/library/ssl_tls13_keys.c | 1861 ++ .../mbedtls/library/ssl_tls13_keys.h | 663 + .../mbedtls/library/ssl_tls13_server.c | 3084 +++ .../libmbedtls/mbedtls/library/threading.c | 193 + .../lib/libmbedtls/mbedtls/library/timing.c | 166 + .../lib/libmbedtls/mbedtls/library/version.c | 44 + .../mbedtls/library/version_features.c | 808 + .../lib/libmbedtls/mbedtls/library/x509.c | 1641 ++ .../libmbedtls/mbedtls/library/x509_create.c | 368 + .../lib/libmbedtls/mbedtls/library/x509_crl.c | 727 + .../lib/libmbedtls/mbedtls/library/x509_crt.c | 2889 +++ .../lib/libmbedtls/mbedtls/library/x509_csr.c | 588 + .../mbedtls/library/x509write_crt.c | 674 + .../mbedtls/library/x509write_csr.c | 436 + optee/optee_os/lib/libmbedtls/sub.mk | 141 + .../optee_os/lib/libunw/include/unw/unwind.h | 157 + optee/optee_os/lib/libunw/sub.mk | 10 + optee/optee_os/lib/libunw/unwind_arm32.c | 418 + optee/optee_os/lib/libunw/unwind_arm64.c | 95 + optee/optee_os/lib/libunw/unwind_riscv.c | 79 + 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 | 43 + 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 | 1059 + .../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 + .../optee_os/lib/libutee/include/pta_device.h | 29 + .../optee_os/lib/libutee/include/pta_gprof.h | 43 + .../lib/libutee/include/pta_imx_dek_blob.h | 16 + .../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 + .../libutee/include/pta_jetson_ftpm_helper.h | 147 + .../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 + .../optee_os/lib/libutee/include/pta_stats.h | 94 + .../lib/libutee/include/pta_stm32mp_bsec.h | 89 + .../optee_os/lib/libutee/include/pta_system.h | 204 + .../lib/libutee/include/pta_widevine.h | 36 + .../lib/libutee/include/remoteproc_pta.h | 150 + .../lib/libutee/include/riscv_user_sysreg.h | 54 + .../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 | 54 + .../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 | 155 + .../lib/libutee/include/utee_defines.h | 362 + .../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 | 30 + optee/optee_os/lib/libutee/tcb.c | 207 + optee/optee_os/lib/libutee/tee_api.c | 813 + .../optee_os/lib/libutee/tee_api_arith_mpi.c | 1014 + optee/optee_os/lib/libutee/tee_api_objects.c | 1054 + .../optee_os/lib/libutee/tee_api_operations.c | 2710 +++ 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/mcount_rv.S | 122 + .../lib/libutils/ext/arch/riscv/sub.mk | 4 + .../lib/libutils/ext/consttime_memcmp.c | 51 + .../lib/libutils/ext/fault_mitigation.c | 153 + .../optee_os/lib/libutils/ext/ftrace/ftrace.c | 150 + .../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 | 91 + .../lib/libutils/ext/include/atomic.h | 66 + .../lib/libutils/ext/include/bitstring.h | 159 + .../lib/libutils/ext/include/compiler.h | 287 + .../lib/libutils/ext/include/config.h | 68 + .../ext/include/confine_array_index.h | 157 + .../libutils/ext/include/fault_mitigation.h | 690 + .../lib/libutils/ext/include/mempool.h | 77 + .../lib/libutils/ext/include/memtag.h | 234 + .../lib/libutils/ext/include/printk.h | 28 + .../optee_os/lib/libutils/ext/include/riscv.S | 14 + .../ext/include/speculation_barrier.h | 574 + .../lib/libutils/ext/include/stdlib_ext.h | 18 + .../lib/libutils/ext/include/string_ext.h | 55 + .../optee_os/lib/libutils/ext/include/trace.h | 153 + .../lib/libutils/ext/include/trace_levels.h | 36 + .../lib/libutils/ext/include/types_ext.h | 37 + .../optee_os/lib/libutils/ext/include/util.h | 208 + optee/optee_os/lib/libutils/ext/mempool.c | 188 + .../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 | 311 + .../isoc/arch/arm/arm32_aeabi_divmod.c | 153 + .../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 | 83 + .../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 | 1141 + 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 | 77 + .../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 | 168 + .../lib/libutils/isoc/include/memory.h | 9 + .../lib/libutils/isoc/include/setjmp.h | 79 + .../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/fcntl.h | 23 + .../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 | 195 + optee/optee_os/mk/cc-option.mk | 17 + optee/optee_os/mk/checkconf.mk | 183 + 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 | 308 + optee/optee_os/mk/config.mk | 1237 + optee/optee_os/mk/gcc.mk | 36 + optee/optee_os/mk/lib.mk | 103 + optee/optee_os/mk/macros.mk | 9 + optee/optee_os/mk/subdir.mk | 184 + .../optee_os/prebuilt/t234/libcommon_crypto.a | Bin 0 -> 399780 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/derive_rpmb_key.py | 134 + optee/optee_os/scripts/ftrace_format.py | 79 + .../optee_os/scripts/gen_compile_commands.py | 237 + 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/sign_rproc_fw.py | 508 + optee/optee_os/scripts/symbolize.py | 570 + optee/optee_os/scripts/tee_bin_parser.py | 61 + optee/optee_os/scripts/ts_bin_to_c.py | 196 + optee/optee_os/scripts/update_changelog.py | 101 + optee/optee_os/ta/arch/arm/ta.ld.S | 103 + optee/optee_os/ta/arch/arm/ta_entry_a32.S | 23 + optee/optee_os/ta/arch/riscv/ta.ld.S | 96 + optee/optee_os/ta/avb/Makefile | 18 + optee/optee_os/ta/avb/entry.c | 401 + 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 | 124 + 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 | 156 + optee/optee_os/ta/pkcs11/Android.mk | 3 + optee/optee_os/ta/pkcs11/Makefile | 9 + optee/optee_os/ta/pkcs11/include/pkcs11_ta.h | 1368 ++ .../ta/pkcs11/scripts/dump_ec_curve_params.sh | 30 + .../ta/pkcs11/scripts/verify-helpers.sh | 103 + optee/optee_os/ta/pkcs11/src/attributes.c | 460 + 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 | 119 + optee/optee_os/ta/pkcs11/src/handle.h | 53 + optee/optee_os/ta/pkcs11/src/object.c | 1285 + optee/optee_os/ta/pkcs11/src/object.h | 90 + .../optee_os/ta/pkcs11/src/persistent_token.c | 714 + .../ta/pkcs11/src/pkcs11_attributes.c | 3039 +++ .../ta/pkcs11/src/pkcs11_attributes.h | 227 + optee/optee_os/ta/pkcs11/src/pkcs11_helpers.c | 844 + optee/optee_os/ta/pkcs11/src/pkcs11_helpers.h | 105 + optee/optee_os/ta/pkcs11/src/pkcs11_token.c | 1671 ++ optee/optee_os/ta/pkcs11/src/pkcs11_token.h | 355 + optee/optee_os/ta/pkcs11/src/processing.c | 1297 + optee/optee_os/ta/pkcs11/src/processing.h | 286 + optee/optee_os/ta/pkcs11/src/processing_aes.c | 567 + .../optee_os/ta/pkcs11/src/processing_asymm.c | 1110 + .../ta/pkcs11/src/processing_digest.c | 219 + optee/optee_os/ta/pkcs11/src/processing_ec.c | 965 + optee/optee_os/ta/pkcs11/src/processing_rsa.c | 777 + .../optee_os/ta/pkcs11/src/processing_symm.c | 1243 + .../optee_os/ta/pkcs11/src/sanitize_object.c | 430 + .../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 | 465 + .../ta/pkcs11/src/token_capabilities.h | 40 + .../ta/pkcs11/src/user_ta_header_defines.h | 26 + optee/optee_os/ta/pkcs11/sub.mk | 18 + optee/optee_os/ta/pkcs11/user_ta.mk | 8 + optee/optee_os/ta/remoteproc/Makefile | 18 + .../ta/remoteproc/include/ta_remoteproc.h | 64 + optee/optee_os/ta/remoteproc/src/elf_parser.c | 175 + optee/optee_os/ta/remoteproc/src/elf_parser.h | 91 + .../ta/remoteproc/src/remoteproc_core.c | 1107 + optee/optee_os/ta/remoteproc/src/sub.mk | 2 + .../remoteproc/src/user_ta_header_defines.h | 29 + optee/optee_os/ta/remoteproc/sub.mk | 3 + optee/optee_os/ta/remoteproc/user_ta.mk | 4 + optee/optee_os/ta/ta.mk | 218 + 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 | 36 + .../.github/workflows/stale_issue.yml | 28 + optee/optee_test/Android.mk | 173 + 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/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 | 149 + optee/optee_test/host/xtest/LICENSE | 339 + optee/optee_test/host/xtest/Makefile | 234 + .../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 + .../aes_gcm_counter_overflow_test_decrypt.h | 689 + .../aes_gcm_counter_overflow_test_encrypt.h | 689 + optee/optee_test/host/xtest/asym_perf.c | 966 + optee/optee_test/host/xtest/benchmark_1000.c | 145 + optee/optee_test/host/xtest/benchmark_2000.c | 97 + optee/optee_test/host/xtest/clear_storage.c | 58 + optee/optee_test/host/xtest/clear_storage.h | 11 + optee/optee_test/host/xtest/crypto_common.h | 53 + optee/optee_test/host/xtest/ffa_spmc_1000.c | 534 + 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 + .../gp/patches/0016-TEE_Crypto_API.xml.patch | 134 + .../optee_test/host/xtest/gp/prepare_suite.sh | 26 + optee/optee_test/host/xtest/hash_perf.c | 496 + .../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 | 10019 ++++++++ optee/optee_test/host/xtest/pkcs11_1000.h | 12 + 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 | 3363 +++ optee/optee_test/host/xtest/regression_2000.c | 929 + optee/optee_test/host/xtest/regression_4000.c | 6200 +++++ .../host/xtest/regression_4000_data.h | 9070 +++++++ 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 | 2318 ++ 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 | 698 + 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 | 371 + optee/optee_test/host/xtest/stats.h | 12 + .../optee_test/host/xtest/symm_cipher_perf.c | 753 + 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 | 292 + optee/optee_test/host/xtest/xtest_test.c | 208 + optee/optee_test/host/xtest/xtest_test.h | 147 + .../host/xtest/xtest_uuid_helpers.c | 175 + .../host/xtest/xtest_uuid_helpers.h | 34 + optee/optee_test/scripts/aes_gcm_test.py | 80 + 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 | 120 + optee/optee_test/ta/Android.mk | 2 + optee/optee_test/ta/CMakeLists.txt | 27 + optee/optee_test/ta/Makefile | 63 + 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 + optee/optee_test/ta/crypto_perf/Android.mk | 4 + optee/optee_test/ta/crypto_perf/Makefile | 4 + .../ta/crypto_perf/include/ta_crypto_perf.h | 147 + .../crypto_perf/include/ta_crypto_perf_priv.h | 27 + .../include/user_ta_header_defines.h | 18 + optee/optee_test/ta/crypto_perf/sub.mk | 3 + .../ta/crypto_perf/ta_crypto_perf.c | 992 + optee/optee_test/ta/crypto_perf/ta_entry.c | 92 + .../enc_fs/include/enc_fs_key_manager_test.h | 17 + 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 | 55 + 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 | 50 + .../ta/os_test/include/ta_os_test.h | 51 + .../ta/os_test/include/tb_asserts.h | 153 + .../optee_test/ta/os_test/include/tb_macros.h | 57 + .../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 | 1603 ++ optee/optee_test/ta/os_test/pauth_a64.S | 23 + optee/optee_test/ta/os_test/sub.mk | 31 + optee/optee_test/ta/os_test/ta_arm_pauth.c | 54 + optee/optee_test/ta/os_test/ta_entry.c | 187 + 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 | 164 + 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 | 367 + 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 | 45 + .../storage/include/user_ta_header_defines.h | 23 + optee/optee_test/ta/storage/storage.c | 740 + optee/optee_test/ta/storage/sub.mk | 4 + optee/optee_test/ta/storage/ta_entry.c | 128 + 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 | 405 + .../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/cpubl-payload-dec/LICENSE | 23 + optee/samples/cpubl-payload-dec/Makefile | 25 + optee/samples/cpubl-payload-dec/ta/Makefile | 7 + optee/samples/cpubl-payload-dec/ta/entry.c | 119 + .../ta/include/ta_cpubl_dec.h | 16 + optee/samples/cpubl-payload-dec/ta/sub.mk | 3 + optee/samples/cpubl-payload-dec/ta/user_ta.mk | 2 + .../ta/user_ta_header_defines.h | 19 + optee/samples/ftpm-helper/LICENSE | 23 + optee/samples/ftpm-helper/Makefile | 35 + optee/samples/ftpm-helper/README.md | 1872 ++ optee/samples/ftpm-helper/host/Makefile | 39 + .../samples/ftpm-helper/host/ftpm_helper_ca.c | 716 + .../host/tool/conf/ftpm_i_ca_sim.config | 22 + .../host/tool/conf/ftpm_root_ca_sim.config | 21 + .../host/tool/ftpm_device_provision.sh | 154 + .../tool/ftpm_manufacturer_ca_sign_sid_csr.py | 163 + .../tool/ftpm_manufacturer_ca_sign_sid_csr.sh | 152 + .../tool/ftpm_manufacturer_ca_simulator.py | 184 + .../tool/ftpm_manufacturer_ca_simulator.sh | 158 + .../host/tool/ftpm_manufacturer_gen_ek_csr.sh | 110 + .../tool/ftpm_manufacturer_gen_ek_csr_tool.py | 103 + .../tool/ftpm_offline_provisioning_verify.sh | 87 + .../host/tool/ftpm_test_local_attestation.sh | 133 + .../samples/ftpm-helper/host/tool/kdk_gen.py | 267 + .../ftpm-helper/host/tool/lib/aes_drbg.py | 435 + .../ftpm-helper/host/tool/lib/ftpm_ek.py | 676 + .../ftpm-helper/host/tool/lib/ftpm_ek_csr.py | 124 + .../host/tool/lib/silicon_id_csr.py | 86 + .../ftpm-helper/host/tool/odm_ekb_gen.py | 439 + .../ftpm-helper/host/tool/oem_ekb_gen.py | 259 + optee/samples/ftpm-helper/ta/Makefile | 7 + optee/samples/ftpm-helper/ta/ftpm_helper_ta.c | 480 + .../ftpm-helper/ta/include/ftpm_helper_ta.h | 135 + optee/samples/ftpm-helper/ta/sub.mk | 6 + .../ftpm-helper/ta/user_ta_header_defines.h | 18 + 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 | 143 + .../hwkey-agent/host/tool/gen_ekb/example.sh | 31 + .../hwkey-agent/host/tool/gen_ekb/gen_ekb.py | 271 + optee/samples/hwkey-agent/ta/Makefile | 7 + optee/samples/hwkey-agent/ta/hwkey_agent_ta.c | 248 + .../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/samples/ms-tpm-20-ref/.clang-format | 97 + optee/samples/ms-tpm-20-ref/.travis.yml | 38 + optee/samples/ms-tpm-20-ref/CONTRIBUTING.md | 42 + .../samples/ms-tpm-20-ref/CppProperties.json | 21 + optee/samples/ms-tpm-20-ref/LICENSE | 17 + optee/samples/ms-tpm-20-ref/README.md | 67 + optee/samples/ms-tpm-20-ref/SECURITY.md | 41 + .../Samples/ARM32-FirmwareTPM/README.md | 112 + .../ARM32-FirmwareTPM/optee_ta/Makefile | 25 + .../ARM32-FirmwareTPM/optee_ta/fTPM/Makefile | 37 + .../ARM32-FirmwareTPM/optee_ta/fTPM/fTPM.c | 589 + .../fTPM/include/Wolf/TpmToWolfHash.h | 199 + .../fTPM/include/Wolf/TpmToWolfMath.h | 91 + .../optee_ta/fTPM/include/Wolf/TpmToWolfSym.h | 120 + .../fTPM/include/Wolf/user_settings.h | 108 + .../optee_ta/fTPM/include/fTPM.h | 106 + .../optee_ta/fTPM/include/fTPM_event_log.h | 13 + .../fTPM/include/fTPM_event_log_private.h | 269 + .../optee_ta/fTPM/include/fTPM_helpers.h | 15 + .../optee_ta/fTPM/lib/mbedtls_ltc/sub.mk | 24 + .../fTPM/lib/mbedtls_ltc/user_custom.h | 14 + .../optee_ta/fTPM/lib/sub.mk | 2 + .../optee_ta/fTPM/lib/tpm/sub.mk | 258 + .../optee_ta/fTPM/lib/wolf/sub.mk | 58 + .../optee_ta/fTPM/platform/AdminPPI.c | 426 + .../optee_ta/fTPM/platform/Cancel.c | 80 + .../optee_ta/fTPM/platform/Clock.c | 348 + .../optee_ta/fTPM/platform/DebugHelpers.c | 41 + .../optee_ta/fTPM/platform/EPS.c | 91 + .../optee_ta/fTPM/platform/Entropy.c | 128 + .../optee_ta/fTPM/platform/EventLogPrint.c | 283 + .../optee_ta/fTPM/platform/LocalityPlat.c | 65 + .../optee_ta/fTPM/platform/NVMem.c | 666 + .../optee_ta/fTPM/platform/NvAdmin.c | 151 + .../optee_ta/fTPM/platform/PPPlat.c | 80 + .../optee_ta/fTPM/platform/PlatformACT.c | 345 + .../optee_ta/fTPM/platform/PlatformData.c | 82 + .../optee_ta/fTPM/platform/PowerPlat.c | 113 + .../optee_ta/fTPM/platform/RunCommand.c | 90 + .../optee_ta/fTPM/platform/Unique.c | 102 + .../optee_ta/fTPM/platform/fTPM_event_log.c | 391 + .../optee_ta/fTPM/platform/fTPM_helpers.c | 26 + .../optee_ta/fTPM/platform/include/Admin.h | 230 + .../optee_ta/fTPM/platform/include/Platform.h | 52 + .../fTPM/platform/include/PlatformData.h | 137 + .../fTPM/platform/include/Platform_fp.h | 529 + .../optee_ta/fTPM/reference/RuntimeSupport.c | 84 + .../fTPM/reference/include/RuntimeSupport.h | 94 + .../fTPM/reference/include/TpmProfile.h | 804 + .../optee_ta/fTPM/reference/include/TpmSal.h | 115 + .../fTPM/reference/include/VendorString.h | 93 + .../optee_ta/fTPM/reference/include/bool.h | 51 + .../ARM32-FirmwareTPM/optee_ta/fTPM/sub.mk | 31 + .../optee_ta/fTPM/user_ta_header_defines.h | 56 + .../ta_prod_signing_scripts/README.md | 17 + .../generate_digest.py | 90 + .../ta_prod_signing_scripts/stitch_ta.py | 104 + .../Samples/Nucleo-TPM/L476RG/.cproject | 311 + .../Samples/Nucleo-TPM/L476RG/.mxproject | 14 + .../Samples/Nucleo-TPM/L476RG/.project | 155 + ...lic.truestudio.debug.hardware_device.prefs | 11 + .../L476RG/.settings/language.settings.xml | 20 + .../org.eclipse.cdt.managedbuilder.core.prefs | 11 + .../Device/ST/STM32L4xx/Include/stm32l476xx.h | 18537 ++++++++++++++ .../Device/ST/STM32L4xx/Include/stm32l4xx.h | 257 + .../ST/STM32L4xx/Include/system_stm32l4xx.h | 123 + .../Drivers/CMSIS/Include/arm_common_tables.h | 136 + .../Drivers/CMSIS/Include/arm_const_structs.h | 79 + .../L476RG/Drivers/CMSIS/Include/arm_math.h | 7154 ++++++ .../Drivers/CMSIS/Include/cmsis_armcc.h | 734 + .../Drivers/CMSIS/Include/cmsis_armcc_V6.h | 1800 ++ .../L476RG/Drivers/CMSIS/Include/cmsis_gcc.h | 1373 ++ .../L476RG/Drivers/CMSIS/Include/core_cm0.h | 798 + .../Drivers/CMSIS/Include/core_cm0plus.h | 914 + .../L476RG/Drivers/CMSIS/Include/core_cm3.h | 1763 ++ .../L476RG/Drivers/CMSIS/Include/core_cm4.h | 1937 ++ .../L476RG/Drivers/CMSIS/Include/core_cm7.h | 2512 ++ .../Drivers/CMSIS/Include/core_cmFunc.h | 87 + .../Drivers/CMSIS/Include/core_cmInstr.h | 87 + .../Drivers/CMSIS/Include/core_cmSimd.h | 96 + .../L476RG/Drivers/CMSIS/Include/core_sc000.h | 926 + .../L476RG/Drivers/CMSIS/Include/core_sc300.h | 1745 ++ .../Inc/Legacy/stm32_hal_legacy.h | 3309 +++ .../STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal.h | 669 + .../Inc/stm32l4xx_hal_cortex.h | 433 + .../Inc/stm32l4xx_hal_def.h | 213 + .../Inc/stm32l4xx_hal_dma.h | 766 + .../Inc/stm32l4xx_hal_dma_ex.h | 298 + .../Inc/stm32l4xx_hal_flash.h | 1022 + .../Inc/stm32l4xx_hal_flash_ex.h | 134 + .../Inc/stm32l4xx_hal_flash_ramfunc.h | 126 + .../Inc/stm32l4xx_hal_gpio.h | 316 + .../Inc/stm32l4xx_hal_gpio_ex.h | 822 + .../Inc/stm32l4xx_hal_i2c.h | 708 + .../Inc/stm32l4xx_hal_i2c_ex.h | 186 + .../Inc/stm32l4xx_hal_pcd.h | 874 + .../Inc/stm32l4xx_hal_pcd_ex.h | 136 + .../Inc/stm32l4xx_hal_pwr.h | 427 + .../Inc/stm32l4xx_hal_pwr_ex.h | 906 + .../Inc/stm32l4xx_hal_rcc.h | 4594 ++++ .../Inc/stm32l4xx_hal_rcc_ex.h | 3018 +++ .../Inc/stm32l4xx_hal_rng.h | 325 + .../Inc/stm32l4xx_hal_rtc.h | 861 + .../Inc/stm32l4xx_hal_rtc_ex.h | 1100 + .../Inc/stm32l4xx_hal_tim.h | 2043 ++ .../Inc/stm32l4xx_hal_tim_ex.h | 484 + .../Inc/stm32l4xx_hal_uart.h | 1638 ++ .../Inc/stm32l4xx_hal_uart_ex.h | 771 + .../Inc/stm32l4xx_ll_usb.h | 617 + .../STM32L4xx_HAL_Driver/Src/stm32l4xx_hal.c | 693 + .../Src/stm32l4xx_hal_cortex.c | 539 + .../Src/stm32l4xx_hal_dma.c | 1179 + .../Src/stm32l4xx_hal_dma_ex.c | 319 + .../Src/stm32l4xx_hal_flash.c | 835 + .../Src/stm32l4xx_hal_flash_ex.c | 1305 + .../Src/stm32l4xx_hal_flash_ramfunc.c | 271 + .../Src/stm32l4xx_hal_gpio.c | 568 + .../Src/stm32l4xx_hal_i2c.c | 4868 ++++ .../Src/stm32l4xx_hal_i2c_ex.c | 355 + .../Src/stm32l4xx_hal_pcd.c | 1675 ++ .../Src/stm32l4xx_hal_pcd_ex.c | 523 + .../Src/stm32l4xx_hal_pwr.c | 674 + .../Src/stm32l4xx_hal_pwr_ex.c | 1399 ++ .../Src/stm32l4xx_hal_rcc.c | 1730 ++ .../Src/stm32l4xx_hal_rcc_ex.c | 3358 +++ .../Src/stm32l4xx_hal_rng.c | 527 + .../Src/stm32l4xx_hal_rtc.c | 1539 ++ .../Src/stm32l4xx_hal_rtc_ex.c | 1875 ++ .../Src/stm32l4xx_hal_tim.c | 5675 +++++ .../Src/stm32l4xx_hal_tim_ex.c | 2243 ++ .../Src/stm32l4xx_hal_uart.c | 3448 +++ .../Src/stm32l4xx_hal_uart_ex.c | 900 + .../Src/stm32l4xx_ll_usb.c | 2397 ++ .../Samples/Nucleo-TPM/L476RG/Inc/main.h | 100 + .../L476RG/Inc/stm32l4xx_hal_conf.h | 430 + .../Nucleo-TPM/L476RG/Inc/stm32l4xx_it.h | 59 + .../Nucleo-TPM/L476RG/Inc/usb_device.h | 115 + .../Nucleo-TPM/L476RG/Inc/usbd_cdc_if.h | 158 + .../Samples/Nucleo-TPM/L476RG/Inc/usbd_conf.h | 204 + .../Samples/Nucleo-TPM/L476RG/Inc/usbd_desc.h | 156 + .../Class/CDC/Inc/usbd_cdc.h | 179 + .../Class/CDC/Src/usbd_cdc.c | 925 + .../Core/Inc/usbd_core.h | 167 + .../Core/Inc/usbd_ctlreq.h | 113 + .../Core/Inc/usbd_def.h | 330 + .../Core/Inc/usbd_ioreq.h | 128 + .../Core/Src/usbd_core.c | 565 + .../Core/Src/usbd_ctlreq.c | 782 + .../Core/Src/usbd_ioreq.c | 236 + .../L476RG/Nucleo-L476RG.elf.launch | 67 + .../Nucleo-TPM/L476RG/Nucleo-L476RG.ioc | 227 + .../Nucleo-TPM/L476RG/Nucleo-L476RG.pdf | Bin 0 -> 249470 bytes .../Nucleo-TPM/L476RG/Nucleo-L476RG.txt | 65 + .../Nucleo-TPM/L476RG/STM32L476RG_FLASH.ld | 204 + .../Samples/Nucleo-TPM/L476RG/Src/main.c | 409 + .../Nucleo-TPM/L476RG/Src/stm32l4xx_hal_msp.c | 225 + .../Nucleo-TPM/L476RG/Src/stm32l4xx_it.c | 88 + .../Nucleo-TPM/L476RG/Src/system_stm32l4xx.c | 353 + .../Nucleo-TPM/L476RG/Src/usb_device.c | 173 + .../Nucleo-TPM/L476RG/Src/usbd_cdc_if.c | 392 + .../Samples/Nucleo-TPM/L476RG/Src/usbd_conf.c | 894 + .../Samples/Nucleo-TPM/L476RG/Src/usbd_desc.c | 405 + .../Samples/Nucleo-TPM/L476RG/mx.scratch | 91 + .../L476RG/startup/startup_stm32l476xx.s | 524 + .../Samples/Nucleo-TPM/L4A6RG/.cproject | 325 + .../Samples/Nucleo-TPM/L4A6RG/.mxproject | 14 + .../Samples/Nucleo-TPM/L4A6RG/.project | 160 + ...lic.truestudio.debug.hardware_device.prefs | 11 + .../L4A6RG/.settings/language.settings.xml | 20 + .../org.eclipse.cdt.managedbuilder.core.prefs | 11 + .../Device/ST/STM32L4xx/Include/stm32l4a6xx.h | 20127 ++++++++++++++++ .../Device/ST/STM32L4xx/Include/stm32l4xx.h | 257 + .../ST/STM32L4xx/Include/system_stm32l4xx.h | 123 + .../Drivers/CMSIS/Include/arm_common_tables.h | 136 + .../Drivers/CMSIS/Include/arm_const_structs.h | 79 + .../L4A6RG/Drivers/CMSIS/Include/arm_math.h | 7154 ++++++ .../Drivers/CMSIS/Include/cmsis_armcc.h | 734 + .../Drivers/CMSIS/Include/cmsis_armcc_V6.h | 1800 ++ .../L4A6RG/Drivers/CMSIS/Include/cmsis_gcc.h | 1373 ++ .../L4A6RG/Drivers/CMSIS/Include/core_cm0.h | 798 + .../Drivers/CMSIS/Include/core_cm0plus.h | 914 + .../L4A6RG/Drivers/CMSIS/Include/core_cm3.h | 1763 ++ .../L4A6RG/Drivers/CMSIS/Include/core_cm4.h | 1937 ++ .../L4A6RG/Drivers/CMSIS/Include/core_cm7.h | 2512 ++ .../Drivers/CMSIS/Include/core_cmFunc.h | 87 + .../Drivers/CMSIS/Include/core_cmInstr.h | 87 + .../Drivers/CMSIS/Include/core_cmSimd.h | 96 + .../L4A6RG/Drivers/CMSIS/Include/core_sc000.h | 926 + .../L4A6RG/Drivers/CMSIS/Include/core_sc300.h | 1745 ++ .../Inc/Legacy/stm32_hal_legacy.h | 3309 +++ .../STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal.h | 669 + .../Inc/stm32l4xx_hal_cortex.h | 433 + .../Inc/stm32l4xx_hal_def.h | 213 + .../Inc/stm32l4xx_hal_dma.h | 766 + .../Inc/stm32l4xx_hal_dma_ex.h | 298 + .../Inc/stm32l4xx_hal_flash.h | 1022 + .../Inc/stm32l4xx_hal_flash_ex.h | 134 + .../Inc/stm32l4xx_hal_flash_ramfunc.h | 126 + .../Inc/stm32l4xx_hal_gpio.h | 316 + .../Inc/stm32l4xx_hal_gpio_ex.h | 822 + .../Inc/stm32l4xx_hal_i2c.h | 708 + .../Inc/stm32l4xx_hal_i2c_ex.h | 186 + .../Inc/stm32l4xx_hal_pcd.h | 874 + .../Inc/stm32l4xx_hal_pcd_ex.h | 136 + .../Inc/stm32l4xx_hal_pwr.h | 427 + .../Inc/stm32l4xx_hal_pwr_ex.h | 906 + .../Inc/stm32l4xx_hal_rcc.h | 4594 ++++ .../Inc/stm32l4xx_hal_rcc_ex.h | 3018 +++ .../Inc/stm32l4xx_hal_rng.h | 325 + .../Inc/stm32l4xx_hal_rtc.h | 861 + .../Inc/stm32l4xx_hal_rtc_ex.h | 1100 + .../Inc/stm32l4xx_hal_tim.h | 2043 ++ .../Inc/stm32l4xx_hal_tim_ex.h | 484 + .../Inc/stm32l4xx_hal_uart.h | 1638 ++ .../Inc/stm32l4xx_hal_uart_ex.h | 771 + .../Inc/stm32l4xx_ll_usb.h | 617 + .../STM32L4xx_HAL_Driver/Src/stm32l4xx_hal.c | 693 + .../Src/stm32l4xx_hal_cortex.c | 539 + .../Src/stm32l4xx_hal_dma.c | 1179 + .../Src/stm32l4xx_hal_dma_ex.c | 319 + .../Src/stm32l4xx_hal_flash.c | 835 + .../Src/stm32l4xx_hal_flash_ex.c | 1305 + .../Src/stm32l4xx_hal_flash_ramfunc.c | 271 + .../Src/stm32l4xx_hal_gpio.c | 568 + .../Src/stm32l4xx_hal_i2c.c | 4868 ++++ .../Src/stm32l4xx_hal_i2c_ex.c | 355 + .../Src/stm32l4xx_hal_pcd.c | 1675 ++ .../Src/stm32l4xx_hal_pcd_ex.c | 523 + .../Src/stm32l4xx_hal_pwr.c | 674 + .../Src/stm32l4xx_hal_pwr_ex.c | 1399 ++ .../Src/stm32l4xx_hal_rcc.c | 1730 ++ .../Src/stm32l4xx_hal_rcc_ex.c | 3358 +++ .../Src/stm32l4xx_hal_rng.c | 527 + .../Src/stm32l4xx_hal_rtc.c | 1539 ++ .../Src/stm32l4xx_hal_rtc_ex.c | 1875 ++ .../Src/stm32l4xx_hal_tim.c | 5675 +++++ .../Src/stm32l4xx_hal_tim_ex.c | 2243 ++ .../Src/stm32l4xx_hal_uart.c | 3448 +++ .../Src/stm32l4xx_hal_uart_ex.c | 900 + .../Src/stm32l4xx_ll_usb.c | 2397 ++ .../Samples/Nucleo-TPM/L4A6RG/Inc/main.h | 90 + .../L4A6RG/Inc/stm32l4xx_hal_conf.h | 430 + .../Nucleo-TPM/L4A6RG/Inc/stm32l4xx_it.h | 67 + .../Nucleo-TPM/L4A6RG/Inc/usb_device.h | 114 + .../Nucleo-TPM/L4A6RG/Inc/usbd_cdc_if.h | 158 + .../Samples/Nucleo-TPM/L4A6RG/Inc/usbd_conf.h | 204 + .../Samples/Nucleo-TPM/L4A6RG/Inc/usbd_desc.h | 156 + .../Class/CDC/Inc/usbd_cdc.h | 179 + .../Class/CDC/Src/usbd_cdc.c | 925 + .../Core/Inc/usbd_core.h | 167 + .../Core/Inc/usbd_ctlreq.h | 113 + .../Core/Inc/usbd_def.h | 330 + .../Core/Inc/usbd_ioreq.h | 128 + .../Core/Src/usbd_core.c | 565 + .../Core/Src/usbd_ctlreq.c | 782 + .../Core/Src/usbd_ioreq.c | 236 + .../L4A6RG/Nucleo-L4A6RG.elf.launch | 67 + .../Nucleo-TPM/L4A6RG/Nucleo-L4A6RG.ioc | 192 + .../Nucleo-TPM/L4A6RG/Nucleo-L4A6RG.pdf | Bin 0 -> 253594 bytes .../Nucleo-TPM/L4A6RG/Nucleo-L4A6RG.txt | 63 + .../Nucleo-TPM/L4A6RG/STM32L4A6RG_FLASH.ld | 186 + .../Samples/Nucleo-TPM/L4A6RG/Src/main.c | 401 + .../Nucleo-TPM/L4A6RG/Src/stm32l4xx_hal_msp.c | 225 + .../Nucleo-TPM/L4A6RG/Src/stm32l4xx_it.c | 212 + .../Nucleo-TPM/L4A6RG/Src/system_stm32l4xx.c | 353 + .../Nucleo-TPM/L4A6RG/Src/usb_device.c | 173 + .../Nucleo-TPM/L4A6RG/Src/usbd_cdc_if.c | 392 + .../Samples/Nucleo-TPM/L4A6RG/Src/usbd_conf.c | 894 + .../Samples/Nucleo-TPM/L4A6RG/Src/usbd_desc.c | 405 + .../Samples/Nucleo-TPM/L4A6RG/mx.scratch | 91 + .../L4A6RG/startup/startup_stm32l4a6xx.s | 563 + .../Shared/Platform/include/PlatformData.h | 126 + .../Platform/include/prototypes/Platform_fp.h | 443 + .../Nucleo-TPM/Shared/Platform/src/Cancel.c | 81 + .../Nucleo-TPM/Shared/Platform/src/Clock.c | 246 + .../Nucleo-TPM/Shared/Platform/src/Entropy.c | 104 + .../Shared/Platform/src/LocalityPlat.c | 66 + .../Nucleo-TPM/Shared/Platform/src/NVMem.c | 558 + .../Nucleo-TPM/Shared/Platform/src/PPPlat.c | 81 + .../Shared/Platform/src/PlatformData.c | 76 + .../Shared/Platform/src/PowerPlat.c | 114 + .../Shared/Platform/src/RunCommand.c | 91 + .../Nucleo-TPM/Shared/Platform/src/Unique.c | 85 + .../Shared/TPMDevice/include/StmUtil.h | 35 + .../Shared/TPMDevice/include/TpmDevice.h | 78 + .../Shared/TPMDevice/include/user_settings.h | 54 + .../Nucleo-TPM/Shared/TPMDevice/src/StmUtil.c | 141 + .../Shared/TPMDevice/src/TpmDevice.c | 964 + .../Samples/Nucleo-TPM/Shared/syscalls.c | 296 + .../Samples/Nucleo-TPM/USB_Hookup.jpg | Bin 0 -> 838421 bytes .../Samples/Nucleo-TPM/VCOM/VCOM-TPM.sln | 31 + .../Nucleo-TPM/VCOM/VCOM-TPM/VCOM-TPM.cpp | Bin 0 -> 13340 bytes .../Nucleo-TPM/VCOM/VCOM-TPM/VCOM-TPM.vcxproj | 163 + .../VCOM/VCOM-TPM/VCOM-TPM.vcxproj.filters | 33 + .../Nucleo-TPM/VCOM/VCOM-TPM/stdafx.cpp | Bin 0 -> 592 bytes .../Samples/Nucleo-TPM/VCOM/VCOM-TPM/stdafx.h | Bin 0 -> 3116 bytes .../Nucleo-TPM/VCOM/VCOM-TPM/targetver.h | Bin 0 -> 630 bytes .../Samples/Nucleo-TPM/microUSB_Hookup.jpg | Bin 0 -> 858243 bytes .../TPMCmd-DeviceID/Platform/src/EPS.c | 285 + .../build-tpmsimulator-deviceid | 52 + .../samples/ms-tpm-20-ref/TPMCmd/Makefile.am | 62 + .../TPMCmd/Platform/include/Platform.h | 51 + .../TPMCmd/Platform/include/PlatformACT.h | 181 + .../TPMCmd/Platform/include/PlatformClock.h | 69 + .../TPMCmd/Platform/include/PlatformData.h | 125 + .../Platform/include/prototypes/Platform_fp.h | 403 + .../TPMCmd/Platform/platform.vcxproj | 509 + .../TPMCmd/Platform/platform.vcxproj.filters | 66 + .../TPMCmd/Platform/src/Cancel.c | 70 + .../ms-tpm-20-ref/TPMCmd/Platform/src/Clock.c | 258 + .../TPMCmd/Platform/src/DebugHelpers.c | 120 + .../TPMCmd/Platform/src/Entropy.c | 149 + .../TPMCmd/Platform/src/LocalityPlat.c | 57 + .../ms-tpm-20-ref/TPMCmd/Platform/src/NVMem.c | 372 + .../TPMCmd/Platform/src/PPPlat.c | 70 + .../TPMCmd/Platform/src/PlatformACT.c | 302 + .../TPMCmd/Platform/src/PlatformData.c | 41 + .../TPMCmd/Platform/src/PowerPlat.c | 103 + .../TPMCmd/Platform/src/RunCommand.c | 81 + .../TPMCmd/Platform/src/Unique.c | 82 + .../TPMCmd/Simulator/include/TpmTcpProtocol.h | 126 + .../include/prototypes/Simulator_fp.h | 201 + .../TPMCmd/Simulator/simulator.vcxproj | 491 + .../TPMCmd/Simulator/src/TPMCmdp.c | 282 + .../TPMCmd/Simulator/src/TPMCmds.c | 293 + .../TPMCmd/Simulator/src/TcpServer.c | 711 + .../TPMCmd/Simulator/src/tpmsim.service | 18 + optee/samples/ms-tpm-20-ref/TPMCmd/bootstrap | 66 + .../samples/ms-tpm-20-ref/TPMCmd/configure.ac | 89 + optee/samples/ms-tpm-20-ref/TPMCmd/flags.m4 | 84 + .../ms-tpm-20-ref/TPMCmd/simulator.sln | 109 + .../ms-tpm-20-ref/TPMCmd/tpm/Tpm.vcxproj | 1061 + .../TPMCmd/tpm/Tpm.vcxproj.filters | 1428 ++ .../ms-tpm-20-ref/TPMCmd/tpm/include/ACT.h | 235 + .../TPMCmd/tpm/include/BaseTypes.h | 59 + .../TPMCmd/tpm/include/BnValues.h | 354 + .../TPMCmd/tpm/include/Capabilities.h | 50 + .../TPMCmd/tpm/include/CommandAttributeData.h | 944 + .../TPMCmd/tpm/include/CommandAttributes.h | 67 + .../TPMCmd/tpm/include/CommandDispatchData.h | 5090 ++++ .../TPMCmd/tpm/include/CommandDispatcher.h | 2640 ++ .../TPMCmd/tpm/include/Commands.h | 461 + .../TPMCmd/tpm/include/CompilerDependencies.h | 130 + .../TPMCmd/tpm/include/CryptEcc.h | 80 + .../TPMCmd/tpm/include/CryptHash.h | 324 + .../TPMCmd/tpm/include/CryptRand.h | 195 + .../TPMCmd/tpm/include/CryptRsa.h | 69 + .../TPMCmd/tpm/include/CryptSym.h | 116 + .../TPMCmd/tpm/include/CryptTest.h | 69 + .../TPMCmd/tpm/include/EccTestData.h | 184 + .../ms-tpm-20-ref/TPMCmd/tpm/include/Global.h | 1415 ++ .../TPMCmd/tpm/include/GpMacros.h | 398 + .../TPMCmd/tpm/include/HandleProcess.h | 1168 + .../TPMCmd/tpm/include/HashTestData.h | 128 + .../TPMCmd/tpm/include/InternalRoutines.h | 129 + .../TPMCmd/tpm/include/KdfTestData.h | 98 + .../TPMCmd/tpm/include/LibSupport.h | 75 + .../TPMCmd/tpm/include/Ltc/LtcSettings.h | 84 + .../TPMCmd/tpm/include/Ltc/TpmToLtcHash.h | 162 + .../TPMCmd/tpm/include/Ltc/TpmToLtcMath.h | 87 + .../TPMCmd/tpm/include/Ltc/TpmToLtcSym.h | 107 + .../TPMCmd/tpm/include/Marshal.h | 53 + .../tpm/include/Mbedtls/TpmToMbedtlsHash.h | 162 + .../tpm/include/Mbedtls/TpmToMbedtlsMath.h | 57 + .../tpm/include/Mbedtls/TpmToMbedtlsSym.h | 78 + .../ms-tpm-20-ref/TPMCmd/tpm/include/MinMax.h | 46 + .../ms-tpm-20-ref/TPMCmd/tpm/include/NV.h | 150 + .../ms-tpm-20-ref/TPMCmd/tpm/include/OIDs.h | 287 + .../TPMCmd/tpm/include/Ossl/TpmToOsslHash.h | 201 + .../TPMCmd/tpm/include/Ossl/TpmToOsslMath.h | 132 + .../TPMCmd/tpm/include/Ossl/TpmToOsslSym.h | 181 + .../TPMCmd/tpm/include/PRNG_TestVectors.h | 131 + .../TPMCmd/tpm/include/RsaTestData.h | 519 + .../TPMCmd/tpm/include/SelfTest.h | 105 + .../SupportLibraryFunctionPrototypes_fp.h | 124 + .../TPMCmd/tpm/include/SymmetricTest.h | 107 + .../TPMCmd/tpm/include/SymmetricTestData.h | 165 + .../ms-tpm-20-ref/TPMCmd/tpm/include/TPMB.h | 74 + .../TPMCmd/tpm/include/TableMarshal.h | 236 + .../TPMCmd/tpm/include/TableMarshalDefines.h | 1453 ++ .../TPMCmd/tpm/include/TableMarshalTypes.h | 1671 ++ .../ms-tpm-20-ref/TPMCmd/tpm/include/Tpm.h | 55 + .../TPMCmd/tpm/include/TpmASN1.h | 126 + .../TPMCmd/tpm/include/TpmAlgorithmDefines.h | 409 + .../TPMCmd/tpm/include/TpmBuildSwitches.h | 343 + .../TPMCmd/tpm/include/TpmError.h | 57 + .../TPMCmd/tpm/include/TpmProfile.h | 784 + .../TPMCmd/tpm/include/TpmTypes.h | 2724 +++ .../TPMCmd/tpm/include/VendorString.h | 88 + .../TPMCmd/tpm/include/Wolf/TpmToWolfHash.h | 190 + .../TPMCmd/tpm/include/Wolf/TpmToWolfMath.h | 91 + .../TPMCmd/tpm/include/Wolf/TpmToWolfSym.h | 124 + .../TPMCmd/tpm/include/Wolf/user_settings.h | 104 + .../ms-tpm-20-ref/TPMCmd/tpm/include/X509.h | 132 + .../include/prototypes/ACT_SetTimeout_fp.h | 61 + .../tpm/include/prototypes/ACT_spt_fp.h | 80 + .../include/prototypes/AC_GetCapability_fp.h | 70 + .../tpm/include/prototypes/AC_Send_fp.h | 71 + .../TPMCmd/tpm/include/prototypes/AC_spt_fp.h | 74 + .../prototypes/ActivateCredential_fp.h | 71 + .../tpm/include/prototypes/AlgorithmCap_fp.h | 63 + .../include/prototypes/AlgorithmTests_fp.h | 69 + .../tpm/include/prototypes/Attest_spt_fp.h | 84 + .../TPMCmd/tpm/include/prototypes/Bits_fp.h | 67 + .../tpm/include/prototypes/BnConvert_fp.h | 114 + .../TPMCmd/tpm/include/prototypes/BnMath_fp.h | 173 + .../tpm/include/prototypes/BnMemory_fp.h | 90 + .../include/prototypes/CertifyCreation_fp.h | 76 + .../tpm/include/prototypes/CertifyX509_fp.h | 75 + .../tpm/include/prototypes/Certify_fp.h | 72 + .../tpm/include/prototypes/ChangeEPS_fp.h | 59 + .../tpm/include/prototypes/ChangePPS_fp.h | 59 + .../tpm/include/prototypes/ClearControl_fp.h | 61 + .../TPMCmd/tpm/include/prototypes/Clear_fp.h | 59 + .../include/prototypes/ClockRateAdjust_fp.h | 61 + .../tpm/include/prototypes/ClockSet_fp.h | 61 + .../tpm/include/prototypes/CommandAudit_fp.h | 117 + .../prototypes/CommandCodeAttributes_fp.h | 161 + .../include/prototypes/CommandDispatcher_fp.h | 54 + .../TPMCmd/tpm/include/prototypes/Commit_fp.h | 74 + .../tpm/include/prototypes/ContextLoad_fp.h | 65 + .../tpm/include/prototypes/ContextSave_fp.h | 65 + .../tpm/include/prototypes/Context_spt_fp.h | 90 + .../tpm/include/prototypes/CreateLoaded_fp.h | 72 + .../tpm/include/prototypes/CreatePrimary_fp.h | 78 + .../TPMCmd/tpm/include/prototypes/Create_fp.h | 77 + .../tpm/include/prototypes/CryptCmac_fp.h | 71 + .../tpm/include/prototypes/CryptDes_fp.h | 71 + .../tpm/include/prototypes/CryptEccCrypt_fp.h | 94 + .../prototypes/CryptEccKeyExchange_fp.h | 86 + .../tpm/include/prototypes/CryptEccMain_fp.h | 318 + .../include/prototypes/CryptEccSignature_fp.h | 132 + .../tpm/include/prototypes/CryptHash_fp.h | 369 + .../include/prototypes/CryptPrimeSieve_fp.h | 137 + .../tpm/include/prototypes/CryptPrime_fp.h | 130 + .../tpm/include/prototypes/CryptRand_fp.h | 182 + .../tpm/include/prototypes/CryptRsa_fp.h | 187 + .../tpm/include/prototypes/CryptSelfTest_fp.h | 100 + .../tpm/include/prototypes/CryptSmac_fp.h | 73 + .../tpm/include/prototypes/CryptSym_fp.h | 114 + .../tpm/include/prototypes/CryptUtil_fp.h | 410 + .../TPMCmd/tpm/include/prototypes/DA_fp.h | 78 + .../prototypes/DictionaryAttackLockReset_fp.h | 59 + .../DictionaryAttackParameters_fp.h | 65 + .../tpm/include/prototypes/Duplicate_fp.h | 73 + .../tpm/include/prototypes/ECC_Decrypt_fp.h | 73 + .../tpm/include/prototypes/ECC_Encrypt_fp.h | 71 + .../include/prototypes/ECC_Parameters_fp.h | 65 + .../tpm/include/prototypes/ECDH_KeyGen_fp.h | 66 + .../tpm/include/prototypes/ECDH_ZGen_fp.h | 67 + .../tpm/include/prototypes/EC_Ephemeral_fp.h | 66 + .../include/prototypes/EncryptDecrypt2_fp.h | 74 + .../include/prototypes/EncryptDecrypt_fp.h | 74 + .../prototypes/EncryptDecrypt_spt_fp.h | 62 + .../TPMCmd/tpm/include/prototypes/Entity_fp.h | 102 + .../prototypes/EventSequenceComplete_fp.h | 70 + .../tpm/include/prototypes/EvictControl_fp.h | 63 + .../tpm/include/prototypes/ExecCommand_fp.h | 87 + .../include/prototypes/FieldUpgradeData_fp.h | 66 + .../include/prototypes/FieldUpgradeStart_fp.h | 65 + .../tpm/include/prototypes/FirmwareRead_fp.h | 65 + .../tpm/include/prototypes/FlushContext_fp.h | 59 + .../tpm/include/prototypes/GetCapability_fp.h | 70 + .../prototypes/GetCommandAuditDigest_fp.h | 73 + .../tpm/include/prototypes/GetRandom_fp.h | 65 + .../prototypes/GetSessionAuditDigest_fp.h | 75 + .../tpm/include/prototypes/GetTestResult_fp.h | 57 + .../tpm/include/prototypes/GetTime_fp.h | 72 + .../tpm/include/prototypes/HMAC_Start_fp.h | 69 + .../TPMCmd/tpm/include/prototypes/HMAC_fp.h | 69 + .../TPMCmd/tpm/include/prototypes/Handle_fp.h | 83 + .../include/prototypes/HashSequenceStart_fp.h | 67 + .../TPMCmd/tpm/include/prototypes/Hash_fp.h | 70 + .../prototypes/HierarchyChangeAuth_fp.h | 61 + .../include/prototypes/HierarchyControl_fp.h | 63 + .../tpm/include/prototypes/Hierarchy_fp.h | 76 + .../TPMCmd/tpm/include/prototypes/Import_fp.h | 75 + .../prototypes/IncrementalSelfTest_fp.h | 65 + .../tpm/include/prototypes/IoBuffers_fp.h | 74 + .../tpm/include/prototypes/LoadExternal_fp.h | 70 + .../TPMCmd/tpm/include/prototypes/Load_fp.h | 70 + .../tpm/include/prototypes/Locality_fp.h | 52 + .../tpm/include/prototypes/MAC_Start_fp.h | 69 + .../TPMCmd/tpm/include/prototypes/MAC_fp.h | 69 + .../include/prototypes/MakeCredential_fp.h | 70 + .../tpm/include/prototypes/Manufacture_fp.h | 73 + .../tpm/include/prototypes/Marshal_fp.h | 2345 ++ .../include/prototypes/MathOnByteBuffers_fp.h | 128 + .../TPMCmd/tpm/include/prototypes/Memory_fp.h | 138 + .../tpm/include/prototypes/NV_Certify_fp.h | 78 + .../tpm/include/prototypes/NV_ChangeAuth_fp.h | 61 + .../include/prototypes/NV_DefineSpace_fp.h | 63 + .../tpm/include/prototypes/NV_Extend_fp.h | 63 + .../prototypes/NV_GlobalWriteLock_fp.h | 59 + .../tpm/include/prototypes/NV_Increment_fp.h | 61 + .../tpm/include/prototypes/NV_ReadLock_fp.h | 61 + .../tpm/include/prototypes/NV_ReadPublic_fp.h | 66 + .../tpm/include/prototypes/NV_Read_fp.h | 71 + .../tpm/include/prototypes/NV_SetBits_fp.h | 63 + .../prototypes/NV_UndefineSpaceSpecial_fp.h | 61 + .../include/prototypes/NV_UndefineSpace_fp.h | 61 + .../tpm/include/prototypes/NV_WriteLock_fp.h | 61 + .../tpm/include/prototypes/NV_Write_fp.h | 65 + .../TPMCmd/tpm/include/prototypes/NV_spt_fp.h | 88 + .../tpm/include/prototypes/NvDynamic_fp.h | 408 + .../tpm/include/prototypes/NvReserved_fp.h | 108 + .../include/prototypes/ObjectChangeAuth_fp.h | 69 + .../TPMCmd/tpm/include/prototypes/Object_fp.h | 302 + .../tpm/include/prototypes/Object_spt_fp.h | 368 + .../tpm/include/prototypes/PCR_Allocate_fp.h | 70 + .../tpm/include/prototypes/PCR_Event_fp.h | 67 + .../tpm/include/prototypes/PCR_Extend_fp.h | 61 + .../tpm/include/prototypes/PCR_Read_fp.h | 67 + .../tpm/include/prototypes/PCR_Reset_fp.h | 59 + .../include/prototypes/PCR_SetAuthPolicy_fp.h | 65 + .../include/prototypes/PCR_SetAuthValue_fp.h | 61 + .../TPMCmd/tpm/include/prototypes/PCR_fp.h | 278 + .../tpm/include/prototypes/PP_Commands_fp.h | 63 + .../TPMCmd/tpm/include/prototypes/PP_fp.h | 88 + .../include/prototypes/PolicyAuthValue_fp.h | 59 + .../include/prototypes/PolicyAuthorizeNV_fp.h | 63 + .../include/prototypes/PolicyAuthorize_fp.h | 67 + .../include/prototypes/PolicyCommandCode_fp.h | 61 + .../prototypes/PolicyCounterTimer_fp.h | 65 + .../tpm/include/prototypes/PolicyCpHash_fp.h | 61 + .../prototypes/PolicyDuplicationSelect_fp.h | 65 + .../include/prototypes/PolicyGetDigest_fp.h | 65 + .../include/prototypes/PolicyLocality_fp.h | 61 + .../tpm/include/prototypes/PolicyNV_fp.h | 69 + .../include/prototypes/PolicyNameHash_fp.h | 61 + .../include/prototypes/PolicyNvWritten_fp.h | 61 + .../tpm/include/prototypes/PolicyOR_fp.h | 61 + .../tpm/include/prototypes/PolicyPCR_fp.h | 63 + .../include/prototypes/PolicyPassword_fp.h | 59 + .../prototypes/PolicyPhysicalPresence_fp.h | 59 + .../tpm/include/prototypes/PolicyRestart_fp.h | 59 + .../tpm/include/prototypes/PolicySecret_fp.h | 76 + .../tpm/include/prototypes/PolicySigned_fp.h | 78 + .../include/prototypes/PolicyTemplate_fp.h | 61 + .../tpm/include/prototypes/PolicyTicket_fp.h | 69 + .../prototypes/Policy_AC_SendSelect_fp.h | 67 + .../tpm/include/prototypes/Policy_spt_fp.h | 92 + .../TPMCmd/tpm/include/prototypes/Power_fp.h | 60 + .../tpm/include/prototypes/PropertyCap_fp.h | 58 + .../TPMCmd/tpm/include/prototypes/Quote_fp.h | 72 + .../tpm/include/prototypes/RSA_Decrypt_fp.h | 71 + .../tpm/include/prototypes/RSA_Encrypt_fp.h | 71 + .../tpm/include/prototypes/ReadClock_fp.h | 56 + .../tpm/include/prototypes/ReadPublic_fp.h | 67 + .../prototypes/ResponseCodeProcessing_fp.h | 49 + .../tpm/include/prototypes/Response_fp.h | 51 + .../TPMCmd/tpm/include/prototypes/Rewrap_fp.h | 74 + .../tpm/include/prototypes/RsaKeyCache_fp.h | 60 + .../tpm/include/prototypes/SelfTest_fp.h | 59 + .../include/prototypes/SequenceComplete_fp.h | 70 + .../include/prototypes/SequenceUpdate_fp.h | 61 + .../include/prototypes/SessionProcess_fp.h | 110 + .../tpm/include/prototypes/Session_fp.h | 254 + .../include/prototypes/SetAlgorithmSet_fp.h | 61 + .../prototypes/SetCommandCodeAuditStatus_fp.h | 65 + .../include/prototypes/SetPrimaryPolicy_fp.h | 63 + .../tpm/include/prototypes/Shutdown_fp.h | 59 + .../TPMCmd/tpm/include/prototypes/Sign_fp.h | 71 + .../include/prototypes/StartAuthSession_fp.h | 78 + .../tpm/include/prototypes/Startup_fp.h | 59 + .../tpm/include/prototypes/StirRandom_fp.h | 59 + .../prototypes/TableDrivenMarshal_fp.h | 92 + .../tpm/include/prototypes/TestParms_fp.h | 59 + .../TPMCmd/tpm/include/prototypes/Ticket_fp.h | 93 + .../TPMCmd/tpm/include/prototypes/Time_fp.h | 120 + .../tpm/include/prototypes/TpmASN1_fp.h | 183 + .../tpm/include/prototypes/TpmFail_fp.h | 84 + .../tpm/include/prototypes/TpmSizeChecks_fp.h | 53 + .../prototypes/TpmToLtcDesSupport_fp.h | 53 + .../tpm/include/prototypes/TpmToLtcMath_fp.h | 118 + .../include/prototypes/TpmToLtcSupport_fp.h | 61 + .../include/prototypes/TpmToMbedtlsMath_fp.h | 166 + .../prototypes/TpmToMbedtlsSupport_fp.h | 21 + .../prototypes/TpmToOsslDesSupport_fp.h | 66 + .../tpm/include/prototypes/TpmToOsslMath_fp.h | 177 + .../include/prototypes/TpmToOsslSupport_fp.h | 69 + .../prototypes/TpmToWolfDesSupport_fp.h | 67 + .../tpm/include/prototypes/TpmToWolfMath_fp.h | 150 + .../include/prototypes/TpmToWolfSupport_fp.h | 50 + .../TPMCmd/tpm/include/prototypes/Unseal_fp.h | 65 + .../include/prototypes/Vendor_TCG_Test_fp.h | 65 + .../include/prototypes/VerifySignature_fp.h | 69 + .../tpm/include/prototypes/X509_ECC_fp.h | 70 + .../tpm/include/prototypes/X509_RSA_fp.h | 65 + .../tpm/include/prototypes/X509_spt_fp.h | 105 + .../tpm/include/prototypes/ZGen_2Phase_fp.h | 74 + .../include/prototypes/_TPM_Hash_Data_fp.h | 48 + .../tpm/include/prototypes/_TPM_Hash_End_fp.h | 46 + .../include/prototypes/_TPM_Hash_Start_fp.h | 46 + .../tpm/include/prototypes/_TPM_Init_fp.h | 46 + .../ms-tpm-20-ref/TPMCmd/tpm/include/swap.h | 129 + .../TPMCmd/tpm/src/X509/TpmASN1.c | 460 + .../TPMCmd/tpm/src/X509/X509_ECC.c | 139 + .../TPMCmd/tpm/src/X509/X509_RSA.c | 230 + .../TPMCmd/tpm/src/X509/X509_spt.c | 285 + .../tpm/src/command/Asymmetric/ECC_Decrypt.c | 68 + .../tpm/src/command/Asymmetric/ECC_Encrypt.c | 61 + .../src/command/Asymmetric/ECC_Parameters.c | 60 + .../tpm/src/command/Asymmetric/ECDH_KeyGen.c | 93 + .../tpm/src/command/Asymmetric/ECDH_ZGen.c | 86 + .../tpm/src/command/Asymmetric/EC_Ephemeral.c | 72 + .../tpm/src/command/Asymmetric/RSA_Decrypt.c | 105 + .../tpm/src/command/Asymmetric/RSA_Encrypt.c | 89 + .../tpm/src/command/Asymmetric/ZGen_2Phase.c | 119 + .../AttachedComponent/AC_GetCapability.c | 56 + .../src/command/AttachedComponent/AC_Send.c | 99 + .../src/command/AttachedComponent/AC_spt.c | 153 + .../AttachedComponent/Policy_AC_SendSelect.c | 114 + .../tpm/src/command/Attestation/Attest_spt.c | 203 + .../tpm/src/command/Attestation/Certify.c | 96 + .../src/command/Attestation/CertifyCreation.c | 100 + .../tpm/src/command/Attestation/CertifyX509.c | 282 + .../Attestation/GetCommandAuditDigest.c | 101 + .../Attestation/GetSessionAuditDigest.c | 97 + .../tpm/src/command/Attestation/GetTime.c | 91 + .../tpm/src/command/Attestation/Quote.c | 101 + .../src/command/Capability/GetCapability.c | 171 + .../tpm/src/command/Capability/TestParms.c | 55 + .../src/command/ClockTimer/ACT_SetTimeout.c | 60 + .../tpm/src/command/ClockTimer/ACT_spt.c | 264 + .../src/command/ClockTimer/ClockRateAdjust.c | 54 + .../tpm/src/command/ClockTimer/ClockSet.c | 64 + .../tpm/src/command/ClockTimer/ReadClock.c | 55 + .../CommandAudit/SetCommandCodeAuditStatus.c | 103 + .../tpm/src/command/Context/ContextLoad.c | 199 + .../tpm/src/command/Context/ContextSave.c | 238 + .../tpm/src/command/Context/Context_spt.c | 243 + .../tpm/src/command/Context/EvictControl.c | 130 + .../tpm/src/command/Context/FlushContext.c | 83 + .../command/DA/DictionaryAttackLockReset.c | 67 + .../command/DA/DictionaryAttackParameters.c | 76 + .../tpm/src/command/Duplication/Duplicate.c | 162 + .../tpm/src/command/Duplication/Import.c | 218 + .../tpm/src/command/Duplication/Rewrap.c | 164 + .../tpm/src/command/EA/PolicyAuthValue.c | 80 + .../tpm/src/command/EA/PolicyAuthorize.c | 128 + .../tpm/src/command/EA/PolicyAuthorizeNV.c | 122 + .../tpm/src/command/EA/PolicyCommandCode.c | 89 + .../tpm/src/command/EA/PolicyCounterTimer.c | 130 + .../TPMCmd/tpm/src/command/EA/PolicyCpHash.c | 101 + .../src/command/EA/PolicyDuplicationSelect.c | 113 + .../tpm/src/command/EA/PolicyGetDigest.c | 60 + .../tpm/src/command/EA/PolicyLocality.c | 136 + .../TPMCmd/tpm/src/command/EA/PolicyNV.c | 140 + .../tpm/src/command/EA/PolicyNameHash.c | 96 + .../tpm/src/command/EA/PolicyNvWritten.c | 93 + .../TPMCmd/tpm/src/command/EA/PolicyOR.c | 99 + .../TPMCmd/tpm/src/command/EA/PolicyPCR.c | 126 + .../tpm/src/command/EA/PolicyPassword.c | 80 + .../src/command/EA/PolicyPhysicalPresence.c | 77 + .../TPMCmd/tpm/src/command/EA/PolicySecret.c | 136 + .../TPMCmd/tpm/src/command/EA/PolicySigned.c | 186 + .../tpm/src/command/EA/PolicyTemplate.c | 102 + .../TPMCmd/tpm/src/command/EA/PolicyTicket.c | 137 + .../TPMCmd/tpm/src/command/EA/Policy_spt.c | 276 + .../TPMCmd/tpm/src/command/Ecdaa/Commit.c | 168 + .../command/FieldUpgrade/FieldUpgradeData.c | 52 + .../command/FieldUpgrade/FieldUpgradeStart.c | 50 + .../src/command/FieldUpgrade/FirmwareRead.c | 54 + .../command/HashHMAC/EventSequenceComplete.c | 110 + .../tpm/src/command/HashHMAC/HMAC_Start.c | 101 + .../src/command/HashHMAC/HashSequenceStart.c | 62 + .../tpm/src/command/HashHMAC/MAC_Start.c | 89 + .../src/command/HashHMAC/SequenceComplete.c | 130 + .../tpm/src/command/HashHMAC/SequenceUpdate.c | 105 + .../tpm/src/command/Hierarchy/ChangeEPS.c | 98 + .../tpm/src/command/Hierarchy/ChangePPS.c | 95 + .../TPMCmd/tpm/src/command/Hierarchy/Clear.c | 123 + .../tpm/src/command/Hierarchy/ClearControl.c | 71 + .../tpm/src/command/Hierarchy/CreatePrimary.c | 146 + .../command/Hierarchy/HierarchyChangeAuth.c | 90 + .../src/command/Hierarchy/HierarchyControl.c | 142 + .../src/command/Hierarchy/SetPrimaryPolicy.c | 110 + .../TPMCmd/tpm/src/command/Misc/PP_Commands.c | 79 + .../tpm/src/command/Misc/SetAlgorithmSet.c | 61 + .../tpm/src/command/NVStorage/NV_Certify.c | 147 + .../tpm/src/command/NVStorage/NV_ChangeAuth.c | 67 + .../src/command/NVStorage/NV_DefineSpace.c | 225 + .../tpm/src/command/NVStorage/NV_Extend.c | 107 + .../command/NVStorage/NV_GlobalWriteLock.c | 56 + .../tpm/src/command/NVStorage/NV_Increment.c | 100 + .../tpm/src/command/NVStorage/NV_Read.c | 96 + .../tpm/src/command/NVStorage/NV_ReadLock.c | 88 + .../tpm/src/command/NVStorage/NV_ReadPublic.c | 61 + .../tpm/src/command/NVStorage/NV_SetBits.c | 89 + .../src/command/NVStorage/NV_UndefineSpace.c | 75 + .../NVStorage/NV_UndefineSpaceSpecial.c | 71 + .../tpm/src/command/NVStorage/NV_Write.c | 104 + .../tpm/src/command/NVStorage/NV_WriteLock.c | 89 + .../TPMCmd/tpm/src/command/NVStorage/NV_spt.c | 158 + .../src/command/Object/ActivateCredential.c | 105 + .../TPMCmd/tpm/src/command/Object/Create.c | 161 + .../tpm/src/command/Object/CreateLoaded.c | 221 + .../TPMCmd/tpm/src/command/Object/Load.c | 124 + .../tpm/src/command/Object/LoadExternal.c | 133 + .../tpm/src/command/Object/MakeCredential.c | 94 + .../tpm/src/command/Object/ObjectChangeAuth.c | 93 + .../tpm/src/command/Object/Object_spt.c | 1596 ++ .../tpm/src/command/Object/ReadPublic.c | 66 + .../TPMCmd/tpm/src/command/Object/Unseal.c | 67 + .../TPMCmd/tpm/src/command/PCR/PCR_Allocate.c | 82 + .../TPMCmd/tpm/src/command/PCR/PCR_Event.c | 90 + .../TPMCmd/tpm/src/command/PCR/PCR_Extend.c | 89 + .../TPMCmd/tpm/src/command/PCR/PCR_Read.c | 59 + .../TPMCmd/tpm/src/command/PCR/PCR_Reset.c | 73 + .../tpm/src/command/PCR/PCR_SetAuthPolicy.c | 81 + .../tpm/src/command/PCR/PCR_SetAuthValue.c | 72 + .../TPMCmd/tpm/src/command/Random/GetRandom.c | 62 + .../tpm/src/command/Random/StirRandom.c | 53 + .../tpm/src/command/Session/PolicyRestart.c | 53 + .../src/command/Session/StartAuthSession.c | 169 + .../TPMCmd/tpm/src/command/Signature/Sign.c | 112 + .../src/command/Signature/VerifySignature.c | 91 + .../TPMCmd/tpm/src/command/Startup/Shutdown.c | 109 + .../TPMCmd/tpm/src/command/Startup/Startup.c | 246 + .../src/command/Symmetric/EncryptDecrypt.c | 169 + .../src/command/Symmetric/EncryptDecrypt2.c | 85 + .../command/Symmetric/EncryptDecrypt_spt.c | 163 + .../TPMCmd/tpm/src/command/Symmetric/HMAC.c | 106 + .../TPMCmd/tpm/src/command/Symmetric/Hash.c | 87 + .../TPMCmd/tpm/src/command/Symmetric/MAC.c | 94 + .../tpm/src/command/Testing/GetTestResult.c | 60 + .../src/command/Testing/IncrementalSelfTest.c | 64 + .../TPMCmd/tpm/src/command/Testing/SelfTest.c | 57 + .../tpm/src/command/Vendor/Vendor_TCG_Test.c | 49 + .../TPMCmd/tpm/src/crypt/AlgorithmTests.c | 912 + .../TPMCmd/tpm/src/crypt/BnConvert.c | 278 + .../TPMCmd/tpm/src/crypt/BnMath.c | 536 + .../TPMCmd/tpm/src/crypt/BnMemory.c | 166 + .../TPMCmd/tpm/src/crypt/CryptCmac.c | 172 + .../TPMCmd/tpm/src/crypt/CryptDes.c | 174 + .../TPMCmd/tpm/src/crypt/CryptEccCrypt.c | 214 + .../TPMCmd/tpm/src/crypt/CryptEccData.c | 731 + .../tpm/src/crypt/CryptEccKeyExchange.c | 367 + .../TPMCmd/tpm/src/crypt/CryptEccMain.c | 771 + .../TPMCmd/tpm/src/crypt/CryptEccSignature.c | 920 + .../TPMCmd/tpm/src/crypt/CryptHash.c | 857 + .../TPMCmd/tpm/src/crypt/CryptPrime.c | 367 + .../TPMCmd/tpm/src/crypt/CryptPrimeSieve.c | 537 + .../TPMCmd/tpm/src/crypt/CryptRand.c | 943 + .../TPMCmd/tpm/src/crypt/CryptRsa.c | 1445 ++ .../TPMCmd/tpm/src/crypt/CryptSelfTest.c | 211 + .../TPMCmd/tpm/src/crypt/CryptSmac.c | 121 + .../TPMCmd/tpm/src/crypt/CryptSym.c | 466 + .../TPMCmd/tpm/src/crypt/CryptUtil.c | 1917 ++ .../src/crypt/Mbedtls/Mbedtls_mpi_Ltc_desc.c | 600 + .../tpm/src/crypt/Mbedtls/TpmToMbedtlsMath.c | 476 + .../src/crypt/Mbedtls/TpmToMbedtlsSupport.c | 28 + .../TPMCmd/tpm/src/crypt/PrimeData.c | 391 + .../TPMCmd/tpm/src/crypt/RsaKeyCache.c | 244 + .../TPMCmd/tpm/src/crypt/Ticket.c | 269 + .../tpm/src/crypt/ltc/TpmToLtcDesSupport.c | 71 + .../TPMCmd/tpm/src/crypt/ltc/TpmToLtcMath.c | 267 + .../tpm/src/crypt/ltc/TpmToLtcSupport.c | 85 + .../tpm/src/crypt/ossl/TpmToOsslDesSupport.c | 84 + .../TPMCmd/tpm/src/crypt/ossl/TpmToOsslMath.c | 574 + .../tpm/src/crypt/ossl/TpmToOsslSupport.c | 94 + .../tpm/src/crypt/wolf/TpmToWolfDesSupport.c | 96 + .../TPMCmd/tpm/src/crypt/wolf/TpmToWolfMath.c | 482 + .../tpm/src/crypt/wolf/TpmToWolfSupport.c | 57 + .../TPMCmd/tpm/src/crypt/wolf/wolfssl.vcxproj | 194 + .../TPMCmd/tpm/src/events/_TPM_Hash_Data.c | 67 + .../TPMCmd/tpm/src/events/_TPM_Hash_End.c | 97 + .../TPMCmd/tpm/src/events/_TPM_Hash_Start.c | 89 + .../TPMCmd/tpm/src/events/_TPM_Init.c | 90 + .../TPMCmd/tpm/src/main/CommandDispatcher.c | 457 + .../TPMCmd/tpm/src/main/ExecCommand.c | 330 + .../TPMCmd/tpm/src/main/SessionProcess.c | 2149 ++ .../TPMCmd/tpm/src/subsystem/CommandAudit.c | 255 + .../TPMCmd/tpm/src/subsystem/DA.c | 224 + .../TPMCmd/tpm/src/subsystem/Hierarchy.c | 226 + .../TPMCmd/tpm/src/subsystem/NvDynamic.c | 1813 ++ .../TPMCmd/tpm/src/subsystem/NvReserved.c | 237 + .../TPMCmd/tpm/src/subsystem/Object.c | 936 + .../TPMCmd/tpm/src/subsystem/PCR.c | 1281 + .../TPMCmd/tpm/src/subsystem/PP.c | 170 + .../TPMCmd/tpm/src/subsystem/Session.c | 1026 + .../TPMCmd/tpm/src/subsystem/Time.c | 253 + .../TPMCmd/tpm/src/support/AlgorithmCap.c | 232 + .../TPMCmd/tpm/src/support/Bits.c | 85 + .../tpm/src/support/CommandCodeAttributes.c | 531 + .../TPMCmd/tpm/src/support/Entity.c | 490 + .../TPMCmd/tpm/src/support/Global.c | 62 + .../TPMCmd/tpm/src/support/Handle.c | 196 + .../TPMCmd/tpm/src/support/IoBuffers.c | 112 + .../TPMCmd/tpm/src/support/Locality.c | 74 + .../TPMCmd/tpm/src/support/Manufacture.c | 176 + .../TPMCmd/tpm/src/support/Marshal.c | 6922 ++++++ .../tpm/src/support/MathOnByteBuffers.c | 240 + .../TPMCmd/tpm/src/support/Memory.c | 231 + .../TPMCmd/tpm/src/support/Power.c | 73 + .../TPMCmd/tpm/src/support/PropertyCap.c | 596 + .../TPMCmd/tpm/src/support/Response.c | 80 + .../tpm/src/support/ResponseCodeProcessing.c | 52 + .../tpm/src/support/TableDrivenMarshal.c | 890 + .../TPMCmd/tpm/src/support/TableMarshalData.c | 1725 ++ .../TPMCmd/tpm/src/support/TpmFail.c | 423 + .../TPMCmd/tpm/src/support/TpmSizeChecks.c | 216 + optee/samples/pkcs11-sample/LICENSE | 23 + optee/samples/pkcs11-sample/Makefile | 27 + optee/samples/pkcs11-sample/host/Makefile | 37 + .../pkcs11-sample/host/pkcs11_sample_ca.c | 367 + optee/tegra234-optee.dts | 178 + optee_src_build.sh | 235 + push_info.txt | 1 + 4211 files changed, 1146160 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.bp 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/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/libteeacl/teeacl.pc.in 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/tee_client_api.h create mode 100644 optee/optee_client/libteec/include/tee_client_api_extensions.h create mode 100644 optee/optee_client/libteec/include/tee_plugin_method.h create mode 100644 optee/optee_client/libteec/include/teec_trace.h create mode 100644 optee/optee_client/libteec/src/linux/tee.h create mode 100644 optee/optee_client/libteec/src/tee_client_api.c create mode 100644 optee/optee_client/libteec/src/teec_trace.c create mode 100644 optee/optee_client/libteec/teec.pc.in create mode 100644 optee/optee_client/optee_client.device.mk create mode 100644 optee/optee_client/prebuilt/include/uuid.h create mode 100644 optee/optee_client/prebuilt/libuuid.a create mode 100644 optee/optee_client/prebuilt/uuid.pc 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/typedefs.checkpatch create mode 100644 optee/optee_os/.checkpatch.conf create mode 100644 optee/optee_os/.clang-format 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/at91-sama7g54_ek.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/sama7g5-pinfunc.h create mode 100644 optee/optee_os/core/arch/arm/dts/sama7g5.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-scmi.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-scmi.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-scmi.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-scmi.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/dts/stm32mp25-pinctrl.dtsi create mode 100644 optee/optee_os/core/arch/arm/dts/stm32mp251.dtsi create mode 100644 optee/optee_os/core/arch/arm/dts/stm32mp253.dtsi create mode 100644 optee/optee_os/core/arch/arm/dts/stm32mp255.dtsi create mode 100644 optee/optee_os/core/arch/arm/dts/stm32mp257.dtsi create mode 100644 optee/optee_os/core/arch/arm/dts/stm32mp257f-ev1-ca35tdcid-rif.dtsi create mode 100644 optee/optee_os/core/arch/arm/dts/stm32mp257f-ev1.dts create mode 100644 optee/optee_os/core/arch/arm/dts/stm32mp25xc.dtsi create mode 100644 optee/optee_os/core/arch/arm/dts/stm32mp25xf.dtsi create mode 100644 optee/optee_os/core/arch/arm/dts/stm32mp25xxai-pinctrl.dtsi create mode 100644 optee/optee_os/core/arch/arm/dts/stm32mp25xxak-pinctrl.dtsi create mode 100644 optee/optee_os/core/arch/arm/dts/stm32mp25xxal-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/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/user_access_arch.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/sm/watchdog_smc.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/generic_timer.c 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/semihosting_a64.S 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_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/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_ast2700.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/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/platform_config.h 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/cn10k/core_pos.S 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-nuvoton/conf.mk create mode 100644 optee/optee_os/core/arch/arm/plat-nuvoton/main.c create mode 100644 optee/optee_os/core/arch/arm/plat-nuvoton/platform_config.h create mode 100644 optee/optee_os/core/arch/arm/plat-nuvoton/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/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/platform_sama5d2.c create mode 100644 optee/optee_os/core/arch/arm/plat-sam/platform_sama7g5.c 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/sama7g5.h create mode 100644 optee/optee_os/core/arch/arm/plat-sam/scmi_server.c 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/stm32mp1_syscfg.h 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-stm32mp2/conf.mk create mode 100644 optee/optee_os/core/arch/arm/plat-stm32mp2/main.c create mode 100644 optee/optee_os/core/arch/arm/plat-stm32mp2/platform_config.h create mode 100644 optee/optee_os/core/arch/arm/plat-stm32mp2/stm32_util.h create mode 100644 optee/optee_os/core/arch/arm/plat-stm32mp2/stm32mp_pm.c create mode 100644 optee/optee_os/core/arch/arm/plat-stm32mp2/stm32mp_pm.h create mode 100644 optee/optee_os/core/arch/arm/plat-stm32mp2/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/tlb_helpers.h create mode 100644 optee/optee_os/core/arch/riscv/include/kernel/user_access_arch.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/include/tee/entry_fast.h create mode 100644 optee/optee_os/core/arch/riscv/include/tee/optee_abi.h create mode 100644 optee/optee_os/core/arch/riscv/include/tee/teeabi_opteed.h create mode 100644 optee/optee_os/core/arch/riscv/include/tee/teeabi_opteed_macros.h 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/semihosting_rv.S 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_optee_abi.c create mode 100644 optee/optee_os/core/arch/riscv/kernel/thread_optee_abi_rv.S create mode 100644 optee/optee_os/core/arch/riscv/kernel/thread_rv.S create mode 100644 optee/optee_os/core/arch/riscv/kernel/unwind_rv.c create mode 100644 optee/optee_os/core/arch/riscv/mm/core_mmu_arch.c 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/entry_fast.c 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/clk-sam9x60-pll.c create mode 100644 optee/optee_os/core/drivers/clk/sam/phy-sama7-utmi-clk.c create mode 100644 optee/optee_os/core/drivers/clk/sam/sama5d2_clk.c create mode 100644 optee/optee_os/core/drivers/clk/sam/sama7g5_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/caam_dek.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_key.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/caam_sm.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/hal_sm.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/sm_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_hal_sm.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_key.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_sm.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/hisilicon/hisi_qm.c create mode 100644 optee/optee_os/core/drivers/crypto/hisilicon/hpre_main.c create mode 100644 optee/optee_os/core/drivers/crypto/hisilicon/include/hisi_qm.h create mode 100644 optee/optee_os/core/drivers/crypto/hisilicon/include/hpre_main.h create mode 100644 optee/optee_os/core/drivers/crypto/hisilicon/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/stm32_saes.c create mode 100644 optee/optee_os/core/drivers/crypto/stm32/stm32_saes.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/firewall/stm32_rif.c create mode 100644 optee/optee_os/core/drivers/firewall/stm32_rifsc.c create mode 100644 optee/optee_os/core/drivers/firewall/sub.mk create mode 100644 optee/optee_os/core/drivers/gic.c create mode 100644 optee/optee_os/core/drivers/gpio/gpio.c create mode 100644 optee/optee_os/core/drivers/gpio/sub.mk 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/hisi_trng.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/nvmem/atmel_sfc.c create mode 100644 optee/optee_os/core/drivers/nvmem/nvmem.c create mode 100644 optee/optee_os/core/drivers/nvmem/nvmem_die_id.c create mode 100644 optee/optee_os/core/drivers/nvmem/nvmem_huk.c create mode 100644 optee/optee_os/core/drivers/nvmem/sub.mk create mode 100644 optee/optee_os/core/drivers/pinctrl/atmel_pio.c create mode 100644 optee/optee_os/core/drivers/pinctrl/pinctrl.c create mode 100644 optee/optee_os/core/drivers/pinctrl/sub.mk 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/plic.c create mode 100644 optee/optee_os/core/drivers/pm/imx/gpcv2.c create mode 100644 optee/optee_os/core/drivers/pm/imx/local.h create mode 100644 optee/optee_os/core/drivers/pm/imx/psci.c create mode 100644 optee/optee_os/core/drivers/pm/imx/src.c create mode 100644 optee/optee_os/core/drivers/pm/imx/sub.mk 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/regulator/regulator.c create mode 100644 optee/optee_os/core/drivers/regulator/regulator_dt.c create mode 100644 optee/optee_os/core/drivers/regulator/regulator_fixed.c create mode 100644 optee/optee_os/core/drivers/regulator/regulator_gpio.c create mode 100644 optee/optee_os/core/drivers/regulator/stm32_vrefbuf.c create mode 100644 optee/optee_os/core/drivers/regulator/stm32mp13_regulator_iod.c create mode 100644 optee/optee_os/core/drivers/regulator/sub.mk create mode 100644 optee/optee_os/core/drivers/remoteproc/stm32_remoteproc.c create mode 100644 optee/optee_os/core/drivers/remoteproc/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/clock_generic.c 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/semihosting_console.c 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/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_fuse.c 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/crypto/tegra_driver_hash.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/t234/tegra_se_map_device.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/widevine_huk.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/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/gpio.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/nvmem.h create mode 100644 optee/optee_os/core/include/drivers/pinctrl.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/plic.h create mode 100644 optee/optee_os/core/include/drivers/pm/sam/atmel_pm.h create mode 100644 optee/optee_os/core/include/drivers/regulator.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/semihosting_console.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_remoteproc.h create mode 100644 optee/optee_os/core/include/drivers/stm32_rif.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/stm32_vrefbuf.h create mode 100644 optee/optee_os/core/include/drivers/stm32mp13_rcc.h create mode 100644 optee/optee_os/core/include/drivers/stm32mp13_regulator_iod.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/firewall/stm32mp25-rif.h create mode 100644 optee/optee_os/core/include/dt-bindings/firewall/stm32mp25-rifsc.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/gpio/stm32mp_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/dt-bindings/rtc/rtc-stm32.h create mode 100644 optee/optee_os/core/include/gen-asm-defines.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/callout.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/mutex_pm_aware.h create mode 100644 optee/optee_os/core/include/kernel/notif.h create mode 100644 optee/optee_os/core/include/kernel/nv_counter.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/semihosting.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/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/transfer_list.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_ree_state.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/callout.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/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/notif_default.c create mode 100644 optee/optee_os/core/kernel/nv_counter.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/semihosting.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/transfer_list.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/pgt_cache.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/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/dek_blob.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/remoteproc_pta.c create mode 100644 optee/optee_os/core/pta/stm32mp/rproc_pub_key.h 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/include/jetson_decrypt_cpubl_payload.h create mode 100644 optee/optee_os/core/pta/tegra/include/jetson_user_key_pta_compute_cmac.h create mode 100644 optee/optee_os/core/pta/tegra/include/jetson_user_key_pta_ftpm.h create mode 100644 optee/optee_os/core/pta/tegra/jetson_ftpm_helper_pta.c 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/dt_driver_test.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/pta/widevine.c 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_ree_state.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/notif_test_wd.c create mode 100644 optee/optee_os/core/tests/sub.mk create mode 100644 optee/optee_os/keys/default.pem create mode 120000 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/.uncrustify.cfg 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/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/build_info.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/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/cmac.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/compat-2.x.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/config_psa.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/entropy.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/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/legacy_or_psa.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/lms.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/mbedtls_config.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/md5.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_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/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/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/pkcs7.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/private_access.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/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_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/psa/crypto.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_builtin_composites.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_builtin_primitives.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_compat.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_config.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_driver_common.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_driver_contexts_composites.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_driver_contexts_primitives.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_extra.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_platform.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_se_driver.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_sizes.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_struct.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_types.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_values.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/aes.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/aesce.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/aesce.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/aesni.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/aesni.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/alignment.h 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/bignum_core.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_core.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_mod.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_mod.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_mod_raw.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_mod_raw.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_mod_raw_invasive.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/bn_mul.h 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/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/cipher_wrap.h 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_internal_alt.h 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/entropy_poll.h 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/hash_info.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/hash_info.h 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/lmots.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/lmots.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/lms.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/md.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/md5.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/md_wrap.h 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/padlock.h 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/pk_wrap.h 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/pkcs7.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/pkwrite.h 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_alt_helpers.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/rsa_alt_helpers.h 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_client.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_client.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_cookie.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_debug_helpers.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_debug_helpers_generated.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_misc.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_msg.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_tls12_client.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls12_server.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_client.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_generic.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_invasive.h 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/ssl_tls13_server.c 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/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/libunw/unwind_riscv.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_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_dek_blob.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_ftpm_helper.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_stats.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/pta_widevine.h create mode 100644 optee/optee_os/lib/libutee/include/remoteproc_pta.h create mode 100644 optee/optee_os/lib/libutee/include/riscv_user_sysreg.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/mcount_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/riscv.S 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/fcntl.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/macros.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/derive_rpmb_key.py create mode 100755 optee/optee_os/scripts/ftrace_format.py create mode 100755 optee/optee_os/scripts/gen_compile_commands.py 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/sign_rproc_fw.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/remoteproc/Makefile create mode 100644 optee/optee_os/ta/remoteproc/include/ta_remoteproc.h create mode 100644 optee/optee_os/ta/remoteproc/src/elf_parser.c create mode 100644 optee/optee_os/ta/remoteproc/src/elf_parser.h create mode 100644 optee/optee_os/ta/remoteproc/src/remoteproc_core.c create mode 100644 optee/optee_os/ta/remoteproc/src/sub.mk create mode 100644 optee/optee_os/ta/remoteproc/src/user_ta_header_defines.h create mode 100644 optee/optee_os/ta/remoteproc/sub.mk create mode 100644 optee/optee_os/ta/remoteproc/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/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_gcm_counter_overflow_test_decrypt.h create mode 100644 optee/optee_test/host/xtest/aes_gcm_counter_overflow_test_encrypt.h create mode 100644 optee/optee_test/host/xtest/asym_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/clear_storage.c create mode 100644 optee/optee_test/host/xtest/clear_storage.h 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/patches/0016-TEE_Crypto_API.xml.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/pkcs11_1000.h 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/symm_cipher_perf.c 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 100644 optee/optee_test/scripts/aes_gcm_test.py 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/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/crypto_perf/Android.mk create mode 100644 optee/optee_test/ta/crypto_perf/Makefile create mode 100644 optee/optee_test/ta/crypto_perf/include/ta_crypto_perf.h create mode 100644 optee/optee_test/ta/crypto_perf/include/ta_crypto_perf_priv.h create mode 100644 optee/optee_test/ta/crypto_perf/include/user_ta_header_defines.h create mode 100644 optee/optee_test/ta/crypto_perf/sub.mk create mode 100644 optee/optee_test/ta/crypto_perf/ta_crypto_perf.c create mode 100644 optee/optee_test/ta/crypto_perf/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/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/cpubl-payload-dec/LICENSE create mode 100644 optee/samples/cpubl-payload-dec/Makefile create mode 100644 optee/samples/cpubl-payload-dec/ta/Makefile create mode 100644 optee/samples/cpubl-payload-dec/ta/entry.c create mode 100644 optee/samples/cpubl-payload-dec/ta/include/ta_cpubl_dec.h create mode 100644 optee/samples/cpubl-payload-dec/ta/sub.mk create mode 100644 optee/samples/cpubl-payload-dec/ta/user_ta.mk create mode 100644 optee/samples/cpubl-payload-dec/ta/user_ta_header_defines.h create mode 100644 optee/samples/ftpm-helper/LICENSE create mode 100644 optee/samples/ftpm-helper/Makefile create mode 100644 optee/samples/ftpm-helper/README.md create mode 100644 optee/samples/ftpm-helper/host/Makefile create mode 100644 optee/samples/ftpm-helper/host/ftpm_helper_ca.c create mode 100644 optee/samples/ftpm-helper/host/tool/conf/ftpm_i_ca_sim.config create mode 100644 optee/samples/ftpm-helper/host/tool/conf/ftpm_root_ca_sim.config create mode 100755 optee/samples/ftpm-helper/host/tool/ftpm_device_provision.sh create mode 100755 optee/samples/ftpm-helper/host/tool/ftpm_manufacturer_ca_sign_sid_csr.py create mode 100755 optee/samples/ftpm-helper/host/tool/ftpm_manufacturer_ca_sign_sid_csr.sh create mode 100755 optee/samples/ftpm-helper/host/tool/ftpm_manufacturer_ca_simulator.py create mode 100755 optee/samples/ftpm-helper/host/tool/ftpm_manufacturer_ca_simulator.sh create mode 100755 optee/samples/ftpm-helper/host/tool/ftpm_manufacturer_gen_ek_csr.sh create mode 100755 optee/samples/ftpm-helper/host/tool/ftpm_manufacturer_gen_ek_csr_tool.py create mode 100755 optee/samples/ftpm-helper/host/tool/ftpm_offline_provisioning_verify.sh create mode 100755 optee/samples/ftpm-helper/host/tool/ftpm_test_local_attestation.sh create mode 100755 optee/samples/ftpm-helper/host/tool/kdk_gen.py create mode 100644 optee/samples/ftpm-helper/host/tool/lib/aes_drbg.py create mode 100644 optee/samples/ftpm-helper/host/tool/lib/ftpm_ek.py create mode 100644 optee/samples/ftpm-helper/host/tool/lib/ftpm_ek_csr.py create mode 100644 optee/samples/ftpm-helper/host/tool/lib/silicon_id_csr.py create mode 100755 optee/samples/ftpm-helper/host/tool/odm_ekb_gen.py create mode 100755 optee/samples/ftpm-helper/host/tool/oem_ekb_gen.py create mode 100644 optee/samples/ftpm-helper/ta/Makefile create mode 100644 optee/samples/ftpm-helper/ta/ftpm_helper_ta.c create mode 100644 optee/samples/ftpm-helper/ta/include/ftpm_helper_ta.h create mode 100644 optee/samples/ftpm-helper/ta/sub.mk create mode 100644 optee/samples/ftpm-helper/ta/user_ta_header_defines.h 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/samples/ms-tpm-20-ref/.clang-format create mode 100644 optee/samples/ms-tpm-20-ref/.travis.yml create mode 100644 optee/samples/ms-tpm-20-ref/CONTRIBUTING.md create mode 100644 optee/samples/ms-tpm-20-ref/CppProperties.json create mode 100644 optee/samples/ms-tpm-20-ref/LICENSE create mode 100644 optee/samples/ms-tpm-20-ref/README.md create mode 100644 optee/samples/ms-tpm-20-ref/SECURITY.md create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/README.md create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/Makefile create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/Makefile create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/fTPM.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/Wolf/TpmToWolfHash.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/Wolf/TpmToWolfMath.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/Wolf/TpmToWolfSym.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/Wolf/user_settings.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/fTPM.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/fTPM_event_log.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/fTPM_event_log_private.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/fTPM_helpers.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/lib/mbedtls_ltc/sub.mk create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/lib/mbedtls_ltc/user_custom.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/lib/sub.mk create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/lib/tpm/sub.mk create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/lib/wolf/sub.mk create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/AdminPPI.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/Cancel.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/Clock.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/DebugHelpers.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/EPS.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/Entropy.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/EventLogPrint.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/LocalityPlat.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/NVMem.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/NvAdmin.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/PPPlat.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/PlatformACT.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/PlatformData.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/PowerPlat.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/RunCommand.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/Unique.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/fTPM_event_log.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/fTPM_helpers.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/include/Admin.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/include/Platform.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/include/PlatformData.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/include/Platform_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/reference/RuntimeSupport.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/reference/include/RuntimeSupport.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/reference/include/TpmProfile.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/reference/include/TpmSal.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/reference/include/VendorString.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/reference/include/bool.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/sub.mk create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/user_ta_header_defines.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/ta_prod_signing_scripts/README.md create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/ta_prod_signing_scripts/generate_digest.py create mode 100644 optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/ta_prod_signing_scripts/stitch_ta.py create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/.cproject create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/.mxproject create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/.project create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/.settings/com.atollic.truestudio.debug.hardware_device.prefs create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/.settings/language.settings.xml create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/.settings/org.eclipse.cdt.managedbuilder.core.prefs create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Device/ST/STM32L4xx/Include/stm32l476xx.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Device/ST/STM32L4xx/Include/stm32l4xx.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Device/ST/STM32L4xx/Include/system_stm32l4xx.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/arm_common_tables.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/arm_const_structs.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/arm_math.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/cmsis_armcc.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/cmsis_armcc_V6.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/cmsis_gcc.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cm0.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cm0plus.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cm3.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cm4.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cm7.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cmFunc.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cmInstr.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cmSimd.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_sc000.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_sc300.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_cortex.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_def.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_dma.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_dma_ex.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash_ex.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash_ramfunc.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_gpio.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_gpio_ex.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_i2c.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_i2c_ex.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pcd.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pcd_ex.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pwr.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pwr_ex.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rcc.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rcc_ex.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rng.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rtc.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rtc_ex.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_tim.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_tim_ex.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_uart.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_uart_ex.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_usb.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_cortex.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_dma.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_dma_ex.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash_ex.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash_ramfunc.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_gpio.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_i2c.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_i2c_ex.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pcd.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pcd_ex.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pwr.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pwr_ex.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rcc.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rcc_ex.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rng.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rtc.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rtc_ex.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_tim.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_tim_ex.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_uart.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_uart_ex.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_usb.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/main.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/stm32l4xx_hal_conf.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/stm32l4xx_it.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/usb_device.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/usbd_cdc_if.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/usbd_conf.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/usbd_desc.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc/usbd_cdc.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_core.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ctlreq.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_def.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ioreq.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Nucleo-L476RG.elf.launch create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Nucleo-L476RG.ioc create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Nucleo-L476RG.pdf create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Nucleo-L476RG.txt create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/STM32L476RG_FLASH.ld create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/main.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/stm32l4xx_hal_msp.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/stm32l4xx_it.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/system_stm32l4xx.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/usb_device.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/usbd_cdc_if.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/usbd_conf.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/usbd_desc.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/mx.scratch create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/startup/startup_stm32l476xx.s create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/.cproject create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/.mxproject create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/.project create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/.settings/com.atollic.truestudio.debug.hardware_device.prefs create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/.settings/language.settings.xml create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/.settings/org.eclipse.cdt.managedbuilder.core.prefs create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Device/ST/STM32L4xx/Include/stm32l4a6xx.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Device/ST/STM32L4xx/Include/stm32l4xx.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Device/ST/STM32L4xx/Include/system_stm32l4xx.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/arm_common_tables.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/arm_const_structs.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/arm_math.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/cmsis_armcc.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/cmsis_armcc_V6.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/cmsis_gcc.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cm0.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cm0plus.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cm3.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cm4.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cm7.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cmFunc.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cmInstr.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cmSimd.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_sc000.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_sc300.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_cortex.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_def.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_dma.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_dma_ex.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash_ex.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash_ramfunc.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_gpio.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_gpio_ex.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_i2c.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_i2c_ex.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pcd.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pcd_ex.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pwr.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pwr_ex.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rcc.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rcc_ex.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rng.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rtc.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rtc_ex.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_tim.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_tim_ex.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_uart.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_uart_ex.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_usb.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_cortex.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_dma.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_dma_ex.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash_ex.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash_ramfunc.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_gpio.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_i2c.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_i2c_ex.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pcd.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pcd_ex.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pwr.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pwr_ex.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rcc.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rcc_ex.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rng.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rtc.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rtc_ex.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_tim.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_tim_ex.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_uart.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_uart_ex.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_usb.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/main.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/stm32l4xx_hal_conf.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/stm32l4xx_it.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/usb_device.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/usbd_cdc_if.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/usbd_conf.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/usbd_desc.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc/usbd_cdc.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_core.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ctlreq.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_def.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ioreq.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Nucleo-L4A6RG.elf.launch create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Nucleo-L4A6RG.ioc create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Nucleo-L4A6RG.pdf create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Nucleo-L4A6RG.txt create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/STM32L4A6RG_FLASH.ld create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/main.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/stm32l4xx_hal_msp.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/stm32l4xx_it.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/system_stm32l4xx.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/usb_device.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/usbd_cdc_if.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/usbd_conf.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/usbd_desc.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/mx.scratch create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/startup/startup_stm32l4a6xx.s create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/include/PlatformData.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/include/prototypes/Platform_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/Cancel.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/Clock.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/Entropy.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/LocalityPlat.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/NVMem.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/PPPlat.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/PlatformData.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/PowerPlat.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/RunCommand.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/Unique.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/TPMDevice/include/StmUtil.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/TPMDevice/include/TpmDevice.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/TPMDevice/include/user_settings.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/TPMDevice/src/StmUtil.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/TPMDevice/src/TpmDevice.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/syscalls.c create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/USB_Hookup.jpg create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/VCOM/VCOM-TPM.sln create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/VCOM/VCOM-TPM/VCOM-TPM.cpp create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/VCOM/VCOM-TPM/VCOM-TPM.vcxproj create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/VCOM/VCOM-TPM/VCOM-TPM.vcxproj.filters create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/VCOM/VCOM-TPM/stdafx.cpp create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/VCOM/VCOM-TPM/stdafx.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/VCOM/VCOM-TPM/targetver.h create mode 100644 optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/microUSB_Hookup.jpg create mode 100644 optee/samples/ms-tpm-20-ref/Samples/TPMCmd-DeviceID/Platform/src/EPS.c create mode 100755 optee/samples/ms-tpm-20-ref/Samples/TPMCmd-DeviceID/build-tpmsimulator-deviceid create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/Makefile.am create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/Platform/include/Platform.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/Platform/include/PlatformACT.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/Platform/include/PlatformClock.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/Platform/include/PlatformData.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/Platform/include/prototypes/Platform_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/Platform/platform.vcxproj create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/Platform/platform.vcxproj.filters create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/Cancel.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/Clock.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/DebugHelpers.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/Entropy.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/LocalityPlat.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/NVMem.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/PPPlat.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/PlatformACT.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/PlatformData.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/PowerPlat.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/RunCommand.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/Unique.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/include/TpmTcpProtocol.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/include/prototypes/Simulator_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/simulator.vcxproj create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/src/TPMCmdp.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/src/TPMCmds.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/src/TcpServer.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/src/tpmsim.service create mode 100755 optee/samples/ms-tpm-20-ref/TPMCmd/bootstrap create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/configure.ac create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/flags.m4 create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/simulator.sln create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/Tpm.vcxproj create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/Tpm.vcxproj.filters create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/ACT.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/BaseTypes.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/BnValues.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Capabilities.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CommandAttributeData.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CommandAttributes.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CommandDispatchData.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CommandDispatcher.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Commands.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CompilerDependencies.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CryptEcc.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CryptHash.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CryptRand.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CryptRsa.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CryptSym.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CryptTest.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/EccTestData.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Global.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/GpMacros.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/HandleProcess.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/HashTestData.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/InternalRoutines.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/KdfTestData.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/LibSupport.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ltc/LtcSettings.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ltc/TpmToLtcHash.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ltc/TpmToLtcMath.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ltc/TpmToLtcSym.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Marshal.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Mbedtls/TpmToMbedtlsHash.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Mbedtls/TpmToMbedtlsMath.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Mbedtls/TpmToMbedtlsSym.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/MinMax.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/NV.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/OIDs.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ossl/TpmToOsslHash.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ossl/TpmToOsslMath.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ossl/TpmToOsslSym.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/PRNG_TestVectors.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/RsaTestData.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/SelfTest.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/SupportLibraryFunctionPrototypes_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/SymmetricTest.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/SymmetricTestData.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TPMB.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TableMarshal.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TableMarshalDefines.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TableMarshalTypes.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Tpm.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TpmASN1.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TpmAlgorithmDefines.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TpmBuildSwitches.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TpmError.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TpmProfile.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TpmTypes.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/VendorString.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Wolf/TpmToWolfHash.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Wolf/TpmToWolfMath.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Wolf/TpmToWolfSym.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Wolf/user_settings.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/X509.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ACT_SetTimeout_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ACT_spt_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/AC_GetCapability_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/AC_Send_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/AC_spt_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ActivateCredential_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/AlgorithmCap_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/AlgorithmTests_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Attest_spt_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Bits_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/BnConvert_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/BnMath_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/BnMemory_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CertifyCreation_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CertifyX509_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Certify_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ChangeEPS_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ChangePPS_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ClearControl_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Clear_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ClockRateAdjust_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ClockSet_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CommandAudit_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CommandCodeAttributes_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CommandDispatcher_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Commit_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ContextLoad_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ContextSave_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Context_spt_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CreateLoaded_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CreatePrimary_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Create_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptCmac_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptDes_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptEccCrypt_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptEccKeyExchange_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptEccMain_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptEccSignature_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptHash_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptPrimeSieve_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptPrime_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptRand_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptRsa_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptSelfTest_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptSmac_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptSym_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptUtil_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/DA_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/DictionaryAttackLockReset_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/DictionaryAttackParameters_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Duplicate_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ECC_Decrypt_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ECC_Encrypt_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ECC_Parameters_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ECDH_KeyGen_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ECDH_ZGen_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/EC_Ephemeral_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/EncryptDecrypt2_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/EncryptDecrypt_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/EncryptDecrypt_spt_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Entity_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/EventSequenceComplete_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/EvictControl_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ExecCommand_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/FieldUpgradeData_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/FieldUpgradeStart_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/FirmwareRead_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/FlushContext_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/GetCapability_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/GetCommandAuditDigest_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/GetRandom_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/GetSessionAuditDigest_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/GetTestResult_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/GetTime_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/HMAC_Start_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/HMAC_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Handle_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/HashSequenceStart_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Hash_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/HierarchyChangeAuth_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/HierarchyControl_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Hierarchy_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Import_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/IncrementalSelfTest_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/IoBuffers_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/LoadExternal_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Load_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Locality_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/MAC_Start_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/MAC_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/MakeCredential_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Manufacture_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Marshal_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/MathOnByteBuffers_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Memory_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_Certify_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_ChangeAuth_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_DefineSpace_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_Extend_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_GlobalWriteLock_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_Increment_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_ReadLock_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_ReadPublic_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_Read_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_SetBits_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_UndefineSpaceSpecial_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_UndefineSpace_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_WriteLock_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_Write_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_spt_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NvDynamic_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NvReserved_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ObjectChangeAuth_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Object_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Object_spt_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_Allocate_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_Event_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_Extend_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_Read_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_Reset_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_SetAuthPolicy_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_SetAuthValue_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PP_Commands_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PP_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyAuthValue_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyAuthorizeNV_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyAuthorize_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyCommandCode_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyCounterTimer_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyCpHash_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyDuplicationSelect_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyGetDigest_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyLocality_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyNV_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyNameHash_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyNvWritten_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyOR_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyPCR_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyPassword_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyPhysicalPresence_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyRestart_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicySecret_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicySigned_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyTemplate_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyTicket_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Policy_AC_SendSelect_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Policy_spt_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Power_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PropertyCap_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Quote_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/RSA_Decrypt_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/RSA_Encrypt_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ReadClock_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ReadPublic_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ResponseCodeProcessing_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Response_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Rewrap_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/RsaKeyCache_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SelfTest_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SequenceComplete_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SequenceUpdate_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SessionProcess_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Session_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SetAlgorithmSet_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SetCommandCodeAuditStatus_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SetPrimaryPolicy_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Shutdown_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Sign_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/StartAuthSession_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Startup_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/StirRandom_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TableDrivenMarshal_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TestParms_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Ticket_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Time_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmASN1_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmFail_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmSizeChecks_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToLtcDesSupport_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToLtcMath_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToLtcSupport_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToMbedtlsMath_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToMbedtlsSupport_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToOsslDesSupport_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToOsslMath_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToOsslSupport_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToWolfDesSupport_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToWolfMath_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToWolfSupport_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Unseal_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Vendor_TCG_Test_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/VerifySignature_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/X509_ECC_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/X509_RSA_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/X509_spt_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ZGen_2Phase_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/_TPM_Hash_Data_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/_TPM_Hash_End_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/_TPM_Hash_Start_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/_TPM_Init_fp.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/swap.h create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/X509/TpmASN1.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/X509/X509_ECC.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/X509/X509_RSA.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/X509/X509_spt.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/ECC_Decrypt.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/ECC_Encrypt.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/ECC_Parameters.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/ECDH_KeyGen.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/ECDH_ZGen.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/EC_Ephemeral.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/RSA_Decrypt.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/RSA_Encrypt.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/ZGen_2Phase.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/AttachedComponent/AC_GetCapability.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/AttachedComponent/AC_Send.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/AttachedComponent/AC_spt.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/AttachedComponent/Policy_AC_SendSelect.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/Attest_spt.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/Certify.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/CertifyCreation.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/CertifyX509.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/GetCommandAuditDigest.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/GetSessionAuditDigest.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/GetTime.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/Quote.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Capability/GetCapability.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Capability/TestParms.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/ClockTimer/ACT_SetTimeout.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/ClockTimer/ACT_spt.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/ClockTimer/ClockRateAdjust.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/ClockTimer/ClockSet.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/ClockTimer/ReadClock.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/CommandAudit/SetCommandCodeAuditStatus.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Context/ContextLoad.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Context/ContextSave.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Context/Context_spt.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Context/EvictControl.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Context/FlushContext.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/DA/DictionaryAttackLockReset.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/DA/DictionaryAttackParameters.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Duplication/Duplicate.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Duplication/Import.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Duplication/Rewrap.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyAuthValue.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyAuthorize.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyAuthorizeNV.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyCommandCode.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyCounterTimer.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyCpHash.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyDuplicationSelect.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyGetDigest.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyLocality.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyNV.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyNameHash.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyNvWritten.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyOR.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyPCR.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyPassword.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyPhysicalPresence.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicySecret.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicySigned.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyTemplate.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyTicket.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/Policy_spt.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Ecdaa/Commit.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/FieldUpgrade/FieldUpgradeData.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/FieldUpgrade/FieldUpgradeStart.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/FieldUpgrade/FirmwareRead.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/HashHMAC/EventSequenceComplete.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/HashHMAC/HMAC_Start.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/HashHMAC/HashSequenceStart.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/HashHMAC/MAC_Start.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/HashHMAC/SequenceComplete.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/HashHMAC/SequenceUpdate.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/ChangeEPS.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/ChangePPS.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/Clear.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/ClearControl.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/CreatePrimary.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/HierarchyChangeAuth.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/HierarchyControl.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/SetPrimaryPolicy.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Misc/PP_Commands.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Misc/SetAlgorithmSet.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_Certify.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_ChangeAuth.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_DefineSpace.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_Extend.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_GlobalWriteLock.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_Increment.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_Read.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_ReadLock.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_ReadPublic.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_SetBits.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_UndefineSpace.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_UndefineSpaceSpecial.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_Write.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_WriteLock.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_spt.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/ActivateCredential.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/Create.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/CreateLoaded.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/Load.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/LoadExternal.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/MakeCredential.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/ObjectChangeAuth.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/Object_spt.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/ReadPublic.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/Unseal.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_Allocate.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_Event.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_Extend.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_Read.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_Reset.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_SetAuthPolicy.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_SetAuthValue.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Random/GetRandom.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Random/StirRandom.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Session/PolicyRestart.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Session/StartAuthSession.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Signature/Sign.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Signature/VerifySignature.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Startup/Shutdown.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Startup/Startup.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Symmetric/EncryptDecrypt.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Symmetric/EncryptDecrypt2.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Symmetric/EncryptDecrypt_spt.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Symmetric/HMAC.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Symmetric/Hash.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Symmetric/MAC.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Testing/GetTestResult.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Testing/IncrementalSelfTest.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Testing/SelfTest.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Vendor/Vendor_TCG_Test.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/AlgorithmTests.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/BnConvert.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/BnMath.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/BnMemory.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptCmac.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptDes.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptEccCrypt.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptEccData.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptEccKeyExchange.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptEccMain.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptEccSignature.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptHash.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptPrime.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptPrimeSieve.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptRand.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptRsa.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptSelfTest.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptSmac.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptSym.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptUtil.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/Mbedtls/Mbedtls_mpi_Ltc_desc.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/Mbedtls/TpmToMbedtlsMath.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/Mbedtls/TpmToMbedtlsSupport.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/PrimeData.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/RsaKeyCache.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/Ticket.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/ltc/TpmToLtcDesSupport.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/ltc/TpmToLtcMath.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/ltc/TpmToLtcSupport.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/ossl/TpmToOsslDesSupport.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/ossl/TpmToOsslMath.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/ossl/TpmToOsslSupport.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/wolf/TpmToWolfDesSupport.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/wolf/TpmToWolfMath.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/wolf/TpmToWolfSupport.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/wolf/wolfssl.vcxproj create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/events/_TPM_Hash_Data.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/events/_TPM_Hash_End.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/events/_TPM_Hash_Start.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/events/_TPM_Init.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/main/CommandDispatcher.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/main/ExecCommand.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/main/SessionProcess.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/CommandAudit.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/DA.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/Hierarchy.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/NvDynamic.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/NvReserved.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/Object.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/PCR.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/PP.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/Session.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/Time.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/AlgorithmCap.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Bits.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/CommandCodeAttributes.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Entity.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Global.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Handle.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/IoBuffers.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Locality.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Manufacture.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Marshal.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/MathOnByteBuffers.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Memory.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Power.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/PropertyCap.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Response.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/ResponseCodeProcessing.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/TableDrivenMarshal.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/TableMarshalData.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/TpmFail.c create mode 100644 optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/TpmSizeChecks.c create mode 100644 optee/samples/pkcs11-sample/LICENSE create mode 100644 optee/samples/pkcs11-sample/Makefile create mode 100644 optee/samples/pkcs11-sample/host/Makefile create mode 100644 optee/samples/pkcs11-sample/host/pkcs11_sample_ca.c 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..16e3de6 --- /dev/null +++ b/commitFile.txt @@ -0,0 +1,3815 @@ +Updating prebuilts and/or headers + +e69802011573f0178bf178e270e2645bf7f62df8 - optee_src_build.sh +d15f50688485e11293e0d0bd66d73655e79f7718 - nvcommon_build.sh +79e468b5eb3da5dfc49e4d5027cff370177d9699 - optee/tegra234-optee.dts +c8e0513c06b701ddb65f4524dded76abdf77647c - optee/optee_os/Makefile +8b3eaf0d1f2e980508aac43f9391b7650d628a35 - optee/optee_os/.clang-format +96558a7a79bf90ebde8720b0087c9c578efa981b - optee/optee_os/.checkpatch.conf +f0e65c7d69a4cdd4ca654f479018b5d319c49485 - optee/optee_os/MAINTAINERS +d2eb09f40476bdbbdbfa709b1cc0cc80c873f0ee - optee/optee_os/CHANGELOG.md +6bf9bd872a69d8c13e8dcac71fac8d094646251d - optee/optee_os/README.md +3a608e255399bb5cf2302bb52e533d81c469ecce - optee/optee_os/LICENSE.NVIDIA +370d68b1c9485f254e7c701c31e3c74fd16cacd7 - optee/optee_os/LICENSE +25ecfc13bc9b5205cb9db1ffb015fa973c8a754b - optee/optee_os/typedefs.checkpatch +a7d5f5139d7b9b81a37f26931af0c4922afdaa69 - optee/optee_os/keys/default_ta.pem +4ec1a9b7d2f64d94ccdaa889afe2cba025e5b33b - optee/optee_os/keys/default.pem +739a223e693f30815eb57c7b1bdae6bc5e2c8028 - optee/optee_os/lib/libunw/unwind_arm32.c +7a5d43bd6596d563ed816f9c1422b44e0b5a1b26 - optee/optee_os/lib/libunw/unwind_riscv.c +aa98ee7f2f58e8d9487aef8238db499ea48e9bf7 - optee/optee_os/lib/libunw/unwind_arm64.c +04ec37249588b61e2dfa9cd7874a618b1f27bddd - optee/optee_os/lib/libunw/include/unw/unwind.h +be4c6a3071f47d6d836b24e210bc1d446aa9afcc - optee/optee_os/lib/libdl/dlfcn.c +902b546a61d836961ed0f5fe348b564b0583755a - optee/optee_os/lib/libdl/include/dlfcn.h +34cd5767e5498e0e9fbc3ea30953dbb7a30cc6f6 - optee/optee_os/lib/libmbedtls/mbedtls/BUGS.md +23318adb490dc06c5a2e3ec6619ef9ccb2751594 - optee/optee_os/lib/libmbedtls/mbedtls/SECURITY.md +c15664798564c531febb48552a2c5b37843e833e - optee/optee_os/lib/libmbedtls/mbedtls/SUPPORT.md +36296c1c4e8e0d763476423778c44dbc04b50bd4 - optee/optee_os/lib/libmbedtls/mbedtls/.uncrustify.cfg +b6d56304e5d93a8359613c2c00dd9360ef825323 - optee/optee_os/lib/libmbedtls/mbedtls/README.md +673fcd822394bfa34159701cc14750fea1a03f35 - optee/optee_os/lib/libmbedtls/mbedtls/ChangeLog +2b8b815229aa8a61e483fb4ba0588b8b6c491890 - optee/optee_os/lib/libmbedtls/mbedtls/LICENSE +fc289e09626931286b47247438179e2e37b56f5f - optee/optee_os/lib/libmbedtls/mbedtls/CONTRIBUTING.md +d44e3c3b56f9fdcb029f34d00b948afd4d6e45e7 - optee/optee_os/lib/libmbedtls/mbedtls/library/version.c +4c895118edfa4ee419cc7796b5185536917ec939 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_client.c +7770ce4815a1ba16ea28e17fc5c528e27440e789 - optee/optee_os/lib/libmbedtls/mbedtls/library/check_crypto_config.h +e4ef78ff1d50ef8cadd19f1505ff94f1dac62093 - optee/optee_os/lib/libmbedtls/mbedtls/library/md5.c +e5be29bd80ac40ecaad6bcc41abb658bd1c695ca - optee/optee_os/lib/libmbedtls/mbedtls/library/hash_info.h +bcdd5b1c541c7197c9ae80b7b41de32ae5b2ad65 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_debug_helpers.h +1dd82643f69b90a342121c72e599b6c3ed613d26 - optee/optee_os/lib/libmbedtls/mbedtls/library/ecdsa.c +d1961d06c288f65b5fc6fb506b4a2631b7947227 - optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_mod.h +b6638d76665125ba505e4beda15943c8a4b75a8d - optee/optee_os/lib/libmbedtls/mbedtls/library/entropy_poll.h +16359a21196d6070404f14d38f5aef727f2167e1 - optee/optee_os/lib/libmbedtls/mbedtls/library/threading.c +fe734580e467840b9b4afa0716fd6e3ffd4942e7 - optee/optee_os/lib/libmbedtls/mbedtls/library/ecjpake.c +5c96237b70f097ac411154f9c56dc1e6bf3b8689 - optee/optee_os/lib/libmbedtls/mbedtls/library/pem.c +e3d039b0374d156fb2acf43a47ca8f553955e544 - optee/optee_os/lib/libmbedtls/mbedtls/library/dhm.c +98cd71c1713713bbb6cd199be758b8592a27c42d - optee/optee_os/lib/libmbedtls/mbedtls/library/padlock.c +b29e0ceb0e7c97ce7824a79a6fc154dcdf35bca0 - optee/optee_os/lib/libmbedtls/mbedtls/library/ecp.c +84eb33b63afb20735abd67e33ced56e1e69173b9 - optee/optee_os/lib/libmbedtls/mbedtls/library/chachapoly.c +6ee8cc29349d39a34b172357c2d5da549d315813 - optee/optee_os/lib/libmbedtls/mbedtls/library/pk_wrap.c +7271c82b848fda7b11750274f46664ba6a7f7ab0 - optee/optee_os/lib/libmbedtls/mbedtls/library/entropy.c +7d92089bbd60045d1caf07e02223ac6b8e1708cf - optee/optee_os/lib/libmbedtls/mbedtls/library/bn_mul.h +03d4e38794009d4be0452dc243665f871a6025b1 - optee/optee_os/lib/libmbedtls/mbedtls/library/ctr_drbg.c +78f1b75306d2a679d87a1dbcd73cb656c5410cc9 - optee/optee_os/lib/libmbedtls/mbedtls/library/x509_crt.c +01bc4944a27e202656ef9f1fdde863fb9e4de3e3 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls.c +8c9f2ee60d829ece04a767a04a4ef06de9d72139 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_cache.c +d95ae27168cedfdd598f6a92654ac3c00f3b67f0 - optee/optee_os/lib/libmbedtls/mbedtls/library/error.c +b24a27e4ce8b259ccc9eea73e1bfbd492f70bb99 - optee/optee_os/lib/libmbedtls/mbedtls/library/pkcs7.c +6a234d07608722c41590614b9f0ec2b5e88e7339 - optee/optee_os/lib/libmbedtls/mbedtls/library/padlock.h +739a5f1f19451ca406d2e52b8eec849c62eb53a8 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_ciphersuites.c +99e0a239c9f19e14cf6ce18a3840fb2fca404713 - optee/optee_os/lib/libmbedtls/mbedtls/library/hmac_drbg.c +ce8fff546c26c2f14d68f3d3fcf9f20a14c115ce - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_invasive.h +4af04f83c979b6ced3e680a2fa590ac6036c49c9 - optee/optee_os/lib/libmbedtls/mbedtls/library/oid.c +e165b12c049a63c601126933df86ac7788533c80 - optee/optee_os/lib/libmbedtls/mbedtls/library/version_features.c +eaf09cc7765dd62d5217d239db5866ef14cbbcc5 - optee/optee_os/lib/libmbedtls/mbedtls/library/nist_kw.c +f33d29752d62bd5be5b94ab27abcb2c62bfae415 - optee/optee_os/lib/libmbedtls/mbedtls/library/sha256.c +b3f01220df7e01b622c4d903e9c40c6cb3203ec7 - optee/optee_os/lib/libmbedtls/mbedtls/library/platform.c +ff7a9b66046c0de1a36bcd7c09a2307fb860aeb4 - optee/optee_os/lib/libmbedtls/mbedtls/library/aes.c +ff5f51be79458657afcb92b173c63f15e725652a - optee/optee_os/lib/libmbedtls/mbedtls/library/net_sockets.c +d9581ba9d5255971f4d9e85adcc8e255e3690af9 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_ticket.c +6e68dbefe68f198625ac005ee1030684626f677e - optee/optee_os/lib/libmbedtls/mbedtls/library/constant_time_internal.h +7727cc53f6d74155b26ee8b5998bf3747bc8697e - optee/optee_os/lib/libmbedtls/mbedtls/library/platform_util.c +3b9243735cc374f8ade3dfa5579640b6911d38a3 - optee/optee_os/lib/libmbedtls/mbedtls/library/chacha20.c +90e90cf98195b7b842e4fe3560dc3af0b98576fe - optee/optee_os/lib/libmbedtls/mbedtls/library/ecp_invasive.h +8404b765bfb0f3d07acd2403655c41357841fbd8 - optee/optee_os/lib/libmbedtls/mbedtls/library/lmots.h +6b031e72d28b388ec56568fb16dbfcd3b49b23df - optee/optee_os/lib/libmbedtls/mbedtls/library/pk.c +15644378eab950e066a06564db258eb38a5628c4 - optee/optee_os/lib/libmbedtls/mbedtls/library/sha512.c +0c28525180d3b52933a129728b8ca9c7b45685ef - optee/optee_os/lib/libmbedtls/mbedtls/library/aesce.h +119003e69094f7f58c5f7b7c8297712eb1c066a6 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_misc.h +19d6760fd47f19624204d669e96410c6f2de2cc8 - optee/optee_os/lib/libmbedtls/mbedtls/library/x509_create.c +bb141273d9cc4967730f58c9df9ccf52ebce1c5d - optee/optee_os/lib/libmbedtls/mbedtls/library/cipher.c +cba8732c79a4b1f77acfaa6e407abf1f883b1424 - optee/optee_os/lib/libmbedtls/mbedtls/library/pkparse.c +5bd7a8da938d48cedd9875f261fb6189b284d407 - optee/optee_os/lib/libmbedtls/mbedtls/library/x509_crl.c +6732bbddb23ffdbd9f0a76ab9b2c259133fb61a9 - optee/optee_os/lib/libmbedtls/mbedtls/library/x509_csr.c +edebd5be7d3d6f1d67ed39ee288f6152cf28ade3 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_debug_helpers_generated.c +1eea4712651b9bbf77f83ce725f1a932493f8894 - optee/optee_os/lib/libmbedtls/mbedtls/library/x509.c +baf14771ebe0476dbe644e7bfcc8d62b21c5713f - optee/optee_os/lib/libmbedtls/mbedtls/library/asn1parse.c +5fa68d30e7d3c6a0d10bccf0826c15fc0e9d38a9 - optee/optee_os/lib/libmbedtls/mbedtls/library/pkwrite.c +4509f6798e2fca09d888f42f2ce9ee2da001c307 - optee/optee_os/lib/libmbedtls/mbedtls/library/alignment.h +4a9d15ec9dfd5b5f325d8f087f7190d64edc097e - optee/optee_os/lib/libmbedtls/mbedtls/library/constant_time_invasive.h +db65452086da8483b9d6b915fb70a40b948545c3 - optee/optee_os/lib/libmbedtls/mbedtls/library/lms.c +53415759da55cbb415f71e3ebfde42e38a068a50 - optee/optee_os/lib/libmbedtls/mbedtls/library/pkwrite.h +23f18586a432d734114ed496a5c353a1650035f6 - optee/optee_os/lib/libmbedtls/mbedtls/library/asn1write.c +3639af0ef05f1a45d10b37194fa545d2b9bcf993 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_client.h +3ca7167353009560f76e6956baa3bf4b34a563cd - optee/optee_os/lib/libmbedtls/mbedtls/library/md.c +4107f08bc1470b4cf703bd702bd458b67a329e79 - optee/optee_os/lib/libmbedtls/mbedtls/library/aesce.c +dc62d3c0502a13a522b51dde3a39f8d9c9f6da3c - optee/optee_os/lib/libmbedtls/mbedtls/library/base64.c +0607553e84acf3ad608f42db5a86151053e21e4b - optee/optee_os/lib/libmbedtls/mbedtls/library/des.c +a0955ccbdbfb3c22ecbca9a8f91ed5a3a1e775a3 - optee/optee_os/lib/libmbedtls/mbedtls/library/constant_time.c +ce3bfca0ba9327f83686dc6d74a2170ecb14d4ae - optee/optee_os/lib/libmbedtls/mbedtls/library/pkcs5.c +8b9d26205c5224da0964b29edd7a45821daf96db - optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_mod.c +e1c3d2e229393412977b04c76cf8c86a4821ea07 - optee/optee_os/lib/libmbedtls/mbedtls/library/gcm.c +d90aa1bf42c16ceb4870ae7a3d3678fa4b01fd9d - optee/optee_os/lib/libmbedtls/mbedtls/library/hkdf.c +a6c1c10394f80d236c7a242ceaccc0ac6414fe44 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_cookie.c +14353e3414b814893557982d985a03ed8d687abf - optee/optee_os/lib/libmbedtls/mbedtls/library/bignum.c +4ba4b18dcb3a60651d24555a1125a9c2d226af5a - optee/optee_os/lib/libmbedtls/mbedtls/library/x509write_crt.c +85c379cc812b43e8436af3a12ddf9d96cd2ae282 - optee/optee_os/lib/libmbedtls/mbedtls/library/cipher_wrap.c +d974cb499431b226552b0132e29b52d624dbf598 - optee/optee_os/lib/libmbedtls/mbedtls/library/hash_info.c +47ddc30fc88488fb374094fa2eceba8e6fad4138 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_keys.h +8628488e4ae680019e691313853788e572480181 - optee/optee_os/lib/libmbedtls/mbedtls/library/aria.c +246d2c4b6bcd2bc5d8caa3c647b4849dbde31334 - optee/optee_os/lib/libmbedtls/mbedtls/library/pk_wrap.h +4b81ddd5a55b6605b66c2ef896883cbd83513d12 - optee/optee_os/lib/libmbedtls/mbedtls/library/lmots.c +eb190023507c8a4e75925189905512116ee2ff9b - optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_mod_raw.h +2293962f77728a8f33e100aed92d7766a1a2bc57 - optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_mod_raw.c +71d11dea6aa1fca13aaaddd6c4c9a53dd0a6d243 - optee/optee_os/lib/libmbedtls/mbedtls/library/ecp_curves.c +67958d1e91e6df087bcc331a433b33985307df71 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_server.c +6c0519e9add157846123cb46d3dcb2e90afdb0e4 - optee/optee_os/lib/libmbedtls/mbedtls/library/md_wrap.h +1c1eacc97bf0cef27c7814ef8505fa0698c5ba6b - optee/optee_os/lib/libmbedtls/mbedtls/library/common.h +6c39e72e1686552144f2e5d1bb7e61b35c9f24d4 - optee/optee_os/lib/libmbedtls/mbedtls/library/timing.c +b5af70ad6da2f4b68ec723d1f31dac17e99bbce8 - optee/optee_os/lib/libmbedtls/mbedtls/library/rsa_alt_helpers.h +7a9dfd9eb3ad4b72c8eabba544aa22bad1b76b82 - optee/optee_os/lib/libmbedtls/mbedtls/library/entropy_poll.c +2e2d37262a4fcf868902f0d8cc7dd769edebdf07 - optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_mod_raw_invasive.h +783f3d68843e641b6aae9942ecf5ee71d880e87c - optee/optee_os/lib/libmbedtls/mbedtls/library/poly1305.c +154a942dbce1fc3eda40ac948f9052a7b64031ed - optee/optee_os/lib/libmbedtls/mbedtls/library/aesni.h +92e4737de82118950ee187100f82cea0f21892b8 - optee/optee_os/lib/libmbedtls/mbedtls/library/sha1.c +4ebf29fb2f2de150df473f3205cbe65f24187d71 - optee/optee_os/lib/libmbedtls/mbedtls/library/pkcs12.c +2a42128d6600aa5ac94c8fa8e33eae58294b9979 - optee/optee_os/lib/libmbedtls/mbedtls/library/aesni.c +50947d3bdc6828a91c5cc87e98ddfad59819b8da - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_client.c +a107e54f6aa27c409eca764bbbb57b5076f1d8f7 - optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_core.h +35fd3ec54ab25ba897c90670e275a02b663398fa - optee/optee_os/lib/libmbedtls/mbedtls/library/rsa.c +e38a083f5ceeadc8bb63d1affc622d269e051df1 - optee/optee_os/lib/libmbedtls/mbedtls/library/camellia.c +7742da57b8a202b800bbfd228d11ace043e9ff53 - optee/optee_os/lib/libmbedtls/mbedtls/library/ecp_internal_alt.h +08102e4b89e44c02f731eed0e96c6253be58a28a - optee/optee_os/lib/libmbedtls/mbedtls/library/debug.c +a1bd10348d84bfb7b7403501fe8ac18c43a5d0bd - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_msg.c +c6bb15185e97b9cce4be1b0f1b717c66e7629f85 - optee/optee_os/lib/libmbedtls/mbedtls/library/cmac.c +7eba3b8d085ec63deef34ad378d6ff0dfb8772c6 - optee/optee_os/lib/libmbedtls/mbedtls/library/memory_buffer_alloc.c +e1f466c89d96a92b9a5a8ff9e8057b43819ea576 - optee/optee_os/lib/libmbedtls/mbedtls/library/cipher_wrap.h +d73c9a1f19fa01faff542a4d4883ee8ea65ca3b4 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_generic.c +e3c7fb464c5949f48b961879ae6086786aee3139 - optee/optee_os/lib/libmbedtls/mbedtls/library/ecdh.c +321c43f4130cc3549c34cea35c3bacf190fdd1c1 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls12_client.c +b78ab9253ba70b0daf12c1a340d86e30e18af87b - optee/optee_os/lib/libmbedtls/mbedtls/library/ripemd160.c +94dc6df926a5508e2768a3fd5548f5b3fdce5137 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_keys.c +0ac5b7484872759c4f5fbbadc274e323bec14f04 - optee/optee_os/lib/libmbedtls/mbedtls/library/ccm.c +013516f2c5b13515271831f3074dd8483f46a008 - optee/optee_os/lib/libmbedtls/mbedtls/library/rsa_alt_helpers.c +d44df335d6040133dd34dc6618136bdc05e3d041 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls12_server.c +65cfbaeb638274d06bb384b2cfffe7a71c327566 - optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_core.c +3efd049c3efff8626c1bb0e3cbf8d805a1cab499 - optee/optee_os/lib/libmbedtls/mbedtls/library/x509write_csr.c +2fa6f5794a2b39f61736225acdc1e506d5e34fc4 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pkcs7.h +d1365ec3dcc0d0019b4fad3b9d493349e31f3cc6 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/bignum.h +77a20bc7000287fff180917229509526e46281a1 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/legacy_or_psa.h +b5694fa3505daeb7573dd758bd6b653c0de1afc9 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/platform_util.h +3f7ababa154ed97e00cc354a85dd6dfb01bf191a - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/asn1.h +3a7b764d7fb3eda659a0a40d859cb8c11189711f - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/base64.h +964ae1d8e907f310ba4305e2e2fe5eb420e1d44e - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pkcs12.h +83fa40eedddc46f115ecd2b7d694ec480a7c3877 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_cache.h +66a2f6f275b96497eff585c81cf3ed51789cad81 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/platform.h +a3c459aa9af3e2b93c623fe18df065d29a669438 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/sha512.h +4d297428c707305b537f3a980013fe78d0402f15 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/debug.h +5fea2e00b7e30a8e8af9dbb928580820ed60a923 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/cmac.h +61cf33a4be261e8b301912b2c000b65663d808dd - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/asn1write.h +3a2eeab85a1baae2bdb391b5533fdecc2a0234a7 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/oid.h +9c535b705238b7772d94d641b302c7f6ccf530e3 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/x509_csr.h +2dcb2e9392425e97aadc4ef0ea9d89d98101190b - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/aes.h +dcad3cd68a858d8be40a59270c12554638d3ae73 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/timing.h +17807a5ea8b97b81929fb3617c8fd6d3fd9b5c17 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecdsa.h +7725757926d55789561f174d43a2bb3c559ba3b1 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/x509_crl.h +dc30308e03eccc8a141cfe512ac21d04fc4044ac - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/hmac_drbg.h +600cf785bb5f196b192156e07c54ed60119dcb70 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pem.h +680032e2aefe4768ded08425cbc436df6a7063fd - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/psa_util.h +75a2ca90c8514886cb71aefea93b50682fa8a097 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecp.h +6c5cdf212852e356a6d6b59217c19724f9b8a67c - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl.h +88ed65ff99b7a98bdc81116adf4b3cf3b93c3698 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/mbedtls_config.h +af055530f86c36845b6cc259e1b5ac2d76a06595 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_ciphersuites.h +5f769959d10aaa928ab2ea49c53683aa7ab446ec - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ccm.h +165d31572d6623a93a30cba0e29da8219f645381 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/threading.h +e388025ddb055c304c2192546aaba27fdf13a6f6 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/md.h +c1326c4315382c22d36653a2218259f0213e79e6 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/rsa.h +268fc8231ff7d8492dddbfcad58509e0c1674dda - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_cookie.h +ac851218aae0791fad561743509193cab88ecc7d - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/sha1.h +1dad42f86d7f7f6757aae9d148fcc01da828b685 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/des.h +84a7c437cb483895988e6c99b5d813fe9cd41b20 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/private_access.h +a39c918b9088d3613c149ac45fa6846b8b9e9718 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/version.h +3e3b30db9e4ed323b2f09885bc5d72d553f4af69 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/platform_time.h +290f0392f61186fcf279c42c7af4c748ffdc1077 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ripemd160.h +ab6e31829204b25841aa43a557116e39893507b9 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/x509_crt.h +07d8d6633e32f1d7eae45458f894d16e26b7bb56 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/gcm.h +5b7567b30cde9c7af7e07081004a6de7b6da1677 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/chacha20.h +76ef7f16b918ace41a80bab34517b9e1a3bd849a - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pkcs5.h +9f154acc5f1403d57d4e320fc9ab07cafb77b92c - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/nist_kw.h +69e6f5b121e0db62e1e09066bf65e6672e159171 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/config_psa.h +40e4f413f90a3bd0d2707181246aa1f826afed34 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/md5.h +02b2014b160fc815ac10e66428c5a91782d5bc75 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ctr_drbg.h +71cbb1524e95b09856e4292aa796972a65fc2c5e - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/compat-2.x.h +bc30314856f913a9bb357c98e82512e2c87fba26 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/check_config.h +56f7cb406aad762ab2e4c9da9fb921f2ed50ff52 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/sha256.h +e0cbaac26e5e75327639bdb8c9bbbde147ae7bc3 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/cipher.h +ef896f03a4a70fb9f7d571c6407a45ae7c966628 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/build_info.h +c5e0f50fa94d537bd48d372d258c986a6a5898ef - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/camellia.h +ae94188698121fe0a337e5d7488a1177ba1356d0 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/error.h +2e197e5112b78be40dab23f5ec9ca26f0b7d508f - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/constant_time.h +9f316a2285bbcbbf1359c2ee62b07f0c779242ed - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecdh.h +283e1b401def7ba93ffd27b4951d234c38422f93 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/lms.h +062b24a18b2cef0cd22397570e2d20193bcd2828 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/hkdf.h +155e9ba5f70b0b71503c8a74f18c4ce05e606d6a - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/poly1305.h +f7246ab94041815719a72b69676254de11372fe7 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_ticket.h +4f2a63b8c6d3b8d031455f1f23858eaca5fa2866 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/aria.h +25ab17cb92e38c8a12e0a3092d597ff5051ae123 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/x509.h +dde4b8c94d7b2068edbc221843a8844aac09d597 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pk.h +2ae504202c3cdb2e397d0585366a20df46740d1a - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/chachapoly.h +4db5552e53a6e7b6f6f53186024695937a440891 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecjpake.h +00722750ae0ad09c5bcb00a4d7475f7a04c6e85f - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/entropy.h +5bc0f0200458b7ec76e2ac5d91b388fa9bb5de43 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/memory_buffer_alloc.h +995fefdf01e797568c300e32af0640ed5a752a0a - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/net_sockets.h +db57e0e1844cb5bfe2f2ccb5d4777a86ca46cbc1 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/dhm.h +dee3c667186591ed2aaadc40dd7dcacc58d59153 - optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_platform.h +df1c30dcd3e39f02ac914b9e5ce58ffe854645a9 - optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_config.h +b40b450cd5591203be962595eb2d2ac3460f14c3 - optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_extra.h +a6362ed70348246bf4991cc563a8b4afbbb4fe1d - optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_builtin_primitives.h +e75b044cb8e16e09cc751c08581aa4a438ecb3ed - optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_sizes.h +b4d90f0647f47fa5d3cf20b6a95526b657611c3d - optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_driver_common.h +466672cb252e250e358e3bd653aef09078264614 - optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_builtin_composites.h +7e8e95004150031806caf80fe1ca8acd7cebceb5 - optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_types.h +e4b5bd933df2cac806539b80a680ce33fc0f3171 - optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_struct.h +838afa1cf1cde025164212d9144103902a3a8ad4 - optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_driver_contexts_primitives.h +e0437efb823b29d8680400d8a77274c18a66ade6 - optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_compat.h +ea264bd84d15599d077e90945753dd0ae96e1c9f - optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_values.h +9c07dd65a273431dda589f00c3df456995718771 - optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto.h +d36849352ac5ca4d1bdb3a43ffd6b7a8d6f5fef4 - optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_se_driver.h +66c6c3e45cb8b148263fb036fde8a9d9d525abcd - optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_driver_contexts_composites.h +34712c06411d1a00ae58d2857f73d33892be0ef7 - optee/optee_os/lib/libmbedtls/include/mbedtls_config_uta.h +a44f5dc58a410538389a74b4cd2fc016b826f839 - optee/optee_os/lib/libmbedtls/include/mbedtls_config_kernel.h +61a92d97bc038e1636f35968f5a75f708383e065 - optee/optee_os/lib/libmbedtls/include/aes_alt.h +b68da531ca86368d8d211961616d067dca104cf2 - optee/optee_os/lib/libmbedtls/core/aes_cbc.c +1e3080bd5db0189b057a3f4fa1d45dae9ce59c72 - optee/optee_os/lib/libmbedtls/core/des_ecb.c +53cec4289bac3bbe8e4fc0ebac55b3071878d7db - optee/optee_os/lib/libmbedtls/core/hash.c +89b5b1b09c6141ce6cae83b42b24106dbf5d19d7 - optee/optee_os/lib/libmbedtls/core/sm2-dsa.c +2475b97d485b317cc088b6d1b3842d0bb9e4bd07 - optee/optee_os/lib/libmbedtls/core/aes.c +7cf5fb5fdbffcf6f9ad1ffefde20cb30eb66d58f - optee/optee_os/lib/libmbedtls/core/sm2-kep.c +a86c6c8bf63ea21ef2492f49cbc071f2f23a1d35 - optee/optee_os/lib/libmbedtls/core/mbed_helpers.c +3eb60b38bd9b87944a242c659ad68d8aaa8e220f - optee/optee_os/lib/libmbedtls/core/aes_ctr.c +3a1838593a7cbf67a1966456b9e4e441e14368ea - optee/optee_os/lib/libmbedtls/core/aes_ecb.c +7d7d3c3b185a01f15e64f2b4815b1f604ed06cb7 - optee/optee_os/lib/libmbedtls/core/mbed_helpers.h +4be86702d2f54b1d3c9fa62c47c1c16e8f9a5210 - optee/optee_os/lib/libmbedtls/core/sm2-pke.h +9eac1bef00d42cb5d29355da4ff216ab65029708 - optee/optee_os/lib/libmbedtls/core/des3_ecb.c +03091ed4d6dc54646fb16556db614135ab3b3128 - optee/optee_os/lib/libmbedtls/core/bignum.c +7c72db258e4db9095f0efed76d97590d49db1025 - optee/optee_os/lib/libmbedtls/core/ecc.c +12ba008130153663cb6542e80dcdb00d3a09d35c - optee/optee_os/lib/libmbedtls/core/hmac.c +bc4a14352a35d7f28ca65fda6e4625eaad768ef2 - optee/optee_os/lib/libmbedtls/core/sm2-pke.c +95257f1b9669bd55e715296a5db0520dfef94dfa - optee/optee_os/lib/libmbedtls/core/des3_cbc.c +e5f2f25d4125ec02f8b75e88014c122601fee192 - optee/optee_os/lib/libmbedtls/core/rsa.c +44c09d4b791e9fc7eb12c3090186b990a05f4484 - optee/optee_os/lib/libmbedtls/core/cmac.c +27d0d017d652207089357343fefde8822d574a56 - optee/optee_os/lib/libmbedtls/core/tomcrypt.c +4a3549fe50b6596fa95703bdad942578f79ff095 - optee/optee_os/lib/libmbedtls/core/des_cbc.c +78d30d0ba985e6d4114a2163f83194e58c30ad9b - optee/optee_os/lib/libmbedtls/core/dh.c +98b5b0189cbb8c50b0e303790d23dbf9681647cc - optee/optee_os/lib/libmbedtls/core/sm2-dsa.h +61ba39ae5f3db7e446666d29227a87474f4a6117 - optee/optee_os/lib/libutee/tee_socket_pta.c +6a2bd30d6d4442e50515c09a081afd22562e62a8 - optee/optee_os/lib/libutee/base64.h +8e021ba886ee4c9113f7e5f943eff836e70d9c62 - optee/optee_os/lib/libutee/tee_api_arith_mpi.c +077681c818e3003b52065a80dbacbd498dff6b29 - optee/optee_os/lib/libutee/tee_api_private.h +8fa85961841aca5f32b051d7c2137dce6048c90a - optee/optee_os/lib/libutee/trace_ext.c +756eb32d34c8adc8518381acb1da0e71abfc07c9 - optee/optee_os/lib/libutee/assert.c +2f5ffed76f45e88e6a21f21030600fdf1485141c - optee/optee_os/lib/libutee/tee_api.c +dc820097b9daaecdbebb44d2745b59ab6c868b3c - optee/optee_os/lib/libutee/user_ta_entry_compat.c +de26a71b90cb412c9efc752727836f54fb1d95b9 - optee/optee_os/lib/libutee/tee_api_objects.c +2a8949363bf9be408cbddf09c072982132988ffc - optee/optee_os/lib/libutee/abort.c +505da116e55bfaee3c94a6db710ef70a860f9bf1 - optee/optee_os/lib/libutee/tcb.c +b4d75c22cea319de57b7d095ce76316fa38d1506 - optee/optee_os/lib/libutee/base64.c +9389ec3691da465689f9ef3c7e4a843bdad07389 - optee/optee_os/lib/libutee/tee_tcpudp_socket.c +0fb276adf148a0417f0f9fd329ccf1c340b3c582 - optee/optee_os/lib/libutee/tee_api_property.c +45c1ba4438be0ecfb4d4bca51534640836b8c995 - optee/optee_os/lib/libutee/tee_api_panic.c +bc9153018927868009fb5a5e6df2a409ecb13f4c - optee/optee_os/lib/libutee/tee_system_pta.c +b1398a9a37ee47f2718169316310a4a16c61166c - optee/optee_os/lib/libutee/tee_uuid_from_str.c +cd3c2b81c2fa7237a975213bafcf7ac4e67ff177 - optee/optee_os/lib/libutee/tee_socket_private.h +681df366c32f67cc5a24341f7b96e459d68b2b2e - optee/optee_os/lib/libutee/tee_api_operations.c +b9209dd75181e9d8ea1f62de22f752dc82097d5d - optee/optee_os/lib/libutee/user_ta_entry.c +07b4cbc455efb89b2f41b5d8b5b7d58008497abf - optee/optee_os/lib/libutee/arch/riscv/utee_syscalls_rv.S +b1ff8027d8f72d6043aefff12c169937335d77c2 - optee/optee_os/lib/libutee/arch/arm/utee_syscalls_a32.S +137080dcbc697e48f567709fe3fda2528f5d40fa - optee/optee_os/lib/libutee/arch/arm/utee_syscalls_a64.S +16e0dc83cf08600fd769832ff1d21611782da066 - optee/optee_os/lib/libutee/arch/arm/gprof/gprof_pta.c +2e2b03efa22c915b6ab0a59c54793e918ae83560 - optee/optee_os/lib/libutee/arch/arm/gprof/gprof_pta.h +a2170433362124e5401cea1cf6f4dafaca653856 - optee/optee_os/lib/libutee/arch/arm/gprof/gmon.h +1a3e524ad810227480d10b0d8426c780c85328bb - optee/optee_os/lib/libutee/arch/arm/gprof/gprof.c +be6fc3000484b65889ef0ddf1e7a926e364575a8 - optee/optee_os/lib/libutee/arch/arm/gprof/gmon_out.h +5e23b121b492913159ac492c975bc689fe4fe9d5 - optee/optee_os/lib/libutee/include/utee_syscalls.h +d6461788cfe9c7fa1812938fccf00428981ca21f - optee/optee_os/lib/libutee/include/pta_rtc.h +e3514bd732b3d0be323aae77cdfcbfb736b42fdb - optee/optee_os/lib/libutee/include/tee_internal_api.h +aa09af74960113ccd4fb8827d07e4b9140aacf8f - optee/optee_os/lib/libutee/include/arm_user_sysreg.h +d6494aea8b2d08af66c5b03901a962d4c23afa5c - optee/optee_os/lib/libutee/include/pta_secstor_ta_mgmt.h +083e406c1b8993f6c0226bf312fcd140b1bc2cc4 - optee/optee_os/lib/libutee/include/pta_imx_digprog.h +989a3f3ba297d8913c040b838c9cab1a5103308f - optee/optee_os/lib/libutee/include/pta_attestation.h +1f3e231e2e68ce744bb262619fadfdb1e8f137a9 - optee/optee_os/lib/libutee/include/tee_arith_internal.h +faeceac8862bbe02c984a8839b1e1cae06319dba - optee/optee_os/lib/libutee/include/pta_rng.h +c4e212610ccdc55f55421917a843a5b8ddb567c2 - optee/optee_os/lib/libutee/include/pta_imx_ocotp.h +c603b51b2bfba8baa7cb2c4dfbaaa421d9461207 - optee/optee_os/lib/libutee/include/tee_api_defines_extensions.h +8981169f89ce2d195a17112b676bb8552d21ad4c - optee/optee_os/lib/libutee/include/tee_api.h +62fdcf80906b4877ba0a4d22e69a0c75e98e8b9b - optee/optee_os/lib/libutee/include/pta_imx_manufacturing_protection.h +ce4bc2d3ed7f6c3ecb68a1f98a7f368f7369a286 - optee/optee_os/lib/libutee/include/utee_syscalls_asm.S +80eb8b37eb87886d40dc390c74bfae90f83ea208 - optee/optee_os/lib/libutee/include/pta_socket.h +aff5768a908441b37ad3a28350e0b0f6bf0007b0 - optee/optee_os/lib/libutee/include/tee_api_defines.h +9155ede1378206e1762eb2696d1589cb2b620ee6 - optee/optee_os/lib/libutee/include/utee_types.h +591d4ed947e32e0c72a95a7a2514221f1cf9490d - optee/optee_os/lib/libutee/include/pta_gprof.h +f6b88edde49c7f79eebc0c3f861b6f19ff685fd1 - optee/optee_os/lib/libutee/include/tee_udpsocket.h +987521c6dd87009f2cad24c545048d20baad76e5 - optee/optee_os/lib/libutee/include/pta_jetson_user_key.h +398b00b2fdfc1d0dd1987e95722a21a6de7413bc - optee/optee_os/lib/libutee/include/pta_device.h +0311b7bfd98a444eeef7c7c89d4e942a84ea6787 - optee/optee_os/lib/libutee/include/tee_ta_api.h +9c2c1f4769d19646dfe1493dfaa1007b8c538af0 - optee/optee_os/lib/libutee/include/rng_pta_client.h +4c169dffab3432c000d70fe610898278c4568483 - optee/optee_os/lib/libutee/include/user_ta_header.h +f5d83909e5071e2affc98fc56ac4b941e00ef03a - optee/optee_os/lib/libutee/include/pta_apdu.h +8572ff4140b947a4e4a4b5752d8265fe1ea5b348 - optee/optee_os/lib/libutee/include/pta_scmi_client.h +aa7d01574e3506e0ee2f42cdb251145908b75381 - optee/optee_os/lib/libutee/include/elf.h +ebea83d32048f9808bd31f5e2dabc5c0314057bb - optee/optee_os/lib/libutee/include/__tee_ipsocket.h +bfd21882753009a9bff306c49ea3d6ba0a27715d - optee/optee_os/lib/libutee/include/pta_stm32mp_bsec.h +47e7cf8af6ad09392aa45b94e88e4cc07e54520e - optee/optee_os/lib/libutee/include/tee_syscall_numbers.h +5ca4833e2188ae7c12e8b39f0448c7f3627571c7 - optee/optee_os/lib/libutee/include/__tee_tcpsocket_defines.h +ef91d0380fcc7f9a3bb92041f649b2756d3f1282 - optee/optee_os/lib/libutee/include/elf_common.h +34686e9ef3d016d68cb94ca12b860c89349b5eca - optee/optee_os/lib/libutee/include/__tee_tcpsocket_defines_extensions.h +f5e7435c16a3b97874cafc61dd32e3e448ea9b79 - optee/optee_os/lib/libutee/include/pta_jetson_ftpm_helper.h +f06afef5b0c60b95525e92a721eb9bcfcf6e6d3a - optee/optee_os/lib/libutee/include/remoteproc_pta.h +793d80272b98715200cd83435c35de534049b96e - optee/optee_os/lib/libutee/include/__tee_isocket_defines.h +5d2f8542dbd85a819207cf9201d5c104d1f45799 - optee/optee_os/lib/libutee/include/arm64_user_sysreg.h +4bfb3666782f62ba34d4645501617d1f4b424a98 - optee/optee_os/lib/libutee/include/riscv_user_sysreg.h +5a4c5c4386df019b937e53bdfca5e05bf5f10921 - optee/optee_os/lib/libutee/include/pta_invoke_tests.h +24acf5f9664ccd81af1147a5e2f875e5a303d97a - optee/optee_os/lib/libutee/include/pta_system.h +8ddaf3ec29e785a63a8b8ba266c13abdce68c125 - optee/optee_os/lib/libutee/include/elf32.h +7812d9a6cf27c9c8cb718a2a8824323576ccaf38 - optee/optee_os/lib/libutee/include/tee_api_compat.h +0f06e417dc0b4434790db823616a67697a157404 - optee/optee_os/lib/libutee/include/__tee_udpsocket_defines.h +dfe89d4404a213f5751887db149a30135cd07f9a - optee/optee_os/lib/libutee/include/pta_scp03.h +f5bd9efbf15469a7a654c4063b66c9cfa7ce476f - optee/optee_os/lib/libutee/include/pta_stats.h +f4adab9015698b3a5ad156216c44340a86567794 - optee/optee_os/lib/libutee/include/link.h +5e08d24c95ed9a2dbbcf69ef3896898ad97abc8a - optee/optee_os/lib/libutee/include/tee_internal_api_extensions.h +9a9e2018f6c94451408a11cb0c0be264353a3c7f - optee/optee_os/lib/libutee/include/pta_imx_dek_blob.h +ed871d9884b5e4c5c7801d8dfc5f77f30d79d4ec - optee/optee_os/lib/libutee/include/tee_tcpsocket.h +41b79406ff05bc4d3528fca688813e7f88e7d135 - optee/optee_os/lib/libutee/include/tee_isocket.h +1ee95d67db99aa4b7dab212672290e1dcf51e1e6 - optee/optee_os/lib/libutee/include/tee_api_types.h +16a82e5d6e02952d5d445df9b95c3d540e9aaa4b - optee/optee_os/lib/libutee/include/utee_defines.h +0914ffb8eea917ca32ddfd5e9d1e07b08242a132 - optee/optee_os/lib/libutee/include/elf64.h +fd26dac1d8ff0a59b77021c57b346cf0d9767c1f - optee/optee_os/lib/libutee/include/pta_widevine.h +d84b15deba3ac3edfa192902098d7b012e19893c - optee/optee_os/lib/libutee/include/k3/otp_keywriting_ta.h +69389cffd2f2392d520b42fb8a877d88184eb7ce - optee/optee_os/lib/libutils/isoc/fputc.c +3c0076665f570bb3894f7975c7af19546b24b949 - optee/optee_os/lib/libutils/isoc/stack_check.c +adf5b4c7851eccb3ab23eaa51e2c67aaea646dba - optee/optee_os/lib/libutils/isoc/ispunct.c +44884a714f6031d8c9899eda446ab6bd902d63bc - optee/optee_os/lib/libutils/isoc/bget.doc +3871de5c02c34257cb8c03aea71c406eca1389eb - optee/optee_os/lib/libutils/isoc/isupper.c +3072e334c9965c360ee485346541f37b1cade0ce - optee/optee_os/lib/libutils/isoc/strndup.c +9bef02b228d5d11a675a74e974644af7f91dc6ec - optee/optee_os/lib/libutils/isoc/iscntrl.c +b2a87efad81c7fc35f3f17a1507b650945a64089 - optee/optee_os/lib/libutils/isoc/fputs.c +486e4ec67949ba32eb52d521355b28c032ea31d4 - optee/optee_os/lib/libutils/isoc/fp.c +a426f426e3093d41ca84adcdf9eefd3d37354379 - optee/optee_os/lib/libutils/isoc/isspace.c +3849e364a583d8e2a6b06c73b88cbff340651414 - optee/optee_os/lib/libutils/isoc/isdigit.c +fbbd10cc345ddfe50e1ca5ec8a2e936b5cfe396a - optee/optee_os/lib/libutils/isoc/toupper.c +15d9b02b2f680e631dc3cb4acb612c5051534577 - optee/optee_os/lib/libutils/isoc/snprintf.c +e50bee77ddab437d58aec0c7d06ad8e70066d752 - optee/optee_os/lib/libutils/isoc/isgraph.c +f3a4dd8bf719bba595428ad39e580b4bdb83c0f2 - optee/optee_os/lib/libutils/isoc/isprint.c +05dba8367bdb83c45ecf37dc4146c37431fb7b40 - optee/optee_os/lib/libutils/isoc/bget_malloc.c +aae0aea5aeb4c700916f3a0cb796958a066f2033 - optee/optee_os/lib/libutils/isoc/islower.c +07859d16a6f156a7b7d53976c3ea35d8c181c050 - optee/optee_os/lib/libutils/isoc/strdup.c +bdba22e240af00ccb765dec28ab938c5e3619bd3 - optee/optee_os/lib/libutils/isoc/isalpha.c +465dccda5f6216b5156acdf8d97692de7a6bc618 - optee/optee_os/lib/libutils/isoc/tolower.c +66446d12deb5b2f6768b0037c5cd7f6bda49c01a - optee/optee_os/lib/libutils/isoc/fwrite.c +afbd6bbf47f8aceef9ce91f60a65246aa8579e52 - optee/optee_os/lib/libutils/isoc/write.c +29a7857f6999a06d58d700ca9bd712c157595adc - optee/optee_os/lib/libutils/isoc/isxdigit.c +fd0766e5127d24a75662d988de4c18f5686b3020 - optee/optee_os/lib/libutils/isoc/isalnum.c +08ed68e1c3fcaca243143f636c99d7b1c7c325bf - optee/optee_os/lib/libutils/isoc/sprintf.c +cc419cf9b3049ca5a067f8efc8b87fb21d16cc17 - optee/optee_os/lib/libutils/isoc/bget.h +d7303541082db306fa6b0447bd5aca62f4cb8169 - optee/optee_os/lib/libutils/isoc/bget.c +bd92a4e902b8f071cb08e11be594c2cc03b13e0b - optee/optee_os/lib/libutils/isoc/qsort.c +013f93c8f430036a391ce8954024b19664a7bfda - optee/optee_os/lib/libutils/isoc/arch/riscv/setjmp_rv.S +dbc715c45b8998c5276e4a7f3dfc71bd81a03947 - optee/optee_os/lib/libutils/isoc/arch/arm/setjmp_a64.S +24bfedc4ffd1c78df045ab1c725bd811b0531bee - optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_ldivmod_a32.S +30211cfa366caf873a7801a7ac8e5828d0518b42 - optee/optee_os/lib/libutils/isoc/arch/arm/setjmp_a32.S +99b85b897d6a461c3fa3c1f9bd54fb771c45ae5c - optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_softfloat.c +6a325e1881f32b8ca7c74367132e75f9318aff08 - optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_ldivmod.c +0519b9fc5474ccc5a5e50b508e05aa1d81b33c3b - optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_divmod.c +4d6df8e998067ae07c67580b5f7f261238c7cdb6 - optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_divmod_a32.S +0f25fedd6c6f397a39b1254cce305242fe230e0b - optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_shift.c +eea63204ff2fd371e116939e14a504bd9d17de4c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/README.html +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 +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 +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 +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 +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 +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 +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 +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 +2e201e03147cc253f93e31812b6cc1fa19c54acc - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftLeft128.c +1a1af8af29ddb0214656df304b31583e97bbe044 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_le_quiet.c +2a8c469188ac72f1647a4e23121d6baab2f46881 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_i64_r_minMag.c +b390f4671e459aa98a5e6eba67989a524df502c6 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackToF128.c +ed1a42257f7a11ddfb2896bb3db8fa6b6b799910 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_add.c +cc9936a7e89313dabf987a759166c6b627c5697f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_f128M.c +5aa2d29c4f2ecefdd83adab4927c2dba794a0a43 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_f128.c +04822aab5f0c58ebdfca756670ddbddf4524258b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_add.c +a44f15f379846d39821c025d6b7afe2f94cb4411 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_sqrt.c +c62a95ceba02a10b8f43ebf0b1621e6a814f07ad - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToF128.c +321d4491ee122d9ff20f50a5fd4708eec3a9bbc4 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addCarryM.c +67a5f98ae9f74d18b7c83f145618185127a93260 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJam128Extra.c +c0e3f7568f5ce015eb6724ca13dcdebf3846138f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_i32.c +23659a34fd66f6a163767159d9191aece60e9833 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_f64.c +b8189771723e965a9e94712bfa8135b04f844af1 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackMToI64.c +3f17bb81a05b30c928c6f3dcbd9d6c33f6dd808b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_eq.c +039cc691a2609fb90724786e7ed7be17b006803f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_i32_r_minMag.c +74978af5148ccce4ca51465a934e52d8ff03fb9a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_f32.c +ddf3732777273f55557aa33c85aaea98c3017a0d - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToExtF80.c +c3d4d8448c3e622688342aa49d892b84716125a5 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_eq128.c +bf60482d7a8c7573451dd9d358a4f59882b4ecd8 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_sub.c +e0f5d8c33a9db5f50d0fc16b09808a48a8b052b5 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul128MTo256M.c +62e6926f729011d5c3aa3af610ce0b916b919eb4 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_rem.c +0fb28e0101aaab0bd33ae51a05e4b522cea887b3 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_ui64.c +25066beb2f05f436d718c8073ec11ad550f53ef1 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mulAddF64.c +1fb366479cad4034726000f4f22cdbcdcb95a4c0 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_roundToInt.c +c87f6f4eb78569c01e3fd0c6caed99232b37a378 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_extF80.c +f81c603cb90e956ee8dde34149ac6bd684d4c70a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_lt_quiet.c +2fc25c51a836eb30d5a0215659d5fd8b4dbda2e8 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_lt.c +1d4036336aa49d6961f510e234caf45cba50d995 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_ui64_r_minMag.c +2af1a8917871bcc8c0560e709aa28418d004c97e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_i64_r_minMag.c +d64953149b1077f8e6d0848e2fd5506136e6f2d6 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_add.c +71d3ef74fe02e7fe6891e4db41241c5b2e615643 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_extF80M.c +4189613b8730aaff62a01f6254b071b9fd3c8cb6 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_f32.c +a091e47127bd1311d2cd2b78353ee99ddfc54100 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftLeftM.c +fb72828cc90ce8ac0bb436552fbd39bee0f11d35 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_f128M.c +7fbcbd3346af638125a977564bb94e3a4112db4c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subMagsF64.c +73e3351f07e2c7c7d591555895c25042a56c82fd - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_le.c +28ed562132fa508b794485f84e37ffebf0f45c03 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_f128M.c +e5f8702f5072f781a5b4ef72c7ec4db154d75965 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_invalidF128M.c +d11f89d0268036c5e2190b2001b08b46df5a1496 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_mul.c +3e0d54c15411c2c997b29fa7132f305ba0986d0c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_ui64_r_minMag.c +a04e210c7ba96d0c982f31acdc218a4a63b5326d - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_div.c +cc614514257c6b0a721ebfbf2f2eb22e764e75e4 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightM.c +39e684d513bd8e1bc18146fe5b6b41ca6abfb889 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_ui64_r_minMag.c +993bf55183ee975278a5e4c34e658f6f7bd3702e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_sub.c +5f3d886dc9c8533c8093c13f3b4242c66ba17e5a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_ui32_r_minMag.c +4e4a329eebd8c7675a57c1b06f75ff4ac326b2e1 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_tryPropagateNaNExtF80M.c +f02ad3fb3c3e82d60532e677d475a578ecdf6a1d - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addExtF80M.c +d2e10d43888a0af127c80ebb29261c8c424b217e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_f128M.c +7749e3a634b0f7cb154a734be194e52d612310c5 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_sub128.c +3314b591c37fbe10125dd1047b564db3968c7246 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_isSignalingNaN.c +f7e21606f0f60046e7ed31a99520969bf3cff7c5 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subM.c +61342ccf516ad5891a6f2eb1980d37329501ea4e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_le.c +2355160c0a3526eb32abd1d54fb01083a1fbe18a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_countLeadingZeros32.c +5d919ea71a15f028ff7b85cd73d9543cbe322b06 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackMToF128M.c +f815fd87ebd1c160aa9ddb1c232c1de58da01072 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_ui32.c +876085f70200480ee30305fa6463d7c6504e7e77 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftLeftM.c +dd1f8b3669ce1b87360bd05963ce288acfd9f386 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mulAddF128.c +29d181916bd52d0effa525808e4e4564f56b5ed3 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subMagsF128.c +9b35552cd723623625c63511e14b0e559d678f4f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normExtF80SigM.c +df4f91f5c1ef40d1eaec328ca6b879bf095951a7 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_eq_signaling.c +9611fba0e534169527d66900db62b107e96b8e2a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_roundToInt.c +27897b3a3e2b0f5cfd67ca737c35af7cc360c3cf - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_ui64.c +2211257786a567ae6daea47fa4ddd31c0339d328 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_add256M.c +89e1c8f8d93bed98125ee2c0e27f4ad4b87f5f9e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_ui64.c +0d9fe463bfee7b28f85650d68588f7fb47358282 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_lt_quiet.c +b37dddeca4634f2e81fadc1fe8c9ec9f9643c56c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_ui32.c +e5c280ffda9fadc7cf51f4e49ba880138473c188 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_sqrt.c +b6e5c30069ee1bfdeb29301eb988d9b5ef1e6fd7 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_remStepMBy32.c +672608ed7c1150531f5d4e2b3aa274de76f24f44 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_extF80.c +04b228218122ee8f024959ef831393289d417e7e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_extF80M.c +97688d5996165455b0ead5c1973e36b6d096c21f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackMToUI64.c +71874d6de8e801c14005d5b1f68170c3c6c6baba - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_lt_quiet.c +9fbd0b33c76b78481c512902dc4d9a0d67f4f210 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_i32_r_minMag.c +3ad627bba48b5bb63c11c5e86c0081d283f4a13c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackToExtF80.c +e0d12d5167bae0c40dc2ee4e8eb79ccb7d7f8709 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToF32.c +082138b2e89a050296984be3e3d195746735edfa - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToF64.c +db04e48a5c823e4f060cc56187b01cbb89ee1afc - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_mul.c +03ee79d8d396bc6778c8bd477647f5e7b2035214 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_f32.c +6de7ad17814ec3532d2cc20927580d8cb52c44de - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mulAddF128M.c +a6ea63bd09a37c67ab0db5c7378603bc343f7c4a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_lt_quiet.c +a4bba6333e9a92cef62ff68ef528240c29173398 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_extF80.c +cddf72a19a53f1cc1e2077dbf7e9269f0ba5cf16 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_rem.c +d7dec92efc7a7503386861fc8a67b770c78d50fd - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_lt_quiet.c +bbb2e442ce63abe6d694eab84ce821e2ec210522 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_lt128.c +b48f6bd306c3509038d6c4d283bc189d517d3b4f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_f128.c +eed7248a2360c629c3dc0b39a7b019c718c1f8f8 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_roundToInt.c +d594421c568958d475a5939b2bc14c195493768f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_le_quiet.c +c7030401c4589ebe4ca9df47cdf4473be706e9c8 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_div.c +016a9e65ca19c7f5d3561d54a3fcbddfb6a310ee - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftLeft64To96M.c +9fb6f1767a51f28d28e6af39ffaedc9883363298 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_i32_r_minMag.c +2cbd145a4e3465e12bfd47dc4a52fd75c4e0b427 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_i32_r_minMag.c +b28464c7ae4ca7eb7416555259cf21f36e3906ba - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul64To128M.c +c04c45b92e29225e1d2e3decc3dfc108ae63b093 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_ui32.c +ef40011bbd21ac40df712f0f16dc844ee06aa453 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_add.c +f394231a827adbe842d2249d968ff138ad99c20b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normSubnormalF32Sig.c +9783f22f581b7feca4f86660b538b214dd32b129 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam256M.c +4042678da076368eb21bb4ded888e17dd2109b55 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_f64.c +f5755b53bfa3d4ada8ed3be7b2e264ca31c83e9b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_sqrt.c +0020d431a9fe3314ba42c1dafe946fbd2ef7e606 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_f32.c +f1663c2acfcb26909b23e18b18c43a4aecee1908 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_extF80.c +bc52a98da5add09bb146c15a8cc1e524e1e36989 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_f128.c +73f1f3cdf7a70d4d02ddd5d73f8198482d373296 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_f128M.c +47e7b19a3c969e8c6acf899992a2b3dc02ee894f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRight128.c +6772aca13808c91d5fbc62b23e65a9aba99df8ef - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addF128M.c +84791d4f50e8187197aeca69dbef6a333d167fc1 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_f32.c +5e4ff4edf1d3a006c61ca3098f1919088d42dd66 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_isSignalingNaN.c +289aeaf52ea847d12eab9ab91e1b080ae5cc4774 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_mulAdd.c +4dbe7ada2eae098c62ec673be2cb2452390c0a78 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_f128.c +467dcd8f83fcddef3d3402ebcc2c08822c68621e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_compare128M.c +68c9d3e3654c5107bd58185d3632d6e8c4b04687 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_approxRecip32_1.c +6a29d35180197bb865f52b54695f07430e3e06db - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_mul.c +c32eb171afa353fe6d96c9fcc1b6bc9116ba3237 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_sub.c +1d30d31c5765c77e617b9969b778019b60c4b1bd - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_i64.c +3166b1b25c791f37186ac5ace33c6369720cd72d - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_f32.c +20b550200dc22a4995a52f7bb20f8177c851d08b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_le_quiet.c +8c11bd928370bc41568ae3c44ed648224268134b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackMToExtF80M.c +622a359dab67eedd5448775dc3204d4f48039034 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_i64.c +757e08593f768490c92840e212583a4ec63dbbf9 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackToF64.c +e6b71c319835a3d037818d3ca0d1468b2dd3c325 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_ui64.c +bbe0db256dda63763f1a09d9af66cfbfa51c69f6 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_le.c +3e4e1cde87c7d37013c4665489e22a5e653b9e75 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_i32_r_minMag.c +0db18e1a005858944af9123bb29580ebac102bac - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_i64_r_minMag.c +0f29c869a8f46f705f24531b2826deabe579032f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_extF80M.c +809dcde66eb6eff4e7af6a71ab240cdae5c11097 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam128Extra.c +3155ae7f402b23659c4ff5e89bd77c5599ee23e0 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToI32.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 +6eb4a2a36946f25f5528e564a0391b709127224b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_eq.c +e14e58254cc0fe0ce4710d073c7a4c41961df960 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_mulAdd.c +644f4fb69b6d67725a586cb47755d4472694dc54 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_sqrt.c +188a513a8b2102d97b435bddcaa70a13422fd36b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_ui32_r_minMag.c +64b0e4b0e7bb5d8073e937068421026aa213bb57 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_isSignalingNaN.c +fb78669ac8ebe25845bdac20fd3007ac6ed6e254 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_sqrt.c +49a30ac92f2823400a43a7b0789def54eac5d67e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_mul.c +39eaa261c0332f55f617941b8bf51f30dfa288bb - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_f128.c +ea9e18329087b88e680a9b0e1dc3f73d78ffc97b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normSubnormalF128SigM.c +20cc97dd02d91a85b8d58ab1373f550058a5a4ce - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_f32.c +f3c0c6bf5032a3f329e5637aa49336a98dc365f1 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_rem.c +d5160582645bf346bf920e38f896596319da591b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_eq.c +54fed28ecc0bb163f71b7d5f47c960063b16f0f0 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_i32.c +c9372c8b60f9e67962d30179a0595294d74953a2 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_mulAdd.c +60cccf04237a9a059b26075b3bc4742662905190 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_f64.c +6504b9481457cfd6e39a69e7066fe09ffbbdb258 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_div.c +acd11d468d7a20b0e4381a8b7168e186b7d49d4b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_le.c +60a64ea74aeaa87b706af4f0c880e551d68ee8f6 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addMagsF32.c +6b7125daba8bb60ca3e2db6c38bf5cbc5df906ea - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToUI32.c +3fef81240caee61991a4a7c3ffa8e6d6e2e8066b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_sub.c +5d1495da9f0d75aa3f5fa75b43c5edbc95dc1ae9 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_f64.c +7bed7a39e5684ce23986346806ce19c0a2d198a4 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_i32.c +b4f539877d9b40f21099ed92d2e18a9f57f28566 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_eq.c +623ab3fb8b679ac1b86f7c366eb192d128358f16 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam128.c +a473fd92baf36ab51a725b665f964a7a082f4eb3 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_le_quiet.c +4cc27ddd980713ad95fd12a90c077df01999893f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_i32.c +5158c6ca5efcc7ee5067415f6df5988c4b3645ed - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam32.c +25ad3859febf3093e91de0392cb0d7c98d3e9dcd - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_ui32.c +a8cd508101d5d02ae58933c2b91b0638fe9ce308 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_extF80M.c +7a1740bacdd6fbf37b3e9ad6b304b772722041c2 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_extF80M.c +a5d1d8aa31fb5646e96d1f889729bd9eb7867e9a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_countLeadingZeros64.c +ea2befd81aa697654bc1baf2a7da10508ae8b9ce - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_roundToInt.c +6ee82c2c62f3442cc1c0b2e9ef6b0b85da32cf3c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_lt.c +ff0afa5079cd15008d3d3386ac73d3b62a0c4d79 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_negXM.c +73622cf9aea053c968f1922c8a206030cab025a9 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_f128.c +6c279773b785568a5567bfe33f5a6082265b9efb - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_eq.c +3c7d728ab8fa5d0e345c67d53f5335d672d8fd5a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_i32.c +fd6492962962b16aeabef92ff9542da4aae05f26 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToUI64.c +4cc44bf1f32b533112fceaf74f2116052c251f45 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_lt.c +28af646437af4de6033b2176542a5d805636323e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam64.c +6ba3f71a3a306c79f58d469163b33f810aa8faa8 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftNormSigF128M.c +ebd71c72d17dd55dc010988fcc223aeb9679ee6f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_mul.c +5bddd155904f96e1af61acc11b87973856d66810 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_sub.c +3088c598cdb456e47e280fd0bc369fb0d5e6d2f9 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_i64_r_minMag.c +de37f2fef538ee89236273ac956585b2d58a15ab - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul64ByShifted32To128.c +9cd0d76126fdd8add379caa20c766668256efb6e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_eq_signaling.c +a91c926882ae26c3a59dc8885fabc6e86ce9465e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJamM.c +6e91b9e38753aa8aa2094b6b40b596796bd11b3d - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subMagsExtF80.c +62cbafb0d4719707254e3021383d31fd007b3971 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_invalidExtF80M.c +e550bcef98e4bc5091eac085dd5972d58c2bab09 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul128To256M.c +61fb9da8313a688f608a43d8aa36ac9861c74c75 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addMagsF128.c +920cf94c441178943a1442a168fb4649cfe755d2 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normSubnormalF128Sig.c +019af317356453e7119ac20be4c98c0a1c83f8af - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToI64.c +d0375fd187a2ec8138e6a29c04afb951176c31bb - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam64Extra.c +a56defbdfcb63c086c83b3754d2848c2d67b561c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJamM.c +57500b9bade8439c0c3f06cbb999f6ba13952ad9 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_f64.c +6f034e453e9efaa8477ac48fed5ff48d6320f99a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_isNaNF128M.c +260bca4ccf486c140c36950f988253e30be3f9e2 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_ui64_r_minMag.c +5547439bc882d6cb17257578b63ed5dea9e85ad3 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_i32_r_minMag.c +97a45958e5ea33d1fed598272e527b7f72a9d8ee - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightM.c +136777686e7e2c7b3decdc75d9cb9e0f802b4dec - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_ui32_r_minMag.c +7edbff34e15aeda6b14e5e01fa34a2e4ec230d88 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_countLeadingZeros8.c +b971ed0265436f05a8f8f5eb8653de23e49747f1 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_f32.c +5adc627cc2a4ed39719943fac8c29517f3d39bbe - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_f32.c +440066ddfc6cb2460e07a86d2552d5aa6978ca47 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_compare96M.c +7c39994169fccf5700f2fe944d8b94d912a07723 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_roundToInt.c +5bd19e6fff94dd11976e8f78f6ef8b9af01d33d2 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_div.c +d724729fe9aff2647d82d44cf7c98ef024550f4c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_ui32_r_minMag.c +7233f7a2c75705b0b4173168df45777f969cae96 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_eq_signaling.c +5cd984d2fe4bfa79945c464d200d7b17d205b475 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackMToExtF80M.c +0ac05f3c78dd89e1084687237ede90311fc758d6 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normSubnormalF64Sig.c +1a5d352e9bacfa36ecd8ef231155053713acece0 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_mul.c +32ee0bb66ee86e9f4d4f49c23487905e3e09715e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_rem.c +60f8ae03f26507e95f988d859c2a779d957c4efa - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_extF80.c +9cdcb1720d52c0b09ac2ab14aab047bfe940304a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_ui32_r_minMag.c +f79c163815f902511ac25f8f5a391149043a846b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_f64.c +02501e2df1729d1c331ab6288158859f5302a791 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_ui32.c +bb4b86c5d78b77f1babf89d73c262ab3e47b6832 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_f128.c +e9570bb5907e357489fdf310d629201fb63fe691 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_sub.c +add3de1ad7693fb4a2a5453483938b93b287e275 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackToF32.c +dd00b7472e373b2a72b05389fd8c595c9e688831 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_extF80.c +80f53f88a6f924eaf40e9f79955bdfff87f72d14 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_i64.c +0fa1c7015b7c39efbe07d739a03f2a83b85745b8 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_compareNonnormExtF80M.c +33dedf42e83eb53f8ce20395143a01a73b412457 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_sub256M.c +70a0a4dddf509479def6ff905d493e6a50c1bacd - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_sqrt.c +bf81966f25644611be0129d9ef8aaf0f5c6da21e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_ui32.c +35820af43505df9a372d4e74e3f0550a3af9a249 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_eq.c +7aeebb299243e2d857eef25300233d709662a1be - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addMagsF64.c +c42aa8ca5eb2a847874b705199b3033ae8fc00ee - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_le.c +495735b890e1bebb53e4e2cef50ffda57a242662 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJam64.c +83db5e18b844bed794c0f1690aa2aa28ed93e4dd - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_ui64.c +c8fa83b76113c38831b0a21b4b6359fe6976b133 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_lt_quiet.c +3d89aeb6e7880b1152564ff98fac17e80a4beab4 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_mulAdd.c +23a84b7f28ce5a2345b3d037ccc8f2707163d262 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_lt.c +06c8f4bcf358da5b2930df117ecc0f2324a59b3f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightExtendM.c +359da64e36a5f411cf383e3fd0f83a248a1dd066 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_f64.c +8fd3330c1a032cc7c4a7ad995996169ac7f0805d - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_ui64_r_minMag.c +58782db3382eb567580f7105c6c8d88dd1a6fc67 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_i64.c +f06279e2d0e5d4a308a35ce0eae73d18ff2b0ad1 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_ui64_r_minMag.c +e4be027468e7ee598e8835dfe5c58692978be102 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addComplCarryM.c +6ab2cbbff35bbae58c14a90419c2dd153b667063 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addM.c +9c753ee79b20998c7b9c420d50cd9ca84b18a3f4 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_le.c +2d988cd65efb881d8f5103b71c9f6b121121ef6d - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_i32.c +c5fd85ea4a5cf0a00edfc6cb66cf20b3e7100062 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_eq_signaling.c +c50d86d027171a9f2481e8f7c1cb4308f1cf1d3a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_i64.c +1aff280581ce3e0a033ebdb2257a5095804f4a18 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_isSignalingNaN.c +c425d403c3b3dfaed940888bca06384b967e8e5e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_i64_r_minMag.c +12d0070692fad1189770f55c41aab025bee462a7 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_f128M.c +d688f7a888e0e7b33a166af94044edc80100754e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_le128.c +1843081e5eaa9f77ccd80c3cba04e650ceee756b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul128By32.c +63a8a8dcae334e46b7fbc7ebc687e8d6c011fb7a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addMagsExtF80.c +5728e535d2903cca9e9558dddf7a571e606a385e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_div.c +2679177fa989374186316764ed9a90c42e38edd7 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_le_quiet.c +e33d236ac36ab3726429718fa699498e908afb21 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_i64_r_minMag.c +0529a095355f150e35063942c7aec7276033842d - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_add.c +d586657c54173f413fa72807b84027e1beeb6234 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_approxRecipSqrt32_1.c +327934b641bc5a6a891fd19aab7b9f0363952a0c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_extF80M.c +641b01960569783533397d0ed1cdbb00695a3578 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subMagsF32.c +1e172d64c3dbd60e0e9ffcbcc7a0225702f04848 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackMToF128M.c +14119b8fcb0828e0621f0d1c0b3130721abcf3a8 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mulAddF32.c +fc451ef01165565a1d593b0e2572eb8e37aa72a3 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/softfloat_state.c +0f3d7b35ae34828864a226e8b123484e88b8cd13 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_extF80.c +9a156cc904d7427a794de20f093bdff4a44cc12f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_sub1XM.c +3c754eb220ded3a7e9c82cb01c7ed8adc2144452 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_lt.c +4802d692dda23c6bdb15e682f8895eaa2e02a824 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_lt.c +e6ad1063b924e4b96a1801d49b960b3d8534342e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_rem.c +badda43bf474995d00db78fe6ae6b40268e9f90f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_f64.c +c841c237414b6697fc42f3a261082257cec7dbec - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_add.c +9e7235e0ad3872a7b6f005a0203e63508f11eaab - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_eq_signaling.c +d5a7b42551a9289e11b502dcd611101098d47502 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_f128M.c +625d048386528b1c63a19813ace77ab7484e1876 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_tryPropagateNaNF128M.c +0ef83486a7270a31dab5ced482dfaec14b9a5b4f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_ui64.c +dda54df5d890a969ba663a54ceae83c6492d7866 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_le_quiet.c +faf4056d360eb6faeccac416f54caa2a1a8bae9a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_i64.c +8a4a364a4b4f144bc47fb5e28144cfe82dd3b585 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normSubnormalExtF80Sig.c +345b454a7bf01265db26b15ff80f98692e81fc5f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_div.c +684615f62d1f460768c6b9cf951bbe7d82b7aa4e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_extF80M.c +d3cdaf7ed2016c9f9764a514ec05b2dd6f86fc85 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJam64Extra.c +fab91920cf859d0f22562a98eea05a843806e70e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_ui32_r_minMag.c +a05a89d48fe8216f0fa0babd342a60249c72cef2 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_eq_signaling.c +01cd4ad4fff8805cc5bf43533b1576d7e170925b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_rem.c +890504face9da670bb9338c6587d893fd632819b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJam128.c +7db7c6e3e7ed45f7c7ed16ea6935cc7fdba73da3 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul64To128.c +a8129c9fa34f996b39adef2e0620dd63b5ab655e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_roundToInt.c +784083a6783d1d5de48e4b5a95ccb43b8103bfff - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNF64UI.c +74a3e6c966c47167bebd7abdfb17797124ee9279 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNF32UI.c +f58e104619733d72884d1de3ce89eedacb671595 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/specialize.h +d8fc85a2746e3c31e70de675027af01735ba105f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_extF80UIToCommonNaN.c +52bc24f91ee7846596274fb2b29654539fd3fa00 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToF128M.c +2c9f36c79b5d80fe13893b8c9b9f9c94273c1c95 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_f32UIToCommonNaN.c +52fee0fd73c94d2e2f5a21a55f082e1963b1569b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_f128MToCommonNaN.c +8c5a81c2b54db7d09ea4a08a43171c7f9ed3cbe7 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToExtF80UI.c +b6b8b672735a45d7c495bf8af1fa94d1c8e6556c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToF128UI.c +7c65ad2301cc6e79aa3392bdb9010a7ce81b0c38 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_f64UIToCommonNaN.c +868cee0046c6b1426f45136804fd662b030f263e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/f128M_isSignalingNaN.c +67e0a5407af29f70e8a1cd10563b7aaec9ccbcdb - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNExtF80UI.c +94e7fa32804e73cff91d5bfa140aebbbb55fe6cb - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNExtF80M.c +4a66a4eaba41707a706d22a724ff5853260d070c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/extF80M_isSignalingNaN.c +7e3b18d1139373153529a43d88c469da845d393b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToExtF80M.c +70de120b27bf3bf6917bf2a9536aad6fe8536358 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToF64UI.c +7d5189099e205be2e0420013770668fb8b96e133 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_f128UIToCommonNaN.c +35b37030a4086b22b7974082589b33ca07ccc8bb - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToF32UI.c +b0822433062f48471e106e268f79f079d1a1cd55 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNF128M.c +7dc9295fddc66cd74761fa03a90c65985b964c08 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/softfloat_raiseFlags.c +302b57e7a9ad056c7936806892309cb4de6ffc96 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNF128UI.c +1c390c99fc7405c9a44b4117383cce7de291c13e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_extF80MToCommonNaN.c +3b6c666fa3fd1fcdb96504690f34db6740d85b2f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/include/softfloat_types.h +1afdc66c33767a868d162893776bf6d3ba9f1247 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/include/primitiveTypes.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 +8450fc5ca89f94b128b1d1d4608903ffd0de498b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/include/internals.h +93bd291166335a88ca0721d5beaebd9599a2475e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNF64UI.c +5e2ab65ab8c5b830b547afdfac8b72c1a7b193f5 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNF32UI.c +ade8c323e356c3e70af2424ed9e2ca0ccabc68c5 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/specialize.h +d8fc85a2746e3c31e70de675027af01735ba105f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_extF80UIToCommonNaN.c +52bc24f91ee7846596274fb2b29654539fd3fa00 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToF128M.c +2c9f36c79b5d80fe13893b8c9b9f9c94273c1c95 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_f32UIToCommonNaN.c +52fee0fd73c94d2e2f5a21a55f082e1963b1569b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_f128MToCommonNaN.c +8c5a81c2b54db7d09ea4a08a43171c7f9ed3cbe7 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToExtF80UI.c +b6b8b672735a45d7c495bf8af1fa94d1c8e6556c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToF128UI.c +7c65ad2301cc6e79aa3392bdb9010a7ce81b0c38 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_f64UIToCommonNaN.c +868cee0046c6b1426f45136804fd662b030f263e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/f128M_isSignalingNaN.c +67e0a5407af29f70e8a1cd10563b7aaec9ccbcdb - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNExtF80UI.c +94e7fa32804e73cff91d5bfa140aebbbb55fe6cb - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNExtF80M.c +4a66a4eaba41707a706d22a724ff5853260d070c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/extF80M_isSignalingNaN.c +7e3b18d1139373153529a43d88c469da845d393b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToExtF80M.c +70de120b27bf3bf6917bf2a9536aad6fe8536358 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToF64UI.c +7d5189099e205be2e0420013770668fb8b96e133 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_f128UIToCommonNaN.c +35b37030a4086b22b7974082589b33ca07ccc8bb - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToF32UI.c +3b12a5a00c5ee315f9665165cc0160e7e4e7b946 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNF128M.c +7dc9295fddc66cd74761fa03a90c65985b964c08 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/softfloat_raiseFlags.c +cc1a5d99c9f6833e79108373c21162c7fb65a742 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNF128UI.c +1c390c99fc7405c9a44b4117383cce7de291c13e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_extF80MToCommonNaN.c +75e9aa350d3aae45b151a9bbe2f6e70ccad11c7f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/doc/SoftFloat.html +90d2bc9a9afc3396f0a2271c1d79a76287c2516a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/doc/SoftFloat-history.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 +5fbd70f4fe7a023e3b9c3c6997b0cc042bec58d8 - optee/optee_os/lib/libutils/isoc/include/inttypes.h +b61508c5b2e6fa2f5e16faf66b4ea52d273b2767 - optee/optee_os/lib/libutils/isoc/include/assert.h +b704c2144f4058cc83eff91c732a965487af7f2f - optee/optee_os/lib/libutils/isoc/include/signal.h +2f1e8ef53989a85982945a254710d877d86ddab0 - optee/optee_os/lib/libutils/isoc/include/malloc.h +7146a287e1507a73b42aa6ae46d72881a5b318a8 - optee/optee_os/lib/libutils/isoc/include/stdlib.h +44f78c63d935ad93ce68039331f214dcc699f6e1 - optee/optee_os/lib/libutils/isoc/include/stdint.h +1b5da4e5962171c39a2b4762a169e12e50dd6641 - optee/optee_os/lib/libutils/isoc/include/stdio.h +eb700f736fea47a51c03069d099ff492d566f45b - optee/optee_os/lib/libutils/isoc/include/time.h +e83da5f07c33bc84bb291affe6480214bb4e6f9a - optee/optee_os/lib/libutils/isoc/include/ctype.h +e7fdba9acf2bc6ddc6d25cd852eeff72855d143d - optee/optee_os/lib/libutils/isoc/include/limits.h +9edc066dbedabb03c6479c2dfc962125c09207b5 - optee/optee_os/lib/libutils/isoc/include/memory.h +d107150611ad4db054a4c134a03cb4072e5b978f - optee/optee_os/lib/libutils/isoc/include/strings.h +f1ba2ffbb8b80c3d2c8baf5ad09f2d1883ccc95e - optee/optee_os/lib/libutils/isoc/include/wchar.h +15ec9c6af06bd04877ce230bac8bfa3ce26a23e9 - optee/optee_os/lib/libutils/isoc/include/unistd.h +c6501a452dfc56db99d454ab6785417f3fd2049c - optee/optee_os/lib/libutils/isoc/include/setjmp.h +8629e94b3bc7a9b628d559492f6859405e065233 - optee/optee_os/lib/libutils/isoc/include/string.h +e646420d5133d287b223a251d711caef5077d8aa - optee/optee_os/lib/libutils/isoc/include/sys/cdefs.h +04b7e694a49520ea266a7acc30e79a4d5d015854 - optee/optee_os/lib/libutils/isoc/include/sys/fcntl.h +ea09b9213223627399f059ff48bc083ac9652a96 - optee/optee_os/lib/libutils/isoc/include/sys/queue.h +f39fd14f91c4f1b1a6c2636a7abfaa0cad378a37 - optee/optee_os/lib/libutils/isoc/include/sys/types.h +5a9624425bf1040b1f7f44f5391b07f0f54eb969 - optee/optee_os/lib/libutils/isoc/newlib/strstr.c +5f94025cb7d772e0b69eb04008405feb9ef86a0c - optee/optee_os/lib/libutils/isoc/newlib/strlen.c +5c1c0c4053502cfc23acb11a61aef64e6a9f7383 - optee/optee_os/lib/libutils/isoc/newlib/strcpy.c +afd073d96ce316d15f065f34576779bf31b11b4a - optee/optee_os/lib/libutils/isoc/newlib/strtok_r.c +ffc219c3a21638f7e62d3b658ee6c4a3dad8e628 - optee/optee_os/lib/libutils/isoc/newlib/strncmp.c +108514868e87a312a98be4104fdfa5f0b689a956 - optee/optee_os/lib/libutils/isoc/newlib/memcmp.c +5604c3647615806cbfd5068d684f1127272226c0 - optee/optee_os/lib/libutils/isoc/newlib/str-two-way.h +ca1b181d9d51ccd041f7a54adb83afacde6591b7 - optee/optee_os/lib/libutils/isoc/newlib/bcmp.c +b1d845daf20cc5443488f37fac3559c721bcfb45 - optee/optee_os/lib/libutils/isoc/newlib/memcpy.c +4536b43b4035e668869db96685c3e398be901a40 - optee/optee_os/lib/libutils/isoc/newlib/strtoul.c +0800e9eb716a2e65ba7a95b2fbd873749abb41ec - optee/optee_os/lib/libutils/isoc/newlib/strcmp.c +6054fbc2e1ca96c1f5291cab671fc90d7ce00fa5 - optee/optee_os/lib/libutils/isoc/newlib/memchr.c +f4be3b2ac744128b112751c273f2850ec6277a45 - optee/optee_os/lib/libutils/isoc/newlib/abs.c +ad3617f14072481d06acd4c17903f9eaf3301223 - optee/optee_os/lib/libutils/isoc/newlib/memmove.c +811f31f56bd454989b15ad39bd9201411a4971f2 - optee/optee_os/lib/libutils/isoc/newlib/memset.c +e0298efe1346c7206253a9f0f174acc71479f134 - optee/optee_os/lib/libutils/isoc/newlib/strchr.c +3eaef3643d7bc2740a34226b2b66dca0fd662558 - optee/optee_os/lib/libutils/isoc/newlib/strrchr.c +2424e0252f73a9e6fea420e9f7f2967538d56444 - optee/optee_os/lib/libutils/isoc/newlib/_ansi.h +c62c5a7633896186fdfc21ab5992c569d0b93d28 - optee/optee_os/lib/libutils/isoc/newlib/strnlen.c +f78df3e9bb90074ab9ac143f5e62bed8c2557796 - optee/optee_os/lib/libutils/isoc/newlib/strncpy.c +89ebb1873af1f851bc8fc67e813f81eb6a676a2c - optee/optee_os/lib/libutils/ext/consttime_memcmp.c +ce50432f4d5515d5ce9fb398b5098b9c0ec12c38 - optee/optee_os/lib/libutils/ext/pthread_stubs.c +6bff861d7ee6d2d199bf849da8673bc2f7644a81 - optee/optee_os/lib/libutils/ext/mempool.c +47c2201804ad35107c694730f37c017ee288ee01 - optee/optee_os/lib/libutils/ext/fault_mitigation.c +eeaf7cbef43d983ce60db9ac8731767dc6bbf22b - optee/optee_os/lib/libutils/ext/nex_strdup.c +53a0650d0e1a37aefbb511bb3f422ca162180c36 - optee/optee_os/lib/libutils/ext/strlcpy.c +ffad6974fa755ea998a6801173ebf69647d8e204 - optee/optee_os/lib/libutils/ext/memzero_explicit.c +20e3e9705f80898b933d3708b6c1b4133ffa949b - optee/optee_os/lib/libutils/ext/trace.c +8d6b22214c57ad89d47fbf50c9d2a28ec11c2951 - optee/optee_os/lib/libutils/ext/snprintk.c +7a501727fe2d0e89ac822ec9ecfc06ac9387eb69 - optee/optee_os/lib/libutils/ext/strlcat.c +ece984c44b615c403bcea03f8d97fec4569856f1 - optee/optee_os/lib/libutils/ext/arch/riscv/atomic_rv.S +9744e9d7926714ea8ced25857ff8db9a0b12cff5 - optee/optee_os/lib/libutils/ext/arch/riscv/mcount_rv.S +fcd9b20bfb493ed1ef33987681cef3c072605105 - optee/optee_os/lib/libutils/ext/arch/arm/mcount_a32.S +3c9419abbdb07dffd661757f2b8acbc0c49e971b - optee/optee_os/lib/libutils/ext/arch/arm/memtag.c +7249fff01b1ca0cec36cca67bec4a1395ee4224f - optee/optee_os/lib/libutils/ext/arch/arm/atomic_a32.S +527c3d07f4d854cb770425c1d1bb43d87d25a622 - optee/optee_os/lib/libutils/ext/arch/arm/aeabi_unwind.c +c76559d831152142d5a0612b9a2ba8988ead0414 - optee/optee_os/lib/libutils/ext/arch/arm/auxval.c +adf6c7b011707e03c48439a6a7de0b07e91d5e59 - optee/optee_os/lib/libutils/ext/arch/arm/mcount_a64.S +ff0eea4f25438d8836034710afb20c6ff62d9805 - optee/optee_os/lib/libutils/ext/arch/arm/atomic_a64.S +e0f599207b28b33bf06b5e1c02b650d0e1a2d7c5 - optee/optee_os/lib/libutils/ext/include/trace_levels.h +0e9c096815b105d29d59a8cfadaaeb5e7a3b7998 - optee/optee_os/lib/libutils/ext/include/arm64_bti.S +5d1943eba944ecd7ffb277b76460ab47a379f73f - optee/optee_os/lib/libutils/ext/include/memtag.h +84039f2a7ab7966f95cf82f76639cb60c3d8f17c - optee/optee_os/lib/libutils/ext/include/util.h +2896ec82cb868e5f5d1b8338aba45f9490c96419 - optee/optee_os/lib/libutils/ext/include/asm.S +8aef0ea1cd59799ea3f9b89eb12d8ad5f9482b68 - optee/optee_os/lib/libutils/ext/include/speculation_barrier.h +93a77e57894a180ceb9cbf485c96b316b0223286 - optee/optee_os/lib/libutils/ext/include/string_ext.h +af2b6927c92cd80ffae87a12bf87645f43748dd8 - optee/optee_os/lib/libutils/ext/include/atomic.h +70ac170a6c79b30435a4b8fef9cf7e98ea61e9a9 - optee/optee_os/lib/libutils/ext/include/printk.h +6d52c01d26b5f87893d70ca173d1fd712d53f4a5 - optee/optee_os/lib/libutils/ext/include/confine_array_index.h +1439d0e682d301147076a8f0ef733acb0d21d451 - optee/optee_os/lib/libutils/ext/include/riscv.S +caef86fc6055f0c19ce5e5429996c4a422645a3b - optee/optee_os/lib/libutils/ext/include/trace.h +b049afe67cfa21b37d9733a47ac95b142b1bbf55 - optee/optee_os/lib/libutils/ext/include/fault_mitigation.h +d0fd7d83680885f9a71f56435b92b078f79e14df - optee/optee_os/lib/libutils/ext/include/mempool.h +296cc431c36cb1c06ef0965e569bb8f0028aaa86 - optee/optee_os/lib/libutils/ext/include/bitstring.h +ce8e8d219a06d536dfb044bd004db98fd595d438 - optee/optee_os/lib/libutils/ext/include/stdlib_ext.h +0c4e420d80821bc2e9d1c85cb5488cdba9b2dfb0 - optee/optee_os/lib/libutils/ext/include/config.h +cb245d42df602e376891d86e4a5bc7e4adf563ed - optee/optee_os/lib/libutils/ext/include/compiler.h +603efb52be462838f3f8f8f5ddb20258ac30f353 - optee/optee_os/lib/libutils/ext/include/types_ext.h +cb974d6f302fc21a6380a7a8d4e86e824279e6f5 - optee/optee_os/lib/libutils/ext/ftrace/ftrace.c +d252604ab38468dc215d8fff7e20420e53adb60d - optee/optee_os/lib/libutils/ext/ftrace/ftrace.h +76a908634bfe89773fd70c57fd77d712c4bc89ee - optee/optee_os/scripts/sign_encrypt.py +57eab194acd3e07adfaba6438695da8c79d0d289 - optee/optee_os/scripts/ts_bin_to_c.py +570bf1d2a225e0124496bc57c287ff0991fd023a - optee/optee_os/scripts/gen_stmm_hex.py +ab4324da2d6fb92edbcaa95bc23911ed63e4514d - optee/optee_os/scripts/arm32_sysreg.py +08b1957d02a5f8fb853138fa4b3f2b8b04f8d847 - optee/optee_os/scripts/update_changelog.py +d302da149f2f0d0b11b9c365bf3add51a131b8a9 - optee/optee_os/scripts/gen_ldelf_hex.py +edc01ccf3e16f1a4bdb1908f57a4722d3bfa203a - optee/optee_os/scripts/checkpatch.sh +e13049cc7ecc4774a0b40b42d6a72617f540db8d - optee/optee_os/scripts/bin_to_c.py +bd6f1fe3cc1334b262bfbcf3d1b4b2f98bda0d3d - optee/optee_os/scripts/checkpatch_inc.sh +ffaf1fbbaa6d01cecaeae7d8ce75f8315240228d - optee/optee_os/scripts/pem_to_pub_c.py +31f300bb6c5a381759d5e2a3b54e42039be66dd5 - optee/optee_os/scripts/sign_helper_kms.py +c92fcf555467abe77b88cea98e805eaa6eca5462 - optee/optee_os/scripts/gen_ld_sects.py +b1241b7d0c39f88fb4382637396901002f682b69 - optee/optee_os/scripts/gen_tee_bin.py +6d38439ab83fa8f0869ae12e569bbd89074aea8b - optee/optee_os/scripts/symbolize.py +24ab5b3587dac3d8b99136338a79a57b38027da9 - optee/optee_os/scripts/mem_usage.py +1119399c06c6d97111c710e321f7317d2d67df3a - optee/optee_os/scripts/ftrace_format.py +44102438f54e075418710993095e3d5b5f0cec54 - optee/optee_os/scripts/gen_compile_commands.py +f8bce245ce0b6610d39e02928e25307a5b6cc818 - optee/optee_os/scripts/print_tee_hash.py +718761702d374076e980d8684a032e9543d4e0e4 - optee/optee_os/scripts/sign_rproc_fw.py +e6692bdad99dbf466f146fe7169981ae542eb6cd - optee/optee_os/scripts/get_maintainer.py +d28afa9fcae64f65d207dc150f051b7c609bbe32 - optee/optee_os/scripts/derive_rpmb_key.py +ff71ab8e19870db30e4a8fba666168c645f37126 - optee/optee_os/scripts/tee_bin_parser.py +f38c4636b6798cab2823555649a59b72061b756b - optee/optee_os/ldelf/ldelf.ld.S +d7ed8b2b8bca2a9b7b2b50e4c5ef3533b96cbe02 - optee/optee_os/ldelf/ta_elf.h +db3db1aeff618f5696eb16e7076b63464784267e - optee/optee_os/ldelf/syscalls_asm.S +ecc193b3d2a051728bc5d4e5841c8bdc021b6d35 - optee/optee_os/ldelf/sys.c +a270591f1efb8037df1d1369287b15f5f2964e0c - optee/optee_os/ldelf/start_a32.S +c5d1a1d261c8bada5f949335bffe29a029d03e05 - optee/optee_os/ldelf/syscalls_a32.S +d875d1a5979daa09b5b535d0a3f040c86a60f078 - optee/optee_os/ldelf/start_rv64.S +139e3f4826e35954af3c3bfe5112f11c1bd0db62 - optee/optee_os/ldelf/syscalls_rv.S +16e361c79bd359473a90bde00b493ca4182cc975 - optee/optee_os/ldelf/ftrace.c +87d8438d725c689049dabad1a58459a5efaaef0a - optee/optee_os/ldelf/dl.c +cb079ab7bac5d488cf5375c1b028130bcb2c7997 - optee/optee_os/ldelf/sys.h +29a349fad517b13af907e7705113c3831dccd9e9 - optee/optee_os/ldelf/syscalls_a64.S +af3868e37b5f97fafb0a1843478916e687050325 - optee/optee_os/ldelf/ftrace.h +f133be54ea11df978fa33a5afe3a2d8ed8c8f035 - optee/optee_os/ldelf/pauth.h +0a9f8943d795fd8edd10c5cc7c83baab9970b012 - optee/optee_os/ldelf/ta_elf_rel.c +9201638e87d7051478eaabddd7ca1d9054f35f5f - optee/optee_os/ldelf/tlsdesc_rel_a64.S +4b036af7eee80c9d1402b0b1dcd09cab729a7a9b - optee/optee_os/ldelf/pauth.c +d733071f9aa144e7310fba8dee83b811398327e8 - optee/optee_os/ldelf/ta_elf.c +13ded24e6da6026069baf1c4dd3159b6410f5308 - optee/optee_os/ldelf/start_a64.S +611d7981c55b4c62f5b13677c04a314e1a2f3218 - optee/optee_os/ldelf/dl.h +2450caf3ccde56f97078cfabd0a6378472ae1a23 - optee/optee_os/ldelf/main.c +e753e305779ac38002c5db612439fd95d3e9a20d - optee/optee_os/ldelf/include/ldelf_syscalls.h +9d6a14f727a55f4691af8e78834e23c243a1be39 - optee/optee_os/ldelf/include/ldelf.h +1c8f13cf72490970da6d19a7a3d3c06f18770f07 - optee/optee_os/core/lib/libfdt/fdt_wip.c +78de4be67ce92f5b90ff1ab89c2ba46a1a34da7d - optee/optee_os/core/lib/libfdt/fdt_ro.c +966e9a4b174cc33c3ba6126614b919ca0bfd09e4 - optee/optee_os/core/lib/libfdt/fdt_overlay.c +ed2772a8c2274cf02551a2a21cfbc33a7d81c2dd - optee/optee_os/core/lib/libfdt/fdt_rw.c +a6759c569917866b44961c88629ae4f3f07ea686 - optee/optee_os/core/lib/libfdt/README.license +0da7a6ee0118d32ca78e772cbf5a81f0cd62af9a - optee/optee_os/core/lib/libfdt/fdt.c +e01b7a0052b837a4650f2c9ac75ad38c40edc583 - optee/optee_os/core/lib/libfdt/fdt_empty_tree.c +e5657b776e8466d0d7c9578591d9c2ef45ef2799 - optee/optee_os/core/lib/libfdt/fdt_strerror.c +fd3af5baadbf42cca01d1a438cc826ae85a21f97 - optee/optee_os/core/lib/libfdt/fdt_sw.c +5ac5dba57124ad85911a67c10cf941f08ae861bd - optee/optee_os/core/lib/libfdt/libfdt_internal.h +55fc5d2ffcba07e29948822d0b12e4bf5546b8b8 - optee/optee_os/core/lib/libfdt/fdt_addresses.c +265155048eb725a03c49a45a27f322ca6f3dfe6b - optee/optee_os/core/lib/libfdt/include/fdt.h +c90d25bb7b217171ad9437ee0bc8d4e0c5c7f4d3 - optee/optee_os/core/lib/libfdt/include/libfdt_env.h +7cf2619336867b335fe8f3c919607242477ccfa0 - optee/optee_os/core/lib/libfdt/include/libfdt.h +cc088246b745446e2d222bd1c5219334f1c8a430 - optee/optee_os/core/lib/libtomcrypt/mpi_desc.c +ef50fbda210143489722c5c073b049220aee69ce - optee/optee_os/core/lib/libtomcrypt/cbc.c +bf7cfd733029fd500704f55382b02cd8fba1b84e - optee/optee_os/core/lib/libtomcrypt/hash.c +5a1e99eeb7282f69b7e7cbd68a0f514644c4d2eb - optee/optee_os/core/lib/libtomcrypt/x25519.c +f38de7925c7043b9c008b228fe88f291f90fe671 - optee/optee_os/core/lib/libtomcrypt/sha3_accel.c +422469b123ee31fdd517259a2ff73fe03da28d95 - optee/optee_os/core/lib/libtomcrypt/ed25519.c +181064609b067d38f551f69dcacc2d7a6ee4c249 - optee/optee_os/core/lib/libtomcrypt/sm2-dsa.c +bc5761862d3f2bdc223bbd894e1edffc89db0614 - optee/optee_os/core/lib/libtomcrypt/aes.c +627ba519b1c58c51f6ba86d4c3efcf948e497db9 - optee/optee_os/core/lib/libtomcrypt/sm2-kep.c +36ca35680a4370d4f993961371d80d2e7b777458 - optee/optee_os/core/lib/libtomcrypt/acipher_helpers.h +466eb4dd083c77261b455c56dfb3036243b0992e - optee/optee_os/core/lib/libtomcrypt/sha1_accel.c +191319cf67c91dac0437c501694f9973ada49045 - optee/optee_os/core/lib/libtomcrypt/xts.c +5d3683701305265a319ea23c3053100dc9ae0bfa - optee/optee_os/core/lib/libtomcrypt/gcm.c +f11a282fb43eece165553ab1545b7035b44ebe24 - optee/optee_os/core/lib/libtomcrypt/ecc.c +a2ecdde9b88869f00656b532502bf2e1c9c778bf - optee/optee_os/core/lib/libtomcrypt/shake.c +2fc6c08d346f75feec7f1c1633ccf1ddc1ac7736 - optee/optee_os/core/lib/libtomcrypt/hmac.c +b1d9c45ed1f78bc67c1bf788fd2478f835b86f80 - optee/optee_os/core/lib/libtomcrypt/aes_accel.c +9197499a951acd6f4952270e28672de2d04696ca - optee/optee_os/core/lib/libtomcrypt/ctr.c +f2db1584836afadf8108bc4068ada599727f3a85 - optee/optee_os/core/lib/libtomcrypt/sm2-pke.c +2680c6505dd66000230072a984d24a8085db27d0 - optee/optee_os/core/lib/libtomcrypt/dsa.c +7f870de527ffa71429d8016fd5b6800110e56460 - optee/optee_os/core/lib/libtomcrypt/rsa.c +ac9a9648fe065d77e8a07c0f153c16784b90b675 - optee/optee_os/core/lib/libtomcrypt/cmac.c +bd085d21425692efa0737d43fe957bf83da73e8c - optee/optee_os/core/lib/libtomcrypt/des2_key.h +a53dd03d8ef444dc1ee628dd000ca066984be89d - optee/optee_os/core/lib/libtomcrypt/sha256_accel.c +db10215efa57b04d6d0c2259256832c69da9d405 - optee/optee_os/core/lib/libtomcrypt/tomcrypt.c +e6002d6bda94d5566d0598b73957a79863fc5869 - optee/optee_os/core/lib/libtomcrypt/dh.c +99aa558ed75d6462b266bdab24faa189c03b4563 - optee/optee_os/core/lib/libtomcrypt/ccm.c +a001afe7f955e43839c5e0d73be3db5db77d94d3 - optee/optee_os/core/lib/libtomcrypt/ecb.c +72b382fc200ec2a39395f48c821d263bb827cd3c - optee/optee_os/core/lib/libtomcrypt/sha512_accel.c +999e42770e9ee014be2004a0f9ce41d08a2002ac - optee/optee_os/core/lib/libtomcrypt/include/tomcrypt_mp.h +5c28c3c8b5fdb83a197148d44816e8b005affa3e - optee/optee_os/core/lib/libtomcrypt/include/tomcrypt_init.h +ed9c10d0285b377accb1e2494f6286e154bed777 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_macros.h +d86162251e3b48c30f090b3d893a17106c1b59d3 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_mac.h +4e5b33b2454acbfaa9b2ab42a0a03fcabc598d30 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt.h +941fea915f92af82307b36234f5ce179c0fd3025 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_argchk.h +c4d8079f35569279e5f30da5d4666d1a145c29e1 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_pkcs.h +47a31bfd38f96720df80f298c98d96cb435b3ad3 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_cfg.h +6e3431e86381584751e3fe17d1f783454fad2f52 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_misc.h +23b6ced88dc0c3124f432f3017aba8b385df4866 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_hash.h +44976f48c4f37ff61e8b03ca839b1a65f273117f - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_pk.h +b024a3e54d8b78ef88bc56740995d089836bfc81 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_cipher.h +2e713c6c463faaebb4e01472732e51d74aa5b185 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_arm_neon.h +6603ac9ecc182ac6407d2a5bdd90f3baa4552f58 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_private.h +4cdf5186a0f57233bdeac68a7db9e2e488806fd7 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_custom.h +49b2782b96dbf7d798398be0b39ba922e5a21bf1 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_math.h +660c8803aeecea2223f2075be243bfdf24187599 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_prng.h +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 +b27bb0657c7accb0df147f4bf193b12933a9d970 - optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_done.c +224913f37550084d0b6a11c46a674e2560b9f6de - optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_memory_multi.c +c987048ee653d7b9e528924cd4ea2041d81ffbd3 - optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_memory.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 +8151c66fd55cb82b2e4252f211a7d14de20599e1 - optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_test.c +f86f622ff3761a9086d7779d77559eddf2774ece - optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_memory.c +b8c88d3152a2d9384baf86c1ec61ebb26f13660f - optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_done.c +ac3fb83b5d619e067782a032452e215cc2ccc3b4 - optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_memory_multi.c +114da72cefd715009a772baebd50f69a3237da72 - optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_init.c +bbf18f6d75557cfdbb5aec0cb00e3df605536d68 - optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_file.c +a3529bef5d5ca05f194021b998a1d7ba5fdec700 - optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_process.c +6f1f256d9e8a6ee6660406b43866a0dd79fbd255 - optee/optee_os/core/lib/libtomcrypt/src/mac/poly1305/poly1305_memory_multi.c +86f1332253c798f3fdfa01762ed1c64949a69794 - optee/optee_os/core/lib/libtomcrypt/src/mac/poly1305/poly1305_test.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 +5e2fa3a8a8b8c0d38d74aa0bab4d4cc206166453 - optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_memory.c +a081274e2f9dcc2ed96ec2a4db00ededed0ec9e8 - optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_test.c +7314b670b2c1a382ba1017ccd3b3806fe451aad6 - optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_memory_multi.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 +daee17f76d3539a02d8567dc943b2b3217098786 - optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_file.c +5a792633cf4c62bb31894bcce5bb07e78763b88e - optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_process.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 +9b028196ee6d1b9299d41bc2c6d66cacd1011ed3 - optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_memory.c +5c61eca352761007c4111cf83cabf66f712cb67c - optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_process.c +78be422e4801b343c32f4a4574075488109af2e0 - optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_memory_multi.c +de921bd15503ba513e2979be7113493b8c679ac9 - optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_init.c +7ec5d863f61666d818632fd057c4fe9bc1a879f0 - optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_done.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 +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 +208bbe5ced04c13eb0e1d3b24e76f5c81345cd04 - optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2smac_memory_multi.c +93f44519ebb2341e9ca27ec077a77a455641dba9 - optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2bmac_memory.c +9bf71a86a4483d4e404521f696f591017b261b9e - optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2bmac_test.c +361ba0aee5e365c0c0cb186cb4aefdac17289943 - optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2bmac.c +e29b12ee69c044ee575a389f95878c7498a62af9 - optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2smac.c +420e593df278e8c4bce349965dc185a1654e27b7 - optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2bmac_file.c +7ef84ee8949eea9fb48ef217f1c8ff24f6adf1d7 - optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2smac_test.c +13a4a399570926073872b210027dc5539d30d44e - optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2smac_memory.c +539c06612340597abac186f272ceeec032082a08 - optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_shift_xor.c +0e00b9ac2e143fc27c3122a3f3d9bc87d8282076 - optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_process.c +1336042d04c7dd5b0ee965be9d037bf654049339 - optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_test.c +0371334e645562a86984c83f6257967f26cf1464 - optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_done.c +fd77eaabb5a5ffddd12e2f91920bd8e657aaff2f - optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_ntz.c +74a84dcfca09518e42ab725a717c8aedc0fb9f84 - optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_memory_multi.c +eb8f24748a3fbff1fabe0be3ce91f76ace71528b - optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_init.c +4a8d8ec6fb7faf70d806473ae0d8a3d1c9d3cc5d - optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_file.c +21ade96dad372a77d13f421cc9c1f8d2290e239c - optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_memory.c +af7e5ec699439a45de3f29a72e6779709ebce7ac - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_encrypt.c +16d4c4b33c5e68749766312b86e074433514c453 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_ntz.c +727b4d190bb993d395c276fdc4b6772e7507af6f - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_decrypt_verify_memory.c +93e89b145ff46fcae1c653ee70c2061ac539e737 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_done_encrypt.c +87188dae93ef2263dd1baa4207faf5551bf57bff - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_decrypt.c +9874e24493855b4ccab70b0ff538125c23e3515b - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_init.c +83f9d3b22b6bd8960fde8524bcd094d2fd1bad6b - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_test.c +069dc6544fea4923f5ffc9ed6cb508d1e3be4b16 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/s_ocb_done.c +4c0669699a2b11b52aacda4fd2c617d5695da4c1 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_shift_xor.c +fb2baeda2808e719b2543a5bf4e92e86c5a8475f - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_encrypt_authenticate_memory.c +5fd053c692f154fa517d1a66afac3bf88a666dc1 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_done_decrypt.c +00df47ac677f1c073e872b02d89d034defae3198 - optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_setiv_rfc7905.c +a1a4e685352d4984fd5d49522bcd50c4492ea66c - optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_init.c +0af7bc735a8720e5b936a261204b1aa73a0943f5 - optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_memory.c +9de6e2171df8c3c6a974888bfde2f9333e56e12a - optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_done.c +2d89b89d0738d4db5b761d40f9cd02510f413933 - optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_test.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 +559a51a7d6a1d21918f5908f788bb294acf88bee - optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_decrypt.c +5cc80740578579a16d394fdd144d7d71daabfa35 - optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_add_aad.c +9eb480ccdf51a957a9391e17f2740e53048dd90a - optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_add_aad.c +f8f818328098018b9bc6836915dbfc34bafbf574 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_reset.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 +e045e646861478e232fea83658bd42d37547f4fb - optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_done.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 +782a71b6b10b0305491529ce9963ace0c26a38f6 - optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_test.c +8f82752538241e4f3c3f48ccdb5bf6fd41d7e889 - optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_decrypt.c +30473a74f19214129f69b8b067d6d2d5a87a7364 - optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_addheader.c +cf42e3ab0129e2962618a2b9b261e9ea20e0bcf2 - optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_encrypt.c +c5f08bda970ba7d30ff7bee44fda96f5e6515caf - optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_init.c +3199f0f705460b9182e1e9b543e800f7d26b305b - optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_decrypt_verify_memory.c +f60e6c18f07779e8b066581926c51522a92069d6 - optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_done.c +633dfd755ba58507be81b2d70c2d483d28ca9597 - optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_encrypt_authenticate_memory.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 +f162118759bca19c0f87c3807df85b6373ae5644 - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_add_iv.c +6799d4d2d91f4e12e8d866fd920ae847eb66d5e6 - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_add_aad.c +cf505805e8a15d2a7e342491371d6f38a799f8e3 - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_mult_h.c +60ead8187339abc082c6fb5cfa8ca4a07d5bd3d1 - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_mult_h_arm_ce.c +19aceaaa2254b78b3210d81efdb82d2909a5edbe - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_test.c +7b1c5747593a58fdf9669888bd86df7718579054 - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_memory.c +d071d7e805d688ccaaf2b3f8c3b7bc5d68bbba1e - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_process.c +9dd030615b3a2c6b70c7e24dc125673f88550909 - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_gf_mult.c +38d9de8caef78490c170d9f138c49db6374e6a02 - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_done.c +ce658863c830e150ad4cc3c3bf741b91dfa68c6c - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_encrypt_last.c +9b663e83c3004ebe1725ad851bde5f946c0e6150 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_encrypt_authenticate_memory.c +650667de1f0e3d2308872cf4537ae49498239261 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_decrypt_last.c +7d45e3754a326d8386f2e536d6baa81554378581 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_decrypt_verify_memory.c +df0f2138b4cb5a037739e226490a0d08bd268048 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_decrypt.c +7c091098e78cd1fb572b8b2e843ac04d30099719 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_add_aad.c +d3aff516bc303de0bedf794c42305bb770b41629 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_int_ntz.c +487cb958837ebcf06f92ef604fb17b4a495bbd64 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_test.c +5de251abffe4c5d5eea6c9deb2b5a3dd7c128147 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_int_xor_blocks.c +4dd6870aa2c7606e90a94d802fa383dd8515b825 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_encrypt.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 +4a0d52f29c5da69ba1248de543b53f80f00f0358 - optee/optee_os/core/lib/libtomcrypt/src/modes/ecb/ecb_done.c +2f93fc0a9e1afdf93c263f75675e15d9aae63cf6 - optee/optee_os/core/lib/libtomcrypt/src/modes/ecb/ecb_encrypt.c +a0941ac3c7a39107c7f3049a9ce6b7cc3d120c58 - optee/optee_os/core/lib/libtomcrypt/src/modes/ecb/ecb_decrypt.c +a1361518be72e5f0a2c22cf2e99afc5155c64421 - optee/optee_os/core/lib/libtomcrypt/src/modes/ecb/ecb_start.c +ad10e437f618657cf5b5e3ffc20fb6c5219a6db8 - optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_process.c +3e8b2b92ce4faeef2ac7282bb0e58253ed01bc41 - optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_encrypt.c +6166a8f10c3d96dd48d974f0c420288c79faaeed - optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_done.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 +89b75f314fad2f247f3c02a8d043c69822182beb - optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_decrypt.c +6343e513ad46501c7b3c7dc039c8b246ea927590 - optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_getiv.c +6186f3e377626cce35518099044023ede1954ee7 - optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_start.c +75a66324c9304c63a62bc2a97fbc8ea51df97255 - optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_encrypt.c +85a32e2be465b69f7a4132892ad684cbcd8ea293 - optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_test.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 +3dea7eb14320987637e14b812e161c7efa873b76 - optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_mult_x.c +a2a2185a5cbe8319ecd9e65dbb720317d63814ad - optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_decrypt.c +41b01b20223d2bb66ac8f419cf6f8435c9867f86 - optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_encrypt.c +ad7cdbcaef35b7db424ce95e64bf87baf2f4164a - optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_setiv.c +cf8ba7e0b9c7428652d258729d7790277015c181 - optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_start.c +2140195d11a6c4c204d39ed215e9600018bd23cf - optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_done.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 +06cbb137bfc9d209674f552805083aeb3ae1516e - optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_test_mode.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 +747a817bfdd38ce834a9198f1e176c1fe227b3bd - optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_setiv.c +4a3b1b9453c09f7842de157e91770af0c0ed7415 - optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_decrypt.c +9e461ccf05f3b82c258302f4a3eb873038978a89 - optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_start.c +e6d6ea2e6d96293a8daf46f6c0748936ccc3527b - optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_encrypt.c +7d9c7698b787a53e3bd28940cdd444746994860b - optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_encrypt.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 +3a750d0cc44888f039a609e54a400af43310abcd - optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_decrypt.c +a5a54f70612eca541d03a7a560aba8cdff0b4df3 - optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_getiv.c +56f1ea6d8684edf6bbfc6e96fec03f21f3ec7879 - optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_done.c +b03f3351e97f9628fb7921eda85ae3f0b0534156 - optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_encrypt.c +c9abd410a11d44eb94910ab6d95bafc4e75fcbe7 - optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_getiv.c +cf2740b0fb974b94f1cc08890920c5e95f703310 - optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_done.c +2997b2353ddb192f89b3ec278ad91cdc8d7f2b62 - optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_setiv.c +0303400a05e16078ca1944029c36280472d79869 - optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_test.c +ee5c9c1fd94d09694078522a5a470058f1aa78ea - optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_decrypt.c +265e8429da2df62461fd0b313a0120c58034bd0b - optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_start.c +eb172f92954aa6843672b7d7bc9707f7448bc1c4 - optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_getiv.c +207351014a29ed0dce3fcaa0898b5c563262e0e1 - optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_decrypt.c +4ec1b143f43bb9aac8d870e9bad201ea008c17c3 - optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_start.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 +f5dfcba990f115b494ccd95e958582ca983bfb31 - optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_setiv.c +e618ce5c3d8409cf47b68ba9621e64262846a123 - optee/optee_os/core/lib/libtomcrypt/src/prngs/sprng.c +4b6959d31d2cd9d600c17adca9edd2b7fbb70bb8 - optee/optee_os/core/lib/libtomcrypt/src/prngs/fortuna.c +65bdd642447c1d4dfc26f0f35958f0e1f9dbf51b - optee/optee_os/core/lib/libtomcrypt/src/prngs/yarrow.c +b1696e891350ceb540ac60bc6d4fc5601ae109b1 - optee/optee_os/core/lib/libtomcrypt/src/prngs/chacha20.c +0175635dc4f43317153da8fa639515156755da5c - optee/optee_os/core/lib/libtomcrypt/src/prngs/sober128.c +91b049316fd473eb33d4807d7b5aaa9a00844a82 - optee/optee_os/core/lib/libtomcrypt/src/prngs/rc4.c +94ca15102c5937a658d63a00e39be8d7ce0a25fe - optee/optee_os/core/lib/libtomcrypt/src/prngs/rng_make_prng.c +9931d364f7feeae167aaad25aabc387977444f87 - optee/optee_os/core/lib/libtomcrypt/src/prngs/rng_get_bytes.c +02474538dadafba33694c8ecab5fc2e6d00a7281 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/khazad.c +48cdd948011ecd3e9298f56dce531d60ede7608d - optee/optee_os/core/lib/libtomcrypt/src/ciphers/idea.c +398a2df01e72511a00c4fd56ef10ba61c9e08ae4 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/kseed.c +461cbf82c045454db297fe16c3c478c4cde8fadd - optee/optee_os/core/lib/libtomcrypt/src/ciphers/noekeon.c +c870397dc946312c9c0304e8f132b1fe87eb18c3 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/tea.c +819970a30ad279c10add699d9bb08c1023039bbc - optee/optee_os/core/lib/libtomcrypt/src/ciphers/anubis.c +e28e47ef72883f05ef629df3d495fddfda0372f9 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/skipjack.c +60505e6a888a893c8edf9d6065362453230d0d78 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/des.c +d48e4087de75284fb9aa215069515ac90849dd5f - optee/optee_os/core/lib/libtomcrypt/src/ciphers/serpent.c +06e4fcdd40cc84f756e818ffb70a63da8066c7a1 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/kasumi.c +b0f8a843a280133fbab3d261ce7a7486c5f20bb2 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/cast5.c +9748ebff9d560f59b42bb6c8c1dedc71dccbc225 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/rc2.c +4e35739fffcd60f1f9971113810a08c7c7fb114e - optee/optee_os/core/lib/libtomcrypt/src/ciphers/camellia.c +cfc7412e0fbe23e14536db6836f3da2102c02e06 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/xtea.c +9d2d04084cdc6c4c56cec3479af1ccb74619fe42 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/rc5.c +783f175a7e6e630e954aa409e43cc67a854e2921 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/blowfish.c +0e87ea79442a67dec4fad902f2df7a827f1c233f - optee/optee_os/core/lib/libtomcrypt/src/ciphers/rc6.c +840013cf542fd64a45cdea8afb965f8aa0e51df8 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/multi2.c +4a6bb1fb9b2eed818cf6aebf8d6fc78f108db521 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/twofish/twofish.c +b6e57c2661c58975ca885c612932e68bfeb45d9e - optee/optee_os/core/lib/libtomcrypt/src/ciphers/twofish/twofish_tab.c +48a4a60cd68d5143a1998139b830ee8fa7e56faf - optee/optee_os/core/lib/libtomcrypt/src/ciphers/aes/aes_tab.c +4d6e2810b820eb2b29529f2bb429d35841b3bdd5 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/aes/aes.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 +82aa1b04a2ce5276fd516e96169dc1b0c2432bb6 - optee/optee_os/core/lib/libtomcrypt/src/hashes/md5.c +3c19181cce8bd461cc6a736ec3f3940ec737bcdd - optee/optee_os/core/lib/libtomcrypt/src/hashes/rmd160.c +1767c79b4e8637fd2636ed3e5d54dcd37cebae04 - optee/optee_os/core/lib/libtomcrypt/src/hashes/tiger.c +699622196fe40d368c4aa87afa335085d2d7cbd8 - optee/optee_os/core/lib/libtomcrypt/src/hashes/md2.c +17750b4d62fad12b1ae16ef01a8ffa2cac05fe1a - optee/optee_os/core/lib/libtomcrypt/src/hashes/sha3.c +50f0d32cf7879499990c4ec792546db1e812dfaf - optee/optee_os/core/lib/libtomcrypt/src/hashes/md4.c +f0e38b2df179903a5c62a5d1223c27d9468f2b55 - optee/optee_os/core/lib/libtomcrypt/src/hashes/sha3_test.c +a24770ddff20aa047ca6e50ed3b40f67fb229213 - optee/optee_os/core/lib/libtomcrypt/src/hashes/rmd256.c +f7476e6db75e35d781ab4d7ac8fbbb76133f2158 - optee/optee_os/core/lib/libtomcrypt/src/hashes/blake2s.c +c4e009d4708e3b97b2d83467411f582076ec374b - optee/optee_os/core/lib/libtomcrypt/src/hashes/sha1.c +436cc2c14c7f7f513d234253ebce325da3441faf - optee/optee_os/core/lib/libtomcrypt/src/hashes/blake2b.c +bbb1244d51ea6efa2a0d6fd5ff5d1a6b507eb3cb - optee/optee_os/core/lib/libtomcrypt/src/hashes/rmd128.c +c991e82af32c3fd33d4ca7f63a43c46aaa3a8af5 - optee/optee_os/core/lib/libtomcrypt/src/hashes/rmd320.c +63de08d2a37229f4bc2e4138db49d71e7f5786d0 - optee/optee_os/core/lib/libtomcrypt/src/hashes/chc/chc.c +5c4268acde331fa5dfc75643f9edc2c04189e29c - optee/optee_os/core/lib/libtomcrypt/src/hashes/whirl/whirl.c +d4fe8714b77fd3ad07260899bc8b5307e2d44e68 - optee/optee_os/core/lib/libtomcrypt/src/hashes/whirl/whirltab.c +18123fb06342b70d7c8af10d2c72fd07b75e1d2c - optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha384.c +f25a1dad013d500b85f3eef3b3570f30a88b8937 - optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha256.c +91834258fd0a291b0c2e8b5a43b6bd8f7278bca6 - optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha512_256.c +3ff874c5735dc5e5d895621a56ed2a379f35f3fa - optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha512.c +3b7138b66d581516a8dd7568842636ce576e8f33 - optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha512_224.c +3d396867f33dd56b9cb7f66e66c902badeee4bfc - optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha224.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 +2f7b628448c81541c1e80e9cd8cd61e1489736f8 - optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_ivctr32.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 +76550dd06cbcff27a2d8ac4d8f8ef0428da2a4ba - optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_memory.c +a1c69b888c2662b3db2c4343318cfed05ce1a262 - optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_test.c +19529a1c91610536d1f56e09d8f7f0c1c44ed1fb - optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_ivctr64.c +95e2d29cf4201f1cc469997b0aef539883229f02 - optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_crypt.c +408fed5f27e4bb531ec7c18c4ea4b85e1b3e25b4 - optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_keystream.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 +e554ce2b664e1b21e037000eab5b05a464e2f913 - optee/optee_os/core/lib/libtomcrypt/src/stream/rc4/rc4_test.c +43f7927b89b648f1b642bbe96a30329482a96706 - optee/optee_os/core/lib/libtomcrypt/src/stream/rc4/rc4_stream_memory.c +0370402bb2b440618f27fff3e9a7d3e2219a348e - optee/optee_os/core/lib/libtomcrypt/src/stream/rc4/rc4_stream.c +d7ddc63403a0836fcb998d8a80e1d253aad3fac4 - optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_ivctr64.c +b8a013b428ced9671422b507d6833d25312bd823 - optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_test.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 +c1487e9b5be5b8d3a2662a6e37a477cf5c86bb8f - optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_setup.c +e8f1fb8eb2b962abfef86027594a70a50023e9d9 - optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/xsalsa20_memory.c +5d403e317c9deb62133d017412250702a48683d9 - optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_crypt.c +a4f8195e9e117c1053f0272b7b26bc835bdc5337 - optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_done.c +51497c0e6a261a2ebe26056565149049e7154e05 - optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/xsalsa20_setup.c +1e3ea925d7df004fe7994bcedc4d5e0d9551c09d - optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_keystream.c +cc60780ba62cc198b8657fb2994150ebdbd9aabd - optee/optee_os/core/lib/libtomcrypt/src/stream/sosemanuk/sosemanuk_test.c +51e23c33fc2f379b97fdbb9128414859204e00a4 - optee/optee_os/core/lib/libtomcrypt/src/stream/sosemanuk/sosemanuk.c +15c26663221b68b94b5e2f66b93c1b4468d6b956 - optee/optee_os/core/lib/libtomcrypt/src/stream/sosemanuk/sosemanuk_memory.c +7c4f40cf2659b91a59b92ee79867fc47b44affe1 - optee/optee_os/core/lib/libtomcrypt/src/stream/sober128/sober128tab.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 +ff214c34d15c197a91a236c37775d89e959c1bec - optee/optee_os/core/lib/libtomcrypt/src/stream/sober128/sober128_test.c +6adfd2c5e4b416a65be0e9e7d0b6a24c1a3589d1 - optee/optee_os/core/lib/libtomcrypt/src/misc/adler32.c +f4059601bb534681d08bbf29b543f5bc37d29267 - optee/optee_os/core/lib/libtomcrypt/src/misc/zeromem.c +746776871c1d225104237b1021e530a23d5c1fd0 - optee/optee_os/core/lib/libtomcrypt/src/misc/compare_testvector.c +5c187006ec54c463347d528d5671b8e92f9b762b - optee/optee_os/core/lib/libtomcrypt/src/misc/copy_or_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 +ff2dcdde770c5904024d8bd59763632a301e9790 - optee/optee_os/core/lib/libtomcrypt/src/misc/burn_stack.c +ad0c66e6a4431f567b49915d01f026888538f63e - optee/optee_os/core/lib/libtomcrypt/src/misc/error_to_string.c +c2fa3c8655b71dc36a48c5aa409c9ed586f9c8d0 - optee/optee_os/core/lib/libtomcrypt/src/misc/base32/base32_encode.c +f5d1d5c1f347ba72d7eecf6995812bd9b0443efc - optee/optee_os/core/lib/libtomcrypt/src/misc/base32/base32_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 +d0feb5c364be991806af64380cd3a6e5d7062ab3 - optee/optee_os/core/lib/libtomcrypt/src/misc/bcrypt/bcrypt.c +80d8a64decdaeb241abf260380e42f406eb7e132 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_unregister_hash.c +18b723be741bf36e94966af24f7f0da9fa256f26 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_constants.c +0090a8c4b12094134c7e3fcdd6c82cd26327c271 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_prng.c +082f0d654b13f0b93cbe1d28f01726941f0bac78 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_all_hashes.c +abb752921991a5264ecf76f92d09589c9477d1d6 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_sizes.c +20925129239360b39ed195a0d8b6b99d59b890f2 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash_oid.c +1221efc9a518048e34fe881a93fe5c765524f34e - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_unregister_prng.c +d15ddf5b26ce2f13c726a540479ac62355bc4ab3 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_prng_is_valid.c +9e47537140b5988fba0847120d3e311f83085ac8 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_hash_descriptor.c +70ff3cb0ee05909a347b56392e40b79171d1d3ce - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_unregister_cipher.c +6809767adc93fcb15bd91fdd9e99a6264937a6ef - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_all_ciphers.c +d92b5cc31e60e6581ee77b6e9780353b967e8321 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt.c +994a86f2bda5d048c5755b0e7819184195f24ce9 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_cipher.c +28e1308aa1d2f79105cf6aedb36a9ea1664e3567 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_prng_descriptor.c +474440e2037216fed3c26f124fd92a96e2bf51d8 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_argchk.c +81f55ffa10b11eb901eb4a3e44acce81c2582f84 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash.c +5c81f4d8d18f6544665cf9385fabb100324f2323 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_cipher_any.c +f1821b4e1d8e159fc9eebb3c49abfe0f6eef8da9 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_cipher_id.c +a98c18ecdba584f662232ca582bb88b502daee55 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_fsa.c +26a169c33ea38516c1421f536f7bbeeb2983f01c - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_hash_is_valid.c +23eb56683e5cb3b2a6203532f2261e1146584ee2 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_cipher_is_valid.c +c261fdd28c1198d33aeccd35a7728d324671e3b1 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_hash.c +34b218af0b0d226b125bb51da3c2016bcde2eb62 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_inits.c +c22b0f36bb603c5a4cc0e043d1fc84ed5615c82a - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_cipher_descriptor.c +209b907a121df459daa08c8ab473adaedc01f56b - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_ltc_mp_descriptor.c +07ad1815506e2a82911ec0c3fbb9dbe66466efde - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_prng_rng_descriptor.c +96342e249d7c747d11849bf1a4a2cfa99139134f - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash_any.c +233015470408b5b2e38773c5b1127762f545a856 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_prng.c +dd27864633e7f1746e256cc07e47437bbbb4bc97 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_all_prngs.c +d4220e04397554fa19428f3ff33ebc5b80d93d7d - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash_id.c +63d0675dee46f130dd505b9ef11305f66b51d5ef - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_cipher.c +eb9ee827d87cbf5ee6013ea99a318a0e5c477a57 - optee/optee_os/core/lib/libtomcrypt/src/misc/base64/base64_encode.c +b4f980accf155a8df885c69266a8b2154992181a - optee/optee_os/core/lib/libtomcrypt/src/misc/base64/base64_decode.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 +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 +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 +5e2328959d1d9fa3dfe651bc8390f56e97cfeeb9 - optee/optee_os/core/lib/libtomcrypt/src/misc/pbes/pbes.c +8ea5fa890004eae1957192d67e017a2f68ad820f - optee/optee_os/core/lib/libtomcrypt/src/misc/pbes/pbes1.c +e0622cab6f654c9d78768c0037a71e91c7c904d8 - optee/optee_os/core/lib/libtomcrypt/src/misc/pbes/pbes2.c +6b7496efa00caecdbe62a0a85ac0ac8b7a637d57 - optee/optee_os/core/lib/libtomcrypt/src/misc/ssh/ssh_decode_sequence_multi.c +4a0a598b182902b1813bb584ef6dd3ae446d0c70 - optee/optee_os/core/lib/libtomcrypt/src/misc/ssh/ssh_encode_sequence_multi.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 +cbc194b08bb465a7b3cea249824712fda8857789 - optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_import.c +f2e15ff205094f5a30ffd289282806adf3bfa02c - optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_import_x509.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 +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 +9e8045a9b7b85a4fd345a8606dda5a4529102a84 - optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_import_raw.c +8d59b1b306078e34f08e267a5aa226debdf7551d - optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_import_x509.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 +d06add7d54e686364cb1d56bc5c23a69c71597c3 - optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_import.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 +3c7f07f8405b9f895d89a3ea2090632df8c19cc8 - optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_make_key.c +bca50dcf7601a449f350e48f0db458f6e0377f15 - optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_export.c +f527339cc3a30c2b3135771f132f79c94331a0d8 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_import_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 +cf05860092837c42f574e893b097a13b3374da04 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c +b818e0a65fbcb65e56211555e7979eb98ece81a0 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_export_point.c +966e686fb8e1225167a2e3a7c6df50b0540fa9c6 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_points.c +3e64593819f63544e4b0a5e7d7aca57eb34eade6 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_ansi_x963_import.c +5b57ce74997f89ba8f1107d442aca33bb2dc01e4 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_import.c +fbe398aee3a10e7dcb094e86282410752aa1a8b7 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_set_curve_internal.c +df15dd31ef7691042508e5eb5a7963483113cfc1 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_encrypt_key.c +a5205a7b0f315b2ebe0a2ced975772f8a1057571 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_is_point_at_infinity.c +d8f5cf749289d6a9c685c94b34909b764e1d7689 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_import_x509.c +1c00b1e26aaf1253c27c4f23b98535e45a041610 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_shared_secret.c +280c3e6ecb5e86ef00f694afb173a251ce58babc - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_find_curve.c +015e8b1e8df2b67df5666581c49ed3b443a17ebd - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_export.c +8149696ce9b92edc4b72e701857542c66a19265d - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc.c +1a11b95c51b4280fc073baaebd5f749bf0b623c0 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.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 +0287f0fa69106c0067f42dcf123ce01e29d98031 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c +1860b05d1e6d84e49e6bde6665be70d81cc9c8a1 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_get_size.c +4204640f642d5ddb2df36d5eb318b13aed778172 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_map.c +450bf440ad3be5053c0d9c6d7926d5cdcd9714be - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_is_point.c +b482130a4f79e28597bcb38ab42cff07c19787a6 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_set_curve.c +450616e20f9d56c11a1adb892a3645a93741b105 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_verify_key.c +6b5a515a99122e80c6c6b9aa06a86e21ee73b3fa - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_get_oid_str.c +c5c1644f8bcfb94a1e9dc96faf3657ba2ebb4266 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_ssh_ecdsa_encode_name.c +f03fb73a557258c6ea41d3193cd6bd750a62245e - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_verify_hash.c +4703d1e4bec1f70e5e1b17f15db6ee3a4046b47c - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_sizes.c +b51764d8bd42b7561f41b8a977e021f720d461f6 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c +bf20409e528c89116d228521a61e12ec29b6b8e5 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_make_key.c +42aa854ffcb3552db4fb57796569ea830db3d9e1 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_import_openssl.c +bc4963f87689adb59ace0786a7b43d6a677b8512 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_import_pkcs8.c +c8932926feb1db7458a4121747277fbf302deca4 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod_timing.c +96db40ce102160544ab24dfd2a14926461815e18 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_set_key.c +1fb03ce919d517f2cdd83c378d731a39ff656df8 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_recover_key.c +257ac82c33135561dfe7b5c7edecb5a2d0cdf7e1 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_free.c +f547d958caecd824b0b17b1355530bcc788c20ca - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_shared_secret.c +2893671ff36eba57509da1721ac9e5cf8567b6db - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_generate_pqg.c +272952cb667172cf8fba5e852b5b8147d03f3534 - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_make_key.c +a55666907f63f401c00cfa793eac033bc2226339 - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_sign_hash.c +0803f50e230a9797701852fd02cdc9821544fa74 - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_encrypt_key.c +b6d3f3a6c24debd170f1ec62a74d682113250cff - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_free.c +5dc0463320e60a8062e4bb3b76301bfbb72227a5 - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_import.c +4b2dbab5e2aa90bd324218ea5674fef8777f8473 - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_export.c +bb5f98cabbead6be93d785dcc286f45498d5c0c9 - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_set.c +b2e238370d7a369638a2b76d7c64b726f3eb53eb - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_decrypt_key.c +3b82a4885c17b3d11eae9d1f870da34e6cae9f0f - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_set_pqg_dsaparam.c +b0a3bbbaf6fb172cc402a25cfd4114abb554850c - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_generate_key.c +fa3c683b57ff8087a2fd90fb5c6accf72d63ffd8 - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_verify_key.c +7da5513cb4e6ebca0d19c35d74509deb172ebac6 - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_verify_hash.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 +952b34bccc6c1b05ad9de3bcddb1cca3b46b4e58 - optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_generate_key.c +e304ed0a492309f8b0055a4e147f87970fdf38bc - optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_export.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 +a1886213cc203cfe7e6ef49271838e7d967f53bd - optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_free.c +ec26e921ae1e3e3d36d45dc1e9485f2ce7793529 - optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_set.c +3f0628db016f76777bae6ec89728511a7cb6cfa5 - optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh.c +fb90bf4aa59ee4d6f4371b1ed062a7efdf83462e - optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_set_pg_dhparam.c +af78940c2ff22884837509d7ba94f767ac3af81e - optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_import.c +9765d9c7ad353767665e26aa27114aed5064b9d5 - optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_encode.c +f804f75c30cacbad97b14cac9f9603f27f4ee67f - optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_encode.c +7a444c752e2d4df2d1384ce8f9a56dff42a02347 - optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c +7bb1feddfc1ba6fcb69cb4ef537c5a0dfafb8d1e - optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c +fa6b0f40cef3e152cec36c4ccd8d895e10dc60ca - optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_i2osp.c +2d5bca5df73d8684673df1d6ab38bae6f25cd304 - optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c +7e7beaf2f29e72101e3ff7ff9cde8d32af8b6305 - optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_os2ip.c +f97b4369ca4a6cee89a277cd05e60345fcc88377 - optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c +357e06818540426a6b09b30b6265482454ba9342 - optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.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 +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 +fde5cba0f1fbdcfa0af606a17b90c2ece77fdfee - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/x509/x509_decode_subject_public_key_info.c +2e7715416f0b9b81765354e9b71ac389bc674bdb - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/x509/x509_encode_subject_public_key_info.c +2e24598b6fabfaad933446c87bd5a064a275e144 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c +e9d1241660244c310419ea1378b9ae323a7ac61d - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_length_asn1_identifier.c +5ae066c005e04dc7f013a783713675e77547f565 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_length_asn1_length.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 +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 +aedf07da8f7d1b98991abe3e3e74d0760c207630 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_multi.c +16be383d4118fcac43cee6cf8550a7b4027ace1e - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_ex.c +c5977a968d09b999595cf145d3429a62599ca661 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_free.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 +36b1d4df09d77914a9621e323848927e19b9e482 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_length_sequence.c +3547f3191ec66412dcb8347be374eca128c03c11 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_shrink.c +ca146db1227ca30261685565e96aad77b75b5577 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c +24de714f216931c3f599fc8d1e2deb86c21b847d - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_decode_bit_string.c +df1aa22c0a11a444fa3e307b084eb35b6d651a88 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_encode_raw_bit_string.c +291e2e946e23e0e29c802af28ecfb68aa74a3179 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_length_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 +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 +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 +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 +4ab4dd3b5bbbb87afcfc52966eb024bb4d0c8234 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/generalizedtime/der_length_generalizedtime.c +52132cd7a799e297b872a524bda661601b33e5a3 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/generalizedtime/der_decode_generalizedtime.c +e50711035dcfcaa4d0c1fc32f433be0aa8d98689 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/generalizedtime/der_encode_generalizedtime.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 +715c09b19bbef0a9d89511be2ba47db3eb184457 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utf8/der_length_utf8_string.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 +ddc24ebe07f30aff933f0dcacceca877f7a8c912 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/ia5/der_length_ia5_string.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 +f65972e7e1e35ea9bf3c750f6d2fbd3c22de8df1 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/boolean/der_length_boolean.c +2c41e8e870f523500c8fb60f9d88b90dd079c9ab - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/boolean/der_decode_boolean.c +b85ec531d4f44b87eb3be27290a2aaddc246d62b - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/boolean/der_encode_boolean.c +cdc82def06cef9eb373fb549f277544af32d2d40 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/integer/der_length_integer.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 +13994ec081d65c83c2a411ecce60211f79aa7f8a - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utctime/der_encode_utctime.c +9d6bf8a3d490c881c022ec153b9dfd96d4798be1 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utctime/der_length_utctime.c +5c2277093dc1c4f2d6b877f924200805c950e697 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utctime/der_decode_utctime.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 +8eedec47a421b47090137b1e2da8eb203fdef911 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/custom_type/der_encode_custom_type.c +cdbe2378f68d5da22b7a94428334cb11343dd5ff - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/custom_type/der_length_custom_type.c +6dc60f80f7af76c0a1b5992f03ddea0435b439ec - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/custom_type/der_decode_custom_type.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 +979846f85b72946ff810edf5eafeca166d4283fd - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_sign_hash.c +47347830be6ee382ced26f00e0be055570804c49 - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_sign_saltlen_get.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 +9a424e42fb17d230990378f002faa44cd171738f - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_make_key.c +01b964e18bfa23b2d17ae36580bb114f096fb07c - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c +071f6f93d133ca61acdffd03ca03180bd812032b - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_export.c +11826b990bf085ee0676611201c6a738ee4bff48 - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_verify_hash.c +38f5811d94e0c86e4215591ed40917dbde19a7f8 - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_encrypt_key.c +87a49a80c12d41e8594da7524050eba34e5f96f0 - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_import_x509.c +a47196953806fe0b060f66e17a9f5c26db46a788 - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_key.c +9f43d136949b104d186b32b4e272ab71212d140b - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_import_pkcs8.c +32efc4a6c51bd46b2e5123cff17d55cc8560d582 - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_import.c +131a94c18f4c6d67111f71772ce64e30b214b7c6 - optee/optee_os/core/lib/libtomcrypt/src/pk/ec25519/ec25519_crypto_ctx.c +344a33caba6182cfa38c93b69be392fdb85ac4c9 - optee/optee_os/core/lib/libtomcrypt/src/pk/ec25519/tweetnacl.c +bbaf6a67e160f4064a99efb50a56e264bcd9722d - optee/optee_os/core/lib/libtomcrypt/src/pk/ec25519/ec25519_export.c +406b6b0422373c9c2a3c3f85df960bd5fd4134d8 - optee/optee_os/core/lib/libtomcrypt/src/pk/ec25519/ec25519_import_pkcs8.c +4107a71b931755873657a1db5c1d361d3baad0e5 - optee/optee_os/core/lib/libtomcrypt/src/math/radix_to_bin.c +0519f4dfb1ed6bcad6119da63132e2cb99a1ed77 - optee/optee_os/core/lib/libtomcrypt/src/math/ltm_desc.c +2ca00d67d4090191db790a545cd86d609c5678eb - optee/optee_os/core/lib/libtomcrypt/src/math/gmp_desc.c +9974963705cf2ee6ede4a5f04102ba8237fe707e - optee/optee_os/core/lib/libtomcrypt/src/math/tfm_desc.c +64535e883ae11fec86629844a95e9c1d7f02a486 - optee/optee_os/core/lib/libtomcrypt/src/math/rand_prime.c +6eb1e1c16c036e2717dc3ab41e98acde07da53a8 - optee/optee_os/core/lib/libtomcrypt/src/math/rand_bn.c +829f687603d1caba9543ddddb56af948b6a6369e - optee/optee_os/core/lib/libtomcrypt/src/math/multi.c +5a3aef9006609eab6327112f5508e2991e7a678e - optee/optee_os/core/lib/libtomcrypt/src/math/fp/ltc_ecc_fp_mulmod.c +eb37e780cdfe0dbafb29c0fa8629125c6e19bd6a - optee/optee_os/core/lib/zlib/adler32.c +edf93d4bfb11950ac75aade2faf0bf05d0aaff47 - optee/optee_os/core/lib/zlib/zutil.h +ce569e81ab26f5eb8d922b18be6561af7876c4e8 - optee/optee_os/core/lib/zlib/zconf.h +5121bcf9ae9f1eb58b39c4debbc5931e5be16434 - optee/optee_os/core/lib/zlib/inffast.c +47e5da9b88163c7194af9b7b6a17fb46ca08b009 - optee/optee_os/core/lib/zlib/inflate.h +341003df806d2bcfcbd194fc3f9da99919b918a9 - optee/optee_os/core/lib/zlib/inffast.h +8770ab43c9050b824c646f6e6cee8b3c0628cbda - optee/optee_os/core/lib/zlib/inffixed.h +1e0b1438feffed910661d48b2b793a5f7c308f06 - optee/optee_os/core/lib/zlib/zutil.c +00b226f75f6beab393031f6893b2868c707d0d0c - optee/optee_os/core/lib/zlib/inftrees.c +206b2054814df6c3f42f29c045d584c6a25c462f - optee/optee_os/core/lib/zlib/inflate.c +4192c931405d13fabed42ec8725255502d35fbcc - optee/optee_os/core/lib/zlib/zlib.h +8139ab5dd86e53ccbde7ba4e78200db4cd79f9a9 - optee/optee_os/core/lib/zlib/inftrees.h +36c4f51e48f8320621c5739dd2ee69ef0d973a21 - optee/optee_os/core/lib/zlib/gzguts.h +79b1451ee0197c749cd4f07450ed2d374f1c3cee - optee/optee_os/core/lib/scmi-server/scmi_server.c +619aa8e61beb89b2df060ca24485432e8269b5fd - optee/optee_os/core/lib/scmi-server/include/optee_scmi.h +c05559286b41f00c3815a047a26e80df6785a42b - optee/optee_os/core/mm/core_mmu.c +129dfa30ed6d0f01fa944600085cfb54b0dae9a0 - optee/optee_os/core/mm/mobj.c +7f4fbb1dbd7b0a4a78f67b449a3ec8ed6e2289b2 - optee/optee_os/core/mm/tee_mm.c +fbf52bc1a50fae147acaeca0138d7dc640a88275 - optee/optee_os/core/mm/pgt_cache.c +73be8d9cc10ccf4ecc646ab51ec17b8bbb51177c - optee/optee_os/core/mm/fobj.c +e7f04184eddb0da4969adfcbd5dd4a378d087fca - optee/optee_os/core/mm/vm.c +4c81a53362b3a07b1dabb5a197f0e3ec26117bee - optee/optee_os/core/mm/file.c +62bea91954c0b60ce398bcc52950deef1311beb8 - optee/optee_os/core/pta/device.c +b137817eff91658d19d1a479dee6a84dda10ccbc - optee/optee_os/core/pta/attestation.c +3ea15c610f4ecba8788d1055a06e13c3b6aeea5f - optee/optee_os/core/pta/scp03.c +4b7b26064a5527653817507ced6b5d36e09d75dd - optee/optee_os/core/pta/rtc.c +14015171ba8ab23dce63f6011ecd0899f08137c1 - optee/optee_os/core/pta/hwrng.c +4e1b614df9067b7a1f2158f1d5111c1925483f9b - optee/optee_os/core/pta/apdu.c +6a748b8c571c2b207c9db79b56b491192bf22379 - optee/optee_os/core/pta/gprof.c +a479d607c3f4dcbca4d5d1e9797340ef6e59131d - optee/optee_os/core/pta/scmi.c +b07d570bacd753a4f6c4ddd3730017971f2f9d85 - optee/optee_os/core/pta/widevine.c +8f532c3b41d08bdbee29cdf99e831e9a5652bd71 - optee/optee_os/core/pta/system.c +6284c967a1103f26724ff4dfe45af409bfbbf948 - optee/optee_os/core/pta/secstor_ta_mgmt.c +c8f8fa8bd161af69f46889e90966bef0ad018b68 - optee/optee_os/core/pta/stats.c +4c4029f19bf83df309ffd54d9d525c327ff8a7c7 - optee/optee_os/core/pta/tegra/jetson_ftpm_helper_pta.c +f04e7c33a8c114fd563d57de4d069c6cebd01e0f - optee/optee_os/core/pta/tegra/jetson_user_key_pta.c +9f086ff5817b522588e0b043af390b20bc659347 - optee/optee_os/core/pta/tegra/jetson_t234_decrypt_cpubl_payload.c +186b949fc854bc97be7883a0f85300a6113bce2c - optee/optee_os/core/pta/tegra/jetson_t194_decrypt_cpubl_payload.c +169bda07f69b89df46b79e7a085d3fc44595d2ec - optee/optee_os/core/pta/tegra/include/jetson_decrypt_cpubl_payload.h +c527ed81dee9ab0a7262d28f7a7318bfb152c4da - optee/optee_os/core/pta/tegra/include/jetson_user_key_pta_ftpm.h +434dbf013ffa6633ede1816527dfb82782c3db0d - optee/optee_os/core/pta/tegra/include/jetson_user_key_pta_compute_cmac.h +8c32652450144f8d62ba455a35cede26cedf44c3 - optee/optee_os/core/pta/tests/fs_htree.c +598beefd2c0b1d1ed3caf79b7ee3f6fd4315b410 - optee/optee_os/core/pta/tests/mutex.c +58a21a5d072a642b4650c67cc299e210a254d9fb - optee/optee_os/core/pta/tests/dt_driver_test.c +9d5f604852b526c4c03348962f3d622ead341452 - optee/optee_os/core/pta/tests/invoke.c +773d0fc2245c86d75271917a6eef93910cd5a5f2 - optee/optee_os/core/pta/tests/misc.h +a27586aab31e93cb9ce669c13e202c989d6f3e00 - optee/optee_os/core/pta/tests/lockdep.c +1828d31f10e6236e1f4f6c98f71f34b61827f092 - optee/optee_os/core/pta/tests/misc.c +b939d0c32959ac65dafe67f6019699ab4f194d94 - optee/optee_os/core/pta/tests/aes_perf.c +f76d93f72808e78fe854329128254e40a8ae64ef - optee/optee_os/core/pta/imx/digprog.c +9c77709e56621860013c067a19359bd3f2fb621c - optee/optee_os/core/pta/imx/manufacturing_protection.c +1141e0df408fb0977880fbd63e8a1575a2a81e8d - optee/optee_os/core/pta/imx/ocotp.c +fc52da8f6cfc83dc3606768cd703affc8029c2df - optee/optee_os/core/pta/imx/dek_blob.c +5b825d9894d2ed56396b487aaa3d994d6860b837 - optee/optee_os/core/pta/k3/otp.c +83d3b7f9616db0d5e42b621f55691ec5d505b4dc - optee/optee_os/core/pta/stm32mp/bsec_pta.c +8e4201b982761ca70f6155537299a9fbcdd9555e - optee/optee_os/core/pta/stm32mp/rproc_pub_key.h +e3cc7102b54ea2bb07693ad42f9497a44a93df51 - optee/optee_os/core/pta/stm32mp/remoteproc_pta.c +5d347d3376095cbc05c1ae47cb6d4ac6f74ef5b5 - optee/optee_os/core/pta/bcm/sotp.c +3a98f4eae781f4b50887b79395cb6cefbf957df3 - optee/optee_os/core/pta/bcm/gpio.c +92265a3a661a4862d09043e5c3ed8787895b4d23 - optee/optee_os/core/pta/bcm/bnxt.c +8accf96a33e318180c18fd79729c3476c4e4a567 - optee/optee_os/core/pta/bcm/hwrng.c +c53ce6db2d7519d9bd08c02472fe525fbb768a6c - optee/optee_os/core/pta/bcm/elog.c +1d96880636f5a98568edf08f68e5e4b38291da17 - optee/optee_os/core/pta/bcm/wdt.c +565af249a8ad523f04c21a52b091bb00f021d43d - optee/optee_os/core/tee/tee_cryp_utl.c +792b545f3897e6cf80b0b561c1f99382c02dafe1 - optee/optee_os/core/tee/tee_nvme_rpmb_fs.c +791192c3a090ffefe53650af896cb341e30c6552 - optee/optee_os/core/tee/tee_rpmb_fs.c +40a7130c87b8874c0ff3df4ba6d7ac5ecc7010a1 - optee/optee_os/core/tee/socket.c +3be470d597c40bff1ed4641b735cb7fef3dce6eb - optee/optee_os/core/tee/tee_ree_state.c +e8ee3f02aee406877da4da3ff36dacb130cfab40 - optee/optee_os/core/tee/tee_time_generic.c +a2028063632c8857bed15d993063a7fd353ee9c0 - optee/optee_os/core/tee/tee_cryp_hkdf.c +a1f3d00831693e2b21465993a0b88230998270fd - optee/optee_os/core/tee/fs_htree.c +8462217cd1216cdeb47261930203db704ccd4ed7 - optee/optee_os/core/tee/tee_svc.c +0cdf747942eaeec2f670e600d773b8d1143cc2e8 - optee/optee_os/core/tee/tee_fs_key_manager.c +5be8cb39c5a5a4e02648d219b3f67eacc9868f36 - optee/optee_os/core/tee/tee_ree_fs.c +53578bdbeb3107e8113102750cbc8d8861701bf8 - optee/optee_os/core/tee/tee_pobj.c +3264e7dee283facb91122a3be3a91c34300d49dd - optee/optee_os/core/tee/tee_svc_cryp.c +bbd20680e1d41ecf7f806411c32f0eac33c860f9 - optee/optee_os/core/tee/tee_supp_plugin_rpc.c +8fabba1dda1dee9af15b514f65afdae49ba948ff - optee/optee_os/core/tee/tadb.c +dc4bbc967130baa858c0d97bb72c8d16aeb961d8 - optee/optee_os/core/tee/entry_std.c +fc58bf53b6b42bf286bd64683b86c6d31dc3a517 - optee/optee_os/core/tee/tee_cryp_concat_kdf.c +4ca9c10d9b17380efab8d45d2de31948c98a16e5 - optee/optee_os/core/tee/tee_ta_enc_manager.c +e59e39dfb4986541318ae84e47f44e52afa20b12 - optee/optee_os/core/tee/tee_fs_rpc.c +a1202328842c81639257318e2047a9e13b1802c0 - optee/optee_os/core/tee/uuid.c +dd81c49e2b9da8f822e7246d08cecde9f28fc2a7 - optee/optee_os/core/tee/tee_cryp_pbkdf2.c +4c03723f4ad981f468207f5a6437352c5c87b0db - optee/optee_os/core/tee/tee_svc_storage.c +ee7b25818bd52227343d7f45f5ef5f725be9a89b - optee/optee_os/core/tee/tee_obj.c +d18ce49edc69a8027687b7b43c5d4d36c33cfac3 - optee/optee_os/core/tee/fs_dirfile.c +c62767343baa3f2bbf0bb384fa1feee2ff2784c5 - optee/optee_os/core/arch/riscv/mm/core_mmu_arch.c +a67134011a6bba88ca1207fbcbfe628c0ac0b4ba - optee/optee_os/core/arch/riscv/mm/tlb_helpers_rv.S +4065c59874a936748d321924f558ea342fae8947 - optee/optee_os/core/arch/riscv/tee/entry_fast.c +a141eda98aea803a64ff9542fcd8a574020b418a - optee/optee_os/core/arch/riscv/plat-virt/platform_config.h +159322372864ce9f888c412d5d39c84fda99e290 - optee/optee_os/core/arch/riscv/plat-virt/main.c +5f83776d0c7ce64d6d01df485fd353b7d1d20699 - optee/optee_os/core/arch/riscv/include/sbi.h +56bd7d4c065fb5932029bbc17b96d59a42f34270 - optee/optee_os/core/arch/riscv/include/riscv.h +1223e5cd29f4984ecabe36e78efe63b42f2bb84d - optee/optee_os/core/arch/riscv/include/riscv_macros.S +aaf4ec0db08de01b5e8012ce949710f9dcf0f993 - optee/optee_os/core/arch/riscv/include/encoding.h +f90a39605a177515f57172f8bfcac31468bec502 - optee/optee_os/core/arch/riscv/include/mm/generic_ram_layout.h +fd17c38c386b15bdb4e87b47c4a2fbc2a66e8171 - optee/optee_os/core/arch/riscv/include/mm/core_mmu_arch.h +291fa9f4f92f4c42ffc5713f505e357cd3d7e9c1 - optee/optee_os/core/arch/riscv/include/tee/optee_abi.h +3e29f4f935b7151c6a16978c5c3d956c8b1d3be2 - optee/optee_os/core/arch/riscv/include/tee/teeabi_opteed.h +5eaa1cef4d6a42985aca8a8308f4f1f732ce71b0 - optee/optee_os/core/arch/riscv/include/tee/teeabi_opteed_macros.h +b66cd21c1e374e71627820cd3c2a6621a7212f89 - optee/optee_os/core/arch/riscv/include/tee/entry_fast.h +0c4cbba16aac1f17267a36ecda588756cfd3277c - optee/optee_os/core/arch/riscv/include/kernel/clint.h +d331fbb22fc7d3164c7b2d0ba55f2fec013d9cf4 - optee/optee_os/core/arch/riscv/include/kernel/thread_private_arch.h +8cc637a0b1fa21930752c33d1cc58d647bc81179 - optee/optee_os/core/arch/riscv/include/kernel/arch_scall.h +826a1d5fe853d5d25e39ce6e66d577e479b11016 - optee/optee_os/core/arch/riscv/include/kernel/stmm_sp.h +9fe08ff654da68413ec097e684cf2d6a39de3b56 - optee/optee_os/core/arch/riscv/include/kernel/misc_arch.h +b3be5129fb98824666e9dbe5734dd1f811ab97d4 - optee/optee_os/core/arch/riscv/include/kernel/cache_helpers_arch.h +359cfc0da1c4cc03f466ebe78020a796e736dd55 - optee/optee_os/core/arch/riscv/include/kernel/user_access_arch.h +0152544509ec093752ad771824add96b3ed7a04c - optee/optee_os/core/arch/riscv/include/kernel/tee_l2cc_mutex.h +e363a3270c54efb0764aceaa2210b94a552269b1 - optee/optee_os/core/arch/riscv/include/kernel/tlb_helpers.h +b7fa8ca503a4c669510829a0aa242d662cb674f7 - optee/optee_os/core/arch/riscv/include/kernel/delay_arch.h +9ff069cbffd055e8fc24029279eafec7c295b34a - optee/optee_os/core/arch/riscv/include/kernel/secure_partition.h +f9ad119abcc0fb84ce214fa4cc0d9f507c860d7f - optee/optee_os/core/arch/riscv/include/kernel/thread_arch.h +f4d75a0309e2040dbb1ca13717a13dfa6be01e03 - optee/optee_os/core/arch/riscv/plat-spike/kern.ld.S +fbcbb1531e4e70ea9aad7289c3cda3efc1eed54f - optee/optee_os/core/arch/riscv/plat-spike/platform_config.h +944299de7735a170cb3eccd15eec91c07a5e7672 - optee/optee_os/core/arch/riscv/plat-spike/main.c +359b98fad7ce1225b5fb675394acb32df9e74380 - optee/optee_os/core/arch/riscv/plat-spike/drivers/htif.h +558db749b68778acc836e96fc170bc823ab0e441 - optee/optee_os/core/arch/riscv/plat-spike/drivers/htif.c +09e09dcb96e69d3d3ea89c3997d9340fe33f53da - optee/optee_os/core/arch/riscv/kernel/semihosting_rv.S +53456fe6fd16922b93fddbb3e177d68557843d5d - optee/optee_os/core/arch/riscv/kernel/tee_time_rdtime.c +b163d4b03cb454500769933734d6cfc2f5b50155 - optee/optee_os/core/arch/riscv/kernel/entry.S +ef752dba0afbc3441defa0ce7f596275e4eacdf6 - optee/optee_os/core/arch/riscv/kernel/idle.c +de03d1758884a3e0e0f7ea910139d312790963d1 - optee/optee_os/core/arch/riscv/kernel/arch_scall_rv.S +6543d720eb1111ece07baa5ef24e17f5166c3c66 - optee/optee_os/core/arch/riscv/kernel/thread_rv.S +b3ad33b5f5481b84a1a568cfec88d6bce78f4e40 - optee/optee_os/core/arch/riscv/kernel/thread_optee_abi.c +137070765c0c55bc0ad0e2a1c59919088ed69e85 - optee/optee_os/core/arch/riscv/kernel/arch_scall.c +0f43c49d2273009469484b2cc76a2b941e4d9d68 - optee/optee_os/core/arch/riscv/kernel/cache_helpers_rv.S +d7ea3b838aae7c777e6db63f192267e50bf10cec - optee/optee_os/core/arch/riscv/kernel/sbi_console.c +7c20c3e99ed3f34f87513b8b6648ce62062805f3 - optee/optee_os/core/arch/riscv/kernel/thread_optee_abi_rv.S +937e79d309f828a69b64d6998e80595aa1eea7b5 - optee/optee_os/core/arch/riscv/kernel/abort.c +9fc8bce83666ebb14ca70e1a2140db274ba5f0c1 - optee/optee_os/core/arch/riscv/kernel/thread_arch.c +848daa8b88efcef6b41ae9cd1598e5aa1d24574d - optee/optee_os/core/arch/riscv/kernel/asm-defines.c +0de310d21aaf90056a2327f208ed61a659cf483f - optee/optee_os/core/arch/riscv/kernel/sbi.c +df7133315b272219ed0615fbcd0b9f2770f8c32d - optee/optee_os/core/arch/riscv/kernel/unwind_rv.c +7f1c0c47cf8d4455d3bb56977982a34a008a7fbe - optee/optee_os/core/arch/riscv/kernel/spinlock.S +6309bad6a7c50cedfe6901944f520790b07f26b1 - optee/optee_os/core/arch/riscv/kernel/kern.ld.S +f3714d71c5a47d36649c0a35563b87efce775068 - optee/optee_os/core/arch/riscv/kernel/boot.c +4e0482b88d52f8a7d6adf974d0e5015f13872f65 - optee/optee_os/core/arch/arm/plat-rcar/hw_rng.c +15d328d6ef35c2f6a4c4f5a69f4eb2a571802c1c - optee/optee_os/core/arch/arm/plat-rcar/romapi_call.S +29cb5b650192d2e9a8bc4b01921c70539825e413 - optee/optee_os/core/arch/arm/plat-rcar/romapi.c +9ca9f50ac43c9276ee67375c8e915f0827e349d9 - optee/optee_os/core/arch/arm/plat-rcar/core_pos_a64.S +b713d037582ce7c9f21402a91665b067ed931ff7 - optee/optee_os/core/arch/arm/plat-rcar/rcar.h +f8a2662937d568146b977cdedf2e268e5b1f6b6e - optee/optee_os/core/arch/arm/plat-rcar/romapi.h +e5ec049ffef670a29b7cade4d9d9f96abef549f6 - optee/optee_os/core/arch/arm/plat-rcar/platform_config.h +d99c2594d96797d631564d55d1cec73d69073a16 - optee/optee_os/core/arch/arm/plat-rcar/main.c +105fcd115c8f37f13c3f1617c6e564dce1a1a50f - optee/optee_os/core/arch/arm/plat-stm32mp1/reset.S +41fc0d480726ccac287c2341b62956a102d2b134 - optee/optee_os/core/arch/arm/plat-stm32mp1/boot_api.h +166fbca392a757857b207b6a39177ebdae48c2a1 - optee/optee_os/core/arch/arm/plat-stm32mp1/stm32_util.h +4cd706376b2b8e9f29529251f6e8dd0f97b45a2d - optee/optee_os/core/arch/arm/plat-stm32mp1/link_dummies_paged.c +7a02cc2b686285ca057686052ccf437bc2441e81 - optee/optee_os/core/arch/arm/plat-stm32mp1/scmi_server.c +b2bae4d35241a08ab393a13a463719aacabe7159 - optee/optee_os/core/arch/arm/plat-stm32mp1/shared_resources.c +5b41538b0faeb38ba559f5e71fc8c7fb4b808593 - optee/optee_os/core/arch/arm/plat-stm32mp1/platform_config.h +ee9a76fa832621b03cd35d4e26d326eb11e278aa - optee/optee_os/core/arch/arm/plat-stm32mp1/plat_tzc400.c +92c2966c3109fd535677e7f5a34fd89106328ea6 - optee/optee_os/core/arch/arm/plat-stm32mp1/main.c +8e7e39483872171d059e87be0b70594fb8a2abaf - optee/optee_os/core/arch/arm/plat-stm32mp1/pm/psci.c +a1238faa3df41c0c66412e3b032255e1cd4988eb - optee/optee_os/core/arch/arm/plat-stm32mp1/scripts/stm32image.py +0c65b2a9483053f11245b70f723294b6d32fea5e - optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_syscfg.h +af1241bfcd71e1d8950df5ee76e9cd120d9a67e8 - optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.h +f1cfb11d1e643d8118b07e9de2b36797b20c4cc2 - optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.c +6f513d1b2ba687dd8a5d3d5b3942d070b8475b3f - optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_syscfg.c +0a5b02ff39cea084c1bafb0169edd9f4a643592b - optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.h +a3ac99fd762c9216188d37d084dd70008fbe1199 - optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_etzpc.h +8e140261281a08779ff3209432e4170bf4ea066b - optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c +4e92814caf4d208f3424697ce4a54cbceba75632 - optee/optee_os/core/arch/arm/plat-stm32mp1/nsec-service/stm32mp1_svc_setup.c +536663cb01d75d67a4021fe8314c5ae79909dbd8 - optee/optee_os/core/arch/arm/plat-stm32mp1/nsec-service/stm32mp1_smc.h +e7ec6cb3b0018db5664ccd87d3ab1529e5d5713e - optee/optee_os/core/arch/arm/plat-stm32mp1/nsec-service/bsec_svc.h +d335d9bb50b2453d365ca88f3f18520fdd0a1086 - optee/optee_os/core/arch/arm/plat-stm32mp1/nsec-service/bsec_svc.c +81eaad1a97f464cb81867fe716edddc6a94c14a2 - optee/optee_os/core/arch/arm/plat-sam/platform_sama7g5.c +b04aabae313af1ab007337548c8d3c3340147467 - optee/optee_os/core/arch/arm/plat-sam/sam_sfr.c +05ae55b82f1b86db41cd5dec856b760b9cbac2db - optee/optee_os/core/arch/arm/plat-sam/sam_sfr.h +6bb95a72f4df9441141153c1f593d952cdbd5088 - optee/optee_os/core/arch/arm/plat-sam/platform_sama5d2.c +9e03ab42551128401c4786a75250b1db1cd4922d - optee/optee_os/core/arch/arm/plat-sam/sam_pl310.c +c85debf71cacdc0e53e262424984cec5fece885f - optee/optee_os/core/arch/arm/plat-sam/sama5d2.h +66bba258091108cedb62f43234a3e9fa874dbd85 - optee/optee_os/core/arch/arm/plat-sam/matrix.h +c6124d9de9443cdbc216ffbbe7eaa083e321867e - optee/optee_os/core/arch/arm/plat-sam/matrix.c +d452ceba090437688ae1658171bcda10e43263b4 - optee/optee_os/core/arch/arm/plat-sam/tz_matrix.h +087ee14fbb7d4606fe2f1b748c159783d18a6ec5 - optee/optee_os/core/arch/arm/plat-sam/scmi_server.c +cb565968e3bdcd440dd373b4b88bd1e995c64e08 - optee/optee_os/core/arch/arm/plat-sam/sama7g5.h +e41104fa5f74b992b4dbd859dd2a1b4b3b2bb913 - optee/optee_os/core/arch/arm/plat-sam/freq.c +48e145a8a02773f53e3afc68f9d44f1aab5f8be5 - optee/optee_os/core/arch/arm/plat-sam/platform_config.h +51975d5a6d4516cacb42fd70885043c1f8b6fbf1 - optee/optee_os/core/arch/arm/plat-sam/pm/psci.c +0dfa109395fbc4b3c968756ccf16d0e1d8cef554 - optee/optee_os/core/arch/arm/plat-sam/nsec-service/sm_platform_handler.c +c11e25489752cfc848301693c08dff59b589ed3f - optee/optee_os/core/arch/arm/plat-sam/nsec-service/smc_ids.h +49dbe1b862ab1676a3186ddc9f6c7650820902d7 - optee/optee_os/core/arch/arm/plat-totalcompute/platform_config.h +d07921192fb4097f0da3129fcfc442229f93154f - optee/optee_os/core/arch/arm/plat-totalcompute/main.c +00e4e12466db95649e17c7dce132fd03e23b837c - optee/optee_os/core/arch/arm/plat-totalcompute/fdts/optee_sp_manifest.dts +46a2594f3aa4681ffd83538ff397c8e3bf3974ca - optee/optee_os/core/arch/arm/plat-rockchip/grf.h +384be00889fd82aa785e7d07fa9f819c764557c4 - optee/optee_os/core/arch/arm/plat-rockchip/platform.h +82976a1c26f0098dc91782fdd667476feac53253 - optee/optee_os/core/arch/arm/plat-rockchip/platform_px30.c +24c8244ba3044caed1943ad05138413c6db6ab2e - optee/optee_os/core/arch/arm/plat-rockchip/platform_rk322x.c +e8c669f6cd515061ddc1fac878644149427040c8 - optee/optee_os/core/arch/arm/plat-rockchip/psci_rk322x.c +7993e64e5bfd2d72ce89ef822b3a49a1381e8c69 - optee/optee_os/core/arch/arm/plat-rockchip/platform.c +1853ca66ab2f40919fcb69448e1b866eb2bc9e4b - optee/optee_os/core/arch/arm/plat-rockchip/core_pos_a32.S +971d879311868f34f4ebf712ba6de5f9f0ea6f35 - optee/optee_os/core/arch/arm/plat-rockchip/plat_init.S +de4933508c95b4cc044fec515f190d8ff6ebfdc0 - optee/optee_os/core/arch/arm/plat-rockchip/common.h +b74b363d6e2a566d4a03278aaacaf9391d505a44 - optee/optee_os/core/arch/arm/plat-rockchip/cru.h +5c98cb66829c84f0e07676a8a66b6883c782b877 - optee/optee_os/core/arch/arm/plat-rockchip/platform_rk3399.c +86e640e06414afd26ad833d31867572408fd251a - optee/optee_os/core/arch/arm/plat-rockchip/platform_config.h +4d0bc50554ebec63e6fb62a4772b77b82ec501cd - optee/optee_os/core/arch/arm/plat-rockchip/main.c +a1a353aa32ebd77dd5c2966ff38e024d0e8938bb - optee/optee_os/core/arch/arm/plat-k3/platform_config.h +882cb529fe6df1cf2eed27c1d61be5069bf860a6 - optee/optee_os/core/arch/arm/plat-k3/main.c +6a4aeba37a7be60d63bfeff66846d3a0c9cfa796 - optee/optee_os/core/arch/arm/plat-k3/drivers/sa2ul_rng.c +167f0568d280c4eaa824b31126105d0f2a0d3f89 - optee/optee_os/core/arch/arm/plat-k3/drivers/ti_sci_protocol.h +96e780127fe944086f4e057b31baea9b2fa125e2 - optee/optee_os/core/arch/arm/plat-k3/drivers/sec_proxy.h +31bc4f9734a7ba434af482766846ba6cfc120a82 - optee/optee_os/core/arch/arm/plat-k3/drivers/sa2ul.c +7e9288bc18f6a5ae30fd66d3f04abd5a43971250 - optee/optee_os/core/arch/arm/plat-k3/drivers/ti_sci.h +2020136e5c1ef325c92bc319ebb5f582d8d1b447 - optee/optee_os/core/arch/arm/plat-k3/drivers/sa2ul.h +259f0d13481825cf2b56b06524f54b93aaf8abeb - optee/optee_os/core/arch/arm/plat-k3/drivers/sec_proxy.c +08166357e31dfc2ba303f00ae83b8bb6cfb13c3f - optee/optee_os/core/arch/arm/plat-k3/drivers/ti_sci.c +4210a13d7617d8becb16ca879152a64ba12e99a5 - optee/optee_os/core/arch/arm/dts/sama5d2.dtsi +abbe0e5a7c63995c207b1995649e3a6ed6b4221a - optee/optee_os/core/arch/arm/dts/stm32mp15xc.dtsi +d6dbda8b14af74b3a63db810c4c4ed53bfb097bc - optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcom-som.dtsi +80e5d5425cd21aaac73665beba3aa827a985f10e - optee/optee_os/core/arch/arm/dts/stm32mp13-pinctrl.dtsi +d23af59b64d5380f6f9c8ca37a1a5b1af3e9f93c - optee/optee_os/core/arch/arm/dts/at91-sama5d27_som1_ek.dts +41aa3da18dcb49b316aefc9ad5eed7dc2664dabc - optee/optee_os/core/arch/arm/dts/stm32mp157c-ev1.dts +23b592b2e03dead1636f2110cd64531ec92bf807 - optee/optee_os/core/arch/arm/dts/stm32mp133.dtsi +6785fab64335569d7bd355648ab3eea10428ba95 - optee/optee_os/core/arch/arm/dts/stm32mp135f-dk.dts +6ed7397e2751cabb21fc7e87b53983b9117d2e26 - optee/optee_os/core/arch/arm/dts/sama5d2-pinfunc.h +ff54b38797ff11d07b4812b54de0c54381e5c944 - optee/optee_os/core/arch/arm/dts/stm32mp255.dtsi +ed24a9b0089183c2059975547510395e1e35c43f - optee/optee_os/core/arch/arm/dts/stm32mp257f-ev1-ca35tdcid-rif.dtsi +361479ac7684841706aca2fdb4c3d2c9f8e0e13e - optee/optee_os/core/arch/arm/dts/stm32mp15xxac-pinctrl.dtsi +409d4ed71faffbe877746442e5f91e568dc7df1e - optee/optee_os/core/arch/arm/dts/stm32mp25xxai-pinctrl.dtsi +c801e4c35f00786835f0cd63b71559a146086866 - optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcor-io1v8.dtsi +ed30a800e2e2a388fbecc51158b47a9cc3921038 - optee/optee_os/core/arch/arm/dts/stm32mp157c-dk2.dts +d631d38e887afb5747ac43a31fbfa52feff971c1 - optee/optee_os/core/arch/arm/dts/fsl-lx2160a.dtsi +731b9a6acef7c38b916dc026ccdb6d9fab7a7528 - optee/optee_os/core/arch/arm/dts/stm32mp25-pinctrl.dtsi +db15a31ad3135aacca1c525a09c102593c0f1bfb - optee/optee_os/core/arch/arm/dts/stm32mp157a-dk1-scmi.dts +6c18e9690a909c9b4898d1d609cdf3874e22d19a - optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcor-avenger96.dtsi +d26bbcf985b7523a6af715be4feb22233be74ba5 - optee/optee_os/core/arch/arm/dts/stm32mp15xxaa-pinctrl.dtsi +fb4be0e25bdca79fcf443034897f81e669e42d88 - optee/optee_os/core/arch/arm/dts/fsl-lx2160a-qds.dts +642045067c7bfc99b19f317cb3af060f111d3f58 - optee/optee_os/core/arch/arm/dts/stm32mp131.dtsi +0c1276612681bf9f22517513242e678c22551542 - optee/optee_os/core/arch/arm/dts/stm32mp153.dtsi +8b0ff69354da1ce17daa0d18c67f38fdd3bcdd7c - optee/optee_os/core/arch/arm/dts/stm32mp135.dtsi +fad0980d9bf80c0fc0a8dc20548c3d6d65a9c4ee - optee/optee_os/core/arch/arm/dts/stm32mp257.dtsi +414473317258a6e6a9fe63c8f9b0125faf78845b - optee/optee_os/core/arch/arm/dts/stm32mp253.dtsi +d8011a03e68d20864da688cd4e37f5f00fceb92c - optee/optee_os/core/arch/arm/dts/stm32mp15xx-dkx.dtsi +cc1a5787a5c707145c1d43a2dafde4081469219f - optee/optee_os/core/arch/arm/dts/stm32mp15-pinctrl.dtsi +e793accc60529af1c41651063de57ef9cd0a0b5e - optee/optee_os/core/arch/arm/dts/stm32mp157a-dhcor-avenger96.dts +af297633ee1dd3ddc9a4e06782e0390214b9c3dd - optee/optee_os/core/arch/arm/dts/stm32mp251.dtsi +c07147cb14bc871e069f3be8248fc2c79e311949 - optee/optee_os/core/arch/arm/dts/stm32mp15xxad-pinctrl.dtsi +6f054373484e9a7e6b398ac064c824e838b666e0 - optee/optee_os/core/arch/arm/dts/at91-sama7g54_ek.dts +1985ea8670dc7c7937541f6b2da9c30c41ee000d - optee/optee_os/core/arch/arm/dts/at91-sama5d27_wlsom1.dtsi +62934ca38185da79af035ba4a82f62ae3a33f4ac - optee/optee_os/core/arch/arm/dts/hikey.dts +e4fa73abdd45e453c0b16f0617ff2e73f505c20d - optee/optee_os/core/arch/arm/dts/stm32mp25xc.dtsi +9d307000551e74012b0ab3eecedcce5e21315f12 - optee/optee_os/core/arch/arm/dts/stm32mp25xxal-pinctrl.dtsi +28f113e9a075bf7903cddddaacfda1cbe77f6947 - optee/optee_os/core/arch/arm/dts/stm32mp151.dtsi +ce82c06ac99261e680a62585d80c90e9dfe941fb - optee/optee_os/core/arch/arm/dts/stm32mp157c-dhcom-pdk2.dts +9d307000551e74012b0ab3eecedcce5e21315f12 - optee/optee_os/core/arch/arm/dts/stm32mp25xxak-pinctrl.dtsi +ad3b5f3ede872c44e014eb6ca5a69329195968a6 - optee/optee_os/core/arch/arm/dts/at91-sama5d27_wlsom1_ek.dts +676f90d7c25eb035af4475d83d6e355f07ac0634 - optee/optee_os/core/arch/arm/dts/embedded_dtb_test.dts +d7230a1568081b9a39b151bbe38f188691b2b84b - optee/optee_os/core/arch/arm/dts/fsl-lx2160a-rdb.dts +b90fd277b20c2235559780745427fce254204eb5 - optee/optee_os/core/arch/arm/dts/sama7g5-pinfunc.h +e4c09d7943a625db6187d1b74f0990a9918b7663 - optee/optee_os/core/arch/arm/dts/dt_driver_test.dtsi +c8ec256ae55cb6c849aa51624b9974259884b159 - optee/optee_os/core/arch/arm/dts/at91-sama5d2_xplained.dts +e4fa73abdd45e453c0b16f0617ff2e73f505c20d - optee/optee_os/core/arch/arm/dts/stm32mp25xf.dtsi +0740af056d7271572901b9dc8ed2822af6546c20 - optee/optee_os/core/arch/arm/dts/stm32mp13xc.dtsi +8275c3486f497663a76c22d5ef4895c0c6ef6721 - optee/optee_os/core/arch/arm/dts/stm32mp157c-ed1-scmi.dts +9dea507c72c9eec09336578711a432b198478a56 - optee/optee_os/core/arch/arm/dts/at91-sama5d27_som1.dtsi +e4418357621a953d3e4b62676dcd52da1e958777 - optee/optee_os/core/arch/arm/dts/stm32mp157a-dk1.dts +0740af056d7271572901b9dc8ed2822af6546c20 - optee/optee_os/core/arch/arm/dts/stm32mp13xf.dtsi +ce5455a1f2afa724bbdec2b0c14f79a6bed0b1e4 - optee/optee_os/core/arch/arm/dts/stm32mp257f-ev1.dts +bceeab3e2319f80b613c6ccaefc42154a2d76148 - optee/optee_os/core/arch/arm/dts/stm32mp157c-ev1-scmi.dts +1b30098b442b7f3ded006ca7b7e80e963cc9fc6f - optee/optee_os/core/arch/arm/dts/stm32mp157c-dk2-scmi.dts +9f93f18baccbb7718af6c571e70dfecb3529b694 - optee/optee_os/core/arch/arm/dts/stm32mp15xxab-pinctrl.dtsi +b318d72ed3eee6e4bd7d8ecdb5b1eba8dfc31f89 - optee/optee_os/core/arch/arm/dts/stm32mp157.dtsi +5af1e6fee13bee69410732af10981f063661c519 - optee/optee_os/core/arch/arm/dts/stm32mp157c-ed1.dts +0cc38427ae1b225d88d000f9438b7cc34e883b30 - optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcom-pdk2.dtsi +6cec48599b2381a43a302f390c48d557ba064697 - optee/optee_os/core/arch/arm/dts/sama7g5.dtsi +0f41a6ee8e489bec0d79a976edb540945506d498 - optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcor-som.dtsi +9c453b2fc11aaa02877de7f09472e5d5fd74cbea - optee/optee_os/core/arch/arm/mm/mobj_ffa.c +864e848f1defa3de1e5572ca3d95b4e44792d0f8 - optee/optee_os/core/arch/arm/mm/core_mmu.c +0800ed2cdb60a7e006e239b48c9a13db03283eb9 - optee/optee_os/core/arch/arm/mm/mobj_dyn_shm.c +feeeaeae7f26fdd8673fba9c1c90c5997766aad6 - optee/optee_os/core/arch/arm/mm/core_mmu_lpae.c +57677b0d6e625b07083889d81e304b9c700c5c13 - optee/optee_os/core/arch/arm/mm/tee_pager.c +e6f86e9d7f1972ae55f5ca9938620da5246c59b8 - optee/optee_os/core/arch/arm/mm/sp_mem.c +48384d9c72c1c7a6dd5c2b5395d330221188e699 - optee/optee_os/core/arch/arm/mm/core_mmu_v7.c +ac0abfb473091ac6c14804be7ef4894e137990ee - optee/optee_os/core/arch/arm/plat-mediatek/platform_config.h +4af0e09221ce2161556eec932ee5c97df9943156 - optee/optee_os/core/arch/arm/plat-mediatek/main.c +e1fca0dd2d7d34c4bab110dfb24010cbd1538b8d - optee/optee_os/core/arch/arm/tee/entry_fast.c +df18a9464597e6dbc2844ec1e5d735db00c74f37 - optee/optee_os/core/arch/arm/tee/svc_cache.c +176317554a2541fa4a9d6504dbe52227bdcb5083 - optee/optee_os/core/arch/arm/tee/cache.c +6631e40f0ad62f389ac0fc0c59e142b9313bb246 - optee/optee_os/core/arch/arm/plat-aspeed/core_pos_a32.S +c2a044439dfe43a71ae10d3b6dac3011aa488674 - optee/optee_os/core/arch/arm/plat-aspeed/platform_ast2600.c +70fb1d819f629339d313a83ea0f8efa6e4fa80ca - optee/optee_os/core/arch/arm/plat-aspeed/platform_ast2700.c +b8d3a5d517e206505803d023df167bb48a6eacb5 - optee/optee_os/core/arch/arm/plat-aspeed/platform_config.h +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 +194b1c2efb4a1b60d27d88813f6317cca0a978ce - optee/optee_os/core/arch/arm/plat-tegra/platform_config.h +d448b3370e0f8e7cbe52eefd2d149899a6ab0860 - optee/optee_os/core/arch/arm/plat-tegra/main.c +390b45a60cc4219e64e58f0ca0ea2890dc31a351 - optee/optee_os/core/arch/arm/plat-vexpress/vendor_props.c +178685f16c79b3f0dd48d1b8fb551d428ab67b68 - optee/optee_os/core/arch/arm/plat-vexpress/juno_core_pos_a32.S +cbbb4b7ba94d66daba35e4e8de0e1ea8f3975534 - optee/optee_os/core/arch/arm/plat-vexpress/juno_core_pos_a64.S +00d480f375e00da8a39d12face3416dc339d7205 - optee/optee_os/core/arch/arm/plat-vexpress/platform_config.h +baaed900d9ea88c65994dfc76dbe982ffbbfb5ad - optee/optee_os/core/arch/arm/plat-vexpress/main.c +c043a9411306559a982b5d09ae419821ff026bd0 - optee/optee_os/core/arch/arm/plat-uniphier/kern.ld.S +11ce785f6bdd56fdc8b32c6c2174a9b49b96b230 - optee/optee_os/core/arch/arm/plat-uniphier/platform_config.h +2c699c471ccb146cc88b3899204cbdd9d4fd82d6 - optee/optee_os/core/arch/arm/plat-uniphier/main.c +1cea08afcf4cab7bbff31ea3666c5360c4c03498 - optee/optee_os/core/arch/arm/include/arm32_macros_cortex_a9.S +236e177873dbb765f512f6690ca9df800109edb4 - optee/optee_os/core/arch/arm/include/arm64.h +c24a0141912421b79a8ecb62ec4ee5d10c8f5d11 - optee/optee_os/core/arch/arm/include/arm32.h +55298b41d3e8800e2aeebd746e9e1371142fbd6e - optee/optee_os/core/arch/arm/include/smccc.h +12dc0bca72b62cb9e340cb631b2cbab3bf9b26fc - optee/optee_os/core/arch/arm/include/arm64_macros.S +ff294f026e09453cbd1ffb3cbc764befc573676c - optee/optee_os/core/arch/arm/include/arm32_macros.S +33a023b2aefc347327909bc18584a5a7f7c96d5f - optee/optee_os/core/arch/arm/include/arm.h +6f4f3bf783228669c7e3f15094154e9affc48745 - optee/optee_os/core/arch/arm/include/optee_ffa.h +ef7bffd960c06d3d1f3248123500188bfb08cd13 - optee/optee_os/core/arch/arm/include/pta_stmm.h +4a7c4dda42996356c37cb094d4908f62d0ab1bd4 - optee/optee_os/core/arch/arm/include/ffa.h +33da86787f5ed31b247e1b8f9b33f6e4346fe53f - optee/optee_os/core/arch/arm/include/mm/generic_ram_layout.h +79775424a3d2afb3c555a91a210974e20db667ca - optee/optee_os/core/arch/arm/include/mm/core_mmu_arch.h +36508e4fbdf66e9683c7425ff68edf20b89d4243 - optee/optee_os/core/arch/arm/include/tee/entry_fast.h +4771b6a98c18654bdf73d522fbadb6ba28acb94f - optee/optee_os/core/arch/arm/include/sm/teesmc_opteed.h +b99db7102beabc3103377efbcd2cb4f144d615f6 - optee/optee_os/core/arch/arm/include/sm/watchdog_smc.h +913aa87cc293d3fcebd5bb787ee5da1e8af74be2 - optee/optee_os/core/arch/arm/include/sm/std_smc.h +f98998e892ec280bcd9da125164c5462995da079 - optee/optee_os/core/arch/arm/include/sm/teesmc_opteed_macros.h +d135a39b3545929f32e6c75c5c6ee45eb44e5a30 - optee/optee_os/core/arch/arm/include/sm/optee_smc.h +c3cff2cbe62224e1869a92e1b246525bab44944c - optee/optee_os/core/arch/arm/include/sm/pm.h +28cac67ced3db8dcaccca1fe953dde17f3401ba9 - optee/optee_os/core/arch/arm/include/sm/psci.h +eb652901568dbd1107a5a134f53d5741b458f453 - optee/optee_os/core/arch/arm/include/sm/sm.h +52885058120498a8199e4cb48f05ed7a3e6ed510 - optee/optee_os/core/arch/arm/include/kernel/thread_private_arch.h +b3b756fb7bc39e3f2db4127b0ae7461715f6b08b - optee/optee_os/core/arch/arm/include/kernel/spmc_sp_handler.h +daca510172fc09d7f8395b9e4700f1e76edd9629 - optee/optee_os/core/arch/arm/include/kernel/thread_spmc.h +34937789ac227f638211cfec7cb102dcffe2e120 - optee/optee_os/core/arch/arm/include/kernel/tz_ssvce_def.h +2360143179a1f2cfd4a3cbbbc03448bb6790d698 - optee/optee_os/core/arch/arm/include/kernel/arch_scall.h +b95d779051d2b0e70152491dc1046ef721584d7a - optee/optee_os/core/arch/arm/include/kernel/stmm_sp.h +2cb8761a88828b0812171b4a8fb7fc6338baa169 - optee/optee_os/core/arch/arm/include/kernel/misc_arch.h +59802332e69d96bb3641667a395d02f3c2fcd82f - optee/optee_os/core/arch/arm/include/kernel/cache_helpers_arch.h +621b56388a4696754f95b4599e1822d9a34a412c - optee/optee_os/core/arch/arm/include/kernel/vfp.h +bcf79acc39a9f4ce8fdd50e3929bba0bceaf33aa - optee/optee_os/core/arch/arm/include/kernel/user_access_arch.h +9723fb1cc272c7203c2e914cc6186ae2098e80bf - optee/optee_os/core/arch/arm/include/kernel/tee_l2cc_mutex.h +524a5a3c2a8e9d1c2d5a74c054a5465f28328abf - optee/optee_os/core/arch/arm/include/kernel/tz_proc_def.h +787920f87e2f8f5b90ab5a7dbb652cdcac005aa8 - optee/optee_os/core/arch/arm/include/kernel/tlb_helpers.h +bd02afc86bd0e2a2d5b96382da5b08872e3704b3 - optee/optee_os/core/arch/arm/include/kernel/delay_arch.h +ccc12fd93eb51399e2102d7549c3460ce011b98e - optee/optee_os/core/arch/arm/include/kernel/tz_ssvce_pl310.h +88697bcdf5234c2ad97597d4455f819c4c13797e - optee/optee_os/core/arch/arm/include/kernel/secure_partition.h +c36bfdcd6ad5e85e7f084678b7dc5595db7639ae - optee/optee_os/core/arch/arm/include/kernel/thread_arch.h +9397b11c32fdff7d6f2fb9203459b016a3dc0861 - optee/optee_os/core/arch/arm/include/crypto/ghash-ce-core.h +c020f068ad8593457e743ff0430d6a3cd685e142 - optee/optee_os/core/arch/arm/include/scmi/scmi_server.h +6c637d1038773281e56bbbd0e1381510508531cd - optee/optee_os/core/arch/arm/plat-synquacer/rng_pta.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 +63b965066fdfe0c218542a9cc90635f1177300d8 - optee/optee_os/core/arch/arm/plat-synquacer/main.c +dd54ce3d620f2b22180ef201aeecf74b5b4480ad - optee/optee_os/core/arch/arm/plat-rzg/platform_config.h +8c4023604f9a8209cc2f3fbc55da146ee176f62e - optee/optee_os/core/arch/arm/plat-rzg/main.c +435d5321e6d484c095ede7a5b320ec92fddb3025 - optee/optee_os/core/arch/arm/plat-bcm/bcm_elog.c +3d4f18ba7a9634be9a46f900264cb0132fd65654 - optee/optee_os/core/arch/arm/plat-bcm/bcm_elog.h +db3ddcb5c48ff30c64e8b561ed5300400d67bca1 - optee/optee_os/core/arch/arm/plat-bcm/crc32.c +92cb86eafac038fc02be252efc14c3e3316f27af - optee/optee_os/core/arch/arm/plat-bcm/crc32.h +0b99d0c7135e7f0002ef7a51d63461307e66203b - optee/optee_os/core/arch/arm/plat-bcm/platform_config.h +43a45ac90d01fd0045318dc972f78f0bf1b526ba - optee/optee_os/core/arch/arm/plat-bcm/main.c +d15ae1ce071edbfc8d4d4de7c944cb1d8712136e - optee/optee_os/core/arch/arm/sm/sm.c +0fbfd45981f9512d688a49c32add4297540c689e - optee/optee_os/core/arch/arm/sm/pm_a32.S +bbd1df35108340d6d4e6179926681fb794f8ce12 - optee/optee_os/core/arch/arm/sm/sm_private.h +9421c26b6ce38f1d5da0e2f431afc0cab732f0e6 - optee/optee_os/core/arch/arm/sm/std_smc.c +79b02c9017b471e73d8c11acc7f91278ec851f2b - optee/optee_os/core/arch/arm/sm/pm.c +615d9401894c37dec5e5ebe9bcdb678df854564e - optee/optee_os/core/arch/arm/sm/psci-helper.S +45960371e7a1224c4d067ff3c172952b7d616998 - optee/optee_os/core/arch/arm/sm/sm_a32.S +8a9cd4bad5748dac76110944be1fb3442e98b2f6 - optee/optee_os/core/arch/arm/sm/psci.c +e2b43db2de0208697b4c88f2f0562d58a4b0b2fb - optee/optee_os/core/arch/arm/plat-d02/platform_config.h +64f5feb8d512291b20a4f975aaf809383b8501f9 - optee/optee_os/core/arch/arm/plat-d02/main.c +2a0bf39e0ef3f1dfa764058f0142b54a53a92006 - optee/optee_os/core/arch/arm/plat-ti/api_monitor_index_a9.h +ec14532de7ea2afbf4bb14220372faf052e0d77c - optee/optee_os/core/arch/arm/plat-ti/sm_platform_handler_a9.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 +188877287aafc257998231f234a1a79a4886c0af - optee/optee_os/core/arch/arm/plat-ti/a9_plat_init.S +f185f9e1ea859d9f4233cffc8c78fcbe72e4c090 - optee/optee_os/core/arch/arm/plat-ti/platform_config.h +9925b7637fef70a5a09336acc3facf8f32a968cc - optee/optee_os/core/arch/arm/plat-ti/main.c +608a97cee50965f940169862e6754dd17612fadf - optee/optee_os/core/arch/arm/plat-ti/api_monitor_index_a15.h +8fa033ec5237e06aef907c0f641f208388793c26 - optee/optee_os/core/arch/arm/plat-poplar/hi3798cv200.h +d4139567b62848e1c43b6759cd767e034e10db73 - optee/optee_os/core/arch/arm/plat-poplar/platform_config.h +65c024516806f7b43dd1ecc361e617bb25fa8a7a - optee/optee_os/core/arch/arm/plat-poplar/main.c +da5b397448c96664ff0d89282edbecf39150b736 - optee/optee_os/core/arch/arm/kernel/generic_timer.c +8ebc782c56e8a49cbb1a1842f396de645f1f46a7 - optee/optee_os/core/arch/arm/kernel/cache_helpers_a32.S +96a20985eac7f15b591f72bdd3a413deab7bed66 - optee/optee_os/core/arch/arm/kernel/thread_spmc.c +6fd7aa6291ba867b69684437a7dd5bb5a7bf35f0 - optee/optee_os/core/arch/arm/kernel/tee_time_arm_cntpct.c +cfe9209c0f08602f20df8752df4016c257305627 - optee/optee_os/core/arch/arm/kernel/vfp.c +170f9fade8d4cfd3805f2aa2383b7f3d358507df - optee/optee_os/core/arch/arm/kernel/idle.c +0dafbe192d55bfc13650b4d9b06857d1b515e38d - optee/optee_os/core/arch/arm/kernel/cache_helpers_a64.S +99dbd4c6ced9d21fbf6db2c3e7c6755d8c6bce28 - optee/optee_os/core/arch/arm/kernel/vfp_a32.S +07324ee362ff4d159fdf6bce6b0b02e8e78b88c4 - optee/optee_os/core/arch/arm/kernel/arch_scall.c +a3d562edc0d696f64d77e9c96d86c9a88451b5a1 - optee/optee_os/core/arch/arm/kernel/vfp_private.h +5e41ac280fa605fa56477c6e9667c7421ae832c1 - optee/optee_os/core/arch/arm/kernel/thread_optee_smc_a64.S +d347c9bafe24140b9717de8891d9659b01333e07 - optee/optee_os/core/arch/arm/kernel/arch_scall_a32.S +4ee8f8d86109824375f2cc97d335f68da3fdaa62 - optee/optee_os/core/arch/arm/kernel/tlb_helpers_a64.S +c591321644c6fd32d600a9a797daf4cdc48647d2 - optee/optee_os/core/arch/arm/kernel/spin_lock_a64.S +fd41f03a86b219928984dc3153a10bd5702fcca3 - optee/optee_os/core/arch/arm/kernel/spmc_sp_handler.c +a0adb6240ef123f1b7a7d5c06d1f43bbe84ab420 - optee/optee_os/core/arch/arm/kernel/stmm_sp.c +b4d64fa787d883488032c460e9bdd9219c8b7e6b - optee/optee_os/core/arch/arm/kernel/link_dummy.ld +ab6654f9a53a145c7e2bc78923bed0bc0657bfe3 - optee/optee_os/core/arch/arm/kernel/thread_a64.S +d5860b562cc073c556bae2a7af9a7e1eb58a120f - optee/optee_os/core/arch/arm/kernel/thread_optee_smc_a32.S +f5f53c7818eac3cb9a438d50e42b970aa59256a0 - optee/optee_os/core/arch/arm/kernel/virtualization.c +3bc11c7750b18f421431d5d75da90d8db8f968e8 - optee/optee_os/core/arch/arm/kernel/entry_a64.S +af8d99e369132adac450a89f4b07fbbada85156d - optee/optee_os/core/arch/arm/kernel/misc_a64.S +4100714c5da0ab3a043f026f768aa0f42963f0f7 - optee/optee_os/core/arch/arm/kernel/link_dummies_paged.c +dee3ef20e88a64d3e5c6a703b7e499cf302b0d3e - optee/optee_os/core/arch/arm/kernel/abort.c +7926173ef40ab1dffbd3b48ff3aa6da3fc04408c - optee/optee_os/core/arch/arm/kernel/asm-defines.c +24e1db339b48a73b6aaafcfca9047c7855896faf - optee/optee_os/core/arch/arm/kernel/rpc_io_i2c.c +da59d8db4ac8cd365ffd09d040ddc2a6ecab1d06 - optee/optee_os/core/arch/arm/kernel/thread_optee_smc.c +cff200d2106d26baf930f16e6caa8634adebbe08 - optee/optee_os/core/arch/arm/kernel/vfp_a64.S +8430d6b00cd4f9685acc4a7635286460c6c6656b - optee/optee_os/core/arch/arm/kernel/entry_a32.S +f41ca1e85c2faac131a78224385cef504fa5fb20 - optee/optee_os/core/arch/arm/kernel/tlb_helpers_a32.S +5ccfc6d56a72745aa30a58576530f6a552424dd9 - optee/optee_os/core/arch/arm/kernel/secure_partition.c +44470d3e7b9cdbed041ae13408e647edc645aa74 - optee/optee_os/core/arch/arm/kernel/misc_a32.S +8e7f44c940c10653f99ce491cc9ee014042dd270 - optee/optee_os/core/arch/arm/kernel/tz_ssvce_pl310_a32.S +4eb9e4b6f2b6b8f595acf22a683d831fee0ef40f - optee/optee_os/core/arch/arm/kernel/unwind_private.h +b5ebdeae94cfe7fd7a32f0be15e8a28b230cd175 - optee/optee_os/core/arch/arm/kernel/tee_l2cc_mutex.c +db8f47350612f3b8a6329c86401fdd3f68deea35 - optee/optee_os/core/arch/arm/kernel/timer_a64.c +9447a2f925a8c4a712433747c0b99e00733645d3 - optee/optee_os/core/arch/arm/kernel/semihosting_a64.S +63ea63ab5d506208970d6f5b8738ee82850aefe3 - optee/optee_os/core/arch/arm/kernel/unwind_arm32.c +9d0bd8480809254b743bf3d766efe7c3cdc70034 - optee/optee_os/core/arch/arm/kernel/kern.ld.S +af2646c2f7bed754eace205139dfe421ab8bd3a5 - optee/optee_os/core/arch/arm/kernel/thread_a32.S +288600f47bcdb1589b53bf9f9679cd62fc048b35 - optee/optee_os/core/arch/arm/kernel/thread.c +599bd7fb683e3e1c0eddc71e66e5eb979e8e7c28 - optee/optee_os/core/arch/arm/kernel/spin_lock_a32.S +9e422c03938a8b32edd015a653d5dac29880a5e2 - optee/optee_os/core/arch/arm/kernel/unwind_arm64.c +d6c09e6c39b889a25fcb82340f1725f9d0427d59 - optee/optee_os/core/arch/arm/kernel/arch_scall_a64.S +429869efe81ea182c117279b62d84611f6c67d9e - optee/optee_os/core/arch/arm/kernel/thread_spmc_a64.S +4d984b5505df1222904d25ec03a4521297c86119 - optee/optee_os/core/arch/arm/kernel/boot.c +85841b19544e59c0896f7c344b4695e129135d4e - optee/optee_os/core/arch/arm/kernel/link_dummies_init.c +43dcd40dee8c1bca63526b7590768c430e2b9eb4 - optee/optee_os/core/arch/arm/plat-corstone1000/platform_config.h +a2bbb6d8467a57da3e214024d754db8c39773688 - optee/optee_os/core/arch/arm/plat-corstone1000/main.c +eba718605aa45932a4b80632aa65d8cb35dc2b22 - optee/optee_os/core/arch/arm/plat-versal/platform_config.h +bfcf05746b3abe951fa87eae66701a8f965aa611 - optee/optee_os/core/arch/arm/plat-versal/main.c +095caecf26786efe69779aab593c67447f44b9c2 - optee/optee_os/core/arch/arm/plat-ls/plat_init.S +f413d0ba2e04b6ef2802475a9132687b2f19237a - optee/optee_os/core/arch/arm/plat-ls/platform_config.h +13868e401113be9ac3e66fcf65079f44ea2bacc5 - optee/optee_os/core/arch/arm/plat-ls/main.c +94a132cb905aa39756cd3bd0c4cd0bb955893219 - optee/optee_os/core/arch/arm/plat-amlogic/platform_config.h +c361b974a831b2e73783b393d9d3893180fcd1af - optee/optee_os/core/arch/arm/plat-amlogic/main.c +b1793c2149008cfc5c242a3fbbfcdfecfb082b4b - optee/optee_os/core/arch/arm/plat-amlogic/scripts/aml_bin2img.py +2399244b8020942c1b3a3cb924194e8770560051 - optee/optee_os/core/arch/arm/plat-sunxi/plat_init.S +eaa619f9de58ee047ca541b4c238b2afb5b83b6a - optee/optee_os/core/arch/arm/plat-sunxi/psci.c +4e93d8d25766b05b285896a4944c227f8b4da442 - optee/optee_os/core/arch/arm/plat-sunxi/platform_config.h +e88f1ed007545a2d9bad93b2b4339ad8b3495d1c - optee/optee_os/core/arch/arm/plat-sunxi/main.c +bf4be1dd46e6278e5b9b8b6a40b710d90007d915 - optee/optee_os/core/arch/arm/plat-hisilicon/hi3519av100_plat_init.S +92415c6775326559b08df1d2a9976b3e1ebb0a72 - optee/optee_os/core/arch/arm/plat-hisilicon/psci.c +012cc9cc5cd4d1213266d657558cd6c1fb998e1f - optee/optee_os/core/arch/arm/plat-hisilicon/platform_config.h +1e0932868e4fc72946b4b12a3650c383dcdd7a79 - optee/optee_os/core/arch/arm/plat-hisilicon/hi3519av100.h +a8c72f869ba4905a042677386935fe5f89594db8 - optee/optee_os/core/arch/arm/plat-hisilicon/main.c +2d7ce0ada1137b16132294b438cf80dc592fc2d2 - optee/optee_os/core/arch/arm/plat-stm32mp2/stm32mp_pm.c +409ab7028ed4877a9e66ce00a6aa0f1f0facd611 - optee/optee_os/core/arch/arm/plat-stm32mp2/stm32_util.h +1dbd06a7324f258effac9a8ef4ac5baf9c426440 - optee/optee_os/core/arch/arm/plat-stm32mp2/platform_config.h +46b98d93bcfa1a298f80c25b710f13f434f751e8 - optee/optee_os/core/arch/arm/plat-stm32mp2/stm32mp_pm.h +0597459671a071898baca88cd6fd4c7319cb6e7f - optee/optee_os/core/arch/arm/plat-stm32mp2/main.c +6bad30092b6947c38cd0dcc571b822356d63152e - optee/optee_os/core/arch/arm/plat-zynqmp/platform_config.h +00aa4ae9cc5e6bc0ee8dc057986548b31545f5ed - optee/optee_os/core/arch/arm/plat-zynqmp/main.c +0fce490355fabf44c68c3e70a54be1e01f9c097a - optee/optee_os/core/arch/arm/plat-marvell/platform_config.h +af9cccac94bc9f4624a345c140c5b6e92cc1cbf6 - 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 +9f34e39f67ff62c0eb53b7758b4bb2acdc47c228 - optee/optee_os/core/arch/arm/plat-marvell/cn10k/core_pos.S +9899b78e83cfa336552e36d0be06113de438bf15 - optee/optee_os/core/arch/arm/plat-hikey/hikey_peripherals.h +4957879ea142b46fd1ace368df87de82c90f5e5f - optee/optee_os/core/arch/arm/plat-hikey/spi_test.c +11fa51fa797eb2a0ed5a79b96c4c48ab77451fc9 - optee/optee_os/core/arch/arm/plat-hikey/platform_config.h +a3ca539721787ac30ecbe03305f389325b894ff1 - optee/optee_os/core/arch/arm/plat-hikey/main.c +f59a39b271b322f5bdd6baebdedb3ef701a78b02 - optee/optee_os/core/arch/arm/crypto/sha3_armv8a_ce_a64.S +9c1f14fdc223c00af03fe8b922a520419b7fd0b9 - optee/optee_os/core/arch/arm/crypto/sha1_armv8a_ce.c +afc997b206bbdc6c60cd9f08308b7b53832eac0b - optee/optee_os/core/arch/arm/crypto/aes_modes_armv8a_ce_a64.S +d857b4b442486f2ac052ee687cb6d6f424843433 - optee/optee_os/core/arch/arm/crypto/sha512_armv8a_ce.c +fb5f716381766749999f0032bf39f39bf88af12e - optee/optee_os/core/arch/arm/crypto/aes_modes_armv8a_ce_a32.S +cb5a3413393627c5fb4626c2315e2e12bf01abf1 - optee/optee_os/core/arch/arm/crypto/ghash-ce-core_a32.S +02305ae36a17490cecdc906c0970e8625ea9e6a1 - optee/optee_os/core/arch/arm/crypto/sm4_armv8a_neon.c +45797af469d803907920fecce84f86fbe684a40c - optee/optee_os/core/arch/arm/crypto/sha3_armv8a_ce.c +1ab432ea10e0e0edf03b0ce17bb5277fea163578 - optee/optee_os/core/arch/arm/crypto/sha256_armv8a_ce.c +6e006d07e0e25f49c5af73e0e522f6f97963275c - optee/optee_os/core/arch/arm/crypto/sm4_armv8a_aese_a64.S +933f5b3256795b2ffea6b7b93d75365f865599b3 - optee/optee_os/core/arch/arm/crypto/sha1_armv8a_ce_a32.S +182b52f83f99ae6bbfa5098b2a3b2018194acde0 - optee/optee_os/core/arch/arm/crypto/ghash-ce-core_a64.S +2da4cbb016071dacfbbd7c99799a27ad6d8c56a7 - optee/optee_os/core/arch/arm/crypto/sha512_armv8a_ce_a64.S +0b84c15b4796a2a23a095ae2d6d037677510760a - optee/optee_os/core/arch/arm/crypto/sha256_armv8a_ce_a64.S +bb50a2e7fffd5945ce8214bf57ad9d55135b46c0 - optee/optee_os/core/arch/arm/crypto/sm3_armv8a_ce.c +2c3ba8b73e012b48da6c8ff12c635f8fa109e5a8 - optee/optee_os/core/arch/arm/crypto/aes_armv8a_ce.c +47012ceb6af70d59a7666ca551814aa811efe9e8 - optee/optee_os/core/arch/arm/crypto/sm4_armv8a_ce.h +ad9a80c4d43acd03ae5d27e14df6dfee3abc4e05 - optee/optee_os/core/arch/arm/crypto/sha256_armv8a_ce_a32.S +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 +cf714bfd8657a2fff8112b3b94d7e476d51e2e60 - optee/optee_os/core/arch/arm/crypto/sm4_armv8a_ce_a64.S +56e9da14883d74e8eca3a4c7737185590cf14c08 - optee/optee_os/core/arch/arm/crypto/sha1_armv8a_ce_a64.S +0c1913711dd52b93cfe5d2d476a3a050a5bae97d - optee/optee_os/core/arch/arm/crypto/aes-gcm-ce.c +09cb511f6b571c162ae284911b5af9c702dd5130 - optee/optee_os/core/arch/arm/crypto/aes_armv8a_ce.h +0cd13267dd6db52ed1ff3742dcb7adb15bdff8cd - optee/optee_os/core/arch/arm/crypto/sm4_armv8a_ce.c +55fee8bf238c661a2f59118cbea5d8fca29471f3 - optee/optee_os/core/arch/arm/plat-zynq7k/plat_init.S +e8a97315a58b289054e1f3fb5418cba746b5633e - optee/optee_os/core/arch/arm/plat-zynq7k/platform_smc.h +8694a8f4be2551b1bf8f1abcb17284a8b202e5af - optee/optee_os/core/arch/arm/plat-zynq7k/platform_config.h +8ec4ce70677e98cc80e5c401bf9640ec0fee3b83 - optee/optee_os/core/arch/arm/plat-zynq7k/main.c +fd20baae7413cd701b88ba6dfeb2a294a9eeb452 - optee/optee_os/core/arch/arm/plat-stm/rng_support.c +bdd38a0220aac82b0aafa97e8f1993cb27e0ac1f - optee/optee_os/core/arch/arm/plat-stm/tz_a9init.S +784a5cea3b2741f04facdeaf7bfac0e093630875 - optee/optee_os/core/arch/arm/plat-stm/platform_config.h +445f45675057a9e6f1aaab83895215595ae65915 - optee/optee_os/core/arch/arm/plat-stm/main.c +1b82881f2b80531fc7743309c38c8e9370969ef1 - optee/optee_os/core/arch/arm/plat-rzn1/rzn1_tz.h +776215d1f8598a5514e759d70ae400a8101f835a - optee/optee_os/core/arch/arm/plat-rzn1/a7_plat_init.S +48ef8147e12f826d7e87c67d7c12e3932d317546 - optee/optee_os/core/arch/arm/plat-rzn1/sm_platform_handler.c +245d63c49ace44a4319be3f8b9882e520bf67448 - optee/optee_os/core/arch/arm/plat-rzn1/psci.c +2ecc2eb6bff695c5b86aba9d1b07e0edcef5ab75 - optee/optee_os/core/arch/arm/plat-rzn1/platform_config.h +c9a02f7b7f7b87ffbcb1b4817f13f0a9ce102e7a - optee/optee_os/core/arch/arm/plat-rzn1/rzn1_regauth.h +efb02131d3016042f019eb5255aea2a304f26d44 - optee/optee_os/core/arch/arm/plat-rzn1/main.c +1362e6bff2c7739808fe60425baeb2fadc816d16 - optee/optee_os/core/arch/arm/plat-sprd/console.c +43ecf7e39e7a28c27b7b79a3615e3614939834bf - optee/optee_os/core/arch/arm/plat-sprd/platform_config.h +ff3678a750adfc1d8371ccec9e74da720682f3c6 - optee/optee_os/core/arch/arm/plat-sprd/main.c +7a47d9b9d80c3ff0539ada4663d95c9e7bdac984 - optee/optee_os/core/arch/arm/plat-imx/tzc380.c +33c6bb81805293647a9e56f5a1c069e159c98217 - optee/optee_os/core/arch/arm/plat-imx/imx_pl310.c +8f2a801bfab0d2fb53487c8d7dca3be221530eae - optee/optee_os/core/arch/arm/plat-imx/imx.h +576710aa6118eebca00bfa8024c4f48ad57b89ec - optee/optee_os/core/arch/arm/plat-imx/a7_plat_init.S +adedaaade5c7177a170c74433b126fb1bd75463b - optee/optee_os/core/arch/arm/plat-imx/sm_platform_handler.c +658c3b177340e2efe74ac7cfe5a0c688aeadf90d - optee/optee_os/core/arch/arm/plat-imx/imx_pl310.h +19f7be18a342945b17601d7b48c613ea1468eaa2 - optee/optee_os/core/arch/arm/plat-imx/a9_plat_init.S +13e40fd4f55de4dc5467690339cf670d76621be0 - optee/optee_os/core/arch/arm/plat-imx/imx-common.c +584afcf20fad8029781743589f1d8b888d4d7edf - optee/optee_os/core/arch/arm/plat-imx/platform_config.h +29532130fde10f9c8426ef28f98f4c500de5e004 - optee/optee_os/core/arch/arm/plat-imx/imx-regs.h +130bb1cd7a5b0a7a3b471a004449a211455bdd4e - optee/optee_os/core/arch/arm/plat-imx/main.c +be59b37f3baf5d18ad949415e77e4c09a1a2ebb3 - optee/optee_os/core/arch/arm/plat-imx/config/imx6sl.h +93a6155f6f294fddb38ac1947f5dce49d68f71d5 - optee/optee_os/core/arch/arm/plat-imx/config/imx6sx.h +2d95ab53312d29b23061b747e96c695708612d8d - optee/optee_os/core/arch/arm/plat-imx/config/imx6qdlsolo.h +6c0a9e819b3e4b156c47a4761eef280bcfd0ab2f - optee/optee_os/core/arch/arm/plat-imx/config/imx6sll.h +7df27071dbcbeb1f977a02e17445136fa22a3749 - optee/optee_os/core/arch/arm/plat-imx/registers/imx7-crm.h +3931a5db91c6b50993dba75c296966e3e9416994 - optee/optee_os/core/arch/arm/plat-imx/registers/imx7ulp-crm.h +f44811ad0707fbcbcb20271e209f14481ae12b31 - optee/optee_os/core/arch/arm/plat-imx/registers/imx6.h +9976e7cbeeb2ff5f852c838ecc82e62f85555b72 - optee/optee_os/core/arch/arm/plat-imx/registers/imx8m.h +46dc26d459e4a5adb2a904c7f6b4c5ef4546ab75 - optee/optee_os/core/arch/arm/plat-imx/registers/imx8m-crm.h +1a557c230d0c95aeb775b8f02c4a5294b829132e - optee/optee_os/core/arch/arm/plat-imx/registers/imx7ulp.h +b355b4bb04068d735c1faa8039e1ade0d88d60d2 - optee/optee_os/core/arch/arm/plat-imx/registers/imx6-crm.h +0ab3222c89bd29af45b6838cb1126597ea378f7f - optee/optee_os/core/arch/arm/plat-imx/registers/imx8ulp.h +e8e364071825472444c0223168929efe4a9385d2 - optee/optee_os/core/arch/arm/plat-imx/registers/imx93.h +f93579c365bf08fb597488903040c0b92041517d - optee/optee_os/core/arch/arm/plat-imx/registers/imx8q.h +55f6aaaf23e460dbfd791e81c80dd5de5d3bfbfa - optee/optee_os/core/arch/arm/plat-imx/registers/imx8ulp-crm.h +845f9ec3fb38a2456492626af9b5dfe8f583bfec - optee/optee_os/core/arch/arm/plat-imx/registers/imx7.h +443dd0395348c2b831b9ea34e1d0df567e22dfa4 - optee/optee_os/core/arch/arm/plat-imx/registers/imx6-dcp.h +e0bd5cc425555563f9b9428c5ab4088ab77dca2d - optee/optee_os/core/arch/arm/plat-nuvoton/platform_config.h +b5eab9ec78f6d28b2c8c130ef28fb357b65f5235 - optee/optee_os/core/arch/arm/plat-nuvoton/main.c +b3d21a1017a2f66d52d2f6da7f671715aba08021 - optee/optee_os/core/arch/arm/plat-rpi3/platform_config.h +ec372362de1d4e3528e6ba2db82b0c9a6949239b - optee/optee_os/core/arch/arm/plat-rpi3/main.c +ca3077b3f16c93f5d5350d4b21c08770138bc3af - optee/optee_os/core/arch/arm/plat-d06/core_pos_a64.S +ef651043e13845e8c87166c7f7c63c304bad4336 - optee/optee_os/core/arch/arm/plat-d06/platform_config.h +f3bb0c06c205574018197b20b6b28b4b4d95e9bb - optee/optee_os/core/arch/arm/plat-d06/main.c +fa6b95e58563f8332731f989e0d1bca1fffbbac4 - optee/optee_os/core/include/optee_rpc_cmd.h +88da2be579e9631f960e2e446fde123208299e46 - optee/optee_os/core/include/gen-asm-defines.h +6cd050c7ddd4d5c1022f00bf74e621a0a04818df - optee/optee_os/core/include/scattered_array.h +230b6235c3972d7ad25e31b52d8dd6e446d170b7 - optee/optee_os/core/include/optee_msg.h +fe35bcb23450f547f7b098c1dc83a86e94884a96 - optee/optee_os/core/include/rng_support.h +5f4af7ab7f5e65ed9a75fdef46311017a029b9b8 - optee/optee_os/core/include/initcall.h +d507db96fbda840a8a7615c35c15fa3cd392b7ad - optee/optee_os/core/include/console.h +129133eb0ba4e4b73eaf1d84710e580b22e10009 - optee/optee_os/core/include/spi.h +5c27242ef89ad221fbf7dc967d4227bb1210f3c5 - optee/optee_os/core/include/ta_pub_key.h +17854fd3bc11a0554f93349178a5ebde2df45a21 - optee/optee_os/core/include/io.h +1cdb9baa31ff97e081376c5efb6ab5476a90fd9e - optee/optee_os/core/include/keep.h +804d76c5793756bf65288f5d87b37716fc8a2a27 - optee/optee_os/core/include/signed_hdr.h +dcd9135e8790bfdbf7e925e8e5c9d421b5e89041 - optee/optee_os/core/include/dt-bindings/pinctrl/stm32-pinfunc.h +19bb520476cff77efd84b0106f690c4dd972bd63 - optee/optee_os/core/include/dt-bindings/regulator/active-semi,8945a-regulator.h +51c769451ca1c189b2b01b45473d6fb93157a4f2 - optee/optee_os/core/include/dt-bindings/regulator/st,stm32mp15-regulator.h +4c0440a1ff7d6b4704a914a7c2ad8192fa6e3c63 - optee/optee_os/core/include/dt-bindings/regulator/st,stm32mp13-regulator.h +6f7d303afc4981c5aaf8ae4eedae611976aa5b7e - optee/optee_os/core/include/dt-bindings/reset/stm32mp1-resets.h +75e3b85cfb7663af28a4aeabd71f5d9171713d1b - optee/optee_os/core/include/dt-bindings/reset/stm32mp13-resets.h +c09a35772e7498a4ece6515946754488ec651860 - optee/optee_os/core/include/dt-bindings/interrupt-controller/irq.h +8bbae85d2c9ec2416cc28a15f3d8e79d19c9847c - optee/optee_os/core/include/dt-bindings/interrupt-controller/arm-gic.h +2d0e795df5e3ef26343c50b0371d892d062942b6 - optee/optee_os/core/include/dt-bindings/clock/at91.h +11cb6c3b8996e757f9d20becbf83d65d9da3497e - optee/optee_os/core/include/dt-bindings/clock/stm32mp13-clks.h +700be76cdd56cf4beca99964e8bef7679ca119a4 - optee/optee_os/core/include/dt-bindings/clock/stm32mp13-clksrc.h +c82fd3d48caa51f67f6bb71f5637c491c8869afb - optee/optee_os/core/include/dt-bindings/clock/stm32mp1-clks.h +a70bccff932cfe66485a89fd2fa7a4365f265e12 - optee/optee_os/core/include/dt-bindings/firewall/stm32mp25-rif.h +f79b5f2ced860b24f63fd994d127216b28a39fd8 - optee/optee_os/core/include/dt-bindings/firewall/stm32mp25-rifsc.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 +23149233a025ca8a0b84821b398694bbf0bfdf4e - optee/optee_os/core/include/dt-bindings/iio/adc/at91-sama5d2_adc.h +9eea9ced1442cf0f623a3e71799533baf44cd8ce - optee/optee_os/core/include/dt-bindings/gpio/stm32mp_gpio.h +736b382bd5ae6f63e95b0ec473a146ffe182294e - optee/optee_os/core/include/dt-bindings/gpio/atmel,piobu.h +f0ee73ec026d62a1125c4410ba4a0a72b924d09f - optee/optee_os/core/include/dt-bindings/gpio/gpio.h +1e7ab5294d740390ffb703e0912f612c043e1ce3 - optee/optee_os/core/include/dt-bindings/dma/at91.h +bf573306daa40e7d3a9a2d47afdb08f99e78b3a7 - optee/optee_os/core/include/dt-bindings/rtc/rtc-stm32.h +c15642cd88cddd72322e27f38fb29ca150a0b99e - optee/optee_os/core/include/mm/vm.h +152f0ce018b49d6fc2b0b320f82c1b29e25cad29 - optee/optee_os/core/include/mm/core_memprot.h +c97a01f7bba80935fcbf2dafe9e946d43c247e1b - optee/optee_os/core/include/mm/sp_mem.h +6d521abcb9da5acc5abe3d8e3bd7d39f79d32075 - optee/optee_os/core/include/mm/pgt_cache.h +7478c95b4ec03b37de3abbfa9a8a6f526c19e4c9 - optee/optee_os/core/include/mm/core_mmu.h +30b8bfeb037aa430b36a9d62a9d906834dcf8903 - optee/optee_os/core/include/mm/fobj.h +4f1bf0f7dbc04b954ec0408e786fe257c4ac6b0c - optee/optee_os/core/include/mm/mobj.h +3ab7ecf667fa906a144379998f686f44c83c2394 - optee/optee_os/core/include/mm/file.h +816a10ca244ab70efbf0059722455fd3f006211e - optee/optee_os/core/include/mm/tee_mm.h +208482cdefa0c15d6a3c7f325a33799eba7160e0 - optee/optee_os/core/include/mm/tee_pager.h +d49b92eae62339ee11a9bc33e9de868b864333ea - optee/optee_os/core/include/mm/tee_mmu_types.h +86d731fbc4dec94afb6d508b95a533f7d47c3485 - optee/optee_os/core/include/tee/tee_supp_plugin_rpc.h +1308f358a4a299c363fc1ff9d4449995132b18c1 - optee/optee_os/core/include/tee/tee_ta_enc_manager.h +59f15f82c6b72fdca29ff7d5492653a84202aa93 - optee/optee_os/core/include/tee/tee_cryp_utl.h +a99d6817471b82716d363a37e72fd6a6eadf42a9 - optee/optee_os/core/include/tee/cache.h +128881dfa00d0a1df793f816382efaa4e9d9bcce - optee/optee_os/core/include/tee/tee_fs.h +18a016ad9187e9e46b9b4758e73fadd9a375bbc3 - optee/optee_os/core/include/tee/tee_svc_cryp.h +0d89839cb1cbe5cc90c8acdb64ce5eaa35474503 - optee/optee_os/core/include/tee/tee_fs_rpc.h +053be96056cb04167009eb9368f7a8afc6dfaa5c - optee/optee_os/core/include/tee/tee_ree_state.h +6d690cb2041bea9138c24294d54a4d77aad41aff - optee/optee_os/core/include/tee/tee_cryp_hkdf.h +abea67617b2ab0ac70350ff3fe67b738eaa3645d - optee/optee_os/core/include/tee/uuid.h +b1c5d8f39981550bb0c40e7175bce5057378e3d0 - optee/optee_os/core/include/tee/entry_std.h +cf47b8057c9b037363f5a4bc50e424c35f2e3f92 - optee/optee_os/core/include/tee/tadb.h +6950b4690d1bf6ed1c32bc5bb06c44fbe39a29c7 - optee/optee_os/core/include/tee/tee_svc_storage.h +a90a966755ea02bf958fe6e492dda2d298e80403 - optee/optee_os/core/include/tee/tee_pobj.h +310b549683246f2258017d58572e9ab296981ec9 - optee/optee_os/core/include/tee/tee_fs_key_manager.h +0ac5827ea6d593ab3ff7382f2ee79d2be03fd2ae - optee/optee_os/core/include/tee/tee_cryp_concat_kdf.h +d7019362eb2c68e0692df4fa18c0cea06919e3f1 - optee/optee_os/core/include/tee/tee_cryp_pbkdf2.h +d517b1e0bd1ffceea1229d891891f62fa512b539 - optee/optee_os/core/include/tee/tee_svc.h +1c154159486140e838e057c58caf72c4a3b7d1b4 - optee/optee_os/core/include/tee/svc_cache.h +e825068e0bf9924af7215f4327bef758ff1f815f - optee/optee_os/core/include/tee/fs_dirfile.h +01a38ef0fc64d28f2ea1e65966093196abe543f5 - optee/optee_os/core/include/tee/tee_obj.h +97cfacaf0101f86f6d7edc4a3a3ff67110792801 - optee/optee_os/core/include/tee/fs_htree.h +ee6cb7826fbd60a90595fcc4962e428c46610b5b - optee/optee_os/core/include/drivers/stm32mp_dt_bindings.h +40c07075659d9321c0d0bf90cc0c2a567e4f070c - optee/optee_os/core/include/drivers/stm32_etzpc.h +d9e6e80aa5d27c1fcf9c1edc4895e62394b0d4d4 - optee/optee_os/core/include/drivers/versal_nvm.h +58ddebbef8bd6c594d871fb476d88a5f9831153d - optee/optee_os/core/include/drivers/ls_sec_mon.h +91b6d3c752a3d89e785356b8589c47726ff68d98 - optee/optee_os/core/include/drivers/zynqmp_csudma.h +511feb397f8a383b92c4d238c9639c0ff2f6b5e1 - optee/optee_os/core/include/drivers/stm32_uart.h +cca1719ab46702da66faa45ee2e674cbf56e0936 - optee/optee_os/core/include/drivers/zynqmp_csu_puf.h +996e4e71228a955032f4422f1857fc86adeef560 - optee/optee_os/core/include/drivers/mvebu_uart.h +c8ca68f41b1afee076215f931ae25f18f2ffdf32 - optee/optee_os/core/include/drivers/serial8250_uart.h +b1d5544ff4f3ab0503a7b7403cafc67a0893bc29 - optee/optee_os/core/include/drivers/tzc400.h +ba6f897176895794b2c32406a85d56460b869a02 - optee/optee_os/core/include/drivers/bcm_sotp.h +d6e344ad9b81930944052a2aa7439fea4f98e7a3 - optee/optee_os/core/include/drivers/imx_sc_api.h +2ddfccba77effaf40a1b9a0ccc978bdfd8162d7b - optee/optee_os/core/include/drivers/atmel_rstc.h +5a5250f891c8e3fd01fe97da71d746ab170d70f8 - optee/optee_os/core/include/drivers/zynqmp_efuse.h +2862b25eeafb9f6e676ed83d48581638899573d9 - optee/optee_os/core/include/drivers/caam_extension.h +7cd32050e290fd4a576185a57e4ee3deac99984a - optee/optee_os/core/include/drivers/versal_gpio.h +631cc4ec89ffe0c7e2eb61ef0c441a265c1cff11 - optee/optee_os/core/include/drivers/versal_pm.h +e134f758ab7ac37003823e6518be9ab1ec171e88 - optee/optee_os/core/include/drivers/lpc_uart.h +ee4402299d8587fe8e625421815d09e610917439 - optee/optee_os/core/include/drivers/stm32_remoteproc.h +e82a2ed50b41b1008781a3fc944bc32366f9eb02 - optee/optee_os/core/include/drivers/imx_wdog.h +04f9993ffd5c2f798953978835626f7d91793c27 - optee/optee_os/core/include/drivers/zynqmp_pm.h +345ebf6d5dc2948c7a760d3cdf168f3461f36cf4 - optee/optee_os/core/include/drivers/imx_ocotp.h +ed0702ba8e49ca5d2b8fde5b754911bdd2120b71 - optee/optee_os/core/include/drivers/imx_i2c.h +7861330159692f9f887f6ab44a547cbe1f3f24dd - optee/optee_os/core/include/drivers/sp805_wdt.h +abea729d88bd897be58ed6c9534b6d37cf914d57 - optee/optee_os/core/include/drivers/zynqmp_csu.h +e5f12caa0c11061b91eac6b6165657e68158cc84 - optee/optee_os/core/include/drivers/ls_gpio.h +72846a719bd42c01c0f3fba621809252fa7e6aca - optee/optee_os/core/include/drivers/imx_uart.h +f7944ca30772475a66c4f8ff168470477e282d19 - optee/optee_os/core/include/drivers/i2c.h +0957985db83d64a10b0b4d453a89e517f1162217 - optee/optee_os/core/include/drivers/wdt.h +5a4750980a258bf284a226cd8646a4d9a4f20486 - optee/optee_os/core/include/drivers/imx_mu.h +f4951939c2d41480ee8077883f4e3f9634c9ddd8 - optee/optee_os/core/include/drivers/regulator.h +acdcb0f0430baed3d90047cd49aec102e6dffc4e - optee/optee_os/core/include/drivers/cdns_uart.h +e5581364847f5fd4af18e00895e96feae66c2dc8 - optee/optee_os/core/include/drivers/rtc.h +adc8eb02c13ad66bb1e3be9c024aed644b40d9f5 - optee/optee_os/core/include/drivers/bcm_hwrng.h +54f6572933ae458e1115bd8d43337c0955900239 - optee/optee_os/core/include/drivers/atmel_shdwc.h +2ee9ec2b7a82e5db03c61a7ebdaccf200365ef19 - optee/optee_os/core/include/drivers/scmi.h +bf5353223f3ff261e30e843cf6810e7da7985b3a - optee/optee_os/core/include/drivers/semihosting_console.h +bbd9f402bd751cfe638fb2585b52d940de3cd704 - optee/optee_os/core/include/drivers/stm32_tamp.h +9faff0556c12ea1887a80ebbfb60c2634048a51d - optee/optee_os/core/include/drivers/serial.h +a2a83ef6478b6f51f852629efe31b59304ed79ce - optee/optee_os/core/include/drivers/imx_snvs.h +c74b30cd58a799ad95ea9d8bb96bc87c362f4912 - optee/optee_os/core/include/drivers/stm32_rif.h +793f688738ed5e21251d77bdb463baae3fbf9d0a - optee/optee_os/core/include/drivers/hi16xx_uart.h +4dccf4b5a3f384b716473dd5f22fe88e62e69454 - optee/optee_os/core/include/drivers/pl011.h +044cf7b8b0ceb07ad4609f53ced52b569babfad3 - optee/optee_os/core/include/drivers/stih_asc.h +d2608b476c0a3e6772cbc28ea1b2b555091784fc - optee/optee_os/core/include/drivers/atmel_rtc.h +209a9de5a95c149ed87d06209a00416aca6bdf59 - optee/optee_os/core/include/drivers/versal_puf.h +c52233fb46f4ad3050a806e473cfd2f936f6b53f - optee/optee_os/core/include/drivers/scif.h +f53a2a41bd93c15bcdbd21f59b7580157c370051 - optee/optee_os/core/include/drivers/ls_dspi.h +9f095079d511b5d789cac4b93714a3f09b75f4b7 - optee/optee_os/core/include/drivers/scmi-msg.h +daff84d47d1e712ea0390efbdef06fcd3fadaebc - optee/optee_os/core/include/drivers/stm32_i2c.h +988feb107f388f0e02ddd78e2887e84a221e0839 - optee/optee_os/core/include/drivers/ns16550.h +6110fa3ecbd1bb7185abcee753303ad1090d1aca - optee/optee_os/core/include/drivers/ls_i2c.h +0ae76ea5b86bea63251e635eee1a0eb79682d8b5 - optee/optee_os/core/include/drivers/amlogic_uart.h +e6927231b7845a9e7e71687a8b104775b431807c - optee/optee_os/core/include/drivers/bcm_gpio.h +121789edb4cf9b2797d850a0cb4a0ab1059814ed - optee/optee_os/core/include/drivers/nvmem.h +90f5cecf44f1353954b9f509e72380c23dae5481 - optee/optee_os/core/include/drivers/zynqmp_csu_aes.h +8f00fe24571b769a4046de9ec9733504c4f9aa4a - optee/optee_os/core/include/drivers/hfic.h +95ea00a994106d233112cdafcbbdecbf43efe8b1 - optee/optee_os/core/include/drivers/stpmic1.h +a74eeaca5f6fc6a32f24486af30eb3bed2a377a5 - optee/optee_os/core/include/drivers/stm32_vrefbuf.h +1a127ceb7473cce35868a0e3b6fb6c0fe09f67a0 - optee/optee_os/core/include/drivers/atmel_saic.h +62c0202bb311d341e9df9d92d2a63e249d112b97 - optee/optee_os/core/include/drivers/clk_dt.h +01e3e3b8a4910f25dfdfdd865b70e885b8eb5151 - optee/optee_os/core/include/drivers/versal_mbox.h +58d82325f216b80a9bf970807e4c42339bb5b193 - optee/optee_os/core/include/drivers/pl061_gpio.h +5a47d280fbbdebc8b4b8220b9c0be960a7e80966 - optee/optee_os/core/include/drivers/stm32_iwdg.h +0858c735ecd0b0f69511c80da83b88cb428ae108 - optee/optee_os/core/include/drivers/versal_sha3_384.h +406ff8e0cfe26a1e6e63621ffa9ac1176426c376 - optee/optee_os/core/include/drivers/tegra_combined_uart.h +f0a3ee94f6f4b5e982ec8cee6d771f396e5aa1ee - optee/optee_os/core/include/drivers/clk.h +a33c92d997da4b5500e761f99997e9ae7747e0dc - optee/optee_os/core/include/drivers/sprd_uart.h +6c1691ca8fd41135a8d571021414095918e1ddae - optee/optee_os/core/include/drivers/stpmic1_regulator.h +e0b56498b27d3bd08d540168b77b98051f90ed82 - optee/optee_os/core/include/drivers/stm32mp13_regulator_iod.h +be006782da2caa19f262b37496195eb6654f9576 - optee/optee_os/core/include/drivers/stm32_gpio.h +7f3ef46e25244f20b8ad05b4953dc9bdc01db532 - optee/optee_os/core/include/drivers/stm32mp13_rcc.h +1e350e5217c7c9547170036a21103a9c8bd25c69 - optee/optee_os/core/include/drivers/cbmem_console.h +f6c06a7e3d38d67183bbde4814b1b4fc68226fda - optee/optee_os/core/include/drivers/stm32_shared_io.h +a534a04c75f7b25a685f14b9a9c4ad5bc1ce215a - optee/optee_os/core/include/drivers/pl022_spi.h +c35d53480ece3d50dbd7ebc42aaaec3952ce010a - optee/optee_os/core/include/drivers/rstctrl.h +08d26cdf94c5c5ac4238ecbe1fe7920162d98c63 - optee/optee_os/core/include/drivers/stm32_bsec.h +ef27ccc40f8a3475cc86c8746c95720ec0b5a9ee - optee/optee_os/core/include/drivers/stm32mp1_rcc.h +a4463c93ac3eedb1207d208b410182b2aa7be43d - optee/optee_os/core/include/drivers/atmel_uart.h +f79ce31669141d007d3d46c0510c83271a074888 - optee/optee_os/core/include/drivers/zynqmp_huk.h +5b966c643d05fffd950b8cc2875b441e6bc9938f - optee/optee_os/core/include/drivers/gic.h +f0ed3b98bd6633f74dab58757059ac11933671ea - optee/optee_os/core/include/drivers/pinctrl.h +17e4e2d1b983087461bfcc4bbfbd70e8b3ae1dac - optee/optee_os/core/include/drivers/ls_sfp.h +573aef790439e7f8668bf6d5be663c9504f9273a - optee/optee_os/core/include/drivers/tzc380.h +2a38bd2d5a0cebf403be03fa37429bd62e7a05cb - optee/optee_os/core/include/drivers/plic.h +a244838f90d18ae96bf58df83a82d4723e5e109c - optee/optee_os/core/include/drivers/gpio.h +33ea27d3d7b5742a187f56005a3c9ef39258ca2a - optee/optee_os/core/include/drivers/pm/sam/atmel_pm.h +e00827b01eb60bbc2838dc0177a8fba77754c4a3 - optee/optee_os/core/include/drivers/tegra/tegra_se_keyslot.h +2ceae52c37cb480b625927a556e6deb4689ced3a - optee/optee_os/core/include/drivers/tegra/tegra_fuse.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 +4fc3e6c0473a8f822f3bcaaa66f3f668625884d2 - optee/optee_os/core/include/drivers/tegra/tegra_se_kdf.h +129d940801fe4b67f12bbd828bc01928ccd0b626 - optee/optee_os/core/include/drivers/sam/at91_ddr.h +c1ef23d7109f9ca715be1cbe858cd914f69a163f - optee/optee_os/core/include/drivers/imx/dcp.h +01ae4874fa40f1573c4604c8bc580b524346c9e7 - optee/optee_os/core/include/drivers/bcm/bnxt.h +9580dfe1f16580758041e227e65811d04ca384b6 - optee/optee_os/core/include/kernel/lockdep.h +47bae777ab0439c6c5f650a64c7eda7938bc750e - optee/optee_os/core/include/kernel/trace_ta.h +f4f803096be84380cf2c48dce52aaf855b3ab2d0 - optee/optee_os/core/include/kernel/mutex.h +7c41d260656d83bc3cb2f1504f1ab5305e787c72 - optee/optee_os/core/include/kernel/virtualization.h +c1f5708a89345bd1d1e59c0998656cb1b410984d - optee/optee_os/core/include/kernel/cache_helpers.h +08718b75d19035055180740c78363d96b950f76f - optee/optee_os/core/include/kernel/scall.h +ff1ad215df335bbc1bf5a8365c96c64746e4388d - optee/optee_os/core/include/kernel/refcount.h +7454568aad694133ddcefc1c65ffc1a6b8f06f0f - optee/optee_os/core/include/kernel/ldelf_loader.h +00b49554c88edc39e0bea14f007188c859e0b7fb - optee/optee_os/core/include/kernel/thread.h +2d5870c0a7b942b4325b6c466fee777e6d9663df - optee/optee_os/core/include/kernel/mutex_pm_aware.h +828549ba13cdf97222d005e03793bddd388afb02 - optee/optee_os/core/include/kernel/tee_common.h +de2778b5ee55508a8a54df96e419cb482f563b30 - optee/optee_os/core/include/kernel/semihosting.h +e813ebd4165bad56ac4e83aa96bfb64404ff86cf - optee/optee_os/core/include/kernel/nv_counter.h +1836e525384f0bcf97d7ccf701668c6c0c4f43df - optee/optee_os/core/include/kernel/ldelf_syscalls.h +4d33576f2922c7d3f23cca65c93c8069cc665e38 - optee/optee_os/core/include/kernel/tee_misc.h +72ac22282aa32da2fc27ec02fac1ec0e5e4b433f - optee/optee_os/core/include/kernel/huk_subkey.h +641871b38417b1213428160e9c0d378ac082b3ab - optee/optee_os/core/include/kernel/dt_driver.h +854c7104502755ee6babaf7af37ea75618f7c6f9 - optee/optee_os/core/include/kernel/boot.h +a614bf9bad94e38d4c27aad6b7cb71b21f02be3f - optee/optee_os/core/include/kernel/tee_time.h +c5127403e01dde874dd5af239caa97296d0e8695 - optee/optee_os/core/include/kernel/user_mode_ctx_struct.h +a7d6eb26cc4a919d59beb0de50ca14f3bdaeba81 - optee/optee_os/core/include/kernel/tee_common_otp.h +e4719588b0cc670eee34fbf59d8d50f39cdbdc45 - optee/optee_os/core/include/kernel/thread_private.h +2071ef11bd6c92008e3267688dcec4614ce898c2 - optee/optee_os/core/include/kernel/abort.h +482af27dd67588f4f1d2d4a5cd17c50bd645df49 - optee/optee_os/core/include/kernel/chip_services.h +cd624668c9f76defe8e05e3cc7547bd27128a5b2 - optee/optee_os/core/include/kernel/user_ta.h +625040376d7bc280e4dffbe23e77e046dbf40e2d - optee/optee_os/core/include/kernel/asan.h +abaea6379087b38a14691b6be5fe6356a055a37c - optee/optee_os/core/include/kernel/dt.h +c39885dc2548b8d6723071bcc766bb513e3ef78b - optee/optee_os/core/include/kernel/user_mode_ctx.h +2c04a3ad84fb1354bc98a83a02b34baaa2aeeb85 - optee/optee_os/core/include/kernel/transfer_list.h +f16062ce2b71d0032aafbbca0b6622522111e156 - optee/optee_os/core/include/kernel/delay.h +f79653070916157aa62f38869870204765305d74 - optee/optee_os/core/include/kernel/rpc_io_i2c.h +ed3147f55cf57484f6b235d33d44b7ac008321e7 - optee/optee_os/core/include/kernel/panic.h +f2ab69b044d5bcce9b58ca8ccb79b83d50b5fb70 - optee/optee_os/core/include/kernel/notif.h +2aaa4829d6e477b28a49aa4b15858e4d58528c38 - optee/optee_os/core/include/kernel/wait_queue.h +b9ebf51c4e2cb9b094423a70588cbd6eda7efbba - optee/optee_os/core/include/kernel/pseudo_ta.h +55b39e185d6756ef7e18929f99a9c6f0e15332ae - optee/optee_os/core/include/kernel/ts_store.h +736c236f73c04985ca81ea10c2f261fd06c44707 - optee/optee_os/core/include/kernel/pm.h +590c3ba3b3785bd1b70f32788080caa459b55454 - optee/optee_os/core/include/kernel/tpm.h +fdc42f8632716f2e930ccadebc2ba52fc85242a2 - optee/optee_os/core/include/kernel/user_access.h +8b22ed423b1b8e85f58048dd7072053fa9f0af4c - optee/optee_os/core/include/kernel/callout.h +5bb3a8cd5160f07a93fd9293957242604e679291 - optee/optee_os/core/include/kernel/misc.h +812a74ab18019aba6f14d3f06de6ceb0f03686f7 - optee/optee_os/core/include/kernel/early_ta.h +2233249756e47fc006e8a04186fa12757b84dba7 - optee/optee_os/core/include/kernel/embedded_ts.h +f809853f7dafcd931003f4f03ec346a85a86d1a3 - optee/optee_os/core/include/kernel/handle.h +06984aa4db6e47ec48c82a3fe7b24147ffa3ca19 - optee/optee_os/core/include/kernel/spinlock.h +f508df7c418ee1d26a9ac0b7bb9c02efaa95109f - optee/optee_os/core/include/kernel/unwind.h +23cec14e03085b7156a4095bb04eb95c3a096653 - optee/optee_os/core/include/kernel/timer.h +446e9f32d38a7ba8ba794474ba9d448c9c711994 - optee/optee_os/core/include/kernel/linker.h +92070cefa4d439c716c037e108416492f5d11ee0 - optee/optee_os/core/include/kernel/tee_ta_manager.h +92febe612c6bcab059b9309fc4c2d7d2c2c18e01 - optee/optee_os/core/include/kernel/interrupt.h +6633a78968c544109666de89e07ebbbb7624c4cd - optee/optee_os/core/include/kernel/msg_param.h +21af0145ee2a642abfe64f32b0618a6acb283781 - optee/optee_os/core/include/kernel/ts_manager.h +1b397670d3a135238d76ac0e6dd9cbe5095e6ecc - optee/optee_os/core/include/crypto/sm2-kdf.h +951fb0d4a44684edd5dea57f9af4dc3bfe63d7b7 - optee/optee_os/core/include/crypto/crypto_se.h +3c37642b6f4bfefdcae5a1697faef8aa2b82b756 - optee/optee_os/core/include/crypto/crypto_accel.h +eef0ead7045789d8587d0a0a470491a3138a9c3b - optee/optee_os/core/include/crypto/internal_aes-gcm.h +66960122dabaed2d352fcd0a703454038d12f387 - optee/optee_os/core/include/crypto/crypto_impl.h +302739e8b28cdc82ad0a5c9b26de42e9dd0e73f0 - optee/optee_os/core/include/crypto/crypto.h +89ce33aaddb1581c98d889695b695d3f91d1abac - optee/optee_os/core/drivers/stm32_shared_io.c +5b608ade5b6d8d262288fdc49165d0e0fb72f72b - optee/optee_os/core/drivers/imx_lpuart.c +f2395342fb43346befc286959fa01114b0ff28e2 - optee/optee_os/core/drivers/versal_mbox.c +1f8114767f04f10575e9d516120b9e8004560045 - optee/optee_os/core/drivers/zynqmp_csudma.c +6c4db16c8b3b5b7946f42531edaed3c24d4d07b0 - optee/optee_os/core/drivers/atmel_trng.c +a9e721b1faeb4865248d3c188b56278116a3185f - optee/optee_os/core/drivers/pl061_gpio.c +9629633ef9a1ec9606d960053dd7705e7179d502 - optee/optee_os/core/drivers/pl011.c +060e285588ec6082bcbf7f3b3c1907b0a98eb75c - optee/optee_os/core/drivers/semihosting_console.c +b195778e8106f48ecbe971f404a484cf3cb43d6c - optee/optee_os/core/drivers/widevine_huk.c +576097eeaf883a6a69e86b88a2364c3cd06450eb - optee/optee_os/core/drivers/stm32_uart.c +9203d1e334c03870efbb1296fc2b9151c8971267 - optee/optee_os/core/drivers/imx_sc_api.c +23020b20bb1b040dadd8e1d454b4d5a5b6229b09 - optee/optee_os/core/drivers/atmel_rstc.c +033052ada215ccb3f67e6643ef12c4b5665f0448 - optee/optee_os/core/drivers/atmel_shdwc_a32.S +1a2ee2977ed079a1526806d298af2550d23ec1c3 - optee/optee_os/core/drivers/stm32mp15_huk.c +fb0a553d5a6fdc9f6c00930976fae0be73b27535 - optee/optee_os/core/drivers/ls_i2c.c +22d95a3e938617774e29f89760c65f77f932f148 - optee/optee_os/core/drivers/ls_gpio.c +1427572daefd0b1d7949a5bf943320c3ce4b9733 - optee/optee_os/core/drivers/imx_ocotp.c +09898d9b6b3ce2ff6bfaca61a6b13f0b9cd4efab - optee/optee_os/core/drivers/tzc400.c +707867f2731e424b641a7ec3409ee954fb610f37 - optee/optee_os/core/drivers/tzc380.c +ba938d917edc42fd1e53f93a707cc9ff5ff45686 - optee/optee_os/core/drivers/scif.c +59a9c4ca5b114eddb0dbe6e37771eb8d04954d41 - optee/optee_os/core/drivers/atmel_wdt.c +2897acd81f2d1a3996adb59bd9dec1f0000f919c - optee/optee_os/core/drivers/versal_puf.c +f6e601063c224f648486bed923c509cb27a5d5cc - optee/optee_os/core/drivers/sp805_wdt.c +9f608bd36d7697b68b44c50cf8070bcfa4c872c0 - optee/optee_os/core/drivers/imx_rngb.c +514313602dfb100842f336c91efef495a658b3a9 - optee/optee_os/core/drivers/stih_asc.c +e14a90f2bcf9018fa5a0467d3681cb66d3f43369 - optee/optee_os/core/drivers/atmel_piobu.c +b234794403be1c10b3977fc742799919f7b5d16e - optee/optee_os/core/drivers/ls_sfp.c +23eed3a3d72852b8eda78fe73dfa5b7f7e5cb44d - optee/optee_os/core/drivers/zynqmp_huk.c +9fbe74cf959bf2b80b39c4cf5ff6d4cc0ed64759 - optee/optee_os/core/drivers/tegra_combined_uart.c +740e5cd3acbeb54e5e8bc8cce81aba50e2593a5d - optee/optee_os/core/drivers/bcm_hwrng.c +d727565a02416f45a77d93a9d363380f5f38ad79 - optee/optee_os/core/drivers/imx_scu.c +7ca34a8edb3c18eb51fa80927c8cf4f9ec8cca24 - optee/optee_os/core/drivers/plic.c +52c9fd38c2174bf6f84138c477cbee17c48cbded - optee/optee_os/core/drivers/bcm_sotp.c +c96f731961fc579a4966cae12e597d72c1ed06f3 - optee/optee_os/core/drivers/atmel_uart.c +7f6538800a647267da6f019328e5814cc7c1cbf5 - optee/optee_os/core/drivers/imx_csu.c +47509d9c897d567527308698b101326d495b6f43 - optee/optee_os/core/drivers/versal_pm.c +9c0fffe583ce8197aac49fa87c158bec166776ec - optee/optee_os/core/drivers/stm32_tamp.c +0c949972e03559a0168bc9e5b75be1c0fc00320f - optee/optee_os/core/drivers/atmel_shdwc.c +52d39e5794d051ab27898621b9ad9ad78caca1bc - optee/optee_os/core/drivers/ns16550.c +42b41e7d6dba7a7d9a97f8a296aa72adc0a42be5 - optee/optee_os/core/drivers/lpc_uart.c +29302475f05ea928763d589f7149ac31fb251bc6 - optee/optee_os/core/drivers/zynqmp_csu_puf.c +63f40f459d11f83bfa729e6bcaa98cd8d785d176 - optee/optee_os/core/drivers/stm32_rng.c +285a03d5b9f6657a5a74f219b40e639aac379b41 - optee/optee_os/core/drivers/zynqmp_csu_aes.c +e60b8921f76cb3ed026a112e561330bac6d39693 - optee/optee_os/core/drivers/stm32_i2c.c +9a6399d3b9a2944a5cfebf5b6c67e29dc97474e5 - optee/optee_os/core/drivers/pl022_spi.c +8c9bd89348d37d78be7efd291fc5f9279a62093d - optee/optee_os/core/drivers/cbmem_console.c +04ff6a848f0dd5e16fb7fd76e95ce39785601df1 - optee/optee_os/core/drivers/mvebu_uart.c +ddf2c0a622b6f91a81ac09e02fbca99d48e19dca - optee/optee_os/core/drivers/atmel_saic.c +2127927945e603116f83b2815f785f5b3daa9cd0 - optee/optee_os/core/drivers/imx_ele.c +45fe58e31faea84f641347c7bd70e426567d781b - optee/optee_os/core/drivers/serial8250_uart.c +1320b4d29ffd0a7d76b3bca9ca5b46c18addcc96 - optee/optee_os/core/drivers/ls_dspi.c +360698584af5e09cf3bab225cf66053d658552b6 - optee/optee_os/core/drivers/imx_wdog.c +90ef3f7cef8ca0b5ea51d6514433067919d92331 - optee/optee_os/core/drivers/versal_trng.c +453275821dbd497ee05f6e25f01e69a4a0e96732 - optee/optee_os/core/drivers/xiphera_trng.c +488329789386ed718c577ec619a4315c61bfad80 - optee/optee_os/core/drivers/imx_i2c.c +5ab383a1f35751f76041e860257e0e0a3c2589d9 - optee/optee_os/core/drivers/versal_gpio.c +37dd20ab884cd41cc9d03a23df71144b0b97a765 - optee/optee_os/core/drivers/stpmic1.c +336c2f714f6f3c8267473f821b95e998a63e3cd1 - optee/optee_os/core/drivers/versal_sha3_384.c +54a609280735c84a28f8d94cc34c03b2316634fe - optee/optee_os/core/drivers/versal_huk.c +0cdb9912f3a35cdd9d52951d5f489087f96d327b - optee/optee_os/core/drivers/amlogic_uart.c +5e0cb642d735a12ab5988ae85b3a92aa9ffef6f3 - optee/optee_os/core/drivers/hi16xx_rng.c +236e360ae321cce536a289ebec4b6424211b595d - optee/optee_os/core/drivers/gic.c +72c106642fd5baba523177b44cceb0e2dd268bb5 - optee/optee_os/core/drivers/zynqmp_pm.c +e26dcea60a7bdcf95acd06bb25f806e8b4d3d9ff - optee/optee_os/core/drivers/bcm_gpio.c +15006081e89bc8300728779c6253899a10614a9b - optee/optee_os/core/drivers/imx_caam.c +8d04ceb536a6bf4d80820154070d8c7c642edb42 - optee/optee_os/core/drivers/sprd_uart.c +c6562bca735f2354108d76425eb80d1786bc60f4 - optee/optee_os/core/drivers/atmel_tcb.c +0a0c075afc9d78481d4d5e31b27ffeb5b2268fd3 - optee/optee_os/core/drivers/stm32_gpio.c +095d526f4c1187395f09dc20e28b5250754c1797 - optee/optee_os/core/drivers/atmel_rtc.c +8294666cb76a8dde2dc2f1155586de082381312b - optee/optee_os/core/drivers/hi16xx_uart.c +f8a2cf16ad82a5a58a932430f4155678097f4ef4 - optee/optee_os/core/drivers/ls_sec_mon.c +a5bf3dc83db9f97617b33e477a531942b3e75d81 - optee/optee_os/core/drivers/stm32_etzpc.c +58426138a9216b6f14a2fe1b3d3cd6250525b28b - optee/optee_os/core/drivers/hisi_trng.c +c22ba5f5ef7f6a34235ad0d658510c6825b62d2e - optee/optee_os/core/drivers/stm32_iwdg.c +99907094047bf316222d7f0af9b7b043693a92fd - optee/optee_os/core/drivers/imx_uart.c +5aeb71fa00b57da2074319687b417f8cfce19043 - optee/optee_os/core/drivers/hfic.c +5f7af6748259588f30732bd198cada68ea449968 - optee/optee_os/core/drivers/versal_nvm.c +2ace80614760dbbe872200c0405c3e28fe6a5880 - optee/optee_os/core/drivers/cdns_uart.c +530fee444603ac95a1d3b87bca6a175a250b92f8 - optee/optee_os/core/drivers/stm32_bsec.c +4c9d2cdbfc272ae7e69a1bea5dd20c454eb958e2 - optee/optee_os/core/drivers/smccc_trng.c +fed0f01a801201479250f34692013a5bdd4225ca - optee/optee_os/core/drivers/dra7_rng.c +138292dd3d320deb98c7243cfdb71918c02e2afe - optee/optee_os/core/drivers/imx_snvs.c +b8c4ff65271508ceb0b46a94201aa3f0315e3558 - optee/optee_os/core/drivers/pinctrl/pinctrl.c +2cb2f913ef3999b884c98aef82fd8307f3d69169 - optee/optee_os/core/drivers/pinctrl/atmel_pio.c +d0a8fc04ba4bcf51aebf34a8ac8691193668dd78 - optee/optee_os/core/drivers/wdt/watchdog_sm.c +11ae5906c65655bea1e0310e78fe9a2cd6f87709 - optee/optee_os/core/drivers/wdt/watchdog.c +dec5d60dc6ea7b921fa5ed12484476228a08c0d4 - optee/optee_os/core/drivers/regulator/regulator_dt.c +8787994f69f69e02e156488324426826b16a27ed - optee/optee_os/core/drivers/regulator/regulator.c +04332d5beb8ff3dc39195861bc9ccb54f641b015 - optee/optee_os/core/drivers/regulator/stm32_vrefbuf.c +12f730c1d7f9187a40d66c3b90615e9c0e971d19 - optee/optee_os/core/drivers/regulator/stm32mp13_regulator_iod.c +1e600f477768bc97699dab081ae2d93d11d7ea47 - optee/optee_os/core/drivers/regulator/regulator_fixed.c +525682464b93345fd90c046fdce25d6f677a4f4a - optee/optee_os/core/drivers/regulator/regulator_gpio.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 +399fa3fd4b68a0c3ca446add566a9e832be98b0a - optee/optee_os/core/drivers/pm/sam/at91_pm.c +4af2105f9cb20e8151aae7f9f5b9343f9c80cc2e - optee/optee_os/core/drivers/pm/sam/pm_resume.S +7cae1c15dfe3d06ef928dd5eefa14a4aec1f9d6a - optee/optee_os/core/drivers/pm/imx/gpcv2.c +676549817f71135f3b0178c78c523c84b12e5082 - optee/optee_os/core/drivers/pm/imx/local.h +2b8c1f4839c1e5b0efe66bec52afdc1f63c37726 - optee/optee_os/core/drivers/pm/imx/src.c +e675276b10ee4b5f7b2b67729fbb657d4c4c9522 - optee/optee_os/core/drivers/pm/imx/psci.c +aef7b491a53e52047bf7dd3c9150eae717ecc458 - optee/optee_os/core/drivers/tegra/t234/tegra_fuse.c +6dde88cf82c01c28a6eb27bbb5520cd326e117a6 - optee/optee_os/core/drivers/tegra/t234/tegra_se_map_device.c +01aeb814d645694dbb3a7b6cba73a8dbdb00b2c5 - optee/optee_os/core/drivers/tegra/t234/tegra_rpmb.c +2fe53582494ad0c999f05bc6bb867f0515c2fe87 - optee/optee_os/core/drivers/tegra/t234/tegra_se_aes_rng.c +657b7a4a56f717718f15b36f8e647d6aa3c85e81 - optee/optee_os/core/drivers/tegra/t234/include/tegra_se_ccc.h +d0c05c35bf7b3a14be8f22ef4a1aadbe280144bb - optee/optee_os/core/drivers/tegra/t234/include/tegra_se_ccc_errno.h +bb5f09ed357b48f6a968eb465e43988280e2a5a2 - optee/optee_os/core/drivers/tegra/t234/crypto/tegra_driver_hash.c +2aec9a4db595681f9bd4907d81cf0244c992b8a8 - optee/optee_os/core/drivers/tegra/t194/tegra_fuse.c +c67e3cfb2ca9a5fa42769943cc7e64cd190651af - optee/optee_os/core/drivers/tegra/t194/tegra_se_aes.c +e09c85691a66c623638973ebd587a1986680786d - optee/optee_os/core/drivers/tegra/t194/tegra_se_rng1.c +3b96618ecaf4ddecb14a6af70d8f80d32724299d - optee/optee_os/core/drivers/tegra/t194/tegra_se_mgnt.c +59b8fddcab1c4118b35c29a98d2e68efe471715a - optee/optee_os/core/drivers/tegra/t194/tegra_rpmb.c +88ee29ff327c35524c79fd85e9c71ffff90df695 - optee/optee_os/core/drivers/tegra/t194/include/tegra_se_mgnt.h +17ddfcb103fb3b6272fb935b6ffcf6c9277d809e - optee/optee_os/core/drivers/tegra/common/tegra_driver_se.c +174f41f9f1e928f7ec63d51501a4cec4655cdba2 - optee/optee_os/core/drivers/tegra/common/tegra_driver_fuse.c +7f9f2a7e263e7cf21f1f3f2a249d984671a196c0 - optee/optee_os/core/drivers/tegra/common/tegra_driver_srv_intf.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 +db6b2d8179fcbc42da79480d5ee5d0ee046b8459 - optee/optee_os/core/drivers/tegra/common/tegra_driver_rng1.c +542a320020446e6712e8518616780ed091faf0de - optee/optee_os/core/drivers/tegra/common/include/tegra_driver_rng1.h +3a4cc745a837a9ffdf0c17d7ae2bea7f54161d79 - optee/optee_os/core/drivers/tegra/common/include/tegra_driver_fuse.h +1ed70b78a41a680b9fd609b2756145e19af309e6 - optee/optee_os/core/drivers/tegra/common/include/tegra_driver_srv_intf.h +352d6c58d195d5c44b8e06c006e713fe506dc77e - optee/optee_os/core/drivers/tegra/common/include/tegra_driver_common.h +4ee2de7e913868ad183b6f5459e97292199bac93 - optee/optee_os/core/drivers/tegra/common/include/tegra_driver_se.h +0f8548c5da8a36282a4683b4cbe749a21cd08cb9 - optee/optee_os/core/drivers/remoteproc/stm32_remoteproc.c +758385879c9afaea1eb9f1b85e07def0dadde420 - optee/optee_os/core/drivers/nvmem/nvmem_huk.c +00216a3e7662c8e93065826fcc5b9d1a08a3a0d4 - optee/optee_os/core/drivers/nvmem/nvmem.c +5c85e3f66b00f377246a021e0206af4ca134af19 - optee/optee_os/core/drivers/nvmem/atmel_sfc.c +f7988928ec7527a764000f09149daab97a93ae98 - optee/optee_os/core/drivers/nvmem/nvmem_die_id.c +ad920986e4bc0e99a570d96563a8fd651d98e5c6 - optee/optee_os/core/drivers/firewall/stm32_rif.c +1fe13991952d6bbc693b33615e294315900f9522 - optee/optee_os/core/drivers/firewall/stm32_rifsc.c +9c919e1b7826c8bad2ba459cc8cd4ce0035a8c45 - optee/optee_os/core/drivers/clk/clk_dt.c +497491c5aa9f4b7533a2de992b9c5ae414f45cb3 - optee/optee_os/core/drivers/clk/clk.c +2f5ae6ad224c7a1ce0808c19972c7e819292c0dd - optee/optee_os/core/drivers/clk/clk-stm32mp13.c +df9d03048fb6affa7b0eb30f116f370f8194db93 - optee/optee_os/core/drivers/clk/clk-stm32mp15.c +1432346fe6a161fe80162595b76f60e63689f1d2 - optee/optee_os/core/drivers/clk/clk-stm32-core.c +98169c49a2b31260fbbbbe0a0394251d9b62cc4f - optee/optee_os/core/drivers/clk/fixed_clk.c +c8f48d30481a1983d8c5991574a486ed83ebef49 - optee/optee_os/core/drivers/clk/clk-stm32-core.h +6e8872e62a9bcb7b22bd63c492045b8e3610c851 - optee/optee_os/core/drivers/clk/sam/sama5d2_clk.c +48f146dde6d5ca943dbc1c3d3e909da6c816cb42 - optee/optee_os/core/drivers/clk/sam/at91_peripheral.c +b101367d257bc9abab7f6653946a5290c6beb2f0 - optee/optee_os/core/drivers/clk/sam/at91_pmc.h +18acdc71569e2a780d0476642f03bc85218be532 - optee/optee_os/core/drivers/clk/sam/at91_plldiv.c +530a8ac463371dd1e9b7fa1c1ca9e30c7958808b - optee/optee_os/core/drivers/clk/sam/at91_system.c +fe1488b5f2e77d0468227c7cfc2a30712d2b529c - optee/optee_os/core/drivers/clk/sam/sama7g5_clk.c +7b04bf02eb44efee1878613f81656fd5acf46b86 - optee/optee_os/core/drivers/clk/sam/at91_generated.c +c99eceb036f865d8c6c2df48b7dd402af247fd34 - optee/optee_os/core/drivers/clk/sam/at91_programmable.c +c1c10c6ffec3be99f161ce8c6e467efd939ff7d4 - optee/optee_os/core/drivers/clk/sam/at91_utmi.c +13078eaf7868f4a2a4dcd703d8eadc76630f1b3d - optee/optee_os/core/drivers/clk/sam/at91_usb.c +e90a1c0ffe8e8d869859768ddc4f978630f52990 - optee/optee_os/core/drivers/clk/sam/at91_pll.c +3cc6160c3ae52400111c85d3c4ce08d787630856 - optee/optee_os/core/drivers/clk/sam/at91_i2s_mux.c +1cf0a55892076fb8587178bf570a91ba7a2ba82a - optee/optee_os/core/drivers/clk/sam/at91_main.c +12cb9cf9414303b0fe7c636c24a94b413fcbbf24 - optee/optee_os/core/drivers/clk/sam/at91_master.c +3e57a61dcae8fc7e3b0a9ef6fa21b454f0a6ab99 - optee/optee_os/core/drivers/clk/sam/at91_sckc.c +1050ecd58ec5f9140571e29544df45407324d89c - optee/optee_os/core/drivers/clk/sam/at91_audio_pll.c +8771db99eec65c3ff322515b835e8bda8f4ebe4d - optee/optee_os/core/drivers/clk/sam/phy-sama7-utmi-clk.c +92fb0755687c8983cedc51f140de48967a4f16a6 - optee/optee_os/core/drivers/clk/sam/clk-sam9x60-pll.c +2b9eb96b9e23c5b50710c6cb81e630ded5600812 - optee/optee_os/core/drivers/clk/sam/at91_clk.h +8cd3321b319b3e9c1131a8ccb02eaa043ff64f3d - optee/optee_os/core/drivers/clk/sam/at91_pmc.c +152f3551f54e3ee176d8a09bd21b8692d3d34ae0 - optee/optee_os/core/drivers/clk/sam/at91_h32mx.c +67bb3144d0d145d7b6f806fe9f77c21ee007c9c0 - optee/optee_os/core/drivers/rstctrl/stm32_rstctrl.c +6ea97a6c89fdbbb425562f878dd045fd6f626046 - optee/optee_os/core/drivers/rstctrl/rstctrl.c +15a98472af569d660b8ba57d3e4515f74ad49743 - optee/optee_os/core/drivers/scmi-msg/clock.c +a5fb58a50b0ccc0dde34d6fa91b0b03c5e0ca554 - optee/optee_os/core/drivers/scmi-msg/voltage_domain.c +13ed9520d3f452a3b5919a38066b702cc2f31c5b - optee/optee_os/core/drivers/scmi-msg/reset_domain.c +33be09787080f4627f5fdc10d7378880994ded05 - optee/optee_os/core/drivers/scmi-msg/entry.c +93be063666a6a98dd1fa8f45bba0c3ca91136171 - optee/optee_os/core/drivers/scmi-msg/voltage_domain.h +c85de6ce4c133bc5d968be70c2b068b613042d31 - optee/optee_os/core/drivers/scmi-msg/clock_generic.c +b6dc570c20e25ebbb69c815e65c4e3a77f6cf00d - optee/optee_os/core/drivers/scmi-msg/reset_domain.h +cf9d967498746a73d9d033a11d89d20a95631dc6 - optee/optee_os/core/drivers/scmi-msg/base.c +0faefd362396637c831c3c6823053228443f5778 - optee/optee_os/core/drivers/scmi-msg/smt.c +1420d3d8ef64053f5b6cbf009539fd6ddddf6e95 - optee/optee_os/core/drivers/scmi-msg/common.h +fbee23ad24545aea0bd9fd6ae6b67e9acc2ef16f - optee/optee_os/core/drivers/scmi-msg/base.h +189d1a32fdc699c67e4da64ae26380a2b3facd66 - optee/optee_os/core/drivers/scmi-msg/clock.h +ac6217df4e25acd1b996d379ee7dc022ea03e8a8 - optee/optee_os/core/drivers/scmi-msg/shm_msg.c +d103d5da1feea200154f02a82697d86c6294c0f4 - optee/optee_os/core/drivers/i2c/atmel_i2c.c +7da841080f45a989a835a1fec30f6aa50d847b10 - optee/optee_os/core/drivers/i2c/i2c.c +34825682d3731dc9ea51680257ae795e76a288f2 - optee/optee_os/core/drivers/imx/dcp/dcp_huk.c +590ea022b10a9c7283c5ffc2433de61c90148fb2 - optee/optee_os/core/drivers/imx/dcp/dcp_utils.c +0d6b0a14fd3b05ba3c8c21eb1a895e8e3ba465e4 - optee/optee_os/core/drivers/imx/dcp/dcp.c +2b2febd277aeda9813289b22b87000c559b8e4d8 - optee/optee_os/core/drivers/imx/dcp/include/local.h +2086f64aaa2a6e6c7903ab74de13c177b978297d - optee/optee_os/core/drivers/imx/dcp/include/dcp_utils.h +536893e1752c9cfee18bc1228f09fa04c0971db1 - optee/optee_os/core/drivers/imx/mu/imx_mu_8ulp.c +975a25a6b342dfc2b466f157acaf11910eb0c3b3 - optee/optee_os/core/drivers/imx/mu/imx_mu_platform.h +1ba75e71228b378cb3c43d6ba87f3d11140b855b - optee/optee_os/core/drivers/imx/mu/imx_mu.c +555963669dcfbb957e415c040be083676f914c2e - optee/optee_os/core/drivers/imx/mu/imx_mu_8q.c +a7009131f76447718645c703ed1373bd329a4528 - optee/optee_os/core/drivers/bnxt/bnxt_fw.c +49865544561297dc1688131470c0baaa35112a86 - optee/optee_os/core/drivers/bnxt/bnxt.c +7651789fc830ed002efb38c51f34bda32a3e8e46 - optee/optee_os/core/drivers/bnxt/bnxt_images.c +289d35c3f71ddb7a5f121fb6723e63538130bb47 - optee/optee_os/core/drivers/gpio/gpio.c +0167f0613b4286349c7403ea6c9a7dfe0a322533 - optee/optee_os/core/drivers/crypto/aspeed/hace_ast2600.c +ecc8a0a2fa12870fc85783fb7f60d717f6bf40d5 - optee/optee_os/core/drivers/crypto/aspeed/hace_ast2600.h +2702c09d55cbed00cd7326d5d6e35b12126fbe96 - optee/optee_os/core/drivers/crypto/aspeed/crypto_ast2600.c +828360f1fe0d8cb9892dd9b467df8cf52e119eea - optee/optee_os/core/drivers/crypto/versal/ipi.c +098e2cd056d7c0109c48e1c0fe7fa13577cdd79e - optee/optee_os/core/drivers/crypto/versal/authenc.c +af9a8f5b582e42214ef925abde8ba38ad8bf8763 - optee/optee_os/core/drivers/crypto/versal/ecc.c +0c3d0695339eaa6535604758e28d42e1177c52cd - optee/optee_os/core/drivers/crypto/versal/rsa.c +a7d7f00d8287e6bad7ec81709ec0463d5f483dcb - optee/optee_os/core/drivers/crypto/versal/include/ipi.h +e2ede389a1c5a24403439cd397bc8a69fc16ac0d - optee/optee_os/core/drivers/crypto/se050/session.c +374c26b225f2311ce209fecac1317c2566d76f5b - optee/optee_os/core/drivers/crypto/se050/adaptors/include/se050.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 +4732906bb4ca33cb409bd901b0c94c24a26055a4 - optee/optee_os/core/drivers/crypto/se050/adaptors/include/se050_user_apis.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 +3238acd7dd2e169621bbe8ab9e9f93372f6b111b - optee/optee_os/core/drivers/crypto/se050/adaptors/utils/scp_config.c +ad754aaaf0b0850065a9e68027ee82642a44e817 - optee/optee_os/core/drivers/crypto/se050/adaptors/utils/info.c +6e42bccb8cc7140adefd2baee2a8f2b2c9757348 - optee/optee_os/core/drivers/crypto/se050/adaptors/utils/utils.c +05b8cb927ce8c6dc6b2c3391b71366cf1b9dfc89 - optee/optee_os/core/drivers/crypto/se050/glue/user.c +75e0506e1992b38a38a83d6805b15b095924a783 - optee/optee_os/core/drivers/crypto/se050/glue/i2c.c +64681be01124b403991ca09721e4e6c6e023b72e - optee/optee_os/core/drivers/crypto/se050/glue/i2c_imx.c +c0ffc8ba7635af755f6bc8dabf96b142cd473202 - optee/optee_os/core/drivers/crypto/se050/glue/i2c_stm32.c +bc9e0c1bff88a8c8a8b844d676d9ac9d76658357 - optee/optee_os/core/drivers/crypto/se050/glue/include/i2c_native.h +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 +ddc645a154efbbe06890e01fc9d2e8456eba3849 - optee/optee_os/core/drivers/crypto/se050/core/apdu.c +2bfc19e0e0e85d9305249130e474588e60b28f37 - optee/optee_os/core/drivers/crypto/se050/core/cipher.c +432313af00fe913874dd57175755d4c140cc0f23 - optee/optee_os/core/drivers/crypto/se050/core/ecc.c +acd04d6ec81f1e8fcd19581e8e7d194f372b861d - optee/optee_os/core/drivers/crypto/se050/core/ctr.c +07804a4e636cd6a530a1ed8a87a523615ece79b7 - optee/optee_os/core/drivers/crypto/se050/core/storage.c +cde6ea6e53f00b5a9bd70d2d430f7380e0136efd - optee/optee_os/core/drivers/crypto/se050/core/rsa.c +77ac6992ffdbc505fd3b8113c9335ea835c5f6c1 - optee/optee_os/core/drivers/crypto/se050/core/include/se050_cipher_algorithms.h +1a9e16344dbc4eb636d939a82a556a5d286c7dd9 - optee/optee_os/core/drivers/crypto/hisilicon/hisi_qm.c +5385e76fe8f2e229eb77cffd4ae238c21c482293 - optee/optee_os/core/drivers/crypto/hisilicon/hpre_main.c +e06579463785ebd66688b38bd65af92ef788947f - optee/optee_os/core/drivers/crypto/hisilicon/include/hpre_main.h +757cdaf6c60a48e7779b7da7052b35ccf8c09382 - optee/optee_os/core/drivers/crypto/hisilicon/include/hisi_qm.h +601b922f3c15a1c4d5abb05d995f5735c1e356b9 - optee/optee_os/core/drivers/crypto/stm32/stm32_cryp.h +2f3ab4f2cb6b5d01d0b5e7842bed6baf91e5d182 - optee/optee_os/core/drivers/crypto/stm32/stm32_saes.h +8199d52c7baf643957c32674f889260cf2341dbb - optee/optee_os/core/drivers/crypto/stm32/authenc.c +b5f0d8262b85306d730358c44941245a067cb25a - optee/optee_os/core/drivers/crypto/stm32/stm32_saes.c +fcbed8594a9eb90a38465eb15df80cdbf4a1deb5 - optee/optee_os/core/drivers/crypto/stm32/cipher.c +fb67584aabc078f87f6267ea7306f830e0e46064 - optee/optee_os/core/drivers/crypto/stm32/stm32_cryp.c +b179d07b90bf70b2ed08a34fbf03c9294d1a205b - optee/optee_os/core/drivers/crypto/stm32/common.h +efb3950cfa10b5ba1a647d083e5aa06e6a5378e8 - optee/optee_os/core/drivers/crypto/caam/caam_ctrl.c +3961eb920e409de78ae8d214ce44f802b27a379c - optee/optee_os/core/drivers/crypto/caam/caam_jr.c +e50b088ae52c3e7016bce9511e39b1adfa3f0b4a - optee/optee_os/core/drivers/crypto/caam/caam_desc.c +699a8346a6775299a19d00eda00fa748fe04892d - optee/optee_os/core/drivers/crypto/caam/caam_rng.c +5abf9725310659d557245e78b391f46a589f065a - optee/optee_os/core/drivers/crypto/caam/caam_pwr.c +df4f77213b909b92241663307cddf6ab6f950c8c - optee/optee_os/core/drivers/crypto/caam/caam_key.c +f3959046a0ae29e21707eb07d7635232d3412a6e - optee/optee_os/core/drivers/crypto/caam/caam_sm.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 +ae43fe99412d31c2f21f732a6798cda49fa12d3d - optee/optee_os/core/drivers/crypto/caam/hal/imx_8m/hal_clk.c +e2251ce08c70bf59c08a56cd48659683536708df - optee/optee_os/core/drivers/crypto/caam/hal/imx_8m/registers/ctrl_regs.h +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 +dc2680e783f647bce21513453573f8f426d9ae8d - optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/hal_clk_mx6.c +a8796a5f28445049f810dd2b2cf6bd4700d39090 - optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/hal_clk_mx7.c +fee09baaa8fd82c62ecca9d059220329bb51e466 - optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/registers/ctrl_regs.h +75e141d842a44be2fc54fc9aa3d6233d43786cf8 - optee/optee_os/core/drivers/crypto/caam/hal/common/hal_cfg_dt.c +aad80d84aafe3253f980f8e72ad014fa860f51ac - optee/optee_os/core/drivers/crypto/caam/hal/common/hal_jr.c +bbed4e39b9bcd1f945beda876fda141a02a74f4b - optee/optee_os/core/drivers/crypto/caam/hal/common/hal_ctrl.c +8db1294f384bce6384f85139c546c8efbb4fe62c - optee/optee_os/core/drivers/crypto/caam/hal/common/hal_rng.c +b16e31abdbe671ee4a824e1bb701902be03edb0d - optee/optee_os/core/drivers/crypto/caam/hal/common/hal_sm.c +62b95ec89eb5763cd260f23face8cdb73f51bc9e - optee/optee_os/core/drivers/crypto/caam/hal/common/hal_cfg.c +e7c18e488182d4bf3c8c821885db52c980fb5f7a - optee/optee_os/core/drivers/crypto/caam/hal/common/registers/version_regs.h +1061deddc2311407d8fa66dfe6df6e9c74ffda39 - 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 +79bf2c681239bff0327007e0823aa9bc43f46ae5 - optee/optee_os/core/drivers/crypto/caam/hal/common/registers/sm_regs.h +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 +7bbd78ddb18f062b0ee9521f445979c6acb2ee1e - optee/optee_os/core/drivers/crypto/caam/hal/imx_8ulp/hal_clk.c +dc66e73bb6be55941cae77b073fdaab8d4badfc5 - optee/optee_os/core/drivers/crypto/caam/hal/imx_8ulp/registers/ctrl_regs.h +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 +05f90a24f3fbacc399604028453c4885f1e107f0 - optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/hal_rng.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 +aa940d1d85879826ef54d8a93ceac16d8134c9f9 - optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/registers/ctrl_regs.h +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 +ad05613f64dba65f1576f358f3d0ad0182e393f3 - optee/optee_os/core/drivers/crypto/caam/hal/ls/hal_clk.c +db232940b3c2f122c53b11e6dec5e70c5ec347d8 - optee/optee_os/core/drivers/crypto/caam/hal/ls/registers/ctrl_regs.h +1c222211eb56c4447e53ae06851aeb468c7423c1 - optee/optee_os/core/drivers/crypto/caam/acipher/caam_ecc.c +b344e97a5a51b3bc2f8cb52dcc2fe9adbdaa3e02 - optee/optee_os/core/drivers/crypto/caam/acipher/caam_dh.c +f677ba67d639efb7e1d7aebdc1a4b96eca37fa2f - optee/optee_os/core/drivers/crypto/caam/acipher/local.h +809e7d9d1c8018be4c447fa948a3954dbd7738ab - optee/optee_os/core/drivers/crypto/caam/acipher/caam_prime_rsa.c +7b9390d54de54fa7f6778b6a73a75799cb97fe1f - optee/optee_os/core/drivers/crypto/caam/acipher/caam_math.c +eca8db4225df0c60977968141451b3500fd30eda - optee/optee_os/core/drivers/crypto/caam/acipher/caam_dsa.c +91c843a382b813a556a3192e3b89d4f6e2330afe - optee/optee_os/core/drivers/crypto/caam/acipher/caam_prime_dsa.c +3be0a9dac0a7d29db56b054f58f8483795177eb6 - optee/optee_os/core/drivers/crypto/caam/acipher/caam_rsa.c +981c3652730c78df0fa0ab1841ce939ae699d9f9 - optee/optee_os/core/drivers/crypto/caam/cipher/caam_cipher.c +b1050722e24889ba59c987cb274897949dcd39a7 - optee/optee_os/core/drivers/crypto/caam/cipher/local.h +7c67490b6b2e00a9435c568bac2bbee4069ccc38 - 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 +240eae18f54b7ba6f442845afea7c4b916b911f8 - optee/optee_os/core/drivers/crypto/caam/hash/caam_hash_mac.c +d8824580f4b1889d9a23ddd2047c3b102b9e7a17 - optee/optee_os/core/drivers/crypto/caam/hash/local.h +731f10c0a7fe34860f0d1d21271b01a8a378b1a9 - optee/optee_os/core/drivers/crypto/caam/hash/caam_hash.c +0a5a24f76cbb0ec22c85016a7db24bb4694e66cc - optee/optee_os/core/drivers/crypto/caam/mp/caam_mp.c +2f780d7215aa1c23b998dfe17edabba1d0f4b1f9 - optee/optee_os/core/drivers/crypto/caam/include/caam_acipher.h +eb20c569c7f68eb8f8a1eb16eb82c24a8ac4cd9b - optee/optee_os/core/drivers/crypto/caam/include/caam_jr.h +912d6553b392b20581d016f9eba91479662d6062 - optee/optee_os/core/drivers/crypto/caam/include/caam_blob.h +1f43c71456b997c24eb44cfb6ce30f4558931b42 - optee/optee_os/core/drivers/crypto/caam/include/caam_utils_status.h +d43f75ad0f55131ccce9ec1aa4ca58872a8fc8b7 - optee/optee_os/core/drivers/crypto/caam/include/caam_desc_defines.h +3cefd9acd10d65bb6c61f2e0aec31f43e48f6abb - optee/optee_os/core/drivers/crypto/caam/include/caam_utils_mem.h +f782be2c739055bbdf95842d912e891293d0c1fb - optee/optee_os/core/drivers/crypto/caam/include/caam_hal_rng.h +bc18f3fc396e705bd01c6d443fa911800700bb8d - optee/optee_os/core/drivers/crypto/caam/include/caam_hal_ctrl.h +631d3ce5a38c82b07ae1a14ee6b6cb5ef95d32ba - optee/optee_os/core/drivers/crypto/caam/include/caam_status.h +2ffbbb6180a3ba5fcc49f2958836e6391a2c7375 - optee/optee_os/core/drivers/crypto/caam/include/caam_hash.h +3831fd7967d2e9a71b3b958e87a4dc3f1eb38261 - optee/optee_os/core/drivers/crypto/caam/include/caam_hal_sm.h +898dd496c1a8f25b592f261d9d13a74d3873ff7e - optee/optee_os/core/drivers/crypto/caam/include/caam_pwr.h +a1083a9ff0bc9f8b3c8fbd60ea263a88488951a3 - optee/optee_os/core/drivers/crypto/caam/include/caam_desc_helper.h +7c8acb595959705bbf481d1ffcdda173637dccbf - optee/optee_os/core/drivers/crypto/caam/include/caam_mp.h +f60708cc4c84df857fc20cdef0710a388ecd56f8 - optee/optee_os/core/drivers/crypto/caam/include/caam_io.h +74a055714e2db637adc0291d19cea1c02974e030 - optee/optee_os/core/drivers/crypto/caam/include/caam_hal_clk.h +ee68dcf290038d3ebad07beabb3517b5860bc3f5 - optee/optee_os/core/drivers/crypto/caam/include/caam_utils_delay.h +7be3b8463755df707782bdaee0ed26c692c0f32b - optee/optee_os/core/drivers/crypto/caam/include/caam_jr_status.h +aedd672ed034e8265f35ebab812a5af4135e94d2 - optee/optee_os/core/drivers/crypto/caam/include/caam_rng.h +7e8b656ec0076e7092003e5db98cbed4ea9a458b - optee/optee_os/core/drivers/crypto/caam/include/caam_trace.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 +b6481ab7a2c7318250e4e38c57291ffa69016129 - optee/optee_os/core/drivers/crypto/caam/include/caam_sm.h +d23a06ce5206f043b33f8ee8d4e6bfd62d8bb981 - optee/optee_os/core/drivers/crypto/caam/include/caam_types.h +8266a0db8e50af51f61dbe0ad34e4c4f30dbfc1a - optee/optee_os/core/drivers/crypto/caam/include/caam_key.h +0d6de8f72472e2554ab7666852ac52a37175465f - optee/optee_os/core/drivers/crypto/caam/include/caam_utils_sgt.h +547857b357f6594d407d46fcab2f93fa7074d3cd - optee/optee_os/core/drivers/crypto/caam/include/caam_common.h +42cc84af73a8980ed1e51aac57b7ac2bfe8ea567 - optee/optee_os/core/drivers/crypto/caam/include/caam_hal_cfg.h +3a804ad72278dc57b300a9df498d00db63fcefb6 - optee/optee_os/core/drivers/crypto/caam/include/caam_utils_dmaobj.h +cfa13823918f625810c9958b6499358d179c8960 - optee/optee_os/core/drivers/crypto/caam/include/caam_desc_ccb_defines.h +eb43fbde76dd94674bb94f9d314b9c0246403ac0 - optee/optee_os/core/drivers/crypto/caam/blob/caam_blob.c +5d2441d5350d00687dd8e35d19f42faedbb632ee - optee/optee_os/core/drivers/crypto/caam/blob/caam_dek.c +0f4455a2b7723d3cc63f4f0d0623d29b0363b39a - optee/optee_os/core/drivers/crypto/caam/utils/utils_status.c +a5f84b35d9776908441db01241d508dfe83a3347 - optee/optee_os/core/drivers/crypto/caam/utils/utils_dmaobj.c +06d77bc7f344869783912b109cd485ef4e8590ad - optee/optee_os/core/drivers/crypto/caam/utils/utils_mem.c +a34c25f439fb74912fddf47fac4b0295ba1effa6 - optee/optee_os/core/drivers/crypto/caam/utils/utils_sgt_v1.c +130800ee65979019cc2117d690340aaa75cd92a9 - optee/optee_os/core/drivers/crypto/caam/utils/utils_sgt.c +dc70d7f20e3b0430b6dd2fe0dd0261c929d3db6a - optee/optee_os/core/drivers/crypto/caam/utils/utils_delay.c +7c483d7465e733ab3503e26d161daafaa25755be - optee/optee_os/core/drivers/crypto/caam/utils/utils_sgt_v2.c +bb297b79a3f0cc6cb59b1a18f8d19242c9fc12b7 - optee/optee_os/core/drivers/crypto/crypto_api/drvcrypt.c +a6e4483d1fd80f6f7f23a89a9e1ead0fbfcf65d9 - optee/optee_os/core/drivers/crypto/crypto_api/mac/mac.c +d235d21c1de200d48e91b12063eb2f8f1caf0881 - optee/optee_os/core/drivers/crypto/crypto_api/acipher/local.h +38819ea8744620f296d47e0b1cab78567242c9fc - optee/optee_os/core/drivers/crypto/crypto_api/acipher/rsassa.c +46947c70982d23fe999c5a70666a676833b13725 - optee/optee_os/core/drivers/crypto/crypto_api/acipher/ecc.c +013e32cb9018761e86ee0b8b5d19b5c2089902db - optee/optee_os/core/drivers/crypto/crypto_api/acipher/rsamgf.c +979dd11c468df335b342654f7263949e51d1535a - optee/optee_os/core/drivers/crypto/crypto_api/acipher/dsa.c +7ac822e6fdd1cdb08537631b7e8a3a823a0af57e - optee/optee_os/core/drivers/crypto/crypto_api/acipher/rsa.c +1e295f6ab5c32f104ea23abb3978af44f64547bf - optee/optee_os/core/drivers/crypto/crypto_api/acipher/dh.c +8ddc0db04f5251ffd3c0beb7d3947298685d5cf4 - optee/optee_os/core/drivers/crypto/crypto_api/cipher/cipher.c +5104681db824caa455d34ffcb91e6bad1b8afad7 - optee/optee_os/core/drivers/crypto/crypto_api/oid/hash_oid.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 +622acb83b02d0d5e1f8cc107df2871c1d99220b5 - optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_math.h +f8f01711239d5a9fc6ece9f19e40d2f805b04c3a - optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_authenc.h +b70e470e5e716917b0983224109234da6d526139 - optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_asn1_oid.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 +8a2b361dc6d53a49514314969ea94af861314241 - optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt.h +bd9d68e0b833479e5a83ac90bbb55776791434c0 - optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_acipher.h +30d67ef67cd36d0794f2055d1705d14905f3ab0b - optee/optee_os/core/drivers/crypto/crypto_api/authenc/authenc.c +3502395b082081a4c3f6e68c5f0774a90715d7bd - optee/optee_os/core/drivers/crypto/crypto_api/math/modulus.c +b1b96d68d4bf3e82a538f91afea8b87b5c0f43f6 - optee/optee_os/core/drivers/rtc/rtc.c +843216e2097db39b59f4ed88b5f4422475008878 - optee/optee_os/core/tests/notif_test_wd.c +22edc57cadee3b6787489b0d44956d4bbeec2ab6 - optee/optee_os/core/tests/ftmn_boot_tests.c +95db84ed2db1edad93dd163e910a57e8a493e1af - optee/optee_os/core/kernel/ubsan.c +a81400384a7af050ce6655fe6cbce6764c11336c - optee/optee_os/core/kernel/tee_misc.c +3eab63aa13442a732d757c7b98dcbf84c5ca5782 - optee/optee_os/core/kernel/notif.c +1beba0db1ff1f826641fd640ce1927e68758f838 - optee/optee_os/core/kernel/early_ta.c +0a4f43b4d4ae6202abe451e4d5b89b295b6c69ab - optee/optee_os/core/kernel/nv_counter.c +c150b4e1f0b0906ce608d1354af8d0a722da86e7 - optee/optee_os/core/kernel/dt_driver.c +3f6a42889e84d4b674901b0cc5d83f5146e84506 - optee/optee_os/core/kernel/trace_ext.c +816e78200c8dc67e4942dc7453e0b3244e3b2aea - optee/optee_os/core/kernel/dt.c +9ac56717aa2a733944a03a9646b90bc16d817535 - optee/optee_os/core/kernel/mutex.c +aeea2000adf22742f11bf2f37577da2d641ba9ff - optee/optee_os/core/kernel/ldelf_syscalls.c +2434b4d3b027cbf76b22f7245fd1764390bfe3a1 - optee/optee_os/core/kernel/user_access.c +309c59c03e9e9577dff0819b23e420d73280278b - optee/optee_os/core/kernel/refcount.c +7be1928ee7e34f7f47f52b99bce43e0024f06a44 - optee/optee_os/core/kernel/assert.c +417bc2dbf92f6a481e18233c7237d492361f4106 - optee/optee_os/core/kernel/panic.c +44103fc460d59f0a919bb3c07cf1944aa91ae2f4 - optee/optee_os/core/kernel/tee_time.c +8b3381928033ddd7c37a99aad2e60a229fbcdbd6 - optee/optee_os/core/kernel/embedded_ts.c +9975d02cd73795987cd451389809dfce9a902e9b - optee/optee_os/core/kernel/user_mode_ctx.c +d259aa482d7c511f3d52cfeaa64953ad08d56223 - optee/optee_os/core/kernel/ree_fs_ta.c +28790afb155662f972fbd11f4d06c6baf1c54260 - optee/optee_os/core/kernel/pseudo_ta.c +cabaa99807cb88c99fde2bd61eeb6768e35983e3 - optee/optee_os/core/kernel/console.c +fd81d6b6ad33c46f7627aeb1afb49530b9c36898 - optee/optee_os/core/kernel/ldelf_loader.c +221e610e4adbc3cd9e97867d9d1ae548a818fdfd - optee/optee_os/core/kernel/ts_manager.c +93124514b7ec652f01b26753e0fbe172e526412c - optee/optee_os/core/kernel/tpm.c +55966f5406e5879e4b98143e47868368d9247225 - optee/optee_os/core/kernel/callout.c +f31d663584038d598520283f7cea7ff093871a2d - optee/optee_os/core/kernel/tee_time_ree.c +94e2c0c379ce289434664a0320006df2fbae034b - optee/optee_os/core/kernel/msg_param.c +892e55c191245007f2bf20567c307871cd426060 - optee/optee_os/core/kernel/interrupt.c +e0f7be46eb2d862733bba0c834997c6d4203d425 - optee/optee_os/core/kernel/pm.c +a26e6665b04355864f7f98807e57d6d4d568fc63 - optee/optee_os/core/kernel/notif_default.c +bf3cb1de7bd749b2628925f3a1b32fa1b6085826 - optee/optee_os/core/kernel/transfer_list.c +98fd2892161b2b537e6e91e8e7c6f6a59c55de82 - optee/optee_os/core/kernel/semihosting.c +76b1d45323c31ed6bd5987d7d7400d15d4832eee - optee/optee_os/core/kernel/delay.c +ed43b747e9e9f2732be9fde2e036575eb84fbae0 - optee/optee_os/core/kernel/scall.c +9323261c4542f4f78ce0668852a81df361a9953e - optee/optee_os/core/kernel/initcall.c +de1675480ef4043349e0bc3875749598f8092a54 - optee/optee_os/core/kernel/show_conf.c +693a3b47871398f69679ce69211649fcf704261b - optee/optee_os/core/kernel/asan.c +1392391e0dc7cfbd68e9b5738cb0b747ed13ab29 - optee/optee_os/core/kernel/wait_queue.c +bccabf562ac6d81f8c7d94841b23d160fb1a48ac - optee/optee_os/core/kernel/tee_ta_manager.c +7aeef825f355d2436dc4fd47d92ca857decaa195 - optee/optee_os/core/kernel/spin_lock_debug.c +21449d26573f5cefed595f37780b901b7b937304 - optee/optee_os/core/kernel/mutex_lockdep.h +813e8ed14c578b5b735b29cae3bbb42af9f03a58 - optee/optee_os/core/kernel/handle.c +1b0bede72d10c96c528f188c6afdecf4306b97bf - optee/optee_os/core/kernel/secstor_ta.c +8abe5fcfb8a632e1c77c0e0f92bbc0414f1e2857 - optee/optee_os/core/kernel/mutex_lockdep.c +1962b8040874d00636c9541f532f3ee5b2ef4f16 - optee/optee_os/core/kernel/scattered_array.c +2a1975e7689ec6a1b519c0301e47924240440878 - optee/optee_os/core/kernel/thread.c +6e6b6a100da1286e715cf135ad873d4bf9063715 - optee/optee_os/core/kernel/user_ta.c +02448f355229caa2a32a4411c3198eb084395320 - optee/optee_os/core/kernel/lockdep.c +f4b199a80f0476f43f34060f72493f81a289748e - optee/optee_os/core/kernel/otp_stubs.c +f7c65c67d04a7829967fe1b8c657314f645a5ab9 - optee/optee_os/core/kernel/huk_subkey.c +2bfc17f9e38fa5fd9c637a5cd1ddcce6300ced48 - optee/optee_os/core/crypto/rng_fortuna.c +6ee664faf892cf6eb54780694431dbc599714a4c - optee/optee_os/core/crypto/aes-gcm-sw.c +5e7555e339aca88d6573eef4844fe96171e073ef - optee/optee_os/core/crypto/sm4.c +e73ae6d522f149d7ffc117d3f026bd44fcd262c0 - optee/optee_os/core/crypto/aes-cts.c +057545a9e027cdd9daa7be1500acbb767b134a5a - optee/optee_os/core/crypto/rng_hw.c +d5a046c4f72b832688b7ba9a347dc8aaa9da47cf - optee/optee_os/core/crypto/sm3.c +8136a818dce4a27b5d4375a2ed743707222337cd - optee/optee_os/core/crypto/crypto.c +135fa97faba70e8a9e76d02ac418349f734e5971 - optee/optee_os/core/crypto/sm3-hmac.c +5e36787d311129f8c3649eed00a7bc54de3dc471 - optee/optee_os/core/crypto/sm4-xts.c +7b6658854eec61d103f730922493a99440ca594d - optee/optee_os/core/crypto/sm4-cbc.c +be1aa6aee3798fdc77ebc0a6b37bf5a80fc3baee - optee/optee_os/core/crypto/sm4-ctr.c +e68ca1aeee7c839ed6427892eba453b827fe73a5 - optee/optee_os/core/crypto/sm4-ecb.c +ed4f8a199dfc091202a84e729efc08be8166e573 - optee/optee_os/core/crypto/sm3.h +a730ddd73aac7bf7e2f4530cb84b4139920cc30e - optee/optee_os/core/crypto/sm4_accel.c +8f248f23b28edaaa10678438d9965c0cb94c6a48 - optee/optee_os/core/crypto/aes-gcm-ghash-tbl.c +35204fa717049aa26af2abef06d5466dd22b09a0 - optee/optee_os/core/crypto/sm3-hash.c +7c5fada22f5c639a3b8aef284822d484e1a0c7ae - optee/optee_os/core/crypto/cbc-mac.c +82c796645d5446d81b6013ad6338920da67f8ee6 - optee/optee_os/core/crypto/sm4.h +8616cfea725a82c1c4544264382e782985f9d153 - optee/optee_os/core/crypto/aes-gcm.c +3c8f23a338eea10aca5682c64d8a12902fc433f5 - optee/optee_os/core/crypto/sm2-kdf.c +4a9aec205bda6db9f341b00e62940610c4e3e728 - optee/optee_os/core/crypto/signed_hdr.c +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 +048e947aac490abffbce35e24ad1bfc69bc5ac83 - optee/optee_os/ta/pkcs11/include/pkcs11_ta.h +9f912a950243969c9bd8bcd1a3f8a7672a7c8ef4 - optee/optee_os/ta/pkcs11/src/pkcs11_token.h +9bf2174cd5400ba8a556261a46c0aea1a5f0504e - optee/optee_os/ta/pkcs11/src/processing.h +8a63bd474856b01d14303d306048e3981ddf19c4 - optee/optee_os/ta/pkcs11/src/entry.c +0f72c03b0ed1543181e76fad7ef7b4fc1b5c5219 - optee/optee_os/ta/pkcs11/src/object.c +f6be4d7e2f874ba52219afaf071f4367deb9836e - optee/optee_os/ta/pkcs11/src/processing_ec.c +5d4af2af14cf8c06a09e6cd0d5d40a28c60b9fa7 - optee/optee_os/ta/pkcs11/src/processing_symm.c +aee16d7bf1c5d2a0c39c6a5112cec71f528421b3 - optee/optee_os/ta/pkcs11/src/user_ta_header_defines.h +ae9d768bd9244e2db1ccbd555c05eb4b9e3eac14 - optee/optee_os/ta/pkcs11/src/processing.c +0e3dca0597af48781c952400ea4ecad857110eef - optee/optee_os/ta/pkcs11/src/serializer.h +e1a1a97f5050d21eae952c8db75322333235309a - optee/optee_os/ta/pkcs11/src/sanitize_object.c +aaff008a064e973b8f57ec40853d5935a7fd36cd - optee/optee_os/ta/pkcs11/src/pkcs11_helpers.h +9d7de06484bf080c9fb9d2922ea6a4d808edce81 - optee/optee_os/ta/pkcs11/src/sanitize_object.h +03548923ad53ebeb43856bb7cee45d24b899dbce - optee/optee_os/ta/pkcs11/src/pkcs11_attributes.c +114f7df1ed43dd70f8b8de1604d73c0be609664c - optee/optee_os/ta/pkcs11/src/processing_asymm.c +84f772fd6ba20b3e261cde79ea54a10da7f542dc - optee/optee_os/ta/pkcs11/src/pkcs11_token.c +894d688c805cbbca2bde46ae5dfcf38092d7e8dd - optee/optee_os/ta/pkcs11/src/attributes.h +ed1904bbe93d945ae27a1c8a5fceb6eeeb5e9135 - optee/optee_os/ta/pkcs11/src/token_capabilities.c +26dc92427964930f69b616be7c77b90da4bcb8df - optee/optee_os/ta/pkcs11/src/object.h +2cdc8362b15bac1a4efd183cdb7f8eb495875a65 - optee/optee_os/ta/pkcs11/src/pkcs11_helpers.c +dd669facb02254f0bc7ea46368aa8a0b4a91b373 - optee/optee_os/ta/pkcs11/src/handle.c +8c9b1335779fc8cc85d4a9057276dc5b237c3c41 - optee/optee_os/ta/pkcs11/src/attributes.c +5f8de729864d1ad926d2f9ec4ef37e8ff38ceb70 - optee/optee_os/ta/pkcs11/src/serializer.c +4b7dbda490ed1c5ac55d3357b440a8f012c647d5 - optee/optee_os/ta/pkcs11/src/persistent_token.c +a199684d2e257ba2568ad8c8d6788b9e4e8abcab - optee/optee_os/ta/pkcs11/src/token_capabilities.h +9740a8f2cd4228a931861239615d6f0565541730 - optee/optee_os/ta/pkcs11/src/handle.h +9e799d40bc5157fad91180105d091bf81c2695ab - optee/optee_os/ta/pkcs11/src/processing_digest.c +8b6c55e93d111035599141cb97c51bd50631817c - optee/optee_os/ta/pkcs11/src/processing_aes.c +1db1e2fc44c7afd4cfa93f2b32750e814aeff77b - optee/optee_os/ta/pkcs11/src/pkcs11_attributes.h +0aa2868227123053da7d9368bc3640a839d4e682 - optee/optee_os/ta/pkcs11/src/processing_rsa.c +6ce862868db1d139be88ffc2fa433b9f85a089dd - optee/optee_os/ta/remoteproc/Makefile +e9c8b0e7823787c4fa84725f41a45595f8ad8309 - optee/optee_os/ta/remoteproc/include/ta_remoteproc.h +c6760c67a37a18f9055ec466b20753434d64e9f0 - optee/optee_os/ta/remoteproc/src/remoteproc_core.c +c1f49c2292f12b9f1ec2111a6cdae3e2e1834afd - optee/optee_os/ta/remoteproc/src/elf_parser.h +e9b100254cc04ff146b7b63d2b5481f702007507 - optee/optee_os/ta/remoteproc/src/elf_parser.c +e492697cf2d2e97abde9c2175b8d72f598868312 - optee/optee_os/ta/remoteproc/src/user_ta_header_defines.h +cc0a07d6f59b29a9ec0e01f5ca6a378b3d445248 - optee/optee_os/ta/avb/Makefile +db8e85c91fed835a1d918c50afc26d97eccc131e - optee/optee_os/ta/avb/entry.c +78100b9031d82bc62fe38e0650f780d2c18f2f5b - optee/optee_os/ta/avb/user_ta_header_defines.h +04d61d12d0b618ec98f1f36f7aac7e7f6a0bada7 - optee/optee_os/ta/avb/include/ta_avb.h +f4be3da6e57a11e1c68fa2328f442963bf259f0c - optee/optee_os/ta/arch/riscv/ta.ld.S +47eac8b54f94d5d5a52a43ad5554f4e4c3f7ae62 - optee/optee_os/ta/arch/arm/ta.ld.S +44f007aca97998b425d27b7af67779c039d4d8d7 - optee/optee_os/ta/arch/arm/ta_entry_a32.S +50fac4ba9aede25524155ad8cd8cdd905f195a87 - optee/optee_os/ta/trusted_keys/entry.c +b28af208dabadef396024e4007f36154699e975b - optee/optee_os/ta/trusted_keys/user_ta_header_defines.h +8ff25744520aea7259967d34911798667d2cf6fd - optee/optee_os/ta/trusted_keys/include/trusted_keys.h +857d0e9eef00f7eecbb7f9eecedfae0ab2cd3366 - optee/optee_os/prebuilt/t234/libcommon_crypto.a +1764bfc2b32f604e3b3b7d735ce13aebfbd84d74 - optee/optee_test/Makefile +30a64b524a40d63d6e6f97698875a98100706c59 - optee/optee_test/LICENSE.md +1677c508f843daf45fcf3a1e8c23dacf24f2f222 - optee/optee_test/README.md +9f9d1e370fe395412ffa6a5bc7d21a13586d1551 - optee/optee_test/typedefs.checkpatch +72d26f74f4c2afb8675278b599c37c055eeeee59 - optee/optee_test/scripts/file_to_c.py +d178f675a81f53b7e725d270b25fadc6b064d6f8 - optee/optee_test/scripts/checkpatch.sh +3bef832a16e054c84c76c9efc89b3948ce5b0589 - optee/optee_test/scripts/rsp_to_gcm_test.py +0545607f4b3fd8f7d31fa40ceddfabc907bfb06b - optee/optee_test/scripts/aes_gcm_test.py +c6f2d858387614cd7e1ba883db5977638bbcfd55 - optee/optee_test/host/supp_plugin/Makefile +c035f30f1e5286ab496634f87b76fca573244cec - optee/optee_test/host/supp_plugin/test_supp_plugin.c +fa35e416cf42119ff66e1a064a4d5db8c785118e - optee/optee_test/host/supp_plugin/include/test_supp_plugin.h +1c0d518167dbd004a55feb971308505c53869a40 - optee/optee_test/host/xtest/sock_server.h +9af5cc1bb69f89b1501ceba2daea681936af8889 - optee/optee_test/host/xtest/ffa_spmc_1000.c +99e8b9a2f56ea25f5ff71ba126a28d51208cb2f6 - optee/optee_test/host/xtest/clear_storage.c +0e4e675b01c2f3a1bf1ed7ff6630b17fd4f0861b - optee/optee_test/host/xtest/Makefile +c546d1c8398ea1f2a5718cc966c2abeca418dad3 - optee/optee_test/host/xtest/xtest_main.c +24ba696e706583a4a4a94d7c43e8c31d986c47d0 - optee/optee_test/host/xtest/symm_cipher_perf.c +97f93f7703f25e42f830363a054f94fa70106e3f - optee/optee_test/host/xtest/xtest_test.h +3203c2511c56b80cf0757ce40aff2627e1589f54 - optee/optee_test/host/xtest/regression_5000.c +b8ec54c51ef808cf8e681d82cc13d6c180380a2c - optee/optee_test/host/xtest/xtest_uuid_helpers.c +d9f2461c2a9d755472e666b2c5b60fe21ae7f431 - optee/optee_test/host/xtest/regression_8100.c +27d3681d1dde596e9363305f28906b4b8e53e1f3 - optee/optee_test/host/xtest/crypto_common.h +d4e67633393e1eafbf02639e218f430a71cb978d - optee/optee_test/host/xtest/xtest_helpers.c +12ca0aa8361d1e3bdbf54e11e288ca087745ce14 - optee/optee_test/host/xtest/benchmark_1000.c +1049f2d88d1a17c10c65e55629e4d86b0f182367 - optee/optee_test/host/xtest/regression_1000.c +66930a95666bc4c78d83c2cb4c087aa37a4d42b0 - optee/optee_test/host/xtest/regression_4000_data.h +aeb9e6f5f8382411a15b0321473fd05148890a09 - optee/optee_test/host/xtest/pkcs11_1000.h +a611cff7cdaf3b04d87eef15c299048990ec3ea1 - optee/optee_test/host/xtest/xtest_helpers.h +9e020836d511e6e309f374901ad228d82443e779 - optee/optee_test/host/xtest/hash_perf.c +4e533d0531c352071ee236302dab1c2fed2068d6 - optee/optee_test/host/xtest/install_ta.h +6074430df45012584a40484c4ed72373bcbbe599 - optee/optee_test/host/xtest/benchmark_2000.c +52b11c0af213c40771048607e3da5eb5943e0d98 - optee/optee_test/host/xtest/regression_2000.c +f3517bebcb21463533c4004d029833eaf5cde12f - optee/optee_test/host/xtest/xtest_uuid_helpers.h +e1fb4f35907beabaf3b0dbe646b45d64d4aa5d03 - optee/optee_test/host/xtest/stats.h +01ce700dbb77213e51c372e4e6dc61082d7da4fe - optee/optee_test/host/xtest/regression_8000.c +79632869b30c8dc171f607ff89baa306b89fdc11 - optee/optee_test/host/xtest/aes_gcm_counter_overflow_test_decrypt.h +0edc9005d19339ab2a94dd1fa3749336bfe9b774 - optee/optee_test/host/xtest/asym_perf.c +bdea22513e96e2e87438e6fedf846a8fa6b3cf98 - optee/optee_test/host/xtest/clear_storage.h +16276b9d01ba73bf3bb21cb41ff264f3d0126d20 - optee/optee_test/host/xtest/sock_server.c +d5fc61a73a10975c5945aa67296797824b64b8b4 - optee/optee_test/host/xtest/rand_stream.c +4cc77b90af91e615a64ae04893fdffa7939db84c - optee/optee_test/host/xtest/LICENSE +4b76e6786bed1ae8da806d21ac567198a5bebdd8 - optee/optee_test/host/xtest/rand_stream.h +1f18023df5bcdb1bd566f84860dff7f4c5fa0bb1 - optee/optee_test/host/xtest/regression_6000.c +3b971536fd7cabeefba193938f8e1fd76ca56831 - optee/optee_test/host/xtest/pkcs11_1000.c +80a9b9f4795682feb072795a92f15c630eefa57d - optee/optee_test/host/xtest/sdp_basic.h +89d308baa51ac6c6fdc1128a98ebcaf98652b24f - optee/optee_test/host/xtest/sdp_basic.c +4ed1b27140db56a58e598a1d47e2eee729363f6c - optee/optee_test/host/xtest/xtest_test.c +55594d7bf611c68c77fc65b917fe860c4cc0654e - optee/optee_test/host/xtest/regression_4000.c +14686c51c1e1fc99b03e351c11aed2874aee799d - optee/optee_test/host/xtest/install_ta.c +da6d39a1f11c2a83cb0e37cccd9ef44979bd3d8c - optee/optee_test/host/xtest/stats.c +68d3a5e5deb31ba074b1848cf8e1ab7b3ee6606a - optee/optee_test/host/xtest/regression_4100.c +cf936c5da248d096b5c90cc9c6c3b4b278794e84 - optee/optee_test/host/xtest/aes_gcm_counter_overflow_test_encrypt.h +aa6291df45558c38403e3272c86920d0441aace1 - optee/optee_test/host/xtest/include/uapi/linux/arm_ffa_user.h +dd01f2d86e9e0e0a15aab712c3828f76e4c6e2fc - optee/optee_test/host/xtest/adbg/include/adbg.h +877fc553d7b1b08364cb1189bf4cdc3b6cf3c0e6 - optee/optee_test/host/xtest/adbg/src/security_utils_hex.c +e62cdf03f6bf82c09ca10f285a951c1018bbe70d - optee/optee_test/host/xtest/adbg/src/adbg_log.c +825ea0288d353fbf26dd5cb0e56be8db4e7bf245 - optee/optee_test/host/xtest/adbg/src/adbg_enum.c +bef73e2c136bf2a04bc8cf33b2052afac83535c1 - optee/optee_test/host/xtest/adbg/src/adbg_case.c +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 +4f57fda84526a6b64ecc3eccc008e18b97fc3523 - optee/optee_test/host/xtest/adbg/src/security_utils_hex.h +e6ac80b711f1a44d2eb77e1c618fe7f3270205be - optee/optee_test/host/xtest/nist/186-2ecdsatestvectors.h +99f104f79f66a659ea913d475077f7503b8a1c51 - optee/optee_test/host/xtest/nist/186-3dsatestvectors.h +a8012c439058a9ab645990d2efcd10447bc34324 - optee/optee_test/host/xtest/nist/ecccdhtestvectors.h +baf0c6e02b9300a37bd4409628cea730d71faa5f - optee/optee_test/host/xtest/gp/TEE_DataStorage_API.xsl +35ce411007e4e624913b8da87f51325be763d65d - optee/optee_test/host/xtest/gp/prepare_suite.sh +d00562756b00f6607632030c58bbd3576f7c13aa - optee/optee_test/host/xtest/gp/TEE_Internal_API.xsl +78e225e2b8581d7bd917bf1c007f4fee5b1d088b - optee/optee_test/host/xtest/gp/TEE_Crypto_API.xsl +488980fe7c4d8999c8466da403ef5b2811727e7d - optee/optee_test/host/xtest/gp/TEE_TimeArithm_API.xsl +39dbed853b87d4a916b95de14d5e23a8f434bfb2 - optee/optee_test/host/xtest/gp/TEE.xsl +be52e9104f2b38176beb182c8e36ecc119bb5eb1 - optee/optee_test/host/xtest/gp/include/xml_datastorage_api.h +53fb592b76fe82621b4c212f07b0555b4d40992a - optee/optee_test/host/xtest/gp/include/xml_internal_api.h +7b0cf45da16221e265fbd01221f541b851cb9e21 - optee/optee_test/host/xtest/gp/include/xml_client_api.h +45865ac02ab8782763d078613beaf33dce452445 - optee/optee_test/host/xtest/gp/include/xml_timearithm_api.h +392440db195c83fb488b7829e6ec09d994c95319 - optee/optee_test/host/xtest/gp/include/xml_crypto_api.h +01305480c8ecffffa5e19202e81c3611f714ff21 - optee/optee_test/host/xtest/gp/include/xml_common_api.h +705d65243c1e46af9f9642bb84f45b2daeff957f - optee/optee_test/host/xtest/gp/patches/0008-TEE.xml.patch +496f8635c2c0110849cb7e095423e036dae754ec - optee/optee_test/host/xtest/gp/patches/0014-Pass-upper-32-bits-of-TEE_PropSetHandle-in-value.b.patch +4f9aca322840391a171d320f3e9d5976b257fa41 - optee/optee_test/host/xtest/gp/patches/0006-TTA_TCF-fix-CmdTEEGetPropertyA-_withoutEnum.patch +cc1ccad0b05569188be42a4e6fad9069b9b44d05 - optee/optee_test/host/xtest/gp/patches/0011-TEE_Crypto_API.xml.patch +c85d2439e6af14cf1845341a721831d294e94e35 - optee/optee_test/host/xtest/gp/patches/0016-TEE_Crypto_API.xml.patch +34223b3e49b6b18b8bf88abf784fac10a0648a10 - optee/optee_test/host/xtest/gp/patches/0015-Enable-compatibility-with-TEE-Internal-Core-API-v1.1.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 +c834f47f97dd115566b874fa7e4a6d40d064d939 - optee/optee_test/host/xtest/gp/patches/0013-Disable-Invoke_GetTAPersistentTimeNotSet_and_SetTAPe.patch +4436ae2a8726be665c4adbc30899d7dbcf721afd - optee/optee_test/host/xtest/gp/patches/0002-TTAs-add-files-needed-to-compile.patch +0c86f63bc803a23617fb13ba1479108edaf5dac5 - optee/optee_test/host/xtest/gp/patches/0009-TEE_Internal_API.xml.patch +93fe519236e63a82aec4fa2e267aa9c10a9cf3e2 - optee/optee_test/host/xtest/gp/patches/0007-TTAs-revert-to-v1.1-types.patch +146a6228e298272ab7e73778962df356d9198311 - optee/optee_test/host/xtest/gp/patches/0010-TEE_DataStorage_API.xml.patch +cbc872e82c403faa84376db8efc78150338e2693 - optee/optee_test/host/xtest/gp/patches/0004-TTA_Arithmetical-patch.patch +5bdbfb7c09b73b8ee3f012bb4c05c5655a2e426c - optee/optee_test/host/xtest/gp/patches/0012-TTA_TCF-remove-TEE_MemMove-from-CmdTEEGetPropertyAsX.patch +89bb7582daae987e60e094aebfd5b2b073e9ac62 - optee/optee_test/cert/my.conf +1f75eacaea5baa5f8ecd35d3c8df7e746c3f73a9 - optee/optee_test/cert/mid.srl +6b932b1ab7b3565ddb4557b31b13ff823577f997 - optee/optee_test/cert/my.csr +6f108292e83a3a3555b56add6fba6bfc75bb1d03 - optee/optee_test/cert/my.key +ca513a618e76b7425f4f1350e90c7b74d4778eac - optee/optee_test/cert/my.crt +5870a0a431a6e7fd1fb251ada8f25d58c79a762a - optee/optee_test/cert/mid.csr +c858311b53e86391299c5bc0c30a39801b3893a3 - optee/optee_test/cert/mid.ext +4c8bd2753f58de91b618d71902216b93834e1b18 - optee/optee_test/cert/ca.key +c1c1370410a6251da1f2a65d4bb6799b6695ae46 - optee/optee_test/cert/mid.crt +f11ba7468488761597018fef555faaa8dcf0049f - optee/optee_test/cert/ca.crt +cf7626a2e6fdd3e5cd2455117e6ff59e38cc3a99 - optee/optee_test/cert/mid.key +93503a34df30013f6f47e50cde65662d3e5d3a8c - optee/optee_test/cert/mid.conf +9162a5682d5d26b3df6021cc646498709aadc3e9 - optee/optee_test/cert/ca.srl +eaa886f698fec46167f30ea7abbd0c72881e3e9c - optee/optee_test/ta/Makefile +494d296fe7e6b7bc0f500a343c6a33cf9f0b05a3 - optee/optee_test/ta/top_level_subkey.bin +525fc4d0105b2261ed118a2d96d2cbf71cba2432 - optee/optee_test/ta/top_level_subkey.pem +d9a4193c1df764fc72c7e49efeeb550f84c6dcb0 - optee/optee_test/ta/identity_subkey2.bin +2f0deec19c000366d2fd6d627f9b4363213eef7a - optee/optee_test/ta/mid_level_subkey.bin +8890459880f4ef0eb20f8a28b727540e789f07a3 - optee/optee_test/ta/identity_subkey2.pem +5d45a78f116ff6a6a5ce6227b1dd705d86a1a640 - optee/optee_test/ta/mid_level_subkey.pem +192ebe9f6d76a6b9d3938a69c72663ef7b627fff - optee/optee_test/ta/os_test_lib/Makefile +b0992bc9d242a926b54b8162b36f7f219c278624 - optee/optee_test/ta/os_test_lib/os_test_lib.c +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 +5558acac0905fc8f55ec7451c6cafff4654c532c - optee/optee_test/ta/large/Makefile +3231e66bc961e72de9759c2d801cf7e081611183 - optee/optee_test/ta/large/ta_entry.c +04b692b46b7c145c2fe975bb20250626d9e5680e - optee/optee_test/ta/large/include/user_ta_header_defines.h +78c0f90194587f8ec4696ed9937eab82bd2d6102 - optee/optee_test/ta/large/include/ta_large.h +6902d41cad5e1a7fdd792070ee6fe09543fd0a36 - optee/optee_test/ta/miss/Makefile +63727dbe77411a56de4384f2647ac604df1bb77e - optee/optee_test/ta/miss/ta_entry.c +17584ab846d09d2e11a0c62ee9c12f7eb00a89f2 - optee/optee_test/ta/miss/ta_miss.c +e8cc80687d4a1d454c124c0288798e280142a723 - optee/optee_test/ta/miss/include/ta_miss_test.h +7577f16d52d892d26d2aba97100c391696f1b4e0 - optee/optee_test/ta/miss/include/user_ta_header_defines.h +dfc1e1eb35732695271ed55f42d20a4f3d65dd85 - optee/optee_test/ta/socket/Makefile +e1b35b65fffd182965ab59d513da17f3bc2cb637 - optee/optee_test/ta/socket/ta_entry.c +7caf8e51e601aad92bfa2080fd1d462af34a690f - optee/optee_test/ta/socket/include/user_ta_header_defines.h +60c71c4fd9746b52eff3180768cadfb42246ad63 - optee/optee_test/ta/socket/include/ta_socket.h +159ab9161f614e0e78c7ed8ad589b1da7dc49313 - optee/optee_test/ta/tpm_log_test/Makefile +f041af378514b0adb83e13683c439bdfda633a38 - optee/optee_test/ta/tpm_log_test/ta_entry.c +071de3ab826aea3082b54036a436e42d20e5e829 - optee/optee_test/ta/tpm_log_test/include/ta_tpm_log_test.h +15979122b263375291e30ed248816c707e51aa9d - optee/optee_test/ta/tpm_log_test/include/user_ta_header_defines.h +05d9586c179dfa463023108f57186c397f67b168 - optee/optee_test/ta/tpm_log_test/include/ta_tpm_log.h +3762c8d8188b6fd5c0e0216aa0dfbc1a81c33bd4 - optee/optee_test/ta/sdp_basic/Makefile +3e89b728bfdb79e36b4831135f52d8907cc6b6ba - 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 +3e93b929b783566f5933da6daf3bf178b60f0ac9 - optee/optee_test/ta/sims_keepalive/Makefile +63727dbe77411a56de4384f2647ac604df1bb77e - optee/optee_test/ta/sims_keepalive/ta_entry.c +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 +e3deb7bd3c13099679c0218b2daabc17547fb2aa - optee/optee_test/ta/supp_plugin/Makefile +615513981a90fabad2bd36d67b4ece7b3e63bfe6 - optee/optee_test/ta/supp_plugin/ta_entry.c +a6d7b87593d95249d1adf41e1ed2855be8557092 - optee/optee_test/ta/supp_plugin/include/ta_supp_plugin.h +97d8481ac3b8dd32d148d69acc3da07308fb759a - optee/optee_test/ta/supp_plugin/include/user_ta_header_defines.h +62093428f73279ad6337e6b83de79cdc9638aa07 - optee/optee_test/ta/sims/Makefile +a2d1207a964e7c839176e0c9beb333de1aa5114d - optee/optee_test/ta/sims/ta_entry.c +b27b844ff53c4ce9ea4b37becfc73759661121c9 - optee/optee_test/ta/sims/ta_sims.c +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 +56e682b335cbdbb4b053f31838a28d596ea0dbf5 - optee/optee_test/ta/subkey2/Makefile +3484bf8a9bd48d0fd2c66b682574dcbd80ae59e7 - optee/optee_test/ta/subkey2/ta_entry.c +d1217850bdabdc5c5f402556a4dd76a32af19d03 - optee/optee_test/ta/subkey2/include/user_ta_header_defines.h +786d2761de772f9af4885b058126e8596a16e194 - optee/optee_test/ta/subkey2/include/ta_subkey2.h +f22bc5e3e7d42fae8b515ed89e6d52e14853097d - optee/optee_test/ta/crypt/arith_taf.c +707f95e800674bd769a22f4b05b0f86bde9bdda0 - optee/optee_test/ta/crypt/Makefile +0205269ec12a07945fa15e1f01beacd396129c02 - optee/optee_test/ta/crypt/ta_entry.c +89299c5c290be38d0509309892bd9bf67946a552 - optee/optee_test/ta/crypt/sha2_impl.c +0f5728bb87da64faea76a4d60859ffc6ee7cfb0e - optee/optee_test/ta/crypt/seed_rng_taf.c +6d536756fbdc5623379b5c8c68b3383c6c3c7535 - optee/optee_test/ta/crypt/aes_impl.c +2f8d16642c23418d96eae0799cdbb319adae9bd2 - optee/optee_test/ta/crypt/aes_taf.c +cda695cd368148125b67d4b5049b4b5e44f19d4d - optee/optee_test/ta/crypt/sha2_taf.c +71541fecba370d8d5d888ff889cc55a649e0f6e3 - optee/optee_test/ta/crypt/handle.c +59232c5714af3b17dab86effad8c4adcdc6193ec - optee/optee_test/ta/crypt/mbedtls_taf.c +62f575dd691dc4df07cd85b6aaf381bb1fa129df - optee/optee_test/ta/crypt/handle.h +ae237aa24606ab8442252be914264ebc32acb3f1 - optee/optee_test/ta/crypt/derive_key_taf.c +08792d69cd8404668362c47a42015e3ed15a03e2 - optee/optee_test/ta/crypt/cryp_taf.c +bece95c11da1deff583de5cccb73aeb047b13bb3 - optee/optee_test/ta/crypt/include/seed_rng_taf.h +65726ede28ff3980980f0786f73da00bf00f7adf - optee/optee_test/ta/crypt/include/aes_impl.h +f922975017d8e69cf55d924ad3475f48207c778c - optee/optee_test/ta/crypt/include/sha2_taf.h +e39b6697e3f099db9e9210630f403279d821b01d - optee/optee_test/ta/crypt/include/user_ta_header_defines.h +751a9eda488bdee96dd4666819f86792eb94e63c - optee/optee_test/ta/crypt/include/mbedtls_taf.h +d6094f43aff3a5e99b1b4916e6f0616f4b506c4e - optee/optee_test/ta/crypt/include/ta_crypt.h +dedb18c14d2c13ecb2666beff2d43a1c6f2b1f4c - optee/optee_test/ta/crypt/include/derive_key_taf.h +971b7e4384dfd449056d2d98600938baaa13b45c - optee/optee_test/ta/crypt/include/arith_taf.h +81c28b5d39b57c60583003aa3b19d4e9355be3e8 - optee/optee_test/ta/crypt/include/aes_taf.h +59bb92661052957ededa8bf444418db0f792e5df - optee/optee_test/ta/crypt/include/sha2_impl.h +98b131e0650e8848c202b367de6afd9713234b23 - optee/optee_test/ta/crypt/include/cryp_taf.h +0b8f95e1cc815a73f1913f8b1cd1199b86afd777 - optee/optee_test/ta/os_test_lib_dl/Makefile +34655a75cdbf9b1cf1a0f475a835630aa77d76ad - optee/optee_test/ta/os_test_lib_dl/os_test_lib_dl.c +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 +403faf3efbd2a187981acd30a58067dcb43d4d2f - optee/optee_test/ta/concurrent/Makefile +b33588442f2691e00ae34677fee3503279ec4251 - optee/optee_test/ta/concurrent/ta_entry.c +81d9fc2603da64f6aca629d4c1f6152ce40f4299 - optee/optee_test/ta/concurrent/include/ta_concurrent.h +b203b24b6fb092d32555949aece3d104a945d314 - optee/optee_test/ta/concurrent/include/user_ta_header_defines.h +545a9527a5a59df10e9fc50f958bf567149bb8b6 - optee/optee_test/ta/include/ta_storage.h +3777dde2c0aee5f993ddf5f6e2899d578554736d - optee/optee_test/ta/storage2/Makefile +fd20f8c7b48682f3cb154209d193c38ef5fa8afa - optee/optee_test/ta/storage2/ta_entry.c +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 +969daad84d451c2beaaeb0205d361045b135c899 - optee/optee_test/ta/create_fail_test/Makefile +327bcd861d17179ed6eec837ae40d93f6d4d5171 - optee/optee_test/ta/create_fail_test/ta_entry.c +f8ff5608bd441c5bb14ba4e0d1ac825036c0be26 - optee/optee_test/ta/create_fail_test/include/ta_create_fail_test.h +28f22d74fc72b507d9530a7788812714f4ccd2be - optee/optee_test/ta/create_fail_test/include/user_ta_header_defines.h +a7891e77ba72a13303bee70e3469d5b66c4dd0ff - optee/optee_test/ta/storage_benchmark/Makefile +126f0a0f43f2045ed64ac151420ff2750039cae6 - optee/optee_test/ta/storage_benchmark/ta_entry.c +1c896a32ab658f67fe2c2469efab67c781d40d17 - optee/optee_test/ta/storage_benchmark/benchmark.c +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 +350b57d8d13e85db59890347995fb8b25902941d - optee/optee_test/ta/storage_benchmark/include/storage_benchmark.h +49c2d5872d9a41ded424776ddde01ab79ca78988 - optee/optee_test/ta/crypto_perf/Makefile +12f72f4f686c7e5c42580ed7eae7c3687d07bfa6 - optee/optee_test/ta/crypto_perf/ta_entry.c +76173f317d8ec7c0d93c8e416222325635b95a68 - optee/optee_test/ta/crypto_perf/ta_crypto_perf.c +cbdc030bb470e5a4955e3e9156033676053db836 - optee/optee_test/ta/crypto_perf/include/user_ta_header_defines.h +080c319338a6832c33fc4980075e44db13d22020 - optee/optee_test/ta/crypto_perf/include/ta_crypto_perf.h +bef96027f5481438c3532aa395fb391799d91bfb - optee/optee_test/ta/crypto_perf/include/ta_crypto_perf_priv.h +305e7a10ae0489f83dfe773f06b47ad314bb9771 - optee/optee_test/ta/concurrent_large/Makefile +c5741796e6b99090e6fd99dc03a6bbcfe6871028 - optee/optee_test/ta/concurrent_large/ta_entry.c +6fc98a616100591a9ba17fe01d8cd7f30c449420 - optee/optee_test/ta/concurrent_large/include/user_ta_header_defines.h +51f374f9df753de95e0ee8a082c29395bed8625a - optee/optee_test/ta/concurrent_large/include/ta_concurrent_large.h +19e490a77411c75a67b54eb0684edc9dc35f7192 - optee/optee_test/ta/bti_test/Makefile +9752d870fbaca8ae7c1554096be6f228b5a0efaf - optee/optee_test/ta/bti_test/ta_entry.c +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 +e00637d3dc4e177f4693a591711c655a84f82c6e - optee/optee_test/ta/os_test/Makefile +f99e6541faaf5c1e883528d5a9a247c9a404ad5b - optee/optee_test/ta/os_test/ta_entry.c +c845f1bef062d33dd7e59d0647155b05ef5ed6ac - optee/optee_test/ta/os_test/attestation.c +f99ecd7a7d1466b6ae095553f19b144a3b5e05a6 - optee/optee_test/ta/os_test/cxx_tests_c.c +a4ae385c460bad98c3f1bb74e4cd6d78a3d1c569 - optee/optee_test/ta/os_test/cxx_tests.cpp +0821f97bb6d0e672f229f163d91a44db3b3cfc21 - optee/optee_test/ta/os_test/pauth_a64.S +30c95077d893a72f6dd6f25698b9e3c4c90c7173 - optee/optee_test/ta/os_test/ta_arm_pauth.c +7c34f62620b2c3cf1e435dc2f06b5bc695a0ffca - optee/optee_test/ta/os_test/init.c +81b48e32f421e3809c799370e7d5a84be82e4007 - optee/optee_test/ta/os_test/test_float_subj.c +4b24fec7bb0779f54df830b2accd4589c58ee714 - optee/optee_test/ta/os_test/test_float_subj.h +9474cf4fc4a3b252db66bceae94a0d1af55032a0 - optee/optee_test/ta/os_test/os_test.c +0455da7d426f2d9c91e8d1f0ceedcbcdc25b7e63 - optee/optee_test/ta/os_test/cxx_tests.h +8e61b08c2d218f799c0ceb8531677adaf702b81c - optee/optee_test/ta/os_test/include/os_test.h +c250edae8e50b81ddc7f2d82b74533be8ce36484 - optee/optee_test/ta/os_test/include/user_ta_header_defines.h +5925bcc4d74e66a2c9ac214c3afb53d3a2c40385 - optee/optee_test/ta/os_test/include/tb_asserts.h +f61b829b0f8774e078f535f9dcb469a402aab63f - optee/optee_test/ta/os_test/include/ta_os_test.h +ef669e3a5af86a9d7433680efe47e7475ebae840 - optee/optee_test/ta/os_test/include/testframework.h +0fc4efc474f17406466b3a01708a70604c4bf90a - optee/optee_test/ta/os_test/include/tb_macros.h +c0f2b4917d2e7e2c64767ce20c51277d030da95e - optee/optee_test/ta/os_test/include/init.h +ab190ed1cbd92987955bd1b18cf1125760e00235 - optee/optee_test/ta/subkey1/Makefile +e98d28dd7d955c5f1430b86d1f9fa9a293f2c6a5 - optee/optee_test/ta/subkey1/ta_entry.c +3ef18fee5ed3f12595bcae5cd670e9b614bddccb - optee/optee_test/ta/subkey1/include/user_ta_header_defines.h +fccce5046748bb0a2c4bf866d2ee4099789327e9 - optee/optee_test/ta/subkey1/include/ta_subkey1.h +a29dec4b78281324f1e479a7648b636feef1d163 - optee/optee_test/ta/storage/Makefile +7e3e9ed670136ea79aa56b6e986e2b795074cc8f - optee/optee_test/ta/storage/ta_entry.c +a2575f658d20bade8d2751a438a3881dec9506ba - optee/optee_test/ta/storage/storage.c +cbcf995c4fce7f48869248f9f3bf912195d4873e - optee/optee_test/ta/storage/include/user_ta_header_defines.h +470456cae0c3f509a24f5ec3678881a672b863c7 - optee/optee_test/ta/storage/include/storage.h +96b12ede29af7df11c0b54a3d3924599f9ad0de4 - optee/optee_test/ta/enc_fs/include/enc_fs_key_manager_test.h +db39d7c16208c8b18547c18b524c4d4d8d8533a6 - optee/optee_test/ta/rpc_test/Makefile +28e50e4d884a51351b0454dcf8971ea8619becb2 - optee/optee_test/ta/rpc_test/ta_entry.c +100bd8db89d7d506ba95afa1adf59c093bee623b - optee/optee_test/ta/rpc_test/ta_rpc.c +daf6f0380173f9c72cb5ab411c7e145635102403 - optee/optee_test/ta/rpc_test/include/ta_rpc.h +bb5b31def49e12cb5ca13946631064fdab7f3ce1 - optee/optee_test/ta/rpc_test/include/user_ta_header_defines.h +5a06508a48d77c9bc4d4483f2c1064bc11547f17 - optee/optee_test/ta/rpc_test/include/ta_rpc_test.h +6c873429bc677416677c5807645bf161215865df - optee/optee_client/Makefile +1d22df2514ce91279fc9fd16270cf6b0ced2e65a - optee/optee_client/Android.bp +1be3a93bb56c46ee4d4693b47ddd7c4c5487ffd3 - optee/optee_client/README.md +a7d910ff308216f427e9a4776d72cfe84e2915ad - optee/optee_client/LICENSE +c9b3bb5ab0a3d0252ed93cfc3578e3991ee2b994 - optee/optee_client/typedefs.checkpatch +d064a25e20d345a05792931a265ee41e75706c88 - optee/optee_client/tee-supplicant/Makefile +f24b5d7b4681f11f33d735e96c6193f040d61420 - optee/optee_client/tee-supplicant/src/rpmb.c +eb428488f05ca6049614557e2a89abbe531b1e24 - optee/optee_client/tee-supplicant/src/sha2.c +ea069507eb088c8be58fd316e1182d94fdcfffb6 - optee/optee_client/tee-supplicant/src/optee_msg_supplicant.h +5387e1fcf4e95d497b72ee814d729c4c90adb740 - optee/optee_client/tee-supplicant/src/plugin.h +435831cff86e23874de21d77aa2acd2e2847e629 - optee/optee_client/tee-supplicant/src/tee_supplicant.h +2eeff0bb8ad1aaf5594e87a9faa9b9bffa63ee8f - optee/optee_client/tee-supplicant/src/plugin.c +b738d8b04995c56175826db5cbaca1ed21e079ad - optee/optee_client/tee-supplicant/src/teec_ta_load.c +f5b0fdcf3343c38ff2495f438044546952d538e2 - optee/optee_client/tee-supplicant/src/tee_supp_fs.c +a5f3a0cb9e4309400c0c22dc574de3c8eef67a65 - optee/optee_client/tee-supplicant/src/nvme_rpmb.h +945a945fa92b85f4b7003123e4ef27a588bdc2bd - optee/optee_client/tee-supplicant/src/hmac_sha2.c +bed7d31fece3711cc20a9418d51d24ef7fe3391b - optee/optee_client/tee-supplicant/src/prof.c +8fbfe192d68bdb1e126598cb730e7c11f511960d - optee/optee_client/tee-supplicant/src/hmac_sha2.h +946a1750a3bd2cb7ee8a0934d7df7849d1649aee - optee/optee_client/tee-supplicant/src/__tee_ipsocket.h +721aca20ceeacd1648d0f7204c85f69b282fe101 - optee/optee_client/tee-supplicant/src/__tee_tcpsocket_defines.h +593518d07f2abcdc15942f188796aaa0bb12d4c6 - optee/optee_client/tee-supplicant/src/__tee_tcpsocket_defines_extensions.h +a80eb6caf9c8732d74f0fc4c329a4222995ec6c8 - optee/optee_client/tee-supplicant/src/__tee_isocket_defines.h +a16a80d873293f74d73baf53721eb5019ded25cf - optee/optee_client/tee-supplicant/src/tee_socket.c +d6dd587b4421a742de3144b103342789681958a4 - optee/optee_client/tee-supplicant/src/teec_ta_load.h +2b4e00ad1b9e0f3a5e7c2efbef6591de41a0e409 - optee/optee_client/tee-supplicant/src/sha2.h +df8821ae52abffd9ffd2d962078fd715185513d4 - optee/optee_client/tee-supplicant/src/tee_supplicant.c +b81a505561be6982f3eea681e266827c8236583c - optee/optee_client/tee-supplicant/src/__tee_udpsocket_defines.h +f17cf7d08bb300eb71cf0b2ca503f505c269e761 - optee/optee_client/tee-supplicant/src/tee_socket.h +f1107acfa97784e2a91a1a393dd6198fc4a4a222 - optee/optee_client/tee-supplicant/src/prof.h +1f145b8b2fe3882017290f627f46dfc328a7c144 - optee/optee_client/tee-supplicant/src/handle.c +4a38f4ea1eea116c78d27b03a2cbfb92f8ea3a97 - optee/optee_client/tee-supplicant/src/tee_supp_fs.h +9763ee4354d75e34559e80fe8dda7bb158c4c5d0 - optee/optee_client/tee-supplicant/src/handle.h +07af4053379b51e5d33dda8ac2eda2181ae23a02 - optee/optee_client/tee-supplicant/src/nvme_rpmb.c +f04b1790f669de1573516dc81fe3f4eefcb59c1f - optee/optee_client/tee-supplicant/src/rpmb.h +d6e6c51b13d0f6f61ae51ff3da8b8f51b3ac433e - optee/optee_client/scripts/checkpatch_inc.sh +5f5e044fbbcd7b4262c4d4405cac9dc8115b9bd6 - optee/optee_client/libteec/Makefile +a5fbbcfc0214db8015e94fc05998f548c339e1ab - optee/optee_client/libteec/teec.pc.in +c6e011ef6751f07449bffe9fd19006a15b8624b5 - optee/optee_client/libteec/include/tee_client_api_extensions.h +43da45835976c93e70ec5ad1ed02b891a0dbe000 - optee/optee_client/libteec/include/tee_plugin_method.h +668dfffd684890e7dd9bedbfd635db0df9af35d8 - optee/optee_client/libteec/include/teec_trace.h +a3e6eec2b0c6f60ab6995f2b082b866bda6a808c - optee/optee_client/libteec/include/tee_client_api.h +16cd3b045e35ef0e65b2c33238b2b59f62255883 - optee/optee_client/libteec/src/tee_client_api.c +d842563e16728b8e4b8e70f1fd7522598235d843 - optee/optee_client/libteec/src/teec_trace.c +15278a332dd772f0c91e486e562d10ba1b9cb6df - optee/optee_client/libteec/src/linux/tee.h +c2eeeb99eea300a1748db00f9803a548f2282c49 - optee/optee_client/libteeacl/Makefile +1cf357b019b2533237bef65ce240ef9e7d0d77b2 - optee/optee_client/libteeacl/teeacl.pc.in +ee867d9d7bddd079e18e86b614ddb0951d3a79ce - optee/optee_client/libteeacl/include/teeacl.h +3842833a20a863d971c8d33f5e101ccc77e88c62 - optee/optee_client/libteeacl/src/group.c +d44856b3c2e641d34dc08c44aa14df8111f0f2a0 - optee/optee_client/libteeacl/src/tee_uuid.c +94dc6f25362ba38974deb9290b3ea1460569ff71 - optee/optee_client/libckteec/Makefile +f25fe667d7155f39694414e63dac8d54adb5e264 - optee/optee_client/libckteec/include/pkcs11_ta.h +cbd1cf1d939303ee17050057c176ddb7498b1598 - optee/optee_client/libckteec/include/pkcs11.h +7d66a5a9955374f577b36eda3684c254841edbda - optee/optee_client/libckteec/include/ck_debug.h +e640a280681f076f112beee518ea1adff965c818 - optee/optee_client/libckteec/src/local_utils.h +3d1d16bc8a998c7382d0e5deb177e421613cbdb9 - optee/optee_client/libckteec/src/pkcs11_token.h +28f837a80c95ceb3f72437386993f46469f861e9 - optee/optee_client/libckteec/src/serialize_ck.h +48b8562a4200b00fe6382797789d8e694186c620 - optee/optee_client/libckteec/src/invoke_ta.h +a36127385f3d497598291e167cfc4147e48861ed - optee/optee_client/libckteec/src/pkcs11_processing.h +4a7c34adbc6006ef9230bb1919ca520891b9823a - optee/optee_client/libckteec/src/invoke_ta.c +04e59fc9b03985ed9c71fb751bcf60dc050aa517 - optee/optee_client/libckteec/src/ck_helpers.c +0db1379449cb2cdae53a7b480a402e8c43457431 - optee/optee_client/libckteec/src/serializer.h +53de33af06e51fb21fe2f24c2c0665a45baeb3b8 - optee/optee_client/libckteec/src/ck_helpers.h +66ad3fbe5639477f5ef0f50c0a87bb825db643aa - optee/optee_client/libckteec/src/pkcs11_token.c +27cd49c5be59123275b6d2d23f61956cd86846c0 - optee/optee_client/libckteec/src/pkcs11_processing.c +a4b2b6fc00af2b337386db3fc110f54709a248bb - optee/optee_client/libckteec/src/serializer.c +d38060ba408bececaceffc5392363c4255e064a3 - optee/optee_client/libckteec/src/serialize_ck.c +145e33a2859354e90473957df5bdd430b63f437c - optee/optee_client/libckteec/src/pkcs11_api.c +f88324eb36dec1f8579a56f5e446475ced59b52d - optee/optee_client/libckteec/src/ck_debug.c +2a0b9b82ad279a7127d4fb8fa2c4c4bb0bbfb62e - optee/optee_client/ci/Dockerfile.debian +874f552974cb3d5f17a63dd2ba50582a28e2d28e - optee/optee_client/ci/Dockerfile.ubuntu +acd8d0f397cd4e0ffdc9aed50f3f91fcf357822b - optee/optee_client/libseteec/Makefile +2219ff4dd85f1c6a0ee11024a1834c7d17124a79 - optee/optee_client/libseteec/include/se_tee.h +eb52a5aa690916e1cdb6e9d58fd746762ac03bbc - optee/optee_client/libseteec/src/se.c +f5d83909e5071e2affc98fc56ac4b941e00ef03a - optee/optee_client/libseteec/src/pta_apdu.h +dfe89d4404a213f5751887db149a30135cd07f9a - optee/optee_client/libseteec/src/pta_scp03.h +fbddcc56f1918f9c27f657f1e527b77f9a94382d - optee/optee_client/prebuilt/libuuid.a +3eb30c4c0069f3a45e46ea616d1bfaa9c81dcf95 - optee/optee_client/prebuilt/uuid.pc +f946a4e57b4901f5733debd6aec83a809534f9cd - optee/optee_client/prebuilt/include/uuid.h +bf52776d687b57bc5e886b2f4e7a0f7ece62b0b7 - optee/samples/Makefile +b2def2faca96323618fae5d302c50260bccb869e - optee/samples/LICENSE +2f700b45a00530a528bbd7086b22444f8a91ea96 - optee/samples/cpubl-payload-dec/Makefile +ea49cce3ddf319882d8e400806f6a761de306ce7 - optee/samples/cpubl-payload-dec/LICENSE +3945bd127a3cab935cd8b206bdc6bfbabd07e020 - optee/samples/cpubl-payload-dec/ta/Makefile +c37254b292d303cab4ab95c06ce5cbc3adc72b5a - optee/samples/cpubl-payload-dec/ta/entry.c +135be83f6d1ba5b8793d6127420fe3b879424531 - optee/samples/cpubl-payload-dec/ta/user_ta_header_defines.h +22e887e40458255171cfad715a9c477826fa3cfb - optee/samples/cpubl-payload-dec/ta/include/ta_cpubl_dec.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 +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 +6d3ac3cebb74c4f088accfac2d48654ea788769b - optee/samples/luks-srv/host/tool/gen_luks_passphrase/example.sh +fa3f0583c33f15560475d2899643217e9b8bdedd - optee/samples/luks-srv/ta/Makefile +9198ad9d0108d1f0c5411e43cfcdbbb011dc6ddd - optee/samples/luks-srv/ta/user_ta_header_defines.h +7dcf0c69657674d5c8d84f037993856ccdabf784 - optee/samples/luks-srv/ta/luks_srv_ta.c +80db8ae67e3a08227b8feeb7c71d80c97e620988 - optee/samples/luks-srv/ta/include/luks_srv_ta.h +b534b3c1b0a9fc7ea3c6a3ecc9d4a7182a66f022 - optee/samples/ms-tpm-20-ref/.clang-format +56cea4315ced27989bf4993b5ebb6f5123222c3b - optee/samples/ms-tpm-20-ref/SECURITY.md +9fcc9b4c93fd85452b4b1a3c89afe4d598d545df - optee/samples/ms-tpm-20-ref/README.md +e12c4ff9f6d12441b1b697d24c4b8b6923b2fb08 - optee/samples/ms-tpm-20-ref/.travis.yml +bbf046fa124b7c4632ae2631e9059507a72a3d2a - optee/samples/ms-tpm-20-ref/LICENSE +13c6e4813b3e9761d334db45a93cef59b96cde02 - optee/samples/ms-tpm-20-ref/CppProperties.json +10937e6af19c7747e93a8367c3ce6953f2c09b6e - optee/samples/ms-tpm-20-ref/CONTRIBUTING.md +7cd6e55737ca672c343962a688186bc665f41898 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/README.md +df67ed7bc549a84f8ff8a5de0d3d096a6e2bbd48 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/Makefile +6d3239af75e740ae509ca8b2e0d51b584f3465a5 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/Makefile +3f229d45d7d2ce7e5d7e46e12377af9165e6c361 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/user_ta_header_defines.h +1bce5759e31235d9c5bdba21dd91adaa428fc3f0 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/fTPM.c +8a3ff6f0fbf400d5960a0b9e29100a2f0c257cce - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/lib/mbedtls_ltc/user_custom.h +53e682c13d0856ad3840af92efef4f69ce2e1d61 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/fTPM.h +ea9d25b54a0bfb6a2f2919629390ac2f1a7cd709 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/fTPM_event_log_private.h +f0e69701b65f4b4bf75a97838a5784c8b96377eb - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/fTPM_event_log.h +eca8429d573b1efe6aabb85e729081ecd232cd9c - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/fTPM_helpers.h +d265a8bc723bc221914fe71eecf809497317402b - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/Wolf/TpmToWolfMath.h +1abdd3758b52641bc84ab63597b351aec39dd45b - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/Wolf/user_settings.h +369f00bc9361a2d2471b00bbf96c1ba518e645b3 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/Wolf/TpmToWolfSym.h +2a43b3beb22e372a4284450764b201c24f4e7f97 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/Wolf/TpmToWolfHash.h +376c946270a22a79f5ae90cbbd3efeb4b6a0b5f4 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/PlatformData.c +9c1182d6fbfc09acdb617e2c6e644e7bc7add570 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/Unique.c +87d59c28e82a41130b6d7f9a8a36c75e1b750a0c - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/NVMem.c +c9349c1d5329a5100adce5dcc24d234c9bdcaa61 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/fTPM_event_log.c +b59bde7a93e1cc1855b209291ae236fbffcdedbf - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/Cancel.c +d8d1e1184b822d904eceda19ad720da371cefc24 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/PowerPlat.c +79c38e67602cae65ee67146a13518eeed36f2bf8 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/EventLogPrint.c +7c5cb20afa4a0e569b22aec797fabdb2f30552bd - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/PPPlat.c +52663f93a5790e3ca64daed728e5491847136e5e - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/AdminPPI.c +13ac1a0dcd262678d94da7a3b86856a3a3851361 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/fTPM_helpers.c +283a4b88a1e84f5ef741d4f4d4fde82d9407ca55 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/Entropy.c +d5d1030b42d4d34b5b1384aa182b441c909f4df5 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/EPS.c +411c14cd40d0d71d28c13f52c3911e5a8c411b2e - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/Clock.c +61e1c6504462645f5064ea9dc434804a824a5075 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/RunCommand.c +d7201b197b3e91e981077abb03ae2827b42a9b63 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/LocalityPlat.c +46c4a6540314c172068f6dc8fffe1f467861b7d6 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/DebugHelpers.c +963be460c3847e12f66b652610ba0bc3281f4bf4 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/PlatformACT.c +d9b2bbfdaceb0f02c468ede7e0b05fe5a8aa50f4 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/NvAdmin.c +b493c94195fe836564fb88852ba0fea97814ca6c - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/include/Platform.h +b5b9fbb93586419230ff8d1ec018285878ad46c2 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/include/Admin.h +82113c01765d59f6759fd977d625e6444fd75572 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/include/PlatformData.h +f7c1239e5dea6bb93130c66ed56ce33485985ed3 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/include/Platform_fp.h +62105e5307c3636450c1864348a5d5d35b63660f - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/reference/RuntimeSupport.c +cd7e6c680ef80aab7901ba9978c4afd5a7e52a63 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/reference/include/bool.h +2706d6092917100fd8117a9d5c315e7862629748 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/reference/include/TpmProfile.h +5bc59f1069c9183079f5bfaa521e4398048fb2a4 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/reference/include/VendorString.h +e6eb4da02d48333abbca49a31090610423fa06d0 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/reference/include/TpmSal.h +468436d93e40d0fc852d4e86920fbc68718c929b - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/reference/include/RuntimeSupport.h +65607068ebad388e1a689ac6e701b0b45e02c5a3 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/ta_prod_signing_scripts/generate_digest.py +14fb1121df155d6da96d7a1d6351b9fcf47a0af5 - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/ta_prod_signing_scripts/README.md +e643f090d5cbaaa3dd73f87fd32aa7bb079e776e - optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/ta_prod_signing_scripts/stitch_ta.py +a7aeff0addca9724f945178d6857a4d5b254de77 - optee/samples/ms-tpm-20-ref/Samples/TPMCmd-DeviceID/build-tpmsimulator-deviceid +32b6f41f8cb17695fa4e40dcdb5a13bcefb7d93e - optee/samples/ms-tpm-20-ref/Samples/TPMCmd-DeviceID/Platform/src/EPS.c +e855760eaf75328c77fc714300151c27ce864ec3 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/USB_Hookup.jpg +10c3fd48393c33d4510c403bde7a91efbf05666c - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/microUSB_Hookup.jpg +3f8d0256d18033e053779e7864508daa371797a9 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/.mxproject +0206b31f994b247b4ef78e829cdc3fbfec23dd97 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/mx.scratch +8086602309481b27c6586f824f4783f514c027d0 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/.project +17bc2133944d7885da66070c51191d5c4c7a86ce - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Nucleo-L476RG.elf.launch +77f371cf9bdfbd2ee243ceb2d60dfc4f734095a6 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/STM32L476RG_FLASH.ld +e40037acef5ee9515273d568d4fa1f7d7c2dfb98 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Nucleo-L476RG.pdf +96cf2e3a3a7fe535463d74a9e77bdd6eff9e544e - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/.cproject +8f3874f3592022902246b887ff77ba3dafe8988d - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Nucleo-L476RG.ioc +20bd88d6e69c5795823fcabe4faf5f97189eab7d - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/usbd_desc.c +d866ccd9ea216a89eb9d539b9a9df43b83b1c7cd - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/system_stm32l4xx.c +efe613f6cfea1253034d36d8f9eb0a3885a72b51 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/stm32l4xx_it.c +e82acf04a1cad0a297e5cfc954c31a504c3c53e6 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/stm32l4xx_hal_msp.c +6d604522f0cef3bff34a64eb9e500cdce25b5d57 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/usbd_cdc_if.c +c1db06ecec983da549ee3a8ae57154b2460f8d4f - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/usbd_conf.c +16d1db972ccab86a0e8c0aca69dfb400853b139d - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/usb_device.c +55729e915ad655e9e16d0d30c7699bef97c14a99 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/main.c +f8423beb4a536d57e5aa0c948599c0c8feb00a9e - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c +c766b5449c964208e6c0301ca2f558902b8b9528 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc/usbd_cdc.h +ab94a34d9ab12695aebd8fa8466ade808f27e929 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c +3b25e71498a2311c71b3919166ecf09dc5141b1e - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c +9a2873d30abe93eeb862acfe28f3590a9a6f06b7 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c +60317c715b32cdb43f4f23b57141868055ea4589 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_def.h +f2e11c0c40d6e621c683638444082ccb2cd1e404 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ioreq.h +ae9cd8bf67b36f59b68abe1006f6e621b3097871 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_core.h +10fec4a5fea35ec45db039d5a366c3b6a4dfdc47 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ctlreq.h +03bd0280d262095dfc54880a3beebc7e8d1cd238 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/usbd_conf.h +75b6204210b1d2d7bc133c477e55b55ab886553d - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/stm32l4xx_it.h +29fa5f1155f4b6471a344eb19184bb023e939cbf - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/main.h +f2d077bd5409d6fd6fe3992c5cb64c6f4632d217 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/stm32l4xx_hal_conf.h +97a7710fdcc32282cbf75739e2b1afaff643e09f - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/usbd_cdc_if.h +c20ba1d07bb19091580f77d81b3ef95b0b843914 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/usbd_desc.h +b1f85fda09c5bd2d09cea7044da1fe04616da066 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/usb_device.h +25392a40719c25b125bb4abc1c9105228b153444 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/.settings/com.atollic.truestudio.debug.hardware_device.prefs +988b68517c27704d1f464138322cb3e7ef94c005 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/.settings/language.settings.xml +a19a363124b0fdc91c783bf67234bfd09ec1c211 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/.settings/org.eclipse.cdt.managedbuilder.core.prefs +72ad8c891c625eccc2ed488d63e73685b36bb7de - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/startup/startup_stm32l476xx.s +7b273c6190dd31db4d1f5091bb46a780eed2f065 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rtc.c +6905470e6a40b7909609c5a5e902c0efcae29c17 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rcc_ex.c +b31f07cb494c120315b086a52a662d098943fb56 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_gpio.c +4dbd5f4ac87a7b6ac1d550a567e59f1238f7d026 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_tim.c +54204b942a2710a64b6ba0c30b84e1b3b52dae74 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash_ex.c +622a5ea51bdb8c062e8e889f4b71bf6482fa5264 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pwr_ex.c +12784369e6124301623660326aeffa81593b036a - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_usb.c +4dda1150337631a2d17123634e05b782a5668b04 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rtc_ex.c +25ec312cbb302ca24cf9e909df42265a12821a78 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_dma.c +2b8ea417236425866c81e285a0ab18d04783b587 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_i2c_ex.c +b167ca16a9d80ffe8bdffec69454d740bf0117bc - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_uart_ex.c +5f07fe6dad1130b6ee4df5a184ac8b0226619cd6 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_tim_ex.c +7e7baefb69d9a62f7684c185a9fb3ddd83500a39 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_cortex.c +df06884b75649ad21d7110e12ab4de41f1e9eb4c - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash.c +a15fdfad695b08ee5b822074ff541cf712f2c39b - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_dma_ex.c +da703e39e170c4cb94dfa998f3f1ffa29d80d699 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal.c +36599a4da2f2d80c6e6ac0220385ee433b03e54f - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rng.c +4516770dad8099473586dfb47cf5cc4cf85dbecc - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_uart.c +e926d3bdc7e3bf71bb7539ea30ea292b92d7ffe3 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pcd_ex.c +70c187cc31e577582b15c93b82183a02ae1e45c4 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rcc.c +a049a3b8f2c1bbc893531c3dec916646bc42443c - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pcd.c +b241444200a682980fe3e6bec522da4e967a170a - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash_ramfunc.c +1e88ee4f8bd2b1617b9d2523943dd1e6acb23dcc - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pwr.c +296985473134d81cdcee7e324c2d47a069390872 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_i2c.c +da4c5dc66fa19f1a2dea73d7aa3e81597b676dcc - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_tim.h +76daccf26f1c1119f653377547eebb3aead3ae9a - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pcd.h +3f9db9098124b6d4bf658a9ff358a93525f658b0 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rng.h +eeefa20586b1afc75301a9c1a9fa51984bf8e5be - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_def.h +85ce004e873496c1eacf6087a2b3c82652c2f87c - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash_ex.h +cc2961929d2d137935b8d36ce4d073c22ecb6d0a - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_tim_ex.h +ef09ef096f9aea54c52b3f8643d4a2de8caefd08 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_usb.h +7d01a2e45f24933398c321ebf63ab167f6681b98 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_cortex.h +2905f1d5f33236d983b4c332990276c9e1bb5521 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash.h +05b58c53586df1d7b41ae67ee282455482c2467d - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_dma.h +7a1f93772829c677cd79a5c7d91c49a0d414bfb8 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_gpio.h +66a329dbf83da1d835ef3a2056ff37b30cc34c2a - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_dma_ex.h +7cae377cfa95e6bca50a18ebe16d4ecc325278df - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pcd_ex.h +cde58e7973942b2d9f6fddaa266fff01a9f39a9b - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rcc.h +d87d95f0dce5fc06196437a894acb9c5d4f02f95 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rcc_ex.h +a737f1820b6165f725d7549f95775b4d21c6767f - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_i2c_ex.h +ee193c30ba73303f2644de840804e121c4a9a4ea - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rtc.h +c98c6c63fac3bcc2cdeac550828e9bf253b0aa5d - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal.h +dffe5c55f2b819f9601130a43806007a1746359b - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_gpio_ex.h +06a183a5b3a97fb5a3ccdfeae53c776cfb650a04 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash_ramfunc.h +b93c1179f456734f5977ee7fde296795f371dfaf - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pwr_ex.h +ced33137d14e602db17d8caf629ada93528ee8a8 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_uart.h +54e67e3be92290f9e6457f2f91c04bbc7099ea48 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pwr.h +5de56cbae29e353bad3c38d9081a059eface1630 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rtc_ex.h +d79b95f004663f145e964ff6cb145e92a36e9652 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_uart_ex.h +4e41e93110701a53f7bc809136a4ab0649de3413 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_i2c.h +c23c26b4a5705dfa36703ea8b6c5f40dffd8ab7f - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h +16b99b227562ccb1354b33482c354c1812123013 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cm4.h +3fea94e10d135f6717a70f8d1e199b010baa7f08 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cm0plus.h +9f5c937feac2936c1cf0ced43722f527a1531ca2 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_sc000.h +6c2c8dba3fe5460a7310efae010a5b7937025aa1 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/cmsis_armcc_V6.h +e0a1f1bbe188023d261188754e1dc59c781fb565 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/cmsis_gcc.h +70a7d2f8ffcfbebc2f39f3cdb5ef701e081a6e92 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cmInstr.h +e68945e0faf5ee8d1f027d7e8be3b4c321028e39 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cm3.h +0186b62597ed4f4804e7b81abd3b598e6c2bd555 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/cmsis_armcc.h +bcb11dcd98c7ba42403d991919032dde3049b364 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/arm_math.h +c93167da8e8344f98d9b28f27a857a1d41a10530 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/arm_const_structs.h +3d909ef05e1c328dbc138a1b906e914b968239ed - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cmSimd.h +c6f03caabac7d0b08fed7d09ee6db8b6f2093853 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cm7.h +c87716fe24718015c2d01cf913480c92e3b0b4b3 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cmFunc.h +441239dec598474dc7ab14b7283195c7f649a3c1 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cm0.h +90061e5e149725c682eb80978b557fd388191f24 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_sc300.h +0a94a9650bfc5345f574fb23a10d495f06735cd9 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/arm_common_tables.h +bcaf73ba929b494e9c3f2993e975bb7de3fbff2e - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Device/ST/STM32L4xx/Include/stm32l4xx.h +5d6591e31b6229f63fd06eb0de8724554b4b44f0 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Device/ST/STM32L4xx/Include/system_stm32l4xx.h +8f94380a70fb6a2a723ab7278572292ae274e564 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Device/ST/STM32L4xx/Include/stm32l476xx.h +dc8595af01c9444a2c541182900bf2b0fb28b819 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/.mxproject +a52f7d5678ac81e61ec37b727b6292b6369b0caa - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Nucleo-L4A6RG.ioc +3985a4fde219680c1e17e341acd59488439dcfde - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/mx.scratch +ece39ffdce43f997fdf2dd55d74017f38603c617 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/.project +cda727dead5740c98700cc1fd4ad37858a6f0320 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Nucleo-L4A6RG.pdf +4afdcaa4fef2feb33d218e6d2388e3f3b3838203 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Nucleo-L4A6RG.elf.launch +3f8bc8936a633424641eab00ba651f076d380035 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/STM32L4A6RG_FLASH.ld +44ea1cb0eee4d33fe6e691653cea4a32e74e87f0 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/.cproject +20bd88d6e69c5795823fcabe4faf5f97189eab7d - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/usbd_desc.c +d866ccd9ea216a89eb9d539b9a9df43b83b1c7cd - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/system_stm32l4xx.c +65f7e0f37508e288cec330f92d477098d2ff4c82 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/stm32l4xx_it.c +c28cb48bd43bb7b4c492078ab1dc6f494bfdba2a - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/stm32l4xx_hal_msp.c +6d604522f0cef3bff34a64eb9e500cdce25b5d57 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/usbd_cdc_if.c +c1db06ecec983da549ee3a8ae57154b2460f8d4f - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/usbd_conf.c +16d1db972ccab86a0e8c0aca69dfb400853b139d - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/usb_device.c +40579596ad18cd876b59233ace09918e6c93fc64 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/main.c +f8423beb4a536d57e5aa0c948599c0c8feb00a9e - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c +c766b5449c964208e6c0301ca2f558902b8b9528 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc/usbd_cdc.h +ab94a34d9ab12695aebd8fa8466ade808f27e929 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c +3b25e71498a2311c71b3919166ecf09dc5141b1e - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c +9a2873d30abe93eeb862acfe28f3590a9a6f06b7 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c +60317c715b32cdb43f4f23b57141868055ea4589 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_def.h +f2e11c0c40d6e621c683638444082ccb2cd1e404 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ioreq.h +ae9cd8bf67b36f59b68abe1006f6e621b3097871 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_core.h +10fec4a5fea35ec45db039d5a366c3b6a4dfdc47 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ctlreq.h +03bd0280d262095dfc54880a3beebc7e8d1cd238 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/usbd_conf.h +984804b6ff3ca103ce3abb97027764ede06f0b28 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/stm32l4xx_it.h +9d1ea64fa5998b911cc7f5af6cec6ddbf4fc8f9a - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/main.h +b90b9552c0a39dbb50871b7d2d0487c31ab43c23 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/stm32l4xx_hal_conf.h +97a7710fdcc32282cbf75739e2b1afaff643e09f - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/usbd_cdc_if.h +c20ba1d07bb19091580f77d81b3ef95b0b843914 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/usbd_desc.h +715d5dee9ff492cfad346512f7d1d53801e4f445 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/usb_device.h +2393e776dd333dae85dc34f806ad87b6e55aaff1 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/.settings/com.atollic.truestudio.debug.hardware_device.prefs +988b68517c27704d1f464138322cb3e7ef94c005 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/.settings/language.settings.xml +a19a363124b0fdc91c783bf67234bfd09ec1c211 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/.settings/org.eclipse.cdt.managedbuilder.core.prefs +3ae4b06f79f30f7f8aa7cb36e8911765333cf94e - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/startup/startup_stm32l4a6xx.s +7b273c6190dd31db4d1f5091bb46a780eed2f065 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rtc.c +6905470e6a40b7909609c5a5e902c0efcae29c17 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rcc_ex.c +b31f07cb494c120315b086a52a662d098943fb56 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_gpio.c +4dbd5f4ac87a7b6ac1d550a567e59f1238f7d026 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_tim.c +54204b942a2710a64b6ba0c30b84e1b3b52dae74 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash_ex.c +622a5ea51bdb8c062e8e889f4b71bf6482fa5264 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pwr_ex.c +12784369e6124301623660326aeffa81593b036a - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_usb.c +4dda1150337631a2d17123634e05b782a5668b04 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rtc_ex.c +25ec312cbb302ca24cf9e909df42265a12821a78 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_dma.c +2b8ea417236425866c81e285a0ab18d04783b587 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_i2c_ex.c +b167ca16a9d80ffe8bdffec69454d740bf0117bc - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_uart_ex.c +5f07fe6dad1130b6ee4df5a184ac8b0226619cd6 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_tim_ex.c +7e7baefb69d9a62f7684c185a9fb3ddd83500a39 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_cortex.c +df06884b75649ad21d7110e12ab4de41f1e9eb4c - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash.c +a15fdfad695b08ee5b822074ff541cf712f2c39b - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_dma_ex.c +da703e39e170c4cb94dfa998f3f1ffa29d80d699 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal.c +36599a4da2f2d80c6e6ac0220385ee433b03e54f - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rng.c +4516770dad8099473586dfb47cf5cc4cf85dbecc - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_uart.c +e926d3bdc7e3bf71bb7539ea30ea292b92d7ffe3 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pcd_ex.c +70c187cc31e577582b15c93b82183a02ae1e45c4 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rcc.c +a049a3b8f2c1bbc893531c3dec916646bc42443c - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pcd.c +b241444200a682980fe3e6bec522da4e967a170a - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash_ramfunc.c +1e88ee4f8bd2b1617b9d2523943dd1e6acb23dcc - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pwr.c +296985473134d81cdcee7e324c2d47a069390872 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_i2c.c +da4c5dc66fa19f1a2dea73d7aa3e81597b676dcc - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_tim.h +76daccf26f1c1119f653377547eebb3aead3ae9a - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pcd.h +3f9db9098124b6d4bf658a9ff358a93525f658b0 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rng.h +eeefa20586b1afc75301a9c1a9fa51984bf8e5be - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_def.h +85ce004e873496c1eacf6087a2b3c82652c2f87c - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash_ex.h +cc2961929d2d137935b8d36ce4d073c22ecb6d0a - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_tim_ex.h +ef09ef096f9aea54c52b3f8643d4a2de8caefd08 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_usb.h +7d01a2e45f24933398c321ebf63ab167f6681b98 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_cortex.h +2905f1d5f33236d983b4c332990276c9e1bb5521 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash.h +05b58c53586df1d7b41ae67ee282455482c2467d - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_dma.h +7a1f93772829c677cd79a5c7d91c49a0d414bfb8 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_gpio.h +66a329dbf83da1d835ef3a2056ff37b30cc34c2a - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_dma_ex.h +7cae377cfa95e6bca50a18ebe16d4ecc325278df - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pcd_ex.h +cde58e7973942b2d9f6fddaa266fff01a9f39a9b - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rcc.h +d87d95f0dce5fc06196437a894acb9c5d4f02f95 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rcc_ex.h +a737f1820b6165f725d7549f95775b4d21c6767f - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_i2c_ex.h +ee193c30ba73303f2644de840804e121c4a9a4ea - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rtc.h +c98c6c63fac3bcc2cdeac550828e9bf253b0aa5d - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal.h +dffe5c55f2b819f9601130a43806007a1746359b - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_gpio_ex.h +06a183a5b3a97fb5a3ccdfeae53c776cfb650a04 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash_ramfunc.h +b93c1179f456734f5977ee7fde296795f371dfaf - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pwr_ex.h +ced33137d14e602db17d8caf629ada93528ee8a8 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_uart.h +54e67e3be92290f9e6457f2f91c04bbc7099ea48 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pwr.h +5de56cbae29e353bad3c38d9081a059eface1630 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rtc_ex.h +d79b95f004663f145e964ff6cb145e92a36e9652 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_uart_ex.h +4e41e93110701a53f7bc809136a4ab0649de3413 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_i2c.h +c23c26b4a5705dfa36703ea8b6c5f40dffd8ab7f - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h +16b99b227562ccb1354b33482c354c1812123013 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cm4.h +3fea94e10d135f6717a70f8d1e199b010baa7f08 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cm0plus.h +9f5c937feac2936c1cf0ced43722f527a1531ca2 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_sc000.h +6c2c8dba3fe5460a7310efae010a5b7937025aa1 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/cmsis_armcc_V6.h +e0a1f1bbe188023d261188754e1dc59c781fb565 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/cmsis_gcc.h +70a7d2f8ffcfbebc2f39f3cdb5ef701e081a6e92 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cmInstr.h +e68945e0faf5ee8d1f027d7e8be3b4c321028e39 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cm3.h +0186b62597ed4f4804e7b81abd3b598e6c2bd555 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/cmsis_armcc.h +bcb11dcd98c7ba42403d991919032dde3049b364 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/arm_math.h +c93167da8e8344f98d9b28f27a857a1d41a10530 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/arm_const_structs.h +3d909ef05e1c328dbc138a1b906e914b968239ed - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cmSimd.h +c6f03caabac7d0b08fed7d09ee6db8b6f2093853 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cm7.h +c87716fe24718015c2d01cf913480c92e3b0b4b3 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cmFunc.h +441239dec598474dc7ab14b7283195c7f649a3c1 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cm0.h +90061e5e149725c682eb80978b557fd388191f24 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_sc300.h +0a94a9650bfc5345f574fb23a10d495f06735cd9 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/arm_common_tables.h +bcaf73ba929b494e9c3f2993e975bb7de3fbff2e - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Device/ST/STM32L4xx/Include/stm32l4xx.h +0f852853d184800034247a5d0050de2038777c65 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Device/ST/STM32L4xx/Include/stm32l4a6xx.h +5d6591e31b6229f63fd06eb0de8724554b4b44f0 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Device/ST/STM32L4xx/Include/system_stm32l4xx.h +85e7e51a25b2016e19b43a83b81346b96db2098c - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/syscalls.c +9d4edc03b07fb9a306f35477b2a45b832a0b66ba - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/include/PlatformData.h +fe5b2785e65fcf188d1d792ffd7c6fc9c70e9e7f - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/include/prototypes/Platform_fp.h +af14794f057b0fe6e08f9ff6dff3f0984e2cc237 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/PlatformData.c +2ed430e9572654a9f6a7d1c1de12420cc48fcbe4 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/Unique.c +7f88737cf8bf4c13e5bf0e728c99ecd1ec2eac82 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/NVMem.c +c1fce976f4e44378a135909f67cc1ef149b461c1 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/Cancel.c +6cc02291ef841cd08ee3118ea5c136fb69c5ee46 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/PowerPlat.c +b9b1622090e7b69eda0c3f496ef773e397a0e0f5 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/PPPlat.c +a1acb654a01f63360985c13e32deb69a3606c39e - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/Entropy.c +c063491490aa3f9157ea6d4880a3bb5648095413 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/Clock.c +3d94e64861a183a21778f017d310208436cb95a2 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/RunCommand.c +7dabb6c802903adc4edfa6e0ba4b894cf0ffd4de - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/LocalityPlat.c +bb9a6b6f33159fa31c2e47ad133c70f5e77d3d39 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/TPMDevice/include/TpmDevice.h +a2564dc3ec0abc5d2445670de944311b40bfb514 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/TPMDevice/include/StmUtil.h +d7040d40a32ff98b1198bae412d846d457bd6a4b - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/TPMDevice/include/user_settings.h +bce98e24be98537929f371316db2f2801c152ed8 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/TPMDevice/src/StmUtil.c +ddf299e517d5b6ad1395c4106f50d0261d7a26c5 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/TPMDevice/src/TpmDevice.c +1afb5b61a4b2c034a07aad4f5e11c78d9b1f0412 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/VCOM/VCOM-TPM.sln +507bf667be23c5916dad43a004b8cc0f97f4ed50 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/VCOM/VCOM-TPM/VCOM-TPM.cpp +6b81e4587698e6857f4814dce4b4d0391a2e8766 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/VCOM/VCOM-TPM/VCOM-TPM.vcxproj +57c8c0f47d2168b6955706ef677c467b7368a98b - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/VCOM/VCOM-TPM/targetver.h +6a0dc513f9c01293d6cdbe167f765c5b5f4d5e83 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/VCOM/VCOM-TPM/VCOM-TPM.vcxproj.filters +74f86a73a25ac67fc34a014747a6efeb3d44e1fa - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/VCOM/VCOM-TPM/stdafx.h +5310225c6b795c683cf6f10a15abceae11332937 - optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/VCOM/VCOM-TPM/stdafx.cpp +f9b4aae1684da7aaee3611a970f76f38a46d52a2 - optee/samples/ms-tpm-20-ref/TPMCmd/flags.m4 +0204b212240ca16f5e60f43b0a30b2697f77d183 - optee/samples/ms-tpm-20-ref/TPMCmd/simulator.sln +1cd01c0cf4c4a66ec725a1f0fccca2350024844d - optee/samples/ms-tpm-20-ref/TPMCmd/Makefile.am +194cc98738c13d785c82704c6fc8e0ed0bcc99e2 - optee/samples/ms-tpm-20-ref/TPMCmd/bootstrap +90c98d16825e38e3e8c730857334eb3678940874 - optee/samples/ms-tpm-20-ref/TPMCmd/configure.ac +dabc6f784df969fbda726a380436cc15b3ae3a54 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/Tpm.vcxproj.filters +1767e2e5744eb1166945e42a8b4c345bf876c401 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/Tpm.vcxproj +6134fd9595a0db3004b3200ab2754e6060a9e613 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/X509.h +731ef0324c0883b40649fa1ce81f85f6c6f64e7b - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/swap.h +d80e69a62cc5bc30321acc8ba40916ae6c11bac9 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/KdfTestData.h +09c046895d104e84270b38f51a580a571d067e37 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TableMarshalTypes.h +f03b22a486395fb8481df3912c4beb5814cbd117 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Tpm.h +cfb478e72c88b38989a79c857ca529c96cb05a26 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CommandAttributeData.h +0bee8bdd2a0e7cec942ab1ffe4f5a5a0819f3204 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Commands.h +58e518b99239ed12b3b9d18225645004fc7416d0 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/HandleProcess.h +0b3bdd77473b5c674385a4de1fb1ba806385ffa2 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/ACT.h +3cdb1b7e18bf92a0a11db7ba7bd87f76f7c62157 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CryptHash.h +5ee1c6c70f36b1a98a1c09e82db86bdfb94d6bd6 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/SelfTest.h +5c7992298c480a370df9665518ec6dbae0de0602 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CryptSym.h +6690e48f59d84a65cb431aedc4ff04060ce0390d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/NV.h +48323efd0b877a90ca646e264addeeed14adc169 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TpmProfile.h +04a11a40106e32d1a2c327ed2ee76d52f1fac338 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TpmAlgorithmDefines.h +040719da4c629d01698b06072537878d1ea7d2b9 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Marshal.h +6a410f835b221a8130b8be5650395d9faba6072a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CommandAttributes.h +7cbe82bc9668a6dba6a469b42f3d0b942f0520f4 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TableMarshal.h +a11f6a872439861a933474fe412a0427c0730fe1 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TpmBuildSwitches.h +5d1d9bf90c4bd7e98673e597da72ba2f3b9bca93 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/BnValues.h +ed8716500b6fa3680567484cef4705f9a874e365 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TpmASN1.h +94aa65d7ce788d652472e56c424a45e7769dbcc2 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/GpMacros.h +c5f4ed58f4082b8a06c2dea39618e8fb10454877 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/PRNG_TestVectors.h +bdb13a835cd51676ea457d951ca7433dbc57eab5 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CompilerDependencies.h +58c4efd7565cb517e7ab2c25a966cab710d92663 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/VendorString.h +144f3bb0c333db82f37ff9d5fccf48dc4fab0f41 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/SupportLibraryFunctionPrototypes_fp.h +bafcf4a000318fac0009b809ac2bf9a70cf9c791 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/LibSupport.h +f69660e465a1480bd79a1f8cf16f80352a60a7ef - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Global.h +d2108a7734eec6c0e66394d3c12a50150c04ac3d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Capabilities.h +f249cb73e1800699c831824f77261a2ec96eae6e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/EccTestData.h +09d85312988cbf36c3dd26e95988b816d1873095 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TableMarshalDefines.h +b38f19b0bed0f5f71f2da37145d05356d0dc94d6 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CryptRand.h +5adbbfd2ff8e8dee66469ce1ce6f2d285589c6d0 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CryptRsa.h +efc8b2228515d82aea4ea093d4cab20a7d249f7f - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TpmError.h +18af239d7a28f416247aa8dd6e9ecf28141a0c89 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/SymmetricTestData.h +6d0f1fb0d0f3b2a8d19f1ce046869d30150fce09 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CommandDispatchData.h +c3b8d078373237d8e7f138c67b4f382b40517192 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TpmTypes.h +7e6987419dcd3d08639dfd3e91a8c57fd9872b5a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/BaseTypes.h +cc0a6421806e68997e500be631aa81828521ec2d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CommandDispatcher.h +70fda7df3afa9fd65627182e71265908467556af - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CryptTest.h +29a46309c3fb01be084d8e8951eb7901dde603a0 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/SymmetricTest.h +23b7e6271c380c8e85532c40b58f8224ffbb6d82 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/MinMax.h +3b05494bbc0dc8e939e8026e84571fff9e472617 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TPMB.h +bae04f0ac0d19fc1461941fea785027bcb9dad6e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/OIDs.h +b18d3976f439634cb05a45561819d0b9b4d73098 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CryptEcc.h +11b48254afade03ed20f8c729f3892f435436345 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/InternalRoutines.h +fd18d2b01b63b618061ff8f370e2033b8c4dea10 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/HashTestData.h +ca5a553f1de3616fbf5052b6c38342e00959ff12 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/RsaTestData.h +dc6d2d41f9734e7709dfc69708fc6287a3622925 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ossl/TpmToOsslHash.h +6e52cb65b5558ad2766ed1b90d74c6c67b8e1e73 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ossl/TpmToOsslSym.h +8f4370cfcc34bb136a67d12a14149d9cf9f60d13 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ossl/TpmToOsslMath.h +4f5f2c13cc24a386e4bbd872b04e28b04c23750f - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/StartAuthSession_fp.h +0c232e0f1f0a3ffbb6252b7dcc284e0eb5816e65 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/HierarchyChangeAuth_fp.h +a3c777b5e458806ba068d57d179e56d85752ecb0 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyCounterTimer_fp.h +f8c1f6beaff3089603dbb43f6bfbe4bced35471b - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/MAC_fp.h +426dee6a25a2583b6247df858ff7964ef871b9a9 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/FirmwareRead_fp.h +0a390598326789930752b0a4eb4eeca9534919ac - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToOsslSupport_fp.h +87c144583176739ed4827270dbc6b9d3abd5e813 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_Event_fp.h +c0addab72ad3020cfff53f078df316c064e7cc1d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/X509_RSA_fp.h +68e113f085c014c63f20b6a810267fb29992b4dd - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/EventSequenceComplete_fp.h +d4738948505e602dfd25c30c2d2127f169469349 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToOsslMath_fp.h +1e20b1d0983d33cd549b8720837621ef325c250b - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ECDH_KeyGen_fp.h +4ba84b2df817a6524144f53ad70869d329891eed - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Commit_fp.h +d81b55f0818fc590e22d0091bb1d5e39562ee877 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/_TPM_Init_fp.h +033c9057731df5494aa445d61a4886cccfd01e58 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PropertyCap_fp.h +a4fbdeaa426df1653196174226b6b48afe347c43 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_Read_fp.h +d0e86324b120265b5227e7cf729d89e4c2768bf5 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ECC_Decrypt_fp.h +872ea306826581c94a3901d981a4e343c3c357f8 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyAuthorize_fp.h +00fc2ade3a5dc5ddd4221acf56cf8d9972c88224 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ECC_Parameters_fp.h +39d4dcf44ec35f860980866e35e51cfa327029c5 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Sign_fp.h +e3e0bfa681c313b42f930b39cb3706c12188f7fb - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/IoBuffers_fp.h +9becf531f45281cd080d8ad3140178b7011db42c - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/_TPM_Hash_End_fp.h +fe5b4ced7121524a956e7e2a8779f95b254062c5 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/EncryptDecrypt_fp.h +8ef2616ae42cfc6341c39bfc7d5c9e251fa4123e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/VerifySignature_fp.h +f81667c844095ebcbde3be4b80103fb2411ccf0e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToWolfSupport_fp.h +263799522ef3ff9d6677847e2d97fdb59aa3744c - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/HashSequenceStart_fp.h +10cd33e9e84c65659b05a614fe22885bbb0b5576 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmASN1_fp.h +c079447cd9518a4638372c0f5063406242518cbb - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyAuthorizeNV_fp.h +f60fac38469c28712e358afb8d737112e7c8462e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Shutdown_fp.h +ce280d1906b146f860d0548256feb7020cd26383 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_Allocate_fp.h +300bf426a8fb3f09d3f7536ed32dacb0bd9c4628 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ObjectChangeAuth_fp.h +cd7e7991d07683dfac8d62da427618dd0b1bc1e1 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_SetBits_fp.h +21253e9f491e5c3aa9285fc9b5ead280258b2349 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptEccKeyExchange_fp.h +4568199cccb437653f262a20a4ea2790cc2ece54 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptPrime_fp.h +f27e1a7967e61ef8bf65bd75de47cc20c76e6109 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/X509_spt_fp.h +8fb75dbf117c7fb587355b323ad006c34e9bdf1d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CreateLoaded_fp.h +d7c909486a97798ffe4f88811bdde662f1efbb2c - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyPassword_fp.h +06772c3dacd56547129c09c8f9f6df1379a19fdb - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Clear_fp.h +ab94632d4ded278cb4f2ea153cc8f08f9422224f - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptHash_fp.h +f97a3facaa3598f5623f6b88e79c27b8d291adbe - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/RsaKeyCache_fp.h +b5051ade5493dc76c56085d8dedd7ba18165b13d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_Extend_fp.h +efa6e3cd6c13f77fcdd2f0324b56f4bef02a7aff - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyTemplate_fp.h +0cc1fd2ec5abeb0f1e845c49aaa160d4e68a85a1 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/EC_Ephemeral_fp.h +7761e46cea834947efcaf77d4bd95b35090d4f8a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ContextSave_fp.h +8e49bb3ca7117e6e780bab45db67db0ead9c5ca2 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TestParms_fp.h +300b61a4e1ef2d90038d34101216bb4f4f438d57 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyPhysicalPresence_fp.h +356266471ea0cd56744fa25a7f491dd297962e09 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/IncrementalSelfTest_fp.h +4d86f90ac8d6bbf2bce7ad8624c1dc2b3bf5dcdc - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmSizeChecks_fp.h +7b4a1bba6d26a63e4053870aefe57a5a989c9ade - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/_TPM_Hash_Data_fp.h +d04a57074c5a6696f79ce639e9c000f5afdda980 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/RSA_Encrypt_fp.h +60a578ecc4a1311da2cb2d314599e50eda98ce20 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ClockSet_fp.h +0e48f14c10cf6cce68174a223525dc0d4881c586 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyGetDigest_fp.h +079dd0f1840e22baed846c9e02ebe113c11b5cc0 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ChangePPS_fp.h +4496b790b236610306f95697b6d469d62f55c0de - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CertifyX509_fp.h +7c4c000d51e015f75eed6d80280e1775c39f389d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NvReserved_fp.h +46313fe32eab76dd78587ec08d8197ceecd05aeb - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptSelfTest_fp.h +6a189ce8aa6a78a130802b206df376563a9bef79 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SequenceComplete_fp.h +f451b90022116d27da1d8daa055a756cfd2c7433 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ECC_Encrypt_fp.h +8137948f4115d2d4d54323a472d93d4ec6fa4d50 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/GetCapability_fp.h +f36fa0be0029ba31ccb3df0c3708912eda650857 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Import_fp.h +d31443ea45f0f2036bb833bb61864921aba958e8 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Create_fp.h +c459ecbfa01a1793393632af787ef0449d5c3409 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptDes_fp.h +e062efc91d99f491e381087a02b61db9dc73fdf2 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToWolfDesSupport_fp.h +74c9451a504f6cf1c95ca2d65b544d5c2fd05271 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyNameHash_fp.h +f2718ee13d5cf19fc376ce3c4832f2b01aa99516 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/DA_fp.h +fe973ac240eb632c90e84f8da86116fbbd38d2c6 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SelfTest_fp.h +9a38584e2a30c9b5500393ce93e9818dda8f5d72 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyLocality_fp.h +e6492c7ec627a702d359ea6ae8794969f786c692 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_spt_fp.h +070f1d957fa166d1382a794efa2a8c20d939d5f7 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyCpHash_fp.h +fdaf877c881d86c0f02329d28429fad0f8307ff7 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/RSA_Decrypt_fp.h +44ddd229666c154957ee9376cf1e97248f1e34b8 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Manufacture_fp.h +0fdbef88eafe31c268daa16552451e6bf681fdef - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ACT_SetTimeout_fp.h +c82c8ae619c5d23244bef504b7fea485ccb9a91d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/GetTime_fp.h +9a33da54fde72510b33d0294d27b8cad4580dc27 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Session_fp.h +991c478c0252e36dd9106ee335303bc77a90966d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SequenceUpdate_fp.h +914d7b438c78e8a7242539c0cbfe573751cd7c47 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToLtcMath_fp.h +3e5aed256a4e7a1fda0a90fcfe86ec3531bbcb43 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Quote_fp.h +a3f4d21d0c5c06d44cab05bec5bf92983bafc3fd - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CreatePrimary_fp.h +3c2afbef3c046c3160a4ea2edd1140f5d954b71f - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Hash_fp.h +f74b75d1e6ff70241553a77c88f91d61c4a26ec2 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ChangeEPS_fp.h +cb1eec55cf276e26c8975988e7a423c33ac5f10f - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Duplicate_fp.h +1fe54f80c4cb8cce2fe745633c3010c7bd74dfe7 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptEccMain_fp.h +245146b2f725f65a40c489a792047786a96128b3 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Policy_spt_fp.h +7bc81e20a06653013e4acbf2174985473486bac9 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Hierarchy_fp.h +06d4cfb6780878c42481e4a77c5308cfafca5837 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Load_fp.h +f74d147bc6c976470de0070c75351df3aa04b120 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SetCommandCodeAuditStatus_fp.h +5304584889d4d650f0af1712e0a977aa2ea0f5be - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/EncryptDecrypt2_fp.h +5a4039d7f94ae60ce02866c46425571dfb8006e2 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/AC_spt_fp.h +e9a553efde26f94f58686193a7e6008b733519da - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptCmac_fp.h +f1ba19c3c43065642a6af8fa5895220506394517 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToLtcDesSupport_fp.h +af0ede8240131c95b2285547640960087becef7b - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Ticket_fp.h +f5b68b2634bec606fd5bd4eec855bc0ab5bd210d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Entity_fp.h +f4427b665d78cdc3834335573899fbb6350ccfd1 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/LoadExternal_fp.h +fdc545be48642a8de20e4fd3b7d30084222ea399 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_Read_fp.h +225763ffa0645413e5a490914ecd7a9de8f99a50 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/GetTestResult_fp.h +3c59906bb8361d9498ea673335e88b92361d6f18 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/AC_GetCapability_fp.h +bbd8c64c38105cbd75fce5e356241e0d42b3dbc6 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_SetAuthPolicy_fp.h +932e66bb1587712ac42bed734b088921f4f6f911 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyPCR_fp.h +1a5420f04ea7e3e726390dd2ff1bff61fd988102 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyNV_fp.h +87d27972c3bc15584593dd37d0ef50f0c73cfcfb - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ResponseCodeProcessing_fp.h +9667984e3855fc027a45cfb981949f64b2a980a2 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_SetAuthValue_fp.h +765379d25d1438de22351a96a9820bf9f67c6369 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_Increment_fp.h +6c1fb57a8caea7622cc7cda8dbd7418164257de4 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicySigned_fp.h +54c2a1e796afe1f9a817b5e36aee8e51edb67faa - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Policy_AC_SendSelect_fp.h +185e4f5e8e6ec8bc7c973a7e77db33409494980f - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/DictionaryAttackParameters_fp.h +f6d26035cccaae7afe8b836b2985803184981afc - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToLtcSupport_fp.h +9e0e5f492375fcc68e65dad4a397b231a504cb60 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Object_spt_fp.h +fea4b12eaff5c6e50481a9887b53037725a2b164 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SetAlgorithmSet_fp.h +906c4e6e7787dcc7647de13894175b9b8c78c94a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Handle_fp.h +7f1299d217585c2efab081499e77f630a0080127 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NvDynamic_fp.h +71ed6694c0ef2f14696a671067200c134221da42 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Marshal_fp.h +be6e44fe64124ec47e14bf135c7237b8480639c4 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/BnMemory_fp.h +062e68dbb60c05523086cfe239dbfeeb8fb00b47 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TableDrivenMarshal_fp.h +ffe4657deebfe157a4a2ee653cedf9bcb8fa2aa2 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/MAC_Start_fp.h +615b75cd87214bebe2493a06d39fc014fd87a003 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyCommandCode_fp.h +7a31af2eae74a929f10edfcc4c24a5da80259da6 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToOsslDesSupport_fp.h +ff21254543ae6a56beeb71d3af23f8ca5af1c641 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Context_spt_fp.h +1f07c1a9db3fbb122f8ea251ebdd8594b931316d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptEccCrypt_fp.h +4f57f936b4064fc13f7b608cb7931359c8248413 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Certify_fp.h +2530b56f366d5693bd4b9788364595dd64ef8bb1 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/StirRandom_fp.h +bd088f3ed8a49ffeb79779805d7fe8f5fe429e6d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptPrimeSieve_fp.h +809a441e0cd662f3edc35bb48c71b70fa4de923a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/FieldUpgradeStart_fp.h +fc5fd2f87d6c7a171ac18ad6e702315be926ff5f - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Attest_spt_fp.h +8e12dde0d8b6a4a6df5111e1cb35070963a9c1ab - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/FlushContext_fp.h +8b01720df595ad116744109fe662ac1041ef2d17 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyAuthValue_fp.h +26d0cc4fbdb4c876f246cd35c500de0df11d004a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyDuplicationSelect_fp.h +3b1f567f4eec7189eeb071adccba7008432b2f1d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/AlgorithmCap_fp.h +194c22bd1d2268c21271034395c6e5c7f3456317 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/HMAC_fp.h +4eb345137b18f67c6d6a92362de243a4470b189f - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyNvWritten_fp.h +3c4776d65fe50a6b4f993be0274bfc9af6a3788f - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ClockRateAdjust_fp.h +b6d95fc4fb41098675bf252b54fd9f70e151396a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_fp.h +398b220fbfcc188a24581dbdc0233f38cf46da65 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ReadPublic_fp.h +5f3c95f7f2d37e876472a869c5744b9f2836586b - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_UndefineSpaceSpecial_fp.h +cd64ef63467eebced0395ccae4075ca03b9b477a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_Certify_fp.h +1cb2a688416c6bbadc8f136f5cd7ba4f41e6a908 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CertifyCreation_fp.h +189603b73c164917c3ad6da3e57d43795df47e49 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmFail_fp.h +181d669752be56b7d098c0e2b997e83bbf4e3463 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToMbedtlsSupport_fp.h +50d60105aeb491c363fb7fc71af8f6d184a8ddb0 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SessionProcess_fp.h +342bfded66f61b70aeb3d6535cb587da5c084190 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Startup_fp.h +657d7a2f6be74009fd6ba71259a0ba9db9a5f9b4 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptRsa_fp.h +30e2baf658cea26efa3f65366091f18add1dd3e2 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_ChangeAuth_fp.h +70caac4f95082012db4c203616bedd8902a33e1b - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PP_Commands_fp.h +705c42624a99f8a50f98e73d8e689dfb980e2353 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_Extend_fp.h +62167537419cf517ebecbeef3a3f5a0c1022339e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ZGen_2Phase_fp.h +423a70459c7a42197b1022dc4985f46533df4f9c - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PP_fp.h +0db82ff3316ed8f8a4f35ac28136f4534cdf8ada - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_Reset_fp.h +4b3379ea7110dd195658a8bea5a69f015634fa2a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToMbedtlsMath_fp.h +4014e8a2dee7e34d380f54a9f63e57eb084c7e38 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyTicket_fp.h +33f109b5abdbba662dcfd9adba3ee83d6f5761c7 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToWolfMath_fp.h +3eaadf88924cb87a0f87197e56d730d10aa4bcea - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/AC_Send_fp.h +e2bab6b783da540ebed7c7744c2ab12f96de3a6c - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/X509_ECC_fp.h +9208541836c9bd37a1ecf8b8da894d2d06caa429 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ContextLoad_fp.h +3a2df2a3ba359f45c72afc5477feaeb04c040911 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptSym_fp.h +e1a70369cd10c91bfa80cabac0164abae4071c00 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptUtil_fp.h +bcca270ebd95b6c36bb026701c1fc6e10554269c - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/AlgorithmTests_fp.h +64aa9231cb6f99292517ddf87646f4ec58112fae - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/BnMath_fp.h +1dc8a1b1ee77cdaad11ae24d7c9e233a1aa179ad - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/GetRandom_fp.h +d91913b01b764e0449460491497eebbf88f9f916 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SetPrimaryPolicy_fp.h +3fa7b7eff4068d80739c460f99deaaeb38dcbfbd - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_Write_fp.h +1f5d61b4bc666bc9e2c7a2b2340981780b1d5621 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/GetSessionAuditDigest_fp.h +da0cc9b12038fa5755653d91b6af905656867d8c - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ACT_spt_fp.h +cb593754e54997bfec26b244337da487832a169d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Bits_fp.h +966a94c84420a6e831b2345e42c2a1b5208935ca - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicySecret_fp.h +daf655f7f9d8e642540ae12f919a65c9e3272999 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Time_fp.h +8c79c59ab5b57268d7b68edae092db9e1da1b272 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Object_fp.h +fc302c9e27b645c41806d3e0314fa5af086ba321 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CommandAudit_fp.h +d7ac37a61726d7e3b2733f8b704489a828207d79 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/EncryptDecrypt_spt_fp.h +5c6bef2af8c42ced4e3549272d93b6d9a7abbb4e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Locality_fp.h +94e53599dcb7a66ec20387e0622c76308ffa7518 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CommandCodeAttributes_fp.h +e78e7c727698052ba6fd837e2274a99ea439623f - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/HMAC_Start_fp.h +d688bd13f2834c070a6436dc0eb7a8ef69968ef1 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/DictionaryAttackLockReset_fp.h +eeda26581cdae3c60f7b85d412d6e722fa1cca1d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptEccSignature_fp.h +18ec7d3e9e1a2b6819d68862aa501f87cf313e57 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_ReadLock_fp.h +1fee483125e847c0c6a692a5d8bcced1cfd2f968 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/GetCommandAuditDigest_fp.h +65f6077d8ce98912da5a797f9cb1a618663f987e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyRestart_fp.h +ff4177b6562723e9391aa6c1cee96acdbd5f54e5 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ActivateCredential_fp.h +6a98f30011aab15ae4a3e2f4a5f18a678003d64f - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ReadClock_fp.h +dff750cbe8395a88e93634e511dc2c2ff71d28ae - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/MathOnByteBuffers_fp.h +b9702a44eb11019d3a4ec6675ce4e38e67221d9a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ExecCommand_fp.h +06199d37140facc7d34c4897130d896fa683bf3a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/FieldUpgradeData_fp.h +46dae84767e488ee05b03d268bf0077488f135fb - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Vendor_TCG_Test_fp.h +966015a1f338b6ce76df6dd119a899c8dd5193a0 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Unseal_fp.h +0a1f40864a1114ba7310efa53eec36ff9ff0d0c3 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/EvictControl_fp.h +6c15358e6e765bb1709933086621bc6de87c8324 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Power_fp.h +e4c92fb55cb82f8c0c8bee37aa8e6bfc27414535 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ClearControl_fp.h +a3044ccd6ff15c5f98f7e3e928bd21ece990f192 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_ReadPublic_fp.h +385303ab908baf98f40aaa1773f283a2eaf47fdf - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyOR_fp.h +81fa16e20941dcace05e6e8cd07213fc49a61045 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Response_fp.h +1e6063cb8570108a24316b1d0b0a19f8d3fbfe8e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ECDH_ZGen_fp.h +294a8c44266ef8fe51719e7f4aa2431c106efa4c - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_UndefineSpace_fp.h +bda7a075bd3ac2b5484c7ab74c9a1149331b1606 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/BnConvert_fp.h +cd0104a0d1225c54870a961051303400679e6f18 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/_TPM_Hash_Start_fp.h +5bbc5c70ebc57d409d90c3429cd56b9b5ba41bc7 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Rewrap_fp.h +4614c9b4ac558792b4bca4a00db55929090dcb8a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/HierarchyControl_fp.h +c334eea2de454d94ebf0fcb31d0a0abd4478e222 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Memory_fp.h +9df5275bee6405837a4e152739b4caab9caf9708 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_GlobalWriteLock_fp.h +4cee80ce92fd1c8adb25144bd0e41b0e9cdbbec1 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_WriteLock_fp.h +b432f0167cfc07f57f8eefe34ae9d371f0e65f1c - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/MakeCredential_fp.h +9e65c289c6e006611fd88114375bf5d690b38d37 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_DefineSpace_fp.h +0295a03af3062947bf7f4b6b8630449aa099ab2c - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CommandDispatcher_fp.h +a306f5aa9c06af0466100491598149650dfdaaa7 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptRand_fp.h +ba809abff8c2bbeab31d3bf32837b04784fa1b5a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptSmac_fp.h +83f5aa1e09b5cf7f7e9c963a04924be2d387ea46 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ltc/TpmToLtcHash.h +9ac20ce300cd3be129fa297a4a163f3fa3f1eba0 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ltc/TpmToLtcMath.h +7c782bef7fc2962fd03c896be5358aac325fa276 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ltc/TpmToLtcSym.h +48edc2e51ce501d43db4723d8322b229fc0eda1f - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ltc/LtcSettings.h +18938ceb070982017d5632c8111ccec6d8717bbd - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Mbedtls/TpmToMbedtlsSym.h +392bc93b6983659b99c8b56b15805a38ac333db2 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Mbedtls/TpmToMbedtlsMath.h +ff17ddc4c85292ce6f01b76548e25b0a98419666 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Mbedtls/TpmToMbedtlsHash.h +64aad5263d919aa145dffc96a4941c942d70691b - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Wolf/TpmToWolfMath.h +21b31bbdb64ac04aa1f112c364cb48c84dec6d73 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Wolf/user_settings.h +618c984b216712a3ed059461036bb34c4833c38e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Wolf/TpmToWolfSym.h +11cc83c54cb1323456bd8f3b0cb56de7a5ea6952 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Wolf/TpmToWolfHash.h +ce4065d5dbc369ef2260cfa2e091a9cdbad8ffc6 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptDes.c +8b5eeb7ff5530df4bddc9efe348fd45d8609c6bb - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/BnMath.c +87697819416bc9f6b5f4eb7971686f0d03d6cb80 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/AlgorithmTests.c +3fdc1e98645d29e1259c89193310a10565e0c381 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/RsaKeyCache.c +4958b5f51bffdefa5547f7e727a876d9490fe9be - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/Ticket.c +3a3ddfe5fe7f68485fa4470ee618469d5d1fb33e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptEccKeyExchange.c +6ed45ed0c56d83ef758a7f2c862927bdf71b156a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptPrimeSieve.c +b5d37ef8c950f8a169f5a9ef1e7b4328d2899401 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptSmac.c +9d5ee1ec8336ff2b940ec56b380b95b98f41a104 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptRand.c +d34cd17447bc01028977a012463d65f135f96fcd - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptUtil.c +b1a8ebaef50f97ee33ecae24d5edc0aa580c8ed7 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptSym.c +447f5d6341ed6ada7a8f30e830eb7464046b8e5c - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/PrimeData.c +368e618850636f255e9e57c0b139dcddf82af1e3 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptSelfTest.c +3a9e9a081c926caf63db37bffb80cda40c21ec2a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptEccCrypt.c +1401ef177f3e3bd7de55d6e5f0f8cf2e3ee71cf0 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/BnConvert.c +e81147da24030ba21f12edaf9d1917661c163be5 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/BnMemory.c +8cc48da41f271b6527a5855300cccd7c4094b96e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptEccData.c +9b79ff2b06c224c971f1e1e048045cf767db0830 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptCmac.c +4b29d8a36dc33ffc4d29ebc5fa799d6d99007ba4 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptHash.c +22eb0ea9add313f80a3ec949c2178c80c14bea52 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptPrime.c +c68e7e9e168486bd7ee10b85712f8cbd28c8c2c9 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptRsa.c +0ffb452a1717483aabfe47a9eeb7b99ac06ded4e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptEccSignature.c +61b0cd7757e3673f4054a6b67be5df89fa6c78e8 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptEccMain.c +54022276bfb56c330602829897c3fd1950feb456 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/ossl/TpmToOsslSupport.c +08b72177479e566714d6fef52816fe3b32322152 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/ossl/TpmToOsslMath.c +480e6f783ba16658f88981764ffe2f9218ba8f83 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/ossl/TpmToOsslDesSupport.c +aa003ed14dfbd14f15c33f8c85d2f780947c7624 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/ltc/TpmToLtcDesSupport.c +efd79a528de091dba68dffefc751a0a688423b93 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/ltc/TpmToLtcMath.c +9c1b3604bbf2860b0d80a657410e2a029adba6a1 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/ltc/TpmToLtcSupport.c +57d49fcf7d7e75f0f36db31891f577fe559dfd9a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/Mbedtls/TpmToMbedtlsMath.c +4368ae6f39b8b331277add014bbff034b940d525 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/Mbedtls/Mbedtls_mpi_Ltc_desc.c +4613687d53030af00a6b329a71087cd94acb5f11 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/Mbedtls/TpmToMbedtlsSupport.c +b0a0e725f466c5f614f8bda31e08f9a919f12fb1 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/wolf/TpmToWolfMath.c +3af0edffcca6f089325ee30b97c2fb94e3b291bb - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/wolf/TpmToWolfDesSupport.c +8eb628b011385e5d70d3cfde68069f665ad56e51 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/wolf/TpmToWolfSupport.c +f030593dac7c1db3e6e839d0e1d7d0ac8945970c - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/wolf/wolfssl.vcxproj +466691e67c12dd9a679781b63234956dcaceba1d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/X509/TpmASN1.c +04b37d6adbf120e357ccb4678e380a1802931de0 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/X509/X509_spt.c +5c354c7223a81d7915882b573c56d94861eb2696 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/X509/X509_ECC.c +77b2c67dc99cf0e49e4cbabc22dc9acadf309708 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/X509/X509_RSA.c +46bab656e2cbbcf766c84d400690e11877f8a515 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/main/ExecCommand.c +0334c584b4a788c6fa56ca81ee53716501df41b1 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/main/CommandDispatcher.c +eafaa29ba3e6f0cec01550636783df940a842bab - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/main/SessionProcess.c +82f676616d720a25d5644ecc7960b7eeff0389d5 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/TpmFail.c +ef0426dabd8f706a78db06b58f8068b38ea9168a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/MathOnByteBuffers.c +0b4b574b83e692740b0c4e5d62635fa967d01e85 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Marshal.c +2c65acd9bd5f6337e5abd55c998395192cea06e2 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/ResponseCodeProcessing.c +38de6a36d2444e1ed0f3bee1d4fa5751c01943fc - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/TpmSizeChecks.c +58ee288becbef146b8dd5c5429f456388af332ef - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/PropertyCap.c +efb8e8833bd517b3b9385257aed75aeb07b5c4ae - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Entity.c +20cbfa127bd4687094564ecd2ba0d71c11785b92 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/CommandCodeAttributes.c +42ba5fa4090f7900b93f25610272c5d2744f92fc - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Bits.c +d1f11e405396fc8a356db922fe2cb0c8f654fafa - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/TableMarshalData.c +1ba30fb3845df79d51ee779b4eed9d9b7d1a3746 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Memory.c +94ba9200336a7684a6fa85ec99615753998935fb - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Global.c +9fce7edfb51de4c44936f9d5f46af956fd8e86ce - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Manufacture.c +40037ba43bb2780caab6c9320b9428a9e50c179e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/AlgorithmCap.c +6e7dea780558ebfdd0b1668661ac43fd7e876dc6 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Handle.c +b80579004bf66d76c34c31b4fe0ba65e1a34eb8a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/IoBuffers.c +36be33ce745c22699c4e2c5fe1eb19df4deac267 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Locality.c +5d749f54ac223562addbb57a4b3ece73eb25b9c4 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Power.c +f8b98f1215fd1f432f6e12fc63cc39e8bdd8be20 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Response.c +f117763dee48fbe30eec672134d8f4c747362762 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/TableDrivenMarshal.c +ebbf99f5b71a40e2dcb3b0718428993ceb092ea7 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/PCR.c +ec1d7790053a5109933da61c97434e47e326bd4f - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/Object.c +74b6eb8868ae67779b9cd920d12e7566d91ee613 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/PP.c +6f80821c4cecac735c594a05787bbed9e95b3079 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/NvReserved.c +391883c2c03bebc1ae73eaf4532d5329e15efbeb - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/NvDynamic.c +8f0cc6cde494e0e8e21ea01a914f39d3f98bf4ff - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/Time.c +c8236f84f180f2a66e475945307c6aab4e482bcd - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/CommandAudit.c +8d9c13452adc813895f72f470b65117e0e51db1d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/Hierarchy.c +26ddeedbe4bc042989c17d41b3103a7de8ac1aa6 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/Session.c +e04ffaaa0b2a9a182d315f2296f0f850fb06f440 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/DA.c +956f4eb8bf2f4bf527b634e5a10d21044d4a92e7 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/DA/DictionaryAttackLockReset.c +5b5d449bdc2e71ff8057f449d9e5d1ec8e1da5c3 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/DA/DictionaryAttackParameters.c +e877361fbd9ab03f37548f2b969f26c1e5d1a986 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/CommandAudit/SetCommandCodeAuditStatus.c +49d503f437be88abb3f8fe4e3843e150d3cbae80 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/ECDH_ZGen.c +4c9c1d8f06b9befc1dd89a87aa787db5a447a776 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/ECDH_KeyGen.c +36c60811874f45b8d6a79f79937c751c30988a07 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/ECC_Parameters.c +0b8899ea87e95427aceea6603379cd4e0ae8dd48 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/EC_Ephemeral.c +49f8fe178b8e7a87b01c6859413053a68c12cda7 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/ECC_Decrypt.c +9711def3ae76eb059ae7e10b3cbc85227c5d666a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/ECC_Encrypt.c +748f01adc89b2fe04ba4a8ac53d4bf345cc57c50 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/RSA_Decrypt.c +c2c0552d7494c97ddf408939c954951b1dc3033e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/RSA_Encrypt.c +44fb9d7637a41f76fd3105365c223cca6d5bde79 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/ZGen_2Phase.c +f523d6e9f92f556eb67c7192a4a212dcd21cb783 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/Unseal.c +1270d2675a052e452604abf21ae7d1e7ce9f055b - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/MakeCredential.c +96d90b66981dcfa3e2a05c0cbecbf34b91a65e14 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/Load.c +1bca8c7f48e122b595f81ecb428b54ea1dc50742 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/ActivateCredential.c +f020bb04aae416aeb7c1189d6ed5c79fb0a6e345 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/ObjectChangeAuth.c +5d5beaf98ae2e96ed9e9c00ab6ea26a57c78204e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/Object_spt.c +c09f0b9df15e12662d6ad78a68444a67bbdca8eb - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/CreateLoaded.c +310b0898c923667f453d165e0a9926eb8d346a6f - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/Create.c +64d5919c672dfc44fc10b7b069c2c866cabe82ac - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/LoadExternal.c +c3b9c77f50fb64add3975acb54afcb9419a522c3 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/ReadPublic.c +cabe90d3a0189bba8f0ec6be382ecb611e56d766 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/AttachedComponent/AC_GetCapability.c +cf6f2db7011f13d73a939be1a73a566edb53c5a0 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/AttachedComponent/AC_spt.c +8a5d00c0ff144f96ffef9e3e2ca6fdf521a138cb - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/AttachedComponent/Policy_AC_SendSelect.c +fbaae98602eedfa517257f018c3ba4cb424d9315 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/AttachedComponent/AC_Send.c +973173f0edfcf6ab2d80e4380b6bb78bf08119a9 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Context/ContextSave.c +96b1b4082707dddfd7fe52922b12ec510b3fca8a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Context/FlushContext.c +551606340bbbbd796441854729786c2c94a53f9c - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Context/ContextLoad.c +4c3fc77c75e0b5742471eeb110d6e6fabcb65731 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Context/EvictControl.c +733767778ac50dbd49ae6b97c045e5b0cc37046f - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Context/Context_spt.c +09e831c6316eb9fcc1350c6072797e7c9c2aa283 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Misc/SetAlgorithmSet.c +4fe85236b0efdf18eeab5b29cc23556f0279c206 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Misc/PP_Commands.c +e7a9e652bb4ac5e85c8e1db3d4e360db21571d1c - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Session/PolicyRestart.c +5bacab95011862392ab50c7063fbd39a71e4e1f1 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Session/StartAuthSession.c +68daa6c7c87031c44832452db4f633ccfefa061a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Startup/Shutdown.c +19dadc62f6dd24fbe1617b47f8643ede9afbb6d8 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Startup/Startup.c +a85083fd1766596d284bfcda7878062e4f848d31 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Testing/IncrementalSelfTest.c +043f05cbf29aaea72976bafa119fe4c6ea52947d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Testing/SelfTest.c +a04e1f890e0dc85c03762a0f93da8933cf72eeb8 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Testing/GetTestResult.c +39cef4fdd45cfae84dfe0b10421a8d22e48040bd - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/Attest_spt.c +c5b487407768a4cc47ce3e439229365023ba38c7 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/GetSessionAuditDigest.c +06e3406314f390af840548aa1e2bffa1500d0f38 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/CertifyX509.c +39d8048f7d7f6324dede76816b9cdce1895eda8a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/GetCommandAuditDigest.c +cccb8929c774f62ace8cc0f950b76aabc02e3f0c - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/Quote.c +7c3924284378b21001f6120874f7286b08bcab70 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/GetTime.c +0581c121a0ffb4b5516cb531fe622ce94df07d53 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/CertifyCreation.c +f7ef52b7fc3e51ac574ad1711265b80fae74a4b4 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/Certify.c +60025cb0327048a1655b2293a91790ea95968b89 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_ReadPublic.c +9b707597db32549caed72d79d4348286c2c8c84d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_UndefineSpaceSpecial.c +9b54b8fc55f8ee130f13641cba871c467c2f6539 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_DefineSpace.c +ff8f74e23cf6637980a1019ff15003dafaf84a91 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_Increment.c +bb0a22e25778627d4f64d217c94007571f56ead0 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_Read.c +b41bf18cd2dfd6937ebd33df85106bbd74c13966 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_UndefineSpace.c +34b1f44147ff14e1982afaf5ad498c710d71c461 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_Write.c +0f132292bc781aa375c73d7cc156d5ae2296885a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_ChangeAuth.c +4018d34a03f1542e2e6e07fc3c885b9a7151709c - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_Extend.c +9dce4f4ece8e8dc71a031b70d4772c43260808bf - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_spt.c +274e0fef208e3559e364558f2505ab960c569d05 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_GlobalWriteLock.c +7b599ffb429ad0c3f2893a1435dc227ffbdf9450 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_WriteLock.c +d5100f5da31705c1061b5c4fe009738a90d6991d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_ReadLock.c +328ae9a3a794b68bb003885fe34eea037f074d2e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_Certify.c +b16f3b8589cb0d5de3ede0e38c3df9566439dfc7 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_SetBits.c +1195dda2bfef5b2f0ebf5d9dd0c1483e693feb73 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Ecdaa/Commit.c +83b2aab8bfa4d8152b836dc79e649d2f9df8b428 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Vendor/Vendor_TCG_Test.c +ba06c2bbc967f489c0ef81a52ffd5bc61d854b10 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/HierarchyControl.c +f3ad6beabba99f2d302804f9e4040e30edbd168d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/SetPrimaryPolicy.c +3c6a9b5585e15ed5d931d520b13f18d3cf7a6427 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/Clear.c +2c0105db6fabf84cd5e1264af61fbcf8ca44ee4e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/ChangePPS.c +3b58be2b254ce73d0a09c4f40181e757b5801583 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/CreatePrimary.c +7c066a0b22f5047720515190002981c2bb4f8559 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/ChangeEPS.c +e40fdd1540746ada2ef6193fcfef5264945f440c - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/HierarchyChangeAuth.c +fb72b54a400108f311ba215a95647b182ec390ab - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/ClearControl.c +0cd97f9c3068ce2beeec5cdbe59a35195b92f647 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Symmetric/HMAC.c +ed64e70b14016b3e27d91724d8fb78a86c84492c - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Symmetric/MAC.c +bbf716723d7949b6ad949afb4c82e74f200e8c24 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Symmetric/Hash.c +a30e4e882bab65b23bad83718f0df3a86be8b240 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Symmetric/EncryptDecrypt.c +c41a91e8a169399e5c3daf950f1903d22ec91757 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Symmetric/EncryptDecrypt_spt.c +40161da967ed914f228a3aab5100d896da33824d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Symmetric/EncryptDecrypt2.c +73735fc467c6d10ff8de1c9bd2fd6048cceabb71 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/Policy_spt.c +48b353b2ebd17849912faca615aa97d50d2141b8 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyGetDigest.c +40cf33b0b774dae8c6ccb5d65405a7e54903e4c9 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicySigned.c +1e23cd2245b273f4e2d7c559727c9b160b0477e5 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyLocality.c +8705b3a606961e1b05c0d5dd32765309a325ed52 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyCounterTimer.c +932ed2d5107b414d84be1be9a2a851f4e4e8b347 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicySecret.c +a05c262c1e6127b2a49b9489b60850b35762bd26 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyCommandCode.c +753243158f166cb485c6e7a3471c6b4b028c68d3 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyNameHash.c +aab6431ac9d4fcce238593514a9cbadf4b9215ef - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyOR.c +88c03c37cfbed2aff36dfbcf94b95177d54762fe - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyPCR.c +588a8d77a584bacab70eb45e8653cc26182caa9b - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyNvWritten.c +1bfef4dab67e4efb29fa68b09e96d2627fad2be6 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyTemplate.c +d0a42a69ce9e7024add491c99d63f917623c341d - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyAuthValue.c +866b4da196d99d410685d625146c5262614a1057 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyTicket.c +dcaa8cea72af93d8c5f3d8a57089f1fd72ed3e74 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyCpHash.c +7a3b44021510f326081fdbe1076c06ab481e2a97 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyDuplicationSelect.c +68f8914ab2417a723a81d1d2b51282e8487cd768 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyPassword.c +ffb4fc98afe39eaf79abbe1a21e1f9cb4f142d9a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyPhysicalPresence.c +ded5971153e324b8b4f6aa95db951d09de1b2ecd - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyAuthorizeNV.c +f961c5947f92e32233dc32e62249202b2cd07570 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyAuthorize.c +19218fe30830606f6ec36f65abfa5e6dc61a2d12 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyNV.c +5286c36046943f4d9666a1f20f762f249903529a - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_Event.c +b85eb5bb0cb8d3c1f3f066d6592d520c64a30028 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_Read.c +1723fd5edd58d258867ce07a1e6cb192a9134684 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_Reset.c +567fcf447739ce658f12b708c9e630adac2c02a1 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_SetAuthValue.c +85b8105ca22c96106141ea7ca062c4f3b55f288b - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_Allocate.c +2f0d5d80986eab6a2f480f5a119aa292574a5c43 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_SetAuthPolicy.c +1936c8a82923b6cf455ae9a32086f8b47e9fcec5 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_Extend.c +131c53ad4309da75d2d0c0fc48b42eb85ab892a5 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/HashHMAC/SequenceComplete.c +4998afedc6c5beb0fa299bee383dfe91fbc7de4b - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/HashHMAC/MAC_Start.c +1d73e64673af7532369bdea0b79d8b3b9c2809a2 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/HashHMAC/HMAC_Start.c +182701b3fd417d0a2f45bf6e0b05851de8424950 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/HashHMAC/SequenceUpdate.c +6a557c5edff08e22d2de7967bfb737a1a26634e6 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/HashHMAC/EventSequenceComplete.c +2c67c87e19679660cdb2f8d32954da97e14f8079 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/HashHMAC/HashSequenceStart.c +2be8b39f7a4a7cf50977aa0ac7b44554f06e29df - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Duplication/Import.c +bb1c1c731518c7698413695ba8d8e16627303ea2 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Duplication/Rewrap.c +93626622fb78f36fff350c70113da9af69da76fa - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Duplication/Duplicate.c +77c7e04182e899c143665ccc8d47f7ec8205b288 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Random/GetRandom.c +fbfe1dd32c3d5e790448ead7346654838dc3e482 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Random/StirRandom.c +1d02ad4911a3717f8c16a00147f895e042001df2 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Capability/TestParms.c +705d003f4eda4e14d5adc59e0dbd61083645812b - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Capability/GetCapability.c +e9fb4d674523f5fa0950178867220d9afdc21e6e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/FieldUpgrade/FirmwareRead.c +ac9421f2de85e45f1fdacc55df00ee912f582661 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/FieldUpgrade/FieldUpgradeStart.c +c5d528a495db164b7eeba279c3408a6e5864080b - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/FieldUpgrade/FieldUpgradeData.c +fcf83214d3f3c1296dc883a93dc91e189c82b88e - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Signature/VerifySignature.c +523dab0ff81bc5d2333604b81b8c655a72fb5957 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Signature/Sign.c +dcc4083b045cf3765b91c539f299216534cd07b3 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/ClockTimer/ACT_SetTimeout.c +b85fab62d41638b1960347ab5db0f5c04cc40b48 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/ClockTimer/ReadClock.c +36dc3efeecfa5aa7c6ea85f3634adb5d15a3be00 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/ClockTimer/ClockSet.c +fdc898681b4fb8c7223334448233c6e83fa470a6 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/ClockTimer/ClockRateAdjust.c +578761745c2b6d96650e066060a08eeedafe6de7 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/ClockTimer/ACT_spt.c +a68f1d79f27d6415a6946a5cad9f997591b471bf - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/events/_TPM_Init.c +c4e81a39b2206a46fdfcb4d7bbf14ee4307489c1 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/events/_TPM_Hash_Data.c +d209bee5b5913f0b761575695c8511fe6722f515 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/events/_TPM_Hash_End.c +6a0f30c4781067b8428260fe466e5d6e8d808842 - optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/events/_TPM_Hash_Start.c +29c82ba9ec61627d639ba195206aae5986b6d713 - optee/samples/ms-tpm-20-ref/TPMCmd/Platform/platform.vcxproj +7aaa3dd88ec8382f37bf795db6b66041ec21d6b6 - optee/samples/ms-tpm-20-ref/TPMCmd/Platform/platform.vcxproj.filters +28d350e18f1aef2b1a498f6a3c4d6b6fc4801e16 - optee/samples/ms-tpm-20-ref/TPMCmd/Platform/include/PlatformClock.h +e6bb9513e4249c3ac0a989c5fd7bfb903d289620 - optee/samples/ms-tpm-20-ref/TPMCmd/Platform/include/Platform.h +96a84654a7f17be4142d2be731b34f75a98ed392 - optee/samples/ms-tpm-20-ref/TPMCmd/Platform/include/PlatformACT.h +6bb582b72adaf604087fb29ed50662e4022c3ccc - optee/samples/ms-tpm-20-ref/TPMCmd/Platform/include/PlatformData.h +3981e6d6dadaa8e8d24d15a406bf689b056f0417 - optee/samples/ms-tpm-20-ref/TPMCmd/Platform/include/prototypes/Platform_fp.h +d290d3667f6beb284f0939e9bb8de8e5f791ae65 - optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/PlatformData.c +48252f45915ed083a6bac0596f3f735e790030ff - optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/Unique.c +a0db60df8165e3f3d2b061e5d016e276436ac491 - optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/NVMem.c +840342229d7c6e58ac57152754601a3bc71ba600 - optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/Cancel.c +bb85408dbeab5098eb77aa2313d4b28c1d50c029 - optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/PowerPlat.c +f3feb56e3c38c94f33efddfc87b0a0c57195b8f5 - optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/PPPlat.c +2d34f6fdc0779ace9b29380650859eb2dc9beb3b - optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/Entropy.c +d0b4a5d97e521e77f766897886f80c684d758eab - optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/Clock.c +5dd2e2afbb7b708d9bc585d6c7a1263fe5e3e6cc - optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/RunCommand.c +913caab5748d7a733058680722290dd4cbaa18a6 - optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/LocalityPlat.c +8904b7172e9c95bf5ccca723413a69488c1eb920 - optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/DebugHelpers.c +8fa7666caa7a84f328f87f9a9dbebd3c9388c8a5 - optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/PlatformACT.c +2db3c7ae60b9a166c0d001451a16c623a1182ded - optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/simulator.vcxproj +97dd5b29b67f302ad063523d539990c19123b90a - optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/include/TpmTcpProtocol.h +b3c67c071ec064771e077773cb203d881499a063 - optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/include/prototypes/Simulator_fp.h +adbc8328158bfbac3794e5bd132d5ea0304dbcd2 - optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/src/tpmsim.service +ed0d9f117bda9b562ce47f09fa526466ea647130 - optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/src/TPMCmds.c +d7bd32e37a53264b6ec8ebcf3b41f087652c4d3d - optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/src/TPMCmdp.c +922b6cdcf8fe2c2afbea87d499eba8234873cbb8 - optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/src/TcpServer.c +5a493d9124d00ded9800ae107ba167c72c9056ad - optee/samples/ftpm-helper/Makefile +7522d5293f83744f086728d6cd38c877fe39a3ad - optee/samples/ftpm-helper/README.md +96da5d9fe175e882abdd919aa1c4bd9a2def2f06 - optee/samples/ftpm-helper/LICENSE +5dbb2cb40501d442a50453c79e55f6fe7aa642c9 - optee/samples/ftpm-helper/host/Makefile +4ebeba0c52d359825b26ffad5fd456d1c43277d8 - optee/samples/ftpm-helper/host/ftpm_helper_ca.c +05ab08f5221f05e94520ed9495423d026bcd5460 - optee/samples/ftpm-helper/host/tool/odm_ekb_gen.py +44dd5efe74224613ae3361b5288d5f4fbbffb808 - optee/samples/ftpm-helper/host/tool/ftpm_manufacturer_ca_sign_sid_csr.sh +46d7267ff5f2e40f0cb402b89ccef57708c6ce05 - optee/samples/ftpm-helper/host/tool/ftpm_manufacturer_ca_sign_sid_csr.py +ffaf17771c52fb326d9298929500e7cad003d933 - optee/samples/ftpm-helper/host/tool/ftpm_manufacturer_gen_ek_csr.sh +e3f3060340f290f4b9ac80f0bfef98636605414c - optee/samples/ftpm-helper/host/tool/ftpm_offline_provisioning_verify.sh +6040c09f6e07731353cde2f79647f9b37019012c - optee/samples/ftpm-helper/host/tool/ftpm_manufacturer_ca_simulator.py +ddb11390ea289ff539c833fcd9849d0bf81106b2 - optee/samples/ftpm-helper/host/tool/ftpm_test_local_attestation.sh +58f17af47d0dd8ec7ec3e5a0a4cfcc10da119248 - optee/samples/ftpm-helper/host/tool/ftpm_manufacturer_gen_ek_csr_tool.py +17aa9eb1d7d6989dee35a50bb30d873f45ab053f - optee/samples/ftpm-helper/host/tool/kdk_gen.py +18d61e2198cfc4965ec932ad1751e98ea619bffe - optee/samples/ftpm-helper/host/tool/oem_ekb_gen.py +fe950095be80ba8e01f91fc8db3c98d64f2ce7b3 - optee/samples/ftpm-helper/host/tool/ftpm_device_provision.sh +cce78a2db51c264b884b2e53c7605556e4651318 - optee/samples/ftpm-helper/host/tool/ftpm_manufacturer_ca_simulator.sh +22dcd0ebfce77a7abdceaa85dadfbd5151814ef4 - optee/samples/ftpm-helper/host/tool/lib/silicon_id_csr.py +68063b7cdc77b6f03971c9b479950603d395e530 - optee/samples/ftpm-helper/host/tool/lib/ftpm_ek.py +2989d9817b1d1ee76139b1bf780f937af2721fe3 - optee/samples/ftpm-helper/host/tool/lib/aes_drbg.py +79c7dece1ab210876510b24cf9a18ec129a93693 - optee/samples/ftpm-helper/host/tool/lib/ftpm_ek_csr.py +2b3f0a1315886edf3fe2969e88e4f709914c2ea1 - optee/samples/ftpm-helper/host/tool/conf/ftpm_i_ca_sim.config +ab33fbbfb23ed4c0687e915bd88cc7b568b319d1 - optee/samples/ftpm-helper/host/tool/conf/ftpm_root_ca_sim.config +174230a84516fd6fc4c6dfa553bfba136df35489 - optee/samples/ftpm-helper/ta/Makefile +6442bb99b6d3029526133a362a0838012c051149 - optee/samples/ftpm-helper/ta/user_ta_header_defines.h +a521701086a719a903d80697a572009e501ffb6b - optee/samples/ftpm-helper/ta/ftpm_helper_ta.c +680c8e7491b86f42fa79551446d38294fae5bd5e - optee/samples/ftpm-helper/ta/include/ftpm_helper_ta.h +9eebaea6c013cd863161f00430bf4b6a154813a6 - optee/samples/pkcs11-sample/Makefile +fc4fb84dcbf00b04fcc91f516aedd701350aed89 - optee/samples/pkcs11-sample/LICENSE +a7f13b06bf4c5eb0669cf42f2632c2b235262393 - optee/samples/pkcs11-sample/host/Makefile +b7cb007727b4c2e482d77fcb1a3c7834caf80fbd - optee/samples/pkcs11-sample/host/pkcs11_sample_ca.c +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 +52056059ceb33df8556122c574b98bbaf33f9599 - optee/samples/hwkey-agent/host/tool/gen_ekb/gen_ekb.py +db9d139cadc808f2be7926b333651ef7b0cb09f8 - optee/samples/hwkey-agent/host/tool/gen_ekb/README +31660a5c7c817d388aa60d8e7425a54d0faa3241 - optee/samples/hwkey-agent/host/tool/gen_ekb/example.sh +5054796c29272096d67dbf4fa7453f9bfa3ad280 - optee/samples/hwkey-agent/ta/Makefile +01a5ebf5ecbf58a06002ad10b902e18d78d452d8 - optee/samples/hwkey-agent/ta/user_ta_header_defines.h +52fd37078d752fb17a039afd148a99a6f90c57b7 - optee/samples/hwkey-agent/ta/hwkey_agent_ta.c +f1652fd24c49bf7be742b2e2081280bcd33d2ddd - optee/samples/hwkey-agent/ta/include/hwkey_agent_ta.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..7281f48 --- /dev/null +++ b/optee/atf_and_optee_README.txt @@ -0,0 +1,131 @@ +********************************************************************** +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 AGX Orin series + +---------------------------------------------------------------------- +Prerequisites +---------------------------------------------------------------------- +To install build prerequisites, for example, python3-pycryptodome and +python3-pyelftools, in your build machine, refer to: +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 in this document +---------------------------------------------------------------------- +This document uses a placeholder, "", to indicate Jetson platforms. +Its possible value is: +- 234 + +To build different trusted OS images and DTBs, select the platform value +based on your Jetson board. + +---------------------------------------------------------------------- +Toolchain +---------------------------------------------------------------------- +1. Go to https://developer.nvidia.com/embedded/jetson-linux-archive and download + the toolchain from Jetson release page for your L4T version. + +2. Set the CROSS_COMPILE_AARCH64_PATH environment variable to point to the aarch64 + toolchain. + + For example, if the aarch64 toolchain directory is + /toolchain/aarch64--glibc--stable-2022.03-1/, set the CROSS_COMPILE_AARCH64_PATH + with the following command: + + export CROSS_COMPILE_AARCH64_PATH=/toolchain/aarch64--glibc--stable-2022.03-1 + +3. Set the CROSS_COMPILE_AARCH64 environment variable with the following command: + + export CROSS_COMPILE_AARCH64=/toolchain/aarch64--glibc--stable-2022.03-1/bin/aarch64-buildroot-linux-gnu- + +---------------------------------------------------------------------- +UEFI StMM Image +---------------------------------------------------------------------- +- To build OP-TEE, a UEFI StMM image is required. + For the Jetson AGX Orin series, the image is usually in the following directory: + + /bootloader/standalonemm_optee_t234.bin + +- To notify the OP-TEE build script about the location of the image, set the "UEFI_STMM_PATH" + environment variable to the following path: + + export UEFI_STMM_PATH= + +---------------------------------------------------------------------- +Building the OP-TEE Source Code +---------------------------------------------------------------------- +To build the OP-TEE source package, run the the following command: + +./optee_src_build.sh -p t + +---------------------------------------------------------------------- +Building the OP-TEE dtb +---------------------------------------------------------------------- +To build OP-TEE dtb, run the following command: + +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 + export NV_TARGET_BOARD=generic + ./nvbuild.sh + cd .. + +---------------------------------------------------------------------- +Generating the tos.img with ATF and OP-TEE Images +---------------------------------------------------------------------- +1. Get gen_tos_part_img.py file. + This file is usually in the /nv_tegra/tos-scripts/ of BSP package. + +2. Generate the tos.img with the following commands: + ./gen_tos_part_img.py \ + --monitor ./atf_build/arm-trusted-firmware/generic-t/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. Complete one of the following tasks: + - Flash the system as usual. + This is useful for flashing a new system or replacing the + entire operating system. + - Flash the TOS image again using the following partition flash commands: + sudo ./flash.sh -k mmcblk0p1 + For example: + 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.bp b/optee/optee_client/Android.bp new file mode 100644 index 0000000..199f472 --- /dev/null +++ b/optee/optee_client/Android.bp @@ -0,0 +1,294 @@ +// SPDX-License-Identifier: Apache-2.0 +// +// Copyright (C) 2024 The Android Open Source Project + +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +soong_config_module_type { + name: "optee_client_cflags_cc_defaults", + module_type: "cc_defaults", + config_namespace: "optee_client", + bool_variables: [ + "cfg_debug", + "cfg_werror", + ], + properties: ["cflags"], +} + +optee_client_cflags_cc_defaults { + name: "optee_client_cflags_defaults", + cflags: [ + "-c", + "-fPIC", + "-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", + ], + soong_config_variables: { + cfg_debug: { + cflags: [ + "-DDEBUG", + "-O0", + "-g", + ], + }, + cfg_werror: { + cflags: ["-Werror"], + }, + }, +} + +soong_config_module_type { + name: "optee_client_libteec_cc_defaults", + module_type: "cc_defaults", + config_namespace: "optee_client", + bool_variables: [ + "cfg_tee_benchmark", + ], + value_variables: [ + "cfg_tee_client_log_level", + "cfg_tee_client_log_file", + "cfg_tee_fs_parent_path", + ], + properties: [ + "cflags", + "defaults", + "srcs", + ], +} + +optee_client_libteec_cc_defaults { + name: "optee_client_libteec_log_file_defaults", + soong_config_variables: { + cfg_tee_fs_parent_path: { + cflags: ["-DTEEC_LOG_FILE=\"%s/teec.log\""], + conditions_default: { + cflags: ["-DTEEC_LOG_FILE=\"/data/vendor/tee/teec.log\""], + }, + }, + }, +} + +optee_client_libteec_cc_defaults { + name: "optee_client_libteec_defaults", + soong_config_variables: { + cfg_tee_benchmark: { + cflags: ["-DCFG_TEE_BENCHMARK"], + srcs: ["teec_benchmark.c"], + }, + cfg_tee_client_log_level: { + cflags: ["-DDEBUGLEVEL_%s"], + conditions_default: { + cflags: ["-DDEBUGLEVEL_2"], + }, + }, + cfg_tee_client_log_file: { + cflags: ["-DTEEC_LOG_FILE=\"%s\""], + conditions_default: { + defaults: ["optee_client_libteec_log_file_defaults"], + }, + }, + cfg_tee_fs_parent_path: { + cflags: ["-DTEE_FS_PARENT_PATH=\"%s\""], + conditions_default: { + cflags: ["-DTEE_FS_PARENT_PATH=\"/data/vendor/tee\""], + }, + }, + }, +} + +cc_library_shared { + name: "libteec", + vendor: true, + compile_multilib: "both", + defaults: [ + "optee_client_cflags_defaults", + "optee_client_libteec_defaults", + ], + cflags: [ + "-DBINARY_PREFIX=\"TEEC\"", + ], + srcs: [ + "libteec/src/tee_client_api.c", + "libteec/src/teec_trace.c", + ], + local_include_dirs: [ + "libteec/include", + "libteec/src", + ], + export_include_dirs: ["libteec/include"], +} + +cc_library_shared { + name: "libckteec", + vendor: true, + compile_multilib: "both", + defaults: ["optee_client_cflags_defaults"], + srcs: [ + "libckteec/src/ck_debug.c", + "libckteec/src/ck_helpers.c", + "libckteec/src/invoke_ta.c", + "libckteec/src/pkcs11_api.c", + "libckteec/src/pkcs11_processing.c", + "libckteec/src/pkcs11_token.c", + "libckteec/src/serialize_ck.c", + "libckteec/src/serializer.c", + ], + shared_libs: ["libteec"], + local_include_dirs: [ + "libckteec/include", + "libteec/include", + ], + export_include_dirs: ["libckteec/include"], +} + +soong_config_module_type { + name: "optee_client_tee_supplicant_cc_defaults", + module_type: "cc_defaults", + config_namespace: "optee_client", + bool_variables: [ + "cfg_ftrace_support", + "cfg_gp_sockets", + "cfg_ta_gprof_support", + "cfg_tee_supp_plugins", + "rpmb_emu", + ], + value_variables: [ + "cfg_tee_client_load_path", + "cfg_tee_fs_parent_path", + "cfg_tee_plugin_load_path", + "cfg_tee_supp_log_level", + ], + properties: [ + "cflags", + "defaults", + "ldflags", + "srcs", + ], +} + +optee_client_tee_supplicant_cc_defaults { + name: "optee_client_tee_supplicant_plugin_load_path_defaults", + multilib: { + lib32: { + cflags: ["-DTEE_PLUGIN_LOAD_PATH=\"/vendor/lib/tee-supplicant/plugins/\""], + ldflags: ["-Wl,-rpath=/vendor/lib/tee-supplicant/plugins/"], + }, + lib64: { + cflags: ["-DTEE_PLUGIN_LOAD_PATH=\"/vendor/lib64/tee-supplicant/plugins/\""], + ldflags: ["-Wl,-rpath=/vendor/lib64/tee-supplicant/plugins/"], + }, + }, +} + +optee_client_tee_supplicant_cc_defaults { + name: "optee_client_tee_supplicant_plugin_defaults", + soong_config_variables: { + cfg_tee_plugin_load_path: { + cflags: ["-DTEE_PLUGIN_LOAD_PATH=\"%s\""], + ldflags: ["-Wl,-rpath=%s"], + conditions_default: { + defaults: ["optee_client_tee_supplicant_plugin_load_path_defaults"], + }, + }, + }, +} + +optee_client_tee_supplicant_cc_defaults { + name: "optee_client_tee_supplicant_prof_defaults", + srcs: ["tee-supplicant/src/prof.c"], +} + +optee_client_tee_supplicant_cc_defaults { + name: "optee_client_tee_supplicant_defaults", + soong_config_variables: { + cfg_ftrace_support: { + cflags: ["-DCFG_FTRACE_SUPPORT"], + defaults: ["optee_client_tee_supplicant_prof_defaults"], + }, + cfg_gp_sockets: { + cflags: ["-DCFG_GP_SOCKETS=1"], + srcs: ["tee-supplicant/src/tee_socket.c"], + }, + cfg_ta_gprof_support: { + cflags: ["-DCFG_TA_GPROF_SUPPORT"], + defaults: ["optee_client_tee_supplicant_prof_defaults"], + }, + cfg_tee_client_load_path: { + cflags: ["-DTEEC_LOAD_PATH=\"%s\""], + conditions_default: { + cflags: ["-DTEEC_LOAD_PATH=\"/vendor/lib\""], + }, + }, + cfg_tee_fs_parent_path: { + cflags: ["-DTEE_FS_PARENT_PATH=\"%s\""], + conditions_default: { + cflags: ["-DTEE_FS_PARENT_PATH=\"/data/vendor/tee\""], + }, + }, + cfg_tee_supp_log_level: { + cflags: ["-DDEBUGLEVEL_%s"], + conditions_default: { + cflags: ["-DDEBUGLEVEL_2"], + }, + }, + cfg_tee_supp_plugins: { + srcs: ["tee-supplicant/src/plugin.c"], + cflags: ["-DTEE_SUPP_PLUGINS"], + defaults: ["optee_client_tee_supplicant_plugin_defaults"], + }, + rpmb_emu: { + cflags: ["-DRPMB_EMU=1"], + srcs: [ + "tee-supplicant/src/hmac_sha2.c", + "tee-supplicant/src/sha2.c", + ], + }, + }, +} + +cc_binary { + name: "tee-supplicant", + vendor: true, + defaults: [ + "optee_client_cflags_defaults", + "optee_client_tee_supplicant_defaults", + ], + cflags: [ + "-DBINARY_PREFIX=\"TEES\"", + "-pthread", + ], + srcs: [ + "tee-supplicant/src/handle.c", + "tee-supplicant/src/rpmb.c", + "tee-supplicant/src/tee_supp_fs.c", + "tee-supplicant/src/tee_supplicant.c", + "tee-supplicant/src/teec_ta_load.c", + ], + shared_libs: ["libteec"], + local_include_dirs: [ + "libteec/include", + "libteec/src", + "tee-supplicant/src", + ], +} diff --git a/optee/optee_client/CMakeLists.txt b/optee/optee_client/CMakeLists.txt new file mode 100644 index 0000000..83107f4 --- /dev/null +++ b/optee/optee_client/CMakeLists.txt @@ -0,0 +1,49 @@ +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(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..10844c9 --- /dev/null +++ b/optee/optee_client/Makefile @@ -0,0 +1,175 @@ +# 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_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 +ifeq ($(WITH_TEEACL),1) +build: build-libteeacl +endif + +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 +ifeq ($(WITH_TEEACL),1) +clean: clean-libteeacl +endif + +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 libteec/include/*.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) + 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) + cp prebuilt/include/*.h $(DESTDIR)$(includedir) 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/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..eae481f --- /dev/null +++ b/optee/optee_client/config.mk @@ -0,0 +1,73 @@ +######################################################################### +# 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_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..978e665 --- /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..de7e330 --- /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}/../libteec/include + +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..c342012 --- /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..9af5ecf --- /dev/null +++ b/optee/optee_client/libckteec/src/pkcs11_processing.c @@ -0,0 +1,1707 @@ +// 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 */ + if (in) { + 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..00bb6ca --- /dev/null +++ b/optee/optee_client/libckteec/src/pkcs11_token.c @@ -0,0 +1,863 @@ +// 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" + +/** + * Converts uint32_t value to CK_ULONG with unavailable information support + * + * On 64 bit systems uint32_t cannot handle CK_ULONG defined + * CK_UNAVAILABLE_INFORMATION. Check for this specific situation and return + * correct value. + * + * @ta_value: Value form PKCS#11 TA + * @return Valid CK_ULONG value + */ +static CK_ULONG maybe_unavail(uint32_t ta_value) +{ + if (ta_value == PKCS11_CK_UNAVAILABLE_INFORMATION) + return CK_UNAVAILABLE_INFORMATION; + else + return ta_value; +} + +/** + * 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 = maybe_unavail(ta_info->max_session_count); + info->ulSessionCount = maybe_unavail(ta_info->session_count); + info->ulMaxRwSessionCount = + maybe_unavail(ta_info->max_rw_session_count); + info->ulRwSessionCount = maybe_unavail(ta_info->rw_session_count); + info->ulMaxPinLen = ta_info->max_pin_len; + info->ulMinPinLen = ta_info->min_pin_len; + info->ulTotalPublicMemory = + maybe_unavail(ta_info->total_public_memory); + info->ulFreePublicMemory = maybe_unavail(ta_info->free_public_memory); + info->ulTotalPrivateMemory = + maybe_unavail(ta_info->total_private_memory); + info->ulFreePrivateMemory = + maybe_unavail(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..ffcffd6 --- /dev/null +++ b/optee/optee_client/libckteec/src/serialize_ck.c @@ -0,0 +1,836 @@ +// 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_gcm(struct serializer *obj, + CK_MECHANISM_PTR mecha) +{ + CK_GCM_PARAMS_PTR param = mecha->pParameter; + CK_RV rv = CKR_GENERAL_ERROR; + CK_ULONG aad_len = 0; + + /* AAD is not manadatory */ + if (param->pAAD) + aad_len = param->ulAADLen; + + if (!param->pIv) + return CKR_MECHANISM_PARAM_INVALID; + + rv = serialize_32b(obj, obj->type); + if (rv) + return rv; + + rv = serialize_32b(obj, 3 * sizeof(uint32_t) + + param->ulIvLen + aad_len); + if (rv) + return rv; + + rv = serialize_ck_ulong(obj, param->ulIvLen); + if (rv) + return rv; + + rv = serialize_buffer(obj, param->pIv, param->ulIvLen); + if (rv) + return rv; + + rv = serialize_ck_ulong(obj, aad_len); + if (rv) + return rv; + + rv = serialize_buffer(obj, param->pAAD, aad_len); + if (rv) + return rv; + + return serialize_ck_ulong(obj, param->ulTagBits); +} + +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_GCM: + return serialize_mecha_aes_gcm(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..cabf92f --- /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..ce8b217 --- /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}/../libteec/include + +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..ee6fadd --- /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..d3cacea --- /dev/null +++ b/optee/optee_client/libteeacl/CMakeLists.txt @@ -0,0 +1,59 @@ +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}) + +configure_file(teeacl.pc.in teeacl.pc @ONLY) + +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}") + +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/teeacl.pc" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig" +) 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/libteeacl/teeacl.pc.in b/optee/optee_client/libteeacl/teeacl.pc.in new file mode 100644 index 0000000..92a7073 --- /dev/null +++ b/optee/optee_client/libteeacl/teeacl.pc.in @@ -0,0 +1,12 @@ +prefix="@CMAKE_INSTALL_PREFIX@" +exec_prefix="${prefix}" +libdir="${prefix}/lib" +includedir="${prefix}/include" + +Name: @PROJECT_NAME@ +Description: Access Control List utilities for teec library +URL: @CMAKE_PROJECT_HOMEPAGE_URL@ +Version: @PROJECT_VERSION@ +Requires: uuid >= 2.34 +Cflags: -I"${includedir}" +Libs: -L"${libdir}" -lteeacl diff --git a/optee/optee_client/libteec/CMakeLists.txt b/optee/optee_client/libteec/CMakeLists.txt new file mode 100644 index 0000000..c742d31 --- /dev/null +++ b/optee/optee_client/libteec/CMakeLists.txt @@ -0,0 +1,76 @@ +project(libteec + VERSION 2.0.0 + LANGUAGES C) + +################################################################################ +# Packages +################################################################################ +find_package(Threads REQUIRED) +if(NOT THREADS_FOUND) + message(FATAL_ERROR "Threads not found") +endif() + +################################################################################ +# Configuration flags always included +################################################################################ +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 +) + +################################################################################ +# Built library +################################################################################ +add_library(teec ${SRC}) + +set(libteectgt teec) +configure_file(teec.pc.in teec.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" +) + +################################################################################ +# Public and private header and library dependencies +################################################################################ +target_include_directories(teec + PUBLIC include + PRIVATE src +) + +target_link_libraries(teec + PUBLIC ${CMAKE_THREAD_LIBS_INIT} # this is pthreads +) + +################################################################################ +# 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}") + +install(DIRECTORY include + DESTINATION ${CMAKE_INSTALL_PREFIX} +) + +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/teec.pc" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig" +) diff --git a/optee/optee_client/libteec/Makefile b/optee/optee_client/libteec/Makefile new file mode 100644 index 0000000..6e80a50 --- /dev/null +++ b/optee/optee_client/libteec/Makefile @@ -0,0 +1,63 @@ +include ../flags.mk +include ../config.mk + +OUT_DIR := $(OO)/libteec + +.PHONY: all libteec clean + +all: libteec +################################################################################ +# Teec configuration +################################################################################ +MAJOR_VERSION := 2 +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 + +TEEC_SRC_DIR := src +TEEC_OBJ_DIR := $(OUT_DIR) +TEEC_OBJS := $(patsubst %.c,$(TEEC_OBJ_DIR)/%.o, $(TEEC_SRCS)) +TEEC_INCLUDES := \ + ${CURDIR}/include \ + ${CURDIR}/src + +TEEC_CFLAGS := $(addprefix -I, $(TEEC_INCLUDES)) $(CFLAGS) -D_GNU_SOURCE \ + -DDEBUGLEVEL_$(CFG_TEE_CLIENT_LOG_LEVEL) \ + -DBINARY_PREFIX=\"TEEC\" + +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/tee_client_api.h b/optee/optee_client/libteec/include/tee_client_api.h new file mode 100644 index 0000000..ba0cdc3 --- /dev/null +++ b/optee/optee_client/libteec/include/tee_client_api.h @@ -0,0 +1,583 @@ +/* + * 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_RegisteredMemoryReference. 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. + * TEE_ERROR_EXTERNAL_CANCEL Defined by the Trusted User Interface + * specification: An external event has caused a + * User Interface operation to be aborted. + * TEEC_ERROR_EXTERNAL_CANCEL Deprecated: not specified in client API, use + * TEE_ERROR_EXTERNAL_CANCEL intead. + * TEE_ERROR_OVERFLOW Internal TEE error – documented for completeness + * TEE_ERROR_TARGET_DEAD The Trusted Application has terminated. + * TEEC_ERROR_TARGET_DEAD The Trusted Application has terminated. + * TEE_ERROR_STORAGE_NO_SPACE Internal TEE error – documented for completeness + * TEEC_ERROR_STORAGE_NO_SPACE Deprecated: not specified in client API, use + * TEE_ERROR_STORAGE_NO_SPACE instead. + * TEE_ERROR_MAC_INVALID Internal TEE error – documented for completeness + * TEE_ERROR_SIGNATURE_INVALID Internal TEE error – documented for completeness + * TEE_ERROR_TIME_NOT_SET Internal TEE error – documented for completeness + * TEE_ERROR_TIME_NEEDS_RESET Internal TEE error – documented for completeness + */ + +/** + * 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 TEE_ERROR_EXTERNAL_CANCEL 0xFFFF0011 +#define TEEC_ERROR_EXTERNAL_CANCEL 0xFFFF0011 +#define TEE_ERROR_OVERFLOW 0xFFFF300F +#define TEE_ERROR_TARGET_DEAD 0xFFFF3024 +#define TEEC_ERROR_TARGET_DEAD 0xFFFF3024 +#define TEE_ERROR_STORAGE_NO_SPACE 0xFFFF3041 +#define TEEC_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 + +/** + * 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 */ + struct { + int fd; + bool reg_mem; + bool memref_null; + } imp; +} 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 + */ + struct { + int id; + size_t alloced_size; + void *shadow_buffer; + int registered_fd; + uint32_t flags; + } imp; +} 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 */ + struct { + TEEC_Context *ctx; + uint32_t session_id; + } imp; +} 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 imp Implementation defined parameter. Here it is a struct + * containing one parameter: session. session is an + * 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 */ + struct { + TEEC_Session *session; + } imp; +} 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/libteec/include/tee_client_api_extensions.h b/optee/optee_client/libteec/include/tee_client_api_extensions.h new file mode 100644 index 0000000..85298aa --- /dev/null +++ b/optee/optee_client/libteec/include/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/libteec/include/tee_plugin_method.h b/optee/optee_client/libteec/include/tee_plugin_method.h new file mode 100644 index 0000000..c08dc12 --- /dev/null +++ b/optee/optee_client/libteec/include/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/libteec/include/teec_trace.h b/optee/optee_client/libteec/include/teec_trace.h new file mode 100644 index 0000000..f75358f --- /dev/null +++ b/optee/optee_client/libteec/include/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/libteec/src/linux/tee.h b/optee/optee_client/libteec/src/linux/tee.h new file mode 100644 index 0000000..f883ebc --- /dev/null +++ b/optee/optee_client/libteec/src/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/src/tee_client_api.c b/optee/optee_client/libteec/src/tee_client_api.c new file mode 100644 index 0000000..512fdac --- /dev/null +++ b/optee/optee_client/libteec/src/tee_client_api.c @@ -0,0 +1,954 @@ +/* + * 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 + +#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; + size_t page_sz = sysconf(_SC_PAGESIZE); + size_t aligned_sz = ((sz + page_sz - 1) / page_sz) * page_sz; + + if (aligned_sz >= sz && !posix_memalign(&p, page_sz, aligned_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->imp.fd = fd; + ctx->imp.reg_mem = gen_caps & TEE_GEN_CAP_REG_MEM; + ctx->imp.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->imp.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->imp.memref_null) { + /* Null pointer, indicate no shared memory attached */ + MEMREF_SHM_ID(param) = TEE_MEMREF_NULL; + shm->imp.id = -1; + } else { + res = TEEC_AllocateSharedMemory(ctx, shm); + if (res != TEEC_SUCCESS) + return res; + MEMREF_SHM_ID(param) = shm->imp.id; + } + } else { + shm->buffer = tmpref->buffer; + res = TEEC_RegisterSharedMemory(ctx, shm); + if (res != TEEC_SUCCESS) + return res; + + if (shm->imp.shadow_buffer) + memcpy(shm->imp.shadow_buffer, tmpref->buffer, + tmpref->size); + + MEMREF_SHM_ID(param) = shm->imp.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->imp.shadow_buffer && (flags & TEEC_MEM_INPUT)) + memcpy(shm->imp.shadow_buffer, shm->buffer, shm->size); + + MEMREF_SHM_ID(param) = shm->imp.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->imp.shadow_buffer && param_type != TEEC_MEMREF_PARTIAL_OUTPUT) + memcpy((char *)shm->imp.shadow_buffer + memref->offset, + (char *)shm->buffer + memref->offset, memref->size); + + MEMREF_SHM_ID(param) = shm->imp.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].imp.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->imp.shadow_buffer) + memcpy(tmpref->buffer, shm->imp.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->imp.shadow_buffer && MEMREF_SIZE(param) <= shm->size) + memcpy(shm->buffer, shm->imp.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->imp.shadow_buffer && MEMREF_SIZE(param) <= memref->size) + memcpy((char *)shm->buffer + memref->offset, + (char *)shm->imp.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->imp.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->imp.ctx = ctx; + session->imp.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->imp.session_id; + if (ioctl(session->imp.ctx->imp.fd, TEE_IOC_CLOSE_SESSION, &arg)) + EMSG("Failed to close session 0x%x", session->imp.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; + } + + 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->imp.session_id; + arg->func = cmd_id; + + if (operation) { + teec_mutex_lock(&teec_mutex); + operation->imp.session = session; + teec_mutex_unlock(&teec_mutex); + } + + res = teec_pre_process_operation(session->imp.ctx, operation, params, shm); + if (res != TEEC_SUCCESS) { + eorig = TEEC_ORIGIN_API; + goto out_free_temp_refs; + } + + rc = ioctl(session->imp.ctx->imp.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); + +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->imp.session; + teec_mutex_unlock(&teec_mutex); + + if (!session) + return; + + arg.session = session->imp.session_id; + arg.cancel_id = 0; + + if (ioctl(session->imp.ctx->imp.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->imp.reg_mem) { + fd = teec_shm_register(ctx->imp.fd, shm->buffer, s, &shm->imp.id); + if (fd >= 0) { + shm->imp.registered_fd = fd; + shm->imp.shadow_buffer = NULL; + shm->imp.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->imp.shadow_buffer = teec_paged_aligned_alloc(s); + if (!shm->imp.shadow_buffer) + return TEEC_ERROR_OUT_OF_MEMORY; + fd = teec_shm_register(ctx->imp.fd, shm->imp.shadow_buffer, s, + &shm->imp.id); + if (fd >= 0) { + shm->imp.registered_fd = fd; + shm->imp.flags = SHM_FLAG_SHADOW_BUFFER_ALLOCED; + goto out; + } + + if (errno == ENOMEM) + res = TEEC_ERROR_OUT_OF_MEMORY; + else + res = TEEC_ERROR_GENERIC; + free(shm->imp.shadow_buffer); + shm->imp.shadow_buffer = NULL; + return res; + } else { + fd = teec_shm_alloc(ctx->imp.fd, s, &shm->imp.id); + if (fd < 0) + return TEEC_ERROR_OUT_OF_MEMORY; + + shm->imp.shadow_buffer = mmap(NULL, s, PROT_READ | PROT_WRITE, + MAP_SHARED, fd, 0); + close(fd); + if (shm->imp.shadow_buffer == (void *)MAP_FAILED) { + shm->imp.id = -1; + return TEEC_ERROR_OUT_OF_MEMORY; + } + shm->imp.registered_fd = -1; + shm->imp.flags = 0; + } + +out: + shm->imp.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->imp.fd, TEE_IOC_SHM_REGISTER_FD, &data); + if (rfd < 0) + return TEEC_ERROR_BAD_PARAMETERS; + + shm->buffer = NULL; + shm->imp.shadow_buffer = NULL; + shm->imp.registered_fd = rfd; + shm->imp.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->imp.reg_mem) { + shm->buffer = teec_paged_aligned_alloc(s); + if (!shm->buffer) + return TEEC_ERROR_OUT_OF_MEMORY; + + fd = teec_shm_register(ctx->imp.fd, shm->buffer, s, &shm->imp.id); + if (fd < 0) { + free(shm->buffer); + shm->buffer = NULL; + return TEEC_ERROR_OUT_OF_MEMORY; + } + shm->imp.registered_fd = fd; + } else { + fd = teec_shm_alloc(ctx->imp.fd, s, &shm->imp.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->imp.id = -1; + return TEEC_ERROR_OUT_OF_MEMORY; + } + shm->imp.registered_fd = -1; + } + + shm->imp.shadow_buffer = NULL; + shm->imp.alloced_size = s; + shm->imp.flags = SHM_FLAG_BUFFER_ALLOCED; + return TEEC_SUCCESS; +} + +void TEEC_ReleaseSharedMemory(TEEC_SharedMemory *shm) +{ + if (!shm || shm->imp.id == -1) + return; + + if (shm->imp.shadow_buffer) { + if (shm->imp.registered_fd >= 0) { + if (shm->imp.flags & + SHM_FLAG_SHADOW_BUFFER_ALLOCED) + free(shm->imp.shadow_buffer); + close(shm->imp.registered_fd); + } else { + munmap(shm->imp.shadow_buffer, shm->imp.alloced_size); + } + } else if (shm->buffer) { + if (shm->imp.registered_fd >= 0) { + if (shm->imp.flags & SHM_FLAG_BUFFER_ALLOCED) + free(shm->buffer); + close(shm->imp.registered_fd); + } else { + munmap(shm->buffer, shm->imp.alloced_size); + } + } else if (shm->imp.registered_fd >= 0) { + close(shm->imp.registered_fd); + } + + shm->imp.id = -1; + shm->imp.shadow_buffer = NULL; + shm->buffer = NULL; + shm->imp.registered_fd = -1; + shm->imp.flags = 0; +} 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/libteec/teec.pc.in b/optee/optee_client/libteec/teec.pc.in new file mode 100644 index 0000000..6bd6fc1 --- /dev/null +++ b/optee/optee_client/libteec/teec.pc.in @@ -0,0 +1,13 @@ +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@ diff --git a/optee/optee_client/optee_client.device.mk b/optee/optee_client/optee_client.device.mk new file mode 100644 index 0000000..709d8cf --- /dev/null +++ b/optee/optee_client/optee_client.device.mk @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (C) 2024 The Android Open Source Project + +# Enable TEE supplicant plugin support +$(call soong_config_set,optee_client,cfg_tee_supp_plugins,true) + +# Enable Global Platform Sockets support +$(call soong_config_set,optee_client,cfg_gp_sockets,true) + +# Enable dumping gprof data +$(call soong_config_set,optee_client,cfg_ta_gprof_support,true) + +# Enable dumping ftrace data +$(call soong_config_set,optee_client,cfg_ftrace_support,true) + +# Emulate RPMB +$(call soong_config_set,optee_client,rpmb_emu,true) diff --git a/optee/optee_client/prebuilt/include/uuid.h b/optee/optee_client/prebuilt/include/uuid.h new file mode 100644 index 0000000..e791abf --- /dev/null +++ b/optee/optee_client/prebuilt/include/uuid.h @@ -0,0 +1,123 @@ +/* + * Public include file for the UUID library + * + * Copyright (C) 1996, 1997, 1998 Theodore Ts'o. + * + * %Begin-Header% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce 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, ALL OF + * WHICH ARE HEREBY 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 NOT ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * %End-Header% + */ + +#ifndef _UL_LIBUUID_UUID_H +#define _UL_LIBUUID_UUID_H + +#include +#ifndef _WIN32 +#include +#endif +#include + +typedef unsigned char uuid_t[16]; + +/* UUID Variant definitions */ +#define UUID_VARIANT_NCS 0 +#define UUID_VARIANT_DCE 1 +#define UUID_VARIANT_MICROSOFT 2 +#define UUID_VARIANT_OTHER 3 + +#define UUID_VARIANT_SHIFT 5 +#define UUID_VARIANT_MASK 0x7 + +/* UUID Type definitions */ +#define UUID_TYPE_DCE_NIL 0 +#define UUID_TYPE_DCE_TIME 1 +#define UUID_TYPE_DCE_SECURITY 2 +#define UUID_TYPE_DCE_MD5 3 +#define UUID_TYPE_DCE_RANDOM 4 +#define UUID_TYPE_DCE_SHA1 5 + +#define UUID_TYPE_SHIFT 4 +#define UUID_TYPE_MASK 0xf + +#define UUID_STR_LEN 37 + +/* Allow UUID constants to be defined */ +#ifdef __GNUC__ +#define UUID_DEFINE(name,u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15) \ + static const uuid_t name __attribute__ ((unused)) = {u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15} +#else +#define UUID_DEFINE(name,u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15) \ + static const uuid_t name = {u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15} +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* clear.c */ +extern void uuid_clear(uuid_t uu); + +/* compare.c */ +extern int uuid_compare(const uuid_t uu1, const uuid_t uu2); + +/* copy.c */ +extern void uuid_copy(uuid_t dst, const uuid_t src); + +/* gen_uuid.c */ +extern void uuid_generate(uuid_t out); +extern void uuid_generate_random(uuid_t out); +extern void uuid_generate_time(uuid_t out); +extern int uuid_generate_time_safe(uuid_t out); + +extern void uuid_generate_md5(uuid_t out, const uuid_t ns, const char *name, size_t len); +extern void uuid_generate_sha1(uuid_t out, const uuid_t ns, const char *name, size_t len); + +/* isnull.c */ +extern int uuid_is_null(const uuid_t uu); + +/* parse.c */ +extern int uuid_parse(const char *in, uuid_t uu); +extern int uuid_parse_range(const char *in_start, const char *in_end, uuid_t uu); + +/* unparse.c */ +extern void uuid_unparse(const uuid_t uu, char *out); +extern void uuid_unparse_lower(const uuid_t uu, char *out); +extern void uuid_unparse_upper(const uuid_t uu, char *out); + +/* uuid_time.c */ +extern time_t uuid_time(const uuid_t uu, struct timeval *ret_tv); +extern int uuid_type(const uuid_t uu); +extern int uuid_variant(const uuid_t uu); + +/* predefined.c */ +extern const uuid_t *uuid_get_template(const char *alias); + +#ifdef __cplusplus +} +#endif + +#endif /* _UL_LIBUUID_UUID_H */ diff --git a/optee/optee_client/prebuilt/libuuid.a b/optee/optee_client/prebuilt/libuuid.a new file mode 100644 index 0000000000000000000000000000000000000000..38f7f486a883bf74be22fb81fba4885e5e2afc99 GIT binary patch literal 60704 zcmd^o4Rl>cb?)3NCw6QT6k8CNnEKc;#5jp9|HP5Nk6bx_Ms|p~Hce>KO0p#XU|EtS znb^dyxq&lr7dUXQfvN=aAKLf;E%Xk%WC z-uKPf``o#sJJMAwFKFLr>7F^??Ad$Io;fpf=I_j2-qh8+>HU)zM#XN?vSqckHCI$G zS`tOoHpu;rqGh#7BxyhJ6zOVSdH!{ZkKlX?*#sAy4Z*FO5ZfkAoGO@Q~YiCnetKM|(Gz|?l zU}I~0YgbcGYeUcGtr9#M)X?3up>}l;*ik{ZC zwubJG?On}~(bjOoHCKF~eKRCj?}s~E$UMGT2NvBMI=Wz48+hI3_9hsltzqrTx18Vfp-VxN?E6zjz(_KTt=w!kl{u3oluX%sD5x*fL=STY|9H?0NcYk}nz`+aCFv0v{s1!j($rKt>fxl9&0-Stz zo&`!-ihR!X$zdzHiKc2;2uoOEZ1>_htI7GG+^Gz0SQ~j}DVDxoMXhQx&1TxD?lcTQWQIw`X=H z^v=D~!{(NL7U>&6e}_Zw+$;Utgnl~dn?e6chu*nYdgQs~kMdN-^rYsYT|+uiS?u{f z(hNK7MVjZUJq9nyoT`9LR+x&PRUkZL(`EMND^l}M-~NNL+CA_}>g`b5x0;2c?))|T zCm%R3{h`qtKa!u#wl8iU{1VHQu*~~4t}$_AedcW+pDDNPvvvXYyZA5F_Ob3Og)a}_ zR|jyT4`XpFD!uTA2HTD`G;i9{uyK1+mo&1{cSS4PytNY@>;ln-rp;}TRM728n9^-? zwU1Ea;Y<%5+vvDI5#MLx%P@R~WD)7#A~d{c-RH}lEA+nHMuH@HvitaA10!=b)Gx$#4N1C1Z4V7aP%y@vV*hm{}@U*S;S;E2S3 zvwee2l2O_Rp#8_vH+Wg(Z<6a+`vz+y|IxS=Io~XyzClj(AH8qTxije)pwS<#Z?I^| zvUtEFD!*^AJ6%XZ#(FcTqb8f7r_7J@6U`~KgQtdOnZEqQ%&Gizb1Gkf>xJeN>ZPiI z3p1yp31~ZUpP!yNm4<&1G_y^n7PhF(&&u?nfw~~i`0&qKZnkax_0T%LFY+HU_LTF^ zNVT+nciT?pzm@@8)7G6|{Smj~vgs-QVIGaW&2)_9uq*W*8TT*!k`PBK^_~~E2j>Rf z7l*g8}!|Su|jpO%e>k&rG zFUiLxj<1)#Cn?Ko;h{}43dq%ePh&jhk;d2Ovy^PhLKK}OSJvfYc~A4-(=AW@2s^zs zp}JV#(?+YyF*<6;UbQ|RwJu&-T^qlsm0uShUy`URcFv$bH`NSPO#AWa+fDMW2CCi3 zd)ifL`<^y*5ys{4j#Y>M4E{m0H-9PWUA&*+J!;!W^Z^sq#=*T!9(v2-s{l5SLLtH^yL?tzM)G@-!*I#@UE1< zB-a-ib1&-sQvLP`%+TrtKY0(#E$02RbHE#6W+mDaq$Ph*<`iW9qLDcKNN+85 zsH>2Bv^9!7nigzQ0ZS=1wSYC@{nYZREMQMEP2^uy!1_stu}#X)!OwTX0njAxz+#gK zc1FEh#kLI3mA&RKfxUXs=D{AY1#A<)8?XAeA=h@ z(xhBAmFn#(@NwUZ@!o7uW|05P*8&a78)W5>Pl~0DrP&SoJ^70Ce9|NRC{D3{z>&X+ zuGa2P!tM@MBm?6T(8Uexz07RuMOh(k?<-Np zV5iEMM(tJn^SuR zF2?itoZ0jD6%~)aRFQuC#fsG9e0CT=w&l6>@0|smpJaKz5_VpWZopDAEyb(I0qstd zOZMf8Y>u*7j7>nf!dQ+IFY&`RalSbDY9_?kY+y*^35`dc3jWN_Qu-hdL-eOo6U>h_ zK6FRDCeIdZBJuVPKzF5~ZdV!ev#+Ael)|asz!HZZdXxU6alUI_>@?`BhU}-ZkYCm& z&}mQp?rRTaCYVEWpkFDutd~m39q`Kbthr{}4JdQZ3=LhVa#$8&2R2()KiHwqEmx)V zpe)qgkDJ&2=sC22_ag4SZl05;*_C-PV%>Zx>R8SH;}4uL(|ccycA1AUes@a4>BmU! ziKz2WUd?>#saG@0@~>)G9^-$|;TOG=QSR(mpndMQUGCgN{|`Y2wQt|-c=#hpkA|g? zAL^%$gU{ZV{r4YtW=+o+vx@qI57QR&L77ebh?_^;e#DJ- zMGqUqO(Sk3aaW}99PUbA6oC)yxf^`;z;E*tJW#eAJ)qP2hd*`V`~Ui_S63YW>8tCT zUw$>cYX$VlK4{*!|`4aY-j$eOdo0Du*|8!D@Pi`{qJ@Rcj%LN=beRi z8*S8d5N);bx(%vQVaUUshLG} zH!;f>_RQM!W2`zIVH_UUJoI}J&)+HVXP+aF@otm3U@_~ld^7BDamKa@`CG)lt8%Ta z<1T{?+eTEyv<+q_<$(X5{Ey6@IVgLmao;41cZ@39lKDtkIZ4aZub z589%>{1WMR{$KPv(Jv^v&^^D%hZ zw%h-vmXG45WpYf-bvTIb(qT@vtp)LF@Ea3X*MK}4?!aS|1u_s)DT3Uw&Ip)}rPwi# zy7P1A)$QM%I&gm~eaGMa9moGTrpGxix<(F&*PY+F|NH}QsrX6CP9|0Xx|M-&cKi?P zY_3H_`o$C`g9ZTcGW#bTn3(=xJO|0}z4)ig@JH6?NU)86lsH_(9|^xsrZ5@*dE#&? zm+O13b;4hZgU!-de&hbB2d1P~738B)u&#x_80X!8?tyb|a^l-~2Mx>IMEU9 z3!H-s0p3I4gh()6-i80PgX@?X!%B@w$NbM>aFJVtJMz)^wu}LLAO2I$$f#=e0gK~K zRMIiQ-xFNN{Ls&^j!z-eTPgJV9CQdC39kI_08V{2anKOXmMvT##6S7yJg3q>D)>C% zqhrZ`2Aq7JmM1)ed%D;Tq5R?lR_tQ>N%rNxID~fA)E9@8nn(X3NHpy(^-lx%U;zKe z0DcA1UyA?#3DEyr0RMFWe`|pMg#r9+0eofvzc_%i4k(qb_XY5}0REu>-WtHW0{F)R z_?-d#-T?jpaL(=ACFMMWd%8aj(C-!c39{HAved?WUGTYr>+|wM!83x>j&ylkOWBhz ztJJ556%<@cd@(;4{G{NvE=Jg|1Ya$S6SS_MiU+?G{|f{7+yGt;ocd(g2*TMq9M`J@ z^fw0ZKM3F^8T@ZHon0Lp8#cFptf6~TL;Kc-_1iaaxg{1|+7-neEv*fkTdd!95)4*@ zV43!YmIcd}*3{@7Z))RSL_>G$Hr&=$o3^Iz9tK=#(1Y0C-NQAMykBOy+4YV_7ZL2<>RrKUZW%bO*-;@Mdtj-|}F+uU5VI%T6>!qSbN3>JsV8qv)i z%{^_w}5kNS66!nR&6&o^=yWM z8<2ji_ujy+5<)jaP;G6)hVJI3_6=MKJ#3LR?8kN79UEGjcA5>HU7Oo`Hkb_?+O~IZ zG8=ljwzq>Z_}$jE8JF-n_`*W+WIa3Cj=uceU4yPsJzLsU?;|e!mId2fe5*WAP@1qZ zK3@Ah+EQ;@e3NH_>vrA|L-w~y{9L!=;!6eR`XA1ds=HM@#PwMxlymTRil3L=4$ie! z>Yfn~`NVBp47}jrE+1WALi$K(cwxOnN8IKAYydwgxNnCS1o!Rmn!{&yEXw{yc&_Pu zKCDmZd_FoSI34`l)_=Lsv%PZhb%Oi!HwWn31g9P5#46a|oWn<|dW+xX@Nw~b96lF2 zd~{8Rug_kGkE?&L!)K1e=P|*3J_iGQjs@tS2+%+6&@)|;$bQD5ck$zb({6JeJx@A( zY+n!IbT2r3T>PZ~{mTLR*ByG-Zf`jBEPOqYw_`yBS@6+a?4?aT=Wbw>kyjs^HU6QF-KK!4Js*Yv*N(JP)8oO)iW zO5*xbfX~YTKCcDnUk}h%%20wYcZT3vZ>XL#1=o5*@#+Bm(g6L+0R8F!{jDCo<}cQu zSf~0Zz9T@tD?opjN3Z4i9*Uq+mSN!Jz z`d0$Lwg838_#N3ZqaT#sJyYL8y?WvNH6`0@aKCP2T^qu27b+M`#z z#i3_^X^q%olSA*~or2SDmpOLZ;qb9dpV)tw!^g$%a`<3RT;lF=__+CdpToz+_c?qP zBwUPn%;Dq8J?QXp@h2R5rgw+%>UZc}{As~yhlP&ZXB<8*|7RUOF8;j3$F;-B0G}5E zd|q<+xaIj}hmUKwpF4b9{B?)VJSSZd6A!1)mzL+bg6s38_;SJhafXcG{y4+Ug43R} zV^Q{ZZ-CFf0H1?`tDZXVaaeHGQ}HJ}`gu}r`#pNapAXQV4A8$IIMe0!hw}kGF9rC# z7NCDUKyMe0JNc#Qogni%z8y9Ru6EP(wt4i5-zPZJ#knwb`vmv%{Sm?ad_U^&ar6Ck z2d`G<3F>#$MxNo<4g8O#MIDA|^ zTLOGG1^Dc8_|!W3+~?r$b@0am_z?%^+^)K(9o#KHl``+*m!BDe`*xTqxNnE04j2N@+wQiO>9FT#YZ;YW4ADgUs|_z+X6dzh`sLBH_np_sP#YK&GF&58$vb zqR4s4F%(lO{-z~yw5Foi!|k`Zn+JsHPP#JoHD9@CalDkS{JnHX90fC0A3gJ=u#Ow> zZahWtx>i}kJv5X)#I?@cuU53K6>CoO7k=p-m`I&gw3fDvwa;ZN`Ag<}Lu>wemu~00gYXe^_c>d;0OR~~smFI=0ACisjTFwJ z9n*TGoqM`RynZ5h?1ywE?VPi8yCJclBilR|*M24Y4jPyAEBOP*zJp7@I)?4swTrh1 zPCn9Ivq-4#F!na{x2vtx{Fh|gdR6_rhT2M)|QY*40S; ztZf?Y&tXoDuQ>JbWdlmqh^`TZSs!V8$#9JyYU>(>>GdRboS*(sTc>A$e8h=MuOFZ5 zkqRwcIc?ptnz6QZI$uor8UEmRDr$?UG_K0x*2KN(Sk2Lox z&qmt@{cE|u$LyN4HVMbR>Jh`S7dsdZUMcXU9Lt-sv8O2EjeXa_xYP}MwTr?Tf2tFI zrWfw(KEn%V{7NVOTrb>@&wWYxFh}2R=KEiSu` zaR!O(6H)>Dy($sdG*TM53!H@0zmbl=}&V*NyxXP&J_DLNGENH^J!{_Vb`Z>sV~zl=iJz|6HBw- zb7ih?;L_BdIh!I@1Bne(KH49fw~1|;&sApI6Omf9oV(_FGbHW%2If10RLD3 z|DynYPXIUe^nM&T7u+agx3X9&?lft`9+Cng9|agb&eG7(%(ML))^mr+@ZBank-THO z`^^EDMRE`;bgsfboj*RZGKMWK(>oT~Bsj-kWO&;mZGv+g$HiX}ocvw;ua+W4ob9E$ zMhBm!Ag-Gn+@-(A!CiWHZ-q;LG(g|);4XdM!Cn5`+ePQ=e~t7peEenyclo$`A6&V* z*MNMm2|RH}gpY6kqk{YPf7X$!c}-@azWs8Mq;pdGeEoYL7t_5DYDmB43-$S{W$xg0 z$?vg_i_MfitIE}@u+!UMpFh(0UIg^LirgaHk)*l^HAdq{948tU_BRDK}7!l6FD z#=lt!hsSNLQU6L$Hn%E{+fU6^H0UU%GY*1G%luVjvw;$SGy_9XSbB8ZWciw zQ9`-;@#F1wg--uyef~vP)+`-spZ|47!Hm@-+~?Q+zU}X!-){SR93SKO)vYtuvX7WX zUvN;uA}npPV_0Vz&UXm%VE+*^-jsayo59DP({rXgrsABDGv!eU9?%CHRO0b5@Pqls zG&aWU()QEso5Jo%-}EjPDjgqd_|5k{`K%3pJGLO66{%R`Tl;&q=ESUBAc1Y3+Rzbe zj68frBV^7w_Sp1mU5`ApY?J?g7$;M^sjbRwGdD>+t)*JF8s1`fzBR ztlapaHdEtADp;;6U$3Dy^Ccw+#8)`fX1*-(^_^1b)qZ*(YBO^s>_3)qvPk-jk?6ta znExu@%~z*MQMHV=`4=Zh?D5SKYBROXE~m|ON6JQPGZ!yiI_7b*l}P z=h$=YYV!**R)X=hC?1Qd<=B)RW8zrV8`nHHfHUZ4BaCrvTa37~3un!9Ug&`lX&~Q@ zvp{F73(ljz;a3=E0Y8ib)N-6_2xBfhlioc~j%kJ|xUG860NORq{X8+k`E#Y{kBpK2 zF^|4_(c&dbuUK|vO>NWq=9bnCh5Nb{S6_4Ob#G>_iSI{RwqJoCZE5D?c==_!q5V&L zmGhkHrHN(u8q&j+3XgzyG7zp*cpOstm(R@EoWo)}R_aV8jQ3f|_Tv4NIwL8jKgXkt z*YT%J0k0H_xb8hCX^$1Jv*Ap2vAYJh?wL)mIKid9BNyv)=4TJx0683IQhC)Pw^4Ad zBNgu!T<75xw|xv&R-uugO|3gxHgDYA(=A_mEZoPRdBl+_c3fz~R{4k{J1FIU7!paa zj%)kb7O0ybIQIg$c(q4gDG`=>^olon^vb`*qgR~I44sZM#CL`D|11KS zRT(9aYfh@nM!DDim&Vt2iu#mNRnI(8JFuQ-f6I>_8u!pM2y%$yIzRoPK3rb(Z*n8U z@5i@w8c!sWp^s7faLcY7^V(P4?@CoN{K0R$9%%G)aCuIxyY4mraAqgxo$_D8+~9JY z9ei2kw1{IL>_e@J&y{6g%Is=<4*28zb_2hafG^3O=)eCvul8R1!mGVM9C{UD=(ojT zy*J%+BJ<}@yxRN46R+m~=2tiyyB}wD-}D^&dW;(iPve~OG|nm4GqVT&A^l$;edrb^IrvN^;E9dBKVyvCo;$DRSP#om134%~;n)zYlyW zMK|}dTKFqpn=in4o+st@N|J4UFk+#yD;jFD-|KcK=r#`foT3|Qr|)7`!#?j#DT%KB z8tEz<8lUgwj$c&^&T%b{jjPkXq0eWMq^ky3mro=(`NVl1bJFi9`g}40KDRo2Tzz!> z&F8Ztz-PC^$JOVs;69%t0Y2_|Y_2}@q~Z1XTqd}0A9rrh)hE;!UM?A-eOoPOw|cmi zv$6Mif4kPM>$!1B`BRTvLvwU`ZjR>PSm)^U95_#$k>ZfRm%+#WlRxHFZhYhq?I zHGZUkTvfhaL*tD{rM!93hv^?0Z#*XPcX$l6uc&Z6Jf-@o&qx)%QV7R7M^`Nd%}GMp z*VXZ|H`Q_Uh@FKRcv5A{_m<;8cj@y5=sR*W=lZf|XgJFBDiRj*jGY^-y1 z2c70HV-=6b8{P3Yj<>N-*UNE3_|c!O#r?LXxUX{p<&;%DtG{?%cDx=-*09-QE%#t- zc2t^oltBZVmgJMSx{Ry?iXGzSPUv?jnA|OYdaQE)*Dm;R?x^X%@%id!aDRb!Kh3+Z za_?K(IRb;GwyVuvJ8=9g-Ht1&?PIrNf%S}f=zOJ(h4+<@XU&8izni*f>MRoh)3W#y z!(|-sw%>w27S$;=E*G!eDU837j*iblsc|`!Ba3VL^?JGB5w3KKvu{K`)fO$_tScB& z%9R?gi}f78@j8`j^9eT%_*b1Z%wC;`8lAEh^TDRAt!uG7zO~_+53Y6YKAc_c+}-$r zYn;2AS*CP=jt3w2v~KNeI$MSmA~7E{?ysxVHW5OEIt1X&tM4 z6kjbK<)ipI@hH8<*LMY_SG-Z^eYx?|6rcS8=dk|T-y?ryCxeAPia#Q_(rY?hWom`(tudxr+A-?(=z8aMh<;?vKk= z`6xb9aP9NStr>gY?zeM1Q=dmo*97&*HPpwm9S_iGpPT&y)-IDI-VC{h#xv)VxP-gy4KHo zKqe#lH}S@Cete$ezP)F2Tem-+xg?4fUs1hiQMAO)K`*MVUbb{;6fIpQpT!-+H_B%? z3v4r17wsd;cp1Lg26#8LF51hFZ_oBM9)CF7*nAM*1MIcm12ns)t<7^hlY27);rKRR zc97pam2U-d{L}nreDez5N8}hL$Nf_1$3Z5)V>(}D50)`rmh8#Yy&=&3Md&ezy&wZv zC)GbE=3CfH^4<8`P5dt1Me#lgj$;m9l;J*%z6`&K$nQkryNGk9_J1)09V2{Cka{s3 z{wdnu)bT~tm-|4tw}EMK(}eK7`HN#&c6<@vkV|3gm*a-uS8sVkSL?T9y(xBo_PRW{ zhRo6-oOCF>(=fimRJ(niBAW4twxCvA(FCGt*3O!hfAf)nlLU^klCu${*}v z_c^gFa&F-&d^h&Xr?F;4wE`S?*U%2Im zJ>t80?};|x0~hwg8D$KpSCSc=`>w`*)C`N39uH@Djf7Y8D(fcQH61rgxb0iZyWWSK zH6J@9{CFJSej}{Q3EwB-G=RP(fUS|bu!h5R0zF&JBb^IJw^-VM}U!*SHop=&F+-rM{DRwH<|u(EcRIHlfoBOAuI zli{w^J7;9c&itM8TJT|h`7X5Qs0oCn=(_^=$ANP`LHo|OJOX=vfc`T9{0jm6Kmh+r z0RI|rJFg-gwcWU<`!@bdrK>-H|0Qtp(Yb2-902=Y0eZAOCHcP+!2cCE`Rlp%$#Ycb zq=i=F;AMWt_U^XU*3Lq$WSS9gi+rgEd#(zf0gC5q+MC)t;wWyIovrEKi4Xm>wHXS= zmvDL-+P80A-`Yjqg^&E;rZfIn626yXy5p+QM(NmUBW-9g_8UVRn%nVNqEa6X8urw$ z!F@iD2~Iwot5c`-9&t8Q>RuBM@wY38EBVs-a&_Lxmx~UNb>wql?6to)JNOI-Z*=hA zad7k-tRo+cl_qYVgS-5XIk>C;Nx^;n-S7Ii_J7UcpTSM(U(cw1bHFz@yY-m1#n%L?(^B< z&~yAjU9W>j3gTKNO&7i|*FK@wd{JEU!XE=#F0vHY_VQK_e@X6l zdAPQtk9as5W$T{saIKeL@NiAff0Qw)UdabZCi+svj%9*arWiIm&^f2uE#-u_C=$cQ zB-rmEE@be5l%<0;O56fs}_8j1h163W%rpD)9u@^4Z+>0k~@Jmw$c zYJ6=2O37xFNXCR#O2)8mWj*c34~IGXNa#v0Hw~u?=EX7~kRhKj|PVzJeFW zJ$AiwZNh_LJO^Y~#aeV!?6>Xh`5$=yk0!>vQanckG!fVPacpT4##Q3`Rn(1RZoH@b zK^a@YxXR=9EEK+PI)eITz6NIew_5AWqd1hy0PPWiA;>;aBM{5 zr6=KBPx+2}ke?05x7@)i9{WiZ#;M*g+Ya*mpLU}jNY7wJ%IZ&DPT#I$Q^U_*WBw$z zJ*We3%}qnusU4UI8^$!NbiE(PaaLmNggEV#;X_=3PAQ`D7a1zx(%QGynXpu4Q-*ezM{7(|?kF+mzmPRee9`?^Jr6 zF=xOZg*f0drSYQAX3brX zbuC4lz3<;UeQ$dDl*aVi>vM?nq{gW(!~vfv{eSyVw)e_oU1*P{d~^QirhhYCHDy>@ zU~|!XIlFI?TgvmrC%R8E&YW!OiO0&C$gq%l(ZZ##9>+*7o*&K<9j2gC0~eR)3WWJ zZ1g{mj+{5I6yh*F(FBy6WrvE=!{?we@Eq9m9KI{t|CE%q_W0T1bC7eNgT{g!rpIjh zeAY}l7N_SA<7bD@L9hE9IJRbbqWXKY{Xddtr#^mm_#E^j4tN$l(~p8a^UHnN{$<~Z z)3P{zZic00O+l|G5vO;`C$jk;NIeiri&JJGcS_@DK9S9>>>W8Rj-BshT8=-GjjFyK z=S?UrnSyRikJB%3tGu!*c?~a_FTpZ`*b6*RW)5Vd|9vDbXTMi?W*$}gBL)88fqLe?Z0|R|7N=oF;dyyd>GK78 z@R*WI-JR`yLh9vr7oL|UrLQc|gU6KI%Kh2?FB}c)pDECT$CT)o4`usrKNQyA%LCK) z>1^ZQNSP|7e{X?5^*5jWLN@<5e-W3bQu-e+&{O~ZllNyEr++1^zth%dhVIHn>!htO zW&7#^?>oV}xAIdcbKeTvzOg`0-FtgKnKgTQ!@BP-&{OwlBHEqzemkste}TS<{FgtN zZT#sIVcWk_pr`)kOZR6puYEbJe^j8i`ak=bZ0>W?M-kiSE0)YheLf%jit6Sk!9TYW z_WUo>W_&a*`}vBc^HG=22fvuUvmm1haq_QzDVu4P{>ksh#r#IZ0na#2z7Xe5 z#_72$o9mMP$#wBFkgr%aKZiKr8OK>ui1R4oL=*RB8y}G8U_tyG3`>h+U&x-)SaWZ- z@vDd9{0OC|x*!L#r(_;@D4QFQ{z)i3y@fb;B2Mr92eSFo-;47ll%C2$9GjkR-J8uF zITDwxP(|g^4Z01k@B7SB<>4^$)n4ZR) zzL?Gb{#QoMpWTHxHa%Tm%=ULmKSk4H-_bIC)Sd4$_FaltCD)Y1?=Z*0F7OPPqy%h&m?J0zc+#D{sOW%uIN7 zZ0s>83Ea*Fr#HrPxeQ-}e>yuSp=b2m5QonL-f2UPS;vhb2!HV0z30?@Zo=m)DzX*N zKlj%^k)a-;8h)YJvpEMGFOjE|;jYvku6Stl%=d879Cofz#9F(<&wL=R_tx&f-i3e7 zJ9rbvF;voDBLivH&cK!nK1l`_bTWt+DTyw<-+BaiMzV&{%6W>p2 zHFB_ajIF~&UiXHMuB}3I-RAbDHj;F=_81H$KoA_~5_BGp_csUdP6wxL)E#timruWg zyYz23xJ!@r!aC~XEHg9v9Ngt|*uh=;X9IYZ*q{7eK1&_k<-=!(PUk%0yTZC@#kCx) z69UCGUtwzN6xVVv_Bo8-u02!xyh1ub(y5ow+(n~I97a+OI7UscKXx6OyEy5|Re8cr zZw;S2@|5gN@N(lXLJab(PGZI$jURcq%Gc|A5w3oh^z}0Jzfs~#aZXrh{Cx=$d(?gk z*Tcg+$tWP#92*n3M*C|F?aw+^<7+!Z-F?}Nvik!58k3X6vA*TMA3rqrP$~J(^tsNr z6~*{@NBX?z{}DGb{C@oIO-+m3$%kam)RNNcVHYh~A_p6mKliYbg+yG&UUh%}v7+^d z2-=ODKpz9^=dQw7Jl1*I^NU_Id*)2d97<0$hvrPJ!!?EL3S85;UX5$Tp?tj03g;i1 zKI`YWE7vCy=h!Rv|I?50*ZdOk%lyLt*5T!s*tv)L{H69fIk|ry$C`7~(~nG=mZ!fl zH{Cp9rXd~k^X~&6V6!nEYR9D8a?|OLmf)Rb%~!i3_y^*-gei8O1H8?o+;r+S06*9N zfxez`ah;spU**W8-<5e4WCF7?!P}IQiL_9*O()07DHC=XfM3#A&-n%`Gfr=P{%S`i z{jN-$ht6;-6TC~xL|Uv&+L?M$Cg)G!m-N+(O(!S!*E=%lcV%7=KESL@u9Ga4PUvoB zGM}jzWg>3};Ft8(i%lmd_p2P4^t&=wfe$b%6TC~xgbl4smNV)_nMm`9W#~pnCjG9= z8^H&dl?mP@Wx|G5ChW=lvoc33Lu(zG^t&?Gf)6k&lX+Fjwy>d<$!CRnl~aapa%9r) z%Df4DfLWQ~T~a3OX=RS34Bg_$q~Dc!3uFSbGQqo~OxV-P97`E$aAeZ&%4~p4U{>aM zmZ4@xCjG9=X2=9)WsYYV+UUrn-<7!$GJ#o{<5`BbI5O#XWp05?U{>aMmZ1(uCjG9= z4#)&%WsYYV>ULz(@5=0kOkh^#c$T5t9GUdHGH-)SU{>ZhmZ3q|j?dr!U%~kk6u(yGpJ|cZPdP zm|nLn9mn!C2%GYGv~q8hE7G0Fb=%XimMPFDeG}LUWu$%(w&b&D<*k(~(woS0+fuhY z^zPro*D-w5BcPr0t z%Rry>XOUJb54L09)ymWIigYIO+_n>ZOUi@pR-WG%0{yV^0^70QYUOP#q%)D{wwvHv zQXX`-^89`f=!caT*eeD=)Ae`>Qs69ffoz^4#`v zJjx5o2>Ys5UbkG4&P1NuR*pw`K^b8`)ylg~u1IGh&uu4>|0V5-e6sc|r@U;0Jd_zL zPs=INnaFe7NboHw5BX%}l~Z0|JN8elJT0e4XClvSAHlbzJmjmDS5A3>?aFQ!!MCJ5 zl@`5r_cKbITGxm8v-Dalnl!c(9Ga^F0~u z;rziHaj*5vXzig>esT|gA=~)k*URnC;2cWZ{!ShQ54Kr}eAu?^_R%R%Me>pF_W2Cg zKl7!XoID5~Y{L@yuyxt(CFE%RP$VB|v+~3B5xzkp=?4$?ffD&BV`aCWkW*4V>}lnP z>!O=||eE{BZjgE`MWbUm>St`e9EiKiuAh%il)W17*-Y zclsQ3+x&^&Tio^*a!Sfao?7{Dru=Pze3U^ef3)@&a!SfSlk(RA`C8ARu2nmrd<=h2 zJsaf@wl2GUJ{#rlHptg{Z^HK)%nZ%!HtlIGNtX9y>>h0*=^6A@>C=b`E2Ed`*S*XSwFZ1@=%7XoYC5Er~DMj zL%v#h;r^S>Th>C$@A)tD?8<-NFMUl$_w|`3grd1E4zIjkMeRG%5Ju^BTA+bY9*wb`AJ=?oCg<|B-Cn z$B%W{edXBej_>{1z3QnM&=>dIM_$&Rb?iOQbMBaH;pv}+u?Xy4xA|hRIE;JLk-p-6 z>yVYwee0A@ddepcci%e05I5O-4SD26I`&s)VNdrz;`};G!#n{W;P+M_|Lp#C(BgiT z&aHEg^Z@o5=PN26hwb+cf}XOmsJ&=kI?hL^vSFy#Nl%_d`__SD1>ptC*Svvq@t_m; z#;^SK(7GY$nFfy`_PwBk@pNN*LB4az7x8#+^^|?w0~HgnM?Th(c~RJ#Uii+;fPC99 zStlsxLGrtfILjyguH#gE%kl2`oVx+;2gg~H+@oM#`=jTWrWDr(vYb{#^Rf7I8uKrj z+y9RAOf!x6z*AUnxGAckAK@2hx#k}B^SGBD``q(?Zffzr$DWDEJ?oSM+hUDq)leYJ z(x6t6aNcO_8qPfG0NRH2 z1=hgYvl3Vi@XXxHFxrsetV^uDK{vp9MatGEX(!NG8?oGyme)0A56&U7-@#P512=|r z{;RU~m4HvOufW|~!gcO57zh_}(RJPVxzzs318=SP)Op+`!sWI#420XoAM8E(1KE4B zhWBvxJSyFL(p1=c(isPveaN_EZ%RuX9szPI2FXO{OWOp|AoWyIH zDP_1TwdW*0+v?2soN%v=yXVB_2QZX{B=1~}xcs=%1;o$%DusUlIQc7Io1efwEcheL ze>go~tQr1Nd_D@CeCEv~HNG$=rn(J&;{ETjaQr+f&?A>o(di z5XmMLHz5A_P+J3|>c$uPhwXeJ7;kmKHW=O%(!g`hiq0X6)wJihx%eyG%ma53=-oXk zuM6(;c|-6TpTF3XeB3=JJ(m>tyY{`$!MUbh-QfT}L+nrfE}t5~eLa^8?(2En;p6Us z`FQ}ZlKiDympzJz`Hu z9@>OrcM)z&?SVOdc}&-fP95EO_(xG5wudFO2kEFMmptgm!*!uONae<7{Z5|ME>rk5 ze&pdQU$3D(NY9t4e`pWVNr`{NlRwG3ug85U`*%u$b_hM~kN)K_`!gMqMM4>0?zuF+ rJ|hX8j9dPzeC^MWZ>c>*Yb5{gh}k5+YBvS=te1-avgkkB9;E*V|83AC literal 0 HcmV?d00001 diff --git a/optee/optee_client/prebuilt/uuid.pc b/optee/optee_client/prebuilt/uuid.pc new file mode 100644 index 0000000..f0ac383 --- /dev/null +++ b/optee/optee_client/prebuilt/uuid.pc @@ -0,0 +1,10 @@ +prefix=/prebuilt +exec_prefix=/prebuilt +libdir=${exec_prefix} +includedir=${prefix}/include + +Name: uuid +Description: UUID library +Version: 2.38 +Cflags: -I${includedir} +Libs: -L${libdir} -luuid 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..6b33522 --- /dev/null +++ b/optee/optee_client/tee-supplicant/CMakeLists.txt @@ -0,0 +1,115 @@ +project(tee-supplicant C) + +################################################################################ +# Configuration flags always included +################################################################################ +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(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 + PRIVATE ../libteec/src +) + +target_link_libraries(${PROJECT_NAME} + PRIVATE teec +) + +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..23a84cb --- /dev/null +++ b/optee/optee_client/tee-supplicant/Makefile @@ -0,0 +1,104 @@ +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}/../libteec/src \ + +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 +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..e4e4818 --- /dev/null +++ b/optee/optee_client/tee-supplicant/src/tee_supplicant.c @@ -0,0 +1,1032 @@ +/* + * 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 DEFAULT_TA_DIR "optee_armtz" + +#define RPC_BUF_SIZE (sizeof(struct tee_iocl_supp_send_arg) + \ + RPC_NUM_PARAMS * sizeof(struct tee_ioctl_param)) + +char **ta_path; + +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 = { +#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->imp.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(&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-l, --ta-path: TA load path\n"); + fprintf(stderr, "\t-t, --ta-dir: TAs dirname under %s [%s]" + " (deprecated, cannot be used with --ta-path)\n", + TEEC_LOAD_PATH, DEFAULT_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; +} + +static void set_ta_path(void) +{ + char *ta_path_str = NULL; + char *p = NULL; + char *saveptr = NULL; + char *new_path = NULL; + size_t n = 0; + const char *path = supplicant_params.ta_load_path; + int path_len = -1; + + if (!path) + path = TEEC_LOAD_PATH; + + 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 = calloc(n, sizeof(char *)); + if (!ta_path) + goto err; + + n = 0; + strcpy(ta_path_str, path); + p = ta_path_str; + + while ((new_path = strtok_r(p, ":", &saveptr))) { + if (!supplicant_params.ta_load_path) { + char full_path[PATH_MAX] = { 0 }; + + path_len = snprintf(full_path, PATH_MAX, "%s/%s", new_path, + supplicant_params.ta_dir); + if (path_len < 0 || path_len >= PATH_MAX) + goto err_path; + + ta_path[n++] = strdup(full_path); + } else { + path_len = strnlen(new_path, PATH_MAX); + if (path_len == PATH_MAX) + goto err_path; + + ta_path[n++] = strdup(new_path); + } + + p = NULL; + } + + free(ta_path_str); + + return; +err: + EMSG("out of memory"); + exit(EXIT_FAILURE); + +err_path: + EMSG("Path exceeds maximum path length"); + 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-path", required_argument, 0, 'l' }, + { "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:l: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 'l': + supplicant_params.ta_load_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); + } + } + + if (!supplicant_params.ta_dir && !supplicant_params.ta_load_path) { + supplicant_params.ta_dir = DEFAULT_TA_DIR; + } else if (supplicant_params.ta_dir && supplicant_params.ta_load_path) { + fprintf(stderr, "Cannot use --ta-path and --ta-dir at the same time\n"); + 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..58a2ef7 --- /dev/null +++ b/optee/optee_client/tee-supplicant/src/tee_supplicant.h @@ -0,0 +1,59 @@ +/* + * 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 *ta_load_path; + 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..d5f9fdf --- /dev/null +++ b/optee/optee_client/tee-supplicant/src/teec_ta_load.c @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#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: ta_load_path Where to load the TA from. The full path to the TA + * binary is @ta_load_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 *ta_load_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/%08x-%04x-%04x-%02x%02x%s%02x%02x%02x%02x%02x%02x.ta", + ta_load_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 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, 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..a10b171 --- /dev/null +++ b/optee/optee_client/tee-supplicant/src/teec_ta_load.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _TEEC_TA_LOAD_H +#define _TEEC_TA_LOAD_H +#include + +#define TA_BINARY_FOUND 0 +#define TA_BINARY_NOT_FOUND -1 + +/* NULL-terminated list of paths */ +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 TEEC_UUID *destination, void *ta, + size_t *ta_size); +#endif 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/.clang-format b/optee/optee_os/.clang-format new file mode 100644 index 0000000..4a78b29 --- /dev/null +++ b/optee/optee_os/.clang-format @@ -0,0 +1,150 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# clang-format configuration file. Intended for clang-format >= 11. +# +# This is not perfect, but should help in most cases. +# Please note that the maintainers have the last word if there's +# disagrement with this tool. +# +# For more information, see: +# https://clang.llvm.org/docs/ClangFormat.html +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html +# +--- +AccessModifierOffset: -4 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Left +AlignOperands: true +AlignTrailingComments: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: false +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Custom +BreakBeforeInheritanceComma: false +BreakBeforeTernaryOperators: false +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeComma +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: false +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 8 +ContinuationIndentWidth: 8 +Cpp11BracedListStyle: false +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: false + +# Taken from: +# find lib core -name "*.h" -path '*/include/*' -print0 | xargs -0 grep -E -h \ +# '^#define[[:blank:]]*[^[:blank:]]*(FOREACH|for_each)[^[:blank:]]' | \ +# sed \ +# -e "s,^#define[ \t]*\([^[:space:]]*for_each[^[:space:]]*\)(.*$, - '\1'," \ +# -e "s,^#define[ \t]*\([^[:space:]]*FOREACH[^[:space:]]*\)(.*$, - '\1'," | \ +# LC_ALL=C sort -u +ForEachMacros: + - 'CIRCLEQ_FOREACH' + - 'CIRCLEQ_FOREACH_REVERSE' + - 'LIST_FOREACH' + - 'LIST_FOREACH_SAFE' + - 'SCATTERED_ARRAY_FOREACH' + - 'SIMPLEQ_FOREACH' + - 'SLIST_FOREACH' + - 'SLIST_FOREACH_SAFE' + - 'STAILQ_FOREACH' + - 'STAILQ_FOREACH_SAFE' + - 'TAILQ_FOREACH' + - 'TAILQ_FOREACH_REVERSE' + - 'TAILQ_FOREACH_REVERSE_SAFE' + - 'TAILQ_FOREACH_SAFE' + - 'fdt_for_each_property_offset' + - 'fdt_for_each_subnode' + - 'for_each_dt_driver' + - 'for_each_early_ta' + - 'for_each_fip_sp' + - 'for_each_secure_partition' + +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '.*' + Priority: 1 +IncludeIsMainRegex: '(Test)?$' +IndentCaseLabels: false +IndentGotoLabels: false +IndentPPDirectives: None +IndentWidth: 8 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: false +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 8 +ObjCSpaceAfterProperty: true +ObjCSpaceBeforeProtocolList: true + +# Taken from git's rules +PenaltyBreakAssignment: 10 +PenaltyBreakBeforeFirstCallParameter: 30 +PenaltyBreakComment: 10 +PenaltyBreakFirstLessLess: 0 +PenaltyBreakString: 10 +PenaltyExcessCharacter: 100 +PenaltyReturnTypeOnItsOwnLine: 60 + +PointerAlignment: Right +ReflowComments: false +SortIncludes: false +SortUsingDeclarations: false +SpaceAfterCStyleCast: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatementsExceptForEachMacros +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: false +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp03 +TabWidth: 8 +UseTab: Always +... 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..62b9006 --- /dev/null +++ b/optee/optee_os/.github/workflows/ci.yml @@ -0,0 +1,455 @@ +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@v4 + 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@v4 + - shell: bash + run: | + # build task + set -e -v + export LC_ALL=C + export PATH=/usr/local/bin:$PATH # clang + 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 --depth 1 https://github.com/ARM-software/SCP-firmware.git -b v2.13.0 $HOME/scp-firmware || echo Nervermind; } + + ccache -s -v + download_plug_and_trust + download_scp_firmware + + export CROSS_COMPILE32="ccache arm-linux-gnueabihf-" + export CROSS_COMPILE64="ccache aarch64-linux-gnu-" + + _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 CFG_CORE_ASLR=n + _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_TRANSFER_LIST=y CFG_MAP_EXT_DT_SECURE=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 + _make PLATFORM=vexpress-qemu_armv8a CFG_CORE_SEL1_SPMC=y CFG_NS_VIRTUALIZATION=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 CFG_DRIVERS_CLK_PRINT_TREE=y CFG_DRIVERS_REGULATOR_PRINT_TREE=y + _make PLATFORM=stm32mp1-135F_DK COMPILER=clang + if [ -d $HOME/scp-firmware ]; then _make PLATFORM=stm32mp1-157C_DK2 CFG_SCMI_SCPFW=y CFG_SCP_FIRMWARE=$HOME/scp-firmware; fi + _make PLATFORM=stm32mp2 + _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-mx8dxmek + _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-sama5d2_xplained + _make PLATFORM=sam-sama5d27_som1_ek + _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=marvell-cn10ka + _make PLATFORM=marvell-cn10kb + _make PLATFORM=marvell-cnf10ka + _make PLATFORM=marvell-cnf10kb + _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 + _make PLATFORM=nuvoton + _make PLATFORM=d06 + _make PLATFORM=d06 CFG_HISILICON_ACC_V3=y + + export ARCH=riscv + unset CROSS_COMPILE32 + export CROSS_COMPILE64="ccache riscv64-linux-gnu-" + + _make PLATFORM=virt + + QEMUv7_check: + name: make check (QEMUv7) + runs-on: ubuntu-latest + container: jforissier/optee_os_ci:qemu_check + steps: + - name: Remove /__t/* + run: rm -rf /__t/* + - name: Restore build cache + uses: actions/cache@v3 + with: + path: /github/home/.cache/ccache + key: qemuv7_check-cache-${{ github.sha }} + restore-keys: | + qemuv7_check-cache- + - name: Checkout + uses: actions/checkout@v4 + - 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 + /root/get_optee.sh default ${TOP} + mv ${TOP}/optee_os ${TOP}/optee_os_old + ln -s ${WD} ${TOP}/optee_os + cd ${TOP}/build + + make -j$(nproc) check CFG_LOCKDEP=y CFG_LOCKDEP_RECORD_STACK=n CFG_IN_TREE_EARLY_TAS=pkcs11/fd02c9da-306c-48c7-a49c-bbd827ae86ee CFG_PKCS11_TA=y + + QEMUv8_check: + name: make check (QEMUv8) + runs-on: ubuntu-latest + container: jforissier/optee_os_ci:qemu_check + steps: + - name: Remove /__t/* + run: rm -rf /__t/* + - 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@v4 + - 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 + export CFG_ATTESTATION_PTA=y + export CFG_ATTESTATION_PTA_KEY_SIZE=1024 + OPTEE_OS_TO_TEST=$(pwd) + cd .. + TOP=$(pwd)/optee_repo_qemu_v8 + /root/get_optee.sh qemu_v8 ${TOP} + mv ${TOP}/optee_os ${TOP}/optee_os_old + ln -s ${OPTEE_OS_TO_TEST} ${TOP}/optee_os + cd ${TOP}/build + + make -j$(nproc) check + make -j$(nproc) check CFG_CRYPTO_WITH_CE82=y + # Rust is disabled because signature_verification-rs hangs with this OP-TEE configuration + make -j$(nproc) check CFG_FTRACE_SUPPORT=y CFG_SYSCALL_FTRACE=y XTEST_ARGS=regression_1001 RUST_ENABLE=n + make -j$(nproc) check CFG_PAN=y + make -j$(nproc) check CFG_WITH_PAGER=y + + QEMUv8_Xen_check: + name: make check (QEMUv8, Xen) + runs-on: ubuntu-latest + container: jforissier/optee_os_ci:qemu_check + steps: + - name: Remove /__t/* + run: rm -rf /__t/* + - 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@v4 + - 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 + OPTEE_OS_TO_TEST=$(pwd) + cd .. + TOP=$(pwd)/optee_repo_qemu_v8 + /root/get_optee.sh qemu_v8 ${TOP} + mv ${TOP}/optee_os ${TOP}/optee_os_old + ln -s ${OPTEE_OS_TO_TEST} ${TOP}/optee_os + cd ${TOP}/build + + make -j$(nproc) check XEN_BOOT=y + + QEMUv8_Hafnium_check: + name: make check (QEMUv8, Hafnium) + runs-on: ubuntu-latest + container: jforissier/optee_os_ci:qemu_check + steps: + - name: Remove /__t/* + run: rm -rf /__t/* + - name: Restore build cache + uses: actions/cache@v3 + with: + path: /github/home/.cache/ccache + key: qemuv8_hafnium_check-cache-${{ github.sha }} + restore-keys: | + qemuv8_hafnium_check-cache- + - name: Checkout + uses: actions/checkout@v4 + - 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 + OPTEE_OS_TO_TEST=$(pwd) + cd .. + TOP=$(pwd)/optee_repo_qemu_v8 + /root/get_optee.sh qemu_v8 ${TOP} + mv ${TOP}/optee_os ${TOP}/optee_os_old + ln -s ${OPTEE_OS_TO_TEST} ${TOP}/optee_os + cd ${TOP}/build + + make -j$(nproc) check SPMC_AT_EL=2 + + QEMUv8_check_BTI_MTE_PAC: + name: make check (QEMUv8, BTI+MTE+PAC) + runs-on: ubuntu-latest + container: jforissier/optee_os_ci:qemu_check + steps: + - name: Remove /__t/* + run: rm -rf /__t/* + - 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@v4 + - 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 + OPTEE_OS_TO_TEST=$(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.sh qemu_v8 ${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 ${OPTEE_OS_TO_TEST} ${TOP}/optee_os + cd ${TOP}/build + + # xtest 1031 is excluded because 1031.4 (C++ exception from shared library) fails with this cross-compiler + # Rust is disabled because of a link error in the examples with this toolchain + make -j$(nproc) CFG_CORE_BTI=y CFG_TA_BTI=y MEMTAG=y PAUTH=y RUST_ENABLE=n XTEST_ARGS="-x 1031" check 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..f9c936b --- /dev/null +++ b/optee/optee_os/CHANGELOG.md @@ -0,0 +1,1795 @@ +# OP-TEE - version 4.2.0 (2024-04-12) + +- 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_4_2_0], [commits][OP_TEE_optee_os_commits_4_2_0] and [pull requests][OP_TEE_optee_os_pr_4_2_0] + - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_4_2_0], [commits][OP_TEE_optee_client_commits_4_2_0] and [pull requests][OP_TEE_optee_client_pr_4_2_0] + - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_4_2_0], [commits][OP_TEE_optee_test_commits_4_2_0] and [pull requests][OP_TEE_optee_test_pr_4_2_0] + - OP-TEE/build: [release page][OP_TEE_build_release_4_2_0], [commits][OP_TEE_build_commits_4_2_0] and [pull requests][OP_TEE_build_pr_4_2_0] + - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_4_2_0], [commits][linaro_swg_optee_examples_commits_4_2_0] and [pull requests][linaro_swg_optee_examples_pr_4_2_0] + + +[OP_TEE_optee_os_release_4_2_0]: https://github.com/OP-TEE/optee_os/releases/tag/4.2.0 +[OP_TEE_optee_os_commits_4_2_0]: https://github.com/OP-TEE/optee_os/compare/4.1.0...4.2.0 +[OP_TEE_optee_os_pr_4_2_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2024-01-19..2024-04-12 + +[OP_TEE_optee_client_release_4_2_0]: https://github.com/OP-TEE/optee_client/releases/tag/4.2.0 +[OP_TEE_optee_client_commits_4_2_0]: https://github.com/OP-TEE/optee_client/compare/4.1.0...4.2.0 +[OP_TEE_optee_client_pr_4_2_0]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2024-01-19..2024-04-12 + +[OP_TEE_optee_test_release_4_2_0]: https://github.com/OP-TEE/optee_test/releases/tag/4.2.0 +[OP_TEE_optee_test_commits_4_2_0]: https://github.com/OP-TEE/optee_test/compare/4.1.0...4.2.0 +[OP_TEE_optee_test_pr_4_2_0]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2024-01-19..2024-04-12 + +[OP_TEE_build_release_4_2_0]: https://github.com/OP-TEE/build/releases/tag/4.2.0 +[OP_TEE_build_commits_4_2_0]: https://github.com/OP-TEE/build/compare/4.1.0...4.2.0 +[OP_TEE_build_pr_4_2_0]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2024-01-19..2024-04-12 + +[linaro_swg_optee_examples_release_4_2_0]: https://github.com/linaro-swg/optee_examples/releases/tag/4.2.0 +[linaro_swg_optee_examples_commits_4_2_0]: https://github.com/linaro-swg/optee_examples/compare/4.1.0...4.2.0 +[linaro_swg_optee_examples_pr_4_2_0]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2024-01-19..2024-04-12 + +# OP-TEE - version 4.1.0 (2024-01-19) + +- 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_4_1], [commits][OP_TEE_optee_os_commits_4_1] and [pull requests][OP_TEE_optee_os_pr_4_1] + - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_4_1], [commits][OP_TEE_optee_client_commits_4_1] and [pull requests][OP_TEE_optee_client_pr_4_1] + - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_4_1], [commits][OP_TEE_optee_test_commits_4_1] and [pull requests][OP_TEE_optee_test_pr_4_1] + - OP-TEE/build: [release page][OP_TEE_build_release_4_1], [commits][OP_TEE_build_commits_4_1] and [pull requests][OP_TEE_build_pr_4_1] + - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_4_1], [commits][linaro_swg_optee_examples_commits_4_1] and [pull requests][linaro_swg_optee_examples_pr_4_1] + + +[OP_TEE_optee_os_release_4_1]: https://github.com/OP-TEE/optee_os/releases/tag/4.1.0 +[OP_TEE_optee_os_commits_4_1]: https://github.com/OP-TEE/optee_os/compare/4.0.0...4.1.0 +[OP_TEE_optee_os_pr_4_1]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-10-20..2024-01-19 + +[OP_TEE_optee_client_release_4_1]: https://github.com/OP-TEE/optee_client/releases/tag/4.1.0 +[OP_TEE_optee_client_commits_4_1]: https://github.com/OP-TEE/optee_client/compare/4.0.0...4.1.0 +[OP_TEE_optee_client_pr_4_1]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-10-20..2024-01-19 + +[OP_TEE_optee_test_release_4_1]: https://github.com/OP-TEE/optee_test/releases/tag/4.1.0 +[OP_TEE_optee_test_commits_4_1]: https://github.com/OP-TEE/optee_test/compare/4.0.0...4.1.0 +[OP_TEE_optee_test_pr_4_1]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-10-20..2024-01-19 + +[OP_TEE_build_release_4_1]: https://github.com/OP-TEE/build/releases/tag/4.1.0 +[OP_TEE_build_commits_4_1]: https://github.com/OP-TEE/build/compare/4.0.0...4.1.0 +[OP_TEE_build_pr_4_1]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-10-20..2024-01-19 + +[linaro_swg_optee_examples_release_4_1]: https://github.com/linaro-swg/optee_examples/releases/tag/4.1.0 +[linaro_swg_optee_examples_commits_4_1]: https://github.com/linaro-swg/optee_examples/compare/4.0.0...4.1.0 +[linaro_swg_optee_examples_pr_4_1]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-10-20..2024-01-19 + +# OP-TEE - version 4.0.0 (2023-10-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_4_0], [commits][OP_TEE_optee_os_commits_4_0] and [pull requests][OP_TEE_optee_os_pr_4_0] + - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_4_0], [commits][OP_TEE_optee_client_commits_4_0] and [pull requests][OP_TEE_optee_client_pr_4_0] + - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_4_0], [commits][OP_TEE_optee_test_commits_4_0] and [pull requests][OP_TEE_optee_test_pr_4_0] + - OP-TEE/build: [release page][OP_TEE_build_release_4_0], [commits][OP_TEE_build_commits_4_0] and [pull requests][OP_TEE_build_pr_4_0] + - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_4_0], [commits][linaro_swg_optee_examples_commits_4_0] and [pull requests][linaro_swg_optee_examples_pr_4_0] + + +[OP_TEE_optee_os_release_4_0]: https://github.com/OP-TEE/optee_os/releases/tag/4.0.0 +[OP_TEE_optee_os_commits_4_0]: https://github.com/OP-TEE/optee_os/compare/3.22.0...4.0.0 +[OP_TEE_optee_os_pr_4_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-07-07..2023-10-20 + +[OP_TEE_optee_client_release_4_0]: https://github.com/OP-TEE/optee_client/releases/tag/4.0.0 +[OP_TEE_optee_client_commits_4_0]: https://github.com/OP-TEE/optee_client/compare/3.22.0...4.0.0 +[OP_TEE_optee_client_pr_4_0]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-07-07..2023-10-20 + +[OP_TEE_optee_test_release_4_0]: https://github.com/OP-TEE/optee_test/releases/tag/4.0.0 +[OP_TEE_optee_test_commits_4_0]: https://github.com/OP-TEE/optee_test/compare/3.22.0...4.0.0 +[OP_TEE_optee_test_pr_4_0]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-07-07..2023-10-20 + +[OP_TEE_build_release_4_0]: https://github.com/OP-TEE/build/releases/tag/4.0.0 +[OP_TEE_build_commits_4_0]: https://github.com/OP-TEE/build/compare/3.22.0...4.0.0 +[OP_TEE_build_pr_4_0]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-07-07..2023-10-20 + +[linaro_swg_optee_examples_release_4_0]: https://github.com/linaro-swg/optee_examples/releases/tag/4.0.0 +[linaro_swg_optee_examples_commits_4_0]: https://github.com/linaro-swg/optee_examples/compare/3.22.0...4.0.0 +[linaro_swg_optee_examples_pr_4_0]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-07-07..2023-10-20 + +# OP-TEE - version 3.22.0 (2023-07-07) + +- 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_22], [commits][OP_TEE_optee_os_commits_3_22] and [pull requests][OP_TEE_optee_os_pr_3_22] + - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_3_22], [commits][OP_TEE_optee_client_commits_3_22] and [pull requests][OP_TEE_optee_client_pr_3_22] + - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_3_22], [commits][OP_TEE_optee_test_commits_3_22] and [pull requests][OP_TEE_optee_test_pr_3_22] + - OP-TEE/build: [release page][OP_TEE_build_release_3_22], [commits][OP_TEE_build_commits_3_22] and [pull requests][OP_TEE_build_pr_3_22] + - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_3_22], [commits][linaro_swg_optee_examples_commits_3_22] and [pull requests][linaro_swg_optee_examples_pr_3_22] + + +[OP_TEE_optee_os_release_3_22]: https://github.com/OP-TEE/optee_os/releases/tag/3.22.0 +[OP_TEE_optee_os_commits_3_22]: https://github.com/OP-TEE/optee_os/compare/3.21.0...3.22.0 +[OP_TEE_optee_os_pr_3_22]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-04-14..2023-07-07 + +[OP_TEE_optee_client_release_3_22]: https://github.com/OP-TEE/optee_client/releases/tag/3.22.0 +[OP_TEE_optee_client_commits_3_22]: https://github.com/OP-TEE/optee_client/compare/3.21.0...3.22.0 +[OP_TEE_optee_client_pr_3_22]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-04-14..2023-07-07 + +[OP_TEE_optee_test_release_3_22]: https://github.com/OP-TEE/optee_test/releases/tag/3.22.0 +[OP_TEE_optee_test_commits_3_22]: https://github.com/OP-TEE/optee_test/compare/3.21.0...3.22.0 +[OP_TEE_optee_test_pr_3_22]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-04-14..2023-07-07 + +[OP_TEE_build_release_3_22]: https://github.com/OP-TEE/build/releases/tag/3.22.0 +[OP_TEE_build_commits_3_22]: https://github.com/OP-TEE/build/compare/3.21.0...3.22.0 +[OP_TEE_build_pr_3_22]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-04-14..2023-07-07 + +[linaro_swg_optee_examples_release_3_22]: https://github.com/linaro-swg/optee_examples/releases/tag/3.22.0 +[linaro_swg_optee_examples_commits_3_22]: https://github.com/linaro-swg/optee_examples/compare/3.21.0...3.22.0 +[linaro_swg_optee_examples_pr_3_22]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-04-14..2023-07-07 + +# 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..9639b8b --- /dev/null +++ b/optee/optee_os/MAINTAINERS @@ -0,0 +1,344 @@ + 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 + +---------- + +AOSP build +R: Tadd Kao [@taddk] +S: Maintained +F: mk/aosp_optee.mk + +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: Emekcan.Aras@arm.com [@ememarar] +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, CN10K +R: Tao Lu [@taovcu] +S: Maintained +F: core/arch/arm/plat-marvell/ + +MediaTek MT8173 EVB +S: Orphan +F: core/arch/arm/plat-mediatek/ + +NXP LS1043A-RDB, LS1046A-RDB, LS1012A-RDB, 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: Silvano Di Ninno [@sdininno] +R: Sahil Malhotra [@sahilnxp] +S: Maintained +F: core/arch/arm/plat-imx/ +F: core/arch/arm/plat-imx/registers +F: core/drivers/crypto/caam/ +F: core/drivers/imx/ +F: core/drivers/imx_csu.c +F: core/drivers/imx_ele.c +F: core/drivers/imx_lpuart.c +F: core/drivers/imx_ocotp.c +F: core/drivers/imx_sc_api.c +F: core/drivers/imx_scu.c +F: core/drivers/imx_snvs.c +F: core/drivers/imx_uart.c +F: core/drivers/imx_wdog.c + +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: Sahil Malhotra [@sahilnxp] +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 drivers +R: Etienne Carriere [@etienne-lms] +R: Gatien Chevallier [@GseoC] +S: Maintained +F: core/drivers/stm32_* + +STMicroelectronics stm32mp1 +R: Etienne Carriere [@etienne-lms] +S: Maintained +F: core/arch/arm/plat-stm32mp1/ +F: core/drivers/stm32mp15_huk.c +F: core/drivers/stpmic1.c + +STMicroelectronics stm32mp2 +R: Etienne Carriere [@etienne-lms] +R: Gatien Chevallier [@GseoC] +S: Maintained +F: core/arch/arm/plat-stm32mp2/* + +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, AST2700 +R: Chia-Wei Wang [@ChiaweiW] +R: Neal Liu [@Neal-liu] +S: Maintained +F: core/arch/arm/plat-aspeed/ + +RISC-V +R: Marouene Boubakri [@maroueneboubakri] +S: Maintained +F: core/arch/riscv/ +F: lib/libutee/arch/riscv/ +F: lib/libutils/ext/arch/riscv/ +F: lib/libutils/isoc/arch/riscv/ +F: ta/arch/riscv/ + +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..8908849 --- /dev/null +++ b/optee/optee_os/Makefile @@ -0,0 +1,129 @@ +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/macros.mk +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 +$(call force,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 + ${q}rm -f compile_commands.json + +.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..f45ede0 --- /dev/null +++ b/optee/optee_os/core/arch/arm/arm.mk @@ -0,0 +1,455 @@ +# 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_FFA),y) +ifneq ($(CFG_DT),y) +$(error CFG_CORE_FFA depends on CFG_DT) +endif +ifneq ($(CFG_ARM64_core),y) +$(error CFG_CORE_FFA depends on CFG_ARM64_core) +endif +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 or equal to 24 to make it of the type SPI or PPI (secure PPI +# only). +# 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..0abf91c --- /dev/null +++ b/optee/optee_os/core/arch/arm/crypto/ghash-ce-core_a64.S @@ -0,0 +1,652 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2020, 2024 Linaro Limited + * Copyright (C) 2014 - 2017 Linaro Ltd. + * + * Accelerated GHASH implementation with ARMv8 PMULL instructions. + */ + +#include +#include +#define CPU_LE(x...) x + +/* + * Only increase the lowest quarter, that is, 32-bits of the counter. If + * it wraps it must not propagate into the upper bits. + */ +#define INC_QUART_CTR 1 + + 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_QUART_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_QUART_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_QUART_CTR + lsr x12, x8, #32 // Save the upper 32 bits + rev x9, x8 + add w11, w8, #1 + add w8, w8, #2 + add x11, x11, x12, lsl #32 // Restore the upper 32 bits + add x8, x8, x12, lsl #32 +#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_QUART_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_QUART_CTR +CPU_LE( rev x9, x9 ) +#endif + st1 {XL.2d}, [x1] +#if INC_QUART_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/at91-sama7g54_ek.dts b/optee/optee_os/core/arch/arm/dts/at91-sama7g54_ek.dts new file mode 100644 index 0000000..de9a8b4 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/at91-sama7g54_ek.dts @@ -0,0 +1,958 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * at91-sama7g54_ek.dts - Device Tree file for SAMA7G54-EK board + * + * Copyright (c) 2017, Microchip Technology Inc. + * 2016 Nicolas Ferre + * 2017 Cristian Birsan + * 2017 Claudiu Beznea + */ +/dts-v1/; +#include "sama7g5-pinfunc.h" +#include "sama7g5.dtsi" +#include + +/ { + model = "Microchip SAMA7G5-EK"; + compatible = "microchip,sama7g5ek", "microchip,sama7g5", "microchip,sama7"; + + aliases { + serial0 = &uart3; + serial1 = &uart4; + serial2 = &uart7; + serial3 = &uart0; + i2c0 = &i2c1; + i2c1 = &i2c8; + i2c2 = &i2c9; + }; + + clocks { + slow_xtal { + clock-frequency = <32768>; + }; + + main_xtal { + clock-frequency = <24000000>; + }; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_led_gpio_default>; + status = "okay"; /* Conflict with pwm. */ + + red_led { + label = "red"; + gpios = <&pioA PIN_PB8 GPIO_ACTIVE_HIGH>; + }; + + green_led { + label = "green"; + gpios = <&pioA PIN_PA13 GPIO_ACTIVE_HIGH>; + }; + + blue_led { + label = "blue"; + gpios = <&pioA PIN_PD20 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + }; + }; + + /* 512 M */ + memory@60000000 { + device_type = "memory"; + reg = <0x60000000 0x20000000>; + }; + + sound: sound { + #address-cells = <1>; + #size-cells = <0>; + assigned-clocks = <&pmc PMC_TYPE_CORE PMC_AUDIOPMCPLL>; + assigned-clock-rates = <196608000>; + compatible = "microchip,asrc-card"; + microchip,model = "mchp-asrc-card @ sama7g5 EK"; + status = "disabled"; + + microchip,audio-asrc = <&asrc 0>, <&asrc 1>, <&asrc 2>, <&asrc 3>; + + microchip,dai-link@0 { + reg = <0>; + microchip,convert-channels = <2>; + microchip,convert-rate = <48000>; + cpu { + sound-dai = <&spdiftx>; + }; + codec { + sound-dai = <&spdif_out>; + }; + }; + + microchip,dai-link@1 { + reg = <1>; + microchip,convert-channels = <2>; + microchip,convert-rate = <48000>; + cpu { + sound-dai = <&spdifrx>; + }; + codec { + sound-dai = <&spdif_in>; + }; + }; + }; + + spdif_in: spdif-in { + #sound-dai-cells = <0>; + compatible = "linux,spdif-dir"; + }; + + spdif_out: spdif-out { + #sound-dai-cells = <0>; + compatible = "linux,spdif-dit"; + }; +}; + +&asrc { + status = "okay"; +}; + +&adc { + vddana-supply = <&vddout25>; + vref-supply = <&vddout25>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_mikrobus1_an_default &pinctrl_mikrobus2_an_default>; + status = "disabled"; +}; + +&can0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_can0_default>; + status = "okay"; +}; + +&can1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_can1_default>; + status = "okay"; +}; + +&cpu0 { + cpu-supply = <&vddcpu>; +}; + +&qspi0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_qspi>; + status = "okay"; + + flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <133000000>; + spi-tx-bus-width = <8>; + spi-rx-bus-width = <8>; + m25p,fast-read; + + at91bootstrap@0 { + label = "ospi: at91bootstrap"; + reg = <0x0 0x40000>; + }; + + bootloader@40000 { + label = "ospi: bootloader"; + reg = <0x40000 0xc0000>; + }; + + bootloaderenvred@100000 { + label = "ospi: bootloader env redundant"; + reg = <0x100000 0x40000>; + }; + + bootloaderenv@140000 { + label = "ospi: bootloader env"; + reg = <0x140000 0x40000>; + }; + + dtb@180000 { + label = "ospi: device tree"; + reg = <0x180000 0x80000>; + }; + + kernel@200000 { + label = "ospi: kernel"; + reg = <0x200000 0x600000>; + }; + + rootfs@800000 { + label = "ospi: rootfs"; + reg = <0x800000 0x7800000>; + }; + + }; +}; + +&dma0 { + status = "okay"; +}; + +&dma1 { + status = "okay"; +}; + +&dma2 { + status = "okay"; +}; + +&flx0 { + atmel,flexcom-mode = ; + status = "disabled"; + + uart0: serial@200 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flx0_default>; + status = "disabled"; + }; +}; + +&flx1 { + atmel,flexcom-mode = ; + status = "okay"; + + i2c1: i2c@600 { + dmas = <0>, <0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c1_default>; + i2c-analog-filter; + i2c-digital-filter; + i2c-digital-filter-width-ns = <35>; + status = "disable"; + secure-status = "okay"; + + pac1934@10 { + compatible = "microchip,pac1934"; + reg = <0x10>; + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + channel@1 { + reg = <0x1>; + shunt-resistor-micro-ohms = <10000>; + label = "VDD3V3"; + }; + + channel@2 { + reg = <0x2>; + shunt-resistor-micro-ohms = <10000>; + label = "VDDIODDR"; + }; + + channel@3 { + reg = <0x3>; + shunt-resistor-micro-ohms = <10000>; + label = "VDDCORE"; + }; + + channel@4 { + reg = <0x4>; + shunt-resistor-micro-ohms = <10000>; + label = "VDDCPU"; + }; + }; + + mcp16502@5b { + compatible = "microchip,mcp16502"; + reg = <0x5b>; + status = "okay"; + + regulators { + vdd_3v3: VDD_IO { + regulator-name = "VDD_IO"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-initial-mode = <2>; + regulator-allowed-modes = <2>, <4>; + regulator-always-on; + + regulator-state-standby { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + regulator-mode = <4>; + }; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-mode = <4>; + }; + }; + + vddioddr: VDD_DDR { + regulator-name = "VDD_DDR"; + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; + regulator-initial-mode = <2>; + regulator-allowed-modes = <2>, <4>; + regulator-always-on; + + regulator-state-standby { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1350000>; + regulator-mode = <4>; + }; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1350000>; + regulator-mode = <4>; + }; + }; + + vddcore: VDD_CORE { + regulator-name = "VDD_CORE"; + regulator-min-microvolt = <1150000>; + regulator-max-microvolt = <1150000>; + regulator-initial-mode = <2>; + regulator-allowed-modes = <2>, <4>; + regulator-always-on; + + regulator-state-standby { + regulator-on-in-suspend; + regulator-suspend-voltage = <1150000>; + regulator-mode = <4>; + }; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-mode = <4>; + }; + }; + + vddcpu: VDD_OTHER { + regulator-name = "VDD_OTHER"; + regulator-min-microvolt = <1050000>; + regulator-max-microvolt = <1250000>; + regulator-initial-mode = <2>; + regulator-allowed-modes = <2>, <4>; + regulator-ramp-delay = <3125>; + regulator-always-on; + + regulator-state-standby { + regulator-on-in-suspend; + regulator-suspend-voltage = <1050000>; + regulator-mode = <4>; + }; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-mode = <4>; + }; + }; + + vldo1: LDO1 { + regulator-name = "LDO1"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + + regulator-state-standby { + regulator-suspend-voltage = <1800000>; + regulator-on-in-suspend; + }; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vldo2: LDO2 { + regulator-name = "LDO2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <3700000>; + + regulator-state-standby { + regulator-suspend-voltage = <1800000>; + regulator-on-in-suspend; + }; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + }; + }; +}; + +&flx3 { + atmel,flexcom-mode = ; + status = "okay"; + + uart3: serial@200 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flx3_default>; + status = "okay"; + }; +}; + +&flx4 { + atmel,flexcom-mode = ; + status = "okay"; + + uart4: serial@200 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flx4_default>; + status = "okay"; + }; +}; + +&flx7 { + atmel,flexcom-mode = ; + status = "okay"; + + uart7: serial@200 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flx7_default>; + status = "okay"; + }; +}; + +&flx8 { + atmel,flexcom-mode = ; + status = "okay"; + + i2c8: i2c@600 { + dmas = <0>, <0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c8_default>; + i2c-analog-filter; + i2c-digital-filter; + i2c-digital-filter-width-ns = <35>; + status = "okay"; + + eeprom0: eeprom0@52 { + compatible = "atmel,24mac02e4"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x52>; + pagesize = <16>; + size = <256>; + status = "okay"; + + eeprom0_eui48: eui48@fa { + reg = <0xfa 0x6>; + }; + }; + + eeprom1: eeprom1@53 { + compatible = "atmel,24mac02e4"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x53>; + pagesize = <16>; + size = <256>; + status = "okay"; + + eeprom1_eui48: eui48@fa { + reg = <0xfa 0x6>; + }; + }; + }; +}; + +&flx9 { + atmel,flexcom-mode = ; + status = "okay"; + + i2c9: i2c@600 { + dmas = <0>, <0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c9_default>; + i2c-analog-filter; + i2c-digital-filter; + i2c-digital-filter-width-ns = <35>; + status = "okay"; + }; +}; + +&flx11 { + atmel,flexcom-mode = ; + status = "okay"; + + spi11: spi@400 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_mikrobus1_spi &pinctrl_mikrobus1_spi_cs>; + status = "okay"; + }; +}; + +&gmac0 { + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gmac0_default + &pinctrl_gmac0_mdio_default + &pinctrl_gmac0_txck_default + &pinctrl_gmac0_phy_irq>; + phy-mode = "rgmii-id"; + status = "okay"; + + nvmem-cells = <&eeprom0_eui48>; + nvmem-cell-names = "mac-address"; + + ethernet-phy@7 { + reg = <0x7>; + interrupt-parent = <&pioA>; + interrupts = ; + }; +}; + +&gmac1 { + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gmac1_default + &pinctrl_gmac1_mdio_default + &pinctrl_gmac1_phy_irq>; + phy-mode = "rmii"; + status = "disabled"; /* Conflict with pdmc0. */ + + nvmem-cells = <&eeprom1_eui48>; + nvmem-cell-names = "mac-address"; + + ethernet-phy@0 { + reg = <0x0>; + interrupt-parent = <&pioA>; + interrupts = ; + }; +}; + +&i2s0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2s0_default>; +}; + +&pdmc0 { + #sound-dai-cells = <0>; + status = "disabled"; /* Conflict with gmac1. */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pdmc0_default>; +}; + +&pioA { + + pinctrl_can0_default: can0_default { + pinmux = , + ; + bias-disable; + }; + + pinctrl_can1_default: can1_default { + pinmux = , + ; + bias-disable; + }; + + pinctrl_flx0_default: flx0_default { + pinmux = , + , + , + ; + bias-disable; + }; + + pinctrl_flx3_default: flx3_default { + pinmux = , + ; + bias-pull-up; + }; + + pinctrl_flx4_default: flx4_default { + pinmux = , + ; + bias-disable; + }; + + pinctrl_flx7_default: flx7_default { + pinmux = , + ; + bias-disable; + }; + + pinctrl_gmac0_default: gmac0_default { + pinmux = , + , + , + , + , + , + , + , + , + , + , + ; + slew-rate = <0>; + bias-disable; + }; + + pinctrl_gmac0_mdio_default: gmac0_mdio_default { + pinmux = , + ; + bias-disable; + }; + + pinctrl_gmac0_txck_default: gmac0_txck_default { + pinmux = ; + slew-rate = <0>; + bias-pull-up; + }; + + pinctrl_gmac0_phy_irq: gmac0_phy_irq { + pinmux = ; + bias-disable; + }; + + pinctrl_gmac1_default: gmac1_default { + pinmux = , + , + , + , + , + , + , + ; + slew-rate = <0>; + bias-disable; + }; + + pinctrl_gmac1_mdio_default: gmac1_mdio_default { + pinmux = , + ; + bias-disable; + }; + + pinctrl_gmac1_phy_irq: gmac1_phy_irq { + pinmux = ; + bias-disable; + }; + + pinctrl_i2c1_default: i2c1_default { + pinmux = , + ; + bias-disable; + }; + + pinctrl_i2c8_default: i2c8_default { + pinmux = , + ; + bias-disable; + }; + + pinctrl_i2c9_default: i2c9_default { + pinmux = , + ; + bias-disable; + }; + + pinctrl_i2s0_default: i2s0_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_mikrobus1_an_default: mikrobus1_an_default { + pinmux = ; + bias-disable; + }; + + pinctrl_mikrobus2_an_default: mikrobus2_an_default { + pinmux = ; + bias-disable; + }; + + pinctrl_mikrobus1_pwm2_default: mikrobus1_pwm2_default { + pinmux = ; + bias-disable; + }; + + pinctrl_mikrobus2_pwm3_default: mikrobus2_pwm3_default { + pinmux = ; + bias-disable; + }; + + pinctrl_mikrobus1_spi_cs: mikrobus1_spi_cs { + pinmux = ; + bias-disable; + }; + + pinctrl_mikrobus1_spi: mikrobus1_spi { + pinmux = , + , + ; + bias-disable; + }; + + pinctrl_pdmc0_default: pdmc0_default { + pinmux = , + , + ; + bias_disable; + }; + + pinctrl_qspi: qspi { + pinmux = , + , + , + , + , + , + , + , + , + , + , + , + ; + bias-disable; + slew-rate = <0>; + }; + + pinctrl_sdmmc0_default: sdmmc0_default { + cmd_data { + pinmux = , + , + , + , + , + , + , + , + ; + slew-rate = <0>; + bias-pull-up; + }; + + ck_cd_rstn_vddsel { + pinmux = , + , + ; + slew-rate = <0>; + bias-pull-up; + }; + }; + + pinctrl_sdmmc1_default: sdmmc1_default { + cmd_data { + pinmux = , + , + , + , + ; + slew-rate = <0>; + bias-pull-up; + }; + + ck_cd_rstn_vddsel { + pinmux = , + , + , + ; + slew-rate = <0>; + bias-pull-up; + }; + }; + + pinctrl_sdmmc2_default: sdmmc2_default { + cmd_data { + pinmux = , + , + , + , + ; + slew-rate = <0>; + bias-pull-up; + }; + + ck { + pinmux = ; + slew-rate = <0>; + bias-pull-up; + }; + }; + + pinctrl_spdifrx_default: spdifrx_default { + pinmux = ; + bias-disable; + }; + + pinctrl_spdiftx_default: spdiftx_default { + pinmux = ; + bias-disable; + }; + + pinctrl_usba_vbus_det: usba_vbus_det { + pinmux = ; + bias-disable; + }; + + pinctrl_usbb_vbus_det: usbb_vbus_det { + pinmux = ; + bias-disable; + }; + + pinctrl_usba_vbus_en: usba_vbus_en { + pinmux = ; + bias-disable; + }; + + pinctrl_usbb_vbus_en: usbb_vbus_en { + pinmux = ; + bias-disable; + }; + + pinctrl_usbc_vbus_en: usbc_vbus_en { + pinmux = ; + bias-disable; + }; +}; + +&pwm { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_mikrobus1_pwm2_default &pinctrl_mikrobus2_pwm3_default>; + status = "disabled"; /* Conflict with leds. */ +}; + +&rtt { + atmel,rtt-rtc-time-reg = <&gpbr 0x0>; +}; + +&sdmmc0 { + bus-width = <8>; + non-removable; + vmmc-supply = <&vdd_3v3>; + vqmmc-supply = <&vldo1>; + mmc-ddr-1_8v; + cap-mmc-highspeed; + cap-mmc-hw-reset; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sdmmc0_default>; + status = "okay"; +}; + +&sdmmc1 { + bus-width = <4>; + vmmc-supply = <&vdd_3v3>; + vqmmc-supply = <&vdd_3v3>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sdmmc1_default>; + status = "okay"; +}; + +&sdmmc2 { + bus-width = <4>; + no-1-8-v; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sdmmc2_default>; +}; + +&shdwc { + debounce-delay-us = <976>; + microchip,lpm-connection = <&gmac1 &main_xtal>; + + input@0 { + reg = <0>; + }; +}; + +&spdifrx { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_spdifrx_default>; + status = "okay"; +}; + +&spdiftx { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_spdiftx_default>; + status = "okay"; +}; + +&tcb0 { + timer0: timer@0 { + compatible = "atmel,tcb-timer"; + reg = <0>; + }; + + timer1: timer@1 { + compatible = "atmel,tcb-timer"; + reg = <1>; + }; +}; + +&usb0 { + atmel,vbus-gpio = <&pioA PIN_PD11 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usba_vbus_det>; + phys = <&usb_phy0>; + phy-names = "usb"; + status = "okay"; +}; + +&usb1 { + atmel,vbus-gpio = <&pioA PIN_PC12 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usbb_vbus_det>; + phys = <&usb_phy1>; + phy-names = "usb"; + status = "disabled"; +}; + +&usb2 { + num-ports = <3>; + atmel,vbus-gpio = <0 + &pioA PIN_PC11 GPIO_ACTIVE_HIGH + &pioA PIN_PC6 GPIO_ACTIVE_HIGH + >; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usbb_vbus_en &pinctrl_usbc_vbus_en>; + phys = <&usb_phy1>, <&usb_phy2>; + phy-names = "usb", "usb"; + status = "okay"; +}; + +&usb3 { + status = "okay"; +}; + +&usb_phy0 { + status = "okay"; +}; + +&usb_phy1 { + status = "okay"; +}; + +&usb_phy2 { + status = "okay"; +}; + +&vddout25 { + vin-supply = <&vdd_3v3>; + status = "okay"; +}; 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..69bae56 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/dt_driver_test.dtsi @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022, Linaro Limited + */ + #include + +/ { + /* + * 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"; + test-gpios = <&dt_test_provider 1 GPIO_ACTIVE_LOW>, + <&dt_test_provider 2 GPIO_PULL_UP>; + }; + + /* + * 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>; + #gpio-cells = <2>; + }; + }; + }; + }; + }; + + 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..2acdf63 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/fsl-lx2160a.dtsi @@ -0,0 +1,1391 @@ +// 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>; + }; + + memory@2080000000 { + // DRAM space - 1, size : 126 GB DRAM + device_type = "memory"; + reg = <0x00000020 0x80000000 0x0000001F 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..8e150ab --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/sama5d2.dtsi @@ -0,0 +1,1238 @@ +// 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"; + }; + + sfc: sfc@f804c000 { + compatible = "atmel,sama5d2-sfc"; + reg = <0xf804c000 0x64>; + read-only; + status = "disabled"; + secure-status = "okay"; + #address-cells = <1>; + #size-cells = <1>; + + sfc_kr: cell@0 { + reg = <0x0 0x4>; + bits = <0 7>; + }; + + sfc_dr0: cell@20 { + reg = <0x20 0x4>; + }; + }; + + die_id: die_id { + compatible = "optee,nvmem-die-id"; + nvmem-cells = <&sfc_kr>; + nvmem-cell-names = "die_id"; + }; + + huk: huk { + compatible = "optee,nvmem-huk"; + nvmem-cells = <&sfc_dr0>; + nvmem-cell-names = "hw_unique_key"; + }; + + 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>; + status = "disabled"; + secure-status = "okay"; + }; + + 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/sama7g5-pinfunc.h b/optee/optee_os/core/arch/arm/dts/sama7g5-pinfunc.h new file mode 100644 index 0000000..4f98cdb --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/sama7g5-pinfunc.h @@ -0,0 +1,927 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2024 Microchip Technology, Inc. and its subsidiaries + */ + +#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__FLEXCOM0_IO0 PINMUX_PIN(PIN_PA0, 2, 1) +#define PIN_PA0__CANTX3 PINMUX_PIN(PIN_PA0, 3, 1) +#define PIN_PA0__PWML0 PINMUX_PIN(PIN_PA0, 5, 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__FLEXCOM0_IO1 PINMUX_PIN(PIN_PA1, 2, 1) +#define PIN_PA1__CANRX3 PINMUX_PIN(PIN_PA1, 3, 1) +#define PIN_PA1__D14 PINMUX_PIN(PIN_PA1, 4, 1) +#define PIN_PA1__PWMH0 PINMUX_PIN(PIN_PA1, 5, 3) +#define PIN_PA2 2 +#define PIN_PA2__GPIO PINMUX_PIN(PIN_PA2, 0, 0) +#define PIN_PA2__SDMMC0_RSTN PINMUX_PIN(PIN_PA2, 1, 1) +#define PIN_PA2__FLEXCOM0_IO2 PINMUX_PIN(PIN_PA2, 2, 1) +#define PIN_PA2__PDMC1_CLK PINMUX_PIN(PIN_PA2, 3, 1) +#define PIN_PA2__D15 PINMUX_PIN(PIN_PA2, 4, 1) +#define PIN_PA2__PWMH1 PINMUX_PIN(PIN_PA2, 5, 3) +#define PIN_PA2__FLEXCOM1_IO0 PINMUX_PIN(PIN_PA2, 6, 3) +#define PIN_PA3 3 +#define PIN_PA3__GPIO PINMUX_PIN(PIN_PA3, 0, 0) +#define PIN_PA3__SDMMC0_DAT0 PINMUX_PIN(PIN_PA3, 1, 1) +#define PIN_PA3__FLEXCOM0_IO3 PINMUX_PIN(PIN_PA3, 2, 1) +#define PIN_PA3__PDMC1_DS0 PINMUX_PIN(PIN_PA3, 3, 1) +#define PIN_PA3__NWR1_NBS1 PINMUX_PIN(PIN_PA3, 4, 1) +#define PIN_PA3__PWML3 PINMUX_PIN(PIN_PA3, 5, 3) +#define PIN_PA3__FLEXCOM1_IO1 PINMUX_PIN(PIN_PA3, 6, 3) +#define PIN_PA4 4 +#define PIN_PA4__GPIO PINMUX_PIN(PIN_PA4, 0, 0) +#define PIN_PA4__SDMMC0_DAT1 PINMUX_PIN(PIN_PA4, 1, 1) +#define PIN_PA4__FLEXCOM0_IO4 PINMUX_PIN(PIN_PA4, 2, 1) +#define PIN_PA4__PDMC1_DS1 PINMUX_PIN(PIN_PA4, 3, 1) +#define PIN_PA4__NCS2 PINMUX_PIN(PIN_PA4, 4, 1) +#define PIN_PA4__PWMH3 PINMUX_PIN(PIN_PA4, 5, 3) +#define PIN_PA4__FLEXCOM2_IO0 PINMUX_PIN(PIN_PA4, 6, 3) +#define PIN_PA5 5 +#define PIN_PA5__GPIO PINMUX_PIN(PIN_PA5, 0, 0) +#define PIN_PA5__SDMMC0_DAT2 PINMUX_PIN(PIN_PA5, 1, 1) +#define PIN_PA5__FLEXCOM1_IO0 PINMUX_PIN(PIN_PA5, 2, 1) +#define PIN_PA5__CANTX2 PINMUX_PIN(PIN_PA5, 3, 1) +#define PIN_PA5__A23 PINMUX_PIN(PIN_PA5, 4, 1) +#define PIN_PA5__PWMEXTRG0 PINMUX_PIN(PIN_PA5, 5, 3) +#define PIN_PA5__FLEXCOM2_IO1 PINMUX_PIN(PIN_PA5, 6, 3) +#define PIN_PA6 6 +#define PIN_PA6__GPIO PINMUX_PIN(PIN_PA6, 0, 0) +#define PIN_PA6__SDMMC0_DAT3 PINMUX_PIN(PIN_PA6, 1, 1) +#define PIN_PA6__FLEXCOM1_IO1 PINMUX_PIN(PIN_PA6, 2, 1) +#define PIN_PA6__CANRX2 PINMUX_PIN(PIN_PA6, 3, 1) +#define PIN_PA6__A24 PINMUX_PIN(PIN_PA6, 4, 1) +#define PIN_PA6__PWMEXTRG1 PINMUX_PIN(PIN_PA6, 5, 3) +#define PIN_PA6__FLEXCOM3_IO0 PINMUX_PIN(PIN_PA6, 6, 3) +#define PIN_PA7 7 +#define PIN_PA7__GPIO PINMUX_PIN(PIN_PA7, 0, 0) +#define PIN_PA7__SDMMC0_DAT4 PINMUX_PIN(PIN_PA7, 1, 1) +#define PIN_PA7__FLEXCOM2_IO0 PINMUX_PIN(PIN_PA7, 2, 1) +#define PIN_PA7__CANTX1 PINMUX_PIN(PIN_PA7, 3, 1) +#define PIN_PA7__NWAIT PINMUX_PIN(PIN_PA7, 4, 1) +#define PIN_PA7__PWMFI0 PINMUX_PIN(PIN_PA7, 5, 3) +#define PIN_PA7__FLEXCOM3_IO1 PINMUX_PIN(PIN_PA7, 6, 3) +#define PIN_PA8 8 +#define PIN_PA8__GPIO PINMUX_PIN(PIN_PA8, 0, 0) +#define PIN_PA8__SDMMC0_DAT5 PINMUX_PIN(PIN_PA8, 1, 1) +#define PIN_PA8__FLEXCOM2_IO1 PINMUX_PIN(PIN_PA8, 2, 1) +#define PIN_PA8__CANRX1 PINMUX_PIN(PIN_PA8, 3, 1) +#define PIN_PA8__NCS0 PINMUX_PIN(PIN_PA8, 4, 1) +#define PIN_PA8__PWMIF1 PINMUX_PIN(PIN_PA8, 5, 3) +#define PIN_PA8__FLEXCOM4_IO0 PINMUX_PIN(PIN_PA8, 6, 3) +#define PIN_PA9 9 +#define PIN_PA9__GPIO PINMUX_PIN(PIN_PA9, 0, 0) +#define PIN_PA9__SDMMC0_DAT6 PINMUX_PIN(PIN_PA9, 1, 1) +#define PIN_PA9__FLEXCOM2_IO2 PINMUX_PIN(PIN_PA9, 2, 1) +#define PIN_PA9__CANTX0 PINMUX_PIN(PIN_PA9, 3, 1) +#define PIN_PA9__SMCK PINMUX_PIN(PIN_PA9, 4, 1) +#define PIN_PA9__SPDIF_RX PINMUX_PIN(PIN_PA9, 5, 1) +#define PIN_PA9__FLEXCOM4_IO1 PINMUX_PIN(PIN_PA9, 6, 3) +#define PIN_PA10 10 +#define PIN_PA10__GPIO PINMUX_PIN(PIN_PA10, 0, 0) +#define PIN_PA10__SDMMC0_DAT7 PINMUX_PIN(PIN_PA10, 1, 1) +#define PIN_PA10__FLEXCOM2_IO3 PINMUX_PIN(PIN_PA10, 2, 1) +#define PIN_PA10__CANRX0 PINMUX_PIN(PIN_PA10, 3, 1) +#define PIN_PA10__NCS1 PINMUX_PIN(PIN_PA10, 4, 1) +#define PIN_PA10__SPDIF_TX PINMUX_PIN(PIN_PA10, 5, 1) +#define PIN_PA10__FLEXCOM5_IO0 PINMUX_PIN(PIN_PA10, 6, 3) +#define PIN_PA11 11 +#define PIN_PA11__GPIO PINMUX_PIN(PIN_PA11, 0, 0) +#define PIN_PA11__SDMMC0_DS PINMUX_PIN(PIN_PA11, 1, 1) +#define PIN_PA11__FLEXCOM2_IO4 PINMUX_PIN(PIN_PA11, 2, 1) +#define PIN_PA11__A0_NBS0 PINMUX_PIN(PIN_PA11, 4, 1) +#define PIN_PA11__TIOA0 PINMUX_PIN(PIN_PA11, 5, 1) +#define PIN_PA11__FLEXCOM5_IO1 PINMUX_PIN(PIN_PA11, 6, 3) +#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__FLEXCOM1_IO3 PINMUX_PIN(PIN_PA12, 2, 1) +#define PIN_PA12__FLEXCOM3_IO5 PINMUX_PIN(PIN_PA12, 4, 1) +#define PIN_PA12__PWML2 PINMUX_PIN(PIN_PA12, 5, 3) +#define PIN_PA12__FLEXCOM6_IO0 PINMUX_PIN(PIN_PA12, 6, 3) +#define PIN_PA13 13 +#define PIN_PA13__GPIO PINMUX_PIN(PIN_PA13, 0, 0) +#define PIN_PA13__SDMMC0_1V8SEL PINMUX_PIN(PIN_PA13, 1, 1) +#define PIN_PA13__FLEXCOM1_IO2 PINMUX_PIN(PIN_PA13, 2, 1) +#define PIN_PA13__FLEXCOM3_IO6 PINMUX_PIN(PIN_PA13, 4, 1) +#define PIN_PA13__PWMH2 PINMUX_PIN(PIN_PA13, 5, 3) +#define PIN_PA13__FLEXCOM6_IO1 PINMUX_PIN(PIN_PA13, 6, 3) +#define PIN_PA14 14 +#define PIN_PA14__GPIO PINMUX_PIN(PIN_PA14, 0, 0) +#define PIN_PA14__SDMMC0_CD PINMUX_PIN(PIN_PA14, 1, 1) +#define PIN_PA14__FLEXCOM1_IO4 PINMUX_PIN(PIN_PA14, 2, 1) +#define PIN_PA14__A25 PINMUX_PIN(PIN_PA14, 4, 1) +#define PIN_PA14__PWML1 PINMUX_PIN(PIN_PA14, 5, 3) +#define PIN_PA15 15 +#define PIN_PA15__GPIO PINMUX_PIN(PIN_PA15, 0, 0) +#define PIN_PA15__G0_TXEN PINMUX_PIN(PIN_PA15, 1, 1) +#define PIN_PA15__FLEXCOM3_IO0 PINMUX_PIN(PIN_PA15, 2, 1) +#define PIN_PA15__ISC_MCK PINMUX_PIN(PIN_PA15, 3, 1) +#define PIN_PA15__A1 PINMUX_PIN(PIN_PA15, 4, 1) +#define PIN_PA15__TIOB0 PINMUX_PIN(PIN_PA15, 5, 1) +#define PIN_PA16 16 +#define PIN_PA16__GPIO PINMUX_PIN(PIN_PA16, 0, 0) +#define PIN_PA16__G0_TX0 PINMUX_PIN(PIN_PA16, 1, 1) +#define PIN_PA16__FLEXCOM3_IO1 PINMUX_PIN(PIN_PA16, 2, 1) +#define PIN_PA16__ISC_D0 PINMUX_PIN(PIN_PA16, 3, 1) +#define PIN_PA16__A2 PINMUX_PIN(PIN_PA16, 4, 1) +#define PIN_PA16__TCLK0 PINMUX_PIN(PIN_PA16, 5, 1) +#define PIN_PA17 17 +#define PIN_PA17__GPIO PINMUX_PIN(PIN_PA17, 0, 0) +#define PIN_PA17__G0_TX1 PINMUX_PIN(PIN_PA17, 1, 1) +#define PIN_PA17__FLEXCOM3_IO2 PINMUX_PIN(PIN_PA17, 2, 1) +#define PIN_PA17__ISC_D1 PINMUX_PIN(PIN_PA17, 3, 1) +#define PIN_PA17__A3 PINMUX_PIN(PIN_PA17, 4, 1) +#define PIN_PA17__TIOA1 PINMUX_PIN(PIN_PA17, 5, 1) +#define PIN_PA18 18 +#define PIN_PA18__GPIO PINMUX_PIN(PIN_PA18, 0, 0) +#define PIN_PA18__G0_RXDV PINMUX_PIN(PIN_PA18, 1, 1) +#define PIN_PA18__FLEXCOM3_IO3 PINMUX_PIN(PIN_PA18, 2, 1) +#define PIN_PA18__ISC_D2 PINMUX_PIN(PIN_PA18, 3, 1) +#define PIN_PA18__A4 PINMUX_PIN(PIN_PA18, 4, 1) +#define PIN_PA18__TIOB1 PINMUX_PIN(PIN_PA18, 5, 1) +#define PIN_PA19 19 +#define PIN_PA19__GPIO PINMUX_PIN(PIN_PA19, 0, 0) +#define PIN_PA19__G0_RX0 PINMUX_PIN(PIN_PA19, 1, 1) +#define PIN_PA19__FLEXCOM3_IO4 PINMUX_PIN(PIN_PA19, 2, 1) +#define PIN_PA19__ISC_D3 PINMUX_PIN(PIN_PA19, 3, 1) +#define PIN_PA19__A5 PINMUX_PIN(PIN_PA19, 4, 1) +#define PIN_PA19__TCLK1 PINMUX_PIN(PIN_PA19, 5, 1) +#define PIN_PA20 20 +#define PIN_PA20__GPIO PINMUX_PIN(PIN_PA20, 0, 0) +#define PIN_PA20__G0_RX1 PINMUX_PIN(PIN_PA20, 1, 1) +#define PIN_PA20__FLEXCOM4_IO0 PINMUX_PIN(PIN_PA20, 2, 1) +#define PIN_PA20__ISC_D4 PINMUX_PIN(PIN_PA20, 3, 1) +#define PIN_PA20__A6 PINMUX_PIN(PIN_PA20, 4, 1) +#define PIN_PA20__TIOA2 PINMUX_PIN(PIN_PA20, 5, 1) +#define PIN_PA21 21 +#define PIN_PA21__GPIO PINMUX_PIN(PIN_PA21, 0, 0) +#define PIN_PA21__G0_RXER PINMUX_PIN(PIN_PA21, 1, 1) +#define PIN_PA21__FLEXCOM4_IO1 PINMUX_PIN(PIN_PA21, 2, 1) +#define PIN_PA21__ISC_D5 PINMUX_PIN(PIN_PA21, 3, 1) +#define PIN_PA21__A7 PINMUX_PIN(PIN_PA21, 4, 1) +#define PIN_PA21__TIOB2 PINMUX_PIN(PIN_PA21, 5, 1) +#define PIN_PA22 22 +#define PIN_PA22__GPIO PINMUX_PIN(PIN_PA22, 0, 0) +#define PIN_PA22__G0_MDC PINMUX_PIN(PIN_PA22, 1, 1) +#define PIN_PA22__FLEXCOM4_IO2 PINMUX_PIN(PIN_PA22, 2, 1) +#define PIN_PA22__ISC_D6 PINMUX_PIN(PIN_PA22, 3, 1) +#define PIN_PA22__A8 PINMUX_PIN(PIN_PA22, 4, 1) +#define PIN_PA22__TCLK2 PINMUX_PIN(PIN_PA22, 5, 1) +#define PIN_PA23 23 +#define PIN_PA23__GPIO PINMUX_PIN(PIN_PA23, 0, 0) +#define PIN_PA23__G0_MDIO PINMUX_PIN(PIN_PA23, 1, 1) +#define PIN_PA23__FLEXCOM4_IO3 PINMUX_PIN(PIN_PA23, 2, 1) +#define PIN_PA23__ISC_D7 PINMUX_PIN(PIN_PA23, 3, 1) +#define PIN_PA23__A9 PINMUX_PIN(PIN_PA23, 4, 1) +#define PIN_PA24 24 +#define PIN_PA24__GPIO PINMUX_PIN(PIN_PA24, 0, 0) +#define PIN_PA24__G0_TXCK PINMUX_PIN(PIN_PA24, 1, 1) +#define PIN_PA24__FLEXCOM4_IO4 PINMUX_PIN(PIN_PA24, 2, 1) +#define PIN_PA24__ISC_HSYNC PINMUX_PIN(PIN_PA24, 3, 1) +#define PIN_PA24__A10 PINMUX_PIN(PIN_PA24, 4, 1) +#define PIN_PA24__FLEXCOM0_IO5 PINMUX_PIN(PIN_PA24, 5, 1) +#define PIN_PA25 25 +#define PIN_PA25__GPIO PINMUX_PIN(PIN_PA25, 0, 0) +#define PIN_PA25__G0_125CK PINMUX_PIN(PIN_PA25, 1, 1) +#define PIN_PA25__FLEXCOM5_IO4 PINMUX_PIN(PIN_PA25, 2, 1) +#define PIN_PA25__ISC_VSYNC PINMUX_PIN(PIN_PA25, 3, 1) +#define PIN_PA25__A11 PINMUX_PIN(PIN_PA25, 4, 1) +#define PIN_PA25__FLEXCOM0_IO6 PINMUX_PIN(PIN_PA25, 5, 1) +#define PIN_PA25__FLEXCOM7_IO0 PINMUX_PIN(PIN_PA25, 6, 3) +#define PIN_PA26 26 +#define PIN_PA26__GPIO PINMUX_PIN(PIN_PA26, 0, 0) +#define PIN_PA26__G0_TX2 PINMUX_PIN(PIN_PA26, 1, 1) +#define PIN_PA26__FLEXCOM5_IO2 PINMUX_PIN(PIN_PA26, 2, 1) +#define PIN_PA26__ISC_FIELD PINMUX_PIN(PIN_PA26, 3, 1) +#define PIN_PA26__A12 PINMUX_PIN(PIN_PA26, 4, 1) +#define PIN_PA26__TF0 PINMUX_PIN(PIN_PA26, 5, 1) +#define PIN_PA26__FLEXCOM7_IO1 PINMUX_PIN(PIN_PA26, 6, 3) +#define PIN_PA27 27 +#define PIN_PA27__GPIO PINMUX_PIN(PIN_PA27, 0, 0) +#define PIN_PA27__G0_TX3 PINMUX_PIN(PIN_PA27, 1, 1) +#define PIN_PA27__FLEXCOM5_IO3 PINMUX_PIN(PIN_PA27, 2, 1) +#define PIN_PA27__ISC_PCK PINMUX_PIN(PIN_PA27, 3, 1) +#define PIN_PA27__A13 PINMUX_PIN(PIN_PA27, 4, 1) +#define PIN_PA27__TK0 PINMUX_PIN(PIN_PA27, 5, 1) +#define PIN_PA27__FLEXCOM8_IO0 PINMUX_PIN(PIN_PA27, 6, 3) +#define PIN_PA28 28 +#define PIN_PA28__GPIO PINMUX_PIN(PIN_PA28, 0, 0) +#define PIN_PA28__G0_RX2 PINMUX_PIN(PIN_PA28, 1, 1) +#define PIN_PA28__FLEXCOM5_IO0 PINMUX_PIN(PIN_PA28, 2, 1) +#define PIN_PA28__ISC_D8 PINMUX_PIN(PIN_PA28, 3, 1) +#define PIN_PA28__A14 PINMUX_PIN(PIN_PA28, 4, 1) +#define PIN_PA28__RD0 PINMUX_PIN(PIN_PA28, 5, 1) +#define PIN_PA28__FLEXCOM8_IO1 PINMUX_PIN(PIN_PA28, 6, 3) +#define PIN_PA29 29 +#define PIN_PA29__GPIO PINMUX_PIN(PIN_PA29, 0, 0) +#define PIN_PA29__G0_RX3 PINMUX_PIN(PIN_PA29, 1, 1) +#define PIN_PA29__FLEXCOM5_IO1 PINMUX_PIN(PIN_PA29, 2, 1) +#define PIN_PA29__ISC_D9 PINMUX_PIN(PIN_PA29, 3, 1) +#define PIN_PA29__A15 PINMUX_PIN(PIN_PA29, 4, 1) +#define PIN_PA29__RF0 PINMUX_PIN(PIN_PA29, 5, 1) +#define PIN_PA29__FLEXCOM9_IO0 PINMUX_PIN(PIN_PA29, 6, 3) +#define PIN_PA30 30 +#define PIN_PA30__GPIO PINMUX_PIN(PIN_PA30, 0, 0) +#define PIN_PA30__G0_RXCK PINMUX_PIN(PIN_PA30, 1, 1) +#define PIN_PA30__FLEXCOM6_IO4 PINMUX_PIN(PIN_PA30, 2, 1) +#define PIN_PA30__ISC_D10 PINMUX_PIN(PIN_PA30, 3, 1) +#define PIN_PA30__A16 PINMUX_PIN(PIN_PA30, 4, 1) +#define PIN_PA30__RK0 PINMUX_PIN(PIN_PA30, 5, 1) +#define PIN_PA30__FLEXCOM9_IO1 PINMUX_PIN(PIN_PA30, 6, 3) +#define PIN_PA31 31 +#define PIN_PA31__GPIO PINMUX_PIN(PIN_PA31, 0, 0) +#define PIN_PA31__G0_TXER PINMUX_PIN(PIN_PA31, 1, 1) +#define PIN_PA31__FLEXCOM6_IO2 PINMUX_PIN(PIN_PA31, 2, 1) +#define PIN_PA31__ISC_D11 PINMUX_PIN(PIN_PA31, 3, 1) +#define PIN_PA31__A17 PINMUX_PIN(PIN_PA31, 4, 1) +#define PIN_PA31__TD0 PINMUX_PIN(PIN_PA31, 5, 1) +#define PIN_PA31__FLEXCOM10_IO0 PINMUX_PIN(PIN_PA31, 6, 3) +#define PIN_PB0 32 +#define PIN_PB0__GPIO PINMUX_PIN(PIN_PB0, 0, 0) +#define PIN_PB0__G0_COL PINMUX_PIN(PIN_PB0, 1, 1) +#define PIN_PB0__FLEXCOM6_IO3 PINMUX_PIN(PIN_PB0, 2, 2) +#define PIN_PB0__EXT_IRQ0 PINMUX_PIN(PIN_PB0, 3, 1) +#define PIN_PB0__A18 PINMUX_PIN(PIN_PB0, 4, 1) +#define PIN_PB0__SPDIF_RX PINMUX_PIN(PIN_PB0, 5, 2) +#define PIN_PB0__FLEXCOM10_IO1 PINMUX_PIN(PIN_PB0, 6, 3) +#define PIN_PB1 33 +#define PIN_PB1__GPIO PINMUX_PIN(PIN_PB1, 0, 0) +#define PIN_PB1__G0_CRS PINMUX_PIN(PIN_PB1, 1, 1) +#define PIN_PB1__FLEXCOM6_IO1 PINMUX_PIN(PIN_PB1, 2, 2) +#define PIN_PB1__EXT_IRQ1 PINMUX_PIN(PIN_PB1, 3, 1) +#define PIN_PB1__A19 PINMUX_PIN(PIN_PB1, 4, 1) +#define PIN_PB1__SPDIF_TX PINMUX_PIN(PIN_PB1, 5, 2) +#define PIN_PB1__FLEXCOM11_IO0 PINMUX_PIN(PIN_PB1, 6, 3) +#define PIN_PB2 34 +#define PIN_PB2__GPIO PINMUX_PIN(PIN_PB2, 0, 0) +#define PIN_PB2__G0_TSUCOMP PINMUX_PIN(PIN_PB2, 1, 1) +#define PIN_PB2__FLEXCOM6_IO0 PINMUX_PIN(PIN_PB2, 2, 1) +#define PIN_PB2__ADTRG PINMUX_PIN(PIN_PB2, 3, 1) +#define PIN_PB2__A20 PINMUX_PIN(PIN_PB2, 4, 1) +#define PIN_PB2__FLEXCOM11_IO1 PINMUX_PIN(PIN_PB2, 6, 3) +#define PIN_PB3 35 +#define PIN_PB3__GPIO PINMUX_PIN(PIN_PB3, 0, 0) +#define PIN_PB3__RF1 PINMUX_PIN(PIN_PB3, 1, 1) +#define PIN_PB3__FLEXCOM11_IO0 PINMUX_PIN(PIN_PB3, 2, 1) +#define PIN_PB3__PCK2 PINMUX_PIN(PIN_PB3, 3, 2) +#define PIN_PB3__D8 PINMUX_PIN(PIN_PB3, 4, 1) +#define PIN_PB4 36 +#define PIN_PB4__GPIO PINMUX_PIN(PIN_PB4, 0, 0) +#define PIN_PB4__TF1 PINMUX_PIN(PIN_PB4, 1, 1) +#define PIN_PB4__FLEXCOM11_IO1 PINMUX_PIN(PIN_PB4, 2, 1) +#define PIN_PB4__PCK3 PINMUX_PIN(PIN_PB4, 3, 2) +#define PIN_PB4__D9 PINMUX_PIN(PIN_PB4, 4, 1) +#define PIN_PB5 37 +#define PIN_PB5__GPIO PINMUX_PIN(PIN_PB5, 0, 0) +#define PIN_PB5__TK1 PINMUX_PIN(PIN_PB5, 1, 1) +#define PIN_PB5__FLEXCOM11_IO2 PINMUX_PIN(PIN_PB5, 2, 1) +#define PIN_PB5__PCK4 PINMUX_PIN(PIN_PB5, 3, 2) +#define PIN_PB5__D10 PINMUX_PIN(PIN_PB5, 4, 1) +#define PIN_PB6 38 +#define PIN_PB6__GPIO PINMUX_PIN(PIN_PB6, 0, 0) +#define PIN_PB6__RK1 PINMUX_PIN(PIN_PB6, 1, 1) +#define PIN_PB6__FLEXCOM11_IO3 PINMUX_PIN(PIN_PB6, 2, 1) +#define PIN_PB6__PCK5 PINMUX_PIN(PIN_PB6, 3, 2) +#define PIN_PB6__D11 PINMUX_PIN(PIN_PB6, 4, 1) +#define PIN_PB7 39 +#define PIN_PB7__GPIO PINMUX_PIN(PIN_PB7, 0, 0) +#define PIN_PB7__TD1 PINMUX_PIN(PIN_PB7, 1, 1) +#define PIN_PB7__FLEXCOM11_IO4 PINMUX_PIN(PIN_PB7, 2, 1) +#define PIN_PB7__FLEXCOM3_IO5 PINMUX_PIN(PIN_PB7, 3, 2) +#define PIN_PB7__D12 PINMUX_PIN(PIN_PB7, 4, 1) +#define PIN_PB8 40 +#define PIN_PB8__GPIO PINMUX_PIN(PIN_PB8, 0, 0) +#define PIN_PB8__RD1 PINMUX_PIN(PIN_PB8, 1, 1) +#define PIN_PB8__FLEXCOM8_IO0 PINMUX_PIN(PIN_PB8, 2, 1) +#define PIN_PB8__FLEXCOM3_IO6 PINMUX_PIN(PIN_PB8, 3, 2) +#define PIN_PB8__D13 PINMUX_PIN(PIN_PB8, 4, 1) +#define PIN_PB9 41 +#define PIN_PB9__GPIO PINMUX_PIN(PIN_PB9, 0, 0) +#define PIN_PB9__QSPI0_IO3 PINMUX_PIN(PIN_PB9, 1, 1) +#define PIN_PB9__FLEXCOM8_IO1 PINMUX_PIN(PIN_PB9, 2, 1) +#define PIN_PB9__PDMC0_CLK PINMUX_PIN(PIN_PB9, 3, 1) +#define PIN_PB9__NCS3_NANDCS PINMUX_PIN(PIN_PB9, 4, 1) +#define PIN_PB9__PWML0 PINMUX_PIN(PIN_PB9, 5, 2) +#define PIN_PB10 42 +#define PIN_PB10__GPIO PINMUX_PIN(PIN_PB10, 0, 0) +#define PIN_PB10__QSPI0_IO2 PINMUX_PIN(PIN_PB10, 1, 1) +#define PIN_PB10__FLEXCOM8_IO2 PINMUX_PIN(PIN_PB10, 2, 1) +#define PIN_PB10__PDMC0_DS0 PINMUX_PIN(PIN_PB10, 3, 1) +#define PIN_PB10__NWE_NWR0_NANDWE PINMUX_PIN(PIN_PB10, 4, 1) +#define PIN_PB10__PWMH0 PINMUX_PIN(PIN_PB10, 5, 2) +#define PIN_PB11 43 +#define PIN_PB11__GPIO PINMUX_PIN(PIN_PB11, 0, 0) +#define PIN_PB11__QSPI0_IO1 PINMUX_PIN(PIN_PB11, 1, 1) +#define PIN_PB11__FLEXCOM8_IO3 PINMUX_PIN(PIN_PB11, 2, 1) +#define PIN_PB11__PDMC0_DS1 PINMUX_PIN(PIN_PB11, 3, 1) +#define PIN_PB11__NRD_NANDOE PINMUX_PIN(PIN_PB11, 4, 1) +#define PIN_PB11__PWML1 PINMUX_PIN(PIN_PB11, 5, 2) +#define PIN_PB12 44 +#define PIN_PB12__GPIO PINMUX_PIN(PIN_PB12, 0, 0) +#define PIN_PB12__QSPI0_IO0 PINMUX_PIN(PIN_PB12, 1, 1) +#define PIN_PB12__FLEXCOM8_IO4 PINMUX_PIN(PIN_PB12, 2, 1) +#define PIN_PB12__FLEXCOM6_IO5 PINMUX_PIN(PIN_PB12, 3, 1) +#define PIN_PB12__A21_NANDALE PINMUX_PIN(PIN_PB12, 4, 1) +#define PIN_PB12__PWMH1 PINMUX_PIN(PIN_PB12, 5, 2) +#define PIN_PB13 45 +#define PIN_PB13__GPIO PINMUX_PIN(PIN_PB13, 0, 0) +#define PIN_PB13__QSPI0_CS PINMUX_PIN(PIN_PB13, 1, 1) +#define PIN_PB13__FLEXCOM9_IO0 PINMUX_PIN(PIN_PB13, 2, 1) +#define PIN_PB13__FLEXCOM6_IO6 PINMUX_PIN(PIN_PB13, 3, 1) +#define PIN_PB13__A22_NANDCLE PINMUX_PIN(PIN_PB13, 4, 1) +#define PIN_PB13__PWML2 PINMUX_PIN(PIN_PB13, 5, 2) +#define PIN_PB14 46 +#define PIN_PB14__GPIO PINMUX_PIN(PIN_PB14, 0, 0) +#define PIN_PB14__QSPI0_SCK PINMUX_PIN(PIN_PB14, 1, 1) +#define PIN_PB14__FLEXCOM9_IO1 PINMUX_PIN(PIN_PB14, 2, 1) +#define PIN_PB14__D0 PINMUX_PIN(PIN_PB14, 4, 1) +#define PIN_PB14__PWMH2 PINMUX_PIN(PIN_PB14, 5, 2) +#define PIN_PB15 47 +#define PIN_PB15__GPIO PINMUX_PIN(PIN_PB15, 0, 0) +#define PIN_PB15__QSPI0_SCKN PINMUX_PIN(PIN_PB15, 1, 1) +#define PIN_PB15__FLEXCOM9_IO2 PINMUX_PIN(PIN_PB15, 2, 1) +#define PIN_PB15__D1 PINMUX_PIN(PIN_PB15, 4, 1) +#define PIN_PB15__PWML3 PINMUX_PIN(PIN_PB15, 5, 2) +#define PIN_PB16 48 +#define PIN_PB16__GPIO PINMUX_PIN(PIN_PB16, 0, 0) +#define PIN_PB16__QSPI0_IO4 PINMUX_PIN(PIN_PB16, 1, 1) +#define PIN_PB16__FLEXCOM9_IO3 PINMUX_PIN(PIN_PB16, 2, 1) +#define PIN_PB16__PCK0 PINMUX_PIN(PIN_PB16, 3, 1) +#define PIN_PB16__D2 PINMUX_PIN(PIN_PB16, 4, 1) +#define PIN_PB16__PWMH3 PINMUX_PIN(PIN_PB16, 5, 2) +#define PIN_PB16__EXT_IRQ0 PINMUX_PIN(PIN_PB16, 6, 2) +#define PIN_PB17 49 +#define PIN_PB17__GPIO PINMUX_PIN(PIN_PB17, 0, 0) +#define PIN_PB17__QSPI0_IO5 PINMUX_PIN(PIN_PB17, 1, 1) +#define PIN_PB17__FLEXCOM9_IO4 PINMUX_PIN(PIN_PB17, 2, 1) +#define PIN_PB17__PCK1 PINMUX_PIN(PIN_PB17, 3, 1) +#define PIN_PB17__D3 PINMUX_PIN(PIN_PB17, 4, 1) +#define PIN_PB17__PWMEXTRG0 PINMUX_PIN(PIN_PB17, 5, 2) +#define PIN_PB17__EXT_IRQ1 PINMUX_PIN(PIN_PB17, 6, 2) +#define PIN_PB18 50 +#define PIN_PB18__GPIO PINMUX_PIN(PIN_PB18, 0, 0) +#define PIN_PB18__QSPI0_IO6 PINMUX_PIN(PIN_PB18, 1, 1) +#define PIN_PB18__FLEXCOM10_IO0 PINMUX_PIN(PIN_PB18, 2, 1) +#define PIN_PB18__PCK2 PINMUX_PIN(PIN_PB18, 3, 1) +#define PIN_PB18__D4 PINMUX_PIN(PIN_PB18, 4, 1) +#define PIN_PB18__PWMEXTRG1 PINMUX_PIN(PIN_PB18, 5, 2) +#define PIN_PB19 51 +#define PIN_PB19__GPIO PINMUX_PIN(PIN_PB19, 0, 0) +#define PIN_PB19__QSPI0_IO7 PINMUX_PIN(PIN_PB19, 1, 1) +#define PIN_PB19__FLEXCOM10_IO1 PINMUX_PIN(PIN_PB19, 2, 1) +#define PIN_PB19__PCK3 PINMUX_PIN(PIN_PB19, 3, 1) +#define PIN_PB19__D5 PINMUX_PIN(PIN_PB19, 4, 1) +#define PIN_PB19__PWMFI0 PINMUX_PIN(PIN_PB19, 5, 2) +#define PIN_PB20 52 +#define PIN_PB20__GPIO PINMUX_PIN(PIN_PB20, 0, 0) +#define PIN_PB20__QSPI0_DQS PINMUX_PIN(PIN_PB20, 1, 1) +#define PIN_PB20__FLEXCOM10_IO2 PINMUX_PIN(PIN_PB20, 2, 1) +#define PIN_PB20__D6 PINMUX_PIN(PIN_PB20, 4, 1) +#define PIN_PB20__PWMFI1 PINMUX_PIN(PIN_PB20, 5, 2) +#define PIN_PB21 53 +#define PIN_PB21__GPIO PINMUX_PIN(PIN_PB21, 0, 0) +#define PIN_PB21__QSPI0_INT PINMUX_PIN(PIN_PB21, 1, 1) +#define PIN_PB21__FLEXCOM10_IO3 PINMUX_PIN(PIN_PB21, 2, 1) +#define PIN_PB21__FLEXCOM9_IO5 PINMUX_PIN(PIN_PB21, 3, 1) +#define PIN_PB21__D7 PINMUX_PIN(PIN_PB21, 4, 1) +#define PIN_PB22 54 +#define PIN_PB22__GPIO PINMUX_PIN(PIN_PB22, 0, 0) +#define PIN_PB22__QSPI1_IO3 PINMUX_PIN(PIN_PB22, 1, 1) +#define PIN_PB22__FLEXCOM10_IO4 PINMUX_PIN(PIN_PB22, 2, 1) +#define PIN_PB22__FLEXCOM9_IO6 PINMUX_PIN(PIN_PB22, 3, 1) +#define PIN_PB22__NANDRDY PINMUX_PIN(PIN_PB22, 4, 1) +#define PIN_PB23 55 +#define PIN_PB23__GPIO PINMUX_PIN(PIN_PB23, 0, 0) +#define PIN_PB23__QSPI1_IO2 PINMUX_PIN(PIN_PB23, 1, 1) +#define PIN_PB23__FLEXCOM7_IO0 PINMUX_PIN(PIN_PB23, 2, 1) +#define PIN_PB23__I2SMCC0_CK PINMUX_PIN(PIN_PB23, 3, 1) +#define PIN_PB23__PCK4 PINMUX_PIN(PIN_PB23, 6, 1) +#define PIN_PB24 56 +#define PIN_PB24__GPIO PINMUX_PIN(PIN_PB24, 0, 0) +#define PIN_PB24__QSPI1_IO1 PINMUX_PIN(PIN_PB24, 1, 1) +#define PIN_PB24__FLEXCOM7_IO1 PINMUX_PIN(PIN_PB24, 2, 1) +#define PIN_PB24__I2SMCC0_WS PINMUX_PIN(PIN_PB24, 3, 1) +#define PIN_PB24__PCK5 PINMUX_PIN(PIN_PB24, 6, 1) +#define PIN_PB25 57 +#define PIN_PB25__GPIO PINMUX_PIN(PIN_PB25, 0, 0) +#define PIN_PB25__QSPI1_IO0 PINMUX_PIN(PIN_PB25, 1, 1) +#define PIN_PB25__FLEXCOM7_IO2 PINMUX_PIN(PIN_PB25, 2, 1) +#define PIN_PB25__I2SMCC0_DOUT1 PINMUX_PIN(PIN_PB25, 3, 1) +#define PIN_PB25__PCK6 PINMUX_PIN(PIN_PB25, 6, 1) +#define PIN_PB26 58 +#define PIN_PB26__GPIO PINMUX_PIN(PIN_PB26, 0, 0) +#define PIN_PB26__QSPI1_CS PINMUX_PIN(PIN_PB26, 1, 1) +#define PIN_PB26__FLEXCOM7_IO3 PINMUX_PIN(PIN_PB26, 2, 1) +#define PIN_PB26__I2SMCC0_DOUT0 PINMUX_PIN(PIN_PB26, 3, 1) +#define PIN_PB26__PWMEXTRG0 PINMUX_PIN(PIN_PB26, 5, 1) +#define PIN_PB26__PCK7 PINMUX_PIN(PIN_PB26, 6, 1) +#define PIN_PB27 59 +#define PIN_PB27__GPIO PINMUX_PIN(PIN_PB27, 0, 0) +#define PIN_PB27__QSPI1_SCK PINMUX_PIN(PIN_PB27, 1, 1) +#define PIN_PB27__FLEXCOM7_IO4 PINMUX_PIN(PIN_PB27, 2, 1) +#define PIN_PB27__I2SMCC0_MCK PINMUX_PIN(PIN_PB27, 3, 1) +#define PIN_PB27__PWMEXTRG1 PINMUX_PIN(PIN_PB27, 5, 1) +#define PIN_PB28 60 +#define PIN_PB28__GPIO PINMUX_PIN(PIN_PB28, 0, 0) +#define PIN_PB28__SDMMC1_RSTN PINMUX_PIN(PIN_PB28, 1, 1) +#define PIN_PB28__ADTRG PINMUX_PIN(PIN_PB28, 2, 2) +#define PIN_PB28__PWMFI0 PINMUX_PIN(PIN_PB28, 5, 1) +#define PIN_PB28__FLEXCOM7_IO0 PINMUX_PIN(PIN_PB28, 6, 4) +#define PIN_PB29 61 +#define PIN_PB29__GPIO PINMUX_PIN(PIN_PB29, 0, 0) +#define PIN_PB29__SDMMC1_CMD PINMUX_PIN(PIN_PB29, 1, 1) +#define PIN_PB29__FLEXCOM3_IO2 PINMUX_PIN(PIN_PB29, 2, 2) +#define PIN_PB29__FLEXCOM0_IO5 PINMUX_PIN(PIN_PB29, 3, 2) +#define PIN_PB29__TIOA3 PINMUX_PIN(PIN_PB29, 4, 2) +#define PIN_PB29__PWMFI1 PINMUX_PIN(PIN_PB29, 5, 1) +#define PIN_PB29__FLEXCOM7_IO1 PINMUX_PIN(PIN_PB29, 6, 4) +#define PIN_PB30 62 +#define PIN_PB30__GPIO PINMUX_PIN(PIN_PB30, 0, 0) +#define PIN_PB30__SDMMC1_CK PINMUX_PIN(PIN_PB30, 1, 1) +#define PIN_PB30__FLEXCOM3_IO3 PINMUX_PIN(PIN_PB30, 2, 2) +#define PIN_PB30__FLEXCOM0_IO6 PINMUX_PIN(PIN_PB30, 3, 2) +#define PIN_PB30__TIOB3 PINMUX_PIN(PIN_PB30, 4, 1) +#define PIN_PB30__PWMH0 PINMUX_PIN(PIN_PB30, 5, 1) +#define PIN_PB30__FLEXCOM8_IO0 PINMUX_PIN(PIN_PB30, 6, 4) +#define PIN_PB31 63 +#define PIN_PB31__GPIO PINMUX_PIN(PIN_PB31, 0, 0) +#define PIN_PB31__SDMMC1_DAT0 PINMUX_PIN(PIN_PB31, 1, 1) +#define PIN_PB31__FLEXCOM3_IO4 PINMUX_PIN(PIN_PB31, 2, 2) +#define PIN_PB31__FLEXCOM9_IO5 PINMUX_PIN(PIN_PB31, 3, 2) +#define PIN_PB31__TCLK3 PINMUX_PIN(PIN_PB31, 4, 1) +#define PIN_PB31__PWML0 PINMUX_PIN(PIN_PB31, 5, 1) +#define PIN_PB31__FLEXCOM8_IO1 PINMUX_PIN(PIN_PB31, 6, 4) +#define PIN_PC0 64 +#define PIN_PC0__GPIO PINMUX_PIN(PIN_PC0, 0, 0) +#define PIN_PC0__SDMMC1_DAT1 PINMUX_PIN(PIN_PC0, 1, 1) +#define PIN_PC0__FLEXCOM3_IO0 PINMUX_PIN(PIN_PC0, 2, 2) +#define PIN_PC0__TIOA4 PINMUX_PIN(PIN_PC0, 4, 1) +#define PIN_PC0__PWML1 PINMUX_PIN(PIN_PC0, 5, 1) +#define PIN_PC0__FLEXCOM9_IO0 PINMUX_PIN(PIN_PC0, 6, 4) +#define PIN_PC1 65 +#define PIN_PC1__GPIO PINMUX_PIN(PIN_PC1, 0, 0) +#define PIN_PC1__SDMMC1_DAT2 PINMUX_PIN(PIN_PC1, 1, 1) +#define PIN_PC1__FLEXCOM3_IO1 PINMUX_PIN(PIN_PC1, 2, 2) +#define PIN_PC1__TIOB4 PINMUX_PIN(PIN_PC1, 4, 1) +#define PIN_PC1__PWMH1 PINMUX_PIN(PIN_PC1, 5, 1) +#define PIN_PC1__FLEXCOM9_IO1 PINMUX_PIN(PIN_PC1, 6, 4) +#define PIN_PC2 66 +#define PIN_PC2__GPIO PINMUX_PIN(PIN_PC2, 0, 0) +#define PIN_PC2__SDMMC1_DAT3 PINMUX_PIN(PIN_PC2, 1, 1) +#define PIN_PC2__FLEXCOM4_IO0 PINMUX_PIN(PIN_PC2, 2, 2) +#define PIN_PC2__TCLK4 PINMUX_PIN(PIN_PC2, 4, 1) +#define PIN_PC2__PWML2 PINMUX_PIN(PIN_PC2, 5, 1) +#define PIN_PC2__FLEXCOM10_IO0 PINMUX_PIN(PIN_PC2, 6, 4) +#define PIN_PC3 67 +#define PIN_PC3__GPIO PINMUX_PIN(PIN_PC3, 0, 0) +#define PIN_PC3__SDMMC1_WP PINMUX_PIN(PIN_PC3, 1, 1) +#define PIN_PC3__FLEXCOM4_IO1 PINMUX_PIN(PIN_PC3, 2, 2) +#define PIN_PC3__TIOA5 PINMUX_PIN(PIN_PC3, 4, 1) +#define PIN_PC3__PWMH2 PINMUX_PIN(PIN_PC3, 5, 1) +#define PIN_PC3__FLEXCOM10_IO1 PINMUX_PIN(PIN_PC3, 6, 4) +#define PIN_PC4 68 +#define PIN_PC4__GPIO PINMUX_PIN(PIN_PC4, 0, 0) +#define PIN_PC4__SDMMC1_CD PINMUX_PIN(PIN_PC4, 1, 1) +#define PIN_PC4__FLEXCOM4_IO2 PINMUX_PIN(PIN_PC4, 2, 2) +#define PIN_PC4__FLEXCOM9_IO6 PINMUX_PIN(PIN_PC4, 3, 2) +#define PIN_PC4__TIOB5 PINMUX_PIN(PIN_PC4, 4, 1) +#define PIN_PC4__PWML3 PINMUX_PIN(PIN_PC4, 5, 1) +#define PIN_PC4__FLEXCOM11_IO0 PINMUX_PIN(PIN_PC4, 6, 4) +#define PIN_PC5 69 +#define PIN_PC5__GPIO PINMUX_PIN(PIN_PC5, 0, 0) +#define PIN_PC5__SDMMC1_1V8SEL PINMUX_PIN(PIN_PC5, 1, 1) +#define PIN_PC5__FLEXCOM4_IO3 PINMUX_PIN(PIN_PC5, 2, 2) +#define PIN_PC5__FLEXCOM6_IO5 PINMUX_PIN(PIN_PC5, 3, 2) +#define PIN_PC5__TCLK5 PINMUX_PIN(PIN_PC5, 4, 1) +#define PIN_PC5__PWMH3 PINMUX_PIN(PIN_PC5, 5, 1) +#define PIN_PC5__FLEXCOM11_IO1 PINMUX_PIN(PIN_PC5, 6, 4) +#define PIN_PC6 70 +#define PIN_PC6__GPIO PINMUX_PIN(PIN_PC6, 0, 0) +#define PIN_PC6__FLEXCOM4_IO4 PINMUX_PIN(PIN_PC6, 2, 2) +#define PIN_PC6__FLEXCOM6_IO6 PINMUX_PIN(PIN_PC6, 3, 2) +#define PIN_PC7 71 +#define PIN_PC7__GPIO PINMUX_PIN(PIN_PC7, 0, 0) +#define PIN_PC7__I2SMCC0_DIN0 PINMUX_PIN(PIN_PC7, 1, 1) +#define PIN_PC7__FLEXCOM7_IO0 PINMUX_PIN(PIN_PC7, 2, 2) +#define PIN_PC8 72 +#define PIN_PC8__GPIO PINMUX_PIN(PIN_PC8, 0, 0) +#define PIN_PC8__I2SMCC0_DIN1 PINMUX_PIN(PIN_PC8, 1, 1) +#define PIN_PC8__FLEXCOM7_IO1 PINMUX_PIN(PIN_PC8, 2, 2) +#define PIN_PC9 73 +#define PIN_PC9__GPIO PINMUX_PIN(PIN_PC9, 0, 0) +#define PIN_PC9__I2SMCC0_DOUT3 PINMUX_PIN(PIN_PC9, 1, 1) +#define PIN_PC9__FLEXCOM7_IO2 PINMUX_PIN(PIN_PC9, 2, 2) +#define PIN_PC9__FLEXCOM1_IO0 PINMUX_PIN(PIN_PC9, 6, 4) +#define PIN_PC10 74 +#define PIN_PC10__GPIO PINMUX_PIN(PIN_PC10, 0, 0) +#define PIN_PC10__I2SMCC0_DOUT2 PINMUX_PIN(PIN_PC10, 1, 1) +#define PIN_PC10__FLEXCOM7_IO3 PINMUX_PIN(PIN_PC10, 2, 2) +#define PIN_PC10__FLEXCOM1_IO1 PINMUX_PIN(PIN_PC10, 6, 4) +#define PIN_PC11 75 +#define PIN_PC11__GPIO PINMUX_PIN(PIN_PC11, 0, 0) +#define PIN_PC11__I2SMCC1_CK PINMUX_PIN(PIN_PC11, 1, 1) +#define PIN_PC11__FLEXCOM7_IO4 PINMUX_PIN(PIN_PC11, 2, 2) +#define PIN_PC11__FLEXCOM2_IO0 PINMUX_PIN(PIN_PC11, 6, 4) +#define PIN_PC12 76 +#define PIN_PC12__GPIO PINMUX_PIN(PIN_PC12, 0, 0) +#define PIN_PC12__I2SMCC1_WS PINMUX_PIN(PIN_PC12, 1, 1) +#define PIN_PC12__FLEXCOM8_IO2 PINMUX_PIN(PIN_PC12, 2, 2) +#define PIN_PC12__FLEXCOM2_IO1 PINMUX_PIN(PIN_PC12, 6, 4) +#define PIN_PC13 77 +#define PIN_PC13__GPIO PINMUX_PIN(PIN_PC13, 0, 0) +#define PIN_PC13__I2SMCC1_MCK PINMUX_PIN(PIN_PC13, 1, 1) +#define PIN_PC13__FLEXCOM8_IO1 PINMUX_PIN(PIN_PC13, 2, 2) +#define PIN_PC13__FLEXCOM3_IO0 PINMUX_PIN(PIN_PC13, 6, 4) +#define PIN_PC14 78 +#define PIN_PC14__GPIO PINMUX_PIN(PIN_PC14, 0, 0) +#define PIN_PC14__I2SMCC1_DOUT0 PINMUX_PIN(PIN_PC14, 1, 1) +#define PIN_PC14__FLEXCOM8_IO0 PINMUX_PIN(PIN_PC14, 2, 2) +#define PIN_PC14__FLEXCOM3_IO1 PINMUX_PIN(PIN_PC14, 6, 4) +#define PIN_PC15 79 +#define PIN_PC15__GPIO PINMUX_PIN(PIN_PC15, 0, 0) +#define PIN_PC15__I2SMCC1_DOUT1 PINMUX_PIN(PIN_PC15, 1, 1) +#define PIN_PC15__FLEXCOM8_IO3 PINMUX_PIN(PIN_PC15, 2, 2) +#define PIN_PC15__FLEXCOM4_IO0 PINMUX_PIN(PIN_PC15, 6, 4) +#define PIN_PC16 80 +#define PIN_PC16__GPIO PINMUX_PIN(PIN_PC16, 0, 0) +#define PIN_PC16__I2SMCC1_DOUT2 PINMUX_PIN(PIN_PC16, 1, 1) +#define PIN_PC16__FLEXCOM8_IO4 PINMUX_PIN(PIN_PC16, 2, 2) +#define PIN_PC16__FLEXCOM3_IO1 PINMUX_PIN(PIN_PC16, 6, 4) +#define PIN_PC17 81 +#define PIN_PC17__GPIO PINMUX_PIN(PIN_PC17, 0, 0) +#define PIN_PC17__I2SMCC1_DOUT3 PINMUX_PIN(PIN_PC17, 1, 1) +#define PIN_PC17__EXT_IRQ0 PINMUX_PIN(PIN_PC17, 2, 3) +#define PIN_PC17__FLEXCOM5_IO0 PINMUX_PIN(PIN_PC17, 6, 4) +#define PIN_PC18 82 +#define PIN_PC18__GPIO PINMUX_PIN(PIN_PC18, 0, 0) +#define PIN_PC18__I2SMCC1_DIN0 PINMUX_PIN(PIN_PC18, 1, 1) +#define PIN_PC18__FLEXCOM9_IO0 PINMUX_PIN(PIN_PC18, 2, 2) +#define PIN_PC18__FLEXCOM5_IO1 PINMUX_PIN(PIN_PC18, 6, 4) +#define PIN_PC19 83 +#define PIN_PC19__GPIO PINMUX_PIN(PIN_PC19, 0, 0) +#define PIN_PC19__I2SMCC1_DIN1 PINMUX_PIN(PIN_PC19, 1, 1) +#define PIN_PC19__FLEXCOM9_IO1 PINMUX_PIN(PIN_PC19, 2, 2) +#define PIN_PC19__FLEXCOM6_IO0 PINMUX_PIN(PIN_PC19, 6, 4) +#define PIN_PC20 84 +#define PIN_PC20__GPIO PINMUX_PIN(PIN_PC20, 0, 0) +#define PIN_PC20__I2SMCC1_DIN2 PINMUX_PIN(PIN_PC20, 1, 1) +#define PIN_PC20__FLEXCOM9_IO4 PINMUX_PIN(PIN_PC20, 2, 2) +#define PIN_PC20__FLEXCOM6_IO1 PINMUX_PIN(PIN_PC20, 6, 4) +#define PIN_PC21 85 +#define PIN_PC21__GPIO PINMUX_PIN(PIN_PC21, 0, 0) +#define PIN_PC21__I2SMCC1_DIN3 PINMUX_PIN(PIN_PC21, 1, 1) +#define PIN_PC21__FLEXCOM9_IO2 PINMUX_PIN(PIN_PC21, 2, 2) +#define PIN_PC21__D3 PINMUX_PIN(PIN_PC21, 4, 2) +#define PIN_PC21__FLEXCOM6_IO0 PINMUX_PIN(PIN_PC21, 6, 5) +#define PIN_PC22 86 +#define PIN_PC22__GPIO PINMUX_PIN(PIN_PC22, 0, 0) +#define PIN_PC22__I2SMCC0_DIN2 PINMUX_PIN(PIN_PC22, 1, 1) +#define PIN_PC22__FLEXCOM9_IO3 PINMUX_PIN(PIN_PC22, 2, 2) +#define PIN_PC22__D4 PINMUX_PIN(PIN_PC22, 4, 2) +#define PIN_PC22__FLEXCOM6_IO1 PINMUX_PIN(PIN_PC22, 6, 5) +#define PIN_PC23 87 +#define PIN_PC23__GPIO PINMUX_PIN(PIN_PC23, 0, 0) +#define PIN_PC23__I2SMCC0_DIN3 PINMUX_PIN(PIN_PC23, 1, 1) +#define PIN_PC23__FLEXCOM0_IO5 PINMUX_PIN(PIN_PC23, 2, 3) +#define PIN_PC23__D5 PINMUX_PIN(PIN_PC23, 4, 2) +#define PIN_PC23__FLEXCOM7_IO0 PINMUX_PIN(PIN_PC23, 6, 5) +#define PIN_PC24 88 +#define PIN_PC24__GPIO PINMUX_PIN(PIN_PC24, 0, 0) +#define PIN_PC24__FLEXCOM0_IO6 PINMUX_PIN(PIN_PC24, 2, 3) +#define PIN_PC24__EXT_IRQ1 PINMUX_PIN(PIN_PC24, 3, 3) +#define PIN_PC24__D6 PINMUX_PIN(PIN_PC24, 4, 2) +#define PIN_PC24__FLEXCOM7_IO1 PINMUX_PIN(PIN_PC24, 6, 5) +#define PIN_PC25 89 +#define PIN_PC25__GPIO PINMUX_PIN(PIN_PC25, 0, 0) +#define PIN_PC25__NTRST PINMUX_PIN(PIN_PC25, 1, 1) +#define PIN_PC26 90 +#define PIN_PC26__GPIO PINMUX_PIN(PIN_PC26, 0, 0) +#define PIN_PC26__TCK_SWCLK PINMUX_PIN(PIN_PC26, 1, 1) +#define PIN_PC27 91 +#define PIN_PC27__GPIO PINMUX_PIN(PIN_PC27, 0, 0) +#define PIN_PC27__TMS_SWDIO PINMUX_PIN(PIN_PC27, 1, 1) +#define PIN_PC28 92 +#define PIN_PC28__GPIO PINMUX_PIN(PIN_PC28, 0, 0) +#define PIN_PC28__TDI PINMUX_PIN(PIN_PC28, 1, 1) +#define PIN_PC29 93 +#define PIN_PC29__GPIO PINMUX_PIN(PIN_PC29, 0, 0) +#define PIN_PC29__TDO PINMUX_PIN(PIN_PC29, 1, 1) +#define PIN_PC30 94 +#define PIN_PC30__GPIO PINMUX_PIN(PIN_PC30, 0, 0) +#define PIN_PC30__FLEXCOM10_IO0 PINMUX_PIN(PIN_PC30, 2, 2) +#define PIN_PC31 95 +#define PIN_PC31__GPIO PINMUX_PIN(PIN_PC31, 0, 0) +#define PIN_PC31__FLEXCOM10_IO1 PINMUX_PIN(PIN_PC31, 2, 2) +#define PIN_PD0 96 +#define PIN_PD0__GPIO PINMUX_PIN(PIN_PD0, 0, 0) +#define PIN_PD0__FLEXCOM11_IO0 PINMUX_PIN(PIN_PD0, 2, 2) +#define PIN_PD1 97 +#define PIN_PD1__GPIO PINMUX_PIN(PIN_PD1, 0, 0) +#define PIN_PD1__FLEXCOM11_IO1 PINMUX_PIN(PIN_PD1, 2, 2) +#define PIN_PD2 98 +#define PIN_PD2__GPIO PINMUX_PIN(PIN_PD2, 0, 0) +#define PIN_PD2__SDMMC2_RSTN PINMUX_PIN(PIN_PD2, 1, 1) +#define PIN_PD2__PCK0 PINMUX_PIN(PIN_PD2, 2, 2) +#define PIN_PD2__CANTX4 PINMUX_PIN(PIN_PD2, 3, 1) +#define PIN_PD2__D7 PINMUX_PIN(PIN_PD2, 4, 2) +#define PIN_PD2__TIOA0 PINMUX_PIN(PIN_PD2, 5, 2) +#define PIN_PD2__FLEXCOM8_IO0 PINMUX_PIN(PIN_PD2, 6, 5) +#define PIN_PD3 99 +#define PIN_PD3__GPIO PINMUX_PIN(PIN_PD3, 0, 0) +#define PIN_PD3__SDMMC2_CMD PINMUX_PIN(PIN_PD3, 1, 1) +#define PIN_PD3__FLEXCOM0_IO0 PINMUX_PIN(PIN_PD3, 2, 2) +#define PIN_PD3__CANRX4 PINMUX_PIN(PIN_PD3, 3, 1) +#define PIN_PD3__NANDRDY PINMUX_PIN(PIN_PD3, 4, 2) +#define PIN_PD3__TIOB0 PINMUX_PIN(PIN_PD3, 5, 2) +#define PIN_PD3__FLEXCOM8_IO1 PINMUX_PIN(PIN_PD3, 6, 5) +#define PIN_PD4 100 +#define PIN_PD4__GPIO PINMUX_PIN(PIN_PD4, 0, 0) +#define PIN_PD4__SDMMC2_CK PINMUX_PIN(PIN_PD4, 1, 1) +#define PIN_PD4__FLEXCOM0_IO1 PINMUX_PIN(PIN_PD4, 2, 2) +#define PIN_PD4__CANTX5 PINMUX_PIN(PIN_PD4, 3, 1) +#define PIN_PD4__NCS3_NANDCS PINMUX_PIN(PIN_PD4, 4, 2) +#define PIN_PD4__TCLK0 PINMUX_PIN(PIN_PD4, 5, 2) +#define PIN_PD4__FLEXCOM9_IO0 PINMUX_PIN(PIN_PD4, 6, 5) +#define PIN_PD5 101 +#define PIN_PD5__GPIO PINMUX_PIN(PIN_PD5, 0, 0) +#define PIN_PD5__SDMMC2_DAT0 PINMUX_PIN(PIN_PD5, 1, 1) +#define PIN_PD5__FLEXCOM0_IO2 PINMUX_PIN(PIN_PD5, 2, 2) +#define PIN_PD5__CANRX5 PINMUX_PIN(PIN_PD5, 3, 1) +#define PIN_PD5__NWE_NWR0_NANDWE PINMUX_PIN(PIN_PD5, 4, 2) +#define PIN_PD5__TIOA1 PINMUX_PIN(PIN_PD5, 5, 2) +#define PIN_PD5__FLEXCOM9_IO1 PINMUX_PIN(PIN_PD5, 6, 5) +#define PIN_PD6 102 +#define PIN_PD6__GPIO PINMUX_PIN(PIN_PD6, 0, 0) +#define PIN_PD6__SDMMC2_DAT1 PINMUX_PIN(PIN_PD6, 1, 1) +#define PIN_PD6__FLEXCOM0_IO3 PINMUX_PIN(PIN_PD6, 2, 2) +#define PIN_PD6__SPDIF_RX PINMUX_PIN(PIN_PD6, 3, 3) +#define PIN_PD6__NRD_NANDOE PINMUX_PIN(PIN_PD6, 4, 2) +#define PIN_PD6__TIOB1 PINMUX_PIN(PIN_PD6, 5, 2) +#define PIN_PD6__FLEXCOM10_IO0 PINMUX_PIN(PIN_PD6, 6, 5) +#define PIN_PD7 103 +#define PIN_PD7__GPIO PINMUX_PIN(PIN_PD7, 0, 0) +#define PIN_PD7__SDMMC2_DAT2 PINMUX_PIN(PIN_PD7, 1, 1) +#define PIN_PD7__FLEXCOM0_IO4 PINMUX_PIN(PIN_PD7, 2, 2) +#define PIN_PD7__SPDIF_TX PINMUX_PIN(PIN_PD7, 2, 2) +#define PIN_PD7__A21_NANDALE PINMUX_PIN(PIN_PD7, 4, 2) +#define PIN_PD7__TCLK1 PINMUX_PIN(PIN_PD7, 5, 2) +#define PIN_PD7__FLEXCOM10_IO1 PINMUX_PIN(PIN_PD7, 6, 5) +#define PIN_PD8 104 +#define PIN_PD8__GPIO PINMUX_PIN(PIN_PD8, 0, 0) +#define PIN_PD8__SDMMC2_DAT3 PINMUX_PIN(PIN_PD8, 1, 1) +#define PIN_PD8__I2SMCC0_DIN0 PINMUX_PIN(PIN_PD8, 3, 1) +#define PIN_PD8__A11_NANDCLE PINMUX_PIN(PIN_PD8, 4, 2) +#define PIN_PD8__TIOA2 PINMUX_PIN(PIN_PD8, 5, 2) +#define PIN_PD8__FLEXCOM11_IO0 PINMUX_PIN(PIN_PD8, 6, 5) +#define PIN_PD9 105 +#define PIN_PD9__GPIO PINMUX_PIN(PIN_PD9, 0, 0) +#define PIN_PD9__SDMMC2_WP PINMUX_PIN(PIN_PD9, 1, 1) +#define PIN_PD9__I2SMCC0_DIN1 PINMUX_PIN(PIN_PD9, 3, 2) +#define PIN_PD9__D0 PINMUX_PIN(PIN_PD9, 4, 2) +#define PIN_PD9__TIOB2 PINMUX_PIN(PIN_PD9, 5, 2) +#define PIN_PD9__FLEXCOM11_IO1 PINMUX_PIN(PIN_PD9, 6, 5) +#define PIN_PD10 106 +#define PIN_PD10__GPIO PINMUX_PIN(PIN_PD10, 0, 0) +#define PIN_PD10__SDMMC2_CD PINMUX_PIN(PIN_PD10, 1, 1) +#define PIN_PD10__PCK6 PINMUX_PIN(PIN_PD10, 2, 2) +#define PIN_PD10__I2SMCC0_DIN2 PINMUX_PIN(PIN_PD10, 3, 2) +#define PIN_PD10__D1 PINMUX_PIN(PIN_PD10, 4, 2) +#define PIN_PD10__TCLK2 PINMUX_PIN(PIN_PD10, 5, 2) +#define PIN_PD10__FLEXCOM0_IO0 PINMUX_PIN(PIN_PD10, 6, 3) +#define PIN_PD11 107 +#define PIN_PD11__GPIO PINMUX_PIN(PIN_PD11, 0, 0) +#define PIN_PD11__SDMMC2_1V8SEL PINMUX_PIN(PIN_PD11, 1, 1) +#define PIN_PD11__PCK7 PINMUX_PIN(PIN_PD11, 2, 2) +#define PIN_PD11__I2SMCC0_DIN3 PINMUX_PIN(PIN_PD11, 3, 2) +#define PIN_PD11__D2 PINMUX_PIN(PIN_PD11, 4, 2) +#define PIN_PD11__TIOA3 PINMUX_PIN(PIN_PD11, 5, 2) +#define PIN_PD11__FLEXCOM0_IO1 PINMUX_PIN(PIN_PD11, 6, 3) +#define PIN_PD12 108 +#define PIN_PD12__GPIO PINMUX_PIN(PIN_PD12, 0, 0) +#define PIN_PD12__PCK1 PINMUX_PIN(PIN_PD12, 1, 2) +#define PIN_PD12__FLEXCOM1_IO0 PINMUX_PIN(PIN_PD12, 2, 2) +#define PIN_PD12__CANTX0 PINMUX_PIN(PIN_PD12, 4, 2) +#define PIN_PD12__TIOB3 PINMUX_PIN(PIN_PD12, 5, 2) +#define PIN_PD13 109 +#define PIN_PD13__GPIO PINMUX_PIN(PIN_PD13, 0, 0) +#define PIN_PD13__I2SMCC0_CK PINMUX_PIN(PIN_PD13, 1, 2) +#define PIN_PD13__FLEXCOM1_IO1 PINMUX_PIN(PIN_PD13, 2, 2) +#define PIN_PD13__PWML0 PINMUX_PIN(PIN_PD13, 3, 4) +#define PIN_PD13__CANRX0 PINMUX_PIN(PIN_PD13, 4, 2) +#define PIN_PD13__TCLK3 PINMUX_PIN(PIN_PD13, 5, 2) +#define PIN_PD14 110 +#define PIN_PD14__GPIO PINMUX_PIN(PIN_PD14, 0, 0) +#define PIN_PD14__I2SMCC0_MCK PINMUX_PIN(PIN_PD14, 1, 2) +#define PIN_PD14__FLEXCOM1_IO2 PINMUX_PIN(PIN_PD14, 2, 2) +#define PIN_PD14__PWMH0 PINMUX_PIN(PIN_PD14, 3, 4) +#define PIN_PD14__CANTX1 PINMUX_PIN(PIN_PD14, 4, 2) +#define PIN_PD14__TIOA4 PINMUX_PIN(PIN_PD14, 5, 2) +#define PIN_PD14__FLEXCOM2_IO0 PINMUX_PIN(PIN_PD14, 6, 5) +#define PIN_PD15 111 +#define PIN_PD15__GPIO PINMUX_PIN(PIN_PD15, 0, 0) +#define PIN_PD15__I2SMCC0_WS PINMUX_PIN(PIN_PD15, 1, 2) +#define PIN_PD15__FLEXCOM1_IO3 PINMUX_PIN(PIN_PD15, 2, 2) +#define PIN_PD15__PWML1 PINMUX_PIN(PIN_PD15, 3, 4) +#define PIN_PD15__CANRX1 PINMUX_PIN(PIN_PD15, 4, 2) +#define PIN_PD15__TIOB4 PINMUX_PIN(PIN_PD15, 5, 2) +#define PIN_PD15__FLEXCOM2_IO1 PINMUX_PIN(PIN_PD15, 6, 5) +#define PIN_PD16 112 +#define PIN_PD16__GPIO PINMUX_PIN(PIN_PD16, 0, 0) +#define PIN_PD16__I2SMCC0_DOUT0 PINMUX_PIN(PIN_PD16, 1, 2) +#define PIN_PD16__FLEXCOM1_IO4 PINMUX_PIN(PIN_PD16, 2, 2) +#define PIN_PD16__PWMH1 PINMUX_PIN(PIN_PD16, 3, 4) +#define PIN_PD16__CANTX2 PINMUX_PIN(PIN_PD16, 4, 2) +#define PIN_PD16__TCLK4 PINMUX_PIN(PIN_PD16, 5, 2) +#define PIN_PD16__FLEXCOM3_IO0 PINMUX_PIN(PIN_PD16, 6, 5) +#define PIN_PD17 113 +#define PIN_PD17__GPIO PINMUX_PIN(PIN_PD17, 0, 0) +#define PIN_PD17__I2SMCC0_DOUT1 PINMUX_PIN(PIN_PD17, 1, 2) +#define PIN_PD17__FLEXCOM2_IO0 PINMUX_PIN(PIN_PD17, 2, 2) +#define PIN_PD17__PWML2 PINMUX_PIN(PIN_PD17, 3, 4) +#define PIN_PD17__CANRX2 PINMUX_PIN(PIN_PD17, 4, 2) +#define PIN_PD17__TIOA5 PINMUX_PIN(PIN_PD17, 5, 2) +#define PIN_PD17__FLEXCOM3_IO1 PINMUX_PIN(PIN_PD17, 6, 5) +#define PIN_PD18 114 +#define PIN_PD18__GPIO PINMUX_PIN(PIN_PD18, 0, 0) +#define PIN_PD18__I2SMCC0_DOUT2 PINMUX_PIN(PIN_PD18, 1, 2) +#define PIN_PD18__FLEXCOM2_IO1 PINMUX_PIN(PIN_PD18, 2, 2) +#define PIN_PD18__PWMH2 PINMUX_PIN(PIN_PD18, 3, 4) +#define PIN_PD18__CANTX3 PINMUX_PIN(PIN_PD18, 4, 2) +#define PIN_PD18__TIOB5 PINMUX_PIN(PIN_PD18, 5, 2) +#define PIN_PD18__FLEXCOM4_IO0 PINMUX_PIN(PIN_PD18, 6, 5) +#define PIN_PD19 115 +#define PIN_PD19__GPIO PINMUX_PIN(PIN_PD19, 0, 0) +#define PIN_PD19__I2SMCC0_DOUT3 PINMUX_PIN(PIN_PD19, 1, 2) +#define PIN_PD19__FLEXCOM2_IO2 PINMUX_PIN(PIN_PD19, 2, 2) +#define PIN_PD19__PWML3 PINMUX_PIN(PIN_PD19, 3, 4) +#define PIN_PD19__CANRX3 PINMUX_PIN(PIN_PD19, 4, 2) +#define PIN_PD19__TCLK5 PINMUX_PIN(PIN_PD19, 5, 2) +#define PIN_PD19__FLEXCOM4_IO1 PINMUX_PIN(PIN_PD19, 6, 5) +#define PIN_PD20 116 +#define PIN_PD20__GPIO PINMUX_PIN(PIN_PD20, 0, 0) +#define PIN_PD20__PCK0 PINMUX_PIN(PIN_PD20, 1, 3) +#define PIN_PD20__FLEXCOM2_IO3 PINMUX_PIN(PIN_PD20, 2, 2) +#define PIN_PD20__PWMH3 PINMUX_PIN(PIN_PD20, 3, 4) +#define PIN_PD20__CANTX4 PINMUX_PIN(PIN_PD20, 4, 2) +#define PIN_PD20__FLEXCOM5_IO0 PINMUX_PIN(PIN_PD20, 6, 5) +#define PIN_PD21 117 +#define PIN_PD21__GPIO PINMUX_PIN(PIN_PD21, 0, 0) +#define PIN_PD21__PCK1 PINMUX_PIN(PIN_PD21, 1, 3) +#define PIN_PD21__FLEXCOM2_IO4 PINMUX_PIN(PIN_PD21, 2, 2) +#define PIN_PD21__CANRX4 PINMUX_PIN(PIN_PD21, 4, 2) +#define PIN_PD21__FLEXCOM5_IO1 PINMUX_PIN(PIN_PD21, 6, 5) +#define PIN_PD21__G1_TXEN PINMUX_PIN(PIN_PD21, 7, 1) +#define PIN_PD22 118 +#define PIN_PD22__GPIO PINMUX_PIN(PIN_PD22, 0, 0) +#define PIN_PD22__PDMC0_CLK PINMUX_PIN(PIN_PD22, 1, 2) +#define PIN_PD22__PWMEXTRG0 PINMUX_PIN(PIN_PD22, 3, 4) +#define PIN_PD22__RD1 PINMUX_PIN(PIN_PD22, 4, 2) +#define PIN_PD22__CANTX5 PINMUX_PIN(PIN_PD22, 6, 2) +#define PIN_PD22__G1_TX0 PINMUX_PIN(PIN_PD22, 7, 1) +#define PIN_PD23 119 +#define PIN_PD23__GPIO PINMUX_PIN(PIN_PD23, 0, 0) +#define PIN_PD23__PDMC0_DS0 PINMUX_PIN(PIN_PD23, 1, 2) +#define PIN_PD23__PWMEXTRG1 PINMUX_PIN(PIN_PD23, 3, 4) +#define PIN_PD23__RF1 PINMUX_PIN(PIN_PD23, 4, 2) +#define PIN_PD23__ISC_MCK PINMUX_PIN(PIN_PD23, 5, 2) +#define PIN_PD23__CANRX5 PINMUX_PIN(PIN_PD23, 6, 2) +#define PIN_PD23__G1_TX1 PINMUX_PIN(PIN_PD23, 7, 1) +#define PIN_PD24 120 +#define PIN_PD24__GPIO PINMUX_PIN(PIN_PD24, 0, 0) +#define PIN_PD24__PDMC0_DS1 PINMUX_PIN(PIN_PD24, 1, 2) +#define PIN_PD24__PWMFI0 PINMUX_PIN(PIN_PD24, 3, 4) +#define PIN_PD24__RK1 PINMUX_PIN(PIN_PD24, 4, 2) +#define PIN_PD24__ISC_D0 PINMUX_PIN(PIN_PD24, 5, 2) +#define PIN_PD24__G1_RXDV PINMUX_PIN(PIN_PD24, 7, 1) +#define PIN_PD25 121 +#define PIN_PD25__GPIO PINMUX_PIN(PIN_PD25, 0, 0) +#define PIN_PD25__PDMC1_CLK PINMUX_PIN(PIN_PD25, 1, 2) +#define PIN_PD25__FLEXCOM5_IO0 PINMUX_PIN(PIN_PD25, 2, 2) +#define PIN_PD25__PWMFI1 PINMUX_PIN(PIN_PD25, 3, 4) +#define PIN_PD25__TD1 PINMUX_PIN(PIN_PD25, 4, 2) +#define PIN_PD25__ISC_D1 PINMUX_PIN(PIN_PD25, 5, 2) +#define PIN_PD25__G1_RX0 PINMUX_PIN(PIN_PD25, 7, 1) +#define PIN_PD26 122 +#define PIN_PD26__GPIO PINMUX_PIN(PIN_PD26, 0, 0) +#define PIN_PD26__PDMC1_DS0 PINMUX_PIN(PIN_PD26, 1, 2) +#define PIN_PD26__FLEXCOM5_IO1 PINMUX_PIN(PIN_PD26, 2, 2) +#define PIN_PD26__ADTRG PINMUX_PIN(PIN_PD26, 3, 3) +#define PIN_PD26__TF1 PINMUX_PIN(PIN_PD26, 4, 2) +#define PIN_PD26__ISC_D2 PINMUX_PIN(PIN_PD26, 5, 2) +#define PIN_PD26__G1_RX1 PINMUX_PIN(PIN_PD26, 7, 1) +#define PIN_PD27 123 +#define PIN_PD27__GPIO PINMUX_PIN(PIN_PD27, 0, 0) +#define PIN_PD27__PDMC1_DS1 PINMUX_PIN(PIN_PD27, 1, 2) +#define PIN_PD27__FLEXCOM5_IO2 PINMUX_PIN(PIN_PD27, 2, 2) +#define PIN_PD27__TIOA0 PINMUX_PIN(PIN_PD27, 3, 3) +#define PIN_PD27__TK1 PINMUX_PIN(PIN_PD27, 4, 2) +#define PIN_PD27__ISC_D3 PINMUX_PIN(PIN_PD27, 5, 2) +#define PIN_PD27__G1_RXER PINMUX_PIN(PIN_PD27, 7, 1) +#define PIN_PD28 124 +#define PIN_PD28__GPIO PINMUX_PIN(PIN_PD28, 0, 0) +#define PIN_PD28__RD0 PINMUX_PIN(PIN_PD28, 1, 2) +#define PIN_PD28__FLEXCOM5_IO3 PINMUX_PIN(PIN_PD28, 2, 2) +#define PIN_PD28__TIOB0 PINMUX_PIN(PIN_PD28, 3, 3) +#define PIN_PD28__I2SMCC1_CK PINMUX_PIN(PIN_PD28, 4, 2) +#define PIN_PD28__ISC_D4 PINMUX_PIN(PIN_PD28, 5, 2) +#define PIN_PD28__PWML3 PINMUX_PIN(PIN_PD28, 6, 5) +#define PIN_PD28__G1_MDC PINMUX_PIN(PIN_PD28, 7, 1) +#define PIN_PD29 125 +#define PIN_PD29__GPIO PINMUX_PIN(PIN_PD29, 0, 0) +#define PIN_PD29__RF0 PINMUX_PIN(PIN_PD29, 1, 2) +#define PIN_PD29__FLEXCOM5_IO4 PINMUX_PIN(PIN_PD29, 2, 2) +#define PIN_PD29__TCLK0 PINMUX_PIN(PIN_PD29, 3, 3) +#define PIN_PD29__I2SMCC1_WS PINMUX_PIN(PIN_PD29, 4, 2) +#define PIN_PD29__ISC_D5 PINMUX_PIN(PIN_PD29, 5, 2) +#define PIN_PD29__PWMH3 PINMUX_PIN(PIN_PD29, 6, 5) +#define PIN_PD29__G1_MDIO PINMUX_PIN(PIN_PD29, 7, 1) +#define PIN_PD30 126 +#define PIN_PD30__GPIO PINMUX_PIN(PIN_PD30, 0, 0) +#define PIN_PD30__RK0 PINMUX_PIN(PIN_PD30, 1, 2) +#define PIN_PD30__FLEXCOM6_IO0 PINMUX_PIN(PIN_PD30, 2, 2) +#define PIN_PD30__TIOA1 PINMUX_PIN(PIN_PD30, 3, 3) +#define PIN_PD30__I2SMCC1_MCK PINMUX_PIN(PIN_PD30, 4, 2) +#define PIN_PD30__ISC_D6 PINMUX_PIN(PIN_PD30, 5, 2) +#define PIN_PD30__PWMEXTRG0 PINMUX_PIN(PIN_PD30, 6, 5) +#define PIN_PD30__G1_TXCK PINMUX_PIN(PIN_PD30, 7, 1) +#define PIN_PD31 127 +#define PIN_PD31__GPIO PINMUX_PIN(PIN_PD31, 0, 0) +#define PIN_PD31__TD0 PINMUX_PIN(PIN_PD31, 1, 2) +#define PIN_PD31__FLEXCOM6_IO1 PINMUX_PIN(PIN_PD31, 2, 2) +#define PIN_PD31__TIOB1 PINMUX_PIN(PIN_PD31, 3, 3) +#define PIN_PD31__I2SMCC1_DOUT0 PINMUX_PIN(PIN_PD31, 4, 2) +#define PIN_PD31__ISC_D7 PINMUX_PIN(PIN_PD31, 5, 2) +#define PIN_PD31__PWM_EXTRG1 PINMUX_PIN(PIN_PD31, 6, 5) +#define PIN_PD31__G1_TX2 PINMUX_PIN(PIN_PD31, 7, 1) +#define PIN_PE0 128 +#define PIN_PE0__GPIO PINMUX_PIN(PIN_PE0, 0, 0) +#define PIN_PE0__TF0 PINMUX_PIN(PIN_PE0, 1, 2) +#define PIN_PE0__FLEXCOM6_IO2 PINMUX_PIN(PIN_PE0, 2, 2) +#define PIN_PE0__TCLK1 PINMUX_PIN(PIN_PE0, 3, 3) +#define PIN_PE0__I2SMCC1_DOUT1 PINMUX_PIN(PIN_PE0, 4, 2) +#define PIN_PE0__ISC_HSYNC PINMUX_PIN(PIN_PE0, 5, 2) +#define PIN_PE0__PWMFI0 PINMUX_PIN(PIN_PE0, 6, 5) +#define PIN_PE0__G1_TX3 PINMUX_PIN(PIN_PE0, 7, 1) +#define PIN_PE1 129 +#define PIN_PE1__GPIO PINMUX_PIN(PIN_PE1, 0, 0) +#define PIN_PE1__TK0 PINMUX_PIN(PIN_PE1, 1, 2) +#define PIN_PE1__FLEXCOM6_IO3 PINMUX_PIN(PIN_PE1, 2, 2) +#define PIN_PE1__TIOA2 PINMUX_PIN(PIN_PE1, 3, 3) +#define PIN_PE1__I2SMCC1_DOUT2 PINMUX_PIN(PIN_PE1, 4, 2) +#define PIN_PE1__ISC_VSYNC PINMUX_PIN(PIN_PE1, 5, 2) +#define PIN_PE1__PWMFI1 PINMUX_PIN(PIN_PE1, 6, 5) +#define PIN_PE1__G1_RX2 PINMUX_PIN(PIN_PE1, 7, 1) +#define PIN_PE2 130 +#define PIN_PE2__GPIO PINMUX_PIN(PIN_PE2, 0, 0) +#define PIN_PE2__PWML0 PINMUX_PIN(PIN_PE2, 1, 5) +#define PIN_PE2__FLEXCOM6_IO4 PINMUX_PIN(PIN_PE2, 2, 2) +#define PIN_PE2__TIOB2 PINMUX_PIN(PIN_PE2, 3, 3) +#define PIN_PE2__I2SMCC1_DOUT3 PINMUX_PIN(PIN_PE2, 4, 2) +#define PIN_PE2__ISC_FIELD PINMUX_PIN(PIN_PE2, 5, 2) +#define PIN_PE2__G1_RX3 PINMUX_PIN(PIN_PE2, 7, 1) +#define PIN_PE3 131 +#define PIN_PE3__GPIO PINMUX_PIN(PIN_PE3, 0, 0) +#define PIN_PE3__PWMH0 PINMUX_PIN(PIN_PE3, 1, 5) +#define PIN_PE3__FLEXCOM0_IO0 PINMUX_PIN(PIN_PE3, 2, 4) +#define PIN_PE3__TCLK2 PINMUX_PIN(PIN_PE3, 3, 3) +#define PIN_PE3__I2SMCC1_DIN0 PINMUX_PIN(PIN_PE3, 4, 2) +#define PIN_PE3__ISC_PCK PINMUX_PIN(PIN_PE3, 5, 2) +#define PIN_PE3__G1_RXCK PINMUX_PIN(PIN_PE3, 7, 1) +#define PIN_PE4 132 +#define PIN_PE4__GPIO PINMUX_PIN(PIN_PE4, 0, 0) +#define PIN_PE4__PWML1 PINMUX_PIN(PIN_PE4, 1, 5) +#define PIN_PE4__FLEXCOM0_IO1 PINMUX_PIN(PIN_PE4, 2, 4) +#define PIN_PE4__TIOA3 PINMUX_PIN(PIN_PE4, 3, 3) +#define PIN_PE4__I2SMCC1_DIN1 PINMUX_PIN(PIN_PE4, 4, 2) +#define PIN_PE4__ISC_D8 PINMUX_PIN(PIN_PE4, 5, 2) +#define PIN_PE4__G1_TXER PINMUX_PIN(PIN_PE4, 7, 1) +#define PIN_PE5 133 +#define PIN_PE5__GPIO PINMUX_PIN(PIN_PE5, 0, 0) +#define PIN_PE5__PWMH1 PINMUX_PIN(PIN_PE5, 1, 5) +#define PIN_PE5__FLEXCOM0_IO2 PINMUX_PIN(PIN_PE5, 2, 4) +#define PIN_PE5__TIOB3 PINMUX_PIN(PIN_PE5, 3, 3) +#define PIN_PE5__I2SMCC1_DIN2 PINMUX_PIN(PIN_PE5, 4, 2) +#define PIN_PE5__ISC_D9 PINMUX_PIN(PIN_PE5, 5, 2) +#define PIN_PE5__G1_COL PINMUX_PIN(PIN_PE5, 7, 1) +#define PIN_PE6 134 +#define PIN_PE6__GPIO PINMUX_PIN(PIN_PE6, 0, 0) +#define PIN_PE6__PWML2 PINMUX_PIN(PIN_PE6, 1, 5) +#define PIN_PE6__FLEXCOM0_IO3 PINMUX_PIN(PIN_PE6, 2, 4) +#define PIN_PE6__TCLK3 PINMUX_PIN(PIN_PE6, 3, 3) +#define PIN_PE6__I2SMCC1_DIN3 PINMUX_PIN(PIN_PE6, 4, 2) +#define PIN_PE6__ISC_D10 PINMUX_PIN(PIN_PE6, 5, 2) +#define PIN_PE6__G1_CRS PINMUX_PIN(PIN_PE6, 7, 1) +#define PIN_PE7 135 +#define PIN_PE7__GPIO PINMUX_PIN(PIN_PE7, 0, 0) +#define PIN_PE7__PWMH2 PINMUX_PIN(PIN_PE7, 1, 5) +#define PIN_PE7__FLEXCOM0_IO4 PINMUX_PIN(PIN_PE7, 2, 4) +#define PIN_PE7__TIOA4 PINMUX_PIN(PIN_PE7, 3, 3) +#define PIN_PE7__ISC_D11 PINMUX_PIN(PIN_PE7, 5, 2) +#define PIN_PE7__G1_TSUCOMP PINMUX_PIN(PIN_PE7, 7, 1) diff --git a/optee/optee_os/core/arch/arm/dts/sama7g5.dtsi b/optee/optee_os/core/arch/arm/dts/sama7g5.dtsi new file mode 100644 index 0000000..309449c --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/sama7g5.dtsi @@ -0,0 +1,1219 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * sama7g5.dtsi - Device Tree Include file for SAMA7G5 family SoC + * + * Copyright (C) 2020 Microchip Technology, Inc. and its subsidiaries + * + * Author: Eugen Hristev + * Author: Claudiu Beznea + */ + +#include +#include +#include +#include +#include +#include + +/ { + model = "Microchip SAMA7G5 family SoC"; + compatible = "microchip,sama7g5"; + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <&gic>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a7"; + reg = <0x0>; + clocks = <&pmc PMC_TYPE_CORE PMC_CPUPLL>; + clock-names = "cpu"; + operating-points-v2 = <&cpu_opp_table>; + #cooling-cells = <2>; /* min followed by max */ + }; + }; + + cpu_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-90000000 { + opp-hz = /bits/ 64 <90000000>; + opp-microvolt = <1050000 1050000 1225000>; + clock-latency-ns = <320000>; + }; + + opp-250000000 { + opp-hz = /bits/ 64 <250000000>; + opp-microvolt = <1050000 1050000 1225000>; + clock-latency-ns = <320000>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + opp-microvolt = <1050000 1050000 1225000>; + clock-latency-ns = <320000>; + opp-suspend; + }; + + opp-800000000 { + opp-hz = /bits/ 64 <800000000>; + opp-microvolt = <1150000 1125000 1225000>; + clock-latency-ns = <320000>; + }; + + opp-1000000002 { + opp-hz = /bits/ 64 <1000000002>; + opp-microvolt = <1250000 1225000 1300000>; + clock-latency-ns = <320000>; + }; + }; + + thermal-zones { + cpu_thermal: cpu-thermal { + polling-delay-passive = <1000>; + polling-delay = <5000>; + thermal-sensors = <&thermal_sensor>; + + trips { + cpu_normal: cpu-alert0 { + temperature = <90000>; + hysteresis = <0>; + type = "passive"; + }; + + cpu_hot: cpu-alert1 { + temperature = <95000>; + hysteresis = <0>; + type = "passive"; + }; + + cpu_critical: cpu-critical { + temperature = <100000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&cpu_normal>; + }; + + map1 { + trip = <&cpu_hot>; + }; + }; + }; + }; + + clocks { + slow_xtal: slow_xtal { + compatible = "fixed-clock"; + #clock-cells = <0>; + }; + + main_xtal: main_xtal { + compatible = "fixed-clock"; + #clock-cells = <0>; + }; + + usb_clk: usb_clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <48000000>; + }; + }; + + utmi_clk: utmi-clk { + compatible = "microchip,sama7g5-utmi-clk"; + sfr-phandle = <&sfr>; + #clock-cells = <1>; + clocks = <&pmc PMC_TYPE_CORE PMC_UTMI>; + clock-names = "utmi_clk"; + reset-names = "usb0_reset", "usb1_reset", "usb2_reset"; + status = "disabled"; + }; + + utmi { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <0>; + + usb_phy0: phy@0 { + compatible = "microchip,sama7g5-usb-phy"; + sfr-phandle = <&sfr>; + reg = <0>; + clock-names = "utmi_clk"; + status = "disabled"; + #phy-cells = <0>; + }; + + usb_phy1: phy@1 { + compatible = "microchip,sama7g5-usb-phy"; + sfr-phandle = <&sfr>; + reg = <1>; + clock-names = "utmi_clk"; + status = "disabled"; + #phy-cells = <0>; + }; + + usb_phy2: phy@2 { + compatible = "microchip,sama7g5-usb-phy"; + sfr-phandle = <&sfr>; + reg = <2>; + clock-names = "utmi_clk"; + status = "disabled"; + #phy-cells = <0>; + }; + }; + + vddout25: fixed-regulator-vddout25 { + compatible = "regulator-fixed"; + + regulator-name = "VDDOUT25"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + regulator-boot-on; + status = "disabled"; + }; + + ns_sram: sram@100000 { + compatible = "atmel,sama5d2-sram", "mmio-sram"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x100000 0x3400>; + ranges; + status = "disabled"; + secure-status = "okay"; + }; + + thermal_sensor: thermal-sensor { + compatible = "generic-adc-thermal"; + #thermal-sensor-cells = <0>; + io-channel-names = "sensor-channel"; + status = "disabled"; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + usb0: gadget@200000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "microchip,sama7g5-udc"; + reg = <0x00200000 0x100000 + 0xe0814000 0x400>; + interrupts = ; + clocks = <&pmc PMC_TYPE_PERIPHERAL 104>, <&usb_clk>; + clock-names = "pclk", "hclk"; + status = "disabled"; + }; + + usb1: gadget@300000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "microchip,sama7g5-udc"; + reg = <0x00300000 0x100000 + 0xe0818000 0x400>; + interrupts = ; + clocks = <&pmc PMC_TYPE_PERIPHERAL 105>, <&usb_clk>; + clock-names = "pclk", "hclk"; + status = "disabled"; + }; + + usb2: ohci@400000 { + compatible = "microchip,sama7g5-ohci", "usb-ohci"; + reg = <0x00400000 0x100000>; + interrupts = ; + clock-names = "ohci_clk", "hclk", "uhpck"; + status = "disabled"; + }; + + usb3: ehci@500000 { + compatible = "atmel,at91sam9g45-ehci", "usb-ehci"; + reg = <0x00500000 0x100000>; + interrupts = ; + clocks = <&usb_clk>, <&pmc PMC_TYPE_PERIPHERAL 106>; + clock-names = "usb_clk", "ehci_clk"; + status = "disabled"; + }; + + nfc_sram: sram@600000 { + compatible = "mmio-sram"; + no-memory-wc; + reg = <0x00600000 0x2400>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x00600000 0x2400>; + }; + + nfc_io: nfc-io@10000000 { + compatible = "atmel,sama5d3-nfc-io", "syscon"; + reg = <0x10000000 0x8000000>; + }; + + ebi: ebi@40000000 { + compatible = "atmel,sama5d3-ebi"; + #address-cells = <2>; + #size-cells = <1>; + atmel,smc = <&hsmc>; + reg = <0x40000000 0x20000000>; + ranges = <0x0 0x0 0x40000000 0x8000000 + 0x1 0x0 0x48000000 0x8000000 + 0x2 0x0 0x50000000 0x8000000 + 0x3 0x0 0x58000000 0x8000000>; + clocks = <&pmc PMC_TYPE_CORE PMC_MCK1>; + 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"; + }; + }; + + securam: sram@e0000000 { + compatible = "microchip,sama7g5-securam", "atmel,sama5d2-securam", "mmio-sram"; + reg = <0xe0000000 0x4000>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 18>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0xe0000000 0x4000>; + no-memory-wc; + status = "disabled"; + secure-status = "okay"; + }; + + secumod: secumod@e0004000 { + compatible = "microchip,sama7g5-secumod", "atmel,sama5d2-secumod", "syscon"; + reg = <0xe0004000 0x4000>; + gpio-controller; + #gpio-cells = <2>; + status = "disabled"; + secure-status = "okay"; + }; + + sfrbu: sfr@e0008000 { + compatible = "microchip,sama7g5-sfrbu", "atmel,sama5d2-sfrbu", "syscon"; + reg = <0xe0008000 0x20>; + }; + + pioA: pinctrl@e0014000 { + compatible = "microchip,sama7g5-pinctrl"; + reg = <0xe0014000 0x800>; + interrupts = , + , + , + , + ; + interrupt-controller; + #interrupt-cells = <2>; + gpio-controller; + #gpio-cells = <2>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 11>; + status = "disabled"; + secure-status = "okay"; + }; + + pmc: pmc@e0018000 { + compatible = "microchip,sama7g5-pmc", "syscon"; + reg = <0xe0018000 0x200>; + interrupts = ; + #clock-cells = <2>; + clocks = <&clk32k 1>, <&clk32k 0>, <&main_xtal>; + clock-names = "td_slck", "md_slck", "main_xtal"; + status = "disabled"; + secure-status = "okay"; + }; + + reset_controller: reset-controller@e001d000 { + compatible = "microchip,sama7g5-rstc"; + reg = <0xe001d000 0xc>, <0xe001d0e4 0x4>; + #reset-cells = <1>; + clocks = <&clk32k 0>; + status = "disabled"; + secure-status = "okay"; + }; + + shdwc: shdwc@e001d010 { + compatible = "microchip,sama7g5-shdwc", "syscon"; + reg = <0xe001d010 0x10>; + clocks = <&clk32k 0>; + #address-cells = <1>; + #size-cells = <0>; + atmel,wakeup-rtc-timer; + atmel,wakeup-rtt-timer; + status = "disabled"; + secure-status = "okay"; + }; + + rtt: rtc@e001d020 { + compatible = "microchip,sama7g5-rtt", "microchip,sam9x60-rtt", "atmel,at91sam9260-rtt"; + reg = <0xe001d020 0x30>; + interrupts = ; + clocks = <&clk32k 0>; + }; + + clk32k: clock-controller@e001d050 { + compatible = "microchip,sama7g5-sckc", "microchip,sam9x60-sckc"; + reg = <0xe001d050 0x4>; + clocks = <&slow_xtal>; + #clock-cells = <1>; + status = "disabled"; + secure-status = "okay"; + }; + + gpbr: gpbr@e001d060 { + compatible = "microchip,sama7g5-gpbr", "syscon"; + reg = <0xe001d060 0x48>; + }; + + rtc: rtc@e001d0a8 { + compatible = "microchip,sama7g5-rtc", "microchip,sam9x60-rtc"; + reg = <0xe001d0a8 0x30>; + interrupts = ; + clocks = <&clk32k 1>; + status = "disabled"; + secure-status = "okay"; + }; + + ps_wdt: watchdog@e001d180 { + compatible = "microchip,sama7g5-wdt"; + reg = <0xe001d180 0x24>; + interrupts = ; + clocks = <&clk32k 0>; + status = "disabled"; + secure-status = "okay"; + }; + + chipid@e0020000 { + compatible = "microchip,sama7g5-chipid"; + reg = <0xe0020000 0x8>; + }; + + tcb1: timer@e0800000 { + compatible = "atmel,sama5d2-tcb", "simple-mfd", "syscon"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0xe0800000 0x100>; + interrupts = , , ; + clocks = <&pmc PMC_TYPE_PERIPHERAL 91>, <&pmc PMC_TYPE_PERIPHERAL 92>, <&pmc PMC_TYPE_PERIPHERAL 93>, <&clk32k 1>; + clock-names = "t0_clk", "t1_clk", "t2_clk", "slow_clk"; + status = "disabled"; + secure-status = "okay"; + }; + + hsmc: hsmc@e0808000 { + compatible = "atmel,sama5d2-smc", "syscon", "simple-mfd"; + reg = <0xe0808000 0x1000>; + interrupts = ; + clocks = <&pmc PMC_TYPE_PERIPHERAL 21>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + pmecc: ecc-engine@e0808070 { + compatible = "atmel,sama5d2-pmecc"; + reg = <0xe0808070 0x490>, + <0xe0808500 0x200>; + }; + }; + + qspi0: spi@e080c000 { + compatible = "microchip,sama7g5-ospi"; + reg = <0xe080c000 0x400>, <0x20000000 0x10000000>; + reg-names = "qspi_base", "qspi_mmap"; + interrupts = ; + dmas = <&dma0 AT91_XDMAC_DT_PERID(41)>, + <&dma0 AT91_XDMAC_DT_PERID(40)>; + dma-names = "tx", "rx"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 78>, <&pmc PMC_TYPE_GCK 78>; + clock-names = "pclk", "gclk"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + qspi1: spi@e0810000 { + compatible = "microchip,sama7g5-qspi"; + reg = <0xe0810000 0x400>, <0x30000000 0x10000000>; + reg-names = "qspi_base", "qspi_mmap"; + interrupts = ; + dmas = <&dma0 AT91_XDMAC_DT_PERID(43)>, + <&dma0 AT91_XDMAC_DT_PERID(42)>; + dma-names = "tx", "rx"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 79>, <&pmc PMC_TYPE_GCK 79>; + clock-names = "pclk", "gclk"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + can0: can@e0828000 { + compatible = "bosch,m_can"; + reg = <0xe0828000 0x100>, <0x100000 0x7800>; + reg-names = "m_can", "message_ram"; + interrupts = ; + interrupt-names = "int0", "int1"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 61>, <&pmc PMC_TYPE_GCK 61>; + clock-names = "hclk", "cclk"; + assigned-clocks = <&pmc PMC_TYPE_GCK 61>; + assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_SYSPLL>; + assigned-clock-rates = <40000000>; + bosch,mram-cfg = <0x3400 0 0 64 0 0 32 32>; + status = "disabled"; + }; + + can1: can@e082c000 { + compatible = "bosch,m_can"; + reg = <0xe082c000 0x100>, <0x100000 0xbc00>; + reg-names = "m_can", "message_ram"; + interrupts = ; + interrupt-names = "int0", "int1"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 62>, <&pmc PMC_TYPE_GCK 62>; + clock-names = "hclk", "cclk"; + assigned-clocks = <&pmc PMC_TYPE_GCK 62>; + assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_SYSPLL>; + assigned-clock-rates = <40000000>; + bosch,mram-cfg = <0x7800 0 0 64 0 0 32 32>; + status = "disabled"; + }; + + can2: can@e0830000 { + compatible = "bosch,m_can"; + reg = <0xe0830000 0x100>, <0x100000 0x10000>; + reg-names = "m_can", "message_ram"; + interrupts = ; + interrupt-names = "int0", "int1"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 63>, <&pmc PMC_TYPE_GCK 63>; + clock-names = "hclk", "cclk"; + assigned-clocks = <&pmc PMC_TYPE_GCK 63>; + assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_SYSPLL>; + assigned-clock-rates = <40000000>; + bosch,mram-cfg = <0xbc00 0 0 64 0 0 32 32>; + status = "disabled"; + }; + + can3: can@e0834000 { + compatible = "bosch,m_can"; + reg = <0xe0834000 0x100>, <0x110000 0x4400>; + reg-names = "m_can", "message_ram"; + interrupts = ; + interrupt-names = "int0", "int1"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 64>, <&pmc PMC_TYPE_GCK 64>; + clock-names = "hclk", "cclk"; + assigned-clocks = <&pmc PMC_TYPE_GCK 64>; + assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_SYSPLL>; + assigned-clock-rates = <40000000>; + bosch,mram-cfg = <0x0 0 0 64 0 0 32 32>; + status = "disabled"; + }; + + can4: can@e0838000 { + compatible = "bosch,m_can"; + reg = <0xe0838000 0x100>, <0x110000 0x8800>; + reg-names = "m_can", "message_ram"; + interrupts = ; + interrupt-names = "int0", "int1"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 65>, <&pmc PMC_TYPE_GCK 65>; + clock-names = "hclk", "cclk"; + assigned-clocks = <&pmc PMC_TYPE_GCK 65>; + assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_SYSPLL>; + assigned-clock-rates = <40000000>; + bosch,mram-cfg = <0x4400 0 0 64 0 0 32 32>; + status = "disabled"; + }; + + can5: can@e083c000 { + compatible = "bosch,m_can"; + reg = <0xe083c000 0x100>, <0x110000 0xcc00>; + reg-names = "m_can", "message_ram"; + interrupts = ; + interrupt-names = "int0", "int1"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 66>, <&pmc PMC_TYPE_GCK 66>; + clock-names = "hclk", "cclk"; + assigned-clocks = <&pmc PMC_TYPE_GCK 66>; + assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_SYSPLL>; + assigned-clock-rates = <40000000>; + bosch,mram-cfg = <0x8800 0 0 64 0 0 32 32>; + status = "disabled"; + }; + + adc: adc@e1000000 { + compatible = "microchip,sama7g5-adc"; + reg = <0xe1000000 0x200>; + interrupts = ; + clocks = <&pmc PMC_TYPE_GCK 26>; + assigned-clocks = <&pmc PMC_TYPE_GCK 26>; + assigned-clock-rates = <100000000>; + clock-names = "adc_clk"; + dmas = <&dma0 AT91_XDMAC_DT_PERID(0)>; + dma-names = "rx"; + atmel,min-sample-rate-hz = <200000>; + atmel,max-sample-rate-hz = <20000000>; + atmel,startup-time-ms = <4>; + #io-channel-cells = <1>; + nvmem-cells = <&temperature_calib>; + nvmem-cell-names = "temperature_calib"; + status = "disabled"; + }; + + sdmmc0: mmc@e1204000 { + compatible = "microchip,sama7g5-sdhci", "microchip,sam9x60-sdhci"; + reg = <0xe1204000 0x4000>; + interrupts = ; + clocks = <&pmc PMC_TYPE_PERIPHERAL 80>, <&pmc PMC_TYPE_GCK 80>; + clock-names = "hclock", "multclk"; + assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_SYSPLL>; + assigned-clocks = <&pmc PMC_TYPE_GCK 80>; + assigned-clock-rates = <200000000>; + microchip,sdcal-inverted; + status = "disabled"; + }; + + sdmmc1: mmc@e1208000 { + compatible = "microchip,sama7g5-sdhci", "microchip,sam9x60-sdhci"; + reg = <0xe1208000 0x4000>; + interrupts = ; + clocks = <&pmc PMC_TYPE_PERIPHERAL 81>, <&pmc PMC_TYPE_GCK 81>; + clock-names = "hclock", "multclk"; + assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_SYSPLL>; + assigned-clocks = <&pmc PMC_TYPE_GCK 81>; + assigned-clock-rates = <200000000>; + microchip,sdcal-inverted; + status = "disabled"; + }; + + sdmmc2: mmc@e120c000 { + compatible = "microchip,sama7g5-sdhci", "microchip,sam9x60-sdhci"; + reg = <0xe120c000 0x4000>; + interrupts = ; + clocks = <&pmc PMC_TYPE_PERIPHERAL 82>, <&pmc PMC_TYPE_GCK 82>; + clock-names = "hclock", "multclk"; + assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_SYSPLL>; + assigned-clocks = <&pmc PMC_TYPE_GCK 82>; + assigned-clock-rates = <200000000>; + microchip,sdcal-inverted; + status = "disabled"; + }; + + csi2host: csi2host@e1400000 { + compatible = "snps,dw-csi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0xe1400000 0x7FF>; + interrupts = ; + clocks = <&pmc PMC_TYPE_PERIPHERAL 33>, <&pmc PMC_TYPE_GCK 33>; + clock-names = "perclk", "phyclk"; + assigned-clocks = <&pmc PMC_TYPE_GCK 33>; + assigned-clock-rates = <26600000>; + snps,output-type = <1>; + phys = <&csi_dphy>; + status = "disabled"; + + port@1 { + reg = <1>; + csi2host_in: endpoint { + }; + }; + + port@2 { + reg = <2>; + csi2host_out: endpoint { + }; + }; + }; + + csi_dphy: dphy@e1400040 { + compatible = "snps,dw-dphy-rx"; + #phy-cells = <0>; + bus-width = <8>; + snps,dphy-frequency = <900000>; + snps,phy_type = <0>; + reg = <0xe1400040 0x20>; + status = "disabled"; + }; + + csi2dc: csi2dc@e1404000 { + compatible = "microchip,sama7g5-csi2dc"; + reg = <0xe1404000 0x500>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 34>, <&xisc>; + clock-names = "pclk", "scck"; + assigned-clocks = <&xisc>; + assigned-clock-rates = <266000000>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + csi2dc_in: endpoint { + }; + }; + + port@1 { + reg = <1>; + csi2dc_out: endpoint { + bus-width = <14>; + hsync-active = <1>; + vsync-active = <1>; + remote-endpoint = <&xisc_in>; + }; + }; + }; + }; + + xisc: xisc@e1408000 { + compatible = "microchip,sama7g5-isc"; + reg = <0xe1408000 0x2000>; + interrupts = ; + clocks = <&pmc PMC_TYPE_PERIPHERAL 56>; + clock-names = "hclock"; + #clock-cells = <0>; + clock-output-names = "isc-mck"; + status = "disabled"; + + port { + xisc_in: endpoint { + bus-type = <5>; /* Parallel */ + bus-width = <14>; + hsync-active = <1>; + vsync-active = <1>; + remote-endpoint = <&csi2dc_out>; + }; + }; + }; + + pwm: pwm@e1604000 { + compatible = "microchip,sama7g5-pwm", "atmel,sama5d2-pwm"; + reg = <0xe1604000 0x4000>; + interrupts = ; + #pwm-cells = <3>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 77>; + status = "disabled"; + }; + + pdmc0: sound@e1608000 { + compatible = "microchip,sama7g5-pdmc"; + reg = <0xe1608000 0x1000>; + interrupts = ; + #sound-dai-cells = <0>; + dmas = <&dma0 AT91_XDMAC_DT_PERID(37)>; + dma-names = "rx"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 68>, <&pmc PMC_TYPE_GCK 68>; + clock-names = "pclk", "gclk"; + sound-name-prefix = "PDMC0"; + status = "disabled"; + }; + + pdmc1: sound@e160c000 { + compatible = "microchip,sama7g5-pdmc"; + reg = <0xe160c000 0x1000>; + interrupts = ; + #sound-dai-cells = <0>; + dmas = <&dma0 AT91_XDMAC_DT_PERID(38)>; + dma-names = "rx"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 69>, <&pmc PMC_TYPE_GCK 69>; + clock-names = "pclk", "gclk"; + sound-name-prefix = "PDMC1"; + status = "disabled"; + }; + + asrc: sound@e1610000 { + compatible = "microchip,sama7g5-asrc"; + reg = <0xe1610000 0x1000>; + interrupts = ; + #sound-dai-cells = <1>; + dmas = <&dma0 AT91_XDMAC_DT_PERID(55)>, + <&dma0 AT91_XDMAC_DT_PERID(56)>, + <&dma0 AT91_XDMAC_DT_PERID(57)>, + <&dma0 AT91_XDMAC_DT_PERID(58)>, + <&dma0 AT91_XDMAC_DT_PERID(59)>, + <&dma0 AT91_XDMAC_DT_PERID(60)>, + <&dma0 AT91_XDMAC_DT_PERID(61)>, + <&dma0 AT91_XDMAC_DT_PERID(62)>; + dma-names = "rx0", "tx0", "rx1", "tx1", + "rx2", "tx2", "rx3", "tx3"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 30>, <&pmc PMC_TYPE_GCK 30>; + clock-names = "pclk", "gclk"; + microchip,triggers = <&i2s0>, <&i2s1>, <&pdmc0>, <&pdmc1>, + <&ssc0>, <&ssc1>, <&spdiftx>, <&spdifrx>; + microchip,trigger-indexes = <1>, <2>, <3>, <4>, <5>, <8>, <9>, <10>; + assigned-clocks = <&pmc PMC_TYPE_GCK 30>; + assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_AUDIOPMCPLL>; + status = "disabled"; + }; + + spdifrx: spdifrx@e1614000 { + #sound-dai-cells = <0>; + compatible = "microchip,sama7g5-spdifrx"; + reg = <0xe1614000 0x4000>; + interrupts = ; + dmas = <&dma0 AT91_XDMAC_DT_PERID(49)>; + dma-names = "rx"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 84>, <&pmc PMC_TYPE_GCK 84>; + clock-names = "pclk", "gclk"; + status = "disabled"; + sound-name-prefix = "SPDIFRX0"; + }; + + spdiftx: spdiftx@e1618000 { + #sound-dai-cells = <0>; + compatible = "microchip,sama7g5-spdiftx"; + reg = <0xe1618000 0x4000>; + interrupts = ; + dmas = <&dma0 AT91_XDMAC_DT_PERID(50)>; + dma-names = "tx"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 85>, <&pmc PMC_TYPE_GCK 85>; + clock-names = "pclk", "gclk"; + sound-name-prefix = "SPDIFTX0"; + }; + + i2s0: i2s@e161c000 { + compatible = "microchip,sama7g5-i2smcc"; + #sound-dai-cells = <0>; + reg = <0xe161c000 0x4000>; + interrupts = ; + dmas = <&dma0 AT91_XDMAC_DT_PERID(34)>, <&dma0 AT91_XDMAC_DT_PERID(33)>; + dma-names = "tx", "rx"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 57>, <&pmc PMC_TYPE_GCK 57>; + clock-names = "pclk", "gclk"; + sound-name-prefix = "I2SMCC0"; + status = "disabled"; + }; + + i2s1: i2s@e1620000 { + compatible = "microchip,sama7g5-i2smcc"; + #sound-dai-cells = <0>; + reg = <0xe1620000 0x4000>; + interrupts = ; + dmas = <&dma0 AT91_XDMAC_DT_PERID(36)>, <&dma0 AT91_XDMAC_DT_PERID(35)>; + dma-names = "tx", "rx"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 58>, <&pmc PMC_TYPE_GCK 58>; + clock-names = "pclk", "gclk"; + sound-name-prefix = "I2SMCC1"; + status = "disabled"; + }; + + sfr: sfr@e1624000 { + compatible = "microchip,sama7g5-sfr", "syscon"; + reg = <0xe1624000 0x4000>; + }; + + eic: interrupt-controller@e1628000 { + compatible = "microchip,sama7g5-eic"; + reg = <0xe1628000 0xec>; + interrupt-parent = <&gic>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = , + ; + clocks = <&pmc PMC_TYPE_PERIPHERAL 37>; + clock-names = "pclk"; + status = "disabled"; + }; + + pit64b0: timer@e1800000 { + compatible = "microchip,sama7g5-pit64b", "microchip,sam9x60-pit64b"; + reg = <0xe1800000 0x4000>; + interrupts = ; + clocks = <&pmc PMC_TYPE_PERIPHERAL 70>, <&pmc PMC_TYPE_GCK 70>; + clock-names = "pclk", "gclk"; + }; + + pit64b1: timer@e1804000 { + compatible = "microchip,sama7g5-pit64b", "microchip,sam9x60-pit64b"; + reg = <0xe1804000 0x4000>; + interrupts = ; + clocks = <&pmc PMC_TYPE_PERIPHERAL 71>, <&pmc PMC_TYPE_GCK 71>; + clock-names = "pclk", "gclk"; + }; + + ssc0: sound@e180c000 { + compatible = "atmel,at91sam9g45-ssc"; + reg = <0xe180c000 0x1000>; + #sound-dai-cells = <0>; + interrupts = ; + dmas = <&dma0 AT91_XDMAC_DT_PERID(44)>, + <&dma0 AT91_XDMAC_DT_PERID(45)>; + dma-names = "rx", "tx"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 86>; + clock-names = "pclk"; + sound-name-prefix = "SSC0"; + status = "disabled"; + }; + + aes: crypto@e1810000 { + compatible = "atmel,at91sam9g46-aes"; + reg = <0xe1810000 0x100>; + interrupts = ; + clocks = <&pmc PMC_TYPE_PERIPHERAL 27>; + clock-names = "aes_clk"; + dmas = <&dma0 AT91_XDMAC_DT_PERID(1)>, + <&dma0 AT91_XDMAC_DT_PERID(2)>; + dma-names = "tx", "rx"; + status = "okay"; + }; + + sha: crypto@e1814000 { + compatible = "atmel,at91sam9g46-sha"; + reg = <0xe1814000 0x100>; + interrupts = ; + clocks = <&pmc PMC_TYPE_PERIPHERAL 83>; + clock-names = "sha_clk"; + dmas = <&dma0 AT91_XDMAC_DT_PERID(48)>; + dma-names = "tx"; + status = "okay"; + }; + + flx0: flexcom@e1818000 { + compatible = "atmel,sama5d2-flexcom"; + reg = <0xe1818000 0x200>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 38>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xe1818000 0x800>; + status = "disabled"; + + uart0: serial@200 { + compatible = "atmel,at91sam9260-usart"; + reg = <0x200 0x200>; + interrupts = ; + clocks = <&pmc PMC_TYPE_PERIPHERAL 38>; + clock-names = "usart"; + dmas = <&dma1 AT91_XDMAC_DT_PERID(6)>, + <&dma1 AT91_XDMAC_DT_PERID(5)>; + dma-names = "tx", "rx"; + atmel,use-dma-rx; + atmel,use-dma-tx; + status = "disabled"; + }; + }; + + flx1: flexcom@e181c000 { + compatible = "atmel,sama5d2-flexcom"; + reg = <0xe181c000 0x200>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 39>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xe181c000 0x800>; + status = "disabled"; + + i2c1: i2c@600 { + compatible = "microchip,sama7g5-i2c", "microchip,sam9x60-i2c"; + reg = <0x600 0x200>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 39>; + atmel,fifo-size = <32>; + dmas = <&dma0 AT91_XDMAC_DT_PERID(8)>, + <&dma0 AT91_XDMAC_DT_PERID(7)>; + dma-names = "tx", "rx"; + status = "disabled"; + }; + }; + + flx3: flexcom@e1824000 { + compatible = "atmel,sama5d2-flexcom"; + reg = <0xe1824000 0x200>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 41>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xe1824000 0x800>; + status = "disabled"; + + uart3: serial@200 { + compatible = "atmel,at91sam9260-usart"; + reg = <0x200 0x200>; + interrupts = ; + clocks = <&pmc PMC_TYPE_PERIPHERAL 41>; + clock-names = "usart"; + dmas = <&dma1 AT91_XDMAC_DT_PERID(12)>, + <&dma1 AT91_XDMAC_DT_PERID(11)>; + dma-names = "tx", "rx"; + atmel,use-dma-rx; + atmel,use-dma-tx; + status = "disabled"; + }; + }; + + ssc1: sound@e200c000 { + compatible = "atmel,at91sam9g45-ssc"; + reg = <0xe200c000 0x1000>; + #sound-dai-cells = <0>; + interrupts = ; + dmas = <&dma0 AT91_XDMAC_DT_PERID(46)>, + <&dma0 AT91_XDMAC_DT_PERID(47)>; + dma-names = "rx", "tx"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 87>; + clock-names = "pclk"; + sound-name-prefix = "SSC1"; + status = "disabled"; + }; + + trng: rng@e2010000 { + compatible = "microchip,sama7g5-trng", "atmel,at91sam9g45-trng"; + reg = <0xe2010000 0x100>; + interrupts = ; + clocks = <&pmc PMC_TYPE_PERIPHERAL 97>; + status = "disabled"; + secure-status = "okay"; + }; + + tdes: crypto@e2014000 { + compatible = "atmel,at91sam9g46-tdes"; + reg = <0xe2014000 0x100>; + interrupts = ; + clocks = <&pmc PMC_TYPE_PERIPHERAL 96>; + clock-names = "tdes_clk"; + dmas = <&dma0 AT91_XDMAC_DT_PERID(54)>, + <&dma0 AT91_XDMAC_DT_PERID(53)>; + dma-names = "tx", "rx"; + status = "okay"; + }; + + flx4: flexcom@e2018000 { + compatible = "atmel,sama5d2-flexcom"; + reg = <0xe2018000 0x200>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 42>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xe2018000 0x800>; + status = "disabled"; + + uart4: serial@200 { + compatible = "atmel,at91sam9260-usart"; + reg = <0x200 0x200>; + interrupts = ; + clocks = <&pmc PMC_TYPE_PERIPHERAL 42>; + clock-names = "usart"; + dmas = <&dma1 AT91_XDMAC_DT_PERID(14)>, + <&dma1 AT91_XDMAC_DT_PERID(13)>; + dma-names = "tx", "rx"; + atmel,use-dma-rx; + atmel,use-dma-tx; + atmel,fifo-size = <16>; + status = "disabled"; + }; + }; + + flx7: flexcom@e2024000 { + compatible = "atmel,sama5d2-flexcom"; + reg = <0xe2024000 0x200>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 45>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xe2024000 0x800>; + status = "disabled"; + + uart7: serial@200 { + compatible = "atmel,at91sam9260-usart"; + reg = <0x200 0x200>; + interrupts = ; + clocks = <&pmc PMC_TYPE_PERIPHERAL 45>; + clock-names = "usart"; + dmas = <&dma1 AT91_XDMAC_DT_PERID(20)>, + <&dma1 AT91_XDMAC_DT_PERID(19)>; + dma-names = "tx", "rx"; + atmel,use-dma-rx; + atmel,use-dma-tx; + atmel,fifo-size = <16>; + status = "disabled"; + }; + }; + + gmac0: ethernet@e2800000 { + compatible = "microchip,sama7g5-gem"; + reg = <0xe2800000 0x1000>; + interrupts = ; + clocks = <&pmc PMC_TYPE_PERIPHERAL 51>, <&pmc PMC_TYPE_PERIPHERAL 51>, <&pmc PMC_TYPE_GCK 51>, <&pmc PMC_TYPE_GCK 53>; + clock-names = "pclk", "hclk", "tx_clk", "tsu_clk"; + assigned-clocks = <&pmc PMC_TYPE_GCK 51>; + assigned-clock-rates = <125000000>; + assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_ETHPLL>; + status = "disabled"; + }; + + gmac1: ethernet@e2804000 { + compatible = "microchip,sama7g5-emac"; + reg = <0xe2804000 0x1000>; + interrupts = ; + clocks = <&pmc PMC_TYPE_PERIPHERAL 52>, <&pmc PMC_TYPE_PERIPHERAL 52>, <&pmc PMC_TYPE_GCK 54>; + clock-names = "pclk", "hclk", "tsu_clk"; + assigned-clocks = <&pmc PMC_TYPE_GCK 54>; + assigned-clock-rates = <200000000>; + status = "disabled"; + }; + + dma0: dma-controller@e2808000 { + compatible = "microchip,sama7g5-dma"; + reg = <0xe2808000 0x1000>; + interrupts = ; + #dma-cells = <1>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 22>; + clock-names = "dma_clk"; + status = "disabled"; + }; + + dma1: dma-controller@e280c000 { + compatible = "microchip,sama7g5-dma"; + reg = <0xe280c000 0x1000>; + interrupts = ; + #dma-cells = <1>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 23>; + clock-names = "dma_clk"; + status = "disabled"; + }; + + /* Place dma2 here despite it's address */ + dma2: dma-controller@e1200000 { + compatible = "microchip,sama7g5-dma"; + reg = <0xe1200000 0x1000>; + interrupts = ; + #dma-cells = <1>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 24>; + clock-names = "dma_clk"; + dma-requests = <0>; + status = "disabled"; + }; + + tcb0: timer@e2814000 { + compatible = "atmel,sama5d2-tcb", "simple-mfd", "syscon"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0xe2814000 0x100>; + interrupts = , , ; + clocks = <&pmc PMC_TYPE_PERIPHERAL 88>, <&pmc PMC_TYPE_PERIPHERAL 89>, <&pmc PMC_TYPE_PERIPHERAL 90>, <&clk32k 1>; + clock-names = "t0_clk", "t1_clk", "t2_clk", "slow_clk"; + }; + + flx8: flexcom@e2818000 { + compatible = "atmel,sama5d2-flexcom"; + reg = <0xe2818000 0x200>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 46>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xe2818000 0x800>; + status = "disabled"; + + i2c8: i2c@600 { + compatible = "microchip,sama7g5-i2c", "microchip,sam9x60-i2c"; + reg = <0x600 0x200>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 46>; + atmel,fifo-size = <32>; + dmas = <&dma0 AT91_XDMAC_DT_PERID(22)>, + <&dma0 AT91_XDMAC_DT_PERID(21)>; + dma-names = "tx", "rx"; + status = "disabled"; + }; + }; + + flx9: flexcom@e281c000 { + compatible = "atmel,sama5d2-flexcom"; + reg = <0xe281c000 0x200>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 47>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xe281c000 0x800>; + status = "disabled"; + + i2c9: i2c@600 { + compatible = "microchip,sama7g5-i2c", "microchip,sam9x60-i2c"; + reg = <0x600 0x200>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 47>; + atmel,fifo-size = <32>; + dmas = <&dma0 AT91_XDMAC_DT_PERID(24)>, + <&dma0 AT91_XDMAC_DT_PERID(23)>; + dma-names = "tx", "rx"; + status = "disabled"; + }; + }; + + flx11: flexcom@e2824000 { + compatible = "atmel,sama5d2-flexcom"; + reg = <0xe2824000 0x200>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 49>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xe2824000 0x800>; + status = "disabled"; + + spi11: spi@400 { + compatible = "atmel,at91rm9200-spi"; + reg = <0x400 0x200>; + interrupts = ; + clocks = <&pmc PMC_TYPE_PERIPHERAL 49>; + clock-names = "spi_clk"; + #address-cells = <1>; + #size-cells = <0>; + atmel,fifo-size = <32>; + dmas = <&dma0 AT91_XDMAC_DT_PERID(28)>, + <&dma0 AT91_XDMAC_DT_PERID(27)>; + dma-names = "tx", "rx"; + status = "disabled"; + }; + }; + + uddrc: uddrc@e3800000 { + compatible = "microchip,sama7g5-uddrc"; + reg = <0xe3800000 0x4000>; + }; + + ddr3phy: ddr3phy@e3804000 { + compatible = "microchip,sama7g5-ddr3phy"; + reg = <0xe3804000 0x1000>; + }; + + otpc: efuse@e8c00000 { + compatible = "microchip,sama7g5-otpc", "syscon"; + reg = <0xe8c00000 0x100>; + #address-cells = <1>; + #size-cells = <1>; + + temperature_calib: calib@1 { + status = "disabled"; + }; + }; + + gic: interrupt-controller@e8c11000 { + compatible = "arm,cortex-a7-gic"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0xe8c11000 0x1000>, + <0xe8c12000 0x2000>; + }; + }; +}; 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..6bf8419 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp13-pinctrl.dtsi @@ -0,0 +1,55 @@ +// 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>; + }; + }; + + rcc_mco_pins_a: rcc-pins-0 { + pins { + pinmux = ; /* RCC_MCO_1 */ + bias-disable; + drive-push-pull; + slew-rate = <1>; + }; + }; + + 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..3ddfaab --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp131.dtsi @@ -0,0 +1,643 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2021-2023 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +#include +#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>; + }; + }; + + hse_monitor: hse-monitor { + compatible = "st,freq-monitor"; + counter = <&lptimer3 1 1 0 0>; + status = "disabled"; + }; + + 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>; + }; + + }; + + sdmmc1_io: sdmmc1_io { + compatible = "st,stm32mp13-iod"; + regulator-name = "sdmmc1_io"; + regulator-always-on; + }; + + sdmmc2_io: sdmmc2_io { + compatible = "st,stm32mp13-iod"; + regulator-name = "sdmmc2_io"; + regulator-always-on; + }; + + 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 = ; + clocks = <&rcc USART3_K>; + resets = <&rcc USART3_R>; + status = "disabled"; + }; + + uart4: serial@40010000 { + compatible = "st,stm32h7-uart"; + reg = <0x40010000 0x400>; + interrupts = ; + clocks = <&rcc UART4_K>; + resets = <&rcc UART4_R>; + status = "disabled"; + }; + + uart5: serial@40011000 { + compatible = "st,stm32h7-uart"; + reg = <0x40011000 0x400>; + interrupts = ; + clocks = <&rcc UART5_K>; + resets = <&rcc UART5_R>; + status = "disabled"; + }; + + uart7: serial@40018000 { + compatible = "st,stm32h7-uart"; + reg = <0x40018000 0x400>; + interrupts = ; + clocks = <&rcc UART7_K>; + resets = <&rcc UART7_R>; + status = "disabled"; + }; + + uart8: serial@40019000 { + compatible = "st,stm32h7-uart"; + reg = <0x40019000 0x400>; + interrupts = ; + clocks = <&rcc UART8_K>; + resets = <&rcc UART8_R>; + status = "disabled"; + }; + + usart6: serial@44003000 { + compatible = "st,stm32h7-uart"; + reg = <0x44003000 0x400>; + interrupts = ; + clocks = <&rcc USART6_K>; + resets = <&rcc USART6_R>; + 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"; + }; + + 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_irq: pwr@50001010 { + compatible = "st,stm32mp1,pwr-irq"; + status = "disabled"; + }; + + syscfg: syscon@50020000 { + compatible = "st,stm32mp157-syscfg", "syscon"; + reg = <0x50020000 0x400>; + }; + + iwdg2: watchdog@5a002000 { + compatible = "st,stm32mp1-iwdg"; + reg = <0x5a002000 0x400>; + interrupts = ; + clocks = <&rcc IWDG2>, <&rcc CK_LSI>; + clock-names = "pclk", "lsi"; + status = "disabled"; + }; + + rtc: rtc@5c004000 { + compatible = "st,stm32mp13-rtc"; + reg = <0x5c004000 0x400>; + clocks = <&rcc RTCAPB>, <&rcc RTC>; + clock-names = "pclk", "rtc_ck"; + 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>; + bits = <0 12>; + }; + 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>; + }; + + tamp: tamp@5c00a000 { + compatible = "st,stm32mp13-tamp"; + reg = <0x5c00a000 0x400>; + interrupts = ; + clocks = <&rcc RTCAPB>; + }; + + 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>; + }; + }; + + etzpc: etzpc@5c007000 { + compatible = "st,stm32-etzpc", "firewall-bus"; + reg = <0x5C007000 0x400>; + clocks = <&rcc TZPC>; + #address-cells = <1>; + #size-cells = <1>; + + adc_2: adc@48004000 { + reg = <0x48004000 0x400>; + compatible = "st,stm32mp13-adc-core"; + interrupts = ; + clocks = <&rcc ADC2>, <&rcc ADC2_K>; + clock-names = "bus", "adc"; + interrupt-controller; + #interrupt-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + + adc2: adc@0 { + compatible = "st,stm32mp13-adc"; + reg = <0x0>; + #io-channel-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; + interrupt-parent = <&adc_2>; + interrupts = <0>; + status = "disabled"; + + channel@13 { + reg = <13>; + label = "vrefint"; + }; + + channel@14 { + reg = <14>; + label = "vddcore"; + }; + + channel@16 { + reg = <16>; + label = "vddcpu"; + }; + + channel@17 { + reg = <17>; + label = "vddq_ddr"; + }; + }; + }; + + usart1: serial@4c000000 { + compatible = "st,stm32h7-uart"; + reg = <0x4c000000 0x400>; + interrupts = ; + clocks = <&rcc USART1_K>; + resets = <&rcc USART1_R>; + status = "disabled"; + }; + + usart2: serial@4c001000 { + compatible = "st,stm32h7-uart"; + reg = <0x4c001000 0x400>; + interrupts = ; + clocks = <&rcc USART2_K>; + resets = <&rcc USART2_R>; + status = "disabled"; + }; + + i2c3: i2c@4c004000 { + compatible = "st,stm32mp13-i2c"; + reg = <0x4c004000 0x400>; + clocks = <&rcc I2C3_K>; + resets = <&rcc I2C3_R>; + #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>; + clocks = <&rcc I2C4_K>; + resets = <&rcc I2C4_R>; + #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>; + clocks = <&rcc I2C5_K>; + resets = <&rcc I2C5_R>; + #address-cells = <1>; + #size-cells = <0>; + st,syscfg-fmp = <&syscfg 0x4 0x10>; + i2c-analog-filter; + status = "disabled"; + }; + + timers12: timer@4c007000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32-timers"; + reg = <0x4c007000 0x400>; + interrupts = ; + clocks = <&rcc TIM12_K>; + clock-names = "int"; + + counter { + compatible = "st,stm32-timer-counter"; + status = "disabled"; + }; + }; + + timers13: timer@4c008000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32-timers"; + reg = <0x4c008000 0x400>; + clocks = <&rcc TIM13_K>; + clock-names = "int"; + status = "disabled"; + }; + + timers14: timer@4c009000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32-timers"; + reg = <0x4c009000 0x400>; + clocks = <&rcc TIM14_K>; + clock-names = "int"; + status = "disabled"; + }; + + timers15: timer@4c00a000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32-timers"; + reg = <0x4c00a000 0x400>; + interrupts = ; + clocks = <&rcc TIM15_K>; + clock-names = "int"; + status = "disabled"; + + counter { + compatible = "st,stm32-timer-counter"; + status = "disabled"; + }; + }; + + timers16: timer@4c00b000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32-timers"; + reg = <0x4c00b000 0x400>; + clocks = <&rcc TIM16_K>; + clock-names = "int"; + status = "disabled"; + + }; + + timers17: timer@4c00c000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32-timers"; + reg = <0x4c00c000 0x400>; + clocks = <&rcc TIM17_K>; + clock-names = "int"; + status = "disabled"; + }; + + lptimer2: timer@50021000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32-lptimer"; + reg = <0x50021000 0x400>; + interrupts = ; + clocks = <&rcc LPTIM2_K>; + clock-names = "mux"; + status = "disabled"; + }; + + lptimer3: timer@50022000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32-lptimer"; + reg = <0x50022000 0x400>; + interrupts = ; + clocks = <&rcc LPTIM3_K>; + clock-names = "mux"; + status = "disabled"; + + counter { + compatible = "st,stm32-lptimer-counter"; + status = "disabled"; + }; + }; + + vrefbuf: vrefbuf@50025000 { + compatible = "st,stm32mp13-vrefbuf"; + reg = <0x50025000 0x8>; + regulator-name = "vrefbuf"; + regulator-min-microvolt = <1650000>; + regulator-max-microvolt = <2500000>; + clocks = <&rcc VREF>; + status = "disabled"; + }; + + hash: hash@54003000 { + compatible = "st,stm32mp13-hash"; + reg = <0x54003000 0x400>; + interrupts = ; + clocks = <&rcc HASH1>; + resets = <&rcc HASH1_R>; + status = "disabled"; + }; + + rng: rng@54004000 { + compatible = "st,stm32mp13-rng"; + reg = <0x54004000 0x400>; + clocks = <&rcc RNG1_K>; + resets = <&rcc RNG1_R>; + 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"; + }; + + stgen: stgen@5c008000 { + compatible = "st,stm32-stgen"; + reg = <0x5C008000 0x1000>; + }; + }; + }; +}; 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..1e790f9 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp135.dtsi @@ -0,0 +1,24 @@ +// 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" + +/ { + soc { + etzpc: etzpc@5c007000 { + 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"; + }; + }; + }; +}; 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..7357601 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp135f-dk.dts @@ -0,0 +1,481 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2021-2023 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +/dts-v1/; + +#include +#include +#include +#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; + }; +}; + +&adc_2 { + vdda-supply = <&vdd_adc>; + vref-supply = <&vdd_adc>; + status = "okay"; + + adc2: adc@0 { + status = "okay"; + + channel@15 { + reg = <15>; + label = "vbat"; + }; + }; +}; + +&bsec { + board_id: board_id@f0 { + reg = <0xf0 0x4>; + st,non-secure-otp; + }; +}; + +&gpiob { + st,protreg = ; +}; + +&gpiod { + st,protreg = ; +}; + +&gpioe { + st,protreg = ; +}; + +&i2c4 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c4_pins_a>; + i2c-scl-rising-time-ns = <185>; + i2c-scl-falling-time-ns = <20>; + clock-frequency = <400000>; + status = "okay"; + + pmic: stpmic@33 { + compatible = "st,stpmic1"; + reg = <0x33>; + status = "okay"; + st,wakeup-pin-number = <1>; + st,notif-it-id = <0>; + + regulators { + compatible = "st,stpmic1-regulators"; + buck1-supply = <&vin>; + buck2-supply = <&vin>; + buck3-supply = <&vin>; + buck4-supply = <&vin>; + ldo1-supply = <&vin>; + ldo4-supply = <&vin>; + ldo5-supply = <&vin>; + ldo6-supply = <&vin>; + vref_ddr-supply = <&vin>; + pwr_sw1-supply = <&bst_out>; + pwr_sw2-supply = <&v3v3_ao>; + + vddcpu: buck1 { + regulator-name = "vddcpu"; + regulator-min-microvolt = <1250000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-over-current-protection; + + lp-stop { + regulator-suspend-microvolt = <1250000>; + }; + lplv-stop { + regulator-suspend-microvolt = <900000>; + }; + lplv-stop2 { + regulator-off-in-suspend; + }; + standby-ddr-sr { + regulator-off-in-suspend; + }; + standby-ddr-off { + regulator-off-in-suspend; + }; + }; + + vdd_ddr: buck2 { + regulator-name = "vdd_ddr"; + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-over-current-protection; + + standby-ddr-off { + regulator-off-in-suspend; + }; + }; + + vdd: buck3 { + regulator-name = "vdd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + st,mask-reset; + regulator-over-current-protection; + }; + + vddcore: buck4 { + regulator-name = "vddcore"; + regulator-min-microvolt = <1250000>; + regulator-max-microvolt = <1250000>; + regulator-always-on; + regulator-over-current-protection; + + lplv-stop { + regulator-suspend-microvolt = <900000>; + }; + lplv-stop2 { + regulator-suspend-microvolt = <900000>; + }; + standby-ddr-sr { + regulator-off-in-suspend; + }; + standby-ddr-off { + regulator-off-in-suspend; + }; + }; + + vdd_adc: ldo1 { + regulator-name = "vdd_adc"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + standby-ddr-sr { + regulator-off-in-suspend; + }; + standby-ddr-off { + regulator-off-in-suspend; + }; + }; + + unused1: ldo2 { + regulator-name = "ldo2"; + }; + + unused2: ldo3 { + regulator-name = "ldo3"; + }; + + vdd_usb: ldo4 { + regulator-name = "vdd_usb"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + standby-ddr-sr { + regulator-off-in-suspend; + }; + standby-ddr-off { + regulator-off-in-suspend; + }; + }; + + vdd_sd: ldo5 { + regulator-name = "vdd_sd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + + standby-ddr-sr { + regulator-off-in-suspend; + }; + standby-ddr-off { + regulator-off-in-suspend; + }; + }; + + v1v8_periph: ldo6 { + regulator-name = "v1v8_periph"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + + standby-ddr-sr { + regulator-off-in-suspend; + }; + standby-ddr-off { + regulator-off-in-suspend; + }; + }; + + vref_ddr: vref_ddr { + regulator-name = "vref_ddr"; + regulator-always-on; + + standby-ddr-sr { + regulator-off-in-suspend; + }; + standby-ddr-off { + regulator-off-in-suspend; + }; + }; + + bst_out: boost { + regulator-name = "bst_out"; + }; + + v3v3_sw: pwr_sw2 { + regulator-name = "v3v3_sw"; + regulator-active-discharge = <1>; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + }; + }; +}; + +&iwdg1 { + timeout-sec = <32>; + status = "okay"; +}; + +&oem_enc_key { + st,non-secure-otp-provisioning; +}; + +&pwr_regulators { + vdd-supply = <&vdd>; + vdd_3v3_usbfs-supply = <&vdd_usb>; +}; + +&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_I2C5_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 = ; + divmn = <1 82>; + frac = <0xAAA>; + }; + + pll1_vco_1300Mhz: pll1-vco-1300Mhz { + src = ; + divmn = <2 80>; + frac = <0x800>; + }; + + pll2_vco_1066Mhz: pll2-vco-1066Mhz { + src = ; + divmn = <2 65>; + frac = <0x1400>; + }; + + pll3_vco_417Mhz: pll3-vco-417Mhz { + src = ; + divmn = <1 33>; + frac = <0x1a04>; + }; + + pll4_vco_600Mhz: pll4-vco-600Mhz { + src = ; + 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_417Mhz>; + 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 = <650000000>; + st,clksrc = ; + st,pll = <&pll1_cfg1>; + }; + + cfg_2 { + hz = <1000000000>; + st,clksrc = ; + st,pll = <&pll1_cfg2>; + }; + }; + }; +}; + +&rng { + status = "okay"; + clock-error-detect; +}; + +&rtc { + status = "okay"; +}; + +&saes { + status = "okay"; +}; + +&sdmmc1_io { + vddsd1-supply = <&vdd>; +}; + +&sdmmc2_io { + vddsd2-supply = <&vdd>; +}; + +&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..4527f11 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp13xc.dtsi @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2021-2022 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +&etzpc { + cryp: crypto@54002000 { + compatible = "st,stm32mp1-cryp"; + reg = <0x54002000 0x400>; + interrupts = ; + clocks = <&rcc CRYP1>; + resets = <&rcc CRYP1_R>; + status = "disabled"; + }; + + saes: saes@54005000 { + compatible = "st,stm32mp13-saes"; + reg = <0x54005000 0x400>; + interrupts = ; + clocks = <&rcc SAES_K>; + resets = <&rcc SAES_R>; + status = "disabled"; + }; + + pka: pka@54006000 { + compatible = "st,stm32mp13-pka64"; + reg = <0x54006000 0x2000>; + interrupts = ; + clocks = <&rcc PKA>; + resets = <&rcc PKA_R>; + 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..4527f11 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp13xf.dtsi @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2021-2022 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +&etzpc { + cryp: crypto@54002000 { + compatible = "st,stm32mp1-cryp"; + reg = <0x54002000 0x400>; + interrupts = ; + clocks = <&rcc CRYP1>; + resets = <&rcc CRYP1_R>; + status = "disabled"; + }; + + saes: saes@54005000 { + compatible = "st,stm32mp13-saes"; + reg = <0x54005000 0x400>; + interrupts = ; + clocks = <&rcc SAES_K>; + resets = <&rcc SAES_R>; + status = "disabled"; + }; + + pka: pka@54006000 { + compatible = "st,stm32mp13-pka64"; + reg = <0x54006000 0x2000>; + interrupts = ; + clocks = <&rcc PKA>; + resets = <&rcc PKA_R>; + 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..7edff9c --- /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 = <0>; + }; + 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 = <0>; + }; + 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..d6729c8 --- /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>, <&rcc MCU_HOLD_BOOT_R>; + reset-names = "mcu_rst", "hold_boot"; + 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-scmi.dts b/optee/optee_os/core/arch/arm/dts/stm32mp157a-dk1-scmi.dts new file mode 100644 index 0000000..8236375 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp157a-dk1-scmi.dts @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 + */ + +/dts-v1/; + +#include "stm32mp157a-dk1.dts" + +/ { + model = "STMicroelectronics STM32MP157A-DK1 SCMI Discovery Board"; + compatible = "st,stm32mp157a-dk1-scmi", "st,stm32mp157"; +}; + +&rcc { + compatible = "st,stm32mp1-rcc-secure"; + status = "okay"; +}; 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..294746d --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp157a-dk1.dts @@ -0,0 +1,38 @@ +// 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>; + }; +}; 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-scmi.dts b/optee/optee_os/core/arch/arm/dts/stm32mp157c-dk2-scmi.dts new file mode 100644 index 0000000..e80e2a4 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp157c-dk2-scmi.dts @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 + */ + +/dts-v1/; + +#include "stm32mp157c-dk2.dts" + +/ { + model = "STMicroelectronics STM32MP157C-DK2 SCMI Discovery Board"; + compatible = "st,stm32mp157c-dk2-scmi", "st,stm32mp157"; +}; + +&rcc { + compatible = "st,stm32mp1-rcc-secure"; + 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..dfb8f98 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp157c-dk2.dts @@ -0,0 +1,107 @@ +// 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>; + }; + }; +}; + +&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-scmi.dts b/optee/optee_os/core/arch/arm/dts/stm32mp157c-ed1-scmi.dts new file mode 100644 index 0000000..19cf9bc --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp157c-ed1-scmi.dts @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 + */ +/dts-v1/; + +#include "stm32mp157c-ed1.dts" + +/ { + model = "STMicroelectronics STM32MP157C SCMI eval daughter"; + compatible = "st,stm32mp157c-ed1-scmi", "st,stm32mp157"; +}; + +&iwdg1 { + timeout-sec = <32>; +}; + +&iwdg2 { + timeout-sec = <32>; + status = "okay"; + secure-status = "disabled"; +}; + +&rcc { + compatible = "st,stm32mp1-rcc-secure"; + status = "okay"; +}; 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..c0b4e1a --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp157c-ed1.dts @@ -0,0 +1,425 @@ +// 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; + }; + + ipc_shmem: ipc-shmem@1004f000 { + compatible = "shared-dma-pool"; + reg = <0x10048000 0x8000>; + 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 = ; + regulator-always-on; + }; + + 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>; + status = "okay"; +}; + +&iwdg2 { + timeout-sec = <32>; + status = "disabled"; +}; + +&m4_rproc { + memory-region = <&retram>, <&mcuram>, <&mcuram2>, <&vdev0vring0>, + <&vdev0vring1>, <&vdev0buffer>, <&ipc_shmem>; + 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 { + compatible = "st,stm32mp1-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-scmi.dts b/optee/optee_os/core/arch/arm/dts/stm32mp157c-ev1-scmi.dts new file mode 100644 index 0000000..5474c9a --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp157c-ev1-scmi.dts @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 + */ +/dts-v1/; + +#include "stm32mp157c-ev1.dts" + +/ { + model = "STMicroelectronics STM32MP157C SCMI eval daughter on eval mother"; + compatible = "st,stm32mp157c-ev1-scmi", "st,stm32mp157c-ed1-scmi", "st,stm32mp157"; +}; + +&rcc { + compatible = "st,stm32mp1-rcc-secure"; + status = "okay"; +}; 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..af5a053 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp15xx-dkx.dtsi @@ -0,0 +1,746 @@ +// 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; + }; + + ipc_shmem: ipc-shmem@1004f000 { + compatible = "shared-dma-pool"; + reg = <0x10048000 0x8000>; + 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 = ; + regulator-always-on; + }; + + 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>; + status = "okay"; +}; + +&iwdg2 { + timeout-sec = <32>; + 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>, <&ipc_shmem>; + 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>; +}; + +&rcc { + compatible = "st,stm32mp1-rcc"; + status = "okay"; +}; + +&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/dts/stm32mp25-pinctrl.dtsi b/optee/optee_os/core/arch/arm/dts/stm32mp25-pinctrl.dtsi new file mode 100644 index 0000000..5bd2776 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp25-pinctrl.dtsi @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ +#include + diff --git a/optee/optee_os/core/arch/arm/dts/stm32mp251.dtsi b/optee/optee_os/core/arch/arm/dts/stm32mp251.dtsi new file mode 100644 index 0000000..a90afb3 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp251.dtsi @@ -0,0 +1,243 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +#include + +/ { + #address-cells = <2>; + #size-cells = <2>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + compatible = "arm,cortex-a35"; + device_type = "cpu"; + reg = <0>; + enable-method = "psci"; + }; + }; + + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + }; + + intc: interrupt-controller@4ac00000 { + compatible = "arm,cortex-a7-gic"; + #interrupt-cells = <3>; + interrupt-controller; + reg = <0x0 0x4ac10000 0x0 0x1000>, + <0x0 0x4ac20000 0x0 0x2000>, + <0x0 0x4ac40000 0x0 0x2000>, + <0x0 0x4ac60000 0x0 0x2000>; + #address-cells = <1>; + }; + + 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_msi: clk-msi { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <4000000>; + }; + + clk_i2sin: clk-i2sin { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <0>; + }; + + clocks { + clk_rcbsec: clk-rcbsec { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <64000000>; + }; + }; + }; + + soc@0 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <&intc>; + ranges = <0x0 0x0 0x0 0x80000000>; + + rifsc: rifsc@42080000 { + compatible = "st,stm32mp25-rifsc"; + reg = <0x42080000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + + usart2: serial@400e0000 { + reg = <0x400e0000 0x400>; + status = "disabled"; + }; + }; + + pinctrl: pinctrl@44240000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "st,stm32mp257-pinctrl"; + ranges = <0 0x44240000 0xa0400>; + pins-are-numbered; + + gpioa: gpio@44240000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x0 0x400>; + st,bank-name = "GPIOA"; + status = "disabled"; + }; + + gpiob: gpio@44250000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x10000 0x400>; + st,bank-name = "GPIOB"; + status = "disabled"; + }; + + gpioc: gpio@44260000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x20000 0x400>; + st,bank-name = "GPIOC"; + status = "disabled"; + }; + + gpiod: gpio@44270000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x30000 0x400>; + st,bank-name = "GPIOD"; + status = "disabled"; + }; + + gpioe: gpio@44280000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x40000 0x400>; + st,bank-name = "GPIOE"; + status = "disabled"; + }; + + gpiof: gpio@44290000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x50000 0x400>; + st,bank-name = "GPIOF"; + status = "disabled"; + }; + + gpiog: gpio@442a0000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x60000 0x400>; + st,bank-name = "GPIOG"; + status = "disabled"; + }; + + gpioh: gpio@442b0000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x70000 0x400>; + st,bank-name = "GPIOH"; + status = "disabled"; + }; + + gpioi: gpio@442c0000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x80000 0x400>; + st,bank-name = "GPIOI"; + status = "disabled"; + }; + + gpioj: gpio@442d0000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x90000 0x400>; + st,bank-name = "GPIOJ"; + status = "disabled"; + }; + + gpiok: gpio@442e0000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0xa0000 0x400>; + st,bank-name = "GPIOK"; + status = "disabled"; + }; + }; + + pinctrl_z: pinctrl-z@46200000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "st,stm32mp257-z-pinctrl"; + ranges = <0 0x46200000 0x400>; + pins-are-numbered; + + gpioz: gpio@46200000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0 0x400>; + st,bank-name = "GPIOZ"; + st,bank-ioport = <11>; + status = "disabled"; + }; + }; + }; +}; diff --git a/optee/optee_os/core/arch/arm/dts/stm32mp253.dtsi b/optee/optee_os/core/arch/arm/dts/stm32mp253.dtsi new file mode 100644 index 0000000..93b7ab8 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp253.dtsi @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ +#include "stm32mp251.dtsi" + +/ { + cpus { + cpu1: cpu@1 { + compatible = "arm,cortex-a35"; + device_type = "cpu"; + reg = <1>; + enable-method = "psci"; + }; + }; +}; diff --git a/optee/optee_os/core/arch/arm/dts/stm32mp255.dtsi b/optee/optee_os/core/arch/arm/dts/stm32mp255.dtsi new file mode 100644 index 0000000..e6fa596 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp255.dtsi @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ +#include "stm32mp253.dtsi" + +/ { +}; diff --git a/optee/optee_os/core/arch/arm/dts/stm32mp257.dtsi b/optee/optee_os/core/arch/arm/dts/stm32mp257.dtsi new file mode 100644 index 0000000..5c5000d --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp257.dtsi @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ +#include "stm32mp255.dtsi" + +/ { +}; diff --git a/optee/optee_os/core/arch/arm/dts/stm32mp257f-ev1-ca35tdcid-rif.dtsi b/optee/optee_os/core/arch/arm/dts/stm32mp257f-ev1-ca35tdcid-rif.dtsi new file mode 100644 index 0000000..110dd08 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp257f-ev1-ca35tdcid-rif.dtsi @@ -0,0 +1,139 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2024 - All Rights Reserved + */ + +&rifsc { + st,protreg = < + RIFPROT(STM32MP25_RIFSC_TIM1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_TIM2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_TIM3_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_TIM4_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_TIM5_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_TIM6_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_TIM7_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_TIM8_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_TIM10_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_TIM11_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_TIM12_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_TIM13_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_TIM14_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_TIM15_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_TIM16_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_TIM17_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_TIM20_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_LPTIM1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_LPTIM2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_LPTIM3_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_LPTIM4_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_LPTIM5_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_SPI1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_SPI2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_SPI3_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_SPI4_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_SPI5_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_SPI6_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_SPI7_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_SPI8_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_SPDIFRX_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_USART1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_USART2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_USART3_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_UART4_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_UART5_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_USART6_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_UART7_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_UART8_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_UART9_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_LPUART1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_I2C1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_I2C2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_I2C3_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_I2C4_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_I2C5_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_I2C6_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_I2C7_ID, RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN) + RIFPROT(STM32MP25_RIFSC_I2C8_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_SAI1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_SAI2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_SAI3_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_SAI4_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_MDF1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_ADF1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_FDCAN_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_HDP_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_ADC12_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_ADC3_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_ETH1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_ETH2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_ETHSW_DEIP_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_ETHSW_ACM_MSGBUF_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_ETHSW_ACM_CFG_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_USBH_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_USB3DR_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_COMBOPHY_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_PCIE_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_UCPD1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_STGEN_ID, RIF_UNUSED, RIF_LOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN) + RIFPROT(STM32MP25_RIFSC_SDMMC1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_SDMMC2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_SDMMC3_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_GPU_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_LTDC_CMN_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_LTDC_L0L1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_LTDC_L2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_LTDC_ROT_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_DSI_CMN_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_DSI_TRIG_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_DSI_RDFIFO_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_LVDS_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_CSI_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_DCMIPP_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_DCMI_PSSI_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_VDEC_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_VENC_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_RNG_ID, RIF_CID1_BF|RIF_CID2_BF, RIF_LOCK, RIF_SEC, RIF_PRIV, RIF_UNUSED, RIF_SEM_EN, RIF_CFEN) + RIFPROT(STM32MP25_RIFSC_PKA_ID, RIF_CID1_BF|RIF_CID2_BF, RIF_LOCK, RIF_SEC, RIF_PRIV, RIF_UNUSED, RIF_SEM_EN, RIF_CFEN) + RIFPROT(STM32MP25_RIFSC_SAES_ID, RIF_CID1_BF|RIF_CID2_BF, RIF_LOCK, RIF_SEC, RIF_PRIV, RIF_UNUSED, RIF_SEM_EN, RIF_CFEN) + RIFPROT(STM32MP25_RIFSC_HASH_ID, RIF_UNUSED, RIF_LOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN) + RIFPROT(STM32MP25_RIFSC_CRYP1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_CRYP2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN) + RIFPROT(STM32MP25_RIFSC_IWDG1_ID, RIF_UNUSED, RIF_LOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN) + RIFPROT(STM32MP25_RIFSC_IWDG2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_IWDG3_ID, RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN) + RIFPROT(STM32MP25_RIFSC_IWDG4_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_IWDG5_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_WWDG1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_WWDG2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_VREFBUF_ID, RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN) + RIFPROT(STM32MP25_RIFSC_DTS_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_RAMCFG_ID, RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN) + RIFPROT(STM32MP25_RIFSC_CRC_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_SERC_ID, RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN) + RIFPROT(STM32MP25_RIFSC_GICV2M_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_I3C1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_I3C2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_I3C3_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_I3C4_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + RIFPROT(STM32MP25_RIFSC_ICACHE_DCACHE_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) + >; + st,rimu = < + RIMUPROT(RIMU_ID(0), RIF_CID1, RIF_NSEC, RIF_NPRIV, RIF_CIDSEL_M) + RIMUPROT(RIMU_ID(1), RIF_UNUSED, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_P) + RIMUPROT(RIMU_ID(2), RIF_UNUSED, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_P) + RIMUPROT(RIMU_ID(3), RIF_UNUSED, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_P) + RIMUPROT(RIMU_ID(4), RIF_UNUSED, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_P) + RIMUPROT(RIMU_ID(5), RIF_UNUSED, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_P) + RIMUPROT(RIMU_ID(6), RIF_UNUSED, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_P) + RIMUPROT(RIMU_ID(7), RIF_UNUSED, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_P) + RIMUPROT(RIMU_ID(8), RIF_UNUSED, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_P) + RIMUPROT(RIMU_ID(9), RIF_CID1, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_M) + RIMUPROT(RIMU_ID(10), RIF_UNUSED, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_P) + RIMUPROT(RIMU_ID(11), RIF_CID4, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_M) + RIMUPROT(RIMU_ID(12), RIF_CID4, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_M) + RIMUPROT(RIMU_ID(13), RIF_CID4, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_M) + RIMUPROT(RIMU_ID(14), RIF_UNUSED, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_P) + RIMUPROT(RIMU_ID(15), RIF_UNUSED, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_P) + >; + st,glocked = ; +}; diff --git a/optee/optee_os/core/arch/arm/dts/stm32mp257f-ev1.dts b/optee/optee_os/core/arch/arm/dts/stm32mp257f-ev1.dts new file mode 100644 index 0000000..fcb7983 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp257f-ev1.dts @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +/dts-v1/; +#include +#include +#include "stm32mp25-pinctrl.dtsi" +#include "stm32mp257.dtsi" +#include "stm32mp257f-ev1-ca35tdcid-rif.dtsi" +#include "stm32mp25xf.dtsi" +#include "stm32mp25xxai-pinctrl.dtsi" + +/ { + model = "STMicroelectronics STM32MP257F-EV1 Evaluation Board"; + compatible = "st,stm32mp257f-ev1", "st,stm32mp257"; + + aliases { + serial0 = &usart2; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x0 0x80000000 0x1 0x00000000>; + }; +}; diff --git a/optee/optee_os/core/arch/arm/dts/stm32mp25xc.dtsi b/optee/optee_os/core/arch/arm/dts/stm32mp25xc.dtsi new file mode 100644 index 0000000..5e83a69 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp25xc.dtsi @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +/ { +}; diff --git a/optee/optee_os/core/arch/arm/dts/stm32mp25xf.dtsi b/optee/optee_os/core/arch/arm/dts/stm32mp25xf.dtsi new file mode 100644 index 0000000..5e83a69 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp25xf.dtsi @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +/ { +}; diff --git a/optee/optee_os/core/arch/arm/dts/stm32mp25xxai-pinctrl.dtsi b/optee/optee_os/core/arch/arm/dts/stm32mp25xxai-pinctrl.dtsi new file mode 100644 index 0000000..4fb8920 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp25xxai-pinctrl.dtsi @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +&pinctrl { + gpioa: gpio@44240000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 0 16>; + }; + + gpiob: gpio@44250000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 16 16>; + }; + + gpioc: gpio@44260000 { + status = "okay"; + ngpios = <14>; + gpio-ranges = <&pinctrl 0 32 14>; + }; + + gpiod: gpio@44270000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 48 16>; + }; + + gpioe: gpio@44280000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 64 16>; + }; + + gpiof: gpio@44290000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 80 16>; + }; + + gpiog: gpio@442a0000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 96 16>; + }; + + gpioh: gpio@442b0000 { + status = "okay"; + ngpios = <12>; + gpio-ranges = <&pinctrl 2 114 12>; + }; + + gpioi: gpio@442c0000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 128 16>; + }; + + gpioj: gpio@442d0000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 144 16>; + }; + + gpiok: gpio@442e0000 { + status = "okay"; + ngpios = <8>; + gpio-ranges = <&pinctrl 0 160 8>; + }; +}; + +&pinctrl_z { + gpioz: gpio@46200000 { + status = "okay"; + ngpios = <10>; + gpio-ranges = <&pinctrl_z 0 400 10>; + }; +}; diff --git a/optee/optee_os/core/arch/arm/dts/stm32mp25xxak-pinctrl.dtsi b/optee/optee_os/core/arch/arm/dts/stm32mp25xxak-pinctrl.dtsi new file mode 100644 index 0000000..b758b2c --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp25xxak-pinctrl.dtsi @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +&pinctrl { + gpioa: gpio@44240000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 0 16>; + }; + + gpiob: gpio@44250000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 16 16>; + }; + + gpioc: gpio@44260000 { + status = "okay"; + ngpios = <14>; + gpio-ranges = <&pinctrl 0 32 14>; + }; + + gpiod: gpio@44270000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 48 16>; + }; + + gpioe: gpio@44280000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 64 16>; + }; + + gpiof: gpio@44290000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 80 16>; + }; + + gpiog: gpio@442a0000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 96 16>; + }; + + gpioh: gpio@442b0000 { + status = "okay"; + ngpios = <12>; + gpio-ranges = <&pinctrl 2 114 12>; + }; + + gpioi: gpio@442c0000 { + status = "okay"; + ngpios = <12>; + gpio-ranges = <&pinctrl 0 128 12>; + }; +}; + +&pinctrl_z { + gpioz: gpio@46200000 { + status = "okay"; + ngpios = <10>; + gpio-ranges = <&pinctrl_z 0 400 10>; + }; +}; diff --git a/optee/optee_os/core/arch/arm/dts/stm32mp25xxal-pinctrl.dtsi b/optee/optee_os/core/arch/arm/dts/stm32mp25xxal-pinctrl.dtsi new file mode 100644 index 0000000..b758b2c --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp25xxal-pinctrl.dtsi @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2023 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +&pinctrl { + gpioa: gpio@44240000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 0 16>; + }; + + gpiob: gpio@44250000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 16 16>; + }; + + gpioc: gpio@44260000 { + status = "okay"; + ngpios = <14>; + gpio-ranges = <&pinctrl 0 32 14>; + }; + + gpiod: gpio@44270000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 48 16>; + }; + + gpioe: gpio@44280000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 64 16>; + }; + + gpiof: gpio@44290000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 80 16>; + }; + + gpiog: gpio@442a0000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 96 16>; + }; + + gpioh: gpio@442b0000 { + status = "okay"; + ngpios = <12>; + gpio-ranges = <&pinctrl 2 114 12>; + }; + + gpioi: gpio@442c0000 { + status = "okay"; + ngpios = <12>; + gpio-ranges = <&pinctrl 0 128 12>; + }; +}; + +&pinctrl_z { + gpioz: gpio@46200000 { + status = "okay"; + ngpios = <10>; + gpio-ranges = <&pinctrl_z 0 400 10>; + }; +}; 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..f859a69 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/arm.h @@ -0,0 +1,272 @@ +/* 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 ULL(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_AFF3_SHIFT U(32) +#define MPIDR_AFF3_MASK (MPIDR_AFFLVL_MASK << MPIDR_AFF3_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) + +/* ID_ISAR5 Cryptography Extension masks */ +#define ID_ISAR5_AES GENMASK_32(7, 4) +#define ID_ISAR5_SHA1 GENMASK_32(11, 8) +#define ID_ISAR5_SHA2 GENMASK_32(15, 12) +#define ID_ISAR5_CRC32 GENMASK_32(19, 16) + +/* 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 unsigned int feat_pan_implemented(void) +{ +#ifdef ARM32 + return 0; +#else + return (read_id_aa64mmfr1_el1() >> ID_AA64MMFR1_EL1_PAN_SHIFT) & + ID_AA64MMFR1_EL1_PAN_MASK; +#endif +} + +static inline bool feat_crc32_implemented(void) +{ +#ifdef ARM32 + return read_id_isar5() & ID_ISAR5_CRC32; +#else + return read_id_aa64isar0_el1() & ID_AA64ISAR0_CRC32; +#endif +} + +static inline bool feat_aes_implemented(void) +{ +#ifdef ARM32 + return read_id_isar5() & ID_ISAR5_AES; +#else + return read_id_aa64isar0_el1() & ID_AA64ISAR0_AES; +#endif +} + +static inline bool feat_sha1_implemented(void) +{ +#ifdef ARM32 + return read_id_isar5() & ID_ISAR5_SHA1; +#else + return read_id_aa64isar0_el1() & ID_AA64ISAR0_SHA1; +#endif +} + +static inline bool feat_sha256_implemented(void) +{ +#ifdef ARM32 + return read_id_isar5() & ID_ISAR5_SHA2; +#else + return read_id_aa64isar0_el1() & ID_AA64ISAR0_SHA2; +#endif +} + +static inline bool feat_sha512_implemented(void) +{ +#ifdef ARM32 + return false; +#else + return ((read_id_aa64isar0_el1() & ID_AA64ISAR0_SHA2) >> + ID_AA64ISAR0_SHA2_SHIFT) == ID_AA64ISAR0_SHA2_FEAT_SHA512; +#endif +} + +static inline bool feat_sha3_implemented(void) +{ +#ifdef ARM32 + return false; +#else + return read_id_aa64isar0_el1() & ID_AA64ISAR0_SHA3; +#endif +} + +static inline bool feat_sm3_implemented(void) +{ +#ifdef ARM32 + return false; +#else + return read_id_aa64isar0_el1() & ID_AA64ISAR0_SM3; +#endif +} + +static inline bool feat_sm4_implemented(void) +{ +#ifdef ARM32 + return false; +#else + return read_id_aa64isar0_el1() & ID_AA64ISAR0_SM4; +#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..ef729d4 --- /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..2892263 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/arm64.h @@ -0,0 +1,545 @@ +/* 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) + +#if defined(CFG_CORE_IRQ_IS_NATIVE_INTR) +#define DAIFBIT_NATIVE_INTR DAIFBIT_IRQ +#define DAIFBIT_FOREIGN_INTR DAIFBIT_FIQ +#else +#define DAIFBIT_NATIVE_INTR DAIFBIT_FIQ +#define DAIFBIT_FOREIGN_INTR DAIFBIT_IRQ +#endif + +#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_64_PAN BIT64(22) + +#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_VA_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_AA64MMFR0_EL1_PARANGE_MASK UL(0xf) + +#define ID_AA64MMFR1_EL1_PAN_MASK UL(0xf) +#define ID_AA64MMFR1_EL1_PAN_SHIFT U(20) +#define FEAT_PAN_NOT_IMPLEMENTED U(0x0) +#define FEAT_PAN_IMPLEMENTED U(0x1) +#define FEAT_PAN2_IMPLEMENTED U(0x2) +#define FEAT_PAN3_IMPLEMENTED U(0x3) + +#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 ID_MMFR3_EL1_PAN_SHIFT U(16) + +#define GCR_EL1_RRND BIT64(16) + +/* ID_AA64ISAR0_EL1, AArch64 Instruction Set Attribute Register 0 */ +#define ID_AA64ISAR0_AES GENMASK_64(7, 4) +#define ID_AA64ISAR0_SHA1 GENMASK_64(11, 8) +#define ID_AA64ISAR0_SHA2 GENMASK_64(15, 12) +#define ID_AA64ISAR0_CRC32 GENMASK_64(19, 16) +#define ID_AA64ISAR0_ATOMIC GENMASK_64(23, 20) +#define ID_AA64ISAR0_TME GENMASK_64(27, 24) +#define ID_AA64ISAR0_RDM GENMASK_64(31, 28) +#define ID_AA64ISAR0_SHA3 GENMASK_64(35, 32) +#define ID_AA64ISAR0_SM3 GENMASK_64(39, 36) +#define ID_AA64ISAR0_SM4 GENMASK_64(43, 40) + +#define ID_AA64ISAR0_SHA2_SHIFT U(12) +#define ID_AA64ISAR0_SHA2_FEAT_SHA256 U(1) +#define ID_AA64ISAR0_SHA2_FEAT_SHA512 U(2) + +#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 dsb_osh(void) +{ + asm volatile ("dsb osh" : : : "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 va) +{ + asm volatile ("tlbi vaae1is, %0" : : "r" (va)); +} + +static inline __noprof void tlbi_vale1is(uint64_t va) +{ + asm volatile ("tlbi vale1is, %0" : : "r" (va)); +} + +static inline void write_64bit_pair(uint64_t dst, uint64_t hi, uint64_t lo) +{ + /* 128bits should be written to hardware at one time */ + asm volatile ("stp %1, %0, [%2]" : : + "r" (hi), "r" (lo), "r" (dst) : "memory"); +} + +static inline void read_64bit_pair(uint64_t src, uint64_t *hi, uint64_t *lo) +{ + uint64_t tmp0 = 0; + uint64_t tmp1 = 0; + + /* 128bits should be read from hardware at one time */ + asm volatile ("ldp %0, %1, [%2]\n" : "=&r"(tmp0), "=&r"(tmp1) : + "r"(src) : "memory"); + + *lo = tmp0; + *hi = tmp1; +} + +/* + * 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_(cntps_cval, uint64_t, cntps_cval_el1) +DEFINE_REG_WRITE_FUNC_(cntps_cval, uint64_t, cntps_cval_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_aa64mmfr0_el1) +DEFINE_U64_REG_READ_FUNC(id_aa64mmfr1_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) +DEFINE_REG_WRITE_FUNC_(icc_sgi1r, uint64_t, S3_0_C12_C11_5) +DEFINE_REG_WRITE_FUNC_(icc_asgi1r, uint64_t, S3_0_C12_C11_6) + +DEFINE_REG_WRITE_FUNC_(pan, uint64_t, S3_0_c4_c2_3) +DEFINE_REG_READ_FUNC_(pan, uint64_t, S3_0_c4_c2_3) + +static inline void write_pan_enable(void) +{ + /* msr pan, #1 */ + asm volatile("msr S0_0_c4_c1_4, xzr" ::: "memory" ); +} + +static inline void write_pan_disable(void) +{ + /* msr pan, #0 */ + asm volatile("msr S0_0_c4_c0_4, xzr" ::: "memory" ); +} + +#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..34295d6 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/arm64_macros.S @@ -0,0 +1,183 @@ +/* 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 + + .macro add_imm _reg, _val + .if ((\_val) > 0xfff) + add \_reg, \_reg, ((\_val) >> 12), LSL #12 + .endif + .if (((\_val) & 0xfff) > 0) + add \_reg, \_reg, ((\_val) & 0xfff) + .endif + .endm + + .macro sub_imm _reg, _val + .if ((\_val) > 0xfff) + sub \_reg, \_reg, ((\_val) >> 12), LSL #12 + .endif + .if (((\_val) & 0xfff) > 0) + sub \_reg, \_reg, ((\_val) & 0xfff) + .endif + .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 + + .macro write_pan reg + /* msr pan, \reg */ + msr S3_0_c4_c2_3, \reg + .endm + + .macro write_pan_enable + /* msr pan, #1 */ + msr S0_0_c4_c1_4, xzr + .endm + + .macro write_pan_disable + /* msr pan, #0 */ + msr S0_0_c4_c0_4, xzr + .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..e2be237 --- /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 __CRYPTO_GHASH_CE_CORE_H +#define __CRYPTO_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 /*__CRYPTO_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..7fb3545 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/ffa.h @@ -0,0 +1,378 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2020, Linaro Limited + * Copyright (c) 2018-2023, 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(1) +#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)) + +#define FFA_VERSION_1_0 MAKE_FFA_VERSION(1, 0) +#define FFA_VERSION_1_1 MAKE_FFA_VERSION(1, 1) + +/* 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_SPM_ID_GET U(0x84000085) +#define FFA_MSG_WAIT U(0x8400006B) +#define FFA_MSG_YIELD U(0x8400006C) +#define FFA_RUN U(0x8400006D) +#define FFA_MSG_SEND2 U(0x84000086) +#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_NORMAL_WORLD_RESUME U(0x8400007C) +#define FFA_NOTIFICATION_BITMAP_CREATE U(0x8400007D) +#define FFA_NOTIFICATION_BITMAP_DESTROY U(0x8400007E) +#define FFA_NOTIFICATION_BIND U(0x8400007F) +#define FFA_NOTIFICATION_UNBIND U(0x84000080) +#define FFA_NOTIFICATION_SET U(0x84000081) +#define FFA_NOTIFICATION_GET U(0x84000082) +#define FFA_NOTIFICATION_INFO_GET_32 U(0x84000083) +#define FFA_NOTIFICATION_INFO_GET_64 U(0xC4000083) +#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) +#define FFA_CONSOLE_LOG_32 U(0x8400008A) +#define FFA_CONSOLE_LOG_64 U(0xC400008A) + +#define FFA_FEATURES_FUNC_ID_MASK BIT32(31) +#define FFA_FEATURES_FEATURE_ID_MASK GENMASK_32(7, 0) + +#define FFA_FEATURE_NOTIF_PEND_INTR U(0x1) +#define FFA_FEATURE_SCHEDULE_RECV_INTR U(0x2) +#define FFA_FEATURE_MANAGED_EXIT_INTR U(0x3) + +/* Special value for traffic targeted to the Hypervisor or SPM */ +#define FFA_TARGET_INFO_MBZ U(0x0) + +#define FFA_MSG_FLAG_FRAMEWORK BIT(31) +#define FFA_MSG_TYPE_MASK GENMASK_32(7, 0) +#define FFA_MSG_PSCI U(0x0) +#define FFA_MSG_SEND_VM_CREATED U(0x4) +#define FFA_MSG_RESP_VM_CREATED U(0x5) +#define FFA_MSG_SEND_VM_DESTROYED U(0x6) +#define FFA_MSG_RESP_VM_DESTROYED U(0x7) +#define FFA_MSG_VERSION_REQ U(0x8) +#define FFA_MSG_VERSION_RESP U(0x9) + +/* + * Flag used as parameter to FFA_PARTITION_INFO_GET to return partition + * count only. + */ +#define FFA_PARTITION_INFO_GET_COUNT_FLAG BIT(0) + +/* 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) + +/* + * The W1 register in FFA_INTERRUPT and FFA_RUN interfaces contains the target + * information. This value has two parts, the SP ID and vCPU ID. The SP ID + * identifies the SP to resume and the vCPU ID identifies the vCPU or execution + * context to resume (FF-A v1.1 section 4.8). + */ +#define FFA_TARGET_INFO_SET(sp_id, vcpu_id) (((sp_id) << 16) | (vcpu_id)) +#define FFA_TARGET_INFO_GET_SP_ID(info) (((info) >> 16) & 0xffff) +#define FFA_TARGET_INFO_GET_VCPU_ID(info) ((info) & 0xffff) + +/* + * 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): Can send and receive indirect messages + * BIT(3): Supports receipt of notifications + * BIT(4-5): Partition ID is a PE endpoint ID + */ +#define FFA_PART_PROP_DIRECT_REQ_RECV BIT(0) +#define FFA_PART_PROP_DIRECT_REQ_SEND BIT(1) +#define FFA_PART_PROP_INDIRECT_MSGS BIT(2) +#define FFA_PART_PROP_RECV_NOTIF BIT(3) +#define FFA_PART_PROP_IS_PE_ID SHIFT_U32(0, 4) +#define FFA_PART_PROP_IS_SEPID_INDEP SHIFT_U32(1, 4) +#define FFA_PART_PROP_IS_SEPID_DEP SHIFT_U32(2, 4) +#define FFA_PART_PROP_IS_AUX_ID SHIFT_U32(3, 4) +#define FFA_PART_PROP_NOTIF_CREATED BIT(6) +#define FFA_PART_PROP_NOTIF_DESTROYED BIT(7) +#define FFA_PART_PROP_AARCH64_STATE BIT(8) + +#define FFA_MEMORY_HANDLE_HYPERVISOR_BIT BIT64(63) +#define FFA_MEMORY_HANDLE_SECURE_BIT BIT64(45) +#define FFA_MEMORY_HANDLE_NON_SECURE_BIT BIT64(44) +/* + * Codes the OP-TEE partition/guest ID into a cookie in order to know which + * partition to activate when reclaiming the shared memory. This field is 0 + * unless CFG_NS_VIRTUALIZATION is enabled. + */ +#define FFA_MEMORY_HANDLE_PRTN_SHIFT 16 +#define FFA_MEMORY_HANDLE_PRTN_MASK GENMASK_32(16, 0) + + +#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) + +#define FFA_CONSOLE_LOG_CHAR_COUNT_MASK GENMASK_32(7, 0) +#define FFA_CONSOLE_LOG_32_MAX_MSG_LEN U(24) +#define FFA_CONSOLE_LOG_64_MAX_MSG_LEN U(48) + +#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_1_0 { + 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[]; +}; + +struct ffa_mem_transaction_1_1 { + uint16_t sender_id; + uint16_t mem_reg_attr; + uint32_t flags; + uint64_t global_handle; + uint64_t tag; + uint32_t mem_access_size; + uint32_t mem_access_count; + uint32_t mem_access_offs; + uint8_t reserved[12]; +}; + +/* + * The parts needed from struct ffa_mem_transaction_1_0 or struct + * ffa_mem_transaction_1_1, used to provide an abstraction of difference in + * data structures between version 1.0 and 1.1. This is just an internal + * interface and can be changed without changing any ABI. + */ +struct ffa_mem_transaction_x { + uint16_t sender_id; + uint8_t mem_reg_attr; + uint8_t flags; + uint8_t mem_access_size; + uint8_t mem_access_count; + uint16_t mem_access_offs; + uint64_t global_handle; + uint64_t tag; +}; + +#define FFA_UUID_SIZE 16 + +/* Partition information descriptor */ +struct ffa_partition_info_x { + uint16_t id; + uint16_t execution_context; + uint32_t partition_properties; + /* + * The uuid field is absent in FF-A 1.0, and an array of 16 + * (FFA_UUID_SIZE) from FF-A 1.1 + */ + uint8_t uuid[]; +}; + +/* 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.0 boot information name-value pairs */ +struct ffa_boot_info_nvp_1_0 { + uint32_t name[4]; + uint64_t value; + uint64_t size; +}; + +/* FF-A v1.0 boot information descriptor */ +struct ffa_boot_info_1_0 { + uint32_t magic; + uint32_t count; + struct ffa_boot_info_nvp_1_0 nvp[]; +}; + +/* FF-A v1.1 boot information descriptor */ +struct ffa_boot_info_1_1 { + 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_1_1 { + 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/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..4008e69 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/kernel/delay_arch.h @@ -0,0 +1,47 @@ +/* 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 + +#ifdef CFG_CORE_HAS_GENERIC_TIMER +#include +#include + +static inline unsigned int delay_cnt_freq(void) +{ + return read_cntfrq(); +} + +static inline uint64_t delay_cnt_read(void) +{ + return barrier_read_counter_timer(); +} +#endif /* CFG_CORE_HAS_GENERIC_TIMER */ +#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..992c75f --- /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..9924148 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/kernel/secure_partition.h @@ -0,0 +1,100 @@ +/* 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); + +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; + uint32_t boot_order; + struct ts_session ts_sess; + unsigned int spinlock; + const void *fdt; + bool is_initialized; + TEE_UUID ffa_uuid; + uint32_t ns_int_mode; + uint32_t ns_int_mode_inherited; + 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(uint32_t ffa_vers, void *buf, size_t buf_size, + const TEE_UUID *ffa_uuid, size_t *elem_count, + bool count_only); +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..d43ee40 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/kernel/spmc_sp_handler.h @@ -0,0 +1,54 @@ +/* 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_mem_transaction_x *mem_trans, + struct ffa_rxtx *rxtx, size_t blen, + uint64_t *global_handle, struct sp_session *owner_sp); +void spmc_sp_set_to_preempted(struct ts_session *ts_sess); +int spmc_sp_resume_from_preempted(uint16_t endpoint_id); +#else +static inline void spmc_sp_start_thread(struct thread_smc_args *args __unused) +{ +} + +static inline int +spmc_sp_add_share(struct ffa_mem_transaction_x *mem_trans __unused, + struct ffa_rxtx *rxtx __unused, size_t blen __unused, + uint64_t *global_handle __unused, + struct sp_session *owner_sp __unused) +{ + return FFA_NOT_SUPPORTED; +} + +static inline void spmc_sp_set_to_preempted(struct ts_session *ts_sess __unused) +{ +} + +static inline int spmc_sp_resume_from_preempted(uint16_t endpoint_id __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..7fb5af3 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/kernel/tee_l2cc_mutex.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#ifndef __KERNEL_TEE_L2CC_MUTEX_H +#define __KERNEL_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 /* __KERNEL_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..37fffbc --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/kernel/thread_arch.h @@ -0,0 +1,465 @@ +/* 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_FFA) + /* Function ID to use for a direct response, 32-bit vs 64-bit */ + uint32_t direct_resp_fid; +#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 +#ifdef CFG_FAULT_MITIGATION + struct ftmn_func_arg *ftmn_arg; +#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..b3220ed --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/kernel/thread_private_arch.h @@ -0,0 +1,259 @@ +/* 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__)) || \ + defined(CFG_CORE_SANITIZE_KADDRESS) +#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 +#if defined(CFG_CORE_SANITIZE_KADDRESS) +#define STACK_THREAD_SIZE (10240 + CFG_STACK_THREAD_EXTRA) +#else +#define STACK_THREAD_SIZE (8192 + CFG_STACK_THREAD_EXTRA) +#endif + +#define STACK_ABT_SIZE 3072 +#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); + +/* + * The thread_rpc() function suspends current thread and temporarily 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 ARM64 +void thread_rpc_spsr(uint32_t rv[THREAD_RPC_NUM_ARGS], uint64_t spsr); +void __thread_rpc(uint32_t rv[THREAD_RPC_NUM_ARGS]); + +#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]; + }; +}; + +static inline void thread_rpc(struct thread_rpc_arg *rpc_arg) +{ + __thread_rpc(rpc_arg->pad); +} +#else +static inline void thread_rpc(uint32_t rv[THREAD_RPC_NUM_ARGS]) +{ + __thread_rpc(rv); +} +#endif +#endif +#ifdef ARM32 +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..7a03f40 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/kernel/thread_spmc.h @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021-2024, Arm Limited. + * Copyright (c) 2023, Linaro Limited + */ +#ifndef __KERNEL_THREAD_SPMC_H +#define __KERNEL_THREAD_SPMC_H + +#include +#include +#include +#include + +/* The FF-A ID of Secure World components should be between these limits */ +#define FFA_SWD_ID_MIN 0x8000 +#define FFA_SWD_ID_MAX UINT16_MAX + +/* + * OP-TEE FF-A partition ID. This is valid both when + * - the SPMC is implemented by OP-TEE and the core OP-TEE functionality runs + * in a logical SP that resides at the same exception level as the SPMC, or, + * - the SPMC is at a higher EL and OP-TEE is running as a standalone S-EL1 SP. + */ +extern uint16_t optee_endpoint_id; + +/* + * FF-A ID of the SPMC. This is valid both when the SPMC is implemented in + * OP-TEE or at a higher EL. + */ +extern uint16_t spmc_id; + +#if defined(CFG_CORE_SEL1_SPMC) +/* FF-A ID of the SPMD. This is only valid when OP-TEE is the S-EL1 SPMC. */ +extern uint16_t spmd_id; +#endif + +#define SPMC_CORE_SEL1_MAX_SHM_COUNT 64 + +struct ffa_rxtx { + void *rx; + void *tx; + unsigned int size; + unsigned int spinlock; + uint32_t ffa_vers; + bool tx_is_mine; +}; + +void spmc_handle_spm_id_get(struct thread_smc_args *args); +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); +uint32_t spmc_exchange_version(uint32_t vers, struct ffa_rxtx *rxtx); + +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); +TEE_Result spmc_fill_partition_entry(uint32_t ffa_vers, void *buf, size_t blen, + size_t idx, uint16_t endpoint_id, + uint16_t execution_context, + uint32_t part_props, + const uint32_t uuid_words[4]); +int spmc_read_mem_transaction(uint32_t ffa_vers, void *buf, size_t blen, + struct ffa_mem_transaction_x *trans); + +#if defined(CFG_CORE_SEL1_SPMC) +void thread_spmc_set_async_notif_intid(int intid); +#else +static inline void __noreturn +thread_spmc_set_async_notif_intid(int intid __unused) +{ + panic(); +} +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..92d596a --- /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 __KERNEL_TLB_HELPERS_H +#define __KERNEL_TLB_HELPERS_H + +#include + +#ifndef __ASSEMBLER__ +#include + +void tlbi_all(void); +void tlbi_asid(unsigned long asid); +void tlbi_va_allasid(unsigned long addr); + +static inline void tlbi_va_allasid_nosync(vaddr_t va) +{ +#ifdef ARM64 + tlbi_vaae1is(va >> TLBI_VA_SHIFT); +#else + write_tlbimvaais(va); +#endif +} + +static inline void tlbi_va_asid_nosync(vaddr_t va, uint32_t asid) +{ + uint32_t a = asid & TLBI_ASID_MASK; + +#ifdef ARM64 + tlbi_vale1is((va >> TLBI_VA_SHIFT) | SHIFT_U64(a, TLBI_ASID_SHIFT)); + tlbi_vale1is((va >> TLBI_VA_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_va_asid(vaddr_t va, uint32_t asid) +{ + dsb_ishst(); + tlbi_va_asid_nosync(va, asid); + dsb_ish(); + isb(); +} +#endif /*!__ASSEMBLER__*/ + +#endif /* __KERNEL_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..2d69b85 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/kernel/tz_proc_def.h @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#ifndef __KERNEL_TZ_PROC_DEF_H +#define __KERNEL_TZ_PROC_DEF_H + +#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) + +#endif /*__KERNEL_TZ_PROC_DEF_H*/ 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..e69e81b --- /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 __KERNEL_TZ_SSVCE_DEF_H +#define __KERNEL_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 /* __KERNEL_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..7112c09 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/kernel/tz_ssvce_pl310.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#ifndef __KERNEL_TZ_SSVCE_PL310_H +#define __KERNEL_TZ_SSVCE_PL310_H + +#include +#include +#include + +vaddr_t pl310_base(void); +vaddr_t pl310_nsbase(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 /* __KERNEL_TZ_SSVCE_PL310_H */ diff --git a/optee/optee_os/core/arch/arm/include/kernel/user_access_arch.h b/optee/optee_os/core/arch/arm/include/kernel/user_access_arch.h new file mode 100644 index 0000000..5dea613 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/kernel/user_access_arch.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2023, Amazon.com Inc. or its affiliates. All rights Reserved. + */ + +#ifndef __KERNEL_USER_ACCESS_ARCH_H +#define __KERNEL_USER_ACCESS_ARCH_H + +#include + +#ifdef CFG_PAN +/* Enter a section where user mode access is temporarily enabled. */ +static inline void enter_user_access(void) +{ + write_pan_disable(); +} + +/* Exit from the section where user mode access was temporarily enabled. */ +static inline void exit_user_access(void) +{ + write_pan_enable(); +} +#else +static inline void enter_user_access(void) {} +static inline void exit_user_access(void) {} +#endif /* CFG_PAN */ + +#endif /* __KERNEL_USER_ACCESS_ARCH_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..f42ca97 --- /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..9de0431 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/mm/core_mmu_arch.h @@ -0,0 +1,232 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#ifndef __MM_CORE_MMU_ARCH_H +#define __MM_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); + +#if defined(ARM64) +unsigned int core_mmu_arm64_get_pa_width(void); +#endif + +static inline bool core_mmu_check_max_pa(paddr_t pa __maybe_unused) +{ +#if defined(ARM64) + return pa <= (BIT64(core_mmu_arm64_get_pa_width()) - 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; +} + +static inline bool core_mmu_level_in_range(unsigned int level) +{ +#if CORE_MMU_BASE_TABLE_LEVEL == 0 + return level <= CORE_MMU_PGDIR_LEVEL; +#else + return level >= CORE_MMU_BASE_TABLE_LEVEL && + level <= CORE_MMU_PGDIR_LEVEL; +#endif +} + +#endif /*__ASSEMBLER__*/ + +#endif /* __MM_CORE_MMU_ARCH_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..367dd35 --- /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_WITH_PAGER) && 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..b5adffa --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/optee_ffa.h @@ -0,0 +1,184 @@ +/* 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: Not 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 OP-TEE capabilities OPTEE_FFA_SEC_CAP_* + * w6: The maximum secure world notification number + * 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) +/* OP-TEE supports asynchronous notification via FF-A */ +#define OPTEE_FFA_SEC_CAP_ASYNC_NOTIF BIT(1) + +#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: Not used (MBZ) + */ +#define OPTEE_FFA_UNREGISTER_SHM OPTEE_FFA_BLOCKING_CALL(3) + +/* + * Inform OP-TEE that normal world is able to receive asynchronous + * notifications. + * + * Call register usage: + * w3: Service ID, OPTEE_FFA_ENABLE_ASYNC_NOTIF + * w4: Notification value to request bottom half processing, should be + * less than OPTEE_FFA_MAX_ASYNC_NOTIF_VALUE + * w5-w7: Not used (MBZ) + * + * Return register usage: + * w3: Error code, 0 on success + * w4-w7: Not used (MBZ) + */ +#define OPTEE_FFA_ENABLE_ASYNC_NOTIF OPTEE_FFA_BLOCKING_CALL(5) + +#define OPTEE_FFA_MAX_ASYNC_NOTIF_VALUE 64 + +/* + * 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..d969e23 --- /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_SCMI_SERVER_H +#define __SCMI_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_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..fe9aff0 --- /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 __SM_OPTEE_SMC_H +#define __SM_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 /* __SM_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..351095a --- /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..95ccdfa --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/sm/psci.h @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017-2023, Linaro Limited + */ +#ifndef __SM_PSCI_H +#define __SM_PSCI_H + +#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); +#endif /* __SM_PSCI_H */ 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..9e7b987 --- /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..80e71a8 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/sm/std_smc.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017-2023, Linaro Limited + */ +#ifndef __SM_STD_SMC_H__ +#define __SM_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..7213531 --- /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 __SM_TEESMC_OPTEED_H +#define __SM_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 /*__SM_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..2171c62 --- /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 __SM_TEESMC_OPTEED_MACROS_H +#define __SM_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 /*__SM_TEESMC_OPTEED_MACROS_H*/ diff --git a/optee/optee_os/core/arch/arm/include/sm/watchdog_smc.h b/optee/optee_os/core/arch/arm/include/sm/watchdog_smc.h new file mode 100644 index 0000000..555d519 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/sm/watchdog_smc.h @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) STMicroelectronics 2023 + */ +#ifndef __SM_WATCHDOG_SMC_H +#define __SM_WATCHDOG_SMC_H + +/* + * This file describes the secure watchdog management service. + * It exposes the SMC supported commands. + * We're following ARM SMC Calling Convention as specified in + * https://developer.arm.com/documentation/den0028. + */ + +/* + * Overall global call for watchdog interface + * Call requests usage: + * a0 [in] SMC Function ID, CFG_WDT_SM_HANDLER_ID + * [out] PSCI error code return + * a1 [in] Watchdog command (one of SMCWD_*) + * [out] Depends on watchdog command (input a1) + * a2 [in/out] Depends on watchdog command (input a1) + * a3-6 [in/out] Not used + * a7 [in/out] Hypervisor Client ID register + */ + +/* Watchdog supported commands */ + +#define SMCWD_INIT 0 +#define SMCWD_SET_TIMEOUT 1 +#define SMCWD_ENABLE 2 +#define SMCWD_PET 3 +#define SMCWD_GET_TIMELEFT 4 + +/* + * Command SMCWD_INIT : Watchdog initialization + * [in] a1 Set to SMCWD_INIT + * [out] a1 The minimal timeout value in seconds supported + * a2 The maximum timeout value in seconds supported + * Return codes: + * PSCI_RET_SUCCESS - Command success + * PSCI_RET_INTERNAL_FAILURE - Initialization failure + * + * Command SMCWD_SET_TIMEOUT : Watchdog set timeout + * [in] a1 Set to SMCWD_SET_TIMEOUT + * a2 The timeout value in seconds to set + * Return codes: + * PSCI_RET_SUCCESS - Command success + * PSCI_RET_INVALID_PARAMETERS - Incorrect input param + * + * Command SMCWD_ENABLE : Watchdog enable + * [in] a1 Set to SMCWD_ENABLE + * a2 Set to 0 to stop the watchdog, 1 to enable it + * Return codes: + * PSCI_RET_SUCCESS - Command success + * PSCI_RET_INVALID_PARAMETERS - Incorrect input param + * + * Command SMCWD_PET : Ping the watchdog for refresh + * [in] a1 Set to SMCWD_PET + * Return codes: + * PSCI_RET_SUCCESS - Command success + * PSCI_RET_DISABLED - The watchdog is not enabled + * + * Command SMCWD_GET_TIMELEFT : Get time left + * [in] a1 Set to SMCWD_GET_TIMELEFT + * [out] a1 The timeout value in seconds before watchdog expires + * Return codes: + * PSCI_RET_SUCCESS - Command success + * PSCI_RET_DISABLED - The watchdog is not enabled + * PSCI_RET_NOT_SUPPORTED - Function not supported + * + * Other commands + * [in] a1 Other values + * Return codes: + * PSCI_RET_NOT_SUPPORTED - Function not supported + * + * a3-6 Not used + * a7 Hypervisor Client ID register + */ + +#endif /* __SM_WATCHDOG_SMC_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..b6e77da --- /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..c5d5c91 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/abort.c @@ -0,0 +1,591 @@ +// 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 + +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(""); + if (IS_ENABLED(CFG_MEMTAG)) + EMSG_RAW("%s %s-abort at address 0x%" PRIxVA + " [tagged 0x%" PRIxVA "]%s", ctx, + abort_type_to_str(ai->abort_type), + memtag_strip_tag_vaddr((void *)ai->va), ai->va, + fault_to_str(ai->abort_type, ai->fault_descr)); + else + 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; + uint32_t pan_bit = 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 + + if (IS_ENABLED(CFG_PAN) && feat_pan_implemented() && read_pan()) + pan_bit = SPSR_64_PAN; + 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) | + pan_bit; +} +#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..1a865dc --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/arch_scall.c @@ -0,0 +1,154 @@ +// 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 + +#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) +{ + TEE_Result res = TEE_SUCCESS; + uint64_t x29 = 0; + uint64_t elr = 0; + + res = GET_USER_SCALAR(x29, &pushed[0]); + if (res) + x29 = 0; + + res = GET_USER_SCALAR(elr, &pushed[1]); + if (res) + elr = 0; + + tsd->abort_regs = (struct thread_abort_regs){ + .x29 = x29, + .elr = elr, + .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..1bafd6d --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/asm-defines.c @@ -0,0 +1,174 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016-2022, Linaro Limited + */ + +#include +#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)) + DEFINE(THREAD_CTX_FLAGS, + offsetof(struct thread_ctx, flags)) +#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)); +#if defined(ARM64) && defined(CFG_CORE_FFA) + DEFINE(THREAD_CORE_LOCAL_DIRECT_RESP_FID, + offsetof(struct thread_core_local, direct_resp_fid)); +#endif + + 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)); + +#ifdef CORE_MMU_BASE_TABLE_OFFSET + /* + * This define is too complex to be used as an argument for the + * macros add_imm and sub_imm so evaluate it here. + */ + DEFINE(__CORE_MMU_BASE_TABLE_OFFSET, CORE_MMU_BASE_TABLE_OFFSET); +#endif + +} 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..5554587 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/boot.c @@ -0,0 +1,1740 @@ +// 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 + +#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 + +static void *manifest_dt __nex_bss; +static unsigned long boot_arg_fdt __nex_bss; +static unsigned long boot_arg_nsec_entry __nex_bss; +static unsigned long boot_arg_pageable_part __nex_bss; +static unsigned long boot_arg_transfer_list __nex_bss; +static struct transfer_list_header *mapped_tl __nex_bss; + +#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 boot_primary_init_intc(void) +{ +} + +/* May be overridden in plat-$(PLATFORM)/main.c */ +__weak void boot_secondary_init_intc(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) || defined(CFG_WITH_STACK_CANARIES) +/* Generate random stack canary value on boot up */ +__weak void plat_get_random_stack_canaries(void *buf, size_t ncan, size_t size) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + size_t i = 0; + + assert(buf && ncan && size); + + /* + * 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"); + memset(buf, 0xab, ncan * size); + goto out; + } + + ret = crypto_rng_read(buf, ncan * size); + if (ret != TEE_SUCCESS) + panic("Failed to generate random stack canary"); + +out: + /* Leave null byte in canary to prevent string base exploit */ + for (i = 0; i < ncan; i++) + *((uint8_t *)buf + size * i) = 0; +} +#endif /* _CFG_CORE_STACK_PROTECTOR || CFG_WITH_STACK_CANARIES */ + +/* + * 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 + +static void check_crypto_extensions(void) +{ + bool ce_supported = true; + + if (!feat_aes_implemented() && + IS_ENABLED(CFG_CRYPTO_AES_ARM_CE)) { + EMSG("AES instructions are not supported"); + ce_supported = false; + } + + if (!feat_sha1_implemented() && + IS_ENABLED(CFG_CRYPTO_SHA1_ARM_CE)) { + EMSG("SHA1 instructions are not supported"); + ce_supported = false; + } + + if (!feat_sha256_implemented() && + IS_ENABLED(CFG_CRYPTO_SHA256_ARM_CE)) { + EMSG("SHA256 instructions are not supported"); + ce_supported = false; + } + + /* Check aarch64 specific instructions */ + if (IS_ENABLED(CFG_ARM64_core)) { + if (!feat_sha512_implemented() && + IS_ENABLED(CFG_CRYPTO_SHA512_ARM_CE)) { + EMSG("SHA512 instructions are not supported"); + ce_supported = false; + } + + if (!feat_sha3_implemented() && + IS_ENABLED(CFG_CRYPTO_SHA3_ARM_CE)) { + EMSG("SHA3 instructions are not supported"); + ce_supported = false; + } + + if (!feat_sm3_implemented() && + IS_ENABLED(CFG_CRYPTO_SM3_ARM_CE)) { + EMSG("SM3 instructions are not supported"); + ce_supported = false; + } + + if (!feat_sm4_implemented() && + IS_ENABLED(CFG_CRYPTO_SM4_ARM_CE)) { + EMSG("SM4 instructions are not supported"); + ce_supported = false; + } + } + + if (!ce_supported) + panic("HW doesn't support CE instructions"); +} + +#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); +#ifdef ARM32 + asan_tag_access(__exidx_start, __exidx_end); + asan_tag_access(__extab_start, __extab_end); +#endif + + 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) +{ + memtag_init_ops(feat_mte_implemented()); +} + +/* Called from entry_a64.S only when MEMTAG is configured */ +void boot_clear_memtag(void) +{ + enum teecore_memtypes mtypes[] = { + MEM_AREA_TEE_RAM, MEM_AREA_TEE_RAM_RW, MEM_AREA_NEX_RAM_RO, + MEM_AREA_NEX_RAM_RW, MEM_AREA_TEE_ASAN, MEM_AREA_TA_RAM + }; + vaddr_t s = 0; + vaddr_t e = 0; + size_t n = 0; + + for (n = 0; n < ARRAY_SIZE(mtypes); n++) { + core_mmu_get_mem_by_type(mtypes[n], &s, &e); + if (e > s) { + DMSG("Clearing tags for VA %#"PRIxVA"..%#"PRIxVA, + s, e - 1); + memtag_set_tags((void *)s, e - s, 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 + +#if defined(CFG_DT) +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(IS_ENABLED(CFG_CORE_FFA) || + !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*/ + +#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 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 = get_external_dt_desc(); + + if (!dt || !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*/ +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_FFA) +void *get_manifest_dt(void) +{ + return manifest_dt; +} + +static void reinit_manifest_dt(void) +{ + paddr_t pa = (unsigned long)manifest_dt; + void *fdt = NULL; + int ret = 0; + + if (!pa) { + EMSG("No manifest DT found"); + return; + } + + fdt = core_mmu_add_mapping(MEM_AREA_MANIFEST_DT, pa, CFG_DTB_MAX_SIZE); + if (!fdt) + panic("Failed to map manifest DT"); + + manifest_dt = fdt; + + ret = fdt_check_full(fdt, CFG_DTB_MAX_SIZE); + if (ret < 0) { + EMSG("Invalid manifest Device Tree at %#lx: error %d", pa, ret); + panic(); + } + + IMSG("manifest DT found"); +} + +static TEE_Result release_manifest_dt(void) +{ + if (!manifest_dt) + return TEE_SUCCESS; + + if (core_mmu_remove_mapping(MEM_AREA_MANIFEST_DT, manifest_dt, + CFG_DTB_MAX_SIZE)) + panic("Failed to remove temporary manifest DT mapping"); + manifest_dt = NULL; + + return TEE_SUCCESS; +} + +boot_final(release_manifest_dt); +#else +void *get_manifest_dt(void) +{ + return NULL; +} + +static void reinit_manifest_dt(void) +{ +} +#endif /*CFG_CORE_FFA*/ + +#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 external DT"); + } + + fdt = get_embedded_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 embedded DT"); + } + + 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(); + + /* + * Reinitialize canaries around the stacks with crypto_rng_read(). + * + * TODO: Updating canaries when CFG_NS_VIRTUALIZATION is enabled will + * require synchronization between thread_check_canaries() and + * thread_update_canaries(). + */ + if (!IS_ENABLED(CFG_NS_VIRTUALIZATION)) + thread_update_canaries(); +} + +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(); + + if (IS_ENABLED(CFG_CRYPTO_WITH_CE)) + check_crypto_extensions(); + + /* + * 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 __unused, + unsigned long manifest __unused) +{ + size_t fdt_size = CFG_DTB_MAX_SIZE; + + if (IS_ENABLED(CFG_TRANSFER_LIST) && mapped_tl) { + struct transfer_list_entry *tl_e = NULL; + + tl_e = transfer_list_find(mapped_tl, TL_TAG_FDT); + if (tl_e) + fdt_size = tl_e->data_size; + } + + init_external_dt(boot_arg_fdt, fdt_size); + reinit_manifest_dt(); +#ifdef CFG_CORE_SEL1_SPMC + tpm_map_log_area(get_manifest_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_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"); + } + + boot_primary_init_intc(); + 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) +{ + DMSG("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); + boot_secondary_init_intc(); + init_vfp_sec(); + init_vfp_nsec(); + + DMSG("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(void) +{ + unsigned long pageable_part = 0; + unsigned long e = PADDR_INVALID; + struct transfer_list_entry *tl_e = NULL; + + if (!IS_ENABLED(CFG_WITH_ARM_TRUSTED_FW)) + e = boot_arg_nsec_entry; + + if (IS_ENABLED(CFG_TRANSFER_LIST) && boot_arg_transfer_list) { + /* map and save the TL */ + mapped_tl = transfer_list_map(boot_arg_transfer_list); + if (!mapped_tl) + panic("Failed to map transfer list"); + + transfer_list_dump(mapped_tl); + tl_e = transfer_list_find(mapped_tl, TL_TAG_FDT); + if (tl_e) { + /* + * Expand the data size of the DTB entry to the maximum + * allocable mapped memory to reserve sufficient space + * for inserting new nodes, avoid potentially corrupting + * next entries. + */ + uint32_t dtb_max_sz = mapped_tl->max_size - + mapped_tl->size + tl_e->data_size; + + if (!transfer_list_set_data_size(mapped_tl, tl_e, + dtb_max_sz)) { + EMSG("Failed to extend DTB size to %#"PRIx32, + dtb_max_sz); + panic(); + } + } + tl_e = transfer_list_find(mapped_tl, TL_TAG_OPTEE_PAGABLE_PART); + } + + if (IS_ENABLED(CFG_WITH_PAGER)) { + if (IS_ENABLED(CFG_TRANSFER_LIST) && tl_e) + pageable_part = + get_le64(transfer_list_entry_data(tl_e)); + else + pageable_part = boot_arg_pageable_part; + } + + init_primary(pageable_part, e); +} + +static void boot_save_transfer_list(unsigned long zero_reg, + unsigned long transfer_list, + unsigned long fdt) +{ + struct transfer_list_header *tl = (void *)transfer_list; + struct transfer_list_entry *tl_e = NULL; + + if (zero_reg != 0) + panic("Incorrect transfer list register convention"); + + if (!IS_ALIGNED_WITH_TYPE(transfer_list, struct transfer_list_header) || + !IS_ALIGNED(transfer_list, TL_ALIGNMENT_FROM_ORDER(tl->alignment))) + panic("Transfer list base address is not aligned"); + + if (transfer_list_check_header(tl) == TL_OPS_NONE) + panic("Invalid transfer list"); + + tl_e = transfer_list_find(tl, TL_TAG_FDT); + if (fdt != (unsigned long)transfer_list_entry_data(tl_e)) + panic("DT does not match to the DT entry of the TL"); + + boot_arg_transfer_list = transfer_list; +} + +#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) +{ + void *fdt = NULL; + int rc = 0; + const uint64_t *seed = NULL; + int offs = 0; + int len = 0; + + if (!IS_ENABLED(CFG_CORE_SEL2_SPMC)) + fdt = (void *)boot_arg_fdt; + + 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) +{ + /* Try platform implementation */ + return plat_get_aslr_seed(); +} +#endif /*!CFG_DT*/ +#endif /*CFG_CORE_ASLR*/ + +static void *get_fdt_from_boot_info(struct ffa_boot_info_header_1_1 *hdr) +{ + struct ffa_boot_info_1_1 *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_args(unsigned long a0, unsigned long a1, + unsigned long a2, unsigned long a3, + unsigned long a4 __maybe_unused) +{ + /* + * Register use: + * + * Scenario A: Default arguments + * a0 - 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 || CFG_CORE_EL3_SPMC=y): + * address of FF-A Boot Information Blob + * - CFG_CORE_FFA=n: + * if non-NULL holds the pagable part address + * a1 - CFG_WITH_ARM_TRUSTED_FW=n (Armv7): + * Armv7 standard bootarg #1 (kept track of in entry_a32.S) + * a2 - CFG_CORE_SEL2_SPMC=n: + * if non-NULL holds the system DTB address + * - CFG_WITH_ARM_TRUSTED_FW=n (Armv7): + * Armv7 standard bootarg #2 (system DTB address, kept track + * of in entry_a32.S) + * a3 - Not used + * a4 - CFG_WITH_ARM_TRUSTED_FW=n: + * Non-secure entry address + * + * [1] A TF-A concept: TOS_FW_CONFIG - Trusted OS Firmware + * configuration file. Used by Trusted OS (BL32), that is, OP-TEE + * here. This is also called Manifest DT, related to the Manifest DT + * passed in the FF-A Boot Information Blob, but with a different + * compatible string. + + * Scenario B: FW Handoff via Transfer List + * Note: FF-A and non-secure entry are not yet supported with + * Transfer List + * a0 - DTB address or 0 (AArch64) + * - must be 0 (AArch32) + * a1 - TRANSFER_LIST_SIGNATURE | REG_CONVENTION_VER_MASK + * a2 - must be 0 (AArch64) + * - DTB address or 0 (AArch32) + * a3 - Transfer list base address + * a4 - Not used + */ + + if (IS_ENABLED(CFG_TRANSFER_LIST) && + a1 == (TRANSFER_LIST_SIGNATURE | REG_CONVENTION_VER_MASK)) { + if (IS_ENABLED(CFG_ARM64_core)) { + boot_save_transfer_list(a2, a3, a0); + boot_arg_fdt = a0; + } else { + boot_save_transfer_list(a0, a3, a2); + boot_arg_fdt = a2; + } + return; + } + + if (!IS_ENABLED(CFG_CORE_SEL2_SPMC)) { +#if defined(CFG_DT_ADDR) + boot_arg_fdt = CFG_DT_ADDR; +#else + boot_arg_fdt = a2; +#endif + } + + if (IS_ENABLED(CFG_CORE_FFA)) { + if (IS_ENABLED(CFG_CORE_SEL2_SPMC) || + IS_ENABLED(CFG_CORE_EL3_SPMC)) + manifest_dt = get_fdt_from_boot_info((void *)a0); + else + manifest_dt = (void *)a0; + if (IS_ENABLED(CFG_CORE_SEL2_SPMC) && + IS_ENABLED(CFG_CORE_PHYS_RELOCATABLE)) { + paddr_t base = 0; + size_t size = 0; + + get_sec_mem_from_manifest(manifest_dt, &base, &size); + core_mmu_set_secure_memory(base, size); + } + } else { + if (IS_ENABLED(CFG_WITH_PAGER)) { +#if defined(CFG_PAGEABLE_ADDR) + boot_arg_pageable_part = CFG_PAGEABLE_ADDR; +#else + boot_arg_pageable_part = a0; +#endif + } + if (!IS_ENABLED(CFG_WITH_ARM_TRUSTED_FW)) { +#if defined(CFG_NS_ENTRY_ADDR) + boot_arg_nsec_entry = CFG_NS_ENTRY_ADDR; +#else + boot_arg_nsec_entry = a4; +#endif + } + } +} + +#if defined(CFG_TRANSFER_LIST) +static TEE_Result release_transfer_list(void) +{ + struct dt_descriptor *dt = get_external_dt_desc(); + + if (!mapped_tl) + return TEE_SUCCESS; + + if (dt) { + int ret = 0; + struct transfer_list_entry *tl_e = NULL; + + /* + * Pack the DTB and update the transfer list before un-mapping + */ + ret = fdt_pack(dt->blob); + if (ret < 0) { + EMSG("Failed to pack Device Tree at 0x%" PRIxPA + ": error %d", virt_to_phys(dt->blob), ret); + panic(); + } + + tl_e = transfer_list_find(mapped_tl, TL_TAG_FDT); + assert(dt->blob == transfer_list_entry_data(tl_e)); + transfer_list_set_data_size(mapped_tl, tl_e, + fdt_totalsize(dt->blob)); + dt->blob = NULL; + } + + transfer_list_unmap_sync(mapped_tl); + mapped_tl = NULL; + + return TEE_SUCCESS; +} + +boot_final(release_transfer_list); +#endif + +#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..2ed02a9 --- /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_va 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_va civac +END_FUNC dcache_cleaninv_range + + /* ------------------------------------------ + * Clean from base address till size. + * 'x0' = addr, 'x1' = size + * ------------------------------------------ + */ +FUNC dcache_clean_range , : + do_dcache_maintenance_by_va cvac +END_FUNC dcache_clean_range + + /* ------------------------------------------ + * Invalidate from base address till + * size. 'x0' = addr, 'x1' = size + * ------------------------------------------ + */ +FUNC dcache_inv_range , : + do_dcache_maintenance_by_va 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_va 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..a43d36a --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/entry_a32.S @@ -0,0 +1,898 @@ +/* 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 + + .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) + /* + * Temporary copy of boot argument registers, will be passed to + * boot_save_args() further down. + */ + mov r4, r0 + mov r5, r1 + mov r6, r2 + mov r7, r3 + mov r8, lr + + /* + * 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-r8: 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, r9-r12} + stmdb r0!, {r3, r9-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, r9-r12} + stmdb r0!, {r3, r9-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 + + mov r0, r8 + mov r1, #0 + push {r0, r1} + mov r0, r4 + mov r1, r5 + mov r2, r6 + mov r3, r7 + bl boot_save_args + add sp, sp, #(2 * 4) + +#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 + 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 + + 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 + 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 */ + sub sp, sp, #0x8 + mov r0, sp + mov r1, #1 + mov r2, #0x4 + bl plat_get_random_stack_canaries + ldr r0, [sp] + ldr r1, =__stack_chk_guard + str r0, [r1] + add sp, sp, #0x8 +#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 + /* Relay standard bootarg #1 and #2 to non-secure entry */ + mov r4, #0 + mov r3, r6 /* std bootarg #2 for register R2 */ + mov r2, r5 /* 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, r8 /* 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..3039a0c --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/entry_a64.S @@ -0,0 +1,762 @@ +/* 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 read_feat_pan reg + mrs \reg, id_mmfr3_el1 + ubfx \reg, \reg, #ID_MMFR3_EL1_PAN_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 + + .macro init_pan + read_feat_pan x0 + cmp x0, #0 + b.eq 1f + mrs x0, sctlr_el1 + bic x0, x0, #SCTLR_SPAN + msr sctlr_el1, x0 + write_pan_enable + 1: + .endm + +FUNC _start , : + /* + * Temporary copy of boot argument registers, will be passed to + * boot_save_args() further down. + */ + mov x19, x0 + mov x20, x1 + mov x21, x2 + mov x22, x3 + + adr x0, reset_vect_table + msr vbar_el1, x0 + isb + +#ifdef CFG_PAN + init_pan +#endif + + 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_l x0, __nex_bss_start + adr_l 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 + mov x0, x19 + mov x1, x20 + mov x2, x21 + mov x3, x22 + mov x4, xzr + bl boot_save_args + +#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 + 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_MEMTAG + bl boot_clear_memtag +#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 + + bl boot_init_primary_early + +#ifdef CFG_MEMTAG + init_memtag_per_cpu +#endif + +#ifndef CFG_NS_VIRTUALIZATION + mov x23, sp + adr_l x0, threads + ldr x0, [x0, #THREAD_CTX_STACK_VA_END] + mov sp, x0 + bl thread_get_core_local + mov x24, x0 + str wzr, [x24, #THREAD_CORE_LOCAL_FLAGS] +#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, [x24, #THREAD_CORE_LOCAL_FLAGS] + mov sp, x23 +#endif + +#ifdef _CFG_CORE_STACK_PROTECTOR + /* Update stack canary value */ + sub sp, sp, #0x10 + mov x0, sp + mov x1, #1 + mov x2, #0x8 + bl plat_get_random_stack_canaries + ldr x0, [sp] + adr_l x5, __stack_chk_guard + str x0, [x5] + add sp, sp, #0x10 +#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 + +#ifdef CFG_PAN + init_pan +#endif + + /* 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/generic_timer.c b/optee/optee_os/core/arch/arm/kernel/generic_timer.c new file mode 100644 index 0000000..5d101fc --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/generic_timer.c @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2024, Linaro Limited + */ + +#include +#include +#include + +static void timer_disable(const struct callout_timer_desc *desc __unused) +{ + write_cntps_ctl(0); +} + +static void timer_set_next(const struct callout_timer_desc *desc __unused, + uint64_t ctrval) +{ + write_cntps_cval(ctrval); + write_cntps_ctl(1); +} + +static uint64_t +timer_ms_to_ticks(const struct callout_timer_desc *desc __unused, + uint32_t timeout_ms) +{ + uint64_t freq = read_cntfrq(); + + return (freq * timeout_ms) / 1000; +} + +static uint64_t timer_now(const struct callout_timer_desc *desc __unused) +{ + return barrier_read_counter_timer(); +} + +static struct itr_handler timer_itr __nex_bss; +static const struct callout_timer_desc timer_desc +__relrodata_unpaged("timer_desc") = { + .disable_timeout = timer_disable, + .set_next_timeout = timer_set_next, + .ms_to_ticks = timer_ms_to_ticks, + .get_now = timer_now, + .is_per_cpu = true, +}; +DECLARE_KEEP_PAGER(timer_desc); + +static enum itr_return timer_itr_cb(struct itr_handler *h __unused) +{ + callout_service_cb(); + + return ITRR_HANDLED; +} +DECLARE_KEEP_PAGER(timer_itr_cb); + +void timer_init_callout_service(struct itr_chip *itr_chip, size_t itr_number) +{ + timer_itr = (struct itr_handler){ + .it = itr_number, + .flags = ITRF_TRIGGER_LEVEL, + .handler = timer_itr_cb, + }; + + if (interrupt_add_handler_with_chip(itr_chip, &timer_itr)) + panic(); + + interrupt_enable(timer_itr.chip, timer_itr.it); + callout_service_init(&timer_desc); +} 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..7c7e8a0 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/link.mk @@ -0,0 +1,268 @@ +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) + +ifeq ($(CFG_TEGRA_PREBUILT_BINARY),y) +link-ldadd += --whole-archive $(TEGRA_PREBUILT_BINARY) --no-whole-archive +endif + +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..c3617b2 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/link_dummies_init.c @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020, Linaro Limited + */ +#include +#include +#include + +void __section(".text.dummy.boot_save_boot_info") +boot_save_args(unsigned long a0 __unused, unsigned long a1 __unused, + unsigned long a2 __unused, unsigned long a3 __unused, + unsigned long a4 __unused) +{ +} + +unsigned long __section(".text.dummy.get_aslr_seed") +get_aslr_seed(void) +{ + 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(void) +{ +} 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..d989ed1 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/link_dummies_paged.c @@ -0,0 +1,55 @@ +// 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 + +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 manifest __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_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..46f3557 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/secure_partition.c @@ -0,0 +1,1960 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020-2024, 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 + +#define BOUNCE_BUFFER_SIZE 4096 + +#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_MANIFEST_NS_INT_QUEUED (0x0) +#define SP_MANIFEST_NS_INT_MANAGED_EXIT (0x1) +#define SP_MANIFEST_NS_INT_SIGNALED (0x2) + +#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(uint32_t ffa_vers, void *buf, size_t buf_size, + const TEE_UUID *ffa_uuid, size_t *elem_count, + bool count_only) +{ + TEE_Result res = TEE_SUCCESS; + uint32_t part_props = FFA_PART_PROP_DIRECT_REQ_RECV | + FFA_PART_PROP_DIRECT_REQ_SEND; + struct sp_session *s = NULL; + + 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_only && !res) { + uint32_t uuid_words[4] = { 0 }; + + tee_uuid_to_octets((uint8_t *)uuid_words, &s->ffa_uuid); + res = spmc_fill_partition_entry(ffa_vers, buf, buf_size, + *elem_count, + s->endpoint_id, 1, + part_props, uuid_words); + } + *elem_count += 1; + } + + return res; +} + +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 bool endpoint_id_is_valid(uint32_t id) +{ + /* + * These IDs are assigned at the SPMC init so already have valid values + * by the time this function gets first called + */ + return id != spmd_id && id != spmc_id && id != optee_endpoint_id && + id >= FFA_SWD_ID_MIN && id <= FFA_SWD_ID_MAX; +} + +static TEE_Result new_session_id(uint16_t *endpoint_id) +{ + uint32_t id = 0; + + /* Find the first available endpoint id */ + for (id = FFA_SWD_ID_MIN; id <= FFA_SWD_ID_MAX; id++) { + if (endpoint_id_is_valid(id) && !sp_get_session(id)) { + *endpoint_id = id; + return TEE_SUCCESS; + } + } + + return TEE_ERROR_BAD_FORMAT; +} + +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; +} + +/* + * Insert a new sp_session to the sessions list, so that it is ordered + * by boot_order. + */ +static void insert_session_ordered(struct sp_sessions_head *open_sessions, + struct sp_session *session) +{ + struct sp_session *s = NULL; + + if (!open_sessions || !session) + return; + + TAILQ_FOREACH(s, &open_sp_sessions, link) { + if (s->boot_order > session->boot_order) + break; + } + + if (!s) + TAILQ_INSERT_TAIL(open_sessions, session, link); + else + TAILQ_INSERT_BEFORE(s, session, link); +} + +static TEE_Result sp_create_session(struct sp_sessions_head *open_sessions, + const TEE_UUID *bin_uuid, + const uint32_t boot_order, + 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->boot_order = boot_order; + + res = new_session_id(&s->endpoint_id); + if (res) + goto err; + + DMSG("Loading Secure Partition %pUl", (void *)bin_uuid); + res = sp_create_ctx(bin_uuid, s); + if (res) + goto err; + + insert_session_ordered(open_sessions, s); + *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_u16(const void *fdt, int node, const char *property, + uint16_t *value) +{ + const fdt16_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 = fdt16_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; + size_t bb_size = ROUNDUP(BOUNCE_BUFFER_SIZE, SMALL_PAGE_SIZE); + size_t bb_num_pages = bb_size / SMALL_PAGE_SIZE; + 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 fobj *fobj = 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); + + /* Initialize the bounce buffer */ + fobj = fobj_sec_mem_alloc(bb_num_pages); + 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(uctx, &va, bb_size, TEE_MATTR_PRW, 0, mobj, 0); + mobj_put(mobj); + if (res) + return res; + + uctx->bbuf = (uint8_t *)va; + uctx->bbuf_size = BOUNCE_BUFFER_SIZE; + + 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 */ + va = 0; + 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, NULL, (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 uint32_t boot_order, + 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, boot_order, &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. + * Set state to busy to prevent other endpoints from sending messages to + * the SP before its boot phase is done. + */ + s->state = sp_busy; + 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; +} + +static TEE_Result copy_and_map_fdt(struct sp_ctx *ctx, const void * const fdt, + void **fdt_copy, size_t *mapped_size) +{ + size_t total_size = ROUNDUP(fdt_totalsize(fdt), SMALL_PAGE_SIZE); + size_t num_pages = total_size / SMALL_PAGE_SIZE; + uint32_t perm = TEE_MATTR_UR | TEE_MATTR_PRW; + TEE_Result res = TEE_SUCCESS; + struct mobj *m = NULL; + struct fobj *f = NULL; + vaddr_t va = 0; + + f = fobj_sec_mem_alloc(num_pages); + 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; + + if (fdt_open_into(fdt, (void *)va, total_size)) + return TEE_ERROR_GENERIC; + + *fdt_copy = (void *)va; + *mapped_size = total_size; + + return res; +} + +static void fill_boot_info_1_0(vaddr_t buf, const void *fdt) +{ + struct ffa_boot_info_1_0 *info = (struct ffa_boot_info_1_0 *)buf; + static const char fdt_name[16] = "TYPE_DT\0\0\0\0\0\0\0\0"; + + memcpy(&info->magic, "FF-A", 4); + info->count = 1; + + 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 = (uintptr_t)fdt; + info->nvp[0].size = fdt_totalsize(fdt); +} + +static void fill_boot_info_1_1(vaddr_t buf, const void *fdt) +{ + size_t desc_offs = ROUNDUP(sizeof(struct ffa_boot_info_header_1_1), 8); + struct ffa_boot_info_header_1_1 *header = + (struct ffa_boot_info_header_1_1 *)buf; + struct ffa_boot_info_1_1 *desc = + (struct ffa_boot_info_1_1 *)(buf + desc_offs); + + header->signature = FFA_BOOT_INFO_SIGNATURE; + header->version = FFA_BOOT_INFO_VERSION; + header->blob_size = desc_offs + sizeof(struct ffa_boot_info_1_1); + header->desc_size = sizeof(struct ffa_boot_info_1_1); + header->desc_count = 1; + header->desc_offset = desc_offs; + + memset(&desc[0].name, 0, sizeof(desc[0].name)); + /* Type: Standard boot info (bit[7] == 0), FDT type */ + desc[0].type = FFA_BOOT_INFO_TYPE_ID_FDT; + /* Flags: Contents field contains an address */ + desc[0].flags = FFA_BOOT_INFO_FLAG_CONTENT_FORMAT_ADDR << + FFA_BOOT_INFO_FLAG_CONTENT_FORMAT_SHIFT; + desc[0].size = fdt_totalsize(fdt); + desc[0].contents = (uintptr_t)fdt; +} + +static TEE_Result create_and_map_boot_info(struct sp_ctx *ctx, const void *fdt, + struct thread_smc_args *args, + vaddr_t *va, size_t *mapped_size, + uint32_t sp_ffa_version) +{ + size_t total_size = ROUNDUP(CFG_SP_INIT_INFO_MAX_SIZE, SMALL_PAGE_SIZE); + size_t num_pages = total_size / SMALL_PAGE_SIZE; + uint32_t perm = TEE_MATTR_UR | TEE_MATTR_PRW; + TEE_Result res = TEE_SUCCESS; + struct fobj *f = NULL; + struct mobj *m = NULL; + uint32_t info_reg = 0; + + f = fobj_sec_mem_alloc(num_pages); + 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; + + *mapped_size = total_size; + + switch (sp_ffa_version) { + case MAKE_FFA_VERSION(1, 0): + fill_boot_info_1_0(*va, fdt); + break; + case MAKE_FFA_VERSION(1, 1): + fill_boot_info_1_1(*va, fdt); + break; + default: + EMSG("Unknown FF-A version: %#"PRIx32, sp_ffa_version); + return TEE_ERROR_NOT_SUPPORTED; + } + + res = sp_dt_get_u32(fdt, 0, "gp-register-num", &info_reg); + if (res) { + if (res == TEE_ERROR_ITEM_NOT_FOUND) { + /* If the property is not present, set default to x0 */ + info_reg = 0; + } else { + return TEE_ERROR_BAD_FORMAT; + } + } + + switch (info_reg) { + case 0: + args->a0 = *va; + break; + case 1: + args->a1 = *va; + break; + case 2: + args->a2 = *va; + break; + case 3: + args->a3 = *va; + break; + default: + EMSG("Invalid register selected for passing boot info"); + return TEE_ERROR_BAD_FORMAT; + } + + 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_is_valid(endpoint_id)) { + EMSG("Invalid endpoint ID 0x%"PRIx32, 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 read_ns_interrupts_action(const void *fdt, + struct sp_session *s) +{ + TEE_Result res = TEE_ERROR_BAD_PARAMETERS; + + res = sp_dt_get_u32(fdt, 0, "ns-interrupts-action", &s->ns_int_mode); + + if (res) { + EMSG("Mandatory property is missing: ns-interrupts-action"); + return res; + } + + switch (s->ns_int_mode) { + case SP_MANIFEST_NS_INT_QUEUED: + case SP_MANIFEST_NS_INT_SIGNALED: + /* OK */ + break; + + case SP_MANIFEST_NS_INT_MANAGED_EXIT: + EMSG("Managed exit is not implemented"); + return TEE_ERROR_NOT_IMPLEMENTED; + + default: + EMSG("Invalid ns-interrupts-action value: %"PRIu32, + s->ns_int_mode); + return TEE_ERROR_BAD_PARAMETERS; + } + + return TEE_SUCCESS; +} + +static TEE_Result read_ffa_version(const void *fdt, struct sp_session *s) +{ + TEE_Result res = TEE_ERROR_BAD_PARAMETERS; + uint32_t ffa_version = 0; + + res = sp_dt_get_u32(fdt, 0, "ffa-version", &ffa_version); + if (res) { + EMSG("Mandatory property is missing: ffa-version"); + return res; + } + + if (ffa_version != FFA_VERSION_1_0 && ffa_version != FFA_VERSION_1_1) { + EMSG("Invalid FF-A version value: 0x%08"PRIx32, ffa_version); + return TEE_ERROR_BAD_PARAMETERS; + } + + s->rxtx.ffa_vers = ffa_version; + + 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 = {}; + uint16_t boot_order = 0; + uint32_t boot_order_arg = 0; + + res = fdt_get_uuid(fdt, &ffa_uuid); + if (res) + return res; + + res = sp_dt_get_u16(fdt, 0, "boot-order", &boot_order); + if (res == TEE_SUCCESS) { + boot_order_arg = boot_order; + } else if (res == TEE_ERROR_ITEM_NOT_FOUND) { + boot_order_arg = UINT32_MAX; + } else { + EMSG("Failed reading boot-order property err:%#"PRIx32, res); + return res; + } + + res = sp_open_session(&sess, + &open_sp_sessions, + &ffa_uuid, bin_uuid, boot_order_arg, 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); + + res = read_ns_interrupts_action(fdt, sess); + if (res) + return res; + + res = read_ffa_version(fdt, sess); + if (res) + return res; + + return TEE_SUCCESS; +} + +static TEE_Result sp_first_run(struct sp_session *sess) +{ + TEE_Result res = TEE_SUCCESS; + struct thread_smc_args args = { }; + struct sp_ctx *ctx = NULL; + vaddr_t boot_info_va = 0; + size_t boot_info_size = 0; + void *fdt_copy = NULL; + size_t fdt_size = 0; + + ctx = to_sp_ctx(sess->ts_sess.ctx); + ts_push_current_session(&sess->ts_sess); + sess->is_initialized = false; + + /* + * 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 = copy_and_map_fdt(ctx, sess->fdt, &fdt_copy, &fdt_size); + 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; + + res = create_and_map_boot_info(ctx, fdt_copy, &args, &boot_info_va, + &boot_info_size, sess->rxtx.ffa_vers); + if (res) + goto out; + + ts_pop_current_session(); + + res = sp_enter(&args, sess); + if (res) { + ts_push_current_session(&sess->ts_sess); + goto out; + } + + spmc_sp_msg_handler(&args, sess); + + ts_push_current_session(&sess->ts_sess); + sess->is_initialized = true; + +out: + /* Free the boot info page from the SP memory */ + vm_unmap(&ctx->uctx, boot_info_va, boot_info_size); + vm_unmap(&ctx->uctx, (vaddr_t)fdt_copy, fdt_size); + ts_pop_current_session(); + + return res; +} + +TEE_Result sp_enter(struct thread_smc_args *args, struct sp_session *sp) +{ + TEE_Result res = TEE_SUCCESS; + 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; +} + +/* + * According to FF-A v1.1 section 8.3.1.4 if a caller requires less permissive + * active on NS interrupt than the callee, the callee must inherit the caller's + * configuration. + * Each SP's own NS action setting is stored in ns_int_mode. The effective + * action will be MIN([self action], [caller's action]) which is stored in the + * ns_int_mode_inherited field. + */ +static void sp_cpsr_configure_foreign_interrupts(struct sp_session *s, + struct ts_session *caller, + uint64_t *cpsr) +{ + if (caller) { + struct sp_session *caller_sp = to_sp_session(caller); + + s->ns_int_mode_inherited = MIN(caller_sp->ns_int_mode_inherited, + s->ns_int_mode); + } else { + s->ns_int_mode_inherited = s->ns_int_mode; + } + + if (s->ns_int_mode_inherited == SP_MANIFEST_NS_INT_QUEUED) + *cpsr |= SHIFT_U32(THREAD_EXCP_FOREIGN_INTR, + ARM32_CPSR_F_SHIFT); + else + *cpsr &= ~SHIFT_U32(THREAD_EXCP_FOREIGN_INTR, + ARM32_CPSR_F_SHIFT); +} + +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; + struct sp_session *sp_s = to_sp_session(s); + struct ts_session *sess = NULL; + struct thread_ctx_regs *sp_regs = NULL; + uint32_t thread_id = THREAD_ID_INVALID; + struct ts_session *caller = NULL; + uint32_t rpc_target_info = 0; + uint32_t panicked = false; + uint32_t panic_code = 0; + + sp_regs = &ctx->sp_regs; + ts_push_current_session(s); + + exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); + + /* Enable/disable foreign interrupts in CPSR/SPSR */ + caller = ts_get_calling_session(); + sp_cpsr_configure_foreign_interrupts(sp_s, caller, &sp_regs->cpsr); + + /* + * Store endpoint ID and thread ID in rpc_target_info. This will be used + * as w1 in FFA_INTERRUPT in case of a foreign interrupt. + */ + rpc_target_info = thread_get_tsd()->rpc_target_info; + thread_id = thread_get_id(); + assert(thread_id <= UINT16_MAX); + thread_get_tsd()->rpc_target_info = + FFA_TARGET_INFO_SET(sp_s->endpoint_id, thread_id); + + __thread_enter_user_mode(sp_regs, &panicked, &panic_code); + + /* Restore rpc_target_info */ + thread_get_tsd()->rpc_target_info = rpc_target_info; + + 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); + + 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_manifest_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; + struct sp_session *prev_sp = 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(); + + /* + * Now that all SPs are loaded, check through the boot order values, + * and warn in case there is a non-unique value. + */ + TAILQ_FOREACH(s, &open_sp_sessions, link) { + /* User specified boot-order values are uint16 */ + if (s->boot_order > UINT16_MAX) + break; + + if (prev_sp && prev_sp->boot_order == s->boot_order) + IMSG("WARNING: duplicated boot-order (%pUl vs %pUl)", + &prev_sp->ts_sess.ctx->uuid, + &s->ts_sess.ctx->uuid); + + prev_sp = s; + } + + /* Continue the initialization and run the SP */ + TAILQ_FOREACH(s, &open_sp_sessions, link) { + DMSG("Starting SP: 0x%"PRIx16, s->endpoint_id); + + 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/semihosting_a64.S b/optee/optee_os/core/arch/arm/kernel/semihosting_a64.S new file mode 100644 index 0000000..1271cc8 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/semihosting_a64.S @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2024 Linaro, Ltd. + */ + +#include + +/* + * uintptr_t __do_semihosting(uintptr_t op, uintptr_t arg) + * + * Refer to "Semihosting for Aarch32 and Aarch64": + * https://github.com/ARM-software/abi-aa/blob/main/semihosting/semihosting.rst + */ +FUNC __do_semihosting , : + hlt #0xf000 + ret +END_FUNC __do_semihosting 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..0dd125d --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/spmc_sp_handler.c @@ -0,0 +1,1285 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021-2024, Arm Limited + */ +#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->a1 = FFA_PARAM_MBZ; + args->a2 = error; + args->a3 = FFA_PARAM_MBZ; + args->a4 = FFA_PARAM_MBZ; + args->a5 = FFA_PARAM_MBZ; + args->a6 = FFA_PARAM_MBZ; + args->a7 = FFA_PARAM_MBZ; +} + +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) +{ + struct ffa_mem_transaction_x mem_trans = { }; + uint32_t tot_len = args->a1; + uint32_t frag_len = args->a2; + uint64_t global_handle = 0; + int res = FFA_OK; + + cpu_spin_lock(&rxtx->spinlock); + + /* Descriptor fragments aren't supported yet. */ + if (frag_len != tot_len) + res = FFA_NOT_SUPPORTED; + else if (frag_len > rxtx->size) + res = FFA_INVALID_PARAMETERS; + else + res = spmc_read_mem_transaction(rxtx->ffa_vers, rxtx->rx, + frag_len, &mem_trans); + if (!res) + res = spmc_sp_add_share(&mem_trans, rxtx, tot_len, + &global_handle, owner_sp); + if (!res) { + args->a3 = high32_from_64(global_handle); + args->a2 = low32_from_64(global_handle); + 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_mem_transaction_x *mem_trans, + 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(); + uint16_t sender_id = mem_trans->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 = mem_trans->mem_access_count; + mem_acc = (void *)((vaddr_t)rxtx->rx + mem_trans->mem_access_offs); + + if (!num_mem_accs) { + res = FFA_DENIED; + goto cleanup; + } + + /* Store the ffa_mem_transaction */ + smem->sender_id = sender_id; + smem->mem_reg_attr = mem_trans->mem_reg_attr; + smem->flags = mem_trans->flags; + smem->tag = mem_trans->tag; + + if (MUL_OVERFLOW(num_mem_accs, sizeof(*mem_acc), &needed_size) || + ADD_OVERFLOW(needed_size, mem_trans->mem_access_offs, + &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 *)rxtx->rx + 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; +} + +void spmc_sp_set_to_preempted(struct ts_session *ts_sess) +{ + if (ts_sess && is_sp_ctx(ts_sess->ctx)) { + struct sp_session *sp_sess = to_sp_session(ts_sess); + + assert(sp_sess->state == sp_busy); + sp_sess->state = sp_preempted; + } +} + +int spmc_sp_resume_from_preempted(uint16_t endpoint_id) +{ + struct sp_session *sp_sess = sp_get_session(endpoint_id); + + if (!sp_sess) + return FFA_INVALID_PARAMETERS; + + if (sp_sess->state != sp_preempted) + return FFA_DENIED; + + sp_sess->state = sp_busy; + + return FFA_OK; +} + +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, uint32_t ffa_vers, + struct ffa_mem_transaction_x *mem_trans, + void *rx, 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 = mem_trans->flags; + uint64_t retr_tag = mem_trans->tag; + struct sp_mem_map_region *reg = NULL; + + /* + * The request came from the endpoint. It should only have one + * ffa_mem_access element + */ + if (mem_trans->mem_access_count != 1) + return TEE_ERROR_BAD_PARAMETERS; + + retr_access = (void *)((vaddr_t)rx + mem_trans->mem_access_offs); + 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. + */ + if (ffa_vers <= FFA_VERSION_1_0) + tx_len -= sizeof(struct ffa_mem_transaction_1_0); + else + tx_len -= sizeof(struct ffa_mem_transaction_1_1); + tx_len -= 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(uint32_t ffa_vers, 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_address_range *addr_dst = NULL; + struct sp_mem_map_region *reg = NULL; + struct ffa_mem_access *mem_acc = 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 + */ + if (ffa_vers <= FFA_VERSION_1_0) { + struct ffa_mem_transaction_1_0 *d_ds = dst_buffer; + + memset(d_ds, 0, sizeof(*d_ds)); + + off = sizeof(*d_ds); + mem_acc = d_ds->mem_access_array; + + /* 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; + d_ds->mem_access_count = 1; + } else { + struct ffa_mem_transaction_1_1 *d_ds = dst_buffer; + + memset(d_ds, 0, sizeof(*d_ds)); + + off = sizeof(*d_ds); + mem_acc = (void *)(d_ds + 1); + + 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; + d_ds->mem_access_size = sizeof(*mem_acc); + d_ds->mem_access_count = 1; + d_ds->mem_access_offs = off; + } + + off += sizeof(struct ffa_mem_access); + dst_region = (struct ffa_mem_region *)(mem_acc + 1); + + /* Copy the mem_accsess_descr */ + mem_acc[0].region_offs = off; + memcpy(&mem_acc[0].access_perm, &receiver->perm, + sizeof(struct ffa_mem_access_perm)); + + /* Copy the mem_region_descr */ + memset(dst_region, 0, sizeof(*dst_region)); + 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) +{ + struct ffa_mem_transaction_x mem_trans = { }; + uint32_t tot_len = args->a1; + uint32_t frag_len = args->a2; + int ret = FFA_OK; + size_t tx_len = 0; + struct ffa_mem_access *mem_acc = 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; + } + /* Descriptor fragments aren't supported yet. */ + if (frag_len != tot_len) { + ret = FFA_NOT_SUPPORTED; + goto err; + } + if (frag_len > rxtx->size) { + ret = FFA_INVALID_PARAMETERS; + goto err; + } + + tx_len = rxtx->size; + + ret = spmc_read_mem_transaction(rxtx->ffa_vers, rxtx->rx, frag_len, + &mem_trans); + if (ret) + goto err; + + smem = sp_mem_get(mem_trans.global_handle); + if (!smem) { + DMSG("Incorrect handle"); + ret = FFA_DENIED; + goto err; + } + + receiver = sp_mem_get_receiver(caller_sp->endpoint_id, smem); + + mem_acc = (void *)((vaddr_t)rxtx->rx + mem_trans.mem_access_offs); + + address_offset = READ_ONCE(mem_acc[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, rxtx->ffa_vers, &mem_trans, + rxtx->rx, 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)rxtx->rx + + 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->ffa_vers, 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; + 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 the caller is an SP, make sure that it is the owner of the share. + * If the call comes from NWd this is ensured by the hypervisor. + */ + if (caller_sp && caller_sp->endpoint_id != smem->sender_id) { + ffa_set_error(args, FFA_INVALID_PARAMETERS); + 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 caller_sp; + } + + 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 caller_sp; + } + + if (dst == caller_sp) { + EMSG("Cannot send message to own ID"); + ffa_set_error(args, FFA_INVALID_PARAMETERS); + return caller_sp; + } + + 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 (dst && dst->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) +{ + /* If caller_sp == NULL send message to Normal World */ + if (caller_sp && sp_enter(args, caller_sp)) { + /* + * We can not return the error. Unwind the call chain with one + * link. Set the state of the SP to dead. + */ + caller_sp->state = sp_dead; + /* Create error. */ + ffa_set_error(args, FFA_ABORTED); + return sp_get_session(caller_sp->caller_id); + } + + return caller_sp; +} + +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); +} + +static void spmc_handle_version(struct thread_smc_args *args, + struct ffa_rxtx *rxtx) +{ + spmc_set_args(args, spmc_exchange_version(args->a1, rxtx), + FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ); +} + +static void handle_console_log(struct thread_smc_args *args) +{ + uint32_t ret_fid = FFA_ERROR; + uint32_t ret_val = FFA_INVALID_PARAMETERS; + size_t char_count = args->a1 & FFA_CONSOLE_LOG_CHAR_COUNT_MASK; + const void *reg_list[] = { + &args->a2, &args->a3, &args->a4, + &args->a5, &args->a6, &args->a7 + }; + char buffer[FFA_CONSOLE_LOG_64_MAX_MSG_LEN + 1] = { 0 }; + size_t max_length = 0; + size_t reg_size = 0; + size_t n = 0; + + if (args->a0 == FFA_CONSOLE_LOG_64) { + max_length = FFA_CONSOLE_LOG_64_MAX_MSG_LEN; + reg_size = sizeof(uint64_t); + } else { + max_length = FFA_CONSOLE_LOG_32_MAX_MSG_LEN; + reg_size = sizeof(uint32_t); + } + + if (char_count < 1 || char_count > max_length) + goto out; + + for (n = 0; n < char_count; n += reg_size) + memcpy(buffer + n, reg_list[n / reg_size], + MIN(char_count - n, reg_size)); + + buffer[char_count] = '\0'; + + trace_ext_puts(buffer); + + 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, &caller_sp->rxtx); + sp_enter(args, caller_sp); + break; + case FFA_FEATURES: + handle_features(args); + sp_enter(args, caller_sp); + break; + case FFA_SPM_ID_GET: + spmc_handle_spm_id_get(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; + +#ifdef ARM64 + case FFA_CONSOLE_LOG_64: +#endif + case FFA_CONSOLE_LOG_32: + handle_console_log(args); + 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..0ef3b63 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/stmm_sp.c @@ -0,0 +1,1135 @@ +// 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 +#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 uint16_t ffa_variable_authentication = 5U; + +static const unsigned int stmm_stack_size = 4 * SMALL_PAGE_SIZE; +static const unsigned int stmm_heap_size = 1024 * 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 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(); + + res = tee_pobj_get(&sess->ctx->uuid, obj_id, obj_id_len, flags, + TEE_POBJ_USAGE_OPEN, 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, NULL, 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; + 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(); + + res = tee_pobj_get(&sess->ctx->uuid, obj_id, obj_id_len, flags, + TEE_POBJ_USAGE_OPEN, 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, NULL, 0, &fh); + if (res == TEE_SUCCESS) { + res = po->fops->write(fh, offset, NULL, 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 TEE_Result stmm_handle_variable_authentication (struct thread_scall_regs *regs) +{ + TEE_Result res = TEE_ERROR_GENERIC; + uint32_t hash_len = SVC_REGS_A2 (regs); + uint8_t *hash_val = (uint8_t *)SVC_REGS_A3 (regs); + + res = jetson_user_key_pta_uefi_vars_auth(hash_val, hash_len); + if (res) { + EMSG ("Failed to get signed CMAC %x\n", res); + } + service_compose_direct_resp(regs, res); + return res; +} + +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 if (dst_id == ffa_variable_authentication) { + stmm_handle_variable_authentication (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..40b7a3f --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/sub.mk @@ -0,0 +1,88 @@ +srcs-y += rpc_io_i2c.c +srcs-y += idle.c + +srcs-$(CFG_SECURE_TIME_SOURCE_CNTPCT) += tee_time_arm_cntpct.c +ifeq ($(CFG_CALLOUT),y) +srcs-$(CFG_ARM64_core) += generic_timer.c +endif +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_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 +ifeq ($(CFG_SEMIHOSTING),y) +srcs-$(CFG_ARM64_core) += semihosting_a64.S +endif + +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..5154271 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/tee_time_arm_cntpct.c @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, 2015 Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +TEE_Result tee_time_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; +} + +uint32_t tee_time_get_sys_time_protection_level(void) +{ + return 1000; +} + +/* + * 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..a7d45d9 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/thread.c @@ -0,0 +1,1198 @@ +// 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 +#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, uint32_t flags) +{ + 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 = flags; + 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, 0); +} + +#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, THREAD_FLAGS_FFA_ONLY); +} +#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 +static uint64_t spsr_from_pstate(void) +{ + uint64_t spsr = SPSR_64(SPSR_64_MODE_EL1, SPSR_64_MODE_SP_EL0, 0); + + spsr |= read_daif(); + if (IS_ENABLED(CFG_PAN) && feat_pan_implemented() && read_pan()) + spsr |= SPSR_64_PAN; + + return spsr; +} + +void __thread_rpc(uint32_t rv[THREAD_RPC_NUM_ARGS]) +{ + thread_rpc_spsr(rv, spsr_from_pstate()); +} + +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); + } + + if (IS_ENABLED(CFG_SECURE_PARTITION)) { + struct ts_session *ts_sess = + TAILQ_FIRST(&threads[ct].tsd.sess_stack); + + spmc_sp_set_to_preempted(ts_sess); + } + + 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_from_pstate(); + /* + * 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 interrupt_main_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..5a20421 --- /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 interrupt_main_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..256195e --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/thread_a64.S @@ -0,0 +1,1336 @@ +/* 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_imm x0, __CORE_MMU_BASE_TABLE_OFFSET + /* 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_imm x0, __CORE_MMU_BASE_TABLE_OFFSET + 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 */ + orr x2, x5, #BIT(TTBR_ASID_SHIFT) /* switch to user mode ASID */ + add_imm x2, __CORE_MMU_BASE_TABLE_OFFSET + 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 interrupt_main_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..95ae9ff --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/thread_optee_smc.c @@ -0,0 +1,709 @@ +// 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 + +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->a7 != HYP_CLNT_ID) { + 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) +{ + return thread_rpc_alloc(size, 8, OPTEE_RPC_SHM_TYPE_KERNEL); +} + +void thread_rpc_free_kernel_payload(struct mobj *mobj) +{ + if (mobj) + thread_rpc_free(OPTEE_RPC_SHM_TYPE_KERNEL, + mobj_get_cookie(mobj), mobj); +} + +void thread_rpc_free_payload(struct mobj *mobj) +{ + if (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..2a8c14c --- /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 interrupt_main_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..1b08414 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/thread_optee_smc_a64.S @@ -0,0 +1,257 @@ +/* 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 interrupt_main_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_spsr(uint32_t rv[THREAD_RPC_NUM_ARGS], uint64_t spsr) */ +FUNC thread_rpc_spsr , : + /* 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_spsr +DECLARE_KEEP_PAGER thread_rpc_spsr + +/* + * 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..b154c82 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/thread_spmc.c @@ -0,0 +1,2398 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020-2023, Linaro Limited. + * Copyright (c) 2019-2024, 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 +#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 + +static unsigned int spmc_notif_lock = SPINLOCK_UNLOCK; +static int do_bottom_half_value = -1; +static uint16_t notif_vm_id; +static bool spmc_notif_is_ready; + +/* Initialized in spmc_init() below */ +uint16_t optee_endpoint_id __nex_bss; +uint16_t spmc_id __nex_bss; +#ifdef CFG_CORE_SEL1_SPMC +uint16_t spmd_id __nex_bss; +static const uint32_t my_part_props = FFA_PART_PROP_DIRECT_REQ_RECV | + FFA_PART_PROP_DIRECT_REQ_SEND | +#ifdef CFG_NS_VIRTUALIZATION + FFA_PART_PROP_NOTIF_CREATED | + FFA_PART_PROP_NOTIF_DESTROYED | +#endif +#ifdef ARM64 + FFA_PART_PROP_AARCH64_STATE | +#endif + FFA_PART_PROP_IS_PE_ID; + +static uint32_t my_uuid_words[] = { + /* + * - if the SPMC is in S-EL2 this UUID describes OP-TEE as a S-EL1 + * SP, or + * - if the SPMC is in S-EL1 then this UUID is for OP-TEE as a + * logical partition, residing in the same exception level as the + * SPMC + * UUID 486178e0-e7f8-11e3-bc5e-0002a5d5c51b + */ + 0xe0786148, 0xe311f8e7, 0x02005ebc, 0x1bc5d5a5, +}; + +/* + * 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. + */ + +static struct ffa_rxtx my_rxtx __nex_bss; + +static bool is_nw_buf(struct ffa_rxtx *rxtx) +{ + return rxtx == &my_rxtx; +} + +static SLIST_HEAD(mem_frag_state_head, mem_frag_state) frag_state_head = + SLIST_HEAD_INITIALIZER(&frag_state_head); + +static uint64_t notif_pending_bitmap; +static uint64_t notif_bound_bitmap; +static bool notif_vm_id_valid; +static int notif_intid = -1; +#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 my_rxtx = { + .rx = __rx_buf, + .tx = __tx_buf, + .size = sizeof(__rx_buf), +}; +#endif + +static uint32_t swap_src_dst(uint32_t src_dst) +{ + return (src_dst >> 16) | (src_dst << 16); +} + +static uint16_t get_sender_id(uint32_t src_dst) +{ + return 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, }; +} + +static void set_simple_ret_val(struct thread_smc_args *args, int ffa_ret) +{ + if (ffa_ret) + spmc_set_args(args, FFA_ERROR, 0, ffa_ret, 0, 0, 0); + else + spmc_set_args(args, FFA_SUCCESS_32, 0, 0, 0, 0, 0); +} + +uint32_t spmc_exchange_version(uint32_t vers, struct ffa_rxtx *rxtx) +{ + /* + * No locking, if the caller does concurrent calls to this it's + * only making a mess for itself. We must be able to renegotiate + * the FF-A version in order to support differing versions between + * the loader and the driver. + */ + if (vers < FFA_VERSION_1_1) + rxtx->ffa_vers = FFA_VERSION_1_0; + else + rxtx->ffa_vers = FFA_VERSION_1_1; + + return rxtx->ffa_vers; +} + +static bool is_ffa_success(uint32_t fid) +{ +#ifdef ARM64 + if (fid == FFA_SUCCESS_64) + return true; +#endif + return fid == FFA_SUCCESS_32; +} + +static int32_t get_ffa_ret_code(const struct thread_smc_args *args) +{ + if (is_ffa_success(args->a0)) + return FFA_OK; + if (args->a0 == FFA_ERROR && args->a2) + return args->a2; + return FFA_NOT_SUPPORTED; +} + +static int ffa_simple_call(uint32_t fid, unsigned long a1, unsigned long a2, + unsigned long a3, unsigned long a4) +{ + struct thread_smc_args args = { + .a0 = fid, + .a1 = a1, + .a2 = a2, + .a3 = a3, + .a4 = a4, + }; + + thread_smccc(&args); + + return get_ffa_ret_code(&args); +} + +static int __maybe_unused ffa_features(uint32_t id) +{ + return ffa_simple_call(FFA_FEATURES, id, 0, 0, 0); +} + +static int __maybe_unused ffa_set_notification(uint16_t dst, uint16_t src, + uint32_t flags, uint64_t bitmap) +{ + return ffa_simple_call(FFA_NOTIFICATION_SET, + SHIFT_U32(src, 16) | dst, flags, + low32_from_64(bitmap), high32_from_64(bitmap)); +} + +#if defined(CFG_CORE_SEL1_SPMC) +static void handle_features(struct thread_smc_args *args) +{ + uint32_t ret_fid = FFA_ERROR; + uint32_t ret_w2 = FFA_NOT_SUPPORTED; + + switch (args->a1) { + case FFA_FEATURE_SCHEDULE_RECV_INTR: + if (spmc_notif_is_ready) { + ret_fid = FFA_SUCCESS_32; + ret_w2 = notif_intid; + } + break; + +#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_FEATURES: + case FFA_SPM_ID_GET: + case FFA_MEM_FRAG_TX: + case FFA_MEM_RECLAIM: + case FFA_MSG_SEND_DIRECT_REQ_64: + case FFA_MSG_SEND_DIRECT_REQ_32: + case FFA_INTERRUPT: + case FFA_PARTITION_INFO_GET: + case FFA_RXTX_UNMAP: + case FFA_RX_RELEASE: + case FFA_FEATURE_MANAGED_EXIT_INTR: + case FFA_NOTIFICATION_BITMAP_CREATE: + case FFA_NOTIFICATION_BITMAP_DESTROY: + case FFA_NOTIFICATION_BIND: + case FFA_NOTIFICATION_UNBIND: + case FFA_NOTIFICATION_SET: + case FFA_NOTIFICATION_GET: + case FFA_NOTIFICATION_INFO_GET_32: +#ifdef ARM64 + case FFA_NOTIFICATION_INFO_GET_64: +#endif + ret_fid = FFA_SUCCESS_32; + ret_w2 = FFA_PARAM_MBZ; + break; + default: + 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; +} + +void spmc_handle_spm_id_get(struct thread_smc_args *args) +{ + spmc_set_args(args, FFA_SUCCESS_32, FFA_PARAM_MBZ, spmc_id, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ); +} + +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; + 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)) { + if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) { + enum teecore_memtypes mt = MEM_AREA_NEX_NSEC_SHM; + bool tx_alloced = false; + + /* + * With virtualization we establish this mapping in + * the nexus mapping which then is replicated to + * each partition. + * + * This means that this mapping must be done before + * any partition is created and then must not be + * changed. + */ + + /* + * core_mmu_add_mapping() may reuse previous + * mappings. First check if there's any mappings to + * reuse so we know how to clean up in case of + * failure. + */ + tx = phys_to_virt(tx_pa, mt, sz); + rx = phys_to_virt(rx_pa, mt, sz); + if (!tx) { + tx = core_mmu_add_mapping(mt, tx_pa, sz); + if (!tx) { + rc = FFA_NO_MEMORY; + goto out; + } + tx_alloced = true; + } + if (!rx) + rx = core_mmu_add_mapping(mt, rx_pa, sz); + + if (!rx) { + if (tx_alloced && tx) + core_mmu_remove_mapping(mt, tx, sz); + rc = FFA_NO_MEMORY; + goto out; + } + } else { + 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; + 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); + set_simple_ret_val(args, rc); +} + +void spmc_handle_rxtx_unmap(struct thread_smc_args *args, struct ffa_rxtx *rxtx) +{ + 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; + rc = 0; +out: + cpu_spin_unlock(&rxtx->spinlock); + set_simple_ret_val(args, rc); +} + +void spmc_handle_rx_release(struct thread_smc_args *args, struct ffa_rxtx *rxtx) +{ + int rc = 0; + + cpu_spin_lock(&rxtx->spinlock); + /* The senders RX is our TX */ + if (!rxtx->size || rxtx->tx_is_mine) { + rc = FFA_DENIED; + } else { + rc = 0; + rxtx->tx_is_mine = true; + } + cpu_spin_unlock(&rxtx->spinlock); + + set_simple_ret_val(args, rc); +} + +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 == my_uuid_words[0] && w1 == my_uuid_words[1] && + w2 == my_uuid_words[2] && w3 == my_uuid_words[3]; +} + +TEE_Result spmc_fill_partition_entry(uint32_t ffa_vers, void *buf, size_t blen, + size_t idx, uint16_t endpoint_id, + uint16_t execution_context, + uint32_t part_props, + const uint32_t uuid_words[4]) +{ + struct ffa_partition_info_x *fpi = NULL; + size_t fpi_size = sizeof(*fpi); + + if (ffa_vers >= FFA_VERSION_1_1) + fpi_size += FFA_UUID_SIZE; + + if ((idx + 1) * fpi_size > blen) + return TEE_ERROR_OUT_OF_MEMORY; + + fpi = (void *)((vaddr_t)buf + idx * fpi_size); + fpi->id = endpoint_id; + /* Number of execution contexts implemented by this partition */ + fpi->execution_context = execution_context; + + fpi->partition_properties = part_props; + + if (ffa_vers >= FFA_VERSION_1_1) { + if (uuid_words) + memcpy(fpi->uuid, uuid_words, FFA_UUID_SIZE); + else + memset(fpi->uuid, 0, FFA_UUID_SIZE); + } + + return TEE_SUCCESS; +} + +static int handle_partition_info_get_all(size_t *elem_count, + struct ffa_rxtx *rxtx, bool count_only) +{ + if (!count_only) { + /* Add OP-TEE SP */ + if (spmc_fill_partition_entry(rxtx->ffa_vers, rxtx->tx, + rxtx->size, 0, optee_endpoint_id, + CFG_TEE_CORE_NB_CORE, + my_part_props, my_uuid_words)) + return FFA_NO_MEMORY; + } + *elem_count = 1; + + if (IS_ENABLED(CFG_SECURE_PARTITION)) { + if (sp_partition_info_get(rxtx->ffa_vers, rxtx->tx, rxtx->size, + NULL, elem_count, count_only)) + return FFA_NO_MEMORY; + } + + return FFA_OK; +} + +void spmc_handle_partition_info_get(struct thread_smc_args *args, + struct ffa_rxtx *rxtx) +{ + TEE_Result res = TEE_SUCCESS; + uint32_t ret_fid = FFA_ERROR; + uint32_t fpi_size = 0; + uint32_t rc = 0; + bool count_only = args->a5 & FFA_PARTITION_INFO_GET_COUNT_FLAG; + + if (!count_only) { + cpu_spin_lock(&rxtx->spinlock); + + if (!rxtx->size || !rxtx->tx_is_mine) { + rc = FFA_BUSY; + 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, + count_only); + + 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)) { + if (!count_only) { + res = spmc_fill_partition_entry(rxtx->ffa_vers, + rxtx->tx, rxtx->size, 0, + optee_endpoint_id, + CFG_TEE_CORE_NB_CORE, + my_part_props, + my_uuid_words); + if (res) { + ret_fid = FFA_ERROR; + rc = FFA_INVALID_PARAMETERS; + goto out; + } + } + rc = 1; + } else if (IS_ENABLED(CFG_SECURE_PARTITION)) { + uint32_t uuid_array[4] = { 0 }; + TEE_UUID uuid = { }; + size_t count = 0; + + 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(rxtx->ffa_vers, rxtx->tx, + rxtx->size, &uuid, &count, + count_only); + 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; + +out: + if (ret_fid == FFA_SUCCESS_32 && !count_only && + rxtx->ffa_vers >= FFA_VERSION_1_1) + fpi_size = sizeof(struct ffa_partition_info_x) + FFA_UUID_SIZE; + + spmc_set_args(args, ret_fid, FFA_PARAM_MBZ, rc, fpi_size, + FFA_PARAM_MBZ, FFA_PARAM_MBZ); + if (!count_only) { + rxtx->tx_is_mine = false; + cpu_spin_unlock(&rxtx->spinlock); + } +} + +static void spmc_handle_run(struct thread_smc_args *args) +{ + uint16_t endpoint = FFA_TARGET_INFO_GET_SP_ID(args->a1); + uint16_t thread_id = FFA_TARGET_INFO_GET_VCPU_ID(args->a1); + uint32_t rc = FFA_OK; + + if (endpoint != optee_endpoint_id) { + /* + * The endpoint should be an SP, try to resume the SP from + * preempted into busy state. + */ + rc = spmc_sp_resume_from_preempted(endpoint); + if (rc) + goto out; + } + + thread_resume_from_rpc(thread_id, 0, 0, 0, 0); + + /* thread_resume_from_rpc return only of the thread_id is invalid */ + rc = FFA_INVALID_PARAMETERS; + +out: + set_simple_ret_val(args, rc); +} +#endif /*CFG_CORE_SEL1_SPMC*/ + +static uint32_t spmc_enable_async_notif(uint32_t bottom_half_value, + uint16_t vm_id) +{ + uint32_t old_itr_status = 0; + + if (!spmc_notif_is_ready) { + /* + * This should never happen, not if normal world respects the + * exchanged capabilities. + */ + EMSG("Asynchronous notifications are not ready"); + return TEE_ERROR_NOT_IMPLEMENTED; + } + + if (bottom_half_value >= OPTEE_FFA_MAX_ASYNC_NOTIF_VALUE) { + EMSG("Invalid bottom half value %"PRIu32, bottom_half_value); + return TEE_ERROR_BAD_PARAMETERS; + } + + old_itr_status = cpu_spin_lock_xsave(&spmc_notif_lock); + do_bottom_half_value = bottom_half_value; + if (!IS_ENABLED(CFG_CORE_SEL1_SPMC)) + notif_vm_id = vm_id; + cpu_spin_unlock_xrestore(&spmc_notif_lock, old_itr_status); + + notif_deliver_atomic_event(NOTIF_EVENT_STARTED); + return TEE_SUCCESS; +} + +static void handle_yielding_call(struct thread_smc_args *args, + uint32_t direct_resp_fid) +{ + TEE_Result res = 0; + + thread_check_canaries(); + +#ifdef ARM64 + /* Saving this for an eventual RPC */ + thread_get_core_local()->direct_resp_fid = direct_resp_fid; +#endif + + 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, direct_resp_fid, 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, + uint32_t direct_resp_fid) +{ + uint32_t sec_caps = 0; + + switch (args->a3) { + case OPTEE_FFA_GET_API_VERSION: + spmc_set_args(args, direct_resp_fid, 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, direct_resp_fid, swap_src_dst(args->a1), 0, + CFG_OPTEE_REVISION_MAJOR, + CFG_OPTEE_REVISION_MINOR, TEE_IMPL_GIT_SHA1); + break; + case OPTEE_FFA_EXCHANGE_CAPABILITIES: + sec_caps = OPTEE_FFA_SEC_CAP_ARG_OFFSET; + if (spmc_notif_is_ready) + sec_caps |= OPTEE_FFA_SEC_CAP_ASYNC_NOTIF; + spmc_set_args(args, direct_resp_fid, + swap_src_dst(args->a1), 0, 0, + THREAD_RPC_MAX_NUM_PARAMS, sec_caps); + break; + case OPTEE_FFA_UNREGISTER_SHM: + spmc_set_args(args, direct_resp_fid, swap_src_dst(args->a1), 0, + handle_unregister_shm(args->a4, args->a5), 0, 0); + break; + case OPTEE_FFA_ENABLE_ASYNC_NOTIF: + spmc_set_args(args, direct_resp_fid, + swap_src_dst(args->a1), 0, + spmc_enable_async_notif(args->a4, + FFA_SRC(args->a1)), + 0, 0); + break; + default: + EMSG("Unhandled blocking service ID %#"PRIx32, + (uint32_t)args->a3); + spmc_set_args(args, direct_resp_fid, swap_src_dst(args->a1), 0, + TEE_ERROR_BAD_PARAMETERS, 0, 0); + } +} + +static void handle_framework_direct_request(struct thread_smc_args *args, + struct ffa_rxtx *rxtx, + uint32_t direct_resp_fid) +{ + uint32_t w0 = FFA_ERROR; + uint32_t w1 = FFA_PARAM_MBZ; + uint32_t w2 = FFA_NOT_SUPPORTED; + uint32_t w3 = FFA_PARAM_MBZ; + + switch (args->a2 & FFA_MSG_TYPE_MASK) { + case FFA_MSG_SEND_VM_CREATED: + if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) { + uint16_t guest_id = args->a5; + TEE_Result res = virt_guest_created(guest_id); + + w0 = direct_resp_fid; + w1 = swap_src_dst(args->a1); + w2 = FFA_MSG_FLAG_FRAMEWORK | FFA_MSG_RESP_VM_CREATED; + if (res == TEE_SUCCESS) + w3 = FFA_OK; + else if (res == TEE_ERROR_OUT_OF_MEMORY) + w3 = FFA_DENIED; + else + w3 = FFA_INVALID_PARAMETERS; + } + break; + case FFA_MSG_SEND_VM_DESTROYED: + if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) { + uint16_t guest_id = args->a5; + TEE_Result res = virt_guest_destroyed(guest_id); + + w0 = direct_resp_fid; + w1 = swap_src_dst(args->a1); + w2 = FFA_MSG_FLAG_FRAMEWORK | FFA_MSG_RESP_VM_DESTROYED; + if (res == TEE_SUCCESS) + w3 = FFA_OK; + else + w3 = FFA_INVALID_PARAMETERS; + } + break; + case FFA_MSG_VERSION_REQ: + w0 = direct_resp_fid; + w1 = swap_src_dst(args->a1); + w2 = FFA_MSG_FLAG_FRAMEWORK | FFA_MSG_VERSION_RESP; + w3 = spmc_exchange_version(args->a3, rxtx); + break; + default: + break; + } + spmc_set_args(args, w0, w1, w2, w3, FFA_PARAM_MBZ, FFA_PARAM_MBZ); +} + +static void handle_direct_request(struct thread_smc_args *args, + struct ffa_rxtx *rxtx) +{ + uint32_t direct_resp_fid = 0; + + if (IS_ENABLED(CFG_SECURE_PARTITION) && + FFA_DST(args->a1) != optee_endpoint_id) { + spmc_sp_start_thread(args); + return; + } + + if (OPTEE_SMC_IS_64(args->a0)) + direct_resp_fid = FFA_MSG_SEND_DIRECT_RESP_64; + else + direct_resp_fid = FFA_MSG_SEND_DIRECT_RESP_32; + + if (args->a2 & FFA_MSG_FLAG_FRAMEWORK) { + handle_framework_direct_request(args, rxtx, direct_resp_fid); + return; + } + + if (IS_ENABLED(CFG_NS_VIRTUALIZATION) && + virt_set_guest(get_sender_id(args->a1))) { + spmc_set_args(args, direct_resp_fid, swap_src_dst(args->a1), 0, + TEE_ERROR_ITEM_NOT_FOUND, 0, 0); + return; + } + + if (args->a3 & BIT32(OPTEE_FFA_YIELDING_CALL_BIT)) + handle_yielding_call(args, direct_resp_fid); + else + handle_blocking_call(args, direct_resp_fid); + + /* + * Note that handle_yielding_call() typically only returns if a + * thread cannot be allocated or found. virt_unset_guest() is also + * called from thread_state_suspend() and thread_state_free(). + */ + virt_unset_guest(); +} + +int spmc_read_mem_transaction(uint32_t ffa_vers, void *buf, size_t blen, + struct ffa_mem_transaction_x *trans) +{ + uint16_t mem_reg_attr = 0; + uint32_t flags = 0; + uint32_t count = 0; + uint32_t offs = 0; + uint32_t size = 0; + size_t n = 0; + + if (!IS_ALIGNED_WITH_TYPE(buf, uint64_t)) + return FFA_INVALID_PARAMETERS; + + if (ffa_vers >= FFA_VERSION_1_1) { + struct ffa_mem_transaction_1_1 *descr = NULL; + + if (blen < sizeof(*descr)) + return FFA_INVALID_PARAMETERS; + + descr = buf; + trans->sender_id = READ_ONCE(descr->sender_id); + mem_reg_attr = READ_ONCE(descr->mem_reg_attr); + flags = READ_ONCE(descr->flags); + trans->global_handle = READ_ONCE(descr->global_handle); + trans->tag = READ_ONCE(descr->tag); + + count = READ_ONCE(descr->mem_access_count); + size = READ_ONCE(descr->mem_access_size); + offs = READ_ONCE(descr->mem_access_offs); + } else { + struct ffa_mem_transaction_1_0 *descr = NULL; + + if (blen < sizeof(*descr)) + return FFA_INVALID_PARAMETERS; + + descr = buf; + trans->sender_id = READ_ONCE(descr->sender_id); + mem_reg_attr = READ_ONCE(descr->mem_reg_attr); + flags = READ_ONCE(descr->flags); + trans->global_handle = READ_ONCE(descr->global_handle); + trans->tag = READ_ONCE(descr->tag); + + count = READ_ONCE(descr->mem_access_count); + size = sizeof(struct ffa_mem_access); + offs = offsetof(struct ffa_mem_transaction_1_0, + mem_access_array); + } + + if (mem_reg_attr > UINT8_MAX || flags > UINT8_MAX || + size > UINT8_MAX || count > UINT8_MAX || offs > UINT16_MAX) + return FFA_INVALID_PARAMETERS; + + /* Check that the endpoint memory access descriptor array fits */ + if (MUL_OVERFLOW(size, count, &n) || ADD_OVERFLOW(offs, n, &n) || + n > blen) + return FFA_INVALID_PARAMETERS; + + trans->mem_reg_attr = mem_reg_attr; + trans->flags = flags; + trans->mem_access_size = size; + trans->mem_access_count = count; + trans->mem_access_offs = offs; + return 0; +} + +#if defined(CFG_CORE_SEL1_SPMC) +static int get_acc_perms(vaddr_t mem_acc_base, unsigned int mem_access_size, + unsigned int mem_access_count, uint8_t *acc_perms, + unsigned int *region_offs) +{ + struct ffa_mem_access_perm *descr = NULL; + struct ffa_mem_access *mem_acc = NULL; + unsigned int n = 0; + + for (n = 0; n < mem_access_count; n++) { + mem_acc = (void *)(mem_acc_base + mem_access_size * n); + descr = &mem_acc->access_perm; + if (READ_ONCE(descr->endpoint_id) == optee_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(struct ffa_mem_transaction_x *mem_trans, void *buf, + size_t blen, unsigned int *page_count, + unsigned int *region_count, size_t *addr_range_offs) +{ + const uint16_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; + unsigned int region_descr_offs = 0; + uint8_t mem_acc_perm = 0; + size_t n = 0; + + if (mem_trans->mem_reg_attr != exp_mem_reg_attr) + return FFA_INVALID_PARAMETERS; + + /* Check that the access permissions matches what's expected */ + if (get_acc_perms((vaddr_t)buf + mem_trans->mem_access_offs, + mem_trans->mem_access_size, + mem_trans->mem_access_count, + &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)buf + region_descr_offs, + struct ffa_mem_region)) + return FFA_INVALID_PARAMETERS; + + region_descr = (struct ffa_mem_region *)((vaddr_t)buf + + 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(struct ffa_mem_transaction_x *mem_trans, + void *buf) +{ + struct ffa_mem_access_perm *perm = NULL; + struct ffa_mem_access *mem_acc = NULL; + + if (!IS_ENABLED(CFG_SECURE_PARTITION)) + return false; + + if (mem_trans->mem_access_count < 1) + return false; + + mem_acc = (void *)((vaddr_t)buf + mem_trans->mem_access_offs); + perm = &mem_acc->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) != optee_endpoint_id; +} + +static int add_mem_share(struct ffa_mem_transaction_x *mem_trans, + 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; + uint64_t cookie = OPTEE_MSG_FMEM_INVALID_GLOBAL_ID; + size_t n = 0; + + rc = mem_share_init(mem_trans, 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; + + if (mem_trans->global_handle) + cookie = mem_trans->global_handle; + share.mf = mobj_ffa_sel1_spmc_new(cookie, 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) +{ + struct ffa_mem_transaction_x mem_trans = { }; + int rc = 0; + size_t len = 0; + void *buf = NULL; + 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 flen is covered by len even + * if the offset is taken into account. + */ + if (len < flen || len - offs < flen) + 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; + } + buf = (void *)(tee_mm_get_smem(mm) + offs); + + cpu_spin_lock(&rxtx->spinlock); + rc = spmc_read_mem_transaction(rxtx->ffa_vers, buf, flen, &mem_trans); + if (!rc && IS_ENABLED(CFG_NS_VIRTUALIZATION) && + virt_set_guest(mem_trans.sender_id)) + rc = FFA_DENIED; + if (!rc) + rc = add_mem_share(&mem_trans, mm, buf, blen, flen, + global_handle); + virt_unset_guest(); + 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) +{ + struct ffa_mem_transaction_x mem_trans = { }; + int rc = FFA_DENIED; + + cpu_spin_lock(&rxtx->spinlock); + + if (!rxtx->rx || flen > rxtx->size) + goto out; + + rc = spmc_read_mem_transaction(rxtx->ffa_vers, rxtx->rx, flen, + &mem_trans); + if (rc) + goto out; + if (is_sp_share(&mem_trans, rxtx->rx)) { + rc = spmc_sp_add_share(&mem_trans, rxtx, blen, + global_handle, NULL); + goto out; + } + + if (IS_ENABLED(CFG_NS_VIRTUALIZATION) && + virt_set_guest(mem_trans.sender_id)) + goto out; + + rc = add_mem_share(&mem_trans, NULL, rxtx->rx, blen, flen, + global_handle); + + virt_unset_guest(); + +out: + cpu_spin_unlock(&rxtx->spinlock); + + return rc; +} + +static void handle_mem_share(struct thread_smc_args *args, + struct ffa_rxtx *rxtx) +{ + uint32_t tot_len = args->a1; + uint32_t frag_len = args->a2; + uint64_t addr = args->a3; + uint32_t page_count = args->a4; + 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; + + /* Check that fragment length doesn't exceed total length */ + if (frag_len > tot_len) + goto out; + + /* Check for 32-bit calling convention */ + if (args->a0 == FFA_MEM_SHARE_32) + addr &= UINT32_MAX; + + if (!addr) { + /* + * The memory transaction descriptor is passed via our rx + * buffer. + */ + if (page_count) + goto out; + rc = handle_mem_share_rxbuf(tot_len, frag_len, &global_handle, + rxtx); + } else { + rc = handle_mem_share_tmem(addr, tot_len, frag_len, page_count, + &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) +{ + uint64_t global_handle = reg_pair_to_64(args->a2, args->a1); + size_t flen = args->a3; + uint32_t endpoint_id = args->a4; + 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; + int rc = 0; + + if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) { + uint16_t guest_id = endpoint_id >> 16; + + if (!guest_id || virt_set_guest(guest_id)) { + rc = FFA_INVALID_PARAMETERS; + goto out_set_rc; + } + } + + /* + * 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: + virt_unset_guest(); + cpu_spin_unlock(&rxtx->spinlock); + + if (rc <= 0 && mm) { + core_mmu_unmap_pages(tee_mm_get_smem(mm), page_count); + tee_mm_free(mm); + } + +out_set_rc: + 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) +{ + int rc = FFA_INVALID_PARAMETERS; + 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); + if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) { + uint16_t guest_id = 0; + + if (cookie & FFA_MEMORY_HANDLE_HYPERVISOR_BIT) { + guest_id = virt_find_guest_by_cookie(cookie); + } else { + guest_id = (cookie >> FFA_MEMORY_HANDLE_PRTN_SHIFT) & + FFA_MEMORY_HANDLE_PRTN_MASK; + } + if (!guest_id) + goto out; + if (virt_set_guest(guest_id)) { + if (!virt_reclaim_cookie_from_destroyed_guest(guest_id, + cookie)) + rc = FFA_OK; + goto out; + } + } + + switch (mobj_ffa_sel1_spmc_reclaim(cookie)) { + case TEE_SUCCESS: + rc = FFA_OK; + break; + case TEE_ERROR_ITEM_NOT_FOUND: + DMSG("cookie %#"PRIx64" not found", cookie); + rc = FFA_INVALID_PARAMETERS; + break; + default: + DMSG("cookie %#"PRIx64" busy", cookie); + rc = FFA_DENIED; + break; + } + + virt_unset_guest(); + +out: + set_simple_ret_val(args, rc); +} + +static void handle_notification_bitmap_create(struct thread_smc_args *args) +{ + uint32_t ret_val = FFA_INVALID_PARAMETERS; + uint32_t ret_fid = FFA_ERROR; + uint32_t old_itr_status = 0; + + if (!FFA_TARGET_INFO_GET_SP_ID(args->a1) && !args->a3 && !args->a4 && + !args->a5 && !args->a6 && !args->a7) { + uint16_t vm_id = args->a1; + + old_itr_status = cpu_spin_lock_xsave(&spmc_notif_lock); + + if (notif_vm_id_valid) { + if (vm_id == notif_vm_id) + ret_val = FFA_DENIED; + else + ret_val = FFA_NO_MEMORY; + } else { + notif_vm_id = vm_id; + notif_vm_id_valid = true; + ret_val = FFA_OK; + ret_fid = FFA_SUCCESS_32; + } + + cpu_spin_unlock_xrestore(&spmc_notif_lock, old_itr_status); + } + + spmc_set_args(args, ret_fid, 0, ret_val, 0, 0, 0); +} + +static void handle_notification_bitmap_destroy(struct thread_smc_args *args) +{ + uint32_t ret_val = FFA_INVALID_PARAMETERS; + uint32_t ret_fid = FFA_ERROR; + uint32_t old_itr_status = 0; + + if (!FFA_TARGET_INFO_GET_SP_ID(args->a1) && !args->a3 && !args->a4 && + !args->a5 && !args->a6 && !args->a7) { + uint16_t vm_id = args->a1; + + old_itr_status = cpu_spin_lock_xsave(&spmc_notif_lock); + + if (notif_vm_id_valid && vm_id == notif_vm_id) { + if (notif_pending_bitmap || notif_bound_bitmap) { + ret_val = FFA_DENIED; + } else { + notif_vm_id_valid = false; + ret_val = FFA_OK; + ret_fid = FFA_SUCCESS_32; + } + } + + cpu_spin_unlock_xrestore(&spmc_notif_lock, old_itr_status); + } + + spmc_set_args(args, ret_fid, 0, ret_val, 0, 0, 0); +} + +static void handle_notification_bind(struct thread_smc_args *args) +{ + uint32_t ret_val = FFA_INVALID_PARAMETERS; + uint32_t ret_fid = FFA_ERROR; + uint32_t old_itr_status = 0; + uint64_t bitmap = 0; + uint16_t vm_id = 0; + + if (args->a5 || args->a6 || args->a7) + goto out; + if (args->a2) { + /* We only deal with global notifications for now */ + ret_val = FFA_NOT_SUPPORTED; + goto out; + } + + /* The destination of the eventual notification */ + vm_id = FFA_DST(args->a1); + bitmap = reg_pair_to_64(args->a4, args->a3); + + old_itr_status = cpu_spin_lock_xsave(&spmc_notif_lock); + + if (notif_vm_id_valid && vm_id == notif_vm_id) { + if (bitmap & notif_bound_bitmap) { + ret_val = FFA_DENIED; + } else { + notif_bound_bitmap |= bitmap; + ret_val = FFA_OK; + ret_fid = FFA_SUCCESS_32; + } + } + + cpu_spin_unlock_xrestore(&spmc_notif_lock, old_itr_status); +out: + spmc_set_args(args, ret_fid, 0, ret_val, 0, 0, 0); +} + +static void handle_notification_unbind(struct thread_smc_args *args) +{ + uint32_t ret_val = FFA_INVALID_PARAMETERS; + uint32_t ret_fid = FFA_ERROR; + uint32_t old_itr_status = 0; + uint64_t bitmap = 0; + uint16_t vm_id = 0; + + if (args->a2 || args->a5 || args->a6 || args->a7) + goto out; + + /* The destination of the eventual notification */ + vm_id = FFA_DST(args->a1); + bitmap = reg_pair_to_64(args->a4, args->a3); + + old_itr_status = cpu_spin_lock_xsave(&spmc_notif_lock); + + if (notif_vm_id_valid && vm_id == notif_vm_id) { + /* + * Spec says: + * At least one notification is bound to another Sender or + * is currently pending. + * + * Not sure what the intention is. + */ + if (bitmap & notif_pending_bitmap) { + ret_val = FFA_DENIED; + } else { + notif_bound_bitmap &= ~bitmap; + ret_val = FFA_OK; + ret_fid = FFA_SUCCESS_32; + } + } + + cpu_spin_unlock_xrestore(&spmc_notif_lock, old_itr_status); +out: + spmc_set_args(args, ret_fid, 0, ret_val, 0, 0, 0); +} + +static void handle_notification_get(struct thread_smc_args *args) +{ + uint32_t w2 = FFA_INVALID_PARAMETERS; + uint32_t ret_fid = FFA_ERROR; + uint32_t old_itr_status = 0; + uint16_t vm_id = 0; + uint32_t w3 = 0; + + if (args->a5 || args->a6 || args->a7) + goto out; + if (!(args->a2 & 0x1)) { + ret_fid = FFA_SUCCESS_32; + w2 = 0; + goto out; + } + vm_id = FFA_DST(args->a1); + + old_itr_status = cpu_spin_lock_xsave(&spmc_notif_lock); + + if (notif_vm_id_valid && vm_id == notif_vm_id) { + reg_pair_from_64(notif_pending_bitmap, &w3, &w2); + notif_pending_bitmap = 0; + ret_fid = FFA_SUCCESS_32; + } + + cpu_spin_unlock_xrestore(&spmc_notif_lock, old_itr_status); +out: + spmc_set_args(args, ret_fid, 0, w2, w3, 0, 0); +} + +static void handle_notification_info_get(struct thread_smc_args *args) +{ + uint32_t w2 = FFA_INVALID_PARAMETERS; + uint32_t ret_fid = FFA_ERROR; + + if (args->a1 || args->a2 || args->a3 || args->a4 || args->a5 || + args->a6 || args->a7) + goto out; + + if (OPTEE_SMC_IS_64(args->a0)) + ret_fid = FFA_SUCCESS_64; + else + ret_fid = FFA_SUCCESS_32; + + /* + * Note, we're only supporting physical OS kernel in normal world + * with Global Notifications. + * So one list of ID list registers (BIT[11:7]) + * and one count of IDs (BIT[13:12] + 1) + * and the VM is always 0. + */ + w2 = SHIFT_U32(1, 7); +out: + spmc_set_args(args, ret_fid, 0, w2, 0, 0, 0); +} + +void thread_spmc_set_async_notif_intid(int intid) +{ + assert(interrupt_can_raise_sgi(interrupt_get_main_chip())); + notif_intid = intid; + spmc_notif_is_ready = true; + DMSG("Asynchronous notifications are ready"); +} + +void notif_send_async(uint32_t value) +{ + uint32_t old_itr_status = 0; + + old_itr_status = cpu_spin_lock_xsave(&spmc_notif_lock); + assert(value == NOTIF_VALUE_DO_BOTTOM_HALF && spmc_notif_is_ready && + do_bottom_half_value >= 0 && notif_intid >= 0); + notif_pending_bitmap |= BIT64(do_bottom_half_value); + interrupt_raise_sgi(interrupt_get_main_chip(), notif_intid, + ITR_CPU_MASK_TO_THIS_CPU); + cpu_spin_unlock_xrestore(&spmc_notif_lock, old_itr_status); +} +#else +void notif_send_async(uint32_t value) +{ + /* global notification, delay notification interrupt */ + uint32_t flags = BIT32(1); + int res = 0; + + assert(value == NOTIF_VALUE_DO_BOTTOM_HALF && spmc_notif_is_ready && + do_bottom_half_value >= 0); + res = ffa_set_notification(notif_vm_id, optee_endpoint_id, flags, + BIT64(do_bottom_half_value)); + if (res) { + EMSG("notification set failed with error %d", res); + panic(); + } +} +#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_FEATURES: + handle_features(args); + break; + case FFA_SPM_ID_GET: + spmc_handle_spm_id_get(args); + break; +#ifdef ARM64 + case FFA_RXTX_MAP_64: +#endif + case FFA_RXTX_MAP_32: + spmc_handle_rxtx_map(args, &my_rxtx); + break; + case FFA_RXTX_UNMAP: + spmc_handle_rxtx_unmap(args, &my_rxtx); + break; + case FFA_RX_RELEASE: + spmc_handle_rx_release(args, &my_rxtx); + break; + case FFA_PARTITION_INFO_GET: + spmc_handle_partition_info_get(args, &my_rxtx); + break; + case FFA_RUN: + spmc_handle_run(args); + break; +#endif /*CFG_CORE_SEL1_SPMC*/ + case FFA_INTERRUPT: + if (IS_ENABLED(CFG_CORE_SEL1_SPMC)) + spmc_set_args(args, FFA_NORMAL_WORLD_RESUME, 0, 0, 0, + 0, 0); + else + 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: + handle_direct_request(args, &my_rxtx); + break; +#if defined(CFG_CORE_SEL1_SPMC) +#ifdef ARM64 + case FFA_MEM_SHARE_64: +#endif + case FFA_MEM_SHARE_32: + handle_mem_share(args, &my_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, &my_rxtx); + break; + case FFA_NOTIFICATION_BITMAP_CREATE: + handle_notification_bitmap_create(args); + break; + case FFA_NOTIFICATION_BITMAP_DESTROY: + handle_notification_bitmap_destroy(args); + break; + case FFA_NOTIFICATION_BIND: + handle_notification_bind(args); + break; + case FFA_NOTIFICATION_UNBIND: + handle_notification_unbind(args); + break; + case FFA_NOTIFICATION_GET: + handle_notification_get(args); + break; +#ifdef ARM64 + case FFA_NOTIFICATION_INFO_GET_64: +#endif + case FFA_NOTIFICATION_INFO_GET_32: + handle_notification_info_get(args); + break; +#endif /*CFG_CORE_SEL1_SPMC*/ + case FFA_ERROR: + EMSG("Cannot handle FFA_ERROR(%d)", (int)args->a2); + if (!IS_ENABLED(CFG_CORE_SEL1_SPMC)) { + /* + * The SPMC will return an FFA_ERROR back so better + * panic() now than flooding the log. + */ + panic("FFA_ERROR from SPMC is fatal"); + } + spmc_set_args(args, FFA_ERROR, FFA_PARAM_MBZ, FFA_NOT_SUPPORTED, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ); + break; + default: + EMSG("Unhandled FFA function ID %#"PRIx32, (uint32_t)args->a0); + set_simple_ret_val(args, FFA_NOT_SUPPORTED); + } +} + +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; + + virt_on_stdcall(); + 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) +{ + if (mobj) + thread_rpc_free(OPTEE_RPC_SHM_TYPE_KERNEL, + mobj_get_cookie(mobj), mobj); +} + +void thread_rpc_free_payload(struct mobj *mobj) +{ + if (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) +{ + if (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); +} + +static uint16_t ffa_id_get(void) +{ + /* + * Ask the SPM component running at a higher EL to return our FF-A ID. + * This can either be the SPMC ID (if the SPMC is enabled in OP-TEE) or + * the partition ID (if not). + */ + 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 uint16_t ffa_spm_id_get(void) +{ + /* + * Ask the SPM component running at a higher EL to return its ID. + * If OP-TEE implements the S-EL1 SPMC, this will get the SPMD ID. + * If not, the ID of the SPMC will be returned. + */ + struct thread_smc_args args = { + .a0 = FFA_SPM_ID_GET, + }; + + thread_smccc(&args); + if (!is_ffa_success(args.a0)) { + if (args.a0 == FFA_ERROR) + EMSG("Get spm id failed with error %ld", args.a2); + else + EMSG("Get spm id failed"); + panic(); + } + + return args.a2; +} + +#if defined(CFG_CORE_SEL1_SPMC) +static TEE_Result spmc_init(void) +{ + spmd_id = ffa_spm_id_get(); + DMSG("SPMD ID %#"PRIx16, spmd_id); + + spmc_id = ffa_id_get(); + DMSG("SPMC ID %#"PRIx16, spmc_id); + + optee_endpoint_id = FFA_SWD_ID_MIN; + while (optee_endpoint_id == spmd_id || optee_endpoint_id == spmc_id) + optee_endpoint_id++; + + DMSG("OP-TEE endpoint ID %#"PRIx16, optee_endpoint_id); + + /* + * If SPMD think we are version 1.0 it will report version 1.0 to + * normal world regardless of what version we query the SPM with. + * However, if SPMD think we are version 1.1 it will forward + * queries from normal world to let us negotiate version. So by + * setting version 1.0 here we should be compatible. + * + * Note that disagreement on negotiated version means that we'll + * have communication problems with normal world. + */ + my_rxtx.ffa_vers = FFA_VERSION_1_0; + + return TEE_SUCCESS; +} +#else /* !defined(CFG_CORE_SEL1_SPMC) */ +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 uint32_t get_ffa_version(uint32_t my_version) +{ + struct thread_smc_args args = { + .a0 = FFA_VERSION, + .a1 = my_version, + }; + + thread_smccc(&args); + if (args.a0 & BIT(31)) { + EMSG("FF-A version failed with error %ld", args.a0); + panic(); + } + + return args.a0; +} + +static void *spmc_retrieve_req(uint64_t cookie, + struct ffa_mem_transaction_x *trans) +{ + struct ffa_mem_access *acc_descr_array = NULL; + struct ffa_mem_access_perm *perm_descr = NULL; + struct thread_smc_args args = { + .a0 = FFA_MEM_RETRIEVE_REQ_32, + .a3 = 0, /* Address, Using TX -> MBZ */ + .a4 = 0, /* Using TX -> MBZ */ + }; + size_t size = 0; + int rc = 0; + + if (my_rxtx.ffa_vers == FFA_VERSION_1_0) { + struct ffa_mem_transaction_1_0 *trans_descr = my_rxtx.tx; + + size = sizeof(*trans_descr) + 1 * sizeof(struct ffa_mem_access); + 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; + } else { + struct ffa_mem_transaction_1_1 *trans_descr = my_rxtx.tx; + + size = sizeof(*trans_descr) + 1 * sizeof(struct ffa_mem_access); + 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; + trans_descr->mem_access_offs = sizeof(*trans_descr); + trans_descr->mem_access_size = sizeof(struct ffa_mem_access); + acc_descr_array = (void *)((vaddr_t)my_rxtx.tx + + sizeof(*trans_descr)); + } + acc_descr_array->region_offs = 0; + acc_descr_array->reserved = 0; + perm_descr = &acc_descr_array->access_perm; + perm_descr->endpoint_id = optee_endpoint_id; + perm_descr->perm = FFA_MEM_ACC_RW; + perm_descr->flags = 0; + + args.a1 = size; /* Total Length */ + args.a2 = size; /* Frag Length == Total length */ + 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; + } + rc = spmc_read_mem_transaction(my_rxtx.ffa_vers, my_rxtx.rx, + my_rxtx.size, trans); + if (rc) { + EMSG("Memory transaction failure for cookie %#"PRIx64" rc %d", + cookie, rc); + return NULL; + } + + return my_rxtx.rx; +} + +void thread_spmc_relinquish(uint64_t cookie) +{ + struct ffa_mem_relinquish *relinquish_desc = my_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] = optee_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_x retrieve_desc = { }; + 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; + void *buf = NULL; + 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. + */ + buf = spmc_retrieve_req(cookie, &retrieve_desc); + if (!buf) { + EMSG("Failed to retrieve cookie from rx buffer %#"PRIx64, + cookie); + return NULL; + } + + descr_array = (void *)((vaddr_t)buf + retrieve_desc.mem_access_offs); + offs = READ_ONCE(descr_array->region_offs); + descr = (struct ffa_mem_region *)((vaddr_t)buf + 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) +{ + unsigned int major = 0; + unsigned int minor __maybe_unused = 0; + uint32_t my_vers = 0; + uint32_t vers = 0; + + my_vers = MAKE_FFA_VERSION(FFA_VERSION_MAJOR, FFA_VERSION_MINOR); + vers = get_ffa_version(my_vers); + major = (vers >> FFA_VERSION_MAJOR_SHIFT) & FFA_VERSION_MAJOR_MASK; + minor = (vers >> FFA_VERSION_MINOR_SHIFT) & FFA_VERSION_MINOR_MASK; + DMSG("SPMC reported version %u.%u", major, minor); + if (major != FFA_VERSION_MAJOR) { + EMSG("Incompatible major version %u, expected %u", + major, FFA_VERSION_MAJOR); + panic(); + } + if (vers < my_vers) + my_vers = vers; + DMSG("Using version %u.%u", + (my_vers >> FFA_VERSION_MAJOR_SHIFT) & FFA_VERSION_MAJOR_MASK, + (my_vers >> FFA_VERSION_MINOR_SHIFT) & FFA_VERSION_MINOR_MASK); + my_rxtx.ffa_vers = my_vers; + + spmc_rxtx_map(&my_rxtx); + + spmc_id = ffa_spm_id_get(); + DMSG("SPMC ID %#"PRIx16, spmc_id); + + optee_endpoint_id = ffa_id_get(); + DMSG("OP-TEE endpoint ID %#"PRIx16, optee_endpoint_id); + + if (!ffa_features(FFA_NOTIFICATION_SET)) { + spmc_notif_is_ready = true; + DMSG("Asynchronous notifications are ready"); + } + + return TEE_SUCCESS; +} +#endif /* !defined(CFG_CORE_SEL1_SPMC) */ + +/* + * boot_final() is always done before exiting at end of boot + * initialization. In case of virtualization the init-calls are done only + * once a OP-TEE partition has been created. So with virtualization we have + * to initialize via boot_final() to make sure we have a value assigned + * before it's used the first time. + */ +#ifdef CFG_NS_VIRTUALIZATION +boot_final(spmc_init); +#else +service_init(spmc_init); +#endif 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..f451263 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/thread_spmc_a64.S @@ -0,0 +1,219 @@ +/* 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 + +#ifdef CFG_SECURE_PARTITION +LOCAL_FUNC thread_ffa_interrupt , : + mov_imm x0, FFA_INTERRUPT /* FID */ + /* X1: Endpoint/vCPU IDs is set by caller */ + 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_interrupt +#endif /* CFG_SECURE_PARTITION */ + +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 , : + msr spsel, #1 + ldr w0, [sp, #THREAD_CORE_LOCAL_DIRECT_RESP_FID] + msr spsel, #0 + mov x2, #FFA_PARAM_MBZ /* RES MBZ */ + +.ffa_msg_loop: + /* + * Native interrupts unmasked while invoking SMC with caller + * provided parameters. + */ + msr daifclr, #DAIFBIT_NATIVE_INTR + smc #0 + msr daifset, #DAIFBIT_NATIVE_INTR + + /* 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_spsr(uint32_t rv[THREAD_RPC_NUM_ARGS], uint64_t spsr) */ +FUNC thread_rpc_spsr , : + /* 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 w1, w21 + mov w3, #0 /* Error code = 0 */ + mov w4, w22 + mov w5, w23 + mov w6, w24 + mov w7, w0 /* Supply thread index */ + 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_spsr + +/* + * 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. + * If the active FF-A endpoint is OP-TEE (or a TA) then an this function send an + * OPTEE_FFA_YIELDING_CALL_RETURN_INTERRUPT message to the normal world via the + * FFA_MSG_SEND_DIRECT_RESP interface. This is handled by the OP-TEE + * driver in Linux so it can schedule task to the thread. + * If the active endpoint is an SP the function sends an FFA_INTERRUPT. This is + * handled by the FF-A driver and after taking care of the NWd interrupts it + * returns via an FFA_RUN call. + * The active endpoint is determined by checking the THREAD_FLAGS_FFA_ONLY flag + * in threads[w0].flags. This is only set for the thread which handles SPs. + */ +FUNC thread_foreign_intr_exit , : + /* load threads[w0].tsd.rpc_target_info into w1 */ + mov x1, #THREAD_CTX_SIZE + adr_l x2, threads + madd x2, x1, x0, x2 + ldr w1, [x2, #THREAD_CTX_TSD_RPC_TARGET_INFO] +#ifdef CFG_SECURE_PARTITION + /* load threads[w0].flags into w2 */ + ldr w2, [x2, #THREAD_CTX_FLAGS] + and w2, w2, #THREAD_FLAGS_FFA_ONLY + cbnz w2, thread_ffa_interrupt +#endif /* CFG_SECURE_PARTITION */ + 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..16f4ac0 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/timer_a64.c @@ -0,0 +1,62 @@ +// 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 = cpu_spin_lock_xsave(&timer_lock); + uint32_t timer_ticks = 0; + + if (timer_running == true) + goto exit; + + /* The timer will fire time_ms from now */ + timer_ticks = ((uint64_t)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_xrestore(&timer_lock, exceptions); +} + +void generic_timer_stop(void) +{ + uint32_t exceptions = cpu_spin_lock_xsave(&timer_lock); + + /* Disable the timer */ + write_cntps_ctl(0); + + timer_running = false; + + cpu_spin_unlock_xrestore(&timer_lock, exceptions); +} + +void generic_timer_handler(uint32_t time_ms) +{ + uint32_t timer_ticks = 0; + + /* 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 = ((uint64_t)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..79bffdd --- /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_va_allasid(vaddr_t va); */ +FUNC tlbi_va_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_va_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..fddc883 --- /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_va_allasid(vaddr_t va); */ +FUNC tlbi_va_allasid , : + lsr x0, x0, #TLBI_VA_SHIFT + dsb ishst /* Sync with table update */ + tlbi vaae1is, x0 /* Invalidate tlb by va in inner shareable */ + dsb ish /* Sync with tlb invalidation completion */ + isb /* Sync execution on tlb update */ + ret +END_FUNC tlbi_va_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..c5c94e7 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/tz_ssvce_pl310_a32.S @@ -0,0 +1,235 @@ +/* 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 + +/* + * __weak vaddr_t pl310_nsbase(void); + * return the non-secure PL310 base address + * + * Weak implementation to preserve the previous behavior where only the + * secure PL310 base address was returned. Up to the platform to map + * and return non-secure PL310 base address. + */ +WEAK_FUNC pl310_nsbase , : + b pl310_base +END_FUNC pl310_nsbase 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..506c5e7 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/virtualization.c @@ -0,0 +1,621 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2018, EPAM Systems. All rights reserved. + * Copyright (c) 2023, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +LIST_HEAD(prtn_list_head, guest_partition); + +static unsigned int prtn_list_lock __nex_data = SPINLOCK_UNLOCK; + +static struct prtn_list_head prtn_list __nex_data = + LIST_HEAD_INITIALIZER(prtn_list); +static struct prtn_list_head prtn_destroy_list __nex_data = + LIST_HEAD_INITIALIZER(prtn_destroy_list); + +/* 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; +#ifdef CFG_CORE_SEL1_SPMC + uint64_t cookies[SPMC_CORE_SEL1_MAX_SHM_COUNT]; + uint8_t cookie_count; + bitstr_t bit_decl(shm_bits, SPMC_CORE_SEL1_MAX_SHM_COUNT); +#endif +}; + +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; +} + +uint16_t virt_get_current_guest_id(void) +{ + struct guest_partition *prtn = get_current_prtn(); + + if (!prtn) + return 0; + return prtn->id; +} + +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; +} + +static bool +prtn_have_remaining_resources(struct guest_partition *prtn __maybe_unused) +{ +#ifdef CFG_CORE_SEL1_SPMC + int i = 0; + + if (prtn->cookie_count) + return true; + bit_ffs(prtn->shm_bits, SPMC_CORE_SEL1_MAX_SHM_COUNT, &i); + return i >= 0; +#else + return false; +#endif +} + +TEE_Result virt_guest_destroyed(uint16_t guest_id) +{ + struct guest_partition *prtn = NULL; + uint32_t exceptions = 0; + bool do_free = true; + + 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) { + if (!refcount_dec(&prtn->refc)) { + EMSG("Guest thread(s) is still running. refc = %d", + refcount_val(&prtn->refc)); + panic(); + } + LIST_REMOVE(prtn, link); + if (prtn_have_remaining_resources(prtn)) { + LIST_INSERT_HEAD(&prtn_destroy_list, prtn, + link); + /* + * Delay the nex_free() until + * virt_reclaim_cookie_from_destroyed_guest() + * is done with this partition. + */ + do_free = false; + } + break; + } + } + cpu_spin_unlock_xrestore(&prtn_list_lock, exceptions); + + if (prtn) { + tee_mm_free(prtn->tee_ram); + prtn->tee_ram = NULL; + tee_mm_free(prtn->ta_ram); + prtn->ta_ram = NULL; + tee_mm_free(prtn->tables); + prtn->tables = NULL; + core_free_mmu_prtn(prtn->mmu_prtn); + prtn->mmu_prtn = NULL; + nex_free(prtn->memory_map); + prtn->memory_map = NULL; + if (do_free) + 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); + + 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); +} + +#ifdef CFG_CORE_SEL1_SPMC +static int find_cookie(struct guest_partition *prtn, uint64_t cookie) +{ + int i = 0; + + for (i = 0; i < prtn->cookie_count; i++) + if (prtn->cookies[i] == cookie) + return i; + return -1; +} + +static struct guest_partition *find_prtn_cookie(uint64_t cookie, int *idx) +{ + struct guest_partition *prtn = NULL; + int i = 0; + + LIST_FOREACH(prtn, &prtn_list, link) { + i = find_cookie(prtn, cookie); + if (i >= 0) { + if (idx) + *idx = i; + return prtn; + } + } + + return NULL; +} + +TEE_Result virt_add_cookie_to_current_guest(uint64_t cookie) +{ + TEE_Result res = TEE_ERROR_ACCESS_DENIED; + struct guest_partition *prtn = NULL; + uint32_t exceptions = 0; + + exceptions = cpu_spin_lock_xsave(&prtn_list_lock); + if (find_prtn_cookie(cookie, NULL)) + goto out; + + prtn = current_partition[get_core_pos()]; + if (prtn->cookie_count < ARRAY_SIZE(prtn->cookies)) { + prtn->cookies[prtn->cookie_count] = cookie; + prtn->cookie_count++; + res = TEE_SUCCESS; + } +out: + cpu_spin_unlock_xrestore(&prtn_list_lock, exceptions); + + return res; +} + +void virt_remove_cookie(uint64_t cookie) +{ + struct guest_partition *prtn = NULL; + uint32_t exceptions = 0; + int i = 0; + + exceptions = cpu_spin_lock_xsave(&prtn_list_lock); + prtn = find_prtn_cookie(cookie, &i); + if (prtn) { + memmove(prtn->cookies + i, prtn->cookies + i + 1, + sizeof(uint64_t) * (prtn->cookie_count - i - 1)); + prtn->cookie_count--; + } + cpu_spin_unlock_xrestore(&prtn_list_lock, exceptions); +} + +uint16_t virt_find_guest_by_cookie(uint64_t cookie) +{ + struct guest_partition *prtn = NULL; + uint32_t exceptions = 0; + uint16_t ret = 0; + + exceptions = cpu_spin_lock_xsave(&prtn_list_lock); + prtn = find_prtn_cookie(cookie, NULL); + if (prtn) + ret = prtn->id; + + cpu_spin_unlock_xrestore(&prtn_list_lock, exceptions); + + return ret; +} + +bitstr_t *virt_get_shm_bits(void) +{ + return get_current_prtn()->shm_bits; +} + +static TEE_Result reclaim_cookie(struct guest_partition *prtn, uint64_t cookie) +{ + if (cookie & FFA_MEMORY_HANDLE_HYPERVISOR_BIT) { + size_t n = 0; + + for (n = 0; n < prtn->cookie_count; n++) { + if (prtn->cookies[n] == cookie) { + memmove(prtn->cookies + n, + prtn->cookies + n + 1, + sizeof(uint64_t) * + (prtn->cookie_count - n - 1)); + prtn->cookie_count--; + return TEE_SUCCESS; + } + } + } else { + uint64_t mask = FFA_MEMORY_HANDLE_NON_SECURE_BIT | + SHIFT_U64(FFA_MEMORY_HANDLE_PRTN_MASK, + FFA_MEMORY_HANDLE_PRTN_SHIFT); + int64_t i = cookie & ~mask; + + if (i >= 0 && i < SPMC_CORE_SEL1_MAX_SHM_COUNT && + bit_test(prtn->shm_bits, i)) { + bit_clear(prtn->shm_bits, i); + return TEE_SUCCESS; + } + } + + return TEE_ERROR_ITEM_NOT_FOUND; +} + +TEE_Result virt_reclaim_cookie_from_destroyed_guest(uint16_t guest_id, + uint64_t cookie) + +{ + struct guest_partition *prtn = NULL; + TEE_Result res = TEE_ERROR_ITEM_NOT_FOUND; + uint32_t exceptions = 0; + + exceptions = cpu_spin_lock_xsave(&prtn_list_lock); + LIST_FOREACH(prtn, &prtn_destroy_list, link) { + if (prtn->id == guest_id) { + res = reclaim_cookie(prtn, cookie); + if (prtn_have_remaining_resources(prtn)) + prtn = NULL; + else + LIST_REMOVE(prtn, link); + break; + } + } + cpu_spin_unlock_xrestore(&prtn_list_lock, exceptions); + + nex_free(prtn); + + return res; +} +#endif /*CFG_CORE_SEL1_SPMC*/ 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..334cdc6 --- /dev/null +++ b/optee/optee_os/core/arch/arm/mm/core_mmu.c @@ -0,0 +1,239 @@ +// 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_va_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_va_allasid_nosync(va); + len -= granule; + va += granule; + } + dsb_ish(); + isb(); +} + +void tlbi_va_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_va_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); + vaddr_t pl310_base_pa_op = 0; + + /* + * According the ARM PL310 documentation, if the operation is specific + * to the PA, the behavior is presented in the following manner: + * - Secure access: The data in the cache is only affected by the + * operation if it is secure. + * - Non-secure access: The data in the cache is only affected by the + * operation if it is non-secure. + * + * https://developer.arm.com/documentation/ddi0246/a/programmer-s-model/register-descriptions/register-7--cache-maintenance-operations + * + * Depending on the buffer location, use the secure or non-secure PL310 + * base address to do physical address based cache operation on the + * buffer. + */ + if (tee_pbuf_is_sec(pa, len)) + pl310_base_pa_op = pl310_base(); + else + pl310_base_pa_op = pl310_nsbase(); + + 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_op, 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_op, 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_op, pa, + pa + len - 1); + break; + default: + ret = TEE_ERROR_NOT_IMPLEMENTED; + } + + tee_l2cc_mutex_unlock(); + thread_unmask_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..dffbda8 --- /dev/null +++ b/optee/optee_os/core/arch/arm/mm/core_mmu_lpae.c @@ -0,0 +1,1381 @@ +// 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 TCR_PS_BITS_4PB (0x6) + +#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_hard_coded_pa_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 + */ + static_assert(CFG_CORE_ARM64_PA_BITS >= 32); + static_assert(CFG_CORE_ARM64_PA_BITS <= 52); + + 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; + + if (CFG_CORE_ARM64_PA_BITS <= 48) + return TCR_PS_BITS_256TB; + + /* CFG_CORE_ARM64_PA_BITS <= 48 */ + return TCR_PS_BITS_4PB; +} + +static unsigned int get_physical_addr_size_bits(void) +{ + const unsigned int size_bits = read_id_aa64mmfr0_el1() & + ID_AA64MMFR0_EL1_PARANGE_MASK; + unsigned int b = 0; + + if (IS_ENABLED(CFG_AUTO_MAX_PA_BITS)) + return size_bits; + + b = get_hard_coded_pa_size_bits(); + assert(b <= size_bits); + return b; +} + +unsigned int core_mmu_arm64_get_pa_width(void) +{ + const uint8_t map[] = { 32, 36, 40, 42, 44, 48, 52, }; + unsigned int size_bits = get_physical_addr_size_bits(); + + size_bits = MIN(size_bits, ARRAY_SIZE(map) - 1); + return map[size_bits]; +} + +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->next_level = level + 1; + 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->next_level = level + 1; + 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..61e703d --- /dev/null +++ b/optee/optee_os/core/arch/arm/mm/core_mmu_v7.c @@ -0,0 +1,828 @@ +// 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->next_level = level + 1; + 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..6a6aa0d --- /dev/null +++ b/optee/optee_os/core/arch/arm/mm/mobj_dyn_shm.c @@ -0,0 +1,472 @@ +// 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 + +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 beaten 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); + + /* + * Check that another thread hasn't been able to: + * - increase the mapcount + * - or, increase the mapcount, decrease it again, and set r->mm to + * NULL + * before we acquired the spinlock + */ + if (!refcount_val(&r->mapcount) && r->mm) + 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..2af1ec4 --- /dev/null +++ b/optee/optee_os/core/arch/arm/mm/mobj_ffa.c @@ -0,0 +1,767 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016-2020, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Life cycle of struct mobj_ffa + * + * SPMC at S-EL1 (CFG_CORE_SEL1_SPMC=y) + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * During FFA_MEM_SHARE allocated in mobj_ffa_sel1_spmc_new() and finally + * added to the inactive list at the end of add_mem_share() once + * successfully filled in. + * registered_by_cookie = false + * mobj.refs.val = 0 + * inactive_refs = 0 + * + * During FFA_MEM_RECLAIM reclaimed/freed using + * mobj_ffa_sel1_spmc_reclaim(). This will always succeed if the normal + * world is only calling this when all other threads are done with the + * shared memory object. However, there are some conditions that must be + * met to make sure that this is the case: + * mobj not in the active list, else -> return TEE_ERROR_BUSY + * mobj not in inactive list, else -> return TEE_ERROR_ITEM_NOT_FOUND + * mobj inactive_refs is 0, else -> return TEE_ERROR_BUSY + * + * mobj is activated using mobj_ffa_get_by_cookie() which unless the mobj + * is active already: + * - move the mobj into the active list + * - if not registered_by_cookie -> + * set registered_by_cookie and increase inactive_refs + * - set mobj.refc.val to 1 + * - increase inactive_refs + * + * A previously activated mobj is made ready for reclaim using + * mobj_ffa_unregister_by_cookie() which only succeeds if the mobj is in + * the inactive list and registered_by_cookie is set and then: + * - clears registered_by_cookie + * - decreases inactive_refs + * + * Each successful call to mobj_ffa_get_by_cookie() must be matched by a + * call to mobj_put(). If the mobj.refc.val reaches 0 it's + * - moved to the inactive list + * - inactive_refs is decreased + * + * SPMC at S-EL2/EL3 (CFG_CORE_SEL1_SPMC=n) + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * mobj is activated/allocated using mobj_ffa_get_by_cookie() which if + * already active only is + * - increasing mobj.refc.val and inactive_refs + * if found in inactive list is + * - setting mobj.refc.val to 1 + * - increasing inactive_refs + * - moved into active list + * if not found is created using thread_spmc_populate_mobj_from_rx() and + * then: + * - setting mobj.refc.val to 1 + * - increasing inactive_refs + * - moved into active list + * + * A previously activated mobj is relinquished using + * mobj_ffa_unregister_by_cookie() which only succeeds if the mobj is in + * the inactive list and inactive_refs is 1 + */ +struct mobj_ffa { + struct mobj mobj; + SLIST_ENTRY(mobj_ffa) link; + uint64_t cookie; + tee_mm_entry_t *mm; + struct refcount mapcount; + unsigned int inactive_refs; + uint16_t page_offset; +#ifdef CFG_CORE_SEL1_SPMC + bool registered_by_cookie; +#endif + paddr_t pages[]; +}; + +SLIST_HEAD(mobj_ffa_head, mobj_ffa); + +#ifdef CFG_CORE_SEL1_SPMC +#ifdef CFG_NS_VIRTUALIZATION +static bitstr_t *get_shm_bits(void) +{ + return virt_get_shm_bits(); +} +#else +static bitstr_t bit_decl(__shm_bits, SPMC_CORE_SEL1_MAX_SHM_COUNT); + +static bitstr_t *get_shm_bits(void) +{ + return __shm_bits; +} +#endif +#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); + mf->inactive_refs = 0; + + return mf; +} + +#ifdef CFG_CORE_SEL1_SPMC +struct mobj_ffa *mobj_ffa_sel1_spmc_new(uint64_t cookie, + unsigned int num_pages) +{ + struct mobj_ffa *mf = NULL; + bitstr_t *shm_bits = NULL; + uint32_t exceptions = 0; + int i = 0; + + if (cookie != OPTEE_MSG_FMEM_INVALID_GLOBAL_ID) { + if (!(cookie & FFA_MEMORY_HANDLE_HYPERVISOR_BIT)) + return NULL; + if (virt_add_cookie_to_current_guest(cookie)) + return NULL; + } + + mf = ffa_new(num_pages); + if (!mf) { + if (cookie != OPTEE_MSG_FMEM_INVALID_GLOBAL_ID) + virt_remove_cookie(cookie); + return NULL; + } + + if (cookie != OPTEE_MSG_FMEM_INVALID_GLOBAL_ID) { + mf->cookie = cookie; + return mf; + } + + shm_bits = get_shm_bits(); + exceptions = cpu_spin_lock_xsave(&shm_lock); + bit_ffc(shm_bits, SPMC_CORE_SEL1_MAX_SHM_COUNT, &i); + if (i != -1) { + bit_set(shm_bits, i); + mf->cookie = i; + mf->cookie |= FFA_MEMORY_HANDLE_NON_SECURE_BIT; + /* + * Encode the partition ID into the handle so we know which + * partition to switch to when reclaiming a handle. + */ + mf->cookie |= SHIFT_U64(virt_get_current_guest_id(), + FFA_MEMORY_HANDLE_PRTN_SHIFT); + } + 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) +{ + + if (!IS_ENABLED(CFG_NS_VIRTUALIZATION) || + !(mf->cookie & FFA_MEMORY_HANDLE_HYPERVISOR_BIT)) { + uint64_t mask = FFA_MEMORY_HANDLE_NON_SECURE_BIT; + bitstr_t *shm_bits = get_shm_bits(); + uint32_t exceptions = 0; + int64_t i = 0; + + if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) + mask |= SHIFT_U64(FFA_MEMORY_HANDLE_PRTN_MASK, + FFA_MEMORY_HANDLE_PRTN_SHIFT); + i = mf->cookie & ~mask; + assert(i >= 0 && i < SPMC_CORE_SEL1_MAX_SHM_COUNT); + + exceptions = cpu_spin_lock_xsave(&shm_lock); + assert(bit_test(shm_bits, i)); + bit_clear(shm_bits, i); + cpu_spin_unlock_xrestore(&shm_lock, exceptions); + } + + assert(!mf->mm); + 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->inactive_refs) { + DMSG("cookie %#"PRIx64" busy inactive_refs %u", + cookie, mf->inactive_refs); + 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); + virt_remove_cookie(cookie); + } + 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) { + EMSG("cookie %#"PRIx64" busy refc %u:%u", + cookie, refcount_val(&mf->mobj.refc), mf->inactive_refs); + 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 (!mf) { + EMSG("cookie %#"PRIx64" not found", cookie); + res = TEE_ERROR_ITEM_NOT_FOUND; + goto out; + } +#if defined(CFG_CORE_SEL1_SPMC) + if (!mf->registered_by_cookie) { + /* + * This is expected behaviour if the normal world has + * registered the memory but OP-TEE has not yet used the + * corresponding cookie with mobj_ffa_get_by_cookie(). It + * can be non-trivial for the normal world to predict if + * the cookie really has been used or not. So even if we + * return it as an error it will be ignored by + * handle_unregister_shm(). + */ + EMSG("cookie %#"PRIx64" not registered refs %u:%u", + cookie, refcount_val(&mf->mobj.refc), mf->inactive_refs); + res = TEE_ERROR_ITEM_NOT_FOUND; + goto out; + } + assert(mf->inactive_refs); + mf->inactive_refs--; + mf->registered_by_cookie = false; +#else + if (mf->inactive_refs) { + EMSG("cookie %#"PRIx64" busy refc %u:%u", + cookie, refcount_val(&mf->mobj.refc), mf->inactive_refs); + res = TEE_ERROR_BUSY; + 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); + mf->inactive_refs++; + } + DMSG("cookie %#"PRIx64" active: refc %u:%u", + cookie, refcount_val(&mf->mobj.refc), + mf->inactive_refs); + } 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 { + DMSG("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) + if (!mf->registered_by_cookie) { + mf->inactive_refs++; + 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->inactive_refs++; + + /* + * 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; + } + + /* + * pop_from_list() can fail to find the mobj if we had just + * decreased the refcount to 0 in mobj_put() and was going to + * acquire the shm_lock but another thread found this mobj and + * reinitialized the refcount to 1. Then before we got cpu time the + * other thread called mobj_put() and deactivated the mobj again. + * + * However, we still have the inactive count that guarantees + * that the mobj can't be freed until it reaches 0. + * At this point the mobj is in the inactive list. + */ + if (pop_from_list(&shm_head, cmp_ptr, (vaddr_t)mf)) { + unmap_helper(mf); + SLIST_INSERT_HEAD(&shm_inactive_head, mf, link); + } +out: + if (!mf->inactive_refs) + panic(); + mf->inactive_refs--; + 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/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..1fff635 --- /dev/null +++ b/optee/optee_os/core/arch/arm/mm/sub.mk @@ -0,0 +1,24 @@ +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-$(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..a9d3f39 --- /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_va_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_va_asid(va, asid); + return; + } +#endif + tlbi_va_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_va_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_va_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_va_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..42a32c2 --- /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 plat_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..d3249e2 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-aspeed/conf.mk @@ -0,0 +1,49 @@ +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 ?= 0xb0000000 +CFG_TZDRAM_SIZE ?= 0x1000000 + +CFG_CORE_RESERVED_SHM ?= n + +arm32-platform-cflags += -mfpu=vfpv3-d16 +else ifeq ($(PLATFORM_FLAVOR),ast2700) +include core/arch/arm/cpu/cortex-armv8-0.mk + +$(call force,CFG_8250_UART,y) +$(call force,CFG_ARM64_core,y) +$(call force,CFG_TEE_CORE_NB_CORE,4) +$(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) +$(call force,CFG_CORE_ARM64_PA_BITS,36) +$(call force,CFG_LPAE_ADDR_SPACE_BITS,36) + +CFG_NUM_THREADS ?= $(CFG_TEE_CORE_NB_CORE) + +CFG_DRAM_BASE ?= 0x400000000 +CFG_DRAM_SIZE ?= 0x40000000 + +CFG_TZDRAM_START ?= 0x430080000 +CFG_TZDRAM_SIZE ?= 0x1000000 + +CFG_CORE_RESERVED_SHM ?= n + +supported-ta-targets = ta_arm64 +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..8cc3eb3 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-aspeed/platform_ast2600.c @@ -0,0 +1,102 @@ +// 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; + +void boot_primary_init_intc(void) +{ + gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET); +} + +void boot_secondary_init_intc(void) +{ + gic_init_per_cpu(); +} + +void plat_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_ast2700.c b/optee/optee_os/core/arch/arm/plat-aspeed/platform_ast2700.c new file mode 100644 index 0000000..d88ec72 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-aspeed/platform_ast2700.c @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2023, Aspeed Technology Inc. + */ + +#include +#include +#include +#include +#include +#include +#include + +register_phys_mem(MEM_AREA_IO_SEC, UART_BASE, SMALL_PAGE_SIZE); +register_phys_mem(MEM_AREA_IO_SEC, GICD_BASE, GIC_DIST_REG_SIZE); +register_phys_mem(MEM_AREA_IO_SEC, GICR_BASE, GICR_SIZE); + +register_ddr(CFG_DRAM_BASE, CFG_DRAM_SIZE); + +static struct serial8250_uart_data console_data; + +void boot_primary_init_intc(void) +{ + gic_init_v3(0, GICD_BASE, GICR_BASE); +} + +void boot_secondary_init_intc(void) +{ + gic_init_per_cpu(); +} + +void plat_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-aspeed/platform_config.h b/optee/optee_os/core/arch/arm/plat-aspeed/platform_config.h new file mode 100644 index 0000000..c6b322f --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-aspeed/platform_config.h @@ -0,0 +1,41 @@ +/* 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 +#elif defined(PLATFORM_FLAVOR_ast2700) +#define GICD_BASE 0x12200000 +#define GICR_BASE 0x12280000 +#define GICR_SIZE 0x100000 + +#define UART_BASE 0x14c33000 +#define UART12_BASE (UART_BASE + 0xb00) + +#define CONSOLE_UART_BASE UART12_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..a9ca2b8 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-aspeed/sub.mk @@ -0,0 +1,3 @@ +global-incdirs-y += . +srcs-$(PLATFORM_FLAVOR_ast2600) += platform_ast2600.c core_pos_a32.S +srcs-$(PLATFORM_FLAVOR_ast2700) += platform_ast2700.c 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..5f4b816 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-bcm/conf.mk @@ -0,0 +1,44 @@ +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) +$(call force,CFG_CORE_ARM64_PA_BITS,48) +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..387d9d0 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-bcm/main.c @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2019 Broadcom. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 plat_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 boot_primary_init_intc(void) +{ + gic_init(0, GICD_BASE); +} 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..67fa5ce --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-corstone1000/main.c @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022, Arm Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +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 boot_primary_init_intc(void) +{ + gic_init(GICC_BASE, GICD_BASE); +} + +void boot_secondary_init_intc(void) +{ + gic_init_per_cpu(); +} + +void plat_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..0e5b9ec --- /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 plat_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..7c250a7 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-d06/conf.mk @@ -0,0 +1,30 @@ +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 ?= n +CFG_WITH_STATS ?= y +CFG_TEE_CORE_EMBED_INTERNAL_TESTS ?= y +CFG_HISILICON_CRYPTO_DRIVER ?= 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..9b83e75 --- /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 plat_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..3ca0a0f --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-d06/platform_config.h @@ -0,0 +1,24 @@ +/* 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 + +/* HISI_TRNG */ +#define HISI_TRNG_BASE 0x2010C0000 +#define HISI_TRNG_SIZE 0x100 + +#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..ac245b1 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-hikey/conf.mk @@ -0,0 +1,65 @@ +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_DRAM1_BASE ?= 0x40000000 + +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..44707bd --- /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_ddr(DRAM0_BASE, DRAM0_SIZE_NSEC); +#ifdef DRAM1_SIZE_NSEC +register_ddr(DRAM1_BASE, DRAM1_SIZE_NSEC); +#endif +#ifdef DRAM2_SIZE_NSEC +register_ddr(DRAM2_BASE, DRAM2_SIZE_NSEC); +#endif + +void plat_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"); + 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", + 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", read_val); + + DMSG("enable SPI clock"); + /* + * 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", + io_read32(peri_base + PERI_SC_PERIPH_CLKEN3)); + + DMSG("PERI_SC_PERIPH_CLKSTAT3: 0x%x", + 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"); + 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"); + 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"); + /* + * 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..f47479a --- /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 CFG_DRAM1_BASE + +#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..5b43da6 --- /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, 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, 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, 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, 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..77b8385 --- /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 plat_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..9c53338 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/conf.mk @@ -0,0 +1,540 @@ +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 \ + mx8dxmek \ + +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) +$(call force,CFG_TZC380,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) +$(call force,CFG_TZC380,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) +$(call force,CFG_TZC380,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) +$(call force,CFG_TZC380,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) +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 ?= n +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 ?= n +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),mx8dxmek)) +CFG_DDR_SIZE ?= 0x40000000 +CFG_UART_BASE ?= UART0_BASE +$(call force,CFG_MX8DX,y) +endif + +ifneq (,$(filter $(PLATFORM_FLAVOR),mx8dxlevk)) +CFG_DDR_SIZE ?= 0x40000000 +CFG_UART_BASE ?= UART0_BASE +CFG_NSEC_DDR_1_BASE ?= 0x800000000UL +CFG_NSEC_DDR_1_SIZE ?= 0x400000000UL +CFG_CORE_ARM64_PA_BITS ?= 40 +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)) + +# Enable embedded tests by default +CFG_ENABLE_EMBEDDED_TESTS ?= y + +# Set default heap size for imx platforms to 128k +CFG_CORE_HEAP_SIZE ?= 131072 + +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 +CFG_PKCS11_TA ?= 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..f846286 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/imx-regs.h @@ -0,0 +1,51 @@ +/* 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. + */ +#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 +#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..dfdee0b --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/imx.h @@ -0,0 +1,53 @@ +/* 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__ +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); +#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..ddf355e --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/imx_pl310.c @@ -0,0 +1,131 @@ +// 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); +register_phys_mem_pgdir(MEM_AREA_IO_NSEC, 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); +} + +vaddr_t pl310_nsbase(void) +{ + return core_mmu_get_va(PL310_BASE, MEM_AREA_IO_NSEC, 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/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..07b01f7 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/main.c @@ -0,0 +1,122 @@ +// 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 + +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 plat_console_init(void) +{ +#ifdef CONSOLE_UART_BASE + imx_uart_init(&console_data, CONSOLE_UART_BASE); + register_serial_console(&console_data.chip); +#endif +} + +void boot_primary_init_intc(void) +{ +#ifdef GICD_BASE + gic_init(0, GICD_BASE); +#else + gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET); +#endif +} + +#if CFG_TEE_CORE_NB_CORE > 1 +void boot_secondary_init_intc(void) +{ + gic_init_per_cpu(); +} +#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/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..3889989 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/registers/imx6.h @@ -0,0 +1,167 @@ +/* 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 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..6c3baf4 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/registers/imx7.h @@ -0,0 +1,79 @@ +/* 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_SIZE 0x4000 +#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 SRC_SIZE 0x4000 +#define GPC_BASE 0x303A0000 +#define GPC_SIZE 0x4000 +#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..9bda805 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/registers/imx8m.h @@ -0,0 +1,67 @@ +/* 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 +#define SECMEM_BASE 0x00100000 +#define SECMEM_SIZE 0x8000 + +#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..0849d03 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/sub.mk @@ -0,0 +1,20 @@ +global-incdirs-y += . +srcs-y += main.c imx-common.c + +srcs-$(CFG_PL310) += imx_pl310.c +ifeq ($(CFG_PSCI_ARM32),y) +$(call force,CFG_PM_ARM32,y) +CFG_IMX_PM ?= y +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 + +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..2fd235e --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-k3/conf.mk @@ -0,0 +1,37 @@ +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_LARGE_PHYS_ADDR,y) +$(call force,CFG_K3_OTP_KEYWRITING,y) +$(call force,CFG_CORE_ARM64_PA_BITS,36) + +ifneq (,$(filter ${PLATFORM_FLAVOR},am65x)) +$(call force,CFG_CORE_CLUSTER_SHIFT,1) +endif + +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..e11423e --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-k3/drivers/sa2ul.c @@ -0,0 +1,153 @@ +// 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_TIFS_PRIVID 0xca +#define FW_WILDCARD_PRIVID 0xc3 +#define FW_SECURE_ONLY GENMASK_32(7, 0) +#define FW_NON_SECURE GENMASK_32(15, 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] = { }; + uint32_t num_perm = 0; + 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; + start_address = RNG_BASE; + end_address = RNG_BASE + RNG_REG_SIZE - 1; + permissions[num_perm++] = (FW_BIG_ARM_PRIVID << 16) | FW_SECURE_ONLY; +#if defined(PLATFORM_FLAVOR_am62x) + permissions[num_perm++] = (FW_TIFS_PRIVID << 16) | FW_NON_SECURE; +#endif + ret = ti_sci_set_fwl_region(fwl_id, rng_region, num_perm, + 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..bbbaeac --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-k3/drivers/sa2ul_rng.c @@ -0,0 +1,161 @@ +// 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 struct mutex fifo_lock = MUTEX_INITIALIZER; +static vaddr_t rng; + +static bool sa2ul_rng_is_enabled(void) +{ + return io_read32(rng + RNG_CONTROL) & ENABLE_TRNG; +} + +static void sa2ul_rng_init_seq(void) +{ + uint32_t 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); + + io_write32(rng + RNG_CONTROL, ENABLE_TRNG); +} + +static void sa2ul_rng_read128(uint32_t *word0, uint32_t *word1, + uint32_t *word2, uint32_t *word3) +{ + if (!sa2ul_rng_is_enabled()) + sa2ul_rng_init_seq(); + + /* 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) { + mutex_lock(&fifo_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; + + mutex_unlock(&fifo_lock); + } + + return TEE_SUCCESS; +} + +TEE_Result sa2ul_rng_init(void) +{ + rng = (vaddr_t)phys_to_virt(RNG_BASE, MEM_AREA_IO_SEC, RNG_REG_SIZE); + + sa2ul_rng_init_seq(); + + 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..152fb5e --- /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..9d7c7dc --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-k3/drivers/ti_sci.c @@ -0,0 +1,496 @@ +// 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_get_swrev(uint32_t *swrev) +{ + struct ti_sci_msq_req_get_swrev req = { }; + struct ti_sci_msq_resp_get_swrev resp = { }; + struct ti_sci_xfer xfer = { }; + int ret = 0; + + ret = ti_sci_setup_xfer(TI_SCI_MSG_READ_SWREV, 0, + &req, sizeof(req), &resp, sizeof(resp), &xfer); + if (ret) + return ret; + + req.identifier = OTP_REV_ID_SEC_BRDCFG; + + ret = ti_sci_do_xfer(&xfer); + if (ret) + return ret; + + *swrev = resp.swrev; + memzero_explicit(&resp, sizeof(resp)); + return 0; +} + +int ti_sci_get_keycnt_keyrev(uint32_t *key_cnt, uint32_t *key_rev) +{ + struct ti_sci_msq_req_get_keycnt_keyrev req = { }; + struct ti_sci_msq_resp_get_keycnt_keyrev resp = { }; + struct ti_sci_xfer xfer = { }; + int ret = 0; + + ret = ti_sci_setup_xfer(TI_SCI_MSG_READ_KEYCNT_KEYREV, 0, + &req, sizeof(req), &resp, sizeof(resp), &xfer); + if (ret) + return ret; + + ret = ti_sci_do_xfer(&xfer); + if (ret) + return ret; + + *key_cnt = resp.keycnt; + *key_rev = resp.keyrev; + memzero_explicit(&resp, sizeof(resp)); + 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..497c4d9 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-k3/drivers/ti_sci.h @@ -0,0 +1,193 @@ +/* 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_get_swrev - Read Software Revision + * @swrev: Software Revision + * + * Reads the software revision. The System Firmware currently supports reading + * only the software revision from the Secure Board Configuration. + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_get_swrev(uint32_t *swrev); + +/** + * ti_sci_get_keycnt_keyrev - Read Key Count and Key Revision values + * @key_cnt: Key Count + * @key_rev: Key Revision + * + * Reads the Key Count and Key Revision in OTP + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_get_keycnt_keyrev(uint32_t *key_cnt, uint32_t *key_rev); + +/** + * 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..12e3098 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-k3/drivers/ti_sci_protocol.h @@ -0,0 +1,452 @@ +/* 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 + +/* OTP Revision Read/Write Message Description */ +#define TI_SCI_MSG_WRITE_SWREV 0x9032 +#define TI_SCI_MSG_READ_SWREV 0x9033 +#define TI_SCI_MSG_READ_KEYCNT_KEYREV 0x9034 +#define TI_SCI_MSG_WRITE_KEYREV 0x9035 + +/** + * 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; + +/** + * \brief OTP Revision Identifiers + */ +enum tisci_otp_revision_identifier { + /** Software Revision SBL */ + OTP_REV_ID_SBL = 0, + /** Software Revision SYSFW */ + OTP_REV_ID_SYSFW = 1, + /** Software Revision Secure Board Configuration */ + OTP_REV_ID_SEC_BRDCFG = 2, +}; + +/** + * struct ti_sci_msq_req_get_swrev - Request for reading the Software Revision + * in OTP + * @hdr: Generic header + * @identifier: One of the entries from enum tisci_otp_revision_identifier + * (Current support only for OTP_REV_ID_SEC_BRDCFG) + * + * Request for TI_SCI_MSG_READ_SWREV + */ +struct ti_sci_msq_req_get_swrev { + struct ti_sci_msg_hdr hdr; + uint8_t identifier; +} __packed; + +/** + * struct ti_sci_msq_req_get_swrev - Response for reading the Software Revision + * in OTP + * @hdr: Generic header + * @swrev: Decoded Sofrware Revision value from efuses + * + * Response for TI_SCI_MSG_READ_SWREV + */ +struct ti_sci_msq_resp_get_swrev { + struct ti_sci_msg_hdr hdr; + uint32_t swrev; +} __packed; + +/** + * struct ti_sci_msq_req_get_keycnt_keyrev - Request for reading the Key Count + * and Key Revision in OTP + * @hdr: Generic header + * + * Request for TI_SCI_MSG_READ_KEYCNT_KEYREV + */ +struct ti_sci_msq_req_get_keycnt_keyrev { + struct ti_sci_msg_hdr hdr; +} __packed; + +/** + * struct ti_sci_msq_req_get_swrev - Response for reading the Key Count and Key + * Revision in OTP + * @hdr: Generic header + * @keycnt: Key Count integer value + * @keyrev: Key Revision integer value + * + * Response for TI_SCI_MSG_READ_SWREV + */ +struct ti_sci_msq_resp_get_keycnt_keyrev { + struct ti_sci_msg_hdr hdr; + uint32_t keycnt; + uint32_t keyrev; +} __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..ecfe483 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-k3/main.c @@ -0,0 +1,107 @@ +// 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 + +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 boot_primary_init_intc(void) +{ + gic_init(GICC_BASE, GICD_BASE); +} + +void boot_secondary_init_intc(void) +{ + gic_init_per_cpu(); +} + +void plat_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); + +static TEE_Result secure_boot_information(void) +{ + uint32_t keycnt = 0; + uint32_t keyrev = 0; + uint32_t swrev = 0; + + if (!ti_sci_get_swrev(&swrev)) + IMSG("Secure Board Configuration Software: Rev %"PRIu32, + swrev); + + if (!ti_sci_get_keycnt_keyrev(&keycnt, &keyrev)) + IMSG("Secure Boot Keys: Count %"PRIu32 ", Rev %"PRIu32, + keycnt, keyrev); + + return TEE_SUCCESS; +} + +service_init_late(secure_boot_information); + +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..ae77a27 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-ls/conf.mk @@ -0,0 +1,131 @@ +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) + +CFG_ENABLE_EMBEDDED_TESTS ?= y +CFG_PKCS11_TA ?= y + +CFG_CORE_HEAP_SIZE ?= 131072 + +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,40) +$(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,40) +$(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..b501737 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-ls/main.c @@ -0,0 +1,221 @@ +// 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 + +#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 plat_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 boot_primary_init_intc(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); + gic_init(gic_base + gicc_offset, gic_base + gicd_offset); +} + +void boot_secondary_init_intc(void) +{ + gic_init_per_cpu(); +} 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/cn10k/core_pos.S b/optee/optee_os/core/arch/arm/plat-marvell/cn10k/core_pos.S new file mode 100644 index 0000000..dd7cced --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-marvell/cn10k/core_pos.S @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2023 Marvell. + */ + +#include +#include +#include + +FUNC get_core_pos_mpidr , : +/* No clusters, core position is affinity2 of MPIDR_EL1 */ + mov_imm x1, MPIDR_AFFLVL_MASK + and x0, x1, x0, LSR #MPIDR_AFF2_SHIFT + ret +END_FUNC get_core_pos_mpidr 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..473fd91 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-marvell/conf.mk @@ -0,0 +1,169 @@ +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_FLAVOR),cn10ka) +include core/arch/arm/cpu/cortex-armv8-0.mk +$(call force,CFG_TEE_CORE_NB_CORE,24) +$(call force,CFG_TZDRAM_START,0x00001000) +$(call force,CFG_TZDRAM_SIZE,0x000a00000) +$(call force,CFG_SHMEM_START,0x03400000) +$(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_USER_TA_TARGETS ?= ta_arm64 +CFG_NUM_THREADS ?= CFG_TEE_CORE_NB_CORE +CFG_CORE_HEAP_SIZE ?= 131072 +endif + +ifeq ($(PLATFORM_FLAVOR),cn10kb) +include core/arch/arm/cpu/cortex-armv8-0.mk +$(call force,CFG_TEE_CORE_NB_CORE,8) +$(call force,CFG_TZDRAM_START,0x00001000) +$(call force,CFG_TZDRAM_SIZE,0x000a00000) +$(call force,CFG_SHMEM_START,0x03400000) +$(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_USER_TA_TARGETS ?= ta_arm64 +CFG_NUM_THREADS ?= CFG_TEE_CORE_NB_CORE +CFG_CORE_HEAP_SIZE ?= 131072 +endif + +ifeq ($(PLATFORM_FLAVOR),cnf10ka) +include core/arch/arm/cpu/cortex-armv8-0.mk +$(call force,CFG_TEE_CORE_NB_CORE,18) +$(call force,CFG_TZDRAM_START,0x00001000) +$(call force,CFG_TZDRAM_SIZE,0x000a00000) +$(call force,CFG_SHMEM_START,0x03400000) +$(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_USER_TA_TARGETS ?= ta_arm64 +CFG_NUM_THREADS ?= CFG_TEE_CORE_NB_CORE +CFG_CORE_HEAP_SIZE ?= 131072 +endif + +ifeq ($(PLATFORM_FLAVOR),cnf10kb) +include core/arch/arm/cpu/cortex-armv8-0.mk +$(call force,CFG_TEE_CORE_NB_CORE,12) +$(call force,CFG_TZDRAM_START,0x00001000) +$(call force,CFG_TZDRAM_SIZE,0x000a00000) +$(call force,CFG_SHMEM_START,0x03400000) +$(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_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..1075c02 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-marvell/main.c @@ -0,0 +1,117 @@ +// 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 + +#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 boot_primary_init_intc(void) +{ + paddr_t gicd_base = 0; + paddr_t gicc_base = 0; + +#ifdef GICC_BASE + gicc_base = GIC_BASE + GICC_OFFSET; +#endif + gicd_base = GIC_BASE + GICD_OFFSET; + + gic_init(gicc_base, gicd_base); +} +#endif + +void plat_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..365a6e6 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-marvell/platform_config.h @@ -0,0 +1,160 @@ +/* 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) + +#elif defined(PLATFORM_FLAVOR_cn10ka) || defined(PLATFORM_FLAVOR_cn10kb) || \ + defined(PLATFORM_FLAVOR_cnf10ka) || defined(PLATFORM_FLAVOR_cnf10kb) +/* + * cn10k 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 + +#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..e72a8ec --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-marvell/sub.mk @@ -0,0 +1,10 @@ +global-incdirs-y += . +srcs-y += main.c +ifneq (,$(filter $(PLATFORM_FLAVOR),otx2t96 otx2f95 otx2t98)) +srcs-$(CFG_ARM64_core) += otx2/core_pos.S +endif +ifneq (,$(filter $(PLATFORM_FLAVOR),cn10ka cn10kb cnf10ka cnf10kb)) +srcs-$(CFG_ARM64_core) += cn10k/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..2975fc6 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-mediatek/conf.mk @@ -0,0 +1,92 @@ +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 + +ifeq ($(PLATFORM_FLAVOR),mt8188) +$(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 + +ifeq ($(PLATFORM_FLAVOR),mt7988) +$(call force,CFG_TEE_CORE_NB_CORE,4) +$(call force,CFG_CORE_CLUSTER_SHIFT,1) +$(call force,CFG_ARM_GICV3,y) +$(call force,CFG_GIC,y) +$(call force,CFG_WITH_SOFTWARE_PRNG,Y) +CFG_TZDRAM_START ?= 0x43041000 +CFG_TZDRAM_SIZE ?= 0x04ff000 +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..4d84e32 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-mediatek/main.c @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#if (CFG_TEE_CORE_LOG_LEVEL != 0) +register_phys_mem_pgdir(MEM_AREA_IO_NSEC, + CONSOLE_UART_BASE, SERIAL8250_UART_REG_SIZE); +#endif + +static struct serial8250_uart_data console_data; + +register_ddr(CFG_DRAM_BASE, CFG_DRAM_SIZE); + +#ifdef CFG_GIC +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 boot_primary_init_intc(void) +{ + gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET); +} +#endif + +void plat_console_init(void) +{ + if (CFG_TEE_CORE_LOG_LEVEL != 0) { + 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..ced421f --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-mediatek/platform_config.h @@ -0,0 +1,130 @@ +/* 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 + +#elif defined(PLATFORM_FLAVOR_mt8188) + +#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 115200 +#define CONSOLE_UART_CLK_IN_HZ 26000000 + +#elif defined(PLATFORM_FLAVOR_mt7988) + +#define GIC_BASE 0x0C000000 +#define GICC_OFFSET 0x400000 +#define GICD_OFFSET 0x000000 + +#define UART0_BASE 0x11000000 +#define UART1_BASE 0x11000100 +#define UART2_BASE 0x11000200 + +#define CONSOLE_UART_BASE UART0_BASE +#define CONSOLE_BAUDRATE 115200 +#define CONSOLE_UART_CLK_IN_HZ 40000000 + +#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-nuvoton/conf.mk b/optee/optee_os/core/arch/arm/plat-nuvoton/conf.mk new file mode 100644 index 0000000..c3fc96b --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-nuvoton/conf.mk @@ -0,0 +1,41 @@ +PLATFORM_FLAVOR ?= npcm845x + +ifeq ($(PLATFORM_FLAVOR),npcm845x) +include core/arch/arm/cpu/cortex-armv8-0.mk +CFG_ARM64_core ?= y +endif #npcm845x + +CFG_USER_TA_TARGETS ?= ta_arm64 + +$(call force,CFG_WITH_ARM_TRUSTED_FW,y) +$(call force,CFG_GIC,y) +$(call force,CFG_ARM_GICV2,y) +$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) +$(call force,CFG_16550_UART,y) + +# Not used now for current platform +$(call force,CFG_EXTERNAL_DT,n) + +CFG_WITH_STATS ?= y + +# To enable version printing with color in main +CFG_NPCM_DEBUG ?= n + +ifeq ($(PLATFORM_FLAVOR),npcm845x) +CFG_TEE_CORE_NB_CORE ?= 4 +# [3000.0000 031f.ffff] is reserved to early boot +CFG_TZDRAM_START ?= 0x02100000 +CFG_TZDRAM_SIZE ?= 0x03f00000 +# SHM chosen arbitrary, in a way that it does not interfere +# with initial location of linux kernel, dtb and initrd. +CFG_SHMEM_START ?= 0x06000000 +CFG_SHMEM_SIZE ?= 0x00200000 +# When Secure Data Path is enable, last MByte of TZDRAM is SDP test memory. +CFG_TEE_SDP_MEM_BASE ?= 0x05F00000 +CFG_TEE_SDP_MEM_SIZE ?= 0x00100000 +$(call force,CFG_DT,y) +CFG_DTB_MAX_SIZE ?= 0x100000 +$(call force,CFG_WITH_PAGER,n,Pager is not supported for NPCM845x) +else +$(error Unsupported platform flavor "$(PLATFORM_FLAVOR)") +endif #npcm845x diff --git a/optee/optee_os/core/arch/arm/plat-nuvoton/main.c b/optee/optee_os/core/arch/arm/plat-nuvoton/main.c new file mode 100644 index 0000000..c5ca407 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-nuvoton/main.c @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016-2023, Linaro Limited + * Copyright (c) 2014-2023, STMicroelectronics International N.V. + * Copyright (C) 2022-2023 Nuvoton Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define COLOR_NORMAL "\x1B[0m" +#define COLOR_RED "\x1B[31m" +#define COLOR_GREEN "\x1B[32m" +#define COLOR_YELLOW "\x1B[33m" +#define COLOR_BLUE "\x1B[34m" +#define COLOR_MAGENTA "\x1B[35m" +#define COLOR_CYAN "\x1B[36m" +#define COLOR_WHITE "\x1B[37m" + +#define NPCM_MEASURE_BASE 0xF0848000 +#define NPCM_MEASURE_UUID 0xC50 +#define NPCM_MEASURE_SIZE 5 + +static struct ns16550_data console_data __nex_bss; + +static struct { + uint8_t data[HW_UNIQUE_KEY_LENGTH]; + bool ready; +} npcm_hwkey; + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, CONSOLE_UART_BASE, UART_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_phys_mem_pgdir(MEM_AREA_RAM_NSEC, NPCM_MEASURE_BASE, SMALL_PAGE_SIZE); + +register_ddr(DRAM0_BASE, DRAM0_SIZE); + +static void print_version(void) +{ + IMSG(COLOR_MAGENTA); + IMSG(">================================================"); + IMSG("OP-TEE OS Version %s", core_v_str); + IMSG(">================================================"); + IMSG(COLOR_NORMAL); +} + +void boot_primary_init_intc(void) +{ + if (IS_ENABLED(CFG_NPCM_DEBUG)) + print_version(); + + gic_init(GICC_BASE, GICD_BASE); +} + +void plat_console_init(void) +{ + ns16550_init(&console_data, CONSOLE_UART_BASE, IO_WIDTH_U32, 2); + register_serial_console(&console_data.chip); +} + +TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey) +{ + void *vaddr = NULL; + TEE_Result res = TEE_SUCCESS; + uint32_t bin[HW_UNIQUE_KEY_LENGTH / sizeof(uint32_t)] = {}; + uint8_t *bin_val = (uint8_t *)(&bin[0]); + + if (npcm_hwkey.ready) + goto out; + + vaddr = phys_to_virt(NPCM_MEASURE_BASE + NPCM_MEASURE_UUID, + MEM_AREA_RAM_NSEC, NPCM_MEASURE_SIZE); + if (!vaddr) { + EMSG("Not enough memory mapped"); + return TEE_ERROR_SECURITY; + } + + res = tee_hash_createdigest(TEE_ALG_SHA256, (uint8_t *)vaddr, + NPCM_MEASURE_SIZE, bin_val, + HW_UNIQUE_KEY_LENGTH); + if (res != TEE_SUCCESS) { + EMSG("Can't create a digest for HUK"); + return TEE_ERROR_SECURITY; + } + + memcpy(&npcm_hwkey.data[0], bin, HW_UNIQUE_KEY_LENGTH); + npcm_hwkey.ready = true; + + IMSG("HUK Initialized"); + +out: + memcpy(hwkey->data, npcm_hwkey.data, HW_UNIQUE_KEY_LENGTH); + + return res; +} diff --git a/optee/optee_os/core/arch/arm/plat-nuvoton/platform_config.h b/optee/optee_os/core/arch/arm/plat-nuvoton/platform_config.h new file mode 100644 index 0000000..2d7dc77 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-nuvoton/platform_config.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014-2023, Linaro Limited + * Copyright (C) 2022-2023 Nuvoton Ltd. + */ + +#ifndef PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#include + +/* Make stacks aligned to data cache line length */ +#define STACK_ALIGNMENT 64 +#define DRAM0_BASE 0x00000000 +#define DRAM0_SIZE 0x40000000 /* 1G DDR */ +#define GIC_BASE 0xDFFF8000 +#define UART0_BASE 0xf0000000 +#define UART_REG_SIZE 0x100 +#define CONSOLE_UART_BASE UART0_BASE +#define GICD_OFFSET 0x1000 +#define GICC_OFFSET 0x2000 +#define GICD_BASE (GIC_BASE + GICD_OFFSET) +#define GICC_BASE (GIC_BASE + GICC_OFFSET) + +#endif /*PLATFORM_CONFIG_H*/ diff --git a/optee/optee_os/core/arch/arm/plat-nuvoton/sub.mk b/optee/optee_os/core/arch/arm/plat-nuvoton/sub.mk new file mode 100644 index 0000000..8ddc2fd --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-nuvoton/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..a97b6c8 --- /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 plat_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..451df5c --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rcar/conf.mk @@ -0,0 +1,46 @@ +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_DT ?= y +ifeq ($(CFG_RCAR_GEN3_HWRNG), y) +$(warning "Warning: Use of HWRNG can cause crashes on some Renesas SoCs") +CFG_WITH_SOFTWARE_PRNG ?= n +CFG_HWRNG_QUALITY ?= 1024 +CFG_HWRNG_PTA ?= y +$(call force,CFG_RCAR_ROMAPI, y) +endif +endif + +ifeq ($(CFG_RCAR_GEN4), y) +# 1xx - for SCIFxx +# 2xx - for HSCIFxx +CFG_TZDRAM_SIZE = 0x2200000 +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..122ad9b --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rcar/main.c @@ -0,0 +1,98 @@ +// 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; + +#ifdef PRR_BASE +uint32_t rcar_prr_value __nex_bss; +#endif + +void plat_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 boot_primary_init_intc(void) +{ + gic_init(GICC_BASE, GICD_BASE); +} + +void boot_secondary_init_intc(void) +{ + gic_init_per_cpu(); +} 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..19c2045 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rcar/romapi.c @@ -0,0 +1,162 @@ +// 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; + int try = 0; + 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); + + while (try++ < 3) { + ret = plat_call_romapi(func_addr, rndbuff_pa, scratch_pa, + scratch_sz); + if (ret == 0) + break; + IMSG("ROM_GetRndVector() returned "PRIx32, ret); + } + + /* + * 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..d50bede --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rockchip/main.c @@ -0,0 +1,50 @@ +// 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 + +#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 boot_primary_init_intc(void) +{ + gic_init(GICC_BASE, GICD_BASE); +} + +void boot_secondary_init_intc(void) +{ + gic_init_per_cpu(); +} + +void plat_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..8028f2c --- /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", 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..08cd490 --- /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", 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..1ff72ce --- /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", 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..5008c1b --- /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 plat_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..c58ca47 --- /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 plat_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..025645f --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rzn1/main.c @@ -0,0 +1,109 @@ +// 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 + +#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 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 plat_console_init(void) +{ + ns16550_init(&console_data, CONSOLE_UART_BASE, IO_WIDTH_U32, 2); + register_serial_console(&console_data.chip); +} + +void boot_primary_init_intc(void) +{ + gic_init(GICC_BASE, GICD_BASE); +} + +void boot_secondary_init_intc(void) +{ + gic_init_per_cpu(); +} + +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..a5a2fb1 --- /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 0x40000000 /* 1GB, and support 256MB */ + +/* 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..29a99b9 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sam/conf.mk @@ -0,0 +1,138 @@ +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 +flavor_dts_file-sama7g54_ek = at91-sama7g54_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)) + +ifeq ($(PLATFORM_FLAVOR),sama7g54_ek) +include core/arch/arm/cpu/cortex-a7.mk +$(call force,CFG_SAMA7G5,y) +$(call force,CFG_GIC,y) +$(call force,CFG_TZC400,y) +else +include core/arch/arm/cpu/cortex-a5.mk +$(call force,CFG_SAMA5D2,y) +$(call force,CFG_ATMEL_SAIC,y) +$(call force,CFG_PL310,y) +$(call force,CFG_PL310_LOCKED,y) +endif + +$(call force,CFG_TEE_CORE_NB_CORE,1) +$(call force,CFG_ATMEL_UART,y) +$(call force,CFG_ATMEL_TCB,y) +$(call force,CFG_NO_SMP,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_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(). +ifeq ($(CFG_SAMA7G5),y) +$(call force,CFG_TZDRAM_START,0x60000000) +endif +ifeq ($(CFG_SAMA5D2),y) +$(call force,CFG_TZDRAM_START,0x20000000) +endif +$(call force,CFG_TZDRAM_SIZE,0x800000) + +# This value is forced because these feature aren't used by SAM platforms. +$(call force,CFG_EXTERNAL_DT,n) +$(call force,CFG_CORE_DYN_SHM,n) + +CFG_MMAP_REGIONS ?= 24 + +CFG_SHMEM_START ?= ($(CFG_TZDRAM_START) + 0x1000000) +CFG_SHMEM_SIZE ?= 0x400000 + +CFG_SCMI_SHMEM_START ?= ($(CFG_TZDRAM_START) + 0x1400000) +CFG_SCMI_SHMEM_SIZE ?= 0x1000 + +CFG_TEE_RAM_VA_SIZE ?= 0x100000 + +# Device tree related configuration +CFG_DT_ADDR ?= ($(CFG_TZDRAM_START) + 0x1500000) +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_GPIO ?= y +CFG_DRIVERS_I2C ?= y +CFG_ATMEL_I2C ?= y +CFG_DRIVERS_PINCTRL ?= y +CFG_ATMEL_PIO ?= y +endif + +# SCMI related configuration +CFG_SCMI_PTA ?= y + +CFG_SCMI_MSG_DRIVERS ?= y +ifeq ($(CFG_SCMI_MSG_DRIVERS),y) +$(call force,CFG_SCMI_MSG_SMT,y) +$(call force,CFG_SCMI_MSG_CLOCK,y) +$(call force,CFG_SCMI_MSG_USE_CLK,y) +$(call force,CFG_SCMI_MSG_SMT_FASTCALL_ENTRY,y) +endif + +CFG_DRIVERS_NVMEM ?= y +ifeq ($(CFG_SAMA7G5),y) +CFG_ATMEL_SFC ?= n +CFG_NVMEM_DIE_ID ?= n +CFG_NVMEM_HUK ?= n +else +CFG_ATMEL_SFC ?= y +CFG_NVMEM_DIE_ID ?= y +CFG_NVMEM_HUK ?= 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..7ca1471 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sam/freq.c @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2022 Microchip + */ + +#include +#include +#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(); + + if (IS_ENABLED(CFG_SAMA7G5)) + node = fdt_node_offset_by_compatible(fdt, -1, "arm,cortex-a7"); + else + 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/matrix.c b/optee/optee_os/core/arch/arm/plat-sam/matrix.c new file mode 100644 index 0000000..f897e06 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sam/matrix.c @@ -0,0 +1,280 @@ +// 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 +#include + +#define WORLD_NON_SECURE 0 +#define WORLD_SECURE 1 + +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); +} + +vaddr_t matrix_base(unsigned int matrix) +{ + unsigned int i = 0; + struct matrix *pmatrix = NULL; + + do { + pmatrix = matrix_get(i++); + if (!pmatrix) + panic("Invalid matrix"); + } while (pmatrix->matrix != matrix); + + return io_pa_or_va_secure(&pmatrix->p, CORE_MMU_PGDIR_SIZE); +} + +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 = 0; + struct peri_security *p = NULL; + + do { + p = peri_security_get(i++); + if (p && peri_id == p->peri_id) + break; + } while (p); + + return p; +} + +static int matrix_set_periph_world(unsigned int matrix, unsigned int peri_id, + unsigned int world) +{ + unsigned int spselr = 0; + unsigned int idx = peri_id / 32; + unsigned int bit = 0x01 << (peri_id % 32); + unsigned int base = matrix_base(matrix); + + if (idx > 3) + 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; + struct peri_security *p = NULL; + + pbase = fdt_reg_base_address(fdt, node); + if (pbase == DT_INFO_INVALID_REG) + return TEE_ERROR_BAD_PARAMETERS; + + do { + p = peri_security_get(i++); + if (p && p->addr == pbase) { + *id = p->peri_id; + return TEE_SUCCESS; + } + } while (p); + + 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 = 0; + unsigned int *peri_id_p = peri_id_array; + unsigned int matrix = 0; + unsigned int peri_id = 0; + const struct peri_security *peripheral_sec = NULL; + int ret = 0; + + if (!peri_id_array || !size) + return -1; + + 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 + +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) +{ + unsigned int i = 0; + struct matrix *pmatrix = NULL; + + for (pmatrix = matrix_get(i++); pmatrix; pmatrix = matrix_get(i++)) + matrix_save_regs(matrix_base(pmatrix->matrix), &pmatrix->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) +{ + unsigned int i = 0; + struct matrix *pmatrix = NULL; + + for (pmatrix = matrix_get(i++); pmatrix; pmatrix = matrix_get(i++)) + matrix_restore_regs(matrix_base(pmatrix->matrix), + &pmatrix->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..eefe2d1 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sam/matrix.h @@ -0,0 +1,86 @@ +/* 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 +#include +#include + +#define SECURITY_TYPE_AS 1 +#define SECURITY_TYPE_NS 2 +#define SECURITY_TYPE_PS 3 + +#define MATRIX_SPSELR_COUNT 3 +#define MATRIX_SLAVE_COUNT 15 + +#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; +}; +#endif + +struct matrix { + unsigned int matrix; + struct io_pa_va p; +#ifdef CFG_PM_ARM32 + struct matrix_state state; +#endif +}; + +struct peri_security { + unsigned int peri_id; + unsigned int matrix; + unsigned int security_type; + paddr_t addr; +}; + +struct peri_security *peri_security_get(unsigned int idx); +struct matrix *matrix_get(unsigned int idx); +vaddr_t matrix_base(unsigned int matrix); + +void matrix_write_protect_enable(unsigned int matrix_base); +void matrix_write_protect_disable(unsigned int matrix_base); +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); + +#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..ff837c1 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sam/nsec-service/sm_platform_handler.c @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021, Microchip + */ + +#include +#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); + case SAMA5_SMC_SIP_SCMI_CALL_ID: + scmi_smt_fastcall_smc_entry(0); + args->a0 = SAMA5_SMC_SIP_RETURN_SUCCESS; + break; + 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..17180a0 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sam/nsec-service/smc_ids.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, Microchip + */ + +#ifndef SMC_IDS_H +#define SMC_IDS_H +#include +#include + +#define SAMA5_SMC_SIP_SCMI_CALL_ID 0x200 + +#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..d7f1f5b --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sam/platform_config.h @@ -0,0 +1,112 @@ +/* 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 +#if defined(PLATFORM_FLAVOR_sama7g54_ek) +#include +#else +#include +#endif + +#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_sama7g54_ek) +#define CONSOLE_UART_BASE (FLEXCOM3_BASE_ADDRESS + 0x200) +#define SFR_BASE SFR_BASE_ADDRESS +#define AT91C_BASE_TC0 TC0_BASE_ADDRESS +#define AT91C_ID_TC0 ID_TC0_CHANNEL0 +#define AT91C_ID_TC1 ID_TC1_CHANNEL0 +#define AT91C_ID_SYS ID_RSTC +#define AT91C_ID_PIOA ID_PIOA +#define AT91C_ID_PIOB ID_PIOB +#define AT91C_ID_PIOC ID_PIOC +#define AT91C_ID_PIOD ID_PIOD +#define AT91C_ID_WDT ID_DWDT_SW +#define AT91C_ID_TRNG ID_TRNG +#define AT91C_ID_SECUMOD ID_SECUMOD +#define AT91C_ID_SFR ID_SFR +#define AT91C_ID_SFRBU ID_SFRBU +#else +#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) +#endif + +/* + * 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/platform_sama5d2.c b/optee/optee_os/core/arch/arm/plat-sam/platform_sama5d2.c new file mode 100644 index 0000000..c52d8a8 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sam/platform_sama5d2.c @@ -0,0 +1,792 @@ +// 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 + +#define MATRIX_AXIMX 1 +#define MATRIX_H64MX 2 +#define MATRIX_H32MX 3 + +static struct matrix matrixes[] = { + { + .matrix = MATRIX_H64MX, + .p = { .pa = AT91C_BASE_MATRIX64 } + }, + { + .matrix = MATRIX_H32MX, + .p = { .pa = AT91C_BASE_MATRIX32, } + } +}; + +static 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 struct atmel_uart_data console_data; +register_phys_mem_pgdir(MEM_AREA_IO_SEC, CONSOLE_UART_BASE, + CORE_MMU_PGDIR_SIZE); + +void plat_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); + +struct peri_security *peri_security_get(unsigned int idx) +{ + struct peri_security *p = NULL; + + if (idx < ARRAY_SIZE(peri_security_array)) + p = &peri_security_array[idx]; + + return p; +} + +struct matrix *matrix_get(unsigned int idx) +{ + struct matrix *pmatrix = NULL; + + if (idx < ARRAY_SIZE(matrixes)) + pmatrix = &matrixes[idx]; + + return pmatrix; +} + +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(matrix_base(MATRIX_H64MX), + 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(matrix_base(MATRIX_H64MX), + 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(matrix_base(MATRIX_H64MX), + 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(matrix_base(MATRIX_H64MX), + H64MX_SLAVE_QSPI0, + srtop_setting, sasplit_setting, + ssr_setting); + matrix_configure_slave_security(matrix_base(MATRIX_H64MX), + 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(matrix_base(MATRIX_H32MX), + 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(matrix_base(MATRIX_H32MX), + 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(matrix_base(MATRIX_H32MX), + 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(matrix_base(MATRIX_H64MX)); + matrix_write_protect_disable(matrix_base(MATRIX_H32MX)); + + 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 boot_primary_init_intc(void) +{ + if (atmel_saic_setup()) + panic("Failed to init interrupts\n"); +} diff --git a/optee/optee_os/core/arch/arm/plat-sam/platform_sama7g5.c b/optee/optee_os/core/arch/arm/plat-sam/platform_sama7g5.c new file mode 100644 index 0000000..9c0653a --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sam/platform_sama7g5.c @@ -0,0 +1,937 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2024 Microchip Technology Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MATRIX_SAMA7G54 0 + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, CONSOLE_UART_BASE, + CORE_MMU_PGDIR_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, MATRIX_BASE_ADDRESS, + CORE_MMU_PGDIR_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, TZC_BASE_ADDRESS, CORE_MMU_PGDIR_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, TZPM_BASE_ADDRESS, + CORE_MMU_PGDIR_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_INTERFACE_BASE, GICC_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_DISTRIBUTOR_BASE, GICD_SIZE); + +static struct matrix matrixes[] = { + { + .matrix = MATRIX_SAMA7G54, + .p = { .pa = MATRIX_BASE_ADDRESS, }, + }, +}; + +static struct peri_security peri_security_array[] = { + { + .peri_id = ID_DWDT_SW, + .security_type = SECURITY_TYPE_AS, + .addr = DWDT_BASE_ADDRESS, + }, + { + .peri_id = ID_DWDT_NSW, + .security_type = SECURITY_TYPE_NS, + .addr = DWDT_BASE_ADDRESS, + }, + { + .peri_id = ID_DWDT_NSW_ALARM, + .security_type = SECURITY_TYPE_AS, + .addr = DWDT_BASE_ADDRESS, + }, + { + .peri_id = ID_SCKC, + .security_type = SECURITY_TYPE_AS, + .addr = SCKC_BASE_ADDRESS, + }, + { + .peri_id = ID_SHDWC, + .security_type = SECURITY_TYPE_AS, + .addr = SHDWC_BASE_ADDRESS, + }, + { + .peri_id = ID_RSTC, + .security_type = SECURITY_TYPE_AS, + .addr = RSTC_BASE_ADDRESS, + }, + { + .peri_id = ID_RTC, + .security_type = SECURITY_TYPE_AS, + .addr = RTC_BASE_ADDRESS, + }, + { + .peri_id = ID_RTT, + .security_type = SECURITY_TYPE_AS, + .addr = RTT_BASE_ADDRESS, + }, + { + .peri_id = ID_CHIPID, + .security_type = SECURITY_TYPE_PS, + .addr = CHIPID_BASE_ADDRESS, + }, + { + .peri_id = ID_PMC, + .security_type = SECURITY_TYPE_AS, + .addr = PMC_BASE_ADDRESS, + }, + { + .peri_id = ID_PIOA, + .security_type = SECURITY_TYPE_PS, + .addr = PIO_BASE_ADDRESS, + }, + { + .peri_id = ID_PIOB, + .security_type = SECURITY_TYPE_PS, + .addr = PIO_BASE_ADDRESS + 0x40, + }, + { + .peri_id = ID_PIOC, + .security_type = SECURITY_TYPE_PS, + .addr = PIO_BASE_ADDRESS + 0x80, + }, + { + .peri_id = ID_PIOD, + .security_type = SECURITY_TYPE_PS, + .addr = PIO_BASE_ADDRESS + 0xC0, + }, + { + .peri_id = ID_PIOE, + .security_type = SECURITY_TYPE_PS, + .addr = PIO_BASE_ADDRESS + 0x100, + }, + { + .peri_id = ID_SECUMOD, + .security_type = SECURITY_TYPE_AS, + .addr = SECUMOD_BASE_ADDRESS, + }, + { + .peri_id = ID_SECURAM, + .security_type = SECURITY_TYPE_AS, + .addr = 0xE0000000, + }, + { + .peri_id = ID_SFR, + .security_type = SECURITY_TYPE_PS, + .addr = SFR_BASE_ADDRESS, + }, + { + .peri_id = ID_SFRBU, + .security_type = SECURITY_TYPE_AS, + .addr = SFRBU_BASE_ADDRESS, + }, + { + .peri_id = ID_HSMC, + .security_type = SECURITY_TYPE_PS, + .addr = HSMC_BASE_ADDRESS, + }, + { + .peri_id = ID_XDMAC0, + .security_type = SECURITY_TYPE_PS, + .addr = XDMAC0_BASE_ADDRESS, + }, + { + .peri_id = ID_XDMAC1, + .security_type = SECURITY_TYPE_PS, + .addr = XDMAC1_BASE_ADDRESS, + }, + { + .peri_id = ID_XDMAC2, + .security_type = SECURITY_TYPE_PS, + .addr = XDMAC2_BASE_ADDRESS, + }, + { + .peri_id = ID_ACC, + .security_type = SECURITY_TYPE_PS, + .addr = ACC_BASE_ADDRESS, + }, + { + .peri_id = ID_ADC, + .security_type = SECURITY_TYPE_PS, + .addr = ADC_BASE_ADDRESS, + }, + { + .peri_id = ID_AES, + .security_type = SECURITY_TYPE_PS, + .addr = AES_BASE_ADDRESS, + }, + { + .peri_id = ID_TZAESBASC, + .security_type = SECURITY_TYPE_AS, + .addr = TZAESBASC_BASE_ADDRESS, + }, + { + .peri_id = ID_ASRC, + .security_type = SECURITY_TYPE_PS, + .addr = ASRC_BASE_ADDRESS, + }, + { + .peri_id = ID_CPKCC, + .security_type = SECURITY_TYPE_PS, + .addr = CPKCC_BASE_ADDRESS, + }, + { + .peri_id = ID_CSI, + .security_type = SECURITY_TYPE_PS, + .addr = CSI_BASE_ADDRESS, + }, + { + .peri_id = ID_CSI2DC, + .security_type = SECURITY_TYPE_PS, + .addr = CSI2DC_BASE_ADDRESS, + }, + { + .peri_id = ID_DDRPUBL, + .security_type = SECURITY_TYPE_PS, + .addr = DDRPUBL_BASE_ADDRESS, + }, + { + .peri_id = ID_DDRUMCTL, + .security_type = SECURITY_TYPE_PS, + .addr = DDRUMCTL_BASE_ADDRESS, + }, + { + .peri_id = ID_EIC, + .security_type = SECURITY_TYPE_PS, + .addr = EIC_BASE_ADDRESS, + }, + { + .peri_id = ID_FLEXCOM0, + .security_type = SECURITY_TYPE_PS, + .addr = FLEXCOM0_BASE_ADDRESS, + }, + { + .peri_id = ID_FLEXCOM1, + .security_type = SECURITY_TYPE_PS, + .addr = FLEXCOM1_BASE_ADDRESS, + }, + { + .peri_id = ID_FLEXCOM2, + .security_type = SECURITY_TYPE_PS, + .addr = FLEXCOM2_BASE_ADDRESS, + }, + { + .peri_id = ID_FLEXCOM3, + .security_type = SECURITY_TYPE_PS, + .addr = FLEXCOM3_BASE_ADDRESS, + }, + { + .peri_id = ID_FLEXCOM4, + .security_type = SECURITY_TYPE_PS, + .addr = FLEXCOM4_BASE_ADDRESS, + }, + { + .peri_id = ID_FLEXCOM5, + .security_type = SECURITY_TYPE_PS, + .addr = FLEXCOM5_BASE_ADDRESS, + }, + { + .peri_id = ID_FLEXCOM6, + .security_type = SECURITY_TYPE_PS, + .addr = FLEXCOM6_BASE_ADDRESS, + }, + { + .peri_id = ID_FLEXCOM7, + .security_type = SECURITY_TYPE_PS, + .addr = FLEXCOM7_BASE_ADDRESS, + }, + { + .peri_id = ID_FLEXCOM8, + .security_type = SECURITY_TYPE_PS, + .addr = FLEXCOM8_BASE_ADDRESS, + }, + { + .peri_id = ID_FLEXCOM9, + .security_type = SECURITY_TYPE_PS, + .addr = FLEXCOM9_BASE_ADDRESS, + }, + { + .peri_id = ID_FLEXCOM10, + .security_type = SECURITY_TYPE_PS, + .addr = FLEXCOM10_BASE_ADDRESS, + }, + { + .peri_id = ID_FLEXCOM11, + .security_type = SECURITY_TYPE_PS, + .addr = FLEXCOM11_BASE_ADDRESS, + }, + { + .peri_id = ID_GMAC0, + .security_type = SECURITY_TYPE_PS, + .addr = GMAC0_BASE_ADDRESS, + }, + { + .peri_id = ID_GMAC1, + .security_type = SECURITY_TYPE_PS, + .addr = GMAC1_BASE_ADDRESS, + }, + { + .peri_id = ID_GMAC0_TSU, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = ID_GMAC1_TSU, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = ID_ICM, + .security_type = SECURITY_TYPE_AS, + .addr = ICM_BASE_ADDRESS, + }, + { + .peri_id = ID_ISC, + .security_type = SECURITY_TYPE_PS, + .addr = ISC_BASE_ADDRESS, + }, + { + .peri_id = ID_I2SMCC0, + .security_type = SECURITY_TYPE_PS, + .addr = I2SMCC0_BASE_ADDRESS, + }, + { + .peri_id = ID_I2SMCC1, + .security_type = SECURITY_TYPE_PS, + .addr = I2SMCC1_BASE_ADDRESS, + }, + { + .peri_id = ID_MATRIX, + .security_type = SECURITY_TYPE_AS, + .addr = MATRIX_BASE_ADDRESS, + }, + { + .peri_id = ID_MCAN0, + .security_type = SECURITY_TYPE_PS, + .addr = MCAN0_BASE_ADDRESS, + }, + { + .peri_id = ID_MCAN1, + .security_type = SECURITY_TYPE_PS, + .addr = MCAN1_BASE_ADDRESS, + }, + { + .peri_id = ID_MCAN2, + .security_type = SECURITY_TYPE_PS, + .addr = MCAN2_BASE_ADDRESS, + }, + { + .peri_id = ID_MCAN3, + .security_type = SECURITY_TYPE_PS, + .addr = MCAN3_BASE_ADDRESS, + }, + { + .peri_id = ID_MCAN4, + .security_type = SECURITY_TYPE_PS, + .addr = MCAN4_BASE_ADDRESS, + }, + { + .peri_id = ID_MCAN5, + .security_type = SECURITY_TYPE_PS, + .addr = MCAN5_BASE_ADDRESS, + }, + { + .peri_id = ID_OTPC, + .security_type = SECURITY_TYPE_PS, + .addr = OTPC_BASE_ADDRESS, + }, + { + .peri_id = ID_PDMC0, + .security_type = SECURITY_TYPE_PS, + .addr = PDMC0_BASE_ADDRESS, + }, + { + .peri_id = ID_PDMC1, + .security_type = SECURITY_TYPE_PS, + .addr = PDMC1_BASE_ADDRESS, + }, + { + .peri_id = ID_PIT64B0, + .security_type = SECURITY_TYPE_PS, + .addr = PIT64B0_BASE_ADDRESS, + }, + { + .peri_id = ID_PIT64B1, + .security_type = SECURITY_TYPE_PS, + .addr = PIT64B1_BASE_ADDRESS, + }, + { + .peri_id = ID_PIT64B2, + .security_type = SECURITY_TYPE_PS, + .addr = PIT64B2_BASE_ADDRESS, + }, + { + .peri_id = ID_PIT64B3, + .security_type = SECURITY_TYPE_PS, + .addr = PIT64B3_BASE_ADDRESS, + }, + { + .peri_id = ID_PIT64B4, + .security_type = SECURITY_TYPE_PS, + .addr = PIT64B4_BASE_ADDRESS, + }, + { + .peri_id = ID_PIT64B5, + .security_type = SECURITY_TYPE_PS, + .addr = PIT64B5_BASE_ADDRESS, + }, + { + .peri_id = ID_PWM, + .security_type = SECURITY_TYPE_PS, + .addr = PWM_BASE_ADDRESS, + }, + { + .peri_id = ID_QSPI0, + .security_type = SECURITY_TYPE_PS, + .addr = QSPI0_BASE_ADDRESS, + }, + { + .peri_id = ID_QSPI1, + .security_type = SECURITY_TYPE_PS, + .addr = QSPI1_BASE_ADDRESS, + }, + { + .peri_id = ID_SDMMC0, + .security_type = SECURITY_TYPE_PS, + .addr = SDMMC0_BASE_ADDRESS, + }, + { + .peri_id = ID_SDMMC1, + .security_type = SECURITY_TYPE_PS, + .addr = SDMMC1_BASE_ADDRESS, + }, + { + .peri_id = ID_SDMMC2, + .security_type = SECURITY_TYPE_PS, + .addr = SDMMC2_BASE_ADDRESS, + }, + { + .peri_id = ID_SHA, + .security_type = SECURITY_TYPE_PS, + .addr = SHA_BASE_ADDRESS, + }, + { + .peri_id = ID_SPDIFRX, + .security_type = SECURITY_TYPE_PS, + .addr = SPDIFRX_BASE_ADDRESS, + }, + { + .peri_id = ID_SPDIFTX, + .security_type = SECURITY_TYPE_PS, + .addr = SPDIFTX_BASE_ADDRESS, + }, + { + .peri_id = ID_SSC0, + .security_type = SECURITY_TYPE_PS, + .addr = SSC0_BASE_ADDRESS, + }, + { + .peri_id = ID_SSC1, + .security_type = SECURITY_TYPE_PS, + .addr = SSC1_BASE_ADDRESS, + }, + { + .peri_id = ID_TC0_CHANNEL0, + .security_type = SECURITY_TYPE_PS, + .addr = TC0_BASE_ADDRESS, + }, + { + .peri_id = ID_TC0_CHANNEL1, + .security_type = SECURITY_TYPE_PS, + .addr = TC0_BASE_ADDRESS + 0x40, + }, + { + .peri_id = ID_TC0_CHANNEL2, + .security_type = SECURITY_TYPE_PS, + .addr = TC0_BASE_ADDRESS + 0x80, + }, + { + .peri_id = ID_TC1_CHANNEL0, + .security_type = SECURITY_TYPE_PS, + .addr = TC1_BASE_ADDRESS, + }, + { + .peri_id = ID_TC1_CHANNEL1, + .security_type = SECURITY_TYPE_PS, + .addr = TC1_BASE_ADDRESS + 0x40, + }, + { + .peri_id = ID_TC1_CHANNEL2, + .security_type = SECURITY_TYPE_PS, + .addr = TC1_BASE_ADDRESS + 0x80, + }, + { + .peri_id = ID_TCPCA, + .security_type = SECURITY_TYPE_PS, + .addr = TCPCA_BASE_ADDRESS, + }, + { + .peri_id = ID_TCPCB, + .security_type = SECURITY_TYPE_PS, + .addr = TCPCB_BASE_ADDRESS, + }, + { + .peri_id = ID_TDES, + .security_type = SECURITY_TYPE_PS, + .addr = TDES_BASE_ADDRESS, + }, + { + .peri_id = ID_TRNG, + .security_type = SECURITY_TYPE_PS, + .addr = TRNG_BASE_ADDRESS, + }, + { + .peri_id = ID_TZAESB_NS, + .security_type = SECURITY_TYPE_PS, + .addr = TZAESBNS_BASE_ADDRESS, + }, + { + .peri_id = ID_TZAESB_NS_SINT, + .security_type = SECURITY_TYPE_AS, + .addr = TZAESBNS_BASE_ADDRESS,}, + { + .peri_id = ID_TZAESB_S, + .security_type = SECURITY_TYPE_PS, + .addr = TZAESBS_BASE_ADDRESS, + }, + { + .peri_id = ID_TZAESB_S_SINT, + .security_type = SECURITY_TYPE_AS, + .addr = TZAESBS_BASE_ADDRESS, + }, + { + .peri_id = ID_TZC, + .security_type = SECURITY_TYPE_AS, + .addr = TZC_BASE_ADDRESS, + }, + { + .peri_id = ID_TZPM, + .security_type = SECURITY_TYPE_PS, + .addr = TZPM_BASE_ADDRESS, + }, + { + .peri_id = ID_UDPHSA, + .security_type = SECURITY_TYPE_PS, + .addr = UDPHSA_BASE_ADDRESS, + }, + { + .peri_id = ID_UDPHSB, + .security_type = SECURITY_TYPE_PS, + .addr = UDPHSB_BASE_ADDRESS, + }, + { + .peri_id = ID_UHPHS, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = ID_XDMAC0_SINT, + .security_type = SECURITY_TYPE_PS, + .addr = XDMAC0_BASE_ADDRESS, + }, + { + .peri_id = ID_XDMAC1_SINT, + .security_type = SECURITY_TYPE_PS, + .addr = XDMAC1_BASE_ADDRESS, + }, + { + .peri_id = ID_XDMAC2_SINT, + .security_type = SECURITY_TYPE_PS, + .addr = XDMAC2_BASE_ADDRESS, + }, + { + .peri_id = ID_AES_SINT, + .security_type = SECURITY_TYPE_PS, + .addr = AES_BASE_ADDRESS, + }, + { + .peri_id = ID_GMAC0_Q1, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = ID_GMAC0_Q2, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = ID_GMAC0_Q3, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = ID_GMAC0_Q4, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = ID_GMAC0_Q5, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = ID_GMAC1_Q1, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = ID_ICM_SINT, + .security_type = SECURITY_TYPE_AS, + .addr = ICM_BASE_ADDRESS, + }, + { + .peri_id = ID_MCAN0_INT1, + .security_type = SECURITY_TYPE_PS, + .addr = MCAN0_BASE_ADDRESS, + }, + { + .peri_id = ID_MCAN1_INT1, + .security_type = SECURITY_TYPE_PS, + .addr = MCAN1_BASE_ADDRESS, + }, + { + .peri_id = ID_MCAN2_INT1, + .security_type = SECURITY_TYPE_PS, + .addr = MCAN2_BASE_ADDRESS, + }, + { + .peri_id = ID_MCAN3_INT1, + .security_type = SECURITY_TYPE_PS, + .addr = MCAN3_BASE_ADDRESS, + }, + { + .peri_id = ID_MCAN4_INT1, + .security_type = SECURITY_TYPE_PS, + .addr = MCAN4_BASE_ADDRESS, + }, + { + .peri_id = ID_MCAN5_INT1, + .security_type = SECURITY_TYPE_PS, + .addr = MCAN5_BASE_ADDRESS, + }, + { + .peri_id = ID_PIOA_SINT, + .security_type = SECURITY_TYPE_PS, + .addr = PIO_BASE_ADDRESS, + }, + { + .peri_id = ID_PIOB_SINT, + .security_type = SECURITY_TYPE_PS, + .addr = PIO_BASE_ADDRESS + 0x40, + }, + { + .peri_id = ID_PIOC_SINT, + .security_type = SECURITY_TYPE_PS, + .addr = PIO_BASE_ADDRESS + 0x80, + }, + { + .peri_id = ID_PIOD_SINT, + .security_type = SECURITY_TYPE_PS, + .addr = PIO_BASE_ADDRESS + 0xC0, + }, + { + .peri_id = ID_PIOE_SINT, + .security_type = SECURITY_TYPE_PS, + .addr = PIO_BASE_ADDRESS + 0x100, + }, + { + .peri_id = ID_PIT64B0_SINT, + .security_type = SECURITY_TYPE_PS, + .addr = PIT64B0_BASE_ADDRESS, + }, + { + .peri_id = ID_PIT64B1_SINT, + .security_type = SECURITY_TYPE_PS, + .addr = PIT64B1_BASE_ADDRESS, + }, + { + .peri_id = ID_PIT64B2_SINT, + .security_type = SECURITY_TYPE_PS, + .addr = PIT64B2_BASE_ADDRESS, + }, + { + .peri_id = ID_PIT64B3_SINT, + .security_type = SECURITY_TYPE_PS, + .addr = PIT64B3_BASE_ADDRESS, + }, + { + .peri_id = ID_PIT64B4_SINT, + .security_type = SECURITY_TYPE_PS, + .addr = PIT64B4_BASE_ADDRESS, + }, + { + .peri_id = ID_PIT64B5_SINT, + .security_type = SECURITY_TYPE_PS, + .addr = PIT64B5_BASE_ADDRESS, + }, + { + .peri_id = ID_SDMMC0_TIMER, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = ID_SDMMC1_TIMER, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = ID_SDMMC2_TIMER, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = ID_SHA_SINT, + .security_type = SECURITY_TYPE_PS, + .addr = SHA_BASE_ADDRESS, + }, + { + .peri_id = ID_TC0_SINT0, + .security_type = SECURITY_TYPE_PS, + .addr = TC0_BASE_ADDRESS, + }, + { + .peri_id = ID_TC0_SINT1, + .security_type = SECURITY_TYPE_PS, + .addr = TC0_BASE_ADDRESS, + }, + { + .peri_id = ID_TC0_SINT2, + .security_type = SECURITY_TYPE_PS, + .addr = TC0_BASE_ADDRESS, + }, + { + .peri_id = ID_TC1_SINT0, + .security_type = SECURITY_TYPE_PS, + .addr = TC1_BASE_ADDRESS, + }, + { + .peri_id = ID_TC1_SINT1, + .security_type = SECURITY_TYPE_PS, + .addr = TC1_BASE_ADDRESS, + }, + { + .peri_id = ID_TC1_SINT2, + .security_type = SECURITY_TYPE_PS, + .addr = TC1_BASE_ADDRESS, + }, + { + .peri_id = ID_TDES_SINT, + .security_type = SECURITY_TYPE_PS, + .addr = TDES_BASE_ADDRESS, + }, + { + .peri_id = ID_TRNG_SINT, + .security_type = SECURITY_TYPE_PS, + .addr = TRNG_BASE_ADDRESS, + }, + { + .peri_id = ID_EXT_IRQ0, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = ID_EXT_IRQ1, + .security_type = SECURITY_TYPE_PS, + }, +}; + +static struct atmel_uart_data console_data; + +void plat_console_init(void) +{ + atmel_uart_init(&console_data, CONSOLE_UART_BASE); + register_serial_console(&console_data.chip); +} + +struct peri_security *peri_security_get(unsigned int idx) +{ + struct peri_security *p = NULL; + + if (idx < ARRAY_SIZE(peri_security_array)) + p = &peri_security_array[idx]; + + return p; +} + +struct matrix *matrix_get(unsigned int idx) +{ + struct matrix *p = NULL; + + if (idx < ARRAY_SIZE(matrixes)) + p = &matrixes[idx]; + + return p; +} + +static void matrix_configure_slave(void) +{ + unsigned int sasplit_setting = 0; + unsigned int srtop_setting = 0; + unsigned int ssr_setting = 0; + unsigned int base = 0; + + static_assert(CFG_TZDRAM_START == DDR_CS_ADDR); + static_assert(CFG_TZDRAM_SIZE == 0x800000); + + base = matrix_base(MATRIX_SAMA7G54); + + /* 0: QSPI0: Normal world */ + /* 1: QSPI1: Normal world */ + srtop_setting = MATRIX_SRTOP(0, MATRIX_SRTOP_VALUE_128M) | + MATRIX_SRTOP(1, MATRIX_SRTOP_VALUE_128M); + sasplit_setting = MATRIX_SASPLIT(0, MATRIX_SASPLIT_VALUE_128M) | + MATRIX_SASPLIT(1, MATRIX_SASPLIT_VALUE_128M); + ssr_setting = MATRIX_LANSECH_NS(0) | + MATRIX_LANSECH_NS(1) | + MATRIX_RDNSECH_NS(0) | + MATRIX_RDNSECH_NS(1) | + MATRIX_WRNSECH_NS(0) | + MATRIX_WRNSECH_NS(1); + matrix_configure_slave_security(base, 0, srtop_setting, + sasplit_setting, ssr_setting); + matrix_configure_slave_security(base, 1, srtop_setting, + sasplit_setting, ssr_setting); + + /* 2: TZAESB: Default */ + + /* 3: UDDRC_P1: Non-Secure, except op-tee tee/ta memory */ + /* + * 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. + */ + srtop_setting = MATRIX_SRTOP(0, MATRIX_SRTOP_VALUE_128M); + sasplit_setting = MATRIX_SASPLIT(0, MATRIX_SASPLIT_VALUE_8M); + ssr_setting = MATRIX_LANSECH_S(0) | + MATRIX_RDNSECH_S(0) | + MATRIX_WRNSECH_S(0); + matrix_configure_slave_security(base, 3, srtop_setting, + sasplit_setting, ssr_setting); + + /* 4: APB6: Default */ + + /* + * 5: SRAM_P0 + * 6: SRAM_P1 + */ + srtop_setting = MATRIX_SRTOP(0, MATRIX_SRTOP_VALUE_128K); + sasplit_setting = MATRIX_SASPLIT(0, MATRIX_SASPLIT_VALUE_64K); + ssr_setting = MATRIX_LANSECH_NS(0) | + MATRIX_RDNSECH_S(0) | + MATRIX_WRNSECH_S(0); + matrix_configure_slave_security(base, 5, srtop_setting, + sasplit_setting, ssr_setting); + matrix_configure_slave_security(base, 6, srtop_setting, + sasplit_setting, ssr_setting); + + /* + * 7: SMC + * EBI_CS0 ----> Slave Region 0 + * EBI_CS1 ----> Slave Region 1 + * EBI_CS2 ----> Slave Region 2 + * EBI_CS3 ----> Slave Region 3 + * NFC_CMD ----> Slave Region 4 : Non-Secure + */ + srtop_setting = MATRIX_SRTOP(4, MATRIX_SRTOP_VALUE_128M); + sasplit_setting = MATRIX_SASPLIT(4, MATRIX_SASPLIT_VALUE_128M); + ssr_setting = MATRIX_LANSECH_NS(4) | + MATRIX_RDNSECH_NS(4) | + MATRIX_WRNSECH_NS(4); + matrix_configure_slave_security(base, 7, srtop_setting, + sasplit_setting, ssr_setting); + + /* + * 8: NFC_RAM + * Slave area below SASSPLIT boundary is configured as Not Secured + */ + 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_configure_slave_security(base, 8, srtop_setting, + sasplit_setting, ssr_setting); + + /* + * 9: USB_RAM + * Slave area below SASSPLIT boundary is configured as Not Secured + */ + srtop_setting = MATRIX_SRTOP(0, MATRIX_SRTOP_VALUE_1M) | + MATRIX_SRTOP(1, MATRIX_SRTOP_VALUE_1M) | + MATRIX_SRTOP(2, MATRIX_SRTOP_VALUE_4K) | + MATRIX_SRTOP(3, MATRIX_SRTOP_VALUE_4K); + sasplit_setting = MATRIX_SASPLIT(0, MATRIX_SASPLIT_VALUE_1M) | + MATRIX_SASPLIT(1, MATRIX_SASPLIT_VALUE_1M) | + MATRIX_SASPLIT(2, MATRIX_SASPLIT_VALUE_4K) | + MATRIX_SASPLIT(3, MATRIX_SASPLIT_VALUE_4K); + ssr_setting = MATRIX_LANSECH_NS(0) | + MATRIX_LANSECH_NS(1) | + MATRIX_LANSECH_NS(2) | + MATRIX_LANSECH_NS(3); + matrix_configure_slave_security(base, 9, srtop_setting, + sasplit_setting, ssr_setting); +} + +static void matrix_init(void) +{ + matrix_write_protect_disable(matrix_base(MATRIX_SAMA7G54)); + matrix_configure_slave(); +} + +static void tzc400_init(void) +{ + struct tzc_region_config cfg = { }; + unsigned int tzc_idx = 0; + vaddr_t addr = 0; + + for (tzc_idx = 0; tzc_idx <= 1; tzc_idx++) { + addr = TZC_BASE_ADDRESS + 0x1000 * tzc_idx; + tzc_init(addr); + + if (tzc_idx) + cfg.filters = BIT(0); + else + cfg.filters = GENMASK_32(3, 0); + cfg.sec_attr = TZC_REGION_S_RDWR; + + cfg.base = 0x00000000; + cfg.top = 0xffffffff; + cfg.ns_device_access = BIT(16) | BIT(0); + tzc_configure_region(0, &cfg); + + cfg.base = CFG_TZDRAM_START; + cfg.top = cfg.base + CFG_TZDRAM_SIZE - 1; + cfg.ns_device_access = 0; + tzc_configure_region(1, &cfg); + + cfg.base += CFG_TZDRAM_SIZE; + cfg.top = cfg.base - CFG_TZDRAM_SIZE + DDR_CS_SIZE - 1; + cfg.ns_device_access = BIT(16) | BIT(0); + tzc_configure_region(2, &cfg); + } +} + +static void tzpm_init(void) +{ + struct peri_security *p = peri_security_array; + unsigned int i = 0; + vaddr_t addr = TZPM_BASE_ADDRESS; + + /* TZPM_PIDx register write is possible. */ + io_write32(addr + 0x04, 0x12AC4B5D); + + for (i = 0; i < ARRAY_SIZE(peri_security_array); i++, p++) + if (p->peri_id < 128 && + p->security_type == SECURITY_TYPE_PS) + io_setbits32(addr + 8 + 4 * (p->peri_id / 32), + BIT(p->peri_id % 32)); +} + +void plat_primary_init_early(void) +{ + assert(!cpu_mmu_enabled()); + matrix_init(); + tzc400_init(); + tzpm_init(); +} + +void boot_primary_init_intc(void) +{ + gic_init(GIC_INTERFACE_BASE, GIC_DISTRIBUTOR_BASE); +} 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..184f72b --- /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/sama7g5.h b/optee/optee_os/core/arch/arm/plat-sam/sama7g5.h new file mode 100644 index 0000000..46f6bd2 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sam/sama7g5.h @@ -0,0 +1,338 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Header file for ATSAMA7G54 + * + * Copyright (c) 2023 Microchip Technology Inc. and its subsidiaries. + */ + +#ifndef _SAMA7G54_H_ +#define _SAMA7G54_H_ + +/* + * SAMA7G54 definitions + * This file defines all structures and symbols for SAMA7G54: + * - registers and bitfields + * - peripheral base address + * - peripheral ID + * - PIO definitions + */ + +#define GIC_DISTRIBUTOR_BASE 0xE8C11000 /* Base for GIC distributor interface */ +#define GIC_INTERFACE_BASE 0xE8C12000 /* Base address for GIC CPU interface */ +#define GICC_SIZE 0x1000 +#define GICD_SIZE 0x1000 + +/* ************************************************************************** */ +/* PERIPHERAL ID DEFINITIONS FOR SAMA7G54 */ +/* ************************************************************************** */ +#define ID_DWDT_SW 0 /* Dual Watchdog Timer, Secure World (DWDT_SW) */ +#define ID_DWDT_NSW 1 /* DWDT Non Secure World, interrupt (DWDT_NSW) */ +#define ID_DWDT_NSW_ALARM 2 /* DWDT Non Secure World Alarm, interrupt */ +#define ID_SCKC 4 /* Slow Clock Controller (SCKC) */ +#define ID_SHDWC 5 /* SHutDoWn Controller (SHDWC) */ +#define ID_RSTC 6 /* Reset Controller (RSTC) */ +#define ID_RTC 7 /* Real-Time Clock (RTC) */ +#define ID_RTT 8 /* Real-Time Timer (RTT) */ +#define ID_CHIPID 9 /* Chip Identifier (CHIPID) */ +#define ID_PMC 10 /* Power Management Controller (PMC) */ +#define ID_PIOA 11 /* For PIO 0 to 31 (PIOA) */ +#define ID_PIOB 12 /* For PIO 32 to 63, interrupt (PIOB) */ +#define ID_PIOC 13 /* For PIO 64 to 95, interrupt (PIOC) */ +#define ID_PIOD 14 /* For PIO 96 to 127, interrupt (PIOD) */ +#define ID_PIOE 15 /* For PIO 128 to 136, interrupt (PIOE) */ +#define ID_SECUMOD 17 /* Security Module (SECUMOD) */ +#define ID_SECURAM 18 /* Secret RAM (SECURAM) */ +#define ID_SFR 19 /* Special Function Register (SFR) */ +#define ID_SFRBU 20 /* Special Function Register in BackUp zone */ +#define ID_HSMC 21 /* Static Memory Controller - NAND (HSMC) */ +#define ID_XDMAC0 22 /* DMA 0, mem to periph, 32 Channels (XDMAC0) */ +#define ID_XDMAC1 23 /* DMA 1, mem to periph, 32 Channels (XDMAC1) */ +#define ID_XDMAC2 24 /* DMA 2, mem to mem, 4 Channels (XDMAC2) */ +#define ID_ACC 25 /* Analog Comparator Controller (ACC) */ +#define ID_ADC 26 /* Analog-to-Digital Converter (ADC) */ +#define ID_AES 27 /* Advanced Encryption Standard (AES) */ +#define ID_TZAESBASC 28 /* TZ AES Bridge - Address Space Controlller */ +#define ID_ASRC 30 /* Asynchronous Sample Rate Converter (ASRC) */ +#define ID_CPKCC 32 /* Classic Public Key Cryptography Controller */ +#define ID_CSI 33 /* CSI 2 between ISC and MIPI PHY (CSI) */ +#define ID_CSI2DC 34 /* CSI to Demultiplexer Controller (CSI2DC) */ +#define ID_DDRPUBL 35 /* DDR SDRAM PHY Utility Block "Lite" aka PUBL */ +#define ID_DDRUMCTL 36 /* Universal DDR-SDRAM Memory Controller */ +#define ID_EIC 37 /* External Interrupt Controller (EIC) */ +#define ID_FLEXCOM0 38 /* Flexcom 0 (FLEXCOM0) */ +#define ID_FLEXCOM1 39 /* Flexcom 1 (FLEXCOM1) */ +#define ID_FLEXCOM2 40 /* Flexcom 2 (FLEXCOM2) */ +#define ID_FLEXCOM3 41 /* Flexcom 3 (FLEXCOM3) */ +#define ID_FLEXCOM4 42 /* Flexcom 4 (FLEXCOM4) */ +#define ID_FLEXCOM5 43 /* Flexcom 5 (FLEXCOM5) */ +#define ID_FLEXCOM6 44 /* Flexcom 6 (FLEXCOM6) */ +#define ID_FLEXCOM7 45 /* Flexcom 7 (FLEXCOM7) */ +#define ID_FLEXCOM8 46 /* Flexcom 8 (FLEXCOM8) */ +#define ID_FLEXCOM9 47 /* Flexcom 9 (FLEXCOM9) */ +#define ID_FLEXCOM10 48 /* Flexcom 10 (FLEXCOM10) */ +#define ID_FLEXCOM11 49 /* Flexcom 11 (FLEXCOM11) */ +#define ID_GMAC0 51 /* Gigabit Ethernet MAC (GMAC0) */ +#define ID_GMAC1 52 /* Ethernet MAC (GMAC1) */ +#define ID_GMAC0_TSU 53 /* GMAC - TSU Generic Clock - No Interrupt */ +#define ID_GMAC1_TSU 54 /* EMAC - TSU Generic Clock - No Interrupt */ +#define ID_ICM 55 /* Integrity Check Monitor (ICM) */ +#define ID_ISC 56 /* Camera Interface (ISC) */ +#define ID_I2SMCC0 57 /* Inter-IC Sound Controller 0 (I2SMCC0) */ +#define ID_I2SMCC1 58 /* Inter-IC Sound Controller 1 (I2SMCC1) */ +#define ID_MATRIX 60 /* HSS AHB Matrix (MATRIX) */ +#define ID_MCAN0 61 /* Master CAN 0 (MCAN0) */ +#define ID_MCAN1 62 /* Master CAN 1 (MCAN1) */ +#define ID_MCAN2 63 /* Master CAN 2 (MCAN2) */ +#define ID_MCAN3 64 /* Master CAN 3 (MCAN3) */ +#define ID_MCAN4 65 /* Master CAN 4 (MCAN4) */ +#define ID_MCAN5 66 /* Master CAN 5 (MCAN5) */ +#define ID_OTPC 67 /* One Time Programmable memory Controller */ +#define ID_PDMC0 68 /* Pulse Density Modulation Controller 0 */ +#define ID_PDMC1 69 /* Pulse Density Modulation Controller 1 */ +#define ID_PIT64B0 70 /* 64-bit Periodic Interval Timer 0 (PIT64B0) */ +#define ID_PIT64B1 71 /* 64-bit Periodic Interval Timer 1 (PIT64B1) */ +#define ID_PIT64B2 72 /* 64-bit Periodic Interval Timer 2 (PIT64B2) */ +#define ID_PIT64B3 73 /* 64-bit Periodic Interval Timer 3 (PIT64B3) */ +#define ID_PIT64B4 74 /* 64-bit Periodic Interval Timer 4 (PIT64B4) */ +#define ID_PIT64B5 75 /* 64-bit Periodic Interval Timer 5 (PIT64B5) */ +#define ID_PWM 77 /* Pulse Width Modulation (PWM) */ +#define ID_QSPI0 78 /* Quad IO Serial Peripheral Interface 0 */ +#define ID_QSPI1 79 /* Quad IO Serial Peripheral Interface 1 */ +#define ID_SDMMC0 80 /* Ultra HS SD Host controller 0 (eMMC 5.1) */ +#define ID_SDMMC1 81 /* Ultra HS SD Host controller 1 (eMMC 4.51) */ +#define ID_SDMMC2 82 /* Ultra HS SD Host controller 2 (eMMC 4.51) */ +#define ID_SHA 83 /* Secure Hash Algorithm (SHA) */ +#define ID_SPDIFRX 84 /* Sony Philips Digital Interface RX (SPDIFRX) */ +#define ID_SPDIFTX 85 /* Sony Philips Digital Interface TX (SPDIFTX) */ +#define ID_SSC0 86 /* Synchronous Serial Interface 0 (SSC0) */ +#define ID_SSC1 87 /* Synchronous Serial Interface 1 (SSC1) */ +#define ID_TC0_CHANNEL0 88 /* 32-bit Timer Counter 0 Channel 0 */ +#define ID_TC0_CHANNEL1 89 /* 32-bit Timer Counter 0 Channel 1 interrupt */ +#define ID_TC0_CHANNEL2 90 /* 32-bit Timer Counter 0 Channel 2 interrupt */ +#define ID_TC1_CHANNEL0 91 /* 32-bit Timer Counter 1 Channel 0 */ +#define ID_TC1_CHANNEL1 92 /* 32-bit Timer Counter 1 Channel 1 interrupt */ +#define ID_TC1_CHANNEL2 93 /* 32-bit Timer Counter 1 Channel 2 interrupt */ +#define ID_TCPCA 94 /* USB Type-C Port Controller A (TCPCA) */ +#define ID_TCPCB 95 /* USB Type-C Port Controller B (TCPCB) */ +#define ID_TDES 96 /* Triple Data Encryption System (TDES) */ +#define ID_TRNG 97 /* True Random Number Generator (TRNG) */ +#define ID_TZAESB_NS 98 /* TZAESB Non-Secure (Clocks & Interrupt) */ +#define ID_TZAESB_NS_SINT 99 /* TZAESB Non-Secure (Interrupt only) */ +#define ID_TZAESB_S 100 /* TZAESB Secure */ +#define ID_TZAESB_S_SINT 101 /* TZAESB Secure (Interrupt only) */ +#define ID_TZC 102 /* TrustZone Address Space Controller (TZC400) */ +#define ID_TZPM 103 /* TrustZone Peripheral Manager (TZPM) */ +#define ID_UDPHSA 104 /* USB Device High Speed A (UDPHSA) */ +#define ID_UDPHSB 105 /* USB Device High Speed B (UDPHSB) */ +#define ID_UHPHS 106 /* USB Host Controller High Speed (UHPHS) */ +#define ID_XDMAC0_SINT 112 /* DMA 0, mem to periph, 32 CH, Secure INT */ +#define ID_XDMAC1_SINT 113 /* DMA 1, mem to periph, 32 CH, Secure INT */ +#define ID_XDMAC2_SINT 114 /* DMA 2, mem to mem, 4 Channels, Secure INT */ +#define ID_AES_SINT 115 /* Advanced Encryption Standard, Secure INT */ +#define ID_GMAC0_Q1 116 /* GMAC0 Queue 1 */ +#define ID_GMAC0_Q2 117 /* GMAC0 Queue 2 */ +#define ID_GMAC0_Q3 118 /* GMAC0 Queue 3 */ +#define ID_GMAC0_Q4 119 /* GMAC0 Queue 4 */ +#define ID_GMAC0_Q5 120 /* GMAC0 Queue 5 */ +#define ID_GMAC1_Q1 121 /* GMAC1 Queue 1 */ +#define ID_ICM_SINT 122 /* Integrity Check Monitor, Secure INTerrupt */ +#define ID_MCAN0_INT1 123 /* MCAN0 interrupt1 (MCAN0_INT1) */ +#define ID_MCAN1_INT1 124 /* MCAN1 interrupt1 (MCAN1_INT1) */ +#define ID_MCAN2_INT1 125 /* MCAN2 interrupt1 (MCAN2_INT1) */ +#define ID_MCAN3_INT1 126 /* MCAN3 interrupt1 (MCAN3_INT1) */ +#define ID_MCAN4_INT1 127 /* MCAN4 interrupt1 (MCAN4_INT1) */ +#define ID_MCAN5_INT1 128 /* MCAN5 interrupt1 (MCAN5_INT1) */ +#define ID_PIOA_SINT 129 /* For PIO 0 to 31, Secure INTerrupt */ +#define ID_PIOB_SINT 130 /* For PIO 32 to 63, Secure INTerrupt */ +#define ID_PIOC_SINT 131 /* For PIO 64 to 95, Secure INTerrupt */ +#define ID_PIOD_SINT 132 /* For PIO 96 to 127, Secure INTerrupt */ +#define ID_PIOE_SINT 133 /* For PIO 128 to 136, Secure INTerrupt */ +#define ID_PIT64B0_SINT 135 /* 64-bit PIT 0, Secure INTerrupt */ +#define ID_PIT64B1_SINT 136 /* 64-bit PIT 1, Secure INTerrupt */ +#define ID_PIT64B2_SINT 137 /* 64-bit PIT 2, Secure INTerrupt */ +#define ID_PIT64B3_SINT 138 /* 64-bit PIT 3, Secure INTerrupt */ +#define ID_PIT64B4_SINT 139 /* 64-bit PIT 4, Secure INTerrupt */ +#define ID_PIT64B5_SINT 140 /* 64-bit PIT 5, Secure INTerrupt */ +#define ID_SDMMC0_TIMER 141 /* SD Host controller 0 (eMMC 5.1) Timer int */ +#define ID_SDMMC1_TIMER 142 /* SD Host controller 1 (eMMC 4.51) Timer int */ +#define ID_SDMMC2_TIMER 143 /* SD Host controller 2 (eMMC 4.51) Timer int */ +#define ID_SHA_SINT 144 /* Secure Hash Algorithm, Secure INTerrupt */ +#define ID_TC0_SINT0 145 /* 32-bit TC 0 Channel 0, Secure INTerrupt */ +#define ID_TC0_SINT1 146 /* 32-bit TC 0 Channel 1, Secure INTerrupt */ +#define ID_TC0_SINT2 147 /* 32-bit TC 0 Channel 2 (TC0_SINT2) */ +#define ID_TC1_SINT0 148 /* 32-bit TC 1 Channel 0, Secure INTerrupt */ +#define ID_TC1_SINT1 149 /* 32-bit TC 1 Channel 1, Secure INTerrupt */ +#define ID_TC1_SINT2 150 /* 32-bit TC 1 Channel 2, Secure INTerrupt */ +#define ID_TDES_SINT 151 /* Triple Data Encryption System, Secure INT */ +#define ID_TRNG_SINT 152 /* True Random Number Generator, Secure INT */ +#define ID_EXT_IRQ0 153 /* External Interrupt ID0 (FIQ) (EXT_IRQ0) */ +#define ID_EXT_IRQ1 154 /* External Interrupt ID1 (IRQ) (EXT_IRQ1) */ + +#define ID_PERIPH_MAX 154 /* Number of peripheral IDs */ + +/* ************************************************************************** */ +/* BASE ADDRESS DEFINITIONS FOR SAMA7G54 */ +/* ************************************************************************** */ +#define ACC_BASE_ADDRESS 0xe1600000 +#define ADC_BASE_ADDRESS 0xe1000000 +#define AES_BASE_ADDRESS 0xe1810000 +#define ASRC_BASE_ADDRESS 0xe1610000 +#define BSC_BASE_ADDRESS 0xe001d054 +#define CHIPID_BASE_ADDRESS 0xe0020000 +#define CSI_BASE_ADDRESS 0xe1400000 +#define CPKCC_BASE_ADDRESS 0xe000c000 +#define CSI2DC_BASE_ADDRESS 0xe1404000 +#define DDRPUBL_BASE_ADDRESS 0xe3804000 +#define DWDT_BASE_ADDRESS 0xe001c000 +#define EIC_BASE_ADDRESS 0xe1628000 +#define FLEXCOM0_BASE_ADDRESS 0xe1818000 +#define FLEXCOM1_BASE_ADDRESS 0xe181c000 +#define FLEXCOM2_BASE_ADDRESS 0xe1820000 +#define FLEXCOM3_BASE_ADDRESS 0xe1824000 +#define FLEXCOM4_BASE_ADDRESS 0xe2018000 +#define FLEXCOM5_BASE_ADDRESS 0xe201c000 +#define FLEXCOM6_BASE_ADDRESS 0xe2020000 +#define FLEXCOM7_BASE_ADDRESS 0xe2024000 +#define FLEXCOM8_BASE_ADDRESS 0xe2818000 +#define FLEXCOM9_BASE_ADDRESS 0xe281c000 +#define FLEXCOM10_BASE_ADDRESS 0xe2820000 +#define FLEXCOM11_BASE_ADDRESS 0xe2824000 +#define GMAC0_BASE_ADDRESS 0xe2800000 +#define GMAC1_BASE_ADDRESS 0xe2804000 +#define GPBR_BASE_ADDRESS 0xe001d060 +#define I2SMCC0_BASE_ADDRESS 0xe161c000 +#define I2SMCC1_BASE_ADDRESS 0xe1620000 +#define ICM_BASE_ADDRESS 0xe081c000 +#define ISC_BASE_ADDRESS 0xe1408000 +#define MATRIX_BASE_ADDRESS 0xe0804000 +#define MCAN0_BASE_ADDRESS 0xe0828000 +#define MCAN1_BASE_ADDRESS 0xe082c000 +#define MCAN2_BASE_ADDRESS 0xe0830000 +#define MCAN3_BASE_ADDRESS 0xe0834000 +#define MCAN4_BASE_ADDRESS 0xe0838000 +#define MCAN5_BASE_ADDRESS 0xe083c000 +#define NICGPV_BASE_ADDRESS 0xe8b00000 +#define OTPC_BASE_ADDRESS 0xe8c00000 +#define PDMC0_BASE_ADDRESS 0xe1608000 +#define PDMC1_BASE_ADDRESS 0xe160c000 +#define PIO_BASE_ADDRESS 0xe0014000 +#define PIT64B0_BASE_ADDRESS 0xe1800000 +#define PIT64B1_BASE_ADDRESS 0xe1804000 +#define PIT64B2_BASE_ADDRESS 0xe1808000 +#define PIT64B3_BASE_ADDRESS 0xe2004000 +#define PIT64B4_BASE_ADDRESS 0xe2008000 +#define PIT64B5_BASE_ADDRESS 0xe2810000 +#define PMC_BASE_ADDRESS 0xe0018000 +#define PWM_BASE_ADDRESS 0xe1604000 +#define QSPI0_BASE_ADDRESS 0xe080c000 +#define QSPI1_BASE_ADDRESS 0xe0810000 +#define RSTC_BASE_ADDRESS 0xe001d000 +#define RTC_BASE_ADDRESS 0xe001d0a8 +#define RTT_BASE_ADDRESS 0xe001d020 +#define SCKC_BASE_ADDRESS 0xe001d050 +#define SDMMC0_BASE_ADDRESS 0xe1204000 +#define SDMMC1_BASE_ADDRESS 0xe1208000 +#define SDMMC2_BASE_ADDRESS 0xe120c000 +#define SECUMOD_BASE_ADDRESS 0xe0004000 +#define SFR_BASE_ADDRESS 0xe1624000 +#define SFRBU_BASE_ADDRESS 0xe0008000 +#define SHA_BASE_ADDRESS 0xe1814000 +#define SHDWC_BASE_ADDRESS 0xe001d010 +#define HSMC_BASE_ADDRESS 0xe0808000 +#define SPDIFRX_BASE_ADDRESS 0xe1614000 +#define SPDIFTX_BASE_ADDRESS 0xe1618000 +#define SSC0_BASE_ADDRESS 0xe180c000 +#define SSC1_BASE_ADDRESS 0xe200c000 +#define SYSCWP_BASE_ADDRESS 0xe001d0dc +#define TC0_BASE_ADDRESS 0xe2814000 +#define TC1_BASE_ADDRESS 0xe0800000 +#define TCPCA_BASE_ADDRESS 0xe0840000 +#define TCPCB_BASE_ADDRESS 0xe0844000 +#define TDES_BASE_ADDRESS 0xe2014000 +#define TRNG_BASE_ADDRESS 0xe2010000 +#define TZAESBNS_BASE_ADDRESS 0xe0820000 +#define TZAESBS_BASE_ADDRESS 0xe0824000 +#define TZAESBASC_BASE_ADDRESS 0xe2000000 +#define TZC_BASE_ADDRESS 0xe3000000 +#define TZPM_BASE_ADDRESS 0xe0010000 +#define DDRUMCTL_BASE_ADDRESS 0xe3800000 +#define UDPHSA_BASE_ADDRESS 0xe0814000 +#define UDPHSB_BASE_ADDRESS 0xe0818000 +#define UHPHS_OHCI_BASE_ADDRESS 0x00400000 +#define UHPHS_EHCI_BASE_ADDRESS 0x00500000 +#define XDMAC0_BASE_ADDRESS 0xe2808000 +#define XDMAC1_BASE_ADDRESS 0xe280c000 +#define XDMAC2_BASE_ADDRESS 0xe1200000 + +/* ************************************************************************** */ +/* MEMORY MAPPING DEFINITIONS FOR SAMA7G54 */ +/* ************************************************************************** */ +#define IROM_SIZE 0x00014000 +#define ECC_ROM_SIZE 0x00018000 +#define CPKCC_ROM_SIZE 0x00010000 +#define CPKCC_RAM_SIZE 0x00001000 +#define IRAM_SIZE 0x00020000 +#define UDPHS_RAMA_SIZE 0x00100000 +#define UDPHS_RAMB_SIZE 0x00100000 +#define UHPHS_OHCI_SIZE 0x00001000 +#define UHPHS_EHCI_SIZE 0x00100000 +#define NFC_RAM_SIZE 0x00003000 +#define NFC_SIZE 0x08000000 +#define QSPIMEM0_SIZE 0x10000000 +#define QSPIMEM1_SIZE 0x10000000 +#define EBI_CS0_SIZE 0x08000000 +#define EBI_CS1_SIZE 0x08000000 +#define EBI_CS2_SIZE 0x08000000 +#define EBI_CS3_SIZE 0x08000000 +#define DDR_CS_SIZE 0x80000000 +#define SECURAM_SIZE 0x00004000 +#define SDMMC0_SIZE 0x00004000 +#define SDMMC1_SIZE 0x00004000 +#define SDMMC2_SIZE 0x00004000 +#define APB_DBG_S_SIZE 0x00060000 +#define APB_DBG_SIZE 0x00001000 +#define NICGPV_SIZE 0x00100000 +#define OTPC_SIZE 0x00001000 +#define CSI2DC_META_SIZE 0x00002000 +#define ARM_PERIPH_SIZE 0x00008000 +#define PERIPHERALS_SIZE 0x10000000 + +#define IROM_ADDR 0x00000000 +#define ECC_ROM_ADDR 0x00020000 +#define CPKCC_ROM_ADDR 0x00040000 +#define CPKCC_RAM_ADDR 0x00051000 +#define IRAM_ADDR 0x00100000 +#define UDPHS_RAMA_ADDR 0x00200000 +#define UDPHS_RAMB_ADDR 0x00300000 +#define UHPHS_OHCI_ADDR 0x00400000 +#define UHPHS_EHCI_ADDR 0x00500000 +#define NFC_RAM_ADDR 0x00600000 +#define NFC_ADDR 0x10000000 +#define QSPIMEM0_ADDR 0x20000000 +#define QSPIMEM1_ADDR 0x30000000 +#define EBI_CS0_ADDR 0x40000000 +#define EBI_CS1_ADDR 0x48000000 +#define EBI_CS2_ADDR 0x50000000 +#define EBI_CS3_ADDR 0x58000000 +#define DDR_CS_ADDR 0x60000000 +#define SECURAM_ADDR 0xe0000000 +#define SDMMC0_ADDR 0xe1204000 +#define SDMMC1_ADDR 0xe1208000 +#define SDMMC2_ADDR 0xe120c000 +#define APB_DBG_S_ADDR 0xe8800000 +#define APB_DBG_ADDR 0xe8900000 +#define NICGPV_ADDR 0xe8b00000 +#define OTPC_ADDR 0xe8c00000 +#define CSI2DC_META_ADDR 0xe8c02000 +#define ARM_PERIPH_ADDR 0xe8c10000 +#define PERIPHERALS_ADDR 0xe0000000 + +/* ************************************************************************** */ +/* DEVICE SIGNATURES FOR SAMA7G54 */ +/* ************************************************************************** */ +#define CHIP_JTAGID 0X05B4203F +#define CHIP_CIDR 0X80162110 +#define CHIP_EXID 0X00000000 + +#endif /* _SAMA7G54_H_ */ + diff --git a/optee/optee_os/core/arch/arm/plat-sam/scmi_server.c b/optee/optee_os/core/arch/arm/plat-sam/scmi_server.c new file mode 100644 index 0000000..8dd5ecc --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sam/scmi_server.c @@ -0,0 +1,1054 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019, STMicroelectronics + * Copyright (c) 2021, Microchip + */ + +#include +#include +#include +#include +#include +#include +#include + +static_assert(SMT_BUF_SLOT_SIZE <= CFG_SCMI_SHMEM_SIZE); + +register_phys_mem(MEM_AREA_IO_NSEC, CFG_SCMI_SHMEM_START, CFG_SCMI_SHMEM_SIZE); + +struct channel_resources { + struct scmi_msg_channel *channel; +}; + +static const struct channel_resources scmi_channel[] = { + [0] = { + .channel = &(struct scmi_msg_channel){ + .shm_addr = { .pa = CFG_SCMI_SHMEM_START }, + .shm_size = SMT_BUF_SLOT_SIZE, + }, + }, +}; + +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 const char vendor[] = "Microchip"; +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 only SCMI Base protocol */ +static const uint8_t plat_protocol_list[] = { + SCMI_PROTOCOL_ID_CLOCK, + 0 /* Null termination */ +}; + +size_t plat_scmi_protocol_count(void) +{ + return ARRAY_SIZE(plat_protocol_list) - 1; +} + +const uint8_t *plat_scmi_protocol_list(unsigned int channel_id __unused) +{ + return plat_protocol_list; +} + +struct sam_pmc_clk { + unsigned int scmi_id; + unsigned int pmc_type; + unsigned int pmc_id; +}; + +#ifdef CFG_SAMA7G5 +static const struct sam_pmc_clk pmc_clks[] = { + { + .scmi_id = AT91_SCMI_CLK_CORE_MCK, + .pmc_type = PMC_TYPE_CORE, + .pmc_id = PMC_MCK + }, + { + .scmi_id = AT91_SCMI_CLK_CORE_UTMI, + .pmc_type = PMC_TYPE_CORE, + .pmc_id = PMC_UTMI + }, + { + .scmi_id = AT91_SCMI_CLK_CORE_CPUPLLCK, + .pmc_type = PMC_TYPE_CORE, + .pmc_id = PMC_CPUPLL + }, + { + .scmi_id = AT91_SCMI_CLK_CORE_MAIN, + .pmc_type = PMC_TYPE_CORE, + .pmc_id = PMC_MAIN + }, + { + .scmi_id = AT91_SCMI_CLK_CORE_SYSPLLCK, + .pmc_type = PMC_TYPE_CORE, + .pmc_id = PMC_SYSPLL + }, + + { + .scmi_id = AT91_SCMI_CLK_CORE_AUDIOPLLCK, + .pmc_type = PMC_TYPE_CORE, + .pmc_id = PMC_AUDIOPMCPLL + }, + + { + .scmi_id = AT91_SCMI_CLK_CORE_MCK_PRES, + .pmc_type = PMC_TYPE_CORE, + .pmc_id = PMC_MCK_PRES + }, + { + .scmi_id = AT91_SCMI_CLK_CORE_DDRPLLCK, + .pmc_type = PMC_TYPE_CORE, + .pmc_id = PMC_DDRPLL + }, + { + .scmi_id = AT91_SCMI_CLK_CORE_IMGPLLCK, + .pmc_type = PMC_TYPE_CORE, + .pmc_id = PMC_IMGPLL + }, + { + .scmi_id = AT91_SCMI_CLK_CORE_ETHPLLCK, + .pmc_type = PMC_TYPE_CORE, + .pmc_id = PMC_ETHPLL + }, + { + .scmi_id = AT91_SCMI_CLK_UTMI1, + .pmc_type = PMC_TYPE_CORE, + .pmc_id = PMC_UTMI1 + }, + { + .scmi_id = AT91_SCMI_CLK_UTMI2, + .pmc_type = PMC_TYPE_CORE, + .pmc_id = PMC_UTMI2 + }, + { + .scmi_id = AT91_SCMI_CLK_UTMI3, + .pmc_type = PMC_TYPE_CORE, + .pmc_id = PMC_UTMI3 + }, + { + .scmi_id = AT91_SCMI_CLK_SYSTEM_PCK0, + .pmc_type = PMC_TYPE_SYSTEM, + .pmc_id = 8 + }, + { + .scmi_id = AT91_SCMI_CLK_SYSTEM_PCK1, + .pmc_type = PMC_TYPE_SYSTEM, + .pmc_id = 9 + }, + { + .scmi_id = AT91_SCMI_CLK_SYSTEM_PCK2, + .pmc_type = PMC_TYPE_SYSTEM, + .pmc_id = 10 + }, + { + .scmi_id = AT91_SCMI_CLK_SYSTEM_PCK3, + .pmc_type = PMC_TYPE_SYSTEM, + .pmc_id = 11 + }, + { + .scmi_id = AT91_SCMI_CLK_SYSTEM_PCK4, + .pmc_type = PMC_TYPE_SYSTEM, + .pmc_id = 12 + }, + { + .scmi_id = AT91_SCMI_CLK_SYSTEM_PCK5, + .pmc_type = PMC_TYPE_SYSTEM, + .pmc_id = 13 + }, + { + .scmi_id = AT91_SCMI_CLK_SYSTEM_PCK6, + .pmc_type = PMC_TYPE_SYSTEM, + .pmc_id = 14 + }, + { + .scmi_id = AT91_SCMI_CLK_SYSTEM_PCK7, + .pmc_type = PMC_TYPE_SYSTEM, + .pmc_id = 15 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_ASRC_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_ASRC + }, + { + .scmi_id = AT91_SCMI_CLK_GCK_ASRC_GCLK, + .pmc_type = PMC_TYPE_GCK, + .pmc_id = ID_ASRC + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_CSI_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_CSI + }, + { + .scmi_id = AT91_SCMI_CLK_GCK_CSI_GCLK, + .pmc_type = PMC_TYPE_GCK, + .pmc_id = ID_CSI + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_CSI2DC_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_CSI2DC + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_MACB0_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_GMAC0 + }, + { + .scmi_id = AT91_SCMI_CLK_GCK_MACB0_GCLK, + .pmc_type = PMC_TYPE_GCK, + .pmc_id = ID_GMAC0 + }, + { + .scmi_id = AT91_SCMI_CLK_GCK_MACB0_TSU, + .pmc_type = PMC_TYPE_GCK, + .pmc_id = ID_GMAC0_TSU + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_MACB1_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_GMAC1 + }, + { + .scmi_id = AT91_SCMI_CLK_GCK_MACB1_GCLK, + .pmc_type = PMC_TYPE_GCK, + .pmc_id = ID_GMAC1 + }, + { + .scmi_id = AT91_SCMI_CLK_GCK_MACB1_TSU, + .pmc_type = PMC_TYPE_GCK, + .pmc_id = ID_GMAC1_TSU + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_TDES_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_TDES + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_HSMC_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_HSMC + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_PIOA_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_PIOA + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_FLX0_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_FLEXCOM0 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_FLX1_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_FLEXCOM1 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_FLX2_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_FLEXCOM2 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_FLX3_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_FLEXCOM3 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_FLX4_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_FLEXCOM4 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_FLX5_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_FLEXCOM5 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_FLX6_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_FLEXCOM6 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_FLX7_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_FLEXCOM7 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_FLX8_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_FLEXCOM8 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_FLX9_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_FLEXCOM9 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_FLX10_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_FLEXCOM10 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_FLX11_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_FLEXCOM11 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_TCB0_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_TC0_CHANNEL0 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_TCB1_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_TC1_CHANNEL0 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_PWM_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_PWM + }, + { + .scmi_id = AT91_SCMI_CLK_GCK_ADC_GCLK, + .pmc_type = PMC_TYPE_GCK, + .pmc_id = ID_ADC + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_UHPHS_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_UHPHS + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_UDPHSA_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_UDPHSA + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_UDPHSB_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_UDPHSB + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_SSC0_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_SSC0 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_SSC1_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_SSC1 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_TRNG_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_TRNG + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_PDMC0_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_PDMC0 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_PDMC1_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_PDMC1 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_SECURAM_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_SECURAM + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_I2S0_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_I2SMCC0 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_I2S1_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_I2SMCC1 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_CAN0_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_MCAN0 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_CAN1_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_MCAN1 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_CAN2_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_MCAN2 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_CAN3_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_MCAN3 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_CAN4_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_MCAN4 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_CAN5_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_MCAN5 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_DMA0_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_XDMAC0 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_DMA1_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_XDMAC1 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_DMA2_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_XDMAC2 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_SPDIFRX_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_SPDIFRX + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_SPDIFTX_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_SPDIFTX + }, + { + .scmi_id = AT91_SCMI_CLK_GCK_SPDIFRX_GCLK, + .pmc_type = PMC_TYPE_GCK, + .pmc_id = ID_SPDIFRX + }, + { + .scmi_id = AT91_SCMI_CLK_GCK_SPDIFTX_GCLK, + .pmc_type = PMC_TYPE_GCK, + .pmc_id = ID_SPDIFTX + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_AES_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_AES + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_AESB_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_TZAESBASC + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_SHA_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_SHA + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_SDMMC0_HCLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_SDMMC0 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_SDMMC1_HCLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_SDMMC1 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_SDMMC2_HCLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_SDMMC2 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_ISC_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_ISC + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_QSPI0_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_QSPI0 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_QSPI1_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = ID_QSPI1 + }, + { + .scmi_id = AT91_SCMI_CLK_GCK_QSPI0_GCLK, + .pmc_type = PMC_TYPE_GCK, + .pmc_id = ID_QSPI0 + }, + { + .scmi_id = AT91_SCMI_CLK_GCK_QSPI1_GCLK, + .pmc_type = PMC_TYPE_GCK, + .pmc_id = ID_QSPI1 + }, + { + .scmi_id = AT91_SCMI_CLK_GCK_SDMMC0_GCLK, + .pmc_type = PMC_TYPE_GCK, + .pmc_id = ID_SDMMC0 + }, + { + .scmi_id = AT91_SCMI_CLK_GCK_SDMMC1_GCLK, + .pmc_type = PMC_TYPE_GCK, + .pmc_id = ID_SDMMC1 + }, + { + .scmi_id = AT91_SCMI_CLK_GCK_SDMMC2_GCLK, + .pmc_type = PMC_TYPE_GCK, + .pmc_id = ID_SDMMC2 + }, + { + .scmi_id = AT91_SCMI_CLK_GCK_TCB0_GCLK, + .pmc_type = PMC_TYPE_GCK, + .pmc_id = ID_TC0_CHANNEL0 + }, + { + .scmi_id = AT91_SCMI_CLK_GCK_TCB1_GCLK, + .pmc_type = PMC_TYPE_GCK, + .pmc_id = ID_TC1_CHANNEL0 + }, + { + .scmi_id = AT91_SCMI_CLK_GCK_I2S0_GCLK, + .pmc_type = PMC_TYPE_GCK, + .pmc_id = ID_I2SMCC0 + }, + { + .scmi_id = AT91_SCMI_CLK_GCK_I2S1_GCLK, + .pmc_type = PMC_TYPE_GCK, + .pmc_id = ID_I2SMCC1 + }, + { + .scmi_id = AT91_SCMI_CLK_GCK_CAN0_GCLK, + .pmc_type = PMC_TYPE_GCK, + .pmc_id = ID_MCAN0 + }, + { + .scmi_id = AT91_SCMI_CLK_GCK_CAN1_GCLK, + .pmc_type = PMC_TYPE_GCK, + .pmc_id = ID_MCAN1 + }, + { + .scmi_id = AT91_SCMI_CLK_GCK_CAN2_GCLK, + .pmc_type = PMC_TYPE_GCK, + .pmc_id = ID_MCAN2 + }, + { + .scmi_id = AT91_SCMI_CLK_GCK_CAN3_GCLK, + .pmc_type = PMC_TYPE_GCK, + .pmc_id = ID_MCAN3 + }, + { + .scmi_id = AT91_SCMI_CLK_GCK_CAN4_GCLK, + .pmc_type = PMC_TYPE_GCK, + .pmc_id = ID_MCAN4 + }, + { + .scmi_id = AT91_SCMI_CLK_GCK_CAN5_GCLK, + .pmc_type = PMC_TYPE_GCK, + .pmc_id = ID_MCAN5 + }, +}; +#else +static const struct sam_pmc_clk pmc_clks[] = { + { + .scmi_id = AT91_SCMI_CLK_CORE_MCK, + .pmc_type = PMC_TYPE_CORE, + .pmc_id = PMC_MCK + }, + { + .scmi_id = AT91_SCMI_CLK_CORE_UTMI, + .pmc_type = PMC_TYPE_CORE, + .pmc_id = PMC_UTMI + }, + { + .scmi_id = AT91_SCMI_CLK_CORE_MAIN, + .pmc_type = PMC_TYPE_CORE, + .pmc_id = PMC_MAIN + }, + { + .scmi_id = AT91_SCMI_CLK_CORE_MCK2, + .pmc_type = PMC_TYPE_CORE, + .pmc_id = PMC_MCK2 + }, + { + .scmi_id = AT91_SCMI_CLK_CORE_I2S0_MUX, + .pmc_type = PMC_TYPE_CORE, + .pmc_id = PMC_I2S0_MUX + }, + { + .scmi_id = AT91_SCMI_CLK_CORE_I2S1_MUX, + .pmc_type = PMC_TYPE_CORE, + .pmc_id = PMC_I2S1_MUX + }, + { + .scmi_id = AT91_SCMI_CLK_CORE_PLLACK, + .pmc_type = PMC_TYPE_CORE, + .pmc_id = PMC_PLLACK + }, + { + .scmi_id = AT91_SCMI_CLK_CORE_AUDIOPLLCK, + .pmc_type = PMC_TYPE_CORE, + .pmc_id = PMC_AUDIOPLLCK + }, + { + .scmi_id = AT91_SCMI_CLK_CORE_MCK_PRES, + .pmc_type = PMC_TYPE_CORE, + .pmc_id = PMC_MCK_PRES + }, + { + .scmi_id = AT91_SCMI_CLK_SYSTEM_DDRCK, + .pmc_type = PMC_TYPE_SYSTEM, + .pmc_id = 2 + }, + { + .scmi_id = AT91_SCMI_CLK_SYSTEM_LCDCK, + .pmc_type = PMC_TYPE_SYSTEM, + .pmc_id = 3 + }, + { + .scmi_id = AT91_SCMI_CLK_SYSTEM_UHPCK, + .pmc_type = PMC_TYPE_SYSTEM, + .pmc_id = 6 + }, + { + .scmi_id = AT91_SCMI_CLK_SYSTEM_UDPCK, + .pmc_type = PMC_TYPE_SYSTEM, + .pmc_id = 7 + }, + { + .scmi_id = AT91_SCMI_CLK_SYSTEM_PCK0, + .pmc_type = PMC_TYPE_SYSTEM, + .pmc_id = 8 + }, + { + .scmi_id = AT91_SCMI_CLK_SYSTEM_PCK1, + .pmc_type = PMC_TYPE_SYSTEM, + .pmc_id = 9 + }, + { + .scmi_id = AT91_SCMI_CLK_SYSTEM_PCK2, + .pmc_type = PMC_TYPE_SYSTEM, + .pmc_id = 10 + }, + { + .scmi_id = AT91_SCMI_CLK_SYSTEM_ISCCK, + .pmc_type = PMC_TYPE_SYSTEM, + .pmc_id = 18 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_MACB0_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 5 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_TDES_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 11 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_MATRIX1_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 14 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_HSMC_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 17 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_PIOA_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 18 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_FLX0_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 19 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_FLX1_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 20 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_FLX2_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 21 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_FLX3_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 22 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_FLX4_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 23 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_UART0_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 24 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_UART1_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 25 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_UART2_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 26 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_UART3_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 27 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_UART4_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 28 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_TWI0_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 29 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_TWI1_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 30 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_SPI0_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 33 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_SPI1_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 34 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_TCB0_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 35 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_TCB1_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 36 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_PWM_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 38 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_ADC_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 40 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_UHPHS_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 41 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_UDPHS_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 42 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_SSC0_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 43 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_SSC1_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 44 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_TRNG_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 47 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_PDMIC_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 48 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_SECURAM_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 51 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_I2S0_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 54 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_I2S1_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 55 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_CAN0_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 56 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_CAN1_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 57 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_PTC_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 58 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_CLASSD_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 59 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_DMA0_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 6 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_DMA1_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 7 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_AES_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 9 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_AESB_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 10 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_SHA_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 12 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_MPDDR_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 13 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_MATRIX0_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 15 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_SDMMC0_HCLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 31 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_SDMMC1_HCLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 32 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_LCDC_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 45 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_ISC_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 46 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_QSPI0_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 52 + }, + { + .scmi_id = AT91_SCMI_CLK_PERIPH_QSPI1_CLK, + .pmc_type = PMC_TYPE_PERIPHERAL, + .pmc_id = 53 + }, + { + .scmi_id = AT91_SCMI_CLK_GCK_SDMMC0_GCLK, + .pmc_type = PMC_TYPE_GCK, + .pmc_id = 31 + }, + { + .scmi_id = AT91_SCMI_CLK_GCK_SDMMC1_GCLK, + .pmc_type = PMC_TYPE_GCK, + .pmc_id = 32 + }, + { + .scmi_id = AT91_SCMI_CLK_GCK_TCB0_GCLK, + .pmc_type = PMC_TYPE_GCK, + .pmc_id = 35 + }, + { + .scmi_id = AT91_SCMI_CLK_GCK_TCB1_GCLK, + .pmc_type = PMC_TYPE_GCK, + .pmc_id = 36 + }, + { + .scmi_id = AT91_SCMI_CLK_GCK_PWM_GCLK, + .pmc_type = PMC_TYPE_GCK, + .pmc_id = 38 + }, + { + .scmi_id = AT91_SCMI_CLK_GCK_ISC_GCLK, + .pmc_type = PMC_TYPE_GCK, + .pmc_id = 46 + }, + { + .scmi_id = AT91_SCMI_CLK_GCK_PDMIC_GCLK, + .pmc_type = PMC_TYPE_GCK, + .pmc_id = 48 + }, + { + .scmi_id = AT91_SCMI_CLK_GCK_I2S0_GCLK, + .pmc_type = PMC_TYPE_GCK, + .pmc_id = 54 + }, + { + .scmi_id = AT91_SCMI_CLK_GCK_I2S1_GCLK, + .pmc_type = PMC_TYPE_GCK, + .pmc_id = 55 + }, + { + .scmi_id = AT91_SCMI_CLK_GCK_CAN0_GCLK, + .pmc_type = PMC_TYPE_GCK, + .pmc_id = 56 + }, + { + .scmi_id = AT91_SCMI_CLK_GCK_CAN1_GCLK, + .pmc_type = PMC_TYPE_GCK, + .pmc_id = 57 + }, + { + .scmi_id = AT91_SCMI_CLK_GCK_CLASSD_GCLK, + .pmc_type = PMC_TYPE_GCK, + .pmc_id = 59 + }, + { + .scmi_id = AT91_SCMI_CLK_PROG_PROG0, + .pmc_type = PMC_TYPE_PROGRAMMABLE, + .pmc_id = 0 + }, + { + .scmi_id = AT91_SCMI_CLK_PROG_PROG1, + .pmc_type = PMC_TYPE_PROGRAMMABLE, + .pmc_id = 1 + }, + { + .scmi_id = AT91_SCMI_CLK_PROG_PROG2, + .pmc_type = PMC_TYPE_PROGRAMMABLE, + .pmc_id = 2 + }, +}; +#endif + +static TEE_Result sam_init_scmi_clk(void) +{ + unsigned int i = 0; + struct clk *clk = NULL; + TEE_Result res = TEE_ERROR_GENERIC; + const struct sam_pmc_clk *pmc_clk = NULL; + + for (i = 0; i < ARRAY_SIZE(pmc_clks); i++) { + pmc_clk = &pmc_clks[i]; + res = at91_pmc_clk_get(pmc_clk->pmc_type, pmc_clk->pmc_id, + &clk); + if (res) { + EMSG("Failed to get PMC clock type %u, id %u", + pmc_clk->pmc_type, pmc_clk->pmc_id); + return res; + } + res = scmi_clk_add(clk, 0, pmc_clk->scmi_id); + if (res) { + EMSG("Failed to add PMC SCMI clock id %u", + pmc_clk->scmi_id); + return res; + } + } + + clk = at91_sckc_clk_get(); + if (!clk) + return TEE_ERROR_GENERIC; + + res = scmi_clk_add(clk, 0, AT91_SCMI_CLK_SCKC_SLOWCK_32K); + if (res) { + EMSG("Failed to add slow clock to SCMI clocks"); + return res; + } + + return TEE_SUCCESS; +} + +/* + * Initialize platform SCMI resources + */ +static TEE_Result sam_init_scmi_server(void) +{ + size_t i = 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); + } + + return sam_init_scmi_clk(); +} + +driver_init_late(sam_init_scmi_server); 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..2ec74d3 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sam/sub.mk @@ -0,0 +1,10 @@ +global-incdirs-y += . +srcs-y += freq.c sam_sfr.c +srcs-$(CFG_SAMA5D2) += platform_sama5d2.c +srcs-$(CFG_SAMA7G5) += platform_sama7g5.c +srcs-$(CFG_AT91_MATRIX) += matrix.c +srcs-$(CFG_PL310) += sam_pl310.c +srcs-$(CFG_SCMI_MSG_DRIVERS) += scmi_server.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..eb765ff --- /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 plat_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..a8e0a12 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sprd/main.c @@ -0,0 +1,52 @@ +// 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 + +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); + +void boot_primary_init_intc(void) +{ + gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET); +} + 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..45e25dc --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm/main.c @@ -0,0 +1,143 @@ +// 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 + +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 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 plat_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 boot_primary_init_intc(void) +{ + gic_init(GIC_CPU_BASE, GIC_DIST_BASE); +} + +void boot_secondary_init_intc(void) +{ + gic_init_per_cpu(); +} 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..870ddf9 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/conf.mk @@ -0,0 +1,413 @@ +# 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-157A_DK1_SCMI = stm32mp157a-dk1-scmi.dts +flavor_dts_file-157C_DK2_SCMI = stm32mp157c-dk2-scmi.dts +flavor_dts_file-157C_ED1_SCMI = stm32mp157c-ed1-scmi.dts +flavor_dts_file-157C_EV1_SCMI = stm32mp157c-ev1-scmi.dts + +flavor_dts_file-135F_DK = stm32mp135f-dk.dts + +flavorlist-cryp-512M = $(flavor_dts_file-157C_DK2) \ + $(flavor_dts_file-157C_DK2_SCMI) \ + $(flavor_dts_file-135F_DK) + +flavorlist-no_cryp-512M = $(flavor_dts_file-157A_DK1) \ + $(flavor_dts_file-157A_DK1_SCMI) + +flavorlist-cryp-1G = $(flavor_dts_file-157C_DHCOM_PDK2) \ + $(flavor_dts_file-157C_ED1) \ + $(flavor_dts_file-157C_EV1) \ + $(flavor_dts_file-157C_ED1_SCMI) \ + $(flavor_dts_file-157C_EV1_SCMI) + +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) \ + $(flavor_dts_file-157A_DK1_SCMI) \ + $(flavor_dts_file-157C_DK2_SCMI) \ + $(flavor_dts_file-157C_ED1_SCMI) \ + $(flavor_dts_file-157C_EV1_SCMI) + +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) \ + $(flavor_dts_file-157A_DK1_SCMI) \ + $(flavor_dts_file-157C_DK2_SCMI) \ + $(flavor_dts_file-157C_ED1_SCMI) \ + $(flavor_dts_file-157C_EV1_SCMI) + +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) +$(call force,CFG_STM32_SAES,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_DRIVERS_GPIO,y) +$(call force,CFG_DRIVERS_PINCTRL,y) +$(call force,CFG_DRIVERS_REGULATOR,y) +$(call force,CFG_GIC,y) +$(call force,CFG_INIT_CNTVOFF,y) +$(call force,CFG_PSCI_ARM32,y) +$(call force,CFG_REGULATOR_FIXED,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_ASYNC_NOTIF,y) +$(call force,CFG_CORE_ASYNC_NOTIF_GIC_INTID,31) +$(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_STM32_VREFBUF,y) +$(call force,CFG_STM32MP_CLK_CORE,y) +$(call force,CFG_STM32MP1_SHARED_RESOURCES,n) +$(call force,CFG_STM32MP13_CLK,y) +$(call force,CFG_STM32MP13_REGULATOR_IOD,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_HALT_CORES_ON_PANIC_SGI,15) +$(call force,CFG_SECONDARY_INIT_CNTFRQ,y) +$(call force,CFG_STM32MP1_SHARED_RESOURCES,y) +$(call force,CFG_STM32_SAES,n) +$(call force,CFG_STM32MP15_CLK,y) +CFG_CORE_RESERVED_SHM ?= n +CFG_HALT_CORES_ON_PANIC ?= 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 + +CFG_STM32MP_REMOTEPROC ?= n +CFG_DRIVERS_REMOTEPROC ?= $(CFG_STM32MP_REMOTEPROC) +CFG_REMOTEPROC_PTA ?= $(CFG_STM32MP_REMOTEPROC) +ifeq ($(CFG_REMOTEPROC_PTA),y) +# Remoteproc early TA for coprocessor firmware management in boot stages +CFG_IN_TREE_EARLY_TAS += remoteproc/80a4c275-0a47-4905-8285-1486a9771a08 +# Embed public part of this key in OP-TEE OS +RPROC_SIGN_KEY ?= keys/default.pem +endif + +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 and CFG_STM32MP1_SCMI_SHM_SIZE define the +# device memory mapped SRAM used for SCMI message transfers. +# When CFG_STM32MP1_SCMI_SHM_BASE is set to 0, the platform uses OP-TEE +# native shared memory for SCMI communication instead of SRAM. +# +# When CFG_STM32MP1_SCMI_SHM_SYSRAM is enabled, OP-TEE uses the +# last 4KB page of SYSRAM as SCMI shared memory. The switch is default +# disabled. +CFG_STM32MP1_SCMI_SHM_SYSRAM ?= n +ifeq ($(CFG_STM32MP1_SCMI_SHM_SYSRAM),y) +$(call force,CFG_STM32MP1_SCMI_SHM_BASE,0x2ffff000) +else +CFG_STM32MP1_SCMI_SHM_BASE ?= 0 +endif +$(call force,CFG_STM32MP1_SCMI_SHM_SIZE,0x1000) + +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_SAES ?= y +CFG_STM32_TAMP ?= y +CFG_STM32_UART ?= y +CFG_STPMIC1 ?= y +CFG_TZC400 ?= y + +CFG_DRIVERS_I2C ?= $(CFG_STM32_I2C) +CFG_REGULATOR_GPIO ?= $(CFG_STM32_GPIO) + +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 CFG_STM32_SAES),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) +CFG_WDT_SM_HANDLER ?= $(CFG_WDT) +CFG_WDT_SM_HANDLER_ID ?= 0xbc000000 + +# 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) +CFG_SCMI_MSG_SMT_THREAD_ENTRY ?= y +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 + +# Default enable software fallback on crypto drivers +CFG_STM32_SAES_SW_FALLBACK ?= 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..42735b8 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c @@ -0,0 +1,797 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2017-2023, STMicroelectronics + */ + +#include +#include +#include +#include +#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 + +enum { + PMIC_REGU_FLAG_MASK_RESET = 0, + PMIC_REGU_FLAG_COUNT +}; + +static_assert(IS_ENABLED(CFG_DRIVERS_REGULATOR)); +static_assert(PMIC_REGU_FLAG_COUNT <= UINT_MAX); + +/* + * struct pmic_regulator_data - Platform specific data + * @flags: Flags for platform property to apply + * @regu_name: Regulator name ID in stpmic1 driver + * @voltages_desc: Supported levels description + * @voltages_level: Pointer to supported levels or NULL if not yet allocated + */ +struct pmic_regulator_data { + unsigned int flags; + char *regu_name; + struct regulator_voltages_desc voltages_desc; + int *voltages_level; +}; + +/* Expect a single PMIC instance */ +static struct i2c_handle_s *i2c_handle; +static uint32_t pmic_i2c_addr; +static int pmic_status = -1; + +/* CPU voltage supplier if found */ +static char cpu_supply_name[PMIC_REGU_SUPPLY_NAME_LEN]; + +bool stm32mp_with_pmic(void) +{ + return pmic_status > 0; +} + +static void init_pmic_state(const void *fdt, int pmic_node) +{ + pmic_status = fdt_get_status(fdt, pmic_node); +} + +static bool dt_pmic_is_secure(void) +{ + return stm32mp_with_pmic() && + i2c_handle->dt_status == DT_STATUS_OK_SEC; +} + +static void priv_dt_properties(const void *fdt, int regu_node, + struct pmic_regulator_data *priv) +{ + const char *name = fdt_get_name(fdt, regu_node, NULL); + + assert(name); + priv->regu_name = strdup(name); + if (!priv->regu_name) + panic(); + + if (fdt_getprop(fdt, regu_node, "st,mask-reset", NULL)) + priv->flags |= PMIC_REGU_FLAG_MASK_RESET; +} + +/* + * @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(const 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 TEE_Result pmic_set_state(struct regulator *regulator, bool enable) +{ + struct pmic_regulator_data *priv = regulator->priv; + int ret = 0; + + stm32mp_get_pmic(); + + if (enable) + ret = stpmic1_regulator_enable(priv->regu_name); + else + ret = stpmic1_regulator_disable(priv->regu_name); + + stm32mp_put_pmic(); + + if (ret) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +static TEE_Result pmic_get_state(struct regulator *regulator, bool *enabled) +{ + struct pmic_regulator_data *priv = regulator->priv; + + stm32mp_get_pmic(); + *enabled = stpmic1_is_regulator_enabled(priv->regu_name); + stm32mp_put_pmic(); + + return TEE_SUCCESS; +} + +static TEE_Result pmic_get_voltage(struct regulator *regulator, int *level_uv) +{ + struct pmic_regulator_data *priv = regulator->priv; + int rc = 0; + + stm32mp_get_pmic(); + rc = stpmic1_regulator_voltage_get(priv->regu_name); + stm32mp_put_pmic(); + + if (rc < 0) + return TEE_ERROR_GENERIC; + + *level_uv = rc * 1000; + + return TEE_SUCCESS; +} + +static TEE_Result pmic_set_voltage(struct regulator *regulator, int level_uv) +{ + struct pmic_regulator_data *priv = regulator->priv; + unsigned int level_mv = level_uv / 1000; + int rc = 0; + + if (level_mv > UINT16_MAX) + return TEE_ERROR_BAD_PARAMETERS; + + stm32mp_get_pmic(); + rc = stpmic1_regulator_voltage_set(priv->regu_name, level_mv); + stm32mp_put_pmic(); + + if (rc) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +static int cmp_int_value(const void *a, const void *b) +{ + const int *ia = a; + const int *ib = b; + + return CMP_TRILEAN(*ia, *ib); +} + +static size_t refine_levels_array(size_t count, int *levels_uv, + int min_uv, int max_uv) +{ + size_t n = 0; + size_t m = 0; + + /* We need to sort the array has STPMIC1 driver does not */ + qsort(levels_uv, count, sizeof(*levels_uv), cmp_int_value); + + /* Remove duplicates and return optimized count */ + for (n = 1; n < count; n++) { + if (levels_uv[m] != levels_uv[n]) { + if (m + 1 != n) + levels_uv[m + 1] = levels_uv[n]; + m++; + } + } + count = m + 1; + + for (n = count; n; n--) + if (levels_uv[n - 1] <= max_uv) + break; + count = n; + + for (n = 0; n < count; n++) + if (levels_uv[n] >= min_uv) + break; + count -= n; + + memmove(levels_uv, levels_uv + n, count * sizeof(*levels_uv)); + + return count; +} + +static TEE_Result pmic_list_voltages(struct regulator *regulator, + struct regulator_voltages_desc **out_desc, + const int **out_levels) +{ + struct pmic_regulator_data *priv = regulator->priv; + + if (!priv->voltages_level) { + const uint16_t *level_ref = NULL; + size_t level_count = 0; + int *levels2 = NULL; + int *levels = NULL; + size_t n = 0; + + /* + * Allocate and build a consised and ordered voltage list + * based on the voltage list provided by stpmic1 driver. + */ + stpmic1_regulator_levels_mv(priv->regu_name, &level_ref, + &level_count); + + levels = calloc(level_count, sizeof(*levels)); + if (!levels) + return TEE_ERROR_OUT_OF_MEMORY; + for (n = 0; n < level_count; n++) + levels[n] = level_ref[n] * 1000; + + level_count = refine_levels_array(level_count, levels, + regulator->min_uv, + regulator->max_uv); + + /* Shrink levels array to not waste heap memory */ + levels2 = realloc(levels, sizeof(*levels) * level_count); + if (!levels2) { + free(levels); + return TEE_ERROR_OUT_OF_MEMORY; + } + + priv->voltages_desc.type = VOLTAGE_TYPE_FULL_LIST; + priv->voltages_desc.num_levels = level_count; + priv->voltages_level = levels2; + } + + *out_desc = &priv->voltages_desc; + *out_levels = priv->voltages_level; + + return TEE_SUCCESS; +} + +static TEE_Result pmic_regu_init(struct regulator *regulator, + const void *fdt __unused, int node __unused) +{ + struct pmic_regulator_data *priv = regulator->priv; + struct stpmic1_bo_cfg cfg = { }; + + if (!priv->flags) + return TEE_SUCCESS; + + stm32mp_get_pmic(); + + if (priv->flags & PMIC_REGU_FLAG_MASK_RESET) { + if (stpmic1_bo_mask_reset_cfg(priv->regu_name, &cfg) || + stpmic1_bo_mask_reset_unpg(&cfg)) { + EMSG("Mask reset failed for %s", priv->regu_name); + return TEE_ERROR_GENERIC; + } + } + + if (regulator->flags & REGULATOR_PULL_DOWN) { + if (stpmic1_bo_pull_down_cfg(priv->regu_name, &cfg) || + stpmic1_bo_pull_down_unpg(&cfg)) { + EMSG("Pull down failed for %s", priv->regu_name); + return TEE_ERROR_GENERIC; + } + } + + stm32mp_put_pmic(); + + return TEE_SUCCESS; +} + +static const struct regulator_ops pmic_regu_ops = { + .set_state = pmic_set_state, + .get_state = pmic_get_state, + .set_voltage = pmic_set_voltage, + .get_voltage = pmic_get_voltage, + .supported_voltages = pmic_list_voltages, + .supplied_init = pmic_regu_init, +}; +DECLARE_KEEP_PAGER(pmic_regu_ops); + +static const struct regulator_ops pmic_sw_ops = { + .set_state = pmic_set_state, + .get_state = pmic_get_state, + .supplied_init = pmic_regu_init, +}; +DECLARE_KEEP_PAGER(pmic_sw_ops); + +/* + * STPMIC1 regulator names, used in the DT as regulator node name and + * provider node -supply property, + */ +static const char * const pmic_regu_name_ids[] = { + "buck1", "buck2", "buck3", "buck4", + "ldo1", "ldo2", "ldo3", "ldo4", "ldo5", "ldo6", + "vref_ddr", "boost", "pwr_sw1", "pwr_sw2" +}; + +/* Preallocated regulator instances */ +static struct regulator pmic_regulators[ARRAY_SIZE(pmic_regu_name_ids)]; +static struct pmic_regulator_data pmic_regu_cfg[ARRAY_SIZE(pmic_regu_name_ids)]; + +static TEE_Result release_voltage_lists(void) +{ + size_t n = 0; + + /* Voltage list will be rebuilt at runtime if needed at least once */ + for (n = 0; n < ARRAY_SIZE(pmic_regulators); n++) { + struct pmic_regulator_data *priv = pmic_regulators[n].priv; + + if (priv && priv->voltages_level) + free(priv->voltages_level); + } + + return TEE_SUCCESS; +} + +release_init_resource(release_voltage_lists); + +struct regulator *stm32mp_pmic_get_regulator(const char *name) +{ + size_t i = 0; + + if (!name) + return NULL; + + for (i = 0; i < ARRAY_SIZE(pmic_regu_name_ids); i++) + if (!strcmp(pmic_regu_name_ids[i], name) && + pmic_regulators[i].ops) + return pmic_regulators + i; + + return NULL; +} + +static TEE_Result register_pmic_regulator(const void *fdt, + const char *regu_name, int regu_node, + int regulators_node) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct regu_dt_desc desc = { }; + size_t i = 0; + + for (i = 0; i < ARRAY_SIZE(pmic_regu_name_ids); i++) + if (!strcmp(pmic_regu_name_ids[i], regu_name)) + break; + if (i >= ARRAY_SIZE(pmic_regu_name_ids)) { + EMSG("Unknown regulator name %s", regu_name); + panic(); + } + + desc = (struct regu_dt_desc){ + .name = pmic_regu_name_ids[i], + .supply_name = pmic_regu_name_ids[i], + .regulator = pmic_regulators + i, + .priv = pmic_regu_cfg + i, + }; + + priv_dt_properties(fdt, regu_node, pmic_regu_cfg + i); + + /* + * pwr_sw1 and pwr_sw2 are regulator switches hence have no + * set_voltage.get_voltage handler. + */ + if (!strncmp(regu_name, "pwr_sw", 6)) + desc.ops = &pmic_sw_ops; + else + desc.ops = &pmic_regu_ops; + + res = regulator_dt_register(fdt, regu_node, regulators_node, &desc); + if (res) + EMSG("Failed to register %s, error: %#"PRIx32, regu_name, res); + + return res; +} + +static void parse_regulator_fdt_nodes(const void *fdt, int pmic_node) +{ + int regulators_node = 0; + int regu_node = 0; + + 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; + + assert(status >= 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); + + 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 (register_pmic_regulator(fdt, regu_name, regu_node, + regulators_node)) + panic(); + } + + if (save_cpu_supply_name()) + DMSG("No CPU supply provided"); +} + +/* + * PMIC and resource initialization + */ + +static void initialize_pmic_i2c(const void *fdt, int pmic_node) +{ + const fdt32_t *cuint = NULL; + + cuint = fdt_getprop(fdt, pmic_node, "reg", NULL); + if (!cuint) { + EMSG("PMIC configuration failed on reg property"); + panic(); + } + + pmic_i2c_addr = fdt32_to_cpu(*cuint) << 1; + if (pmic_i2c_addr > UINT16_MAX) { + EMSG("PMIC configuration failed on i2c address translation"); + panic(); + } + + stm32mp_get_pmic(); + + if (!stm32_i2c_is_device_ready(i2c_handle, pmic_i2c_addr, + PMIC_I2C_TRIALS, + PMIC_I2C_TIMEOUT_BUSY_MS)) + panic(); + + stpmic1_bind_i2c(i2c_handle, pmic_i2c_addr); + + stm32mp_put_pmic(); +} + +/* + * 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) +{ + /* Allow this function to be called when STPMIC1 not used */ + if (!i2c_handle->base.pa) + return; + + stm32mp_register_non_secure_pinctrl(i2c_handle->pinctrl); + if (i2c_handle->pinctrl_sleep) + stm32mp_register_non_secure_pinctrl(i2c_handle->pinctrl_sleep); + + stm32mp_register_non_secure_periph_iomem(i2c_handle->base.pa); +} + +static void register_secure_pmic(void) +{ + stm32mp_register_secure_pinctrl(i2c_handle->pinctrl); + if (i2c_handle->pinctrl_sleep) + stm32mp_register_secure_pinctrl(i2c_handle->pinctrl_sleep); + + stm32mp_register_secure_periph_iomem(i2c_handle->base.pa); + register_pm_driver_cb(pmic_pm, NULL, "stm32mp1-pmic"); +} + +static TEE_Result initialize_pmic(const void *fdt, int pmic_node) +{ + unsigned long pmic_version = 0; + + init_pmic_state(fdt, pmic_node); + + initialize_pmic_i2c(fdt, pmic_node); + + stm32mp_get_pmic(); + + if (stpmic1_get_version(&pmic_version)) + panic("Failed to access PMIC"); + + DMSG("PMIC version = 0x%02lx", pmic_version); + stm32mp_put_pmic(); + + if (dt_pmic_is_secure()) + register_secure_pmic(); + else + register_non_secure_pmic(); + + parse_regulator_fdt_nodes(fdt, pmic_node); + + return TEE_SUCCESS; +} + +static TEE_Result stm32_pmic_probe(const void *fdt, int node, + const void *compat_data __unused) +{ + struct stm32_i2c_dev *stm32_i2c_dev = NULL; + struct i2c_dev *i2c_dev = NULL; + TEE_Result res = TEE_SUCCESS; + + res = i2c_dt_get_dev(fdt, node, &i2c_dev); + if (res) + return res; + + stm32_i2c_dev = container_of(i2c_dev, struct stm32_i2c_dev, i2c_dev); + i2c_handle = stm32_i2c_dev->handle; + + res = initialize_pmic(fdt, node); + if (res) { + DMSG("Unexpectedly failed to get I2C bus: %#"PRIx32, res); + panic(); + } + + return TEE_SUCCESS; +} + +static const struct dt_device_match stm32_pmic_match_table[] = { + { .compatible = "st,stpmic1" }, + { } +}; + +DEFINE_DT_DRIVER(stm32_pmic_dt_driver) = { + .name = "st,stpmic1", + .match_table = stm32_pmic_match_table, + .probe = stm32_pmic_probe, +}; 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..73794e3 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.h @@ -0,0 +1,51 @@ +/* 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); +const char *stm32mp_pmic_get_cpu_supply_name(void); + +/* Get the PMIC regulator related to @name or NULL if not found */ +struct regulator *stm32mp_pmic_get_regulator(const char *name); +#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 const char *stm32mp_pmic_get_cpu_supply_name(void) +{ + return NULL; +} + +static inline struct regulator * +stm32mp_pmic_get_regulator(const char *name __unused) +{ + 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..e06e2a2 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.c @@ -0,0 +1,291 @@ +// 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 + +#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) + +#define TIMEOUT_US_10MS U(10000) + +#define VOLTAGE_2V7_THREDSHOLD_UV 2700000 + +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) { + uint32_t ready_mask = pwr_regulators[id].cr3_ready_mask; + uint64_t to = 0; + + io_setbits32(cr3, enable_mask); + + to = timeout_init_us(10 * 1000); + 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; +} + +static TEE_Result stm32mp1_pwr_regu_set_state(struct regulator *regu, + bool enable) +{ + const struct pwr_regu_desc *desc = regu->priv; + uintptr_t cr3 = stm32_pwr_base() + PWR_CR3_OFF; + + assert(desc); + + if (enable) { + uint32_t value = 0; + + io_setbits32_stm32shregs(cr3, desc->cr3_enable_mask); + + if (IO_READ32_POLL_TIMEOUT(cr3, value, + value & desc->cr3_ready_mask, + 0, TIMEOUT_US_10MS)) + return TEE_ERROR_GENERIC; + } else { + io_clrbits32_stm32shregs(cr3, desc->cr3_enable_mask); + } + + return TEE_SUCCESS; +} + +static TEE_Result stm32mp1_pwr_regu_read_state(struct regulator *regu, + bool *enabled) +{ + const struct pwr_regu_desc *desc = regu->priv; + + assert(desc); + + *enabled = io_read32(stm32_pwr_base() + PWR_CR3_OFF) & + desc->cr3_enable_mask; + + return TEE_SUCCESS; +} + +static TEE_Result stm32mp1_pwr_regu_read_voltage(struct regulator *regu, + int *level_uv) +{ + const struct pwr_regu_desc *desc = regu->priv; + + assert(desc); + + *level_uv = (int)desc->level_mv * 1000; + + return TEE_SUCCESS; +} + +static const struct regulator_ops stm32mp1_pwr_regu_ops = { + .set_state = stm32mp1_pwr_regu_set_state, + .get_state = stm32mp1_pwr_regu_read_state, + .get_voltage = stm32mp1_pwr_regu_read_voltage, +}; + +/* Preallocated regulator devices */ +static struct regulator pwr_regu_device[PWR_REGU_COUNT]; + +#define DEFINE_REG(_id, _name, _supply) { \ + .ops = &stm32mp1_pwr_regu_ops, \ + .name = _name, \ + .supply_name = _supply, \ + .priv = (void *)(pwr_regulators + (_id)), \ + .regulator = pwr_regu_device + (_id), \ +} + +static const struct regu_dt_desc stm32mp1_pwr_regu_dt_desc[] = { + [PWR_REG11] = DEFINE_REG(PWR_REG11, "reg11", "vdd"), + [PWR_REG18] = DEFINE_REG(PWR_REG18, "reg18", "vdd"), + [PWR_USB33] = DEFINE_REG(PWR_USB33, "usb33", "vdd_3v3_usbfs"), +}; +DECLARE_KEEP_PAGER(stm32mp1_pwr_regu_dt_desc); + +struct regulator *stm32mp1_pwr_get_regulator(enum pwr_regulator id) +{ + if (id < ARRAY_SIZE(pwr_regu_device)) + return pwr_regu_device + id; + + return NULL; +} + +static TEE_Result vdd_hslv_pm(enum pm_op op, uint32_t pm_hint __unused, + const struct pm_callback_handle *pm_hdl __unused) +{ + if (op == PM_OP_RESUME) + stm32mp_enable_fixed_vdd_hslv(); + + return TEE_SUCCESS; +} +DECLARE_KEEP_PAGER(vdd_hslv_pm); + +static TEE_Result set_fixed_vdd_hslv_mode(struct regulator *vdd_supply) +{ + TEE_Result res = TEE_ERROR_GENERIC; + bool product_below_2v5 = false; + uint32_t otp_value = 0; + uint32_t otp_id = 0; + + /* + * High Speed Low Voltage Pad mode Enable for SPI, SDMMC, ETH, QSPI + * and TRACE. Needed above ~50MHz and conditioned by AFMUX selection. + * It could be disabled for low frequencies or if AFMUX is selected + * but the function is not used, typically for TRACE. + * If high speed low voltage pad mode is enabled, platform will + * over consume. + * + * WARNING: + * Enabling High Speed mode while Vdd > 2.7V + * with the OTP product_below_2v5 (OTP 18, BIT 13) + * erroneously set to 1 can damage the SoC. + */ + res = stm32_bsec_find_otp_in_nvmem_layout("hw2_otp", &otp_id, + NULL, NULL); + if (res) + panic(); + + res = stm32_bsec_read_otp(&otp_value, otp_id); + if (res) + panic(); + + if (otp_value & HW2_OTP_PRODUCT_BELOW_2V5) + product_below_2v5 = true; + + if (regulator_get_voltage(vdd_supply) < VOLTAGE_2V7_THREDSHOLD_UV) { + if (!product_below_2v5) { + DMSG("Vdd domains HSLV protected by HW"); + } else { + stm32mp_enable_fixed_vdd_hslv(); + register_pm_driver_cb(vdd_hslv_pm, NULL, + "stm32mp1-pwr-hslv"); + } + } else if (product_below_2v5) { + panic("Vdd too high for related IO domains"); + } + + return TEE_SUCCESS; +} + +static TEE_Result stm32mp1_pwr_regu_probe(const void *fdt, int node, + const void *compat_data __unused) +{ + TEE_Result res = TEE_ERROR_GENERIC; + const struct regu_dt_desc *dt_desc = stm32mp1_pwr_regu_dt_desc; + struct regulator *vdd_supply = NULL; + int subnode = 0; + + /* Setup High Speed Low Voltage mode for fixed VDD domain */ + res = regulator_dt_get_supply(fdt, node, "vdd", &vdd_supply); + if (res) + return res; + + res = set_fixed_vdd_hslv_mode(vdd_supply); + if (res) + return res; + + /* Register PWR regulators */ + fdt_for_each_subnode(subnode, fdt, node) { + const char *node_name = fdt_get_name(fdt, subnode, NULL); + unsigned int n = 0; + + for (n = 0; n < ARRAY_SIZE(stm32mp1_pwr_regu_dt_desc); n++) + if (!strcmp(dt_desc[n].name, node_name)) + break; + + if (n >= ARRAY_SIZE(stm32mp1_pwr_regu_dt_desc)) { + EMSG("Invalid PWR regulator node %s", node_name); + panic(); + } + + res = regulator_dt_register(fdt, subnode, node, dt_desc + n); + if (res) { + EMSG("Can't register %s: %#"PRIx32, node_name, res); + panic(); + } + } + + return TEE_SUCCESS; +} + +static const struct dt_device_match stm32mp1_pwr_regu_match_table[] = { + { .compatible = "st,stm32mp1,pwr-reg" }, + { } +}; + +DEFINE_DT_DRIVER(stm32mp1_pwr_regu_dt_driver) = { + .name = "stm32mp1-pwr-regu", + .match_table = stm32mp1_pwr_regu_match_table, + .probe = stm32mp1_pwr_regu_probe, +}; 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..d6dc5de --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2018-2023, STMicroelectronics + */ + +#ifndef __STM32MP1_PWR_H +#define __STM32MP1_PWR_H + +#include +#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 + +/* CR3 register bitfield for STM32MP13 variants */ +#define PWR_CR3_VDDSD1EN BIT(13) +#define PWR_CR3_VDDSD1RDY BIT(14) +#define PWR_CR3_VDDSD2EN BIT(15) +#define PWR_CR3_VDDSD2RDY BIT(16) +#define PWR_CR3_VDDSD1VALID BIT(22) +#define PWR_CR3_VDDSD2VALID BIT(23) + +#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); + +/* Returns the registered regulator related to @id or NULL */ +struct regulator *stm32mp1_pwr_get_regulator(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..1b2ecbc --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_syscfg.c @@ -0,0 +1,199 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019-2023, STMicroelectronics + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * SYSCFG register offsets (base relative) + */ +#define SYSCFG_IOCTRLSETR U(0x18) +#define SYSCFG_CMPCR U(0x20) +#define SYSCFG_CMPENSETR U(0x24) +#define SYSCFG_CMPSD1CR U(0x30) +#define SYSCFG_CMPSD2CR U(0x40) +#define SYSCFG_HSLVEN0R U(0x50) +#define SYSCFG_IOSIZE U(0x400) + +/* + * SYSCFG_IOCTRLSETR Register for STM32MP15 variants + */ +#define SYSCFG_IOCTRLSETR_HSLVEN_TRACE BIT(0) +#define SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI BIT(1) +#define SYSCFG_IOCTRLSETR_HSLVEN_ETH BIT(2) +#define SYSCFG_IOCTRLSETR_HSLVEN_SDMMC BIT(3) +#define SYSCFG_IOCTRLSETR_HSLVEN_SPI BIT(4) + +/* + * 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 U(16) +#define SYSCFG_CMPCR_RAPSRC GENMASK_32(23, 20) +#define SYSCFG_CMPCR_ANSRC_SHIFT U(24) + +#define SYSCFG_CMPCR_READY_TIMEOUT_US U(1000) + +#define CMPENSETR_OFFSET U(0x4) +#define CMPENCLRR_OFFSET U(0x8) + +/* + * SYSCFG_CMPENSETR Register + */ +#define SYSCFG_CMPENSETR_MPU_EN BIT(0) + +/* + * HSLV definitions + */ +#define SYSCFG_HSLV_MASK GENMASK_32(15, 0) +#define SYSCFG_HSLV_KEY U(0x1018) + +static vaddr_t get_syscfg_base(void) +{ + static struct io_pa_va base = { .pa = SYSCFG_BASE }; + + return io_pa_or_va(&base, SYSCFG_IOSIZE); +} + +static void enable_io_compensation(int cmpcr_offset) +{ + vaddr_t cmpcr_va = get_syscfg_base() + cmpcr_offset; + uint32_t value = 0; + + if (io_read32(cmpcr_va) & SYSCFG_CMPCR_READY) + return; + + io_setbits32(cmpcr_va + CMPENSETR_OFFSET, SYSCFG_CMPENSETR_MPU_EN); + + if (IO_READ32_POLL_TIMEOUT(cmpcr_va, value, value & SYSCFG_CMPCR_READY, + 0, SYSCFG_CMPCR_READY_TIMEOUT_US)) { + /* Allow an almost silent failure here */ + EMSG("IO compensation cell not ready"); + } + + io_clrbits32(cmpcr_va, SYSCFG_CMPCR_SW_CTRL); + + DMSG("SYSCFG.cmpcr = %#"PRIx32, io_read32(cmpcr_va)); +} + +static __maybe_unused void disable_io_compensation(int cmpcr_offset) +{ + vaddr_t cmpcr_base = get_syscfg_base() + cmpcr_offset; + uint32_t value_cmpcr = 0; + uint32_t apsrc_ansrc = 0; + uint32_t value_cmpcr2 = 0; + + value_cmpcr = io_read32(cmpcr_base); + value_cmpcr2 = io_read32(cmpcr_base + CMPENSETR_OFFSET); + if (!(value_cmpcr & SYSCFG_CMPCR_READY && + value_cmpcr2 & SYSCFG_CMPENSETR_MPU_EN)) + return; + + /* Copy APSRC (resp. ANSRC) in RAPSRC (resp. RANSRC) */ + apsrc_ansrc = value_cmpcr >> SYSCFG_CMPCR_ANSRC_SHIFT; + value_cmpcr &= ~(SYSCFG_CMPCR_RANSRC | SYSCFG_CMPCR_RAPSRC); + value_cmpcr |= SHIFT_U32(apsrc_ansrc, SYSCFG_CMPCR_RANSRC_SHIFT); + + io_write32(cmpcr_base, value_cmpcr | SYSCFG_CMPCR_SW_CTRL); + + io_setbits32(cmpcr_base + CMPENCLRR_OFFSET, SYSCFG_CMPENSETR_MPU_EN); + + DMSG("SYSCFG.cmpcr = %#"PRIx32, io_read32(cmpcr_base)); +} + +static TEE_Result stm32mp1_iocomp(void) +{ + if (clk_enable(stm32mp_rcc_clock_id_to_clk(CK_CSI)) || + clk_enable(stm32mp_rcc_clock_id_to_clk(SYSCFG))) + panic(); + + enable_io_compensation(SYSCFG_CMPCR); + + return TEE_SUCCESS; +} + +driver_init(stm32mp1_iocomp); + +#ifdef CFG_STM32MP13 +void stm32mp_set_vddsd_comp_state(enum stm32mp13_vddsd_comp_id id, bool enable) +{ + int cmpcr_offset = 0; + + switch (id) { + case SYSCFG_IO_COMP_IDX_SD1: + cmpcr_offset = SYSCFG_CMPSD1CR; + break; + case SYSCFG_IO_COMP_IDX_SD2: + cmpcr_offset = SYSCFG_CMPSD2CR; + break; + default: + panic(); + } + + if (enable) + enable_io_compensation(cmpcr_offset); + else + disable_io_compensation(cmpcr_offset); +} + +void stm32mp_set_hslv_state(enum stm32mp13_hslv_id id, bool enable) +{ + size_t hslvenxr_offset = 0; + uint32_t hlvs_value = 0; + + assert(id < SYSCFG_HSLV_COUNT); + + if (enable) + hlvs_value = SYSCFG_HSLV_KEY; + + /* IDs are indices of SYSCFG_HSLVENxR registers */ + hslvenxr_offset = SYSCFG_HSLVEN0R + id * sizeof(uint32_t); + + io_write32(get_syscfg_base() + hslvenxr_offset, hlvs_value); + + /* Value read shall be 1 on enable and 0 on disable */ + hlvs_value = io_read32(get_syscfg_base() + hslvenxr_offset) & + SYSCFG_HSLV_MASK; + if (enable != hlvs_value) + panic(); +} + +void stm32mp_enable_fixed_vdd_hslv(void) +{ + enum stm32mp13_hslv_id id = SYSCFG_HSLV_COUNT; + + for (id = SYSCFG_HSLV_IDX_TPIU; id < SYSCFG_HSLV_COUNT; id++) { + /* SDMMCs domains may not be supplied by VDD */ + if (id == SYSCFG_HSLV_IDX_SDMMC1 || + id == SYSCFG_HSLV_IDX_SDMMC2) + continue; + + stm32mp_set_hslv_state(id, true); + } +} +#endif /* CFG_STM32MP13 */ + +#ifdef CFG_STM32MP15 +void stm32mp_enable_fixed_vdd_hslv(void) +{ + io_write32(get_syscfg_base() + SYSCFG_IOCTRLSETR, + SYSCFG_IOCTRLSETR_HSLVEN_TRACE | + SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI | + SYSCFG_IOCTRLSETR_HSLVEN_ETH | + SYSCFG_IOCTRLSETR_HSLVEN_SDMMC | + SYSCFG_IOCTRLSETR_HSLVEN_SPI); +} +#endif diff --git a/optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_syscfg.h b/optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_syscfg.h new file mode 100644 index 0000000..575f147 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_syscfg.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2023, STMicroelectronics + */ + +#ifndef __DRIVERS_STM32MP1_SYSCFG_H +#define __DRIVERS_STM32MP1_SYSCFG_H + +/* High Speed Low Voltage domains IDs for STM32MP13 variants */ +enum stm32mp13_hslv_id { + SYSCFG_HSLV_IDX_TPIU = 0, + SYSCFG_HSLV_IDX_QSPI, + SYSCFG_HSLV_IDX_ETH1, + SYSCFG_HSLV_IDX_ETH2, + SYSCFG_HSLV_IDX_SDMMC1, + SYSCFG_HSLV_IDX_SDMMC2, + SYSCFG_HSLV_IDX_SPI1, + SYSCFG_HSLV_IDX_SPI2, + SYSCFG_HSLV_IDX_SPI3, + SYSCFG_HSLV_IDX_SPI4, + SYSCFG_HSLV_IDX_SPI5, + SYSCFG_HSLV_IDX_LTDC, + SYSCFG_HSLV_COUNT +}; + +/* IO compensation domains IDs for STM32MP13 variants */ +enum stm32mp13_vddsd_comp_id { + SYSCFG_IO_COMP_IDX_SD1, + SYSCFG_IO_COMP_IDX_SD2, + SYSCFG_IO_COMP_COUNT +}; + +#ifdef CFG_STM32MP13 +/* + * Enable or disable IO compensation for a VDDSD IO domains + * @id: VDDSD domain ID + * @enable: True to enable IO compensation, false to disable + */ +void stm32mp_set_vddsd_comp_state(enum stm32mp13_vddsd_comp_id id, bool enable); + +/* + * Enable or disable High Speed Low Voltage mode of an IO domain + * @index: HSLV IO domain ID + * @enable: True to enable IO compensation, false to disable + */ +void stm32mp_set_hslv_state(enum stm32mp13_hslv_id id, bool enable); +#endif /*CFG_STM32MP13*/ + +/* Enable High Speed Low Voltage mode for domains fixed supplied VDD */ +void stm32mp_enable_fixed_vdd_hslv(void); +#endif /*__DRIVERS_STM32MP1_SYSCFG_H*/ 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..b8bb1f4 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/main.c @@ -0,0 +1,576 @@ +// 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 +#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); + +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 plat_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 + */ +void boot_primary_init_intc(void) +{ + gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET); + + stm32mp_register_online_cpu(); +} + +void boot_secondary_init_intc(void) +{ + gic_init_per_cpu(); + + 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_S_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 */ +#endif /* CFG_STM32MP13 */ + +#ifdef CFG_STM32MP15 +/* + * This concerns OP-TEE pager for STM32MP1 to use secure internal + * RAMs to execute. TZSRAM refers the TZSRAM_BASE/TZSRAM_SIZE + * used in boot.c to locate secure unpaged memory. + * + * STM32MP15 variants embed 640kB of contiguous securable SRAMs + * + * +--------------+ <-- SYSRAM_BASE + * | | lower part can be assigned to secure world + * | SYSRAM 256kB | 4kB granule boundary + * | | upper part can be assigned to secure world + * +--------------+ <-- SRAM1_BASE (= SYSRAM_BASE + SYSRAM_SIZE) + | | full range assigned to non-secure world or + * | SRAM1 128kB | to secure world, or to- Cortex-M4 exclusive access + * +--------------+ <-- SRAM2_BASE (= SRAM1_BASE + SRAM1_SIZE) + | | full range assigned to non-secure world or + * | SRAM2 128kB | to secure world, or to- Cortex-M4 exclusive access + * +--------------+ <-- SRAM3_BASE (= SRAM2_BASE + SRAM2_SIZE) + | | full range assigned to non-secure world or + * | SRAM3 64kB | to secure world, or to- Cortex-M4 exclusive access + * +--------------+ <-- SRAM4_BASE (= SRAM3_BASE + SRAM3_SIZE) + | | full range assigned to non-secure world or + * | SRAM4 64kB | to secure world, or to- Cortex-M4 exclusive access + * +--------------+ <-- SRAM4_BASE + SRAM4_SIZE + * + * If SRAMx memories are not used for the companion Cortex-M4 + * processor, OP-TEE can use this memory. + * + * SYSRAM configuration for secure/non-secure boundaries requires the + * secure SYSRAM memory to start at the SYSRAM physical base address and grow + * from there while the non-secure SYSRAM range lies at SYSRAM end addresses + * with a 4KB page granule. + * + * SRAM1, SRAM2, SRAM3 and SRAM4 are independently assigned to secure world, + * to non-secure world or possibly to Cortex-M4 exclusive access. Each + * assignment covers the full related SRAMx memory range. + * + * Using non-secure SYSRAM or one of the SRAMx for SCMI message communication + * can be done using CFG_STM32MP1_SCMI_SHM_BASE/CFG_STM32MP1_SCMI_SHM_SIZE. + * This imposes related memory area is assigned to non-secure world. + + * Using secure internal memories (SYSRAM and/or some SRAMx) with STM32MP15 + * shall meet this constraints known the TZSRAM physical memory range shall + * be contiguous. + */ + +#define SYSRAM_END (SYSRAM_BASE + SYSRAM_SIZE) +#define SYSRAM_SEC_END (SYSRAM_BASE + SYSRAM_SEC_SIZE) +#define SRAMS_END (SRAM4_BASE + SRAM4_SIZE) +#define SRAMS_START SRAM1_BASE +#define TZSRAM_END (CFG_TZSRAM_START + CFG_TZSRAM_SIZE) + +#define SCMI_SHM_IS_IN_SRAMX ((CFG_STM32MP1_SCMI_SHM_BASE >= SRAM1_BASE) && \ + (CFG_STM32MP1_SCMI_SHM_BASE + \ + CFG_STM32MP1_SCMI_SHM_SIZE) <= SRAMS_END) + +#define TZSRAM_FITS_IN_SYSRAM_SEC ((CFG_TZSRAM_START >= SYSRAM_BASE) && \ + (TZSRAM_END <= SYSRAM_SEC_END)) + +#define TZSRAM_FITS_IN_SYSRAM_AND_SRAMS ((CFG_TZSRAM_START >= SYSRAM_BASE) && \ + (CFG_TZSRAM_START < SYSRAM_END) && \ + (TZSRAM_END > SYSRAM_END) && \ + (TZSRAM_END <= SRAMS_END) && \ + (SYSRAM_SIZE == SYSRAM_SEC_SIZE)) + +#define TZSRAM_FITS_IN_SRAMS ((CFG_TZSRAM_START >= SRAMS_START) && \ + (CFG_TZSRAM_START < SRAMS_END) && \ + (TZSRAM_END <= SRAMS_END)) + +#define TZSRAM_IS_IN_DRAM (CFG_TZSRAM_START >= CFG_DRAM_BASE) + +#ifdef CFG_WITH_PAGER +/* + * At build time, we enforce that, when pager is used, + * either TZSRAM fully fits inside SYSRAM secure address range, + * or TZSRAM fully fits inside the full SYSRAM and spread inside SRAMx orderly, + * or TZSRAM fully fits some inside SRAMs address range, + * or TZSRAM is in DDR for debug and test purpose. + */ +static_assert(TZSRAM_FITS_IN_SYSRAM_SEC || TZSRAM_FITS_IN_SYSRAM_AND_SRAMS || + TZSRAM_FITS_IN_SRAMS || TZSRAM_IS_IN_DRAM); +#endif + +#if TZSRAM_FITS_IN_SYSRAM_AND_SRAMS || TZSRAM_FITS_IN_SRAMS || \ + SCMI_SHM_IS_IN_SRAMX +/* At run time we enforce that SRAM1 to SRAM4 are properly assigned if used */ +static TEE_Result init_stm32mp15_secure_srams(void) +{ + if (IS_ENABLED(CFG_WITH_PAGER)) { + if (core_is_buffer_intersect(CFG_TZSRAM_START, CFG_TZSRAM_SIZE, + SRAM1_BASE, SRAM1_SIZE)) + stm32mp_register_secure_periph_iomem(SRAM1_BASE); + + if (core_is_buffer_intersect(CFG_TZSRAM_START, CFG_TZSRAM_SIZE, + SRAM2_BASE, SRAM2_SIZE)) + stm32mp_register_secure_periph_iomem(SRAM2_BASE); + + if (core_is_buffer_intersect(CFG_TZSRAM_START, CFG_TZSRAM_SIZE, + SRAM3_BASE, SRAM3_SIZE)) + stm32mp_register_secure_periph_iomem(SRAM3_BASE); + + if (core_is_buffer_intersect(CFG_TZSRAM_START, CFG_TZSRAM_SIZE, + SRAM4_BASE, SRAM4_SIZE)) + stm32mp_register_secure_periph_iomem(SRAM4_BASE); + } + + if (SCMI_SHM_IS_IN_SRAMX) { + if (core_is_buffer_intersect(CFG_STM32MP1_SCMI_SHM_BASE, + CFG_STM32MP1_SCMI_SHM_SIZE, + SRAM1_BASE, SRAM1_SIZE)) + stm32mp_register_non_secure_periph_iomem(SRAM1_BASE); + + if (core_is_buffer_intersect(CFG_STM32MP1_SCMI_SHM_BASE, + CFG_STM32MP1_SCMI_SHM_SIZE, + SRAM2_BASE, SRAM2_SIZE)) + stm32mp_register_non_secure_periph_iomem(SRAM2_BASE); + + if (core_is_buffer_intersect(CFG_STM32MP1_SCMI_SHM_BASE, + CFG_STM32MP1_SCMI_SHM_SIZE, + SRAM3_BASE, SRAM3_SIZE)) + stm32mp_register_non_secure_periph_iomem(SRAM3_BASE); + + if (core_is_buffer_intersect(CFG_STM32MP1_SCMI_SHM_BASE, + CFG_STM32MP1_SCMI_SHM_SIZE, + SRAM4_BASE, SRAM4_SIZE)) + stm32mp_register_non_secure_periph_iomem(SRAM4_BASE); + } + + return TEE_SUCCESS; +} + +service_init_late(init_stm32mp15_secure_srams); +#endif /* TZSRAM_FITS_IN_SYSRAM_AND_SRAMS || TZSRAM_FITS_IN_SRAMS */ +#endif /* CFG_STM32MP15 && CFG_TZSRAM_START */ + +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); + + 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(); +} + +#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; + uint8_t bit_offset = 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_offset, + &bit_len) || + bit_len != 32 || bit_offset != 0) + 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_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 */ + +/* Some generic resources need to be unpaged */ +DECLARE_KEEP_PAGER(pinctrl_apply_state); 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..25c75b9 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/plat_tzc400.c @@ -0,0 +1,123 @@ +// 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, uint64_t pa, 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; + vaddr_t base = pa; + + 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) +{ + TEE_Result res = TEE_ERROR_GENERIC; + 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"); + } + + res = interrupt_add_handler_with_chip(interrupt_get_main_chip(), + &tzc_itr_handler); + if (res) + panic(); + + interrupt_enable(tzc_itr_handler.chip, 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..c3867fc --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/platform_config.h @@ -0,0 +1,241 @@ +/* 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 +#ifdef CFG_STM32MP15 +#define SRAM1_BASE 0x30000000 +#define SRAM2_BASE 0x30020000 +#define SRAM3_BASE 0x30040000 +#define SRAM4_BASE 0x30050000 +#endif +#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) + +#define HW2_OTP_PRODUCT_BELOW_2V5 BIT(13) + +/* 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 */ +#define STM32MP1_SCMI_SHM_END (CFG_STM32MP1_SCMI_SHM_BASE + \ + CFG_STM32MP1_SCMI_SHM_SIZE) + +#if (CFG_STM32MP1_SCMI_SHM_BASE && \ + (CFG_STM32MP1_SCMI_SHM_BASE >= SYSRAM_BASE) && \ + (STM32MP1_SCMI_SHM_END <= (SYSRAM_BASE + SYSRAM_SIZE))) +#define SYSRAM_SEC_SIZE (CFG_STM32MP1_SCMI_SHM_BASE - SYSRAM_BASE) +#else +#define SYSRAM_SEC_SIZE SYSRAM_SIZE +#endif + +#ifdef CFG_STM32MP15 +#define SRAM1_SIZE 0x20000 +#define SRAM2_SIZE 0x20000 +#define SRAM3_SIZE 0x10000 +#define SRAM4_SIZE 0x10000 +#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..bb20680 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/pm/psci.c @@ -0,0 +1,277 @@ +// 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) +{ + struct itr_chip *itr_chip = interrupt_get_main_chip(); + + /* 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(); + interrupt_raise_sgi(itr_chip, 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..b0cc34b --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/scmi_server.c @@ -0,0 +1,904 @@ +// 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 +#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, + VOLTD_VREFBUF, + VOLTD_IOD, +}; + +/* + * struct stm32_scmi_voltd - Data for the exposed voltage domains + * @name: Power regulator string ID exposed to channel + * @priv_name: Internal string ID for the PMIC regulators + * @priv_id: Internal ID for the regulator aside PMIC ones + * @priv_dev: Internal ID for the device implementing the regulator + * @regulator: Regulator controller device + * @state: State of the SCMI voltage domain (true: enable, false: disable) + */ +struct stm32_scmi_voltd { + const char *name; + const char *priv_name; + unsigned int priv_id; + enum voltd_device priv_dev; + struct regulator *regulator; + bool state; +}; + +#if CFG_STM32MP1_SCMI_SHM_BASE +register_phys_mem(MEM_AREA_IO_NSEC, CFG_STM32MP1_SCMI_SHM_BASE, + CFG_STM32MP1_SCMI_SHM_SIZE); + +/* 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 +#endif /*CFG_STM32MP1_SCMI_SHM_BASE*/ + +#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, _priv_name, _name) \ + [(_scmi_id)] = { \ + .priv_name = (_priv_name), \ + .priv_id = (_priv_id), \ + .priv_dev = (_dev_id), \ + .name = (_name), \ + } + +#define VOLTD_CELL_PWR(_scmi_id, _priv_id, _name) \ + VOLTD_CELL((_scmi_id), VOLTD_PWR, (_priv_id), NULL, (_name)) + +#define VOLTD_CELL_IOD(_scmi_id, _priv_id, _name) \ + VOLTD_CELL((_scmi_id), VOLTD_IOD, (_priv_id), NULL, (_name)) + +#define VOLTD_CELL_VREFBUF(_scmi_id, _name) \ + VOLTD_CELL((_scmi_id), VOLTD_VREFBUF, 0, NULL, (_name)) + +#define VOLTD_CELL_PMIC(_scmi_id, _priv_name, _name) \ + VOLTD_CELL((_scmi_id), VOLTD_PMIC, 0, (_priv_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 + +#ifdef CFG_STM32MP13 +struct stm32_scmi_voltd scmi_voltage_domain[] = { + VOLTD_CELL_PWR(VOLTD_SCMI_REG11, PWR_REG11, "reg11"), + VOLTD_CELL_PWR(VOLTD_SCMI_REG18, PWR_REG18, "reg18"), + VOLTD_CELL_PWR(VOLTD_SCMI_USB33, PWR_USB33, "usb33"), + VOLTD_CELL_IOD(VOLTD_SCMI_SDMMC1_IO, IOD_SDMMC1, "sdmmc1"), + VOLTD_CELL_IOD(VOLTD_SCMI_SDMMC2_IO, IOD_SDMMC2, "sdmmc2"), + VOLTD_CELL_VREFBUF(VOLTD_SCMI_VREFBUF, "vrefbuf"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BUCK1, "buck1", "buck1"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BUCK2, "buck2", "buck2"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BUCK3, "buck3", "buck3"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BUCK4, "buck4", "buck4"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO1, "ldo1", "ldo1"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO2, "ldo2", "ldo2"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO3, "ldo3", "ldo3"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO4, "ldo4", "ldo4"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO5, "ldo5", "ldo5"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO6, "ldo6", "ldo6"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_VREFDDR, "vref_ddr", "vref_ddr"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BOOST, "boost", "bst_out"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_PWR_SW1, "pwr_sw1", "pwr_sw1"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_PWR_SW2, "pwr_sw2", "pwr_sw2"), +}; +#endif + +#ifdef CFG_STM32MP15 +struct stm32_scmi_voltd scmi_voltage_domain[] = { + VOLTD_CELL_PWR(VOLTD_SCMI_REG11, PWR_REG11, "reg11"), + VOLTD_CELL_PWR(VOLTD_SCMI_REG18, PWR_REG18, "reg18"), + VOLTD_CELL_PWR(VOLTD_SCMI_USB33, PWR_USB33, "usb33"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BUCK1, "buck1", "vddcore"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BUCK2, "buck2", "vdd_ddr"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BUCK3, "buck3", "vdd"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BUCK4, "buck4", "v3v3"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO1, "ldo1", "v1v8_audio"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO2, "ldo2", "v3v3_hdmi"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO3, "ldo3", "vtt_ddr"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO4, "ldo4", "vdd_usb"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO5, "ldo5", "vdda"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO6, "ldo6", "v1v2_hdmi"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_VREFDDR, "vref_ddr", "vref_ddr"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BOOST, "boost", "bst_out"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_PWR_SW1, "pwr_sw1", "vbus_otg"), + VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_PWR_SW2, "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){ +#ifdef SMT_BUFFER_BASE + .shm_addr = { .pa = SMT_BUFFER_BASE }, + .shm_size = SMT_BUF_SLOT_SIZE, +#endif + }, + .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) { + FMSG("SCMI clock %u enable", scmi_id); + clk_enable(clock->clk); + clock->enabled = true; + } + } else { + if (clock->enabled) { + FMSG("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; + + FMSG("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) { + FMSG("SCMI reset %u set", scmi_id); + res = rstctrl_assert(rd->rstctrl); + } else { + FMSG("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; +} + +int32_t plat_scmi_voltd_levels_array(unsigned int channel_id, + unsigned int scmi_id, size_t start_index, + long *out_levels, size_t *nb_elts) + +{ + struct stm32_scmi_voltd *voltd = find_voltd(channel_id, scmi_id); + + if (!voltd) + return SCMI_NOT_FOUND; + + if (voltd->regulator) { + struct regulator_voltages_desc *desc = NULL; + TEE_Result res = TEE_ERROR_GENERIC; + const int *levels = NULL; + size_t n = 0; + + res = regulator_supported_voltages(voltd->regulator, &desc, + &levels); + if (res == TEE_ERROR_NOT_SUPPORTED) + return SCMI_NOT_SUPPORTED; + if (res) + return SCMI_GENERIC_ERROR; + if (!desc || desc->type != VOLTAGE_TYPE_FULL_LIST) { + /* + * Triplet min/max/step description. Caller should use + * plat_scmi_voltd_levels_by_step(). + */ + return SCMI_NOT_SUPPORTED; + } + + if (start_index >= desc->num_levels) + return SCMI_OUT_OF_RANGE; + + if (!*nb_elts) { + *nb_elts = desc->num_levels - start_index; + return SCMI_SUCCESS; + } + + *nb_elts = MIN(*nb_elts, desc->num_levels - start_index); + for (n = 0; n < *nb_elts; n++) + out_levels[n] = levels[start_index + n]; + + return SCMI_SUCCESS; + } + + return SCMI_DENIED; +} + +int32_t plat_scmi_voltd_levels_by_step(unsigned int channel_id, + unsigned int scmi_id, long *min_max_step) +{ + struct stm32_scmi_voltd *voltd = find_voltd(channel_id, scmi_id); + + if (!voltd) + return SCMI_NOT_FOUND; + + if (voltd->regulator) { + struct regulator_voltages_desc *desc = NULL; + TEE_Result res = TEE_ERROR_GENERIC; + const int *levels = NULL; + + res = regulator_supported_voltages(voltd->regulator, &desc, + &levels); + if (res == TEE_ERROR_NOT_SUPPORTED) + return SCMI_NOT_SUPPORTED; + if (res) + return SCMI_GENERIC_ERROR; + if (!desc || desc->type != VOLTAGE_TYPE_INCREMENT) { + /* + * Triplet min/max/step description. Caller should use + * plat_scmi_voltd_levels_by_step(). + */ + return SCMI_NOT_SUPPORTED; + } + + min_max_step[0] = levels[0]; + min_max_step[1] = levels[1]; + min_max_step[2] = levels[2]; + + return SCMI_SUCCESS; + } + + return SCMI_NOT_SUPPORTED; +} + +int32_t plat_scmi_voltd_get_level(unsigned int channel_id, unsigned int scmi_id, + long *level_uv) +{ + struct stm32_scmi_voltd *voltd = find_voltd(channel_id, scmi_id); + + if (!voltd) + return SCMI_INVALID_PARAMETERS; + + if (voltd->regulator) { + *level_uv = regulator_get_voltage(voltd->regulator); + return SCMI_SUCCESS; + } + + return SCMI_DENIED; +} + +int32_t plat_scmi_voltd_set_level(unsigned int channel_id, unsigned int scmi_id, + long level_uv) +{ + struct stm32_scmi_voltd *voltd = find_voltd(channel_id, scmi_id); + + if (!voltd) + return SCMI_NOT_FOUND; + + if (voltd->regulator) { + TEE_Result res = TEE_ERROR_GENERIC; + + if (level_uv < INT_MIN || level_uv > INT_MAX) + return SCMI_OUT_OF_RANGE; + + res = regulator_set_voltage(voltd->regulator, level_uv); + if (res) + return SCMI_GENERIC_ERROR; + else + return SCMI_SUCCESS; + } + + return SCMI_DENIED; +} + +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; + + if (voltd->regulator) { + if (voltd->state) + *config = SCMI_VOLTAGE_DOMAIN_CONFIG_ARCH_ON; + else + *config = SCMI_VOLTAGE_DOMAIN_CONFIG_ARCH_OFF; + + return SCMI_SUCCESS; + } + + return SCMI_DENIED; +} + +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); + + if (!voltd) + return SCMI_NOT_FOUND; + + if (voltd->regulator) { + switch (config) { + case SCMI_VOLTAGE_DOMAIN_CONFIG_ARCH_ON: + if (!voltd->state) { + if (regulator_enable(voltd->regulator)) + return SCMI_GENERIC_ERROR; + + voltd->state = true; + } + break; + case SCMI_VOLTAGE_DOMAIN_CONFIG_ARCH_OFF: + if (voltd->state) { + if (regulator_disable(voltd->regulator)) + return SCMI_GENERIC_ERROR; + + voltd->state = false; + } + break; + default: + return SCMI_INVALID_PARAMETERS; + } + + return SCMI_SUCCESS; + } + + return SCMI_DENIED; +} + +static void get_voltd_regulator(struct stm32_scmi_voltd *voltd) +{ + switch (voltd->priv_dev) { + case VOLTD_PWR: + voltd->regulator = stm32mp1_pwr_get_regulator(voltd->priv_id); + break; + case VOLTD_PMIC: + voltd->regulator = stm32mp_pmic_get_regulator(voltd->priv_name); + break; + case VOLTD_VREFBUF: + voltd->regulator = stm32_vrefbuf_regulator(); + break; + case VOLTD_IOD: + voltd->regulator = stm32mp1_get_iod_regulator(voltd->priv_id); + break; + default: + break; + } + + if (voltd->regulator && voltd->regulator->flags & REGULATOR_BOOT_ON) + regulator_enable(voltd->regulator); +} + +/* + * 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; + + if (chan->shm_addr.pa) { + struct io_pa_va *addr = &chan->shm_addr; + + /* Enforce non-secure shm mapped as device memory */ + addr->va = (vaddr_t)phys_to_virt(addr->pa, + MEM_AREA_IO_NSEC, + chan->shm_size); + assert(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"); + + get_voltd_regulator(voltd); + } + } + + 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..4562ebd --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/shared_resources.c @@ -0,0 +1,755 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2017-2023, STMicroelectronics + */ + +#include +#include +#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", + [STM32MP1_SHRES_SRAM1] = "SRAM1", + [STM32MP1_SHRES_SRAM2] = "SRAM2", + [STM32MP1_SHRES_SRAM3] = "SRAM3", + [STM32MP1_SHRES_SRAM4] = "SRAM4", +}; + +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; +} + +void stm32mp_register_gpioz_pin_count(size_t count) +{ + assert(gpioz_nbpin == -1); + + gpioz_nbpin = count; +} + +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; + case SRAM1_BASE: + id = STM32MP1_SHRES_SRAM1; + break; + case SRAM2_BASE: + id = STM32MP1_SHRES_SRAM2; + break; + case SRAM3_BASE: + id = STM32MP1_SHRES_SRAM3; + break; + case SRAM4_BASE: + id = STM32MP1_SHRES_SRAM4; + 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; + } +} + +void stm32mp_register_secure_pinctrl(struct pinctrl_state *pinctrl) +{ + unsigned int *bank = NULL; + unsigned int *pin = NULL; + size_t count = 0; + size_t n = 0; + + stm32_gpio_pinctrl_bank_pin(pinctrl, NULL, NULL, &count); + if (!count) + return; + + bank = calloc(count, sizeof(*bank)); + pin = calloc(count, sizeof(*pin)); + if (!bank || !pin) + panic(); + + stm32_gpio_pinctrl_bank_pin(pinctrl, bank, pin, &count); + for (n = 0; n < count; n++) + stm32mp_register_secure_gpio(bank[n], pin[n]); + + free(bank); + free(pin); +} + +void stm32mp_register_non_secure_pinctrl(struct pinctrl_state *pinctrl) +{ + unsigned int *bank = NULL; + unsigned int *pin = NULL; + size_t count = 0; + size_t n = 0; + + stm32_gpio_pinctrl_bank_pin(pinctrl, NULL, NULL, &count); + if (!count) + return; + + bank = calloc(count, sizeof(*bank)); + pin = calloc(count, sizeof(*pin)); + if (!bank || !pin) + panic(); + + stm32_gpio_pinctrl_bank_pin(pinctrl, bank, pin, &count); + for (n = 0; n < count; n++) + stm32mp_register_non_secure_gpio(bank[n], pin[n]); + + free(bank); + free(pin); +} + +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_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)); + + config_lock_decprot(STM32MP1_ETZPC_SRAM1_ID, + shres2decprot_attr(STM32MP1_SHRES_SRAM1)); + config_lock_decprot(STM32MP1_ETZPC_SRAM2_ID, + shres2decprot_attr(STM32MP1_SHRES_SRAM2)); + config_lock_decprot(STM32MP1_ETZPC_SRAM3_ID, + shres2decprot_attr(STM32MP1_SHRES_SRAM3)); + config_lock_decprot(STM32MP1_ETZPC_SRAM4_ID, + shres2decprot_attr(STM32MP1_SHRES_SRAM4)); +} +#else +static void set_etzpc_secure_configuration(void) +{ + /* Nothing to do */ +} +#endif + +static void rcc_secure_configuration(void) +{ + bool secure = stm32_rcc_is_secure(); + bool mckprot = stm32_rcc_is_mckprot(); + enum stm32mp_shres id = STM32MP1_SHRES_COUNT; + bool need_secure = false; + bool need_mckprot = 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; + + /* SRAMs have no constraints on RCC configuration */ + if (id == STM32MP1_SHRES_SRAM1 || + id == STM32MP1_SHRES_SRAM2 || + id == STM32MP1_SHRES_SRAM3 || + id == STM32MP1_SHRES_SRAM4) + continue; + + need_secure = true; + if (mckprot_resource(id)) + need_mckprot = true; + + if (!secure || (need_mckprot && !mckprot)) + EMSG("Error RCC TZEN=%u MCKPROT=%u and %s (%u) secure", + secure, mckprot, shres2str_id(id), id); + } + + if ((need_secure && !secure) || (need_mckprot && !mckprot)) { + if (IS_ENABLED(CFG_INSECURE)) + EMSG("WARNING: CFG_INSECURE allows insecure RCC configuration"); + else + panic(); + } + + if (!need_mckprot && mckprot) { + DMSG("Disable RCC MCKPROT"); + stm32_rcc_set_mckprot(false); + } +} + +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"); + } + 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..627933e --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/stm32_util.h @@ -0,0 +1,332 @@ +/* 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 +#include +#include + +/* Backup registers and RAM utils */ +vaddr_t stm32mp_bkpreg(unsigned int idx); + +/* 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 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_SRAM1, + STM32MP1_SHRES_SRAM2, + STM32MP1_SHRES_SRAM3, + STM32MP1_SHRES_SRAM4, + + 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); + +/* + * Register pin resource of a pin control state as a secure peripheral + * @bank: Bank of the target GPIO + * @pin: Bit position of the target GPIO in the bank + */ +void stm32mp_register_secure_pinctrl(struct pinctrl_state *pinctrl); + +/* + * Register pin resource of a pin control state 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_pinctrl(struct pinctrl_state *pinctrl); + +/* 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 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); + +/* Register number of pins in the GPIOZ bank */ +void stm32mp_register_gpioz_pin_count(size_t count); + +#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 void +stm32mp_register_secure_pinctrl(struct pinctrl_state *pinctrl __unused) +{ +} + +static inline void +stm32mp_register_non_secure_pinctrl(struct pinctrl_state *pinctrl __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_non_secure(unsigned int bank __unused) +{ + return false; +} + +static inline void stm32mp_register_clock_parents_secure(unsigned long clock_id + __unused) +{ +} + +static inline void stm32mp_register_gpioz_pin_count(size_t count __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-stm32mp2/conf.mk b/optee/optee_os/core/arch/arm/plat-stm32mp2/conf.mk new file mode 100644 index 0000000..711675f --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp2/conf.mk @@ -0,0 +1,77 @@ +flavor_dts_file-257F_EV1 = stm32mp257f-ev1.dts + +flavorlist-MP25 = $(flavor_dts_file-257F_EV1) + +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 ?= stm32mp257f-ev1.dts + +ifneq ($(filter $(CFG_EMBED_DTB_SOURCE_FILE),$(flavorlist-MP25)),) +$(call force,CFG_STM32MP25,y) +endif + +ifneq ($(CFG_STM32MP25),y) +$(error STM32 Platform must be defined) +endif + +include core/arch/arm/cpu/cortex-armv8-0.mk +supported-ta-targets ?= ta_arm64 + +$(call force,CFG_ARM64_core,y) +$(call force,CFG_DRIVERS_CLK,y) +$(call force,CFG_DRIVERS_CLK_DT,y) +$(call force,CFG_DRIVERS_GPIO,y) +$(call force,CFG_DRIVERS_PINCTRL,y) +$(call force,CFG_DT,y) +$(call force,CFG_GIC,y) +$(call force,CFG_HALT_CORES_ON_PANIC_SGI,15) +$(call force,CFG_INIT_CNTVOFF,y) +$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) +$(call force,CFG_WITH_ARM_TRUSTED_FW,y) +$(call force,CFG_WITH_LPAE,y) + +CFG_TZDRAM_START ?= 0x82000000 +CFG_TZDRAM_SIZE ?= 0x02000000 + +# Support DDR ranges up to 8GBytes (address range: 0x80000000 + DDR size) +CFG_CORE_LARGE_PHYS_ADDR ?= y +CFG_CORE_ARM64_PA_BITS ?= 34 + +CFG_CORE_HEAP_SIZE ?= 262144 +CFG_CORE_RESERVED_SHM ?= n +CFG_DTB_MAX_SIZE ?= 262144 +CFG_HALT_CORES_ON_PANIC ?= y +CFG_MMAP_REGIONS ?= 30 +CFG_NUM_THREADS ?= 5 +CFG_TEE_CORE_NB_CORE ?= 2 + +CFG_STM32_GPIO ?= y +CFG_STM32_RIF ?= y +CFG_STM32_RIFSC ?= y +CFG_STM32_RNG ?= y +CFG_STM32_UART ?= y + +# Default enable some test facitilites +CFG_ENABLE_EMBEDDED_TESTS ?= y +CFG_WITH_STATS ?= y + +# Default disable ASLR +CFG_CORE_ASLR ?= n + +# UART instance used for early console (0 disables early console) +CFG_STM32_EARLY_CONSOLE_UART ?= 2 + +# Default disable external DT support +CFG_EXTERNAL_DT ?= n + +# Default enable HWRNG PTA support +CFG_HWRNG_PTA ?= y +ifeq ($(CFG_HWRNG_PTA),y) +$(call force,CFG_STM32_RNG,y,Required by CFG_HWRNG_PTA) +$(call force,CFG_WITH_SOFTWARE_PRNG,n,Required by CFG_HWRNG_PTA) +CFG_HWRNG_QUALITY ?= 1024 +endif diff --git a/optee/optee_os/core/arch/arm/plat-stm32mp2/main.c b/optee/optee_os/core/arch/arm/plat-stm32mp2/main.c new file mode 100644 index 0000000..3601fac --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp2/main.c @@ -0,0 +1,144 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2023, STMicroelectronics + */ + +#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_SEC, APB1_BASE, APB1_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, APB2_BASE, APB2_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, AHB2_BASE, AHB2_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, AHB3_BASE, AHB3_SIZE); +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, SAPB_BASE, SAPB_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, SAHB_BASE, SAHB_SIZE); + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_BASE, GIC_SIZE); + +#define _ID2STR(id) (#id) +#define ID2STR(id) _ID2STR(id) + +static TEE_Result platform_banner(void) +{ + IMSG("Platform stm32mp2: 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 plat_console_init(void) +{ +#ifdef CFG_STM32_UART + /* 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, }, + [9] = { .pa = UART9_BASE, .secure = false, }, + }; + + static_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); +#endif +} + +#ifdef CFG_STM32_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); +#endif /*STM32_UART*/ + +void boot_primary_init_intc(void) +{ + gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET); +} + +void boot_secondary_init_intc(void) +{ + gic_init_per_cpu(); +} diff --git a/optee/optee_os/core/arch/arm/plat-stm32mp2/platform_config.h b/optee/optee_os/core/arch/arm/plat-stm32mp2/platform_config.h new file mode 100644 index 0000000..4d7af4a --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp2/platform_config.h @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2023, STMicroelectronics + */ + +#ifndef PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#include + +/* Make stacks aligned to data cache line length */ +#define STACK_ALIGNMENT 32 + +/* SoC interface registers base address ranges */ +#define APB1_BASE 0x40000000 +#define APB1_SIZE 0x00200000 +#define APB2_BASE 0x40200000 +#define APB2_SIZE 0x00040000 +#define AHB2_BASE 0x40400000 +#define AHB2_SIZE 0x01c00000 +#define AHB3_BASE 0x42000000 +#define AHB3_SIZE 0x02000000 +#define APB3_BASE 0x44000000 +#define APB3_SIZE 0x001f0000 +#define AHB4_BASE 0x44200000 +#define AHB4_SIZE 0x01e00000 +#define SAPB_BASE 0x46000000 +#define SAPB_SIZE 0x00200000 +#define SAHB_BASE 0x46200000 +#define SAHB_SIZE 0x01e00000 +#define APB4_BASE 0x48000000 +#define APB4_SIZE 0x00200000 +#define AHB5_BASE 0x48200000 +#define AHB5_SIZE 0x01e00000 + +/* SoC interface registers base address */ +#define UART2_BASE 0x400e0000 +#define UART3_BASE 0x400f0000 +#define UART4_BASE 0x40100000 +#define UART5_BASE 0x40110000 +#define I2C4_BASE 0x40150000 +#define I2C6_BASE 0x40170000 +#define UART6_BASE 0x40220000 +#define UART9_BASE 0x402c0000 +#define UART1_BASE 0x40330000 +#define SPI6_BASE 0x40350000 +#define UART7_BASE 0x40370000 +#define UART8_BASE 0x40380000 +#define OSPI1_BASE 0x40430000 +#define OSPI2_BASE 0x40440000 +#define HASH1_BASE 0x42010000 +#define RNG1_BASE 0x42020000 +#define CRYP1_BASE 0x42030000 +#define SAES_BASE 0x42050000 +#define PKA_BASE 0x42060000 +#define RIFSC_BASE 0x42080000 +#define RISAF5_BASE 0x420e0000 +#define RISAB6_BASE 0x42140000 +#define BSEC3_BASE 0x44000000 +#define IWDG2_BASE 0x44002000 +#define IWDG1_BASE 0x44010000 +#define RCC_BASE 0x44200000 +#define PWR_BASE 0x44210000 +#define SYSCFG_BASE 0x44230000 +#define GPIOA_BASE 0x44240000 +#define GPIOB_BASE 0x44250000 +#define GPIOC_BASE 0x44260000 +#define GPIOD_BASE 0x44270000 +#define GPIOE_BASE 0x44280000 +#define GPIOF_BASE 0x44290000 +#define GPIOG_BASE 0x442a0000 +#define GPIOH_BASE 0x442b0000 +#define GPIOI_BASE 0x442c0000 +#define GPIOJ_BASE 0x442d0000 +#define GPIOK_BASE 0x442e0000 +#define RTC_BASE 0x46000000 +#define TAMP_BASE 0x46010000 +#define GPIOZ_BASE 0x46200000 +#define STGEN_BASE 0x48080000 +#define FMC_BASE 0x48200000 +#define PCIE_BASE 0x48400000 +#define A35SSC_BASE 0x48800000 +#define GIC_BASE 0x4ac00000 +#define DDR_BASE UL(0x80000000) + +#define SYSRAM_BASE 0x0e000000 + +#define SRAM1_BASE 0x0e040000 + +/* GIC resources */ +#define GIC_SIZE 0x80000 +#define GICC_OFFSET 0x20000 +#define GICD_OFFSET 0x10000 + +/* Console configuration */ +#define GIC_SPI_UART4 126 + +#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) + +/* USART/UART resources */ +#define USART1_BASE UART1_BASE +#define USART2_BASE UART2_BASE +#define USART3_BASE UART3_BASE +#define USART6_BASE UART6_BASE + +#endif /*PLATFORM_CONFIG_H*/ diff --git a/optee/optee_os/core/arch/arm/plat-stm32mp2/stm32_util.h b/optee/optee_os/core/arch/arm/plat-stm32mp2/stm32_util.h new file mode 100644 index 0000000..2575f0a --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp2/stm32_util.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2023, STMicroelectronics + */ + +#ifndef __STM32_UTIL_H__ +#define __STM32_UTIL_H__ + +#include +#include +#include + +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_gpioz_pin_count(size_t count __unused) { } + +#define may_spin_lock(lock) cpu_spin_lock_xsave(lock) +#define may_spin_unlock(lock, exceptions) cpu_spin_unlock_xrestore(lock, \ + exceptions) +#endif /*__STM32_UTIL_H__*/ diff --git a/optee/optee_os/core/arch/arm/plat-stm32mp2/stm32mp_pm.c b/optee/optee_os/core/arch/arm/plat-stm32mp2/stm32mp_pm.c new file mode 100644 index 0000000..7dfe0e3 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp2/stm32mp_pm.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2023-2024, STMicroelectronics + */ + +#include +#include +#include +#include +#include + +/** + * @brief Handler for system off + * + * @param[in] a0 Unused + * @param[in] a1 Unused + * + * @retval 0 if OK, other value else and TF-A will panic + */ +unsigned long thread_system_off_handler(unsigned long a0 __unused, + unsigned long a1 __unused) +{ + /* + * configure targeted mode in PMIC for system OFF, + * no need to save context + */ + uint32_t pm_hint = PM_HINT_CLOCK_STATE | + ((PM_MAX_LEVEL << PM_HINT_PLATFORM_STATE_SHIFT) & + PM_HINT_PLATFORM_STATE_MASK); + + return pm_change_state(PM_OP_SUSPEND, pm_hint); +} + +static uint32_t get_pm_hint(unsigned long a0) +{ + uint32_t pm_hint = 0U; + + /* a0 is the highest power level which was powered down. */ + if (a0 < PM_D2_LPLV_LEVEL) + pm_hint = PM_HINT_CLOCK_STATE; + else + pm_hint = PM_HINT_CONTEXT_STATE; + + pm_hint |= ((a0 << PM_HINT_PLATFORM_STATE_SHIFT) & + PM_HINT_PLATFORM_STATE_MASK); + + return pm_hint; +} + +/** + * @brief Handler for cpu resume + * + * @param[in] a0 Max power level powered down + * @param[in] a1 Unused + * + * @retval 0 if OK, other value else and TF-A will panic + */ +unsigned long thread_cpu_resume_handler(unsigned long a0, + unsigned long a1 __unused) +{ + TEE_Result retstatus = TEE_SUCCESS; + + retstatus = pm_change_state(PM_OP_RESUME, get_pm_hint(a0)); + + /* + * Returned value to the TF-A. + * If it is not 0, the system will panic + */ + if (retstatus == TEE_SUCCESS) + return 0; + else + return 1; +} + +/** + * @brief Handler for cpu suspend + * + * @param[in] a0 Max power level to power down + * @param[in] a1 Unused + * + * @retval 0 if OK, other value else and TF-A will panic + */ +unsigned long thread_cpu_suspend_handler(unsigned long a0, + unsigned long a1 __unused) +{ + TEE_Result retstatus = TEE_SUCCESS; + + retstatus = pm_change_state(PM_OP_SUSPEND, get_pm_hint(a0)); + + /* + * Returned value to the TF-A. + * If it is not 0, the system will panic + */ + if (retstatus == TEE_SUCCESS) + return 0; + else + return 1; +} diff --git a/optee/optee_os/core/arch/arm/plat-stm32mp2/stm32mp_pm.h b/optee/optee_os/core/arch/arm/plat-stm32mp2/stm32mp_pm.h new file mode 100644 index 0000000..d8ac02d --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp2/stm32mp_pm.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2023-2024, STMicroelectronics + */ + +#ifndef __STM32MP_PM_H__ +#define __STM32MP_PM_H__ + +/* + * The PSCI topology is defined in TF-A, with 5 power levels supported in + * the first parameter a0="Max power level powered down" of TF-A SPD hooks + * + * power level (associated low power mode for a0) + * 0: CPU1 core#0 or core#1 (Stop1 or LP-Stop1) + * 1: D1 domain (LPLV-Stop1) + * 2: LPLV D1 (Stop2 or LP-Stop2) + * 3: D2 (LPLV-Stop1) + * 4: LPLV D2 (Standby) + * 5: MAX (PowerOff) + * + * these power level are only managed in power driver (PMIC), for pm function + * use the 2 associated parameters: + * - PM_HINT_CONTEXT_STATE : advertise driver to save all their context in DDR + * (self refresh) for standby mode + * - PM_HINT_CLOCK_STATE : advertise driver to interrupt operation when clock + * are stalled for the other low power modes + */ +#define PM_CORE_LEVEL 0 +#define PM_D1_LEVEL 1 +#define PM_D1_LPLV_LEVEL 2 +#define PM_D2_LEVEL 3 +#define PM_D2_LPLV_LEVEL 4 +#define PM_MAX_LEVEL 5 + +#endif /*__STM32MP_PM_H__*/ diff --git a/optee/optee_os/core/arch/arm/plat-stm32mp2/sub.mk b/optee/optee_os/core/arch/arm/plat-stm32mp2/sub.mk new file mode 100644 index 0000000..9d15798 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp2/sub.mk @@ -0,0 +1,4 @@ +global-incdirs-y += . + +srcs-y += main.c +srcs-y += stm32mp_pm.c 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..5ed2f95 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sunxi/main.c @@ -0,0 +1,179 @@ +// 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 SUNXI_TZPC_BASE +static void tzpc_init(void); +#endif + +static struct serial8250_uart_data console_data; + +void plat_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 boot_primary_init_intc(void) +{ + gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET); +} + +void boot_secondary_init_intc(void) +{ + gic_init_per_cpu(); +} +#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..54d7bee --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-synquacer/main.c @@ -0,0 +1,73 @@ +// 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 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 plat_console_init(void) +{ + pl011_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ, + CONSOLE_BAUDRATE); + register_serial_console(&console_data.chip); +} + +void boot_primary_init_intc(void) +{ + gic_init(0, GIC_BASE + GICD_OFFSET); +} + +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) +{ + if (interrupt_add_handler_with_chip(interrupt_get_main_chip(), + &timer_itr)) + panic(); + + interrupt_enable(timer_itr.chip, timer_itr.it); + + /* 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..2a34d33 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-synquacer/rng_pta.c @@ -0,0 +1,360 @@ +// 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 = 0; + + 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 = 0; + + 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; + uint32_t rising_edge_count = 0; + uint32_t lo_edge_count = 0; + uint32_t hi_edge_count = 0; + uint32_t i = 0; + + 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 = 0; + uint8_t entropy_sha512_256[TEE_SHA256_HASH_SIZE]; + uint8_t pool_status = 0; + TEE_Result res = TEE_ERROR_GENERIC; + + 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 = 0; + void *vaddr = 0; + uint8_t pool_full = 0; + uint32_t exceptions = 0; + + exceptions = cpu_spin_lock_xsave(&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_xrestore(&entropy_lock, exceptions); +} + +static TEE_Result rng_get_entropy(uint32_t types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint8_t *e = NULL; + uint32_t rq_size = 0; + uint32_t pool_size = 0; + uint32_t exceptions = 0; + 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 = cpu_spin_lock_xsave(&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_xrestore(&entropy_lock, 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..69f025e --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-tegra/conf.mk @@ -0,0 +1,168 @@ +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2020-2024, 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 + +# Default size for reserved virtual memory space, 32 MB +CFG_RESERVED_VASPACE_SIZE ?= (1024 * 1024 * 32) + +# Increase the mmap region to accommodate more +# device mappings in the global static map +CFG_MMAP_REGIONS ?= 24 + +# 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) + +# 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) + +$(call force,CFG_CORE_ASLR,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) + +ifneq (,$(findstring libnvdec,$(NV_NVDEC_PREBUILT))) +$(call force,CFG_TEGRA_PREBUILT_BINARY,y) +TEGRA_PREBUILT_BINARY = $(NV_NVDEC_PREBUILT) +endif + +# Leverage relocatable optee feature while not enable EL2 SPMC +$(call force,CFG_CORE_SEL2_SPMC,n) +$(call force,CFG_CORE_PHYS_RELOCATABLE,y) + +CFG_TEE_RAM_VA_SIZE ?= 0x400000 + +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 + +# Enable tegra crypto driver +$(call force,CFG_CRYPTO_DRIVER_TEGRA_SE,n) +ifeq ($(CFG_CRYPTO_DRIVER_TEGRA_SE),y) +# Enable tegra crypto HW accelerated hash driver +$(call force,CFG_CRYPTO_DRV_HASH_TEGRA_SE,y) +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) + +# Enable Pointer Authentication for core(S-EL1) and TA(S-EL0) +$(call force,CFG_CORE_PAUTH,y) +$(call force,CFG_TA_PAUTH,y) +endif + +# Enable generic cryptographic driver interface +# if tegra crypto driver is enabled +ifeq ($(CFG_CRYPTO_DRIVER_TEGRA_SE),y) +$(call force,CFG_CRYPTO_DRIVER,y) +ifeq ($(DEBUG),1) +# Enable the debug log for crypto driver +$(call force,CFG_CRYPTO_DRIVER_DEBUG,1) +else +$(call force,CFG_CRYPTO_DRIVER_DEBUG,0) +endif +ifeq ($(CFG_CRYPTO_DRV_HASH_TEGRA_SE),y) +$(call force,CFG_CRYPTO_DRV_HASH,y) +endif +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..354087c --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-tegra/main.c @@ -0,0 +1,49 @@ +/* + * 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 + +#if defined(PLATFORM_FLAVOR_t234) +#define TEGRA234_SCRATCH_BASE 0xc390000 +#define TEGRA234_SCRATCH_SIZE 0x1000 +register_phys_mem_pgdir(MEM_AREA_IO_SEC, TEGRA234_SCRATCH_BASE, TEGRA234_SCRATCH_SIZE); +#endif + +void plat_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..dedb116 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-tegra/platform_config.h @@ -0,0 +1,14 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2020-2021, NVIDIA CORPORATION. All rights reserved. + */ + +#ifndef PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#include + +#define MAX_XLAT_TABLES 8 + +#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..067c5d4 --- /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 boot_primary_init_intc + + 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..7ae0313 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-ti/main.c @@ -0,0 +1,126 @@ +// 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 + +#define PLAT_HW_UNIQUE_KEY_LENGTH 32 + +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 boot_primary_init_intc(void) +{ + gic_init(GICC_BASE, GICD_BASE); +} + +void boot_secondary_init_intc(void) +{ + gic_init_per_cpu(); +} + +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 plat_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..9224282 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-totalcompute/main.c @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +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 boot_primary_init_intc(void) +{ + gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICC_OFFSET); +} +#endif + +void plat_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..a01e8ff --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-uniphier/main.c @@ -0,0 +1,51 @@ +// 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 serial8250_uart_data console_data; + +void boot_primary_init_intc(void) +{ + gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET); +} + +void plat_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..b443269 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-versal/main.c @@ -0,0 +1,117 @@ +// 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 + +#define VERSAL_AHWROT_SECURED 0xA5A5A5A5 +#define VERSAL_SHWROT_SECURED 0x96969696 +#define VERSAL_AHWROT_REG 0x14C +#define VERSAL_SHWROT_REG 0x150 + +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 boot_primary_init_intc(void) +{ + gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET); +} + +void plat_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 __maybe_unused *ahwrot_str = "OFF"; + const char __maybe_unused *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..721f09e --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-vexpress/conf.mk @@ -0,0 +1,173 @@ +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 +supported-ta-targets ?= ta_arm64 ta_arm32 +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_HALT_CORES_ON_PANIC ?= y +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) +CFG_AUTO_MAX_PA_BITS ?= y +ifeq ($(CFG_SCMI_SCPFW),y) +$(call force,CFG_SCMI_SCPFW_PRODUCT,optee-fvp) +endif +ifeq ($(CFG_CORE_SEL1_SPMC),y) +CFG_CORE_ASYNC_NOTIF_GIC_INTID ?= 9 +endif +endif + +ifeq ($(PLATFORM_FLAVOR),juno) +CFG_HALT_CORES_ON_PANIC ?= y +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_HALT_CORES_ON_PANIC ?= y +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_CORE_HEAP_SIZE ?= 131072 +CFG_HALT_CORES_ON_PANIC ?= y +CFG_TEE_CORE_NB_CORE ?= 4 +CFG_AUTO_MAX_PA_BITS ?= y +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 +ifeq ($(CFG_CORE_SANITIZE_KADDRESS),y) +# See comment above +CFG_ASAN_SHADOW_OFFSET ?= 0xc6a71c0 +endif +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 + +CFG_CORE_ASYNC_NOTIF ?= y +ifeq ($(CFG_CORE_SEL1_SPMC),y) +CFG_CORE_ASYNC_NOTIF_GIC_INTID ?= 8 +else ifneq ($(CFG_CORE_SEL2_SPMC),y) +CFG_CORE_ASYNC_NOTIF_GIC_INTID ?= 219 +endif +endif #PLATFORM_FLAVOR==qemu_armv8a + +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..3f51872 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-vexpress/main.c @@ -0,0 +1,271 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016-2023, 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 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, GICC_BASE, GIC_CPU_REG_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICD_BASE, GIC_DIST_REG_SIZE); +#ifdef GIC_REDIST_BASE +register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_REDIST_BASE, GIC_REDIST_SIZE); +#endif + +void boot_primary_init_intc(void) +{ +#ifdef GIC_REDIST_BASE + gic_init_v3(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET, + GIC_REDIST_BASE); +#else + gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET); +#endif + if (IS_ENABLED(CFG_CORE_SEL1_SPMC) && + IS_ENABLED(CFG_CORE_ASYNC_NOTIF)) { + size_t it = CFG_CORE_ASYNC_NOTIF_GIC_INTID; + + if (it >= GIC_SGI_SEC_BASE && it <= GIC_SGI_SEC_MAX) + gic_init_donate_sgi_to_ns(it); + thread_spmc_set_async_notif_intid(it); + } +} + +void boot_secondary_init_intc(void) +{ + gic_init_per_cpu(); +} +#endif /*CFG_GIC*/ + +#ifdef CFG_CORE_HAFNIUM_INTC +void boot_primary_init_intc(void) +{ + hfic_init(); +} +#endif + +void plat_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)) && \ + !defined(CFG_SEMIHOSTING_CONSOLE) +/* + * 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 *hdl __unused) +{ + if (notif_async_is_started()) { + /* + * Asynchronous notifications are enabled, lets read from + * uart in the bottom half instead. + */ + console_data.chip.ops->rx_intr_disable(&console_data.chip); + 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(); + console_data.chip.ops->rx_intr_enable(&console_data.chip); + break; + case NOTIF_EVENT_STOPPED: + DMSG("Asynchronous notifications stopped"); + console_data.chip.ops->rx_intr_enable(&console_data.chip); + 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) +{ + TEE_Result res = TEE_ERROR_GENERIC; + bool have_itr_ctrl = console_data.chip.ops->rx_intr_enable && + console_data.chip.ops->rx_intr_disable; + + res = interrupt_add_handler_with_chip(interrupt_get_main_chip(), + &console_itr); + if (res) + return res; + + interrupt_enable(console_itr.chip, console_itr.it); + + if (IS_ENABLED(CFG_CORE_ASYNC_NOTIF) && have_itr_ctrl) + 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*/ + +#if defined(CFG_CALLOUT) && defined(IT_SEC_PHY_TIMER) && \ + !defined(CFG_CORE_SEL2_SPMC) +static TEE_Result init_callout_service(void) +{ + timer_init_callout_service(interrupt_get_main_chip(), IT_SEC_PHY_TIMER); + + return TEE_SUCCESS; +} + +nex_early_init(init_callout_service); +#endif 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..95142e6 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-vexpress/platform_config.h @@ -0,0 +1,158 @@ +/* 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 IT_SEC_PHY_TIMER 29 + +#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 +#ifdef CFG_ARM_GICV3 +#define GIC_REDIST_BASE 0x2F100000 +#define GIC_REDIST_SIZE 0x00100000 +#endif + +#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 +#ifdef CFG_ARM_GICV3 +#define GIC_REDIST_BASE 0x080A0000 +#define GIC_REDIST_SIZE 0x00F60000 +#endif + +#else +#error "Unknown platform flavor" +#endif + +#define GICD_BASE (GIC_BASE + GICD_OFFSET) +#define GICC_BASE (GIC_BASE + GICC_OFFSET) + +#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..5f71a05 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-zynq7k/main.c @@ -0,0 +1,217 @@ +// 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 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 plat_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 boot_primary_init_intc(void) +{ + gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET); +} + +void boot_secondary_init_intc(void) +{ + gic_init_per_cpu(); +} + +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..16d7d15 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-zynqmp/main.c @@ -0,0 +1,110 @@ +// 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 + +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 boot_primary_init_intc(void) +{ + gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET); +} + +void plat_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..cc9189e --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-zynqmp/platform_config.h @@ -0,0 +1,103 @@ +/* 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) || \ + 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..e493c78 --- /dev/null +++ b/optee/optee_os/core/arch/arm/tee/entry_fast.c @@ -0,0 +1,362 @@ +// 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) +{ +#ifdef ARM32 + TEE_Result ret = TEE_ERROR_NOT_SUPPORTED; + 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; + } + + 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; +#else + args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION; +#endif +} + +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; +} + +static void tee_entry_watchdog(struct thread_smc_args *args) +{ +#if defined(CFG_WDT_SM_HANDLER) + __wdt_sm_handler(args); +#else + args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION; +#endif +} + +/* + * 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; + + /* Watchdog entry if handler ID is defined in TOS range */ + case CFG_WDT_SM_HANDLER_ID: + tee_entry_watchdog(args); + 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..3b9e54a --- /dev/null +++ b/optee/optee_os/core/arch/riscv/include/kernel/delay_arch.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2022-2023 NXP + */ + +#ifndef __KERNEL_DELAY_ARCH_H +#define __KERNEL_DELAY_ARCH_H + +#include +#include + +static inline unsigned int delay_cnt_freq(void) +{ + return read_cntfrq(); +} + +static inline uint64_t delay_cnt_read(void) +{ + return read_time(); +} +#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..c48c7d9 --- /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..9dc873a --- /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 __KERNEL_TEE_L2CC_MUTEX_H +#define __KERNEL_TEE_L2CC_MUTEX_H + +#endif /* __KERNEL_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..3f43950 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/include/kernel/thread_arch.h @@ -0,0 +1,253 @@ +/* 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 +#ifdef CFG_FAULT_MITIGATION + struct ftmn_func_arg *ftmn_arg; +#endif +} THREAD_CORE_LOCAL_ALIGNED; + +struct thread_user_vfp_state { +}; + +struct thread_abi_args { + unsigned long a0; /* ABI 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 ie; +} __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 epc; + unsigned long status; + unsigned long ie; +}; + +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..edf27a4 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/include/kernel/thread_private_arch.h @@ -0,0 +1,125 @@ +/* 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); + +void thread_return_to_udomain(unsigned long arg0, unsigned long arg1, + unsigned long arg2, unsigned long arg3, + unsigned long arg4, unsigned long arg5); + +void __panic_at_abi_return(void); + +/* Helper function to prepare CSR status for exception return */ +unsigned long xstatus_for_xret(uint8_t pie, uint8_t pp); + +/* + * Assembly function as the first function in a thread. Handles a stdcall, + * a0-a3 holds the parameters. Hands over to __thread_std_abi_entry() when + * everything is set up and does some post processing once + * __thread_std_abi_entry() returns. + */ +void thread_std_abi_entry(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, + uint32_t a4, uint32_t a5); +uint32_t __thread_std_abi_entry(uint32_t a0, uint32_t a1, uint32_t a2, + uint32_t a3, uint32_t a4, uint32_t a5); +/* + * Called from assembly only, vector_fast_abi_entry(). Handles a fast ABI + * by dispatching it to the registered fast ABI handler. + */ +void thread_handle_fast_abi(struct thread_abi_args *args); + +/* + * Called from assembly only, vector_std_abi_entry(). Handles a std ABI by + * dispatching it to the registered std ABI handler. + */ +uint32_t thread_handle_std_abi(uint32_t a0, uint32_t a1, uint32_t a2, + uint32_t a3, uint32_t a4, uint32_t a5, + uint32_t a6, uint32_t a7); + +/* + * Private functions made available for thread_rv.S + */ +int thread_state_suspend(uint32_t flags, unsigned long 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_xstatus(uint32_t rv[THREAD_RPC_NUM_ARGS], unsigned long status); +void __thread_rpc(uint32_t rv[THREAD_RPC_NUM_ARGS]); + +static inline void thread_rpc(uint32_t rv[THREAD_RPC_NUM_ARGS]) +{ + __thread_rpc(rv); +} + +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/tlb_helpers.h b/optee/optee_os/core/arch/riscv/include/kernel/tlb_helpers.h new file mode 100644 index 0000000..d81766b --- /dev/null +++ b/optee/optee_os/core/arch/riscv/include/kernel/tlb_helpers.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2022 NXP + */ + +#ifndef __KERNEL_TLB_HELPERS_H +#define __KERNEL_TLB_HELPERS_H + +#ifndef __ASSEMBLER__ + +void tlbi_all(void); +void tlbi_va_allasid(vaddr_t va); +void tlbi_asid(unsigned long asid); +void tlbi_va_asid(vaddr_t va, uint32_t asid); + +#endif /*!__ASSEMBLER__*/ + +#endif /* __KERNEL_TLB_HELPERS_H */ diff --git a/optee/optee_os/core/arch/riscv/include/kernel/user_access_arch.h b/optee/optee_os/core/arch/riscv/include/kernel/user_access_arch.h new file mode 100644 index 0000000..2b9d563 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/include/kernel/user_access_arch.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2023 Andes Technology Corporation + * Copyright (c) 2023, Amazon.com Inc. or its affiliates. All rights Reserved. + */ + +#ifndef __KERNEL_USER_ACCESS_ARCH_H +#define __KERNEL_USER_ACCESS_ARCH_H + +#include + +#ifdef CFG_PAN +/* Enter a section where user mode access is temporarily enabled. */ +static inline void enter_user_access(void) +{ + set_csr(CSR_XSTATUS, CSR_XSTATUS_SUM); +} + +/* Exit from the section where user mode access was temporarily enabled. */ +static inline void exit_user_access(void) +{ + clear_csr(CSR_XSTATUS, CSR_XSTATUS_SUM); +} +#else +static inline void enter_user_access(void) {} +static inline void exit_user_access(void) {} +#endif /* CFG_PAN */ + +#endif /* __KERNEL_USER_ACCESS_ARCH_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..640296e --- /dev/null +++ b/optee/optee_os/core/arch/riscv/include/mm/core_mmu_arch.h @@ -0,0 +1,153 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2022-2023 NXP + */ +#ifndef __MM_CORE_MMU_ARCH_H +#define __MM_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) +#define RISCV_MMU_ASID_WIDTH 16 +#else +#define RISCV_MMU_MODE U(32) +#define RISCV_MMU_ASID_WIDTH 9 +#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 RISCV_MMU_MAX_PGTS 16 + +#define SMALL_PAGE_SHIFT U(12) + +/* + * Level 0, shift = 12, 4 KiB pages + * Level 1, shift = 21, 2 MiB pages (4 MiB pages in Sv32) + * Level 2, shift = 30, 1 GiB pages + * Level 3, shift = 39, 512 GiB pages + * Level 4, shift = 48, 256 TiB pages + */ +#define CORE_MMU_SHIFT_OF_LEVEL(level) (RISCV_PGLEVEL_BITS * \ + (level) + \ + RISCV_PGSHIFT) + +#define CORE_MMU_USER_CODE_SHIFT SMALL_PAGE_SHIFT +#define CORE_MMU_USER_PARAM_SHIFT SMALL_PAGE_SHIFT + +/* + * In all MMU modes, the CORE_MMU_PGDIR_LEVEL is always 0: + * Sv32: 4 KiB, 4 MiB + * Sv39: 4 KiB, 2 MiB, 1 GiB + * Sv48: 4 KiB, 2 MiB, 1 GiB, 512 GiB + * Sv57: 4 KiB, 2 MiB, 1 GiB, 512 GiB, 256 TiB + */ +#define CORE_MMU_PGDIR_LEVEL U(0) +#define CORE_MMU_PGDIR_SHIFT \ + CORE_MMU_SHIFT_OF_LEVEL(CORE_MMU_PGDIR_LEVEL + 1) + +#define CORE_MMU_BASE_TABLE_LEVEL (RISCV_PGLEVELS - 1) +#define CORE_MMU_BASE_TABLE_SHIFT \ + CORE_MMU_SHIFT_OF_LEVEL(CORE_MMU_BASE_TABLE_LEVEL) + +#ifndef __ASSEMBLER__ + +struct core_mmu_config { + unsigned long satp[CFG_TEE_CORE_NB_CORE]; + uint32_t map_offset; +}; + +struct core_mmu_user_map { + unsigned long 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; +} + +static inline bool core_mmu_level_in_range(unsigned int level) +{ + return level <= CORE_MMU_BASE_TABLE_LEVEL; +} +#endif /*__ASSEMBLER__*/ + +#endif /* __MM_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..76c655f --- /dev/null +++ b/optee/optee_os/core/arch/riscv/include/riscv.h @@ -0,0 +1,400 @@ +/* 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) + +/* 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_gp(void) +{ + unsigned long gp = 0; + + asm volatile("mv %0, gp" : "=&r"(gp)); + return gp; +} + +static inline __noprof unsigned long read_tp(void) +{ + unsigned long tp = 0; + + asm volatile("mv %0, tp" : "=&r"(tp)); + return tp; +} + +static inline __noprof unsigned long read_fp(void) +{ + unsigned long fp = 0; + + asm volatile ("mv %0, s0" : "=r" (fp)); + + return fp; +} + +static inline __noprof unsigned long read_pc(void) +{ + unsigned long pc = 0; + + asm volatile ("auipc %0, 0" : "=r" (pc)); + + return pc; +} + +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"); +} + +__noprof uint64_t read_time(void); + +static inline __noprof uint64_t barrier_read_counter_timer(void) +{ + mb(); /* Get timer value after pending operations have completed */ + return read_time(); +} + +static inline __noprof uint32_t read_cntfrq(void) +{ + return CFG_RISCV_MTIME_RATE; +} + +#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..ff40b87 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/include/riscv_macros.S @@ -0,0 +1,78 @@ +/* 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 + + .macro panic_at_abi_return +#if defined(CFG_TEE_CORE_DEBUG) + jal __panic_at_abi_return +#else + j . +#endif + .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..a2ae38c --- /dev/null +++ b/optee/optee_os/core/arch/riscv/include/sbi.h @@ -0,0 +1,71 @@ +/* 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 +#define SBI_EXT_BASE 0x10 +#define SBI_EXT_HSM 0x48534D +#define SBI_EXT_DBCN 0x4442434E +#define SBI_EXT_TEE 0x544545 + +#ifndef __ASSEMBLER__ + +/* SBI function IDs for Base extension */ +enum sbi_ext_base_fid { + SBI_EXT_BASE_GET_SPEC_VERSION = 0, + SBI_EXT_BASE_GET_IMP_ID, + SBI_EXT_BASE_GET_IMP_VERSION, + SBI_EXT_BASE_PROBE_EXT, + SBI_EXT_BASE_GET_MVENDORID, + SBI_EXT_BASE_GET_MARCHID, + SBI_EXT_BASE_GET_MIMPID, +}; + +/* SBI function IDs for HSM extension */ +enum sbi_ext_hsm_fid { + SBI_EXT_HSM_HART_START = 0, + SBI_EXT_HSM_HART_STOP, + SBI_EXT_HSM_HART_GET_STATUS, + SBI_EXT_HSM_HART_SUSPEND, +}; + +/* SBI function IDs for Debug Console extension */ +enum sbi_ext_dbcn_fid { + SBI_EXT_DBCN_CONSOLE_WRITE = 0, + SBI_EXT_DBCN_CONSOLE_READ = 1, + SBI_EXT_DBCN_CONSOLE_WRITE_BYTE = 2, +}; + +#include +#include +#include +#include +#include +#include + +int sbi_probe_extension(int extid); +void sbi_console_putchar(int ch); +int sbi_dbcn_write_byte(unsigned char ch); +int sbi_hsm_hart_start(uint32_t hartid, 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/include/tee/entry_fast.h b/optee/optee_os/core/arch/riscv/include/tee/entry_fast.h new file mode 100644 index 0000000..b3f1f81 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/include/tee/entry_fast.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2023 NXP + * 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_abi_args *args); +void tee_entry_get_api_uuid(struct thread_abi_args *args); +void tee_entry_get_api_revision(struct thread_abi_args *args); +void tee_entry_get_os_uuid(struct thread_abi_args *args); +void tee_entry_get_os_revision(struct thread_abi_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_abi_args *args); +void __tee_entry_fast(struct thread_abi_args *args); + +#endif /* __TEE_ENTRY_FAST_H */ diff --git a/optee/optee_os/core/arch/riscv/include/tee/optee_abi.h b/optee/optee_os/core/arch/riscv/include/tee/optee_abi.h new file mode 100644 index 0000000..8528b34 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/include/tee/optee_abi.h @@ -0,0 +1,705 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2023 NXP + * Copyright (c) 2015-2021, Linaro Limited + */ +#ifndef __TEE_OPTEE_ABI_H +#define __TEE_OPTEE_ABI_H + +#include + +/* + * This file should be kept in sync between secure domain and non-secure + * domain kernel driver. + * This file depends on optee_msg.h being included to expand the ABI id + * macros below. + */ + +#define OPTEE_ABI_32 U(0) +#define OPTEE_ABI_64 U(0x40000000) +#define OPTEE_ABI_FAST_CALL U(0x80000000) +#define OPTEE_ABI_STD_CALL U(0) + +#define OPTEE_ABI_OWNER_MASK U(0x3F) +#define OPTEE_ABI_OWNER_SHIFT U(24) + +#define OPTEE_ABI_FUNC_MASK U(0xFFFF) + +#define OPTEE_ABI_IS_FAST_CALL(abi_val) ((abi_val) & OPTEE_ABI_FAST_CALL) +#define OPTEE_ABI_IS_64(abi_val) ((abi_val) & OPTEE_ABI_64) +#define OPTEE_ABI_FUNC_NUM(abi_val) ((abi_val) & OPTEE_ABI_FUNC_MASK) +#define OPTEE_ABI_OWNER_NUM(abi_val) \ + (((abi_val) >> OPTEE_ABI_OWNER_SHIFT) & OPTEE_ABI_OWNER_MASK) + +#define OPTEE_ABI_CALL_VAL(type, calling_convention, owner, func_num) \ + ((type) | (calling_convention) | \ + (((owner) & OPTEE_ABI_OWNER_MASK) << \ + OPTEE_ABI_OWNER_SHIFT) |\ + ((func_num) & OPTEE_ABI_FUNC_MASK)) + +#define OPTEE_ABI_STD_CALL_VAL(func_num) \ + OPTEE_ABI_CALL_VAL(OPTEE_ABI_32, OPTEE_ABI_STD_CALL, \ + OPTEE_ABI_OWNER_TRUSTED_OS, (func_num)) +#define OPTEE_ABI_FAST_CALL_VAL(func_num) \ + OPTEE_ABI_CALL_VAL(OPTEE_ABI_32, OPTEE_ABI_FAST_CALL, \ + OPTEE_ABI_OWNER_TRUSTED_OS, (func_num)) + +#define OPTEE_ABI_OWNER_ARCH U(0) +#define OPTEE_ABI_OWNER_CPU U(1) +#define OPTEE_ABI_OWNER_SIP U(2) +#define OPTEE_ABI_OWNER_OEM U(3) +#define OPTEE_ABI_OWNER_STANDARD U(4) +#define OPTEE_ABI_OWNER_TRUSTED_APP U(48) +#define OPTEE_ABI_OWNER_TRUSTED_OS U(50) + +#define OPTEE_ABI_OWNER_TRUSTED_OS_OPTEED U(62) +#define OPTEE_ABI_OWNER_TRUSTED_OS_API U(63) + +/* + * Function specified by ABI Calling convention. + */ +#define OPTEE_ABI_FUNCID_CALLS_COUNT U(0xFF00) +#define OPTEE_ABI_CALLS_COUNT \ + OPTEE_ABI_CALL_VAL(OPTEE_ABI_32, OPTEE_ABI_FAST_CALL, \ + OPTEE_ABI_OWNER_TRUSTED_OS_API, \ + OPTEE_ABI_FUNCID_CALLS_COUNT) + +/* + * Normal cached memory (write-back), shareable for SMP systems and not + * shareable for UP systems. + */ +#define OPTEE_ABI_SHM_CACHED U(1) + +/* + * a0..a7 is used as register names in the descriptions below. + */ + +/* + * Function specified by ABI 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_ABI_FUNCID_CALLS_UID OPTEE_MSG_FUNCID_CALLS_UID +#define OPTEE_ABI_CALLS_UID \ + OPTEE_ABI_CALL_VAL(OPTEE_ABI_32, OPTEE_ABI_FAST_CALL, \ + OPTEE_ABI_OWNER_TRUSTED_OS_API, \ + OPTEE_ABI_FUNCID_CALLS_UID) + +/* + * Function specified by ABI 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_ABI_FUNCID_CALLS_REVISION OPTEE_MSG_FUNCID_CALLS_REVISION +#define OPTEE_ABI_CALLS_REVISION \ + OPTEE_ABI_CALL_VAL(OPTEE_ABI_32, OPTEE_ABI_FAST_CALL, \ + OPTEE_ABI_OWNER_TRUSTED_OS_API, \ + OPTEE_ABI_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_ABI_CALLS_UID + * described above. + */ +#define OPTEE_ABI_FUNCID_GET_OS_UUID OPTEE_MSG_FUNCID_GET_OS_UUID +#define OPTEE_ABI_CALL_GET_OS_UUID \ + OPTEE_ABI_FAST_CALL_VAL(OPTEE_ABI_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_ABI_CALLS_REVISION + * described above. May optionally return a 32-bit build identifier in a2, + * with zero meaning unspecified. + */ +#define OPTEE_ABI_FUNCID_GET_OS_REVISION OPTEE_MSG_FUNCID_GET_OS_REVISION +#define OPTEE_ABI_CALL_GET_OS_REVISION \ + OPTEE_ABI_FAST_CALL_VAL(OPTEE_ABI_FUNCID_GET_OS_REVISION) + +/* + * Call with struct optee_msg_arg as argument + * + * When called with OPTEE_ABI_CALL_WITH_RPC_ARG or + * OPTEE_ABI_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_ABI_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_ABI_CALL_WITH_ARG and + * OPTEE_ABI_CALL_WITH_RPC_ARG: + * a0 ABI Function ID, OPTEE_ABI_CALL_WITH_ARG or OPTEE_ABI_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_ABI_SHM_* + * a4-6 Not used + * a7 Hypervisor Client ID register + * + * Call register usage, OPTEE_ABI_CALL_WITH_REGD_ARG: + * a0 ABI Function ID, OPTEE_ABI_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_ABI_RETURN_* + * a1-3 Not used + * a4-7 Preserved + * + * OPTEE_ABI_RETURN_ETHREAD_LIMIT return register usage: + * a0 Return value, OPTEE_ABI_RETURN_ETHREAD_LIMIT + * a1-3 Preserved + * a4-7 Preserved + * + * RPC return register usage: + * a0 Return value, OPTEE_ABI_RETURN_IS_RPC(val) + * a1-2 RPC parameters + * a3-7 Resume information, must be preserved + * + * Possible return values: + * OPTEE_ABI_RETURN_UNKNOWN_FUNCTION Trusted OS does not recognize this + * function. + * OPTEE_ABI_RETURN_OK Call completed, result updated in + * the previously supplied struct + * optee_msg_arg. + * OPTEE_ABI_RETURN_ETHREAD_LIMIT Number of Trusted OS threads exceeded, + * try again later. + * OPTEE_ABI_RETURN_EBADADDR Bad physical pointer to struct + * optee_msg_arg. + * OPTEE_ABI_RETURN_EBADCMD Bad/unknown cmd in struct optee_msg_arg + * OPTEE_ABI_RETURN_IS_RPC() Call suspended by RPC call to normal + * world. + */ +#define OPTEE_ABI_FUNCID_CALL_WITH_ARG OPTEE_MSG_FUNCID_CALL_WITH_ARG +#define OPTEE_ABI_CALL_WITH_ARG \ + OPTEE_ABI_STD_CALL_VAL(OPTEE_ABI_FUNCID_CALL_WITH_ARG) +#define OPTEE_ABI_CALL_WITH_RPC_ARG \ + OPTEE_ABI_STD_CALL_VAL(OPTEE_ABI_FUNCID_CALL_WITH_RPC_ARG) +#define OPTEE_ABI_CALL_WITH_REGD_ARG \ + OPTEE_ABI_STD_CALL_VAL(OPTEE_ABI_FUNCID_CALL_WITH_REGD_ARG) + +/* + * Get Shared Memory Config + * + * Returns the Secure/Non-secure shared memory config. + * + * Call register usage: + * a0 ABI Function ID, OPTEE_ABI_GET_SHM_CONFIG + * a1-6 Not used + * a7 Hypervisor Client ID register + * + * Have config return register usage: + * a0 OPTEE_ABI_RETURN_OK + * a1 Physical address of start of SHM + * a2 Size of SHM + * a3 Cache settings of memory, as defined by the + * OPTEE_ABI_SHM_* values above + * a4-7 Preserved + * + * Not available register usage: + * a0 OPTEE_ABI_RETURN_ENOTAVAIL + * a1-3 Not used + * a4-7 Preserved + */ +#define OPTEE_ABI_FUNCID_GET_SHM_CONFIG 7 +#define OPTEE_ABI_GET_SHM_CONFIG \ + OPTEE_ABI_FAST_CALL_VAL(OPTEE_ABI_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 ABI Function ID, OPTEE_ABI_L2CC_MUTEX + * a1 OPTEE_ABI_L2CC_MUTEX_GET_ADDR Get physical address of mutex + * OPTEE_ABI_L2CC_MUTEX_SET_ADDR Set physical address of mutex + * OPTEE_ABI_L2CC_MUTEX_ENABLE Enable usage of mutex + * OPTEE_ABI_L2CC_MUTEX_DISABLE Disable usage of mutex + * a2 if a1 == OPTEE_ABI_L2CC_MUTEX_SET_ADDR, upper 32bit of a 64bit + * physical address of mutex + * a3 if a1 == OPTEE_ABI_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_ABI_RETURN_OK + * a1 Preserved + * a2 if a1 == OPTEE_ABI_L2CC_MUTEX_GET_ADDR, upper 32bit of a 64bit + * physical address of mutex + * a3 if a1 == OPTEE_ABI_L2CC_MUTEX_GET_ADDR, lower 32bit of a 64bit + * physical address of mutex + * a3-7 Preserved + * + * Error return register usage: + * a0 OPTEE_ABI_RETURN_ENOTAVAIL Physical address not available + * OPTEE_ABI_RETURN_EBADADDR Bad supplied physical address + * OPTEE_ABI_RETURN_EBADCMD Unsupported value in a1 + * a1-7 Preserved + */ +#define OPTEE_ABI_L2CC_MUTEX_GET_ADDR U(0) +#define OPTEE_ABI_L2CC_MUTEX_SET_ADDR U(1) +#define OPTEE_ABI_L2CC_MUTEX_ENABLE U(2) +#define OPTEE_ABI_L2CC_MUTEX_DISABLE U(3) +#define OPTEE_ABI_FUNCID_L2CC_MUTEX U(8) +#define OPTEE_ABI_L2CC_MUTEX \ + OPTEE_ABI_FAST_CALL_VAL(OPTEE_ABI_FUNCID_L2CC_MUTEX) + +/* + * Exchanges capabilities between normal world and secure world + * + * Call register usage: + * a0 ABI Function ID, OPTEE_ABI_EXCHANGE_CAPABILITIES + * a1 bitfield of normal world capabilities OPTEE_ABI_NSEC_CAP_* + * a2-6 Not used + * a7 Hypervisor Client ID register + * + * Normal return register usage: + * a0 OPTEE_ABI_RETURN_OK + * a1 bitfield of secure world capabilities OPTEE_ABI_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_ABI_CALL_WITH_ARG + * Bit[31:8]: Reserved (MBZ) + * a3-7 Preserved + * + * Error return register usage: + * a0 OPTEE_ABI_RETURN_ENOTAVAIL, can't use the capabilities from normal world + * a1 bitfield of secure world capabilities OPTEE_ABI_SEC_CAP_* + * a2-7 Preserved + */ +/* Normal world works as a uniprocessor system */ +#define OPTEE_ABI_NSEC_CAP_UNIPROCESSOR BIT(0) +/* Secure world has reserved shared memory for normal world to use */ +#define OPTEE_ABI_SEC_CAP_HAVE_RESERVED_SHM BIT(0) +/* Secure world can communicate via previously unregistered shared memory */ +#define OPTEE_ABI_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_ABI_SEC_CAP_DYNAMIC_SHM BIT(2) +/* Secure world is built with virtualization support */ +#define OPTEE_ABI_SEC_CAP_VIRTUALIZATION BIT(3) +/* Secure world supports Shared Memory with a NULL reference */ +#define OPTEE_ABI_SEC_CAP_MEMREF_NULL BIT(4) +/* Secure world supports asynchronous notification of normal world */ +#define OPTEE_ABI_SEC_CAP_ASYNC_NOTIF BIT(5) +/* Secure world supports pre-allocating RPC arg struct */ +#define OPTEE_ABI_SEC_CAP_RPC_ARG BIT(6) + +#define OPTEE_ABI_FUNCID_EXCHANGE_CAPABILITIES U(9) +#define OPTEE_ABI_EXCHANGE_CAPABILITIES \ + OPTEE_ABI_FAST_CALL_VAL(OPTEE_ABI_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_ABI_RETURN_ENOTAVAIL. + * + * Call register usage: + * a0 ABI Function ID, OPTEE_ABI_DISABLE_SHM_CACHE + * a1-6 Not used + * a7 Hypervisor Client ID register + * + * Normal return register usage: + * a0 OPTEE_ABI_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_ABI_RETURN_ENOTAVAIL + * a1-7 Preserved + * + * Not idle return register usage: + * a0 OPTEE_ABI_RETURN_EBUSY + * a1-7 Preserved + */ +#define OPTEE_ABI_FUNCID_DISABLE_SHM_CACHE U(10) +#define OPTEE_ABI_DISABLE_SHM_CACHE \ + OPTEE_ABI_FAST_CALL_VAL(OPTEE_ABI_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_ABI_RETURN_OK and the cache is enabled. If + * secure world isn't idle OPTEE_ABI_RETURN_EBUSY is returned. + * + * Call register usage: + * a0 ABI Function ID, OPTEE_ABI_ENABLE_SHM_CACHE + * a1-6 Not used + * a7 Hypervisor Client ID register + * + * Normal return register usage: + * a0 OPTEE_ABI_RETURN_OK + * a1-7 Preserved + * + * Not idle return register usage: + * a0 OPTEE_ABI_RETURN_EBUSY + * a1-7 Preserved + */ +#define OPTEE_ABI_FUNCID_ENABLE_SHM_CACHE U(11) +#define OPTEE_ABI_ENABLE_SHM_CACHE \ + OPTEE_ABI_FAST_CALL_VAL(OPTEE_ABI_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 ABI Function ID, OPTEE_ABI_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_ABI_RETURN_OK + * a1-7 Preserved + * + * Error return: + * a0 OPTEE_ABI_RETURN_EBADCMD Core index out of range + * a1-7 Preserved + * + * Not idle return register usage: + * a0 OPTEE_ABI_RETURN_EBUSY + * a1-7 Preserved + */ +#define OPTEE_ABI_FUNCID_BOOT_SECONDARY U(12) +#define OPTEE_ABI_BOOT_SECONDARY \ + OPTEE_ABI_FAST_CALL_VAL(OPTEE_ABI_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 ABI Function ID, OPTEE_ABI_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_ABI_RETURN_OK + * a1-7 Preserved + * + * Error return: + * a0 OPTEE_ABI_RETURN_ENOTAVAIL OP-TEE have no resources for + * another VM + * a1-7 Preserved + * + */ +#define OPTEE_ABI_FUNCID_VM_CREATED U(13) +#define OPTEE_ABI_VM_CREATED \ + OPTEE_ABI_FAST_CALL_VAL(OPTEE_ABI_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 ABI Function ID, OPTEE_ABI_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_ABI_RETURN_OK + * a1-7 Preserved + * + */ +#define OPTEE_ABI_FUNCID_VM_DESTROYED U(14) +#define OPTEE_ABI_VM_DESTROYED \ + OPTEE_ABI_FAST_CALL_VAL(OPTEE_ABI_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_ABI_RETURN_ETHREAD_LIMIT. + * + * Call requests usage: + * a0 ABI Function ID, OPTEE_ABI_GET_THREAD_COUNT + * a1-6 Not used + * a7 Hypervisor Client ID register + * + * Normal return register usage: + * a0 OPTEE_ABI_RETURN_OK + * a1 Number of threads + * a2-7 Preserved + * + * Error return: + * a0 OPTEE_ABI_RETURN_UNKNOWN_FUNCTION Requested call is not implemented + * a1-7 Preserved + */ +#define OPTEE_ABI_FUNCID_GET_THREAD_COUNT U(15) +#define OPTEE_ABI_GET_THREAD_COUNT \ + OPTEE_ABI_FAST_CALL_VAL(OPTEE_ABI_FUNCID_GET_THREAD_COUNT) + +/* + * Inform OP-TEE that normal world is able to receive asynchronous + * notifications. + * + * Call requests usage: + * a0 ABI Function ID, OPTEE_ABI_ENABLE_ASYNC_NOTIF + * a1-6 Not used + * a7 Hypervisor Client ID register + * + * Normal return register usage: + * a0 OPTEE_ABI_RETURN_OK + * a1-7 Preserved + * + * Not supported return register usage: + * a0 OPTEE_ABI_RETURN_ENOTAVAIL + * a1-7 Preserved + */ +#define OPTEE_ABI_FUNCID_ENABLE_ASYNC_NOTIF 16 +#define OPTEE_ABI_ENABLE_ASYNC_NOTIF \ + OPTEE_ABI_FAST_CALL_VAL(OPTEE_ABI_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 ABI Function ID, OPTEE_ABI_GET_ASYNC_NOTIF_VALUE + * a1-6 Not used + * a7 Hypervisor Client ID register + * + * Normal return register usage: + * a0 OPTEE_ABI_RETURN_OK + * a1 value + * a2 Bit[0]: OPTEE_ABI_ASYNC_NOTIF_VALUE_VALID if the value in a1 is + * valid, else 0 if no values were pending + * a2 Bit[1]: OPTEE_ABI_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_ABI_RETURN_ENOTAVAIL + * a1-7 Preserved + */ +#define OPTEE_ABI_ASYNC_NOTIF_VALID BIT(0) +#define OPTEE_ABI_ASYNC_NOTIF_PENDING BIT(1) + +/* + * Notification that OP-TEE expects a yielding call to do some bottom half + * work in a driver. + */ +#define OPTEE_ABI_ASYNC_NOTIF_VALUE_DO_BOTTOM_HALF 0 + +#define OPTEE_ABI_FUNCID_GET_ASYNC_NOTIF_VALUE 17 +#define OPTEE_ABI_GET_ASYNC_NOTIF_VALUE \ + OPTEE_ABI_FAST_CALL_VAL(OPTEE_ABI_FUNCID_GET_ASYNC_NOTIF_VALUE) + +/* See OPTEE_ABI_CALL_WITH_RPC_ARG above */ +#define OPTEE_ABI_FUNCID_CALL_WITH_RPC_ARG U(18) + +/* See OPTEE_ABI_CALL_WITH_REGD_ARG above */ +#define OPTEE_ABI_FUNCID_CALL_WITH_REGD_ARG U(19) + +/* + * Resume from RPC (for example after processing a foreign interrupt) + * + * Call register usage: + * a0 ABI Function ID, OPTEE_ABI_CALL_RETURN_FROM_RPC + * a1-3 Value of a1-3 when OPTEE_ABI_CALL_WITH_ARG returned + * OPTEE_ABI_RETURN_RPC in a0 + * + * Return register usage is the same as for OPTEE_ABI_*CALL_WITH_ARG above. + * + * Possible return values + * OPTEE_ABI_RETURN_UNKNOWN_FUNCTION Trusted OS does not recognize this + * function. + * OPTEE_ABI_RETURN_OK Original call completed, result + * updated in the previously supplied. + * struct optee_msg_arg + * OPTEE_ABI_RETURN_RPC Call suspended by RPC call to normal + * world. + * OPTEE_ABI_RETURN_ERESUME Resume failed, the opaque resume + * information was corrupt. + */ +#define OPTEE_ABI_FUNCID_RETURN_FROM_RPC U(3) +#define OPTEE_ABI_CALL_RETURN_FROM_RPC \ + OPTEE_ABI_STD_CALL_VAL(OPTEE_ABI_FUNCID_RETURN_FROM_RPC) + +#define OPTEE_ABI_RETURN_RPC_PREFIX_MASK U(0xFFFF0000) +#define OPTEE_ABI_RETURN_RPC_PREFIX U(0xFFFF0000) +#define OPTEE_ABI_RETURN_RPC_FUNC_MASK U(0x0000FFFF) + +#define OPTEE_ABI_RETURN_GET_RPC_FUNC(ret) \ + ((ret) & OPTEE_ABI_RETURN_RPC_FUNC_MASK) + +#define OPTEE_ABI_RPC_VAL(func) ((func) | OPTEE_ABI_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_ABI_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 ABI Function ID, OPTEE_ABI_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_ABI_RPC_FUNC_ALLOC U(0) +#define OPTEE_ABI_RETURN_RPC_ALLOC \ + OPTEE_ABI_RPC_VAL(OPTEE_ABI_RPC_FUNC_ALLOC) + +/* + * Free memory previously allocated by OPTEE_ABI_RETURN_RPC_ALLOC + * + * "Call" register usage: + * a0 This value, OPTEE_ABI_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 ABI Function ID, OPTEE_ABI_CALL_RETURN_FROM_RPC. + * a1-2 Not used + * a3-7 Preserved + */ +#define OPTEE_ABI_RPC_FUNC_FREE U(2) +#define OPTEE_ABI_RETURN_RPC_FREE \ + OPTEE_ABI_RPC_VAL(OPTEE_ABI_RPC_FUNC_FREE) + +/* + * Deliver a foreign interrupt in normal world. + * + * "Call" register usage: + * a0 OPTEE_ABI_RETURN_RPC_FOREIGN_INTR + * a1-7 Resume information, must be preserved + * + * "Return" register usage: + * a0 ABI Function ID, OPTEE_ABI_CALL_RETURN_FROM_RPC. + * a1-7 Preserved + */ +#define OPTEE_ABI_RPC_FUNC_FOREIGN_INTR U(4) +#define OPTEE_ABI_RETURN_RPC_FOREIGN_INTR \ + OPTEE_ABI_RPC_VAL(OPTEE_ABI_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_ABI_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 ABI Function ID, OPTEE_ABI_CALL_RETURN_FROM_RPC. + * a1-2 Not used + * a3-7 Preserved + */ +#define OPTEE_ABI_RPC_FUNC_CMD U(5) +#define OPTEE_ABI_RETURN_RPC_CMD \ + OPTEE_ABI_RPC_VAL(OPTEE_ABI_RPC_FUNC_CMD) + +/* Returned in a0 */ +#define OPTEE_ABI_RETURN_UNKNOWN_FUNCTION U(0xFFFFFFFF) + +/* Returned in a0 only from Trusted OS functions */ +#define OPTEE_ABI_RETURN_OK U(0x0) +#define OPTEE_ABI_RETURN_ETHREAD_LIMIT U(0x1) +#define OPTEE_ABI_RETURN_EBUSY U(0x2) +#define OPTEE_ABI_RETURN_ERESUME U(0x3) +#define OPTEE_ABI_RETURN_EBADADDR U(0x4) +#define OPTEE_ABI_RETURN_EBADCMD U(0x5) +#define OPTEE_ABI_RETURN_ENOMEM U(0x6) +#define OPTEE_ABI_RETURN_ENOTAVAIL U(0x7) +#define OPTEE_ABI_RETURN_IS_RPC(_ret) ({\ + typeof(_ret) (ret) = (_ret); \ + (((ret) != OPTEE_ABI_RETURN_UNKNOWN_FUNCTION) && \ + ((((ret) & OPTEE_ABI_RETURN_RPC_PREFIX_MASK) == \ + OPTEE_ABI_RETURN_RPC_PREFIX))); }) + +#endif /* __TEE_OPTEE_ABI_H */ diff --git a/optee/optee_os/core/arch/riscv/include/tee/teeabi_opteed.h b/optee/optee_os/core/arch/riscv/include/tee/teeabi_opteed.h new file mode 100644 index 0000000..05c6aab --- /dev/null +++ b/optee/optee_os/core/arch/riscv/include/tee/teeabi_opteed.h @@ -0,0 +1,111 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2023 NXP + * Copyright (c) 2014, Linaro Limited + */ + +#ifndef __TEE_TEEABI_OPTEED_H +#define __TEE_TEEABI_OPTEED_H + +/* + * This file specify ABI function IDs used when returning from TEE to the + * secure monitor if applicable. + */ + +/* + * Issued when returning from initial entry. + * + * Register usage: + * a0 ABI Function ID, TEEABI_OPTEED_RETURN_ENTRY_DONE + * a1 Pointer to entry vector + */ +#define TEEABI_OPTEED_FUNCID_RETURN_ENTRY_DONE 0 +#define TEEABI_OPTEED_RETURN_ENTRY_DONE \ + TEEABI_OPTEED_RV(TEEABI_OPTEED_FUNCID_RETURN_ENTRY_DONE) + +/* + * Issued when returning from "cpu_on" vector + * + * Register usage: + * a0 ABI Function ID, TEEABI_OPTEED_RETURN_ON_DONE + * a1 0 on success and anything else to indicate error condition + */ +#define TEEABI_OPTEED_FUNCID_RETURN_ON_DONE 1 +#define TEEABI_OPTEED_RETURN_ON_DONE \ + TEEABI_OPTEED_RV(TEEABI_OPTEED_FUNCID_RETURN_ON_DONE) + +/* + * Issued when returning from "cpu_off" vector + * + * Register usage: + * a0 ABI Function ID, TEEABI_OPTEED_RETURN_OFF_DONE + * a1 0 on success and anything else to indicate error condition + */ +#define TEEABI_OPTEED_FUNCID_RETURN_OFF_DONE 2 +#define TEEABI_OPTEED_RETURN_OFF_DONE \ + TEEABI_OPTEED_RV(TEEABI_OPTEED_FUNCID_RETURN_OFF_DONE) + +/* + * Issued when returning from "cpu_suspend" vector + * + * Register usage: + * a0 ABI Function ID, TEEABI_OPTEED_RETURN_SUSPEND_DONE + * a1 0 on success and anything else to indicate error condition + */ +#define TEEABI_OPTEED_FUNCID_RETURN_SUSPEND_DONE 3 +#define TEEABI_OPTEED_RETURN_SUSPEND_DONE \ + TEEABI_OPTEED_RV(TEEABI_OPTEED_FUNCID_RETURN_SUSPEND_DONE) + +/* + * Issued when returning from "cpu_resume" vector + * + * Register usage: + * a0 ABI Function ID, TEEABI_OPTEED_RETURN_RESUME_DONE + * a1 0 on success and anything else to indicate error condition + */ +#define TEEABI_OPTEED_FUNCID_RETURN_RESUME_DONE 4 +#define TEEABI_OPTEED_RETURN_RESUME_DONE \ + TEEABI_OPTEED_RV(TEEABI_OPTEED_FUNCID_RETURN_RESUME_DONE) + +/* + * Issued when returning from "std_abi" or "fast_abi" vector + * + * Register usage: + * a0 ABI Function ID, TEEABI_OPTEED_RETURN_CALL_DONE + * a1-4 Return value 0-3 which will passed to non-secure domain in a0-3 + */ +#define TEEABI_OPTEED_FUNCID_RETURN_CALL_DONE 5 +#define TEEABI_OPTEED_RETURN_CALL_DONE \ + TEEABI_OPTEED_RV(TEEABI_OPTEED_FUNCID_RETURN_CALL_DONE) + +/* + * Issued when returning from "fiq" vector + * + * Register usage: + * a0 ABI Function ID, TEEABI_OPTEED_RETURN_FIQ_DONE + */ +#define TEEABI_OPTEED_FUNCID_RETURN_FIQ_DONE 6 +#define TEEABI_OPTEED_RETURN_FIQ_DONE \ + TEEABI_OPTEED_RV(TEEABI_OPTEED_FUNCID_RETURN_FIQ_DONE) + +/* + * Issued when returning from "system_off" vector + * + * Register usage: + * a0 ABI Function ID, TEEABI_OPTEED_RETURN_SYSTEM_OFF_DONE + */ +#define TEEABI_OPTEED_FUNCID_RETURN_SYSTEM_OFF_DONE 7 +#define TEEABI_OPTEED_RETURN_SYSTEM_OFF_DONE \ + TEEABI_OPTEED_RV(TEEABI_OPTEED_FUNCID_RETURN_SYSTEM_OFF_DONE) + +/* + * Issued when returning from "system_reset" vector + * + * Register usage: + * a0 ABI Function ID, TEEABI_OPTEED_RETURN_SYSTEM_RESET_DONE + */ +#define TEEABI_OPTEED_FUNCID_RETURN_SYSTEM_RESET_DONE 8 +#define TEEABI_OPTEED_RETURN_SYSTEM_RESET_DONE \ + TEEABI_OPTEED_RV(TEEABI_OPTEED_FUNCID_RETURN_SYSTEM_RESET_DONE) + +#endif /*__TEE_TEEABI_OPTEED_H*/ diff --git a/optee/optee_os/core/arch/riscv/include/tee/teeabi_opteed_macros.h b/optee/optee_os/core/arch/riscv/include/tee/teeabi_opteed_macros.h new file mode 100644 index 0000000..911821d --- /dev/null +++ b/optee/optee_os/core/arch/riscv/include/tee/teeabi_opteed_macros.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2023 NXP + * Copyright (c) 2014, Linaro Limited + */ + +#ifndef __TEE_TEEABI_OPTEED_MACROS_H +#define __TEE_TEEABI_OPTEED_MACROS_H + +#define TEEABI_OPTEED_RV(func_num) \ + OPTEE_ABI_CALL_VAL(OPTEE_ABI_32, OPTEE_ABI_FAST_CALL, \ + OPTEE_ABI_OWNER_TRUSTED_OS_OPTEED, (func_num)) + +#endif /*__TEE_TEEABI_OPTEED_MACROS_H*/ 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..0b9c539 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/kernel/abort.c @@ -0,0 +1,394 @@ +// 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_riscv state = { + .fp = ai->regs->s0, + .pc = ai->regs->epc, + }; + + print_stack_riscv(&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 = xstatus_for_xret(true, PRV_S); + + 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..546ea68 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/kernel/arch_scall.c @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2023 Andes Technology Corporation + * Copyright 2022-2023 NXP + * Copyright (c) 2014-2022, Linaro Limited + * Copyright (c) 2020, Arm Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TA_CONTEXT_MAX_SIZE (RISCV_XLEN_BYTES * 32) + +#ifdef CFG_UNWIND + +/* Get register values pushed onto the stack by _utee_panic() */ +static void save_panic_regs_rv_ta(struct thread_specific_data *tsd, + unsigned long *pushed) +{ + TEE_Result res = TEE_SUCCESS; + unsigned long s0 = 0; + unsigned long epc = 0; +#if defined(RV32) + unsigned long *stack_s0 = &pushed[2]; + unsigned long *stack_epc = &pushed[3]; +#elif defined(RV64) + unsigned long *stack_s0 = &pushed[0]; + unsigned long *stack_epc = &pushed[1]; +#endif + + res = GET_USER_SCALAR(s0, stack_s0); + if (res) + s0 = 0; + + res = GET_USER_SCALAR(epc, stack_epc); + if (res) + epc = 0; + + tsd->abort_regs = (struct thread_abort_regs){ + .sp = (unsigned long)pushed, + .s0 = s0, + .epc = epc, + }; +} + +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..6dfdfca --- /dev/null +++ b/optee/optee_os/core/arch/riscv/kernel/asm-defines.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2022-2023 NXP + */ + +#include +#include +#include +#include +#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_X0, offsetof(struct thread_core_local, x[0])); + DEFINE(THREAD_CORE_LOCAL_X1, offsetof(struct thread_core_local, x[1])); + + 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_EPC, offsetof(struct thread_ctx_regs, epc)); + DEFINE(THREAD_CTX_REG_IE, offsetof(struct thread_ctx_regs, ie)); + 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_X4, + offsetof(struct thread_user_mode_rec, x[3])); + 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_S0, offsetof(struct thread_trap_regs, s0)); + 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_REG_IE, offsetof(struct thread_trap_regs, ie)); + 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)); + + /* struct core_mmu_config */ + DEFINE(CORE_MMU_CONFIG_SIZE, sizeof(struct core_mmu_config)); + DEFINE(CORE_MMU_CONFIG_SATP, + offsetof(struct core_mmu_config, satp[0])); + DEFINE(CORE_MMU_CONFIG_SATP_SIZE, sizeof(unsigned long)); + + /* struct thread_abi_args */ + DEFINE(THREAD_ABI_ARGS_A0, offsetof(struct thread_abi_args, a0)); + DEFINE(THREAD_ABI_ARGS_SIZE, sizeof(struct thread_abi_args)); +} 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..f2b3c1c --- /dev/null +++ b/optee/optee_os/core/arch/riscv/kernel/boot.c @@ -0,0 +1,181 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2023 Andes Technology Corporation + * Copyright 2022-2023 NXP + */ + +#include +#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]; + +#if defined(CFG_DT) +static int mark_tddram_as_reserved(struct dt_descriptor *dt) +{ + return add_res_mem_dt_node(dt, "optee_core", CFG_TDDRAM_START, + CFG_TDDRAM_SIZE); +} + +static void update_external_dt(void) +{ + struct dt_descriptor *dt = get_external_dt_desc(); + + if (!dt || !dt->blob) + return; + + if (mark_tddram_as_reserved(dt)) + panic("Failed to config secure memory"); +} +#else /*CFG_DT*/ +static void update_external_dt(void) +{ +} +#endif /*!CFG_DT*/ + +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_hsm_hart_start(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 boot_primary_init_intc(void) +{ +} + +/* May be overridden in plat-$(PLATFORM)/main.c */ +__weak void boot_secondary_init_intc(void) +{ +} + +void boot_init_primary_early(void) +{ + unsigned long e = PADDR_INVALID; + + init_primary(e); +} + +void boot_init_primary_late(unsigned long fdt, + unsigned long tos_fw_config __unused) +{ + init_external_dt(fdt, CFG_DTB_MAX_SIZE); + update_external_dt(); + + IMSG("OP-TEE version: %s", core_v_str); + if (IS_ENABLED(CFG_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"); + boot_primary_init_intc(); + 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); + boot_secondary_init_intc(); + + 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..5251a00 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/kernel/entry.S @@ -0,0 +1,299 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2023 Andes Technology Corporation + * Copyright 2022-2023 NXP + */ + +#include +#include +#include +#include +#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 + /* + * a0 = hartid + * a1 = address of boot_mmu_config.satp[0] + * a2 = size of CSR SATP + * + * This hart's SATP is of value (a1 + (a0 * a2)). + */ + csrr a0, CSR_XSCRATCH + la a1, boot_mmu_config + addi a1, a1, CORE_MMU_CONFIG_SATP + li a2, CORE_MMU_CONFIG_SATP_SIZE + mul a0, a0, a2 + add a1, a1, a0 + LDR a2, 0(a1) + csrw CSR_SATP, a2 + 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 , : + /* + * Register usage: + * a0 - if non-NULL holds the hart ID + * a1 - if non-NULL holds the system DTB address + * + * CSR_XSCRATCH - saved a0 + * s1 - saved a1 + */ +.option push +.option norelax + la gp, __global_pointer$ +.option pop +#ifdef CFG_RISCV_M_MODE + csrr a0, CSR_MHARTID +#endif + csrw CSR_XSCRATCH, a0 +#if defined(CFG_DT_ADDR) + li s1, CFG_DT_ADDR +#else + mv s1, a1 /* Save device tree address into s1 */ +#endif + + /* Only first hart who wins lottery runs the primary boot sequence. */ + la a3, hart_lottery + li a2, 1 + amoadd.w a3, a2, (a3) + bnez a3, 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 + + /* + * Before entering boot_init_primary_late(), we do these two steps: + * 1. Save current sp to s2, and set sp as threads[0].stack_va_end + * 2. Clear the flag which indicates usage of the temporary stack in the + * current hart's thread_core_local structure. + */ + mv s2, sp + la a0, threads + LDR a0, THREAD_CTX_STACK_VA_END(a0) + mv sp, a0 + jal thread_get_core_local + mv s3, a0 + STR x0, THREAD_CORE_LOCAL_FLAGS(s3) + + mv a0, s1 /* s1 contains saved device tree address */ + mv a1, x0 /* unused */ + jal boot_init_primary_late + + /* + * After returning from boot_init_primary_late(), the flag and sp are + * restored. + */ + li a0, THREAD_CLF_TMP + STR a0, THREAD_CORE_LOCAL_FLAGS(s3) + mv sp, s2 + + cpu_is_ready + flush_cpu_semaphores + wait_secondary + + jal thread_clr_boot_thread + + li a0, TEEABI_OPTEED_RETURN_ENTRY_DONE + la a1, thread_vector_table + j thread_return_to_udomain +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 +#ifdef CFG_RISCV_WITH_M_MODE_SM + /* Return to untrusted domain */ + li a0, TEEABI_OPTEED_RETURN_ON_DONE + j thread_return_to_udomain +#endif + j . +END_FUNC reset_secondary + +LOCAL_FUNC unhandled_cpu , : + wfi + j unhandled_cpu +END_FUNC unhandled_cpu + + .section .identity_map.data + .balign 8 +LOCAL_DATA hart_lottery , : + /* The hart who first increments this variable will be primary hart. */ + .word 0 +END_DATA hart_lottery + +#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..a2aade5 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/kernel/kern.ld.S @@ -0,0 +1,278 @@ +/* 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 ); + *(.sdata .sdata.* .gnu.linkonce.s.*) + } + + /* uninitialized data */ + .bss : { + __data_end = .; + __bss_start = .; + *(.sbss .sbss.*) + *(.gnu.linkonce.sb.*) + *(.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..ce0cf3a --- /dev/null +++ b/optee/optee_os/core/arch/riscv/kernel/sbi.c @@ -0,0 +1,80 @@ +// 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) + +/** + * sbi_probe_extension() - Check if an SBI extension ID is supported or not. + * @extid: The extension ID to be probed. + * + * Return: 1 or an extension specific nonzero value if yes, 0 otherwise. + */ +int sbi_probe_extension(int extid) +{ + struct sbiret ret = { }; + + ret = sbi_ecall(SBI_EXT_BASE, SBI_EXT_BASE_PROBE_EXT, extid); + if (!ret.error) + return ret.value; + + return 0; +} + +/** + * sbi_console_putchar() - Writes given character to the console device. + * @ch: The data to be written to the console. + */ +void sbi_console_putchar(int ch) +{ + sbi_ecall(SBI_EXT_0_1_CONSOLE_PUTCHAR, 0, ch); +} + +/** + * sbi_dbcn_write_byte() - Write byte to debug console + * @ch: Byte to be written + * + * Return: SBI error code (SBI_SUCCESS = 0 on success) + */ +int sbi_dbcn_write_byte(unsigned char ch) +{ + struct sbiret ret = { }; + + ret = sbi_ecall(SBI_EXT_DBCN, SBI_EXT_DBCN_CONSOLE_WRITE_BYTE, ch); + return ret.error; +} + +int sbi_hsm_hart_start(uint32_t hartid, paddr_t start_addr, unsigned long arg) +{ + struct sbiret ret = { }; + + ret = sbi_ecall(SBI_EXT_HSM, SBI_EXT_HSM_HART_START, hartid, 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..0b6ec27 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/kernel/sbi_console.c @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2022 NXP + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct sbi_console_data { + struct serial_chip chip; +}; + +static struct sbi_console_data console_data __nex_bss; +static struct serial_ops sbi_console_ops __nex_bss; + +static void sbi_console_putc_legacy(struct serial_chip *chip __unused, int ch) +{ + sbi_console_putchar(ch); +} + +static void sbi_console_putc(struct serial_chip *chip __unused, int ch) +{ + sbi_dbcn_write_byte(ch); +} + +static void sbi_console_init(struct sbi_console_data *pd) +{ + if (sbi_probe_extension(SBI_EXT_DBCN)) + sbi_console_ops.putc = sbi_console_putc; + else + sbi_console_ops.putc = sbi_console_putc_legacy; + + pd->chip.ops = &sbi_console_ops; +} + +void plat_console_init(void) +{ + sbi_console_init(&console_data); + register_serial_console(&console_data.chip); +} diff --git a/optee/optee_os/core/arch/riscv/kernel/semihosting_rv.S b/optee/optee_os/core/arch/riscv/kernel/semihosting_rv.S new file mode 100644 index 0000000..7adb359 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/kernel/semihosting_rv.S @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2024 Andes Technology Corporation + */ + +#include + +/* + * uintptr_t __do_semihosting(uintptr_t op, uintptr_t arg) + * + * Refer to RISC-V Semihosting Binary Interface: + * https://github.com/riscv-non-isa/riscv-semihosting/blob/main/binary-interface.adoc + */ +FUNC __do_semihosting , : , .identity_map +.option push +.option norvc + slli x0, x0, 0x1f + ebreak + srai x0, x0, 0x7 +.option pop + ret +END_FUNC __do_semihosting 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..48242e2 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/kernel/sub.mk @@ -0,0 +1,31 @@ +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 +srcs-$(CFG_UNWIND) += unwind_rv.c +srcs-$(CFG_SEMIHOSTING) += semihosting_rv.S +srcs-y += thread_optee_abi.c +srcs-y += thread_optee_abi_rv.S +asm-defines-y += asm-defines.c + +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_arch.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_rv.c-y += -pg +endif +endif 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..d965861 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/kernel/tee_time_rdtime.c @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2022-2023 NXP + */ + +#include +#include +#include +#include + +__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; +} + +TEE_Result tee_time_get_sys_time(TEE_Time *time) +{ + uint64_t tm = read_time(); + uint64_t rate = read_cntfrq(); + + time->seconds = tm / rate; + time->millis = (tm % rate) / (rate / TEE_TIME_MILLIS_BASE); + + return TEE_SUCCESS; +} + +uint32_t tee_time_get_sys_time_protection_level(void) +{ + return 1000; +} 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..8654aa6 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/kernel/thread_arch.c @@ -0,0 +1,693 @@ +// 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 +#include + +/* + * This function is called as a guard after each ABI call which is not + * supposed to return. + */ +void __noreturn __panic_at_abi_return(void) +{ + panic(); +} + +/* This function returns current masked exception bits. */ +uint32_t __nostackcheck thread_get_exceptions(void) +{ + uint32_t xie = read_csr(CSR_XIE) & THREAD_EXCP_ALL; + + return 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(); + + /* + * In ARM, the bits in DAIF register are used to mask the exceptions. + * While in RISC-V, the bits in CSR XIE are used to enable(unmask) + * corresponding interrupt sources. To not modify the function of + * thread_set_exceptions(), we should "invert" the bits in "exceptions". + * The corresponding bits in "exceptions" will be inverted so they will + * be cleared when we write the final value into CSR XIE. So that we + * can mask those exceptions. + */ + exceptions &= THREAD_EXCP_ALL; + exceptions ^= THREAD_EXCP_ALL; + + 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 = xstatus_for_xret(true, PRV_S); + 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) +{ + interrupt_main_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); +} + +unsigned long xstatus_for_xret(uint8_t pie, uint8_t pp) +{ + unsigned long xstatus = read_csr(CSR_XSTATUS); + + assert(pp == PRV_M || pp == PRV_S || pp == PRV_U); + +#ifdef RV32 + xstatus = set_field_u32(xstatus, CSR_XSTATUS_IE, 0); + xstatus = set_field_u32(xstatus, CSR_XSTATUS_PIE, pie); + xstatus = set_field_u32(xstatus, CSR_XSTATUS_SPP, pp); +#else /* RV64 */ + xstatus = set_field_u64(xstatus, CSR_XSTATUS_IE, 0); + xstatus = set_field_u64(xstatus, CSR_XSTATUS_PIE, pie); + xstatus = set_field_u64(xstatus, CSR_XSTATUS_SPP, pp); +#endif + + return xstatus; +} + +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) +{ + memset(&thread->regs, 0, sizeof(thread->regs)); + + thread->regs.epc = (uintptr_t)pc; + + /* Set up xstatus */ + thread->regs.status = xstatus_for_xret(true, PRV_S); + + /* Enable native interrupt */ + thread->regs.ie = THREAD_EXCP_NATIVE_INTR; + + /* Reinitialize stack pointer */ + thread->regs.sp = thread->stack_va_end; + + /* Set up GP and TP */ + thread->regs.gp = read_gp(); + thread->regs.tp = read_tp(); + + /* + * 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_abi_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) == 0; +} + +#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(); + + /* + * We may resume thread at another hart, so we need to re-assign value + * of tp to be current hart's thread_core_local. + */ + if (!is_user_mode(&threads[n].regs)) + threads[n].regs.tp = read_tp(); + + /* + * 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, unsigned long 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.epc = 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); +#ifndef CFG_PAN + /* + * Allow access to user pages. When CFG_PAN is enabled, the SUM bit will + * be set and clear at runtime when necessary. + */ + set_csr(CSR_XSTATUS, CSR_XSTATUS_SUM); +#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, + unsigned long status, unsigned long ie, + struct thread_pauth_keys *keys __unused) +{ + *regs = (struct thread_ctx_regs){ + .a0 = a0, + .a1 = a1, + .a2 = a2, + .a3 = a3, + .s0 = 0, + .sp = user_sp, + .ra = entry_func, + .status = status, + .ie = ie, + }; +} + +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) +{ + unsigned long status = 0; + unsigned long ie = 0; + uint32_t exceptions = 0; + uint32_t rc = 0; + struct thread_ctx_regs *regs = NULL; + + tee_ta_update_session_utime_resume(); + + /* Read current interrupt masks */ + ie = read_csr(CSR_XIE); + + /* + * Mask all exceptions, the CSR_XSTATUS.IE will be set from + * setup_unwind_user_mode() after exiting. + */ + exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); + regs = thread_get_ctx_regs(); + status = xstatus_for_xret(true, PRV_U); + set_ctx_regs(regs, a0, a1, a2, a3, user_sp, entry_func, status, ie, + NULL); + rc = __thread_enter_user_mode(regs, exit_status0, exit_status1); + thread_unmask_exceptions(exceptions); + + return rc; +} + +void __thread_rpc(uint32_t rv[THREAD_RPC_NUM_ARGS]) +{ + thread_rpc_xstatus(rv, xstatus_for_xret(false, PRV_S)); +} diff --git a/optee/optee_os/core/arch/riscv/kernel/thread_optee_abi.c b/optee/optee_os/core/arch/riscv/kernel/thread_optee_abi.c new file mode 100644 index 0000000..d94da93 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/kernel/thread_optee_abi.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_ABI_ASYNC_NOTIF_VALUE_DO_BOTTOM_HALF); + +void thread_handle_fast_abi(struct thread_abi_args *args) +{ + thread_check_canaries(); + + if (IS_ENABLED(CFG_NS_VIRTUALIZATION) && + virt_set_guest(args->a7)) { + args->a0 = OPTEE_ABI_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_abi(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_ABI_RETURN_OK; + + thread_check_canaries(); + + if (IS_ENABLED(CFG_NS_VIRTUALIZATION) && virt_set_guest(a7)) + return OPTEE_ABI_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_ABI_CALL_RETURN_FROM_RPC) { + thread_resume_from_rpc(a3, a1, a2, a4, a5); + rv = OPTEE_ABI_RETURN_ERESUME; + } else { + thread_alloc_and_run(a0, a1, a2, a3, 0, 0); + rv = OPTEE_ABI_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_ABI_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_ABI_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_ABI_RETURN_EBADADDR; + + *arg = p; + *num_params = READ_ONCE((*arg)->num_params); + if (*num_params > OPTEE_MSG_MAX_NUM_PARAMS) + return OPTEE_ABI_RETURN_EBADADDR; + + sz = OPTEE_MSG_GET_ARG_SIZE(*num_params); + if (!mobj_get_va(mobj, offset, sz)) + return OPTEE_ABI_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_ABI_RETURN_EBADADDR; + *rpc_arg = p; + } + + return OPTEE_ABI_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_ABI_RETURN_EBADCMD; + else + rv = OPTEE_ABI_RETURN_OK; + + thread_rpc_shm_cache_clear(&thr->shm_cache); + if (rpc_arg) + thr->rpc_arg = NULL; + + if (rv == OPTEE_ABI_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_ABI_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); + } + + 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_ABI_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_ABI_RETURN_EBADADDR; + } + + if (mobj_inc_map(mobj)) { + rv = OPTEE_ABI_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_abi_entry(uint32_t a0, uint32_t a1, uint32_t a2, + uint32_t a3 __unused) +{ + const bool with_rpc_arg = true; + + switch (a0) { + case OPTEE_ABI_CALL_WITH_ARG: + return std_entry_with_parg(reg_pair_to_64(a1, a2), + !with_rpc_arg); + case OPTEE_ABI_CALL_WITH_RPC_ARG: + return std_entry_with_parg(reg_pair_to_64(a1, a2), + with_rpc_arg); + case OPTEE_ABI_CALL_WITH_REGD_ARG: + return std_entry_with_regd_arg(reg_pair_to_64(a1, a2), a3); + default: + EMSG("Unknown ABI 0x%"PRIx32, a0); + return OPTEE_ABI_RETURN_EBADCMD; + } +} + +/* + * Helper routine for the assembly function thread_std_abi_entry() + * + * Note: this function is weak just to make it possible to exclude it from + * the unpaged area. + */ +uint32_t __weak __thread_std_abi_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_abi_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_ABI_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_ABI_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_ABI_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_ABI_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/riscv/kernel/thread_optee_abi_rv.S b/optee/optee_os/core/arch/riscv/kernel/thread_optee_abi_rv.S new file mode 100644 index 0000000..e8ebba8 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/kernel/thread_optee_abi_rv.S @@ -0,0 +1,223 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2023 NXP + * Copyright (c) 2023 Andes Technology Corporation + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * 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. + * + * void thread_return_to_udomain(unsigned long arg0, unsigned long arg1, + * unsigned long arg2, unsigned long arg3, + * unsigned long arg4, unsigned long arg5); + */ +FUNC thread_return_to_udomain , : + /* Caller should provide arguments in a0~a5 */ +#if defined(CFG_RISCV_WITH_M_MODE_SM) + li a7, SBI_EXT_TEE /* extension ID */ + li a6, 0 /* function ID (unused) */ + ecall +#else + /* Other protocol */ +#endif + /* ABI to REE should not return */ + panic_at_abi_return +END_FUNC thread_return_to_udomain + +FUNC thread_std_abi_entry , : + jal __thread_std_abi_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_abi_entry() return value */ + mv a1, s0 + li a2, 0 + li a3, 0 + li a4, 0 + li a0, TEEABI_OPTEED_RETURN_CALL_DONE + + /* Return to untrusted domain */ + jal thread_return_to_udomain +END_FUNC thread_std_abi_entry + +/* + * void thread_rpc_xstatus(uint32_t rv[THREAD_RPC_NUM_ARGS], + * unsigned long status); + */ +FUNC thread_rpc_xstatus , : + /* Use stack for temporary storage */ + addi sp, sp, -REGOFF(8) + + /* Read xSTATUS */ + csrr a2, CSR_XSTATUS + + /* Mask all maskable exceptions before switching to temporary stack */ + csrw CSR_XIE, x0 + + /* Save return address xSTATUS and pointer to rv */ + STR a0, REGOFF(0)(sp) + STR a1, REGOFF(1)(sp) + STR s0, REGOFF(2)(sp) + STR ra, REGOFF(3)(sp) + STR a2, REGOFF(4)(sp) +#ifdef CFG_UNWIND + addi s0, sp, REGOFF(8) +#endif + + /* Save thread state */ + jal thread_get_ctx_regs + LDR ra, REGOFF(3)(sp) + /* Save ra, sp, gp, tp, and s0~s11 */ + store_xregs a0, THREAD_CTX_REG_RA, REG_RA, REG_TP + 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 s1, REGOFF(0)(sp) + + /* xSTATUS to restore */ + LDR a1, REGOFF(1)(sp) + /* Switch to tmp stack */ + mv sp, a0 + + /* Early load rv[] into s2-s4 */ + lw s2, 0(s1) + lw s3, 4(s1) + lw s4, 8(s1) + + li a0, THREAD_FLAGS_COPY_ARGS_ON_RETURN + la a2, .thread_rpc_return + jal thread_state_suspend + + mv a4, a0 /* thread index */ + mv a1, s2 /* rv[0] */ + mv a2, s3 /* rv[1] */ + mv a3, s4 /* rv[2] */ + li a0, TEEABI_OPTEED_RETURN_CALL_DONE + + /* Return to untrusted domain */ + jal thread_return_to_udomain +.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 saved XSTATUS from stack */ + LDR s0, REGOFF(4)(sp) + csrw CSR_XSTATUS, s0 + + /* Pop s0 from stack */ + LDR s0, REGOFF(2)(sp) + + addi sp, sp, REGOFF(8) + ret +END_FUNC thread_rpc_xstatus +DECLARE_KEEP_PAGER thread_rpc_xstatus + +LOCAL_FUNC vector_std_abi_entry, : , .identity_map + jal thread_handle_std_abi + /* + * Normally thread_handle_std_abi() should return via + * thread_exit(), thread_rpc(), but if thread_handle_std_abi() + * hasn't switched stack (error detected) it will do a normal "C" + * return. + */ + /* Restore thread_handle_std_abi() return value */ + mv a1, a0 + li a2, 0 + li a3, 0 + li a4, 0 + li a0, TEEABI_OPTEED_RETURN_CALL_DONE + + /* Return to untrusted domain */ + j thread_return_to_udomain +END_FUNC vector_std_abi_entry + +LOCAL_FUNC vector_fast_abi_entry , : , .identity_map + addi sp, sp, -THREAD_ABI_ARGS_SIZE + store_xregs sp, THREAD_ABI_ARGS_A0, REG_A0, REG_A7 + mv a0, sp + jal thread_handle_fast_abi + load_xregs sp, THREAD_ABI_ARGS_A0, REG_A1, REG_A7 + addi sp, sp, THREAD_ABI_ARGS_SIZE + + li a0, TEEABI_OPTEED_RETURN_CALL_DONE + /* Return to untrusted domain */ + j thread_return_to_udomain +END_FUNC vector_fast_abi_entry + +LOCAL_FUNC vector_fiq_entry , : , .identity_map + /* Secure Monitor received a FIQ and passed control to us. */ + jal interrupt_main_handler + + li a0, TEEABI_OPTEED_RETURN_FIQ_DONE + /* Return to untrusted domain */ + j thread_return_to_udomain +END_FUNC vector_fiq_entry + +/* + * Vector table supplied to M-mode secure monitor (e.g., openSBI) at + * initialization. + * + * Note that M-mode secure monitor depends on the layout of this vector table, + * any change in layout has to be synced with M-mode secure monitor. + */ +FUNC thread_vector_table , : , .identity_map, , nobti + .option push + .option norvc + j vector_std_abi_entry + j vector_fast_abi_entry + j . + j . + j . + j . + j vector_fiq_entry + j . + j . + .option pop +END_FUNC thread_vector_table +DECLARE_KEEP_PAGER thread_vector_table 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..eeddc34 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/kernel/thread_rv.S @@ -0,0 +1,326 @@ +/* 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 b_if_prev_priv_is_u reg, label + andi \reg, \reg, CSR_XSTATUS_SPP + beqz \reg, \label +.endm + +.macro save_regs, mode +.if \mode == TRAP_MODE_USER + /* Save user sp, a0, a1 into temporary spaces of thread_core_local */ + store_xregs tp, THREAD_CORE_LOCAL_X0, REG_SP + store_xregs tp, THREAD_CORE_LOCAL_X1, REG_A0, REG_A1 + /* Load and set kernel sp from thread context */ + get_thread_ctx a0, a1 + load_xregs a0, THREAD_CTX_KERN_SP, REG_SP + /* Now sp is kernel sp, create stack frame to save user context */ + addi sp, sp, -THREAD_TRAP_REGS_SIZE + + /* Save user sp */ + load_xregs tp, THREAD_CORE_LOCAL_X0, REG_A0 + store_xregs sp, THREAD_TRAP_REG_SP, REG_A0 + + /* Restore user a0, a1 which can be saved later */ + load_xregs tp, THREAD_CORE_LOCAL_X1, REG_A0, REG_A1 + + /* Save user gp */ + 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 + /* Save user tp we previously swapped into CSR_XSCRATCH */ + store_xregs sp, THREAD_TRAP_REG_TP, REG_GP +.option push +.option norelax + la gp, __global_pointer$ +.option pop +.else + /* sp is kernel sp */ + addi sp, sp, -THREAD_TRAP_REGS_SIZE + store_xregs sp, THREAD_TRAP_REG_GP, REG_GP + store_xregs sp, THREAD_TRAP_REG_SP, REG_SP +.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 +#if defined(CFG_UNWIND) + /* To unwind stack we need s0, which is frame pointer. */ + store_xregs sp, THREAD_TRAP_REG_S0, REG_S0 +#endif + + csrr t0, CSR_XIE + store_xregs sp, THREAD_TRAP_REG_IE, REG_T0 + + /* Mask all interrupts */ + csrw CSR_XIE, x0 + + 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_IE, REG_T0 + csrw CSR_XIE, 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 defined(CFG_UNWIND) + /* To unwind stack we need s0, which is frame pointer. */ + load_xregs sp, THREAD_TRAP_REG_S0, REG_S0 +#endif + +.if \mode == TRAP_MODE_USER + /* Set scratch as thread_core_local */ + csrw CSR_XSCRATCH, tp + + 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 + load_xregs sp, THREAD_TRAP_REG_GP, REG_GP + load_xregs sp, THREAD_TRAP_REG_SP, REG_SP + 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 tp, CSR_XSCRATCH, tp + bnez tp, 0f + /* Read tp back */ + csrrw tp, CSR_XSCRATCH, tp + j trap_from_kernel +0: + /* Now tp is thread_core_local */ + 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_GP + 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 + + /* 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 + + /* + * Zeroize xSCRATCH to indicate to thread_trap_vect() + * that we are executing in kernel. + */ + csrw CSR_XSCRATCH, zero + + /* + * Mask all interrupts first. Interrupts will be unmasked after + * returning from __thread_enter_user_mode(). + */ + csrw CSR_XIE, zero + + /* Set epc as thread_unwind_user_mode() */ + csrw CSR_XEPC, a5 + + XRET +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 , : + /* Disable kernel mode exceptions first */ + csrc CSR_XSTATUS, CSR_XSTATUS_IE + + /* + * 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_GP + 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 thread_core_local in xSCRATCH to ensure that thread_trap_vect() + * uses correct core local structure. + */ + csrw CSR_XSCRATCH, tp + + /* Set user ie */ + load_xregs a0, THREAD_CTX_REG_IE, REG_S0 + csrw CSR_XIE, s0 + + /* Set user status */ + load_xregs a0, THREAD_CTX_REG_STATUS, REG_S0 + csrw CSR_XSTATUS, s0 + + /* 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 + +/* void thread_resume(struct thread_ctx_regs *regs) */ +FUNC thread_resume , : + /* Disable global interrupts first */ + csrc CSR_XSTATUS, CSR_XSTATUS_IE + + /* Restore epc */ + load_xregs a0, THREAD_CTX_REG_EPC, REG_T0 + csrw CSR_XEPC, t0 + + /* Restore ie */ + load_xregs a0, THREAD_CTX_REG_IE, REG_T0 + csrw CSR_XIE, t0 + + /* Restore status */ + load_xregs a0, THREAD_CTX_REG_STATUS, REG_T0 + csrw CSR_XSTATUS, t0 + + /* Check if previous privilege mode by status.SPP */ + b_if_prev_priv_is_u t0, 1f + /* Set scratch as zero to indicate that we are in kernel mode */ + csrw CSR_XSCRATCH, zero + j 2f +1: + /* Resume to U-mode, set scratch as tp to be used in the trap handler */ + csrw CSR_XSCRATCH, tp +2: + /* Restore all 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 + + XRET +END_FUNC thread_resume diff --git a/optee/optee_os/core/arch/riscv/kernel/unwind_rv.c b/optee/optee_os/core/arch/riscv/kernel/unwind_rv.c new file mode 100644 index 0000000..5c3a17b --- /dev/null +++ b/optee/optee_os/core/arch/riscv/kernel/unwind_rv.c @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: BSD-2-Clause +/*- + * Copyright (c) 2023 Andes Technology Corporation + * Copyright (c) 2015 Linaro Limited + * Copyright (c) 2015 The FreeBSD Foundation + */ + +#include +#include +#include +#include +#include + +#if defined(CFG_UNWIND) && (TRACE_LEVEL > 0) +void print_kernel_stack(void) +{ + struct unwind_state_riscv 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_riscv(&state, stack_start, stack_end - stack_start); +} +#endif diff --git a/optee/optee_os/core/arch/riscv/mm/core_mmu_arch.c b/optee/optee_os/core/arch/riscv/mm/core_mmu_arch.c new file mode 100644 index 0000000..b6b9b2b --- /dev/null +++ b/optee/optee_os/core/arch/riscv/mm/core_mmu_arch.c @@ -0,0 +1,770 @@ +// 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 + +#ifndef RV64 +#error implement +#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 + +static bitstr_t bit_decl(g_asid, RISCV_MMU_ASID_WIDTH) __nex_bss; +static unsigned int g_asid_spinlock __nex_bss = SPINLOCK_UNLOCK; + +struct mmu_pte { + unsigned long entry; +}; + +struct mmu_pgt { + struct mmu_pte entries[RISCV_PTES_PER_PT]; +}; + +#define RISCV_MMU_PGT_SIZE (sizeof(struct mmu_pgt)) + +static struct mmu_pgt root_pgt[CFG_TEE_CORE_NB_CORE] + __aligned(RISCV_PGSIZE) + __section(".nozi.mmu.root_pgt"); + +static struct mmu_pgt pool_pgts[RISCV_MMU_MAX_PGTS] + __aligned(RISCV_PGSIZE) __section(".nozi.mmu.pool_pgts"); + +static struct mmu_pgt user_pgts[CFG_NUM_THREADS] + __aligned(RISCV_PGSIZE) __section(".nozi.mmu.usr_pgts"); + +static int user_va_idx __nex_data = -1; + +struct mmu_partition { + struct mmu_pgt *root_pgt; + struct mmu_pgt *pool_pgts; + struct mmu_pgt *user_pgts; + unsigned int pgts_used; + unsigned int asid; +}; + +static struct mmu_partition default_partition __nex_data = { + .root_pgt = root_pgt, + .pool_pgts = pool_pgts, + .user_pgts = user_pgts, + .pgts_used = 0, + .asid = 0 +}; + +static struct mmu_pte *core_mmu_table_get_entry(struct mmu_pgt *pgt, + unsigned int idx) +{ + return &pgt->entries[idx & RISCV_MMU_VPN_MASK]; +} + +static void core_mmu_entry_set(struct mmu_pte *pte, uint64_t val) +{ + pte->entry = val; +} + +static uint64_t core_mmu_entry_get(struct mmu_pte *pte) +{ + return pte->entry; +} + +static bool core_mmu_entry_is_valid(struct mmu_pte *pte) +{ + return pte->entry & PTE_V; +} + +static bool core_mmu_entry_is_invalid(struct mmu_pte *pte) +{ + return !core_mmu_entry_is_valid(pte); +} + +static bool core_mmu_entry_is_leaf(struct mmu_pte *pte) +{ + /* A leaf has one or more RWX bits set */ + return pte->entry & (PTE_R | PTE_W | PTE_X); +} + +static bool __maybe_unused core_mmu_entry_is_branch(struct mmu_pte *pte) +{ + return !core_mmu_entry_is_leaf(pte); +} + +static unsigned long core_mmu_pte_create(unsigned long ppn, uint8_t pte_bits) +{ + /* + * This function may be called from core_mmu_set_entry(). There is a + * case that MM core wants to clear PTE by calling core_mmu_set_entry() + * with zero physical address and zero memory attributes, which turns + * @ppn and @pte_bits in this function to be both zero. In this case, we + * should create zero PTE without setting its V bit. + */ + + return SHIFT_U64(ppn, PTE_PPN_SHIFT) | pte_bits; +} + +static unsigned long core_mmu_ptp_create(unsigned long ppn) +{ + /* Set V bit to create PTE points to next level of the page table. */ + return core_mmu_pte_create(ppn, PTE_V); +} + +static unsigned long core_mmu_pte_ppn(struct mmu_pte *pte) +{ + return pte->entry >> PTE_PPN_SHIFT; +} + +static unsigned long pa_to_ppn(paddr_t pa) +{ + return pa >> RISCV_PGSHIFT; +} + +static paddr_t pte_to_pa(struct mmu_pte *pte) +{ + return SHIFT_U64(core_mmu_pte_ppn(pte), RISCV_PGSHIFT); +} + +static unsigned long core_mmu_pgt_to_satp(unsigned long asid, + struct mmu_pgt *pgt) +{ + unsigned long satp = 0; + unsigned long pgt_ppn = virt_to_phys(pgt) >> RISCV_PGSHIFT; + + assert(asid & g_asid == asid); + satp |= SHIFT_U64(asid, RISCV_SATP_ASID_SHIFT); + satp |= SHIFT_U64(RISCV_SATP_MODE, RISCV_SATP_MODE_SHIFT); + satp |= pgt_ppn; + + return satp; +} + +static unsigned long pte_to_mattr(unsigned level __maybe_unused, + struct mmu_pte *pte) +{ + unsigned long mattr = TEE_MATTR_SECURE; + unsigned long entry = core_mmu_entry_get(pte); + + if (entry & PTE_V) { + if (!(entry & (PTE_R | PTE_W | PTE_X))) + return TEE_MATTR_TABLE; + + mattr |= TEE_MATTR_VALID_BLOCK; + } + + if (entry & PTE_U) { + if (entry & PTE_R) + mattr |= TEE_MATTR_UR | TEE_MATTR_PR; + if (entry & PTE_W) + mattr |= TEE_MATTR_UW | TEE_MATTR_PW; + if (entry & PTE_X) + mattr |= TEE_MATTR_UX | TEE_MATTR_PX; + } else { + if (entry & PTE_R) + mattr |= TEE_MATTR_PR; + if (entry & PTE_W) + mattr |= TEE_MATTR_PW; + if (entry & PTE_X) + mattr |= TEE_MATTR_PX; + } + + if (entry & PTE_G) + mattr |= TEE_MATTR_GLOBAL; + + return mattr; +} + +static uint8_t mattr_to_pte_bits(unsigned level __maybe_unused, uint32_t attr) +{ + unsigned long pte_bits = 0; + + if (attr & TEE_MATTR_TABLE) + return PTE_V; + + if (attr & TEE_MATTR_VALID_BLOCK) + pte_bits |= PTE_V; + + if (attr & TEE_MATTR_UR) + pte_bits |= PTE_R | PTE_U; + if (attr & TEE_MATTR_UW) + pte_bits |= PTE_W | PTE_U; + if (attr & TEE_MATTR_UX) + pte_bits |= PTE_X | PTE_U; + + if (attr & TEE_MATTR_PR) + pte_bits |= PTE_R; + if (attr & TEE_MATTR_PW) + pte_bits |= PTE_W | PTE_R; + if (attr & TEE_MATTR_PX) + pte_bits |= PTE_X | PTE_R; + + if (attr & (TEE_MATTR_UR | TEE_MATTR_PR)) + pte_bits |= PTE_A; + + if (attr & (TEE_MATTR_UW | TEE_MATTR_PW)) + pte_bits |= PTE_D; + + if (attr & TEE_MATTR_GLOBAL) + pte_bits |= PTE_G; + + return pte_bits; +} + +static unsigned int core_mmu_pgt_idx(vaddr_t va, unsigned int level) +{ + unsigned int idx = va >> CORE_MMU_SHIFT_OF_LEVEL(level); + + return idx & RISCV_MMU_VPN_MASK; +} + +static struct mmu_partition *core_mmu_get_prtn(void) +{ + return &default_partition; +} + +static struct mmu_pgt *core_mmu_get_root_pgt_va(struct mmu_partition *prtn) +{ + return prtn->root_pgt + get_core_pos(); +} + +static struct mmu_pgt *core_mmu_get_ta_pgt_va(struct mmu_partition *prtn) +{ + return &prtn->user_pgts[thread_get_id()]; +} + +static struct mmu_pgt *core_mmu_pgt_alloc(struct mmu_partition *prtn) +{ + struct mmu_pgt *pgt = NULL; + + if (prtn->pgts_used >= RISCV_MMU_MAX_PGTS) { + debug_print("%u pgts exhausted", RISCV_MMU_MAX_PGTS); + panic(); + return NULL; + } + + pgt = &prtn->pool_pgts[prtn->pgts_used++]; + + memset(pgt, 0, RISCV_MMU_PGT_SIZE); + + debug_print("pgts used %u / %u", prtn->pgts_used, RISCV_MMU_MAX_PGTS); + + return pgt; +} + +static void core_init_mmu_prtn_ta_core(struct mmu_partition *prtn __unused, + unsigned int core __unused) +{ + /* + * user_va_idx is the index in CORE_MMU_BASE_TABLE_LEVEL. + * The entry holds pointer to the user mapping table in next level + * that changes per core. Therefore, nothing to do. + */ +} + +static void core_init_mmu_prtn_ta(struct mmu_partition *prtn) +{ + unsigned int core = 0; + + assert(user_va_idx != -1); + + memset(prtn->user_pgts, 0, CFG_NUM_THREADS * RISCV_MMU_PGT_SIZE); + for (core = 0; core < CFG_TEE_CORE_NB_CORE; core++) + core_init_mmu_prtn_ta_core(prtn, core); +} + +static void core_init_mmu_prtn_tee(struct mmu_partition *prtn, + struct tee_mmap_region *mm) +{ + size_t n = 0; + void *pgt = core_mmu_get_root_pgt_va(prtn); + + /* Clear table before using it. */ + memset(prtn->root_pgt, 0, RISCV_MMU_PGT_SIZE * CFG_TEE_CORE_NB_CORE); + memset(pgt, 0, RISCV_MMU_PGT_SIZE); + memset(prtn->pool_pgts, 0, RISCV_MMU_MAX_PGTS * RISCV_MMU_PGT_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); + + /* + * 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()) + memcpy(&prtn->root_pgt[n], + &prtn->root_pgt[get_core_pos()], + RISCV_MMU_PGT_SIZE); + } +} + +void tlbi_va_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))); + + /* + * Ensure operations are completed or observed before proceeding + * with TLB invalidation. + */ + mb(); + while (len) { + tlbi_va_allasid(va); + len -= granule; + va += granule; + } + /* + * After invalidating TLB entries, a memory barrier is required + * to ensure that the page table entries become visible to other harts + * before subsequent memory accesses are performed. + */ + mb(); +} + +void tlbi_va_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))); + + /* + * A memory barrier is necessary here to ensure the consistency + * and correctness of memory accesses. + */ + mb(); + while (len) { + tlbi_va_asid(va, asid); + len -= granule; + va += granule; + } + /* Enforce ordering of memory operations and ensure that all + * preceding memory operations are completed after TLB + * invalidation. + */ + mb(); +} + +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; +} + +unsigned int asid_alloc(void) +{ + uint32_t exceptions = cpu_spin_lock_xsave(&g_asid_spinlock); + unsigned int r = 0; + int i = 0; + + bit_ffc(g_asid, RISCV_MMU_ASID_WIDTH, &i); + if (i == -1) { + r = 0; + } else { + bit_set(g_asid, i); + r = i + 1; + } + + 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); + + if (asid) { + int i = asid - 1; + + assert(i < RISCV_MMU_ASID_WIDTH && 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); + vaddr_t vaddr = (vaddr_t)va; + struct mmu_pgt *pgt = NULL; + struct mmu_pte *pte = NULL; + int level = 0; + unsigned int idx = 0; + struct mmu_partition *prtn = core_mmu_get_prtn(); + + assert(pa); + + pgt = core_mmu_get_root_pgt_va(prtn); + + for (level = CORE_MMU_BASE_TABLE_LEVEL; level >= 0; level--) { + idx = core_mmu_pgt_idx(vaddr, level); + pte = core_mmu_table_get_entry(pgt, idx); + + if (core_mmu_entry_is_invalid(pte)) { + thread_unmask_exceptions(exceptions); + return false; + } else if (core_mmu_entry_is_leaf(pte)) { + *pa = pte_to_pa(pte) | + (vaddr & (BIT64(RISCV_PGSHIFT) - 1)); + thread_unmask_exceptions(exceptions); + return true; + } + + pgt = phys_to_virt(pte_to_pa(pte), + MEM_AREA_TEE_RAM_RW_DATA, sizeof(*pgt)); + } + + thread_unmask_exceptions(exceptions); + return false; +} + +bool cpu_mmu_enabled(void) +{ + return read_satp(); +} + +bool core_mmu_find_table(struct mmu_partition *prtn, vaddr_t va, + unsigned int max_level, + struct core_mmu_table_info *tbl_info) +{ + uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); + struct mmu_pgt *pgt = NULL; + struct mmu_pte *pte = NULL; + unsigned int level = CORE_MMU_BASE_TABLE_LEVEL; + unsigned int idx = 0; + unsigned int deepest_level = max_level; + vaddr_t va_base = 0; + bool ret = false; + + if (max_level == UINT_MAX) + deepest_level = 0; + + if (!prtn) + prtn = core_mmu_get_prtn(); + + pgt = core_mmu_get_root_pgt_va(prtn); + + while (true) { + idx = core_mmu_pgt_idx(va - va_base, level); + pte = core_mmu_table_get_entry(pgt, idx); + if (level == deepest_level || level == 0 || + core_mmu_entry_is_invalid(pte) || + core_mmu_entry_is_leaf(pte)) { + core_mmu_set_info_table(tbl_info, level, va_base, pgt); + ret = true; + goto out; + } + pgt = phys_to_virt(pte_to_pa(pte), + MEM_AREA_TEE_RAM_RW_DATA, sizeof(*pgt)); + if (!pgt) + goto out; + va_base += SHIFT_U64(idx, CORE_MMU_SHIFT_OF_LEVEL(level)); + level--; + } +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) +{ + struct mmu_pgt *pgt = NULL; + struct mmu_pte *pte = NULL; + struct mmu_partition *prtn = core_mmu_get_prtn(); + unsigned long ptp = 0; + + if (!core_mmu_level_in_range(tbl_info->level)) + return false; + + pgt = tbl_info->table; + pte = core_mmu_table_get_entry(pgt, idx); + + if (core_mmu_entry_is_invalid(pte)) { + pgt = core_mmu_pgt_alloc(prtn); + if (!pgt) + return false; + + ptp = core_mmu_ptp_create(pa_to_ppn((paddr_t)pgt)); + core_mmu_entry_set(pte, ptp); + } + + return true; +} + +void core_mmu_set_info_table(struct core_mmu_table_info *tbl_info, + unsigned int level, vaddr_t va_base, void *table) +{ + tbl_info->level = level; + tbl_info->next_level = level - 1; + tbl_info->table = table; + tbl_info->va_base = va_base; + tbl_info->shift = CORE_MMU_SHIFT_OF_LEVEL(level); + assert(level < RISCV_PGLEVELS); + tbl_info->num_entries = RISCV_PTES_PER_PT; +} + +void core_mmu_get_entry_primitive(const void *table, size_t level, + size_t idx, paddr_t *pa, uint32_t *attr) +{ + struct mmu_pgt *pgt = (struct mmu_pgt *)table; + struct mmu_pte *pte = core_mmu_table_get_entry(pgt, idx); + + if (core_mmu_entry_is_valid(pte)) { + if (pa) + *pa = pte_to_pa(pte); + if (attr) + *attr = pte_to_mattr(level, pte); + } else { + if (pa) + *pa = 0; + if (attr) + *attr = 0; + } +} + +void core_mmu_set_entry_primitive(void *table, size_t level, size_t idx, + paddr_t pa, uint32_t attr) +{ + struct mmu_pgt *pgt = (struct mmu_pgt *)table; + struct mmu_pte *pte = core_mmu_table_get_entry(pgt, idx); + uint8_t pte_bits = mattr_to_pte_bits(level, attr); + + core_mmu_entry_set(pte, core_mmu_pte_create(pa_to_ppn(pa), pte_bits)); +} + +static void set_user_va_idx(struct mmu_partition *prtn) +{ + struct mmu_pgt *pgt = NULL; + struct mmu_pte *pte = NULL; + unsigned int idx = 0; + + pgt = core_mmu_get_root_pgt_va(prtn); + + for (idx = 1 ; idx < RISCV_PTES_PER_PT; idx++) { + pte = core_mmu_table_get_entry(pgt, idx); + if (core_mmu_entry_is_invalid(pte)) { + user_va_idx = idx; + return; + } + } + if (user_va_idx < 0) + panic(); +} + +static struct mmu_pte * +core_mmu_get_user_mapping_entry(struct mmu_partition *prtn) +{ + struct mmu_pgt *pgt = core_mmu_get_root_pgt_va(prtn); + + assert(user_va_idx != -1); + + return core_mmu_table_get_entry(pgt, user_va_idx); +} + +void core_mmu_set_user_map(struct core_mmu_user_map *map) +{ + unsigned long satp = 0; + uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); + struct mmu_partition *prtn = core_mmu_get_prtn(); + struct mmu_pte *pte = NULL; + unsigned long ptp = 0; + + satp = read_satp(); + /* Clear ASID */ + satp &= ~SHIFT_U64(RISCV_SATP_ASID_MASK, RISCV_SATP_ASID_SHIFT); + pte = core_mmu_get_user_mapping_entry(prtn); + if (map && map->user_map) { + ptp = core_mmu_ptp_create(pa_to_ppn((paddr_t)map->user_map)); + core_mmu_entry_set(pte, ptp); + core_mmu_table_write_barrier(); + satp |= SHIFT_U64(map->asid, RISCV_SATP_ASID_SHIFT); + write_satp(satp); + } else { + core_mmu_entry_set(pte, 0); + core_mmu_table_write_barrier(); + } + + tlbi_all(); + thread_unmask_exceptions(exceptions); +} + +void core_mmu_get_user_va_range(vaddr_t *base, size_t *size) +{ + assert(user_va_idx != -1); + + if (base) + *base = SHIFT_U64(user_va_idx, CORE_MMU_BASE_TABLE_SHIFT); + + if (size) + *size = BIT64(CORE_MMU_BASE_TABLE_SHIFT); +} + +void core_mmu_get_user_pgdir(struct core_mmu_table_info *pgd_info) +{ + vaddr_t va_range_base = 0; + struct mmu_partition *prtn = core_mmu_get_prtn(); + struct mmu_pgt *pgt = core_mmu_get_ta_pgt_va(prtn); + + core_mmu_get_user_va_range(&va_range_base, NULL); + core_mmu_set_info_table(pgd_info, CORE_MMU_PGDIR_LEVEL + 1, + va_range_base, pgt); +} + +void core_mmu_create_user_map(struct user_mode_ctx *uctx, + struct core_mmu_user_map *map) +{ + struct core_mmu_table_info tbl_info = { }; + + core_mmu_get_user_pgdir(&tbl_info); + memset(tbl_info.table, 0, RISCV_MMU_PGT_SIZE); + core_mmu_populate_user_map(&tbl_info, uctx); + map->user_map = virt_to_phys(tbl_info.table); + map->asid = uctx->vm_info.asid; +} + +void core_mmu_get_user_map(struct core_mmu_user_map *map) +{ + struct mmu_partition *prtn = core_mmu_get_prtn(); + struct mmu_pte *pte = core_mmu_get_user_mapping_entry(prtn); + + map->user_map = pte_to_pa(pte); + + if (map->user_map) + map->asid = (read_satp() >> RISCV_SATP_ASID_SHIFT) & + RISCV_SATP_ASID_MASK; + else + map->asid = 0; +} + +bool core_mmu_user_mapping_is_active(void) +{ + struct mmu_partition *prtn = core_mmu_get_prtn(); + bool ret = false; + struct mmu_pte *pte = NULL; + uint32_t exceptions = 0; + + exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); + pte = core_mmu_get_user_mapping_entry(prtn); + ret = core_mmu_entry_is_valid(pte); + thread_unmask_exceptions(exceptions); + + return ret; +} + +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 = 0; + + static_assert((RISCV_MMU_MAX_PGTS * RISCV_MMU_PGT_SIZE) == + sizeof(pool_pgts)); + + /* 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); + + assert(max_va < BIT64(RISCV_MMU_VA_WIDTH)); +} + +void core_init_mmu_regs(struct core_mmu_config *cfg) +{ + struct mmu_partition *p = core_mmu_get_prtn(); + unsigned int n = 0; + + for (n = 0; n < CFG_TEE_CORE_NB_CORE; n++) + cfg->satp[n] = core_mmu_pgt_to_satp(p->asid, p->root_pgt + n); +} + +enum core_mmu_fault core_mmu_get_fault_type(uint32_t fault_descr) +{ + switch (fault_descr) { + case CAUSE_MISALIGNED_FETCH: + case CAUSE_MISALIGNED_LOAD: + case CAUSE_MISALIGNED_STORE: + return CORE_MMU_FAULT_ALIGNMENT; + case CAUSE_STORE_ACCESS: + case CAUSE_LOAD_ACCESS: + return CORE_MMU_FAULT_ACCESS_BIT; + case CAUSE_FETCH_PAGE_FAULT: + case CAUSE_LOAD_PAGE_FAULT: + case CAUSE_STORE_PAGE_FAULT: + case CAUSE_FETCH_GUEST_PAGE_FAULT: + case CAUSE_LOAD_GUEST_PAGE_FAULT: + case CAUSE_STORE_GUEST_PAGE_FAULT: + return CORE_MMU_FAULT_TRANSLATION; + case CAUSE_BREAKPOINT: + return CORE_MMU_FAULT_DEBUG_EVENT; + default: + return CORE_MMU_FAULT_OTHER; + } +} 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..17b374b --- /dev/null +++ b/optee/optee_os/core/arch/riscv/mm/sub.mk @@ -0,0 +1,10 @@ +srcs-y += core_mmu_arch.c +srcs-y += tlb_helpers_rv.S + +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. +cflags-remove-core_mmu_arch.c-y += -pg +endif 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..ee8da22 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/mm/tlb_helpers_rv.S @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2023 Andes Technology Corporation + * Copyright 2022 NXP + */ + +#include + +/* void tlbi_all(void); */ +FUNC tlbi_all , : + sfence.vma zero, zero + ret +END_FUNC tlbi_all + +/* void tlbi_va_allasid(vaddr_t va); */ +FUNC tlbi_va_allasid , : + sfence.vma a0, zero + ret +END_FUNC tlbi_va_allasid + +/* void tlbi_asid(unsigned int asid); */ +FUNC tlbi_asid , : + sfence.vma zero, a0 + ret +END_FUNC tlbi_asid + +/* void tlbi_va_asid(vaddr_t va, uint32_t asid); */ +FUNC tlbi_va_asid , : + sfence.vma a0, a1 + ret +END_FUNC tlbi_va_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..2047341 --- /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_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..b1dedf7 --- /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 plat_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..7a3ff43 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/plat-spike/platform_config.h @@ -0,0 +1,22 @@ +/* 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 + +/* CLINT */ +#ifndef CLINT_BASE +#define CLINT_BASE 0x02000000 +#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..72bd2c3 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/plat-virt/conf.mk @@ -0,0 +1,44 @@ +$(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) + +CFG_DT ?= y + +# 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 +CFG_TEE_CORE_NB_CORE ?= 1 +CFG_NUM_THREADS ?= 1 +$(call force,CFG_BOOT_SYNC_CPU,y) + +# RISC-V-specific flags +rv64-platform-isa ?= rv64imafdc_zicsr_zifencei + +$(call force,CFG_RISCV_M_MODE,n) +$(call force,CFG_RISCV_S_MODE,y) +$(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 +CFG_RISCV_SBI ?= y +CFG_RISCV_WITH_M_MODE_SM ?= y + +# 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..f6f6120 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/plat-virt/main.c @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2022-2023 NXP + */ + +#include +#include +#include +#include +#include +#include + +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 boot_primary_init_intc(void) +{ + plic_init(PLIC_BASE); +} + +void boot_secondary_init_intc(void) +{ + plic_hart_init(); +} +#endif /* CFG_RISCV_PLIC */ + +void plat_console_init(void) +{ + ns16550_init(&console_data, UART0_BASE, IO_WIDTH_U8, 0); + register_serial_console(&console_data.chip); +} + +void interrupt_main_handler(void) +{ + if (IS_ENABLED(CFG_RISCV_PLIC)) + plic_it_handle(); +} 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..064cca2 --- /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 0x600000 +#define PLIC_NUM_SOURCES 0x5f +#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..9088638 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/riscv.mk @@ -0,0 +1,247 @@ +# 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_WITH_LPAE is ARM-related flag, however, it is used by core code. +# In order to maintain the code logic, we set it when CFG_CORE_LARGE_PHYS_ADDR is set. +# Platform configuration should accordingly set CFG_CORE_LARGE_PHYS_ADDR or not. +ifeq ($(CFG_CORE_LARGE_PHYS_ADDR),y) +$(call force,CFG_WITH_LPAE,y) +endif + +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 + +# 'y' to let M-mode secure monitor handle the communication between OP-TEE OS +# and untrusted domain. +CFG_RISCV_WITH_M_MODE_SM ?= n +ifeq ($(CFG_RISCV_WITH_M_MODE_SM),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) + +# Enable generic timer +$(call force,CFG_CORE_HAS_GENERIC_TIMER,y) + +core-platform-cppflags += -I$(arch-dir)/include +core-platform-subdirs += \ + $(addprefix $(arch-dir)/, kernel mm tee) $(platform-dir) + +# Default values for "-mcmodel", "-march", and "-abi" compiler flags. +# Platform-specific overrides are in core/arch/riscv/plat-*/conf.mk. +riscv-platform-mcmodel ?= medany +rv64-platform-isa ?= rv64imafd +rv64-platform-abi ?= lp64d +rv32-platform-isa ?= rv32imafd +rv32-platform-abi ?= ilp32d + +rv64-platform-cflags += -mcmodel=$(riscv-platform-mcmodel) +rv64-platform-cflags += -march=$(rv64-platform-isa) -mabi=$(rv64-platform-abi) +rv64-platform-cflags += -Wno-missing-include-dirs +rv32-platform-cflags += -mcmodel=$(riscv-platform-mcmodel) +rv32-platform-cflags += -march=$(rv32-platform-isa) -mabi=$(rv32-platform-abi) + +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_UNWIND),y) +core-platform-cppflags += -fno-omit-frame-pointer +core-platform-cflags += -fno-omit-frame-pointer +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 += -fno-omit-frame-pointer +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 ($(CFG_UNWIND),y) +ta_rv64-platform-cflags += -fno-omit-frame-pointer +endif +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/entry_fast.c b/optee/optee_os/core/arch/riscv/tee/entry_fast.c new file mode 100644 index 0000000..99faa15 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/tee/entry_fast.c @@ -0,0 +1,316 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2023 NXP + * 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_abi_args *args) +{ + args->a0 = OPTEE_ABI_RETURN_OK; + args->a1 = default_nsec_shm_paddr; + args->a2 = default_nsec_shm_size; + /* Should this be TEEABI cache attributes instead? */ + args->a3 = core_mmu_is_shm_cached(); +} +#endif + +static void tee_entry_fastcall_l2cc_mutex(struct thread_abi_args *args) +{ + args->a0 = OPTEE_ABI_RETURN_UNKNOWN_FUNCTION; +} + +static void tee_entry_exchange_capabilities(struct thread_abi_args *args) +{ + bool res_shm_en = IS_ENABLED(CFG_CORE_RESERVED_SHM); + bool dyn_shm_en __maybe_unused = false; + + /* + * Currently we ignore OPTEE_ABI_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_ABI_NSEC_CAP_UNIPROCESSOR. + */ + + if (args->a1 & ~OPTEE_ABI_NSEC_CAP_UNIPROCESSOR) { + /* Unknown capability. */ + args->a0 = OPTEE_ABI_RETURN_ENOTAVAIL; + return; + } + + args->a0 = OPTEE_ABI_RETURN_OK; + args->a1 = 0; + + if (res_shm_en) + args->a1 |= OPTEE_ABI_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_ABI_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_ABI_SEC_CAP_VIRTUALIZATION; + IMSG("Normal World virtualization support is %sabled", + IS_ENABLED(CFG_NS_VIRTUALIZATION) ? "en" : "dis"); + + args->a1 |= OPTEE_ABI_SEC_CAP_MEMREF_NULL; + + if (IS_ENABLED(CFG_CORE_ASYNC_NOTIF)) { + args->a1 |= OPTEE_ABI_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_ABI_SEC_CAP_RPC_ARG; + args->a3 = THREAD_RPC_MAX_NUM_PARAMS; +} + +static void tee_entry_disable_shm_cache(struct thread_abi_args *args) +{ + uint64_t cookie; + + if (!thread_disable_prealloc_rpc_cache(&cookie)) { + args->a0 = OPTEE_ABI_RETURN_EBUSY; + return; + } + + if (!cookie) { + args->a0 = OPTEE_ABI_RETURN_ENOTAVAIL; + return; + } + + args->a0 = OPTEE_ABI_RETURN_OK; + args->a1 = cookie >> 32; + args->a2 = cookie; +} + +static void tee_entry_enable_shm_cache(struct thread_abi_args *args) +{ + if (thread_enable_prealloc_rpc_cache()) + args->a0 = OPTEE_ABI_RETURN_OK; + else + args->a0 = OPTEE_ABI_RETURN_EBUSY; +} + +static void tee_entry_boot_secondary(struct thread_abi_args *args) +{ +#if defined(CFG_BOOT_SECONDARY_REQUEST) + if (!boot_core_release(args->a1, (paddr_t)(args->a3))) + args->a0 = OPTEE_ABI_RETURN_OK; + else + args->a0 = OPTEE_ABI_RETURN_EBADCMD; +#else + args->a0 = OPTEE_ABI_RETURN_ENOTAVAIL; +#endif +} + +static void tee_entry_get_thread_count(struct thread_abi_args *args) +{ + args->a0 = OPTEE_ABI_RETURN_OK; + args->a1 = CFG_NUM_THREADS; +} + +#if defined(CFG_NS_VIRTUALIZATION) +static void tee_entry_vm_created(struct thread_abi_args *args) +{ + uint16_t guest_id = args->a1; + + /* Only hypervisor can issue this request */ + if (args->a7 != HYP_CLNT_ID) { + args->a0 = OPTEE_ABI_RETURN_ENOTAVAIL; + return; + } + + if (virt_guest_created(guest_id)) + args->a0 = OPTEE_ABI_RETURN_ENOTAVAIL; + else + args->a0 = OPTEE_ABI_RETURN_OK; +} + +static void tee_entry_vm_destroyed(struct thread_abi_args *args) +{ + uint16_t guest_id = args->a1; + + /* Only hypervisor can issue this request */ + if (args->a7 != HYP_CLNT_ID) { + args->a0 = OPTEE_ABI_RETURN_ENOTAVAIL; + return; + } + + if (virt_guest_destroyed(guest_id)) + args->a0 = OPTEE_ABI_RETURN_ENOTAVAIL; + else + args->a0 = OPTEE_ABI_RETURN_OK; +} +#endif + +/* Note: this function is weak to let platforms add special handling */ +void __weak tee_entry_fast(struct thread_abi_args *args) +{ + __tee_entry_fast(args); +} + +static void get_async_notif_value(struct thread_abi_args *args) +{ + bool value_valid = false; + bool value_pending = false; + + args->a0 = OPTEE_ABI_RETURN_OK; + args->a1 = notif_get_value(&value_valid, &value_pending); + args->a2 = 0; + if (value_valid) + args->a2 |= OPTEE_ABI_ASYNC_NOTIF_VALID; + if (value_pending) + args->a2 |= OPTEE_ABI_ASYNC_NOTIF_PENDING; +} + +/* + * If tee_entry_fast() is overridden, it's still supposed to call this + * function. + */ +void __tee_entry_fast(struct thread_abi_args *args) +{ + switch (args->a0) { + /* Generic functions */ + case OPTEE_ABI_CALLS_COUNT: + tee_entry_get_api_call_count(args); + break; + case OPTEE_ABI_CALLS_UID: + tee_entry_get_api_uuid(args); + break; + case OPTEE_ABI_CALLS_REVISION: + tee_entry_get_api_revision(args); + break; + case OPTEE_ABI_CALL_GET_OS_UUID: + tee_entry_get_os_uuid(args); + break; + case OPTEE_ABI_CALL_GET_OS_REVISION: + tee_entry_get_os_revision(args); + break; + + /* OP-TEE specific ABI functions */ +#ifdef CFG_CORE_RESERVED_SHM + case OPTEE_ABI_GET_SHM_CONFIG: + tee_entry_get_shm_config(args); + break; +#endif + case OPTEE_ABI_L2CC_MUTEX: + tee_entry_fastcall_l2cc_mutex(args); + break; + case OPTEE_ABI_EXCHANGE_CAPABILITIES: + tee_entry_exchange_capabilities(args); + break; + case OPTEE_ABI_DISABLE_SHM_CACHE: + tee_entry_disable_shm_cache(args); + break; + case OPTEE_ABI_ENABLE_SHM_CACHE: + tee_entry_enable_shm_cache(args); + break; + case OPTEE_ABI_BOOT_SECONDARY: + tee_entry_boot_secondary(args); + break; + case OPTEE_ABI_GET_THREAD_COUNT: + tee_entry_get_thread_count(args); + break; + +#if defined(CFG_NS_VIRTUALIZATION) + case OPTEE_ABI_VM_CREATED: + tee_entry_vm_created(args); + break; + case OPTEE_ABI_VM_DESTROYED: + tee_entry_vm_destroyed(args); + break; +#endif + + case OPTEE_ABI_ENABLE_ASYNC_NOTIF: + if (IS_ENABLED(CFG_CORE_ASYNC_NOTIF)) { + notif_deliver_atomic_event(NOTIF_EVENT_STARTED); + args->a0 = OPTEE_ABI_RETURN_OK; + } else { + args->a0 = OPTEE_ABI_RETURN_UNKNOWN_FUNCTION; + } + break; + case OPTEE_ABI_GET_ASYNC_NOTIF_VALUE: + if (IS_ENABLED(CFG_CORE_ASYNC_NOTIF)) + get_async_notif_value(args); + else + args->a0 = OPTEE_ABI_RETURN_UNKNOWN_FUNCTION; + break; + + default: + args->a0 = OPTEE_ABI_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_abi_args *args) +{ + args->a0 = tee_entry_generic_get_api_call_count(); +} + +void __weak tee_entry_get_api_uuid(struct thread_abi_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_abi_args *args) +{ + args->a0 = OPTEE_MSG_REVISION_MAJOR; + args->a1 = OPTEE_MSG_REVISION_MINOR; +} + +void __weak tee_entry_get_os_uuid(struct thread_abi_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_abi_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/riscv/tee/sub.mk b/optee/optee_os/core/arch/riscv/tee/sub.mk new file mode 100644 index 0000000..958c87a --- /dev/null +++ b/optee/optee_os/core/arch/riscv/tee/sub.mk @@ -0,0 +1,2 @@ +srcs-y += entry_fast.c +cppflags-entry_fast.c-y += -DTEE_IMPL_GIT_SHA1=$(TEE_IMPL_GIT_SHA1) diff --git a/optee/optee_os/core/core.mk b/optee/optee_os/core/core.mk new file mode 100644 index 0000000..71c4699 --- /dev/null +++ b/optee/optee_os/core/core.mk @@ -0,0 +1,177 @@ +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)) +_CFG_CORE_ASYNC_NOTIF_DEFAULT_IMPL ?= $(CFG_CORE_ASYNC_NOTIF) +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..7679f32 --- /dev/null +++ b/optee/optee_os/core/crypto.mk @@ -0,0 +1,319 @@ +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 + +# 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 + +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 := $(call cfg-one-enabled, CFG_CRYPTO_XTS CFG_CRYPTO_CCM \ + CFG_CRYPTO_AES) +_CFG_CORE_LTC_AES_ACCEL := $(CFG_CORE_CRYPTO_AES_ACCEL) +_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_MD5_DESC := $(call cfg-one-enabled, _CFG_CORE_LTC_MD5_DESC \ + _CFG_CORE_LTC_MD5) +_CFG_CORE_LTC_SHA1_DESC := $(call cfg-one-enabled, _CFG_CORE_LTC_SHA1_DESC \ + _CFG_CORE_LTC_SHA1) +_CFG_CORE_LTC_SHA224_DESC := $(call cfg-one-enabled, _CFG_CORE_LTC_SHA224_DESC \ + _CFG_CORE_LTC_SHA224) +_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..47fd61f --- /dev/null +++ b/optee/optee_os/core/crypto/aes-gcm-ghash-tbl.c @@ -0,0 +1,144 @@ +// 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 + +/* + * 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..c16c138 --- /dev/null +++ b/optee/optee_os/core/crypto/aes-gcm.c @@ -0,0 +1,547 @@ +// 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; + uint32_t lower = 0; + + c = TEE_U64_FROM_BIG_ENDIAN(state->ctr[1]); + lower = c + 1; + c = (c & GENMASK_64(63, 32)) | lower; + state->ctr[1] = TEE_U64_TO_BIG_ENDIAN(c); +} + +void internal_aes_gcm_dec_ctr(struct internal_aes_gcm_state *state) +{ + uint64_t c = 0; + uint32_t lower = 0; + + c = TEE_U64_FROM_BIG_ENDIAN(state->ctr[1]); + lower = c - 1; + c = (c & GENMASK_64(63, 32)) | lower; + state->ctr[1] = 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..7fdcecd --- /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 = calloc(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..7b849bf --- /dev/null +++ b/optee/optee_os/core/crypto/crypto.c @@ -0,0 +1,955 @@ +// 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 + +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 && *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 montgomery_keypair *key + __unused, + size_t key_size_bits __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +TEE_Result crypto_acipher_gen_x25519_key(struct montgomery_keypair + *key __unused, + size_t key_size __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +TEE_Result crypto_acipher_x25519_shared_secret(struct montgomery_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_X448) +TEE_Result crypto_acipher_alloc_x448_keypair(struct montgomery_keypair *key + __unused, + size_t key_size_bits __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +TEE_Result crypto_acipher_gen_x448_key(struct montgomery_keypair *key __unused, + size_t key_size __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +TEE_Result crypto_acipher_x448_shared_secret(struct montgomery_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..0b69d99 --- /dev/null +++ b/optee/optee_os/core/crypto/sm3-hmac.c @@ -0,0 +1,112 @@ +// 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 "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..b0d9a8e --- /dev/null +++ b/optee/optee_os/core/crypto/sm3.c @@ -0,0 +1,320 @@ +// 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; +} + +#define SHL(x, n) ((x) << (n)) + +static uint32_t rotl(uint32_t val, int shift) +{ + shift &= 0x1F; + + if (shift == 0) + return val; + + return SHL(val, shift) | (val >> (32 - shift)); +} + +#define ROTL(x, n) rotl((x), (n)) + +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 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..8d4c1dc --- /dev/null +++ b/optee/optee_os/core/drivers/atmel_piobu.c @@ -0,0 +1,481 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2022 Microchip + * + * Driver for AT91 PIOBU + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SECUMOD_MAX_PINS (piobu_device->compat->max_pins) +#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_FNTRST 0x1 + +/* + * PIOBU instance data + * @compat - Reference to compat data passed at driver initialization + */ +struct piobu_instance { + struct piobu_compat *compat; +}; + +/* + * @max_pins the number of the tamper I/Os + * @of_jtagcr offset of SECUMOD JTAG Protection Control Register + * @of_bmpr offset of SECUMOD Backup Mode Protection Register + * @of_nmpr offset of SECUMOD Normal Mode Protection Register + * @of_niepr offset of SECUMOD Normal Interrupt Enable Protection Register + * @of_nidpr offset of SECUMOD Normal Interrupt Disable Protection Register + * @of_nimpr offset of SECUMOD Normal Interrupt Mask Protection Register + * @of_wkpr offset of SECUMOD Wake-up Register + */ +struct piobu_compat { + uint8_t max_pins; + uint8_t of_jtagcr; + uint8_t of_bmpr; + uint8_t of_nmpr; + uint8_t of_niepr; + uint8_t of_nidpr; + uint8_t of_nimpr; + uint8_t of_wkpr; +}; + +/* Expects at most a single instance */ +static struct piobu_instance *piobu_device; + +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 secumod_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 secumod_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 secumod_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 secumod_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 +secumod_gpio_get_interrupt(struct gpio_chip *chip __unused, + unsigned int gpio_pin) +{ + vaddr_t nimpr_addr = secumod_base + piobu_device->compat->of_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 secumod_gpio_set_interrupt(struct gpio_chip *chip __unused, + unsigned int gpio_pin, + enum gpio_interrupt interrupt) +{ + vaddr_t niepr_addr = secumod_base + piobu_device->compat->of_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 = secumod_gpio_get_direction, + .set_direction = secumod_gpio_set_direction, + .get_value = secumod_gpio_get_value, + .set_value = secumod_gpio_set_value, + .get_interrupt = secumod_gpio_get_interrupt, + .set_interrupt = secumod_gpio_set_interrupt, +}; + +static TEE_Result secumod_dt_get(struct dt_pargs *pargs, void *data, + struct gpio **out_gpio) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct gpio *gpio = NULL; + struct gpio_chip *chip = data; + + res = gpio_dt_alloc_pin(pargs, &gpio); + if (res) + return res; + + if (gpio_protected & BIT32(gpio->pin)) { + free(gpio); + return TEE_ERROR_GENERIC; + } + + gpio->chip = chip; + *out_gpio = gpio; + + return TEE_SUCCESS; +} + +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) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + secumod_itr_handler.chip = interrupt_get_main_chip(); + + res = interrupt_add_configure_handler(&secumod_itr_handler, + IRQ_TYPE_LEVEL_HIGH, 7); + if (res) + panic(); + + interrupt_enable(secumod_itr_handler.chip, 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 */ + secumod_gpio_set_interrupt(&secumod_chip, gpio_pin, + GPIO_INTERRUPT_ENABLE); + + /* Enable Intrusion Detection */ + io_setbits32(secumod_base + piobu_device->compat->of_nmpr, + SECUMOD_PIN_VAL(gpio_pin)); + + /* Enable Wakeup */ + if (PIOBU_PIN_WAKEUP(config)) + io_setbits32(secumod_base + piobu_device->compat->of_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 + piobu_device->compat->of_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 + piobu_device->compat->of_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) +{ + size_t size = 0; + + if (secumod_base) + return TEE_ERROR_GENERIC; + + piobu_device = calloc(1, sizeof(*piobu_device)); + if (!piobu_device) + return TEE_ERROR_OUT_OF_MEMORY; + + piobu_device->compat = (struct piobu_compat *)compat_data; + + 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(); + + assert(gpio_ops_is_valid(&atmel_piobu_ops)); + + return gpio_register_provider(fdt, node, secumod_dt_get, &secumod_chip); +} + +static const struct piobu_compat sama5d2_compat = { + .max_pins = 8, + .of_jtagcr = 0x68, + .of_bmpr = 0x7C, + .of_nmpr = 0x80, + .of_niepr = 0x84, + .of_nidpr = 0x88, + .of_nimpr = 0x8C, + .of_wkpr = 0x90, +}; + +static const struct piobu_compat sama7g54_compat = { + .max_pins = 4, + .of_jtagcr = 0x70, + .of_bmpr = 0x84, + .of_nmpr = 0x88, + .of_niepr = 0x8C, + .of_nidpr = 0x90, + .of_nimpr = 0x94, + .of_wkpr = 0x98, +}; + +static const struct dt_device_match atmel_secumod_match_table[] = { + { + .compatible = "atmel,sama5d2-secumod", + .compat_data = &sama5d2_compat, + }, + { + .compatible = "microchip,sama7g5-secumod", + .compat_data = &sama7g54_compat, + }, + { } +}; + +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..ada1c2f --- /dev/null +++ b/optee/optee_os/core/drivers/atmel_rstc.c @@ -0,0 +1,94 @@ +// 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) + +#define AT91_RSTC_GRSTR 0xE4 +#define AT91_RSTC_GRSTR_USB(x) SHIFT_U32(1, 4 + (x)) + +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) + ; +} + +void sam_rstc_usb_por(unsigned char id, bool enable) +{ + if (!atmel_rstc_available()) + panic(); + + if (enable) + io_setbits32(rstc_base + AT91_RSTC_GRSTR, + AT91_RSTC_GRSTR_USB(id)); + else + io_clrbits32(rstc_base + AT91_RSTC_GRSTR, + AT91_RSTC_GRSTR_USB(id)); +} + +/* Non-null reference for compat data */ +static const uint8_t rstc_always_secure; + +static TEE_Result atmel_rstc_probe(const void *fdt, int node, + const void *compat_data) + +{ + size_t size = 0; + + if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC) + return TEE_ERROR_BAD_PARAMETERS; + + if (compat_data != &rstc_always_secure) + 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" }, + { + .compatible = "microchip,sama7g5-rstc", + .compat_data = &rstc_always_secure, + }, + { } +}; + +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..55e5ebb --- /dev/null +++ b/optee/optee_os/core/drivers/atmel_rtc.c @@ -0,0 +1,329 @@ +// 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 }, +}; + +/* Non-null reference for compat data */ +static const uint8_t rtc_always_secure; + +static TEE_Result atmel_rtc_probe(const void *fdt, int node, + const void *compat_data) +{ + 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; + + if (compat_data != &rtc_always_secure) + 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" }, + { + .compatible = "microchip,sama7g5-rtc", + .compat_data = &rtc_always_secure, + }, + { } +}; + +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..32aa867 --- /dev/null +++ b/optee/optee_os/core/drivers/atmel_saic.c @@ -0,0 +1,341 @@ +// 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; + +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 interrupt_main_handler(void) +{ + uint32_t irqnr = saic_read_reg(AT91_AIC_IVR); + + interrupt_call_handlers(&saic.chip, 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 const struct itr_ops saic_ops = { + .add = saic_add, + .mask = saic_disable, + .unmask = saic_enable, + .enable = saic_enable, + .disable = saic_disable, +}; + +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; +} + +static struct saic_data 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"); + return TEE_ERROR_GENERIC; + } + + saic.chip.ops = &saic_ops; + saic.nr_irqs = SAMA5D2_AIC_MAX_IRQS; + + saic_init_external(fdt, node); + saic_init_hw(); + + interrupt_main_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..01aa723 --- /dev/null +++ b/optee/optee_os/core/drivers/atmel_shdwc.c @@ -0,0 +1,234 @@ +// 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) + +/* + * @type_offset offset of Memory Device Register + * @type_mask mask of Memory Device Type in Memory Device Register + */ +struct ddrc_reg_config { + uint32_t type_offset; + uint32_t type_mask; +}; + +/* + * @shdwc_always_secure Is peripheral SHDWC always secured? + * @ddrc DDR controller configurations + */ +struct shdwc_compat { + bool shdwc_always_secure; + struct ddrc_reg_config ddrc; +}; + +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) +{ + int ddr_node = 0; + size_t size = 0; + uint32_t ddr = AT91_DDRSDRC_MD_LPDDR2; + struct shdwc_compat *compat = (struct shdwc_compat *)compat_data; + + /* + * 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; + + if (!compat->shdwc_always_secure) + matrix_configure_periph_secure(AT91C_ID_SYS); + + if (dt_map_dev(fdt, node, &shdwc_base, &size, DT_MAP_AUTO) < 0) + return TEE_ERROR_GENERIC; + + if (!compat->ddrc.type_mask) + return TEE_SUCCESS; + + 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 + compat->ddrc.type_offset); + ddr &= compat->ddrc.type_mask; + 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 shdwc_compat sama5d2_compat = { + .shdwc_always_secure = false, + .ddrc = { + .type_offset = AT91_DDRSDRC_MDR, + .type_mask = AT91_DDRSDRC_MD, + } +}; + +static const struct shdwc_compat sama7g5_compat = { + .shdwc_always_secure = true, +}; + +static const struct dt_device_match atmel_shdwc_match_table[] = { + { + .compatible = "atmel,sama5d2-shdwc", + .compat_data = &sama5d2_compat + }, + { + .compatible = "microchip,sama7g5-shdwc", + .compat_data = &sama7g5_compat, + }, + { } +}; + +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..ca6f750 --- /dev/null +++ b/optee/optee_os/core/drivers/atmel_tcb.c @@ -0,0 +1,204 @@ +// 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 + +#ifdef CFG_SAMA7G5 +static const char * const tcb_clocks[] = { + "t0_clk", "t1_clk", "t2_clk", "slow_clk"}; +#else +static const char * const tcb_clocks[] = { "t0_clk", "gclk", "slow_clk" }; +#endif +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; +} + +TEE_Result tee_time_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; +} + +uint32_t tee_time_get_sys_time_protection_level(void) +{ + return 1000; +} + +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..2db5ef2 --- /dev/null +++ b/optee/optee_os/core/drivers/atmel_trng.c @@ -0,0 +1,122 @@ +// 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" }, + { .compatible = "microchip,sama7g5-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..3d29046 --- /dev/null +++ b/optee/optee_os/core/drivers/atmel_wdt.c @@ -0,0 +1,398 @@ +// 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) /* Watchdog Disable of WDT on bit 15 */ +#define WDT_MR_WDDIS_DWDT BIT(12) /* Watchdog Disable of DWDT on bit 12 */ +#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) + +/* DWDT: Watchdog Timer Mode Register */ +#define WDT_MR_PERIODRST BIT(4) +#define WDT_MR_RPTHRST BIT(5) + +/* DWDT: Watchdog Timer Value Register (Read-only) */ +#define WDT_VR 0x8 +#define WDT_VR_COUNTER_SHIFT 0 +#define WDT_VR_COUNTER_MASK GENMASK_32(11, 0) + +/* DWDT: Watchdog Timer Window Level Register */ +#define WDT_WL 0xc +#define WDT_WL_RPTH_SHIFT 16 +#define WDT_WL_RPTH_MASK GENMASK_32(27, 16) +#define WDT_WL_PERIOD_SHIFT 0 +#define WDT_WL_PERIOD_MASK GENMASK_32(11, 0) + +/* DWDT: Watchdog Timer Interrupt Level Register */ +#define WDT_IL 0x10 +#define WDT_IL_LVLTH_SHIFT 0 +#define WDT_IL_LVLTH_MASK GENMASK_32(11, 0) + +/* DWDT: Watchdog Timer Interrupt Enable/Disable/Status/Mask Register */ +#define WDT_IER 0x14 +#define WDT_IDR 0x18 +#define WDT_ISR 0x1c +#define WDT_IMR 0x20 +#define WDT_NSRPTHINT BIT(4) +#define WDT_NSPERINT BIT(3) +#define WDT_LVLINT BIT(2) +#define WDT_RPTHINT BIT(1) +#define WDT_PERINT BIT(0) + +/* + * 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, dis_mask) (!((mr) & (dis_mask))) + +enum wdt_type { + WDT_TYPE_WDT, /* Watchdog Timer */ + WDT_TYPE_DWDT, /* Dual Watchdog Timer */ +}; + +struct wdt_compat { + bool wdt_ps; /* Is Peripheral SHDWC Programmable Secure */ + enum wdt_type type; /* Type of Watchdog Timer */ + uint32_t dis_mask; /* Mask of Watchdog Disable in Mode Register */ +}; + +struct atmel_wdt { + struct wdt_chip chip; + enum wdt_type type; + uint32_t dis_mask; + vaddr_t base; + 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); + + if (wdt->type == WDT_TYPE_WDT) { + wdt->mr &= ~WDT_MR_WDV; + wdt->mr |= WDT_MR_WDV_SET(SEC_TO_WDT(timeout)); + + /* WDV and WDD only be updated when the watchdog is running */ + if (WDT_ENABLED(wdt->mr, wdt->dis_mask)) + atmel_wdt_write_sleep(wdt, WDT_MR, wdt->mr); + } else { + io_write32(wdt->base + WDT_WL, + SHIFT_U32(SEC_TO_WDT(timeout), WDT_WL_PERIOD_SHIFT)); + } + + 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->dis_mask; + 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->dis_mask; + 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 = 0; + + if (wdt->type == WDT_TYPE_WDT) { + sr = io_read32(wdt->base + WDT_SR); + + if (sr & WDT_SR_DUNF) + DMSG("Watchdog Underflow"); + if (sr & WDT_SR_DERR) + DMSG("Watchdog Error"); + } else if (wdt->type == WDT_TYPE_DWDT) { + sr = io_read32(wdt->base + WDT_ISR); + + if (sr & WDT_NSRPTHINT) + DMSG("NS Watchdog Repeat Threshold Interrupt"); + if (sr & WDT_NSPERINT) + DMSG("NS Watchdog Period Interrupt"); + if (sr & WDT_LVLINT) + DMSG("Watchdog Level Threshold Interrupt"); + if (sr & WDT_RPTHINT) + DMSG("Watchdog Repeat Threshold Interrupt"); + if (sr & WDT_PERINT) + DMSG("Watchdog Period Interrupt"); + } + + 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, wdt->dis_mask)) { + mr = io_read32(wdt->base + WDT_MR); + if (WDT_ENABLED(mr, wdt->dis_mask)) + io_write32(wdt->base + WDT_MR, mr | wdt->dis_mask); + } + + if (wdt->type == WDT_TYPE_WDT) { + /* 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)); + } else if (wdt->type == WDT_TYPE_DWDT) { + /* Enable interrupt */ + io_write32(wdt->base + WDT_ISR, WDT_PERINT); + /* Disable watchdog in debug and idle */ + wdt->mr |= WDT_MR_WDDBGHLT | WDT_MR_WDIDLEHLT; + /* Enable watchdog period reset */ + wdt->mr |= WDT_MR_PERIODRST; + io_write32(wdt->base + WDT_WL, + SHIFT_U32(SEC_TO_WDT(WDT_DEFAULT_TIMEOUT), + WDT_WL_PERIOD_SHIFT)); + } else { + panic("Invalid Watchdog"); + } + + /* + * If the watchdog was enabled, write the configuration which will ping + * the watchdog. + */ + if (WDT_ENABLED(wdt->mr, wdt->dis_mask)) + 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) +{ + const struct wdt_compat *compat = compat_data; + 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 = NULL; + TEE_Result res = TEE_ERROR_GENERIC; + + if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC) + return TEE_ERROR_BAD_PARAMETERS; + + if (compat->wdt_ps) + 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; + wdt->type = compat->type; + wdt->dis_mask = compat->dis_mask; + + it = dt_get_irq_type_prio(fdt, node, &irq_type, &irq_prio); + if (it == DT_INFO_INVALID_INTERRUPT) + goto err_free; + + res = interrupt_alloc_add_conf_handler(interrupt_get_main_chip(), + it, atmel_wdt_itr_cb, 0, wdt, + irq_type, irq_prio, &it_hdlr); + if (res) + goto err_free; + + if (dt_map_dev(fdt, node, &wdt->base, &size, DT_MAP_AUTO) < 0) + goto err_remove_handler; + + /* Get current state of the watchdog */ + wdt->mr = io_read32(wdt->base + WDT_MR) & wdt->dis_mask; + + atmel_wdt_init_hw(wdt); + interrupt_enable(it_hdlr->chip, it_hdlr->it); + + res = watchdog_register(&wdt->chip); + if (res) + goto err_disable_unmap; + + atmel_wdt_register_pm(wdt); + + return TEE_SUCCESS; + +err_disable_unmap: + interrupt_disable(it_hdlr->chip, it_hdlr->it); + core_mmu_remove_mapping(MEM_AREA_IO_SEC, (void *)wdt->base, size); +err_remove_handler: + interrupt_remove_free_handler(it_hdlr); +err_free: + free(wdt); + + return TEE_ERROR_GENERIC; +} + +static const struct wdt_compat sama5d2_compat = { + .wdt_ps = true, + .type = WDT_TYPE_WDT, + .dis_mask = WDT_MR_WDDIS, +}; + +static const struct wdt_compat sama7g5_compat = { + .wdt_ps = false, + .type = WDT_TYPE_DWDT, + .dis_mask = WDT_MR_WDDIS_DWDT, +}; + +static const struct dt_device_match atmel_wdt_match_table[] = { + { + .compatible = "atmel,sama5d4-wdt", + .compat_data = &sama5d2_compat, + }, + { + .compatible = "microchip,sama7g5-wdt", + .compat_data = &sama7g5_compat, + }, + { } +}; + +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..96e3097 --- /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"); + 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..536197f --- /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 TEE_Result stm32mp_clk_dt_get_clk(struct dt_pargs *pargs, + void *data __unused, + struct clk **out_clk) +{ + unsigned long clock_id = pargs->args[0]; + struct clk *clk = NULL; + + if (pargs->args_count != 1) + return TEE_ERROR_BAD_PARAMETERS; + + clk = stm32mp_rcc_clock_id_to_clk(clock_id); + if (!clk) + return TEE_ERROR_BAD_PARAMETERS; + + *out_clk = clk; + + return TEE_SUCCESS; +} + +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..738b348 --- /dev/null +++ b/optee/optee_os/core/drivers/clk/clk-stm32mp13.c @@ -0,0 +1,2748 @@ +// 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) { + if (fdt_err == -FDT_ERR_NOTFOUND) { + /* Oscillator not found means it is not wired */ + osci->freq = 0; + } else { + 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 UDIV_ROUND_NEAREST(fvco, 100000) * 100000; +}; + +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 TEE_Result +clk_stm32_composite_get_duty_cycle(struct clk *clk, + struct clk_duty_cycle *duty_cycle) +{ + struct clk_stm32_composite_cfg *cfg = clk->priv; + uint32_t val = stm32_div_get_value(cfg->div_id); + + duty_cycle->num = (val + 1) / 2; + duty_cycle->den = val + 1; + + return TEE_SUCCESS; +} + +static const struct clk_ops clk_stm32_composite_duty_cycle_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, + .get_duty_cycle = clk_stm32_composite_get_duty_cycle, +}; + +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_duty_cycle_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 TEE_Result clk_stm32_oscillator_enable(struct clk *clk) +{ + struct clk_stm32_gate_cfg *cfg = clk->priv; + + if (clk->rate == 0U) + return TEE_SUCCESS; + + return stm32_gate_rdy_enable(cfg->gate_id); +} + +static void clk_stm32_oscillator_disable(struct clk *clk) +{ + struct clk_stm32_gate_cfg *cfg = clk->priv; + + if (clk->rate == 0U) + return; + + if (stm32_gate_rdy_disable(cfg->gate_id)) + panic(); +} + +static const struct clk_ops clk_stm32_oscillator_ops = { + .enable = clk_stm32_oscillator_enable, + .disable = clk_stm32_oscillator_disable, +}; + +/* + * Each oscillator has 1 parent which reference is NULL here + * but set during initialization. + */ +#define STM32_OSCILLATOR(_name, _gate_id)\ + struct clk _name = {\ + .ops = &clk_stm32_oscillator_ops,\ + .priv = &(struct clk_stm32_gate_cfg) {\ + .gate_id = (_gate_id),\ + },\ + .name = #_name,\ + .num_parents = 1, \ + .parents = { NULL }, \ + } + +static STM32_OSCILLATOR(ck_hsi, GATE_HSI); +static STM32_OSCILLATOR(ck_hse, GATE_HSE); +static STM32_OSCILLATOR(ck_csi, GATE_CSI); +static STM32_OSCILLATOR(ck_lsi, GATE_LSI); +static STM32_OSCILLATOR(ck_lse, 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 = CLK_SET_RATE_PARENT, + .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 = CLK_SET_RATE_PARENT, + .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 = CLK_SET_PARENT_PRE_ENABLE | CLK_SET_RATE_PARENT, + .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 = CLK_SET_PARENT_PRE_ENABLE | CLK_SET_RATE_PARENT, + .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 = CLK_SET_PARENT_PRE_ENABLE | CLK_SET_RATE_PARENT, + .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_adc1, &ck_mlahb, 0, GATE_ADC1); +static STM32_GATE(ck_adc2, &ck_mlahb, 0, GATE_ADC2); +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_PMBCTRL); +static STM32_GATE(ck_hdp, &ck_pclk3, 0, GATE_HDP); +static STM32_GATE(ck_stgenro, &ck_pclk4, 0, GATE_STGENRO); +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_DMA3); +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_CRC1); +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); +static STM32_GATE(ck_spi1, &ck_pclk2, 0, GATE_SPI1); +static STM32_GATE(ck_spi2, &ck_pclk1, 0, GATE_SPI2); +static STM32_GATE(ck_spi3, &ck_pclk1, 0, GATE_SPI3); +static STM32_GATE(ck_spi4, &ck_pclk6, 0, GATE_SPI4); +static STM32_GATE(ck_spi5, &ck_pclk6, 0, GATE_SPI5); + +/* 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_off, &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, + [ADC1] = &ck_adc1, + [ADC2] = &ck_adc2, + [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, + [SPI1] = &ck_spi1, + [SPI2] = &ck_spi2, + [SPI3] = &ck_spi3, + [SPI4] = &ck_spi4, + [SPI5] = &ck_spi5, + [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..a5b7270 --- /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 TEE_Result stm32mp1_clk_dt_get_clk(struct dt_pargs *pargs, + void *data __unused, + struct clk **out_clk) +{ + unsigned long clock_id = pargs->args[0]; + struct clk *clk = NULL; + + if (pargs->args_count != 1) + return TEE_ERROR_BAD_PARAMETERS; + + clk = clock_id_to_clk(clock_id); + if (!clk) + return TEE_ERROR_BAD_PARAMETERS; + + *out_clk = clk; + + return TEE_SUCCESS; +} + +/* 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..43122ff --- /dev/null +++ b/optee/optee_os/core/drivers/clk/clk.c @@ -0,0 +1,548 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021, Bootlin + * Copyright (c) 2023, STMicroelectronics + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Global clock tree access protection complying the power state transitions */ +static struct mutex_pm_aware mu = MUTEX_PM_AWARE_INITIALIZER; + +#ifdef CFG_DRIVERS_CLK_PRINT_TREE +static SLIST_HEAD(, clk) clock_list = SLIST_HEAD_INITIALIZER(clock_list); +#endif + +static void lock_clk(void) +{ + mutex_pm_aware_lock(&mu); +} + +static void unlock_clk(void) +{ + mutex_pm_aware_unlock(&mu); +} + +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 || !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); + +#ifdef CFG_DRIVERS_CLK_PRINT_TREE + SLIST_INSERT_HEAD(&clock_list, clk, link); +#endif + + 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) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + lock_clk(); + res = clk_enable_no_lock(clk); + unlock_clk(); + + return res; +} + +void clk_disable(struct clk *clk) +{ + lock_clk(); + clk_disable_no_lock(clk); + unlock_clk(); +} + +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); + + assert(!(clk->flags & CLK_SET_RATE_PARENT) || clk->parent); + if (clk->flags & CLK_SET_RATE_PARENT) { + res = clk_set_rate_no_lock(clk->parent, rate); + if (res) + return res; + rate = clk_get_rate(clk->parent); + } + + if (clk->ops->set_rate) { + if (clk->flags & CLK_SET_RATE_UNGATE) { + res = clk_enable_no_lock(clk); + if (res) + return res; + } + + res = clk->ops->set_rate(clk, rate, parent_rate); + + if (clk->flags & CLK_SET_RATE_UNGATE) + clk_disable_no_lock(clk); + + if (res) + return res; + } + + clk_compute_rate_no_lock(clk); + + return TEE_SUCCESS; +} + +TEE_Result clk_set_rate(struct clk *clk, unsigned long rate) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + lock_clk(); + + 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); + + unlock_clk(); + + 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) { + if (clk->flags & CLK_SET_PARENT_PRE_ENABLE) { + res = clk_enable_no_lock(parent); + if (res) + return res; + } + + 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"); + + if (clk->flags & CLK_SET_PARENT_PRE_ENABLE) { + /* Balance refcount when new parent was pre-enabled */ + clk_disable_no_lock(parent); + } + } + + return res; +} + +TEE_Result clk_set_parent(struct clk *clk, struct clk *parent) +{ + size_t pidx = 0; + TEE_Result res = TEE_ERROR_GENERIC; + + if (clk_get_parent_idx(clk, parent, &pidx) || !clk->ops->set_parent) + return TEE_ERROR_BAD_PARAMETERS; + + lock_clk(); + 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: + unlock_clk(); + + 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); +} + +TEE_Result clk_get_rates_steps(struct clk *clk, unsigned long *min, + unsigned long *max, unsigned long *step) +{ + if (!clk->ops->get_rates_steps) + return TEE_ERROR_NOT_SUPPORTED; + + return clk->ops->get_rates_steps(clk, min, max, step); +} + +TEE_Result clk_get_duty_cycle(struct clk *clk, + struct clk_duty_cycle *duty_cycle) +{ + if (clk->ops->get_duty_cycle) + return clk->ops->get_duty_cycle(clk, duty_cycle); + + if (clk->parent && (clk->flags & CLK_DUTY_CYCLE_PARENT)) + return clk_get_duty_cycle(clk->parent, duty_cycle); + + /* Default set 50% duty cycle */ + duty_cycle->num = 1; + duty_cycle->den = 2; + + return TEE_SUCCESS; +} + +/* Return updated message buffer position of NULL on failure */ +static __printf(3, 4) char *add_msg(char *cur, char *end, const char *fmt, ...) +{ + va_list ap = { }; + int max_len = end - cur; + int ret = 0; + + va_start(ap, fmt); + ret = vsnprintf(cur, max_len, fmt, ap); + va_end(ap); + + if (ret < 0 || ret >= max_len) + return NULL; + + return cur + ret; +} + +static struct clk *find_next_clk(struct clk *parent __maybe_unused, + struct clk *sibling __maybe_unused) +{ + struct clk *clk = NULL; + +#ifdef CFG_DRIVERS_CLK_PRINT_TREE + if (sibling) + clk = SLIST_NEXT(sibling, link); + else + clk = SLIST_FIRST(&clock_list); + + while (clk && clk->parent != parent) + clk = SLIST_NEXT(clk, link); +#endif + + return clk; +} + +static bool clk_is_parent_last_child(struct clk *clk) +{ + return !find_next_clk(clk->parent, clk); +} + +static bool indent_last_node_already_found(struct clk *node_clk, + int node_indent, int cur_indent) +{ + struct clk *clk = node_clk; + int n = 0; + + /* Find parent clock at level @node_indent - @cur_indent - 1 */ + for (n = 0; n < node_indent - cur_indent - 1; n++) + clk = clk->parent; + + return clk_is_parent_last_child(clk); +} + +static void __maybe_unused print_clk(struct clk *clk, int indent) +{ + static const char * const rate_unit[] = { "Hz", "kHz", "MHz", "GHz" }; + int max_unit = ARRAY_SIZE(rate_unit); + unsigned long rate = 0; + char msg_buf[128] = { }; + char *msg_end = msg_buf + sizeof(msg_buf); + char *msg = msg_buf; + int n = 0; + + /* + * Currently prints the clock state based on the clock refcount. + * A future change could print the hardware clock state when + * related clock driver provides a struct clk_ops::is_enabled handler + */ + + if (indent) { + /* Indent for root clock level */ + msg = add_msg(msg, msg_end, " "); + if (!msg) + goto out; + + /* Indent for root parent to clock parent levels */ + for (n = 0; n < indent - 1; n++) { + if (indent_last_node_already_found(clk, indent, n)) + msg = add_msg(msg, msg_end, " "); + else + msg = add_msg(msg, msg_end, "| "); + + if (!msg) + goto out; + } + + /* Clock indentation */ + if (clk_is_parent_last_child(clk)) + msg = add_msg(msg, msg_end, "`-- "); + else + msg = add_msg(msg, msg_end, "|-- "); + } else { + /* Root clock indentation */ + msg = add_msg(msg, msg_end, "o- "); + } + if (!msg) + goto out; + + rate = clk_get_rate(clk); + for (n = 1; rate && !(rate % 1000) && n < max_unit; n++) + rate /= 1000; + + msg = add_msg(msg, msg_end, "%s \t(%3s / refcnt %u / %ld %s)", + clk_get_name(clk), + refcount_val(&clk->enabled_count) ? "on " : "off", + refcount_val(&clk->enabled_count), + rate, rate_unit[n - 1]); + if (!msg) + goto out; + +out: + if (!msg) + snprintf(msg_end - 4, 4, "..."); + + DMSG("%s", msg_buf); +} + +static void print_tree(void) +{ + struct clk *clk = NULL; + struct clk *parent = NULL; + struct clk *next = NULL; + int indent = -1; + +#ifdef CFG_DRIVERS_CLK_PRINT_TREE + if (SLIST_EMPTY(&clock_list)) { + DMSG("-- No registered clock"); + return; + } +#endif + + while (true) { + next = find_next_clk(parent, clk); + if (next) { + print_clk(next, indent + 1); + /* Enter the subtree of the next clock */ + parent = next; + indent++; + clk = NULL; + } else { + /* + * We've processed all children at this level. + * If parent is NULL we're at the top and are done. + */ + if (!parent) + break; + /* + * Move up one level to resume with the next + * child clock of the parent. + */ + clk = parent; + parent = clk->parent; + indent--; + } + } +} + +void clk_print_tree(void) +{ + if (IS_ENABLED(CFG_DRIVERS_CLK_PRINT_TREE) && + TRACE_LEVEL >= TRACE_DEBUG) { + DMSG("Clock tree summary (informative):"); + print_tree(); + } +} 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..fcb3d3c --- /dev/null +++ b/optee/optee_os/core/drivers/clk/clk_dt.c @@ -0,0 +1,217 @@ +// 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; + void *out_clk = NULL; + + res = dt_driver_device_from_node_idx_prop(prop_name, fdt, nodeoffset, + clk_idx, DT_DRIVER_CLK, + &out_clk); + if (!res) + *clk = out_clk; + + 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 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 (res) + return; + assert(clk); + + 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..d8261f5 --- /dev/null +++ b/optee/optee_os/core/drivers/clk/sam/at91_clk.h @@ -0,0 +1,280 @@ +/* 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); + +TEE_Result at91_pmc_clk_get(unsigned int type, unsigned int idx, + struct clk **clk); + +TEE_Result pmc_clk_get(struct pmc_data *pmc, unsigned int type, + unsigned int idx, struct clk **clk); + +struct clk *at91_sckc_clk_get(void); + +struct pmc_data *pmc_data_allocate(unsigned int ncore, unsigned int nsystem, + unsigned int nperiph, unsigned int ngck, + unsigned int npck); + +TEE_Result clk_dt_pmc_get(struct dt_pargs *args, void *data, struct clk **clk); + +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); + +struct clk *sam9x60_clk_register_frac_pll(struct pmc_data *pmc, + const char *name, + struct clk *parent, + uint8_t id, + const struct clk_pll_charac *charac, + const struct clk_pll_layout *layout, + uint32_t flags); + +struct clk *sam9x60_clk_register_div_pll(struct pmc_data *pmc, + const char *name, + struct clk *parent, + uint8_t id, + const struct clk_pll_charac *charac, + const struct clk_pll_layout *layout, + uint32_t flags, + uint32_t safe_div); + +/* UTMI */ +struct clk * +at91_clk_register_utmi(struct pmc_data *pmc, const char *name, + struct clk *parent); + +struct clk *at91_clk_sama7g5_register_utmi(struct pmc_data *pmc, + const char *name, + struct clk *parent); + +struct clk *sama7_utmi_clk_register(const char *name, + struct clk *parent, + uint8_t id); + +/* 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); + +/* + * @mux_table: when @mux_table is not NULL it shall hold @num_parents cells + */ +struct clk *at91_clk_sama7g5_register_master(struct pmc_data *pmc, + const char *name, + int num_parents, + struct clk **parent, + uint32_t *mux_table, + uint8_t id, + int chg_pid); + +/* 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, + uint32_t *mux_table, + 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..1f30c5c --- /dev/null +++ b/optee/optee_os/core/drivers/clk/sam/at91_generated.c @@ -0,0 +1,194 @@ +// 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; + + if (gck->mux_table) + gck->parent_id = gck->mux_table[index]; + else + gck->parent_id = index; + + return TEE_SUCCESS; +} + +static size_t clk_generated_get_parent(struct clk *clk) +{ + struct clk_generated *gck = clk->priv; + unsigned int i = 0; + + if (gck->mux_table) { + for (i = 0; i < clk_get_num_parents(clk); i++) + if (gck->mux_table[i] == gck->parent_id) + return i; + panic("Can't get correct parent of clock"); + } else { + 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, + uint32_t *mux_table, + 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; + gck->mux_table = mux_table; + + 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..c84a973 --- /dev/null +++ b/optee/optee_os/core/drivers/clk/sam/at91_master.c @@ -0,0 +1,307 @@ +// 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 +#define MASTER_MAX_ID 4 /* Total 5 MCK clocks for SAMA7G5 */ + +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; + uint8_t id; /* ID of MCK clocks for SAMA7G5, MCK0 ~ MCK4 */ + uint8_t parent; /* the source clock for SAMA7G5 MCKx */ +}; + +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, +}; + +static size_t clk_sama7g5_master_get_parent(struct clk *hw) +{ + struct clk_master *master = hw->priv; + size_t i = 0; + + for (i = 0; i < hw->num_parents; i++) + if (master->mux_table[i] == master->parent) + return i; + + panic("Can't get correct parent of clock"); +} + +static TEE_Result clk_sama7g5_master_set_parent(struct clk *hw, size_t index) +{ + struct clk_master *master = hw->priv; + + if (index >= hw->num_parents) + return TEE_ERROR_BAD_PARAMETERS; + + master->parent = master->mux_table[index]; + + return TEE_SUCCESS; +} + +static TEE_Result clk_sama7g5_master_set_rate(struct clk *hw, + unsigned long rate, + unsigned long parent_rate) +{ + struct clk_master *master = hw->priv; + unsigned long div = 0; + + div = UDIV_ROUND_NEAREST(parent_rate, rate); + if (div > (1 << (MASTER_PRES_MAX - 1)) || + (!IS_POWER_OF_TWO(div) && div != 3)) + return TEE_ERROR_BAD_PARAMETERS; + + /* + * Divisor Value: Select the division ratio to be applied to the + * selected clock to generate the corresponding MCKx. + * Value | Description + * 0 | Selected clock divided by 1 + * 1 | Selected clock divided by 2 + * 2 | Selected clock divided by 4 + * 3 | Selected clock divided by 8 + * 4 | Selected clock divided by 16 + * 5 | Selected clock divided by 32 + * 6 | Selected clock divided by 64 + * 7 | Selected clock divided by 3 + */ + if (div == 3) + master->div = MASTER_PRES_MAX; + else + master->div = ffs(div) - 1; + + return TEE_SUCCESS; +} + +static unsigned long clk_sama7g5_master_get_rate(struct clk *hw, + unsigned long parent_rate) +{ + struct clk_master *master = hw->priv; + unsigned long rate = parent_rate >> master->div; + + if (master->div == 7) + rate = parent_rate / 3; + + return rate; +} + +static const struct clk_ops sama7g5_master_ops = { + .set_rate = clk_sama7g5_master_set_rate, + .get_rate = clk_sama7g5_master_get_rate, + .get_parent = clk_sama7g5_master_get_parent, + .set_parent = clk_sama7g5_master_set_parent, +}; + +struct clk *at91_clk_sama7g5_register_master(struct pmc_data *pmc, + const char *name, + int num_parents, + struct clk **parent, + uint32_t *mux_table, + uint8_t id, + int chg_pid) +{ + struct clk_master *master = NULL; + struct clk *hw = NULL; + unsigned int val = 0; + + if (!name || !num_parents || !parent || !mux_table || + id > MASTER_MAX_ID) + return NULL; + + master = calloc(1, sizeof(*master)); + if (!master) + return NULL; + + hw = clk_alloc(name, &sama7g5_master_ops, parent, num_parents); + if (!hw) { + free(master); + return NULL; + } + + hw->priv = master; + master->base = pmc->base; + master->id = id; + master->chg_pid = chg_pid; + master->mux_table = mux_table; + + io_write32(master->base + AT91_PMC_MCR_V2, master->id); + val = io_read32(master->base + AT91_PMC_MCR_V2); + master->parent = (val & AT91_PMC_MCR_V2_CSS_MASK) >> + AT91_PMC_MCR_V2_CSS_SHIFT; + master->div = (val & AT91_PMC_MCR_V2_DIV_MASK) >> MASTER_DIV_SHIFT; + + if (clk_register(hw)) { + clk_free(hw); + free(master); + return NULL; + } + + return hw; +} 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..34983b4 --- /dev/null +++ b/optee/optee_os/core/drivers/clk/sam/at91_pmc.c @@ -0,0 +1,293 @@ +// 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 (clks[i].clk && strcmp(clks[i].clk->name, name) == 0) + return clks[i].clk; + + return NULL; +} + +TEE_Result pmc_clk_get(struct pmc_data *pmc, unsigned int type, + unsigned int idx, struct clk **clk) +{ + unsigned int nclk = 0; + struct pmc_clk *clks = NULL; + + switch (type) { + case PMC_TYPE_CORE: + nclk = pmc->ncore; + clks = pmc->chws; + break; + case PMC_TYPE_SYSTEM: + nclk = pmc->nsystem; + clks = pmc->shws; + break; + case PMC_TYPE_PERIPHERAL: + nclk = pmc->nperiph; + clks = pmc->phws; + break; + case PMC_TYPE_GCK: + nclk = pmc->ngck; + clks = pmc->ghws; + break; + case PMC_TYPE_PROGRAMMABLE: + nclk = pmc->npck; + clks = pmc->pchws; + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + + *clk = pmc_clk_get_by_id(clks, nclk, idx); + if (!*clk) + return TEE_ERROR_BAD_PARAMETERS; + + return TEE_SUCCESS; +} + +TEE_Result clk_dt_pmc_get(struct dt_pargs *clkspec, void *data, + struct clk **out_clk) +{ + unsigned int type = clkspec->args[0]; + unsigned int idx = clkspec->args[1]; + struct pmc_data *pmc_data = data; + + if (clkspec->args_count != 2) + return TEE_ERROR_BAD_PARAMETERS; + + return pmc_clk_get(pmc_data, type, idx, out_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..0eae3a0 --- /dev/null +++ b/optee/optee_os/core/drivers/clk/sam/at91_pmc.h @@ -0,0 +1,289 @@ +/* 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_MASK GENMASK_32(3, 0) +#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) + +/* definitions for the PMC register of SAMA7G5 */ +#define AT91_PMC_MCR_V2 0x30 +#define AT91_PMC_MCR_V2_ID_MASK GENMASK_32(3, 0) +#define AT91_PMC_MCR_V2_ID(_id) ((_id) & AT91_PMC_MCR_V2_ID_MASK) +#define AT91_PMC_MCR_V2_CMD BIT(7) +#define AT91_PMC_MCR_V2_DIV_MASK GENMASK_32(10, 8) +#define AT91_PMC_MCR_V2_DIV1 SHIFT_U32(0, 8) +#define AT91_PMC_MCR_V2_DIV2 SHIFT_U32(1, 8) +#define AT91_PMC_MCR_V2_DIV4 SHIFT_U32(2, 8) +#define AT91_PMC_MCR_V2_DIV8 SHIFT_U32(3, 8) +#define AT91_PMC_MCR_V2_DIV16 SHIFT_U32(4, 8) +#define AT91_PMC_MCR_V2_DIV32 SHIFT_U32(5, 8) +#define AT91_PMC_MCR_V2_DIV64 SHIFT_U32(6, 8) +#define AT91_PMC_MCR_V2_DIV3 SHIFT_U32(7, 8) +#define AT91_PMC_MCR_V2_CSS_SHIFT 16 +#define AT91_PMC_MCR_V2_CSS_MASK GENMASK_32(20, 16) +#define AT91_PMC_MCR_V2_CSS_MD_SLCK SHIFT_U32(0, 16) +#define AT91_PMC_MCR_V2_CSS_TD_SLCK SHIFT_U32(1, 16) +#define AT91_PMC_MCR_V2_CSS_MAINCK SHIFT_U32(2, 16) +#define AT91_PMC_MCR_V2_CSS_MCK0 SHIFT_U32(3, 16) +#define AT91_PMC_MCR_V2_CSS_SYSPLL SHIFT_U32(5, 16) +#define AT91_PMC_MCR_V2_CSS_DDRPLL SHIFT_U32(6, 16) +#define AT91_PMC_MCR_V2_CSS_IMGPLL SHIFT_U32(7, 16) +#define AT91_PMC_MCR_V2_CSS_BAUDPLL SHIFT_U32(8, 16) +#define AT91_PMC_MCR_V2_CSS_AUDIOPLL SHIFT_U32(9, 16) +#define AT91_PMC_MCR_V2_CSS_ETHPLL SHIFT_U32(10, 16) +#define AT91_PMC_MCR_V2_EN BIT(28) + +#define AT91_PMC_XTALF 0x34 +#define AT91_PMC_XTALF_XTALF 7 + +#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..59a6340 --- /dev/null +++ b/optee/optee_os/core/drivers/clk/sam/at91_sckc.c @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause +/* + * Copyright (C) 2013 Boris BREZILLON + * Copyright (C) 2021 Microchip + */ + +#include "at91_clk.h" +#include +#include + +static struct clk *slow_clk; + +#define SLOW_CLOCK_FREQ 32768 + +struct clk *at91_sckc_clk_get(void) +{ + return slow_clk; +} + +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; + + if (slow_clk) + return 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; + } + + res = clk_dt_register_clk_provider(fdt, offs, clk_dt_get_simple_clk, + clk); + if (res) + return res; + + slow_clk = clk; + + return TEE_SUCCESS; +} + +static const struct dt_device_match at91_sckc_match_table[] = { + { .compatible = "atmel,sama5d4-sckc" }, + { .compatible = "microchip,sama7g5-sckc" }, + { } +}; + +DEFINE_DT_DRIVER(at91_sckc_dt_driver) = { + .name = "at91_sckc", + .type = DT_DRIVER_CLK, + .match_table = at91_sckc_match_table, + .probe = 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..d2e603b --- /dev/null +++ b/optee/optee_os/core/drivers/clk/sam/at91_utmi.c @@ -0,0 +1,193 @@ +// 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, +}; + +static struct clk *at91_clk_register_utmi_internal(struct pmc_data *pmc, + const char *name, + const struct clk_ops *ops, + struct clk *parent) +{ + struct clk_utmi *utmi = NULL; + struct clk *clk = NULL; + + clk = clk_alloc(name, 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; +} + +struct clk *at91_clk_register_utmi(struct pmc_data *pmc, + const char *name, + struct clk *parent) +{ + return at91_clk_register_utmi_internal(pmc, name, &utmi_ops, parent); +} + +static TEE_Result clk_utmi_sama7g5_prepare(struct clk *clk) +{ + struct clk *clk_parent = NULL; + struct clk_utmi *utmi = clk->priv; + unsigned long parent_rate = 0; + uint32_t val = 0; + + clk_parent = clk_get_parent(clk); + parent_rate = clk_get_rate(clk_parent); + + switch (parent_rate) { + case 16000000: + val = 0; + break; + case 20000000: + val = 2; + break; + case 24000000: + val = 3; + break; + case 32000000: + val = 5; + break; + default: + EMSG("UTMICK: unsupported main_xtal rate"); + return TEE_ERROR_BAD_PARAMETERS; + } + + io_clrsetbits32(utmi->pmc_base + AT91_PMC_XTALF, AT91_PMC_XTALF_XTALF, + val); + + return TEE_SUCCESS; +} + +static const struct clk_ops sama7g5_utmi_ops = { + .enable = clk_utmi_sama7g5_prepare, + .get_rate = clk_utmi_get_rate, +}; + +struct clk *at91_clk_sama7g5_register_utmi(struct pmc_data *pmc, + const char *name, + struct clk *parent) +{ + return at91_clk_register_utmi_internal(pmc, name, &sama7g5_utmi_ops, + parent); +} diff --git a/optee/optee_os/core/drivers/clk/sam/clk-sam9x60-pll.c b/optee/optee_os/core/drivers/clk/sam/clk-sam9x60-pll.c new file mode 100644 index 0000000..f7853d0 --- /dev/null +++ b/optee/optee_os/core/drivers/clk/sam/clk-sam9x60-pll.c @@ -0,0 +1,520 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2019 Microchip Technology Inc. + */ + +#include +#include +#include +#include +#include +#include "at91_clk.h" + +#define PMC_PLL_CTRL0_DIV_MASK 0xf +#define PMC_PLL_CTRL0_DIV_POS 0 +#define PMC_PLL_CTRL1_MUL_MASK 0xff +#define PMC_PLL_CTRL1_MUL_POS 24 +#define PMC_PLL_CTRL1_FRACR_MASK 0x3fffff +#define PMC_PLL_CTRL1_FRACR_POS 0 + +#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) SHIFT_U64(0xffff, PLL_ICPR_SHIFT(id)) +#define PLL_MAX_COUNT 0x3f +#define PLL_COUNT_SHIFT 8 +#define PLL_OUT_SHIFT 14 + +struct sam9x60_pll_core { + vaddr_t base; + const struct clk_pll_charac *charac; + const struct clk_pll_layout *layout; + struct clk *hw; + uint8_t id; +}; + +struct sam9x60_frac { + struct sam9x60_pll_core core; + uint32_t frac; + uint16_t mul; +}; + +struct sam9x60_div { + struct sam9x60_pll_core core; + uint8_t div; + uint8_t safe_div; +}; + +#define WAIT_PLL_READY_TIMEOUT(_base, _id) \ + ({ \ + uint32_t __timeout = 0; \ + uint32_t _c = 0; \ + \ + while (__timeout++ < 500) { \ + _c = io_read32((_base) + AT91_PMC_PLL_ISR0) & \ + BIT(_id); \ + if (_c) \ + break; \ + wait_cycles(100); \ + } \ + !(_c); \ + }) + +static bool sam9x60_pll_ready(vaddr_t base, int id) +{ + return io_read32(base + AT91_PMC_PLL_ISR0) & BIT(id); +} + +static bool sam9x60_frac_pll_ready(vaddr_t regmap, uint8_t id) +{ + return sam9x60_pll_ready(regmap, id); +} + +static unsigned long sam9x60_frac_pll_recalc_rate(struct clk *hw, + unsigned long parent_rate) +{ + struct sam9x60_frac *frac = hw->priv; + + return parent_rate * (frac->mul + 1) + + UDIV_ROUND_NEAREST((unsigned long long)parent_rate * frac->frac, + 1 << 22); +} + +static TEE_Result sam9x60_frac_pll_set(struct sam9x60_frac *frac) +{ + struct sam9x60_pll_core *core = &frac->core; + vaddr_t regmap = frac->core.base; + unsigned int val = 0; + unsigned int cfrac = 0; + unsigned int cmul = 0; + + io_clrsetbits32(regmap + AT91_PMC_PLL_UPDT, + AT91_PMC_PLL_UPDT_ID_MASK, core->id); + val = io_read32(regmap + AT91_PMC_PLL_CTRL1); + cmul = (val & core->layout->mul_mask) >> core->layout->mul_shift; + cfrac = (val & core->layout->frac_mask) >> core->layout->frac_shift; + + if (sam9x60_frac_pll_ready(regmap, core->id) && + cmul == frac->mul && cfrac == frac->frac) + return TEE_SUCCESS; + + /* Recommended value for PMC_PLL_ACR */ + if (core->charac->upll) + val = AT91_PMC_PLL_ACR_DEFAULT_UPLL; + else + val = AT91_PMC_PLL_ACR_DEFAULT_PLLA; + io_write32(regmap + AT91_PMC_PLL_ACR, val); + + io_write32(regmap + AT91_PMC_PLL_CTRL1, + SHIFT_U32(frac->mul, core->layout->mul_shift) | + SHIFT_U32(frac->frac, core->layout->frac_shift)); + + if (core->charac->upll) { + /* Enable the UTMI internal bandgap */ + val |= AT91_PMC_PLL_ACR_UTMIBG; + io_write32(regmap + AT91_PMC_PLL_ACR, val); + + udelay(10); + + /* Enable the UTMI internal regulator */ + val |= AT91_PMC_PLL_ACR_UTMIVR; + io_write32(regmap + AT91_PMC_PLL_ACR, val); + + udelay(10); + } + + io_clrsetbits32(regmap + AT91_PMC_PLL_UPDT, + AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MASK, + AT91_PMC_PLL_UPDT_UPDATE | core->id); + + io_setbits32(regmap + AT91_PMC_PLL_CTRL0, + AT91_PMC_PLL_CTRL0_ENLOCK | AT91_PMC_PLL_CTRL0_ENPLL); + + io_clrsetbits32(regmap + AT91_PMC_PLL_UPDT, + AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MASK, + AT91_PMC_PLL_UPDT_UPDATE | core->id); + + if (WAIT_PLL_READY_TIMEOUT(regmap, core->id)) { + EMSG("PLL not ready"); + return TEE_ERROR_BUSY; + } + + return TEE_SUCCESS; +} + +static TEE_Result sam9x60_frac_pll_prepare(struct clk *hw) +{ + struct sam9x60_frac *frac = hw->priv; + + return sam9x60_frac_pll_set(frac); +} + +static void sam9x60_frac_pll_unprepare(struct clk *hw) +{ + struct sam9x60_frac *frac = hw->priv; + + io_clrsetbits32(frac->core.base + AT91_PMC_PLL_UPDT, + AT91_PMC_PLL_UPDT_ID_MASK, frac->core.id); + + io_clrbits32(frac->core.base + AT91_PMC_PLL_CTRL0, + AT91_PMC_PLL_CTRL0_ENPLL); + + if (frac->core.charac->upll) + io_clrbits32(frac->core.base + AT91_PMC_PLL_ACR, + AT91_PMC_PLL_ACR_UTMIBG | + AT91_PMC_PLL_ACR_UTMIVR); + + io_clrsetbits32(frac->core.base + AT91_PMC_PLL_UPDT, + AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MASK, + AT91_PMC_PLL_UPDT_UPDATE | frac->core.id); +} + +static TEE_Result sam9x60_frac_pll_compute_mul_frac(struct sam9x60_frac *frac, + unsigned long rate, + unsigned long parent_rate, + bool update) +{ + unsigned long tmprate = 0; + unsigned long remainder = 0; + unsigned long nmul = 0; + unsigned long nfrac = 0; + + if (rate < frac->core.charac->output[0].min || + rate > frac->core.charac->output[0].max) + return TEE_ERROR_GENERIC; + + /* + * Calculate the multiplier associated with the current + * divider that provide the closest rate to the requested one. + */ + nmul = rate / parent_rate; + tmprate = parent_rate * nmul; + remainder = rate - tmprate; + + if (remainder) { + nfrac = UDIV_ROUND_NEAREST((uint64_t)remainder * (1 << 22), + parent_rate); + + tmprate += UDIV_ROUND_NEAREST((uint64_t)nfrac * parent_rate, + 1 << 22); + } + + /* Check if resulted rate is a valid. */ + if (tmprate < frac->core.charac->output[0].min || + tmprate > frac->core.charac->output[0].max) + return TEE_ERROR_GENERIC; + + if (update) { + frac->mul = nmul - 1; + frac->frac = nfrac; + } + + return TEE_SUCCESS; +} + +static TEE_Result sam9x60_frac_pll_set_rate_chg(struct clk *hw, + unsigned long rate, + unsigned long parent_rate) +{ + TEE_Result ret = TEE_SUCCESS; + struct sam9x60_frac *frac = hw->priv; + struct sam9x60_pll_core *core = &frac->core; + vaddr_t regmap = core->base; + + ret = sam9x60_frac_pll_compute_mul_frac(frac, rate, parent_rate, true); + if (ret == TEE_SUCCESS) { + io_write32(regmap + AT91_PMC_PLL_CTRL1, + SHIFT_U32(frac->mul, core->layout->mul_shift) | + SHIFT_U32(frac->frac, core->layout->frac_shift)); + + io_clrsetbits32(regmap + AT91_PMC_PLL_UPDT, + AT91_PMC_PLL_UPDT_UPDATE | + AT91_PMC_PLL_UPDT_ID_MASK, + AT91_PMC_PLL_UPDT_UPDATE | core->id); + + io_setbits32(regmap + AT91_PMC_PLL_CTRL0, + AT91_PMC_PLL_CTRL0_ENLOCK | + AT91_PMC_PLL_CTRL0_ENPLL); + + io_clrsetbits32(regmap + AT91_PMC_PLL_UPDT, + AT91_PMC_PLL_UPDT_UPDATE | + AT91_PMC_PLL_UPDT_ID_MASK, + AT91_PMC_PLL_UPDT_UPDATE | core->id); + + if (WAIT_PLL_READY_TIMEOUT(regmap, core->id)) { + EMSG("PLL not ready"); + return TEE_ERROR_BUSY; + } + } + + return ret; +} + +static const struct clk_ops sam9x60_frac_pll_ops_chg = { + .enable = sam9x60_frac_pll_prepare, + .disable = sam9x60_frac_pll_unprepare, + .get_rate = sam9x60_frac_pll_recalc_rate, + .set_rate = sam9x60_frac_pll_set_rate_chg, +}; + +static TEE_Result sam9x60_div_pll_set_div(struct sam9x60_pll_core *core, + uint32_t div, + bool enable) +{ + vaddr_t regmap = core->base; + uint32_t enable_mask = enable ? core->layout->endiv_mask : 0; + uint32_t ena_val = enable ? BIT(core->layout->endiv_shift) : 0; + + io_clrsetbits32(regmap + AT91_PMC_PLL_CTRL0, + core->layout->div_mask | enable_mask, + SHIFT_U32(div, core->layout->div_shift) | ena_val); + + io_clrsetbits32(regmap + AT91_PMC_PLL_UPDT, + AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MASK, + AT91_PMC_PLL_UPDT_UPDATE | core->id); + + if (WAIT_PLL_READY_TIMEOUT(regmap, core->id)) { + EMSG("PLL not ready"); + return TEE_ERROR_BUSY; + } + + return TEE_SUCCESS; +} + +static TEE_Result sam9x60_div_pll_set(struct sam9x60_div *div) +{ + struct sam9x60_pll_core *core = &div->core; + vaddr_t regmap = core->base; + unsigned int val = 0; + unsigned int cdiv = 0; + + io_clrsetbits32(regmap + AT91_PMC_PLL_UPDT, + AT91_PMC_PLL_UPDT_ID_MASK, core->id); + val = io_read32(regmap + AT91_PMC_PLL_CTRL0); + cdiv = (val & core->layout->div_mask) >> core->layout->div_shift; + + /* Stop if enabled an nothing changed. */ + if ((val & core->layout->endiv_mask) && cdiv == div->div) + return TEE_SUCCESS; + + return sam9x60_div_pll_set_div(core, div->div, 1); +} + +static TEE_Result sam9x60_div_pll_prepare(struct clk *hw) +{ + struct sam9x60_div *div = hw->priv; + + return sam9x60_div_pll_set(div); +} + +static void sam9x60_div_pll_unprepare(struct clk *hw) +{ + struct sam9x60_div *div = hw->priv; + struct sam9x60_pll_core *core = &div->core; + vaddr_t regmap = core->base; + + io_clrsetbits32(regmap + AT91_PMC_PLL_UPDT, + AT91_PMC_PLL_UPDT_ID_MASK, core->id); + + io_clrbits32(regmap + AT91_PMC_PLL_CTRL0, core->layout->endiv_mask); + + io_clrsetbits32(regmap + AT91_PMC_PLL_UPDT, + AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MASK, + AT91_PMC_PLL_UPDT_UPDATE | core->id); +} + +static unsigned long sam9x60_div_pll_recalc_rate(struct clk *hw, + unsigned long parent_rate) +{ + struct sam9x60_div *div = hw->priv; + + return UDIV_ROUND_NEAREST(parent_rate, div->div + 1); +} + +static TEE_Result sam9x60_div_pll_set_rate(struct clk *hw, + unsigned long rate, + unsigned long parent_rate) +{ + struct sam9x60_div *div = hw->priv; + + div->div = UDIV_ROUND_NEAREST(parent_rate, rate) - 1; + + return TEE_SUCCESS; +} + +static TEE_Result sam9x60_div_pll_set_rate_chg(struct clk *hw, + unsigned long rate, + unsigned long parent_rate) +{ + struct sam9x60_div *div = hw->priv; + struct sam9x60_pll_core *core = &div->core; + vaddr_t regmap = core->base; + unsigned int val = 0; + unsigned int cdiv = 0; + + div->div = UDIV_ROUND_NEAREST(parent_rate, rate) - 1; + + io_clrsetbits32(regmap + AT91_PMC_PLL_UPDT, + AT91_PMC_PLL_UPDT_ID_MASK, + core->id); + val = io_read32(regmap + AT91_PMC_PLL_CTRL0); + cdiv = (val & core->layout->div_mask) >> core->layout->div_shift; + + /* Stop if nothing changed. */ + if (cdiv == div->div) + return TEE_SUCCESS; + + return sam9x60_div_pll_set_div(core, div->div, 0); +} + +static const struct clk_ops sam9x60_div_pll_ops = { + .enable = sam9x60_div_pll_prepare, + .disable = sam9x60_div_pll_unprepare, + .set_rate = sam9x60_div_pll_set_rate, + .get_rate = sam9x60_div_pll_recalc_rate, +}; + +static const struct clk_ops sam9x60_div_pll_ops_chg = { + .enable = sam9x60_div_pll_prepare, + .disable = sam9x60_div_pll_unprepare, + .set_rate = sam9x60_div_pll_set_rate_chg, + .get_rate = sam9x60_div_pll_recalc_rate, +}; + +struct clk *sam9x60_clk_register_frac_pll(struct pmc_data *pmc, + const char *name, + struct clk *parent, + uint8_t id, + const struct clk_pll_charac *charac, + const struct clk_pll_layout *layout, + uint32_t flags) +{ + struct sam9x60_frac *frac = NULL; + struct clk *hw = NULL; + unsigned long parent_rate = 0; + unsigned int val = 0; + TEE_Result ret = TEE_SUCCESS; + + frac = calloc(1, sizeof(*frac)); + if (!frac) + return NULL; + + hw = clk_alloc(name, &sam9x60_frac_pll_ops_chg, &parent, 1); + if (!hw) { + free(frac); + return NULL; + } + + hw->priv = frac; + hw->flags = flags; + frac->core.id = id; + frac->core.charac = charac; + frac->core.layout = layout; + frac->core.base = pmc->base; + + if (sam9x60_pll_ready(pmc->base, id)) { + io_clrsetbits32(frac->core.base + AT91_PMC_PLL_UPDT, + AT91_PMC_PLL_UPDT_ID_MASK, id); + val = io_read32(pmc->base + AT91_PMC_PLL_CTRL1); + frac->mul = (val >> PMC_PLL_CTRL1_MUL_POS) & + PMC_PLL_CTRL1_MUL_MASK; + frac->frac = (val >> PMC_PLL_CTRL1_FRACR_POS) & + PMC_PLL_CTRL1_FRACR_MASK; + } else { + /* + * This means the PLL is not setup by bootloaders. In this + * case we need to set the minimum rate for it. Otherwise + * a clock child of this PLL may be enabled before setting + * its rate leading to enabling this PLL with unsupported + * rate. This will lead to PLL not being locked at all. + */ + parent_rate = clk_get_rate(parent); + if (!parent_rate) { + clk_free(hw); + free(frac); + return NULL; + } + + ret = sam9x60_frac_pll_compute_mul_frac(frac, + charac->output[0].min, + parent_rate, true); + if (ret != TEE_SUCCESS) { + clk_free(hw); + free(frac); + return NULL; + } + } + + frac->core.hw = hw; + if (clk_register(hw)) { + clk_free(hw); + free(frac); + return NULL; + } + + return hw; +} + +struct clk *sam9x60_clk_register_div_pll(struct pmc_data *pmc, + const char *name, + struct clk *parent, + uint8_t id, + const struct clk_pll_charac *charac, + const struct clk_pll_layout *layout, + uint32_t flags, + uint32_t safe_div) +{ + struct sam9x60_div *div = NULL; + struct clk *hw = NULL; + unsigned int val = 0; + + if (safe_div >= PLL_DIV_MAX) + safe_div = PLL_DIV_MAX - 1; + + div = calloc(1, sizeof(*div)); + if (!div) + return NULL; + + if (flags & CLK_SET_RATE_GATE) + hw = clk_alloc(name, &sam9x60_div_pll_ops, &parent, 1); + else + hw = clk_alloc(name, &sam9x60_div_pll_ops_chg, &parent, 1); + if (!hw) { + free(div); + return NULL; + } + + hw->priv = div; + hw->flags = flags; + div->core.id = id; + div->core.charac = charac; + div->core.layout = layout; + div->core.base = pmc->base; + div->safe_div = safe_div; + + io_clrsetbits32(pmc->base + AT91_PMC_PLL_UPDT, + AT91_PMC_PLL_UPDT_ID_MASK, id); + val = io_read32(pmc->base + AT91_PMC_PLL_CTRL0); + div->div = (val >> PMC_PLL_CTRL0_DIV_POS) & PMC_PLL_CTRL0_DIV_MASK; + + div->core.hw = hw; + if (clk_register(hw)) { + clk_free(hw); + free(div); + return NULL; + } + + return hw; +} diff --git a/optee/optee_os/core/drivers/clk/sam/phy-sama7-utmi-clk.c b/optee/optee_os/core/drivers/clk/sam/phy-sama7-utmi-clk.c new file mode 100644 index 0000000..7729893 --- /dev/null +++ b/optee/optee_os/core/drivers/clk/sam/phy-sama7-utmi-clk.c @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Driver for the Microchip SAMA7 USB 2.0 PHY Clock + * + * Copyright (C) 2024 Microchip Technology, Inc. and its subsidiaries + * + * Author: Tony Han + * + */ + +#include +#include +#include +#include +#include +#include "at91_clk.h" + +#define SAMA7_SFR_UTMI0R(x) (0x2040 + 4 * (x)) /* offset of SFR_UTMI0Rx */ +#define SAMA7_SFR_UTMI_COMMONON BIT(3) /* PLL Common ON bit */ + +struct sama7_utmi_clk { + vaddr_t base; + uint8_t id; +}; + +static TEE_Result sama7_utmi_clk_enable(struct clk *hw) +{ + struct sama7_utmi_clk *utmi = hw->priv; + uint8_t id = utmi->id; + + sam_rstc_usb_por(id, true); + io_clrbits32(utmi->base + SAMA7_SFR_UTMI0R(id), + SAMA7_SFR_UTMI_COMMONON); + sam_rstc_usb_por(id, false); + + /* Datasheet states a minimum of 45 us before any USB operation */ + udelay(50); + + return TEE_SUCCESS; +} + +static void sama7_utmi_clk_disable(struct clk *hw) +{ + struct sama7_utmi_clk *utmi = hw->priv; + uint8_t id = utmi->id; + + sam_rstc_usb_por(id, true); + io_setbits32(utmi->base + SAMA7_SFR_UTMI0R(id), + SAMA7_SFR_UTMI_COMMONON); +} + +static const struct clk_ops sama7_utmi_ops = { + .enable = sama7_utmi_clk_enable, + .disable = sama7_utmi_clk_disable, +}; + +struct clk *sama7_utmi_clk_register(const char *name, + struct clk *parent, + uint8_t id) +{ + struct clk *hw = NULL; + struct sama7_utmi_clk *utmi_clk = NULL; + + hw = clk_alloc(name, &sama7_utmi_ops, &parent, 1); + if (!hw) + return NULL; + + utmi_clk = calloc(1, sizeof(*utmi_clk)); + if (!utmi_clk) { + clk_free(hw); + return NULL; + } + + utmi_clk->base = sam_sfr_base(); + utmi_clk->id = id; + hw->priv = utmi_clk; + + if (clk_register(hw)) { + clk_free(hw); + free(utmi_clk); + return NULL; + } + + return hw; +} 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..3bc9ce6 --- /dev/null +++ b/optee/optee_os/core/drivers/clk/sam/sama5d2_clk.c @@ -0,0 +1,612 @@ +// 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; +} + +TEE_Result at91_pmc_clk_get(unsigned int type, unsigned int idx, + struct clk **clk) +{ + return pmc_clk_get(pmc, type, idx, clk); +} + +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, NULL, 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/sama7g5_clk.c b/optee/optee_os/core/drivers/clk/sam/sama7g5_clk.c new file mode 100644 index 0000000..2e78023 --- /dev/null +++ b/optee/optee_os/core/drivers/clk/sam/sama7g5_clk.c @@ -0,0 +1,1580 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2024, Microchip + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "at91_clk.h" + +#define CLK_IS_CRITICAL 0 + +/* PLL clocks identifiers */ +enum pll_ids { + PLL_ID_CPU, + PLL_ID_SYS, + PLL_ID_DDR, + PLL_ID_IMG, + PLL_ID_BAUD, + PLL_ID_AUDIO, + PLL_ID_ETH, + PLL_ID_MAX, +}; + +/* PLL type identifiers */ +enum pll_type { + PLL_TYPE_FRAC, + PLL_TYPE_DIV, + PLL_TYPE_CNT, +}; + +/* Layout for fractional PLLs */ +static const struct clk_pll_layout pll_layout_frac = { + .mul_mask = GENMASK_32(31, 24), + .frac_mask = GENMASK_32(21, 0), + .mul_shift = 24, + .frac_shift = 0, +}; + +/* Layout for DIVPMC dividers */ +static const struct clk_pll_layout pll_layout_divpmc = { + .div_mask = GENMASK_32(7, 0), + .endiv_mask = BIT(29), + .div_shift = 0, + .endiv_shift = 29, +}; + +/* Layout for DIVIO dividers */ +static const struct clk_pll_layout pll_layout_divio = { + .div_mask = GENMASK_32(19, 12), + .endiv_mask = BIT(30), + .div_shift = 12, + .endiv_shift = 30, +}; + +/* + * CPU PLL output range + * Notice: The upper limit has been setup to 1000000002 due to hardware + * block which cannot output exactly 1GHz. + */ +static const struct clk_range cpu_pll_output[] = { + { .min = 2343750, .max = 1000000002 }, +}; + +/* PLL output range */ +static const struct clk_range pll_output[] = { + { .min = 2343750, .max = 1200000000 }, +}; + +/* CPU PLL characteristics */ +static const struct clk_pll_charac cpu_pll_characteristics = { + .input = { .min = 12000000, .max = 50000000 }, + .num_output = ARRAY_SIZE(cpu_pll_output), + .output = cpu_pll_output, +}; + +/* PLL characteristics */ +static const struct clk_pll_charac pll_characteristics = { + .input = { .min = 12000000, .max = 50000000 }, + .num_output = ARRAY_SIZE(pll_output), + .output = pll_output, +}; + +/* PLL clocks description */ +struct sama7g5_pll { + const char *name; + const char *parent; + const struct clk_pll_layout *layout; + const struct clk_pll_charac *charac; + unsigned long flags; + uint8_t type; + uint8_t eid; /* export index in sama7g5->chws[] array */ + uint8_t safe_div; /* intermediate divider need to be set on + * PRE_RATE_CHANGE notification + */ +}; + +static const struct sama7g5_pll sama7g5_plls[][PLL_ID_MAX] = { + [PLL_ID_CPU] = { + { + .name = "cpupll_fracck", + .parent = "mainck", + .layout = &pll_layout_frac, + .charac = &cpu_pll_characteristics, + .type = PLL_TYPE_FRAC, + /* + * This feeds cpupll_divpmcck which feeds CPU. It + * should not be disabled. + */ + .flags = CLK_IS_CRITICAL, + }, + { + .name = "cpupll_divpmcck", + .parent = "cpupll_fracck", + .layout = &pll_layout_divpmc, + .charac = &cpu_pll_characteristics, + .type = PLL_TYPE_DIV, + /* This feeds CPU. It should not be disabled. */ + .flags = CLK_IS_CRITICAL, + .eid = PMC_CPUPLL, + /* + * Safe div=15 should be safe even for switching b/w + * 1GHz and 90MHz (frac pll might go up to 1.2GHz). + */ + .safe_div = 15, + }, + }, + + [PLL_ID_SYS] = { + { + .name = "syspll_fracck", + .parent = "mainck", + .layout = &pll_layout_frac, + .charac = &pll_characteristics, + .type = PLL_TYPE_FRAC, + /* + * This feeds syspll_divpmcck which may feed critical + * parts of the systems like timers. Therefore it + * should not be disabled. + */ + .flags = CLK_IS_CRITICAL | CLK_SET_RATE_GATE, + }, + { + .name = "syspll_divpmcck", + .parent = "syspll_fracck", + .layout = &pll_layout_divpmc, + .charac = &pll_characteristics, + .type = PLL_TYPE_DIV, + /* + * This may feed critical parts of the systems like + * timers. Therefore it should not be disabled. + */ + .flags = CLK_IS_CRITICAL | CLK_SET_RATE_GATE, + .eid = PMC_SYSPLL, + }, + }, + + [PLL_ID_DDR] = { + { + .name = "ddrpll_fracck", + .parent = "mainck", + .layout = &pll_layout_frac, + .charac = &pll_characteristics, + .type = PLL_TYPE_FRAC, + /* + * This feeds ddrpll_divpmcck which feeds DDR. It + * should not be disabled. + */ + .flags = CLK_IS_CRITICAL | CLK_SET_RATE_GATE, + }, + { + .name = "ddrpll_divpmcck", + .parent = "ddrpll_fracck", + .layout = &pll_layout_divpmc, + .charac = &pll_characteristics, + .type = PLL_TYPE_DIV, + /* This feeds DDR. It should not be disabled. */ + .flags = CLK_IS_CRITICAL | CLK_SET_RATE_GATE, + .eid = PMC_DDRPLL, + }, + }, + + [PLL_ID_IMG] = { + { + .name = "imgpll_fracck", + .parent = "mainck", + .layout = &pll_layout_frac, + .charac = &pll_characteristics, + .type = PLL_TYPE_FRAC, + .flags = CLK_SET_RATE_GATE, + }, + { + .name = "imgpll_divpmcck", + .parent = "imgpll_fracck", + .layout = &pll_layout_divpmc, + .charac = &pll_characteristics, + .type = PLL_TYPE_DIV, + .flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE, + .eid = PMC_IMGPLL, + }, + }, + + [PLL_ID_BAUD] = { + { + .name = "baudpll_fracck", + .parent = "mainck", + .layout = &pll_layout_frac, + .charac = &pll_characteristics, + .type = PLL_TYPE_FRAC, + .flags = CLK_SET_RATE_GATE, + }, + { + .name = "baudpll_divpmcck", + .parent = "baudpll_fracck", + .layout = &pll_layout_divpmc, + .charac = &pll_characteristics, + .type = PLL_TYPE_DIV, + .flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE, + .eid = PMC_BAUDPLL, + }, + }, + + [PLL_ID_AUDIO] = { + { + .name = "audiopll_fracck", + .parent = "main_xtal", + .layout = &pll_layout_frac, + .charac = &pll_characteristics, + .type = PLL_TYPE_FRAC, + .flags = CLK_SET_RATE_GATE, + }, + { + .name = "audiopll_divck", + .parent = "audiopll_fracck", + .layout = &pll_layout_divpmc, + .charac = &pll_characteristics, + .type = PLL_TYPE_DIV, + .flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE, + .eid = PMC_AUDIOPMCPLL, + }, + { + .name = "audiopll_diviock", + .parent = "audiopll_fracck", + .layout = &pll_layout_divio, + .charac = &pll_characteristics, + .type = PLL_TYPE_DIV, + .flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE, + .eid = PMC_AUDIOIOPLL, + }, + }, + + [PLL_ID_ETH] = { + { + .name = "ethpll_fracck", + .parent = "main_xtal", + .layout = &pll_layout_frac, + .charac = &pll_characteristics, + .type = PLL_TYPE_FRAC, + .flags = CLK_SET_RATE_GATE, + }, + { + .name = "ethpll_divpmcck", + .parent = "ethpll_fracck", + .layout = &pll_layout_divpmc, + .charac = &pll_characteristics, + .type = PLL_TYPE_DIV, + .flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE, + .eid = PMC_ETHPLL, + }, + }, +}; + +/* + * Master clock (MCK[1..4]) description + * @eparents: extra parents names array + * @eparents_chg_id: index in parents array that specifies the changeable + * parent + * @eparents_count: extra parents count + * @eparents_mux_table: mux table for extra parents + * @id: clock id + * @eid: export index in sama7g5->chws[] array + */ +struct sama7g5_mck { + const char *name; + const char *eparents[4]; + int eparents_chg_id; + uint8_t eparents_count; + uint8_t eparents_mux_table[4]; + uint8_t id; + uint8_t eid; +}; + +static const struct sama7g5_mck sama7g5_mckx[] = { + { + .name = "mck1", + .id = 1, + .eparents = { "syspll_divpmcck", }, + .eparents_mux_table = { 5, }, + .eparents_count = 1, + .eparents_chg_id = INT_MIN, + .eid = PMC_MCK1, + }, + { + .name = "mck2", + .id = 2, + .eparents = { "ddrpll_divpmcck", }, + .eparents_mux_table = { 6, }, + .eparents_count = 1, + .eparents_chg_id = INT_MIN, + }, + { + .name = "mck3", + .id = 3, + .eparents = { "syspll_divpmcck", + "ddrpll_divpmcck", + "imgpll_divpmcck", }, + .eparents_mux_table = { 5, 6, 7, }, + .eparents_count = 3, + .eparents_chg_id = 5, + }, + { + .name = "mck4", + .id = 4, + .eparents = { "syspll_divpmcck", }, + .eparents_mux_table = { 5, }, + .eparents_count = 1, + .eparents_chg_id = INT_MIN, + }, +}; + +/* System clock description */ +static const struct { + const char *name; + const char *parent; + uint8_t id; +} sama7g5_systemck[] = { + { .name = "pck0", .parent = "prog0", .id = 8, }, + { .name = "pck1", .parent = "prog1", .id = 9, }, + { .name = "pck2", .parent = "prog2", .id = 10, }, + { .name = "pck3", .parent = "prog3", .id = 11, }, + { .name = "pck4", .parent = "prog4", .id = 12, }, + { .name = "pck5", .parent = "prog5", .id = 13, }, + { .name = "pck6", .parent = "prog6", .id = 14, }, + { .name = "pck7", .parent = "prog7", .id = 15, }, +}; + +/* Peripheral clock description */ +static const struct { + const char *name; + const char *parent; + struct clk_range output; + uint8_t id; +} peri_clks[] = { + { + .name = "pioA_clk", + .parent = "mck0", + .id = 11, + }, + { + .name = "securam_clk", + .parent = "mck0", + .id = 18, + }, + { + .name = "sfr_clk", + .parent = "mck1", + .id = 19, + }, + { + .name = "hsmc_clk", + .parent = "mck1", + .id = 21, + }, + { + .name = "xdmac0_clk", + .parent = "mck1", + .id = 22, + }, + { + .name = "xdmac1_clk", + .parent = "mck1", + .id = 23, + }, + { + .name = "xdmac2_clk", + .parent = "mck1", + .id = 24, + }, + { + .name = "acc_clk", + .parent = "mck1", + .id = 25, + }, + { + .name = "aes_clk", + .parent = "mck1", + .id = 27, + }, + { + .name = "tzaesbasc_clk", + .parent = "mck1", + .id = 28, + }, + { + .name = "asrc_clk", + .parent = "mck1", + .id = 30, + .output = { .max = 200000000, }, + }, + { + .name = "cpkcc_clk", + .parent = "mck0", + .id = 32, + }, + { + .name = "csi_clk", + .parent = "mck3", + .id = 33, + .output = { .max = 266000000, }, + }, + { + .name = "csi2dc_clk", + .parent = "mck3", + .id = 34, + .output = { .max = 266000000, }, + }, + { + .name = "eic_clk", + .parent = "mck1", + .id = 37, + }, + { + .name = "flex0_clk", + .parent = "mck1", + .id = 38, + }, + { + .name = "flex1_clk", + .parent = "mck1", + .id = 39, + }, + { + .name = "flex2_clk", + .parent = "mck1", + .id = 40, + }, + { + .name = "flex3_clk", + .parent = "mck1", + .id = 41, + }, + { + .name = "flex4_clk", + .parent = "mck1", + .id = 42, + }, + { + .name = "flex5_clk", + .parent = "mck1", + .id = 43, + }, + { + .name = "flex6_clk", + .parent = "mck1", + .id = 44, + }, + { + .name = "flex7_clk", + .parent = "mck1", + .id = 45, + }, + { + .name = "flex8_clk", + .parent = "mck1", + .id = 46, + }, + { + .name = "flex9_clk", + .parent = "mck1", + .id = 47, + }, + { + .name = "flex10_clk", + .parent = "mck1", + .id = 48, + }, + { + .name = "flex11_clk", + .parent = "mck1", + .id = 49, + }, + { + .name = "gmac0_clk", + .parent = "mck1", + .id = 51, + }, + { + .name = "gmac1_clk", + .parent = "mck1", + .id = 52, + }, + { + .name = "icm_clk", + .parent = "mck1", + .id = 55, + }, + { + .name = "isc_clk", + .parent = "mck3", + .id = 56, + .output = { .max = 266000000, }, + }, + { + .name = "i2smcc0_clk", + .parent = "mck1", + .id = 57, + .output = { .max = 200000000, }, + }, + { + .name = "i2smcc1_clk", + .parent = "mck1", + .id = 58, + .output = { .max = 200000000, }, + }, + { + .name = "matrix_clk", + .parent = "mck1", + .id = 60, }, + { + .name = "mcan0_clk", + .parent = "mck1", + .id = 61, + .output = { .max = 200000000, }, + }, + { + .name = "mcan1_clk", + .parent = "mck1", + .id = 62, + .output = { .max = 200000000, }, + }, + { + .name = "mcan2_clk", + .parent = "mck1", + .id = 63, + .output = { .max = 200000000, }, + }, + { + .name = "mcan3_clk", + .parent = "mck1", + .id = 64, + .output = { .max = 200000000, }, + }, + { + .name = "mcan4_clk", + .parent = "mck1", + .id = 65, + .output = { .max = 200000000, }, + }, + { + .name = "mcan5_clk", + .parent = "mck1", + .id = 66, + .output = { .max = 200000000, }, + }, + { + .name = "pdmc0_clk", + .parent = "mck1", + .id = 68, + .output = { .max = 200000000, }, + }, + { + .name = "pdmc1_clk", + .parent = "mck1", + .id = 69, + .output = { .max = 200000000, }, + }, + { + .name = "pit64b0_clk", + .parent = "mck1", + .id = 70, + }, + { + .name = "pit64b1_clk", + .parent = "mck1", + .id = 71, + }, + { + .name = "pit64b2_clk", + .parent = "mck1", + .id = 72, + }, + { + .name = "pit64b3_clk", + .parent = "mck1", + .id = 73, + }, + { + .name = "pit64b4_clk", + .parent = "mck1", + .id = 74, + }, + { + .name = "pit64b5_clk", + .parent = "mck1", + .id = 75, + }, + { + .name = "pwm_clk", + .parent = "mck1", + .id = 77, + }, + { + .name = "qspi0_clk", + .parent = "mck1", + .id = 78, + }, + { + .name = "qspi1_clk", + .parent = "mck1", + .id = 79, + }, + { + .name = "sdmmc0_clk", + .parent = "mck1", + .id = 80, + }, + { + .name = "sdmmc1_clk", + .parent = "mck1", + .id = 81, + }, + { + .name = "sdmmc2_clk", + .parent = "mck1", + .id = 82, + }, + { + .name = "sha_clk", + .parent = "mck1", + .id = 83, + }, + { + .name = "spdifrx_clk", + .parent = "mck1", + .id = 84, + .output = { .max = 200000000, }, + }, + { + .name = "spdiftx_clk", + .parent = "mck1", + .id = 85, + .output = { .max = 200000000, }, + }, + { + .name = "ssc0_clk", + .parent = "mck1", + .id = 86, + .output = { .max = 200000000, }, + }, + { + .name = "ssc1_clk", + .parent = "mck1", + .id = 87, + .output = { .max = 200000000, }, + }, + { + .name = "tcb0_ch0_clk", + .parent = "mck1", + .id = 88, + .output = { .max = 200000000, }, + }, + { + .name = "tcb0_ch1_clk", + .parent = "mck1", + .id = 89, + .output = { .max = 200000000, }, + }, + { + .name = "tcb0_ch2_clk", + .parent = "mck1", + .id = 90, + .output = { .max = 200000000, }, + }, + { + .name = "tcb1_ch0_clk", + .parent = "mck1", + .id = 91, + .output = { .max = 200000000, }, + }, + { + .name = "tcb1_ch1_clk", + .parent = "mck1", + .id = 92, + .output = { .max = 200000000, }, + }, + { + .name = "tcb1_ch2_clk", + .parent = "mck1", + .id = 93, + .output = { .max = 200000000, }, + }, + { + .name = "tcpca_clk", + .parent = "mck1", + .id = 94, + }, + { + .name = "tcpcb_clk", + .parent = "mck1", + .id = 95, + }, + { + .name = "tdes_clk", + .parent = "mck1", + .id = 96, + }, + { + .name = "trng_clk", + .parent = "mck1", + .id = 97, + }, + { + .name = "udphsa_clk", + .parent = "mck1", + .id = 104, + }, + { + .name = "udphsb_clk", + .parent = "mck1", + .id = 105, + }, + { + .name = "uhphs_clk", + .parent = "mck1", + .id = 106, + }, +}; + +/* UTMI clock description */ +static struct { + const char *name; + const char *parent; + uint8_t id; +} sama7_utmick[] = { + { .name = "utmi1", .parent = "utmick", .id = 0, }, + { .name = "utmi2", .parent = "utmi1", .id = 1, }, + { .name = "utmi3", .parent = "utmi1", .id = 2, }, +}; + +/* Generic clock description */ +struct sama7g5_gck { + const char *name; + const char *parents[8]; + const char parents_mux_table[8]; + struct clk_range output; + int parents_chg_id; /* id in parent array of changeable PLL parent */ + uint8_t parents_count; + uint8_t id; +}; + +static const struct sama7g5_gck sama7g5_gcks[] = { + { + .name = "adc_gclk", + .id = 26, + .output = { .max = 100000000, }, + .parents = { "syspll_divpmcck", + "imgpll_divpmcck", + "audiopll_divck", }, + .parents_mux_table = { 5, 7, 9, }, + .parents_count = 3, + .parents_chg_id = INT_MIN, + }, + { + .name = "asrc_gclk", + .id = 30, + .output = { .max = 200000000 }, + .parents = { "audiopll_divck", }, + .parents_mux_table = { 9, }, + .parents_count = 1, + .parents_chg_id = INT_MIN, + }, + { + .name = "csi_gclk", + .id = 33, + .output = { .max = 27000000 }, + .parents = { "ddrpll_divpmcck", "imgpll_divpmcck", }, + .parents_mux_table = { 6, 7, }, + .parents_count = 2, + .parents_chg_id = INT_MIN, + }, + { + .name = "flex0_gclk", + .id = 38, + .output = { .max = 200000000 }, + .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, + .parents_mux_table = { 5, 8, }, + .parents_count = 2, + .parents_chg_id = INT_MIN, + }, + { + .name = "flex1_gclk", + .id = 39, + .output = { .max = 200000000 }, + .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, + .parents_mux_table = { 5, 8, }, + .parents_count = 2, + .parents_chg_id = INT_MIN, + }, + { + .name = "flex2_gclk", + .id = 40, + .output = { .max = 200000000 }, + .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, + .parents_mux_table = { 5, 8, }, + .parents_count = 2, + .parents_chg_id = INT_MIN, + }, + { + .name = "flex3_gclk", + .id = 41, + .output = { .max = 200000000 }, + .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, + .parents_mux_table = { 5, 8, }, + .parents_count = 2, + .parents_chg_id = INT_MIN, + }, + { + .name = "flex4_gclk", + .id = 42, + .output = { .max = 200000000 }, + .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, + .parents_mux_table = { 5, 8, }, + .parents_count = 2, + .parents_chg_id = INT_MIN, + }, + { + .name = "flex5_gclk", + .id = 43, + .output = { .max = 200000000 }, + .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, + .parents_mux_table = { 5, 8, }, + .parents_count = 2, + .parents_chg_id = INT_MIN, + }, + { + .name = "flex6_gclk", + .id = 44, + .output = { .max = 200000000 }, + .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, + .parents_mux_table = { 5, 8, }, + .parents_count = 2, + .parents_chg_id = INT_MIN, + }, + { + .name = "flex7_gclk", + .id = 45, + .output = { .max = 200000000 }, + .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, + .parents_mux_table = { 5, 8, }, + .parents_count = 2, + .parents_chg_id = INT_MIN, + }, + { + .name = "flex8_gclk", + .id = 46, + .output = { .max = 200000000 }, + .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, + .parents_mux_table = { 5, 8, }, + .parents_count = 2, + .parents_chg_id = INT_MIN, + }, + { + .name = "flex9_gclk", + .id = 47, + .output = { .max = 200000000 }, + .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, + .parents_mux_table = { 5, 8, }, + .parents_count = 2, + .parents_chg_id = INT_MIN, + }, + { + .name = "flex10_gclk", + .id = 48, + .output = { .max = 200000000 }, + .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, + .parents_mux_table = { 5, 8, }, + .parents_count = 2, + .parents_chg_id = INT_MIN, + }, + { + .name = "flex11_gclk", + .id = 49, + .output = { .max = 200000000 }, + .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, + .parents_mux_table = { 5, 8, }, + .parents_count = 2, + .parents_chg_id = INT_MIN, + }, + { + .name = "gmac0_gclk", + .id = 51, + .output = { .max = 125000000 }, + .parents = { "ethpll_divpmcck", }, + .parents_mux_table = { 10, }, + .parents_count = 1, + .parents_chg_id = 3, + }, + { + .name = "gmac1_gclk", + .id = 52, + .output = { .max = 50000000 }, + .parents = { "ethpll_divpmcck", }, + .parents_mux_table = { 10, }, + .parents_count = 1, + .parents_chg_id = INT_MIN, + }, + { + .name = "gmac0_tsu_gclk", + .id = 53, + .output = { .max = 300000000 }, + .parents = { "audiopll_divck", "ethpll_divpmcck", }, + .parents_mux_table = { 9, 10, }, + .parents_count = 2, + .parents_chg_id = INT_MIN, + }, + { + .name = "gmac1_tsu_gclk", + .id = 54, + .output = { .max = 300000000 }, + .parents = { "audiopll_divck", "ethpll_divpmcck", }, + .parents_mux_table = { 9, 10, }, + .parents_count = 2, + .parents_chg_id = INT_MIN, + }, + { + .name = "i2smcc0_gclk", + .id = 57, + .output = { .max = 100000000 }, + .parents = { "syspll_divpmcck", "audiopll_divck", }, + .parents_mux_table = { 5, 9, }, + .parents_count = 2, + .parents_chg_id = INT_MIN, + }, + { + .name = "i2smcc1_gclk", + .id = 58, + .output = { .max = 100000000 }, + .parents = { "syspll_divpmcck", "audiopll_divck", }, + .parents_mux_table = { 5, 9, }, + .parents_count = 2, + .parents_chg_id = INT_MIN, + }, + { + .name = "mcan0_gclk", + .id = 61, + .output = { .max = 200000000 }, + .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, + .parents_mux_table = { 5, 8, }, + .parents_count = 2, + .parents_chg_id = INT_MIN, + }, + { + .name = "mcan1_gclk", + .id = 62, + .output = { .max = 200000000 }, + .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, + .parents_mux_table = { 5, 8, }, + .parents_count = 2, + .parents_chg_id = INT_MIN, + }, + { + .name = "mcan2_gclk", + .id = 63, + .output = { .max = 200000000 }, + .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, + .parents_mux_table = { 5, 8, }, + .parents_count = 2, + .parents_chg_id = INT_MIN, + }, + { + .name = "mcan3_gclk", + .id = 64, + .output = { .max = 200000000 }, + .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, + .parents_mux_table = { 5, 8, }, + .parents_count = 2, + .parents_chg_id = INT_MIN, + }, + { + .name = "mcan4_gclk", + .id = 65, + .output = { .max = 200000000 }, + .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, + .parents_mux_table = { 5, 8, }, + .parents_count = 2, + .parents_chg_id = INT_MIN, + }, + { + .name = "mcan5_gclk", + .id = 66, + .output = { .max = 200000000 }, + .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, + .parents_mux_table = { 5, 8, }, + .parents_count = 2, + .parents_chg_id = INT_MIN, + }, + { + .name = "pdmc0_gclk", + .id = 68, + .output = { .max = 50000000 }, + .parents = { "syspll_divpmcck", "audiopll_divck", }, + .parents_mux_table = { 5, 9, }, + .parents_count = 2, + .parents_chg_id = INT_MIN, + }, + { + .name = "pdmc1_gclk", + .id = 69, + .output = { .max = 50000000, }, + .parents = { "syspll_divpmcck", "audiopll_divck", }, + .parents_mux_table = { 5, 9, }, + .parents_count = 2, + .parents_chg_id = INT_MIN, + }, + { + .name = "pit64b0_gclk", + .id = 70, + .output = { .max = 200000000 }, + .parents = { "syspll_divpmcck", "imgpll_divpmcck", + "baudpll_divpmcck", "audiopll_divck", + "ethpll_divpmcck", }, + .parents_mux_table = { 5, 7, 8, 9, 10, }, + .parents_count = 5, + .parents_chg_id = INT_MIN, + }, + { + .name = "pit64b1_gclk", + .id = 71, + .output = { .max = 200000000 }, + .parents = { "syspll_divpmcck", "imgpll_divpmcck", + "baudpll_divpmcck", "audiopll_divck", + "ethpll_divpmcck", }, + .parents_mux_table = { 5, 7, 8, 9, 10, }, + .parents_count = 5, + .parents_chg_id = INT_MIN, + }, + { + .name = "pit64b2_gclk", + .id = 72, + .output = { .max = 200000000 }, + .parents = { "syspll_divpmcck", "imgpll_divpmcck", + "baudpll_divpmcck", "audiopll_divck", + "ethpll_divpmcck", }, + .parents_mux_table = { 5, 7, 8, 9, 10, }, + .parents_count = 5, + .parents_chg_id = INT_MIN, + }, + { + .name = "pit64b3_gclk", + .id = 73, + .output = { .max = 200000000 }, + .parents = { "syspll_divpmcck", "imgpll_divpmcck", + "baudpll_divpmcck", "audiopll_divck", + "ethpll_divpmcck", }, + .parents_mux_table = { 5, 7, 8, 9, 10, }, + .parents_count = 5, + .parents_chg_id = INT_MIN, + }, + { + .name = "pit64b4_gclk", + .id = 74, + .output = { .max = 200000000 }, + .parents = { "syspll_divpmcck", "imgpll_divpmcck", + "baudpll_divpmcck", "audiopll_divck", + "ethpll_divpmcck", }, + .parents_mux_table = { 5, 7, 8, 9, 10, }, + .parents_count = 5, + .parents_chg_id = INT_MIN, + }, + { + .name = "pit64b5_gclk", + .id = 75, + .output = { .max = 200000000 }, + .parents = { "syspll_divpmcck", "imgpll_divpmcck", + "baudpll_divpmcck", "audiopll_divck", + "ethpll_divpmcck", }, + .parents_mux_table = { 5, 7, 8, 9, 10, }, + .parents_count = 5, + .parents_chg_id = INT_MIN, + }, + { + .name = "qspi0_gclk", + .id = 78, + .output = { .max = 200000000 }, + .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, + .parents_mux_table = { 5, 8, }, + .parents_count = 2, + .parents_chg_id = INT_MIN, + }, + { + .name = "qspi1_gclk", + .id = 79, + .output = { .max = 200000000 }, + .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, + .parents_mux_table = { 5, 8, }, + .parents_count = 2, + .parents_chg_id = INT_MIN, + }, + { + .name = "sdmmc0_gclk", + .id = 80, + .output = { .max = 208000000 }, + .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, + .parents_mux_table = { 5, 8, }, + .parents_count = 2, + .parents_chg_id = 4, + }, + { + .name = "sdmmc1_gclk", + .id = 81, + .output = { .max = 208000000 }, + .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, + .parents_mux_table = { 5, 8, }, + .parents_count = 2, + .parents_chg_id = 4, + }, + { + .name = "sdmmc2_gclk", + .id = 82, + .output = { .max = 208000000 }, + .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, + .parents_mux_table = { 5, 8, }, + .parents_count = 2, + .parents_chg_id = 4, + }, + { + .name = "spdifrx_gclk", + .id = 84, + .output = { .max = 150000000 }, + .parents = { "syspll_divpmcck", "audiopll_divck", }, + .parents_mux_table = { 5, 9, }, + .parents_count = 2, + .parents_chg_id = INT_MIN, + }, + { + .name = "spdiftx_gclk", + .id = 85, + .output = { .max = 25000000 }, + .parents = { "syspll_divpmcck", "audiopll_divck", }, + .parents_mux_table = { 5, 9, }, + .parents_count = 2, + .parents_chg_id = INT_MIN, + }, + { + .name = "tcb0_ch0_gclk", + .id = 88, + .output = { .max = 200000000 }, + .parents = { "syspll_divpmcck", "imgpll_divpmcck", + "baudpll_divpmcck", "audiopll_divck", + "ethpll_divpmcck", }, + .parents_mux_table = { 5, 7, 8, 9, 10, }, + .parents_count = 5, + .parents_chg_id = INT_MIN, + }, + { + .name = "tcb1_ch0_gclk", + .id = 91, + .output = { .max = 200000000 }, + .parents = { "syspll_divpmcck", "imgpll_divpmcck", + "baudpll_divpmcck", "audiopll_divck", + "ethpll_divpmcck", }, + .parents_mux_table = { 5, 7, 8, 9, 10, }, + .parents_count = 5, + .parents_chg_id = INT_MIN, + }, + { + .name = "tcpca_gclk", + .id = 94, + .output = { .max = 32768, }, + .parents_chg_id = INT_MIN, + }, + { + .name = "tcpcb_gclk", + .id = 95, + .output = { .max = 32768, }, + .parents_chg_id = INT_MIN, + }, +}; + +/* MCK0 characteristics */ +static const struct clk_master_charac mck0_characteristics = { + .output = { .min = 32768, .max = 200000000 }, + .divisors = { 1, 2, 4, 3, 5 }, + .have_div3_pres = 1, +}; + +/* MCK0 layout */ +static const struct clk_master_layout mck0_layout = { + .mask = 0x773, + .pres_shift = 4, + .offset = 0x28, +}; + +/* Peripheral clock layout */ +static const struct clk_pcr_layout sama7g5_pcr_layout = { + .offset = 0x88, + .cmd = BIT(31), + .div_mask = GENMASK_32(27, 20), + .gckcss_mask = GENMASK_32(12, 8), + .pid_mask = GENMASK_32(6, 0), +}; + +static const struct clk_programmable_layout sama7g5_prog_layout = { + .pres_mask = 0xff, + .pres_shift = 8, + .css_mask = GENMASK_32(4, 0), + .have_slck_mck = 0, + .is_pres_direct = 1, +}; + +static const struct { + const char *name; + uint8_t id; +} sama7g5_progck[] = { + { .name = "prog0", .id = 0 }, + { .name = "prog1", .id = 1 }, + { .name = "prog2", .id = 2 }, + { .name = "prog3", .id = 3 }, + { .name = "prog4", .id = 4 }, + { .name = "prog5", .id = 5 }, + { .name = "prog6", .id = 6 }, + { .name = "prog7", .id = 7 }, +}; + +static struct pmc_data *sama7g5_pmc; + +vaddr_t at91_pmc_get_base(void) +{ + assert(sama7g5_pmc); + + return sama7g5_pmc->base; +} + +TEE_Result at91_pmc_clk_get(unsigned int type, unsigned int idx, + struct clk **clk) +{ + return pmc_clk_get(sama7g5_pmc, type, idx, clk); +} + +static TEE_Result pmc_setup_sama7g5(const void *fdt, int nodeoffset, + const void *data __unused) +{ + struct clk *pll_frac_clk[PLL_ID_MAX] = { }; + struct clk *pll_div_clk[PLL_ID_MAX] = { }; + TEE_Result res = TEE_ERROR_GENERIC; + const uint32_t *fdt_prop = NULL; + struct pmc_clk *pmc_clk = NULL; + struct clk *parents[11] = { }; + struct clk *main_xtal_clk = NULL; + struct clk *main_rc_osc = NULL; + struct clk *main_osc = NULL; + struct clk *mck0_clk = NULL; + struct clk *main_clk = NULL; + struct clk *md_slck = NULL; + struct clk *td_slck = NULL; + struct clk *parent = NULL; + struct clk *clk = NULL; + unsigned int i = 0; + unsigned int j = 0; + vaddr_t base = 0; + size_t size = 0; + int bypass = 0; + + 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(ID_PMC); + + res = clk_dt_get_by_name(fdt, nodeoffset, "md_slck", &md_slck); + if (res) + return res; + + res = clk_dt_get_by_name(fdt, nodeoffset, "td_slck", &td_slck); + if (res) + return res; + + res = clk_dt_get_by_name(fdt, nodeoffset, "main_xtal", &main_xtal_clk); + if (res) + return res; + + sama7g5_pmc = pmc_data_allocate(PMC_SAMA7G5_CORE_CLK_COUNT, + ARRAY_SIZE(sama7g5_systemck), + ARRAY_SIZE(peri_clks), + ARRAY_SIZE(sama7g5_gcks), 8); + if (!sama7g5_pmc) + panic(); + + sama7g5_pmc->base = base; + + main_rc_osc = pmc_register_main_rc_osc(sama7g5_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(sama7g5_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(sama7g5_pmc, "mainck", + parents, 2); + if (!main_clk) + panic(); + pmc_clk = &sama7g5_pmc->chws[PMC_MAIN]; + pmc_clk->clk = main_clk; + pmc_clk->id = PMC_MAIN; + + for (i = 0; i < PLL_ID_MAX; i++) { + struct pmc_data *pmc = sama7g5_pmc; + const struct sama7g5_pll *p = NULL; + + for (j = 0; j < 3; j++) { + p = &sama7g5_plls[i][j]; + if (!p->name) + continue; + + switch (p->type) { + case PLL_TYPE_FRAC: + if (!strcmp(p->parent, "mainck")) + parent = main_clk; + else if (!strcmp(p->parent, "main_xtal")) + parent = main_xtal_clk; + else + parent = pmc_clk_get_by_name(pmc->chws, + pmc->ncore, + p->parent); + assert(parent); + + clk = sam9x60_clk_register_frac_pll(sama7g5_pmc, + p->name, + parent, i, + p->charac, + p->layout, + p->flags); + pll_frac_clk[i] = clk; + break; + + case PLL_TYPE_DIV: + parent = clk; + clk = sam9x60_clk_register_div_pll(sama7g5_pmc, + p->name, + parent, i, + p->charac, + p->layout, + p->flags, + p->safe_div); + break; + + default: + continue; + } + if (!clk) + panic(); + + if (p->eid) { + sama7g5_pmc->chws[p->eid].clk = clk; + sama7g5_pmc->chws[p->eid].id = p->eid; + } + } + p = &sama7g5_plls[i][PLL_TYPE_DIV]; + pll_div_clk[i] = sama7g5_pmc->chws[p->eid].clk; + } + + parents[0] = md_slck; + parents[1] = main_clk; + parents[2] = pll_div_clk[PLL_ID_CPU]; + parents[3] = pll_div_clk[PLL_ID_SYS]; + clk = at91_clk_register_master_pres(sama7g5_pmc, "fclk", 4, + parents, + &mck0_layout, + &mck0_characteristics, INT_MIN); + if (!clk) + panic(); + pmc_clk = &sama7g5_pmc->chws[PMC_MCK_PRES]; + pmc_clk->clk = clk; + pmc_clk->id = PMC_MCK_PRES; + + mck0_clk = at91_clk_register_master_div(sama7g5_pmc, "mck0", + clk, + &mck0_layout, + &mck0_characteristics); + if (!mck0_clk) + panic(); + pmc_clk = &sama7g5_pmc->chws[PMC_MCK]; + pmc_clk->clk = mck0_clk; + pmc_clk->id = PMC_MCK; + + parents[0] = md_slck; + parents[1] = td_slck; + parents[2] = main_clk; + parents[3] = mck0_clk; + for (i = 0; i < ARRAY_SIZE(sama7g5_mckx); i++) { + const struct sama7g5_mck *mck = &sama7g5_mckx[i]; + uint8_t num_parents = 4 + mck->eparents_count; + uint32_t *mux_table = calloc(num_parents, sizeof(*mux_table)); + + if (!mux_table) + panic(); + + mux_table[0] = 0; + mux_table[1] = 1; + mux_table[2] = 2; + mux_table[3] = 3; + for (j = 0; j < mck->eparents_count; j++) { + parents[4 + j] = pmc_clk_get_by_name(sama7g5_pmc->chws, + sama7g5_pmc->ncore, + mck->eparents[j]); + assert(parents[4 + j]); + mux_table[4 + j] = mck->eparents_mux_table[j]; + } + + clk = at91_clk_sama7g5_register_master(sama7g5_pmc, + mck->name, + num_parents, parents, + mux_table, + mck->id, + mck->eparents_chg_id); + if (!clk) + panic(); + + sama7g5_pmc->chws[PMC_MCK1 + i].clk = clk; + } + + clk = at91_clk_sama7g5_register_utmi(sama7g5_pmc, "utmick", main_clk); + if (!clk) + panic(); + sama7g5_pmc->chws[PMC_UTMI].clk = clk; + sama7g5_pmc->chws[PMC_UTMI].id = PMC_UTMI; + + for (i = 0; i < ARRAY_SIZE(sama7_utmick); i++) { + if (strcmp("utmick", sama7_utmick[i].parent) == 0) + parent = clk; + else if (strcmp("utmi1", sama7_utmick[i].parent) == 0) + parent = sama7g5_pmc->chws[PMC_UTMI1].clk; + else + panic(); + clk = sama7_utmi_clk_register(sama7_utmick[i].name, parent, + sama7_utmick[i].id); + if (!clk) + panic(); + + pmc_clk = &sama7g5_pmc->chws[PMC_UTMI1 + i]; + pmc_clk->clk = clk; + pmc_clk->id = PMC_UTMI1 + i; + } + + parents[0] = md_slck; + parents[1] = td_slck; + parents[2] = main_clk; + parents[3] = pll_div_clk[PLL_ID_SYS]; + parents[4] = pll_div_clk[PLL_ID_DDR]; + parents[5] = pll_div_clk[PLL_ID_IMG]; + parents[6] = pll_div_clk[PLL_ID_BAUD]; + parents[7] = pll_div_clk[PLL_ID_AUDIO]; + parents[8] = pll_div_clk[PLL_ID_ETH]; + for (i = 0; i < ARRAY_SIZE(sama7g5_progck); i++) { + clk = at91_clk_register_programmable(sama7g5_pmc, + sama7g5_progck[i].name, + parents, 9, i, + &sama7g5_prog_layout); + if (!clk) + panic(); + + pmc_clk = &sama7g5_pmc->pchws[i]; + pmc_clk->clk = clk; + pmc_clk->id = sama7g5_progck[i].id; + } + + for (i = 0; i < ARRAY_SIZE(sama7g5_systemck); i++) { + clk = at91_clk_register_system(sama7g5_pmc, + sama7g5_systemck[i].name, + sama7g5_pmc->pchws[i].clk, + sama7g5_systemck[i].id); + if (!clk) + panic(); + + pmc_clk = &sama7g5_pmc->shws[i]; + pmc_clk->clk = clk; + pmc_clk->id = sama7g5_systemck[i].id; + } + + for (i = 0; i < ARRAY_SIZE(peri_clks); i++) { + parent = pmc_clk_get_by_name(sama7g5_pmc->chws, + sama7g5_pmc->ncore, + peri_clks[i].parent); + clk = at91_clk_register_sam9x5_periph(sama7g5_pmc, + &sama7g5_pcr_layout, + peri_clks[i].name, + parent, + peri_clks[i].id, + &peri_clks[i].output); + if (!clk) + panic(); + + pmc_clk = &sama7g5_pmc->phws[i]; + pmc_clk->clk = clk; + pmc_clk->id = peri_clks[i].id; + } + + parents[0] = md_slck; + parents[1] = td_slck; + parents[2] = main_clk; + for (i = 0; i < ARRAY_SIZE(sama7g5_gcks); i++) { + const struct sama7g5_gck *gck = sama7g5_gcks + i; + uint8_t num_parents = 3 + gck->parents_count; + uint32_t *mux_table = calloc(num_parents, sizeof(*mux_table)); + + if (!mux_table) + panic(); + + mux_table[0] = 0; + mux_table[1] = 1; + mux_table[2] = 2; + for (j = 0; j < gck->parents_count; j++) { + parents[3 + j] = pmc_clk_get_by_name(sama7g5_pmc->chws, + sama7g5_pmc->ncore, + gck->parents[j]); + assert(parents[3 + j]); + mux_table[3 + j] = gck->parents_mux_table[j]; + } + + clk = at91_clk_register_generated(sama7g5_pmc, + &sama7g5_pcr_layout, + gck->name, parents, + mux_table, + num_parents, gck->id, + &gck->output, + gck->parents_chg_id); + if (!clk) + panic(); + + pmc_clk = &sama7g5_pmc->ghws[i]; + pmc_clk->clk = clk; + pmc_clk->id = gck->id; + } + + res = clk_set_rate(pll_frac_clk[PLL_ID_ETH], 625000000); + if (res) + panic(); + + res = clk_set_rate(pll_div_clk[PLL_ID_ETH], 625000000); + if (res) + panic(); + + res = clk_dt_register_clk_provider(fdt, nodeoffset, clk_dt_pmc_get, + sama7g5_pmc); + if (res) + panic(); + + pmc_register_pm(); + + return TEE_SUCCESS; +} + +CLK_DT_DECLARE(sama7g5_clk, "microchip,sama7g5-pmc", pmc_setup_sama7g5); 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..acd14b0 --- /dev/null +++ b/optee/optee_os/core/drivers/clk/sam/sub.mk @@ -0,0 +1,13 @@ +global-incdirs-y += . + +srcs-y += at91_sckc.c at91_main.c at91_pmc.c +srcs-y += at91_utmi.c at91_master.c +srcs-y += at91_programmable.c at91_system.c at91_peripheral.c +srcs-y += at91_generated.c + +srcs-$(CFG_SAMA5D2) += at91_pll.c at91_plldiv.c +srcs-$(CFG_SAMA5D2) += at91_h32mx.c at91_usb.c +srcs-$(CFG_SAMA5D2) += at91_i2s_mux.c at91_audio_pll.c +srcs-$(CFG_SAMA5D2) += sama5d2_clk.c + +srcs-$(CFG_SAMA7G5) += clk-sam9x60-pll.c phy-sama7-utmi-clk.c sama7g5_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..c6b352d --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/acipher/caam_dh.c @@ -0,0 +1,523 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2021, 2023 NXP + * + * Implementation of DH + */ +#include +#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 caamkey 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_key_free(&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_key_deserialize_from_bn(inkey->x, &outkey->x, 0); + if (retstatus != CAAM_NO_ERROR) + return retstatus; + + caam_key_cache_op(TEE_CACHECLEAN, &outkey->x); + + 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(CFG_CORE_BIGNUM_MAX_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; + enum caam_key_type key_type = caam_key_default_key_gen_type(); + + 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 */ + caam_dh_key.x.key_type = key_type; + caam_dh_key.x.sec_size = n_bytes; + caam_dh_key.x.is_blob = false; + + retstatus = caam_key_alloc(&caam_dh_key.x); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto out; + } + + caam_key_cache_op(TEE_CACHEFLUSH, &caam_dh_key.x); + + /* 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.buf.paddr); + caam_desc_add_ptr(desc, caam_dh_key.y.paddr); + + switch (key_type) { + case CAAM_KEY_PLAIN_TEXT: + caam_desc_add_word(desc, PK_KEYPAIR_GEN(DL, NONE)); + break; + case CAAM_KEY_BLACK_ECB: + caam_desc_add_word(desc, PK_KEYPAIR_GEN(DL, ECB)); + break; + case CAAM_KEY_BLACK_CCM: + caam_desc_add_word(desc, PK_KEYPAIR_GEN(DL, CCM)); + break; + default: + ret = TEE_ERROR_GENERIC; + goto out; + } + + 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) { + caam_key_cache_op(TEE_CACHEINVALIDATE, &caam_dh_key.x); + cache_operation(TEE_CACHEINVALIDATE, caam_dh_key.y.data, + caam_dh_key.y.length); + + /* Copy Private and Public keypair */ + ret = caam_key_serialize_to_bn(key->x, &caam_dh_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.sec_size)); + /* 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.buf.paddr); + /* Output secret */ + caam_desc_add_ptr(desc, secret.sgtbuf.paddr); + + switch (caam_dh_key.x.key_type) { + case CAAM_KEY_PLAIN_TEXT: + caam_desc_add_word(desc, SHARED_SECRET(DL, NONE)); + break; + case CAAM_KEY_BLACK_ECB: + caam_desc_add_word(desc, SHARED_SECRET(DL, ECB)); + break; + case CAAM_KEY_BLACK_CCM: + caam_desc_add_word(desc, SHARED_SECRET(DL, CCM)); + break; + default: + ret = TEE_ERROR_GENERIC; + goto out; + } + + 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..d7264c5 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/acipher/caam_dsa.c @@ -0,0 +1,806 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2019-2021, 2023 NXP + * + * Implementation of DSA functions + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "local.h" +#include "utee_types.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 caamkey 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_key_free(&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); + + retstatus = caam_key_deserialize_from_bn(inkey->x, &outkey->x, n_bytes); + if (retstatus != CAAM_NO_ERROR) + return retstatus; + + 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); + caam_key_cache_op(TEE_CACHECLEAN, &outkey->x); + + 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(CFG_CORE_BIGNUM_MAX_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; + enum caam_key_type key_type = caam_key_default_key_gen_type(); + + 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 */ + caam_dsa_key.x.key_type = caam_key_default_key_gen_type(); + caam_dsa_key.x.sec_size = n_bytes; + caam_dsa_key.x.is_blob = false; + + retstatus = caam_key_alloc(&caam_dsa_key.x); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto out; + } + + caam_key_cache_op(TEE_CACHEFLUSH, &caam_dsa_key.x); + + /* 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.buf.paddr); + caam_desc_add_ptr(desc, caam_dsa_key.y.paddr); + + switch (key_type) { + case CAAM_KEY_PLAIN_TEXT: + caam_desc_add_word(desc, PK_KEYPAIR_GEN(DL, NONE)); + break; + case CAAM_KEY_BLACK_ECB: + caam_desc_add_word(desc, PK_KEYPAIR_GEN(DL, ECB)); + break; + case CAAM_KEY_BLACK_CCM: + caam_desc_add_word(desc, PK_KEYPAIR_GEN(DL, CCM)); + break; + default: + ret = TEE_ERROR_GENERIC; + goto out; + } + + 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) { + caam_key_cache_op(TEE_CACHEINVALIDATE, &caam_dsa_key.x); + + cache_operation(TEE_CACHEINVALIDATE, caam_dsa_key.y.data, + caam_dsa_key.y.length); + + /* Copy Private and Public keypair */ + ret = caam_key_serialize_to_bn(key->x, &caam_dsa_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.buf.data, + caam_dsa_key.x.buf.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.buf.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); + + switch (dsakey.x.key_type) { + case CAAM_KEY_PLAIN_TEXT: + caam_desc_add_word(desc, DSA_SIGN(DL, HASHED, NONE)); + break; + case CAAM_KEY_BLACK_ECB: + caam_desc_add_word(desc, DSA_SIGN(DL, HASHED, ECB)); + break; + case CAAM_KEY_BLACK_CCM: + caam_desc_add_word(desc, DSA_SIGN(DL, HASHED, CCM)); + break; + default: + ret = TEE_ERROR_GENERIC; + goto out; + } + + 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, HASHED)); + 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..085200e --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/acipher/caam_ecc.c @@ -0,0 +1,911 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2021, 2024 NXP + * + * Implementation of ECC functions + */ +#include +#include +#include +#include +#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 caamkey d; +}; + +/* + * Free local ECC keypair + * + * @key ECC keypair + */ +static void do_keypair_free(struct caam_ecc_keypair *key) +{ + caam_free_buf(&key->xy); + caam_key_free(&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; + + ECC_TRACE("ECC Convert Keypair size %zu bytes", size_sec); + + /* Private key is only scalar d of sec_size bytes */ + retstatus = caam_key_deserialize_from_bn(inkey->d, &outkey->d, + size_sec); + if (retstatus) + return retstatus; + + caam_key_cache_op(TEE_CACHEFLUSH, &outkey->d); + + ECC_DUMPBUF("Outkey", outkey->d.buf.data, outkey->d.buf.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, + size_t size_bits) +{ + ECC_TRACE("Allocate Keypair of %zu bits", size_bits); + + switch (type) { + case TEE_TYPE_SM2_PKE_KEYPAIR: + case TEE_TYPE_SM2_DSA_KEYPAIR: + /* Software fallback */ + return TEE_ERROR_NOT_IMPLEMENTED; + default: + break; + } + + /* Initialize the key fields to NULL */ + memset(key, 0, sizeof(*key)); + + /* Allocate Secure Scalar */ + key->d = crypto_bignum_allocate(CFG_CORE_BIGNUM_MAX_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, + size_t size_bits) +{ + ECC_TRACE("Allocate Public Key of %zu bits", size_bits); + + switch (type) { + case TEE_TYPE_SM2_PKE_PUBLIC_KEY: + case TEE_TYPE_SM2_DSA_PUBLIC_KEY: + /* Software fallback */ + return TEE_ERROR_NOT_IMPLEMENTED; + default: + break; + } + + /* 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 caamkey d = { }; + struct caambuf xy = { }; + struct caam_jobctx jobctx = { }; + uint32_t *desc = NULL; + uint32_t desclen = 0; + enum caam_key_type key_type = caam_key_default_key_gen_type(); + + 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 two buffers + * Secure key size = key_size align in bytes + * Public key size = (key_size * 2) align in bytes + */ + d.key_type = key_type; + d.sec_size = ROUNDUP_DIV(key_size, 8); + d.is_blob = false; + + retstatus = caam_key_alloc(&d); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto out; + } + + retstatus = caam_alloc_align_buf(&xy, (key_size / 8) * 2); + 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_PKGEN_PD1 | PDB_ECC_ECDSEL(curve)); + caam_desc_add_ptr(desc, d.buf.paddr); + caam_desc_add_ptr(desc, xy.paddr); + + switch (key_type) { + case CAAM_KEY_PLAIN_TEXT: + caam_desc_add_word(desc, PK_KEYPAIR_GEN(ECC, NONE)); + break; + case CAAM_KEY_BLACK_ECB: + caam_desc_add_word(desc, PK_KEYPAIR_GEN(ECC, ECB)); + break; + case CAAM_KEY_BLACK_CCM: + caam_desc_add_word(desc, PK_KEYPAIR_GEN(ECC, CCM)); + break; + default: + ret = TEE_ERROR_GENERIC; + goto out; + } + + desclen = caam_desc_get_len(desc); + caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1)); + + ECC_DUMPDESC(desc); + + jobctx.desc = desc; + caam_key_cache_op(TEE_CACHEFLUSH, &d); + cache_operation(TEE_CACHEFLUSH, xy.data, xy.length); + + retstatus = caam_jr_enqueue(&jobctx, NULL); + + if (retstatus == CAAM_NO_ERROR) { + caam_key_cache_op(TEE_CACHEINVALIDATE, &d); + cache_operation(TEE_CACHEINVALIDATE, xy.data, xy.length); + + /* Copy all keypair parameters */ + retstatus = caam_key_serialize_to_bn(key->d, &d); + if (retstatus) { + ret = caam_status_to_tee_result(retstatus); + 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.buf.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_key_free(&d); + caam_free_buf(&xy); + + return ret; +} + +/* + * Check if MES_REP to be sent in descriptor is 00. + * Only required in case message length and key size is more than 40bytes + * because of limitation of Class 2 context register size on i.MX8M series. + * Example case below: + * When we try to do signature with P384-SHA384, in this case the key size + * will be 48bytes and Message size will also be 48bytes. + * This will work only when we set MES_REP = 0 in descriptor, + * but in this case, we don't need the padding to be done on the message. + * + * @msg_length: Message Length in bytes + * @key_size: Key size in bytes + */ +static bool msg_mes_rep(size_t msg_length, size_t key_size) +{ + return IS_ENABLED(CFG_NXP_CAAM_C2_CTX_REG_WA) && msg_length > 40 && + key_size > 40; +} + +/* + * Check if padding is required on message to make it of same length + * as that of key size. + * Only required in case message length and key size is more than 40bytes + * because of limitation of Class 2 context register size on i.MX8M series. + * So this will be applicable on P384 and P521 ECC curves because these + * curves have key_size more than 40bytes. + * + * @msg_length: Message Length in bytes + * @key_size: Key size in bytes + */ +static bool padding_required(size_t msg_length, size_t key_size) +{ + return msg_mes_rep(msg_length, key_size) && msg_length < key_size; +} + +/* + * Add padding of 00s in start of message + * + * @buf: Buffer in which padded message will be placed. + * @data: Original message + * @msg_length: Message Length in bytes + * @key_size: Key Size in bytes + */ +static TEE_Result add_padding(struct caambuf *buf, uint8_t *data, + size_t msg_length, size_t key_size) +{ + enum caam_status retstatus = CAAM_FAILURE; + + retstatus = caam_calloc_align_buf(buf, key_size); + if (retstatus != CAAM_NO_ERROR) + return caam_status_to_tee_result(retstatus); + + memcpy(buf->data + key_size - msg_length, data, msg_length); + + return TEE_SUCCESS; +} + +/* + * 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; + struct caambuf caambuf_msg = { }; + + 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; + } + + ECC_DUMPBUF("Message", sdata->message.data, sdata->message.length); + + if (padding_required(sdata->message.length, sdata->size_sec)) { + ret = add_padding(&caambuf_msg, sdata->message.data, + sdata->message.length, sdata->size_sec); + if (ret) + goto out; + + /* Prepare the input message CAAM Descriptor entry */ + ret = caam_dmaobj_input_sgtbuf(&msg, caambuf_msg.data, + caambuf_msg.length); + if (ret) + goto out; + + ECC_DUMPBUF("Padded Message", caambuf_msg.data, + caambuf_msg.length); + } else { + /* 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); + + /* + * 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.buf.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); + + if (msg_mes_rep(sdata->message.length, sdata->size_sec)) { + switch (ecckey.d.key_type) { + case CAAM_KEY_PLAIN_TEXT: + caam_desc_add_word(desc, DSA_SIGN(ECC, MES_REP, NONE)); + break; + case CAAM_KEY_BLACK_ECB: + caam_desc_add_word(desc, DSA_SIGN(ECC, MES_REP, ECB)); + break; + case CAAM_KEY_BLACK_CCM: + caam_desc_add_word(desc, DSA_SIGN(ECC, MES_REP, CCM)); + break; + default: + ret = TEE_ERROR_GENERIC; + goto out; + } + } else { + /* Message length */ + caam_desc_add_word(desc, sdata->message.length); + + switch (ecckey.d.key_type) { + case CAAM_KEY_PLAIN_TEXT: + caam_desc_add_word(desc, DSA_SIGN(ECC, HASHED, NONE)); + break; + case CAAM_KEY_BLACK_ECB: + caam_desc_add_word(desc, DSA_SIGN(ECC, HASHED, ECB)); + break; + case CAAM_KEY_BLACK_CCM: + caam_desc_add_word(desc, DSA_SIGN(ECC, HASHED, CCM)); + break; + default: + ret = TEE_ERROR_GENERIC; + goto out; + } + } + + 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); + caam_free_buf(&caambuf_msg); + + 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; + struct caambuf caambuf_msg = { }; + + ECC_TRACE("ECC Verify"); + ECC_DUMPBUF("Message", sdata->message.data, sdata->message.length); + ECC_DUMPBUF("Signature", sdata->signature.data, + sdata->signature.length); + + /* 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; + } + + if (padding_required(sdata->message.length, sdata->size_sec)) { + ret = add_padding(&caambuf_msg, sdata->message.data, + sdata->message.length, sdata->size_sec); + if (ret) + goto out; + + /* Prepare the input message CAAM Descriptor entry */ + ret = caam_dmaobj_input_sgtbuf(&msg, caambuf_msg.data, + caambuf_msg.length); + if (ret) + goto out; + } else { + /* 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); + + if (msg_mes_rep(sdata->message.length, sdata->size_sec)) { + caam_desc_add_word(desc, DSA_VERIFY(ECC, MES_REP)); + } else { + /* Message length */ + caam_desc_add_word(desc, sdata->message.length); + + caam_desc_add_word(desc, DSA_VERIFY(ECC, HASHED)); + } + + 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); + cache_operation(TEE_CACHEFLUSH, ecckey.xy.data, ecckey.xy.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); + caam_free_buf(&caambuf_msg); + + 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.buf.paddr); + /* Output secret */ + caam_desc_add_ptr(desc, secret.sgtbuf.paddr); + + switch (ecckey.d.key_type) { + case CAAM_KEY_PLAIN_TEXT: + caam_desc_add_word(desc, SHARED_SECRET(ECC, NONE)); + break; + case CAAM_KEY_BLACK_ECB: + caam_desc_add_word(desc, SHARED_SECRET(ECC, ECB)); + break; + case CAAM_KEY_BLACK_CCM: + caam_desc_add_word(desc, SHARED_SECRET(ECC, CCM)); + break; + default: + ret = TEE_ERROR_GENERIC; + goto out; + } + + 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..3f02d61 --- /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, 2023 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(CLASS_NO, 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(CLASS_NO, 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(CLASS_NO, 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(CLASS_NO, 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(CLASS_NO, 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..53037a5 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/acipher/caam_prime_rsa.c @@ -0,0 +1,869 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2021, 2023 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) +{ + size_t key_size = data->key_size / 8; + + /* + * 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 ((key_size / 2) > (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, + key_size / 2)); + 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, key_size / 2); + + /* + * 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->key_size / 8 / 2) - 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->key_size / 8 / 2)); + 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(CLASS_NO, PKHA_N, (data->key_size / 8 / 2))); + + 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, + size_t key_size) +{ + 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, key_size)); + 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 (key_size > 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, + (key_size - 128 - check_len))); + } else if (key_size > check_len) { + caam_desc_add_word(desc, MOVE(OFIFO, C1_CTX_REG, 0, + (key_size - 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; + size_t key_size = data->key_size / 8 / 2; + + /* 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, key_size + 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(key_size, &small_prime); + + RSA_TRACE("Do prime of %zu bytes (security len %zu bits) (ERA=%" PRId8 + ")", + key_size, 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, + key_size); + } 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..4a8a1e0 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/acipher/caam_rsa.c @@ -0,0 +1,1712 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2021, 2023 NXP + * + * CAAM RSA manager. + * Implementation of RSA functions + */ +#include +#include +#include +#include +#include +#include +#include +#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 caamkey d; /* Private Exponent [d = 1/e mod LCM(p-1, q-1)] */ + struct caamkey p; /* Private Prime p */ + struct caamkey q; /* Private Prime q */ + struct caamkey dp; /* Private [dp = d mod (p-1)] */ + struct caamkey dq; /* Private [dq = d mod (q-1)] */ + struct caamkey 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_key_free(&key->d); + caam_key_free(&key->p); + caam_key_free(&key->q); + caam_key_free(&key->dp); + caam_key_free(&key->dq); + caam_key_free(&key->qp); +} + +/* + * 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.sec_size; + size_q = outkey->q.sec_size; + size_dp = crypto_bignum_num_bytes(inkey->dp); + size_dq = crypto_bignum_num_bytes(inkey->dq); + size_qp = crypto_bignum_num_bytes(inkey->qp); + + /* + * 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. + */ + retstatus = caam_key_deserialize_from_bn(inkey->dp, + &outkey->dp, size_p); + if (retstatus) + return retstatus; + + /* Field dq */ + retstatus = caam_key_deserialize_from_bn(inkey->dq, + &outkey->dq, size_p); + if (retstatus) + return retstatus; + + /* Field qp */ + retstatus = caam_key_deserialize_from_bn(inkey->qp, + &outkey->qp, size_q); + if (retstatus) + return retstatus; + + /* Push fields value to the physical memory */ + caam_key_cache_op(TEE_CACHECLEAN, &outkey->dp); + caam_key_cache_op(TEE_CACHECLEAN, &outkey->qp); + caam_key_cache_op(TEE_CACHECLEAN, &outkey->dq); + + 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; + + /* Field Prime p */ + retstatus = caam_key_deserialize_from_bn(inkey->p, &outkey->p, 0); + if (retstatus) + return retstatus; + + /* Field Prime q */ + retstatus = caam_key_deserialize_from_bn(inkey->q, &outkey->q, 0); + if (retstatus) + return retstatus; + + /* Push fields value to the physical memory */ + caam_key_cache_op(TEE_CACHECLEAN, &outkey->p); + caam_key_cache_op(TEE_CACHECLEAN, &outkey->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_key_deserialize_from_bn(inkey->d, &outkey->d, 0); + if (retstatus) + return retstatus; + + caam_key_cache_op(TEE_CACHECLEAN, &outkey->d); + + 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(CFG_CORE_BIGNUM_MAX_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(CFG_CORE_BIGNUM_MAX_BITS); + if (!key->p) + goto err_alloc_keypair; + + /* Allocate the prime number q of size (size_bits / 2) */ + key->q = crypto_bignum_allocate(CFG_CORE_BIGNUM_MAX_BITS); + if (!key->q) + goto err_alloc_keypair; + + /* Allocate dp (size_bits / 2) [d mod (p-1)] */ + key->dp = crypto_bignum_allocate(CFG_CORE_BIGNUM_MAX_BITS); + if (!key->dp) + goto err_alloc_keypair; + + /* Allocate dq (size_bits / 2) [d mod (q-1)] */ + key->dq = crypto_bignum_allocate(CFG_CORE_BIGNUM_MAX_BITS); + if (!key->dq) + goto err_alloc_keypair; + + /* Allocate qp (size_bits / 2) [1/q mod p] */ + key->qp = crypto_bignum_allocate(CFG_CORE_BIGNUM_MAX_BITS); + 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) +{ + enum caam_status status = CAAM_FAILURE; + + caam_key_cache_op(TEE_CACHEINVALIDATE, &genkey->dp); + caam_key_cache_op(TEE_CACHEINVALIDATE, &genkey->dq); + caam_key_cache_op(TEE_CACHEINVALIDATE, &genkey->qp); + + RSA_DUMPBUF("dp", genkey->dp.buf.data, genkey->dp.buf.length); + RSA_DUMPBUF("dq", genkey->dq.buf.data, genkey->dq.buf.length); + RSA_DUMPBUF("qp", genkey->qp.buf.data, genkey->qp.buf.length); + + status = caam_key_serialize_to_bn(key->dp, &genkey->dp); + if (status) + return caam_status_to_tee_result(status); + + status = caam_key_serialize_to_bn(key->dq, &genkey->dq); + if (status) + return caam_status_to_tee_result(status); + + status = caam_key_serialize_to_bn(key->qp, &genkey->qp); + if (status) + return caam_status_to_tee_result(status); + + return TEE_SUCCESS; +} + +/* + * 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) +{ + enum caam_status status = CAAM_FAILURE; + + caam_key_cache_op(TEE_CACHEINVALIDATE, &genkey->q); + caam_key_cache_op(TEE_CACHEINVALIDATE, &genkey->p); + + RSA_DUMPBUF("p", genkey->p.buf.data, genkey->p.buf.length); + RSA_DUMPBUF("q", genkey->q.buf.data, genkey->q.buf.length); + + status = caam_key_serialize_to_bn(key->p, &genkey->p); + if (status) + return caam_status_to_tee_result(status); + + status = caam_key_serialize_to_bn(key->q, &genkey->q); + if (status) + return caam_status_to_tee_result(status); + + if (genkey->format > RSA_PRIVATE_KEY_FORMAT_2) + return gen_keypair_get_f3(key, genkey); + + return TEE_SUCCESS; +} + +static TEE_Result +do_black_key_encapsulation(struct caam_rsa_keypair *rsa_keypair) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + enum caam_key_type key_type = caam_key_default_key_gen_type(); + + ret = caam_key_black_encapsulation(&rsa_keypair->p, key_type); + if (ret) { + RSA_TRACE("RSA Key p component encapsulation failed"); + return ret; + } + + ret = caam_key_black_encapsulation(&rsa_keypair->q, key_type); + if (ret) { + RSA_TRACE("RSA Key q component encapsulation failed"); + return ret; + } + + RSA_TRACE("Black key encapsulation done"); + + return TEE_SUCCESS; +} + +/* + * 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_gen __maybe_unused = 0; + uint32_t *size_d_gen_val_ptr = NULL; + struct caam_jobctx jobctx = { }; + uint32_t *desc = 0; + uint32_t desclen = 0; + struct prime_data_rsa prime = { }; + enum caam_key_type key_type = caam_key_default_key_gen_type(); + size_t key_size_bytes = key_size / 8; + + 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; + } + + size_d_gen_val_ptr = caam_calloc_align(sizeof(uint32_t)); + if (!size_d_gen_val_ptr) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto exit_gen_keypair; + } + + /* First allocate primes p and q */ + genkey.p.key_type = CAAM_KEY_PLAIN_TEXT; + genkey.p.sec_size = key_size_bytes / 2; + genkey.p.is_blob = false; + + retstatus = caam_key_alloc(&genkey.p); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto exit_gen_keypair; + } + + genkey.q.key_type = CAAM_KEY_PLAIN_TEXT; + genkey.q.sec_size = key_size_bytes / 2; + genkey.q.is_blob = false; + + retstatus = caam_key_alloc(&genkey.q); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto exit_gen_keypair; + } + + /* 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; + } + + genkey.d.key_type = key_type; + genkey.d.sec_size = key_size_bytes; + genkey.d.is_blob = false; + + retstatus = caam_key_alloc(&genkey.d); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto exit_gen_keypair; + } + + retstatus = caam_calloc_align_buf(&genkey.n, key_size_bytes); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto exit_gen_keypair; + } + + if (genkey.format > RSA_PRIVATE_KEY_FORMAT_2) { + genkey.dp.key_type = key_type; + genkey.dp.sec_size = key_size_bytes / 2; + genkey.dp.is_blob = false; + + retstatus = caam_key_alloc(&genkey.dp); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto exit_gen_keypair; + } + + genkey.dq.key_type = key_type; + genkey.dq.sec_size = key_size_bytes / 2; + genkey.dq.is_blob = false; + + retstatus = caam_key_alloc(&genkey.dq); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto exit_gen_keypair; + } + + genkey.qp.key_type = key_type; + genkey.qp.sec_size = key_size_bytes / 2; + genkey.qp.is_blob = false; + + retstatus = caam_key_alloc(&genkey.qp); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto exit_gen_keypair; + } + } + + 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.buf; + prime.q = &genkey.q.buf; + + /* 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.sec_size)); + 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.buf.paddr); + caam_desc_add_ptr(desc, genkey.q.buf.paddr); + caam_desc_add_ptr(desc, genkey.e.paddr); + caam_desc_add_ptr(desc, genkey.n.paddr); + caam_desc_add_ptr(desc, genkey.d.buf.paddr); + caam_desc_add_ptr(desc, virt_to_phys(size_d_gen_val_ptr)); + + if (genkey.format > RSA_PRIVATE_KEY_FORMAT_2) { + caam_desc_add_ptr(desc, genkey.dp.buf.paddr); + caam_desc_add_ptr(desc, genkey.dq.buf.paddr); + caam_desc_add_ptr(desc, genkey.qp.buf.paddr); + + switch (key_type) { + case CAAM_KEY_PLAIN_TEXT: + caam_desc_add_word(desc, RSA_FINAL_KEY(ALL, NONE)); + break; + case CAAM_KEY_BLACK_ECB: + caam_desc_add_word(desc, RSA_FINAL_KEY(ALL, ECB)); + break; + case CAAM_KEY_BLACK_CCM: + caam_desc_add_word(desc, RSA_FINAL_KEY(ALL, CCM)); + break; + default: + ret = TEE_ERROR_GENERIC; + goto exit_gen_keypair; + } + + caam_key_cache_op(TEE_CACHEFLUSH, &genkey.dp); + caam_key_cache_op(TEE_CACHEFLUSH, &genkey.dq); + caam_key_cache_op(TEE_CACHEFLUSH, &genkey.qp); + } else { + switch (key_type) { + case CAAM_KEY_PLAIN_TEXT: + caam_desc_add_word(desc, RSA_FINAL_KEY(N_D, NONE)); + break; + case CAAM_KEY_BLACK_ECB: + caam_desc_add_word(desc, RSA_FINAL_KEY(N_D, ECB)); + break; + case CAAM_KEY_BLACK_CCM: + caam_desc_add_word(desc, RSA_FINAL_KEY(N_D, CCM)); + break; + default: + ret = TEE_ERROR_GENERIC; + goto exit_gen_keypair; + } + } + + 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); + caam_key_cache_op(TEE_CACHEFLUSH, &genkey.p); + caam_key_cache_op(TEE_CACHEFLUSH, &genkey.q); + caam_key_cache_op(TEE_CACHEFLUSH, &genkey.d); + cache_operation(TEE_CACHEFLUSH, genkey.n.data, genkey.n.length); + cache_operation(TEE_CACHEFLUSH, size_d_gen_val_ptr, sizeof(uint32_t)); + + retstatus = caam_jr_enqueue(&jobctx, NULL); + + if (retstatus == CAAM_NO_ERROR) { + caam_key_cache_op(TEE_CACHEINVALIDATE, &genkey.d); + cache_operation(TEE_CACHEINVALIDATE, &genkey.n, + genkey.n.length); + + cache_operation(TEE_CACHEINVALIDATE, size_d_gen_val_ptr, + sizeof(uint32_t)); + + size_d_gen = caam_read_val32(size_d_gen_val_ptr); + + RSA_TRACE("D size %zu", size_d_gen); + RSA_DUMPBUF("D", genkey.d.buf.data, genkey.d.buf.length); + RSA_DUMPBUF("N", genkey.n.data, genkey.n.length); + + genkey.d.sec_size = size_d_gen; + + if (key_type != CAAM_KEY_PLAIN_TEXT) { + ret = do_black_key_encapsulation(&genkey); + if (ret != TEE_SUCCESS) + goto exit_gen_keypair; + } + + ret = crypto_bignum_bin2bn(genkey.n.data, genkey.n.length, + key->n); + if (ret != TEE_SUCCESS) + goto exit_gen_keypair; + + retstatus = caam_key_serialize_to_bn(key->d, &genkey.d); + if (retstatus) { + ret = caam_status_to_tee_result(retstatus); + 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: + do_keypair_free(&genkey); + caam_free(size_d_gen_val_ptr); + 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; +} + +/* + * Get RSA key pair key type + * + * @kp RSA key pair + */ +static enum caam_key_type get_caam_key_type(const struct caam_rsa_keypair kp) +{ + switch (kp.format) { + case RSA_PRIVATE_KEY_FORMAT_1: + return kp.d.key_type; + case RSA_PRIVATE_KEY_FORMAT_2: + if (kp.p.key_type == kp.q.key_type && + kp.q.key_type == kp.d.key_type) + return kp.p.key_type; + else + return CAAM_KEY_MAX_VALUE; + case RSA_PRIVATE_KEY_FORMAT_3: + if (kp.p.key_type == kp.q.key_type && + kp.q.key_type == kp.dp.key_type && + kp.dp.key_type == kp.dq.key_type && + kp.dq.key_type == kp.qp.key_type) + return kp.p.key_type; + else + return CAAM_KEY_MAX_VALUE; + default: + return CAAM_KEY_MAX_VALUE; + } +} + +/* + * 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 caamkey tmp_1 = { }; + struct caamkey tmp_2 = { }; + enum caam_key_type g_key_type = CAAM_KEY_MAX_VALUE; + + 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 two temporary buffers used by the CAAM */ + tmp_1.key_type = CAAM_KEY_PLAIN_TEXT; + tmp_1.sec_size = key.p.sec_size; + tmp_1.is_blob = false; + + retstatus = caam_key_alloc(&tmp_1); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto exit_decrypt; + } + + tmp_2.key_type = CAAM_KEY_PLAIN_TEXT; + tmp_2.sec_size = key.q.sec_size; + tmp_2.is_blob = false; + + retstatus = caam_key_alloc(&tmp_2); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto exit_decrypt; + } + + caam_key_cache_op(TEE_CACHEFLUSH, &tmp_1); + caam_key_cache_op(TEE_CACHEFLUSH, &tmp_2); + 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.sec_size) | + 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.buf.paddr); + + break; + + case RSA_PRIVATE_KEY_FORMAT_2: + caam_desc_add_word(desc, + PDB_RSA_DEC_D_SIZE(key.d.sec_size) | + 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.buf.paddr); + caam_desc_add_ptr(desc, key.p.buf.paddr); + caam_desc_add_ptr(desc, key.q.buf.paddr); + caam_desc_add_ptr(desc, tmp_1.buf.paddr); + caam_desc_add_ptr(desc, tmp_2.buf.paddr); + caam_desc_add_word(desc, + PDB_RSA_DEC_Q_SIZE(key.q.sec_size) | + PDB_RSA_DEC_P_SIZE(key.p.sec_size)); + 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.buf.paddr); + caam_desc_add_ptr(desc, key.p.buf.paddr); + caam_desc_add_ptr(desc, key.q.buf.paddr); + caam_desc_add_ptr(desc, key.dp.buf.paddr); + caam_desc_add_ptr(desc, key.dq.buf.paddr); + caam_desc_add_ptr(desc, tmp_1.buf.paddr); + caam_desc_add_ptr(desc, tmp_2.buf.paddr); + caam_desc_add_word(desc, + PDB_RSA_DEC_Q_SIZE(key.q.sec_size) | + PDB_RSA_DEC_P_SIZE(key.p.sec_size)); + break; + + default: + ret = TEE_ERROR_GENERIC; + goto exit_decrypt; + } + + /* Set the Decryption operation type */ + operation |= PROT_RSA_DEC_KEYFORM(key.format); + + /* Get key type */ + g_key_type = get_caam_key_type(key); + switch (g_key_type) { + case CAAM_KEY_PLAIN_TEXT: + operation |= PROT_RSA_KEY_ENC(NONE); + break; + case CAAM_KEY_BLACK_ECB: + operation |= PROT_RSA_KEY_ENC(ECB); + break; + case CAAM_KEY_BLACK_CCM: + operation |= PROT_RSA_KEY_ENC(CCM); + break; + default: + ret = TEE_ERROR_GENERIC; + goto exit_decrypt; + } + + caam_desc_add_word(desc, operation); + + 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_key_free(&tmp_1); + caam_key_free(&tmp_2); + + 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/caam_dek.c b/optee/optee_os/core/drivers/crypto/caam/blob/caam_dek.c new file mode 100644 index 0000000..cff61a7 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/blob/caam_dek.c @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2019-2021, 2023 NXP + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CFG_PHYS_64BIT +#define BLOB_OPERATE_DESC_ENTRIES 12 +#else +#define BLOB_OPERATE_DESC_ENTRIES 10 +#endif + +/* Secure Memory Access Permission allowed */ +#define SM_GRP_BLOB BIT32(3) /* Export/Import Secure Memory blobs allowed */ + +/* Secure Memory Page(s)/Partition definition for DEK Blob generation */ +static const struct caam_sm_page_desc dek_sm_page = { + .partition = 1, + .page = 3, + .page_count = 1, +}; + +TEE_Result caam_dek_generate(const uint8_t *payload, size_t payload_size, + uint8_t *dek, size_t dek_size) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + enum caam_status retstatus = CAAM_FAILURE; + struct caam_sm_page_addr dek_sm_addr = { }; + struct caamdmaobj resblob = { }; + struct caam_jobctx jobctx = { }; + uint32_t key_modifier[2] = { }; + uint32_t *desc = NULL; + unsigned int opflags = 0; + + assert(payload && dek); + assert(payload_size && dek_size); + + /* Re-allocate output buffer if alignment needed */ + ret = caam_dmaobj_output_sgtbuf(&resblob, dek, dek_size, dek_size); + if (ret) + return ret; + + /* Allocate page(s) in one Secure Memory partition */ + ret = caam_sm_alloc(&dek_sm_page, &dek_sm_addr); + if (ret != CAAM_NO_ERROR) { + BLOB_TRACE("Secure memory allocation error 0x%" PRIx32, ret); + goto out; + } + + /* Copy input data to encapsulate in Secure Memory allocated */ + memcpy((void *)dek_sm_addr.vaddr, payload, payload_size); + + /* + * Set the partition access rights for the group #1 to be + * a blob export/import + */ + caam_sm_set_access_perm(&dek_sm_page, SM_GRP_BLOB, 0); + + /* + * Create the key modifier: + * 31 16 8 0 + * --------------------------------------------------- + * | Length of the payload | AES - 0x55 | CCM - 0x66 | + * --------------------------------------------------- + */ + key_modifier[0] = SHIFT_U32(payload_size, 16) | SHIFT_U32(0x55, 8) | + SHIFT_U32(0x66, 0); + key_modifier[1] = 0; + + /* Allocate the descriptor */ + desc = caam_calloc_desc(BLOB_OPERATE_DESC_ENTRIES); + if (!desc) { + BLOB_TRACE("CAAM Context Descriptor Allocation error"); + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + caam_desc_init(desc); + caam_desc_add_word(desc, DESC_HEADER(0)); + caam_desc_add_word(desc, LD_IMM_OFF(CLASS_2, REG_KEY, 8, 12)); + caam_desc_add_word(desc, key_modifier[0]); + caam_desc_add_word(desc, key_modifier[1]); + caam_desc_add_word(desc, SEQ_IN_PTR(payload_size)); + caam_desc_add_ptr(desc, dek_sm_addr.paddr); + caam_desc_seq_out(desc, &resblob); + caam_desc_add_word(desc, BLOB_ENCAPS | PROT_BLOB_SEC_MEM | opflags); + + BLOB_DUMPDESC(desc); + + cache_operation(TEE_CACHECLEAN, (void *)payload, payload_size); + caam_dmaobj_cache_push(&resblob); + + jobctx.desc = desc; + retstatus = caam_jr_enqueue(&jobctx, NULL); + + if (retstatus) { + BLOB_TRACE("CAAM Status 0x%08" PRIx32 "", jobctx.status); + goto out; + } + + caam_dmaobj_copy_to_orig(&resblob); + + BLOB_TRACE("Done CAAM BLOB from Secure Memory encaps"); + BLOB_DUMPBUF("Blob Output", resblob.orig.data, resblob.orig.length); +out: + caam_sm_free(&dek_sm_page); + caam_free_desc(&desc); + caam_dmaobj_free(&resblob); + + return caam_status_to_tee_result(retstatus); +} 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..15e445c --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/blob/sub.mk @@ -0,0 +1,4 @@ +srcs-$(CFG_NXP_CAAM_BLOB_DRV) += caam_blob.c +srcs-$(CFG_NXP_CAAM_DEK_DRV) += caam_dek.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..f24d6fb --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/caam_ctrl.c @@ -0,0 +1,205 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2017-2021, 2023 NXP + * + * Brief CAAM Global Controller. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * If the CAAM DMA only supports 32 bits physical addresses, OPTEE must + * be located within the 32 bits address space. + */ +#ifndef CFG_CAAM_64BIT +static_assert((CFG_TZDRAM_START + CFG_TZDRAM_SIZE) < UINT32_MAX); +#endif + +/* 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; + } + + /* Initialize the secure memory */ + retstatus = caam_sm_init(&jrcfg); + if (retstatus != CAAM_NO_ERROR) { + retresult = TEE_ERROR_GENERIC; + goto exit_init; + } + + /* Initialize the KEY Module */ + retstatus = caam_key_init(); + if (retstatus != CAAM_NO_ERROR) { + 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..a3bf68a --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/caam_jr.c @@ -0,0 +1,688 @@ +// 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"); + interrupt_disable(handler->chip, 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.chip = interrupt_get_main_chip(); + 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) + if (interrupt_add_handler(&jr_privdata->it_handler)) { + retstatus = CAAM_FAILURE; + goto end_init; + } +#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_key.c b/optee/optee_os/core/drivers/crypto/caam/caam_key.c new file mode 100644 index 0000000..5205b8b --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/caam_key.c @@ -0,0 +1,752 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2023 NXP + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * CAAM Key magic number. + * When the first 32 bits of a key buffer are equal to this value, the buffer + * is a serialized CAAM key structure. + */ +#define MAGIC_NUMBER 0xCAAFBFFB + +/* + * Because the CAAM driver relies on this magic number to determine if the key + * is plain text or black, collision can happen. A randomly generated plain text + * key could feature the magic number. That's unlikely but still possible. + * + * Regarding the possibility of collision or forging attack, there are no + * security concerns. Forging and trying to make a plain text key look like a + * black key, won't do much. If the key is forged to look like an ECB Black + * key, the singing operation will output a corrupted result. If the key is + * forged to look like a CCM Black key, the import key will fail (because the + * MAC verification) and no signing operation will be done. + */ + +#define BLOB_BKEK_SIZE 32 /* Blob key encryption key size */ +#define BLOB_MAC_SIZE 16 /* Blob MAC size */ +#define BLOB_PAD_SIZE (BLOB_BKEK_SIZE + BLOB_MAC_SIZE) + +/* + * CAAM Blob key modifier + * Key modifier used to derive Blob-key encryption key (BKEK) from the CAAM + * master key. + * + * A CAAM black key is encrypted using a volatile Job Descriptor key encryption + * key or JDKEK. Black keys are not intended for storage of keys across SoC + * power cycles. The JDKEK is re-generated upon every power cycle (reset, + * suspend/resume ...) or CAAM RNG re-seed. + * + * To retain key across power cycles, the black key must be encapsulated as a + * blob. The blob key encryption key is derived from the CAAM master key which + * makes it non-volatile and can be re-created when the chip powers up again. + */ +#define KEY_BLOB_MODIFIER_SIZE 16 +static const uint8_t key_blob_modifier[KEY_BLOB_MODIFIER_SIZE] = + "NXP_OPTEE_BLOB"; + +/* + * Serialized CAAM key structure format. + * + * If the incoming key buffer is the following: + * | Magic number | key type | key size | key blob buffer | + * The CAAM Key structure will be populated as following: + * struct caamkey { + * .key_type = key type, + * .key_size = key size, + * .is_blob = true, + * .buf = key blob buffer + * } + * + * If the incoming key buffer is the following: + * | Key buffer | + * The CAAM Key structure will be populated as following: + * struct caamkey { + * .key_type = CAAM_KEY_PLAIN_TEXT, + * .key_size = sizeof(Key buffer), + * .is_blob = false, + * .buf = key buffer + * } + */ +struct caam_key_serialized { + uint32_t magic_number; /* Magic number */ + uint32_t key_type; /* Black key type */ + uint32_t sec_size; /* The original plain text key size */ + uint8_t key[]; +}; + +/* + * CAAM key type enumeration to string + */ +static const char *const caam_key_type_to_str[] __maybe_unused = { + [CAAM_KEY_PLAIN_TEXT] = "Plain Text", + [CAAM_KEY_BLACK_ECB] = "Black ECB", + [CAAM_KEY_BLACK_CCM] = "Black CCM", +}; + +static struct caam_key_serialized *data_to_serialized_key(const uint8_t *data, + size_t size) +{ + assert(data && size); + assert(size > sizeof(struct caam_key_serialized)); + + /* + * It's important to make sure uint8_t and caam_key_serialized{} are + * actually aligned for performance purpose. + * + * A __packed attribute to caam_key_serialized{} could solve the + * alignment issue but at the cost of un-optimize memory access. + * To avoid using the __packed attribute, caam_key_serialized{} is + * defined to be aligned on uint8_t. The following assert checks + * for this alignment. + */ + assert(IS_ALIGNED_WITH_TYPE(data, struct caam_key_serialized)); + + /* + * The cast to void* instead of struct caam_key_serialized* is needed + * to avoid the cast alignment compilation warning. + */ + return (void *)data; +} + +/* + * Return the CAAM key type of the given key buffer + * + * @data Input buffer + * @size Input buffer size + */ +static enum caam_key_type get_key_type(const uint8_t *data, size_t size) +{ + struct caam_key_serialized *key = data_to_serialized_key(data, size); + + if (key->magic_number != MAGIC_NUMBER) + return CAAM_KEY_PLAIN_TEXT; + + return key->key_type; +} + +/* + * Return the CAAM key size of the given key buffer + * + * @data Input buffer + * @size Input buffer size + */ +static size_t get_key_sec_size(const uint8_t *data, size_t size) +{ + struct caam_key_serialized *key = data_to_serialized_key(data, size); + + if (key->magic_number != MAGIC_NUMBER) + return size; + + return key->sec_size; +} + +/* + * Return the CAAM key buffer pointer of the given key buffer + * + * @data Input buffer + * @size Input buffer size + */ +static unsigned long get_key_buf_offset(const uint8_t *data, size_t size) +{ + struct caam_key_serialized *key = data_to_serialized_key(data, size); + + if (key->magic_number != MAGIC_NUMBER) + return 0; + else + return offsetof(struct caam_key_serialized, key); +} + +/* + * Return the CAAM key buffer size of the given key buffer + * + * @data Input buffer + * @size Input buffer size + */ +static size_t get_key_buf_size(const uint8_t *data, size_t size) +{ + struct caam_key_serialized *key = data_to_serialized_key(data, size); + + /* + * In the caam_key_serialized{}, the last element of the structure is + * a variable-sized buffer. + */ + return size - sizeof(*key); +} + +size_t caam_key_get_alloc_size(const struct caamkey *key) +{ + if (!key) + return 0; + + /* A blob size is independent from the key encryption algorithm */ + if (key->is_blob) + return key->sec_size + BLOB_PAD_SIZE; + + switch (key->key_type) { + case CAAM_KEY_PLAIN_TEXT: + /* + * If the key is plain text, the allocation size is equal to the + * key size and no blob operation on this key is possible. + */ + return key->sec_size; + case CAAM_KEY_BLACK_ECB: + /* ECB-black key must be a multiple of 16 bytes */ + return ROUNDUP(key->sec_size, 16); + case CAAM_KEY_BLACK_CCM: + /* + * CCM-black key must be a multiple of 8 bytes. The nonce and + * ICV add another 12 bytes to the allocation size + */ + return ROUNDUP(key->sec_size, 8) + BLACK_KEY_NONCE_SIZE + + BLACK_KEY_ICV_SIZE; + default: + return 0; + } +} + +void caam_key_dump(const char *trace, const struct caamkey *key) +{ + if (!key || !trace) + return; + + if (key->key_type >= CAAM_KEY_MAX_VALUE) + return; + + KEY_TRACE("%s key_type:%s key_size:%zu is_blob:%s addr:%p", + caam_key_type_to_str[key->key_type], trace, key->sec_size, + key->is_blob ? "yes" : "no", key->buf.data); + + if (key->buf.data) + KEY_DUMPBUF("Key data", key->buf.data, key->buf.length); +} + +enum caam_status caam_key_alloc(struct caamkey *key) +{ + size_t alloc_size = 0; + + if (!key) + return CAAM_BAD_PARAM; + + if (key->buf.data) { + KEY_TRACE("Key already allocated"); + return CAAM_BAD_PARAM; + } + + alloc_size = caam_key_get_alloc_size(key); + if (!alloc_size) + return CAAM_FAILURE; + + return caam_calloc_align_buf(&key->buf, alloc_size); +} + +void caam_key_free(struct caamkey *key) +{ + if (!key) + return; + + caam_free_buf(&key->buf); +} + +void caam_key_cache_op(enum utee_cache_operation op, const struct caamkey *key) +{ + if (!key) + return; + + if (!key->buf.nocache) + cache_operation(op, key->buf.data, key->buf.length); +} + +#define BLOB_OP_DESC_ENTRIES 12 +enum caam_status caam_key_operation_blob(const struct caamkey *in_key, + struct caamkey *out_key) +{ + enum caam_status status = CAAM_FAILURE; + struct caam_jobctx jobctx = { }; + uint32_t opflag = PROT_BLOB_TYPE(BLACK_KEY); + uint32_t *desc = NULL; + size_t output_buffer_size = 0; + size_t input_buffer_size = 0; + + assert(in_key && out_key); + + KEY_TRACE("Blob %scapsulation of the following key", + in_key->is_blob ? "de" : "en"); + + caam_key_dump("Blob input key", in_key); + + /* This function blobs or un-blobs */ + if (in_key->is_blob == out_key->is_blob) { + KEY_TRACE("Only one key must be defined as a blob"); + return CAAM_BAD_PARAM; + } + + /* A black blob cannot take a plain test key as input */ + if (out_key->key_type == CAAM_KEY_PLAIN_TEXT || + in_key->key_type == CAAM_KEY_PLAIN_TEXT) { + KEY_TRACE("A blob in/out operation cannot be plain text"); + return CAAM_BAD_PARAM; + } + + /* The key type must remain the same */ + if (out_key->key_type != in_key->key_type) { + KEY_TRACE("The in/out keys must have the same key type"); + return CAAM_BAD_PARAM; + } + + /* Define blob operation direction */ + if (out_key->is_blob) + opflag |= BLOB_ENCAPS; + else + opflag |= BLOB_DECAPS; + + /* Build OP flags depending on the blob type */ + switch (out_key->key_type) { + case CAAM_KEY_BLACK_ECB: + opflag |= PROT_BLOB_INFO(ECB); + break; + case CAAM_KEY_BLACK_CCM: + opflag |= PROT_BLOB_INFO(CCM); + break; + default: + return CAAM_BAD_PARAM; + } + + /* Allocate the descriptor */ + desc = caam_calloc_desc(BLOB_OP_DESC_ENTRIES); + if (!desc) { + KEY_TRACE("CAAM Context Descriptor Allocation error"); + return CAAM_OUT_MEMORY; + } + + status = caam_key_alloc(out_key); + if (status) { + KEY_TRACE("Key output allocation error"); + goto err; + } + + /* Define input and output buffer size */ + if (out_key->is_blob) { + /* + * For a blob operation, the input key size is the original key + * size of the black key. + * The output key size is the final blob size. + */ + input_buffer_size = in_key->sec_size; + output_buffer_size = out_key->buf.length; + } else { + /* + * For an non-blob operation, the input key size is the original + * key size of the black key. + * The output key size is the key security size. + */ + input_buffer_size = in_key->buf.length; + output_buffer_size = out_key->sec_size; + } + + /* Create the blob encapsulation/decapsulation descriptor */ + caam_desc_init(desc); + caam_desc_add_word(desc, DESC_HEADER(0)); + + /* Load the key modifier */ + caam_desc_add_word(desc, + LD_NOIMM(CLASS_2, REG_KEY, KEY_BLOB_MODIFIER_SIZE)); + caam_desc_add_ptr(desc, virt_to_phys((void *)key_blob_modifier)); + + /* Define the Input data sequence */ + caam_desc_add_word(desc, SEQ_IN_PTR(input_buffer_size)); + caam_desc_add_ptr(desc, in_key->buf.paddr); + + /* Define the Output data sequence */ + caam_desc_add_word(desc, SEQ_OUT_PTR(output_buffer_size)); + caam_desc_add_ptr(desc, out_key->buf.paddr); + caam_desc_add_word(desc, opflag); + + KEY_DUMPDESC(desc); + + caam_key_cache_op(TEE_CACHECLEAN, in_key); + caam_key_cache_op(TEE_CACHECLEAN, out_key); + + jobctx.desc = desc; + status = caam_jr_enqueue(&jobctx, NULL); + + if (status == CAAM_NO_ERROR) { + KEY_TRACE("CAAM Blob %scapsulation Done", + out_key->is_blob ? "En" : "De"); + + caam_key_cache_op(TEE_CACHEINVALIDATE, out_key); + caam_key_dump("Blob output key", out_key); + + goto out; + } else { + KEY_TRACE("CAAM Blob Status 0x%08" PRIx32 "", jobctx.status); + } + +err: + caam_key_free(out_key); +out: + caam_free_desc(&desc); + return status; +} + +enum caam_status caam_key_deserialize_from_bin(uint8_t *data, size_t size, + struct caamkey *key, + size_t sec_size) +{ + enum caam_status status = CAAM_FAILURE; + struct caamkey blob = { }; + + assert(data && size && key); + + KEY_TRACE("Deserialization binary buffer"); + KEY_DUMPBUF("Deserialize key buffer input", data, size); + + /* + * If a security key size is given, use it. Otherwise, rely on + * the buffer size. + * In some case, like ECC keys, the bignum size is less than the + * security size and it requires the key to be padded with 0's. + */ + if (sec_size == 0) + sec_size = get_key_sec_size(data, size); + + blob.key_type = get_key_type(data, size); + blob.sec_size = sec_size; + blob.is_blob = true; + + if (blob.key_type == CAAM_KEY_PLAIN_TEXT) { + key->sec_size = blob.sec_size; + key->key_type = blob.key_type; + key->is_blob = false; + + status = caam_key_alloc(key); + if (status) { + KEY_TRACE("Key allocation error"); + return status; + } + + /* Some asymmetric keys have leading zeros we must preserve */ + memcpy(key->buf.data + key->buf.length - size, data, size); + + return CAAM_NO_ERROR; + } + + status = caam_key_alloc(&blob); + if (status) { + KEY_TRACE("Key allocation error"); + return status; + } + + memcpy(blob.buf.data, data + get_key_buf_offset(data, size), + get_key_buf_size(data, size)); + + /* Set destination key */ + key->key_type = blob.key_type; + key->sec_size = blob.sec_size; + key->is_blob = false; + + /* De-blob operation */ + status = caam_key_operation_blob(&blob, key); + if (status) { + KEY_TRACE("De-blob operation fail"); + goto out; + } + + KEY_TRACE("Deserialization binary buffer done"); + caam_key_dump("Deserialization output key", key); +out: + caam_key_free(&blob); + return status; +} + +enum caam_status caam_key_serialize_to_bin(uint8_t *data, size_t size, + const struct caamkey *key) +{ + struct caam_key_serialized key_ser = { }; + struct caamkey blob = { }; + enum caam_status status = CAAM_FAILURE; + size_t serialized_size = 0; + + assert(data && size && key); + + caam_key_dump("Serialization input key", key); + + /* If the key is plain text, just copy key to buffer */ + if (key->key_type == CAAM_KEY_PLAIN_TEXT) { + if (size < key->buf.length) { + KEY_TRACE("Buffer is too short"); + return CAAM_SHORT_BUFFER; + } + + memcpy(data, key->buf.data, key->buf.length); + + return CAAM_NO_ERROR; + } + + /* The input key must not be a blob */ + assert(!key->is_blob); + + /* Blob the given key for serialization and export */ + blob.is_blob = true; + blob.sec_size = key->sec_size; + blob.key_type = key->key_type; + + /* + * Check if the destination is big enough for the black blob buffer and + * header. + */ + status = caam_key_serialized_size(&blob, &serialized_size); + if (status) + return status; + + if (size < serialized_size) { + KEY_TRACE("Destination buffer is too short %zu < %zu", size, + serialized_size); + return CAAM_OUT_MEMORY; + } + + /* Blob the given key */ + status = caam_key_operation_blob(key, &blob); + if (status) { + KEY_TRACE("Blob operation fail"); + return status; + } + + /* Copy the header to destination */ + key_ser.magic_number = MAGIC_NUMBER; + key_ser.key_type = blob.key_type; + key_ser.sec_size = blob.sec_size; + memcpy(data, &key_ser, sizeof(key_ser)); + + /* Copy the key buffer */ + memcpy(data + sizeof(key_ser), blob.buf.data, blob.buf.length); + + KEY_DUMPBUF("Key data", data, size); + + caam_key_free(&blob); + + return status; +} + +enum caam_status caam_key_serialized_size(const struct caamkey *key, + size_t *size) +{ + assert(key && size); + + /* For a plain text key, the serialized key is identical to the key */ + *size = key->buf.length; + + /* + * For black keys, the serialized key includes the header and must be + * in a blob format + */ + if (key->key_type != CAAM_KEY_PLAIN_TEXT) { + size_t alloc = 0; + const struct caamkey tmp = { + .key_type = key->key_type, + .sec_size = key->sec_size, + .is_blob = true, + }; + + alloc = caam_key_get_alloc_size(&tmp); + if (!alloc) + return CAAM_FAILURE; + + *size = alloc + sizeof(struct caam_key_serialized); + } + + return CAAM_NO_ERROR; +} + +enum caam_status caam_key_deserialize_from_bn(const struct bignum *inkey, + struct caamkey *outkey, + size_t size_sec) +{ + enum caam_status status = CAAM_FAILURE; + uint8_t *buf = NULL; + size_t size = 0; + + assert(inkey && outkey); + + KEY_TRACE("Deserialization bignum"); + + /* Get bignum size */ + size = crypto_bignum_num_bytes((struct bignum *)inkey); + + /* Allocate temporary buffer */ + buf = caam_calloc(size); + if (!buf) + return CAAM_OUT_MEMORY; + + /* Convert bignum to binary */ + crypto_bignum_bn2bin(inkey, buf); + + status = caam_key_deserialize_from_bin(buf, size, outkey, size_sec); + + caam_key_dump("Output key", outkey); + + caam_free(buf); + + return status; +} + +enum caam_status caam_key_serialize_to_bn(struct bignum *outkey, + const struct caamkey *inkey) +{ + enum caam_status status = CAAM_FAILURE; + TEE_Result res = TEE_ERROR_GENERIC; + uint8_t *buf = NULL; + size_t size = 0; + + assert(inkey && outkey); + + KEY_TRACE("Serialization bignum"); + caam_key_dump("Input key", inkey); + + status = caam_key_serialized_size(inkey, &size); + if (status) + return status; + + buf = caam_calloc(size); + if (!buf) + return CAAM_OUT_MEMORY; + + status = caam_key_serialize_to_bin(buf, size, inkey); + if (status) + goto out; + + res = crypto_bignum_bin2bn(buf, size, outkey); + if (res) + status = CAAM_FAILURE; +out: + caam_free(buf); + + return status; +} + +#define MAX_DESC_ENTRIES 22 +enum caam_status caam_key_black_encapsulation(struct caamkey *key, + enum caam_key_type key_type) +{ + enum caam_status status = CAAM_FAILURE; + struct caambuf input_buf = { }; + struct caam_jobctx jobctx = { }; + uint32_t *desc = NULL; + + assert(key); + assert(!key->is_blob && key->key_type == CAAM_KEY_PLAIN_TEXT); + assert(key_type != CAAM_KEY_PLAIN_TEXT); + + KEY_TRACE("Black key encapsulation"); + + /* Copy input plain text key to temp buffer */ + status = caam_calloc_align_buf(&input_buf, key->buf.length); + if (status) + return status; + + memcpy(input_buf.data, key->buf.data, key->buf.length); + cache_operation(TEE_CACHEFLUSH, input_buf.data, input_buf.length); + + /* Re-allocate the output key for black format */ + caam_key_free(key); + key->key_type = key_type; + + status = caam_key_alloc(key); + if (status) + goto out; + + /* Allocate the descriptor */ + desc = caam_calloc_desc(MAX_DESC_ENTRIES); + if (!desc) { + KEY_TRACE("Allocation descriptor error"); + status = CAAM_OUT_MEMORY; + goto out; + } + + caam_key_dump("Input key", key); + + caam_desc_init(desc); + caam_desc_add_word(desc, DESC_HEADER(0)); + caam_desc_add_word(desc, LD_KEY(CLASS_1, PKHA_E, key->sec_size)); + caam_desc_add_ptr(desc, input_buf.paddr); + + switch (key->key_type) { + case CAAM_KEY_BLACK_ECB: + caam_desc_add_word(desc, FIFO_ST(CLASS_NO, PKHA_E_AES_ECB_JKEK, + key->sec_size)); + break; + case CAAM_KEY_BLACK_CCM: + caam_desc_add_word(desc, FIFO_ST(CLASS_NO, PKHA_E_AES_CCM_JKEK, + key->sec_size)); + break; + default: + status = CAAM_FAILURE; + goto out; + } + + caam_desc_add_ptr(desc, key->buf.paddr); + + KEY_DUMPDESC(desc); + + caam_key_cache_op(TEE_CACHEFLUSH, key); + + jobctx.desc = desc; + status = caam_jr_enqueue(&jobctx, NULL); + if (status != CAAM_NO_ERROR) { + KEY_TRACE("CAAM return 0x%08x Status 0x%08" PRIx32, status, + jobctx.status); + status = CAAM_FAILURE; + goto out; + } + + caam_key_cache_op(TEE_CACHEINVALIDATE, key); + + caam_key_dump("Output Key", key); + +out: + caam_free_buf(&input_buf); + caam_free_desc(&desc); + + return status; +} + +enum caam_status caam_key_init(void) +{ + size_t alloc_size = 0; + const struct caamkey key = { + .key_type = caam_key_default_key_gen_type(), + .sec_size = 4096, /* Max RSA key size */ + .is_blob = true, + }; + + /* + * Ensure bignum format maximum size is enough to store a black key + * blob. The largest key is a 4096 bits RSA key pair. + */ + if (caam_key_serialized_size(&key, &alloc_size)) + return CAAM_FAILURE; + + assert(alloc_size <= CFG_CORE_BIGNUM_MAX_BITS); + + KEY_TRACE("Max serialized key size %zu", alloc_size); + + KEY_TRACE("Default CAAM key generation type %s", + caam_key_type_to_str[caam_key_default_key_gen_type()]); + + return CAAM_NO_ERROR; +} 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..b4f8b95 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/caam_rng.c @@ -0,0 +1,603 @@ +// 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 */ + bool pr_enabled; /* RNG prediction resistance */ + 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; + uint32_t op = RNG_GEN_DATA; + + if (rng_privdata->pr_enabled) + op |= ALGO_RNG_PR; + + /* 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, op); + caam_desc_add_word(desc, FIFO_ST(CLASS_NO, 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; + rng_privdata->pr_enabled = + caam_hal_rng_pr_enabled(rng_privdata->baseaddr); + + RNG_TRACE("RNG prediction resistance is %sabled", + rng_privdata->pr_enabled ? "en" : "dis"); + } + + 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 +#ifdef CFG_WITH_SOFTWARE_PRNG +void plat_rng_init(void) +{ + TEE_Result res = TEE_SUCCESS; + uint8_t buf[64] = { }; + + res = do_rng_read(buf, sizeof(buf)); + if (res) { + EMSG("Failed to read RNG: %#" PRIx32, res); + panic(); + } + + res = crypto_rng_init(buf, sizeof(buf)); + if (res) { + EMSG("Failed to initialize RNG: %#" PRIx32, res); + panic(); + } + + RNG_TRACE("PRNG seeded from CAAM"); +} +#else /* !CFG_WITH_SOFTWARE_PRNG */ +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 /* CFG_WITH_SOFTWARE_PRNG */ +#endif /* CFG_NXP_CAAM_RNG_DRV */ diff --git a/optee/optee_os/core/drivers/crypto/caam/caam_sm.c b/optee/optee_os/core/drivers/crypto/caam/caam_sm.c new file mode 100644 index 0000000..231df87 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/caam_sm.c @@ -0,0 +1,181 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2019, 2023 NXP + */ +#include +#include +#include +#include +#include +#include +#include + +/* + * Secure memory module private data + */ +static struct sm_privdata { + vaddr_t baseaddr; /* Secure memory base address */ + vaddr_t ctrl_addr; /* CAAM base address */ + vaddr_t jr_addr; /* Job Ring base address */ + paddr_t jr_offset; /* Job Ring offset */ +} sm_privdata; + +enum caam_status caam_sm_alloc(const struct caam_sm_page_desc *page_desc, + struct caam_sm_page_addr *page_addr) +{ + enum caam_status ret = CAAM_FAILURE; + + if (!page_desc || !page_addr) + return TEE_ERROR_BAD_PARAMETERS; + + ret = caam_hal_sm_check_page_partition(sm_privdata.jr_addr, page_desc); + if (ret != CAAM_NO_ERROR) { + SM_TRACE("Pages %u to %u or partition %u are out of bounds", + page_desc->page, + page_desc->page + page_desc->page_count - 1, + page_desc->partition); + return ret; + } + + /* Check if partition is already allocated */ + if (!caam_hal_sm_prtn_is_free(sm_privdata.jr_addr, + page_desc->partition)) { + SM_TRACE("Partition %u not available", page_desc->partition); + return CAAM_BUSY; + } + + /* Open secure memory partition to all groups */ + caam_hal_sm_open_access_perm(sm_privdata.jr_addr, page_desc->partition); + caam_hal_sm_set_access_all_group(sm_privdata.jr_addr, + page_desc->partition); + + ret = caam_hal_sm_allocate_page(sm_privdata.jr_addr, page_desc); + if (ret != CAAM_NO_ERROR) { + SM_TRACE("Error allocation Pages %u to %u into partition %u", + page_desc->page, + page_desc->page + page_desc->page_count - 1, + page_desc->partition); + + /* Free all potientiel pages allocated before failure */ + return caam_hal_sm_deallocate_pages(sm_privdata.jr_addr, + page_desc); + } + + page_addr->paddr = caam_hal_ctrl_get_smvaddr(sm_privdata.ctrl_addr, + sm_privdata.jr_offset) + + caam_hal_sm_get_pages_size(sm_privdata.jr_addr, + page_desc->page); + page_addr->vaddr = sm_privdata.baseaddr + + caam_hal_sm_get_pages_size(sm_privdata.jr_addr, + page_desc->page); + + SM_TRACE("Partition %u Pages %u to %u allocated @0x%" PRIxVA + " (phys 0x@%" PRIxPA, + page_desc->partition, page_desc->page, + page_desc->page + page_desc->page_count - 1, page_addr->vaddr, + page_addr->paddr); + + return CAAM_NO_ERROR; +} + +enum caam_status caam_sm_free(const struct caam_sm_page_desc *page_desc) +{ + enum caam_status ret = CAAM_FAILURE; + + SM_TRACE("Free Secure Memory pages %u to %u from partition %u", + page_desc->page, page_desc->page + page_desc->page_count, + page_desc->partition); + + /* + * De-allocate partition. It automatically releases partition's pages + * to the pool of available pages. if the partition if marked as CSP, + * pages will be zeroized. If the partition is marked as PSP, + * partition and pages will not be de-allocated and a PSP will be + * returned. + */ + if (!caam_hal_sm_prtn_is_owned(sm_privdata.jr_addr, + page_desc->partition)) { + SM_TRACE("Partition %u not owned by used JR", + page_desc->partition); + return TEE_ERROR_ACCESS_DENIED; + } + + ret = caam_hal_sm_deallocate_pages(sm_privdata.jr_addr, page_desc); + if (ret) { + SM_TRACE("De-alloc pages %u to %u error 0x%" PRIx32, + page_desc->page, + page_desc->page + page_desc->page_count, ret); + + return ret; + } + + ret = caam_hal_sm_deallocate_partition(sm_privdata.jr_addr, + page_desc->partition); + if (ret) { + SM_TRACE("De-alloc partition %u error 0x%" PRIx32, + page_desc->partition, ret); + return ret; + } + + return CAAM_NO_ERROR; +} + +enum caam_status +caam_sm_set_access_perm(const struct caam_sm_page_desc *page_desc, + unsigned int grp1_perm, unsigned int grp2_perm) +{ + uint32_t grp1 = UINT32_MAX; + uint32_t grp2 = UINT32_MAX; + + if (!page_desc) + return CAAM_BAD_PARAM; + + /* Check if the partition is already owned */ + if (!caam_hal_sm_prtn_is_owned(sm_privdata.jr_addr, + page_desc->partition)) { + SM_TRACE("Partition %d not owned by current JR", + page_desc->partition); + return CAAM_FAILURE; + } + + /* + * Set ourself to access Secure Memory group 1 and/or group 2 + * function if @grp1_perm and/or @grp2_perm not equal 0. + * + * The Access Group is related to the Job Ring owner setting without + * the Secure Bit setting already managed by the Job Ring. + */ + if (grp1_perm) + grp1 = JROWN_ARM_NS; + + if (grp2_perm) + grp2 = JROWN_ARM_NS; + + caam_hal_sm_set_access_group(sm_privdata.jr_addr, page_desc->partition, + grp1, grp2); + caam_hal_sm_set_access_perm(sm_privdata.jr_addr, page_desc->partition, + grp1_perm, grp2_perm); + + return CAAM_NO_ERROR; +} + +enum caam_status caam_sm_init(struct caam_jrcfg *jrcfg) +{ + if (!jrcfg) + return CAAM_FAILURE; + + sm_privdata.ctrl_addr = jrcfg->base; + sm_privdata.jr_addr = jrcfg->base + jrcfg->offset; + sm_privdata.jr_offset = jrcfg->offset; + sm_privdata.baseaddr = caam_hal_sm_get_base(); + + if (!sm_privdata.baseaddr) + return CAAM_FAILURE; + + SM_TRACE("Secure Memory Base address = 0x%" PRIxVA, + sm_privdata.baseaddr); + SM_TRACE("CAAM controller address = 0x%" PRIxVA, sm_privdata.ctrl_addr); + SM_TRACE("CAAM Job Ring address = 0x%" PRIxVA, sm_privdata.jr_addr); + + return CAAM_NO_ERROR; +} 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..f73a6f1 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/cipher/caam_cipher_mac.c @@ -0,0 +1,825 @@ +// 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; + + /* + * 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; + } + 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..0b54b2b --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/crypto.mk @@ -0,0 +1,215 @@ +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),$(mx8dxl-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,356) +$(call force, CFG_NXP_CAAM_SGT_V1,y) +$(call force, CFG_CAAM_JR_DISABLE_NODE,n) +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) +# There is a limitation on i.MX8M platforms regarding ECDSA Sign/Verify +# Size of Class 2 Context register is 40bytes, because of which sign/verify +# of a hash of more than 40bytes fails. So a workaround is implemented for +# this issue, controlled by CFG_NXP_CAAM_C2_CTX_REG_WA flag. +$(call force, CFG_NXP_CAAM_C2_CTX_REG_WA,y) +caam-drivers += MP DEK +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 + +# Define the default CAAM private key encryption generation and the bignum +# maximum size needed. +# CAAM_KEY_PLAIN_TEXT -> 4096 bits +# CAAM_KEY_BLACK_ECB|CCM -> 4156 bits +CFG_CORE_BIGNUM_MAX_BITS ?= 4156 + +# Enable CAAM non-crypto drivers +$(foreach drv, $(caam-drivers), $(eval CFG_NXP_CAAM_$(drv)_DRV ?= y)) + +# Prefer CAAM HWRNG over PRNG seeded by CAAM +ifeq ($(CFG_NXP_CAAM_RNG_DRV), y) +CFG_WITH_SOFTWARE_PRNG ?= n +endif + +# DEK driver requires the SM driver to be enabled +ifeq ($(CFG_NXP_CAAM_DEK_DRV), y) +$(call force, CFG_NXP_CAAM_SM_DRV,y,Mandated by CFG_NXP_CAAM_DEK_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 + +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..2bdf9e6 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/common/hal_cfg.c @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2017-2019, 2021 NXP + * + * Brief CAAM Configuration. + */ +#include +#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..8783eec --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/common/hal_ctrl.c @@ -0,0 +1,270 @@ +// 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 +#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 */ + +#ifdef CFG_NXP_CAAM_SM_DRV +vaddr_t caam_hal_ctrl_get_smvaddr(vaddr_t ctrl_addr, paddr_t jr_offset) +{ + /* + * The Secure Memory Virtual Base Address contains only the upper + * bits of the base address of Secure Memory in this Job Ring's virtual + * address space. Since the base address of Secure Memory must be on a + * 64 kbyte boundary, the least significant 16 bits are omitted. + */ + return io_caam_read32(ctrl_addr + JRX_SMVBAR(JRX_IDX(jr_offset))) << 16; +} +#endif /* CFG_NXP_CAAM_SM_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..3fab565 --- /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"); + 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"); + 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..aba8cbc --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/common/hal_rng.c @@ -0,0 +1,162 @@ +// 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; +} + +/* + * This function will be overridden for i.MX8QX and i.MX8DX platforms. + */ +bool __weak caam_hal_rng_pr_enabled(vaddr_t baseaddr) +{ + uint32_t bitmask = RNG_STA_PR0; + + if (caam_hal_rng_get_nb_sh(baseaddr) > 1) + bitmask |= RNG_STA_PR1; + + return (io_caam_read32(baseaddr + RNG_STA) & bitmask) == bitmask; +} + +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/hal_sm.c b/optee/optee_os/core/drivers/crypto/caam/hal/common/hal_sm.c new file mode 100644 index 0000000..04552c2 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/common/hal_sm.c @@ -0,0 +1,220 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2019, 2023 NXP + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Issue a Secure Memory Command to the @page and @partition. + * Returns the command status when completed + * + * @jr_base JR virtual base address + * @page Memory Page + * @partition Partition + * @cmd Command to sent + */ +static uint32_t issue_cmd(vaddr_t jr_base, unsigned int page, + unsigned int partition, uint8_t cmd) +{ + uint32_t status = 0; + uint64_t timeout_ref = timeout_init_us(10000); + + assert(jr_base); + + /* Send cmd */ + io_caam_write32(jr_base + SM_SMCR, SM_SMCR_PAGE(page) | + SM_SMCR_PRTN(partition) | + SM_SMCR_CMD(cmd)); + + /* Wait for the command to complete */ + do { + if (timeout_elapsed(timeout_ref)) + break; + status = io_caam_read32(jr_base + SM_SMCSR); + } while (SM_SMCSR_CERR(status) == SM_SMCSR_CERR_NOT_COMPLETED); + + return io_caam_read32(jr_base + SM_SMCSR); +} + +enum caam_status +caam_hal_sm_check_page_partition(vaddr_t jr_base, + const struct caam_sm_page_desc *page_desc) +{ + uint32_t val = 0; + + if (!jr_base || !page_desc) + return CAAM_BAD_PARAM; + + val = io_caam_read32(jr_base + SMVID_MS); + + if (page_desc->page + page_desc->page_count > + GET_SMVID_MS_MAX_NPAG(val) || + page_desc->partition > GET_SMVID_MS_NPRT(val)) + return CAAM_BAD_PARAM; + + return CAAM_NO_ERROR; +} + +size_t caam_hal_sm_get_pages_size(vaddr_t jr_base, unsigned int page) +{ + size_t page_size = 0; + + page_size = GET_SMVID_LS_PSIZ(io_caam_read32(jr_base + SMVID_LS)); + + return SHIFT_U32(1, page_size) * (size_t)page * 1024; +} + +bool caam_hal_sm_prtn_is_free(vaddr_t jr_base, unsigned int partition) +{ + return SM_SMPO_OWNER(io_caam_read32(jr_base + SM_SMPO), partition) == + SMPO_PO_AVAIL; +} + +bool caam_hal_sm_prtn_is_owned(vaddr_t jr_base, unsigned int partition) +{ + return SM_SMPO_OWNER(io_caam_read32(jr_base + SM_SMPO), partition) == + SMPO_PO_OWNED; +} + +void caam_hal_sm_set_access_all_group(vaddr_t jr_base, unsigned int partition) +{ + io_caam_write32(jr_base + SM_SMAG1(partition), UINT32_MAX); + io_caam_write32(jr_base + SM_SMAG2(partition), UINT32_MAX); +} + +void caam_hal_sm_set_access_group(vaddr_t jr_base, unsigned int partition, + uint32_t grp1, uint32_t grp2) +{ + if (!jr_base) + return; + + if (grp1 != UINT32_MAX) + io_caam_write32(jr_base + SM_SMAG1(partition), + SHIFT_U32(1, grp1)); + + if (grp2 != UINT32_MAX) + io_caam_write32(jr_base + SM_SMAG2(partition), + SHIFT_U32(1, grp2)); +} + +void caam_hal_sm_open_access_perm(vaddr_t jr_base, unsigned int partition) +{ + io_caam_write32(jr_base + SM_SMAPR(partition), + SM_SMAPR_GRP1(UINT8_MAX) | SM_SMAPR_GRP2(UINT8_MAX)); +} + +void caam_hal_sm_set_access_perm(vaddr_t jr_base, unsigned int partition, + unsigned int grp1_perm, unsigned int grp2_perm) +{ + io_caam_write32(jr_base + SM_SMAPR(partition), + SM_SMAPR_GRP1(grp1_perm) | SM_SMAPR_GRP2(grp2_perm) | + SM_SMAPR_CSP | SM_SMAPR_SMAP_LCK | SM_SMAPR_SMAG_LCK); +} + +enum caam_status +caam_hal_sm_allocate_page(vaddr_t jr_base, + const struct caam_sm_page_desc *page_desc) +{ + unsigned int page = 0; + uint32_t status = 0; + + if (!jr_base || !page_desc) + return CAAM_BAD_PARAM; + + /* Check if pages are available */ + for (page = page_desc->page; + page < page_desc->page + page_desc->page_count; page++) { + status = issue_cmd(jr_base, page, page_desc->partition, + SM_SMCR_PAGE_INQ); + if (SM_SMCSR_PO(status) != SM_SMCSR_PO_AVAILABLE) + return CAAM_BUSY; + } + + /* Allocate pages to partition */ + for (page = page_desc->page; + page < page_desc->page + page_desc->page_count; page++) { + status = issue_cmd(jr_base, page, page_desc->partition, + SM_SMCR_PAGE_ALLOC); + if (SM_SMCSR_AERR(status) != SM_SMCSR_AERR_NO_ERROR) + return CAAM_FAILURE; + } + + /* Check if pages are available */ + for (page = page_desc->page; + page < page_desc->page + page_desc->page_count; page++) { + status = issue_cmd(jr_base, page, page_desc->partition, + SM_SMCR_PAGE_INQ); + if (SM_SMCSR_PO(status) != SM_SMCSR_PO_OWNED || + SM_SMCSR_PRTN(status) != page_desc->partition) + return CAAM_FAILURE; + } + + return CAAM_NO_ERROR; +} + +enum caam_status caam_hal_sm_deallocate_partition(vaddr_t jr_base, + unsigned int partition) +{ + unsigned int status = 0; + + if (!jr_base) + return CAAM_BAD_PARAM; + + /* De-Allocate partition and so all partition's page */ + status = issue_cmd(jr_base, 0, partition, SM_SMCR_PARTITION_DEALLOC); + if (SM_SMCSR_AERR(status) != SM_SMCSR_AERR_NO_ERROR) + return CAAM_FAILURE; + + return CAAM_NO_ERROR; +} + +enum caam_status +caam_hal_sm_deallocate_pages(vaddr_t jr_base, + const struct caam_sm_page_desc *page_desc) +{ + unsigned int page = 0; + uint32_t status = 0; + + if (!jr_base || !page_desc) + return CAAM_BAD_PARAM; + + for (page = page_desc->page; + page < page_desc->page + page_desc->page_count; page++) { + /* Deallocate page, set partition as not used */ + status = issue_cmd(jr_base, page, 0, SM_SMCR_PAGE_DEALLOC); + if (SM_SMCSR_AERR(status) != SM_SMCSR_AERR_NO_ERROR) + return CAAM_FAILURE; + } + + return CAAM_NO_ERROR; +} + +register_phys_mem(MEM_AREA_IO_SEC, SECMEM_BASE, SECMEM_SIZE); +vaddr_t caam_hal_sm_get_base(void) +{ + vaddr_t sm_base = 0; + void *fdt = NULL; + + fdt = get_dt(); + if (fdt) + caam_hal_sm_get_base_dt(fdt, &sm_base); + + if (!sm_base) + sm_base = core_mmu_get_va(SECMEM_BASE, MEM_AREA_IO_SEC, + SECMEM_SIZE); + + return sm_base; +} 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..260fef5 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/common/registers/rng_regs.h @@ -0,0 +1,121 @@ +/* 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) +#define RNG_STA_PR0 BIT32(4) +#define RNG_STA_PR1 BIT32(5) + +#endif /* __RNG_REGS_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/common/registers/sm_regs.h b/optee/optee_os/core/drivers/crypto/caam/hal/common/registers/sm_regs.h new file mode 100644 index 0000000..f8a328c --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/common/registers/sm_regs.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2019 NXP + */ +#ifndef __SM_REGS_H__ +#define __SM_REGS_H__ + +#include + +/* Access Permission */ +#define SM_SMAPR(prtn) (0x0A04 + (prtn) * 16) +#define SM_SMAPR_GRP1(perm) SHIFT_U32((perm) & 0xF, 0) +#define SM_SMAPR_GRP2(perm) SHIFT_U32((perm) & 0xF, 4) +#define SM_SMAPR_CSP BIT32(15) +#define SM_SMAPR_SMAP_LCK BIT32(13) +#define SM_SMAPR_SMAG_LCK BIT32(12) + +/* Access Group */ +#define SM_SMAG2(prtn) (0x0A08 + (prtn) * 16) +#define SM_SMAG1(prtn) (0x0A0C + (prtn) * 16) + +/* Command */ +#define SM_SMCR 0x0BE4 +#define SM_SMCR_PAGE(page) SHIFT_U32((page) & UINT16_MAX, 16) +#define SM_SMCR_PRTN(prtn) SHIFT_U32((prtn) & 0xF, 8) +#define SM_SMCR_CMD(cmd) SHIFT_U32((cmd) & 0xF, 0) +#define SM_SMCR_PAGE_ALLOC 0x1 +#define SM_SMCR_PAGE_DEALLOC 0x2 +#define SM_SMCR_PARTITION_DEALLOC 0x3 +#define SM_SMCR_PAGE_INQ 0x5 + +/* Command Status */ +#define SM_SMCSR 0x0BEC +#define SM_SMCSR_CERR(val) (((val) >> 14) & 0x3) +#define SM_SMCSR_CERR_NO_ERROR 0x0 +#define SM_SMCSR_CERR_NOT_COMPLETED 0x1 +#define SM_SMCSR_AERR(val) (((val) >> 12) & 0x3) +#define SM_SMCSR_AERR_NO_ERROR 0x0 +#define SM_SMCSR_PO(val) (((val) >> 6) & 0x3) +#define SM_SMCSR_PO_AVAILABLE 0x0 +#define SM_SMCSR_PO_UNKNOWN 0x1 +#define SM_SMCSR_PO_OWNED_BY_OTHER 0x2 +#define SM_SMCSR_PO_OWNED 0x3 +#define SM_SMCSR_PRTN(val) ((val) & 0x3) + +/* Partition Owners */ +#define SM_SMPO 0x0FBC +#define SM_SMPO_PART(prtn) ((prtn) * 2) +#define SM_SMPO_OWNER(val, prtn) (((val) >> SM_SMPO_PART(prtn)) & 0x3) +#define SMPO_PO_AVAIL 0x0 +#define SMPO_PO_OWNED 0x3 + +#endif /* __SM_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..dbab332 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/common/sub.mk @@ -0,0 +1,10 @@ +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 +srcs-$(CFG_NXP_CAAM_SM_DRV) += hal_sm.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..2235d28 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/imx_8m/registers/ctrl_regs.h @@ -0,0 +1,44 @@ +/* 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) + +/* Secure Memory physical base address */ +#define JRX_SMVBAR(idx) (0x0184 + (idx) * 8) + +#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..40d9a6b --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/hal_rng.c @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2020-2021, 2024 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; +} + +bool caam_hal_rng_pr_enabled(vaddr_t baseaddr __unused) +{ + /* + * On platforms i.MX8Q and i.MX8DXL CAAM RNG Prediction + * resistance is enabled by default. So returning true. + */ + return true; +} 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..86f316a --- /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) $(CFG_MX8DXL)),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..3bc5b31 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hash/caam_hash_mac.c @@ -0,0 +1,350 @@ +// 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(CLASS_NO, + 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..370388a --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/include/caam_desc_defines.h @@ -0,0 +1,747 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2018-2021, 2023 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 + +#define PROT_RSA_FINISH_KEY_ENC_OUT(alg) PROT_RSA_FINISH_KEY_ENC_OUT_##alg +#define PROT_RSA_FINISH_KEY_ENC_OUT_ECB BIT32(6) +#define PROT_RSA_FINISH_KEY_ENC_OUT_CCM BIT32(6) + +#define PROT_RSA_FINISH_KEY_ENC(alg) PROT_RSA_FINISH_KEY_ENC_##alg +#define PROT_RSA_FINISH_KEY_ENC_ECB 0 +#define PROT_RSA_FINISH_KEY_ENC_CCM BIT32(4) + +#define PROT_RSA_FINISH_KEY(alg) PROT_RSA_FINISH_KEY_##alg +#define PROT_RSA_FINISH_KEY_NONE 0 +#define PROT_RSA_FINISH_KEY_ECB (PROT_RSA_FINISH_KEY_ENC_OUT_ECB | \ + PROT_RSA_FINISH_KEY_ENC_ECB) +#define PROT_RSA_FINISH_KEY_CCM (PROT_RSA_FINISH_KEY_ENC_OUT_CCM | \ + PROT_RSA_FINISH_KEY_ENC_CCM) + +#define PROT_RSA_KEY_ENC(format) SHIFT_U32((PROT_RSA_KEY_ENC_##format) & 0x3, 8) +#define PROT_RSA_KEY_ENC_NONE 0 +#define PROT_RSA_KEY_ENC_ECB 1 +#define PROT_RSA_KEY_ENC_CCM 3 + +/* + * ECC Protocol Information + */ +#define PROT_PK_MSG(type) SHIFT_U32(PROT_PK_MSG_##type, 10) +#define PROT_PK_MSG_MES_REP 0 +#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 +#define PROT_PRI_ENC(alg) PROT_PRI_ENC_##alg +#define PROT_PRI_ENC_ECB BIT32(2) +#define PROT_PRI_ENC_CCM BIT32(2) +#define PROT_PRI_EXT(type) PROT_PRI_EXT_##type +#define PROT_PRI_EXT_ECB 0 +#define PROT_PRI_EXT_CCM BIT32(4) +#define PROT_PRI(alg) PROT_PRI_##alg +#define PROT_PRI_NONE 0 +#define PROT_PRI_ECB (PROT_PRI_ENC(ECB) | PROT_PRI_EXT(ECB)) +#define PROT_PRI_CCM (PROT_PRI_ENC(CCM) | PROT_PRI_EXT(CCM)) + +/* + * 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_SEC_MEM BIT32(3) +#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..7c1d255 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/include/caam_desc_helper.h @@ -0,0 +1,567 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2018-2021, 2024 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(CLASS_NO, 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 of class starting of + * register offset. + */ +#define LD_IMM_OFF(cla, dst, len, off) \ + (CMD_LOAD_TYPE | CMD_CLASS(cla) | CMD_IMM | LOAD_DST(dst) | \ + LOAD_OFFSET(off) | 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(cla, src, len) \ + (CMD_FIFO_STORE_TYPE | CMD_CLASS(cla) | 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)) + +/* + * Load a class cla key of length len to register dst. + */ +#define LD_KEY(cla, dst, len) \ + (CMD_KEY_TYPE | CMD_CLASS(cla) | KEY_DEST(dst) | 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, alg) \ + (CMD_OP_TYPE | PROTID(RSA_FINISH_KEY) | PROT_RSA_KEY(format) | \ + PROT_RSA_FINISH_KEY(alg)) + +/* + * Public Keypair generation + */ +#define PK_KEYPAIR_GEN(type, alg) \ + (CMD_OP_TYPE | OP_TYPE(UNI) | PROTID(PKKEY) | PROT_PK_TYPE(type) | \ + PROT_PRI(alg)) + +/* + * DSA/ECDSA signature of message of msg_type + */ +#define DSA_SIGN(type, msg_type, alg) \ + (CMD_OP_TYPE | OP_TYPE(UNI) | PROTID(DSASIGN) | \ + PROT_PK_MSG(msg_type) | PROT_PK_TYPE(type) | PROT_PRI(alg)) + +/* + * DSA/ECDSA signature verify message of msg_type + */ +#define DSA_VERIFY(type, msg_type) \ + (CMD_OP_TYPE | OP_TYPE(UNI) | PROTID(DSAVERIFY) | \ + PROT_PK_MSG(msg_type) | PROT_PK_TYPE(type)) + +/* + * DH/ECC Shared Secret + */ +#define SHARED_SECRET(type, alg) \ + (CMD_OP_TYPE | OP_TYPE(UNI) | PROTID(SHARED_SECRET) | \ + PROT_PK_TYPE(type) | PROT_PRI(alg)) + +/* + * 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..f3cea24 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/include/caam_hal_ctrl.h @@ -0,0 +1,108 @@ +/* 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 */ + +#ifdef CFG_NXP_CAAM_SM_DRV +/* + * Get the Secure Memory Virtual base address setup in the given job ring + * + * @ctrl_addr Controller base address + * @jr_offset Job ring offset + */ +vaddr_t caam_hal_ctrl_get_smvaddr(vaddr_t ctrl_addr, paddr_t jr_offset); +#endif /* CFG_NXP_CAAM_SM_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..ef5e19a --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/include/caam_hal_rng.h @@ -0,0 +1,57 @@ +/* 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); + +/* + * Returns true if the RNG was initialized for prediction resistance + * + * @baseaddr RNG Base Address + */ +bool caam_hal_rng_pr_enabled(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_hal_sm.h b/optee/optee_os/core/drivers/crypto/caam/include/caam_hal_sm.h new file mode 100644 index 0000000..171a9bd --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/include/caam_hal_sm.h @@ -0,0 +1,127 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2019, 2023 NXP + */ +#ifndef __CAAM_HAL_SM_H__ +#define __CAAM_HAL_SM_H__ + +#include +#include + +/* + * Checks if @page and @partition number are valid + * + * @jr_base JR base address + * @sm_page_desc Secure Memory page + */ +enum caam_status +caam_hal_sm_check_page_partition(vaddr_t jr_base, + const struct caam_sm_page_desc *sm_page_desc); + +/* + * Return the Pages Size in KBytes + * + * @jr_base JR base address + * @page Page number + */ +size_t caam_hal_sm_get_pages_size(vaddr_t jr_base, unsigned int page); + +/* + * Return if the partition is free (available) + * + * @jr_base JR base address + * @partition Partition number + */ +bool caam_hal_sm_prtn_is_free(vaddr_t jr_base, unsigned int partition); + +/* + * Return if the partition is owned (by the HW register reader) + * + * @jr_base JR base address + * @partition Partition number + */ +bool caam_hal_sm_prtn_is_owned(vaddr_t jr_base, unsigned int partition); + +/* + * Set the Secure Memory access to all groups + * + * @jr_base JR base address + * @partition Partition number + * @grp1 Group 1 value + * @grp2 Group 2 value + */ +void caam_hal_sm_set_access_all_group(vaddr_t jr_base, unsigned int partition); + +/* + * Set the Secure Memory access to group 1 and/or group 2 + * + * @jr_base JR base address + * @partition Partition number + * @grp1 Group 1 value + * @grp2 Group 2 value + */ +void caam_hal_sm_set_access_group(vaddr_t jr_base, unsigned int partition, + uint32_t grp1, uint32_t grp2); + +/* + * Open all Secure Memory Permissions + * + * @jr_base JR base address + * @partition Partition number + */ +void caam_hal_sm_open_access_perm(vaddr_t jr_base, unsigned int partition); + +/* + * Set the Secure Memory access permission for group 1 and group 2. + * Enable Critical Security and lock configuration + * + * @jr_base JR base address + * @partition Partition number + * @grp1_perm Group 1 Permissions + * @grp2_perm Group 2 Permissions + */ +void caam_hal_sm_set_access_perm(vaddr_t jr_base, unsigned int partition, + unsigned int grp1_perm, + unsigned int grp2_perm); + +/* + * Allocate a @page to the @partition. + * + * @jr_base JR base address + * @sm_page_desc Secure Memory page + */ +enum caam_status +caam_hal_sm_allocate_page(vaddr_t jr_base, + const struct caam_sm_page_desc *sm_page_desc); + +/* + * De-allocate a @partition and all partition's page. + * + * @jr_base JR base address + * @partition Partition number + */ +enum caam_status caam_hal_sm_deallocate_partition(vaddr_t jr_base, + unsigned int partition); + +/* + * De-allocate all pages specified in the @sm struct + * + * @jr_base JR base address + * @sm_page_desc Secure Memory page + */ +enum caam_status +caam_hal_sm_deallocate_pages(vaddr_t jr_base, + const struct caam_sm_page_desc *sm_page_desc); + +/* Return the virtual base address of the Secure Memory registers */ +vaddr_t caam_hal_sm_get_base(void); + +#ifdef CFG_DT +void caam_hal_sm_get_base_dt(void *fdt, vaddr_t *sm_base); +#else +static inline void caam_hal_sm_get_base_dt(void *fdt __unused, vaddr_t *sm_base) +{ + *sm_base = 0; +} +#endif /* CFG_DT */ +#endif /* __CAAM_HAL_SM_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_key.h b/optee/optee_os/core/drivers/crypto/caam/include/caam_key.h new file mode 100644 index 0000000..e0a98a2 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/include/caam_key.h @@ -0,0 +1,155 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2023 NXP + */ +#ifndef __CAAM_KEY_H__ +#define __CAAM_KEY_H__ + +#include +#include +#include + +/* + * CAAM Key types + */ +enum caam_key_type { + CAAM_KEY_PLAIN_TEXT = 0, /* Plain text key or red key */ + CAAM_KEY_BLACK_ECB, /* Black key AES-ECB encrypted */ + CAAM_KEY_BLACK_CCM, /* Black key AES-CCM encrypted */ + CAAM_KEY_MAX_VALUE, /* Max value - not valid */ +}; + +/* + * CAAM key structure + */ +struct caamkey { + struct caambuf buf; /* Key buffer */ + enum caam_key_type key_type; /* CAAM Key type */ + size_t sec_size; /* Security key size */ + bool is_blob; /* Shows if the key is in blob format */ +}; + +/* + * Returns the default key type for CAAM key generation. + * The CAAM can only generate one key type. + */ +static inline enum caam_key_type caam_key_default_key_gen_type(void) +{ + return CAAM_KEY_BLACK_CCM; +} + +/* + * Print CAAM Key structure + * + * @trace Additional log string + * @key Key to print + */ +void caam_key_dump(const char *trace, const struct caamkey *key); + +/* + * Allocate CAAM key buffer based on the CAAM key type, key security size, and + * whether it is in a blob format or not. + * + * @key CAAM key to allocate + */ +enum caam_status caam_key_alloc(struct caamkey *key); + +/* + * Free the CAAM key buffer + * + * @key CAAM key to free + */ +void caam_key_free(struct caamkey *key); + +/* + * Perform a cache operation on CAAM key buffer. + * + * @op Cache operation type + * @key CAAM key buffer to operate + */ +void caam_key_cache_op(enum utee_cache_operation op, const struct caamkey *key); + +/* + * Encapsulate or decapsulate the given CAAM key + * + * @in_key CAAM Key to encapsulate or decapsulate + * @out_key CAAM Key operation result. The out_key is allocated by the function. + */ +enum caam_status caam_key_operation_blob(const struct caamkey *in_key, + struct caamkey *out_key); + +/* + * Deserialize CAAM key structure from binary buffer + * + * @data Buffer input + * @size Buffer input size + * @key CAAM key structure to populate + * @sec_size Security key size to deserialize, optional. If not needed, + * set it to 0. + */ +enum caam_status caam_key_deserialize_from_bin(uint8_t *data, size_t size, + struct caamkey *key, + size_t sec_size); + +/* + * Serialize CAAM key structure to binary buffer + * + * @data Buffer output + * @size Buffer output size + * @key CAAM key structure to serialize + */ +enum caam_status caam_key_serialize_to_bin(uint8_t *data, size_t size, + const struct caamkey *key); + +/* + * Deserialize CAAM key structure from bignum + * + * @inkey Bignum input + * @outkey CAAM key structure to populate + * @size_sec Security key size to deserialize, optional. If not needed, + * set it to zero. + */ +enum caam_status caam_key_deserialize_from_bn(const struct bignum *inkey, + struct caamkey *outkey, + size_t size_sec); + +/* + * Serialize CAAM key structure to bignum + * + * @outkey Bignum output + * @inkey CAAM key structure to serialize + */ +enum caam_status caam_key_serialize_to_bn(struct bignum *outkey, + const struct caamkey *inkey); + +/* + * Return the key buffer size needed given the CAAM key type, key security size, + * and whether it is in a blob format or not + * + * @key CAAM key structure input + */ +size_t caam_key_get_alloc_size(const struct caamkey *key); + +/* + * Return the buffer size needed to serialize the given CAAM key structure + * + * @key CAAM Key structure to serialize + * @size returned buffer size + */ +enum caam_status caam_key_serialized_size(const struct caamkey *key, + size_t *size); + +/* + * Encapsulate a plain text key to CAAM black key. + * + * @key CAAM key to encapsulate + * @key_type CAAM key encapsulation type + */ +enum caam_status caam_key_black_encapsulation(struct caamkey *key, + enum caam_key_type key_type); + +/* + * CAAM Key initialization + */ +enum caam_status caam_key_init(void); +#endif /* __CAAM_KEY_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_sm.h b/optee/optee_os/core/drivers/crypto/caam/include/caam_sm.h new file mode 100644 index 0000000..5dee433 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/include/caam_sm.h @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2018-2019, 2023 NXP + */ +#ifndef __CAAM_SM_H__ +#define __CAAM_SM_H__ + +#include "caam_jr.h" +#include "drivers/caam_extension.h" + +/* + * Secure Memory data + */ +struct caam_sm_page_addr { + paddr_t paddr; /* Secure memory base address */ + vaddr_t vaddr; /* Secure memory virtual base address */ +}; + +/* + * Secure Memory Page(s)/Partition definition + */ +struct caam_sm_page_desc { + unsigned int partition; /* Partition number */ + unsigned int page; /* Page number */ + unsigned int page_count; /* Number of pages used */ +}; + +#ifdef CFG_NXP_CAAM_SM_DRV +/* + * CAAM Secure memory module initialization + * + * @jrcfg JR configuration structure + */ +enum caam_status caam_sm_init(struct caam_jrcfg *jrcfg); + +/* + * Allocate page(s) to one partition in the CAAM secure memory. + * Reset the group access and permission access to remove restrictions. + * + * @sm_page_descriptor Secure Memory page + * @sm_page_addr [out] Secure Memory page addresses + */ +enum caam_status +caam_sm_alloc(const struct caam_sm_page_desc *sm_page_descriptor, + struct caam_sm_page_addr *sm_page_addr); + +/* + * Set the Secure Memory group 1 and group 2 access rights to allocated + * partition and lock configuration. + * + * @page_desc Secure Memory page + * @grp1_perm Group 1 Permission value + * @grp2_perm Group 2 Permission value + */ +enum caam_status +caam_sm_set_access_perm(const struct caam_sm_page_desc *page_desc, + unsigned int grp1_perm, unsigned int grp2_perm); + +/* + * Free a Secure Memory pages + * + * @sm_page_descriptor Secure Memory page + */ +enum caam_status +caam_sm_free(const struct caam_sm_page_desc *sm_page_descriptor); + +#else +static inline enum caam_status caam_sm_init(struct caam_jrcfg *jrcfg __unused) +{ + return CAAM_NO_ERROR; +} +#endif /* CFG_NXP_CAAM_SM_DRV */ +#endif /* __CAAM_SM_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..7e1bc64 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/include/caam_trace.h @@ -0,0 +1,357 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2019-2021, 2023 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 */ +#define DBG_TRACE_SM BIT32(16) /* Secure Memory trace */ +#define DBG_TRACE_KEY BIT32(17) /* KEY 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 { \ + DSA_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 + +/* KEY */ +#if CAAM_DBG_TRACE(KEY) +#define KEY_TRACE DRV_TRACE +#if CAAM_DBG_DESC(KEY) +#define KEY_DUMPDESC(desc) \ + do { \ + KEY_TRACE("KEY Descriptor"); \ + DRV_DUMPDESC(desc); \ + } while (0) +#else +#define KEY_DUMPDESC(desc) +#endif +#if CAAM_DBG_BUF(KEY) +#define KEY_DUMPBUF DRV_DUMPBUF +#else +#define KEY_DUMPBUF(...) +#endif +#else +#define KEY_TRACE(...) do { } while (0) +#define KEY_DUMPDESC(desc) do { } while (0) +#define KEY_DUMPBUF(...) do { } while (0) +#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 + +/* Secure Memory */ +#if CAAM_DBG_TRACE(SM) +#define SM_TRACE DRV_TRACE +#else +#define SM_TRACE(...) +#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..886de0e --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/include/caam_utils_status.h @@ -0,0 +1,28 @@ +/* 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 +#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..6447f21 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/mp/caam_mp.c @@ -0,0 +1,408 @@ +// 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) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + 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); + } + +out: + 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..4906dfe --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/sub.mk @@ -0,0 +1,17 @@ +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 +srcs-$(CFG_NXP_CAAM_SM_DRV) += caam_sm.c +srcs-y += caam_key.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-y += 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..424757c --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/utils/utils_dmaobj.c @@ -0,0 +1,1415 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2020-2021, 2023 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 err; + } + + obj->orig.paddr = virt_to_phys((void *)data); + if (!obj->orig.paddr) { + DMAOBJ_TRACE("Object virtual address error"); + ret = TEE_ERROR_BAD_PARAMETERS; + goto err; + } + + 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) + goto err; + + ret = check_buffer_boundary(obj, &obj->orig, obj->orig.length); + + goto out; +err: + caam_dmaobj_free(obj); +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) + goto err; + + ret = caam_dmaobj_prepare(obj, NULL, length); + if (ret) + goto err; + + ret = caam_dmaobj_sgtbuf_build(obj, &size_done, 0, length); + if (ret) + goto err; + + if (size_done != length) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto err; + } + + return TEE_SUCCESS; +err: + caam_dmaobj_free(obj); + return ret; +} + +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 err; + + 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 err; + } + + 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 err; + } + + 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 err; + } + + /* 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; + goto out; + +err: + caam_dmaobj_free(obj); +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]; + + 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->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->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..2414517 --- /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(private_key->p); + 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..7b559a6 --- /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 = calloc(1, 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..b248f99 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt.h @@ -0,0 +1,90 @@ +/* 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_X25519, /* Asymmetric X25519 driver */ + CRYPTO_X448, /* Asymmetric X448 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..2a009c9 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_acipher.h @@ -0,0 +1,273 @@ +/* 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_bits); + /* 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); +} + +/* + * Crypto Library Montgomery driver operations + */ + +struct drvcrypt_montgomery { + /* Allocates the Montgomery key pair */ + TEE_Result (*alloc_keypair)(struct montgomery_keypair *key, + size_t size_bits); + /* Generates the Montgomery key pair */ + TEE_Result (*gen_keypair)(struct montgomery_keypair *key, + size_t key_size); + /* Montgomery Shared Secret */ + TEE_Result (*shared_secret)(struct drvcrypt_secret_data *sdata); +}; + +/* + * Register a X25519 processing driver in the crypto API + * + * @ops - Driver operations in the HW layer + */ +static inline TEE_Result drvcrypt_register_x25519(struct drvcrypt_montgomery + *ops) +{ + return drvcrypt_register(CRYPTO_X25519, (void *)ops); +} + +/* + * Register a X448 processing driver in the crypto API + * + * @ops - Driver operations in the HW layer + */ +static inline TEE_Result drvcrypt_register_x448(struct drvcrypt_montgomery *ops) +{ + return drvcrypt_register(CRYPTO_X448, (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/hisilicon/hisi_qm.c b/optee/optee_os/core/drivers/crypto/hisilicon/hisi_qm.c new file mode 100644 index 0000000..a7f1bf3 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/hisilicon/hisi_qm.c @@ -0,0 +1,898 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2022-2023 HiSilicon Limited. + * Kunpeng hardware accelerator queue management module. + */ +#include "hisi_qm.h" + +#define QM_FVT_CFG_RDY_BIT 0x1 +/* Doorbell */ +#define QM_DOORBELL_SQ_CQ_BASE 0x1000 +#define QM_DB_CMD_SHIFT 12 +#define QM_DB_RAND_DATA_SHIFT 16 +#define QM_DB_INDEX_SHIFT 32 +#define QM_DB_PRIORITY_SHIFT 48 +#define QM_DB_RAND_DATA 0x5a +#define QM_DOORBELL_CMD_SQ 0 +#define QM_DOORBELL_CMD_CQ 1 +/* Mailbox */ +#define QM_MAILBOX_BASE 0x300 +#define QM_MAILBOX_DATA_ADDR_L 0x304 +#define QM_MAILBOX_DATA_ADDR_H 0x308 +#define QM_MB_BUSY_SHIFT 13 +#define QM_MB_BUSY_BIT BIT32(QM_MB_BUSY_SHIFT) +#define QM_MB_OP_SHIFT 14 +#define QM_MB_OP_WR 0 +#define QM_MB_OP_RD 1 +#define QM_MB_STATUS_MASK GENMASK_32(12, 9) +#define QM_MB_WAIT_READY_CNT 10 +#define QM_MB_WAIT_MAX_CNT 21000 +#define QM_MB_WAIT_PERIOD 200 +/* XQC_VFT */ +#define QM_VFT_CFG_OP_ENABLE 0x100054 +#define QM_VFT_CFG_OP_WR 0x100058 +#define QM_VFT_CFG_TYPE 0x10005c +#define QM_VFT_CFG_ADDRESS 0x100060 +#define QM_VFT_CFG_DATA_L 0x100064 +#define QM_VFT_CFG_DATA_H 0x100068 +#define QM_VFT_CFG_RDY 0x10006c +#define QM_SQC_VFT 0 +#define QM_CQC_VFT 1 +#define QM_SQC_VFT_START_SQN_SHIFT 28 +#define QM_SQC_VFT_VALID BIT64(44) +#define QM_SQC_VFT_SQ_NUM_SHIFT 45 +#define QM_CQC_VFT_VALID BIT(28) +#define QM_VFT_WRITE 0 +#define QM_VFT_READ 1 +#define QM_SQC_VFT_BASE_MASK 0x3ff +#define QM_SQC_VFT_NUM_MASK 0x3ff +/* QM INIT */ +#define QM_MEM_START_INIT 0x100040 +#define QM_MEM_INIT_DONE 0x100044 +#define QM_VF_AEQ_INT_MASK 0x4 +#define QM_VF_AEQ_INT_MASK_EN 0x1 +#define QM_VF_EQ_INT_MASK 0xc +#define QM_VF_EQ_INT_MASK_EN 0x1 +#define QM_ARUSER_M_CFG_1 0x100088 +#define QM_ARUSER_M_CFG_ENABLE 0x100090 +#define QM_AWUSER_M_CFG_1 0x100098 +#define QM_AWUSER_M_CFG_ENABLE 0x1000a0 +#define QM_AXUSER_CFG 0x40001070 +#define AXUSER_M_CFG_ENABLE 0x7ffffc +#define QM_AXI_M_CFG 0x1000ac +#define AXI_M_CFG 0xffff +#define QM_PEH_AXUSER_CFG 0x1000cc +#define PEH_AXUSER_CFG 0x400801 +#define QM_CACHE_CTL 0x100050 +#define QM_CACHE_CFG 0x4893 +#define QM_CACHE_WB_START 0x204 +#define QM_CACHE_WB_DONE 0x208 +#define QM_PM_CTRL0 0x100148 +#define QM_IDLE_DISABLE BIT(9) +#define QM_DB_TIMEOUT_CFG 0x100074 +#define QM_DB_TIMEOUT_SET 0x1fffff +/* XQC shift */ +#define QM_SQ_SQE_SIZE_SHIFT 12 +#define QM_SQ_ORDER_SHIFT 4 +#define QM_SQ_TYPE_SHIFT 8 +#define QM_CQE_SIZE 4 +#define QM_CQ_CQE_SIZE_SHIFT 12 +/* CQE */ +#define QM_CQE_PHASE(cqe) (((cqe)->w7) & QM_FVT_CFG_RDY_BIT) + +enum qm_mailbox_common_cmd { + QM_MB_CMD_SQC = 0x0, + QM_MB_CMD_CQC, + QM_MB_CMD_EQC, + QM_MB_CMD_AEQC, + QM_MB_CMD_SQC_BT, + QM_MB_CMD_CQC_BT, + QM_MB_CMD_SQC_VFT, +}; + +enum qm_mailbox_cmd_v3 { + QM_MB_CM_CLOSE_QM = 0x7, + QM_MB_CMD_CLOSE_QP, + QM_MB_CMD_FLUSH_QM, + QM_MB_CMD_FLUSH_QP, + QM_MB_CMD_SRC = 0xc, + QM_MB_CMD_DST, + QM_MB_CMD_STOP_QM, +}; + +struct qm_mailbox { + union { + struct { + uint16_t w0; + uint16_t queue; + uint32_t base_l; + uint32_t base_h; + uint32_t token; + }; + uint64_t x[2]; + }; +}; + +struct qm_dfx_registers { + const char *reg_name; + uint32_t reg_offset; +}; + +static const struct qm_dfx_registers qm_dfx_regs[] = { + { .reg_name = "QM_ECC_1BIT_CNT ", .reg_offset = 0x104000 }, + { .reg_name = "QM_ECC_MBIT_CNT ", .reg_offset = 0x104008 }, + { .reg_name = "QM_DFX_MB_CNT ", .reg_offset = 0x104018 }, + { .reg_name = "QM_DFX_DB_CNT ", .reg_offset = 0x104028 }, + { .reg_name = "QM_DFX_SQE_CNT ", .reg_offset = 0x104038 }, + { .reg_name = "QM_DFX_CQE_CNT ", .reg_offset = 0x104048 }, + { .reg_name = "QM_DFX_SEND_SQE_TO_ACC_CNT", .reg_offset = 0x104050 }, + { .reg_name = "QM_DFX_WB_SQE_FROM_ACC_CNT", .reg_offset = 0x104058 }, + { .reg_name = "QM_DFX_ACC_FINISH_CNT ", .reg_offset = 0x104060 }, + { .reg_name = "QM_DFX_CQE_ERR_CNT ", .reg_offset = 0x1040b4 }, + { } +}; + +void hisi_qm_get_version(struct hisi_qm *qm) +{ + qm->version = io_read32(qm->io_base + HISI_QM_REVISON_ID_BASE) & + HISI_QM_REVISON_ID_MASK; +} + +static void qm_db(struct hisi_qm *qm, uint16_t qn, uint8_t cmd, uint16_t index, + uint8_t priority) +{ + uint64_t doorbell = 0; + + doorbell = qn | SHIFT_U64(cmd, QM_DB_CMD_SHIFT) | + SHIFT_U64(QM_DB_RAND_DATA, QM_DB_RAND_DATA_SHIFT) | + SHIFT_U64(index, QM_DB_INDEX_SHIFT) | + SHIFT_U64(priority, QM_DB_PRIORITY_SHIFT); + + io_write64(qm->io_base + QM_DOORBELL_SQ_CQ_BASE, doorbell); +} + +static void qm_mb_write(struct hisi_qm *qm, struct qm_mailbox *mb) +{ + vaddr_t dst = qm->io_base + QM_MAILBOX_BASE; + + write_64bit_pair(dst, mb->x[1], mb->x[0]); + dsb_osh(); +} + +static void qm_mb_read(struct hisi_qm *qm, struct qm_mailbox *mb) +{ + vaddr_t mb_base = qm->io_base + QM_MAILBOX_BASE; + + read_64bit_pair(mb_base, mb->x + 1, mb->x); + dsb_osh(); +} + +static enum hisi_drv_status qm_wait_mb_ready(struct hisi_qm *qm) +{ + struct qm_mailbox mb = { }; + uint32_t timeout = 0; + + timeout = timeout_init_us(QM_MB_WAIT_PERIOD * QM_MB_WAIT_READY_CNT); + while (!timeout_elapsed(timeout)) { + /* 128 bits should be read from hardware at one time*/ + qm_mb_read(qm, &mb); + if (!(mb.w0 & QM_MB_BUSY_BIT)) + return HISI_QM_DRVCRYPT_NO_ERR; + } + + EMSG("QM mailbox is busy to start!"); + + return HISI_QM_DRVCRYPT_EBUSY; +} + +static enum hisi_drv_status qm_wait_mb_finish(struct hisi_qm *qm, + struct qm_mailbox *mb) +{ + uint32_t timeout = 0; + + timeout = timeout_init_us(QM_MB_WAIT_PERIOD * QM_MB_WAIT_MAX_CNT); + while (!timeout_elapsed(timeout)) { + qm_mb_read(qm, mb); + if (!(mb->w0 & QM_MB_BUSY_BIT)) { + if (mb->w0 & QM_MB_STATUS_MASK) { + EMSG("QM mailbox operation failed!"); + return HISI_QM_DRVCRYPT_EIO; + } else { + return HISI_QM_DRVCRYPT_NO_ERR; + } + } + } + + return HISI_QM_DRVCRYPT_ETMOUT; +} + +static void qm_mb_init(struct qm_mailbox *mb, uint8_t cmd, uint64_t base, + uint16_t qnum, uint8_t op) +{ + mb->w0 = cmd | SHIFT_U32(op, QM_MB_OP_SHIFT) | QM_MB_BUSY_BIT; + mb->queue = qnum; + reg_pair_from_64(base, &mb->base_h, &mb->base_l); + mb->token = 0; +} + +static enum hisi_drv_status qm_mb_nolock(struct hisi_qm *qm, + struct qm_mailbox *mb) +{ + if (qm_wait_mb_ready(qm)) + return HISI_QM_DRVCRYPT_EBUSY; + + qm_mb_write(qm, mb); + + return qm_wait_mb_finish(qm, mb); +} + +static enum hisi_drv_status hisi_qm_mb_write(struct hisi_qm *qm, uint8_t cmd, + uintptr_t dma_addr, uint16_t qnum) +{ + enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; + struct qm_mailbox mb = { }; + + qm_mb_init(&mb, cmd, dma_addr, qnum, QM_MB_OP_WR); + mutex_lock(&qm->mailbox_lock); + ret = qm_mb_nolock(qm, &mb); + mutex_unlock(&qm->mailbox_lock); + + return ret; +} + +static enum hisi_drv_status hisi_qm_mb_read(struct hisi_qm *qm, uint64_t *base, + uint8_t cmd, uint16_t qnum) +{ + enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; + struct qm_mailbox mb = { }; + + qm_mb_init(&mb, cmd, 0, qnum, QM_MB_OP_RD); + mutex_lock(&qm->mailbox_lock); + ret = qm_mb_nolock(qm, &mb); + mutex_unlock(&qm->mailbox_lock); + if (ret) + return ret; + + reg_pair_from_64(*base, &mb.base_h, &mb.base_l); + + return HISI_QM_DRVCRYPT_NO_ERR; +} + +static void qm_cfg_vft_data(struct hisi_qm *qm, uint8_t vft_type, + uint32_t base, uint32_t number) +{ + uint32_t data_h = 0; + uint32_t data_l = 0; + uint64_t data = 0; + + switch (vft_type) { + case QM_SQC_VFT: + data = SHIFT_U64(base, QM_SQC_VFT_START_SQN_SHIFT) | + QM_SQC_VFT_VALID | + SHIFT_U64((number - 1), QM_SQC_VFT_SQ_NUM_SHIFT); + break; + case QM_CQC_VFT: + data = QM_CQC_VFT_VALID; + break; + default: + panic("Invalid vft type"); + } + + reg_pair_from_64(data, &data_h, &data_l); + io_write32(qm->io_base + QM_VFT_CFG_DATA_L, data_l); + io_write32(qm->io_base + QM_VFT_CFG_DATA_H, data_h); +} + +static enum hisi_drv_status qm_set_vft_common(struct hisi_qm *qm, + uint8_t vft_type, + uint32_t function, + uint32_t base, + uint32_t num) +{ + uint32_t val = 0; + + if (IO_READ32_POLL_TIMEOUT(qm->io_base + QM_VFT_CFG_RDY, val, + val & QM_FVT_CFG_RDY_BIT, POLL_PERIOD, + POLL_TIMEOUT)) { + EMSG("QM VFT is not ready"); + return HISI_QM_DRVCRYPT_EBUSY; + } + + io_write32(qm->io_base + QM_VFT_CFG_OP_WR, QM_VFT_WRITE); + io_write32(qm->io_base + QM_VFT_CFG_TYPE, vft_type); + io_write32(qm->io_base + QM_VFT_CFG_ADDRESS, function); + qm_cfg_vft_data(qm, vft_type, base, num); + io_write32(qm->io_base + QM_VFT_CFG_RDY, 0x0); + io_write32(qm->io_base + QM_VFT_CFG_OP_ENABLE, QM_FVT_CFG_RDY_BIT); + + if (IO_READ32_POLL_TIMEOUT(qm->io_base + QM_VFT_CFG_RDY, val, + val & QM_FVT_CFG_RDY_BIT, POLL_PERIOD, + POLL_TIMEOUT)) { + EMSG("QM VFT is not ready"); + return HISI_QM_DRVCRYPT_EBUSY; + } + + return HISI_QM_DRVCRYPT_NO_ERR; +} + +static enum hisi_drv_status qm_set_xqc_vft(struct hisi_qm *qm, + uint32_t function, + uint32_t base, uint32_t num) +{ + enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; + int i = 0; + + for (i = QM_SQC_VFT; i <= QM_CQC_VFT; i++) { + ret = qm_set_vft_common(qm, i, function, base, num); + if (ret) { + EMSG("QM set type %d fail", i); + return ret; + } + } + + return HISI_QM_DRVCRYPT_NO_ERR; +} + +static enum hisi_drv_status qm_get_vft(struct hisi_qm *qm, uint32_t *base, + uint32_t *num) +{ + enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; + uint64_t sqc_vft = 0; + + ret = hisi_qm_mb_read(qm, &sqc_vft, QM_MB_CMD_SQC_VFT, 0); + if (ret) + return ret; + + *base = (sqc_vft >> QM_SQC_VFT_START_SQN_SHIFT) & QM_SQC_VFT_BASE_MASK; + *num = ((sqc_vft >> QM_SQC_VFT_SQ_NUM_SHIFT) & QM_SQC_VFT_NUM_MASK) + 1; + + return HISI_QM_DRVCRYPT_NO_ERR; +} + +static void qp_free(struct hisi_qm *qm, uint32_t id) +{ + struct hisi_qp *qp = &qm->qp_array[id]; + + free(qp->sqe); + free(qp->cqe); +} + +static enum hisi_drv_status qp_alloc(struct hisi_qm *qm, uint32_t id) +{ + size_t sq_size = qm->sqe_size * HISI_QM_Q_DEPTH; + size_t cq_size = sizeof(struct qm_cqe) * HISI_QM_Q_DEPTH; + struct hisi_qp *qp = &qm->qp_array[id]; + enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; + + qp->sqe = memalign(HISI_QM_ALIGN128, sq_size); + if (!qp->sqe) { + EMSG("Fail to malloc sq[%"PRIu32"]", id); + return HISI_QM_DRVCRYPT_ENOMEM; + } + qp->sqe_dma = virt_to_phys(qp->sqe); + qp->cqe = memalign(HISI_QM_ALIGN32, cq_size); + if (!qp->cqe) { + EMSG("Fail to malloc cq[%"PRIu32"]", id); + ret = HISI_QM_DRVCRYPT_ENOMEM; + goto free_sqe; + } + qp->cqe_dma = virt_to_phys(qp->cqe); + + qp->qp_id = id; + qp->qm = qm; + return HISI_QM_DRVCRYPT_NO_ERR; + +free_sqe: + free(qp->sqe); + return ret; +} + +static void hisi_qm_free_xqc(struct qm_xqc *xqc) +{ + free(xqc->cqc); + free(xqc->sqc); +} + +static void qm_free(struct hisi_qm *qm) +{ + unsigned int i = 0; + + for (i = 0; i < qm->qp_num; i++) + qp_free(qm, i); + + free(qm->qp_array); + hisi_qm_free_xqc(&qm->xqc); + hisi_qm_free_xqc(&qm->cfg_xqc); +} + +static enum hisi_drv_status hisi_qm_alloc_xqc(struct qm_xqc *xqc, + uint32_t qp_num) +{ + enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; + size_t sqc_size = 0; + size_t cqc_size = 0; + + sqc_size = sizeof(struct qm_sqc) * qp_num; + cqc_size = sizeof(struct qm_cqc) * qp_num; + + xqc->sqc = memalign(HISI_QM_ALIGN32, sqc_size); + if (!xqc->sqc) { + EMSG("Fail to malloc sqc"); + return HISI_QM_DRVCRYPT_ENOMEM; + } + memset(xqc->sqc, 0, sqc_size); + xqc->sqc_dma = virt_to_phys(xqc->sqc); + + xqc->cqc = memalign(HISI_QM_ALIGN32, cqc_size); + if (!xqc->cqc) { + EMSG("Fail to malloc cqc"); + ret = HISI_QM_DRVCRYPT_ENOMEM; + goto free_sqc; + } + memset(xqc->cqc, 0, cqc_size); + xqc->cqc_dma = virt_to_phys(xqc->cqc); + + return HISI_QM_DRVCRYPT_NO_ERR; + + free(xqc->cqc); +free_sqc: + free(xqc->sqc); + return ret; +} + +static enum hisi_drv_status qm_alloc(struct hisi_qm *qm) +{ + enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; + int32_t j; + uint32_t i; + + ret = hisi_qm_alloc_xqc(&qm->xqc, qm->qp_num); + if (ret) + return ret; + + ret = hisi_qm_alloc_xqc(&qm->cfg_xqc, 1); + if (ret) + goto free_xqc; + + qm->qp_array = calloc(qm->qp_num, sizeof(struct hisi_qp)); + if (!qm->qp_array) { + EMSG("Fail to malloc qp_array"); + ret = HISI_QM_DRVCRYPT_ENOMEM; + goto free_cfg_xqc; + } + + for (i = 0; i < qm->qp_num; i++) { + ret = qp_alloc(qm, i); + if (ret) + goto free_qp_mem; + } + + return HISI_QM_DRVCRYPT_NO_ERR; + +free_qp_mem: + for (j = (int)i - 1; j >= 0; j--) + qp_free(qm, j); + free(qm->qp_array); +free_cfg_xqc: + hisi_qm_free_xqc(&qm->cfg_xqc); +free_xqc: + hisi_qm_free_xqc(&qm->xqc); + return ret; +} + +enum hisi_drv_status hisi_qm_init(struct hisi_qm *qm) +{ + enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; + + if (qm->fun_type == HISI_QM_HW_VF) { + ret = qm_get_vft(qm, &qm->qp_base, &qm->qp_num); + if (ret) { + EMSG("Fail to get function vft config"); + return ret; + } + } + + if (!qm->qp_num || !qm->sqe_size) { + EMSG("Invalid QM parameters"); + return HISI_QM_DRVCRYPT_EINVAL; + } + + ret = qm_alloc(qm); + if (ret) + return ret; + + qm->qp_in_used = 0; + qm->qp_idx = 0; + mutex_init(&qm->qp_lock); + mutex_init(&qm->mailbox_lock); + + return HISI_QM_DRVCRYPT_NO_ERR; +} + +static void qm_cache_writeback(struct hisi_qm *qm) +{ + uint32_t val = 0; + + io_write32(qm->io_base + QM_CACHE_WB_START, QM_FVT_CFG_RDY_BIT); + + if (IO_READ32_POLL_TIMEOUT(qm->io_base + QM_CACHE_WB_DONE, val, + val & QM_FVT_CFG_RDY_BIT, POLL_PERIOD, + POLL_TIMEOUT)) + panic("QM writeback sqc cache fail"); +} + +void hisi_qm_uninit(struct hisi_qm *qm) +{ + qm_cache_writeback(qm); + qm_free(qm); + mutex_destroy(&qm->qp_lock); + mutex_destroy(&qm->mailbox_lock); +} + +static enum hisi_drv_status qm_hw_mem_reset(struct hisi_qm *qm) +{ + uint32_t val = 0; + + io_write32(qm->io_base + QM_MEM_START_INIT, QM_FVT_CFG_RDY_BIT); + + if (IO_READ32_POLL_TIMEOUT(qm->io_base + QM_MEM_INIT_DONE, val, + val & QM_FVT_CFG_RDY_BIT, POLL_PERIOD, + POLL_TIMEOUT)) + return HISI_QM_DRVCRYPT_EBUSY; + + return HISI_QM_DRVCRYPT_NO_ERR; +} + +static enum hisi_drv_status qm_func_vft_cfg(struct hisi_qm *qm) +{ + enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; + uint32_t q_base = qm->qp_num; + uint32_t act_q_num = 0; + unsigned int i = 0; + unsigned int j = 0; + + if (!qm->vfs_num) + return HISI_QM_DRVCRYPT_NO_ERR; + + if (qm->vfs_num > HISI_QM_MAX_VFS_NUM) { + EMSG("Invalid QM vfs_num"); + return HISI_QM_DRVCRYPT_EINVAL; + } + + for (i = 1; i <= qm->vfs_num; i++) { + act_q_num = HISI_QM_VF_Q_NUM; + ret = qm_set_xqc_vft(qm, i, q_base, act_q_num); + if (ret) { + for (j = 1; j < i; j++) + (void)qm_set_xqc_vft(qm, j, 0, 0); + return ret; + } + q_base += act_q_num; + } + + return HISI_QM_DRVCRYPT_NO_ERR; +} + +enum hisi_drv_status hisi_qm_start(struct hisi_qm *qm) +{ + enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; + + if (qm->fun_type == HISI_QM_HW_PF) { + ret = qm_hw_mem_reset(qm); + if (ret) { + EMSG("Fail to reset QM hardware mem"); + return ret; + } + + ret = qm_set_xqc_vft(qm, 0, qm->qp_base, qm->qp_num); + if (ret) { + EMSG("Fail to set PF xqc_vft"); + return ret; + } + + ret = qm_func_vft_cfg(qm); + if (ret) { + EMSG("Fail to set VF xqc_vft"); + return ret; + } + } + + ret = hisi_qm_mb_write(qm, QM_MB_CMD_SQC_BT, qm->xqc.sqc_dma, 0); + if (ret) { + EMSG("Fail to set sqc_bt"); + return ret; + } + + ret = hisi_qm_mb_write(qm, QM_MB_CMD_CQC_BT, qm->xqc.cqc_dma, 0); + if (ret) { + EMSG("Fail to set cqc_bt"); + return ret; + } + + /* Security mode does not support msi */ + io_write32(qm->io_base + QM_VF_AEQ_INT_MASK, QM_VF_AEQ_INT_MASK_EN); + io_write32(qm->io_base + QM_VF_EQ_INT_MASK, QM_VF_EQ_INT_MASK_EN); + + return HISI_QM_DRVCRYPT_NO_ERR; +} + +static void qm_disable_clock_gate(struct hisi_qm *qm) + +{ + if (qm->version == HISI_QM_HW_V2) + return; + + io_setbits32(qm->io_base + QM_PM_CTRL0, QM_IDLE_DISABLE); +} + +void hisi_qm_dev_init(struct hisi_qm *qm) +{ + if (qm->fun_type == HISI_QM_HW_VF) + return; + + qm_disable_clock_gate(qm); + + /* QM user domain */ + io_write32(qm->io_base + QM_ARUSER_M_CFG_1, QM_AXUSER_CFG); + io_write32(qm->io_base + QM_ARUSER_M_CFG_ENABLE, AXUSER_M_CFG_ENABLE); + io_write32(qm->io_base + QM_AWUSER_M_CFG_1, QM_AXUSER_CFG); + io_write32(qm->io_base + QM_AWUSER_M_CFG_ENABLE, AXUSER_M_CFG_ENABLE); + /* QM cache */ + io_write32(qm->io_base + QM_AXI_M_CFG, AXI_M_CFG); + + if (qm->version == HISI_QM_HW_V2) { + /* Disable FLR triggered by BME(bus master enable) */ + io_write32(qm->io_base + QM_PEH_AXUSER_CFG, PEH_AXUSER_CFG); + /* Set sec sqc and cqc cache wb threshold 4 */ + io_write32(qm->io_base + QM_CACHE_CTL, QM_CACHE_CFG); + } + /* Disable QM ras */ + io_write32(qm->io_base + HISI_QM_ABNML_INT_MASK, + HISI_QM_ABNML_INT_MASK_CFG); + /* Set doorbell timeout to QM_DB_TIMEOUT_SET ns */ + io_write32(qm->io_base + QM_DB_TIMEOUT_CFG, QM_DB_TIMEOUT_SET); +} + +static enum hisi_drv_status qm_sqc_cfg(struct hisi_qp *qp) +{ + enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; + struct hisi_qm *qm = qp->qm; + struct qm_sqc *sqc = qm->cfg_xqc.sqc; + struct qm_mailbox mb = { }; + + mutex_lock(&qm->mailbox_lock); + memset(sqc, 0, sizeof(struct qm_sqc)); + reg_pair_from_64(qp->sqe_dma, &sqc->base_h, &sqc->base_l); + sqc->dw3 = (HISI_QM_Q_DEPTH - 1) | + SHIFT_U32(qm->sqe_log2_size, QM_SQ_SQE_SIZE_SHIFT); + sqc->rand_data = QM_DB_RAND_DATA; + sqc->cq_num = qp->qp_id; + sqc->w13 = BIT32(QM_SQ_ORDER_SHIFT) | + SHIFT_U32(qp->sq_type, QM_SQ_TYPE_SHIFT); + + qm_mb_init(&mb, QM_MB_CMD_SQC, qm->cfg_xqc.sqc_dma, qp->qp_id, + QM_MB_OP_WR); + ret = qm_mb_nolock(qm, &mb); + mutex_unlock(&qm->mailbox_lock); + + return ret; +} + +static enum hisi_drv_status qm_cqc_cfg(struct hisi_qp *qp) +{ + enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; + struct hisi_qm *qm = qp->qm; + struct qm_cqc *cqc = qm->cfg_xqc.cqc; + struct qm_mailbox mb = { }; + + mutex_lock(&qm->mailbox_lock); + memset(cqc, 0, sizeof(struct qm_cqc)); + reg_pair_from_64(qp->cqe_dma, &cqc->base_h, &cqc->base_l); + cqc->dw3 = (HISI_QM_Q_DEPTH - 1) | + SHIFT_U32(QM_CQE_SIZE, QM_CQ_CQE_SIZE_SHIFT); + cqc->rand_data = QM_DB_RAND_DATA; + cqc->dw6 = PHASE_DEFAULT_VAL; + + qm_mb_init(&mb, QM_MB_CMD_CQC, qm->cfg_xqc.cqc_dma, qp->qp_id, + QM_MB_OP_WR); + ret = qm_mb_nolock(qm, &mb); + mutex_unlock(&qm->mailbox_lock); + + return ret; +} + +struct hisi_qp *hisi_qm_create_qp(struct hisi_qm *qm, uint8_t sq_type) +{ + struct hisi_qp *qp = NULL; + int cur_idx = 0; + uint32_t i = 0; + + mutex_lock(&qm->qp_lock); + if (qm->qp_in_used == qm->qp_num) { + EMSG("All %"PRIu32" queues of QM are busy", qm->qp_num); + goto err_proc; + } + + for (i = 0; i < qm->qp_num; i++) { + cur_idx = (qm->qp_idx + i) % qm->qp_num; + if (!qm->qp_array[cur_idx].used) { + qm->qp_array[cur_idx].used = true; + qm->qp_idx = cur_idx + 1; + break; + } + } + + qp = qm->qp_array + cur_idx; + memset(qp->cqe, 0, sizeof(struct qm_cqe) * HISI_QM_Q_DEPTH); + qp->sq_type = sq_type; + qp->sq_tail = 0; + qp->cq_head = 0; + qp->cqc_phase = true; + + if (qm_sqc_cfg(qp)) { + EMSG("Fail to set qp[%"PRIu32"] sqc", qp->qp_id); + goto err_qp_release; + } + + if (qm_cqc_cfg(qp)) { + EMSG("Fail to set qp[%"PRIu32"] cqc", qp->qp_id); + goto err_qp_release; + } + + qm->qp_in_used++; + mutex_unlock(&qm->qp_lock); + return qp; + +err_qp_release: + qp->used = false; +err_proc: + qp->sq_type = 0; + qp->cqc_phase = false; + mutex_unlock(&qm->qp_lock); + return NULL; +} + +void hisi_qm_release_qp(struct hisi_qp *qp) +{ + struct hisi_qm *qm = NULL; + + if (!qp) { + EMSG("QP is NULL"); + return; + } + + qm = qp->qm; + mutex_lock(&qm->qp_lock); + qm->qp_in_used--; + qp->used = false; + mutex_unlock(&qm->qp_lock); +} + +static void qm_sq_tail_update(struct hisi_qp *qp) +{ + if (qp->sq_tail == HISI_QM_Q_DEPTH - 1) + qp->sq_tail = 0; + else + qp->sq_tail++; +} + +/* + * One task thread will just bind to one hardware queue, and + * hardware does not support msi. So we have no lock here. + */ +enum hisi_drv_status hisi_qp_send(struct hisi_qp *qp, void *msg) +{ + enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; + struct hisi_qm *qm = NULL; + void *sqe = NULL; + + if (!qp) { + EMSG("QP is NULL"); + return HISI_QM_DRVCRYPT_EINVAL; + } + + qm = qp->qm; + ret = qm->dev_status_check(qm); + if (ret) + return ret; + + sqe = (void *)((vaddr_t)qp->sqe + qm->sqe_size * qp->sq_tail); + memset(sqe, 0, qm->sqe_size); + + ret = qp->fill_sqe(sqe, msg); + if (ret) { + EMSG("Fail to fill sqe"); + return ret; + } + + qm_sq_tail_update(qp); + + dsb(); + qm_db(qm, qp->qp_id, QM_DOORBELL_CMD_SQ, qp->sq_tail, 0); + + return HISI_QM_DRVCRYPT_NO_ERR; +} + +static void qm_cq_head_update(struct hisi_qp *qp) +{ + if (qp->cq_head == HISI_QM_Q_DEPTH - 1) { + qp->cqc_phase = !qp->cqc_phase; + qp->cq_head = 0; + } else { + qp->cq_head++; + } +} + +static enum hisi_drv_status hisi_qp_recv(struct hisi_qp *qp, void *msg) +{ + enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; + struct hisi_qm *qm = qp->qm; + struct qm_cqe *cqe = NULL; + void *sqe = NULL; + + ret = qm->dev_status_check(qm); + if (ret) + return ret; + + cqe = qp->cqe + qp->cq_head; + if (QM_CQE_PHASE(cqe) == qp->cqc_phase) { + dsb_osh(); + sqe = (void *)((vaddr_t)qp->sqe + qm->sqe_size * cqe->sq_head); + ret = qp->parse_sqe(sqe, msg); + qm_cq_head_update(qp); + qm_db(qm, qp->qp_id, QM_DOORBELL_CMD_CQ, qp->cq_head, 0); + if (ret) { + EMSG("Fail to parse sqe"); + return ret; + } + } else { + return HISI_QM_DRVCRYPT_NO_ERR; + } + + return HISI_QM_DRVCRYPT_RECV_DONE; +} + +static void qm_dfx_dump(struct hisi_qm *qm) +{ + const struct qm_dfx_registers *regs = qm_dfx_regs; + __maybe_unused uint32_t val = 0; + + if (qm->fun_type == HISI_QM_HW_VF) + return; + + while (regs->reg_name) { + val = io_read32(qm->io_base + regs->reg_offset); + EMSG("%s= 0x%" PRIx32, regs->reg_name, val); + regs++; + } +} + +enum hisi_drv_status hisi_qp_recv_sync(struct hisi_qp *qp, void *msg) +{ + enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; + uint32_t timeout = 0; + + if (!qp || !qp->qm || !msg) { + EMSG("Invalid qp recv sync parameters"); + return HISI_QM_DRVCRYPT_EINVAL; + } + + timeout = timeout_init_us(QM_SINGLE_WAIT_TIME * + HISI_QM_RECV_SYNC_TIMEOUT); + while (!timeout_elapsed(timeout)) { + ret = hisi_qp_recv(qp, msg); + if (ret) { + if (ret != HISI_QM_DRVCRYPT_RECV_DONE) { + EMSG("QM recv task error"); + qm_dfx_dump(qp->qm); + return ret; + } else { + return HISI_QM_DRVCRYPT_NO_ERR; + } + } + } + + EMSG("QM recv task timeout"); + qm_dfx_dump(qp->qm); + return HISI_QM_DRVCRYPT_ETMOUT; +} diff --git a/optee/optee_os/core/drivers/crypto/hisilicon/hpre_main.c b/optee/optee_os/core/drivers/crypto/hisilicon/hpre_main.c new file mode 100644 index 0000000..0ac9100 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/hisilicon/hpre_main.c @@ -0,0 +1,326 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2024 HiSilicon Limited. + * Kunpeng hardware accelerator HPRE module init. + */ +#include "hpre_main.h" + +/* base config */ +#define HPRE_COMMON_CNT_CLR_CE 0x301000 +#define HPRE_CFG_AXCACHE 0x301010 +#define HPRE_RDCHN_INI_CFG 0x301014 +#define HPRE_BD_ENDIAN 0x301020 +#define HPRE_ECC_BYPASS 0x301024 +#define HPRE_POISON_BYPASS 0x30102c +#define HPRE_BD_ARUSR_CFG 0x301030 +#define HPRE_BD_AWUSR_CFG 0x301034 +#define HPRE_TYPES_ENB 0x301038 +#define HPRE_DATA_RUSER_CFG 0x30103c +#define HPRE_DATA_WUSER_CFG 0x301040 +#define HPRE_HAC_INT_MASK 0x301400 +#define HPRE_RAS_ECC_1BIT_TH 0x30140c +#define HPRE_RAS_CE_ENB 0x301410 +#define HPRE_RAS_NFE_ENB 0x301414 +#define HPRE_RAS_FE_ENB 0x301418 +#define HPRE_HAC_INT_SRC 0x301600 +#define HPRE_RDCHN_INI_ST 0x301a00 +#define HPRE_OOO_SHUTDOWN_SEL 0x301a3c +#define HPRE_CORE_ENB 0x302004 +#define HPRE_CORE_INI_CFG 0x302020 +#define HPRE_CORE_INI_STATUS 0x302080 +/* clock gate */ +#define HPRE_CLKGATE_CTL 0x301a10 +#define HPRE_PEH_CFG_AUTO_GATE 0x301a2c +#define HPRE_CLUSTER_DYN_CTL 0x302010 +#define HPRE_CORE_SHB_CFG 0x302088 +#define HPRE_CORE_GATE_ENABLE GENMASK_32(31, 30) + +#define HPRE_AXCACHE_MASK 0xff +#define HPRE_HAC_INT_DISABLE 0x1ffffff +#define HPRE_RAS_CE_MASK 0x1 +#define HPRE_RAS_NFE_MASK 0x1fffffe +#define HPRE_RAS_FE_MASK 0 +#define HPRE_BD_LITTLE_ENDIAN 0 +#define HPRE_RSA_ENB BIT(0) +#define HPRE_ECC_ENB BIT(1) +#define HPRE_BD_ARUSR_MASK 0x2 +#define HPRE_BD_AWUSR_MASK 0x102 +#define HPRE_DATA_USR_MASK 0x32 +#define HPRE_CLUSTER_CORE_MASK GENMASK_32(9, 0) + +static SLIST_HEAD(, acc_device) hpre_list = SLIST_HEAD_INITIALIZER(hpre_list); + +struct hisi_qp *hpre_create_qp(uint8_t sq_type) +{ + struct acc_device *hpre_dev = NULL; + struct acc_device *cur_dev = NULL; + struct hisi_qm *qm = NULL; + uint32_t free_qp_num = 0; + uint32_t max_qp_num = 0; + + /* Find the HPRE device with the most remaining qp numbers */ + SLIST_FOREACH(cur_dev, &hpre_list, link) { + qm = &cur_dev->qm; + if (qm->fun_type == HISI_QM_HW_PF) + free_qp_num = HISI_QM_PF_Q_NUM - qm->qp_in_used; + else + free_qp_num = HISI_QM_VF_Q_NUM - qm->qp_in_used; + if (free_qp_num > max_qp_num) { + max_qp_num = free_qp_num; + hpre_dev = cur_dev; + } + } + + if (!hpre_dev) { + EMSG("No available hpre device"); + return NULL; + } + + return hisi_qm_create_qp(&hpre_dev->qm, sq_type); +} + +enum hisi_drv_status hpre_bin_from_crypto_bin(uint8_t *dst, const uint8_t *src, + uint32_t bsize, uint32_t dsize) +{ + if (!src || !dst || !dsize || !bsize) { + EMSG("parameter error"); + return HISI_QM_DRVCRYPT_EINVAL; + } + + if (bsize < dsize) { + EMSG("dsize is too long"); + return HISI_QM_DRVCRYPT_EINVAL; + } + + if (src == dst && bsize == dsize) + return HISI_QM_DRVCRYPT_NO_ERR; + + /* + * Copying non-zero data and padding with zeroes in high-bits + * (eg: 1 2 3 0 0 -> 0 0 1 2 3) + */ + memmove(dst + bsize - dsize, src, dsize); + memset(dst, 0, bsize - dsize); + + return HISI_QM_DRVCRYPT_NO_ERR; +} + +enum hisi_drv_status hpre_bin_to_crypto_bin(uint8_t *dst, const uint8_t *src, + uint32_t bsize, uint32_t dsize) +{ + if (!dst || !src || !bsize || !dsize) { + EMSG("parameter error"); + return HISI_QM_DRVCRYPT_EINVAL; + } + + if (bsize < dsize) { + EMSG("dsize is too long"); + return HISI_QM_DRVCRYPT_EINVAL; + } + + if (src == dst && bsize == dsize) + return HISI_QM_DRVCRYPT_NO_ERR; + /* + * Copying non-zero data and padding with zeroes in low-bits + * (eg: 0 0 1 2 3 -> 1 2 3 0 0) + */ + memmove(dst, src + bsize - dsize, dsize); + memset(dst + dsize, 0, bsize - dsize); + + return HISI_QM_DRVCRYPT_NO_ERR; +} + +static enum hisi_drv_status hpre_set_cluster(struct hisi_qm *qm) +{ + uint32_t val = 0; + + io_write32(qm->io_base + HPRE_CORE_ENB, HPRE_CLUSTER_CORE_MASK); + io_write32(qm->io_base + HPRE_CORE_INI_CFG, 0x1); + + if (IO_READ32_POLL_TIMEOUT(qm->io_base + HPRE_CORE_INI_STATUS, val, + (val & HPRE_CLUSTER_CORE_MASK) == + HPRE_CLUSTER_CORE_MASK, POLL_PERIOD, + POLL_TIMEOUT)) + return HISI_QM_DRVCRYPT_EBUSY; + return HISI_QM_DRVCRYPT_NO_ERR; +} + +static void hpre_disable_clock_gate(struct hisi_qm *qm) +{ + io_write32(qm->io_base + HPRE_CLKGATE_CTL, 0x0); + io_write32(qm->io_base + HPRE_PEH_CFG_AUTO_GATE, 0x0); + io_write32(qm->io_base + HPRE_CLUSTER_DYN_CTL, 0x0); + io_clrbits32(qm->io_base + HPRE_CORE_SHB_CFG, HPRE_CORE_GATE_ENABLE); +} + +static void hpre_enable_clock_gate(struct hisi_qm *qm) +{ + io_write32(qm->io_base + HPRE_CLKGATE_CTL, 0x1); + io_write32(qm->io_base + HPRE_PEH_CFG_AUTO_GATE, 0x1); + io_write32(qm->io_base + HPRE_CLUSTER_DYN_CTL, 0x1); + io_setbits32(qm->io_base + HPRE_CORE_SHB_CFG, HPRE_CORE_GATE_ENABLE); +} + +static TEE_Result hpre_engine_init(struct acc_device *hpre_dev) +{ + struct hisi_qm *qm = &hpre_dev->qm; + uint32_t val = 0; + int32_t ret = 0; + + if (qm->fun_type == HISI_QM_HW_VF) + return TEE_SUCCESS; + + hpre_disable_clock_gate(qm); + hisi_qm_dev_init(qm); + + io_write32(qm->io_base + HPRE_CFG_AXCACHE, HPRE_AXCACHE_MASK); + io_write32(qm->io_base + HPRE_BD_ENDIAN, HPRE_BD_LITTLE_ENDIAN); + io_write32(qm->io_base + HPRE_RAS_CE_ENB, HPRE_RAS_CE_MASK); + io_write32(qm->io_base + HPRE_RAS_NFE_ENB, HPRE_RAS_NFE_MASK); + io_write32(qm->io_base + HPRE_RAS_FE_ENB, HPRE_RAS_FE_MASK); + io_write32(qm->io_base + HPRE_HAC_INT_MASK, HPRE_HAC_INT_DISABLE); + io_write32(qm->io_base + HPRE_POISON_BYPASS, 0x0); + io_write32(qm->io_base + HPRE_COMMON_CNT_CLR_CE, 0x0); + io_write32(qm->io_base + HPRE_ECC_BYPASS, 0x0); + /* cmd_type is controlled by hac subctrl */ + io_write32(qm->io_base + HPRE_BD_ARUSR_CFG, HPRE_BD_ARUSR_MASK); + io_write32(qm->io_base + HPRE_BD_AWUSR_CFG, HPRE_BD_AWUSR_MASK); + io_write32(qm->io_base + HPRE_DATA_RUSER_CFG, HPRE_DATA_USR_MASK); + io_write32(qm->io_base + HPRE_DATA_WUSER_CFG, HPRE_DATA_USR_MASK); + io_write32(qm->io_base + HPRE_TYPES_ENB, HPRE_RSA_ENB | HPRE_ECC_ENB); + io_write32(qm->io_base + HPRE_RDCHN_INI_CFG, 0x1); + ret = IO_READ32_POLL_TIMEOUT(qm->io_base + HPRE_RDCHN_INI_ST, val, + val & 0x1, POLL_PERIOD, POLL_TIMEOUT); + if (ret) { + EMSG("Fail to init rd channel"); + return TEE_ERROR_BUSY; + } + + ret = hpre_set_cluster(qm); + if (ret) { + EMSG("Fail to init hpre cluster cores"); + return TEE_ERROR_BUSY; + } + + hpre_enable_clock_gate(qm); + + return TEE_SUCCESS; +} + +static enum hisi_drv_status hpre_dev_status_check(struct hisi_qm *qm) +{ + uint32_t val = 0; + + val = io_read32(qm->io_base + HPRE_HAC_INT_SRC); + if (val & HPRE_RAS_NFE_MASK) { + EMSG("HPRE NFE RAS happened, need to reset"); + return HISI_QM_DRVCRYPT_HW_EACCESS; + } + + val = io_read32(qm->io_base + HISI_QM_ABNML_INT_SRC); + if (val) { + if (val & HISI_QM_HPRE_NFE_INT_MASK) + EMSG("QM NFE RAS happened, need to reset"); + + if (val & HISI_QM_INVALID_DB) { + EMSG("QM invalid db happened, please check"); + io_write32(qm->io_base + HISI_QM_ABNML_INT_SRC, + HISI_QM_INVALID_DB); + } + + return HISI_QM_DRVCRYPT_HW_EACCESS; + } + + return HISI_QM_DRVCRYPT_NO_ERR; +} + +static enum hisi_drv_status hpre_qm_init(struct acc_device *hpre_dev) +{ + struct hisi_qm *qm = &hpre_dev->qm; + + if (cpu_mmu_enabled()) { + qm->io_base = (uintptr_t)phys_to_virt_io(hpre_dev->io_base, + hpre_dev->io_size); + if (!qm->io_base) { + EMSG("Fail to get qm io_base"); + return HISI_QM_DRVCRYPT_EFAULT; + } + } else { + qm->io_base = hpre_dev->io_base; + } + + qm->vfs_num = hpre_dev->vfs_num; + qm->fun_type = hpre_dev->fun_type; + qm->sqe_size = HPRE_SQE_SIZE; + qm->sqe_log2_size = HPRE_SQE_LOG2_SIZE; + if (qm->fun_type == HISI_QM_HW_PF) { + hisi_qm_get_version(qm); + DMSG("HPRE hardware version is 0x%"PRIx32, qm->version); + qm->qp_base = HISI_QM_PF_Q_BASE; + qm->qp_num = HISI_QM_PF_Q_NUM; + qm->dev_status_check = hpre_dev_status_check; + } + + return hisi_qm_init(qm); +} + +static struct acc_device *hpre_pre_init(void) +{ + struct acc_device *hpre_dev = NULL; + + hpre_dev = calloc(1, sizeof(*hpre_dev)); + if (!hpre_dev) { + EMSG("Fail to alloc hpre_dev"); + return NULL; + } + + hpre_dev->io_base = HPRE_BAR_BASE; + hpre_dev->io_size = HPRE_BAR_SIZE; + hpre_dev->fun_type = HISI_QM_HW_PF; + SLIST_INSERT_HEAD(&hpre_list, hpre_dev, link); + + return hpre_dev; +} + +static TEE_Result hpre_probe(void) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + struct acc_device *hpre_dev = NULL; + struct hisi_qm *qm = NULL; + + DMSG("HPRE driver init start"); + hpre_dev = hpre_pre_init(); + if (!hpre_dev) + return TEE_ERROR_OUT_OF_MEMORY; + + qm = &hpre_dev->qm; + if (hpre_qm_init(hpre_dev)) { + EMSG("Fail to init hpre qm"); + goto err_with_pre_init; + } + + ret = hpre_engine_init(hpre_dev); + if (ret) { + EMSG("Fail to init engine"); + goto err_with_qm_init; + } + + if (hisi_qm_start(qm)) { + EMSG("Fail to start qm"); + ret = TEE_ERROR_BAD_STATE; + goto err_with_qm_init; + } + + DMSG("HPRE driver init done"); + return TEE_SUCCESS; + +err_with_qm_init: + hisi_qm_uninit(qm); +err_with_pre_init: + SLIST_REMOVE_HEAD(&hpre_list, link); + free(hpre_dev); + + return ret; +} + +driver_init(hpre_probe); diff --git a/optee/optee_os/core/drivers/crypto/hisilicon/include/hisi_qm.h b/optee/optee_os/core/drivers/crypto/hisilicon/include/hisi_qm.h new file mode 100644 index 0000000..8ea1f6f --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/hisilicon/include/hisi_qm.h @@ -0,0 +1,271 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2022-2023, Huawei Technologies Co., Ltd + */ +#ifndef __HISI_QM_H__ +#define __HISI_QM_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define HISI_QM_HW_V2 0x21 +#define HISI_QM_HW_V3 0x30 +#define HISI_QM_MAX_VFS_NUM 63 +#define HISI_QM_PF_Q_BASE 0 +#define HISI_QM_PF_Q_NUM 64 +#define HISI_QM_VF_Q_NUM 15 +#define HISI_QM_Q_DEPTH 8 +#define PHASE_DEFAULT_VAL 0x1 + +#define HISI_QM_ABNML_INT_MASK 0x100004 +#define HISI_QM_ABNML_INT_MASK_CFG 0x7fff +#define HISI_QM_ABNML_INT_SRC 0x100000 +#define HISI_QM_HPRE_NFE_INT_MASK 0x6fb7 +#define HISI_QM_SEC_NFE_INT_MASK 0x6ff7 +#define HISI_QM_INVALID_DB BIT(12) +#define HISI_QM_REVISON_ID_BASE 0x1000dc +#define HISI_QM_REVISON_ID_MASK GENMASK_32(7, 0) +#define POLL_PERIOD 10 +#define POLL_TIMEOUT 1000 +#define HISI_QM_RECV_SYNC_TIMEOUT 0xfffff +#define HISI_QM_ALIGN128 128 +#define HISI_QM_ALIGN32 32 +#define QM_SINGLE_WAIT_TIME 5 +#define ADDR_U64(upper, lower) ((uint64_t)(upper) << 32 | (lower)) + +enum qm_fun_type { + HISI_QM_HW_PF, + HISI_QM_HW_VF, +}; + +enum qm_sq_type { + HISI_QM_CHANNEL_TYPE0 = 0, + HISI_QM_CHANNEL_TYPE1, + HISI_QM_CHANNEL_TYPE2, +}; + +struct qm_sqc { + uint16_t head; + uint16_t tail; + uint32_t base_l; + uint32_t base_h; + /* + * qes : 12 + * sqe : 4 + * rsv(stash_nid/stash_en) : 16 + */ + uint32_t dw3; + uint16_t rand_data; + uint16_t rsv0; + uint16_t pasid; + /* + * rsv : 5 + * head_sig : 1 + * tail_sig : 1 + * pasid_en : 1 + * rsv : 8 + */ + uint16_t w11; + uint16_t cq_num; + /* + * priority(Credit): 4 + * order(order/fc/close/rsv) : 4 + * type : 4 + * rsv : 4 + */ + uint16_t w13; + uint32_t rsv1; +}; + +struct qm_cqc { + uint16_t head; + uint16_t tail; + uint32_t base_l; + uint32_t base_h; + /* + * qes : 12 + * cqe_size : 4 + * rsv(stash_nid/stash_en) : 16 + */ + uint32_t dw3; + uint16_t rand_data; + uint16_t rsv0; + uint16_t pasid; + /* + * pasid_en : 1 + * rsv : 4 + * head_sig : 1 + * tail_sig : 1 + * rsv : 9 + */ + uint16_t w11; + /* + * phase : 1 + * c_flag : 1 + * stash_vld : 1 + */ + uint32_t dw6; + uint32_t rsv1; +}; + +struct qm_cqe { + uint32_t rsv0; + uint16_t cmd_id; + uint16_t rsv1; + uint16_t sq_head; + uint16_t sq_id; + uint16_t rsv2; + /* + * p : 1 + * status : 15 + */ + uint16_t w7; +}; + +struct hisi_qp { + struct hisi_qm *qm; + uint32_t qp_id; + uint8_t sq_type; + uint16_t sq_tail; + uint16_t cq_head; + bool cqc_phase; + bool used; + + void *sqe; + struct qm_cqe *cqe; + paddr_t sqe_dma; + paddr_t cqe_dma; + + enum hisi_drv_status (*fill_sqe)(void *sqe, void *msg); + enum hisi_drv_status (*parse_sqe)(void *sqe, void *msg); +}; + +struct qm_xqc { + struct qm_sqc *sqc; + struct qm_cqc *cqc; + paddr_t sqc_dma; + paddr_t cqc_dma; +}; + +struct hisi_qm { + enum qm_fun_type fun_type; + vaddr_t io_base; + uint32_t io_size; + uint32_t vfs_num; + uint32_t version; + + struct qm_xqc xqc; + struct qm_xqc cfg_xqc; + uint32_t sqe_size; + uint32_t sqe_log2_size; + uint32_t qp_base; + uint32_t qp_num; + uint32_t qp_in_used; + uint32_t qp_idx; + struct hisi_qp *qp_array; + struct mutex qp_lock; /* protect the qp instance */ + struct mutex mailbox_lock; + + enum hisi_drv_status (*dev_status_check)(struct hisi_qm *qm); +}; + +enum hisi_drv_status { + HISI_QM_DRVCRYPT_NO_ERR = 0, + HISI_QM_DRVCRYPT_FAIL = 1, + HISI_QM_DRVCRYPT_EIO = 5, + HISI_QM_DRVCRYPT_EAGAIN = 11, + HISI_QM_DRVCRYPT_ENOMEM = 12, + HISI_QM_DRVCRYPT_EFAULT = 14, + HISI_QM_DRVCRYPT_EBUSY = 16, + HISI_QM_DRVCRYPT_ENODEV = 19, + HISI_QM_DRVCRYPT_EINVAL = 22, + HISI_QM_DRVCRYPT_ETMOUT = 110, + HISI_QM_DRVCRYPT_RECV_DONE = 175, + HISI_QM_DRVCRYPT_ENOPROC, + HISI_QM_DRVCRYPT_IN_EPARA, + HISI_QM_DRVCRYPT_VERIFY_ERR, + HISI_QM_DRVCRYPT_HW_EACCESS, +}; + +struct acc_device { + struct hisi_qm qm; + vaddr_t io_base; + uint32_t io_size; + uint32_t vfs_num; + uint32_t endian; + enum qm_fun_type fun_type; + SLIST_ENTRY(acc_device) link; +}; + +/** + * @Description: Get the version information of QM hardware + * @param qm: Handle of Queue Management module + */ +void hisi_qm_get_version(struct hisi_qm *qm); + +/** + * @Description: Init QM for Kunpeng drv + * @param qm: Handle of Queue Management module + * @return success: HISI_QM_DRVCRYPT_NO_ERR, + * fail: HISI_QM_DRVCRYPT_EBUSY/HISI_QM_DRVCRYPT_EINVAL + */ +enum hisi_drv_status hisi_qm_init(struct hisi_qm *qm); + +/** + * @Description:deinit QM for Kunpeng drv + * @param qm: Handle of Queue Management module + */ +void hisi_qm_uninit(struct hisi_qm *qm); + +/** + * @Description: Start QM for Kunpeng drv + * @param qm: Handle of Queue Management module + */ +enum hisi_drv_status hisi_qm_start(struct hisi_qm *qm); + +/** + * @Description: Config QM for Kunpeng drv + * @param qm: Handle of Queue Management module + */ +void hisi_qm_dev_init(struct hisi_qm *qm); + +/** + * @Description: Create Queue Pair, allocated to PF/VF for configure + * and service use. Each QP includes one SQ and one CQ + * @param qm: Handle of Queue Management module + * @param sq_type: Accelerator specific algorithm type in sqc + * @return success: Handle of QP,fail: NULL + */ +struct hisi_qp *hisi_qm_create_qp(struct hisi_qm *qm, uint8_t sq_type); + +/** + * @Description:Release Queue Pair + * @param qp: Handle of Queue Pair + */ +void hisi_qm_release_qp(struct hisi_qp *qp); + +/** + * @Description: Send SQE(Submmision Queue Element) to Kunpeng dev + * @param qp: Handle of Queue Pair + * @param msg: The message + * @return success: HISI_QM_DRVCRYPT_NO_ERR,fail: HISI_QM_DRVCRYPT_EINVAL + */ +enum hisi_drv_status hisi_qp_send(struct hisi_qp *qp, void *msg); + +/** + * @Description: Recevice result from Kunpeng dev + * @param qp: Handle of Queue Pair + * @param msg: The message + * @return success: HISI_QM_DRVCRYPT_NO_ERR + * fail: HISI_QM_DRVCRYPT_EINVAL/ETMOUT + */ +enum hisi_drv_status hisi_qp_recv_sync(struct hisi_qp *qp, void *msg); + +#endif diff --git a/optee/optee_os/core/drivers/crypto/hisilicon/include/hpre_main.h b/optee/optee_os/core/drivers/crypto/hisilicon/include/hpre_main.h new file mode 100644 index 0000000..2ca2785 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/hisilicon/include/hpre_main.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2024 HiSilicon Limited. + */ +#ifndef _HPRE_MAIN_H +#define _HPRE_MAIN_H + +#include +#include "hisi_qm.h" + +#define HPRE_BAR_BASE 0x150000000 +#define HPRE_BAR_SIZE 0x400000 +#define HPRE_SQE_SIZE 64 +#define HPRE_SQE_LOG2_SIZE 6 +#define HPRE_SQE_SM2_KSEL_SHIFT 1 +#define HPRE_SQE_BD_RSV2_SHIFT 7 +#define HPRE_HW_TASK_INIT 0x1 +#define HPRE_HW_TASK_DONE 0x3 +#define TASK_LENGTH(len) ((len) / 8 - 1) +#define BITS_TO_BYTES(len) (((len) + 7) / 8) +#define BYTES_TO_BITS(len) ((len) * 8) + +#define HPRE_ETYPE_SHIFT 5 +#define HPRE_ETYPE_MASK 0x7ff +#define HPRE_ETYPE1_SHIFT 16 +#define HPRE_ETYPE1_MASK 0x3fff +#define HPRE_DONE_SHIFT 30 +#define HPRE_DONE_MASK 0x3 +#define HPRE_TASK_ETYPE(w0) (((w0) >> HPRE_ETYPE_SHIFT) & HPRE_ETYPE_MASK) +#define HPRE_TASK_ETYPE1(w0) (((w0) >> HPRE_ETYPE1_SHIFT) & HPRE_ETYPE1_MASK) +#define HPRE_TASK_DONE(w0) (((w0) >> HPRE_DONE_SHIFT) & HPRE_DONE_MASK) + +struct hisi_qp *hpre_create_qp(uint8_t sq_type); +enum hisi_drv_status hpre_bin_from_crypto_bin(uint8_t *dst, const uint8_t *src, + uint32_t bsize, uint32_t dsize); +enum hisi_drv_status hpre_bin_to_crypto_bin(uint8_t *dst, const uint8_t *src, + uint32_t bsize, uint32_t dsize); + +#endif diff --git a/optee/optee_os/core/drivers/crypto/hisilicon/sub.mk b/optee/optee_os/core/drivers/crypto/hisilicon/sub.mk new file mode 100644 index 0000000..bebda29 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/hisilicon/sub.mk @@ -0,0 +1,4 @@ +incdirs-y += include + +srcs-y += hisi_qm.c +srcs-$(CFG_HISILICON_ACC_V3) += hpre_main.c 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..c55ab8b --- /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..475d2b9 --- /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..0f937b8 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/se050/core/storage.c @@ -0,0 +1,109 @@ +// 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, NULL, &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..8c4adf0 --- /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..c897d56 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/se050/glue/i2c_stm32.c @@ -0,0 +1,90 @@ +// 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 +#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 pinctrl_state **pinctrl_active, + struct pinctrl_state **pinctrl_sleep) +{ + 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, pinctrl_active, + pinctrl_sleep); +} + +int native_i2c_init(void) +{ + struct stm32_i2c_init_s i2c_init = { }; + + /* 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, &i2c.pinctrl, &i2c.pinctrl_sleep)) + return -1; + + /* Probe the device */ + i2c_init.own_address1 = SMCOM_I2C_ADDRESS; + i2c_init.digital_filter_coef = 0; + i2c_init.analog_filter = true; + + 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..bf305b0 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/stm32/authenc.c @@ -0,0 +1,372 @@ +// 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 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] = TEE_U32_TO_BIG_ENDIAN(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] = TEE_U32_TO_BIG_ENDIAN(TEE_U32_FROM_BIG_ENDIAN(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] = TEE_U32_TO_BIG_ENDIAN(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..2cc1a6e --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/stm32/cipher.c @@ -0,0 +1,377 @@ +// 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" +#include "stm32_saes.h" + +#define DES3_KEY_SIZE 24 + +struct cryp_ctx { + struct stm32_cryp_context ctx; + enum stm32_cryp_algo_mode algo; +}; + +struct saes_ctx { + struct stm32_saes_context ctx; + enum stm32_saes_chaining_mode algo; + /* Fallback to software implementation on 192bit AES key */ + bool use_fallback; + struct crypto_cipher_ctx *fallback_ctx; +}; + +/* + * Internal peripheral context + * SAES and CRYP are registered under the same ID in the crypto framework. + * Therefore, only one of them can be registered. + */ + +union ip_ctx { + struct saes_ctx saes; + struct cryp_ctx cryp; +}; + +/* Internal Peripheral cipher ops*/ +struct ip_cipher_ops { + TEE_Result (*init)(union ip_ctx *ctx, bool is_decrypt, + const uint8_t *key, size_t key_len, + const uint8_t *iv, size_t iv_len); + TEE_Result (*update)(union ip_ctx *ctx, bool last_block, uint8_t *src, + uint8_t *dst, size_t len); + void (*final)(union ip_ctx *ctx); + void (*copy_state)(union ip_ctx *dst_ctx, union ip_ctx *src_ctx); +}; + +struct stm32_cipher_ctx { + struct crypto_cipher_ctx c_ctx; + union ip_ctx ip_ctx; + const struct ip_cipher_ops *ops; +}; + +static TEE_Result cryp_init(union ip_ctx *ip_ctx, bool is_decrypt, + const uint8_t *key, size_t key_len, + const uint8_t *iv, size_t iv_len) +{ + uint8_t temp_key[DES3_KEY_SIZE] = { }; + + if (!IS_ENABLED(CFG_STM32_CRYP)) + return TEE_ERROR_NOT_IMPLEMENTED; + + if (key_len == 16 && + (ip_ctx->cryp.algo == STM32_CRYP_MODE_TDES_ECB || + ip_ctx->cryp.algo == STM32_CRYP_MODE_TDES_CBC)) { + /* Manage DES2: i.e. K=K1.K2.K1 */ + memcpy(temp_key, key, key_len); + memcpy(temp_key + key_len, key, key_len / 2); + key_len = DES3_KEY_SIZE; + key = temp_key; + } + + return stm32_cryp_init(&ip_ctx->cryp.ctx, is_decrypt, ip_ctx->cryp.algo, + key, key_len, iv, iv_len); +} + +static TEE_Result cryp_update(union ip_ctx *ip_ctx, bool last_block, + uint8_t *src, uint8_t *dst, size_t len) +{ + if (!IS_ENABLED(CFG_STM32_CRYP)) + return TEE_ERROR_NOT_IMPLEMENTED; + + return stm32_cryp_update(&ip_ctx->cryp.ctx, last_block, src, dst, len); +} + +static void cryp_copy_state(union ip_ctx *dst_ip_ctx, union ip_ctx *src_ip_ctx) +{ + assert(IS_ENABLED(CFG_STM32_CRYP)); + + memcpy(&dst_ip_ctx->cryp, &src_ip_ctx->cryp, sizeof(dst_ip_ctx->cryp)); +} + +static const struct ip_cipher_ops cryp_ops = { + .init = cryp_init, + .update = cryp_update, + .copy_state = cryp_copy_state, +}; + +static TEE_Result saes_init(union ip_ctx *ip_ctx, bool is_decrypt, + const uint8_t *key, size_t key_len, + const uint8_t *iv, size_t iv_len) +{ + enum stm32_saes_key_selection key_sel = STM32_SAES_KEY_SOFT; + + if (!IS_ENABLED(CFG_STM32_SAES)) + return TEE_ERROR_NOT_IMPLEMENTED; + + if (key_len == AES_KEYSIZE_192) { + struct crypto_cipher_ctx *ctx = ip_ctx->saes.fallback_ctx; + TEE_OperationMode mode = TEE_MODE_ILLEGAL_VALUE; + TEE_Result res = TEE_ERROR_GENERIC; + + if (!IS_ENABLED(CFG_STM32_SAES_SW_FALLBACK)) { + EMSG("STM32 SAES does not support 192bit keys"); + + return TEE_ERROR_NOT_IMPLEMENTED; + } + + if (is_decrypt) + mode = TEE_MODE_DECRYPT; + else + mode = TEE_MODE_ENCRYPT; + + res = ctx->ops->init(ctx, mode, key, key_len, NULL, 0, iv, + iv_len); + if (res) + return res; + + ip_ctx->saes.use_fallback = true; + + return TEE_SUCCESS; + } + + ip_ctx->saes.use_fallback = false; + + return stm32_saes_init(&ip_ctx->saes.ctx, is_decrypt, ip_ctx->saes.algo, + key_sel, key, key_len, iv, iv_len); +} + +static TEE_Result saes_update(union ip_ctx *ip_ctx, bool last_block, + uint8_t *src, uint8_t *dst, size_t len) +{ + if (!IS_ENABLED(CFG_STM32_SAES)) + return TEE_ERROR_NOT_IMPLEMENTED; + + if (ip_ctx->saes.use_fallback) { + struct crypto_cipher_ctx *ctx = ip_ctx->saes.fallback_ctx; + + assert(IS_ENABLED(CFG_STM32_SAES_SW_FALLBACK)); + + return ctx->ops->update(ctx, last_block, src, len, dst); + } + + return stm32_saes_update(&ip_ctx->saes.ctx, last_block, src, dst, len); +} + +static void saes_final(union ip_ctx *ip_ctx) +{ + struct crypto_cipher_ctx *ctx = ip_ctx->saes.fallback_ctx; + + assert(IS_ENABLED(CFG_STM32_SAES)); + + if (ip_ctx->saes.use_fallback) { + assert(IS_ENABLED(CFG_STM32_SAES_SW_FALLBACK)); + ctx->ops->final(ctx); + } +} + +static void saes_copy_state(union ip_ctx *dst_ip_ctx, union ip_ctx *src_ip_ctx) +{ + struct saes_ctx *src_ctx = &src_ip_ctx->saes; + struct crypto_cipher_ctx *fb_ctx = src_ctx->fallback_ctx; + + assert(IS_ENABLED(CFG_STM32_SAES)); + + memcpy(&dst_ip_ctx->saes.ctx, &src_ctx->ctx, sizeof(src_ctx->ctx)); + + dst_ip_ctx->saes.algo = src_ctx->algo; + dst_ip_ctx->saes.use_fallback = src_ctx->use_fallback; + + if (src_ctx->use_fallback) { + assert(IS_ENABLED(CFG_STM32_SAES_SW_FALLBACK)); + fb_ctx->ops->copy_state(dst_ip_ctx->saes.fallback_ctx, fb_ctx); + } +} + +static const struct ip_cipher_ops saes_ops = { + .init = saes_init, + .update = saes_update, + .final = saes_final, + .copy_state = saes_copy_state, +}; + +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); + + return c->ops->init(&c->ip_ctx, !dinit->encrypt, dinit->key1.data, + dinit->key1.length, 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 c->ops->update(&c->ip_ctx, dupdate->last, dupdate->src.data, + dupdate->dst.data, len); +} + +static void stm32_cipher_final(void *ctx __unused) +{ + struct stm32_cipher_ctx *c = to_stm32_cipher_ctx(ctx); + + if (c->ops->final) + c->ops->final(&c->ip_ctx); +} + +static void stm32_cipher_copy_state(void *dst_ctx, void *src_ctx) +{ + struct stm32_cipher_ctx *src_c = to_stm32_cipher_ctx(src_ctx); + struct stm32_cipher_ctx *dst_c = to_stm32_cipher_ctx(dst_ctx); + + src_c->ops->copy_state(&dst_c->ip_ctx, &src_c->ip_ctx); +} + +static TEE_Result alloc_cryp_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; + + FMSG("Using CRYP %d", algo); + c->ip_ctx.cryp.algo = algo; + c->ops = &cryp_ops; + *ctx = &c->c_ctx; + + return TEE_SUCCESS; +} + +static TEE_Result stm32_cryp_cipher_allocate(void **ctx, uint32_t algo) +{ + /* + * Convert TEE_ALGO id to internal id + */ + switch (algo) { + case TEE_ALG_DES_ECB_NOPAD: + return alloc_cryp_ctx(ctx, STM32_CRYP_MODE_DES_ECB); + case TEE_ALG_DES_CBC_NOPAD: + return alloc_cryp_ctx(ctx, STM32_CRYP_MODE_DES_CBC); + case TEE_ALG_DES3_ECB_NOPAD: + return alloc_cryp_ctx(ctx, STM32_CRYP_MODE_TDES_ECB); + case TEE_ALG_DES3_CBC_NOPAD: + return alloc_cryp_ctx(ctx, STM32_CRYP_MODE_TDES_CBC); + case TEE_ALG_AES_ECB_NOPAD: + return alloc_cryp_ctx(ctx, STM32_CRYP_MODE_AES_ECB); + case TEE_ALG_AES_CBC_NOPAD: + return alloc_cryp_ctx(ctx, STM32_CRYP_MODE_AES_CBC); + case TEE_ALG_AES_CTR: + return alloc_cryp_ctx(ctx, STM32_CRYP_MODE_AES_CTR); + default: + return TEE_ERROR_NOT_IMPLEMENTED; + } +} + +static void stm32_cryp_cipher_free(void *ctx) +{ + struct stm32_cipher_ctx *c = to_stm32_cipher_ctx(ctx); + + free(c); +} + +static TEE_Result stm32_saes_cipher_allocate(void **ctx, uint32_t algo) +{ + enum stm32_saes_chaining_mode saes_algo = STM32_SAES_MODE_ECB; + struct crypto_cipher_ctx *fallback_ctx = NULL; + struct stm32_cipher_ctx *saes_ctx = NULL; + TEE_Result res = TEE_SUCCESS; + + switch (algo) { + case TEE_ALG_AES_ECB_NOPAD: + saes_algo = STM32_SAES_MODE_ECB; + if (IS_ENABLED(CFG_STM32_SAES_SW_FALLBACK)) + res = crypto_aes_ecb_alloc_ctx(&fallback_ctx); + break; + case TEE_ALG_AES_CBC_NOPAD: + saes_algo = STM32_SAES_MODE_CBC; + if (IS_ENABLED(CFG_STM32_SAES_SW_FALLBACK)) + res = crypto_aes_cbc_alloc_ctx(&fallback_ctx); + break; + case TEE_ALG_AES_CTR: + saes_algo = STM32_SAES_MODE_CTR; + if (IS_ENABLED(CFG_STM32_SAES_SW_FALLBACK)) + res = crypto_aes_ctr_alloc_ctx(&fallback_ctx); + break; + default: + return TEE_ERROR_NOT_IMPLEMENTED; + } + if (res) + return res; + + saes_ctx = calloc(1, sizeof(*saes_ctx)); + if (!saes_ctx) { + if (IS_ENABLED(CFG_STM32_SAES_SW_FALLBACK)) + fallback_ctx->ops->free_ctx(fallback_ctx); + + return TEE_ERROR_OUT_OF_MEMORY; + } + + FMSG("Using SAES %d", saes_algo); + saes_ctx->ip_ctx.saes.algo = saes_algo; + saes_ctx->ops = &saes_ops; + saes_ctx->ip_ctx.saes.fallback_ctx = fallback_ctx; + *ctx = &saes_ctx->c_ctx; + + return TEE_SUCCESS; +} + +static void stm32_saes_cipher_free(void *ctx) +{ + struct stm32_cipher_ctx *c = to_stm32_cipher_ctx(ctx); + + if (IS_ENABLED(CFG_STM32_SAES_SW_FALLBACK)) { + struct crypto_cipher_ctx *fb_ctx = c->ip_ctx.saes.fallback_ctx; + + fb_ctx->ops->free_ctx(fb_ctx); + } + + free(c); +} + +static struct drvcrypt_cipher driver_cipher_cryp = { + .alloc_ctx = stm32_cryp_cipher_allocate, + .free_ctx = stm32_cryp_cipher_free, + .init = stm32_cipher_initialize, + .update = stm32_cipher_update, + .final = stm32_cipher_final, + .copy_state = stm32_cipher_copy_state, +}; + +static struct drvcrypt_cipher driver_cipher_saes = { + .alloc_ctx = stm32_saes_cipher_allocate, + .free_ctx = stm32_saes_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(enum stm32_cipher_ip_id cipher_ip) +{ + if (cipher_ip == SAES_IP) + return drvcrypt_register_cipher(&driver_cipher_saes); + else if (cipher_ip == CRYP_IP) + return drvcrypt_register_cipher(&driver_cipher_cryp); + else + return TEE_ERROR_BAD_PARAMETERS; +} 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..7ae7f29 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/stm32/common.h @@ -0,0 +1,38 @@ +/* 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 + +enum stm32_cipher_ip_id { + CRYP_IP, + SAES_IP, +}; + +/* + * Crypto algorithm common macro used in stm32_saes and stm32_cryp driver + */ + +#define INT8_BIT U(8) +#define AES_BLOCK_SIZE_BIT U(128) +#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 U(64) +#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 U(16) +#define AES_KEYSIZE_192 U(24) +#define AES_KEYSIZE_256 U(32) +#define AES_IVSIZE U(16) + +TEE_Result stm32_register_authenc(void); +TEE_Result stm32_register_cipher(enum stm32_cipher_ip_id); + +#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..3f3aa88 --- /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 ($(call cfg-one-enabled, CFG_STM32_CRYP CFG_STM32_SAES),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..e8da4d5 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/stm32/stm32_cryp.c @@ -0,0 +1,1337 @@ +// 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 + +#include "stm32_cryp.h" +#include "common.h" + +/* 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 +#define CRYP_RESET_DELAY_US U(2) + +/* 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 a local variable + * before writing only once to the hardware 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) + +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 TEE_Result stm32_cryp_reset(void) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + if (!cryp_pdata.reset) + return TEE_SUCCESS; + + res = rstctrl_assert_to(cryp_pdata.reset, TIMEOUT_US_1MS); + if (res) + return res; + + udelay(CRYP_RESET_DELAY_US); + + return rstctrl_deassert_to(cryp_pdata.reset, TIMEOUT_US_1MS); +} + +static void cryp_end(struct stm32_cryp_context *ctx, TEE_Result prev_error) +{ + if (prev_error && stm32_cryp_reset()) + 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 + * TEE_U32_TO_BIG_ENDIAN(data) before write to DIN register + * nor + * TEE_U32_FROM_BIG_ENDIAN after reading from DOUT register. + */ + 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] = TEE_U32_TO_BIG_ENDIAN(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] = TEE_U32_TO_BIG_ENDIAN(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_pm(enum pm_op op, uint32_t pm_hint, + const struct pm_callback_handle *hdl __unused) +{ + switch (op) { + case PM_OP_SUSPEND: + clk_disable(cryp_pdata.clock); + return TEE_SUCCESS; + case PM_OP_RESUME: + if (clk_enable(cryp_pdata.clock)) + panic(); + + if (PM_HINT_IS_STATE(pm_hint, CONTEXT) && stm32_cryp_reset()) + panic(); + + return TEE_SUCCESS; + default: + /* Unexpected PM operation */ + assert(0); + return TEE_ERROR_NOT_IMPLEMENTED; + } +} +DECLARE_KEEP_PAGER(stm32_cryp_pm); + +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 != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND) + 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 (stm32_cryp_reset()) + 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(CRYP_IP); + if (res) { + EMSG("Failed to register to cipher: %#"PRIx32, res); + panic(); + } + } + + register_pm_core_service_cb(stm32_cryp_pm, NULL, "stm32-cryp"); + + 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/stm32_saes.c b/optee/optee_os/core/drivers/crypto/stm32/stm32_saes.c new file mode 100644 index 0000000..e9f5a57 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/stm32/stm32_saes.c @@ -0,0 +1,1432 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021-2023, STMicroelectronics - All Rights Reserved + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "stm32_saes.h" + +/* SAES control register */ +#define _SAES_CR U(0x0) +/* SAES status register */ +#define _SAES_SR U(0x04) +/* SAES data input register */ +#define _SAES_DINR U(0x08) +/* SAES data output register */ +#define _SAES_DOUTR U(0x0c) +/* SAES key registers [0-3] */ +#define _SAES_KEYR0 U(0x10) +#define _SAES_KEYR1 U(0x14) +#define _SAES_KEYR2 U(0x18) +#define _SAES_KEYR3 U(0x1c) +/* SAES initialization vector registers [0-3] */ +#define _SAES_IVR0 U(0x20) +#define _SAES_IVR1 U(0x24) +#define _SAES_IVR2 U(0x28) +#define _SAES_IVR3 U(0x2c) +/* SAES key registers [4-7] */ +#define _SAES_KEYR4 U(0x30) +#define _SAES_KEYR5 U(0x34) +#define _SAES_KEYR6 U(0x38) +#define _SAES_KEYR7 U(0x3c) +/* SAES suspend registers [0-7] */ +#define _SAES_SUSPR0 U(0x40) +#define _SAES_SUSPR1 U(0x44) +#define _SAES_SUSPR2 U(0x48) +#define _SAES_SUSPR3 U(0x4c) +#define _SAES_SUSPR4 U(0x50) +#define _SAES_SUSPR5 U(0x54) +#define _SAES_SUSPR6 U(0x58) +#define _SAES_SUSPR7 U(0x5c) +/* SAES Interrupt Enable Register */ +#define _SAES_IER U(0x300) +/* SAES Interrupt Status Register */ +#define _SAES_ISR U(0x304) +/* SAES Interrupt Clear Register */ +#define _SAES_ICR U(0x308) + +/* SAES control register fields */ +#define _SAES_CR_RESET_VALUE U(0x0) +#define _SAES_CR_IPRST BIT(31) +#define _SAES_CR_KEYSEL_MASK GENMASK_32(30, 28) +#define _SAES_CR_KEYSEL_SHIFT U(28) +#define _SAES_CR_KEYSEL_SOFT U(0x0) +#define _SAES_CR_KEYSEL_DHUK U(0x1) +#define _SAES_CR_KEYSEL_BHK U(0x2) +#define _SAES_CR_KEYSEL_BHU_XOR_BH_K U(0x4) +#define _SAES_CR_KEYSEL_TEST U(0x7) +#define _SAES_CR_KSHAREID_MASK GENMASK_32(27, 26) +#define _SAES_CR_KSHAREID_SHIFT U(26) +#define _SAES_CR_KSHAREID_CRYP U(0x0) +#define _SAES_CR_KEYMOD_MASK GENMASK_32(25, 24) +#define _SAES_CR_KEYMOD_SHIFT U(24) +#define _SAES_CR_KEYMOD_NORMAL U(0x0) +#define _SAES_CR_KEYMOD_WRAPPED U(0x1) +#define _SAES_CR_KEYMOD_SHARED U(0x2) +#define _SAES_CR_NPBLB_MASK GENMASK_32(23, 20) +#define _SAES_CR_NPBLB_SHIFT U(20) +#define _SAES_CR_KEYPROT BIT(19) +#define _SAES_CR_KEYSIZE BIT(18) +#define _SAES_CR_GCMPH_MASK GENMASK_32(14, 13) +#define _SAES_CR_GCMPH_SHIFT U(13) +#define _SAES_CR_GCMPH_INIT U(0) +#define _SAES_CR_GCMPH_HEADER U(1) +#define _SAES_CR_GCMPH_PAYLOAD U(2) +#define _SAES_CR_GCMPH_FINAL U(3) +#define _SAES_CR_DMAOUTEN BIT(12) +#define _SAES_CR_DMAINEN BIT(11) +#define _SAES_CR_CHMOD_MASK (BIT(16) | GENMASK_32(6, 5)) +#define _SAES_CR_CHMOD_SHIFT U(5) +#define _SAES_CR_CHMOD_ECB U(0x0) +#define _SAES_CR_CHMOD_CBC U(0x1) +#define _SAES_CR_CHMOD_CTR U(0x2) +#define _SAES_CR_CHMOD_GCM U(0x3) +#define _SAES_CR_CHMOD_GMAC U(0x3) +#define _SAES_CR_CHMOD_CCM U(0x800) +#define _SAES_CR_MODE_MASK GENMASK_32(4, 3) +#define _SAES_CR_MODE_SHIFT U(3) +#define _SAES_CR_MODE_ENC U(0) +#define _SAES_CR_MODE_KEYPREP U(1) +#define _SAES_CR_MODE_DEC U(2) +#define _SAES_CR_DATATYPE_MASK GENMASK_32(2, 1) +#define _SAES_CR_DATATYPE_SHIFT U(1) +#define _SAES_CR_DATATYPE_NONE U(0) +#define _SAES_CR_DATATYPE_HALF_WORD U(1) +#define _SAES_CR_DATATYPE_BYTE U(2) +#define _SAES_CR_DATATYPE_BIT U(3) +#define _SAES_CR_EN BIT(0) + +/* SAES status register fields */ +#define _SAES_SR_KEYVALID BIT(7) +#define _SAES_SR_BUSY BIT(3) +#define _SAES_SR_WRERR BIT(2) +#define _SAES_SR_RDERR BIT(1) +#define _SAES_SR_CCF BIT(0) + +/* SAES interrupt registers fields */ +#define _SAES_I_RNG_ERR BIT(3) +#define _SAES_I_KEY_ERR BIT(2) +#define _SAES_I_RW_ERR BIT(1) +#define _SAES_I_CC BIT(0) + +#define SAES_TIMEOUT_US U(100000) +#define TIMEOUT_US_1MS U(1000) +#define SAES_RESET_DELAY U(2) + +#define IS_CHAINING_MODE(mode, cr) \ + (((cr) & _SAES_CR_CHMOD_MASK) == (_SAES_CR_CHMOD_##mode << \ + _SAES_CR_CHMOD_SHIFT)) + +#define SET_CHAINING_MODE(mode, cr) \ + set_field_u32(cr, _SAES_CR_CHMOD_MASK, _SAES_CR_CHMOD_##mode) + +static struct mutex saes_lock = MUTEX_INITIALIZER; +static struct stm32_saes_platdata { + vaddr_t base; + struct clk *clk; + struct rstctrl *reset; +} saes_pdata; + +static bool does_chaining_mode_need_iv(uint32_t cr) +{ + return !IS_CHAINING_MODE(ECB, cr); +} + +static bool is_encrypt(uint32_t cr) +{ + return (cr & _SAES_CR_MODE_MASK) == + SHIFT_U32(_SAES_CR_MODE_ENC, _SAES_CR_MODE_SHIFT); +} + +static bool is_decrypt(uint32_t cr) +{ + return (cr & _SAES_CR_MODE_MASK) == + SHIFT_U32(_SAES_CR_MODE_DEC, _SAES_CR_MODE_SHIFT); +} + +static bool does_need_npblb(uint32_t cr) +{ + return (IS_CHAINING_MODE(GCM, cr) && is_encrypt(cr)) || + (IS_CHAINING_MODE(CCM, cr) && is_decrypt(cr)); +} + +static bool can_suspend(uint32_t cr) +{ + return !IS_CHAINING_MODE(GCM, cr); +} + +static void write_aligned_block(vaddr_t base, uint32_t *data) +{ + unsigned int i = 0; + + /* SAES is configured to swap bytes as expected */ + for (i = 0; i < AES_BLOCK_NB_U32; i++) + io_write32(base + _SAES_DINR, data[i]); +} + +static void write_block(vaddr_t base, uint8_t *data) +{ + if (IS_ALIGNED_WITH_TYPE(data, uint32_t)) { + write_aligned_block(base, (void *)data); + } else { + uint32_t data_u32[AES_BLOCK_NB_U32] = { }; + + memcpy(data_u32, data, sizeof(data_u32)); + write_aligned_block(base, data_u32); + } +} + +static void read_aligned_block(vaddr_t base, uint32_t *data) +{ + unsigned int i = 0; + + /* SAES is configured to swap bytes as expected */ + for (i = 0; i < AES_BLOCK_NB_U32; i++) + data[i] = io_read32(base + _SAES_DOUTR); +} + +static void read_block(vaddr_t base, uint8_t *data) +{ + if (IS_ALIGNED_WITH_TYPE(data, uint32_t)) { + read_aligned_block(base, (void *)data); + } else { + uint32_t data_u32[AES_BLOCK_NB_U32] = { }; + + read_aligned_block(base, data_u32); + + memcpy(data, data_u32, sizeof(data_u32)); + } +} + +static TEE_Result wait_computation_completed(vaddr_t base) +{ + uint64_t timeout_ref = timeout_init_us(SAES_TIMEOUT_US); + + while ((io_read32(base + _SAES_SR) & _SAES_SR_CCF) != _SAES_SR_CCF) + if (timeout_elapsed(timeout_ref)) + break; + + if ((io_read32(base + _SAES_SR) & _SAES_SR_CCF) != _SAES_SR_CCF) { + DMSG("CCF timeout"); + return TEE_ERROR_GENERIC; + } + + return TEE_SUCCESS; +} + +static void clear_computation_completed(uintptr_t base) +{ + io_setbits32(base + _SAES_ICR, _SAES_I_CC); +} + +static TEE_Result wait_key_valid(vaddr_t base) +{ + uint64_t timeout_ref = timeout_init_us(SAES_TIMEOUT_US); + + while (!(io_read32(base + _SAES_SR) & _SAES_SR_KEYVALID)) + if (timeout_elapsed(timeout_ref)) + break; + + if (!(io_read32(base + _SAES_SR) & _SAES_SR_KEYVALID)) { + DMSG("CCF timeout"); + return TEE_ERROR_GENERIC; + } + + return TEE_SUCCESS; +} + +static TEE_Result saes_start(struct stm32_saes_context *ctx) +{ + uint64_t timeout_ref = 0; + + /* Reset SAES */ + io_setbits32(ctx->base + _SAES_CR, _SAES_CR_IPRST); + io_clrbits32(ctx->base + _SAES_CR, _SAES_CR_IPRST); + + timeout_ref = timeout_init_us(SAES_TIMEOUT_US); + while (io_read32(ctx->base + _SAES_SR) & _SAES_SR_BUSY) + if (timeout_elapsed(timeout_ref)) + break; + + if (io_read32(ctx->base + _SAES_SR) & _SAES_SR_BUSY) { + DMSG("busy timeout"); + return TEE_ERROR_GENERIC; + } + + return TEE_SUCCESS; +} + +static void saes_end(struct stm32_saes_context *ctx, int prev_error) +{ + if (prev_error) { + /* Reset SAES */ + io_setbits32(ctx->base + _SAES_CR, _SAES_CR_IPRST); + io_clrbits32(ctx->base + _SAES_CR, _SAES_CR_IPRST); + } + + /* Disable the SAES peripheral */ + io_clrbits32(ctx->base + _SAES_CR, _SAES_CR_EN); +} + +static void saes_write_iv(struct stm32_saes_context *ctx) +{ + /* If chaining mode need to restore IV */ + if (does_chaining_mode_need_iv(ctx->cr)) { + unsigned int i = 0; + + for (i = 0; i < AES_IVSIZE / sizeof(uint32_t); i++) { + io_write32(ctx->base + _SAES_IVR0 + i * + sizeof(uint32_t), ctx->iv[i]); + } + } +} + +static void saes_save_suspend(struct stm32_saes_context *ctx) +{ + size_t i = 0; + + for (i = 0; i < 8; i++) + ctx->susp[i] = io_read32(ctx->base + _SAES_SUSPR0 + + i * sizeof(uint32_t)); +} + +static void saes_restore_suspend(struct stm32_saes_context *ctx) +{ + size_t i = 0; + + for (i = 0; i < 8; i++) + io_write32(ctx->base + _SAES_SUSPR0 + i * sizeof(uint32_t), + ctx->susp[i]); +} + +static void saes_write_key(struct stm32_saes_context *ctx) +{ + /* Restore the _SAES_KEYRx if SOFTWARE key */ + if ((ctx->cr & _SAES_CR_KEYSEL_MASK) == + SHIFT_U32(_SAES_CR_KEYSEL_SOFT, _SAES_CR_KEYSEL_SHIFT)) { + size_t i = 0; + + for (i = 0; i < AES_KEYSIZE_128 / sizeof(uint32_t); i++) + io_write32(ctx->base + _SAES_KEYR0 + i * + sizeof(uint32_t), + ctx->key[i]); + + if ((ctx->cr & _SAES_CR_KEYSIZE) == _SAES_CR_KEYSIZE) { + for (i = 0; + i < (AES_KEYSIZE_256 / 2) / sizeof(uint32_t); + i++) { + io_write32(ctx->base + _SAES_KEYR4 + i * + sizeof(uint32_t), + ctx->key[i + 4]); + } + } + } +} + +static TEE_Result saes_prepare_key(struct stm32_saes_context *ctx) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + /* Disable the SAES peripheral */ + io_clrbits32(ctx->base + _SAES_CR, _SAES_CR_EN); + + /* Set key size */ + if ((ctx->cr & _SAES_CR_KEYSIZE)) + io_setbits32(ctx->base + _SAES_CR, _SAES_CR_KEYSIZE); + else + io_clrbits32(ctx->base + _SAES_CR, _SAES_CR_KEYSIZE); + + saes_write_key(ctx); + + res = wait_key_valid(ctx->base); + if (res) + return res; + + /* + * For ECB/CBC decryption, key preparation mode must be selected + * to populate the key. + */ + if ((IS_CHAINING_MODE(ECB, ctx->cr) || + IS_CHAINING_MODE(CBC, ctx->cr)) && is_decrypt(ctx->cr)) { + /* Select Mode 2 */ + io_clrsetbits32(ctx->base + _SAES_CR, _SAES_CR_MODE_MASK, + SHIFT_U32(_SAES_CR_MODE_KEYPREP, + _SAES_CR_MODE_SHIFT)); + + /* Enable SAES */ + io_setbits32(ctx->base + _SAES_CR, _SAES_CR_EN); + + res = wait_computation_completed(ctx->base); + if (res) + return res; + + clear_computation_completed(ctx->base); + + /* Set Mode 3 */ + io_clrsetbits32(ctx->base + _SAES_CR, _SAES_CR_MODE_MASK, + SHIFT_U32(_SAES_CR_MODE_DEC, + _SAES_CR_MODE_SHIFT)); + } + + return TEE_SUCCESS; +} + +static TEE_Result save_context(struct stm32_saes_context *ctx) +{ + if ((io_read32(ctx->base + _SAES_SR) & _SAES_SR_CCF)) { + /* Device should not be in a processing phase */ + return TEE_ERROR_BAD_STATE; + } + + /* Save CR */ + ctx->cr = io_read32(ctx->base + _SAES_CR); + + if (!can_suspend(ctx->cr)) + return TEE_SUCCESS; + + saes_save_suspend(ctx); + + /* If chaining mode need to save current IV */ + if (does_chaining_mode_need_iv(ctx->cr)) { + uint8_t i = 0; + + /* Save IV */ + for (i = 0; i < AES_IVSIZE / sizeof(uint32_t); i++) { + ctx->iv[i] = io_read32(ctx->base + _SAES_IVR0 + i * + sizeof(uint32_t)); + } + } + + /* Disable the SAES peripheral */ + io_clrbits32(ctx->base + _SAES_CR, _SAES_CR_EN); + + return TEE_SUCCESS; +} + +/* To resume the processing of a message */ +static TEE_Result restore_context(struct stm32_saes_context *ctx) +{ + TEE_Result res = TEE_SUCCESS; + + /* SAES shall be disabled */ + if ((io_read32(ctx->base + _SAES_CR) & _SAES_CR_EN)) { + DMSG("Device is still enabled"); + return TEE_ERROR_BAD_STATE; + } + + /* Reset internal state */ + io_setbits32(ctx->base + _SAES_CR, _SAES_CR_IPRST); + + /* Restore configuration register */ + io_write32(ctx->base + _SAES_CR, ctx->cr); + + /* Write key and, in case of CBC or ECB decrypt, prepare it */ + res = saes_prepare_key(ctx); + if (res) + return res; + + saes_restore_suspend(ctx); + + saes_write_iv(ctx); + + /* Enable the SAES peripheral */ + io_setbits32(ctx->base + _SAES_CR, _SAES_CR_EN); + + return TEE_SUCCESS; +} + +static TEE_Result do_from_init_to_phase(struct stm32_saes_context *ctx, + uint32_t new_phase) +{ + TEE_Result res = TEE_SUCCESS; + + /* We didn't run the init phase yet */ + res = restore_context(ctx); + if (res) + return res; + + res = wait_computation_completed(ctx->base); + if (res) + return res; + + clear_computation_completed(ctx->base); + + /* Move to 'new_phase' */ + io_clrsetbits32(ctx->base + _SAES_CR, _SAES_CR_GCMPH_MASK, + SHIFT_U32(new_phase, _SAES_CR_GCMPH_SHIFT)); + + /* Enable the SAES peripheral (init disabled it) */ + io_setbits32(ctx->base + _SAES_CR, _SAES_CR_EN); + + return TEE_SUCCESS; +} + +static TEE_Result do_from_header_to_phase(struct stm32_saes_context *ctx, + uint32_t new_phase) +{ + TEE_Result res = TEE_SUCCESS; + + if (can_suspend(ctx->cr)) { + 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, + AES_BLOCK_SIZE - ctx->extra_size); + + write_aligned_block(ctx->base, ctx->extra); + + res = wait_computation_completed(ctx->base); + if (res) + return res; + + clear_computation_completed(ctx->base); + + ctx->assoc_len += ctx->extra_size * INT8_BIT; + ctx->extra_size = U(0); + } + + /* Move to 'new_phase' */ + io_clrsetbits32(ctx->base + _SAES_CR, _SAES_CR_GCMPH_MASK, + SHIFT_U32(new_phase, _SAES_CR_GCMPH_SHIFT)); + + return TEE_SUCCESS; +} + +/** + * @brief Start an AES computation. + * @param ctx: SAES process context + * @param is_dec: true if decryption, false if encryption + * @param ch_mode: define the chaining mode + * @param key_select: define where the key comes from + * @param key: pointer to key (if key_select is KEY_SOFT, else unused) + * @param key_size: key size + * @param iv: pointer to initialization vector (unused if ch_mode 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 or a TEE_Result compliant code. + */ +TEE_Result stm32_saes_init(struct stm32_saes_context *ctx, bool is_dec, + enum stm32_saes_chaining_mode ch_mode, + enum stm32_saes_key_selection key_select, + const void *key, size_t key_size, const void *iv, + size_t iv_size) +{ + const uint32_t *key_u32 = NULL; + const uint32_t *iv_u32 = NULL; + uint32_t local_key[8] = { }; + uint32_t local_iv[4] = { }; + unsigned int i = 0; + + if (!ctx) + return TEE_ERROR_BAD_PARAMETERS; + + *ctx = (struct stm32_saes_context){ + .lock = &saes_lock, + .base = saes_pdata.base, + .cr = _SAES_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) + ctx->cr |= set_field_u32(ctx->cr, _SAES_CR_MODE_MASK, + _SAES_CR_MODE_DEC); + else + ctx->cr |= set_field_u32(ctx->cr, _SAES_CR_MODE_MASK, + _SAES_CR_MODE_ENC); + + /* Save chaining mode */ + switch (ch_mode) { + case STM32_SAES_MODE_ECB: + ctx->cr |= SET_CHAINING_MODE(ECB, ctx->cr); + break; + case STM32_SAES_MODE_CBC: + ctx->cr |= SET_CHAINING_MODE(CBC, ctx->cr); + break; + case STM32_SAES_MODE_CTR: + ctx->cr |= SET_CHAINING_MODE(CTR, ctx->cr); + break; + case STM32_SAES_MODE_GCM: + ctx->cr |= SET_CHAINING_MODE(GCM, ctx->cr); + break; + case STM32_SAES_MODE_CCM: + ctx->cr |= SET_CHAINING_MODE(CCM, ctx->cr); + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + + /* + * We will use HW Byte swap (_SAES_CR_DATATYPE_BYTE) for data. + * So we won't need to + * TEE_U32_TO_BIG_ENDIAN(data) before write to DINR + * nor + * TEE_U32_FROM_BIG_ENDIAN after reading from DOUTR. + * + * But note that wrap key only accept _SAES_CR_DATATYPE_NONE. + */ + ctx->cr |= set_field_u32(ctx->cr, _SAES_CR_DATATYPE_MASK, + _SAES_CR_DATATYPE_BYTE); + + /* Configure keysize */ + switch (key_size) { + case AES_KEYSIZE_128: + ctx->cr &= ~_SAES_CR_KEYSIZE; + break; + case AES_KEYSIZE_256: + ctx->cr |= _SAES_CR_KEYSIZE; + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + + /* Configure key */ + switch (key_select) { + case STM32_SAES_KEY_SOFT: + ctx->cr |= set_field_u32(ctx->cr, _SAES_CR_KEYSEL_MASK, + SHIFT_U32(_SAES_CR_KEYSEL_SOFT, + _SAES_CR_KEYSEL_SHIFT)); + /* Save key */ + switch (key_size) { + case AES_KEYSIZE_128: + /* First 16 bytes == 4 u32 */ + for (i = 0; i < AES_KEYSIZE_128 / sizeof(uint32_t); + i++) { + ctx->key[i] = + TEE_U32_TO_BIG_ENDIAN(key_u32[3 - i]); + /* + * /!\ we save the key in HW byte order + * and word order: key[i] is for _SAES_KEYRi. + */ + } + break; + case AES_KEYSIZE_256: + for (i = 0; i < AES_KEYSIZE_256 / sizeof(uint32_t); + i++) { + ctx->key[i] = + TEE_U32_TO_BIG_ENDIAN(key_u32[7 - i]); + /* + * /!\ we save the key in HW byte order + * and word order: key[i] is for _SAES_KEYRi. + */ + } + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + break; + case STM32_SAES_KEY_DHU: + ctx->cr |= set_field_u32(ctx->cr, _SAES_CR_KEYSEL_MASK, + SHIFT_U32(_SAES_CR_KEYSEL_DHUK, + _SAES_CR_KEYSEL_SHIFT)); + break; + case STM32_SAES_KEY_BH: + ctx->cr |= set_field_u32(ctx->cr, _SAES_CR_KEYSEL_MASK, + SHIFT_U32(_SAES_CR_KEYSEL_BHK, + _SAES_CR_KEYSEL_SHIFT)); + break; + case STM32_SAES_KEY_BHU_XOR_BH: + ctx->cr |= set_field_u32(ctx->cr, _SAES_CR_KEYSEL_MASK, + SHIFT_U32(_SAES_CR_KEYSEL_BHU_XOR_BH_K, + _SAES_CR_KEYSEL_SHIFT)); + break; + case STM32_SAES_KEY_WRAPPED: + ctx->cr |= set_field_u32(ctx->cr, _SAES_CR_KEYSEL_MASK, + SHIFT_U32(_SAES_CR_KEYSEL_SOFT, + _SAES_CR_KEYSEL_SHIFT)); + break; + + default: + return TEE_ERROR_BAD_PARAMETERS; + } + + /* Save IV */ + if (ch_mode != STM32_SAES_MODE_ECB) { + if (!iv || iv_size != AES_IVSIZE) + return TEE_ERROR_BAD_PARAMETERS; + + for (i = 0; i < AES_IVSIZE / sizeof(uint32_t); i++) + ctx->iv[i] = TEE_U32_TO_BIG_ENDIAN(iv_u32[3 - i]); + } + + /* Reset suspend registers */ + memset(ctx->susp, 0, sizeof(ctx->susp)); + + return saes_start(ctx); +} + +/** + * @brief Update (or start) an AES authentificate process of + * associated data (CCM or GCM). + * @param ctx: SAES process context + * @param data: pointer to associated data + * @param data_size: data size + * + * @retval 0 if OK. + */ +TEE_Result stm32_saes_update_assodata(struct stm32_saes_context *ctx, + uint8_t *data, size_t data_size) +{ + TEE_Result res = TEE_SUCCESS; + unsigned int i = 0; + uint32_t previous_phase = 0; + + if (!ctx) + return TEE_ERROR_BAD_PARAMETERS; + + /* If no associated data, nothing to do */ + if (!data || !data_size) + return TEE_SUCCESS; + + mutex_lock(ctx->lock); + + previous_phase = (ctx->cr & _SAES_CR_GCMPH_MASK) >> + _SAES_CR_GCMPH_SHIFT; + + switch (previous_phase) { + case _SAES_CR_GCMPH_INIT: + res = do_from_init_to_phase(ctx, _SAES_CR_GCMPH_HEADER); + break; + case _SAES_CR_GCMPH_HEADER: + /* + * Function update_assodata() was already called. + * We only need to restore the context. + */ + if (can_suspend(ctx->cr)) + res = restore_context(ctx); + + break; + default: + DMSG("out of order call"); + 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) >= AES_BLOCK_SIZE)) { + uint32_t block[AES_BLOCK_NB_U32] = { }; + + memcpy(block, ctx->extra, ctx->extra_size); + memcpy((uint8_t *)block + ctx->extra_size, data, + AES_BLOCK_SIZE - ctx->extra_size); + + write_aligned_block(ctx->base, block); + + res = wait_computation_completed(ctx->base); + if (res) + goto out; + + clear_computation_completed(ctx->base); + + i += AES_BLOCK_SIZE - ctx->extra_size; + ctx->extra_size = 0; + ctx->assoc_len += AES_BLOCK_SIZE_BIT; + } + + while (data_size - i >= AES_BLOCK_SIZE) { + write_block(ctx->base, data + i); + + res = wait_computation_completed(ctx->base); + if (res) + goto out; + + clear_computation_completed(ctx->base); + + /* Process next block */ + i += AES_BLOCK_SIZE; + ctx->assoc_len += AES_BLOCK_SIZE_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) + saes_end(ctx, res); + + mutex_unlock(ctx->lock); + + return res; +} + +/** + * @brief Update (or start) an AES authenticate and de/encrypt with + * payload data (CCM or GCM). + * @param ctx: SAES 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_saes_update_load(struct stm32_saes_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; + uint32_t previous_phase = 0; + + if (!ctx) + return TEE_ERROR_BAD_PARAMETERS; + + /* If there is no data, nothing to do */ + if (!data_in || !data_size) + return TEE_SUCCESS; + + mutex_lock(ctx->lock); + + previous_phase = ((ctx->cr & _SAES_CR_GCMPH_MASK) >> + _SAES_CR_GCMPH_SHIFT); + + switch (previous_phase) { + case _SAES_CR_GCMPH_INIT: + res = do_from_init_to_phase(ctx, _SAES_CR_GCMPH_PAYLOAD); + break; + case _SAES_CR_GCMPH_HEADER: + res = do_from_header_to_phase(ctx, _SAES_CR_GCMPH_PAYLOAD); + break; + case _SAES_CR_GCMPH_PAYLOAD: + /* new update_load call, we only need to restore context */ + if (can_suspend(ctx->cr)) + res = restore_context(ctx); + + break; + default: + DMSG("out of order call"); + res = TEE_ERROR_BAD_STATE; + } + + if (res) + goto out; + + while (i < ROUNDDOWN(data_size, AES_BLOCK_SIZE)) { + write_block(ctx->base, data_in + i); + + res = wait_computation_completed(ctx->base); + if (res) + goto out; + + read_block(ctx->base, data_out + i); + + clear_computation_completed(ctx->base); + + /* Process next block */ + i += AES_BLOCK_SIZE; + ctx->load_len += AES_BLOCK_SIZE_BIT; + } + + /* Manage last block if not a block size multiple */ + if (last_block && i < data_size) { + uint32_t block_in[AES_BLOCK_NB_U32] = { }; + uint32_t block_out[AES_BLOCK_NB_U32] = { }; + + memcpy(block_in, data_in + i, data_size - i); + + if (does_need_npblb(ctx->cr)) { + uint32_t npblb = AES_BLOCK_SIZE - (data_size - i); + + io_clrsetbits32(ctx->base + _SAES_CR, + _SAES_CR_NPBLB_MASK, + SHIFT_U32(npblb, _SAES_CR_NPBLB_SHIFT)); + } + + write_aligned_block(ctx->base, block_in); + + res = wait_computation_completed(ctx->base); + if (res) + goto out; + + read_aligned_block(ctx->base, block_out); + + clear_computation_completed(ctx->base); + + memcpy(data_out + i, block_out, data_size - i); + + ctx->load_len += (data_size - i) * INT8_BIT; + } + + res = save_context(ctx); +out: + if (res) + saes_end(ctx, res); + + mutex_unlock(ctx->lock); + + return res; +} + +/** + * @brief Get authentication tag for AES authenticated algorithms (CCM or GCM). + * @param ctx: SAES process context + * @param tag: pointer where to save the tag + * @param data_size: tag size + * + * @retval TEE_SUCCESS if OK. + */ +TEE_Result stm32_saes_final(struct stm32_saes_context *ctx, uint8_t *tag, + size_t tag_size) +{ + TEE_Result res = TEE_SUCCESS; + uint32_t tag_u32[4] = { }; + uint32_t previous_phase = 0; + + if (!ctx) + return TEE_ERROR_BAD_PARAMETERS; + + mutex_lock(ctx->lock); + + previous_phase = (ctx->cr & _SAES_CR_GCMPH_MASK) >> + _SAES_CR_GCMPH_SHIFT; + + switch (previous_phase) { + case _SAES_CR_GCMPH_INIT: + res = do_from_init_to_phase(ctx, _SAES_CR_GCMPH_FINAL); + break; + case _SAES_CR_GCMPH_HEADER: + res = do_from_header_to_phase(ctx, _SAES_CR_GCMPH_FINAL); + break; + case _SAES_CR_GCMPH_PAYLOAD: + if (can_suspend(ctx->cr)) + res = restore_context(ctx); + + /* Move to final phase */ + io_clrsetbits32(ctx->base + _SAES_CR, _SAES_CR_GCMPH_MASK, + SHIFT_U32(_SAES_CR_GCMPH_FINAL, + _SAES_CR_GCMPH_SHIFT)); + break; + default: + DMSG("out of order call"); + res = TEE_ERROR_BAD_STATE; + } + if (res) + goto out; + + if (IS_CHAINING_MODE(GCM, ctx->cr)) { + /* SAES is configured to swap bytes as expected */ + io_write32(ctx->base + _SAES_DINR, 0); + io_write32(ctx->base + _SAES_DINR, ctx->assoc_len); + io_write32(ctx->base + _SAES_DINR, 0); + io_write32(ctx->base + _SAES_DINR, ctx->load_len); + } + + res = wait_computation_completed(ctx->base); + if (res) + goto out; + + read_aligned_block(ctx->base, tag_u32); + + clear_computation_completed(ctx->base); + + memcpy(tag, tag_u32, MIN(sizeof(tag_u32), tag_size)); + +out: + saes_end(ctx, res); + mutex_unlock(ctx->lock); + + return res; +} + +/** + * @brief Update (or start) an AES de/encrypt process (ECB, CBC or CTR). + * @param ctx: SAES 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_saes_update(struct stm32_saes_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 = U(0); + + if (!ctx) + return TEE_ERROR_BAD_PARAMETERS; + + mutex_lock(ctx->lock); + + /* + * CBC encryption requires the 2 last blocks to be aligned with AES + * block size. + */ + if (last_block && IS_CHAINING_MODE(CBC, ctx->cr) && + is_encrypt(ctx->cr) && + (ROUNDDOWN(data_size, AES_BLOCK_SIZE) != data_size)) { + if (data_size < AES_BLOCK_SIZE * 2) { + /* + * If CBC, size of the last part should be at + * least 2*AES_BLOCK_SIZE + */ + EMSG("Unexpected last block size"); + res = TEE_ERROR_BAD_STATE; + goto out; + } + /* + * Do not support padding if the total size is not aligned with + * the size of a block. + */ + res = TEE_ERROR_NOT_IMPLEMENTED; + goto out; + } + + /* Manage remaining CTR mask from previous update call */ + if (IS_CHAINING_MODE(CTR, ctx->cr) && ctx->extra_size) { + unsigned int j = 0; + uint8_t *mask = (uint8_t *)ctx->extra; + + for (i = 0, 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 >= AES_BLOCK_SIZE) { + write_block(ctx->base, data_in + i); + + res = wait_computation_completed(ctx->base); + if (res) + goto out; + + read_block(ctx->base, data_out + i); + + clear_computation_completed(ctx->base); + + /* Process next block */ + i += AES_BLOCK_SIZE; + } + + /* Manage last block if not a block size multiple */ + if (i < data_size) { + if (IS_CHAINING_MODE(CTR, ctx->cr)) { + /* + * For CTR we save the generated mask to use it at next + * update call. + */ + uint32_t block_in[AES_BLOCK_NB_U32] = { }; + uint32_t block_out[AES_BLOCK_NB_U32] = { }; + + memcpy(block_in, data_in + i, data_size - i); + + write_aligned_block(ctx->base, block_in); + + res = wait_computation_completed(ctx->base); + if (res) + goto out; + + read_aligned_block(ctx->base, block_out); + + clear_computation_completed(ctx->base); + + memcpy(data_out + i, block_out, data_size - i); + + /* Save mask for possibly next call */ + ctx->extra_size = AES_BLOCK_SIZE - (data_size - i); + memcpy(ctx->extra, (uint8_t *)block_out + data_size - i, + ctx->extra_size); + } else { + /* CBC and ECB can manage only multiple of block_size */ + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + } + + if (!last_block) + res = save_context(ctx); + +out: + /* If last block or error, end of SAES process */ + if (last_block || res) + saes_end(ctx, res); + + mutex_unlock(ctx->lock); + + return res; +} + +static void xor_block(uint8_t *b1, uint8_t *b2, size_t size) +{ + size_t i = 0; + + for (i = 0; i < size; i++) + b1[i] ^= b2[i]; +} + +static TEE_Result stm32_saes_cmac_prf_128(struct stm32_saes_context *ctx, + enum stm32_saes_key_selection key_sel, + const void *key, size_t key_size, + uint8_t *data, size_t data_size, + uint8_t *out) +{ + TEE_Result res = TEE_ERROR_GENERIC; + uint8_t block[AES_BLOCK_SIZE] = { }; + uint8_t k1[AES_BLOCK_SIZE] = { }; + uint8_t k2[AES_BLOCK_SIZE] = { }; + uint8_t l[AES_BLOCK_SIZE] = { }; + size_t processed = 0; + uint8_t bit = 0; + int i = 0; + + if (!ctx) + return TEE_ERROR_BAD_PARAMETERS; + + /* Get K1 and K2 */ + res = stm32_saes_init(ctx, false, STM32_SAES_MODE_ECB, key_sel, + key, key_size, NULL, 0); + if (res) + return res; + + res = stm32_saes_update(ctx, true, l, l, sizeof(l)); + if (res) + return res; + + /* MSB(L) == 0 => K1 = L << 1 */ + bit = 0; + for (i = sizeof(l) - 1; i >= 0; i--) { + k1[i] = (l[i] << 1) | bit; + bit = (l[i] & 0x80) >> 7; + } + /* MSB(L) == 1 => K1 = (L << 1) XOR const_Rb */ + if ((l[0] & 0x80)) + k1[sizeof(k1) - 1] = k1[sizeof(k1) - 1] ^ 0x87; + + /* MSB(K1) == 0 => K2 = K1 << 1 */ + bit = 0; + for (i = sizeof(k1) - 1; i >= 0; i--) { + k2[i] = (k1[i] << 1) | bit; + bit = (k1[i] & 0x80) >> 7; + } + + /* MSB(K1) == 1 => K2 = (K1 << 1) XOR const_Rb */ + if ((k1[0] & 0x80)) + k2[sizeof(k2) - 1] = k2[sizeof(k2) - 1] ^ 0x87; + + if (data_size > AES_BLOCK_SIZE) { + uint8_t *data_out = NULL; + + /* All block but last in CBC mode */ + res = stm32_saes_init(ctx, false, STM32_SAES_MODE_CBC, + key_sel, key, key_size, block, + sizeof(block)); + if (res) + return res; + + processed = ROUNDDOWN(data_size - 1, AES_BLOCK_SIZE); + data_out = malloc(processed); + if (!data_out) + return TEE_ERROR_OUT_OF_MEMORY; + + res = stm32_saes_update(ctx, true, data, data_out, processed); + if (!res) { + /* Copy last out block or keep block as { 0 } */ + memcpy(block, data_out + processed - AES_BLOCK_SIZE, + AES_BLOCK_SIZE); + } + + free(data_out); + + if (res) + return res; + } + + /* Manage last block */ + xor_block(block, data + processed, data_size - processed); + if (data_size - processed == AES_BLOCK_SIZE) { + xor_block(block, k1, AES_BLOCK_SIZE); + } else { + /* xor with padding = 0b100... */ + block[data_size - processed] ^= 0x80; + xor_block(block, k2, AES_BLOCK_SIZE); + } + + /* + * AES last block. + * We need to use same chaining mode to keep same key if DHUK is + * selected so we reuse l as a zero initialized IV. + */ + memset(l, 0, sizeof(l)); + res = stm32_saes_init(ctx, false, STM32_SAES_MODE_CBC, key_sel, key, + key_size, l, sizeof(l)); + if (res) + return res; + + return stm32_saes_update(ctx, true, block, out, AES_BLOCK_SIZE); +} + +TEE_Result stm32_saes_kdf(struct stm32_saes_context *ctx, + enum stm32_saes_key_selection key_sel, + const void *key, size_t key_size, + const void *input, size_t input_size, + uint8_t *subkey, size_t subkey_size) + +{ + TEE_Result res = TEE_SUCCESS; + uint32_t index = 0; + uint32_t index_be = 0; + uint8_t *data = NULL; + size_t data_index = 0; + size_t subkey_index = 0; + size_t data_size = input_size + sizeof(index_be); + uint8_t cmac[AES_BLOCK_SIZE] = { }; + + if (!ctx || !input || !input_size) + return TEE_ERROR_BAD_PARAMETERS; + + /* For each K(i) we will add an index */ + data = malloc(data_size); + if (!data) + return TEE_ERROR_OUT_OF_MEMORY; + + data_index = 0; + index_be = TEE_U32_TO_BIG_ENDIAN(index); + memcpy(data + data_index, &index_be, sizeof(index_be)); + data_index += sizeof(index_be); + memcpy(data + data_index, input, input_size); + data_index += input_size; + + /* K(i) computation. */ + index = 0; + while (subkey_index < subkey_size) { + index++; + index_be = TEE_U32_TO_BIG_ENDIAN(index); + memcpy(data, &index_be, sizeof(index_be)); + + res = stm32_saes_cmac_prf_128(ctx, key_sel, key, key_size, + data, data_size, cmac); + if (res) + goto out; + + memcpy(subkey + subkey_index, cmac, + MIN(subkey_size - subkey_index, sizeof(cmac))); + subkey_index += sizeof(cmac); + } + +out: + free(data); + if (res) + memzero_explicit(subkey, subkey_size); + + return res; +} + +/* Implement hardware HUK derivation using SAES resources */ +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) +{ + TEE_Result res = TEE_ERROR_GENERIC; + uint8_t *input = NULL; + size_t input_index = 0; + size_t subkey_bitlen = 0; + struct stm32_saes_context ctx = { }; + uint8_t separator = 0; + + /* Check if driver is probed */ + if (!saes_pdata.base) { + return __huk_subkey_derive(usage, const_data, const_data_len, + subkey, subkey_len); + } + + input = malloc(const_data_len + sizeof(separator) + sizeof(usage) + + sizeof(subkey_bitlen) + AES_BLOCK_SIZE); + if (!input) + return TEE_ERROR_OUT_OF_MEMORY; + + input_index = 0; + if (const_data) { + memcpy(input + input_index, const_data, const_data_len); + input_index += const_data_len; + + memcpy(input + input_index, &separator, sizeof(separator)); + input_index += sizeof(separator); + } + + memcpy(input + input_index, &usage, sizeof(usage)); + input_index += sizeof(usage); + + /* + * We should add the subkey_len in bits at end of input. + * And we choose to put in a MSB first uint32_t. + */ + subkey_bitlen = TEE_U32_TO_BIG_ENDIAN(subkey_len * INT8_BIT); + memcpy(input + input_index, &subkey_bitlen, sizeof(subkey_bitlen)); + input_index += sizeof(subkey_bitlen); + + /* + * We get K(0) to avoid some key control attack + * and store it at end of input. + */ + res = stm32_saes_cmac_prf_128(&ctx, STM32_SAES_KEY_DHU, NULL, + AES_KEYSIZE_128, + input, input_index, + input + input_index); + if (res) + goto out; + + /* We just added K(0) to input */ + input_index += AES_BLOCK_SIZE; + + res = stm32_saes_kdf(&ctx, STM32_SAES_KEY_DHU, NULL, AES_KEYSIZE_128, + input, input_index, subkey, subkey_len); + +out: + free(input); + return res; +} + +static TEE_Result stm32_saes_parse_fdt(struct stm32_saes_platdata *pdata, + const void *fdt, int node) +{ + struct dt_node_info dt_saes = { }; + TEE_Result res = TEE_ERROR_GENERIC; + + dt_saes.reg = fdt_reg_base_address(fdt, node); + dt_saes.reg_size = fdt_reg_size(fdt, node); + + if (dt_saes.reg == DT_INFO_INVALID_REG || + dt_saes.reg_size == DT_INFO_INVALID_REG_SIZE) + return TEE_ERROR_BAD_PARAMETERS; + + res = clk_dt_get_by_index(fdt, node, 0, &pdata->clk); + if (res != TEE_SUCCESS) + return res; + + res = rstctrl_dt_get_by_index(fdt, node, 0, &pdata->reset); + if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND) + return res; + + pdata->base = (vaddr_t)phys_to_virt(dt_saes.reg, MEM_AREA_IO_SEC, + dt_saes.reg_size); + if (!pdata->base) + panic(); + + return TEE_SUCCESS; +} + +static TEE_Result stm32_saes_probe(const void *fdt, int node, + const void *compat_data __unused) +{ + TEE_Result res = TEE_SUCCESS; + + assert(!saes_pdata.base); + + res = stm32_saes_parse_fdt(&saes_pdata, fdt, node); + if (res) + return res; + + if (clk_enable(saes_pdata.clk)) + panic(); + + if (saes_pdata.reset) { + /* External reset of SAES */ + if (rstctrl_assert_to(saes_pdata.reset, TIMEOUT_US_1MS)) + panic(); + + udelay(SAES_RESET_DELAY); + + if (rstctrl_deassert_to(saes_pdata.reset, TIMEOUT_US_1MS)) + panic(); + } else { + /* Internal reset of SAES */ + io_setbits32(saes_pdata.base + _SAES_CR, _SAES_CR_IPRST); + udelay(SAES_RESET_DELAY); + io_clrbits32(saes_pdata.base + _SAES_CR, _SAES_CR_IPRST); + } + + if (IS_ENABLED(CFG_CRYPTO_DRV_CIPHER)) { + res = stm32_register_cipher(SAES_IP); + if (res) { + EMSG("Failed to register to cipher: %#"PRIx32, res); + panic(); + } + } + + return TEE_SUCCESS; +} + +static const struct dt_device_match saes_match_table[] = { + { .compatible = "st,stm32mp13-saes" }, + { } +}; + +DEFINE_DT_DRIVER(stm32_saes_dt_driver) = { + .name = "stm32-saes", + .match_table = saes_match_table, + .probe = stm32_saes_probe, +}; diff --git a/optee/optee_os/core/drivers/crypto/stm32/stm32_saes.h b/optee/optee_os/core/drivers/crypto/stm32/stm32_saes.h new file mode 100644 index 0000000..8a35706 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/stm32/stm32_saes.h @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021-2023, STMicroelectronics - All Rights Reserved + */ + +#ifndef STM32_SAES_H +#define STM32_SAES_H + +#include +#include +#include +#include +#include +#include +#include + +enum stm32_saes_chaining_mode { + STM32_SAES_MODE_ECB, + STM32_SAES_MODE_CBC, + STM32_SAES_MODE_CTR, + STM32_SAES_MODE_GCM, + STM32_SAES_MODE_CCM, +}; + +enum stm32_saes_key_selection { + STM32_SAES_KEY_SOFT, + STM32_SAES_KEY_DHU, /* Derived HW unique key */ + STM32_SAES_KEY_BH, /* Boot HW key */ + STM32_SAES_KEY_BHU_XOR_BH, /* XOR of DHUK and BHK */ + STM32_SAES_KEY_WRAPPED +}; + +struct stm32_saes_context { + vaddr_t base; + uint32_t cr; + struct mutex *lock; /* Save the HW instance mutex */ + uint32_t assoc_len; + uint32_t load_len; + uint32_t key[8]; /* In HW byte order */ + uint32_t iv[4]; /* In HW byte order */ + uint32_t susp[8]; + uint32_t extra[4]; + size_t extra_size; +}; + +TEE_Result stm32_saes_init(struct stm32_saes_context *ctx, bool is_decrypt, + enum stm32_saes_chaining_mode ch_mode, + enum stm32_saes_key_selection key_select, + const void *key, size_t key_len, const void *iv, + size_t iv_len); +TEE_Result stm32_saes_update(struct stm32_saes_context *ctx, bool last_block, + uint8_t *data_in, uint8_t *data_out, + size_t data_len); +TEE_Result stm32_saes_update_assodata(struct stm32_saes_context *ctx, + uint8_t *data, size_t data_len); +TEE_Result stm32_saes_update_load(struct stm32_saes_context *ctx, + bool last_block, uint8_t *data_in, + uint8_t *data_out, size_t data_len); +TEE_Result stm32_saes_final(struct stm32_saes_context *ctx, uint8_t *tag, + size_t tag_len); + +TEE_Result stm32_saes_kdf(struct stm32_saes_context *ctx, + enum stm32_saes_key_selection key_sel, + const void *key, size_t key_size, + const void *input, size_t input_size, + uint8_t *subkey, size_t subkey_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..153e52c --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/stm32/sub.mk @@ -0,0 +1,4 @@ +srcs-$(CFG_STM32_CRYP) += stm32_cryp.c +srcs-$(CFG_STM32_SAES) += stm32_saes.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..71cb6bd --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/sub.mk @@ -0,0 +1,15 @@ +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 + +subdirs-$(CFG_HISILICON_CRYPTO_DRIVER) += hisilicon 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..64a919e --- /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..caea21e --- /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"); + } + } + /* 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/firewall/stm32_rif.c b/optee/optee_os/core/drivers/firewall/stm32_rif.c new file mode 100644 index 0000000..8721062 --- /dev/null +++ b/optee/optee_os/core/drivers/firewall/stm32_rif.c @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021-2024, STMicroelectronics + */ + +#include +#include +#include +#include +#include +#include + +#define MAX_CID_BITFIELD U(3) + +/** + * get_scid_mask() - Get the static CID mask according to the number of + * supported CIDs + * + * @nb_cid_supp: Number of CIDs supported. Cannot be 0. + */ +static uint32_t get_scid_mask(unsigned int nb_cid_supp) +{ + uint32_t msb_nb_cid_supp = 0; + + assert(nb_cid_supp); + + msb_nb_cid_supp = sizeof(nb_cid_supp) * 8 - + __builtin_clz((nb_cid_supp - 1) | 1); + + /* SCID bitfield highend can't be > SCID_SHIFT + MAX_CID_BITFIELD */ + assert(msb_nb_cid_supp <= MAX_CID_BITFIELD); + + return GENMASK_32(SCID_SHIFT + msb_nb_cid_supp - 1, SCID_SHIFT); +} + +TEE_Result stm32_rif_check_access(uint32_t cidcfgr, + uint32_t semcr, + unsigned int nb_cid_supp, + unsigned int cid_to_check) +{ + uint32_t scid_mask = get_scid_mask(nb_cid_supp); + + if (!(cidcfgr & _CIDCFGR_CFEN)) + return TEE_SUCCESS; + + if (stm32_rif_scid_ok(cidcfgr, scid_mask, cid_to_check)) + return TEE_SUCCESS; + + if (stm32_rif_semaphore_enabled_and_ok(cidcfgr, cid_to_check)) { + if (!(semcr & _SEMCR_MUTEX) || + ((semcr & scid_mask) >> SCID_SHIFT) == cid_to_check) { + return TEE_SUCCESS; + } + } + + return TEE_ERROR_ACCESS_DENIED; +} + +void stm32_rif_parse_cfg(uint32_t rif_conf, + struct rif_conf_data *conf_data, + unsigned int nb_cid_supp, + unsigned int nb_channel) +{ + uint32_t scid_mask = get_scid_mask(nb_cid_supp); + uint32_t cidcfdg_conf_mask = 0; + uint32_t channel_id = 0; + uint32_t semwl_mask = 0; + unsigned int conf_index = 0; + + semwl_mask = GENMASK_32(SEMWL_SHIFT + nb_cid_supp - 1, SEMWL_SHIFT); + + cidcfdg_conf_mask = scid_mask | semwl_mask | _CIDCFGR_CFEN | + _CIDCFGR_SEMEN; + + /* Shift corresponding to the desired resources */ + channel_id = RIF_CHANNEL_ID(rif_conf); + if (channel_id >= nb_channel) + panic("Bad RIF controllers number"); + + /* Some peripherals have more than 32 RIF channels */ + conf_index = channel_id / 32; + + /* Privilege configuration */ + if (rif_conf & RIFPROT_PRIV) + conf_data->priv_conf[conf_index] |= BIT(channel_id); + + /* Security RIF configuration */ + if (rif_conf & RIFPROT_SEC) + conf_data->sec_conf[conf_index] |= BIT(channel_id); + + /* RIF configuration lock */ + if (rif_conf & RIFPROT_LOCK && conf_data->lock_conf) + conf_data->lock_conf[conf_index] |= BIT(channel_id); + + /* CID configuration */ + conf_data->cid_confs[channel_id] = rif_conf & cidcfdg_conf_mask; + + /* Store that this RIF resource is to be configured */ + conf_data->access_mask[conf_index] |= BIT(channel_id); +} + +bool stm32_rif_semaphore_is_available(vaddr_t addr) +{ + return !(io_read32(addr) & _SEMCR_MUTEX); +} + +TEE_Result stm32_rif_acquire_semaphore(vaddr_t addr, unsigned int nb_cid_supp) +{ + uint32_t scid_mask = get_scid_mask(nb_cid_supp); + + /* Take the semaphore */ + io_setbits32(addr, _SEMCR_MUTEX); + + /* Check that the Cortex-A has the semaphore */ + if (stm32_rif_semaphore_is_available(addr) || + ((io_read32(addr) & scid_mask) >> SCID_SHIFT) != RIF_CID1) + return TEE_ERROR_ACCESS_DENIED; + + return TEE_SUCCESS; +} + +TEE_Result stm32_rif_release_semaphore(vaddr_t addr, unsigned int nb_cid_supp) +{ + uint32_t scid_mask = get_scid_mask(nb_cid_supp); + + if (stm32_rif_semaphore_is_available(addr)) + return TEE_SUCCESS; + + /* Release the semaphore */ + io_clrbits32(addr, _SEMCR_MUTEX); + + /* Check that current compartment no more owns the semaphore */ + if (!stm32_rif_semaphore_is_available(addr) && + ((io_read32(addr) & scid_mask) >> SCID_SHIFT) == RIF_CID1) + return TEE_ERROR_ACCESS_DENIED; + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/drivers/firewall/stm32_rifsc.c b/optee/optee_os/core/drivers/firewall/stm32_rifsc.c new file mode 100644 index 0000000..7c1b5a6 --- /dev/null +++ b/optee/optee_os/core/drivers/firewall/stm32_rifsc.c @@ -0,0 +1,561 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021-2024, STMicroelectronics + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* RIFSC offset register */ +#define _RIFSC_RISC_SECCFGR0 U(0x10) +#define _RIFSC_RISC_PRIVCFGR0 U(0x30) +#define _RIFSC_RISC_RCFGLOCKR0 U(0x50) +#define _RIFSC_RISC_PER0_CIDCFGR U(0x100) +#define _RIFSC_RISC_PER0_SEMCR U(0x104) +#define _RIFSC_RIMC_CR U(0xC00) +#define _RIFSC_RIMC_ATTR0 U(0xC10) + +#define _RIFSC_HWCFGR3 U(0xFE8) +#define _RIFSC_HWCFGR2 U(0xFEC) +#define _RIFSC_HWCFGR1 U(0xFF0) +#define _RIFSC_VERR U(0xFF4) + +/* RIFSC_HWCFGR2 register fields */ +#define _RIFSC_HWCFGR2_CFG1_MASK GENMASK_32(15, 0) +#define _RIFSC_HWCFGR2_CFG1_SHIFT U(0) +#define _RIFSC_HWCFGR2_CFG2_MASK GENMASK_32(23, 16) +#define _RIFSC_HWCFGR2_CFG2_SHIFT U(16) +#define _RIFSC_HWCFGR2_CFG3_MASK GENMASK_32(31, 24) +#define _RIFSC_HWCFGR2_CFG3_SHIFT U(24) + +/* RIFSC_HWCFGR1 register fields */ +#define _RIFSC_HWCFGR1_CFG1_MASK GENMASK_32(3, 0) +#define _RIFSC_HWCFGR1_CFG1_SHIFT U(0) +#define _RIFSC_HWCFGR1_CFG2_MASK GENMASK_32(7, 4) +#define _RIFSC_HWCFGR1_CFG2_SHIFT U(4) +#define _RIFSC_HWCFGR1_CFG3_MASK GENMASK_32(11, 8) +#define _RIFSC_HWCFGR1_CFG3_SHIFT U(8) +#define _RIFSC_HWCFGR1_CFG4_MASK GENMASK_32(15, 12) +#define _RIFSC_HWCFGR1_CFG4_SHIFT U(12) +#define _RIFSC_HWCFGR1_CFG5_MASK GENMASK_32(19, 16) +#define _RIFSC_HWCFGR1_CFG5_SHIFT U(16) +#define _RIFSC_HWCFGR1_CFG6_MASK GENMASK_32(23, 20) +#define _RIFSC_HWCFGR1_CFG6_SHIFT U(20) + +/* + * RISC_CR register fields + */ +#define _RIFSC_RISC_CR_GLOCK BIT(0) + +/* + * RIMC_CR register fields + */ +#define _RIFSC_RIMC_CR_GLOCK BIT(0) +#define _RIFSC_RIMC_CR_TDCID_MASK GENMASK_32(6, 4) + +/* RIFSC_VERR register fields */ +#define _RIFSC_VERR_MINREV_MASK GENMASK_32(3, 0) +#define _RIFSC_VERR_MINREV_SHIFT U(0) +#define _RIFSC_VERR_MAJREV_MASK GENMASK_32(7, 4) +#define _RIFSC_VERR_MAJREV_SHIFT U(4) + +/* Periph id per register */ +#define _PERIPH_IDS_PER_REG U(32) +#define _OFFSET_PERX_CIDCFGR U(0x8) + +#define RIFSC_RISC_CFEN_MASK BIT(0) +#define RIFSC_RISC_SEM_EN_MASK BIT(1) +#define RIFSC_RISC_SCID_MASK GENMASK_32(6, 4) +#define RIFSC_RISC_SEC_MASK BIT(8) +#define RIFSC_RISC_PRIV_MASK BIT(9) +#define RIFSC_RISC_LOCK_MASK BIT(10) +#define RIFSC_RISC_SEML_MASK GENMASK_32(23, 16) +#define RIFSC_RISC_PER_ID_MASK GENMASK_32(31, 24) + +#define RIFSC_RISC_PERx_CID_MASK (RIFSC_RISC_CFEN_MASK | \ + RIFSC_RISC_SEM_EN_MASK | \ + RIFSC_RISC_SCID_MASK | \ + RIFSC_RISC_SEML_MASK) + +#define RIFSC_RIMC_MODE_MASK BIT(2) +#define RIFSC_RIMC_MCID_MASK GENMASK_32(6, 4) +#define RIFSC_RIMC_MSEC_MASK BIT(8) +#define RIFSC_RIMC_MPRIV_MASK BIT(9) +#define RIFSC_RIMC_M_ID_MASK GENMASK_32(23, 16) + +#define RIFSC_RIMC_ATTRx_MASK (RIFSC_RIMC_MODE_MASK | \ + RIFSC_RIMC_MCID_MASK | \ + RIFSC_RIMC_MSEC_MASK | \ + RIFSC_RIMC_MPRIV_MASK) + +/* max entries */ +#define MAX_RIMU U(16) +#define MAX_RISUP U(128) + +#define _RIF_FLD_GET(field, value) (((uint32_t)(value) & \ + (field ## _MASK)) >>\ + (field ## _SHIFT)) + +struct risup_cfg { + uint32_t cid_attr; + uint32_t id; + bool sec; + bool priv; + bool lock; + bool pm_sem; +}; + +struct rimu_cfg { + uint32_t id; + uint32_t attr; +}; + +struct rifsc_driver_data { + bool rif_en; + bool sec_en; + bool priv_en; + uint8_t nb_rimu; + uint8_t nb_risup; + uint8_t nb_risal; + uint8_t version; +}; + +struct rifsc_platdata { + uintptr_t base; + struct rifsc_driver_data *drv_data; + struct risup_cfg *risup; + unsigned int nrisup; + struct rimu_cfg *rimu; + unsigned int nrimu; +}; + +/* There is only 1 instance of the RIFSC subsystem */ +static struct rifsc_driver_data rifsc_drvdata; +static struct rifsc_platdata rifsc_pdata; + +static void stm32_rifsc_get_driverdata(struct rifsc_platdata *pdata) +{ + uint32_t regval = 0; + + regval = io_read32(pdata->base + _RIFSC_HWCFGR1); + rifsc_drvdata.rif_en = _RIF_FLD_GET(_RIFSC_HWCFGR1_CFG1, regval) != 0; + rifsc_drvdata.sec_en = _RIF_FLD_GET(_RIFSC_HWCFGR1_CFG2, regval) != 0; + rifsc_drvdata.priv_en = _RIF_FLD_GET(_RIFSC_HWCFGR1_CFG3, regval) != 0; + + regval = io_read32(pdata->base + _RIFSC_HWCFGR2); + rifsc_drvdata.nb_risup = _RIF_FLD_GET(_RIFSC_HWCFGR2_CFG1, regval); + rifsc_drvdata.nb_rimu = _RIF_FLD_GET(_RIFSC_HWCFGR2_CFG2, regval); + rifsc_drvdata.nb_risal = _RIF_FLD_GET(_RIFSC_HWCFGR2_CFG3, regval); + + pdata->drv_data = &rifsc_drvdata; + + rifsc_drvdata.version = io_read8(pdata->base + _RIFSC_VERR); + + DMSG("RIFSC version %"PRIu32".%"PRIu32, + _RIF_FLD_GET(_RIFSC_VERR_MAJREV, rifsc_drvdata.version), + _RIF_FLD_GET(_RIFSC_VERR_MINREV, rifsc_drvdata.version)); + + DMSG("HW cap: enabled[rif:sec:priv]:[%s:%s:%s] nb[risup|rimu|risal]:[%"PRIu8",%"PRIu8",%"PRIu8"]", + rifsc_drvdata.rif_en ? "true" : "false", + rifsc_drvdata.sec_en ? "true" : "false", + rifsc_drvdata.priv_en ? "true" : "false", + rifsc_drvdata.nb_risup, + rifsc_drvdata.nb_rimu, + rifsc_drvdata.nb_risal); +} + +static TEE_Result stm32_rifsc_glock_config(const void *fdt, int node, + struct rifsc_platdata *pdata) +{ + const fdt32_t *cuint = NULL; + uint32_t glock_conf = 0; + int len = 0; + + cuint = fdt_getprop(fdt, node, "st,glocked", &len); + if (!cuint) { + DMSG("No global lock on RIF configuration"); + return TEE_SUCCESS; + } + assert(len == sizeof(uint32_t)); + + glock_conf = fdt32_to_cpu(*cuint); + + if (glock_conf & RIFSC_RIMU_GLOCK) { + DMSG("Setting global lock on RIMU configuration"); + + io_setbits32(pdata->base + _RIFSC_RIMC_CR, + _RIFSC_RIMC_CR_GLOCK); + + if (!(io_read32(pdata->base + _RIFSC_RIMC_CR) & + _RIFSC_RIMC_CR_GLOCK)) + return TEE_ERROR_ACCESS_DENIED; + } + + if (glock_conf & RIFSC_RISUP_GLOCK) { + DMSG("Setting global lock on RISUP configuration"); + + io_setbits32(pdata->base, _RIFSC_RISC_CR_GLOCK); + + if (!(io_read32(pdata->base) & _RIFSC_RISC_CR_GLOCK)) + return TEE_ERROR_ACCESS_DENIED; + } + + return TEE_SUCCESS; +} + +static TEE_Result stm32_rifsc_dt_conf_risup(const void *fdt, int node, + struct rifsc_platdata *pdata) +{ + const fdt32_t *conf_list = NULL; + unsigned int i = 0; + int len = 0; + + conf_list = fdt_getprop(fdt, node, "st,protreg", &len); + if (!conf_list) { + DMSG("No RISUP configuration in DT"); + return TEE_ERROR_ITEM_NOT_FOUND; + } + assert(!(len % sizeof(uint32_t))); + + pdata->nrisup = len / sizeof(uint32_t); + pdata->risup = calloc(pdata->nrisup, sizeof(*pdata->risup)); + if (!pdata->risup) + return TEE_ERROR_OUT_OF_MEMORY; + + for (i = 0; i < pdata->nrisup; i++) { + uint32_t value = fdt32_to_cpu(conf_list[i]); + struct risup_cfg *risup = pdata->risup + i; + + risup->id = _RIF_FLD_GET(RIFSC_RISC_PER_ID, value); + risup->sec = _RIF_FLD_GET(RIFSC_RISC_SEC, value) != 0; + risup->priv = _RIF_FLD_GET(RIFSC_RISC_PRIV, value) != 0; + risup->lock = _RIF_FLD_GET(RIFSC_RISC_LOCK, value) != 0; + risup->cid_attr = _RIF_FLD_GET(RIFSC_RISC_PERx_CID, value); + } + + return TEE_SUCCESS; +} + +static TEE_Result stm32_rifsc_dt_conf_rimu(const void *fdt, int node, + struct rifsc_platdata *pdata) +{ + const fdt32_t *conf_list = NULL; + unsigned int i = 0; + int len = 0; + + conf_list = fdt_getprop(fdt, node, "st,rimu", &len); + if (!conf_list) { + DMSG("No RIMU configuration in DT"); + return TEE_ERROR_ITEM_NOT_FOUND; + } + assert(!(len % sizeof(uint32_t))); + + pdata->nrimu = len / sizeof(uint32_t); + pdata->rimu = calloc(pdata->nrimu, sizeof(*pdata->rimu)); + if (!pdata->rimu) + return TEE_ERROR_OUT_OF_MEMORY; + + for (i = 0; i < pdata->nrimu; i++) { + uint32_t value = fdt32_to_cpu(*conf_list); + struct rimu_cfg *rimu = pdata->rimu + i; + + rimu->id = _RIF_FLD_GET(RIFSC_RIMC_M_ID, value); + rimu->attr = _RIF_FLD_GET(RIFSC_RIMC_ATTRx, value); + } + + return TEE_SUCCESS; +} + +static TEE_Result stm32_rifsc_parse_fdt(const void *fdt, int node, + struct rifsc_platdata *pdata) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct io_pa_va base = { }; + size_t reg_size = 0; + + base.pa = fdt_reg_base_address(fdt, node); + if (base.pa == DT_INFO_INVALID_REG) + return TEE_ERROR_BAD_PARAMETERS; + + reg_size = fdt_reg_size(fdt, node); + if (reg_size == DT_INFO_INVALID_REG_SIZE) + return TEE_ERROR_BAD_PARAMETERS; + + pdata->base = io_pa_or_va_secure(&base, reg_size); + + res = stm32_rifsc_dt_conf_risup(fdt, node, pdata); + if (res) + return res; + + return stm32_rifsc_dt_conf_rimu(fdt, node, pdata); +} + +static TEE_Result stm32_risup_cfg(struct rifsc_platdata *pdata, + struct risup_cfg *risup) +{ + uintptr_t offset = sizeof(uint32_t) * (risup->id / _PERIPH_IDS_PER_REG); + uintptr_t cidcfgr_offset = _OFFSET_PERX_CIDCFGR * risup->id; + struct rifsc_driver_data *drv_data = pdata->drv_data; + uint32_t shift = risup->id % _PERIPH_IDS_PER_REG; + TEE_Result res = TEE_ERROR_GENERIC; + + if (!risup || risup->id >= drv_data->nb_risup) + return TEE_ERROR_BAD_PARAMETERS; + + if (drv_data->sec_en) + io_clrsetbits32(pdata->base + _RIFSC_RISC_SECCFGR0 + offset, + BIT(shift), SHIFT_U32(risup->sec, shift)); + + if (drv_data->priv_en) + io_clrsetbits32(pdata->base + _RIFSC_RISC_PRIVCFGR0 + offset, + BIT(shift), SHIFT_U32(risup->priv, shift)); + + if (drv_data->rif_en) + io_write32(pdata->base + _RIFSC_RISC_PER0_CIDCFGR + + cidcfgr_offset, risup->cid_attr); + + /* Lock configuration for this RISUP */ + if (risup->lock) { + DMSG("Locking RIF conf for peripheral %"PRIu32, risup->id); + io_setbits32(pdata->base + _RIFSC_RISC_RCFGLOCKR0 + offset, + BIT(shift)); + } + + /* Take semaphore if the resource is in semaphore mode and secured */ + if (!stm32_rif_semaphore_enabled_and_ok(risup->cid_attr, RIF_CID1) || + !(io_read32(pdata->base + _RIFSC_RISC_SECCFGR0 + offset) & + BIT(shift))) { + res = stm32_rif_release_semaphore(pdata->base + + _RIFSC_RISC_PER0_SEMCR + + cidcfgr_offset, + MAX_CID_SUPPORTED); + if (res) { + EMSG("Couldn't release semaphore for resource %"PRIu32, + risup->id); + return TEE_ERROR_ACCESS_DENIED; + } + } else { + res = stm32_rif_acquire_semaphore(pdata->base + + _RIFSC_RISC_PER0_SEMCR + + cidcfgr_offset, + MAX_CID_SUPPORTED); + if (res) { + EMSG("Couldn't acquire semaphore for resource %"PRIu32, + risup->id); + return TEE_ERROR_ACCESS_DENIED; + } + } + + return TEE_SUCCESS; +} + +static TEE_Result stm32_risup_setup(struct rifsc_platdata *pdata) +{ + struct rifsc_driver_data *drv_data = pdata->drv_data; + TEE_Result res = TEE_ERROR_GENERIC; + unsigned int i = 0; + + for (i = 0; i < pdata->nrisup && i < drv_data->nb_risup; i++) { + struct risup_cfg *risup = pdata->risup + i; + + res = stm32_risup_cfg(pdata, risup); + if (res) { + EMSG("risup cfg(%d/%d) error", i + 1, pdata->nrisup); + return res; + } + } + + return TEE_SUCCESS; +} + +static TEE_Result stm32_rimu_cfg(struct rifsc_platdata *pdata, + struct rimu_cfg *rimu) +{ + uintptr_t offset = _RIFSC_RIMC_ATTR0 + (sizeof(uint32_t) * rimu->id); + struct rifsc_driver_data *drv_data = pdata->drv_data; + + if (!rimu || rimu->id >= drv_data->nb_rimu) + return TEE_ERROR_BAD_PARAMETERS; + + if (drv_data->rif_en) + io_write32(pdata->base + offset, rimu->attr); + + return TEE_SUCCESS; +} + +static TEE_Result stm32_rimu_setup(struct rifsc_platdata *pdata) +{ + struct rifsc_driver_data *drv_data = pdata->drv_data; + TEE_Result res = TEE_ERROR_GENERIC; + unsigned int i = 0; + + for (i = 0; i < pdata->nrimu && i < drv_data->nb_rimu; i++) { + struct rimu_cfg *rimu = pdata->rimu + i; + + res = stm32_rimu_cfg(pdata, rimu); + if (res) { + EMSG("rimu cfg(%d/%d) error", i + 1, pdata->nrimu); + return res; + } + } + + return TEE_SUCCESS; +} + +static TEE_Result stm32_rifsc_sem_pm_suspend(void) +{ + unsigned int i = 0; + + for (i = 0; i < rifsc_pdata.nrisup && i < rifsc_drvdata.nb_risup; i++) { + uint32_t semcfgr = io_read32(rifsc_pdata.base + + _RIFSC_RISC_PER0_SEMCR + + _OFFSET_PERX_CIDCFGR * i); + struct risup_cfg *risup = rifsc_pdata.risup + i; + + /* Save semaphores that were taken by the CID1 */ + risup->pm_sem = semcfgr & _SEMCR_MUTEX && + ((semcfgr & _SEMCR_SEMCID_MASK) >> + _SEMCR_SEMCID_SHIFT) == RIF_CID1; + + FMSG("RIF semaphore %s for ID: %"PRIu32, + risup->pm_sem ? "SAVED" : "NOT SAVED", risup->id); + } + + return TEE_SUCCESS; +} + +static TEE_Result stm32_rifsc_sem_pm_resume(void) +{ + TEE_Result res = TEE_ERROR_GENERIC; + unsigned int i = 0; + + for (i = 0; i < rifsc_pdata.nrisup && i < rifsc_drvdata.nb_risup; i++) { + struct risup_cfg *risup = rifsc_pdata.risup + i; + uintptr_t cidcfgr_offset = _OFFSET_PERX_CIDCFGR * risup->id; + uintptr_t offset = sizeof(uint32_t) * + (risup->id / _PERIPH_IDS_PER_REG); + uintptr_t perih_offset = risup->id % _PERIPH_IDS_PER_REG; + uint32_t seccgfr = io_read32(rifsc_pdata.base + + _RIFSC_RISC_SECCFGR0 + offset); + uint32_t privcgfr = io_read32(rifsc_pdata.base + + _RIFSC_RISC_PRIVCFGR0 + offset); + uint32_t lockcfgr = io_read32(rifsc_pdata.base + + _RIFSC_RISC_RCFGLOCKR0 + offset); + + /* Update RISUPs fields */ + risup->cid_attr = io_read32(rifsc_pdata.base + + _RIFSC_RISC_PER0_CIDCFGR + + cidcfgr_offset); + risup->sec = (seccgfr & BIT(perih_offset)) != 0; + risup->priv = (privcgfr & BIT(perih_offset)) != 0; + risup->lock = (lockcfgr & BIT(perih_offset)) != 0; + + /* Acquire available appropriate semaphores */ + if (!stm32_rif_semaphore_enabled_and_ok(risup->cid_attr, + RIF_CID1) || + !risup->pm_sem) + continue; + + res = stm32_rif_acquire_semaphore(rifsc_pdata.base + + _RIFSC_RISC_PER0_SEMCR + + cidcfgr_offset, + MAX_CID_SUPPORTED); + if (res) { + EMSG("Could not acquire semaphore for resource %"PRIu32, + risup->id); + return TEE_ERROR_ACCESS_DENIED; + } + } + + return TEE_SUCCESS; +} + +static TEE_Result +stm32_rifsc_sem_pm(enum pm_op op, unsigned int pm_hint, + const struct pm_callback_handle *pm_handle __unused) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + if (pm_hint != PM_HINT_CONTEXT_STATE) + return TEE_SUCCESS; + + if (op == PM_OP_RESUME) + res = stm32_rifsc_sem_pm_resume(); + else + res = stm32_rifsc_sem_pm_suspend(); + + return res; +} + +TEE_Result stm32_rifsc_check_tdcid(bool *tdcid_state) +{ + if (!rifsc_pdata.base) + return TEE_ERROR_DEFER_DRIVER_INIT; + + if (((io_read32(rifsc_pdata.base + _RIFSC_RIMC_CR) & + _RIFSC_RIMC_CR_TDCID_MASK)) == (RIF_CID1 << SCID_SHIFT)) + *tdcid_state = true; + else + *tdcid_state = false; + + return TEE_SUCCESS; +} + +static TEE_Result stm32_rifsc_probe(const void *fdt, int node, + const void *compat_data __unused) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + res = stm32_rifsc_parse_fdt(fdt, node, &rifsc_pdata); + if (res) { + EMSG("Could not parse RIFSC node, res = %#"PRIx32, res); + panic(); + } + + if (!rifsc_pdata.drv_data) + stm32_rifsc_get_driverdata(&rifsc_pdata); + + res = stm32_risup_setup(&rifsc_pdata); + if (res) { + EMSG("Could not setup RISUPs, res = %#"PRIx32, res); + panic(); + } + + res = stm32_rimu_setup(&rifsc_pdata); + if (res) { + EMSG("Could not setup RIMUs, res = %#"PRIx32, res); + panic(); + } + + res = stm32_rifsc_glock_config(fdt, node, &rifsc_pdata); + if (res) + panic("Couldn't lock RIFSC configuration"); + + register_pm_core_service_cb(stm32_rifsc_sem_pm, NULL, + "stm32-rifsc-semaphores"); + + return TEE_SUCCESS; +} + +static const struct dt_device_match rifsc_match_table[] = { + { .compatible = "st,stm32mp25-rifsc" }, + { } +}; + +DEFINE_DT_DRIVER(rifsc_dt_driver) = { + .name = "stm32-rifsc", + .match_table = rifsc_match_table, + .probe = stm32_rifsc_probe, +}; diff --git a/optee/optee_os/core/drivers/firewall/sub.mk b/optee/optee_os/core/drivers/firewall/sub.mk new file mode 100644 index 0000000..ba217a6 --- /dev/null +++ b/optee/optee_os/core/drivers/firewall/sub.mk @@ -0,0 +1,2 @@ +srcs-$(CFG_STM32_RIF) += stm32_rif.c +srcs-$(CFG_STM32_RIFSC) += stm32_rifsc.c diff --git a/optee/optee_os/core/drivers/gic.c b/optee/optee_os/core/drivers/gic.c new file mode 100644 index 0000000..a1d9766 --- /dev/null +++ b/optee/optee_os/core/drivers/gic.c @@ -0,0 +1,1079 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016-2017, 2023-2024 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 + +/* 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 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) + +#ifdef CFG_ARM_GICV3 +#define GICD_PIDR2 (0xFFE8) +#else +/* Called ICPIDR2 in GICv2 specification */ +#define GICD_PIDR2 (0xFE8) +#endif + +#define GICD_CTLR_ENABLEGRP0 BIT32(0) +#define GICD_CTLR_ENABLEGRP1NS BIT32(1) +#define GICD_CTLR_ENABLEGRP1S BIT32(2) +#define GICD_CTLR_ARE_S BIT32(4) +#define GICD_CTLR_ARE_NS BIT32(5) + +/* Offsets from gic.gicr_base[core_pos] */ +#define GICR_V3_PCPUBASE_SIZE (2 * 64 * 1024) +#define GICR_SGI_BASE_OFFSET (64 * 1024) +#define GICR_CTLR (0x00) +#define GICR_TYPER (0x08) + +#define GICR_IGROUPR0 (GICR_SGI_BASE_OFFSET + 0x080) +#define GICR_IGRPMODR0 (GICR_SGI_BASE_OFFSET + 0xD00) +#define GICR_ICENABLER0 (GICR_SGI_BASE_OFFSET + 0x180) +#define GICR_ICPENDR0 (GICR_SGI_BASE_OFFSET + 0x280) +#define GICR_ISENABLER0 (GICR_SGI_BASE_OFFSET + 0x100) +#define GICR_ICFGR0 (GICR_SGI_BASE_OFFSET + 0xC00) +#define GICR_ICFGR1 (GICR_SGI_BASE_OFFSET + 0xC04) +#define GICR_IPRIORITYR(n) (GICR_SGI_BASE_OFFSET + 0x400 + (n) * 4) + +#define GICR_CTLR_RWP BIT32(3) + +#define GICR_TYPER_LAST BIT64(4) +#define GICR_TYPER_AFF3_SHIFT 56 +#define GICR_TYPER_AFF2_SHIFT 48 +#define GICR_TYPER_AFF1_SHIFT 40 +#define GICR_TYPER_AFF0_SHIFT 32 + +/* GICD IDR2 name differs on GICv3 and GICv2 but uses same bit map */ +#define GICD_PIDR2_ARCHREV_SHIFT 4 +#define GICD_PIDR2_ARCHREV_MASK 0xF + +/* 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 + +#define GICD_TYPER_IT_LINES_NUM_MASK 0x1f +#define GICC_IAR_IT_ID_MASK 0x3ff +#define GICC_IAR_CPU_ID_MASK 0x7 +#define GICC_IAR_CPU_ID_SHIFT 10 + +#define GICC_SGI_IRM_BIT 40 +#define GICC_SGI_AFF1_SHIFT 16 +#define GICC_SGI_AFF2_SHIFT 32 +#define GICC_SGI_AFF3_SHIFT 48 + +#define GICD_SGIR_SIGINTID_MASK 0xf +#define GICD_SGIR_TO_OTHER_CPUS 0x1 +#define GICD_SGIR_TO_THIS_CPU 0x2 +#define GICD_SGIR_TARGET_LIST_FILTER_SHIFT 24 +#define GICD_SGIR_NSATT_SHIFT 15 +#define GICD_SGIR_CPU_TARGET_LIST_SHIFT 16 + +struct gic_data { + vaddr_t gicc_base; + vaddr_t gicd_base; +#if defined(CFG_ARM_GICV3) + vaddr_t gicr_base[CFG_TEE_CORE_NB_CORE]; +#endif + size_t max_it; + uint32_t per_cpu_group_status; + uint32_t per_cpu_group_modifier; + uint32_t per_cpu_enable; + struct itr_chip chip; +}; + +static bool gic_primary_done __nex_bss; +static struct gic_data gic_data __nex_bss; + +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, + uint32_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, + .mask = gic_op_disable, + .unmask = gic_op_enable, + .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 vaddr_t __maybe_unused get_gicr_base(struct gic_data *gd __maybe_unused) +{ +#if defined(CFG_ARM_GICV3) + return gd->gicr_base[get_core_pos()]; +#else + return 0; +#endif +} + +static bool affinity_routing_is_enabled(struct gic_data *gd) +{ + return IS_ENABLED(CFG_ARM_GICV3) && + io_read32(gd->gicd_base + GICD_CTLR) & GICD_CTLR_ARE_S; +} + +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; + size_t max_regs = io_read32(gicd_base + GICD_TYPER) & + GICD_TYPER_IT_LINES_NUM_MASK; + + /* + * 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; +} + +static void gicr_wait_for_pending_write(vaddr_t gicr_base) +{ + /* + * Wait for changes to + * - GICR_ICENABLER0 + * - GICR_CTLR.DPG1S + * - GICR_CTLR.DPG1NS + * - GICR_CTLR.DPG0 + * to be visible to all agents in the system. + */ + while (io_read32(gicr_base + GICR_CTLR) & GICR_CTLR_RWP) + ; +} + +static void gicv3_sync_redist_config(struct gic_data *gd) +{ + vaddr_t gicr_base = get_gicr_base(gd); + bool need_sync = false; + uint32_t gmod0 = 0; + uint32_t grp0 = 0; + size_t n = 0; + + /* + * If gicr_base isn't available there's no need to synchronize SGI + * configuration since gic_init_donate_sgi_to_ns() would panic. + */ + if (!gicr_base) + return; + + grp0 = io_read32(gicr_base + GICR_IGROUPR0); + gmod0 = io_read32(gicr_base + GICR_IGRPMODR0); + for (n = GIC_SGI_SEC_BASE; n < GIC_SPI_BASE; n++) { + /* Ignore matching bits */ + if (!(BIT32(n) & (grp0 ^ gd->per_cpu_group_status)) && + !(BIT32(n) & (gmod0 ^ gd->per_cpu_group_modifier))) + continue; + /* + * SGI/PPI-n differs from primary CPU configuration, + * let's sync up. + */ + need_sync = true; + + /* Disable interrupt */ + io_write32(gicr_base + GICR_ICENABLER0, BIT32(n)); + + /* Wait for the write to GICR_ICENABLER0 to propagate */ + gicr_wait_for_pending_write(gicr_base); + + /* Make interrupt non-pending */ + io_write32(gicr_base + GICR_ICPENDR0, BIT32(n)); + + if (BIT32(n) & gd->per_cpu_group_status) + grp0 |= BIT32(n); + else + grp0 &= ~BIT32(n); + if (BIT32(n) & gd->per_cpu_group_modifier) + gmod0 |= BIT32(n); + else + gmod0 &= ~BIT32(n); + } + + if (need_sync) { + io_write32(gicr_base + GICR_IGROUPR0, grp0); + io_write32(gicr_base + GICR_IGRPMODR0, gmod0); + io_write32(gicr_base + GICR_ISENABLER0, gd->per_cpu_enable); + } +} + +static void gic_legacy_sync_dist_config(struct gic_data *gd) +{ + bool need_sync = false; + uint32_t grp0 = 0; + size_t n = 0; + + grp0 = io_read32(gd->gicd_base + GICD_IGROUPR(0)); + for (n = GIC_SGI_SEC_BASE; n < GIC_SPI_BASE; n++) { + /* Ignore matching bits */ + if (!(BIT32(n) & (grp0 ^ gd->per_cpu_group_status))) + continue; + /* + * SGI/PPI-n differs from primary CPU configuration, + * let's sync up. + */ + need_sync = true; + + /* Disable interrupt */ + io_write32(gd->gicd_base + GICD_ICENABLER(0), BIT(n)); + + /* Make interrupt non-pending */ + io_write32(gd->gicd_base + GICD_ICPENDR(0), BIT(n)); + + if (BIT32(n) & gd->per_cpu_group_status) + grp0 |= BIT32(n); + else + grp0 &= ~BIT32(n); + } + + if (need_sync) { + io_write32(gd->gicd_base + GICD_IGROUPR(0), grp0); + io_write32(gd->gicd_base + GICD_ISENABLER(0), + gd->per_cpu_enable); + } +} + +static void init_gic_per_cpu(struct gic_data *gd) +{ + io_write32(gd->gicd_base + GICD_IGROUPR(0), gd->per_cpu_group_status); + + /* + * 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_per_cpu(void) +{ + struct gic_data *gd = &gic_data; + +#if defined(CFG_ARM_GICV3) + assert(gd->gicd_base); +#else + assert(gd->gicd_base && gd->gicc_base); +#endif + + if (IS_ENABLED(CFG_WITH_ARM_TRUSTED_FW)) { + /* + * GIC is already initialized by TF-A, we only need to + * handle eventual SGI or PPI configuration changes. + */ + if (affinity_routing_is_enabled(gd)) + gicv3_sync_redist_config(gd); + else + gic_legacy_sync_dist_config(gd); + } else { + /* + * Non-TF-A case where all CPU specific configuration + * of GIC must be done here. + */ + init_gic_per_cpu(gd); + } +} + +void gic_init_donate_sgi_to_ns(size_t it) +{ + struct gic_data *gd = &gic_data; + + assert(it >= GIC_SGI_SEC_BASE && it <= GIC_SGI_SEC_MAX); + + /* Assert it's secure to start with. */ + assert(!(gd->per_cpu_group_status & BIT32(it)) && + (gd->per_cpu_group_modifier & BIT32(it))); + + gd->per_cpu_group_modifier &= ~BIT32(it); + gd->per_cpu_group_status |= BIT32(it); + + if (affinity_routing_is_enabled(gd)) { + vaddr_t gicr_base = get_gicr_base(gd); + + if (!gicr_base) + panic("GICR_BASE missing"); + + /* Disable interrupt */ + io_write32(gicr_base + GICR_ICENABLER0, BIT32(it)); + + /* Wait for the write to GICR_ICENABLER0 to propagate */ + gicr_wait_for_pending_write(gicr_base); + + /* Make interrupt non-pending */ + io_write32(gicr_base + GICR_ICPENDR0, BIT32(it)); + + /* Make it to non-secure */ + io_write32(gicr_base + GICR_IGROUPR0, gd->per_cpu_group_status); + io_write32(gicr_base + GICR_IGRPMODR0, + gd->per_cpu_group_modifier); + } else { + /* Disable interrupt */ + io_write32(gd->gicd_base + GICD_ICENABLER(0), BIT(it)); + + /* Make interrupt non-pending */ + io_write32(gd->gicd_base + GICD_ICPENDR(0), BIT(it)); + + /* Make it to non-secure */ + io_write32(gd->gicd_base + GICD_IGROUPR(0), + gd->per_cpu_group_status); + } +} + +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 GIC_PPI: + it_num += 16; + break; + case GIC_SPI: + it_num += 32; + break; + default: + it_num = DT_INFO_INVALID_INTERRUPT; + } + + return it_num; +} + +static void __maybe_unused probe_redist_base_addrs(vaddr_t *gicr_base_addrs, + paddr_t gicr_base_pa) +{ + size_t sz = GICR_V3_PCPUBASE_SIZE; + paddr_t pa = gicr_base_pa; + size_t core_pos = 0; + uint64_t mt_bit = 0; + uint64_t mpidr = 0; + uint64_t tv = 0; + vaddr_t va = 0; + +#ifdef ARM64 + mt_bit = read_mpidr_el1() & MPIDR_MT_MASK; +#endif + do { + va = core_mmu_get_va(pa, MEM_AREA_IO_SEC, sz); + if (!va) + panic(); + tv = io_read64(va + GICR_TYPER); + + /* + * Extract an mpidr from the Type register to calculate the + * core position of this redistributer instance. + */ + mpidr = mt_bit; + mpidr |= SHIFT_U64((tv >> GICR_TYPER_AFF3_SHIFT) & + MPIDR_AFFLVL_MASK, MPIDR_AFF3_SHIFT); + mpidr |= (tv >> GICR_TYPER_AFF0_SHIFT) & + (MPIDR_AFF0_MASK | MPIDR_AFF1_MASK | MPIDR_AFF2_MASK); + core_pos = get_core_pos_mpidr(mpidr); + if (core_pos < CFG_TEE_CORE_NB_CORE) { + DMSG("GICR_BASE[%zu] at %#"PRIxVA, core_pos, va); + gicr_base_addrs[core_pos] = va; + } else { + EMSG("Skipping too large core_pos %zu from GICR_TYPER", + core_pos); + } + pa += sz; + } while (!(tv & GICR_TYPER_LAST)); +} + +static void gic_init_base_addr(paddr_t gicc_base_pa, paddr_t gicd_base_pa, + paddr_t gicr_base_pa __maybe_unused) +{ + struct gic_data *gd = &gic_data; + vaddr_t gicc_base = 0; + vaddr_t gicd_base = 0; + uint32_t vers __maybe_unused = 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(); + + vers = io_read32(gicd_base + GICD_PIDR2); + vers >>= GICD_PIDR2_ARCHREV_SHIFT; + vers &= GICD_PIDR2_ARCHREV_MASK; + + if (IS_ENABLED(CFG_ARM_GICV3)) { + assert(vers == 3); + } else { + assert(vers == 2 || vers == 1); + 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); +#if defined(CFG_ARM_GICV3) + if (affinity_routing_is_enabled(gd) && gicr_base_pa) + probe_redist_base_addrs(gd->gicr_base, gicr_base_pa); +#endif + gd->chip.ops = &gic_ops; + + if (IS_ENABLED(CFG_DT)) + gd->chip.dt_get_irq = gic_dt_get_irq; +} + +void gic_init_v3(paddr_t gicc_base_pa, paddr_t gicd_base_pa, + paddr_t gicr_base_pa) +{ + struct gic_data __maybe_unused *gd = &gic_data; + size_t __maybe_unused n = 0; + + gic_init_base_addr(gicc_base_pa, gicd_base_pa, gicr_base_pa); + +#if defined(CFG_WITH_ARM_TRUSTED_FW) + /* GIC configuration is initialized from TF-A when embedded */ + if (affinity_routing_is_enabled(gd)) { + /* Secure affinity routing enabled */ + vaddr_t gicr_base = get_gicr_base(gd); + + if (gicr_base) { + gd->per_cpu_group_status = io_read32(gicr_base + + GICR_IGROUPR0); + gd->per_cpu_group_modifier = io_read32(gicr_base + + GICR_IGRPMODR0); + } else { + IMSG("GIC redistributor base address not provided"); + IMSG("Assuming default GIC group status and modifier"); + gd->per_cpu_group_status = 0xffff00ff; + gd->per_cpu_group_modifier = ~gd->per_cpu_group_status; + } + } else { + /* Legacy operation with secure affinity routing disabled */ + gd->per_cpu_group_status = io_read32(gd->gicd_base + + GICD_IGROUPR(0)); + gd->per_cpu_group_modifier = ~gd->per_cpu_group_status; + } +#else /*!CFG_WITH_ARM_TRUSTED_FW*/ + /* + * Without TF-A, GIC is always configured in for legacy operation + * with secure affinity routing disabled. + */ + 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. + */ + gd->per_cpu_group_status = 0xffff00ff; + gd->per_cpu_group_modifier = ~gd->per_cpu_group_status; + io_write32(gd->gicd_base + GICD_IGROUPR(n), + gd->per_cpu_group_status); + } 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_ENABLEGRP1NS); +#endif +#endif /*!CFG_WITH_ARM_TRUSTED_FW*/ + + interrupt_main_init(&gic_data.chip); +} + +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); + + assert(gd == &gic_data); + + /* 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); + + assert(gd == &gic_data); + + /* 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); + + assert(gd == &gic_data); + + /* 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; + + assert(gd == &gic_data); + + /* 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); + + assert(gd == &gic_data); + + /* 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); + + assert(gd == &gic_data); + + /* Should be Peripheral Interrupt */ + assert(it >= NUM_SGI); + + /* Raise the interrupt */ + io_write32(gd->gicd_base + GICD_ISPENDR(idx), mask); +} + +static void assert_cpu_mask_is_valid(uint32_t cpu_mask) +{ + bool __maybe_unused to_others = cpu_mask & ITR_CPU_MASK_TO_OTHER_CPUS; + bool __maybe_unused to_current = cpu_mask & ITR_CPU_MASK_TO_THIS_CPU; + bool __maybe_unused to_list = cpu_mask & 0xff; + + /* One and only one of the bit fields shall be non-zero */ + assert(to_others + to_current + to_list == 1); +} + +static void gic_it_raise_sgi(struct gic_data *gd __maybe_unused, size_t it, + uint32_t cpu_mask, bool ns) +{ +#if defined(CFG_ARM_GICV3) + uint32_t mask_id = it & 0xf; + uint64_t mask = SHIFT_U64(mask_id, 24); + + assert_cpu_mask_is_valid(cpu_mask); + + if (cpu_mask & ITR_CPU_MASK_TO_OTHER_CPUS) { + mask |= BIT64(GICC_SGI_IRM_BIT); + } else { + uint64_t mpidr = read_mpidr(); + uint64_t mask_aff1 = (mpidr & MPIDR_AFF1_MASK) >> + MPIDR_AFF1_SHIFT; + uint64_t mask_aff2 = (mpidr & MPIDR_AFF2_MASK) >> + MPIDR_AFF2_SHIFT; + uint64_t mask_aff3 = (mpidr & MPIDR_AFF3_MASK) >> + MPIDR_AFF3_SHIFT; + + mask |= SHIFT_U64(mask_aff1, GICC_SGI_AFF1_SHIFT); + mask |= SHIFT_U64(mask_aff2, GICC_SGI_AFF2_SHIFT); + mask |= SHIFT_U64(mask_aff3, GICC_SGI_AFF3_SHIFT); + + if (cpu_mask & ITR_CPU_MASK_TO_THIS_CPU) { + mask |= BIT32(mpidr & 0xf); + } else { + /* + * Only support sending SGI to the cores in the + * same cluster now. + */ + mask |= cpu_mask & 0xff; + } + } + + /* Raise the interrupt */ + if (ns) + write_icc_asgi1r(mask); + else + write_icc_sgi1r(mask); +#else + uint32_t mask_id = it & GICD_SGIR_SIGINTID_MASK; + uint32_t mask_group = ns; + uint32_t mask = mask_id; + + assert_cpu_mask_is_valid(cpu_mask); + + mask |= SHIFT_U32(mask_group, GICD_SGIR_NSATT_SHIFT); + if (cpu_mask & ITR_CPU_MASK_TO_OTHER_CPUS) { + mask |= SHIFT_U32(GICD_SGIR_TO_OTHER_CPUS, + GICD_SGIR_TARGET_LIST_FILTER_SHIFT); + } else if (cpu_mask & ITR_CPU_MASK_TO_THIS_CPU) { + mask |= SHIFT_U32(GICD_SGIR_TO_THIS_CPU, + GICD_SGIR_TARGET_LIST_FILTER_SHIFT); + } else { + mask |= SHIFT_U32(cpu_mask & 0xff, + GICD_SGIR_CPU_TARGET_LIST_SHIFT); + } + + /* Raise the interrupt */ + io_write32(gd->gicd_base + GICD_SGIR, mask); +#endif +} + +static uint32_t gic_read_iar(struct gic_data *gd __maybe_unused) +{ + assert(gd == &gic_data); + +#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) +{ + assert(gd == &gic_data); + +#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); + + assert(gd == &gic_data); + 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); + + assert(gd == &gic_data); + 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)); + + assert(gd == &gic_data); + return (target & target_mask) >> target_shift; +} + +void gic_dump_state(void) +{ + struct gic_data *gd = &gic_data; + int i = 0; + +#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)); + } + } +} + +static void __maybe_unused gic_native_itr_handler(void) +{ + struct gic_data *gd = &gic_data; + uint32_t iar = 0; + uint32_t id = 0; + + iar = gic_read_iar(gd); + id = iar & GICC_IAR_IT_ID_MASK; + + if (id <= gd->max_it) + interrupt_call_handlers(&gd->chip, id); + else + DMSG("ignoring interrupt %" PRIu32, id); + + gic_write_eoir(gd, iar); +} + +#ifndef CFG_CORE_WORKAROUND_ARM_NMFI +/* Override interrupt_main_handler() with driver implementation */ +void interrupt_main_handler(void) +{ + gic_native_itr_handler(); +} +#endif /*CFG_CORE_WORKAROUND_ARM_NMFI*/ + +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); + + assert(gd == &gic_data); + + if (it > gd->max_it) + panic(); + + if (it < GIC_SPI_BASE) { + if (gic_primary_done) + panic("Cannot add SGI or PPI after boot"); + + /* Assign it to Secure Group 1, G1S */ + gd->per_cpu_group_modifier |= BIT32(it); + gd->per_cpu_group_status &= ~BIT32(it); + } + + if (it < GIC_SPI_BASE && affinity_routing_is_enabled(gd)) { + vaddr_t gicr_base = get_gicr_base(gd); + + if (!gicr_base) + panic("GICR_BASE missing"); + + /* Disable interrupt */ + io_write32(gicr_base + GICR_ICENABLER0, BIT32(it)); + + /* Wait for the write to GICR_ICENABLER0 to propagate */ + gicr_wait_for_pending_write(gicr_base); + + /* Make interrupt non-pending */ + io_write32(gicr_base + GICR_ICPENDR0, BIT32(it)); + + /* Make it to Secure */ + io_write32(gicr_base + GICR_IGROUPR0, gd->per_cpu_group_status); + io_write32(gicr_base + GICR_IGRPMODR0, + gd->per_cpu_group_modifier); + } else { + 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); + + assert(gd == &gic_data); + + if (it > gd->max_it) + panic(); + + if (it < GIC_SPI_BASE) + gd->per_cpu_enable |= BIT(it); + + if (it < GIC_SPI_BASE && affinity_routing_is_enabled(gd)) { + vaddr_t gicr_base = get_gicr_base(gd); + + if (!gicr_base) + panic("GICR_BASE missing"); + + /* Assigned to G1S */ + assert(gd->per_cpu_group_modifier & BIT(it) && + !(gd->per_cpu_group_status & BIT(it))); + io_write32(gicr_base + GICR_ISENABLER0, gd->per_cpu_enable); + } else { + 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); + + assert(gd == &gic_data); + + 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); + + assert(gd == &gic_data); + + 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, + uint32_t cpu_mask) +{ + struct gic_data *gd = container_of(chip, struct gic_data, chip); + bool ns = false; + + assert(gd == &gic_data); + + /* Should be Software Generated Interrupt */ + assert(it < NUM_SGI); + + ns = BIT32(it) & gd->per_cpu_group_status; + gic_it_raise_sgi(gd, it, cpu_mask, ns); +} + +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); + + assert(gd == &gic_data); + + if (it > gd->max_it) + panic(); + + gic_it_set_cpu_mask(gd, it, cpu_mask); +} + +#ifdef CFG_DT +/* Callback for "interrupts" and "interrupts-extended" DT node properties */ +static TEE_Result dt_get_gic_chip_cb(struct dt_pargs *arg, void *priv_data, + struct itr_desc *itr_desc) +{ + int itr_num = DT_INFO_INVALID_INTERRUPT; + struct itr_chip *chip = priv_data; + uint32_t phandle_args[2] = { }; + uint32_t type = 0; + uint32_t prio = 0; + + assert(arg && itr_desc); + + /* + * gic_dt_get_irq() expects phandle arguments passed are still in DT + * format (big-endian) whereas struct dt_pargs carries converted + * formats. Therefore swap again phandle arguments. gic_dt_get_irq() + * consumes only the 2 first arguments. + */ + if (arg->args_count < 2) + return TEE_ERROR_GENERIC; + phandle_args[0] = cpu_to_fdt32(arg->args[0]); + phandle_args[1] = cpu_to_fdt32(arg->args[1]); + + itr_num = gic_dt_get_irq((const void *)phandle_args, 2, &type, &prio); + if (itr_num == DT_INFO_INVALID_INTERRUPT) + return TEE_ERROR_GENERIC; + + gic_op_add(chip, itr_num, type, prio); + + itr_desc->chip = chip; + itr_desc->itr_num = itr_num; + + return TEE_SUCCESS; +} + +static TEE_Result gic_probe(const void *fdt, int offs, const void *cd __unused) +{ + if (interrupt_register_provider(fdt, offs, dt_get_gic_chip_cb, + &gic_data.chip)) + panic(); + + return TEE_SUCCESS; +} + +static const struct dt_device_match gic_match_table[] = { + { .compatible = "arm,cortex-a15-gic" }, + { .compatible = "arm,cortex-a7-gic" }, + { .compatible = "arm,cortex-a5-gic" }, + { .compatible = "arm,cortex-a9-gic" }, + { .compatible = "arm,gic-400" }, + { } +}; + +DEFINE_DT_DRIVER(gic_dt_driver) = { + .name = "gic", + .match_table = gic_match_table, + .probe = gic_probe, +}; +#endif /*CFG_DT*/ + +static TEE_Result gic_set_primary_done(void) +{ + gic_primary_done = true; + return TEE_SUCCESS; +} + +nex_release_init_resource(gic_set_primary_done); diff --git a/optee/optee_os/core/drivers/gpio/gpio.c b/optee/optee_os/core/drivers/gpio/gpio.c new file mode 100644 index 0000000..bcdb91c --- /dev/null +++ b/optee/optee_os/core/drivers/gpio/gpio.c @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022, Microchip + */ + +#include +#include +#include +#include +#include +#include + +TEE_Result gpio_dt_alloc_pin(struct dt_pargs *pargs, struct gpio **out_gpio) +{ + struct gpio *gpio = NULL; + + if (pargs->args_count != 2) + return TEE_ERROR_BAD_PARAMETERS; + + gpio = calloc(1, sizeof(struct gpio)); + if (!gpio) + return TEE_ERROR_OUT_OF_MEMORY; + + gpio->pin = pargs->args[0]; + gpio->dt_flags = pargs->args[1]; + + *out_gpio = gpio; + + return TEE_SUCCESS; +} + +static char *gpio_get_dt_prop_name(const char *gpio_name) +{ + int ret = 0; + char *prop_name = NULL; + size_t max_len = strlen(gpio_name) + strlen("-gpios") + 1; + + prop_name = calloc(1, max_len); + if (!prop_name) + return NULL; + + ret = snprintf(prop_name, max_len, "%s-gpios", gpio_name); + if (ret < 0 || (size_t)ret >= max_len) { + free(prop_name); + return NULL; + } + + return prop_name; +} + +TEE_Result gpio_dt_get_by_index(const void *fdt, int nodeoffset, + unsigned int index, const char *gpio_name, + struct gpio **gpio) +{ + TEE_Result res = TEE_ERROR_GENERIC; + char *prop_name = NULL; + void *out_gpio = NULL; + + prop_name = gpio_get_dt_prop_name(gpio_name); + if (!prop_name) + return TEE_ERROR_OUT_OF_MEMORY; + + res = dt_driver_device_from_node_idx_prop(prop_name, fdt, nodeoffset, + index, DT_DRIVER_GPIO, + &out_gpio); + free(prop_name); + if (!res) + *gpio = out_gpio; + + return res; +} diff --git a/optee/optee_os/core/drivers/gpio/sub.mk b/optee/optee_os/core/drivers/gpio/sub.mk new file mode 100644 index 0000000..9b91fbc --- /dev/null +++ b/optee/optee_os/core/drivers/gpio/sub.mk @@ -0,0 +1 @@ +srcs-y += gpio.c diff --git a/optee/optee_os/core/drivers/hfic.c b/optee/optee_os/core/drivers/hfic.c new file mode 100644 index 0000000..08e7293 --- /dev/null +++ b/optee/optee_os/core/drivers/hfic.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * For documentation of the paravirtualized interface see: + * https://hafnium.readthedocs.io/en/latest/design/secure-partition-manager.html#paravirtualized-interfaces + */ + +#define HF_INTERRUPT_ENABLE 0xff03 +#define HF_INTERRUPT_GET 0xff04 +#define HF_INTERRUPT_DEACTIVATE 0xff08 +#define HF_INTERRUPT_RECONFIGURE 0xff09 + +#define HF_INVALID_INTID 0xffffffff +#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 + +#define HF_INT_RECONFIGURE_STATUS 2 + +struct hfic_data { + struct itr_chip chip; +}; + +static struct hfic_data hfic_data __nex_bss; + +static void hfic_op_add(struct itr_chip *chip __unused, size_t it, + uint32_t type __unused, uint32_t prio __unused) +{ + 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_enable(struct itr_chip *chip __unused, size_t it) +{ + uint32_t res __maybe_unused = 0; + + res = thread_hvc(HF_INTERRUPT_RECONFIGURE, it, + HF_INT_RECONFIGURE_STATUS, HF_ENABLE); + 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_RECONFIGURE, it, + HF_INT_RECONFIGURE_STATUS, HF_DISABLE); + assert(!res); +} + +static const struct itr_ops hfic_ops = { + .add = hfic_op_add, + .mask = hfic_op_disable, + .unmask = hfic_op_enable, + .enable = hfic_op_enable, + .disable = hfic_op_disable, +}; + +void hfic_init(void) +{ + hfic_data.chip.ops = &hfic_ops; + interrupt_main_init(&hfic_data.chip); +} + +/* Override interrupt_main_handler() with driver implementation */ +void interrupt_main_handler(void) +{ + 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; + } + + interrupt_call_handlers(&hfic_data.chip, 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/hisi_trng.c b/optee/optee_os/core/drivers/hisi_trng.c new file mode 100644 index 0000000..3d865e4 --- /dev/null +++ b/optee/optee_os/core/drivers/hisi_trng.c @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2023 HiSilicon Limited. */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define HTRNG_RANDATA_REG 0xF0 +#define HTRNG_BYTES 4U + +#define POLL_PERIOD 10 +#define POLL_TIMEOUT 1000 + +struct hisi_trng { + vaddr_t base; +}; + +static unsigned int trng_lock = SPINLOCK_UNLOCK; +static struct hisi_trng *trng_dev; + +static TEE_Result trng_read(uint32_t *val) +{ + TEE_Result ret = TEE_SUCCESS; + uint32_t exceptions = 0; + + exceptions = cpu_spin_lock_xsave(&trng_lock); + if (IO_READ32_POLL_TIMEOUT(trng_dev->base + HTRNG_RANDATA_REG, + *val, *val, POLL_PERIOD, POLL_TIMEOUT)) { + EMSG("Hardware busy"); + ret = TEE_ERROR_BUSY; + } + cpu_spin_unlock_xrestore(&trng_lock, exceptions); + + return ret; +} + +TEE_Result hw_get_random_bytes(void *buf, size_t len) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + size_t current_len = 0; + uint32_t val = 0; + size_t size = 0; + + if (!trng_dev) { + EMSG("No valid TRNG device"); + return TEE_ERROR_NOT_SUPPORTED; + } + + if (!buf || !len) { + EMSG("Invalid input parameter"); + return TEE_ERROR_BAD_PARAMETERS; + } + + while (current_len < len) { + ret = trng_read(&val); + if (ret) + return TEE_ERROR_BUSY; + + size = MIN(HTRNG_BYTES, len - current_len); + memcpy((uint8_t *)buf + current_len, &val, size); + current_len += size; + } + + return TEE_SUCCESS; +} + +static TEE_Result trng_init(void) +{ + DMSG("TRNG driver init start"); + trng_dev = calloc(1, sizeof(struct hisi_trng)); + if (!trng_dev) { + EMSG("Fail to calloc trng device"); + return TEE_ERROR_OUT_OF_MEMORY; + } + + trng_dev->base = (vaddr_t)phys_to_virt_io(HISI_TRNG_BASE, + HISI_TRNG_SIZE); + if (!trng_dev->base) { + EMSG("Fail to get trng io_base"); + free(trng_dev); + trng_dev = NULL; + return TEE_ERROR_ACCESS_DENIED; + } + + DMSG("TRNG driver init done"); + + return TEE_SUCCESS; +} + +early_init(trng_init); 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..df44f31 --- /dev/null +++ b/optee/optee_os/core/drivers/i2c/atmel_i2c.c @@ -0,0 +1,366 @@ +// 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 TEE_Result atmel_i2c_get_dt_i2c(struct dt_pargs *args, void *data, + struct i2c_dev **out_device) +{ + struct i2c_dev *i2c_dev = NULL; + struct i2c_ctrl *i2c_ctrl = data; + + i2c_dev = i2c_create_dev(i2c_ctrl, args->fdt, args->phandle_node); + if (!i2c_dev) + return TEE_ERROR_OUT_OF_MEMORY; + + *out_device = i2c_dev; + + return TEE_SUCCESS; +} + +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..017b97a --- /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(base); + + 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(base); + + 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..6089339 --- /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(vaddr_t base __unused) +{ + return MU_MAX_CHANNEL; +} + +unsigned int imx_mu_plat_get_tx_channel(vaddr_t base __unused) +{ + 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..da09dde --- /dev/null +++ b/optee/optee_os/core/drivers/imx/mu/imx_mu_8ulp.c @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2022-2023 NXP + */ +#include +#include +#include +#include +#include + +#include "imx_mu_platform.h" + +#define MU_PAR 0x004 +#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 RR_NUM_MASK GENMASK_32(15, 8) +#define RR_NUM_SHIFT 8 +#define TR_NUM_MASK GENMASK_32(7, 0) + +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(vaddr_t base) +{ + return (io_read32(base + MU_PAR) & RR_NUM_MASK) >> RR_NUM_SHIFT; +} + +unsigned int imx_mu_plat_get_tx_channel(vaddr_t base) +{ + return io_read32(base + MU_PAR) & TR_NUM_MASK; +} + +TEE_Result imx_mu_plat_send(vaddr_t base, unsigned int index, uint32_t msg) +{ + assert(index < imx_mu_plat_get_tx_channel(base)); + + /* 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 < imx_mu_plat_get_rx_channel(base)); + + /* 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..2342f47 --- /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(vaddr_t base); + +/* + * Return the number of transmission channels + */ +unsigned int imx_mu_plat_get_tx_channel(vaddr_t base); + +/* + * 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..368c22c --- /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) $(CFG_MX8DXL)),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..fc06697 --- /dev/null +++ b/optee/optee_os/core/drivers/imx_csu.c @@ -0,0 +1,175 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2017-2023 NXP + * + */ + +#include +#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_configure(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; +} + +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) + csu_configure(); + + return TEE_SUCCESS; +} + +static TEE_Result csu_init(void) +{ + csu_configure(); + register_pm_driver_cb(pm_enter_resume, NULL, "imx-csu"); + + 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..bfa2f19 --- /dev/null +++ b/optee/optee_os/core/drivers/imx_ele.c @@ -0,0 +1,559 @@ +// 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 0xCD +#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; + const char pattern[16] __aligned(CACHELINE_SIZE) = "TEE_for_HUK_ELE"; + 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; + uint32_t ctx_addr_msb; + uint32_t ctx_addr_lsb; + uint16_t key_size; + uint16_t ctx_size; + uint32_t crc; + } __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; + + reg_pair_from_64((uint64_t)virt_to_phys((void *)pattern), &msb, &lsb); + + cmd.ctx_addr_lsb = lsb; + cmd.ctx_addr_msb = msb; + cmd.ctx_size = sizeof(pattern); + + memcpy(msg.data.u8, &cmd, sizeof(cmd)); + update_crc(&msg); + + cache_operation(TEE_CACHEFLUSH, key, HW_UNIQUE_KEY_LENGTH); + cache_operation(TEE_CACHECLEAN, (void *)pattern, sizeof(pattern)); + + 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..7f05614 --- /dev/null +++ b/optee/optee_os/core/drivers/imx_snvs.c @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2020 Pengutronix + * Rouven Czerwinski + * Copyright 2022-2023 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_LPCR 0x38 +#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) + +#define SNVS_LPCR_TOP_MASK BIT(6) +#define SNVS_LPCR_DP_EN_MASK BIT(5) +#define SNVS_LPCR_SRTC_ENV_MASK BIT(1) + +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; +} + +void imx_snvs_shutdown(void) +{ + vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE); + + io_write32(base + SNVS_LPCR, + SNVS_LPCR_TOP_MASK | + SNVS_LPCR_DP_EN_MASK | + SNVS_LPCR_SRTC_ENV_MASK); +} 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..bdd5f39 --- /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"); + 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", 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"); + 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"); + 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"); + 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..23942aa --- /dev/null +++ b/optee/optee_os/core/drivers/ls_dspi.c @@ -0,0 +1,614 @@ +// 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)) + +/* 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 + */ +static 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); +} + +/* + * Flush DSPI module + * chip: spi_chip instance + */ +static void ls_dspi_flush(struct spi_chip *chip) +{ + struct ls_dspi_data *data = container_of(chip, struct ls_dspi_data, + chip); + + dspi_flush_fifo(data); +} + +/* + * 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"); + 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, + .flushfifo = ls_dspi_flush, +}; +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..27a7352 --- /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 ls_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 ls_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 ls_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 ls_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"); + 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 = ls_gpio_get_direction, + .set_direction = ls_gpio_set_direction, + .get_value = ls_gpio_get_value, + .set_value = ls_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..91df013 --- /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"); + 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..4c22040 --- /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, DT_MAP_AUTO); + 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..d0e52ce --- /dev/null +++ b/optee/optee_os/core/drivers/ns16550.c @@ -0,0 +1,121 @@ +// 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_DR 0x01 /* DATA Ready */ +#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ + +static vaddr_t chip_to_base_and_data(struct serial_chip *chip, + struct ns16550_data **pd) +{ + *pd = container_of(chip, struct ns16550_data, chip); + + return io_pa_or_va(&(*pd)->base, NS16550_UART_REG_SIZE); +} + +static void ns16550_flush(struct serial_chip *chip) +{ + struct ns16550_data *pd = NULL; + vaddr_t base = chip_to_base_and_data(chip, &pd); + + 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 = NULL; + vaddr_t base = chip_to_base_and_data(chip, &pd); + + ns16550_flush(chip); + + /* write out charset to Transmit-hold-register */ + serial_out(base + (UART_THR << pd->reg_shift), pd->io_width, ch); +} + +static bool ns16550_have_rx_data(struct serial_chip *chip) +{ + struct ns16550_data *pd = NULL; + vaddr_t base = chip_to_base_and_data(chip, &pd); + + return serial_in(base + (UART_LSR << pd->reg_shift), pd->io_width) & + UART_LSR_DR; +} + +static int ns16550_getchar(struct serial_chip *chip) +{ + struct ns16550_data *pd = NULL; + vaddr_t base = chip_to_base_and_data(chip, &pd); + + while (!ns16550_have_rx_data(chip)) { + /* Data is not ready, waiting again */ + ; + } + + return serial_in(base + (UART_RBR << pd->reg_shift), pd->io_width) & + 0xFF; +} + +static const struct serial_ops ns16550_ops = { + .flush = ns16550_flush, + .putc = ns16550_putc, + .getchar = ns16550_getchar, + .have_rx_data = ns16550_have_rx_data, +}; +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/nvmem/atmel_sfc.c b/optee/optee_os/core/drivers/nvmem/atmel_sfc.c new file mode 100644 index 0000000..f8db1ff --- /dev/null +++ b/optee/optee_os/core/drivers/nvmem/atmel_sfc.c @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021, Microchip + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ATMEL_SFC_KR 0x0 +#define ATMEL_SFC_SR 0x1C +#define ATMEL_SFC_SR_PGMC BIT(0) +#define ATMEL_SFC_SR_PGMF BIT(1) +#define ATMEL_SFC_DR 0x20 + +#define ATMEL_SFC_CELLS_32 17 +#define ATMEL_SFC_CELLS_8 (ATMEL_SFC_CELLS_32 * sizeof(uint32_t)) + +struct atmel_sfc { + vaddr_t base; + uint8_t fuses[ATMEL_SFC_CELLS_8]; +}; + +static TEE_Result atmel_sfc_read_cell(struct nvmem_cell *cell, uint8_t *data) +{ + struct atmel_sfc *atmel_sfc = cell->drv_data; + + memcpy(data, &atmel_sfc->fuses[cell->offset], cell->len); + + return TEE_SUCCESS; +} + +static void atmel_sfc_put_cell(struct nvmem_cell *cell) +{ + free(cell); +} + +static const struct nvmem_ops atmel_sfc_nvmem_ops = { + .read_cell = atmel_sfc_read_cell, + .put_cell = atmel_sfc_put_cell, +}; + +static TEE_Result atmel_sfc_dt_get(struct dt_pargs *args, + void *data, struct nvmem_cell **out_cell) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct nvmem_cell *cell = NULL; + + /* Freed from atmel_sfc_put_cell() */ + cell = calloc(1, sizeof(*cell)); + if (!cell) + return TEE_ERROR_OUT_OF_MEMORY; + + res = nvmem_cell_parse_dt(args->fdt, args->phandle_node, cell); + if (res) + goto out_free; + + if (cell->offset + cell->len > ATMEL_SFC_CELLS_8) { + res = TEE_ERROR_GENERIC; + goto out_free; + } + + cell->ops = &atmel_sfc_nvmem_ops; + cell->drv_data = data; + *out_cell = cell; + + return TEE_SUCCESS; + +out_free: + free(cell); + + return res; +} + +static void atmel_sfc_read_fuse(struct atmel_sfc *atmel_sfc) +{ + size_t i = 0; + uint32_t val = 0; + + for (i = 0; i < ATMEL_SFC_CELLS_32; i++) { + val = io_read32(atmel_sfc->base + ATMEL_SFC_DR + i * 4); + memcpy(&atmel_sfc->fuses[i * 4], &val, sizeof(val)); + } +} + +static TEE_Result atmel_sfc_probe(const void *fdt, int node, + const void *compat_data __unused) +{ + vaddr_t base = 0; + size_t size = 0; + struct atmel_sfc *atmel_sfc = NULL; + + if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC) + return TEE_ERROR_NODE_DISABLED; + + matrix_configure_periph_secure(AT91C_ID_SFC); + + if (dt_map_dev(fdt, node, &base, &size, DT_MAP_AUTO) < 0) + return TEE_ERROR_GENERIC; + + atmel_sfc = calloc(1, sizeof(*atmel_sfc)); + if (!atmel_sfc) + return TEE_ERROR_OUT_OF_MEMORY; + + atmel_sfc->base = base; + + atmel_sfc_read_fuse(atmel_sfc); + + return nvmem_register_provider(fdt, node, atmel_sfc_dt_get, atmel_sfc); +} + +static const struct dt_device_match atmel_sfc_match_table[] = { + { .compatible = "atmel,sama5d2-sfc" }, + { } +}; + +DEFINE_DT_DRIVER(atmel_sfc_dt_driver) = { + .name = "atmel_sfc", + .type = DT_DRIVER_NVMEM, + .match_table = atmel_sfc_match_table, + .probe = atmel_sfc_probe, +}; diff --git a/optee/optee_os/core/drivers/nvmem/nvmem.c b/optee/optee_os/core/drivers/nvmem/nvmem.c new file mode 100644 index 0000000..7d30c2c --- /dev/null +++ b/optee/optee_os/core/drivers/nvmem/nvmem.c @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2023, Microchip + */ + +#include +#include +#include + +TEE_Result nvmem_cell_parse_dt(const void *fdt, int nodeoffset, + struct nvmem_cell *cell) +{ + size_t buf_len = 0; + paddr_t offset = 0; + + buf_len = fdt_reg_size(fdt, nodeoffset); + if (buf_len == DT_INFO_INVALID_REG_SIZE) + return TEE_ERROR_GENERIC; + + offset = fdt_reg_base_address(fdt, nodeoffset); + if (offset == DT_INFO_INVALID_REG) + return TEE_ERROR_GENERIC; + + cell->len = buf_len; + cell->offset = offset; + + return TEE_SUCCESS; +} + +TEE_Result nvmem_get_cell_by_name(const void *fdt, int nodeoffset, + const char *name, struct nvmem_cell **cell) +{ + int index = 0; + + index = fdt_stringlist_search(fdt, nodeoffset, "nvmem-cell-names", + name); + if (index < 0) + return TEE_ERROR_ITEM_NOT_FOUND; + + return nvmem_get_cell_by_index(fdt, nodeoffset, index, cell); +} + +TEE_Result nvmem_get_cell_by_index(const void *fdt, + int nodeoffset, + unsigned int index, + struct nvmem_cell **out_cell) +{ + TEE_Result res = TEE_ERROR_GENERIC; + void *cell = NULL; + + res = dt_driver_device_from_node_idx_prop("nvmem-cells", fdt, + nodeoffset, index, + DT_DRIVER_NVMEM, &cell); + if (!res) + *out_cell = cell; + + return res; +} + +TEE_Result nvmem_cell_malloc_and_read(struct nvmem_cell *cell, + uint8_t **out_data) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + if (!cell->ops->read_cell) + return TEE_ERROR_NOT_SUPPORTED; + + *out_data = malloc(cell->len); + if (!out_data) + return TEE_ERROR_OUT_OF_MEMORY; + + res = cell->ops->read_cell(cell, *out_data); + if (res) + free(*out_data); + + return res; +} diff --git a/optee/optee_os/core/drivers/nvmem/nvmem_die_id.c b/optee/optee_os/core/drivers/nvmem/nvmem_die_id.c new file mode 100644 index 0000000..9ba1e79 --- /dev/null +++ b/optee/optee_os/core/drivers/nvmem/nvmem_die_id.c @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2023, Microchip + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static uint8_t *die_id; +static size_t die_id_len; + +int tee_otp_get_die_id(uint8_t *buffer, size_t len) +{ + if (!die_id) { + if (huk_subkey_derive(HUK_SUBKEY_DIE_ID, NULL, 0, buffer, len)) + return -1; + return 0; + } + + memcpy(buffer, die_id, MIN(die_id_len, len)); + + return 0; +} + +static TEE_Result nvmem_die_id_probe(const void *fdt, int node, + const void *compat_data __unused) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct nvmem_cell *cell = NULL; + uint8_t *data = NULL; + + res = nvmem_get_cell_by_name(fdt, node, "die_id", &cell); + if (res) + return res; + + res = nvmem_cell_malloc_and_read(cell, &data); + if (!res) + die_id = data; + + nvmem_put_cell(cell); + + return res; +} + +static const struct dt_device_match nvmem_die_id_match_table[] = { + { .compatible = "optee,nvmem-die-id" }, + { } +}; + +DEFINE_DT_DRIVER(nvmem_die_id_dt_driver) = { + .name = "nvmem_die_id_key", + .type = DT_DRIVER_NVMEM, + .match_table = nvmem_die_id_match_table, + .probe = nvmem_die_id_probe, +}; diff --git a/optee/optee_os/core/drivers/nvmem/nvmem_huk.c b/optee/optee_os/core/drivers/nvmem/nvmem_huk.c new file mode 100644 index 0000000..1fb03b6 --- /dev/null +++ b/optee/optee_os/core/drivers/nvmem/nvmem_huk.c @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2023, Microchip + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct nvmem_cell *huk_cell; + +TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey) +{ + TEE_Result res = TEE_ERROR_GENERIC; + uint8_t *huk = NULL; + size_t len = 0; + + res = nvmem_cell_malloc_and_read(huk_cell, &huk); + if (res) + goto out_free_cell; + + if (len != HW_UNIQUE_KEY_LENGTH) { + res = TEE_ERROR_GENERIC; + goto out_free_cell; + } + + memcpy(hwkey->data, huk, HW_UNIQUE_KEY_LENGTH); + +out_free_cell: + nvmem_put_cell(huk_cell); + + return res; +} + +static TEE_Result nvmem_huk_get_cell(const void *fdt, int node) +{ + return nvmem_get_cell_by_name(fdt, node, "hw_unique_key", &huk_cell); +} + +static TEE_Result nvmem_huk_probe(const void *fdt, int node, + const void *compat_data __unused) +{ + return nvmem_huk_get_cell(fdt, node); +} + +static const struct dt_device_match nvmem_huk_match_table[] = { + { .compatible = "optee,nvmem-huk" }, + { } +}; + +DEFINE_DT_DRIVER(nvmem_huk_dt_driver) = { + .name = "nvmem_huk", + .type = DT_DRIVER_NVMEM, + .match_table = nvmem_huk_match_table, + .probe = nvmem_huk_probe, +}; diff --git a/optee/optee_os/core/drivers/nvmem/sub.mk b/optee/optee_os/core/drivers/nvmem/sub.mk new file mode 100644 index 0000000..dd5e1f6 --- /dev/null +++ b/optee/optee_os/core/drivers/nvmem/sub.mk @@ -0,0 +1,4 @@ +srcs-y += nvmem.c +srcs-$(CFG_ATMEL_SFC) += atmel_sfc.c +srcs-$(CFG_NVMEM_DIE_ID) += nvmem_die_id.c +srcs-$(CFG_NVMEM_HUK) += nvmem_huk.c diff --git a/optee/optee_os/core/drivers/pinctrl/atmel_pio.c b/optee/optee_os/core/drivers/pinctrl/atmel_pio.c new file mode 100644 index 0000000..320d527 --- /dev/null +++ b/optee/optee_os/core/drivers/pinctrl/atmel_pio.c @@ -0,0 +1,248 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2019 Microchip. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PIO_GROUP_COUNT 4 +#define PIO_GROUP_OFFSET 0x40 +#define PIO_REG(reg, group) ((reg) + ((group) * PIO_GROUP_OFFSET)) +/* Mask register */ +#define PIO_MSKR(group) PIO_REG(0x0, (group)) +/* Configuration register */ +#define PIO_CFGR(group) PIO_REG(0x4, (group)) +#define PIO_CFGR_FUNC GENMASK(2, 0) +#define PIO_CFGR_PUEN BIT(9) +#define PIO_CFGR_PDEN BIT(10) + +/* Non-Secure configuration register */ +#define PIO_SIONR(group) PIO_REG(0x30, (group)) +/* Secure configuration register */ +#define PIO_SIOSR(group) PIO_REG(0x34, (group)) + +#define DT_GET_PIN_NO(val) ((val) & 0xFF) +#define DT_GET_FUNC(val) (((val) >> 16) & 0xF) + +struct atmel_pio { + vaddr_t base; +}; + +struct atmel_pio_pin_conf { + uint32_t pin_mask; + uint32_t pin_cfg; + uint8_t pio_group; + struct atmel_pio *pio; +}; + +static void pio_write(struct atmel_pio *pio, unsigned int offset, uint32_t val) +{ + io_write32(pio->base + offset, val); +} + +static TEE_Result pio_conf_apply(struct pinconf *conf) +{ + struct atmel_pio_pin_conf *pio_conf = conf->priv; + struct atmel_pio *pio = pio_conf->pio; + + DMSG("Apply cfg %#" PRIx32 " on group %" PRIu8 ", pins %#" PRIx32, + pio_conf->pin_cfg, pio_conf->pio_group, pio_conf->pin_mask); + + pio_write(pio, PIO_SIOSR(pio_conf->pio_group), pio_conf->pin_mask); + pio_write(pio, PIO_MSKR(pio_conf->pio_group), pio_conf->pin_mask); + pio_write(pio, PIO_CFGR(pio_conf->pio_group), pio_conf->pin_cfg); + + return TEE_SUCCESS; +} + +static void pio_conf_free(struct pinconf *conf) +{ + free(conf); +} + +static const struct pinctrl_ops pio_pinctrl_ops = { + .conf_apply = pio_conf_apply, + .conf_free = pio_conf_free, +}; + +static TEE_Result pio_pinctrl_dt_get(struct dt_pargs *pargs, void *data, + struct pinconf **out_pinconf) +{ + TEE_Result res = TEE_ERROR_GENERIC; + int i = 0; + int func = 0; + int group = 0; + int pin_no = 0; + uint32_t cfg = 0; + int prop_count = 0; + int pio_group = -1; + uint32_t pinmux = 0; + uint32_t pin_mask = 0; + bitstr_t *cfg_modes = NULL; + const uint32_t *prop = NULL; + struct pinconf *pinconf = NULL; + struct atmel_pio *atmel_pio = data; + struct atmel_pio_pin_conf *pio_conf = NULL; + + prop = fdt_getprop(pargs->fdt, pargs->phandle_node, "pinmux", + &prop_count); + if (!prop) + return TEE_ERROR_ITEM_NOT_FOUND; + + prop_count /= sizeof(uint32_t); + for (i = 0; i < prop_count; i++) { + pinmux = fdt32_to_cpu(prop[i]); + + pin_no = DT_GET_PIN_NO(pinmux); + func = DT_GET_FUNC(pinmux); + + group = pin_no / 32; + if (pio_group == -1) { + pio_group = group; + } else { + if (group != pio_group) { + EMSG("Unexpected group %d vs %d", group, + pio_group); + return TEE_ERROR_GENERIC; + } + } + + pin_mask |= BIT(pin_no % 32); + } + + cfg = func; + + res = pinctrl_parse_dt_pin_modes(pargs->fdt, pargs->phandle_node, + &cfg_modes); + if (res) + return res; + + for (i = 0; i < PINCTRL_DT_PROP_MAX; i++) { + if (!bit_test(cfg_modes, i)) + continue; + + switch (i) { + case PINCTRL_DT_PROP_BIAS_PULL_UP: + cfg |= PIO_CFGR_PUEN; + cfg &= ~PIO_CFGR_PDEN; + break; + case PINCTRL_DT_PROP_BIAS_PULL_DOWN: + cfg |= PIO_CFGR_PDEN; + cfg &= ~PIO_CFGR_PUEN; + break; + case PINCTRL_DT_PROP_BIAS_DISABLE: + break; + default: + EMSG("Unhandled config %u", i); + break; + } + } + + free(cfg_modes); + + pinconf = calloc(1, sizeof(*pinconf) + sizeof(*pio_conf)); + if (!pinconf) + return TEE_ERROR_OUT_OF_MEMORY; + + pio_conf = (struct atmel_pio_pin_conf *)(pinconf + 1); + + pio_conf->pin_mask = pin_mask; + pio_conf->pin_cfg = cfg; + pio_conf->pio = atmel_pio; + pio_conf->pio_group = pio_group; + pinconf->priv = pio_conf; + pinconf->ops = &pio_pinctrl_ops; + + *out_pinconf = pinconf; + + return TEE_SUCCESS; +} + +static void pio_init_hw(struct atmel_pio *pio) +{ + int i = 0; + + /* Set all IOs as non-secure */ + for (i = 0; i < PIO_GROUP_COUNT; i++) + pio_write(pio, PIO_SIONR(PIO_GROUP_COUNT), GENMASK_32(31, 0)); +} + +/* Non-null reference for compat data */ +static const uint8_t has_pioe; + +static TEE_Result pio_node_probe(const void *fdt, int node, + const void *compat_data) +{ + size_t size = 0; + struct clk *clk = NULL; + struct atmel_pio *pio = NULL; + TEE_Result res = TEE_ERROR_GENERIC; + + if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC) + return TEE_ERROR_BAD_STATE; + + pio = calloc(1, sizeof(*pio)); + if (!pio) + return TEE_ERROR_OUT_OF_MEMORY; + + res = clk_dt_get_by_index(fdt, node, 0, &clk); + if (res) + goto free_pio; + + if (dt_map_dev(fdt, node, &pio->base, &size, DT_MAP_AUTO) < 0) + goto free_pio; + + res = clk_enable(clk); + if (res) + goto free_pio; + + matrix_configure_periph_secure(AT91C_ID_PIOA); + matrix_configure_periph_secure(AT91C_ID_PIOB); + matrix_configure_periph_secure(AT91C_ID_PIOC); + matrix_configure_periph_secure(AT91C_ID_PIOD); + + if (compat_data == &has_pioe) + matrix_configure_periph_secure(AT91C_ID_PIOD + 1); + + pio_init_hw(pio); + + res = pinctrl_register_provider(fdt, node, pio_pinctrl_dt_get, pio); + if (res) + goto disable_clock; + + return TEE_SUCCESS; + +disable_clock: + clk_disable(clk); +free_pio: + free(pio); + + return res; +} + +static const struct dt_device_match atmel_pio_match_table[] = { + { .compatible = "atmel,sama5d2-pinctrl" }, + { + .compatible = "microchip,sama7g5-pinctrl", + .compat_data = &has_pioe, + }, + { } +}; + +DEFINE_DT_DRIVER(atmel_pio_dt_driver) = { + .name = "atmel_pio", + .type = DT_DRIVER_PINCTRL, + .match_table = atmel_pio_match_table, + .probe = pio_node_probe, +}; diff --git a/optee/optee_os/core/drivers/pinctrl/pinctrl.c b/optee/optee_os/core/drivers/pinctrl/pinctrl.c new file mode 100644 index 0000000..2ebeee0 --- /dev/null +++ b/optee/optee_os/core/drivers/pinctrl/pinctrl.c @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2023, Microchip + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static const char * const pin_modes[PINCTRL_DT_PROP_MAX] = { + [PINCTRL_DT_PROP_BIAS_DISABLE] = "bias-disable", + [PINCTRL_DT_PROP_BIAS_PULL_UP] = "bias-pull-up", + [PINCTRL_DT_PROP_BIAS_PULL_DOWN] = "bias-pull-down", +}; + +TEE_Result pinctrl_parse_dt_pin_modes(const void *fdt, int node, + bitstr_t **modes) +{ + unsigned int i = 0; + bitstr_t *modes_ptr = NULL; + + modes_ptr = bit_alloc(PINCTRL_DT_PROP_MAX); + if (!modes_ptr) + return TEE_ERROR_OUT_OF_MEMORY; + + for (i = 0; i < ARRAY_SIZE(pin_modes); i++) + if (fdt_getprop(fdt, node, pin_modes[i], NULL)) + bit_set(modes_ptr, i); + + *modes = modes_ptr; + + return TEE_SUCCESS; +} + +TEE_Result pinctrl_apply_state(struct pinctrl_state *state) +{ + unsigned int i = 0; + struct pinconf *conf = NULL; + TEE_Result res = TEE_ERROR_GENERIC; + + for (i = 0; i < state->conf_count; i++) { + conf = state->confs[i]; + + res = conf->ops->conf_apply(conf); + if (res) { + EMSG("Failed to apply pin conf"); + return res; + } + } + + return TEE_SUCCESS; +} + +void pinctrl_free_state(struct pinctrl_state *state) +{ + unsigned int i = 0; + + for (i = 0; i < state->conf_count; i++) + state->confs[i]->ops->conf_free(state->confs[i]); + + free(state); +} + +TEE_Result pinctrl_get_state_by_idx(const void *fdt, int nodeoffset, + unsigned int pinctrl_index, + struct pinctrl_state **state_ret) +{ + int bw = 0; + unsigned int conf_id = 0; + const uint32_t *prop = NULL; + unsigned int conf_count = 0; + /* Enough char to hold "pinctrl-" */ + char prop_name[8 + 20 + 1] = { }; + struct pinctrl_state *state = NULL; + TEE_Result res = TEE_ERROR_GENERIC; + + bw = snprintf(prop_name, sizeof(prop_name), "pinctrl-%d", + pinctrl_index); + if (bw >= (int)sizeof(prop_name)) + return TEE_ERROR_OVERFLOW; + + prop = fdt_getprop(fdt, nodeoffset, prop_name, (int *)&conf_count); + if (!prop) + return TEE_ERROR_ITEM_NOT_FOUND; + + conf_count /= sizeof(uint32_t); + state = calloc(1, sizeof(struct pinctrl_state) + + conf_count * sizeof(struct pinconf *)); + if (!state) + return TEE_ERROR_OUT_OF_MEMORY; + + state->conf_count = conf_count; + for (conf_id = 0; conf_id < conf_count; conf_id++) { + void *pinconf = NULL; + + res = dt_driver_device_from_node_idx_prop(prop_name, fdt, + nodeoffset, conf_id, + DT_DRIVER_PINCTRL, + &pinconf); + if (res) { + free(state); + return res; + } + + state->confs[conf_id] = pinconf; + } + + *state_ret = state; + + return TEE_SUCCESS; +} + +TEE_Result pinctrl_get_state_by_name(const void *fdt, int nodeoffset, + const char *name, + struct pinctrl_state **state) +{ + int pinctrl_index = 0; + + if (!name) + name = "default"; + + pinctrl_index = fdt_stringlist_search(fdt, nodeoffset, "pinctrl-names", + name); + if (pinctrl_index < 0) { + *state = NULL; + if (pinctrl_index == -FDT_ERR_NOTFOUND) + return TEE_ERROR_ITEM_NOT_FOUND; + else + return TEE_ERROR_GENERIC; + } + + return pinctrl_get_state_by_idx(fdt, nodeoffset, pinctrl_index, state); +} diff --git a/optee/optee_os/core/drivers/pinctrl/sub.mk b/optee/optee_os/core/drivers/pinctrl/sub.mk new file mode 100644 index 0000000..90b07de --- /dev/null +++ b/optee/optee_os/core/drivers/pinctrl/sub.mk @@ -0,0 +1,2 @@ +srcs-$(CFG_DRIVERS_PINCTRL) += pinctrl.c +srcs-$(CFG_ATMEL_PIO) += atmel_pio.c diff --git a/optee/optee_os/core/drivers/pl011.c b/optee/optee_os/core/drivers/pl011.c new file mode 100644 index 0000000..da16392 --- /dev/null +++ b/optee/optee_os/core/drivers/pl011.c @@ -0,0 +1,251 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, Linaro Limited + */ +#include +#include +#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 void pl011_rx_intr_enable(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + + io_write32(base + UART_IMSC, UART_IMSC_RXIM); +} + +static void pl011_rx_intr_disable(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + + io_write32(base + UART_IMSC, 0); +} + +static const struct serial_ops pl011_ops = { + .flush = pl011_flush, + .getchar = pl011_getchar, + .have_rx_data = pl011_have_rx_data, + .putc = pl011_putc, + .rx_intr_enable = pl011_rx_intr_enable, + .rx_intr_disable = pl011_rx_intr_disable, +}; +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 receive interrupt */ + io_write32(base + UART_IMSC, UART_IMSC_RXIM); + + /* 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/plic.c b/optee/optee_os/core/drivers/plic.c new file mode 100644 index 0000000..3356dac --- /dev/null +++ b/optee/optee_os/core/drivers/plic.c @@ -0,0 +1,284 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2022-2023 NXP + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PLIC_PRIORITY_OFFSET 0 +#define PLIC_PENDING_OFFSET 0x1000 +#define PLIC_ENABLE_OFFSET 0x2000 +#define PLIC_THRESHOLD_OFFSET 0x200000 +#define PLIC_CLAIM_OFFSET 0x200004 + +#define PLIC_PRIORITY_SHIFT_PER_SOURCE U(2) +#define PLIC_PENDING_SHIFT_PER_SOURCE U(0) + +#define PLIC_ENABLE_SHIFT_PER_TARGET U(7) +#define PLIC_THRESHOLD_SHIFT_PER_TARGET U(12) +#define PLIC_CLAIM_SHIFT_PER_TARGET U(12) + +#define PLIC_PRIORITY(base, source) \ + ((base) + PLIC_PRIORITY_OFFSET + \ + SHIFT_U32(source, PLIC_PRIORITY_SHIFT_PER_SOURCE) \ + ) +#define PLIC_PENDING(base, source) \ + ((base) + PLIC_PENDING_OFFSET + \ + (4 * ((source) / 32)) \ + ) +#define PLIC_ENABLE(base, source, context) \ + ((base) + PLIC_ENABLE_OFFSET + \ + SHIFT_U32(context, PLIC_ENABLE_SHIFT_PER_TARGET) +\ + (4 * ((source) / 32)) \ + ) +#define PLIC_THRESHOLD(base, context) \ + ((base) + PLIC_THRESHOLD_OFFSET + \ + SHIFT_U32(context, PLIC_THRESHOLD_SHIFT_PER_TARGET) \ + ) +#define PLIC_COMPLETE(base, context) \ + ((base) + PLIC_CLAIM_OFFSET + \ + SHIFT_U32(context, PLIC_CLAIM_SHIFT_PER_TARGET) \ + ) +#define PLIC_CLAIM(base, context) PLIC_COMPLETE(base, context) + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, PLIC_BASE, PLIC_REG_SIZE); + +struct plic_data { + vaddr_t plic_base; + size_t max_it; + struct itr_chip chip; +}; + +static struct plic_data plic_data __nex_bss; + +/* + * We assume that each hart has M-mode and S-mode, so the contexts look like: + * PLIC context 0 is hart 0 M-mode + * PLIC context 1 is hart 0 S-mode + * PLIC context 2 is hart 1 M-mode + * PLIC context 3 is hart 1 S-mode + * ... + */ +static uint32_t plic_get_context(void) +{ + size_t hartid = get_core_pos(); + bool smode = IS_ENABLED(CFG_RISCV_S_MODE) ? true : false; + + return hartid * 2 + smode; +} + +static bool __maybe_unused +plic_is_pending(struct plic_data *pd, uint32_t source) +{ + return io_read32(PLIC_PENDING(pd->plic_base, source)) & + BIT(source % 32); +} + +static void plic_set_pending(struct plic_data *pd, uint32_t source) +{ + io_setbits32(PLIC_PENDING(pd->plic_base, source), BIT(source % 32)); +} + +static void plic_enable_interrupt(struct plic_data *pd, uint32_t source) +{ + uint32_t context = plic_get_context(); + + io_setbits32(PLIC_ENABLE(pd->plic_base, source, context), + BIT(source & 0x1f)); +} + +static uint32_t __maybe_unused +plic_get_interrupt_enable(struct plic_data *pd, uint32_t source) +{ + uint32_t context = plic_get_context(); + + return io_read32(PLIC_ENABLE(pd->plic_base, source, context)) & + BIT(source & 0x1f); +} + +static void plic_disable_interrupt(struct plic_data *pd, uint32_t source) +{ + uint32_t context = plic_get_context(); + + io_clrbits32(PLIC_ENABLE(pd->plic_base, source, context), + BIT(source & 0x1f)); +} + +static uint32_t __maybe_unused plic_get_threshold(struct plic_data *pd) +{ + uint32_t context = plic_get_context(); + + return io_read32(PLIC_THRESHOLD(pd->plic_base, context)); +} + +static void plic_set_threshold(struct plic_data *pd, uint32_t threshold) +{ + uint32_t context = plic_get_context(); + + io_write32(PLIC_THRESHOLD(pd->plic_base, context), threshold); +} + +static uint32_t __maybe_unused +plic_get_priority(struct plic_data *pd, uint32_t source) +{ + return io_read32(PLIC_PRIORITY(pd->plic_base, source)); +} + +static void plic_set_priority(struct plic_data *pd, uint32_t source, + uint32_t priority) +{ + io_write32(PLIC_PRIORITY(pd->plic_base, source), priority); +} + +static uint32_t plic_claim_interrupt(struct plic_data *pd) +{ + uint32_t context = plic_get_context(); + + return io_read32(PLIC_CLAIM(pd->plic_base, context)); +} + +static void plic_complete_interrupt(struct plic_data *pd, uint32_t source) +{ + uint32_t context = plic_get_context(); + + io_write32(PLIC_CLAIM(pd->plic_base, context), source); +} + +static void plic_op_add(struct itr_chip *chip, size_t it, + uint32_t type __unused, + uint32_t prio) +{ + struct plic_data *pd = container_of(chip, struct plic_data, chip); + + if (it > pd->max_it) + panic(); + + plic_disable_interrupt(pd, it); + plic_set_priority(pd, it, prio); +} + +static void plic_op_enable(struct itr_chip *chip, size_t it) +{ + struct plic_data *pd = container_of(chip, struct plic_data, chip); + + if (it > pd->max_it) + panic(); + + plic_enable_interrupt(pd, it); +} + +static void plic_op_disable(struct itr_chip *chip, size_t it) +{ + struct plic_data *pd = container_of(chip, struct plic_data, chip); + + if (it > pd->max_it) + panic(); + + plic_disable_interrupt(pd, it); +} + +static void plic_op_raise_pi(struct itr_chip *chip, size_t it) +{ + struct plic_data *pd = container_of(chip, struct plic_data, chip); + + if (it > pd->max_it) + panic(); + + plic_set_pending(pd, it); +} + +static void plic_op_raise_sgi(struct itr_chip *chip __unused, + size_t it __unused, uint32_t cpu_mask __unused) +{ +} + +static void plic_op_set_affinity(struct itr_chip *chip __unused, + size_t it __unused, uint8_t cpu_mask __unused) +{ +} + +static int plic_dt_get_irq(const uint32_t *properties __unused, + int count __unused, uint32_t *type __unused, + uint32_t *prio __unused) +{ + return DT_INFO_INVALID_INTERRUPT; +} + +static size_t probe_max_it(vaddr_t plic_base __unused) +{ + return PLIC_NUM_SOURCES; +} + +static const struct itr_ops plic_ops = { + .add = plic_op_add, + .mask = plic_op_disable, + .unmask = plic_op_enable, + .enable = plic_op_enable, + .disable = plic_op_disable, + .raise_pi = plic_op_raise_pi, + .raise_sgi = plic_op_raise_sgi, + .set_affinity = plic_op_set_affinity, +}; + +static void plic_init_base_addr(struct plic_data *pd, paddr_t plic_base_pa) +{ + vaddr_t plic_base = 0; + + assert(cpu_mmu_enabled()); + + plic_base = core_mmu_get_va(plic_base_pa, MEM_AREA_IO_SEC, + PLIC_REG_SIZE); + if (!plic_base) + panic(); + + pd->plic_base = plic_base; + pd->max_it = probe_max_it(plic_base); + pd->chip.ops = &plic_ops; + + if (IS_ENABLED(CFG_DT)) + pd->chip.dt_get_irq = plic_dt_get_irq; +} + +void plic_hart_init(void) +{ + /* TODO: To be called by secondary harts */ +} + +void plic_init(paddr_t plic_base_pa) +{ + struct plic_data *pd = &plic_data; + size_t n = 0; + + plic_init_base_addr(pd, plic_base_pa); + + for (n = 0; n <= pd->max_it; n++) { + plic_disable_interrupt(pd, n); + plic_set_priority(pd, n, 1); + } + + plic_set_threshold(pd, 0); + + interrupt_main_init(&plic_data.chip); +} + +void plic_it_handle(void) +{ + struct plic_data *pd = &plic_data; + uint32_t id = plic_claim_interrupt(pd); + + if (id > 0 && id <= pd->max_it) + interrupt_call_handlers(&pd->chip, id); + else + DMSG("ignoring interrupt %" PRIu32, id); + + plic_complete_interrupt(pd, id); +} diff --git a/optee/optee_os/core/drivers/pm/imx/gpcv2.c b/optee/optee_os/core/drivers/pm/imx/gpcv2.c new file mode 100644 index 0000000..ec21e68 --- /dev/null +++ b/optee/optee_os/core/drivers/pm/imx/gpcv2.c @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2017, 2023 NXP + * + * Peng Fan + */ + +#include +#include +#include + +#include "local.h" + +#define GPC_PGC_C1 0x840 +#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) + +static void imx_gpcv2_set_core_pgc(bool enable, uint32_t offset) +{ + vaddr_t va = core_mmu_get_va(GPC_BASE, MEM_AREA_IO_SEC, GPC_SIZE); + + if (enable) + io_setbits32(va + offset, GPC_PGC_PCG_MASK); + else + io_clrbits32(va + offset, GPC_PGC_PCG_MASK); +} + +void imx_gpcv2_set_core1_pup_by_software(void) +{ + vaddr_t va = core_mmu_get_va(GPC_BASE, MEM_AREA_IO_SEC, GPC_SIZE); + uint64_t timeout = timeout_init_us(10 * 1000); + + imx_gpcv2_set_core_pgc(true, GPC_PGC_C1); + + io_setbits32(va + GPC_CPU_PGC_SW_PUP_REQ, + GPC_PGC_SW_PDN_PUP_REQ_CORE1_MASK); + + while ((io_read32(va + GPC_CPU_PGC_SW_PUP_REQ) & + GPC_PGC_SW_PDN_PUP_REQ_CORE1_MASK)) { + if (timeout_elapsed(timeout)) + return; + } + + imx_gpcv2_set_core_pgc(false, GPC_PGC_C1); +} diff --git a/optee/optee_os/core/drivers/pm/imx/local.h b/optee/optee_os/core/drivers/pm/imx/local.h new file mode 100644 index 0000000..ee2a0bf --- /dev/null +++ b/optee/optee_os/core/drivers/pm/imx/local.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2023 NXP + */ + +#include + +/* + * Read the SRC GPR ARG register for the given core number + * @cpu Core number + */ +uint32_t imx_get_src_gpr_arg(unsigned int cpu); + +/* + * Set the SRC GPR ARG register for the given core number + * @cpu Core number + * @val Register value to set + */ +void imx_set_src_gpr_arg(unsigned int cpu, uint32_t val); + +/* + * Read the SRC GPR ENTRY register for the given core number + * @cpu Core number + */ +uint32_t imx_get_src_gpr_entry(unsigned int cpu); + +/* + * Set the SRC GPR ENTRY register for the given core number + * @cpu Core number + * @val Register value to set + */ +void imx_set_src_gpr_entry(unsigned int cpu, uint32_t val); + +/* + * Release the given core + * @cpu Core number + */ +void imx_src_release_secondary_core(unsigned int cpu); + +/* + * Shutdown the given core + * @cpu Core number + */ +void imx_src_shutdown_core(unsigned int cpu); + +/* + * GPC Core 1 power down + */ +void imx_gpcv2_set_core1_pup_by_software(void); diff --git a/optee/optee_os/core/drivers/pm/imx/psci.c b/optee/optee_os/core/drivers/pm/imx/psci.c new file mode 100644 index 0000000..a0e21dd --- /dev/null +++ b/optee/optee_os/core/drivers/pm/imx/psci.c @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2016 Freescale Semiconductor, Inc. + * Copyright 2023 NXP + * + * Peng Fan + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "local.h" + +#define IOMUXC_GPR5_OFFSET 0x14 +#define ARM_WFI_STAT_MASK(n) BIT(n) + +int psci_features(uint32_t psci_fid) +{ + switch (psci_fid) { + case ARM_SMCCC_VERSION: + case PSCI_PSCI_FEATURES: + case PSCI_VERSION: + 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) +{ + 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); + imx_set_src_gpr_entry(core_idx, virt_to_phys((void *)TEE_LOAD_ADDR)); + +#ifdef CFG_MX7 + imx_gpcv2_set_core1_pup_by_software(); + imx_src_release_secondary_core(core_idx); +#else + imx_src_release_secondary_core(core_idx); + imx_set_src_gpr_arg(core_idx, 0); +#endif /* CFG_MX7 */ + + IMSG("psci on ok"); + + return PSCI_RET_SUCCESS; +} + +int __noreturn psci_cpu_off(void) +{ + uint32_t core_id = get_core_pos(); + + IMSG("core_id: %" PRIu32, core_id); + + psci_armv7_cpu_off(); + + imx_set_src_gpr_arg(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 base = core_mmu_get_va(IOMUXC_BASE, MEM_AREA_IO_SEC, + IOMUXC_SIZE); + uint32_t cpu = affinity; + bool wfi = true; + + if (!soc_is_imx7ds()) + wfi = io_read32(base + IOMUXC_GPR5_OFFSET) & + ARM_WFI_STAT_MASK(cpu); + + if (imx_get_src_gpr_arg(cpu) == 0 || !wfi) + return PSCI_AFFINITY_LEVEL_ON; + + DMSG("cpu: %" PRIu32 "GPR: %" PRIx32, cpu, imx_get_src_gpr_arg(cpu)); + + while (imx_get_src_gpr_arg(cpu) != UINT_MAX) + ; + + imx_src_shutdown_core(cpu); + imx_set_src_gpr_arg(cpu, 0); + + return PSCI_AFFINITY_LEVEL_OFF; +} +#endif + +void __noreturn psci_system_off(void) +{ +#ifndef CFG_MX7ULP + imx_snvs_shutdown(); +#endif + dsb(); + + while (1) + ; +} + +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/drivers/pm/imx/src.c b/optee/optee_os/core/drivers/pm/imx/src.c new file mode 100644 index 0000000..d6cb46a --- /dev/null +++ b/optee/optee_os/core/drivers/pm/imx/src.c @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2019, 2023 NXP + */ + +#include +#include +#include +#include + +#include "local.h" + +#define SRC_SCR 0x000 +#define SRC_A7RCR0 0x004 +#define SRC_A7RCR1 0x008 +#if defined(CFG_MX7) +#define SRC_GPR1 0x074 +#else +#define SRC_GPR1 0x020 +#endif + +#define SRC_SCR_CORE1_RST_BIT(_cpu) BIT32(14 + (_cpu) - 1) +#define SRC_SCR_CORE1_ENABLE_BIT(_cpu) BIT32(22 + (_cpu) - 1) +#define SRC_A7RCR0_A7_CORE_RESET0_BIT(_cpu) BIT32((_cpu) - 1) +#define SRC_A7RCR1_A7_CORE1_ENABLE_BIT(_cpu) BIT32(1 + (_cpu) - 1) + +#define ENTRY_OFFSET(_cpu) ((_cpu) * 8) +#define ARG_OFFSET(_cpu) (ENTRY_OFFSET(_cpu) + 4) + +register_phys_mem(MEM_AREA_IO_SEC, SRC_BASE, SRC_SIZE); + +uint32_t imx_get_src_gpr_arg(unsigned int cpu) +{ + vaddr_t va = core_mmu_get_va(SRC_BASE, MEM_AREA_IO_SEC, SRC_SIZE); + + return io_read32(va + SRC_GPR1 + ARG_OFFSET(cpu)); +} + +void imx_set_src_gpr_arg(unsigned int cpu, uint32_t val) +{ + vaddr_t va = core_mmu_get_va(SRC_BASE, MEM_AREA_IO_SEC, SRC_SIZE); + + io_write32(va + SRC_GPR1 + ARG_OFFSET(cpu), val); +} + +uint32_t imx_get_src_gpr_entry(unsigned int cpu) +{ + vaddr_t va = core_mmu_get_va(SRC_BASE, MEM_AREA_IO_SEC, SRC_SIZE); + + return io_read32(va + SRC_GPR1 + ENTRY_OFFSET(cpu)); +} + +void imx_set_src_gpr_entry(unsigned int cpu, uint32_t val) +{ + vaddr_t va = core_mmu_get_va(SRC_BASE, MEM_AREA_IO_SEC, SRC_SIZE); + + io_write32(va + SRC_GPR1 + ENTRY_OFFSET(cpu), val); +} + +void imx_src_release_secondary_core(unsigned int cpu) +{ + vaddr_t va = core_mmu_get_va(SRC_BASE, MEM_AREA_IO_SEC, SRC_SIZE); + + if (soc_is_imx7ds()) + io_setbits32(va + SRC_A7RCR1, + SRC_A7RCR1_A7_CORE1_ENABLE_BIT(cpu)); + else + io_setbits32(va + SRC_SCR, SRC_SCR_CORE1_ENABLE_BIT(cpu) | + SRC_SCR_CORE1_RST_BIT(cpu)); +} + +void imx_src_shutdown_core(unsigned int cpu) +{ + vaddr_t va = core_mmu_get_va(SRC_BASE, MEM_AREA_IO_SEC, SRC_SIZE); + + if (soc_is_imx7ds()) { + io_clrbits32(va + SRC_A7RCR1, + SRC_A7RCR1_A7_CORE1_ENABLE_BIT(cpu)); + } else { + uint32_t mask = io_read32(va + SRC_SCR); + + mask &= ~SRC_SCR_CORE1_ENABLE_BIT(cpu); + mask |= SRC_SCR_CORE1_RST_BIT(cpu); + io_write32(va + SRC_SCR, mask); + } +} diff --git a/optee/optee_os/core/drivers/pm/imx/sub.mk b/optee/optee_os/core/drivers/pm/imx/sub.mk new file mode 100644 index 0000000..c3860cb --- /dev/null +++ b/optee/optee_os/core/drivers/pm/imx/sub.mk @@ -0,0 +1,3 @@ +srcs-y += psci.c +srcs-$(CFG_MX7) += gpcv2.c +srcs-$(CFG_MX6)$(CFG_MX7) += src.c 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..b52e455 --- /dev/null +++ b/optee/optee_os/core/drivers/pm/sub.mk @@ -0,0 +1,2 @@ +subdirs-$(CFG_ATMEL_PM) += sam +subdirs-$(CFG_IMX_PM) += imx diff --git a/optee/optee_os/core/drivers/regulator/regulator.c b/optee/optee_os/core/drivers/regulator/regulator.c new file mode 100644 index 0000000..e90c3cd --- /dev/null +++ b/optee/optee_os/core/drivers/regulator/regulator.c @@ -0,0 +1,492 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2023, STMicroelectronics + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static SLIST_HEAD(, regulator) regulator_device_list = + SLIST_HEAD_INITIALIZER(regulator); + +/* Access protection mutex complying the power state transitions context */ +static void lock_regulator(struct regulator *regulator) +{ + mutex_pm_aware_lock(®ulator->mutex); +} + +static void unlock_regulator(struct regulator *regulator) +{ + mutex_pm_aware_unlock(®ulator->mutex); +} + +static TEE_Result set_state(struct regulator *regulator, bool on_not_off) +{ + if (!regulator->ops->set_state) + return TEE_SUCCESS; + + return regulator->ops->set_state(regulator, on_not_off); +} + +static TEE_Result regulator_refcnt_enable(struct regulator *regulator) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + FMSG("%s", regulator_name(regulator)); + + if (regulator->supply) { + res = regulator_enable(regulator->supply); + if (res) + return res; + } + + lock_regulator(regulator); + + if (!regulator->refcount) { + res = set_state(regulator, true); + if (res) { + EMSG("regul %s set state failed with %#"PRIx32, + regulator_name(regulator), res); + + unlock_regulator(regulator); + + if (regulator->supply && + regulator_disable(regulator->supply)) + panic(); + + return res; + } + } + + regulator->refcount++; + if (!regulator->refcount) + panic(); + + FMSG("%s refcount: %u", regulator_name(regulator), regulator->refcount); + + unlock_regulator(regulator); + + return TEE_SUCCESS; +} + +TEE_Result regulator_enable(struct regulator *regulator) +{ + assert(regulator); + FMSG("%s", regulator_name(regulator)); + + if (regulator_is_always_on(regulator)) + return TEE_SUCCESS; + + return regulator_refcnt_enable(regulator); +} + +static TEE_Result regulator_refcnt_disable(struct regulator *regulator) +{ + FMSG("%s", regulator_name(regulator)); + + lock_regulator(regulator); + + if (regulator->refcount == 1) { + TEE_Result res = set_state(regulator, false); + + if (res) { + EMSG("regul %s set state failed with %#"PRIx32, + regulator_name(regulator), res); + unlock_regulator(regulator); + return res; + } + } + + if (!regulator->refcount) { + EMSG("Unbalanced %s", regulator_name(regulator)); + panic(); + } + + regulator->refcount--; + + FMSG("%s refcount: %u", regulator_name(regulator), regulator->refcount); + + unlock_regulator(regulator); + + if (regulator->supply && regulator_disable(regulator->supply)) { + /* We can't leave this unbalanced */ + EMSG("Can't disable %s", regulator_name(regulator->supply)); + panic(); + } + + return TEE_SUCCESS; +} + +TEE_Result regulator_disable(struct regulator *regulator) +{ + assert(regulator); + FMSG("%s", regulator_name(regulator)); + + if (regulator_is_always_on(regulator)) + return TEE_SUCCESS; + + return regulator_refcnt_disable(regulator); +} + +bool regulator_is_enabled(struct regulator *regulator) +{ + TEE_Result res = TEE_SUCCESS; + bool enabled = false; + + if (!regulator->ops->get_state) + return true; + + lock_regulator(regulator); + res = regulator->ops->get_state(regulator, &enabled); + unlock_regulator(regulator); + + if (res) + EMSG("regul %s get state failed with %#"PRIx32, + regulator_name(regulator), res); + + return !res && enabled; +} + +int regulator_get_voltage(struct regulator *regulator) +{ + TEE_Result res = TEE_SUCCESS; + int level_uv = regulator->min_uv; + + if (regulator->ops->get_voltage) { + res = regulator->ops->get_voltage(regulator, &level_uv); + if (res) { + EMSG("%s get_voltage failed with %#"PRIx32, + regulator_name(regulator), res); + level_uv = 0; + } + } + + return level_uv; +} + +TEE_Result regulator_set_voltage(struct regulator *regulator, int level_uv) +{ + TEE_Result res = TEE_ERROR_GENERIC; + int cur_uv = 0; + + assert(regulator); + FMSG("%s %duV", regulator_name(regulator), level_uv); + + if (level_uv < regulator->min_uv || level_uv > regulator->max_uv) + return TEE_ERROR_BAD_PARAMETERS; + + cur_uv = regulator_get_voltage(regulator); + if (level_uv == cur_uv) + return TEE_SUCCESS; + + if (!regulator->ops->set_voltage) + return TEE_ERROR_NOT_SUPPORTED; + + lock_regulator(regulator); + res = regulator->ops->set_voltage(regulator, level_uv); + unlock_regulator(regulator); + + if (res) { + EMSG("regul %s set volt failed with %#"PRIx32, + regulator_name(regulator), res); + return res; + } + + return TEE_SUCCESS; +} + +TEE_Result regulator_supported_voltages(struct regulator *regulator, + struct regulator_voltages_desc **desc, + const int **levels) +{ + assert(regulator && desc && levels); + + if (regulator->ops->supported_voltages) { + TEE_Result res = TEE_ERROR_GENERIC; + + res = regulator->ops->supported_voltages(regulator, desc, + levels); + if (res != TEE_ERROR_NOT_SUPPORTED) + return res; + } else { + *desc = ®ulator->voltages_fallback.desc; + *levels = regulator->voltages_fallback.levels; + } + + assert(((*desc)->type == VOLTAGE_TYPE_FULL_LIST && + (*levels)[0] >= regulator->min_uv && (*desc)->num_levels && + (*levels)[(*desc)->num_levels - 1] <= regulator->max_uv) || + ((*desc)->type == VOLTAGE_TYPE_INCREMENT && + (*levels)[0] >= regulator->min_uv && + (*levels)[1] <= regulator->max_uv)); + + return TEE_SUCCESS; +} + +TEE_Result regulator_register(struct regulator *regulator) +{ + TEE_Result res = TEE_SUCCESS; + int min_uv = 0; + int max_uv = 0; + int uv = 0; + + if (!regulator || !regulator->ops || + regulator->flags & ~REGULATOR_FLAGS_MASK) + return TEE_ERROR_BAD_PARAMETERS; + + mutex_pm_aware_init(®ulator->mutex); + + regulator_get_range(regulator, &min_uv, &max_uv); + if (min_uv > max_uv) + return TEE_ERROR_BAD_PARAMETERS; + + /* Sanitize regulator effective level */ + uv = regulator_get_voltage(regulator); + + if (uv < min_uv || uv > max_uv) { + res = regulator_set_voltage(regulator, min_uv); + if (res) + return res; + } + + /* Unbalanced enable refcount to keep always-on regulators enabled */ + if (regulator_is_always_on(regulator)) { + res = regulator_refcnt_enable(regulator); + if (res) + return res; + } + + /* Preset voltage list in case ops::supported_voltages is NULL */ + if (regulator->min_uv == regulator->max_uv) { + regulator->voltages_fallback.desc.type = VOLTAGE_TYPE_FULL_LIST; + regulator->voltages_fallback.desc.num_levels = 1; + regulator->voltages_fallback.levels[0] = regulator->min_uv; + } else { + regulator->voltages_fallback.desc.type = VOLTAGE_TYPE_INCREMENT; + regulator->voltages_fallback.levels[0] = regulator->min_uv; + regulator->voltages_fallback.levels[1] = regulator->max_uv; + regulator->voltages_fallback.levels[2] = 1; + } + + SLIST_INSERT_HEAD(®ulator_device_list, regulator, link); + + return TEE_SUCCESS; +} + +/* + * Clean-up regulators that are not used. + */ +static TEE_Result regulator_core_cleanup(void) +{ + struct regulator *regulator = NULL; + + SLIST_FOREACH(regulator, ®ulator_device_list, link) { + if (!regulator->refcount) { + DMSG("disable %s", regulator_name(regulator)); + lock_regulator(regulator); + set_state(regulator, false /* disable */); + unlock_regulator(regulator); + } + } + + regulator_print_tree(); + + return TEE_SUCCESS; +} + +release_init_resource(regulator_core_cleanup); + +/* Return updated message buffer position of NULL on failure */ +static __printf(3, 4) char *add_msg(char *cur, char *end, const char *fmt, ...) +{ + va_list ap = { }; + int max_len = end - cur; + int ret = 0; + + va_start(ap, fmt); + ret = vsnprintf(cur, max_len, fmt, ap); + va_end(ap); + + if (ret < 0 || ret >= max_len) + return NULL; + + return cur + ret; +} + +static struct regulator *find_next_regulator(struct regulator *parent, + struct regulator *sibling) +{ + struct regulator *regulator = NULL; + + if (sibling) + regulator = SLIST_NEXT(sibling, link); + else + regulator = SLIST_FIRST(®ulator_device_list); + + while (regulator && regulator->supply != parent) + regulator = SLIST_NEXT(regulator, link); + + return regulator; +} + +/* Regulator is the last supplied one by its supply in the registered list */ +static bool regulator_is_supply_last_supplied(struct regulator *regulator) +{ + return !find_next_regulator(regulator->supply, regulator); +} + +/* Supply last node may already be printed for indentation level @cur_indent */ +static bool indent_with_empty_string(struct regulator *node_regulator, + int node_indent, int cur_indent) +{ + struct regulator *r = node_regulator; + int n = 0; + + /* Find supply at indentation level @node_indent - @cur_indent - 1 */ + for (n = 0; n < node_indent - cur_indent - 1; n++) + r = r->supply; + + return regulator_is_supply_last_supplied(r); +} + +static void __maybe_unused print_regulator(struct regulator *regulator, + int indent) +{ + static const char * const level_unit[] = { "uV", "mV", "V" }; + int max_unit = ARRAY_SIZE(level_unit); + int level_max = 0; + int level_min = 0; + int level_cur = 0; + char msg_buf[128] = { }; + char *msg_end = msg_buf + sizeof(msg_buf); + char *msg = msg_buf; + int n_max = 0; + int n_min = 0; + int n_cur = 0; + int n = 0; + + if (indent) { + /* Indent for root clock level */ + msg = add_msg(msg, msg_end, " "); + if (!msg) + goto out; + + /* Indent for root supply to regulator supply levels */ + for (n = 0; n < indent - 1; n++) { + if (indent_with_empty_string(regulator, indent, n)) + msg = add_msg(msg, msg_end, " "); + else + msg = add_msg(msg, msg_end, "| "); + if (!msg) + goto out; + } + + /* Regulator indentation */ + if (regulator_is_supply_last_supplied(regulator)) + msg = add_msg(msg, msg_end, "`-- "); + else + msg = add_msg(msg, msg_end, "|-- "); + + if (!msg) + goto out; + } else { + /* Root supply indentation */ + msg = add_msg(msg, msg_end, "o- "); + } + + regulator_get_range(regulator, &level_min, &level_max); + level_cur = regulator_get_voltage(regulator); + + for (n_cur = 1; !(level_cur % 1000) && n_cur < max_unit; n_cur++) + level_cur /= 1000; + for (n_max = 1; !(level_max % 1000) && n_max < max_unit; n_max++) + level_max /= 1000; + for (n_min = 1; !(level_min % 1000) && n_min < max_unit; n_min++) + level_min /= 1000; + + msg = add_msg(msg, msg_end, "%s \t(%3s / refcnt %u / flags %#"PRIx32 + " / %d %s ", regulator_name(regulator), + regulator_is_enabled(regulator) ? "on " : "off", + regulator->refcount, regulator->flags, + level_cur, level_unit[n_cur - 1]); + if (!msg) + goto out; + + if (level_min == level_max) + msg = add_msg(msg, msg_end, "fixed)"); + else if (level_max == INT_MAX) + msg = add_msg(msg, msg_end, "[%d %s .. MAX])", + level_min, level_unit[n_min - 1]); + else + msg = add_msg(msg, msg_end, "[%d %s .. %d %s])", + level_min, level_unit[n_min - 1], + level_max, level_unit[n_max - 1]); + +out: + if (!msg) + snprintf(msg_end - 4, 4, "..."); + + DMSG("%s", msg_buf); +} + +static void print_tree(void) +{ + struct regulator *regulator = NULL; + struct regulator *parent = NULL; + struct regulator *next = NULL; + int indent = -1; + + while (true) { + next = find_next_regulator(parent, regulator); + if (next) { + print_regulator(next, indent + 1); + /* Enter the subtree of the next regulator */ + parent = next; + indent++; + regulator = NULL; + } else { + /* + * We've processed all children at this level. + * If parent is NULL we're at the top and are done. + */ + if (!parent) + break; + /* + * Move up one level to resume with the next + * regulator of the parent. + */ + regulator = parent; + parent = regulator->supply; + indent--; + } + } +} + +void regulator_print_tree(void) +{ + if (IS_ENABLED(CFG_DRIVERS_REGULATOR_PRINT_TREE) && + TRACE_LEVEL >= TRACE_DEBUG) { + DMSG("Regulator tree summary"); + if (SLIST_EMPTY(®ulator_device_list)) + DMSG("-- No registered regulator"); + else + print_tree(); + } +} diff --git a/optee/optee_os/core/drivers/regulator/regulator_dt.c b/optee/optee_os/core/drivers/regulator/regulator_dt.c new file mode 100644 index 0000000..4265419 --- /dev/null +++ b/optee/optee_os/core/drivers/regulator/regulator_dt.c @@ -0,0 +1,413 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022-2023, STMicroelectronics + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * struct regulator_property - DT binding boolean property names + * @name: Property name in the regulator DT node + * @flag: Mask of the related REGULATOR_* boolean property + */ +struct regulator_property { + const char *name; + unsigned int flag; +}; + +static struct regulator_property flag_prop[] = { + { + .name = "regulator-always-on", + .flag = REGULATOR_ALWAYS_ON, + }, + { + .name = "regulator-pull-down", + .flag = REGULATOR_PULL_DOWN, + }, + { + .name = "regulator-boot-on", + .flag = REGULATOR_BOOT_ON, + }, +}; + +/* + * struct pending_regu - Regulators waiting for their supply to be ready + * + * @fdt: DT to work on + * @node: Node of the regulator in @fdt + * @supply_phandle: Phandle in @fdt of the regulator supply, or 0 if no supply + * @regulator_allocated: True if framework allocates and frees @regulator + * @regulator: Regulator device instance + * @link: Link in pending regulators list + * + * When calling regulator_dt_register(), either the regulator depends on a + * supply that is not initialized, or this dependency is resolved (there is + * no supply or the supply is ready to use). + * + * In the former case, the regulator is placed in a pending regulator list. + * Each time a new regulator is successfully registered, we process the + * pending regulator list in case some pending regulators find their + * supply and finalize their registration and initialization. + * + * In the latter case, the regulator registration and initialization + * are processed. + */ +struct pending_regu { + const void *fdt; + int node; + int supply_phandle; + bool regulator_allocated; + struct regulator *regulator; + SLIST_ENTRY(pending_regu) link; +}; + +static SLIST_HEAD(, pending_regu) pending_regu_list = + SLIST_HEAD_INITIALIZER(pending_regu); + +/* Helper to find the phandle of a regulator supply */ +static TEE_Result get_supply_phandle(const void *fdt, int node, + const char *supply_name, + uint32_t *supply_phandle) +{ + char *supply_prop = NULL; + size_t prop_len = 0; + const fdt32_t *cuint = NULL; + int len = 0; + + prop_len = strlen(supply_name) + strlen("-supply") + 1; + supply_prop = calloc(1, prop_len); + if (!supply_prop) + return TEE_ERROR_OUT_OF_MEMORY; + + len = snprintf(supply_prop, prop_len, "%s-supply", supply_name); + assert(len > 0 && (size_t)len == prop_len - 1); + + cuint = fdt_getprop(fdt, node, supply_prop, &len); + free(supply_prop); + if (!cuint || (size_t)len != sizeof(*cuint)) { + if (len != -FDT_ERR_NOTFOUND) + return TEE_ERROR_GENERIC; + + *supply_phandle = 0; + + return TEE_SUCCESS; + } + + *supply_phandle = fdt32_to_cpu(*cuint); + assert(*supply_phandle); + + return TEE_SUCCESS; +} + +TEE_Result regulator_dt_get_supply(const void *fdt, int node, + const char *supply_name, + struct regulator **regulator) +{ + struct dt_driver_provider *provider = NULL; + TEE_Result res = TEE_ERROR_GENERIC; + uint32_t supply_phandle = 0; + + res = get_supply_phandle(fdt, node, supply_name, &supply_phandle); + if (res) + return res; + + provider = dt_driver_get_provider_by_phandle(supply_phandle, + DT_DRIVER_REGULATOR); + if (!provider) + return TEE_ERROR_DEFER_DRIVER_INIT; + + *regulator = dt_driver_provider_priv_data(provider); + assert(*regulator); + + return TEE_SUCCESS; +} + +/* Helper function to register a regulator provider instance */ +static TEE_Result regulator_register_provider(const void *fdt, int node, + struct regulator *regulator) +{ + TEE_Result res = TEE_ERROR_GENERIC; + uint32_t phandle = 0; + + phandle = fdt_get_phandle(fdt, node); + switch (phandle) { + case 0: + /* We can ignore regulators without any phandle */ + return TEE_SUCCESS; + case (uint32_t)-1: + DMSG("Failed to find provider phandle"); + return TEE_ERROR_GENERIC; + default: + res = dt_driver_register_provider(fdt, node, NULL, regulator, + DT_DRIVER_REGULATOR); + if (res) + EMSG("Can't register regulator provider %s: %#"PRIx32, + regulator_name(regulator), res); + + return res; + } +} + +static TEE_Result register_final(const void *fdt, int node, + struct regulator *regulator) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + FMSG("Regulator: finalize %s registering", regulator_name(regulator)); + + res = regulator_register(regulator); + if (res) + return res; + + if (regulator->ops->supplied_init) { + res = regulator->ops->supplied_init(regulator, fdt, node); + if (res) + return res; + } + + return regulator_register_provider(fdt, node, regulator); +} + +/* + * Pending regulators list: stores all regulator devices registered by their + * driver but not yet available to consumers as their dependency on their + * regulator supply is not yet resolved (supply has not been initialized yet). + */ + +static void __maybe_unused print_pending_regulators(void) +{ + struct pending_regu *pending = NULL; + + SLIST_FOREACH(pending, &pending_regu_list, link) + DMSG("Pending regulator %s", + regulator_name(pending->regulator)); +} + +/* + * Returns true if at least 1 regulator found its supply and finalized its + * registration. + */ +static bool process_pending_list(void) +{ + struct dt_driver_provider *p = NULL; + struct pending_regu *pending = NULL; + struct pending_regu *next = NULL; + bool supplied = false; + + SLIST_FOREACH_SAFE(pending, &pending_regu_list, link, next) { + p = dt_driver_get_provider_by_phandle(pending->supply_phandle, + DT_DRIVER_REGULATOR); + if (!p) + continue; + + pending->regulator->supply = dt_driver_provider_priv_data(p); + + if (register_final(pending->fdt, pending->node, + pending->regulator)) + panic(); + + SLIST_REMOVE(&pending_regu_list, pending, pending_regu, link); + free(pending); + + supplied = true; + } + + return supplied; +} + +/* + * Attempt to register pending regulators once their supply is found. + * Return true if pending regulator list is empty upon processing. + */ +static bool resolve_pending_list(void) +{ + while (process_pending_list()) + ; + + return SLIST_EMPTY(&pending_regu_list); +} + +/* Adds a regulator to the pending list: those waiting for their supply */ +static TEE_Result add_to_pending_list(const void *fdt, int node, + struct regulator *regulator, + uint32_t supply_phandle, + bool regulator_allocated) +{ + struct pending_regu *pending = NULL; + + pending = calloc(1, sizeof(*pending)); + if (!pending) + return TEE_ERROR_OUT_OF_MEMORY; + + *pending = (struct pending_regu){ + .fdt = fdt, + .node = node, + .supply_phandle = supply_phandle, + .regulator = regulator, + .regulator_allocated = regulator_allocated, + }; + + SLIST_INSERT_HEAD(&pending_regu_list, pending, link); + + return TEE_SUCCESS; +} + +static TEE_Result parse_dt(const void *fdt, int node, + struct regulator *regulator) +{ + struct regulator_property *fp = NULL; + const fdt32_t *cuint = NULL; + int len = 0; + + FMSG("Regulator: parse DT node %s", fdt_get_name(fdt, node, NULL)); + + cuint = fdt_getprop(fdt, node, "regulator-name", NULL); + if (cuint) { + /* Replace name with the one found from the DT node */ + char *name = (char *)cuint; + + free(regulator->name); + regulator->name = strdup(name); + if (!regulator->name) + return TEE_ERROR_OUT_OF_MEMORY; + } + + for (fp = flag_prop; fp < (flag_prop + ARRAY_SIZE(flag_prop)); fp++) + if (fdt_getprop(fdt, node, fp->name, NULL)) + regulator->flags |= fp->flag; + + cuint = fdt_getprop(fdt, node, "regulator-min-microvolt", &len); + if (cuint && len == sizeof(*cuint)) + regulator->min_uv = fdt32_to_cpu(*cuint); + else if (cuint || len != -FDT_ERR_NOTFOUND) + panic(); + + cuint = fdt_getprop(fdt, node, "regulator-max-microvolt", &len); + if (cuint && len == sizeof(*cuint)) { + regulator->max_uv = fdt32_to_cpu(*cuint); + + if (regulator->max_uv < regulator->min_uv) { + EMSG("Regulator %s max_uv %d < %d", + regulator_name(regulator), regulator->max_uv, + regulator->min_uv); + + return TEE_ERROR_GENERIC; + } + } else if (cuint || len != -FDT_ERR_NOTFOUND) { + panic(); + } else { + regulator->max_uv = INT_MAX; + } + + return TEE_SUCCESS; +} + +/* + * API function to register a DRIVER_REGULATOR provider instance. + * The registration can be deferred if the regulator supply (if any) + * is not yet registered, in which case the regulator is placed in + * a regulator pending list. + */ +TEE_Result regulator_dt_register(const void *fdt, int node, int provider_node, + const struct regu_dt_desc *desc) +{ + TEE_Result res = TEE_ERROR_OUT_OF_MEMORY; + struct regulator *regulator = NULL; + uint32_t supply_phandle = 0; + char *name = NULL; + + assert(desc); + + if (!desc->regulator) { + regulator = calloc(1, sizeof(*regulator)); + if (!regulator) + return TEE_ERROR_OUT_OF_MEMORY; + } else { + regulator = desc->regulator; + memset(regulator, 0, sizeof(*regulator)); + } + + if (desc->name) { + /* Will be freed if overridden by DT node content */ + name = strdup(desc->name); + if (!name) + goto err_free; + } + + *regulator = (struct regulator){ + .name = name, + .ops = desc->ops, + .priv = desc->priv, + }; + + res = parse_dt(fdt, node, regulator); + if (res) + goto err_free; + + if (desc->supply_name) { + res = get_supply_phandle(fdt, provider_node, desc->supply_name, + &supply_phandle); + if (res) + goto err_free; + } + + if (supply_phandle) { + res = add_to_pending_list(fdt, node, regulator, supply_phandle, + !desc->regulator); + if (res) + goto err_free; + } else { + res = register_final(fdt, node, regulator); + if (res) + goto err_free; + } + + resolve_pending_list(); + + return TEE_SUCCESS; + +err_free: + /* This function cannot return TEE_ERROR_DEFER_DRIVER_INIT */ + assert(res != TEE_ERROR_DEFER_DRIVER_INIT); + + free(regulator->name); + if (!desc->regulator) + free(regulator); + + return res; +} + +static TEE_Result release_regulator_pending_lists(void) +{ + struct pending_regu *pending = NULL; + struct pending_regu *next = NULL; + + if (!SLIST_EMPTY(&pending_regu_list)) + DMSG("Some regulators were not supplied:"); + + SLIST_FOREACH_SAFE(pending, &pending_regu_list, link, next) { + DMSG(" Unsupplied regulator %s", + regulator_name(pending->regulator)); + + SLIST_REMOVE(&pending_regu_list, pending, pending_regu, link); + if (pending->regulator_allocated) + free(pending->regulator); + free(pending); + } + + return TEE_SUCCESS; +} + +release_init_resource(release_regulator_pending_lists); diff --git a/optee/optee_os/core/drivers/regulator/regulator_fixed.c b/optee/optee_os/core/drivers/regulator/regulator_fixed.c new file mode 100644 index 0000000..0037cad --- /dev/null +++ b/optee/optee_os/core/drivers/regulator/regulator_fixed.c @@ -0,0 +1,184 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022-2023, STMicroelectronics + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static_assert(GPIO_LEVEL_HIGH == 1 && GPIO_LEVEL_LOW == 0); + +/* + * struct regulator_gpio - GPIO controlled regulator + * @regulator: Preallocated regulator instance + * @enable_gpio: GPIO for the enable state of the regulator or NULL if always on + * @enable_delay: Time (in microsecond) for the regulator to get enabled + * @off_on_delay: Min time (in microsecond) between enable and disable request + * @off_on_us: Timestamp of the last disable request + */ +struct regulator_fixed { + struct regulator regulator; + struct gpio *enable_gpio; + unsigned int enable_delay; + unsigned int off_on_delay; + uint64_t off_on_us; +}; + +static struct regulator_fixed *regulator_priv(struct regulator *regulator) +{ + return container_of(regulator, struct regulator_fixed, regulator); +} + +static TEE_Result fixed_set_state(struct regulator *regulator, bool enabled) +{ + struct regulator_fixed *regu = regulator_priv(regulator); + + if (regu->enable_gpio) { + if (enabled) { + while (!timeout_elapsed(regu->off_on_us)) + udelay(1); + gpio_set_value(regu->enable_gpio, GPIO_LEVEL_HIGH); + udelay(regu->enable_delay); + } else { + regu->off_on_us = timeout_init_us(regu->off_on_delay); + gpio_set_value(regu->enable_gpio, GPIO_LEVEL_LOW); + } + } + + return TEE_SUCCESS; +} + +static TEE_Result fixed_get_state(struct regulator *regulator, bool *enabled) +{ + struct regulator_fixed *regu = regulator_priv(regulator); + + if (regu->enable_gpio) + *enabled = gpio_get_value(regu->enable_gpio); + else + *enabled = true; + + return TEE_SUCCESS; +} + +static const struct regulator_ops fixed_regulator_ops = { + .set_state = fixed_set_state, + .get_state = fixed_get_state, +}; + +static TEE_Result get_enable_gpio(const void *fdt, int node, + struct regulator_fixed *regu) +{ + TEE_Result res = TEE_ERROR_GENERIC; + const fdt32_t *cuint = NULL; + struct gpio *gpio = NULL; + void *gpio_ref = &gpio; + + res = dt_driver_device_from_node_idx_prop("gpios", fdt, node, 0, + DT_DRIVER_GPIO, gpio_ref); + if (res == TEE_ERROR_ITEM_NOT_FOUND) + res = dt_driver_device_from_node_idx_prop("gpio", fdt, node, 0, + DT_DRIVER_GPIO, + gpio_ref); + if (res == TEE_ERROR_ITEM_NOT_FOUND) { + regu->enable_gpio = NULL; + + return TEE_SUCCESS; + } + if (res) + return res; + + /* Override active level phandle flag, as per DT bindings */ + if (dt_have_prop(fdt, node, "enable-active-high")) + gpio->dt_flags &= ~GPIO_ACTIVE_LOW; + else + gpio->dt_flags |= GPIO_ACTIVE_LOW; + + /* Override open drain/open source phandle flag, as per DT bindings */ + if (dt_have_prop(fdt, node, "gpio-open-drain")) + gpio->dt_flags |= GPIO_LINE_OPEN_DRAIN; + else + gpio->dt_flags &= ~GPIO_LINE_OPEN_DRAIN; + + cuint = fdt_getprop(fdt, node, "startup-delay-us", NULL); + if (cuint) + regu->enable_delay = fdt32_to_cpu(*cuint); + + cuint = fdt_getprop(fdt, node, "off-on-delay-us", NULL); + if (cuint) + regu->off_on_delay = fdt32_to_cpu(*cuint); + + gpio_set_direction(gpio, GPIO_DIR_OUT); + + regu->enable_gpio = gpio; + + return TEE_SUCCESS; +} + +static TEE_Result fixed_regulator_probe(const void *fdt, int node, + const void *compat_data __unused) +{ + struct regulator_fixed *regu = NULL; + TEE_Result res = TEE_ERROR_GENERIC; + struct regu_dt_desc desc = { }; + const char *supply_name = NULL; + const char *type = NULL; + char *regu_name = NULL; + + regu_name = (char *)fdt_get_name(fdt, node, NULL); + + type = fdt_getprop(fdt, node, "regulator-type", NULL); + if (type && strcmp(type, "voltage")) { + EMSG("Regulator gpio node %s: type %s not supported", + regu_name, type); + return TEE_ERROR_GENERIC; + } + + regu = calloc(1, sizeof(*regu)); + if (!regu) + return TEE_ERROR_OUT_OF_MEMORY; + + res = get_enable_gpio(fdt, node, regu); + if (res) + goto err; + + if (fdt_getprop(fdt, node, "vin-supply", NULL)) + supply_name = "vin"; + + desc = (struct regu_dt_desc){ + .name = regu_name, + .ops = &fixed_regulator_ops, + .supply_name = supply_name, + .regulator = ®u->regulator, + }; + + res = regulator_dt_register(fdt, node, node, &desc); + if (res) { + EMSG("Can't register regulator %s: %#"PRIx32, regu_name, res); + goto err; + } + + return TEE_SUCCESS; + +err: + free(regu); + + return res; +} + +static const struct dt_device_match regulator_match_table[] = { + { .compatible = "regulator-fixed" }, + { } +}; + +DEFINE_DT_DRIVER(fixed_regulator_dt_driver) = { + .name = "regulator-fixed", + .match_table = regulator_match_table, + .probe = fixed_regulator_probe, +}; diff --git a/optee/optee_os/core/drivers/regulator/regulator_gpio.c b/optee/optee_os/core/drivers/regulator/regulator_gpio.c new file mode 100644 index 0000000..e48d585 --- /dev/null +++ b/optee/optee_os/core/drivers/regulator/regulator_gpio.c @@ -0,0 +1,300 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2023, STMicroelectronics + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static_assert(GPIO_LEVEL_HIGH == 1 && GPIO_LEVEL_LOW == 0); + +/* + * struct regulator_gpio - GPIO controlled regulator + * @regulator: Preallocated regulator instance + * @enable_gpio: GPIO for the enable state of the regulator or NULL if always on + * @enable_delay: Time (in microsecond) for the regulator to get enabled + * @voltage_gpio: GPIO for the voltage level selection + * @levels_desc: Supported voltage levels description + * @voltage_levels_uv: 2 cells array supported voltage levels, increasing order + * @voltage_level_high: True if higher voltage level relates to GPIO state 1 + */ +struct regulator_gpio { + struct regulator regulator; + struct gpio *enable_gpio; + unsigned int enable_delay; + struct gpio *voltage_gpio; + struct regulator_voltages_desc levels_desc; + int voltage_levels_uv[2]; + bool voltage_level_high; +}; + +static struct regulator_gpio *regulator_priv(struct regulator *regulator) +{ + return container_of(regulator, struct regulator_gpio, regulator); +} + +static TEE_Result regulator_gpio_set_state(struct regulator *regulator, + bool enabled) +{ + struct regulator_gpio *regu = regulator_priv(regulator); + + if (regu->enable_gpio) { + if (enabled) { + gpio_set_value(regu->enable_gpio, GPIO_LEVEL_HIGH); + if (regu->enable_delay) + udelay(regu->enable_delay); + } else { + gpio_set_value(regu->enable_gpio, GPIO_LEVEL_LOW); + } + } + + return TEE_SUCCESS; +} + +static TEE_Result regulator_gpio_read_state(struct regulator *regulator, + bool *enabled) +{ + struct regulator_gpio *regu = regulator_priv(regulator); + + if (regu->enable_gpio) + *enabled = gpio_get_value(regu->enable_gpio); + else + *enabled = true; + + return TEE_SUCCESS; +} + +static TEE_Result regulator_gpio_set_voltage(struct regulator *regulator, + int level_uv) +{ + struct regulator_gpio *regu = regulator_priv(regulator); + enum gpio_level value = GPIO_LEVEL_LOW; + + if (level_uv == regu->voltage_levels_uv[0]) + value = GPIO_LEVEL_LOW; + else if (level_uv == regu->voltage_levels_uv[1]) + value = GPIO_LEVEL_HIGH; + else + return TEE_ERROR_BAD_PARAMETERS; + + if (!regu->voltage_level_high) + value = !value; + + gpio_set_value(regu->voltage_gpio, value); + + return TEE_SUCCESS; +} + +static TEE_Result regulator_gpio_read_voltage(struct regulator *regulator, + int *level_uv) +{ + struct regulator_gpio *regu = regulator_priv(regulator); + enum gpio_level value = gpio_get_value(regu->voltage_gpio); + + if (!regu->voltage_level_high) + value = !value; + + *level_uv = regu->voltage_levels_uv[value]; + + return TEE_SUCCESS; +} + +static TEE_Result regulator_gpio_voltages(struct regulator *regulator, + struct regulator_voltages_desc **desc, + const int **levels) +{ + struct regulator_gpio *regu = regulator_priv(regulator); + + *desc = ®u->levels_desc; + *levels = regu->voltage_levels_uv; + + return TEE_SUCCESS; +} + +static const struct regulator_ops regulator_gpio_ops = { + .set_state = regulator_gpio_set_state, + .get_state = regulator_gpio_read_state, + .set_voltage = regulator_gpio_set_voltage, + .get_voltage = regulator_gpio_read_voltage, + .supported_voltages = regulator_gpio_voltages, +}; + +static TEE_Result get_enable_gpio(const void *fdt, int node, + struct regulator_gpio *regu) +{ + TEE_Result res = TEE_ERROR_GENERIC; + const fdt32_t *cuint = NULL; + struct gpio *gpio = NULL; + + res = gpio_dt_get_by_index(fdt, node, 0, "enable", &gpio); + if (res == TEE_ERROR_ITEM_NOT_FOUND) { + regu->enable_gpio = NULL; + + return TEE_SUCCESS; + } + if (res) + return res; + + /* Override active level phandle flag, as per DT bindings */ + if (dt_have_prop(fdt, node, "enable-active-high")) + gpio->dt_flags &= ~GPIO_ACTIVE_LOW; + else + gpio->dt_flags |= GPIO_ACTIVE_LOW; + + /* Override open drain/open source phandle flag, as per DT bindings */ + if (dt_have_prop(fdt, node, "gpio-open-drain")) + gpio->dt_flags |= GPIO_LINE_OPEN_DRAIN; + else + gpio->dt_flags &= ~GPIO_LINE_OPEN_DRAIN; + + cuint = fdt_getprop(fdt, node, "startup-delay-us", NULL); + if (cuint) + regu->enable_delay = fdt32_to_cpu(*cuint); + + gpio_set_direction(gpio, GPIO_DIR_OUT); + + regu->enable_gpio = gpio; + + return TEE_SUCCESS; +} + +static TEE_Result get_voltage_level_gpio(const void *fdt, int node, + struct regulator_gpio *regu) +{ + TEE_Result res = TEE_ERROR_GENERIC; + const fdt32_t *cuint = NULL; + struct gpio *gpio = NULL; + void *gpio_ref = &gpio; + int level0 = 0; + int level1 = 0; + int len = 0; + + res = dt_driver_device_from_node_idx_prop("gpios", fdt, node, 0, + DT_DRIVER_GPIO, gpio_ref); + if (res) + return res; + + /* + * DT bindings allows more than 1 GPIO to control more than + * 2 voltage levels. As it's not used so far in known platforms + * this implementation is simplified to support only 2 voltage + * levels controlled with a single GPIO. + */ + if (dt_driver_device_from_node_idx_prop("gpios", fdt, node, 1, + DT_DRIVER_GPIO, gpio_ref) != + TEE_ERROR_ITEM_NOT_FOUND) { + EMSG("Multiple GPIOs not supported for level control"); + return TEE_ERROR_GENERIC; + } + + cuint = fdt_getprop(fdt, node, "states", &len); + if (!cuint || len != 4 * sizeof(fdt32_t)) { + EMSG("Node %s expects 2 levels from property \"states\"", + fdt_get_name(fdt, node, NULL)); + return TEE_ERROR_GENERIC; + } + + if (fdt32_to_cpu(*(cuint + 1))) { + assert(!fdt32_to_cpu(*(cuint + 3))); + level1 = fdt32_to_cpu(*(cuint)); + level0 = fdt32_to_cpu(*(cuint + 2)); + } else { + assert(fdt32_to_cpu(*(cuint + 3)) == 1); + level0 = fdt32_to_cpu(*(cuint)); + level1 = fdt32_to_cpu(*(cuint + 2)); + } + + /* Get the 2 supported levels in increasing order */ + regu->levels_desc.type = VOLTAGE_TYPE_FULL_LIST; + regu->levels_desc.num_levels = 2; + if (level0 < level1) { + regu->voltage_levels_uv[0] = level0; + regu->voltage_levels_uv[1] = level1; + regu->voltage_level_high = true; + } else { + regu->voltage_levels_uv[0] = level1; + regu->voltage_levels_uv[1] = level0; + regu->voltage_level_high = false; + } + + gpio_set_direction(gpio, GPIO_DIR_OUT); + + regu->voltage_gpio = gpio; + + return TEE_SUCCESS; +} + +static TEE_Result regulator_gpio_probe(const void *fdt, int node, + const void *compat_data __unused) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct regulator_gpio *regu = NULL; + struct regu_dt_desc desc = { }; + const char *supply_name = NULL; + const char *type = NULL; + char *regu_name = NULL; + + regu_name = (char *)fdt_get_name(fdt, node, NULL); + + type = fdt_getprop(fdt, node, "regulator-type", NULL); + if (type && strcmp(type, "voltage")) { + EMSG("Regulator node %s: type \"%s\" not supported", + regu_name, type); + res = TEE_ERROR_GENERIC; + goto err; + } + + regu = calloc(1, sizeof(*regu)); + if (!regu) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto err; + } + + res = get_enable_gpio(fdt, node, regu); + if (res) + goto err; + + res = get_voltage_level_gpio(fdt, node, regu); + if (res) + goto err; + + if (fdt_getprop(fdt, node, "vin-supply", NULL)) + supply_name = "vin"; + + desc = (struct regu_dt_desc){ + .name = regu_name, + .ops = ®ulator_gpio_ops, + .supply_name = supply_name, + .regulator = ®u->regulator, + }; + + res = regulator_dt_register(fdt, node, node, &desc); + if (res) { + EMSG("Can't register regulator %s: %#"PRIx32, regu_name, res); + goto err; + } + + return TEE_SUCCESS; + +err: + free(regu); + + return res; +} + +static const struct dt_device_match regulator_gpio_match_table[] = { + { .compatible = "regulator-gpio" }, + { } +}; + +DEFINE_DT_DRIVER(regulator_gpio_dt_driver) = { + .name = "regulator-gpio", + .match_table = regulator_gpio_match_table, + .probe = regulator_gpio_probe, +}; diff --git a/optee/optee_os/core/drivers/regulator/stm32_vrefbuf.c b/optee/optee_os/core/drivers/regulator/stm32_vrefbuf.c new file mode 100644 index 0000000..18ccb09 --- /dev/null +++ b/optee/optee_os/core/drivers/regulator/stm32_vrefbuf.c @@ -0,0 +1,390 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021-2023, STMicroelectronics + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* STM32 VREFBUF registers */ +#define VREFBUF_CSR U(0) + +/* STM32 VREFBUF CSR bitfields */ + +/* VRS bit 3 is unused because the voltage is not specified */ +#define VREFBUF_CSR_VRS GENMASK_32(5, 4) +#define VREFBUF_CSR_VRS_SHIFT U(4) +#define INV_VRS(x) ((~(x)) & VREFBUF_CSR_VRS) + +#define VREFBUF_CSR_VRR BIT(3) +#define VREFBUF_CSR_HIZ BIT(1) +#define VREFBUF_CSR_ENVR BIT(0) + +#define TIMEOUT_US_10MS U(10 * 1000) +#define TIMEOUT_US_1MS U(1 * 1000) + +#define VREFBUF_LEVELS_COUNT U(4) + +/* + * struct vrefbuf_compat - Compatibility data + * @voltages: Voltage levels supported + */ +struct vrefbuf_compat { + int voltages[VREFBUF_LEVELS_COUNT]; +}; + +/* + * struct vrefbuf_regul - VREFBUF regulator + * @base: IO memory base address + * @clock: VREFBUF access bus clock + * @regulator: Preallocated instance for the regulator + * @compat: Compatibility data + * @voltages_desc: Supported voltage level description + * @voltages_level: Supplorted levels description + * @voltages_start_index: start index in compat for supported levels + */ +struct vrefbuf_regul { + vaddr_t base; + struct clk *clock; + uint64_t disable_timeout; + struct regulator regulator; + const struct vrefbuf_compat *compat; + struct regulator_voltages_desc voltages_desc; + size_t voltages_start_index; +}; + +static const struct vrefbuf_compat stm32mp15_vrefbuf_compat = { + .voltages = { + /* Matches resp. VRS = 011b, 010b, 001b, 000b */ + 1500000, 1800000, 2048000, 2500000, + }, +}; + +static const struct vrefbuf_compat stm32mp13_vrefbuf_compat = { + .voltages = { + /* Matches resp. VRS = 011b, 010b, 001b, 000b */ + 1650000, 1800000, 2048000, 2500000, + }, +}; + +/* Expect at most 1 instance */ +static struct vrefbuf_regul *stm32_vrefbuf; + +struct regulator *stm32_vrefbuf_regulator(void) +{ + if (!stm32_vrefbuf) + return NULL; + + return &stm32_vrefbuf->regulator; +} + +static struct vrefbuf_regul *regulator_to_vr(struct regulator *regulator) +{ + return container_of(regulator, struct vrefbuf_regul, regulator); +} + +static TEE_Result vrefbuf_wait_ready(struct vrefbuf_regul *vr) +{ + uint32_t val = 0; + + if (IO_READ32_POLL_TIMEOUT(vr->base + VREFBUF_CSR, val, + val & VREFBUF_CSR_VRR, 0, TIMEOUT_US_10MS)) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +static TEE_Result vrefbuf_set_state(struct regulator *regulator, bool enable) +{ + struct vrefbuf_regul *vr = regulator_to_vr(regulator); + TEE_Result res = TEE_ERROR_GENERIC; + + res = clk_enable(vr->clock); + if (res) + return res; + + if (enable) { + io_clrbits32(vr->base + VREFBUF_CSR, VREFBUF_CSR_HIZ); + + /* + * If first enable after boot or if it was disabled since + * less than 1ms, then wait for 1ms in pull down mode to + * avoid an overshoot. + */ + if (!vr->disable_timeout || + !timeout_elapsed(vr->disable_timeout)) + udelay(1000); + + io_setbits32(vr->base + VREFBUF_CSR, VREFBUF_CSR_ENVR); + + if (vrefbuf_wait_ready(vr) != TEE_SUCCESS) { + clk_disable(vr->clock); + + return TEE_ERROR_GENERIC; + } + } else { + io_clrbits32(vr->base + VREFBUF_CSR, VREFBUF_CSR_ENVR); + + vr->disable_timeout = timeout_init_us(TIMEOUT_US_1MS); + } + + clk_disable(vr->clock); + + return TEE_SUCCESS; +} + +static TEE_Result vrefbuf_get_state(struct regulator *regulator, bool *enabled) +{ + struct vrefbuf_regul *vr = regulator_to_vr(regulator); + TEE_Result res = TEE_ERROR_GENERIC; + + res = clk_enable(vr->clock); + if (res) + return res; + + *enabled = io_read32(vr->base + VREFBUF_CSR) & VREFBUF_CSR_VRR; + + clk_disable(vr->clock); + + return TEE_SUCCESS; +} + +static TEE_Result vrefbuf_get_voltage(struct regulator *regulator, + int *level_uv) +{ + struct vrefbuf_regul *vr = regulator_to_vr(regulator); + TEE_Result res = TEE_ERROR_GENERIC; + uint32_t index = 0; + + res = clk_enable(vr->clock); + if (res) + return res; + + index = io_read32(vr->base + VREFBUF_CSR) & VREFBUF_CSR_VRS; + index = INV_VRS(index) >> VREFBUF_CSR_VRS_SHIFT; + + clk_disable(vr->clock); + + *level_uv = vr->compat->voltages[index]; + + return TEE_SUCCESS; +} + +static TEE_Result vrefbuf_set_voltage(struct regulator *regulator, int level_uv) +{ + struct vrefbuf_regul *vr = regulator_to_vr(regulator); + TEE_Result res = TEE_ERROR_GENERIC; + size_t i = 0; + + for (i = 0 ; i < ARRAY_SIZE(vr->compat->voltages) ; i++) { + if (vr->compat->voltages[i] == level_uv) { + uint32_t val = INV_VRS(i << VREFBUF_CSR_VRS_SHIFT); + + res = clk_enable(vr->clock); + if (res) + return res; + + io_clrsetbits32(vr->base + VREFBUF_CSR, VREFBUF_CSR_VRS, + val); + + clk_disable(vr->clock); + + return TEE_SUCCESS; + } + } + + EMSG("Failed to set voltage on vrefbuf"); + + return TEE_ERROR_BAD_PARAMETERS; +} + +static TEE_Result vrefbuf_list_voltages(struct regulator *regulator __unused, + struct regulator_voltages_desc **desc, + const int **levels) +{ + struct vrefbuf_regul *vr = regulator_to_vr(regulator); + const int *levels_ref = vr->compat->voltages; + + *desc = &vr->voltages_desc; + *levels = levels_ref + vr->voltages_start_index; + + return TEE_SUCCESS; +} + +static TEE_Result set_voltages_desc(struct regulator *regulator) +{ + struct vrefbuf_regul *vr = regulator_to_vr(regulator); + size_t num_levels = ARRAY_SIZE(vr->compat->voltages); + int index_high = num_levels - 1; + int index_low = 0; + int n = 0; + + vr->voltages_desc.type = VOLTAGE_TYPE_FULL_LIST; + + for (n = 0; n <= index_high; n++) + if (vr->compat->voltages[n] >= regulator->min_uv) + break; + if (n > index_high) + return TEE_ERROR_GENERIC; + index_low = n; + + for (n = index_high; n >= index_low; n--) + if (vr->compat->voltages[n] <= regulator->max_uv) + break; + if (n < index_low) + return TEE_ERROR_GENERIC; + index_high = n; + + assert(index_high - index_low + 1 >= 0 && index_low >= 0); + + vr->voltages_desc.type = VOLTAGE_TYPE_FULL_LIST; + vr->voltages_desc.num_levels = index_high - index_low + 1; + vr->voltages_start_index = index_low; + + return TEE_SUCCESS; +} + +static TEE_Result stm32_vrefbuf_pm(enum pm_op op, unsigned int pm_hint __unused, + const struct pm_callback_handle *hdl) +{ + struct regulator *regulator = hdl->handle; + struct vrefbuf_regul *vr = regulator_to_vr(regulator); + vaddr_t csr_va = vr->base + VREFBUF_CSR; + TEE_Result res = TEE_ERROR_GENERIC; + /* Context to save/restore on PM suspend/resume */ + static uint32_t pm_val; + + assert(op == PM_OP_SUSPEND || op == PM_OP_RESUME); + + res = clk_enable(vr->clock); + if (res) + return res; + + if (op == PM_OP_SUSPEND) { + pm_val = io_read32(csr_va); + + if (pm_val & VREFBUF_CSR_ENVR && vrefbuf_wait_ready(vr)) { + clk_disable(vr->clock); + + return TEE_ERROR_GENERIC; + } + } else { + io_clrsetbits32(csr_va, VREFBUF_CSR_VRS, pm_val); + + if (pm_val & VREFBUF_CSR_ENVR) { + vr->disable_timeout = 0; + vrefbuf_set_state(&vr->regulator, true); + } + } + + clk_disable(vr->clock); + + return TEE_SUCCESS; +} +DECLARE_KEEP_PAGER(stm32_vrefbuf_pm); + +static TEE_Result stm32_vrefbuf_init(struct regulator *regulator, + const void *fdt __unused, + int node __unused) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + res = set_voltages_desc(regulator); + if (res) + return res; + + register_pm_driver_cb(stm32_vrefbuf_pm, regulator, "stm32-vrefbuf"); + + return TEE_SUCCESS; +} + +static const struct regulator_ops vrefbuf_ops = { + .set_state = vrefbuf_set_state, + .get_state = vrefbuf_get_state, + .set_voltage = vrefbuf_set_voltage, + .get_voltage = vrefbuf_get_voltage, + .supported_voltages = vrefbuf_list_voltages, + .supplied_init = stm32_vrefbuf_init, +}; + +static TEE_Result stm32_vrefbuf_regulator_probe(const void *fdt, int node, + const void *compat_data) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct vrefbuf_regul *vr = NULL; + struct regu_dt_desc desc = { }; + char *regu_name = NULL; + struct clk *clk = NULL; + paddr_t reg_base = 0; + size_t reg_size = 0; + + assert(!stm32_vrefbuf); + + res = clk_dt_get_by_index(fdt, node, 0, &clk); + if (res) + return res; + + vr = calloc(1, sizeof(*vr)); + if (!vr) + panic(); + + vr->compat = compat_data; + + regu_name = strdup(fdt_get_name(fdt, node, NULL)); + if (!regu_name) + panic(); + + reg_base = fdt_reg_base_address(fdt, node); + reg_size = fdt_reg_size(fdt, node); + if (reg_base == DT_INFO_INVALID_REG || + reg_size == DT_INFO_INVALID_REG_SIZE) + panic(); + + vr->base = (vaddr_t)phys_to_virt(reg_base, MEM_AREA_IO_SEC, reg_size); + if (!vr->base) + panic(); + + vr->clock = clk; + + desc = (struct regu_dt_desc){ + .name = regu_name, + .ops = &vrefbuf_ops, + .supply_name = "vdda", + .regulator = &vr->regulator, + }; + + res = regulator_dt_register(fdt, node, node, &desc); + if (res) + panic(); + + stm32_vrefbuf = vr; + + return TEE_SUCCESS; +} + +static const struct dt_device_match stm32_vrefbuf_match_table[] = { + { + .compatible = "st,stm32-vrefbuf", + .compat_data = &stm32mp15_vrefbuf_compat, + }, + { + .compatible = "st,stm32mp13-vrefbuf", + .compat_data = &stm32mp13_vrefbuf_compat + }, + { } +}; + +DEFINE_DT_DRIVER(stm32_vrefbuf_regulator_dt_driver) = { + .name = "stm32-vrefbuf-regulator", + .match_table = stm32_vrefbuf_match_table, + .probe = &stm32_vrefbuf_regulator_probe, +}; diff --git a/optee/optee_os/core/drivers/regulator/stm32mp13_regulator_iod.c b/optee/optee_os/core/drivers/regulator/stm32mp13_regulator_iod.c new file mode 100644 index 0000000..a678d51 --- /dev/null +++ b/optee/optee_os/core/drivers/regulator/stm32mp13_regulator_iod.c @@ -0,0 +1,297 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021-2023, STMicroelectronics + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TIMEOUT_US_10MS U(10000) + +#define IO_VOLTAGE_THRESHOLD_UV 2700000 + +/* + * struct iod_regul - IO domain regulator instance + * + * @enable_reg: PWR register offset for the IO domain + * @enable_mask: Domain enable register bit mask in PWR register + * @ready_mask: Domain ready bit mask in PWR register + * @valid_mask: Domain valid bit mask in PWR register + * @hslv_id: ID of the related HSLV domain + * @io_comp_id: ID of the related IO compensation domain + * @suspend_state: True if regulator is enabled before suspend, false otherwise + * @suspend_level_uv: Voltage level before suspend, in microvolts + */ +struct iod_regul { + uint32_t enable_reg; + uint32_t enable_mask; + uint32_t ready_mask; + uint32_t valid_mask; + enum stm32mp13_hslv_id hslv_id; + enum stm32mp13_vddsd_comp_id io_comp_id; + bool suspend_state; + int suspend_level_uv; +}; + +static struct iod_regul iod_regulator_priv[IOD_REGU_COUNT] = { + [IOD_SDMMC1] = { + .enable_reg = PWR_CR3_OFF, + .enable_mask = PWR_CR3_VDDSD1EN, + .ready_mask = PWR_CR3_VDDSD1RDY, + .valid_mask = PWR_CR3_VDDSD1VALID, + .hslv_id = SYSCFG_HSLV_IDX_SDMMC1, + .io_comp_id = SYSCFG_IO_COMP_IDX_SD1, + }, + [IOD_SDMMC2] = { + .enable_reg = PWR_CR3_OFF, + .enable_mask = PWR_CR3_VDDSD2EN, + .ready_mask = PWR_CR3_VDDSD2RDY, + .valid_mask = PWR_CR3_VDDSD2VALID, + .hslv_id = SYSCFG_HSLV_IDX_SDMMC2, + .io_comp_id = SYSCFG_IO_COMP_IDX_SD2, + }, +}; + +static struct regulator *iod_regulator[IOD_REGU_COUNT]; + +struct regulator *stm32mp1_get_iod_regulator(enum iod_regulator_id index) +{ + assert(index >= IOD_SDMMC1 && index < IOD_REGU_COUNT); + + return iod_regulator[index]; +} + +static TEE_Result iod_set_state(struct regulator *regu, bool enable) +{ + struct iod_regul *iod = regu->priv; + uintptr_t pwr_reg = stm32_pwr_base() + iod->enable_reg; + + FMSG("%s: set state %u", regulator_name(regu), enable); + + if (enable) { + uint32_t value = 0; + + io_setbits32(pwr_reg, iod->enable_mask); + + if (IO_READ32_POLL_TIMEOUT(pwr_reg, value, + value & iod->ready_mask, + 0, TIMEOUT_US_10MS)) + return TEE_ERROR_GENERIC; + + io_setbits32(pwr_reg, iod->valid_mask); + io_clrbits32(pwr_reg, iod->enable_mask); + + stm32mp_set_vddsd_comp_state(iod->io_comp_id, true); + } else { + stm32mp_set_vddsd_comp_state(iod->io_comp_id, false); + + io_clrbits32(pwr_reg, iod->enable_mask | iod->valid_mask); + } + + return TEE_SUCCESS; +} + +static TEE_Result iod_get_state(struct regulator *regu, bool *enabled) +{ + struct iod_regul *iod = regu->priv; + uintptr_t pwr_reg = stm32_pwr_base() + iod->enable_reg; + + *enabled = io_read32(pwr_reg) & (iod->enable_mask | iod->valid_mask); + + return TEE_SUCCESS; +} + +static TEE_Result iod_get_voltage(struct regulator *regu, int *level_uv) +{ + *level_uv = regulator_get_voltage(regu->supply); + + return TEE_SUCCESS; +} + +static TEE_Result iod_set_voltage(struct regulator *regu, int level_uv) +{ + struct iod_regul *iod = regu->priv; + TEE_Result res = TEE_ERROR_GENERIC; + bool iod_enabled = false; + + FMSG("%s: set voltage level to %duV", regulator_name(regu), level_uv); + + res = iod_get_state(regu, &iod_enabled); + if (res) + return res; + + /* Isolate IOs and disable IOs compensation when changing voltage */ + if (iod_enabled) { + res = iod_set_state(regu, false); + if (res) + return res; + } + + /* + * Set IO to low speed. + * Setting high voltage with IOs in high speed mode may damage the IOs. + */ + stm32mp_set_hslv_state(iod->hslv_id, false); + + /* Forward set voltage request to the power supply */ + res = regulator_set_voltage(regu->supply, level_uv); + if (res) { + EMSG("regulator %s set voltage failed: %#"PRIx32, + regulator_name(regu), res); + + /* Ensure IO domain consistency for current voltage level */ + level_uv = regulator_get_voltage(regu->supply); + } + + if (level_uv <= IO_VOLTAGE_THRESHOLD_UV) + stm32mp_set_hslv_state(iod->hslv_id, true); + + if (iod_enabled) { + TEE_Result res2 = TEE_ERROR_GENERIC; + + res2 = iod_set_state(regu, true); + if (res2) + return res2; + } + + return res; +} + +static TEE_Result iod_list_voltages(struct regulator *regu, + struct regulator_voltages_desc **desc, + const int **levels) +{ + /* Return supply voltage list */ + return regulator_supported_voltages(regu->supply, desc, levels); +} + +/* + * To protect the IOs, we disable High Speed Low Voltage mode before + * entering suspend state and restore the configuration when resuming. + */ +static TEE_Result iod_pm(enum pm_op op, unsigned int pm_hint __unused, + const struct pm_callback_handle *hdl) +{ + struct regulator *regu = hdl->handle; + struct iod_regul *iod = regu->priv; + TEE_Result res = TEE_ERROR_GENERIC; + + assert(op == PM_OP_SUSPEND || op == PM_OP_RESUME); + + if (op == PM_OP_SUSPEND) { + FMSG("%s: suspend", regulator_name(regu)); + + res = iod_get_state(regu, &iod->suspend_state); + if (res) + return res; + + res = iod_get_voltage(regu, &iod->suspend_level_uv); + if (res) + return res; + + stm32mp_set_hslv_state(iod->hslv_id, false); + } else { + FMSG("%s: resume", regulator_name(regu)); + + res = iod_set_voltage(regu, iod->suspend_level_uv); + if (res) + return res; + + res = iod_set_state(regu, iod->suspend_state); + if (res) + return res; + } + + return TEE_SUCCESS; +} + +static TEE_Result iod_supplied_init(struct regulator *regu, + const void *fdt __unused, int node __unused) +{ + struct iod_regul *iod = regu->priv; + int index = iod - iod_regulator_priv; + + assert(index >= 0 && index < IOD_REGU_COUNT); + + if (regulator_get_voltage(regu) < IO_VOLTAGE_THRESHOLD_UV) + stm32mp_set_hslv_state(iod->hslv_id, true); + + /* Save regulator reference */ + iod_regulator[index] = regu; + + register_pm_driver_cb(iod_pm, regu, "iod-regulator"); + + FMSG("IOD regulator %s intiialized", regulator_name(regu)); + + return TEE_SUCCESS; +} + +static const struct regulator_ops iod_ops = { + .set_state = iod_set_state, + .get_state = iod_get_state, + .set_voltage = iod_set_voltage, + .get_voltage = iod_get_voltage, + .supported_voltages = iod_list_voltages, + .supplied_init = iod_supplied_init, +}; + +#define DEFINE_REG(_id, _name, _supply_name) { \ + .name = (_name), \ + .ops = &iod_ops, \ + .priv = iod_regulator_priv + (_id), \ + .supply_name = (_supply_name), \ +} + +static struct regu_dt_desc iod_regul_desc[IOD_REGU_COUNT] = { + [IOD_SDMMC1] = DEFINE_REG(IOD_SDMMC1, "sdmmc1_io", "vddsd1"), + [IOD_SDMMC2] = DEFINE_REG(IOD_SDMMC2, "sdmmc2_io", "vddsd2"), +}; + +static TEE_Result iod_regulator_probe(const void *fdt, int node, + const void *compat_data __unused) +{ + const char *node_name = NULL; + size_t i = 0; + + node_name = fdt_get_name(fdt, node, NULL); + + FMSG("iod probe node '%s'", node_name); + + /* Look up matching regulator name defined in SoC DTSI file */ + for (i = 0; i < IOD_REGU_COUNT; i++) + if (!strcmp(iod_regul_desc[i].name, node_name)) + break; + + if (i == IOD_REGU_COUNT) { + EMSG("Unexpected IO domain node name '%s'", node_name); + return TEE_ERROR_GENERIC; + } + + return regulator_dt_register(fdt, node, node, iod_regul_desc + i); +} + +static const struct dt_device_match iod_regulator_match_table[] = { + { .compatible = "st,stm32mp13-iod" }, + { } +}; + +DEFINE_DT_DRIVER(stm32mp13_regulator_iod_dt_driver) = { + .name = "stm32mp13-iod-regulator", + .match_table = iod_regulator_match_table, + .probe = iod_regulator_probe, +}; diff --git a/optee/optee_os/core/drivers/regulator/sub.mk b/optee/optee_os/core/drivers/regulator/sub.mk new file mode 100644 index 0000000..82d839a --- /dev/null +++ b/optee/optee_os/core/drivers/regulator/sub.mk @@ -0,0 +1,6 @@ +srcs-y += regulator.c +srcs-$(CFG_DT) += regulator_dt.c +srcs-$(CFG_REGULATOR_FIXED) += regulator_fixed.c +srcs-$(CFG_REGULATOR_GPIO) += regulator_gpio.c +srcs-$(CFG_STM32_VREFBUF) += stm32_vrefbuf.c +srcs-$(CFG_STM32MP13_REGULATOR_IOD) += stm32mp13_regulator_iod.c diff --git a/optee/optee_os/core/drivers/remoteproc/stm32_remoteproc.c b/optee/optee_os/core/drivers/remoteproc/stm32_remoteproc.c new file mode 100644 index 0000000..e4cd6c8 --- /dev/null +++ b/optee/optee_os/core/drivers/remoteproc/stm32_remoteproc.c @@ -0,0 +1,388 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2023, STMicroelectronics + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TIMEOUT_US_1MS U(1000) + +/** + * struct stm32_rproc_mem - Memory regions used by the remote processor + * + * @addr: physical base address from the CPU space perspective + * @da: device address corresponding to the physical base address + * from remote processor space perspective + * @size: size of the region + */ +struct stm32_rproc_mem { + paddr_t addr; + paddr_t da; + size_t size; +}; + +/** + * struct stm32_rproc_instance - rproc instance context + * + * @cdata: pointer to the device compatible data + * @link: the node in the rproc_list + * @n_regions: number of memory regions + * @regions: memory regions used + * @mcu_rst: remote processor reset control + * @hold_boot: remote processor hold boot control + */ +struct stm32_rproc_instance { + const struct stm32_rproc_compat_data *cdata; + SLIST_ENTRY(stm32_rproc_instance) link; + size_t n_regions; + struct stm32_rproc_mem *regions; + struct rstctrl *mcu_rst; + struct rstctrl *hold_boot; +}; + +/** + * struct stm32_rproc_compat_data - rproc associated data for compatible list + * + * @rproc_id: identifies the remote processor + */ +struct stm32_rproc_compat_data { + uint32_t rproc_id; +}; + +static SLIST_HEAD(, stm32_rproc_instance) rproc_list = + SLIST_HEAD_INITIALIZER(rproc_list); + +void *stm32_rproc_get(uint32_t rproc_id) +{ + struct stm32_rproc_instance *rproc = NULL; + + SLIST_FOREACH(rproc, &rproc_list, link) + if (rproc->cdata->rproc_id == rproc_id) + break; + + return rproc; +} + +TEE_Result stm32_rproc_start(uint32_t rproc_id) +{ + struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id); + TEE_Result res = TEE_ERROR_GENERIC; + + if (!rproc || !rproc->hold_boot) + return TEE_ERROR_GENERIC; + + /* + * The firmware is started by de-asserting the hold boot and + * asserting it back to avoid auto restart on a crash. + * No need to release the MCU reset as it is automatically released by + * the hardware. + */ + res = rstctrl_deassert_to(rproc->hold_boot, TIMEOUT_US_1MS); + if (!res) + res = rstctrl_assert_to(rproc->hold_boot, TIMEOUT_US_1MS); + + return res; +} + +static TEE_Result rproc_stop(struct stm32_rproc_instance *rproc) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + if (!rproc->hold_boot || !rproc->mcu_rst) + return TEE_ERROR_GENERIC; + + res = rstctrl_assert_to(rproc->hold_boot, TIMEOUT_US_1MS); + if (!res) + res = rstctrl_assert_to(rproc->mcu_rst, TIMEOUT_US_1MS); + + return res; +} + +TEE_Result stm32_rproc_stop(uint32_t rproc_id) +{ + struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id); + + if (!rproc) + return TEE_ERROR_BAD_PARAMETERS; + + return rproc_stop(rproc); +} + +TEE_Result stm32_rproc_da_to_pa(uint32_t rproc_id, paddr_t da, size_t size, + paddr_t *pa) +{ + struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id); + struct stm32_rproc_mem *mems = NULL; + unsigned int i = 0; + + if (!rproc) + return TEE_ERROR_BAD_PARAMETERS; + + mems = rproc->regions; + + for (i = 0; i < rproc->n_regions; i++) { + if (core_is_buffer_inside(da, size, mems[i].da, mems[i].size)) { + /* + * A match between the requested DA memory area and the + * registered regions has been found. + * The PA is the reserved-memory PA address plus the + * delta between the requested DA and the + * reserved-memory DA address. + */ + *pa = mems[i].addr + da - mems[i].da; + return TEE_SUCCESS; + } + } + + return TEE_ERROR_ACCESS_DENIED; +} + +TEE_Result stm32_rproc_map(uint32_t rproc_id, paddr_t pa, size_t size, + void **va) +{ + struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id); + struct stm32_rproc_mem *mems = NULL; + unsigned int i = 0; + + if (!rproc) + return TEE_ERROR_BAD_PARAMETERS; + + mems = rproc->regions; + + for (i = 0; i < rproc->n_regions; i++) { + if (!core_is_buffer_inside(pa, size, mems[i].addr, + mems[i].size)) + continue; + *va = core_mmu_add_mapping(MEM_AREA_RAM_NSEC, pa, size); + if (!*va) { + EMSG("Can't map region %#"PRIxPA" size %zu", pa, size); + return TEE_ERROR_GENERIC; + } + + return TEE_SUCCESS; + } + + return TEE_ERROR_ACCESS_DENIED; +} + +TEE_Result stm32_rproc_unmap(uint32_t rproc_id, void *va, size_t size) +{ + struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id); + struct stm32_rproc_mem *mems = NULL; + paddr_t pa = virt_to_phys(va); + unsigned int i = 0; + + if (!rproc || !pa) + return TEE_ERROR_BAD_PARAMETERS; + + mems = rproc->regions; + + for (i = 0; i < rproc->n_regions; i++) { + if (!core_is_buffer_inside(pa, size, mems[i].addr, + mems[i].size)) + continue; + + /* Flush the cache before unmapping the memory */ + dcache_clean_range(va, size); + + if (core_mmu_remove_mapping(MEM_AREA_RAM_NSEC, va, size)) { + EMSG("Can't unmap region %#"PRIxPA" size %zu", + pa, size); + return TEE_ERROR_GENERIC; + } + + return TEE_SUCCESS; + } + + return TEE_ERROR_ACCESS_DENIED; +} + +static TEE_Result stm32_rproc_get_dma_range(struct stm32_rproc_mem *region, + const void *fdt, int node) +{ + const fdt32_t *list = NULL; + int ahb_node = 0; + int len = 0; + int nranges = 0; + int i = 0; + + /* + * The match between local and remote processor memory mapping is + * described in the dma-ranges defined by the bus parent node. + */ + ahb_node = fdt_parent_offset(fdt, node); + + list = fdt_getprop(fdt, ahb_node, "dma-ranges", &len); + if (!list) { + if (len != -FDT_ERR_NOTFOUND) + return TEE_ERROR_GENERIC; + /* Same memory mapping */ + DMSG("No dma-ranges found in DT"); + region->da = region->addr; + return TEE_SUCCESS; + } + + if ((len % (sizeof(uint32_t) * 3))) + return TEE_ERROR_GENERIC; + + nranges = len / sizeof(uint32_t); + + for (i = 0; i < nranges; i += 3) { + uint32_t da = fdt32_to_cpu(list[i]); + uint32_t pa = fdt32_to_cpu(list[i + 1]); + uint32_t size = fdt32_to_cpu(list[i + 2]); + + if (core_is_buffer_inside(region->addr, region->size, + pa, size)) { + region->da = da + (region->addr - pa); + return TEE_SUCCESS; + } + } + + return TEE_ERROR_BAD_PARAMETERS; +} + +/* Get device tree memory regions reserved for the Cortex-M and the IPC */ +static TEE_Result stm32_rproc_parse_mems(struct stm32_rproc_instance *rproc, + const void *fdt, int node) +{ + const fdt32_t *list = NULL; + TEE_Result res = TEE_ERROR_GENERIC; + struct stm32_rproc_mem *regions = NULL; + int len = 0; + int n_regions = 0; + int i = 0; + + list = fdt_getprop(fdt, node, "memory-region", &len); + if (!list) { + EMSG("No memory regions found in DT"); + return TEE_ERROR_GENERIC; + } + + n_regions = len / sizeof(uint32_t); + + regions = calloc(n_regions, sizeof(*regions)); + if (!regions) + return TEE_ERROR_OUT_OF_MEMORY; + + for (i = 0; i < n_regions; i++) { + int pnode = 0; + + pnode = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(list[i])); + if (pnode < 0) { + res = TEE_ERROR_GENERIC; + goto err; + } + + regions[i].addr = fdt_reg_base_address(fdt, pnode); + regions[i].size = fdt_reg_size(fdt, pnode); + + if (regions[i].addr <= 0 || regions[i].size <= 0) { + res = TEE_ERROR_GENERIC; + goto err; + } + + res = stm32_rproc_get_dma_range(®ions[i], fdt, node); + if (res) + goto err; + + if (!regions[i].addr || !regions[i].size) { + res = TEE_ERROR_BAD_PARAMETERS; + goto err; + } + + DMSG("register region %#"PRIxPA" size %#zx", + regions[i].addr, regions[i].size); + } + + rproc->n_regions = n_regions; + rproc->regions = regions; + + return TEE_SUCCESS; + +err: + free(regions); + + return res; +} + +static void stm32_rproc_cleanup(struct stm32_rproc_instance *rproc) +{ + free(rproc->regions); + free(rproc); +} + +static TEE_Result stm32_rproc_probe(const void *fdt, int node, + const void *comp_data) +{ + struct stm32_rproc_instance *rproc = NULL; + TEE_Result res = TEE_ERROR_GENERIC; + + rproc = calloc(1, sizeof(*rproc)); + if (!rproc) + return TEE_ERROR_OUT_OF_MEMORY; + + rproc->cdata = comp_data; + + res = stm32_rproc_parse_mems(rproc, fdt, node); + if (res) + goto err; + + res = rstctrl_dt_get_by_name(fdt, node, "mcu_rst", &rproc->mcu_rst); + if (res) + goto err; + + res = rstctrl_dt_get_by_name(fdt, node, "hold_boot", &rproc->hold_boot); + if (res) + goto err; + + /* Ensure that the MCU is HOLD */ + if (rproc->mcu_rst) { + res = rproc_stop(rproc); + if (res) + goto err; + } + + /* + * The memory management should be enhance with firewall + * mechanism to map the memory in secure area for the firmware + * loading and then to give exclusive access right to the + * coprocessor (except for the shared memory). + */ + IMSG("Warning: the remoteproc memories are not protected by firewall"); + + SLIST_INSERT_HEAD(&rproc_list, rproc, link); + + return TEE_SUCCESS; + +err: + stm32_rproc_cleanup(rproc); + return res; +} + +static const struct stm32_rproc_compat_data stm32_rproc_m4_compat = { + .rproc_id = STM32_M4_RPROC_ID, +}; + +static const struct dt_device_match stm32_rproc_match_table[] = { + { + .compatible = "st,stm32mp1-m4-tee", + .compat_data = &stm32_rproc_m4_compat, + }, + { } +}; + +DEFINE_DT_DRIVER(stm32_rproc_dt_driver) = { + .name = "stm32-rproc", + .match_table = stm32_rproc_match_table, + .probe = &stm32_rproc_probe, +}; diff --git a/optee/optee_os/core/drivers/remoteproc/sub.mk b/optee/optee_os/core/drivers/remoteproc/sub.mk new file mode 100644 index 0000000..4eb5ca3 --- /dev/null +++ b/optee/optee_os/core/drivers/remoteproc/sub.mk @@ -0,0 +1 @@ +srcs-$(CFG_STM32MP_REMOTEPROC) += stm32_remoteproc.c 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..50ff4ec --- /dev/null +++ b/optee/optee_os/core/drivers/rstctrl/stm32_rstctrl.c @@ -0,0 +1,235 @@ +// 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; + +#ifdef CFG_STM32MP15 + 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; + } +#endif + + 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; + +#ifdef CFG_STM32MP15 + 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; + } +#endif + + 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 TEE_Result stm32_rstctrl_get_dev(struct dt_pargs *arg, + void *priv_data __unused, + struct rstctrl **out_device) +{ + struct stm32_rstline *stm32_rstline = NULL; + uintptr_t control_id = 0; + + if (arg->args_count != 1) + return TEE_ERROR_BAD_PARAMETERS; + + control_id = arg->args[0]; + + stm32_rstline = find_or_allocate_rstline(control_id); + if (!stm32_rstline) + return TEE_ERROR_OUT_OF_MEMORY; + + *out_device = &stm32_rstline->rstctrl; + + return TEE_SUCCESS; +} + +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" }, + { .compatible = "st,stm32mp13-rcc" }, + { } +}; + +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/clock_generic.c b/optee/optee_os/core/drivers/scmi-msg/clock_generic.c new file mode 100644 index 0000000..1b2d1e6 --- /dev/null +++ b/optee/optee_os/core/drivers/scmi-msg/clock_generic.c @@ -0,0 +1,223 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021, Microchip + */ + +#include +#include +#include +#include +#include +#include + +#include "clock.h" + +/** + * struct scmi_clk - Binds an SCMI channel/clock to a core clk reference + * @clk: Core clock reference + * @channel_id: SCMI server channel handle exposing the clock + * @scmi_id: SCMI clock domain ID + * @enabled: SCMI clock state + * @link: Reference in SCMI server clock list + */ +struct scmi_clk { + struct clk *clk; + unsigned int channel_id; + unsigned int scmi_id; + bool enabled; + SLIST_ENTRY(scmi_clk) link; +}; + +static bool scmi_clk_init_done; +static SLIST_HEAD(, scmi_clk) scmi_clk_list = + SLIST_HEAD_INITIALIZER(scmi_clk_list); + +size_t plat_scmi_clock_count(unsigned int channel_id) +{ + unsigned int count = 0; + unsigned int max_id = 0; + struct scmi_clk *clk = NULL; + + SLIST_FOREACH(clk, &scmi_clk_list, link) { + if (clk->channel_id == channel_id) { + count++; + max_id = MAX(max_id, clk->scmi_id); + } + } + + if (!count) + return 0; + + /* IDs are starting from 0 so we need to return max_id + 1 for count */ + return max_id + 1; +} + +static struct scmi_clk *clk_scmi_get_by_id(unsigned int channel_id, + unsigned int scmi_id) +{ + struct scmi_clk *clk = NULL; + + SLIST_FOREACH(clk, &scmi_clk_list, link) + if (clk->channel_id == channel_id && clk->scmi_id == scmi_id) + return clk; + + return NULL; +} + +const char *plat_scmi_clock_get_name(unsigned int channel_id, + unsigned int scmi_id) +{ + struct scmi_clk *clk = NULL; + + clk = clk_scmi_get_by_id(channel_id, scmi_id); + if (!clk) + return "dummy"; + + return clk_get_name(clk->clk); +} + +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) +{ + struct scmi_clk *clk = NULL; + + clk = clk_scmi_get_by_id(channel_id, scmi_id); + if (!clk) + return SCMI_DENIED; + + if (clk_get_rates_array(clk->clk, start_index, rates, nb_elts)) + return SCMI_GENERIC_ERROR; + + return SCMI_SUCCESS; +} + +unsigned long plat_scmi_clock_get_rate(unsigned int channel_id, + unsigned int scmi_id) +{ + struct scmi_clk *clk = NULL; + + clk = clk_scmi_get_by_id(channel_id, scmi_id); + if (!clk) + return 0; + + return clk_get_rate(clk->clk); +} + +int32_t plat_scmi_clock_set_rate(unsigned int channel_id, + unsigned int scmi_id, + unsigned long rate) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct scmi_clk *clk = NULL; + + clk = clk_scmi_get_by_id(channel_id, scmi_id); + if (!clk) + return SCMI_DENIED; + + res = clk_set_rate(clk->clk, rate); + if (res) + return SCMI_GENERIC_ERROR; + + return SCMI_SUCCESS; +} + +int32_t plat_scmi_clock_get_state(unsigned int channel_id, + unsigned int scmi_id) +{ + struct scmi_clk *clk = NULL; + + clk = clk_scmi_get_by_id(channel_id, scmi_id); + if (!clk) + return false; + + return clk->enabled; +} + +int32_t plat_scmi_clock_set_state(unsigned int channel_id, + unsigned int scmi_id, + bool enable_not_disable) +{ + struct scmi_clk *clk = NULL; + + clk = clk_scmi_get_by_id(channel_id, scmi_id); + if (!clk) { + if (enable_not_disable) + return SCMI_DENIED; + else + return SCMI_SUCCESS; + } + + if (enable_not_disable) { + if (!clk->enabled) { + if (clk_enable(clk->clk)) + return SCMI_GENERIC_ERROR; + clk->enabled = true; + } + } else { + if (clk->enabled) { + clk_disable(clk->clk); + clk->enabled = false; + } + } + + return SCMI_SUCCESS; +} + +static TEE_Result clk_check_scmi_id(struct clk *new_clk, + unsigned int channel_id, + unsigned int scmi_id) +{ + struct scmi_clk *clk = NULL; + + SLIST_FOREACH(clk, &scmi_clk_list, link) { + if (clk->channel_id == channel_id && clk->scmi_id == scmi_id) { + EMSG("SCMI channel %u, clock %u already registered", + channel_id, scmi_id); + return TEE_ERROR_BAD_PARAMETERS; + } + } + + if (strlen(clk_get_name(new_clk)) >= SCMI_CLOCK_NAME_LENGTH_MAX) + return TEE_ERROR_BAD_PARAMETERS; + + return TEE_SUCCESS; +} + +TEE_Result scmi_clk_add(struct clk *clk, unsigned int channel_id, + unsigned int scmi_id) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct scmi_clk *scmi_clk = NULL; + + if (scmi_clk_init_done) + return TEE_ERROR_BAD_STATE; + + res = clk_check_scmi_id(clk, channel_id, scmi_id); + if (res) + return res; + + scmi_clk = calloc(1, sizeof(*scmi_clk)); + if (!scmi_clk) + return TEE_ERROR_OUT_OF_MEMORY; + + scmi_clk->clk = clk; + scmi_clk->channel_id = channel_id; + scmi_clk->scmi_id = scmi_id; + scmi_clk->enabled = false; + + SLIST_INSERT_HEAD(&scmi_clk_list, scmi_clk, link); + + return TEE_SUCCESS; +} + +static TEE_Result scmi_clk_init_fini(void) +{ + scmi_clk_init_done = true; + + return TEE_SUCCESS; +} + +release_init_resource(scmi_clk_init_fini); 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..8067f66 --- /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 %zu", 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..9a97d5c --- /dev/null +++ b/optee/optee_os/core/drivers/scmi-msg/sub.mk @@ -0,0 +1,8 @@ +srcs-y += base.c +srcs-$(CFG_SCMI_MSG_CLOCK) += clock.c +srcs-$(CFG_SCMI_MSG_USE_CLK) += clock_generic.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/semihosting_console.c b/optee/optee_os/core/drivers/semihosting_console.c new file mode 100644 index 0000000..18072c1 --- /dev/null +++ b/optee/optee_os/core/drivers/semihosting_console.c @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2024 Andes Technology Corporation + */ + +#include +#include +#include +#include +#include +#include + +/* + * struct semihosting_console_data - Structure for semihosting console driver + * @chip - General structure for each serial chip + * @fd - Handle of the file at @file_path when semihosting_console_init() is + * called, or -1 if using the semihosting console + */ +struct semihosting_console_data { + struct serial_chip chip; + int fd; +}; + +static struct semihosting_console_data sh_console_data __nex_bss; + +static void semihosting_console_putc(struct serial_chip *chip __unused, int ch) +{ + semihosting_sys_writec(ch); +} + +static int semihosting_console_getchar(struct serial_chip *chip __unused) +{ + return semihosting_sys_readc(); +} + +static const struct serial_ops semihosting_console_ops = { + .putc = semihosting_console_putc, + .getchar = semihosting_console_getchar, +}; +DECLARE_KEEP_PAGER(semihosting_console_ops); + +static void semihosting_console_fd_putc(struct serial_chip *chip __unused, + int ch) +{ + if (sh_console_data.fd >= 0) + semihosting_write(sh_console_data.fd, &ch, 1); +} + +static const struct serial_ops semihosting_console_fd_ops = { + .putc = semihosting_console_fd_putc, +}; +DECLARE_KEEP_PAGER(semihosting_console_fd_ops); + +void semihosting_console_init(const char *file_path) +{ + if (file_path) { + /* Output log to given file on the semihosting host system. */ + sh_console_data.chip.ops = &semihosting_console_fd_ops; + sh_console_data.fd = + semihosting_open(file_path, O_RDWR | O_CREAT | O_TRUNC); + } else { + /* Output log to semihosting host debug console. */ + sh_console_data.chip.ops = &semihosting_console_ops; + sh_console_data.fd = -1; + } + + register_serial_console(&sh_console_data.chip); +} 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..4cb5112 --- /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", + 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..cd4624f --- /dev/null +++ b/optee/optee_os/core/drivers/sp805_wdt.c @@ -0,0 +1,140 @@ +// 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) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct itr_handler *wdt_itr = NULL; + + assert(!pd->chip.wdt_itr); + + res = interrupt_alloc_add_handler(interrupt_get_main_chip(), itr_num, + wdt_itr_cb, itr_flags, + &pd->chip, &wdt_itr); + if (res) + return res; + + pd->itr_handler = itr_handler; + pd->chip.wdt_itr = wdt_itr; + + interrupt_enable(wdt_itr->chip, 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..4a87969 --- /dev/null +++ b/optee/optee_os/core/drivers/stm32_bsec.c @@ -0,0 +1,956 @@ +// 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) + +/* BSEC_DEBUG bitfields */ +#ifdef CFG_STM32MP13 +#define BSEC_DEN_ALL_MSK (GENMASK_32(11, 10) | GENMASK_32(8, 1)) +#endif +#ifdef CFG_STM32MP15 +#define BSEC_DEN_ALL_MSK GENMASK_32(11, 1) +#endif + +/* + * 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; + size_t __maybe_unused sz = 0; + uint8_t __maybe_unused offset = 0; + + if (IS_ENABLED(CFG_STM32MP13)) + return bsec_status() & BSEC_MODE_CLOSED; + + res = stm32_bsec_find_otp_in_nvmem_layout("cfg0_otp", &otp_cfg, + &offset, &sz); + if (res || sz != 8 || offset) + panic("CFG0 OTP not found or invalid"); + + 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 = 0; + + io_mask32(bsec_base() + BSEC_OTP_CONF_OFF, BSEC_CONF_POWER_UP_MASK, + BSEC_CONF_POWER_UP_MASK); + + timeout_ref = timeout_init_us(BSEC_TIMEOUT_US); + 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 = 0; + + io_mask32(bsec_base() + BSEC_OTP_CONF_OFF, 0, BSEC_CONF_POWER_UP_MASK); + + timeout_ref = timeout_init_us(BSEC_TIMEOUT_US); + 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; +} + +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; +} +#endif /*CFG_STM32_BSEC_WRITE*/ + +TEE_Result stm32_bsec_write_debug_conf(uint32_t value) +{ + TEE_Result result = TEE_ERROR_GENERIC; + uint32_t exceptions = 0; + + assert(!(value & ~BSEC_DEN_ALL_MSK)); + + if (state_is_invalid_mode()) + return TEE_ERROR_SECURITY; + + exceptions = bsec_lock(); + + io_clrsetbits32(bsec_base() + BSEC_DEN_OFF, BSEC_DEN_ALL_MSK, value); + + if (stm32_bsec_read_debug_conf() == value) + result = TEE_SUCCESS; + + bsec_unlock(exceptions); + + return result; +} + +uint32_t stm32_bsec_read_debug_conf(void) +{ + return io_read32(bsec_base() + BSEC_DEN_OFF) & BSEC_DEN_ALL_MSK; +} + +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 - NVMEM cell description + * @name: Name of the nvmem node in the DT + * @otp_id: BSEC base index for the OTP words + * @bit_offset: Bit offset in the OTP word + * @bit_len: Bit size of the OTP word + * @phandle: Associated phandle in embedded DTB + */ +struct nvmem_layout { + char *name; + uint32_t otp_id; + uint8_t bit_offset; + size_t bit_len; + uint32_t phandle; +}; + +static struct nvmem_layout *nvmem_layout; +static size_t nvmem_layout_count; + +static TEE_Result stm32_bsec_otp_setting(size_t i, + uint32_t *otp_id, + uint8_t *otp_bit_offset, + size_t *otp_bit_len) +{ + if (otp_id) + *otp_id = nvmem_layout[i].otp_id; + + if (otp_bit_offset) + *otp_bit_offset = nvmem_layout[i].bit_offset; + + if (otp_bit_len) + *otp_bit_len = nvmem_layout[i].bit_len; + + DMSG("nvmem[%zu] = %s at BSEC word %" PRIu32 " bits [%" PRIu8 " %zu]", + i, nvmem_layout[i].name, nvmem_layout[i].otp_id, + nvmem_layout[i].bit_offset, nvmem_layout[i].bit_len); + + return TEE_SUCCESS; +} + +TEE_Result stm32_bsec_find_otp_in_nvmem_layout(const char *name, + uint32_t *otp_id, + uint8_t *otp_bit_offset, + 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; + + return stm32_bsec_otp_setting(i, otp_id, otp_bit_offset, + otp_bit_len); + } + + DMSG("nvmem %s failed", name); + + return TEE_ERROR_ITEM_NOT_FOUND; +} + +TEE_Result stm32_bsec_find_otp_by_phandle(const uint32_t phandle, + uint32_t *otp_id, + uint8_t *otp_bit_offset, + size_t *otp_bit_len) +{ + size_t i = 0; + + if (!phandle) + return TEE_ERROR_GENERIC; + + for (i = 0; i < nvmem_layout_count; i++) { + if (nvmem_layout[i].phandle != phandle) + continue; + + return stm32_bsec_otp_setting(i, otp_id, otp_bit_offset, + otp_bit_len); + } + + DMSG("nvmem %u not found", phandle); + + return TEE_ERROR_ITEM_NOT_FOUND; +} + +TEE_Result stm32_bsec_get_state(enum stm32_bsec_sec_state *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]; + uint32_t bits[2] = { }; + + string = fdt_get_name(fdt, node, &len); + if (!string || !len) + continue; + + layout_cell->phandle = fdt_get_phandle(fdt, node); + assert(layout_cell->phandle != (uint32_t)-1); + + 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; + } + + layout_cell->otp_id = reg_offset / sizeof(uint32_t); + layout_cell->bit_offset = (reg_offset % sizeof(uint32_t)) * + CHAR_BIT; + layout_cell->bit_len = reg_length * CHAR_BIT; + + if (!fdt_read_uint32_array(fdt, node, "bits", bits, 2)) { + layout_cell->bit_offset += bits[0]; + layout_cell->bit_len = bits[1]; + } + + 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 at BSEC word %" PRIu32 + " bits [%" PRIu8 " %zu]", + cell_cnt, layout_cell->name, layout_cell->otp_id, + layout_cell->bit_offset, 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..19c7d70 --- /dev/null +++ b/optee/optee_os/core/drivers/stm32_etzpc.c @@ -0,0 +1,348 @@ +// 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 +#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); +} + +static TEE_Result stm32_etzpc_probe(const void *fdt, int node, + const void *compat_data __unused) +{ + TEE_Result res = TEE_ERROR_GENERIC; + paddr_t pbase = 0; + int subnode = 0; + + pbase = fdt_reg_base_address(fdt, node); + if (pbase == DT_INFO_INVALID_REG) + panic(); + + init_device_from_hw_config(&etzpc_dev, pbase); + + fdt_for_each_subnode(subnode, fdt, node) { + res = dt_driver_maybe_add_probe_node(fdt, subnode); + if (res) { + EMSG("Failed to add node %s to probe list: %#"PRIx32, + fdt_get_name(fdt, subnode, NULL), res); + panic(); + } + } + + return TEE_SUCCESS; +} + +static const struct dt_device_match etzpc_match_table[] = { + { .compatible = "st,stm32-etzpc" }, + { } +}; + +DEFINE_DT_DRIVER(etzpc_dt_driver) = { + .name = "stm32-etzpc", + .match_table = etzpc_match_table, + .probe = stm32_etzpc_probe, +}; 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..40f1ccb --- /dev/null +++ b/optee/optee_os/core/drivers/stm32_gpio.c @@ -0,0 +1,984 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2017-2023, STMicroelectronics + * + * STM32 GPIO driver is used as pin controller for stm32mp SoCs. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef CFG_DRIVERS_GPIO +#error stm32_gpio driver expects CFG_DRIVERS_GPIO +#endif + +#define GPIO_PIN_MAX 15 + +#define GPIO_MODER_OFFSET U(0x00) +#define GPIO_OTYPER_OFFSET U(0x04) +#define GPIO_OSPEEDR_OFFSET U(0x08) +#define GPIO_PUPDR_OFFSET U(0x0c) +#define GPIO_IDR_OFFSET U(0x10) +#define GPIO_ODR_OFFSET U(0x14) +#define GPIO_BSRR_OFFSET U(0x18) +#define GPIO_AFRL_OFFSET U(0x20) +#define GPIO_AFRH_OFFSET U(0x24) +#define GPIO_SECR_OFFSET U(0x30) + +#define GPIO_ALT_LOWER_LIMIT U(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 U(12) +#define DT_GPIO_BANK_MASK GENMASK_32(16, 12) +#define DT_GPIO_PIN_SHIFT U(8) +#define DT_GPIO_PIN_MASK GENMASK_32(11, 8) +#define DT_GPIO_MODE_MASK GENMASK_32(7, 0) + +#define DT_GPIO_BANK_NAME0 "GPIOA" + +#define GPIO_MODE_INPUT U(0x0) +#define GPIO_MODE_OUTPUT U(0x1) +#define GPIO_MODE_ALTERNATE U(0x2) +#define GPIO_MODE_ANALOG U(0x3) + +#define GPIO_OTYPE_PUSH_PULL U(0x0) +#define GPIO_OTYPE_OPEN_DRAIN U(0x1) + +#define GPIO_OSPEED_LOW U(0x0) +#define GPIO_OSPEED_MEDIUM U(0x1) +#define GPIO_OSPEED_HIGH U(0x2) +#define GPIO_OSPEED_VERY_HIGH U(0x3) + +#define GPIO_PUPD_NO_PULL U(0x0) +#define GPIO_PUPD_PULL_UP U(0x1) +#define GPIO_PUPD_PULL_DOWN U(0x2) + +#define GPIO_OD_LEVEL_LOW U(0x0) +#define GPIO_OD_LEVEL_HIGH U(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; +}; + +/* + * Description of a pin and its muxing + * + * @bank: GPIO bank identifier as assigned by the platform + * @pin: Pin number in the GPIO bank + * @cfg: Pin configuration + */ +struct stm32_pinctrl { + uint8_t bank; + uint8_t pin; + struct gpio_cfg cfg; +}; + +/* + * struct stm32_pinctrl_array - Array of pins in a pin control state + * @count: Number of cells in @pinctrl + * @pinctrl: Pin control configuration + */ +struct stm32_pinctrl_array { + size_t count; + struct stm32_pinctrl pinctrl[]; +}; + +/** + * struct stm32_gpio_bank - GPIO bank instance + * + * @base: base address of the GPIO controller registers. + * @clock: clock identifier. + * @gpio_chip: GPIO chip reference for that GPIO bank + * @ngpios: number of GPIOs. + * @bank_id: Id of the bank. + * @lock: lock protecting the GPIO bank access. + * @sec_support: True if bank supports pin security protection, otherwise false + * @link: Link in bank list + */ +struct stm32_gpio_bank { + vaddr_t base; + struct clk *clock; + struct gpio_chip gpio_chip; + unsigned int ngpios; + unsigned int bank_id; + unsigned int lock; + bool sec_support; + STAILQ_ENTRY(stm32_gpio_bank) link; +}; + +/** + * Compatibility information of supported banks + * + * @gpioz: True if bank is a GPIOZ bank + * @secure_control: Identify GPIO security bank capability. + */ +struct bank_compat { + bool gpioz; + bool secure_control; +}; + +static unsigned int gpio_lock; + +static STAILQ_HEAD(, stm32_gpio_bank) bank_list = + STAILQ_HEAD_INITIALIZER(bank_list); + +static bool is_stm32_gpio_chip(struct gpio_chip *chip); + +static struct stm32_gpio_bank *gpio_chip_to_bank(struct gpio_chip *chip) +{ + return container_of(chip, struct stm32_gpio_bank, gpio_chip); +} + +static enum gpio_level stm32_gpio_get_level(struct gpio_chip *chip, + unsigned int gpio_pin) +{ + struct stm32_gpio_bank *bank = gpio_chip_to_bank(chip); + enum gpio_level level = GPIO_LEVEL_HIGH; + unsigned int reg_offset = 0; + unsigned int mode = 0; + + assert(gpio_pin < bank->ngpios); + + if (clk_enable(bank->clock)) + panic(); + + mode = (io_read32(bank->base + GPIO_MODER_OFFSET) >> (gpio_pin << 1)) & + GPIO_MODE_MASK; + + switch (mode) { + case GPIO_MODE_INPUT: + reg_offset = GPIO_IDR_OFFSET; + break; + case GPIO_MODE_OUTPUT: + reg_offset = GPIO_ODR_OFFSET; + break; + default: + panic(); + } + + if (io_read32(bank->base + reg_offset) & BIT(gpio_pin)) + level = GPIO_LEVEL_HIGH; + else + level = GPIO_LEVEL_LOW; + + clk_disable(bank->clock); + + return level; +} + +static void stm32_gpio_set_level(struct gpio_chip *chip, unsigned int gpio_pin, + enum gpio_level level) +{ + struct stm32_gpio_bank *bank = gpio_chip_to_bank(chip); + + assert(gpio_pin < bank->ngpios); + + if (clk_enable(bank->clock)) + panic(); + + assert(((io_read32(bank->base + GPIO_MODER_OFFSET) >> + (gpio_pin << 1)) & GPIO_MODE_MASK) == GPIO_MODE_OUTPUT); + + if (level == GPIO_LEVEL_HIGH) + io_write32(bank->base + GPIO_BSRR_OFFSET, BIT(gpio_pin)); + else + io_write32(bank->base + GPIO_BSRR_OFFSET, BIT(gpio_pin + 16)); + + clk_disable(bank->clock); +} + +static enum gpio_dir stm32_gpio_get_direction(struct gpio_chip *chip, + unsigned int gpio_pin) +{ + struct stm32_gpio_bank *bank = gpio_chip_to_bank(chip); + uint32_t mode = 0; + + assert(gpio_pin < bank->ngpios); + + if (clk_enable(bank->clock)) + panic(); + + mode = (io_read32(bank->base + GPIO_MODER_OFFSET) >> (gpio_pin << 1)) & + GPIO_MODE_MASK; + + clk_disable(bank->clock); + + switch (mode) { + case GPIO_MODE_INPUT: + return GPIO_DIR_IN; + case GPIO_MODE_OUTPUT: + return GPIO_DIR_OUT; + default: + panic(); + } +} + +static void stm32_gpio_set_direction(struct gpio_chip *chip, + unsigned int gpio_pin, + enum gpio_dir direction) +{ + struct stm32_gpio_bank *bank = gpio_chip_to_bank(chip); + uint32_t exceptions = 0; + uint32_t mode = 0; + + assert(gpio_pin < bank->ngpios); + + if (direction == GPIO_DIR_IN) + mode = GPIO_MODE_INPUT; + else + mode = GPIO_MODE_OUTPUT; + + if (clk_enable(bank->clock)) + panic(); + exceptions = cpu_spin_lock_xsave(&gpio_lock); + io_clrsetbits32(bank->base + GPIO_MODER_OFFSET, + SHIFT_U32(GPIO_MODE_MASK, gpio_pin << 1), + SHIFT_U32(mode, gpio_pin << 1)); + cpu_spin_unlock_xrestore(&gpio_lock, exceptions); + clk_disable(bank->clock); +} + +static void stm32_gpio_put_gpio(struct gpio_chip *chip __maybe_unused, + struct gpio *gpio) +{ + assert(is_stm32_gpio_chip(chip)); + free(gpio); +} + +static const struct gpio_ops stm32_gpio_ops = { + .get_direction = stm32_gpio_get_direction, + .set_direction = stm32_gpio_set_direction, + .get_value = stm32_gpio_get_level, + .set_value = stm32_gpio_set_level, + .put = stm32_gpio_put_gpio, +}; + +static bool __maybe_unused is_stm32_gpio_chip(struct gpio_chip *chip) +{ + return chip && chip->ops == &stm32_gpio_ops; +} + +static struct stm32_gpio_bank *stm32_gpio_get_bank(unsigned int bank_id) +{ + struct stm32_gpio_bank *bank = NULL; + + STAILQ_FOREACH(bank, &bank_list, link) + if (bank_id == bank->bank_id) + return bank; + + panic(); +} + +/* Save to output @cfg the current GPIO (@bank_id/@pin) configuration */ +static void __maybe_unused get_gpio_cfg(uint32_t bank_id, uint32_t pin, + struct gpio_cfg *cfg) +{ + struct stm32_gpio_bank *bank = stm32_gpio_get_bank(bank_id); + + if (clk_enable(bank->clock)) + panic(); + + /* + * 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(bank->base + GPIO_MODER_OFFSET) >> (pin << 1)) & + GPIO_MODE_MASK; + + cfg->otype = (io_read32(bank->base + GPIO_OTYPER_OFFSET) >> pin) & 1; + + cfg->ospeed = (io_read32(bank->base + GPIO_OSPEEDR_OFFSET) >> + (pin << 1)) & GPIO_OSPEED_MASK; + + cfg->pupd = (io_read32(bank->base + GPIO_PUPDR_OFFSET) >> (pin << 1)) & + GPIO_PUPD_PULL_MASK; + + cfg->od = (io_read32(bank->base + GPIO_ODR_OFFSET) >> (pin << 1)) & 1; + + if (pin < GPIO_ALT_LOWER_LIMIT) + cfg->af = (io_read32(bank->base + GPIO_AFRL_OFFSET) >> + (pin << 2)) & GPIO_ALTERNATE_MASK; + else + cfg->af = (io_read32(bank->base + GPIO_AFRH_OFFSET) >> + ((pin - GPIO_ALT_LOWER_LIMIT) << 2)) & + GPIO_ALTERNATE_MASK; + + clk_disable(bank->clock); +} + +/* Apply GPIO (@bank/@pin) configuration described by @cfg */ +static void set_gpio_cfg(uint32_t bank_id, uint32_t pin, struct gpio_cfg *cfg) +{ + struct stm32_gpio_bank *bank = stm32_gpio_get_bank(bank_id); + uint32_t exceptions = 0; + + if (clk_enable(bank->clock)) + panic(); + exceptions = cpu_spin_lock_xsave(&gpio_lock); + + /* Load GPIO MODE value, 2bit value shifted by twice the pin number */ + io_clrsetbits32(bank->base + GPIO_MODER_OFFSET, + SHIFT_U32(GPIO_MODE_MASK, pin << 1), + SHIFT_U32(cfg->mode, pin << 1)); + + /* Load GPIO Output TYPE value, 1bit shifted by pin number value */ + io_clrsetbits32(bank->base + GPIO_OTYPER_OFFSET, BIT(pin), + SHIFT_U32(cfg->otype, pin)); + + /* Load GPIO Output Speed confguration, 2bit value */ + io_clrsetbits32(bank->base + GPIO_OSPEEDR_OFFSET, + SHIFT_U32(GPIO_OSPEED_MASK, pin << 1), + SHIFT_U32(cfg->ospeed, pin << 1)); + + /* Load GPIO pull configuration, 2bit value */ + io_clrsetbits32(bank->base + GPIO_PUPDR_OFFSET, BIT(pin), + SHIFT_U32(cfg->pupd, pin << 1)); + + /* Load pin mux Alternate Function configuration, 4bit value */ + if (pin < GPIO_ALT_LOWER_LIMIT) { + io_clrsetbits32(bank->base + GPIO_AFRL_OFFSET, + SHIFT_U32(GPIO_ALTERNATE_MASK, pin << 2), + SHIFT_U32(cfg->af, pin << 2)); + } else { + size_t shift = (pin - GPIO_ALT_LOWER_LIMIT) << 2; + + io_clrsetbits32(bank->base + GPIO_AFRH_OFFSET, + SHIFT_U32(GPIO_ALTERNATE_MASK, shift), + SHIFT_U32(cfg->af, shift)); + } + + /* Load GPIO Output direction confuguration, 1bit */ + io_clrsetbits32(bank->base + GPIO_ODR_OFFSET, BIT(pin), cfg->od << pin); + + cpu_spin_unlock_xrestore(&gpio_lock, exceptions); + clk_disable(bank->clock); +} + +/* Count pins described in the DT node and get related data if possible */ +static int get_pinctrl_from_fdt(const void *fdt, int node, + struct stm32_pinctrl *pinctrl, size_t count) +{ + const fdt32_t *cuint = NULL; + const fdt32_t *slewrate = NULL; + int len = 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; + + 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; + uint32_t odata = 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; + + if (fdt_getprop(fdt, node, "output-high", NULL) && + mode == GPIO_MODE_INPUT) { + mode = GPIO_MODE_OUTPUT; + odata = 1; + } + + if (fdt_getprop(fdt, node, "output-low", NULL) && + mode == GPIO_MODE_INPUT) { + mode = GPIO_MODE_OUTPUT; + odata = 0; + } + + if (found < count) { + struct stm32_pinctrl *ref = &pinctrl[found]; + + ref->bank = (uint8_t)bank; + ref->pin = (uint8_t)pin; + ref->cfg.mode = mode; + if (opendrain) + ref->cfg.otype = GPIO_OTYPE_OPEN_DRAIN; + else + ref->cfg.otype = GPIO_OTYPE_PUSH_PULL; + ref->cfg.ospeed = speed; + ref->cfg.pupd = pull; + ref->cfg.od = odata; + ref->cfg.af = alternate; + } + + found++; + } + + return (int)found; +} + +static TEE_Result stm32_gpio_get_dt(struct dt_pargs *pargs, void *data, + struct gpio **out_gpio) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct stm32_gpio_bank *bank = data; + struct gpio *gpio = NULL; + unsigned int shift_1b = 0; + unsigned int shift_2b = 0; + uint32_t exceptions = 0; + uint32_t otype = 0; + uint32_t pupd = 0; + uint32_t mode = 0; + + res = gpio_dt_alloc_pin(pargs, &gpio); + if (res) + return res; + + if (gpio->pin >= bank->ngpios) { + DMSG("Invalid GPIO reference"); + free(gpio); + return TEE_ERROR_GENERIC; + } + + shift_1b = gpio->pin; + shift_2b = SHIFT_U32(gpio->pin, 1); + + if (gpio->dt_flags & GPIO_PULL_UP) + pupd = GPIO_PUPD_PULL_UP; + else if (gpio->dt_flags & GPIO_PULL_DOWN) + pupd = GPIO_PUPD_PULL_DOWN; + else + pupd = GPIO_PUPD_NO_PULL; + + if (gpio->dt_flags & GPIO_LINE_OPEN_DRAIN) + otype = GPIO_OTYPE_OPEN_DRAIN; + else + otype = GPIO_OTYPE_PUSH_PULL; + + if (clk_enable(bank->clock)) + panic(); + exceptions = cpu_spin_lock_xsave(&gpio_lock); + + io_clrsetbits32(bank->base + GPIO_MODER_OFFSET, + SHIFT_U32(GPIO_MODE_MASK, shift_2b), + SHIFT_U32(mode, shift_2b)); + + io_clrsetbits32(bank->base + GPIO_OTYPER_OFFSET, + SHIFT_U32(GPIO_OTYPE_OPEN_DRAIN, shift_1b), + SHIFT_U32(otype, shift_1b)); + + io_clrsetbits32(bank->base + GPIO_PUPDR_OFFSET, + SHIFT_U32(GPIO_PUPD_PULL_MASK, shift_2b), + SHIFT_U32(pupd, shift_2b)); + + cpu_spin_unlock_xrestore(&gpio_lock, exceptions); + clk_disable(bank->clock); + + gpio->chip = &bank->gpio_chip; + + *out_gpio = gpio; + + return TEE_SUCCESS; +} + +/* Get bank ID from bank node property st,bank-name or panic on failure */ +static unsigned int dt_get_bank_id(const void *fdt, int node) +{ + const int dt_name_len = strlen(DT_GPIO_BANK_NAME0); + const fdt32_t *cuint = NULL; + int len = 0; + + /* Parse "st,bank-name" to get its id (eg: GPIOA -> 0) */ + cuint = fdt_getprop(fdt, node, "st,bank-name", &len); + if (!cuint || (len != dt_name_len + 1)) + panic("Missing/wrong st,bank-name property"); + + if (strncmp((const char *)cuint, DT_GPIO_BANK_NAME0, dt_name_len - 1) || + strcmp((const char *)cuint, DT_GPIO_BANK_NAME0) < 0) + panic("Wrong st,bank-name property"); + + return (unsigned int)strcmp((const char *)cuint, DT_GPIO_BANK_NAME0); +} + +/* + * Return whether or not the GPIO bank related to a DT node is already + * registered in the GPIO bank link. + */ +static bool bank_is_registered(const void *fdt, int node) +{ + unsigned int bank_id = dt_get_bank_id(fdt, node); + struct stm32_gpio_bank *bank = NULL; + + STAILQ_FOREACH(bank, &bank_list, link) + if (bank->bank_id == bank_id) + return true; + + return false; +} + +/* Get GPIO bank information from the DT */ +static TEE_Result dt_stm32_gpio_bank(const void *fdt, int node, + const void *compat_data, + int range_offset, + struct stm32_gpio_bank **out_bank) +{ + const struct bank_compat *compat = compat_data; + TEE_Result res = TEE_ERROR_GENERIC; + struct stm32_gpio_bank *bank = NULL; + const fdt32_t *cuint = NULL; + struct io_pa_va pa_va = { }; + struct clk *clk = NULL; + size_t blen = 0; + paddr_t pa = 0; + int len = 0; + int i = 0; + + assert(out_bank); + + /* Probe deferrable devices first */ + res = clk_dt_get_by_index(fdt, node, 0, &clk); + if (res) + return res; + + bank = calloc(1, sizeof(*bank)); + if (!bank) + return TEE_ERROR_OUT_OF_MEMORY; + + /* + * Do not rely *only* on the "reg" property to get the address, + * but consider also the "ranges" translation property + */ + pa = fdt_reg_base_address(fdt, node); + if (pa == DT_INFO_INVALID_REG) + panic("missing reg property"); + + pa_va.pa = pa + range_offset; + + blen = fdt_reg_size(fdt, node); + if (blen == DT_INFO_INVALID_REG_SIZE) + panic("missing reg size property"); + + DMSG("Bank name %s", fdt_get_name(fdt, node, NULL)); + bank->bank_id = dt_get_bank_id(fdt, node); + bank->clock = clk; + bank->gpio_chip.ops = &stm32_gpio_ops; + bank->sec_support = compat->secure_control; + if (bank->sec_support) + bank->base = io_pa_or_va_secure(&pa_va, blen); + else + bank->base = io_pa_or_va_nsec(&pa_va, blen); + assert(bank->base); + + /* Parse gpio-ranges with its 4 parameters */ + cuint = fdt_getprop(fdt, node, "gpio-ranges", &len); + len /= sizeof(*cuint); + if (len % 4) + panic("wrong gpio-ranges syntax"); + + /* Get the last defined gpio line (offset + nb of pins) */ + for (i = 0; i < len / 4; i++) { + bank->ngpios = MAX(bank->ngpios, + (unsigned int)(fdt32_to_cpu(*(cuint + 1)) + + fdt32_to_cpu(*(cuint + 3)))); + cuint += 4; + } + + if (compat->gpioz) + stm32mp_register_gpioz_pin_count(bank->ngpios); + + *out_bank = bank; + return TEE_SUCCESS; +} + +static void set_bank_gpio_non_secure(struct stm32_gpio_bank *bank) +{ + unsigned int pin = 0; + + for (pin = 0; pin < bank->ngpios; pin++) + stm32_gpio_set_secure_cfg(bank->bank_id, pin, false); +} + +/* Parse a pinctrl node to register and configure the GPIO banks it describes */ +static TEE_Result dt_stm32_gpio_pinctrl(const void *fdt, int node, + const void *compat_data) +{ + TEE_Result res = TEE_SUCCESS; + const fdt32_t *cuint = NULL; + int range_offs = 0; + int b_node = 0; + int len = 0; + + /* Read the ranges property (for regs memory translation) */ + cuint = fdt_getprop(fdt, node, "ranges", &len); + if (!cuint) + panic("missing ranges property"); + + len /= sizeof(*cuint); + if (len == 3) + range_offs = fdt32_to_cpu(*(cuint + 1)) - fdt32_to_cpu(*cuint); + + fdt_for_each_subnode(b_node, fdt, node) { + cuint = fdt_getprop(fdt, b_node, "gpio-controller", &len); + if (cuint) { + /* + * We found a property "gpio-controller" in the node: + * the node is a GPIO bank description, add it to the + * bank list. + */ + struct stm32_gpio_bank *bank = NULL; + + if (fdt_get_status(fdt, b_node) == DT_STATUS_DISABLED || + bank_is_registered(fdt, b_node)) + continue; + + res = dt_stm32_gpio_bank(fdt, b_node, compat_data, + range_offs, &bank); + if (res) + return res; + + /* Registering a provider should not defer probe */ + res = gpio_register_provider(fdt, b_node, + stm32_gpio_get_dt, bank); + if (res) + panic(); + + STAILQ_INSERT_TAIL(&bank_list, bank, link); + + DMSG("Registered GPIO bank %c (%d pins) @%#"PRIxVA, + bank->bank_id + 'A', bank->ngpios, bank->base); + + assert(bank->ngpios <= GPIO_PIN_MAX + 1); + + if (bank->sec_support) { + uint32_t seccfgr = 0; + unsigned int i = 0; + int lenp = 0; + + cuint = fdt_getprop(fdt, b_node, "st,protreg", + &lenp); + if (!cuint) { + set_bank_gpio_non_secure(bank); + continue; + } + + seccfgr = fdt32_to_cpu(*cuint); + for (i = 0; i < bank->ngpios; i++) + stm32_gpio_set_secure_cfg(bank->bank_id, + i, + seccfgr & + TZPROT(i)); + } + } else { + if (len != -FDT_ERR_NOTFOUND) + panic(); + } + } + + return TEE_SUCCESS; +} + +void stm32_gpio_set_secure_cfg(unsigned int bank_id, unsigned int pin, + bool secure) +{ + struct stm32_gpio_bank *bank = stm32_gpio_get_bank(bank_id); + uint32_t exceptions = 0; + + if (clk_enable(bank->clock)) + panic(); + exceptions = cpu_spin_lock_xsave(&gpio_lock); + + if (secure) + io_setbits32(bank->base + GPIO_SECR_OFFSET, BIT(pin)); + else + io_clrbits32(bank->base + GPIO_SECR_OFFSET, BIT(pin)); + + FMSG("Set secure GPIO: bank %c pin %u", bank->bank_id + 'A', pin); + + cpu_spin_unlock_xrestore(&gpio_lock, exceptions); + clk_disable(bank->clock); +} + +#ifdef CFG_DRIVERS_PINCTRL +static TEE_Result stm32_pinctrl_conf_apply(struct pinconf *conf) +{ + struct stm32_pinctrl_array *ref = conf->priv; + struct stm32_pinctrl *p = ref->pinctrl; + size_t pin_count = ref->count; + size_t n = 0; + + for (n = 0; n < pin_count; n++) + set_gpio_cfg(p[n].bank, p[n].pin, &p[n].cfg); + + return TEE_SUCCESS; +} + +static void stm32_pinctrl_conf_free(struct pinconf *conf) +{ + free(conf); +} + +static const struct pinctrl_ops stm32_pinctrl_ops = { + .conf_apply = stm32_pinctrl_conf_apply, + .conf_free = stm32_pinctrl_conf_free, +}; + +DECLARE_KEEP_PAGER(stm32_pinctrl_ops); + +void stm32_gpio_pinctrl_bank_pin(struct pinctrl_state *pinctrl, + unsigned int *bank, unsigned int *pin, + unsigned int *count) +{ + size_t conf_index = 0; + size_t pin_count = 0; + size_t n = 0; + + assert(count); + if (!pinctrl) + goto out; + + for (conf_index = 0; conf_index < pinctrl->conf_count; conf_index++) { + struct pinconf *pinconf = pinctrl->confs[conf_index]; + struct stm32_pinctrl_array *ref = pinconf->priv; + + /* Consider only the stm32_gpio pins */ + if (pinconf->ops != &stm32_pinctrl_ops) + continue; + + if (bank || pin) { + for (n = 0; n < ref->count; n++) { + if (bank && pin_count < *count) + bank[pin_count] = ref->pinctrl[n].bank; + if (pin && pin_count < *count) + pin[pin_count] = ref->pinctrl[n].pin; + pin_count++; + } + } else { + pin_count += ref->count; + } + } + +out: + *count = pin_count; +} + +void stm32_pinctrl_set_secure_cfg(struct pinctrl_state *pinctrl, bool secure) +{ + size_t conf_index = 0; + + if (!pinctrl) + return; + + for (conf_index = 0; conf_index < pinctrl->conf_count; conf_index++) { + struct pinconf *pinconf = pinctrl->confs[conf_index]; + struct stm32_pinctrl_array *ref = pinconf->priv; + struct stm32_pinctrl *pc = NULL; + size_t n = 0; + + for (n = 0; n < ref->count; n++) { + if (pinconf->ops != &stm32_pinctrl_ops) + continue; + + pc = ref->pinctrl + n; + stm32_gpio_set_secure_cfg(pc->bank, pc->pin, secure); + } + } +} + +/* Allocate and return a pinctrl configuration from a DT reference */ +static TEE_Result stm32_pinctrl_dt_get(struct dt_pargs *pargs, + void *data __unused, + struct pinconf **out_pinconf) +{ + struct conf { + struct pinconf pinconf; + struct stm32_pinctrl_array array_ref; + } *loc_conf = NULL; + struct stm32_pinctrl *pinctrl = NULL; + struct pinconf *pinconf = NULL; + const void *fdt = NULL; + size_t pin_count = 0; + int pinctrl_node = 0; + int pinmux_node = 0; + int count = 0; + + pinctrl_node = pargs->phandle_node; + fdt = pargs->fdt; + assert(fdt && pinctrl_node); + + fdt_for_each_subnode(pinmux_node, fdt, pinctrl_node) { + if (fdt_getprop(fdt, pinmux_node, "pinmux", &count)) + pin_count += (size_t)count / sizeof(uint32_t); + else if (count != -FDT_ERR_NOTFOUND) + panic(); + } + + loc_conf = calloc(1, sizeof(*loc_conf) + sizeof(*pinctrl) * pin_count); + if (!loc_conf) + return TEE_ERROR_OUT_OF_MEMORY; + + pinconf = &loc_conf->pinconf; + pinconf->ops = &stm32_pinctrl_ops; + pinconf->priv = &loc_conf->array_ref; + + loc_conf->array_ref.count = pin_count; + pinctrl = loc_conf->array_ref.pinctrl; + + count = 0; + fdt_for_each_subnode(pinmux_node, fdt, pinctrl_node) { + int found = 0; + + found = get_pinctrl_from_fdt(fdt, pinmux_node, pinctrl + count, + pin_count - count); + if (found <= 0 && found > ((int)pin_count - count)) { + /* We can't recover from an error here so let's panic */ + panic(); + } + + count += found; + } + + *out_pinconf = pinconf; + + return TEE_SUCCESS; +} +#endif /*CFG_DRIVERS_PINCTRL*/ + +static TEE_Result stm32_pinctrl_probe(const void *fdt, int node, + const void *compat_data) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + /* Register GPIO banks described in this pin control node */ + res = dt_stm32_gpio_pinctrl(fdt, node, compat_data); + if (res) + return res; + +#ifdef CFG_DRIVERS_PINCTRL + res = pinctrl_register_provider(fdt, node, stm32_pinctrl_dt_get, + (void *)compat_data); + if (res) + return res; +#endif + + return TEE_SUCCESS; +} + +static const struct dt_device_match stm32_pinctrl_match_table[] = { + { + .compatible = "st,stm32mp135-pinctrl", + .compat_data = &(struct bank_compat){ + .secure_control = true, + }, + }, + { + .compatible = "st,stm32mp157-pinctrl", + .compat_data = &(struct bank_compat){ + .secure_control = false, + }, + }, + { + .compatible = "st,stm32mp157-z-pinctrl", + .compat_data = &(struct bank_compat){ + .gpioz = true, + .secure_control = true, + }, + }, + { } +}; + +DEFINE_DT_DRIVER(stm32_pinctrl_dt_driver) = { + .name = "stm32_gpio-pinctrl", + .type = DT_DRIVER_PINCTRL, + .match_table = stm32_pinctrl_match_table, + .probe = stm32_pinctrl_probe, +}; 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..da75a25 --- /dev/null +++ b/optee/optee_os/core/drivers/stm32_i2c.c @@ -0,0 +1,1702 @@ +// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +/* + * Copyright (c) 2017-2024, 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 +#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 I2C_TIMEOUT_DEFAULT_MS 100 + +#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 + */ +static void i2c_config_analog_filter(struct i2c_handle_s *hi2c, + bool analog_filter_on) +{ + vaddr_t base = get_base(hi2c); + + /* 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); +} + +TEE_Result stm32_i2c_get_setup_from_fdt(void *fdt, int node, + struct stm32_i2c_init_s *init, + struct pinctrl_state **pinctrl, + struct pinctrl_state **pinctrl_sleep) +{ + TEE_Result res = TEE_ERROR_GENERIC; + const fdt32_t *cuint = NULL; + struct dt_node_info info = { .status = 0 }; + int __maybe_unused 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; + } + + if (pinctrl) { + res = pinctrl_get_state_by_name(fdt, node, "default", pinctrl); + if (res) + return res; + } + + if (pinctrl_sleep) { + res = pinctrl_get_state_by_name(fdt, node, "sleep", + pinctrl_sleep); + if (res == TEE_ERROR_ITEM_NOT_FOUND) + res = TEE_SUCCESS; + if (res) + return res; + } + + 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; + + mutex_pm_aware_init(&hi2c->mu); + + 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; + + i2c_config_analog_filter(hi2c, init_data->analog_filter); + + if (IS_ENABLED(CFG_STM32MP13)) + stm32_pinctrl_set_secure_cfg(hi2c->pinctrl, true); + + clk_disable(hi2c->clock); + + if (hi2c->pinctrl && pinctrl_apply_state(hi2c->pinctrl)) + return -1; + + return 0; +} + +/* 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 do_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 (!p_data || !size) + return -1; + + mutex_pm_aware_lock(&hi2c->mu); + + if (hi2c->i2c_state != I2C_STATE_READY) { + mutex_pm_aware_unlock(&hi2c->mu); + 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); + mutex_pm_aware_unlock(&hi2c->mu); + + 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 do_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 do_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; + + mutex_pm_aware_lock(&hi2c->mu); + + if (hi2c->i2c_state != I2C_STATE_READY || !p_data) { + mutex_pm_aware_unlock(&hi2c->mu); + 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); + mutex_pm_aware_unlock(&hi2c->mu); + + 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 do_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 (!p_data || !size) + return -1; + + mutex_pm_aware_lock(&hi2c->mu); + + if (hi2c->i2c_state != I2C_STATE_READY) { + mutex_pm_aware_unlock(&hi2c->mu); + 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); + mutex_pm_aware_unlock(&hi2c->mu); + + 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 do_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 do_read(hi2c, &request, p_data, size); +} + +static struct i2c_handle_s *stm32_i2c_dev_to_handle(struct i2c_dev *i2c_dev) +{ + struct stm32_i2c_dev *dev = container_of(i2c_dev, struct stm32_i2c_dev, + i2c_dev); + + return dev->handle; +} + +static TEE_Result stm32_i2c_read_data(struct i2c_dev *i2c_dev, uint8_t *buf, + size_t len) +{ + struct i2c_handle_s *i2c_handle = stm32_i2c_dev_to_handle(i2c_dev); + int rc = 0; + + rc = stm32_i2c_master_receive(i2c_handle, i2c_dev->addr, buf, len, + I2C_TIMEOUT_DEFAULT_MS); + if (!rc) + return TEE_SUCCESS; + else + return TEE_ERROR_GENERIC; +} + +static TEE_Result stm32_i2c_write_data(struct i2c_dev *i2c_dev, + const uint8_t *buf, size_t len) +{ + struct i2c_handle_s *i2c_handle = stm32_i2c_dev_to_handle(i2c_dev); + uint8_t *buf2 = (uint8_t *)buf; + int rc = 0; + + rc = stm32_i2c_master_transmit(i2c_handle, i2c_dev->addr, buf2, len, + I2C_TIMEOUT_DEFAULT_MS); + if (!rc) + return TEE_SUCCESS; + else + return TEE_ERROR_GENERIC; +} + +static const struct i2c_ctrl_ops stm32_i2c_ops = { + .read = stm32_i2c_read_data, + .write = stm32_i2c_write_data, +}; + +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; + + mutex_pm_aware_lock(&hi2c->mu); + + if (hi2c->i2c_state != I2C_STATE_READY) { + mutex_pm_aware_unlock(&hi2c->mu); + 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); + mutex_pm_aware_unlock(&hi2c->mu); + + 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(); + + if (pinctrl_apply_state(hi2c->pinctrl)) + panic(); + + 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_pinctrl_set_secure_cfg(hi2c->pinctrl, 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); + + if (hi2c->pinctrl_sleep && pinctrl_apply_state(hi2c->pinctrl_sleep)) + panic(); + + hi2c->i2c_state = I2C_STATE_SUSPENDED; +} + +static TEE_Result stm32_get_i2c_dev(struct dt_pargs *args, void *data, + struct i2c_dev **out_device) +{ + struct stm32_i2c_dev *stm32_i2c_dev = NULL; + paddr_t addr = 0; + + addr = fdt_reg_base_address(args->fdt, args->phandle_node); + if (addr == DT_INFO_INVALID_REG) { + DMSG("Can't get device I2C address"); + return TEE_ERROR_GENERIC; + } + + stm32_i2c_dev = calloc(1, sizeof(*stm32_i2c_dev)); + if (!stm32_i2c_dev) + return TEE_ERROR_OUT_OF_MEMORY; + + stm32_i2c_dev->handle = data; + stm32_i2c_dev->i2c_dev.addr = addr; + stm32_i2c_dev->i2c_ctrl.ops = &stm32_i2c_ops; + stm32_i2c_dev->i2c_dev.ctrl = &stm32_i2c_dev->i2c_ctrl; + + *out_device = &stm32_i2c_dev->i2c_dev; + + return TEE_SUCCESS; +} + +static TEE_Result stm32_i2c_probe(const void *fdt, int node, + const void *compat_data __unused) +{ + TEE_Result res = TEE_SUCCESS; + int subnode = 0; + struct i2c_handle_s *i2c_handle_p = NULL; + struct stm32_i2c_init_s init_data = { }; + struct pinctrl_state *pinctrl_active = NULL; + struct pinctrl_state *pinctrl_idle = NULL; + + res = stm32_i2c_get_setup_from_fdt((void *)fdt, node, &init_data, + &pinctrl_active, &pinctrl_idle); + if (res) + return res; + + i2c_handle_p = calloc(1, sizeof(struct i2c_handle_s)); + if (!i2c_handle_p) + return TEE_ERROR_OUT_OF_MEMORY; + + i2c_handle_p->dt_status = init_data.dt_status; + i2c_handle_p->reg_size = init_data.reg_size; + i2c_handle_p->clock = init_data.clock; + i2c_handle_p->base.pa = init_data.pbase; + i2c_handle_p->base.va = io_pa_or_va(&i2c_handle_p->base, + init_data.reg_size); + assert(i2c_handle_p->base.va); + i2c_handle_p->clock = init_data.clock; + i2c_handle_p->i2c_state = I2C_STATE_RESET; + i2c_handle_p->pinctrl = pinctrl_active; + i2c_handle_p->pinctrl_sleep = pinctrl_idle; + + init_data.analog_filter = true; + init_data.digital_filter_coef = 0; + + if (stm32_i2c_init(i2c_handle_p, &init_data)) + panic("Couldn't initialise I2C"); + + res = i2c_register_provider(fdt, node, stm32_get_i2c_dev, i2c_handle_p); + if (res) + panic("Couldn't register I2C provider"); + + 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 res; +} + +static const struct dt_device_match stm32_i2c_match_table[] = { + { .compatible = "st,stm32mp15-i2c" }, + { .compatible = "st,stm32mp13-i2c" }, + { .compatible = "st,stm32mp15-i2c-non-secure" }, + { } +}; + +DEFINE_DT_DRIVER(stm32_i2c_dt_driver) = { + .name = "stm32_i2c", + .match_table = stm32_i2c_match_table, + .probe = stm32_i2c_probe, + .type = DT_DRIVER_I2C +}; 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..c7b7ae8 --- /dev/null +++ b/optee/optee_os/core/drivers/stm32_iwdg.c @@ -0,0 +1,414 @@ +// 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 + * @clk_pclk - 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 *clk_pclk; + struct clk *clk_lsi; + uint32_t flags; + unsigned long timeout; + struct wdt_chip wdt_chip; + SLIST_ENTRY(stm32_iwdg_device) link; +}; + +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 void iwdg_wdt_set_enabled(struct stm32_iwdg_device *iwdg) +{ + iwdg->flags |= IWDG_FLAGS_ENABLED; +} + +static bool iwdg_wdt_is_enabled(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(iwdg_wdt_is_enabled(iwdg)); + + rlr_value = iwdg_timeout_cnt(iwdg, iwdg->timeout); + if (!rlr_value) + return TEE_ERROR_GENERIC; + + 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); + + return res; +} + +static void iwdg_start(struct stm32_iwdg_device *iwdg) +{ + io_write32(get_base(iwdg) + IWDG_KR_OFFSET, IWDG_KR_START_KEY); + + iwdg_wdt_set_enabled(iwdg); +} + +static void iwdg_refresh(struct stm32_iwdg_device *iwdg) +{ + io_write32(get_base(iwdg) + IWDG_KR_OFFSET, IWDG_KR_RELOAD_KEY); +} + +/* 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 TEE_Result iwdg_wdt_init(struct wdt_chip *chip, + unsigned long *min_timeout, + unsigned long *max_timeout) +{ + struct stm32_iwdg_device *iwdg = wdt_chip_to_iwdg(chip); + unsigned long rate = clk_get_rate(iwdg->clk_lsi); + + if (!rate) + return TEE_ERROR_GENERIC; + + /* Be safe and expect any counter to be above 2 */ + *min_timeout = 3 * IWDG_PRESCALER_256 / rate; + *max_timeout = (IWDG_CNT_MASK + 1) * IWDG_PRESCALER_256 / rate; + + return TEE_SUCCESS; +} + +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 (iwdg_wdt_is_enabled(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 = { + .init = iwdg_wdt_init, + .start = iwdg_wdt_start, + .ping = iwdg_wdt_refresh, + .set_timeout = iwdg_wdt_set_timeout, +}; +DECLARE_KEEP_PAGER(stm32_iwdg_ops); + +/* 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->clk_pclk); + 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 and bus clocks once for all */ + clk_enable(iwdg->clk_lsi); + clk_enable(iwdg->clk_pclk); + + 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..bb9d4ae --- /dev/null +++ b/optee/optee_os/core/drivers/stm32_rng.c @@ -0,0 +1,750 @@ +// 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 +#include + +#define RNG_CR U(0x00) +#define RNG_SR U(0x04) +#define RNG_DR U(0x08) +#define RNG_NSCR U(0x0C) +#define RNG_HTCR U(0x10) +#define RNG_VERR U(0x3F4) + +#define RNG_CR_RNGEN BIT(2) +#define RNG_CR_IE BIT(3) +#define RNG_CR_CED BIT(5) +#define RNG_CR_CONFIG1 GENMASK_32(11, 8) +#define RNG_CR_NISTC BIT(12) +#define RNG_CR_POWER_OPTIM BIT(13) +#define RNG_CR_CONFIG2 GENMASK_32(15, 13) +#define RNG_CR_CLKDIV GENMASK_32(19, 16) +#define RNG_CR_CLKDIV_SHIFT U(16) +#define RNG_CR_CONFIG3 GENMASK_32(25, 20) +#define RNG_CR_CONDRST BIT(30) +#define RNG_CR_ENTROPY_SRC_MASK (RNG_CR_CONFIG1 | RNG_CR_NISTC | \ + RNG_CR_CONFIG2 | RNG_CR_CONFIG3) + +#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) + +#define RNG_NSCR_MASK GENMASK_32(17, 0) + +#define RNG_VERR_MINOR_MASK GENMASK_32(3, 0) +#define RNG_VERR_MAJOR_MASK GENMASK_32(7, 4) +#define RNG_VERR_MAJOR_SHIFT U(4) + +#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_CONFIG_MASK (RNG_CR_ENTROPY_SRC_MASK | RNG_CR_CED | \ + RNG_CR_CLKDIV) + +struct stm32_rng_driver_data { + unsigned long max_noise_clk_freq; + unsigned long nb_clock; + uint32_t cr; + uint32_t nscr; + uint32_t htcr; + bool has_power_optim; + bool has_cond_reset; +}; + +struct stm32_rng_instance { + struct io_pa_va base; + struct clk *clock; + struct clk *bus_clock; + struct rstctrl *rstctrl; + const struct stm32_rng_driver_data *ddata; + unsigned int lock; + uint64_t error_to_ref; + uint32_t pm_cr; + uint32_t pm_health; + uint32_t pm_noise_ctrl; + uint32_t health_test_conf; + uint32_t noise_ctrl_conf; + uint32_t rng_config; + bool release_post_boot; + bool clock_error; + bool error_conceal; +}; + +/* 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 = 0; + size_t sz = MIN(len, sizeof(uint32_t)); + + if (!(io_read32(rng_base + RNG_SR) & RNG_SR_DRDY)) + break; + data32 = io_read32(rng_base + RNG_DR); + + /* 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 - len; + + 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) > dev->ddata->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(); + uint32_t cr_ced_mask = 0; + uint32_t value = 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(); + + /* + * Keep default RNG configuration if none was specified. + * 0 is an invalid value as it disables all entropy sources. + */ + if (!stm32_rng->rng_config) + stm32_rng->rng_config = io_read32(rng_base + RNG_CR) & + RNG_CR_ENTROPY_SRC_MASK; + + /* + * Configuration must be set in the same access that sets + * RNG_CR_CONDRST bit. Otherwise, the configuration setting is + * not taken into account. CONFIGLOCK bit is always cleared at + * this stage. + */ + io_clrsetbits32(rng_base + RNG_CR, RNG_CONFIG_MASK, + stm32_rng->rng_config | RNG_CR_CONDRST | + cr_ced_mask | + SHIFT_U32(clock_div, RNG_CR_CLKDIV_SHIFT)); + + /* + * Write health test and noise source control configuration + * according to current RNG entropy source configuration + */ + if (stm32_rng->noise_ctrl_conf) + io_write32(rng_base + RNG_NSCR, + stm32_rng->noise_ctrl_conf); + + if (stm32_rng->health_test_conf) + io_write32(rng_base + RNG_HTCR, + stm32_rng->health_test_conf); + + io_clrsetbits32(rng_base + RNG_CR, RNG_CR_CONDRST, + RNG_CR_RNGEN); + + if (IO_READ32_POLL_TIMEOUT(rng_base + RNG_CR, value, + !(value & RNG_CR_CONDRST), 0, + RNG_READY_TIMEOUT_US)) + panic(); + + DMSG("RNG control register %#"PRIx32, + io_read32(rng_base + RNG_CR)); + DMSG("RNG noise source control register %#"PRIx32, + io_read32(rng_base + RNG_NSCR)); + DMSG("RNG health test register %#"PRIx32, + io_read32(rng_base + RNG_HTCR)); + } else { + io_setbits32(rng_base + RNG_CR, RNG_CR_RNGEN | cr_ced_mask); + } + + if (IO_READ32_POLL_TIMEOUT(rng_base + RNG_SR, value, + value & RNG_SR_DRDY, 0, + RNG_READY_TIMEOUT_US)) + 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; + } + + rc = clk_enable(stm32_rng->clock); + if (rc) + return rc; + + if (stm32_rng->bus_clock) { + rc = clk_enable(stm32_rng->bus_clock); + if (rc) { + clk_disable(stm32_rng->clock); + return rc; + } + } + + 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); + if (stm32_rng->bus_clock) + clk_disable(stm32_rng->bus_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(void) +{ + vaddr_t base = get_base(); + + /* Clean error indications */ + io_write32(base + RNG_SR, 0); + + if (stm32_rng->ddata->has_cond_reset) { + uint64_t timeout_ref = 0; + + /* + * Configuration must be set in the same access that sets + * RNG_CR_CONDRST bit. Otherwise, the configuration setting is + * not taken into account. CONFIGLOCK bit is always cleared in + * this configuration. + */ + io_write32(base + RNG_CR, stm32_rng->pm_cr | RNG_CR_CONDRST); + + /* Restore health test and noise control configuration */ + io_write32(base + RNG_NSCR, stm32_rng->pm_noise_ctrl); + io_write32(base + RNG_HTCR, stm32_rng->pm_health); + + io_clrsetbits32(base + RNG_CR, RNG_CR_CONDRST, RNG_CR_RNGEN); + + timeout_ref = timeout_init_us(RNG_READY_TIMEOUT_US); + while (io_read32(base + RNG_CR) & RNG_CR_CONDRST) + if (timeout_elapsed(timeout_ref)) + break; + if (io_read32(base + RNG_CR) & RNG_CR_CONDRST) + panic(); + } else { + io_write32(base + RNG_CR, RNG_CR_RNGEN | stm32_rng->pm_cr); + } + + return TEE_SUCCESS; +} + +static TEE_Result stm32_rng_pm_suspend(void) +{ + vaddr_t rng_base = get_base(); + + stm32_rng->pm_cr = io_read32(rng_base + RNG_CR); + + if (stm32_rng->ddata->has_cond_reset) { + stm32_rng->pm_health = io_read32(rng_base + RNG_HTCR); + stm32_rng->pm_noise_ctrl = io_read32(rng_base + RNG_NSCR); + } + + if (stm32_rng->ddata->has_power_optim) { + uint64_t timeout_ref = 0; + + /* + * As per reference manual, it is recommended to set + * RNG_CONFIG2[bit0] when RNG power consumption is critical. + */ + io_setbits32(rng_base + RNG_CR, RNG_CR_POWER_OPTIM | + RNG_CR_CONDRST); + io_clrbits32(rng_base + RNG_CR, RNG_CR_CONDRST); + + timeout_ref = timeout_init_us(RNG_READY_TIMEOUT_US); + while (io_read32(rng_base + RNG_CR) & RNG_CR_CONDRST) + if (timeout_elapsed(timeout_ref)) + break; + if (io_read32(rng_base + RNG_CR) & RNG_CR_CONDRST) + panic(); + } else { + io_clrbits32(rng_base + RNG_CR, RNG_CR_RNGEN); + } + + 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) +{ + 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 (stm32_rng->bus_clock) { + res = clk_enable(stm32_rng->bus_clock); + if (res) { + clk_disable(stm32_rng->clock); + return res; + } + } + + if (op == PM_OP_RESUME) + res = stm32_rng_pm_resume(); + else + res = stm32_rng_pm_suspend(); + + clk_disable(stm32_rng->clock); + if (stm32_rng->bus_clock) + clk_disable(stm32_rng->bus_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; + + if (stm32_rng->ddata->nb_clock > 1) { + res = clk_dt_get_by_name(fdt, node, "rng_clk", + &stm32_rng->clock); + if (res) + return res; + + res = clk_dt_get_by_name(fdt, node, "rng_hclk", + &stm32_rng->bus_clock); + if (res) + return res; + } else { + 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 after initialization */ + stm32_rng->release_post_boot = IS_ENABLED(CFG_WITH_SOFTWARE_PRNG); + + stm32_rng->rng_config = stm32_rng->ddata->cr; + if (stm32_rng->rng_config & ~RNG_CR_ENTROPY_SRC_MASK) + panic("Incorrect entropy source configuration"); + stm32_rng->health_test_conf = stm32_rng->ddata->htcr; + stm32_rng->noise_ctrl_conf = stm32_rng->ddata->nscr; + if (stm32_rng->noise_ctrl_conf & ~RNG_NSCR_MASK) + panic("Incorrect noise source control configuration"); + + return TEE_SUCCESS; +} + +static TEE_Result stm32_rng_probe(const void *fdt, int offs, + const void *compat_data) +{ + TEE_Result res = TEE_ERROR_GENERIC; + unsigned int __maybe_unused version = 0; + + /* Expect a single RNG instance */ + assert(!stm32_rng); + + stm32_rng = calloc(1, sizeof(*stm32_rng)); + if (!stm32_rng) + panic(); + + stm32_rng->ddata = compat_data; + assert(stm32_rng->ddata); + + res = stm32_rng_parse_fdt(fdt, offs); + if (res) + goto err; + + res = clk_enable(stm32_rng->clock); + if (res) + goto err; + + if (stm32_rng->bus_clock) { + res = clk_enable(stm32_rng->bus_clock); + if (res) { + clk_disable(stm32_rng->clock); + goto err; + } + } + + version = io_read32(get_base() + RNG_VERR); + DMSG("RNG version Major %u, Minor %u", + (version & RNG_VERR_MAJOR_MASK) >> RNG_VERR_MAJOR_SHIFT, + version & RNG_VERR_MINOR_MASK); + + 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->bus_clock) + clk_disable(stm32_rng->bus_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); + + /* Power management implementation expects both or none are set */ + assert(stm32_rng->ddata->has_power_optim == + stm32_rng->ddata->has_cond_reset); + + register_pm_core_service_cb(stm32_rng_pm, &stm32_rng, "rng-service"); + + return TEE_SUCCESS; + +err_clk: + clk_disable(stm32_rng->clock); + if (stm32_rng->bus_clock) + clk_disable(stm32_rng->bus_clock); +err: + free(stm32_rng); + stm32_rng = NULL; + + return res; +} + +static const struct stm32_rng_driver_data mp13_data[] = { + { + .max_noise_clk_freq = U(48000000), + .nb_clock = 1, + .has_cond_reset = true, + .has_power_optim = true, + .cr = 0x00F00D00, + .nscr = 0x2B5BB, + .htcr = 0x969D, + }, +}; + +static const struct stm32_rng_driver_data mp15_data[] = { + { + .max_noise_clk_freq = U(48000000), + .nb_clock = 1, + .has_cond_reset = false, + .has_power_optim = false, + }, +}; +DECLARE_KEEP_PAGER(mp15_data); + +static const struct stm32_rng_driver_data mp25_data[] = { + { + .max_noise_clk_freq = U(48000000), + .nb_clock = 2, + .has_cond_reset = true, + .has_power_optim = true, + .cr = 0x00F00D00, + .nscr = 0x2B5BB, + .htcr = 0x969D, + }, +}; + +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 }, + { .compatible = "st,stm32mp25-rng", .compat_data = &mp25_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..f737525 --- /dev/null +++ b/optee/optee_os/core/drivers/stm32_uart.c @@ -0,0 +1,196 @@ +// 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 +#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 23 TXFE: TXFIFO empty + */ +#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(23) + +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) +{ +#ifndef CFG_STM32MP25 + stm32mp_register_secure_periph_iomem(pd->base.pa); + stm32mp_register_secure_pinctrl(pd->pinctrl); + if (pd->pinctrl_sleep) + stm32mp_register_secure_pinctrl(pd->pinctrl_sleep); +#else + stm32_pinctrl_set_secure_cfg(pd->pinctrl, true); + if (pd->pinctrl_sleep) + stm32_pinctrl_set_secure_cfg(pd->pinctrl, true); +#endif +} + +static void register_non_secure_uart(struct stm32_uart_pdata *pd) +{ +#ifndef CFG_STM32MP25 + stm32mp_register_non_secure_periph_iomem(pd->base.pa); + stm32mp_register_non_secure_pinctrl(pd->pinctrl); + if (pd->pinctrl_sleep) + stm32mp_register_non_secure_pinctrl(pd->pinctrl_sleep); +#else + stm32_pinctrl_set_secure_cfg(pd->pinctrl, false); + if (pd->pinctrl_sleep) + stm32_pinctrl_set_secure_cfg(pd->pinctrl, false); +#endif + +} + +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 = { }; + + 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); + + res = pinctrl_get_state_by_name(fdt, node, "default", &pd->pinctrl); + if (res) + panic(); + + res = pinctrl_get_state_by_name(fdt, node, "sleep", &pd->pinctrl_sleep); + if (res && res != TEE_ERROR_ITEM_NOT_FOUND) + panic(); + + res = pinctrl_apply_state(pd->pinctrl); + if (res) + panic(); + + 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..e0550d9 --- /dev/null +++ b/optee/optee_os/core/drivers/stm32mp15_huk.c @@ -0,0 +1,220 @@ +// 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; + uint8_t __maybe_unused offset = 0; + + ret = stm32_bsec_find_otp_in_nvmem_layout("uid_otp", &otp_idx, &offset, + &sz); + if (ret) + return ret; + assert(sz == 3 * 32); + assert(offset == 0); + + /* + * 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 sz = 0; + uint8_t offset = 0; + size_t i = 0; + + ret = stm32_bsec_find_otp_in_nvmem_layout("huk-otp", &otp_start, + &offset, &sz); + if (ret) + return ret; + + if (sz != (HW_UNIQUE_KEY_LENGTH * CHAR_BIT) || offset != 0) + 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..444b983 --- /dev/null +++ b/optee/optee_os/core/drivers/stpmic1.c @@ -0,0 +1,1027 @@ +// 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; + + /* Remove last cell 0xFFFF that is not a voltage level */ + if (regul->voltage_table == ldo3_voltage_table) + (*levels_count)--; + } + + 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..808e420 --- /dev/null +++ b/optee/optee_os/core/drivers/sub.mk @@ -0,0 +1,101 @@ +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_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_TEGRA_TCU) += tegra_combined_uart.c +srcs-$(CFG_CBMEM_CONSOLE) += cbmem_console.c +srcs-$(CFG_RISCV_PLIC) += plic.c +srcs-$(CFG_HISILICON_CRYPTO_DRIVER) += hisi_trng.c +srcs-$(CFG_WIDEVINE_HUK) += widevine_huk.c +srcs-$(CFG_SEMIHOSTING_CONSOLE) += semihosting_console.c + +subdirs-y += crypto +subdirs-$(CFG_BNXT_FW) += bnxt +subdirs-$(CFG_DRIVERS_CLK) += clk +subdirs-$(CFG_DRIVERS_GPIO) += gpio +subdirs-$(CFG_DRIVERS_I2C) += i2c +subdirs-$(CFG_DRIVERS_NVMEM) += nvmem +subdirs-$(CFG_DRIVERS_PINCTRL) += pinctrl +subdirs-$(CFG_DRIVERS_REGULATOR) += regulator +subdirs-$(CFG_DRIVERS_RSTCTRL) += rstctrl +subdirs-$(CFG_DRIVERS_REMOTEPROC) += remoteproc +subdirs-$(CFG_SCMI_MSG_DRIVERS) += scmi-msg +subdirs-y += imx +subdirs-$(CFG_TEGRA_DRIVERS) += tegra +subdirs-y += pm +subdirs-y += wdt +subdirs-y += rtc +subdirs-y += firewall 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..e4f6a96 --- /dev/null +++ b/optee/optee_os/core/drivers/tegra/common/include/tegra_driver_fuse.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. + */ + +#ifndef __TEGRA_DRIVER_FUSE_H__ +#define __TEGRA_DRIVER_FUSE_H__ + +#include + +#if defined(PLATFORM_FLAVOR_t194) +#define TEGRA_FUSE_BASE 0x03820000 +#define TEGRA_FUSE_SIZE 0x600 +#define TEGRA_INT_CID 7ULL +#endif + +#if defined(PLATFORM_FLAVOR_t234) +#define TEGRA_FUSE_BASE 0x03810000 +#define TEGRA_FUSE_SIZE 0x600 +#define TEGRA_INT_CID 8ULL +#endif + +#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 +#define FUSE_SN_SIZE 10U +#define FUSE_ODMID0_0 0x408 +#define FUSE_ODMID1_0 0x40c +#define FUSE_ODM_INFO_0 0x29c + +TEE_Result tegra_fuse_map_regs(vaddr_t *va, size_t *size); +TEE_Result tegra_fuse_unmap_regs(vaddr_t va, size_t size); +TEE_Result fuse_generate_ecid(vaddr_t fuse_va_base, fuse_ecid_t *ecid_128, uint64_t *ecid_64); +TEE_Result fuse_generate_sn(vaddr_t fuse_va_base, uint8_t *sn, uint32_t *size); + +#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..c9d6b79 --- /dev/null +++ b/optee/optee_os/core/drivers/tegra/common/include/tegra_driver_se.h @@ -0,0 +1,46 @@ +/* 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; + +typedef enum +{ + /** Message digests **/ + /** + * SHA digests calculated/supported by the Tegra HW engine. + * CRYPTO_HASH + */ + TEGRA_ALG_SHA1, /**< SHA-1 */ + TEGRA_ALG_SHA224, /**< SHA-224 */ + TEGRA_ALG_SHA256, /**< SHA-256 */ + TEGRA_ALG_SHA384, /**< SHA-384 */ + TEGRA_ALG_SHA512, /**< SHA-512 */ +} tegra_crypto_algo_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..f9ba5e6 --- /dev/null +++ b/optee/optee_os/core/drivers/tegra/common/include/tegra_driver_srv_intf.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021-2024, 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); + TEE_Result (*get_64bit_ecid)(uint64_t *val); + /* Fuse BSI interface */ + TEE_Result (*get_bsi)(uint32_t *val); + /* Fuse security mode interface */ + TEE_Result (*get_sec_mode)(uint32_t *val); + /* Fuse get SN interface */ + TEE_Result (*get_sn)(uint8_t **sn, uint32_t *size); + /* 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..5295013 --- /dev/null +++ b/optee/optee_os/core/drivers/tegra/common/tegra_driver_fuse.c @@ -0,0 +1,228 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2022-2024, NVIDIA CORPORATION & AFFILIATES. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +TEE_Result fuse_generate_ecid(vaddr_t fuse_va_base, fuse_ecid_t *ecid_128, uint64_t *ecid_64) +{ + uint32_t vendor, fab, wafer; + uint32_t lot, lot0, lot1; + uint32_t i, x, y, digit; + uint32_t rsvd1; + uint32_t reg; + + if (fuse_va_base == 0) + return TEE_ERROR_BAD_PARAMETERS; + if (ecid_128 == NULL || ecid_64 == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + 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; + ecid_128->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; + ecid_128->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; + ecid_128->ecid[2] = reg; + + reg = 0; + reg |= vendor & ECID_ECID3_0_VENDOR_MASK; + ecid_128->ecid[3] = reg; + + /* Start to get the 64-bit version ECID */ + /* Lot code must be re-encoded from a 5 digit base-36 'BCD' number + * to a binary number. + */ + lot = 0; + reg = io_read32(fuse_va_base + FUSE_OPT_LOT_CODE_0_0); + reg = reg << 2; + for (i = 0; i < 5; ++i) { + digit = (reg & 0xFC000000) >> 26; + if (digit >=36) + return TEE_ERROR_GENERIC; + + lot *= 36; + lot += digit; + reg <<= 6; + } + + /* The 64-bit version ECID format: + * Field Bits Position Data + * ------- ---- -------- ---------------------------------------- + * CID 4 60 Chip id + * VENDOR 4 56 Vendor code + * FAB 6 50 FAB code + * LOT 26 24 Lot code (5-digit base-36-coded-decimal, + * re-encoded to 26 bits binary) + * WAFER 6 18 Wafer id + * X 9 9 Wafer X-coordinate + * Y 9 0 Wafer Y-coordinate + * ------- ---- + * Total 64 + */ + *ecid_64 = (TEGRA_INT_CID << 60ull) + | ((unsigned long long)vendor << 56ull) + | ((unsigned long long)fab << 50ull) + | ((unsigned long long)lot << 24ull) + | ((unsigned long long)wafer << 18ull) + | ((unsigned long long)x << 9ull) + | ((unsigned long long)y << 0ull); + + return TEE_SUCCESS; +} + +TEE_Result fuse_generate_sn(vaddr_t fuse_va_base, uint8_t *sn, uint32_t *size) +{ + uint32_t odm_id_0, odm_id_1, odm_info; + uint16_t tmp = 0; + + if (fuse_va_base == 0) + return TEE_ERROR_BAD_PARAMETERS; + if (sn == NULL || size == NULL) + return TEE_ERROR_BAD_PARAMETERS; + if (*size < FUSE_SN_SIZE) + return TEE_ERROR_BAD_PARAMETERS; + + odm_id_0 = io_read32(fuse_va_base + FUSE_ODMID0_0); + odm_id_1 = io_read32(fuse_va_base + FUSE_ODMID1_0); + odm_info = io_read32(fuse_va_base + FUSE_ODM_INFO_0); + + /* + * All 4-byte or less Tegra fuses are stored in little-endian so we need + * to convert the first 2 bytes of SN here because odm_info is a 4-byte fuse. + * Besides PSC_BL1, all usages of SN assume it is saved in big-endian. + * For odm_id_0 and odm_id_1, they're treated as a 8-byte fuse so their values + * are always stored in big-endian. + */ + memcpy(&tmp, &odm_info, sizeof(tmp)); + tmp = __builtin_bswap16(tmp); + + memcpy(sn, &tmp, 2); + memcpy(sn + 2, &odm_id_0, 4); + memcpy(sn + 6, &odm_id_1, 4); + + *size = FUSE_SN_SIZE; + return TEE_SUCCESS; +} + +#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, size_t *size) +{ + void *fdt = NULL; + int node = -1; + uint32_t i = 0; + size_t map_size; + enum dt_map_dev_directive mapping = DT_MAP_SECURE; + + if (va == NULL || size == 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, &map_size, mapping) < 0) { + EMSG("%s: DT unable to map device address.", __func__); + return TEE_ERROR_GENERIC; + } + + *size = map_size; + 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, size_t *size) +{ + TEE_Result rc = TEE_SUCCESS; + + if (va == NULL || size == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + if (IS_ENABLED(CFG_DT)) { + rc = tegra_fuse_dt_init(va, size); + } else { + rc = iomap_pa2va(TEGRA_FUSE_BASE, TEGRA_FUSE_SIZE, va); + if (rc == TEE_SUCCESS) + *size = TEGRA_FUSE_SIZE; + } + + return rc; +} + +TEE_Result tegra_fuse_unmap_regs(vaddr_t va, size_t size) +{ + return core_mmu_remove_mapping(MEM_AREA_IO_SEC, (void *)va, size); +} 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..e282493 --- /dev/null +++ b/optee/optee_os/core/drivers/tegra/common/tegra_driver_srv_intf.c @@ -0,0 +1,144 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021-2024, 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_64bit_ecid(uint64_t *val) +{ + if (!tegra_drv_srv_intf || !tegra_drv_srv_intf->get_64bit_ecid) + return TEE_ERROR_NOT_SUPPORTED; + + return tegra_drv_srv_intf->get_64bit_ecid(val); +} + +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); +} + +TEE_Result tegra_fuse_get_sec_mode(uint32_t *val) +{ + if (!tegra_drv_srv_intf || !tegra_drv_srv_intf->get_sec_mode) + return TEE_ERROR_NOT_SUPPORTED; + + return tegra_drv_srv_intf->get_sec_mode(val); +} + + +TEE_Result tegra_fuse_get_sn(uint8_t **sn, uint32_t *size) +{ + if (!tegra_drv_srv_intf || !tegra_drv_srv_intf->get_sn) + return TEE_ERROR_NOT_SUPPORTED; + + return tegra_drv_srv_intf->get_sn(sn, size); +} + +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/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..243fca1 --- /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) += tegra_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_fuse.c b/optee/optee_os/core/drivers/tegra/t194/tegra_fuse.c new file mode 100644 index 0000000..153ac6a --- /dev/null +++ b/optee/optee_os/core/drivers/tegra/t194/tegra_fuse.c @@ -0,0 +1,99 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021-2024, NVIDIA CORPORATION & AFFILIATES. + */ + +#include +#include +#include +#include +#include +#include +#include + +static vaddr_t fuse_va_base = 0; +static fuse_ecid_t fuse_ecid; +static uint64_t fuse_ecid_64bit = 0; +static uint8_t fuse_sn[FUSE_SN_SIZE]; + +static fuse_ecid_t* fuse_get_ecid(void) +{ + return &fuse_ecid; +} + +static TEE_Result fuse_get_64bit_ecid(uint64_t *val) +{ + if (val == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + if (fuse_ecid_64bit == 0) + return TEE_ERROR_NOT_SUPPORTED; + + *val = fuse_ecid_64bit; + return TEE_SUCCESS; +} + +static TEE_Result fuse_get_bsi(uint32_t *val) +{ + (void) val; + return TEE_ERROR_NOT_SUPPORTED; +} + +static TEE_Result fuse_get_sec_mode(uint32_t *val) +{ + if (val == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + *val = io_read32(fuse_va_base + FUSE_SECURITY_MODE_0); + return TEE_SUCCESS; +} + +static TEE_Result fuse_get_sn(uint8_t **sn, uint32_t *size) +{ + if (sn == NULL || size == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + *sn = fuse_sn; + *size = FUSE_SN_SIZE; + return TEE_SUCCESS; +} + +static TEE_Result tegra_fuse_init(void) +{ + TEE_Result rc = TEE_SUCCESS; + tegra_drv_srv_intf_t *drv_srv_intf = NULL; + size_t map_size = 0; + uint32_t sn_size = FUSE_SN_SIZE; + + rc = tegra_fuse_map_regs(&fuse_va_base, &map_size); + if (rc == TEE_SUCCESS) { + rc = fuse_generate_ecid(fuse_va_base, &fuse_ecid, &fuse_ecid_64bit); + if (rc != TEE_SUCCESS) { + EMSG("Tegra fuse: generate ECID failed: 0x%x\n", rc); + tegra_fuse_unmap_regs(fuse_va_base, map_size); + return rc; + } + + rc = fuse_generate_sn(fuse_va_base, fuse_sn, &sn_size); + if (rc != TEE_SUCCESS) { + EMSG("Tegra fuse: generate SN failed: 0x%x\n", rc); + tegra_fuse_unmap_regs(fuse_va_base, map_size); + return rc; + } + + drv_srv_intf = tegra_drv_srv_intf_get(); + if (drv_srv_intf != NULL) { + drv_srv_intf->get_ecid = fuse_get_ecid; + drv_srv_intf->get_64bit_ecid = fuse_get_64bit_ecid; + drv_srv_intf->get_bsi = fuse_get_bsi; + drv_srv_intf->get_sec_mode = fuse_get_sec_mode; + drv_srv_intf->get_sn = fuse_get_sn; + } else { + return TEE_ERROR_NOT_SUPPORTED; + } + } + + return rc; +} + +service_init(tegra_fuse_init); 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/crypto/tegra_driver_hash.c b/optee/optee_os/core/drivers/tegra/t234/crypto/tegra_driver_hash.c new file mode 100644 index 0000000..69cb580 --- /dev/null +++ b/optee/optee_os/core/drivers/tegra/t234/crypto/tegra_driver_hash.c @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static TEE_Result tegra_hash_initialize(struct crypto_hash_ctx *ctx) +{ + return tegra_ccc_hash_initialize(ctx); +} + +static TEE_Result tegra_hash_update( + struct crypto_hash_ctx *ctx, + const uint8_t *data, size_t len) +{ + return tegra_ccc_hash_update(ctx, data, len); +} + +static TEE_Result tegra_hash_final( + struct crypto_hash_ctx *ctx, + uint8_t *digest, size_t len) +{ + return tegra_ccc_hash_final(ctx, digest, len); +} + +static void tegra_hash_free(struct crypto_hash_ctx *ctx) +{ + tegra_ccc_hash_free(ctx); +} + +static void tegra_hash_copy_state( + struct crypto_hash_ctx *dst_ctx, + struct crypto_hash_ctx *src_ctx) +{ + tegra_ccc_hash_copy_state(dst_ctx, src_ctx); +} + +static const struct crypto_hash_ops hash_ops = { + .init = &tegra_hash_initialize, + .update = &tegra_hash_update, + .final = &tegra_hash_final, + .free_ctx = &tegra_hash_free, + .copy_state = &tegra_hash_copy_state, +}; + +static TEE_Result tegra_hash_allocate( + struct crypto_hash_ctx **ctx, + uint32_t algo) +{ + TEE_Result res = TEE_ERROR_NOT_IMPLEMENTED; + + switch (algo) + { + case TEE_ALG_SHA1: + res = tegra_hash_alloc_ctx(ctx, TEGRA_ALG_SHA1); + break; + + case TEE_ALG_SHA224: + res = tegra_hash_alloc_ctx(ctx, TEGRA_ALG_SHA224); + break; + + case TEE_ALG_SHA256: + res = tegra_hash_alloc_ctx(ctx, TEGRA_ALG_SHA256); + break; + + case TEE_ALG_SHA384: + res = tegra_hash_alloc_ctx(ctx, TEGRA_ALG_SHA384); + break; + + case TEE_ALG_SHA512: + res = tegra_hash_alloc_ctx(ctx, TEGRA_ALG_SHA512); + break; + + default: + return TEE_ERROR_NOT_IMPLEMENTED; + } + + (*ctx)->ops = &hash_ops; + return res; +} + +/* Register the Tegra SE hash processing driver in the crypto API. + * During OP-TEE initialization this sets up "*crypt_algo" for + * CRYPTO_HASH with Tegra SE. + */ +TEE_Result tegra_register_hash(void) +{ + return drvcrypt_register_hash(&tegra_hash_allocate); +} + +driver_init_late(tegra_register_hash); 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..7cdc74f --- /dev/null +++ b/optee/optee_os/core/drivers/tegra/t234/include/tegra_se_ccc.h @@ -0,0 +1,66 @@ +/* + * 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 +#if defined (CFG_CRYPTO_DRIVER_TEGRA_SE) +#include +#include +#endif + +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; + +#define TEGRA_INIT_CRYPTO_PROTO_DECLARED /* Prevent redundant declaration warning */ +status_t tegra_init_crypto_devices(void); + +/* tegra_se_ccc_crypto_wrapper functions */ +#if defined (CFG_CRYPTO_DRIVER_TEGRA_SE) +/* hash functions */ +#if defined (CFG_CRYPTO_DRV_HASH_TEGRA_SE) +TEE_Result tegra_register_hash(void); +TEE_Result tegra_hash_alloc_ctx( + struct crypto_hash_ctx **ctx, + tegra_crypto_algo_mode algo); +TEE_Result tegra_ccc_hash_initialize(struct crypto_hash_ctx *ctx); +TEE_Result tegra_ccc_hash_update(struct crypto_hash_ctx *ctx, + const uint8_t *data, size_t len); +TEE_Result tegra_ccc_hash_final(struct crypto_hash_ctx *ctx, + uint8_t *digest, size_t len); +void tegra_ccc_hash_free(struct crypto_hash_ctx *ctx); +void tegra_ccc_hash_copy_state(struct crypto_hash_ctx *dst_ctx, + struct crypto_hash_ctx *src_ctx); +#endif +#endif + +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..bd8bf00 --- /dev/null +++ b/optee/optee_os/core/drivers/tegra/t234/sub.mk @@ -0,0 +1,8 @@ +incdirs-y += include +incdirs-y += ../common/include + +srcs-$(CFG_CRYPTO_DRV_HASH_TEGRA_SE) += crypto/tegra_driver_hash.c +srcs-$(CFG_TEGRA_SE) += tegra_se_aes_rng.c +srcs-$(CFG_TEGRA_SE) += tegra_se_map_device.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..6e46749 --- /dev/null +++ b/optee/optee_os/core/drivers/tegra/t234/tegra_fuse.c @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022-2024, NVIDIA CORPORATION & AFFILIATES. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static vaddr_t fuse_va_base = 0; +static fuse_ecid_t fuse_ecid; +static uint64_t fuse_ecid_64bit = 0; +static uint8_t fuse_sn[FUSE_SN_SIZE]; + +static fuse_ecid_t* fuse_get_ecid(void) +{ + return &fuse_ecid; +} + +static TEE_Result fuse_get_64bit_ecid(uint64_t *val) +{ + if (val == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + if (fuse_ecid_64bit == 0) + return TEE_ERROR_NOT_SUPPORTED; + + *val = fuse_ecid_64bit; + return TEE_SUCCESS; +} + +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 TEE_Result fuse_get_sec_mode(uint32_t *val) +{ + if (val == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + *val = io_read32(fuse_va_base + FUSE_SECURITY_MODE_0); + return TEE_SUCCESS; +} + +static TEE_Result fuse_get_sn(uint8_t **sn, uint32_t *size) +{ + if (sn == NULL || size == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + *sn = fuse_sn; + *size = FUSE_SN_SIZE; + return TEE_SUCCESS; +} + +static TEE_Result tegra_fuse_init(void) +{ + TEE_Result rc = TEE_SUCCESS; + tegra_drv_srv_intf_t *drv_srv_intf = NULL; + size_t map_size = 0; + uint32_t sn_size = FUSE_SN_SIZE; + + rc = tegra_fuse_map_regs(&fuse_va_base, &map_size); + if (rc == TEE_SUCCESS) { + rc = fuse_generate_ecid(fuse_va_base, &fuse_ecid, &fuse_ecid_64bit); + if (rc != TEE_SUCCESS) { + EMSG("Tegra fuse: generate ECID failed: 0x%x\n", rc); + tegra_fuse_unmap_regs(fuse_va_base, map_size); + return rc; + } + + rc = fuse_generate_sn(fuse_va_base, fuse_sn, &sn_size); + if (rc != TEE_SUCCESS) { + EMSG("Tegra fuse: generate SN failed: 0x%x\n", rc); + tegra_fuse_unmap_regs(fuse_va_base, map_size); + return rc; + } + + drv_srv_intf = tegra_drv_srv_intf_get(); + if (drv_srv_intf != NULL) { + drv_srv_intf->get_ecid = fuse_get_ecid; + drv_srv_intf->get_64bit_ecid = fuse_get_64bit_ecid; + drv_srv_intf->get_bsi = fuse_get_bsi; + drv_srv_intf->get_sec_mode = fuse_get_sec_mode; + drv_srv_intf->get_sn = fuse_get_sn; + } 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..86d3a6b --- /dev/null +++ b/optee/optee_os/core/drivers/tegra/t234/tegra_se_aes_rng.c @@ -0,0 +1,265 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022-2024, 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 + +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/OEM_K2: 0000000000000000000000000000000000000000000000000000000000000000 */ + const uint8_t test_oem_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, + }; + + TEE_Result err = TEE_SUCCESS; + uint32_t bsi = 0; +#endif + +#ifndef TEGRA_SE_CRYPTO_INITIALIZED +#define TEGRA_SE_CRYPTO_INITIALIZED + /* This function will call tegra_se_map_device to map devices */ + ret = tegra_init_crypto_devices(); + if (ret != NO_ERROR) { + return TEE_ERROR_GENERIC; + } +#endif + +#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(test_oem_key, test_oem_key); + 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/t234/tegra_se_map_device.c b/optee/optee_os/core/drivers/tegra/t234/tegra_se_map_device.c new file mode 100644 index 0000000..32f3d79 --- /dev/null +++ b/optee/optee_os/core/drivers/tegra/t234/tegra_se_map_device.c @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(CFG_TEGRA_SE_RNG1) +#include +#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; +} 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..514ee40 --- /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 versal_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 versal_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 versal_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 */ + versal_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 versal_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 versal_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 versal_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 versal_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 versal_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..a9fbc1b --- /dev/null +++ b/optee/optee_os/core/drivers/wdt/watchdog_sm.c @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2022 Microchip + */ + +#include +#include +#include +#include +#include + +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/widevine_huk.c b/optee/optee_os/core/drivers/widevine_huk.c new file mode 100644 index 0000000..de26632 --- /dev/null +++ b/optee/optee_os/core/drivers/widevine_huk.c @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2023, The ChromiumOS Authors + */ + +#include +#include +#include +#include + +static uint8_t dt_huk[HW_UNIQUE_KEY_LENGTH]; +static bool dt_huk_initialized; + +static TEE_Result init_widevine_huk_dt_data(void) +{ + int node = 0; + int len = 0; + void *fdt = NULL; + const void *value = NULL; + + if (dt_huk_initialized) + return TEE_SUCCESS; + + fdt = get_secure_dt(); + if (!fdt) + return TEE_ERROR_NO_DATA; + + node = fdt_path_offset(fdt, "/options/op-tee/widevine"); + if (node < 0) + return TEE_ERROR_ITEM_NOT_FOUND; + + value = fdt_getprop(fdt, node, "op-tee,hardware-unique-key", &len); + if (!value) + return TEE_ERROR_ITEM_NOT_FOUND; + + if (len >= HW_UNIQUE_KEY_LENGTH) + len = HW_UNIQUE_KEY_LENGTH; + else + return TEE_ERROR_BAD_FORMAT; + + memcpy(dt_huk, value, len); + dt_huk_initialized = true; + + return TEE_SUCCESS; +} + +service_init(init_widevine_huk_dt_data); + +TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey) +{ + TEE_Result result = TEE_SUCCESS; + + /* + * Ensure we get data from the DT, in case called before service_init() + * handler. + */ + result = init_widevine_huk_dt_data(); + if (result != TEE_SUCCESS) + return result; + + memcpy(hwkey->data, dt_huk, HW_UNIQUE_KEY_LENGTH); + + return TEE_SUCCESS; +} 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..970acf5 --- /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"); + 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"); + return TEE_ERROR_GENERIC; + } + + EMSG("Startup tests yielded no response -> TRNG stuck"); + return TEE_ERROR_GENERIC; + } + + io_write32(xiphera_trng_base + CONTROL_REG, HOST_TO_TRNG_ACK_ZEROIZE); + + DMSG("TRNG initialized"); + + 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/console.h b/optee/optee_os/core/include/console.h new file mode 100644 index 0000000..c596283 --- /dev/null +++ b/optee/optee_os/core/include/console.h @@ -0,0 +1,57 @@ +/* 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); + +void plat_console_init(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..d0ee5f3 --- /dev/null +++ b/optee/optee_os/core/include/crypto/crypto.h @@ -0,0 +1,425 @@ +/* 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 montgomery_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 montgomery_keypair *s, + size_t key_size_bits); +TEE_Result crypto_acipher_alloc_x448_keypair(struct montgomery_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 montgomery_keypair *key, + size_t key_size); +TEE_Result crypto_acipher_gen_x448_key(struct montgomery_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 montgomery_keypair + *private_key, + void *public_key, void *secret, + unsigned long *secret_len); +TEE_Result crypto_acipher_x448_shared_secret(struct montgomery_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..e6dff64 --- /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_ecc_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..d8471e5 --- /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_CRYPTO_SE_H +#define __CRYPTO_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..4ac246b --- /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..e575afe --- /dev/null +++ b/optee/optee_os/core/include/drivers/amlogic_uart.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +#ifndef __DRIVERS_AMLOGIC_UART_H +#define __DRIVERS_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 /* __DRIVERS_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..9d4bfda --- /dev/null +++ b/optee/optee_os/core/include/drivers/atmel_rstc.h @@ -0,0 +1,27 @@ +/* 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); +void sam_rstc_usb_por(unsigned char id, bool enable); +#else +static inline bool atmel_rstc_available(void) +{ + return false; +} + +static inline void atmel_rstc_reset(void) {} +static inline void sam_rstc_usb_por(unsigned char id __unused, + bool enable __unused) {} +#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..c1b8b60 --- /dev/null +++ b/optee/optee_os/core/include/drivers/atmel_saic.h @@ -0,0 +1,46 @@ +/* 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 + +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..2639fce --- /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 __DRIVERS_ATMEL_UART_H +#define __DRIVERS_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 /* __DRIVERS_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..51aae18 --- /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 __DRIVERS_BCM_BNXT_H +#define __DRIVERS_BCM_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..7d5e408 --- /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 __DRIVERS_BCM_GPIO_H +#define __DRIVERS_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 /* __DRIVERS_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..b4d84f9 --- /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 __DRIVERS_BCM_HWRNG_H +#define __DRIVERS_BCM_HWRNG_H + +#include + +uint32_t bcm_hwrng_read_rng(uint32_t *p_out, uint32_t words_to_read); + +#endif /* __DRIVERS_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..aa13270 --- /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 __DRIVERS_BCM_SOTP_H +#define __DRIVERS_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..41ccec0 --- /dev/null +++ b/optee/optee_os/core/include/drivers/caam_extension.h @@ -0,0 +1,55 @@ +/* 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 */ + +#ifdef CFG_NXP_CAAM_DEK_DRV +/* + * Data encryption key generation using CAAM Secure Memory. + * + * @blob_data [in/out] Blob data + */ +TEE_Result caam_dek_generate(const uint8_t *payload, size_t payload_size, + uint8_t *dek, size_t dek_size); +#endif /* CFG_NXP_CAAM_DEK_DRV */ +#endif /* __DRIVERS_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..a8b695a --- /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..b5ee112 --- /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 __DRIVERS_CDNS_UART_H +#define __DRIVERS_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 /* __DRIVERS_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..71f5293 --- /dev/null +++ b/optee/optee_os/core/include/drivers/clk.h @@ -0,0 +1,261 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, Bootlin + */ + +#ifndef __DRIVERS_CLK_H +#define __DRIVERS_CLK_H + +#include +#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 */ +#define CLK_DUTY_CYCLE_PARENT BIT(2) /* forward duty cycle call to parent */ +#define CLK_SET_RATE_PARENT BIT(3) /* propagate rate change up to parent */ +#define CLK_SET_RATE_UNGATE BIT(4) /* clock needs to run to set rate */ +#define CLK_SET_PARENT_PRE_ENABLE BIT(5) /* enable new parent if needed */ + +/** + * 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 + * @link: Link the clock list + */ +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; +#ifdef CFG_DRIVERS_CLK_PRINT_TREE + SLIST_ENTRY(clk) link; +#endif + size_t num_parents; + struct clk *parents[]; +}; + +/** + * struct clk_duty_cycle - Encoding the duty cycle ratio of a clock + * + * @num: Numerator of the duty cycle ratio + * @den: Denominator of the duty cycle ratio + */ +struct clk_duty_cycle { + unsigned int num; + unsigned int den; +}; + +/** + * struct clk_ops - Clock operations + * + * @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 + * @get_rates_steps: Get support clock rates by min/max/step representation + * @get_duty_cycle: Get duty cytcle of the clock + * + * All clock operations are expected to execute in a interruptible thread + * context at the exclusion of power management sequence where non secure + * world is not operating (power off, suspend, resume). + */ +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); + TEE_Result (*get_rates_steps)(struct clk *clk, unsigned long *min, + unsigned long *max, unsigned long *step); + TEE_Result (*get_duty_cycle)(struct clk *clk, + struct clk_duty_cycle *duty_cycle); +}; + +/** + * clk_get_name() - 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; +} + +/** + * clk_get_parent_by_index() - 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); + +/** + * clk_get_rates_steps() - Get supported rates as min/max/step triplet + * + * @clk: Clock for which the rates are requested + * @min: Output min supported rate in Hz + * @max: Output max supported rate in Hz + * @step: Output rate step in Hz + * Returns a TEE_Result compliant value + */ +TEE_Result clk_get_rates_steps(struct clk *clk, unsigned long *min, + unsigned long *max, unsigned long *step); + +/** + * clk_get_duty_cycle() - Get clock duty cycle + * + * @clk: Clock for which the duty cycle is requested + * @duty: Output duty cycle info + * Return a TEE_Result compliant value + */ +TEE_Result clk_get_duty_cycle(struct clk *clk, + struct clk_duty_cycle *duty_cycle); + +#ifdef CFG_DRIVERS_CLK +/** + * clk_print_tree() - Print current clock tree summary to output console + * + * The clock is printed with the debug trace level. + */ +void clk_print_tree(void); +#else +static inline void clk_print_tree(void) +{ +} +#endif /* CFG_DRIVERS_CLK */ +#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..ba55d5e --- /dev/null +++ b/optee/optee_os/core/include/drivers/clk_dt.h @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, Bootlin + */ + +#ifndef __DRIVERS_CLK_DT_H +#define __DRIVERS_CLK_DT_H + +#include +#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 + * @clk: Output clock reference upon success + */ +typedef TEE_Result (*clk_dt_get_func)(struct dt_pargs *args, void *data, + struct clk **out_clk); + +/** + * clk_dt_register_clk_provider() - Register a clock provider + * + * @fdt: Device tree to work on + * @nodeoffset: Node offset of the clock + * @func: 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 func, + void *data) +{ + return dt_driver_register_provider(fdt, nodeoffset, + (get_of_device_func)func, data, + DT_DRIVER_CLK); +} + +/** + * clk_dt_get_simple_clk() - Simple clock matching function for single clock + * providers + * + * @args: Unused argument as there is no description to parse + * @data: Pointer to data given at clk_dt_register_clk_provider() call + * @out_clk: Output clock reference filled with @data + */ +static inline TEE_Result clk_dt_get_simple_clk(struct dt_pargs *args __unused, + void *data, struct clk **out_clk) +{ + *out_clk = data; + + return TEE_SUCCESS; +} + +#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..498e3c8 --- /dev/null +++ b/optee/optee_os/core/include/drivers/gic.h @@ -0,0 +1,59 @@ +/* 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) + +/* + * Default lowest ID for secure SGIs, note that this does not account for + * interrupts donated to non-secure world with gic_init_donate_sgi_to_ns(). + */ +#define GIC_SGI_SEC_BASE 8 +/* Max ID for secure SGIs */ +#define GIC_SGI_SEC_MAX 15 + +/* + * The two gic_init() and gic_init_v3() functions initializes the struct + * gic_data which is then used by the other functions. These two functions + * also initializes the GIC and are only supposed to be called from the + * primary boot CPU. + */ +void gic_init_v3(paddr_t gicc_base_pa, paddr_t gicd_base_pa, + paddr_t gicr_base_pa); +static inline void gic_init(paddr_t gicc_base_pa, paddr_t gicd_base_pa) +{ + gic_init_v3(gicc_base_pa, gicd_base_pa, 0); +} + +/* Donates one of the secure SGIs to normal world */ +void gic_init_donate_sgi_to_ns(size_t it); + +/* + * Does per-CPU specific GIC initialization, should be called by all + * secondary CPUs when booting. + */ +void gic_init_per_cpu(void); + +/* Print GIC state to console */ +void gic_dump_state(void); +#endif /*__DRIVERS_GIC_H*/ diff --git a/optee/optee_os/core/include/drivers/gpio.h b/optee/optee_os/core/include/drivers/gpio.h new file mode 100644 index 0000000..b6406d4 --- /dev/null +++ b/optee/optee_os/core/include/drivers/gpio.h @@ -0,0 +1,222 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Linaro Limited + */ + +#ifndef __DRIVERS_GPIO_H +#define __DRIVERS_GPIO_H + +#include +#include +#include +#include +#include + +/** + * GPIO_DT_DECLARE - Declare a GPIO controller driver with a single + * device tree compatible string. + * + * @__name: GPIO controller driver name + * @__compat: Compatible string + * @__probe: GPIO controller probe function + */ +#define GPIO_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_GPIO, \ + .match_table = __name ## _match_table, \ + .probe = __probe, \ + } + +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; +struct gpio_ops; + +struct gpio_chip { + const struct gpio_ops *ops; +}; + +struct gpio_ops { + /* Get GPIO direction current configuration */ + enum gpio_dir (*get_direction)(struct gpio_chip *chip, + unsigned int gpio_pin); + /* Set GPIO direction configuration */ + void (*set_direction)(struct gpio_chip *chip, unsigned int gpio_pin, + enum gpio_dir direction); + /* Get GPIO current level */ + enum gpio_level (*get_value)(struct gpio_chip *chip, + unsigned int gpio_pin); + /* Set GPIO level */ + void (*set_value)(struct gpio_chip *chip, unsigned int gpio_pin, + enum gpio_level value); + /* Get GPIO interrupt state */ + enum gpio_interrupt (*get_interrupt)(struct gpio_chip *chip, + unsigned int gpio_pin); + /* Enable or disable a GPIO interrupt */ + void (*set_interrupt)(struct gpio_chip *chip, unsigned int gpio_pin, + enum gpio_interrupt enable_disable); + /* Release GPIO resources */ + void (*put)(struct gpio_chip *chip, struct gpio *gpio); +}; + +/* + * struct gpio - GPIO pin description + * @chip: GPIO controller chip reference + * @dt_flags: Pin boolean properties set from DT node + * @pin: Pin number in GPIO controller + */ +struct gpio { + struct gpio_chip *chip; + uint32_t dt_flags; + unsigned int pin; +}; + +static inline bool gpio_ops_is_valid(const struct gpio_ops *ops) +{ + return ops->set_direction && ops->get_direction && ops->get_value && + ops->set_value; +} + +static inline void gpio_set_direction(struct gpio *gpio, enum gpio_dir dir) +{ + gpio->chip->ops->set_direction(gpio->chip, gpio->pin, dir); +} + +static inline enum gpio_dir gpio_get_direction(struct gpio *gpio) +{ + return gpio->chip->ops->get_direction(gpio->chip, gpio->pin); +} + +static inline void gpio_set_value(struct gpio *gpio, enum gpio_level value) +{ + if (gpio->dt_flags & GPIO_ACTIVE_LOW) + value = !value; + + gpio->chip->ops->set_value(gpio->chip, gpio->pin, value); +} + +static inline enum gpio_level gpio_get_value(struct gpio *gpio) +{ + enum gpio_level value = GPIO_LEVEL_LOW; + + value = gpio->chip->ops->get_value(gpio->chip, gpio->pin); + + if (gpio->dt_flags & GPIO_ACTIVE_LOW) + value = !value; + + return value; +} + +static inline void gpio_put(struct gpio *gpio) +{ + assert(!gpio || (gpio->chip && gpio->chip->ops)); + + if (gpio && gpio->chip->ops->put) + gpio->chip->ops->put(gpio->chip, gpio); +} + +#if defined(CFG_DT) && defined(CFG_DRIVERS_GPIO) +/** + * gpio_dt_alloc_pin() - Get an allocated GPIO instance from its DT phandle + * + * @pargs: Pointer to devicetree description of the GPIO controller to parse + * @res: Output result code of the operation: + * TEE_SUCCESS in case of success + * TEE_ERROR_DEFER_DRIVER_INIT if GPIO controller is not initialized + * Any TEE_Result compliant code in case of error. + * + * Returns a struct gpio pointer pointing to a GPIO instance matching + * the devicetree description or NULL if invalid description in which case + * @res provides the error code. + */ +TEE_Result gpio_dt_alloc_pin(struct dt_pargs *pargs, struct gpio **gpio); + +/** + * gpio_dt_get_by_index() - Get a GPIO controller at a specific index in + * 'gpios' property + * + * @fdt: Device tree to work on + * @nodeoffset: Node offset of the subnode containing a 'gpios' property + * @index: GPIO pin index in '*-gpios' property + * @gpio_name: Name of the GPIO pin + * @gpio: Output GPIO pin reference upon success + * + * Return TEE_SUCCESS in case of success + * Return TEE_ERROR_DEFER_DRIVER_INIT if GPIO controller is not initialized + * Return a TEE_Result compliant code in case of error + */ +TEE_Result gpio_dt_get_by_index(const void *fdt, int nodeoffset, + unsigned int index, const char *gpio_name, + struct gpio **gpio); +#else +static inline TEE_Result gpio_dt_get_by_index(const void *fdt __unused, + int nodeoffset __unused, + unsigned int index __unused, + const char *gpio_name __unused, + struct gpio **gpio __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +static inline TEE_Result gpio_dt_alloc_pin(struct dt_pargs *pargs __unused, + struct gpio **gpio __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} +#endif /*CFG_DT*/ + +/** + * gpio_dt_get_func - Typedef of function to get GPIO instance from + * devicetree properties + * + * @pargs: Pointer to GPIO phandle and its argument in the FDT + * @data: Pointer to the data given at gpio_dt_register_provider() call + * @res: Output result code of the operation: + * TEE_SUCCESS in case of success + * TEE_ERROR_DEFER_DRIVER_INIT if GPIO controller is not initialized + * Any TEE_Result compliant code in case of error. + * + * Returns a struct GPIO pointer pointing to a GPIO instance matching + * the devicetree description or NULL if invalid description in which case + * @res provides the error code. + */ +typedef TEE_Result (*gpio_dt_get_func)(struct dt_pargs *pargs, void *data, + struct gpio **out_gpio); + +/** + * gpio_dt_register_provider() - Register a GPIO controller provider + * + * @fdt: Device tree to work on + * @nodeoffset: Node offset of the GPIO controller + * @get_dt_gpio: Callback to match the GPIO controller with a struct gpio + * @data: Opaque reference which will be passed to the get_dt_gpio callback + * Returns TEE_Result value + */ +static inline TEE_Result gpio_register_provider(const void *fdt, int nodeoffset, + gpio_dt_get_func get_dt_gpio, + void *data) +{ + return dt_driver_register_provider(fdt, nodeoffset, + (get_of_device_func)get_dt_gpio, + data, DT_DRIVER_GPIO); +} + +#endif /* __DRIVERS_GPIO_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..0c03c84 --- /dev/null +++ b/optee/optee_os/core/include/drivers/hfic.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2022, Linaro Limited + */ + +#ifndef __DRIVERS_HFIC_H +#define __DRIVERS_HFIC_H + +void hfic_init(void); + +#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..9fb11a4 --- /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 __DRIVERS_HI16XX_UART_H +#define __DRIVERS_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 /* __DRIVERS_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..287689c --- /dev/null +++ b/optee/optee_os/core/include/drivers/i2c.h @@ -0,0 +1,344 @@ +/* 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 **out_i2c_dev) +{ + TEE_Result res = TEE_ERROR_GENERIC; + void *i2c_dev = NULL; + + res = dt_driver_device_from_parent(fdt, nodeoffset, DT_DRIVER_I2C, + &i2c_dev); + if (!res) + *out_i2c_dev = i2c_dev; + + 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 __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} +#endif + +/** + * i2c_dt_get_func - Typedef of function to get I2C bus device from + * devicetree properties + * + * @args: Pointer to devicetree description of the I2C bus device to parse + * @data: Pointer to data given at i2c_dt_register_provider() call + * @out_device: Output pointer to I2C device upon success + */ +typedef TEE_Result (*i2c_dt_get_func)(struct dt_pargs *args, void *data, + struct i2c_dev **out_device); + +/** + * 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..28ff080 --- /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 __DRIVERS_IMX_DCP_H +#define __DRIVERS_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 /* __DRIVERS_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..d100135 --- /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 __DRIVERS_IMX_OCOTP_H +#define __DRIVERS_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 /* __DRIVERS_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..74f9750 --- /dev/null +++ b/optee/optee_os/core/include/drivers/imx_snvs.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2020 Pengutronix + * Rouven Czerwinski + * Copyright 2022-2023 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); +void imx_snvs_shutdown(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; +} + +static inline void imx_snvs_shutdown(void) {} +#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..a62bd17 --- /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 __DRIVERS_IMX_UART_H +#define __DRIVERS_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 /* __DRIVERS_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..7df879a --- /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 __DRIVERS_IMX_WDOG_H +#define __DRIVERS_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..e219a90 --- /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 __DRIVERS_LPC_UART_H +#define __DRIVERS_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 /* __DRIVERS_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..0c83f2b --- /dev/null +++ b/optee/optee_os/core/include/drivers/ls_dspi.h @@ -0,0 +1,74 @@ +/* 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] */ + +/* 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 */ + +/* + * 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); + +#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..594fb35 --- /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..a393428 --- /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 __DRIVERS_MVEBU_UART_H +#define __DRIVERS_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 /* __DRIVERS_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..60d3671 --- /dev/null +++ b/optee/optee_os/core/include/drivers/ns16550.h @@ -0,0 +1,67 @@ +/* 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 __DRIVERS_NS16550_H +#define __DRIVERS_NS16550_H + +#include +#include +#include + +#define NS16550_UART_REG_SIZE 0x1000 + +#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 /* __DRIVERS_NS16550_H */ diff --git a/optee/optee_os/core/include/drivers/nvmem.h b/optee/optee_os/core/include/drivers/nvmem.h new file mode 100644 index 0000000..5db573d --- /dev/null +++ b/optee/optee_os/core/include/drivers/nvmem.h @@ -0,0 +1,193 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2023, Microchip + */ + +#ifndef __DRIVERS_NVMEM_H +#define __DRIVERS_NVMEM_H + +#include +#include +#include +#include + +struct nvmem_cell; + +/* + * struct nvmem_ops - NVMEM device driver operations + * @read_cell: Allocate @data in the heap and load @len bytes to from an + * NVMEM cell + * @put_cell: Release resources allocated from nvmem_dt_get_func callback + * function + */ +struct nvmem_ops { + /* + * Read data from an NVMEM cell. + * @cell: Cell to read data from + * @data: Output buffer of size greater or equal to @cell->size + */ + TEE_Result (*read_cell)(struct nvmem_cell *cell, uint8_t *data); + void (*put_cell)(struct nvmem_cell *cell); +}; + +/* + * struct nvmem_cell - Description of an NVMEM cell + * @offset: Cell byte offset in the NVMEM device + * @len: Cell byte size + * @ops: NVMEM device driver operation handlers + * @drv_data: NVMEM device driver private data + */ +struct nvmem_cell { + paddr_t offset; + size_t len; + const struct nvmem_ops *ops; + void *drv_data; +}; + +/* + * nvmem_dt_get_func - Typedef of handlers to get an NVMEM cell from a npode + * @args: Reference to phandle arguments + * @data: Pointer to data given at nvmem_dt_get_func() call + * @cell: Output reference to cell instance upon success + * + * Return TEE_SUCCESS in case of success. + * Return TEE_ERROR_DEFER_DRIVER_INIT if NVMEM driver is not initialized + * Return another TEE_Result compliant code otherwise. + */ +typedef TEE_Result (*nvmem_dt_get_func)(struct dt_pargs *args, + void *data, struct nvmem_cell **cell); + +#ifdef CFG_DRIVERS_NVMEM +/** + * nvmem_register_provider() - Register a NVMEM controller + * + * @fdt: Device tree to work on + * @nodeoffset: Node offset of NVMEM cell consumer + * @get_dt_nvmem: Callback to match the devicetree NVMEM reference with + * nvmem_cell + * @data: Data which will be passed to the get_dt_nvmem callback + * Return a TEE_Result compliant value + */ +static inline TEE_Result nvmem_register_provider(const void *fdt, + int nodeoffset, + nvmem_dt_get_func get_dt_nvmem, + void *data) +{ + return dt_driver_register_provider(fdt, nodeoffset, + (get_of_device_func)get_dt_nvmem, + data, DT_DRIVER_NVMEM); +} + +/** + * nvmem_get_cell_by_name() - Obtain a NVMEM cell from its name in the DT node + * + * @fdt: Device tree to work on + * @nodeoffset: Node offset of NVMEM cell consumer + * @name: name of the NVMEM cell defined by property nvmem-cell-names to obtain + * from the device tree + * @cell: Pointer filled with the retrieved cell, must be freed after use + using nvmem_put_cell() + * Return a TEE_Result compliant value + */ +TEE_Result nvmem_get_cell_by_name(const void *fdt, int nodeoffset, + const char *name, struct nvmem_cell **cell); + +/** + * nvmem_get_cell_by_index() - Obtain a NVMEM cell from property nvmem-cells + * + * @fdt: Device tree to work on + * @nodeoffset: Node offset of NVMEM cell consumer + * @index: Index of the NVMEM cell to obtain from device-tree + * @out_cell: Pointer filled with the retrieved cell, must be freed after use + * using nvmem_put_cell() + * Return a TEE_Result compliant value + */ +TEE_Result nvmem_get_cell_by_index(const void *fdt, + int nodeoffset, + unsigned int index, + struct nvmem_cell **out_cell); + +/** + * nvmem_cell_parse_dt() - Parse device-tree information to fill a NVMEM cell + * + * @fdt: Device tree to work on + * @nodeoffset: Node offset of the NVMEM cell controller + * @cell: Pointer to cell that will be filled + */ +TEE_Result nvmem_cell_parse_dt(const void *fdt, int nodeoffset, + struct nvmem_cell *cell); + +/** + * nvmem_put_cell() - Free resource allocated from nvmem_get_cell_by_*() + * + * @cell: Cell to be freed + */ +static inline void nvmem_put_cell(struct nvmem_cell *cell) +{ + if (cell->ops->put_cell) + cell->ops->put_cell(cell); +} + +/* + * nvmem_cell_read() - Read data from a NVMEM cell + * @cell: Cell to read from NVMEM + * @data: Output data read from the cell upon success, byte size >= @cell->size + */ +static inline TEE_Result nvmem_cell_read(struct nvmem_cell *cell, + uint8_t *data) +{ + if (!cell->ops->read_cell) + return TEE_ERROR_NOT_SUPPORTED; + + return cell->ops->read_cell(cell, data); +} + +/* + * nvmem_cell_malloc_and_read() - Allocate and read data from a NVMEM cell + * @cell: Cell to read from NVMEM + * @data: Output allocated buffer where NVMEM cell data are stored upon success + * + * Upon success, the output buffer is allocated with malloc(). Caller is + * responsible for freeing the buffer with free() if needed. + */ +TEE_Result nvmem_cell_malloc_and_read(struct nvmem_cell *cell, + uint8_t **out_data); + +#else /* CFG_DRIVERS_NVMEM */ +static inline TEE_Result nvmem_register_provider(const void *fdt __unused, + int nodeoffset __unused, + nvmem_dt_get_func fn __unused, + void *data __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +static inline TEE_Result nvmem_get_cell_by_name(const void *fdt __unused, + int nodeoffset __unused, + const char *name __unused, + struct nvmem_cell **c __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +static inline +TEE_Result nvmem_get_cell_by_index(const void *fdt __unused, + int nodeoffset __unused, + unsigned int index __unused, + struct nvmem_cell **cell __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +static inline TEE_Result nvmem_cell_parse_dt(const void *fdt __unused, + int nodeoffset __unused, + struct nvmem_cell *cell __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +static inline void nvmem_put_cell(struct nvmem_cell *cell __unused) +{ +} +#endif /* CFG_DRIVERS_NVMEM */ +#endif /* __DRIVERS_NVMEM_H */ diff --git a/optee/optee_os/core/include/drivers/pinctrl.h b/optee/optee_os/core/include/drivers/pinctrl.h new file mode 100644 index 0000000..bdf7166 --- /dev/null +++ b/optee/optee_os/core/include/drivers/pinctrl.h @@ -0,0 +1,176 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2022-2023, Microchip + */ + +#ifndef __DRIVERS_PINCTRL_H +#define __DRIVERS_PINCTRL_H + +#include +#include +#include +#include + +enum pinctrl_dt_prop { + /* Property "bias-disable" found in pinctrl node */ + PINCTRL_DT_PROP_BIAS_DISABLE, + /* Property "bias-pull-up" found in pinctrl node */ + PINCTRL_DT_PROP_BIAS_PULL_UP, + /* Property "bias-pull-down" found in pinctrl node */ + PINCTRL_DT_PROP_BIAS_PULL_DOWN, + /* Terminal ID */ + PINCTRL_DT_PROP_MAX +}; + +/* + * struct pinconf - Pinctrl device + * @ops: Operation handlers + * @priv: Pinctrl driver private data + */ +struct pinconf { + const struct pinctrl_ops *ops; + void *priv; +}; + +/* + * struct pinctrl_state - Pinctrl configuration state + * @conf_count: Number of cells in @confs + * @confs: Array of pin configurations related to the pinctrl config state + */ +struct pinctrl_state { + unsigned int conf_count; + struct pinconf *confs[]; +}; + +struct pinctrl_ops { + /* Apply a pinctrl configuration */ + TEE_Result (*conf_apply)(struct pinconf *conf); + /* Release resources allocated for a pinctrl configuration */ + void (*conf_free)(struct pinconf *conf); +}; + +/** + * pinctrl_dt_get_func - Typedef of function to get a pin configuration from + * a device tree property + * + * @args: Pointer to device tree phandle arguments of the pin control reference + * @data: Pointer to data given at pinctrl_register_provider() call + * @out_pinconf: Output pin configuration reference upon success + */ +typedef TEE_Result (*pinctrl_dt_get_func)(struct dt_pargs *pargs, void *data, + struct pinconf **out_pinconf); + +#ifdef CFG_DRIVERS_PINCTRL +/** + * pinctrl_dt_register_provider - Register a pinctrl controller provider + * + * @fdt: Device tree to work on + * @nodeoffset: Node offset of the pin controller + * @get_pinctrl: Callback to match the pin controller with a struct pinconf + * @data: Data which will be passed to the get_pinctrl callback + * Return a TEE_Result compliant value + */ +static inline TEE_Result pinctrl_register_provider(const void *fdt, + int nodeoffset, + pinctrl_dt_get_func func, + void *data) +{ + return dt_driver_register_provider(fdt, nodeoffset, + (get_of_device_func)func, data, + DT_DRIVER_PINCTRL); +} + +/** + * pinctrl_get_state_by_name - Obtain a pinctrl state by name + * + * @fdt: Device tree to work on + * @nodeoffset: Node offset of the pin controller + * @name: name of the pinctrl state to obtain from device-tree + * @state: Pointer filled with the retrieved state, must be freed after use + using pinctrl_free_state() + * Return a TEE_Result compliant value + */ +TEE_Result pinctrl_get_state_by_name(const void *fdt, int nodeoffset, + const char *name, + struct pinctrl_state **state); + +/** + * pinctrl_get_state_by_idx - Obtain a pinctrl state by index + * + * @fdt: Device tree to work on + * @nodeoffset: Node offset of the pin controller + * @pinctrl_id: Index of the pinctrl state to obtain from device-tree + * @state: Pointer filled with the retrieved state, must be freed after use + using pinctrl_free_state() + * Return a TEE_Result compliant value + */ +TEE_Result pinctrl_get_state_by_idx(const void *fdt, int nodeoffset, + unsigned int pinctrl_id, + struct pinctrl_state **state); + +/** + * pinctrl_free_state - Free a pinctrl state that was previously obtained + * + * @state: State to be freed + */ +void pinctrl_free_state(struct pinctrl_state *state); + +/** + * pinctrl_apply_state - apply a pinctrl state + * + * @state: State to be applied + * Return a TEE_Result compliant value + */ +TEE_Result pinctrl_apply_state(struct pinctrl_state *state); + +/* + * pinctrl_parse_dt_pin_modes - Parse DT node properties + * @fdt: Device tree to work on + * @nodeoffset: Pinctrl node + * @modes: Output allocated regulator properties + * Return a TEE_Result compliant value + */ +TEE_Result pinctrl_parse_dt_pin_modes(const void *fdt, int nodeoffset, + bitstr_t **modes); +#else /* CFG_DRIVERS_PINCTRL */ +static inline TEE_Result +pinctrl_register_provider(const void *fdt __unused, int nodeoffset __unused, + get_of_device_func func __unused, void *data __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +static inline TEE_Result +pinctrl_get_state_by_name(const void *fdt __unused, int nodeoffset __unused, + const char *name __unused, + struct pinctrl_state **state __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +static inline TEE_Result +pinctrl_get_state_by_idx(const void *fdt __unused, int nodeoffset __unused, + unsigned int pinctrl_id __unused, + struct pinctrl_state **state __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +static inline void pinctrl_free_state(struct pinctrl_state *state __unused) +{ +} + +static inline TEE_Result pinctrl_apply_state(struct pinctrl_state *s __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +static inline TEE_Result pinctrl_parse_dt_pin_modes(const void *fdt __unused, + int nodeoffset __unused, + bitstr_t **modes __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +#endif /* CFG_DRIVERS_PINCTRL */ +#endif /* __DRIVERS_PINCTRL_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..59475c1 --- /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 __DRIVERS_PL011_H +#define __DRIVERS_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 /* __DRIVERS_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..0ccef78 --- /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 __DRIVERS_PL022_SPI_H +#define __DRIVERS_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 /* __DRIVERS_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..d6a36c4 --- /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 __DRIVERS_PL061_GPIO_H +#define __DRIVERS_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 /* __DRIVERS_PL061_GPIO_H */ diff --git a/optee/optee_os/core/include/drivers/plic.h b/optee/optee_os/core/include/drivers/plic.h new file mode 100644 index 0000000..f1f2604 --- /dev/null +++ b/optee/optee_os/core/include/drivers/plic.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2022-2023 NXP + */ + +#ifndef __DRIVERS_PLIC_H +#define __DRIVERS_PLIC_H + +#include +#include +#include + +void plic_init(paddr_t plic_base_pa); +void plic_hart_init(void); +void plic_it_handle(void); +void plic_dump_state(void); + +#endif /*__DRIVERS_PLIC_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/regulator.h b/optee/optee_os/core/include/drivers/regulator.h new file mode 100644 index 0000000..3cf7362 --- /dev/null +++ b/optee/optee_os/core/include/drivers/regulator.h @@ -0,0 +1,329 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2023, STMicroelectronics + */ +#ifndef __DRIVERS_REGULATOR_H +#define __DRIVERS_REGULATOR_H + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Regulator property flags: related to device tree binding properties */ + +/* Regulator should never be disabled. DT property: regulator-always-on */ +#define REGULATOR_ALWAYS_ON BIT(0) +/* Enables pull down mode. DT property: regulator-pull-down */ +#define REGULATOR_PULL_DOWN BIT(1) +/* + * It's expected that this regulator was left on by the bootloader. + * The core shouldn't prevent it from being turned off later. + * DT property: regulator-boot-on + */ +#define REGULATOR_BOOT_ON BIT(2) + +#define REGULATOR_FLAGS_MASK (REGULATOR_ALWAYS_ON | REGULATOR_PULL_DOWN | \ + REGULATOR_BOOT_ON) + +struct regulator_ops; + +/* + * struct regu_dt_desc - Regulator description passed to regulator_dt_register() + * @priv: Regulator driver private data + * @name: Regulator string name for debug purpose + * @supply_name: Regulator supply name for node property *-supply or NULL + * @ops: Operation handlers for the regulator + * @regulator: Pointer to preallocated regulator or NULL if none + */ +struct regu_dt_desc { + void *priv; + const char *name; + const char *supply_name; + const struct regulator_ops *ops; + struct regulator *regulator; +}; + +/* + * Defines the format of struct voltages::entries + * + * If regulator_voltages::type is VOLTAGE_TYPE_FULL_LIST, then + * regulator_voltages@entries stores regulator_voltages::num_levels cells, + * listing supported voltage levels in uV from lowest to highest value. + * + * If regulator_voltages::type is VOLTAGE_TYPE_INCREMENT, then + * regulator_voltages::entries stores 3 cells: min level, max level and + * level increment step, all in uV. When so, regulator_voltages::num_levels + * is meaningless. + */ +enum voltage_type { + VOLTAGE_TYPE_INVALID = 0, + VOLTAGE_TYPE_FULL_LIST, /* extensive list in uV */ + VOLTAGE_TYPE_INCREMENT /* min, max, increment (in uV) */ +}; + +/* + * struct regulator_voltages_desc - Voltage levels description + * @type: Type of level description + * @num_levels: Number of voltage levels when @type is VOLTAGE_TYPE_FULL_LIST + * + */ +struct regulator_voltages_desc { + enum voltage_type type; + size_t num_levels; +}; + +/* + * struct regulator - A regulator instance + * @ops: Operation handlers for the regulator + * @supply: Regulator supply reference or NULL if none + * @priv: Regulator driver private data + * @name: Regulator string name for debug purpose or NULL + * @min_uv: Min possible voltage level in microvolt (uV) + * @max_uv: Max possible voltage level in microvolt (uV) + * @flags: REGULATOR_* property flags + * @refcount: Regulator enable request reference counter + * @mutex: Concurrent access protection considering PM context sequences + * @voltages_fallback: Default supported voltage range description + * @link: Link in initialized regulator list + */ +struct regulator { + /* Fields initialized by caller of regulator_register() */ + const struct regulator_ops *ops; + struct regulator *supply; + void *priv; + char *name; + int min_uv; + int max_uv; + /* Fields internal to regulator framework */ + unsigned int flags; + unsigned int refcount; + struct mutex_pm_aware mutex; + struct voltages_fallback { + struct regulator_voltages_desc desc; + int levels[3]; + } voltages_fallback; + size_t levels_count_fallback; + SLIST_ENTRY(regulator) link; +}; + +/* + * struct regulator_ops - Regulator operation handlers + * + * @set_state: Enable or disable a regulator + * @get_state: Get regulator effective state + * @set_voltage: Set voltage level in microvolt (uV) + * @get_voltage: Get current voltage in microvolt (uV) + * @supported_voltages: Get supported levels description + * @supplied_init: Optional, finalize initialization once supply is ready + */ +struct regulator_ops { + TEE_Result (*set_state)(struct regulator *r, bool enabled); + TEE_Result (*get_state)(struct regulator *r, bool *enabled); + TEE_Result (*set_voltage)(struct regulator *r, int level_uv); + TEE_Result (*get_voltage)(struct regulator *r, int *level_uv); + TEE_Result (*supported_voltages)(struct regulator *r, + struct regulator_voltages_desc **desc, + const int **levels); + TEE_Result (*supplied_init)(struct regulator *r, const void *fdt, + int node); +}; + +#ifdef CFG_DRIVERS_REGULATOR +/* + * regulator_enable() - Enable regulator + * @regulator: Regulator reference + */ +TEE_Result regulator_enable(struct regulator *regulator); + +/* + * regulator_disable() - Disable regulator + * @regulator: Regulator reference + */ +TEE_Result regulator_disable(struct regulator *regulator); + +/* + * regulator_is_enabled() - Return whether or not regulator is currently enabled + * despite its refcount value. + * @regulator: Regulator reference + */ +bool regulator_is_enabled(struct regulator *regulator); + +/* + * regulator_set_voltage() - Set regulator to target level in microvolt + * @regulator: Regulator reference + * @level_uv: Level in microvolt + */ +TEE_Result regulator_set_voltage(struct regulator *regulator, int level_uv); + +/* + * regulator_register() - Register and initialize a regulator + * @regulator: Regulator reference + */ +TEE_Result regulator_register(struct regulator *regulator); + +/* Print registered regulators and their state to the output console */ +void regulator_print_state(const char *message); +#else +static inline TEE_Result regulator_enable(struct regulator *regulator __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +static inline TEE_Result regulator_disable(struct regulator *regulator __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +static inline bool regulator_is_enabled(struct regulator *regulator __unused) +{ + return false; +} + +static inline TEE_Result regulator_set_voltage(struct regulator *regul __unused, + int level_mv __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +static inline TEE_Result regulator_init(struct regulator *regulator __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +static inline void regulator_print_state(const char *message __unused) +{ +} +#endif /*CFG_DRIVERS_REGULATOR*/ + +#if defined(CFG_DRIVERS_REGULATOR) && defined(CFG_DT) +/* + * regulator_dt_get_supply() - Get a regulator supply from name and DT node + * @fdt: FDT to work on + * @node: DT node of the regulator consumer + * @supply_name: Name of the supply in DT property xxx-supply + * @regulator: Output regulator upon success + * + * Upon success, this function provides the pointer to regulator + * defined by DT binding property @name-supply phandle reference. + * + * This function returns TEE_ERROR_DEFER_DRIVER_INIT if supply exists but is + * not yet initialized. + */ +TEE_Result regulator_dt_get_supply(const void *fdt, int node, + const char *supply_name, + struct regulator **regulator); + +/* + * regulator_dt_register() - Register a regulator to related to a DT node + * @fdt: FDT to work on + * @node: DT node of the regulator exposed by regulator driver + * @provider_node: Node where xxx-supply property is found or -1 if no supply. + * @desc: Description of the regulator to register + * + * This function registers and initializes a regulator instance once its supply + * if found, if any. Regulators registered with this function can be found by + * their consumer drivers using API function regulator_dt_get_supply() or like. + * + * Return TEE_SUCCESS in case of success + * Return TEE_ERROR_OUT_OF_MEMORY if failed on memory allocation + * Return any other TEE_Result compliant code in case of error + */ +TEE_Result regulator_dt_register(const void *fdt, int node, int provider_node, + const struct regu_dt_desc *desc); +#else +static inline TEE_Result regulator_dt_get_supply(const void *fdt __unused, + int node __unused, + const char *supply __unused, + struct regulator **r __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +static inline TEE_Result +regulator_dt_register(const void *fdt __unused, int node __unused, + int provider_node __unused, + const struct regu_dt_desc *d __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} +#endif /* CFG_DRIVERS_REGULATOR && CFG_DT */ + +/* + * regulator_name() - Return regulator name or NULL + * @regulator: Regulator reference + */ +static inline const char *regulator_name(struct regulator *regulator) +{ + return regulator->name; +} + +/* + * regulator_is_always_on() - Return the state of REGULATOR_ALWAYS_ON flag + * @regulator: Regulator reference + */ +static inline bool regulator_is_always_on(struct regulator *regulator) +{ + return regulator->flags & REGULATOR_ALWAYS_ON; +} + +/* + * regulator_set_min_voltage() - Set regulator to its min level + * @regulator: Regulator reference + */ +static inline TEE_Result regulator_set_min_voltage(struct regulator *regulator) +{ + return regulator_set_voltage(regulator, regulator->min_uv); +} + +/* + * regulator_get_voltage() - Get regulator effective voltage level in microvolt + * @regulator: Regulator reference + */ +int regulator_get_voltage(struct regulator *regulator); + +/* + * regulator_get_range() - Get regulator min and/or max support levels + * @regulator: Regulator reference + * @min_mv: Output reference to min level in microvolt (uV) or NULL + * @max_mv: Output reference to max level in microvolt (uV) or NULL + */ +static inline void regulator_get_range(struct regulator *regulator, int *min_uv, + int *max_uv) +{ + assert(regulator); + if (min_uv) + *min_uv = regulator->min_uv; + if (max_uv) + *max_uv = regulator->max_uv; +} + +/* + * regulator_supported_voltages() - Get regulator supported levels in microvolt + * @regulator: Regulator reference + * @desc: Output reference to supported voltage levels description + * @levels: Output reference to voltage level array, in microvolts + * + * When @desc->type is VOLTAGE_TYPE_FULL_LIST, number of cells of @*levels + * is defined by @desc->num_levels, each cell being a level in microvolts (uV). + * When @desc->type is VOLTAGE_TYPE_INCREMENT, @levels has 3 cells: + * @levels[0] is the min voltage level, @levels[1] is the max level, @levels[2] + * is the incremental level step, all in microvolts (uV). + */ +TEE_Result regulator_supported_voltages(struct regulator *regulator, + struct regulator_voltages_desc **desc, + const int **levels); + +/* Print current regulator tree summary to console with debug trace level */ +#ifdef CFG_DRIVERS_REGULATOR +void regulator_print_tree(void); +#else +static inline void regulator_print_tree(void) +{ +} +#endif /* CFG_DRIVERS_REGULATOR */ +#endif /* __DRIVERS_REGULATOR_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..d111240 --- /dev/null +++ b/optee/optee_os/core/include/drivers/rstctrl.h @@ -0,0 +1,231 @@ +/* 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 **out_rstctrl) +{ + TEE_Result res = TEE_ERROR_GENERIC; + void *rstctrl = NULL; + + res = dt_driver_device_from_node_idx_prop("resets", fdt, nodeoffset, + index, DT_DRIVER_RSTCTRL, + &rstctrl); + if (!res) + *out_rstctrl = rstctrl; + + 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 **ctrl __unused) +{ + 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 + * + * @args: Pointer to devicetree description of the reset controller to parse + * @data: Pointer to data given at rstctrl_dt_register_provider() call + * @rstctrl: Output reset controller reference upon success + */ +typedef TEE_Result (*rstctrl_dt_get_func)(struct dt_pargs *args, void *data, + struct rstctrl **out_rstctrl); + +/** + * rstctrl_dt_register_provider - Register a reset controller provider + * + * @fdt: Device tree to work on + * @nodeoffset: Node offset of the reset controller + * @func: 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 func, + void *data) +{ + return dt_driver_register_provider(fdt, nodeoffset, + (get_of_device_func)func, 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..1e0df82 --- /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..5424303 --- /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 __DRIVERS_SAM_AT91_DDRSDR_H +#define __DRIVERS_SAM_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..7cb3ac0 --- /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 __DRIVERS_SCIF_H +#define __DRIVERS_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 /* __DRIVERS_SCIF_H */ 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..c276ea8 --- /dev/null +++ b/optee/optee_os/core/include/drivers/scmi-msg.h @@ -0,0 +1,411 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2021, Linaro Limited + */ + +#ifndef __DRIVERS_SCMI_MSG_H +#define __DRIVERS_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 + +struct clk; + +#ifdef CFG_SCMI_MSG_USE_CLK +/* + * Expose a clock through SCMI + * @clk: Clock to be exposed + * @channel_id: SCMI server channel exposing the clock + * @scmi_id: SCMI ID of the clock within the channel + */ +TEE_Result scmi_clk_add(struct clk *clk, unsigned int channel_id, + unsigned int scmi_id); +#else +static inline TEE_Result scmi_clk_add(struct clk *clk __unused, + unsigned int channel_id __unused, + unsigned int scmi_id __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 voltage domain 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 voltage domain 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 /* __DRIVERS_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..1e43bac --- /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 __DRIVERS_SCMI_MSG_SCMI_H +#define __DRIVERS_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 /* __DRIVERS_SCMI_MSG_SCMI_H */ diff --git a/optee/optee_os/core/include/drivers/semihosting_console.h b/optee/optee_os/core/include/drivers/semihosting_console.h new file mode 100644 index 0000000..93cc726 --- /dev/null +++ b/optee/optee_os/core/include/drivers/semihosting_console.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2024 Andes Technology Corporation + */ +#ifndef __DRIVERS_SEMIHOSTING_CONSOLE_H +#define __DRIVERS_SEMIHOSTING_CONSOLE_H + +#ifdef CFG_SEMIHOSTING_CONSOLE +/* + * Initialize console which uses architecture-specific semihosting mechanism. + * If @file_path is not NULL, OP-TEE OS will try to output log to that file, + * which is on the semihosting host system. + * Otherwise, if @file_path is NULL, OP-TEE OS will try to output log to the + * semihosting host debug console. + */ +void semihosting_console_init(const char *file_path); +#else +static inline void semihosting_console_init(const char *file_path __unused) +{ +} +#endif + +#endif /* __DRIVERS_SEMIHOSTING_CONSOLE_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..2a1e074 --- /dev/null +++ b/optee/optee_os/core/include/drivers/serial.h @@ -0,0 +1,48 @@ +/* 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); + void (*rx_intr_enable)(struct serial_chip *chip); + void (*rx_intr_disable)(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..e56811f --- /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 __DRIVERS_SERIAL8250_UART_H +#define __DRIVERS_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 /* __DRIVERS_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..a8f8f45 --- /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 __DRIVERS_SP805_WDT_H +#define __DRIVERS_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 /* __DRIVERS_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..8c12c39 --- /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 __DRIVERS_SPRD_UART_H +#define __DRIVERS_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 /* __DRIVERS_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..79df157 --- /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 __DRIVERS_STIH_ASC_H +#define __DRIVERS_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 /* __DRIVERS_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..f0577bc --- /dev/null +++ b/optee/optee_os/core/include/drivers/stm32_bsec.h @@ -0,0 +1,202 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2017-2022, STMicroelectronics + */ + +#ifndef __DRIVERS_STM32_BSEC_H +#define __DRIVERS_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 + */ +#ifdef CFG_STM32_BSEC_WRITE +TEE_Result stm32_bsec_permanent_lock_otp(uint32_t otp_id); +#else +static inline TEE_Result stm32_bsec_permanent_lock_otp(uint32_t otp_id __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} +#endif + +/* + * 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_offset: pointer to output OTP bit offset in the NVMEM cell 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, + uint8_t *otp_bit_offset, + size_t *otp_bit_len); + +/* + * Find and get OTP location from its phandle. + * @phandle: node phandle to look up. + * @otp_id: pointer to read OTP number or NULL. + * @otp_bit_offset: pointer to read offset in OTP in bits or NULL. + * @otp_bit_len: pointer to read OTP length in bits or NULL. + * Return a TEE_Result compliant status + */ +TEE_Result stm32_bsec_find_otp_by_phandle(const uint32_t phandle, + uint32_t *otp_id, + uint8_t *otp_bit_offset, + 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 /*__DRIVERS_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..48f0385 --- /dev/null +++ b/optee/optee_os/core/include/drivers/stm32_etzpc.h @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2018-2019, STMicroelectronics + */ + +#ifndef __DRIVERS_STM32_ETZPC_H +#define __DRIVERS_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); +#endif /*__DRIVERS_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..8838881 --- /dev/null +++ b/optee/optee_os/core/include/drivers/stm32_gpio.h @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2017-2023, STMicroelectronics + */ + +#ifndef __DRIVERS_STM32_GPIO_H +#define __DRIVERS_STM32_GPIO_H + +#include +#include +#include +#include +#include + +struct pinctrl_state; +struct stm32_pinctrl; + +#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); + +/* + * Configure pin muxing access permission: can be secure or not + * + * @pinctrl: Pin control state where STM32_GPIO pin are to configure + * @secure: True if pin is secure, false otherwise + */ +void stm32_pinctrl_set_secure_cfg(struct pinctrl_state *pinctrl, bool secure); + +/* + * Get the bank and pin indices related to a pin control state + * @pinctrl: Pinctrl state + * @bank: Output bank indices array or NULL + * @pin: Output pin indices array or NULL + * @count: [in] Number of cells of @bank and @pin, [out] pin count in @pinctrl + */ +void stm32_gpio_pinctrl_bank_pin(struct pinctrl_state *pinctrl, + unsigned int *bank, unsigned int *pin, + unsigned int *count); +#else +static inline void +stm32_pinctrl_set_secure_cfg(struct pinctrl_state *pinctrl __unused, + bool secure __unused) +{ +} + +static inline void stm32_gpio_pinctrl_bank_pin(struct pinctrl_state *p __unused, + unsigned int *bank __unused, + unsigned int *pin __unused, + unsigned int *count __unused) +{ +} +#endif /*CFG_STM32_GPIO*/ +#endif /*__DRIVERS_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..42b26b0 --- /dev/null +++ b/optee/optee_os/core/include/drivers/stm32_i2c.h @@ -0,0 +1,284 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* + * Copyright (c) 2017-2023, STMicroelectronics + */ + +#ifndef __DRIVERS_STM32_I2C_H +#define __DRIVERS_STM32_I2C_H + +#include +#include +#include +#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) + +/* + * struct stm32_i2c_init_s - STM32 I2C configuration data + * + * @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: Pin control configuration for the I2C bus in active state + * @pinctrl_sleep: Pin control configuration for the I2C bus in standby state + * @mu: Protection on concurrent access to the I2C bus considering PM context + */ +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 pinctrl_state *pinctrl; + struct pinctrl_state *pinctrl_sleep; + struct mutex_pm_aware mu; +}; + +/* + * struct stm32_i2c_dev - Bus consumer device over an STM32 I2C bus + * @i2c_dev: I2C consumer instance + * @i2c_ctrl: I2C bus control operation + * @handle: Handle on a single STM32 I2C bus interface + */ +struct stm32_i2c_dev { + struct i2c_dev i2c_dev; + struct i2c_ctrl i2c_ctrl; + struct i2c_handle_s *handle; +}; + +/* 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_active: Output active I2C pinctrl state + * @pinctrl_sleep: Output suspended I2C pinctrl state + * 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 pinctrl_state **pinctrl_active, + struct pinctrl_state **pinctrl_sleep); + +/* + * 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 /* __DRIVERS_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..a575a19 --- /dev/null +++ b/optee/optee_os/core/include/drivers/stm32_iwdg.h @@ -0,0 +1,29 @@ +/* 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); +#endif /*__DRIVERS_STM32_IWDG_H*/ diff --git a/optee/optee_os/core/include/drivers/stm32_remoteproc.h b/optee/optee_os/core/include/drivers/stm32_remoteproc.h new file mode 100644 index 0000000..8cb1efd --- /dev/null +++ b/optee/optee_os/core/include/drivers/stm32_remoteproc.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2023, STMicroelectronics - All Rights Reserved + */ + +#ifndef __DRIVERS_STM32_REMOTEPROC_H +#define __DRIVERS_STM32_REMOTEPROC_H + +#include +#include +#include + +/* IDs of the supported remote processors*/ +#define STM32_M4_RPROC_ID 0 + +/* + * stm32_rproc_get() - get the rproc handle associated to a remote processor ID + * @rproc_id unique identifier of the remote processor + * Return a pointer to the rproc firmware handle related to @rproc_id or NULL. + */ +void *stm32_rproc_get(uint32_t rproc_id); + +/* + * stm32_rproc_da_to_pa() - Convert the coprocessor device address to a CPU + * physical address. + * @rproc_id unique identifier of the remote processor + * @da device memory address from the remote processor space + * perspective. + * @size size of the memory + * @pa Output CPU physical address associated to @da. + * Return TEE_SUCCESS or appropriate error. + */ +TEE_Result stm32_rproc_da_to_pa(uint32_t rproc_id, paddr_t da, size_t size, + paddr_t *pa); + +/* + * stm32_rproc_map() - map the physical address if valid + * @rproc_id unique identifier of the remote processor + * @pa physical address from the CPU space perspective + * @size size of the memory + * @va Output CPU virtual address associated to @pa. + * Return TEE_SUCCESS or appropriate error. + */ +TEE_Result stm32_rproc_map(uint32_t rproc_id, paddr_t pa, size_t size, + void **va); + +/* + * stm32_rproc_unmap() - ummap the virtual address mapped with stm32_rproc_map + * @rproc_id unique identifier of the remote processor + * @va virtual address + * @size size of the memory + * Return TEE_SUCCESS or appropriate error. + */ +TEE_Result stm32_rproc_unmap(uint32_t rproc_id, void *va, size_t size); + +/* + * stm32_rproc_start() - start the remote processor core + * @rproc_id unique identifier of the remote processor + * Return TEE_SUCCESS or appropriate error. + */ +TEE_Result stm32_rproc_start(uint32_t rproc_id); + +/* + * stm32_rproc_stop() - stop the remote processor core + * @rproc_id unique identifier of the remote processor + * Return TEE_SUCCESS or appropriate error. + */ +TEE_Result stm32_rproc_stop(uint32_t rproc_id); + +#endif /* __DRIVERS_STM32_REMOTEPROC_H */ diff --git a/optee/optee_os/core/include/drivers/stm32_rif.h b/optee/optee_os/core/include/drivers/stm32_rif.h new file mode 100644 index 0000000..96ea30a --- /dev/null +++ b/optee/optee_os/core/include/drivers/stm32_rif.h @@ -0,0 +1,224 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2022-2024, STMicroelectronics + */ + +#ifndef __DRIVERS_STM32_RIF_H +#define __DRIVERS_STM32_RIF_H + +#include +#include +#include +#include + +/* + * CIDCFGR register + */ +#define _CIDCFGR_CFEN BIT(0) +#define _CIDCFGR_SEMEN BIT(1) +#define _CIDCFGR_SEMWL(x) BIT(SEMWL_SHIFT + (x)) + +/* + * SEMCR register + */ +#define _SEMCR_MUTEX BIT(0) +#define _SEMCR_SEMCID_SHIFT U(4) +#define _SEMCR_SEMCID_MASK GENMASK_32(6, 4) + +/* + * Miscellaneous + */ +#define MAX_CID_SUPPORTED U(8) + +#define SCID_SHIFT U(4) +#define SEMWL_SHIFT U(16) +#define RIF_ID_SHIFT U(24) + +#define RIF_ID_MASK GENMASK_32(31, 24) +#define RIF_CHANNEL_ID(x) ((RIF_ID_MASK & (x)) >> RIF_ID_SHIFT) + +#define RIFPROT_SEC BIT(8) +#define RIFPROT_PRIV BIT(9) +#define RIFPROT_LOCK BIT(10) + +/** + * struct rif_conf_data - Structure containing RIF configuration data + * + * @access_mask: Array of the masks of the registers which will be configured. + * @sec_conf: Secure configuration registers. + * @priv_conf: Privilege configuration registers. + * @cid_confs: CID filtering configuration register value for a peripheral + * resource (e.g: GPIO pins, FMC controllers) + * @lock_conf: RIF configuration locking registers + * + * For a hardware block having 56 channels, there will be 56 cid_confs + * registers and 2 sec_conf and priv_conf registers + */ +struct rif_conf_data { + uint32_t *access_mask; + uint32_t *sec_conf; + uint32_t *priv_conf; + uint32_t *cid_confs; + uint32_t *lock_conf; +}; + +#ifdef CFG_STM32_RIF +/** + * stm32_rif_scid_ok() - Check if a given static CID configuration authorizes + * access to a given CID + * + * @cidcfgr: Value of the CIDCFGR register + * @scid_m: Mask of the static CID in the register + * @cid_to_check: CID of the target compartment + * + * Returns true if given CID is authorized, false otherwise. + */ +static inline bool stm32_rif_scid_ok(uint32_t cidcfgr, uint32_t scid_m, + uint32_t cid_to_check) +{ + return (cidcfgr & scid_m) == SHIFT_U32(cid_to_check, SCID_SHIFT) && + !(cidcfgr & _CIDCFGR_SEMEN); +} + +/** + * stm32_rif_semaphore_enabled_and_ok() - Check if semaphore mode is enabled and + * that a given CID can request the + * semaphore ownership + * + * @cidcfgr: Value of the cidcfgr register + * @cid_bf_to_check: Bitfield of CIDs to check + * + * Returns true if all requested CIDs can request the semaphore ownership, + * false otherwise. + */ +static inline bool stm32_rif_semaphore_enabled_and_ok(uint32_t cidcfgr, + uint32_t cid_bf_to_check) +{ + return (cidcfgr & _CIDCFGR_CFEN) && (cidcfgr & _CIDCFGR_SEMEN) && + (cidcfgr & _CIDCFGR_SEMWL(cid_bf_to_check)); +} + +/** + * stm32_rifsc_check_tdcid() - Check if the execution context is TDCID or not + * + * @tdcid_state: [out] Set to true if TDCID, false otherwise. + * + * Returns TEE_ERROR_DEFER_DRIVER_INIT if RIFSC driver isn't probed, TEE_SUCCESS + * otherwise. + */ +TEE_Result stm32_rifsc_check_tdcid(bool *tdcid_state); + +/** + * stm32_rif_check_access() - Test peripheral access for a given compartment + * + * @cidcfgr: CIDCFGR configuration register value + * @semcr: SEMCR register value + * @nb_cid_supp: Number of supported CID for the peripheral + * @cid_to_check: CID of the target compartment + * + * Returns TEE_SUCCESS if access is authorized, a TEE_Result error value + * otherwise. + */ +TEE_Result stm32_rif_check_access(uint32_t cidcfgr, + uint32_t semcr, + unsigned int nb_cid_supp, + unsigned int cid_to_check); + +/** + * stm32_rif_parse_cfg() - Parse RIF config from Device Tree extracted + * information + * + * @rif_conf: Configuration read in the device tree + * @conf_data: Buffer containing the RIF configuration to apply for a peripheral + * @nb_cid_supp: Number of supported CID for the peripheral + * @nb_channel: Number of channels for the peripheral + */ +void stm32_rif_parse_cfg(uint32_t rif_conf, + struct rif_conf_data *conf_data, + unsigned int nb_cid_supp, + unsigned int nb_channel); + +/** + * stm32_rif_semaphore_is_available() - Checks if the _SEMCR_MUTEX bit is set + * + * @addr: Address of the register to read from + */ +bool stm32_rif_semaphore_is_available(vaddr_t addr); + +/** + * stm32_rif_semaphore_is_available() - Acquires the semaphore by setting the + * _SEMCR_MUTEX bit + * + * @addr: Address of the register to write to + * @nb_cid_supp: Number of CID supported + */ +TEE_Result stm32_rif_acquire_semaphore(vaddr_t addr, + unsigned int nb_cid_supp); + +/** + * stm32_rif_semaphore_is_available() - Releases the semaphore by clearing the + * _SEMCR_MUTEX bit + * + * @addr: Address of the register to write to + * @nb_cid_supp: Number of CID supported + */ +TEE_Result stm32_rif_release_semaphore(vaddr_t addr, + unsigned int nb_cid_supp); +#else +static inline bool stm32_rif_scid_ok(uint32_t cidcfgr, uint32_t scid_m, + uint32_t cid_to_check) +{ + return true; +} + +static inline bool stm32_rif_semaphore_enabled_and_ok(uint32_t cidcfgr, + uint32_t cid_bf_to_check) +{ + return true; +} + +static inline TEE_Result stm32_rifsc_check_tdcid(bool *tdcid_state) +{ + /* Without CFG_STM32_RIF every CPU can behave as TDCID */ + *tdcid_state = true; + + return TEE_SUCCESS; +} + +static inline TEE_Result +stm32_rif_check_access(uint32_t cidcfgr __unused, + uint32_t semcr __unused, + unsigned int nb_cid_supp __unused, + unsigned int cid_to_check __unused) +{ + return TEE_SUCCESS; +} + +static inline void +stm32_rif_parse_cfg(uint32_t rif_conf __unused, + struct rif_conf_data *conf_data __unused, + unsigned int nb_cid_supp __unused, + unsigned int nb_channel __unused) +{ +} + +static inline bool stm32_rif_semaphore_is_available(vaddr_t addr __unused) +{ + return true; +} + +static inline TEE_Result +stm32_rif_acquire_semaphore(vaddr_t addr __unused, + unsigned int nb_cid_supp __unused) +{ + return TEE_SUCCESS; +} + +static inline TEE_Result +stm32_rif_release_semaphore(vaddr_t addr __unused, + unsigned int nb_cid_supp __unused) +{ + return TEE_SUCCESS; +} +#endif /* CFG_STM32_RIF */ +#endif /* __DRIVERS_STM32_RIF_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..6054df7 --- /dev/null +++ b/optee/optee_os/core/include/drivers/stm32_uart.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017-2023, STMicroelectronics + */ + +#ifndef __DRIVERS_STM32_UART_H +#define __DRIVERS_STM32_UART_H + +#include +#include +#include +#include +#include +#include + +struct stm32_uart_pdata { + struct io_pa_va base; + struct serial_chip chip; + bool secure; + struct clk *clock; + struct pinctrl_state *pinctrl; + struct pinctrl_state *pinctrl_sleep; +}; + +/* + * 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 /*__DRIVERS_STM32_UART_H*/ diff --git a/optee/optee_os/core/include/drivers/stm32_vrefbuf.h b/optee/optee_os/core/include/drivers/stm32_vrefbuf.h new file mode 100644 index 0000000..5aa5618 --- /dev/null +++ b/optee/optee_os/core/include/drivers/stm32_vrefbuf.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2023, STMicroelectronics + */ +#ifndef DRIVERS_STM32_VREFBUF_H +#define DRIVERS_STM32_VREFBUF_H + +#include + +#ifdef CFG_STM32_VREFBUF +/* Return VREFBUF regulator handler if registered */ +struct regulator *stm32_vrefbuf_regulator(void); +#else +static inline struct regulator *stm32_vrefbuf_regulator(void) +{ + return NULL; +} +#endif + +#endif /*DRIVERS_STM32_VREFBUF_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/stm32mp13_regulator_iod.h b/optee/optee_os/core/include/drivers/stm32mp13_regulator_iod.h new file mode 100644 index 0000000..9cd70e3 --- /dev/null +++ b/optee/optee_os/core/include/drivers/stm32mp13_regulator_iod.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021-2023, STMicroelectronics + */ + +#ifndef __DRIVERS_STM32MP13_REGULATOR_IOD_H +#define __DRIVERS_STM32MP13_REGULATOR_IOD_H + +#include + +enum iod_regulator_id { + IOD_SDMMC1, + IOD_SDMMC2, + IOD_REGU_COUNT +}; + +#ifdef CFG_STM32MP13_REGULATOR_IOD +struct regulator *stm32mp1_get_iod_regulator(enum iod_regulator_id index); +#else +static inline struct regulator * +stm32mp1_get_iod_regulator(enum iod_regulator_id id __unused) { return NULL; } +#endif /* CFG_STM32MP13_REGULATOR_IOD */ +#endif /* __DRIVERS_STM32MP13_REGULATOR_IOD_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..83f3ead --- /dev/null +++ b/optee/optee_os/core/include/drivers/stm32mp1_rcc.h @@ -0,0 +1,577 @@ +/* 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; +} + +static inline void stm32_rcc_set_mckprot(bool enable) +{ + vaddr_t tzcr_reg = stm32_rcc_base() + RCC_TZCR; + + if (enable) + io_setbits32(tzcr_reg, RCC_TZCR_MCKPROT); + else + io_clrbits32(tzcr_reg, 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..7e11a4b --- /dev/null +++ b/optee/optee_os/core/include/drivers/stm32mp_dt_bindings.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2022, STMicroelectronics + */ +#ifndef __DRIVERS_STM32MP_DT_BINDINGS_H +#define __DRIVERS_STM32MP_DT_BINDINGS_H + +#ifdef CFG_STM32MP13 +#include +#include +#include +#include +#endif + +#ifdef CFG_STM32MP15 +#include +#include +#include +#endif + +#ifdef CFG_STM32MP25 +#include +#include +#endif + +#endif /* __DRIVERS_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..13539c6 --- /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 __DRIVERS_STPMIC1_H +#define __DRIVERS_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 /*__DRIVERS_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..9c255e4 --- /dev/null +++ b/optee/optee_os/core/include/drivers/tegra/tegra_fuse.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021-2024, 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 FUSE_BOOT_SECURITY_INFO_0 0x268 +#define BSI_OEM_KEY_VALID_MASK 0x200 +#define FUSE_SECURITY_MODE_0 0x1a0 +#define SECURITY_MODE_ENABLED_MASK 0x1 + +/* + * Get an 128-bit ECID from fuse + */ +fuse_ecid_t* tegra_fuse_get_ecid(void); + +/* + * Get a 64-bit ECID from fuse + * [out] val: the buffer saves the ECID + */ +TEE_Result tegra_fuse_get_64bit_ecid(uint64_t *val); + +/* + * Get Boot Security Info from fuse + */ +TEE_Result tegra_fuse_get_bsi(uint32_t *val); + +/* + * Get Security Mode from fuse + */ +TEE_Result tegra_fuse_get_sec_mode(uint32_t *val); + +/* + * Get the serial number from fuse ODMID and ODMINFO + * [out] sn: the buffer saves the serial number + * [inout] size: the size of the buffer, will be updated by the function + */ +TEE_Result tegra_fuse_get_sn(uint8_t **sn, uint32_t *size); + +#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..e0f175e --- /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..07f1f82 --- /dev/null +++ b/optee/optee_os/core/include/drivers/tegra/tegra_se_keyslot.h @@ -0,0 +1,72 @@ +/* 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 + +typedef enum +{ +#if defined(PLATFORM_FLAVOR_t194) + 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, + +#elif defined(PLATFORM_FLAVOR_t234) + 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, + +#else + SE_AES_KEYSLOT_COUNT = 0, +#endif +} se_aes_keyslot_t; + +/* + * 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..3070cc1 --- /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..8a22b5e --- /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..0e73b4c --- /dev/null +++ b/optee/optee_os/core/include/dt-bindings/clock/at91.h @@ -0,0 +1,195 @@ +/* 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) +/* Reserved for PMC_MCK_PRES */ +#define PMC_AUDIOIOPLL (PMC_MAIN + 8) +#define PMC_ETHPLL (PMC_MAIN + 9) +#define PMC_MCK1 (PMC_MAIN + 10) +/* Reserved for MCK2, MCK3, MCK4 */ +#define PMC_UTMI1 (PMC_MAIN + 14) +#define PMC_UTMI2 (PMC_MAIN + 15) +#define PMC_UTMI3 (PMC_MAIN + 16) +#define PMC_SAMA7G5_CORE_CLK_COUNT (PMC_MAIN + 17) + +#define AT91_SCMI_CLK_CORE_MCK 0 +#define AT91_SCMI_CLK_CORE_UTMI 1 +#define AT91_SCMI_CLK_CORE_MAIN 2 +#define AT91_SCMI_CLK_CORE_MCK2 3 +#define AT91_SCMI_CLK_CORE_I2S0_MUX 4 +#define AT91_SCMI_CLK_CORE_I2S1_MUX 5 +#define AT91_SCMI_CLK_CORE_PLLACK 6 +#define AT91_SCMI_CLK_CORE_PLLBCK 7 +#define AT91_SCMI_CLK_CORE_AUDIOPLLCK 8 +#define AT91_SCMI_CLK_CORE_MCK_PRES 9 + +#define AT91_SCMI_CLK_SYSTEM_DDRCK 10 +#define AT91_SCMI_CLK_SYSTEM_LCDCK 11 +#define AT91_SCMI_CLK_SYSTEM_UHPCK 12 +#define AT91_SCMI_CLK_SYSTEM_UDPCK 13 +#define AT91_SCMI_CLK_SYSTEM_PCK0 14 +#define AT91_SCMI_CLK_SYSTEM_PCK1 15 +#define AT91_SCMI_CLK_SYSTEM_PCK2 16 +#define AT91_SCMI_CLK_SYSTEM_ISCCK 17 + +#define AT91_SCMI_CLK_PERIPH_MACB0_CLK 18 +#define AT91_SCMI_CLK_PERIPH_TDES_CLK 19 +#define AT91_SCMI_CLK_PERIPH_MATRIX1_CLK 20 +#define AT91_SCMI_CLK_PERIPH_HSMC_CLK 21 +#define AT91_SCMI_CLK_PERIPH_PIOA_CLK 22 +#define AT91_SCMI_CLK_PERIPH_FLX0_CLK 23 +#define AT91_SCMI_CLK_PERIPH_FLX1_CLK 24 +#define AT91_SCMI_CLK_PERIPH_FLX2_CLK 25 +#define AT91_SCMI_CLK_PERIPH_FLX3_CLK 26 +#define AT91_SCMI_CLK_PERIPH_FLX4_CLK 27 +#define AT91_SCMI_CLK_PERIPH_UART0_CLK 28 +#define AT91_SCMI_CLK_PERIPH_UART1_CLK 29 +#define AT91_SCMI_CLK_PERIPH_UART2_CLK 30 +#define AT91_SCMI_CLK_PERIPH_UART3_CLK 31 +#define AT91_SCMI_CLK_PERIPH_UART4_CLK 32 +#define AT91_SCMI_CLK_PERIPH_TWI0_CLK 33 +#define AT91_SCMI_CLK_PERIPH_TWI1_CLK 34 +#define AT91_SCMI_CLK_PERIPH_SPI0_CLK 35 +#define AT91_SCMI_CLK_PERIPH_SPI1_CLK 36 +#define AT91_SCMI_CLK_PERIPH_TCB0_CLK 37 +#define AT91_SCMI_CLK_PERIPH_TCB1_CLK 38 +#define AT91_SCMI_CLK_PERIPH_PWM_CLK 39 +#define AT91_SCMI_CLK_PERIPH_ADC_CLK 40 +#define AT91_SCMI_CLK_PERIPH_UHPHS_CLK 41 +#define AT91_SCMI_CLK_PERIPH_UDPHS_CLK 42 +#define AT91_SCMI_CLK_PERIPH_SSC0_CLK 43 +#define AT91_SCMI_CLK_PERIPH_SSC1_CLK 44 +#define AT91_SCMI_CLK_PERIPH_TRNG_CLK 45 +#define AT91_SCMI_CLK_PERIPH_PDMIC_CLK 46 +#define AT91_SCMI_CLK_PERIPH_SECURAM_CLK 47 +#define AT91_SCMI_CLK_PERIPH_I2S0_CLK 48 +#define AT91_SCMI_CLK_PERIPH_I2S1_CLK 49 +#define AT91_SCMI_CLK_PERIPH_CAN0_CLK 50 +#define AT91_SCMI_CLK_PERIPH_CAN1_CLK 51 +#define AT91_SCMI_CLK_PERIPH_PTC_CLK 52 +#define AT91_SCMI_CLK_PERIPH_CLASSD_CLK 53 +#define AT91_SCMI_CLK_PERIPH_DMA0_CLK 54 +#define AT91_SCMI_CLK_PERIPH_DMA1_CLK 55 +#define AT91_SCMI_CLK_PERIPH_AES_CLK 56 +#define AT91_SCMI_CLK_PERIPH_AESB_CLK 57 +#define AT91_SCMI_CLK_PERIPH_SHA_CLK 58 +#define AT91_SCMI_CLK_PERIPH_MPDDR_CLK 59 +#define AT91_SCMI_CLK_PERIPH_MATRIX0_CLK 60 +#define AT91_SCMI_CLK_PERIPH_SDMMC0_HCLK 61 +#define AT91_SCMI_CLK_PERIPH_SDMMC1_HCLK 62 +#define AT91_SCMI_CLK_PERIPH_LCDC_CLK 63 +#define AT91_SCMI_CLK_PERIPH_ISC_CLK 64 +#define AT91_SCMI_CLK_PERIPH_QSPI0_CLK 65 +#define AT91_SCMI_CLK_PERIPH_QSPI1_CLK 66 + +#define AT91_SCMI_CLK_GCK_SDMMC0_GCLK 67 +#define AT91_SCMI_CLK_GCK_SDMMC1_GCLK 68 +#define AT91_SCMI_CLK_GCK_TCB0_GCLK 69 +#define AT91_SCMI_CLK_GCK_TCB1_GCLK 70 +#define AT91_SCMI_CLK_GCK_PWM_GCLK 71 +#define AT91_SCMI_CLK_GCK_ISC_GCLK 72 +#define AT91_SCMI_CLK_GCK_PDMIC_GCLK 73 +#define AT91_SCMI_CLK_GCK_I2S0_GCLK 74 +#define AT91_SCMI_CLK_GCK_I2S1_GCLK 75 +#define AT91_SCMI_CLK_GCK_CAN0_GCLK 76 +#define AT91_SCMI_CLK_GCK_CAN1_GCLK 77 +#define AT91_SCMI_CLK_GCK_CLASSD_GCLK 78 + +#define AT91_SCMI_CLK_PROG_PROG0 79 +#define AT91_SCMI_CLK_PROG_PROG1 80 +#define AT91_SCMI_CLK_PROG_PROG2 81 + +#define AT91_SCMI_CLK_SCKC_SLOWCK_32K 82 + +#ifdef CFG_SAMA7G5 +#define AT91_SCMI_CLK_CORE_CPUPLLCK 4 +#define AT91_SCMI_CLK_CORE_SYSPLLCK 5 +#define AT91_SCMI_CLK_CORE_DDRPLLCK 6 +#define AT91_SCMI_CLK_CORE_IMGPLLCK 7 +#define AT91_SCMI_CLK_CORE_ETHPLLCK 10 +#define AT91_SCMI_CLK_SYSTEM_PCK3 11 +#define AT91_SCMI_CLK_SYSTEM_PCK4 12 +#define AT91_SCMI_CLK_SYSTEM_PCK5 13 +#define AT91_SCMI_CLK_SYSTEM_PCK6 17 +#define AT91_SCMI_CLK_SYSTEM_PCK7 20 +#define AT91_SCMI_CLK_UTMI1 97 +#define AT91_SCMI_CLK_UTMI2 98 +#define AT91_SCMI_CLK_UTMI3 99 +#define AT91_SCMI_CLK_PERIPH_DMA2_CLK 100 +#define AT91_SCMI_CLK_PERIPH_FLX5_CLK 28 +#define AT91_SCMI_CLK_PERIPH_FLX6_CLK 29 +#define AT91_SCMI_CLK_PERIPH_FLX7_CLK 30 +#define AT91_SCMI_CLK_PERIPH_FLX8_CLK 31 +#define AT91_SCMI_CLK_PERIPH_FLX9_CLK 32 +#define AT91_SCMI_CLK_PERIPH_FLX10_CLK 33 +#define AT91_SCMI_CLK_PERIPH_FLX11_CLK 34 +#define AT91_SCMI_CLK_PERIPH_UDPHSB_CLK 35 +#define AT91_SCMI_CLK_PERIPH_PDMC1_CLK 36 +#define AT91_SCMI_CLK_PERIPH_UDPHSA_CLK 42 +#define AT91_SCMI_CLK_GCK_ADC_GCLK 40 +#define AT91_SCMI_CLK_PERIPH_PDMC0_CLK 46 +#define AT91_SCMI_CLK_PERIPH_CAN2_CLK 52 +#define AT91_SCMI_CLK_PERIPH_CAN3_CLK 53 +#define AT91_SCMI_CLK_PERIPH_CAN4_CLK 59 +#define AT91_SCMI_CLK_PERIPH_CAN5_CLK 60 +#define AT91_SCMI_CLK_PERIPH_SDMMC2_HCLK 63 +#define AT91_SCMI_CLK_GCK_SDMMC2_GCLK 71 +#define AT91_SCMI_CLK_GCK_MACB0_GCLK 72 +#define AT91_SCMI_CLK_GCK_MACB0_TSU 73 +#define AT91_SCMI_CLK_GCK_CAN2_GCLK 78 +#define AT91_SCMI_CLK_GCK_CAN3_GCLK 79 +#define AT91_SCMI_CLK_GCK_CAN4_GCLK 80 +#define AT91_SCMI_CLK_GCK_CAN5_GCLK 81 +#define AT91_SCMI_CLK_PERIPH_SPDIFRX_CLK 83 +#define AT91_SCMI_CLK_PERIPH_SPDIFTX_CLK 84 +#define AT91_SCMI_CLK_GCK_QSPI0_GCLK 85 +#define AT91_SCMI_CLK_GCK_QSPI1_GCLK 86 +#define AT91_SCMI_CLK_GCK_SPDIFRX_GCLK 87 +#define AT91_SCMI_CLK_GCK_SPDIFTX_GCLK 88 +#define AT91_SCMI_CLK_GCK_MACB1_GCLK 89 +#define AT91_SCMI_CLK_PERIPH_MACB1_CLK 90 +#define AT91_SCMI_CLK_GCK_MACB1_TSU 91 +#define AT91_SCMI_CLK_PERIPH_CSI_CLK 92 +#define AT91_SCMI_CLK_GCK_CSI_GCLK 93 +#define AT91_SCMI_CLK_PERIPH_CSI2DC_CLK 94 +#define AT91_SCMI_CLK_PERIPH_ASRC_CLK 95 +#define AT91_SCMI_CLK_GCK_ASRC_GCLK 96 +#endif + +#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..ec00898 --- /dev/null +++ b/optee/optee_os/core/include/dt-bindings/clock/stm32mp13-clks.h @@ -0,0 +1,236 @@ +/* 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 SPI1 162 +#define SPI2 163 +#define SPI3 164 +#define SPI4 165 +#define SPI5 166 + +#define STM32MP1_LAST_CLK 167 + +/* 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/firewall/stm32mp25-rif.h b/optee/optee_os/core/include/dt-bindings/firewall/stm32mp25-rif.h new file mode 100644 index 0000000..eceeb3a --- /dev/null +++ b/optee/optee_os/core/include/dt-bindings/firewall/stm32mp25-rif.h @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */ +/* + * Copyright (C) 2020-2024, STMicroelectronics - All Rights Reserved + */ + +#ifndef _DT_BINDINGS_FIREWALL_STM32MP25_RIF_H +#define _DT_BINDINGS_FIREWALL_STM32MP25_RIF_H + +/* RIF CIDs */ +#define RIF_CID0 0x0 +#define RIF_CID1 0x1 +#define RIF_CID2 0x2 +#define RIF_CID3 0x3 +#define RIF_CID4 0x4 +#define RIF_CID5 0x5 +#define RIF_CID6 0x6 +#define RIF_CID7 0x7 + +/* RIF semaphore list */ +#define EMPTY_SEMWL 0x0 +#ifdef __ASSEMBLER__ +#define RIF_CID0_BF (1 << RIF_CID0) +#define RIF_CID1_BF (1 << RIF_CID1) +#define RIF_CID2_BF (1 << RIF_CID2) +#define RIF_CID3_BF (1 << RIF_CID3) +#define RIF_CID4_BF (1 << RIF_CID4) +#define RIF_CID5_BF (1 << RIF_CID5) +#define RIF_CID6_BF (1 << RIF_CID6) +#define RIF_CID7_BF (1 << RIF_CID7) +#else /* __ASSEMBLER__ */ +#define RIF_CID0_BF BIT(RIF_CID0) +#define RIF_CID1_BF BIT(RIF_CID1) +#define RIF_CID2_BF BIT(RIF_CID2) +#define RIF_CID3_BF BIT(RIF_CID3) +#define RIF_CID4_BF BIT(RIF_CID4) +#define RIF_CID5_BF BIT(RIF_CID5) +#define RIF_CID6_BF BIT(RIF_CID6) +#define RIF_CID7_BF BIT(RIF_CID7) +#endif /* __ASSEMBLER__ */ + +/* RIF secure levels */ +#define RIF_NSEC 0x0 +#define RIF_SEC 0x1 + +/* RIF privilege levels */ +#define RIF_NPRIV 0x0 +#define RIF_PRIV 0x1 + +/* RIF semaphore modes */ +#define RIF_SEM_DIS 0x0 +#define RIF_SEM_EN 0x1 + +/* RIF CID filtering modes */ +#define RIF_CFDIS 0x0 +#define RIF_CFEN 0x1 + +/* RIF lock states */ +#define RIF_UNLOCK 0x0 +#define RIF_LOCK 0x1 + +/* Used when a field in a macro has no impact */ +#define RIF_UNUSED 0x0 + +/* Most below macros aim to ease DTS files readability */ +#define RIF_EXTI1_RESOURCE(x) (x) + +#define RIF_EXTI2_RESOURCE(x) (x) + +#define RIF_FMC_CTRL(x) (x) + +#define RIF_IOPORT_PIN(x) (x) + +#define RIF_HPDMA_CHANNEL(x) (x) + +#define RIF_IPCC_CPU1_CHANNEL(x) ((x) - 1) + +#define RIF_IPCC_CPU2_CHANNEL(x) (((x) - 1) + 16) + +#define RIF_PWR_RESOURCE(x) (x) + +#define RIF_HSEM_RESOURCE(x) (x) + +/* Shareable PWR resources, RIF_PWR_RESOURCE_WIO(0) doesn't exist */ +#define RIF_PWR_RESOURCE_WIO(x) ((x) + 6) + +#define RIF_RCC_RESOURCE(x) (x) + +#define RIF_RTC_RESOURCE(x) (x) + +#define RIF_TAMP_RESOURCE(x) (x) + +#endif /* _DT_BINDINGS_FIREWALL_STM32MP25_RIF_H */ diff --git a/optee/optee_os/core/include/dt-bindings/firewall/stm32mp25-rifsc.h b/optee/optee_os/core/include/dt-bindings/firewall/stm32mp25-rifsc.h new file mode 100644 index 0000000..a8476a1 --- /dev/null +++ b/optee/optee_os/core/include/dt-bindings/firewall/stm32mp25-rifsc.h @@ -0,0 +1,173 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* + * Copyright (c) 2020-2024, STMicroelectronics + */ +#ifndef _DT_BINDINGS_FIREWALL_STM32MP25_RIFSC_H +#define _DT_BINDINGS_FIREWALL_STM32MP25_RIFSC_H + +/* RIFSC ID */ +#define STM32MP25_RIFSC_TIM1_ID 0 +#define STM32MP25_RIFSC_TIM2_ID 1 +#define STM32MP25_RIFSC_TIM3_ID 2 +#define STM32MP25_RIFSC_TIM4_ID 3 +#define STM32MP25_RIFSC_TIM5_ID 4 +#define STM32MP25_RIFSC_TIM6_ID 5 +#define STM32MP25_RIFSC_TIM7_ID 6 +#define STM32MP25_RIFSC_TIM8_ID 7 +#define STM32MP25_RIFSC_TIM10_ID 8 +#define STM32MP25_RIFSC_TIM11_ID 9 +#define STM32MP25_RIFSC_TIM12_ID 10 +#define STM32MP25_RIFSC_TIM13_ID 11 +#define STM32MP25_RIFSC_TIM14_ID 12 +#define STM32MP25_RIFSC_TIM15_ID 13 +#define STM32MP25_RIFSC_TIM16_ID 14 +#define STM32MP25_RIFSC_TIM17_ID 15 +#define STM32MP25_RIFSC_TIM20_ID 16 +#define STM32MP25_RIFSC_LPTIM1_ID 17 +#define STM32MP25_RIFSC_LPTIM2_ID 18 +#define STM32MP25_RIFSC_LPTIM3_ID 19 +#define STM32MP25_RIFSC_LPTIM4_ID 20 +#define STM32MP25_RIFSC_LPTIM5_ID 21 +#define STM32MP25_RIFSC_SPI1_ID 22 +#define STM32MP25_RIFSC_SPI2_ID 23 +#define STM32MP25_RIFSC_SPI3_ID 24 +#define STM32MP25_RIFSC_SPI4_ID 25 +#define STM32MP25_RIFSC_SPI5_ID 26 +#define STM32MP25_RIFSC_SPI6_ID 27 +#define STM32MP25_RIFSC_SPI7_ID 28 +#define STM32MP25_RIFSC_SPI8_ID 29 +#define STM32MP25_RIFSC_SPDIFRX_ID 30 +#define STM32MP25_RIFSC_USART1_ID 31 +#define STM32MP25_RIFSC_USART2_ID 32 +#define STM32MP25_RIFSC_USART3_ID 33 +#define STM32MP25_RIFSC_UART4_ID 34 +#define STM32MP25_RIFSC_UART5_ID 35 +#define STM32MP25_RIFSC_USART6_ID 36 +#define STM32MP25_RIFSC_UART7_ID 37 +#define STM32MP25_RIFSC_UART8_ID 38 +#define STM32MP25_RIFSC_UART9_ID 39 +#define STM32MP25_RIFSC_LPUART1_ID 40 +#define STM32MP25_RIFSC_I2C1_ID 41 +#define STM32MP25_RIFSC_I2C2_ID 42 +#define STM32MP25_RIFSC_I2C3_ID 43 +#define STM32MP25_RIFSC_I2C4_ID 44 +#define STM32MP25_RIFSC_I2C5_ID 45 +#define STM32MP25_RIFSC_I2C6_ID 46 +#define STM32MP25_RIFSC_I2C7_ID 47 +#define STM32MP25_RIFSC_I2C8_ID 48 +#define STM32MP25_RIFSC_SAI1_ID 49 +#define STM32MP25_RIFSC_SAI2_ID 50 +#define STM32MP25_RIFSC_SAI3_ID 51 +#define STM32MP25_RIFSC_SAI4_ID 52 +#define STM32MP25_RIFSC_MDF1_ID 54 +#define STM32MP25_RIFSC_ADF1_ID 55 +#define STM32MP25_RIFSC_FDCAN_ID 56 +#define STM32MP25_RIFSC_HDP_ID 57 +#define STM32MP25_RIFSC_ADC12_ID 58 +#define STM32MP25_RIFSC_ADC3_ID 59 +#define STM32MP25_RIFSC_ETH1_ID 60 +#define STM32MP25_RIFSC_ETH2_ID 61 +#define STM32MP25_RIFSC_USBH_ID 63 +#define STM32MP25_RIFSC_USB3DR_ID 66 +#define STM32MP25_RIFSC_COMBOPHY_ID 67 +#define STM32MP25_RIFSC_PCIE_ID 68 +#define STM32MP25_RIFSC_UCPD1_ID 69 +#define STM32MP25_RIFSC_ETHSW_DEIP_ID 70 +#define STM32MP25_RIFSC_ETHSW_ACM_CFG_ID 71 +#define STM32MP25_RIFSC_ETHSW_ACM_MSGBUF_ID 72 +#define STM32MP25_RIFSC_STGEN_ID 73 +#define STM32MP25_RIFSC_OCTOSPI1_ID 74 +#define STM32MP25_RIFSC_OCTOSPI2_ID 75 +#define STM32MP25_RIFSC_SDMMC1_ID 76 +#define STM32MP25_RIFSC_SDMMC2_ID 77 +#define STM32MP25_RIFSC_SDMMC3_ID 78 +#define STM32MP25_RIFSC_GPU_ID 79 +#define STM32MP25_RIFSC_LTDC_CMN_ID 80 +#define STM32MP25_RIFSC_DSI_CMN_ID 81 +#define STM32MP25_RIFSC_LVDS_ID 84 +#define STM32MP25_RIFSC_CSI_ID 86 +#define STM32MP25_RIFSC_DCMIPP_ID 87 +#define STM32MP25_RIFSC_DCMI_PSSI_ID 88 +#define STM32MP25_RIFSC_VDEC_ID 89 +#define STM32MP25_RIFSC_VENC_ID 90 +#define STM32MP25_RIFSC_RNG_ID 92 +#define STM32MP25_RIFSC_PKA_ID 93 +#define STM32MP25_RIFSC_SAES_ID 94 +#define STM32MP25_RIFSC_HASH_ID 95 +#define STM32MP25_RIFSC_CRYP1_ID 96 +#define STM32MP25_RIFSC_CRYP2_ID 97 +#define STM32MP25_RIFSC_IWDG1_ID 98 +#define STM32MP25_RIFSC_IWDG2_ID 99 +#define STM32MP25_RIFSC_IWDG3_ID 100 +#define STM32MP25_RIFSC_IWDG4_ID 101 +#define STM32MP25_RIFSC_IWDG5_ID 102 +#define STM32MP25_RIFSC_WWDG1_ID 103 +#define STM32MP25_RIFSC_WWDG2_ID 104 +#define STM32MP25_RIFSC_VREFBUF_ID 106 +#define STM32MP25_RIFSC_DTS_ID 107 +#define STM32MP25_RIFSC_RAMCFG_ID 108 +#define STM32MP25_RIFSC_CRC_ID 109 +#define STM32MP25_RIFSC_SERC_ID 110 +#define STM32MP25_RIFSC_OCTOSPIM_ID 111 +#define STM32MP25_RIFSC_GICV2M_ID 112 +#define STM32MP25_RIFSC_I3C1_ID 114 +#define STM32MP25_RIFSC_I3C2_ID 115 +#define STM32MP25_RIFSC_I3C3_ID 116 +#define STM32MP25_RIFSC_I3C4_ID 117 +#define STM32MP25_RIFSC_ICACHE_DCACHE_ID 118 +#define STM32MP25_RIFSC_LTDC_L0L1_ID 119 +#define STM32MP25_RIFSC_LTDC_L2_ID 120 +#define STM32MP25_RIFSC_LTDC_ROT_ID 121 +#define STM32MP25_RIFSC_DSI_TRIG_ID 122 +#define STM32MP25_RIFSC_DSI_RDFIFO_ID 123 +#define STM32MP25_RIFSC_OTFDEC1_ID 125 +#define STM32MP25_RIFSC_OTFDEC2_ID 126 +#define STM32MP25_RIFSC_IAC_ID 127 + +#define RIFSC_RISC_CFEN_SHIFT 0 +#define RIFSC_RISC_SEM_EN_SHIFT 1 +#define RIFSC_RISC_SCID_SHIFT 4 +#define RIFSC_RISC_SEC_SHIFT 8 +#define RIFSC_RISC_PRIV_SHIFT 9 +#define RIFSC_RISC_LOCK_SHIFT 10 +#define RIFSC_RISC_SEML_SHIFT 16 +#define RIFSC_RISC_PER_ID_SHIFT 24 +#define RIFSC_RISC_PERx_CID_SHIFT 0 + +/* Global lock bindings */ +#define RIFSC_RIMU_GLOCK 1 +#define RIFSC_RISUP_GLOCK 2 + +#define RIFPROT(rifid, sem_list, lock, sec, priv, scid, sem_en, cfen) \ + (((rifid) << RIFSC_RISC_PER_ID_SHIFT) | \ + ((sem_list) << RIFSC_RISC_SEML_SHIFT) | \ + ((lock) << RIFSC_RISC_LOCK_SHIFT) | \ + ((priv) << RIFSC_RISC_PRIV_SHIFT) | \ + ((sec) << RIFSC_RISC_SEC_SHIFT) | \ + ((scid) << RIFSC_RISC_SCID_SHIFT) | \ + ((sem_en) << RIFSC_RISC_SEM_EN_SHIFT) | \ + ((cfen) << RIFSC_RISC_CFEN_SHIFT)) + +/* masters ID */ +#define RIMU_ID(idx) (idx) + +/* master configuration modes */ +#define RIF_CIDSEL_P 0x0 /* config from RISUP */ +#define RIF_CIDSEL_M 0x1 /* config from RIMU */ + +#define RIFSC_RIMC_MODE_SHIFT 2 +#define RIFSC_RIMC_MCID_SHIFT 4 +#define RIFSC_RIMC_MSEC_SHIFT 8 +#define RIFSC_RIMC_MPRIV_SHIFT 9 +#define RIFSC_RIMC_M_ID_SHIFT 16 +#define RIFSC_RIMC_ATTRx_SHIFT 0 + +#define RIMUPROT(rimuid, mcid, msec, mpriv, mode) \ + (((rimuid) << RIFSC_RIMC_M_ID_SHIFT) | \ + ((mpriv) << RIFSC_RIMC_MPRIV_SHIFT) | \ + ((msec) << RIFSC_RIMC_MSEC_SHIFT) | \ + ((mcid) << RIFSC_RIMC_MCID_SHIFT) | \ + ((mode) << RIFSC_RIMC_MODE_SHIFT)) + +#endif /* _DT_BINDINGS_FIREWALL_STM32MP25_RIFSC_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/gpio/stm32mp_gpio.h b/optee/optee_os/core/include/dt-bindings/gpio/stm32mp_gpio.h new file mode 100644 index 0000000..3afcf41 --- /dev/null +++ b/optee/optee_os/core/include/dt-bindings/gpio/stm32mp_gpio.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) */ +/* + * Copyright (C) STMicroelectronics 2023 - All Rights Reserved + */ + +#ifndef _DT_BINDINGS_GPIO_STM32MP_GPIO_H +#define _DT_BINDINGS_GPIO_STM32MP_GPIO_H + +#include + +/* Macro to define the security for GPIO */ +#ifdef __ASSEMBLER__ +#define TZPROT(id) (1 << (id)) +#else +#define TZPROT(id) (UINT32_C(1) << (id)) +#endif + +#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..a4ea712 --- /dev/null +++ b/optee/optee_os/core/include/dt-bindings/regulator/st,stm32mp13-regulator.h @@ -0,0 +1,42 @@ +/* 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 + +/* External regulators */ +#define VOLTD_SCMI_REGU0 20 +#define VOLTD_SCMI_REGU1 21 +#define VOLTD_SCMI_REGU2 22 +#define VOLTD_SCMI_REGU3 23 +#define VOLTD_SCMI_REGU4 24 + +#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/dt-bindings/rtc/rtc-stm32.h b/optee/optee_os/core/include/dt-bindings/rtc/rtc-stm32.h new file mode 100644 index 0000000..8e77aae --- /dev/null +++ b/optee/optee_os/core/include/dt-bindings/rtc/rtc-stm32.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ +/* + * Copyright (C) STMicroelectronics 2022-2023 - All Rights Reserved + * This header provides constants for STM32_RTC bindings. + */ + +#ifndef _DT_BINDINGS_RTC_STM32_H +#define _DT_BINDINGS_RTC_STM32_H + +#define RTC_OUT1 0 +#define RTC_OUT2 1 +#define RTC_OUT2_RMP 2 + +#endif /*_DT_BINDINGS_RTC_STM32_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..8b612a5 --- /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/initcall.h b/optee/optee_os/core/include/initcall.h new file mode 100644 index 0000000..147adce --- /dev/null +++ b/optee/optee_os/core/include/initcall.h @@ -0,0 +1,133 @@ +/* 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, final calls | + * | 2. call_initcalls() +-----------------------------------+ + * | 3. call_finalcalls() | 1. boot_final() / nex_*init*() | + * +-------------------------------+-----------------------------------+ + * | "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) + +/* + * These nex_* init-calls are provided for drivers and services that reside + * in the nexus in case of virtualization. The init-calls are performed + * before exiting to the non-secure world at the end of boot + * initialization. In case of virtualization the init-calls are based on + * final calls, while otherwise are the same as the non-nex counterpart. + */ +#ifdef CFG_NS_VIRTUALIZATION +#define nex_early_init(fn) boot_final(fn) +#define nex_early_init_late(fn) __define_initcall(final, 2, fn) +#define nex_service_init(fn) __define_initcall(final, 3, fn) +#define nex_service_init_late(fn) __define_initcall(final, 4, fn) +#define nex_driver_init(fn) __define_initcall(final, 5, fn) +#define nex_driver_init_late(fn) __define_initcall(final, 6, fn) +#define nex_release_init_resource(fn) __define_initcall(final, 7, fn) +#else +#define nex_early_init(fn) early_init(fn) +#define nex_early_init_late(fn) early_init_late(fn) +#define nex_service_init(fn) service_init(fn) +#define nex_service_init_late(fn) service_init_late(fn) +#define nex_driver_init(fn) driver_init(fn) +#define nex_driver_init_late(fn) driver_init_late(fn) +#define nex_release_init_resource(fn) release_init_resource(fn) +#endif + +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..2b47176 --- /dev/null +++ b/optee/optee_os/core/include/io.h @@ -0,0 +1,304 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014-2019, Linaro Limited + */ +#ifndef __IO_H +#define __IO_H + +#include +#include +#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); +} + +/* + * Poll on a IO memory content or timeout + * + * @_addr is the address of the memory cell accessed + * @_val represents the val of the memory cell accessed + * @_cond represents the condition to get the correct value + * @_delay_us represents the read interval in mircorseconds + * @_timeout_us represents the timeout period in microseconds + * + * @return nonzero value means timeout, 0 means got right value + */ +#define IO_READ32_POLL_TIMEOUT(_addr, _val, _cond, _delay_us, _timeout_us) \ + ({ \ + uint64_t __timeout = timeout_init_us(_timeout_us); \ + uint32_t __delay = (_delay_us); \ + \ + while (!timeout_elapsed(__timeout)) { \ + (_val) = io_read32(_addr); \ + if (_cond) \ + break; \ + udelay(__delay); \ + } \ + (_val) = io_read32(_addr); \ + !(_cond); \ + }) + +#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..622d1d6 --- /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..4a0f527 --- /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..b1d6b1e --- /dev/null +++ b/optee/optee_os/core/include/kernel/boot.h @@ -0,0 +1,105 @@ +/* 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 const struct core_mmu_config boot_mmu_config; + +void boot_init_primary_early(void); +void boot_init_primary_late(unsigned long fdt, unsigned long manifest); +void boot_init_memtag(void); +void boot_clear_memtag(void); +void boot_save_args(unsigned long a0, unsigned long a1, unsigned long a2, + unsigned long a3, unsigned long a4); +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 boot_primary_init_intc(void); +void boot_secondary_init_intc(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) || defined(CFG_WITH_STACK_CANARIES) +/* + * plat_get_random_stack_canaries() - Get random values for stack canaries. + * @buf: Pointer to the buffer where to store canaries + * @ncan: The number of canaries to generate. + * @size: The size (in bytes) of each canary. + * + * This function has a __weak default implementation. + */ +void plat_get_random_stack_canaries(void *buf, size_t ncan, size_t size); +#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 TOS_FW_CONFIG DTB or SP manifest DTB if present, otherwise NULL */ +void *get_manifest_dt(void); + +/* + * get_aslr_seed() - return a random seed for core ASLR + * + * This function has a __weak default implementation. + */ +unsigned long get_aslr_seed(void); + +#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/callout.h b/optee/optee_os/core/include/kernel/callout.h new file mode 100644 index 0000000..07fb2fc --- /dev/null +++ b/optee/optee_os/core/include/kernel/callout.h @@ -0,0 +1,134 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2024, Linaro Limited + */ + +#ifndef __KERNEL_CALLOUT_H +#define __KERNEL_CALLOUT_H + +#include +#include +#include + +/* + * struct callout - callout reference + * @callback: function to be called when a callout expires + * @expiry_value: callout expiry time counter value + * @period: ticks to next timeout + * @link: linked list element + * + * @callback is called from an interrupt handler so thread resources must + * not be used. The main callout service lock is held while @callback is + * called so callout_rem() and callout_add() can't be used, but it is safe + * to call callout_set_next_timeout() if the call period should be changed. + * @callback returns true if it should be called again in @period ticks + * or false if the callout should be removed and inactivated. Returning + * false from @callback is the equivalent of calling callout_rem() on the + * callout reference. + */ +struct callout { + bool (*callback)(struct callout *co); + uint64_t expiry_value; + uint64_t period; + TAILQ_ENTRY(callout) link; +}; + +/* + * callout_add() - Add a callout + * @co: callout reference + * @callback: callback function accociated with the callout + * @ms: time to next callout in milliseconds + * + * Adds a callout to the callout service with an associated callback + * function @callback that is to be called in @ms milliseconds. + * + * If callout_add() is called before callout_service_init() has been called + * then it will be called @ms milliseconds after callout_service_init() has + * been called. + * + * The callout structure can reside in global data or on the heap. It's + * safe to embed it inside another struct, but it must not be freed until + * removed with callout_rem() or equivalent. + * + * The function takes the main callout service for synchronization so it + * can't be called from within a callback function in a callout or there's + * deadlock. + */ +void callout_add(struct callout *co, bool (*callback)(struct callout *co), + uint32_t ms); + +/* + * callout_rem() - Remove a callout + * @co: callout reference + * + * Removes a callout previously added to the callout service with + * callout_add(). Note that when the callback function in a callout + * returns false the callout is also removed. + * + * It's safe to try to remove a callback even if it isn't active any + * longer. Nothing will happen in that case, but it's guaranteed to be + * inactive and it's safe to free the memory after callout_rem() has + * returned. + */ +void callout_rem(struct callout *co); + +/* + * callout_set_next_timeout() - set time to next callout + * @co: callout reference + * @ms: time to next callout in milliseconds + * + * Updates the @co->ticks field with the new number of ticks based on @ms. + * This value is used to when to calculate the time of the next callout + * following then one already set. + * + * Must only be called from @co->callback() when the callout is triggered. + */ +void callout_set_next_timeout(struct callout *co, uint32_t ms); + +/* + * struct callout_timer_desc - callout timer descriptor + * @disable_timeout: disables the timer from triggering an interrupt + * @set_next_timeout: sets the next timeout and enables the timer + * @ms_to_ticks: converts milliseconds to ticks, the counter value + * unit + * @get_now: get the current counter value + * @is_per_cpu: flag to indicate if this timer is per CPU (true) or + * global (false). + * + * This descriptor provides an abstract timer interface first used by + * callout_service_init() and then stored to be used by + * callout_service_cb(). + * + * When @is_per_cpu is true there is one private timer per CPU so + * @disable_timeout() and @set_next_timeout() only affects the timer on the + * current CPU. If for instance @set_next_timeout() is called on a new CPU + * compared to last time the timer on the old CPU will remain unchanged. + * Timer interrupts may trigger based on obsolete configuration, the + * callout service is expected to handle this gracefully. + */ +struct callout_timer_desc { + void (*disable_timeout)(const struct callout_timer_desc *desc); + void (*set_next_timeout)(const struct callout_timer_desc *desc, + uint64_t expiry_value); + uint64_t (*ms_to_ticks)(const struct callout_timer_desc *desc, + uint32_t ms); + uint64_t (*get_now)(const struct callout_timer_desc *desc); + bool is_per_cpu; +}; + +/* + * callout_service_init() - Initialize the callout service + * @desc: Pointer to the timer interface + * + * The callout service is initialized with the supplied timer interface + */ +void callout_service_init(const struct callout_timer_desc *desc); + +/* + * callout_service_cb() - Callout service callback + * + * Called from interrupt service function for the timer. + */ +void callout_service_cb(void); + +#endif /*__KERNEL_CALLOUT_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..c051078 --- /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 __KERNEL_CHIP_SERVICES_H +#define __KERNEL_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..312d307 --- /dev/null +++ b/optee/optee_os/core/include/kernel/delay.h @@ -0,0 +1,71 @@ +/* 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 +#include + +#ifdef CFG_CORE_HAS_GENERIC_TIMER +/* Convert microsecond base delay @us into architecture time tick counts */ +static inline uint64_t delay_us2cnt(uint32_t us) +{ + return ((uint64_t)us * (uint64_t)delay_cnt_freq()) / ULL(1000000); +} + +/* Return delay tick counter for a timeout expiration in @us microseconds */ +static inline uint64_t timeout_init_us(uint32_t us) +{ + return delay_cnt_read() + delay_us2cnt(us); +} + +/* Check if timeout tick counter @expire from timeout_init_us() has expired */ + +static inline bool timeout_elapsed(uint64_t expire) +{ + return delay_cnt_read() > expire; +} + +/* + * Return the time in microseconds since/until timeout tick counter @expired, + * that was initialized with timeout_init_us() or like, has/will expire. + * A positive value means the timeout has expired and a negative one it has not. + */ +int timeout_elapsed_us(uint64_t expire); +#endif /*CFG_CORE_HAS_GENERIC_TIMER*/ + +/* Wait @us microseconds actively polling on architecture timer */ +void udelay(uint32_t us); + +/* Wait @ms milliseconds actively polling on architecture timer */ +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..3de3c92 --- /dev/null +++ b/optee/optee_os/core/include/kernel/dt.h @@ -0,0 +1,457 @@ +/* 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 + +/* + * 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 +}; + +/* + * struct dt_descriptor - Descriptor of the device tree + * @blob: Pointer to the device tree binary + * @frag_id: Used ID of fragments for device tree overlay + */ +struct dt_descriptor { + void *blob; +#ifdef _CFG_USE_DTB_OVERLAY + int frag_id; +#endif +}; + +extern uint8_t embedded_secure_dtb[]; + +#ifdef CFG_DT +/* + * 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); + +/* + * 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); + +/* 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 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(); +} + +/* Returns DTB descriptor of the external DTB if present, otherwise NULL */ +struct dt_descriptor *get_external_dt_desc(void); + +/* + * init_external_dt() - Initialize the external DTB located at given address. + * @phys_dt: Physical address where the external DTB located. + * @dt_sz: Maximum size of the external DTB. + * + * Initialize the external DTB. + * + * 1. Add MMU mapping of the external DTB, + * 2. Initialize device tree overlay + */ +void init_external_dt(unsigned long phys_dt, size_t dt_sz); + +/* Returns external DTB if present, otherwise NULL */ +void *get_external_dt(void); + +/* + * add_dt_path_subnode() - Add new child node into a parent node. + * @dt: Pointer to a device tree descriptor which has DTB. + * @path: Path to the parent node. + * @subnode: Name of the child node. + * + * Returns the offset of the child node in DTB on success or a negative libfdt + * error number. + */ +int add_dt_path_subnode(struct dt_descriptor *dt, const char *path, + const char *subnode); + +/* + * add_res_mem_dt_node() - Create "reserved-memory" parent and child nodes. + * @dt: Pointer to a device tree descriptor which has DTB. + * @name: Name of the child node. + * @pa: Physical address of specific reserved memory region. + * @size: Size of specific reserved memory region. + * + * Returns 0 if succeeds, otherwise a negative libfdt error number. + */ +int add_res_mem_dt_node(struct dt_descriptor *dt, const char *name, + paddr_t pa, 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; +} + +static inline int dt_getprop_as_number(const void *fdt __unused, + int nodeoffset __unused, + const char *name __unused, + uint64_t *num __unused) +{ + return -1; +} + +static inline void *get_dt(void) +{ + return NULL; +} + +static inline void *get_secure_dt(void) +{ + return NULL; +} + +static inline void *get_embedded_dt(void) +{ + return NULL; +} + +static inline bool is_embedded_dt(void *fdt __unused) +{ + return false; +} + +static inline struct dt_descriptor *get_external_dt_desc(void) +{ + return NULL; +} + +static inline void init_external_dt(unsigned long phys_dt __unused, + size_t dt_sz __unused) +{ +} + +static inline void *get_external_dt(void) +{ + return NULL; +} + +static inline int add_dt_path_subnode(struct dt_descriptor *dt __unused, + const char *path __unused, + const char *subnode __unused) +{ + return -1; +} + +static inline int add_res_mem_dt_node(struct dt_descriptor *dt __unused, + const char *name __unused, + paddr_t pa __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..f73f300 --- /dev/null +++ b/optee/optee_os/core/include/kernel/dt_driver.h @@ -0,0 +1,283 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, Linaro Limited + * Copyright (c) 2021, Bootlin + * Copyright (c) 2021, STMicroelectronics + */ + +#ifndef __KERNEL_DT_DRIVER_H +#define __KERNEL_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 controller using generic I2C bus DT bindings + * DT_DRIVER_GPIO GPIO controller using generic GPIO DT bindings + * DT_DRIVER_PINCTRL Pin controller using generic reset DT bindings + * DT_DRIVER_INTERRUPT Interrupt controller using generic DT bindings + * DT_DRIVER_REGULATOR Voltage regulator controller using generic DT bindings + * DT_DRIVER_NVMEM NVMEM controller using generic NVMEM DT bindings + */ +enum dt_driver_type { + DT_DRIVER_NOTYPE, + DT_DRIVER_UART, + DT_DRIVER_CLK, + DT_DRIVER_RSTCTRL, + DT_DRIVER_I2C, + DT_DRIVER_GPIO, + DT_DRIVER_PINCTRL, + DT_DRIVER_INTERRUPT, + DT_DRIVER_REGULATOR, + DT_DRIVER_NVMEM, +}; + +/* + * 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_pargs - 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_pargs { + 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. + * @device_ref: output device reference upon success, e.g. a struct clk + * pointer for a clock driver. + * + * Return code: + * 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. + */ +typedef TEE_Result (*get_of_device_func)(struct dt_pargs *parg, void *data, + void *device_ref); + +/** + * 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 + * @device_ref: output device opaque reference upon support, for example + * a struct clk pointer for a clock driver. + + * Return code: + * 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 + * or @prop_idx does not match any index in @prop_name phandle list + * Any TEE_Result compliant code in case of error. + */ +TEE_Result 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, + void *device_ref); + +/* + * 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 + * @device_ref: output device opaque reference upon success, for example + * a struct i2c_dev pointer for a I2C bus driver + * + * Return code: + * 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. + */ +TEE_Result dt_driver_device_from_parent(const void *fdt, int nodeoffset, + enum dt_driver_type type, + void *device_ref); + +/* + * dt_driver_device_from_node_idx_prop_phandle() - Same as + * dt_driver_device_from_node_idx_prop() but phandle is not the first + * cells in property @prop_name but is passed as an argument. + * + * This function is used for DT bindings as "interrupts" property where the + * property carries the interrupt information but not the interrupt controller + * phandle which is found in a specific property (here "interrupt-parent"). + */ +TEE_Result dt_driver_device_from_node_idx_prop_phandle(const char *prop_name, + const void *fdt, + int nodeoffs, + unsigned int prop_index, + enum dt_driver_type type, + uint32_t phandle, + void *device_ref); + +/* + * 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); + +/* + * Return provider private data registered by dt_driver_register_provider() + */ +void *dt_driver_provider_priv_data(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 /* __KERNEL_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..8ad12e5 --- /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..aeaabff --- /dev/null +++ b/optee/optee_os/core/include/kernel/embedded_ts.h @@ -0,0 +1,37 @@ +/* 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_core, + void *data_user, 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..9a7504d --- /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..c8c5f9f --- /dev/null +++ b/optee/optee_os/core/include/kernel/huk_subkey.h @@ -0,0 +1,66 @@ +/* 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. + * Function huk_subkey_derive() is __weak to allow platform specific + * implementation. + * __huk_subkey_derive() implements the default behavior of HUK derivation. + * + * Return TEE_SUCCESS 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); +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..22a7a04 --- /dev/null +++ b/optee/optee_os/core/include/kernel/interrupt.h @@ -0,0 +1,544 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016-2019, Linaro Limited + */ +#ifndef __KERNEL_INTERRUPT_H +#define __KERNEL_INTERRUPT_H + +#include +#include +#include +#include +#include +#include +#include + +#define ITRF_TRIGGER_LEVEL BIT(0) +#define ITRF_SHARED BIT(1) + +/* Forward the interrupt only to the current CPU */ +#define ITR_CPU_MASK_TO_THIS_CPU BIT(31) +/* Forward the interrupt to all CPUs except the current CPU */ +#define ITR_CPU_MASK_TO_OTHER_CPUS BIT(30) + +struct itr_handler; + +/* + * struct itr_chip - Interrupt controller + * + * @ops Operation callback functions + * @name Controller name, for debug purpose + * @handlers Registered handlers list head + * @dt_get_irq Device tree node parsing function + */ +struct itr_chip { + const struct itr_ops *ops; + const char *name; + SLIST_HEAD(, itr_handler) handlers; + /* + * 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 - Interrupt controller operations + * @add Register and configure an interrupt + * @enable Enable an interrupt + * @disable Disable an interrupt + * @mask Mask an interrupt, may be called from an interrupt context + * @unmask Unmask an interrupt, may be called from an interrupt context + * @raise_pi Raise per-cpu interrupt or NULL if not applicable + * @raise_sgi Raise a SGI or NULL if not applicable to that controller + * @set_affinity Set interrupt/cpu affinity or NULL if not applicable + * + * Handlers @enable, @disable, @mask, @unmask and @add are mandated. Handlers + * @mask and @unmask have unpaged memory contrainsts. See itr_chip_is_valid(). + */ +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 (*mask)(struct itr_chip *chip, size_t it); + void (*unmask)(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, + uint32_t cpu_mask); + void (*set_affinity)(struct itr_chip *chip, size_t it, + uint8_t cpu_mask); +}; + +/* + * struct itr_desc - Interrupt description + * @chip Interrupt controller reference + * @itr_num Interrupt number + * + * This struct is used for binding interrupt device data between + * drivers when using DT_DRIVERS means. See itr_dt_get_func type + * definition. + */ +struct itr_desc { + struct itr_chip *chip; + size_t itr_num; +}; + +/* Interrupt handler return value */ +enum itr_return { + ITRR_NONE, + ITRR_HANDLED, +}; + +/* Interrupt handler signature */ +typedef enum itr_return (*itr_handler_t)(struct itr_handler *h); + +/* + * struct itr_handler - Interrupt handler reference + * @it Interrupt number + * @flags Property bit flags (ITRF_*) or 0 + * @data Private data for that interrupt handler + * @chip Interrupt controller chip device + * @link Reference in controller handler list + */ +struct itr_handler { + size_t it; + uint32_t flags; + itr_handler_t handler; + void *data; + struct itr_chip *chip; + SLIST_ENTRY(itr_handler) link; +}; + +#define ITR_HANDLER(_chip, _itr_num, _flags, _fn, _priv) \ + ((struct itr_handler){ \ + .chip = (_chip), .it = (_itr_num), .flags = (_flags), \ + .handler = (_fn), .data = (_priv), \ + }) + +/* + * Return true only if interrupt chip provides required handlers + * @chip: Interrupt controller reference + */ +static inline bool itr_chip_is_valid(struct itr_chip *chip) +{ + return chip && is_unpaged(chip) && chip->ops && + is_unpaged((void *)chip->ops) && + chip->ops->mask && is_unpaged(chip->ops->mask) && + chip->ops->unmask && is_unpaged(chip->ops->unmask) && + chip->ops->enable && chip->ops->disable && + chip->ops->add; +} + +/* + * Initialise an interrupt controller handle + * @chip Interrupt controller + */ +TEE_Result itr_chip_init(struct itr_chip *chip); + +/* + * Initialise main interrupt controller driver + * @data Main controller main data reference to register + */ +void interrupt_main_init(struct itr_chip *data); + +/* Retrieve main interrupt controller reference */ +struct itr_chip *interrupt_get_main_chip(void); +/* Retrieve main interrupt controller reference, or NULL on failure */ +struct itr_chip *interrupt_get_main_chip_may_fail(void); + +#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 + +/* + * __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 interrupt_main_handler(void); + +/* + * Interrupt controller chip API functions + */ + +/* + * interrupt_call_handlers() - Call registered handlers for an interrupt + * @chip Interrupt controller + * @itr_num Interrupt number + * + * This function is called from an interrupt context by a primary interrupt + * handler. This function calls the handlers registered for that interrupt. + * If interrupt is not handled, it is masked. + */ +void interrupt_call_handlers(struct itr_chip *chip, size_t itr_num); + +/* + * interrupt_mask() - Mask an interrupt + * @chip Interrupt controller + * @itr_num Interrupt number + * + * This function may be called in interrupt context + */ +static inline void interrupt_mask(struct itr_chip *chip, size_t itr_num) +{ + chip->ops->mask(chip, itr_num); +} + +/* + * interrupt_unmask() - Unmask an interrupt + * @chip Interrupt controller + * @itr_num Interrupt number + * + * This function may be called in interrupt context + */ +static inline void interrupt_unmask(struct itr_chip *chip, size_t itr_num) +{ + chip->ops->unmask(chip, itr_num); +} + +/* + * interrupt_enable() - Enable an interrupt + * @chip Interrupt controller + * @itr_num Interrupt number + */ +static inline void interrupt_enable(struct itr_chip *chip, size_t itr_num) +{ + chip->ops->enable(chip, itr_num); +} + +/* + * interrupt_disable() - Disable an interrupt + * @chip Interrupt controller + * @itr_num Interrupt number + */ +static inline void interrupt_disable(struct itr_chip *chip, size_t itr_num) +{ + chip->ops->disable(chip, itr_num); +} + +/* + * interrupt_can_raise_pi() - Return whether controller embeds raise_pi + * @chip Interrupt controller + */ +static inline bool interrupt_can_raise_pi(struct itr_chip *chip) +{ + return chip->ops->raise_pi; +} + +/* + * interrupt_can_raise_sgi() - Return whether controller embeds raise_sgi + * @chip Interrupt controller + */ +static inline bool interrupt_can_raise_sgi(struct itr_chip *chip) +{ + return chip->ops->raise_sgi; +} + +/* + * interrupt_can_set_affinity() - Return whether controller embeds set_affinity + * @chip Interrupt controller + */ +static inline bool interrupt_can_set_affinity(struct itr_chip *chip) +{ + return chip->ops->set_affinity; +} + +/* + * interrupt_raise_pi() - Raise a peripheral interrupt of a controller + * @chip Interrupt controller + * @itr_num Interrupt number to raise + */ +static inline void interrupt_raise_pi(struct itr_chip *chip, size_t itr_num) +{ + assert(interrupt_can_raise_pi(chip)); + chip->ops->raise_pi(chip, itr_num); +} + +/* + * interrupt_raise_sgi() - Raise a software generiated interrupt of a controller + * @chip Interrupt controller + * @itr_num Interrupt number to raise + * @cpu_mask: A bitfield of CPUs to forward the interrupt to, unless + * ITR_CPU_MASK_TO_THIS_CPU or ITR_CPU_MASK_TO_OTHER_CPUS + * (mutually exclusive) are set. + */ +static inline void interrupt_raise_sgi(struct itr_chip *chip, size_t itr_num, + uint32_t cpu_mask) +{ + assert(interrupt_can_raise_sgi(chip)); + chip->ops->raise_sgi(chip, itr_num, cpu_mask); +} + +/* + * interrupt_set_affinity() - Set CPU affinity for a controller interrupt + * @chip Interrupt controller + * @itr_num Interrupt number to raise + * @cpu_mask Mask of the CPUs targeted by the interrupt + */ +static inline void interrupt_set_affinity(struct itr_chip *chip, size_t itr_num, + uint8_t cpu_mask) +{ + assert(interrupt_can_set_affinity(chip)); + chip->ops->set_affinity(chip, itr_num, cpu_mask); +} + +/* + * interrupt_configure() - Configure an interrupt in an interrupt controller + * @chip Interrupt controller + * @itr_num Interrupt number + * @type Interrupt trigger type (IRQ_TYPE_* defines) or IRQ_TYPE_NONE + * @prio Interrupt priority or 0 + * + * Interrupt consumers that get their interrupt from the DT do not need to + * call interrupt_configure() since the interrupt configuration has already + * been done by interrupt controller based on the DT bidings. + */ +TEE_Result interrupt_configure(struct itr_chip *chip, size_t itr_num, + uint32_t type, uint32_t prio); + +/* + * interrupt_add_and_configure_handler() - Register and configure a handler + * @hdl Interrupt handler to register + * @type Interrupt trigger type (IRQ_TYPE_* defines) or IRQ_TYPE_NONE + * @prio Interrupt priority or 0 + */ +TEE_Result interrupt_add_configure_handler(struct itr_handler *hdl, + uint32_t type, uint32_t prio); + +/* + * interrupt_add_handler() - Register an interrupt handler + * @hdl Interrupt handler to register + * + * This helper function assumes interrupt type is set to IRQ_TYPE_NONE + * and interrupt priority to 0. + */ +static inline TEE_Result interrupt_add_handler(struct itr_handler *hdl) +{ + return interrupt_add_configure_handler(hdl, IRQ_TYPE_NONE, 0); +} + +/* + * interrupt_create_handler() - Allocate/register an interrupt callback handler + * @itr_chip Interrupt chip obtained from dt_get_interrupt_by_*() + * @itr_num Interrupt number obtained from dt_get_interrupt_by_*() + * @callback Callback handler function + * @priv Private dat to pssa to @callback + * @flags INTERRUPT_FLAGS_* or 0 + * @out_hdl Output allocated and registered handler or NULL + * + * This function differs from interrupt_add_handler() in that the + * interrupt is not reconfigured. interrupt_create_handler() expects + * @itr_desc was obtained from a call to dt_get_interrupt_by_index() + * or dt_get_interrupt_by_name(). That call configured the interrupt. + */ +TEE_Result interrupt_create_handler(struct itr_chip *itr_chip, size_t itr_num, + itr_handler_t callback, void *priv, + uint32_t flags, + struct itr_handler **out_hdl); + +/* + * interrupt_add_handler_with_chip() - Register an interrupt handler providing + * the interrupt chip reference in specific argument @chip. + * @chip Interrupt controller + * @h Interrupt handler to register + */ +static inline TEE_Result interrupt_add_handler_with_chip(struct itr_chip *chip, + struct itr_handler *h) +{ + h->chip = chip; + return interrupt_add_handler(h); +} + +/* + * interrupt_remove_handler() - Remove a registered interrupt handler + * @hdl Interrupt handler to remove + * + * This function is the counterpart of interrupt_add_handler(). + * This function may panic on non-NULL invalid @hdl reference. + */ +void interrupt_remove_handler(struct itr_handler *hdl); + +/* + * interrupt_alloc_add_conf_handler() - Allocate, configure, register a handler + * @chip Interrupt controller + * @itr_num Interrupt number + * @handler Interrupt handler to register + * @flags Bitmask flag ITRF_* + * @data Private data reference passed to @handler + * @type Interrupt trigger type (IRQ_TYPE_* defines) or IRQ_TYPE_NONE + * @prio Interrupt priority or 0 + * @out_hdl NULL or output pointer to allocated struct itr_handler + */ +TEE_Result interrupt_alloc_add_conf_handler(struct itr_chip *chip, + size_t it_num, + itr_handler_t handler, + uint32_t flags, void *data, + uint32_t type, uint32_t prio, + struct itr_handler **out_hdl); + +/* + * interrupt_alloc_add_handler() - Allocate and register an interrupt handler + * @chip Interrupt controller + * @itr_num Interrupt number + * @handler Interrupt handler to register + * @flags Bitmask flag ITRF_* + * @data Private data reference passed to @handler + * @out_hdl NULL or output pointer to allocated struct itr_handler + */ +static inline TEE_Result interrupt_alloc_add_handler(struct itr_chip *chip, + size_t it_num, + itr_handler_t handler, + uint32_t flags, + void *data, + struct itr_handler **hdl) +{ + return interrupt_alloc_add_conf_handler(chip, it_num, handler, flags, + data, IRQ_TYPE_NONE, 0, hdl); +} + +/* + * interrupt_remove_free_handler() - Remove/free a registered interrupt handler + * @hdl Interrupt handler to remove and free + * + * This function is the counterpart of interrupt_alloc_add_handler() + * and interrupt_alloc_add_conf_handler(). + * This function may panic on non-NULL invalid @hdl reference. + */ +void interrupt_remove_free_handler(struct itr_handler *hdl); + +/* + * itr_dt_get_func - Typedef of function to get an interrupt in DT node + * + * @args Reference to phandle arguments + * @data Pointer to data given at interrupt_register_provider() call + * @itr_desc_p Pointer to the struct itr_desc to fill + * Return TEE_SUCCESS in case of success. + * Return TEE_ERROR_DEFER_DRIVER_INIT if controller is not initialized. + * Return another TEE_Result code otherwise. + * + * Upon success, the interrupt is configured and consumer can add a handler + * function to the interrupt. Yet, the interrupt is not enabled until consumer + * calls interrupt_enable(). + */ +typedef TEE_Result (*itr_dt_get_func)(struct dt_pargs *args, void *data, + struct itr_desc *itr_desc_p); + +#ifdef CFG_DT +/** + * interrupt_register_provider() - Register an interrupt provider + * + * @fdt Device tree to work on + * @node Node offset of the interrupt controller in the DT + * @dt_get_itr Callback to match the devicetree interrupt reference with + * @data Data which will be passed to the get_dt_its callback + */ +TEE_Result interrupt_register_provider(const void *fdt, int node, + itr_dt_get_func dt_get_itr, void *data); + +/** + * interrupt_dt_get_by_index() - Get an interrupt from DT by interrupt index + * + * Interrupt index (@index) refers to the index of the target interrupt to be + * retrieved as DT binding property "interrupts" may define several + * interrupts. + * + * @fdt Device tree to work on + * @node Node offset of the subnode containing interrupt(s) references + * @index Index in "interrupts" or "extended-interrupts" property list + * @chip Output interrupt controller reference upon success + * @itr_num Output interrupt number upon success + * + * Return TEE_SUCCESS in case of success + * Return TEE_ERROR_DEFER_DRIVER_INIT if interrupt driver is not yet initialized + * Return TEE_ERROR_ITEM_NOT_FOUND if the DT does not reference target interrupt + * Return any other TEE_Result compliant code in case of error + */ +TEE_Result interrupt_dt_get_by_index(const void *fdt, int node, + unsigned int index, struct itr_chip **chip, + size_t *itr_num); + +/** + * interrupt_dt_get_by_name() - Get an interrupt from DT by interrupt name + * + * @fdt Device tree to work on + * @node Node offset of the subnode containing interrupt(s) references + * @name Name identifier used in "interrupt-names" property + * @chip Output interrupt controller reference upon success + * @itr_num Output interrupt number upon success + * + * Return TEE_SUCCESS in case of success + * Return TEE_ERROR_DEFER_DRIVER_INIT if interrupt driver is not yet initialized + * Return TEE_ERROR_ITEM_NOT_FOUND if the DT does not reference target interrupt + * Return any other TEE_Result compliant code in case of error + */ +TEE_Result interrupt_dt_get_by_name(const void *fdt, int node, const char *name, + struct itr_chip **chip, size_t *itr_num); +#else +static inline TEE_Result interrupt_register_provider(const void *dt __unused, + int node __unused, + itr_dt_get_func f __unused, + void *data __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +static inline TEE_Result interrupt_dt_get_by_index(const void *fdt __unused, + int node __unused, + unsigned int index __unused, + struct itr_chip **c __unused, + size_t *itr_num __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +static inline TEE_Result interrupt_dt_get_by_name(const void *fdt __unused, + int node __unused, + const char *name __unused, + struct itr_chip **ch __unused, + size_t *itr_num __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} +#endif /*CFG_DT*/ + +/* + * Helper function for when caller retrieves the first interrupt defined + * in "interrupts" or "extended-interrupts" DT binding property list. + */ +static inline TEE_Result interrupt_dt_get(const void *fdt, int node, + struct itr_chip **chip, + size_t *itr_num) +{ + return interrupt_dt_get_by_index(fdt, node, 0, chip, itr_num); +} +#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..fef590c --- /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 symlen, 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..62b410a --- /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..949ffd8 --- /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 ARM32 + +/* + * 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..d204a3a --- /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..d840dfa --- /dev/null +++ b/optee/optee_os/core/include/kernel/msg_param.h @@ -0,0 +1,83 @@ +/* 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 + +/** + * 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..c701188 --- /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/mutex_pm_aware.h b/optee/optee_os/core/include/kernel/mutex_pm_aware.h new file mode 100644 index 0000000..1345feb --- /dev/null +++ b/optee/optee_os/core/include/kernel/mutex_pm_aware.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2024, STMicroelectronics + */ +#ifndef __KERNEL_MUTEX_PM_AWARE_H +#define __KERNEL_MUTEX_PM_AWARE_H + +#include +#include + +/* + * struct mutex_pm_aware - Mutex usable in PM atomic sequence + * + * Some resources need a mutex protection for runtime operations but are + * also accessed during specific system power transition (PM power off, + * suspend and resume) that operate in atomic execution environment where + * non-secure world is not operational, for example in fastcall SMC entries + * of the PSCI services. In such case we cannot take a mutex and we expect + * the mutex is unlocked. Additionally a spinning lock is attempted to be + * locked to check the resource access consistency. + * + * Core intentionally panics in case of unexpected resource access contention: + * - When a thread requests a mutex held by a non-thread context; + * - When a non-thread context requests a mutex held by a thread; + * - When a non-thread context requests a mutex held by a non-thread context. + */ +struct mutex_pm_aware { + struct mutex mutex; /* access protection in thread context */ + unsigned int lock; /* access consistency in PM context */ +}; + +#define MUTEX_PM_AWARE_INITIALIZER { \ + .mutex = MUTEX_INITIALIZER, \ + .lock = SPINLOCK_UNLOCK, \ + } + +void mutex_pm_aware_init(struct mutex_pm_aware *m); +void mutex_pm_aware_destroy(struct mutex_pm_aware *m); +void mutex_pm_aware_lock(struct mutex_pm_aware *m); +void mutex_pm_aware_unlock(struct mutex_pm_aware *m); + +#endif /*__KERNEL_MUTEX_PM_AWARE_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/nv_counter.h b/optee/optee_os/core/include/kernel/nv_counter.h new file mode 100644 index 0000000..bdf071e --- /dev/null +++ b/optee/optee_os/core/include/kernel/nv_counter.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2023, Linaro Limited + */ + +#ifndef __KERNEL_NV_COUNTER_H +#define __KERNEL_NV_COUNTER_H + +#include +#include + +TEE_Result nv_counter_get_ree_fs(uint32_t *value); +TEE_Result nv_counter_incr_ree_fs_to(uint32_t value); + +#endif /*__KERNEL_NV_COUNTER_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..3d4fa55 --- /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..a1100f3 --- /dev/null +++ b/optee/optee_os/core/include/kernel/pm.h @@ -0,0 +1,175 @@ +/* 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) + +#define PM_HINT_STATE(_x) ((_x) & ~PM_HINT_PLATFORM_STATE_MASK) +#define PM_HINT_PLATFORM_STATE(_x) \ + (((_x) & PM_HINT_PLATFORM_STATE_MASK) >> PM_HINT_PLATFORM_STATE_SHIFT) + +#define PM_HINT_IS_STATE(_x, _name) ((_x) & PM_HINT_ ## _name ## _STATE) + +/* + * 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..965ca0d --- /dev/null +++ b/optee/optee_os/core/include/kernel/pseudo_ta.h @@ -0,0 +1,99 @@ +/* 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 +#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); + +/* + * Helper functions for PTAs to support calls from a TA when CFG_PAN=y + */ + +static inline bool is_caller_ta_with_pan(void) +{ + struct ts_session *s = NULL; + + if (!IS_ENABLED(CFG_PAN)) + return false; + s = ts_get_calling_session(); + return s && is_user_ta_ctx(s->ctx); +} + +/* + * If caller is a TA and PAN is enabled, allocate bounce buffers for each + * memref in @params and build @bparams, then make *@oparams point to @bparams. + * Otherwise just make *@oparams point to @params. + */ +TEE_Result to_bounce_params(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS], + TEE_Param bparams[TEE_NUM_PARAMS], + TEE_Param **oparams); + +/* + * If @eparams == @bparams, copy data from @bparams to @params. Otherwise, do + * nothing. + */ +TEE_Result from_bounce_params(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS], + TEE_Param bparams[TEE_NUM_PARAMS], + TEE_Param *eparams); + +#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..fe9f6b8 --- /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 __KERNEL_RPC_IO_I2C_H +#define __KERNEL_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 /* __KERNEL_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/semihosting.h b/optee/optee_os/core/include/kernel/semihosting.h new file mode 100644 index 0000000..ed81a51 --- /dev/null +++ b/optee/optee_os/core/include/kernel/semihosting.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2024 Andes Technology Corporation + */ +#ifndef __KERNEL_SEMIHOSTING_H +#define __KERNEL_SEMIHOSTING_H + +#include +#include +#include +#include + +/* Perform architecture-specific semihosting instructions. */ +uintptr_t __do_semihosting(uintptr_t op, uintptr_t arg); + +char semihosting_sys_readc(void); +void semihosting_sys_writec(char c); +int semihosting_open(const char *fname, int flags); +size_t semihosting_read(int fd, void *ptr, size_t len); +size_t semihosting_write(int fd, const void *ptr, size_t len); +int semihosting_close(int fd); + +#endif /* __KERNEL_SEMIHOSTING_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..d8eb519 --- /dev/null +++ b/optee/optee_os/core/include/kernel/spinlock.h @@ -0,0 +1,155 @@ +/* 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(); +} + +static inline bool thread_spin_trylock(unsigned int *lock) +{ + assert(thread_get_id_may_fail() != THREAD_ID_INVALID); + return !__cpu_spin_trylock(lock); +} + +/* + * To be used with lot of care: it is not recommended to spin in a thread + * context without masking foreign interrupts + */ +static inline void thread_spin_lock(unsigned int *lock) +{ + assert(thread_get_id_may_fail() != THREAD_ID_INVALID); + __cpu_spin_lock(lock); +} + +static inline void thread_spin_unlock(unsigned int *lock) +{ + assert(thread_get_id_may_fail() != THREAD_ID_INVALID); + __cpu_spin_unlock(lock); +} + +#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 __must_check +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 __must_check +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 __must_check 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..d4b0672 --- /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 __KERNEL_TEE_COMMON_H +#define __KERNEL_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 /* __KERNEL_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..3d0f44f --- /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 __KERNEL_TEE_COMMON_OTP_H +#define __KERNEL_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 /* __KERNEL_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..6655252 --- /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 __KERNEL_TEE_MISC_H +#define __KERNEL_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 /* __KERNEL_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..8cae350 --- /dev/null +++ b/optee/optee_os/core/include/kernel/tee_ta_manager.h @@ -0,0 +1,175 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2017, Linaro Limited + * Copyright (c) 2020, Arm Limited + */ + +#ifndef __KERNEL_TEE_TA_MANAGER_H +#define __KERNEL_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 */ + bool is_releasing; /* Context is about to be released */ + 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 *__noprof 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..28b4154 --- /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 __KERNEL_TEE_TIME_H +#define __KERNEL_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..b7f497e --- /dev/null +++ b/optee/optee_os/core/include/kernel/thread.h @@ -0,0 +1,399 @@ +/* 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_FLAGS_FFA_ONLY BIT(3) + +#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); + +#if defined(CFG_WITH_STACK_CANARIES) +void thread_update_canaries(void); +#else +static inline void thread_update_canaries(void) { } +#endif + +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/timer.h b/optee/optee_os/core/include/kernel/timer.h new file mode 100644 index 0000000..1638a4a --- /dev/null +++ b/optee/optee_os/core/include/kernel/timer.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2018, 2024, Linaro Limited + */ + +#ifndef __KERNEL_TIMER_H +#define __KERNEL_TIMER_H + +#include +#include + +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); + +/* + * timer_init_callout_service() - Initializes the callout service + * @itr_chip: Interrupt chip, typically interrupt_get_main_chip() + * @itr_number: Interrupt number in @itr_chip space for the timer. + * + * This function starts the callout service via interrupts from the timer. + * The platform or architecture specific code provides the implementation + * of this function. The interrupt callback function for the timer calls + * callout_service_cb() to drive the callout service. + * + * Note that usage of this function is incompatible with usage of the + * generic_timer_start(), generic_timer_stop() and generic_timer_handler() + * functions. + */ +void timer_init_callout_service(struct itr_chip *itr_chip, size_t itr_number); + +#endif /* __KERNEL_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..96ced9f --- /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 __KERNEL_TRACE_TA_H +#define __KERNEL_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 /*__KERNEL_TRACE_TA_H*/ + diff --git a/optee/optee_os/core/include/kernel/transfer_list.h b/optee/optee_os/core/include/kernel/transfer_list.h new file mode 100644 index 0000000..ed81397 --- /dev/null +++ b/optee/optee_os/core/include/kernel/transfer_list.h @@ -0,0 +1,157 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2023, Linaro Limited + */ + +#ifndef __KERNEL_TRANSFER_LIST_H +#define __KERNEL_TRANSFER_LIST_H + +#define TRANSFER_LIST_SIGNATURE U(0x4a0fb10b) +#define TRANSFER_LIST_VERSION U(0x0001) + +/* + * Init value of maximum alignment required by any transfer entry data in the TL + * specified as a power of two + */ +#define TRANSFER_LIST_INIT_MAX_ALIGN U(3) + +/* Alignment required by transfer entry header start address, in bytes */ +#define TRANSFER_LIST_GRANULE U(8) + +/* + * Version of the register convention used. + * Set to 1 for both AArch64 and AArch32 according to fw handoff spec v0.9 + */ +#define REG_CONVENTION_VER_MASK BIT(24) + +#define TL_FLAGS_HAS_CHECKSUM BIT(0) + +/* Transfer list operation codes */ +#define TL_OPS_NONE U(0) /* invalid for any operation */ +#define TL_OPS_ALL U(1) /* valid for all operations */ +#define TL_OPS_RO U(2) /* valid for read only */ +#define TL_OPS_CUS U(3) /* either abort or special code to interpret */ + +#ifndef __ASSEMBLER__ + +#include + +/* Get alignment from a value specified as power of two */ +#define TL_ALIGNMENT_FROM_ORDER(a) BIT(a) + +enum transfer_list_tag_id { + TL_TAG_EMPTY = 0, + TL_TAG_FDT = 1, + TL_TAG_HOB_BLOCK = 2, + TL_TAG_HOB_LIST = 3, + TL_TAG_ACPI_TABLE_AGGREGATE = 4, + TL_TAG_OPTEE_PAGABLE_PART = 0x100, +}; + +struct transfer_list_header { + uint32_t signature; + uint8_t checksum; + uint8_t version; + uint8_t hdr_size; + uint8_t alignment; /* max alignment of transfer entry data */ + uint32_t size; /* TL header + all transfer entries */ + uint32_t max_size; + uint32_t flags; + uint32_t reserved; /* spare bytes */ + /* + * Commented out element used to visualize dynamic part of the + * data structure. + * + * Note that struct transfer_list_entry also is dynamic in size + * so the elements can't be indexed directly but instead must be + * traversed in order + * + * struct transfer_list_entry entries[]; + */ +}; + +struct transfer_list_entry { + uint16_t tag_id; + uint8_t reserved0; /* place holder for tag ID 3rd byte (MSB) */ + uint8_t hdr_size; + uint32_t data_size; + /* + * Commented out element used to visualize dynamic part of the + * data structure. + * + * Note that padding is added at the end of @data to make it reach + * a 8-byte boundary. + * + * uint8_t data[ROUNDUP(data_size, 8)]; + */ +}; + +struct transfer_list_header *transfer_list_map(paddr_t pa); +void transfer_list_unmap_sync(struct transfer_list_header *tl); +void transfer_list_unmap_nosync(struct transfer_list_header *tl); + +void transfer_list_dump(struct transfer_list_header *tl); +struct transfer_list_header *transfer_list_init(paddr_t pa, size_t max_size); + +struct transfer_list_header * +transfer_list_relocate(struct transfer_list_header *tl, paddr_t pa, + size_t max_size); + +#if defined(CFG_TRANSFER_LIST) + +int transfer_list_check_header(const struct transfer_list_header *tl); + +struct transfer_list_entry *transfer_list_find(struct transfer_list_header *tl, + uint16_t tag_id); + +void *transfer_list_entry_data(struct transfer_list_entry *tl_e); + +#else /* CFG_TRANSFER_LIST */ + +static inline int +transfer_list_check_header(const struct transfer_list_header *tl __unused) +{ + return TL_OPS_NONE; +} + +static inline struct transfer_list_entry * +transfer_list_find(struct transfer_list_header *tl __unused, + uint16_t tag_id __unused) +{ + return NULL; +} + +static inline void * +transfer_list_entry_data(struct transfer_list_entry *tl_e __unused) +{ + return NULL; +} + +#endif /* CFG_TRANSFER_LIST */ + +void transfer_list_update_checksum(struct transfer_list_header *tl); +bool transfer_list_verify_checksum(const struct transfer_list_header *tl); + +bool transfer_list_set_data_size(struct transfer_list_header *tl, + struct transfer_list_entry *tl_e, + uint32_t new_data_size); + +bool transfer_list_rem(struct transfer_list_header *tl, + struct transfer_list_entry *tl_e); + +struct transfer_list_entry *transfer_list_add(struct transfer_list_header *tl, + uint16_t tag_id, + uint32_t data_size, + const void *data); + +struct transfer_list_entry * +transfer_list_add_with_align(struct transfer_list_header *tl, uint16_t tag_id, + uint32_t data_size, const void *data, + uint8_t alignment); + +struct transfer_list_entry * +transfer_list_next(struct transfer_list_header *tl, + struct transfer_list_entry *last); + +#endif /*__ASSEMBLER__*/ +#endif /*__TRANSFER_LIST_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..ab14654 --- /dev/null +++ b/optee/optee_os/core/include/kernel/ts_manager.h @@ -0,0 +1,84 @@ +/* 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 - Trusted Service operations + * The operations below are called when: + * @enter_open_session(): opening a session to the service + * @enter_invoke_cmd(): invoking a command in the service + * @enter_close_session(): closing a session to the service + * @dump_mem_stats(): dumping heap state of the service + * @dump_state(): dumping active memory mappings + * @dump_ftrace(): dumping the ftrace data via RPC + * @release_state(): the service has panicked and as much state + * as possible need to be released + * @destroy(): freeing the struct ts_ctx removing all + * trace of the service + * @get_instance_id(): a unique ID of the service is needed + * @handle_scall(): handling a syscall from the service + * @gprof_set_status(): updating the gprof status of the service + */ +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 (*release_state)(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..58c2173 --- /dev/null +++ b/optee/optee_os/core/include/kernel/ts_store.h @@ -0,0 +1,89 @@ +/* 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_core: pointer to secure memory where the TS bytes should be + * copied. + * @data_user: pointer to user memory where the TS bytes should be + * copied. + * At least one of @data_core and @data_user are normally NULL, but + * both are also permitted to be non-NULL. + * If @data_core == NULL and @data_user == NULL and @len != 0, the + * function should just skip @len bytes. + */ + TEE_Result (*read)(struct ts_store_handle *h, void *data_core, + void *data_user, 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..8ecf343 --- /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..54b3bfd --- /dev/null +++ b/optee/optee_os/core/include/kernel/user_access.h @@ -0,0 +1,189 @@ +/* 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 +#include + +#ifdef CFG_WITH_USER_TA +TEE_Result check_user_access(uint32_t flags, const void *uaddr, size_t len); +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); +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); +#else +static inline TEE_Result check_user_access(uint32_t flags __unused, + const void *uaddr __unused, + size_t len __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +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; +} + +static inline TEE_Result copy_to_user_private(void *uaddr __unused, + const void *kaddr __unused, + size_t len __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +static inline TEE_Result copy_to_user(void *uaddr __unused, + const void *kaddr __unused, + size_t len __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} +#endif + +/* + * bb_alloc() - Allocate a bounce buffer + * @len: Length of bounce buffer + * + * The bounce buffer is allocated from a per user TA context region reserved + * for bounce buffers. Buffers are allocated in a stack like fashion so + * only the last buffer can be free. Buffers generally don't have to be + * freed, all bounce buffer allocations are reset on each syscall entry. + * + * Return NULL on failure or a valid pointer on success. + */ +void *bb_alloc(size_t len); + +/* + * bb_free() - Free a bounce buffer + * @bb: Buffer + * @len: Length of buffer + * + * The bounce buffer is only freed if it is last on the stack of allocated + * bounce buffers. This function does normally not need to be called, see + * description of bb_alloc(). + */ +void bb_free(void *bb, size_t len); + +/* + * bb_free_wipe() - Wipe and free a bounce buffer + * @bb: Buffer + * @len: Length of buffer + * + * The bounce buffer is always wiped if @bb is non-NULL, but only freed if + * it is last on the stack of allocated bounce buffers. + */ +void bb_free_wipe(void *bb, size_t len); + +/* + * bb_reset() - Reset bounce buffer allocation + * + * Resets the bounce buffer allocatation state, old pointers allocated + * with bb_alloc() should not be used any longer. + */ +void bb_reset(void); + +TEE_Result clear_user(void *uaddr, size_t n); + +size_t strnlen_user(const void *s, size_t n); + +#define __BB_MEMDUP(memdup_func, src, len, p) ({ \ + TEE_Result __res = TEE_SUCCESS; \ + void *__p = NULL; \ + \ + __res = memdup_func((src), (len), &__p); \ + if (!__res) \ + *(p) = __p; \ + __res; \ +}) + +/* + * bb_memdup_user() - Duplicate a user-space buffer into a bounce buffer + * @src: Pointer to the user buffer to be duplicated. + * @len: Length of the user buffer to be duplicated. + * @p: Holds duplicated bounce buffer on success, or unchanged on failure. + * Note that the returned buffer is allocated by bb_alloc() and + * normally doesn't have to be freed. + * Return TEE_SUCCESS on success. + * Return TEE_ERROR_OUT_OF_MEMORY or TEE_ERROR_ACCESS_DENIED on error. + */ +TEE_Result bb_memdup_user(const void *src, size_t len, void **p); +#define BB_MEMDUP_USER(src, len, p) \ + __BB_MEMDUP(bb_memdup_user, (src), (len), (p)) + +/* + * bb_memdup_user_private() - Duplicate a private user-space buffer + * @src: Pointer to the user buffer to be duplicated. The buffer should + * be private to current TA (i.e., !TEE_MEMORY_ACCESS_ANY_OWNER). + * @len: Length of the user buffer to be duplicated. + * @p: Holds duplicated kernel buffer on success, or unchanged on failure. + * Note that the returned buffer is allocated by bb_alloc() and + * normally doesn't have to be freed. + * Return TEE_SUCCESS on success. + * Return TEE_ERROR_OUT_OF_MEMORY or TEE_ERROR_ACCESS_DENIED on error. + */ +TEE_Result bb_memdup_user_private(const void *src, size_t len, void **p); +#define BB_MEMDUP_USER_PRIVATE(src, len, p) \ + __BB_MEMDUP(bb_memdup_user_private, (src), (len), (p)) + +/* + * bb_strndup_user() - Duplicate a user-space string into a bounce buffer + * @src: Pointer to the user string to be duplicated. + * @maxlen: Maximum length of the user string + * @dst: Holds duplicated string on success, or unchanged on failure. + * @dstlen: Length of string, excluding the terminating zero, returned in + * @dst. + * + * Note that the returned buffer is allocated by bb_alloc() and normally + * doesn't have to be freed. But if it is to be freed the supplied length + * to bb_free() should be dstlen + 1. + * + * Return TEE_SUCCESS on success. + * Return TEE_ERROR_OUT_OF_MEMORY or TEE_ERROR_ACCESS_DENIED on error. + */ +TEE_Result bb_strndup_user(const char *src, size_t maxlen, char **dst, + size_t *dstlen); + +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); +} + +#define GET_USER_SCALAR(_x, _p) ({ \ + TEE_Result __res = TEE_SUCCESS; \ + typeof(_p) __p = (_p); \ + \ + static_assert(sizeof(_x) == sizeof(*__p)); \ + \ + __res = copy_from_user(&(_x), (const void *)__p, sizeof(*__p)); \ + __res; \ +}) + +#define PUT_USER_SCALAR(_x, _p) ({ \ + TEE_Result __res = TEE_SUCCESS; \ + typeof(_p) __p = (_p); \ + \ + static_assert(sizeof(_x) == sizeof(*__p)); \ + \ + __res = copy_to_user((void *)__p, &(_x), sizeof(*__p)); \ + __res; \ +}) + +#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..6c91f4e --- /dev/null +++ b/optee/optee_os/core/include/kernel/user_mode_ctx_struct.h @@ -0,0 +1,62 @@ +/* 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 + * @bbuf: Bounce buffer for user buffers + * @bbuf_size: Size of bounce buffer + * @bbuf_offs: Offset to unused part of bounce buffer + */ +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; + uint8_t *bbuf; + size_t bbuf_size; + size_t bbuf_offs; +}; +#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..667122b --- /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 __noprof 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..4097df4 --- /dev/null +++ b/optee/optee_os/core/include/kernel/virtualization.h @@ -0,0 +1,147 @@ +/* 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 +#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); + +/** + * virt_get_current_guest_id() - return current guest ID + * + * Returns current guest ID or 0 if none is set. + */ +uint16_t virt_get_current_guest_id(void); + +#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) { } +static inline uint16_t virt_get_current_guest_id(void) { return 0; } +#endif /*CFG_NS_VIRTUALIZATION*/ + +#if defined(CFG_CORE_SEL1_SPMC) && defined(CFG_NS_VIRTUALIZATION) +TEE_Result virt_add_cookie_to_current_guest(uint64_t cookie); +void virt_remove_cookie(uint64_t cookie); +uint16_t virt_find_guest_by_cookie(uint64_t cookie); +bitstr_t *virt_get_shm_bits(void); + +TEE_Result virt_reclaim_cookie_from_destroyed_guest(uint16_t guest_id, + uint64_t cookie); +#else +static inline TEE_Result +virt_add_cookie_to_current_guest(uint64_t cookie __unused) +{ return TEE_ERROR_NOT_SUPPORTED; } +static inline void virt_remove_cookie(uint64_t cookie __unused) { } +static inline uint16_t virt_find_guest_by_cookie(uint64_t cookie __unused) +{ return 0; } +static inline bitstr_t *virt_get_shm_bits(void) { return NULL; } +static inline TEE_Result +virt_reclaim_cookie_from_destroyed_guest(uint16_t guest_id __unused, + uint64_t cookie __unused) +{ return TEE_ERROR_NOT_SUPPORTED; } +#endif + +#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..20691e7 --- /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..a4839ab --- /dev/null +++ b/optee/optee_os/core/include/mm/core_memprot.h @@ -0,0 +1,142 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#ifndef __MM_CORE_MEMPROT_H +#define __MM_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); + +/* + * is_unpaged() - report unpaged status of an address + * @va: virtual address + * + * Returns true if the @va is non-NULL and is in the unpaged area if paging + * is enabled, else false. + */ +#ifdef CFG_WITH_PAGER +bool is_unpaged(const void *va); +#else +static inline bool is_unpaged(const void *va) { return va; } +#endif + +/* + * is_nexus() - report nexus status of an address + * @va: virtual address + * + * Returns true if the @va is non-NULL and is in the nexus memory area + * if ns-virtualization is enabled, else false. + */ +#ifdef CFG_NS_VIRTUALIZATION +bool is_nexus(const void *va); +#else +static inline bool is_nexus(const void *va) { return va; } +#endif + +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 /* __MM_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..b239c6f --- /dev/null +++ b/optee/optee_os/core/include/mm/core_mmu.h @@ -0,0 +1,698 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#ifndef __MM_CORE_MMU_H +#define __MM_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_NEX_NSEC_SHM: nexus non-secure 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_ROM_SEC: Secure read only memory 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_MANIFEST_DT: Memory loads manifest device tree + * MEM_AREA_TRANSFER_LIST: Memory area mapped for Transfer List + * 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_NEX_NSEC_SHM, + MEM_AREA_RAM_NSEC, + MEM_AREA_RAM_SEC, + MEM_AREA_ROM_SEC, + MEM_AREA_IO_NSEC, + MEM_AREA_IO_SEC, + MEM_AREA_EXT_DT, + MEM_AREA_MANIFEST_DT, + MEM_AREA_TRANSFER_LIST, + 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_NEX_NSEC_SHM] = "NEX_NSEC_SHM", + [MEM_AREA_RAM_NSEC] = "RAM_NSEC", + [MEM_AREA_RAM_SEC] = "RAM_SEC", + [MEM_AREA_ROM_SEC] = "ROM_SEC", + [MEM_AREA_IO_NSEC] = "IO_NSEC", + [MEM_AREA_IO_SEC] = "IO_SEC", + [MEM_AREA_EXT_DT] = "EXT_DT", + [MEM_AREA_MANIFEST_DT] = "MANIFEST_DT", + [MEM_AREA_TRANSFER_LIST] = "TRANSFER_LIST", + [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 + * @next_level: Finer grained translation table level according to @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 num_entries; +#ifdef CFG_NS_VIRTUALIZATION + struct mmu_partition *prtn; +#endif + uint8_t level; + uint8_t shift; + uint8_t next_level; +}; + +/* + * 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_va_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_va_range(vaddr_t va, size_t len, size_t granule); + +/* + * tlbi_va_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_va_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); +} + +/* + * 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); + +/* + * 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 /* __MM_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..3b73b00 --- /dev/null +++ b/optee/optee_os/core/include/mm/mobj.h @@ -0,0 +1,321 @@ +/* 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_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(uint64_t cookie, + 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_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..4f3e37e --- /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..aae35f8 --- /dev/null +++ b/optee/optee_os/core/include/mm/tee_mm.h @@ -0,0 +1,120 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#ifndef __MM_TEE_MM_H +#define __MM_TEE_MM_H + +#include +#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 pta_stats_alloc *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..d0faebf --- /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 __MM_TEE_MMU_TYPES_H +#define __MM_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..3c5b630 --- /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..16bafe8 --- /dev/null +++ b/optee/optee_os/core/include/mm/vm.h @@ -0,0 +1,100 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#ifndef __MM_VM_H +#define __MM_VM_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); + +/* + * 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 /*__MM_VM_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..5fa626b --- /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..0aacd8f --- /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..dc02a6f --- /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 __TA_PUB_KEY_H +#define __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 /*__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..cb41210 --- /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..d9ddb62 --- /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..2ed6791 --- /dev/null +++ b/optee/optee_os/core/include/tee/fs_dirfile.h @@ -0,0 +1,158 @@ +/* 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, uint32_t min_counter, + 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, + uint32_t *counter); +}; + +/** + * 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 + * @min_counter: the smallest accepted value in struct htree_image.counter + * @fops: file interface + * @dirh: returned dirfile handle + */ +TEE_Result tee_fs_dirfile_open(bool create, uint8_t *hash, uint32_t min_counter, + 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 + * @counter: version counter 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, uint32_t *counter); + +/** + * 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..19f9426 --- /dev/null +++ b/optee/optee_os/core/include/tee/fs_htree.h @@ -0,0 +1,177 @@ +/* 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 + * @min_counter: the smallest accepted value in struct htree_image.counter + * @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, uint32_t min_counter, + 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 + * @counter: ever increasing version counter 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, uint32_t *counter); + +/** + * 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..56321ed --- /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 __TEE_SVC_CACHE_H +#define __TEE_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 /*__TEE_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..33dd700 --- /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_core, + void *buf_user, 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..dbcca31 --- /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_TEE_CRYP_CONCAT_KDF_H +#define __TEE_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_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..adce9d8 --- /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_TEE_CRYP_HKDF_H +#define __TEE_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_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..d141032 --- /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_TEE_CRYP_PBKDF2_H +#define __TEE_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_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..7259cc3 --- /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_TEE_CRYP_UTL_H +#define __TEE_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..dd25e99 --- /dev/null +++ b/optee/optee_os/core/include/tee/tee_fs.h @@ -0,0 +1,122 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2022-2024, NVIDIA CORPORATION & AFFILIATES. + */ + +#ifndef __TEE_TEE_FS_H +#define __TEE_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_core, const void *data_user, + 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_core, void *buf_user, size_t *len); + TEE_Result (*write)(struct tee_file_handle *fh, size_t pos, + const void *buf_core, const void *buf_user, + 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_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..736dedf --- /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_TEE_FS_KEY_MANAGER_H +#define __TEE_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..8813295 --- /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_TEE_FS_RPC_H +#define __TEE_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_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..1c23dc0 --- /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_TEE_OBJ_H +#define __TEE_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..8fcd792 --- /dev/null +++ b/optee/optee_os/core/include/tee/tee_pobj.h @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#ifndef __TEE_TEE_POBJ_H +#define __TEE_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; + uint32_t obj_info_usage; + 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); + +/* + * Locks and unlocks a mutex intended to protect the obj_info_usage field + * in struct tee_pobj. + */ +void tee_pobj_lock_usage(struct tee_pobj *obj); +void tee_pobj_unlock_usage(struct tee_pobj *obj); + +#endif diff --git a/optee/optee_os/core/include/tee/tee_ree_state.h b/optee/optee_os/core/include/tee/tee_ree_state.h new file mode 100644 index 0000000..e78343c --- /dev/null +++ b/optee/optee_os/core/include/tee/tee_ree_state.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. + */ + +#ifndef __TEE_REE_STATE_H__ +#define __TEE_REE_STATE_H__ + +#include + +/* + * Helper functions for OT-TEE to tracking the normal world state. + */ + +typedef enum { + TEE_REE_STATE_UNKNOWN, + TEE_REE_STATE_BOOT, /* Early boot stage. */ + TEE_REE_STATE_REE_OS, /* OP-TEE driver ready. */ + TEE_REE_STATE_REE_SUPP, /* tee-supplicant ready. */ +} tee_ree_state; + +#ifdef CFG_REE_STATE +TEE_Result tee_set_ree_state(tee_ree_state state); +tee_ree_state tee_get_ree_state(void); +#else +static inline TEE_Result tee_set_ree_state(tee_ree_state state __unused) +{ + return TEE_SUCCESS; +} + +static inline tee_ree_state tee_get_ree_state(void) +{ + return TEE_REE_STATE_UNKNOWN; +} +#endif +#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..5e4688a --- /dev/null +++ b/optee/optee_os/core/include/tee/tee_supp_plugin_rpc.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2020, Open Mobile Platform LLC + */ + +#ifndef __TEE_TEE_SUPP_PLUGIN_RPC_H +#define __TEE_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_core, + void *buf_user, size_t len, + size_t *outlen); + +#endif /* __TEE_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..7c14765 --- /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_TEE_SVC_H +#define __TEE_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_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..526d6e6 --- /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_TEE_SVC_CRYP_H +#define __TEE_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_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..d30fce9 --- /dev/null +++ b/optee/optee_os/core/include/tee/tee_svc_storage.h @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2023, Linaro Limited + */ + +#ifndef __TEE_TEE_SVC_STORAGE_H +#define __TEE_TEE_SVC_STORAGE_H + +#include +#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); +TEE_Result tee_svc_storage_write_usage(struct tee_obj *o, uint32_t usage); + +void tee_svc_storage_init(void); + +#endif /* __TEE_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..e258679 --- /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_TEE_TA_ENC_MANAGER_H +#define __TEE_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..0f2d670 --- /dev/null +++ b/optee/optee_os/core/kernel/asan.c @@ -0,0 +1,285 @@ +// 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)); +} + +__inhibit_loop_to_libcall 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; +} + +__inhibit_loop_to_libcall +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/callout.c b/optee/optee_os/core/kernel/callout.c new file mode 100644 index 0000000..6a1b006 --- /dev/null +++ b/optee/optee_os/core/kernel/callout.c @@ -0,0 +1,188 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2024, Linaro Limited + */ + +#include +#include +#include +#include + +TAILQ_HEAD(callout_head, callout); + +static unsigned int callout_sched_lock __nex_data = SPINLOCK_UNLOCK; +static size_t callout_sched_core __nex_bss; +static unsigned int callout_lock __nex_data = SPINLOCK_UNLOCK; +static const struct callout_timer_desc *callout_desc __nex_bss; +static struct callout_head callout_head __nex_data = + TAILQ_HEAD_INITIALIZER(callout_head); + +static void insert_callout(struct callout *co) +{ + struct callout *co2 = NULL; + + TAILQ_FOREACH(co2, &callout_head, link) { + if (co->expiry_value < co2->expiry_value) { + TAILQ_INSERT_BEFORE(co2, co, link); + return; + } + } + + TAILQ_INSERT_TAIL(&callout_head, co, link); +} + +static void schedule_next_timeout(void) +{ + const struct callout_timer_desc *desc = callout_desc; + struct callout *co = TAILQ_FIRST(&callout_head); + + if (co) + desc->set_next_timeout(desc, co->expiry_value); + else + desc->disable_timeout(desc); + + if (desc->is_per_cpu) { + /* + * Remember which core is supposed to receive the next + * timer interrupt. This will not disable timers on other + * CPUs, instead they will be ignored as a spurious call. + */ + cpu_spin_lock(&callout_sched_lock); + callout_sched_core = get_core_pos(); + cpu_spin_unlock(&callout_sched_lock); + } +} + +static bool callout_is_active(struct callout *co) +{ + struct callout *co2 = NULL; + + TAILQ_FOREACH(co2, &callout_head, link) + if (co2 == co) + return true; + + return false; +} + +void callout_rem(struct callout *co) +{ + uint32_t state = 0; + + state = cpu_spin_lock_xsave(&callout_lock); + + if (callout_is_active(co)) { + TAILQ_REMOVE(&callout_head, co, link); + schedule_next_timeout(); + } + + cpu_spin_unlock_xrestore(&callout_lock, state); +} + +void callout_add(struct callout *co, bool (*callback)(struct callout *co), + uint32_t ms) +{ + const struct callout_timer_desc *desc = callout_desc; + uint32_t state = 0; + + state = cpu_spin_lock_xsave(&callout_lock); + + assert(is_nexus(co) && !callout_is_active(co) && is_unpaged(callback)); + *co = (struct callout){ .callback = callback, }; + + if (desc) { + co->period = desc->ms_to_ticks(desc, ms); + co->expiry_value = desc->get_now(desc) + co->period; + } else { + /* This will be converted to ticks in callout_service_init(). */ + co->period = ms; + } + + insert_callout(co); + if (desc && co == TAILQ_FIRST(&callout_head)) + schedule_next_timeout(); + + cpu_spin_unlock_xrestore(&callout_lock, state); +} + +void callout_set_next_timeout(struct callout *co, uint32_t ms) +{ + co->period = callout_desc->ms_to_ticks(callout_desc, ms); +} + +void callout_service_init(const struct callout_timer_desc *desc) +{ + struct callout_head tmp_head = TAILQ_HEAD_INITIALIZER(tmp_head); + struct callout *co = NULL; + uint32_t state = 0; + uint64_t now = 0; + + state = cpu_spin_lock_xsave(&callout_lock); + + assert(!callout_desc); + assert(is_nexus(desc) && is_unpaged(desc->disable_timeout) && + is_unpaged(desc->set_next_timeout) && + is_unpaged(desc->ms_to_ticks) && is_unpaged(desc->get_now)); + + callout_desc = desc; + now = desc->get_now(desc); + + TAILQ_CONCAT(&tmp_head, &callout_head, link); + while (!TAILQ_EMPTY(&tmp_head)) { + co = TAILQ_FIRST(&tmp_head); + TAILQ_REMOVE(&tmp_head, co, link); + + /* + * Periods set before the timer descriptor are in + * milliseconds since the frequency of the timer isn't + * available at that point. So update it to ticks now. + */ + co->period = desc->ms_to_ticks(desc, co->period); + co->expiry_value = now + co->period; + insert_callout(co); + } + schedule_next_timeout(); + + cpu_spin_unlock_xrestore(&callout_lock, state); +} + +void callout_service_cb(void) +{ + const struct callout_timer_desc *desc = callout_desc; + struct callout *co = NULL; + uint64_t now = 0; + + if (desc->is_per_cpu) { + bool do_callout = false; + + /* + * schedule_next_timeout() saves the core it was last + * called on. If there's a mismatch here it means that + * another core has been scheduled for the next callout, so + * there's no work to be done for this core. + */ + cpu_spin_lock(&callout_sched_lock); + do_callout = (get_core_pos() == callout_sched_core); + cpu_spin_unlock(&callout_sched_lock); + if (!do_callout) + return; + } + + cpu_spin_lock(&callout_lock); + + now = desc->get_now(desc); + while (!TAILQ_EMPTY(&callout_head)) { + co = TAILQ_FIRST(&callout_head); + if (co->expiry_value > now) + break; + + TAILQ_REMOVE(&callout_head, co, link); + + if (co->callback(co)) { + co->expiry_value += co->period; + insert_callout(co); + } + } + schedule_next_timeout(); + + cpu_spin_unlock(&callout_lock); +} diff --git a/optee/optee_os/core/kernel/console.c b/optee/optee_os/core/kernel/console.c new file mode 100644 index 0000000..ce44f07 --- /dev/null +++ b/optee/optee_os/core/kernel/console.c @@ -0,0 +1,181 @@ +// 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; + +/* May be overridden by platform */ +__weak void plat_console_init(void) +{ +} + +void console_init(void) +{ + if (IS_ENABLED(CFG_SEMIHOSTING_CONSOLE)) + semihosting_console_init(CFG_SEMIHOSTING_CONSOLE_FILE); + else + plat_console_init(); +} + +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..91d636e --- /dev/null +++ b/optee/optee_os/core/kernel/delay.c @@ -0,0 +1,77 @@ +// 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 +int timeout_elapsed_us(uint64_t expire) +{ + int64_t diff = delay_cnt_read() - expire; + + if (MUL_OVERFLOW(diff, 1000000, &diff) || + diff < INT_MIN || diff > INT_MAX) { + if (timeout_elapsed(expire)) + return INT_MAX; + else + return INT_MIN; + } + + return diff / delay_cnt_freq(); +} + +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..19f9fa5 --- /dev/null +++ b/optee/optee_os/core/kernel/dt.c @@ -0,0 +1,744 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct dt_descriptor external_dt __nex_bss; + +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; + } +} + +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*/ + +#ifdef _CFG_USE_DTB_OVERLAY +static int add_dt_overlay_fragment(struct dt_descriptor *dt, int ioffs) +{ + char frag[32] = { }; + int offs = 0; + int ret = 0; + + ret = snprintf(frag, sizeof(frag), "fragment@%d", dt->frag_id); + if (ret < 0 || (size_t)ret >= sizeof(frag)) + return -1; + + 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 ret; + + return fdt_add_subnode(dt->blob, offs, "__overlay__"); +} + +static int init_dt_overlay(struct dt_descriptor *dt, int __maybe_unused dt_size) +{ + int fragment = 0; + + 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 */ + +struct dt_descriptor *get_external_dt_desc(void) +{ + if (!IS_ENABLED(CFG_EXTERNAL_DT)) + return NULL; + + return &external_dt; +} + +void init_external_dt(unsigned long phys_dt, size_t dt_sz) +{ + struct dt_descriptor *dt = &external_dt; + int ret = 0; + enum teecore_memtypes mtype = MEM_AREA_MAXTYPE; + + if (!IS_ENABLED(CFG_EXTERNAL_DT)) + return; + + if (!phys_dt || !dt_sz) { + /* + * 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; + } + + mtype = core_mmu_get_type_by_pa(phys_dt); + if (mtype == MEM_AREA_MAXTYPE) { + /* Map the DTB if it is not yet mapped */ + dt->blob = core_mmu_add_mapping(MEM_AREA_EXT_DT, phys_dt, + dt_sz); + if (!dt->blob) + panic("Failed to map external DTB"); + } else { + /* Get the DTB address if already mapped in a memory area */ + dt->blob = phys_to_virt(phys_dt, mtype, dt_sz); + if (!dt->blob) { + EMSG("Failed to get a mapped external DTB for PA %#lx", + phys_dt); + panic(); + } + } + + ret = init_dt_overlay(dt, dt_sz); + if (ret < 0) { + EMSG("Device Tree Overlay init fail @ %#lx: error %d", phys_dt, + ret); + panic(); + } + + ret = fdt_open_into(dt->blob, dt->blob, dt_sz); + if (ret < 0) { + EMSG("Invalid Device Tree at %#lx: error %d", phys_dt, ret); + panic(); + } + + IMSG("Non-secure external DT found"); +} + +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; + paddr_t pa_dt = 0; + + if (!IS_ENABLED(CFG_EXTERNAL_DT)) + return TEE_SUCCESS; + + if (!external_dt.blob) + return TEE_SUCCESS; + + pa_dt = virt_to_phys(external_dt.blob); + /* + * Skip packing and un-mapping operations if the external DTB is mapped + * in a different memory area + */ + if (core_mmu_get_type_by_pa(pa_dt) != MEM_AREA_EXT_DT) + 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); + +int add_dt_path_subnode(struct dt_descriptor *dt, const char *path, + const char *subnode) +{ + int offs = 0; + + offs = fdt_path_offset(dt->blob, path); + if (offs < 0) + return offs; + offs = add_dt_overlay_fragment(dt, offs); + if (offs < 0) + return offs; + return fdt_add_subnode(dt->blob, offs, subnode); +} + +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)); + } +} + +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] = { }; + + 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 len_size; + addr_size = fdt_address_cells(dt->blob, offs); + if (addr_size < 0) + return addr_size; + } + + if (!found) { + offs = add_dt_path_subnode(dt, "/", "reserved-memory"); + if (offs < 0) + return offs; + ret = fdt_setprop_cell(dt->blob, offs, "#address-cells", + addr_size); + if (ret < 0) + return ret; + ret = fdt_setprop_cell(dt->blob, offs, "#size-cells", len_size); + if (ret < 0) + return ret; + ret = fdt_setprop(dt->blob, offs, "ranges", NULL, 0); + if (ret < 0) + return ret; + } + + 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 ret; + ret = fdt_setprop(dt->blob, offs, "no-map", NULL, 0); + if (ret < 0) + return ret; + } else { + return offs; + } + return 0; +} 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..c0160da --- /dev/null +++ b/optee/optee_os/core/kernel/dt_driver.c @@ -0,0 +1,914 @@ +// 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_GPIO: + case DT_DRIVER_I2C: + case DT_DRIVER_PINCTRL: + case DT_DRIVER_INTERRUPT: + case DT_DRIVER_REGULATOR: + case DT_DRIVER_NVMEM: + 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; +} + +static bool dt_driver_use_parent_controller(enum dt_driver_type type) +{ + switch (type) { + case DT_DRIVER_PINCTRL: + case DT_DRIVER_NVMEM: + return true; + default: + return false; + } +} + +/* + * 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; + + if (dt_driver_use_parent_controller(type)) + return 0; + + switch (type) { + case DT_DRIVER_CLK: + cells_name = "#clock-cells"; + break; + case DT_DRIVER_INTERRUPT: + cells_name = "#interrupt-cells"; + break; + case DT_DRIVER_RSTCTRL: + cells_name = "#reset-cells"; + break; + case DT_DRIVER_GPIO: + cells_name = "#gpio-cells"; + break; + case DT_DRIVER_I2C: + case DT_DRIVER_REGULATOR: + 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; +} + +void *dt_driver_provider_priv_data(struct dt_driver_provider *prv) +{ + return prv->priv_data; +} + +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 TEE_Result device_from_provider_prop(struct dt_driver_provider *prv, + const void *fdt, int phandle_node, + const uint32_t *prop, + void *device_ref) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct dt_pargs *pargs = NULL; + unsigned int n = 0; + + pargs = calloc(1, prv->provider_cells * sizeof(uint32_t *) + + sizeof(*pargs)); + if (!pargs) + return TEE_ERROR_OUT_OF_MEMORY; + + pargs->fdt = fdt; + pargs->phandle_node = phandle_node; + pargs->args_count = prv->provider_cells; + for (n = 0; n < prv->provider_cells; n++) { + assert(prop); + pargs->args[n] = fdt32_to_cpu(prop[n]); + } + + res = prv->get_of_device(pargs, prv->priv_data, device_ref); + + free(pargs); + + return res; +} + +TEE_Result dt_driver_device_from_parent(const void *fdt, int nodeoffset, + enum dt_driver_type type, + void *device_ref) +{ + int parent = -1; + struct dt_driver_provider *prv = NULL; + + assert(fdt == get_secure_dt()); + + parent = fdt_parent_offset(fdt, nodeoffset); + if (parent < 0) + return TEE_ERROR_GENERIC; + + prv = dt_driver_get_provider_by_node(parent, type); + if (!prv) { + /* No provider registered yet */ + return TEE_ERROR_DEFER_DRIVER_INIT; + } + + return device_from_provider_prop(prv, fdt, nodeoffset, NULL, + device_ref); +} + +TEE_Result dt_driver_device_from_node_idx_prop_phandle(const char *prop_name, + const void *fdt, + int nodeoffs, + unsigned int prop_index, + enum dt_driver_type type, + uint32_t phandle, + void *device_ref) +{ + int len = 0; + const uint32_t *prop = NULL; + int phandle_node_unused = -1; + struct dt_driver_provider *prv = NULL; + + prop = fdt_getprop(fdt, nodeoffs, prop_name, &len); + if (!prop) { + if (len != -FDT_ERR_NOTFOUND) { + DMSG("Corrupted node %s", prop_name); + return TEE_ERROR_GENERIC; + } else { + DMSG("Property %s missing in node %s", prop_name, + fdt_get_name(fdt, nodeoffs, NULL)); + return TEE_ERROR_ITEM_NOT_FOUND; + } + } + + prv = dt_driver_get_provider_by_phandle(phandle, type); + if (!prv) + return TEE_ERROR_DEFER_DRIVER_INIT; + + prop_index *= dt_driver_provider_cells(prv); + if ((prop_index + 1) * sizeof(*prop) > (size_t)len) + return TEE_ERROR_ITEM_NOT_FOUND; + + return device_from_provider_prop(prv, fdt, phandle_node_unused, + prop + prop_index, device_ref); +} + +TEE_Result 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, + void *device_ref) +{ + 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)); + return TEE_ERROR_ITEM_NOT_FOUND; + } + + 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; + } + + /* + * In some cases, pinctrl, i2c, nvmem, etc, the consumer phandle + * points directly to a subnode of the parent. In such cases, + * the provider does not have any "-cells" property and + * potentially no "phandle" property. + */ + if (dt_driver_use_parent_controller(type)) { + phandle_node = fdt_node_offset_by_phandle(fdt, phandle); + if (phandle_node < 0) + return TEE_ERROR_GENERIC; + + nodeoffset = fdt_parent_offset(fdt, phandle_node); + if (nodeoffset < 0) + return TEE_ERROR_GENERIC; + + prv = dt_driver_get_provider_by_node(nodeoffset, type); + } else { + prv = dt_driver_get_provider_by_phandle(phandle, type); + } + + if (prv) { + prv_cells = dt_driver_provider_cells(prv); + } else if (prop_idx) { + /* + * When we need to skip another provider phandle + * arguments cells (aka when prop_idx != 0), we don't + * really need the skipped provider to be already + * registered, we can look straight in its DT node. + */ + phandle_node = fdt_node_offset_by_phandle(fdt, phandle); + if (phandle_node < 0) { + DMSG("Can't find node for phandle %"PRIu32, + phandle); + return TEE_ERROR_GENERIC; + } + + prv_cells = fdt_get_dt_driver_cells(fdt, phandle_node, + type); + if (prv_cells < 0) { + DMSG("Can't find cells count on node %s: %d", + fdt_get_name(fdt, phandle_node, NULL), + prv_cells); + return TEE_ERROR_GENERIC; + } + } + + if (prop_idx) { + prop_idx--; + idx += sizeof(phandle) + prv_cells * sizeof(uint32_t); + continue; + } + + if (!prv) + return TEE_ERROR_DEFER_DRIVER_INIT; + + /* Skip property cell with the phandle, already handled */ + idx32++; + + return device_from_provider_prop(prv, fdt, phandle_node, + prop + idx32, device_ref); + } + + return TEE_ERROR_ITEM_NOT_FOUND; +} + +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", drv_name, node_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); + 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/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..9392260 --- /dev/null +++ b/optee/optee_os/core/kernel/embedded_ts.c @@ -0,0 +1,223 @@ +// 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 +#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_core, + void *data_user, size_t len) +{ + TEE_Result res = TEE_SUCCESS; + 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_core) + memcpy(data_core, src, len); + if (data_user) + res = copy_to_user(data_user, src, len); + if (!res) + h->offs = next_offs; + + return res; +} + +static TEE_Result read_compressed(struct ts_store_handle *h, void *data_core, + void *data_user, size_t len) +{ + TEE_Result res = TEE_SUCCESS; + z_stream *strm = &h->strm; + size_t total = 0; + uint8_t *bb = NULL; + size_t bb_len = 0; + size_t out = 0; + int st = Z_OK; + + /* Inflate into a 1kB bounce buffer */ + bb_len = MIN(len, 1024U); + bb = bb_alloc(bb_len); + if (!bb) { + EMSG("Out of memory"); + return TEE_ERROR_OUT_OF_MEMORY; + } + + strm->avail_out = bb_len; + strm->next_out = bb; + + /* + * 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; + FMSG("%zu bytes", out); + if (data_core) + memcpy((uint8_t *)data_core + total, bb, out); + if (data_user) { + res = copy_to_user((uint8_t *)data_user + total, bb, + out); + if (res) + goto out; + } + total += out; + /* + * Reset the pointer since we've just copied out the last + * data. + */ + strm->next_out = bb; + strm->avail_out = MIN(len - total, bb_len); + } while ((st == Z_OK || st == Z_BUF_ERROR) && (total != len)); + + if (st != Z_OK && st != Z_STREAM_END) { + EMSG("Decompression error (%d)", st); + res = TEE_ERROR_GENERIC; + goto out; + } + res = TEE_SUCCESS; +out: + bb_free(bb, bb_len); + + return res; +} + +TEE_Result emb_ts_read(struct ts_store_handle *h, void *data_core, + void *data_user, size_t len) +{ + if (h->ts->uncompressed_size) + return read_compressed(h, data_core, data_user, len); + else + return read_uncompressed(h, data_core, data_user, 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..66b1447 --- /dev/null +++ b/optee/optee_os/core/kernel/huk_subkey.c @@ -0,0 +1,112 @@ +// 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; +} + +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) +__weak __alias("__huk_subkey_derive"); 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..4fe92bd --- /dev/null +++ b/optee/optee_os/core/kernel/interrupt.c @@ -0,0 +1,352 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016-2019, Linaro Limited + */ + +#include +#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_main_chip __nex_bss; + +TEE_Result itr_chip_init(struct itr_chip *chip) +{ + if (!itr_chip_is_valid(chip)) + return TEE_ERROR_BAD_PARAMETERS; + + SLIST_INIT(&chip->handlers); + + return TEE_SUCCESS; +} + +void interrupt_main_init(struct itr_chip *chip) +{ + if (itr_chip_init(chip)) + panic(); + + itr_main_chip = chip; +} + +struct itr_chip *interrupt_get_main_chip(void) +{ + assert(itr_main_chip); + return itr_main_chip; +} + +struct itr_chip *interrupt_get_main_chip_may_fail(void) +{ + return itr_main_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_main_chip || !itr_main_chip->dt_get_irq) + return it_num; + + prop = fdt_getprop(fdt, node, "interrupts", &count); + if (!prop) + return it_num; + + return itr_main_chip->dt_get_irq(prop, count, type, prio); +} +#endif + +/* This function is supposed to be overridden in platform specific code */ +void __weak __noreturn interrupt_main_handler(void) +{ + panic("Secure interrupt handler not defined"); +} + +/* + * Interrupt controller chip support + */ +void interrupt_call_handlers(struct itr_chip *chip, size_t itr_num) +{ + struct itr_handler *h = NULL; + bool was_handled = false; + + assert(chip); + + SLIST_FOREACH(h, &chip->handlers, link) { + if (h->it == itr_num) { + if (h->handler(h) == ITRR_HANDLED) + was_handled = true; + else if (!(h->flags & ITRF_SHARED)) + break; + } + } + + if (!was_handled) { + EMSG("Mask unhandled interrupt %s:%zu", chip->name, itr_num); + interrupt_mask(chip, itr_num); + } +} + +TEE_Result interrupt_configure(struct itr_chip *chip, size_t itr_num, + uint32_t type, uint32_t prio) +{ + chip->ops->add(chip, itr_num, type, prio); + + return TEE_SUCCESS; +} + +static TEE_Result add_configure_handler(struct itr_handler *hdl, + uint32_t type, uint32_t prio, + bool configure) +{ + struct itr_handler *h = NULL; + + assert(hdl && hdl->chip->ops && is_unpaged(hdl) && + hdl->handler && is_unpaged(hdl->handler)); + + SLIST_FOREACH(h, &hdl->chip->handlers, link) { + if (h->it == hdl->it && + (!(hdl->flags & ITRF_SHARED) || + !(h->flags & ITRF_SHARED))) { + EMSG("Shared and non-shared flags on interrupt %s#%zu", + hdl->chip->name, hdl->it); + return TEE_ERROR_GENERIC; + } + } + + if (configure) + interrupt_configure(hdl->chip, hdl->it, type, prio); + + SLIST_INSERT_HEAD(&hdl->chip->handlers, hdl, link); + + return TEE_SUCCESS; +} + +TEE_Result interrupt_add_configure_handler(struct itr_handler *hdl, + uint32_t type, uint32_t prio) +{ + return add_configure_handler(hdl, type, prio, true /* configure */); +} + +TEE_Result interrupt_create_handler(struct itr_chip *itr_chip, size_t itr_num, + itr_handler_t callback, void *priv, + uint32_t flags, + struct itr_handler **out_hdl) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct itr_handler *itr_hdl = NULL; + + itr_hdl = calloc(1, sizeof(*itr_hdl)); + if (!itr_hdl) + return TEE_ERROR_OUT_OF_MEMORY; + + *itr_hdl = (struct itr_handler){ + .chip = itr_chip, + .it = itr_num, + .flags = flags, + .handler = callback, + .data = priv, + }; + + res = add_configure_handler(itr_hdl, 0, 0, false /* configure */); + if (res) { + free(itr_hdl); + return res; + } + + if (out_hdl) + *out_hdl = itr_hdl; + + return TEE_SUCCESS; +} + +void interrupt_remove_handler(struct itr_handler *hdl) +{ + struct itr_handler *h = NULL; + bool disable_itr = true; + + if (!hdl) + return; + + SLIST_FOREACH(h, &hdl->chip->handlers, link) + if (h == hdl) + break; + if (!h) { + DMSG("Invalid %s:%zu", hdl->chip->name, hdl->it); + assert(false); + return; + } + + if (hdl->flags & ITRF_SHARED) { + SLIST_FOREACH(h, &hdl->chip->handlers, link) { + if (h != hdl && h->it == hdl->it) { + disable_itr = false; + break; + } + } + } + + if (disable_itr) + interrupt_disable(hdl->chip, hdl->it); + + SLIST_REMOVE(&hdl->chip->handlers, hdl, itr_handler, link); +} + +TEE_Result interrupt_alloc_add_conf_handler(struct itr_chip *chip, + size_t itr_num, + itr_handler_t handler, + uint32_t flags, void *data, + uint32_t type, uint32_t prio, + struct itr_handler **out_hdl) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct itr_handler *hdl = NULL; + + hdl = calloc(1, sizeof(*hdl)); + if (!hdl) + return TEE_ERROR_OUT_OF_MEMORY; + + *hdl = ITR_HANDLER(chip, itr_num, flags, handler, data); + + res = interrupt_add_configure_handler(hdl, type, prio); + if (res) { + free(hdl); + return res; + } + + if (out_hdl) + *out_hdl = hdl; + + return TEE_SUCCESS; +} + +void interrupt_remove_free_handler(struct itr_handler *hdl) +{ + if (hdl) { + interrupt_remove_handler(hdl); + free(hdl); + } +} + +#ifdef CFG_DT +TEE_Result interrupt_register_provider(const void *fdt, int node, + itr_dt_get_func dt_get_itr, void *data) +{ + return dt_driver_register_provider(fdt, node, + (get_of_device_func)dt_get_itr, + data, DT_DRIVER_INTERRUPT); +} + +/* + * Fills an itr_desc reference based on "interrupts" property bindings. + * May return TEE_ERROR_DEFER_DRIVER_INIT if parent controller is found but + * not yet initialized. + */ +static TEE_Result get_legacy_interrupt_by_index(const void *fdt, int node, + unsigned int index, + struct itr_desc *itr_desc) +{ + const uint32_t *prop = NULL; + uint32_t phandle = 0; + int pnode = 0; + int len = 0; + + prop = fdt_getprop(fdt, node, "interrupts", &len); + if (!prop) + return TEE_ERROR_ITEM_NOT_FOUND; + + /* Find "interrupt-parent" in node or its parents */ + pnode = node; + prop = fdt_getprop(fdt, pnode, "interrupt-parent", &len); + + while (!prop) { + pnode = fdt_parent_offset(fdt, pnode); + if (pnode < 0) + break; + + prop = fdt_getprop(fdt, pnode, "interrupt-parent", &len); + if (!prop && len != -FDT_ERR_NOTFOUND) + break; + } + if (!prop) { + DMSG("No interrupt parent for node %s", + fdt_get_name(fdt, node, NULL)); + return TEE_ERROR_GENERIC; + } + + /* "interrupt-parent" provides interrupt controller phandle */ + phandle = fdt32_to_cpu(prop[0]); + + /* Get interrupt chip/number from phandle and "interrupts" property */ + return dt_driver_device_from_node_idx_prop_phandle("interrupts", fdt, + node, index, + DT_DRIVER_INTERRUPT, + phandle, + itr_desc); +} + +/* + * Fills an itr_desc based on "interrupts-extended" property bindings. + * May return TEE_ERROR_DEFER_DRIVER_INIT if parent controller is found + * but not yet initialized. + */ +static TEE_Result get_extended_interrupt_by_index(const void *fdt, int node, + unsigned int index, + struct itr_desc *itr_desc) +{ + return dt_driver_device_from_node_idx_prop("interrupts-extended", + fdt, node, index, + DT_DRIVER_INTERRUPT, + itr_desc); +} + +TEE_Result interrupt_dt_get_by_index(const void *fdt, int node, + unsigned int index, struct itr_chip **chip, + size_t *itr_num) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct itr_desc desc = { }; + + assert(chip && itr_num); + + /* "interrupts-extended" takes precedence over "interrupts" */ + if (fdt_getprop(fdt, node, "interrupts-extended", NULL)) + res = get_extended_interrupt_by_index(fdt, node, index, &desc); + else + res = get_legacy_interrupt_by_index(fdt, node, index, &desc); + + if (!res) { + assert(desc.chip); + *chip = desc.chip; + *itr_num = desc.itr_num; + } + + return res; +} + +TEE_Result interrupt_dt_get_by_name(const void *fdt, int node, const char *name, + struct itr_chip **chip, size_t *itr_num) +{ + int idx = 0; + + idx = fdt_stringlist_search(fdt, node, "interrupt-names", name); + if (idx < 0) + return TEE_ERROR_GENERIC; + + return interrupt_dt_get_by_index(fdt, node, idx, chip, itr_num); +} +#endif /*CFG_DT*/ 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..cf00f7d --- /dev/null +++ b/optee/optee_os/core/kernel/ldelf_loader.c @@ -0,0 +1,477 @@ +// 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 +#include + +#define BOUNCE_BUFFER_SIZE 4096 + +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_fobj(struct user_mode_ctx *uctx, size_t sz, + uint32_t prot, uint32_t flags, 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, flags, 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; + vaddr_t bb_addr = 0; + uint32_t prot = 0; + + uctx->is_32bit = is_32bit; + + res = alloc_and_map_fobj(uctx, BOUNCE_BUFFER_SIZE, TEE_MATTR_PRW, 0, + &bb_addr); + if (res) + return res; + uctx->bbuf = (void *)bb_addr; + uctx->bbuf_size = BOUNCE_BUFFER_SIZE; + + res = alloc_and_map_fobj(uctx, LDELF_STACK_SIZE, + TEE_MATTR_URW | TEE_MATTR_PRW, VM_FLAG_LDELF, + &stack_addr); + if (res) + return res; + uctx->ldelf_stack_ptr = stack_addr + LDELF_STACK_SIZE; + + res = alloc_and_map_fobj(uctx, ldelf_code_size, TEE_MATTR_PRW, + VM_FLAG_LDELF, &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_fobj(uctx, ldelf_data_size, + TEE_MATTR_URW | TEE_MATTR_PRW, VM_FLAG_LDELF, + &rw_addr); + if (res) + return res; + + vm_set_ctx(uctx->ts_ctx); + + memcpy((void *)code_addr, ldelf_data, ldelf_code_size); + + res = copy_to_user((void *)rw_addr, ldelf_data + ldelf_code_size, + ldelf_data_size); + if (res) + return res; + + 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; + struct ldelf_arg *arg_bbuf = NULL; + + usr_stack = uctx->ldelf_stack_ptr; + usr_stack -= ROUNDUP(sizeof(*arg), STACK_ALIGNMENT); + arg = (struct ldelf_arg *)usr_stack; + sess->handle_scall = scall_handle_ldelf; + + res = clear_user(arg, sizeof(*arg)); + if (res) + return res; + + res = PUT_USER_SCALAR(uctx->ts_ctx->uuid, &arg->uuid); + if (res) + return res; + + 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 = BB_MEMDUP_USER(arg, sizeof(*arg), &arg_bbuf); + 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_bbuf->flags & ~TA_FLAGS_MASK) + return TEE_ERROR_BAD_FORMAT; + + to_user_ta_ctx(uctx->ts_ctx)->ta_ctx.flags = arg_bbuf->flags; + } + + uctx->is_32bit = arg_bbuf->is_32bit; + uctx->entry_func = arg_bbuf->entry_func; + uctx->load_addr = arg_bbuf->load_addr; + uctx->stack_ptr = arg_bbuf->stack_ptr; + uctx->dump_entry_func = arg_bbuf->dump_entry; +#ifdef CFG_FTRACE_SUPPORT + uctx->ftrace_entry_func = arg_bbuf->ftrace_entry; + sess->fbuf = arg_bbuf->fbuf; +#endif + uctx->dl_entry_func = arg_bbuf->dl_entry; + + bb_free(arg_bbuf, sizeof(*arg)); + + 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 arg_size = 0; + size_t n = 0; + + TAILQ_FOREACH(r, &uctx->vm_info.regions, link) + if (r->attr & TEE_MATTR_URWX) + n++; + + arg_size = ROUNDUP(sizeof(*arg) + n * sizeof(struct dump_map), + STACK_ALIGNMENT); + + usr_stack = uctx->ldelf_stack_ptr; + usr_stack -= arg_size; + + arg = bb_alloc(arg_size); + if (!arg) + return TEE_ERROR_OUT_OF_MEMORY; + memset(arg, 0, arg_size); + + 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*/ + + res = copy_to_user((void *)usr_stack, arg, arg_size); + if (res) + return res; + + sess = ts_get_current_session(); + sess->handle_scall = scall_handle_ldelf; + + res = thread_enter_user_mode(usr_stack, 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 *usr_arg = NULL; + struct dl_entry_arg *arg = NULL; + uint32_t panic_code = 0; + uint32_t panicked = 0; + struct ts_session *sess = NULL; + + assert(uuid); + + arg = bb_alloc(sizeof(*arg)); + if (!arg) + return TEE_ERROR_OUT_OF_MEMORY; + + memset(arg, 0, sizeof(*arg)); + arg->cmd = LDELF_DL_ENTRY_DLOPEN; + arg->dlopen.uuid = *uuid; + arg->dlopen.flags = flags; + + usr_stack -= ROUNDUP(sizeof(*arg), STACK_ALIGNMENT); + usr_arg = (void *)usr_stack; + + res = copy_to_user(usr_arg, arg, sizeof(*arg)); + if (res) + return res; + + sess = ts_get_current_session(); + sess->handle_scall = scall_handle_ldelf; + + res = thread_enter_user_mode(usr_stack, 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) { + TEE_Result res2 = TEE_SUCCESS; + + res2 = GET_USER_SCALAR(res, &usr_arg->ret); + if (res2) + res = res2; + } + + return res; +} + +TEE_Result ldelf_dlsym(struct user_mode_ctx *uctx, TEE_UUID *uuid, + const char *sym, size_t symlen, vaddr_t *val) +{ + uaddr_t usr_stack = uctx->ldelf_stack_ptr; + TEE_Result res = TEE_ERROR_GENERIC; + struct dl_entry_arg *usr_arg = NULL; + struct dl_entry_arg *arg = NULL; + uint32_t panic_code = 0; + uint32_t panicked = 0; + struct ts_session *sess = NULL; + + usr_stack -= ROUNDUP(sizeof(*arg) + symlen + 1, STACK_ALIGNMENT); + usr_arg = (void *)usr_stack; + arg = bb_alloc(sizeof(*arg)); + if (!arg) + return TEE_ERROR_OUT_OF_MEMORY; + memset(arg, 0, sizeof(*arg)); + arg->cmd = LDELF_DL_ENTRY_DLSYM; + arg->dlsym.uuid = *uuid; + res = copy_to_user(usr_arg, arg, sizeof(*arg)); + if (res) + return res; + res = copy_to_user(usr_arg->dlsym.symbol, sym, symlen + 1); + if (res) + return res; + + sess = ts_get_current_session(); + sess->handle_scall = scall_handle_ldelf; + + res = thread_enter_user_mode((vaddr_t)usr_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) { + TEE_Result res2 = TEE_SUCCESS; + + res2 = GET_USER_SCALAR(res, &usr_arg->ret); + if (res2) + res = res2; + if (!res) + res = GET_USER_SCALAR(*val, &usr_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..1c4fcef --- /dev/null +++ b/optee/optee_os/core/kernel/ldelf_syscalls.c @@ -0,0 +1,612 @@ +// 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 +#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; +}; + +static void unmap_or_panic(struct user_mode_ctx *uctx, vaddr_t va, + size_t byte_count) +{ + TEE_Result res = vm_unmap(uctx, va, byte_count); + + if (res) { + EMSG("vm_unmap(%#"PRIxVA", %#zx) returned %#"PRIx32, + va, byte_count, res); + panic("Can't restore memory map"); + } +} + +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; + vaddr_t va_copy = 0; + + if (flags & ~LDELF_MAP_FLAG_SHAREABLE) + return TEE_ERROR_BAD_PARAMETERS; + + res = GET_USER_SCALAR(va_copy, va); + if (res) + return res; + + 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_copy, num_bytes, prot, vm_flags, + mobj, 0, pad_begin, pad_end, 0); + mobj_put(mobj); + if (!res) { + res = PUT_USER_SCALAR(va_copy, va); + if (res) + unmap_or_panic(uctx, va_copy, num_bytes); + } + + 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); + TEE_UUID *bb_uuid = NULL; + int h = 0; + + res = BB_MEMDUP_USER(uuid, sizeof(*uuid), &bb_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 *)bb_uuid, binh->op->description); + + res = binh->op->open(bb_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 *)bb_uuid, binh->op->description); + + res = binh->op->open(bb_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; + res = PUT_USER_SCALAR(h, handle); + if (res) { + handle_put(&sys_ctx->db, h); + goto err; + } + + 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, 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_core, + vaddr_t va_user, 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, 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_core, + (void *)va_user, rb); + if (res) + return res; + if (va_core) + memset((uint8_t *)va_core + rb, 0, num_bytes - rb); + if (va_user) { + res = clear_user((uint8_t *)va_user + rb, + num_bytes - rb); + if (res) + return res; + } + binh->offs_bytes = binh->size_bytes; + } else { + res = binh->op->read(binh->h, (void *)va_core, + (void *)va_user, 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; + vaddr_t va_copy = 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; + + res = GET_USER_SCALAR(va_copy, va); + 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; + + 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_copy, 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_copy, 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_copy, 0, offs_bytes, num_bytes); + if (res) + goto err_unmap_va; + res = vm_set_prot(uctx, va_copy, 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; + } + } + + res = PUT_USER_SCALAR(va_copy, va); + if (res) + goto err_unmap_va; + + file_unlock(binh->f); + + return TEE_SUCCESS; + +err_unmap_va: + unmap_or_panic(uctx, va_copy, num_rounded_bytes); + + /* + * 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, 0, (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; + vaddr_t va_copy = 0; + + res = GET_USER_SCALAR(va_copy, new_va); + if (res) + return res; + 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, &va_copy, old_va, num_bytes, pad_begin, pad_end); + if (res) + return res; + + res = PUT_USER_SCALAR(va_copy, new_va); + if (res) { + TEE_Result res2 = TEE_SUCCESS; + vaddr_t va = old_va; + + res2 = vm_remap(uctx, &va, va_copy, num_bytes, 0, 0); + if (res2) { + EMSG("vm_remap(%#"PRIxVA", %#"PRIxVA", %#zx) returned %#"PRIx32, + va, va_copy, num_bytes, res2); + panic("Can't restore memory map"); + } + return res; + } + + return TEE_SUCCESS; +} + +TEE_Result ldelf_syscall_gen_rnd_num(void *buf, size_t num_bytes) +{ + TEE_Result res = TEE_SUCCESS; + void *bb = NULL; + + bb = bb_alloc(num_bytes); + if (!bb) + return TEE_ERROR_OUT_OF_MEMORY; + + res = crypto_rng_read(bb, num_bytes); + if (res) + return res; + + return copy_to_user(buf, bb, 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..dfdb759 --- /dev/null +++ b/optee/optee_os/core/kernel/mutex.c @@ -0,0 +1,490 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015-2017, Linaro Limited + */ + +#include +#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 mutex_pm_aware_init(struct mutex_pm_aware *m) +{ + *m = (struct mutex_pm_aware)MUTEX_PM_AWARE_INITIALIZER; +} + +void mutex_pm_aware_destroy(struct mutex_pm_aware *m) +{ + mutex_destroy(&m->mutex); +} + +void mutex_pm_aware_lock(struct mutex_pm_aware *m) +{ + if (thread_get_id_may_fail() == THREAD_ID_INVALID) { + if (!cpu_spin_trylock(&m->lock) || m->mutex.state) + panic(); + } else { + mutex_lock(&m->mutex); + if (!thread_spin_trylock(&m->lock)) + panic(); + } +} + +void mutex_pm_aware_unlock(struct mutex_pm_aware *m) +{ + if (thread_get_id_may_fail() == THREAD_ID_INVALID) { + assert(!m->mutex.state); + cpu_spin_unlock(&m->lock); + } else { + thread_spin_unlock(&m->lock); + mutex_unlock(&m->mutex); + } +} + +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..f2fcc32 --- /dev/null +++ b/optee/optee_os/core/kernel/notif.c @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021-2023, Linaro Limited + */ + +#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 __nex_data = SPINLOCK_UNLOCK; +static bool notif_started; + +SLIST_HEAD(notif_driver_head, notif_driver); +static struct notif_driver_head notif_driver_head __nex_data = + SLIST_HEAD_INITIALIZER(¬if_driver_head); + + +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; + + assert(is_nexus(ndrv) && is_unpaged(ndrv->atomic_cb)); + + 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/notif_default.c b/optee/optee_os/core/kernel/notif_default.c new file mode 100644 index 0000000..6f73b77 --- /dev/null +++ b/optee/optee_os/core/kernel/notif_default.c @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021-2023, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include + +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 unsigned int notif_default_lock = SPINLOCK_UNLOCK; + +TEE_Result notif_alloc_async_value(uint32_t *val) +{ + static bool alloc_values_inited; + uint32_t old_itr_status = 0; + int bit = 0; + + assert(interrupt_can_raise_pi(interrupt_get_main_chip())); + + old_itr_status = cpu_spin_lock_xsave(¬if_default_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_default_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_default_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_default_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_default_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_default_lock, old_itr_status); + + return res; +} + +void notif_send_async(uint32_t value) +{ + uint32_t old_itr_status = 0; + struct itr_chip *itr_chip = interrupt_get_main_chip(); + + assert(value <= NOTIF_ASYNC_VALUE_MAX); + old_itr_status = cpu_spin_lock_xsave(¬if_default_lock); + + bit_set(notif_values, value); + interrupt_raise_pi(itr_chip, CFG_CORE_ASYNC_NOTIF_GIC_INTID); + + cpu_spin_unlock_xrestore(¬if_default_lock, old_itr_status); +} diff --git a/optee/optee_os/core/kernel/nv_counter.c b/optee/optee_os/core/kernel/nv_counter.c new file mode 100644 index 0000000..ce397f2 --- /dev/null +++ b/optee/optee_os/core/kernel/nv_counter.c @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2023, Linaro Limited + */ + +#include +#include + +TEE_Result __weak nv_counter_get_ree_fs(uint32_t *value __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +TEE_Result __weak nv_counter_incr_ree_fs_to(uint32_t value __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} 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..17d4bb0 --- /dev/null +++ b/optee/optee_os/core/kernel/panic.c @@ -0,0 +1,92 @@ +// 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 + +/* SGI number chosen to halt other cores must be in the secure SGI range */ +static_assert(!IS_ENABLED(CFG_HALT_CORES_ON_PANIC) || + (CFG_HALT_CORES_ON_PANIC_SGI >= 8 && + CFG_HALT_CORES_ON_PANIC_SGI < 16)); + +static enum itr_return __noreturn +multi_core_panic_it_handler(struct itr_handler *hdl __unused) +{ + IMSG("Halting CPU %zu", get_core_pos()); + + while (true) + cpu_idle(); +} + +static struct itr_handler multi_core_panic_handler __nex_data = { + .it = CFG_HALT_CORES_ON_PANIC_SGI, + .handler = multi_core_panic_it_handler, +}; +DECLARE_KEEP_PAGER(multi_core_panic_handler); + +static void notify_other_cores(void) +{ + struct itr_chip *chip = interrupt_get_main_chip_may_fail(); + + if (chip) + interrupt_raise_sgi(chip, CFG_HALT_CORES_ON_PANIC_SGI, + ITR_CPU_MASK_TO_OTHER_CPUS); + else + EMSG("Can't notify other cores, main interrupt chip not set"); +} + +static TEE_Result init_multi_core_panic_handler(void) +{ + if (!IS_ENABLED(CFG_HALT_CORES_ON_PANIC) || CFG_TEE_CORE_NB_CORE == 1) + return TEE_SUCCESS; + + if (interrupt_add_handler_with_chip(interrupt_get_main_chip(), + &multi_core_panic_handler)) + panic(); + + interrupt_enable(interrupt_get_main_chip(), + multi_core_panic_handler.it); + + return TEE_SUCCESS; +} + +nex_driver_init_late(init_multi_core_panic_handler); + +void __do_panic(const char *file __maybe_unused, + const int line __maybe_unused, + const char *func __maybe_unused, + const char *msg __maybe_unused) +{ + /* disable preemption */ + (void)thread_mask_exceptions(THREAD_EXCP_ALL); + + /* 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(); + + if (IS_ENABLED(CFG_HALT_CORES_ON_PANIC) && CFG_TEE_CORE_NB_CORE > 1) + notify_other_cores(); + + /* 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..828a1d8 --- /dev/null +++ b/optee/optee_os/core/kernel/pseudo_ta.c @@ -0,0 +1,422 @@ +// 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 +#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 __noprof 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; +} + +TEE_Result to_bounce_params(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS], + TEE_Param bparams[TEE_NUM_PARAMS], + TEE_Param **oparams) +{ + TEE_Result res = TEE_ERROR_GENERIC; + void *kptr = NULL; + void *uptr = NULL; + size_t size = 0; + int i = 0; + + if (!is_caller_ta_with_pan()) { + *oparams = params; + return TEE_SUCCESS; + } + + for (i = 0; i < TEE_NUM_PARAMS; i++) { + switch (TEE_PARAM_TYPE_GET(param_types, i)) { + case TEE_PARAM_TYPE_MEMREF_INPUT: + case TEE_PARAM_TYPE_MEMREF_OUTPUT: + case TEE_PARAM_TYPE_MEMREF_INOUT: + size = params[i].memref.size; + uptr = params[i].memref.buffer; + kptr = bb_alloc(size); + if (!kptr) + return TEE_ERROR_OUT_OF_MEMORY; + bparams[i].memref.buffer = kptr; + bparams[i].memref.size = size; + break; + default: + break; + } + switch (TEE_PARAM_TYPE_GET(param_types, i)) { + case TEE_PARAM_TYPE_MEMREF_INPUT: + case TEE_PARAM_TYPE_MEMREF_INOUT: + res = copy_from_user(kptr, uptr, size); + if (res) + return res; + break; + case TEE_PARAM_TYPE_VALUE_INPUT: + case TEE_PARAM_TYPE_VALUE_INOUT: + bparams[i].value.a = params[i].value.a; + bparams[i].value.b = params[i].value.b; + break; + default: + break; + } + } + *oparams = bparams; + + return TEE_SUCCESS; +} + +TEE_Result from_bounce_params(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS], + TEE_Param bparams[TEE_NUM_PARAMS], + TEE_Param *eparams) +{ + TEE_Result res = TEE_ERROR_GENERIC; + void *kptr = NULL; + void *uptr = NULL; + size_t size = 0; + int i = 0; + + if (eparams == params) + return TEE_SUCCESS; + + for (i = 0; i < TEE_NUM_PARAMS; i++) { + switch (TEE_PARAM_TYPE_GET(param_types, i)) { + case TEE_PARAM_TYPE_MEMREF_OUTPUT: + case TEE_PARAM_TYPE_MEMREF_INOUT: + uptr = params[i].memref.buffer; + kptr = bparams[i].memref.buffer; + size = bparams[i].memref.size; + res = copy_to_user(uptr, kptr, size); + if (res) + return res; + params[i].memref.size = size; + break; + case TEE_PARAM_TYPE_VALUE_OUTPUT: + case TEE_PARAM_TYPE_VALUE_INOUT: + params[i].value.a = bparams[i].value.a; + params[i].value.b = bparams[i].value.b; + break; + default: + break; + } + } + + return res; +} 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..c36fb50 --- /dev/null +++ b/optee/optee_os/core/kernel/ree_fs_ta.c @@ -0,0 +1,822 @@ +// 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, NULL, + 0, &fh); + if (res != TEE_SUCCESS) + goto out; + + res = ops->write(fh, 0, &db_hdr, NULL, sizeof(db_hdr)); + if (res != TEE_SUCCESS) + goto out; + } else { + len = sizeof(db_hdr); + + res = ops->read(fh, 0, &db_hdr, NULL, &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, + NULL, &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, NULL, 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, NULL, len); + if (res != TEE_SUCCESS) + goto out; + + db_hdr.nb_entries++; + res = ops->write(fh, 0, &db_hdr, NULL, 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_core, + void *data_user, 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 bb_len = MIN(1024U, len); + size_t next_offs = 0; + TEE_Result res = TEE_SUCCESS; + size_t num_bytes = 0; + size_t dst_len = 0; + void *dst = NULL; + void *bb = NULL; + + + if (ADD_OVERFLOW(handle->offs, len, &next_offs) || + next_offs > handle->nw_ta_size) + return TEE_ERROR_BAD_PARAMETERS; + + if (data_core) { + dst = data_core; + dst_len = len; + } else { + bb = bb_alloc(bb_len); + if (!bb) + return TEE_ERROR_OUT_OF_MEMORY; + dst = bb; + dst_len = bb_len; + } + + /* + * This loop will only run once if data_core is non-NULL, but as + * many times as needed if the bounce buffer bb is used. That's why + * dst doesn't need to be updated in the loop. + */ + while (num_bytes < len) { + size_t n = MIN(dst_len, len - num_bytes); + + if (handle->shdr->img_type == SHDR_ENCRYPTED_TA) { + res = tee_ta_decrypt_update(handle->enc_ctx, dst, + src + num_bytes, n); + if (res) { + res = TEE_ERROR_SECURITY; + goto out; + } + } else { + memcpy(dst, src + num_bytes, n); + } + + res = crypto_hash_update(handle->hash_ctx, dst, n); + if (res) { + res = TEE_ERROR_SECURITY; + goto out; + } + if (data_user) { + res = copy_to_user((uint8_t *)data_user + num_bytes, + dst, n); + if (res) { + res = TEE_ERROR_SECURITY; + goto out; + } + } + num_bytes += n; + } + + 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) { + res = TEE_ERROR_SECURITY; + goto out; + } + } + /* + * Last read: time to check if our digest matches the expected + * one (from the signed header) + */ + res = check_digest(handle); + if (res != TEE_SUCCESS) + goto out; + + if (handle->bs_hdr) + res = check_update_version(ta_ver_db, + handle->bs_hdr->uuid, + handle->bs_hdr->ta_version); + } +out: + bb_free(bb, bb_len); + 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, NULL, 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_core, + void *data_user, size_t len) +{ + struct buf_ree_fs_ta_handle *handle = (struct buf_ree_fs_ta_handle *)h; + uint8_t *src = handle->buf + handle->offs; + TEE_Result res = TEE_SUCCESS; + 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_core) + memcpy(data_core, src, len); + if (data_user) { + res = copy_to_user(data_user, src, len); + if (res) + return res; + } + 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..4d8869f --- /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 + +#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; + + bb_reset(); + 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; + + bb_reset(); + 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..b520c25 --- /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, 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_core, + void *data_user, 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_core, data_user, &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/semihosting.c b/optee/optee_os/core/kernel/semihosting.c new file mode 100644 index 0000000..83895ff --- /dev/null +++ b/optee/optee_os/core/kernel/semihosting.c @@ -0,0 +1,169 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2024 Andes Technology Corporation + */ + +#include +#include + +/* + * ARM and RISC-V have defined the standard way to perform + * the semihosting operations. + * - Operation codes and open modes are identical. + * - The implementation of the low-level __do_semihosting() call is + * architecture-specific. + * - Arm semihosting interface: + * https://developer.arm.com/documentation/dui0471/g/Semihosting/The-semihosting-interface + * - RISC-V semihosting interface: + * https://github.com/riscv-non-isa/riscv-semihosting/blob/main/binary-interface.adoc + */ + +/* An integer that specifies the file open mode */ +enum semihosting_open_mode { + SEMIHOSTING_OPEN_R = 0, + SEMIHOSTING_OPEN_RB = 1, + SEMIHOSTING_OPEN_RX = 2, + SEMIHOSTING_OPEN_RXB = 3, + SEMIHOSTING_OPEN_W = 4, + SEMIHOSTING_OPEN_WB = 5, + SEMIHOSTING_OPEN_WX = 6, + SEMIHOSTING_OPEN_WXB = 7, + SEMIHOSTING_OPEN_A = 8, + SEMIHOSTING_OPEN_AB = 9, + SEMIHOSTING_OPEN_AX = 10, + SEMIHOSTING_OPEN_AXB = 11, +}; + +enum semihosting_sys_ops { + /* Regular operations */ + SEMIHOSTING_SYS_OPEN = 0x01, + SEMIHOSTING_SYS_CLOSE = 0x02, + SEMIHOSTING_SYS_WRITEC = 0x03, + SEMIHOSTING_SYS_WRITE = 0x05, + SEMIHOSTING_SYS_READ = 0x06, + SEMIHOSTING_SYS_READC = 0x07, +}; + +struct semihosting_param_t { + uintptr_t param0; + uintptr_t param1; + uintptr_t param2; +}; + +/** + * @brief Read one character byte from the semihosting host debug terminal + * + * @retval the character read from the semihosting host + */ +char semihosting_sys_readc(void) +{ + return __do_semihosting(SEMIHOSTING_SYS_READC, 0); +} + +/** + * @brief Write one character byte to the semihosting host debug terminal + * @param c: the character to be written + */ +void semihosting_sys_writec(char c) +{ + __do_semihosting(SEMIHOSTING_SYS_WRITEC, (uintptr_t)&c); +} + +/** + * @brief Request the semihosting host to open a file on the host system + * @param fname: the path or name of the file + * @param flags: sys/fcntl.h standard flags to open the file with + * + * @retval nonzero if OK, or -1 if fails + */ +int semihosting_open(const char *fname, int flags) +{ + int semi_open_flags = 0; + const int flags_mask = O_RDONLY | O_WRONLY | O_RDWR | + O_CREAT | O_TRUNC | O_APPEND; + struct semihosting_param_t arg = { }; + + /* Convert the flags to semihosting open. */ + switch (flags & flags_mask) { + case O_RDONLY: /* 'r' */ + semi_open_flags = SEMIHOSTING_OPEN_R; + break; + case O_WRONLY | O_CREAT | O_TRUNC: /* 'w' */ + semi_open_flags = SEMIHOSTING_OPEN_W; + break; + case O_WRONLY | O_CREAT | O_APPEND: /* 'a' */ + semi_open_flags = SEMIHOSTING_OPEN_A; + break; + case O_RDWR: /* 'r+' */ + semi_open_flags = SEMIHOSTING_OPEN_RX; + break; + case O_RDWR | O_CREAT | O_TRUNC: /* 'w+' */ + semi_open_flags = SEMIHOSTING_OPEN_WX; + break; + case O_RDWR | O_CREAT | O_APPEND: /* 'a+' */ + semi_open_flags = SEMIHOSTING_OPEN_AX; + break; + default: + return -1; + } + + arg.param0 = (uintptr_t)fname; + arg.param1 = semi_open_flags; + arg.param2 = strlen(fname); + + return (int)__do_semihosting(SEMIHOSTING_SYS_OPEN, (uintptr_t)&arg); +} + +/** + * @brief Read data from a file on the semihosting host system + * @param fd: a handle for a file previously opened + * @param ptr: pointer to a buffer + * @param len: the number of bytes to read to the buffer from the file + * + * @retval zero if OK, the same value as @len if fails, smaller value than @len + * for partial success + */ +size_t semihosting_read(int fd, void *ptr, size_t len) +{ + struct semihosting_param_t arg = { + .param0 = fd, + .param1 = (uintptr_t)ptr, + .param2 = len + }; + + return __do_semihosting(SEMIHOSTING_SYS_READ, (uintptr_t)&arg); +} + +/** + * @brief Write data into a file on the semihosting host system + * @param fd: a handle for a file previously opened + * @param ptr: pointer to a buffer + * @param len: the number of bytes to be written from the buffer to the file + * + * @retval zero if OK, otherwise the number of bytes that are not written + */ +size_t semihosting_write(int fd, const void *ptr, size_t len) +{ + struct semihosting_param_t arg = { + .param0 = fd, + .param1 = (uintptr_t)ptr, + .param2 = len + }; + + return __do_semihosting(SEMIHOSTING_SYS_WRITE, (uintptr_t)&arg); +} + +/** + * @brief Close a file on the semihosting host system + * @param fd: a handle for a file previously opened + * + * @retval zero if OK, -1 if fails + */ +int semihosting_close(int fd) +{ + struct semihosting_param_t arg = { + .param0 = fd, + }; + + return (int)__do_semihosting(SEMIHOSTING_SYS_CLOSE, (uintptr_t)&arg); +} 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..4d2b21e --- /dev/null +++ b/optee/optee_os/core/kernel/sub.mk @@ -0,0 +1,66 @@ +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-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-$(_CFG_CORE_ASYNC_NOTIF_DEFAULT_IMPL) += notif_default.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 + +srcs-$(CFG_TRANSFER_LIST) += transfer_list.c + +srcs-$(CFG_SEMIHOSTING) += semihosting.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 +srcs-y += nv_counter.c +srcs-$(CFG_CALLOUT) += callout.c 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..f8c5194 --- /dev/null +++ b/optee/optee_os/core/kernel/tee_misc.c @@ -0,0 +1,139 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#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..0185ddd --- /dev/null +++ b/optee/optee_os/core/kernel/tee_ta_manager.c @@ -0,0 +1,1133 @@ +// 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 + +#if defined(CFG_TA_STATS) +#define MAX_DUMP_SESS_NUM (16) + +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); +} + +/* + * 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 && (ctx->panicked || !keep_alive)) { + if (!ctx->is_releasing) { + TAILQ_REMOVE(&tee_ctxes, ctx, link); + ctx->is_releasing = true; + } + 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; +} + +static void release_ta_ctx(struct tee_ta_ctx *ctx) +{ + bool was_releasing = false; + + mutex_lock(&tee_ta_mutex); + was_releasing = ctx->is_releasing; + ctx->is_releasing = true; + if (!was_releasing) { + DMSG("Releasing panicked TA ctx"); + TAILQ_REMOVE(&tee_ctxes, ctx, link); + } + mutex_unlock(&tee_ta_mutex); + + if (!was_releasing) + ctx->ts_ctx.ops->release_state(&ctx->ts_ctx); +} + +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; + ctx = ts_to_ta_ctx(ts_ctx); + + if (tee_ta_try_set_busy(ctx)) { + if (!ctx->panicked) { + /* Save identity of the owner of the session */ + s->clnt_id = *clnt_id; + s->param = param; + set_invoke_timeout(s, cancel_req_to); + res = ts_ctx->ops->enter_open_session(&s->ts_sess); + s->param = NULL; + } + + panicked = ctx->panicked; + if (panicked) { + release_ta_ctx(ctx); + res = TEE_ERROR_TARGET_DEAD; + } + + tee_ta_clear_busy(ctx); + } else { + /* Deadlock avoided */ + res = TEE_ERROR_BUSY; + was_busy = true; + } + + /* + * 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) + *sess = s; + else + EMSG("Failed for TA %pUl. Return error %#"PRIx32, uuid, 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; + bool panicked = false; + + 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; + ta_ctx = ts_to_ta_ctx(ts_ctx); + + tee_ta_set_busy(ta_ctx); + + if (!ta_ctx->panicked) { + sess->param = param; + set_invoke_timeout(sess, cancel_req_to); + res = ts_ctx->ops->enter_invoke_cmd(&sess->ts_sess, cmd); + sess->param = NULL; + } + + panicked = ta_ctx->panicked; + if (panicked) { + release_ta_ctx(ta_ctx); + res = TEE_ERROR_TARGET_DEAD; + } + + tee_ta_clear_busy(ta_ctx); + + /* + * Origin error equal to TEE_ORIGIN_TRUSTED_APP for "regular" error, + * apart from panicking. + */ + if (panicked) + *err = TEE_ORIGIN_TEE; + else + *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; + bool panicked = false; + + 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 (tee_ta_try_set_busy(ctx)) { + if (!ctx->panicked) { + s->param = param; + set_invoke_timeout(s, TEE_TIMEOUT_INFINITE); + res = ts_ctx->ops->dump_mem_stats(&s->ts_sess); + s->param = NULL; + } + + panicked = ctx->panicked; + if (panicked) { + release_ta_ctx(ctx); + res = TEE_ERROR_TARGET_DEAD; + } + + 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 pta_stats_ta *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 pta_stats_ta *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 pta_stats_ta *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 pta_stats_ta) * 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 pta_stats_ta *)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 __noprof 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..cc5bebc --- /dev/null +++ b/optee/optee_os/core/kernel/tee_time.c @@ -0,0 +1,43 @@ +// 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 + +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..aa3a11d --- /dev/null +++ b/optee/optee_os/core/kernel/tee_time_ree.c @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, Linaro Limited + */ + +#include +#include + +static TEE_Time prev; + +static struct mutex time_mu = MUTEX_INITIALIZER; + +TEE_Result tee_time_get_sys_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; +} + +uint32_t tee_time_get_sys_time_protection_level(void) +{ + return 100; +} diff --git a/optee/optee_os/core/kernel/thread.c b/optee/optee_os/core/kernel/thread.c new file mode 100644 index 0000000..2a1f22d --- /dev/null +++ b/optee/optee_os/core/kernel/thread.c @@ -0,0 +1,695 @@ +// 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 + +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 +static uint32_t start_canary_value = 0xdedede00; +static uint32_t end_canary_value = 0xababab00; +#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*/ +} + +#if defined(CFG_WITH_STACK_CANARIES) +void thread_update_canaries(void) +{ + uint32_t canary[2] = { }; + uint32_t exceptions = 0; + + plat_get_random_stack_canaries(canary, ARRAY_SIZE(canary), + sizeof(canary[0])); + + exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); + + thread_check_canaries(); + + start_canary_value = canary[0]; + end_canary_value = canary[1]; + thread_init_canaries(); + + thread_unmask_exceptions(exceptions); +} +#endif + +#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..c223b91 --- /dev/null +++ b/optee/optee_os/core/kernel/tpm.c @@ -0,0 +1,166 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2020-2023, ARM Limited. All rights reserved. + * Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. 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; +#ifdef ARM32 + log_addr = fdt32_to_cpu(property[1]); +#else + log_addr = fdt32_to_cpu(property[0]); + log_addr = (log_addr << 32) | fdt32_to_cpu(property[1]); +#endif + + if (!IS_ENABLED(CFG_CORE_SEL1_SPMC)) { + 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"); + 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; + void *tpm_log_buf = NULL; + + 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_buf = core_mmu_add_mapping(MEM_AREA_RAM_SEC, log_addr, + rounded_size); + if (!tpm_log_buf) { + EMSG("TPM: Failed to map TPM log memory"); + return; + } + + tpm_log_addr = calloc(1, rounded_size); + if (!tpm_log_addr) { + EMSG("TPM: Failed to alloc TPM log memory in TEE"); + return; + } + memcpy(tpm_log_addr, tpm_log_buf, rounded_size); + core_mmu_remove_mapping(MEM_AREA_RAM_SEC, tpm_log_buf, rounded_size); +} 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..007d6c3 --- /dev/null +++ b/optee/optee_os/core/kernel/trace_ext.c @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, Linaro Limited + */ +#include +#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; +} + +int trace_ext_get_guest_id(void) +{ + return virt_get_current_guest_id(); +} diff --git a/optee/optee_os/core/kernel/transfer_list.c b/optee/optee_os/core/kernel/transfer_list.c new file mode 100644 index 0000000..1be1b84 --- /dev/null +++ b/optee/optee_os/core/kernel/transfer_list.c @@ -0,0 +1,591 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2023, Linaro Limited + */ + +/******************************************************************************* + * Transfer list library compliant with the Firmware Handoff specification at: + * https://github.com/FirmwareHandoff/firmware_handoff + ******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +/******************************************************************************* + * Adapt a physical address to match the maximum transfer entry data alignment + * required by an existing transfer list. + * Compliant with 2.4.6 of Firmware Handoff specification (v0.9). + * @pa: Physical address for adapting. + * @tl: Pointer to the existing transfer list. + * Return the adapted physical address. + ******************************************************************************/ +static paddr_t get_align_base_addr(paddr_t pa, + struct transfer_list_header *tl) +{ + paddr_t align_mask = TL_ALIGNMENT_FROM_ORDER(tl->alignment) - 1; + paddr_t align_off = (paddr_t)tl & align_mask; + paddr_t new_addr = (pa & ~align_mask) + align_off; + + if (new_addr < pa) + new_addr += TL_ALIGNMENT_FROM_ORDER(tl->alignment); + + return new_addr; +} + +static void unmap_list(struct transfer_list_header *tl, size_t sz) +{ + if (core_mmu_remove_mapping(MEM_AREA_TRANSFER_LIST, tl, sz)) + panic("Failed to remove transfer list mapping"); +} + +struct transfer_list_header *transfer_list_map(paddr_t pa) +{ + struct transfer_list_header *tl = NULL; + size_t sz = SMALL_PAGE_SIZE; + size_t old_sz = 0; + + while (true) { + tl = core_mmu_add_mapping(MEM_AREA_TRANSFER_LIST, pa, sz); + if (!tl) { + EMSG("Failed to map TL with PA %#"PRIxPA", size %#zx", + pa, sz); + return NULL; + } + old_sz = sz; + + if (transfer_list_check_header(tl) == TL_OPS_NONE) { + unmap_list(tl, sz); + return NULL; + } + + if (tl->max_size <= sz) + return tl; + + sz = ROUNDUP(tl->max_size, SMALL_PAGE_SIZE); + unmap_list(tl, old_sz); + } +} + +void transfer_list_unmap_sync(struct transfer_list_header *tl) +{ + size_t sz = tl->max_size; + + transfer_list_update_checksum(tl); + dcache_cleaninv_range(tl, sz); + unmap_list(tl, sz); +} + +void transfer_list_unmap_nosync(struct transfer_list_header *tl) +{ + unmap_list(tl, tl->max_size); +} + +void transfer_list_dump(struct transfer_list_header *tl) +{ + struct transfer_list_entry *tl_e = NULL; + int i __maybe_unused = 0; + + if (!tl) + return; + + DMSG("Dump transfer list:"); + DMSG("signature %#"PRIx32, tl->signature); + DMSG("checksum %#"PRIx8, tl->checksum); + DMSG("version %#"PRIx8, tl->version); + DMSG("hdr_size %#"PRIx8, tl->hdr_size); + DMSG("alignment %#"PRIx8, tl->alignment); + DMSG("size %#"PRIx32, tl->size); + DMSG("max_size %#"PRIx32, tl->max_size); + DMSG("flags %#"PRIx32, tl->flags); + while (true) { + tl_e = transfer_list_next(tl, tl_e); + if (!tl_e) + break; + + DMSG("Entry %d:", i++); + DMSG("tag_id %#"PRIx16, tl_e->tag_id); + DMSG("hdr_size %#"PRIx8, tl_e->hdr_size); + DMSG("data_size %#"PRIx32, tl_e->data_size); + DMSG("data_addr %#"PRIxVA, + (vaddr_t)transfer_list_entry_data(tl_e)); + } +} + +/******************************************************************************* + * Creating a transfer list in a specified reserved memory region. + * Compliant with 2.4.5 of Firmware Handoff specification (v0.9). + * @pa: Physical address for residing the new transfer list. + * @max_size: Maximum size of the new transfer list. + * Return pointer to the created transfer list or NULL on error. + ******************************************************************************/ +struct transfer_list_header *transfer_list_init(paddr_t pa, size_t max_size) +{ + struct transfer_list_header *tl = NULL; + int align = TL_ALIGNMENT_FROM_ORDER(TRANSFER_LIST_INIT_MAX_ALIGN); + + if (!pa || !max_size) + return NULL; + + if (!IS_ALIGNED(pa, align) || !IS_ALIGNED(max_size, align) || + max_size < sizeof(*tl)) + return NULL; + + tl = core_mmu_add_mapping(MEM_AREA_TRANSFER_LIST, pa, max_size); + if (!tl) + return NULL; + + memset(tl, 0, max_size); + tl->signature = TRANSFER_LIST_SIGNATURE; + tl->version = TRANSFER_LIST_VERSION; + tl->hdr_size = sizeof(*tl); + tl->alignment = TRANSFER_LIST_INIT_MAX_ALIGN; /* initial max align */ + tl->size = sizeof(*tl); /* initial size is the size of header */ + tl->max_size = max_size; + tl->flags = TL_FLAGS_HAS_CHECKSUM; + + transfer_list_update_checksum(tl); + + return tl; +} + +/******************************************************************************* + * Relocating a transfer list to a specified reserved memory region. + * Compliant with 2.4.6 of Firmware Handoff specification (v0.9). + * @tl: Pointer to the transfer list for relocating. + * @pa: Physical address for relocating the transfer list. + * @max_size: Maximum size of the transfer list after relocating + * Return pointer to the relocated transfer list or NULL on error. + ******************************************************************************/ +struct transfer_list_header * +transfer_list_relocate(struct transfer_list_header *tl, paddr_t pa, + size_t max_size) +{ + paddr_t new_addr = 0; + struct transfer_list_header *new_tl = NULL; + size_t new_max_size = 0; + + if (!tl || !pa || !max_size) + return NULL; + + new_addr = get_align_base_addr(pa, tl); + new_max_size = max_size - (new_addr - pa); + + /* The new space is not sufficient for the TL */ + if (tl->size > new_max_size) + return NULL; + + new_tl = core_mmu_add_mapping(MEM_AREA_TRANSFER_LIST, new_addr, + new_max_size); + if (!new_tl) + return NULL; + + memmove(new_tl, tl, tl->size); + new_tl->max_size = new_max_size; + + transfer_list_update_checksum(new_tl); + transfer_list_unmap_nosync(tl); + + return new_tl; +} + +/******************************************************************************* + * Verifying the header of a transfer list. + * Compliant with 2.4.1 of Firmware Handoff specification (v0.9). + * @tl: Pointer to the transfer list. + * Return transfer list operation status code. + ******************************************************************************/ +int transfer_list_check_header(const struct transfer_list_header *tl) +{ + if (!tl) + return TL_OPS_NONE; + + if (tl->signature != TRANSFER_LIST_SIGNATURE) { + EMSG("Bad transfer list signature %#"PRIx32, tl->signature); + return TL_OPS_NONE; + } + + if (!tl->max_size) { + EMSG("Bad transfer list max size %#"PRIx32, tl->max_size); + return TL_OPS_NONE; + } + + if (tl->size > tl->max_size) { + EMSG("Bad transfer list size %#"PRIx32, tl->size); + return TL_OPS_NONE; + } + + if (tl->hdr_size != sizeof(struct transfer_list_header)) { + EMSG("Bad transfer list header size %#"PRIx8, tl->hdr_size); + return TL_OPS_NONE; + } + + if (!transfer_list_verify_checksum(tl)) { + EMSG("Bad transfer list checksum %#"PRIx8, tl->checksum); + return TL_OPS_NONE; + } + + if (tl->version == 0) { + EMSG("Transfer list version is invalid"); + return TL_OPS_NONE; + } else if (tl->version == TRANSFER_LIST_VERSION) { + DMSG("Transfer list version is valid for all operations"); + return TL_OPS_ALL; + } else if (tl->version > TRANSFER_LIST_VERSION) { + DMSG("Transfer list version is valid for read-only"); + return TL_OPS_RO; + } + + DMSG("Old transfer list version is detected"); + return TL_OPS_CUS; +} + +/******************************************************************************* + * Enumerate the next transfer entry. + * @tl: Pointer to the transfer list. + * @cur: Pointer to the current transfer entry where we want to search for the + * next one. + * Return pointer to the next transfer entry or NULL on error or if @cur is the + * last entry. + ******************************************************************************/ +struct transfer_list_entry *transfer_list_next(struct transfer_list_header *tl, + struct transfer_list_entry *cur) +{ + struct transfer_list_entry *tl_e = NULL; + vaddr_t tl_ev = 0; + vaddr_t va = 0; + vaddr_t ev = 0; + size_t sz = 0; + + if (!tl) + return NULL; + + tl_ev = (vaddr_t)tl + tl->size; + + if (cur) { + va = (vaddr_t)cur; + /* check if the total size overflow */ + if (ADD_OVERFLOW(cur->hdr_size, cur->data_size, &sz)) + return NULL; + /* roundup to the next entry */ + if (ADD_OVERFLOW(va, sz, &va) || + ROUNDUP_OVERFLOW(va, TRANSFER_LIST_GRANULE, &va)) + return NULL; + } else { + va = (vaddr_t)tl + tl->hdr_size; + } + + tl_e = (struct transfer_list_entry *)va; + + if (va + sizeof(*tl_e) > tl_ev || tl_e->hdr_size < sizeof(*tl_e) || + ADD_OVERFLOW(tl_e->hdr_size, tl_e->data_size, &sz) || + ADD_OVERFLOW(va, sz, &ev) || ev > tl_ev) + return NULL; + + return tl_e; +} + +/******************************************************************************* + * Calculate the byte sum (modulo 256) of a transfer list. + * @tl: Pointer to the transfer list. + * Return byte sum of the transfer list. + ******************************************************************************/ +static uint8_t calc_byte_sum(const struct transfer_list_header *tl) +{ + uint8_t *b = (uint8_t *)tl; + uint8_t cs = 0; + size_t n = 0; + + for (n = 0; n < tl->size; n++) + cs += b[n]; + + return cs; +} + +/******************************************************************************* + * Update the checksum of a transfer list. + * @tl: Pointer to the transfer list. + * Return updated checksum of the transfer list. + ******************************************************************************/ +void transfer_list_update_checksum(struct transfer_list_header *tl) +{ + uint8_t cs = 0; + + if (!tl || !(tl->flags & TL_FLAGS_HAS_CHECKSUM)) + return; + + cs = calc_byte_sum(tl); + cs -= tl->checksum; + cs = 256 - cs; + tl->checksum = cs; + assert(transfer_list_verify_checksum(tl)); +} + +/******************************************************************************* + * Verify the checksum of a transfer list. + * @tl: Pointer to the transfer list. + * Return true if verified or false if not. + ******************************************************************************/ +bool transfer_list_verify_checksum(const struct transfer_list_header *tl) +{ + if (!tl) + return false; + + if (!(tl->flags & TL_FLAGS_HAS_CHECKSUM)) + return true; + + return !calc_byte_sum(tl); +} + +/******************************************************************************* + * Update the data size of a transfer entry. + * @tl: Pointer to the transfer list. + * @tl_e: Pointer to the transfer entry. + * @new_data_size: New data size of the transfer entry. + * Return true on success or false on error. + ******************************************************************************/ +bool transfer_list_set_data_size(struct transfer_list_header *tl, + struct transfer_list_entry *tl_e, + uint32_t new_data_size) +{ + vaddr_t tl_old_ev = 0; + vaddr_t new_ev = 0; + vaddr_t old_ev = 0; + vaddr_t r_new_ev = 0; + struct transfer_list_entry *dummy_te = NULL; + size_t gap = 0; + size_t mov_dis = 0; + size_t sz = 0; + + if (!tl || !tl_e) + return false; + + tl_old_ev = (vaddr_t)tl + tl->size; + + /* + * Calculate the old and new end of transfer entry + * both must be roundup to align with TRANSFER_LIST_GRANULE + */ + if (ADD_OVERFLOW(tl_e->hdr_size, tl_e->data_size, &sz) || + ADD_OVERFLOW((vaddr_t)tl_e, sz, &old_ev) || + ROUNDUP_OVERFLOW(old_ev, TRANSFER_LIST_GRANULE, &old_ev)) + return false; + + if (ADD_OVERFLOW(tl_e->hdr_size, new_data_size, &sz) || + ADD_OVERFLOW((vaddr_t)tl_e, sz, &new_ev) || + ROUNDUP_OVERFLOW(new_ev, TRANSFER_LIST_GRANULE, &new_ev)) + return false; + + if (new_ev > old_ev) { + /* + * Move distance should be rounded up to match the entry data + * alignment. + * Ensure that the increased size doesn't exceed the max size + * of TL + */ + mov_dis = new_ev - old_ev; + if (ROUNDUP_OVERFLOW(mov_dis, + TL_ALIGNMENT_FROM_ORDER(tl->alignment), + &mov_dis) || + tl->size + mov_dis > tl->max_size) { + return false; + } + r_new_ev = old_ev + mov_dis; + tl->size += mov_dis; + } else { + /* + * Move distance should be rounded down to match the entry data + * alignment. + */ + mov_dis = ROUNDDOWN(old_ev - new_ev, + TL_ALIGNMENT_FROM_ORDER(tl->alignment)); + r_new_ev = old_ev - mov_dis; + tl->size -= mov_dis; + } + /* Move all following entries to fit in the expanded or shrunk space */ + memmove((void *)r_new_ev, (void *)old_ev, tl_old_ev - old_ev); + + /* + * Fill the gap due to round up/down with a void entry if the size of + * the gap is more than an entry header. + */ + gap = r_new_ev - new_ev; + if (gap >= sizeof(*dummy_te)) { + /* Create a dummy transfer entry to fill up the gap */ + dummy_te = (struct transfer_list_entry *)new_ev; + dummy_te->tag_id = TL_TAG_EMPTY; + dummy_te->reserved0 = 0; + dummy_te->hdr_size = sizeof(*dummy_te); + dummy_te->data_size = gap - sizeof(*dummy_te); + } + + tl_e->data_size = new_data_size; + + transfer_list_update_checksum(tl); + return true; +} + +/******************************************************************************* + * Remove a specified transfer entry from a transfer list. + * @tl: Pointer to the transfer list. + * @tl_e: Pointer to the transfer entry. + * Return true on success or false on error. + ******************************************************************************/ +bool transfer_list_rem(struct transfer_list_header *tl, + struct transfer_list_entry *tl_e) +{ + if (!tl || !tl_e || (vaddr_t)tl_e > (vaddr_t)tl + tl->size) + return false; + + tl_e->tag_id = TL_TAG_EMPTY; + tl_e->reserved0 = 0; + transfer_list_update_checksum(tl); + return true; +} + +/******************************************************************************* + * Add a new transfer entry into a transfer list. + * Compliant with 2.4.3 of Firmware Handoff specification (v0.9). + * @tl: Pointer to the transfer list. + * @tag_id: Tag ID for the new transfer entry. + * @data_size: Data size of the new transfer entry. + * @data: Pointer to the data for the new transfer entry. + * NULL to skip data copying. + * Return pointer to the added transfer entry or NULL on error. + ******************************************************************************/ +struct transfer_list_entry *transfer_list_add(struct transfer_list_header *tl, + uint16_t tag_id, + uint32_t data_size, + const void *data) +{ + vaddr_t max_tl_ev = 0; + vaddr_t tl_ev = 0; + vaddr_t ev = 0; + struct transfer_list_entry *tl_e = NULL; + size_t sz = 0; + + if (!tl) + return NULL; + + max_tl_ev = (vaddr_t)tl + tl->max_size; + tl_ev = (vaddr_t)tl + tl->size; + ev = tl_ev; + + /* + * Skip the step 1 (optional step). + * New transfer entry will be added into the tail + */ + if (ADD_OVERFLOW(sizeof(*tl_e), data_size, &sz) || + ADD_OVERFLOW(ev, sz, &ev) || + ROUNDUP_OVERFLOW(ev, TRANSFER_LIST_GRANULE, &ev) || + ev > max_tl_ev) { + return NULL; + } + + tl_e = (struct transfer_list_entry *)tl_ev; + *tl_e = (struct transfer_list_entry){ + .tag_id = tag_id, + .hdr_size = sizeof(*tl_e), + .data_size = data_size, + }; + + tl->size += ev - tl_ev; + + if (data) + memmove(tl_e + tl_e->hdr_size, data, data_size); + + transfer_list_update_checksum(tl); + + return tl_e; +} + +/******************************************************************************* + * Add a new transfer entry into a transfer list with specified new data + * alignment requirement. + * Compliant with 2.4.4 of Firmware Handoff specification (v0.9). + * @tl: Pointer to the transfer list. + * @tag_id: Tag ID for the new transfer entry. + * @data_size: Data size of the new transfer entry. + * @data: Pointer to the data for the new transfer entry. + * @alignment: New data alignment specified as a power of two. + * Return pointer to the added transfer entry or NULL on error. + ******************************************************************************/ +struct transfer_list_entry * +transfer_list_add_with_align(struct transfer_list_header *tl, uint16_t tag_id, + uint32_t data_size, const void *data, + uint8_t alignment) +{ + struct transfer_list_entry *tl_e = NULL; + vaddr_t tl_ev = 0; + vaddr_t ev = 0; + vaddr_t new_tl_ev = 0; + size_t dummy_te_data_sz = 0; + + if (!tl) + return NULL; + + tl_ev = (vaddr_t)tl + tl->size; + ev = tl_ev + sizeof(struct transfer_list_entry); + + if (!IS_ALIGNED(ev, TL_ALIGNMENT_FROM_ORDER(alignment))) { + /* + * Transfer entry data address is not aligned to the new + * alignment. Fill the gap with an empty transfer entry as a + * placeholder before adding the desired transfer entry + */ + new_tl_ev = ROUNDUP(ev, TL_ALIGNMENT_FROM_ORDER(alignment)) - + sizeof(struct transfer_list_entry); + assert(new_tl_ev - tl_ev > sizeof(struct transfer_list_entry)); + dummy_te_data_sz = new_tl_ev - tl_ev - + sizeof(struct transfer_list_entry); + if (!transfer_list_add(tl, TL_TAG_EMPTY, dummy_te_data_sz, + NULL)) { + return NULL; + } + } + + tl_e = transfer_list_add(tl, tag_id, data_size, data); + + if (alignment > tl->alignment) { + tl->alignment = alignment; + transfer_list_update_checksum(tl); + } + + return tl_e; +} + +/******************************************************************************* + * Search for an existing transfer entry with the specified tag id from a + * transfer list. + * @tl: Pointer to the transfer list. + * @tag_id: Tag ID to match a transfer entry. + * Return pointer to the found transfer entry or NULL if not found. + ******************************************************************************/ +struct transfer_list_entry *transfer_list_find(struct transfer_list_header *tl, + uint16_t tag_id) +{ + struct transfer_list_entry *tl_e = NULL; + + do { + tl_e = transfer_list_next(tl, tl_e); + } while (tl_e && tl_e->tag_id != tag_id); + + return tl_e; +} + +/******************************************************************************* + * Retrieve the data pointer of a specified transfer entry. + * @tl_e: Pointer to the transfer entry. + * Return pointer to the transfer entry data or NULL on error. + ******************************************************************************/ +void *transfer_list_entry_data(struct transfer_list_entry *tl_e) +{ + if (!tl_e) + return NULL; + + return (uint8_t *)tl_e + tl_e->hdr_size; +} 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..3f229f9 --- /dev/null +++ b/optee/optee_os/core/kernel/user_access.c @@ -0,0 +1,332 @@ +// 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 + +#define BB_ALIGNMENT (sizeof(long) * 2) + +static struct user_mode_ctx *get_current_uctx(void) +{ + struct ts_session *s = ts_get_current_session(); + + if (!is_user_mode_ctx(s->ctx)) { + /* + * We may be called within a PTA session, which doesn't + * have a user_mode_ctx. Here, try to retrieve the + * user_mode_ctx associated with the calling session. + */ + s = TAILQ_NEXT(s, link_tsd); + if (!s || !is_user_mode_ctx(s->ctx)) + return NULL; + } + + return to_user_mode_ctx(s->ctx); +} + +TEE_Result check_user_access(uint32_t flags, const void *uaddr, size_t len) +{ + struct user_mode_ctx *uctx = get_current_uctx(); + + if (!uctx) + return TEE_ERROR_GENERIC; + + return vm_check_access_rights(uctx, 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_user_access(flags, uaddr, len); + if (!res) { + enter_user_access(); + memcpy(kaddr, uaddr, len); + exit_user_access(); + } + + 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_user_access(flags, uaddr, len); + if (!res) { + enter_user_access(); + memcpy(uaddr, kaddr, len); + exit_user_access(); + } + + 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_user_access(flags, uaddr, len); + if (!res) { + enter_user_access(); + memcpy(kaddr, uaddr, len); + exit_user_access(); + } + + 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_user_access(flags, uaddr, len); + if (!res) { + enter_user_access(); + memcpy(uaddr, kaddr, len); + exit_user_access(); + } + + return res; +} + +static void *maybe_tag_bb(void *buf, size_t sz) +{ + static_assert(MEMTAG_GRANULE_SIZE <= BB_ALIGNMENT); + + if (!MEMTAG_IS_ENABLED) + return buf; + + assert(!((vaddr_t)buf % MEMTAG_GRANULE_SIZE)); + return memtag_set_random_tags(buf, ROUNDUP(sz, MEMTAG_GRANULE_SIZE)); +} + +static void maybe_untag_bb(void *buf, size_t sz) +{ + if (MEMTAG_IS_ENABLED) { + assert(!((vaddr_t)buf % MEMTAG_GRANULE_SIZE)); + memtag_set_tags(buf, ROUNDUP(sz, MEMTAG_GRANULE_SIZE), 0); + } +} + +void *bb_alloc(size_t len) +{ + struct user_mode_ctx *uctx = get_current_uctx(); + size_t offs = 0; + void *bb = NULL; + + if (uctx && !ADD_OVERFLOW(uctx->bbuf_offs, len, &offs) && + offs <= uctx->bbuf_size) { + bb = maybe_tag_bb(uctx->bbuf + uctx->bbuf_offs, len); + uctx->bbuf_offs = ROUNDUP(offs, BB_ALIGNMENT); + } + return bb; +} + +static void bb_free_helper(struct user_mode_ctx *uctx, vaddr_t bb, size_t len) +{ + vaddr_t bbuf = (vaddr_t)uctx->bbuf; + + if (bb >= bbuf && IS_ALIGNED(bb, BB_ALIGNMENT)) { + size_t prev_offs = bb - bbuf; + + /* + * Even if we can't update offset we can still invalidate + * the memory allocation. + */ + maybe_untag_bb((void *)bb, len); + + if (prev_offs + ROUNDUP(len, BB_ALIGNMENT) == uctx->bbuf_offs) + uctx->bbuf_offs = prev_offs; + } +} + +void bb_free(void *bb, size_t len) +{ + struct user_mode_ctx *uctx = get_current_uctx(); + + if (uctx) + bb_free_helper(uctx, memtag_strip_tag_vaddr(bb), len); +} + +void bb_free_wipe(void *bb, size_t len) +{ + if (bb) + memset(bb, 0, len); + bb_free(bb, len); +} + +void bb_reset(void) +{ + struct user_mode_ctx *uctx = get_current_uctx(); + + if (uctx) { + /* + * Only the part up to the offset have been allocated, so + * no need to clear tags beyond that. + */ + maybe_untag_bb(uctx->bbuf, uctx->bbuf_offs); + + uctx->bbuf_offs = 0; + } +} + +TEE_Result clear_user(void *uaddr, size_t n) +{ + uint32_t flags = TEE_MEMORY_ACCESS_WRITE | TEE_MEMORY_ACCESS_ANY_OWNER; + TEE_Result res = TEE_SUCCESS; + + uaddr = memtag_strip_tag(uaddr); + res = check_user_access(flags, uaddr, n); + if (res) + return res; + + enter_user_access(); + memset(uaddr, 0, n); + exit_user_access(); + + return TEE_SUCCESS; +} + +size_t strnlen_user(const void *uaddr, size_t len) +{ + uint32_t flags = TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_ANY_OWNER; + TEE_Result res = TEE_SUCCESS; + size_t n = 0; + + if (!len) + return 0; + + uaddr = memtag_strip_tag_const(uaddr); + res = check_user_access(flags, uaddr, len); + if (!res) { + enter_user_access(); + n = strnlen(uaddr, len); + exit_user_access(); + } + + return n; +} + +static TEE_Result __bb_memdup_user(TEE_Result (*copy_func)(void *uaddr, + const void *kaddr, + size_t len), + const void *src, size_t len, void **p) +{ + TEE_Result res = TEE_SUCCESS; + void *buf = NULL; + + buf = bb_alloc(len); + if (!buf) + return TEE_ERROR_OUT_OF_MEMORY; + + if (len) + res = copy_func(buf, src, len); + + if (res) + bb_free(buf, len); + else + *p = buf; + + return res; +} + +TEE_Result bb_memdup_user(const void *src, size_t len, void **p) +{ + return __bb_memdup_user(copy_from_user, src, len, p); +} + +TEE_Result bb_memdup_user_private(const void *src, size_t len, void **p) +{ + return __bb_memdup_user(copy_from_user_private, src, len, p); +} + +TEE_Result bb_strndup_user(const char *src, size_t maxlen, char **dst, + size_t *dstlen) +{ + uint32_t flags = TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_ANY_OWNER; + TEE_Result res = TEE_SUCCESS; + size_t l = 0; + char *d = NULL; + + src = memtag_strip_tag_const(src); + if (maxlen) { + res = check_user_access(flags, src, maxlen); + if (res) + return res; + + enter_user_access(); + l = strnlen(src, maxlen); + exit_user_access(); + } + + d = bb_alloc(l + 1); + if (!d) + return TEE_ERROR_OUT_OF_MEMORY; + + if (l) { + enter_user_access(); + memcpy(d, src, l); + exit_user_access(); + } + + d[l] = 0; + + *dst = d; + *dstlen = l; + return TEE_SUCCESS; +} + +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 |= (vaddr_t)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..cba8de3 --- /dev/null +++ b/optee/optee_os/core/kernel/user_ta.c @@ -0,0 +1,532 @@ +// 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 + +static TEE_Result init_utee_param(struct utee_params *up, + const struct tee_ta_param *p, + void *va[TEE_NUM_PARAMS]) +{ + TEE_Result res = TEE_SUCCESS; + size_t n = 0; + struct utee_params *up_bbuf = NULL; + + up_bbuf = bb_alloc(sizeof(struct utee_params)); + if (!up_bbuf) + return TEE_ERROR_OUT_OF_MEMORY; + + up_bbuf->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_bbuf->vals[n * 2] = a; + up_bbuf->vals[n * 2 + 1] = b; + } + + res = copy_to_user(up, up_bbuf, sizeof(struct utee_params)); + + bb_free(up_bbuf, sizeof(struct utee_params)); + + return res; +} + +static void update_from_utee_param(struct tee_ta_param *p, + const struct utee_params *up) +{ + TEE_Result res = TEE_SUCCESS; + size_t n = 0; + struct utee_params *up_bbuf = NULL; + + res = BB_MEMDUP_USER(up, sizeof(*up), &up_bbuf); + if (res) + return; + + 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_bbuf->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_bbuf->vals[n * 2]; + p->u[n].val.b = up_bbuf->vals[n * 2 + 1]; + break; + default: + break; + } + } + + bb_free(up_bbuf, sizeof(*up)); +} + +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) + res = init_utee_param(usr_params, ta_sess->param, param_va); + else + res = clear_user(usr_params, sizeof(*usr_params)); + + if (res) + goto out_pop_session; + + 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); + } + +out_pop_session: + if (ta_sess->param) { + /* + * 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: + /* + * Reset 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; + ta_sess->cancel_mask = true; + + 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 release_utc_state(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); +} + +static void free_utc(struct user_ta_ctx *utc) +{ + release_utc_state(utc); + free(utc); +} + +static void user_ta_release_state(struct ts_ctx *ctx) +{ + release_utc_state(to_user_ta_ctx(ctx)); +} + +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 + .release_state = user_ta_release_state, + .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 __noprof 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..926f39f --- /dev/null +++ b/optee/optee_os/core/kernel/wait_queue.c @@ -0,0 +1,210 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015-2021, Linaro Limited + */ + +#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..b1d0a4d --- /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..d6243c4 --- /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..ac05212 --- /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..bf1f02a --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/gcm.c @@ -0,0 +1,220 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014-2019, Linaro Limited + */ + +#include +#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..791db1e --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/mpi_desc.c @@ -0,0 +1,782 @@ +// 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, int *c) +{ + int res = mbedtls_mpi_is_prime_ext(a, b, 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) +{ + assert(s); + + mbedtls_mpi_free((mbedtls_mpi *)*s); + free(*s); + *s = NULL; +} + +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..f63bfe9 --- /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_DESC) + 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_DESC) + 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_DESC) + 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_DESC) + 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_DESC) + 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_DESC) + 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..cd701ec --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sub.mk @@ -0,0 +1,13 @@ +srcs-$(_CFG_CORE_LTC_SHA224_DESC) += 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..6a35fe2 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/hashes/sub.mk @@ -0,0 +1,14 @@ +srcs-$(_CFG_CORE_LTC_MD5_DESC) += md5.c + +ifeq ($(_CFG_CORE_LTC_SHA1_DESC),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..f035f6f --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_verify_hash.c @@ -0,0 +1,208 @@ +/* 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; + } + + if (!*stat) { + /* + * The call to ftmn_set_check_res_memcmp() above might have failed, + * since memcmp() may set any non-zero result force it 1 to match the + * check with FTMN_CALLEE_DONE_CHECK() below. + */ + FTMN_SET_CHECK_RES_NOT_ZERO(&ftmn, FTMN_INCR1, 1); + inc1++; + } + +#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..de11ccc --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/sub.mk @@ -0,0 +1,155 @@ +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_DESC),y) + cppflags-lib-y += -DLTC_MD5 +endif +ifeq ($(_CFG_CORE_LTC_SHA1_DESC),y) + cppflags-lib-y += -DLTC_SHA1 +endif +ifeq ($(_CFG_CORE_LTC_SHA224_DESC),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 +cppflags-mpi_desc.c-y += -DMBEDTLS_ALLOW_PRIVATE_ACCESS +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..cdff8f3 --- /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_DESC) + register_hash(&md5_desc); +#endif +#if defined(_CFG_CORE_LTC_SHA1) || defined(_CFG_CORE_LTC_SHA1_DESC) + register_hash(&sha1_desc); +#endif +#if defined(_CFG_CORE_LTC_SHA224) || defined(_CFG_CORE_LTC_SHA224_DESC) + 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..6098a46 --- /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 montgomery_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 montgomery_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 montgomery_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..0b060c4 --- /dev/null +++ b/optee/optee_os/core/lib/scmi-server/conf-optee-fvp.mk @@ -0,0 +1,23 @@ +$(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_SCMI_PERF_PROTOCOL_OPS,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..d719a1c --- /dev/null +++ b/optee/optee_os/core/lib/scmi-server/sub.mk @@ -0,0 +1,226 @@ +# 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_PERF_PROTOCOL_OPS) \ + += -DBUILD_HAS_SCMI_PERF_PROTOCOL_OPS + +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 + +# SCMI_Perf in SCP-firmware has components that can be added conditionally at +# build time. +ifeq ($(1), scmi_perf) + +ifeq ($(CFG_SCPFW_SCMI_PERF_PROTOCOL_OPS),y) +srcs-$(CFG_SCPFW_MOD_SCMI_PERF) += $(scpfw-path)/$3/$2/src/scmi_perf_protocol_ops.c +endif + +ifeq ($(CFG_SCPFW_SCMI_PERF_FAST_CHANNELS),y) +srcs-$(CFG_SCPFW_MOD_SCMI_PERF) += $(scpfw-path)/$3/$2/src/scmi_perf_fastchannels.c +endif + +endif + +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..0735f5c --- /dev/null +++ b/optee/optee_os/core/mm/core_mmu.c @@ -0,0 +1,2598 @@ +// 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; +} + +void core_mmu_set_secure_memory(paddr_t base, size_t size) +{ +#ifdef CFG_CORE_PHYS_RELOCATABLE + static_assert(ARRAY_SIZE(secure_only) == 1); +#endif + runtime_assert(IS_ENABLED(CFG_CORE_PHYS_RELOCATABLE)); + assert(!secure_only[0].size); + assert(base && size); + + DMSG("Physical secure memory base %#"PRIxPA" size %#zx", base, size); + secure_only[0].paddr = base; + secure_only[0].size = size; +} + +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_MANIFEST_DT: + case MEM_AREA_RAM_NSEC: + 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, + 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; + + 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; mmap->type != MEM_AREA_END; mmap++) { + 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: + case MEM_AREA_NEX_NSEC_SHM: + return attr | TEE_MATTR_PRW | cached; + case MEM_AREA_MANIFEST_DT: + return attr | TEE_MATTR_SECURE | TEE_MATTR_PR | cached; + case MEM_AREA_TRANSFER_LIST: + return attr | TEE_MATTR_SECURE | 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_ROM_SEC: + return attr | TEE_MATTR_SECURE | TEE_MATTR_PR | 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 void collect_device_mem_ranges(struct tee_mmap_region *memory_map, + size_t num_elems, size_t *last) +{ + const char *compatible = "arm,ffa-manifest-device-regions"; + void *fdt = get_manifest_dt(); + const char *name = NULL; + uint64_t page_count = 0; + uint64_t base = 0; + int subnode = 0; + int node = 0; + + assert(fdt); + + node = fdt_node_offset_by_compatible(fdt, 0, compatible); + if (node < 0) + return; + + fdt_for_each_subnode(subnode, fdt, node) { + name = fdt_get_name(fdt, subnode, NULL); + if (!name) + continue; + + if (dt_getprop_as_number(fdt, subnode, "base-address", + &base)) { + EMSG("Mandatory field is missing: base-address"); + continue; + } + + if (base & SMALL_PAGE_MASK) { + EMSG("base-address is not page aligned"); + continue; + } + + if (dt_getprop_as_number(fdt, subnode, "pages-count", + &page_count)) { + EMSG("Mandatory field is missing: pages-count"); + continue; + } + + add_phys_mem(memory_map, num_elems, name, MEM_AREA_IO_SEC, + base, base + page_count * SMALL_PAGE_SIZE, last); + } +} + +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 + + /* Collect device memory info from SP manifest */ + if (IS_ENABLED(CFG_CORE_SEL2_SPMC)) + collect_device_mem_ranges(memory_map, num_elems, &last); + + 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, 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_MANIFEST_DT: + case MEM_AREA_TRANSFER_LIST: + case MEM_AREA_RAM_SEC: + case MEM_AREA_RAM_NSEC: + case MEM_AREA_ROM_SEC: + 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(enum teecore_memtypes 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(core_mmu_level_in_range(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 = tbl_info.next_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->next_level, 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(const void *va) +{ + vaddr_t v = (vaddr_t)va; + + return v >= VCORE_START_VA && v < get_linear_map_end_va(); +} +#endif + +#ifdef CFG_NS_VIRTUALIZATION +bool is_nexus(const void *va) +{ + vaddr_t v = (vaddr_t)va; + + return v >= VCORE_START_VA && v < VCORE_NEX_RW_PA + VCORE_NEX_RW_SZ; +} +#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..55c1a22 --- /dev/null +++ b/optee/optee_os/core/mm/mobj.c @@ -0,0 +1,544 @@ +// 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 + +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_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; +} + +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_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/pgt_cache.c b/optee/optee_os/core/mm/pgt_cache.c new file mode 100644 index 0000000..79553c6 --- /dev/null +++ b/optee/optee_os/core/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/mm/sub.mk b/optee/optee_os/core/mm/sub.mk new file mode 100644 index 0000000..7d3c5ea --- /dev/null +++ b/optee/optee_os/core/mm/sub.mk @@ -0,0 +1,9 @@ +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 += pgt_cache.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..95084ca --- /dev/null +++ b/optee/optee_os/core/mm/tee_mm.c @@ -0,0 +1,395 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#include +#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 pta_stats_alloc *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..cf87c64 --- /dev/null +++ b/optee/optee_os/core/mm/vm.c @@ -0,0 +1,1355 @@ +// 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 + +#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_va_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_va_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; +} + +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); + uctx->vm_info.asid = 0; + + while (!TAILQ_EMPTY(&uctx->vm_info.regions)) + umap_remove_region(&uctx->vm_info, + TAILQ_FIRST(&uctx->vm_info.regions)); +} + +/* 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..d8a4107 --- /dev/null +++ b/optee/optee_os/core/pta/attestation.c @@ -0,0 +1,802 @@ +// 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 +#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) + goto err; + + res = crypto_bignum_bin2bn((uint8_t *)&e, sizeof(e), key->e); + if (res) + goto err; + + /* + * 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) + goto out; + +err: + free_key(); +out: + 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, + TEE_POBJ_USAGE_OPEN, 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, NULL, &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, + TEE_POBJ_USAGE_OPEN, 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, NULL, 0, &fh); + if (!res) { + res = po->fops->write(fh, offset, data, NULL, 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 dontwant = VM_FLAG_EPHEMERAL | VM_FLAG_PERMANENT | + VM_FLAG_LDELF; + uint32_t want = VM_FLAG_READONLY; + + return ((r->flags & want) == want && !(r->flags & dontwant)); +} + +/* + * 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; + + enter_user_access(); + + /* + * 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) + break; + } + + exit_user_access(); + + 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]) +{ + TEE_Result res = TEE_ERROR_BAD_PARAMETERS; + TEE_Result res2 = TEE_ERROR_GENERIC; + TEE_Param bparams[TEE_NUM_PARAMS] = { }; + TEE_Param *eparams = NULL; + + res = to_bounce_params(param_types, params, bparams, &eparams); + if (res) + return res; + + switch (cmd_id) { + case PTA_ATTESTATION_GET_PUBKEY: + res = cmd_get_pubkey(param_types, eparams); + break; + case PTA_ATTESTATION_GET_TA_SHDR_DIGEST: + res = cmd_get_ta_shdr_digest(param_types, eparams); + break; + case PTA_ATTESTATION_HASH_TA_MEMORY: + res = cmd_hash_ta_memory(param_types, eparams); + break; + case PTA_ATTESTATION_HASH_TEE_MEMORY: + res = cmd_hash_tee_memory(param_types, eparams); + break; + default: + break; + } + + res2 = from_bounce_params(param_types, params, bparams, eparams); + if (!res && res2) + res = res2; + + return res; +} + +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..f77f923 --- /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", 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/device.c b/optee/optee_os/core/pta/device.c new file mode 100644 index 0000000..0aff9a8 --- /dev/null +++ b/optee/optee_os/core/pta/device.c @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2019, Linaro Limited + * Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved. + */ + +/* + * 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: + tee_set_ree_state(TEE_REE_STATE_REE_OS); + return get_devices(nParamTypes, pParams, + TA_FLAG_DEVICE_ENUM); + case PTA_CMD_GET_DEVICES_SUPP: + tee_set_ree_state(TEE_REE_STATE_REE_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/dek_blob.c b/optee/optee_os/core/pta/imx/dek_blob.c new file mode 100644 index 0000000..b7e311b --- /dev/null +++ b/optee/optee_os/core/pta/imx/dek_blob.c @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2019, 2023 NXP + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PTA_NAME "dek_blob.pta" + +/* Blob size padding in bytes */ +#define BLOB_PAD_SIZE 48 + +/* HAB Blob header values */ +#define HAB_HDR_TAG 0x81 +#define HAB_HDR_V4 0x43 +#define HAB_HDR_MODE_CCM 0x66 +#define HAB_HDR_ALG_AES 0x55 + +/* + * DEK blobs are stored by the HAB in a secret key blob data structure. Notice + * that the HAB supports a set of encryption algorithms, but the encrypted boot + * protocol expects AES. The key length is a variable; it can be 128-bit, + * 192-bit, or 256-bit. + * For more info, see NXP application note AN12056 + */ +struct dek_blob_header { + uint8_t tag; /* Constant identifying HAB struct: 0x81 */ + uint8_t len_msb; /* Struct length in 8-bit msb */ + uint8_t len_lsb; /* Struct length in 8-bit lsb */ + uint8_t par; /* Constant value, HAB version: 0x43 */ + uint8_t mode; /* AES encryption CCM mode: 0x66 */ + uint8_t alg; /* AES encryption alg: 0x55 */ + uint8_t size; /* Unwrapped key value size in bytes */ + uint8_t flg; /* Key flags */ +}; + +/* + * Generate HAB DEK blob for encrypted boot + * + * payload [in] Plain text key to encapsulate. + * payload_size [in] Plain text key size. Must be 128, 192 or 256 bits. + * blob [out] DEK blob. + * blob_size [in/out] DEK blob size. + */ +static TEE_Result do_generate(const uint8_t *payload, size_t payload_size, + uint8_t *blob, size_t *blob_size) +{ + struct dek_blob_header *header = NULL; + size_t expected_blob_size = 0; + size_t dek_size = 0; + + /* + * Prevent against an unexpected padding of dek_blob_header structure + * that must remain packed. This structure will be seriailized to a + * buffer along the DEK blob. + */ + static_assert(sizeof(struct dek_blob_header) == 8 * sizeof(uint8_t)); + + assert(payload && blob && payload_size && blob_size); + assert(payload_size == (128 / 8) || payload_size == (192 / 8) || + payload_size == (256 / 8)); + + /* + * The DEK size is equals to input key size plus the required blob + * padding. The total output size is the DEK size plus its header + */ + dek_size = payload_size + BLOB_PAD_SIZE; + expected_blob_size = sizeof(*header) + dek_size; + + /* Check that the output buffer has the required size */ + if (*blob_size < expected_blob_size) { + *blob_size = expected_blob_size; + return TEE_ERROR_SHORT_BUFFER; + } + *blob_size = expected_blob_size; + + /* Defined header */ + header = (struct dek_blob_header *)blob; + header->tag = HAB_HDR_TAG; + header->len_msb = 0; + header->len_lsb = expected_blob_size; + header->par = HAB_HDR_V4; + header->mode = HAB_HDR_MODE_CCM; + header->alg = HAB_HDR_ALG_AES; + header->size = payload_size; + header->flg = 0; + + /* Generate DEK */ + return caam_dek_generate(payload, payload_size, blob + sizeof(*header), + dek_size); +} + +static TEE_Result cmd_dek_generate(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (param_types != exp_param_types) + return TEE_ERROR_BAD_PARAMETERS; + + if (params[0].memref.size != (128 / 8) && + params[0].memref.size != (192 / 8) && + params[0].memref.size != (256 / 8)) + return TEE_ERROR_BAD_PARAMETERS; + + memset(params[1].memref.buffer, 0, params[1].memref.size); + + return do_generate(params[0].memref.buffer, params[0].memref.size, + params[1].memref.buffer, ¶ms[1].memref.size); +} + +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_IMX_DEK_BLOB_CMD_GENERATE: + return cmd_dek_generate(param_types, params); + default: + return TEE_ERROR_BAD_PARAMETERS; + } +} + +pseudo_ta_register(.uuid = PTA_DEK_BLOB_UUID, .name = PTA_NAME, + .flags = PTA_DEFAULT_FLAGS, + .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..22aa41c --- /dev/null +++ b/optee/optee_os/core/pta/imx/manufacturing_protection.c @@ -0,0 +1,125 @@ +// 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; + + if (IS_ENABLED(CFG_NXP_CAAM_MP_NO_ACCESS_CTRL)) + return TEE_SUCCESS; + + 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..6209e97 --- /dev/null +++ b/optee/optee_os/core/pta/imx/sub.mk @@ -0,0 +1,4 @@ +srcs-$(CFG_IMX_DIGPROG) += digprog.c +srcs-$(CFG_IMX_OCOTP) += ocotp.c +srcs-$(CFG_NXP_CAAM_MP_DRV) += manufacturing_protection.c +srcs-$(CFG_NXP_CAAM_DEK_DRV) += dek_blob.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..1ef964d --- /dev/null +++ b/optee/optee_os/core/pta/scmi.c @@ -0,0 +1,246 @@ +// 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; + + 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..353ed0a --- /dev/null +++ b/optee/optee_os/core/pta/stats.c @@ -0,0 +1,234 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015, Linaro Limited + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static TEE_Result get_alloc_stats(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) +{ + struct pta_stats_alloc *stats = NULL; + uint32_t size_to_retrieve = 0; + uint32_t pool_id = 0; + uint32_t i = 0; + + /* + * 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 pta_stats_alloc + */ + 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 pta_stats_alloc); + if (pool_id == ALLOC_ID_ALL) + 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 = ALLOC_ID_HEAP; i <= STATS_NB_POOLS; i++) { + if (pool_id != ALLOC_ID_ALL && i != pool_id) + continue; + + switch (i) { + case ALLOC_ID_HEAP: + malloc_get_stats(stats); + strlcpy(stats->desc, "Heap", sizeof(stats->desc)); + if (p[0].value.b) + malloc_reset_stats(); + break; + + case ALLOC_ID_PUBLIC_DDR: + EMSG("public DDR not managed by secure side anymore"); + break; + + case ALLOC_ID_TA_RAM: + 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 ALLOC_ID_NEXUS_HEAP: + 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; +} + +static TEE_Result get_system_time(uint32_t type, + TEE_Param p[TEE_NUM_PARAMS]) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + TEE_Time ree_time = { }; + TEE_Time tee_time = { }; + + if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE) != type) + return TEE_ERROR_BAD_PARAMETERS; + + ret = tee_time_get_sys_time(&tee_time); + if (ret) + return ret; + + ret = tee_time_get_ree_time(&ree_time); + if (ret) + return ret; + + p[0].value.a = ree_time.seconds; + p[0].value.b = ree_time.millis; + p[1].value.a = tee_time.seconds; + p[1].value.b = tee_time.millis; + + return TEE_SUCCESS; +} + +static TEE_Result print_driver_info(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) +{ + if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE) != type) + return TEE_ERROR_BAD_PARAMETERS; + + switch (p[0].value.a) { + case STATS_DRIVER_TYPE_CLOCK: + clk_print_tree(); + break; + case STATS_DRIVER_TYPE_REGULATOR: + regulator_print_tree(); + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + + return TEE_SUCCESS; +} + +/* + * 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); + case STATS_CMD_GET_TIME: + return get_system_time(ptypes, params); + case STATS_CMD_PRINT_DRIVER_INFO: + return print_driver_info(ptypes, params); + default: + break; + } + return TEE_ERROR_BAD_PARAMETERS; +} + +pseudo_ta_register(.uuid = STATS_UUID, .name = "stats.pta", + .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/remoteproc_pta.c b/optee/optee_os/core/pta/stm32mp/remoteproc_pta.c new file mode 100644 index 0000000..b2eed7f --- /dev/null +++ b/optee/optee_os/core/pta/stm32mp/remoteproc_pta.c @@ -0,0 +1,356 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2023, STMicroelectronics - All Rights Reserved + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rproc_pub_key.h" + +#define PTA_NAME "remoteproc.pta" + +/* + * UUID of the remoteproc Trusted application authorized to communicate with + * the remoteproc pseudo TA. The UID should match the one defined in the + * ta_remoteproc.h header file. + */ +#define TA_REMOTEPROC_UUID \ + { 0x80a4c275, 0x0a47, 0x4905, \ + { 0x82, 0x85, 0x14, 0x86, 0xa9, 0x77, 0x1a, 0x08} } + +/* + * Firmware states + * REMOTEPROC_OFF: firmware is off + * REMOTEPROC_ON: firmware is running + */ +enum rproc_load_state { + REMOTEPROC_OFF = 0, + REMOTEPROC_ON, +}; + +/* Currently supporting a single remote processor instance */ +static enum rproc_load_state rproc_ta_state = REMOTEPROC_OFF; + +static TEE_Result rproc_pta_capabilities(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_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE); + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + if (!stm32_rproc_get(params[0].value.a)) + return TEE_ERROR_NOT_SUPPORTED; + + /* Support only ELF format */ + params[1].value.a = PTA_RPROC_HWCAP_FMT_ELF; + + /* + * Due to stm32mp1 pager, secure memory is too expensive. Support hash + * protected image only, so that firmware image can be loaded from + * non-secure memory. + */ + params[2].value.a = PTA_RPROC_HWCAP_PROT_HASH_TABLE; + + return TEE_SUCCESS; +} + +static TEE_Result rproc_pta_load_segment(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_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT); + TEE_Result res = TEE_ERROR_GENERIC; + paddr_t pa = 0; + void *dst = NULL; + uint8_t *src = params[1].memref.buffer; + size_t size = params[1].memref.size; + uint8_t *hash = params[3].memref.buffer; + paddr_t da = (paddr_t)reg_pair_to_64(params[2].value.b, + params[2].value.a); + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + if (!hash || params[3].memref.size != TEE_SHA256_HASH_SIZE) + return TEE_ERROR_BAD_PARAMETERS; + + if (rproc_ta_state != REMOTEPROC_OFF) + return TEE_ERROR_BAD_STATE; + + /* Get the physical address in local context mapping */ + res = stm32_rproc_da_to_pa(params[0].value.a, da, size, &pa); + if (res) + return res; + + if (stm32_rproc_map(params[0].value.a, pa, size, &dst)) { + EMSG("Can't map region %#"PRIxPA" size %zu", pa, size); + return TEE_ERROR_GENERIC; + } + + /* Copy the segment to the remote processor memory */ + memcpy(dst, src, size); + + /* Verify that loaded segment is valid */ + res = hash_sha256_check(hash, dst, size); + if (res) + memset(dst, 0, size); + + stm32_rproc_unmap(params[0].value.a, dst, size); + + return res; +} + +static TEE_Result rproc_pta_set_memory(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_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT); + TEE_Result res = TEE_ERROR_GENERIC; + paddr_t pa = 0; + void *dst = NULL; + paddr_t da = params[1].value.a; + size_t size = params[2].value.a; + uint8_t value = params[3].value.a && 0xFF; + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + if (rproc_ta_state != REMOTEPROC_OFF) + return TEE_ERROR_BAD_STATE; + + /* Get the physical address in CPU mapping */ + res = stm32_rproc_da_to_pa(params[0].value.a, da, size, &pa); + if (res) + return res; + + res = stm32_rproc_map(params[0].value.a, pa, size, &dst); + if (res) { + EMSG("Can't map region %#"PRIxPA" size %zu", pa, size); + return TEE_ERROR_GENERIC; + } + + memset(dst, value, size); + + return stm32_rproc_unmap(params[0].value.a, dst, size); +} + +static TEE_Result rproc_pta_da_to_pa(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_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT); + TEE_Result res = TEE_ERROR_GENERIC; + paddr_t da = params[1].value.a; + size_t size = params[2].value.a; + paddr_t pa = 0; + + DMSG("Conversion for address %#"PRIxPA" size %zu", da, size); + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + /* Target address is expected 32bit, ensure 32bit MSB are zero */ + if (params[1].value.b || params[2].value.b) + return TEE_ERROR_BAD_PARAMETERS; + + res = stm32_rproc_da_to_pa(params[0].value.a, da, size, &pa); + if (res) + return res; + + reg_pair_from_64((uint64_t)pa, ¶ms[3].value.b, ¶ms[3].value.a); + + return TEE_SUCCESS; +} + +static TEE_Result rproc_pta_start(uint32_t pt, + 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_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + if (rproc_ta_state != REMOTEPROC_OFF) + return TEE_ERROR_BAD_STATE; + + res = stm32_rproc_start(params[0].value.a); + if (res) + return res; + + rproc_ta_state = REMOTEPROC_ON; + + return TEE_SUCCESS; +} + +static TEE_Result rproc_pta_stop(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); + TEE_Result res = TEE_ERROR_GENERIC; + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + if (rproc_ta_state != REMOTEPROC_ON) + return TEE_ERROR_BAD_STATE; + + res = stm32_rproc_stop(params[0].value.a); + if (res) + return res; + + rproc_ta_state = REMOTEPROC_OFF; + + return TEE_SUCCESS; +} + +static TEE_Result rproc_pta_verify_rsa_signature(TEE_Param *hash, + TEE_Param *sig, uint32_t algo) +{ + struct rsa_public_key key = { }; + TEE_Result res = TEE_ERROR_GENERIC; + uint32_t e = TEE_U32_TO_BIG_ENDIAN(rproc_pub_key_exponent); + size_t hash_size = (size_t)hash->memref.size; + size_t sig_size = (size_t)sig->memref.size; + + res = crypto_acipher_alloc_rsa_public_key(&key, sig_size); + if (res) + return res; + + res = crypto_bignum_bin2bn((uint8_t *)&e, sizeof(e), key.e); + if (res) + goto out; + + res = crypto_bignum_bin2bn(rproc_pub_key_modulus, + rproc_pub_key_modulus_size, key.n); + if (res) + goto out; + + res = crypto_acipher_rsassa_verify(algo, &key, hash_size, + hash->memref.buffer, hash_size, + sig->memref.buffer, sig_size); + +out: + crypto_acipher_free_rsa_public_key(&key); + + return res; +} + +static TEE_Result rproc_pta_verify_digest(uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS]) +{ + struct rproc_pta_key_info *keyinfo = NULL; + 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_INPUT); + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + if (!stm32_rproc_get(params[0].value.a)) + return TEE_ERROR_NOT_SUPPORTED; + + if (rproc_ta_state != REMOTEPROC_OFF) + return TEE_ERROR_BAD_STATE; + + keyinfo = params[1].memref.buffer; + + if (!keyinfo || + rproc_pta_keyinfo_size(keyinfo) != params[1].memref.size) + return TEE_ERROR_BAD_PARAMETERS; + + if (keyinfo->algo != TEE_ALG_RSASSA_PKCS1_V1_5_SHA256) + return TEE_ERROR_NOT_SUPPORTED; + + return rproc_pta_verify_rsa_signature(¶ms[2], ¶ms[3], + keyinfo->algo); +} + +static TEE_Result rproc_pta_invoke_command(void *session __unused, + uint32_t cmd_id, + uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + switch (cmd_id) { + case PTA_RPROC_HW_CAPABILITIES: + return rproc_pta_capabilities(param_types, params); + case PTA_RPROC_LOAD_SEGMENT_SHA256: + return rproc_pta_load_segment(param_types, params); + case PTA_RPROC_SET_MEMORY: + return rproc_pta_set_memory(param_types, params); + case PTA_RPROC_FIRMWARE_START: + return rproc_pta_start(param_types, params); + case PTA_RPROC_FIRMWARE_STOP: + return rproc_pta_stop(param_types, params); + case PTA_RPROC_FIRMWARE_DA_TO_PA: + return rproc_pta_da_to_pa(param_types, params); + case PTA_RPROC_VERIFY_DIGEST: + return rproc_pta_verify_digest(param_types, params); + default: + return TEE_ERROR_NOT_IMPLEMENTED; + } +} + +/* + * Pseudo Trusted Application entry points + */ +static TEE_Result rproc_pta_open_session(uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS], + void **sess_ctx __unused) +{ + struct ts_session *s = ts_get_calling_session(); + 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); + struct ts_ctx *ctx = NULL; + TEE_UUID ta_uuid = TA_REMOTEPROC_UUID; + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + if (!s || !is_user_ta_ctx(s->ctx)) + return TEE_ERROR_ACCESS_DENIED; + + /* Check that we're called by the remoteproc Trusted application*/ + ctx = s->ctx; + if (memcmp(&ctx->uuid, &ta_uuid, sizeof(TEE_UUID))) + return TEE_ERROR_ACCESS_DENIED; + + if (!stm32_rproc_get(params[0].value.a)) + return TEE_ERROR_NOT_SUPPORTED; + + return TEE_SUCCESS; +} + +pseudo_ta_register(.uuid = PTA_RPROC_UUID, .name = PTA_NAME, + .flags = PTA_DEFAULT_FLAGS, + .invoke_command_entry_point = rproc_pta_invoke_command, + .open_session_entry_point = rproc_pta_open_session); diff --git a/optee/optee_os/core/pta/stm32mp/rproc_pub_key.h b/optee/optee_os/core/pta/stm32mp/rproc_pub_key.h new file mode 100644 index 0000000..b362565 --- /dev/null +++ b/optee/optee_os/core/pta/stm32mp/rproc_pub_key.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2023, STMicroelectronics - All Rights Reserved + */ + +#ifndef PTA_STM32MP_RPROC_PUB_KEY_H +#define PTA_STM32MP_RPROC_PUB_KEY_H + +#include + +extern const uint32_t rproc_pub_key_exponent; +extern const uint8_t rproc_pub_key_modulus[]; +extern const size_t rproc_pub_key_modulus_size; + +#endif /* PTA_STM32MP_RPROC_PUB_KEY_H */ + 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..53a738d --- /dev/null +++ b/optee/optee_os/core/pta/stm32mp/sub.mk @@ -0,0 +1,2 @@ +srcs-$(CFG_STM32_BSEC_PTA) += bsec_pta.c +srcs-$(CFG_REMOTEPROC_PTA) += remoteproc_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..e7e5e7b --- /dev/null +++ b/optee/optee_os/core/pta/sub.mk @@ -0,0 +1,31 @@ +subdirs-$(CFG_TEE_CORE_EMBED_INTERNAL_TESTS) += tests + +srcs-$(CFG_ATTESTATION_PTA) += attestation.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 +srcs-$(CFG_WIDEVINE_PTA) += widevine.c + +subdirs-y += bcm +subdirs-y += tegra +subdirs-y += stm32mp +subdirs-y += imx +subdirs-y += k3 + +ifeq ($(CFG_REMOTEPROC_PTA),y) +gensrcs-y += rproc_pub_key +produce-rproc_pub_key = rproc_pub_key.c +depends-rproc_pub_key = $(RPROC_SIGN_KEY) scripts/pem_to_pub_c.py +recipe-rproc_pub_key = $(PYTHON3) scripts/pem_to_pub_c.py \ + --prefix rproc_pub_key --key $(RPROC_SIGN_KEY) \ + --out $(sub-dir-out)/rproc_pub_key.c +endif \ No newline at end of file diff --git a/optee/optee_os/core/pta/system.c b/optee/optee_os/core/pta/system.c new file mode 100644 index 0000000..3a1c572 --- /dev/null +++ b/optee/optee_os/core/pta/system.c @@ -0,0 +1,399 @@ +// 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 + +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; + void *seed_bbuf = NULL; + TEE_Result res = TEE_SUCCESS; + 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; + + res = bb_memdup_user(entropy_input, entropy_sz, &seed_bbuf); + if (res) + return res; + + crypto_rng_add_event(CRYPTO_RNG_SRC_NONSECURE, &system_pnum, + seed_bbuf, entropy_sz); + + bb_free(seed_bbuf, 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; + void *subkey_bbuf = NULL; + 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 = bb_alloc(data_len); + if (!data) + return TEE_ERROR_OUT_OF_MEMORY; + + memcpy(data, &uctx->ts_ctx->uuid, sizeof(TEE_UUID)); + + /* Append the user provided data */ + res = copy_from_user(data + sizeof(TEE_UUID), params[0].memref.buffer, + params[0].memref.size); + if (res) + goto out; + + subkey_bbuf = bb_alloc(params[1].memref.size); + if (!subkey_bbuf) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + res = huk_subkey_derive(HUK_SUBKEY_UNIQUE_TA, data, data_len, + subkey_bbuf, params[1].memref.size); + if (res) + goto out; + + res = copy_to_user(params[1].memref.buffer, subkey_bbuf, + params[1].memref.size); + +out: + bb_free_wipe(subkey_bbuf, params[1].memref.size); + bb_free_wipe(data, data_len); + 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 = { }; + uint32_t flags = 0; + + if (exp_pt != param_types) + return TEE_ERROR_BAD_PARAMETERS; + + if (!params[0].memref.buffer || params[0].memref.size != sizeof(uuid)) + return TEE_ERROR_BAD_PARAMETERS; + + res = copy_from_user(&uuid, params[0].memref.buffer, sizeof(uuid)); + if (res) + return res; + + 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; + char *sym = NULL; + TEE_UUID uuid = { }; + size_t symlen = 0; + vaddr_t va = 0; + + if (exp_pt != param_types) + return TEE_ERROR_BAD_PARAMETERS; + + if (!params[0].memref.buffer || params[0].memref.size != sizeof(uuid)) + return TEE_ERROR_BAD_PARAMETERS; + + res = copy_from_user(&uuid, params[0].memref.buffer, sizeof(uuid)); + if (res) + return res; + + if (!params[1].memref.buffer) + return TEE_ERROR_BAD_PARAMETERS; + res = bb_strndup_user(params[1].memref.buffer, params[1].memref.size, + &sym, &symlen); + if (res) + return res; + + s = ts_pop_current_session(); + res = ldelf_dlsym(uctx, &uuid, sym, symlen, &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; + TEE_UUID uuid = { }; + + if (exp_pt != param_types) + return TEE_ERROR_BAD_PARAMETERS; + + if (!params[0].memref.buffer || params[0].memref.size != sizeof(uuid)) + return TEE_ERROR_BAD_PARAMETERS; + + res = copy_from_user(&uuid, params[0].memref.buffer, sizeof(uuid)); + if (res) + return res; + + res = tee_invoke_supp_plugin_rpc(&uuid, + params[1].value.a, /* cmd */ + params[1].value.b, /* sub_cmd */ + NULL, + 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/include/jetson_decrypt_cpubl_payload.h b/optee/optee_os/core/pta/tegra/include/jetson_decrypt_cpubl_payload.h new file mode 100644 index 0000000..d6fe4dd --- /dev/null +++ b/optee/optee_os/core/pta/tegra/include/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/include/jetson_user_key_pta_compute_cmac.h b/optee/optee_os/core/pta/tegra/include/jetson_user_key_pta_compute_cmac.h new file mode 100644 index 0000000..4007775 --- /dev/null +++ b/optee/optee_os/core/pta/tegra/include/jetson_user_key_pta_compute_cmac.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. + */ +#ifndef JETSON_USER_KEY_PTA_COMPUTE_CMAC_H +#define JETSON_USER_KEY_PTA_COMPUTE_CMAC_H + +TEE_Result jetson_user_key_pta_uefi_vars_auth(uint8_t *vars, uint32_t vars_len); + +#endif /* JETSON_USER_KEY_PTA_COMPUTE_CMAC_H */ diff --git a/optee/optee_os/core/pta/tegra/include/jetson_user_key_pta_ftpm.h b/optee/optee_os/core/pta/tegra/include/jetson_user_key_pta_ftpm.h new file mode 100644 index 0000000..7ff6174 --- /dev/null +++ b/optee/optee_os/core/pta/tegra/include/jetson_user_key_pta_ftpm.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. + */ + +#ifndef __JETSON_USER_KEY_PTA_FTPM_H__ +#define __JETSON_USER_KEY_PTA_FTPM_H__ + +typedef enum { + EKB_FTPM_SN = 91, + EKB_FTPM_EPS_SEED, + EKB_FTPM_RSA_EK_CERT, + EKB_FTPM_EC_EK_CERT, + EKB_FTPM_SILICON_ID_CERT, + EKB_FTPM_RSA_EK_CSR, + EKB_FTPM_EC_EK_CSR, + EKB_FTPM_ID_MAX, +} ftpm_ekb_id_t; + +/* Query fTPM EKB properties */ +TEE_Result jetson_user_key_pta_query_ftpm_prop(uint32_t ftpm_ekb_id, + uint8_t **data, + uint32_t *len); + +#endif /* __JETSON_USER_KEY_PTA_FTPM_H__ */ diff --git a/optee/optee_os/core/pta/tegra/jetson_ftpm_helper_pta.c b/optee/optee_os/core/pta/tegra/jetson_ftpm_helper_pta.c new file mode 100644 index 0000000..42b7886 --- /dev/null +++ b/optee/optee_os/core/pta/tegra/jetson_ftpm_helper_pta.c @@ -0,0 +1,768 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define EC_P256_KEY_BIT_SIZE 256UL +#define EC_P256_KEY_BYTE_SIZE (EC_P256_KEY_BIT_SIZE / 8) + +/* The seed size = max secure strength (256 bit) * 2 */ +#define FTPM_EPS_ROOT_SEED_SIZE 64UL +#define FTPM_EPS_SIZE 64UL +#define FTPM_MB2_FTPM_SEED_SIZE 32UL +#define FTPM_HELPER_PTA_NAME "jetson_ftpm_helper.pta" + +/* fTPM Properties */ +enum ftpm_ekb_cont { + FTPM_PROP_RSA_EK_CERT, + FTPM_PROP_EC_EK_CERT, + FTPM_PROP_SID_CERT, + FTPM_PROP_FW_ID_CERT, + FTPM_PROP_RSA_EK_CSR, + FTPM_PROP_EC_EK_CSR, +}; + +/* fTPM EKB Content */ +enum ftpm_prov_mode { + FTPM_PROV_MODE_UNKNOWN, + FTPM_PROV_MODE_OFFLINE, + FTPM_PROV_MODE_ONLINE, +}; + +enum ftpm_ekb_cont_flag { + FTPM_EKB_FLAG_SN = 1 << 0, + FTPM_EKB_FLAG_EPS_SEED = 1 << 1, + FTPM_EKB_FLAG_RSA_EK_CERT = 1 << 2, + FTPM_EKB_FLAG_EC_EK_CERT = 1 << 3, + FTPM_EKB_FLAG_SID_CERT = 1 << 4, + FTPM_EKB_FLAG_RSA_EK_CSR = 1 << 5, + FTPM_EKB_FLAG_EC_EK_CSR = 1 << 6, +}; + +typedef struct { + enum ftpm_prov_mode prov_mode; + enum ftpm_ekb_cont_flag cont_flag; + uint8_t *ftpm_sn; + uint32_t len_ftpm_sn; + uint8_t *ftpm_eps_seed; + uint32_t len_ftpm_eps_seed; + uint8_t *rsa_ek_cert; + uint32_t len_rsa_ek_cert; + uint8_t *ec_ek_cert; + uint32_t len_ec_ek_cert; + uint8_t *sid_cert; + uint32_t len_sid_cert; + uint8_t *rsa_ek_csr; + uint32_t len_rsa_ek_csr; + uint8_t *ec_ek_csr; + uint32_t len_ec_ek_csr; +} ftpm_ekb_t; + +/* + * fTPM TA UUID: BC50D971-D4C9-42C4-82CB-343FB7F37896 + */ +#define FTPM_TA_UUID \ + { 0xBC50D971, 0xD4C9, 0x42C4, \ + {0x82, 0xCB, 0x34, 0x3F, 0xB7, 0xF3, 0x78, 0x96} } + +typedef struct { + struct ecc_keypair fw_id_key; + uint8_t *ftpm_seed; + uint32_t len_ftpm_seed; + uint8_t *fw_id_priv_key; + uint32_t len_fw_id_priv_key; + uint8_t *fw_id_cert; + uint32_t len_fw_id_cert; + ftpm_ekb_t ekb; + bool is_ready; +} ftpm_property_t; +static ftpm_property_t ftpm_property; + +/* Sessions opened by fTPM helper pta */ +static struct tee_ta_session_head tee_ftpm_sessions = +TAILQ_HEAD_INITIALIZER(tee_ftpm_sessions); + +#if defined(CFG_JETSON_FTPM_HELPER_INJECT_EPS) +static uint8_t external_eps[FTPM_EPS_SIZE]; +#endif + +static TEE_Result ping_ns_world(uint32_t ptypes, + TEE_Param params[TEE_NUM_PARAMS]) +{ + tee_ree_state state; + uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (exp_pt != ptypes) + return TEE_ERROR_BAD_PARAMETERS; + + state = tee_get_ree_state(); + if (state == TEE_REE_STATE_REE_SUPP) + params[0].value.a = FTPM_HELPER_PTA_NS_STATE_READY; + else + params[0].value.a = FTPM_HELPER_PTA_NS_STATE_NOT_READY; + + return TEE_SUCCESS; +} + +static TEE_Result query_sn(uint32_t ptypes, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result rc = TEE_SUCCESS; + uint32_t exp_pt; + uint8_t *sn_buf = NULL; + uint32_t sn_len; + + /* Validate the input parameters. */ + exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + if (exp_pt != ptypes) + return TEE_ERROR_BAD_PARAMETERS; + + if (params[0].memref.size != FTPM_HELPER_PTA_SN_LENGTH) + return TEE_ERROR_BAD_PARAMETERS; + + rc = tegra_fuse_get_sn(&sn_buf, &sn_len); + if (rc == TEE_SUCCESS && sn_len != params[0].memref.size) + return TEE_ERROR_SHORT_BUFFER; + + memcpy(params[0].memref.buffer, sn_buf, params[0].memref.size); + + return rc; +} + +static TEE_Result query_ecid(uint32_t ptypes, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result rc = TEE_SUCCESS; + uint32_t exp_pt; + + /* Validate the input parameters. */ + exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + if (exp_pt != ptypes) + return TEE_ERROR_BAD_PARAMETERS; + + if (params[0].memref.size != FTPM_HELPER_PTA_ECID_LENGTH) + return TEE_ERROR_BAD_PARAMETERS; + + rc = tegra_fuse_get_64bit_ecid((uint64_t *)params[0].memref.buffer); + + return rc; +} + +static TEE_Result query_prov_mode(uint32_t ptypes, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result rc = TEE_SUCCESS; + uint32_t exp_pt; + + if (!ftpm_property.is_ready) + return TEE_ERROR_NOT_SUPPORTED; + + exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE); + if (exp_pt != ptypes) + return TEE_ERROR_BAD_PARAMETERS; + + switch (ftpm_property.ekb.prov_mode) { + case FTPM_PROV_MODE_OFFLINE: + params[0].value.a = FTPM_HELPER_PTA_OFFLINE_PROV_MODE; + break; + case FTPM_PROV_MODE_ONLINE: + params[0].value.a = FTPM_HELPER_PTA_ONLINE_PROV_MODE; + break; + default: + params[0].value.a = FTPM_HELPER_PTA_UNKNOWN_PROV_MODE; + break; + } + + params[1].value.a = FTPM_HELPER_PTA_VERSION_MAJOR; + params[2].value.a = FTPM_HELPER_PTA_VERSION_MINOR; + + return rc; +} + +/* Query for the certificate or CSR properties. */ +static TEE_Result query_ftpm_prop(uint32_t prop_type, + uint32_t ptypes, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result rc = TEE_SUCCESS; + uint32_t exp_pt; + uint8_t *cert_buf_addr = NULL; + uint32_t cert_len = 0; + + if (!ftpm_property.is_ready) + return TEE_ERROR_NOT_SUPPORTED; + + exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + if (exp_pt != ptypes) + return TEE_ERROR_BAD_PARAMETERS; + + if (params[0].memref.size < FTPM_HELPER_PTA_EK_CERT_BUF_SIZE) + return TEE_ERROR_BAD_PARAMETERS; + + switch (prop_type) { + case FTPM_PROP_RSA_EK_CERT: + cert_buf_addr = ftpm_property.ekb.rsa_ek_cert; + cert_len = ftpm_property.ekb.len_rsa_ek_cert; + break; + case FTPM_PROP_EC_EK_CERT: + cert_buf_addr = ftpm_property.ekb.ec_ek_cert; + cert_len = ftpm_property.ekb.len_ec_ek_cert; + break; + case FTPM_PROP_SID_CERT: + cert_buf_addr = ftpm_property.ekb.sid_cert; + cert_len = ftpm_property.ekb.len_sid_cert; + break; + case FTPM_PROP_FW_ID_CERT: + cert_buf_addr = ftpm_property.fw_id_cert; + cert_len = ftpm_property.len_fw_id_cert; + break; + case FTPM_PROP_RSA_EK_CSR: + cert_buf_addr = ftpm_property.ekb.rsa_ek_csr; + cert_len = ftpm_property.ekb.len_rsa_ek_csr; + break; + case FTPM_PROP_EC_EK_CSR: + cert_buf_addr = ftpm_property.ekb.ec_ek_csr; + cert_len = ftpm_property.ekb.len_ec_ek_csr; + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + }; + + if (!cert_buf_addr || cert_len == 0) + return TEE_ERROR_NO_DATA; + + if (cert_len > FTPM_HELPER_PTA_EK_CERT_BUF_SIZE) + return TEE_ERROR_SHORT_BUFFER; + + memcpy(params[0].memref.buffer, cert_buf_addr, cert_len); + params[0].memref.size = cert_len; + + return rc; +} + +static TEE_Result sign_ek_csr_digest(uint32_t ptypes, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result rc = TEE_SUCCESS; + uint32_t exp_pt; + + /* Validate the input parameters. */ + 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 != ptypes) + return TEE_ERROR_BAD_PARAMETERS; + + if ((TEE_SHA256_HASH_SIZE != params[0].memref.size) || + (FTPM_EK_CSR_SIG_SIZE != params[1].memref.size)) + return TEE_ERROR_BAD_PARAMETERS; + + rc = crypto_acipher_ecc_sign(TEE_ALG_ECDSA_SHA256, + &ftpm_property.fw_id_key, + params[0].memref.buffer, + params[0].memref.size, + params[1].memref.buffer, + ¶ms[1].memref.size); + + return rc; +} + +#if defined(CFG_JETSON_FTPM_HELPER_INJECT_EPS) +static TEE_Result inject_eps(uint32_t ptypes, TEE_Param params[TEE_NUM_PARAMS]) +{ + uint32_t exp_pt; + + /* Validate the input parameters. */ + 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 != ptypes) + return TEE_ERROR_BAD_PARAMETERS; + + if (!params[0].memref.buffer || params[0].memref.size != FTPM_EPS_SIZE) + return TEE_ERROR_BAD_PARAMETERS; + + memcpy(external_eps, params[0].memref.buffer, FTPM_EPS_SIZE); + return TEE_SUCCESS; +} +#endif + +static TEE_Result invoke_command(void *psess __unused, + uint32_t cmd, uint32_t ptypes, + TEE_Param params[TEE_NUM_PARAMS]) +{ + switch (cmd) { + case FTPM_HELPER_PTA_CMD_PING_NS: + return ping_ns_world(ptypes, params); + case FTPM_HELPER_PTA_CMD_QUERY_SN: + return query_sn(ptypes, params); + case FTPM_HELPER_PTA_CMD_QUERY_ECID: + return query_ecid(ptypes, params); + case FTPM_HELPER_PTA_CMD_QUERY_PROV_MODE: + return query_prov_mode(ptypes, params); + case FTPM_HELPER_PTA_CMD_GET_RSA_EK_CERT: + return query_ftpm_prop(FTPM_PROP_RSA_EK_CERT, ptypes, params); + case FTPM_HELPER_PTA_CMD_GET_EC_EK_CERT: + return query_ftpm_prop(FTPM_PROP_EC_EK_CERT, ptypes, params); + case FTPM_HELPER_PTA_CMD_GET_SID_CERT: + return query_ftpm_prop(FTPM_PROP_SID_CERT, ptypes, params); + case FTPM_HELPER_PTA_CMD_GET_FW_ID_CERT: + return query_ftpm_prop(FTPM_PROP_FW_ID_CERT, ptypes, params); + case FTPM_HELPER_PTA_CMD_GET_RSA_EK_CSR: + return query_ftpm_prop(FTPM_PROP_RSA_EK_CSR, ptypes, params); + case FTPM_HELPER_PTA_CMD_GET_EC_EK_CSR: + return query_ftpm_prop(FTPM_PROP_EC_EK_CSR, ptypes, params); + case FTPM_HELPER_PTA_CMD_SIGN_EK_CSR: + return sign_ek_csr_digest(ptypes, params); +#if defined(CFG_JETSON_FTPM_HELPER_INJECT_EPS) + case FTPM_HELPER_PTA_CMD_INJECT_EPS: + return inject_eps(ptypes, params); +#endif + default: + break; + } + + return TEE_ERROR_NOT_IMPLEMENTED; +} + +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 = FTPM_HELPER_PTA_UUID, + .name = FTPM_HELPER_PTA_NAME, + .flags = PTA_DEFAULT_FLAGS, + .open_session_entry_point = open_session, + .invoke_command_entry_point = invoke_command); + +static TEE_Result get_prop_endorsement_seed(struct ts_session *sess __maybe_unused, + void *buf, size_t *blen) +{ + TEE_Result rc = TEE_SUCCESS; + uint8_t eps[FTPM_EPS_SIZE] = { 0 }; + uint32_t eps_len = sizeof(eps); + uint8_t root_seed[FTPM_EPS_ROOT_SEED_SIZE] = { 0 }; + uint8_t *sn = NULL; + uint32_t len_sn; + static const char root_seed_info[] = {'R', 'o', 'o', 't', '_', + 'S', 'e', 'e', 'd'}; + static const uint8_t root_seed_salt[] = { 0x00 }; + const TEE_UUID ftpm_ta_uuid = FTPM_TA_UUID; + bool is_allowed_ta = false; + +#if defined(CFG_JETSON_FTPM_HELPER_INJECT_EPS) + memcpy(eps, external_eps, eps_len); + goto out; +#endif + + /* Check that we're called by the fTPM TA */ + if (memcmp(&sess->ctx->uuid, &ftpm_ta_uuid, sizeof(TEE_UUID)) == 0) + is_allowed_ta = true; + + /* + * For xtest regression 1006 test. + * + * Caution: + * When fTPM is enabled, please make sure the TA_SIGN_KEY has been + * replaced by your private key to avoid the malicious REE FS TA to + * be loaded and executed by the OP-TEE which could cause the EPS + * leakage. By default, the query is only allowed by the fTPM TA. + * Otherwise always returns 16 byte zero values. + */ + if (!is_allowed_ta) { + uint32_t zlen = 16; + + if (*blen > zlen) + memset(buf, 0, zlen); + else + memset(buf, 0, *blen); + *blen = zlen; + + return TEE_SUCCESS; + } + + if (!ftpm_property.is_ready) + return TEE_ERROR_ITEM_NOT_FOUND; + + if (!ftpm_property.ftpm_seed || !ftpm_property.ekb.ftpm_sn) + return TEE_ERROR_BAD_STATE; + + /* Derive fTPM Root Seed. */ + rc = tee_cryp_hkdf(TEE_MAIN_ALGO_SHA256, + ftpm_property.ftpm_seed, + ftpm_property.len_ftpm_seed, + root_seed_salt, sizeof(root_seed_salt), + (uint8_t *)root_seed_info, sizeof(root_seed_info), + root_seed, sizeof(root_seed)); + if (rc != TEE_SUCCESS) + goto out; + + rc = tegra_fuse_get_sn(&sn, &len_sn); + if (rc != TEE_SUCCESS) + goto out; + + if (memcmp(sn, ftpm_property.ekb.ftpm_sn, len_sn) != 0) { + rc = TEE_ERROR_ACCESS_DENIED; + goto out; + } + + /* Derive EPS. */ + rc = tee_cryp_hkdf(TEE_MAIN_ALGO_SHA256, + root_seed, sizeof(root_seed), + ftpm_property.ekb.ftpm_eps_seed, + ftpm_property.ekb.len_ftpm_eps_seed, + sn, len_sn, + eps, sizeof(eps)); + +out: + if (rc != TEE_SUCCESS) + return rc; + + if (*blen < sizeof(eps)) + eps_len = *blen; + else + *blen = sizeof(eps); + + return copy_to_user(buf, eps, eps_len); +} + +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_seed, + }, +}; + +const struct tee_vendor_props vendor_props_tee = { + .props = vendor_propset_array_tee, + .len = ARRAY_SIZE(vendor_propset_array_tee), +}; + +static const char *const ftpm_helper_dt_match_table[] = { + "nvidia,ftpm-contents", +}; + +static TEE_Result dt_get_sub_node_data(void *fdt, + const char *comp_str, + void **ret_addr, + uint32_t *ret_len) +{ + TEE_Result rc = TEE_SUCCESS; + int node = -1; + paddr_t pbase; + ssize_t sz; + uint8_t *reg_addr = NULL; + uint8_t *tmp_addr = NULL; + + node = fdt_node_offset_by_compatible(fdt, 0, comp_str); + if (node < 0) { + rc = TEE_ERROR_ITEM_NOT_FOUND; + goto fail; + } + + if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC) { + IMSG("The DICE DT sub node \"%s\" is not enabled.\n", comp_str); + rc = TEE_ERROR_GENERIC; + goto fail; + } + + pbase = fdt_reg_base_address(fdt, node); + if (pbase == DT_INFO_INVALID_REG) { + rc = TEE_ERROR_GENERIC; + goto fail; + } + + sz = fdt_reg_size(fdt, node); + if (sz < 0) { + rc = TEE_ERROR_GENERIC; + goto fail; + } + + reg_addr = (uint8_t *)core_mmu_add_mapping(MEM_AREA_RAM_SEC, pbase, sz); + if (!reg_addr) { + EMSG("Failed to map (%s) %zu bytes at PA 0x%"PRIxPA, + comp_str, (size_t)sz, pbase); + rc = TEE_ERROR_GENERIC; + goto fail; + } + + tmp_addr = calloc(1, sz); + if (!tmp_addr) { + rc = TEE_ERROR_OUT_OF_MEMORY; + goto fail; + } + memcpy(tmp_addr, reg_addr, sz); + *ret_addr = (void *)tmp_addr; + *ret_len = sz; + + /* Clear the source. */ + memset(reg_addr, 0, sz); + +fail: + if (reg_addr) + core_mmu_remove_mapping(MEM_AREA_RAM_SEC, reg_addr, sz); + + return rc; +} + +static TEE_Result ftpm_helper_dt_init(void) +{ + TEE_Result rc = TEE_SUCCESS; + void *fdt = NULL; + int node = -1; + uint32_t i = 0; + static const char ftpm_seed_str[] = "nvidia,ftpm-seed"; + static const char fw_id_priv_key_str[] = "nvidia,ftpm-firmware-id-privkey"; + static const char fw_id_cert_str[] = "nvidia,ftpm-firmware-id-certificate"; + + fdt = get_dt(); + if (!fdt) { + EMSG("%s: DTB is not present.", __func__); + rc = TEE_ERROR_ITEM_NOT_FOUND; + goto fail; + } + + for (i = 0; i < ARRAY_SIZE(ftpm_helper_dt_match_table); i++) { + node = fdt_node_offset_by_compatible(fdt, 0, + ftpm_helper_dt_match_table[i]); + if (node >= 0) + break; + } + + if (node < 0) { + EMSG("%s: DT not found (%x).", __func__, node); + rc = TEE_ERROR_ITEM_NOT_FOUND; + goto fail; + } + + if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC) { + IMSG("fTPM ID is not enabled.\n"); + rc = TEE_ERROR_GENERIC; + goto fail; + } + + /* fTPM Seed */ + rc = dt_get_sub_node_data(fdt, ftpm_seed_str, + (void *)&ftpm_property.ftpm_seed, + &ftpm_property.len_ftpm_seed); + if (rc) + goto fail; + + if (ftpm_property.len_ftpm_seed != FTPM_MB2_FTPM_SEED_SIZE) { + rc = TEE_ERROR_BAD_FORMAT; + goto fail; + } + + /* Firmware ID priv key */ + rc = dt_get_sub_node_data(fdt, fw_id_priv_key_str, + (void *)&ftpm_property.fw_id_priv_key, + &ftpm_property.len_fw_id_priv_key); + if (rc) + goto fail; + + if (ftpm_property.len_fw_id_priv_key != EC_P256_KEY_BYTE_SIZE) { + rc = TEE_ERROR_BAD_FORMAT; + goto fail; + } + + crypto_bignum_bin2bn(ftpm_property.fw_id_priv_key, + EC_P256_KEY_BYTE_SIZE, + ftpm_property.fw_id_key.d); + + /* Firmware ID Certificate */ + rc = dt_get_sub_node_data(fdt, fw_id_cert_str, + (void *)&ftpm_property.fw_id_cert, + &ftpm_property.len_fw_id_cert); + if (rc) + goto fail; + +fail: + return rc; +} + +static TEE_Result ftpm_helper_ekb_init(void) +{ + TEE_Result rc = TEE_SUCCESS; + + rc = jetson_user_key_pta_query_ftpm_prop(EKB_FTPM_SN, + &ftpm_property.ekb.ftpm_sn, + &ftpm_property.ekb.len_ftpm_sn); + if (rc == TEE_SUCCESS) + ftpm_property.ekb.cont_flag |= FTPM_EKB_FLAG_SN; + + rc = jetson_user_key_pta_query_ftpm_prop(EKB_FTPM_EPS_SEED, + &ftpm_property.ekb.ftpm_eps_seed, + &ftpm_property.ekb.len_ftpm_eps_seed); + if (rc == TEE_SUCCESS) + ftpm_property.ekb.cont_flag |= FTPM_EKB_FLAG_EPS_SEED; + + if (!(ftpm_property.ekb.cont_flag & FTPM_EKB_FLAG_SN) || + !(ftpm_property.ekb.cont_flag & FTPM_EKB_FLAG_EPS_SEED)) { + rc = TEE_ERROR_BAD_FORMAT; + goto fail; + } + + rc = jetson_user_key_pta_query_ftpm_prop(EKB_FTPM_RSA_EK_CERT, + &ftpm_property.ekb.rsa_ek_cert, + &ftpm_property.ekb.len_rsa_ek_cert); + if (rc == TEE_SUCCESS) + ftpm_property.ekb.cont_flag |= FTPM_EKB_FLAG_RSA_EK_CERT; + + rc = jetson_user_key_pta_query_ftpm_prop(EKB_FTPM_EC_EK_CERT, + &ftpm_property.ekb.ec_ek_cert, + &ftpm_property.ekb.len_ec_ek_cert); + if (rc == TEE_SUCCESS) + ftpm_property.ekb.cont_flag |= FTPM_EKB_FLAG_EC_EK_CERT; + + if (ftpm_property.ekb.cont_flag & FTPM_EKB_FLAG_RSA_EK_CERT && + ftpm_property.ekb.cont_flag & FTPM_EKB_FLAG_EC_EK_CERT) + ftpm_property.ekb.prov_mode = FTPM_PROV_MODE_OFFLINE; + + rc = jetson_user_key_pta_query_ftpm_prop(EKB_FTPM_SILICON_ID_CERT, + &ftpm_property.ekb.sid_cert, + &ftpm_property.ekb.len_sid_cert); + if (rc == TEE_SUCCESS) + ftpm_property.ekb.cont_flag |= FTPM_EKB_FLAG_SID_CERT; + + rc = jetson_user_key_pta_query_ftpm_prop(EKB_FTPM_RSA_EK_CSR, + &ftpm_property.ekb.rsa_ek_csr, + &ftpm_property.ekb.len_rsa_ek_csr); + if (rc == TEE_SUCCESS) + ftpm_property.ekb.cont_flag |= FTPM_EKB_FLAG_RSA_EK_CSR; + + rc = jetson_user_key_pta_query_ftpm_prop(EKB_FTPM_EC_EK_CSR, + &ftpm_property.ekb.ec_ek_csr, + &ftpm_property.ekb.len_ec_ek_csr); + if (rc == TEE_SUCCESS) + ftpm_property.ekb.cont_flag |= FTPM_EKB_FLAG_EC_EK_CSR; + + if (ftpm_property.ekb.cont_flag & FTPM_EKB_FLAG_SID_CERT && + ftpm_property.ekb.cont_flag & FTPM_EKB_FLAG_RSA_EK_CSR && + ftpm_property.ekb.cont_flag & FTPM_EKB_FLAG_EC_EK_CSR) + ftpm_property.ekb.prov_mode = FTPM_PROV_MODE_ONLINE; + + if (ftpm_property.ekb.prov_mode == FTPM_PROV_MODE_UNKNOWN) + rc = TEE_ERROR_BAD_FORMAT; + else + rc = TEE_SUCCESS; + +fail: + return rc; +} + +static TEE_Result init_ftpm_ta(void) +{ + TEE_Result rc = TEE_SUCCESS; + static const TEE_UUID ftpm_ta_uuid = FTPM_TA_UUID; + TEE_UUID pta_uuid = FTPM_HELPER_PTA_UUID; + TEE_ErrorOrigin err_orig = TEE_ORIGIN_TEE; + struct tee_ta_session *s = NULL; + struct tee_ta_param param; + TEE_Identity clnt_id; + + clnt_id.login = TEE_LOGIN_TRUSTED_APP; + memcpy(&clnt_id.uuid, &pta_uuid, sizeof(TEE_UUID)); + param.types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + rc = tee_ta_open_session(&err_orig, &s, &tee_ftpm_sessions, + &ftpm_ta_uuid, &clnt_id, + TEE_TIMEOUT_INFINITE, ¶m); + if (rc != TEE_SUCCESS) { + DMSG("Fail to open session with fTPM TA"); + return rc; + } + + tee_ta_close_session(s, &tee_ftpm_sessions, &clnt_id); + + return rc; +} + +static TEE_Result jetson_ftpm_helper_pta_init(void) +{ + TEE_Result rc = TEE_SUCCESS; + + /* Launch fTPM TA */ + rc = init_ftpm_ta(); + + /* Initialize fTPM properties */ + memset(&ftpm_property, 0, sizeof(ftpm_property_t)); +#if defined(CFG_JETSON_FTPM_HELPER_INJECT_EPS) + memset(external_eps, 0, sizeof(external_eps)); +#endif + + /* Alloc the Firmware ID key */ + rc = crypto_acipher_alloc_ecc_keypair(&ftpm_property.fw_id_key, + TEE_TYPE_ECDSA_KEYPAIR, + EC_P256_KEY_BIT_SIZE); + if (rc != TEE_SUCCESS) + goto ftpm_prop_fail; + + ftpm_property.fw_id_key.curve = TEE_ECC_CURVE_NIST_P256; + + rc = ftpm_helper_dt_init(); + if (rc != TEE_SUCCESS) + goto ftpm_prop_fail; + + rc = ftpm_helper_ekb_init(); + +ftpm_prop_fail: + if (rc != TEE_SUCCESS) { + IMSG("ftpm-helper PTA: fTPM DT or EKB is not available. fTPM provisioning is not supported."); + ftpm_property.is_ready = false; + } else { + ftpm_property.is_ready = true; + } + + return TEE_SUCCESS; +} + +driver_init_late(jetson_ftpm_helper_pta_init); 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..5d60b73 --- /dev/null +++ b/optee/optee_os/core/pta/tegra/jetson_user_key_pta.c @@ -0,0 +1,1163 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021-2024, 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" +#include "jetson_user_key_pta_compute_cmac.h" +#include "jetson_user_key_pta_ftpm.h" + +#define MAX_EKB_RK 2 +#define JETSON_USER_KEY_PTA_NAME "jetson_user_key_pta.ta" + +#if defined(PLATFORM_FLAVOR_t194) || defined(PLATFORM_FLAVOR_t234) +#define EKB_MEMORY_AREA_TYPE MEM_AREA_RAM_SEC +#endif + +/* Magic of EKB header */ +#define EKB_MAGIC_STR "NVEKBP" +/* Magic of EKB content header */ +#define EKB_CONTENT_MAGIC_STR "EEKB" +/* The minimum size of EKB */ +#define EKB_MIN_SIZE 1024U + +static vaddr_t ekb_base_addr; + +/* + * The latest EKB layout: version 2 + * + * ----------------------------------------------------------- + * | EKB_size | Magic | Major | Minor | + * | (4 bytes) | (8 bytes) | (2 bytes) | (2 bytes) | + * ----------------------------------------------------------- + * | FV (16 bytes) | + * ----------------------------------------------------------- + * | MAC (16 bytes) | + * ----------------------------------------------------------- + * | Content_size | Content_magic | Reserved | + * | (4 bytes) | (4 bytes) | (8 bytes) | + * ----------------------------------------------------------- + * | IV (16 bytes) | + * ----------------------------------------------------------- + * | Key1_tag | Key1_len | Key1 | + * | (4 bytes) | (4 bytes) | (Key1_len) | + * ----------------------------------------------------------- + * | Key2_tag | Key2_len | Key2 | + * | (4 bytes) | (4 bytes) | (Key2_len) | + * ----------------------------------------------------------- + * | ... | + * ----------------------------------------------------------- + * | End_tag1(\0\0\0\0) | End_tag2 (\0\0\0\0) | + * ----------------------------------------------------------- + */ + +/* + * EKB version 1: FV is hardcoded in the EKB generation tool and in + * the EKB handling here. + * EKB version 2: FV is randomly generated by the EKB generation tool + * and stored right after EKB header. + */ + +/* + * Fixed vector for EKB version 1. + */ +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_header { + uint32_t ekb_size; + char ekb_magic[8]; + uint16_t ver_maj; + uint16_t ver_min; +}; + +struct ekb_content_header { + uint32_t enc_data_len; + char ekb_content_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 get_ekb_content_start_addr(vaddr_t ekb_addr, + vaddr_t *ekb_content_addr) +{ + struct ekb_header *header; + + if (ekb_addr == 0 || !ekb_content_addr) + return TEE_ERROR_BAD_PARAMETERS; + + header = (struct ekb_header *)ekb_addr; + + if (header->ekb_size < EKB_MIN_SIZE) + return TEE_ERROR_BAD_FORMAT; + + if (strncmp((char *)EKB_MAGIC_STR, header->ekb_magic, strlen(EKB_MAGIC_STR))) + return TEE_ERROR_BAD_FORMAT; + + if (header->ver_maj == 1) { + *ekb_content_addr = ekb_addr + sizeof(struct ekb_header); + } else if (header->ver_maj == 2) { + memcpy(fv_for_ekb, header + 1, sizeof(fv_for_ekb)); + *ekb_content_addr = ekb_addr + sizeof(struct ekb_header) + + sizeof(fv_for_ekb); + } else { + return TEE_ERROR_BAD_FORMAT; + } + + return TEE_SUCCESS; +} + +static TEE_Result ekb_extraction_process(vaddr_t ekb_content_addr) +{ + TEE_Result rc = TEE_SUCCESS; + struct ekb_content *ekb; + struct ekb_content_header *content_header; + 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 (ekb_content_addr == 0) + return TEE_ERROR_BAD_PARAMETERS; + + ekb = (struct ekb_content *)ekb_content_addr; + content_header = &ekb->content_header; + if (strncmp((char *)EKB_CONTENT_MAGIC_STR, + content_header->ekb_content_magic, + strlen(EKB_CONTENT_MAGIC_STR))) + 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; +} + +/* + * Get keys from ekb without check. + * + * NOTE: + * Since this function can get any key from ekb without checking, + * the caller should take the responsibility of checking the key type. + */ +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_user_key_pta_get_user_key(uint8_t **key, + uint32_t *key_len, + uint32_t key_type) +{ + TEE_Result rc = TEE_SUCCESS; + struct user_key *ekb_key = NULL; + + if (!key || !key_len) + return TEE_ERROR_BAD_PARAMETERS; + + if (key_type >= EKB_USER_KEY_NUM_MAX) + return TEE_ERROR_BAD_PARAMETERS; + + rc = jetson_pta_get_key_by_type(&ekb_key, key_type); + if (rc) + return rc; + + *key = ekb_key->data; + *key_len = ekb_key->len; + + return rc; +} + +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; + uint8_t *key = NULL; + uint32_t key_len = 0; + + if (exp_pt != ptypes) + return TEE_ERROR_BAD_PARAMETERS; + + rc = jetson_user_key_pta_get_user_key(&key, &key_len, key_type); + if (rc) + return rc; + + if (key_len <= params[1].memref.size) { + memcpy(params[1].memref.buffer, key, key_len); + params[1].memref.size = 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; + uint32_t key_len; + uint32_t key_type = params[0].value.a; + + if ((exp_pt != ptypes) || + (params[1].memref.size == 0)) { + return TEE_ERROR_BAD_PARAMETERS; + } + + rc = jetson_user_key_pta_get_user_key(&key, &key_len, key_type); + if (rc) + return rc; + + 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, key_len, + 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 TEE_Result jetson_pta_is_user_key_exists(uint32_t ptypes, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint32_t key_type; + uint8_t *key; + uint32_t key_len; + 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_user_key_pta_get_user_key(&key, &key_len, key_type)) + goto out; + + if ((key_len != TEGRA_SE_KEY_128_SIZE) + && (key_len != TEGRA_SE_KEY_256_SIZE)) + 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; + uint8_t *key; + uint32_t key_len; + 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_user_key_pta_get_user_key(&key, &key_len, key_type); + if (rc) + goto error; + + rc = jetson_decrypt_cpubl_payload_process_params(&ctx, + key, 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_user_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 get_oem_key_valid(bool *valid) +{ + TEE_Result rc = TEE_SUCCESS; + uint32_t bsi = 0; + + if (!valid) + return TEE_ERROR_BAD_PARAMETERS; + + rc = tegra_fuse_get_bsi(&bsi); + if (rc) { + EMSG("Read fuse BSI failed: 0x%x", rc); + return rc; + } + + if ((bsi & BSI_OEM_KEY_VALID_MASK) == 0) + *valid = false; + else + *valid = true; + + return rc; +} + +static TEE_Result get_sec_mode_enabled(bool *enabled) +{ + TEE_Result rc = TEE_SUCCESS; + uint32_t sec_mode = 0; + + if (!enabled) + return TEE_ERROR_BAD_PARAMETERS; + + rc = tegra_fuse_get_sec_mode(&sec_mode); + if (rc) { + EMSG("Read fuse security mode failed: 0x%x", rc); + return rc; + } + + if ((sec_mode & SECURITY_MODE_ENABLED_MASK) == 0) + *enabled = false; + else + *enabled = true; + + return rc; +} + +TEE_Result jetson_user_key_pta_uefi_vars_auth(uint8_t *vars, uint32_t vars_len) +{ + TEE_Result rc = TEE_SUCCESS; + uint32_t key_type = EKB_USER_KEY_UEFI_VAR_AUTH; + uint8_t *key; + uint32_t key_len = 16; + void *cmac_ctx = NULL; + bool key_valid; + bool sec_enabled; + /* test UEFI variable auth key: d9f7b49e3b6264985f1326f541bb43c9 */ + uint8_t uefi_vars_auth_key_test[] = { + 0xd9, 0xf7, 0xb4, 0x9e, 0x3b, 0x62, 0x64, 0x98, + 0x5f, 0x13, 0x26, 0xf5, 0x41, 0xbb, 0x43, 0xc9 + }; + + if (!vars || vars_len < TEE_AES_BLOCK_SIZE) + return TEE_ERROR_BAD_PARAMETERS; + + /* Get UEFI variables authentication key */ + rc = jetson_user_key_pta_get_user_key(&key, &key_len, key_type); + if (rc) { + if ((get_oem_key_valid(&key_valid) != TEE_SUCCESS) || + (get_sec_mode_enabled(&sec_enabled) != TEE_SUCCESS)) { + EMSG("Failed to get oem key valid or get security mode !"); + goto error; + } else { + if (key_valid || sec_enabled) { + EMSG("UEFI variable auth key not set !"); + goto error; + } else { + IMSG("WARNING: Test UEFI variable auth " + "key is being used !"); + IMSG("WARNING: UEFI variable protection " + "is not fully enabled !"); + key = uefi_vars_auth_key_test; + } + } + } + + /* Calculate AES-CMAC for uefi variables */ + rc = crypto_mac_alloc_ctx(&cmac_ctx, TEE_ALG_AES_CMAC); + if (rc) + goto error; + + rc = crypto_mac_init(cmac_ctx, key, key_len); + if (rc) + goto error; + + rc = crypto_mac_update(cmac_ctx, vars, vars_len); + if (rc) + goto error; + + rc = crypto_mac_final(cmac_ctx, vars, TEE_AES_BLOCK_SIZE); + if (rc) + goto error; + +error: + if (cmac_ctx) + crypto_mac_free_ctx(cmac_ctx); + + return rc; +} + +TEE_Result jetson_user_key_pta_query_ftpm_prop(uint32_t ftpm_ekb_id, + uint8_t **data, + uint32_t *len) +{ + TEE_Result rc = TEE_SUCCESS; + struct user_key *ekb_key = NULL; + + if ((ftpm_ekb_id < EKB_FTPM_SN) || (ftpm_ekb_id >= EKB_FTPM_ID_MAX)) + return TEE_ERROR_ITEM_NOT_FOUND; + + rc = jetson_pta_get_key_by_type(&ekb_key, ftpm_ekb_id); + if (rc == TEE_SUCCESS) { + *data = ekb_key->data; + *len = ekb_key->len; + } + + return rc; +} + +static TEE_Result jetson_ekb_dt_init(void) +{ + TEE_Result rc = TEE_SUCCESS; + void *fdt = NULL; + void *reg_addr = NULL; + void *tmp_addr = 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__); + rc = TEE_ERROR_ITEM_NOT_FOUND; + goto fail; + } + + 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); + rc = TEE_ERROR_ITEM_NOT_FOUND; + goto fail; + } + + pbase = fdt_reg_base_address(fdt, node); + if (pbase == DT_INFO_INVALID_REG) { + rc = TEE_ERROR_GENERIC; + goto fail; + } + + sz = fdt_reg_size(fdt, node); + if (sz < 0) { + rc = TEE_ERROR_GENERIC; + goto fail; + } + + if (!core_mmu_add_mapping(EKB_MEMORY_AREA_TYPE, pbase, sz)) { + EMSG("Failed to map %zu bytes at PA 0x%"PRIxPA, + (size_t)sz, pbase); + rc = TEE_ERROR_GENERIC; + goto fail; + } + + reg_addr = (void*)phys_to_virt(pbase, EKB_MEMORY_AREA_TYPE, sz); + if (!reg_addr) { + EMSG("Failed to get VA for PA 0x%"PRIxPA, pbase); + rc = TEE_ERROR_GENERIC; + goto fail; + } + + tmp_addr = calloc(1, sz); + if (!tmp_addr) { + rc = TEE_ERROR_OUT_OF_MEMORY; + goto fail; + } + memcpy(tmp_addr, reg_addr, sz); + ekb_base_addr = (vaddr_t)tmp_addr; + + /* Clear the source. */ + memset((void*)reg_addr, 0, sz); + +fail: + if (NULL != reg_addr) + core_mmu_remove_mapping(EKB_MEMORY_AREA_TYPE, reg_addr, sz); + + return rc; +} + +static TEE_Result jetson_user_key_pta_init(void) +{ + TEE_Result rc = TEE_SUCCESS; + struct user_key *ekb_key = NULL; + vaddr_t ekb_content_addr; + + 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; + + /* Get the start address of ekb content. */ + rc = get_ekb_content_start_addr(ekb_base_addr, &ekb_content_addr); + 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_content_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..34e4d51 --- /dev/null +++ b/optee/optee_os/core/pta/tegra/sub.mk @@ -0,0 +1,12 @@ +global-incdirs-y += include +srcs-$(CFG_JETSON_FTPM_HELPER_PTA) += jetson_ftpm_helper_pta.c +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..535aa79 --- /dev/null +++ b/optee/optee_os/core/pta/tests/aes_perf.c @@ -0,0 +1,221 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020, Linaro Limited + */ + +#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/dt_driver_test.c b/optee/optee_os/core/pta/tests/dt_driver_test.c new file mode 100644 index 0000000..7048f38 --- /dev/null +++ b/optee/optee_os/core/pta/tests/dt_driver_test.c @@ -0,0 +1,767 @@ +// 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_gpios; + 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 run", + [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("GPIO ctrl probe: %s", + dt_test_str_sid[dt_test_state.probe_gpios]); + 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_GPIOS) && + dt_test_state.probe_gpios != SUCCESS) { + EMSG("GPIO controllers 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; +} + +static TEE_Result probe_test_clocks(const void *fdt, int node) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct clk *clk0 = NULL; + struct clk *clk1 = NULL; + struct clk *clk = NULL; + + DT_TEST_MSG("Probe clocks"); + dt_test_state.probe_clocks = IN_PROGRESS; + + res = clk_dt_get_by_index(fdt, node, 0, &clk0); + if (res) + goto err; + + res = clk_dt_get_by_index(fdt, node, 1, &clk1); + if (res) + goto err; + + DT_TEST_MSG("Check valid clock references"); + + if (clk_enable(clk0)) { + DT_TEST_MSG("Can't enable %s", clk_get_name(clk0)); + res = TEE_ERROR_GENERIC; + goto err; + } + clk_disable(clk0); + + res = clk_dt_get_by_name(fdt, node, "clk0", &clk); + if (res || clk != clk0) { + DT_TEST_MSG("Unexpected clock reference"); + res = TEE_ERROR_GENERIC; + goto err; + } + + res = clk_dt_get_by_name(fdt, node, "clk1", &clk); + if (res || clk != clk1) { + DT_TEST_MSG("Unexpected clock reference"); + res = TEE_ERROR_GENERIC; + goto err; + } + + 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"); + res = TEE_ERROR_GENERIC; + goto err; + } + + res = clk_dt_get_by_name(fdt, node, "clk2", &clk); + if (!res) { + DT_TEST_MSG("Unexpected clock found on invalid name"); + res = TEE_ERROR_GENERIC; + goto err; + } + + dt_test_state.probe_clocks = SUCCESS; + return TEE_SUCCESS; + +err: + if (res != TEE_ERROR_DEFER_DRIVER_INIT) + dt_test_state.probe_clocks = FAILED; + + return res; +} + +static TEE_Result probe_test_resets(const void *fdt, int node) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct rstctrl *rstctrl0 = NULL; + struct rstctrl *rstctrl1 = NULL; + struct rstctrl *rstctrl = NULL; + + DT_TEST_MSG("Probe reset controllers"); + dt_test_state.probe_resets = IN_PROGRESS; + + res = rstctrl_dt_get_by_index(fdt, node, 0, &rstctrl0); + if (res) + goto err; + + DT_TEST_MSG("Check valid reset controller"); + + if (rstctrl_assert(rstctrl0)) { + EMSG("Can't assert rstctrl %s", rstctrl_name(rstctrl0)); + res = TEE_ERROR_GENERIC; + goto err; + } + + res = rstctrl_dt_get_by_name(fdt, node, "rst0", &rstctrl); + if (res) + goto err; + + if (rstctrl != rstctrl0) { + EMSG("Unexpected reset controller reference"); + res = TEE_ERROR_GENERIC; + goto err; + } + + res = rstctrl_dt_get_by_name(fdt, node, "rst1", &rstctrl1); + if (res) + goto err; + + if (!rstctrl1 || rstctrl1 == rstctrl0) { + EMSG("Unexpected reset controller reference"); + res = TEE_ERROR_GENERIC; + goto err; + } + + dt_test_state.probe_resets = SUCCESS; + return TEE_SUCCESS; + +err: + if (res != TEE_ERROR_DEFER_DRIVER_INIT) + dt_test_state.probe_resets = FAILED; + + return res; +} + +static TEE_Result probe_test_gpios(const void *fdt, int node) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct gpio *gpio = NULL; + + DT_TEST_MSG("Probe GPIO controllers"); + dt_test_state.probe_gpios = IN_PROGRESS; + + res = gpio_dt_get_by_index(fdt, node, 0, "test", &gpio); + if (res) + goto err; + + if (gpio_get_direction(gpio) != GPIO_DIR_IN) { + EMSG("Unexpected gpio_get_direction() return value"); + res = TEE_ERROR_GENERIC; + goto err; + } + + /* GPIO is declared as ACTIVE_LOW in device-tree */ + if (gpio_get_value(gpio) != GPIO_LEVEL_LOW) { + EMSG("Unexpected gpio_get_value() return value"); + res = TEE_ERROR_GENERIC; + goto err; + } + + res = gpio_dt_get_by_index(fdt, node, 1, "test", &gpio); + if (res) + goto err; + + if (gpio_get_direction(gpio) != GPIO_DIR_IN) { + EMSG("Unexpected gpio_get_direction() return value"); + res = TEE_ERROR_GENERIC; + goto err; + } + + if (gpio_get_value(gpio) != GPIO_LEVEL_HIGH) { + EMSG("Unexpected gpio_get_value() return value"); + res = TEE_ERROR_GENERIC; + goto err; + } + + dt_test_state.probe_gpios = SUCCESS; + return TEE_SUCCESS; + +err: + if (res != TEE_ERROR_DEFER_DRIVER_INIT) + dt_test_state.probe_gpios = FAILED; + + 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)) { + res = probe_test_clocks(fdt, node); + if (res) + goto err_probe; + } + + if (IS_ENABLED(CFG_DRIVERS_RSTCTRL)) { + res = probe_test_resets(fdt, node); + if (res) + goto err_probe; + } + + if (IS_ENABLED(CFG_DRIVERS_GPIO)) { + res = probe_test_gpios(fdt, node); + if (res) + goto err_probe; + } + + 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 TEE_Result dt_test_get_clk(struct dt_pargs *args, void *data, + struct clk **out_device) +{ + struct clk *clk_ref = data; + struct clk *clk = NULL; + + if (args->args_count != 1) + return TEE_ERROR_BAD_PARAMETERS; + + 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]); + return TEE_ERROR_BAD_PARAMETERS; + } + + DT_TEST_MSG("Providing clock %s", clk_get_name(clk)); + + *out_device = clk; + return TEE_SUCCESS; +} + +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 TEE_Result dt_test_get_rstctrl(struct dt_pargs *args, void *data, + struct rstctrl **out_device) +{ + struct dt_test_rstctrl *ref = data; + struct rstctrl *rstctrl = NULL; + + if (args->args_count != 1) + return TEE_ERROR_BAD_PARAMETERS; + + 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]); + return TEE_ERROR_BAD_PARAMETERS; + } + + DT_TEST_MSG("Providing reset controller %s", rstctrl_name(rstctrl)); + + *out_device = rstctrl; + + return TEE_SUCCESS; +} + +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 */ + +#ifdef CFG_DRIVERS_GPIO +#define DT_TEST_GPIO_COUNT 2 + +#define DT_TEST_GPIO0_PIN 1 +#define DT_TEST_GPIO0_FLAGS GPIO_ACTIVE_LOW +#define DT_TEST_GPIO1_PIN 2 +#define DT_TEST_GPIO1_FLAGS GPIO_PULL_UP + +struct dt_test_gpio { + unsigned int pin; + unsigned int flags; + struct gpio_chip gpio_chip; +}; + +static struct dt_test_gpio *to_test_gpio(struct gpio_chip *chip) +{ + return container_of(chip, struct dt_test_gpio, gpio_chip); +} + +static enum gpio_dir dt_test_gpio_get_direction(struct gpio_chip *chip, + unsigned int gpio_pin) +{ + struct dt_test_gpio *dtg = to_test_gpio(chip); + + if (dtg->pin != gpio_pin) + panic("Invalid GPIO number"); + + return GPIO_DIR_IN; +} + +static void dt_test_gpio_set_direction(struct gpio_chip *chip, + unsigned int gpio_pin, + enum gpio_dir direction __unused) +{ + struct dt_test_gpio *dtg = to_test_gpio(chip); + + if (dtg->pin != gpio_pin) + panic("Invalid GPIO number"); +} + +static enum gpio_level dt_test_gpio_get_value(struct gpio_chip *chip, + unsigned int gpio_pin) +{ + struct dt_test_gpio *dtg = to_test_gpio(chip); + + if (dtg->pin != gpio_pin) + panic("Invalid GPIO number"); + + return GPIO_LEVEL_HIGH; +} + +static void dt_test_gpio_set_value(struct gpio_chip *chip, + unsigned int gpio_pin, + enum gpio_level value __unused) +{ + struct dt_test_gpio *dtg = to_test_gpio(chip); + + if (dtg->pin != gpio_pin) + panic("Invalid GPIO number"); +} + +static const struct gpio_ops dt_test_gpio_ops = { + .get_direction = dt_test_gpio_get_direction, + .set_direction = dt_test_gpio_set_direction, + .get_value = dt_test_gpio_get_value, + .set_value = dt_test_gpio_set_value, +}; + +static TEE_Result dt_test_gpio_get_dt(struct dt_pargs *args, void *data, + struct gpio **out_device) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct gpio *gpio = NULL; + struct dt_test_gpio *gpios = (struct dt_test_gpio *)data; + + res = gpio_dt_alloc_pin(args, &gpio); + if (res) + return res; + + switch (gpio->pin) { + case DT_TEST_GPIO0_PIN: + gpio->chip = &gpios[0].gpio_chip; + if (gpio->dt_flags != gpios[0].flags) { + EMSG("Unexpected dt_flags %#"PRIx32, gpio->dt_flags); + free(gpio); + return TEE_ERROR_GENERIC; + } + break; + case DT_TEST_GPIO1_PIN: + gpio->chip = &gpios[1].gpio_chip; + if (gpio->dt_flags != gpios[1].flags) { + EMSG("Unexpected dt_flags %#"PRIx32, gpio->dt_flags); + free(gpio); + return TEE_ERROR_GENERIC; + } + break; + default: + EMSG("Unexpected pin ID %u", gpio->pin); + free(gpio); + return TEE_ERROR_BAD_PARAMETERS; + }; + + *out_device = gpio; + + return TEE_SUCCESS; +} + +static TEE_Result dt_test_gpio_provider_probe(const void *fdt, int offs, + const void *data __unused) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct dt_test_gpio *gpios = NULL; + + DT_TEST_MSG("Register GPIO controllers"); + + assert(gpio_ops_is_valid(&dt_test_gpio_ops)); + + gpios = dt_test_alloc(DT_TEST_GPIO_COUNT * sizeof(*gpios)); + if (!gpios) + return TEE_ERROR_OUT_OF_MEMORY; + + gpios[0].gpio_chip.ops = &dt_test_gpio_ops; + gpios[0].pin = DT_TEST_GPIO0_PIN; + gpios[0].flags = DT_TEST_GPIO0_FLAGS; + + gpios[1].gpio_chip.ops = &dt_test_gpio_ops; + gpios[1].pin = DT_TEST_GPIO1_PIN; + gpios[1].flags = DT_TEST_GPIO1_FLAGS; + + res = gpio_register_provider(fdt, offs, dt_test_gpio_get_dt, gpios); + if (res) { + dt_test_free(gpios); + return res; + } + + return TEE_SUCCESS; +} + +GPIO_DT_DECLARE(dt_test_gpio_provider, "linaro,dt-test-provider", + dt_test_gpio_provider_probe); +#endif /* CFG_DRIVERS_GPIO */ 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..2a50045 --- /dev/null +++ b/optee/optee_os/core/pta/tests/fs_htree.c @@ -0,0 +1,627 @@ +// 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, 0, 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, NULL); + 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, 0, 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, 0, 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, 0, 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, 0, 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, 0, 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, NULL); + 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, 0, 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..cb3c29e --- /dev/null +++ b/optee/optee_os/core/pta/tests/sub.mk @@ -0,0 +1,8 @@ +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 +srcs-$(CFG_DT_DRIVER_EMBEDDED_TEST) += dt_driver_test.c diff --git a/optee/optee_os/core/pta/widevine.c b/optee/optee_os/core/pta/widevine.c new file mode 100644 index 0000000..6f84c9e --- /dev/null +++ b/optee/optee_os/core/pta/widevine.c @@ -0,0 +1,182 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2023, The ChromiumOS Authors + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PTA_NAME "widevine.pta" + +#define TPM_AUTH_PUB_MAX_SIZE 1024 +#define WIDEVINE_PRIV_MAX_SIZE 32 + +#define CROS_HWSEC_TA_UUID \ + { \ + 0xed800e33, 0x3c58, 0x4cae, \ + { \ + 0xa7, 0xc0, 0xfd, 0x16, 0x0e, 0x35, 0xe0, 0x0d \ + } \ + } +#define CROS_HDCP_PROV4_TA_UUID \ + { \ + 0x0feb839c, 0xee25, 0x4920, \ + { \ + 0x8e, 0xe3, 0xac, 0x8d, 0xaa, 0x86, 0x0d, 0x3b \ + } \ + } +#define TA_OPTEE_OEMCRYPTO_UUID \ + { \ + 0xa92d116c, 0xce27, 0x4917, \ + { \ + 0xb3, 0x0c, 0x4a, 0x41, 0x6e, 0x2d, 0x93, 0x51 \ + } \ + } + +static const TEE_UUID allowed_ta_uuids[3] = { + CROS_HWSEC_TA_UUID, + CROS_HDCP_PROV4_TA_UUID, + TA_OPTEE_OEMCRYPTO_UUID, +}; + +/* + * The TPM auth public key. Used to communicate with the TPM from OP-TEE. + * The format of data should be TPM2B_PUBLIC. + * For more information, please reference the 12.2.5 section: + * https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part2_Structures_pub.pdf + */ +static uint8_t tpm_auth_pub[TPM_AUTH_PUB_MAX_SIZE]; +static uint32_t tpm_auth_pub_size; + +/* + * The Widevine root of trust secret. Used to sign the widevine + * requests in OP-TEE. The value is an ECC NIST P-256 scalar. + * For more information, please reference the G.1.2 section: + * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-186.pdf + */ +static uint8_t widevine_priv[WIDEVINE_PRIV_MAX_SIZE]; +static uint32_t widevine_priv_size; + +static TEE_Result init_widevine_dt_data(void) +{ + int node = 0; + int len = 0; + void *fdt = NULL; + const void *value = NULL; + + fdt = get_secure_dt(); + if (!fdt) + return TEE_ERROR_NO_DATA; + + node = fdt_path_offset(fdt, "/options/op-tee/widevine"); + if (node < 0) + return TEE_ERROR_ITEM_NOT_FOUND; + + value = fdt_getprop(fdt, node, "tcg,tpm-auth-public-key", &len); + if (!value) + return TEE_ERROR_ITEM_NOT_FOUND; + + if (len > TPM_AUTH_PUB_MAX_SIZE) + return TEE_ERROR_OVERFLOW; + + memcpy(tpm_auth_pub, value, len); + tpm_auth_pub_size = len; + + value = fdt_getprop(fdt, node, "google,widevine-root-of-trust-ecc-p256", + &len); + if (!value) + return TEE_ERROR_ITEM_NOT_FOUND; + + if (len > WIDEVINE_PRIV_MAX_SIZE) + return TEE_ERROR_OVERFLOW; + + memcpy(widevine_priv, value, len); + widevine_priv_size = len; + + return TEE_SUCCESS; +} + +service_init(init_widevine_dt_data); + +static TEE_Result open_session(uint32_t param_types __unused, + TEE_Param params[TEE_NUM_PARAMS] __unused, + void **sess_ctx __unused) +{ + size_t i = 0; + struct ts_session *session = ts_get_calling_session(); + + /* Make sure we are called from a TA */ + if (!is_user_ta_ctx(session->ctx)) + return TEE_ERROR_ACCESS_DENIED; + + /* Make sure we are called from an allowed TA */ + for (i = 0; i < ARRAY_SIZE(allowed_ta_uuids); i++) + if (memcmp(&session->ctx->uuid, &allowed_ta_uuids[i], + sizeof(TEE_UUID)) == 0) + return TEE_SUCCESS; + + return TEE_ERROR_ACCESS_DENIED; +} + +static TEE_Result get_dt_data(uint32_t ptypes, TEE_Param params[TEE_NUM_PARAMS], + uint32_t cmd) +{ + uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + uint8_t *data = NULL; + uint32_t data_length = 0; + + if (exp_pt != ptypes) + return TEE_ERROR_BAD_PARAMETERS; + + if (cmd == PTA_WIDEVINE_GET_TPM_PUBKEY) { + data = tpm_auth_pub; + data_length = tpm_auth_pub_size; + } else if (cmd == PTA_WIDEVINE_GET_WIDEVINE_PRIVKEY) { + data = widevine_priv; + data_length = widevine_priv_size; + } else { + return TEE_ERROR_NOT_IMPLEMENTED; + } + + if (data_length == 0) + return TEE_ERROR_NO_DATA; + + if (data_length > params[0].memref.size) { + params[0].memref.size = data_length; + return TEE_ERROR_SHORT_BUFFER; + } + + params[0].memref.size = data_length; + memcpy(params[0].memref.buffer, data, data_length); + + return TEE_SUCCESS; +} + +/* + * Trusted Application Entry Points + */ +static TEE_Result invoke_command(void *psess __unused, uint32_t cmd, + uint32_t ptypes, + TEE_Param params[TEE_NUM_PARAMS]) +{ + return get_dt_data(ptypes, params, cmd); +} + +pseudo_ta_register(.uuid = PTA_WIDEVINE_UUID, .name = PTA_NAME, + .flags = PTA_DEFAULT_FLAGS, + .open_session_entry_point = open_session, + .invoke_command_entry_point = invoke_command); 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..607ebd4 --- /dev/null +++ b/optee/optee_os/core/tee/entry_std.c @@ -0,0 +1,604 @@ +// 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 + +#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_ERROR_GENERIC; + 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 = 0; + 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 }; + + 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); + + 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..ee623a7 --- /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, uint32_t min_counter, + 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, min_counter, 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, uint32_t *counter) +{ + return dirh->fops->commit_writes(dirh->fh, hash, counter); +} + +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..a65e6e6 --- /dev/null +++ b/optee/optee_os/core/tee/fs_htree.c @@ -0,0 +1,937 @@ +// 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, uint32_t min_counter) +{ + 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]; + } + + if (ht->head.counter < min_counter) + return TEE_ERROR_SECURITY; + + 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, uint32_t min_counter, + 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 = min_counter, + }; + + 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, NULL); + if (res != TEE_SUCCESS) + goto out; + res = rpc_write_head(ht, 0, &dummy_head); + } else { + res = init_head_from_data(ht, hash, min_counter); + 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, uint32_t *counter) +{ + 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)); + if (counter) + *counter = ht->head.counter; +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..16af296 --- /dev/null +++ b/optee/optee_os/core/tee/socket.c @@ -0,0 +1,280 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016-2017, Linaro Limited + */ + +#include +#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; + + res = copy_from_user(va, params[1].memref.buffer, + params[1].memref.size); + if (res) + return res; + + 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; + + res = copy_from_user(va, params[1].memref.buffer, + params[1].memref.size); + if (res) + return res; + + 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) { + TEE_Result res2 = TEE_SUCCESS; + + res2 = copy_to_user(params[1].memref.buffer, va, + MIN(params[1].memref.size, + tpm[1].u.memref.size)); + if (res2) + return res2; + } + 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; + + res = copy_from_user(va, params[1].memref.buffer, + params[1].memref.size); + if (res) + return res; + + 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) { + TEE_Result res2 = TEE_SUCCESS; + + res2 = copy_to_user(params[1].memref.buffer, va, + tpm[1].u.memref.size); + if (res2) + return res2; + } + + 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..3d1f2fc --- /dev/null +++ b/optee/optee_os/core/tee/sub.mk @@ -0,0 +1,54 @@ +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 +ifneq ($(CFG_CRYPTO_HW_PBKDF2),y) +srcs-$(CFG_CRYPTO_PBKDF2) += tee_cryp_pbkdf2.c +endif + +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 +srcs-$(CFG_REE_STATE) += tee_ree_state.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..fbecd3c --- /dev/null +++ b/optee/optee_os/core/tee/tadb.c @@ -0,0 +1,796 @@ +// 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, NULL, &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, NULL, 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, 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_core, + void *buf_user, size_t *len) +{ + TEE_Result res = TEE_SUCCESS; + const size_t sz = ta->entry.prop.custom_size + ta->entry.prop.bin_size; + size_t l = MIN(*len, sz - ta->pos); + size_t bb_len = MIN(1024U, l); + size_t num_bytes = 0; + size_t dst_len = 0; + void *dst = NULL; + void *bb = NULL; + + res = ta_load(ta); + if (res) + return res; + + if (buf_core) { + dst = buf_core; + dst_len = l; + } else { + bb = bb_alloc(bb_len); + if (!bb) + return TEE_ERROR_OUT_OF_MEMORY; + dst = bb; + dst_len = bb_len; + } + + /* + * This loop will only run once if buf_core is non-NULL, but as + * many times as needed if the bounce buffer bb is used. That's why + * dst doesn't need to be updated in the loop. + */ + while (num_bytes < l) { + size_t n = MIN(dst_len, l - num_bytes); + + res = tadb_update_payload(ta->ctx, TEE_MODE_DECRYPT, + ta->ta_buf + ta->pos + num_bytes, + n, dst); + if (res) + goto out; + + if (buf_user) { + res = copy_to_user((uint8_t *)buf_user + num_bytes, + dst, n); + if (res) + goto out; + } + num_bytes += n; + } + + 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; +out: + bb_free(bb, bb_len); + return res; +} + +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..8d1c085 --- /dev/null +++ b/optee/optee_os/core/tee/tee_cryp_utl.c @@ -0,0 +1,217 @@ +// 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 + +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..392fa4d --- /dev/null +++ b/optee/optee_os/core/tee/tee_fs_key_manager.c @@ -0,0 +1,276 @@ +// 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 + +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..8066841 --- /dev/null +++ b/optee/optee_os/core/tee/tee_fs_rpc.c @@ -0,0 +1,219 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016, Linaro Limited + */ + +#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..db0bdd0 --- /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-2024, 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..afffe02 --- /dev/null +++ b/optee/optee_os/core/tee/tee_obj.c @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#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..efc75ba --- /dev/null +++ b/optee/optee_os/core/tee/tee_pobj.c @@ -0,0 +1,210 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#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 struct mutex pobjs_usage_mutex = MUTEX_INITIALIZER; + +static bool pobj_need_usage_lock(struct tee_pobj *obj) +{ + /* Only lock if we don't have exclusive access to the object */ + return obj->flags & (TEE_DATA_FLAG_SHARE_WRITE | + TEE_DATA_FLAG_SHARE_READ); +} + +void tee_pobj_lock_usage(struct tee_pobj *obj) +{ + if (pobj_need_usage_lock(obj)) + mutex_lock(&pobjs_usage_mutex); +} + +void tee_pobj_unlock_usage(struct tee_pobj *obj) +{ + if (pobj_need_usage_lock(obj)) + mutex_unlock(&pobjs_usage_mutex); +} + +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..654a4f6 --- /dev/null +++ b/optee/optee_os/core/tee/tee_ree_fs.c @@ -0,0 +1,1108 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015, Linaro Limited + * Copyright (c) 2023-2024, 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_core, + const void *buf_user, 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_core_ptr = (uint8_t *)buf_core; + uint8_t *data_user_ptr = (uint8_t *)buf_user; + 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_core_ptr) { + memcpy(block + offset, data_core_ptr, size_to_write); + } else if (data_user_ptr) { + res = copy_from_user(block + offset, data_user_ptr, + size_to_write); + if (res) + return res; + } 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_core_ptr) + data_core_ptr += size_to_write; + if (data_user_ptr) + data_user_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, 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_core, void *buf_user, + size_t *len) +{ + TEE_Result res; + int start_block_num; + int end_block_num; + size_t remain_bytes; + uint8_t *data_core_ptr = buf_core; + uint8_t *data_user_ptr = buf_user; + 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); + + /* One of buf_core and buf_user must be NULL */ + assert(!buf_core || !buf_user); + + 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; + + if (data_core_ptr) { + memcpy(data_core_ptr, block + offset, size_to_read); + data_core_ptr += size_to_read; + } else if (data_user_ptr) { + res = copy_to_user(data_user_ptr, block + offset, + size_to_read); + if (res) + goto exit; + data_user_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_core, void *buf_user, size_t *len) +{ + TEE_Result res; + + mutex_lock(&ree_fs_mutex); + res = ree_fs_read_primitive(fh, pos, buf_core, buf_user, 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_core, + const void *buf_user, size_t len) +{ + TEE_Result res; + struct tee_fs_fd *fdp = (struct tee_fs_fd *)fh; + size_t file_size; + + /* One of buf_core and buf_user must be NULL */ + assert(!buf_core || !buf_user); + + 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_core, buf_user, len); +} + +static TEE_Result ree_fs_open_primitive(bool create, uint8_t *hash, + uint32_t min_counter, + 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, min_counter, 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, uint32_t *counter) +{ + 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, counter); + + if (!res && hash) + memcpy(hash, fdp->dfh.hash, sizeof(fdp->dfh.hash)); + + return res; +} + +static TEE_Result dirf_read(struct tee_file_handle *fh, size_t pos, void *buf, + size_t *len) +{ + return ree_fs_read_primitive(fh, pos, buf, NULL, len); +} + +static TEE_Result dirf_write(struct tee_file_handle *fh, size_t pos, + const void *buf, size_t len) +{ + return ree_fs_write_primitive(fh, pos, buf, NULL, len); +} + +static const struct tee_fs_dirfile_operations ree_dirf_ops = { + .open = ree_fs_open_primitive, + .close = ree_fs_close_primitive, + .read = dirf_read, + .write = dirf_write, + .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, NULL, &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, 0, &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, 0, &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, NULL); + if (res) + return res; + return rpmb_ops->write(ree_fs_rpmb_fh, 0, hash, NULL, 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 = TEE_SUCCESS; + uint32_t min_counter = 0; + + res = nv_counter_get_ree_fs(&min_counter); + if (res) { + static bool once; + + if (res != TEE_ERROR_NOT_IMPLEMENTED || + !IS_ENABLED(CFG_INSECURE)) + return res; + + if (!once) { + IMSG("WARNING (insecure configuration): Failed to get monotonic counter for REE FS, using 0"); + once = true; + } + min_counter = 0; + } + res = tee_fs_dirfile_open(false, NULL, min_counter, &ree_dirf_ops, + dirh); + if (res == TEE_ERROR_ITEM_NOT_FOUND) { + if (min_counter) { + if (!IS_ENABLED(CFG_REE_FS_ALLOW_RESET)) { + DMSG("dirf.db file not found"); + return TEE_ERROR_SECURITY; + } + DMSG("dirf.db not found, initializing with a non-zero monotonic counter"); + } + return tee_fs_dirfile_open(true, NULL, min_counter, + &ree_dirf_ops, dirh); + } + + return res; +} + +static TEE_Result commit_dirh_writes(struct tee_fs_dirfile_dirh *dirh) +{ + TEE_Result res = TEE_SUCCESS; + uint32_t counter = 0; + + res = tee_fs_dirfile_commit_writes(dirh, NULL, &counter); + if (res) + return res; + res = nv_counter_incr_ree_fs_to(counter); + if (res == TEE_ERROR_NOT_IMPLEMENTED && IS_ENABLED(CFG_INSECURE)) { + static bool once; + + if (!once) { + IMSG("WARNING (insecure configuration): Failed to commit dirh counter %"PRIu32, counter); + once = true; + } + return TEE_SUCCESS; + } + return res; +} + +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, 0, &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_core, const void *data_user, + 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; + + /* One of data_core and data_user must be NULL */ + assert(!data_core || !data_user); + + *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, 0, &po->uuid, &dfh, fh); + if (res) + goto out; + + if (head && head_size) { + res = ree_fs_write_primitive(*fh, pos, head, NULL, head_size); + if (res) + goto out; + pos += head_size; + } + + if (attr && attr_size) { + res = ree_fs_write_primitive(*fh, pos, attr, NULL, attr_size); + if (res) + goto out; + pos += attr_size; + } + + if ((data_core || data_user) && data_size) { + res = ree_fs_write_primitive(*fh, pos, data_core, data_user, + data_size); + if (res) + goto out; + } + + fdp = (struct tee_fs_fd *)*fh; + res = tee_fs_htree_sync_to_storage(&fdp->ht, fdp->dfh.hash, NULL); + 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_core, const void *buf_user, + size_t len) +{ + TEE_Result res; + struct tee_fs_dirfile_dirh *dirh = NULL; + struct tee_fs_fd *fdp = (struct tee_fs_fd *)fh; + + /* One of buf_core and buf_user must be NULL */ + assert(!buf_core || !buf_user); + + mutex_lock(&ree_fs_mutex); + + res = get_dirh(&dirh); + if (res) + goto out; + + res = ree_fs_write_primitive(fh, pos, buf_core, buf_user, len); + if (res) + goto out; + + res = tee_fs_htree_sync_to_storage(&fdp->ht, fdp->dfh.hash, NULL); + 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, NULL); + 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_ree_state.c b/optee/optee_os/core/tee/tee_ree_state.c new file mode 100644 index 0000000..3443ce2 --- /dev/null +++ b/optee/optee_os/core/tee/tee_ree_state.c @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. + */ + +#include + +static tee_ree_state ree_state = TEE_REE_STATE_BOOT; + +TEE_Result tee_set_ree_state(tee_ree_state state) +{ + if ((state < ree_state) || (state > TEE_REE_STATE_REE_SUPP)) + return TEE_ERROR_BAD_STATE; + + ree_state = state; + + return TEE_SUCCESS; +} + +tee_ree_state tee_get_ree_state(void) +{ + return ree_state; +} 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..6bc42f0 --- /dev/null +++ b/optee/optee_os/core/tee/tee_rpmb_fs.c @@ -0,0 +1,3127 @@ +// 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 +#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 unused; + 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 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) +{ + 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; + } + + 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); + 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); + 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); + 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_core, void *buf_user, size_t *len) +{ + TEE_Result res; + struct rpmb_file_handle *fh = (struct rpmb_file_handle *)tfh; + size_t size = *len; + + /* One of buf_core and buf_user must be NULL */ + assert(!buf_core || !buf_user); + + 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) { + if (buf_core) { + res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID, + fh->fat_entry.start_address + pos, + buf_core, size, fh->fat_entry.fek, + fh->uuid); + if (res != TEE_SUCCESS) + goto out; + } else if (buf_user) { + uint32_t f = TEE_MEMORY_ACCESS_WRITE; + + res = check_user_access(f, buf_user, size); + if (res) + goto out; + enter_user_access(); + res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID, + fh->fat_entry.start_address + pos, + buf_user, size, fh->fat_entry.fek, + fh->uuid); + exit_user_access(); + if (res) + 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); + } + } + +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_core, const void *buf_user, + size_t size) +{ + TEE_Result res = TEE_SUCCESS; + + /* One of buf_core and buf_user must be NULL */ + assert(!buf_core || !buf_user); + + if (!size) + return TEE_SUCCESS; + + mutex_lock(&rpmb_mutex); + if (buf_core) { + res = rpmb_fs_write_primitive((struct rpmb_file_handle *)tfh, + pos, buf_core, size); + } else if (buf_user) { + uint32_t f = TEE_MEMORY_ACCESS_READ; + + res = check_user_access(f, buf_user, size); + if (res) + goto out; + enter_user_access(); + res = rpmb_fs_write_primitive((struct rpmb_file_handle *)tfh, + pos, buf_user, size); + exit_user_access(); + } +out: + 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); +} + +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); + 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); + +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); + +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_core, const void *data_user, + 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); + + /* One of data_core and data_user must be NULL */ + assert(!data_core || !data_user); + + 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_size) { + if (data_core) { + res = rpmb_fs_write_primitive(fh, pos, data_core, + data_size); + if (res) + goto out; + } else if (data_user) { + uint32_t f = TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER; + + res = check_user_access(f, data_user, data_size); + if (res) + goto out; + enter_user_access(); + res = rpmb_fs_write_primitive(fh, pos, data_user, + data_size); + exit_user_access(); + 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..c91d1eb --- /dev/null +++ b/optee/optee_os/core/tee/tee_supp_plugin_rpc.c @@ -0,0 +1,91 @@ +// 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 + +TEE_Result tee_invoke_supp_plugin_rpc(const TEE_UUID *uuid, uint32_t cmd, + uint32_t sub_cmd, void *buf_core, + void *buf_user, 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_core && !buf_user) || + (!len && (buf_core || buf_user)) || (buf_core && buf_user)) + 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; + } + + if (buf_core) + memcpy(va, buf_core, len); + if (buf_user) { + res = copy_from_user(va, buf_user, len); + if (res) + goto out; + } + } + + 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) { + if (buf_core) + memcpy(buf_core, va, *outlen <= len ? *outlen : len); + if (buf_user) + res = copy_to_user(buf_user, va, 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..237a27d --- /dev/null +++ b/optee/optee_os/core/tee/tee_svc.c @@ -0,0 +1,1016 @@ +// 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) +{ + TEE_Result res = TEE_SUCCESS; + size_t n = 0; + uint64_t types = 0; + struct utee_params *up_bbuf = NULL; + + res = BB_MEMDUP_USER(up, sizeof(*up), &up_bbuf); + if (res) + goto out; + + types = up_bbuf->types; + + p->types = types; + for (n = 0; n < TEE_NUM_PARAMS; n++) { + uintptr_t a = up_bbuf->vals[n * 2]; + size_t b = up_bbuf->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) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + p->u[n].mem.mobj = NULL; + break; + } + + p->u[n].mem.mobj = &mobj_virt; + + res = vm_check_access_rights(&utc->uctx, flags, a, b); + if (res) + goto out; + 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; + } + } + +out: + bb_free(up_bbuf, sizeof(struct utee_params)); + return res; +} + +/* + * 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) +{ + struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); + TEE_Result res = TEE_SUCCESS; + 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++) { + 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 (!s) { + param->u[n].mem.mobj = NULL; + break; + } + if (!va) + return TEE_ERROR_BAD_PARAMETERS; + + /* uTA cannot expose its private memory */ + if (vm_buf_is_inside_um_private(&utc->uctx, va, s)) + return TEE_ERROR_BAD_PARAMETERS; + + 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; + } + } + + 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, + struct utee_params *usr_param) +{ + size_t n = 0; + uint64_t *vals = usr_param->vals; + uint64_t sz = 0; + + for (n = 0; n < TEE_NUM_PARAMS; n++) { + TEE_Result res = TEE_SUCCESS; + uint64_t val_buf[2] = { }; + + switch (TEE_PARAM_TYPE_GET(param->types, n)) { + case TEE_PARAM_TYPE_MEMREF_OUTPUT: + case TEE_PARAM_TYPE_MEMREF_INOUT: + sz = param->u[n].mem.size; + + res = PUT_USER_SCALAR(sz, &usr_param->vals[n * 2 + 1]); + if (res) + return res; + + break; + + case TEE_PARAM_TYPE_VALUE_OUTPUT: + case TEE_PARAM_TYPE_VALUE_INOUT: + val_buf[0] = param->u[n].val.a; + val_buf[1] = param->u[n].val.b; + + res = copy_to_user(&vals[n * 2], val_buf, + 2 * sizeof(uint64_t)); + if (res) + return res; + + 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; + 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)); + + 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); + 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, usr_param); + +function_exit: + 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; + + 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); + 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, 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); + 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..7dc733d --- /dev/null +++ b/optee/optee_os/core/tee/tee_svc_cryp.c @@ -0,0 +1,4791 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2020, 2022-2023 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 +#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 +#define ATTR_OPS_INDEX_448 4 + + /* Curve25519 key bytes size is always 32 bytes*/ +#define KEY_SIZE_BYTES_25519 UL(32) +#define KEY_SIZE_BYTES_448 UL(56) + /* 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 montgomery_keypair, priv) + }, + + { + .attr_id = TEE_ATTR_X25519_PUBLIC_VALUE, + .flags = TEE_TYPE_ATTR_REQUIRED, + .ops_index = ATTR_OPS_INDEX_25519, + RAW_DATA(struct montgomery_keypair, pub) + }, +}; + +static +const struct tee_cryp_obj_type_attrs tee_cryp_obj_x448_keypair_attrs[] = { + { + .attr_id = TEE_ATTR_X448_PRIVATE_VALUE, + .flags = TEE_TYPE_ATTR_REQUIRED, + .ops_index = ATTR_OPS_INDEX_448, + RAW_DATA(struct montgomery_keypair, priv) + }, + + { + .attr_id = TEE_ATTR_X448_PUBLIC_VALUE, + .flags = TEE_TYPE_ATTR_REQUIRED, + .ops_index = ATTR_OPS_INDEX_448, + RAW_DATA(struct montgomery_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 montgomery_keypair), + tee_cryp_obj_x25519_keypair_attrs), + + PROP(TEE_TYPE_X448_KEYPAIR, 1, 448, 448, + sizeof(struct montgomery_keypair), + tee_cryp_obj_x448_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) +{ + TEE_Result res = TEE_SUCCESS; + struct tee_cryp_obj_secret *key = attr; + + /* Data size has to fit in allocated buffer */ + if (size > key->alloc_size) + return TEE_ERROR_SECURITY; + res = copy_from_user(key + 1, buffer, size); + if (!res) + key->key_size = size; + + return res; +} + +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) +{ + TEE_Result res = TEE_SUCCESS; + struct bignum **bn = attr; + void *bbuf = NULL; + + res = bb_memdup_user(buffer, size, &bbuf); + if (res) + return res; + + res = crypto_bignum_bin2bn(bbuf, size, *bn); + + bb_free(bbuf, size); + + return res; +} + +static TEE_Result op_attr_bignum_to_user(void *attr, + struct ts_session *sess __unused, + void *buffer, uint64_t *size) +{ + TEE_Result res = TEE_SUCCESS; + struct bignum **bn = attr; + uint64_t req_size = 0; + uint64_t s = 0; + void *bbuf = NULL; + + 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; + + bbuf = bb_alloc(req_size); + if (!bbuf) + return TEE_ERROR_OUT_OF_MEMORY; + + /* + * Write the bignum (wich raw data points to) into an array of + * bytes (stored in buffer) + */ + crypto_bignum_bn2bin(*bn, bbuf); + res = copy_to_user(buffer, bbuf, req_size); + + bb_free(bbuf, req_size); + return res; +} + +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); +} + +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; + + return copy_from_user(*key, buffer, size); +} + +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; + if (o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) { + tee_pobj_lock_usage(o->pobj); + o_info.obj_usage = o->pobj->obj_info_usage; + tee_pobj_unlock_usage(o->pobj); + } else { + 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) + return res; + + if (o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) { + uint32_t new_usage = 0; + + tee_pobj_lock_usage(o->pobj); + new_usage = o->pobj->obj_info_usage & usage; + res = tee_svc_storage_write_usage(o, new_usage); + if (!res) + o->pobj->obj_info_usage = new_usage; + tee_pobj_unlock_usage(o->pobj); + } else { + o->info.objectUsage &= usage; + } + + 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; + uint32_t obj_usage = 0; + + 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)) { + if (o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) { + tee_pobj_lock_usage(o->pobj); + obj_usage = o->pobj->obj_info_usage; + tee_pobj_unlock_usage(o->pobj); + } else { + obj_usage = o->info.objectUsage; + } + if (!(obj_usage & 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 if (o->info.objectType == TEE_TYPE_X448_PUBLIC_KEY) { + if (src->info.objectType != TEE_TYPE_X448_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_X448_KEYPAIR: + res = crypto_acipher_alloc_x448_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; + if (o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) + o->pobj->obj_info_usage = TEE_USAGE_DEFAULT; + else + 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; + struct utee_attribute *usr_attrs_bbuf = NULL; + + if (MUL_OVERFLOW(sizeof(struct utee_attribute), attr_count, &size)) + return TEE_ERROR_OVERFLOW; + + usr_attrs_bbuf = bb_alloc(size); + if (!usr_attrs_bbuf) + return TEE_ERROR_OUT_OF_MEMORY; + + res = copy_from_user(usr_attrs_bbuf, usr_attrs, size); + if (res) + goto out; + + for (n = 0; n < attr_count; n++) { + attrs[n].attributeID = usr_attrs_bbuf[n].attribute_id; + if (attrs[n].attributeID & TEE_ATTR_FLAG_VALUE) { + attrs[n].content.value.a = usr_attrs_bbuf[n].a; + attrs[n].content.value.b = usr_attrs_bbuf[n].b; + } else { + uintptr_t buf = usr_attrs_bbuf[n].a; + size_t len = usr_attrs_bbuf[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) + goto out; + attrs[n].content.ref.buffer = (void *)buf; + attrs[n].content.ref.length = len; + } + } + +out: + bb_free(usr_attrs_bbuf, size); + return res; +} + +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 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 (crypto_bignum_num_bits(*(struct bignum **)attr) > + 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; + if (src_o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) { + tee_pobj_lock_usage(src_o->pobj); + dst_o->info.objectUsage = src_o->pobj->obj_info_usage; + tee_pobj_unlock_usage(src_o->pobj); + } else { + 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 { + res = crypto_bignum_bin2bn((const uint8_t *)&e, sizeof(e), + key->e); + if (res) + return res; + } + 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 montgomery_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 montgomery_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_x448(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 montgomery_keypair *tee_x448_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_x448_key = (struct montgomery_keypair *)o->attr; + res = crypto_acipher_gen_x448_key(tee_x448_key, key_size); + if (res != TEE_SUCCESS) + return res; + + set_attribute(o, type_props, TEE_ATTR_X448_PRIVATE_VALUE); + set_attribute(o, type_props, TEE_ATTR_X448_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_X448_KEYPAIR: + res = tee_svc_obj_generate_key_x448(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; + case TEE_MAIN_ALGO_X448: + req_key_type = TEE_TYPE_X448_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: + enter_user_access(); + res = crypto_hash_update(cs->ctx, chunk, chunk_size); + exit_user_access(); + if (res != TEE_SUCCESS) + return res; + break; + case TEE_OPERATION_MAC: + enter_user_access(); + res = crypto_mac_update(cs->ctx, chunk, chunk_size); + exit_user_access(); + 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) { + enter_user_access(); + res = crypto_hash_update(cs->ctx, chunk, + chunk_size); + exit_user_access(); + if (res) + return res; + } + + /* + * hash_size is supposed to be unchanged for XOF + * algorithms so return directly. + */ + enter_user_access(); + res = crypto_hash_final(cs->ctx, hash, hlen); + exit_user_access(); + return res; + } + + 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) { + enter_user_access(); + res = crypto_hash_update(cs->ctx, chunk, chunk_size); + exit_user_access(); + if (res != TEE_SUCCESS) + return res; + } + + enter_user_access(); + res = crypto_hash_final(cs->ctx, hash, hash_size); + exit_user_access(); + 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) { + enter_user_access(); + res = crypto_mac_update(cs->ctx, chunk, chunk_size); + exit_user_access(); + if (res != TEE_SUCCESS) + return res; + } + + enter_user_access(); + res = crypto_mac_final(cs->ctx, hash, hash_size); + exit_user_access(); + 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; + void *iv_bbuf = 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; + + 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; + + res = bb_memdup_user(iv, iv_len, &iv_bbuf); + if (res) + return res; + + 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_bbuf, iv_len); + } else { + res = crypto_cipher_init(cs->ctx, cs->mode, + (uint8_t *)(key1 + 1), key1->key_size, + NULL, 0, iv_bbuf, 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 */ + enter_user_access(); + res = tee_do_cipher_update(cs->ctx, cs->algo, cs->mode, + last_block, src, src_len, dst); + exit_user_access(); + } + + 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) +{ + TEE_Result res = TEE_SUCCESS; + 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++) { + const TEE_Attribute *p = ¶ms[n]; + + switch (p->attributeID) { + case __OPTEE_TEE_ATTR_HKDF_SALT: + case TEE_ATTR_HKDF_SALT: + if (!(found & SALT)) { + *salt_len = p->content.ref.length; + res = bb_memdup_user(p->content.ref.buffer, + *salt_len, salt); + if (res) + return res; + + found |= SALT; + } + break; + case TEE_ATTR_KDF_KEY_SIZE: + case TEE_ATTR_HKDF_OKM_LENGTH: + if (!(found & LENGTH)) { + *okm_len = p->content.value.a; + found |= LENGTH; + } + break; + case __OPTEE_ATTR_HKDF_INFO: + case TEE_ATTR_HKDF_INFO: + if (!(found & INFO)) { + *info_len = p->content.ref.length; + res = bb_memdup_user(p->content.ref.buffer, + *info_len, info); + if (res) + return res; + + found |= INFO; + } + break; + case TEE_ATTR_HKDF_HASH_ALGORITHM: + if (!(found & HASH)) { + *hash_id = p->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++) { + const TEE_Attribute *p = ¶ms[n]; + + switch (p->attributeID) { + case TEE_ATTR_CONCAT_KDF_OTHER_INFO: + if (!(found & INFO)) { + TEE_Result res = TEE_SUCCESS; + + *other_info_len = p->content.ref.length; + res = bb_memdup_user(p->content.ref.buffer, + *other_info_len, + other_info); + if (res) + return res; + + found |= INFO; + } + break; + case TEE_ATTR_CONCAT_KDF_DKM_LENGTH: + if (!(found & LENGTH)) { + *derived_key_len = p->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++) { + const TEE_Attribute *p = ¶ms[n]; + + switch (p->attributeID) { + case TEE_ATTR_PBKDF2_SALT: + if (!(found & SALT)) { + TEE_Result res = TEE_SUCCESS; + + *salt_len = p->content.ref.length; + res = bb_memdup_user(p->content.ref.buffer, + *salt_len, salt); + if (res) + return res; + + found |= SALT; + } + break; + case TEE_ATTR_PBKDF2_DKM_LENGTH: + if (!(found & LENGTH)) { + *derived_key_len = p->content.value.a; + found |= LENGTH; + } + break; + case TEE_ATTR_PBKDF2_ITERATION_COUNT: + if (!(found & COUNT)) { + *iteration_count = p->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]; + void *bbuf = NULL; + + 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: + res = bb_memdup_user(p->content.ref.buffer, + p->content.ref.length, + &bbuf); + if (res) + return res; + + crypto_bignum_bin2bn(bbuf, + p->content.ref.length, + peer_key->x); + found |= BIT(PEER_KEY_X); + bb_free(bbuf, p->content.ref.length); + break; + case TEE_ATTR_ECC_PUBLIC_VALUE_Y: + res = bb_memdup_user(p->content.ref.buffer, + p->content.ref.length, + &bbuf); + if (res) + return res; + + crypto_bignum_bin2bn(bbuf, + p->content.ref.length, + peer_key->y); + found |= BIT(PEER_KEY_Y); + bb_free(bbuf, p->content.ref.length); + break; + case __OPTEE_SM2_KEP_ATTR_ECC_EPHEMERAL_PUBLIC_VALUE_X: + case TEE_ATTR_ECC_EPHEMERAL_PUBLIC_VALUE_X: + res = bb_memdup_user(p->content.ref.buffer, + p->content.ref.length, + &bbuf); + if (res) + return res; + + crypto_bignum_bin2bn(bbuf, + p->content.ref.length, + peer_eph_key->x); + found |= BIT(PEER_EPH_KEY_X); + bb_free(bbuf, p->content.ref.length); + break; + case __OPTEE_SM2_KEP_ATTR_ECC_EPHEMERAL_PUBLIC_VALUE_Y: + case TEE_ATTR_ECC_EPHEMERAL_PUBLIC_VALUE_Y: + res = bb_memdup_user(p->content.ref.buffer, + p->content.ref.length, + &bbuf); + if (res) + return res; + + crypto_bignum_bin2bn(bbuf, + p->content.ref.length, + peer_eph_key->y); + found |= BIT(PEER_EPH_KEY_Y); + bb_free(bbuf, p->content.ref.length); + break; + case TEE_ATTR_SM2_ID_INITIATOR: + res = bb_memdup_user(p->content.ref.buffer, + p->content.ref.length, + &bbuf); + if (res) + return res; + + kep_parms->initiator_id = bbuf; + kep_parms->initiator_id_len = p->content.ref.length; + found |= BIT(INITIATOR_ID); + break; + case TEE_ATTR_SM2_ID_RESPONDER: + res = bb_memdup_user(p->content.ref.buffer, + p->content.ref.length, + &bbuf); + if (res) + return res; + + kep_parms->responder_id = bbuf; + kep_parms->responder_id_len = p->content.ref.length; + found |= BIT(RESPONDER_ID); + break; + case TEE_ATTR_SM2_KEP_CONFIRMATION_IN: + res = bb_memdup_user(p->content.ref.buffer, + p->content.ref.length, + &bbuf); + if (res) + return res; + + kep_parms->conf_in = bbuf; + kep_parms->conf_in_len = p->content.ref.length; + break; + case TEE_ATTR_SM2_KEP_CONFIRMATION_OUT: + res = bb_memdup_user(p->content.ref.buffer, + p->content.ref.length, + &bbuf); + if (res) + return res; + + kep_parms->conf_out = bbuf; + 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; + void *bbuf = NULL; + + 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; + } + + res = bb_memdup_user(params[0].content.ref.buffer, bin_size, + &bbuf); + if (res) + goto out; + + pub = crypto_bignum_allocate(alloc_size); + ss = crypto_bignum_allocate(alloc_size); + if (pub && ss) { + crypto_bignum_bin2bn(bbuf, 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; + void *x_bbuf = NULL; + void *y_bbuf = NULL; + + 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; + } + + res = bb_memdup_user(params[0].content.ref.buffer, + params[0].content.ref.length, + &x_bbuf); + if (res) + goto out; + + res = bb_memdup_user(params[1].content.ref.buffer, + params[1].content.ref.length, + &y_bbuf); + if (res) + 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(x_bbuf, params[0].content.ref.length, + key_public.x); + crypto_bignum_bin2bn(y_bbuf, 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; + void *bbuf = NULL; + + 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; + } + + res = bb_memdup_user(params[0].content.ref.buffer, + params[0].content.ref.length, + &bbuf); + if (res) + goto out; + + /* Set the public key */ + x25519_pub_key = bbuf; + + 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 +#if defined(CFG_CRYPTO_X448) + else if (cs->algo == TEE_ALG_X448) { + uint8_t *x448_pub_key = NULL; + uint8_t *pt_secret = NULL; + unsigned long pt_secret_len = 0; + void *bbuf = NULL; + + if (param_count != 1 || + params[0].attributeID != TEE_ATTR_X448_PUBLIC_VALUE) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + /* X448 public key size is 56 bytes */ + if (params[0].content.ref.length != KEY_SIZE_BYTES_448) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + res = bb_memdup_user(params[0].content.ref.buffer, + params[0].content.ref.length, + &bbuf); + if (res) + goto out; + + /* Set the public key */ + x448_pub_key = bbuf; + + pt_secret = (uint8_t *)(sk + 1); + pt_secret_len = sk->alloc_size; + res = crypto_acipher_x448_shared_secret(ko->attr, + x448_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) +{ + TEE_Result res = TEE_SUCCESS; + void *bbuf = NULL; + + bbuf = bb_alloc(blen); + if (!bbuf) + return TEE_ERROR_OUT_OF_MEMORY; + + res = crypto_rng_read(bbuf, blen); + if (res != TEE_SUCCESS) + return res; + + res = copy_to_user(buf, bbuf, blen); + 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; + void *nonce_bbuf = NULL; + + 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 = bb_memdup_user(nonce, nonce_len, &nonce_bbuf); + if (res) + return res; + + res = crypto_authenc_init(cs->ctx, cs->mode, (uint8_t *)(key + 1), + key->key_size, nonce_bbuf, 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; + + enter_user_access(); + res = crypto_authenc_update_aad(cs->ctx, cs->mode, aad_data, + aad_data_len); + exit_user_access(); + 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; + } + + enter_user_access(); + res = crypto_authenc_update_payload(cs->ctx, cs->mode, src_data, + src_len, dst_data, &dlen); + exit_user_access(); +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; + + enter_user_access(); + res = crypto_authenc_enc_final(cs->ctx, src_data, src_len, dst_data, + &dlen, tag, &tlen); + exit_user_access(); + +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; + + enter_user_access(); + res = crypto_authenc_dec_final(cs->ctx, src_data, src_len, dst_data, + &dlen, tag, tag_len); + exit_user_access(); + +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) { + enter_user_access(); + res = crypto_acipher_rsanopad_encrypt(o->attr, src_data, + src_len, dst_data, + &dlen); + exit_user_access(); + } else if (cs->mode == TEE_MODE_DECRYPT) { + enter_user_access(); + res = crypto_acipher_rsanopad_decrypt(o->attr, src_data, + src_len, dst_data, + &dlen); + exit_user_access(); + } 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) { + enter_user_access(); + res = crypto_acipher_sm2_pke_encrypt(o->attr, src_data, + src_len, dst_data, + &dlen); + exit_user_access(); + } else if (cs->mode == TEE_MODE_DECRYPT) { + enter_user_access(); + res = crypto_acipher_sm2_pke_decrypt(o->attr, src_data, + src_len, dst_data, + &dlen); + exit_user_access(); + } 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; + void *buf = params[n].content.ref.buffer; + + if (params[n].content.ref.length != + sizeof(hash)) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + res = copy_from_user(&hash, buf, sizeof(hash)); + if (res) + goto out; + + if (hash != + TEE_INTERNAL_HASH_TO_ALGO(cs->algo)) { + res = TEE_ERROR_NOT_SUPPORTED; + goto out; + } + } + } + + if (cs->mode == TEE_MODE_ENCRYPT) { + enter_user_access(); + res = crypto_acipher_rsaes_encrypt(cs->algo, o->attr, + label, label_len, + src_data, src_len, + dst_data, &dlen); + exit_user_access(); + } else if (cs->mode == TEE_MODE_DECRYPT) { + enter_user_access(); + res = crypto_acipher_rsaes_decrypt( + cs->algo, o->attr, label, label_len, + src_data, src_len, dst_data, &dlen); + exit_user_access(); + } 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); + enter_user_access(); + res = crypto_acipher_rsassa_sign(cs->algo, o->attr, salt_len, + src_data, src_len, dst_data, + &dlen); + exit_user_access(); + break; + + case TEE_ALG_DSA_SHA1: + case TEE_ALG_DSA_SHA224: + case TEE_ALG_DSA_SHA256: + enter_user_access(); + res = crypto_acipher_dsa_sign(cs->algo, o->attr, src_data, + src_len, dst_data, &dlen); + exit_user_access(); + break; + + case TEE_ALG_ED25519: + enter_user_access(); + res = tee_svc_obj_ed25519_sign(o->attr, src_data, src_len, + dst_data, &dlen, params, + num_params); + exit_user_access(); + 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: + enter_user_access(); + res = crypto_acipher_ecc_sign(cs->algo, o->attr, src_data, + src_len, dst_data, &dlen); + exit_user_access(); + 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); + } + enter_user_access(); + res = crypto_acipher_rsassa_verify(cs->algo, o->attr, salt_len, + data, data_len, sig, + sig_len); + exit_user_access(); + 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; + } + } + enter_user_access(); + res = crypto_acipher_dsa_verify(cs->algo, o->attr, data, + data_len, sig, sig_len); + exit_user_access(); + break; + + case TEE_MAIN_ALGO_ED25519: + enter_user_access(); + res = tee_svc_obj_ed25519_verify(o->attr, data, + data_len, sig, sig_len, + params, num_params); + exit_user_access(); + break; + + case TEE_MAIN_ALGO_ECDSA: + case TEE_MAIN_ALGO_SM2_DSA_SM3: + enter_user_access(); + res = crypto_acipher_ecc_verify(cs->algo, o->attr, data, + data_len, sig, sig_len); + exit_user_access(); + 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..584e99d --- /dev/null +++ b/optee/optee_os/core/tee/tee_svc_storage.c @@ -0,0 +1,931 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2020, 2022-2023 Linaro Limited + */ + +#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, NULL, &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, NULL, &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->pobj->obj_info_usage = 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; + void *oid_bbuf = 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; + } + + res = bb_memdup_user_private(object_id, object_id_len, &oid_bbuf); + if (res) + goto exit; + + res = tee_pobj_get((void *)&sess->ctx->uuid, oid_bbuf, + object_id_len, flags, TEE_POBJ_USAGE_OPEN, fops, + &po); + bb_free(oid_bbuf, object_id_len); + 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); + + tee_pobj_lock_usage(o->pobj); + res = tee_svc_storage_read_head(o); + tee_pobj_unlock_usage(o->pobj); + 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->pobj->obj_info_usage = 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->pobj->obj_info_usage; + head.objectType = o->info.objectType; + head.have_attrs = o->have_attrs; + + res = fops->create(o->pobj, overwrite, &head, sizeof(head), attr, + attr_size, NULL, 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; + void *oid_bbuf = 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); + + /* Check presence of optional buffer */ + if (len && !data) + return TEE_ERROR_BAD_PARAMETERS; + + res = bb_memdup_user_private(object_id, object_id_len, &oid_bbuf); + if (res) + return res; + + res = tee_pobj_get((void *)&sess->ctx->uuid, oid_bbuf, + object_id_len, flags, TEE_POBJ_USAGE_CREATE, + fops, &po); + bb_free(oid_bbuf, object_id_len); + if (res != TEE_SUCCESS) + 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. + * + * Persistent object keeps the objectUsage field in the + * pobj so move the field below. + */ + 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; + po->obj_info_usage = attr_o->info.objectUsage; + 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; + } + attr_o->info.objectUsage = 0; + } 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; + void *oid_bbuf = 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; + } + + res = bb_memdup_user_private(object_id, object_id_len, &oid_bbuf); + if (res) + goto exit; + + /* reserve dest name */ + fops = o->pobj->fops; + res = tee_pobj_get((void *)&sess->ctx->uuid, oid_bbuf, + object_id_len, TEE_DATA_FLAG_ACCESS_WRITE_META, + TEE_POBJ_USAGE_RENAME, fops, &po); + bb_free(oid_bbuf, object_id_len); + 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, po->obj_id, po->obj_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; + struct utee_object_info bbuf = { }; + + 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; + + tee_pobj_lock_usage(o->pobj); + res = tee_svc_storage_read_head(o); + bbuf = (struct utee_object_info){ + .obj_type = o->info.objectType, + .obj_size = o->info.objectSize, + .max_obj_size = o->info.maxObjectSize, + .obj_usage = o->pobj->obj_info_usage, + .data_size = o->info.dataSize, + .data_pos = o->info.dataPosition, + .handle_flags = o->info.handleFlags, + }; + tee_pobj_unlock_usage(o->pobj); + if (res != TEE_SUCCESS) + goto exit; + + res = copy_to_user(info, &bbuf, sizeof(bbuf)); + if (res) + goto exit; + + res = copy_to_user(obj_id, o->pobj->obj_id, o->pobj->obj_id_len); + if (res) + goto exit; + + 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); + + 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, NULL, 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); + + 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, NULL, 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 tee_svc_storage_write_usage(struct tee_obj *o, uint32_t usage) +{ + const size_t pos = offsetof(struct tee_svc_storage_head, objectUsage); + + return o->pobj->fops->write(o->fh, pos, &usage, NULL, sizeof(usage)); +} + +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..8b03a87 --- /dev/null +++ b/optee/optee_os/core/tee/tee_time_generic.c @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#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/notif_test_wd.c b/optee/optee_os/core/tests/notif_test_wd.c new file mode 100644 index 0000000..8cad0c8 --- /dev/null +++ b/optee/optee_os/core/tests/notif_test_wd.c @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2024, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include + +#define TEST_WD_TIMER_PERIOD_MS 1000 + +struct wd_data { + bool pending; + bool enabled; + unsigned int timeout_count; + unsigned int call_count; + struct callout callout; +}; + +static struct wd_data default_wd_data; + +static struct wd_data *get_wd_data(void) +{ + return &default_wd_data; +} + +static bool test_wd_callback(struct callout *co) +{ + struct wd_data *wd = container_of(co, struct wd_data, callout); + + if (wd->pending) + wd->timeout_count++; + wd->call_count++; + if (wd->call_count < 10 || !(wd->call_count % 60) || wd->pending) + DMSG("WD call_count %u, timeout_count %u", + wd->call_count, wd->timeout_count); + wd->pending = true; + notif_send_async(NOTIF_VALUE_DO_BOTTOM_HALF); + + return true; +} + +static void wd_ndrv_atomic_cb(struct notif_driver *ndrv __unused, + enum notif_event ev) +{ + if (ev == NOTIF_EVENT_STARTED) { + struct wd_data *wd = get_wd_data(); + + if (!wd->enabled) { + callout_add(&wd->callout, test_wd_callback, + TEST_WD_TIMER_PERIOD_MS); + + wd->enabled = true; + } + } +} +DECLARE_KEEP_PAGER(wd_ndrv_atomic_cb); + +static void wd_ndrv_yielding_cb(struct notif_driver *ndrv __unused, + enum notif_event ev) +{ + if (ev == NOTIF_EVENT_DO_BOTTOM_HALF) { + struct wd_data *wd = get_wd_data(); + + if (wd->pending && wd->call_count < 10) + DMSG("Clearing pending"); + wd->pending = false; + } +} + +struct notif_driver wd_ndrv __nex_data = { + .atomic_cb = wd_ndrv_atomic_cb, + .yielding_cb = wd_ndrv_yielding_cb, +}; + +static TEE_Result nex_init_test_wd(void) +{ + notif_register_driver(&wd_ndrv); + + return TEE_SUCCESS; +} + +nex_early_init(nex_init_test_wd); + +struct periodic_data { + unsigned int count; + struct callout callout; +}; + +static bool periodic_callback(struct callout *co) +{ + struct periodic_data *d = container_of(co, struct periodic_data, + callout); + TEE_Time t = { }; + + if (tee_time_get_sys_time(&t)) + panic(); + d->count++; + DMSG("seconds %"PRIu32" millis %"PRIu32" count %u", + t.seconds, t.millis, d->count); + + if (d->count > 20) { + DMSG("Disabling periodic callout"); + return false; + } + + return true; +} +DECLARE_KEEP_PAGER(periodic_callback); + +static TEE_Result nex_init_periodic_callback(void) +{ + struct periodic_data *d = nex_calloc(1, sizeof(*d)); + + if (!d) + return TEE_ERROR_OUT_OF_MEMORY; + + DMSG("Adding a periodic callout"); + callout_add(&d->callout, periodic_callback, TEST_WD_TIMER_PERIOD_MS); + + return TEE_SUCCESS; +} + +nex_early_init(nex_init_periodic_callback); diff --git a/optee/optee_os/core/tests/sub.mk b/optee/optee_os/core/tests/sub.mk new file mode 100644 index 0000000..093b51e --- /dev/null +++ b/optee/optee_os/core/tests/sub.mk @@ -0,0 +1,2 @@ +srcs-y += ftmn_boot_tests.c +srcs-$(CFG_NOTIF_TEST_WD) += notif_test_wd.c diff --git a/optee/optee_os/keys/default.pem b/optee/optee_os/keys/default.pem new file mode 100644 index 0000000..a8e5dcd --- /dev/null +++ b/optee/optee_os/keys/default.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/keys/default_ta.pem b/optee/optee_os/keys/default_ta.pem new file mode 120000 index 0000000..08aee5e --- /dev/null +++ b/optee/optee_os/keys/default_ta.pem @@ -0,0 +1 @@ +default.pem \ No newline at end of file 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..bab60f7 --- /dev/null +++ b/optee/optee_os/ldelf/ftrace.c @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019, Linaro Limited + */ + +#include +#include +#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; + size_t pad = 0; + char *p = NULL; + char magic[] = { 'F', 'T', 'R', 'A', 'C', 'E', 0x00, 0x01 }; + + 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); + p = (char *)fbuf + fbuf->head_off; + count = snprintk(p, MAX_HEADER_STRLEN, + "Function graph for TA: %pUl @ %lx\n", + (void *)&elf->uuid, elf->load_addr); + assert(count < MAX_HEADER_STRLEN); + p += count; + + 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; + /* For proper alignment of uint64_t values in the ftrace buffer */ + pad = 8 - (vaddr_t)p % 8; + if (pad == 8) + pad = 0; + while (pad--) { + *p++ = 0; + fbuf->buf_off++; + count++; + } + /* Delimiter for easier decoding */ + memcpy(p, magic, sizeof(magic)); + fbuf->buf_off += sizeof(magic); + count += sizeof(magic); + fbuf->curr_idx = 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); + char *hstart = (char *)fbuf + fbuf->head_off; + char *cstart = (char *)fbuf + fbuf->buf_off; + char *ccurr = cstart + fbuf->curr_idx * sizeof(uint64_t); + size_t csize = 0; + size_t dump_size = 0; + char *end = NULL; + + assert(elf && elf->is_main); + + if (fbuf->overflow) + csize = fbuf->max_size; + else + csize = fbuf->curr_idx * sizeof(uint64_t); + dump_size = fbuf->buf_off - fbuf->head_off + csize; + end = hstart + dump_size; + + /* Header */ + copy_func(pctx, hstart, fbuf->buf_off - fbuf->head_off); + if (fbuf->overflow) { + /* From current index to end of circular buffer */ + copy_func(pctx, ccurr, end - ccurr); + } + /* From start of circular buffer to current index */ + copy_func(pctx, cstart, ccurr - cstart); + } +} + +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..032b328 --- /dev/null +++ b/optee/optee_os/ldelf/main.c @@ -0,0 +1,187 @@ +// 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); +#if defined(ARM32) || defined(ARM64) + EMSG_RAW(" arch: %s", elf->is_32bit ? "arm" : "aarch64"); +#elif defined(RV32) || defined(RV64) + EMSG_RAW(" arch: %s", elf->is_32bit ? "riscv32" : "riscv64"); +#endif + + ta_elf_print_mappings(NULL, print_to_console, &main_elf_queue, + arg->num_maps, arg->maps, mpool_base); + +#if defined(ARM32) || defined(ARM64) + 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); +#elif defined(RV32) || defined(RV64) + ta_elf_stack_trace_riscv(arg->rv.fp, arg->rv.pc); +#endif + + 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..70f8a84 --- /dev/null +++ b/optee/optee_os/ldelf/ta_elf.c @@ -0,0 +1,2016 @@ +// 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 "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_ident[EI_OSABI] != ELFOSABI_ARM) || + ehdr->e_type != ET_DYN || ehdr->e_machine != EM_ARM || +#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; + + if (ehdr->e_ident[EI_OSABI] == ELFOSABI_NONE && + (ehdr->e_flags & EF_ARM_ABIMASK) != EF_ARM_ABI_V5) + return TEE_ERROR_BAD_FORMAT; + + if (ehdr->e_ident[EI_OSABI] == ELFOSABI_ARM && + (ehdr->e_flags & EF_ARM_ABIMASK) != EF_ARM_ABI_UNKNOWN) + 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++) { + TEE_Result res = TEE_SUCCESS; + + 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"); + res = tee_uuid_from_str(&uuid, str_tab + val); + if (res) + err(res, "Fail to get UUID from string"); + 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) +{ + vaddr_t va = 0; + + 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); + + if (!ta_elf_resolve_sym("ta_head", &va, NULL, elf)) + elf->head = (struct ta_head *)va; + else + 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 + +#if defined(ARM32) || defined(ARM64) +/* 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); +} +#elif defined(RV32) || defined(RV64) +void ta_elf_stack_trace_riscv(uint64_t fp, uint64_t pc) +{ + struct unwind_state_riscv state = { .fp = fp, .pc = pc }; + + print_stack_riscv(&state, ta_stack, ta_stack_size); +} +#endif + +#endif /* CFG_UNWIND */ + +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..fdb6508 --- /dev/null +++ b/optee/optee_os/ldelf/ta_elf.h @@ -0,0 +1,153 @@ +/* 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); +void ta_elf_stack_trace_riscv(uint64_t fp, 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) { } +static inline void ta_elf_stack_trace_riscv(uint64_t fp __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..bc895e8 --- /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 if (val) + *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 __maybe_unused = 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..56ab50b --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/core/aes.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2018, ARM Limited + * Copyright (C) 2019, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#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..dea30f6 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/core/bignum.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 + +#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) +{ + assert(s); + + mbedtls_mpi_free((mbedtls_mpi *)*s); + free(*s); + *s = NULL; +} + +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..25c49cc --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/core/dh.c @@ -0,0 +1,144 @@ +// 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; + size_t len = 0; + + memset(&dhm, 0, sizeof(dhm)); + mbedtls_dhm_init(&dhm); + + dhm.G = *(mbedtls_mpi *)key->g; + dhm.P = *(mbedtls_mpi *)key->p; + + len = mbedtls_dhm_get_len(&dhm); + if (key_size != 8 * len) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + if (xbits == 0) + xbytes = len; + else + xbytes = xbits / 8; + + buf = malloc(len); + if (!buf) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + lmd_res = mbedtls_dhm_make_public(&dhm, (int)xbytes, buf, + 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; + size_t len = 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; + + len = mbedtls_dhm_get_len(&dhm); + + buf = malloc(len); + if (!buf) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + lmd_res = mbedtls_dhm_calc_secret(&dhm, buf, 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..3858557 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/core/ecc.c @@ -0,0 +1,548 @@ +// 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; +} + +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; + } + + /* 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", -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_ecdh_setup(&ecdh, gid); + if (lmd_res != 0) { + res = TEE_ERROR_NOT_SUPPORTED; + goto out; + } + + assert(ecdh.var == MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0); + ecdh.ctx.mbed_ecdh.d = *(mbedtls_mpi *)private_key->d; + ecdh.ctx.mbed_ecdh.Qp.X = *(mbedtls_mpi *)public_key->x; + ecdh.ctx.mbed_ecdh.Qp.Y = *(mbedtls_mpi *)public_key->y; + mbedtls_mpi_read_binary(&ecdh.ctx.mbed_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.ctx.mbed_ecdh.d); + mbedtls_mpi_init(&ecdh.ctx.mbed_ecdh.Qp.X); + mbedtls_mpi_init(&ecdh.ctx.mbed_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..651a9bf --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/core/hash.c @@ -0,0 +1,244 @@ +// 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); + uint8_t block_digest[TEE_MAX_HASH_SIZE] = { 0 }; + uint8_t *tmp_digest = NULL; + size_t hash_size = 0; + + if (len == 0) + return TEE_ERROR_BAD_PARAMETERS; + + hash_size = mbedtls_md_get_size(mbedtls_md_info_from_ctx(&hc->md_ctx)); + 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..0f93017 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/core/hmac.c @@ -0,0 +1,174 @@ +// 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); + uint8_t block_digest[TEE_MAX_HASH_SIZE] = { 0 }; + uint8_t *tmp_digest = NULL; + size_t hmac_size = 0; + + if (len == 0) + return TEE_ERROR_BAD_PARAMETERS; + + hmac_size = mbedtls_md_get_size(mbedtls_md_info_from_ctx(&c->md_ctx)); + 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..1562c53 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/core/mbed_helpers.h @@ -0,0 +1,31 @@ +/* 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; +} + +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..89ebb0d --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/core/rsa.c @@ -0,0 +1,817 @@ +// 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 "../mbedtls/library/pk_wrap.h" +#include "../mbedtls/library/rsa_alt_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 TEE_Result rsa_init_and_complete_from_key_pair(mbedtls_rsa_context *rsa, + struct rsa_keypair *key) +{ + int lmd_res = 0; + + mbedtls_rsa_init(rsa); + + rsa->E = *(mbedtls_mpi *)key->e; + rsa->N = *(mbedtls_mpi *)key->n; + rsa->D = *(mbedtls_mpi *)key->d; + rsa->len = mbedtls_mpi_size(&rsa->N); + + 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; + } else { + mbedtls_mpi_init_mempool(&rsa->P); + mbedtls_mpi_init_mempool(&rsa->Q); + mbedtls_mpi_init_mempool(&rsa->QP); + mbedtls_mpi_init_mempool(&rsa->DP); + mbedtls_mpi_init_mempool(&rsa->DQ); + + lmd_res = mbedtls_rsa_deduce_primes(&rsa->N, &rsa->E, &rsa->D, + &rsa->P, &rsa->Q); + if (lmd_res) { + DMSG("mbedtls_rsa_deduce_primes() returned 0x%x", + -lmd_res); + goto err; + } + + lmd_res = mbedtls_rsa_deduce_crt(&rsa->P, &rsa->Q, &rsa->D, + &rsa->DP, &rsa->DQ, &rsa->QP); + if (lmd_res) { + DMSG("mbedtls_rsa_deduce_crt() returned 0x%x", + -lmd_res); + goto err; + } + } + + return TEE_SUCCESS; +err: + mbedtls_mpi_free(&rsa->P); + mbedtls_mpi_free(&rsa->Q); + mbedtls_mpi_free(&rsa->QP); + mbedtls_mpi_free(&rsa->DP); + mbedtls_mpi_free(&rsa->DQ); + + return get_tee_result(lmd_res); +} + +static void mbd_rsa_free(mbedtls_rsa_context *rsa, struct rsa_keypair *key) +{ + /* + * The mpi's in @rsa are initialized from @key, but the primes and + * CRT part are generated if @key doesn't have them. When freeing + * we should only free the generated mpi's, the ones copied are + * reset instead. + */ + mbedtls_mpi_init(&rsa->E); + mbedtls_mpi_init(&rsa->N); + mbedtls_mpi_init(&rsa->D); + if (key->p && crypto_bignum_num_bytes(key->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); + + /* 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); + + 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; + + res = rsa_init_and_complete_from_key_pair(&rsa, key); + if (res) + return res; + + 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, mbd_rand, 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, key); + 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; + + res = rsa_init_and_complete_from_key_pair(&rsa, key); + if (res) + return 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. + */ + 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); + + 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, key); + 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); + + 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; + + res = rsa_init_and_complete_from_key_pair(&rsa, key); + if (res) + return res; + + switch (algo) { + case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: + 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); + + lmd_res = pk_info->sign_func(&rsa, md_algo, msg, msg_len, sig, + *sig_len, 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, key); + 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); + + 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..2b6a517 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/core/sub.mk @@ -0,0 +1,33 @@ +cppflags-y += -DMBEDTLS_ALLOW_PRIVATE_ACCESS +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..c3924f4 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/include/mbedtls_config_kernel.h @@ -0,0 +1,136 @@ +/* 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) +#if defined(CFG_CRYPTO_SHA224) +#define MBEDTLS_SHA224_C +#endif +#if defined(CFG_CRYPTO_SHA256) +#define MBEDTLS_SHA256_C +#endif +#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) +#if defined(CFG_CRYPTO_SHA384) +#define MBEDTLS_SHA384_C +#endif +#if defined(CFG_CRYPTO_SHA512) +#define MBEDTLS_SHA512_C +#endif +#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 +#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..255b121 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/include/mbedtls_config_uta.h @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2018, Linaro limited + * Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved. + */ +#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_SHA384_C +#define MBEDTLS_SHA512_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/.uncrustify.cfg b/optee/optee_os/lib/libmbedtls/mbedtls/.uncrustify.cfg new file mode 100644 index 0000000..92b8ce9 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/.uncrustify.cfg @@ -0,0 +1,252 @@ +# Configuration options for Uncrustify specifying the Mbed TLS code style. +# +# Note: The code style represented by this file has not yet been introduced +# to 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. + + +# Wrap lines at 100 characters +code_width = 100 + +# Allow splitting long for statements between the condition statements +ls_for_split_full = true + +# Allow splitting function calls between arguments +ls_func_split_full = true + +input_tab_size = 4 + +# Spaces-only indentation +indent_with_tabs = 0 + +indent_columns = 4 + +# Indent 'case' 1 level from 'switch' +indent_switch_case = indent_columns + +# Line-up strings broken by '\' +indent_align_string = true + +# Braces on the same line (Egyptian-style braces) +nl_enum_brace = remove +nl_union_brace = remove +nl_struct_brace = remove +nl_do_brace = remove +nl_if_brace = remove +nl_for_brace = remove +nl_else_brace = remove +nl_while_brace = remove +nl_switch_brace = remove + +# Braces on same line as keywords that follow them - 'else' and the 'while' in 'do {} while ()'; +nl_brace_else = remove +nl_brace_while = remove +# Space before else on the same line +sp_brace_else = add +# If else is on the same line as '{', force exactly 1 space between them +sp_else_brace = force + +# Functions are the exception and have braces on the next line +nl_fcall_brace = add +nl_fdef_brace = add + +# Force exactly one space between ')' and '{' in statements +sp_sparen_brace = force + +# At least 1 space around assignment +sp_assign = add + +# Remove spaces around the preprocessor '##' token-concatenate +sp_pp_concat = ignore + +# At least 1 space around '||' and '&&' +sp_bool = add + +# But no space after the '!' operator +sp_not = remove + +# No space after the bitwise-not '~' operator +sp_inv = remove + +# No space after the addressof '&' operator +sp_addr = remove + +# No space around the member '.' and '->' operators +sp_member = remove + +# No space after the dereference '*' operator +sp_deref = remove + +# No space after a unary negation '-' +sp_sign = remove + +# No space between the '++'/'--' operator and its operand +sp_incdec = remove + +# At least 1 space around comparison operators +sp_compare = add + +# Remove spaces inside all kinds of parentheses: + +# Remove spaces inside parentheses +sp_inside_paren = remove + +# No spaces inside statement parentheses +sp_inside_sparen = remove + +# No spaces inside cast parentheses '( char )x' -> '(char)x' +sp_inside_paren_cast = remove + +# No spaces inside function parentheses +sp_inside_fparen = remove +# (The case where the function has no parameters/arguments) +sp_inside_fparens = remove + +# No spaces inside the first parentheses in a function type +sp_inside_tparen = remove + +# (Uncrustify >= 0.74.0) No spaces inside parens in for statements +sp_inside_for = remove + +# Remove spaces between nested parentheses '( (' -> '((' +sp_paren_paren = remove +# (Uncrustify >= 0.74.0) +sp_sparen_paren = remove + +# Remove spaces between ')' and adjacent '(' +sp_cparen_oparen = remove + +# (Uncrustify >= 0.73.0) space between 'do' and '{' +sp_do_brace_open = force + +# (Uncrustify >= 0.73.0) space between '}' and 'while' +sp_brace_close_while = force + +# At least 1 space before a '*' pointer star +sp_before_ptr_star = add + +# Remove spaces between pointer stars +sp_between_ptr_star = remove + +# No space after a pointer star +sp_after_ptr_star = remove + +# But allow a space in the case of e.g. char * const x; +sp_after_ptr_star_qualifier = ignore + +# Remove space after star in a function return type +sp_after_ptr_star_func = remove + +# At least 1 space after a type in variable definition etc +sp_after_type = add + +# Force exactly 1 space between a statement keyword (e.g. 'if') and an opening parenthesis +sp_before_sparen = force + +# Remove a space before a ';' +sp_before_semi = remove +# (Uncrustify >= 0.73.0) Remove space before a semi in a non-empty for +sp_before_semi_for = remove +# (Uncrustify >= 0.73.0) Remove space in empty first statement of a for +sp_before_semi_for_empty = remove +# (Uncrustify >= 0.74.0) Remove space in empty middle statement of a for +sp_between_semi_for_empty = remove + +# Add a space after a ';' (unless a comment follows) +sp_after_semi = add +# (Uncrustify >= 0.73.0) Add a space after a semi in non-empty for statements +sp_after_semi_for = add +# (Uncrustify >= 0.73.0) No space after final semi in empty for statements +sp_after_semi_for_empty = remove + +# Remove spaces on the inside of square brackets '[]' +sp_inside_square = remove + +# Must have at least 1 space after a comma +sp_after_comma = add + +# Must not have a space before a comma +sp_before_comma = remove + +# No space before the ':' in a case statement +sp_before_case_colon = remove + +# Must have space after a cast - '(char)x' -> '(char) x' +sp_after_cast = add + +# No space between 'sizeof' and '(' +sp_sizeof_paren = remove + +# At least 1 space inside '{ }' +sp_inside_braces = add + +# At least 1 space inside '{ }' in an enum +sp_inside_braces_enum = add + +# At least 1 space inside '{ }' in a struct +sp_inside_braces_struct = add + +# At least 1 space between a function return type and the function name +sp_type_func = add + +# No space between a function name and its arguments/parameters +sp_func_proto_paren = remove +sp_func_def_paren = remove +sp_func_call_paren = remove + +# No space between '__attribute__' and '(' +sp_attribute_paren = remove + +# No space between 'defined' and '(' in preprocessor conditions +sp_defined_paren = remove + +# At least 1 space between a macro's name and its definition +sp_macro = add +sp_macro_func = add + +# Force exactly 1 space between a '}' and the name of a typedef if on the same line +sp_brace_typedef = force + +# At least 1 space before a '\' line continuation +sp_before_nl_cont = add + +# At least 1 space around '?' and ':' in ternary statements +sp_cond_colon = add +sp_cond_question = add + +# Space between #else/#endif and comment afterwards +sp_endif_cmt = add + +# Remove newlines at the start of a file +nl_start_of_file = remove + +# At least 1 newline at the end of a file +nl_end_of_file = add +nl_end_of_file_min = 1 + +# Add braces in single-line statements +mod_full_brace_do = add +mod_full_brace_for = add +mod_full_brace_if = add +mod_full_brace_while = add + +# Remove parentheses from return statements +mod_paren_on_return = remove + +# Disable removal of leading spaces in a multi-line comment if the first and +# last lines are the same length +cmt_multi_check_last = false 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..a7bf198 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/CONTRIBUTING.md @@ -0,0 +1,91 @@ +Contributing +============ +We gratefully accept bug reports and contributions from the community. All PRs are reviewed by the project team / community, and may need some modifications to +be accepted. + +Quick Checklist for PR contributors +----------------------------------- +More details on all of these points may be found in the sections below. + +- [Sign-off](#license-and-copyright): all commits must be signed off. +- [Tests](#tests): please ensure the PR includes adequate tests. +- [Changelog](#documentation): if needed, please provide a changelog entry. +- [Backports](#long-term-support-branches): provide a backport if needed (it's fine to wait until the main PR is accepted). + +Coding Standards +---------------- +- Contributions should include tests, as mentioned in the [Tests](#tests) and [Continuous Integration](#continuous-integration-tests) sections. Please check that your contribution passes basic tests before submission, and check the CI results after making a pull request. +- The code should be written in a clean and readable style, and must follow [our coding standards](https://mbed-tls.readthedocs.io/en/latest/kb/development/mbedtls-coding-standards/). +- 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. + +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. If there is an API change, the contribution, if accepted, will be merged only when there is a major release. + +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. Where changes to an existing interface are necessary, functions in the public interface which need to be changed are marked as 'deprecated'. If there is a strong reason to replace an existing function with one that has a slightly different interface (different prototype, or different documented behavior), create a new function with a new name with the desired interface. Keep the old function, but mark it as deprecated. + +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_rsa.c`). These files are generated from a `function file` (e.g. `suites/test_suite_rsa.function`) and a `data file` (e.g. `suites/test_suite_rsa.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://mbed-tls.readthedocs.io/en/latest/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://mbed-tls.readthedocs.io/en/latest/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. + +License and Copyright +--------------------- + +All new files should include the [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) standard license header where possible. For licensing details, please see the [License section of the README](README.md#License). + +The copyright on contributions is retained by the original authors of the code. Where possible for new files, this should be noted in a comment at the top of the file in the form: "Copyright The Mbed TLS Contributors". + +When contributing code to us, the committer and all authors are required to make the submission under the terms of the [Developer Certificate of Origin](dco.txt), confirming that the code submitted can (legally) become part of the project, and be subject to the same Apache 2.0 license. This is done by including the standard Git `Signed-off-by:` line in every commit message. If more than one person contributed to the commit, they should also add their own `Signed-off-by:` line. diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/ChangeLog b/optee/optee_os/lib/libmbedtls/mbedtls/ChangeLog new file mode 100644 index 0000000..9b30aff --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/ChangeLog @@ -0,0 +1,5527 @@ +Mbed TLS ChangeLog (Sorted per branch, date) + += Mbed TLS 3.4.0 branch released 2023-03-28 + +Default behavior changes + * The default priority order of TLS 1.3 cipher suites has been modified to + follow the same rules as the TLS 1.2 cipher suites (see + ssl_ciphersuites.c). The preferred cipher suite is now + TLS_CHACHA20_POLY1305_SHA256. + +New deprecations + * mbedtls_x509write_crt_set_serial() is now being deprecated in favor of + mbedtls_x509write_crt_set_serial_raw(). The goal here is to remove any + direct dependency of X509 on BIGNUM_C. + * PSA to mbedtls error translation is now unified in psa_util.h, + deprecating mbedtls_md_error_from_psa. Each file that performs error + translation should define its own version of PSA_TO_MBEDTLS_ERR, + optionally providing file-specific error pairs. Please see psa_util.h for + more details. + +Features + * Added partial support for parsing the PKCS #7 Cryptographic Message + Syntax, as defined in RFC 2315. Currently, support is limited to the + following: + - Only the signed-data content type, version 1 is supported. + - Only DER encoding is supported. + - Only a single digest algorithm per message is supported. + - Certificates must be in X.509 format. A message must have either 0 + or 1 certificates. + - There is no support for certificate revocation lists. + - The authenticated and unauthenticated attribute fields of SignerInfo + must be empty. + Many thanks to Daniel Axtens, Nayna Jain, and Nick Child from IBM for + contributing this feature, and to Demi-Marie Obenour for contributing + various improvements, tests and bug fixes. + * General performance improvements by accessing multiple bytes at a time. + Fixes #1666. + * Improvements to use of unaligned and byte-swapped memory, reducing code + size and improving performance (depending on compiler and target + architecture). + * Add support for reading points in compressed format + (MBEDTLS_ECP_PF_COMPRESSED) with mbedtls_ecp_point_read_binary() + (and callers) for Short Weierstrass curves with prime p where p = 3 mod 4 + (all mbedtls MBEDTLS_ECP_DP_SECP* and MBEDTLS_ECP_DP_BP* curves + except MBEDTLS_ECP_DP_SECP224R1 and MBEDTLS_ECP_DP_SECP224K1) + * SHA224_C/SHA384_C are now independent from SHA384_C/SHA512_C respectively. + This helps in saving code size when some of the above hashes are not + required. + * Add parsing of V3 extensions (key usage, Netscape cert-type, + Subject Alternative Names) in x509 Certificate Sign Requests. + * Use HOSTCC (if it is set) when compiling C code during generation of the + configuration-independent files. This allows them to be generated when + CC is set for cross compilation. + * Add parsing of uniformResourceIdentifier subtype for subjectAltName + extension in x509 certificates. + * Add an interruptible version of sign and verify hash to the PSA interface, + backed by internal library support for ECDSA signing and verification. + * Add parsing of rfc822Name subtype for subjectAltName + extension in x509 certificates. + * The configuration macros MBEDTLS_PSA_CRYPTO_PLATFORM_FILE and + MBEDTLS_PSA_CRYPTO_STRUCT_FILE specify alternative locations for + the headers "psa/crypto_platform.h" and "psa/crypto_struct.h". + * When a PSA driver for ECDSA is present, it is now possible to disable + MBEDTLS_ECDSA_C in the build in order to save code size. For PK, X.509 + and TLS to fully work, this requires MBEDTLS_USE_PSA_CRYPTO to be enabled. + Restartable/interruptible ECDSA operations in PK, X.509 and TLS are not + supported in those builds yet, as driver support for interruptible ECDSA + operations is not present yet. + * Add a driver dispatch layer for EC J-PAKE, enabling alternative + implementations of EC J-PAKE through the driver entry points. + * Add new API mbedtls_ssl_cache_remove for cache entry removal by + its session id. + * Add support to include the SubjectAltName extension to a CSR. + * Add support for AES with the Armv8-A Cryptographic Extension on + 64-bit Arm. A new configuration option, MBEDTLS_AESCE_C, can + be used to enable this feature. Run-time detection is supported + under Linux only. + * When a PSA driver for EC J-PAKE is present, it is now possible to disable + MBEDTLS_ECJPAKE_C in the build in order to save code size. For the + corresponding TLS 1.2 key exchange to work, MBEDTLS_USE_PSA_CRYPTO needs + to be enabled. + * Add functions mbedtls_rsa_get_padding_mode() and mbedtls_rsa_get_md_alg() + to read non-public fields for padding mode and hash id from + an mbedtls_rsa_context, as requested in #6917. + * AES-NI is now supported with Visual Studio. + * AES-NI is now supported in 32-bit builds, or when MBEDTLS_HAVE_ASM + is disabled, when compiling with GCC or Clang or a compatible compiler + for a target CPU that supports the requisite instructions (for example + gcc -m32 -msse2 -maes -mpclmul). (Generic x86 builds with GCC-like + compilers still require MBEDTLS_HAVE_ASM and a 64-bit target.) + * It is now possible to use a PSA-held (opaque) password with the TLS 1.2 + ECJPAKE key exchange, using the new API function + mbedtls_ssl_set_hs_ecjpake_password_opaque(). + +Security + * Use platform-provided secure zeroization function where possible, such as + explicit_bzero(). + * Zeroize SSL cache entries when they are freed. + * Fix a potential heap buffer overread in TLS 1.3 client-side when + MBEDTLS_DEBUG_C is enabled. This may result in an application crash. + * Add support for AES with the Armv8-A Cryptographic Extension on 64-bit + Arm, so that these systems are no longer vulnerable to timing side-channel + attacks. This is configured by MBEDTLS_AESCE_C, which is on by default. + Reported by Demi Marie Obenour. + * MBEDTLS_AESNI_C, which is enabled by default, was silently ignored on + builds that couldn't compile the GCC-style assembly implementation + (most notably builds with Visual Studio), leaving them vulnerable to + timing side-channel attacks. There is now an intrinsics-based AES-NI + implementation as a fallback for when the assembly one cannot be used. + +Bugfix + * Fix possible integer overflow in mbedtls_timing_hardclock(), which + could cause a crash in programs/test/benchmark. + * Fix IAR compiler warnings. Fixes #6924. + * Fix a bug in the build where directory names containing spaces were + causing generate_errors.pl to error out resulting in a build failure. + Fixes issue #6879. + * In TLS 1.3, when using a ticket for session resumption, tweak its age + calculation on the client side. It prevents a server with more accurate + ticket timestamps (typically timestamps in milliseconds) compared to the + Mbed TLS ticket timestamps (in seconds) to compute a ticket age smaller + than the age computed and transmitted by the client and thus potentially + reject the ticket. Fix #6623. + * Fix compile error where MBEDTLS_RSA_C and MBEDTLS_X509_CRT_WRITE_C are + defined, but MBEDTLS_PK_RSA_ALT_SUPPORT is not defined. Fixes #3174. + * List PSA_WANT_ALG_CCM_STAR_NO_TAG in psa/crypto_config.h so that it can + be toggled with config.py. + * The key derivation algorithm PSA_ALG_TLS12_ECJPAKE_TO_PMS cannot be + used on a shared secret from a key agreement since its input must be + an ECC public key. Reject this properly. + * mbedtls_x509write_crt_set_serial() now explicitly rejects serial numbers + whose binary representation is longer than 20 bytes. This was already + forbidden by the standard (RFC5280 - section 4.1.2.2) and now it's being + enforced also at code level. + * Fix potential undefined behavior in mbedtls_mpi_sub_abs(). Reported by + Pascal Cuoq using TrustInSoft Analyzer in #6701; observed independently by + Aaron Ucko under Valgrind. + * Fix behavior of certain sample programs which could, when run with no + arguments, access uninitialized memory in some cases. Fixes #6700 (which + was found by TrustInSoft Analyzer during REDOCS'22) and #1120. + * Fix parsing of X.509 SubjectAlternativeName extension. Previously, + malformed alternative name components were not caught during initial + certificate parsing, but only on subsequent calls to + mbedtls_x509_parse_subject_alt_name(). Fixes #2838. + * Make the fields of mbedtls_pk_rsassa_pss_options public. This makes it + possible to verify RSA PSS signatures with the pk module, which was + inadvertently broken since Mbed TLS 3.0. + * Fix bug in conversion from OID to string in + mbedtls_oid_get_numeric_string(). OIDs such as 2.40.0.25 are now printed + correctly. + * Reject OIDs with overlong-encoded subidentifiers when converting + them to a string. + * Reject OIDs with subidentifier values exceeding UINT_MAX. Such + subidentifiers can be valid, but Mbed TLS cannot currently handle them. + * Reject OIDs that have unterminated subidentifiers, or (equivalently) + have the most-significant bit set in their last byte. + * Silence warnings from clang -Wdocumentation about empty \retval + descriptions, which started appearing with Clang 15. Fixes #6960. + * Fix the handling of renegotiation attempts in TLS 1.3. They are now + systematically rejected. + * Fix an unused-variable warning in TLS 1.3-only builds if + MBEDTLS_SSL_RENEGOTIATION was enabled. Fixes #6200. + * Fix undefined behavior in mbedtls_ssl_read() and mbedtls_ssl_write() if + len argument is 0 and buffer is NULL. + * Allow setting user and peer identifiers for EC J-PAKE operation + instead of role in PAKE PSA Crypto API as described in the specification. + This is a partial fix that allows only "client" and "server" identifiers. + * Fix a compilation error when PSA Crypto is built with support for + TLS12_PRF but not TLS12_PSK_TO_MS. Reported by joerchan in #7125. + * In the TLS 1.3 server, select the preferred client cipher suite, not the + least preferred. The selection error was introduced in Mbed TLS 3.3.0. + * Fix TLS 1.3 session resumption when the established pre-shared key is + 384 bits long. That is the length of pre-shared keys created under a + session where the cipher suite is TLS_AES_256_GCM_SHA384. + * Fix an issue when compiling with MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT + enabled, which required specifying compiler flags enabling SHA3 Crypto + Extensions, where some compilers would emit EOR3 instructions in other + modules, which would then fail if run on a CPU without the SHA3 + extensions. Fixes #5758. + +Changes + * Install the .cmake files into CMAKE_INSTALL_LIBDIR/cmake/MbedTLS, + typically /usr/lib/cmake/MbedTLS. + * Mixed-endian systems are explicitly not supported any more. + * When MBEDTLS_USE_PSA_CRYPTO and MBEDTLS_ECDSA_DETERMINISTIC are both + defined, mbedtls_pk_sign() now use deterministic ECDSA for ECDSA + signatures. This aligns the behaviour with MBEDTLS_USE_PSA_CRYPTO to + the behaviour without it, where deterministic ECDSA was already used. + * Visual Studio: Rename the directory containing Visual Studio files from + visualc/VS2010 to visualc/VS2013 as we do not support building with versions + older than 2013. Update the solution file to specify VS2013 as a minimum. + * programs/x509/cert_write: + - now it accepts the serial number in 2 different formats: decimal and + hex. They cannot be used simultaneously + - "serial" is used for the decimal format and it's limted in size to + unsigned long long int + - "serial_hex" is used for the hex format; max length here is + MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN*2 + * The C code follows a new coding style. This is transparent for users but + affects contributors and maintainers of local patches. For more + information, see + https://mbed-tls.readthedocs.io/en/latest/kb/how-to/rewrite-branch-for-coding-style/ + * Changed the default MBEDTLS_ECP_WINDOW_SIZE from 6 to 2. + As tested in issue 6790, the correlation between this define and + RSA decryption performance has changed lately due to security fixes. + To fix the performance degradation when using default values the + window was reduced from 6 to 2, a value that gives the best or close + to best results when tested on Cortex-M4 and Intel i7. + * When enabling MBEDTLS_SHA256_USE_A64_CRYPTO_* or + MBEDTLS_SHA512_USE_A64_CRYPTO_*, it is no longer necessary to specify + compiler target flags on the command line; the library now sets target + options within the appropriate modules. + += Mbed TLS 3.3.0 branch released 2022-12-14 + +Default behavior changes + * Previously the macro MBEDTLS_SSL_DTLS_CONNECTION_ID implemented version 05 + of the IETF draft, and was marked experimental and disabled by default. + It is now no longer experimental, and implements the final version from + RFC 9146, which is not interoperable with the draft-05 version. + If you need to communicate with peers that use earlier versions of + Mbed TLS, then you need to define MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT + to 1, but then you won't be able to communicate with peers that use the + standard (non-draft) version. + If you need to interoperate with both classes of peers with the + same build of Mbed TLS, please let us know about your situation on the + mailing list or GitHub. + +Requirement changes + * When building with PSA drivers using generate_driver_wrappers.py, or + when building the library from the development branch rather than + from a release, the Python module jsonschema is now necessary, in + addition to jinja2. The official list of required Python modules is + maintained in scripts/basic.requirements.txt and may change again + in the future. + +New deprecations + * Deprecate mbedtls_asn1_free_named_data(). + Use mbedtls_asn1_free_named_data_list() + or mbedtls_asn1_free_named_data_list_shallow(). + +Features + * Support rsa_pss_rsae_* signature algorithms in TLS 1.2. + * make: enable building unversioned shared library, with e.g.: + "SHARED=1 SOEXT_TLS=so SOEXT_X509=so SOEXT_CRYPTO=so make lib" + resulting in library names like "libmbedtls.so" rather than + "libmbedcrypto.so.11". + * Expose the EC J-PAKE functionality through the Draft PSA PAKE Crypto API. + Only the ECC primitive with secp256r1 curve and SHA-256 hash algorithm + are supported in this implementation. + * Some modules can now use PSA drivers for hashes, including with no + built-in implementation present, but only in some configurations. + - RSA OAEP and PSS (PKCS#1 v2.1), PKCS5, PKCS12 and EC J-PAKE now use + hashes from PSA when (and only when) MBEDTLS_MD_C is disabled. + - PEM parsing of encrypted files now uses MD-5 from PSA when (and only + when) MBEDTLS_MD5_C is disabled. + See the documentation of the corresponding macros in mbedtls_config.h for + details. + Note that some modules are not able to use hashes from PSA yet, including + the entropy module. As a consequence, for now the only way to build with + all hashes only provided by drivers (no built-in hash) is to use + MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG. + * When MBEDTLS_USE_PSA_CRYPTO is enabled, X.509, TLS 1.2 and TLS 1.3 now + properly negotiate/accept hashes based on their availability in PSA. + As a consequence, they now work in configurations where the built-in + implementations of (some) hashes are excluded and those hashes are only + provided by PSA drivers. (See previous entry for limitation on RSA-PSS + though: that module only use hashes from PSA when MBEDTLS_MD_C is off). + * Add support for opaque keys as the private keys associated to certificates + for authentication in TLS 1.3. + * Add the LMS post-quantum-safe stateful-hash asymmetric signature scheme. + Signature verification is production-ready, but generation is for testing + purposes only. This currently only supports one parameter set + (LMS_SHA256_M32_H10), meaning that each private key can be used to sign + 1024 messages. As such, it is not intended for use in TLS, but instead + for verification of assets transmitted over an insecure channel, + particularly firmware images. + * Add the LM-OTS post-quantum-safe one-time signature scheme, which is + required for LMS. This can be used independently, but each key can only + be used to sign one message so is impractical for most circumstances. + * Mbed TLS now supports TLS 1.3 key establishment via pre-shared keys. + The pre-shared keys can be provisioned externally or via the ticket + mechanism (session resumption). + The ticket mechanism is supported when the configuration option + MBEDTLS_SSL_SESSION_TICKETS is enabled. + New options MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_xxx_ENABLED + control the support for the three possible TLS 1.3 key exchange modes. + * cert_write: support for setting extended key usage attributes. A + corresponding new public API call has been added in the library, + mbedtls_x509write_crt_set_ext_key_usage(). + * cert_write: support for writing certificate files in either PEM + or DER format. + * The PSA driver wrapper generator generate_driver_wrappers.py now + supports a subset of the driver description language, including + the following entry points: import_key, export_key, export_public_key, + get_builtin_key, copy_key. + * The new functions mbedtls_asn1_free_named_data_list() and + mbedtls_asn1_free_named_data_list_shallow() simplify the management + of memory in named data lists in X.509 structures. + * The TLS 1.2 EC J-PAKE key exchange can now use the PSA Crypto API. + Additional PSA key slots will be allocated in the process of such key + exchange for builds that enable MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED and + MBEDTLS_USE_PSA_CRYPTO. + * Add support for DTLS Connection ID as defined by RFC 9146, controlled by + MBEDTLS_SSL_DTLS_CONNECTION_ID (enabled by default) and configured with + mbedtls_ssl_set_cid(). + * Add a driver dispatch layer for raw key agreement, enabling alternative + implementations of raw key agreement through the key_agreement driver + entry point. This entry point is specified in the proposed PSA driver + interface, but had not yet been implemented. + * Add an ad-hoc key derivation function handling EC J-PAKE to PMS + calculation that can be used to derive the session secret in TLS 1.2, + as described in draft-cragie-tls-ecjpake-01. This can be achieved by + using PSA_ALG_TLS12_ECJPAKE_TO_PMS as the key derivation algorithm. + +Security + * Fix potential heap buffer overread and overwrite in DTLS if + MBEDTLS_SSL_DTLS_CONNECTION_ID is enabled and + MBEDTLS_SSL_CID_IN_LEN_MAX > 2 * MBEDTLS_SSL_CID_OUT_LEN_MAX. + * Fix an issue where 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 if the window size used + for the exponentiation was 3 or smaller. Found and reported by Zili KOU, + Wenjian HE, Sharad Sinha, and Wei ZHANG. See "Cache Side-channel Attacks + and Defenses of the Sliding Window Algorithm in TEEs" - Design, Automation + and Test in Europe 2023. + +Bugfix + * Refactor mbedtls_aes_context to support shallow-copying. Fixes #2147. + * Fix an issue with in-tree CMake builds in releases with GEN_FILES + turned off: if a shipped file was missing from the working directory, + it could be turned into a symbolic link to itself. + * Fix a long-standing build failure when building x86 PIC code with old + gcc (4.x). The code will be slower, but will compile. We do however + recommend upgrading to a more recent compiler instead. Fixes #1910. + * Fix support for little-endian Microblaze when MBEDTLS_HAVE_ASM is defined. + Contributed by Kazuyuki Kimura to fix #2020. + * Use double quotes to include private header file psa_crypto_cipher.h. + Fixes 'file not found with include' error + when building with Xcode. + * Fix handling of broken symlinks when loading certificates using + mbedtls_x509_crt_parse_path(). Instead of returning an error as soon as a + broken link is encountered, skip the broken link and continue parsing + other certificate files. Contributed by Eduardo Silva in #2602. + * Fix an interoperability failure between an Mbed TLS client with both + TLS 1.2 and TLS 1.3 support, and a TLS 1.2 server that supports + rsa_pss_rsae_* signature algorithms. This failed because Mbed TLS + advertised support for PSS in both TLS 1.2 and 1.3, but only + actually supported PSS in TLS 1.3. + * Fix a compilation error when using CMake with an IAR toolchain. + Fixes #5964. + * Fix a build error due to a missing prototype warning when + MBEDTLS_DEPRECATED_REMOVED is enabled. + * Fix mbedtls_ctr_drbg_free() on an initialized but unseeded context. When + MBEDTLS_AES_ALT is enabled, it could call mbedtls_aes_free() on an + uninitialized context. + * Fix a build issue on Windows using CMake where the source and build + directories could not be on different drives. Fixes #5751. + * Fix bugs and missing dependencies when building and testing + configurations with only one encryption type enabled in TLS 1.2. + * Provide the missing definition of mbedtls_setbuf() in some configurations + with MBEDTLS_PLATFORM_C disabled. Fixes #6118, #6196. + * Fix compilation errors when trying to build with + PSA drivers for AEAD (GCM, CCM, Chacha20-Poly1305). + * Fix memory leak in ssl_parse_certificate_request() caused by + mbedtls_x509_get_name() not freeing allocated objects in case of error. + Change mbedtls_x509_get_name() to clean up allocated objects on error. + * Fix build failure with MBEDTLS_RSA_C and MBEDTLS_PSA_CRYPTO_C but not + MBEDTLS_USE_PSA_CRYPTO or MBEDTLS_PK_WRITE_C. Fixes #6408. + * Fix build failure with MBEDTLS_RSA_C and MBEDTLS_PSA_CRYPTO_C but not + MBEDTLS_PK_PARSE_C. Fixes #6409. + * Fix ECDSA verification, where it was not always validating the + public key. This bug meant that it was possible to verify a + signature with an invalid public key, in some cases. Reported by + Guido Vranken using Cryptofuzz in #4420. + * Fix a possible null pointer dereference if a memory allocation fails + in TLS PRF code. Reported by Michael Madsen in #6516. + * Fix TLS 1.3 session resumption. Fixes #6488. + * Add a configuration check to exclude optional client authentication + in TLS 1.3 (where it is forbidden). + * Fix a bug in which mbedtls_x509_crt_info() would produce non-printable + bytes when parsing certificates containing a binary RFC 4108 + HardwareModuleName as a Subject Alternative Name extension. Hardware + serial numbers are now rendered in hex format. Fixes #6262. + * Fix bug in error reporting in dh_genprime.c where upon failure, + the error code returned by mbedtls_mpi_write_file() is overwritten + and therefore not printed. + * In the bignum module, operations of the form (-A) - (+A) or (-A) - (-A) + with A > 0 created an unintended representation of the value 0 which was + not processed correctly by some bignum operations. Fix this. This had no + consequence on cryptography code, but might affect applications that call + bignum directly and use negative numbers. + * Fix a bug whereby the list of signature algorithms sent as part of + the TLS 1.2 server certificate request would get corrupted, meaning the + first algorithm would not get sent and an entry consisting of two random + bytes would be sent instead. Found by Serban Bejan and Dudek Sebastian. + * Fix undefined behavior (typically harmless in practice) of + mbedtls_mpi_add_mpi(), mbedtls_mpi_add_abs() and mbedtls_mpi_add_int() + when both operands are 0 and the left operand is represented with 0 limbs. + * Fix undefined behavior (typically harmless in practice) when some bignum + functions receive the most negative value of mbedtls_mpi_sint. Credit + to OSS-Fuzz. Fixes #6597. + * Fix undefined behavior (typically harmless in practice) in PSA ECB + encryption and decryption. + * Move some SSL-specific code out of libmbedcrypto where it had been placed + accidentally. + * Fix a build error when compiling the bignum module for some Arm platforms. + Fixes #6089, #6124, #6217. + +Changes + * Add the ability to query PSA_WANT_xxx macros to query_compile_time_config. + * Calling AEAD tag-specific functions for non-AEAD algorithms (which + should not be done - they are documented for use only by AES-GCM and + ChaCha20+Poly1305) now returns MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE + instead of success (0). + += Mbed TLS 3.2.1 branch released 2022-07-12 + +Bugfix + * Re-add missing generated file library/psa_crypto_driver_wrappers.c + += Mbed TLS 3.2.0 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. + +Requirement changes + * The library will no longer compile out of the box on a platform without + setbuf(). If your platform does not have setbuf(), you can configure an + alternative function by enabling MBEDTLS_PLATFORM_SETBUF_ALT or + MBEDTLS_PLATFORM_SETBUF_MACRO. + +New deprecations + * Deprecate mbedtls_ssl_conf_max_version() and + mbedtls_ssl_conf_min_version() in favor of + mbedtls_ssl_conf_max_tls_version() and + mbedtls_ssl_conf_min_tls_version(). + * Deprecate mbedtls_cipher_setup_psa(). Use psa_aead_xxx() or + psa_cipher_xxx() directly instead. + * Secure element drivers enabled by MBEDTLS_PSA_CRYPTO_SE_C are deprecated. + This was intended as an experimental feature, but had not been explicitly + documented as such. Use opaque drivers with the interface enabled by + MBEDTLS_PSA_CRYPTO_DRIVERS instead. + * Deprecate mbedtls_ssl_conf_sig_hashes() in favor of the more generic + mbedtls_ssl_conf_sig_algs(). Signature algorithms for the TLS 1.2 and + TLS 1.3 handshake should now be configured with + mbedtls_ssl_conf_sig_algs(). + +Features + * Add accessor to obtain ciphersuite id from ssl context. + * Add accessors to get members from ciphersuite info. + * Add mbedtls_ssl_ticket_rotate() for external ticket rotation. + * Add accessor to get the raw buffer pointer from a PEM context. + * The structures mbedtls_ssl_config and mbedtls_ssl_context now store + a piece of user data which is reserved for the application. The user + data can be either a pointer or an integer. + * Add an accessor function to get the configuration associated with + an SSL context. + * Add a function to access the protocol version from an SSL context in a + form that's easy to compare. Fixes #5407. + * Add function mbedtls_md_info_from_ctx() to recall the message digest + information that was used to set up a message digest context. + * Add ALPN support in TLS 1.3 clients. + * Add server certificate selection callback near end of Client Hello. + Register callback with mbedtls_ssl_conf_cert_cb(). + * Provide mechanism to reset handshake cert list by calling + mbedtls_ssl_set_hs_own_cert() with NULL value for own_cert param. + * Add accessor mbedtls_ssl_get_hs_sni() to retrieve SNI from within + cert callback (mbedtls_ssl_conf_cert_cb()) during handshake. + * The X.509 module now uses PSA hash acceleration if present. + * Add support for psa crypto key derivation for elliptic curve + keys. Fixes #3260. + * Add function mbedtls_timing_get_final_delay() to access the private + final delay field in an mbedtls_timing_delay_context, as requested in + #5183. + * Add mbedtls_pk_sign_ext() which allows generating RSA-PSS signatures when + PSA Crypto is enabled. + * Add function mbedtls_ecp_export() to export ECP key pair parameters. + Fixes #4838. + * Add function mbedtls_ssl_is_handshake_over() to enable querying if the SSL + Handshake has completed or not, and thus whether to continue calling + mbedtls_ssl_handshake_step(), requested in #4383. + * Add the function mbedtls_ssl_get_own_cid() to access our own connection id + within mbedtls_ssl_context, as requested in #5184. + * Introduce mbedtls_ssl_hs_cb_t typedef for use with + mbedtls_ssl_conf_cert_cb() and perhaps future callbacks + during TLS handshake. + * Add functions mbedtls_ssl_conf_max_tls_version() and + mbedtls_ssl_conf_min_tls_version() that use a single value to specify + the protocol version. + * Extend the existing PSA_ALG_TLS12_PSK_TO_MS() algorithm to support + mixed-PSK. Add an optional input PSA_KEY_DERIVATION_INPUT_OTHER_SECRET + holding the other secret. + * 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. + * Add the function mbedtls_x509_crt_has_ext_type() to access the ext types + field within mbedtls_x509_crt context, as requested in #5585. + * Add HKDF-Expand and HKDF-Extract as separate algorithms in the PSA API. + * Add support for the ARMv8 SHA-2 acceleration instructions when building + for Aarch64. + * Add support for authentication of TLS 1.3 clients by TLS 1.3 servers. + * Add support for server HelloRetryRequest message. The TLS 1.3 client is + now capable of negotiating another shared secret if the one sent in its + first ClientHello was not suitable to the server. + * Add support for client-side TLS version negotiation. If both TLS 1.2 and + TLS 1.3 protocols are enabled in the build of Mbed TLS, the TLS client now + negotiates TLS 1.3 or TLS 1.2 with TLS servers. + * Enable building of Mbed TLS with TLS 1.3 protocol support but without TLS + 1.2 protocol support. + * Mbed TLS provides an implementation of a TLS 1.3 server (ephemeral key + establishment only). See docs/architecture/tls13-support.md for a + description of the support. The MBEDTLS_SSL_PROTO_TLS1_3 and + MBEDTLS_SSL_SRV_C configuration options control this. + * Add accessors to configure DN hints for certificate request: + mbedtls_ssl_conf_dn_hints() and mbedtls_ssl_set_hs_dn_hints() + * The configuration option MBEDTLS_USE_PSA_CRYPTO, which previously + affected only a limited subset of crypto operations in TLS, X.509 and PK, + now causes most of them to be done using PSA Crypto; see + docs/use-psa-crypto.md for the list of exceptions. + * The function mbedtls_pk_setup_opaque() now supports RSA key pairs as well. + Opaque keys can now be used everywhere a private key is expected in the + TLS and X.509 modules. + * Opaque pre-shared keys for TLS, provisioned with + mbedtls_ssl_conf_psk_opaque() or mbedtls_ssl_set_hs_psk_opaque(), which + previously only worked for "pure" PSK key exchange, now can also be used + for the "mixed" PSK key exchanges as well: ECDHE-PSK, DHE-PSK, RSA-PSK. + * cmake now detects if it is being built as a sub-project, and in that case + disables the target export/installation and package configuration. + * Make USE_PSA_CRYPTO compatible with KEY_ID_ENCODES_OWNER. Fixes #5259. + * Add example programs cipher_aead_demo.c, md_hmac_demo.c, aead_demo.c + and hmac_demo.c, which use PSA and the md/cipher interfaces side + by side in order to illustrate how the operation is performed in PSA. + Addresses #5208. + +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 potential memory leak inside mbedtls_ssl_cache_set() with + an invalid session id length. + * Add the platform function mbedtls_setbuf() to allow buffering to be + disabled on stdio files, to stop secrets loaded from said files being + potentially left in memory after file operations. Reported by + Glenn Strauss. + * 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. + * Fix a buffer overread in TLS 1.3 Certificate parsing. An unauthenticated + client or server could cause an MbedTLS server or client to overread up + to 64 kBytes of data and potentially overread the input buffer by that + amount minus the size of the input buffer. As overread data undergoes + various checks, the likelihood of reaching the boundary of the input + buffer is rather small but increases as its size + MBEDTLS_SSL_IN_CONTENT_LEN decreases. + * Fix check of certificate key usage in TLS 1.3. The usage of the public key + provided by a client or server certificate for authentication was not + checked properly when validating the certificate. This could cause a + client or server to be able to authenticate itself through a certificate + to an Mbed TLS TLS 1.3 server or client while it does not own a proper + certificate to do so. + +Bugfix + * Declare or use PSA_WANT_ALG_CCM_STAR_NO_TAG following the general + pattern for PSA_WANT_xxx symbols. Previously you had to specify + PSA_WANT_ALG_CCM for PSA_ALG_CCM_STAR_NO_TAG. + * Fix a memory leak if mbedtls_ssl_config_defaults() is called twice. + * Fixed swap of client and server random bytes when exporting them alongside + TLS 1.3 handshake and application traffic secret. + * 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. + * The TLS 1.3 implementation is now compatible with the + MBEDTLS_USE_PSA_CRYPTO configuration option. + * Fix unit tests that used 0 as the file UID. This failed on some + implementations of PSA ITS. Fixes #3838. + * Fix mbedtls_ssl_get_version() not reporting TLSv1.3. Fixes #5406. + * 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 a race condition in out-of-source builds with CMake when generated data + files are already present. Fixes #5374. + * 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 not + MBEDTLS_DEBUG_C, DTLS handshakes using CID would crash due to a null + pointer dereference. Fix this. Fixes #3998. + The fix was released, but not announced, in Mbed TLS 3.1.0. + * 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 undefined behavior in mbedtls_asn1_find_named_data(), where val is + not NULL and val_len is zero. + * Fix compilation error with mingw32. Fixed by Cameron Cawley in #4211. + * Fix compilation error when using C++ Builder on Windows. Reported by + Miroslav Mastny in #4015. + * 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. + * Fix a TLS 1.3 handshake failure when the peer Finished message has not + been received yet when we first try to fetch it. + * Encode X.509 dates before 1/1/2000 as UTCTime rather than + GeneralizedTime. Fixes #5465. + * Add mbedtls_x509_dn_get_next function to return the next relative DN in + an X509 name, to allow walking the name list. Fixes #5431. + * 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 check_config.h to check that we have MBEDTLS_SSL_KEEP_PEER_CERTIFICATE + when MBEDTLS_SSL_PROTO_TLS1_3 is specified, and make this and other + dependencies explicit in the documentation. Fixes #5610. + * Fix mbedtls_asn1_write_mpi() writing an incorrect encoding of 0. + * Fix a TLS 1.3 handshake failure when the first attempt to send the client + Finished message on the network cannot be satisfied. Fixes #5499. + * 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. + * Fix MBEDTLS_SVC_KEY_ID_GET_KEY_ID() and MBEDTLS_SVC_KEY_ID_GET_OWNER_ID() + which have been broken, resulting in compilation errors, since Mbed TLS + 3.0. + * Ensure that TLS 1.2 ciphersuite/certificate and key selection takes into + account not just the type of the key (RSA vs EC) but also what it can + actually do. Resolves #5831. + * Fix CMake windows host detection, especially when cross compiling. + * Fix an error in make where the absence of a generated file caused + make to break on a clean checkout. Fixes #5340. + * Work around an MSVC ARM64 compiler bug causing incorrect behaviour + in mbedtls_mpi_exp_mod(). Reported by Tautvydas Žilys in #5467. + * Removed the prompt to exit from all windows build programs, which was causing + issues in CI/CD environments. + +Changes + * The file library/psa_crypto_driver_wrappers.c is now generated + from a template. In the future, the generation will support + driver descriptions. For the time being, to customize this file, + see docs/proposed/psa-driver-wrappers-codegen-migration-guide.md + * Return PSA_ERROR_INVALID_ARGUMENT if the algorithm passed to one-shot + AEAD functions is not an AEAD algorithm. This aligns them with the + multipart functions, and the PSA Crypto API 1.1 specification. + * In mbedtls_pk_parse_key(), if no password is provided, don't allocate a + temporary variable on the heap. Suggested by Sergey Kanatov in #5304. + * Assume source files are in UTF-8 when using MSVC with CMake. + * Fix runtime library install location when building with CMake and MinGW. + DLLs are now installed in the bin directory instead of lib. + * cmake: Use GnuInstallDirs to customize install directories + Replace custom LIB_INSTALL_DIR variable with standard CMAKE_INSTALL_LIBDIR + variable. For backward compatibility, set CMAKE_INSTALL_LIBDIR if + LIB_INSTALL_DIR is set. + * Add a CMake option that enables static linking of the runtime library + in Microsoft Visual C++ compiler. Contributed by Microplankton. + * In CMake builds, add aliases for libraries so that the normal MbedTLS::* + targets work when MbedTLS is built as a subdirectory. This allows the + use of FetchContent, as requested in #5688. + += mbed TLS 3.1.0 branch released 2021-12-17 + +API changes + * New error code for GCM: MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL. + Alternative GCM implementations are expected to verify + the length of the provided output buffers and to return the + MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL in case the buffer length is too small. + * You can configure groups for a TLS key exchange with the new function + mbedtls_ssl_conf_groups(). It extends mbedtls_ssl_conf_curves(). + * Declare a number of structure fields as public: the fields of + mbedtls_ecp_curve_info, the fields describing the result of ASN.1 and + X.509 parsing, and finally the field fd of mbedtls_net_context on + POSIX/Unix-like platforms. + +Requirement changes + * Sign-magnitude and one's complement representations for signed integers are + not supported. Two's complement is the only supported representation. + +New deprecations + * Deprecate mbedtls_ssl_conf_curves() in favor of the more generic + mbedtls_ssl_conf_groups(). + +Removals + * Remove the partial support for running unit tests via Greentea on Mbed OS, + which had been unmaintained since 2018. + +Features + * Enable support for Curve448 via the PSA API. Contributed by + Archana Madhavan in #4626. Fixes #3399 and #4249. + * The identifier of the CID TLS extension can be configured by defining + MBEDTLS_TLS_EXT_CID at compile time. + * Implement the PSA multipart AEAD interface, currently supporting + ChaChaPoly and GCM. + * 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 support for CCM*-no-tag cipher to the PSA. + Currently only 13-byte long IV's are supported. + For decryption a minimum of 16-byte long input is expected. + These restrictions may be subject to change. + * Add new API mbedtls_ct_memcmp for constant time buffer comparison. + * Add functions to get the IV and block size from cipher_info structs. + * Add functions to check if a cipher supports variable IV or key size. + * Add the internal implementation of and support for CCM to the PSA multipart + AEAD interface. + * Mbed TLS provides a minimum viable implementation of the TLS 1.3 + protocol. See docs/architecture/tls13-support.md for the definition of + the TLS 1.3 Minimum Viable Product (MVP). The MBEDTLS_SSL_PROTO_TLS1_3 + configuration option controls the enablement of the support. The APIs + mbedtls_ssl_conf_min_version() and mbedtls_ssl_conf_max_version() allow + to select the 1.3 version of the protocol to establish a TLS connection. + * 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_aead_generate_nonce(), 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. + * 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 compile-time or run-time errors in PSA + AEAD functions when ChachaPoly is disabled. Fixes #5065. + * Remove PSA'a AEAD finish/verify output buffer limitation for GCM. + The requirement of minimum 15 bytes for output buffer in + psa_aead_finish() and psa_aead_verify() does not apply to the built-in + implementation of GCM. + * Move GCM's update output buffer length verification from PSA AEAD to + the built-in implementation of the GCM. + The requirement for output buffer size to be equal or greater then + input buffer size is valid only for the built-in implementation of GCM. + Alternative GCM implementations can process whole blocks only. + * 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 + * Explicitly mark the fields mbedtls_ssl_session.exported and + mbedtls_ssl_config.respect_cli_pref as private. This was an + oversight during the run-up to the release of Mbed TLS 3.0. + The fields were never intended to be public. + * Implement multi-part CCM API. + The multi-part functions: mbedtls_ccm_starts(), mbedtls_ccm_set_lengths(), + mbedtls_ccm_update_ad(), mbedtls_ccm_update(), mbedtls_ccm_finish() + were introduced in mbedTLS 3.0 release, however their implementation was + postponed until now. + Implemented functions support chunked data input for both CCM and CCM* + algorithms. + * Remove MBEDTLS_SSL_EXPORT_KEYS, making it always on and increasing the + code size by about 80B on an M0 build. This option only gated an ability + to set a callback, but was deemed unnecessary as it was yet another define + to remember when writing tests, or test configurations. Fixes #4653. + * 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. + * Ignore plaintext/ciphertext lengths for CCM*-no-tag operations. + For CCM* encryption/decryption without authentication, input + length will be ignored. + * 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. + * The generated configuration-independent files are now automatically + generated by the CMake build system on Unix-like systems. This is not + yet supported when cross-compiling. + += Mbed TLS 3.0.0 branch released 2021-07-07 + +API changes + * Remove HAVEGE module. + The design of HAVEGE makes it unsuitable for microcontrollers. Platforms + with a more complex CPU usually have an operating system interface that + provides better randomness. Instead of HAVEGE, declare OS or hardware RNG + interfaces with mbedtls_entropy_add_source() and/or use an entropy seed + file created securely during device provisioning. See + https://mbed-tls.readthedocs.io/en/latest/kb/how-to/add-entropy-sources-to-entropy-pool/ for + more information. + * Add missing const attributes to API functions. + * Remove helpers for the transition from Mbed TLS 1.3 to Mbed TLS 2.0: the + header compat-1.3.h and the script rename.pl. + * Remove certs module from the API. + Transfer keys and certificates embedded in the library to the test + component. This contributes to minimizing library API and discourages + users from using unsafe keys in production. + * Move alt helpers and definitions. + Various helpers and definitions available for use in alt implementations + have been moved out of the include/ directory and into the library/ + directory. The files concerned are ecp_internal.h and rsa_internal.h + which have also been renamed to ecp_internal_alt.h and rsa_alt_helpers.h + respectively. + * Move internal headers. + Header files that were only meant for the library's internal use and + were not meant to be used in application code have been moved out of + the include/ directory. The headers concerned are bn_mul.h, aesni.h, + padlock.h, entropy_poll.h and *_internal.h. + * Drop support for parsing SSLv2 ClientHello + (MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO). + * Drop support for SSLv3 (MBEDTLS_SSL_PROTO_SSL3). + * Drop support for TLS record-level compression (MBEDTLS_ZLIB_SUPPORT). + * Drop support for RC4 TLS ciphersuites. + * Drop support for single-DES ciphersuites. + * Drop support for MBEDTLS_SSL_HW_RECORD_ACCEL. + * 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. + * Add configuration option MBEDTLS_X509_REMOVE_INFO which + removes the mbedtls_x509_*_info(), mbedtls_debug_print_crt() + as well as other functions and constants only used by + those functions. This reduces the code footprint by + several kB. + * Remove SSL error codes `MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED` + and `MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH` which are never + returned from the public SSL API. + * Remove `MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE` and return + `MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL` instead. + * The output parameter of mbedtls_sha512_finish, mbedtls_sha512, + mbedtls_sha256_finish and mbedtls_sha256 now has a pointer type + rather than array type. This removes spurious warnings in some compilers + when outputting a SHA-384 or SHA-224 hash into a buffer of exactly + the hash size. + * Remove the MBEDTLS_TEST_NULL_ENTROPY config option. Fixes #4388. + * The interface of the GCM module has changed to remove restrictions on + how the input to multipart operations is broken down. mbedtls_gcm_finish() + now takes extra output parameters for the last partial output block. + mbedtls_gcm_update() now takes extra parameters for the output length. + The software implementation always produces the full output at each + call to mbedtls_gcm_update(), but alternative implementations activated + by MBEDTLS_GCM_ALT may delay partial blocks to the next call to + mbedtls_gcm_update() or mbedtls_gcm_finish(). Furthermore, applications + no longer pass the associated data to mbedtls_gcm_starts(), but to the + new function mbedtls_gcm_update_ad(). + These changes are backward compatible for users of the cipher API. + * Replace MBEDTLS_SHA512_NO_SHA384 config option with MBEDTLS_SHA384_C. + This separates config option enabling the SHA384 algorithm from option + enabling the SHA512 algorithm. Fixes #4034. + * Introduce MBEDTLS_SHA224_C. + This separates config option enabling the SHA224 algorithm from option + enabling SHA256. + * The getter and setter API of the SSL session cache (used for + session-ID based session resumption) has changed to that of + a key-value store with keys being session IDs and values + being opaque instances of `mbedtls_ssl_session`. + * Remove the mode parameter from RSA operation functions. Signature and + decryption functions now always use the private key and verification and + encryption use the public key. Verification functions also no longer have + RNG parameters. + * Modify semantics of `mbedtls_ssl_conf_[opaque_]psk()`: + In Mbed TLS 2.X, the API prescribes that later calls overwrite + the effect of earlier calls. In Mbed TLS 3.0, calling + `mbedtls_ssl_conf_[opaque_]psk()` more than once will fail, + leaving the PSK that was configured first intact. + Support for more than one PSK may be added in 3.X. + * The function mbedtls_x509write_csr_set_extension() has an extra parameter + which allows to mark an extension as critical. Fixes #4055. + * For multi-part AEAD operations with the cipher module, calling + mbedtls_cipher_finish() is now mandatory. Previously the documentation + was unclear on this point, and this function happened to never do + anything with the currently implemented AEADs, so in practice it was + possible to skip calling it, which is no longer supported. + * The option MBEDTLS_ECP_FIXED_POINT_OPTIM use pre-computed comb tables + instead of computing tables in runtime. Thus, this option now increase + code size, and it does not increase RAM usage in runtime anymore. + * Remove the SSL APIs mbedtls_ssl_get_input_max_frag_len() and + mbedtls_ssl_get_output_max_frag_len(), and add a new API + mbedtls_ssl_get_max_in_record_payload(), complementing the existing + mbedtls_ssl_get_max_out_record_payload(). + Uses of mbedtls_ssl_get_input_max_frag_len() and + mbedtls_ssl_get_input_max_frag_len() should be replaced by + mbedtls_ssl_get_max_in_record_payload() and + mbedtls_ssl_get_max_out_record_payload(), respectively. + * mbedtls_rsa_init() now always selects the PKCS#1v1.5 encoding for an RSA + key. To use an RSA key with PSS or OAEP, call mbedtls_rsa_set_padding() + after initializing the context. mbedtls_rsa_set_padding() now returns an + error if its parameters are invalid. + * Replace MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE by a runtime + configuration function mbedtls_ssl_conf_preference_order(). Fixes #4398. + * Instead of accessing the len field of a DHM context, which is no longer + supported, use the new function mbedtls_dhm_get_len() . + * In modules that implement cryptographic hash functions, many functions + mbedtls_xxx() now return int instead of void, and the corresponding + function mbedtls_xxx_ret() which was identical except for returning int + has been removed. This also concerns mbedtls_xxx_drbg_update(). See the + migration guide for more information. Fixes #4212. + * For all functions that take a random number generator (RNG) as a + parameter, this parameter is now mandatory (that is, NULL is not an + acceptable value). Functions which previously accepted NULL and now + reject it are: the X.509 CRT and CSR writing functions; the PK and RSA + sign and decrypt function; mbedtls_rsa_private(); the functions + in DHM and ECDH that compute the shared secret; the scalar multiplication + functions in ECP. + * The following functions now require an RNG parameter: + mbedtls_ecp_check_pub_priv(), mbedtls_pk_check_pair(), + mbedtls_pk_parse_key(), mbedtls_pk_parse_keyfile(). + * mbedtls_ssl_conf_export_keys_ext_cb() and + mbedtls_ssl_conf_export_keys_cb() have been removed and + replaced by a new API mbedtls_ssl_set_export_keys_cb(). + Raw keys and IVs are no longer passed to the callback. + Further, callbacks now receive an additional parameter + indicating the type of secret that's being exported, + paving the way for the larger number of secrets + in TLS 1.3. Finally, the key export callback and + context are now connection-specific. + * Signature functions in the RSA and PK modules now require the hash + length parameter to be the size of the hash input. For RSA signatures + other than raw PKCS#1 v1.5, this must match the output size of the + specified hash algorithm. + * The functions mbedtls_pk_sign(), mbedtls_pk_sign_restartable(), + mbedtls_ecdsa_write_signature() and + mbedtls_ecdsa_write_signature_restartable() now take an extra parameter + indicating the size of the output buffer for the signature. + * Implement one-shot cipher functions, psa_cipher_encrypt and + psa_cipher_decrypt, according to the PSA Crypto API 1.0.0 + specification. + * Direct access to fields of structures declared in public headers is no + longer supported except for fields that are documented public. Use accessor + functions instead. For more information, see the migration guide entry + "Most structure fields are now private". + * mbedtls_ssl_get_session_pointer() has been removed, and + mbedtls_ssl_{set,get}_session() may now only be called once for any given + SSL context. + +Default behavior changes + * Enable by default the functionalities which have no reason to be disabled. + They are: ARIA block cipher, CMAC mode, elliptic curve J-PAKE library and + Key Wrapping mode as defined in NIST SP 800-38F. Fixes #4036. + * Some default policies for X.509 certificate verification and TLS have + changed: curves and hashes weaker than 255 bits are no longer accepted + by default. The default order in TLS now favors faster curves over larger + curves. + +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. + * If you build the development version of Mbed TLS, rather than an official + release, some configuration-independent files are now generated at build + time rather than checked into source control. This includes some library + source files as well as the Visual Studio solution. Perl, Python 3 and a + C compiler for the host platform are required. See “Generated source files + in the development branch†in README.md for more information. + * Refresh the minimum supported versions of tools to build the + library. CMake versions older than 3.10.2 and Python older + than 3.6 are no longer supported. + +Removals + * Remove the MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES + compile-time option, which was off by default. Users should not trust + certificates signed with SHA-1 due to the known attacks against SHA-1. + If needed, SHA-1 certificates can still be verified by using a custom + verification profile. + * Removed deprecated things in psa/crypto_compat.h. Fixes #4284 + * Removed deprecated functions from hashing modules. Fixes #4280. + * Remove PKCS#11 library wrapper. PKCS#11 has limited functionality, + lacks automated tests and has scarce documentation. Also, PSA Crypto + provides a more flexible private key management. + More details on PCKS#11 wrapper removal can be found in the mailing list + https://lists.trustedfirmware.org/pipermail/mbed-tls/2020-April/000024.html + * Remove deprecated error codes. Fix #4283 + * Remove MBEDTLS_ENABLE_WEAK_CIPHERSUITES configuration option. Fixes #4416. + * Remove the MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES + compile-time option. This option has been inactive for a long time. + Please use the `lifetime` parameter of `mbedtls_ssl_ticket_setup()` + instead. + * Remove the following deprecated functions and constants of hex-encoded + primes based on RFC 5114 and RFC 3526 from library code and tests: + mbedtls_aes_encrypt(), mbedtls_aes_decrypt(), mbedtls_mpi_is_prime(), + mbedtls_cipher_auth_encrypt(), mbedtls_cipher_auth_decrypt(), + mbedtls_ctr_drbg_update(), mbedtls_hmac_drbg_update(), + mbedtls_ecdsa_write_signature_det(), mbedtls_ecdsa_sign_det(), + mbedtls_ssl_conf_dh_param(), mbedtls_ssl_get_max_frag_len(), + MBEDTLS_DHM_RFC5114_MODP_2048_P, MBEDTLS_DHM_RFC5114_MODP_2048_G, + MBEDTLS_DHM_RFC3526_MODP_2048_P, MBEDTLS_DHM_RFC3526_MODP_2048_G, + MBEDTLS_DHM_RFC3526_MODP_3072_P, MBEDTLS_DHM_RFC3526_MODP_3072_G, + MBEDTLS_DHM_RFC3526_MODP_4096_P, MBEDTLS_DHM_RFC3526_MODP_4096_G. + Remove the deprecated file: include/mbedtls/net.h. Fixes #4282. + * Remove MBEDTLS_SSL_MAX_CONTENT_LEN configuration option, since + MBEDTLS_SSL_IN_CONTENT_LEN and MBEDTLS_SSL_OUT_CONTENT_LEN replace + it. Fixes #4362. + * Remove the MBEDTLS_SSL_RECORD_CHECKING option and enable by default its + previous action. Fixes #4361. + * Remove support for TLS 1.0, TLS 1.1 and DTLS 1.0, as well as support for + CBC record splitting, fallback SCSV, and the ability to configure + ciphersuites per version, which are no longer relevant. This removes the + configuration options MBEDTLS_SSL_PROTO_TLS1, + MBEDTLS_SSL_PROTO_TLS1_1, MBEDTLS_SSL_CBC_RECORD_SPLITTING and + MBEDTLS_SSL_FALLBACK_SCSV as well as the functions + mbedtls_ssl_conf_cbc_record_splitting(), + mbedtls_ssl_get_key_exchange_md_ssl_tls(), mbedtls_ssl_conf_fallback(), + and mbedtls_ssl_conf_ciphersuites_for_version(). Fixes #4286. + * The RSA module no longer supports private-key operations with the public + key and vice versa. + * Remove the MBEDTLS_SSL_DTLS_BADMAC_LIMIT config.h option. Fixes #4403. + * Remove all the 3DES ciphersuites: + MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA. Remove the + MBEDTLS_REMOVE_3DES_CIPHERSUITES option which is no longer relevant. + Fixes #4367. + * Remove the MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 option and let the code + behave as if it was always disabled. Fixes #4386. + * Remove MBEDTLS_ECDH_LEGACY_CONTEXT config option since this was purely for + backward compatibility which is no longer supported. Addresses #4404. + * Remove the following macros: MBEDTLS_CHECK_PARAMS, + MBEDTLS_CHECK_PARAMS_ASSERT, MBEDTLS_PARAM_FAILED, + MBEDTLS_PARAM_FAILED_ALT. Fixes #4313. + * Remove the MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION config.h + option. The mbedtls_x509_crt_parse_der_with_ext_cb() is the way to go for + migration path. Fixes #4378. + * Remove the MBEDTLS_X509_CHECK_KEY_USAGE and + MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE config.h options and let the code + behave as if they were always enabled. Fixes #4405. + * MBEDTLS_ECP_MAX_BITS is no longer a configuration option because it is + now determined automatically based on supported curves. + * Remove the following functions: mbedtls_timing_self_test(), + mbedtls_hardclock_poll(), mbedtls_timing_hardclock() and + mbedtls_set_alarm(). Fixes #4083. + * The configuration option MBEDTLS_ECP_NO_INTERNAL_RNG has been removed as + it no longer had any effect. + * Remove all support for MD2, MD4, RC4, Blowfish and XTEA. This removes the + corresponding modules and all their APIs and related configuration + options. Fixes #4084. + * Remove MBEDTLS_SSL_TRUNCATED_HMAC and also remove + MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT config option. Users are better served by + using a CCM-8 ciphersuite than a CBC ciphersuite with truncated HMAC. + See issue #4341 for more details. + * Remove the compile-time option + MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE. + +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 multi-part GCM interface (mbedtls_gcm_update() or + mbedtls_cipher_update()) no longer requires the size of partial inputs to + be a multiple of 16. + * The multi-part GCM interface now supports chunked associated data through + multiple calls to mbedtls_gcm_update_ad(). + * The new function mbedtls_mpi_random() generates a random value in a + given range uniformly. + * Alternative implementations of the AES, DHM, ECJPAKE, ECP, RSA and timing + modules had undocumented constraints on their context types. These + constraints have been relaxed. + See docs/architecture/alternative-implementations.md for the remaining + constraints. + * The new functions mbedtls_dhm_get_len() and mbedtls_dhm_get_bitlen() + query the size of the modulus in a Diffie-Hellman context. + * The new function mbedtls_dhm_get_value() copy a field out of a + Diffie-Hellman context. + * Use the new function mbedtls_ecjpake_set_point_format() to select the + point format for ECJPAKE instead of accessing the point_format field + directly, which is no longer supported. + * Implement psa_mac_compute() and psa_mac_verify() as defined in the + PSA Cryptograpy API 1.0.0 specification. + +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. + * Fix an issue where 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. + * Fix an issue where 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 + * Fix premature fopen() call in mbedtls_entropy_write_seed_file which may + lead to the seed file corruption in case if the path to the seed file is + equal to MBEDTLS_PLATFORM_STD_NV_SEED_FILE. Contributed by Victor + Krasnoshchok in #3616. + * 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. + * Add printf function attributes to mbedtls_debug_print_msg to ensure we + get printf format specifier warnings. + * 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. + * Fix a bug in ECDSA that would cause it to fail when the hash is all-bits + zero. Fixes #1792 + * 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 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. + * 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. + * 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. + * 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. + * 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 + * Fix the setting of the read timeout in the DTLS sample programs. + * Add extra printf compiler warning flags to builds. + * Fix memsan build false positive in x509_crt.c with clang 11 + * Alternative implementations of CMAC may now opt to not support 3DES as a + CMAC block cipher, and still pass the CMAC self test. + * Remove the AES sample application programs/aes/aescrypt2 which shows + bad cryptographic practice. Fix #1906. + * Remove configs/config-psa-crypto.h, which no longer had any intended + differences from the default configuration, but had accidentally diverged. + * When building the test suites with GNU make, invoke python3 or python, not + python2, which is no longer supported upstream. + * 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. + * Replace MBEDTLS_SSL_CID_PADDING_GRANULARITY and + MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY with a new single unified option + MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY. Fixes #4335. + * 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. + * Add CMake package config generation for CMake projects consuming Mbed TLS. + * config.h has been split into build_info.h and mbedtls_config.h + build_info.h is intended to be included from C code directly, while + mbedtls_config.h is intended to be edited by end users wishing to + change the build configuration, and should generally only be included from + build_info.h. + * The handling of MBEDTLS_CONFIG_FILE has been moved into build_info.h. + * A config file version symbol, MBEDTLS_CONFIG_VERSION was introduced. + Defining it to a particular value will ensure that Mbed TLS interprets + the config file in a way that's compatible with the config file format + used by the Mbed TLS release whose MBEDTLS_VERSION_NUMBER has the same + value. + The only value supported by Mbed TLS 3.0.0 is 0x03000000. + * Various changes to which alert and/or error code may be returned + * during the TLS handshake. + * 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 nonzero) 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..288e692 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/README.md @@ -0,0 +1,320 @@ +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/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 +------------- + +The main Mbed TLS documentation is available via [ReadTheDocs](https://mbed-tls.readthedocs.io/). + +Documentation for the PSA Cryptography API is available [on GitHub](https://arm-software.github.io/psa-api/crypto/). + +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. +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 + +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 3.82 or a build tool that CMake supports. +* A C99 toolchain (compiler, linker, archiver). We actively test with GCC 5.4, Clang 3.8, IAR 8 and Visual Studio 2013. More recent versions should work. Slightly older versions may work. +* Python 3.6 to generate the test code, and to generate sample programs in the development branch. +* Perl to run the tests, and to generate some source files in the development branch. +* CMake 3.10.2 or later (if using CMake). +* Microsoft Visual Studio 2013 or later (if using Visual Studio). +* Doxygen 1.8.11 or later (if building the documentation; slightly older versions should work). + +### Generated source files in the development branch + +The source code of Mbed TLS includes some files that are automatically generated by scripts and whose content depends only on the Mbed TLS source, not on the platform or on the library configuration. These files are not included in the development branch of Mbed TLS, but the generated files are included in official releases. This section explains how to generate the missing files in the development branch. + +The following tools are required: + +* Perl, for some library source files and for Visual Studio build files. +* Python 3 and some Python packages, for some library source files, sample programs and test data. To install the necessary packages, run: + ``` + python3 -m pip install --user -r scripts/basic.requirements.txt + ``` + Depending on your Python installation, you may need to invoke `python` instead of `python3`. To install the packages system-wide, omit the `--user` option. +* A C compiler for the host platform, for some test data. + +If you are cross-compiling, you must set the `CC` environment variable to a C compiler for the host platform when generating the configuration-independent files. + +Any of the following methods are available to generate the configuration-independent files: + +* If not cross-compiling, running `make` with any target, or just `make`, will automatically generate required files. +* On non-Windows systems, when not cross-compiling, CMake will generate the required files automatically. +* Run `make generated_files` to generate all the configuration-independent files. +* On Unix/POSIX systems, run `tests/scripts/check-generated-files.sh -u` to generate all the configuration-independent files. +* On Windows, run `scripts\make_generated_files.bat` to generate all the configuration-independent files. + +### 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://mbed-tls.readthedocs.io/en/latest/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://mbed-tls.readthedocs.io/en/latest/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. + +#### Consuming Mbed TLS + +Mbed TLS provides a package config file for consumption as a dependency in other +CMake projects. You can include Mbed TLS's CMake targets yourself with: + + find_package(MbedTLS) + +If prompted, set `MbedTLS_DIR` to `${YOUR_MBEDTLS_INSTALL_DIR}/cmake`. This +creates the following targets: + +- `MbedTLS::mbedcrypto` (Crypto library) +- `MbedTLS::mbedtls` (TLS library) +- `MbedTLS::mbedx509` (X509 library) + +You can then use these directly through `target_link_libraries()`: + + add_executable(xyz) + + target_link_libraries(xyz + PUBLIC MbedTLS::mbedtls + MbedTLS::mbedcrypto + MbedTLS::mbedx509) + +This will link the Mbed TLS libraries to your library or application, and add +its include directories to your target (transitively, in the case of `PUBLIC` or +`INTERFACE` link libraries). + +#### 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 2013. + +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. + +In the development branch of Mbed TLS, the Visual Studio solution files need to be generated first as described in [“Generated source files in the development branchâ€](#generated-source-files-in-the-development-branch). + +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/depends.py` test builds in configurations with a single curve, key exchange, hash, cipher, or pkalg on. +- `tests/scripts/all.sh` runs a combination of the above tests, plus some more, with various build options (such as ASan, full `mbedtls_config.h`, etc). + +Instead of manually installing the required versions of all tools required for testing, it is possible to use the Docker images from our CI systems, as explained in [our testing infrastructure repository](https://github.com/Mbed-TLS/mbedtls-test/blob/master/README.md#quick-start). + +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://mbed-tls.readthedocs.io/en/latest/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS/) +- [What external dependencies does Mbed TLS rely on?](https://mbed-tls.readthedocs.io/en/latest/kb/development/what-external-dependencies-does-mbedtls-rely-on/) +- [How do I configure Mbed TLS](https://mbed-tls.readthedocs.io/en/latest/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. +- Mixed-endian platforms are not supported. +- SIZE_MAX must be at least as big as INT_MAX and UINT_MAX. + +PSA cryptography API +-------------------- + +### PSA API + +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://arm-software.github.io/psa-api/crypto/) 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 implementation in Mbed TLS + +Mbed TLS includes a reference implementation of the PSA Cryptography API. +However, it does not aim to implement the whole specification; in particular it does not implement all the algorithms. + +The X.509 and TLS code can use PSA cryptography for most operations. To enable this support, activate the compilation option `MBEDTLS_USE_PSA_CRYPTO` in `mbedtls_config.h`. Note that TLS 1.3 uses PSA cryptography for most operations regardless of this option. See `docs/use-psa-crypto.md` for details. + +### 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..61e3936 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/SECURITY.md @@ -0,0 +1,137 @@ +## Reporting Vulnerabilities + +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. + +## Threat model + +We classify attacks based on the capabilities of the attacker. + +### Remote attacks + +In this section, we consider an attacker who can observe and modify data sent +over the network. This includes observing the content and timing of individual +packets, as well as suppressing or delaying legitimate messages, and injecting +messages. + +Mbed TLS aims to fully protect against remote attacks and to enable the user +application in providing full protection against remote attacks. Said +protection is limited to providing security guarantees offered by the protocol +being implemented. (For example Mbed TLS alone won't guarantee that the +messages will arrive without delay, as the TLS protocol doesn't guarantee that +either.) + +**Warning!** Block ciphers do not yet achieve full protection against attackers +who can measure the timing of packets with sufficient precision. For details +and workarounds see the [Block Ciphers](#block-ciphers) section. + +### Local attacks + +In this section, we consider an attacker who can run software on the same +machine. The attacker has insufficient privileges to directly access Mbed TLS +assets such as memory and files. + +#### Timing attacks + +The attacker is able to observe the timing of instructions executed by Mbed TLS +by leveraging shared hardware that both Mbed TLS and the attacker have access +to. Typical attack vectors include cache timings, memory bus contention and +branch prediction. + +Mbed TLS provides limited protection against timing attacks. The cost of +protecting against timing attacks widely varies depending on the granularity of +the measurements and the noise present. Therefore the protection in Mbed TLS is +limited. We are only aiming to provide protection against **publicly +documented attack techniques**. + +As attacks keep improving, so does Mbed TLS's protection. Mbed TLS is moving +towards a model of fully timing-invariant code, but has not reached this point +yet. + +**Remark:** Timing information can be observed over the network or through +physical side channels as well. Remote and physical timing attacks are covered +in the [Remote attacks](remote-attacks) and [Physical +attacks](physical-attacks) sections respectively. + +**Warning!** Block ciphers do not yet achieve full protection. For +details and workarounds see the [Block Ciphers](#block-ciphers) section. + +#### Local non-timing side channels + +The attacker code running on the platform has access to some sensor capable of +picking up information on the physical state of the hardware while Mbed TLS is +running. This could for example be an analogue-to-digital converter on the +platform that is located unfortunately enough to pick up the CPU noise. + +Mbed TLS doesn't make any security guarantees against local non-timing-based +side channel attacks. If local non-timing attacks are present in a use case or +a user application's threat model, they need to be mitigated by the platform. + +#### Local fault injection attacks + +Software running on the same hardware can affect the physical state of the +device and introduce faults. + +Mbed TLS doesn't make any security guarantees against local fault injection +attacks. If local fault injection attacks are present in a use case or a user +application's threat model, they need to be mitigated by the platform. + +### Physical attacks + +In this section, we consider an attacker who has access to physical information +about the hardware Mbed TLS is running on and/or can alter the physical state +of the hardware (e.g. power analysis, radio emissions or fault injection). + +Mbed TLS doesn't make any security guarantees against physical attacks. If +physical attacks are present in a use case or a user application's threat +model, they need to be mitigated by physical countermeasures. + +### Caveats + +#### Out-of-scope countermeasures + +Mbed TLS has evolved organically and a well defined threat model hasn't always +been present. Therefore, Mbed TLS might have countermeasures against attacks +outside the above defined threat model. + +The presence of such countermeasures don't mean that Mbed TLS provides +protection against a class of attacks outside of the above described threat +model. Neither does it mean that the failure of such a countermeasure is +considered a vulnerability. + +#### Block ciphers + +Currently there are four block ciphers in Mbed TLS: AES, CAMELLIA, ARIA and +DES. The pure software implementation in Mbed TLS implementation uses lookup +tables, which are vulnerable to timing attacks. + +These timing attacks can be physical, local or depending on network latency +even a remote. The attacks can result in key recovery. + +**Workarounds:** + +- Turn on hardware acceleration for AES. This is supported only on selected + architectures and currently only available for AES. See configuration options + `MBEDTLS_AESCE_C`, `MBEDTLS_AESNI_C` and `MBEDTLS_PADLOCK_C` for details. +- Add a secure alternative implementation (typically hardware acceleration) for + the vulnerable cipher. See the [Alternative Implementations +Guide](docs/architecture/alternative-implementations.md) for more information. +- Use cryptographic mechanisms that are not based on block ciphers. In + particular, for authenticated encryption, use ChaCha20/Poly1305 instead of + block cipher modes. For random generation, use HMAC\_DRBG instead of CTR\_DRBG. 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..b550e08 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/SUPPORT.md @@ -0,0 +1,16 @@ +## Documentation + +Here are some useful sources of information about using Mbed TLS: + +- [ReadTheDocs](https://mbed-tls.readthedocs.io/); +- API documentation, see the [Documentation section of the + README](README.md#documentation); +- the `docs` directory in the source tree; +- the [Mbed TLS Knowledge Base](https://mbed-tls.readthedocs.io/en/latest/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..42e1fe8 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/aes.h @@ -0,0 +1,634 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" +#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 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_AES_ALT) +// Regular implementation +// + +/** + * \brief The AES context-type definition. + */ +typedef struct mbedtls_aes_context { + int MBEDTLS_PRIVATE(nr); /*!< The number of rounds. */ + size_t MBEDTLS_PRIVATE(rk_offset); /*!< The offset in array elements to AES + round keys in the buffer. */ + uint32_t MBEDTLS_PRIVATE(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 MBEDTLS_PRIVATE(crypt); /*!< The AES context to use for AES block + encryption or decryption. */ + mbedtls_aes_context MBEDTLS_PRIVATE(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_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/aria.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/aria.h new file mode 100644 index 0000000..587cbf8 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/aria.h @@ -0,0 +1,357 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#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. */ + +/** Bad input data. */ +#define MBEDTLS_ERR_ARIA_BAD_INPUT_DATA -0x005C + +/** Invalid data input length. */ +#define MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH -0x005E + +#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 MBEDTLS_PRIVATE(nr); /*!< The number of rounds (12, 14 or 16) */ + /*! The ARIA round keys. */ + uint32_t MBEDTLS_PRIVATE(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..e15aeb3 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/asn1.h @@ -0,0 +1,649 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_BIGNUM_C) +#include "mbedtls/bignum.h" +#endif + +/** + * \addtogroup asn1_module + * \{ + */ + +/** + * \name ASN1 Error codes + * These error codes are combined with other error codes for + * higher error granularity. + * e.g. X.509 and PKCS #7 error codes + * 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. */ + + /** The next entry in the sequence. + * + * The details of memory management for sequences are not documented and + * may change in future versions. Set this field to \p NULL when + * initializing a structure, and do not modify it except via Mbed TLS + * library functions. + */ + struct mbedtls_asn1_sequence *next; +} +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. */ + + /** The next entry in the sequence. + * + * The details of memory management for named data sequences are not + * documented and may change in future versions. Set this field to \p NULL + * when initializing a structure, and do not modify it except via Mbed TLS + * library functions. + */ + struct mbedtls_asn1_named_data *next; + + /** Merge next item into the current one? + * + * This field exists for the sake of Mbed TLS's X.509 certificate parsing + * code and may change in future versions of the library. + */ + unsigned char MBEDTLS_PRIVATE(next_merged); +} +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. + */ +const mbedtls_asn1_named_data *mbedtls_asn1_find_named_data(const mbedtls_asn1_named_data *list, + const char *oid, size_t len); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +/** + * \brief Free a mbedtls_asn1_named_data entry + * + * \deprecated This function is deprecated and will be removed in a + * future version of the library. + * Please use mbedtls_asn1_free_named_data_list() + * or mbedtls_asn1_free_named_data_list_shallow(). + * + * \param entry The named data entry to free. + * This function calls mbedtls_free() on + * `entry->oid.p` and `entry->val.p`. + */ +void MBEDTLS_DEPRECATED mbedtls_asn1_free_named_data(mbedtls_asn1_named_data *entry); +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \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_free() on + * `entry->oid.p` and `entry->val.p` and then on `entry` + * for each list entry, and sets \c *head to \c NULL. + */ +void mbedtls_asn1_free_named_data_list(mbedtls_asn1_named_data **head); + +/** + * \brief Free all shallow entries in a mbedtls_asn1_named_data list, + * but do not free internal pointer targets. + * + * \param name Head of the list of named data entries to free. + * This function calls mbedtls_free() on each list element. + */ +void mbedtls_asn1_free_named_data_list_shallow(mbedtls_asn1_named_data *name); + +/** \} 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..da73759 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/asn1write.h @@ -0,0 +1,375 @@ +/** + * \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 + +#include "mbedtls/build_info.h" + +#include "mbedtls/asn1.h" + +#define MBEDTLS_ASN1_CHK_ADD(g, f) \ + do \ + { \ + if ((ret = (f)) < 0) \ + return ret; \ + else \ + (g) += ret; \ + } while (0) + +#define MBEDTLS_ASN1_CHK_CLEANUP_ADD(g, f) \ + do \ + { \ + if ((ret = (f)) < 0) \ + goto cleanup; \ + 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, const 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, const 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, const unsigned char *start, + const unsigned char *buf, size_t size); + +#if defined(MBEDTLS_BIGNUM_C) +/** + * \brief Write an 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, const 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, const 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, const 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, + const 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, const 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, const 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, const 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, const 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, + const 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, const 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, const 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, const 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, + const 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, const 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 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..635be71 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/base64.h @@ -0,0 +1,94 @@ +/** + * \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 + +#include "mbedtls/build_info.h" + +#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..56c289a --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/bignum.h @@ -0,0 +1,1106 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#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: 2 + * 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 2 /**< 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 */ + +/** \typedef mbedtls_mpi_uint + * \brief The type of machine digits in a bignum, called _limbs_. + * + * This is always an unsigned integer type with no padding bits. The size + * is platform-dependent. + */ + +/** \typedef mbedtls_mpi_sint + * \brief The signed type corresponding to #mbedtls_mpi_uint. + * + * This is always an signed integer type with no padding bits. The size + * is platform-dependent. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MPI structure + */ +typedef struct mbedtls_mpi { + /** Sign: -1 if the mpi is negative, 1 otherwise. + * + * The number 0 must be represented with `s = +1`. Although many library + * functions treat all-limbs-zero as equivalent to a valid representation + * of 0 regardless of the sign bit, there are exceptions, so bignum + * functions and external callers must always set \c s to +1 for the + * number zero. + * + * Note that this implies that calloc() or `... = {0}` does not create + * a valid MPI representation. You must call mbedtls_mpi_init(). + */ + int MBEDTLS_PRIVATE(s); + + /** Total number of limbs in \c p. */ + size_t MBEDTLS_PRIVATE(n); + + /** Pointer to limbs. + * + * This may be \c NULL if \c n is 0. + */ + mbedtls_mpi_uint *MBEDTLS_PRIVATE(p); + + short use_mempool; +} +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. Must be either 0 or 1: + * * \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). + * + * \warning If \p assign is neither 0 nor 1, the result of this function + * is indeterminate, and the resulting value in \p X might be + * neither its original value nor the value in \p Y. + * + * \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 swap The condition deciding whether to perform + * the swap or not. Must be either 0 or 1: + * * \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( swap ) mbedtls_mpi_swap( X, Y ); + * except that it avoids leaking any information about whether + * the swap was done or not (the above code may leak + * information through branch prediction and/or memory access + * patterns analysis). + * + * \warning If \p swap is neither 0 nor 1, the result of this function + * is indeterminate, and both \p X and \p Y might end up with + * values different to either of the original ones. + * + * \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 swap); + +/** + * \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. This must not alias A or B. + * \param R The destination MPI for the remainder value. + * This may be \c NULL if the value of the + * remainder is not needed. This must not alias A or B. + * \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. This must not alias A. + * \param R The destination MPI for the remainder value. + * This may be \c NULL if the value of the + * remainder is not needed. This must not alias A. + * \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. + * This must not alias E or N. + * \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); + +/** + * \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, + 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, 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/build_info.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/build_info.h new file mode 100644 index 0000000..1b3d59f --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/build_info.h @@ -0,0 +1,153 @@ +/** + * \file build_info.h + * + * \brief Build-time configuration info + * + * Include this file if you need to depend on the + * configuration options defined in mbedtls_config.h or MBEDTLS_CONFIG_FILE + */ +/* + * 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_BUILD_INFO_H +#define MBEDTLS_BUILD_INFO_H + +/* + * This set of compile-time defines can be used to determine the version number + * of the Mbed TLS library used. Run-time variables for the same can be found in + * version.h + */ + +/** + * The version number x.y.z is split into three parts. + * Major, Minor, Patchlevel + */ +#define MBEDTLS_VERSION_MAJOR 3 +#define MBEDTLS_VERSION_MINOR 4 +#define MBEDTLS_VERSION_PATCH 0 + +/** + * The single version number has the following structure: + * MMNNPP00 + * Major version | Minor version | Patch version + */ +#define MBEDTLS_VERSION_NUMBER 0x03040000 +#define MBEDTLS_VERSION_STRING "3.4.0" +#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 3.4.0" + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif + +/* Define `inline` on some non-C99-compliant compilers. */ +#if (defined(__ARMCC_VERSION) || defined(_MSC_VER)) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/mbedtls_config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_CONFIG_VERSION) && ( \ + MBEDTLS_CONFIG_VERSION < 0x03000000 || \ + MBEDTLS_CONFIG_VERSION > MBEDTLS_VERSION_NUMBER) +#error "Invalid config version, defined value of MBEDTLS_CONFIG_VERSION is unsupported" +#endif + +/* Target and application specific configurations + * + * Allow user to override any previous default. + * + */ +#if defined(MBEDTLS_USER_CONFIG_FILE) +#include MBEDTLS_USER_CONFIG_FILE +#endif + +/* Auto-enable MBEDTLS_MD_LIGHT based on MBEDTLS_MD_C. + * This allows checking for MD_LIGHT rather than MD_LIGHT || MD_C. + */ +#if defined(MBEDTLS_MD_C) +#define MBEDTLS_MD_LIGHT +#endif + +/* Auto-enable MBEDTLS_MD_LIGHT if some module needs it. + */ +#if defined(MBEDTLS_PEM_PARSE_C) || \ + defined(MBEDTLS_RSA_C) +#define MBEDTLS_MD_LIGHT +#endif + +/* If MBEDTLS_PSA_CRYPTO_C is defined, make sure MBEDTLS_PSA_CRYPTO_CLIENT + * is defined as well to include all PSA code. + */ +#if defined(MBEDTLS_PSA_CRYPTO_C) +#define MBEDTLS_PSA_CRYPTO_CLIENT +#endif /* MBEDTLS_PSA_CRYPTO_C */ + +/* The PK wrappers need pk_write functions to format RSA key objects + * when they are dispatching to the PSA API. This happens under USE_PSA_CRYPTO, + * and also even without USE_PSA_CRYPTO for mbedtls_pk_sign_ext(). */ +#if defined(MBEDTLS_PSA_CRYPTO_C) && defined(MBEDTLS_RSA_C) +#define MBEDTLS_PK_C +#define MBEDTLS_PK_WRITE_C +#define MBEDTLS_PK_PARSE_C +#endif + +#if !defined(MBEDTLS_SSL_PROTO_TLS1_2) +#undef MBEDTLS_KEY_EXCHANGE_RSA_ENABLED +#undef MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED +#undef MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED +#undef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +#undef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED +#undef MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED +#undef MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED +#undef MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED +#undef MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED +#undef MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED +#undef MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED +#endif + +#if !defined(MBEDTLS_SSL_PROTO_TLS1_3) +#undef MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED +#undef MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED +#undef MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED +#undef MBEDTLS_SSL_EARLY_DATA +#endif + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED) || \ + defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED) +#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED +#endif + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) || \ + defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED) +#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED +#endif + +/* Make sure all configuration symbols are set before including check_config.h, + * even the ones that are calculated programmatically. */ +#if defined(MBEDTLS_PSA_CRYPTO_CONFIG) /* PSA_WANT_xxx influences MBEDTLS_xxx */ || \ + defined(MBEDTLS_PSA_CRYPTO_C) /* MBEDTLS_xxx influences PSA_WANT_xxx */ +#include "mbedtls/config_psa.h" +#endif + +#include "mbedtls/check_config.h" + +#endif /* MBEDTLS_BUILD_INFO_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..f4aa002 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/camellia.h @@ -0,0 +1,315 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include +#include + +#include "mbedtls/platform_util.h" + +#define MBEDTLS_CAMELLIA_ENCRYPT 1 +#define MBEDTLS_CAMELLIA_DECRYPT 0 + +/** Bad input data. */ +#define MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA -0x0024 + +/** Invalid data input length. */ +#define MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH -0x0026 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_CAMELLIA_ALT) +// Regular implementation +// + +/** + * \brief CAMELLIA context structure + */ +typedef struct mbedtls_camellia_context { + int MBEDTLS_PRIVATE(nr); /*!< number of rounds */ + uint32_t MBEDTLS_PRIVATE(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..6c22552 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ccm.h @@ -0,0 +1,531 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include "mbedtls/cipher.h" + +#define MBEDTLS_CCM_DECRYPT 0 +#define MBEDTLS_CCM_ENCRYPT 1 +#define MBEDTLS_CCM_STAR_DECRYPT 2 +#define MBEDTLS_CCM_STAR_ENCRYPT 3 + +/** Bad input parameters to the function. */ +#define MBEDTLS_ERR_CCM_BAD_INPUT -0x000D +/** Authenticated decryption failed. */ +#define MBEDTLS_ERR_CCM_AUTH_FAILED -0x000F + +#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 { + unsigned char MBEDTLS_PRIVATE(y)[16]; /*!< The Y working buffer */ + unsigned char MBEDTLS_PRIVATE(ctr)[16]; /*!< The counter buffer */ + mbedtls_cipher_context_t MBEDTLS_PRIVATE(cipher_ctx); /*!< The cipher context used. */ + size_t MBEDTLS_PRIVATE(plaintext_len); /*!< Total plaintext length */ + size_t MBEDTLS_PRIVATE(add_len); /*!< Total authentication data length */ + size_t MBEDTLS_PRIVATE(tag_len); /*!< Total tag length */ + size_t MBEDTLS_PRIVATE(processed); /*!< Track how many bytes of input data + were processed (chunked input). + Used independently for both auth data + and plaintext/ciphertext. + This variable is set to zero after + auth data input is finished. */ + unsigned char MBEDTLS_PRIVATE(q); /*!< The Q working value */ + unsigned char MBEDTLS_PRIVATE(mode); /*!< The operation to perform: + #MBEDTLS_CCM_ENCRYPT or + #MBEDTLS_CCM_DECRYPT or + #MBEDTLS_CCM_STAR_ENCRYPT or + #MBEDTLS_CCM_STAR_DECRYPT. */ + int MBEDTLS_PRIVATE(state); /*!< Working value holding context's + state. Used for chunked data + input */ +} +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 ad The additional data field. If \p ad_len is greater than + * zero, \p ad must be a readable buffer of at least that + * length. + * \param ad_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 *ad, size_t ad_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. + * For tag length = 0, input length is ignored. + * \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 ad The additional data field. This must be a readable buffer of + * at least \p ad_len Bytes. + * \param ad_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 *ad, size_t ad_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 ad The additional data field. This must be a readable buffer + * of at least that \p ad_len Bytes.. + * \param ad_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 *ad, size_t ad_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. + * For tag length = 0, input length is ignored. + * \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 ad The additional data field. This must be a readable buffer of + * at least that \p ad_len Bytes. + * \param ad_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 *ad, size_t ad_len, + const unsigned char *input, unsigned char *output, + const unsigned char *tag, size_t tag_len); + +/** + * \brief This function starts a CCM encryption or decryption + * operation. + * + * This function and mbedtls_ccm_set_lengths() must be called + * before calling mbedtls_ccm_update_ad() or + * mbedtls_ccm_update(). This function can be called before + * or after mbedtls_ccm_set_lengths(). + * + * \note This function is not implemented in Mbed TLS yet. + * + * \param ctx The CCM context. This must be initialized. + * \param mode The operation to perform: #MBEDTLS_CCM_ENCRYPT or + * #MBEDTLS_CCM_DECRYPT or #MBEDTLS_CCM_STAR_ENCRYPT or + * #MBEDTLS_CCM_STAR_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 nonce in Bytes: 7, 8, 9, 10, 11, 12, + * or 13. The length L of the message length field is + * 15 - \p iv_len. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CCM_BAD_INPUT on failure: + * \p ctx is in an invalid state, + * \p mode is invalid, + * \p iv_len is invalid (lower than \c 7 or greater than + * \c 13). + */ +int mbedtls_ccm_starts(mbedtls_ccm_context *ctx, + int mode, + const unsigned char *iv, + size_t iv_len); + +/** + * \brief This function declares the lengths of the message + * and additional data for a CCM encryption or decryption + * operation. + * + * This function and mbedtls_ccm_starts() must be called + * before calling mbedtls_ccm_update_ad() or + * mbedtls_ccm_update(). This function can be called before + * or after mbedtls_ccm_starts(). + * + * \note This function is not implemented in Mbed TLS yet. + * + * \param ctx The CCM context. This must be initialized. + * \param total_ad_len The total length of additional data in bytes. + * This must be less than `2^16 - 2^8`. + * \param plaintext_len The length in bytes of the plaintext to encrypt or + * result of the decryption (thus not encompassing the + * additional data that are not encrypted). + * \param tag_len The length of the tag to generate in Bytes: + * 4, 6, 8, 10, 12, 14 or 16. + * For CCM*, zero is also valid. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CCM_BAD_INPUT on failure: + * \p ctx is in an invalid state, + * \p total_ad_len is greater than \c 0xFF00. + */ +int mbedtls_ccm_set_lengths(mbedtls_ccm_context *ctx, + size_t total_ad_len, + size_t plaintext_len, + size_t tag_len); + +/** + * \brief This function feeds an input buffer as associated data + * (authenticated but not encrypted data) in a CCM + * encryption or decryption operation. + * + * You may call this function zero, one or more times + * to pass successive parts of the additional data. The + * lengths \p ad_len of the data parts should eventually add + * up exactly to the total length of additional data + * \c total_ad_len passed to mbedtls_ccm_set_lengths(). You + * may not call this function after calling + * mbedtls_ccm_update(). + * + * \note This function is not implemented in Mbed TLS yet. + * + * \param ctx The CCM context. This must have been started with + * mbedtls_ccm_starts(), the lengths of the message and + * additional data must have been declared with + * mbedtls_ccm_set_lengths() and this must not have yet + * received any input with mbedtls_ccm_update(). + * \param ad The buffer holding the additional data, or \c NULL + * if \p ad_len is \c 0. + * \param ad_len The length of the additional data. If \c 0, + * \p ad may be \c NULL. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CCM_BAD_INPUT on failure: + * \p ctx is in an invalid state, + * total input length too long. + */ +int mbedtls_ccm_update_ad(mbedtls_ccm_context *ctx, + const unsigned char *ad, + size_t ad_len); + +/** + * \brief This function feeds an input buffer into an ongoing CCM + * encryption or decryption operation. + * + * You may call this function zero, one or more times + * to pass successive parts of the input: the plaintext to + * encrypt, or the ciphertext (not including the tag) to + * decrypt. After the last part of the input, call + * mbedtls_ccm_finish(). The lengths \p input_len of the + * data parts should eventually add up exactly to the + * plaintext length \c plaintext_len passed to + * mbedtls_ccm_set_lengths(). + * + * This function may produce output in one of the following + * ways: + * - Immediate output: the output length is always equal + * to the input length. + * - Buffered output: except for the last part of input data, + * the output consists of a whole number of 16-byte blocks. + * If the total input length so far (not including + * associated data) is 16 \* *B* + *A* with *A* < 16 then + * the total output length is 16 \* *B*. + * For the last part of input data, the output length is + * equal to the input length plus the number of bytes (*A*) + * buffered in the previous call to the function (if any). + * The function uses the plaintext length + * \c plaintext_len passed to mbedtls_ccm_set_lengths() + * to detect the last part of input data. + * + * In particular: + * - It is always correct to call this function with + * \p output_size >= \p input_len + 15. + * - If \p input_len is a multiple of 16 for all the calls + * to this function during an operation (not necessary for + * the last one) then it is correct to use \p output_size + * =\p input_len. + * + * \note This function is not implemented in Mbed TLS yet. + * + * \param ctx The CCM context. This must have been started with + * mbedtls_ccm_starts() and the lengths of the message and + * additional data must have been declared with + * mbedtls_ccm_set_lengths(). + * \param input The buffer holding the input data. If \p input_len + * is greater than zero, this must be a readable buffer + * of at least \p input_len bytes. + * \param input_len The length of the input data in bytes. + * \param output The buffer for the output data. If \p output_size + * is greater than zero, this must be a writable buffer of + * at least \p output_size bytes. + * \param output_size The size of the output buffer in bytes. + * See the function description regarding the output size. + * \param output_len On success, \p *output_len contains the actual + * length of the output written in \p output. + * On failure, the content of \p *output_len is + * unspecified. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CCM_BAD_INPUT on failure: + * \p ctx is in an invalid state, + * total input length too long, + * or \p output_size too small. + */ +int mbedtls_ccm_update(mbedtls_ccm_context *ctx, + const unsigned char *input, size_t input_len, + unsigned char *output, size_t output_size, + size_t *output_len); + +/** + * \brief This function finishes the CCM operation and generates + * the authentication tag. + * + * It wraps up the CCM stream, and generates the + * tag. The tag can have a maximum length of 16 Bytes. + * + * \note This function is not implemented in Mbed TLS yet. + * + * \param ctx The CCM context. This must have been started with + * mbedtls_ccm_starts() and the lengths of the message and + * additional data must have been declared with + * mbedtls_ccm_set_lengths(). + * \param tag The buffer for holding the tag. If \p tag_len is greater + * than zero, this must be a writable buffer of at least \p + * tag_len Bytes. + * \param tag_len The length of the tag. Must match the tag length passed to + * mbedtls_ccm_set_lengths() function. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CCM_BAD_INPUT on failure: + * \p ctx is in an invalid state, + * invalid value of \p tag_len, + * the total amount of additional data passed to + * mbedtls_ccm_update_ad() was lower than the total length of + * additional data \c total_ad_len passed to + * mbedtls_ccm_set_lengths(), + * the total amount of input data passed to + * mbedtls_ccm_update() was lower than the plaintext length + * \c plaintext_len passed to mbedtls_ccm_set_lengths(). + */ +int mbedtls_ccm_finish(mbedtls_ccm_context *ctx, + 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/chacha20.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/chacha20.h new file mode 100644 index 0000000..e24e56b --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/chacha20.h @@ -0,0 +1,214 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include +#include + +/** Invalid input parameter(s). */ +#define MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA -0x0051 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_CHACHA20_ALT) + +typedef struct mbedtls_chacha20_context { + uint32_t MBEDTLS_PRIVATE(state)[16]; /*! The state (before round operations). */ + uint8_t MBEDTLS_PRIVATE(keystream8)[64]; /*! Leftover keystream bytes. */ + size_t MBEDTLS_PRIVATE(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..19baade --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/chachapoly.h @@ -0,0 +1,354 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +/* 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 MBEDTLS_PRIVATE(chacha20_ctx); /**< The ChaCha20 context. */ + mbedtls_poly1305_context MBEDTLS_PRIVATE(poly1305_ctx); /**< The Poly1305 context. */ + uint64_t MBEDTLS_PRIVATE(aad_len); /**< The length (bytes) of the Additional Authenticated Data. */ + uint64_t MBEDTLS_PRIVATE(ciphertext_len); /**< The length (bytes) of the ciphertext. */ + int MBEDTLS_PRIVATE(state); /**< The current state of the context. */ + mbedtls_chachapoly_mode_t MBEDTLS_PRIVATE(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..bd683dd --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/check_config.h @@ -0,0 +1,1108 @@ +/** + * \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. + */ + +#ifndef MBEDTLS_CHECK_CONFIG_H +#define MBEDTLS_CHECK_CONFIG_H + +/* *INDENT-OFF* */ +/* + * 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 + +#include + +#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 mbedtls_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(__aarch64__) && defined(__GNUC__) +/* We don't do anything with MBEDTLS_AESCE_C on systems without ^ these two */ +#if defined(MBEDTLS_AESCE_C) && !defined(MBEDTLS_HAVE_ASM) +#error "MBEDTLS_AESCE_C defined, but not all prerequisites" +#endif +#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_CMAC_C) && \ + ( !defined(MBEDTLS_CIPHER_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) || defined(MBEDTLS_PSA_CRYPTO_C) ) ) +#error "MBEDTLS_ECJPAKE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) && \ + ( 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 ECP implementation" +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) && \ + !defined(MBEDTLS_ECP_C) +#error "MBEDTLS_ECP_RESTARTABLE defined, but not all prerequisites" +#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_PK_PARSE_C) && !defined(MBEDTLS_ASN1_PARSE_C) +#error "MBEDTLS_PK_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PKCS12_C) && !defined(MBEDTLS_CIPHER_C) +#error "MBEDTLS_PKCS12_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PKCS5_C) && \ + ( !( defined(MBEDTLS_MD_C) || defined(MBEDTLS_PSA_CRYPTO_C) ) || \ + !defined(MBEDTLS_CIPHER_C) ) +#error "MBEDTLS_PKCS5_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PKCS12_C) && \ + !( defined(MBEDTLS_MD_C) || defined(MBEDTLS_PSA_CRYPTO_C) ) +#error "MBEDTLS_PKCS12_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PKCS1_V21) && \ + !( defined(MBEDTLS_MD_C) || defined(MBEDTLS_PSA_CRYPTO_C) ) +#error "MBEDTLS_PKCS1_V21 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_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_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 + +/* Helper for ECDSA dependencies, will be undefined at the end of the file */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(PSA_HAVE_FULL_ECDSA) +#define MBEDTLS_PK_HAVE_ECDSA +#endif +#else /* MBEDTLS_USE_PSA_CRYPTO */ +#if defined(MBEDTLS_ECDSA_C) +#define MBEDTLS_PK_HAVE_ECDSA +#endif +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +/* Helper for JPAKE dependencies, will be undefined at the end of the file */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(PSA_HAVE_FULL_JPAKE) +#define MBEDTLS_PK_HAVE_JPAKE +#endif +#else /* MBEDTLS_USE_PSA_CRYPTO */ +#if defined(MBEDTLS_ECJPAKE_C) +#define MBEDTLS_PK_HAVE_JPAKE +#endif +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || \ + !defined(MBEDTLS_PK_HAVE_ECDSA) || \ + !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_PK_HAVE_ECDSA) || \ + !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_PK_HAVE_JPAKE) || \ + !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ) +#error "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites" +#endif + +/* Use of EC J-PAKE in TLS requires SHA-256. + * This will be taken from MD if it is present, or from PSA if MD is absent. + * Note: MBEDTLS_ECJPAKE_C depends on MBEDTLS_MD_C || MBEDTLS_PSA_CRYPTO_C. */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ + !( defined(MBEDTLS_MD_C) && defined(MBEDTLS_SHA256_C) ) && \ + !( !defined(MBEDTLS_MD_C) && defined(PSA_WANT_ALG_SHA_256) ) +#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_MD_C) && !( \ + defined(MBEDTLS_MD5_C) || \ + defined(MBEDTLS_RIPEMD160_C) || \ + defined(MBEDTLS_SHA1_C) || \ + defined(MBEDTLS_SHA224_C) || \ + defined(MBEDTLS_SHA256_C) || \ + defined(MBEDTLS_SHA384_C) || \ + defined(MBEDTLS_SHA512_C) ) +#error "MBEDTLS_MD_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_LMS_C) && \ + ! ( defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_ALG_SHA_256) ) +#error "MBEDTLS_LMS_C requires MBEDTLS_PSA_CRYPTO_C and PSA_WANT_ALG_SHA_256" +#endif + +#if defined(MBEDTLS_LMS_PRIVATE) && \ + ( !defined(MBEDTLS_LMS_C) ) +#error "MBEDTLS_LMS_PRIVATE requires MBEDTLS_LMS_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_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_SETBUF_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_SETBUF_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_SETBUF_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_SETBUF_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_SETBUF_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_SETBUF) ||\ + defined(MBEDTLS_PLATFORM_SETBUF_ALT) ) +#error "MBEDTLS_PLATFORM_SETBUF_MACRO and MBEDTLS_PLATFORM_STD_SETBUF/MBEDTLS_PLATFORM_SETBUF_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_VSNPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_VSNPRINTF_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_VSNPRINTF_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_VSNPRINTF) ||\ + defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) ) +#error "MBEDTLS_PLATFORM_VSNPRINTF_MACRO and MBEDTLS_PLATFORM_STD_VSNPRINTF/MBEDTLS_PLATFORM_VSNPRINTF_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_C) && !defined(MBEDTLS_CIPHER_C ) +#error "MBEDTLS_PSA_CRYPTO_C defined, but not all prerequisites" +#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_SE_C) +#if defined(MBEDTLS_DEPRECATED_REMOVED) +#error "MBEDTLS_PSA_CRYPTO_SE_C is deprecated and will be removed in a future version of Mbed TLS" +#elif defined(MBEDTLS_DEPRECATED_WARNING) +#warning "MBEDTLS_PSA_CRYPTO_SE_C is deprecated and will be removed in a future version of Mbed TLS" +#endif +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + +#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_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_USE_A64_CRYPTO_IF_PRESENT) && \ + defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) +#error "Must only define one of MBEDTLS_SHA512_USE_A64_CRYPTO_*" +#endif + +#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) || \ + defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) +#if !defined(MBEDTLS_SHA512_C) +#error "MBEDTLS_SHA512_USE_A64_CRYPTO_* defined without MBEDTLS_SHA512_C" +#endif +#if defined(MBEDTLS_SHA512_ALT) || defined(MBEDTLS_SHA512_PROCESS_ALT) +#error "MBEDTLS_SHA512_*ALT can't be used with MBEDTLS_SHA512_USE_A64_CRYPTO_*" +#endif + +#endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT || MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */ + +#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) && !defined(__aarch64__) +#error "MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY defined on non-Aarch64 system" +#endif + +#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT) && \ + defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY) +#error "Must only define one of MBEDTLS_SHA256_USE_A64_CRYPTO_*" +#endif + +#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT) || \ + defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY) +#if !defined(MBEDTLS_SHA256_C) +#error "MBEDTLS_SHA256_USE_A64_CRYPTO_* defined without MBEDTLS_SHA256_C" +#endif +#if defined(MBEDTLS_SHA256_ALT) || defined(MBEDTLS_SHA256_PROCESS_ALT) +#error "MBEDTLS_SHA256_*ALT can't be used with MBEDTLS_SHA256_USE_A64_CRYPTO_*" +#endif + +#endif + +#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY) && \ + !defined(__aarch64__) && !defined(_M_ARM64) +#error "MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY defined on non-Aarch64 system" +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && !defined(MBEDTLS_USE_PSA_CRYPTO) && \ + !( defined(MBEDTLS_SHA1_C) || defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA512_C) ) +#error "MBEDTLS_SSL_PROTO_TLS1_2 defined, but not all prerequisites" +#endif + +/* TLS 1.3 requires separate HKDF parts from PSA */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ + !( defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_ALG_HKDF_EXTRACT) && defined(PSA_WANT_ALG_HKDF_EXPAND) ) +#error "MBEDTLS_SSL_PROTO_TLS1_3 defined, but not all prerequisites" +#endif + +/* TLS 1.3 requires at least one ciphersuite, so at least SHA-256 or SHA-384 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) +/* We always need at least one of the hashes via PSA (for use with HKDF) */ +#if !( defined(PSA_WANT_ALG_SHA_256) || defined(PSA_WANT_ALG_SHA_384) ) +#error "MBEDTLS_SSL_PROTO_TLS1_3 defined, but not all prerequisites" +#endif /* !(PSA_WANT_ALG_SHA_256 || PSA_WANT_ALG_SHA_384) */ +#if !defined(MBEDTLS_USE_PSA_CRYPTO) +/* When USE_PSA_CRYPTO is not defined, we also need SHA-256 or SHA-384 via the + * legacy interface, including via the MD layer, for the parts of the code + * that are shared with TLS 1.2 (running handshake hash). */ +#if !defined(MBEDTLS_MD_C) || \ + !( defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA384_C) ) +#error "MBEDTLS_SSL_PROTO_TLS1_3 defined, but not all prerequisites" +#endif /* !MBEDTLS_MD_C || !(MBEDTLS_SHA256_C || MBEDTLS_SHA384_C) */ +#endif /* !MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) +#if !( defined(MBEDTLS_ECDH_C) && defined(MBEDTLS_X509_CRT_PARSE_C) && \ + ( defined(MBEDTLS_PK_HAVE_ECDSA) || defined(MBEDTLS_PKCS1_V21) ) ) +#error "MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED defined, but not all prerequisites" +#endif +#endif + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED) +#if !( defined(MBEDTLS_ECDH_C) ) +#error "MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED defined, but not all prerequisites" +#endif +#endif + +/* + * The current implementation of TLS 1.3 requires MBEDTLS_SSL_KEEP_PEER_CERTIFICATE. + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) +#error "MBEDTLS_SSL_PROTO_TLS1_3 defined without MBEDTLS_SSL_KEEP_PEER_CERTIFICATE" +#endif + +#if 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_EARLY_DATA) && \ + ( !defined(MBEDTLS_SSL_SESSION_TICKETS) || \ + ( !defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED) && \ + !defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED) ) ) +#error "MBEDTLS_SSL_EARLY_DATA defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_SRV_C) && \ + ( !defined(MBEDTLS_SSL_MAX_EARLY_DATA_SIZE) || \ + ( MBEDTLS_SSL_MAX_EARLY_DATA_SIZE < 0 ) || \ + ( MBEDTLS_SSL_MAX_EARLY_DATA_SIZE > UINT32_MAX ) ) +#error "MBEDTLS_SSL_MAX_EARLY_DATA_SIZE MUST be defined and in range(0..UINT32_MAX)" +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) && \ + !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_ASYNC_PRIVATE) && !defined(MBEDTLS_X509_CRT_PARSE_C) +#error "MBEDTLS_SSL_ASYNC_PRIVATE defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && ( !defined(MBEDTLS_CIPHER_C) || \ + ( !defined(MBEDTLS_MD_C) && !defined(MBEDTLS_USE_PSA_CRYPTO) ) ) +#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_TLS1_2) || defined(MBEDTLS_SSL_PROTO_TLS1_3) ) +#error "MBEDTLS_SSL_TLS_C defined, but no protocols are active" +#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_CONNECTION_ID_COMPAT) && \ + !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +#error "MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT) && MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT != 0 +#if defined(MBEDTLS_DEPRECATED_REMOVED) +#error "MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT is deprecated and will be removed in a future version of Mbed TLS" +#elif defined(MBEDTLS_DEPRECATED_WARNING) +#warning "MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT is deprecated and will be removed in a future version of Mbed TLS" +#endif +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT && MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT != 0 */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) && \ + !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_2) +#error "MBEDTLS_SSL_EXTENDED_MASTER_SECRET defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_RENEGOTIATION) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2) +#error "MBEDTLS_SSL_RENEGOTIATION defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_TICKET_C) && ( !defined(MBEDTLS_CIPHER_C) && \ + !defined(MBEDTLS_USE_PSA_CRYPTO) ) +#error "MBEDTLS_SSL_TICKET_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_TICKET_C) && \ + !( defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) || defined(MBEDTLS_CHACHAPOLY_C) ) +#error "MBEDTLS_SSL_TICKET_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH) && \ + MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH >= 256 +#error "MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH must be less than 256" +#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) || \ + ( !defined(MBEDTLS_MD_C) && !defined(MBEDTLS_USE_PSA_CRYPTO) ) ) +#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_PARSE_C) || \ + ( !defined(MBEDTLS_MD_C) && !defined(MBEDTLS_USE_PSA_CRYPTO) ) ) +#error "MBEDTLS_X509_CREATE_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_X509_TRUSTED_CERTIFICATE_CALLBACK) && \ + ( !defined(MBEDTLS_X509_CRT_PARSE_C) ) +#error "MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK 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_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 + +#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) && ( !defined(MBEDTLS_SSL_PROTO_TLS1_3) ) +#error "MBEDTLS_SSL_RECORD_SIZE_LIMIT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) && !( defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) || defined(MBEDTLS_CHACHAPOLY_C) ) +#error "MBEDTLS_SSL_CONTEXT_SERIALIZATION defined, but not all prerequisites" +#endif + +/* Reject attempts to enable options that have been removed and that could + * cause a build to succeed but with features removed. */ + +#if defined(MBEDTLS_HAVEGE_C) //no-check-names +#error "MBEDTLS_HAVEGE_C was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/2599" +#endif + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) //no-check-names +#error "MBEDTLS_SSL_HW_RECORD_ACCEL was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4031" +#endif + +#if defined(MBEDTLS_SSL_PROTO_SSL3) //no-check-names +#error "MBEDTLS_SSL_PROTO_SSL3 (SSL v3.0 support) was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4031" +#endif + +#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) //no-check-names +#error "MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO (SSL v2 ClientHello support) was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4031" +#endif + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT) //no-check-names +#error "MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT (compatibility with the buggy implementation of truncated HMAC in Mbed TLS up to 2.7) was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4031" +#endif + +#if defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES) //no-check-names +#error "MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES was removed in Mbed TLS 3.0. See the ChangeLog entry if you really need SHA-1-signed certificates." +#endif + +#if defined(MBEDTLS_ZLIB_SUPPORT) //no-check-names +#error "MBEDTLS_ZLIB_SUPPORT was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4031" +#endif + +#if defined(MBEDTLS_CHECK_PARAMS) //no-check-names +#error "MBEDTLS_CHECK_PARAMS was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4313" +#endif + +#if defined(MBEDTLS_SSL_CID_PADDING_GRANULARITY) //no-check-names +#error "MBEDTLS_SSL_CID_PADDING_GRANULARITY was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4335" +#endif + +#if defined(MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY) //no-check-names +#error "MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4335" +#endif + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) //no-check-names +#error "MBEDTLS_SSL_TRUNCATED_HMAC was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4341" +#endif + +#if defined(MBEDTLS_PKCS7_C) && ( ( !defined(MBEDTLS_ASN1_PARSE_C) ) || \ + ( !defined(MBEDTLS_OID_C) ) || ( !defined(MBEDTLS_PK_PARSE_C) ) || \ + ( !defined(MBEDTLS_X509_CRT_PARSE_C) ) ||\ + ( !defined(MBEDTLS_X509_CRL_PARSE_C) ) || ( !defined(MBEDTLS_BIGNUM_C) ) || \ + ( !defined(MBEDTLS_MD_C) ) ) +#error "MBEDTLS_PKCS7_C is defined, but not all prerequisites" +#endif + +/* Undefine helper symbols */ +#undef MBEDTLS_PK_HAVE_ECDSA +#undef MBEDTLS_PK_HAVE_JPAKE + +/* + * 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; + +/* *INDENT-ON* */ +#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..0a5319b --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/cipher.h @@ -0,0 +1,1207 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#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_CIPHER_NULL_CIPHER) || \ + defined(MBEDTLS_CHACHA20_C) +#define MBEDTLS_CIPHER_MODE_STREAM +#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 + +#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 DES/3DES are considered weak ciphers and their use + * constitutes a security risk. We recommend 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. \warning DES is considered weak. */ + MBEDTLS_CIPHER_ID_3DES, /**< The Triple DES cipher. \warning 3DES is considered weak. */ + MBEDTLS_CIPHER_ID_CAMELLIA, /**< The Camellia 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 DES/3DES are considered weak ciphers and their use + * constitutes a security risk. We recommend 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. \warning DES is considered weak. */ + MBEDTLS_CIPHER_DES_CBC, /**< DES cipher with CBC mode. \warning DES is considered weak. */ + MBEDTLS_CIPHER_DES_EDE_ECB, /**< DES cipher with EDE ECB mode. \warning 3DES is considered weak. */ + MBEDTLS_CIPHER_DES_EDE_CBC, /**< DES cipher with EDE CBC mode. \warning 3DES is considered weak. */ + MBEDTLS_CIPHER_DES_EDE3_ECB, /**< DES cipher with EDE3 ECB mode. \warning 3DES is considered weak. */ + MBEDTLS_CIPHER_DES_EDE3_CBC, /**< DES cipher with EDE3 CBC mode. \warning 3DES is considered weak. */ + 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_AES_128_CCM_STAR_NO_TAG, /**< AES cipher with 128-bit CCM_STAR_NO_TAG mode. */ + MBEDTLS_CIPHER_AES_192_CCM_STAR_NO_TAG, /**< AES cipher with 192-bit CCM_STAR_NO_TAG mode. */ + MBEDTLS_CIPHER_AES_256_CCM_STAR_NO_TAG, /**< AES cipher with 256-bit CCM_STAR_NO_TAG 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_CAMELLIA_128_CCM_STAR_NO_TAG, /**< Camellia cipher with 128-bit CCM_STAR_NO_TAG mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CCM_STAR_NO_TAG, /**< Camellia cipher with 192-bit CCM_STAR_NO_TAG mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CCM_STAR_NO_TAG, /**< Camellia cipher with 256-bit CCM_STAR_NO_TAG 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_ARIA_128_CCM_STAR_NO_TAG, /**< Aria cipher with 128-bit key and CCM_STAR_NO_TAG mode. */ + MBEDTLS_CIPHER_ARIA_192_CCM_STAR_NO_TAG, /**< Aria cipher with 192-bit key and CCM_STAR_NO_TAG mode. */ + MBEDTLS_CIPHER_ARIA_256_CCM_STAR_NO_TAG, /**< Aria cipher with 256-bit key and CCM_STAR_NO_TAG 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_CCM_STAR_NO_TAG, /**< The CCM*-no-tag 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. \warning DES is considered weak. */ + MBEDTLS_KEY_LENGTH_DES = 64, + /** Key length in bits, including parity, for DES in two-key EDE. \warning 3DES is considered weak. */ + MBEDTLS_KEY_LENGTH_DES_EDE = 128, + /** Key length in bits, including parity, for DES in three-key EDE. \warning 3DES is considered weak. */ + 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 library/ssl_misc.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 library/ssl_misc.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 library/ssl_misc.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. + * + * \note The library does not support custom cipher info structures, + * only built-in structures returned by the functions + * mbedtls_cipher_info_from_string(), + * mbedtls_cipher_info_from_type(), + * mbedtls_cipher_info_from_values(), + * mbedtls_cipher_info_from_psa(). + */ +typedef struct mbedtls_cipher_info_t { + /** Full cipher identifier. For example, + * MBEDTLS_CIPHER_AES_256_CBC. + */ + mbedtls_cipher_type_t MBEDTLS_PRIVATE(type); + + /** The cipher mode. For example, MBEDTLS_MODE_CBC. */ + mbedtls_cipher_mode_t MBEDTLS_PRIVATE(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 MBEDTLS_PRIVATE(key_bitlen); + + /** Name of the cipher. */ + const char *MBEDTLS_PRIVATE(name); + + /** IV or nonce size, in Bytes. + * For ciphers that accept variable IV sizes, + * this is the recommended size. + */ + unsigned int MBEDTLS_PRIVATE(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 MBEDTLS_PRIVATE(flags); + + /** The block size, in Bytes. */ + unsigned int MBEDTLS_PRIVATE(block_size); + + /** Struct for base cipher information and functions. */ + const mbedtls_cipher_base_t *MBEDTLS_PRIVATE(base); + +} mbedtls_cipher_info_t; + +/** + * Generic cipher context. + */ +typedef struct mbedtls_cipher_context_t { + /** Information about the associated cipher. */ + const mbedtls_cipher_info_t *MBEDTLS_PRIVATE(cipher_info); + + /** Key length to use. */ + int MBEDTLS_PRIVATE(key_bitlen); + + /** Operation that the key of the context has been + * initialized for. + */ + mbedtls_operation_t MBEDTLS_PRIVATE(operation); + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) + /** Padding functions to use, if relevant for + * the specific cipher mode. + */ + void(*MBEDTLS_PRIVATE(add_padding))(unsigned char *output, size_t olen, size_t data_len); + int(*MBEDTLS_PRIVATE(get_padding))(unsigned char *input, size_t ilen, size_t *data_len); +#endif + + /** Buffer for input that has not been processed yet. */ + unsigned char MBEDTLS_PRIVATE(unprocessed_data)[MBEDTLS_MAX_BLOCK_LENGTH]; + + /** Number of Bytes that have not been processed yet. */ + size_t MBEDTLS_PRIVATE(unprocessed_len); + + /** Current IV or NONCE_COUNTER for CTR-mode, data unit (or sector) number + * for XTS-mode. */ + unsigned char MBEDTLS_PRIVATE(iv)[MBEDTLS_MAX_IV_LENGTH]; + + /** IV size in Bytes, for ciphers with variable-length IVs. */ + size_t MBEDTLS_PRIVATE(iv_size); + + /** The cipher-specific context. */ + void *MBEDTLS_PRIVATE(cipher_ctx); + +#if defined(MBEDTLS_CMAC_C) + /** CMAC-specific context. */ + mbedtls_cmac_context_t *MBEDTLS_PRIVATE(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 MBEDTLS_PRIVATE(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 Retrieve the identifier for a cipher info structure. + * + * \param[in] info The cipher info structure to query. + * This may be \c NULL. + * + * \return The full cipher identifier (\c MBEDTLS_CIPHER_xxx). + * \return #MBEDTLS_CIPHER_NONE if \p info is \c NULL. + */ +static inline mbedtls_cipher_type_t mbedtls_cipher_info_get_type( + const mbedtls_cipher_info_t *info) +{ + if (info == NULL) { + return MBEDTLS_CIPHER_NONE; + } else { + return info->MBEDTLS_PRIVATE(type); + } +} + +/** + * \brief Retrieve the operation mode for a cipher info structure. + * + * \param[in] info The cipher info structure to query. + * This may be \c NULL. + * + * \return The cipher mode (\c MBEDTLS_MODE_xxx). + * \return #MBEDTLS_MODE_NONE if \p info is \c NULL. + */ +static inline mbedtls_cipher_mode_t mbedtls_cipher_info_get_mode( + const mbedtls_cipher_info_t *info) +{ + if (info == NULL) { + return MBEDTLS_MODE_NONE; + } else { + return info->MBEDTLS_PRIVATE(mode); + } +} + +/** + * \brief Retrieve the key size for a cipher info structure. + * + * \param[in] info The cipher info structure to query. + * This may be \c NULL. + * + * \return The key length in bits. + * For variable-sized ciphers, this is the default length. + * For DES, this includes the parity bits. + * \return \c 0 if \p info is \c NULL. + */ +static inline size_t mbedtls_cipher_info_get_key_bitlen( + const mbedtls_cipher_info_t *info) +{ + if (info == NULL) { + return 0; + } else { + return info->MBEDTLS_PRIVATE(key_bitlen); + } +} + +/** + * \brief Retrieve the human-readable name for a + * cipher info structure. + * + * \param[in] info The cipher info structure to query. + * This may be \c NULL. + * + * \return The cipher name, which is a human readable string, + * with static storage duration. + * \return \c NULL if \c info is \p NULL. + */ +static inline const char *mbedtls_cipher_info_get_name( + const mbedtls_cipher_info_t *info) +{ + if (info == NULL) { + return NULL; + } else { + return info->MBEDTLS_PRIVATE(name); + } +} + +/** + * \brief This function returns the size of the IV or nonce + * for the cipher info structure, in bytes. + * + * \param info The cipher info structure. This may be \c NULL. + * + * \return The recommended IV size. + * \return \c 0 for ciphers not using an IV or a nonce. + * \return \c 0 if \p info is \c NULL. + */ +static inline size_t mbedtls_cipher_info_get_iv_size( + const mbedtls_cipher_info_t *info) +{ + if (info == NULL) { + return 0; + } + + return (size_t) info->MBEDTLS_PRIVATE(iv_size); +} + +/** + * \brief This function returns the block size of the given + * cipher info structure in bytes. + * + * \param info The cipher info structure. This may be \c NULL. + * + * \return The block size of the cipher. + * \return \c 1 if the cipher is a stream cipher. + * \return \c 0 if \p info is \c NULL. + */ +static inline size_t mbedtls_cipher_info_get_block_size( + const mbedtls_cipher_info_t *info) +{ + if (info == NULL) { + return 0; + } + + return (size_t) info->MBEDTLS_PRIVATE(block_size); +} + +/** + * \brief This function returns a non-zero value if the key length for + * the given cipher is variable. + * + * \param info The cipher info structure. This may be \c NULL. + * + * \return Non-zero if the key length is variable, \c 0 otherwise. + * \return \c 0 if the given pointer is \c NULL. + */ +static inline int mbedtls_cipher_info_has_variable_key_bitlen( + const mbedtls_cipher_info_t *info) +{ + if (info == NULL) { + return 0; + } + + return info->MBEDTLS_PRIVATE(flags) & MBEDTLS_CIPHER_VARIABLE_KEY_LEN; +} + +/** + * \brief This function returns a non-zero value if the IV size for + * the given cipher is variable. + * + * \param info The cipher info structure. This may be \c NULL. + * + * \return Non-zero if the IV size is variable, \c 0 otherwise. + * \return \c 0 if the given pointer is \c NULL. + */ +static inline int mbedtls_cipher_info_has_variable_iv_size( + const mbedtls_cipher_info_t *info) +{ + if (info == NULL) { + return 0; + } + + return info->MBEDTLS_PRIVATE(flags) & MBEDTLS_CIPHER_VARIABLE_IV_LEN; +} + +/** + * \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 prepares a cipher context for + * use with the given cipher primitive. + * + * \note After calling this function, you should call + * mbedtls_cipher_setkey() and, if the mode uses padding, + * mbedtls_cipher_set_padding_mode(), then for each + * message to encrypt or decrypt with this key, either: + * - mbedtls_cipher_crypt() for one-shot processing with + * non-AEAD modes; + * - mbedtls_cipher_auth_encrypt_ext() or + * mbedtls_cipher_auth_decrypt_ext() for one-shot + * processing with AEAD modes or NIST_KW; + * - for multi-part processing, see the documentation of + * mbedtls_cipher_reset(). + * + * \param ctx The context to prepare. This must be initialized by + * a call to mbedtls_cipher_init() first. + * \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. + */ +int mbedtls_cipher_setup(mbedtls_cipher_context_t *ctx, + const mbedtls_cipher_info_t *cipher_info); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +/** + * \brief This function initializes a cipher context for + * PSA-based use with the given cipher primitive. + * + * \deprecated This function is deprecated and will be removed in a + * future version of the library. + * Please use psa_aead_xxx() / psa_cipher_xxx() directly + * instead. + * + * \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_ext() or + * mbedtls_cipher_auth_decrypt_ext() 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_DEPRECATED mbedtls_cipher_setup_psa(mbedtls_cipher_context_t *ctx, + const mbedtls_cipher_info_t *cipher_info, + size_t taglen); +#endif /* MBEDTLS_DEPRECATED_REMOVED */ +#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 + * in bytes. + * + * \param ctx The context of the cipher. + * + * \return The block size of the underlying cipher. + * \return \c 1 if the cipher is a stream 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->MBEDTLS_PRIVATE(cipher_info) == NULL) { + return 0; + } + + return ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(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->MBEDTLS_PRIVATE(cipher_info) == NULL) { + return MBEDTLS_MODE_NONE; + } + + return ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(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->MBEDTLS_PRIVATE(cipher_info) == NULL) { + return 0; + } + + if (ctx->MBEDTLS_PRIVATE(iv_size) != 0) { + return (int) ctx->MBEDTLS_PRIVATE(iv_size); + } + + return (int) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(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->MBEDTLS_PRIVATE(cipher_info) == NULL) { + return MBEDTLS_CIPHER_NONE; + } + + return ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(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->MBEDTLS_PRIVATE(cipher_info) == NULL) { + return 0; + } + + return ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(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->MBEDTLS_PRIVATE(cipher_info) == NULL) { + return MBEDTLS_KEY_LENGTH_NONE; + } + + return (int) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(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->MBEDTLS_PRIVATE(cipher_info) == NULL) { + return MBEDTLS_OPERATION_NONE; + } + + return ctx->MBEDTLS_PRIVATE(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. + * + * \note For #MBEDTLS_CIPHER_CHACHA20, the nonce length must + * be 12, and the initial counter value is 0. + * + * \note For #MBEDTLS_CIPHER_CHACHA20_POLY1305, the nonce length + * must be 12. + * + * \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. + * + * \note With non-AEAD ciphers, the order of calls for each message + * is as follows: + * 1. mbedtls_cipher_set_iv() if the mode uses an IV/nonce. + * 2. mbedtls_cipher_reset() + * 3. mbedtls_cipher_update() one or more times + * 4. mbedtls_cipher_finish() + * . + * This sequence can be repeated to encrypt or decrypt multiple + * messages with the same key. + * + * \note With AEAD ciphers, the order of calls for each message + * is as follows: + * 1. mbedtls_cipher_set_iv() if the mode uses an IV/nonce. + * 2. mbedtls_cipher_reset() + * 3. mbedtls_cipher_update_ad() + * 4. mbedtls_cipher_update() one or more times + * 5. mbedtls_cipher_finish() + * 6. mbedtls_cipher_check_tag() (for decryption) or + * mbedtls_cipher_write_tag() (for encryption). + * . + * This sequence can be repeated to encrypt or decrypt multiple + * messages with the same key. + * + * \param ctx The generic cipher context. This must be bound to a key. + * + * \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. + * + * \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. + * + * \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) || 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/cmac.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/cmac.h new file mode 100644 index 0000000..1bc857c --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/cmac.h @@ -0,0 +1,252 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include "mbedtls/cipher.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#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 MBEDTLS_PRIVATE(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 MBEDTLS_PRIVATE(unprocessed_block)[MBEDTLS_CIPHER_BLKSIZE_MAX]; + + /** The length of data pending processing. */ + size_t MBEDTLS_PRIVATE(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-2.x.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/compat-2.x.h new file mode 100644 index 0000000..cdf81dc --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/compat-2.x.h @@ -0,0 +1,58 @@ +/** + * \file compat-2.x.h + * + * \brief Compatibility definitions + * + * \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_DEPRECATED_WARNING) +#warning "Including compat-2.x.h is deprecated" +#endif + +#ifndef MBEDTLS_COMPAT2X_H +#define MBEDTLS_COMPAT2X_H + +/* + * Macros for renamed functions + */ +#define mbedtls_ctr_drbg_update_ret mbedtls_ctr_drbg_update +#define mbedtls_hmac_drbg_update_ret mbedtls_hmac_drbg_update +#define mbedtls_md5_starts_ret mbedtls_md5_starts +#define mbedtls_md5_update_ret mbedtls_md5_update +#define mbedtls_md5_finish_ret mbedtls_md5_finish +#define mbedtls_md5_ret mbedtls_md5 +#define mbedtls_ripemd160_starts_ret mbedtls_ripemd160_starts +#define mbedtls_ripemd160_update_ret mbedtls_ripemd160_update +#define mbedtls_ripemd160_finish_ret mbedtls_ripemd160_finish +#define mbedtls_ripemd160_ret mbedtls_ripemd160 +#define mbedtls_sha1_starts_ret mbedtls_sha1_starts +#define mbedtls_sha1_update_ret mbedtls_sha1_update +#define mbedtls_sha1_finish_ret mbedtls_sha1_finish +#define mbedtls_sha1_ret mbedtls_sha1 +#define mbedtls_sha256_starts_ret mbedtls_sha256_starts +#define mbedtls_sha256_update_ret mbedtls_sha256_update +#define mbedtls_sha256_finish_ret mbedtls_sha256_finish +#define mbedtls_sha256_ret mbedtls_sha256 +#define mbedtls_sha512_starts_ret mbedtls_sha512_starts +#define mbedtls_sha512_update_ret mbedtls_sha512_update +#define mbedtls_sha512_finish_ret mbedtls_sha512_finish +#define mbedtls_sha512_ret mbedtls_sha512 + +#endif /* MBEDTLS_COMPAT2X_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/config_psa.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/config_psa.h new file mode 100644 index 0000000..cedce1e --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/config_psa.h @@ -0,0 +1,866 @@ +/** + * \file mbedtls/config_psa.h + * \brief PSA crypto configuration options (set of defines) + * + * This set of compile-time options takes settings defined in + * include/mbedtls/mbedtls_config.h and include/psa/crypto_config.h and uses + * those definitions to define symbols used in the library code. + * + * Users and integrators should not edit this file, please edit + * include/mbedtls/mbedtls_config.h for MBEDTLS_XXX settings or + * include/psa/crypto_config.h for PSA_WANT_XXX settings. + */ +/* + * 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_CONFIG_PSA_H +#define MBEDTLS_CONFIG_PSA_H + +#if defined(MBEDTLS_PSA_CRYPTO_CONFIG) +#if defined(MBEDTLS_PSA_CRYPTO_CONFIG_FILE) +#include MBEDTLS_PSA_CRYPTO_CONFIG_FILE +#else +#include "psa/crypto_config.h" +#endif +#endif /* defined(MBEDTLS_PSA_CRYPTO_CONFIG) */ + +#if defined(MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE) +#include MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + + +/****************************************************************/ +/* De facto synonyms */ +/****************************************************************/ + +#if defined(PSA_WANT_ALG_ECDSA_ANY) && !defined(PSA_WANT_ALG_ECDSA) +#define PSA_WANT_ALG_ECDSA PSA_WANT_ALG_ECDSA_ANY +#elif !defined(PSA_WANT_ALG_ECDSA_ANY) && defined(PSA_WANT_ALG_ECDSA) +#define PSA_WANT_ALG_ECDSA_ANY PSA_WANT_ALG_ECDSA +#endif + +#if defined(PSA_WANT_ALG_CCM_STAR_NO_TAG) && !defined(PSA_WANT_ALG_CCM) +#define PSA_WANT_ALG_CCM PSA_WANT_ALG_CCM_STAR_NO_TAG +#elif !defined(PSA_WANT_ALG_CCM_STAR_NO_TAG) && defined(PSA_WANT_ALG_CCM) +#define PSA_WANT_ALG_CCM_STAR_NO_TAG PSA_WANT_ALG_CCM +#endif + +#if defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW) && !defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN) +#define PSA_WANT_ALG_RSA_PKCS1V15_SIGN PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW +#elif !defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW) && defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN) +#define PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW PSA_WANT_ALG_RSA_PKCS1V15_SIGN +#endif + +#if defined(PSA_WANT_ALG_RSA_PSS_ANY_SALT) && !defined(PSA_WANT_ALG_RSA_PSS) +#define PSA_WANT_ALG_RSA_PSS PSA_WANT_ALG_RSA_PSS_ANY_SALT +#elif !defined(PSA_WANT_ALG_RSA_PSS_ANY_SALT) && defined(PSA_WANT_ALG_RSA_PSS) +#define PSA_WANT_ALG_RSA_PSS_ANY_SALT PSA_WANT_ALG_RSA_PSS +#endif + + + +/****************************************************************/ +/* Require built-in implementations based on PSA requirements */ +/****************************************************************/ + +#if defined(MBEDTLS_PSA_CRYPTO_CONFIG) + +#if defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA) +#define MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA 1 +#define MBEDTLS_ECDSA_DETERMINISTIC +#define MBEDTLS_ECDSA_C +#define MBEDTLS_HMAC_DRBG_C +#define MBEDTLS_MD_C +#endif /* !MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA */ +#endif /* PSA_WANT_ALG_DETERMINISTIC_ECDSA */ + +#if defined(PSA_WANT_ALG_ECDH) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_ECDH) +#define MBEDTLS_PSA_BUILTIN_ALG_ECDH 1 +#define MBEDTLS_ECDH_C +#define MBEDTLS_ECP_C +#define MBEDTLS_BIGNUM_C +#endif /* !MBEDTLS_PSA_ACCEL_ALG_ECDH */ +#endif /* PSA_WANT_ALG_ECDH */ + +#if defined(PSA_WANT_ALG_ECDSA) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_ECDSA) +#define MBEDTLS_PSA_BUILTIN_ALG_ECDSA 1 +#define MBEDTLS_ECDSA_C +#define MBEDTLS_ECP_C +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_ASN1_PARSE_C +#define MBEDTLS_ASN1_WRITE_C +#endif /* !MBEDTLS_PSA_ACCEL_ALG_ECDSA */ +#endif /* PSA_WANT_ALG_ECDSA */ + +#if defined(PSA_WANT_ALG_HKDF) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_HKDF) +#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1 +#define MBEDTLS_PSA_BUILTIN_ALG_HKDF 1 +#endif /* !MBEDTLS_PSA_ACCEL_ALG_HKDF */ +#endif /* PSA_WANT_ALG_HKDF */ + +#if defined(PSA_WANT_ALG_HKDF_EXTRACT) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_HKDF_EXTRACT) +#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1 +#define MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT 1 +#endif /* !MBEDTLS_PSA_ACCEL_ALG_HKDF_EXTRACT */ +#endif /* PSA_WANT_ALG_HKDF_EXTRACT */ + +#if defined(PSA_WANT_ALG_HKDF_EXPAND) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_HKDF_EXPAND) +#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1 +#define MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND 1 +#endif /* !MBEDTLS_PSA_ACCEL_ALG_HKDF_EXPAND */ +#endif /* PSA_WANT_ALG_HKDF_EXPAND */ + +#if defined(PSA_WANT_ALG_HMAC) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_HMAC) +#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1 +#endif /* !MBEDTLS_PSA_ACCEL_ALG_HMAC */ +#endif /* PSA_WANT_ALG_HMAC */ + +#if defined(PSA_WANT_ALG_MD5) && !defined(MBEDTLS_PSA_ACCEL_ALG_MD5) +#define MBEDTLS_PSA_BUILTIN_ALG_MD5 1 +#define MBEDTLS_MD5_C +#endif + +#if defined(PSA_WANT_ALG_JPAKE) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_JPAKE) +#define MBEDTLS_PSA_BUILTIN_PAKE 1 +#define MBEDTLS_PSA_BUILTIN_ALG_JPAKE 1 +#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_ECP_C +#define MBEDTLS_ECJPAKE_C +#endif /* MBEDTLS_PSA_ACCEL_ALG_JPAKE */ +#endif /* PSA_WANT_ALG_JPAKE */ + +#if defined(PSA_WANT_ALG_RIPEMD160) && !defined(MBEDTLS_PSA_ACCEL_ALG_RIPEMD160) +#define MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160 1 +#define MBEDTLS_RIPEMD160_C +#endif + +#if defined(PSA_WANT_ALG_RSA_OAEP) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_OAEP) +#define MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP 1 +#define MBEDTLS_RSA_C +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_OID_C +#define MBEDTLS_PKCS1_V21 +#endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_OAEP */ +#endif /* PSA_WANT_ALG_RSA_OAEP */ + +#if defined(PSA_WANT_ALG_RSA_PKCS1V15_CRYPT) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_CRYPT) +#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT 1 +#define MBEDTLS_RSA_C +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_OID_C +#define MBEDTLS_PKCS1_V15 +#endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_CRYPT */ +#endif /* PSA_WANT_ALG_RSA_PKCS1V15_CRYPT */ + +#if defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN) +#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN 1 +#define MBEDTLS_RSA_C +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_OID_C +#define MBEDTLS_PKCS1_V15 +#endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN */ +#endif /* PSA_WANT_ALG_RSA_PKCS1V15_SIGN */ + +#if defined(PSA_WANT_ALG_RSA_PSS) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PSS) +#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS 1 +#define MBEDTLS_RSA_C +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_OID_C +#define MBEDTLS_PKCS1_V21 +#endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_PSS */ +#endif /* PSA_WANT_ALG_RSA_PSS */ + +#if defined(PSA_WANT_ALG_SHA_1) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_1) +#define MBEDTLS_PSA_BUILTIN_ALG_SHA_1 1 +#define MBEDTLS_SHA1_C +#endif + +#if defined(PSA_WANT_ALG_SHA_224) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_224) +#define MBEDTLS_PSA_BUILTIN_ALG_SHA_224 1 +#define MBEDTLS_SHA224_C +#endif + +#if defined(PSA_WANT_ALG_SHA_256) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_256) +#define MBEDTLS_PSA_BUILTIN_ALG_SHA_256 1 +#define MBEDTLS_SHA256_C +#endif + +#if defined(PSA_WANT_ALG_SHA_384) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_384) +#define MBEDTLS_PSA_BUILTIN_ALG_SHA_384 1 +#define MBEDTLS_SHA384_C +#endif + +#if defined(PSA_WANT_ALG_SHA_512) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_512) +#define MBEDTLS_PSA_BUILTIN_ALG_SHA_512 1 +#define MBEDTLS_SHA512_C +#endif + +#if defined(PSA_WANT_ALG_TLS12_PRF) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_PRF) +#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF 1 +#endif /* !MBEDTLS_PSA_ACCEL_ALG_TLS12_PRF */ +#endif /* PSA_WANT_ALG_TLS12_PRF */ + +#if defined(PSA_WANT_ALG_TLS12_PSK_TO_MS) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_PSK_TO_MS) +#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS 1 +#endif /* !MBEDTLS_PSA_ACCEL_ALG_TLS12_PSK_TO_MS */ +#endif /* PSA_WANT_ALG_TLS12_PSK_TO_MS */ + +#if defined(PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_ECJPAKE_TO_PMS) +#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS 1 +#endif /* !MBEDTLS_PSA_ACCEL_ALG_TLS12_ECJPAKE_TO_PMS */ +#endif /* PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS */ + +#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR 1 +#define MBEDTLS_ECP_C +#define MBEDTLS_BIGNUM_C +#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR */ +#endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR */ + +#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY 1 +#define MBEDTLS_ECP_C +#define MBEDTLS_BIGNUM_C +#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY */ +#endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */ + +#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR 1 +#define MBEDTLS_RSA_C +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_OID_C +#define MBEDTLS_GENPRIME +#define MBEDTLS_PK_PARSE_C +#define MBEDTLS_PK_WRITE_C +#define MBEDTLS_PK_C +#define MBEDTLS_ASN1_PARSE_C +#define MBEDTLS_ASN1_WRITE_C +#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR */ +#endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR */ + +#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY 1 +#define MBEDTLS_RSA_C +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_OID_C +#define MBEDTLS_PK_PARSE_C +#define MBEDTLS_PK_WRITE_C +#define MBEDTLS_PK_C +#define MBEDTLS_ASN1_PARSE_C +#define MBEDTLS_ASN1_WRITE_C +#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY */ +#endif /* PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY */ + +/* If any of the block modes are requested that don't have an + * associated HW assist, define PSA_HAVE_SOFT_BLOCK_MODE for checking + * in the block cipher key types. */ +#if (defined(PSA_WANT_ALG_CTR) && !defined(MBEDTLS_PSA_ACCEL_ALG_CTR)) || \ + (defined(PSA_WANT_ALG_CFB) && !defined(MBEDTLS_PSA_ACCEL_ALG_CFB)) || \ + (defined(PSA_WANT_ALG_OFB) && !defined(MBEDTLS_PSA_ACCEL_ALG_OFB)) || \ + defined(PSA_WANT_ALG_ECB_NO_PADDING) || \ + (defined(PSA_WANT_ALG_CBC_NO_PADDING) && \ + !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_NO_PADDING)) || \ + (defined(PSA_WANT_ALG_CBC_PKCS7) && \ + !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_PKCS7)) || \ + (defined(PSA_WANT_ALG_CMAC) && !defined(MBEDTLS_PSA_ACCEL_ALG_CMAC)) +#define PSA_HAVE_SOFT_BLOCK_MODE 1 +#endif + +#if (defined(PSA_WANT_ALG_GCM) && !defined(MBEDTLS_PSA_ACCEL_ALG_GCM)) || \ + (defined(PSA_WANT_ALG_CCM) && !defined(MBEDTLS_PSA_ACCEL_ALG_CCM)) +#define PSA_HAVE_SOFT_BLOCK_AEAD 1 +#endif + +#if defined(PSA_WANT_KEY_TYPE_AES) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_AES) +#define PSA_HAVE_SOFT_KEY_TYPE_AES 1 +#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_AES */ +#if defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \ + defined(PSA_HAVE_SOFT_BLOCK_MODE) || \ + defined(PSA_HAVE_SOFT_BLOCK_AEAD) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES 1 +#define MBEDTLS_AES_C +#endif /* PSA_HAVE_SOFT_KEY_TYPE_AES || PSA_HAVE_SOFT_BLOCK_MODE */ +#endif /* PSA_WANT_KEY_TYPE_AES */ + +#if defined(PSA_WANT_KEY_TYPE_ARIA) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ARIA) +#define PSA_HAVE_SOFT_KEY_TYPE_ARIA 1 +#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_ARIA */ +#if defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \ + defined(PSA_HAVE_SOFT_BLOCK_MODE) || \ + defined(PSA_HAVE_SOFT_BLOCK_AEAD) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARIA 1 +#define MBEDTLS_ARIA_C +#endif /* PSA_HAVE_SOFT_KEY_TYPE_ARIA || PSA_HAVE_SOFT_BLOCK_MODE */ +#endif /* PSA_WANT_KEY_TYPE_ARIA */ + +#if defined(PSA_WANT_KEY_TYPE_CAMELLIA) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_CAMELLIA) +#define PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA 1 +#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_CAMELLIA */ +#if defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA) || \ + defined(PSA_HAVE_SOFT_BLOCK_MODE) || \ + defined(PSA_HAVE_SOFT_BLOCK_AEAD) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CAMELLIA 1 +#define MBEDTLS_CAMELLIA_C +#endif /* PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA || PSA_HAVE_SOFT_BLOCK_MODE */ +#endif /* PSA_WANT_KEY_TYPE_CAMELLIA */ + +#if defined(PSA_WANT_KEY_TYPE_DES) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DES) +#define PSA_HAVE_SOFT_KEY_TYPE_DES 1 +#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_DES */ +#if defined(PSA_HAVE_SOFT_KEY_TYPE_DES) || \ + defined(PSA_HAVE_SOFT_BLOCK_MODE) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES 1 +#define MBEDTLS_DES_C +#endif /*PSA_HAVE_SOFT_KEY_TYPE_DES || PSA_HAVE_SOFT_BLOCK_MODE */ +#endif /* PSA_WANT_KEY_TYPE_DES */ + +#if defined(PSA_WANT_KEY_TYPE_CHACHA20) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_CHACHA20) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20 1 +#define MBEDTLS_CHACHA20_C +#endif /*!MBEDTLS_PSA_ACCEL_KEY_TYPE_CHACHA20 */ +#endif /* PSA_WANT_KEY_TYPE_CHACHA20 */ + +/* If any of the software block ciphers are selected, define + * PSA_HAVE_SOFT_BLOCK_CIPHER, which can be used in any of these + * situations. */ +#if defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \ + defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \ + defined(PSA_HAVE_SOFT_KEY_TYPE_DES) || \ + defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA) +#define PSA_HAVE_SOFT_BLOCK_CIPHER 1 +#endif + +#if defined(PSA_WANT_ALG_STREAM_CIPHER) +#define MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER 1 +#endif /* PSA_WANT_ALG_STREAM_CIPHER */ + +#if defined(PSA_WANT_ALG_CBC_MAC) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_MAC) +#error "CBC-MAC is not yet supported via the PSA API in Mbed TLS." +#define MBEDTLS_PSA_BUILTIN_ALG_CBC_MAC 1 +#endif /* !MBEDTLS_PSA_ACCEL_ALG_CBC_MAC */ +#endif /* PSA_WANT_ALG_CBC_MAC */ + +#if defined(PSA_WANT_ALG_CMAC) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_CMAC) || \ + defined(PSA_HAVE_SOFT_BLOCK_CIPHER) +#define MBEDTLS_PSA_BUILTIN_ALG_CMAC 1 +#define MBEDTLS_CMAC_C +#endif /* !MBEDTLS_PSA_ACCEL_ALG_CMAC */ +#endif /* PSA_WANT_ALG_CMAC */ + +#if defined(PSA_WANT_ALG_CTR) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_CTR) || \ + defined(PSA_HAVE_SOFT_BLOCK_CIPHER) +#define MBEDTLS_PSA_BUILTIN_ALG_CTR 1 +#define MBEDTLS_CIPHER_MODE_CTR +#endif +#endif /* PSA_WANT_ALG_CTR */ + +#if defined(PSA_WANT_ALG_CFB) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_CFB) || \ + defined(PSA_HAVE_SOFT_BLOCK_CIPHER) +#define MBEDTLS_PSA_BUILTIN_ALG_CFB 1 +#define MBEDTLS_CIPHER_MODE_CFB +#endif +#endif /* PSA_WANT_ALG_CFB */ + +#if defined(PSA_WANT_ALG_OFB) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_OFB) || \ + defined(PSA_HAVE_SOFT_BLOCK_CIPHER) +#define MBEDTLS_PSA_BUILTIN_ALG_OFB 1 +#define MBEDTLS_CIPHER_MODE_OFB +#endif +#endif /* PSA_WANT_ALG_OFB */ + +#if defined(PSA_WANT_ALG_ECB_NO_PADDING) && \ + !defined(MBEDTLS_PSA_ACCEL_ALG_ECB_NO_PADDING) +#define MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING 1 +#endif + +#if defined(PSA_WANT_ALG_CBC_NO_PADDING) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_NO_PADDING) || \ + defined(PSA_HAVE_SOFT_BLOCK_CIPHER) +#define MBEDTLS_CIPHER_MODE_CBC +#define MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING 1 +#endif +#endif /* PSA_WANT_ALG_CBC_NO_PADDING */ + +#if defined(PSA_WANT_ALG_CBC_PKCS7) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_PKCS7) || \ + defined(PSA_HAVE_SOFT_BLOCK_CIPHER) +#define MBEDTLS_CIPHER_MODE_CBC +#define MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 1 +#define MBEDTLS_CIPHER_PADDING_PKCS7 +#endif +#endif /* PSA_WANT_ALG_CBC_PKCS7 */ + +#if defined(PSA_WANT_ALG_CCM) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_CCM) || \ + defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \ + defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \ + defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA) +#define MBEDTLS_PSA_BUILTIN_ALG_CCM 1 +#define MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG 1 +#define MBEDTLS_CCM_C +#endif +#endif /* PSA_WANT_ALG_CCM */ + +#if defined(PSA_WANT_ALG_GCM) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_GCM) || \ + defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \ + defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \ + defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA) +#define MBEDTLS_PSA_BUILTIN_ALG_GCM 1 +#define MBEDTLS_GCM_C +#endif +#endif /* PSA_WANT_ALG_GCM */ + +#if defined(PSA_WANT_ALG_CHACHA20_POLY1305) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_CHACHA20_POLY1305) +#if defined(PSA_WANT_KEY_TYPE_CHACHA20) +#define MBEDTLS_CHACHAPOLY_C +#define MBEDTLS_CHACHA20_C +#define MBEDTLS_POLY1305_C +#define MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 1 +#endif /* PSA_WANT_KEY_TYPE_CHACHA20 */ +#endif /* !MBEDTLS_PSA_ACCEL_ALG_CHACHA20_POLY1305 */ +#endif /* PSA_WANT_ALG_CHACHA20_POLY1305 */ + +#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256) +#if !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_256) +#define MBEDTLS_ECP_DP_BP256R1_ENABLED +#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_256 1 +#endif /* !MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_256 */ +#endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_256 */ + +#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384) +#if !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_384) +#define MBEDTLS_ECP_DP_BP384R1_ENABLED +#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_384 1 +#endif /* !MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_384 */ +#endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_384 */ + +#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512) +#if !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_512) +#define MBEDTLS_ECP_DP_BP512R1_ENABLED +#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_512 1 +#endif /* !MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_512 */ +#endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_512 */ + +#if defined(PSA_WANT_ECC_MONTGOMERY_255) +#if !defined(MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_255) +#define MBEDTLS_ECP_DP_CURVE25519_ENABLED +#define MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_255 1 +#endif /* !MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_255 */ +#endif /* PSA_WANT_ECC_MONTGOMERY_255 */ + +#if defined(PSA_WANT_ECC_MONTGOMERY_448) +#if !defined(MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_448) +#define MBEDTLS_ECP_DP_CURVE448_ENABLED +#define MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_448 1 +#endif /* !MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_448 */ +#endif /* PSA_WANT_ECC_MONTGOMERY_448 */ + +#if defined(PSA_WANT_ECC_SECP_R1_192) +#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_192) +#define MBEDTLS_ECP_DP_SECP192R1_ENABLED +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_192 1 +#endif /* !MBEDTLS_PSA_ACCEL_ECC_SECP_R1_192 */ +#endif /* PSA_WANT_ECC_SECP_R1_192 */ + +#if defined(PSA_WANT_ECC_SECP_R1_224) +#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_224) +#define MBEDTLS_ECP_DP_SECP224R1_ENABLED +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_224 1 +#endif /* !MBEDTLS_PSA_ACCEL_ECC_SECP_R1_224 */ +#endif /* PSA_WANT_ECC_SECP_R1_224 */ + +#if defined(PSA_WANT_ECC_SECP_R1_256) +#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_256) +#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_256 1 +#endif /* !MBEDTLS_PSA_ACCEL_ECC_SECP_R1_256 */ +#endif /* PSA_WANT_ECC_SECP_R1_256 */ + +#if defined(PSA_WANT_ECC_SECP_R1_384) +#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_384) +#define MBEDTLS_ECP_DP_SECP384R1_ENABLED +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_384 1 +#endif /* !MBEDTLS_PSA_ACCEL_ECC_SECP_R1_384 */ +#endif /* PSA_WANT_ECC_SECP_R1_384 */ + +#if defined(PSA_WANT_ECC_SECP_R1_521) +#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_521) +#define MBEDTLS_ECP_DP_SECP521R1_ENABLED +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_521 1 +#endif /* !MBEDTLS_PSA_ACCEL_ECC_SECP_R1_521 */ +#endif /* PSA_WANT_ECC_SECP_R1_521 */ + +#if defined(PSA_WANT_ECC_SECP_K1_192) +#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_192) +#define MBEDTLS_ECP_DP_SECP192K1_ENABLED +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_192 1 +#endif /* !MBEDTLS_PSA_ACCEL_ECC_SECP_K1_192 */ +#endif /* PSA_WANT_ECC_SECP_K1_192 */ + +#if defined(PSA_WANT_ECC_SECP_K1_224) +#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_224) +/* + * SECP224K1 is buggy via the PSA API in Mbed TLS + * (https://github.com/Mbed-TLS/mbedtls/issues/3541). + */ +#error "SECP224K1 is buggy via the PSA API in Mbed TLS." +#define MBEDTLS_ECP_DP_SECP224K1_ENABLED +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_224 1 +#endif /* !MBEDTLS_PSA_ACCEL_ECC_SECP_K1_224 */ +#endif /* PSA_WANT_ECC_SECP_K1_224 */ + +#if defined(PSA_WANT_ECC_SECP_K1_256) +#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_256) +#define MBEDTLS_ECP_DP_SECP256K1_ENABLED +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_256 1 +#endif /* !MBEDTLS_PSA_ACCEL_ECC_SECP_K1_256 */ +#endif /* PSA_WANT_ECC_SECP_K1_256 */ + + + +/****************************************************************/ +/* Infer PSA requirements from Mbed TLS capabilities */ +/****************************************************************/ + +#else /* MBEDTLS_PSA_CRYPTO_CONFIG */ + +/* + * Ensure PSA_WANT_* defines are setup properly if MBEDTLS_PSA_CRYPTO_CONFIG + * is not defined + */ + +#if defined(MBEDTLS_CCM_C) +#define MBEDTLS_PSA_BUILTIN_ALG_CCM 1 +#define MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG 1 +#define PSA_WANT_ALG_CCM 1 +#define PSA_WANT_ALG_CCM_STAR_NO_TAG 1 +#endif /* MBEDTLS_CCM_C */ + +#if defined(MBEDTLS_CMAC_C) +#define MBEDTLS_PSA_BUILTIN_ALG_CMAC 1 +#define PSA_WANT_ALG_CMAC 1 +#endif /* MBEDTLS_CMAC_C */ + +#if defined(MBEDTLS_ECDH_C) +#define MBEDTLS_PSA_BUILTIN_ALG_ECDH 1 +#define PSA_WANT_ALG_ECDH 1 +#endif /* MBEDTLS_ECDH_C */ + +#if defined(MBEDTLS_ECDSA_C) +#define MBEDTLS_PSA_BUILTIN_ALG_ECDSA 1 +#define PSA_WANT_ALG_ECDSA 1 +#define PSA_WANT_ALG_ECDSA_ANY 1 + +// Only add in DETERMINISTIC support if ECDSA is also enabled +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +#define MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA 1 +#define PSA_WANT_ALG_DETERMINISTIC_ECDSA 1 +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + +#endif /* MBEDTLS_ECDSA_C */ + +#if defined(MBEDTLS_ECP_C) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR 1 +#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR 1 +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY 1 +#define PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY 1 +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_GCM_C) +#define MBEDTLS_PSA_BUILTIN_ALG_GCM 1 +#define PSA_WANT_ALG_GCM 1 +#endif /* MBEDTLS_GCM_C */ + +/* Enable PSA HKDF algorithm if mbedtls HKDF is supported. + * PSA HKDF EXTRACT and PSA HKDF EXPAND have minimal cost when + * PSA HKDF is enabled, so enable both algorithms together + * with PSA HKDF. */ +#if defined(MBEDTLS_HKDF_C) +#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1 +#define PSA_WANT_ALG_HMAC 1 +#define MBEDTLS_PSA_BUILTIN_ALG_HKDF 1 +#define PSA_WANT_ALG_HKDF 1 +#define MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT 1 +#define PSA_WANT_ALG_HKDF_EXTRACT 1 +#define MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND 1 +#define PSA_WANT_ALG_HKDF_EXPAND 1 +#endif /* MBEDTLS_HKDF_C */ + +#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1 +#define PSA_WANT_ALG_HMAC 1 +#define PSA_WANT_KEY_TYPE_HMAC + +#if defined(MBEDTLS_MD_C) +#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF 1 +#define PSA_WANT_ALG_TLS12_PRF 1 +#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS 1 +#define PSA_WANT_ALG_TLS12_PSK_TO_MS 1 +#endif /* MBEDTLS_MD_C */ + +#if defined(MBEDTLS_MD5_C) +#define MBEDTLS_PSA_BUILTIN_ALG_MD5 1 +#define PSA_WANT_ALG_MD5 1 +#endif + +#if defined(MBEDTLS_ECJPAKE_C) +#define MBEDTLS_PSA_BUILTIN_PAKE 1 +#define MBEDTLS_PSA_BUILTIN_ALG_JPAKE 1 +#define PSA_WANT_ALG_JPAKE 1 +#endif + +#if defined(MBEDTLS_RIPEMD160_C) +#define MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160 1 +#define PSA_WANT_ALG_RIPEMD160 1 +#endif + +#if defined(MBEDTLS_RSA_C) +#if defined(MBEDTLS_PKCS1_V15) +#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT 1 +#define PSA_WANT_ALG_RSA_PKCS1V15_CRYPT 1 +#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN 1 +#define PSA_WANT_ALG_RSA_PKCS1V15_SIGN 1 +#define PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW 1 +#endif /* MBEDTLS_PKCS1_V15 */ +#if defined(MBEDTLS_PKCS1_V21) +#define MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP 1 +#define PSA_WANT_ALG_RSA_OAEP 1 +#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS 1 +#define PSA_WANT_ALG_RSA_PSS 1 +#endif /* MBEDTLS_PKCS1_V21 */ +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR 1 +#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR 1 +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY 1 +#define PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY 1 +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_SHA1_C) +#define MBEDTLS_PSA_BUILTIN_ALG_SHA_1 1 +#define PSA_WANT_ALG_SHA_1 1 +#endif + +#if defined(MBEDTLS_SHA224_C) +#define MBEDTLS_PSA_BUILTIN_ALG_SHA_224 1 +#define PSA_WANT_ALG_SHA_224 1 +#endif + +#if defined(MBEDTLS_SHA256_C) +#define MBEDTLS_PSA_BUILTIN_ALG_SHA_256 1 +#define PSA_WANT_ALG_SHA_256 1 +#endif + +#if defined(MBEDTLS_SHA384_C) +#define MBEDTLS_PSA_BUILTIN_ALG_SHA_384 1 +#define PSA_WANT_ALG_SHA_384 1 +#endif + +#if defined(MBEDTLS_SHA512_C) +#define MBEDTLS_PSA_BUILTIN_ALG_SHA_512 1 +#define PSA_WANT_ALG_SHA_512 1 +#endif + +#if defined(MBEDTLS_AES_C) +#define PSA_WANT_KEY_TYPE_AES 1 +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES 1 +#endif + +#if defined(MBEDTLS_ARIA_C) +#define PSA_WANT_KEY_TYPE_ARIA 1 +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARIA 1 +#endif + +#if defined(MBEDTLS_CAMELLIA_C) +#define PSA_WANT_KEY_TYPE_CAMELLIA 1 +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CAMELLIA 1 +#endif + +#if defined(MBEDTLS_DES_C) +#define PSA_WANT_KEY_TYPE_DES 1 +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES 1 +#endif + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) +#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS 1 +#define PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS 1 +#endif + +#if defined(MBEDTLS_CHACHA20_C) +#define PSA_WANT_KEY_TYPE_CHACHA20 1 +#define PSA_WANT_ALG_STREAM_CIPHER 1 +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20 1 +#define MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER 1 +#if defined(MBEDTLS_CHACHAPOLY_C) +#define PSA_WANT_ALG_CHACHA20_POLY1305 1 +#define MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 1 +#endif +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#define MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING 1 +#define PSA_WANT_ALG_CBC_NO_PADDING 1 +#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) +#define MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 1 +#define PSA_WANT_ALG_CBC_PKCS7 1 +#endif +#endif + +#if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) || \ + defined(MBEDTLS_ARIA_C) || defined(MBEDTLS_CAMELLIA_C) +#define MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING 1 +#define PSA_WANT_ALG_ECB_NO_PADDING 1 +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +#define MBEDTLS_PSA_BUILTIN_ALG_CFB 1 +#define PSA_WANT_ALG_CFB 1 +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +#define MBEDTLS_PSA_BUILTIN_ALG_CTR 1 +#define PSA_WANT_ALG_CTR 1 +#endif + +#if defined(MBEDTLS_CIPHER_MODE_OFB) +#define MBEDTLS_PSA_BUILTIN_ALG_OFB 1 +#define PSA_WANT_ALG_OFB 1 +#endif + +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) +#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_256 1 +#define PSA_WANT_ECC_BRAINPOOL_P_R1_256 +#endif + +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) +#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_384 1 +#define PSA_WANT_ECC_BRAINPOOL_P_R1_384 +#endif + +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) +#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_512 1 +#define PSA_WANT_ECC_BRAINPOOL_P_R1_512 +#endif + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +#define MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_255 1 +#define PSA_WANT_ECC_MONTGOMERY_255 +#endif + +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) +#define MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_448 1 +#define PSA_WANT_ECC_MONTGOMERY_448 +#endif + +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_192 1 +#define PSA_WANT_ECC_SECP_R1_192 +#endif + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_224 1 +#define PSA_WANT_ECC_SECP_R1_224 +#endif + +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_256 1 +#define PSA_WANT_ECC_SECP_R1_256 +#endif + +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_384 1 +#define PSA_WANT_ECC_SECP_R1_384 +#endif + +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_521 1 +#define PSA_WANT_ECC_SECP_R1_521 +#endif + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_192 1 +#define PSA_WANT_ECC_SECP_K1_192 +#endif + +/* SECP224K1 is buggy via the PSA API (https://github.com/Mbed-TLS/mbedtls/issues/3541) */ +#if 0 && defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_224 1 +#define PSA_WANT_ECC_SECP_K1_224 +#endif + +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_256 1 +#define PSA_WANT_ECC_SECP_K1_256 +#endif + +#endif /* MBEDTLS_PSA_CRYPTO_CONFIG */ + +#if defined(PSA_WANT_ALG_ECDSA) && defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) && \ + defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) +#define PSA_HAVE_FULL_ECDSA 1 +#endif + +#if defined(PSA_WANT_ALG_JPAKE) && defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) && \ + defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) +#define PSA_HAVE_FULL_JPAKE 1 +#endif + +/* These features are always enabled. */ +#define PSA_WANT_KEY_TYPE_DERIVE 1 +#define PSA_WANT_KEY_TYPE_PASSWORD 1 +#define PSA_WANT_KEY_TYPE_PASSWORD_HASH 1 +#define PSA_WANT_KEY_TYPE_RAW_DATA 1 + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CONFIG_PSA_H */ 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..91a9e7f --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/constant_time.h @@ -0,0 +1,46 @@ +/** + * 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..8d28150 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ctr_drbg.h @@ -0,0 +1,578 @@ +/** + * \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 mbedtls_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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#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 mbedtls_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 MBEDTLS_PRIVATE(counter)[16]; /*!< The counter (V). */ + int MBEDTLS_PRIVATE(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 MBEDTLS_PRIVATE(prediction_resistance); /*!< This determines whether prediction + resistance is enabled, that is + whether to systematically reseed before + each random generation. */ + size_t MBEDTLS_PRIVATE(entropy_len); /*!< The amount of entropy grabbed on each + seed or reseed operation, in bytes. */ + int MBEDTLS_PRIVATE(reseed_interval); /*!< The reseed interval. + * This is the maximum number of requests + * that can be made between reseedings. */ + + mbedtls_aes_context MBEDTLS_PRIVATE(aes_ctx); /*!< The AES context. */ + + /* + * Callbacks (Entropy) + */ + int(*MBEDTLS_PRIVATE(f_entropy))(void *, unsigned char *, size_t); + /*!< The entropy callback function. */ + + void *MBEDTLS_PRIVATE(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 MBEDTLS_PRIVATE(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(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_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..2b0d00e --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/debug.h @@ -0,0 +1,312 @@ +/** + * \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 + +#include "mbedtls/build_info.h" + +#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) +#if !defined(MBEDTLS_X509_REMOVE_INFO) +#define MBEDTLS_SSL_DEBUG_CRT(level, text, crt) \ + mbedtls_debug_print_crt(ssl, level, __FILE__, __LINE__, text, crt) +#else +#define MBEDTLS_SSL_DEBUG_CRT(level, text, crt) do { } while (0) +#endif /* MBEDTLS_X509_REMOVE_INFO */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#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) && !defined(MBEDTLS_X509_REMOVE_INFO) +/** + * \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..f445102 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/des.h @@ -0,0 +1,397 @@ +/** + * \file des.h + * + * \brief DES block cipher + * + * \warning DES/3DES are considered weak ciphers and their 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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" +#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 + +#define MBEDTLS_DES_KEY_SIZE 8 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_DES_ALT) +// Regular implementation +// + +/** + * \brief DES context structure + * + * \warning DES/3DES are considered weak ciphers and their use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +typedef struct mbedtls_des_context { + uint32_t MBEDTLS_PRIVATE(sk)[32]; /*!< DES subkeys */ +} +mbedtls_des_context; + +/** + * \brief Triple-DES context structure + * + * \warning DES/3DES are considered weak ciphers and their use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +typedef struct mbedtls_des3_context { + uint32_t MBEDTLS_PRIVATE(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/3DES are considered weak ciphers and their 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/3DES are considered weak ciphers and their 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 + * + * \warning DES/3DES are considered weak ciphers and their use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +void mbedtls_des3_init(mbedtls_des3_context *ctx); + +/** + * \brief Clear Triple-DES context + * + * \param ctx DES3 context to be cleared + * + * \warning DES/3DES are considered weak ciphers and their use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +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/3DES are considered weak ciphers and their 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/3DES are considered weak ciphers and their 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/3DES are considered weak ciphers and their 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/3DES are considered weak ciphers and their 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/3DES are considered weak ciphers and their 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 + * + * \warning DES/3DES are considered weak ciphers and their use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +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 + * + * \warning DES/3DES are considered weak ciphers and their use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +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 + * + * \warning DES/3DES are considered weak ciphers and their use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +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 + * + * \warning DES/3DES are considered weak ciphers and their use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +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/3DES are considered weak ciphers and their 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/3DES are considered weak ciphers and their 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 + * + * \warning DES/3DES are considered weak ciphers and their use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +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 + * + * \warning DES/3DES are considered weak ciphers and their use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +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/3DES are considered weak ciphers and their 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..6ffe681 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/dhm.h @@ -0,0 +1,984 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" +#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 +/** Setting the modulus and generator failed. */ +#define MBEDTLS_ERR_DHM_SET_GROUP_FAILED -0x3580 + +/** Which parameter to access in mbedtls_dhm_get_value(). */ +typedef enum { + MBEDTLS_DHM_PARAM_P, /*!< The prime modulus. */ + MBEDTLS_DHM_PARAM_G, /*!< The generator. */ + MBEDTLS_DHM_PARAM_X, /*!< Our secret value. */ + MBEDTLS_DHM_PARAM_GX, /*!< Our public key = \c G^X mod \c P. */ + MBEDTLS_DHM_PARAM_GY, /*!< The public key of the peer = \c G^Y mod \c P. */ + MBEDTLS_DHM_PARAM_K, /*!< The shared secret = \c G^(XY) mod \c P. */ +} mbedtls_dhm_parameter; + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_DHM_ALT) + +/** + * \brief The DHM context structure. + */ +typedef struct mbedtls_dhm_context { + mbedtls_mpi MBEDTLS_PRIVATE(P); /*!< The prime modulus. */ + mbedtls_mpi MBEDTLS_PRIVATE(G); /*!< The generator. */ + mbedtls_mpi MBEDTLS_PRIVATE(X); /*!< Our secret value. */ + mbedtls_mpi MBEDTLS_PRIVATE(GX); /*!< Our public key = \c G^X mod \c P. */ + mbedtls_mpi MBEDTLS_PRIVATE(GY); /*!< The public key of the peer = \c G^Y mod \c P. */ + mbedtls_mpi MBEDTLS_PRIVATE(K); /*!< The shared secret = \c G^(XY) mod \c P. */ + mbedtls_mpi MBEDTLS_PRIVATE(RP); /*!< The cached value = \c R^2 mod \c P. */ + mbedtls_mpi MBEDTLS_PRIVATE(Vi); /*!< The blinding value. */ + mbedtls_mpi MBEDTLS_PRIVATE(Vf); /*!< The unblinding value. */ + mbedtls_mpi MBEDTLS_PRIVATE(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. Must not be \c NULL. Used for + * blinding. + * \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_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 returns the size of the prime modulus in bits. + * + * \param ctx The DHM context to query. + * + * \return The size of the prime modulus in bits, + * i.e. the number n such that 2^(n-1) <= P < 2^n. + */ +size_t mbedtls_dhm_get_bitlen(const mbedtls_dhm_context *ctx); + +/** + * \brief This function returns the size of the prime modulus in bytes. + * + * \param ctx The DHM context to query. + * + * \return The size of the prime modulus in bytes, + * i.e. the number n such that 2^(8*(n-1)) <= P < 2^(8*n). + */ +size_t mbedtls_dhm_get_len(const mbedtls_dhm_context *ctx); + +/** + * \brief This function copies a parameter of a DHM key. + * + * \param ctx The DHM context to query. + * \param param The parameter to copy. + * \param dest The MPI object to copy the value into. It must be + * initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_DHM_BAD_INPUT_DATA if \p field is invalid. + * \return An \c MBEDTLS_ERR_MPI_XXX error code if the copy fails. + */ +int mbedtls_dhm_get_value(const mbedtls_dhm_context *ctx, + mbedtls_dhm_parameter param, + mbedtls_mpi *dest); + +/** + * \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). + * + */ + +/* + * 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..67c94f0 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecdh.h @@ -0,0 +1,453 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include "mbedtls/ecp.h" + +/* + * Mbed TLS supports two formats for ECDH contexts (#mbedtls_ecdh_context + * defined in `ecdh.h`). For most applications, the choice of format makes + * no difference, since all library functions can work with either format, + * except that the new format is incompatible with MBEDTLS_ECP_RESTARTABLE. + + * The new format used when this option is disabled is smaller + * (56 bytes on a 32-bit platform). In future versions of the library, it + * will support alternative implementations of ECDH operations. + * The new format is incompatible with applications that access + * context fields directly and with restartable ECP operations. + */ + +#if defined(MBEDTLS_ECP_RESTARTABLE) +#define MBEDTLS_ECDH_LEGACY_CONTEXT +#else +#undef MBEDTLS_ECDH_LEGACY_CONTEXT +#endif + +#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 MBEDTLS_PRIVATE(grp); /*!< The elliptic curve used. */ + mbedtls_mpi MBEDTLS_PRIVATE(d); /*!< The private key. */ + mbedtls_ecp_point MBEDTLS_PRIVATE(Q); /*!< The public key. */ + mbedtls_ecp_point MBEDTLS_PRIVATE(Qp); /*!< The value of the public key of the peer. */ + mbedtls_mpi MBEDTLS_PRIVATE(z); /*!< The shared secret. */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_ctx MBEDTLS_PRIVATE(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 MBEDTLS_PRIVATE(grp); /*!< The elliptic curve used. */ + mbedtls_mpi MBEDTLS_PRIVATE(d); /*!< The private key. */ + mbedtls_ecp_point MBEDTLS_PRIVATE(Q); /*!< The public key. */ + mbedtls_ecp_point MBEDTLS_PRIVATE(Qp); /*!< The value of the public key of the peer. */ + mbedtls_mpi MBEDTLS_PRIVATE(z); /*!< The shared secret. */ + int MBEDTLS_PRIVATE(point_format); /*!< The format of point export in TLS messages. */ + mbedtls_ecp_point MBEDTLS_PRIVATE(Vi); /*!< The blinding value. */ + mbedtls_ecp_point MBEDTLS_PRIVATE(Vf); /*!< The unblinding value. */ + mbedtls_mpi MBEDTLS_PRIVATE(_d); /*!< The previous \p d. */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + int MBEDTLS_PRIVATE(restart_enabled); /*!< The flag for restartable mode. */ + mbedtls_ecp_restart_ctx MBEDTLS_PRIVATE(rs); /*!< The restart context for EC computations. */ +#endif /* MBEDTLS_ECP_RESTARTABLE */ +#else + uint8_t MBEDTLS_PRIVATE(point_format); /*!< The format of point export in TLS messages + as defined in RFC 4492. */ + mbedtls_ecp_group_id MBEDTLS_PRIVATE(grp_id);/*!< The elliptic curve used. */ + mbedtls_ecdh_variant MBEDTLS_PRIVATE(var); /*!< The ECDH implementation/structure used. */ + union { + mbedtls_ecdh_context_mbed MBEDTLS_PRIVATE(mbed_ecdh); +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) + mbedtls_ecdh_context_everest MBEDTLS_PRIVATE(everest_ecdh); +#endif + } MBEDTLS_PRIVATE(ctx); /*!< Implementation-specific context. The + context in use is specified by the \c var + field. */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + uint8_t MBEDTLS_PRIVATE(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 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 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 to use. This must not be \c NULL. + * \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..c5d9701 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecdsa.h @@ -0,0 +1,681 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#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. + * + * \note pk_wrap module assumes that "ecdsa_context" is identical + * to "ecp_keypair" (see for example structure + * "mbedtls_eckey_info" where ECDSA sign/verify functions + * are used also for EC key) + */ +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 MBEDTLS_PRIVATE(ecp); /*!< base context for ECP restart and + shared administrative info */ + mbedtls_ecdsa_restart_ver_ctx *MBEDTLS_PRIVATE(ver); /*!< ecdsa_verify() sub-context */ + mbedtls_ecdsa_restart_sig_ctx *MBEDTLS_PRIVATE(sig); /*!< ecdsa_sign() sub-context */ +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + mbedtls_ecdsa_restart_det_ctx *MBEDTLS_PRIVATE(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_ext() 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) +/** + * \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 */ + +#if !defined(MBEDTLS_ECDSA_SIGN_ALT) +/** + * \brief This function computes the ECDSA signature of a + * previously-hashed message, in a restartable way. + * + * \note The deterministic version implemented in + * mbedtls_ecdsa_sign_det_restartable() is usually + * preferred. + * + * \note This function is like \c mbedtls_ecdsa_sign() but + * it can return early and restart according to the + * limit set with \c mbedtls_ecp_set_max_ops() to + * reduce blocking. + * + * \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 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. + * \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. + * \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_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); + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + +/** + * \brief This function computes the ECDSA signature of a + * previously-hashed message, in a restartable way. + * + * \note This function is like \c + * mbedtls_ecdsa_sign_det_ext() but it can return + * early and restart according to the limit set with + * \c mbedtls_ecp_set_max_ops() to reduce blocking. + * + * \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 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. + * \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_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); + +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + +#endif /* !MBEDTLS_ECDSA_SIGN_ALT */ + +/** + * \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 An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX + * error code on failure. + */ +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); + +#if !defined(MBEDTLS_ECDSA_VERIFY_ALT) +/** + * \brief This function verifies the ECDSA signature of a + * previously-hashed message, in a restartable manner + * + * \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. + * \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 An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX + * error code on failure. + */ +int mbedtls_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); + +#endif /* !MBEDTLS_ECDSA_VERIFY_ALT */ + +/** + * \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 sig_size The size of the \p sig buffer in bytes. + * \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 sig_size, 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 sig_size The size of the \p sig buffer in bytes. + * \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 sig_size, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecdsa_restart_ctx *rs_ctx); + +/** + * \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..a63bb32 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecjpake.h @@ -0,0 +1,309 @@ +/** + * \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 +#include "mbedtls/private_access.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. + */ +#include "mbedtls/build_info.h" + +#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 { + mbedtls_md_type_t MBEDTLS_PRIVATE(md_type); /**< Hash to use */ + mbedtls_ecp_group MBEDTLS_PRIVATE(grp); /**< Elliptic curve */ + mbedtls_ecjpake_role MBEDTLS_PRIVATE(role); /**< Are we client or server? */ + int MBEDTLS_PRIVATE(point_format); /**< Format for point export */ + + mbedtls_ecp_point MBEDTLS_PRIVATE(Xm1); /**< My public key 1 C: X1, S: X3 */ + mbedtls_ecp_point MBEDTLS_PRIVATE(Xm2); /**< My public key 2 C: X2, S: X4 */ + mbedtls_ecp_point MBEDTLS_PRIVATE(Xp1); /**< Peer public key 1 C: X3, S: X1 */ + mbedtls_ecp_point MBEDTLS_PRIVATE(Xp2); /**< Peer public key 2 C: X4, S: X2 */ + mbedtls_ecp_point MBEDTLS_PRIVATE(Xp); /**< Peer public key C: Xs, S: Xc */ + + mbedtls_mpi MBEDTLS_PRIVATE(xm1); /**< My private key 1 C: x1, S: x3 */ + mbedtls_mpi MBEDTLS_PRIVATE(xm2); /**< My private key 2 C: x2, S: x4 */ + + mbedtls_mpi MBEDTLS_PRIVATE(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 not empty 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 Set the point format for future reads and writes. + * + * \param ctx The ECJPAKE context to configure. + * \param point_format The point format to use: + * #MBEDTLS_ECP_PF_UNCOMPRESSED (default) + * or #MBEDTLS_ECP_PF_COMPRESSED. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p point_format + * is invalid. + */ +int mbedtls_ecjpake_set_point_format(mbedtls_ecjpake_context *ctx, + int point_format); + +/** + * \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 Write the shared key material to be passed to a Key + * Derivation Function as described in RFC8236. + * + * \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_write_shared_key(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..08a5f04 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecp.h @@ -0,0 +1,1341 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#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 +/** 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 below. + * - Add the corresponding MBEDTLS_ECP_DP_xxx_ENABLED macro definition to + * mbedtls_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. + * - Add the curve to applicable presets in ssl_tls.c. + */ +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. + */ +#define MBEDTLS_ECP_DP_MAX 14 + +/* + * 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 modulus types + */ +typedef enum { + MBEDTLS_ECP_MOD_NONE = 0, + MBEDTLS_ECP_MOD_COORDINATE, + MBEDTLS_ECP_MOD_SCALAR +} mbedtls_ecp_modulus_type; + +/** + * Curve information, for use by other modules. + * + * The fields of this structure are part of the public API and can be + * accessed directly by applications. Future versions of the library may + * add extra fields or reorder existing fields. + */ +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 MBEDTLS_PRIVATE(X); /*!< The X coordinate of the ECP point. */ + mbedtls_mpi MBEDTLS_PRIVATE(Y); /*!< The Y coordinate of the ECP point. */ + mbedtls_mpi MBEDTLS_PRIVATE(Z); /*!< The Z coordinate of the ECP point. */ +} +mbedtls_ecp_point; + +#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 of the ECP module must obey the + * following constraints. + * * Group IDs must be distinct: if two group structures have + * the same ID, then they must be identical. + * * The fields \c id, \c P, \c A, \c B, \c G, \c N, + * \c pbits and \c nbits must have the same type and semantics + * as in the built-in implementation. + * They must be available for reading, but direct modification + * of these fields does not need to be supported. + * They do not need to be at the same offset in the structure. + */ +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. */ + /* End of public fields */ + + unsigned int MBEDTLS_PRIVATE(h); /*!< \internal 1 if the constants are static. */ + int(*MBEDTLS_PRIVATE(modp))(mbedtls_mpi *); /*!< The function for fast pseudo-reduction + mod \p P (see above).*/ + int(*MBEDTLS_PRIVATE(t_pre))(mbedtls_ecp_point *, void *); /*!< Unused. */ + int(*MBEDTLS_PRIVATE(t_post))(mbedtls_ecp_point *, void *); /*!< Unused. */ + void *MBEDTLS_PRIVATE(t_data); /*!< Unused. */ + mbedtls_ecp_point *MBEDTLS_PRIVATE(T); /*!< Pre-computed points for ecp_mul_comb(). */ + size_t MBEDTLS_PRIVATE(T_size); /*!< The number of dynamic allocated 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 mbedtls_config.h, or define them using the compiler command line. + * \{ + */ + +#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 code size 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. + * + * For each n-bit Short Weierstrass curve that is enabled, this adds 4n bytes + * of code size if n < 384 and 8n otherwise. + * + * Change this value to 0 to reduce code size. + */ +#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 */ + +/** + * The maximum size of the groups, that is, of \c N and \c P. + */ +#if !defined(MBEDTLS_ECP_C) +/* Dummy definition to help code that has optional ECP support and + * defines an MBEDTLS_ECP_MAX_BYTES-sized array unconditionally. */ +#define MBEDTLS_ECP_MAX_BITS 1 +/* Note: the curves must be listed in DECREASING size! */ +#elif defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS 521 +#elif defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS 512 +#elif defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) +#define MBEDTLS_ECP_MAX_BITS 448 +#elif defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS 384 +#elif defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS 384 +#elif defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS 256 +#elif defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS 256 +#elif defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS 256 +#elif defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +#define MBEDTLS_ECP_MAX_BITS 255 +#elif defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS 225 // n is slightly above 2^224 +#elif defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS 224 +#elif defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS 192 +#elif defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS 192 +#else +#error "Missing definition of MBEDTLS_ECP_MAX_BITS" +#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_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 MBEDTLS_PRIVATE(ops_done); /*!< current ops count */ + unsigned MBEDTLS_PRIVATE(depth); /*!< call depth (0 = top-level) */ + mbedtls_ecp_restart_mul_ctx *MBEDTLS_PRIVATE(rsm); /*!< ecp_mul_comb() sub-context */ + mbedtls_ecp_restart_muladd_ctx *MBEDTLS_PRIVATE(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 MBEDTLS_PRIVATE(grp); /*!< Elliptic curve and base point */ + mbedtls_mpi MBEDTLS_PRIVATE(d); /*!< our secret value */ + mbedtls_ecp_point MBEDTLS_PRIVATE(Q); /*!< our public value */ +} +mbedtls_ecp_keypair; + +/** + * The uncompressed point format for Short Weierstrass curves + * (MBEDTLS_ECP_DP_SECP_XXX and MBEDTLS_ECP_DP_BP_XXX). + */ +#define MBEDTLS_ECP_PF_UNCOMPRESSED 0 +/** + * The compressed point format for Short Weierstrass curves + * (MBEDTLS_ECP_DP_SECP_XXX and MBEDTLS_ECP_DP_BP_XXX). + * + * \warning While this format is supported for all concerned curves for + * writing, when it comes to parsing, it is not supported for all + * curves. Specifically, parsing compressed points on + * MBEDTLS_ECP_DP_SECP224R1 and MBEDTLS_ECP_DP_SECP224K1 is not + * supported. + */ +#define MBEDTLS_ECP_PF_COMPRESSED 1 + +/* + * 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). + * + * \warning Using the PSA interruptible interfaces with keys in local + * storage and no accelerator driver will also call this + * function to set the values specified via those interfaces, + * overwriting values previously set. Care should be taken if + * mixing these two interfaces. + * + * \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. + * + * \note For compressed points, see #MBEDTLS_ECP_PF_COMPRESSED for + * limitations. + * + * \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. It also uses + * \p f_rng to randomize some intermediate results. + * + * \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 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. + * + * \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 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 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. + * \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. + * + * \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, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); + +/** + * \brief This function exports generic key-pair parameters. + * + * \param key The key pair to export from. + * \param grp Slot for exported ECP group. + * It must point to an initialized ECP group. + * \param d Slot for the exported secret value. + * It must point to an initialized mpi. + * \param Q Slot for the exported public value. + * It must point to an initialized ECP point. + * + * \return \c 0 on success, + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if key id doesn't + * correspond to a known group. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_export(const mbedtls_ecp_keypair *key, mbedtls_ecp_group *grp, + mbedtls_mpi *d, mbedtls_ecp_point *Q); + +#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/entropy.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/entropy.h new file mode 100644 index 0000000..2c8b750 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/entropy.h @@ -0,0 +1,291 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#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 + + +/** 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 mbedtls_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 MBEDTLS_PRIVATE(f_source); /**< The entropy source callback */ + void *MBEDTLS_PRIVATE(p_source); /**< The callback data pointer */ + size_t MBEDTLS_PRIVATE(size); /**< Amount received in bytes */ + size_t MBEDTLS_PRIVATE(threshold); /**< Minimum bytes required before release */ + int MBEDTLS_PRIVATE(strong); /**< Is the source strong? */ +} +mbedtls_entropy_source_state; + +/** + * \brief Entropy context structure + */ +typedef struct mbedtls_entropy_context { + int MBEDTLS_PRIVATE(accumulator_started); /* 0 after init. + * 1 after the first update. + * -1 after free. */ +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + mbedtls_sha512_context MBEDTLS_PRIVATE(accumulator); +#elif defined(MBEDTLS_ENTROPY_SHA256_ACCUMULATOR) + mbedtls_sha256_context MBEDTLS_PRIVATE(accumulator); +#endif + int MBEDTLS_PRIVATE(source_count); /* Number of entries used in source. */ + mbedtls_entropy_source_state MBEDTLS_PRIVATE(source)[MBEDTLS_ENTROPY_MAX_SOURCES]; +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t MBEDTLS_PRIVATE(mutex); /*!< mutex */ +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) + int MBEDTLS_PRIVATE(initial_entropy_run); +#endif +} +mbedtls_entropy_context; + +#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 + +/** + * \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/error.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/error.h new file mode 100644 index 0000000..23a83f2 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/error.h @@ -0,0 +1,212 @@ +/** + * \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 + +#include "mbedtls/build_info.h" + +#include + +/** + * 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-0x0016 0x0013-0x0013 + * THREADING 3 0x001A-0x001E + * AES 5 0x0020-0x0022 0x0021-0x0025 + * CAMELLIA 3 0x0024-0x0026 0x0027-0x0027 + * 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 + * 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 + * LMS 5 0x0011-0x0019 + * + * 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) + * PKCS7 5 12 (Started from 0x5300) + * SSL 5 2 (Started from 0x5F00) + * CIPHER 6 8 (Started from 0x6080) + * SSL 6 22 (Started from top, plus 0x6000) + * SSL 7 20 (Started from 0x7000, gaps at + * 0x7380, 0x7900-0x7980, 0x7A80-0x7E80) + * + * 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 + +/** 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 + +/** + * \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..c3343e6 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/gcm.h @@ -0,0 +1,382 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#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 +/** Bad input parameters to function. */ +#define MBEDTLS_ERR_GCM_BAD_INPUT -0x0014 +/** An output buffer is too small. */ +#define MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL -0x0016 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_GCM_ALT) + +/** + * \brief The GCM context structure. + */ +typedef struct mbedtls_gcm_context { + mbedtls_cipher_context_t MBEDTLS_PRIVATE(cipher_ctx); /*!< The cipher context used. */ + uint64_t MBEDTLS_PRIVATE(HL)[16]; /*!< Precalculated HTable low. */ + uint64_t MBEDTLS_PRIVATE(HH)[16]; /*!< Precalculated HTable high. */ + uint64_t MBEDTLS_PRIVATE(len); /*!< The total length of the encrypted data. */ + uint64_t MBEDTLS_PRIVATE(add_len); /*!< The total length of the additional data. */ + unsigned char MBEDTLS_PRIVATE(base_ectr)[16]; /*!< The first ECTR for tag. */ + unsigned char MBEDTLS_PRIVATE(y)[16]; /*!< The Y working value. */ + unsigned char MBEDTLS_PRIVATE(buf)[16]; /*!< The buf working value. */ + int MBEDTLS_PRIVATE(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. + * + * \return \c 0 on success. + */ +int mbedtls_gcm_starts(mbedtls_gcm_context *ctx, + int mode, + const unsigned char *iv, + size_t iv_len); + +/** + * \brief This function feeds an input buffer as associated data + * (authenticated but not encrypted data) in a GCM + * encryption or decryption operation. + * + * Call this function after mbedtls_gcm_starts() to pass + * the associated data. If the associated data is empty, + * you do not need to call this function. You may not + * call this function after calling mbedtls_cipher_update(). + * + * \param ctx The GCM context. This must have been started with + * mbedtls_gcm_starts() and must not have yet received + * any input with mbedtls_gcm_update(). + * \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_update_ad(mbedtls_gcm_context *ctx, + const unsigned char *add, + size_t add_len); + +/** + * \brief This function feeds an input buffer into an ongoing GCM + * encryption or decryption operation. + * + * You may call this function zero, one or more times + * to pass successive parts of the input: the plaintext to + * encrypt, or the ciphertext (not including the tag) to + * decrypt. After the last part of the input, call + * mbedtls_gcm_finish(). + * + * This function may produce output in one of the following + * ways: + * - Immediate output: the output length is always equal + * to the input length. + * - Buffered output: the output consists of a whole number + * of 16-byte blocks. If the total input length so far + * (not including associated data) is 16 \* *B* + *A* + * with *A* < 16 then the total output length is 16 \* *B*. + * + * In particular: + * - It is always correct to call this function with + * \p output_size >= \p input_length + 15. + * - If \p input_length is a multiple of 16 for all the calls + * to this function during an operation, then it is + * correct to use \p output_size = \p input_length. + * + * \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 input The buffer holding the input data. If \p input_length + * is greater than zero, this must be a readable buffer + * of at least \p input_length bytes. + * \param input_length The length of the input data in bytes. + * \param output The buffer for the output data. If \p output_size + * is greater than zero, this must be a writable buffer of + * of at least \p output_size bytes. + * \param output_size The size of the output buffer in bytes. + * See the function description regarding the output size. + * \param output_length On success, \p *output_length contains the actual + * length of the output written in \p output. + * On failure, the content of \p *output_length is + * unspecified. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure: + * total input length too long, + * unsupported input/output buffer overlap detected, + * or \p output_size too small. + */ +int mbedtls_gcm_update(mbedtls_gcm_context *ctx, + const unsigned char *input, size_t input_length, + unsigned char *output, size_t output_size, + size_t *output_length); + +/** + * \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. + * \param output The buffer for the final output. + * If \p output_size is nonzero, this must be a writable + * buffer of at least \p output_size bytes. + * \param output_size The size of the \p output buffer in bytes. + * This must be large enough for the output that + * mbedtls_gcm_update() has not produced. In particular: + * - If mbedtls_gcm_update() produces immediate output, + * or if the total input size is a multiple of \c 16, + * then mbedtls_gcm_finish() never produces any output, + * so \p output_size can be \c 0. + * - \p output_size never needs to be more than \c 15. + * \param output_length On success, \p *output_length contains the actual + * length of the output written in \p output. + * On failure, the content of \p *output_length is + * unspecified. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure: + * invalid value of \p tag_len, + * or \p output_size too small. + */ +int mbedtls_gcm_finish(mbedtls_gcm_context *ctx, + unsigned char *output, size_t output_size, + size_t *output_length, + 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/hkdf.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/hkdf.h new file mode 100644 index 0000000..699c6d9 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/hkdf.h @@ -0,0 +1,136 @@ +/** + * \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 + +#include "mbedtls/build_info.h" + +#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..4ca6b08 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/hmac_drbg.h @@ -0,0 +1,446 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#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 mbedtls_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 MBEDTLS_PRIVATE(md_ctx); /*!< HMAC context (inc. K) */ + unsigned char MBEDTLS_PRIVATE(V)[MBEDTLS_MD_MAX_SIZE]; /*!< V in the spec */ + int MBEDTLS_PRIVATE(reseed_counter); /*!< reseed counter */ + + /* Administrative state */ + size_t MBEDTLS_PRIVATE(entropy_len); /*!< entropy bytes grabbed on each (re)seed */ + int MBEDTLS_PRIVATE(prediction_resistance); /*!< enable prediction resistance (Automatic + reseed before every random generation) */ + int MBEDTLS_PRIVATE(reseed_interval); /*!< reseed interval */ + + /* Callbacks */ + int(*MBEDTLS_PRIVATE(f_entropy))(void *, unsigned char *, size_t); /*!< entropy function */ + void *MBEDTLS_PRIVATE(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 MBEDTLS_PRIVATE(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(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_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/legacy_or_psa.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/legacy_or_psa.h new file mode 100644 index 0000000..e9bdb77 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/legacy_or_psa.h @@ -0,0 +1,215 @@ +/** + * Macros to express dependencies for code and tests that may use either the + * legacy API or PSA in various builds. This whole header file is currently + * for internal use only and both the header file and the macros it defines + * may change or be removed without notice. + */ +/* + * 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. + */ + +/* + * Note: applications that are targeting a specific configuration do not need + * to use these macros; instead they should directly use the functions they + * know are available in their configuration. + * + * Note: code that is purely based on PSA Crypto (psa_xxx() functions) + * does not need to use these macros; instead it should use the relevant + * PSA_WANT_xxx macros. + * + * Note: code that is purely based on the legacy crypto APIs (mbedtls_xxx()) + * does not need to use these macros; instead it should use the relevant + * MBEDTLS_xxx macros. + * + * These macros are for code that wants to use and will do so + * using or PSA depending on , where: + * - will generally be an algorithm (SHA-256, ECDH) but may + * also be a key type (AES, RSA, EC) or domain parameters (elliptic curve); + * - will be either: + * - low-level module API (aes.h, sha256.h), or + * - an abstraction layer (md.h, cipher.h); + * - will be either: + * - depending on what's available in the build: + * legacy API used if available, PSA otherwise + * (this is done to ensure backwards compatibility); or + * - depending on whether MBEDTLS_USE_PSA_CRYPTO is defined. + * + * Examples: + * - TLS 1.2 will compute hashes using either mbedtls_md_xxx() (and + * mbedtls_sha256_xxx()) or psa_aead_xxx() depending on whether + * MBEDTLS_USE_PSA_CRYPTO is defined; + * - RSA PKCS#1 v2.1 will compute hashes (for padding) using either + * `mbedtls_md()` if it's available, or `psa_hash_compute()` otherwise; + * - PEM decoding of PEM-encrypted keys will compute MD5 hashes using either + * `mbedtls_md5_xxx()` if it's available, or `psa_hash_xxx()` otherwise. + * + * Note: the macros are essential to express test dependencies. Inside code, + * we could instead just use the equivalent pre-processor condition, but + * that's not possible in test dependencies where we need a single macro. + * Hopefully, using these macros in code will also help with consistency. + * + * The naming scheme for these macros is: + * MBEDTLS_HAS_feature_VIA_legacy_OR_PSA(_condition) + * where: + * - feature is expressed the same way as in PSA_WANT_xxx macros, for example: + * KEY_TYPE_AES, ALG_SHA_256, ECC_SECP_R1_256; + * - legacy is either LOWLEVEL or the name of the layer: MD, CIPHER; + * - condition is omitted if it's based on availability, else it's + * BASED_ON_USE_PSA. + * + * Coming back to the examples above: + * - TLS 1.2 will determine if it can use SHA-256 using + * MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA + * for the purposes of negotiation, and in test dependencies; + * - RSA PKCS#1 v2.1 tests that used SHA-256 will depend on + * MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA + * - PEM decoding code and its associated tests will depend on + * MBEDTLS_HAS_ALG_MD5_VIA_LOWLEVEL_OR_PSA + * + * Note: every time it's possible to use, say SHA-256, via the MD API, then + * it's also possible to use it via the low-level API. So, code that wants to + * use SHA-256 via both APIs only needs to depend on the MD macro. Also, it + * just so happens that all the code choosing which API to use based on + * MBEDTLS_USE_PSA_CRYPTO (X.509, TLS 1.2/shared), always uses the abstraction + * layer (sometimes in addition to the low-level API), so we don't need the + * MBEDTLS_HAS_feature_VIA_LOWLEVEL_OR_PSA_BASED_ON_USE_PSA macros. + * (PK, while obeying MBEDTLS_USE_PSA_CRYPTO, doesn't compute hashes itself, + * even less makes use of ciphers.) + * + * Note: the macros MBEDTLS_HAS_feature_VIA_LOWLEVEL_OR_PSA are the minimal + * condition for being able to use at all. As such, they should be + * used for guarding data about , such as OIDs or size. For example, + * OID values related to SHA-256 are only useful when SHA-256 can be used at + * least in some way. + */ + +#ifndef MBEDTLS_OR_PSA_HELPERS_H +#define MBEDTLS_OR_PSA_HELPERS_H + +#include "mbedtls/build_info.h" +#if defined(MBEDTLS_PSA_CRYPTO_C) +#include "psa/crypto.h" +#endif /* MBEDTLS_PSA_CRYPTO_C */ + +/* + * Hashes + */ + +/* Hashes using low-level or PSA based on availability */ +#if defined(MBEDTLS_MD5_C) || \ + (defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_ALG_MD5)) +#define MBEDTLS_HAS_ALG_MD5_VIA_LOWLEVEL_OR_PSA +#endif +#if defined(MBEDTLS_RIPEMD160_C) || \ + (defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_ALG_RIPEMD160)) +#define MBEDTLS_HAS_ALG_RIPEMD160_VIA_LOWLEVEL_OR_PSA +#endif +#if defined(MBEDTLS_SHA1_C) || \ + (defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_ALG_SHA_1)) +#define MBEDTLS_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA +#endif +#if defined(MBEDTLS_SHA224_C) || \ + (defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_ALG_SHA_224)) +#define MBEDTLS_HAS_ALG_SHA_224_VIA_LOWLEVEL_OR_PSA +#endif +#if defined(MBEDTLS_SHA256_C) || \ + (defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_ALG_SHA_256)) +#define MBEDTLS_HAS_ALG_SHA_256_VIA_LOWLEVEL_OR_PSA +#endif +#if defined(MBEDTLS_SHA384_C) || \ + (defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_ALG_SHA_384)) +#define MBEDTLS_HAS_ALG_SHA_384_VIA_LOWLEVEL_OR_PSA +#endif +#if defined(MBEDTLS_SHA512_C) || \ + (defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_ALG_SHA_512)) +#define MBEDTLS_HAS_ALG_SHA_512_VIA_LOWLEVEL_OR_PSA +#endif + +/* Hashes using MD or PSA based on availability */ +#if (defined(MBEDTLS_MD_C) && defined(MBEDTLS_MD5_C)) || \ + (!defined(MBEDTLS_MD_C) && \ + defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_ALG_MD5)) +#define MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA +#endif +#if (defined(MBEDTLS_MD_C) && defined(MBEDTLS_RIPEMD160_C)) || \ + (!defined(MBEDTLS_MD_C) && \ + defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_ALG_RIPEMD160)) +#define MBEDTLS_HAS_ALG_RIPEMD160_VIA_MD_OR_PSA +#endif +#if (defined(MBEDTLS_MD_C) && defined(MBEDTLS_SHA1_C)) || \ + (!defined(MBEDTLS_MD_C) && \ + defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_ALG_SHA_1)) +#define MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA +#endif +#if (defined(MBEDTLS_MD_C) && defined(MBEDTLS_SHA224_C)) || \ + (!defined(MBEDTLS_MD_C) && \ + defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_ALG_SHA_224)) +#define MBEDTLS_HAS_ALG_SHA_224_VIA_MD_OR_PSA +#endif +#if (defined(MBEDTLS_MD_C) && defined(MBEDTLS_SHA256_C)) || \ + (!defined(MBEDTLS_MD_C) && \ + defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_ALG_SHA_256)) +#define MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA +#endif +#if (defined(MBEDTLS_MD_C) && defined(MBEDTLS_SHA384_C)) || \ + (!defined(MBEDTLS_MD_C) && \ + defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_ALG_SHA_384)) +#define MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA +#endif +#if (defined(MBEDTLS_MD_C) && defined(MBEDTLS_SHA512_C)) || \ + (!defined(MBEDTLS_MD_C) && \ + defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_ALG_SHA_512)) +#define MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA +#endif + +/* Hashes using MD or PSA based on MBEDTLS_USE_PSA_CRYPTO */ +#if (!defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_MD_C) && defined(MBEDTLS_MD5_C)) || \ + (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_MD5)) +#define MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA +#endif +#if (!defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_MD_C) && defined(MBEDTLS_RIPEMD160_C)) || \ + (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_RIPEMD160)) +#define MBEDTLS_HAS_ALG_RIPEMD160_VIA_MD_OR_PSA_BASED_ON_USE_PSA +#endif +#if (!defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_MD_C) && defined(MBEDTLS_SHA1_C)) || \ + (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_SHA_1)) +#define MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA +#endif +#if (!defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_MD_C) && defined(MBEDTLS_SHA224_C)) || \ + (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_SHA_224)) +#define MBEDTLS_HAS_ALG_SHA_224_VIA_MD_OR_PSA_BASED_ON_USE_PSA +#endif +#if (!defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_MD_C) && defined(MBEDTLS_SHA256_C)) || \ + (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_SHA_256)) +#define MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA +#endif +#if (!defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_MD_C) && defined(MBEDTLS_SHA384_C)) || \ + (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_SHA_384)) +#define MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA +#endif +#if (!defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_MD_C) && defined(MBEDTLS_SHA512_C)) || \ + (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_SHA_512)) +#define MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA +#endif + +#endif /* MBEDTLS_OR_PSA_HELPERS_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/lms.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/lms.h new file mode 100644 index 0000000..5c8df42 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/lms.h @@ -0,0 +1,452 @@ +/** + * \file lms.h + * + * \brief This file provides an API for the LMS post-quantum-safe stateful-hash + public-key signature scheme as defined in RFC8554 and NIST.SP.200-208. + * This implementation currently only supports a single parameter set + * MBEDTLS_LMS_SHA256_M32_H10 in order to reduce complexity. This is one + * of the signature schemes recommended by the IETF draft SUIT standard + * for IOT firmware upgrades (RFC9019). + */ +/* + * 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_LMS_H +#define MBEDTLS_LMS_H + +#include +#include + +#include "mbedtls/private_access.h" +#include "mbedtls/build_info.h" + +#define MBEDTLS_ERR_LMS_BAD_INPUT_DATA -0x0011 /**< Bad data has been input to an LMS function */ +#define MBEDTLS_ERR_LMS_OUT_OF_PRIVATE_KEYS -0x0013 /**< Specified LMS key has utilised all of its private keys */ +#define MBEDTLS_ERR_LMS_VERIFY_FAILED -0x0015 /**< LMS signature verification failed */ +#define MBEDTLS_ERR_LMS_ALLOC_FAILED -0x0017 /**< LMS failed to allocate space for a private key */ +#define MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL -0x0019 /**< Input/output buffer is too small to contain requited data */ + +/* Currently only defined for SHA256, 32 is the max hash output size */ +#define MBEDTLS_LMOTS_N_HASH_LEN_MAX (32u) +#define MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX (34u) +#define MBEDTLS_LMOTS_N_HASH_LEN(type) ((type) == MBEDTLS_LMOTS_SHA256_N32_W8 ? 32u : 0) +#define MBEDTLS_LMOTS_I_KEY_ID_LEN (16u) +#define MBEDTLS_LMOTS_Q_LEAF_ID_LEN (4u) +#define MBEDTLS_LMOTS_TYPE_LEN (4u) +#define MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(type) ((type) == MBEDTLS_LMOTS_SHA256_N32_W8 ? 34u : 0) +#define MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(type) (MBEDTLS_LMOTS_N_HASH_LEN(type)) + +#define MBEDTLS_LMOTS_SIG_LEN(type) (MBEDTLS_LMOTS_TYPE_LEN + \ + MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(type) + \ + (MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(type) * \ + MBEDTLS_LMOTS_N_HASH_LEN(type))) + + +#define MBEDTLS_LMS_TYPE_LEN (4) +#define MBEDTLS_LMS_H_TREE_HEIGHT(type) ((type) == MBEDTLS_LMS_SHA256_M32_H10 ? 10u : 0) + +/* The length of a hash output, Currently only implemented for SHA256. + * Max is 32 bytes. + */ +#define MBEDTLS_LMS_M_NODE_BYTES(type) ((type) == MBEDTLS_LMS_SHA256_M32_H10 ? 32 : 0) +#define MBEDTLS_LMS_M_NODE_BYTES_MAX 32 + +#define MBEDTLS_LMS_SIG_LEN(type, otstype) (MBEDTLS_LMOTS_Q_LEAF_ID_LEN + \ + MBEDTLS_LMOTS_SIG_LEN(otstype) + \ + MBEDTLS_LMS_TYPE_LEN + \ + (MBEDTLS_LMS_H_TREE_HEIGHT(type) * \ + MBEDTLS_LMS_M_NODE_BYTES(type))) + +#define MBEDTLS_LMS_PUBLIC_KEY_LEN(type) (MBEDTLS_LMS_TYPE_LEN + \ + MBEDTLS_LMOTS_TYPE_LEN + \ + MBEDTLS_LMOTS_I_KEY_ID_LEN + \ + MBEDTLS_LMS_M_NODE_BYTES(type)) + + +#ifdef __cplusplus +extern "C" { +#endif + +/** The Identifier of the LMS parameter set, as per + * https://www.iana.org/assignments/leighton-micali-signatures/leighton-micali-signatures.xhtml + * We are only implementing a subset of the types, particularly H10, for the sake of simplicity. + */ +typedef enum { + MBEDTLS_LMS_SHA256_M32_H10 = 0x6, +} mbedtls_lms_algorithm_type_t; + +/** The Identifier of the LMOTS parameter set, as per + * https://www.iana.org/assignments/leighton-micali-signatures/leighton-micali-signatures.xhtml. + * We are only implementing a subset of the types, particularly N32_W8, for the sake of simplicity. + */ +typedef enum { + MBEDTLS_LMOTS_SHA256_N32_W8 = 4 +} mbedtls_lmots_algorithm_type_t; + +/** LMOTS parameters structure. + * + * This contains the metadata associated with an LMOTS key, detailing the + * algorithm type, the key ID, and the leaf identifier should be key be part of + * a LMS key. + */ +typedef struct { + unsigned char MBEDTLS_PRIVATE(I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN]); /*!< The key + identifier. */ + unsigned char MBEDTLS_PRIVATE(q_leaf_identifier[MBEDTLS_LMOTS_Q_LEAF_ID_LEN]); /*!< Which + leaf of the LMS key this is. + 0 if the key is not part of an LMS key. */ + mbedtls_lmots_algorithm_type_t MBEDTLS_PRIVATE(type); /*!< The LM-OTS key type identifier as + per IANA. Only SHA256_N32_W8 is + currently supported. */ +} mbedtls_lmots_parameters_t; + +/** LMOTS public context structure. + * + * A LMOTS public key is a hash output, and the applicable parameter set. + * + * The context must be initialized before it is used. A public key must either + * be imported or generated from a private context. + * + * \dot + * digraph lmots_public_t { + * UNINITIALIZED -> INIT [label="init"]; + * HAVE_PUBLIC_KEY -> INIT [label="free"]; + * INIT -> HAVE_PUBLIC_KEY [label="import_public_key"]; + * INIT -> HAVE_PUBLIC_KEY [label="calculate_public_key from private key"]; + * HAVE_PUBLIC_KEY -> HAVE_PUBLIC_KEY [label="export_public_key"]; + * } + * \enddot + */ +typedef struct { + mbedtls_lmots_parameters_t MBEDTLS_PRIVATE(params); + unsigned char MBEDTLS_PRIVATE(public_key)[MBEDTLS_LMOTS_N_HASH_LEN_MAX]; + unsigned char MBEDTLS_PRIVATE(have_public_key); /*!< Whether the context contains a public key. + Boolean values only. */ +} mbedtls_lmots_public_t; + +#if defined(MBEDTLS_LMS_PRIVATE) +/** LMOTS private context structure. + * + * A LMOTS private key is one hash output for each of digit of the digest + + * checksum, and the applicable parameter set. + * + * The context must be initialized before it is used. A public key must either + * be imported or generated from a private context. + * + * \dot + * digraph lmots_public_t { + * UNINITIALIZED -> INIT [label="init"]; + * HAVE_PRIVATE_KEY -> INIT [label="free"]; + * INIT -> HAVE_PRIVATE_KEY [label="generate_private_key"]; + * HAVE_PRIVATE_KEY -> INIT [label="sign"]; + * } + * \enddot + */ +typedef struct { + mbedtls_lmots_parameters_t MBEDTLS_PRIVATE(params); + unsigned char MBEDTLS_PRIVATE(private_key)[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][ + MBEDTLS_LMOTS_N_HASH_LEN_MAX]; + unsigned char MBEDTLS_PRIVATE(have_private_key); /*!< Whether the context contains a private key. + Boolean values only. */ +} mbedtls_lmots_private_t; +#endif /* defined(MBEDTLS_LMS_PRIVATE) */ + + +/** LMS parameters structure. + * + * This contains the metadata associated with an LMS key, detailing the + * algorithm type, the type of the underlying OTS algorithm, and the key ID. + */ +typedef struct { + unsigned char MBEDTLS_PRIVATE(I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN]); /*!< The key + identifier. */ + mbedtls_lmots_algorithm_type_t MBEDTLS_PRIVATE(otstype); /*!< The LM-OTS key type identifier as + per IANA. Only SHA256_N32_W8 is + currently supported. */ + mbedtls_lms_algorithm_type_t MBEDTLS_PRIVATE(type); /*!< The LMS key type identifier as per + IANA. Only SHA256_M32_H10 is currently + supported. */ +} mbedtls_lms_parameters_t; + +/** LMS public context structure. + * + * A LMS public key is the hash output that is the root of the Merkle tree, and + * the applicable parameter set + * + * The context must be initialized before it is used. A public key must either + * be imported or generated from a private context. + * + * \dot + * digraph lms_public_t { + * UNINITIALIZED -> INIT [label="init"]; + * HAVE_PUBLIC_KEY -> INIT [label="free"]; + * INIT -> HAVE_PUBLIC_KEY [label="import_public_key"]; + * INIT -> HAVE_PUBLIC_KEY [label="calculate_public_key from private key"]; + * HAVE_PUBLIC_KEY -> HAVE_PUBLIC_KEY [label="export_public_key"]; + * } + * \enddot + */ +typedef struct { + mbedtls_lms_parameters_t MBEDTLS_PRIVATE(params); + unsigned char MBEDTLS_PRIVATE(T_1_pub_key)[MBEDTLS_LMS_M_NODE_BYTES_MAX]; /*!< The public key, in + the form of the Merkle tree root node. */ + unsigned char MBEDTLS_PRIVATE(have_public_key); /*!< Whether the context contains a public key. + Boolean values only. */ +} mbedtls_lms_public_t; + + +#if defined(MBEDTLS_LMS_PRIVATE) +/** LMS private context structure. + * + * A LMS private key is a set of LMOTS private keys, an index to the next usable + * key, and the applicable parameter set. + * + * The context must be initialized before it is used. A public key must either + * be imported or generated from a private context. + * + * \dot + * digraph lms_public_t { + * UNINITIALIZED -> INIT [label="init"]; + * HAVE_PRIVATE_KEY -> INIT [label="free"]; + * INIT -> HAVE_PRIVATE_KEY [label="generate_private_key"]; + * } + * \enddot + */ +typedef struct { + mbedtls_lms_parameters_t MBEDTLS_PRIVATE(params); + uint32_t MBEDTLS_PRIVATE(q_next_usable_key); /*!< The index of the next OTS key that has not + been used. */ + mbedtls_lmots_private_t *MBEDTLS_PRIVATE(ots_private_keys); /*!< The private key material. One OTS key + for each leaf node in the Merkle tree. NULL + when have_private_key is 0 and non-NULL otherwise. + is 2^MBEDTLS_LMS_H_TREE_HEIGHT(type) in length. */ + mbedtls_lmots_public_t *MBEDTLS_PRIVATE(ots_public_keys); /*!< The OTS key public keys, used to + build the Merkle tree. NULL + when have_private_key is 0 and + non-NULL otherwise. + Is 2^MBEDTLS_LMS_H_TREE_HEIGHT(type) + in length. */ + unsigned char MBEDTLS_PRIVATE(have_private_key); /*!< Whether the context contains a private key. + Boolean values only. */ +} mbedtls_lms_private_t; +#endif /* defined(MBEDTLS_LMS_PRIVATE) */ + +/** + * \brief This function initializes an LMS public context + * + * \param ctx The uninitialized LMS context that will then be + * initialized. + */ +void mbedtls_lms_public_init(mbedtls_lms_public_t *ctx); + +/** + * \brief This function uninitializes an LMS public context + * + * \param ctx The initialized LMS context that will then be + * uninitialized. + */ +void mbedtls_lms_public_free(mbedtls_lms_public_t *ctx); + +/** + * \brief This function imports an LMS public key into a + * public LMS context. + * + * \note Before this function is called, the context must + * have been initialized. + * + * \note See IETF RFC8554 for details of the encoding of + * this public key. + * + * \param ctx The initialized LMS context store the key in. + * \param key The buffer from which the key will be read. + * #MBEDTLS_LMS_PUBLIC_KEY_LEN bytes will be read from + * this. + * \param key_size The size of the key being imported. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lms_import_public_key(mbedtls_lms_public_t *ctx, + const unsigned char *key, size_t key_size); + +/** + * \brief This function exports an LMS public key from a + * LMS public context that already contains a public + * key. + * + * \note Before this function is called, the context must + * have been initialized and the context must contain + * a public key. + * + * \note See IETF RFC8554 for details of the encoding of + * this public key. + * + * \param ctx The initialized LMS public context that contains + * the public key. + * \param key The buffer into which the key will be output. Must + * be at least #MBEDTLS_LMS_PUBLIC_KEY_LEN in size. + * \param key_size The size of the key buffer. + * \param key_len If not NULL, will be written with the size of the + * key. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lms_export_public_key(const mbedtls_lms_public_t *ctx, + unsigned char *key, size_t key_size, + size_t *key_len); + +/** + * \brief This function verifies a LMS signature, using a + * LMS context that contains a public key. + * + * \note Before this function is called, the context must + * have been initialized and must contain a public key + * (either by import or generation). + * + * \param ctx The initialized LMS public context from which the + * public key will be read. + * \param msg The buffer from which the message will be read. + * \param msg_size The size of the message that will be read. + * \param sig The buf from which the signature will be read. + * #MBEDTLS_LMS_SIG_LEN bytes will be read from + * this. + * \param sig_size The size of the signature to be verified. + * + * \return \c 0 on successful verification. + * \return A non-zero error code on failure. + */ +int mbedtls_lms_verify(const mbedtls_lms_public_t *ctx, + const unsigned char *msg, size_t msg_size, + const unsigned char *sig, size_t sig_size); + +#if defined(MBEDTLS_LMS_PRIVATE) +/** + * \brief This function initializes an LMS private context + * + * \param ctx The uninitialized LMS private context that will + * then be initialized. */ +void mbedtls_lms_private_init(mbedtls_lms_private_t *ctx); + +/** + * \brief This function uninitializes an LMS private context + * + * \param ctx The initialized LMS private context that will then + * be uninitialized. + */ +void mbedtls_lms_private_free(mbedtls_lms_private_t *ctx); + +/** + * \brief This function generates an LMS private key, and + * stores in into an LMS private context. + * + * \warning This function is **not intended for use in + * production**, due to as-yet unsolved problems with + * handling stateful keys. The API for this function + * may change considerably in future versions. + * + * \note The seed must have at least 256 bits of entropy. + * + * \param ctx The initialized LMOTS context to generate the key + * into. + * \param type The LMS parameter set identifier. + * \param otstype The LMOTS parameter set identifier. + * \param f_rng The RNG function to be used to generate the key ID. + * \param p_rng The RNG context to be passed to f_rng + * \param seed The seed used to deterministically generate the + * key. + * \param seed_size The length of the seed. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lms_generate_private_key(mbedtls_lms_private_t *ctx, + mbedtls_lms_algorithm_type_t type, + mbedtls_lmots_algorithm_type_t otstype, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, const unsigned char *seed, + size_t seed_size); + +/** + * \brief This function calculates an LMS public key from a + * LMS context that already contains a private key. + * + * \note Before this function is called, the context must + * have been initialized and the context must contain + * a private key. + * + * \param ctx The initialized LMS public context to calculate the key + * from and store it into. + * + * \param priv_ctx The LMS private context to read the private key + * from. This must have been initialized and contain a + * private key. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lms_calculate_public_key(mbedtls_lms_public_t *ctx, + const mbedtls_lms_private_t *priv_ctx); + +/** + * \brief This function creates a LMS signature, using a + * LMS context that contains unused private keys. + * + * \warning This function is **not intended for use in + * production**, due to as-yet unsolved problems with + * handling stateful keys. The API for this function + * may change considerably in future versions. + * + * \note Before this function is called, the context must + * have been initialized and must contain a private + * key. + * + * \note Each of the LMOTS private keys inside a LMS private + * key can only be used once. If they are reused, then + * attackers may be able to forge signatures with that + * key. This is all handled transparently, but it is + * important to not perform copy operations on LMS + * contexts that contain private key material. + * + * \param ctx The initialized LMS private context from which the + * private key will be read. + * \param f_rng The RNG function to be used for signature + * generation. + * \param p_rng The RNG context to be passed to f_rng + * \param msg The buffer from which the message will be read. + * \param msg_size The size of the message that will be read. + * \param sig The buf into which the signature will be stored. + * Must be at least #MBEDTLS_LMS_SIG_LEN in size. + * \param sig_size The size of the buffer the signature will be + * written into. + * \param sig_len If not NULL, will be written with the size of the + * signature. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lms_sign(mbedtls_lms_private_t *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, const unsigned char *msg, + unsigned int msg_size, unsigned char *sig, size_t sig_size, + size_t *sig_len); +#endif /* defined(MBEDTLS_LMS_PRIVATE) */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_LMS_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/mbedtls_config.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/mbedtls_config.h new file mode 100644 index 0000000..5a4661c --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/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/md.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/md.h new file mode 100644 index 0000000..7bad24d --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/md.h @@ -0,0 +1,588 @@ +/** + * \file md.h + * + * \brief This file contains the generic functions for message-digest + * (hashing) and HMAC. + * + * \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 "mbedtls/private_access.h" + +#include + +#include "mbedtls/build_info.h" +#include "mbedtls/platform_util.h" + +#if defined(MBEDTLS_MD_LIGHT) + +/* + * - MBEDTLS_MD_CAN_xxx is defined if the md module can perform xxx. + * - MBEDTLS_MD_xxx_VIA_PSA is defined if the md module may perform xxx via PSA + * (see below). + * - MBEDTLS_MD_SOME_PSA is defined if at least one algorithm may be performed + * via PSA (see below). + * - MBEDTLS_MD_SOME_LEGACY is defined if at least one algorithm may be performed + * via a direct legacy call (see below). + * + * The md module performs an algorithm via PSA if there is a PSA hash + * accelerator and the PSA driver subsytem is initialized at the time the + * operation is started, and makes a direct legacy call otherwise. + */ + +/* PSA accelerated implementations */ +#if defined(MBEDTLS_PSA_CRYPTO_C) +#if defined(MBEDTLS_PSA_ACCEL_ALG_MD5) +#define MBEDTLS_MD_CAN_MD5 +#define MBEDTLS_MD_MD5_VIA_PSA +#define MBEDTLS_MD_SOME_PSA +#endif +#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_1) +#define MBEDTLS_MD_CAN_SHA1 +#define MBEDTLS_MD_SHA1_VIA_PSA +#define MBEDTLS_MD_SOME_PSA +#endif +#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_224) +#define MBEDTLS_MD_CAN_SHA224 +#define MBEDTLS_MD_SHA224_VIA_PSA +#define MBEDTLS_MD_SOME_PSA +#endif +#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_256) +#define MBEDTLS_MD_CAN_SHA256 +#define MBEDTLS_MD_SHA256_VIA_PSA +#define MBEDTLS_MD_SOME_PSA +#endif +#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_384) +#define MBEDTLS_MD_CAN_SHA384 +#define MBEDTLS_MD_SHA384_VIA_PSA +#define MBEDTLS_MD_SOME_PSA +#endif +#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_512) +#define MBEDTLS_MD_CAN_SHA512 +#define MBEDTLS_MD_SHA512_VIA_PSA +#define MBEDTLS_MD_SOME_PSA +#endif +#if defined(MBEDTLS_PSA_ACCEL_ALG_RIPEMD160) +#define MBEDTLS_MD_CAN_RIPEMD160 +#define MBEDTLS_MD_RIPEMD160_VIA_PSA +#define MBEDTLS_MD_SOME_PSA +#endif +#endif /* MBEDTLS_PSA_CRYPTO_C */ + +/* Built-in implementations */ +#if defined(MBEDTLS_MD5_C) +#define MBEDTLS_MD_CAN_MD5 +#define MBEDTLS_MD_SOME_LEGACY +#endif +#if defined(MBEDTLS_SHA1_C) +#define MBEDTLS_MD_CAN_SHA1 +#define MBEDTLS_MD_SOME_LEGACY +#endif +#if defined(MBEDTLS_SHA224_C) +#define MBEDTLS_MD_CAN_SHA224 +#define MBEDTLS_MD_SOME_LEGACY +#endif +#if defined(MBEDTLS_SHA256_C) +#define MBEDTLS_MD_CAN_SHA256 +#define MBEDTLS_MD_SOME_LEGACY +#endif +#if defined(MBEDTLS_SHA384_C) +#define MBEDTLS_MD_CAN_SHA384 +#define MBEDTLS_MD_SOME_LEGACY +#endif +#if defined(MBEDTLS_SHA512_C) +#define MBEDTLS_MD_CAN_SHA512 +#define MBEDTLS_MD_SOME_LEGACY +#endif +#if defined(MBEDTLS_RIPEMD160_C) +#define MBEDTLS_MD_CAN_RIPEMD160 +#define MBEDTLS_MD_SOME_LEGACY +#endif + +#endif /* MBEDTLS_MD_LIGHT */ + +/** 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 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Supported message digests. + * + * \warning 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_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_MD_CAN_SHA512) +#define MBEDTLS_MD_MAX_SIZE 64 /* longest known is SHA512 */ +#elif defined(MBEDTLS_MD_CAN_SHA384) +#define MBEDTLS_MD_MAX_SIZE 48 /* longest known is SHA384 */ +#elif defined(MBEDTLS_MD_CAN_SHA256) +#define MBEDTLS_MD_MAX_SIZE 32 /* longest known is SHA256 */ +#elif defined(MBEDTLS_MD_CAN_SHA224) +#define MBEDTLS_MD_MAX_SIZE 28 /* longest known is SHA224 */ +#else +#define MBEDTLS_MD_MAX_SIZE 20 /* longest known is SHA1 or RIPE MD-160 + or smaller (MD5 and earlier) */ +#endif + +#if defined(MBEDTLS_MD_CAN_SHA512) +#define MBEDTLS_MD_MAX_BLOCK_SIZE 128 +#else +#define MBEDTLS_MD_MAX_BLOCK_SIZE 64 +#endif + +/** + * Opaque struct. + * + * Constructed using either #mbedtls_md_info_from_string or + * #mbedtls_md_info_from_type. + * + * Fields can be accessed with #mbedtls_md_get_size, + * #mbedtls_md_get_type and #mbedtls_md_get_name. + */ +/* Defined internally in library/md_wrap.h. */ +typedef struct mbedtls_md_info_t mbedtls_md_info_t; + +/** + * Used internally to indicate whether a context uses legacy or PSA. + * + * Internal use only. + */ +typedef enum { + MBEDTLS_MD_ENGINE_LEGACY = 0, + MBEDTLS_MD_ENGINE_PSA, +} mbedtls_md_engine_t; + +/** + * The generic message-digest context. + */ +typedef struct mbedtls_md_context_t { + /** Information about the associated message digest. */ + const mbedtls_md_info_t *MBEDTLS_PRIVATE(md_info); + +#if defined(MBEDTLS_MD_SOME_PSA) + /** Are hash operations dispatched to PSA or legacy? */ + mbedtls_md_engine_t MBEDTLS_PRIVATE(engine); +#endif + + /** The digest-specific context (legacy) or the PSA operation. */ + void *MBEDTLS_PRIVATE(md_ctx); + +#if defined(MBEDTLS_MD_C) + /** The HMAC part of the context. */ + void *MBEDTLS_PRIVATE(hmac_ctx); +#endif +} mbedtls_md_context_t; + +/** + * \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); + + +/** + * \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 a 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. + * \return #MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE if both contexts are + * not using the same engine. This can be avoided by moving + * the call to psa_crypto_init() before the first call to + * mbedtls_md_setup(). + */ +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 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); + +/** + * \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 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 returns the message-digest information + * from the given context. + * + * \param ctx The context from which to extract the information. + * This must be initialized (or \c NULL). + * + * \return The message-digest information associated with \p ctx. + * \return \c NULL if \p ctx is \c NULL. + */ +const mbedtls_md_info_t *mbedtls_md_info_from_ctx( + const mbedtls_md_context_t *ctx); + +#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); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_MD_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..8081886 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/md5.h @@ -0,0 +1,202 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include +#include + +#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 MBEDTLS_PRIVATE(total)[2]; /*!< number of bytes processed */ + uint32_t MBEDTLS_PRIVATE(state)[4]; /*!< intermediate digest state */ + unsigned char MBEDTLS_PRIVATE(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(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(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(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]); + +/** + * \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(const unsigned char *input, + size_t ilen, + unsigned char output[16]); + +#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/memory_buffer_alloc.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/memory_buffer_alloc.h new file mode 100644 index 0000000..9694d24 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/memory_buffer_alloc.h @@ -0,0 +1,154 @@ +/** + * \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 + +#include "mbedtls/build_info.h" + +#include + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in mbedtls_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 number of alloc/free so far. + * + * \param alloc_count Number of allocations. + * \param free_count Number of frees. + */ +void mbedtls_memory_buffer_alloc_count_get(size_t *alloc_count, size_t *free_count); + +/** + * \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_sockets.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/net_sockets.h new file mode 100644 index 0000000..14316fb --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/net_sockets.h @@ -0,0 +1,303 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#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 { + /** The underlying file descriptor. + * + * This field is only guaranteed to be present on POSIX/Unix-like platforms. + * On other platforms, it may have a different type, have a different + * meaning, or be absent altogether. + */ + int fd; +} +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..0c95c90 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/nist_kw.h @@ -0,0 +1,178 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#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 MBEDTLS_PRIVATE(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..a592e63 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/oid.h @@ -0,0 +1,655 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include "mbedtls/asn1.h" +#include "mbedtls/pk.h" + +#include + +#if defined(MBEDTLS_CIPHER_C) +#include "mbedtls/cipher.h" +#endif + +#include "mbedtls/md.h" + +/** 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_UID "\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x01" /** id-domainComponent AttributeType:= {itu-t(0) data(9) pss(2342) ucl(19200300) pilot(100) pilotAttributeType(1) uid(1)} */ +#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_PKCS7 MBEDTLS_OID_PKCS "\x07" /**< pkcs-7 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 7 } */ +#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_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_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_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#7 OIDs + */ +#define MBEDTLS_OID_PKCS7_DATA MBEDTLS_OID_PKCS7 "\x01" /**< Content type is Data OBJECT IDENTIFIER ::= {pkcs-7 1} */ +#define MBEDTLS_OID_PKCS7_SIGNED_DATA MBEDTLS_OID_PKCS7 "\x02" /**< Content type is Signed Data OBJECT IDENTIFIER ::= {pkcs-7 2} */ +#define MBEDTLS_OID_PKCS7_ENVELOPED_DATA MBEDTLS_OID_PKCS7 "\x03" /**< Content type is Enveloped Data OBJECT IDENTIFIER ::= {pkcs-7 3} */ +#define MBEDTLS_OID_PKCS7_SIGNED_AND_ENVELOPED_DATA MBEDTLS_OID_PKCS7 "\x04" /**< Content type is Signed and Enveloped Data OBJECT IDENTIFIER ::= {pkcs-7 4} */ +#define MBEDTLS_OID_PKCS7_DIGESTED_DATA MBEDTLS_OID_PKCS7 "\x05" /**< Content type is Digested Data OBJECT IDENTIFIER ::= {pkcs-7 5} */ +#define MBEDTLS_OID_PKCS7_ENCRYPTED_DATA MBEDTLS_OID_PKCS7 "\x06" /**< Content type is Encrypted Data OBJECT IDENTIFIER ::= {pkcs-7 6} */ + +/* + * 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_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 *MBEDTLS_PRIVATE(asn1); /*!< OID ASN.1 representation */ + size_t MBEDTLS_PRIVATE(asn1_len); /*!< length of asn1 */ +#if !defined(MBEDTLS_X509_REMOVE_INFO) + const char *MBEDTLS_PRIVATE(name); /*!< official name (e.g. from RFC) */ + const char *MBEDTLS_PRIVATE(description); /*!< human friendly description */ +#endif +} 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 */ + +/** + * \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 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); + +/** + * \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); + +#if !defined(MBEDTLS_X509_REMOVE_INFO) +/** + * \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); +#endif + +/** + * \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/pem.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pem.h new file mode 100644 index 0000000..a33fc65 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pem.h @@ -0,0 +1,172 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#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 *MBEDTLS_PRIVATE(buf); /*!< buffer for decoded data */ + size_t MBEDTLS_PRIVATE(buflen); /*!< length of the buffer */ + unsigned char *MBEDTLS_PRIVATE(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 + * + * \note \c mbedtls_pem_free must be called on PEM context before + * the PEM context can be reused in another call to + * \c mbedtls_pem_read_buffer + * + * \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 Get the pointer to the decoded binary data in a PEM context. + * + * \param ctx PEM context to access. + * \param buflen On success, this will contain the length of the binary data. + * This must be a valid (non-null) pointer. + * + * \return A pointer to the decoded binary data. + * + * \note The returned pointer remains valid only until \p ctx is + modified or freed. + */ +static inline const unsigned char *mbedtls_pem_get_buffer(mbedtls_pem_context *ctx, size_t *buflen) +{ + *buflen = ctx->MBEDTLS_PRIVATE(buflen); + return ctx->MBEDTLS_PRIVATE(buf); +} + + +/** + * \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..3de7a8f --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pk.h @@ -0,0 +1,1052 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#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 + +/** 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 +/** The output buffer is too small. */ +#define MBEDTLS_ERR_PK_BUFFER_TOO_SMALL -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 { + /** The digest to use for MGF1 in PSS. + * + * \note When #MBEDTLS_USE_PSA_CRYPTO is enabled and #MBEDTLS_RSA_C is + * disabled, this must be equal to the \c md_alg argument passed + * to mbedtls_pk_verify_ext(). In a future version of the library, + * this constraint may apply whenever #MBEDTLS_USE_PSA_CRYPTO is + * enabled regardless of the status of #MBEDTLS_RSA_C. + */ + mbedtls_md_type_t mgf1_hash_id; + + /** The expected length of the salt, in bytes. This may be + * #MBEDTLS_RSA_SALT_LEN_ANY to accept any salt length. + * + * \note When #MBEDTLS_USE_PSA_CRYPTO is enabled, only + * #MBEDTLS_RSA_SALT_LEN_ANY is valid. Any other value may be + * ignored (allowing any salt length). + */ + 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 library/pk_wrap.h 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 The following defines are meant to list ECDSA capabilities of the + * PK module in a general way (without any reference to how this + * is achieved, which can be either through PSA driver or + * MBEDTLS_ECDSA_C) + */ +#if !defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(MBEDTLS_ECDSA_C) +#define MBEDTLS_PK_CAN_ECDSA_SIGN +#define MBEDTLS_PK_CAN_ECDSA_VERIFY +#endif +#else /* MBEDTLS_USE_PSA_CRYPTO */ +#if defined(PSA_WANT_ALG_ECDSA) +#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) +#define MBEDTLS_PK_CAN_ECDSA_SIGN +#endif +#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) +#define MBEDTLS_PK_CAN_ECDSA_VERIFY +#endif +#endif /* PSA_WANT_ALG_ECDSA */ +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) || defined(MBEDTLS_PK_CAN_ECDSA_SIGN) +#define MBEDTLS_PK_CAN_ECDSA_SOME +#endif + +/** + * \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 MBEDTLS_PRIVATE(type); + const char *MBEDTLS_PRIVATE(name); + void *MBEDTLS_PRIVATE(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 + * + * \note The library does not support custom pk info structures, + * only built-in structures returned by + * mbedtls_cipher_info_from_type(). + */ +typedef struct mbedtls_pk_info_t mbedtls_pk_info_t; + +/** + * \brief Public key container + */ +typedef struct mbedtls_pk_context { + const mbedtls_pk_info_t *MBEDTLS_PRIVATE(pk_info); /**< Public key information */ + void *MBEDTLS_PRIVATE(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 *MBEDTLS_PRIVATE(pk_info); /**< Public key information */ + void *MBEDTLS_PRIVATE(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, 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, + 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 or RSA 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 or RSA + * key pairs (that is, 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 mbedtls_svc_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); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/** + * \brief Tell if context can do the operation given by PSA algorithm + * + * \param ctx The context to query. It must have been initialized. + * \param alg PSA algorithm to check against, the following are allowed: + * PSA_ALG_RSA_PKCS1V15_SIGN(hash), + * PSA_ALG_RSA_PSS(hash), + * PSA_ALG_RSA_PKCS1V15_CRYPT, + * PSA_ALG_ECDSA(hash), + * PSA_ALG_ECDH, where hash is a specific hash. + * \param usage PSA usage flag to check against, must be composed of: + * PSA_KEY_USAGE_SIGN_HASH + * PSA_KEY_USAGE_DECRYPT + * PSA_KEY_USAGE_DERIVE. + * Context key must match all passed usage flags. + * + * \warning Since the set of allowed algorithms and usage flags may be + * expanded in the future, the return value \c 0 should not + * be taken in account for non-allowed algorithms and usage + * flags. + * + * \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, for non-allowed algorithms and usage flags, or + * 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_ext(const mbedtls_pk_context *ctx, psa_algorithm_t alg, + psa_key_usage_t usage); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +/** + * \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. + * This can be #MBEDTLS_MD_NONE if the signature algorithm + * does not rely on a hash algorithm (non-deterministic + * ECDSA, RSA PKCS#1 v1.5). + * For PKCS#1 v1.5, if \p md_alg is #MBEDTLS_MD_NONE, then + * \p hash is the DigestInfo structure used by RFC 8017 + * §9.2 steps 3–6. If \p md_alg is a valid hash + * algorithm then \p hash is the digest itself, and this + * function calculates the DigestInfo encoding internally. + * \param hash Hash of the message to sign + * \param hash_len Hash length + * \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. + */ +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. Note that if + * #MBEDTLS_USE_PSA_CRYPTO is defined, the salt length is not + * verified as PSA_ALG_RSA_PSS_ANY_SALT is used. + */ +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 + * \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_size The size of the \p sig buffer in bytes. + * \param sig_len On successful return, + * the number of bytes written to \p sig. + * \param f_rng RNG function, must not be \c NULL. + * \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 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_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); + +#if defined(MBEDTLS_PSA_CRYPTO_C) +/** + * \brief Make signature given a signature type. + * + * \param pk_type Signature type. + * \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 + * \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_size The size of the \p sig buffer in bytes. + * \param sig_len On successful return, + * the number of bytes written to \p sig. + * \param f_rng RNG function, must not be \c NULL. + * \param p_rng RNG parameter + * + * \return 0 on success, or a specific error code. + * + * \note When \p pk_type is #MBEDTLS_PK_RSASSA_PSS, + * see #PSA_ALG_RSA_PSS for a description of PSS options used. + * + * \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_ext(mbedtls_pk_type_t pk_type, + mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng); +#endif /* MBEDTLS_PSA_CRYPTO_C */ + +/** + * \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 + * \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_size The size of the \p sig buffer in bytes. + * \param sig_len On successful return, + * the number of bytes written to \p sig. + * \param f_rng RNG function, must not be \c NULL. + * \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_size, 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, must not be \c NULL. + * \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, must not be \c NULL. + * \param p_rng RNG parameter + * + * \note \p f_rng is used for padding generation. + * + * \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. + * \param f_rng RNG function, must not be \c NULL. + * \param p_rng RNG parameter + * + * \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, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng); + +/** + * \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).MBEDTLS_PRIVATE(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).MBEDTLS_PRIVATE(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 + * + * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto + * subsystem must have been initialized by calling + * psa_crypto_init() before calling this function. + * + * \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. + * \param f_rng RNG function, must not be \c NULL. Used for blinding. + * \param p_rng RNG parameter + * + * \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, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); + +/** \ingroup pk_module */ +/** + * \brief Parse a public key in PEM or DER format + * + * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto + * subsystem must have been initialized by calling + * psa_crypto_init() before calling this function. + * + * \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 For compressed points, see #MBEDTLS_ECP_PF_COMPRESSED for + * limitations. + * + * \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 + * + * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto + * subsystem must have been initialized by calling + * psa_crypto_init() before calling this function. + * + * \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. + * \param f_rng RNG function, must not be \c NULL. Used for blinding. + * \param p_rng RNG parameter + * + * \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, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); + +/** \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(const 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(const 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(const 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(const 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 or RSA 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. + * + * \param pk Input: the EC or RSA 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 alg The algorithm to allow for use with that key. + * \param usage The usage to allow for use with that key. + * \param alg2 The secondary 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, + mbedtls_svc_key_id_t *key, + psa_algorithm_t alg, + psa_key_usage_t usage, + psa_algorithm_t alg2); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_PK_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..eb9e2d9 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pkcs12.h @@ -0,0 +1,117 @@ +/** + * \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 + +#include "mbedtls/build_info.h" + +#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 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..152b45f --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pkcs5.h @@ -0,0 +1,136 @@ +/** + * \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 + +#include "mbedtls/build_info.h" + +#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 without using the HMAC context + * + * \param md_type Hash algorithm used + * \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_ext(mbedtls_md_type_t md_type, + 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_MD_C) +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +/** + * \brief PKCS#5 PBKDF2 using HMAC + * + * \deprecated Superseded by mbedtls_pkcs5_pbkdf2_hmac_ext(). + * + * \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_DEPRECATED 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); +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ +#endif /* MBEDTLS_MD_C */ +#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/pkcs7.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pkcs7.h new file mode 100644 index 0000000..1231e34 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pkcs7.h @@ -0,0 +1,253 @@ +/** + * \file pkcs7.h + * + * \brief PKCS #7 generic defines and structures + * https://tools.ietf.org/html/rfc2315 + */ +/* + * 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. + */ + +/** + * Note: For the time being, this implementation of the PKCS #7 cryptographic + * message syntax is a partial implementation of RFC 2315. + * Differences include: + * - The RFC specifies 6 different content types. The only type currently + * supported in Mbed TLS is the signed-data content type. + * - The only supported PKCS #7 Signed Data syntax version is version 1 + * - The RFC specifies support for BER. This implementation is limited to + * DER only. + * - The RFC specifies that multiple digest algorithms can be specified + * in the Signed Data type. Only one digest algorithm is supported in Mbed TLS. + * - The RFC specifies the Signed Data type can contain multiple X.509 or PKCS #6 extended + * certificates. In Mbed TLS, this list can only contain 0 or 1 certificates + * and they must be in X.509 format. + * - The RFC specifies the Signed Data type can contain + * certificate-revocation lists (CRLs). This implementation has no support + * for CRLs so it is assumed to be an empty list. + * - The RFC allows for SignerInfo structure to optionally contain + * unauthenticatedAttributes and authenticatedAttributes. In Mbed TLS it is + * assumed these fields are empty. + * - The RFC allows for the signed Data type to contain contentInfo. This + * implementation assumes the type is DATA and the content is empty. + */ + +#ifndef MBEDTLS_PKCS7_H +#define MBEDTLS_PKCS7_H + +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include "mbedtls/asn1.h" +#include "mbedtls/x509.h" +#include "mbedtls/x509_crt.h" + +/** + * \name PKCS #7 Module Error codes + * \{ + */ +#define MBEDTLS_ERR_PKCS7_INVALID_FORMAT -0x5300 /**< The format is invalid, e.g. different type expected. */ +#define MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE -0x5380 /**< Unavailable feature, e.g. anything other than signed data. */ +#define MBEDTLS_ERR_PKCS7_INVALID_VERSION -0x5400 /**< The PKCS #7 version element is invalid or cannot be parsed. */ +#define MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO -0x5480 /**< The PKCS #7 content info is invalid or cannot be parsed. */ +#define MBEDTLS_ERR_PKCS7_INVALID_ALG -0x5500 /**< The algorithm tag or value is invalid or cannot be parsed. */ +#define MBEDTLS_ERR_PKCS7_INVALID_CERT -0x5580 /**< The certificate tag or value is invalid or cannot be parsed. */ +#define MBEDTLS_ERR_PKCS7_INVALID_SIGNATURE -0x5600 /**< Error parsing the signature */ +#define MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO -0x5680 /**< Error parsing the signer's info */ +#define MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA -0x5700 /**< Input invalid. */ +#define MBEDTLS_ERR_PKCS7_ALLOC_FAILED -0x5780 /**< Allocation of memory failed. */ +#define MBEDTLS_ERR_PKCS7_VERIFY_FAIL -0x5800 /**< Verification Failed */ +#define MBEDTLS_ERR_PKCS7_CERT_DATE_INVALID -0x5880 /**< The PKCS #7 date issued/expired dates are invalid */ +/* \} name */ + +/** + * \name PKCS #7 Supported Version + * \{ + */ +#define MBEDTLS_PKCS7_SUPPORTED_VERSION 0x01 +/* \} name */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Type-length-value structure that allows for ASN.1 using DER. + */ +typedef mbedtls_asn1_buf mbedtls_pkcs7_buf; + +/** + * Container for ASN.1 named information objects. + * It allows for Relative Distinguished Names (e.g. cn=localhost,ou=code,etc.). + */ +typedef mbedtls_asn1_named_data mbedtls_pkcs7_name; + +/** + * Container for a sequence of ASN.1 items + */ +typedef mbedtls_asn1_sequence mbedtls_pkcs7_sequence; + +/** + * PKCS #7 types + */ +typedef enum { + MBEDTLS_PKCS7_NONE=0, + MBEDTLS_PKCS7_DATA, + MBEDTLS_PKCS7_SIGNED_DATA, + MBEDTLS_PKCS7_ENVELOPED_DATA, + MBEDTLS_PKCS7_SIGNED_AND_ENVELOPED_DATA, + MBEDTLS_PKCS7_DIGESTED_DATA, + MBEDTLS_PKCS7_ENCRYPTED_DATA, +} +mbedtls_pkcs7_type; + +/** + * Structure holding PKCS #7 signer info + */ +typedef struct mbedtls_pkcs7_signer_info { + int MBEDTLS_PRIVATE(version); + mbedtls_x509_buf MBEDTLS_PRIVATE(serial); + mbedtls_x509_name MBEDTLS_PRIVATE(issuer); + mbedtls_x509_buf MBEDTLS_PRIVATE(issuer_raw); + mbedtls_x509_buf MBEDTLS_PRIVATE(alg_identifier); + mbedtls_x509_buf MBEDTLS_PRIVATE(sig_alg_identifier); + mbedtls_x509_buf MBEDTLS_PRIVATE(sig); + struct mbedtls_pkcs7_signer_info *MBEDTLS_PRIVATE(next); +} +mbedtls_pkcs7_signer_info; + +/** + * Structure holding the signed data section + */ +typedef struct mbedtls_pkcs7_signed_data { + int MBEDTLS_PRIVATE(version); + mbedtls_pkcs7_buf MBEDTLS_PRIVATE(digest_alg_identifiers); + int MBEDTLS_PRIVATE(no_of_certs); + mbedtls_x509_crt MBEDTLS_PRIVATE(certs); + int MBEDTLS_PRIVATE(no_of_crls); + mbedtls_x509_crl MBEDTLS_PRIVATE(crl); + int MBEDTLS_PRIVATE(no_of_signers); + mbedtls_pkcs7_signer_info MBEDTLS_PRIVATE(signers); +} +mbedtls_pkcs7_signed_data; + +/** + * Structure holding PKCS #7 structure, only signed data for now + */ +typedef struct mbedtls_pkcs7 { + mbedtls_pkcs7_buf MBEDTLS_PRIVATE(raw); + mbedtls_pkcs7_signed_data MBEDTLS_PRIVATE(signed_data); +} +mbedtls_pkcs7; + +/** + * \brief Initialize mbedtls_pkcs7 structure. + * + * \param pkcs7 mbedtls_pkcs7 structure. + */ +void mbedtls_pkcs7_init(mbedtls_pkcs7 *pkcs7); + +/** + * \brief Parse a single DER formatted PKCS #7 detached signature. + * + * \param pkcs7 The mbedtls_pkcs7 structure to be filled by the parser. + * \param buf The buffer holding only the DER encoded PKCS #7 content. + * \param buflen The size in bytes of \p buf. The size must be exactly the + * length of the DER encoded PKCS #7 content. + * + * \note This function makes an internal copy of the PKCS #7 buffer + * \p buf. In particular, \p buf may be destroyed or reused + * after this call returns. + * \note Signatures with internal data are not supported. + * + * \return The \c mbedtls_pkcs7_type of \p buf, if successful. + * \return A negative error code on failure. + */ +int mbedtls_pkcs7_parse_der(mbedtls_pkcs7 *pkcs7, const unsigned char *buf, + const size_t buflen); + +/** + * \brief Verification of PKCS #7 signature against a caller-supplied + * certificate. + * + * For each signer in the PKCS structure, this function computes + * a signature over the supplied data, using the supplied + * certificate and the same digest algorithm as specified by the + * signer. It then compares this signature against the + * signer's signature; verification succeeds if any comparison + * matches. + * + * This function does not use the certificates held within the + * PKCS #7 structure itself, and does not check that the + * certificate is signed by a trusted certification authority. + * + * \param pkcs7 mbedtls_pkcs7 structure containing signature. + * \param cert Certificate containing key to verify signature. + * \param data Plain data on which signature has to be verified. + * \param datalen Length of the data. + * + * \note This function internally calculates the hash on the supplied + * plain data for signature verification. + * + * \return 0 if the signature verifies, or a negative error code on failure. + */ +int mbedtls_pkcs7_signed_data_verify(mbedtls_pkcs7 *pkcs7, + const mbedtls_x509_crt *cert, + const unsigned char *data, + size_t datalen); + +/** + * \brief Verification of PKCS #7 signature against a caller-supplied + * certificate. + * + * For each signer in the PKCS structure, this function + * validates a signature over the supplied hash, using the + * supplied certificate and the same digest algorithm as + * specified by the signer. Verification succeeds if any + * signature is good. + * + * This function does not use the certificates held within the + * PKCS #7 structure itself, and does not check that the + * certificate is signed by a trusted certification authority. + * + * \param pkcs7 PKCS #7 structure containing signature. + * \param cert Certificate containing key to verify signature. + * \param hash Hash of the plain data on which signature has to be verified. + * \param hashlen Length of the hash. + * + * \note This function is different from mbedtls_pkcs7_signed_data_verify() + * in that it is directly passed the hash of the data. + * + * \return 0 if the signature verifies, or a negative error code on failure. + */ +int mbedtls_pkcs7_signed_hash_verify(mbedtls_pkcs7 *pkcs7, + const mbedtls_x509_crt *cert, + const unsigned char *hash, size_t hashlen); + +/** + * \brief Unallocate all PKCS #7 data and zeroize the memory. + * It doesn't free \p pkcs7 itself. This should be done by the caller. + * + * \param pkcs7 mbedtls_pkcs7 structure to free. + */ +void mbedtls_pkcs7_free(mbedtls_pkcs7 *pkcs7); + +#ifdef __cplusplus +} +#endif + +#endif /* pkcs7.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..f651587 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/platform.h @@ -0,0 +1,472 @@ +/** + * \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. + * + * When all compilation options related to platform abstraction are + * disabled, this header just defines `mbedtls_xxx` function names + * as aliases to the standard `xxx` function. + * + * Most modules in the library and example programs are expected to + * include this header. + */ +/* + * 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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#if defined(MBEDTLS_HAVE_TIME) +#include "mbedtls/platform_time.h" +#endif + +#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 mbedtls_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_SETBUF) +#define MBEDTLS_PLATFORM_STD_SETBUF setbuf /**< The default \c setbuf 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 setbuf + */ +#if defined(MBEDTLS_PLATFORM_SETBUF_ALT) +#include +/** + * \brief Function pointer to call for `setbuf()` functionality + * (changing the internal buffering on stdio calls). + * + * \note The library calls this function to disable + * buffering when reading or writing sensitive data, + * to avoid having extra copies of sensitive data + * remaining in stdio buffers after the file is + * closed. If this is not a concern, for example if + * your platform's stdio doesn't have any buffering, + * you can set mbedtls_setbuf to a function that + * does nothing. + * + * The library always calls this function with + * `buf` equal to `NULL`. + */ +extern void (*mbedtls_setbuf)(FILE *stream, char *buf); + +/** + * \brief Dynamically configure the function that is called + * when the mbedtls_setbuf() function is called by the + * library. + * + * \param setbuf_func The \c setbuf function implementation + * + * \return \c 0 + */ +int mbedtls_platform_set_setbuf(void (*setbuf_func)( + FILE *stream, char *buf)); +#elif defined(MBEDTLS_PLATFORM_SETBUF_MACRO) +/** + * \brief Macro defining the function for the library to + * call for `setbuf` functionality (changing the + * internal buffering on stdio calls). + * + * \note See extra comments on the mbedtls_setbuf() function + * pointer above. + * + * \return \c 0 on success, negative on error. + */ +#define mbedtls_setbuf MBEDTLS_PLATFORM_SETBUF_MACRO +#else +#define mbedtls_setbuf setbuf +#endif /* MBEDTLS_PLATFORM_SETBUF_ALT / MBEDTLS_PLATFORM_SETBUF_MACRO */ + +/* + * 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 MBEDTLS_PRIVATE(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..eae6f5f --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/platform_time.h @@ -0,0 +1,68 @@ +/** + * \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 + +#include "mbedtls/build_info.h" + +#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..edbde94 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/platform_util.h @@ -0,0 +1,207 @@ +/** + * \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 + +#include "mbedtls/build_info.h" + +#include +#if defined(MBEDTLS_HAVE_TIME_DATE) +#include "mbedtls/platform_time.h" +#include +#endif /* MBEDTLS_HAVE_TIME_DATE */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* 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) + +/* Internal helper macros for deprecating API constants. */ +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#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)) +#else /* MBEDTLS_DEPRECATED_WARNING */ +#define MBEDTLS_DEPRECATED +#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 mbedtls_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..3025ef1 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/poly1305.h @@ -0,0 +1,180 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include +#include + +/** Invalid input parameter(s). */ +#define MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA -0x0057 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_POLY1305_ALT) + +typedef struct mbedtls_poly1305_context { + uint32_t MBEDTLS_PRIVATE(r)[4]; /** The value for 'r' (low 128 bits of the key). */ + uint32_t MBEDTLS_PRIVATE(s)[4]; /** The value for 's' (high 128 bits of the key). */ + uint32_t MBEDTLS_PRIVATE(acc)[5]; /** The accumulator number. */ + uint8_t MBEDTLS_PRIVATE(queue)[16]; /** The current partial block of data. */ + size_t MBEDTLS_PRIVATE(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/private_access.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/private_access.h new file mode 100644 index 0000000..61fa877 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/private_access.h @@ -0,0 +1,32 @@ +/** + * \file private_access.h + * + * \brief Macro wrapper for struct's members. + */ +/* + * 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_PRIVATE_ACCESS_H +#define MBEDTLS_PRIVATE_ACCESS_H + +#ifndef MBEDTLS_ALLOW_PRIVATE_ACCESS +#define MBEDTLS_PRIVATE(member) private_##member +#else +#define MBEDTLS_PRIVATE(member) member +#endif + +#endif /* MBEDTLS_PRIVATE_ACCESS_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..b750716 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/psa_util.h @@ -0,0 +1,397 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#if defined(MBEDTLS_PSA_CRYPTO_C) + +#include "psa/crypto.h" + +#include "mbedtls/ecp.h" +#include "mbedtls/md.h" +#include "mbedtls/pk.h" +#include "mbedtls/oid.h" +#include "mbedtls/error.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_CCM_STAR_NO_TAG: + case MBEDTLS_CIPHER_AES_192_CCM_STAR_NO_TAG: + case MBEDTLS_CIPHER_AES_256_CCM_STAR_NO_TAG: + 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_CCM_STAR_NO_TAG: + case MBEDTLS_CIPHER_ARIA_192_CCM_STAR_NO_TAG: + case MBEDTLS_CIPHER_ARIA_256_CCM_STAR_NO_TAG: + 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_CCM_STAR_NO_TAG: + return PSA_ALG_CCM_STAR_NO_TAG; + 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. */ + +/* Note: this function should not be used from inside the library, use + * mbedtls_hash_info_psa_from_md() from the internal hash_info.h instead. + * It is kept only for compatibility in case applications were using it. */ +static inline psa_algorithm_t mbedtls_psa_translate_md(mbedtls_md_type_t md_alg) +{ + switch (md_alg) { +#if defined(MBEDTLS_MD5_C) || defined(PSA_WANT_ALG_MD5) + case MBEDTLS_MD_MD5: + return PSA_ALG_MD5; +#endif +#if defined(MBEDTLS_SHA1_C) || defined(PSA_WANT_ALG_SHA_1) + case MBEDTLS_MD_SHA1: + return PSA_ALG_SHA_1; +#endif +#if defined(MBEDTLS_SHA224_C) || defined(PSA_WANT_ALG_SHA_224) + case MBEDTLS_MD_SHA224: + return PSA_ALG_SHA_224; +#endif +#if defined(MBEDTLS_SHA256_C) || defined(PSA_WANT_ALG_SHA_256) + case MBEDTLS_MD_SHA256: + return PSA_ALG_SHA_256; +#endif +#if defined(MBEDTLS_SHA384_C) || defined(PSA_WANT_ALG_SHA_384) + case MBEDTLS_MD_SHA384: + return PSA_ALG_SHA_384; +#endif +#if defined(MBEDTLS_SHA512_C) || defined(PSA_WANT_ALG_SHA_512) + case MBEDTLS_MD_SHA512: + return PSA_ALG_SHA_512; +#endif +#if defined(MBEDTLS_RIPEMD160_C) || defined(PSA_WANT_ALG_RIPEMD160) + 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 \ + PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) + +#define MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH \ + PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) + +/* 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. */ + + +/* 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) */ + +typedef struct { + psa_status_t psa_status; + int16_t mbedtls_error; +} mbedtls_error_pair_t; + +#if !defined(MBEDTLS_MD_C) || !defined(MBEDTLS_MD5_C) || defined(MBEDTLS_USE_PSA_CRYPTO) +extern const mbedtls_error_pair_t psa_to_md_errors[4]; +#endif + +#if defined(MBEDTLS_LMS_C) +extern const mbedtls_error_pair_t psa_to_lms_errors[3]; +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3) +extern const mbedtls_error_pair_t psa_to_ssl_errors[7]; +#endif + +#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) || \ + defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) +extern const mbedtls_error_pair_t psa_to_pk_rsa_errors[8]; +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) +extern const mbedtls_error_pair_t psa_to_pk_ecdsa_errors[7]; +#endif + +/* Generic fallback function for error translation, + * when the received state was not module-specific. */ +int psa_generic_status_to_mbedtls(psa_status_t status); + +/* This function iterates over provided local error translations, + * and if no match was found - calls the fallback error translation function. */ +int psa_status_to_mbedtls(psa_status_t status, + const mbedtls_error_pair_t *local_translations, + size_t local_errors_num, + int (*fallback_f)(psa_status_t)); + +/* The second out of three-stage error handling functions of the pk module, + * acts as a fallback after RSA / ECDSA error translation, and if no match + * is found, it itself calls psa_generic_status_to_mbedtls. */ +int psa_pk_status_to_mbedtls(psa_status_t status); + +/* Utility macro to shorten the defines of error translator in modules. */ +#define PSA_TO_MBEDTLS_ERR_LIST(status, error_list, fallback_f) \ + psa_status_to_mbedtls(status, error_list, \ + sizeof(error_list)/sizeof(error_list[0]), \ + fallback_f) + +#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..acec3c5 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ripemd160.h @@ -0,0 +1,148 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_RIPEMD160_ALT) +// Regular implementation +// + +/** + * \brief RIPEMD-160 context structure + */ +typedef struct mbedtls_ripemd160_context { + uint32_t MBEDTLS_PRIVATE(total)[2]; /*!< number of bytes processed */ + uint32_t MBEDTLS_PRIVATE(state)[5]; /*!< intermediate digest state */ + unsigned char MBEDTLS_PRIVATE(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) a 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(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(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(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]); + +/** + * \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(const unsigned char *input, + size_t ilen, + unsigned char output[20]); + +#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..da8639b --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/rsa.h @@ -0,0 +1,1149 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#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 + +/* + * RSA constants + */ + +#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. + */ +typedef struct mbedtls_rsa_context { + int MBEDTLS_PRIVATE(ver); /*!< Reserved for internal purposes. + * Do not set this field in application + * code. Its meaning might change without + * notice. */ + size_t MBEDTLS_PRIVATE(len); /*!< The size of \p N in Bytes. */ + + mbedtls_mpi MBEDTLS_PRIVATE(N); /*!< The public modulus. */ + mbedtls_mpi MBEDTLS_PRIVATE(E); /*!< The public exponent. */ + + mbedtls_mpi MBEDTLS_PRIVATE(D); /*!< The private exponent. */ + mbedtls_mpi MBEDTLS_PRIVATE(P); /*!< The first prime factor. */ + mbedtls_mpi MBEDTLS_PRIVATE(Q); /*!< The second prime factor. */ + + mbedtls_mpi MBEDTLS_PRIVATE(DP); /*!< D % (P - 1). */ + mbedtls_mpi MBEDTLS_PRIVATE(DQ); /*!< D % (Q - 1). */ + mbedtls_mpi MBEDTLS_PRIVATE(QP); /*!< 1 / (Q % P). */ + + mbedtls_mpi MBEDTLS_PRIVATE(RN); /*!< cached R^2 mod N. */ + + mbedtls_mpi MBEDTLS_PRIVATE(RP); /*!< cached R^2 mod P. */ + mbedtls_mpi MBEDTLS_PRIVATE(RQ); /*!< cached R^2 mod Q. */ + + mbedtls_mpi MBEDTLS_PRIVATE(Vi); /*!< The cached blinding value. */ + mbedtls_mpi MBEDTLS_PRIVATE(Vf); /*!< The cached un-blinding value. */ + + int MBEDTLS_PRIVATE(padding); /*!< Selects padding mode: + #MBEDTLS_RSA_PKCS_V15 for 1.5 padding and + #MBEDTLS_RSA_PKCS_V21 for OAEP or PSS. */ + int MBEDTLS_PRIVATE(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 MBEDTLS_PRIVATE(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 This function initializes the padding and the hash + * identifier to respectively #MBEDTLS_RSA_PKCS_V15 and + * #MBEDTLS_MD_NONE. See mbedtls_rsa_set_padding() for more + * information about those parameters. + * + * \param ctx The RSA context to initialize. This must not be \c NULL. + */ +void mbedtls_rsa_init(mbedtls_rsa_context *ctx); + +/** + * \brief This function sets padding for an already initialized 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 mbedtls_rsa_rsaes_xxx or \c mbedtls_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 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 hash identifier for PSS or OAEP, if \p padding is + * #MBEDTLS_RSA_PKCS_V21. #MBEDTLS_MD_NONE is accepted by this + * function but may be not suitable for some operations. + * Ignored if \p padding is #MBEDTLS_RSA_PKCS_V15. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_RSA_INVALID_PADDING failure: + * \p padding or \p hash_id is invalid. + */ +int mbedtls_rsa_set_padding(mbedtls_rsa_context *ctx, int padding, + mbedtls_md_type_t hash_id); + +/** + * \brief This function retrieves padding mode of initialized + * RSA context. + * + * \param ctx The initialized RSA context. + * + * \return RSA padding mode. + * + */ +int mbedtls_rsa_get_padding_mode(const mbedtls_rsa_context *ctx); + +/** + * \brief This function retrieves hash identifier of mbedtls_md_type_t + * type. + * + * \param ctx The initialized RSA context. + * + * \return Hash identifier of mbedtls_md_type_t type. + * + */ +int mbedtls_rsa_get_md_alg(const mbedtls_rsa_context *ctx); + +/** + * \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 is 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 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 is mandatory and 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 a 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 mandatory. + * \param p_rng The RNG context to pass to \p f_rng. This may be \c NULL + * 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. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG to use. It is used for padding generation + * and it is mandatory. + * \param p_rng The RNG context to be passed to \p f_rng. May be + * \c NULL if \p f_rng doesn't need a context argument. + * \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, + 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). + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function to use. It is mandatory and used for + * padding generation. + * \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 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, + 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. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function to use. This is needed for padding + * generation and is mandatory. + * \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 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, + 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. + * + * \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. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. This is used for blinding and is + * mandatory; see mbedtls_rsa_private() for more. + * \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 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, + 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. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. This is used for blinding and is + * mandatory; see mbedtls_rsa_private() for more. + * \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 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, + 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. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. This is used for blinding and is + * mandatory. + * \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 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, + 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. + * + * \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. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function to use. This is mandatory and + * 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 or raw data in Bytes. + * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the + * output length of the corresponding hash algorithm. + * \param hash The buffer holding the message digest or raw data. + * This must be a readable buffer of at least \p hashlen Bytes. + * \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, + 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). + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. This is used for blinding and is + * mandatory; see mbedtls_rsa_private() for more. + * \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 or raw data in Bytes. + * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the + * output length of the corresponding hash algorithm. + * \param hash The buffer holding the message digest or raw data. + * This must be a readable buffer of at least \p hashlen Bytes. + * \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, + 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 by calling + * mbedtls_rsa_set_padding() 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 is mandatory and 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 or raw data in Bytes. + * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the + * output length of the corresponding hash algorithm. + * \param hash The buffer holding the message digest or raw data. + * This must be a readable buffer of at least \p hashlen Bytes. + * \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 by calling + * mbedtls_rsa_set_padding() 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. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. It is mandatory and 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 or raw data in Bytes. + * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the + * output length of the corresponding hash algorithm. + * \param hash The buffer holding the message digest or raw data. + * This must be a readable buffer of at least \p hashlen Bytes. + * \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, + 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. + * + * \note For PKCS#1 v2.1 encoding, see comments on + * mbedtls_rsa_rsassa_pss_verify() about \p md_alg and + * \p hash_id. + * + * \param ctx The initialized RSA public key context to use. + * \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 or raw data in Bytes. + * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the + * output length of the corresponding hash algorithm. + * \param hash The buffer holding the message digest or raw data. + * This must be a readable buffer of at least \p hashlen Bytes. + * \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, + 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). + * + * \param ctx The initialized RSA public key context to use. + * \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 or raw data in Bytes. + * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the + * output length of the corresponding hash algorithm. + * \param hash The buffer holding the message digest or raw data. + * This must be a readable buffer of at least \p hashlen Bytes. + * \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, + 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 by calling + * mbedtls_rsa_set_padding() 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 by + * mbedtls_rsa_set_padding() is #MBEDTLS_MD_NONE, the \p md_alg + * parameter is used. + * + * \param ctx The initialized RSA public key context to use. + * \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 or raw data in Bytes. + * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the + * output length of the corresponding hash algorithm. + * \param hash The buffer holding the message digest or raw data. + * This must be a readable buffer of at least \p hashlen Bytes. + * \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, + 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 by mbedtls_rsa_set_padding() is + * ignored. + * + * \param ctx The initialized RSA public key context to use. + * \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 or raw data in Bytes. + * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the + * output length of the corresponding hash algorithm. + * \param hash The buffer holding the message digest or raw data. + * This must be a readable buffer of at least \p hashlen Bytes. + * \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, + 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/sha1.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/sha1.h new file mode 100644 index 0000000..18bde93 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/sha1.h @@ -0,0 +1,231 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include +#include + +/** 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 MBEDTLS_PRIVATE(total)[2]; /*!< The number of Bytes processed. */ + uint32_t MBEDTLS_PRIVATE(state)[5]; /*!< The intermediate digest state. */ + unsigned char MBEDTLS_PRIVATE(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(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(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(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]); + +/** + * \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(const unsigned char *input, + size_t ilen, + unsigned char output[20]); + +#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..87e5cc6 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/sha256.h @@ -0,0 +1,210 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include +#include + +/** 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(). + */ +typedef struct mbedtls_sha256_context { + uint32_t MBEDTLS_PRIVATE(total)[2]; /*!< The number of Bytes processed. */ + uint32_t MBEDTLS_PRIVATE(state)[8]; /*!< The intermediate digest state. */ + unsigned char MBEDTLS_PRIVATE(buffer)[64]; /*!< The data block being processed. */ + int MBEDTLS_PRIVATE(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. + * + * \note is224 must be defined accordingly to the enabled + * MBEDTLS_SHA224_C/MBEDTLS_SHA256_C symbols otherwise the + * function will return #MBEDTLS_ERR_SHA512_BAD_INPUT_DATA. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha256_starts(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(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 + * for SHA-256, \c 28 bytes for SHA-224. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha256_finish(mbedtls_sha256_context *ctx, + unsigned char *output); + +/** + * \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]); + +/** + * \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 + * for SHA-256, \c 28 bytes for SHA-224. + * \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(const unsigned char *input, + size_t ilen, + unsigned char *output, + int is224); + +#if defined(MBEDTLS_SELF_TEST) + +#if defined(MBEDTLS_SHA224_C) +/** + * \brief The SHA-224 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_sha224_self_test(int verbose); +#endif /* MBEDTLS_SHA224_C */ + +#if defined(MBEDTLS_SHA256_C) +/** + * \brief The SHA-256 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_sha256_self_test(int verbose); +#endif /* MBEDTLS_SHA256_C */ + +#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..ea54678 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/sha512.h @@ -0,0 +1,220 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include +#include + +/** 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(). + */ +typedef struct mbedtls_sha512_context { + uint64_t MBEDTLS_PRIVATE(total)[2]; /*!< The number of Bytes processed. */ + uint64_t MBEDTLS_PRIVATE(state)[8]; /*!< The intermediate digest state. */ + unsigned char MBEDTLS_PRIVATE(buffer)[128]; /*!< The data block being processed. */ +#if defined(MBEDTLS_SHA384_C) + int MBEDTLS_PRIVATE(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 is384 must be defined accordingly to the enabled + * MBEDTLS_SHA384_C/MBEDTLS_SHA512_C symbols otherwise 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(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(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 + * for SHA-512, \c 48 bytes for SHA-384. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha512_finish(mbedtls_sha512_context *ctx, + unsigned char *output); + +/** + * \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]); + +/** + * \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 + * for SHA-512, \c 48 bytes for SHA-384. + * \param is384 Determines which function to use. This must be either + * \c 0 for SHA-512, or \c 1 for SHA-384. + * + * \note is384 must be defined accordingly with the supported + * symbols in the config file. If: + * - is384 is 0, but \c MBEDTLS_SHA384_C is not defined, or + * - is384 is 1, but \c MBEDTLS_SHA512_C is not defined + * then 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(const unsigned char *input, + size_t ilen, + unsigned char *output, + int is384); + +#if defined(MBEDTLS_SELF_TEST) + +#if defined(MBEDTLS_SHA384_C) +/** + * \brief The SHA-384 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_sha384_self_test(int verbose); +#endif /* MBEDTLS_SHA384_C */ + +#if defined(MBEDTLS_SHA512_C) +/** + * \brief The SHA-512 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_sha512_self_test(int verbose); +#endif /* MBEDTLS_SHA512_C */ + +#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..68e8d04 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl.h @@ -0,0 +1,5335 @@ +/** + * \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 +#include "mbedtls/platform_util.h" +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#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 in TLS code. 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_HAVE_TIME) +#include "mbedtls/platform_time.h" +#endif + +#include "psa/crypto.h" + +/* + * SSL Error codes + */ +/** A cryptographic operation is in progress. Try again later. */ +#define MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS -0x7000 +/** 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 +/** A message could not be parsed due to a syntactic error. */ +#define MBEDTLS_ERR_SSL_DECODE_ERROR -0x7300 +/* Error space gap */ +/** 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 +/** Client received an extended server hello containing an unsupported extension */ +#define MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION -0x7500 +/** No ALPN protocols supported that the client advertises */ +#define MBEDTLS_ERR_SSL_NO_APPLICATION_PROTOCOL -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 +/** No server could be identified matching the client's SNI. */ +#define MBEDTLS_ERR_SSL_UNRECOGNIZED_NAME -0x7800 +/** The peer notified us that the connection is going to be closed. */ +#define MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY -0x7880 +/* Error space gap */ +/* Error space gap */ +/** Processing of the Certificate handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_CERTIFICATE -0x7A00 +/* Error space gap */ +/** + * Received NewSessionTicket Post Handshake Message. + * This error code is experimental and may be changed or removed without notice. + */ +#define MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET -0x7B00 +/** Not possible to read early data */ +#define MBEDTLS_ERR_SSL_CANNOT_READ_EARLY_DATA -0x7B80 +/** Not possible to write early data */ +#define MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA -0x7C00 +/* Error space gap */ +/* Error space gap */ +/* Error space gap */ +/* Error space gap */ +/* Error space gap */ +/** 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 +/** Handshake protocol not within min/max boundaries */ +#define MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION -0x6E80 +/** The handshake negotiation failed. */ +#define MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE -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 +/* Error space gap */ +/** 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 +/** A field in a message was incorrect or inconsistent with other fields. */ +#define MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER -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 +/* Error space gap */ +/* Error space gap */ +/* Error space gap */ +/* Error space gap */ +/* Error space gap */ +/* Error space gap */ +/* Error space gap */ +/* Error space gap */ +/** 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 +/** Invalid value in SSL config */ +#define MBEDTLS_ERR_SSL_BAD_CONFIG -0x5E80 + +/* + * Constants from RFC 8446 for TLS 1.3 PSK modes + * + * Those are used in the Pre-Shared Key Exchange Modes extension. + * See Section 4.2.9 in RFC 8446. + */ +#define MBEDTLS_SSL_TLS1_3_PSK_MODE_PURE 0 /* Pure PSK-based exchange */ +#define MBEDTLS_SSL_TLS1_3_PSK_MODE_ECDHE 1 /* PSK+ECDHE-based exchange */ + +/* + * TLS 1.3 NamedGroup values + * + * From RF 8446 + * enum { + * // Elliptic Curve Groups (ECDHE) + * secp256r1(0x0017), secp384r1(0x0018), secp521r1(0x0019), + * x25519(0x001D), x448(0x001E), + * // Finite Field Groups (DHE) + * ffdhe2048(0x0100), ffdhe3072(0x0101), ffdhe4096(0x0102), + * ffdhe6144(0x0103), ffdhe8192(0x0104), + * // Reserved Code Points + * ffdhe_private_use(0x01FC..0x01FF), + * ecdhe_private_use(0xFE00..0xFEFF), + * (0xFFFF) + * } NamedGroup; + * + */ + +/* Elliptic Curve Groups (ECDHE) */ +#define MBEDTLS_SSL_IANA_TLS_GROUP_NONE 0 +#define MBEDTLS_SSL_IANA_TLS_GROUP_SECP192K1 0x0012 +#define MBEDTLS_SSL_IANA_TLS_GROUP_SECP192R1 0x0013 +#define MBEDTLS_SSL_IANA_TLS_GROUP_SECP224K1 0x0014 +#define MBEDTLS_SSL_IANA_TLS_GROUP_SECP224R1 0x0015 +#define MBEDTLS_SSL_IANA_TLS_GROUP_SECP256K1 0x0016 +#define MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1 0x0017 +#define MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1 0x0018 +#define MBEDTLS_SSL_IANA_TLS_GROUP_SECP521R1 0x0019 +#define MBEDTLS_SSL_IANA_TLS_GROUP_BP256R1 0x001A +#define MBEDTLS_SSL_IANA_TLS_GROUP_BP384R1 0x001B +#define MBEDTLS_SSL_IANA_TLS_GROUP_BP512R1 0x001C +#define MBEDTLS_SSL_IANA_TLS_GROUP_X25519 0x001D +#define MBEDTLS_SSL_IANA_TLS_GROUP_X448 0x001E +/* Finite Field Groups (DHE) */ +#define MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE2048 0x0100 +#define MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE3072 0x0101 +#define MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE4096 0x0102 +#define MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE6144 0x0103 +#define MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE8192 0x0104 + +/* + * TLS 1.3 Key Exchange Modes + * + * Mbed TLS internal identifiers for use with the SSL configuration API + * mbedtls_ssl_conf_tls13_key_exchange_modes(). + */ + +#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK (1u << 0) /*!< Pure-PSK TLS 1.3 key exchange, + * encompassing both externally agreed PSKs + * as well as resumption PSKs. */ +#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL (1u << 1) /*!< Pure-Ephemeral TLS 1.3 key exchanges, + * including for example ECDHE and DHE + * key exchanges. */ +#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL (1u << 2) /*!< PSK-Ephemeral TLS 1.3 key exchanges, + * using both a PSK and an ephemeral + * key exchange. */ + +/* Convenience macros for sets of key exchanges. */ +#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_ALL \ + (MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK | \ + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL | \ + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL) /*!< All TLS 1.3 key exchanges */ +#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL \ + (MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK | \ + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL) /*!< All PSK-based TLS 1.3 key exchanges */ +#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ALL \ + (MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL | \ + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL) /*!< All ephemeral TLS 1.3 key exchanges */ + +#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_NONE (0) + +/* + * Various constants + */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +/* These are the high and low bytes of ProtocolVersion as defined by: + * - RFC 5246: ProtocolVersion version = { 3, 3 }; // TLS v1.2 + * - RFC 8446: see section 4.2.1 + */ +#define MBEDTLS_SSL_MAJOR_VERSION_3 3 +#define MBEDTLS_SSL_MINOR_VERSION_3 3 /*!< TLS v1.2 */ +#define MBEDTLS_SSL_MINOR_VERSION_4 4 /*!< TLS v1.3 */ +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +#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_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_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_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_EARLY_DATA_DISABLED 0 +#define MBEDTLS_SSL_EARLY_DATA_ENABLED 1 + +#define MBEDTLS_SSL_DTLS_SRTP_MKI_UNSUPPORTED 0 +#define MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED 1 + +#define MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_CLIENT 1 +#define MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_SERVER 0 + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) +#if defined(PSA_WANT_ALG_SHA_384) +#define MBEDTLS_SSL_TLS1_3_TICKET_RESUMPTION_KEY_LEN 48 +#elif defined(PSA_WANT_ALG_SHA_256) +#define MBEDTLS_SSL_TLS1_3_TICKET_RESUMPTION_KEY_LEN 32 +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS */ +/* + * 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 mbedtls_config.h or define them on the compiler command line. + * \{ + */ + +/* + * 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_IN_CONTENT_LEN) +#define MBEDTLS_SSL_IN_CONTENT_LEN 16384 +#endif + +#if !defined(MBEDTLS_SSL_OUT_CONTENT_LEN) +#define MBEDTLS_SSL_OUT_CONTENT_LEN 16384 +#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_TLS1_3_PADDING_GRANULARITY) +#define MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY 16 +#endif + +/** \} name SECTION: Module settings */ + +/* + * Default to standard CID mode + */ +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ + !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT) +#define MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT 0 +#endif + +/* + * Length of the verify data for secure renegotiation + */ +#define MBEDTLS_SSL_VERIFY_DATA_MAX_LEN 12 + +/* + * Signaling ciphersuite values (SCSV) + */ +#define MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO 0xFF /**< renegotiation info ext */ + +/* + * 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 + +/* + * TLS 1.3 signature algorithms + * RFC 8446, Section 4.2.2 + */ + +/* RSASSA-PKCS1-v1_5 algorithms */ +#define MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256 0x0401 +#define MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384 0x0501 +#define MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512 0x0601 + +/* ECDSA algorithms */ +#define MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256 0x0403 +#define MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384 0x0503 +#define MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512 0x0603 + +/* RSASSA-PSS algorithms with public key OID rsaEncryption */ +#define MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256 0x0804 +#define MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384 0x0805 +#define MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512 0x0806 + +/* EdDSA algorithms */ +#define MBEDTLS_TLS1_3_SIG_ED25519 0x0807 +#define MBEDTLS_TLS1_3_SIG_ED448 0x0808 + +/* RSASSA-PSS algorithms with public key OID RSASSA-PSS */ +#define MBEDTLS_TLS1_3_SIG_RSA_PSS_PSS_SHA256 0x0809 +#define MBEDTLS_TLS1_3_SIG_RSA_PSS_PSS_SHA384 0x080A +#define MBEDTLS_TLS1_3_SIG_RSA_PSS_PSS_SHA512 0x080B + +/* LEGACY ALGORITHMS */ +#define MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA1 0x0201 +#define MBEDTLS_TLS1_3_SIG_ECDSA_SHA1 0x0203 + +#define MBEDTLS_TLS1_3_SIG_NONE 0x0 + +/* + * 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_MISSING_EXTENSION 109 /* 0x6d -- new in TLS 1.3 */ +#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_CERT_REQUIRED 116 /* 0x74 */ +#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_END_OF_EARLY_DATA 5 +#define MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS 8 +#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 +#define MBEDTLS_SSL_HS_MESSAGE_HASH 254 + +/* + * 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_STATUS_REQUEST 5 /* RFC 6066 TLS 1.2 and 1.3 */ + +#define MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES 10 +#define MBEDTLS_TLS_EXT_SUPPORTED_GROUPS 10 /* RFC 8422,7919 TLS 1.2 and 1.3 */ +#define MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS 11 + +#define MBEDTLS_TLS_EXT_SIG_ALG 13 /* RFC 8446 TLS 1.3 */ +#define MBEDTLS_TLS_EXT_USE_SRTP 14 +#define MBEDTLS_TLS_EXT_HEARTBEAT 15 /* RFC 6520 TLS 1.2 and 1.3 */ +#define MBEDTLS_TLS_EXT_ALPN 16 + +#define MBEDTLS_TLS_EXT_SCT 18 /* RFC 6962 TLS 1.2 and 1.3 */ +#define MBEDTLS_TLS_EXT_CLI_CERT_TYPE 19 /* RFC 7250 TLS 1.2 and 1.3 */ +#define MBEDTLS_TLS_EXT_SERV_CERT_TYPE 20 /* RFC 7250 TLS 1.2 and 1.3 */ +#define MBEDTLS_TLS_EXT_PADDING 21 /* RFC 7685 TLS 1.2 and 1.3 */ +#define MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC 22 /* 0x16 */ +#define MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET 0x0017 /* 23 */ + +#define MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT 28 /* RFC 8449 (implemented for TLS 1.3 only) */ + +#define MBEDTLS_TLS_EXT_SESSION_TICKET 35 + +#define MBEDTLS_TLS_EXT_PRE_SHARED_KEY 41 /* RFC 8446 TLS 1.3 */ +#define MBEDTLS_TLS_EXT_EARLY_DATA 42 /* RFC 8446 TLS 1.3 */ +#define MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS 43 /* RFC 8446 TLS 1.3 */ +#define MBEDTLS_TLS_EXT_COOKIE 44 /* RFC 8446 TLS 1.3 */ +#define MBEDTLS_TLS_EXT_PSK_KEY_EXCHANGE_MODES 45 /* RFC 8446 TLS 1.3 */ + +#define MBEDTLS_TLS_EXT_CERT_AUTH 47 /* RFC 8446 TLS 1.3 */ +#define MBEDTLS_TLS_EXT_OID_FILTERS 48 /* RFC 8446 TLS 1.3 */ +#define MBEDTLS_TLS_EXT_POST_HANDSHAKE_AUTH 49 /* RFC 8446 TLS 1.3 */ +#define MBEDTLS_TLS_EXT_SIG_ALG_CERT 50 /* RFC 8446 TLS 1.3 */ +#define MBEDTLS_TLS_EXT_KEY_SHARE 51 /* RFC 8446 TLS 1.3 */ + +#if MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT == 0 +#define MBEDTLS_TLS_EXT_CID 54 /* RFC 9146 DTLS 1.2 CID */ +#else +#define MBEDTLS_TLS_EXT_CID 254 /* Pre-RFC 9146 DTLS 1.2 CID */ +#endif + +#define MBEDTLS_TLS_EXT_ECJPAKE_KKPP 256 /* experimental */ + +#define MBEDTLS_TLS_EXT_RENEGOTIATION_INFO 0xFF01 + +/* + * Size defines + */ +#if !defined(MBEDTLS_PSK_MAX_LEN) +/* + * If the library supports TLS 1.3 tickets and the cipher suite + * TLS1-3-AES-256-GCM-SHA384, set the PSK maximum length to 48 instead of 32. + * That way, the TLS 1.3 client and server are able to resume sessions where + * the cipher suite is TLS1-3-AES-256-GCM-SHA384 (pre-shared keys are 48 + * bytes long in that case). + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ + defined(MBEDTLS_SSL_SESSION_TICKETS) && \ + defined(MBEDTLS_AES_C) && defined(MBEDTLS_GCM_C) && \ + defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +#define MBEDTLS_PSK_MAX_LEN 48 /* 384 bits */ +#else +#define MBEDTLS_PSK_MAX_LEN 32 /* 256 bits */ +#endif +#endif /* !MBEDTLS_PSK_MAX_LEN */ + +/* 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) + +#define MBEDTLS_TLS1_3_MD_MAX_SIZE PSA_HASH_MAX_SIZE + + +/* Length in number of bytes of the TLS sequence number */ +#define MBEDTLS_SSL_SEQUENCE_NUMBER_LEN 8 + +#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_NEW_SESSION_TICKET, + MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT, + MBEDTLS_SSL_HELLO_RETRY_REQUEST, + MBEDTLS_SSL_ENCRYPTED_EXTENSIONS, + MBEDTLS_SSL_END_OF_EARLY_DATA, + MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY, + MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED, + MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO, + MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO, + MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO, + MBEDTLS_SSL_SERVER_CCS_AFTER_HELLO_RETRY_REQUEST, + MBEDTLS_SSL_HANDSHAKE_OVER, + MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET, + MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH, +} +mbedtls_ssl_states; + +/** + * \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 number of milliseconds 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 an 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 library/ssl_misc.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_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) +#define MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_PSK_RESUMPTION \ + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK /* 1U << 0 */ +#define MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_PSK_EPHEMERAL_RESUMPTION \ + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL /* 1U << 2 */ +#define MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA (1U << 3) + +#define MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK \ + (MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_PSK_RESUMPTION | \ + MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_PSK_EPHEMERAL_RESUMPTION | \ + MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA) +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS */ + +/** + * \brief Callback type: server-side session cache getter + * + * The session cache is logically a key value store, with + * keys being session IDs and values being instances of + * mbedtls_ssl_session. + * + * This callback retrieves an entry in this key-value store. + * + * \param data The address of the session cache structure to query. + * \param session_id The buffer holding the session ID to query. + * \param session_id_len The length of \p session_id in Bytes. + * \param session The address of the session structure to populate. + * It is initialized with mbdtls_ssl_session_init(), + * and the callback must always leave it in a state + * where it can safely be freed via + * mbedtls_ssl_session_free() independent of the + * return code of this function. + * + * \return \c 0 on success + * \return A non-zero return value on failure. + * + */ +typedef int mbedtls_ssl_cache_get_t(void *data, + unsigned char const *session_id, + size_t session_id_len, + mbedtls_ssl_session *session); +/** + * \brief Callback type: server-side session cache setter + * + * The session cache is logically a key value store, with + * keys being session IDs and values being instances of + * mbedtls_ssl_session. + * + * This callback sets an entry in this key-value store. + * + * \param data The address of the session cache structure to modify. + * \param session_id The buffer holding the session ID to query. + * \param session_id_len The length of \p session_id in Bytes. + * \param session The address of the session to be stored in the + * session cache. + * + * \return \c 0 on success + * \return A non-zero return value on failure. + */ +typedef int mbedtls_ssl_cache_set_t(void *data, + unsigned char const *session_id, + size_t session_id_len, + const mbedtls_ssl_session *session); + +#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_SHA384_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 */ + +typedef struct { + unsigned char client_application_traffic_secret_N[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + unsigned char server_application_traffic_secret_N[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + unsigned char exporter_master_secret[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + unsigned char resumption_master_secret[MBEDTLS_TLS1_3_MD_MAX_SIZE]; +} mbedtls_ssl_tls13_application_secrets; + +#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 MBEDTLS_PRIVATE(chosen_dtls_srtp_profile); + /*! The length of mki_value. */ + uint16_t MBEDTLS_PRIVATE(mki_len); + /*! The mki_value used, with max size of 256 bytes. */ + unsigned char MBEDTLS_PRIVATE(mki_value)[MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH]; +} +mbedtls_dtls_srtp_info; + +#endif /* MBEDTLS_SSL_DTLS_SRTP */ + +/** Human-friendly representation of the (D)TLS protocol version. */ +typedef enum { + MBEDTLS_SSL_VERSION_UNKNOWN, /*!< Context not in use or version not yet negotiated. */ + MBEDTLS_SSL_VERSION_TLS1_2 = 0x0303, /*!< (D)TLS 1.2 */ + MBEDTLS_SSL_VERSION_TLS1_3 = 0x0304, /*!< (D)TLS 1.3 */ +} mbedtls_ssl_protocol_version; + +/* + * 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 MBEDTLS_PRIVATE(mfl_code); /*!< MaxFragmentLength negotiated by peer */ +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + + unsigned char MBEDTLS_PRIVATE(exported); + + /** TLS version negotiated in the session. Used if and when renegotiating + * or resuming a session instead of the configured minor TLS version. + */ + mbedtls_ssl_protocol_version MBEDTLS_PRIVATE(tls_version); + +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t MBEDTLS_PRIVATE(start); /*!< starting time */ +#endif + int MBEDTLS_PRIVATE(ciphersuite); /*!< chosen ciphersuite */ + size_t MBEDTLS_PRIVATE(id_len); /*!< session id length */ + unsigned char MBEDTLS_PRIVATE(id)[32]; /*!< session identifier */ + unsigned char MBEDTLS_PRIVATE(master)[48]; /*!< the master secret */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + mbedtls_x509_crt *MBEDTLS_PRIVATE(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 *MBEDTLS_PRIVATE(peer_cert_digest); + size_t MBEDTLS_PRIVATE(peer_cert_digest_len); + mbedtls_md_type_t MBEDTLS_PRIVATE(peer_cert_digest_type); +#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + uint32_t MBEDTLS_PRIVATE(verify_result); /*!< verification result */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + unsigned char *MBEDTLS_PRIVATE(ticket); /*!< RFC 5077 session ticket */ + size_t MBEDTLS_PRIVATE(ticket_len); /*!< session ticket length */ + uint32_t MBEDTLS_PRIVATE(ticket_lifetime); /*!< ticket lifetime hint */ +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) + uint8_t MBEDTLS_PRIVATE(endpoint); /*!< 0: client, 1: server */ + uint8_t MBEDTLS_PRIVATE(ticket_flags); /*!< Ticket flags */ + uint32_t MBEDTLS_PRIVATE(ticket_age_add); /*!< Randomly generated value used to obscure the age of the ticket */ + uint8_t MBEDTLS_PRIVATE(resumption_key_len); /*!< resumption_key length */ + unsigned char MBEDTLS_PRIVATE(resumption_key)[MBEDTLS_SSL_TLS1_3_TICKET_RESUMPTION_KEY_LEN]; + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && defined(MBEDTLS_SSL_CLI_C) + char *MBEDTLS_PRIVATE(hostname); /*!< host name binded with tickets */ +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_CLI_C) + mbedtls_time_t MBEDTLS_PRIVATE(ticket_received); /*!< time ticket was received */ +#endif /* MBEDTLS_HAVE_TIME && MBEDTLS_SSL_CLI_C */ + +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + int MBEDTLS_PRIVATE(encrypt_then_mac); /*!< flag for EtM activation */ +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + mbedtls_ssl_tls13_application_secrets MBEDTLS_PRIVATE(app_secrets); +#endif +}; + +/* + * Identifiers for PRFs used in various versions of TLS. + */ +typedef enum { + MBEDTLS_SSL_TLS_PRF_NONE, + MBEDTLS_SSL_TLS_PRF_SHA384, + MBEDTLS_SSL_TLS_PRF_SHA256, + MBEDTLS_SSL_HKDF_EXPAND_SHA384, + MBEDTLS_SSL_HKDF_EXPAND_SHA256 +} +mbedtls_tls_prf_types; + +typedef enum { + MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET = 0, +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_EARLY_SECRET, + MBEDTLS_SSL_KEY_EXPORT_TLS1_3_EARLY_EXPORTER_SECRET, + MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_HANDSHAKE_TRAFFIC_SECRET, + MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_HANDSHAKE_TRAFFIC_SECRET, + MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_APPLICATION_TRAFFIC_SECRET, + MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_APPLICATION_TRAFFIC_SECRET, +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ +} mbedtls_ssl_key_export_type; + +/** + * \brief Callback type: Export key alongside random values for + * session identification, and PRF for + * implementation of TLS key exporters. + * + * \param p_expkey Context for the callback. + * \param type The type of the key that is being exported. + * \param secret The address of the buffer holding the secret + * that's being exporterd. + * \param secret_len The length of \p secret in bytes. + * \param client_random The client random bytes. + * \param server_random The server random bytes. + * \param tls_prf_type The identifier for the PRF used in the handshake + * to which the key belongs. + */ +typedef void mbedtls_ssl_export_keys_t(void *p_expkey, + mbedtls_ssl_key_export_type type, + const unsigned char *secret, + size_t secret_len, + const unsigned char client_random[32], + const unsigned char server_random[32], + mbedtls_tls_prf_types tls_prf_type); + +#if defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Callback type: generic handshake callback + * + * \note Callbacks may use user_data funcs to set/get app user data. + * See \c mbedtls_ssl_get_user_data_p() + * \c mbedtls_ssl_get_user_data_n() + * \c mbedtls_ssl_conf_get_user_data_p() + * \c mbedtls_ssl_conf_get_user_data_n() + * + * \param ssl \c mbedtls_ssl_context on which the callback is run + * + * \return The return value of the callback is 0 if successful, + * or a specific MBEDTLS_ERR_XXX code, which will cause + * the handshake to be aborted. + */ +typedef int (*mbedtls_ssl_hs_cb_t)(mbedtls_ssl_context *ssl); +#endif + +/* A type for storing user data in a library structure. + * + * The representation of type may change in future versions of the library. + * Only the behaviors guaranteed by documented accessor functions are + * guaranteed to remain stable. + */ +typedef union { + uintptr_t n; /* typically a handle to an associated object */ + void *p; /* typically a pointer to extra data */ +} mbedtls_ssl_user_data_t; + +/** + * SSL/TLS configuration to be shared between mbedtls_ssl_context structures. + */ +struct mbedtls_ssl_config { + /* Group items mostly by size. This helps to reduce memory wasted to + * padding. It also helps to keep smaller fields early in the structure, + * so that elements tend to be in the 128-element direct access window + * on Arm Thumb, which reduces the code size. */ + + mbedtls_ssl_protocol_version MBEDTLS_PRIVATE(max_tls_version); /*!< max. TLS version used */ + mbedtls_ssl_protocol_version MBEDTLS_PRIVATE(min_tls_version); /*!< min. TLS 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 MBEDTLS_PRIVATE(endpoint); /*!< 0: client, 1: server */ + uint8_t MBEDTLS_PRIVATE(transport); /*!< 0: stream (TLS), 1: datagram (DTLS) */ + uint8_t MBEDTLS_PRIVATE(authmode); /*!< MBEDTLS_SSL_VERIFY_XXX */ + /* needed even with renego disabled for LEGACY_BREAK_HANDSHAKE */ + uint8_t MBEDTLS_PRIVATE(allow_legacy_renegotiation); /*!< MBEDTLS_LEGACY_XXX */ +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + uint8_t MBEDTLS_PRIVATE(mfl_code); /*!< desired fragment length indicator + (MBEDTLS_SSL_MAX_FRAG_LEN_XXX) */ +#endif +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + uint8_t MBEDTLS_PRIVATE(encrypt_then_mac); /*!< negotiate encrypt-then-mac? */ +#endif +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + uint8_t MBEDTLS_PRIVATE(extended_ms); /*!< negotiate extended master secret? */ +#endif +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + uint8_t MBEDTLS_PRIVATE(anti_replay); /*!< detect and prevent replay? */ +#endif +#if defined(MBEDTLS_SSL_RENEGOTIATION) + uint8_t MBEDTLS_PRIVATE(disable_renegotiation); /*!< disable renegotiation? */ +#endif +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && \ + defined(MBEDTLS_SSL_CLI_C) + uint8_t MBEDTLS_PRIVATE(session_tickets); /*!< use session tickets? */ +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && \ + defined(MBEDTLS_SSL_SRV_C) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_3) + uint16_t MBEDTLS_PRIVATE(new_session_tickets_count); /*!< number of NewSessionTicket */ +#endif + +#if defined(MBEDTLS_SSL_SRV_C) + uint8_t MBEDTLS_PRIVATE(cert_req_ca_list); /*!< enable sending CA list in + Certificate Request messages? */ + uint8_t MBEDTLS_PRIVATE(respect_cli_pref); /*!< pick the ciphersuite according to + the client's preferences rather + than ours? */ +#endif +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + uint8_t MBEDTLS_PRIVATE(ignore_unexpected_cid); /*!< Should DTLS record with + * unexpected CID + * lead to failure? */ +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ +#if defined(MBEDTLS_SSL_DTLS_SRTP) + uint8_t MBEDTLS_PRIVATE(dtls_srtp_mki_support); /* support having mki_value + in the use_srtp extension? */ +#endif + + /* + * Pointers + */ + + /** Allowed ciphersuites for (D)TLS 1.2 (0-terminated) */ + const int *MBEDTLS_PRIVATE(ciphersuite_list); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + /** Allowed TLS 1.3 key exchange modes. */ + int MBEDTLS_PRIVATE(tls13_kex_modes); +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + + /** Callback for printing debug output */ + void(*MBEDTLS_PRIVATE(f_dbg))(void *, int, const char *, int, const char *); + void *MBEDTLS_PRIVATE(p_dbg); /*!< context for the debug function */ + + /** Callback for getting (pseudo-)random numbers */ + int(*MBEDTLS_PRIVATE(f_rng))(void *, unsigned char *, size_t); + void *MBEDTLS_PRIVATE(p_rng); /*!< context for the RNG function */ + + /** Callback to retrieve a session from the cache */ + mbedtls_ssl_cache_get_t *MBEDTLS_PRIVATE(f_get_cache); + /** Callback to store a session into the cache */ + mbedtls_ssl_cache_set_t *MBEDTLS_PRIVATE(f_set_cache); + void *MBEDTLS_PRIVATE(p_cache); /*!< context for cache callbacks */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + /** Callback for setting cert according to SNI extension */ + int(*MBEDTLS_PRIVATE(f_sni))(void *, mbedtls_ssl_context *, const unsigned char *, size_t); + void *MBEDTLS_PRIVATE(p_sni); /*!< context for SNI callback */ +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /** Callback to customize X.509 certificate chain verification */ + int(*MBEDTLS_PRIVATE(f_vrfy))(void *, mbedtls_x509_crt *, int, uint32_t *); + void *MBEDTLS_PRIVATE(p_vrfy); /*!< context for X.509 verify calllback */ +#endif + +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED) +#if defined(MBEDTLS_SSL_SRV_C) + /** Callback to retrieve PSK key from identity */ + int(*MBEDTLS_PRIVATE(f_psk))(void *, mbedtls_ssl_context *, const unsigned char *, size_t); + void *MBEDTLS_PRIVATE(p_psk); /*!< context for PSK callback */ +#endif +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) + /** Callback to create & write a cookie for ClientHello verification */ + int(*MBEDTLS_PRIVATE(f_cookie_write))(void *, unsigned char **, unsigned char *, + const unsigned char *, size_t); + /** Callback to verify validity of a ClientHello cookie */ + int(*MBEDTLS_PRIVATE(f_cookie_check))(void *, const unsigned char *, size_t, + const unsigned char *, size_t); + void *MBEDTLS_PRIVATE(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(*MBEDTLS_PRIVATE(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(*MBEDTLS_PRIVATE(f_ticket_parse))(void *, mbedtls_ssl_session *, unsigned char *, size_t); + void *MBEDTLS_PRIVATE(p_ticket); /*!< context for the ticket callbacks */ +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SRV_C */ +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + size_t MBEDTLS_PRIVATE(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 *MBEDTLS_PRIVATE(cert_profile); /*!< verification profile */ + mbedtls_ssl_key_cert *MBEDTLS_PRIVATE(key_cert); /*!< own certificate/key pair(s) */ + mbedtls_x509_crt *MBEDTLS_PRIVATE(ca_chain); /*!< trusted CAs */ + mbedtls_x509_crl *MBEDTLS_PRIVATE(ca_crl); /*!< trusted CAs CRLs */ +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + mbedtls_x509_crt_ca_cb_t MBEDTLS_PRIVATE(f_ca_cb); + void *MBEDTLS_PRIVATE(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 *MBEDTLS_PRIVATE(f_async_sign_start); /*!< start asynchronous signature operation */ + mbedtls_ssl_async_decrypt_t *MBEDTLS_PRIVATE(f_async_decrypt_start); /*!< start asynchronous decryption operation */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + mbedtls_ssl_async_resume_t *MBEDTLS_PRIVATE(f_async_resume); /*!< resume asynchronous operation */ + mbedtls_ssl_async_cancel_t *MBEDTLS_PRIVATE(f_async_cancel); /*!< cancel asynchronous operation */ + void *MBEDTLS_PRIVATE(p_async_config_data); /*!< Configuration data set by mbedtls_ssl_conf_async_private_cb(). */ +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + const int *MBEDTLS_PRIVATE(sig_hashes); /*!< allowed signature hashes */ +#endif + const uint16_t *MBEDTLS_PRIVATE(sig_algs); /*!< allowed signature algorithms */ +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ + +#if defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_DEPRECATED_REMOVED) + const mbedtls_ecp_group_id *MBEDTLS_PRIVATE(curve_list); /*!< allowed curves */ +#endif + + const uint16_t *MBEDTLS_PRIVATE(group_list); /*!< allowed IANA NamedGroups */ + +#if defined(MBEDTLS_DHM_C) + mbedtls_mpi MBEDTLS_PRIVATE(dhm_P); /*!< prime modulus for DHM */ + mbedtls_mpi MBEDTLS_PRIVATE(dhm_G); /*!< generator for DHM */ +#endif + +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED) + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + mbedtls_svc_key_id_t MBEDTLS_PRIVATE(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 *MBEDTLS_PRIVATE(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 MBEDTLS_PRIVATE(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 *MBEDTLS_PRIVATE(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 MBEDTLS_PRIVATE(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_SSL_HANDSHAKE_WITH_PSK_ENABLED */ + +#if defined(MBEDTLS_SSL_EARLY_DATA) + int MBEDTLS_PRIVATE(early_data_enabled); /*!< Early data enablement: + * - MBEDTLS_SSL_EARLY_DATA_DISABLED, + * - MBEDTLS_SSL_EARLY_DATA_ENABLED */ + +#if defined(MBEDTLS_SSL_SRV_C) + /* The maximum amount of 0-RTT data. RFC 8446 section 4.6.1 */ + uint32_t MBEDTLS_PRIVATE(max_early_data_size); +#endif /* MBEDTLS_SSL_SRV_C */ + +#endif /* MBEDTLS_SSL_EARLY_DATA */ + +#if defined(MBEDTLS_SSL_ALPN) + const char **MBEDTLS_PRIVATE(alpn_list); /*!< ordered list of protocols */ +#endif + +#if defined(MBEDTLS_SSL_DTLS_SRTP) + /*! ordered list of supported srtp profile */ + const mbedtls_ssl_srtp_profile *MBEDTLS_PRIVATE(dtls_srtp_profile_list); + /*! number of supported profiles */ + size_t MBEDTLS_PRIVATE(dtls_srtp_profile_list_len); +#endif /* MBEDTLS_SSL_DTLS_SRTP */ + + /* + * Numerical settings (int) + */ + + uint32_t MBEDTLS_PRIVATE(read_timeout); /*!< timeout for mbedtls_ssl_read (ms) */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + uint32_t MBEDTLS_PRIVATE(hs_timeout_min); /*!< initial value of the handshake + retransmission timeout (ms) */ + uint32_t MBEDTLS_PRIVATE(hs_timeout_max); /*!< maximum value of the handshake + retransmission timeout (ms) */ +#endif + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + int MBEDTLS_PRIVATE(renego_max_records); /*!< grace period for renegotiation */ + unsigned char MBEDTLS_PRIVATE(renego_period)[8]; /*!< value of the record counters + that triggers renegotiation */ +#endif + + unsigned int MBEDTLS_PRIVATE(badmac_limit); /*!< limit of records with a bad MAC */ + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) + unsigned int MBEDTLS_PRIVATE(dhm_min_bitlen); /*!< min. bit length of the DHM prime */ +#endif + + /** User data pointer or handle. + * + * The library sets this to \p 0 when creating a context and does not + * access it afterwards. + */ + mbedtls_ssl_user_data_t MBEDTLS_PRIVATE(user_data); + +#if defined(MBEDTLS_SSL_SRV_C) + mbedtls_ssl_hs_cb_t MBEDTLS_PRIVATE(f_cert_cb); /*!< certificate selection callback */ +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) + const mbedtls_x509_crt *MBEDTLS_PRIVATE(dn_hints);/*!< acceptable client cert issuers */ +#endif +}; + +struct mbedtls_ssl_context { + const mbedtls_ssl_config *MBEDTLS_PRIVATE(conf); /*!< configuration information */ + + /* + * Miscellaneous + */ + int MBEDTLS_PRIVATE(state); /*!< SSL handshake: current state */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + int MBEDTLS_PRIVATE(renego_status); /*!< Initial, in progress, pending? */ + int MBEDTLS_PRIVATE(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 */ + + /** Server: Negotiated TLS protocol version. + * Client: Maximum TLS version to be negotiated, then negotiated TLS + * version. + * + * It is initialized as the maximum TLS version to be negotiated in the + * ClientHello writing preparation stage and used throughout the + * ClientHello writing. For a fresh handshake not linked to any previous + * handshake, it is initialized to the configured maximum TLS version + * to be negotiated. When renegotiating or resuming a session, it is + * initialized to the previously negotiated TLS version. + * + * Updated to the negotiated TLS version as soon as the ServerHello is + * received. + */ + mbedtls_ssl_protocol_version MBEDTLS_PRIVATE(tls_version); + + unsigned MBEDTLS_PRIVATE(badmac_seen); /*!< records with a bad MAC received */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /** Callback to customize X.509 certificate chain verification */ + int(*MBEDTLS_PRIVATE(f_vrfy))(void *, mbedtls_x509_crt *, int, uint32_t *); + void *MBEDTLS_PRIVATE(p_vrfy); /*!< context for X.509 verify callback */ +#endif + + mbedtls_ssl_send_t *MBEDTLS_PRIVATE(f_send); /*!< Callback for network send */ + mbedtls_ssl_recv_t *MBEDTLS_PRIVATE(f_recv); /*!< Callback for network receive */ + mbedtls_ssl_recv_timeout_t *MBEDTLS_PRIVATE(f_recv_timeout); + /*!< Callback for network receive with timeout */ + + void *MBEDTLS_PRIVATE(p_bio); /*!< context for I/O operations */ + + /* + * Session layer + */ + mbedtls_ssl_session *MBEDTLS_PRIVATE(session_in); /*!< current session data (in) */ + mbedtls_ssl_session *MBEDTLS_PRIVATE(session_out); /*!< current session data (out) */ + mbedtls_ssl_session *MBEDTLS_PRIVATE(session); /*!< negotiated session data */ + mbedtls_ssl_session *MBEDTLS_PRIVATE(session_negotiate); /*!< session data in negotiation */ + + mbedtls_ssl_handshake_params *MBEDTLS_PRIVATE(handshake); /*!< params required only during + the handshake process */ + + /* + * Record layer transformations + */ + mbedtls_ssl_transform *MBEDTLS_PRIVATE(transform_in); /*!< current transform params (in) + * This is always a reference, + * never an owning pointer. */ + mbedtls_ssl_transform *MBEDTLS_PRIVATE(transform_out); /*!< current transform params (out) + * This is always a reference, + * never an owning pointer. */ + mbedtls_ssl_transform *MBEDTLS_PRIVATE(transform); /*!< negotiated transform params + * This pointer owns the transform + * it references. */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + mbedtls_ssl_transform *MBEDTLS_PRIVATE(transform_negotiate); /*!< transform params in negotiation + * This pointer owns the transform + * it references. */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + /*! The application data transform in TLS 1.3. + * This pointer owns the transform it references. */ + mbedtls_ssl_transform *MBEDTLS_PRIVATE(transform_application); +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + + /* + * Timers + */ + void *MBEDTLS_PRIVATE(p_timer); /*!< context for the timer callbacks */ + + mbedtls_ssl_set_timer_t *MBEDTLS_PRIVATE(f_set_timer); /*!< set timer callback */ + mbedtls_ssl_get_timer_t *MBEDTLS_PRIVATE(f_get_timer); /*!< get timer callback */ + + /* + * Record layer (incoming data) + */ + unsigned char *MBEDTLS_PRIVATE(in_buf); /*!< input buffer */ + unsigned char *MBEDTLS_PRIVATE(in_ctr); /*!< 64-bit incoming message counter + TLS: maintained by us + DTLS: read from peer */ + unsigned char *MBEDTLS_PRIVATE(in_hdr); /*!< start of record header */ +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + unsigned char *MBEDTLS_PRIVATE(in_cid); /*!< The start of the CID; + * (the end is marked by in_len). */ +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + unsigned char *MBEDTLS_PRIVATE(in_len); /*!< two-bytes message length field */ + unsigned char *MBEDTLS_PRIVATE(in_iv); /*!< ivlen-byte IV */ + unsigned char *MBEDTLS_PRIVATE(in_msg); /*!< message contents (in_iv+ivlen) */ + unsigned char *MBEDTLS_PRIVATE(in_offt); /*!< read offset in application data */ + + int MBEDTLS_PRIVATE(in_msgtype); /*!< record header: message type */ + size_t MBEDTLS_PRIVATE(in_msglen); /*!< record header: message length */ + size_t MBEDTLS_PRIVATE(in_left); /*!< amount of data read so far */ +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t MBEDTLS_PRIVATE(in_buf_len); /*!< length of input buffer */ +#endif +#if defined(MBEDTLS_SSL_PROTO_DTLS) + uint16_t MBEDTLS_PRIVATE(in_epoch); /*!< DTLS epoch for incoming records */ + size_t MBEDTLS_PRIVATE(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 MBEDTLS_PRIVATE(in_window_top); /*!< last validated record seq_num */ + uint64_t MBEDTLS_PRIVATE(in_window); /*!< bitmask for replay detection */ +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ + + size_t MBEDTLS_PRIVATE(in_hslen); /*!< current handshake message length, + including the handshake header */ + int MBEDTLS_PRIVATE(nb_zero); /*!< # of 0-length encrypted messages */ + + int MBEDTLS_PRIVATE(keep_current_message); /*!< drop or reuse current message + on next call to record layer? */ + + /* The following three variables indicate if and, if yes, + * what kind of alert is pending to be sent. + */ + unsigned char MBEDTLS_PRIVATE(send_alert); /*!< Determines if a fatal alert + should be sent. Values: + - \c 0 , no alert is to be sent. + - \c 1 , alert is to be sent. */ + unsigned char MBEDTLS_PRIVATE(alert_type); /*!< Type of alert if send_alert + != 0 */ + int MBEDTLS_PRIVATE(alert_reason); /*!< The error code to be returned + to the user once the fatal alert + has been sent. */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + uint8_t MBEDTLS_PRIVATE(disable_datagram_packing); /*!< Disable packing multiple records + * within a single datagram. */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + /* + * Record layer (outgoing data) + */ + unsigned char *MBEDTLS_PRIVATE(out_buf); /*!< output buffer */ + unsigned char *MBEDTLS_PRIVATE(out_ctr); /*!< 64-bit outgoing message counter */ + unsigned char *MBEDTLS_PRIVATE(out_hdr); /*!< start of record header */ +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + unsigned char *MBEDTLS_PRIVATE(out_cid); /*!< The start of the CID; + * (the end is marked by in_len). */ +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + unsigned char *MBEDTLS_PRIVATE(out_len); /*!< two-bytes message length field */ + unsigned char *MBEDTLS_PRIVATE(out_iv); /*!< ivlen-byte IV */ + unsigned char *MBEDTLS_PRIVATE(out_msg); /*!< message contents (out_iv+ivlen) */ + + int MBEDTLS_PRIVATE(out_msgtype); /*!< record header: message type */ + size_t MBEDTLS_PRIVATE(out_msglen); /*!< record header: message length */ + size_t MBEDTLS_PRIVATE(out_left); /*!< amount of data not yet written */ +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t MBEDTLS_PRIVATE(out_buf_len); /*!< length of output buffer */ +#endif + + unsigned char MBEDTLS_PRIVATE(cur_out_ctr)[MBEDTLS_SSL_SEQUENCE_NUMBER_LEN]; /*!< Outgoing record sequence number. */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + uint16_t MBEDTLS_PRIVATE(mtu); /*!< path mtu, used to fragment outgoing messages */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + /* + * User settings + */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + char *MBEDTLS_PRIVATE(hostname); /*!< expected peer CN for verification + (and SNI if available) */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_ALPN) + const char *MBEDTLS_PRIVATE(alpn_chosen); /*!< negotiated protocol */ +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_SSL_DTLS_SRTP) + /* + * use_srtp extension + */ + mbedtls_dtls_srtp_info MBEDTLS_PRIVATE(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 *MBEDTLS_PRIVATE(cli_id); /*!< transport-level ID of the client */ + size_t MBEDTLS_PRIVATE(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 MBEDTLS_PRIVATE(secure_renegotiation); /*!< does peer support legacy or + secure renegotiation */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + size_t MBEDTLS_PRIVATE(verify_data_len); /*!< length of verify data stored */ + char MBEDTLS_PRIVATE(own_verify_data)[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */ + char MBEDTLS_PRIVATE(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 MBEDTLS_PRIVATE(own_cid)[MBEDTLS_SSL_CID_IN_LEN_MAX]; + uint8_t MBEDTLS_PRIVATE(own_cid_len); /*!< The length of \c own_cid. */ + uint8_t MBEDTLS_PRIVATE(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_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) + int MBEDTLS_PRIVATE(early_data_status); +#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_CLI_C */ + + /** Callback to export key block and master secret */ + mbedtls_ssl_export_keys_t *MBEDTLS_PRIVATE(f_export_keys); + void *MBEDTLS_PRIVATE(p_export_keys); /*!< context for key export callback */ + + /** User data pointer or handle. + * + * The library sets this to \p 0 when creating a context and does not + * access it afterwards. + * + * \warning Serializing and restoring an SSL context with + * mbedtls_ssl_context_save() and mbedtls_ssl_context_load() + * does not currently restore the user data. + */ + mbedtls_ssl_user_data_t MBEDTLS_PRIVATE(user_data); +}; + +/** + * \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. + * + * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto + * subsystem must have been initialized by calling + * psa_crypto_init() before calling this function. + * + * \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 or + MBEDTLS_ERR_SSL_HW_ACCEL_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_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_EARLY_DATA) +/** + * \brief Set the early data mode + * Default: disabled on server and client + * + * \param conf The SSL configuration to use. + * \param early_data_enabled can be: + * + * MBEDTLS_SSL_EARLY_DATA_DISABLED: early data functionality is disabled + * This is the default on client and server. + * + * MBEDTLS_SSL_EARLY_DATA_ENABLED: early data functionality is enabled and + * may be negotiated in the handshake. Application using + * early data functionality needs to be aware of the + * lack of replay protection of the early data application + * payloads. + * + * \warning This interface is experimental and may change without notice. + * + */ +void mbedtls_ssl_tls13_conf_early_data(mbedtls_ssl_config *conf, + int early_data_enabled); + +#if defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Set the maximum amount of 0-RTT data in bytes + * Default: #MBEDTLS_SSL_MAX_EARLY_DATA_SIZE + * + * This function sets the value of the max_early_data_size + * field of the early data indication extension included in + * the NewSessionTicket messages that the server may send. + * + * The value defines the maximum amount of 0-RTT data + * in bytes that a client will be allowed to send when using + * one of the tickets defined by the NewSessionTicket messages. + * + * \note When resuming a session using a ticket, if the server receives more + * early data than allowed for the ticket, it terminates the connection. + * The maximum amount of 0-RTT data should thus be large enough + * to allow a minimum of early data to be exchanged. + * + * \param[in] conf The SSL configuration to use. + * \param[in] max_early_data_size The maximum amount of 0-RTT data. + * + * \warning This interface is experimental and may change without notice. + * + */ +void mbedtls_ssl_tls13_conf_max_early_data_size( + mbedtls_ssl_config *conf, uint32_t max_early_data_size); +#endif /* MBEDTLS_SSL_SRV_C */ + +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_EARLY_DATA */ + +#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 (mandatory) + * \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 Return the SSL configuration structure associated + * with the given SSL context. + * + * \note The pointer returned by this function is guaranteed to + * remain valid until the context is freed. + * + * \param ssl The SSL context to query. + * \return Pointer to the SSL configuration associated with \p ssl. + */ +static inline const mbedtls_ssl_config *mbedtls_ssl_context_get_config( + const mbedtls_ssl_context *ssl) +{ + return ssl->MBEDTLS_PRIVATE(conf); +} + +/** + * \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: RFC 9146 (or draft-ietf-tls-dtls-connection-id-05 + * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05 + * for legacy version) + * + * 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 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 our request for usage 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 requested to be used or not. If the CID is + * requested, `*enabled` is set to + * MBEDTLS_SSL_CID_ENABLED; otherwise, it is set to + * MBEDTLS_SSL_CID_DISABLED. + * \param own_cid The address of the buffer in which to store our own + * CID (if the CID extension is requested). This may be + * \c NULL in case the value of our CID isn't needed. If + * it is not \c NULL, \p own_cid_len must not be \c NULL. + * \param own_cid_len The address at which to store the size of our own CID + * (if the CID extension is requested). This is also the + * number of Bytes in \p own_cid that have been written. + * This may be \c NULL in case the length of our own CID + * isn't needed. If it is \c NULL, \p own_cid must be + * \c NULL, too. + * + *\note If we are requesting an empty CID this function sets + * `*enabled` to #MBEDTLS_SSL_CID_DISABLED (the rationale + * for this is that the resulting outcome is the + * same as if the CID extensions wasn't requested). + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_ssl_get_own_cid(mbedtls_ssl_context *ssl, + int *enabled, + unsigned char own_cid[MBEDTLS_SSL_CID_OUT_LEN_MAX], + 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. + * + * \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); + +/** + * \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); + +/** + * \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://mbed-tls.readthedocs.io/en/latest/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); + +#if defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Set the certificate selection callback (server-side only). + * + * If set, the callback is always called for each handshake, + * after `ClientHello` processing has finished. + * + * \param conf The SSL configuration to register the callback with. + * \param f_cert_cb The callback for selecting server certificate after + * `ClientHello` processing has finished. + */ +static inline void mbedtls_ssl_conf_cert_cb(mbedtls_ssl_config *conf, + mbedtls_ssl_hs_cb_t f_cert_cb) +{ + conf->MBEDTLS_PRIVATE(f_cert_cb) = f_cert_cb; +} +#endif /* MBEDTLS_SSL_SRV_C */ + +/** + * \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); + +/** + * \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 */ + +/** + * \brief Configure a key export callback. + * (Default: none.) + * + * This API can be used for two purposes: + * - Debugging: Use this API to e.g. generate an NSSKeylog + * file and use it to inspect encrypted traffic in tools + * such as Wireshark. + * - Application-specific export: Use this API to implement + * key exporters, e.g. for EAP-TLS or DTLS-SRTP. + * + * + * \param ssl The SSL context to which the export + * callback should be attached. + * \param f_export_keys The callback for the key export. + * \param p_export_keys The opaque context pointer to be passed to the + * callback \p f_export_keys. + */ +void mbedtls_ssl_set_export_keys_cb(mbedtls_ssl_context *ssl, + mbedtls_ssl_export_keys_t *f_export_keys, + void *p_export_keys); + +/** \brief Set the user data in an SSL configuration to a pointer. + * + * You can retrieve this value later with mbedtls_ssl_conf_get_user_data_p(). + * + * \note The library stores \c p without accessing it. It is the responsibility + * of the caller to ensure that the pointer remains valid. + * + * \param conf The SSL configuration context to modify. + * \param p The new value of the user data. + */ +static inline void mbedtls_ssl_conf_set_user_data_p( + mbedtls_ssl_config *conf, + void *p) +{ + conf->MBEDTLS_PRIVATE(user_data).p = p; +} + +/** \brief Set the user data in an SSL configuration to an integer. + * + * You can retrieve this value later with mbedtls_ssl_conf_get_user_data_n(). + * + * \param conf The SSL configuration context to modify. + * \param n The new value of the user data. + */ +static inline void mbedtls_ssl_conf_set_user_data_n( + mbedtls_ssl_config *conf, + uintptr_t n) +{ + conf->MBEDTLS_PRIVATE(user_data).n = n; +} + +/** \brief Retrieve the user data in an SSL configuration as a pointer. + * + * This is the value last set with mbedtls_ssl_conf_set_user_data_p(), or + * \c NULL if mbedtls_ssl_conf_set_user_data_p() has not previously been + * called. The value is undefined if mbedtls_ssl_conf_set_user_data_n() has + * been called without a subsequent call to mbedtls_ssl_conf_set_user_data_p(). + * + * \param conf The SSL configuration context to modify. + * \return The current value of the user data. + */ +static inline void *mbedtls_ssl_conf_get_user_data_p( + mbedtls_ssl_config *conf) +{ + return conf->MBEDTLS_PRIVATE(user_data).p; +} + +/** \brief Retrieve the user data in an SSL configuration as an integer. + * + * This is the value last set with mbedtls_ssl_conf_set_user_data_n(), or + * \c 0 if mbedtls_ssl_conf_set_user_data_n() has not previously been + * called. The value is undefined if mbedtls_ssl_conf_set_user_data_p() has + * been called without a subsequent call to mbedtls_ssl_conf_set_user_data_n(). + * + * \param conf The SSL configuration context to modify. + * \return The current value of the user data. + */ +static inline uintptr_t mbedtls_ssl_conf_get_user_data_n( + mbedtls_ssl_config *conf) +{ + return conf->MBEDTLS_PRIVATE(user_data).n; +} + +/** \brief Set the user data in an SSL context to a pointer. + * + * You can retrieve this value later with mbedtls_ssl_get_user_data_p(). + * + * \note The library stores \c p without accessing it. It is the responsibility + * of the caller to ensure that the pointer remains valid. + * + * \param ssl The SSL context to modify. + * \param p The new value of the user data. + */ +static inline void mbedtls_ssl_set_user_data_p( + mbedtls_ssl_context *ssl, + void *p) +{ + ssl->MBEDTLS_PRIVATE(user_data).p = p; +} + +/** \brief Set the user data in an SSL context to an integer. + * + * You can retrieve this value later with mbedtls_ssl_get_user_data_n(). + * + * \param ssl The SSL context to modify. + * \param n The new value of the user data. + */ +static inline void mbedtls_ssl_set_user_data_n( + mbedtls_ssl_context *ssl, + uintptr_t n) +{ + ssl->MBEDTLS_PRIVATE(user_data).n = n; +} + +/** \brief Retrieve the user data in an SSL context as a pointer. + * + * This is the value last set with mbedtls_ssl_set_user_data_p(), or + * \c NULL if mbedtls_ssl_set_user_data_p() has not previously been + * called. The value is undefined if mbedtls_ssl_set_user_data_n() has + * been called without a subsequent call to mbedtls_ssl_set_user_data_p(). + * + * \param ssl The SSL context to modify. + * \return The current value of the user data. + */ +static inline void *mbedtls_ssl_get_user_data_p( + mbedtls_ssl_context *ssl) +{ + return ssl->MBEDTLS_PRIVATE(user_data).p; +} + +/** \brief Retrieve the user data in an SSL context as an integer. + * + * This is the value last set with mbedtls_ssl_set_user_data_n(), or + * \c 0 if mbedtls_ssl_set_user_data_n() has not previously been + * called. The value is undefined if mbedtls_ssl_set_user_data_p() has + * been called without a subsequent call to mbedtls_ssl_set_user_data_n(). + * + * \param ssl The SSL context to modify. + * \return The current value of the user data. + */ +static inline uintptr_t mbedtls_ssl_get_user_data_n( + mbedtls_ssl_context *ssl) +{ + return ssl->MBEDTLS_PRIVATE(user_data).n; +} + +#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 */ + +/** + * \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); + +#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, + mbedtls_ssl_cache_get_t *f_get_cache, + mbedtls_ssl_cache_set_t *f_set_cache); +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Load a session for session resumption. + * + * Sessions loaded through this call will be considered + * for session resumption in the next handshake. + * + * \note Even if this call succeeds, it is not guaranteed that + * the next handshake will indeed be shortened through the + * use of session resumption: The server is always free + * to reject any attempt for resumption and fall back to + * a full handshake. + * + * \note This function can handle a variety of mechanisms for session + * resumption: For TLS 1.2, both session ID-based resumption and + * ticket-based resumption will be considered. For TLS 1.3, + * once implemented, sessions equate to tickets, and loading + * one or more sessions via this call will lead to their + * corresponding tickets being advertised as resumption PSKs + * by the client. + * + * \note Calling this function multiple times will only be useful + * once TLS 1.3 is supported. For TLS 1.2 connections, this + * function should be called at most once. + * + * \param ssl The SSL context representing the connection which should + * be attempted to be setup using session resumption. This + * must be initialized via mbedtls_ssl_init() and bound to + * an SSL configuration via mbedtls_ssl_setup(), but + * the handshake must not yet have been started. + * \param session The session to be considered for session resumption. + * This must be a session previously exported via + * mbedtls_ssl_get_session(), and potentially serialized and + * deserialized through mbedtls_ssl_session_save() and + * mbedtls_ssl_session_load() in the meantime. + * + * \return \c 0 if successful. + * \return \c MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if the session + * could not be loaded because of an implementation limitation. + * This error is non-fatal, and has no observable effect on + * the SSL context or the session that was attempted to be loaded. + * \return Another negative error code on other kinds of failure. + * + * \sa mbedtls_ssl_get_session() + * \sa mbedtls_ssl_session_load() + */ +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() + * + * \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 Set the list of allowed ciphersuites and the preference + * order. First in the list has the highest preference. + * + * For TLS 1.2, the notion of ciphersuite determines both + * the key exchange mechanism and the suite of symmetric + * algorithms to be used during and after the handshake. + * + * For TLS 1.3 (in development), the notion of ciphersuite + * only determines the suite of symmetric algorithms to be + * used during and after the handshake, while key exchange + * mechanisms are configured separately. + * + * In Mbed TLS, ciphersuites for both TLS 1.2 and TLS 1.3 + * are configured via this function. For users of TLS 1.3, + * there will be separate API for the configuration of key + * exchange mechanisms. + * + * The list of ciphersuites passed to this function may + * contain a mixture of TLS 1.2 and TLS 1.3 ciphersuite + * identifiers. This is useful if negotiation of TLS 1.3 + * should be attempted, but a fallback to TLS 1.2 would + * be tolerated. + * + * \note By default, the server chooses its preferred + * ciphersuite among those that the client supports. If + * mbedtls_ssl_conf_preference_order() is called to prefer + * the client's preferences, the server instead chooses + * the client's preferred ciphersuite among those that + * the server supports. + * + * \warning The ciphersuites array \p ciphersuites is not copied. + * It must remain valid for the lifetime of the SSL + * configuration \p conf. + * + * \param conf The SSL configuration to modify. + * \param ciphersuites A 0-terminated list of IANA identifiers of supported + * ciphersuites, accessible through \c MBEDTLS_TLS_XXX + * and \c MBEDTLS_TLS1_3_XXX macros defined in + * ssl_ciphersuites.h. + */ +void mbedtls_ssl_conf_ciphersuites(mbedtls_ssl_config *conf, + const int *ciphersuites); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) +/** + * \brief Set the supported key exchange modes for TLS 1.3 connections. + * + * In contrast to TLS 1.2, the ciphersuite concept in TLS 1.3 does not + * include the choice of key exchange mechanism. It is therefore not + * covered by the API mbedtls_ssl_conf_ciphersuites(). See the + * documentation of mbedtls_ssl_conf_ciphersuites() for more + * information on the ciphersuite concept in TLS 1.2 and TLS 1.3. + * + * The present function is specific to TLS 1.3 and allows users to + * configure the set of supported key exchange mechanisms in TLS 1.3. + * + * \param conf The SSL configuration the change should apply to. + * \param kex_modes A bitwise combination of one or more of the following: + * - MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK + * This flag enables pure-PSK key exchanges. + * - MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL + * This flag enables combined PSK-ephemeral key exchanges. + * - MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL + * This flag enables pure-ephemeral key exchanges. + * For convenience, the following pre-defined macros are + * available for combinations of the above: + * - MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_ALL + * Includes all of pure-PSK, PSK-ephemeral and pure-ephemeral. + * - MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL + * Includes both pure-PSK and combined PSK-ephemeral + * key exchanges, but excludes pure-ephemeral key exchanges. + * - MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ALL + * Includes both pure-ephemeral and combined PSK-ephemeral + * key exchanges. + * + * \note If a PSK-based key exchange mode shall be supported, applications + * must also use the APIs mbedtls_ssl_conf_psk() or + * mbedtls_ssl_conf_psk_cb() or mbedtls_ssl_conf_psk_opaque() + * to configure the PSKs to be used. + * + * \note If a pure-ephemeral key exchange mode shall be supported, + * server-side applications must also provide a certificate via + * mbedtls_ssl_conf_own_cert(). + * + */ + +void mbedtls_ssl_conf_tls13_key_exchange_modes(mbedtls_ssl_config *conf, + const int kex_modes); +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + +#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 */ + +#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_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) +/** + * \brief Set DN hints sent to client in CertificateRequest message + * + * \note If not set, subject distinguished names (DNs) are taken + * from \c mbedtls_ssl_conf_ca_chain() + * or \c mbedtls_ssl_set_hs_ca_chain()) + * + * \param conf SSL configuration + * \param crt crt chain whose subject DNs are issuer DNs of client certs + * from which the client should select client peer certificate. + */ +static inline +void mbedtls_ssl_conf_dn_hints(mbedtls_ssl_config *conf, + const mbedtls_x509_crt *crt) +{ + conf->MBEDTLS_PRIVATE(dn_hints) = crt; +} +#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ + +#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_SSL_HANDSHAKE_WITH_PSK_ENABLED) +/** + * \brief Configure pre-shared keys (PSKs) and their + * identities to be used in PSK-based ciphersuites. + * + * Only one PSK can be registered, through either + * mbedtls_ssl_conf_psk() or mbedtls_ssl_conf_psk_opaque(). + * If you attempt to register more than one PSK, this function + * fails, though this may change in future versions, which + * may add support for multiple PSKs. + * + * \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. + * + * \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 #MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if no more PSKs + * can be configured. In this case, the old PSK(s) remain intact. + * \return Another negative error code on other kinds of 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 one or more opaque pre-shared keys (PSKs) and + * their identities to be used in PSK-based ciphersuites. + * + * Only one PSK can be registered, through either + * mbedtls_ssl_conf_psk() or mbedtls_ssl_conf_psk_opaque(). + * If you attempt to register more than one PSK, this function + * fails, though this may change in future versions, which + * may add support for multiple PSKs. + * + * \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. + * + * \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 #MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if no more PSKs + * can be configured. In this case, the old PSK(s) remain intact. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ssl_conf_psk_opaque(mbedtls_ssl_config *conf, + mbedtls_svc_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, + mbedtls_svc_key_id_t psk); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_SSL_SRV_C) +/** + * \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_SSL_SRV_C */ +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */ + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) +/** + * \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) +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +/** + * \brief Set the allowed curves in order of preference. + * + * 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. + * + * \deprecated Superseded by mbedtls_ssl_conf_groups(). + * + * \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). + * + * \note The default list is the same set of curves that + * #mbedtls_x509_crt_profile_default allows, plus + * ECDHE-only curves selected according to the same criteria. + * The order favors curves with the lowest resource usage. + * + * \note New minor versions of Mbed TLS may extend this list, + * for example if new curves are added to the library. + * New minor versions of Mbed TLS will not remove items + * from this list unless serious security concerns require it. + * New minor versions of Mbed TLS may change the order in + * keeping with the general principle of favoring the lowest + * resource usage. + * + * \param conf SSL configuration + * \param curves Ordered list of allowed curves, + * terminated by MBEDTLS_ECP_DP_NONE. + */ +void MBEDTLS_DEPRECATED mbedtls_ssl_conf_curves(mbedtls_ssl_config *conf, + const mbedtls_ecp_group_id *curves); +#endif /* MBEDTLS_DEPRECATED_REMOVED */ +#endif /* MBEDTLS_ECP_C */ + +/** + * \brief Set the allowed groups in order of preference. + * + * On server: This only affects the choice of key agreement mechanism + * + * On client: this affects the list of groups offered for any + * use. The server can override our preference order. + * + * Both sides: limits the set of groups accepted for use in + * key sharing. + * + * \note This function replaces the deprecated mbedtls_ssl_conf_curves(), + * which only allows ECP curves to be configured. + * + * \note The most recent invocation of either mbedtls_ssl_conf_curves() + * or mbedtls_ssl_conf_groups() nullifies all previous invocations + * of both. + * + * \note This list should be ordered by decreasing preference + * (preferred group first). + * + * \note When this function is not called, a default list is used, + * consisting of all supported curves at 255 bits and above, + * and all supported finite fields at 2048 bits and above. + * The order favors groups with the lowest resource usage. + * + * \note New minor versions of Mbed TLS will not remove items + * from the default list unless serious security concerns require it. + * New minor versions of Mbed TLS may change the order in + * keeping with the general principle of favoring the lowest + * resource usage. + * + * \param conf SSL configuration + * \param groups List of allowed groups ordered by preference, terminated by 0. + * Must contain valid IANA NamedGroup IDs (provided via either an integer + * or using MBEDTLS_TLS1_3_NAMED_GROUP_XXX macros). + */ +void mbedtls_ssl_conf_groups(mbedtls_ssl_config *conf, + const uint16_t *groups); + +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) +#if !defined(MBEDTLS_DEPRECATED_REMOVED) && defined(MBEDTLS_SSL_PROTO_TLS1_2) +/** + * \brief Set the allowed hashes for signatures during the handshake. + * + * \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). + * + * \note By default, all supported hashes whose length is at least + * 256 bits are allowed. This is the same set as the default + * for certificate verification + * (#mbedtls_x509_crt_profile_default). + * The preference order is currently unspecified and may + * change in future versions. + * + * \note New minor versions of Mbed TLS may extend this list, + * for example if new curves are added to the library. + * New minor versions of Mbed TLS will not remove items + * from this list unless serious security concerns require it. + * + * \param conf SSL configuration + * \param hashes Ordered list of allowed signature hashes, + * terminated by \c MBEDTLS_MD_NONE. + */ +void MBEDTLS_DEPRECATED mbedtls_ssl_conf_sig_hashes(mbedtls_ssl_config *conf, + const int *hashes); +#endif /* !MBEDTLS_DEPRECATED_REMOVED && MBEDTLS_SSL_PROTO_TLS1_2 */ + +/** + * \brief Configure allowed signature algorithms for use in TLS 1.3 + * + * \param conf The SSL configuration to use. + * \param sig_algs List of allowed IANA values for TLS 1.3 signature algorithms, + * terminated by \c MBEDTLS_TLS1_3_SIG_NONE. The list must remain + * available throughout the lifetime of the conf object. Supported + * values are available as \c MBEDTLS_TLS1_3_SIG_XXXX + */ +void mbedtls_ssl_conf_sig_algs(mbedtls_ssl_config *conf, + const uint16_t *sig_algs); +#endif /* MBEDTLS_SSL_HANDSHAKE_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 Retrieve SNI extension value for the current handshake. + * Available in \p f_cert_cb of \c mbedtls_ssl_conf_cert_cb(), + * this is the same value passed to \p f_sni callback of + * \c mbedtls_ssl_conf_sni() and may be used instead of + * \c mbedtls_ssl_conf_sni(). + * + * \param ssl SSL context + * \param name_len pointer into which to store length of returned value. + * 0 if SNI extension is not present or not yet processed. + * + * \return const pointer to SNI extension value. + * - value is valid only when called in \p f_cert_cb + * registered with \c mbedtls_ssl_conf_cert_cb(). + * - value is NULL if SNI extension is not present. + * - value is not '\0'-terminated. Use \c name_len for len. + * - value must not be freed. + */ +const unsigned char *mbedtls_ssl_get_hs_sni(mbedtls_ssl_context *ssl, + size_t *name_len); + +/** + * \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 or the certificate selection callback. + * + * \note Passing null \c own_cert clears the certificate list for + * the current handshake. + * + * \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 or the certificate selection 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); + +#if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) +/** + * \brief Set DN hints sent to client in CertificateRequest message + * + * \note Same as \c mbedtls_ssl_conf_dn_hints() but for use within + * the SNI callback or the certificate selection callback. + * + * \param ssl SSL context + * \param crt crt chain whose subject DNs are issuer DNs of client certs + * from which the client should select client peer certificate. + */ +void mbedtls_ssl_set_hs_dn_hints(mbedtls_ssl_context *ssl, + const mbedtls_x509_crt *crt); +#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ + +/** + * \brief Set authmode for the current handshake. + * + * \note Same as \c mbedtls_ssl_conf_authmode() but for use within + * the SNI callback or the certificate selection 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 may return non-zero to abort the handshake. + * + * \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(). + * Password cannot be empty (see RFC 8236). + * + * \param ssl SSL context + * \param pw EC J-PAKE password (pre-shared secret). It cannot be empty + * \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); + +/** + * \brief Set the EC J-PAKE opaque password for current handshake. + * + * \note The key must remain valid until the handshake is over. + * + * \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 pwd EC J-PAKE opaque password + * + * \return 0 on success, or a negative error code. + */ +int mbedtls_ssl_set_hs_ecjpake_password_opaque(mbedtls_ssl_context *ssl, + mbedtls_svc_key_id_t pwd); +#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 */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +/** + * \brief Set the maximum supported version sent from the client side + * and/or accepted at the server side. + * + * See also the documentation of mbedtls_ssl_conf_min_version(). + * + * \note This ignores ciphersuites from higher versions. + * + * \note This function is deprecated and has been replaced by + * \c mbedtls_ssl_conf_max_tls_version(). + * + * \param conf SSL configuration + * \param major Major version number (#MBEDTLS_SSL_MAJOR_VERSION_3) + * \param minor Minor version number + * (#MBEDTLS_SSL_MINOR_VERSION_3 for (D)TLS 1.2, + * #MBEDTLS_SSL_MINOR_VERSION_4 for TLS 1.3) + */ +void MBEDTLS_DEPRECATED mbedtls_ssl_conf_max_version(mbedtls_ssl_config *conf, int major, + int minor); +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Set the maximum supported version sent from the client side + * and/or accepted at the server side. + * + * \note After the handshake, you can call + * mbedtls_ssl_get_version_number() to see what version was + * negotiated. + * + * \param conf SSL configuration + * \param tls_version TLS protocol version number (\p mbedtls_ssl_protocol_version) + * (#MBEDTLS_SSL_VERSION_UNKNOWN is not valid) + */ +static inline void mbedtls_ssl_conf_max_tls_version(mbedtls_ssl_config *conf, + mbedtls_ssl_protocol_version tls_version) +{ + conf->MBEDTLS_PRIVATE(max_tls_version) = tls_version; +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +/** + * \brief Set the minimum accepted SSL/TLS protocol version + * + * \note By default, all supported versions are accepted. + * Future versions of the library may disable older + * protocol versions by default if they become deprecated. + * + * \note The following versions are supported (if enabled at + * compile time): + * - (D)TLS 1.2: \p major = #MBEDTLS_SSL_MAJOR_VERSION_3, + * \p minor = #MBEDTLS_SSL_MINOR_VERSION_3 + * - TLS 1.3: \p major = #MBEDTLS_SSL_MAJOR_VERSION_3, + * \p minor = #MBEDTLS_SSL_MINOR_VERSION_4 + * + * Note that the numbers in the constant names are the + * TLS internal protocol numbers, and the minor versions + * differ by one from the human-readable versions! + * + * \note Input outside of the SSL_MAX_XXXXX_VERSION and + * SSL_MIN_XXXXX_VERSION range is ignored. + * + * \note After the handshake, you can call + * mbedtls_ssl_get_version_number() to see what version was + * negotiated. + * + * \note This function is deprecated and has been replaced by + * \c mbedtls_ssl_conf_min_tls_version(). + * + * \param conf SSL configuration + * \param major Major version number (#MBEDTLS_SSL_MAJOR_VERSION_3) + * \param minor Minor version number + * (#MBEDTLS_SSL_MINOR_VERSION_3 for (D)TLS 1.2, + * #MBEDTLS_SSL_MINOR_VERSION_4 for TLS 1.3) + */ +void MBEDTLS_DEPRECATED mbedtls_ssl_conf_min_version(mbedtls_ssl_config *conf, int major, + int minor); +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Set the minimum supported version sent from the client side + * and/or accepted at the server side. + * + * \note After the handshake, you can call + * mbedtls_ssl_get_version_number() to see what version was + * negotiated. + * + * \param conf SSL configuration + * \param tls_version TLS protocol version number (\p mbedtls_ssl_protocol_version) + * (#MBEDTLS_SSL_VERSION_UNKNOWN is not valid) + */ +static inline void mbedtls_ssl_conf_min_tls_version(mbedtls_ssl_config *conf, + mbedtls_ssl_protocol_version tls_version) +{ + conf->MBEDTLS_PRIVATE(min_tls_version) = tls_version; +} + +#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_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_SRV_C) +/** + * \brief Pick the ciphersuites order according to the second parameter + * in the SSL Server module (MBEDTLS_SSL_SRV_C). + * (Default, if never called: MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_SERVER) + * + * \param conf SSL configuration + * \param order Server or client (MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_SERVER + * or MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_CLIENT) + */ +void mbedtls_ssl_conf_preference_order(mbedtls_ssl_config *conf, int order); +#endif /* MBEDTLS_SSL_SRV_C */ + +#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_SESSION_TICKETS) && \ + defined(MBEDTLS_SSL_SRV_C) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_3) +/** + * \brief Number of NewSessionTicket messages for the server to send + * after handshake completion. + * + * \note The default value is + * \c MBEDTLS_SSL_TLS1_3_DEFAULT_NEW_SESSION_TICKETS. + * + * \note In case of a session resumption, this setting only partially apply. + * At most one ticket is sent in that case to just renew the pool of + * tickets of the client. The rationale is to avoid the number of + * tickets on the server to become rapidly out of control when the + * server has the same configuration for all its connection instances. + * + * \param conf SSL configuration + * \param num_tickets Number of NewSessionTicket. + * + */ +void mbedtls_ssl_conf_new_session_tickets(mbedtls_ssl_config *conf, + uint16_t num_tickets); +#endif /* MBEDTLS_SSL_SESSION_TICKETS && + MBEDTLS_SSL_SRV_C && + MBEDTLS_SSL_PROTO_TLS1_3*/ + +#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 id of the current ciphersuite + * + * \param ssl SSL context + * + * \return a ciphersuite id + */ +int mbedtls_ssl_get_ciphersuite_id_from_ssl(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 (D)TLS protocol version negotiated in the + * given connection. + * + * \note If you call this function too early during the initial + * handshake, before the two sides have agreed on a version, + * this function returns #MBEDTLS_SSL_VERSION_UNKNOWN. + * + * \param ssl The SSL context to query. + * \return The negotiated protocol version. + */ +static inline mbedtls_ssl_protocol_version mbedtls_ssl_get_version_number( + const mbedtls_ssl_context *ssl) +{ + return ssl->MBEDTLS_PRIVATE(tls_version); +} + +/** + * \brief Return the current TLS version + * + * \param ssl SSL context + * + * \return a string containing the TLS 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) + * + * \param ssl SSL context + * + * \return Current maximum record expansion in bytes + */ +int mbedtls_ssl_get_record_expansion(const mbedtls_ssl_context *ssl); + +/** + * \brief Return the current maximum outgoing record payload in bytes. + * + * \note The logic to determine the maximum outgoing record payload is + * version-specific. It takes into account various factors, such as + * the mbedtls_config.h setting \c MBEDTLS_SSL_OUT_CONTENT_LEN, extensions + * such as the max fragment length or record size limit 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. + * + * \sa mbedtls_ssl_get_max_out_record_payload() + * \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); + +/** + * \brief Return the current maximum incoming record payload in bytes. + * + * \note The logic to determine the maximum incoming record payload is + * version-specific. It takes into account various factors, such as + * the mbedtls_config.h setting \c MBEDTLS_SSL_IN_CONTENT_LEN, extensions + * such as the max fragment length extension or record size limit + * extension if used, and the current record expansion. + * + * \sa mbedtls_ssl_set_mtu() + * \sa mbedtls_ssl_get_max_in_record_payload() + * \sa mbedtls_ssl_get_record_expansion() + * + * \param ssl SSL context + * + * \return Current maximum payload for an incoming record, + * or a negative error code. + */ +int mbedtls_ssl_get_max_in_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 Export a session in order to resume it later. + * + * \param ssl The SSL context representing the connection for which to + * to export a session structure for later resumption. + * \param session The target structure in which to store the exported session. + * This must have been initialized with mbedtls_ssl_init_session() + * but otherwise be unused. + * + * \note This function can handle a variety of mechanisms for session + * resumption: For TLS 1.2, both session ID-based resumption and + * ticket-based resumption will be considered. For TLS 1.3, + * once implemented, sessions equate to tickets, and calling + * this function multiple times will export the available + * tickets one a time until no further tickets are available, + * in which case MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE will + * be returned. + * + * \note Calling this function multiple times will only be useful + * once TLS 1.3 is supported. For TLS 1.2 connections, this + * function should be called at most once. + * + * \return \c 0 if successful. In this case, \p session can be used for + * session resumption by passing it to mbedtls_ssl_set_session(), + * and serialized for storage via mbedtls_ssl_session_save(). + * \return #MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if no further session + * is available for export. + * This error is a non-fatal, and has no observable effect on + * the SSL context or the destination session. + * \return Another negative error code on other kinds of failure. + * + * \sa mbedtls_ssl_set_session() + * \sa mbedtls_ssl_session_save() + */ +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. + * + * \note If the context is configured to allow TLS 1.3, or if + * #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto + * subsystem must have been initialized by calling + * psa_crypto_init() before calling this function. + */ +int mbedtls_ssl_handshake(mbedtls_ssl_context *ssl); + +/** + * \brief After calling mbedtls_ssl_handshake() to start the SSL + * handshake you can call this function to check whether the + * handshake is over for a given SSL context. This function + * should be also used to determine when to stop calling + * mbedtls_handshake_step() for that context. + * + * \param ssl SSL context + * + * \return \c 1 if handshake is over, \c 0 if it is still ongoing. + */ +static inline int mbedtls_ssl_is_handshake_over(mbedtls_ssl_context *ssl) +{ + return ssl->MBEDTLS_PRIVATE(state) >= MBEDTLS_SSL_HANDSHAKE_OVER; +} + +/** + * \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 mbedtls_ssl_is_handshake_over() + * returns \c 1. + * + * \warning Whilst in the past you may have used direct access to the + * context state (ssl->state) in order to ascertain when to + * stop calling this function and although you can still do + * so with something like ssl->MBEDTLS_PRIVATE(state) or by + * defining MBEDTLS_ALLOW_PRIVATE_ACCESS, this is now + * considered deprecated and could be broken in any future + * release. If you still find you have good reason for such + * direct access, then please do contact the team to explain + * this (raise an issue or post to the mailing list), so that + * we can add a solution to your problem that will be + * guaranteed to work in the future. + * + * \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 than 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_max_out_record_payload() 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); + +#if defined(MBEDTLS_SSL_EARLY_DATA) + +#if defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Read at most 'len' application data bytes while performing + * the handshake (early data). + * + * \note This function behaves mainly as mbedtls_ssl_read(). The + * specification of mbedtls_ssl_read() relevant to TLS 1.3 + * (thus not the parts specific to (D)TLS 1.2) applies to this + * function and the present documentation is restricted to the + * differences with mbedtls_ssl_read(). + * + * \param ssl SSL context + * \param buf buffer that will hold the data + * \param len maximum number of bytes to read + * + * \return One additional specific return value: + * #MBEDTLS_ERR_SSL_CANNOT_READ_EARLY_DATA. + * + * #MBEDTLS_ERR_SSL_CANNOT_READ_EARLY_DATA is returned when it + * is not possible to read early data for the SSL context + * \p ssl. + * + * It may have been possible and it is not possible + * anymore because the server received the End of Early Data + * message or the maximum number of allowed early data for the + * PSK in use has been reached. + * + * It may never have been possible and will never be possible + * for the SSL context \p ssl because the use of early data + * is disabled for that context or more generally the context + * is not suitably configured to enable early data or the + * client does not use early data or the first call to the + * function was done while the handshake was already too + * advanced to gather and accept early data. + * + * It is not possible to read early data for the SSL context + * \p ssl but this does not preclude for using it with + * mbedtls_ssl_write(), mbedtls_ssl_read() or + * mbedtls_ssl_handshake(). + * + * \note When a server wants to retrieve early data, it is expected + * that this function starts the handshake for the SSL context + * \p ssl. But this is not mandatory. + * + */ +int mbedtls_ssl_read_early_data(mbedtls_ssl_context *ssl, + unsigned char *buf, size_t len); +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Try to write exactly 'len' application data bytes while + * performing the handshake (early data). + * + * \note This function behaves mainly as mbedtls_ssl_write(). The + * specification of mbedtls_ssl_write() relevant to TLS 1.3 + * (thus not the parts specific to (D)TLS1.2) applies to this + * function and the present documentation is restricted to the + * differences with mbedtls_ssl_write(). + * + * \param ssl SSL context + * \param buf buffer holding the data + * \param len how many bytes must be written + * + * \return One additional specific return value: + * #MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA. + * + * #MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA is returned when it + * is not possible to write early data for the SSL context + * \p ssl. + * + * It may have been possible and it is not possible + * anymore because the client received the server Finished + * message, the server rejected early data or the maximum + * number of allowed early data for the PSK in use has been + * reached. + * + * It may never have been possible and will never be possible + * for the SSL context \p ssl because the use of early data + * is disabled for that context or more generally the context + * is not suitably configured to enable early data or the first + * call to the function was done while the handshake was + * already completed. + * + * It is not possible to write early data for the SSL context + * \p ssl but this does not preclude for using it with + * mbedtls_ssl_write(), mbedtls_ssl_read() or + * mbedtls_ssl_handshake(). + * + * \note This function may write early data only if the SSL context + * has been configured for the handshake with a PSK for which + * early data is allowed. + * + * \note To maximize the number of early data that can be written in + * the course of the handshake, it is expected that this + * function starts the handshake for the SSL context \p ssl. + * But this is not mandatory. + * + * \note This function does not provide any information on whether + * the server has accepted or will accept early data or not. + * When it returns a positive value, it just means that it + * has written early data to the server. To know whether the + * server has accepted early data or not, you should call + * mbedtls_ssl_get_early_data_status() with the handshake + * completed. + */ +int mbedtls_ssl_write_early_data(mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len); + +#define MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT 0 +#define MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED 1 +#define MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED 2 +/** + * \brief Get the status of the negotiation of the use of early data. + * + * \param ssl The SSL context to query + * + * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if this function is called + * from the server-side. + * + * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if this function is called + * prior to completion of the handshake. + * + * \return #MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT if the client has + * not indicated the use of early data to the server. + * + * \return #MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED if the client has + * indicated the use of early data and the server has accepted + * it. + * + * \return #MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED if the client has + * indicated the use of early data but the server has rejected + * it. In this situation, the client may want to re-send the + * early data it may have tried to send by calling + * mbedtls_ssl_write_early_data() as ordinary post-handshake + * application data by calling mbedtls_ssl_write(). + * + */ +int mbedtls_ssl_get_early_data_status(mbedtls_ssl_context *ssl); +#endif /* MBEDTLS_SSL_CLI_C */ + +#endif /* MBEDTLS_SSL_EARLY_DATA */ + +/** + * \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 The serialized data only contains the data that is + * necessary to resume the connection: negotiated protocol + * options, session identifier, keys, etc. + * Loading a saved SSL context does not restore settings and + * state related to how the application accesses the context, + * such as configured callback functions, user data, pending + * incoming or outgoing data, etc. + * + * \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(), + * mbedtls_ssl_set_timer_cb(), and + * mbedtls_ssl_set_user_data_n() or + * mbedtls_ssl_set_user_data_p() if they were set originally. + * 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..55dcf77 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_cache.h @@ -0,0 +1,176 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#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 mbedtls_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 MBEDTLS_PRIVATE(timestamp); /*!< entry timestamp */ +#endif + + unsigned char MBEDTLS_PRIVATE(session_id)[32]; /*!< session ID */ + size_t MBEDTLS_PRIVATE(session_id_len); + + unsigned char *MBEDTLS_PRIVATE(session); /*!< serialized session */ + size_t MBEDTLS_PRIVATE(session_len); + + mbedtls_ssl_cache_entry *MBEDTLS_PRIVATE(next); /*!< chain pointer */ +}; + +/** + * \brief Cache context + */ +struct mbedtls_ssl_cache_context { + mbedtls_ssl_cache_entry *MBEDTLS_PRIVATE(chain); /*!< start of the chain */ + int MBEDTLS_PRIVATE(timeout); /*!< cache entry timeout */ + int MBEDTLS_PRIVATE(max_entries); /*!< maximum entries */ +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t MBEDTLS_PRIVATE(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 The SSL cache context to use. + * \param session_id The pointer to the buffer holding the session ID + * for the session to load. + * \param session_id_len The length of \p session_id in bytes. + * \param session The address at which to store the session + * associated with \p session_id, if present. + */ +int mbedtls_ssl_cache_get(void *data, + unsigned char const *session_id, + size_t session_id_len, + mbedtls_ssl_session *session); + +/** + * \brief Cache set callback implementation + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param data The SSL cache context to use. + * \param session_id The pointer to the buffer holding the session ID + * associated to \p session. + * \param session_id_len The length of \p session_id in bytes. + * \param session The session to store. + */ +int mbedtls_ssl_cache_set(void *data, + unsigned char const *session_id, + size_t session_id_len, + const mbedtls_ssl_session *session); + +/** + * \brief Remove the cache entry by the session ID + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param data The SSL cache context to use. + * \param session_id The pointer to the buffer holding the session ID + * associated to \p session. + * \param session_id_len The length of \p session_id in bytes. + * + * \return 0: The cache entry for session with provided ID + * is removed or does not exist. + * Otherwise: fail. + */ +int mbedtls_ssl_cache_remove(void *data, + unsigned char const *session_id, + size_t session_id_len); + +#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..17b8ff7 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_ciphersuites.h @@ -0,0 +1,549 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#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_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_AES_128_CBC_SHA 0x8C +#define MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA 0x8D + +#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_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_AES_128_CBC_SHA 0xC004 +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0xC005 + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA 0xC006 /**< Weak! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009 +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A + +#define MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA 0xC00B /**< Weak! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 0xC00E +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 0xC00F + +#define MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA 0xC010 /**< Weak! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013 +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014 + +#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_AES_128_CBC_SHA 0xC035 +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA 0xC036 +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 0xC037 +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 0xC038 +#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA 0xC039 +#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 0xC03A +#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 0xC03B + +#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 +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC073 +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC074 +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC075 +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xC076 +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 0xC077 +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xC078 +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 0xC079 + +#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 +#define MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC09B + +#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 */ + +/* RFC 8446, Appendix B.4 */ +#define MBEDTLS_TLS1_3_AES_128_GCM_SHA256 0x1301 /**< TLS 1.3 */ +#define MBEDTLS_TLS1_3_AES_256_GCM_SHA384 0x1302 /**< TLS 1.3 */ +#define MBEDTLS_TLS1_3_CHACHA20_POLY1305_SHA256 0x1303 /**< TLS 1.3 */ +#define MBEDTLS_TLS1_3_AES_128_CCM_SHA256 0x1304 /**< TLS 1.3 */ +#define MBEDTLS_TLS1_3_AES_128_CCM_8_SHA256 0x1305 /**< TLS 1.3 */ + +/* 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 + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) || \ + defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) +#define MBEDTLS_SSL_HANDSHAKE_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 + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) || \ + defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) +#define MBEDTLS_SSL_HANDSHAKE_WITH_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 + * + * \note members are defined using integral types instead of enums + * in order to pack structure and reduce memory usage by internal + * \c ciphersuite_definitions[] + */ +struct mbedtls_ssl_ciphersuite_t { + int MBEDTLS_PRIVATE(id); + const char *MBEDTLS_PRIVATE(name); + + uint8_t MBEDTLS_PRIVATE(cipher); /* mbedtls_cipher_type_t */ + uint8_t MBEDTLS_PRIVATE(mac); /* mbedtls_md_type_t */ + uint8_t MBEDTLS_PRIVATE(key_exchange); /* mbedtls_key_exchange_type_t */ + uint8_t MBEDTLS_PRIVATE(flags); + + uint16_t MBEDTLS_PRIVATE(min_tls_version); /* mbedtls_ssl_protocol_version */ + uint16_t MBEDTLS_PRIVATE(max_tls_version); /* mbedtls_ssl_protocol_version */ +}; + +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); +#if defined(MBEDTLS_USE_PSA_CRYPTO) +psa_algorithm_t mbedtls_ssl_get_ciphersuite_sig_pk_psa_alg(const mbedtls_ssl_ciphersuite_t *info); +psa_key_usage_t mbedtls_ssl_get_ciphersuite_sig_pk_psa_usage(const mbedtls_ssl_ciphersuite_t *info); +#endif +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); + +static inline const char *mbedtls_ssl_ciphersuite_get_name(const mbedtls_ssl_ciphersuite_t *info) +{ + return info->MBEDTLS_PRIVATE(name); +} + +size_t mbedtls_ssl_ciphersuite_get_cipher_key_bitlen(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->MBEDTLS_PRIVATE(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->MBEDTLS_PRIVATE(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->MBEDTLS_PRIVATE(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->MBEDTLS_PRIVATE(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->MBEDTLS_PRIVATE(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->MBEDTLS_PRIVATE(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->MBEDTLS_PRIVATE(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->MBEDTLS_PRIVATE(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..5cd1847 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_cookie.h @@ -0,0 +1,118 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include "mbedtls/ssl.h" + +#if !defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif +#endif /* !MBEDTLS_USE_PSA_CRYPTO */ + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in mbedtls_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 { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + mbedtls_svc_key_id_t MBEDTLS_PRIVATE(psa_hmac_key); /*!< key id for the HMAC portion */ + psa_algorithm_t MBEDTLS_PRIVATE(psa_hmac_alg); /*!< key algorithm for the HMAC portion */ +#else + mbedtls_md_context_t MBEDTLS_PRIVATE(hmac_ctx); /*!< context for the HMAC portion */ +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#if !defined(MBEDTLS_HAVE_TIME) + unsigned long MBEDTLS_PRIVATE(serial); /*!< serial number for expiration */ +#endif + unsigned long MBEDTLS_PRIVATE(timeout); /*!< timeout delay, in seconds if HAVE_TIME, + or in number of tickets issued */ + +#if !defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t MBEDTLS_PRIVATE(mutex); +#endif +#endif /* !MBEDTLS_USE_PSA_CRYPTO */ +} 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_ticket.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_ticket.h new file mode 100644 index 0000000..0cefe43 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_ticket.h @@ -0,0 +1,193 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +/* + * 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_HAVE_TIME) +#include "mbedtls/platform_time.h" +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#endif + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define MBEDTLS_SSL_TICKET_MAX_KEY_BYTES 32 /*!< Max supported key length in bytes */ +#define MBEDTLS_SSL_TICKET_KEY_NAME_BYTES 4 /*!< key name length in bytes */ + +/** + * \brief Information for session ticket protection + */ +typedef struct mbedtls_ssl_ticket_key { + unsigned char MBEDTLS_PRIVATE(name)[MBEDTLS_SSL_TICKET_KEY_NAME_BYTES]; + /*!< random key identifier */ +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t MBEDTLS_PRIVATE(generation_time); /*!< key generation timestamp (seconds) */ +#endif +#if !defined(MBEDTLS_USE_PSA_CRYPTO) + mbedtls_cipher_context_t MBEDTLS_PRIVATE(ctx); /*!< context for auth enc/decryption */ +#else + mbedtls_svc_key_id_t MBEDTLS_PRIVATE(key); /*!< key used for auth enc/decryption */ + psa_algorithm_t MBEDTLS_PRIVATE(alg); /*!< algorithm of auth enc/decryption */ + psa_key_type_t MBEDTLS_PRIVATE(key_type); /*!< key type */ + size_t MBEDTLS_PRIVATE(key_bits); /*!< key length in bits */ +#endif +} +mbedtls_ssl_ticket_key; + +/** + * \brief Context for session ticket handling functions + */ +typedef struct mbedtls_ssl_ticket_context { + mbedtls_ssl_ticket_key MBEDTLS_PRIVATE(keys)[2]; /*!< ticket protection keys */ + unsigned char MBEDTLS_PRIVATE(active); /*!< index of the currently active key */ + + uint32_t MBEDTLS_PRIVATE(ticket_lifetime); /*!< lifetime of tickets in seconds */ + + /** Callback for getting (pseudo-)random numbers */ + int(*MBEDTLS_PRIVATE(f_rng))(void *, unsigned char *, size_t); + void *MBEDTLS_PRIVATE(p_rng); /*!< context for the RNG function */ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t MBEDTLS_PRIVATE(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 (mandatory) + * \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 Rotate session ticket encryption key to new specified key. + * Provides for external control of session ticket encryption + * key rotation, e.g. for synchronization between different + * machines. If this function is not used, or if not called + * before ticket lifetime expires, then a new session ticket + * encryption key is generated internally in order to avoid + * unbounded session ticket encryption key lifetimes. + * + * \param ctx Context to be set up + * \param name Session ticket encryption key name + * \param nlength Session ticket encryption key name length in bytes + * \param k Session ticket encryption key + * \param klength Session ticket encryption key length in bytes + * \param lifetime Tickets lifetime in seconds + * Recommended value: 86400 (one day). + * + * \note \c name and \c k are recommended to be cryptographically + * random data. + * + * \note \c nlength must match sizeof( ctx->name ) + * + * \note \c klength must be sufficient for use by cipher specified + * to \c mbedtls_ssl_ticket_setup + * + * \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_rotate(mbedtls_ssl_ticket_context *ctx, + const unsigned char *name, size_t nlength, + const unsigned char *k, size_t klength, + 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..1b9c7ce --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/threading.h @@ -0,0 +1,117 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** 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 MBEDTLS_PRIVATE(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 MBEDTLS_PRIVATE(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..2d4a19c --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/timing.h @@ -0,0 +1,106 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_TIMING_ALT) +// Regular implementation +// + +/** + * \brief timer structure + */ +struct mbedtls_timing_hr_time { + unsigned char MBEDTLS_PRIVATE(opaque)[32]; +}; + +/** + * \brief Context for mbedtls_timing_set/get_delay() + */ +typedef struct mbedtls_timing_delay_context { + struct mbedtls_timing_hr_time MBEDTLS_PRIVATE(timer); + uint32_t MBEDTLS_PRIVATE(int_ms); + uint32_t MBEDTLS_PRIVATE(fin_ms); +} mbedtls_timing_delay_context; + +#else /* MBEDTLS_TIMING_ALT */ +#include "timing_alt.h" +#endif /* MBEDTLS_TIMING_ALT */ + +/* Internal use */ +unsigned long mbedtls_timing_get_timer(struct mbedtls_timing_hr_time *val, int reset); + +/** + * \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); + +/** + * \brief Get the final timing delay + * + * \param data Pointer to timing data + * Must point to a valid \c mbedtls_timing_delay_context struct. + * + * \return Final timing delay in milliseconds. + */ +uint32_t mbedtls_timing_get_final_delay( + const mbedtls_timing_delay_context *data); + +#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..bb1a4c3 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/version.h @@ -0,0 +1,90 @@ +/** + * \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 run-time variables can be used to determine the version number of + * the Mbed TLS library used. Compile-time version defines for the same can be + * found in build_info.h + */ +#ifndef MBEDTLS_VERSION_H +#define MBEDTLS_VERSION_H + +#include "mbedtls/build_info.h" + +#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 mbedtls_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..bd1947e --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/x509.h @@ -0,0 +1,485 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#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 mbedtls_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; + +/** + * From RFC 5280 section 4.2.1.6: + * OtherName ::= SEQUENCE { + * type-id OBJECT IDENTIFIER, + * value [0] EXPLICIT ANY DEFINED BY type-id } + * + * Future versions of the library may add new fields to this structure or + * to its embedded union and structure. + */ +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. + * + * Future versions of the library may add new fields to this structure or + * to its embedded union and structure. + */ +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 unconstructed types. Only rfc822Name, dnsName and uniformResourceIdentifier are currently supported */ + } + san; /**< A union of the supported SAN types */ +} +mbedtls_x509_subject_alternative_name; + +/** \} 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 Return the next relative DN in an X509 name. + * + * \note Intended use is to compare function result to dn->next + * in order to detect boundaries of multi-valued RDNs. + * + * \param dn Current node in the X509 name + * + * \return Pointer to the first attribute-value pair of the + * next RDN in sequence, or NULL if end is reached. + */ +static inline mbedtls_x509_name *mbedtls_x509_dn_get_next( + mbedtls_x509_name *dn) +{ + while (dn->MBEDTLS_PRIVATE(next_merged) && dn->next != NULL) { + dn = dn->next; + } + return dn->next; +} + +/** + * \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); + +/** + * \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 Supported GeneralName types, as defined in RFC 5280: + * "rfc822Name", "dnsName", "uniformResourceIdentifier" and "hardware_module_name" + * of type "otherName", as defined in RFC 4108. + * + * \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); + +/** \} addtogroup x509_module */ + +/* + * 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); +#if !defined(MBEDTLS_X509_REMOVE_INFO) +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); +#endif +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); +int mbedtls_x509_get_ns_cert_type(unsigned char **p, + const unsigned char *end, + unsigned char *ns_cert_type); +int mbedtls_x509_get_key_usage(unsigned char **p, + const unsigned char *end, + unsigned int *key_usage); +int mbedtls_x509_get_subject_alt_name(unsigned char **p, + const unsigned char *end, + mbedtls_x509_sequence *subject_alt_name); +int mbedtls_x509_info_subject_alt_name(char **buf, size_t *size, + const mbedtls_x509_sequence + *subject_alt_name, + const char *prefix); +int mbedtls_x509_info_cert_type(char **buf, size_t *size, + unsigned char ns_cert_type); +int mbedtls_x509_info_key_usage(char **buf, size_t *size, + unsigned int key_usage); + +#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..62694ae --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/x509_crl.h @@ -0,0 +1,196 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#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. + * + * Some fields of this structure are publicly readable. Do not modify + * them except via Mbed TLS library functions: the effect of modifying + * those fields or the data that those fields points to is unspecified. + */ +typedef struct mbedtls_x509_crl_entry { + /** Direct access to the whole entry inside the containing buffer. */ + mbedtls_x509_buf raw; + /** The serial number of the revoked certificate. */ + mbedtls_x509_buf serial; + /** The revocation date of this entry. */ + mbedtls_x509_time revocation_date; + /** Direct access to the list of CRL entry extensions + * (an ASN.1 constructed sequence). + * + * If there are no extensions, `entry_ext.len == 0` and + * `entry_ext.p == NULL`. */ + mbedtls_x509_buf entry_ext; + + /** Next element in the linked list of entries. + * \p NULL indicates the end of the list. + * Do not modify this field directly. */ + 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 MBEDTLS_PRIVATE(sig_oid2); + mbedtls_x509_buf MBEDTLS_PRIVATE(sig); + mbedtls_md_type_t MBEDTLS_PRIVATE(sig_md); /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ + mbedtls_pk_type_t MBEDTLS_PRIVATE(sig_pk); /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ + void *MBEDTLS_PRIVATE(sig_opts); /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ + + /** Next element in the linked list of CRL. + * \p NULL indicates the end of the list. + * Do not modify this field directly. */ + struct mbedtls_x509_crl *next; +} +mbedtls_x509_crl; + +/** + * \brief Parse a DER-encoded CRL and append it to the chained list + * + * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto + * subsystem must have been initialized by calling + * psa_crypto_init() before calling this function. + * + * \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 + * + * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto + * subsystem must have been initialized by calling + * psa_crypto_init() before calling this function. + * + * \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 + * + * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto + * subsystem must have been initialized by calling + * psa_crypto_init() before calling this function. + * + * \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 */ + +#if !defined(MBEDTLS_X509_REMOVE_INFO) +/** + * \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); +#endif /* !MBEDTLS_X509_REMOVE_INFO */ + +/** + * \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..11e5951 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/x509_crt.h @@ -0,0 +1,1187 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" +#include "mbedtls/legacy_or_psa.h" + +#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. + * + * Some fields of this structure are publicly readable. Do not modify + * them except via Mbed TLS library functions: the effect of modifying + * those fields or the data that those fields points to is unspecified. + */ +typedef struct mbedtls_x509_crt { + int MBEDTLS_PRIVATE(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, uniformResourceIdentifier 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 MBEDTLS_PRIVATE(ext_types); /**< Bit string containing detected and parsed extensions */ + int MBEDTLS_PRIVATE(ca_istrue); /**< Optional Basic Constraint extension value: 1 if this certificate belongs to a CA, 0 otherwise. */ + int MBEDTLS_PRIVATE(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 MBEDTLS_PRIVATE(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 MBEDTLS_PRIVATE(ns_cert_type); /**< Optional Netscape certificate type extension value: See the values in x509.h */ + + mbedtls_x509_buf MBEDTLS_PRIVATE(sig); /**< Signature: hash of the tbs part signed with the private key. */ + mbedtls_md_type_t MBEDTLS_PRIVATE(sig_md); /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ + mbedtls_pk_type_t MBEDTLS_PRIVATE(sig_pk); /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ + void *MBEDTLS_PRIVATE(sig_opts); /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ + + /** Next certificate in the linked list that constitutes the CA chain. + * \p NULL indicates the end of the list. + * Do not modify this field directly. */ + struct mbedtls_x509_crt *next; +} +mbedtls_x509_crt; + +/** + * 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(). + * + * The fields of this structure are part of the public API and can be + * manipulated directly by applications. Future versions of the library may + * add extra fields or reorder existing fields. + * + * You can create custom profiles by starting from a copy of + * an existing profile, such as mbedtls_x509_crt_profile_default or + * mbedtls_x509_ctr_profile_none and then tune it to your needs. + * + * For example to allow SHA-224 in addition to the default: + * + * mbedtls_x509_crt_profile my_profile = mbedtls_x509_crt_profile_default; + * my_profile.allowed_mds |= MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ); + * + * Or to allow only RSA-3072+ with SHA-256: + * + * mbedtls_x509_crt_profile my_profile = mbedtls_x509_crt_profile_none; + * my_profile.allowed_mds = MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ); + * my_profile.allowed_pks = MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_RSA ); + * my_profile.rsa_min_bitlen = 3072; + */ +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 20 +#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 + +/* This macro unfolds to the concatenation of macro invocations + * X509_CRT_ERROR_INFO( error code, + * error code as string, + * human readable description ) + * where X509_CRT_ERROR_INFO is defined by the user. + * See x509_crt.c for an example of how to use this. */ +#define MBEDTLS_X509_CRT_ERROR_INFO_LIST \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_EXPIRED, \ + "MBEDTLS_X509_BADCERT_EXPIRED", \ + "The certificate validity has expired") \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_REVOKED, \ + "MBEDTLS_X509_BADCERT_REVOKED", \ + "The certificate has been revoked (is on a CRL)") \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_CN_MISMATCH, \ + "MBEDTLS_X509_BADCERT_CN_MISMATCH", \ + "The certificate Common Name (CN) does not match with the expected CN") \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_NOT_TRUSTED, \ + "MBEDTLS_X509_BADCERT_NOT_TRUSTED", \ + "The certificate is not correctly signed by the trusted CA") \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCRL_NOT_TRUSTED, \ + "MBEDTLS_X509_BADCRL_NOT_TRUSTED", \ + "The CRL is not correctly signed by the trusted CA") \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCRL_EXPIRED, \ + "MBEDTLS_X509_BADCRL_EXPIRED", \ + "The CRL is expired") \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_MISSING, \ + "MBEDTLS_X509_BADCERT_MISSING", \ + "Certificate was missing") \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_SKIP_VERIFY, \ + "MBEDTLS_X509_BADCERT_SKIP_VERIFY", \ + "Certificate verification was skipped") \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_OTHER, \ + "MBEDTLS_X509_BADCERT_OTHER", \ + "Other reason (can be used by verify callback)") \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_FUTURE, \ + "MBEDTLS_X509_BADCERT_FUTURE", \ + "The certificate validity starts in the future") \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCRL_FUTURE, \ + "MBEDTLS_X509_BADCRL_FUTURE", \ + "The CRL is from the future") \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_KEY_USAGE, \ + "MBEDTLS_X509_BADCERT_KEY_USAGE", \ + "Usage does not match the keyUsage extension") \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_EXT_KEY_USAGE, \ + "MBEDTLS_X509_BADCERT_EXT_KEY_USAGE", \ + "Usage does not match the extendedKeyUsage extension") \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_NS_CERT_TYPE, \ + "MBEDTLS_X509_BADCERT_NS_CERT_TYPE", \ + "Usage does not match the nsCertType extension") \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_BAD_MD, \ + "MBEDTLS_X509_BADCERT_BAD_MD", \ + "The certificate is signed with an unacceptable hash.") \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_BAD_PK, \ + "MBEDTLS_X509_BADCERT_BAD_PK", \ + "The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA).") \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_BAD_KEY, \ + "MBEDTLS_X509_BADCERT_BAD_KEY", \ + "The certificate is signed with an unacceptable key (eg bad curve, RSA too short).") \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCRL_BAD_MD, \ + "MBEDTLS_X509_BADCRL_BAD_MD", \ + "The CRL is signed with an unacceptable hash.") \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCRL_BAD_PK, \ + "MBEDTLS_X509_BADCRL_BAD_PK", \ + "The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA).") \ + X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCRL_BAD_KEY, \ + "MBEDTLS_X509_BADCRL_BAD_KEY", \ + "The CRL is signed with an unacceptable key (eg bad curve, RSA too short).") + +/** + * Container for writing a certificate (CRT) + */ +typedef struct mbedtls_x509write_cert { + int MBEDTLS_PRIVATE(version); + unsigned char MBEDTLS_PRIVATE(serial)[MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN]; + size_t MBEDTLS_PRIVATE(serial_len); + mbedtls_pk_context *MBEDTLS_PRIVATE(subject_key); + mbedtls_pk_context *MBEDTLS_PRIVATE(issuer_key); + mbedtls_asn1_named_data *MBEDTLS_PRIVATE(subject); + mbedtls_asn1_named_data *MBEDTLS_PRIVATE(issuer); + mbedtls_md_type_t MBEDTLS_PRIVATE(md_alg); + char MBEDTLS_PRIVATE(not_before)[MBEDTLS_X509_RFC5280_UTC_TIME_LEN + 1]; + char MBEDTLS_PRIVATE(not_after)[MBEDTLS_X509_RFC5280_UTC_TIME_LEN + 1]; + mbedtls_asn1_named_data *MBEDTLS_PRIVATE(extensions); +} +mbedtls_x509write_cert; + +/** + * Item in a verification chain: cert and flags for it + */ +typedef struct { + mbedtls_x509_crt *MBEDTLS_PRIVATE(crt); + uint32_t MBEDTLS_PRIVATE(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 MBEDTLS_PRIVATE(items)[MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE]; + unsigned MBEDTLS_PRIVATE(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 *MBEDTLS_PRIVATE(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 MBEDTLS_PRIVATE(pk); + + /* for find_parent_in() */ + mbedtls_x509_crt *MBEDTLS_PRIVATE(parent); /* non-null iff parent_in in progress */ + mbedtls_x509_crt *MBEDTLS_PRIVATE(fallback_parent); + int MBEDTLS_PRIVATE(fallback_signature_is_good); + + /* for find_parent() */ + int MBEDTLS_PRIVATE(parent_is_trusted); /* -1 if find_parent is not in progress */ + + /* for verify_chain() */ + enum { + x509_crt_rs_none, + x509_crt_rs_find_parent, + } MBEDTLS_PRIVATE(in_progress); /* none if no operation is in progress */ + int MBEDTLS_PRIVATE(self_cnt); + mbedtls_x509_crt_verify_chain MBEDTLS_PRIVATE(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 with at least 256 bits: SHA-256, SHA-384, SHA-512. + * - Elliptic curves with 255 bits and above except secp256k1. + * - RSA with 2048 bits and above. + * + * New minor versions of Mbed TLS may extend this profile, for example if + * new algorithms 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. + * This profile may change at any time. + */ +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; + +/** + * Empty profile that allows nothing. Useful as a basis for constructing + * custom profiles. + */ +extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_none; + +/** + * \brief Parse a single DER formatted certificate and add it + * to the end of the provided chained list. + * + * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto + * subsystem must have been initialized by calling + * psa_crypto_init() before calling this function. + * + * \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. + * + * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto + * subsystem must have been initialized by calling + * psa_crypto_init() before calling this function. + * + * \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. + * + * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto + * subsystem must have been initialized by calling + * psa_crypto_init() before calling this function. + * + * \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 lifetime 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. + * + * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto + * subsystem must have been initialized by calling + * psa_crypto_init() before calling this function. + * + * \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. + * + * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto + * subsystem must have been initialized by calling + * psa_crypto_init() before calling this function. + * + * \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 */ +#if !defined(MBEDTLS_X509_REMOVE_INFO) +/** + * \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); +#endif /* !MBEDTLS_X509_REMOVE_INFO */ + +/** + * \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 */ + +/** + * \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); + +/** + * \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); + +#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 */ + +/** + * \brief Query certificate for given extension type + * + * \param[in] ctx Certificate context to be queried, must not be \c NULL + * \param ext_type Extension type being queried for, must be a valid + * extension type. Must be one of the MBEDTLS_X509_EXT_XXX + * values + * + * \return 0 if the given extension type is not present, + * non-zero otherwise + */ +static inline int mbedtls_x509_crt_has_ext_type(const mbedtls_x509_crt *ctx, + int ext_type) +{ + return ctx->MBEDTLS_PRIVATE(ext_types) & ext_type; +} + +/** \} 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); + +#if defined(MBEDTLS_BIGNUM_C) && !defined(MBEDTLS_DEPRECATED_REMOVED) +/** + * \brief Set the serial number for a Certificate. + * + * \deprecated This function is deprecated and will be removed in a + * future version of the library. Please use + * mbedtls_x509write_crt_set_serial_raw() instead. + * + * \note Even though the MBEDTLS_BIGNUM_C guard looks redundant since + * X509 depends on PK and PK depends on BIGNUM, this emphasizes + * a direct dependency between X509 and BIGNUM which is going + * to be deprecated in the future. + * + * \param ctx CRT context to use + * \param serial serial number to set + * + * \return 0 if successful + */ +int MBEDTLS_DEPRECATED mbedtls_x509write_crt_set_serial( + mbedtls_x509write_cert *ctx, const mbedtls_mpi *serial); +#endif // MBEDTLS_BIGNUM_C && !MBEDTLS_DEPRECATED_REMOVED + +/** + * \brief Set the serial number for a Certificate. + * + * \param ctx CRT context to use + * \param serial A raw array of bytes containing the serial number in big + * endian format + * \param serial_len Length of valid bytes (expressed in bytes) in \p serial + * input buffer + * + * \return 0 if successful, or + * MBEDTLS_ERR_X509_BAD_INPUT_DATA if the provided input buffer + * is too big (longer than MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN) + */ +int mbedtls_x509write_crt_set_serial_raw(mbedtls_x509write_cert *ctx, + unsigned char *serial, size_t serial_len); + +/** + * \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_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA) +/** + * \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_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA */ + +/** + * \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 Extended Key Usage Extension + * (e.g. MBEDTLS_OID_SERVER_AUTH) + * + * \param ctx CRT context to use + * \param exts extended key usage extensions to set, a sequence of + * MBEDTLS_ASN1_OID objects + * + * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_ext_key_usage(mbedtls_x509write_cert *ctx, + const mbedtls_asn1_sequence *exts); + +/** + * \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. This must not be \c NULL. + * \param p_rng RNG parameter + * + * \return length of data written if successful, or a specific + * error code + * + * \note \p f_rng is used for the signature operation. + */ +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. This must not be \c NULL. + * \param p_rng RNG parameter + * + * \return 0 if successful, or a specific error code + * + * \note \p f_rng is used for the signature operation. + */ +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..f3f9e13 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/x509_csr.h @@ -0,0 +1,337 @@ +/** + * \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 +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#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. + * + * Some fields of this structure are publicly readable. Do not modify + * them except via Mbed TLS library functions: the effect of modifying + * those fields or the data that those fields point to is unspecified. + */ +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. */ + + unsigned int key_usage; /**< Optional key usage extension value: See the values in x509.h */ + unsigned char ns_cert_type; /**< Optional Netscape certificate type extension value: See the values in x509.h */ + mbedtls_x509_sequence subject_alt_names; /**< Optional list of raw entries of Subject Alternative Names extension (currently only dNSName and OtherName are listed). */ + + int MBEDTLS_PRIVATE(ext_types); /**< Bit string containing detected and parsed extensions */ + + mbedtls_x509_buf sig_oid; + mbedtls_x509_buf MBEDTLS_PRIVATE(sig); + mbedtls_md_type_t MBEDTLS_PRIVATE(sig_md); /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ + mbedtls_pk_type_t MBEDTLS_PRIVATE(sig_pk); /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ + void *MBEDTLS_PRIVATE(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 *MBEDTLS_PRIVATE(key); + mbedtls_asn1_named_data *MBEDTLS_PRIVATE(subject); + mbedtls_md_type_t MBEDTLS_PRIVATE(md_alg); + mbedtls_asn1_named_data *MBEDTLS_PRIVATE(extensions); +} +mbedtls_x509write_csr; + +typedef struct mbedtls_x509_san_list { + mbedtls_x509_subject_alternative_name node; + struct mbedtls_x509_san_list *next; +} +mbedtls_x509_san_list; + +#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. + * + * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto + * subsystem must have been initialized by calling + * psa_crypto_init() before calling this function. + * + * \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() + * + * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto + * subsystem must have been initialized by calling + * psa_crypto_init() before calling this function. + * + * \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 */ + +#if !defined(MBEDTLS_X509_REMOVE_INFO) +/** + * \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); +#endif /* !MBEDTLS_X509_REMOVE_INFO */ + +/** + * \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 Subject Alternative Name + * + * \param ctx CSR context to use + * \param san_list List of SAN values + * + * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED + * + * \note Only "dnsName", "uniformResourceIdentifier" and "otherName", + * as defined in RFC 5280, are supported. + */ +int mbedtls_x509write_csr_set_subject_alternative_name(mbedtls_x509write_csr *ctx, + const mbedtls_x509_san_list *san_list); + +/** + * \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 critical Set to 1 to mark the extension as critical, 0 otherwise. + * \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, + int critical, + 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. This must not be \c NULL. + * \param p_rng RNG parameter + * + * \return length of data written if successful, or a specific + * error code + * + * \note \p f_rng is used for the signature operation. + */ +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. This must not be \c NULL. + * \param p_rng RNG parameter + * + * \return 0 if successful, or a specific error code + * + * \note \p f_rng is used for the signature operation. + */ +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/psa/crypto.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto.h new file mode 100644 index 0000000..8a05efd --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto.h @@ -0,0 +1,4697 @@ +/** + * \file psa/crypto.h + * \brief Platform Security Architecture cryptography 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. + */ + +#ifndef PSA_CRYPTO_H +#define PSA_CRYPTO_H + +#if defined(MBEDTLS_PSA_CRYPTO_PLATFORM_FILE) +#include MBEDTLS_PSA_CRYPTO_PLATFORM_FILE +#else +#include "crypto_platform.h" +#endif + +#include + +#ifdef __DOXYGEN_ONLY__ +/* This __DOXYGEN_ONLY__ block contains mock definitions for things that + * must be defined in the crypto_platform.h header. These mock definitions + * are present in this file as a convenience to generate pretty-printed + * documentation that includes those definitions. */ + +/** \defgroup platform Implementation-specific definitions + * @{ + */ + +/**@}*/ +#endif /* __DOXYGEN_ONLY__ */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* The file "crypto_types.h" declares types that encode errors, + * algorithms, key types, policies, etc. */ +#include "crypto_types.h" + +/** \defgroup version API version + * @{ + */ + +/** + * The major version of this implementation of the PSA Crypto API + */ +#define PSA_CRYPTO_API_VERSION_MAJOR 1 + +/** + * The minor version of this implementation of the PSA Crypto API + */ +#define PSA_CRYPTO_API_VERSION_MINOR 0 + +/**@}*/ + +/* The file "crypto_values.h" declares macros to build and analyze values + * of integral types defined in "crypto_types.h". */ +#include "crypto_values.h" + +/** \defgroup initialization Library initialization + * @{ + */ + +/** + * \brief Library initialization. + * + * Applications must call this function before calling any other + * function in this module. + * + * Applications may call this function more than once. Once a call + * succeeds, subsequent calls are guaranteed to succeed. + * + * If the application calls other functions before calling psa_crypto_init(), + * the behavior is undefined. Implementations are encouraged to either perform + * the operation as if the library had been initialized or to return + * #PSA_ERROR_BAD_STATE or some other applicable error. In particular, + * implementations should not return a success status if the lack of + * initialization may have security implications, for example due to improper + * seeding of the random number generator. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + */ +psa_status_t psa_crypto_init(void); + +/**@}*/ + +/** \addtogroup attributes + * @{ + */ + +/** \def PSA_KEY_ATTRIBUTES_INIT + * + * This macro returns a suitable initializer for a key attribute structure + * of type #psa_key_attributes_t. + */ + +/** Return an initial value for a key attributes structure. + */ +static psa_key_attributes_t psa_key_attributes_init(void); + +/** Declare a key as persistent and set its key identifier. + * + * If the attribute structure currently declares the key as volatile (which + * is the default content of an attribute structure), this function sets + * the lifetime attribute to #PSA_KEY_LIFETIME_PERSISTENT. + * + * This function does not access storage, it merely stores the given + * value in the structure. + * The persistent key will be written to storage when the attribute + * structure is passed to a key creation function such as + * psa_import_key(), psa_generate_key(), + * psa_key_derivation_output_key() or psa_copy_key(). + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param key The persistent identifier for the key. + */ +static void psa_set_key_id(psa_key_attributes_t *attributes, + mbedtls_svc_key_id_t key); + +#ifdef MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER +/** Set the owner identifier of a key. + * + * When key identifiers encode key owner identifiers, psa_set_key_id() does + * not allow to define in key attributes the owner of volatile keys as + * psa_set_key_id() enforces the key to be persistent. + * + * This function allows to set in key attributes the owner identifier of a + * key. It is intended to be used for volatile keys. For persistent keys, + * it is recommended to use the PSA Cryptography API psa_set_key_id() to define + * the owner of a key. + * + * \param[out] attributes The attribute structure to write to. + * \param owner The key owner identifier. + */ +static void mbedtls_set_key_owner_id(psa_key_attributes_t *attributes, + mbedtls_key_owner_id_t owner); +#endif + +/** Set the location of a persistent key. + * + * To make a key persistent, you must give it a persistent key identifier + * with psa_set_key_id(). By default, a key that has a persistent identifier + * is stored in the default storage area identifier by + * #PSA_KEY_LIFETIME_PERSISTENT. Call this function to choose a storage + * area, or to explicitly declare the key as volatile. + * + * This function does not access storage, it merely stores the given + * value in the structure. + * The persistent key will be written to storage when the attribute + * structure is passed to a key creation function such as + * psa_import_key(), psa_generate_key(), + * psa_key_derivation_output_key() or psa_copy_key(). + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param lifetime The lifetime for the key. + * If this is #PSA_KEY_LIFETIME_VOLATILE, the + * key will be volatile, and the key identifier + * attribute is reset to 0. + */ +static void psa_set_key_lifetime(psa_key_attributes_t *attributes, + psa_key_lifetime_t lifetime); + +/** Retrieve the key identifier from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The persistent identifier stored in the attribute structure. + * This value is unspecified if the attribute structure declares + * the key as volatile. + */ +static mbedtls_svc_key_id_t psa_get_key_id( + const psa_key_attributes_t *attributes); + +/** Retrieve the lifetime from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The lifetime value stored in the attribute structure. + */ +static psa_key_lifetime_t psa_get_key_lifetime( + const psa_key_attributes_t *attributes); + +/** Declare usage flags for a key. + * + * Usage flags are part of a key's usage policy. They encode what + * kind of operations are permitted on the key. For more details, + * refer to the documentation of the type #psa_key_usage_t. + * + * This function overwrites any usage flags + * previously set in \p attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param usage_flags The usage flags to write. + */ +static void psa_set_key_usage_flags(psa_key_attributes_t *attributes, + psa_key_usage_t usage_flags); + +/** Retrieve the usage flags from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The usage flags stored in the attribute structure. + */ +static psa_key_usage_t psa_get_key_usage_flags( + const psa_key_attributes_t *attributes); + +/** Declare the permitted algorithm policy for a key. + * + * The permitted algorithm policy of a key encodes which algorithm or + * algorithms are permitted to be used with this key. The following + * algorithm policies are supported: + * - 0 does not allow any cryptographic operation with the key. The key + * may be used for non-cryptographic actions such as exporting (if + * permitted by the usage flags). + * - An algorithm value permits this particular algorithm. + * - An algorithm wildcard built from #PSA_ALG_ANY_HASH allows the specified + * signature scheme with any hash algorithm. + * - An algorithm built from #PSA_ALG_AT_LEAST_THIS_LENGTH_MAC allows + * any MAC algorithm from the same base class (e.g. CMAC) which + * generates/verifies a MAC length greater than or equal to the length + * encoded in the wildcard algorithm. + * - An algorithm built from #PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG + * allows any AEAD algorithm from the same base class (e.g. CCM) which + * generates/verifies a tag length greater than or equal to the length + * encoded in the wildcard algorithm. + * + * This function overwrites any algorithm policy + * previously set in \p attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param alg The permitted algorithm policy to write. + */ +static void psa_set_key_algorithm(psa_key_attributes_t *attributes, + psa_algorithm_t alg); + + +/** Retrieve the algorithm policy from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The algorithm stored in the attribute structure. + */ +static psa_algorithm_t psa_get_key_algorithm( + const psa_key_attributes_t *attributes); + +/** Declare the type of a key. + * + * This function overwrites any key type + * previously set in \p attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param type The key type to write. + * If this is 0, the key type in \p attributes + * becomes unspecified. + */ +static void psa_set_key_type(psa_key_attributes_t *attributes, + psa_key_type_t type); + + +/** Declare the size of a key. + * + * This function overwrites any key size previously set in \p attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param bits The key size in bits. + * If this is 0, the key size in \p attributes + * becomes unspecified. Keys of size 0 are + * not supported. + */ +static void psa_set_key_bits(psa_key_attributes_t *attributes, + size_t bits); + +/** Retrieve the key type from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The key type stored in the attribute structure. + */ +static psa_key_type_t psa_get_key_type(const psa_key_attributes_t *attributes); + +/** Retrieve the key size from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The key size stored in the attribute structure, in bits. + */ +static size_t psa_get_key_bits(const psa_key_attributes_t *attributes); + +/** Retrieve the attributes of a key. + * + * This function first resets the attribute structure as with + * psa_reset_key_attributes(). It then copies the attributes of + * the given key into the given attribute structure. + * + * \note This function may allocate memory or other resources. + * Once you have called this function on an attribute structure, + * you must call psa_reset_key_attributes() to free these resources. + * + * \param[in] key Identifier of the key to query. + * \param[in,out] attributes On success, the attributes of the key. + * On failure, equivalent to a + * freshly-initialized structure. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_get_key_attributes(mbedtls_svc_key_id_t key, + psa_key_attributes_t *attributes); + +/** Reset a key attribute structure to a freshly initialized state. + * + * You must initialize the attribute structure as described in the + * documentation of the type #psa_key_attributes_t before calling this + * function. Once the structure has been initialized, you may call this + * function at any time. + * + * This function frees any auxiliary resources that the structure + * may contain. + * + * \param[in,out] attributes The attribute structure to reset. + */ +void psa_reset_key_attributes(psa_key_attributes_t *attributes); + +/**@}*/ + +/** \defgroup key_management Key management + * @{ + */ + +/** Remove non-essential copies of key material from memory. + * + * If the key identifier designates a volatile key, this functions does not do + * anything and returns successfully. + * + * If the key identifier designates a persistent key, then this function will + * free all resources associated with the key in volatile memory. The key + * data in persistent storage is not affected and the key can still be used. + * + * \param key Identifier of the key to purge. + * + * \retval #PSA_SUCCESS + * The key material will have been removed from memory if it is not + * currently required. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not a valid key identifier. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_purge_key(mbedtls_svc_key_id_t key); + +/** Make a copy of a key. + * + * Copy key material from one location to another. + * + * This function is primarily useful to copy a key from one location + * to another, since it populates a key using the material from + * another key which may have a different lifetime. + * + * This function may be used to share a key with a different party, + * subject to implementation-defined restrictions on key sharing. + * + * The policy on the source key must have the usage flag + * #PSA_KEY_USAGE_COPY set. + * This flag is sufficient to permit the copy if the key has the lifetime + * #PSA_KEY_LIFETIME_VOLATILE or #PSA_KEY_LIFETIME_PERSISTENT. + * Some secure elements do not provide a way to copy a key without + * making it extractable from the secure element. If a key is located + * in such a secure element, then the key must have both usage flags + * #PSA_KEY_USAGE_COPY and #PSA_KEY_USAGE_EXPORT in order to make + * a copy of the key outside the secure element. + * + * The resulting key may only be used in a way that conforms to + * both the policy of the original key and the policy specified in + * the \p attributes parameter: + * - The usage flags on the resulting key are the bitwise-and of the + * usage flags on the source policy and the usage flags in \p attributes. + * - If both allow the same algorithm or wildcard-based + * algorithm policy, the resulting key has the same algorithm policy. + * - If either of the policies allows an algorithm and the other policy + * allows a wildcard-based algorithm policy that includes this algorithm, + * the resulting key allows the same algorithm. + * - If the policies do not allow any algorithm in common, this function + * fails with the status #PSA_ERROR_INVALID_ARGUMENT. + * + * The effect of this function on implementation-defined attributes is + * implementation-defined. + * + * \param source_key The key to copy. It must allow the usage + * #PSA_KEY_USAGE_COPY. If a private or secret key is + * being copied outside of a secure element it must + * also allow #PSA_KEY_USAGE_EXPORT. + * \param[in] attributes The attributes for the new key. + * They are used as follows: + * - The key type and size may be 0. If either is + * nonzero, it must match the corresponding + * attribute of the source key. + * - The key location (the lifetime and, for + * persistent keys, the key identifier) is + * used directly. + * - The policy constraints (usage flags and + * algorithm policy) are combined from + * the source key and \p attributes so that + * both sets of restrictions apply, as + * described in the documentation of this function. + * \param[out] target_key On success, an identifier for the newly created + * key. For persistent keys, this is the key + * identifier defined in \p attributes. + * \c 0 on failure. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_INVALID_HANDLE + * \p source_key is invalid. + * \retval #PSA_ERROR_ALREADY_EXISTS + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The lifetime or identifier in \p attributes are invalid, or + * the policy constraints on the source and specified in + * \p attributes are incompatible, or + * \p attributes specifies a key type or key size + * which does not match the attributes of the source key. + * \retval #PSA_ERROR_NOT_PERMITTED + * The source key does not have the #PSA_KEY_USAGE_COPY usage flag, or + * the source key is not exportable and its lifetime does not + * allow copying it to the target's lifetime. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_copy_key(mbedtls_svc_key_id_t source_key, + const psa_key_attributes_t *attributes, + mbedtls_svc_key_id_t *target_key); + + +/** + * \brief Destroy a key. + * + * This function destroys a key from both volatile + * memory and, if applicable, non-volatile storage. Implementations shall + * make a best effort to ensure that the key material cannot be recovered. + * + * This function also erases any metadata such as policies and frees + * resources associated with the key. + * + * If a key is currently in use in a multipart operation, then destroying the + * key will cause the multipart operation to fail. + * + * \param key Identifier of the key to erase. If this is \c 0, do nothing and + * return #PSA_SUCCESS. + * + * \retval #PSA_SUCCESS + * \p key was a valid identifier and the key material that it + * referred to has been erased. Alternatively, \p key is \c 0. + * \retval #PSA_ERROR_NOT_PERMITTED + * The key cannot be erased because it is + * read-only, either due to a policy or due to physical restrictions. + * \retval #PSA_ERROR_INVALID_HANDLE + * \p key is not a valid identifier nor \c 0. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * There was a failure in communication with the cryptoprocessor. + * The key material may still be present in the cryptoprocessor. + * \retval #PSA_ERROR_DATA_INVALID + * This error is typically a result of either storage corruption on a + * cleartext storage backend, or an attempt to read data that was + * written by an incompatible version of the library. + * \retval #PSA_ERROR_STORAGE_FAILURE + * The storage is corrupted. Implementations shall make a best effort + * to erase key material even in this stage, however applications + * should be aware that it may be impossible to guarantee that the + * key material is not recoverable in such cases. + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * An unexpected condition which is not a storage corruption or + * a communication failure occurred. The cryptoprocessor may have + * been compromised. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_destroy_key(mbedtls_svc_key_id_t key); + +/**@}*/ + +/** \defgroup import_export Key import and export + * @{ + */ + +/** + * \brief Import a key in binary format. + * + * This function supports any output from psa_export_key(). Refer to the + * documentation of psa_export_public_key() for the format of public keys + * and to the documentation of psa_export_key() for the format for + * other key types. + * + * The key data determines the key size. The attributes may optionally + * specify a key size; in this case it must match the size determined + * from the key data. A key size of 0 in \p attributes indicates that + * the key size is solely determined by the key data. + * + * Implementations must reject an attempt to import a key of size 0. + * + * This specification supports a single format for each key type. + * Implementations may support other formats as long as the standard + * format is supported. Implementations that support other formats + * should ensure that the formats are clearly unambiguous so as to + * minimize the risk that an invalid input is accidentally interpreted + * according to a different format. + * + * \param[in] attributes The attributes for the new key. + * The key size is always determined from the + * \p data buffer. + * If the key size in \p attributes is nonzero, + * it must be equal to the size from \p data. + * \param[out] key On success, an identifier to the newly created key. + * For persistent keys, this is the key identifier + * defined in \p attributes. + * \c 0 on failure. + * \param[in] data Buffer containing the key data. The content of this + * buffer is interpreted according to the type declared + * in \p attributes. + * All implementations must support at least the format + * described in the documentation + * of psa_export_key() or psa_export_public_key() for + * the chosen type. Implementations may allow other + * formats, but should be conservative: implementations + * should err on the side of rejecting content if it + * may be erroneous (e.g. wrong type or truncated data). + * \param data_length Size of the \p data buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * If the key is persistent, the key material and the key's metadata + * have been saved to persistent storage. + * \retval #PSA_ERROR_ALREADY_EXISTS + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The key type or key size is not supported, either by the + * implementation in general or in this particular persistent location. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key attributes, as a whole, are invalid, or + * the key data is not correctly formatted, or + * the size in \p attributes is nonzero and does not match the size + * of the key data. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_import_key(const psa_key_attributes_t *attributes, + const uint8_t *data, + size_t data_length, + mbedtls_svc_key_id_t *key); + + + +/** + * \brief Export a key in binary format. + * + * The output of this function can be passed to psa_import_key() to + * create an equivalent object. + * + * If the implementation of psa_import_key() supports other formats + * beyond the format specified here, the output from psa_export_key() + * must use the representation specified here, not the original + * representation. + * + * For standard key types, the output format is as follows: + * + * - For symmetric keys (including MAC keys), the format is the + * raw bytes of the key. + * - For DES, the key data consists of 8 bytes. The parity bits must be + * correct. + * - For Triple-DES, the format is the concatenation of the + * two or three DES keys. + * - For RSA key pairs (#PSA_KEY_TYPE_RSA_KEY_PAIR), the format + * is the non-encrypted DER encoding of the representation defined by + * PKCS\#1 (RFC 8017) as `RSAPrivateKey`, version 0. + * ``` + * RSAPrivateKey ::= SEQUENCE { + * version INTEGER, -- must be 0 + * 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 + * } + * ``` + * - For elliptic curve key pairs (key types for which + * #PSA_KEY_TYPE_IS_ECC_KEY_PAIR is true), the format is + * a representation of the private value as a `ceiling(m/8)`-byte string + * where `m` is the bit size associated with the curve, i.e. the bit size + * of the order of the curve's coordinate field. This byte string is + * in little-endian order for Montgomery curves (curve types + * `PSA_ECC_FAMILY_CURVEXXX`), and in big-endian order for Weierstrass + * curves (curve types `PSA_ECC_FAMILY_SECTXXX`, `PSA_ECC_FAMILY_SECPXXX` + * and `PSA_ECC_FAMILY_BRAINPOOL_PXXX`). + * For Weierstrass curves, this is the content of the `privateKey` field of + * the `ECPrivateKey` format defined by RFC 5915. For Montgomery curves, + * the format is defined by RFC 7748, and output is masked according to §5. + * For twisted Edwards curves, the private key is as defined by RFC 8032 + * (a 32-byte string for Edwards25519, a 57-byte string for Edwards448). + * - For Diffie-Hellman key exchange key pairs (key types for which + * #PSA_KEY_TYPE_IS_DH_KEY_PAIR is true), the + * format is the representation of the private key `x` as a big-endian byte + * string. The length of the byte string is the private key size in bytes + * (leading zeroes are not stripped). + * - For public keys (key types for which #PSA_KEY_TYPE_IS_PUBLIC_KEY is + * true), the format is the same as for psa_export_public_key(). + * + * The policy on the key must have the usage flag #PSA_KEY_USAGE_EXPORT set. + * + * \param key Identifier of the key to export. It must allow the + * usage #PSA_KEY_USAGE_EXPORT, unless it is a public + * key. + * \param[out] data Buffer where the key data is to be written. + * \param data_size Size of the \p data buffer in bytes. + * \param[out] data_length On success, the number of bytes + * that make up the key data. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED + * The key does not have the #PSA_KEY_USAGE_EXPORT flag. + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p data buffer is too small. You can determine a + * sufficient buffer size by calling + * #PSA_EXPORT_KEY_OUTPUT_SIZE(\c type, \c bits) + * where \c type is the key type + * and \c bits is the key size in bits. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_export_key(mbedtls_svc_key_id_t key, + uint8_t *data, + size_t data_size, + size_t *data_length); + +/** + * \brief Export a public key or the public part of a key pair in binary format. + * + * The output of this function can be passed to psa_import_key() to + * create an object that is equivalent to the public key. + * + * This specification supports a single format for each key type. + * Implementations may support other formats as long as the standard + * format is supported. Implementations that support other formats + * should ensure that the formats are clearly unambiguous so as to + * minimize the risk that an invalid input is accidentally interpreted + * according to a different format. + * + * For standard key types, the output format is as follows: + * - For RSA public keys (#PSA_KEY_TYPE_RSA_PUBLIC_KEY), the DER encoding of + * the representation defined by RFC 3279 §2.3.1 as `RSAPublicKey`. + * ``` + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER } -- e + * ``` + * - For elliptic curve keys on a twisted Edwards curve (key types for which + * #PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY is true and #PSA_KEY_TYPE_ECC_GET_FAMILY + * returns #PSA_ECC_FAMILY_TWISTED_EDWARDS), the public key is as defined + * by RFC 8032 + * (a 32-byte string for Edwards25519, a 57-byte string for Edwards448). + * - For other elliptic curve public keys (key types for which + * #PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY is true), the format is the uncompressed + * representation defined by SEC1 §2.3.3 as the content of an ECPoint. + * Let `m` be the bit size associated with the curve, i.e. the bit size of + * `q` for a curve over `F_q`. The representation consists of: + * - The byte 0x04; + * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; + * - `y_P` as a `ceiling(m/8)`-byte string, big-endian. + * - For Diffie-Hellman key exchange public keys (key types for which + * #PSA_KEY_TYPE_IS_DH_PUBLIC_KEY is true), + * the format is the representation of the public key `y = g^x mod p` as a + * big-endian byte string. The length of the byte string is the length of the + * base prime `p` in bytes. + * + * Exporting a public key object or the public part of a key pair is + * always permitted, regardless of the key's usage flags. + * + * \param key Identifier of the key to export. + * \param[out] data Buffer where the key data is to be written. + * \param data_size Size of the \p data buffer in bytes. + * \param[out] data_length On success, the number of bytes + * that make up the key data. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key is neither a public key nor a key pair. + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p data buffer is too small. You can determine a + * sufficient buffer size by calling + * #PSA_EXPORT_KEY_OUTPUT_SIZE(#PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(\c type), \c bits) + * where \c type is the key type + * and \c bits is the key size in bits. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_export_public_key(mbedtls_svc_key_id_t key, + uint8_t *data, + size_t data_size, + size_t *data_length); + + + +/**@}*/ + +/** \defgroup hash Message digests + * @{ + */ + +/** Calculate the hash (digest) of a message. + * + * \note To verify the hash of a message against an + * expected value, use psa_hash_compare() instead. + * + * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_HASH(\p alg) is true). + * \param[in] input Buffer containing the message to hash. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] hash Buffer where the hash is to be written. + * \param hash_size Size of the \p hash buffer in bytes. + * \param[out] hash_length On success, the number of bytes + * that make up the hash value. This is always + * #PSA_HASH_LENGTH(\p alg). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a hash algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p hash_size is too small + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_compute(psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *hash, + size_t hash_size, + size_t *hash_length); + +/** Calculate the hash (digest) of a message and compare it with a + * reference value. + * + * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_HASH(\p alg) is true). + * \param[in] input Buffer containing the message to hash. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] hash Buffer containing the expected hash value. + * \param hash_length Size of the \p hash buffer in bytes. + * + * \retval #PSA_SUCCESS + * The expected hash is identical to the actual hash of the input. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The hash of the message was calculated successfully, but it + * differs from the expected hash. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a hash algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p input_length or \p hash_length do not match the hash size for \p alg + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_compare(psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *hash, + size_t hash_length); + +/** The type of the state data structure for multipart hash operations. + * + * Before calling any function on a hash operation object, the application must + * initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_hash_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_hash_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_HASH_OPERATION_INIT, + * for example: + * \code + * psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_hash_operation_init() + * to the structure, for example: + * \code + * psa_hash_operation_t operation; + * operation = psa_hash_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure. + * Implementation details can change in future versions without notice. */ +typedef struct psa_hash_operation_s psa_hash_operation_t; + +/** \def PSA_HASH_OPERATION_INIT + * + * This macro returns a suitable initializer for a hash operation object + * of type #psa_hash_operation_t. + */ + +/** Return an initial value for a hash operation object. + */ +static psa_hash_operation_t psa_hash_operation_init(void); + +/** Set up a multipart hash operation. + * + * The sequence of operations to calculate a hash (message digest) + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_hash_operation_t, e.g. #PSA_HASH_OPERATION_INIT. + * -# Call psa_hash_setup() to specify the algorithm. + * -# Call psa_hash_update() zero, one or more times, passing a fragment + * of the message each time. The hash that is calculated is the hash + * of the concatenation of these messages in order. + * -# To calculate the hash, call psa_hash_finish(). + * To compare the hash with an expected value, call psa_hash_verify(). + * + * If an error occurs at any step after a call to psa_hash_setup(), the + * operation will need to be reset by a call to psa_hash_abort(). The + * application may call psa_hash_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_hash_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to psa_hash_finish() or psa_hash_verify(). + * - A call to psa_hash_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_hash_operation_t and not yet in use. + * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_HASH(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not a supported hash algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p alg is not a hash algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive), or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_setup(psa_hash_operation_t *operation, + psa_algorithm_t alg); + +/** Add a message fragment to a multipart hash operation. + * + * The application must call psa_hash_setup() before calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_hash_abort(). + * + * \param[in,out] operation Active hash operation. + * \param[in] input Buffer containing the message fragment to hash. + * \param input_length Size of the \p input buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active), or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_update(psa_hash_operation_t *operation, + const uint8_t *input, + size_t input_length); + +/** Finish the calculation of the hash of a message. + * + * The application must call psa_hash_setup() before calling this function. + * This function calculates the hash of the message formed by concatenating + * the inputs passed to preceding calls to psa_hash_update(). + * + * When this function returns successfully, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_hash_abort(). + * + * \warning Applications should not call this function if they expect + * a specific value for the hash. Call psa_hash_verify() instead. + * Beware that comparing integrity or authenticity data such as + * hash values with a function such as \c memcmp is risky + * because the time taken by the comparison may leak information + * about the hashed data which could allow an attacker to guess + * a valid hash and thereby bypass security controls. + * + * \param[in,out] operation Active hash operation. + * \param[out] hash Buffer where the hash is to be written. + * \param hash_size Size of the \p hash buffer in bytes. + * \param[out] hash_length On success, the number of bytes + * that make up the hash value. This is always + * #PSA_HASH_LENGTH(\c alg) where \c alg is the + * hash algorithm that is calculated. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p hash buffer is too small. You can determine a + * sufficient buffer size by calling #PSA_HASH_LENGTH(\c alg) + * where \c alg is the hash algorithm that is calculated. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active), or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_finish(psa_hash_operation_t *operation, + uint8_t *hash, + size_t hash_size, + size_t *hash_length); + +/** Finish the calculation of the hash of a message and compare it with + * an expected value. + * + * The application must call psa_hash_setup() before calling this function. + * This function calculates the hash of the message formed by concatenating + * the inputs passed to preceding calls to psa_hash_update(). It then + * compares the calculated hash with the expected hash passed as a + * parameter to this function. + * + * When this function returns successfully, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_hash_abort(). + * + * \note Implementations shall make the best effort to ensure that the + * comparison between the actual hash and the expected hash is performed + * in constant time. + * + * \param[in,out] operation Active hash operation. + * \param[in] hash Buffer containing the expected hash value. + * \param hash_length Size of the \p hash buffer in bytes. + * + * \retval #PSA_SUCCESS + * The expected hash is identical to the actual hash of the message. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The hash of the message was calculated successfully, but it + * differs from the expected hash. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active), or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_verify(psa_hash_operation_t *operation, + const uint8_t *hash, + size_t hash_length); + +/** Abort a hash operation. + * + * Aborting an operation frees all associated resources except for the + * \p operation structure itself. Once aborted, the operation object + * can be reused for another operation by calling + * psa_hash_setup() again. + * + * You may call this function any time after the operation object has + * been initialized by one of the methods described in #psa_hash_operation_t. + * + * In particular, calling psa_hash_abort() after the operation has been + * terminated by a call to psa_hash_abort(), psa_hash_finish() or + * psa_hash_verify() is safe and has no effect. + * + * \param[in,out] operation Initialized hash operation. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_abort(psa_hash_operation_t *operation); + +/** Clone a hash operation. + * + * This function copies the state of an ongoing hash operation to + * a new operation object. In other words, this function is equivalent + * to calling psa_hash_setup() on \p target_operation with the same + * algorithm that \p source_operation was set up for, then + * psa_hash_update() on \p target_operation with the same input that + * that was passed to \p source_operation. After this function returns, the + * two objects are independent, i.e. subsequent calls involving one of + * the objects do not affect the other object. + * + * \param[in] source_operation The active hash operation to clone. + * \param[in,out] target_operation The operation object to set up. + * It must be initialized but not active. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The \p source_operation state is not valid (it must be active), or + * the \p target_operation state is not valid (it must be inactive), or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_clone(const psa_hash_operation_t *source_operation, + psa_hash_operation_t *target_operation); + +/**@}*/ + +/** \defgroup MAC Message authentication codes + * @{ + */ + +/** Calculate the MAC (message authentication code) of a message. + * + * \note To verify the MAC of a message against an + * expected value, use psa_mac_verify() instead. + * Beware that comparing integrity or authenticity data such as + * MAC values with a function such as \c memcmp is risky + * because the time taken by the comparison may leak information + * about the MAC value which could allow an attacker to guess + * a valid MAC and thereby bypass security controls. + * + * \param key Identifier of the key to use for the operation. It + * must allow the usage PSA_KEY_USAGE_SIGN_MESSAGE. + * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(\p alg) is true). + * \param[in] input Buffer containing the input message. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] mac Buffer where the MAC value is to be written. + * \param mac_size Size of the \p mac buffer in bytes. + * \param[out] mac_length On success, the number of bytes + * that make up the MAC value. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a MAC algorithm. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p mac_size is too small + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_compute(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *mac, + size_t mac_size, + size_t *mac_length); + +/** Calculate the MAC of a message and compare it with a reference value. + * + * \param key Identifier of the key to use for the operation. It + * must allow the usage PSA_KEY_USAGE_VERIFY_MESSAGE. + * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(\p alg) is true). + * \param[in] input Buffer containing the input message. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] mac Buffer containing the expected MAC value. + * \param mac_length Size of the \p mac buffer in bytes. + * + * \retval #PSA_SUCCESS + * The expected MAC is identical to the actual MAC of the input. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The MAC of the message was calculated successfully, but it + * differs from the expected value. + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a MAC algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_verify(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *mac, + size_t mac_length); + +/** The type of the state data structure for multipart MAC operations. + * + * Before calling any function on a MAC operation object, the application must + * initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_mac_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_mac_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_MAC_OPERATION_INIT, + * for example: + * \code + * psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_mac_operation_init() + * to the structure, for example: + * \code + * psa_mac_operation_t operation; + * operation = psa_mac_operation_init(); + * \endcode + * + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure. + * Implementation details can change in future versions without notice. */ +typedef struct psa_mac_operation_s psa_mac_operation_t; + +/** \def PSA_MAC_OPERATION_INIT + * + * This macro returns a suitable initializer for a MAC operation object of type + * #psa_mac_operation_t. + */ + +/** Return an initial value for a MAC operation object. + */ +static psa_mac_operation_t psa_mac_operation_init(void); + +/** Set up a multipart MAC calculation operation. + * + * This function sets up the calculation of the MAC + * (message authentication code) of a byte string. + * To verify the MAC of a message against an + * expected value, use psa_mac_verify_setup() instead. + * + * The sequence of operations to calculate a MAC is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_mac_operation_t, e.g. #PSA_MAC_OPERATION_INIT. + * -# Call psa_mac_sign_setup() to specify the algorithm and key. + * -# Call psa_mac_update() zero, one or more times, passing a fragment + * of the message each time. The MAC that is calculated is the MAC + * of the concatenation of these messages in order. + * -# At the end of the message, call psa_mac_sign_finish() to finish + * calculating the MAC value and retrieve it. + * + * If an error occurs at any step after a call to psa_mac_sign_setup(), the + * operation will need to be reset by a call to psa_mac_abort(). The + * application may call psa_mac_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_mac_sign_setup(), the application must + * eventually terminate the operation through one of the following methods: + * - A successful call to psa_mac_sign_finish(). + * - A call to psa_mac_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_mac_operation_t and not yet in use. + * \param key Identifier of the key to use for the operation. It + * must remain valid until the operation terminates. + * It must allow the usage PSA_KEY_USAGE_SIGN_MESSAGE. + * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a MAC algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive), or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg); + +/** Set up a multipart MAC verification operation. + * + * This function sets up the verification of the MAC + * (message authentication code) of a byte string against an expected value. + * + * The sequence of operations to verify a MAC is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_mac_operation_t, e.g. #PSA_MAC_OPERATION_INIT. + * -# Call psa_mac_verify_setup() to specify the algorithm and key. + * -# Call psa_mac_update() zero, one or more times, passing a fragment + * of the message each time. The MAC that is calculated is the MAC + * of the concatenation of these messages in order. + * -# At the end of the message, call psa_mac_verify_finish() to finish + * calculating the actual MAC of the message and verify it against + * the expected value. + * + * If an error occurs at any step after a call to psa_mac_verify_setup(), the + * operation will need to be reset by a call to psa_mac_abort(). The + * application may call psa_mac_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_mac_verify_setup(), the application must + * eventually terminate the operation through one of the following methods: + * - A successful call to psa_mac_verify_finish(). + * - A call to psa_mac_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_mac_operation_t and not yet in use. + * \param key Identifier of the key to use for the operation. It + * must remain valid until the operation terminates. + * It must allow the usage + * PSA_KEY_USAGE_VERIFY_MESSAGE. + * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c key is not compatible with \c alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \c alg is not supported or is not a MAC algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive), or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg); + +/** Add a message fragment to a multipart MAC operation. + * + * The application must call psa_mac_sign_setup() or psa_mac_verify_setup() + * before calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_mac_abort(). + * + * \param[in,out] operation Active MAC operation. + * \param[in] input Buffer containing the message fragment to add to + * the MAC calculation. + * \param input_length Size of the \p input buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active), or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_update(psa_mac_operation_t *operation, + const uint8_t *input, + size_t input_length); + +/** Finish the calculation of the MAC of a message. + * + * The application must call psa_mac_sign_setup() before calling this function. + * This function calculates the MAC of the message formed by concatenating + * the inputs passed to preceding calls to psa_mac_update(). + * + * When this function returns successfully, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_mac_abort(). + * + * \warning Applications should not call this function if they expect + * a specific value for the MAC. Call psa_mac_verify_finish() instead. + * Beware that comparing integrity or authenticity data such as + * MAC values with a function such as \c memcmp is risky + * because the time taken by the comparison may leak information + * about the MAC value which could allow an attacker to guess + * a valid MAC and thereby bypass security controls. + * + * \param[in,out] operation Active MAC operation. + * \param[out] mac Buffer where the MAC value is to be written. + * \param mac_size Size of the \p mac buffer in bytes. + * \param[out] mac_length On success, the number of bytes + * that make up the MAC value. This is always + * #PSA_MAC_LENGTH(\c key_type, \c key_bits, \c alg) + * where \c key_type and \c key_bits are the type and + * bit-size respectively of the key and \c alg is the + * MAC algorithm that is calculated. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p mac buffer is too small. You can determine a + * sufficient buffer size by calling PSA_MAC_LENGTH(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active mac sign + * operation), or the library has not been previously initialized + * by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation, + uint8_t *mac, + size_t mac_size, + size_t *mac_length); + +/** Finish the calculation of the MAC of a message and compare it with + * an expected value. + * + * The application must call psa_mac_verify_setup() before calling this function. + * This function calculates the MAC of the message formed by concatenating + * the inputs passed to preceding calls to psa_mac_update(). It then + * compares the calculated MAC with the expected MAC passed as a + * parameter to this function. + * + * When this function returns successfully, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_mac_abort(). + * + * \note Implementations shall make the best effort to ensure that the + * comparison between the actual MAC and the expected MAC is performed + * in constant time. + * + * \param[in,out] operation Active MAC operation. + * \param[in] mac Buffer containing the expected MAC value. + * \param mac_length Size of the \p mac buffer in bytes. + * + * \retval #PSA_SUCCESS + * The expected MAC is identical to the actual MAC of the message. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The MAC of the message was calculated successfully, but it + * differs from the expected MAC. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active mac verify + * operation), or the library has not been previously initialized + * by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation, + const uint8_t *mac, + size_t mac_length); + +/** Abort a MAC operation. + * + * Aborting an operation frees all associated resources except for the + * \p operation structure itself. Once aborted, the operation object + * can be reused for another operation by calling + * psa_mac_sign_setup() or psa_mac_verify_setup() again. + * + * You may call this function any time after the operation object has + * been initialized by one of the methods described in #psa_mac_operation_t. + * + * In particular, calling psa_mac_abort() after the operation has been + * terminated by a call to psa_mac_abort(), psa_mac_sign_finish() or + * psa_mac_verify_finish() is safe and has no effect. + * + * \param[in,out] operation Initialized MAC operation. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_abort(psa_mac_operation_t *operation); + +/**@}*/ + +/** \defgroup cipher Symmetric ciphers + * @{ + */ + +/** Encrypt a message using a symmetric cipher. + * + * This function encrypts a message with a random IV (initialization + * vector). Use the multipart operation interface with a + * #psa_cipher_operation_t object to provide other forms of IV. + * + * \param key Identifier of the key to use for the operation. + * It must allow the usage #PSA_KEY_USAGE_ENCRYPT. + * \param alg The cipher algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * \param[in] input Buffer containing the message to encrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] output Buffer where the output is to be written. + * The output contains the IV followed by + * the ciphertext proper. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a cipher algorithm. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_encrypt(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** Decrypt a message using a symmetric cipher. + * + * This function decrypts a message encrypted with a symmetric cipher. + * + * \param key Identifier of the key to use for the operation. + * It must remain valid until the operation + * terminates. It must allow the usage + * #PSA_KEY_USAGE_DECRYPT. + * \param alg The cipher algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * \param[in] input Buffer containing the message to decrypt. + * This consists of the IV followed by the + * ciphertext proper. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] output Buffer where the plaintext is to be written. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a cipher algorithm. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_decrypt(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** The type of the state data structure for multipart cipher operations. + * + * Before calling any function on a cipher operation object, the application + * must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_cipher_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_cipher_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_CIPHER_OPERATION_INIT, + * for example: + * \code + * psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_cipher_operation_init() + * to the structure, for example: + * \code + * psa_cipher_operation_t operation; + * operation = psa_cipher_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure. + * Implementation details can change in future versions without notice. */ +typedef struct psa_cipher_operation_s psa_cipher_operation_t; + +/** \def PSA_CIPHER_OPERATION_INIT + * + * This macro returns a suitable initializer for a cipher operation object of + * type #psa_cipher_operation_t. + */ + +/** Return an initial value for a cipher operation object. + */ +static psa_cipher_operation_t psa_cipher_operation_init(void); + +/** Set the key for a multipart symmetric encryption operation. + * + * The sequence of operations to encrypt a message with a symmetric cipher + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_cipher_operation_t, e.g. + * #PSA_CIPHER_OPERATION_INIT. + * -# Call psa_cipher_encrypt_setup() to specify the algorithm and key. + * -# Call either psa_cipher_generate_iv() or psa_cipher_set_iv() to + * generate or set the IV (initialization vector). You should use + * psa_cipher_generate_iv() unless the protocol you are implementing + * requires a specific IV value. + * -# Call psa_cipher_update() zero, one or more times, passing a fragment + * of the message each time. + * -# Call psa_cipher_finish(). + * + * If an error occurs at any step after a call to psa_cipher_encrypt_setup(), + * the operation will need to be reset by a call to psa_cipher_abort(). The + * application may call psa_cipher_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_cipher_encrypt_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to psa_cipher_finish(). + * - A call to psa_cipher_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_cipher_operation_t and not yet in use. + * \param key Identifier of the key to use for the operation. + * It must remain valid until the operation + * terminates. It must allow the usage + * #PSA_KEY_USAGE_ENCRYPT. + * \param alg The cipher algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a cipher algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive), or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg); + +/** Set the key for a multipart symmetric decryption operation. + * + * The sequence of operations to decrypt a message with a symmetric cipher + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_cipher_operation_t, e.g. + * #PSA_CIPHER_OPERATION_INIT. + * -# Call psa_cipher_decrypt_setup() to specify the algorithm and key. + * -# Call psa_cipher_set_iv() with the IV (initialization vector) for the + * decryption. If the IV is prepended to the ciphertext, you can call + * psa_cipher_update() on a buffer containing the IV followed by the + * beginning of the message. + * -# Call psa_cipher_update() zero, one or more times, passing a fragment + * of the message each time. + * -# Call psa_cipher_finish(). + * + * If an error occurs at any step after a call to psa_cipher_decrypt_setup(), + * the operation will need to be reset by a call to psa_cipher_abort(). The + * application may call psa_cipher_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_cipher_decrypt_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to psa_cipher_finish(). + * - A call to psa_cipher_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_cipher_operation_t and not yet in use. + * \param key Identifier of the key to use for the operation. + * It must remain valid until the operation + * terminates. It must allow the usage + * #PSA_KEY_USAGE_DECRYPT. + * \param alg The cipher algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a cipher algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive), or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg); + +/** Generate an IV for a symmetric encryption operation. + * + * This function generates a random IV (initialization vector), nonce + * or initial counter value for the encryption operation as appropriate + * for the chosen algorithm, key type and key size. + * + * The application must call psa_cipher_encrypt_setup() before + * calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_cipher_abort(). + * + * \param[in,out] operation Active cipher operation. + * \param[out] iv Buffer where the generated IV is to be written. + * \param iv_size Size of the \p iv buffer in bytes. + * \param[out] iv_length On success, the number of bytes of the + * generated IV. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p iv buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, with no IV set), + * or the library has not been previously initialized + * by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation, + uint8_t *iv, + size_t iv_size, + size_t *iv_length); + +/** Set the IV for a symmetric encryption or decryption operation. + * + * This function sets the IV (initialization vector), nonce + * or initial counter value for the encryption or decryption operation. + * + * The application must call psa_cipher_encrypt_setup() before + * calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_cipher_abort(). + * + * \note When encrypting, applications should use psa_cipher_generate_iv() + * instead of this function, unless implementing a protocol that requires + * a non-random IV. + * + * \param[in,out] operation Active cipher operation. + * \param[in] iv Buffer containing the IV to use. + * \param iv_length Size of the IV in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The size of \p iv is not acceptable for the chosen algorithm, + * or the chosen algorithm does not use an IV. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active cipher + * encrypt operation, with no IV set), or the library has not been + * previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation, + const uint8_t *iv, + size_t iv_length); + +/** Encrypt or decrypt a message fragment in an active cipher operation. + * + * Before calling this function, you must: + * 1. Call either psa_cipher_encrypt_setup() or psa_cipher_decrypt_setup(). + * The choice of setup function determines whether this function + * encrypts or decrypts its input. + * 2. If the algorithm requires an IV, call psa_cipher_generate_iv() + * (recommended when encrypting) or psa_cipher_set_iv(). + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_cipher_abort(). + * + * \param[in,out] operation Active cipher operation. + * \param[in] input Buffer containing the message fragment to + * encrypt or decrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] output Buffer where the output is to be written. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, with an IV set + * if required for the algorithm), or the library has not been + * previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_update(psa_cipher_operation_t *operation, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** Finish encrypting or decrypting a message in a cipher operation. + * + * The application must call psa_cipher_encrypt_setup() or + * psa_cipher_decrypt_setup() before calling this function. The choice + * of setup function determines whether this function encrypts or + * decrypts its input. + * + * This function finishes the encryption or decryption of the message + * formed by concatenating the inputs passed to preceding calls to + * psa_cipher_update(). + * + * When this function returns successfully, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_cipher_abort(). + * + * \param[in,out] operation Active cipher operation. + * \param[out] output Buffer where the output is to be written. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total input size passed to this operation is not valid for + * this particular algorithm. For example, the algorithm is a based + * on block cipher and requires a whole number of blocks, but the + * total input size is not a multiple of the block size. + * \retval #PSA_ERROR_INVALID_PADDING + * This is a decryption operation for an algorithm that includes + * padding, and the ciphertext does not contain valid padding. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, with an IV set + * if required for the algorithm), or the library has not been + * previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** Abort a cipher operation. + * + * Aborting an operation frees all associated resources except for the + * \p operation structure itself. Once aborted, the operation object + * can be reused for another operation by calling + * psa_cipher_encrypt_setup() or psa_cipher_decrypt_setup() again. + * + * You may call this function any time after the operation object has + * been initialized as described in #psa_cipher_operation_t. + * + * In particular, calling psa_cipher_abort() after the operation has been + * terminated by a call to psa_cipher_abort() or psa_cipher_finish() + * is safe and has no effect. + * + * \param[in,out] operation Initialized cipher operation. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation); + +/**@}*/ + +/** \defgroup aead Authenticated encryption with associated data (AEAD) + * @{ + */ + +/** Process an authenticated encryption operation. + * + * \param key Identifier of the key to use for the + * operation. It must allow the usage + * #PSA_KEY_USAGE_ENCRYPT. + * \param alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * \param[in] nonce Nonce or IV to use. + * \param nonce_length Size of the \p nonce buffer in bytes. + * \param[in] additional_data Additional data that will be authenticated + * but not encrypted. + * \param additional_data_length Size of \p additional_data in bytes. + * \param[in] plaintext Data that will be authenticated and + * encrypted. + * \param plaintext_length Size of \p plaintext in bytes. + * \param[out] ciphertext Output buffer for the authenticated and + * encrypted data. The additional data is not + * part of this output. For algorithms where the + * encrypted data and the authentication tag + * are defined as separate outputs, the + * authentication tag is appended to the + * encrypted data. + * \param ciphertext_size Size of the \p ciphertext buffer in bytes. + * This must be appropriate for the selected + * algorithm and key: + * - A sufficient output size is + * #PSA_AEAD_ENCRYPT_OUTPUT_SIZE(\c key_type, + * \p alg, \p plaintext_length) where + * \c key_type is the type of \p key. + * - #PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(\p + * plaintext_length) evaluates to the maximum + * ciphertext size of any supported AEAD + * encryption. + * \param[out] ciphertext_length On success, the size of the output + * in the \p ciphertext buffer. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not an AEAD algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p ciphertext_size is too small. + * #PSA_AEAD_ENCRYPT_OUTPUT_SIZE(\c key_type, \p alg, + * \p plaintext_length) or + * #PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(\p plaintext_length) can be used to + * determine the required buffer size. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_encrypt(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *nonce, + size_t nonce_length, + const uint8_t *additional_data, + size_t additional_data_length, + const uint8_t *plaintext, + size_t plaintext_length, + uint8_t *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length); + +/** Process an authenticated decryption operation. + * + * \param key Identifier of the key to use for the + * operation. It must allow the usage + * #PSA_KEY_USAGE_DECRYPT. + * \param alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * \param[in] nonce Nonce or IV to use. + * \param nonce_length Size of the \p nonce buffer in bytes. + * \param[in] additional_data Additional data that has been authenticated + * but not encrypted. + * \param additional_data_length Size of \p additional_data in bytes. + * \param[in] ciphertext Data that has been authenticated and + * encrypted. For algorithms where the + * encrypted data and the authentication tag + * are defined as separate inputs, the buffer + * must contain the encrypted data followed + * by the authentication tag. + * \param ciphertext_length Size of \p ciphertext in bytes. + * \param[out] plaintext Output buffer for the decrypted data. + * \param plaintext_size Size of the \p plaintext buffer in bytes. + * This must be appropriate for the selected + * algorithm and key: + * - A sufficient output size is + * #PSA_AEAD_DECRYPT_OUTPUT_SIZE(\c key_type, + * \p alg, \p ciphertext_length) where + * \c key_type is the type of \p key. + * - #PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE(\p + * ciphertext_length) evaluates to the maximum + * plaintext size of any supported AEAD + * decryption. + * \param[out] plaintext_length On success, the size of the output + * in the \p plaintext buffer. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The ciphertext is not authentic. + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not an AEAD algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p plaintext_size is too small. + * #PSA_AEAD_DECRYPT_OUTPUT_SIZE(\c key_type, \p alg, + * \p ciphertext_length) or + * #PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE(\p ciphertext_length) can be used + * to determine the required buffer size. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_decrypt(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *nonce, + size_t nonce_length, + const uint8_t *additional_data, + size_t additional_data_length, + const uint8_t *ciphertext, + size_t ciphertext_length, + uint8_t *plaintext, + size_t plaintext_size, + size_t *plaintext_length); + +/** The type of the state data structure for multipart AEAD operations. + * + * Before calling any function on an AEAD operation object, the application + * must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_aead_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_aead_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_AEAD_OPERATION_INIT, + * for example: + * \code + * psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_aead_operation_init() + * to the structure, for example: + * \code + * psa_aead_operation_t operation; + * operation = psa_aead_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure. + * Implementation details can change in future versions without notice. */ +typedef struct psa_aead_operation_s psa_aead_operation_t; + +/** \def PSA_AEAD_OPERATION_INIT + * + * This macro returns a suitable initializer for an AEAD operation object of + * type #psa_aead_operation_t. + */ + +/** Return an initial value for an AEAD operation object. + */ +static psa_aead_operation_t psa_aead_operation_init(void); + +/** Set the key for a multipart authenticated encryption operation. + * + * The sequence of operations to encrypt a message with authentication + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_aead_operation_t, e.g. + * #PSA_AEAD_OPERATION_INIT. + * -# Call psa_aead_encrypt_setup() to specify the algorithm and key. + * -# If needed, call psa_aead_set_lengths() to specify the length of the + * inputs to the subsequent calls to psa_aead_update_ad() and + * psa_aead_update(). See the documentation of psa_aead_set_lengths() + * for details. + * -# Call either psa_aead_generate_nonce() or psa_aead_set_nonce() to + * generate or set the nonce. You should use + * psa_aead_generate_nonce() unless the protocol you are implementing + * requires a specific nonce value. + * -# Call psa_aead_update_ad() zero, one or more times, passing a fragment + * of the non-encrypted additional authenticated data each time. + * -# Call psa_aead_update() zero, one or more times, passing a fragment + * of the message to encrypt each time. + * -# Call psa_aead_finish(). + * + * If an error occurs at any step after a call to psa_aead_encrypt_setup(), + * the operation will need to be reset by a call to psa_aead_abort(). The + * application may call psa_aead_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_aead_encrypt_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to psa_aead_finish(). + * - A call to psa_aead_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_aead_operation_t and not yet in use. + * \param key Identifier of the key to use for the operation. + * It must remain valid until the operation + * terminates. It must allow the usage + * #PSA_KEY_USAGE_ENCRYPT. + * \param alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive), or + * the library has not been previously initialized by psa_crypto_init(). + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not an AEAD algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_encrypt_setup(psa_aead_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg); + +/** Set the key for a multipart authenticated decryption operation. + * + * The sequence of operations to decrypt a message with authentication + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_aead_operation_t, e.g. + * #PSA_AEAD_OPERATION_INIT. + * -# Call psa_aead_decrypt_setup() to specify the algorithm and key. + * -# If needed, call psa_aead_set_lengths() to specify the length of the + * inputs to the subsequent calls to psa_aead_update_ad() and + * psa_aead_update(). See the documentation of psa_aead_set_lengths() + * for details. + * -# Call psa_aead_set_nonce() with the nonce for the decryption. + * -# Call psa_aead_update_ad() zero, one or more times, passing a fragment + * of the non-encrypted additional authenticated data each time. + * -# Call psa_aead_update() zero, one or more times, passing a fragment + * of the ciphertext to decrypt each time. + * -# Call psa_aead_verify(). + * + * If an error occurs at any step after a call to psa_aead_decrypt_setup(), + * the operation will need to be reset by a call to psa_aead_abort(). The + * application may call psa_aead_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_aead_decrypt_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to psa_aead_verify(). + * - A call to psa_aead_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_aead_operation_t and not yet in use. + * \param key Identifier of the key to use for the operation. + * It must remain valid until the operation + * terminates. It must allow the usage + * #PSA_KEY_USAGE_DECRYPT. + * \param alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not an AEAD algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive), or the + * library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_decrypt_setup(psa_aead_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg); + +/** Generate a random nonce for an authenticated encryption operation. + * + * This function generates a random nonce for the authenticated encryption + * operation with an appropriate size for the chosen algorithm, key type + * and key size. + * + * The application must call psa_aead_encrypt_setup() before + * calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \param[in,out] operation Active AEAD operation. + * \param[out] nonce Buffer where the generated nonce is to be + * written. + * \param nonce_size Size of the \p nonce buffer in bytes. + * \param[out] nonce_length On success, the number of bytes of the + * generated nonce. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p nonce buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active aead encrypt + * operation, with no nonce set), or the library has not been + * previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_generate_nonce(psa_aead_operation_t *operation, + uint8_t *nonce, + size_t nonce_size, + size_t *nonce_length); + +/** Set the nonce for an authenticated encryption or decryption operation. + * + * This function sets the nonce for the authenticated + * encryption or decryption operation. + * + * The application must call psa_aead_encrypt_setup() or + * psa_aead_decrypt_setup() before calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \note When encrypting, applications should use psa_aead_generate_nonce() + * instead of this function, unless implementing a protocol that requires + * a non-random IV. + * + * \param[in,out] operation Active AEAD operation. + * \param[in] nonce Buffer containing the nonce to use. + * \param nonce_length Size of the nonce in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The size of \p nonce is not acceptable for the chosen algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, with no nonce + * set), or the library has not been previously initialized + * by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_set_nonce(psa_aead_operation_t *operation, + const uint8_t *nonce, + size_t nonce_length); + +/** Declare the lengths of the message and additional data for AEAD. + * + * The application must call this function before calling + * psa_aead_update_ad() or psa_aead_update() if the algorithm for + * the operation requires it. If the algorithm does not require it, + * calling this function is optional, but if this function is called + * then the implementation must enforce the lengths. + * + * You may call this function before or after setting the nonce with + * psa_aead_set_nonce() or psa_aead_generate_nonce(). + * + * - For #PSA_ALG_CCM, calling this function is required. + * - For the other AEAD algorithms defined in this specification, calling + * this function is not required. + * - For vendor-defined algorithm, refer to the vendor documentation. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \param[in,out] operation Active AEAD operation. + * \param ad_length Size of the non-encrypted additional + * authenticated data in bytes. + * \param plaintext_length Size of the plaintext to encrypt in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * At least one of the lengths is not acceptable for the chosen + * algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, and + * psa_aead_update_ad() and psa_aead_update() must not have been + * called yet), or the library has not been previously initialized + * by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_set_lengths(psa_aead_operation_t *operation, + size_t ad_length, + size_t plaintext_length); + +/** Pass additional data to an active AEAD operation. + * + * Additional data is authenticated, but not encrypted. + * + * You may call this function multiple times to pass successive fragments + * of the additional data. You may not call this function after passing + * data to encrypt or decrypt with psa_aead_update(). + * + * Before calling this function, you must: + * 1. Call either psa_aead_encrypt_setup() or psa_aead_decrypt_setup(). + * 2. Set the nonce with psa_aead_generate_nonce() or psa_aead_set_nonce(). + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \warning When decrypting, until psa_aead_verify() has returned #PSA_SUCCESS, + * there is no guarantee that the input is valid. Therefore, until + * you have called psa_aead_verify() and it has returned #PSA_SUCCESS, + * treat the input as untrusted and prepare to undo any action that + * depends on the input if psa_aead_verify() returns an error status. + * + * \param[in,out] operation Active AEAD operation. + * \param[in] input Buffer containing the fragment of + * additional data. + * \param input_length Size of the \p input buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total input length overflows the additional data length that + * was previously specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, have a nonce + * set, have lengths set if required by the algorithm, and + * psa_aead_update() must not have been called yet), or the library + * has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_update_ad(psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length); + +/** Encrypt or decrypt a message fragment in an active AEAD operation. + * + * Before calling this function, you must: + * 1. Call either psa_aead_encrypt_setup() or psa_aead_decrypt_setup(). + * The choice of setup function determines whether this function + * encrypts or decrypts its input. + * 2. Set the nonce with psa_aead_generate_nonce() or psa_aead_set_nonce(). + * 3. Call psa_aead_update_ad() to pass all the additional data. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \warning When decrypting, until psa_aead_verify() has returned #PSA_SUCCESS, + * there is no guarantee that the input is valid. Therefore, until + * you have called psa_aead_verify() and it has returned #PSA_SUCCESS: + * - Do not use the output in any way other than storing it in a + * confidential location. If you take any action that depends + * on the tentative decrypted data, this action will need to be + * undone if the input turns out not to be valid. Furthermore, + * if an adversary can observe that this action took place + * (for example through timing), they may be able to use this + * fact as an oracle to decrypt any message encrypted with the + * same key. + * - In particular, do not copy the output anywhere but to a + * memory or storage space that you have exclusive access to. + * + * This function does not require the input to be aligned to any + * particular block boundary. If the implementation can only process + * a whole block at a time, it must consume all the input provided, but + * it may delay the end of the corresponding output until a subsequent + * call to psa_aead_update(), psa_aead_finish() or psa_aead_verify() + * provides sufficient input. The amount of data that can be delayed + * in this way is bounded by #PSA_AEAD_UPDATE_OUTPUT_SIZE. + * + * \param[in,out] operation Active AEAD operation. + * \param[in] input Buffer containing the message fragment to + * encrypt or decrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] output Buffer where the output is to be written. + * \param output_size Size of the \p output buffer in bytes. + * This must be appropriate for the selected + * algorithm and key: + * - A sufficient output size is + * #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c key_type, + * \c alg, \p input_length) where + * \c key_type is the type of key and \c alg is + * the algorithm that were used to set up the + * operation. + * - #PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(\p + * input_length) evaluates to the maximum + * output size of any supported AEAD + * algorithm. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. + * #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c key_type, \c alg, \p input_length) or + * #PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(\p input_length) can be used to + * determine the required buffer size. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total length of input to psa_aead_update_ad() so far is + * less than the additional data length that was previously + * specified with psa_aead_set_lengths(), or + * the total input length overflows the plaintext length that + * was previously specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, have a nonce + * set, and have lengths set if required by the algorithm), or the + * library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_update(psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** Finish encrypting a message in an AEAD operation. + * + * The operation must have been set up with psa_aead_encrypt_setup(). + * + * This function finishes the authentication of the additional data + * formed by concatenating the inputs passed to preceding calls to + * psa_aead_update_ad() with the plaintext formed by concatenating the + * inputs passed to preceding calls to psa_aead_update(). + * + * This function has two output buffers: + * - \p ciphertext contains trailing ciphertext that was buffered from + * preceding calls to psa_aead_update(). + * - \p tag contains the authentication tag. + * + * When this function returns successfully, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \param[in,out] operation Active AEAD operation. + * \param[out] ciphertext Buffer where the last part of the ciphertext + * is to be written. + * \param ciphertext_size Size of the \p ciphertext buffer in bytes. + * This must be appropriate for the selected + * algorithm and key: + * - A sufficient output size is + * #PSA_AEAD_FINISH_OUTPUT_SIZE(\c key_type, + * \c alg) where \c key_type is the type of key + * and \c alg is the algorithm that were used to + * set up the operation. + * - #PSA_AEAD_FINISH_OUTPUT_MAX_SIZE evaluates to + * the maximum output size of any supported AEAD + * algorithm. + * \param[out] ciphertext_length On success, the number of bytes of + * returned ciphertext. + * \param[out] tag Buffer where the authentication tag is + * to be written. + * \param tag_size Size of the \p tag buffer in bytes. + * This must be appropriate for the selected + * algorithm and key: + * - The exact tag size is #PSA_AEAD_TAG_LENGTH(\c + * key_type, \c key_bits, \c alg) where + * \c key_type and \c key_bits are the type and + * bit-size of the key, and \c alg is the + * algorithm that were used in the call to + * psa_aead_encrypt_setup(). + * - #PSA_AEAD_TAG_MAX_SIZE evaluates to the + * maximum tag size of any supported AEAD + * algorithm. + * \param[out] tag_length On success, the number of bytes + * that make up the returned tag. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p ciphertext or \p tag buffer is too small. + * #PSA_AEAD_FINISH_OUTPUT_SIZE(\c key_type, \c alg) or + * #PSA_AEAD_FINISH_OUTPUT_MAX_SIZE can be used to determine the + * required \p ciphertext buffer size. #PSA_AEAD_TAG_LENGTH(\c key_type, + * \c key_bits, \c alg) or #PSA_AEAD_TAG_MAX_SIZE can be used to + * determine the required \p tag buffer size. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total length of input to psa_aead_update_ad() so far is + * less than the additional data length that was previously + * specified with psa_aead_set_lengths(), or + * the total length of input to psa_aead_update() so far is + * less than the plaintext length that was previously + * specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active encryption + * operation with a nonce set), or the library has not been previously + * initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_finish(psa_aead_operation_t *operation, + uint8_t *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length, + uint8_t *tag, + size_t tag_size, + size_t *tag_length); + +/** Finish authenticating and decrypting a message in an AEAD operation. + * + * The operation must have been set up with psa_aead_decrypt_setup(). + * + * This function finishes the authenticated decryption of the message + * components: + * + * - The additional data consisting of the concatenation of the inputs + * passed to preceding calls to psa_aead_update_ad(). + * - The ciphertext consisting of the concatenation of the inputs passed to + * preceding calls to psa_aead_update(). + * - The tag passed to this function call. + * + * If the authentication tag is correct, this function outputs any remaining + * plaintext and reports success. If the authentication tag is not correct, + * this function returns #PSA_ERROR_INVALID_SIGNATURE. + * + * When this function returns successfully, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \note Implementations shall make the best effort to ensure that the + * comparison between the actual tag and the expected tag is performed + * in constant time. + * + * \param[in,out] operation Active AEAD operation. + * \param[out] plaintext Buffer where the last part of the plaintext + * is to be written. This is the remaining data + * from previous calls to psa_aead_update() + * that could not be processed until the end + * of the input. + * \param plaintext_size Size of the \p plaintext buffer in bytes. + * This must be appropriate for the selected algorithm and key: + * - A sufficient output size is + * #PSA_AEAD_VERIFY_OUTPUT_SIZE(\c key_type, + * \c alg) where \c key_type is the type of key + * and \c alg is the algorithm that were used to + * set up the operation. + * - #PSA_AEAD_VERIFY_OUTPUT_MAX_SIZE evaluates to + * the maximum output size of any supported AEAD + * algorithm. + * \param[out] plaintext_length On success, the number of bytes of + * returned plaintext. + * \param[in] tag Buffer containing the authentication tag. + * \param tag_length Size of the \p tag buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The calculations were successful, but the authentication tag is + * not correct. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p plaintext buffer is too small. + * #PSA_AEAD_VERIFY_OUTPUT_SIZE(\c key_type, \c alg) or + * #PSA_AEAD_VERIFY_OUTPUT_MAX_SIZE can be used to determine the + * required buffer size. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total length of input to psa_aead_update_ad() so far is + * less than the additional data length that was previously + * specified with psa_aead_set_lengths(), or + * the total length of input to psa_aead_update() so far is + * less than the plaintext length that was previously + * specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active decryption + * operation with a nonce set), or the library has not been previously + * initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_verify(psa_aead_operation_t *operation, + uint8_t *plaintext, + size_t plaintext_size, + size_t *plaintext_length, + const uint8_t *tag, + size_t tag_length); + +/** Abort an AEAD operation. + * + * Aborting an operation frees all associated resources except for the + * \p operation structure itself. Once aborted, the operation object + * can be reused for another operation by calling + * psa_aead_encrypt_setup() or psa_aead_decrypt_setup() again. + * + * You may call this function any time after the operation object has + * been initialized as described in #psa_aead_operation_t. + * + * In particular, calling psa_aead_abort() after the operation has been + * terminated by a call to psa_aead_abort(), psa_aead_finish() or + * psa_aead_verify() is safe and has no effect. + * + * \param[in,out] operation Initialized AEAD operation. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_abort(psa_aead_operation_t *operation); + +/**@}*/ + +/** \defgroup asymmetric Asymmetric cryptography + * @{ + */ + +/** + * \brief Sign a message with a private key. For hash-and-sign algorithms, + * this includes the hashing step. + * + * \note To perform a multi-part hash-and-sign signature algorithm, first use + * a multi-part hash operation and then pass the resulting hash to + * psa_sign_hash(). PSA_ALG_GET_HASH(\p alg) can be used to determine the + * hash algorithm to use. + * + * \param[in] key Identifier of the key to use for the operation. + * It must be an asymmetric key pair. The key must + * allow the usage #PSA_KEY_USAGE_SIGN_MESSAGE. + * \param[in] alg An asymmetric signature algorithm (PSA_ALG_XXX + * value such that #PSA_ALG_IS_SIGN_MESSAGE(\p alg) + * is true), that is compatible with the type of + * \p key. + * \param[in] input The input message to sign. + * \param[in] input_length Size of the \p input buffer in bytes. + * \param[out] signature Buffer where the signature is to be written. + * \param[in] signature_size Size of the \p signature buffer in bytes. This + * must be appropriate for the selected + * algorithm and key: + * - The required signature size is + * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) + * where \c key_type and \c key_bits are the type and + * bit-size respectively of key. + * - #PSA_SIGNATURE_MAX_SIZE evaluates to the + * maximum signature size of any supported + * signature algorithm. + * \param[out] signature_length On success, the number of bytes that make up + * the returned signature value. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED + * The key does not have the #PSA_KEY_USAGE_SIGN_MESSAGE flag, + * or it does not permit the requested algorithm. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p signature buffer is too small. You can + * determine a sufficient buffer size by calling + * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) + * where \c key_type and \c key_bits are the type and bit-size + * respectively of \p key. + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_sign_message(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length); + +/** \brief Verify the signature of a message with a public key, using + * a hash-and-sign verification algorithm. + * + * \note To perform a multi-part hash-and-sign signature verification + * algorithm, first use a multi-part hash operation to hash the message + * and then pass the resulting hash to psa_verify_hash(). + * PSA_ALG_GET_HASH(\p alg) can be used to determine the hash algorithm + * to use. + * + * \param[in] key Identifier of the key to use for the operation. + * It must be a public key or an asymmetric key + * pair. The key must allow the usage + * #PSA_KEY_USAGE_VERIFY_MESSAGE. + * \param[in] alg An asymmetric signature algorithm (PSA_ALG_XXX + * value such that #PSA_ALG_IS_SIGN_MESSAGE(\p alg) + * is true), that is compatible with the type of + * \p key. + * \param[in] input The message whose signature is to be verified. + * \param[in] input_length Size of the \p input buffer in bytes. + * \param[out] signature Buffer containing the signature to verify. + * \param[in] signature_length Size of the \p signature buffer in bytes. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED + * The key does not have the #PSA_KEY_USAGE_SIGN_MESSAGE flag, + * or it does not permit the requested algorithm. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The calculation was performed successfully, but the passed signature + * is not a valid signature. + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_verify_message(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *signature, + size_t signature_length); + +/** + * \brief Sign a hash or short message with a private key. + * + * Note that to perform a hash-and-sign signature algorithm, you must + * first calculate the hash by calling psa_hash_setup(), psa_hash_update() + * and psa_hash_finish(), or alternatively by calling psa_hash_compute(). + * Then pass the resulting hash as the \p hash + * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg) + * to determine the hash algorithm to use. + * + * \param key Identifier of the key to use for the operation. + * It must be an asymmetric key pair. The key must + * allow the usage #PSA_KEY_USAGE_SIGN_HASH. + * \param alg A signature algorithm (PSA_ALG_XXX + * value such that #PSA_ALG_IS_SIGN_HASH(\p alg) + * is true), that is compatible with + * the type of \p key. + * \param[in] hash The hash or message to sign. + * \param hash_length Size of the \p hash buffer in bytes. + * \param[out] signature Buffer where the signature is to be written. + * \param signature_size Size of the \p signature buffer in bytes. + * \param[out] signature_length On success, the number of bytes + * that make up the returned signature value. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p signature buffer is too small. You can + * determine a sufficient buffer size by calling + * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) + * where \c key_type and \c key_bits are the type and bit-size + * respectively of \p key. + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_sign_hash(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length); + +/** + * \brief Verify the signature of a hash or short message using a public key. + * + * Note that to perform a hash-and-sign signature algorithm, you must + * first calculate the hash by calling psa_hash_setup(), psa_hash_update() + * and psa_hash_finish(), or alternatively by calling psa_hash_compute(). + * Then pass the resulting hash as the \p hash + * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg) + * to determine the hash algorithm to use. + * + * \param key Identifier of the key to use for the operation. It + * must be a public key or an asymmetric key pair. The + * key must allow the usage + * #PSA_KEY_USAGE_VERIFY_HASH. + * \param alg A signature algorithm (PSA_ALG_XXX + * value such that #PSA_ALG_IS_SIGN_HASH(\p alg) + * is true), that is compatible with + * the type of \p key. + * \param[in] hash The hash or message whose signature is to be + * verified. + * \param hash_length Size of the \p hash buffer in bytes. + * \param[in] signature Buffer containing the signature to verify. + * \param signature_length Size of the \p signature buffer in bytes. + * + * \retval #PSA_SUCCESS + * The signature is valid. + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The calculation was performed successfully, but the passed + * signature is not a valid signature. + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_verify_hash(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length); + +/** + * \brief Encrypt a short message with a public key. + * + * \param key Identifier of the key to use for the operation. + * It must be a public key or an asymmetric key + * pair. It must allow the usage + * #PSA_KEY_USAGE_ENCRYPT. + * \param alg An asymmetric encryption algorithm that is + * compatible with the type of \p key. + * \param[in] input The message to encrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[in] salt A salt or label, if supported by the + * encryption algorithm. + * If the algorithm does not support a + * salt, pass \c NULL. + * If the algorithm supports an optional + * salt and you do not want to pass a salt, + * pass \c NULL. + * + * - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is + * supported. + * \param salt_length Size of the \p salt buffer in bytes. + * If \p salt is \c NULL, pass 0. + * \param[out] output Buffer where the encrypted message is to + * be written. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. You can + * determine a sufficient buffer size by calling + * #PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) + * where \c key_type and \c key_bits are the type and bit-size + * respectively of \p key. + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_asymmetric_encrypt(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *salt, + size_t salt_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** + * \brief Decrypt a short message with a private key. + * + * \param key Identifier of the key to use for the operation. + * It must be an asymmetric key pair. It must + * allow the usage #PSA_KEY_USAGE_DECRYPT. + * \param alg An asymmetric encryption algorithm that is + * compatible with the type of \p key. + * \param[in] input The message to decrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[in] salt A salt or label, if supported by the + * encryption algorithm. + * If the algorithm does not support a + * salt, pass \c NULL. + * If the algorithm supports an optional + * salt and you do not want to pass a salt, + * pass \c NULL. + * + * - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is + * supported. + * \param salt_length Size of the \p salt buffer in bytes. + * If \p salt is \c NULL, pass 0. + * \param[out] output Buffer where the decrypted message is to + * be written. + * \param output_size Size of the \c output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. You can + * determine a sufficient buffer size by calling + * #PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) + * where \c key_type and \c key_bits are the type and bit-size + * respectively of \p key. + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription + * \retval #PSA_ERROR_INVALID_PADDING \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_asymmetric_decrypt(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *salt, + size_t salt_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/**@}*/ + +/** \defgroup key_derivation Key derivation and pseudorandom generation + * @{ + */ + +/** The type of the state data structure for key derivation operations. + * + * Before calling any function on a key derivation operation object, the + * application must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_key_derivation_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_key_derivation_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_KEY_DERIVATION_OPERATION_INIT, + * for example: + * \code + * psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_key_derivation_operation_init() + * to the structure, for example: + * \code + * psa_key_derivation_operation_t operation; + * operation = psa_key_derivation_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure. + * Implementation details can change in future versions without notice. + */ +typedef struct psa_key_derivation_s psa_key_derivation_operation_t; + +/** \def PSA_KEY_DERIVATION_OPERATION_INIT + * + * This macro returns a suitable initializer for a key derivation operation + * object of type #psa_key_derivation_operation_t. + */ + +/** Return an initial value for a key derivation operation object. + */ +static psa_key_derivation_operation_t psa_key_derivation_operation_init(void); + +/** Set up a key derivation operation. + * + * A key derivation algorithm takes some inputs and uses them to generate + * a byte stream in a deterministic way. + * This byte stream can be used to produce keys and other + * cryptographic material. + * + * To derive a key: + * -# Start with an initialized object of type #psa_key_derivation_operation_t. + * -# Call psa_key_derivation_setup() to select the algorithm. + * -# Provide the inputs for the key derivation by calling + * psa_key_derivation_input_bytes() or psa_key_derivation_input_key() + * as appropriate. Which inputs are needed, in what order, and whether + * they may be keys and if so of what type depends on the algorithm. + * -# Optionally set the operation's maximum capacity with + * psa_key_derivation_set_capacity(). You may do this before, in the middle + * of or after providing inputs. For some algorithms, this step is mandatory + * because the output depends on the maximum capacity. + * -# To derive a key, call psa_key_derivation_output_key(). + * To derive a byte string for a different purpose, call + * psa_key_derivation_output_bytes(). + * Successive calls to these functions use successive output bytes + * calculated by the key derivation algorithm. + * -# Clean up the key derivation operation object with + * psa_key_derivation_abort(). + * + * If this function returns an error, the key derivation operation object is + * not changed. + * + * If an error occurs at any step after a call to psa_key_derivation_setup(), + * the operation will need to be reset by a call to psa_key_derivation_abort(). + * + * Implementations must reject an attempt to derive a key of size 0. + * + * \param[in,out] operation The key derivation operation object + * to set up. It must + * have been initialized but not set up yet. + * \param alg The key derivation algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_KEY_DERIVATION(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c alg is not a key derivation algorithm. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \c alg is not supported or is not a key derivation algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive), or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_setup( + psa_key_derivation_operation_t *operation, + psa_algorithm_t alg); + +/** Retrieve the current capacity of a key derivation operation. + * + * The capacity of a key derivation is the maximum number of bytes that it can + * return. When you get *N* bytes of output from a key derivation operation, + * this reduces its capacity by *N*. + * + * \param[in] operation The operation to query. + * \param[out] capacity On success, the capacity of the operation. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active), or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_get_capacity( + const psa_key_derivation_operation_t *operation, + size_t *capacity); + +/** Set the maximum capacity of a key derivation operation. + * + * The capacity of a key derivation operation is the maximum number of bytes + * that the key derivation operation can return from this point onwards. + * + * \param[in,out] operation The key derivation operation object to modify. + * \param capacity The new capacity of the operation. + * It must be less or equal to the operation's + * current capacity. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p capacity is larger than the operation's current capacity. + * In this case, the operation object remains valid and its capacity + * remains unchanged. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active), or the + * library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_set_capacity( + psa_key_derivation_operation_t *operation, + size_t capacity); + +/** Use the maximum possible capacity for a key derivation operation. + * + * Use this value as the capacity argument when setting up a key derivation + * to indicate that the operation should have the maximum possible capacity. + * The value of the maximum possible capacity depends on the key derivation + * algorithm. + */ +#define PSA_KEY_DERIVATION_UNLIMITED_CAPACITY ((size_t) (-1)) + +/** Provide an input for key derivation or key agreement. + * + * Which inputs are required and in what order depends on the algorithm. + * Refer to the documentation of each key derivation or key agreement + * algorithm for information. + * + * This function passes direct inputs, which is usually correct for + * non-secret inputs. To pass a secret input, which should be in a key + * object, call psa_key_derivation_input_key() instead of this function. + * Refer to the documentation of individual step types + * (`PSA_KEY_DERIVATION_INPUT_xxx` values of type ::psa_key_derivation_step_t) + * for more information. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to use. + * It must have been set up with + * psa_key_derivation_setup() and must not + * have produced any output yet. + * \param step Which step the input data is for. + * \param[in] data Input data to use. + * \param data_length Size of the \p data buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step is not compatible with the operation's algorithm, or + * \c step does not allow direct inputs. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid for this input \p step, or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_input_bytes( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + const uint8_t *data, + size_t data_length); + +/** Provide a numeric input for key derivation or key agreement. + * + * Which inputs are required and in what order depends on the algorithm. + * However, when an algorithm requires a particular order, numeric inputs + * usually come first as they tend to be configuration parameters. + * Refer to the documentation of each key derivation or key agreement + * algorithm for information. + * + * This function is used for inputs which are fixed-size non-negative + * integers. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to use. + * It must have been set up with + * psa_key_derivation_setup() and must not + * have produced any output yet. + * \param step Which step the input data is for. + * \param[in] value The value of the numeric input. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step is not compatible with the operation's algorithm, or + * \c step does not allow numeric inputs. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid for this input \p step, or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_input_integer( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + uint64_t value); + +/** Provide an input for key derivation in the form of a key. + * + * Which inputs are required and in what order depends on the algorithm. + * Refer to the documentation of each key derivation or key agreement + * algorithm for information. + * + * This function obtains input from a key object, which is usually correct for + * secret inputs or for non-secret personalization strings kept in the key + * store. To pass a non-secret parameter which is not in the key store, + * call psa_key_derivation_input_bytes() instead of this function. + * Refer to the documentation of individual step types + * (`PSA_KEY_DERIVATION_INPUT_xxx` values of type ::psa_key_derivation_step_t) + * for more information. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to use. + * It must have been set up with + * psa_key_derivation_setup() and must not + * have produced any output yet. + * \param step Which step the input data is for. + * \param key Identifier of the key. It must have an + * appropriate type for step and must allow the + * usage #PSA_KEY_USAGE_DERIVE or + * #PSA_KEY_USAGE_VERIFY_DERIVATION (see note) + * and the algorithm used by the operation. + * + * \note Once all inputs steps are completed, the operations will allow: + * - psa_key_derivation_output_bytes() if each input was either a direct input + * or a key with #PSA_KEY_USAGE_DERIVE set; + * - psa_key_derivation_output_key() if the input for step + * #PSA_KEY_DERIVATION_INPUT_SECRET or #PSA_KEY_DERIVATION_INPUT_PASSWORD + * was from a key slot with #PSA_KEY_USAGE_DERIVE and each other input was + * either a direct input or a key with #PSA_KEY_USAGE_DERIVE set; + * - psa_key_derivation_verify_bytes() if each input was either a direct input + * or a key with #PSA_KEY_USAGE_VERIFY_DERIVATION set; + * - psa_key_derivation_verify_key() under the same conditions as + * psa_key_derivation_verify_bytes(). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED + * The key allows neither #PSA_KEY_USAGE_DERIVE nor + * #PSA_KEY_USAGE_VERIFY_DERIVATION, or it doesn't allow this + * algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step is not compatible with the operation's algorithm, or + * \c step does not allow key inputs of the given type + * or does not allow key inputs at all. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid for this input \p step, or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_input_key( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + mbedtls_svc_key_id_t key); + +/** Perform a key agreement and use the shared secret as input to a key + * derivation. + * + * A key agreement algorithm takes two inputs: a private key \p private_key + * a public key \p peer_key. + * The result of this function is passed as input to a key derivation. + * The output of this key derivation can be extracted by reading from the + * resulting operation to produce keys and other cryptographic material. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to use. + * It must have been set up with + * psa_key_derivation_setup() with a + * key agreement and derivation algorithm + * \c alg (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_KEY_AGREEMENT(\c alg) is true + * and #PSA_ALG_IS_RAW_KEY_AGREEMENT(\c alg) + * is false). + * The operation must be ready for an + * input of the type given by \p step. + * \param step Which step the input data is for. + * \param private_key Identifier of the private key to use. It must + * allow the usage #PSA_KEY_USAGE_DERIVE. + * \param[in] peer_key Public key of the peer. The peer key must be in the + * same format that psa_import_key() accepts for the + * public key type corresponding to the type of + * private_key. That is, this function performs the + * equivalent of + * #psa_import_key(..., + * `peer_key`, `peer_key_length`) where + * with key attributes indicating the public key + * type corresponding to the type of `private_key`. + * For example, for EC keys, this means that peer_key + * is interpreted as a point on the curve that the + * private key is on. The standard formats for public + * keys are documented in the documentation of + * psa_export_public_key(). + * \param peer_key_length Size of \p peer_key in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c private_key is not compatible with \c alg, + * or \p peer_key is not valid for \c alg or not compatible with + * \c private_key, or \c step does not allow an input resulting + * from a key agreement. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \c alg is not supported or is not a key derivation algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid for this key agreement \p step, + * or the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_key_agreement( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + mbedtls_svc_key_id_t private_key, + const uint8_t *peer_key, + size_t peer_key_length); + +/** Read some data from a key derivation operation. + * + * This function calculates output bytes from a key derivation algorithm and + * return those bytes. + * If you view the key derivation's output as a stream of bytes, this + * function destructively reads the requested number of bytes from the + * stream. + * The operation's capacity decreases by the number of bytes read. + * + * If this function returns an error status other than + * #PSA_ERROR_INSUFFICIENT_DATA, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to read from. + * \param[out] output Buffer where the output will be written. + * \param output_length Number of bytes to output. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED + * One of the inputs was a key whose policy didn't allow + * #PSA_KEY_USAGE_DERIVE. + * \retval #PSA_ERROR_INSUFFICIENT_DATA + * The operation's capacity was less than + * \p output_length bytes. Note that in this case, + * no output is written to the output buffer. + * The operation's capacity is set to 0, thus + * subsequent calls to this function will not + * succeed, even with a smaller output buffer. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active and completed + * all required input steps), or the library has not been previously + * initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_output_bytes( + psa_key_derivation_operation_t *operation, + uint8_t *output, + size_t output_length); + +/** Derive a key from an ongoing key derivation operation. + * + * This function calculates output bytes from a key derivation algorithm + * and uses those bytes to generate a key deterministically. + * The key's location, usage policy, type and size are taken from + * \p attributes. + * + * If you view the key derivation's output as a stream of bytes, this + * function destructively reads as many bytes as required from the + * stream. + * The operation's capacity decreases by the number of bytes read. + * + * If this function returns an error status other than + * #PSA_ERROR_INSUFFICIENT_DATA, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * How much output is produced and consumed from the operation, and how + * the key is derived, depends on the key type and on the key size + * (denoted \c bits below): + * + * - For key types for which the key is an arbitrary sequence of bytes + * of a given size, this function is functionally equivalent to + * calling #psa_key_derivation_output_bytes + * and passing the resulting output to #psa_import_key. + * However, this function has a security benefit: + * if the implementation provides an isolation boundary then + * the key material is not exposed outside the isolation boundary. + * As a consequence, for these key types, this function always consumes + * exactly (\c bits / 8) bytes from the operation. + * The following key types defined in this specification follow this scheme: + * + * - #PSA_KEY_TYPE_AES; + * - #PSA_KEY_TYPE_ARIA; + * - #PSA_KEY_TYPE_CAMELLIA; + * - #PSA_KEY_TYPE_DERIVE; + * - #PSA_KEY_TYPE_HMAC; + * - #PSA_KEY_TYPE_PASSWORD_HASH. + * + * - For ECC keys on a Montgomery elliptic curve + * (#PSA_KEY_TYPE_ECC_KEY_PAIR(\c curve) where \c curve designates a + * Montgomery curve), this function always draws a byte string whose + * length is determined by the curve, and sets the mandatory bits + * accordingly. That is: + * + * - Curve25519 (#PSA_ECC_FAMILY_MONTGOMERY, 255 bits): draw a 32-byte + * string and process it as specified in RFC 7748 §5. + * - Curve448 (#PSA_ECC_FAMILY_MONTGOMERY, 448 bits): draw a 56-byte + * string and process it as specified in RFC 7748 §5. + * + * - For key types for which the key is represented by a single sequence of + * \c bits bits with constraints as to which bit sequences are acceptable, + * this function draws a byte string of length (\c bits / 8) bytes rounded + * up to the nearest whole number of bytes. If the resulting byte string + * is acceptable, it becomes the key, otherwise the drawn bytes are discarded. + * This process is repeated until an acceptable byte string is drawn. + * The byte string drawn from the operation is interpreted as specified + * for the output produced by psa_export_key(). + * The following key types defined in this specification follow this scheme: + * + * - #PSA_KEY_TYPE_DES. + * Force-set the parity bits, but discard forbidden weak keys. + * For 2-key and 3-key triple-DES, the three keys are generated + * successively (for example, for 3-key triple-DES, + * if the first 8 bytes specify a weak key and the next 8 bytes do not, + * discard the first 8 bytes, use the next 8 bytes as the first key, + * and continue reading output from the operation to derive the other + * two keys). + * - Finite-field Diffie-Hellman keys (#PSA_KEY_TYPE_DH_KEY_PAIR(\c group) + * where \c group designates any Diffie-Hellman group) and + * ECC keys on a Weierstrass elliptic curve + * (#PSA_KEY_TYPE_ECC_KEY_PAIR(\c curve) where \c curve designates a + * Weierstrass curve). + * For these key types, interpret the byte string as integer + * in big-endian order. Discard it if it is not in the range + * [0, *N* - 2] where *N* is the boundary of the private key domain + * (the prime *p* for Diffie-Hellman, the subprime *q* for DSA, + * or the order of the curve's base point for ECC). + * Add 1 to the resulting integer and use this as the private key *x*. + * This method allows compliance to NIST standards, specifically + * the methods titled "key-pair generation by testing candidates" + * in NIST SP 800-56A §5.6.1.1.4 for Diffie-Hellman, + * in FIPS 186-4 §B.1.2 for DSA, and + * in NIST SP 800-56A §5.6.1.2.2 or + * FIPS 186-4 §B.4.2 for elliptic curve keys. + * + * - For other key types, including #PSA_KEY_TYPE_RSA_KEY_PAIR, + * the way in which the operation output is consumed is + * implementation-defined. + * + * In all cases, the data that is read is discarded from the operation. + * The operation's capacity is decreased by the number of bytes read. + * + * For algorithms that take an input step #PSA_KEY_DERIVATION_INPUT_SECRET, + * the input to that step must be provided with psa_key_derivation_input_key(). + * Future versions of this specification may include additional restrictions + * on the derived key based on the attributes and strength of the secret key. + * + * \param[in] attributes The attributes for the new key. + * If the key type to be created is + * #PSA_KEY_TYPE_PASSWORD_HASH then the algorithm in + * the policy must be the same as in the current + * operation. + * \param[in,out] operation The key derivation operation object to read from. + * \param[out] key On success, an identifier for the newly created + * key. For persistent keys, this is the key + * identifier defined in \p attributes. + * \c 0 on failure. + * + * \retval #PSA_SUCCESS + * Success. + * If the key is persistent, the key material and the key's metadata + * have been saved to persistent storage. + * \retval #PSA_ERROR_ALREADY_EXISTS + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_INSUFFICIENT_DATA + * There was not enough data to create the desired key. + * Note that in this case, no output is written to the output buffer. + * The operation's capacity is set to 0, thus subsequent calls to + * this function will not succeed, even with a smaller output buffer. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The key type or key size is not supported, either by the + * implementation in general or in this particular location. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The provided key attributes are not valid for the operation. + * \retval #PSA_ERROR_NOT_PERMITTED + * The #PSA_KEY_DERIVATION_INPUT_SECRET or + * #PSA_KEY_DERIVATION_INPUT_PASSWORD input was not provided through a + * key; or one of the inputs was a key whose policy didn't allow + * #PSA_KEY_USAGE_DERIVE. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active and completed + * all required input steps), or the library has not been previously + * initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_output_key( + const psa_key_attributes_t *attributes, + psa_key_derivation_operation_t *operation, + mbedtls_svc_key_id_t *key); + +/** Compare output data from a key derivation operation to an expected value. + * + * This function calculates output bytes from a key derivation algorithm and + * compares those bytes to an expected value in constant time. + * If you view the key derivation's output as a stream of bytes, this + * function destructively reads the expected number of bytes from the + * stream before comparing them. + * The operation's capacity decreases by the number of bytes read. + * + * This is functionally equivalent to the following code: + * \code + * psa_key_derivation_output_bytes(operation, tmp, output_length); + * if (memcmp(output, tmp, output_length) != 0) + * return PSA_ERROR_INVALID_SIGNATURE; + * \endcode + * except (1) it works even if the key's policy does not allow outputting the + * bytes, and (2) the comparison will be done in constant time. + * + * If this function returns an error status other than + * #PSA_ERROR_INSUFFICIENT_DATA or #PSA_ERROR_INVALID_SIGNATURE, + * the operation enters an error state and must be aborted by calling + * psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to read from. + * \param[in] expected_output Buffer containing the expected derivation output. + * \param output_length Length of the expected output; this is also the + * number of bytes that will be read. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The output was read successfully, but it differs from the expected + * output. + * \retval #PSA_ERROR_NOT_PERMITTED + * One of the inputs was a key whose policy didn't allow + * #PSA_KEY_USAGE_VERIFY_DERIVATION. + * \retval #PSA_ERROR_INSUFFICIENT_DATA + * The operation's capacity was less than + * \p output_length bytes. Note that in this case, + * the operation's capacity is set to 0, thus + * subsequent calls to this function will not + * succeed, even with a smaller expected output. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active and completed + * all required input steps), or the library has not been previously + * initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_verify_bytes( + psa_key_derivation_operation_t *operation, + const uint8_t *expected_output, + size_t output_length); + +/** Compare output data from a key derivation operation to an expected value + * stored in a key object. + * + * This function calculates output bytes from a key derivation algorithm and + * compares those bytes to an expected value, provided as key of type + * #PSA_KEY_TYPE_PASSWORD_HASH. + * If you view the key derivation's output as a stream of bytes, this + * function destructively reads the number of bytes corresponding to the + * length of the expected value from the stream before comparing them. + * The operation's capacity decreases by the number of bytes read. + * + * This is functionally equivalent to exporting the key and calling + * psa_key_derivation_verify_bytes() on the result, except that it + * works even if the key cannot be exported. + * + * If this function returns an error status other than + * #PSA_ERROR_INSUFFICIENT_DATA or #PSA_ERROR_INVALID_SIGNATURE, + * the operation enters an error state and must be aborted by calling + * psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to read from. + * \param[in] expected A key of type #PSA_KEY_TYPE_PASSWORD_HASH + * containing the expected output. Its policy must + * include the #PSA_KEY_USAGE_VERIFY_DERIVATION flag + * and the permitted algorithm must match the + * operation. The value of this key was likely + * computed by a previous call to + * psa_key_derivation_output_key(). + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The output was read successfully, but if differs from the expected + * output. + * \retval #PSA_ERROR_INVALID_HANDLE + * The key passed as the expected value does not exist. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key passed as the expected value has an invalid type. + * \retval #PSA_ERROR_NOT_PERMITTED + * The key passed as the expected value does not allow this usage or + * this algorithm; or one of the inputs was a key whose policy didn't + * allow #PSA_KEY_USAGE_VERIFY_DERIVATION. + * \retval #PSA_ERROR_INSUFFICIENT_DATA + * The operation's capacity was less than + * the length of the expected value. In this case, + * the operation's capacity is set to 0, thus + * subsequent calls to this function will not + * succeed, even with a smaller expected output. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active and completed + * all required input steps), or the library has not been previously + * initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_verify_key( + psa_key_derivation_operation_t *operation, + psa_key_id_t expected); + +/** Abort a key derivation operation. + * + * Aborting an operation frees all associated resources except for the \c + * operation structure itself. Once aborted, the operation object can be reused + * for another operation by calling psa_key_derivation_setup() again. + * + * This function may be called at any time after the operation + * object has been initialized as described in #psa_key_derivation_operation_t. + * + * In particular, it is valid to call psa_key_derivation_abort() twice, or to + * call psa_key_derivation_abort() on an operation that has not been set up. + * + * \param[in,out] operation The operation to abort. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_abort( + psa_key_derivation_operation_t *operation); + +/** Perform a key agreement and return the raw shared secret. + * + * \warning The raw result of a key agreement algorithm such as finite-field + * Diffie-Hellman or elliptic curve Diffie-Hellman has biases and should + * not be used directly as key material. It should instead be passed as + * input to a key derivation algorithm. To chain a key agreement with + * a key derivation, use psa_key_derivation_key_agreement() and other + * functions from the key derivation interface. + * + * \param alg The key agreement algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_RAW_KEY_AGREEMENT(\p alg) + * is true). + * \param private_key Identifier of the private key to use. It must + * allow the usage #PSA_KEY_USAGE_DERIVE. + * \param[in] peer_key Public key of the peer. It must be + * in the same format that psa_import_key() + * accepts. The standard formats for public + * keys are documented in the documentation + * of psa_export_public_key(). + * \param peer_key_length Size of \p peer_key in bytes. + * \param[out] output Buffer where the decrypted message is to + * be written. + * \param output_size Size of the \c output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p alg is not a key agreement algorithm, or + * \p private_key is not compatible with \p alg, + * or \p peer_key is not valid for \p alg or not compatible with + * \p private_key. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p output_size is too small + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not a supported key agreement algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_raw_key_agreement(psa_algorithm_t alg, + mbedtls_svc_key_id_t private_key, + const uint8_t *peer_key, + size_t peer_key_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/**@}*/ + +/** \defgroup random Random generation + * @{ + */ + +/** + * \brief Generate random bytes. + * + * \warning This function **can** fail! Callers MUST check the return status + * and MUST NOT use the content of the output buffer if the return + * status is not #PSA_SUCCESS. + * + * \note To generate a key, use psa_generate_key() instead. + * + * \param[out] output Output buffer for the generated data. + * \param output_size Number of bytes to generate and output. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_generate_random(uint8_t *output, + size_t output_size); + +/** + * \brief Generate a key or key pair. + * + * The key is generated randomly. + * Its location, usage policy, type and size are taken from \p attributes. + * + * Implementations must reject an attempt to generate a key of size 0. + * + * The following type-specific considerations apply: + * - For RSA keys (#PSA_KEY_TYPE_RSA_KEY_PAIR), + * the public exponent is 65537. + * The modulus is a product of two probabilistic primes + * between 2^{n-1} and 2^n where n is the bit size specified in the + * attributes. + * + * \param[in] attributes The attributes for the new key. + * \param[out] key On success, an identifier for the newly created + * key. For persistent keys, this is the key + * identifier defined in \p attributes. + * \c 0 on failure. + * + * \retval #PSA_SUCCESS + * Success. + * If the key is persistent, the key material and the key's metadata + * have been saved to persistent storage. + * \retval #PSA_ERROR_ALREADY_EXISTS + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_generate_key(const psa_key_attributes_t *attributes, + mbedtls_svc_key_id_t *key); + +/**@}*/ + +/** \defgroup interruptible_hash Interruptible sign/verify hash + * @{ + */ + +/** The type of the state data structure for interruptible hash + * signing operations. + * + * Before calling any function on a sign hash operation object, the + * application must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_sign_hash_interruptible_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_sign_hash_interruptible_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer + * #PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT, for example: + * \code + * psa_sign_hash_interruptible_operation_t operation = + * PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT; + * \endcode + * - Assign the result of the function + * psa_sign_hash_interruptible_operation_init() to the structure, for + * example: + * \code + * psa_sign_hash_interruptible_operation_t operation; + * operation = psa_sign_hash_interruptible_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure. + * Implementation details can change in future versions without notice. */ +typedef struct psa_sign_hash_interruptible_operation_s psa_sign_hash_interruptible_operation_t; + +/** The type of the state data structure for interruptible hash + * verification operations. + * + * Before calling any function on a sign hash operation object, the + * application must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_verify_hash_interruptible_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_verify_hash_interruptible_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer + * #PSA_VERIFY_HASH_INTERRUPTIBLE_OPERATION_INIT, for example: + * \code + * psa_verify_hash_interruptible_operation_t operation = + * PSA_VERIFY_HASH_INTERRUPTIBLE_OPERATION_INIT; + * \endcode + * - Assign the result of the function + * psa_verify_hash_interruptible_operation_init() to the structure, for + * example: + * \code + * psa_verify_hash_interruptible_operation_t operation; + * operation = psa_verify_hash_interruptible_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure. + * Implementation details can change in future versions without notice. */ +typedef struct psa_verify_hash_interruptible_operation_s psa_verify_hash_interruptible_operation_t; + +/** + * \brief Set the maximum number of ops allowed to be + * executed by an interruptible function in a + * single call. + * + * \warning This is a beta API, and thus subject to change + * at any point. It is not bound by the usual + * interface stability promises. + * + * \note The time taken to execute a single op is + * implementation specific and depends on + * software, hardware, the algorithm, key type and + * curve chosen. Even within a single operation, + * successive ops can take differing amounts of + * time. The only guarantee is that lower values + * for \p max_ops means functions will block for a + * lesser maximum amount of time. The functions + * \c psa_sign_interruptible_get_num_ops() and + * \c psa_verify_interruptible_get_num_ops() are + * provided to help with tuning this value. + * + * \note This value defaults to + * #PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED, which + * means the whole operation will be done in one + * go, regardless of the number of ops required. + * + * \note If more ops are needed to complete a + * computation, #PSA_OPERATION_INCOMPLETE will be + * returned by the function performing the + * computation. It is then the caller's + * responsibility to either call again with the + * same operation context until it returns 0 or an + * error code; or to call the relevant abort + * function if the answer is no longer required. + * + * \note The interpretation of \p max_ops is also + * implementation defined. On a hard real time + * system, this can indicate a hard deadline, as a + * real-time system needs a guarantee of not + * spending more than X time, however care must be + * taken in such an implementation to avoid the + * situation whereby calls just return, not being + * able to do any actual work within the allotted + * time. On a non-real-time system, the + * implementation can be more relaxed, but again + * whether this number should be interpreted as as + * hard or soft limit or even whether a less than + * or equals as regards to ops executed in a + * single call is implementation defined. + * + * \note For keys in local storage when no accelerator + * driver applies, please see also the + * documentation for \c mbedtls_ecp_set_max_ops(), + * which is the internal implementation in these + * cases. + * + * \warning With implementations that interpret this number + * as a hard limit, setting this number too small + * may result in an infinite loop, whereby each + * call results in immediate return with no ops + * done (as there is not enough time to execute + * any), and thus no result will ever be achieved. + * + * \note This only applies to functions whose + * documentation mentions they may return + * #PSA_OPERATION_INCOMPLETE. + * + * \param max_ops The maximum number of ops to be executed in a + * single call. This can be a number from 0 to + * #PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED, where 0 + * is the least amount of work done per call. + */ +void psa_interruptible_set_max_ops(uint32_t max_ops); + +/** + * \brief Get the maximum number of ops allowed to be + * executed by an interruptible function in a + * single call. This will return the last + * value set by + * \c psa_interruptible_set_max_ops() or + * #PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED if + * that function has never been called. + * + * \warning This is a beta API, and thus subject to change + * at any point. It is not bound by the usual + * interface stability promises. + * + * \return Maximum number of ops allowed to be + * executed by an interruptible function in a + * single call. + */ +uint32_t psa_interruptible_get_max_ops(void); + +/** + * \brief Get the number of ops that a hash signing + * operation has taken so far. If the operation + * has completed, then this will represent the + * number of ops required for the entire + * operation. After initialization or calling + * \c psa_sign_hash_interruptible_abort() on + * the operation, a value of 0 will be returned. + * + * \note This interface is guaranteed re-entrant and + * thus may be called from driver code. + * + * \warning This is a beta API, and thus subject to change + * at any point. It is not bound by the usual + * interface stability promises. + * + * This is a helper provided to help you tune the + * value passed to \c + * psa_interruptible_set_max_ops(). + * + * \param operation The \c psa_sign_hash_interruptible_operation_t + * to use. This must be initialized first. + * + * \return Number of ops that the operation has taken so + * far. + */ +uint32_t psa_sign_hash_get_num_ops( + const psa_sign_hash_interruptible_operation_t *operation); + +/** + * \brief Get the number of ops that a hash verification + * operation has taken so far. If the operation + * has completed, then this will represent the + * number of ops required for the entire + * operation. After initialization or calling \c + * psa_verify_hash_interruptible_abort() on the + * operation, a value of 0 will be returned. + * + * \warning This is a beta API, and thus subject to change + * at any point. It is not bound by the usual + * interface stability promises. + * + * This is a helper provided to help you tune the + * value passed to \c + * psa_interruptible_set_max_ops(). + * + * \param operation The \c + * psa_verify_hash_interruptible_operation_t to + * use. This must be initialized first. + * + * \return Number of ops that the operation has taken so + * far. + */ +uint32_t psa_verify_hash_get_num_ops( + const psa_verify_hash_interruptible_operation_t *operation); + +/** + * \brief Start signing a hash or short message with a + * private key, in an interruptible manner. + * + * \see \c psa_sign_hash_complete() + * + * \warning This is a beta API, and thus subject to change + * at any point. It is not bound by the usual + * interface stability promises. + * + * \note This function combined with \c + * psa_sign_hash_complete() is equivalent to + * \c psa_sign_hash() but + * \c psa_sign_hash_complete() can return early and + * resume according to the limit set with \c + * psa_interruptible_set_max_ops() to reduce the + * maximum time spent in a function call. + * + * \note Users should call \c psa_sign_hash_complete() + * repeatedly on the same context after a + * successful call to this function until \c + * psa_sign_hash_complete() either returns 0 or an + * error. \c psa_sign_hash_complete() will return + * #PSA_OPERATION_INCOMPLETE if there is more work + * to do. Alternatively users can call + * \c psa_sign_hash_abort() at any point if they no + * longer want the result. + * + * \note If this function returns an error status, the + * operation enters an error state and must be + * aborted by calling \c psa_sign_hash_abort(). + * + * \param[in, out] operation The \c psa_sign_hash_interruptible_operation_t + * to use. This must be initialized first. + * + * \param key Identifier of the key to use for the operation. + * It must be an asymmetric key pair. The key must + * allow the usage #PSA_KEY_USAGE_SIGN_HASH. + * \param alg A signature algorithm (\c PSA_ALG_XXX + * value such that #PSA_ALG_IS_SIGN_HASH(\p alg) + * is true), that is compatible with + * the type of \p key. + * \param[in] hash The hash or message to sign. + * \param hash_length Size of the \p hash buffer in bytes. + * + * \retval #PSA_SUCCESS + * The operation started successfully - call \c psa_sign_hash_complete() + * with the same context to complete the operation + * + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED + * The key does not have the #PSA_KEY_USAGE_SIGN_HASH flag, or it does + * not permit the requested algorithm. + * \retval #PSA_ERROR_BAD_STATE + * An operation has previously been started on this context, and is + * still in progress. + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_sign_hash_start( + psa_sign_hash_interruptible_operation_t *operation, + mbedtls_svc_key_id_t key, psa_algorithm_t alg, + const uint8_t *hash, size_t hash_length); + +/** + * \brief Continue and eventually complete the action of + * signing a hash or short message with a private + * key, in an interruptible manner. + * + * \see \c psa_sign_hash_start() + * + * \warning This is a beta API, and thus subject to change + * at any point. It is not bound by the usual + * interface stability promises. + * + * \note This function combined with \c + * psa_sign_hash_start() is equivalent to + * \c psa_sign_hash() but this function can return + * early and resume according to the limit set with + * \c psa_interruptible_set_max_ops() to reduce the + * maximum time spent in a function call. + * + * \note Users should call this function on the same + * operation object repeatedly until it either + * returns 0 or an error. This function will return + * #PSA_OPERATION_INCOMPLETE if there is more work + * to do. Alternatively users can call + * \c psa_sign_hash_abort() at any point if they no + * longer want the result. + * + * \note When this function returns successfully, the + * operation becomes inactive. If this function + * returns an error status, the operation enters an + * error state and must be aborted by calling + * \c psa_sign_hash_abort(). + * + * \param[in, out] operation The \c psa_sign_hash_interruptible_operation_t + * to use. This must be initialized first, and have + * had \c psa_sign_hash_start() called with it + * first. + * + * \param[out] signature Buffer where the signature is to be written. + * \param signature_size Size of the \p signature buffer in bytes. This + * must be appropriate for the selected + * algorithm and key: + * - The required signature size is + * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c + * key_bits, \c alg) where \c key_type and \c + * key_bits are the type and bit-size + * respectively of key. + * - #PSA_SIGNATURE_MAX_SIZE evaluates to the + * maximum signature size of any supported + * signature algorithm. + * \param[out] signature_length On success, the number of bytes that make up + * the returned signature value. + * + * \retval #PSA_SUCCESS + * Operation completed successfully + * + * \retval #PSA_OPERATION_INCOMPLETE + * Operation was interrupted due to the setting of \c + * psa_interruptible_set_max_ops(). There is still work to be done. + * Call this function again with the same operation object. + * + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p signature buffer is too small. You can + * determine a sufficient buffer size by calling + * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) + * where \c key_type and \c key_bits are the type and bit-size + * respectively of \p key. + * + * \retval #PSA_ERROR_BAD_STATE + * An operation was not previously started on this context via + * \c psa_sign_hash_start(). + * + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has either not been previously initialized by + * psa_crypto_init() or you did not previously call + * psa_sign_hash_start() with this operation object. It is + * implementation-dependent whether a failure to initialize results in + * this error code. + */ +psa_status_t psa_sign_hash_complete( + psa_sign_hash_interruptible_operation_t *operation, + uint8_t *signature, size_t signature_size, + size_t *signature_length); + +/** + * \brief Abort a sign hash operation. + * + * \warning This is a beta API, and thus subject to change + * at any point. It is not bound by the usual + * interface stability promises. + * + * \note This function is the only function that clears + * the number of ops completed as part of the + * operation. Please ensure you copy this value via + * \c psa_sign_hash_get_num_ops() if required + * before calling. + * + * \note Aborting an operation frees all associated + * resources except for the \p operation structure + * itself. Once aborted, the operation object can + * be reused for another operation by calling \c + * psa_sign_hash_start() again. + * + * \note You may call this function any time after the + * operation object has been initialized. In + * particular, calling \c psa_sign_hash_abort() + * after the operation has already been terminated + * by a call to \c psa_sign_hash_abort() or + * psa_sign_hash_complete() is safe. + * + * \param[in,out] operation Initialized sign hash operation. + * + * \retval #PSA_SUCCESS + * The operation was aborted successfully. + * + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_sign_hash_abort( + psa_sign_hash_interruptible_operation_t *operation); + +/** + * \brief Start reading and verifying a hash or short + * message, in an interruptible manner. + * + * \see \c psa_verify_hash_complete() + * + * \warning This is a beta API, and thus subject to change + * at any point. It is not bound by the usual + * interface stability promises. + * + * \note This function combined with \c + * psa_verify_hash_complete() is equivalent to + * \c psa_verify_hash() but \c + * psa_verify_hash_complete() can return early and + * resume according to the limit set with \c + * psa_interruptible_set_max_ops() to reduce the + * maximum time spent in a function. + * + * \note Users should call \c psa_verify_hash_complete() + * repeatedly on the same operation object after a + * successful call to this function until \c + * psa_verify_hash_complete() either returns 0 or + * an error. \c psa_verify_hash_complete() will + * return #PSA_OPERATION_INCOMPLETE if there is + * more work to do. Alternatively users can call + * \c psa_verify_hash_abort() at any point if they + * no longer want the result. + * + * \note If this function returns an error status, the + * operation enters an error state and must be + * aborted by calling \c psa_verify_hash_abort(). + * + * \param[in, out] operation The \c psa_verify_hash_interruptible_operation_t + * to use. This must be initialized first. + * + * \param key Identifier of the key to use for the operation. + * The key must allow the usage + * #PSA_KEY_USAGE_VERIFY_HASH. + * \param alg A signature algorithm (\c PSA_ALG_XXX + * value such that #PSA_ALG_IS_SIGN_HASH(\p alg) + * is true), that is compatible with + * the type of \p key. + * \param[in] hash The hash whose signature is to be verified. + * \param hash_length Size of the \p hash buffer in bytes. + * \param[in] signature Buffer containing the signature to verify. + * \param signature_length Size of the \p signature buffer in bytes. + * + * \retval #PSA_SUCCESS + * The operation started successfully - please call \c + * psa_verify_hash_complete() with the same context to complete the + * operation. + * + * \retval #PSA_ERROR_BAD_STATE + * Another operation has already been started on this context, and is + * still in progress. + * + * \retval #PSA_ERROR_NOT_PERMITTED + * The key does not have the #PSA_KEY_USAGE_VERIFY_HASH flag, or it does + * not permit the requested algorithm. + * + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_verify_hash_start( + psa_verify_hash_interruptible_operation_t *operation, + mbedtls_svc_key_id_t key, psa_algorithm_t alg, + const uint8_t *hash, size_t hash_length, + const uint8_t *signature, size_t signature_length); + +/** + * \brief Continue and eventually complete the action of + * reading and verifying a hash or short message + * signed with a private key, in an interruptible + * manner. + * + * \see \c psa_verify_hash_start() + * + * \warning This is a beta API, and thus subject to change + * at any point. It is not bound by the usual + * interface stability promises. + * + * \note This function combined with \c + * psa_verify_hash_start() is equivalent to + * \c psa_verify_hash() but this function can + * return early and resume according to the limit + * set with \c psa_interruptible_set_max_ops() to + * reduce the maximum time spent in a function + * call. + * + * \note Users should call this function on the same + * operation object repeatedly until it either + * returns 0 or an error. This function will return + * #PSA_OPERATION_INCOMPLETE if there is more work + * to do. Alternatively users can call + * \c psa_verify_hash_abort() at any point if they + * no longer want the result. + * + * \note When this function returns successfully, the + * operation becomes inactive. If this function + * returns an error status, the operation enters an + * error state and must be aborted by calling + * \c psa_verify_hash_abort(). + * + * \param[in, out] operation The \c psa_verify_hash_interruptible_operation_t + * to use. This must be initialized first, and have + * had \c psa_verify_hash_start() called with it + * first. + * + * \retval #PSA_SUCCESS + * Operation completed successfully, and the passed signature is valid. + * + * \retval #PSA_OPERATION_INCOMPLETE + * Operation was interrupted due to the setting of \c + * psa_interruptible_set_max_ops(). There is still work to be done. + * Call this function again with the same operation object. + * + * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The calculation was performed successfully, but the passed + * signature is not a valid signature. + * \retval #PSA_ERROR_BAD_STATE + * An operation was not previously started on this context via + * \c psa_verify_hash_start(). + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has either not been previously initialized by + * psa_crypto_init() or you did not previously call + * psa_verify_hash_start() on this object. It is + * implementation-dependent whether a failure to initialize results in + * this error code. + */ +psa_status_t psa_verify_hash_complete( + psa_verify_hash_interruptible_operation_t *operation); + +/** + * \brief Abort a verify hash operation. + * + * \warning This is a beta API, and thus subject to change at + * any point. It is not bound by the usual interface + * stability promises. + * + * \note This function is the only function that clears the + * number of ops completed as part of the operation. + * Please ensure you copy this value via + * \c psa_verify_hash_get_num_ops() if required + * before calling. + * + * \note Aborting an operation frees all associated + * resources except for the operation structure + * itself. Once aborted, the operation object can be + * reused for another operation by calling \c + * psa_verify_hash_start() again. + * + * \note You may call this function any time after the + * operation object has been initialized. + * In particular, calling \c psa_verify_hash_abort() + * after the operation has already been terminated by + * a call to \c psa_verify_hash_abort() or + * psa_verify_hash_complete() is safe. + * + * \param[in,out] operation Initialized verify hash operation. + * + * \retval #PSA_SUCCESS + * The operation was aborted successfully. + * + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_verify_hash_abort( + psa_verify_hash_interruptible_operation_t *operation); + + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +/* The file "crypto_sizes.h" contains definitions for size calculation + * macros whose definitions are implementation-specific. */ +#include "crypto_sizes.h" + +/* The file "crypto_struct.h" contains definitions for + * implementation-specific structs that are declared above. */ +#if defined(MBEDTLS_PSA_CRYPTO_STRUCT_FILE) +#include MBEDTLS_PSA_CRYPTO_STRUCT_FILE +#else +#include "crypto_struct.h" +#endif + +/* The file "crypto_extra.h" contains vendor-specific definitions. This + * can include vendor-defined algorithms, extra functions, etc. */ +#include "crypto_extra.h" + +#endif /* PSA_CRYPTO_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_builtin_composites.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_builtin_composites.h new file mode 100644 index 0000000..932c503 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_builtin_composites.h @@ -0,0 +1,219 @@ +/* + * Context structure declaration of the Mbed TLS software-based PSA drivers + * called through the PSA Crypto driver dispatch layer. + * This file contains the context structures of those algorithms which need to + * rely on other algorithms, i.e. are 'composite' algorithms. + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + * + * \note This header and its content is not part of the Mbed TLS API and + * applications must not depend on it. Its main purpose is to define the + * multi-part state objects of the Mbed TLS software-based PSA drivers. The + * definition of these objects are then used by crypto_struct.h to define the + * implementation-defined types of PSA multi-part state objects. + */ +/* + * 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 PSA_CRYPTO_BUILTIN_COMPOSITES_H +#define PSA_CRYPTO_BUILTIN_COMPOSITES_H +#include "mbedtls/private_access.h" + +#include + +/* + * MAC multi-part operation definitions. + */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) +#define MBEDTLS_PSA_BUILTIN_MAC +#endif + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) || defined(PSA_CRYPTO_DRIVER_TEST) +typedef struct { + /** The HMAC algorithm in use */ + psa_algorithm_t MBEDTLS_PRIVATE(alg); + /** The hash context. */ + struct psa_hash_operation_s hash_ctx; + /** The HMAC part of the context. */ + uint8_t MBEDTLS_PRIVATE(opad)[PSA_HMAC_MAX_HASH_BLOCK_SIZE]; +} mbedtls_psa_hmac_operation_t; + +#define MBEDTLS_PSA_HMAC_OPERATION_INIT { 0, PSA_HASH_OPERATION_INIT, { 0 } } +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */ + +#include "mbedtls/cmac.h" + +typedef struct { + psa_algorithm_t MBEDTLS_PRIVATE(alg); + union { + unsigned MBEDTLS_PRIVATE(dummy); /* Make the union non-empty even with no supported algorithms. */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) || defined(PSA_CRYPTO_DRIVER_TEST) + mbedtls_psa_hmac_operation_t MBEDTLS_PRIVATE(hmac); +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) || defined(PSA_CRYPTO_DRIVER_TEST) + mbedtls_cipher_context_t MBEDTLS_PRIVATE(cmac); +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */ + } MBEDTLS_PRIVATE(ctx); +} mbedtls_psa_mac_operation_t; + +#define MBEDTLS_PSA_MAC_OPERATION_INIT { 0, { 0 } } + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) +#define MBEDTLS_PSA_BUILTIN_AEAD 1 +#endif + +/* Context structure for the Mbed TLS AEAD implementation. */ +typedef struct { + psa_algorithm_t MBEDTLS_PRIVATE(alg); + psa_key_type_t MBEDTLS_PRIVATE(key_type); + + unsigned int MBEDTLS_PRIVATE(is_encrypt) : 1; + + uint8_t MBEDTLS_PRIVATE(tag_length); + + union { + unsigned dummy; /* Enable easier initializing of the union. */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) + mbedtls_ccm_context MBEDTLS_PRIVATE(ccm); +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) + mbedtls_gcm_context MBEDTLS_PRIVATE(gcm); +#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) + mbedtls_chachapoly_context MBEDTLS_PRIVATE(chachapoly); +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ + + } ctx; + +} mbedtls_psa_aead_operation_t; + +#define MBEDTLS_PSA_AEAD_OPERATION_INIT { 0, 0, 0, 0, { 0 } } + +#include "mbedtls/ecdsa.h" + +/* Context structure for the Mbed TLS interruptible sign hash implementation. */ +typedef struct { +#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ + defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecdsa_context *MBEDTLS_PRIVATE(ctx); + mbedtls_ecdsa_restart_ctx MBEDTLS_PRIVATE(restart_ctx); + + uint32_t MBEDTLS_PRIVATE(num_ops); + + size_t MBEDTLS_PRIVATE(coordinate_bytes); + psa_algorithm_t MBEDTLS_PRIVATE(alg); + mbedtls_md_type_t MBEDTLS_PRIVATE(md_alg); + uint8_t MBEDTLS_PRIVATE(hash)[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)]; + size_t MBEDTLS_PRIVATE(hash_length); + +#else + /* Make the struct non-empty if algs not supported. */ + unsigned MBEDTLS_PRIVATE(dummy); + +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && + * defined( MBEDTLS_ECP_RESTARTABLE ) */ +} mbedtls_psa_sign_hash_interruptible_operation_t; + +#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ + defined(MBEDTLS_ECP_RESTARTABLE) +#define MBEDTLS_PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT { { 0 }, { 0 }, 0, 0, 0, 0, 0, 0 } +#else +#define MBEDTLS_PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT { 0 } +#endif + +/* Context structure for the Mbed TLS interruptible verify hash + * implementation.*/ +typedef struct { +#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ + defined(MBEDTLS_ECP_RESTARTABLE) + + mbedtls_ecdsa_context *MBEDTLS_PRIVATE(ctx); + mbedtls_ecdsa_restart_ctx MBEDTLS_PRIVATE(restart_ctx); + + uint32_t MBEDTLS_PRIVATE(num_ops); + + uint8_t MBEDTLS_PRIVATE(hash)[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)]; + size_t MBEDTLS_PRIVATE(hash_length); + + mbedtls_mpi MBEDTLS_PRIVATE(r); + mbedtls_mpi MBEDTLS_PRIVATE(s); + +#else + /* Make the struct non-empty if algs not supported. */ + unsigned MBEDTLS_PRIVATE(dummy); + +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && + * defined( MBEDTLS_ECP_RESTARTABLE ) */ + +} mbedtls_psa_verify_hash_interruptible_operation_t; + +#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ + defined(MBEDTLS_ECP_RESTARTABLE) +#define MBEDTLS_VERIFY_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT { { 0 }, { 0 }, 0, 0, 0, 0, { 0 }, \ + { 0 } } +#else +#define MBEDTLS_VERIFY_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT { 0 } +#endif + + +/* EC-JPAKE operation definitions */ + +#include "mbedtls/ecjpake.h" + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) +#define MBEDTLS_PSA_BUILTIN_PAKE 1 +#endif + +/* Note: the format for mbedtls_ecjpake_read/write function has an extra + * length byte for each step, plus an extra 3 bytes for ECParameters in the + * server's 2nd round. */ +#define MBEDTLS_PSA_JPAKE_BUFFER_SIZE ((3 + 1 + 65 + 1 + 65 + 1 + 32) * 2) + +typedef struct { + psa_algorithm_t MBEDTLS_PRIVATE(alg); + + uint8_t *MBEDTLS_PRIVATE(password); + size_t MBEDTLS_PRIVATE(password_len); +#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) + uint8_t MBEDTLS_PRIVATE(role); + uint8_t MBEDTLS_PRIVATE(buffer[MBEDTLS_PSA_JPAKE_BUFFER_SIZE]); + size_t MBEDTLS_PRIVATE(buffer_length); + size_t MBEDTLS_PRIVATE(buffer_offset); +#endif + /* Context structure for the Mbed TLS EC-JPAKE implementation. */ + union { + unsigned int MBEDTLS_PRIVATE(dummy); +#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) + mbedtls_ecjpake_context MBEDTLS_PRIVATE(jpake); +#endif + } MBEDTLS_PRIVATE(ctx); + +} mbedtls_psa_pake_operation_t; + +#define MBEDTLS_PSA_PAKE_OPERATION_INIT { { 0 } } + +#endif /* PSA_CRYPTO_BUILTIN_COMPOSITES_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_builtin_primitives.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_builtin_primitives.h new file mode 100644 index 0000000..c76bc78 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_builtin_primitives.h @@ -0,0 +1,114 @@ +/* + * Context structure declaration of the Mbed TLS software-based PSA drivers + * called through the PSA Crypto driver dispatch layer. + * This file contains the context structures of those algorithms which do not + * rely on other algorithms, i.e. are 'primitive' algorithms. + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + * + * \note This header and its content is not part of the Mbed TLS API and + * applications must not depend on it. Its main purpose is to define the + * multi-part state objects of the Mbed TLS software-based PSA drivers. The + * definition of these objects are then used by crypto_struct.h to define the + * implementation-defined types of PSA multi-part state objects. + */ +/* + * 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 PSA_CRYPTO_BUILTIN_PRIMITIVES_H +#define PSA_CRYPTO_BUILTIN_PRIMITIVES_H +#include "mbedtls/private_access.h" + +#include + +/* + * Hash multi-part operation definitions. + */ + +#include "mbedtls/md5.h" +#include "mbedtls/ripemd160.h" +#include "mbedtls/sha1.h" +#include "mbedtls/sha256.h" +#include "mbedtls/sha512.h" + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) +#define MBEDTLS_PSA_BUILTIN_HASH +#endif + +typedef struct { + psa_algorithm_t MBEDTLS_PRIVATE(alg); + union { + unsigned dummy; /* Make the union non-empty even with no supported algorithms. */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) + mbedtls_md5_context md5; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) + mbedtls_ripemd160_context ripemd160; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1) + mbedtls_sha1_context sha1; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224) + mbedtls_sha256_context sha256; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384) + mbedtls_sha512_context sha512; +#endif + } MBEDTLS_PRIVATE(ctx); +} mbedtls_psa_hash_operation_t; + +#define MBEDTLS_PSA_HASH_OPERATION_INIT { 0, { 0 } } + +/* + * Cipher multi-part operation definitions. + */ + +#include "mbedtls/cipher.h" + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_CTR) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_CFB) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_OFB) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7) +#define MBEDTLS_PSA_BUILTIN_CIPHER 1 +#endif + +typedef struct { + /* Context structure for the Mbed TLS cipher implementation. */ + psa_algorithm_t MBEDTLS_PRIVATE(alg); + uint8_t MBEDTLS_PRIVATE(iv_length); + uint8_t MBEDTLS_PRIVATE(block_length); + union { + unsigned int MBEDTLS_PRIVATE(dummy); + mbedtls_cipher_context_t MBEDTLS_PRIVATE(cipher); + } MBEDTLS_PRIVATE(ctx); +} mbedtls_psa_cipher_operation_t; + +#define MBEDTLS_PSA_CIPHER_OPERATION_INIT { 0, 0, 0, { 0 } } + +#endif /* PSA_CRYPTO_BUILTIN_PRIMITIVES_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_compat.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_compat.h new file mode 100644 index 0000000..3544f96 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_compat.h @@ -0,0 +1,165 @@ +/** + * \file psa/crypto_compat.h + * + * \brief PSA cryptography module: Backward compatibility aliases + * + * This header declares alternative names for macro and functions. + * New application code should not use these names. + * These names may be removed in a future version of Mbed Crypto. + * + * \note This file may not be included directly. Applications must + * include psa/crypto.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. + */ + +#ifndef PSA_CRYPTO_COMPAT_H +#define PSA_CRYPTO_COMPAT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * To support both openless APIs and psa_open_key() temporarily, define + * psa_key_handle_t to be equal to mbedtls_svc_key_id_t. Do not mark the + * type and its utility macros and functions deprecated yet. This will be done + * in a subsequent phase. + */ +typedef mbedtls_svc_key_id_t psa_key_handle_t; + +#define PSA_KEY_HANDLE_INIT MBEDTLS_SVC_KEY_ID_INIT + +/** Check whether a handle is null. + * + * \param handle Handle + * + * \return Non-zero if the handle is null, zero otherwise. + */ +static inline int psa_key_handle_is_null(psa_key_handle_t handle) +{ + return mbedtls_svc_key_id_is_null(handle); +} + +/** Open a handle to an existing persistent key. + * + * Open a handle to a persistent key. A key is persistent if it was created + * with a lifetime other than #PSA_KEY_LIFETIME_VOLATILE. A persistent key + * always has a nonzero key identifier, set with psa_set_key_id() when + * creating the key. Implementations may provide additional pre-provisioned + * keys that can be opened with psa_open_key(). Such keys have an application + * key identifier in the vendor range, as documented in the description of + * #psa_key_id_t. + * + * The application must eventually close the handle with psa_close_key() or + * psa_destroy_key() to release associated resources. If the application dies + * without calling one of these functions, the implementation should perform + * the equivalent of a call to psa_close_key(). + * + * Some implementations permit an application to open the same key multiple + * times. If this is successful, each call to psa_open_key() will return a + * different key handle. + * + * \note This API is not part of the PSA Cryptography API Release 1.0.0 + * specification. It was defined in the 1.0 Beta 3 version of the + * specification but was removed in the 1.0.0 released version. This API is + * kept for the time being to not break applications relying on it. It is not + * deprecated yet but will be in the near future. + * + * \note Applications that rely on opening a key multiple times will not be + * portable to implementations that only permit a single key handle to be + * opened. See also :ref:\`key-handles\`. + * + * + * \param key The persistent identifier of the key. + * \param[out] handle On success, a handle to the key. + * + * \retval #PSA_SUCCESS + * Success. The application can now use the value of `*handle` + * to access the key. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * The implementation does not have sufficient resources to open the + * key. This can be due to reaching an implementation limit on the + * number of open keys, the number of open key handles, or available + * memory. + * \retval #PSA_ERROR_DOES_NOT_EXIST + * There is no persistent key with key identifier \p key. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not a valid persistent key identifier. + * \retval #PSA_ERROR_NOT_PERMITTED + * The specified key exists, but the application does not have the + * permission to access it. Note that this specification does not + * define any way to create such a key, but it may be possible + * through implementation-specific means. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_open_key(mbedtls_svc_key_id_t key, + psa_key_handle_t *handle); + +/** Close a key handle. + * + * If the handle designates a volatile key, this will destroy the key material + * and free all associated resources, just like psa_destroy_key(). + * + * If this is the last open handle to a persistent key, then closing the handle + * will free all resources associated with the key in volatile memory. The key + * data in persistent storage is not affected and can be opened again later + * with a call to psa_open_key(). + * + * Closing the key handle makes the handle invalid, and the key handle + * must not be used again by the application. + * + * \note This API is not part of the PSA Cryptography API Release 1.0.0 + * specification. It was defined in the 1.0 Beta 3 version of the + * specification but was removed in the 1.0.0 released version. This API is + * kept for the time being to not break applications relying on it. It is not + * deprecated yet but will be in the near future. + * + * \note If the key handle was used to set up an active + * :ref:\`multipart operation \`, then closing the + * key handle can cause the multipart operation to fail. Applications should + * maintain the key handle until after the multipart operation has finished. + * + * \param handle The key handle to close. + * If this is \c 0, do nothing and return \c PSA_SUCCESS. + * + * \retval #PSA_SUCCESS + * \p handle was a valid handle or \c 0. It is now closed. + * \retval #PSA_ERROR_INVALID_HANDLE + * \p handle is not a valid handle nor \c 0. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_close_key(psa_key_handle_t handle); + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_COMPAT_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_config.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_config.h new file mode 100644 index 0000000..e68fac8 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_config.h @@ -0,0 +1,133 @@ +/** + * \file psa/crypto_config.h + * \brief PSA crypto configuration options (set of defines) + * + */ +#if defined(MBEDTLS_PSA_CRYPTO_CONFIG) +/** + * When #MBEDTLS_PSA_CRYPTO_CONFIG is enabled in mbedtls_config.h, + * this file determines which cryptographic mechanisms are enabled + * through the PSA Cryptography API (\c psa_xxx() functions). + * + * To enable a cryptographic mechanism, uncomment the definition of + * the corresponding \c PSA_WANT_xxx preprocessor symbol. + * To disable a cryptographic mechanism, comment out the definition of + * the corresponding \c PSA_WANT_xxx preprocessor symbol. + * The names of cryptographic mechanisms correspond to values + * defined in psa/crypto_values.h, with the prefix \c PSA_WANT_ instead + * of \c PSA_. + * + * Note that many cryptographic mechanisms involve two symbols: one for + * the key type (\c PSA_WANT_KEY_TYPE_xxx) and one for the algorithm + * (\c PSA_WANT_ALG_xxx). Mechanisms with additional parameters may involve + * additional symbols. + */ +#else +/** + * When \c MBEDTLS_PSA_CRYPTO_CONFIG is disabled in mbedtls_config.h, + * this file is not used, and cryptographic mechanisms are supported + * through the PSA API if and only if they are supported through the + * mbedtls_xxx API. + */ +#endif +/* + * 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 PSA_CRYPTO_CONFIG_H +#define PSA_CRYPTO_CONFIG_H + +/* + * CBC-MAC is not yet supported via the PSA API in Mbed TLS. + */ +//#define PSA_WANT_ALG_CBC_MAC 1 +#define PSA_WANT_ALG_CBC_NO_PADDING 1 +#define PSA_WANT_ALG_CBC_PKCS7 1 +#define PSA_WANT_ALG_CCM 1 +#define PSA_WANT_ALG_CCM_STAR_NO_TAG 1 +#define PSA_WANT_ALG_CMAC 1 +#define PSA_WANT_ALG_CFB 1 +#define PSA_WANT_ALG_CHACHA20_POLY1305 1 +#define PSA_WANT_ALG_CTR 1 +#define PSA_WANT_ALG_DETERMINISTIC_ECDSA 1 +#define PSA_WANT_ALG_ECB_NO_PADDING 1 +#define PSA_WANT_ALG_ECDH 1 +#define PSA_WANT_ALG_ECDSA 1 +#define PSA_WANT_ALG_JPAKE 1 +#define PSA_WANT_ALG_GCM 1 +#define PSA_WANT_ALG_HKDF 1 +#define PSA_WANT_ALG_HKDF_EXTRACT 1 +#define PSA_WANT_ALG_HKDF_EXPAND 1 +#define PSA_WANT_ALG_HMAC 1 +#define PSA_WANT_ALG_MD5 1 +#define PSA_WANT_ALG_OFB 1 +/* PBKDF2-HMAC is not yet supported via the PSA API in Mbed TLS. + * Note: when adding support, also adjust include/mbedtls/config_psa.h */ +//#define PSA_WANT_ALG_PBKDF2_HMAC 1 +#define PSA_WANT_ALG_RIPEMD160 1 +#define PSA_WANT_ALG_RSA_OAEP 1 +#define PSA_WANT_ALG_RSA_PKCS1V15_CRYPT 1 +#define PSA_WANT_ALG_RSA_PKCS1V15_SIGN 1 +#define PSA_WANT_ALG_RSA_PSS 1 +#define PSA_WANT_ALG_SHA_1 1 +#define PSA_WANT_ALG_SHA_224 1 +#define PSA_WANT_ALG_SHA_256 1 +#define PSA_WANT_ALG_SHA_384 1 +#define PSA_WANT_ALG_SHA_512 1 +#define PSA_WANT_ALG_STREAM_CIPHER 1 +#define PSA_WANT_ALG_TLS12_PRF 1 +#define PSA_WANT_ALG_TLS12_PSK_TO_MS 1 +#define PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS 1 + +/* PBKDF2-HMAC is not yet supported via the PSA API in Mbed TLS. + * Note: when adding support, also adjust include/mbedtls/config_psa.h */ +//#define PSA_WANT_ALG_XTS 1 + +#define PSA_WANT_ECC_BRAINPOOL_P_R1_256 1 +#define PSA_WANT_ECC_BRAINPOOL_P_R1_384 1 +#define PSA_WANT_ECC_BRAINPOOL_P_R1_512 1 +#define PSA_WANT_ECC_MONTGOMERY_255 1 +#define PSA_WANT_ECC_MONTGOMERY_448 1 +#define PSA_WANT_ECC_SECP_K1_192 1 +/* + * SECP224K1 is buggy via the PSA API in Mbed TLS + * (https://github.com/Mbed-TLS/mbedtls/issues/3541). Thus, do not enable it by + * default. + */ +//#define PSA_WANT_ECC_SECP_K1_224 1 +#define PSA_WANT_ECC_SECP_K1_256 1 +#define PSA_WANT_ECC_SECP_R1_192 1 +#define PSA_WANT_ECC_SECP_R1_224 1 +#define PSA_WANT_ECC_SECP_R1_256 1 +#define PSA_WANT_ECC_SECP_R1_384 1 +#define PSA_WANT_ECC_SECP_R1_521 1 + +#define PSA_WANT_KEY_TYPE_DERIVE 1 +#define PSA_WANT_KEY_TYPE_PASSWORD 1 +#define PSA_WANT_KEY_TYPE_PASSWORD_HASH 1 +#define PSA_WANT_KEY_TYPE_HMAC 1 +#define PSA_WANT_KEY_TYPE_AES 1 +#define PSA_WANT_KEY_TYPE_ARIA 1 +#define PSA_WANT_KEY_TYPE_CAMELLIA 1 +#define PSA_WANT_KEY_TYPE_CHACHA20 1 +#define PSA_WANT_KEY_TYPE_DES 1 +#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR 1 +#define PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY 1 +#define PSA_WANT_KEY_TYPE_RAW_DATA 1 +#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR 1 +#define PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY 1 + +#endif /* PSA_CRYPTO_CONFIG_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_driver_common.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_driver_common.h new file mode 100644 index 0000000..26363c6 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_driver_common.h @@ -0,0 +1,56 @@ +/** + * \file psa/crypto_driver_common.h + * \brief Definitions for all PSA crypto drivers + * + * This file contains common definitions shared by all PSA crypto drivers. + * Do not include it directly: instead, include the header file(s) for + * the type(s) of driver that you are implementing. For example, if + * you are writing a dynamically registered driver for a secure element, + * include `psa/crypto_se_driver.h`. + * + * This file is part of the PSA Crypto Driver Model, containing functions for + * driver developers to implement to enable hardware to be called in a + * standardized way by a PSA Cryptographic API implementation. The functions + * comprising the driver model, which driver authors implement, are not + * intended to be called by application developers. + */ + +/* + * 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 PSA_CRYPTO_DRIVER_COMMON_H +#define PSA_CRYPTO_DRIVER_COMMON_H + +#include +#include + +/* Include type definitions (psa_status_t, psa_algorithm_t, + * psa_key_type_t, etc.) and macros to build and analyze values + * of these types. */ +#include "crypto_types.h" +#include "crypto_values.h" +/* Include size definitions which are used to size some arrays in operation + * structures. */ +#include + +/** For encrypt-decrypt functions, whether the operation is an encryption + * or a decryption. */ +typedef enum { + PSA_CRYPTO_DRIVER_DECRYPT, + PSA_CRYPTO_DRIVER_ENCRYPT +} psa_encrypt_or_decrypt_t; + +#endif /* PSA_CRYPTO_DRIVER_COMMON_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_driver_contexts_composites.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_driver_contexts_composites.h new file mode 100644 index 0000000..6c56a51 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_driver_contexts_composites.h @@ -0,0 +1,163 @@ +/* + * Declaration of context structures for use with the PSA driver wrapper + * interface. This file contains the context structures for 'composite' + * operations, i.e. those operations which need to make use of other operations + * from the primitives (crypto_driver_contexts_primitives.h) + * + * Warning: This file will be auto-generated in the future. + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + * + * \note This header and its content is not part of the Mbed TLS API and + * applications must not depend on it. Its main purpose is to define the + * multi-part state objects of the PSA drivers included in the cryptographic + * library. The definition of these objects are then used by crypto_struct.h + * to define the implementation-defined types of PSA multi-part state objects. + */ +/* 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 PSA_CRYPTO_DRIVER_CONTEXTS_COMPOSITES_H +#define PSA_CRYPTO_DRIVER_CONTEXTS_COMPOSITES_H + +#include "psa/crypto_driver_common.h" + +/* Include the context structure definitions for the Mbed TLS software drivers */ +#include "psa/crypto_builtin_composites.h" + +/* Include the context structure definitions for those drivers that were + * declared during the autogeneration process. */ + +#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) +#include +#endif + +#if defined(PSA_CRYPTO_DRIVER_TEST) +#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \ + defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_MAC) +typedef libtestdriver1_mbedtls_psa_mac_operation_t + mbedtls_transparent_test_driver_mac_operation_t; +typedef libtestdriver1_mbedtls_psa_mac_operation_t + mbedtls_opaque_test_driver_mac_operation_t; + +#define MBEDTLS_TRANSPARENT_TEST_DRIVER_MAC_OPERATION_INIT \ + LIBTESTDRIVER1_MBEDTLS_PSA_MAC_OPERATION_INIT +#define MBEDTLS_OPAQUE_TEST_DRIVER_MAC_OPERATION_INIT \ + LIBTESTDRIVER1_MBEDTLS_PSA_MAC_OPERATION_INIT + +#else +typedef mbedtls_psa_mac_operation_t + mbedtls_transparent_test_driver_mac_operation_t; +typedef mbedtls_psa_mac_operation_t + mbedtls_opaque_test_driver_mac_operation_t; + +#define MBEDTLS_TRANSPARENT_TEST_DRIVER_MAC_OPERATION_INIT \ + MBEDTLS_PSA_MAC_OPERATION_INIT +#define MBEDTLS_OPAQUE_TEST_DRIVER_MAC_OPERATION_INIT \ + MBEDTLS_PSA_MAC_OPERATION_INIT + +#endif /* MBEDTLS_TEST_LIBTESTDRIVER1 && LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_MAC */ + +#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \ + defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_AEAD) +typedef libtestdriver1_mbedtls_psa_aead_operation_t + mbedtls_transparent_test_driver_aead_operation_t; + +#define MBEDTLS_TRANSPARENT_TEST_DRIVER_AEAD_OPERATION_INIT \ + LIBTESTDRIVER1_MBEDTLS_PSA_AEAD_OPERATION_INIT +#else +typedef mbedtls_psa_aead_operation_t + mbedtls_transparent_test_driver_aead_operation_t; + +#define MBEDTLS_TRANSPARENT_TEST_DRIVER_AEAD_OPERATION_INIT \ + MBEDTLS_PSA_AEAD_OPERATION_INIT + +#endif /* MBEDTLS_TEST_LIBTESTDRIVER1 && LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_AEAD */ + +#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \ + defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_PAKE) + +typedef libtestdriver1_mbedtls_psa_pake_operation_t + mbedtls_transparent_test_driver_pake_operation_t; +typedef libtestdriver1_mbedtls_psa_pake_operation_t + mbedtls_opaque_test_driver_pake_operation_t; + +#define MBEDTLS_TRANSPARENT_TEST_DRIVER_PAKE_OPERATION_INIT \ + LIBTESTDRIVER1_MBEDTLS_PSA_PAKE_OPERATION_INIT +#define MBEDTLS_OPAQUE_TEST_DRIVER_PAKE_OPERATION_INIT \ + LIBTESTDRIVER1_MBEDTLS_PSA_PAKE_OPERATION_INIT + +#else +typedef mbedtls_psa_pake_operation_t + mbedtls_transparent_test_driver_pake_operation_t; +typedef mbedtls_psa_pake_operation_t + mbedtls_opaque_test_driver_pake_operation_t; + +#define MBEDTLS_TRANSPARENT_TEST_DRIVER_PAKE_OPERATION_INIT \ + MBEDTLS_PSA_PAKE_OPERATION_INIT +#define MBEDTLS_OPAQUE_TEST_DRIVER_PAKE_OPERATION_INIT \ + MBEDTLS_PSA_PAKE_OPERATION_INIT + +#endif /* MBEDTLS_TEST_LIBTESTDRIVER1 && LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_PAKE */ + +#endif /* PSA_CRYPTO_DRIVER_TEST */ + +/* Define the context to be used for an operation that is executed through the + * PSA Driver wrapper layer as the union of all possible driver's contexts. + * + * The union members are the driver's context structures, and the member names + * are formatted as `'drivername'_ctx`. This allows for procedural generation + * of both this file and the content of psa_crypto_driver_wrappers.c */ + +typedef union { + unsigned dummy; /* Make sure this union is always non-empty */ + mbedtls_psa_mac_operation_t mbedtls_ctx; +#if defined(PSA_CRYPTO_DRIVER_TEST) + mbedtls_transparent_test_driver_mac_operation_t transparent_test_driver_ctx; + mbedtls_opaque_test_driver_mac_operation_t opaque_test_driver_ctx; +#endif +} psa_driver_mac_context_t; + +typedef union { + unsigned dummy; /* Make sure this union is always non-empty */ + mbedtls_psa_aead_operation_t mbedtls_ctx; +#if defined(PSA_CRYPTO_DRIVER_TEST) + mbedtls_transparent_test_driver_aead_operation_t transparent_test_driver_ctx; +#endif +} psa_driver_aead_context_t; + +typedef union { + unsigned dummy; /* Make sure this union is always non-empty */ + mbedtls_psa_sign_hash_interruptible_operation_t mbedtls_ctx; +} psa_driver_sign_hash_interruptible_context_t; + +typedef union { + unsigned dummy; /* Make sure this union is always non-empty */ + mbedtls_psa_verify_hash_interruptible_operation_t mbedtls_ctx; +} psa_driver_verify_hash_interruptible_context_t; + +typedef union { + unsigned dummy; /* Make sure this union is always non-empty */ + mbedtls_psa_pake_operation_t mbedtls_ctx; +#if defined(PSA_CRYPTO_DRIVER_TEST) + mbedtls_transparent_test_driver_pake_operation_t transparent_test_driver_ctx; + mbedtls_opaque_test_driver_pake_operation_t opaque_test_driver_ctx; +#endif +} psa_driver_pake_context_t; + +#endif /* PSA_CRYPTO_DRIVER_CONTEXTS_COMPOSITES_H */ +/* End of automatically generated file. */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_driver_contexts_primitives.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_driver_contexts_primitives.h new file mode 100644 index 0000000..620a4b3 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_driver_contexts_primitives.h @@ -0,0 +1,117 @@ +/* + * Declaration of context structures for use with the PSA driver wrapper + * interface. This file contains the context structures for 'primitive' + * operations, i.e. those operations which do not rely on other contexts. + * + * Warning: This file will be auto-generated in the future. + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + * + * \note This header and its content is not part of the Mbed TLS API and + * applications must not depend on it. Its main purpose is to define the + * multi-part state objects of the PSA drivers included in the cryptographic + * library. The definition of these objects are then used by crypto_struct.h + * to define the implementation-defined types of PSA multi-part state objects. + */ +/* 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 PSA_CRYPTO_DRIVER_CONTEXTS_PRIMITIVES_H +#define PSA_CRYPTO_DRIVER_CONTEXTS_PRIMITIVES_H + +#include "psa/crypto_driver_common.h" + +/* Include the context structure definitions for the Mbed TLS software drivers */ +#include "psa/crypto_builtin_primitives.h" + +/* Include the context structure definitions for those drivers that were + * declared during the autogeneration process. */ + +#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) +#include +#endif + +#if defined(PSA_CRYPTO_DRIVER_TEST) + +#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \ + defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_CIPHER) +typedef libtestdriver1_mbedtls_psa_cipher_operation_t + mbedtls_transparent_test_driver_cipher_operation_t; + +#define MBEDTLS_TRANSPARENT_TEST_DRIVER_CIPHER_OPERATION_INIT \ + LIBTESTDRIVER1_MBEDTLS_PSA_CIPHER_OPERATION_INIT +#else +typedef mbedtls_psa_cipher_operation_t + mbedtls_transparent_test_driver_cipher_operation_t; + +#define MBEDTLS_TRANSPARENT_TEST_DRIVER_CIPHER_OPERATION_INIT \ + MBEDTLS_PSA_CIPHER_OPERATION_INIT +#endif /* MBEDTLS_TEST_LIBTESTDRIVER1 && + LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_CIPHER */ + +#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \ + defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_HASH) +typedef libtestdriver1_mbedtls_psa_hash_operation_t + mbedtls_transparent_test_driver_hash_operation_t; + +#define MBEDTLS_TRANSPARENT_TEST_DRIVER_HASH_OPERATION_INIT \ + LIBTESTDRIVER1_MBEDTLS_PSA_HASH_OPERATION_INIT +#else +typedef mbedtls_psa_hash_operation_t + mbedtls_transparent_test_driver_hash_operation_t; + +#define MBEDTLS_TRANSPARENT_TEST_DRIVER_HASH_OPERATION_INIT \ + MBEDTLS_PSA_HASH_OPERATION_INIT +#endif /* MBEDTLS_TEST_LIBTESTDRIVER1 && + LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_HASH */ + +typedef struct { + unsigned int initialised : 1; + mbedtls_transparent_test_driver_cipher_operation_t ctx; +} mbedtls_opaque_test_driver_cipher_operation_t; + +#define MBEDTLS_OPAQUE_TEST_DRIVER_CIPHER_OPERATION_INIT \ + { 0, MBEDTLS_TRANSPARENT_TEST_DRIVER_CIPHER_OPERATION_INIT } + +#endif /* PSA_CRYPTO_DRIVER_TEST */ + +/* Define the context to be used for an operation that is executed through the + * PSA Driver wrapper layer as the union of all possible driver's contexts. + * + * The union members are the driver's context structures, and the member names + * are formatted as `'drivername'_ctx`. This allows for procedural generation + * of both this file and the content of psa_crypto_driver_wrappers.c */ + +typedef union { + unsigned dummy; /* Make sure this union is always non-empty */ + mbedtls_psa_hash_operation_t mbedtls_ctx; +#if defined(PSA_CRYPTO_DRIVER_TEST) + mbedtls_transparent_test_driver_hash_operation_t test_driver_ctx; +#endif +} psa_driver_hash_context_t; + +typedef union { + unsigned dummy; /* Make sure this union is always non-empty */ + mbedtls_psa_cipher_operation_t mbedtls_ctx; +#if defined(PSA_CRYPTO_DRIVER_TEST) + mbedtls_transparent_test_driver_cipher_operation_t transparent_test_driver_ctx; + mbedtls_opaque_test_driver_cipher_operation_t opaque_test_driver_ctx; +#endif +} psa_driver_cipher_context_t; + +#endif /* PSA_CRYPTO_DRIVER_CONTEXTS_PRIMITIVES_H */ +/* End of automatically generated file. */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_extra.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_extra.h new file mode 100644 index 0000000..4920508 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_extra.h @@ -0,0 +1,2141 @@ +/** + * \file psa/crypto_extra.h + * + * \brief PSA cryptography module: Mbed TLS vendor extensions + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + * + * This file is reserved for vendor-specific definitions. + */ +/* + * 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 PSA_CRYPTO_EXTRA_H +#define PSA_CRYPTO_EXTRA_H +#include "mbedtls/private_access.h" + +#include "mbedtls/platform_util.h" + +#include "crypto_types.h" +#include "crypto_compat.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* UID for secure storage seed */ +#define PSA_CRYPTO_ITS_RANDOM_SEED_UID 0xFFFFFF52 + +/* See mbedtls_config.h for definition */ +#if !defined(MBEDTLS_PSA_KEY_SLOT_COUNT) +#define MBEDTLS_PSA_KEY_SLOT_COUNT 32 +#endif + +/** \addtogroup attributes + * @{ + */ + +/** \brief Declare the enrollment algorithm for a key. + * + * An operation on a key may indifferently use the algorithm set with + * psa_set_key_algorithm() or with this function. + * + * \param[out] attributes The attribute structure to write to. + * \param alg2 A second algorithm that the key may be used + * for, in addition to the algorithm set with + * psa_set_key_algorithm(). + * + * \warning Setting an enrollment algorithm is not recommended, because + * using the same key with different algorithms can allow some + * attacks based on arithmetic relations between different + * computations made with the same key, or can escalate harmless + * side channels into exploitable ones. Use this function only + * if it is necessary to support a protocol for which it has been + * verified that the usage of the key with multiple algorithms + * is safe. + */ +static inline void psa_set_key_enrollment_algorithm( + psa_key_attributes_t *attributes, + psa_algorithm_t alg2) +{ + attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(alg2) = alg2; +} + +/** Retrieve the enrollment algorithm policy from key attributes. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The enrollment algorithm stored in the attribute structure. + */ +static inline psa_algorithm_t psa_get_key_enrollment_algorithm( + const psa_key_attributes_t *attributes) +{ + return attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(alg2); +} + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + +/** Retrieve the slot number where a key is stored. + * + * A slot number is only defined for keys that are stored in a secure + * element. + * + * This information is only useful if the secure element is not entirely + * managed through the PSA Cryptography API. It is up to the secure + * element driver to decide how PSA slot numbers map to any other interface + * that the secure element may have. + * + * \param[in] attributes The key attribute structure to query. + * \param[out] slot_number On success, the slot number containing the key. + * + * \retval #PSA_SUCCESS + * The key is located in a secure element, and \p *slot_number + * indicates the slot number that contains it. + * \retval #PSA_ERROR_NOT_PERMITTED + * The caller is not permitted to query the slot number. + * Mbed Crypto currently does not return this error. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key is not located in a secure element. + */ +psa_status_t psa_get_key_slot_number( + const psa_key_attributes_t *attributes, + psa_key_slot_number_t *slot_number); + +/** Choose the slot number where a key is stored. + * + * This function declares a slot number in the specified attribute + * structure. + * + * A slot number is only meaningful for keys that are stored in a secure + * element. It is up to the secure element driver to decide how PSA slot + * numbers map to any other interface that the secure element may have. + * + * \note Setting a slot number in key attributes for a key creation can + * cause the following errors when creating the key: + * - #PSA_ERROR_NOT_SUPPORTED if the selected secure element does + * not support choosing a specific slot number. + * - #PSA_ERROR_NOT_PERMITTED if the caller is not permitted to + * choose slot numbers in general or to choose this specific slot. + * - #PSA_ERROR_INVALID_ARGUMENT if the chosen slot number is not + * valid in general or not valid for this specific key. + * - #PSA_ERROR_ALREADY_EXISTS if there is already a key in the + * selected slot. + * + * \param[out] attributes The attribute structure to write to. + * \param slot_number The slot number to set. + */ +static inline void psa_set_key_slot_number( + psa_key_attributes_t *attributes, + psa_key_slot_number_t slot_number) +{ + attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(flags) |= MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER; + attributes->MBEDTLS_PRIVATE(slot_number) = slot_number; +} + +/** Remove the slot number attribute from a key attribute structure. + * + * This function undoes the action of psa_set_key_slot_number(). + * + * \param[out] attributes The attribute structure to write to. + */ +static inline void psa_clear_key_slot_number( + psa_key_attributes_t *attributes) +{ + attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(flags) &= + ~MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER; +} + +/** Register a key that is already present in a secure element. + * + * The key must be located in a secure element designated by the + * lifetime field in \p attributes, in the slot set with + * psa_set_key_slot_number() in the attribute structure. + * This function makes the key available through the key identifier + * specified in \p attributes. + * + * \param[in] attributes The attributes of the existing key. + * + * \retval #PSA_SUCCESS + * The key was successfully registered. + * Note that depending on the design of the driver, this may or may + * not guarantee that a key actually exists in the designated slot + * and is compatible with the specified attributes. + * \retval #PSA_ERROR_ALREADY_EXISTS + * There is already a key with the identifier specified in + * \p attributes. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The secure element driver for the specified lifetime does not + * support registering a key. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The identifier in \p attributes is invalid, namely the identifier is + * not in the user range, or + * \p attributes specifies a lifetime which is not located + * in a secure element, or no slot number is specified in \p attributes, + * or the specified slot number is not valid. + * \retval #PSA_ERROR_NOT_PERMITTED + * The caller is not authorized to register the specified key slot. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t mbedtls_psa_register_se_key( + const psa_key_attributes_t *attributes); + +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + +/**@}*/ + +/** + * \brief Library deinitialization. + * + * This function clears all data associated with the PSA layer, + * including the whole key store. + * + * This is an Mbed TLS extension. + */ +void mbedtls_psa_crypto_free(void); + +/** \brief Statistics about + * resource consumption related to the PSA keystore. + * + * \note The content of this structure is not part of the stable API and ABI + * of Mbed Crypto and may change arbitrarily from version to version. + */ +typedef struct mbedtls_psa_stats_s { + /** Number of slots containing key material for a volatile key. */ + size_t MBEDTLS_PRIVATE(volatile_slots); + /** Number of slots containing key material for a key which is in + * internal persistent storage. */ + size_t MBEDTLS_PRIVATE(persistent_slots); + /** Number of slots containing a reference to a key in a + * secure element. */ + size_t MBEDTLS_PRIVATE(external_slots); + /** Number of slots which are occupied, but do not contain + * key material yet. */ + size_t MBEDTLS_PRIVATE(half_filled_slots); + /** Number of slots that contain cache data. */ + size_t MBEDTLS_PRIVATE(cache_slots); + /** Number of slots that are not used for anything. */ + size_t MBEDTLS_PRIVATE(empty_slots); + /** Number of slots that are locked. */ + size_t MBEDTLS_PRIVATE(locked_slots); + /** Largest key id value among open keys in internal persistent storage. */ + psa_key_id_t MBEDTLS_PRIVATE(max_open_internal_key_id); + /** Largest key id value among open keys in secure elements. */ + psa_key_id_t MBEDTLS_PRIVATE(max_open_external_key_id); +} mbedtls_psa_stats_t; + +/** \brief Get statistics about + * resource consumption related to the PSA keystore. + * + * \note When Mbed Crypto is built as part of a service, with isolation + * between the application and the keystore, the service may or + * may not expose this function. + */ +void mbedtls_psa_get_stats(mbedtls_psa_stats_t *stats); + +/** + * \brief Inject an initial entropy seed for the random generator into + * secure storage. + * + * This function injects data to be used as a seed for the random generator + * used by the PSA Crypto implementation. On devices that lack a trusted + * entropy source (preferably a hardware random number generator), + * the Mbed PSA Crypto implementation uses this value to seed its + * random generator. + * + * On devices without a trusted entropy source, this function must be + * called exactly once in the lifetime of the device. On devices with + * a trusted entropy source, calling this function is optional. + * In all cases, this function may only be called before calling any + * other function in the PSA Crypto API, including psa_crypto_init(). + * + * When this function returns successfully, it populates a file in + * persistent storage. Once the file has been created, this function + * can no longer succeed. + * + * If any error occurs, this function does not change the system state. + * You can call this function again after correcting the reason for the + * error if possible. + * + * \warning This function **can** fail! Callers MUST check the return status. + * + * \warning If you use this function, you should use it as part of a + * factory provisioning process. The value of the injected seed + * is critical to the security of the device. It must be + * *secret*, *unpredictable* and (statistically) *unique per device*. + * You should be generate it randomly using a cryptographically + * secure random generator seeded from trusted entropy sources. + * You should transmit it securely to the device and ensure + * that its value is not leaked or stored anywhere beyond the + * needs of transmitting it from the point of generation to + * the call of this function, and erase all copies of the value + * once this function returns. + * + * This is an Mbed TLS extension. + * + * \note This function is only available on the following platforms: + * * If the compile-time option MBEDTLS_PSA_INJECT_ENTROPY is enabled. + * Note that you must provide compatible implementations of + * mbedtls_nv_seed_read and mbedtls_nv_seed_write. + * * In a client-server integration of PSA Cryptography, on the client side, + * if the server supports this feature. + * \param[in] seed Buffer containing the seed value to inject. + * \param[in] seed_size Size of the \p seed buffer. + * The size of the seed in bytes must be greater + * or equal to both #MBEDTLS_ENTROPY_BLOCK_SIZE + * and the value of \c MBEDTLS_ENTROPY_MIN_PLATFORM + * in `library/entropy_poll.h` in the Mbed TLS source + * code. + * It must be less or equal to + * #MBEDTLS_ENTROPY_MAX_SEED_SIZE. + * + * \retval #PSA_SUCCESS + * The seed value was injected successfully. The random generator + * of the PSA Crypto implementation is now ready for use. + * You may now call psa_crypto_init() and use the PSA Crypto + * implementation. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p seed_size is out of range. + * \retval #PSA_ERROR_STORAGE_FAILURE + * There was a failure reading or writing from storage. + * \retval #PSA_ERROR_NOT_PERMITTED + * The library has already been initialized. It is no longer + * possible to call this function. + */ +psa_status_t mbedtls_psa_inject_entropy(const uint8_t *seed, + size_t seed_size); + +/** \addtogroup crypto_types + * @{ + */ + +/** DSA public key. + * + * The import and export format is the + * representation of the public key `y = g^x mod p` as a big-endian byte + * string. The length of the byte string is the length of the base prime `p` + * in bytes. + */ +#define PSA_KEY_TYPE_DSA_PUBLIC_KEY ((psa_key_type_t) 0x4002) + +/** DSA key pair (private and public key). + * + * The import and export format is the + * representation of the private key `x` as a big-endian byte string. The + * length of the byte string is the private key size in bytes (leading zeroes + * are not stripped). + * + * Deterministic DSA key derivation with psa_generate_derived_key follows + * FIPS 186-4 §B.1.2: interpret the byte string as integer + * in big-endian order. Discard it if it is not in the range + * [0, *N* - 2] where *N* is the boundary of the private key domain + * (the prime *p* for Diffie-Hellman, the subprime *q* for DSA, + * or the order of the curve's base point for ECC). + * Add 1 to the resulting integer and use this as the private key *x*. + * + */ +#define PSA_KEY_TYPE_DSA_KEY_PAIR ((psa_key_type_t) 0x7002) + +/** Whether a key type is a DSA key (pair or public-only). */ +#define PSA_KEY_TYPE_IS_DSA(type) \ + (PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) == PSA_KEY_TYPE_DSA_PUBLIC_KEY) + +#define PSA_ALG_DSA_BASE ((psa_algorithm_t) 0x06000400) +/** DSA signature with hashing. + * + * This is the signature scheme defined by FIPS 186-4, + * with a random per-message secret number (*k*). + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding DSA signature algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_DSA(hash_alg) \ + (PSA_ALG_DSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +#define PSA_ALG_DETERMINISTIC_DSA_BASE ((psa_algorithm_t) 0x06000500) +#define PSA_ALG_DSA_DETERMINISTIC_FLAG PSA_ALG_ECDSA_DETERMINISTIC_FLAG +/** Deterministic DSA signature with hashing. + * + * This is the deterministic variant defined by RFC 6979 of + * the signature scheme defined by FIPS 186-4. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding DSA signature algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_DETERMINISTIC_DSA(hash_alg) \ + (PSA_ALG_DETERMINISTIC_DSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +#define PSA_ALG_IS_DSA(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_DSA_DETERMINISTIC_FLAG) == \ + PSA_ALG_DSA_BASE) +#define PSA_ALG_DSA_IS_DETERMINISTIC(alg) \ + (((alg) & PSA_ALG_DSA_DETERMINISTIC_FLAG) != 0) +#define PSA_ALG_IS_DETERMINISTIC_DSA(alg) \ + (PSA_ALG_IS_DSA(alg) && PSA_ALG_DSA_IS_DETERMINISTIC(alg)) +#define PSA_ALG_IS_RANDOMIZED_DSA(alg) \ + (PSA_ALG_IS_DSA(alg) && !PSA_ALG_DSA_IS_DETERMINISTIC(alg)) + + +/* We need to expand the sample definition of this macro from + * the API definition. */ +#undef PSA_ALG_IS_VENDOR_HASH_AND_SIGN +#define PSA_ALG_IS_VENDOR_HASH_AND_SIGN(alg) \ + PSA_ALG_IS_DSA(alg) + +/**@}*/ + +/** \addtogroup attributes + * @{ + */ + +/** Custom Diffie-Hellman group. + * + * For keys of type #PSA_KEY_TYPE_DH_PUBLIC_KEY(#PSA_DH_FAMILY_CUSTOM) or + * #PSA_KEY_TYPE_DH_KEY_PAIR(#PSA_DH_FAMILY_CUSTOM), the group data comes + * from domain parameters set by psa_set_key_domain_parameters(). + */ +#define PSA_DH_FAMILY_CUSTOM ((psa_dh_family_t) 0x7e) + +/** PAKE operation stages. */ +#define PSA_PAKE_OPERATION_STAGE_SETUP 0 +#define PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS 1 +#define PSA_PAKE_OPERATION_STAGE_COMPUTATION 2 + +/** + * \brief Set domain parameters for a key. + * + * Some key types require additional domain parameters in addition to + * the key type identifier and the key size. Use this function instead + * of psa_set_key_type() when you need to specify domain parameters. + * + * The format for the required domain parameters varies based on the key type. + * + * - For RSA keys (#PSA_KEY_TYPE_RSA_PUBLIC_KEY or #PSA_KEY_TYPE_RSA_KEY_PAIR), + * the domain parameter data consists of the public exponent, + * represented as a big-endian integer with no leading zeros. + * This information is used when generating an RSA key pair. + * When importing a key, the public exponent is read from the imported + * key data and the exponent recorded in the attribute structure is ignored. + * As an exception, the public exponent 65537 is represented by an empty + * byte string. + * - For DSA keys (#PSA_KEY_TYPE_DSA_PUBLIC_KEY or #PSA_KEY_TYPE_DSA_KEY_PAIR), + * the `Dss-Params` format as defined by RFC 3279 §2.3.2. + * ``` + * Dss-Params ::= SEQUENCE { + * p INTEGER, + * q INTEGER, + * g INTEGER + * } + * ``` + * - For Diffie-Hellman key exchange keys + * (#PSA_KEY_TYPE_DH_PUBLIC_KEY(#PSA_DH_FAMILY_CUSTOM) or + * #PSA_KEY_TYPE_DH_KEY_PAIR(#PSA_DH_FAMILY_CUSTOM)), the + * `DomainParameters` format as defined by RFC 3279 §2.3.3. + * ``` + * DomainParameters ::= SEQUENCE { + * p INTEGER, -- odd prime, p=jq +1 + * g INTEGER, -- generator, g + * q INTEGER, -- factor of p-1 + * j INTEGER OPTIONAL, -- subgroup factor + * validationParams ValidationParams OPTIONAL + * } + * ValidationParams ::= SEQUENCE { + * seed BIT STRING, + * pgenCounter INTEGER + * } + * ``` + * + * \note This function may allocate memory or other resources. + * Once you have called this function on an attribute structure, + * you must call psa_reset_key_attributes() to free these resources. + * + * \note This is an experimental extension to the interface. It may change + * in future versions of the library. + * + * \param[in,out] attributes Attribute structure where the specified domain + * parameters will be stored. + * If this function fails, the content of + * \p attributes is not modified. + * \param type Key type (a \c PSA_KEY_TYPE_XXX value). + * \param[in] data Buffer containing the key domain parameters. + * The content of this buffer is interpreted + * according to \p type as described above. + * \param data_length Size of the \p data buffer in bytes. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + */ +psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes, + psa_key_type_t type, + const uint8_t *data, + size_t data_length); + +/** + * \brief Get domain parameters for a key. + * + * Get the domain parameters for a key with this function, if any. The format + * of the domain parameters written to \p data is specified in the + * documentation for psa_set_key_domain_parameters(). + * + * \note This is an experimental extension to the interface. It may change + * in future versions of the library. + * + * \param[in] attributes The key attribute structure to query. + * \param[out] data On success, the key domain parameters. + * \param data_size Size of the \p data buffer in bytes. + * The buffer is guaranteed to be large + * enough if its size in bytes is at least + * the value given by + * PSA_KEY_DOMAIN_PARAMETERS_SIZE(). + * \param[out] data_length On success, the number of bytes + * that make up the key domain parameters data. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_BUFFER_TOO_SMALL \emptydescription + */ +psa_status_t psa_get_key_domain_parameters( + const psa_key_attributes_t *attributes, + uint8_t *data, + size_t data_size, + size_t *data_length); + +/** Safe output buffer size for psa_get_key_domain_parameters(). + * + * This macro returns a compile-time constant if its arguments are + * compile-time constants. + * + * \warning This function may call its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \note This is an experimental extension to the interface. It may change + * in future versions of the library. + * + * \param key_type A supported key type. + * \param key_bits The size of the key in bits. + * + * \return If the parameters are valid and supported, return + * a buffer size in bytes that guarantees that + * psa_get_key_domain_parameters() will not fail with + * #PSA_ERROR_BUFFER_TOO_SMALL. + * If the parameters are a valid combination that is not supported + * by the implementation, this macro shall return either a + * sensible size or 0. + * If the parameters are not valid, the + * return value is unspecified. + */ +#define PSA_KEY_DOMAIN_PARAMETERS_SIZE(key_type, key_bits) \ + (PSA_KEY_TYPE_IS_RSA(key_type) ? sizeof(int) : \ + PSA_KEY_TYPE_IS_DH(key_type) ? PSA_DH_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) : \ + PSA_KEY_TYPE_IS_DSA(key_type) ? PSA_DSA_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) : \ + 0) +#define PSA_DH_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) \ + (4 + (PSA_BITS_TO_BYTES(key_bits) + 5) * 3 /*without optional parts*/) +#define PSA_DSA_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) \ + (4 + (PSA_BITS_TO_BYTES(key_bits) + 5) * 2 /*p, g*/ + 34 /*q*/) + +/**@}*/ + +/** \defgroup psa_tls_helpers TLS helper functions + * @{ + */ + +#if defined(MBEDTLS_ECP_C) +#include + +/** Convert an ECC curve identifier from the Mbed TLS encoding to PSA. + * + * \note This function is provided solely for the convenience of + * Mbed TLS and may be removed at any time without notice. + * + * \param grpid An Mbed TLS elliptic curve identifier + * (`MBEDTLS_ECP_DP_xxx`). + * \param[out] bits On success, the bit size of the curve. + * + * \return The corresponding PSA elliptic curve identifier + * (`PSA_ECC_FAMILY_xxx`). + * \return \c 0 on failure (\p grpid is not recognized). + */ +static inline psa_ecc_family_t mbedtls_ecc_group_to_psa(mbedtls_ecp_group_id grpid, + size_t *bits) +{ + switch (grpid) { + case MBEDTLS_ECP_DP_SECP192R1: + *bits = 192; + return PSA_ECC_FAMILY_SECP_R1; + case MBEDTLS_ECP_DP_SECP224R1: + *bits = 224; + return PSA_ECC_FAMILY_SECP_R1; + case MBEDTLS_ECP_DP_SECP256R1: + *bits = 256; + return PSA_ECC_FAMILY_SECP_R1; + case MBEDTLS_ECP_DP_SECP384R1: + *bits = 384; + return PSA_ECC_FAMILY_SECP_R1; + case MBEDTLS_ECP_DP_SECP521R1: + *bits = 521; + return PSA_ECC_FAMILY_SECP_R1; + case MBEDTLS_ECP_DP_BP256R1: + *bits = 256; + return PSA_ECC_FAMILY_BRAINPOOL_P_R1; + case MBEDTLS_ECP_DP_BP384R1: + *bits = 384; + return PSA_ECC_FAMILY_BRAINPOOL_P_R1; + case MBEDTLS_ECP_DP_BP512R1: + *bits = 512; + return PSA_ECC_FAMILY_BRAINPOOL_P_R1; + case MBEDTLS_ECP_DP_CURVE25519: + *bits = 255; + return PSA_ECC_FAMILY_MONTGOMERY; + case MBEDTLS_ECP_DP_SECP192K1: + *bits = 192; + return PSA_ECC_FAMILY_SECP_K1; + case MBEDTLS_ECP_DP_SECP224K1: + *bits = 224; + return PSA_ECC_FAMILY_SECP_K1; + case MBEDTLS_ECP_DP_SECP256K1: + *bits = 256; + return PSA_ECC_FAMILY_SECP_K1; + case MBEDTLS_ECP_DP_CURVE448: + *bits = 448; + return PSA_ECC_FAMILY_MONTGOMERY; + default: + *bits = 0; + return 0; + } +} + +/** Convert an ECC curve identifier from the PSA encoding to Mbed TLS. + * + * \note This function is provided solely for the convenience of + * Mbed TLS and may be removed at any time without notice. + * + * \param curve A PSA elliptic curve identifier + * (`PSA_ECC_FAMILY_xxx`). + * \param bits The bit-length of a private key on \p curve. + * \param bits_is_sloppy If true, \p bits may be the bit-length rounded up + * to the nearest multiple of 8. This allows the caller + * to infer the exact curve from the length of a key + * which is supplied as a byte string. + * + * \return The corresponding Mbed TLS elliptic curve identifier + * (`MBEDTLS_ECP_DP_xxx`). + * \return #MBEDTLS_ECP_DP_NONE if \c curve is not recognized. + * \return #MBEDTLS_ECP_DP_NONE if \p bits is not + * correct for \p curve. + */ +mbedtls_ecp_group_id mbedtls_ecc_group_of_psa(psa_ecc_family_t curve, + size_t bits, + int bits_is_sloppy); +#endif /* MBEDTLS_ECP_C */ + +/**@}*/ + +/** \defgroup psa_external_rng External random generator + * @{ + */ + +#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) +/** External random generator function, implemented by the platform. + * + * When the compile-time option #MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG is enabled, + * this function replaces Mbed TLS's entropy and DRBG modules for all + * random generation triggered via PSA crypto interfaces. + * + * \note This random generator must deliver random numbers with cryptographic + * quality and high performance. It must supply unpredictable numbers + * with a uniform distribution. The implementation of this function + * is responsible for ensuring that the random generator is seeded + * with sufficient entropy. If you have a hardware TRNG which is slow + * or delivers non-uniform output, declare it as an entropy source + * with mbedtls_entropy_add_source() instead of enabling this option. + * + * \param[in,out] context Pointer to the random generator context. + * This is all-bits-zero on the first call + * and preserved between successive calls. + * \param[out] output Output buffer. On success, this buffer + * contains random data with a uniform + * distribution. + * \param output_size The size of the \p output buffer in bytes. + * \param[out] output_length On success, set this value to \p output_size. + * + * \retval #PSA_SUCCESS + * Success. The output buffer contains \p output_size bytes of + * cryptographic-quality random data, and \c *output_length is + * set to \p output_size. + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + * The random generator requires extra entropy and there is no + * way to obtain entropy under current environment conditions. + * This error should not happen under normal circumstances since + * this function is responsible for obtaining as much entropy as + * it needs. However implementations of this function may return + * #PSA_ERROR_INSUFFICIENT_ENTROPY if there is no way to obtain + * entropy without blocking indefinitely. + * \retval #PSA_ERROR_HARDWARE_FAILURE + * A failure of the random generator hardware that isn't covered + * by #PSA_ERROR_INSUFFICIENT_ENTROPY. + */ +psa_status_t mbedtls_psa_external_get_random( + mbedtls_psa_external_random_context_t *context, + uint8_t *output, size_t output_size, size_t *output_length); +#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ + +/**@}*/ + +/** \defgroup psa_builtin_keys Built-in keys + * @{ + */ + +/** The minimum value for a key identifier that is built into the + * implementation. + * + * The range of key identifiers from #MBEDTLS_PSA_KEY_ID_BUILTIN_MIN + * to #MBEDTLS_PSA_KEY_ID_BUILTIN_MAX within the range from + * #PSA_KEY_ID_VENDOR_MIN and #PSA_KEY_ID_VENDOR_MAX and must not intersect + * with any other set of implementation-chosen key identifiers. + * + * This value is part of the library's ABI since changing it would invalidate + * the values of built-in key identifiers in applications. + */ +#define MBEDTLS_PSA_KEY_ID_BUILTIN_MIN ((psa_key_id_t) 0x7fff0000) + +/** The maximum value for a key identifier that is built into the + * implementation. + * + * See #MBEDTLS_PSA_KEY_ID_BUILTIN_MIN for more information. + */ +#define MBEDTLS_PSA_KEY_ID_BUILTIN_MAX ((psa_key_id_t) 0x7fffefff) + +/** A slot number identifying a key in a driver. + * + * Values of this type are used to identify built-in keys. + */ +typedef uint64_t psa_drv_slot_number_t; + +#if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS) +/** Test whether a key identifier belongs to the builtin key range. + * + * \param key_id Key identifier to test. + * + * \retval 1 + * The key identifier is a builtin key identifier. + * \retval 0 + * The key identifier is not a builtin key identifier. + */ +static inline int psa_key_id_is_builtin(psa_key_id_t key_id) +{ + return (key_id >= MBEDTLS_PSA_KEY_ID_BUILTIN_MIN) && + (key_id <= MBEDTLS_PSA_KEY_ID_BUILTIN_MAX); +} + +/** Platform function to obtain the location and slot number of a built-in key. + * + * An application-specific implementation of this function must be provided if + * #MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS is enabled. This would typically be provided + * as part of a platform's system image. + * + * #MBEDTLS_SVC_KEY_ID_GET_KEY_ID(\p key_id) needs to be in the range from + * #MBEDTLS_PSA_KEY_ID_BUILTIN_MIN to #MBEDTLS_PSA_KEY_ID_BUILTIN_MAX. + * + * In a multi-application configuration + * (\c MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER is defined), + * this function should check that #MBEDTLS_SVC_KEY_ID_GET_OWNER_ID(\p key_id) + * is allowed to use the given key. + * + * \param key_id The key ID for which to retrieve the + * location and slot attributes. + * \param[out] lifetime On success, the lifetime associated with the key + * corresponding to \p key_id. Lifetime is a + * combination of which driver contains the key, + * and with what persistence level the key is + * intended to be used. If the platform + * implementation does not contain specific + * information about the intended key persistence + * level, the persistence level may be reported as + * #PSA_KEY_PERSISTENCE_DEFAULT. + * \param[out] slot_number On success, the slot number known to the driver + * registered at the lifetime location reported + * through \p lifetime which corresponds to the + * requested built-in key. + * + * \retval #PSA_SUCCESS + * The requested key identifier designates a built-in key. + * In a multi-application configuration, the requested owner + * is allowed to access it. + * \retval #PSA_ERROR_DOES_NOT_EXIST + * The requested key identifier is not a built-in key which is known + * to this function. If a key exists in the key storage with this + * identifier, the data from the storage will be used. + * \return (any other error) + * Any other error is propagated to the function that requested the key. + * Common errors include: + * - #PSA_ERROR_NOT_PERMITTED: the key exists but the requested owner + * is not allowed to access it. + */ +psa_status_t mbedtls_psa_platform_get_builtin_key( + mbedtls_svc_key_id_t key_id, + psa_key_lifetime_t *lifetime, + psa_drv_slot_number_t *slot_number); +#endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ + +/** @} */ + +/** \addtogroup crypto_types + * @{ + */ + +#define PSA_ALG_CATEGORY_PAKE ((psa_algorithm_t) 0x0a000000) + +/** Whether the specified algorithm is a password-authenticated key exchange. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a password-authenticated key exchange (PAKE) + * algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_PAKE(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_PAKE) + +/** The Password-authenticated key exchange by juggling (J-PAKE) algorithm. + * + * This is J-PAKE as defined by RFC 8236, instantiated with the following + * parameters: + * + * - The group can be either an elliptic curve or defined over a finite field. + * - Schnorr NIZK proof as defined by RFC 8235 and using the same group as the + * J-PAKE algorithm. + * - A cryptographic hash function. + * + * To select these parameters and set up the cipher suite, call these functions + * in any order: + * + * \code + * psa_pake_cs_set_algorithm(cipher_suite, PSA_ALG_JPAKE); + * psa_pake_cs_set_primitive(cipher_suite, + * PSA_PAKE_PRIMITIVE(type, family, bits)); + * psa_pake_cs_set_hash(cipher_suite, hash); + * \endcode + * + * For more information on how to set a specific curve or field, refer to the + * documentation of the individual \c PSA_PAKE_PRIMITIVE_TYPE_XXX constants. + * + * After initializing a J-PAKE operation, call + * + * \code + * psa_pake_setup(operation, cipher_suite); + * psa_pake_set_user(operation, ...); + * psa_pake_set_peer(operation, ...); + * psa_pake_set_password_key(operation, ...); + * \endcode + * + * The password is provided as a key. This can be the password text itself, + * in an agreed character encoding, or some value derived from the password + * as required by a higher level protocol. + * + * (The implementation converts the key material to a number as described in + * Section 2.3.8 of _SEC 1: Elliptic Curve Cryptography_ + * (https://www.secg.org/sec1-v2.pdf), before reducing it modulo \c q. Here + * \c q is order of the group defined by the primitive set in the cipher suite. + * The \c psa_pake_set_password_key() function returns an error if the result + * of the reduction is 0.) + * + * The key exchange flow for J-PAKE is as follows: + * -# To get the first round data that needs to be sent to the peer, call + * \code + * // Get g1 + * psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); + * // Get the ZKP public key for x1 + * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); + * // Get the ZKP proof for x1 + * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); + * // Get g2 + * psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); + * // Get the ZKP public key for x2 + * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); + * // Get the ZKP proof for x2 + * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); + * \endcode + * -# To provide the first round data received from the peer to the operation, + * call + * \code + * // Set g3 + * psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); + * // Set the ZKP public key for x3 + * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); + * // Set the ZKP proof for x3 + * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); + * // Set g4 + * psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); + * // Set the ZKP public key for x4 + * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); + * // Set the ZKP proof for x4 + * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); + * \endcode + * -# To get the second round data that needs to be sent to the peer, call + * \code + * // Get A + * psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); + * // Get ZKP public key for x2*s + * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); + * // Get ZKP proof for x2*s + * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); + * \endcode + * -# To provide the second round data received from the peer to the operation, + * call + * \code + * // Set B + * psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); + * // Set ZKP public key for x4*s + * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); + * // Set ZKP proof for x4*s + * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); + * \endcode + * -# To access the shared secret call + * \code + * // Get Ka=Kb=K + * psa_pake_get_implicit_key() + * \endcode + * + * For more information consult the documentation of the individual + * \c PSA_PAKE_STEP_XXX constants. + * + * At this point there is a cryptographic guarantee that only the authenticated + * party who used the same password is able to compute the key. But there is no + * guarantee that the peer is the party it claims to be and was able to do so. + * + * That is, the authentication is only implicit (the peer is not authenticated + * at this point, and no action should be taken that assume that they are - like + * for example accessing restricted files). + * + * To make the authentication explicit there are various methods, see Section 5 + * of RFC 8236 for two examples. + * + */ +#define PSA_ALG_JPAKE ((psa_algorithm_t) 0x0a000100) + +/** @} */ + +/** \defgroup pake Password-authenticated key exchange (PAKE) + * + * This is a proposed PAKE interface for the PSA Crypto API. It is not part of + * the official PSA Crypto API yet. + * + * \note The content of this section is not part of the stable API and ABI + * of Mbed Crypto and may change arbitrarily from version to version. + * Same holds for the corresponding macros #PSA_ALG_CATEGORY_PAKE and + * #PSA_ALG_JPAKE. + * @{ + */ + +/** \brief Encoding of the application role of PAKE + * + * Encodes the application's role in the algorithm is being executed. For more + * information see the documentation of individual \c PSA_PAKE_ROLE_XXX + * constants. + */ +typedef uint8_t psa_pake_role_t; + +/** Encoding of input and output indicators for PAKE. + * + * Some PAKE algorithms need to exchange more data than just a single key share. + * This type is for encoding additional input and output data for such + * algorithms. + */ +typedef uint8_t psa_pake_step_t; + +/** Encoding of the type of the PAKE's primitive. + * + * Values defined by this standard will never be in the range 0x80-0xff. + * Vendors who define additional types must use an encoding in this range. + * + * For more information see the documentation of individual + * \c PSA_PAKE_PRIMITIVE_TYPE_XXX constants. + */ +typedef uint8_t psa_pake_primitive_type_t; + +/** \brief Encoding of the family of the primitive associated with the PAKE. + * + * For more information see the documentation of individual + * \c PSA_PAKE_PRIMITIVE_TYPE_XXX constants. + */ +typedef uint8_t psa_pake_family_t; + +/** \brief Encoding of the primitive associated with the PAKE. + * + * For more information see the documentation of the #PSA_PAKE_PRIMITIVE macro. + */ +typedef uint32_t psa_pake_primitive_t; + +/** A value to indicate no role in a PAKE algorithm. + * This value can be used in a call to psa_pake_set_role() for symmetric PAKE + * algorithms which do not assign roles. + */ +#define PSA_PAKE_ROLE_NONE ((psa_pake_role_t) 0x00) + +/** The first peer in a balanced PAKE. + * + * Although balanced PAKE algorithms are symmetric, some of them needs an + * ordering of peers for the transcript calculations. If the algorithm does not + * need this, both #PSA_PAKE_ROLE_FIRST and #PSA_PAKE_ROLE_SECOND are + * accepted. + */ +#define PSA_PAKE_ROLE_FIRST ((psa_pake_role_t) 0x01) + +/** The second peer in a balanced PAKE. + * + * Although balanced PAKE algorithms are symmetric, some of them needs an + * ordering of peers for the transcript calculations. If the algorithm does not + * need this, either #PSA_PAKE_ROLE_FIRST or #PSA_PAKE_ROLE_SECOND are + * accepted. + */ +#define PSA_PAKE_ROLE_SECOND ((psa_pake_role_t) 0x02) + +/** The client in an augmented PAKE. + * + * Augmented PAKE algorithms need to differentiate between client and server. + */ +#define PSA_PAKE_ROLE_CLIENT ((psa_pake_role_t) 0x11) + +/** The server in an augmented PAKE. + * + * Augmented PAKE algorithms need to differentiate between client and server. + */ +#define PSA_PAKE_ROLE_SERVER ((psa_pake_role_t) 0x12) + +/** The PAKE primitive type indicating the use of elliptic curves. + * + * The values of the \c family and \c bits fields of the cipher suite identify a + * specific elliptic curve, using the same mapping that is used for ECC + * (::psa_ecc_family_t) keys. + * + * (Here \c family means the value returned by psa_pake_cs_get_family() and + * \c bits means the value returned by psa_pake_cs_get_bits().) + * + * Input and output during the operation can involve group elements and scalar + * values: + * -# The format for group elements is the same as for public keys on the + * specific curve would be. For more information, consult the documentation of + * psa_export_public_key(). + * -# The format for scalars is the same as for private keys on the specific + * curve would be. For more information, consult the documentation of + * psa_export_key(). + */ +#define PSA_PAKE_PRIMITIVE_TYPE_ECC ((psa_pake_primitive_type_t) 0x01) + +/** The PAKE primitive type indicating the use of Diffie-Hellman groups. + * + * The values of the \c family and \c bits fields of the cipher suite identify + * a specific Diffie-Hellman group, using the same mapping that is used for + * Diffie-Hellman (::psa_dh_family_t) keys. + * + * (Here \c family means the value returned by psa_pake_cs_get_family() and + * \c bits means the value returned by psa_pake_cs_get_bits().) + * + * Input and output during the operation can involve group elements and scalar + * values: + * -# The format for group elements is the same as for public keys on the + * specific group would be. For more information, consult the documentation of + * psa_export_public_key(). + * -# The format for scalars is the same as for private keys on the specific + * group would be. For more information, consult the documentation of + * psa_export_key(). + */ +#define PSA_PAKE_PRIMITIVE_TYPE_DH ((psa_pake_primitive_type_t) 0x02) + +/** Construct a PAKE primitive from type, family and bit-size. + * + * \param pake_type The type of the primitive + * (value of type ::psa_pake_primitive_type_t). + * \param pake_family The family of the primitive + * (the type and interpretation of this parameter depends + * on \p type, for more information consult the + * documentation of individual ::psa_pake_primitive_type_t + * constants). + * \param pake_bits The bit-size of the primitive + * (Value of type \c size_t. The interpretation + * of this parameter depends on \p family, for more + * information consult the documentation of individual + * ::psa_pake_primitive_type_t constants). + * + * \return The constructed primitive value of type ::psa_pake_primitive_t. + * Return 0 if the requested primitive can't be encoded as + * ::psa_pake_primitive_t. + */ +#define PSA_PAKE_PRIMITIVE(pake_type, pake_family, pake_bits) \ + ((pake_bits & 0xFFFF) != pake_bits) ? 0 : \ + ((psa_pake_primitive_t) (((pake_type) << 24 | \ + (pake_family) << 16) | (pake_bits))) + +/** The key share being sent to or received from the peer. + * + * The format for both input and output at this step is the same as for public + * keys on the group determined by the primitive (::psa_pake_primitive_t) would + * be. + * + * For more information on the format, consult the documentation of + * psa_export_public_key(). + * + * For information regarding how the group is determined, consult the + * documentation #PSA_PAKE_PRIMITIVE. + */ +#define PSA_PAKE_STEP_KEY_SHARE ((psa_pake_step_t) 0x01) + +/** A Schnorr NIZKP public key. + * + * This is the ephemeral public key in the Schnorr Non-Interactive + * Zero-Knowledge Proof (the value denoted by the letter 'V' in RFC 8235). + * + * The format for both input and output at this step is the same as for public + * keys on the group determined by the primitive (::psa_pake_primitive_t) would + * be. + * + * For more information on the format, consult the documentation of + * psa_export_public_key(). + * + * For information regarding how the group is determined, consult the + * documentation #PSA_PAKE_PRIMITIVE. + */ +#define PSA_PAKE_STEP_ZK_PUBLIC ((psa_pake_step_t) 0x02) + +/** A Schnorr NIZKP proof. + * + * This is the proof in the Schnorr Non-Interactive Zero-Knowledge Proof (the + * value denoted by the letter 'r' in RFC 8235). + * + * Both for input and output, the value at this step is an integer less than + * the order of the group selected in the cipher suite. The format depends on + * the group as well: + * + * - For Montgomery curves, the encoding is little endian. + * - For everything else the encoding is big endian (see Section 2.3.8 of + * _SEC 1: Elliptic Curve Cryptography_ at https://www.secg.org/sec1-v2.pdf). + * + * In both cases leading zeroes are allowed as long as the length in bytes does + * not exceed the byte length of the group order. + * + * For information regarding how the group is determined, consult the + * documentation #PSA_PAKE_PRIMITIVE. + */ +#define PSA_PAKE_STEP_ZK_PROOF ((psa_pake_step_t) 0x03) + +/** The type of the data structure for PAKE cipher suites. + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure. + * Implementation details can change in future versions without notice. + */ +typedef struct psa_pake_cipher_suite_s psa_pake_cipher_suite_t; + +/** Return an initial value for a PAKE cipher suite object. + */ +static psa_pake_cipher_suite_t psa_pake_cipher_suite_init(void); + +/** Retrieve the PAKE algorithm from a PAKE cipher suite. + * + * \param[in] cipher_suite The cipher suite structure to query. + * + * \return The PAKE algorithm stored in the cipher suite structure. + */ +static psa_algorithm_t psa_pake_cs_get_algorithm( + const psa_pake_cipher_suite_t *cipher_suite); + +/** Declare the PAKE algorithm for the cipher suite. + * + * This function overwrites any PAKE algorithm + * previously set in \p cipher_suite. + * + * \param[out] cipher_suite The cipher suite structure to write to. + * \param algorithm The PAKE algorithm to write. + * (`PSA_ALG_XXX` values of type ::psa_algorithm_t + * such that #PSA_ALG_IS_PAKE(\c alg) is true.) + * If this is 0, the PAKE algorithm in + * \p cipher_suite becomes unspecified. + */ +static void psa_pake_cs_set_algorithm(psa_pake_cipher_suite_t *cipher_suite, + psa_algorithm_t algorithm); + +/** Retrieve the primitive from a PAKE cipher suite. + * + * \param[in] cipher_suite The cipher suite structure to query. + * + * \return The primitive stored in the cipher suite structure. + */ +static psa_pake_primitive_t psa_pake_cs_get_primitive( + const psa_pake_cipher_suite_t *cipher_suite); + +/** Declare the primitive for a PAKE cipher suite. + * + * This function overwrites any primitive previously set in \p cipher_suite. + * + * \param[out] cipher_suite The cipher suite structure to write to. + * \param primitive The primitive to write. If this is 0, the + * primitive type in \p cipher_suite becomes + * unspecified. + */ +static void psa_pake_cs_set_primitive(psa_pake_cipher_suite_t *cipher_suite, + psa_pake_primitive_t primitive); + +/** Retrieve the PAKE family from a PAKE cipher suite. + * + * \param[in] cipher_suite The cipher suite structure to query. + * + * \return The PAKE family stored in the cipher suite structure. + */ +static psa_pake_family_t psa_pake_cs_get_family( + const psa_pake_cipher_suite_t *cipher_suite); + +/** Retrieve the PAKE primitive bit-size from a PAKE cipher suite. + * + * \param[in] cipher_suite The cipher suite structure to query. + * + * \return The PAKE primitive bit-size stored in the cipher suite structure. + */ +static uint16_t psa_pake_cs_get_bits( + const psa_pake_cipher_suite_t *cipher_suite); + +/** Retrieve the hash algorithm from a PAKE cipher suite. + * + * \param[in] cipher_suite The cipher suite structure to query. + * + * \return The hash algorithm stored in the cipher suite structure. The return + * value is 0 if the PAKE is not parametrised by a hash algorithm or if + * the hash algorithm is not set. + */ +static psa_algorithm_t psa_pake_cs_get_hash( + const psa_pake_cipher_suite_t *cipher_suite); + +/** Declare the hash algorithm for a PAKE cipher suite. + * + * This function overwrites any hash algorithm + * previously set in \p cipher_suite. + * + * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` + * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) + * for more information. + * + * \param[out] cipher_suite The cipher suite structure to write to. + * \param hash The hash involved in the cipher suite. + * (`PSA_ALG_XXX` values of type ::psa_algorithm_t + * such that #PSA_ALG_IS_HASH(\c alg) is true.) + * If this is 0, the hash algorithm in + * \p cipher_suite becomes unspecified. + */ +static void psa_pake_cs_set_hash(psa_pake_cipher_suite_t *cipher_suite, + psa_algorithm_t hash); + +/** The type of the state data structure for PAKE operations. + * + * Before calling any function on a PAKE operation object, the application + * must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_pake_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_pake_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_PAKE_OPERATION_INIT, + * for example: + * \code + * psa_pake_operation_t operation = PSA_PAKE_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_pake_operation_init() + * to the structure, for example: + * \code + * psa_pake_operation_t operation; + * operation = psa_pake_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure. + * Implementation details can change in future versions without notice. */ +typedef struct psa_pake_operation_s psa_pake_operation_t; + +/** The type of input values for PAKE operations. */ +typedef struct psa_crypto_driver_pake_inputs_s psa_crypto_driver_pake_inputs_t; + +/** The type of computation stage for J-PAKE operations. */ +typedef struct psa_jpake_computation_stage_s psa_jpake_computation_stage_t; + +/** Return an initial value for a PAKE operation object. + */ +static psa_pake_operation_t psa_pake_operation_init(void); + +/** Get the length of the password in bytes from given inputs. + * + * \param[in] inputs Operation inputs. + * \param[out] password_len Password length. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * Password hasn't been set yet. + */ +psa_status_t psa_crypto_driver_pake_get_password_len( + const psa_crypto_driver_pake_inputs_t *inputs, + size_t *password_len); + +/** Get the password from given inputs. + * + * \param[in] inputs Operation inputs. + * \param[out] buffer Return buffer for password. + * \param buffer_size Size of the return buffer in bytes. + * \param[out] buffer_length Actual size of the password in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * Password hasn't been set yet. + */ +psa_status_t psa_crypto_driver_pake_get_password( + const psa_crypto_driver_pake_inputs_t *inputs, + uint8_t *buffer, size_t buffer_size, size_t *buffer_length); + +/** Get the role from given inputs. + * + * \param[in] inputs Operation inputs. + * \param[out] role Return buffer for role. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * Role hasn't been set yet. + */ +psa_status_t psa_crypto_driver_pake_get_role( + const psa_crypto_driver_pake_inputs_t *inputs, + psa_pake_role_t *role); + +/** Get the length of the user id in bytes from given inputs. + * + * \param[in] inputs Operation inputs. + * \param[out] user_len User id length. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * User id hasn't been set yet. + */ +psa_status_t psa_crypto_driver_pake_get_user_len( + const psa_crypto_driver_pake_inputs_t *inputs, + size_t *user_len); + +/** Get the length of the peer id in bytes from given inputs. + * + * \param[in] inputs Operation inputs. + * \param[out] peer_len Peer id length. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * Peer id hasn't been set yet. + */ +psa_status_t psa_crypto_driver_pake_get_peer_len( + const psa_crypto_driver_pake_inputs_t *inputs, + size_t *peer_len); + +/** Get the user id from given inputs. + * + * \param[in] inputs Operation inputs. + * \param[out] user_id User id. + * \param user_id_size Size of \p user_id in bytes. + * \param[out] user_id_len Size of the user id in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * User id hasn't been set yet. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p user_id is too small. + */ +psa_status_t psa_crypto_driver_pake_get_user( + const psa_crypto_driver_pake_inputs_t *inputs, + uint8_t *user_id, size_t user_id_size, size_t *user_id_len); + +/** Get the peer id from given inputs. + * + * \param[in] inputs Operation inputs. + * \param[out] peer_id Peer id. + * \param peer_id_size Size of \p peer_id in bytes. + * \param[out] peer_id_length Size of the peer id in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * Peer id hasn't been set yet. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p peer_id is too small. + */ +psa_status_t psa_crypto_driver_pake_get_peer( + const psa_crypto_driver_pake_inputs_t *inputs, + uint8_t *peer_id, size_t peer_id_size, size_t *peer_id_length); + +/** Get the cipher suite from given inputs. + * + * \param[in] inputs Operation inputs. + * \param[out] cipher_suite Return buffer for role. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * Cipher_suite hasn't been set yet. + */ +psa_status_t psa_crypto_driver_pake_get_cipher_suite( + const psa_crypto_driver_pake_inputs_t *inputs, + psa_pake_cipher_suite_t *cipher_suite); + +/** Set the session information for a password-authenticated key exchange. + * + * The sequence of operations to set up a password-authenticated key exchange + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_pake_operation_t, e.g. + * #PSA_PAKE_OPERATION_INIT. + * -# Call psa_pake_setup() to specify the cipher suite. + * -# Call \c psa_pake_set_xxx() functions on the operation to complete the + * setup. The exact sequence of \c psa_pake_set_xxx() functions that needs + * to be called depends on the algorithm in use. + * + * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` + * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) + * for more information. + * + * A typical sequence of calls to perform a password-authenticated key + * exchange: + * -# Call psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...) to get the + * key share that needs to be sent to the peer. + * -# Call psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...) to provide + * the key share that was received from the peer. + * -# Depending on the algorithm additional calls to psa_pake_output() and + * psa_pake_input() might be necessary. + * -# Call psa_pake_get_implicit_key() for accessing the shared secret. + * + * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` + * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) + * for more information. + * + * If an error occurs at any step after a call to psa_pake_setup(), + * the operation will need to be reset by a call to psa_pake_abort(). The + * application may call psa_pake_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_pake_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A call to psa_pake_abort(). + * - A successful call to psa_pake_get_implicit_key(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized but not set up yet. + * \param[in] cipher_suite The cipher suite to use. (A cipher suite fully + * characterizes a PAKE algorithm and determines + * the algorithm as well.) + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The algorithm in \p cipher_suite is not a PAKE algorithm, or the + * PAKE primitive in \p cipher_suite is not compatible with the + * PAKE algorithm, or the hash algorithm in \p cipher_suite is invalid + * or not compatible with the PAKE algorithm and primitive. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The algorithm in \p cipher_suite is not a supported PAKE algorithm, + * or the PAKE primitive in \p cipher_suite is not supported or not + * compatible with the PAKE algorithm, or the hash algorithm in + * \p cipher_suite is not supported or not compatible with the PAKE + * algorithm and primitive. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid, or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_pake_setup(psa_pake_operation_t *operation, + const psa_pake_cipher_suite_t *cipher_suite); + +/** Set the password for a password-authenticated key exchange from key ID. + * + * Call this function when the password, or a value derived from the password, + * is already present in the key store. + * + * \param[in,out] operation The operation object to set the password for. It + * must have been set up by psa_pake_setup() and + * not yet in use (neither psa_pake_output() nor + * psa_pake_input() has been called yet). It must + * be on operation for which the password hasn't + * been set yet (psa_pake_set_password_key() + * hasn't been called yet). + * \param password Identifier of the key holding the password or a + * value derived from the password (eg. by a + * memory-hard function). It must remain valid + * until the operation terminates. It must be of + * type #PSA_KEY_TYPE_PASSWORD or + * #PSA_KEY_TYPE_PASSWORD_HASH. It has to allow + * the usage #PSA_KEY_USAGE_DERIVE. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \p password is not a valid key identifier. + * \retval #PSA_ERROR_NOT_PERMITTED + * The key does not have the #PSA_KEY_USAGE_DERIVE flag, or it does not + * permit the \p operation's algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key type for \p password is not #PSA_KEY_TYPE_PASSWORD or + * #PSA_KEY_TYPE_PASSWORD_HASH, or \p password is not compatible with + * the \p operation's cipher suite. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The key type or key size of \p password is not supported with the + * \p operation's cipher suite. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must have been set up.), or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_pake_set_password_key(psa_pake_operation_t *operation, + mbedtls_svc_key_id_t password); + +/** Set the user ID for a password-authenticated key exchange. + * + * Call this function to set the user ID. For PAKE algorithms that associate a + * user identifier with each side of the session you need to call + * psa_pake_set_peer() as well. For PAKE algorithms that associate a single + * user identifier with the session, call psa_pake_set_user() only. + * + * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` + * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) + * for more information. + * + * \param[in,out] operation The operation object to set the user ID for. It + * must have been set up by psa_pake_setup() and + * not yet in use (neither psa_pake_output() nor + * psa_pake_input() has been called yet). It must + * be on operation for which the user ID hasn't + * been set (psa_pake_set_user() hasn't been + * called yet). + * \param[in] user_id The user ID to authenticate with. + * (temporary limitation: "client" or "server" only) + * \param user_id_len Size of the \p user_id buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p user_id is not valid for the \p operation's algorithm and cipher + * suite. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The value of \p user_id is not supported by the implementation. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid, or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_pake_set_user(psa_pake_operation_t *operation, + const uint8_t *user_id, + size_t user_id_len); + +/** Set the peer ID for a password-authenticated key exchange. + * + * Call this function in addition to psa_pake_set_user() for PAKE algorithms + * that associate a user identifier with each side of the session. For PAKE + * algorithms that associate a single user identifier with the session, call + * psa_pake_set_user() only. + * + * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` + * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) + * for more information. + * + * \param[in,out] operation The operation object to set the peer ID for. It + * must have been set up by psa_pake_setup() and + * not yet in use (neither psa_pake_output() nor + * psa_pake_input() has been called yet). It must + * be on operation for which the peer ID hasn't + * been set (psa_pake_set_peer() hasn't been + * called yet). + * \param[in] peer_id The peer's ID to authenticate. + * (temporary limitation: "client" or "server" only) + * \param peer_id_len Size of the \p peer_id buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p user_id is not valid for the \p operation's algorithm and cipher + * suite. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The algorithm doesn't associate a second identity with the session. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * Calling psa_pake_set_peer() is invalid with the \p operation's + * algorithm, the operation state is not valid, or the library has not + * been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_pake_set_peer(psa_pake_operation_t *operation, + const uint8_t *peer_id, + size_t peer_id_len); + +/** Set the application role for a password-authenticated key exchange. + * + * Not all PAKE algorithms need to differentiate the communicating entities. + * It is optional to call this function for PAKEs that don't require a role + * to be specified. For such PAKEs the application role parameter is ignored, + * or #PSA_PAKE_ROLE_NONE can be passed as \c role. + * + * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` + * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) + * for more information. + * + * \param[in,out] operation The operation object to specify the + * application's role for. It must have been set up + * by psa_pake_setup() and not yet in use (neither + * psa_pake_output() nor psa_pake_input() has been + * called yet). It must be on operation for which + * the application's role hasn't been specified + * (psa_pake_set_role() hasn't been called yet). + * \param role A value of type ::psa_pake_role_t indicating the + * application's role in the PAKE the algorithm + * that is being set up. For more information see + * the documentation of \c PSA_PAKE_ROLE_XXX + * constants. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The \p role is not a valid PAKE role in the \p operation’s algorithm. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The \p role for this algorithm is not supported or is not valid. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid, or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_pake_set_role(psa_pake_operation_t *operation, + psa_pake_role_t role); + +/** Get output for a step of a password-authenticated key exchange. + * + * Depending on the algorithm being executed, you might need to call this + * function several times or you might not need to call this at all. + * + * The exact sequence of calls to perform a password-authenticated key + * exchange depends on the algorithm in use. Refer to the documentation of + * individual PAKE algorithm types (`PSA_ALG_XXX` values of type + * ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) for more + * information. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_pake_abort(). + * + * \param[in,out] operation Active PAKE operation. + * \param step The step of the algorithm for which the output is + * requested. + * \param[out] output Buffer where the output is to be written in the + * format appropriate for this \p step. Refer to + * the documentation of the individual + * \c PSA_PAKE_STEP_XXX constants for more + * information. + * \param output_size Size of the \p output buffer in bytes. This must + * be at least #PSA_PAKE_OUTPUT_SIZE(\p alg, \p + * primitive, \p step) where \p alg and + * \p primitive are the PAKE algorithm and primitive + * in the operation's cipher suite, and \p step is + * the output step. + * + * \param[out] output_length On success, the number of bytes of the returned + * output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p step is not compatible with the operation's algorithm. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p step is not supported with the operation's algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, and fully set + * up, and this call must conform to the algorithm's requirements + * for ordering of input and output steps), or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_pake_output(psa_pake_operation_t *operation, + psa_pake_step_t step, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** Provide input for a step of a password-authenticated key exchange. + * + * Depending on the algorithm being executed, you might need to call this + * function several times or you might not need to call this at all. + * + * The exact sequence of calls to perform a password-authenticated key + * exchange depends on the algorithm in use. Refer to the documentation of + * individual PAKE algorithm types (`PSA_ALG_XXX` values of type + * ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) for more + * information. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_pake_abort(). + * + * \param[in,out] operation Active PAKE operation. + * \param step The step for which the input is provided. + * \param[in] input Buffer containing the input in the format + * appropriate for this \p step. Refer to the + * documentation of the individual + * \c PSA_PAKE_STEP_XXX constants for more + * information. + * \param input_length Size of the \p input buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The verification fails for a #PSA_PAKE_STEP_ZK_PROOF input step. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p is not compatible with the \p operation’s algorithm, or the + * \p input is not valid for the \p operation's algorithm, cipher suite + * or \p step. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p step p is not supported with the \p operation's algorithm, or the + * \p input is not supported for the \p operation's algorithm, cipher + * suite or \p step. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, and fully set + * up, and this call must conform to the algorithm's requirements + * for ordering of input and output steps), or + * the library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_pake_input(psa_pake_operation_t *operation, + psa_pake_step_t step, + const uint8_t *input, + size_t input_length); + +/** Get implicitly confirmed shared secret from a PAKE. + * + * At this point there is a cryptographic guarantee that only the authenticated + * party who used the same password is able to compute the key. But there is no + * guarantee that the peer is the party it claims to be and was able to do so. + * + * That is, the authentication is only implicit. Since the peer is not + * authenticated yet, no action should be taken yet that assumes that the peer + * is who it claims to be. For example, do not access restricted files on the + * peer's behalf until an explicit authentication has succeeded. + * + * This function can be called after the key exchange phase of the operation + * has completed. It imports the shared secret output of the PAKE into the + * provided derivation operation. The input step + * #PSA_KEY_DERIVATION_INPUT_SECRET is used when placing the shared key + * material in the key derivation operation. + * + * The exact sequence of calls to perform a password-authenticated key + * exchange depends on the algorithm in use. Refer to the documentation of + * individual PAKE algorithm types (`PSA_ALG_XXX` values of type + * ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) for more + * information. + * + * When this function returns successfully, \p operation becomes inactive. + * If this function returns an error status, both \p operation + * and \p key_derivation operations enter an error state and must be aborted by + * calling psa_pake_abort() and psa_key_derivation_abort() respectively. + * + * \param[in,out] operation Active PAKE operation. + * \param[out] output A key derivation operation that is ready + * for an input step of type + * #PSA_KEY_DERIVATION_INPUT_SECRET. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * #PSA_KEY_DERIVATION_INPUT_SECRET is not compatible with the + * algorithm in the \p output key derivation operation. + * \retval #PSA_ERROR_NOT_SUPPORTED + * Input from a PAKE is not supported by the algorithm in the \p output + * key derivation operation. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The PAKE operation state is not valid (it must be active, but beyond + * that validity is specific to the algorithm), or + * the library has not been previously initialized by psa_crypto_init(), + * or the state of \p output is not valid for + * the #PSA_KEY_DERIVATION_INPUT_SECRET step. This can happen if the + * step is out of order or the application has done this step already + * and it may not be repeated. + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_pake_get_implicit_key(psa_pake_operation_t *operation, + psa_key_derivation_operation_t *output); + +/** Abort a PAKE operation. + * + * Aborting an operation frees all associated resources except for the \c + * operation structure itself. Once aborted, the operation object can be reused + * for another operation by calling psa_pake_setup() again. + * + * This function may be called at any time after the operation + * object has been initialized as described in #psa_pake_operation_t. + * + * In particular, calling psa_pake_abort() after the operation has been + * terminated by a call to psa_pake_abort() or psa_pake_get_implicit_key() + * is safe and has no effect. + * + * \param[in,out] operation The operation to abort. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_pake_abort(psa_pake_operation_t *operation); + +/**@}*/ + +/** A sufficient output buffer size for psa_pake_output(). + * + * If the size of the output buffer is at least this large, it is guaranteed + * that psa_pake_output() will not fail due to an insufficient output buffer + * size. The actual size of the output might be smaller in any given call. + * + * See also #PSA_PAKE_OUTPUT_MAX_SIZE + * + * \param alg A PAKE algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_PAKE(\p alg) is true). + * \param primitive A primitive of type ::psa_pake_primitive_t that is + * compatible with algorithm \p alg. + * \param output_step A value of type ::psa_pake_step_t that is valid for the + * algorithm \p alg. + * \return A sufficient output buffer size for the specified + * PAKE algorithm, primitive, and output step. If the + * PAKE algorithm, primitive, or output step is not + * recognized, or the parameters are incompatible, + * return 0. + */ +#define PSA_PAKE_OUTPUT_SIZE(alg, primitive, output_step) \ + (alg == PSA_ALG_JPAKE && \ + primitive == PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, \ + PSA_ECC_FAMILY_SECP_R1, 256) ? \ + ( \ + output_step == PSA_PAKE_STEP_KEY_SHARE ? 65 : \ + output_step == PSA_PAKE_STEP_ZK_PUBLIC ? 65 : \ + 32 \ + ) : \ + 0) + +/** A sufficient input buffer size for psa_pake_input(). + * + * The value returned by this macro is guaranteed to be large enough for any + * valid input to psa_pake_input() in an operation with the specified + * parameters. + * + * See also #PSA_PAKE_INPUT_MAX_SIZE + * + * \param alg A PAKE algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_PAKE(\p alg) is true). + * \param primitive A primitive of type ::psa_pake_primitive_t that is + * compatible with algorithm \p alg. + * \param input_step A value of type ::psa_pake_step_t that is valid for the + * algorithm \p alg. + * \return A sufficient input buffer size for the specified + * input, cipher suite and algorithm. If the cipher suite, + * the input type or PAKE algorithm is not recognized, or + * the parameters are incompatible, return 0. + */ +#define PSA_PAKE_INPUT_SIZE(alg, primitive, input_step) \ + (alg == PSA_ALG_JPAKE && \ + primitive == PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, \ + PSA_ECC_FAMILY_SECP_R1, 256) ? \ + ( \ + input_step == PSA_PAKE_STEP_KEY_SHARE ? 65 : \ + input_step == PSA_PAKE_STEP_ZK_PUBLIC ? 65 : \ + 32 \ + ) : \ + 0) + +/** Output buffer size for psa_pake_output() for any of the supported PAKE + * algorithm and primitive suites and output step. + * + * This macro must expand to a compile-time constant integer. + * + * See also #PSA_PAKE_OUTPUT_SIZE(\p alg, \p primitive, \p step). + */ +#define PSA_PAKE_OUTPUT_MAX_SIZE 65 + +/** Input buffer size for psa_pake_input() for any of the supported PAKE + * algorithm and primitive suites and input step. + * + * This macro must expand to a compile-time constant integer. + * + * See also #PSA_PAKE_INPUT_SIZE(\p alg, \p primitive, \p step). + */ +#define PSA_PAKE_INPUT_MAX_SIZE 65 + +/** Returns a suitable initializer for a PAKE cipher suite object of type + * psa_pake_cipher_suite_t. + */ +#define PSA_PAKE_CIPHER_SUITE_INIT { PSA_ALG_NONE, 0, 0, 0, PSA_ALG_NONE } + +/** Returns a suitable initializer for a PAKE operation object of type + * psa_pake_operation_t. + */ +#define PSA_PAKE_OPERATION_INIT { 0, PSA_ALG_NONE, PSA_PAKE_OPERATION_STAGE_SETUP, \ + { 0 }, { { 0 } } } + +struct psa_pake_cipher_suite_s { + psa_algorithm_t algorithm; + psa_pake_primitive_type_t type; + psa_pake_family_t family; + uint16_t bits; + psa_algorithm_t hash; +}; + +static inline psa_algorithm_t psa_pake_cs_get_algorithm( + const psa_pake_cipher_suite_t *cipher_suite) +{ + return cipher_suite->algorithm; +} + +static inline void psa_pake_cs_set_algorithm( + psa_pake_cipher_suite_t *cipher_suite, + psa_algorithm_t algorithm) +{ + if (!PSA_ALG_IS_PAKE(algorithm)) { + cipher_suite->algorithm = 0; + } else { + cipher_suite->algorithm = algorithm; + } +} + +static inline psa_pake_primitive_t psa_pake_cs_get_primitive( + const psa_pake_cipher_suite_t *cipher_suite) +{ + return PSA_PAKE_PRIMITIVE(cipher_suite->type, cipher_suite->family, + cipher_suite->bits); +} + +static inline void psa_pake_cs_set_primitive( + psa_pake_cipher_suite_t *cipher_suite, + psa_pake_primitive_t primitive) +{ + cipher_suite->type = (psa_pake_primitive_type_t) (primitive >> 24); + cipher_suite->family = (psa_pake_family_t) (0xFF & (primitive >> 16)); + cipher_suite->bits = (uint16_t) (0xFFFF & primitive); +} + +static inline psa_pake_family_t psa_pake_cs_get_family( + const psa_pake_cipher_suite_t *cipher_suite) +{ + return cipher_suite->family; +} + +static inline uint16_t psa_pake_cs_get_bits( + const psa_pake_cipher_suite_t *cipher_suite) +{ + return cipher_suite->bits; +} + +static inline psa_algorithm_t psa_pake_cs_get_hash( + const psa_pake_cipher_suite_t *cipher_suite) +{ + return cipher_suite->hash; +} + +static inline void psa_pake_cs_set_hash(psa_pake_cipher_suite_t *cipher_suite, + psa_algorithm_t hash) +{ + if (!PSA_ALG_IS_HASH(hash)) { + cipher_suite->hash = 0; + } else { + cipher_suite->hash = hash; + } +} + +struct psa_crypto_driver_pake_inputs_s { + uint8_t *MBEDTLS_PRIVATE(password); + size_t MBEDTLS_PRIVATE(password_len); + psa_pake_role_t MBEDTLS_PRIVATE(role); + uint8_t *MBEDTLS_PRIVATE(user); + size_t MBEDTLS_PRIVATE(user_len); + uint8_t *MBEDTLS_PRIVATE(peer); + size_t MBEDTLS_PRIVATE(peer_len); + psa_key_attributes_t MBEDTLS_PRIVATE(attributes); + psa_pake_cipher_suite_t MBEDTLS_PRIVATE(cipher_suite); +}; + +typedef enum psa_jpake_step { + PSA_PAKE_STEP_INVALID = 0, + PSA_PAKE_STEP_X1_X2 = 1, + PSA_PAKE_STEP_X2S = 2, + PSA_PAKE_STEP_DERIVE = 3, +} psa_jpake_step_t; + +typedef enum psa_jpake_state { + PSA_PAKE_STATE_INVALID = 0, + PSA_PAKE_STATE_SETUP = 1, + PSA_PAKE_STATE_READY = 2, + PSA_PAKE_OUTPUT_X1_X2 = 3, + PSA_PAKE_OUTPUT_X2S = 4, + PSA_PAKE_INPUT_X1_X2 = 5, + PSA_PAKE_INPUT_X4S = 6, +} psa_jpake_state_t; + +typedef enum psa_jpake_sequence { + PSA_PAKE_SEQ_INVALID = 0, + PSA_PAKE_X1_STEP_KEY_SHARE = 1, /* also X2S & X4S KEY_SHARE */ + PSA_PAKE_X1_STEP_ZK_PUBLIC = 2, /* also X2S & X4S ZK_PUBLIC */ + PSA_PAKE_X1_STEP_ZK_PROOF = 3, /* also X2S & X4S ZK_PROOF */ + PSA_PAKE_X2_STEP_KEY_SHARE = 4, + PSA_PAKE_X2_STEP_ZK_PUBLIC = 5, + PSA_PAKE_X2_STEP_ZK_PROOF = 6, + PSA_PAKE_SEQ_END = 7, +} psa_jpake_sequence_t; + +typedef enum psa_crypto_driver_pake_step { + PSA_JPAKE_STEP_INVALID = 0, /* Invalid step */ + PSA_JPAKE_X1_STEP_KEY_SHARE = 1, /* Round 1: input/output key share (for ephemeral private key X1).*/ + PSA_JPAKE_X1_STEP_ZK_PUBLIC = 2, /* Round 1: input/output Schnorr NIZKP public key for the X1 key */ + PSA_JPAKE_X1_STEP_ZK_PROOF = 3, /* Round 1: input/output Schnorr NIZKP proof for the X1 key */ + PSA_JPAKE_X2_STEP_KEY_SHARE = 4, /* Round 1: input/output key share (for ephemeral private key X2).*/ + PSA_JPAKE_X2_STEP_ZK_PUBLIC = 5, /* Round 1: input/output Schnorr NIZKP public key for the X2 key */ + PSA_JPAKE_X2_STEP_ZK_PROOF = 6, /* Round 1: input/output Schnorr NIZKP proof for the X2 key */ + PSA_JPAKE_X2S_STEP_KEY_SHARE = 7, /* Round 2: output X2S key (our key) */ + PSA_JPAKE_X2S_STEP_ZK_PUBLIC = 8, /* Round 2: output Schnorr NIZKP public key for the X2S key (our key) */ + PSA_JPAKE_X2S_STEP_ZK_PROOF = 9, /* Round 2: output Schnorr NIZKP proof for the X2S key (our key) */ + PSA_JPAKE_X4S_STEP_KEY_SHARE = 10, /* Round 2: input X4S key (from peer) */ + PSA_JPAKE_X4S_STEP_ZK_PUBLIC = 11, /* Round 2: input Schnorr NIZKP public key for the X4S key (from peer) */ + PSA_JPAKE_X4S_STEP_ZK_PROOF = 12 /* Round 2: input Schnorr NIZKP proof for the X4S key (from peer) */ +} psa_crypto_driver_pake_step_t; + + +struct psa_jpake_computation_stage_s { + psa_jpake_state_t MBEDTLS_PRIVATE(state); + psa_jpake_sequence_t MBEDTLS_PRIVATE(sequence); + psa_jpake_step_t MBEDTLS_PRIVATE(input_step); + psa_jpake_step_t MBEDTLS_PRIVATE(output_step); +}; + +struct psa_pake_operation_s { + /** Unique ID indicating which driver got assigned to do the + * operation. Since driver contexts are driver-specific, swapping + * drivers halfway through the operation is not supported. + * ID values are auto-generated in psa_crypto_driver_wrappers.h + * ID value zero means the context is not valid or not assigned to + * any driver (i.e. none of the driver contexts are active). */ + unsigned int MBEDTLS_PRIVATE(id); + /* Algorithm of the PAKE operation */ + psa_algorithm_t MBEDTLS_PRIVATE(alg); + /* Stage of the PAKE operation: waiting for the setup, collecting inputs + * or computing. */ + uint8_t MBEDTLS_PRIVATE(stage); + /* Holds computation stage of the PAKE algorithms. */ + union { + uint8_t MBEDTLS_PRIVATE(dummy); +#if defined(PSA_WANT_ALG_JPAKE) + psa_jpake_computation_stage_t MBEDTLS_PRIVATE(jpake); +#endif + } MBEDTLS_PRIVATE(computation_stage); + union { + psa_driver_pake_context_t MBEDTLS_PRIVATE(ctx); + psa_crypto_driver_pake_inputs_t MBEDTLS_PRIVATE(inputs); + } MBEDTLS_PRIVATE(data); +}; + +static inline struct psa_pake_cipher_suite_s psa_pake_cipher_suite_init(void) +{ + const struct psa_pake_cipher_suite_s v = PSA_PAKE_CIPHER_SUITE_INIT; + return v; +} + +static inline struct psa_pake_operation_s psa_pake_operation_init(void) +{ + const struct psa_pake_operation_s v = PSA_PAKE_OPERATION_INIT; + return v; +} + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_EXTRA_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_platform.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_platform.h new file mode 100644 index 0000000..e8d241b --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_platform.h @@ -0,0 +1,103 @@ +/** + * \file psa/crypto_platform.h + * + * \brief PSA cryptography module: Mbed TLS platform definitions + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + * + * This file contains platform-dependent type definitions. + * + * In implementations with isolation between the application and the + * cryptography module, implementers should take care to ensure that + * the definitions that are exposed to applications match what the + * module implements. + */ +/* + * 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 PSA_CRYPTO_PLATFORM_H +#define PSA_CRYPTO_PLATFORM_H +#include "mbedtls/private_access.h" + +/* Include the Mbed TLS configuration file, the way Mbed TLS does it + * in each of its header files. */ +#include "mbedtls/build_info.h" + +/* Translate between classic MBEDTLS_xxx feature symbols and PSA_xxx + * feature symbols. */ +#include "mbedtls/config_psa.h" + +/* PSA requires several types which C99 provides in stdint.h. */ +#include + +#if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) + +/* Building for the PSA Crypto service on a PSA platform, a key owner is a PSA + * partition identifier. + * + * The function psa_its_identifier_of_slot() in psa_crypto_storage.c that + * translates a key identifier to a key storage file name assumes that + * mbedtls_key_owner_id_t is a 32-bit integer. This function thus needs + * reworking if mbedtls_key_owner_id_t is not defined as a 32-bit integer + * here anymore. + */ +typedef int32_t mbedtls_key_owner_id_t; + +/** Compare two key owner identifiers. + * + * \param id1 First key owner identifier. + * \param id2 Second key owner identifier. + * + * \return Non-zero if the two key owner identifiers are equal, zero otherwise. + */ +static inline int mbedtls_key_owner_id_equal(mbedtls_key_owner_id_t id1, + mbedtls_key_owner_id_t id2) +{ + return id1 == id2; +} + +#endif /* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */ + +/* + * When MBEDTLS_PSA_CRYPTO_SPM is defined, the code is being built for SPM + * (Secure Partition Manager) integration which separates the code into two + * parts: NSPE (Non-Secure Processing Environment) and SPE (Secure Processing + * Environment). When building for the SPE, an additional header file should be + * included. + */ +#if defined(MBEDTLS_PSA_CRYPTO_SPM) +#define PSA_CRYPTO_SECURE 1 +#include "crypto_spe.h" +#endif // MBEDTLS_PSA_CRYPTO_SPM + +#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) +/** The type of the context passed to mbedtls_psa_external_get_random(). + * + * Mbed TLS initializes the context to all-bits-zero before calling + * mbedtls_psa_external_get_random() for the first time. + * + * The definition of this type in the Mbed TLS source code is for + * demonstration purposes. Implementers of mbedtls_psa_external_get_random() + * are expected to replace it with a custom definition. + */ +typedef struct { + uintptr_t MBEDTLS_PRIVATE(opaque)[2]; +} mbedtls_psa_external_random_context_t; +#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ + +#endif /* PSA_CRYPTO_PLATFORM_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_se_driver.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_se_driver.h new file mode 100644 index 0000000..9ae631f --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_se_driver.h @@ -0,0 +1,1395 @@ +/** + * \file psa/crypto_se_driver.h + * \brief PSA external cryptoprocessor driver module + * + * This header declares types and function signatures for cryptography + * drivers that access key material via opaque references. + * This is meant for cryptoprocessors that have a separate key storage from the + * space in which the PSA Crypto implementation runs, typically secure + * elements (SEs). + * + * This file is part of the PSA Crypto Driver HAL (hardware abstraction layer), + * containing functions for driver developers to implement to enable hardware + * to be called in a standardized way by a PSA Cryptography API + * implementation. The functions comprising the driver HAL, which driver + * authors implement, are not intended to be called by application developers. + */ + +/* + * 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 PSA_CRYPTO_SE_DRIVER_H +#define PSA_CRYPTO_SE_DRIVER_H +#include "mbedtls/private_access.h" + +#include "crypto_driver_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup se_init Secure element driver initialization + */ +/**@{*/ + +/** \brief Driver context structure + * + * Driver functions receive a pointer to this structure. + * Each registered driver has one instance of this structure. + * + * Implementations must include the fields specified here and + * may include other fields. + */ +typedef struct { + /** A read-only pointer to the driver's persistent data. + * + * Drivers typically use this persistent data to keep track of + * which slot numbers are available. This is only a guideline: + * drivers may use the persistent data for any purpose, keeping + * in mind the restrictions on when the persistent data is saved + * to storage: the persistent data is only saved after calling + * certain functions that receive a writable pointer to the + * persistent data. + * + * The core allocates a memory buffer for the persistent data. + * The pointer is guaranteed to be suitably aligned for any data type, + * like a pointer returned by `malloc` (but the core can use any + * method to allocate the buffer, not necessarily `malloc`). + * + * The size of this buffer is in the \c persistent_data_size field of + * this structure. + * + * Before the driver is initialized for the first time, the content of + * the persistent data is all-bits-zero. After a driver upgrade, if the + * size of the persistent data has increased, the original data is padded + * on the right with zeros; if the size has decreased, the original data + * is truncated to the new size. + * + * This pointer is to read-only data. Only a few driver functions are + * allowed to modify the persistent data. These functions receive a + * writable pointer. These functions are: + * - psa_drv_se_t::p_init + * - psa_drv_se_key_management_t::p_allocate + * - psa_drv_se_key_management_t::p_destroy + * + * The PSA Cryptography core saves the persistent data from one + * session to the next. It does this before returning from API functions + * that call a driver method that is allowed to modify the persistent + * data, specifically: + * - psa_crypto_init() causes a call to psa_drv_se_t::p_init, and may call + * psa_drv_se_key_management_t::p_destroy to complete an action + * that was interrupted by a power failure. + * - Key creation functions cause a call to + * psa_drv_se_key_management_t::p_allocate, and may cause a call to + * psa_drv_se_key_management_t::p_destroy in case an error occurs. + * - psa_destroy_key() causes a call to + * psa_drv_se_key_management_t::p_destroy. + */ + const void *const MBEDTLS_PRIVATE(persistent_data); + + /** The size of \c persistent_data in bytes. + * + * This is always equal to the value of the `persistent_data_size` field + * of the ::psa_drv_se_t structure when the driver is registered. + */ + const size_t MBEDTLS_PRIVATE(persistent_data_size); + + /** Driver transient data. + * + * The core initializes this value to 0 and does not read or modify it + * afterwards. The driver may store whatever it wants in this field. + */ + uintptr_t MBEDTLS_PRIVATE(transient_data); +} psa_drv_se_context_t; + +/** \brief A driver initialization function. + * + * \param[in,out] drv_context The driver context structure. + * \param[in,out] persistent_data A pointer to the persistent data + * that allows writing. + * \param location The location value for which this driver + * is registered. The driver will be invoked + * for all keys whose lifetime is in this + * location. + * + * \retval #PSA_SUCCESS + * The driver is operational. + * The core will update the persistent data in storage. + * \return + * Any other return value prevents the driver from being used in + * this session. + * The core will NOT update the persistent data in storage. + */ +typedef psa_status_t (*psa_drv_se_init_t)(psa_drv_se_context_t *drv_context, + void *persistent_data, + psa_key_location_t location); + +#if defined(__DOXYGEN_ONLY__) || !defined(MBEDTLS_PSA_CRYPTO_SE_C) +/* Mbed Crypto with secure element support enabled defines this type in + * crypto_types.h because it is also visible to applications through an + * implementation-specific extension. + * For the PSA Cryptography specification, this type is only visible + * via crypto_se_driver.h. */ +/** An internal designation of a key slot between the core part of the + * PSA Crypto implementation and the driver. The meaning of this value + * is driver-dependent. */ +typedef uint64_t psa_key_slot_number_t; +#endif /* __DOXYGEN_ONLY__ || !MBEDTLS_PSA_CRYPTO_SE_C */ + +/**@}*/ + +/** \defgroup se_mac Secure Element Message Authentication Codes + * Generation and authentication of Message Authentication Codes (MACs) using + * a secure element can be done either as a single function call (via the + * `psa_drv_se_mac_generate_t` or `psa_drv_se_mac_verify_t` functions), or in + * parts using the following sequence: + * - `psa_drv_se_mac_setup_t` + * - `psa_drv_se_mac_update_t` + * - `psa_drv_se_mac_update_t` + * - ... + * - `psa_drv_se_mac_finish_t` or `psa_drv_se_mac_finish_verify_t` + * + * If a previously started secure element MAC operation needs to be terminated, + * it should be done so by the `psa_drv_se_mac_abort_t`. Failure to do so may + * result in allocated resources not being freed or in other undefined + * behavior. + */ +/**@{*/ +/** \brief A function that starts a secure element MAC operation for a PSA + * Crypto Driver implementation + * + * \param[in,out] drv_context The driver context structure. + * \param[in,out] op_context A structure that will contain the + * hardware-specific MAC context + * \param[in] key_slot The slot of the key to be used for the + * operation + * \param[in] algorithm The algorithm to be used to underly the MAC + * operation + * + * \retval #PSA_SUCCESS + * Success. + */ +typedef psa_status_t (*psa_drv_se_mac_setup_t)(psa_drv_se_context_t *drv_context, + void *op_context, + psa_key_slot_number_t key_slot, + psa_algorithm_t algorithm); + +/** \brief A function that continues a previously started secure element MAC + * operation + * + * \param[in,out] op_context A hardware-specific structure for the + * previously-established MAC operation to be + * updated + * \param[in] p_input A buffer containing the message to be appended + * to the MAC operation + * \param[in] input_length The size in bytes of the input message buffer + */ +typedef psa_status_t (*psa_drv_se_mac_update_t)(void *op_context, + const uint8_t *p_input, + size_t input_length); + +/** \brief a function that completes a previously started secure element MAC + * operation by returning the resulting MAC. + * + * \param[in,out] op_context A hardware-specific structure for the + * previously started MAC operation to be + * finished + * \param[out] p_mac A buffer where the generated MAC will be + * placed + * \param[in] mac_size The size in bytes of the buffer that has been + * allocated for the `output` buffer + * \param[out] p_mac_length After completion, will contain the number of + * bytes placed in the `p_mac` buffer + * + * \retval #PSA_SUCCESS + * Success. + */ +typedef psa_status_t (*psa_drv_se_mac_finish_t)(void *op_context, + uint8_t *p_mac, + size_t mac_size, + size_t *p_mac_length); + +/** \brief A function that completes a previously started secure element MAC + * operation by comparing the resulting MAC against a provided value + * + * \param[in,out] op_context A hardware-specific structure for the previously + * started MAC operation to be finished + * \param[in] p_mac The MAC value against which the resulting MAC + * will be compared against + * \param[in] mac_length The size in bytes of the value stored in `p_mac` + * + * \retval #PSA_SUCCESS + * The operation completed successfully and the MACs matched each + * other + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The operation completed successfully, but the calculated MAC did + * not match the provided MAC + */ +typedef psa_status_t (*psa_drv_se_mac_finish_verify_t)(void *op_context, + const uint8_t *p_mac, + size_t mac_length); + +/** \brief A function that aborts a previous started secure element MAC + * operation + * + * \param[in,out] op_context A hardware-specific structure for the previously + * started MAC operation to be aborted + */ +typedef psa_status_t (*psa_drv_se_mac_abort_t)(void *op_context); + +/** \brief A function that performs a secure element MAC operation in one + * command and returns the calculated MAC + * + * \param[in,out] drv_context The driver context structure. + * \param[in] p_input A buffer containing the message to be MACed + * \param[in] input_length The size in bytes of `p_input` + * \param[in] key_slot The slot of the key to be used + * \param[in] alg The algorithm to be used to underlie the MAC + * operation + * \param[out] p_mac A buffer where the generated MAC will be + * placed + * \param[in] mac_size The size in bytes of the `p_mac` buffer + * \param[out] p_mac_length After completion, will contain the number of + * bytes placed in the `output` buffer + * + * \retval #PSA_SUCCESS + * Success. + */ +typedef psa_status_t (*psa_drv_se_mac_generate_t)(psa_drv_se_context_t *drv_context, + const uint8_t *p_input, + size_t input_length, + psa_key_slot_number_t key_slot, + psa_algorithm_t alg, + uint8_t *p_mac, + size_t mac_size, + size_t *p_mac_length); + +/** \brief A function that performs a secure element MAC operation in one + * command and compares the resulting MAC against a provided value + * + * \param[in,out] drv_context The driver context structure. + * \param[in] p_input A buffer containing the message to be MACed + * \param[in] input_length The size in bytes of `input` + * \param[in] key_slot The slot of the key to be used + * \param[in] alg The algorithm to be used to underlie the MAC + * operation + * \param[in] p_mac The MAC value against which the resulting MAC will + * be compared against + * \param[in] mac_length The size in bytes of `mac` + * + * \retval #PSA_SUCCESS + * The operation completed successfully and the MACs matched each + * other + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The operation completed successfully, but the calculated MAC did + * not match the provided MAC + */ +typedef psa_status_t (*psa_drv_se_mac_verify_t)(psa_drv_se_context_t *drv_context, + const uint8_t *p_input, + size_t input_length, + psa_key_slot_number_t key_slot, + psa_algorithm_t alg, + const uint8_t *p_mac, + size_t mac_length); + +/** \brief A struct containing all of the function pointers needed to + * perform secure element MAC operations + * + * PSA Crypto API implementations should populate the table as appropriate + * upon startup. + * + * If one of the functions is not implemented (such as + * `psa_drv_se_mac_generate_t`), it should be set to NULL. + * + * Driver implementers should ensure that they implement all of the functions + * that make sense for their hardware, and that they provide a full solution + * (for example, if they support `p_setup`, they should also support + * `p_update` and at least one of `p_finish` or `p_finish_verify`). + * + */ +typedef struct { + /**The size in bytes of the hardware-specific secure element MAC context + * structure + */ + size_t MBEDTLS_PRIVATE(context_size); + /** Function that performs a MAC setup operation + */ + psa_drv_se_mac_setup_t MBEDTLS_PRIVATE(p_setup); + /** Function that performs a MAC update operation + */ + psa_drv_se_mac_update_t MBEDTLS_PRIVATE(p_update); + /** Function that completes a MAC operation + */ + psa_drv_se_mac_finish_t MBEDTLS_PRIVATE(p_finish); + /** Function that completes a MAC operation with a verify check + */ + psa_drv_se_mac_finish_verify_t MBEDTLS_PRIVATE(p_finish_verify); + /** Function that aborts a previously started MAC operation + */ + psa_drv_se_mac_abort_t MBEDTLS_PRIVATE(p_abort); + /** Function that performs a MAC operation in one call + */ + psa_drv_se_mac_generate_t MBEDTLS_PRIVATE(p_mac); + /** Function that performs a MAC and verify operation in one call + */ + psa_drv_se_mac_verify_t MBEDTLS_PRIVATE(p_mac_verify); +} psa_drv_se_mac_t; +/**@}*/ + +/** \defgroup se_cipher Secure Element Symmetric Ciphers + * + * Encryption and Decryption using secure element keys in block modes other + * than ECB must be done in multiple parts, using the following flow: + * - `psa_drv_se_cipher_setup_t` + * - `psa_drv_se_cipher_set_iv_t` (optional depending upon block mode) + * - `psa_drv_se_cipher_update_t` + * - `psa_drv_se_cipher_update_t` + * - ... + * - `psa_drv_se_cipher_finish_t` + * + * If a previously started secure element Cipher operation needs to be + * terminated, it should be done so by the `psa_drv_se_cipher_abort_t`. Failure + * to do so may result in allocated resources not being freed or in other + * undefined behavior. + * + * In situations where a PSA Cryptographic API implementation is using a block + * mode not-supported by the underlying hardware or driver, it can construct + * the block mode itself, while calling the `psa_drv_se_cipher_ecb_t` function + * for the cipher operations. + */ +/**@{*/ + +/** \brief A function that provides the cipher setup function for a + * secure element driver + * + * \param[in,out] drv_context The driver context structure. + * \param[in,out] op_context A structure that will contain the + * hardware-specific cipher context. + * \param[in] key_slot The slot of the key to be used for the + * operation + * \param[in] algorithm The algorithm to be used in the cipher + * operation + * \param[in] direction Indicates whether the operation is an encrypt + * or decrypt + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + */ +typedef psa_status_t (*psa_drv_se_cipher_setup_t)(psa_drv_se_context_t *drv_context, + void *op_context, + psa_key_slot_number_t key_slot, + psa_algorithm_t algorithm, + psa_encrypt_or_decrypt_t direction); + +/** \brief A function that sets the initialization vector (if + * necessary) for a secure element cipher operation + * + * Rationale: The `psa_se_cipher_*` operation in the PSA Cryptographic API has + * two IV functions: one to set the IV, and one to generate it internally. The + * generate function is not necessary for the drivers to implement as the PSA + * Crypto implementation can do the generation using its RNG features. + * + * \param[in,out] op_context A structure that contains the previously set up + * hardware-specific cipher context + * \param[in] p_iv A buffer containing the initialization vector + * \param[in] iv_length The size (in bytes) of the `p_iv` buffer + * + * \retval #PSA_SUCCESS \emptydescription + */ +typedef psa_status_t (*psa_drv_se_cipher_set_iv_t)(void *op_context, + const uint8_t *p_iv, + size_t iv_length); + +/** \brief A function that continues a previously started secure element cipher + * operation + * + * \param[in,out] op_context A hardware-specific structure for the + * previously started cipher operation + * \param[in] p_input A buffer containing the data to be + * encrypted/decrypted + * \param[in] input_size The size in bytes of the buffer pointed to + * by `p_input` + * \param[out] p_output The caller-allocated buffer where the + * output will be placed + * \param[in] output_size The allocated size in bytes of the + * `p_output` buffer + * \param[out] p_output_length After completion, will contain the number + * of bytes placed in the `p_output` buffer + * + * \retval #PSA_SUCCESS \emptydescription + */ +typedef psa_status_t (*psa_drv_se_cipher_update_t)(void *op_context, + const uint8_t *p_input, + size_t input_size, + uint8_t *p_output, + size_t output_size, + size_t *p_output_length); + +/** \brief A function that completes a previously started secure element cipher + * operation + * + * \param[in,out] op_context A hardware-specific structure for the + * previously started cipher operation + * \param[out] p_output The caller-allocated buffer where the output + * will be placed + * \param[in] output_size The allocated size in bytes of the `p_output` + * buffer + * \param[out] p_output_length After completion, will contain the number of + * bytes placed in the `p_output` buffer + * + * \retval #PSA_SUCCESS \emptydescription + */ +typedef psa_status_t (*psa_drv_se_cipher_finish_t)(void *op_context, + uint8_t *p_output, + size_t output_size, + size_t *p_output_length); + +/** \brief A function that aborts a previously started secure element cipher + * operation + * + * \param[in,out] op_context A hardware-specific structure for the + * previously started cipher operation + */ +typedef psa_status_t (*psa_drv_se_cipher_abort_t)(void *op_context); + +/** \brief A function that performs the ECB block mode for secure element + * cipher operations + * + * Note: this function should only be used with implementations that do not + * provide a needed higher-level operation. + * + * \param[in,out] drv_context The driver context structure. + * \param[in] key_slot The slot of the key to be used for the operation + * \param[in] algorithm The algorithm to be used in the cipher operation + * \param[in] direction Indicates whether the operation is an encrypt or + * decrypt + * \param[in] p_input A buffer containing the data to be + * encrypted/decrypted + * \param[in] input_size The size in bytes of the buffer pointed to by + * `p_input` + * \param[out] p_output The caller-allocated buffer where the output + * will be placed + * \param[in] output_size The allocated size in bytes of the `p_output` + * buffer + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + */ +typedef psa_status_t (*psa_drv_se_cipher_ecb_t)(psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key_slot, + psa_algorithm_t algorithm, + psa_encrypt_or_decrypt_t direction, + const uint8_t *p_input, + size_t input_size, + uint8_t *p_output, + size_t output_size); + +/** + * \brief A struct containing all of the function pointers needed to implement + * cipher operations using secure elements. + * + * PSA Crypto API implementations should populate instances of the table as + * appropriate upon startup or at build time. + * + * If one of the functions is not implemented (such as + * `psa_drv_se_cipher_ecb_t`), it should be set to NULL. + */ +typedef struct { + /** The size in bytes of the hardware-specific secure element cipher + * context structure + */ + size_t MBEDTLS_PRIVATE(context_size); + /** Function that performs a cipher setup operation */ + psa_drv_se_cipher_setup_t MBEDTLS_PRIVATE(p_setup); + /** Function that sets a cipher IV (if necessary) */ + psa_drv_se_cipher_set_iv_t MBEDTLS_PRIVATE(p_set_iv); + /** Function that performs a cipher update operation */ + psa_drv_se_cipher_update_t MBEDTLS_PRIVATE(p_update); + /** Function that completes a cipher operation */ + psa_drv_se_cipher_finish_t MBEDTLS_PRIVATE(p_finish); + /** Function that aborts a cipher operation */ + psa_drv_se_cipher_abort_t MBEDTLS_PRIVATE(p_abort); + /** Function that performs ECB mode for a cipher operation + * (Danger: ECB mode should not be used directly by clients of the PSA + * Crypto Client API) + */ + psa_drv_se_cipher_ecb_t MBEDTLS_PRIVATE(p_ecb); +} psa_drv_se_cipher_t; + +/**@}*/ + +/** \defgroup se_asymmetric Secure Element Asymmetric Cryptography + * + * Since the amount of data that can (or should) be encrypted or signed using + * asymmetric keys is limited by the key size, asymmetric key operations using + * keys in a secure element must be done in single function calls. + */ +/**@{*/ + +/** + * \brief A function that signs a hash or short message with a private key in + * a secure element + * + * \param[in,out] drv_context The driver context structure. + * \param[in] key_slot Key slot of an asymmetric key pair + * \param[in] alg A signature algorithm that is compatible + * with the type of `key` + * \param[in] p_hash The hash to sign + * \param[in] hash_length Size of the `p_hash` buffer in bytes + * \param[out] p_signature Buffer where the signature is to be written + * \param[in] signature_size Size of the `p_signature` buffer in bytes + * \param[out] p_signature_length On success, the number of bytes + * that make up the returned signature value + * + * \retval #PSA_SUCCESS \emptydescription + */ +typedef psa_status_t (*psa_drv_se_asymmetric_sign_t)(psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key_slot, + psa_algorithm_t alg, + const uint8_t *p_hash, + size_t hash_length, + uint8_t *p_signature, + size_t signature_size, + size_t *p_signature_length); + +/** + * \brief A function that verifies the signature a hash or short message using + * an asymmetric public key in a secure element + * + * \param[in,out] drv_context The driver context structure. + * \param[in] key_slot Key slot of a public key or an asymmetric key + * pair + * \param[in] alg A signature algorithm that is compatible with + * the type of `key` + * \param[in] p_hash The hash whose signature is to be verified + * \param[in] hash_length Size of the `p_hash` buffer in bytes + * \param[in] p_signature Buffer containing the signature to verify + * \param[in] signature_length Size of the `p_signature` buffer in bytes + * + * \retval #PSA_SUCCESS + * The signature is valid. + */ +typedef psa_status_t (*psa_drv_se_asymmetric_verify_t)(psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key_slot, + psa_algorithm_t alg, + const uint8_t *p_hash, + size_t hash_length, + const uint8_t *p_signature, + size_t signature_length); + +/** + * \brief A function that encrypts a short message with an asymmetric public + * key in a secure element + * + * \param[in,out] drv_context The driver context structure. + * \param[in] key_slot Key slot of a public key or an asymmetric key + * pair + * \param[in] alg An asymmetric encryption algorithm that is + * compatible with the type of `key` + * \param[in] p_input The message to encrypt + * \param[in] input_length Size of the `p_input` buffer in bytes + * \param[in] p_salt A salt or label, if supported by the + * encryption algorithm + * If the algorithm does not support a + * salt, pass `NULL`. + * If the algorithm supports an optional + * salt and you do not want to pass a salt, + * pass `NULL`. + * For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is + * supported. + * \param[in] salt_length Size of the `p_salt` buffer in bytes + * If `p_salt` is `NULL`, pass 0. + * \param[out] p_output Buffer where the encrypted message is to + * be written + * \param[in] output_size Size of the `p_output` buffer in bytes + * \param[out] p_output_length On success, the number of bytes that make up + * the returned output + * + * \retval #PSA_SUCCESS \emptydescription + */ +typedef psa_status_t (*psa_drv_se_asymmetric_encrypt_t)(psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key_slot, + psa_algorithm_t alg, + const uint8_t *p_input, + size_t input_length, + const uint8_t *p_salt, + size_t salt_length, + uint8_t *p_output, + size_t output_size, + size_t *p_output_length); + +/** + * \brief A function that decrypts a short message with an asymmetric private + * key in a secure element. + * + * \param[in,out] drv_context The driver context structure. + * \param[in] key_slot Key slot of an asymmetric key pair + * \param[in] alg An asymmetric encryption algorithm that is + * compatible with the type of `key` + * \param[in] p_input The message to decrypt + * \param[in] input_length Size of the `p_input` buffer in bytes + * \param[in] p_salt A salt or label, if supported by the + * encryption algorithm + * If the algorithm does not support a + * salt, pass `NULL`. + * If the algorithm supports an optional + * salt and you do not want to pass a salt, + * pass `NULL`. + * For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is + * supported. + * \param[in] salt_length Size of the `p_salt` buffer in bytes + * If `p_salt` is `NULL`, pass 0. + * \param[out] p_output Buffer where the decrypted message is to + * be written + * \param[in] output_size Size of the `p_output` buffer in bytes + * \param[out] p_output_length On success, the number of bytes + * that make up the returned output + * + * \retval #PSA_SUCCESS \emptydescription + */ +typedef psa_status_t (*psa_drv_se_asymmetric_decrypt_t)(psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key_slot, + psa_algorithm_t alg, + const uint8_t *p_input, + size_t input_length, + const uint8_t *p_salt, + size_t salt_length, + uint8_t *p_output, + size_t output_size, + size_t *p_output_length); + +/** + * \brief A struct containing all of the function pointers needed to implement + * asymmetric cryptographic operations using secure elements. + * + * PSA Crypto API implementations should populate instances of the table as + * appropriate upon startup or at build time. + * + * If one of the functions is not implemented, it should be set to NULL. + */ +typedef struct { + /** Function that performs an asymmetric sign operation */ + psa_drv_se_asymmetric_sign_t MBEDTLS_PRIVATE(p_sign); + /** Function that performs an asymmetric verify operation */ + psa_drv_se_asymmetric_verify_t MBEDTLS_PRIVATE(p_verify); + /** Function that performs an asymmetric encrypt operation */ + psa_drv_se_asymmetric_encrypt_t MBEDTLS_PRIVATE(p_encrypt); + /** Function that performs an asymmetric decrypt operation */ + psa_drv_se_asymmetric_decrypt_t MBEDTLS_PRIVATE(p_decrypt); +} psa_drv_se_asymmetric_t; + +/**@}*/ + +/** \defgroup se_aead Secure Element Authenticated Encryption with Additional Data + * Authenticated Encryption with Additional Data (AEAD) operations with secure + * elements must be done in one function call. While this creates a burden for + * implementers as there must be sufficient space in memory for the entire + * message, it prevents decrypted data from being made available before the + * authentication operation is complete and the data is known to be authentic. + */ +/**@{*/ + +/** \brief A function that performs a secure element authenticated encryption + * operation + * + * \param[in,out] drv_context The driver context structure. + * \param[in] key_slot Slot containing the key to use. + * \param[in] algorithm The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(`alg`) is true) + * \param[in] p_nonce Nonce or IV to use + * \param[in] nonce_length Size of the `p_nonce` buffer in bytes + * \param[in] p_additional_data Additional data that will be + * authenticated but not encrypted + * \param[in] additional_data_length Size of `p_additional_data` in bytes + * \param[in] p_plaintext Data that will be authenticated and + * encrypted + * \param[in] plaintext_length Size of `p_plaintext` in bytes + * \param[out] p_ciphertext Output buffer for the authenticated and + * encrypted data. The additional data is + * not part of this output. For algorithms + * where the encrypted data and the + * authentication tag are defined as + * separate outputs, the authentication + * tag is appended to the encrypted data. + * \param[in] ciphertext_size Size of the `p_ciphertext` buffer in + * bytes + * \param[out] p_ciphertext_length On success, the size of the output in + * the `p_ciphertext` buffer + * + * \retval #PSA_SUCCESS + * Success. + */ +typedef psa_status_t (*psa_drv_se_aead_encrypt_t)(psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key_slot, + psa_algorithm_t algorithm, + const uint8_t *p_nonce, + size_t nonce_length, + const uint8_t *p_additional_data, + size_t additional_data_length, + const uint8_t *p_plaintext, + size_t plaintext_length, + uint8_t *p_ciphertext, + size_t ciphertext_size, + size_t *p_ciphertext_length); + +/** A function that performs a secure element authenticated decryption operation + * + * \param[in,out] drv_context The driver context structure. + * \param[in] key_slot Slot containing the key to use + * \param[in] algorithm The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(`alg`) is true) + * \param[in] p_nonce Nonce or IV to use + * \param[in] nonce_length Size of the `p_nonce` buffer in bytes + * \param[in] p_additional_data Additional data that has been + * authenticated but not encrypted + * \param[in] additional_data_length Size of `p_additional_data` in bytes + * \param[in] p_ciphertext Data that has been authenticated and + * encrypted. + * For algorithms where the encrypted data + * and the authentication tag are defined + * as separate inputs, the buffer must + * contain the encrypted data followed by + * the authentication tag. + * \param[in] ciphertext_length Size of `p_ciphertext` in bytes + * \param[out] p_plaintext Output buffer for the decrypted data + * \param[in] plaintext_size Size of the `p_plaintext` buffer in + * bytes + * \param[out] p_plaintext_length On success, the size of the output in + * the `p_plaintext` buffer + * + * \retval #PSA_SUCCESS + * Success. + */ +typedef psa_status_t (*psa_drv_se_aead_decrypt_t)(psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key_slot, + psa_algorithm_t algorithm, + const uint8_t *p_nonce, + size_t nonce_length, + const uint8_t *p_additional_data, + size_t additional_data_length, + const uint8_t *p_ciphertext, + size_t ciphertext_length, + uint8_t *p_plaintext, + size_t plaintext_size, + size_t *p_plaintext_length); + +/** + * \brief A struct containing all of the function pointers needed to implement + * secure element Authenticated Encryption with Additional Data operations + * + * PSA Crypto API implementations should populate instances of the table as + * appropriate upon startup. + * + * If one of the functions is not implemented, it should be set to NULL. + */ +typedef struct { + /** Function that performs the AEAD encrypt operation */ + psa_drv_se_aead_encrypt_t MBEDTLS_PRIVATE(p_encrypt); + /** Function that performs the AEAD decrypt operation */ + psa_drv_se_aead_decrypt_t MBEDTLS_PRIVATE(p_decrypt); +} psa_drv_se_aead_t; +/**@}*/ + +/** \defgroup se_key_management Secure Element Key Management + * Currently, key management is limited to importing keys in the clear, + * destroying keys, and exporting keys in the clear. + * Whether a key may be exported is determined by the key policies in place + * on the key slot. + */ +/**@{*/ + +/** An enumeration indicating how a key is created. + */ +typedef enum { + PSA_KEY_CREATION_IMPORT, /**< During psa_import_key() */ + PSA_KEY_CREATION_GENERATE, /**< During psa_generate_key() */ + PSA_KEY_CREATION_DERIVE, /**< During psa_key_derivation_output_key() */ + PSA_KEY_CREATION_COPY, /**< During psa_copy_key() */ + +#ifndef __DOXYGEN_ONLY__ + /** A key is being registered with mbedtls_psa_register_se_key(). + * + * The core only passes this value to + * psa_drv_se_key_management_t::p_validate_slot_number, not to + * psa_drv_se_key_management_t::p_allocate. The call to + * `p_validate_slot_number` is not followed by any other call to the + * driver: the key is considered successfully registered if the call to + * `p_validate_slot_number` succeeds, or if `p_validate_slot_number` is + * null. + * + * With this creation method, the driver must return #PSA_SUCCESS if + * the given attributes are compatible with the existing key in the slot, + * and #PSA_ERROR_DOES_NOT_EXIST if the driver can determine that there + * is no key with the specified slot number. + * + * This is an Mbed Crypto extension. + */ + PSA_KEY_CREATION_REGISTER, +#endif +} psa_key_creation_method_t; + +/** \brief A function that allocates a slot for a key. + * + * To create a key in a specific slot in a secure element, the core + * first calls this function to determine a valid slot number, + * then calls a function to create the key material in that slot. + * In nominal conditions (that is, if no error occurs), + * the effect of a call to a key creation function in the PSA Cryptography + * API with a lifetime that places the key in a secure element is the + * following: + * -# The core calls psa_drv_se_key_management_t::p_allocate + * (or in some implementations + * psa_drv_se_key_management_t::p_validate_slot_number). The driver + * selects (or validates) a suitable slot number given the key attributes + * and the state of the secure element. + * -# The core calls a key creation function in the driver. + * + * The key creation functions in the PSA Cryptography API are: + * - psa_import_key(), which causes + * a call to `p_allocate` with \p method = #PSA_KEY_CREATION_IMPORT + * then a call to psa_drv_se_key_management_t::p_import. + * - psa_generate_key(), which causes + * a call to `p_allocate` with \p method = #PSA_KEY_CREATION_GENERATE + * then a call to psa_drv_se_key_management_t::p_import. + * - psa_key_derivation_output_key(), which causes + * a call to `p_allocate` with \p method = #PSA_KEY_CREATION_DERIVE + * then a call to psa_drv_se_key_derivation_t::p_derive. + * - psa_copy_key(), which causes + * a call to `p_allocate` with \p method = #PSA_KEY_CREATION_COPY + * then a call to psa_drv_se_key_management_t::p_export. + * + * In case of errors, other behaviors are possible. + * - If the PSA Cryptography subsystem dies after the first step, + * for example because the device has lost power abruptly, + * the second step may never happen, or may happen after a reset + * and re-initialization. Alternatively, after a reset and + * re-initialization, the core may call + * psa_drv_se_key_management_t::p_destroy on the slot number that + * was allocated (or validated) instead of calling a key creation function. + * - If an error occurs, the core may call + * psa_drv_se_key_management_t::p_destroy on the slot number that + * was allocated (or validated) instead of calling a key creation function. + * + * Errors and system resets also have an impact on the driver's persistent + * data. If a reset happens before the overall key creation process is + * completed (before or after the second step above), it is unspecified + * whether the persistent data after the reset is identical to what it + * was before or after the call to `p_allocate` (or `p_validate_slot_number`). + * + * \param[in,out] drv_context The driver context structure. + * \param[in,out] persistent_data A pointer to the persistent data + * that allows writing. + * \param[in] attributes Attributes of the key. + * \param method The way in which the key is being created. + * \param[out] key_slot Slot where the key will be stored. + * This must be a valid slot for a key of the + * chosen type. It must be unoccupied. + * + * \retval #PSA_SUCCESS + * Success. + * The core will record \c *key_slot as the key slot where the key + * is stored and will update the persistent data in storage. + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription + */ +typedef psa_status_t (*psa_drv_se_allocate_key_t)( + psa_drv_se_context_t *drv_context, + void *persistent_data, + const psa_key_attributes_t *attributes, + psa_key_creation_method_t method, + psa_key_slot_number_t *key_slot); + +/** \brief A function that determines whether a slot number is valid + * for a key. + * + * To create a key in a specific slot in a secure element, the core + * first calls this function to validate the choice of slot number, + * then calls a function to create the key material in that slot. + * See the documentation of #psa_drv_se_allocate_key_t for more details. + * + * As of the PSA Cryptography API specification version 1.0, there is no way + * for applications to trigger a call to this function. However some + * implementations offer the capability to create or declare a key in + * a specific slot via implementation-specific means, generally for the + * sake of initial device provisioning or onboarding. Such a mechanism may + * be added to a future version of the PSA Cryptography API specification. + * + * This function may update the driver's persistent data through + * \p persistent_data. The core will save the updated persistent data at the + * end of the key creation process. See the description of + * ::psa_drv_se_allocate_key_t for more information. + * + * \param[in,out] drv_context The driver context structure. + * \param[in,out] persistent_data A pointer to the persistent data + * that allows writing. + * \param[in] attributes Attributes of the key. + * \param method The way in which the key is being created. + * \param[in] key_slot Slot where the key is to be stored. + * + * \retval #PSA_SUCCESS + * The given slot number is valid for a key with the given + * attributes. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The given slot number is not valid for a key with the + * given attributes. This includes the case where the slot + * number is not valid at all. + * \retval #PSA_ERROR_ALREADY_EXISTS + * There is already a key with the specified slot number. + * Drivers may choose to return this error from the key + * creation function instead. + */ +typedef psa_status_t (*psa_drv_se_validate_slot_number_t)( + psa_drv_se_context_t *drv_context, + void *persistent_data, + const psa_key_attributes_t *attributes, + psa_key_creation_method_t method, + psa_key_slot_number_t key_slot); + +/** \brief A function that imports a key into a secure element in binary format + * + * This function can support any output from psa_export_key(). Refer to the + * documentation of psa_export_key() for the format for each key type. + * + * \param[in,out] drv_context The driver context structure. + * \param key_slot Slot where the key will be stored. + * This must be a valid slot for a key of the + * chosen type. It must be unoccupied. + * \param[in] attributes The key attributes, including the lifetime, + * the key type and the usage policy. + * Drivers should not access the key size stored + * in the attributes: it may not match the + * data passed in \p data. + * Drivers can call psa_get_key_lifetime(), + * psa_get_key_type(), + * psa_get_key_usage_flags() and + * psa_get_key_algorithm() to access this + * information. + * \param[in] data Buffer containing the key data. + * \param[in] data_length Size of the \p data buffer in bytes. + * \param[out] bits On success, the key size in bits. The driver + * must determine this value after parsing the + * key according to the key type. + * This value is not used if the function fails. + * + * \retval #PSA_SUCCESS + * Success. + */ +typedef psa_status_t (*psa_drv_se_import_key_t)( + psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key_slot, + const psa_key_attributes_t *attributes, + const uint8_t *data, + size_t data_length, + size_t *bits); + +/** + * \brief A function that destroys a secure element key and restore the slot to + * its default state + * + * This function destroys the content of the key from a secure element. + * Implementations shall make a best effort to ensure that any previous content + * of the slot is unrecoverable. + * + * This function returns the specified slot to its default state. + * + * \param[in,out] drv_context The driver context structure. + * \param[in,out] persistent_data A pointer to the persistent data + * that allows writing. + * \param key_slot The key slot to erase. + * + * \retval #PSA_SUCCESS + * The slot's content, if any, has been erased. + */ +typedef psa_status_t (*psa_drv_se_destroy_key_t)( + psa_drv_se_context_t *drv_context, + void *persistent_data, + psa_key_slot_number_t key_slot); + +/** + * \brief A function that exports a secure element key in binary format + * + * The output of this function can be passed to psa_import_key() to + * create an equivalent object. + * + * If a key is created with `psa_import_key()` and then exported with + * this function, it is not guaranteed that the resulting data is + * identical: the implementation may choose a different representation + * of the same key if the format permits it. + * + * This function should generate output in the same format that + * `psa_export_key()` does. Refer to the + * documentation of `psa_export_key()` for the format for each key type. + * + * \param[in,out] drv_context The driver context structure. + * \param[in] key Slot whose content is to be exported. This must + * be an occupied key slot. + * \param[out] p_data Buffer where the key data is to be written. + * \param[in] data_size Size of the `p_data` buffer in bytes. + * \param[out] p_data_length On success, the number of bytes + * that make up the key data. + * + * \retval #PSA_SUCCESS \emptydescription + * \retval #PSA_ERROR_DOES_NOT_EXIST \emptydescription + * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + */ +typedef psa_status_t (*psa_drv_se_export_key_t)(psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key, + uint8_t *p_data, + size_t data_size, + size_t *p_data_length); + +/** + * \brief A function that generates a symmetric or asymmetric key on a secure + * element + * + * If the key type \c type recorded in \p attributes + * is asymmetric (#PSA_KEY_TYPE_IS_ASYMMETRIC(\c type) = 1), + * the driver may export the public key at the time of generation, + * in the format documented for psa_export_public_key() by writing it + * to the \p pubkey buffer. + * This is optional, intended for secure elements that output the + * public key at generation time and that cannot export the public key + * later. Drivers that do not need this feature should leave + * \p *pubkey_length set to 0 and should + * implement the psa_drv_key_management_t::p_export_public function. + * Some implementations do not support this feature, in which case + * \p pubkey is \c NULL and \p pubkey_size is 0. + * + * \param[in,out] drv_context The driver context structure. + * \param key_slot Slot where the key will be stored. + * This must be a valid slot for a key of the + * chosen type. It must be unoccupied. + * \param[in] attributes The key attributes, including the lifetime, + * the key type and size, and the usage policy. + * Drivers can call psa_get_key_lifetime(), + * psa_get_key_type(), psa_get_key_bits(), + * psa_get_key_usage_flags() and + * psa_get_key_algorithm() to access this + * information. + * \param[out] pubkey A buffer where the driver can write the + * public key, when generating an asymmetric + * key pair. + * This is \c NULL when generating a symmetric + * key or if the core does not support + * exporting the public key at generation time. + * \param pubkey_size The size of the `pubkey` buffer in bytes. + * This is 0 when generating a symmetric + * key or if the core does not support + * exporting the public key at generation time. + * \param[out] pubkey_length On entry, this is always 0. + * On success, the number of bytes written to + * \p pubkey. If this is 0 or unchanged on return, + * the core will not read the \p pubkey buffer, + * and will instead call the driver's + * psa_drv_key_management_t::p_export_public + * function to export the public key when needed. + */ +typedef psa_status_t (*psa_drv_se_generate_key_t)( + psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key_slot, + const psa_key_attributes_t *attributes, + uint8_t *pubkey, size_t pubkey_size, size_t *pubkey_length); + +/** + * \brief A struct containing all of the function pointers needed to for secure + * element key management + * + * PSA Crypto API implementations should populate instances of the table as + * appropriate upon startup or at build time. + * + * If one of the functions is not implemented, it should be set to NULL. + */ +typedef struct { + /** Function that allocates a slot for a key. */ + psa_drv_se_allocate_key_t MBEDTLS_PRIVATE(p_allocate); + /** Function that checks the validity of a slot for a key. */ + psa_drv_se_validate_slot_number_t MBEDTLS_PRIVATE(p_validate_slot_number); + /** Function that performs a key import operation */ + psa_drv_se_import_key_t MBEDTLS_PRIVATE(p_import); + /** Function that performs a generation */ + psa_drv_se_generate_key_t MBEDTLS_PRIVATE(p_generate); + /** Function that performs a key destroy operation */ + psa_drv_se_destroy_key_t MBEDTLS_PRIVATE(p_destroy); + /** Function that performs a key export operation */ + psa_drv_se_export_key_t MBEDTLS_PRIVATE(p_export); + /** Function that performs a public key export operation */ + psa_drv_se_export_key_t MBEDTLS_PRIVATE(p_export_public); +} psa_drv_se_key_management_t; + +/**@}*/ + +/** \defgroup driver_derivation Secure Element Key Derivation and Agreement + * Key derivation is the process of generating new key material using an + * existing key and additional parameters, iterating through a basic + * cryptographic function, such as a hash. + * Key agreement is a part of cryptographic protocols that allows two parties + * to agree on the same key value, but starting from different original key + * material. + * The flows are similar, and the PSA Crypto Driver Model uses the same functions + * for both of the flows. + * + * There are two different final functions for the flows, + * `psa_drv_se_key_derivation_derive` and `psa_drv_se_key_derivation_export`. + * `psa_drv_se_key_derivation_derive` is used when the key material should be + * placed in a slot on the hardware and not exposed to the caller. + * `psa_drv_se_key_derivation_export` is used when the key material should be + * returned to the PSA Cryptographic API implementation. + * + * Different key derivation algorithms require a different number of inputs. + * Instead of having an API that takes as input variable length arrays, which + * can be problematic to manage on embedded platforms, the inputs are passed + * to the driver via a function, `psa_drv_se_key_derivation_collateral`, that + * is called multiple times with different `collateral_id`s. Thus, for a key + * derivation algorithm that required 3 parameter inputs, the flow would look + * something like: + * ~~~~~~~~~~~~~{.c} + * psa_drv_se_key_derivation_setup(kdf_algorithm, source_key, dest_key_size_bytes); + * psa_drv_se_key_derivation_collateral(kdf_algorithm_collateral_id_0, + * p_collateral_0, + * collateral_0_size); + * psa_drv_se_key_derivation_collateral(kdf_algorithm_collateral_id_1, + * p_collateral_1, + * collateral_1_size); + * psa_drv_se_key_derivation_collateral(kdf_algorithm_collateral_id_2, + * p_collateral_2, + * collateral_2_size); + * psa_drv_se_key_derivation_derive(); + * ~~~~~~~~~~~~~ + * + * key agreement example: + * ~~~~~~~~~~~~~{.c} + * psa_drv_se_key_derivation_setup(alg, source_key. dest_key_size_bytes); + * psa_drv_se_key_derivation_collateral(DHE_PUBKEY, p_pubkey, pubkey_size); + * psa_drv_se_key_derivation_export(p_session_key, + * session_key_size, + * &session_key_length); + * ~~~~~~~~~~~~~ + */ +/**@{*/ + +/** \brief A function that Sets up a secure element key derivation operation by + * specifying the algorithm and the source key sot + * + * \param[in,out] drv_context The driver context structure. + * \param[in,out] op_context A hardware-specific structure containing any + * context information for the implementation + * \param[in] kdf_alg The algorithm to be used for the key derivation + * \param[in] source_key The key to be used as the source material for + * the key derivation + * + * \retval #PSA_SUCCESS \emptydescription + */ +typedef psa_status_t (*psa_drv_se_key_derivation_setup_t)(psa_drv_se_context_t *drv_context, + void *op_context, + psa_algorithm_t kdf_alg, + psa_key_slot_number_t source_key); + +/** \brief A function that provides collateral (parameters) needed for a secure + * element key derivation or key agreement operation + * + * Since many key derivation algorithms require multiple parameters, it is + * expected that this function may be called multiple times for the same + * operation, each with a different algorithm-specific `collateral_id` + * + * \param[in,out] op_context A hardware-specific structure containing any + * context information for the implementation + * \param[in] collateral_id An ID for the collateral being provided + * \param[in] p_collateral A buffer containing the collateral data + * \param[in] collateral_size The size in bytes of the collateral + * + * \retval #PSA_SUCCESS \emptydescription + */ +typedef psa_status_t (*psa_drv_se_key_derivation_collateral_t)(void *op_context, + uint32_t collateral_id, + const uint8_t *p_collateral, + size_t collateral_size); + +/** \brief A function that performs the final secure element key derivation + * step and place the generated key material in a slot + * + * \param[in,out] op_context A hardware-specific structure containing any + * context information for the implementation + * \param[in] dest_key The slot where the generated key material + * should be placed + * + * \retval #PSA_SUCCESS \emptydescription + */ +typedef psa_status_t (*psa_drv_se_key_derivation_derive_t)(void *op_context, + psa_key_slot_number_t dest_key); + +/** \brief A function that performs the final step of a secure element key + * agreement and place the generated key material in a buffer + * + * \param[out] p_output Buffer in which to place the generated key + * material + * \param[in] output_size The size in bytes of `p_output` + * \param[out] p_output_length Upon success, contains the number of bytes of + * key material placed in `p_output` + * + * \retval #PSA_SUCCESS \emptydescription + */ +typedef psa_status_t (*psa_drv_se_key_derivation_export_t)(void *op_context, + uint8_t *p_output, + size_t output_size, + size_t *p_output_length); + +/** + * \brief A struct containing all of the function pointers needed to for secure + * element key derivation and agreement + * + * PSA Crypto API implementations should populate instances of the table as + * appropriate upon startup. + * + * If one of the functions is not implemented, it should be set to NULL. + */ +typedef struct { + /** The driver-specific size of the key derivation context */ + size_t MBEDTLS_PRIVATE(context_size); + /** Function that performs a key derivation setup */ + psa_drv_se_key_derivation_setup_t MBEDTLS_PRIVATE(p_setup); + /** Function that sets key derivation collateral */ + psa_drv_se_key_derivation_collateral_t MBEDTLS_PRIVATE(p_collateral); + /** Function that performs a final key derivation step */ + psa_drv_se_key_derivation_derive_t MBEDTLS_PRIVATE(p_derive); + /** Function that performs a final key derivation or agreement and + * exports the key */ + psa_drv_se_key_derivation_export_t MBEDTLS_PRIVATE(p_export); +} psa_drv_se_key_derivation_t; + +/**@}*/ + +/** \defgroup se_registration Secure element driver registration + */ +/**@{*/ + +/** A structure containing pointers to all the entry points of a + * secure element driver. + * + * Future versions of this specification may add extra substructures at + * the end of this structure. + */ +typedef struct { + /** The version of the driver HAL that this driver implements. + * This is a protection against loading driver binaries built against + * a different version of this specification. + * Use #PSA_DRV_SE_HAL_VERSION. + */ + uint32_t MBEDTLS_PRIVATE(hal_version); + + /** The size of the driver's persistent data in bytes. + * + * This can be 0 if the driver does not need persistent data. + * + * See the documentation of psa_drv_se_context_t::persistent_data + * for more information about why and how a driver can use + * persistent data. + */ + size_t MBEDTLS_PRIVATE(persistent_data_size); + + /** The driver initialization function. + * + * This function is called once during the initialization of the + * PSA Cryptography subsystem, before any other function of the + * driver is called. If this function returns a failure status, + * the driver will be unusable, at least until the next system reset. + * + * If this field is \c NULL, it is equivalent to a function that does + * nothing and returns #PSA_SUCCESS. + */ + psa_drv_se_init_t MBEDTLS_PRIVATE(p_init); + + const psa_drv_se_key_management_t *MBEDTLS_PRIVATE(key_management); + const psa_drv_se_mac_t *MBEDTLS_PRIVATE(mac); + const psa_drv_se_cipher_t *MBEDTLS_PRIVATE(cipher); + const psa_drv_se_aead_t *MBEDTLS_PRIVATE(aead); + const psa_drv_se_asymmetric_t *MBEDTLS_PRIVATE(asymmetric); + const psa_drv_se_key_derivation_t *MBEDTLS_PRIVATE(derivation); +} psa_drv_se_t; + +/** The current version of the secure element driver HAL. + */ +/* 0.0.0 patchlevel 5 */ +#define PSA_DRV_SE_HAL_VERSION 0x00000005 + +/** Register an external cryptoprocessor (secure element) driver. + * + * This function is only intended to be used by driver code, not by + * application code. In implementations with separation between the + * PSA cryptography module and applications, this function should + * only be available to callers that run in the same memory space as + * the cryptography module, and should not be exposed to applications + * running in a different memory space. + * + * This function may be called before psa_crypto_init(). It is + * implementation-defined whether this function may be called + * after psa_crypto_init(). + * + * \note Implementations store metadata about keys including the lifetime + * value, which contains the driver's location indicator. Therefore, + * from one instantiation of the PSA Cryptography + * library to the next one, if there is a key in storage with a certain + * lifetime value, you must always register the same driver (or an + * updated version that communicates with the same secure element) + * with the same location value. + * + * \param location The location value through which this driver will + * be exposed to applications. + * This driver will be used for all keys such that + * `location == #PSA_KEY_LIFETIME_GET_LOCATION( lifetime )`. + * The value #PSA_KEY_LOCATION_LOCAL_STORAGE is reserved + * and may not be used for drivers. Implementations + * may reserve other values. + * \param[in] methods The method table of the driver. This structure must + * remain valid for as long as the cryptography + * module keeps running. It is typically a global + * constant. + * + * \return #PSA_SUCCESS + * The driver was successfully registered. Applications can now + * use \p location to access keys through the methods passed to + * this function. + * \return #PSA_ERROR_BAD_STATE + * This function was called after the initialization of the + * cryptography module, and this implementation does not support + * driver registration at this stage. + * \return #PSA_ERROR_ALREADY_EXISTS + * There is already a registered driver for this value of \p location. + * \return #PSA_ERROR_INVALID_ARGUMENT + * \p location is a reserved value. + * \return #PSA_ERROR_NOT_SUPPORTED + * `methods->hal_version` is not supported by this implementation. + * \return #PSA_ERROR_INSUFFICIENT_MEMORY + * \return #PSA_ERROR_NOT_PERMITTED + * \return #PSA_ERROR_STORAGE_FAILURE + * \return #PSA_ERROR_DATA_CORRUPT + */ +psa_status_t psa_register_se_driver( + psa_key_location_t location, + const psa_drv_se_t *methods); + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_SE_DRIVER_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_sizes.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_sizes.h new file mode 100644 index 0000000..3d6bb2c --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_sizes.h @@ -0,0 +1,1173 @@ +/** + * \file psa/crypto_sizes.h + * + * \brief PSA cryptography module: Mbed TLS buffer size macros + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + * + * This file contains the definitions of macros that are useful to + * compute buffer sizes. The signatures and semantics of these macros + * are standardized, but the definitions are not, because they depend on + * the available algorithms and, in some cases, on permitted tolerances + * on buffer sizes. + * + * In implementations with isolation between the application and the + * cryptography module, implementers should take care to ensure that + * the definitions that are exposed to applications match what the + * module implements. + * + * Macros that compute sizes whose values do not depend on the + * implementation are in crypto.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. + */ + +#ifndef PSA_CRYPTO_SIZES_H +#define PSA_CRYPTO_SIZES_H + +/* Include the Mbed TLS configuration file, the way Mbed TLS does it + * in each of its header files. */ +#include "mbedtls/build_info.h" + +#define PSA_BITS_TO_BYTES(bits) (((bits) + 7) / 8) +#define PSA_BYTES_TO_BITS(bytes) ((bytes) * 8) + +#define PSA_ROUND_UP_TO_MULTIPLE(block_size, length) \ + (((length) + (block_size) - 1) / (block_size) * (block_size)) + +/** The size of the output of psa_hash_finish(), in bytes. + * + * This is also the hash size that psa_hash_verify() expects. + * + * \param alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p alg) is true), or an HMAC algorithm + * (#PSA_ALG_HMAC(\c hash_alg) where \c hash_alg is a + * hash algorithm). + * + * \return The hash size for the specified hash algorithm. + * If the hash algorithm is not recognized, return 0. + */ +#define PSA_HASH_LENGTH(alg) \ + ( \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD5 ? 16 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_RIPEMD160 ? 20 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_1 ? 20 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_224 ? 28 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_256 ? 32 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_384 ? 48 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512 ? 64 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_224 ? 28 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_256 ? 32 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_224 ? 28 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_256 ? 32 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_384 ? 48 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_512 ? 64 : \ + 0) + +/** The input block size of a hash algorithm, in bytes. + * + * Hash algorithms process their input data in blocks. Hash operations will + * retain any partial blocks until they have enough input to fill the block or + * until the operation is finished. + * This affects the output from psa_hash_suspend(). + * + * \param alg A hash algorithm (\c PSA_ALG_XXX value such that + * PSA_ALG_IS_HASH(\p alg) is true). + * + * \return The block size in bytes for the specified hash algorithm. + * If the hash algorithm is not recognized, return 0. + * An implementation can return either 0 or the correct size for a + * hash algorithm that it recognizes, but does not support. + */ +#define PSA_HASH_BLOCK_LENGTH(alg) \ + ( \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD5 ? 64 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_RIPEMD160 ? 64 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_1 ? 64 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_224 ? 64 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_256 ? 64 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_384 ? 128 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512 ? 128 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_224 ? 128 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_256 ? 128 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_224 ? 144 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_256 ? 136 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_384 ? 104 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_512 ? 72 : \ + 0) + +/** \def PSA_HASH_MAX_SIZE + * + * Maximum size of a hash. + * + * This macro expands to a compile-time constant integer. This value + * is the maximum size of a hash in bytes. + */ +/* Note: for HMAC-SHA-3, the block size is 144 bytes for HMAC-SHA3-226, + * 136 bytes for HMAC-SHA3-256, 104 bytes for SHA3-384, 72 bytes for + * HMAC-SHA3-512. */ +#if defined(PSA_WANT_ALG_SHA_512) || defined(PSA_WANT_ALG_SHA_384) +#define PSA_HASH_MAX_SIZE 64 +#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 128 +#else +#define PSA_HASH_MAX_SIZE 32 +#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 64 +#endif + +/** \def PSA_MAC_MAX_SIZE + * + * Maximum size of a MAC. + * + * This macro expands to a compile-time constant integer. This value + * is the maximum size of a MAC in bytes. + */ +/* All non-HMAC MACs have a maximum size that's smaller than the + * minimum possible value of PSA_HASH_MAX_SIZE in this implementation. */ +/* Note that the encoding of truncated MAC algorithms limits this value + * to 64 bytes. + */ +#define PSA_MAC_MAX_SIZE PSA_HASH_MAX_SIZE + +/** The length of a tag for an AEAD algorithm, in bytes. + * + * This macro can be used to allocate a buffer of sufficient size to store the + * tag output from psa_aead_finish(). + * + * See also #PSA_AEAD_TAG_MAX_SIZE. + * + * \param key_type The type of the AEAD key. + * \param key_bits The size of the AEAD key in bits. + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \return The tag length for the specified algorithm and key. + * If the AEAD algorithm does not have an identified + * tag that can be distinguished from the rest of + * the ciphertext, return 0. + * If the key type or AEAD algorithm is not + * recognized, or the parameters are incompatible, + * return 0. + */ +#define PSA_AEAD_TAG_LENGTH(key_type, key_bits, alg) \ + (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 ? \ + PSA_ALG_AEAD_GET_TAG_LENGTH(alg) : \ + ((void) (key_bits), 0)) + +/** The maximum tag size for all supported AEAD algorithms, in bytes. + * + * See also #PSA_AEAD_TAG_LENGTH(\p key_type, \p key_bits, \p alg). + */ +#define PSA_AEAD_TAG_MAX_SIZE 16 + +/* The maximum size of an RSA key on this implementation, in bits. + * This is a vendor-specific macro. + * + * Mbed TLS does not set a hard limit on the size of RSA keys: any key + * whose parameters fit in a bignum is accepted. However large keys can + * induce a large memory usage and long computation times. Unlike other + * auxiliary macros in this file and in crypto.h, which reflect how the + * library is configured, this macro defines how the library is + * configured. This implementation refuses to import or generate an + * RSA key whose size is larger than the value defined here. + * + * Note that an implementation may set different size limits for different + * operations, and does not need to accept all key sizes up to the limit. */ +#define PSA_VENDOR_RSA_MAX_KEY_BITS 4096 + +/* The maximum size of an ECC key on this implementation, in bits. + * This is a vendor-specific macro. */ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 521 +#elif defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 512 +#elif defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 448 +#elif defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 384 +#elif defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 384 +#elif defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256 +#elif defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256 +#elif defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256 +#elif defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 255 +#elif defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 224 +#elif defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 224 +#elif defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 192 +#elif defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 192 +#else +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 0 +#endif + +/** This macro returns the maximum supported length of the PSK for the + * TLS-1.2 PSK-to-MS key derivation + * (#PSA_ALG_TLS12_PSK_TO_MS(\c hash_alg)). + * + * The maximum supported length does not depend on the chosen hash algorithm. + * + * Quoting RFC 4279, Sect 5.3: + * TLS implementations supporting these ciphersuites MUST support + * arbitrary PSK identities up to 128 octets in length, and arbitrary + * PSKs up to 64 octets in length. Supporting longer identities and + * keys is RECOMMENDED. + * + * Therefore, no implementation should define a value smaller than 64 + * for #PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE. + */ +#define PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE 128 + +/* The expected size of input passed to psa_tls12_ecjpake_to_pms_input, + * which is expected to work with P-256 curve only. */ +#define PSA_TLS12_ECJPAKE_TO_PMS_INPUT_SIZE 65 + +/* The size of a serialized K.X coordinate to be used in + * psa_tls12_ecjpake_to_pms_input. This function only accepts the P-256 + * curve. */ +#define PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE 32 + +/** The maximum size of a block cipher. */ +#define PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE 16 + +/** The size of the output of psa_mac_sign_finish(), in bytes. + * + * This is also the MAC size that psa_mac_verify_finish() expects. + * + * \warning This macro may evaluate its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \param key_type The type of the MAC key. + * \param key_bits The size of the MAC key in bits. + * \param alg A MAC algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_MAC(\p alg) is true). + * + * \return The MAC size for the specified algorithm with + * the specified key parameters. + * \return 0 if the MAC algorithm is not recognized. + * \return Either 0 or the correct size for a MAC algorithm that + * the implementation recognizes, but does not support. + * \return Unspecified if the key parameters are not consistent + * with the algorithm. + */ +#define PSA_MAC_LENGTH(key_type, key_bits, alg) \ + ((alg) & PSA_ALG_MAC_TRUNCATION_MASK ? PSA_MAC_TRUNCATED_LENGTH(alg) : \ + PSA_ALG_IS_HMAC(alg) ? PSA_HASH_LENGTH(PSA_ALG_HMAC_GET_HASH(alg)) : \ + PSA_ALG_IS_BLOCK_CIPHER_MAC(alg) ? PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) : \ + ((void) (key_type), (void) (key_bits), 0)) + +/** The maximum size of the output of psa_aead_encrypt(), in bytes. + * + * If the size of the ciphertext buffer is at least this large, it is + * guaranteed that psa_aead_encrypt() will not fail due to an + * insufficient buffer size. Depending on the algorithm, the actual size of + * the ciphertext may be smaller. + * + * See also #PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(\p plaintext_length). + * + * \warning This macro may evaluate its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \param key_type A symmetric key type that is + * compatible with algorithm \p alg. + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * \param plaintext_length Size of the plaintext in bytes. + * + * \return The AEAD ciphertext size for the specified + * algorithm. + * If the key type or AEAD algorithm is not + * recognized, or the parameters are incompatible, + * return 0. + */ +#define PSA_AEAD_ENCRYPT_OUTPUT_SIZE(key_type, alg, plaintext_length) \ + (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 ? \ + (plaintext_length) + PSA_ALG_AEAD_GET_TAG_LENGTH(alg) : \ + 0) + +/** A sufficient output buffer size for psa_aead_encrypt(), for any of the + * supported key types and AEAD algorithms. + * + * If the size of the ciphertext buffer is at least this large, it is guaranteed + * that psa_aead_encrypt() will not fail due to an insufficient buffer size. + * + * \note This macro returns a compile-time constant if its arguments are + * compile-time constants. + * + * See also #PSA_AEAD_ENCRYPT_OUTPUT_SIZE(\p key_type, \p alg, + * \p plaintext_length). + * + * \param plaintext_length Size of the plaintext in bytes. + * + * \return A sufficient output buffer size for any of the + * supported key types and AEAD algorithms. + * + */ +#define PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(plaintext_length) \ + ((plaintext_length) + PSA_AEAD_TAG_MAX_SIZE) + + +/** The maximum size of the output of psa_aead_decrypt(), in bytes. + * + * If the size of the plaintext buffer is at least this large, it is + * guaranteed that psa_aead_decrypt() will not fail due to an + * insufficient buffer size. Depending on the algorithm, the actual size of + * the plaintext may be smaller. + * + * See also #PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE(\p ciphertext_length). + * + * \warning This macro may evaluate its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \param key_type A symmetric key type that is + * compatible with algorithm \p alg. + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * \param ciphertext_length Size of the plaintext in bytes. + * + * \return The AEAD ciphertext size for the specified + * algorithm. + * If the key type or AEAD algorithm is not + * recognized, or the parameters are incompatible, + * return 0. + */ +#define PSA_AEAD_DECRYPT_OUTPUT_SIZE(key_type, alg, ciphertext_length) \ + (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 && \ + (ciphertext_length) > PSA_ALG_AEAD_GET_TAG_LENGTH(alg) ? \ + (ciphertext_length) - PSA_ALG_AEAD_GET_TAG_LENGTH(alg) : \ + 0) + +/** A sufficient output buffer size for psa_aead_decrypt(), for any of the + * supported key types and AEAD algorithms. + * + * If the size of the plaintext buffer is at least this large, it is guaranteed + * that psa_aead_decrypt() will not fail due to an insufficient buffer size. + * + * \note This macro returns a compile-time constant if its arguments are + * compile-time constants. + * + * See also #PSA_AEAD_DECRYPT_OUTPUT_SIZE(\p key_type, \p alg, + * \p ciphertext_length). + * + * \param ciphertext_length Size of the ciphertext in bytes. + * + * \return A sufficient output buffer size for any of the + * supported key types and AEAD algorithms. + * + */ +#define PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE(ciphertext_length) \ + (ciphertext_length) + +/** The default nonce size for an AEAD algorithm, in bytes. + * + * This macro can be used to allocate a buffer of sufficient size to + * store the nonce output from #psa_aead_generate_nonce(). + * + * See also #PSA_AEAD_NONCE_MAX_SIZE. + * + * \note This is not the maximum size of nonce supported as input to + * #psa_aead_set_nonce(), #psa_aead_encrypt() or #psa_aead_decrypt(), + * just the default size that is generated by #psa_aead_generate_nonce(). + * + * \warning This macro may evaluate its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \param key_type A symmetric key type that is compatible with + * algorithm \p alg. + * + * \param alg An AEAD algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \return The default nonce size for the specified key type and algorithm. + * If the key type or AEAD algorithm is not recognized, + * or the parameters are incompatible, return 0. + */ +#define PSA_AEAD_NONCE_LENGTH(key_type, alg) \ + (PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) == 16 ? \ + MBEDTLS_PSA_ALG_AEAD_EQUAL(alg, PSA_ALG_CCM) ? 13 : \ + MBEDTLS_PSA_ALG_AEAD_EQUAL(alg, PSA_ALG_GCM) ? 12 : \ + 0 : \ + (key_type) == PSA_KEY_TYPE_CHACHA20 && \ + MBEDTLS_PSA_ALG_AEAD_EQUAL(alg, PSA_ALG_CHACHA20_POLY1305) ? 12 : \ + 0) + +/** The maximum default nonce size among all supported pairs of key types and + * AEAD algorithms, in bytes. + * + * This is equal to or greater than any value that #PSA_AEAD_NONCE_LENGTH() + * may return. + * + * \note This is not the maximum size of nonce supported as input to + * #psa_aead_set_nonce(), #psa_aead_encrypt() or #psa_aead_decrypt(), + * just the largest size that may be generated by + * #psa_aead_generate_nonce(). + */ +#define PSA_AEAD_NONCE_MAX_SIZE 13 + +/** A sufficient output buffer size for psa_aead_update(). + * + * If the size of the output buffer is at least this large, it is + * guaranteed that psa_aead_update() will not fail due to an + * insufficient buffer size. The actual size of the output may be smaller + * in any given call. + * + * See also #PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(\p input_length). + * + * \warning This macro may evaluate its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \param key_type A symmetric key type that is + * compatible with algorithm \p alg. + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * \param input_length Size of the input in bytes. + * + * \return A sufficient output buffer size for the specified + * algorithm. + * If the key type or AEAD algorithm is not + * recognized, or the parameters are incompatible, + * return 0. + */ +/* For all the AEAD modes defined in this specification, it is possible + * to emit output without delay. However, hardware may not always be + * capable of this. So for modes based on a block cipher, allow the + * implementation to delay the output until it has a full block. */ +#define PSA_AEAD_UPDATE_OUTPUT_SIZE(key_type, alg, input_length) \ + (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 ? \ + PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ + PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type), (input_length)) : \ + (input_length) : \ + 0) + +/** A sufficient output buffer size for psa_aead_update(), for any of the + * supported key types and AEAD algorithms. + * + * If the size of the output buffer is at least this large, it is guaranteed + * that psa_aead_update() will not fail due to an insufficient buffer size. + * + * See also #PSA_AEAD_UPDATE_OUTPUT_SIZE(\p key_type, \p alg, \p input_length). + * + * \param input_length Size of the input in bytes. + */ +#define PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(input_length) \ + (PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE, (input_length))) + +/** A sufficient ciphertext buffer size for psa_aead_finish(). + * + * If the size of the ciphertext buffer is at least this large, it is + * guaranteed that psa_aead_finish() will not fail due to an + * insufficient ciphertext buffer size. The actual size of the output may + * be smaller in any given call. + * + * See also #PSA_AEAD_FINISH_OUTPUT_MAX_SIZE. + * + * \param key_type A symmetric key type that is + compatible with algorithm \p alg. + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \return A sufficient ciphertext buffer size for the + * specified algorithm. + * If the key type or AEAD algorithm is not + * recognized, or the parameters are incompatible, + * return 0. + */ +#define PSA_AEAD_FINISH_OUTPUT_SIZE(key_type, alg) \ + (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 && \ + PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ + PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) : \ + 0) + +/** A sufficient ciphertext buffer size for psa_aead_finish(), for any of the + * supported key types and AEAD algorithms. + * + * See also #PSA_AEAD_FINISH_OUTPUT_SIZE(\p key_type, \p alg). + */ +#define PSA_AEAD_FINISH_OUTPUT_MAX_SIZE (PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE) + +/** A sufficient plaintext buffer size for psa_aead_verify(). + * + * If the size of the plaintext buffer is at least this large, it is + * guaranteed that psa_aead_verify() will not fail due to an + * insufficient plaintext buffer size. The actual size of the output may + * be smaller in any given call. + * + * See also #PSA_AEAD_VERIFY_OUTPUT_MAX_SIZE. + * + * \param key_type A symmetric key type that is + * compatible with algorithm \p alg. + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \return A sufficient plaintext buffer size for the + * specified algorithm. + * If the key type or AEAD algorithm is not + * recognized, or the parameters are incompatible, + * return 0. + */ +#define PSA_AEAD_VERIFY_OUTPUT_SIZE(key_type, alg) \ + (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 && \ + PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ + PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) : \ + 0) + +/** A sufficient plaintext buffer size for psa_aead_verify(), for any of the + * supported key types and AEAD algorithms. + * + * See also #PSA_AEAD_VERIFY_OUTPUT_SIZE(\p key_type, \p alg). + */ +#define PSA_AEAD_VERIFY_OUTPUT_MAX_SIZE (PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE) + +#define PSA_RSA_MINIMUM_PADDING_SIZE(alg) \ + (PSA_ALG_IS_RSA_OAEP(alg) ? \ + 2 * PSA_HASH_LENGTH(PSA_ALG_RSA_OAEP_GET_HASH(alg)) + 1 : \ + 11 /*PKCS#1v1.5*/) + +/** + * \brief ECDSA signature size for a given curve bit size + * + * \param curve_bits Curve size in bits. + * \return Signature size in bytes. + * + * \note This macro returns a compile-time constant if its argument is one. + */ +#define PSA_ECDSA_SIGNATURE_SIZE(curve_bits) \ + (PSA_BITS_TO_BYTES(curve_bits) * 2) + +/** Sufficient signature buffer size for psa_sign_hash(). + * + * This macro returns a sufficient buffer size for a signature using a key + * of the specified type and size, with the specified algorithm. + * Note that the actual size of the signature may be smaller + * (some algorithms produce a variable-size signature). + * + * \warning This function may call its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \param key_type An asymmetric key type (this may indifferently be a + * key pair type or a public key type). + * \param key_bits The size of the key in bits. + * \param alg The signature algorithm. + * + * \return If the parameters are valid and supported, return + * a buffer size in bytes that guarantees that + * psa_sign_hash() will not fail with + * #PSA_ERROR_BUFFER_TOO_SMALL. + * If the parameters are a valid combination that is not supported, + * return either a sensible size or 0. + * If the parameters are not valid, the + * return value is unspecified. + */ +#define PSA_SIGN_OUTPUT_SIZE(key_type, key_bits, alg) \ + (PSA_KEY_TYPE_IS_RSA(key_type) ? ((void) alg, PSA_BITS_TO_BYTES(key_bits)) : \ + PSA_KEY_TYPE_IS_ECC(key_type) ? PSA_ECDSA_SIGNATURE_SIZE(key_bits) : \ + ((void) alg, 0)) + +#define PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE \ + PSA_ECDSA_SIGNATURE_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) + +/** \def PSA_SIGNATURE_MAX_SIZE + * + * Maximum size of an asymmetric signature. + * + * This macro expands to a compile-time constant integer. This value + * is the maximum size of a signature in bytes. + */ +#define PSA_SIGNATURE_MAX_SIZE \ + (PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) > PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE ? \ + PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) : \ + PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE) + +/** Sufficient output buffer size for psa_asymmetric_encrypt(). + * + * This macro returns a sufficient buffer size for a ciphertext produced using + * a key of the specified type and size, with the specified algorithm. + * Note that the actual size of the ciphertext may be smaller, depending + * on the algorithm. + * + * \warning This function may call its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \param key_type An asymmetric key type (this may indifferently be a + * key pair type or a public key type). + * \param key_bits The size of the key in bits. + * \param alg The asymmetric encryption algorithm. + * + * \return If the parameters are valid and supported, return + * a buffer size in bytes that guarantees that + * psa_asymmetric_encrypt() will not fail with + * #PSA_ERROR_BUFFER_TOO_SMALL. + * If the parameters are a valid combination that is not supported, + * return either a sensible size or 0. + * If the parameters are not valid, the + * return value is unspecified. + */ +#define PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(key_type, key_bits, alg) \ + (PSA_KEY_TYPE_IS_RSA(key_type) ? \ + ((void) alg, PSA_BITS_TO_BYTES(key_bits)) : \ + 0) + +/** A sufficient output buffer size for psa_asymmetric_encrypt(), for any + * supported asymmetric encryption. + * + * See also #PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(\p key_type, \p key_bits, \p alg). + */ +/* This macro assumes that RSA is the only supported asymmetric encryption. */ +#define PSA_ASYMMETRIC_ENCRYPT_OUTPUT_MAX_SIZE \ + (PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS)) + +/** Sufficient output buffer size for psa_asymmetric_decrypt(). + * + * This macro returns a sufficient buffer size for a plaintext produced using + * a key of the specified type and size, with the specified algorithm. + * Note that the actual size of the plaintext may be smaller, depending + * on the algorithm. + * + * \warning This function may call its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \param key_type An asymmetric key type (this may indifferently be a + * key pair type or a public key type). + * \param key_bits The size of the key in bits. + * \param alg The asymmetric encryption algorithm. + * + * \return If the parameters are valid and supported, return + * a buffer size in bytes that guarantees that + * psa_asymmetric_decrypt() will not fail with + * #PSA_ERROR_BUFFER_TOO_SMALL. + * If the parameters are a valid combination that is not supported, + * return either a sensible size or 0. + * If the parameters are not valid, the + * return value is unspecified. + */ +#define PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(key_type, key_bits, alg) \ + (PSA_KEY_TYPE_IS_RSA(key_type) ? \ + PSA_BITS_TO_BYTES(key_bits) - PSA_RSA_MINIMUM_PADDING_SIZE(alg) : \ + 0) + +/** A sufficient output buffer size for psa_asymmetric_decrypt(), for any + * supported asymmetric decryption. + * + * This macro assumes that RSA is the only supported asymmetric encryption. + * + * See also #PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(\p key_type, \p key_bits, \p alg). + */ +#define PSA_ASYMMETRIC_DECRYPT_OUTPUT_MAX_SIZE \ + (PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS)) + +/* Maximum size of the ASN.1 encoding of an INTEGER with the specified + * number of bits. + * + * This definition assumes that bits <= 2^19 - 9 so that the length field + * is at most 3 bytes. The length of the encoding is the length of the + * bit string padded to a whole number of bytes plus: + * - 1 type byte; + * - 1 to 3 length bytes; + * - 0 to 1 bytes of leading 0 due to the sign bit. + */ +#define PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(bits) \ + ((bits) / 8 + 5) + +/* Maximum size of the export encoding of an RSA public key. + * Assumes that the public exponent is less than 2^32. + * + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER } -- e + * + * - 4 bytes of SEQUENCE overhead; + * - n : INTEGER; + * - 7 bytes for the public exponent. + */ +#define PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) \ + (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) + 11) + +/* Maximum size of the export encoding of an RSA key pair. + * Assumes that the public exponent is less than 2^32 and that the size + * difference between the two primes is at most 1 bit. + * + * RSAPrivateKey ::= SEQUENCE { + * version Version, -- 0 + * modulus INTEGER, -- N-bit + * publicExponent INTEGER, -- 32-bit + * privateExponent INTEGER, -- N-bit + * prime1 INTEGER, -- N/2-bit + * prime2 INTEGER, -- N/2-bit + * exponent1 INTEGER, -- N/2-bit + * exponent2 INTEGER, -- N/2-bit + * coefficient INTEGER, -- N/2-bit + * } + * + * - 4 bytes of SEQUENCE overhead; + * - 3 bytes of version; + * - 7 half-size INTEGERs plus 2 full-size INTEGERs, + * overapproximated as 9 half-size INTEGERS; + * - 7 bytes for the public exponent. + */ +#define PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(key_bits) \ + (9 * PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE((key_bits) / 2 + 1) + 14) + +/* Maximum size of the export encoding of a DSA public key. + * + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } -- contains DSAPublicKey + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters Dss-Params } -- SEQUENCE of 3 INTEGERs + * DSAPublicKey ::= INTEGER -- public key, Y + * + * - 3 * 4 bytes of SEQUENCE overhead; + * - 1 + 1 + 7 bytes of algorithm (DSA OID); + * - 4 bytes of BIT STRING overhead; + * - 3 full-size INTEGERs (p, g, y); + * - 1 + 1 + 32 bytes for 1 sub-size INTEGER (q <= 256 bits). + */ +#define PSA_KEY_EXPORT_DSA_PUBLIC_KEY_MAX_SIZE(key_bits) \ + (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) * 3 + 59) + +/* Maximum size of the export encoding of a DSA key pair. + * + * DSAPrivateKey ::= SEQUENCE { + * version Version, -- 0 + * prime INTEGER, -- p + * subprime INTEGER, -- q + * generator INTEGER, -- g + * public INTEGER, -- y + * private INTEGER, -- x + * } + * + * - 4 bytes of SEQUENCE overhead; + * - 3 bytes of version; + * - 3 full-size INTEGERs (p, g, y); + * - 2 * (1 + 1 + 32) bytes for 2 sub-size INTEGERs (q, x <= 256 bits). + */ +#define PSA_KEY_EXPORT_DSA_KEY_PAIR_MAX_SIZE(key_bits) \ + (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) * 3 + 75) + +/* Maximum size of the export encoding of an ECC public key. + * + * The representation of an ECC public key is: + * - The byte 0x04; + * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; + * - `y_P` as a `ceiling(m/8)`-byte string, big-endian; + * - where m is the bit size associated with the curve. + * + * - 1 byte + 2 * point size. + */ +#define PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) \ + (2 * PSA_BITS_TO_BYTES(key_bits) + 1) + +/* Maximum size of the export encoding of an ECC key pair. + * + * An ECC key pair is represented by the secret value. + */ +#define PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(key_bits) \ + (PSA_BITS_TO_BYTES(key_bits)) + +/** Sufficient output buffer size for psa_export_key() or + * psa_export_public_key(). + * + * This macro returns a compile-time constant if its arguments are + * compile-time constants. + * + * \warning This macro may evaluate its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * The following code illustrates how to allocate enough memory to export + * a key by querying the key type and size at runtime. + * \code{c} + * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + * psa_status_t status; + * status = psa_get_key_attributes(key, &attributes); + * if (status != PSA_SUCCESS) handle_error(...); + * psa_key_type_t key_type = psa_get_key_type(&attributes); + * size_t key_bits = psa_get_key_bits(&attributes); + * size_t buffer_size = PSA_EXPORT_KEY_OUTPUT_SIZE(key_type, key_bits); + * psa_reset_key_attributes(&attributes); + * uint8_t *buffer = malloc(buffer_size); + * if (buffer == NULL) handle_error(...); + * size_t buffer_length; + * status = psa_export_key(key, buffer, buffer_size, &buffer_length); + * if (status != PSA_SUCCESS) handle_error(...); + * \endcode + * + * \param key_type A supported key type. + * \param key_bits The size of the key in bits. + * + * \return If the parameters are valid and supported, return + * a buffer size in bytes that guarantees that + * psa_export_key() or psa_export_public_key() will not fail with + * #PSA_ERROR_BUFFER_TOO_SMALL. + * If the parameters are a valid combination that is not supported, + * return either a sensible size or 0. + * If the parameters are not valid, the return value is unspecified. + */ +#define PSA_EXPORT_KEY_OUTPUT_SIZE(key_type, key_bits) \ + (PSA_KEY_TYPE_IS_UNSTRUCTURED(key_type) ? PSA_BITS_TO_BYTES(key_bits) : \ + (key_type) == PSA_KEY_TYPE_RSA_KEY_PAIR ? PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(key_bits) : \ + (key_type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY ? PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \ + (key_type) == PSA_KEY_TYPE_DSA_KEY_PAIR ? PSA_KEY_EXPORT_DSA_KEY_PAIR_MAX_SIZE(key_bits) : \ + (key_type) == PSA_KEY_TYPE_DSA_PUBLIC_KEY ? PSA_KEY_EXPORT_DSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \ + PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type) ? PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(key_bits) : \ + PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(key_type) ? PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) : \ + 0) + +/** Sufficient output buffer size for psa_export_public_key(). + * + * This macro returns a compile-time constant if its arguments are + * compile-time constants. + * + * \warning This macro may evaluate its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * The following code illustrates how to allocate enough memory to export + * a public key by querying the key type and size at runtime. + * \code{c} + * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + * psa_status_t status; + * status = psa_get_key_attributes(key, &attributes); + * if (status != PSA_SUCCESS) handle_error(...); + * psa_key_type_t key_type = psa_get_key_type(&attributes); + * size_t key_bits = psa_get_key_bits(&attributes); + * size_t buffer_size = PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(key_type, key_bits); + * psa_reset_key_attributes(&attributes); + * uint8_t *buffer = malloc(buffer_size); + * if (buffer == NULL) handle_error(...); + * size_t buffer_length; + * status = psa_export_public_key(key, buffer, buffer_size, &buffer_length); + * if (status != PSA_SUCCESS) handle_error(...); + * \endcode + * + * \param key_type A public key or key pair key type. + * \param key_bits The size of the key in bits. + * + * \return If the parameters are valid and supported, return + * a buffer size in bytes that guarantees that + * psa_export_public_key() will not fail with + * #PSA_ERROR_BUFFER_TOO_SMALL. + * If the parameters are a valid combination that is not + * supported, return either a sensible size or 0. + * If the parameters are not valid, + * the return value is unspecified. + * + * If the parameters are valid and supported, + * return the same result as + * #PSA_EXPORT_KEY_OUTPUT_SIZE( + * \p #PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(\p key_type), + * \p key_bits). + */ +#define PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(key_type, key_bits) \ + (PSA_KEY_TYPE_IS_RSA(key_type) ? PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \ + PSA_KEY_TYPE_IS_ECC(key_type) ? PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) : \ + 0) + +/** Sufficient buffer size for exporting any asymmetric key pair. + * + * This macro expands to a compile-time constant integer. This value is + * a sufficient buffer size when calling psa_export_key() to export any + * asymmetric key pair, regardless of the exact key type and key size. + * + * See also #PSA_EXPORT_KEY_OUTPUT_SIZE(\p key_type, \p key_bits). + */ +#define PSA_EXPORT_KEY_PAIR_MAX_SIZE \ + (PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS) > \ + PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) ? \ + PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS) : \ + PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)) + +/** Sufficient buffer size for exporting any asymmetric public key. + * + * This macro expands to a compile-time constant integer. This value is + * a sufficient buffer size when calling psa_export_key() or + * psa_export_public_key() to export any asymmetric public key, + * regardless of the exact key type and key size. + * + * See also #PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(\p key_type, \p key_bits). + */ +#define PSA_EXPORT_PUBLIC_KEY_MAX_SIZE \ + (PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS) > \ + PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) ? \ + PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS) : \ + PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)) + +/** Sufficient output buffer size for psa_raw_key_agreement(). + * + * This macro returns a compile-time constant if its arguments are + * compile-time constants. + * + * \warning This macro may evaluate its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * See also #PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE. + * + * \param key_type A supported key type. + * \param key_bits The size of the key in bits. + * + * \return If the parameters are valid and supported, return + * a buffer size in bytes that guarantees that + * psa_raw_key_agreement() will not fail with + * #PSA_ERROR_BUFFER_TOO_SMALL. + * If the parameters are a valid combination that + * is not supported, return either a sensible size or 0. + * If the parameters are not valid, + * the return value is unspecified. + */ +/* FFDH is not yet supported in PSA. */ +#define PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(key_type, key_bits) \ + (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type) ? \ + PSA_BITS_TO_BYTES(key_bits) : \ + 0) + +/** Maximum size of the output from psa_raw_key_agreement(). + * + * This macro expands to a compile-time constant integer. This value is the + * maximum size of the output any raw key agreement algorithm, in bytes. + * + * See also #PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(\p key_type, \p key_bits). + */ +#define PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE \ + (PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)) + +/** The default IV size for a cipher algorithm, in bytes. + * + * The IV that is generated as part of a call to #psa_cipher_encrypt() is always + * the default IV length for the algorithm. + * + * This macro can be used to allocate a buffer of sufficient size to + * store the IV output from #psa_cipher_generate_iv() when using + * a multi-part cipher operation. + * + * See also #PSA_CIPHER_IV_MAX_SIZE. + * + * \warning This macro may evaluate its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \param key_type A symmetric key type that is compatible with algorithm \p alg. + * + * \param alg A cipher algorithm (\c PSA_ALG_XXX value such that #PSA_ALG_IS_CIPHER(\p alg) is true). + * + * \return The default IV size for the specified key type and algorithm. + * If the algorithm does not use an IV, return 0. + * If the key type or cipher algorithm is not recognized, + * or the parameters are incompatible, return 0. + */ +#define PSA_CIPHER_IV_LENGTH(key_type, alg) \ + (PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) > 1 && \ + ((alg) == PSA_ALG_CTR || \ + (alg) == PSA_ALG_CFB || \ + (alg) == PSA_ALG_OFB || \ + (alg) == PSA_ALG_XTS || \ + (alg) == PSA_ALG_CBC_NO_PADDING || \ + (alg) == PSA_ALG_CBC_PKCS7) ? PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) : \ + (key_type) == PSA_KEY_TYPE_CHACHA20 && \ + (alg) == PSA_ALG_STREAM_CIPHER ? 12 : \ + (alg) == PSA_ALG_CCM_STAR_NO_TAG ? 13 : \ + 0) + +/** The maximum IV size for all supported cipher algorithms, in bytes. + * + * See also #PSA_CIPHER_IV_LENGTH(). + */ +#define PSA_CIPHER_IV_MAX_SIZE 16 + +/** The maximum size of the output of psa_cipher_encrypt(), in bytes. + * + * If the size of the output buffer is at least this large, it is guaranteed + * that psa_cipher_encrypt() will not fail due to an insufficient buffer size. + * Depending on the algorithm, the actual size of the output might be smaller. + * + * See also #PSA_CIPHER_ENCRYPT_OUTPUT_MAX_SIZE(\p input_length). + * + * \warning This macro may evaluate its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \param key_type A symmetric key type that is compatible with algorithm + * alg. + * \param alg A cipher algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * \param input_length Size of the input in bytes. + * + * \return A sufficient output size for the specified key type and + * algorithm. If the key type or cipher algorithm is not + * recognized, or the parameters are incompatible, + * return 0. + */ +#define PSA_CIPHER_ENCRYPT_OUTPUT_SIZE(key_type, alg, input_length) \ + (alg == PSA_ALG_CBC_PKCS7 ? \ + (PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) != 0 ? \ + PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type), \ + (input_length) + 1) + \ + PSA_CIPHER_IV_LENGTH((key_type), (alg)) : 0) : \ + (PSA_ALG_IS_CIPHER(alg) ? \ + (input_length) + PSA_CIPHER_IV_LENGTH((key_type), (alg)) : \ + 0)) + +/** A sufficient output buffer size for psa_cipher_encrypt(), for any of the + * supported key types and cipher algorithms. + * + * If the size of the output buffer is at least this large, it is guaranteed + * that psa_cipher_encrypt() will not fail due to an insufficient buffer size. + * + * See also #PSA_CIPHER_ENCRYPT_OUTPUT_SIZE(\p key_type, \p alg, \p input_length). + * + * \param input_length Size of the input in bytes. + * + */ +#define PSA_CIPHER_ENCRYPT_OUTPUT_MAX_SIZE(input_length) \ + (PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE, \ + (input_length) + 1) + \ + PSA_CIPHER_IV_MAX_SIZE) + +/** The maximum size of the output of psa_cipher_decrypt(), in bytes. + * + * If the size of the output buffer is at least this large, it is guaranteed + * that psa_cipher_decrypt() will not fail due to an insufficient buffer size. + * Depending on the algorithm, the actual size of the output might be smaller. + * + * See also #PSA_CIPHER_DECRYPT_OUTPUT_MAX_SIZE(\p input_length). + * + * \param key_type A symmetric key type that is compatible with algorithm + * alg. + * \param alg A cipher algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * \param input_length Size of the input in bytes. + * + * \return A sufficient output size for the specified key type and + * algorithm. If the key type or cipher algorithm is not + * recognized, or the parameters are incompatible, + * return 0. + */ +#define PSA_CIPHER_DECRYPT_OUTPUT_SIZE(key_type, alg, input_length) \ + (PSA_ALG_IS_CIPHER(alg) && \ + ((key_type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_SYMMETRIC ? \ + (input_length) : \ + 0) + +/** A sufficient output buffer size for psa_cipher_decrypt(), for any of the + * supported key types and cipher algorithms. + * + * If the size of the output buffer is at least this large, it is guaranteed + * that psa_cipher_decrypt() will not fail due to an insufficient buffer size. + * + * See also #PSA_CIPHER_DECRYPT_OUTPUT_SIZE(\p key_type, \p alg, \p input_length). + * + * \param input_length Size of the input in bytes. + */ +#define PSA_CIPHER_DECRYPT_OUTPUT_MAX_SIZE(input_length) \ + (input_length) + +/** A sufficient output buffer size for psa_cipher_update(). + * + * If the size of the output buffer is at least this large, it is guaranteed + * that psa_cipher_update() will not fail due to an insufficient buffer size. + * The actual size of the output might be smaller in any given call. + * + * See also #PSA_CIPHER_UPDATE_OUTPUT_MAX_SIZE(\p input_length). + * + * \param key_type A symmetric key type that is compatible with algorithm + * alg. + * \param alg A cipher algorithm (PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * \param input_length Size of the input in bytes. + * + * \return A sufficient output size for the specified key type and + * algorithm. If the key type or cipher algorithm is not + * recognized, or the parameters are incompatible, return 0. + */ +#define PSA_CIPHER_UPDATE_OUTPUT_SIZE(key_type, alg, input_length) \ + (PSA_ALG_IS_CIPHER(alg) ? \ + (PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) != 0 ? \ + (((alg) == PSA_ALG_CBC_PKCS7 || \ + (alg) == PSA_ALG_CBC_NO_PADDING || \ + (alg) == PSA_ALG_ECB_NO_PADDING) ? \ + PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type), \ + input_length) : \ + (input_length)) : 0) : \ + 0) + +/** A sufficient output buffer size for psa_cipher_update(), for any of the + * supported key types and cipher algorithms. + * + * If the size of the output buffer is at least this large, it is guaranteed + * that psa_cipher_update() will not fail due to an insufficient buffer size. + * + * See also #PSA_CIPHER_UPDATE_OUTPUT_SIZE(\p key_type, \p alg, \p input_length). + * + * \param input_length Size of the input in bytes. + */ +#define PSA_CIPHER_UPDATE_OUTPUT_MAX_SIZE(input_length) \ + (PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE, input_length)) + +/** A sufficient ciphertext buffer size for psa_cipher_finish(). + * + * If the size of the ciphertext buffer is at least this large, it is + * guaranteed that psa_cipher_finish() will not fail due to an insufficient + * ciphertext buffer size. The actual size of the output might be smaller in + * any given call. + * + * See also #PSA_CIPHER_FINISH_OUTPUT_MAX_SIZE(). + * + * \param key_type A symmetric key type that is compatible with algorithm + * alg. + * \param alg A cipher algorithm (PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * \return A sufficient output size for the specified key type and + * algorithm. If the key type or cipher algorithm is not + * recognized, or the parameters are incompatible, return 0. + */ +#define PSA_CIPHER_FINISH_OUTPUT_SIZE(key_type, alg) \ + (PSA_ALG_IS_CIPHER(alg) ? \ + (alg == PSA_ALG_CBC_PKCS7 ? \ + PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) : \ + 0) : \ + 0) + +/** A sufficient ciphertext buffer size for psa_cipher_finish(), for any of the + * supported key types and cipher algorithms. + * + * See also #PSA_CIPHER_FINISH_OUTPUT_SIZE(\p key_type, \p alg). + */ +#define PSA_CIPHER_FINISH_OUTPUT_MAX_SIZE \ + (PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE) + +#endif /* PSA_CRYPTO_SIZES_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_struct.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_struct.h new file mode 100644 index 0000000..934bc17 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_struct.h @@ -0,0 +1,558 @@ +/** + * \file psa/crypto_struct.h + * + * \brief PSA cryptography module: Mbed TLS structured type implementations + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + * + * This file contains the definitions of some data structures with + * implementation-specific definitions. + * + * In implementations with isolation between the application and the + * cryptography module, it is expected that the front-end and the back-end + * would have different versions of this file. + * + *

Design notes about multipart operation structures

+ * + * For multipart operations without driver delegation support, each multipart + * operation structure contains a `psa_algorithm_t alg` field which indicates + * which specific algorithm the structure is for. When the structure is not in + * use, `alg` is 0. Most of the structure consists of a union which is + * discriminated by `alg`. + * + * For multipart operations with driver delegation support, each multipart + * operation structure contains an `unsigned int id` field indicating which + * driver got assigned to do the operation. When the structure is not in use, + * 'id' is 0. The structure contains also a driver context which is the union + * of the contexts of all drivers able to handle the type of multipart + * operation. + * + * Note that when `alg` or `id` is 0, the content of other fields is undefined. + * In particular, it is not guaranteed that a freshly-initialized structure + * is all-zero: we initialize structures to something like `{0, 0}`, which + * is only guaranteed to initializes the first member of the union; + * GCC and Clang initialize the whole structure to 0 (at the time of writing), + * but MSVC and CompCert don't. + * + * In Mbed Crypto, multipart operation structures live independently from + * the key. This allows Mbed Crypto to free the key objects when destroying + * a key slot. If a multipart operation needs to remember the key after + * the setup function returns, the operation structure needs to contain a + * copy of the key. + */ +/* + * 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 PSA_CRYPTO_STRUCT_H +#define PSA_CRYPTO_STRUCT_H +#include "mbedtls/private_access.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Include the Mbed TLS configuration file, the way Mbed TLS does it + * in each of its header files. */ +#include "mbedtls/build_info.h" + +#include "mbedtls/cmac.h" +#include "mbedtls/gcm.h" +#include "mbedtls/ccm.h" +#include "mbedtls/chachapoly.h" + +/* Include the context definition for the compiled-in drivers for the primitive + * algorithms. */ +#include "psa/crypto_driver_contexts_primitives.h" + +struct psa_hash_operation_s { + /** Unique ID indicating which driver got assigned to do the + * operation. Since driver contexts are driver-specific, swapping + * drivers halfway through the operation is not supported. + * ID values are auto-generated in psa_driver_wrappers.h. + * ID value zero means the context is not valid or not assigned to + * any driver (i.e. the driver context is not active, in use). */ + unsigned int MBEDTLS_PRIVATE(id); + psa_driver_hash_context_t MBEDTLS_PRIVATE(ctx); +}; + +#define PSA_HASH_OPERATION_INIT { 0, { 0 } } +static inline struct psa_hash_operation_s psa_hash_operation_init(void) +{ + const struct psa_hash_operation_s v = PSA_HASH_OPERATION_INIT; + return v; +} + +struct psa_cipher_operation_s { + /** Unique ID indicating which driver got assigned to do the + * operation. Since driver contexts are driver-specific, swapping + * drivers halfway through the operation is not supported. + * ID values are auto-generated in psa_crypto_driver_wrappers.h + * ID value zero means the context is not valid or not assigned to + * any driver (i.e. none of the driver contexts are active). */ + unsigned int MBEDTLS_PRIVATE(id); + + unsigned int MBEDTLS_PRIVATE(iv_required) : 1; + unsigned int MBEDTLS_PRIVATE(iv_set) : 1; + + uint8_t MBEDTLS_PRIVATE(default_iv_length); + + psa_driver_cipher_context_t MBEDTLS_PRIVATE(ctx); +}; + +#define PSA_CIPHER_OPERATION_INIT { 0, 0, 0, 0, { 0 } } +static inline struct psa_cipher_operation_s psa_cipher_operation_init(void) +{ + const struct psa_cipher_operation_s v = PSA_CIPHER_OPERATION_INIT; + return v; +} + +/* Include the context definition for the compiled-in drivers for the composite + * algorithms. */ +#include "psa/crypto_driver_contexts_composites.h" + +struct psa_mac_operation_s { + /** Unique ID indicating which driver got assigned to do the + * operation. Since driver contexts are driver-specific, swapping + * drivers halfway through the operation is not supported. + * ID values are auto-generated in psa_driver_wrappers.h + * ID value zero means the context is not valid or not assigned to + * any driver (i.e. none of the driver contexts are active). */ + unsigned int MBEDTLS_PRIVATE(id); + uint8_t MBEDTLS_PRIVATE(mac_size); + unsigned int MBEDTLS_PRIVATE(is_sign) : 1; + psa_driver_mac_context_t MBEDTLS_PRIVATE(ctx); +}; + +#define PSA_MAC_OPERATION_INIT { 0, 0, 0, { 0 } } +static inline struct psa_mac_operation_s psa_mac_operation_init(void) +{ + const struct psa_mac_operation_s v = PSA_MAC_OPERATION_INIT; + return v; +} + +struct psa_aead_operation_s { + + /** Unique ID indicating which driver got assigned to do the + * operation. Since driver contexts are driver-specific, swapping + * drivers halfway through the operation is not supported. + * ID values are auto-generated in psa_crypto_driver_wrappers.h + * ID value zero means the context is not valid or not assigned to + * any driver (i.e. none of the driver contexts are active). */ + unsigned int MBEDTLS_PRIVATE(id); + + psa_algorithm_t MBEDTLS_PRIVATE(alg); + psa_key_type_t MBEDTLS_PRIVATE(key_type); + + size_t MBEDTLS_PRIVATE(ad_remaining); + size_t MBEDTLS_PRIVATE(body_remaining); + + unsigned int MBEDTLS_PRIVATE(nonce_set) : 1; + unsigned int MBEDTLS_PRIVATE(lengths_set) : 1; + unsigned int MBEDTLS_PRIVATE(ad_started) : 1; + unsigned int MBEDTLS_PRIVATE(body_started) : 1; + unsigned int MBEDTLS_PRIVATE(is_encrypt) : 1; + + psa_driver_aead_context_t MBEDTLS_PRIVATE(ctx); +}; + +#define PSA_AEAD_OPERATION_INIT { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0 } } +static inline struct psa_aead_operation_s psa_aead_operation_init(void) +{ + const struct psa_aead_operation_s v = PSA_AEAD_OPERATION_INIT; + return v; +} + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND) +typedef struct { + uint8_t *MBEDTLS_PRIVATE(info); + size_t MBEDTLS_PRIVATE(info_length); +#if PSA_HASH_MAX_SIZE > 0xff +#error "PSA_HASH_MAX_SIZE does not fit in uint8_t" +#endif + uint8_t MBEDTLS_PRIVATE(offset_in_block); + uint8_t MBEDTLS_PRIVATE(block_number); + unsigned int MBEDTLS_PRIVATE(state) : 2; + unsigned int MBEDTLS_PRIVATE(info_set) : 1; + uint8_t MBEDTLS_PRIVATE(output_block)[PSA_HASH_MAX_SIZE]; + uint8_t MBEDTLS_PRIVATE(prk)[PSA_HASH_MAX_SIZE]; + struct psa_mac_operation_s MBEDTLS_PRIVATE(hmac); +} psa_hkdf_key_derivation_t; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF || + MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT || + MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) +typedef struct { + uint8_t MBEDTLS_PRIVATE(data)[PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE]; +} psa_tls12_ecjpake_to_pms_t; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS */ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) +typedef enum { + PSA_TLS12_PRF_STATE_INIT, /* no input provided */ + PSA_TLS12_PRF_STATE_SEED_SET, /* seed has been set */ + PSA_TLS12_PRF_STATE_OTHER_KEY_SET, /* other key has been set - optional */ + PSA_TLS12_PRF_STATE_KEY_SET, /* key has been set */ + PSA_TLS12_PRF_STATE_LABEL_SET, /* label has been set */ + PSA_TLS12_PRF_STATE_OUTPUT /* output has been started */ +} psa_tls12_prf_key_derivation_state_t; + +typedef struct psa_tls12_prf_key_derivation_s { +#if PSA_HASH_MAX_SIZE > 0xff +#error "PSA_HASH_MAX_SIZE does not fit in uint8_t" +#endif + + /* Indicates how many bytes in the current HMAC block have + * not yet been read by the user. */ + uint8_t MBEDTLS_PRIVATE(left_in_block); + + /* The 1-based number of the block. */ + uint8_t MBEDTLS_PRIVATE(block_number); + + psa_tls12_prf_key_derivation_state_t MBEDTLS_PRIVATE(state); + + uint8_t *MBEDTLS_PRIVATE(secret); + size_t MBEDTLS_PRIVATE(secret_length); + uint8_t *MBEDTLS_PRIVATE(seed); + size_t MBEDTLS_PRIVATE(seed_length); + uint8_t *MBEDTLS_PRIVATE(label); + size_t MBEDTLS_PRIVATE(label_length); +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) + uint8_t *MBEDTLS_PRIVATE(other_secret); + size_t MBEDTLS_PRIVATE(other_secret_length); +#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ + + uint8_t MBEDTLS_PRIVATE(Ai)[PSA_HASH_MAX_SIZE]; + + /* `HMAC_hash( prk, A( i ) + seed )` in the notation of RFC 5246, Sect. 5. */ + uint8_t MBEDTLS_PRIVATE(output_block)[PSA_HASH_MAX_SIZE]; +} psa_tls12_prf_key_derivation_t; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || + * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ + +struct psa_key_derivation_s { + psa_algorithm_t MBEDTLS_PRIVATE(alg); + unsigned int MBEDTLS_PRIVATE(can_output_key) : 1; + size_t MBEDTLS_PRIVATE(capacity); + union { + /* Make the union non-empty even with no supported algorithms. */ + uint8_t MBEDTLS_PRIVATE(dummy); +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND) + psa_hkdf_key_derivation_t MBEDTLS_PRIVATE(hkdf); +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) + psa_tls12_prf_key_derivation_t MBEDTLS_PRIVATE(tls12_prf); +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) + psa_tls12_ecjpake_to_pms_t MBEDTLS_PRIVATE(tls12_ecjpake_to_pms); +#endif + } MBEDTLS_PRIVATE(ctx); +}; + +/* This only zeroes out the first byte in the union, the rest is unspecified. */ +#define PSA_KEY_DERIVATION_OPERATION_INIT { 0, 0, 0, { 0 } } +static inline struct psa_key_derivation_s psa_key_derivation_operation_init( + void) +{ + const struct psa_key_derivation_s v = PSA_KEY_DERIVATION_OPERATION_INIT; + return v; +} + +struct psa_key_policy_s { + psa_key_usage_t MBEDTLS_PRIVATE(usage); + psa_algorithm_t MBEDTLS_PRIVATE(alg); + psa_algorithm_t MBEDTLS_PRIVATE(alg2); +}; +typedef struct psa_key_policy_s psa_key_policy_t; + +#define PSA_KEY_POLICY_INIT { 0, 0, 0 } +static inline struct psa_key_policy_s psa_key_policy_init(void) +{ + const struct psa_key_policy_s v = PSA_KEY_POLICY_INIT; + return v; +} + +/* The type used internally for key sizes. + * Public interfaces use size_t, but internally we use a smaller type. */ +typedef uint16_t psa_key_bits_t; +/* The maximum value of the type used to represent bit-sizes. + * This is used to mark an invalid key size. */ +#define PSA_KEY_BITS_TOO_LARGE ((psa_key_bits_t) -1) +/* The maximum size of a key in bits. + * Currently defined as the maximum that can be represented, rounded down + * to a whole number of bytes. + * This is an uncast value so that it can be used in preprocessor + * conditionals. */ +#define PSA_MAX_KEY_BITS 0xfff8 + +/** A mask of flags that can be stored in key attributes. + * + * This type is also used internally to store flags in slots. Internal + * flags are defined in library/psa_crypto_core.h. Internal flags may have + * the same value as external flags if they are properly handled during + * key creation and in psa_get_key_attributes. + */ +typedef uint16_t psa_key_attributes_flag_t; + +#define MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER \ + ((psa_key_attributes_flag_t) 0x0001) + +/* A mask of key attribute flags used externally only. + * Only meant for internal checks inside the library. */ +#define MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY ( \ + MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER | \ + 0) + +/* A mask of key attribute flags used both internally and externally. + * Currently there aren't any. */ +#define MBEDTLS_PSA_KA_MASK_DUAL_USE ( \ + 0) + +typedef struct { + psa_key_type_t MBEDTLS_PRIVATE(type); + psa_key_bits_t MBEDTLS_PRIVATE(bits); + psa_key_lifetime_t MBEDTLS_PRIVATE(lifetime); + mbedtls_svc_key_id_t MBEDTLS_PRIVATE(id); + psa_key_policy_t MBEDTLS_PRIVATE(policy); + psa_key_attributes_flag_t MBEDTLS_PRIVATE(flags); +} psa_core_key_attributes_t; + +#define PSA_CORE_KEY_ATTRIBUTES_INIT { PSA_KEY_TYPE_NONE, 0, \ + PSA_KEY_LIFETIME_VOLATILE, \ + MBEDTLS_SVC_KEY_ID_INIT, \ + PSA_KEY_POLICY_INIT, 0 } + +struct psa_key_attributes_s { + psa_core_key_attributes_t MBEDTLS_PRIVATE(core); +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + psa_key_slot_number_t MBEDTLS_PRIVATE(slot_number); +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + void *MBEDTLS_PRIVATE(domain_parameters); + size_t MBEDTLS_PRIVATE(domain_parameters_size); +}; + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +#define PSA_KEY_ATTRIBUTES_INIT { PSA_CORE_KEY_ATTRIBUTES_INIT, 0, NULL, 0 } +#else +#define PSA_KEY_ATTRIBUTES_INIT { PSA_CORE_KEY_ATTRIBUTES_INIT, NULL, 0 } +#endif + +static inline struct psa_key_attributes_s psa_key_attributes_init(void) +{ + const struct psa_key_attributes_s v = PSA_KEY_ATTRIBUTES_INIT; + return v; +} + +static inline void psa_set_key_id(psa_key_attributes_t *attributes, + mbedtls_svc_key_id_t key) +{ + psa_key_lifetime_t lifetime = attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(lifetime); + + attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(id) = key; + + if (PSA_KEY_LIFETIME_IS_VOLATILE(lifetime)) { + attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(lifetime) = + PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION( + PSA_KEY_LIFETIME_PERSISTENT, + PSA_KEY_LIFETIME_GET_LOCATION(lifetime)); + } +} + +static inline mbedtls_svc_key_id_t psa_get_key_id( + const psa_key_attributes_t *attributes) +{ + return attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(id); +} + +#ifdef MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER +static inline void mbedtls_set_key_owner_id(psa_key_attributes_t *attributes, + mbedtls_key_owner_id_t owner) +{ + attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(id).MBEDTLS_PRIVATE(owner) = owner; +} +#endif + +static inline void psa_set_key_lifetime(psa_key_attributes_t *attributes, + psa_key_lifetime_t lifetime) +{ + attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(lifetime) = lifetime; + if (PSA_KEY_LIFETIME_IS_VOLATILE(lifetime)) { +#ifdef MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER + attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(id).MBEDTLS_PRIVATE(key_id) = 0; +#else + attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(id) = 0; +#endif + } +} + +static inline psa_key_lifetime_t psa_get_key_lifetime( + const psa_key_attributes_t *attributes) +{ + return attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(lifetime); +} + +static inline void psa_extend_key_usage_flags(psa_key_usage_t *usage_flags) +{ + if (*usage_flags & PSA_KEY_USAGE_SIGN_HASH) { + *usage_flags |= PSA_KEY_USAGE_SIGN_MESSAGE; + } + + if (*usage_flags & PSA_KEY_USAGE_VERIFY_HASH) { + *usage_flags |= PSA_KEY_USAGE_VERIFY_MESSAGE; + } +} + +static inline void psa_set_key_usage_flags(psa_key_attributes_t *attributes, + psa_key_usage_t usage_flags) +{ + psa_extend_key_usage_flags(&usage_flags); + attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(usage) = usage_flags; +} + +static inline psa_key_usage_t psa_get_key_usage_flags( + const psa_key_attributes_t *attributes) +{ + return attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(usage); +} + +static inline void psa_set_key_algorithm(psa_key_attributes_t *attributes, + psa_algorithm_t alg) +{ + attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(alg) = alg; +} + +static inline psa_algorithm_t psa_get_key_algorithm( + const psa_key_attributes_t *attributes) +{ + return attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(alg); +} + +/* This function is declared in crypto_extra.h, which comes after this + * header file, but we need the function here, so repeat the declaration. */ +psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes, + psa_key_type_t type, + const uint8_t *data, + size_t data_length); + +static inline void psa_set_key_type(psa_key_attributes_t *attributes, + psa_key_type_t type) +{ + if (attributes->MBEDTLS_PRIVATE(domain_parameters) == NULL) { + /* Common case: quick path */ + attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(type) = type; + } else { + /* Call the bigger function to free the old domain parameters. + * Ignore any errors which may arise due to type requiring + * non-default domain parameters, since this function can't + * report errors. */ + (void) psa_set_key_domain_parameters(attributes, type, NULL, 0); + } +} + +static inline psa_key_type_t psa_get_key_type( + const psa_key_attributes_t *attributes) +{ + return attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(type); +} + +static inline void psa_set_key_bits(psa_key_attributes_t *attributes, + size_t bits) +{ + if (bits > PSA_MAX_KEY_BITS) { + attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(bits) = PSA_KEY_BITS_TOO_LARGE; + } else { + attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(bits) = (psa_key_bits_t) bits; + } +} + +static inline size_t psa_get_key_bits( + const psa_key_attributes_t *attributes) +{ + return attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(bits); +} + +/** + * \brief The context for PSA interruptible hash signing. + */ +struct psa_sign_hash_interruptible_operation_s { + /** Unique ID indicating which driver got assigned to do the + * operation. Since driver contexts are driver-specific, swapping + * drivers halfway through the operation is not supported. + * ID values are auto-generated in psa_crypto_driver_wrappers.h + * ID value zero means the context is not valid or not assigned to + * any driver (i.e. none of the driver contexts are active). */ + unsigned int MBEDTLS_PRIVATE(id); + + psa_driver_sign_hash_interruptible_context_t MBEDTLS_PRIVATE(ctx); + + unsigned int MBEDTLS_PRIVATE(error_occurred) : 1; + + uint32_t MBEDTLS_PRIVATE(num_ops); +}; + +#define PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT { 0, { 0 }, 0, 0 } + +static inline struct psa_sign_hash_interruptible_operation_s +psa_sign_hash_interruptible_operation_init(void) +{ + const struct psa_sign_hash_interruptible_operation_s v = + PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT; + + return v; +} + +/** + * \brief The context for PSA interruptible hash verification. + */ +struct psa_verify_hash_interruptible_operation_s { + /** Unique ID indicating which driver got assigned to do the + * operation. Since driver contexts are driver-specific, swapping + * drivers halfway through the operation is not supported. + * ID values are auto-generated in psa_crypto_driver_wrappers.h + * ID value zero means the context is not valid or not assigned to + * any driver (i.e. none of the driver contexts are active). */ + unsigned int MBEDTLS_PRIVATE(id); + + psa_driver_verify_hash_interruptible_context_t MBEDTLS_PRIVATE(ctx); + + unsigned int MBEDTLS_PRIVATE(error_occurred) : 1; + + uint32_t MBEDTLS_PRIVATE(num_ops); +}; + +#define PSA_VERIFY_HASH_INTERRUPTIBLE_OPERATION_INIT { 0, { 0 }, 0, 0 } + +static inline struct psa_verify_hash_interruptible_operation_s +psa_verify_hash_interruptible_operation_init(void) +{ + const struct psa_verify_hash_interruptible_operation_s v = + PSA_VERIFY_HASH_INTERRUPTIBLE_OPERATION_INIT; + + return v; +} + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_STRUCT_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_types.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_types.h new file mode 100644 index 0000000..a5154fc --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_types.h @@ -0,0 +1,465 @@ +/** + * \file psa/crypto_types.h + * + * \brief PSA cryptography module: type aliases. + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. Drivers must include the appropriate driver + * header file. + * + * This file contains portable definitions of integral types for properties + * of cryptographic keys, designations of cryptographic algorithms, and + * error codes returned by the library. + * + * This header file does not declare any function. + */ +/* + * 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 PSA_CRYPTO_TYPES_H +#define PSA_CRYPTO_TYPES_H + +/* Make sure the Mbed TLS configuration is visible. */ +#include "mbedtls/build_info.h" +/* Define the MBEDTLS_PRIVATE macro. */ +#include "mbedtls/private_access.h" + +#if defined(MBEDTLS_PSA_CRYPTO_PLATFORM_FILE) +#include MBEDTLS_PSA_CRYPTO_PLATFORM_FILE +#else +#include "crypto_platform.h" +#endif + +#include + +/** \defgroup error Error codes + * @{ + */ + +/** + * \brief Function return status. + * + * This is either #PSA_SUCCESS (which is zero), indicating success, + * or a small negative value indicating that an error occurred. Errors are + * encoded as one of the \c PSA_ERROR_xxx values defined here. */ +/* If #PSA_SUCCESS is already defined, it means that #psa_status_t + * is also defined in an external header, so prevent its multiple + * definition. + */ +#ifndef PSA_SUCCESS +typedef int32_t psa_status_t; +#endif + +/**@}*/ + +/** \defgroup crypto_types Key and algorithm types + * @{ + */ + +/** \brief Encoding of a key type. + * + * Values of this type are generally constructed by macros called + * `PSA_KEY_TYPE_xxx`. + * + * \note Values of this type are encoded in the persistent key store. + * Any changes to existing values will require bumping the storage + * format version and providing a translation when reading the old + * format. + */ +typedef uint16_t psa_key_type_t; + +/** The type of PSA elliptic curve family identifiers. + * + * Values of this type are generally constructed by macros called + * `PSA_ECC_FAMILY_xxx`. + * + * The curve identifier is required to create an ECC key using the + * PSA_KEY_TYPE_ECC_KEY_PAIR() or PSA_KEY_TYPE_ECC_PUBLIC_KEY() + * macros. + * + * Values defined by this standard will never be in the range 0x80-0xff. + * Vendors who define additional families must use an encoding in this range. + * + * \note Values of this type are encoded in the persistent key store. + * Any changes to existing values will require bumping the storage + * format version and providing a translation when reading the old + * format. + */ +typedef uint8_t psa_ecc_family_t; + +/** The type of PSA Diffie-Hellman group family identifiers. + * + * Values of this type are generally constructed by macros called + * `PSA_DH_FAMILY_xxx`. + * + * The group identifier is required to create a Diffie-Hellman key using the + * PSA_KEY_TYPE_DH_KEY_PAIR() or PSA_KEY_TYPE_DH_PUBLIC_KEY() + * macros. + * + * Values defined by this standard will never be in the range 0x80-0xff. + * Vendors who define additional families must use an encoding in this range. + * + * \note Values of this type are encoded in the persistent key store. + * Any changes to existing values will require bumping the storage + * format version and providing a translation when reading the old + * format. + */ +typedef uint8_t psa_dh_family_t; + +/** \brief Encoding of a cryptographic algorithm. + * + * Values of this type are generally constructed by macros called + * `PSA_ALG_xxx`. + * + * For algorithms that can be applied to multiple key types, this type + * does not encode the key type. For example, for symmetric ciphers + * based on a block cipher, #psa_algorithm_t encodes the block cipher + * mode and the padding mode while the block cipher itself is encoded + * via #psa_key_type_t. + * + * \note Values of this type are encoded in the persistent key store. + * Any changes to existing values will require bumping the storage + * format version and providing a translation when reading the old + * format. + */ +typedef uint32_t psa_algorithm_t; + +/**@}*/ + +/** \defgroup key_lifetimes Key lifetimes + * @{ + */ + +/** Encoding of key lifetimes. + * + * The lifetime of a key indicates where it is stored and what system actions + * may create and destroy it. + * + * Lifetime values have the following structure: + * - Bits 0-7 (#PSA_KEY_LIFETIME_GET_PERSISTENCE(\c lifetime)): + * persistence level. This value indicates what device management + * actions can cause it to be destroyed. In particular, it indicates + * whether the key is _volatile_ or _persistent_. + * See ::psa_key_persistence_t for more information. + * - Bits 8-31 (#PSA_KEY_LIFETIME_GET_LOCATION(\c lifetime)): + * location indicator. This value indicates which part of the system + * has access to the key material and can perform operations using the key. + * See ::psa_key_location_t for more information. + * + * Volatile keys are automatically destroyed when the application instance + * terminates or on a power reset of the device. Persistent keys are + * preserved until the application explicitly destroys them or until an + * integration-specific device management event occurs (for example, + * a factory reset). + * + * Persistent keys have a key identifier of type #mbedtls_svc_key_id_t. + * This identifier remains valid throughout the lifetime of the key, + * even if the application instance that created the key terminates. + * The application can call psa_open_key() to open a persistent key that + * it created previously. + * + * The default lifetime of a key is #PSA_KEY_LIFETIME_VOLATILE. The lifetime + * #PSA_KEY_LIFETIME_PERSISTENT is supported if persistent storage is + * available. Other lifetime values may be supported depending on the + * library configuration. + * + * Values of this type are generally constructed by macros called + * `PSA_KEY_LIFETIME_xxx`. + * + * \note Values of this type are encoded in the persistent key store. + * Any changes to existing values will require bumping the storage + * format version and providing a translation when reading the old + * format. + */ +typedef uint32_t psa_key_lifetime_t; + +/** Encoding of key persistence levels. + * + * What distinguishes different persistence levels is what device management + * events may cause keys to be destroyed. _Volatile_ keys are destroyed + * by a power reset. Persistent keys may be destroyed by events such as + * a transfer of ownership or a factory reset. What management events + * actually affect persistent keys at different levels is outside the + * scope of the PSA Cryptography specification. + * + * The PSA Cryptography specification defines the following values of + * persistence levels: + * - \c 0 = #PSA_KEY_PERSISTENCE_VOLATILE: volatile key. + * A volatile key is automatically destroyed by the implementation when + * the application instance terminates. In particular, a volatile key + * is automatically destroyed on a power reset of the device. + * - \c 1 = #PSA_KEY_PERSISTENCE_DEFAULT: + * persistent key with a default lifetime. + * - \c 2-254: currently not supported by Mbed TLS. + * - \c 255 = #PSA_KEY_PERSISTENCE_READ_ONLY: + * read-only or write-once key. + * A key with this persistence level cannot be destroyed. + * Mbed TLS does not currently offer a way to create such keys, but + * integrations of Mbed TLS can use it for built-in keys that the + * application cannot modify (for example, a hardware unique key (HUK)). + * + * \note Key persistence levels are 8-bit values. Key management + * interfaces operate on lifetimes (type ::psa_key_lifetime_t) which + * encode the persistence as the lower 8 bits of a 32-bit value. + * + * \note Values of this type are encoded in the persistent key store. + * Any changes to existing values will require bumping the storage + * format version and providing a translation when reading the old + * format. + */ +typedef uint8_t psa_key_persistence_t; + +/** Encoding of key location indicators. + * + * If an integration of Mbed TLS can make calls to external + * cryptoprocessors such as secure elements, the location of a key + * indicates which secure element performs the operations on the key. + * Depending on the design of the secure element, the key + * material may be stored either in the secure element, or + * in wrapped (encrypted) form alongside the key metadata in the + * primary local storage. + * + * The PSA Cryptography API specification defines the following values of + * location indicators: + * - \c 0: primary local storage. + * This location is always available. + * The primary local storage is typically the same storage area that + * contains the key metadata. + * - \c 1: primary secure element. + * Integrations of Mbed TLS should support this value if there is a secure + * element attached to the operating environment. + * As a guideline, secure elements may provide higher resistance against + * side channel and physical attacks than the primary local storage, but may + * have restrictions on supported key types, sizes, policies and operations + * and may have different performance characteristics. + * - \c 2-0x7fffff: other locations defined by a PSA specification. + * The PSA Cryptography API does not currently assign any meaning to these + * locations, but future versions of that specification or other PSA + * specifications may do so. + * - \c 0x800000-0xffffff: vendor-defined locations. + * No PSA specification will assign a meaning to locations in this range. + * + * \note Key location indicators are 24-bit values. Key management + * interfaces operate on lifetimes (type ::psa_key_lifetime_t) which + * encode the location as the upper 24 bits of a 32-bit value. + * + * \note Values of this type are encoded in the persistent key store. + * Any changes to existing values will require bumping the storage + * format version and providing a translation when reading the old + * format. + */ +typedef uint32_t psa_key_location_t; + +/** Encoding of identifiers of persistent keys. + * + * - Applications may freely choose key identifiers in the range + * #PSA_KEY_ID_USER_MIN to #PSA_KEY_ID_USER_MAX. + * - The implementation may define additional key identifiers in the range + * #PSA_KEY_ID_VENDOR_MIN to #PSA_KEY_ID_VENDOR_MAX. + * - 0 is reserved as an invalid key identifier. + * - Key identifiers outside these ranges are reserved for future use. + * + * \note Values of this type are encoded in the persistent key store. + * Any changes to how values are allocated must require careful + * consideration to allow backward compatibility. + */ +typedef uint32_t psa_key_id_t; + +/** Encoding of key identifiers as seen inside the PSA Crypto implementation. + * + * When PSA Crypto is built as a library inside an application, this type + * is identical to #psa_key_id_t. When PSA Crypto is built as a service + * that can store keys on behalf of multiple clients, this type + * encodes the #psa_key_id_t value seen by each client application as + * well as extra information that identifies the client that owns + * the key. + * + * \note Values of this type are encoded in the persistent key store. + * Any changes to existing values will require bumping the storage + * format version and providing a translation when reading the old + * format. + */ +#if !defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) +typedef psa_key_id_t mbedtls_svc_key_id_t; + +#else /* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */ +/* Implementation-specific: The Mbed Cryptography library can be built as + * part of a multi-client service that exposes the PSA Cryptography API in each + * client and encodes the client identity in the key identifier argument of + * functions such as psa_open_key(). + */ +typedef struct { + psa_key_id_t MBEDTLS_PRIVATE(key_id); + mbedtls_key_owner_id_t MBEDTLS_PRIVATE(owner); +} mbedtls_svc_key_id_t; + +#endif /* !MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */ + +/**@}*/ + +/** \defgroup policy Key policies + * @{ + */ + +/** \brief Encoding of permitted usage on a key. + * + * Values of this type are generally constructed as bitwise-ors of macros + * called `PSA_KEY_USAGE_xxx`. + * + * \note Values of this type are encoded in the persistent key store. + * Any changes to existing values will require bumping the storage + * format version and providing a translation when reading the old + * format. + */ +typedef uint32_t psa_key_usage_t; + +/**@}*/ + +/** \defgroup attributes Key attributes + * @{ + */ + +/** The type of a structure containing key attributes. + * + * This is an opaque structure that can represent the metadata of a key + * object. Metadata that can be stored in attributes includes: + * - The location of the key in storage, indicated by its key identifier + * and its lifetime. + * - The key's policy, comprising usage flags and a specification of + * the permitted algorithm(s). + * - Information about the key itself: the key type and its size. + * - Additional implementation-defined attributes. + * + * The actual key material is not considered an attribute of a key. + * Key attributes do not contain information that is generally considered + * highly confidential. + * + * An attribute structure works like a simple data structure where each function + * `psa_set_key_xxx` sets a field and the corresponding function + * `psa_get_key_xxx` retrieves the value of the corresponding field. + * However, a future version of the library may report values that are + * equivalent to the original one, but have a different encoding. Invalid + * values may be mapped to different, also invalid values. + * + * An attribute structure may contain references to auxiliary resources, + * for example pointers to allocated memory or indirect references to + * pre-calculated values. In order to free such resources, the application + * must call psa_reset_key_attributes(). As an exception, calling + * psa_reset_key_attributes() on an attribute structure is optional if + * the structure has only been modified by the following functions + * since it was initialized or last reset with psa_reset_key_attributes(): + * - psa_set_key_id() + * - psa_set_key_lifetime() + * - psa_set_key_type() + * - psa_set_key_bits() + * - psa_set_key_usage_flags() + * - psa_set_key_algorithm() + * + * Before calling any function on a key attribute structure, the application + * must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_key_attributes_t attributes; + * memset(&attributes, 0, sizeof(attributes)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_key_attributes_t attributes = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_KEY_ATTRIBUTES_INIT, + * for example: + * \code + * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + * \endcode + * - Assign the result of the function psa_key_attributes_init() + * to the structure, for example: + * \code + * psa_key_attributes_t attributes; + * attributes = psa_key_attributes_init(); + * \endcode + * + * A freshly initialized attribute structure contains the following + * values: + * + * - lifetime: #PSA_KEY_LIFETIME_VOLATILE. + * - key identifier: 0 (which is not a valid key identifier). + * - type: \c 0 (meaning that the type is unspecified). + * - key size: \c 0 (meaning that the size is unspecified). + * - usage flags: \c 0 (which allows no usage except exporting a public key). + * - algorithm: \c 0 (which allows no cryptographic usage, but allows + * exporting). + * + * A typical sequence to create a key is as follows: + * -# Create and initialize an attribute structure. + * -# If the key is persistent, call psa_set_key_id(). + * Also call psa_set_key_lifetime() to place the key in a non-default + * location. + * -# Set the key policy with psa_set_key_usage_flags() and + * psa_set_key_algorithm(). + * -# Set the key type with psa_set_key_type(). + * Skip this step if copying an existing key with psa_copy_key(). + * -# When generating a random key with psa_generate_key() or deriving a key + * with psa_key_derivation_output_key(), set the desired key size with + * psa_set_key_bits(). + * -# Call a key creation function: psa_import_key(), psa_generate_key(), + * psa_key_derivation_output_key() or psa_copy_key(). This function reads + * the attribute structure, creates a key with these attributes, and + * outputs a key identifier to the newly created key. + * -# The attribute structure is now no longer necessary. + * You may call psa_reset_key_attributes(), although this is optional + * with the workflow presented here because the attributes currently + * defined in this specification do not require any additional resources + * beyond the structure itself. + * + * A typical sequence to query a key's attributes is as follows: + * -# Call psa_get_key_attributes(). + * -# Call `psa_get_key_xxx` functions to retrieve the attribute(s) that + * you are interested in. + * -# Call psa_reset_key_attributes() to free any resources that may be + * used by the attribute structure. + * + * Once a key has been created, it is impossible to change its attributes. + */ +typedef struct psa_key_attributes_s psa_key_attributes_t; + + +#ifndef __DOXYGEN_ONLY__ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +/* Mbed Crypto defines this type in crypto_types.h because it is also + * visible to applications through an implementation-specific extension. + * For the PSA Cryptography specification, this type is only visible + * via crypto_se_driver.h. */ +typedef uint64_t psa_key_slot_number_t; +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ +#endif /* !__DOXYGEN_ONLY__ */ + +/**@}*/ + +/** \defgroup derivation Key derivation + * @{ + */ + +/** \brief Encoding of the step of a key derivation. + * + * Values of this type are generally constructed by macros called + * `PSA_KEY_DERIVATION_INPUT_xxx`. + */ +typedef uint16_t psa_key_derivation_step_t; + +/**@}*/ + +#endif /* PSA_CRYPTO_TYPES_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_values.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_values.h new file mode 100644 index 0000000..39acd96 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/psa/crypto_values.h @@ -0,0 +1,2763 @@ +/** + * \file psa/crypto_values.h + * + * \brief PSA cryptography module: macros to build and analyze integer values. + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. Drivers must include the appropriate driver + * header file. + * + * This file contains portable definitions of macros to build and analyze + * values of integral types that encode properties of cryptographic keys, + * designations of cryptographic algorithms, and error codes returned by + * the library. + * + * Note that many of the constants defined in this file are embedded in + * the persistent key store, as part of key metadata (including usage + * policies). As a consequence, they must not be changed (unless the storage + * format version changes). + * + * This header file only defines preprocessor macros. + */ +/* + * 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 PSA_CRYPTO_VALUES_H +#define PSA_CRYPTO_VALUES_H +#include "mbedtls/private_access.h" + +/** \defgroup error Error codes + * @{ + */ + +/* PSA error codes */ + +/* Error codes are standardized across PSA domains (framework, crypto, storage, + * etc.). Do not change the values in this section or even the expansions + * of each macro: it must be possible to `#include` both this header + * and some other PSA component's headers in the same C source, + * which will lead to duplicate definitions of the `PSA_SUCCESS` and + * `PSA_ERROR_xxx` macros, which is ok if and only if the macros expand + * to the same sequence of tokens. + * + * If you must add a new + * value, check with the Arm PSA framework group to pick one that other + * domains aren't already using. */ + +/* Tell uncrustify not to touch the constant definitions, otherwise + * it might change the spacing to something that is not PSA-compliant + * (e.g. adding a space after casts). + * + * *INDENT-OFF* + */ + +/** The action was completed successfully. */ +#define PSA_SUCCESS ((psa_status_t)0) + +/** An error occurred that does not correspond to any defined + * failure cause. + * + * Implementations may use this error code if none of the other standard + * error codes are applicable. */ +#define PSA_ERROR_GENERIC_ERROR ((psa_status_t)-132) + +/** The requested operation or a parameter is not supported + * by this implementation. + * + * Implementations should return this error code when an enumeration + * parameter such as a key type, algorithm, etc. is not recognized. + * If a combination of parameters is recognized and identified as + * not valid, return #PSA_ERROR_INVALID_ARGUMENT instead. */ +#define PSA_ERROR_NOT_SUPPORTED ((psa_status_t)-134) + +/** The requested action is denied by a policy. + * + * Implementations should return this error code when the parameters + * are recognized as valid and supported, and a policy explicitly + * denies the requested operation. + * + * If a subset of the parameters of a function call identify a + * forbidden operation, and another subset of the parameters are + * not valid or not supported, it is unspecified whether the function + * returns #PSA_ERROR_NOT_PERMITTED, #PSA_ERROR_NOT_SUPPORTED or + * #PSA_ERROR_INVALID_ARGUMENT. */ +#define PSA_ERROR_NOT_PERMITTED ((psa_status_t)-133) + +/** An output buffer is too small. + * + * Applications can call the \c PSA_xxx_SIZE macro listed in the function + * description to determine a sufficient buffer size. + * + * Implementations should preferably return this error code only + * in cases when performing the operation with a larger output + * buffer would succeed. However implementations may return this + * error if a function has invalid or unsupported parameters in addition + * to the parameters that determine the necessary output buffer size. */ +#define PSA_ERROR_BUFFER_TOO_SMALL ((psa_status_t)-138) + +/** Asking for an item that already exists + * + * Implementations should return this error, when attempting + * to write an item (like a key) that already exists. */ +#define PSA_ERROR_ALREADY_EXISTS ((psa_status_t)-139) + +/** Asking for an item that doesn't exist + * + * Implementations should return this error, if a requested item (like + * a key) does not exist. */ +#define PSA_ERROR_DOES_NOT_EXIST ((psa_status_t)-140) + +/** The requested action cannot be performed in the current state. + * + * Multipart operations return this error when one of the + * functions is called out of sequence. Refer to the function + * descriptions for permitted sequencing of functions. + * + * Implementations shall not return this error code to indicate + * that a key either exists or not, + * but shall instead return #PSA_ERROR_ALREADY_EXISTS or #PSA_ERROR_DOES_NOT_EXIST + * as applicable. + * + * Implementations shall not return this error code to indicate that a + * key identifier is invalid, but shall return #PSA_ERROR_INVALID_HANDLE + * instead. */ +#define PSA_ERROR_BAD_STATE ((psa_status_t)-137) + +/** The parameters passed to the function are invalid. + * + * Implementations may return this error any time a parameter or + * combination of parameters are recognized as invalid. + * + * Implementations shall not return this error code to indicate that a + * key identifier is invalid, but shall return #PSA_ERROR_INVALID_HANDLE + * instead. + */ +#define PSA_ERROR_INVALID_ARGUMENT ((psa_status_t)-135) + +/** There is not enough runtime memory. + * + * If the action is carried out across multiple security realms, this + * error can refer to available memory in any of the security realms. */ +#define PSA_ERROR_INSUFFICIENT_MEMORY ((psa_status_t)-141) + +/** There is not enough persistent storage. + * + * Functions that modify the key storage return this error code if + * there is insufficient storage space on the host media. In addition, + * many functions that do not otherwise access storage may return this + * error code if the implementation requires a mandatory log entry for + * the requested action and the log storage space is full. */ +#define PSA_ERROR_INSUFFICIENT_STORAGE ((psa_status_t)-142) + +/** There was a communication failure inside the implementation. + * + * This can indicate a communication failure between the application + * and an external cryptoprocessor or between the cryptoprocessor and + * an external volatile or persistent memory. A communication failure + * may be transient or permanent depending on the cause. + * + * \warning If a function returns this error, it is undetermined + * whether the requested action has completed or not. Implementations + * should return #PSA_SUCCESS on successful completion whenever + * possible, however functions may return #PSA_ERROR_COMMUNICATION_FAILURE + * if the requested action was completed successfully in an external + * cryptoprocessor but there was a breakdown of communication before + * the cryptoprocessor could report the status to the application. + */ +#define PSA_ERROR_COMMUNICATION_FAILURE ((psa_status_t)-145) + +/** There was a storage failure that may have led to data loss. + * + * This error indicates that some persistent storage is corrupted. + * It should not be used for a corruption of volatile memory + * (use #PSA_ERROR_CORRUPTION_DETECTED), for a communication error + * between the cryptoprocessor and its external storage (use + * #PSA_ERROR_COMMUNICATION_FAILURE), or when the storage is + * in a valid state but is full (use #PSA_ERROR_INSUFFICIENT_STORAGE). + * + * Note that a storage failure does not indicate that any data that was + * previously read is invalid. However this previously read data may no + * longer be readable from storage. + * + * When a storage failure occurs, it is no longer possible to ensure + * the global integrity of the keystore. Depending on the global + * integrity guarantees offered by the implementation, access to other + * data may or may not fail even if the data is still readable but + * its integrity cannot be guaranteed. + * + * Implementations should only use this error code to report a + * permanent storage corruption. However application writers should + * keep in mind that transient errors while reading the storage may be + * reported using this error code. */ +#define PSA_ERROR_STORAGE_FAILURE ((psa_status_t)-146) + +/** A hardware failure was detected. + * + * A hardware failure may be transient or permanent depending on the + * cause. */ +#define PSA_ERROR_HARDWARE_FAILURE ((psa_status_t)-147) + +/** A tampering attempt was detected. + * + * If an application receives this error code, there is no guarantee + * that previously accessed or computed data was correct and remains + * confidential. Applications should not perform any security function + * and should enter a safe failure state. + * + * Implementations may return this error code if they detect an invalid + * state that cannot happen during normal operation and that indicates + * that the implementation's security guarantees no longer hold. Depending + * on the implementation architecture and on its security and safety goals, + * the implementation may forcibly terminate the application. + * + * This error code is intended as a last resort when a security breach + * is detected and it is unsure whether the keystore data is still + * protected. Implementations shall only return this error code + * to report an alarm from a tampering detector, to indicate that + * the confidentiality of stored data can no longer be guaranteed, + * or to indicate that the integrity of previously returned data is now + * considered compromised. Implementations shall not use this error code + * to indicate a hardware failure that merely makes it impossible to + * perform the requested operation (use #PSA_ERROR_COMMUNICATION_FAILURE, + * #PSA_ERROR_STORAGE_FAILURE, #PSA_ERROR_HARDWARE_FAILURE, + * #PSA_ERROR_INSUFFICIENT_ENTROPY or other applicable error code + * instead). + * + * This error indicates an attack against the application. Implementations + * shall not return this error code as a consequence of the behavior of + * the application itself. */ +#define PSA_ERROR_CORRUPTION_DETECTED ((psa_status_t)-151) + +/** There is not enough entropy to generate random data needed + * for the requested action. + * + * This error indicates a failure of a hardware random generator. + * Application writers should note that this error can be returned not + * only by functions whose purpose is to generate random data, such + * as key, IV or nonce generation, but also by functions that execute + * an algorithm with a randomized result, as well as functions that + * use randomization of intermediate computations as a countermeasure + * to certain attacks. + * + * Implementations should avoid returning this error after psa_crypto_init() + * has succeeded. Implementations should generate sufficient + * entropy during initialization and subsequently use a cryptographically + * secure pseudorandom generator (PRNG). However implementations may return + * this error at any time if a policy requires the PRNG to be reseeded + * during normal operation. */ +#define PSA_ERROR_INSUFFICIENT_ENTROPY ((psa_status_t)-148) + +/** The signature, MAC or hash is incorrect. + * + * Verification functions return this error if the verification + * calculations completed successfully, and the value to be verified + * was determined to be incorrect. + * + * If the value to verify has an invalid size, implementations may return + * either #PSA_ERROR_INVALID_ARGUMENT or #PSA_ERROR_INVALID_SIGNATURE. */ +#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)-149) + +/** The decrypted padding is incorrect. + * + * \warning In some protocols, when decrypting data, it is essential that + * the behavior of the application does not depend on whether the padding + * is correct, down to precise timing. Applications should prefer + * protocols that use authenticated encryption rather than plain + * encryption. If the application must perform a decryption of + * unauthenticated data, the application writer should take care not + * to reveal whether the padding is invalid. + * + * Implementations should strive to make valid and invalid padding + * as close as possible to indistinguishable to an external observer. + * In particular, the timing of a decryption operation should not + * depend on the validity of the padding. */ +#define PSA_ERROR_INVALID_PADDING ((psa_status_t)-150) + +/** Return this error when there's insufficient data when attempting + * to read from a resource. */ +#define PSA_ERROR_INSUFFICIENT_DATA ((psa_status_t)-143) + +/** The key identifier is not valid. See also :ref:\`key-handles\`. + */ +#define PSA_ERROR_INVALID_HANDLE ((psa_status_t)-136) + +/** Stored data has been corrupted. + * + * This error indicates that some persistent storage has suffered corruption. + * It does not indicate the following situations, which have specific error + * codes: + * + * - A corruption of volatile memory - use #PSA_ERROR_CORRUPTION_DETECTED. + * - A communication error between the cryptoprocessor and its external + * storage - use #PSA_ERROR_COMMUNICATION_FAILURE. + * - When the storage is in a valid state but is full - use + * #PSA_ERROR_INSUFFICIENT_STORAGE. + * - When the storage fails for other reasons - use + * #PSA_ERROR_STORAGE_FAILURE. + * - When the stored data is not valid - use #PSA_ERROR_DATA_INVALID. + * + * \note A storage corruption does not indicate that any data that was + * previously read is invalid. However this previously read data might no + * longer be readable from storage. + * + * When a storage failure occurs, it is no longer possible to ensure the + * global integrity of the keystore. + */ +#define PSA_ERROR_DATA_CORRUPT ((psa_status_t)-152) + +/** Data read from storage is not valid for the implementation. + * + * This error indicates that some data read from storage does not have a valid + * format. It does not indicate the following situations, which have specific + * error codes: + * + * - When the storage or stored data is corrupted - use #PSA_ERROR_DATA_CORRUPT + * - When the storage fails for other reasons - use #PSA_ERROR_STORAGE_FAILURE + * - An invalid argument to the API - use #PSA_ERROR_INVALID_ARGUMENT + * + * This error is typically a result of either storage corruption on a + * cleartext storage backend, or an attempt to read data that was + * written by an incompatible version of the library. + */ +#define PSA_ERROR_DATA_INVALID ((psa_status_t)-153) + +/** The function that returns this status is defined as interruptible and + * still has work to do, thus the user should call the function again with the + * same operation context until it either returns #PSA_SUCCESS or any other + * error. This is not an error per se, more a notification of status. + */ +#define PSA_OPERATION_INCOMPLETE ((psa_status_t)-248) + +/* *INDENT-ON* */ + +/**@}*/ + +/** \defgroup crypto_types Key and algorithm types + * @{ + */ + +/* Note that key type values, including ECC family and DH group values, are + * embedded in the persistent key store, as part of key metadata. As a + * consequence, they must not be changed (unless the storage format version + * changes). + */ + +/** An invalid key type value. + * + * Zero is not the encoding of any key type. + */ +#define PSA_KEY_TYPE_NONE ((psa_key_type_t) 0x0000) + +/** Vendor-defined key type flag. + * + * Key types defined by this standard will never have the + * #PSA_KEY_TYPE_VENDOR_FLAG bit set. Vendors who define additional key types + * must use an encoding with the #PSA_KEY_TYPE_VENDOR_FLAG bit set and should + * respect the bitwise structure used by standard encodings whenever practical. + */ +#define PSA_KEY_TYPE_VENDOR_FLAG ((psa_key_type_t) 0x8000) + +#define PSA_KEY_TYPE_CATEGORY_MASK ((psa_key_type_t) 0x7000) +#define PSA_KEY_TYPE_CATEGORY_RAW ((psa_key_type_t) 0x1000) +#define PSA_KEY_TYPE_CATEGORY_SYMMETRIC ((psa_key_type_t) 0x2000) +#define PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY ((psa_key_type_t) 0x4000) +#define PSA_KEY_TYPE_CATEGORY_KEY_PAIR ((psa_key_type_t) 0x7000) + +#define PSA_KEY_TYPE_CATEGORY_FLAG_PAIR ((psa_key_type_t) 0x3000) + +/** Whether a key type is vendor-defined. + * + * See also #PSA_KEY_TYPE_VENDOR_FLAG. + */ +#define PSA_KEY_TYPE_IS_VENDOR_DEFINED(type) \ + (((type) & PSA_KEY_TYPE_VENDOR_FLAG) != 0) + +/** Whether a key type is an unstructured array of bytes. + * + * This encompasses both symmetric keys and non-key data. + */ +#define PSA_KEY_TYPE_IS_UNSTRUCTURED(type) \ + (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_RAW || \ + ((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_SYMMETRIC) + +/** Whether a key type is asymmetric: either a key pair or a public key. */ +#define PSA_KEY_TYPE_IS_ASYMMETRIC(type) \ + (((type) & PSA_KEY_TYPE_CATEGORY_MASK \ + & ~PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) == \ + PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY) +/** Whether a key type is the public part of a key pair. */ +#define PSA_KEY_TYPE_IS_PUBLIC_KEY(type) \ + (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY) +/** Whether a key type is a key pair containing a private part and a public + * part. */ +#define PSA_KEY_TYPE_IS_KEY_PAIR(type) \ + (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_KEY_PAIR) +/** The key pair type corresponding to a public key type. + * + * You may also pass a key pair type as \p type, it will be left unchanged. + * + * \param type A public key type or key pair type. + * + * \return The corresponding key pair type. + * If \p type is not a public key or a key pair, + * the return value is undefined. + */ +#define PSA_KEY_TYPE_KEY_PAIR_OF_PUBLIC_KEY(type) \ + ((type) | PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) +/** The public key type corresponding to a key pair type. + * + * You may also pass a key pair type as \p type, it will be left unchanged. + * + * \param type A public key type or key pair type. + * + * \return The corresponding public key type. + * If \p type is not a public key or a key pair, + * the return value is undefined. + */ +#define PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) \ + ((type) & ~PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) + +/** Raw data. + * + * A "key" of this type cannot be used for any cryptographic operation. + * Applications may use this type to store arbitrary data in the keystore. */ +#define PSA_KEY_TYPE_RAW_DATA ((psa_key_type_t) 0x1001) + +/** HMAC key. + * + * The key policy determines which underlying hash algorithm the key can be + * used for. + * + * HMAC keys should generally have the same size as the underlying hash. + * This size can be calculated with #PSA_HASH_LENGTH(\c alg) where + * \c alg is the HMAC algorithm or the underlying hash algorithm. */ +#define PSA_KEY_TYPE_HMAC ((psa_key_type_t) 0x1100) + +/** A secret for key derivation. + * + * This key type is for high-entropy secrets only. For low-entropy secrets, + * #PSA_KEY_TYPE_PASSWORD should be used instead. + * + * These keys can be used as the #PSA_KEY_DERIVATION_INPUT_SECRET or + * #PSA_KEY_DERIVATION_INPUT_PASSWORD input of key derivation algorithms. + * + * The key policy determines which key derivation algorithm the key + * can be used for. + */ +#define PSA_KEY_TYPE_DERIVE ((psa_key_type_t) 0x1200) + +/** A low-entropy secret for password hashing or key derivation. + * + * This key type is suitable for passwords and passphrases which are typically + * intended to be memorizable by humans, and have a low entropy relative to + * their size. It can be used for randomly generated or derived keys with + * maximum or near-maximum entropy, but #PSA_KEY_TYPE_DERIVE is more suitable + * for such keys. It is not suitable for passwords with extremely low entropy, + * such as numerical PINs. + * + * These keys can be used as the #PSA_KEY_DERIVATION_INPUT_PASSWORD input of + * key derivation algorithms. Algorithms that accept such an input were + * designed to accept low-entropy secret and are known as password hashing or + * key stretching algorithms. + * + * These keys cannot be used as the #PSA_KEY_DERIVATION_INPUT_SECRET input of + * key derivation algorithms, as the algorithms that take such an input expect + * it to be high-entropy. + * + * The key policy determines which key derivation algorithm the key can be + * used for, among the permissible subset defined above. + */ +#define PSA_KEY_TYPE_PASSWORD ((psa_key_type_t) 0x1203) + +/** A secret value that can be used to verify a password hash. + * + * The key policy determines which key derivation algorithm the key + * can be used for, among the same permissible subset as for + * #PSA_KEY_TYPE_PASSWORD. + */ +#define PSA_KEY_TYPE_PASSWORD_HASH ((psa_key_type_t) 0x1205) + +/** A secret value that can be used in when computing a password hash. + * + * The key policy determines which key derivation algorithm the key + * can be used for, among the subset of algorithms that can use pepper. + */ +#define PSA_KEY_TYPE_PEPPER ((psa_key_type_t) 0x1206) + +/** Key for a cipher, AEAD or MAC algorithm based on the AES block cipher. + * + * The size of the key can be 16 bytes (AES-128), 24 bytes (AES-192) or + * 32 bytes (AES-256). + */ +#define PSA_KEY_TYPE_AES ((psa_key_type_t) 0x2400) + +/** Key for a cipher, AEAD or MAC algorithm based on the + * ARIA block cipher. */ +#define PSA_KEY_TYPE_ARIA ((psa_key_type_t) 0x2406) + +/** Key for a cipher or MAC algorithm based on DES or 3DES (Triple-DES). + * + * The size of the key can be 64 bits (single DES), 128 bits (2-key 3DES) or + * 192 bits (3-key 3DES). + * + * Note that single DES and 2-key 3DES are weak and strongly + * deprecated and should only be used to decrypt legacy data. 3-key 3DES + * is weak and deprecated and should only be used in legacy protocols. + */ +#define PSA_KEY_TYPE_DES ((psa_key_type_t) 0x2301) + +/** Key for a cipher, AEAD or MAC algorithm based on the + * Camellia block cipher. */ +#define PSA_KEY_TYPE_CAMELLIA ((psa_key_type_t) 0x2403) + +/** Key for the ChaCha20 stream cipher or the Chacha20-Poly1305 AEAD algorithm. + * + * ChaCha20 and the ChaCha20_Poly1305 construction are defined in RFC 7539. + * + * \note For ChaCha20 and ChaCha20_Poly1305, Mbed TLS only supports + * 12-byte nonces. + * + * \note For ChaCha20, the initial counter value is 0. To encrypt or decrypt + * with the initial counter value 1, you can process and discard a + * 64-byte block before the real data. + */ +#define PSA_KEY_TYPE_CHACHA20 ((psa_key_type_t) 0x2004) + +/** RSA public key. + * + * The size of an RSA key is the bit size of the modulus. + */ +#define PSA_KEY_TYPE_RSA_PUBLIC_KEY ((psa_key_type_t) 0x4001) +/** RSA key pair (private and public key). + * + * The size of an RSA key is the bit size of the modulus. + */ +#define PSA_KEY_TYPE_RSA_KEY_PAIR ((psa_key_type_t) 0x7001) +/** Whether a key type is an RSA key (pair or public-only). */ +#define PSA_KEY_TYPE_IS_RSA(type) \ + (PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY) + +#define PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE ((psa_key_type_t) 0x4100) +#define PSA_KEY_TYPE_ECC_KEY_PAIR_BASE ((psa_key_type_t) 0x7100) +#define PSA_KEY_TYPE_ECC_CURVE_MASK ((psa_key_type_t) 0x00ff) +/** Elliptic curve key pair. + * + * The size of an elliptic curve key is the bit size associated with the curve, + * i.e. the bit size of *q* for a curve over a field *Fq*. + * See the documentation of `PSA_ECC_FAMILY_xxx` curve families for details. + * + * \param curve A value of type ::psa_ecc_family_t that + * identifies the ECC curve to be used. + */ +#define PSA_KEY_TYPE_ECC_KEY_PAIR(curve) \ + (PSA_KEY_TYPE_ECC_KEY_PAIR_BASE | (curve)) +/** Elliptic curve public key. + * + * The size of an elliptic curve public key is the same as the corresponding + * private key (see #PSA_KEY_TYPE_ECC_KEY_PAIR and the documentation of + * `PSA_ECC_FAMILY_xxx` curve families). + * + * \param curve A value of type ::psa_ecc_family_t that + * identifies the ECC curve to be used. + */ +#define PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve) \ + (PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE | (curve)) + +/** Whether a key type is an elliptic curve key (pair or public-only). */ +#define PSA_KEY_TYPE_IS_ECC(type) \ + ((PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) & \ + ~PSA_KEY_TYPE_ECC_CURVE_MASK) == PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE) +/** Whether a key type is an elliptic curve key pair. */ +#define PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type) \ + (((type) & ~PSA_KEY_TYPE_ECC_CURVE_MASK) == \ + PSA_KEY_TYPE_ECC_KEY_PAIR_BASE) +/** Whether a key type is an elliptic curve public key. */ +#define PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(type) \ + (((type) & ~PSA_KEY_TYPE_ECC_CURVE_MASK) == \ + PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE) + +/** Extract the curve from an elliptic curve key type. */ +#define PSA_KEY_TYPE_ECC_GET_FAMILY(type) \ + ((psa_ecc_family_t) (PSA_KEY_TYPE_IS_ECC(type) ? \ + ((type) & PSA_KEY_TYPE_ECC_CURVE_MASK) : \ + 0)) + +/** Check if the curve of given family is Weierstrass elliptic curve. */ +#define PSA_ECC_FAMILY_IS_WEIERSTRASS(family) ((family & 0xc0) == 0) + +/** SEC Koblitz curves over prime fields. + * + * This family comprises the following curves: + * secp192k1, secp224k1, secp256k1. + * They are defined in _Standards for Efficient Cryptography_, + * _SEC 2: Recommended Elliptic Curve Domain Parameters_. + * https://www.secg.org/sec2-v2.pdf + */ +#define PSA_ECC_FAMILY_SECP_K1 ((psa_ecc_family_t) 0x17) + +/** SEC random curves over prime fields. + * + * This family comprises the following curves: + * secp192k1, secp224r1, secp256r1, secp384r1, secp521r1. + * They are defined in _Standards for Efficient Cryptography_, + * _SEC 2: Recommended Elliptic Curve Domain Parameters_. + * https://www.secg.org/sec2-v2.pdf + */ +#define PSA_ECC_FAMILY_SECP_R1 ((psa_ecc_family_t) 0x12) +/* SECP160R2 (SEC2 v1, obsolete) */ +#define PSA_ECC_FAMILY_SECP_R2 ((psa_ecc_family_t) 0x1b) + +/** SEC Koblitz curves over binary fields. + * + * This family comprises the following curves: + * sect163k1, sect233k1, sect239k1, sect283k1, sect409k1, sect571k1. + * They are defined in _Standards for Efficient Cryptography_, + * _SEC 2: Recommended Elliptic Curve Domain Parameters_. + * https://www.secg.org/sec2-v2.pdf + */ +#define PSA_ECC_FAMILY_SECT_K1 ((psa_ecc_family_t) 0x27) + +/** SEC random curves over binary fields. + * + * This family comprises the following curves: + * sect163r1, sect233r1, sect283r1, sect409r1, sect571r1. + * They are defined in _Standards for Efficient Cryptography_, + * _SEC 2: Recommended Elliptic Curve Domain Parameters_. + * https://www.secg.org/sec2-v2.pdf + */ +#define PSA_ECC_FAMILY_SECT_R1 ((psa_ecc_family_t) 0x22) + +/** SEC additional random curves over binary fields. + * + * This family comprises the following curve: + * sect163r2. + * It is defined in _Standards for Efficient Cryptography_, + * _SEC 2: Recommended Elliptic Curve Domain Parameters_. + * https://www.secg.org/sec2-v2.pdf + */ +#define PSA_ECC_FAMILY_SECT_R2 ((psa_ecc_family_t) 0x2b) + +/** Brainpool P random curves. + * + * This family comprises the following curves: + * brainpoolP160r1, brainpoolP192r1, brainpoolP224r1, brainpoolP256r1, + * brainpoolP320r1, brainpoolP384r1, brainpoolP512r1. + * It is defined in RFC 5639. + */ +#define PSA_ECC_FAMILY_BRAINPOOL_P_R1 ((psa_ecc_family_t) 0x30) + +/** Curve25519 and Curve448. + * + * This family comprises the following Montgomery curves: + * - 255-bit: Bernstein et al., + * _Curve25519: new Diffie-Hellman speed records_, LNCS 3958, 2006. + * The algorithm #PSA_ALG_ECDH performs X25519 when used with this curve. + * - 448-bit: Hamburg, + * _Ed448-Goldilocks, a new elliptic curve_, NIST ECC Workshop, 2015. + * The algorithm #PSA_ALG_ECDH performs X448 when used with this curve. + */ +#define PSA_ECC_FAMILY_MONTGOMERY ((psa_ecc_family_t) 0x41) + +/** The twisted Edwards curves Ed25519 and Ed448. + * + * These curves are suitable for EdDSA (#PSA_ALG_PURE_EDDSA for both curves, + * #PSA_ALG_ED25519PH for the 255-bit curve, + * #PSA_ALG_ED448PH for the 448-bit curve). + * + * This family comprises the following twisted Edwards curves: + * - 255-bit: Edwards25519, the twisted Edwards curve birationally equivalent + * to Curve25519. + * Bernstein et al., _Twisted Edwards curves_, Africacrypt 2008. + * - 448-bit: Edwards448, the twisted Edwards curve birationally equivalent + * to Curve448. + * Hamburg, _Ed448-Goldilocks, a new elliptic curve_, NIST ECC Workshop, 2015. + */ +#define PSA_ECC_FAMILY_TWISTED_EDWARDS ((psa_ecc_family_t) 0x42) + +#define PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE ((psa_key_type_t) 0x4200) +#define PSA_KEY_TYPE_DH_KEY_PAIR_BASE ((psa_key_type_t) 0x7200) +#define PSA_KEY_TYPE_DH_GROUP_MASK ((psa_key_type_t) 0x00ff) +/** Diffie-Hellman key pair. + * + * \param group A value of type ::psa_dh_family_t that identifies the + * Diffie-Hellman group to be used. + */ +#define PSA_KEY_TYPE_DH_KEY_PAIR(group) \ + (PSA_KEY_TYPE_DH_KEY_PAIR_BASE | (group)) +/** Diffie-Hellman public key. + * + * \param group A value of type ::psa_dh_family_t that identifies the + * Diffie-Hellman group to be used. + */ +#define PSA_KEY_TYPE_DH_PUBLIC_KEY(group) \ + (PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE | (group)) + +/** Whether a key type is a Diffie-Hellman key (pair or public-only). */ +#define PSA_KEY_TYPE_IS_DH(type) \ + ((PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) & \ + ~PSA_KEY_TYPE_DH_GROUP_MASK) == PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE) +/** Whether a key type is a Diffie-Hellman key pair. */ +#define PSA_KEY_TYPE_IS_DH_KEY_PAIR(type) \ + (((type) & ~PSA_KEY_TYPE_DH_GROUP_MASK) == \ + PSA_KEY_TYPE_DH_KEY_PAIR_BASE) +/** Whether a key type is a Diffie-Hellman public key. */ +#define PSA_KEY_TYPE_IS_DH_PUBLIC_KEY(type) \ + (((type) & ~PSA_KEY_TYPE_DH_GROUP_MASK) == \ + PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE) + +/** Extract the group from a Diffie-Hellman key type. */ +#define PSA_KEY_TYPE_DH_GET_FAMILY(type) \ + ((psa_dh_family_t) (PSA_KEY_TYPE_IS_DH(type) ? \ + ((type) & PSA_KEY_TYPE_DH_GROUP_MASK) : \ + 0)) + +/** Diffie-Hellman groups defined in RFC 7919 Appendix A. + * + * This family includes groups with the following key sizes (in bits): + * 2048, 3072, 4096, 6144, 8192. A given implementation may support + * all of these sizes or only a subset. + */ +#define PSA_DH_FAMILY_RFC7919 ((psa_dh_family_t) 0x03) + +#define PSA_GET_KEY_TYPE_BLOCK_SIZE_EXPONENT(type) \ + (((type) >> 8) & 7) +/** The block size of a block cipher. + * + * \param type A cipher key type (value of type #psa_key_type_t). + * + * \return The block size for a block cipher, or 1 for a stream cipher. + * The return value is undefined if \p type is not a supported + * cipher key type. + * + * \note It is possible to build stream cipher algorithms on top of a block + * cipher, for example CTR mode (#PSA_ALG_CTR). + * This macro only takes the key type into account, so it cannot be + * used to determine the size of the data that #psa_cipher_update() + * might buffer for future processing in general. + * + * \note This macro returns a compile-time constant if its argument is one. + * + * \warning This macro may evaluate its argument multiple times. + */ +#define PSA_BLOCK_CIPHER_BLOCK_LENGTH(type) \ + (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_SYMMETRIC ? \ + 1u << PSA_GET_KEY_TYPE_BLOCK_SIZE_EXPONENT(type) : \ + 0u) + +/* Note that algorithm values are embedded in the persistent key store, + * as part of key metadata. As a consequence, they must not be changed + * (unless the storage format version changes). + */ + +/** Vendor-defined algorithm flag. + * + * Algorithms defined by this standard will never have the #PSA_ALG_VENDOR_FLAG + * bit set. Vendors who define additional algorithms must use an encoding with + * the #PSA_ALG_VENDOR_FLAG bit set and should respect the bitwise structure + * used by standard encodings whenever practical. + */ +#define PSA_ALG_VENDOR_FLAG ((psa_algorithm_t) 0x80000000) + +#define PSA_ALG_CATEGORY_MASK ((psa_algorithm_t) 0x7f000000) +#define PSA_ALG_CATEGORY_HASH ((psa_algorithm_t) 0x02000000) +#define PSA_ALG_CATEGORY_MAC ((psa_algorithm_t) 0x03000000) +#define PSA_ALG_CATEGORY_CIPHER ((psa_algorithm_t) 0x04000000) +#define PSA_ALG_CATEGORY_AEAD ((psa_algorithm_t) 0x05000000) +#define PSA_ALG_CATEGORY_SIGN ((psa_algorithm_t) 0x06000000) +#define PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION ((psa_algorithm_t) 0x07000000) +#define PSA_ALG_CATEGORY_KEY_DERIVATION ((psa_algorithm_t) 0x08000000) +#define PSA_ALG_CATEGORY_KEY_AGREEMENT ((psa_algorithm_t) 0x09000000) + +/** Whether an algorithm is vendor-defined. + * + * See also #PSA_ALG_VENDOR_FLAG. + */ +#define PSA_ALG_IS_VENDOR_DEFINED(alg) \ + (((alg) & PSA_ALG_VENDOR_FLAG) != 0) + +/** Whether the specified algorithm is a hash algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a hash algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_HASH(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_HASH) + +/** Whether the specified algorithm is a MAC algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a MAC algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_MAC(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_MAC) + +/** Whether the specified algorithm is a symmetric cipher algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a symmetric cipher algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_CIPHER(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_CIPHER) + +/** Whether the specified algorithm is an authenticated encryption + * with associated data (AEAD) algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is an AEAD algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_AEAD(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_AEAD) + +/** Whether the specified algorithm is an asymmetric signature algorithm, + * also known as public-key signature algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is an asymmetric signature algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_SIGN(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_SIGN) + +/** Whether the specified algorithm is an asymmetric encryption algorithm, + * also known as public-key encryption algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is an asymmetric encryption algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION) + +/** Whether the specified algorithm is a key agreement algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a key agreement algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_KEY_AGREEMENT(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_AGREEMENT) + +/** Whether the specified algorithm is a key derivation algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a key derivation algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_KEY_DERIVATION(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_DERIVATION) + +/** Whether the specified algorithm is a key stretching / password hashing + * algorithm. + * + * A key stretching / password hashing algorithm is a key derivation algorithm + * that is suitable for use with a low-entropy secret such as a password. + * Equivalently, it's a key derivation algorithm that uses a + * #PSA_KEY_DERIVATION_INPUT_PASSWORD input step. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a key stretching / password hashing algorithm, 0 + * otherwise. This macro may return either 0 or 1 if \p alg is not a + * supported algorithm identifier. + */ +#define PSA_ALG_IS_KEY_DERIVATION_STRETCHING(alg) \ + (PSA_ALG_IS_KEY_DERIVATION(alg) && \ + (alg) & PSA_ALG_KEY_DERIVATION_STRETCHING_FLAG) + +/** An invalid algorithm identifier value. */ +/* *INDENT-OFF* (https://github.com/ARM-software/psa-arch-tests/issues/337) */ +#define PSA_ALG_NONE ((psa_algorithm_t)0) +/* *INDENT-ON* */ + +#define PSA_ALG_HASH_MASK ((psa_algorithm_t) 0x000000ff) +/** MD5 */ +#define PSA_ALG_MD5 ((psa_algorithm_t) 0x02000003) +/** PSA_ALG_RIPEMD160 */ +#define PSA_ALG_RIPEMD160 ((psa_algorithm_t) 0x02000004) +/** SHA1 */ +#define PSA_ALG_SHA_1 ((psa_algorithm_t) 0x02000005) +/** SHA2-224 */ +#define PSA_ALG_SHA_224 ((psa_algorithm_t) 0x02000008) +/** SHA2-256 */ +#define PSA_ALG_SHA_256 ((psa_algorithm_t) 0x02000009) +/** SHA2-384 */ +#define PSA_ALG_SHA_384 ((psa_algorithm_t) 0x0200000a) +/** SHA2-512 */ +#define PSA_ALG_SHA_512 ((psa_algorithm_t) 0x0200000b) +/** SHA2-512/224 */ +#define PSA_ALG_SHA_512_224 ((psa_algorithm_t) 0x0200000c) +/** SHA2-512/256 */ +#define PSA_ALG_SHA_512_256 ((psa_algorithm_t) 0x0200000d) +/** SHA3-224 */ +#define PSA_ALG_SHA3_224 ((psa_algorithm_t) 0x02000010) +/** SHA3-256 */ +#define PSA_ALG_SHA3_256 ((psa_algorithm_t) 0x02000011) +/** SHA3-384 */ +#define PSA_ALG_SHA3_384 ((psa_algorithm_t) 0x02000012) +/** SHA3-512 */ +#define PSA_ALG_SHA3_512 ((psa_algorithm_t) 0x02000013) +/** The first 512 bits (64 bytes) of the SHAKE256 output. + * + * This is the prehashing for Ed448ph (see #PSA_ALG_ED448PH). For other + * scenarios where a hash function based on SHA3/SHAKE is desired, SHA3-512 + * has the same output size and a (theoretically) higher security strength. + */ +#define PSA_ALG_SHAKE256_512 ((psa_algorithm_t) 0x02000015) + +/** In a hash-and-sign algorithm policy, allow any hash algorithm. + * + * This value may be used to form the algorithm usage field of a policy + * for a signature algorithm that is parametrized by a hash. The key + * may then be used to perform operations using the same signature + * algorithm parametrized with any supported hash. + * + * That is, suppose that `PSA_xxx_SIGNATURE` is one of the following macros: + * - #PSA_ALG_RSA_PKCS1V15_SIGN, #PSA_ALG_RSA_PSS, #PSA_ALG_RSA_PSS_ANY_SALT, + * - #PSA_ALG_ECDSA, #PSA_ALG_DETERMINISTIC_ECDSA. + * Then you may create and use a key as follows: + * - Set the key usage field using #PSA_ALG_ANY_HASH, for example: + * ``` + * psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); // or VERIFY + * psa_set_key_algorithm(&attributes, PSA_xxx_SIGNATURE(PSA_ALG_ANY_HASH)); + * ``` + * - Import or generate key material. + * - Call psa_sign_hash() or psa_verify_hash(), passing + * an algorithm built from `PSA_xxx_SIGNATURE` and a specific hash. Each + * call to sign or verify a message may use a different hash. + * ``` + * psa_sign_hash(key, PSA_xxx_SIGNATURE(PSA_ALG_SHA_256), ...); + * psa_sign_hash(key, PSA_xxx_SIGNATURE(PSA_ALG_SHA_512), ...); + * psa_sign_hash(key, PSA_xxx_SIGNATURE(PSA_ALG_SHA3_256), ...); + * ``` + * + * This value may not be used to build other algorithms that are + * parametrized over a hash. For any valid use of this macro to build + * an algorithm \c alg, #PSA_ALG_IS_HASH_AND_SIGN(\c alg) is true. + * + * This value may not be used to build an algorithm specification to + * perform an operation. It is only valid to build policies. + */ +#define PSA_ALG_ANY_HASH ((psa_algorithm_t) 0x020000ff) + +#define PSA_ALG_MAC_SUBCATEGORY_MASK ((psa_algorithm_t) 0x00c00000) +#define PSA_ALG_HMAC_BASE ((psa_algorithm_t) 0x03800000) +/** Macro to build an HMAC algorithm. + * + * For example, #PSA_ALG_HMAC(#PSA_ALG_SHA_256) is HMAC-SHA-256. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * + * \return The corresponding HMAC algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_HMAC(hash_alg) \ + (PSA_ALG_HMAC_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) + +#define PSA_ALG_HMAC_GET_HASH(hmac_alg) \ + (PSA_ALG_CATEGORY_HASH | ((hmac_alg) & PSA_ALG_HASH_MASK)) + +/** Whether the specified algorithm is an HMAC algorithm. + * + * HMAC is a family of MAC algorithms that are based on a hash function. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is an HMAC algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_HMAC(alg) \ + (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_MAC_SUBCATEGORY_MASK)) == \ + PSA_ALG_HMAC_BASE) + +/* In the encoding of a MAC algorithm, the bits corresponding to + * PSA_ALG_MAC_TRUNCATION_MASK encode the length to which the MAC is + * truncated. As an exception, the value 0 means the untruncated algorithm, + * whatever its length is. The length is encoded in 6 bits, so it can + * reach up to 63; the largest MAC is 64 bytes so its trivial truncation + * to full length is correctly encoded as 0 and any non-trivial truncation + * is correctly encoded as a value between 1 and 63. */ +#define PSA_ALG_MAC_TRUNCATION_MASK ((psa_algorithm_t) 0x003f0000) +#define PSA_MAC_TRUNCATION_OFFSET 16 + +/* In the encoding of a MAC algorithm, the bit corresponding to + * #PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG encodes the fact that the algorithm + * is a wildcard algorithm. A key with such wildcard algorithm as permitted + * algorithm policy can be used with any algorithm corresponding to the + * same base class and having a (potentially truncated) MAC length greater or + * equal than the one encoded in #PSA_ALG_MAC_TRUNCATION_MASK. */ +#define PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG ((psa_algorithm_t) 0x00008000) + +/** Macro to build a truncated MAC algorithm. + * + * A truncated MAC algorithm is identical to the corresponding MAC + * algorithm except that the MAC value for the truncated algorithm + * consists of only the first \p mac_length bytes of the MAC value + * for the untruncated algorithm. + * + * \note This macro may allow constructing algorithm identifiers that + * are not valid, either because the specified length is larger + * than the untruncated MAC or because the specified length is + * smaller than permitted by the implementation. + * + * \note It is implementation-defined whether a truncated MAC that + * is truncated to the same length as the MAC of the untruncated + * algorithm is considered identical to the untruncated algorithm + * for policy comparison purposes. + * + * \param mac_alg A MAC algorithm identifier (value of type + * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p mac_alg) + * is true). This may be a truncated or untruncated + * MAC algorithm. + * \param mac_length Desired length of the truncated MAC in bytes. + * This must be at most the full length of the MAC + * and must be at least an implementation-specified + * minimum. The implementation-specified minimum + * shall not be zero. + * + * \return The corresponding MAC algorithm with the specified + * length. + * \return Unspecified if \p mac_alg is not a supported + * MAC algorithm or if \p mac_length is too small or + * too large for the specified MAC algorithm. + */ +#define PSA_ALG_TRUNCATED_MAC(mac_alg, mac_length) \ + (((mac_alg) & ~(PSA_ALG_MAC_TRUNCATION_MASK | \ + PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG)) | \ + ((mac_length) << PSA_MAC_TRUNCATION_OFFSET & PSA_ALG_MAC_TRUNCATION_MASK)) + +/** Macro to build the base MAC algorithm corresponding to a truncated + * MAC algorithm. + * + * \param mac_alg A MAC algorithm identifier (value of type + * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p mac_alg) + * is true). This may be a truncated or untruncated + * MAC algorithm. + * + * \return The corresponding base MAC algorithm. + * \return Unspecified if \p mac_alg is not a supported + * MAC algorithm. + */ +#define PSA_ALG_FULL_LENGTH_MAC(mac_alg) \ + ((mac_alg) & ~(PSA_ALG_MAC_TRUNCATION_MASK | \ + PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG)) + +/** Length to which a MAC algorithm is truncated. + * + * \param mac_alg A MAC algorithm identifier (value of type + * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p mac_alg) + * is true). + * + * \return Length of the truncated MAC in bytes. + * \return 0 if \p mac_alg is a non-truncated MAC algorithm. + * \return Unspecified if \p mac_alg is not a supported + * MAC algorithm. + */ +#define PSA_MAC_TRUNCATED_LENGTH(mac_alg) \ + (((mac_alg) & PSA_ALG_MAC_TRUNCATION_MASK) >> PSA_MAC_TRUNCATION_OFFSET) + +/** Macro to build a MAC minimum-MAC-length wildcard algorithm. + * + * A minimum-MAC-length MAC wildcard algorithm permits all MAC algorithms + * sharing the same base algorithm, and where the (potentially truncated) MAC + * length of the specific algorithm is equal to or larger then the wildcard + * algorithm's minimum MAC length. + * + * \note When setting the minimum required MAC length to less than the + * smallest MAC length allowed by the base algorithm, this effectively + * becomes an 'any-MAC-length-allowed' policy for that base algorithm. + * + * \param mac_alg A MAC algorithm identifier (value of type + * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p mac_alg) + * is true). + * \param min_mac_length Desired minimum length of the message authentication + * code in bytes. This must be at most the untruncated + * length of the MAC and must be at least 1. + * + * \return The corresponding MAC wildcard algorithm with the + * specified minimum length. + * \return Unspecified if \p mac_alg is not a supported MAC + * algorithm or if \p min_mac_length is less than 1 or + * too large for the specified MAC algorithm. + */ +#define PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(mac_alg, min_mac_length) \ + (PSA_ALG_TRUNCATED_MAC(mac_alg, min_mac_length) | \ + PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) + +#define PSA_ALG_CIPHER_MAC_BASE ((psa_algorithm_t) 0x03c00000) +/** The CBC-MAC construction over a block cipher + * + * \warning CBC-MAC is insecure in many cases. + * A more secure mode, such as #PSA_ALG_CMAC, is recommended. + */ +#define PSA_ALG_CBC_MAC ((psa_algorithm_t) 0x03c00100) +/** The CMAC construction over a block cipher */ +#define PSA_ALG_CMAC ((psa_algorithm_t) 0x03c00200) + +/** Whether the specified algorithm is a MAC algorithm based on a block cipher. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a MAC algorithm based on a block cipher, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_BLOCK_CIPHER_MAC(alg) \ + (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_MAC_SUBCATEGORY_MASK)) == \ + PSA_ALG_CIPHER_MAC_BASE) + +#define PSA_ALG_CIPHER_STREAM_FLAG ((psa_algorithm_t) 0x00800000) +#define PSA_ALG_CIPHER_FROM_BLOCK_FLAG ((psa_algorithm_t) 0x00400000) + +/** Whether the specified algorithm is a stream cipher. + * + * A stream cipher is a symmetric cipher that encrypts or decrypts messages + * by applying a bitwise-xor with a stream of bytes that is generated + * from a key. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a stream cipher algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier or if it is not a symmetric cipher algorithm. + */ +#define PSA_ALG_IS_STREAM_CIPHER(alg) \ + (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_CIPHER_STREAM_FLAG)) == \ + (PSA_ALG_CATEGORY_CIPHER | PSA_ALG_CIPHER_STREAM_FLAG)) + +/** The stream cipher mode of a stream cipher algorithm. + * + * The underlying stream cipher is determined by the key type. + * - To use ChaCha20, use a key type of #PSA_KEY_TYPE_CHACHA20. + */ +#define PSA_ALG_STREAM_CIPHER ((psa_algorithm_t) 0x04800100) + +/** The CTR stream cipher mode. + * + * CTR is a stream cipher which is built from a block cipher. + * The underlying block cipher is determined by the key type. + * For example, to use AES-128-CTR, use this algorithm with + * a key of type #PSA_KEY_TYPE_AES and a length of 128 bits (16 bytes). + */ +#define PSA_ALG_CTR ((psa_algorithm_t) 0x04c01000) + +/** The CFB stream cipher mode. + * + * The underlying block cipher is determined by the key type. + */ +#define PSA_ALG_CFB ((psa_algorithm_t) 0x04c01100) + +/** The OFB stream cipher mode. + * + * The underlying block cipher is determined by the key type. + */ +#define PSA_ALG_OFB ((psa_algorithm_t) 0x04c01200) + +/** The XTS cipher mode. + * + * XTS is a cipher mode which is built from a block cipher. It requires at + * least one full block of input, but beyond this minimum the input + * does not need to be a whole number of blocks. + */ +#define PSA_ALG_XTS ((psa_algorithm_t) 0x0440ff00) + +/** The Electronic Code Book (ECB) mode of a block cipher, with no padding. + * + * \warning ECB mode does not protect the confidentiality of the encrypted data + * except in extremely narrow circumstances. It is recommended that applications + * only use ECB if they need to construct an operating mode that the + * implementation does not provide. Implementations are encouraged to provide + * the modes that applications need in preference to supporting direct access + * to ECB. + * + * The underlying block cipher is determined by the key type. + * + * This symmetric cipher mode can only be used with messages whose lengths are a + * multiple of the block size of the chosen block cipher. + * + * ECB mode does not accept an initialization vector (IV). When using a + * multi-part cipher operation with this algorithm, psa_cipher_generate_iv() + * and psa_cipher_set_iv() must not be called. + */ +#define PSA_ALG_ECB_NO_PADDING ((psa_algorithm_t) 0x04404400) + +/** The CBC block cipher chaining mode, with no padding. + * + * The underlying block cipher is determined by the key type. + * + * This symmetric cipher mode can only be used with messages whose lengths + * are whole number of blocks for the chosen block cipher. + */ +#define PSA_ALG_CBC_NO_PADDING ((psa_algorithm_t) 0x04404000) + +/** The CBC block cipher chaining mode with PKCS#7 padding. + * + * The underlying block cipher is determined by the key type. + * + * This is the padding method defined by PKCS#7 (RFC 2315) §10.3. + */ +#define PSA_ALG_CBC_PKCS7 ((psa_algorithm_t) 0x04404100) + +#define PSA_ALG_AEAD_FROM_BLOCK_FLAG ((psa_algorithm_t) 0x00400000) + +/** Whether the specified algorithm is an AEAD mode on a block cipher. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is an AEAD algorithm which is an AEAD mode based on + * a block cipher, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) \ + (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_AEAD_FROM_BLOCK_FLAG)) == \ + (PSA_ALG_CATEGORY_AEAD | PSA_ALG_AEAD_FROM_BLOCK_FLAG)) + +/** The CCM authenticated encryption algorithm. + * + * The underlying block cipher is determined by the key type. + */ +#define PSA_ALG_CCM ((psa_algorithm_t) 0x05500100) + +/** The CCM* cipher mode without authentication. + * + * This is CCM* as specified in IEEE 802.15.4 §7, with a tag length of 0. + * For CCM* with a nonzero tag length, use the AEAD algorithm #PSA_ALG_CCM. + * + * The underlying block cipher is determined by the key type. + * + * Currently only 13-byte long IV's are supported. + */ +#define PSA_ALG_CCM_STAR_NO_TAG ((psa_algorithm_t) 0x04c01300) + +/** The GCM authenticated encryption algorithm. + * + * The underlying block cipher is determined by the key type. + */ +#define PSA_ALG_GCM ((psa_algorithm_t) 0x05500200) + +/** The Chacha20-Poly1305 AEAD algorithm. + * + * The ChaCha20_Poly1305 construction is defined in RFC 7539. + * + * Implementations must support 12-byte nonces, may support 8-byte nonces, + * and should reject other sizes. + * + * Implementations must support 16-byte tags and should reject other sizes. + */ +#define PSA_ALG_CHACHA20_POLY1305 ((psa_algorithm_t) 0x05100500) + +/* In the encoding of an AEAD algorithm, the bits corresponding to + * PSA_ALG_AEAD_TAG_LENGTH_MASK encode the length of the AEAD tag. + * The constants for default lengths follow this encoding. + */ +#define PSA_ALG_AEAD_TAG_LENGTH_MASK ((psa_algorithm_t) 0x003f0000) +#define PSA_AEAD_TAG_LENGTH_OFFSET 16 + +/* In the encoding of an AEAD algorithm, the bit corresponding to + * #PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG encodes the fact that the algorithm + * is a wildcard algorithm. A key with such wildcard algorithm as permitted + * algorithm policy can be used with any algorithm corresponding to the + * same base class and having a tag length greater than or equal to the one + * encoded in #PSA_ALG_AEAD_TAG_LENGTH_MASK. */ +#define PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG ((psa_algorithm_t) 0x00008000) + +/** Macro to build a shortened AEAD algorithm. + * + * A shortened AEAD algorithm is similar to the corresponding AEAD + * algorithm, but has an authentication tag that consists of fewer bytes. + * Depending on the algorithm, the tag length may affect the calculation + * of the ciphertext. + * + * \param aead_alg An AEAD algorithm identifier (value of type + * #psa_algorithm_t such that #PSA_ALG_IS_AEAD(\p aead_alg) + * is true). + * \param tag_length Desired length of the authentication tag in bytes. + * + * \return The corresponding AEAD algorithm with the specified + * length. + * \return Unspecified if \p aead_alg is not a supported + * AEAD algorithm or if \p tag_length is not valid + * for the specified AEAD algorithm. + */ +#define PSA_ALG_AEAD_WITH_SHORTENED_TAG(aead_alg, tag_length) \ + (((aead_alg) & ~(PSA_ALG_AEAD_TAG_LENGTH_MASK | \ + PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG)) | \ + ((tag_length) << PSA_AEAD_TAG_LENGTH_OFFSET & \ + PSA_ALG_AEAD_TAG_LENGTH_MASK)) + +/** Retrieve the tag length of a specified AEAD algorithm + * + * \param aead_alg An AEAD algorithm identifier (value of type + * #psa_algorithm_t such that #PSA_ALG_IS_AEAD(\p aead_alg) + * is true). + * + * \return The tag length specified by the input algorithm. + * \return Unspecified if \p aead_alg is not a supported + * AEAD algorithm. + */ +#define PSA_ALG_AEAD_GET_TAG_LENGTH(aead_alg) \ + (((aead_alg) & PSA_ALG_AEAD_TAG_LENGTH_MASK) >> \ + PSA_AEAD_TAG_LENGTH_OFFSET) + +/** Calculate the corresponding AEAD algorithm with the default tag length. + * + * \param aead_alg An AEAD algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p aead_alg) is true). + * + * \return The corresponding AEAD algorithm with the default + * tag length for that algorithm. + */ +#define PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(aead_alg) \ + ( \ + PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG_CASE(aead_alg, PSA_ALG_CCM) \ + PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG_CASE(aead_alg, PSA_ALG_GCM) \ + PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG_CASE(aead_alg, PSA_ALG_CHACHA20_POLY1305) \ + 0) +#define PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG_CASE(aead_alg, ref) \ + PSA_ALG_AEAD_WITH_SHORTENED_TAG(aead_alg, 0) == \ + PSA_ALG_AEAD_WITH_SHORTENED_TAG(ref, 0) ? \ + ref : + +/** Macro to build an AEAD minimum-tag-length wildcard algorithm. + * + * A minimum-tag-length AEAD wildcard algorithm permits all AEAD algorithms + * sharing the same base algorithm, and where the tag length of the specific + * algorithm is equal to or larger then the minimum tag length specified by the + * wildcard algorithm. + * + * \note When setting the minimum required tag length to less than the + * smallest tag length allowed by the base algorithm, this effectively + * becomes an 'any-tag-length-allowed' policy for that base algorithm. + * + * \param aead_alg An AEAD algorithm identifier (value of type + * #psa_algorithm_t such that + * #PSA_ALG_IS_AEAD(\p aead_alg) is true). + * \param min_tag_length Desired minimum length of the authentication tag in + * bytes. This must be at least 1 and at most the largest + * allowed tag length of the algorithm. + * + * \return The corresponding AEAD wildcard algorithm with the + * specified minimum length. + * \return Unspecified if \p aead_alg is not a supported + * AEAD algorithm or if \p min_tag_length is less than 1 + * or too large for the specified AEAD algorithm. + */ +#define PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(aead_alg, min_tag_length) \ + (PSA_ALG_AEAD_WITH_SHORTENED_TAG(aead_alg, min_tag_length) | \ + PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) + +#define PSA_ALG_RSA_PKCS1V15_SIGN_BASE ((psa_algorithm_t) 0x06000200) +/** RSA PKCS#1 v1.5 signature with hashing. + * + * This is the signature scheme defined by RFC 8017 + * (PKCS#1: RSA Cryptography Specifications) under the name + * RSASSA-PKCS1-v1_5. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding RSA PKCS#1 v1.5 signature algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_RSA_PKCS1V15_SIGN(hash_alg) \ + (PSA_ALG_RSA_PKCS1V15_SIGN_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +/** Raw PKCS#1 v1.5 signature. + * + * The input to this algorithm is the DigestInfo structure used by + * RFC 8017 (PKCS#1: RSA Cryptography Specifications), §9.2 + * steps 3–6. + */ +#define PSA_ALG_RSA_PKCS1V15_SIGN_RAW PSA_ALG_RSA_PKCS1V15_SIGN_BASE +#define PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PKCS1V15_SIGN_BASE) + +#define PSA_ALG_RSA_PSS_BASE ((psa_algorithm_t) 0x06000300) +#define PSA_ALG_RSA_PSS_ANY_SALT_BASE ((psa_algorithm_t) 0x06001300) +/** RSA PSS signature with hashing. + * + * This is the signature scheme defined by RFC 8017 + * (PKCS#1: RSA Cryptography Specifications) under the name + * RSASSA-PSS, with the message generation function MGF1, and with + * a salt length equal to the length of the hash, or the largest + * possible salt length for the algorithm and key size if that is + * smaller than the hash length. The specified hash algorithm is + * used to hash the input message, to create the salted hash, and + * for the mask generation. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding RSA PSS signature algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_RSA_PSS(hash_alg) \ + (PSA_ALG_RSA_PSS_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) + +/** RSA PSS signature with hashing with relaxed verification. + * + * This algorithm has the same behavior as #PSA_ALG_RSA_PSS when signing, + * but allows an arbitrary salt length (including \c 0) when verifying a + * signature. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding RSA PSS signature algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_RSA_PSS_ANY_SALT(hash_alg) \ + (PSA_ALG_RSA_PSS_ANY_SALT_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) + +/** Whether the specified algorithm is RSA PSS with standard salt. + * + * \param alg An algorithm value or an algorithm policy wildcard. + * + * \return 1 if \p alg is of the form + * #PSA_ALG_RSA_PSS(\c hash_alg), + * where \c hash_alg is a hash algorithm or + * #PSA_ALG_ANY_HASH. 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not + * a supported algorithm identifier or policy. + */ +#define PSA_ALG_IS_RSA_PSS_STANDARD_SALT(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PSS_BASE) + +/** Whether the specified algorithm is RSA PSS with any salt. + * + * \param alg An algorithm value or an algorithm policy wildcard. + * + * \return 1 if \p alg is of the form + * #PSA_ALG_RSA_PSS_ANY_SALT_BASE(\c hash_alg), + * where \c hash_alg is a hash algorithm or + * #PSA_ALG_ANY_HASH. 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not + * a supported algorithm identifier or policy. + */ +#define PSA_ALG_IS_RSA_PSS_ANY_SALT(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PSS_ANY_SALT_BASE) + +/** Whether the specified algorithm is RSA PSS. + * + * This includes any of the RSA PSS algorithm variants, regardless of the + * constraints on salt length. + * + * \param alg An algorithm value or an algorithm policy wildcard. + * + * \return 1 if \p alg is of the form + * #PSA_ALG_RSA_PSS(\c hash_alg) or + * #PSA_ALG_RSA_PSS_ANY_SALT_BASE(\c hash_alg), + * where \c hash_alg is a hash algorithm or + * #PSA_ALG_ANY_HASH. 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not + * a supported algorithm identifier or policy. + */ +#define PSA_ALG_IS_RSA_PSS(alg) \ + (PSA_ALG_IS_RSA_PSS_STANDARD_SALT(alg) || \ + PSA_ALG_IS_RSA_PSS_ANY_SALT(alg)) + +#define PSA_ALG_ECDSA_BASE ((psa_algorithm_t) 0x06000600) +/** ECDSA signature with hashing. + * + * This is the ECDSA signature scheme defined by ANSI X9.62, + * with a random per-message secret number (*k*). + * + * The representation of the signature as a byte string consists of + * the concatenation of the signature values *r* and *s*. Each of + * *r* and *s* is encoded as an *N*-octet string, where *N* is the length + * of the base point of the curve in octets. Each value is represented + * in big-endian order (most significant octet first). + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding ECDSA signature algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_ECDSA(hash_alg) \ + (PSA_ALG_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +/** ECDSA signature without hashing. + * + * This is the same signature scheme as #PSA_ALG_ECDSA(), but + * without specifying a hash algorithm. This algorithm may only be + * used to sign or verify a sequence of bytes that should be an + * already-calculated hash. Note that the input is padded with + * zeros on the left or truncated on the left as required to fit + * the curve size. + */ +#define PSA_ALG_ECDSA_ANY PSA_ALG_ECDSA_BASE +#define PSA_ALG_DETERMINISTIC_ECDSA_BASE ((psa_algorithm_t) 0x06000700) +/** Deterministic ECDSA signature with hashing. + * + * This is the deterministic ECDSA signature scheme defined by RFC 6979. + * + * The representation of a signature is the same as with #PSA_ALG_ECDSA(). + * + * Note that when this algorithm is used for verification, signatures + * made with randomized ECDSA (#PSA_ALG_ECDSA(\p hash_alg)) with the + * same private key are accepted. In other words, + * #PSA_ALG_DETERMINISTIC_ECDSA(\p hash_alg) differs from + * #PSA_ALG_ECDSA(\p hash_alg) only for signature, not for verification. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding deterministic ECDSA signature + * algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_DETERMINISTIC_ECDSA(hash_alg) \ + (PSA_ALG_DETERMINISTIC_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +#define PSA_ALG_ECDSA_DETERMINISTIC_FLAG ((psa_algorithm_t) 0x00000100) +#define PSA_ALG_IS_ECDSA(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_ECDSA_DETERMINISTIC_FLAG) == \ + PSA_ALG_ECDSA_BASE) +#define PSA_ALG_ECDSA_IS_DETERMINISTIC(alg) \ + (((alg) & PSA_ALG_ECDSA_DETERMINISTIC_FLAG) != 0) +#define PSA_ALG_IS_DETERMINISTIC_ECDSA(alg) \ + (PSA_ALG_IS_ECDSA(alg) && PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) +#define PSA_ALG_IS_RANDOMIZED_ECDSA(alg) \ + (PSA_ALG_IS_ECDSA(alg) && !PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) + +/** Edwards-curve digital signature algorithm without prehashing (PureEdDSA), + * using standard parameters. + * + * Contexts are not supported in the current version of this specification + * because there is no suitable signature interface that can take the + * context as a parameter. A future version of this specification may add + * suitable functions and extend this algorithm to support contexts. + * + * PureEdDSA requires an elliptic curve key on a twisted Edwards curve. + * In this specification, the following curves are supported: + * - #PSA_ECC_FAMILY_TWISTED_EDWARDS, 255-bit: Ed25519 as specified + * in RFC 8032. + * The curve is Edwards25519. + * The hash function used internally is SHA-512. + * - #PSA_ECC_FAMILY_TWISTED_EDWARDS, 448-bit: Ed448 as specified + * in RFC 8032. + * The curve is Edwards448. + * The hash function used internally is the first 114 bytes of the + * SHAKE256 output. + * + * This algorithm can be used with psa_sign_message() and + * psa_verify_message(). Since there is no prehashing, it cannot be used + * with psa_sign_hash() or psa_verify_hash(). + * + * The signature format is the concatenation of R and S as defined by + * RFC 8032 §5.1.6 and §5.2.6 (a 64-byte string for Ed25519, a 114-byte + * string for Ed448). + */ +#define PSA_ALG_PURE_EDDSA ((psa_algorithm_t) 0x06000800) + +#define PSA_ALG_HASH_EDDSA_BASE ((psa_algorithm_t) 0x06000900) +#define PSA_ALG_IS_HASH_EDDSA(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HASH_EDDSA_BASE) + +/** Edwards-curve digital signature algorithm with prehashing (HashEdDSA), + * using SHA-512 and the Edwards25519 curve. + * + * See #PSA_ALG_PURE_EDDSA regarding context support and the signature format. + * + * This algorithm is Ed25519 as specified in RFC 8032. + * The curve is Edwards25519. + * The prehash is SHA-512. + * The hash function used internally is SHA-512. + * + * This is a hash-and-sign algorithm: to calculate a signature, + * you can either: + * - call psa_sign_message() on the message; + * - or calculate the SHA-512 hash of the message + * with psa_hash_compute() + * or with a multi-part hash operation started with psa_hash_setup(), + * using the hash algorithm #PSA_ALG_SHA_512, + * then sign the calculated hash with psa_sign_hash(). + * Verifying a signature is similar, using psa_verify_message() or + * psa_verify_hash() instead of the signature function. + */ +#define PSA_ALG_ED25519PH \ + (PSA_ALG_HASH_EDDSA_BASE | (PSA_ALG_SHA_512 & PSA_ALG_HASH_MASK)) + +/** Edwards-curve digital signature algorithm with prehashing (HashEdDSA), + * using SHAKE256 and the Edwards448 curve. + * + * See #PSA_ALG_PURE_EDDSA regarding context support and the signature format. + * + * This algorithm is Ed448 as specified in RFC 8032. + * The curve is Edwards448. + * The prehash is the first 64 bytes of the SHAKE256 output. + * The hash function used internally is the first 114 bytes of the + * SHAKE256 output. + * + * This is a hash-and-sign algorithm: to calculate a signature, + * you can either: + * - call psa_sign_message() on the message; + * - or calculate the first 64 bytes of the SHAKE256 output of the message + * with psa_hash_compute() + * or with a multi-part hash operation started with psa_hash_setup(), + * using the hash algorithm #PSA_ALG_SHAKE256_512, + * then sign the calculated hash with psa_sign_hash(). + * Verifying a signature is similar, using psa_verify_message() or + * psa_verify_hash() instead of the signature function. + */ +#define PSA_ALG_ED448PH \ + (PSA_ALG_HASH_EDDSA_BASE | (PSA_ALG_SHAKE256_512 & PSA_ALG_HASH_MASK)) + +/* Default definition, to be overridden if the library is extended with + * more hash-and-sign algorithms that we want to keep out of this header + * file. */ +#define PSA_ALG_IS_VENDOR_HASH_AND_SIGN(alg) 0 + +/** Whether the specified algorithm is a signature algorithm that can be used + * with psa_sign_hash() and psa_verify_hash(). + * + * This encompasses all strict hash-and-sign algorithms categorized by + * PSA_ALG_IS_HASH_AND_SIGN(), as well as algorithms that follow the + * paradigm more loosely: + * - #PSA_ALG_RSA_PKCS1V15_SIGN_RAW (expects its input to be an encoded hash) + * - #PSA_ALG_ECDSA_ANY (doesn't specify what kind of hash the input is) + * + * \param alg An algorithm identifier (value of type psa_algorithm_t). + * + * \return 1 if alg is a signature algorithm that can be used to sign a + * hash. 0 if alg is a signature algorithm that can only be used + * to sign a message. 0 if alg is not a signature algorithm. + * This macro can return either 0 or 1 if alg is not a + * supported algorithm identifier. + */ +#define PSA_ALG_IS_SIGN_HASH(alg) \ + (PSA_ALG_IS_RSA_PSS(alg) || PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || \ + PSA_ALG_IS_ECDSA(alg) || PSA_ALG_IS_HASH_EDDSA(alg) || \ + PSA_ALG_IS_VENDOR_HASH_AND_SIGN(alg)) + +/** Whether the specified algorithm is a signature algorithm that can be used + * with psa_sign_message() and psa_verify_message(). + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if alg is a signature algorithm that can be used to sign a + * message. 0 if \p alg is a signature algorithm that can only be used + * to sign an already-calculated hash. 0 if \p alg is not a signature + * algorithm. This macro can return either 0 or 1 if \p alg is not a + * supported algorithm identifier. + */ +#define PSA_ALG_IS_SIGN_MESSAGE(alg) \ + (PSA_ALG_IS_SIGN_HASH(alg) || (alg) == PSA_ALG_PURE_EDDSA) + +/** Whether the specified algorithm is a hash-and-sign algorithm. + * + * Hash-and-sign algorithms are asymmetric (public-key) signature algorithms + * structured in two parts: first the calculation of a hash in a way that + * does not depend on the key, then the calculation of a signature from the + * hash value and the key. Hash-and-sign algorithms encode the hash + * used for the hashing step, and you can call #PSA_ALG_SIGN_GET_HASH + * to extract this algorithm. + * + * Thus, for a hash-and-sign algorithm, + * `psa_sign_message(key, alg, input, ...)` is equivalent to + * ``` + * psa_hash_compute(PSA_ALG_SIGN_GET_HASH(alg), input, ..., hash, ...); + * psa_sign_hash(key, alg, hash, ..., signature, ...); + * ``` + * Most usefully, separating the hash from the signature allows the hash + * to be calculated in multiple steps with psa_hash_setup(), psa_hash_update() + * and psa_hash_finish(). Likewise psa_verify_message() is equivalent to + * calculating the hash and then calling psa_verify_hash(). + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a hash-and-sign algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_HASH_AND_SIGN(alg) \ + (PSA_ALG_IS_SIGN_HASH(alg) && \ + ((alg) & PSA_ALG_HASH_MASK) != 0) + +/** Get the hash used by a hash-and-sign signature algorithm. + * + * A hash-and-sign algorithm is a signature algorithm which is + * composed of two phases: first a hashing phase which does not use + * the key and produces a hash of the input message, then a signing + * phase which only uses the hash and the key and not the message + * itself. + * + * \param alg A signature algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_SIGN(\p alg) is true). + * + * \return The underlying hash algorithm if \p alg is a hash-and-sign + * algorithm. + * \return 0 if \p alg is a signature algorithm that does not + * follow the hash-and-sign structure. + * \return Unspecified if \p alg is not a signature algorithm or + * if it is not supported by the implementation. + */ +#define PSA_ALG_SIGN_GET_HASH(alg) \ + (PSA_ALG_IS_HASH_AND_SIGN(alg) ? \ + ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH : \ + 0) + +/** RSA PKCS#1 v1.5 encryption. + */ +#define PSA_ALG_RSA_PKCS1V15_CRYPT ((psa_algorithm_t) 0x07000200) + +#define PSA_ALG_RSA_OAEP_BASE ((psa_algorithm_t) 0x07000300) +/** RSA OAEP encryption. + * + * This is the encryption scheme defined by RFC 8017 + * (PKCS#1: RSA Cryptography Specifications) under the name + * RSAES-OAEP, with the message generation function MGF1. + * + * \param hash_alg The hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true) to use + * for MGF1. + * + * \return The corresponding RSA OAEP encryption algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_RSA_OAEP(hash_alg) \ + (PSA_ALG_RSA_OAEP_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +#define PSA_ALG_IS_RSA_OAEP(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_OAEP_BASE) +#define PSA_ALG_RSA_OAEP_GET_HASH(alg) \ + (PSA_ALG_IS_RSA_OAEP(alg) ? \ + ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH : \ + 0) + +#define PSA_ALG_HKDF_BASE ((psa_algorithm_t) 0x08000100) +/** Macro to build an HKDF algorithm. + * + * For example, `PSA_ALG_HKDF(PSA_ALG_SHA_256)` is HKDF using HMAC-SHA-256. + * + * This key derivation algorithm uses the following inputs: + * - #PSA_KEY_DERIVATION_INPUT_SALT is the salt used in the "extract" step. + * It is optional; if omitted, the derivation uses an empty salt. + * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key used in the "extract" step. + * - #PSA_KEY_DERIVATION_INPUT_INFO is the info string used in the "expand" step. + * You must pass #PSA_KEY_DERIVATION_INPUT_SALT before #PSA_KEY_DERIVATION_INPUT_SECRET. + * You may pass #PSA_KEY_DERIVATION_INPUT_INFO at any time after steup and before + * starting to generate output. + * + * \warning HKDF processes the salt as follows: first hash it with hash_alg + * if the salt is longer than the block size of the hash algorithm; then + * pad with null bytes up to the block size. As a result, it is possible + * for distinct salt inputs to result in the same outputs. To ensure + * unique outputs, it is recommended to use a fixed length for salt values. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * + * \return The corresponding HKDF algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_HKDF(hash_alg) \ + (PSA_ALG_HKDF_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +/** Whether the specified algorithm is an HKDF algorithm. + * + * HKDF is a family of key derivation algorithms that are based on a hash + * function and the HMAC construction. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is an HKDF algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key derivation algorithm identifier. + */ +#define PSA_ALG_IS_HKDF(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_BASE) +#define PSA_ALG_HKDF_GET_HASH(hkdf_alg) \ + (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) + +#define PSA_ALG_HKDF_EXTRACT_BASE ((psa_algorithm_t) 0x08000400) +/** Macro to build an HKDF-Extract algorithm. + * + * For example, `PSA_ALG_HKDF_EXTRACT(PSA_ALG_SHA_256)` is + * HKDF-Extract using HMAC-SHA-256. + * + * This key derivation algorithm uses the following inputs: + * - PSA_KEY_DERIVATION_INPUT_SALT is the salt. + * - PSA_KEY_DERIVATION_INPUT_SECRET is the input keying material used in the + * "extract" step. + * The inputs are mandatory and must be passed in the order above. + * Each input may only be passed once. + * + * \warning HKDF-Extract is not meant to be used on its own. PSA_ALG_HKDF + * should be used instead if possible. PSA_ALG_HKDF_EXTRACT is provided + * as a separate algorithm for the sake of protocols that use it as a + * building block. It may also be a slight performance optimization + * in applications that use HKDF with the same salt and key but many + * different info strings. + * + * \warning HKDF processes the salt as follows: first hash it with hash_alg + * if the salt is longer than the block size of the hash algorithm; then + * pad with null bytes up to the block size. As a result, it is possible + * for distinct salt inputs to result in the same outputs. To ensure + * unique outputs, it is recommended to use a fixed length for salt values. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * + * \return The corresponding HKDF-Extract algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_HKDF_EXTRACT(hash_alg) \ + (PSA_ALG_HKDF_EXTRACT_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +/** Whether the specified algorithm is an HKDF-Extract algorithm. + * + * HKDF-Extract is a family of key derivation algorithms that are based + * on a hash function and the HMAC construction. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is an HKDF-Extract algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key derivation algorithm identifier. + */ +#define PSA_ALG_IS_HKDF_EXTRACT(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_EXTRACT_BASE) + +#define PSA_ALG_HKDF_EXPAND_BASE ((psa_algorithm_t) 0x08000500) +/** Macro to build an HKDF-Expand algorithm. + * + * For example, `PSA_ALG_HKDF_EXPAND(PSA_ALG_SHA_256)` is + * HKDF-Expand using HMAC-SHA-256. + * + * This key derivation algorithm uses the following inputs: + * - PSA_KEY_DERIVATION_INPUT_SECRET is the pseudorandom key (PRK). + * - PSA_KEY_DERIVATION_INPUT_INFO is the info string. + * + * The inputs are mandatory and must be passed in the order above. + * Each input may only be passed once. + * + * \warning HKDF-Expand is not meant to be used on its own. `PSA_ALG_HKDF` + * should be used instead if possible. `PSA_ALG_HKDF_EXPAND` is provided as + * a separate algorithm for the sake of protocols that use it as a building + * block. It may also be a slight performance optimization in applications + * that use HKDF with the same salt and key but many different info strings. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * + * \return The corresponding HKDF-Expand algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_HKDF_EXPAND(hash_alg) \ + (PSA_ALG_HKDF_EXPAND_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +/** Whether the specified algorithm is an HKDF-Expand algorithm. + * + * HKDF-Expand is a family of key derivation algorithms that are based + * on a hash function and the HMAC construction. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is an HKDF-Expand algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key derivation algorithm identifier. + */ +#define PSA_ALG_IS_HKDF_EXPAND(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_EXPAND_BASE) + +/** Whether the specified algorithm is an HKDF or HKDF-Extract or + * HKDF-Expand algorithm. + * + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is any HKDF type algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key derivation algorithm identifier. + */ +#define PSA_ALG_IS_ANY_HKDF(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_BASE || \ + ((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_EXTRACT_BASE || \ + ((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_EXPAND_BASE) + +#define PSA_ALG_TLS12_PRF_BASE ((psa_algorithm_t) 0x08000200) +/** Macro to build a TLS-1.2 PRF algorithm. + * + * TLS 1.2 uses a custom pseudorandom function (PRF) for key schedule, + * specified in Section 5 of RFC 5246. It is based on HMAC and can be + * used with either SHA-256 or SHA-384. + * + * This key derivation algorithm uses the following inputs, which must be + * passed in the order given here: + * - #PSA_KEY_DERIVATION_INPUT_SEED is the seed. + * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key. + * - #PSA_KEY_DERIVATION_INPUT_LABEL is the label. + * + * For the application to TLS-1.2 key expansion, the seed is the + * concatenation of ServerHello.Random + ClientHello.Random, + * and the label is "key expansion". + * + * For example, `PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256)` represents the + * TLS 1.2 PRF using HMAC-SHA-256. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * + * \return The corresponding TLS-1.2 PRF algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_TLS12_PRF(hash_alg) \ + (PSA_ALG_TLS12_PRF_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) + +/** Whether the specified algorithm is a TLS-1.2 PRF algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a TLS-1.2 PRF algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key derivation algorithm identifier. + */ +#define PSA_ALG_IS_TLS12_PRF(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_TLS12_PRF_BASE) +#define PSA_ALG_TLS12_PRF_GET_HASH(hkdf_alg) \ + (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) + +#define PSA_ALG_TLS12_PSK_TO_MS_BASE ((psa_algorithm_t) 0x08000300) +/** Macro to build a TLS-1.2 PSK-to-MasterSecret algorithm. + * + * In a pure-PSK handshake in TLS 1.2, the master secret is derived + * from the PreSharedKey (PSK) through the application of padding + * (RFC 4279, Section 2) and the TLS-1.2 PRF (RFC 5246, Section 5). + * The latter is based on HMAC and can be used with either SHA-256 + * or SHA-384. + * + * This key derivation algorithm uses the following inputs, which must be + * passed in the order given here: + * - #PSA_KEY_DERIVATION_INPUT_SEED is the seed. + * - #PSA_KEY_DERIVATION_INPUT_OTHER_SECRET is the other secret for the + * computation of the premaster secret. This input is optional; + * if omitted, it defaults to a string of null bytes with the same length + * as the secret (PSK) input. + * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key. + * - #PSA_KEY_DERIVATION_INPUT_LABEL is the label. + * + * For the application to TLS-1.2, the seed (which is + * forwarded to the TLS-1.2 PRF) is the concatenation of the + * ClientHello.Random + ServerHello.Random, + * the label is "master secret" or "extended master secret" and + * the other secret depends on the key exchange specified in the cipher suite: + * - for a plain PSK cipher suite (RFC 4279, Section 2), omit + * PSA_KEY_DERIVATION_INPUT_OTHER_SECRET + * - for a DHE-PSK (RFC 4279, Section 3) or ECDHE-PSK cipher suite + * (RFC 5489, Section 2), the other secret should be the output of the + * PSA_ALG_FFDH or PSA_ALG_ECDH key agreement performed with the peer. + * The recommended way to pass this input is to use a key derivation + * algorithm constructed as + * PSA_ALG_KEY_AGREEMENT(ka_alg, PSA_ALG_TLS12_PSK_TO_MS(hash_alg)) + * and to call psa_key_derivation_key_agreement(). Alternatively, + * this input may be an output of `psa_raw_key_agreement()` passed with + * psa_key_derivation_input_bytes(), or an equivalent input passed with + * psa_key_derivation_input_bytes() or psa_key_derivation_input_key(). + * - for a RSA-PSK cipher suite (RFC 4279, Section 4), the other secret + * should be the 48-byte client challenge (the PreMasterSecret of + * (RFC 5246, Section 7.4.7.1)) concatenation of the TLS version and + * a 46-byte random string chosen by the client. On the server, this is + * typically an output of psa_asymmetric_decrypt() using + * PSA_ALG_RSA_PKCS1V15_CRYPT, passed to the key derivation operation + * with `psa_key_derivation_input_bytes()`. + * + * For example, `PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256)` represents the + * TLS-1.2 PSK to MasterSecret derivation PRF using HMAC-SHA-256. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * + * \return The corresponding TLS-1.2 PSK to MS algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_TLS12_PSK_TO_MS(hash_alg) \ + (PSA_ALG_TLS12_PSK_TO_MS_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) + +/** Whether the specified algorithm is a TLS-1.2 PSK to MS algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a TLS-1.2 PSK to MS algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key derivation algorithm identifier. + */ +#define PSA_ALG_IS_TLS12_PSK_TO_MS(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_TLS12_PSK_TO_MS_BASE) +#define PSA_ALG_TLS12_PSK_TO_MS_GET_HASH(hkdf_alg) \ + (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) + +/* The TLS 1.2 ECJPAKE-to-PMS KDF. It takes the shared secret K (an EC point + * in case of EC J-PAKE) and calculates SHA256(K.X) that the rest of TLS 1.2 + * will use to derive the session secret, as defined by step 2 of + * https://datatracker.ietf.org/doc/html/draft-cragie-tls-ecjpake-01#section-8.7. + * Uses PSA_ALG_SHA_256. + * This function takes a single input: + * #PSA_KEY_DERIVATION_INPUT_SECRET is the shared secret K from EC J-PAKE. + * The only supported curve is secp256r1 (the 256-bit curve in + * #PSA_ECC_FAMILY_SECP_R1), so the input must be exactly 65 bytes. + * The output has to be read as a single chunk of 32 bytes, defined as + * PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE. + */ +#define PSA_ALG_TLS12_ECJPAKE_TO_PMS ((psa_algorithm_t) 0x08000609) + +/* This flag indicates whether the key derivation algorithm is suitable for + * use on low-entropy secrets such as password - these algorithms are also + * known as key stretching or password hashing schemes. These are also the + * algorithms that accepts inputs of type #PSA_KEY_DERIVATION_INPUT_PASSWORD. + * + * Those algorithms cannot be combined with a key agreement algorithm. + */ +#define PSA_ALG_KEY_DERIVATION_STRETCHING_FLAG ((psa_algorithm_t) 0x00800000) + +#define PSA_ALG_PBKDF2_HMAC_BASE ((psa_algorithm_t) 0x08800100) +/** Macro to build a PBKDF2-HMAC password hashing / key stretching algorithm. + * + * PBKDF2 is defined by PKCS#5, republished as RFC 8018 (section 5.2). + * This macro specifies the PBKDF2 algorithm constructed using a PRF based on + * HMAC with the specified hash. + * For example, `PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_256)` specifies PBKDF2 + * using the PRF HMAC-SHA-256. + * + * This key derivation algorithm uses the following inputs, which must be + * provided in the following order: + * - #PSA_KEY_DERIVATION_INPUT_COST is the iteration count. + * This input step must be used exactly once. + * - #PSA_KEY_DERIVATION_INPUT_SALT is the salt. + * This input step must be used one or more times; if used several times, the + * inputs will be concatenated. This can be used to build the final salt + * from multiple sources, both public and secret (also known as pepper). + * - #PSA_KEY_DERIVATION_INPUT_PASSWORD is the password to be hashed. + * This input step must be used exactly once. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * + * \return The corresponding PBKDF2-HMAC-XXX algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_PBKDF2_HMAC(hash_alg) \ + (PSA_ALG_PBKDF2_HMAC_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) + +/** Whether the specified algorithm is a PBKDF2-HMAC algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a PBKDF2-HMAC algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key derivation algorithm identifier. + */ +#define PSA_ALG_IS_PBKDF2_HMAC(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_PBKDF2_HMAC_BASE) + +/** The PBKDF2-AES-CMAC-PRF-128 password hashing / key stretching algorithm. + * + * PBKDF2 is defined by PKCS#5, republished as RFC 8018 (section 5.2). + * This macro specifies the PBKDF2 algorithm constructed using the + * AES-CMAC-PRF-128 PRF specified by RFC 4615. + * + * This key derivation algorithm uses the same inputs as + * #PSA_ALG_PBKDF2_HMAC() with the same constraints. + */ +#define PSA_ALG_PBKDF2_AES_CMAC_PRF_128 ((psa_algorithm_t) 0x08800200) + +#define PSA_ALG_KEY_DERIVATION_MASK ((psa_algorithm_t) 0xfe00ffff) +#define PSA_ALG_KEY_AGREEMENT_MASK ((psa_algorithm_t) 0xffff0000) + +/** Macro to build a combined algorithm that chains a key agreement with + * a key derivation. + * + * \param ka_alg A key agreement algorithm (\c PSA_ALG_XXX value such + * that #PSA_ALG_IS_KEY_AGREEMENT(\p ka_alg) is true). + * \param kdf_alg A key derivation algorithm (\c PSA_ALG_XXX value such + * that #PSA_ALG_IS_KEY_DERIVATION(\p kdf_alg) is true). + * + * \return The corresponding key agreement and derivation + * algorithm. + * \return Unspecified if \p ka_alg is not a supported + * key agreement algorithm or \p kdf_alg is not a + * supported key derivation algorithm. + */ +#define PSA_ALG_KEY_AGREEMENT(ka_alg, kdf_alg) \ + ((ka_alg) | (kdf_alg)) + +#define PSA_ALG_KEY_AGREEMENT_GET_KDF(alg) \ + (((alg) & PSA_ALG_KEY_DERIVATION_MASK) | PSA_ALG_CATEGORY_KEY_DERIVATION) + +#define PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) \ + (((alg) & PSA_ALG_KEY_AGREEMENT_MASK) | PSA_ALG_CATEGORY_KEY_AGREEMENT) + +/** Whether the specified algorithm is a raw key agreement algorithm. + * + * A raw key agreement algorithm is one that does not specify + * a key derivation function. + * Usually, raw key agreement algorithms are constructed directly with + * a \c PSA_ALG_xxx macro while non-raw key agreement algorithms are + * constructed with #PSA_ALG_KEY_AGREEMENT(). + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a raw key agreement algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_RAW_KEY_AGREEMENT(alg) \ + (PSA_ALG_IS_KEY_AGREEMENT(alg) && \ + PSA_ALG_KEY_AGREEMENT_GET_KDF(alg) == PSA_ALG_CATEGORY_KEY_DERIVATION) + +#define PSA_ALG_IS_KEY_DERIVATION_OR_AGREEMENT(alg) \ + ((PSA_ALG_IS_KEY_DERIVATION(alg) || PSA_ALG_IS_KEY_AGREEMENT(alg))) + +/** The finite-field Diffie-Hellman (DH) key agreement algorithm. + * + * The shared secret produced by key agreement is + * `g^{ab}` in big-endian format. + * It is `ceiling(m / 8)` bytes long where `m` is the size of the prime `p` + * in bits. + */ +#define PSA_ALG_FFDH ((psa_algorithm_t) 0x09010000) + +/** Whether the specified algorithm is a finite field Diffie-Hellman algorithm. + * + * This includes the raw finite field Diffie-Hellman algorithm as well as + * finite-field Diffie-Hellman followed by any supporter key derivation + * algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a finite field Diffie-Hellman algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key agreement algorithm identifier. + */ +#define PSA_ALG_IS_FFDH(alg) \ + (PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) == PSA_ALG_FFDH) + +/** The elliptic curve Diffie-Hellman (ECDH) key agreement algorithm. + * + * The shared secret produced by key agreement is the x-coordinate of + * the shared secret point. It is always `ceiling(m / 8)` bytes long where + * `m` is the bit size associated with the curve, i.e. the bit size of the + * order of the curve's coordinate field. When `m` is not a multiple of 8, + * the byte containing the most significant bit of the shared secret + * is padded with zero bits. The byte order is either little-endian + * or big-endian depending on the curve type. + * + * - For Montgomery curves (curve types `PSA_ECC_FAMILY_CURVEXXX`), + * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` + * in little-endian byte order. + * The bit size is 448 for Curve448 and 255 for Curve25519. + * - For Weierstrass curves over prime fields (curve types + * `PSA_ECC_FAMILY_SECPXXX` and `PSA_ECC_FAMILY_BRAINPOOL_PXXX`), + * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` + * in big-endian byte order. + * The bit size is `m = ceiling(log_2(p))` for the field `F_p`. + * - For Weierstrass curves over binary fields (curve types + * `PSA_ECC_FAMILY_SECTXXX`), + * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` + * in big-endian byte order. + * The bit size is `m` for the field `F_{2^m}`. + */ +#define PSA_ALG_ECDH ((psa_algorithm_t) 0x09020000) + +/** Whether the specified algorithm is an elliptic curve Diffie-Hellman + * algorithm. + * + * This includes the raw elliptic curve Diffie-Hellman algorithm as well as + * elliptic curve Diffie-Hellman followed by any supporter key derivation + * algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is an elliptic curve Diffie-Hellman algorithm, + * 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key agreement algorithm identifier. + */ +#define PSA_ALG_IS_ECDH(alg) \ + (PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) == PSA_ALG_ECDH) + +/** Whether the specified algorithm encoding is a wildcard. + * + * Wildcard values may only be used to set the usage algorithm field in + * a policy, not to perform an operation. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a wildcard algorithm encoding. + * \return 0 if \c alg is a non-wildcard algorithm encoding (suitable for + * an operation). + * \return This macro may return either 0 or 1 if \c alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_WILDCARD(alg) \ + (PSA_ALG_IS_HASH_AND_SIGN(alg) ? \ + PSA_ALG_SIGN_GET_HASH(alg) == PSA_ALG_ANY_HASH : \ + PSA_ALG_IS_MAC(alg) ? \ + (alg & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) != 0 : \ + PSA_ALG_IS_AEAD(alg) ? \ + (alg & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) != 0 : \ + (alg) == PSA_ALG_ANY_HASH) + +/** Get the hash used by a composite algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return The underlying hash algorithm if alg is a composite algorithm that + * uses a hash algorithm. + * + * \return \c 0 if alg is not a composite algorithm that uses a hash. + */ +#define PSA_ALG_GET_HASH(alg) \ + (((alg) & 0x000000ff) == 0 ? ((psa_algorithm_t) 0) : 0x02000000 | ((alg) & 0x000000ff)) + +/**@}*/ + +/** \defgroup key_lifetimes Key lifetimes + * @{ + */ + +/* Note that location and persistence level values are embedded in the + * persistent key store, as part of key metadata. As a consequence, they + * must not be changed (unless the storage format version changes). + */ + +/** The default lifetime for volatile keys. + * + * A volatile key only exists as long as the identifier to it is not destroyed. + * The key material is guaranteed to be erased on a power reset. + * + * A key with this lifetime is typically stored in the RAM area of the + * PSA Crypto subsystem. However this is an implementation choice. + * If an implementation stores data about the key in a non-volatile memory, + * it must release all the resources associated with the key and erase the + * key material if the calling application terminates. + */ +#define PSA_KEY_LIFETIME_VOLATILE ((psa_key_lifetime_t) 0x00000000) + +/** The default lifetime for persistent keys. + * + * A persistent key remains in storage until it is explicitly destroyed or + * until the corresponding storage area is wiped. This specification does + * not define any mechanism to wipe a storage area, but integrations may + * provide their own mechanism (for example to perform a factory reset, + * to prepare for device refurbishment, or to uninstall an application). + * + * This lifetime value is the default storage area for the calling + * application. Integrations of Mbed TLS may support other persistent lifetimes. + * See ::psa_key_lifetime_t for more information. + */ +#define PSA_KEY_LIFETIME_PERSISTENT ((psa_key_lifetime_t) 0x00000001) + +/** The persistence level of volatile keys. + * + * See ::psa_key_persistence_t for more information. + */ +#define PSA_KEY_PERSISTENCE_VOLATILE ((psa_key_persistence_t) 0x00) + +/** The default persistence level for persistent keys. + * + * See ::psa_key_persistence_t for more information. + */ +#define PSA_KEY_PERSISTENCE_DEFAULT ((psa_key_persistence_t) 0x01) + +/** A persistence level indicating that a key is never destroyed. + * + * See ::psa_key_persistence_t for more information. + */ +#define PSA_KEY_PERSISTENCE_READ_ONLY ((psa_key_persistence_t) 0xff) + +#define PSA_KEY_LIFETIME_GET_PERSISTENCE(lifetime) \ + ((psa_key_persistence_t) ((lifetime) & 0x000000ff)) + +#define PSA_KEY_LIFETIME_GET_LOCATION(lifetime) \ + ((psa_key_location_t) ((lifetime) >> 8)) + +/** Whether a key lifetime indicates that the key is volatile. + * + * A volatile key is automatically destroyed by the implementation when + * the application instance terminates. In particular, a volatile key + * is automatically destroyed on a power reset of the device. + * + * A key that is not volatile is persistent. Persistent keys are + * preserved until the application explicitly destroys them or until an + * implementation-specific device management event occurs (for example, + * a factory reset). + * + * \param lifetime The lifetime value to query (value of type + * ::psa_key_lifetime_t). + * + * \return \c 1 if the key is volatile, otherwise \c 0. + */ +#define PSA_KEY_LIFETIME_IS_VOLATILE(lifetime) \ + (PSA_KEY_LIFETIME_GET_PERSISTENCE(lifetime) == \ + PSA_KEY_PERSISTENCE_VOLATILE) + +/** Whether a key lifetime indicates that the key is read-only. + * + * Read-only keys cannot be created or destroyed through the PSA Crypto API. + * They must be created through platform-specific means that bypass the API. + * + * Some platforms may offer ways to destroy read-only keys. For example, + * consider a platform with multiple levels of privilege, where a + * low-privilege application can use a key but is not allowed to destroy + * it, and the platform exposes the key to the application with a read-only + * lifetime. High-privilege code can destroy the key even though the + * application sees the key as read-only. + * + * \param lifetime The lifetime value to query (value of type + * ::psa_key_lifetime_t). + * + * \return \c 1 if the key is read-only, otherwise \c 0. + */ +#define PSA_KEY_LIFETIME_IS_READ_ONLY(lifetime) \ + (PSA_KEY_LIFETIME_GET_PERSISTENCE(lifetime) == \ + PSA_KEY_PERSISTENCE_READ_ONLY) + +/** Construct a lifetime from a persistence level and a location. + * + * \param persistence The persistence level + * (value of type ::psa_key_persistence_t). + * \param location The location indicator + * (value of type ::psa_key_location_t). + * + * \return The constructed lifetime value. + */ +#define PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(persistence, location) \ + ((location) << 8 | (persistence)) + +/** The local storage area for persistent keys. + * + * This storage area is available on all systems that can store persistent + * keys without delegating the storage to a third-party cryptoprocessor. + * + * See ::psa_key_location_t for more information. + */ +#define PSA_KEY_LOCATION_LOCAL_STORAGE ((psa_key_location_t) 0x000000) + +#define PSA_KEY_LOCATION_VENDOR_FLAG ((psa_key_location_t) 0x800000) + +/* Note that key identifier values are embedded in the + * persistent key store, as part of key metadata. As a consequence, they + * must not be changed (unless the storage format version changes). + */ + +/** The null key identifier. + */ +/* *INDENT-OFF* (https://github.com/ARM-software/psa-arch-tests/issues/337) */ +#define PSA_KEY_ID_NULL ((psa_key_id_t)0) +/* *INDENT-ON* */ +/** The minimum value for a key identifier chosen by the application. + */ +#define PSA_KEY_ID_USER_MIN ((psa_key_id_t) 0x00000001) +/** The maximum value for a key identifier chosen by the application. + */ +#define PSA_KEY_ID_USER_MAX ((psa_key_id_t) 0x3fffffff) +/** The minimum value for a key identifier chosen by the implementation. + */ +#define PSA_KEY_ID_VENDOR_MIN ((psa_key_id_t) 0x40000000) +/** The maximum value for a key identifier chosen by the implementation. + */ +#define PSA_KEY_ID_VENDOR_MAX ((psa_key_id_t) 0x7fffffff) + + +#if !defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) + +#define MBEDTLS_SVC_KEY_ID_INIT ((psa_key_id_t) 0) +#define MBEDTLS_SVC_KEY_ID_GET_KEY_ID(id) (id) +#define MBEDTLS_SVC_KEY_ID_GET_OWNER_ID(id) (0) + +/** Utility to initialize a key identifier at runtime. + * + * \param unused Unused parameter. + * \param key_id Identifier of the key. + */ +static inline mbedtls_svc_key_id_t mbedtls_svc_key_id_make( + unsigned int unused, psa_key_id_t key_id) +{ + (void) unused; + + return key_id; +} + +/** Compare two key identifiers. + * + * \param id1 First key identifier. + * \param id2 Second key identifier. + * + * \return Non-zero if the two key identifier are equal, zero otherwise. + */ +static inline int mbedtls_svc_key_id_equal(mbedtls_svc_key_id_t id1, + mbedtls_svc_key_id_t id2) +{ + return id1 == id2; +} + +/** Check whether a key identifier is null. + * + * \param key Key identifier. + * + * \return Non-zero if the key identifier is null, zero otherwise. + */ +static inline int mbedtls_svc_key_id_is_null(mbedtls_svc_key_id_t key) +{ + return key == 0; +} + +#else /* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */ + +#define MBEDTLS_SVC_KEY_ID_INIT ((mbedtls_svc_key_id_t){ 0, 0 }) +#define MBEDTLS_SVC_KEY_ID_GET_KEY_ID(id) ((id).MBEDTLS_PRIVATE(key_id)) +#define MBEDTLS_SVC_KEY_ID_GET_OWNER_ID(id) ((id).MBEDTLS_PRIVATE(owner)) + +/** Utility to initialize a key identifier at runtime. + * + * \param owner_id Identifier of the key owner. + * \param key_id Identifier of the key. + */ +static inline mbedtls_svc_key_id_t mbedtls_svc_key_id_make( + mbedtls_key_owner_id_t owner_id, psa_key_id_t key_id) +{ + return (mbedtls_svc_key_id_t){ .MBEDTLS_PRIVATE(key_id) = key_id, + .MBEDTLS_PRIVATE(owner) = owner_id }; +} + +/** Compare two key identifiers. + * + * \param id1 First key identifier. + * \param id2 Second key identifier. + * + * \return Non-zero if the two key identifier are equal, zero otherwise. + */ +static inline int mbedtls_svc_key_id_equal(mbedtls_svc_key_id_t id1, + mbedtls_svc_key_id_t id2) +{ + return (id1.MBEDTLS_PRIVATE(key_id) == id2.MBEDTLS_PRIVATE(key_id)) && + mbedtls_key_owner_id_equal(id1.MBEDTLS_PRIVATE(owner), id2.MBEDTLS_PRIVATE(owner)); +} + +/** Check whether a key identifier is null. + * + * \param key Key identifier. + * + * \return Non-zero if the key identifier is null, zero otherwise. + */ +static inline int mbedtls_svc_key_id_is_null(mbedtls_svc_key_id_t key) +{ + return key.MBEDTLS_PRIVATE(key_id) == 0; +} + +#endif /* !MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */ + +/**@}*/ + +/** \defgroup policy Key policies + * @{ + */ + +/* Note that key usage flags are embedded in the + * persistent key store, as part of key metadata. As a consequence, they + * must not be changed (unless the storage format version changes). + */ + +/** Whether the key may be exported. + * + * A public key or the public part of a key pair may always be exported + * regardless of the value of this permission flag. + * + * If a key does not have export permission, implementations shall not + * allow the key to be exported in plain form from the cryptoprocessor, + * whether through psa_export_key() or through a proprietary interface. + * The key may however be exportable in a wrapped form, i.e. in a form + * where it is encrypted by another key. + */ +#define PSA_KEY_USAGE_EXPORT ((psa_key_usage_t) 0x00000001) + +/** Whether the key may be copied. + * + * This flag allows the use of psa_copy_key() to make a copy of the key + * with the same policy or a more restrictive policy. + * + * For lifetimes for which the key is located in a secure element which + * enforce the non-exportability of keys, copying a key outside the secure + * element also requires the usage flag #PSA_KEY_USAGE_EXPORT. + * Copying the key inside the secure element is permitted with just + * #PSA_KEY_USAGE_COPY if the secure element supports it. + * For keys with the lifetime #PSA_KEY_LIFETIME_VOLATILE or + * #PSA_KEY_LIFETIME_PERSISTENT, the usage flag #PSA_KEY_USAGE_COPY + * is sufficient to permit the copy. + */ +#define PSA_KEY_USAGE_COPY ((psa_key_usage_t) 0x00000002) + +/** Whether the key may be used to encrypt a message. + * + * This flag allows the key to be used for a symmetric encryption operation, + * for an AEAD encryption-and-authentication operation, + * or for an asymmetric encryption operation, + * if otherwise permitted by the key's type and policy. + * + * For a key pair, this concerns the public key. + */ +#define PSA_KEY_USAGE_ENCRYPT ((psa_key_usage_t) 0x00000100) + +/** Whether the key may be used to decrypt a message. + * + * This flag allows the key to be used for a symmetric decryption operation, + * for an AEAD decryption-and-verification operation, + * or for an asymmetric decryption operation, + * if otherwise permitted by the key's type and policy. + * + * For a key pair, this concerns the private key. + */ +#define PSA_KEY_USAGE_DECRYPT ((psa_key_usage_t) 0x00000200) + +/** Whether the key may be used to sign a message. + * + * This flag allows the key to be used for a MAC calculation operation or for + * an asymmetric message signature operation, if otherwise permitted by the + * key’s type and policy. + * + * For a key pair, this concerns the private key. + */ +#define PSA_KEY_USAGE_SIGN_MESSAGE ((psa_key_usage_t) 0x00000400) + +/** Whether the key may be used to verify a message. + * + * This flag allows the key to be used for a MAC verification operation or for + * an asymmetric message signature verification operation, if otherwise + * permitted by the key’s type and policy. + * + * For a key pair, this concerns the public key. + */ +#define PSA_KEY_USAGE_VERIFY_MESSAGE ((psa_key_usage_t) 0x00000800) + +/** Whether the key may be used to sign a message. + * + * This flag allows the key to be used for a MAC calculation operation + * or for an asymmetric signature operation, + * if otherwise permitted by the key's type and policy. + * + * For a key pair, this concerns the private key. + */ +#define PSA_KEY_USAGE_SIGN_HASH ((psa_key_usage_t) 0x00001000) + +/** Whether the key may be used to verify a message signature. + * + * This flag allows the key to be used for a MAC verification operation + * or for an asymmetric signature verification operation, + * if otherwise permitted by the key's type and policy. + * + * For a key pair, this concerns the public key. + */ +#define PSA_KEY_USAGE_VERIFY_HASH ((psa_key_usage_t) 0x00002000) + +/** Whether the key may be used to derive other keys or produce a password + * hash. + * + * This flag allows the key to be used for a key derivation operation or for + * a key agreement operation, if otherwise permitted by the key's type and + * policy. + * + * If this flag is present on all keys used in calls to + * psa_key_derivation_input_key() for a key derivation operation, then it + * permits calling psa_key_derivation_output_bytes() or + * psa_key_derivation_output_key() at the end of the operation. + */ +#define PSA_KEY_USAGE_DERIVE ((psa_key_usage_t) 0x00004000) + +/** Whether the key may be used to verify the result of a key derivation, + * including password hashing. + * + * This flag allows the key to be used: + * + * This flag allows the key to be used in a key derivation operation, if + * otherwise permitted by the key's type and policy. + * + * If this flag is present on all keys used in calls to + * psa_key_derivation_input_key() for a key derivation operation, then it + * permits calling psa_key_derivation_verify_bytes() or + * psa_key_derivation_verify_key() at the end of the operation. + */ +#define PSA_KEY_USAGE_VERIFY_DERIVATION ((psa_key_usage_t) 0x00008000) + +/**@}*/ + +/** \defgroup derivation Key derivation + * @{ + */ + +/* Key input steps are not embedded in the persistent storage, so you can + * change them if needed: it's only an ABI change. */ + +/** A secret input for key derivation. + * + * This should be a key of type #PSA_KEY_TYPE_DERIVE + * (passed to psa_key_derivation_input_key()) + * or the shared secret resulting from a key agreement + * (obtained via psa_key_derivation_key_agreement()). + * + * The secret can also be a direct input (passed to + * key_derivation_input_bytes()). In this case, the derivation operation + * may not be used to derive keys: the operation will only allow + * psa_key_derivation_output_bytes(), + * psa_key_derivation_verify_bytes(), or + * psa_key_derivation_verify_key(), but not + * psa_key_derivation_output_key(). + */ +#define PSA_KEY_DERIVATION_INPUT_SECRET ((psa_key_derivation_step_t) 0x0101) + +/** A low-entropy secret input for password hashing / key stretching. + * + * This is usually a key of type #PSA_KEY_TYPE_PASSWORD (passed to + * psa_key_derivation_input_key()) or a direct input (passed to + * psa_key_derivation_input_bytes()) that is a password or passphrase. It can + * also be high-entropy secret such as a key of type #PSA_KEY_TYPE_DERIVE or + * the shared secret resulting from a key agreement. + * + * The secret can also be a direct input (passed to + * key_derivation_input_bytes()). In this case, the derivation operation + * may not be used to derive keys: the operation will only allow + * psa_key_derivation_output_bytes(), + * psa_key_derivation_verify_bytes(), or + * psa_key_derivation_verify_key(), but not + * psa_key_derivation_output_key(). + */ +#define PSA_KEY_DERIVATION_INPUT_PASSWORD ((psa_key_derivation_step_t) 0x0102) + +/** A high-entropy additional secret input for key derivation. + * + * This is typically the shared secret resulting from a key agreement obtained + * via `psa_key_derivation_key_agreement()`. It may alternatively be a key of + * type `PSA_KEY_TYPE_DERIVE` passed to `psa_key_derivation_input_key()`, or + * a direct input passed to `psa_key_derivation_input_bytes()`. + */ +#define PSA_KEY_DERIVATION_INPUT_OTHER_SECRET \ + ((psa_key_derivation_step_t) 0x0103) + +/** A label for key derivation. + * + * This should be a direct input. + * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. + */ +#define PSA_KEY_DERIVATION_INPUT_LABEL ((psa_key_derivation_step_t) 0x0201) + +/** A salt for key derivation. + * + * This should be a direct input. + * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA or + * #PSA_KEY_TYPE_PEPPER. + */ +#define PSA_KEY_DERIVATION_INPUT_SALT ((psa_key_derivation_step_t) 0x0202) + +/** An information string for key derivation. + * + * This should be a direct input. + * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. + */ +#define PSA_KEY_DERIVATION_INPUT_INFO ((psa_key_derivation_step_t) 0x0203) + +/** A seed for key derivation. + * + * This should be a direct input. + * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. + */ +#define PSA_KEY_DERIVATION_INPUT_SEED ((psa_key_derivation_step_t) 0x0204) + +/** A cost parameter for password hashing / key stretching. + * + * This must be a direct input, passed to psa_key_derivation_input_integer(). + */ +#define PSA_KEY_DERIVATION_INPUT_COST ((psa_key_derivation_step_t) 0x0205) + +/**@}*/ + +/** \defgroup helper_macros Helper macros + * @{ + */ + +/* Helper macros */ + +/** Check if two AEAD algorithm identifiers refer to the same AEAD algorithm + * regardless of the tag length they encode. + * + * \param aead_alg_1 An AEAD algorithm identifier. + * \param aead_alg_2 An AEAD algorithm identifier. + * + * \return 1 if both identifiers refer to the same AEAD algorithm, + * 0 otherwise. + * Unspecified if neither \p aead_alg_1 nor \p aead_alg_2 are + * a supported AEAD algorithm. + */ +#define MBEDTLS_PSA_ALG_AEAD_EQUAL(aead_alg_1, aead_alg_2) \ + (!(((aead_alg_1) ^ (aead_alg_2)) & \ + ~(PSA_ALG_AEAD_TAG_LENGTH_MASK | PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG))) + +/**@}*/ + +/**@}*/ + +/** \defgroup interruptible Interruptible operations + * @{ + */ + +/** Maximum value for use with \c psa_interruptible_set_max_ops() to determine + * the maximum number of ops allowed to be executed by an interruptible + * function in a single call. + */ +#define PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED UINT32_MAX + +/**@}*/ + +#endif /* PSA_CRYPTO_VALUES_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..69da582 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/aes.c @@ -0,0 +1,2178 @@ +/* + * 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 "padlock.h" +#endif +#if defined(MBEDTLS_AESNI_C) +#include "aesni.h" +#endif +#if defined(MBEDTLS_AESCE_C) +#include "aesce.h" +#endif + +#include "mbedtls/platform.h" + +#if !defined(MBEDTLS_AES_ALT) + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86) +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) +{ + 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) +{ + 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 */ + +/* Some implementations need the round keys to be aligned. + * Return an offset to be added to buf, such that (buf + offset) is + * correctly aligned. + * Note that the offset is in units of elements of buf, i.e. 32-bit words, + * i.e. an offset of 1 means 4 bytes and so on. + */ +#if (defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)) || \ + (defined(MBEDTLS_AESNI_C) && MBEDTLS_AESNI_HAVE_CODE == 2) +#define MAY_NEED_TO_ALIGN +#endif +static unsigned mbedtls_aes_rk_offset(uint32_t *buf) +{ +#if defined(MAY_NEED_TO_ALIGN) + int align_16_bytes = 0; + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86) + if (aes_padlock_ace == -1) { + aes_padlock_ace = mbedtls_padlock_has_support(MBEDTLS_PADLOCK_ACE); + } + if (aes_padlock_ace) { + align_16_bytes = 1; + } +#endif + +#if defined(MBEDTLS_AESNI_C) && MBEDTLS_AESNI_HAVE_CODE == 2 + if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) { + align_16_bytes = 1; + } +#endif + + if (align_16_bytes) { + /* These implementations needs 16-byte alignment + * for the round key array. */ + unsigned delta = ((uintptr_t) buf & 0x0000000fU) / 4; + if (delta == 0) { + return 0; + } else { + return 4 - delta; // 16 bytes = 4 uint32_t + } + } +#else /* MAY_NEED_TO_ALIGN */ + (void) buf; +#endif /* MAY_NEED_TO_ALIGN */ + + return 0; +} + +/* + * 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; + + 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 + + ctx->rk_offset = mbedtls_aes_rk_offset(ctx->buf); + RK = ctx->buf + ctx->rk_offset; + +#if defined(MBEDTLS_AESNI_HAVE_CODE) + if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) { + return mbedtls_aesni_setkey_enc((unsigned char *) RK, key, keybits); + } +#endif + +#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64) + if (mbedtls_aesce_has_support()) { + return mbedtls_aesce_setkey_enc((unsigned char *) 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; + + mbedtls_aes_init(&cty); + + ctx->rk_offset = mbedtls_aes_rk_offset(ctx->buf); + RK = ctx->buf + ctx->rk_offset; + + /* Also checks keybits */ + if ((ret = mbedtls_aes_setkey_enc(&cty, key, keybits)) != 0) { + goto exit; + } + + ctx->nr = cty.nr; + +#if defined(MBEDTLS_AESNI_HAVE_CODE) + if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) { + mbedtls_aesni_inverse_key((unsigned char *) RK, + (const unsigned char *) (cty.buf + cty.rk_offset), ctx->nr); + goto exit; + } +#endif + +#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64) + if (mbedtls_aesce_has_support()) { + mbedtls_aesce_inverse_key( + (unsigned char *) RK, + (const unsigned char *) (cty.buf + cty.rk_offset), + ctx->nr); + goto exit; + } +#endif + + SK = cty.buf + cty.rk_offset + 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; + + 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; + + 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->buf + ctx->rk_offset; + 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 */ + +/* + * 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->buf + ctx->rk_offset; + 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(MAY_NEED_TO_ALIGN) +/* VIA Padlock and our intrinsics-based implementation of AESNI require + * the round keys to be aligned on a 16-byte boundary. We take care of this + * before creating them, but the AES context may have moved (this can happen + * if the library is called from a language with managed memory), and in later + * calls it might have a different alignment with respect to 16-byte memory. + * So we may need to realign. + */ +static void aes_maybe_realign(mbedtls_aes_context *ctx) +{ + unsigned new_offset = mbedtls_aes_rk_offset(ctx->buf); + if (new_offset != ctx->rk_offset) { + memmove(ctx->buf + new_offset, // new address + ctx->buf + ctx->rk_offset, // current address + (ctx->nr + 1) * 16); // number of round keys * bytes per rk + ctx->rk_offset = new_offset; + } +} +#endif + +/* + * 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]) +{ + if (mode != MBEDTLS_AES_ENCRYPT && mode != MBEDTLS_AES_DECRYPT) { + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + +#if defined(MAY_NEED_TO_ALIGN) + aes_maybe_realign(ctx); +#endif + +#if defined(MBEDTLS_AESNI_HAVE_CODE) + if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) { + return mbedtls_aesni_crypt_ecb(ctx, mode, input, output); + } +#endif + +#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64) + if (mbedtls_aesce_has_support()) { + return mbedtls_aesce_crypt_ecb(ctx, mode, input, output); + } +#endif + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86) + if (aes_padlock_ace > 0) { + return mbedtls_padlock_xcryptecb(ctx, mode, input, output); + } +#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 ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char temp[16]; + + if (mode != MBEDTLS_AES_ENCRYPT && mode != MBEDTLS_AES_DECRYPT) { + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + + if (length % 16) { + return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; + } + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86) + if (aes_padlock_ace > 0) { + 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; + } + + mbedtls_xor(output, output, iv, 16); + + memcpy(iv, temp, 16); + + input += 16; + output += 16; + length -= 16; + } + } else { + while (length > 0) { + mbedtls_xor(output, input, iv, 16); + + 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]; + + if (mode != MBEDTLS_AES_ENCRYPT && mode != MBEDTLS_AES_DECRYPT) { + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + + /* 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--) { + 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 leftover 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); + } + + mbedtls_xor(tmp, input, tweak, 16); + + ret = mbedtls_aes_crypt_ecb(&ctx->crypt, mode, tmp, tmp); + if (ret != 0) { + return ret; + } + + mbedtls_xor(output, tmp, tweak, 16); + + /* 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. */ + for (i = 0; i < leftover; i++) { + output[i] = prev_output[i]; + } + + /* Copy the remainder of the input for this final round. */ + mbedtls_xor(tmp, input, t, leftover); + + /* Copy ciphertext bytes from the previous block for input in this + * round. */ + mbedtls_xor(tmp + i, prev_output + i, t + i, 16 - 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. */ + mbedtls_xor(prev_output, tmp, t, 16); + } + + 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; + + if (mode != MBEDTLS_AES_ENCRYPT && mode != MBEDTLS_AES_DECRYPT) { + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + + 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]; + + if (mode != MBEDTLS_AES_ENCRYPT && mode != MBEDTLS_AES_DECRYPT) { + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + 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; + + 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; + + 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) || \ + defined(MBEDTLS_CIPHER_MODE_OFB) + 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); + + if (verbose != 0) { +#if defined(MBEDTLS_AES_ALT) + mbedtls_printf(" AES note: alternative implementation.\n"); +#else /* MBEDTLS_AES_ALT */ +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86) + if (mbedtls_padlock_has_support(MBEDTLS_PADLOCK_ACE)) { + mbedtls_printf(" AES note: using VIA Padlock.\n"); + } else +#endif +#if defined(MBEDTLS_AESNI_HAVE_CODE) + if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) { + mbedtls_printf(" AES note: using AESNI.\n"); + } else +#endif +#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64) + if (mbedtls_aesce_has_support()) { + mbedtls_printf(" AES note: using AESCE.\n"); + } else +#endif + mbedtls_printf(" AES note: built-in implementation.\n"); +#endif /* MBEDTLS_AES_ALT */ + } + + /* + * 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/aesce.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/aesce.c new file mode 100644 index 0000000..fe056dc --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/aesce.c @@ -0,0 +1,411 @@ +/* + * Armv8-A Cryptographic Extension support functions for Aarch64 + * + * 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(__aarch64__) && !defined(__ARM_FEATURE_CRYPTO) && \ + defined(__clang__) && __clang_major__ >= 4 +/* TODO: Re-consider above after https://reviews.llvm.org/D131064 merged. + * + * The intrinsic declaration are guarded by predefined ACLE macros in clang: + * these are normally only enabled by the -march option on the command line. + * By defining the macros ourselves we gain access to those declarations without + * requiring -march on the command line. + * + * `arm_neon.h` could be included by any header file, so we put these defines + * at the top of this file, before any includes. + */ +#define __ARM_FEATURE_CRYPTO 1 +/* See: https://arm-software.github.io/acle/main/acle.html#cryptographic-extensions + * + * `__ARM_FEATURE_CRYPTO` is deprecated, but we need to continue to specify it + * for older compilers. + */ +#define __ARM_FEATURE_AES 1 +#define MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG +#endif + +#include +#include "common.h" + +#if defined(MBEDTLS_AESCE_C) + +#include "aesce.h" + +#if defined(MBEDTLS_HAVE_ARM64) + +#if !defined(__ARM_FEATURE_AES) || defined(MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG) +# if defined(__clang__) +# if __clang_major__ < 4 +# error "A more recent Clang is required for MBEDTLS_AESCE_C" +# endif +# pragma clang attribute push (__attribute__((target("crypto"))), apply_to=function) +# define MBEDTLS_POP_TARGET_PRAGMA +# elif defined(__GNUC__) +# if __GNUC__ < 6 +# error "A more recent GCC is required for MBEDTLS_AESCE_C" +# endif +# pragma GCC push_options +# pragma GCC target ("arch=armv8-a+crypto") +# define MBEDTLS_POP_TARGET_PRAGMA +# else +# error "Only GCC and Clang supported for MBEDTLS_AESCE_C" +# endif +#endif /* !__ARM_FEATURE_AES || MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG */ + +#include + +#if defined(__linux__) +#include +#include +#endif + +/* + * AES instruction support detection routine + */ +int mbedtls_aesce_has_support(void) +{ +#if defined(__linux__) + unsigned long auxval = getauxval(AT_HWCAP); + return (auxval & (HWCAP_ASIMD | HWCAP_AES)) == + (HWCAP_ASIMD | HWCAP_AES); +#else + /* Assume AES instructions are supported. */ + return 1; +#endif +} + +static uint8x16_t aesce_encrypt_block(uint8x16_t block, + unsigned char *keys, + int rounds) +{ + for (int i = 0; i < rounds - 1; i++) { + /* AES AddRoundKey, SubBytes, ShiftRows (in this order). + * AddRoundKey adds the round key for the previous round. */ + block = vaeseq_u8(block, vld1q_u8(keys + i * 16)); + /* AES mix columns */ + block = vaesmcq_u8(block); + } + + /* AES AddRoundKey for the previous round. + * SubBytes, ShiftRows for the final round. */ + block = vaeseq_u8(block, vld1q_u8(keys + (rounds -1) * 16)); + + /* Final round: no MixColumns */ + + /* Final AddRoundKey */ + block = veorq_u8(block, vld1q_u8(keys + rounds * 16)); + + return block; +} + +static uint8x16_t aesce_decrypt_block(uint8x16_t block, + unsigned char *keys, + int rounds) +{ + + for (int i = 0; i < rounds - 1; i++) { + /* AES AddRoundKey, SubBytes, ShiftRows */ + block = vaesdq_u8(block, vld1q_u8(keys + i * 16)); + /* AES inverse MixColumns for the next round. + * + * This means that we switch the order of the inverse AddRoundKey and + * inverse MixColumns operations. We have to do this as AddRoundKey is + * done in an atomic instruction together with the inverses of SubBytes + * and ShiftRows. + * + * It works because MixColumns is a linear operation over GF(2^8) and + * AddRoundKey is an exclusive or, which is equivalent to addition over + * GF(2^8). (The inverse of MixColumns needs to be applied to the + * affected round keys separately which has been done when the + * decryption round keys were calculated.) */ + block = vaesimcq_u8(block); + } + + /* The inverses of AES AddRoundKey, SubBytes, ShiftRows finishing up the + * last full round. */ + block = vaesdq_u8(block, vld1q_u8(keys + (rounds - 1) * 16)); + + /* Inverse AddRoundKey for inverting the initial round key addition. */ + block = veorq_u8(block, vld1q_u8(keys + rounds * 16)); + + return block; +} + +/* + * AES-ECB block en(de)cryption + */ +int mbedtls_aesce_crypt_ecb(mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16]) +{ + uint8x16_t block = vld1q_u8(&input[0]); + unsigned char *keys = (unsigned char *) (ctx->buf + ctx->rk_offset); + + if (mode == MBEDTLS_AES_ENCRYPT) { + block = aesce_encrypt_block(block, keys, ctx->nr); + } else { + block = aesce_decrypt_block(block, keys, ctx->nr); + } + vst1q_u8(&output[0], block); + + return 0; +} + +/* + * Compute decryption round keys from encryption round keys + */ +void mbedtls_aesce_inverse_key(unsigned char *invkey, + const unsigned char *fwdkey, + int nr) +{ + int i, j; + j = nr; + vst1q_u8(invkey, vld1q_u8(fwdkey + j * 16)); + for (i = 1, j--; j > 0; i++, j--) { + vst1q_u8(invkey + i * 16, + vaesimcq_u8(vld1q_u8(fwdkey + j * 16))); + } + vst1q_u8(invkey + i * 16, vld1q_u8(fwdkey + j * 16)); + +} + +static inline uint32_t aes_rot_word(uint32_t word) +{ + return (word << (32 - 8)) | (word >> 8); +} + +static inline uint32_t aes_sub_word(uint32_t in) +{ + uint8x16_t v = vreinterpretq_u8_u32(vdupq_n_u32(in)); + uint8x16_t zero = vdupq_n_u8(0); + + /* vaeseq_u8 does both SubBytes and ShiftRows. Taking the first row yields + * the correct result as ShiftRows doesn't change the first row. */ + v = vaeseq_u8(zero, v); + return vgetq_lane_u32(vreinterpretq_u32_u8(v), 0); +} + +/* + * Key expansion function + */ +static void aesce_setkey_enc(unsigned char *rk, + const unsigned char *key, + const size_t key_bit_length) +{ + static uint8_t const rcon[] = { 0x01, 0x02, 0x04, 0x08, 0x10, + 0x20, 0x40, 0x80, 0x1b, 0x36 }; + /* See https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.197.pdf + * - Section 5, Nr = Nk + 6 + * - Section 5.2, the length of round keys is Nb*(Nr+1) + */ + const uint32_t key_len_in_words = key_bit_length / 32; /* Nk */ + const size_t round_key_len_in_words = 4; /* Nb */ + const size_t rounds_needed = key_len_in_words + 6; /* Nr */ + const size_t round_keys_len_in_words = + round_key_len_in_words * (rounds_needed + 1); /* Nb*(Nr+1) */ + const uint32_t *rko_end = (uint32_t *) rk + round_keys_len_in_words; + + memcpy(rk, key, key_len_in_words * 4); + + for (uint32_t *rki = (uint32_t *) rk; + rki + key_len_in_words < rko_end; + rki += key_len_in_words) { + + size_t iteration = (rki - (uint32_t *) rk) / key_len_in_words; + uint32_t *rko; + rko = rki + key_len_in_words; + rko[0] = aes_rot_word(aes_sub_word(rki[key_len_in_words - 1])); + rko[0] ^= rcon[iteration] ^ rki[0]; + rko[1] = rko[0] ^ rki[1]; + rko[2] = rko[1] ^ rki[2]; + rko[3] = rko[2] ^ rki[3]; + if (rko + key_len_in_words > rko_end) { + /* Do not write overflow words.*/ + continue; + } + switch (key_bit_length) { + case 128: + break; + case 192: + rko[4] = rko[3] ^ rki[4]; + rko[5] = rko[4] ^ rki[5]; + break; + case 256: + rko[4] = aes_sub_word(rko[3]) ^ rki[4]; + rko[5] = rko[4] ^ rki[5]; + rko[6] = rko[5] ^ rki[6]; + rko[7] = rko[6] ^ rki[7]; + break; + } + } +} + +/* + * Key expansion, wrapper + */ +int mbedtls_aesce_setkey_enc(unsigned char *rk, + const unsigned char *key, + size_t bits) +{ + switch (bits) { + case 128: + case 192: + case 256: + aesce_setkey_enc(rk, key, bits); + break; + default: + return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; + } + + return 0; +} + +#if defined(MBEDTLS_GCM_C) + +#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ == 5 +/* Some intrinsics are not available for GCC 5.X. */ +#define vreinterpretq_p64_u8(a) ((poly64x2_t) a) +#define vreinterpretq_u8_p128(a) ((uint8x16_t) a) +static inline poly64_t vget_low_p64(poly64x2_t __a) +{ + uint64x2_t tmp = (uint64x2_t) (__a); + uint64x1_t lo = vcreate_u64(vgetq_lane_u64(tmp, 0)); + return (poly64_t) (lo); +} +#endif /* !__clang__ && __GNUC__ && __GNUC__ == 5*/ + +/* vmull_p64/vmull_high_p64 wrappers. + * + * Older compilers miss some intrinsic functions for `poly*_t`. We use + * uint8x16_t and uint8x16x3_t as input/output parameters. + */ +static inline uint8x16_t pmull_low(uint8x16_t a, uint8x16_t b) +{ + return vreinterpretq_u8_p128( + vmull_p64( + (poly64_t) vget_low_p64(vreinterpretq_p64_u8(a)), + (poly64_t) vget_low_p64(vreinterpretq_p64_u8(b)))); +} + +static inline uint8x16_t pmull_high(uint8x16_t a, uint8x16_t b) +{ + return vreinterpretq_u8_p128( + vmull_high_p64(vreinterpretq_p64_u8(a), + vreinterpretq_p64_u8(b))); +} + +/* GHASH does 128b polynomial multiplication on block in GF(2^128) defined by + * `x^128 + x^7 + x^2 + x + 1`. + * + * Arm64 only has 64b->128b polynomial multipliers, we need to do 4 64b + * multiplies to generate a 128b. + * + * `poly_mult_128` executes polynomial multiplication and outputs 256b that + * represented by 3 128b due to code size optimization. + * + * Output layout: + * | | | | + * |------------|-------------|-------------| + * | ret.val[0] | h3:h2:00:00 | high 128b | + * | ret.val[1] | :m2:m1:00 | middle 128b | + * | ret.val[2] | : :l1:l0 | low 128b | + */ +static inline uint8x16x3_t poly_mult_128(uint8x16_t a, uint8x16_t b) +{ + uint8x16x3_t ret; + uint8x16_t h, m, l; /* retval high/middle/low */ + uint8x16_t c, d, e; + + h = pmull_high(a, b); /* h3:h2:00:00 = a1*b1 */ + l = pmull_low(a, b); /* : :l1:l0 = a0*b0 */ + c = vextq_u8(b, b, 8); /* :c1:c0 = b0:b1 */ + d = pmull_high(a, c); /* :d2:d1:00 = a1*b0 */ + e = pmull_low(a, c); /* :e2:e1:00 = a0*b1 */ + m = veorq_u8(d, e); /* :m2:m1:00 = d + e */ + + ret.val[0] = h; + ret.val[1] = m; + ret.val[2] = l; + return ret; +} + +/* + * Modulo reduction. + * + * See: https://www.researchgate.net/publication/285612706_Implementing_GCM_on_ARMv8 + * + * Section 4.3 + * + * Modular reduction is slightly more complex. Write the GCM modulus as f(z) = + * z^128 +r(z), where r(z) = z^7+z^2+z+ 1. The well known approach is to + * consider that z^128 ≡r(z) (mod z^128 +r(z)), allowing us to write the 256-bit + * operand to be reduced as a(z) = h(z)z^128 +l(z)≡h(z)r(z) + l(z). That is, we + * simply multiply the higher part of the operand by r(z) and add it to l(z). If + * the result is still larger than 128 bits, we reduce again. + */ +static inline uint8x16_t poly_mult_reduce(uint8x16x3_t input) +{ + uint8x16_t const ZERO = vdupq_n_u8(0); + /* use 'asm' as an optimisation barrier to prevent loading MODULO from memory */ + uint64x2_t r = vreinterpretq_u64_u8(vdupq_n_u8(0x87)); + asm ("" : "+w" (r)); + uint8x16_t const MODULO = vreinterpretq_u8_u64(vshrq_n_u64(r, 64 - 8)); + uint8x16_t h, m, l; /* input high/middle/low 128b */ + uint8x16_t c, d, e, f, g, n, o; + h = input.val[0]; /* h3:h2:00:00 */ + m = input.val[1]; /* :m2:m1:00 */ + l = input.val[2]; /* : :l1:l0 */ + c = pmull_high(h, MODULO); /* :c2:c1:00 = reduction of h3 */ + d = pmull_low(h, MODULO); /* : :d1:d0 = reduction of h2 */ + e = veorq_u8(c, m); /* :e2:e1:00 = m2:m1:00 + c2:c1:00 */ + f = pmull_high(e, MODULO); /* : :f1:f0 = reduction of e2 */ + g = vextq_u8(ZERO, e, 8); /* : :g1:00 = e1:00 */ + n = veorq_u8(d, l); /* : :n1:n0 = d1:d0 + l1:l0 */ + o = veorq_u8(n, f); /* o1:o0 = f1:f0 + n1:n0 */ + return veorq_u8(o, g); /* = o1:o0 + g1:00 */ +} + +/* + * GCM multiplication: c = a times b in GF(2^128) + */ +void mbedtls_aesce_gcm_mult(unsigned char c[16], + const unsigned char a[16], + const unsigned char b[16]) +{ + uint8x16_t va, vb, vc; + va = vrbitq_u8(vld1q_u8(&a[0])); + vb = vrbitq_u8(vld1q_u8(&b[0])); + vc = vrbitq_u8(poly_mult_reduce(poly_mult_128(va, vb))); + vst1q_u8(&c[0], vc); +} + +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_POP_TARGET_PRAGMA) +#if defined(__clang__) +#pragma clang attribute pop +#elif defined(__GNUC__) +#pragma GCC pop_options +#endif +#undef MBEDTLS_POP_TARGET_PRAGMA +#endif + +#endif /* MBEDTLS_HAVE_ARM64 */ + +#endif /* MBEDTLS_AESCE_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/aesce.h b/optee/optee_os/lib/libmbedtls/mbedtls/library/aesce.h new file mode 100644 index 0000000..12ddc74 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/aesce.h @@ -0,0 +1,116 @@ +/** + * \file aesce.h + * + * \brief Support hardware AES acceleration on Armv8-A processors with + * the Armv8-A Cryptographic Extension in AArch64 execution state. + * + * \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_AESCE_H +#define MBEDTLS_AESCE_H + +#include "mbedtls/build_info.h" + +#include "mbedtls/aes.h" + + +#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && \ + defined(__aarch64__) && !defined(MBEDTLS_HAVE_ARM64) +#define MBEDTLS_HAVE_ARM64 +#endif + +#if defined(MBEDTLS_HAVE_ARM64) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Internal function to detect the crypto extension in CPUs. + * + * \return 1 if CPU has support for the feature, 0 otherwise + */ +int mbedtls_aesce_has_support(void); + +/** + * \brief Internal AES-ECB block encryption and decryption + * + * \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_aesce_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_aesce_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. + * + * \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_aesce_inverse_key(unsigned char *invkey, + const unsigned char *fwdkey, + int nr); + +/** + * \brief Internal key expansion for encryption + * + * \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_aesce_setkey_enc(unsigned char *rk, + const unsigned char *key, + size_t bits); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_HAVE_ARM64 */ + +#endif /* MBEDTLS_AESCE_H */ 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..a23c5b5 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/aesni.c @@ -0,0 +1,800 @@ +/* + * 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] https://www.intel.com/content/www/us/en/developer/articles/tool/intel-advanced-encryption-standard-aes-instructions-set.html + * [CLMUL-WP] https://www.intel.com/content/www/us/en/develop/download/intel-carry-less-multiplication-instruction-and-its-usage-for-computing-the-gcm-mode.html + */ + +#include "common.h" + +#if defined(MBEDTLS_AESNI_C) + +#include "aesni.h" + +#include + +#if defined(MBEDTLS_AESNI_HAVE_CODE) + +#if MBEDTLS_AESNI_HAVE_CODE == 2 +#if !defined(_WIN32) +#include +#endif +#include +#endif + +/* + * AES-NI support detection routine + */ +int mbedtls_aesni_has_support(unsigned int what) +{ + static int done = 0; + static unsigned int c = 0; + + if (!done) { +#if MBEDTLS_AESNI_HAVE_CODE == 2 + static unsigned info[4] = { 0, 0, 0, 0 }; +#if defined(_MSC_VER) + __cpuid(info, 1); +#else + __cpuid(1, info[0], info[1], info[2], info[3]); +#endif + c = info[2]; +#else /* AESNI using asm */ + asm ("movl $1, %%eax \n\t" + "cpuid \n\t" + : "=c" (c) + : + : "eax", "ebx", "edx"); +#endif /* MBEDTLS_AESNI_HAVE_CODE */ + done = 1; + } + + return (c & what) != 0; +} + +#if MBEDTLS_AESNI_HAVE_CODE == 2 + +/* + * 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]) +{ + const __m128i *rk = (const __m128i *) (ctx->buf + ctx->rk_offset); + unsigned nr = ctx->nr; // Number of remaining rounds + + // Load round key 0 + __m128i state; + memcpy(&state, input, 16); + state = _mm_xor_si128(state, rk[0]); // state ^= *rk; + ++rk; + --nr; + + if (mode == 0) { + while (nr != 0) { + state = _mm_aesdec_si128(state, *rk); + ++rk; + --nr; + } + state = _mm_aesdeclast_si128(state, *rk); + } else { + while (nr != 0) { + state = _mm_aesenc_si128(state, *rk); + ++rk; + --nr; + } + state = _mm_aesenclast_si128(state, *rk); + } + + memcpy(output, &state, 16); + return 0; +} + +/* + * GCM multiplication: c = a times b in GF(2^128) + * Based on [CLMUL-WP] algorithms 1 (with equation 27) and 5. + */ + +static void gcm_clmul(const __m128i aa, const __m128i bb, + __m128i *cc, __m128i *dd) +{ + /* + * Caryless multiplication dd:cc = aa * bb + * using [CLMUL-WP] algorithm 1 (p. 12). + */ + *cc = _mm_clmulepi64_si128(aa, bb, 0x00); // a0*b0 = c1:c0 + *dd = _mm_clmulepi64_si128(aa, bb, 0x11); // a1*b1 = d1:d0 + __m128i ee = _mm_clmulepi64_si128(aa, bb, 0x10); // a0*b1 = e1:e0 + __m128i ff = _mm_clmulepi64_si128(aa, bb, 0x01); // a1*b0 = f1:f0 + ff = _mm_xor_si128(ff, ee); // e1+f1:e0+f0 + ee = ff; // e1+f1:e0+f0 + ff = _mm_srli_si128(ff, 8); // 0:e1+f1 + ee = _mm_slli_si128(ee, 8); // e0+f0:0 + *dd = _mm_xor_si128(*dd, ff); // d1:d0+e1+f1 + *cc = _mm_xor_si128(*cc, ee); // c1+e0+f0:c0 +} + +static void gcm_shift(__m128i *cc, __m128i *dd) +{ + /* [CMUCL-WP] Algorithm 5 Step 1: shift cc:dd one bit to the left, + * taking advantage of [CLMUL-WP] eq 27 (p. 18). */ + // // *cc = r1:r0 + // // *dd = r3:r2 + __m128i cc_lo = _mm_slli_epi64(*cc, 1); // r1<<1:r0<<1 + __m128i dd_lo = _mm_slli_epi64(*dd, 1); // r3<<1:r2<<1 + __m128i cc_hi = _mm_srli_epi64(*cc, 63); // r1>>63:r0>>63 + __m128i dd_hi = _mm_srli_epi64(*dd, 63); // r3>>63:r2>>63 + __m128i xmm5 = _mm_srli_si128(cc_hi, 8); // 0:r1>>63 + cc_hi = _mm_slli_si128(cc_hi, 8); // r0>>63:0 + dd_hi = _mm_slli_si128(dd_hi, 8); // 0:r1>>63 + + *cc = _mm_or_si128(cc_lo, cc_hi); // r1<<1|r0>>63:r0<<1 + *dd = _mm_or_si128(_mm_or_si128(dd_lo, dd_hi), xmm5); // r3<<1|r2>>62:r2<<1|r1>>63 +} + +static __m128i gcm_reduce(__m128i xx) +{ + // // xx = x1:x0 + /* [CLMUL-WP] Algorithm 5 Step 2 */ + __m128i aa = _mm_slli_epi64(xx, 63); // x1<<63:x0<<63 = stuff:a + __m128i bb = _mm_slli_epi64(xx, 62); // x1<<62:x0<<62 = stuff:b + __m128i cc = _mm_slli_epi64(xx, 57); // x1<<57:x0<<57 = stuff:c + __m128i dd = _mm_slli_si128(_mm_xor_si128(_mm_xor_si128(aa, bb), cc), 8); // a+b+c:0 + return _mm_xor_si128(dd, xx); // x1+a+b+c:x0 = d:x0 +} + +static __m128i gcm_mix(__m128i dx) +{ + /* [CLMUL-WP] Algorithm 5 Steps 3 and 4 */ + __m128i ee = _mm_srli_epi64(dx, 1); // e1:x0>>1 = e1:e0' + __m128i ff = _mm_srli_epi64(dx, 2); // f1:x0>>2 = f1:f0' + __m128i gg = _mm_srli_epi64(dx, 7); // g1:x0>>7 = g1:g0' + + // e0'+f0'+g0' is almost e0+f0+g0, except for some missing + // bits carried from d. Now get those bits back in. + __m128i eh = _mm_slli_epi64(dx, 63); // d<<63:stuff + __m128i fh = _mm_slli_epi64(dx, 62); // d<<62:stuff + __m128i gh = _mm_slli_epi64(dx, 57); // d<<57:stuff + __m128i hh = _mm_srli_si128(_mm_xor_si128(_mm_xor_si128(eh, fh), gh), 8); // 0:missing bits of d + + return _mm_xor_si128(_mm_xor_si128(_mm_xor_si128(_mm_xor_si128(ee, ff), gg), hh), dx); +} + +void mbedtls_aesni_gcm_mult(unsigned char c[16], + const unsigned char a[16], + const unsigned char b[16]) +{ + __m128i aa, bb, cc, dd; + + /* The inputs are in big-endian order, so byte-reverse them */ + for (size_t i = 0; i < 16; i++) { + ((uint8_t *) &aa)[i] = a[15 - i]; + ((uint8_t *) &bb)[i] = b[15 - i]; + } + + gcm_clmul(aa, bb, &cc, &dd); + gcm_shift(&cc, &dd); + /* + * Now reduce modulo the GCM polynomial x^128 + x^7 + x^2 + x + 1 + * using [CLMUL-WP] algorithm 5 (p. 18). + * Currently dd:cc holds x3:x2:x1:x0 (already shifted). + */ + __m128i dx = gcm_reduce(cc); + __m128i xh = gcm_mix(dx); + cc = _mm_xor_si128(xh, dd); // x3+h1:x2+h0 + + /* Now byte-reverse the outputs */ + for (size_t i = 0; i < 16; i++) { + c[i] = ((uint8_t *) &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) +{ + __m128i *ik = (__m128i *) invkey; + const __m128i *fk = (const __m128i *) fwdkey + nr; + + *ik = *fk; + for (--fk, ++ik; fk > (const __m128i *) fwdkey; --fk, ++ik) { + *ik = _mm_aesimc_si128(*fk); + } + *ik = *fk; +} + +/* + * Key expansion, 128-bit case + */ +static __m128i aesni_set_rk_128(__m128i state, __m128i xword) +{ + /* + * Finish generating the next round key. + * + * On entry state is r3:r2:r1:r0 and xword is X:stuff:stuff:stuff + * with X = rot( sub( r3 ) ) ^ RCON (obtained with AESKEYGENASSIST). + * + * On exit, xword is r7:r6:r5:r4 + * with r4 = X + r0, r5 = r4 + r1, r6 = r5 + r2, r7 = r6 + r3 + * and this is returned, to be written to the round key buffer. + */ + xword = _mm_shuffle_epi32(xword, 0xff); // X:X:X:X + xword = _mm_xor_si128(xword, state); // X+r3:X+r2:X+r1:r4 + state = _mm_slli_si128(state, 4); // r2:r1:r0:0 + xword = _mm_xor_si128(xword, state); // X+r3+r2:X+r2+r1:r5:r4 + state = _mm_slli_si128(state, 4); // r1:r0:0:0 + xword = _mm_xor_si128(xword, state); // X+r3+r2+r1:r6:r5:r4 + state = _mm_slli_si128(state, 4); // r0:0:0:0 + state = _mm_xor_si128(xword, state); // r7:r6:r5:r4 + return state; +} + +static void aesni_setkey_enc_128(unsigned char *rk_bytes, + const unsigned char *key) +{ + __m128i *rk = (__m128i *) rk_bytes; + + memcpy(&rk[0], key, 16); + rk[1] = aesni_set_rk_128(rk[0], _mm_aeskeygenassist_si128(rk[0], 0x01)); + rk[2] = aesni_set_rk_128(rk[1], _mm_aeskeygenassist_si128(rk[1], 0x02)); + rk[3] = aesni_set_rk_128(rk[2], _mm_aeskeygenassist_si128(rk[2], 0x04)); + rk[4] = aesni_set_rk_128(rk[3], _mm_aeskeygenassist_si128(rk[3], 0x08)); + rk[5] = aesni_set_rk_128(rk[4], _mm_aeskeygenassist_si128(rk[4], 0x10)); + rk[6] = aesni_set_rk_128(rk[5], _mm_aeskeygenassist_si128(rk[5], 0x20)); + rk[7] = aesni_set_rk_128(rk[6], _mm_aeskeygenassist_si128(rk[6], 0x40)); + rk[8] = aesni_set_rk_128(rk[7], _mm_aeskeygenassist_si128(rk[7], 0x80)); + rk[9] = aesni_set_rk_128(rk[8], _mm_aeskeygenassist_si128(rk[8], 0x1B)); + rk[10] = aesni_set_rk_128(rk[9], _mm_aeskeygenassist_si128(rk[9], 0x36)); +} + +/* + * Key expansion, 192-bit case + */ +static void aesni_set_rk_192(__m128i *state0, __m128i *state1, __m128i xword, + unsigned char *rk) +{ + /* + * Finish generating the next 6 quarter-keys. + * + * On entry state0 is r3:r2:r1:r0, state1 is stuff:stuff:r5:r4 + * and xword is stuff:stuff:X:stuff with X = rot( sub( r3 ) ) ^ RCON + * (obtained with AESKEYGENASSIST). + * + * On exit, state0 is r9:r8:r7:r6 and state1 is stuff:stuff:r11:r10 + * and those are written to the round key buffer. + */ + xword = _mm_shuffle_epi32(xword, 0x55); // X:X:X:X + xword = _mm_xor_si128(xword, *state0); // X+r3:X+r2:X+r1:X+r0 + *state0 = _mm_slli_si128(*state0, 4); // r2:r1:r0:0 + xword = _mm_xor_si128(xword, *state0); // X+r3+r2:X+r2+r1:X+r1+r0:X+r0 + *state0 = _mm_slli_si128(*state0, 4); // r1:r0:0:0 + xword = _mm_xor_si128(xword, *state0); // X+r3+r2+r1:X+r2+r1+r0:X+r1+r0:X+r0 + *state0 = _mm_slli_si128(*state0, 4); // r0:0:0:0 + xword = _mm_xor_si128(xword, *state0); // X+r3+r2+r1+r0:X+r2+r1+r0:X+r1+r0:X+r0 + *state0 = xword; // = r9:r8:r7:r6 + + xword = _mm_shuffle_epi32(xword, 0xff); // r9:r9:r9:r9 + xword = _mm_xor_si128(xword, *state1); // stuff:stuff:r9+r5:r9+r4 + *state1 = _mm_slli_si128(*state1, 4); // stuff:stuff:r4:0 + xword = _mm_xor_si128(xword, *state1); // stuff:stuff:r9+r5+r4:r9+r4 + *state1 = xword; // = stuff:stuff:r11:r10 + + /* Store state0 and the low half of state1 into rk, which is conceptually + * an array of 24-byte elements. Since 24 is not a multiple of 16, + * rk is not necessarily aligned so just `*rk = *state0` doesn't work. */ + memcpy(rk, state0, 16); + memcpy(rk + 16, state1, 8); +} + +static void aesni_setkey_enc_192(unsigned char *rk, + const unsigned char *key) +{ + /* First round: use original key */ + memcpy(rk, key, 24); + /* aes.c guarantees that rk is aligned on a 16-byte boundary. */ + __m128i state0 = ((__m128i *) rk)[0]; + __m128i state1 = _mm_loadl_epi64(((__m128i *) rk) + 1); + + aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x01), rk + 24 * 1); + aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x02), rk + 24 * 2); + aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x04), rk + 24 * 3); + aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x08), rk + 24 * 4); + aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x10), rk + 24 * 5); + aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x20), rk + 24 * 6); + aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x40), rk + 24 * 7); + aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x80), rk + 24 * 8); +} + +/* + * Key expansion, 256-bit case + */ +static void aesni_set_rk_256(__m128i state0, __m128i state1, __m128i xword, + __m128i *rk0, __m128i *rk1) +{ + /* + * Finish generating the next two round keys. + * + * On entry state0 is r3:r2:r1:r0, state1 is r7:r6:r5:r4 and + * xword is X:stuff:stuff:stuff with X = rot( sub( r7 )) ^ RCON + * (obtained with AESKEYGENASSIST). + * + * On exit, *rk0 is r11:r10:r9:r8 and *rk1 is r15:r14:r13:r12 + */ + xword = _mm_shuffle_epi32(xword, 0xff); + xword = _mm_xor_si128(xword, state0); + state0 = _mm_slli_si128(state0, 4); + xword = _mm_xor_si128(xword, state0); + state0 = _mm_slli_si128(state0, 4); + xword = _mm_xor_si128(xword, state0); + state0 = _mm_slli_si128(state0, 4); + state0 = _mm_xor_si128(state0, xword); + *rk0 = state0; + + /* Set xword to stuff:Y:stuff:stuff with Y = subword( r11 ) + * and proceed to generate next round key from there */ + xword = _mm_aeskeygenassist_si128(state0, 0x00); + xword = _mm_shuffle_epi32(xword, 0xaa); + xword = _mm_xor_si128(xword, state1); + state1 = _mm_slli_si128(state1, 4); + xword = _mm_xor_si128(xword, state1); + state1 = _mm_slli_si128(state1, 4); + xword = _mm_xor_si128(xword, state1); + state1 = _mm_slli_si128(state1, 4); + state1 = _mm_xor_si128(state1, xword); + *rk1 = state1; +} + +static void aesni_setkey_enc_256(unsigned char *rk_bytes, + const unsigned char *key) +{ + __m128i *rk = (__m128i *) rk_bytes; + + memcpy(&rk[0], key, 16); + memcpy(&rk[1], key + 16, 16); + + /* + * Main "loop" - Generating one more key than necessary, + * see definition of mbedtls_aes_context.buf + */ + aesni_set_rk_256(rk[0], rk[1], _mm_aeskeygenassist_si128(rk[1], 0x01), &rk[2], &rk[3]); + aesni_set_rk_256(rk[2], rk[3], _mm_aeskeygenassist_si128(rk[3], 0x02), &rk[4], &rk[5]); + aesni_set_rk_256(rk[4], rk[5], _mm_aeskeygenassist_si128(rk[5], 0x04), &rk[6], &rk[7]); + aesni_set_rk_256(rk[6], rk[7], _mm_aeskeygenassist_si128(rk[7], 0x08), &rk[8], &rk[9]); + aesni_set_rk_256(rk[8], rk[9], _mm_aeskeygenassist_si128(rk[9], 0x10), &rk[10], &rk[11]); + aesni_set_rk_256(rk[10], rk[11], _mm_aeskeygenassist_si128(rk[11], 0x20), &rk[12], &rk[13]); + aesni_set_rk_256(rk[12], rk[13], _mm_aeskeygenassist_si128(rk[13], 0x40), &rk[14], &rk[15]); +} + +#else /* MBEDTLS_AESNI_HAVE_CODE == 1 */ + +#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 + +/* + * 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(regs) ".byte 0x66,0x0F,0x38,0xDE," regs "\n\t" +#define AESDECLAST(regs) ".byte 0x66,0x0F,0x38,0xDF," regs "\n\t" +#define AESENC(regs) ".byte 0x66,0x0F,0x38,0xDC," regs "\n\t" +#define AESENCLAST(regs) ".byte 0x66,0x0F,0x38,0xDD," regs "\n\t" +#define AESIMC(regs) ".byte 0x66,0x0F,0x38,0xDB," regs "\n\t" +#define AESKEYGENA(regs, imm) ".byte 0x66,0x0F,0x3A,0xDF," regs "," imm "\n\t" +#define PCLMULQDQ(regs, imm) ".byte 0x66,0x0F,0x3A,0x44," regs "," imm "\n\t" + +#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) // 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) // last round + "jmp 3f \n\t" + + "2: \n\t" // decryption loop + "movdqu (%1), %%xmm1 \n\t" + AESDEC(xmm1_xmm0) // 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) // last round + + "3: \n\t" + "movdqu %%xmm0, (%4) \n\t" // export output + : + : "r" (ctx->nr), "r" (ctx->buf + ctx->rk_offset), "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. 12). + */ + "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") // a0*b0 = c1:c0 + PCLMULQDQ(xmm0_xmm2, "0x11") // a1*b1 = d1:d0 + PCLMULQDQ(xmm0_xmm3, "0x10") // a0*b1 = e1:e0 + PCLMULQDQ(xmm0_xmm4, "0x01") // 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. 18) + */ + "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. 18). + * 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) + "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") "call 1b \n\t" + AESKEYGENA(xmm0_xmm1, "0x02") "call 1b \n\t" + AESKEYGENA(xmm0_xmm1, "0x04") "call 1b \n\t" + AESKEYGENA(xmm0_xmm1, "0x08") "call 1b \n\t" + AESKEYGENA(xmm0_xmm1, "0x10") "call 1b \n\t" + AESKEYGENA(xmm0_xmm1, "0x20") "call 1b \n\t" + AESKEYGENA(xmm0_xmm1, "0x40") "call 1b \n\t" + AESKEYGENA(xmm0_xmm1, "0x80") "call 1b \n\t" + AESKEYGENA(xmm0_xmm1, "0x1B") "call 1b \n\t" + AESKEYGENA(xmm0_xmm1, "0x36") "call 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") "call 1b \n\t" + AESKEYGENA(xmm1_xmm2, "0x02") "call 1b \n\t" + AESKEYGENA(xmm1_xmm2, "0x04") "call 1b \n\t" + AESKEYGENA(xmm1_xmm2, "0x08") "call 1b \n\t" + AESKEYGENA(xmm1_xmm2, "0x10") "call 1b \n\t" + AESKEYGENA(xmm1_xmm2, "0x20") "call 1b \n\t" + AESKEYGENA(xmm1_xmm2, "0x40") "call 1b \n\t" + AESKEYGENA(xmm1_xmm2, "0x80") "call 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") + "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") "call 1b \n\t" + AESKEYGENA(xmm1_xmm2, "0x02") "call 1b \n\t" + AESKEYGENA(xmm1_xmm2, "0x04") "call 1b \n\t" + AESKEYGENA(xmm1_xmm2, "0x08") "call 1b \n\t" + AESKEYGENA(xmm1_xmm2, "0x10") "call 1b \n\t" + AESKEYGENA(xmm1_xmm2, "0x20") "call 1b \n\t" + AESKEYGENA(xmm1_xmm2, "0x40") "call 1b \n\t" + : + : "r" (rk), "r" (key) + : "memory", "cc", "0"); +} + +#endif /* MBEDTLS_AESNI_HAVE_CODE */ + +/* + * 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_AESNI_HAVE_CODE */ + +#endif /* MBEDTLS_AESNI_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/aesni.h b/optee/optee_os/lib/libmbedtls/mbedtls/library/aesni.h new file mode 100644 index 0000000..51b770f --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/aesni.h @@ -0,0 +1,166 @@ +/** + * \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 + +#include "mbedtls/build_info.h" + +#include "mbedtls/aes.h" + +#define MBEDTLS_AESNI_AES 0x02000000u +#define MBEDTLS_AESNI_CLMUL 0x00000002u + +/* Can we do AESNI with inline assembly? + * (Only implemented with gas syntax, only for 64-bit.) + */ +#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_AESNI_C) + +/* Can we do AESNI with intrinsics? + * (Only implemented with certain compilers, only for certain targets.) + */ +#undef MBEDTLS_AESNI_HAVE_INTRINSICS +#if defined(_MSC_VER) +/* Visual Studio supports AESNI intrinsics since VS 2008 SP1. We only support + * VS 2013 and up for other reasons anyway, so no need to check the version. */ +#define MBEDTLS_AESNI_HAVE_INTRINSICS +#endif +/* GCC-like compilers: currently, we only support intrinsics if the requisite + * target flag is enabled when building the library (e.g. `gcc -mpclmul -msse2` + * or `clang -maes -mpclmul`). */ +#if defined(__GNUC__) && defined(__AES__) && defined(__PCLMUL__) +#define MBEDTLS_AESNI_HAVE_INTRINSICS +#endif + +/* Choose the implementation of AESNI, if one is available. */ +#undef MBEDTLS_AESNI_HAVE_CODE +/* To minimize disruption when releasing the intrinsics-based implementation, + * favor the assembly-based implementation if it's available. We intend to + * revise this in a later release of Mbed TLS 3.x. In the long run, we will + * likely remove the assembly implementation. */ +#if defined(MBEDTLS_HAVE_X86_64) +#define MBEDTLS_AESNI_HAVE_CODE 1 // via assembly +#elif defined(MBEDTLS_AESNI_HAVE_INTRINSICS) +#define MBEDTLS_AESNI_HAVE_CODE 2 // via intrinsics +#endif + +#if defined(MBEDTLS_AESNI_HAVE_CODE) + +#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_AESNI_HAVE_CODE */ +#endif /* MBEDTLS_AESNI_C */ + +#endif /* MBEDTLS_AESNI_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/alignment.h b/optee/optee_os/lib/libmbedtls/mbedtls/library/alignment.h new file mode 100644 index 0000000..a518a8a --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/alignment.h @@ -0,0 +1,520 @@ +/** + * \file alignment.h + * + * \brief Utility code for dealing with unaligned memory accesses + */ +/* + * 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_ALIGNMENT_H +#define MBEDTLS_LIBRARY_ALIGNMENT_H + +#include +#include +#include + +#include "mbedtls/build_info.h" + +/* + * Define MBEDTLS_EFFICIENT_UNALIGNED_ACCESS for architectures where unaligned memory + * accesses are known to be efficient. + * + * All functions defined here will behave correctly regardless, but might be less + * efficient when this is not defined. + */ +#if defined(__ARM_FEATURE_UNALIGNED) \ + || defined(__i386__) || defined(__amd64__) || defined(__x86_64__) +/* + * __ARM_FEATURE_UNALIGNED is defined where appropriate by armcc, gcc 7, clang 9 + * (and later versions) for Arm v7 and later; all x86 platforms should have + * efficient unaligned access. + */ +#define MBEDTLS_EFFICIENT_UNALIGNED_ACCESS +#endif + +/** + * Read the unsigned 16 bits integer from the given address, which need not + * be aligned. + * + * \param p pointer to 2 bytes of data + * \return Data at the given address + */ +inline uint16_t mbedtls_get_unaligned_uint16(const void *p) +{ + uint16_t r; + memcpy(&r, p, sizeof(r)); + return r; +} + +/** + * Write the unsigned 16 bits integer to the given address, which need not + * be aligned. + * + * \param p pointer to 2 bytes of data + * \param x data to write + */ +inline void mbedtls_put_unaligned_uint16(void *p, uint16_t x) +{ + memcpy(p, &x, sizeof(x)); +} + +/** + * Read the unsigned 32 bits integer from the given address, which need not + * be aligned. + * + * \param p pointer to 4 bytes of data + * \return Data at the given address + */ +inline uint32_t mbedtls_get_unaligned_uint32(const void *p) +{ + uint32_t r; + memcpy(&r, p, sizeof(r)); + return r; +} + +/** + * Write the unsigned 32 bits integer to the given address, which need not + * be aligned. + * + * \param p pointer to 4 bytes of data + * \param x data to write + */ +inline void mbedtls_put_unaligned_uint32(void *p, uint32_t x) +{ + memcpy(p, &x, sizeof(x)); +} + +/** + * Read the unsigned 64 bits integer from the given address, which need not + * be aligned. + * + * \param p pointer to 8 bytes of data + * \return Data at the given address + */ +inline uint64_t mbedtls_get_unaligned_uint64(const void *p) +{ + uint64_t r; + memcpy(&r, p, sizeof(r)); + return r; +} + +/** + * Write the unsigned 64 bits integer to the given address, which need not + * be aligned. + * + * \param p pointer to 8 bytes of data + * \param x data to write + */ +inline void mbedtls_put_unaligned_uint64(void *p, uint64_t x) +{ + memcpy(p, &x, sizeof(x)); +} + +/** 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)) + +/* + * Detect GCC built-in byteswap routines + */ +#if defined(__GNUC__) && defined(__GNUC_PREREQ) +#if __GNUC_PREREQ(4, 8) +#define MBEDTLS_BSWAP16 __builtin_bswap16 +#endif /* __GNUC_PREREQ(4,8) */ +#if __GNUC_PREREQ(4, 3) +#define MBEDTLS_BSWAP32 __builtin_bswap32 +#define MBEDTLS_BSWAP64 __builtin_bswap64 +#endif /* __GNUC_PREREQ(4,3) */ +#endif /* defined(__GNUC__) && defined(__GNUC_PREREQ) */ + +/* + * Detect Clang built-in byteswap routines + */ +#if defined(__clang__) && defined(__has_builtin) +#if __has_builtin(__builtin_bswap16) && !defined(MBEDTLS_BSWAP16) +#define MBEDTLS_BSWAP16 __builtin_bswap16 +#endif /* __has_builtin(__builtin_bswap16) */ +#if __has_builtin(__builtin_bswap32) && !defined(MBEDTLS_BSWAP32) +#define MBEDTLS_BSWAP32 __builtin_bswap32 +#endif /* __has_builtin(__builtin_bswap32) */ +#if __has_builtin(__builtin_bswap64) && !defined(MBEDTLS_BSWAP64) +#define MBEDTLS_BSWAP64 __builtin_bswap64 +#endif /* __has_builtin(__builtin_bswap64) */ +#endif /* defined(__clang__) && defined(__has_builtin) */ + +/* + * Detect MSVC built-in byteswap routines + */ +#if defined(_MSC_VER) +#if !defined(MBEDTLS_BSWAP16) +#define MBEDTLS_BSWAP16 _byteswap_ushort +#endif +#if !defined(MBEDTLS_BSWAP32) +#define MBEDTLS_BSWAP32 _byteswap_ulong +#endif +#if !defined(MBEDTLS_BSWAP64) +#define MBEDTLS_BSWAP64 _byteswap_uint64 +#endif +#endif /* defined(_MSC_VER) */ + +/* Detect armcc built-in byteswap routine */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 410000) && !defined(MBEDTLS_BSWAP32) +#define MBEDTLS_BSWAP32 __rev +#endif + +/* + * Where compiler built-ins are not present, fall back to C code that the + * compiler may be able to detect and transform into the relevant bswap or + * similar instruction. + */ +#if !defined(MBEDTLS_BSWAP16) +static inline uint16_t mbedtls_bswap16(uint16_t x) +{ + return + (x & 0x00ff) << 8 | + (x & 0xff00) >> 8; +} +#define MBEDTLS_BSWAP16 mbedtls_bswap16 +#endif /* !defined(MBEDTLS_BSWAP16) */ + +#if !defined(MBEDTLS_BSWAP32) +static inline uint32_t mbedtls_bswap32(uint32_t x) +{ + return + (x & 0x000000ff) << 24 | + (x & 0x0000ff00) << 8 | + (x & 0x00ff0000) >> 8 | + (x & 0xff000000) >> 24; +} +#define MBEDTLS_BSWAP32 mbedtls_bswap32 +#endif /* !defined(MBEDTLS_BSWAP32) */ + +#if !defined(MBEDTLS_BSWAP64) +static inline uint64_t mbedtls_bswap64(uint64_t x) +{ + return + (x & 0x00000000000000ffULL) << 56 | + (x & 0x000000000000ff00ULL) << 40 | + (x & 0x0000000000ff0000ULL) << 24 | + (x & 0x00000000ff000000ULL) << 8 | + (x & 0x000000ff00000000ULL) >> 8 | + (x & 0x0000ff0000000000ULL) >> 24 | + (x & 0x00ff000000000000ULL) >> 40 | + (x & 0xff00000000000000ULL) >> 56; +} +#define MBEDTLS_BSWAP64 mbedtls_bswap64 +#endif /* !defined(MBEDTLS_BSWAP64) */ + +#if !defined(__BYTE_ORDER__) +static const uint16_t mbedtls_byte_order_detector = { 0x100 }; +#define MBEDTLS_IS_BIG_ENDIAN (*((unsigned char *) (&mbedtls_byte_order_detector)) == 0x01) +#else +#define MBEDTLS_IS_BIG_ENDIAN ((__BYTE_ORDER__) == (__ORDER_BIG_ENDIAN__)) +#endif /* !defined(__BYTE_ORDER__) */ + +/** + * 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 data of the first and most significant + * byte of the four bytes to build the 32 bits unsigned + * integer from. + */ +#define MBEDTLS_GET_UINT32_BE(data, offset) \ + ((MBEDTLS_IS_BIG_ENDIAN) \ + ? mbedtls_get_unaligned_uint32((data) + (offset)) \ + : MBEDTLS_BSWAP32(mbedtls_get_unaligned_uint32((data) + (offset))) \ + ) + +/** + * 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 data where to put the most significant + * byte of the 32 bits unsigned integer \p n. + */ +#define MBEDTLS_PUT_UINT32_BE(n, data, offset) \ + { \ + if (MBEDTLS_IS_BIG_ENDIAN) \ + { \ + mbedtls_put_unaligned_uint32((data) + (offset), (uint32_t) (n)); \ + } \ + else \ + { \ + mbedtls_put_unaligned_uint32((data) + (offset), MBEDTLS_BSWAP32((uint32_t) (n))); \ + } \ + } + +/** + * 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 data of the first and least significant + * byte of the four bytes to build the 32 bits unsigned + * integer from. + */ +#define MBEDTLS_GET_UINT32_LE(data, offset) \ + ((MBEDTLS_IS_BIG_ENDIAN) \ + ? MBEDTLS_BSWAP32(mbedtls_get_unaligned_uint32((data) + (offset))) \ + : mbedtls_get_unaligned_uint32((data) + (offset)) \ + ) + + +/** + * 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 data where to put the least significant + * byte of the 32 bits unsigned integer \p n. + */ +#define MBEDTLS_PUT_UINT32_LE(n, data, offset) \ + { \ + if (MBEDTLS_IS_BIG_ENDIAN) \ + { \ + mbedtls_put_unaligned_uint32((data) + (offset), MBEDTLS_BSWAP32((uint32_t) (n))); \ + } \ + else \ + { \ + mbedtls_put_unaligned_uint32((data) + (offset), ((uint32_t) (n))); \ + } \ + } + +/** + * 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 data of the first and least significant + * byte of the two bytes to build the 16 bits unsigned + * integer from. + */ +#define MBEDTLS_GET_UINT16_LE(data, offset) \ + ((MBEDTLS_IS_BIG_ENDIAN) \ + ? MBEDTLS_BSWAP16(mbedtls_get_unaligned_uint16((data) + (offset))) \ + : mbedtls_get_unaligned_uint16((data) + (offset)) \ + ) + +/** + * 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 data where to put the least significant + * byte of the 16 bits unsigned integer \p n. + */ +#define MBEDTLS_PUT_UINT16_LE(n, data, offset) \ + { \ + if (MBEDTLS_IS_BIG_ENDIAN) \ + { \ + mbedtls_put_unaligned_uint16((data) + (offset), MBEDTLS_BSWAP16((uint16_t) (n))); \ + } \ + else \ + { \ + mbedtls_put_unaligned_uint16((data) + (offset), (uint16_t) (n)); \ + } \ + } + +/** + * 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 data of the first and most significant + * byte of the two bytes to build the 16 bits unsigned + * integer from. + */ +#define MBEDTLS_GET_UINT16_BE(data, offset) \ + ((MBEDTLS_IS_BIG_ENDIAN) \ + ? mbedtls_get_unaligned_uint16((data) + (offset)) \ + : MBEDTLS_BSWAP16(mbedtls_get_unaligned_uint16((data) + (offset))) \ + ) + +/** + * 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 data where to put the most significant + * byte of the 16 bits unsigned integer \p n. + */ +#define MBEDTLS_PUT_UINT16_BE(n, data, offset) \ + { \ + if (MBEDTLS_IS_BIG_ENDIAN) \ + { \ + mbedtls_put_unaligned_uint16((data) + (offset), (uint16_t) (n)); \ + } \ + else \ + { \ + mbedtls_put_unaligned_uint16((data) + (offset), MBEDTLS_BSWAP16((uint16_t) (n))); \ + } \ + } + +/** + * Get the unsigned 24 bits integer corresponding to three bytes in + * big-endian order (MSB first). + * + * \param data Base address of the memory to get the three bytes from. + * \param offset Offset from \p data of the first and most significant + * byte of the three bytes to build the 24 bits unsigned + * integer from. + */ +#define MBEDTLS_GET_UINT24_BE(data, offset) \ + ( \ + ((uint32_t) (data)[(offset)] << 16) \ + | ((uint32_t) (data)[(offset) + 1] << 8) \ + | ((uint32_t) (data)[(offset) + 2]) \ + ) + +/** + * Put in memory a 24 bits unsigned integer in big-endian order. + * + * \param n 24 bits unsigned integer to put in memory. + * \param data Base address of the memory where to put the 24 + * bits unsigned integer in. + * \param offset Offset from \p data where to put the most significant + * byte of the 24 bits unsigned integer \p n. + */ +#define MBEDTLS_PUT_UINT24_BE(n, data, offset) \ + { \ + (data)[(offset)] = MBEDTLS_BYTE_2(n); \ + (data)[(offset) + 1] = MBEDTLS_BYTE_1(n); \ + (data)[(offset) + 2] = MBEDTLS_BYTE_0(n); \ + } + +/** + * Get the unsigned 24 bits integer corresponding to three bytes in + * little-endian order (LSB first). + * + * \param data Base address of the memory to get the three bytes from. + * \param offset Offset from \p data of the first and least significant + * byte of the three bytes to build the 24 bits unsigned + * integer from. + */ +#define MBEDTLS_GET_UINT24_LE(data, offset) \ + ( \ + ((uint32_t) (data)[(offset)]) \ + | ((uint32_t) (data)[(offset) + 1] << 8) \ + | ((uint32_t) (data)[(offset) + 2] << 16) \ + ) + +/** + * Put in memory a 24 bits unsigned integer in little-endian order. + * + * \param n 24 bits unsigned integer to put in memory. + * \param data Base address of the memory where to put the 24 + * bits unsigned integer in. + * \param offset Offset from \p data where to put the least significant + * byte of the 24 bits unsigned integer \p n. + */ +#define MBEDTLS_PUT_UINT24_LE(n, data, offset) \ + { \ + (data)[(offset)] = MBEDTLS_BYTE_0(n); \ + (data)[(offset) + 1] = MBEDTLS_BYTE_1(n); \ + (data)[(offset) + 2] = MBEDTLS_BYTE_2(n); \ + } + +/** + * 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 data of the first and most significant + * byte of the eight bytes to build the 64 bits unsigned + * integer from. + */ +#define MBEDTLS_GET_UINT64_BE(data, offset) \ + ((MBEDTLS_IS_BIG_ENDIAN) \ + ? mbedtls_get_unaligned_uint64((data) + (offset)) \ + : MBEDTLS_BSWAP64(mbedtls_get_unaligned_uint64((data) + (offset))) \ + ) + +/** + * 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 data where to put the most significant + * byte of the 64 bits unsigned integer \p n. + */ +#define MBEDTLS_PUT_UINT64_BE(n, data, offset) \ + { \ + if (MBEDTLS_IS_BIG_ENDIAN) \ + { \ + mbedtls_put_unaligned_uint64((data) + (offset), (uint64_t) (n)); \ + } \ + else \ + { \ + mbedtls_put_unaligned_uint64((data) + (offset), MBEDTLS_BSWAP64((uint64_t) (n))); \ + } \ + } + +/** + * 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 data of the first and least significant + * byte of the eight bytes to build the 64 bits unsigned + * integer from. + */ +#define MBEDTLS_GET_UINT64_LE(data, offset) \ + ((MBEDTLS_IS_BIG_ENDIAN) \ + ? MBEDTLS_BSWAP64(mbedtls_get_unaligned_uint64((data) + (offset))) \ + : mbedtls_get_unaligned_uint64((data) + (offset)) \ + ) + +/** + * 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 data where to put the least significant + * byte of the 64 bits unsigned integer \p n. + */ +#define MBEDTLS_PUT_UINT64_LE(n, data, offset) \ + { \ + if (MBEDTLS_IS_BIG_ENDIAN) \ + { \ + mbedtls_put_unaligned_uint64((data) + (offset), MBEDTLS_BSWAP64((uint64_t) (n))); \ + } \ + else \ + { \ + mbedtls_put_unaligned_uint64((data) + (offset), (uint64_t) (n)); \ + } \ + } + +#endif /* MBEDTLS_LIBRARY_ALIGNMENT_H */ 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..0980362 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/aria.c @@ -0,0 +1,1003 @@ +/* + * 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 + +#include "mbedtls/platform.h" + +#if !defined(MBEDTLS_ARIA_ALT) + +#include "mbedtls/platform_util.h" + +/* 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 + */ +#define ARIA_P3(x) MBEDTLS_BSWAP32(x) + +/* + * 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) +{ + 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); + + mbedtls_xor(output, output, iv, MBEDTLS_ARIA_BLOCKSIZE); + + memcpy(iv, temp, MBEDTLS_ARIA_BLOCKSIZE); + + input += MBEDTLS_ARIA_BLOCKSIZE; + output += MBEDTLS_ARIA_BLOCKSIZE; + length -= MBEDTLS_ARIA_BLOCKSIZE; + } + } else { + while (length > 0) { + mbedtls_xor(output, input, iv, MBEDTLS_ARIA_BLOCKSIZE); + + 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_ASSERT(cond) \ + do { \ + if (cond) { \ + if (verbose) \ + mbedtls_printf("failed\n"); \ + goto exit; \ + } else { \ + if (verbose) \ + mbedtls_printf("passed\n"); \ + } \ + } while (0) + +/* + * 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); + ARIA_SELF_TEST_ASSERT( + memcmp(blk, aria_test1_ecb_ct[i], MBEDTLS_ARIA_BLOCKSIZE) + != 0); + + /* 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); + ARIA_SELF_TEST_ASSERT( + memcmp(blk, aria_test1_ecb_pt, MBEDTLS_ARIA_BLOCKSIZE) + != 0); + } + 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); + ARIA_SELF_TEST_ASSERT(memcmp(buf, aria_test2_cbc_ct[i], 48) + != 0); + + /* 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); + ARIA_SELF_TEST_ASSERT(memcmp(buf, aria_test2_pt, 48) != 0); + } + 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); + ARIA_SELF_TEST_ASSERT(memcmp(buf, aria_test2_cfb_ct[i], 48) != 0); + + /* 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); + ARIA_SELF_TEST_ASSERT(memcmp(buf, aria_test2_pt, 48) != 0); + } + 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); + ARIA_SELF_TEST_ASSERT(memcmp(buf, aria_test2_ctr_ct[i], 48) != 0); + + /* 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); + ARIA_SELF_TEST_ASSERT(memcmp(buf, aria_test2_pt, 48) != 0); + } + 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..d257ef4 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/asn1parse.c @@ -0,0 +1,506 @@ +/* + * 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 + +#include "mbedtls/platform.h" + +/* + * 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_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; +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +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)); +} +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +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_free(cur->oid.p); + mbedtls_free(cur->val.p); + mbedtls_free(cur); + } +} + +void mbedtls_asn1_free_named_data_list_shallow(mbedtls_asn1_named_data *name) +{ + for (mbedtls_asn1_named_data *next; name != NULL; name = next) { + next = name->next; + mbedtls_free(name); + } +} + +const mbedtls_asn1_named_data *mbedtls_asn1_find_named_data(const 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..b9d586a --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/asn1write.c @@ -0,0 +1,481 @@ +/* + * 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 + +#include "mbedtls/platform.h" + +int mbedtls_asn1_write_len(unsigned char **p, const 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; + } + + int len_is_valid = 1; +#if SIZE_MAX > 0xFFFFFFFF + len_is_valid = (len <= 0xFFFFFFFF); +#endif + if (len_is_valid) { + 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; + } + + return MBEDTLS_ERR_ASN1_INVALID_LENGTH; +} + +int mbedtls_asn1_write_tag(unsigned char **p, const 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, const 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, const 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, const 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, const 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, const 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, const 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, const 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, const unsigned char *start, int val) +{ + return asn1_write_tagged_int(p, start, val, MBEDTLS_ASN1_INTEGER); +} + +int mbedtls_asn1_write_enum(unsigned char **p, const 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, const 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, const 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, const 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, const 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, + const 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, const 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, const 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..4170610 --- /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 +#include "mbedtls/platform.h" +#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..b6733b7 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/bignum.c @@ -0,0 +1,2773 @@ +/* + * 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 "bignum_core.h" +#include "bn_mul.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" +#include "constant_time_internal.h" + +#include +#include + +#include "mbedtls/platform.h" + +#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 MPI_SIZE_T_MAX ((size_t) -1) /* SIZE_T_MAX is not standard */ + +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 { + if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(i, ciL)) == 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)); +} + +static inline mbedtls_mpi_uint mpi_sint_abs(mbedtls_mpi_sint z) +{ + if (z >= 0) { + return z; + } + /* Take care to handle the most negative value (-2^(biL-1)) correctly. + * A naive -z would have undefined behavior. + * Write this in a way that makes popular compilers happy (GCC, Clang, + * MSVC). */ + return (mbedtls_mpi_uint) 0 - (mbedtls_mpi_uint) z; +} + +/* + * 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] = mpi_sint_abs(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; +} + +/* + * 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; +} + +/* + * Return the number of bits + */ +size_t mbedtls_mpi_bitlen(const mbedtls_mpi *X) +{ + return mbedtls_mpi_core_bitlen(X->p, X->n); +} + +/* + * 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 */ + +/* + * Import X from unsigned binary data, little endian + * + * This function is guaranteed to return an MPI with exactly the necessary + * number of limbs (in particular, it does not skip 0s in the input). + */ +int mbedtls_mpi_read_binary_le(mbedtls_mpi *X, + const unsigned char *buf, size_t buflen) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const size_t 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)); + + MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_le(X->p, X->n, buf, buflen)); + +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 + * + * This function is guaranteed to return an MPI with exactly the necessary + * number of limbs (in particular, it does not skip 0s in the input). + */ +int mbedtls_mpi_read_binary(mbedtls_mpi *X, const unsigned char *buf, size_t buflen) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const size_t limbs = CHARS_TO_LIMBS(buflen); + + 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)); + + MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_be(X->p, X->n, buf, buflen)); + +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) +{ + return mbedtls_mpi_core_write_le(X->p, X->n, buf, buflen); +} + +/* + * Export X into unsigned binary data, big endian + */ +int mbedtls_mpi_write_binary(const mbedtls_mpi *X, + unsigned char *buf, size_t buflen) +{ + return mbedtls_mpi_core_write_be(X->p, X->n, buf, buflen); +} + +/* + * 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) +{ + MPI_VALIDATE_RET(X != NULL); + if (X->n != 0) { + mbedtls_mpi_core_shift_r(X->p, X->n, count); + } + 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 = mpi_sint_abs(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 j; + 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 must 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; + } + } + + /* Exit early to avoid undefined behavior on NULL+0 when X->n == 0 + * and B is 0 (of any size). */ + if (j == 0) { + return 0; + } + + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j)); + + /* j is the number of non-zero limbs of B. Add those to X. */ + + mbedtls_mpi_uint *p = X->p; + + mbedtls_mpi_uint c = mbedtls_mpi_core_add(p, p, B->p, j); + + p += j; + + /* Now propagate any carry */ + + while (c != 0) { + if (j >= X->n) { + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j + 1)); + p = X->p + j; + } + + *p += c; c = (*p < c); j++; p++; + } + +cleanup: + + return ret; +} + +/* + * 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 && A != X) { + 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 = mbedtls_mpi_core_sub(X->p, A->p, B->p, n); + if (carry != 0) { + /* Propagate the carry through the rest of X. */ + carry = mbedtls_mpi_core_sub_int(X->p + n, X->p + n, carry, X->n - n); + + /* If we have further carry/borrow, the result is negative. */ + if (carry != 0) { + ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE; + goto cleanup; + } + } + + /* X should always be positive as a result of unsigned subtractions. */ + X->s = 1; + +cleanup: + return ret; +} + +/* Common function for signed addition and subtraction. + * Calculate A + B * flip_B where flip_B is 1 or -1. + */ +static int add_sub_mpi(mbedtls_mpi *X, + const mbedtls_mpi *A, const mbedtls_mpi *B, + int flip_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 * flip_B < 0) { + int cmp = mbedtls_mpi_cmp_abs(A, B); + if (cmp >= 0) { + MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, A, B)); + /* If |A| = |B|, the result is 0 and we must set the sign bit + * to +1 regardless of which of A or B was negative. Otherwise, + * since |A| > |B|, the sign is the sign of A. */ + X->s = cmp == 0 ? 1 : s; + } else { + MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, B, A)); + /* Since |A| < |B|, the sign is the opposite of 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_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B) +{ + return add_sub_mpi(X, A, B, 1); +} + +/* + * Signed subtraction: X = A - B + */ +int mbedtls_mpi_sub_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B) +{ + return add_sub_mpi(X, A, B, -1); +} + +/* + * 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] = mpi_sint_abs(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] = mpi_sint_abs(b); + B.s = (b < 0) ? -1 : 1; + B.n = 1; + B.p = p; + + return mbedtls_mpi_sub_mpi(X, A, &B); +} + +/* + * 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 (size_t k = 0; k < j; k++) { + /* We know that there cannot be any carry-out since we're + * iterating from bottom to top. */ + (void) mbedtls_mpi_core_mla(X->p + k, i + 1, + A->p, i, + B->p[k]); + } + + /* 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); + + size_t n = A->n; + while (n > 0 && A->p[n - 1] == 0) { + --n; + } + + /* The general method below doesn't work if b==0. */ + if (b == 0 || n == 0) { + return mbedtls_mpi_lset(X, 0); + } + + /* Calculate A*b as A + A*(b-1) to take advantage of mbedtls_mpi_core_mla */ + 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. + * + * Note that calculating A*b as 0 + A*b doesn't work as-is because + * A,X can be the same. */ + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n + 1)); + MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A)); + mbedtls_mpi_core_mla(X->p, X->n, A->p, n, 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 = ~(mbedtls_mpi_uint) 0u; + } + + return ~(mbedtls_mpi_uint) 0u; + } + +#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_mpi_core_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] = ~(mbedtls_mpi_uint) 0u; + } 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] = mpi_sint_abs(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; +} + +static void mpi_montg_init(mbedtls_mpi_uint *mm, const mbedtls_mpi *N) +{ + *mm = mbedtls_mpi_core_montmul_init(N->p); +} + +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 modulus. \p 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 1 + * (T->n >= 2 * N->n + 1). + * Its initial content is unused and + * its final content is indeterminate. + * It does not get reallocated. + */ +static void mpi_montmul(mbedtls_mpi *A, const mbedtls_mpi *B, + const mbedtls_mpi *N, mbedtls_mpi_uint mm, + mbedtls_mpi *T) +{ + mbedtls_mpi_core_montmul(A->p, A->p, B->p, B->n, N->p, N->n, mm, T->p); +} + +void mbedtls_mpi_montmul(mbedtls_mpi *A, const mbedtls_mpi *B, + const mbedtls_mpi *N, mbedtls_mpi_uint mm, + 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, 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, 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 window_bitsize; + size_t i, j, nblimbs; + size_t bufsize, nbits; + size_t exponent_bits_in_window = 0; + mbedtls_mpi_uint ei, mm, state; + mbedtls_mpi RR, T, WW, Apos; + mbedtls_mpi *W; + 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); + + window_bitsize = (i > 671) ? 6 : (i > 239) ? 5 : + (i > 79) ? 4 : (i > 23) ? 3 : 1; + +#if (MBEDTLS_MPI_WINDOW_SIZE < 6) + if (window_bitsize > MBEDTLS_MPI_WINDOW_SIZE) { + window_bitsize = MBEDTLS_MPI_WINDOW_SIZE; + } +#endif + + const size_t w_table_used_size = (size_t) 1 << window_bitsize; + + 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); + /* + * This function is not constant-trace: its memory accesses depend on the + * exponent value. To defend against timing attacks, callers (such as RSA + * and DHM) should use exponent blinding. However this is not enough if the + * adversary can find the exponent in a single trace, so this function + * takes extra precautions against adversaries who can observe memory + * access patterns. + * + * This function performs a series of multiplications by table elements and + * squarings, and we want the prevent the adversary from finding out which + * table element was used, and from distinguishing between multiplications + * and squarings. Firstly, when multiplying by an element of the window + * W[i], we do a constant-trace table lookup to obfuscate i. This leaves + * squarings as having a different memory access patterns from other + * multiplications. So secondly, we put the accumulator X in the table as + * well, and also do a constant-trace table lookup to multiply by X. + * + * This way, all multiplications take the form of a lookup-and-multiply. + * The number of lookup-and-multiply operations inside each iteration of + * the main loop still depends on the bits of the exponent, but since the + * other operations in the loop don't have an easily recognizable memory + * trace, an adversary is unlikely to be able to observe the exact + * patterns. + * + * An adversary may still be able to recover the exponent if they can + * observe both memory accesses and branches. However, branch prediction + * exploitation typically requires many traces of execution over the same + * data, which is defeated by randomized blinding. + * + * To achieve this, we make a copy of X and we use the table entry in each + * calculation from this point on. + */ + const size_t x_index = 0; + mbedtls_mpi_copy(&W[x_index], X); + + 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(&W[x_index], 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)); + } + + 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); + + /* + * W[x_index] = R^2 * R^-1 mod N = R mod N + */ + MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[x_index], &RR)); + mpi_montred(&W[x_index], N, mm, &T); + + + if (window_bitsize > 1) { + /* + * W[i] = W[1] ^ i + * + * The first bit of the sliding window is always 1 and therefore we + * only need to store the second half of the table. + * + * (There are two special elements in the table: W[0] for the + * accumulator/result and W[1] for A in Montgomery form. Both of these + * are already set at this point.) + */ + j = w_table_used_size / 2; + + 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 < window_bitsize - 1; i++) { + mpi_montmul(&W[j], &W[j], N, mm, &T); + } + + /* + * W[i] = W[i - 1] * W[1] + */ + for (i = j + 1; i < w_table_used_size; 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; + 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 W[x_index] + */ + MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index)); + mpi_montmul(&W[x_index], &WW, N, mm, &T); + continue; + } + + /* + * add ei to current window + */ + state = 2; + + nbits++; + exponent_bits_in_window |= (ei << (window_bitsize - nbits)); + + if (nbits == window_bitsize) { + /* + * W[x_index] = W[x_index]^window_bitsize R^-1 mod N + */ + for (i = 0; i < window_bitsize; i++) { + MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, + x_index)); + mpi_montmul(&W[x_index], &WW, N, mm, &T); + } + + /* + * W[x_index] = W[x_index] * W[exponent_bits_in_window] R^-1 mod N + */ + MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, + exponent_bits_in_window)); + mpi_montmul(&W[x_index], &WW, N, mm, &T); + + state--; + nbits = 0; + exponent_bits_in_window = 0; + } + } + + /* + * process the remaining bits + */ + for (i = 0; i < nbits; i++) { + MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index)); + mpi_montmul(&W[x_index], &WW, N, mm, &T); + + exponent_bits_in_window <<= 1; + + if ((exponent_bits_in_window & ((size_t) 1 << window_bitsize)) != 0) { + MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, 1)); + mpi_montmul(&W[x_index], &WW, N, mm, &T); + } + } + + /* + * W[x_index] = A^E * R * R^-1 mod N = A^E mod N + */ + mpi_montred(&W[x_index], N, mm, &T); + + if (neg && E->n != 0 && (E->p[0] & 1) != 0) { + W[x_index].s = -1; + MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&W[x_index], N, &W[x_index])); + } + + /* + * Load the result in the output variable. + */ + mbedtls_mpi_copy(X, &W[x_index]); + +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 size bytes of random. + * The bytes returned from the RNG are used in a specific order which + * is suitable for deterministic ECDSA (see the specification of + * mbedtls_mpi_random() and the implementation in mbedtls_mpi_fill_random()). + */ +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; + const size_t 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 = mbedtls_mpi_core_fill_random(X->p, X->n, 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) +{ + 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; + } + + /* 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 mbedtls_mpi_core_random. */ + int ret = mbedtls_mpi_resize_clear(X, N->n); + if (ret != 0) { + return ret; + } + + return mbedtls_mpi_core_random(X->p, min, N->p, X->n, f_rng, p_rng); +} + +/* + * 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); +} + +/* + * 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 { + /* + * A 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/bignum_core.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_core.c new file mode 100644 index 0000000..e50f043 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_core.c @@ -0,0 +1,871 @@ +/* + * Core bignum 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_BIGNUM_C) + +#include + +#include "mbedtls/error.h" +#include "mbedtls/platform_util.h" +#include "constant_time_internal.h" + +#include "mbedtls/platform.h" + +#include "bignum_core.h" +#include "bn_mul.h" +#include "constant_time_internal.h" + +size_t mbedtls_mpi_core_clz(mbedtls_mpi_uint a) +{ + size_t j; + mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1); + + for (j = 0; j < biL; j++) { + if (a & mask) { + break; + } + + mask >>= 1; + } + + return j; +} + +size_t mbedtls_mpi_core_bitlen(const mbedtls_mpi_uint *A, size_t A_limbs) +{ + size_t i, j; + + if (A_limbs == 0) { + return 0; + } + + for (i = A_limbs - 1; i > 0; i--) { + if (A[i] != 0) { + break; + } + } + + j = biL - mbedtls_mpi_core_clz(A[i]); + + return (i * biL) + j; +} + +/* 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_bigendian_to_host_c(mbedtls_mpi_uint a) +{ + uint8_t i; + unsigned char *a_ptr; + mbedtls_mpi_uint tmp = 0; + + for (i = 0, a_ptr = (unsigned char *) &a; i < ciL; i++, a_ptr++) { + tmp <<= CHAR_BIT; + tmp |= (mbedtls_mpi_uint) *a_ptr; + } + + return tmp; +} + +static mbedtls_mpi_uint mpi_bigendian_to_host(mbedtls_mpi_uint a) +{ + if (MBEDTLS_IS_BIG_ENDIAN) { + /* Nothing to do on bigendian systems. */ + return a; + } else { + switch (sizeof(mbedtls_mpi_uint)) { + case 4: + return (mbedtls_mpi_uint) MBEDTLS_BSWAP32((uint32_t) a); + case 8: + return (mbedtls_mpi_uint) MBEDTLS_BSWAP64((uint64_t) a); + } + + /* 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_bigendian_to_host_c(a); + } +} + +void mbedtls_mpi_core_bigendian_to_host(mbedtls_mpi_uint *A, + size_t A_limbs) +{ + mbedtls_mpi_uint *cur_limb_left; + mbedtls_mpi_uint *cur_limb_right; + if (A_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 = A, cur_limb_right = A + (A_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_bigendian_to_host(*cur_limb_left); + *cur_limb_left = mpi_bigendian_to_host(*cur_limb_right); + *cur_limb_right = tmp; + } +} + +/* Whether min <= A, in constant time. + * A_limbs must be at least 1. */ +unsigned mbedtls_mpi_core_uint_le_mpi(mbedtls_mpi_uint min, + const mbedtls_mpi_uint *A, + size_t A_limbs) +{ + /* min <= least significant limb? */ + unsigned min_le_lsl = 1 ^ mbedtls_ct_mpi_uint_lt(A[0], min); + + /* limbs other than the least significant one are all zero? */ + mbedtls_mpi_uint msll_mask = 0; + for (size_t i = 1; i < A_limbs; i++) { + msll_mask |= A[i]; + } + /* The most significant limbs of A are not all zero iff msll_mask != 0. */ + unsigned msll_nonzero = mbedtls_ct_mpi_uint_mask(msll_mask) & 1; + + /* min <= A iff the lowest limb of A is >= min or the other limbs + * are not all zero. */ + return min_le_lsl | msll_nonzero; +} + +void mbedtls_mpi_core_cond_assign(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + size_t limbs, + unsigned char assign) +{ + if (X == A) { + return; + } + + mbedtls_ct_mpi_uint_cond_assign(limbs, X, A, assign); +} + +void mbedtls_mpi_core_cond_swap(mbedtls_mpi_uint *X, + mbedtls_mpi_uint *Y, + size_t limbs, + unsigned char swap) +{ + if (X == Y) { + return; + } + + /* all-bits 1 if swap is 1, all-bits 0 if swap is 0 */ + mbedtls_mpi_uint limb_mask = mbedtls_ct_mpi_uint_mask(swap); + + for (size_t i = 0; i < limbs; i++) { + mbedtls_mpi_uint tmp = X[i]; + X[i] = (X[i] & ~limb_mask) | (Y[i] & limb_mask); + Y[i] = (Y[i] & ~limb_mask) | (tmp & limb_mask); + } +} + +int mbedtls_mpi_core_read_le(mbedtls_mpi_uint *X, + size_t X_limbs, + const unsigned char *input, + size_t input_length) +{ + const size_t limbs = CHARS_TO_LIMBS(input_length); + + if (X_limbs < limbs) { + return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL; + } + + if (X != NULL) { + memset(X, 0, X_limbs * ciL); + + for (size_t i = 0; i < input_length; i++) { + size_t offset = ((i % ciL) << 3); + X[i / ciL] |= ((mbedtls_mpi_uint) input[i]) << offset; + } + } + + return 0; +} + +int mbedtls_mpi_core_read_be(mbedtls_mpi_uint *X, + size_t X_limbs, + const unsigned char *input, + size_t input_length) +{ + const size_t limbs = CHARS_TO_LIMBS(input_length); + + if (X_limbs < limbs) { + return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL; + } + + /* If X_limbs is 0, input_length must also be 0 (from previous test). + * Nothing to do. */ + if (X_limbs == 0) { + return 0; + } + + memset(X, 0, X_limbs * ciL); + + /* memcpy() with (NULL, 0) is undefined behaviour */ + if (input_length != 0) { + size_t overhead = (X_limbs * ciL) - input_length; + unsigned char *Xp = (unsigned char *) X; + memcpy(Xp + overhead, input, input_length); + } + + mbedtls_mpi_core_bigendian_to_host(X, X_limbs); + + return 0; +} + +int mbedtls_mpi_core_write_le(const mbedtls_mpi_uint *A, + size_t A_limbs, + unsigned char *output, + size_t output_length) +{ + size_t stored_bytes = A_limbs * ciL; + size_t bytes_to_copy; + + if (stored_bytes < output_length) { + bytes_to_copy = stored_bytes; + } else { + bytes_to_copy = output_length; + + /* The output buffer is smaller than the allocated size of A. + * However A may fit if its leading bytes are zero. */ + for (size_t i = bytes_to_copy; i < stored_bytes; i++) { + if (GET_BYTE(A, i) != 0) { + return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL; + } + } + } + + for (size_t i = 0; i < bytes_to_copy; i++) { + output[i] = GET_BYTE(A, i); + } + + if (stored_bytes < output_length) { + /* Write trailing 0 bytes */ + memset(output + stored_bytes, 0, output_length - stored_bytes); + } + + return 0; +} + +int mbedtls_mpi_core_write_be(const mbedtls_mpi_uint *X, + size_t X_limbs, + unsigned char *output, + size_t output_length) +{ + size_t stored_bytes; + size_t bytes_to_copy; + unsigned char *p; + + stored_bytes = X_limbs * ciL; + + if (stored_bytes < output_length) { + /* 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 = output + output_length - stored_bytes; + memset(output, 0, output_length - 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 = output_length; + p = output; + for (size_t i = bytes_to_copy; i < stored_bytes; i++) { + if (GET_BYTE(X, i) != 0) { + return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL; + } + } + } + + for (size_t i = 0; i < bytes_to_copy; i++) { + p[bytes_to_copy - i - 1] = GET_BYTE(X, i); + } + + return 0; +} + +void mbedtls_mpi_core_shift_r(mbedtls_mpi_uint *X, size_t limbs, + size_t count) +{ + size_t i, v0, v1; + mbedtls_mpi_uint r0 = 0, r1; + + v0 = count / biL; + v1 = count & (biL - 1); + + if (v0 > limbs || (v0 == limbs && v1 > 0)) { + memset(X, 0, limbs * ciL); + return; + } + + /* + * shift by count / limb_size + */ + if (v0 > 0) { + for (i = 0; i < limbs - v0; i++) { + X[i] = X[i + v0]; + } + + for (; i < limbs; i++) { + X[i] = 0; + } + } + + /* + * shift by count % limb_size + */ + if (v1 > 0) { + for (i = limbs; i > 0; i--) { + r1 = X[i - 1] << (biL - v1); + X[i - 1] >>= v1; + X[i - 1] |= r0; + r0 = r1; + } + } +} + +mbedtls_mpi_uint mbedtls_mpi_core_add(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *B, + size_t limbs) +{ + mbedtls_mpi_uint c = 0; + + for (size_t i = 0; i < limbs; i++) { + mbedtls_mpi_uint t = c + A[i]; + c = (t < A[i]); + t += B[i]; + c += (t < B[i]); + X[i] = t; + } + + return c; +} + +mbedtls_mpi_uint mbedtls_mpi_core_add_if(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + size_t limbs, + unsigned cond) +{ + mbedtls_mpi_uint c = 0; + + /* all-bits 0 if cond is 0, all-bits 1 if cond is non-0 */ + const mbedtls_mpi_uint mask = mbedtls_ct_mpi_uint_mask(cond); + + for (size_t i = 0; i < limbs; i++) { + mbedtls_mpi_uint add = mask & A[i]; + mbedtls_mpi_uint t = c + X[i]; + c = (t < X[i]); + t += add; + c += (t < add); + X[i] = t; + } + + return c; +} + +mbedtls_mpi_uint mbedtls_mpi_core_sub(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *B, + size_t limbs) +{ + mbedtls_mpi_uint c = 0; + + for (size_t i = 0; i < limbs; i++) { + mbedtls_mpi_uint z = (A[i] < c); + mbedtls_mpi_uint t = A[i] - c; + c = (t < B[i]) + z; + X[i] = t - B[i]; + } + + return c; +} + +mbedtls_mpi_uint mbedtls_mpi_core_mla(mbedtls_mpi_uint *d, size_t d_len, + const mbedtls_mpi_uint *s, size_t s_len, + mbedtls_mpi_uint b) +{ + mbedtls_mpi_uint c = 0; /* carry */ + /* + * It is a documented precondition of this function that d_len >= s_len. + * If that's not the case, we swap these round: this turns what would be + * a buffer overflow into an incorrect result. + */ + if (d_len < s_len) { + s_len = d_len; + } + size_t excess_len = d_len - s_len; + size_t steps_x8 = s_len / 8; + size_t steps_x1 = s_len & 7; + + while (steps_x8--) { + MULADDC_X8_INIT + MULADDC_X8_CORE + MULADDC_X8_STOP + } + + while (steps_x1--) { + MULADDC_X1_INIT + MULADDC_X1_CORE + MULADDC_X1_STOP + } + + while (excess_len--) { + *d += c; + c = (*d < c); + d++; + } + + return c; +} + +/* + * Fast Montgomery initialization (thanks to Tom St Denis). + */ +mbedtls_mpi_uint mbedtls_mpi_core_montmul_init(const mbedtls_mpi_uint *N) +{ + mbedtls_mpi_uint x = N[0]; + + x += ((N[0] + 2) & 4) << 1; + + for (unsigned int i = biL; i >= 8; i /= 2) { + x *= (2 - (N[0] * x)); + } + + return ~x + 1; +} + +void mbedtls_mpi_core_montmul(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *B, + size_t B_limbs, + const mbedtls_mpi_uint *N, + size_t AN_limbs, + mbedtls_mpi_uint mm, + mbedtls_mpi_uint *T) +{ + memset(T, 0, (2 * AN_limbs + 1) * ciL); + + for (size_t i = 0; i < AN_limbs; i++) { + /* T = (T + u0*B + u1*N) / 2^biL */ + mbedtls_mpi_uint u0 = A[i]; + mbedtls_mpi_uint u1 = (T[0] + u0 * B[0]) * mm; + + (void) mbedtls_mpi_core_mla(T, AN_limbs + 2, B, B_limbs, u0); + (void) mbedtls_mpi_core_mla(T, AN_limbs + 2, N, AN_limbs, u1); + + T++; + } + + /* + * The result we want is (T >= N) ? T - N : T. + * + * For better constant-time properties in this function, we always do the + * subtraction, with the result in X. + * + * We also look to see if there was any carry in the final additions in the + * loop above. + */ + + mbedtls_mpi_uint carry = T[AN_limbs]; + mbedtls_mpi_uint borrow = mbedtls_mpi_core_sub(X, T, N, AN_limbs); + + /* + * Using R as the Montgomery radix (auxiliary modulus) i.e. 2^(biL*AN_limbs): + * + * T can be in one of 3 ranges: + * + * 1) T < N : (carry, borrow) = (0, 1): we want T + * 2) N <= T < R : (carry, borrow) = (0, 0): we want X + * 3) T >= R : (carry, borrow) = (1, 1): we want X + * + * and (carry, borrow) = (1, 0) can't happen. + * + * So the correct return value is already in X if (carry ^ borrow) = 0, + * but is in (the lower AN_limbs limbs of) T if (carry ^ borrow) = 1. + */ + mbedtls_ct_mpi_uint_cond_assign(AN_limbs, X, T, (unsigned char) (carry ^ borrow)); +} + +int mbedtls_mpi_core_get_mont_r2_unsafe(mbedtls_mpi *X, + const mbedtls_mpi *N) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 1)); + MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(X, N->n * 2 * biL)); + MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(X, X, N)); + MBEDTLS_MPI_CHK(mbedtls_mpi_shrink(X, N->n)); + +cleanup: + return ret; +} + +MBEDTLS_STATIC_TESTABLE +void mbedtls_mpi_core_ct_uint_table_lookup(mbedtls_mpi_uint *dest, + const mbedtls_mpi_uint *table, + size_t limbs, + size_t count, + size_t index) +{ + for (size_t i = 0; i < count; i++, table += limbs) { + unsigned char assign = mbedtls_ct_size_bool_eq(i, index); + mbedtls_mpi_core_cond_assign(dest, table, limbs, assign); + } +} + +/* 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 the specification of + * mbedtls_mpi_core_random()). + */ +int mbedtls_mpi_core_fill_random( + mbedtls_mpi_uint *X, size_t X_limbs, + 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_limbs < limbs) { + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + } + + memset(X, 0, overhead); + memset((unsigned char *) X + limbs * ciL, 0, (X_limbs - limbs) * ciL); + MBEDTLS_MPI_CHK(f_rng(p_rng, (unsigned char *) X + overhead, n_bytes)); + mbedtls_mpi_core_bigendian_to_host(X, limbs); + +cleanup: + return ret; +} + +int mbedtls_mpi_core_random(mbedtls_mpi_uint *X, + mbedtls_mpi_uint min, + const mbedtls_mpi_uint *N, + size_t limbs, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) +{ + unsigned ge_lower = 1, lt_upper = 0; + size_t n_bits = mbedtls_mpi_core_bitlen(N, limbs); + size_t n_bytes = (n_bits + 7) / 8; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* + * 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. + */ + int count = (n_bytes > 4 ? 30 : 250); + + /* + * 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(mbedtls_mpi_core_fill_random(X, limbs, + n_bytes, + f_rng, p_rng)); + mbedtls_mpi_core_shift_r(X, limbs, 8 * n_bytes - n_bits); + + if (--count == 0) { + ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + goto cleanup; + } + + ge_lower = mbedtls_mpi_core_uint_le_mpi(min, X, limbs); + lt_upper = mbedtls_mpi_core_lt_ct(X, N, limbs); + } while (ge_lower == 0 || lt_upper == 0); + +cleanup: + return ret; +} + +/* BEGIN MERGE SLOT 1 */ + +static size_t exp_mod_get_window_size(size_t Ebits) +{ + size_t wsize = (Ebits > 671) ? 6 : (Ebits > 239) ? 5 : + (Ebits > 79) ? 4 : 1; + +#if (MBEDTLS_MPI_WINDOW_SIZE < 6) + if (wsize > MBEDTLS_MPI_WINDOW_SIZE) { + wsize = MBEDTLS_MPI_WINDOW_SIZE; + } +#endif + + return wsize; +} + +size_t mbedtls_mpi_core_exp_mod_working_limbs(size_t AN_limbs, size_t E_limbs) +{ + const size_t wsize = exp_mod_get_window_size(E_limbs * biL); + const size_t welem = ((size_t) 1) << wsize; + + /* How big does each part of the working memory pool need to be? */ + const size_t table_limbs = welem * AN_limbs; + const size_t select_limbs = AN_limbs; + const size_t temp_limbs = 2 * AN_limbs + 1; + + return table_limbs + select_limbs + temp_limbs; +} + +static void exp_mod_precompute_window(const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *N, + size_t AN_limbs, + mbedtls_mpi_uint mm, + const mbedtls_mpi_uint *RR, + size_t welem, + mbedtls_mpi_uint *Wtable, + mbedtls_mpi_uint *temp) +{ + /* W[0] = 1 (in Montgomery presentation) */ + memset(Wtable, 0, AN_limbs * ciL); + Wtable[0] = 1; + mbedtls_mpi_core_montmul(Wtable, Wtable, RR, AN_limbs, N, AN_limbs, mm, temp); + + /* W[1] = A (already in Montgomery presentation) */ + mbedtls_mpi_uint *W1 = Wtable + AN_limbs; + memcpy(W1, A, AN_limbs * ciL); + + /* W[i+1] = W[i] * W[1], i >= 2 */ + mbedtls_mpi_uint *Wprev = W1; + for (size_t i = 2; i < welem; i++) { + mbedtls_mpi_uint *Wcur = Wprev + AN_limbs; + mbedtls_mpi_core_montmul(Wcur, Wprev, W1, AN_limbs, N, AN_limbs, mm, temp); + Wprev = Wcur; + } +} + +/* Exponentiation: X := A^E mod N. + * + * A must already be in Montgomery form. + * + * As in other bignum functions, assume that AN_limbs and E_limbs are nonzero. + * + * RR must contain 2^{2*biL} mod N. + * + * The algorithm is a variant of Left-to-right k-ary exponentiation: HAC 14.82 + * (The difference is that the body in our loop processes a single bit instead + * of a full window.) + */ +void mbedtls_mpi_core_exp_mod(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *N, + size_t AN_limbs, + const mbedtls_mpi_uint *E, + size_t E_limbs, + const mbedtls_mpi_uint *RR, + mbedtls_mpi_uint *T) +{ + const size_t wsize = exp_mod_get_window_size(E_limbs * biL); + const size_t welem = ((size_t) 1) << wsize; + + /* This is how we will use the temporary storage T, which must have space + * for table_limbs, select_limbs and (2 * AN_limbs + 1) for montmul. */ + const size_t table_limbs = welem * AN_limbs; + const size_t select_limbs = AN_limbs; + + /* Pointers to specific parts of the temporary working memory pool */ + mbedtls_mpi_uint *const Wtable = T; + mbedtls_mpi_uint *const Wselect = Wtable + table_limbs; + mbedtls_mpi_uint *const temp = Wselect + select_limbs; + + /* + * Window precomputation + */ + + const mbedtls_mpi_uint mm = mbedtls_mpi_core_montmul_init(N); + + /* Set Wtable[i] = A^(2^i) (in Montgomery representation) */ + exp_mod_precompute_window(A, N, AN_limbs, + mm, RR, + welem, Wtable, temp); + + /* + * Fixed window exponentiation + */ + + /* X = 1 (in Montgomery presentation) initially */ + memcpy(X, Wtable, AN_limbs * ciL); + + /* We'll process the bits of E from most significant + * (limb_index=E_limbs-1, E_bit_index=biL-1) to least significant + * (limb_index=0, E_bit_index=0). */ + size_t E_limb_index = E_limbs; + size_t E_bit_index = 0; + /* At any given time, window contains window_bits bits from E. + * window_bits can go up to wsize. */ + size_t window_bits = 0; + mbedtls_mpi_uint window = 0; + + do { + /* Square */ + mbedtls_mpi_core_montmul(X, X, X, AN_limbs, N, AN_limbs, mm, temp); + + /* Move to the next bit of the exponent */ + if (E_bit_index == 0) { + --E_limb_index; + E_bit_index = biL - 1; + } else { + --E_bit_index; + } + /* Insert next exponent bit into window */ + ++window_bits; + window <<= 1; + window |= (E[E_limb_index] >> E_bit_index) & 1; + + /* Clear window if it's full. Also clear the window at the end, + * when we've finished processing the exponent. */ + if (window_bits == wsize || + (E_bit_index == 0 && E_limb_index == 0)) { + /* Select Wtable[window] without leaking window through + * memory access patterns. */ + mbedtls_mpi_core_ct_uint_table_lookup(Wselect, Wtable, + AN_limbs, welem, window); + /* Multiply X by the selected element. */ + mbedtls_mpi_core_montmul(X, X, Wselect, AN_limbs, N, AN_limbs, mm, + temp); + window = 0; + window_bits = 0; + } + } while (!(E_bit_index == 0 && E_limb_index == 0)); +} + +/* END MERGE SLOT 1 */ + +/* BEGIN MERGE SLOT 2 */ + +/* END MERGE SLOT 2 */ + +/* BEGIN MERGE SLOT 3 */ + +mbedtls_mpi_uint mbedtls_mpi_core_sub_int(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + mbedtls_mpi_uint c, /* doubles as carry */ + size_t limbs) +{ + for (size_t i = 0; i < limbs; i++) { + mbedtls_mpi_uint s = A[i]; + mbedtls_mpi_uint t = s - c; + c = (t > s); + X[i] = t; + } + + return c; +} + +mbedtls_mpi_uint mbedtls_mpi_core_check_zero_ct(const mbedtls_mpi_uint *A, + size_t limbs) +{ + mbedtls_mpi_uint bits = 0; + + for (size_t i = 0; i < limbs; i++) { + bits |= A[i]; + } + + return bits; +} + +void mbedtls_mpi_core_to_mont_rep(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *N, + size_t AN_limbs, + mbedtls_mpi_uint mm, + const mbedtls_mpi_uint *rr, + mbedtls_mpi_uint *T) +{ + mbedtls_mpi_core_montmul(X, A, rr, AN_limbs, N, AN_limbs, mm, T); +} + +void mbedtls_mpi_core_from_mont_rep(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *N, + size_t AN_limbs, + mbedtls_mpi_uint mm, + mbedtls_mpi_uint *T) +{ + const mbedtls_mpi_uint Rinv = 1; /* 1/R in Mont. rep => 1 */ + + mbedtls_mpi_core_montmul(X, A, &Rinv, 1, N, AN_limbs, mm, T); +} + +/* END MERGE SLOT 3 */ + +/* BEGIN MERGE SLOT 4 */ + +/* END MERGE SLOT 4 */ + +/* BEGIN MERGE SLOT 5 */ + +/* END MERGE SLOT 5 */ + +/* BEGIN MERGE SLOT 6 */ + +/* END MERGE SLOT 6 */ + +/* BEGIN MERGE SLOT 7 */ + +/* END MERGE SLOT 7 */ + +/* BEGIN MERGE SLOT 8 */ + +/* END MERGE SLOT 8 */ + +/* BEGIN MERGE SLOT 9 */ + +/* END MERGE SLOT 9 */ + +/* BEGIN MERGE SLOT 10 */ + +/* END MERGE SLOT 10 */ + +#endif /* MBEDTLS_BIGNUM_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_core.h b/optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_core.h new file mode 100644 index 0000000..05bc923 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_core.h @@ -0,0 +1,767 @@ +/** + * Core bignum functions + * + * This interface should only be used by the legacy bignum module (bignum.h) + * and the modular bignum modules (bignum_mod.c, bignum_mod_raw.c). All other + * modules should use the high-level modular bignum interface (bignum_mod.h) + * or the legacy bignum interface (bignum.h). + * + * This module is about processing non-negative integers with a fixed upper + * bound that's of the form 2^n-1 where n is a multiple of #biL. + * These can be thought of integers written in base 2^#biL with a fixed + * number of digits. Digits in this base are called *limbs*. + * Many operations treat these numbers as the principal representation of + * a number modulo 2^n or a smaller bound. + * + * The functions in this module obey the following conventions unless + * explicitly indicated otherwise: + * + * - **Overflow**: some functions indicate overflow from the range + * [0, 2^n-1] by returning carry parameters, while others operate + * modulo and so cannot overflow. This should be clear from the function + * documentation. + * - **Bignum parameters**: Bignums are passed as pointers to an array of + * limbs. A limb has the type #mbedtls_mpi_uint. Unless otherwise specified: + * - Bignum parameters called \p A, \p B, ... are inputs, and are + * not modified by the function. + * - For operations modulo some number, the modulus is called \p N + * and is input-only. + * - Bignum parameters called \p X, \p Y are outputs or input-output. + * The initial content of output-only parameters is ignored. + * - Some functions use different names that reflect traditional + * naming of operands of certain operations (e.g. + * divisor/dividend/quotient/remainder). + * - \p T is a temporary storage area. The initial content of such + * parameter is ignored and the final content is unspecified. + * - **Bignum sizes**: bignum sizes are always expressed in limbs. + * Most functions work on bignums of a given size and take a single + * \p limbs parameter that applies to all parameters that are limb arrays. + * All bignum sizes must be at least 1 and must be significantly less than + * #SIZE_MAX. The behavior if a size is 0 is undefined. The behavior if the + * total size of all parameters overflows #SIZE_MAX is undefined. + * - **Parameter ordering**: for bignum parameters, outputs come before inputs. + * Temporaries come last. + * - **Aliasing**: in general, output bignums may be aliased to one or more + * inputs. As an exception, parameters that are documented as a modulus value + * may not be aliased to an output. Outputs may not be aliased to one another. + * Temporaries may not be aliased to any other parameter. + * - **Overlap**: apart from aliasing of limb array pointers (where two + * arguments are equal pointers), overlap is not supported and may result + * in undefined behavior. + * - **Error handling**: This is a low-level module. Functions generally do not + * try to protect against invalid arguments such as nonsensical sizes or + * null pointers. Note that some functions that operate on bignums of + * different sizes have constraints about their size, and violating those + * constraints may lead to buffer overflows. + * - **Modular representatives**: functions that operate modulo \p N expect + * all modular inputs to be in the range [0, \p N - 1] and guarantee outputs + * in the range [0, \p N - 1]. If an input is out of range, outputs are + * fully unspecified, though bignum values out of range should not cause + * buffer overflows (beware that this is not extensively tested). + */ + +/* + * 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_CORE_H +#define MBEDTLS_BIGNUM_CORE_H + +#include "common.h" + +#if defined(MBEDTLS_BIGNUM_C) +#include "mbedtls/bignum.h" +#endif + +#define ciL (sizeof(mbedtls_mpi_uint)) /** chars in limb */ +#define biL (ciL << 3) /** bits in limb */ +#define biH (ciL << 2) /** half limb size */ + +/* + * 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)) +/* Get a specific byte, without range checks. */ +#define GET_BYTE(X, i) \ + (((X)[(i) / ciL] >> (((i) % ciL) * 8)) & 0xff) + +/** Count leading zero bits in a given integer. + * + * \param a Integer to count leading zero bits. + * + * \return The number of leading zero bits in \p a. + */ +size_t mbedtls_mpi_core_clz(mbedtls_mpi_uint a); + +/** Return the minimum number of bits required to represent the value held + * in the MPI. + * + * \note This function returns 0 if all the limbs of \p A are 0. + * + * \param[in] A The address of the MPI. + * \param A_limbs The number of limbs of \p A. + * + * \return The number of bits in \p A. + */ +size_t mbedtls_mpi_core_bitlen(const mbedtls_mpi_uint *A, size_t A_limbs); + +/** Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint + * into the storage form used by mbedtls_mpi. + * + * \param[in,out] A The address of the MPI. + * \param A_limbs The number of limbs of \p A. + */ +void mbedtls_mpi_core_bigendian_to_host(mbedtls_mpi_uint *A, + size_t A_limbs); + +/** \brief Compare a machine integer with an MPI. + * + * This function operates in constant time with respect + * to the values of \p min and \p A. + * + * \param min A machine integer. + * \param[in] A An MPI. + * \param A_limbs The number of limbs of \p A. + * This must be at least 1. + * + * \return 1 if \p min is less than or equal to \p A, otherwise 0. + */ +unsigned mbedtls_mpi_core_uint_le_mpi(mbedtls_mpi_uint min, + const mbedtls_mpi_uint *A, + size_t A_limbs); + +/** + * \brief Perform a safe conditional copy of an MPI which doesn't reveal + * whether assignment was done or not. + * + * \param[out] X The address of the destination MPI. + * This must be initialized. Must have enough limbs to + * store the full value of \p A. + * \param[in] A The address of the source MPI. This must be initialized. + * \param limbs The number of limbs of \p A. + * \param assign The condition deciding whether to perform the + * assignment or not. Must be either 0 or 1: + * * \c 1: Perform the assignment `X = A`. + * * \c 0: Keep the original value of \p X. + * + * \note This function avoids leaking any information about whether + * the assignment was done or not. + * + * \warning If \p assign is neither 0 nor 1, the result of this function + * is indeterminate, and the resulting value in \p X might be + * neither its original value nor the value in \p A. + */ +void mbedtls_mpi_core_cond_assign(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + size_t limbs, + unsigned char assign); + +/** + * \brief Perform a safe conditional swap of two MPIs which doesn't reveal + * whether the swap was done or not. + * + * \param[in,out] X The address of the first MPI. + * This must be initialized. + * \param[in,out] Y The address of the second MPI. + * This must be initialized. + * \param limbs The number of limbs of \p X and \p Y. + * \param swap The condition deciding whether to perform + * the swap or not. Must be either 0 or 1: + * * \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 avoids leaking any information about whether + * the swap was done or not. + * + * \warning If \p swap is neither 0 nor 1, the result of this function + * is indeterminate, and both \p X and \p Y might end up with + * values different to either of the original ones. + */ +void mbedtls_mpi_core_cond_swap(mbedtls_mpi_uint *X, + mbedtls_mpi_uint *Y, + size_t limbs, + unsigned char swap); + +/** Import X from unsigned binary data, little-endian. + * + * The MPI needs to have enough limbs to store the full value (including any + * most significant zero bytes in the input). + * + * \param[out] X The address of the MPI. + * \param X_limbs The number of limbs of \p X. + * \param[in] input The input buffer to import from. + * \param input_length The length bytes of \p input. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p X isn't + * large enough to hold the value in \p input. + */ +int mbedtls_mpi_core_read_le(mbedtls_mpi_uint *X, + size_t X_limbs, + const unsigned char *input, + size_t input_length); + +/** Import X from unsigned binary data, big-endian. + * + * The MPI needs to have enough limbs to store the full value (including any + * most significant zero bytes in the input). + * + * \param[out] X The address of the MPI. + * May only be #NULL if \p X_limbs is 0 and \p input_length + * is 0. + * \param X_limbs The number of limbs of \p X. + * \param[in] input The input buffer to import from. + * May only be #NULL if \p input_length is 0. + * \param input_length The length in bytes of \p input. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p X isn't + * large enough to hold the value in \p input. + */ +int mbedtls_mpi_core_read_be(mbedtls_mpi_uint *X, + size_t X_limbs, + const unsigned char *input, + size_t input_length); + +/** Export A into unsigned binary data, little-endian. + * + * \note If \p output is shorter than \p A the export is still successful if the + * value held in \p A fits in the buffer (that is, if enough of the most + * significant bytes of \p A are 0). + * + * \param[in] A The address of the MPI. + * \param A_limbs The number of limbs of \p A. + * \param[out] output The output buffer to export to. + * \param output_length The length in bytes of \p output. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p output isn't + * large enough to hold the value of \p A. + */ +int mbedtls_mpi_core_write_le(const mbedtls_mpi_uint *A, + size_t A_limbs, + unsigned char *output, + size_t output_length); + +/** Export A into unsigned binary data, big-endian. + * + * \note If \p output is shorter than \p A the export is still successful if the + * value held in \p A fits in the buffer (that is, if enough of the most + * significant bytes of \p A are 0). + * + * \param[in] A The address of the MPI. + * \param A_limbs The number of limbs of \p A. + * \param[out] output The output buffer to export to. + * \param output_length The length in bytes of \p output. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p output isn't + * large enough to hold the value of \p A. + */ +int mbedtls_mpi_core_write_be(const mbedtls_mpi_uint *A, + size_t A_limbs, + unsigned char *output, + size_t output_length); + +/** \brief Shift an MPI right in place by a number of bits. + * + * Shifting by more bits than there are bit positions + * in \p X is valid and results in setting \p X to 0. + * + * This function's execution time depends on the value + * of \p count (and of course \p limbs). + * + * \param[in,out] X The number to shift. + * \param limbs The number of limbs of \p X. This must be at least 1. + * \param count The number of bits to shift by. + */ +void mbedtls_mpi_core_shift_r(mbedtls_mpi_uint *X, size_t limbs, + size_t count); + +/** + * \brief Add two fixed-size large unsigned integers, returning the carry. + * + * Calculates `A + B` where `A` and `B` have the same size. + * + * This function operates modulo `2^(biL*limbs)` and returns the carry + * (1 if there was a wraparound, and 0 otherwise). + * + * \p X may be aliased to \p A or \p B. + * + * \param[out] X The result of the addition. + * \param[in] A Little-endian presentation of the left operand. + * \param[in] B Little-endian presentation of the right operand. + * \param limbs Number of limbs of \p X, \p A and \p B. + * + * \return 1 if `A + B >= 2^(biL*limbs)`, 0 otherwise. + */ +mbedtls_mpi_uint mbedtls_mpi_core_add(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *B, + size_t limbs); + +/** + * \brief Conditional addition of two fixed-size large unsigned integers, + * returning the carry. + * + * Functionally equivalent to + * + * ``` + * if( cond ) + * X += A; + * return carry; + * ``` + * + * This function operates modulo `2^(biL*limbs)`. + * + * \param[in,out] X The pointer to the (little-endian) array + * representing the bignum to accumulate onto. + * \param[in] A The pointer to the (little-endian) array + * representing the bignum to conditionally add + * to \p X. This may be aliased to \p X but may not + * overlap otherwise. + * \param limbs Number of limbs of \p X and \p A. + * \param cond Condition bit dictating whether addition should + * happen or not. This must be \c 0 or \c 1. + * + * \warning If \p cond is neither 0 nor 1, the result of this function + * is unspecified, and the resulting value in \p X might be + * neither its original value nor \p X + \p A. + * + * \return 1 if `X + cond * A >= 2^(biL*limbs)`, 0 otherwise. + */ +mbedtls_mpi_uint mbedtls_mpi_core_add_if(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + size_t limbs, + unsigned cond); + +/** + * \brief Subtract two fixed-size large unsigned integers, returning the borrow. + * + * Calculate `A - B` where \p A and \p B have the same size. + * This function operates modulo `2^(biL*limbs)` and returns the carry + * (1 if there was a wraparound, i.e. if `A < B`, and 0 otherwise). + * + * \p X may be aliased to \p A or \p B, or even both, but may not overlap + * either otherwise. + * + * \param[out] X The result of the subtraction. + * \param[in] A Little-endian presentation of left operand. + * \param[in] B Little-endian presentation of right operand. + * \param limbs Number of limbs of \p X, \p A and \p B. + * + * \return 1 if `A < B`. + * 0 if `A >= B`. + */ +mbedtls_mpi_uint mbedtls_mpi_core_sub(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *B, + size_t limbs); + +/** + * \brief Perform a fixed-size multiply accumulate operation: X += b * A + * + * \p X may be aliased to \p A (when \p X_limbs == \p A_limbs), but may not + * otherwise overlap. + * + * This function operates modulo `2^(biL*X_limbs)`. + * + * \param[in,out] X The pointer to the (little-endian) array + * representing the bignum to accumulate onto. + * \param X_limbs The number of limbs of \p X. This must be + * at least \p A_limbs. + * \param[in] A The pointer to the (little-endian) array + * representing the bignum to multiply with. + * This may be aliased to \p X but may not overlap + * otherwise. + * \param A_limbs The number of limbs of \p A. + * \param b X scalar to multiply with. + * + * \return The carry at the end of the operation. + */ +mbedtls_mpi_uint mbedtls_mpi_core_mla(mbedtls_mpi_uint *X, size_t X_limbs, + const mbedtls_mpi_uint *A, size_t A_limbs, + mbedtls_mpi_uint b); + +/** + * \brief Calculate initialisation value for fast Montgomery modular + * multiplication + * + * \param[in] N Little-endian presentation of the modulus. This must have + * at least one limb. + * + * \return The initialisation value for fast Montgomery modular multiplication + */ +mbedtls_mpi_uint mbedtls_mpi_core_montmul_init(const mbedtls_mpi_uint *N); + +/** + * \brief Montgomery multiplication: X = A * B * R^-1 mod N (HAC 14.36) + * + * \p A and \p B must be in canonical form. That is, < \p N. + * + * \p X may be aliased to \p A or \p N, or even \p B (if \p AN_limbs == + * \p B_limbs) but may not overlap any parameters otherwise. + * + * \p A and \p B may alias each other, if \p AN_limbs == \p B_limbs. They may + * not alias \p N (since they must be in canonical form, they cannot == \p N). + * + * \param[out] X The destination MPI, as a little-endian array of + * length \p AN_limbs. + * On successful completion, X contains the result of + * the multiplication `A * B * R^-1` mod N where + * `R = 2^(biL*AN_limbs)`. + * \param[in] A Little-endian presentation of first operand. + * Must have the same number of limbs as \p N. + * \param[in] B Little-endian presentation of second operand. + * \param[in] B_limbs The number of limbs in \p B. + * Must be <= \p AN_limbs. + * \param[in] N Little-endian presentation of the modulus. + * This must be odd, and have exactly the same number + * of limbs as \p A. + * It may alias \p X, but must not alias or otherwise + * overlap any of the other parameters. + * \param[in] AN_limbs The number of limbs in \p X, \p A and \p N. + * \param mm The Montgomery constant for \p N: -N^-1 mod 2^biL. + * This can be calculated by `mbedtls_mpi_core_montmul_init()`. + * \param[in,out] T Temporary storage of size at least 2*AN_limbs+1 limbs. + * Its initial content is unused and + * its final content is indeterminate. + * It must not alias or otherwise overlap any of the + * other parameters. + */ +void mbedtls_mpi_core_montmul(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *B, size_t B_limbs, + const mbedtls_mpi_uint *N, size_t AN_limbs, + mbedtls_mpi_uint mm, mbedtls_mpi_uint *T); + +/** + * \brief Calculate the square of the Montgomery constant. (Needed + * for conversion and operations in Montgomery form.) + * + * \param[out] X A pointer to the result of the calculation of + * the square of the Montgomery constant: + * 2^{2*n*biL} mod N. + * \param[in] N Little-endian presentation of the modulus, which must be odd. + * + * \return 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if there is not enough space + * to store the value of Montgomery constant squared. + * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p N modulus is zero. + * \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p N modulus is negative. + */ +int mbedtls_mpi_core_get_mont_r2_unsafe(mbedtls_mpi *X, + const mbedtls_mpi *N); + +#if defined(MBEDTLS_TEST_HOOKS) +/** + * Copy an MPI from a table without leaking the index. + * + * \param dest The destination buffer. This must point to a writable + * buffer of at least \p limbs limbs. + * \param table The address of the table. This must point to a readable + * array of \p count elements of \p limbs limbs each. + * \param limbs The number of limbs in each table entry. + * \param count The number of entries in \p table. + * \param index The (secret) table index to look up. This must be in the + * range `0 .. count-1`. + */ +void mbedtls_mpi_core_ct_uint_table_lookup(mbedtls_mpi_uint *dest, + const mbedtls_mpi_uint *table, + size_t limbs, + size_t count, + size_t index); +#endif /* MBEDTLS_TEST_HOOKS */ + +/** + * \brief Fill an integer with a number of random bytes. + * + * \param X The destination MPI. + * \param X_limbs The number of limbs of \p X. + * \param bytes 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_BAD_INPUT_DATA if \p X does not have + * enough room for \p bytes bytes. + * \return A negative error code on RNG 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_core_fill_random(mbedtls_mpi_uint *X, size_t X_limbs, + size_t bytes, + 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, with \p limbs limbs. + * It must not be aliased with \p N or otherwise overlap it. + * \param min The minimum value to return. + * \param N The upper bound of the range, exclusive, with \p limbs limbs. + * In other words, this is one plus the maximum value to return. + * \p N must be strictly larger than \p min. + * \param limbs The number of limbs of \p N and \p X. + * This must not be 0. + * \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_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. + */ +int mbedtls_mpi_core_random(mbedtls_mpi_uint *X, + mbedtls_mpi_uint min, + const mbedtls_mpi_uint *N, + size_t limbs, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng); + +/* BEGIN MERGE SLOT 1 */ + +/** + * \brief Returns the number of limbs of working memory required for + * a call to `mbedtls_mpi_core_exp_mod()`. + * + * \note This will always be at least + * `mbedtls_mpi_core_montmul_working_limbs(AN_limbs)`, + * i.e. sufficient for a call to `mbedtls_mpi_core_montmul()`. + * + * \param AN_limbs The number of limbs in the input `A` and the modulus `N` + * (they must be the same size) that will be given to + * `mbedtls_mpi_core_exp_mod()`. + * \param E_limbs The number of limbs in the exponent `E` that will be given + * to `mbedtls_mpi_core_exp_mod()`. + * + * \return The number of limbs of working memory required by + * `mbedtls_mpi_core_exp_mod()`. + */ +size_t mbedtls_mpi_core_exp_mod_working_limbs(size_t AN_limbs, size_t E_limbs); + +/** + * \brief Perform a modular exponentiation with secret exponent: + * X = A^E mod N, where \p A is already in Montgomery form. + * + * \p X may be aliased to \p A, but not to \p RR or \p E, even if \p E_limbs == + * \p AN_limbs. + * + * \param[out] X The destination MPI, as a little endian array of length + * \p AN_limbs. + * \param[in] A The base MPI, as a little endian array of length \p AN_limbs. + * Must be in Montgomery form. + * \param[in] N The modulus, as a little endian array of length \p AN_limbs. + * \param AN_limbs The number of limbs in \p X, \p A, \p N, \p RR. + * \param[in] E The exponent, as a little endian array of length \p E_limbs. + * \param E_limbs The number of limbs in \p E. + * \param[in] RR The precomputed residue of 2^{2*biL} modulo N, as a little + * endian array of length \p AN_limbs. + * \param[in,out] T Temporary storage of at least the number of limbs returned + * by `mbedtls_mpi_core_exp_mod_working_limbs()`. + * Its initial content is unused and its final content is + * indeterminate. + * It must not alias or otherwise overlap any of the other + * parameters. + * It is up to the caller to zeroize \p T when it is no + * longer needed, and before freeing it if it was dynamically + * allocated. + */ +void mbedtls_mpi_core_exp_mod(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *N, size_t AN_limbs, + const mbedtls_mpi_uint *E, size_t E_limbs, + const mbedtls_mpi_uint *RR, + mbedtls_mpi_uint *T); + +/* END MERGE SLOT 1 */ + +/* BEGIN MERGE SLOT 2 */ + +/* END MERGE SLOT 2 */ + +/* BEGIN MERGE SLOT 3 */ + +/** + * \brief Subtract unsigned integer from known-size large unsigned integers. + * Return the borrow. + * + * \param[out] X The result of the subtraction. + * \param[in] A The left operand. + * \param b The unsigned scalar to subtract. + * \param limbs Number of limbs of \p X and \p A. + * + * \return 1 if `A < b`. + * 0 if `A >= b`. + */ +mbedtls_mpi_uint mbedtls_mpi_core_sub_int(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + mbedtls_mpi_uint b, + size_t limbs); + +/** + * \brief Determine if a given MPI has the value \c 0 in constant time with + * respect to the value (but not with respect to the number of limbs). + * + * \param[in] A The MPI to test. + * \param limbs Number of limbs in \p A. + * + * \return 0 if `A == 0` + * non-0 (may be any value) if `A != 0`. + */ +mbedtls_mpi_uint mbedtls_mpi_core_check_zero_ct(const mbedtls_mpi_uint *A, + size_t limbs); + +/** + * \brief Returns the number of limbs of working memory required for + * a call to `mbedtls_mpi_core_montmul()`. + * + * \param AN_limbs The number of limbs in the input `A` and the modulus `N` + * (they must be the same size) that will be given to + * `mbedtls_mpi_core_montmul()` or one of the other functions + * that specifies this as the amount of working memory needed. + * + * \return The number of limbs of working memory required by + * `mbedtls_mpi_core_montmul()` (or other similar function). + */ +static inline size_t mbedtls_mpi_core_montmul_working_limbs(size_t AN_limbs) +{ + return 2 * AN_limbs + 1; +} + +/** Convert an MPI into Montgomery form. + * + * \p X may be aliased to \p A, but may not otherwise overlap it. + * + * \p X may not alias \p N (it is in canonical form, so must be strictly less + * than \p N). Nor may it alias or overlap \p rr (this is unlikely to be + * required in practice.) + * + * This function is a thin wrapper around `mbedtls_mpi_core_montmul()` that is + * an alternative to calling `mbedtls_mpi_mod_raw_to_mont_rep()` when we + * don't want to allocate memory. + * + * \param[out] X The result of the conversion. + * Must have the same number of limbs as \p A. + * \param[in] A The MPI to convert into Montgomery form. + * Must have the same number of limbs as the modulus. + * \param[in] N The address of the modulus, which gives the size of + * the base `R` = 2^(biL*N->limbs). + * \param[in] AN_limbs The number of limbs in \p X, \p A, \p N and \p rr. + * \param mm The Montgomery constant for \p N: -N^-1 mod 2^biL. + * This can be determined by calling + * `mbedtls_mpi_core_montmul_init()`. + * \param[in] rr The residue for `2^{2*n*biL} mod N`. + * \param[in,out] T Temporary storage of size at least + * `mbedtls_mpi_core_montmul_working_limbs(AN_limbs)` + * limbs. + * Its initial content is unused and + * its final content is indeterminate. + * It must not alias or otherwise overlap any of the + * other parameters. + */ +void mbedtls_mpi_core_to_mont_rep(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *N, + size_t AN_limbs, + mbedtls_mpi_uint mm, + const mbedtls_mpi_uint *rr, + mbedtls_mpi_uint *T); + +/** Convert an MPI from Montgomery form. + * + * \p X may be aliased to \p A, but may not otherwise overlap it. + * + * \p X may not alias \p N (it is in canonical form, so must be strictly less + * than \p N). + * + * This function is a thin wrapper around `mbedtls_mpi_core_montmul()` that is + * an alternative to calling `mbedtls_mpi_mod_raw_from_mont_rep()` when we + * don't want to allocate memory. + * + * \param[out] X The result of the conversion. + * Must have the same number of limbs as \p A. + * \param[in] A The MPI to convert from Montgomery form. + * Must have the same number of limbs as the modulus. + * \param[in] N The address of the modulus, which gives the size of + * the base `R` = 2^(biL*N->limbs). + * \param[in] AN_limbs The number of limbs in \p X, \p A and \p N. + * \param mm The Montgomery constant for \p N: -N^-1 mod 2^biL. + * This can be determined by calling + * `mbedtls_mpi_core_montmul_init()`. + * \param[in,out] T Temporary storage of size at least + * `mbedtls_mpi_core_montmul_working_limbs(AN_limbs)` + * limbs. + * Its initial content is unused and + * its final content is indeterminate. + * It must not alias or otherwise overlap any of the + * other parameters. + */ +void mbedtls_mpi_core_from_mont_rep(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *N, + size_t AN_limbs, + mbedtls_mpi_uint mm, + mbedtls_mpi_uint *T); + +/* END MERGE SLOT 3 */ + +/* BEGIN MERGE SLOT 4 */ + +/* END MERGE SLOT 4 */ + +/* BEGIN MERGE SLOT 5 */ + +/* END MERGE SLOT 5 */ + +/* BEGIN MERGE SLOT 6 */ + +/* END MERGE SLOT 6 */ + +/* BEGIN MERGE SLOT 7 */ + +/* END MERGE SLOT 7 */ + +/* BEGIN MERGE SLOT 8 */ + +/* END MERGE SLOT 8 */ + +/* BEGIN MERGE SLOT 9 */ + +/* END MERGE SLOT 9 */ + +/* BEGIN MERGE SLOT 10 */ + +/* END MERGE SLOT 10 */ + +#endif /* MBEDTLS_BIGNUM_CORE_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_mod.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_mod.c new file mode 100644 index 0000000..e986865 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_mod.c @@ -0,0 +1,434 @@ +/** + * Modular bignum 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_BIGNUM_C) + +#include + +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" +#include "mbedtls/bignum.h" + +#include "mbedtls/platform.h" + +#include "bignum_core.h" +#include "bignum_mod.h" +#include "bignum_mod_raw.h" +#include "constant_time_internal.h" + +int mbedtls_mpi_mod_residue_setup(mbedtls_mpi_mod_residue *r, + const mbedtls_mpi_mod_modulus *N, + mbedtls_mpi_uint *p, + size_t p_limbs) +{ + if (p_limbs != N->limbs || !mbedtls_mpi_core_lt_ct(p, N->p, N->limbs)) { + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + } + + r->limbs = N->limbs; + r->p = p; + + return 0; +} + +void mbedtls_mpi_mod_residue_release(mbedtls_mpi_mod_residue *r) +{ + if (r == NULL) { + return; + } + + r->limbs = 0; + r->p = NULL; +} + +void mbedtls_mpi_mod_modulus_init(mbedtls_mpi_mod_modulus *N) +{ + if (N == NULL) { + return; + } + + N->p = NULL; + N->limbs = 0; + N->bits = 0; + N->int_rep = MBEDTLS_MPI_MOD_REP_INVALID; +} + +void mbedtls_mpi_mod_modulus_free(mbedtls_mpi_mod_modulus *N) +{ + if (N == NULL) { + return; + } + + switch (N->int_rep) { + case MBEDTLS_MPI_MOD_REP_MONTGOMERY: + if (N->rep.mont.rr != NULL) { + mbedtls_platform_zeroize((mbedtls_mpi_uint *) N->rep.mont.rr, + N->limbs * sizeof(mbedtls_mpi_uint)); + mbedtls_free((mbedtls_mpi_uint *) N->rep.mont.rr); + N->rep.mont.rr = NULL; + } + N->rep.mont.mm = 0; + break; + case MBEDTLS_MPI_MOD_REP_OPT_RED: + mbedtls_free(N->rep.ored); + break; + case MBEDTLS_MPI_MOD_REP_INVALID: + break; + } + + N->p = NULL; + N->limbs = 0; + N->bits = 0; + N->int_rep = MBEDTLS_MPI_MOD_REP_INVALID; +} + +static int set_mont_const_square(const mbedtls_mpi_uint **X, + const mbedtls_mpi_uint *A, + size_t limbs) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi N; + mbedtls_mpi RR; + *X = NULL; + + mbedtls_mpi_init(&N); + mbedtls_mpi_init(&RR); + + if (A == NULL || limbs == 0 || limbs >= (MBEDTLS_MPI_MAX_LIMBS / 2) - 2) { + goto cleanup; + } + + if (mbedtls_mpi_grow(&N, limbs)) { + goto cleanup; + } + + memcpy(N.p, A, sizeof(mbedtls_mpi_uint) * limbs); + + ret = mbedtls_mpi_core_get_mont_r2_unsafe(&RR, &N); + + if (ret == 0) { + *X = RR.p; + RR.p = NULL; + } + +cleanup: + mbedtls_mpi_free(&N); + mbedtls_mpi_free(&RR); + ret = (ret != 0) ? MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED : 0; + return ret; +} + +int mbedtls_mpi_mod_modulus_setup(mbedtls_mpi_mod_modulus *N, + const mbedtls_mpi_uint *p, + size_t p_limbs, + mbedtls_mpi_mod_rep_selector int_rep) +{ + int ret = 0; + + N->p = p; + N->limbs = p_limbs; + N->bits = mbedtls_mpi_core_bitlen(p, p_limbs); + + switch (int_rep) { + case MBEDTLS_MPI_MOD_REP_MONTGOMERY: + N->int_rep = int_rep; + N->rep.mont.mm = mbedtls_mpi_core_montmul_init(N->p); + ret = set_mont_const_square(&N->rep.mont.rr, N->p, N->limbs); + break; + case MBEDTLS_MPI_MOD_REP_OPT_RED: + N->int_rep = int_rep; + N->rep.ored = NULL; + break; + default: + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + goto exit; + } + +exit: + + if (ret != 0) { + mbedtls_mpi_mod_modulus_free(N); + } + + return ret; +} + +/* BEGIN MERGE SLOT 1 */ + +/* END MERGE SLOT 1 */ + +/* BEGIN MERGE SLOT 2 */ + +int mbedtls_mpi_mod_mul(mbedtls_mpi_mod_residue *X, + const mbedtls_mpi_mod_residue *A, + const mbedtls_mpi_mod_residue *B, + const mbedtls_mpi_mod_modulus *N) +{ + if (N->limbs == 0) { + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + } + + if (X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs) { + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + } + + mbedtls_mpi_uint *T = mbedtls_calloc(N->limbs * 2 + 1, ciL); + if (T == NULL) { + return MBEDTLS_ERR_MPI_ALLOC_FAILED; + } + + mbedtls_mpi_mod_raw_mul(X->p, A->p, B->p, N, T); + + mbedtls_free(T); + + return 0; +} + +/* END MERGE SLOT 2 */ + +/* BEGIN MERGE SLOT 3 */ +int mbedtls_mpi_mod_sub(mbedtls_mpi_mod_residue *X, + const mbedtls_mpi_mod_residue *A, + const mbedtls_mpi_mod_residue *B, + const mbedtls_mpi_mod_modulus *N) +{ + if (X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs) { + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + } + + mbedtls_mpi_mod_raw_sub(X->p, A->p, B->p, N); + + return 0; +} + +static int mbedtls_mpi_mod_inv_mont(mbedtls_mpi_mod_residue *X, + const mbedtls_mpi_mod_residue *A, + const mbedtls_mpi_mod_modulus *N, + mbedtls_mpi_uint *working_memory) +{ + /* Input already in Montgomery form, so there's little to do */ + mbedtls_mpi_mod_raw_inv_prime(X->p, A->p, + N->p, N->limbs, + N->rep.mont.rr, + working_memory); + return 0; +} + +static int mbedtls_mpi_mod_inv_non_mont(mbedtls_mpi_mod_residue *X, + const mbedtls_mpi_mod_residue *A, + const mbedtls_mpi_mod_modulus *N, + mbedtls_mpi_uint *working_memory) +{ + /* Need to convert input into Montgomery form */ + + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_mpi_mod_modulus Nmont; + mbedtls_mpi_mod_modulus_init(&Nmont); + + MBEDTLS_MPI_CHK(mbedtls_mpi_mod_modulus_setup(&Nmont, N->p, N->limbs, + MBEDTLS_MPI_MOD_REP_MONTGOMERY)); + + /* We'll use X->p to hold the Montgomery form of the input A->p */ + mbedtls_mpi_core_to_mont_rep(X->p, A->p, Nmont.p, Nmont.limbs, + Nmont.rep.mont.mm, Nmont.rep.mont.rr, + working_memory); + + mbedtls_mpi_mod_raw_inv_prime(X->p, X->p, + Nmont.p, Nmont.limbs, + Nmont.rep.mont.rr, + working_memory); + + /* And convert back from Montgomery form */ + + mbedtls_mpi_core_from_mont_rep(X->p, X->p, Nmont.p, Nmont.limbs, + Nmont.rep.mont.mm, working_memory); + +cleanup: + mbedtls_mpi_mod_modulus_free(&Nmont); + return ret; +} + +int mbedtls_mpi_mod_inv(mbedtls_mpi_mod_residue *X, + const mbedtls_mpi_mod_residue *A, + const mbedtls_mpi_mod_modulus *N) +{ + if (X->limbs != N->limbs || A->limbs != N->limbs) { + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + } + + /* Zero has the same value regardless of Montgomery form or not */ + if (mbedtls_mpi_core_check_zero_ct(A->p, A->limbs) == 0) { + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + } + + size_t working_limbs = + mbedtls_mpi_mod_raw_inv_prime_working_limbs(N->limbs); + + mbedtls_mpi_uint *working_memory = mbedtls_calloc(working_limbs, + sizeof(mbedtls_mpi_uint)); + if (working_memory == NULL) { + return MBEDTLS_ERR_MPI_ALLOC_FAILED; + } + + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + switch (N->int_rep) { + case MBEDTLS_MPI_MOD_REP_MONTGOMERY: + ret = mbedtls_mpi_mod_inv_mont(X, A, N, working_memory); + break; + case MBEDTLS_MPI_MOD_REP_OPT_RED: + ret = mbedtls_mpi_mod_inv_non_mont(X, A, N, working_memory); + break; + default: + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + break; + } + + mbedtls_platform_zeroize(working_memory, + working_limbs * sizeof(mbedtls_mpi_uint)); + mbedtls_free(working_memory); + + return ret; +} +/* END MERGE SLOT 3 */ + +/* BEGIN MERGE SLOT 4 */ + +/* END MERGE SLOT 4 */ + +/* BEGIN MERGE SLOT 5 */ +int mbedtls_mpi_mod_add(mbedtls_mpi_mod_residue *X, + const mbedtls_mpi_mod_residue *A, + const mbedtls_mpi_mod_residue *B, + const mbedtls_mpi_mod_modulus *N) +{ + if (X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs) { + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + } + + mbedtls_mpi_mod_raw_add(X->p, A->p, B->p, N); + + return 0; +} +/* END MERGE SLOT 5 */ + +/* BEGIN MERGE SLOT 6 */ + +int mbedtls_mpi_mod_random(mbedtls_mpi_mod_residue *X, + mbedtls_mpi_uint min, + const mbedtls_mpi_mod_modulus *N, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) +{ + if (X->limbs != N->limbs) { + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + } + return mbedtls_mpi_mod_raw_random(X->p, min, N, f_rng, p_rng); +} + +/* END MERGE SLOT 6 */ + +/* BEGIN MERGE SLOT 7 */ +int mbedtls_mpi_mod_read(mbedtls_mpi_mod_residue *r, + const mbedtls_mpi_mod_modulus *N, + const unsigned char *buf, + size_t buflen, + mbedtls_mpi_mod_ext_rep ext_rep) +{ + int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + + /* Do our best to check if r and m have been set up */ + if (r->limbs == 0 || N->limbs == 0) { + goto cleanup; + } + if (r->limbs != N->limbs) { + goto cleanup; + } + + ret = mbedtls_mpi_mod_raw_read(r->p, N, buf, buflen, ext_rep); + if (ret != 0) { + goto cleanup; + } + + r->limbs = N->limbs; + + ret = mbedtls_mpi_mod_raw_canonical_to_modulus_rep(r->p, N); + +cleanup: + return ret; +} + +int mbedtls_mpi_mod_write(const mbedtls_mpi_mod_residue *r, + const mbedtls_mpi_mod_modulus *N, + unsigned char *buf, + size_t buflen, + mbedtls_mpi_mod_ext_rep ext_rep) +{ + int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + + /* Do our best to check if r and m have been set up */ + if (r->limbs == 0 || N->limbs == 0) { + goto cleanup; + } + if (r->limbs != N->limbs) { + goto cleanup; + } + + if (N->int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY) { + ret = mbedtls_mpi_mod_raw_from_mont_rep(r->p, N); + if (ret != 0) { + goto cleanup; + } + } + + ret = mbedtls_mpi_mod_raw_write(r->p, N, buf, buflen, ext_rep); + + if (N->int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY) { + /* If this fails, the value of r is corrupted and we want to return + * this error (as opposed to the error code from the write above) to + * let the caller know. If it succeeds, we want to return the error + * code from write above. */ + int conv_ret = mbedtls_mpi_mod_raw_to_mont_rep(r->p, N); + if (ret == 0) { + ret = conv_ret; + } + } + +cleanup: + + return ret; +} +/* END MERGE SLOT 7 */ + +/* BEGIN MERGE SLOT 8 */ + +/* END MERGE SLOT 8 */ + +/* BEGIN MERGE SLOT 9 */ + +/* END MERGE SLOT 9 */ + +/* BEGIN MERGE SLOT 10 */ + +/* END MERGE SLOT 10 */ + +#endif /* MBEDTLS_BIGNUM_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_mod.h b/optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_mod.h new file mode 100644 index 0000000..d4c1d5d --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_mod.h @@ -0,0 +1,481 @@ +/** + * Modular bignum functions + * + * This module implements operations on integers modulo some fixed modulus. + * + * The functions in this module obey the following conventions unless + * explicitly indicated otherwise: + * + * - **Modulus parameters**: the modulus is passed as a pointer to a structure + * of type #mbedtls_mpi_mod_modulus. The structure must be set up with an + * array of limbs storing the bignum value of the modulus. The modulus must + * be odd and is assumed to have no leading zeroes. The modulus is usually + * named \c N and is usually input-only. Functions which take a parameter + * of type \c const #mbedtls_mpi_mod_modulus* must not modify its value. + * - **Bignum parameters**: Bignums are passed as pointers to an array of + * limbs or to a #mbedtls_mpi_mod_residue structure. A limb has the type + * #mbedtls_mpi_uint. Residues must be initialized before use, and must be + * associated with the modulus \c N. Unless otherwise specified: + * - Bignum parameters called \c A, \c B, ... are inputs and are not + * modified by the function. Functions which take a parameter of + * type \c const #mbedtls_mpi_mod_residue* must not modify its value. + * - Bignum parameters called \c X, \c Y, ... are outputs or input-output. + * The initial bignum value of output-only parameters is ignored, but + * they must be set up and associated with the modulus \c N. Some + * functions (typically constant-flow) require that the limbs in an + * output residue are initialized. + * - Bignum parameters called \c p are inputs used to set up a modulus or + * residue. These must be pointers to an array of limbs. + * - \c T is a temporary storage area. The initial content of such a + * parameter is ignored and the final content is unspecified. + * - Some functions use different names, such as \c r for the residue. + * - **Bignum sizes**: bignum sizes are always expressed in limbs. Both + * #mbedtls_mpi_mod_modulus and #mbedtls_mpi_mod_residue have a \c limbs + * member storing its size. All bignum parameters must have the same + * number of limbs as the modulus. All bignum sizes must be at least 1 and + * must be significantly less than #SIZE_MAX. The behavior if a size is 0 is + * undefined. + * - **Bignum representation**: the representation of inputs and outputs is + * specified by the \c int_rep field of the modulus. + * - **Parameter ordering**: for bignum parameters, outputs come before inputs. + * The modulus is passed after residues. Temporaries come last. + * - **Aliasing**: in general, output bignums may be aliased to one or more + * inputs. Modulus values may not be aliased to any other parameter. Outputs + * may not be aliased to one another. Temporaries may not be aliased to any + * other parameter. + * - **Overlap**: apart from aliasing of residue pointers (where two residue + * arguments are equal pointers), overlap is not supported and may result + * in undefined behavior. + * - **Error handling**: functions generally check compatibility of input + * sizes. Most functions will not check that input values are in canonical + * form (i.e. that \c A < \c N), this is only checked during setup of a + * residue structure. + * - **Modular representatives**: all functions expect inputs to be in the + * range [0, \c N - 1] and guarantee outputs in the range [0, \c N - 1]. + * Residues are set up with an associated modulus, and operations are only + * guaranteed to work if the modulus is associated with all residue + * parameters. If a residue is passed with a modulus other than the one it + * is associated with, then it may be out of range. If an input is out of + * range, outputs are fully unspecified, though bignum values out of range + * should not cause buffer overflows (beware that this is not extensively + * tested). + */ + +/* + * 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_MOD_H +#define MBEDTLS_BIGNUM_MOD_H + +#include "common.h" + +#if defined(MBEDTLS_BIGNUM_C) +#include "mbedtls/bignum.h" +#endif + +/** How residues associated with a modulus are represented. + * + * This also determines which fields of the modulus structure are valid and + * what their contents are (see #mbedtls_mpi_mod_modulus). + */ +typedef enum { + /** Representation not chosen (makes the modulus structure invalid). */ + MBEDTLS_MPI_MOD_REP_INVALID = 0, + /* Skip 1 as it is slightly easier to accidentally pass to functions. */ + /** Montgomery representation. */ + MBEDTLS_MPI_MOD_REP_MONTGOMERY = 2, + /** TODO: document this. + * + * Residues are in canonical representation. + */ + MBEDTLS_MPI_MOD_REP_OPT_RED, +} mbedtls_mpi_mod_rep_selector; + +/* Make mbedtls_mpi_mod_rep_selector and mbedtls_mpi_mod_ext_rep disjoint to + * make it easier to catch when they are accidentally swapped. */ +typedef enum { + MBEDTLS_MPI_MOD_EXT_REP_INVALID = 0, + MBEDTLS_MPI_MOD_EXT_REP_LE = 8, + MBEDTLS_MPI_MOD_EXT_REP_BE +} mbedtls_mpi_mod_ext_rep; + +typedef struct { + mbedtls_mpi_uint *p; + size_t limbs; +} mbedtls_mpi_mod_residue; + +typedef struct { + mbedtls_mpi_uint const *rr; /* The residue for 2^{2*n*biL} mod N */ + mbedtls_mpi_uint mm; /* Montgomery const for -N^{-1} mod 2^{ciL} */ +} mbedtls_mpi_mont_struct; + +typedef void *mbedtls_mpi_opt_red_struct; + +typedef struct { + const mbedtls_mpi_uint *p; + size_t limbs; // number of limbs + size_t bits; // bitlen of p + mbedtls_mpi_mod_rep_selector int_rep; // selector to signal the active member of the union + union rep { + /* if int_rep == #MBEDTLS_MPI_MOD_REP_MONTGOMERY */ + mbedtls_mpi_mont_struct mont; + /* if int_rep == #MBEDTLS_MPI_MOD_REP_OPT_RED */ + mbedtls_mpi_opt_red_struct ored; + } rep; +} mbedtls_mpi_mod_modulus; + +/** Setup a residue structure. + * + * The residue will be set up with the buffer \p p and modulus \p N. + * + * The memory pointed to by \p p will be used by the resulting residue structure. + * The value at the pointed-to memory will be the initial value of \p r and must + * hold a value that is less than the modulus. This value will be used as-is + * and interpreted according to the value of the `N->int_rep` field. + * + * The modulus \p N will be the modulus associated with \p r. The residue \p r + * should only be used in operations where the modulus is \p N. + * + * \param[out] r The address of the residue to setup. + * \param[in] N The address of the modulus related to \p r. + * \param[in] p The address of the limb array containing the value of \p r. + * The memory pointed to by \p p will be used by \p r and must + * not be modified in any way until after + * mbedtls_mpi_mod_residue_release() is called. The data + * pointed to by \p p must be less than the modulus (the value + * pointed to by `N->p`) and already in the representation + * indicated by `N->int_rep`. + * \param p_limbs The number of limbs of \p p. Must be the same as the number + * of limbs in the modulus \p N. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p p_limbs is less than the + * limbs in \p N or if \p p is not less than \p N. + */ +int mbedtls_mpi_mod_residue_setup(mbedtls_mpi_mod_residue *r, + const mbedtls_mpi_mod_modulus *N, + mbedtls_mpi_uint *p, + size_t p_limbs); + +/** Unbind elements of a residue structure. + * + * This function removes the reference to the limb array that was passed to + * mbedtls_mpi_mod_residue_setup() to make it safe to free or use again. + * + * This function invalidates \p r and it must not be used until after + * mbedtls_mpi_mod_residue_setup() is called on it again. + * + * \param[out] r The address of residue to release. + */ +void mbedtls_mpi_mod_residue_release(mbedtls_mpi_mod_residue *r); + +/** Initialize a modulus structure. + * + * \param[out] N The address of the modulus structure to initialize. + */ +void mbedtls_mpi_mod_modulus_init(mbedtls_mpi_mod_modulus *N); + +/** Setup a modulus structure. + * + * \param[out] N The address of the modulus structure to populate. + * \param[in] p The address of the limb array storing the value of \p N. + * The memory pointed to by \p p will be used by \p N and must + * not be modified in any way until after + * mbedtls_mpi_mod_modulus_free() is called. + * \param p_limbs The number of limbs of \p p. + * \param int_rep The internal representation to be used for residues + * associated with \p N (see #mbedtls_mpi_mod_rep_selector). + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p int_rep is invalid. + */ +int mbedtls_mpi_mod_modulus_setup(mbedtls_mpi_mod_modulus *N, + const mbedtls_mpi_uint *p, + size_t p_limbs, + mbedtls_mpi_mod_rep_selector int_rep); + +/** Free elements of a modulus structure. + * + * This function frees any memory allocated by mbedtls_mpi_mod_modulus_setup(). + * + * \warning This function does not free the limb array passed to + * mbedtls_mpi_mod_modulus_setup() only removes the reference to it, + * making it safe to free or to use it again. + * + * \param[in,out] N The address of the modulus structure to free. + */ +void mbedtls_mpi_mod_modulus_free(mbedtls_mpi_mod_modulus *N); + +/* BEGIN MERGE SLOT 1 */ + +/* END MERGE SLOT 1 */ + +/* BEGIN MERGE SLOT 2 */ + +/** \brief Multiply two residues, returning the residue modulo the specified + * modulus. + * + * \note Currently handles the case when `N->int_rep` is + * MBEDTLS_MPI_MOD_REP_MONTGOMERY. + * + * The size of the operation is determined by \p N. \p A, \p B and \p X must + * all be associated with the modulus \p N and must all have the same number + * of limbs as \p N. + * + * \p X may be aliased to \p A or \p B, or even both, but may not overlap + * either otherwise. They may not alias \p N (since they must be in canonical + * form, they cannot == \p N). + * + * \param[out] X The address of the result MPI. Must have the same + * number of limbs as \p N. + * On successful completion, \p X contains the result of + * the multiplication `A * B * R^-1` mod N where + * `R = 2^(biL * N->limbs)`. + * \param[in] A The address of the first MPI. + * \param[in] B The address of the second MPI. + * \param[in] N The address of the modulus. Used to perform a modulo + * operation on the result of the multiplication. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if all the parameters do not + * have the same number of limbs or \p N is invalid. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + */ +int mbedtls_mpi_mod_mul(mbedtls_mpi_mod_residue *X, + const mbedtls_mpi_mod_residue *A, + const mbedtls_mpi_mod_residue *B, + const mbedtls_mpi_mod_modulus *N); + +/* END MERGE SLOT 2 */ + +/* BEGIN MERGE SLOT 3 */ +/** + * \brief Perform a fixed-size modular subtraction. + * + * Calculate `A - B modulo N`. + * + * \p A, \p B and \p X must all have the same number of limbs as \p N. + * + * \p X may be aliased to \p A or \p B, or even both, but may not overlap + * either otherwise. + * + * \note This function does not check that \p A or \p B are in canonical + * form (that is, are < \p N) - that will have been done by + * mbedtls_mpi_mod_residue_setup(). + * + * \param[out] X The address of the result MPI. Must be initialized. + * Must have the same number of limbs as the modulus \p N. + * \param[in] A The address of the first MPI. + * \param[in] B The address of the second MPI. + * \param[in] N The address of the modulus. Used to perform a modulo + * operation on the result of the subtraction. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the given MPIs do not + * have the correct number of limbs. + */ +int mbedtls_mpi_mod_sub(mbedtls_mpi_mod_residue *X, + const mbedtls_mpi_mod_residue *A, + const mbedtls_mpi_mod_residue *B, + const mbedtls_mpi_mod_modulus *N); + +/** + * \brief Perform modular inversion of an MPI with respect to a modulus \p N. + * + * \p A and \p X must be associated with the modulus \p N and will therefore + * have the same number of limbs as \p N. + * + * \p X may be aliased to \p A. + * + * \warning Currently only supports prime moduli, but does not check for them. + * + * \param[out] X The modular inverse of \p A with respect to \p N. + * \param[in] A The number to calculate the modular inverse of. + * Must not be 0. + * \param[in] N The modulus to use. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p A and \p N do not + * have the same number of limbs. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p A is zero. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if couldn't allocate enough + * memory (needed for conversion to and from Mongtomery form + * when not in Montgomery form already, and for temporary use + * by the inversion calculation itself). + */ + +int mbedtls_mpi_mod_inv(mbedtls_mpi_mod_residue *X, + const mbedtls_mpi_mod_residue *A, + const mbedtls_mpi_mod_modulus *N); +/* END MERGE SLOT 3 */ + +/* BEGIN MERGE SLOT 4 */ + +/* END MERGE SLOT 4 */ + +/* BEGIN MERGE SLOT 5 */ +/** + * \brief Perform a fixed-size modular addition. + * + * Calculate `A + B modulo N`. + * + * \p A, \p B and \p X must all be associated with the modulus \p N and must + * all have the same number of limbs as \p N. + * + * \p X may be aliased to \p A or \p B, or even both, but may not overlap + * either otherwise. + * + * \note This function does not check that \p A or \p B are in canonical + * form (that is, are < \p N) - that will have been done by + * mbedtls_mpi_mod_residue_setup(). + * + * \param[out] X The address of the result residue. Must be initialized. + * Must have the same number of limbs as the modulus \p N. + * \param[in] A The address of the first input residue. + * \param[in] B The address of the second input residue. + * \param[in] N The address of the modulus. Used to perform a modulo + * operation on the result of the addition. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the given MPIs do not + * have the correct number of limbs. + */ +int mbedtls_mpi_mod_add(mbedtls_mpi_mod_residue *X, + const mbedtls_mpi_mod_residue *A, + const mbedtls_mpi_mod_residue *B, + const mbedtls_mpi_mod_modulus *N); +/* END MERGE SLOT 5 */ + +/* BEGIN MERGE SLOT 6 */ + +/** 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 residue. + * \param min The minimum value to return. It must be strictly smaller + * than \b N. + * \param N The modulus. + * This is the upper bound of the output range, exclusive. + * \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_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. + */ +int mbedtls_mpi_mod_random(mbedtls_mpi_mod_residue *X, + mbedtls_mpi_uint min, + const mbedtls_mpi_mod_modulus *N, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng); + +/* END MERGE SLOT 6 */ + +/* BEGIN MERGE SLOT 7 */ +/** Read a residue from a byte buffer. + * + * The residue will be automatically converted to the internal representation + * based on the value of the `N->int_rep` field. + * + * The modulus \p N will be the modulus associated with \p r. The residue \p r + * should only be used in operations where the modulus is \p N or a modulus + * equivalent to \p N (in the sense that all their fields or memory pointed by + * their fields hold the same value). + * + * \param[out] r The address of the residue. It must have exactly the same + * number of limbs as the modulus \p N. + * \param[in] N The address of the modulus. + * \param[in] buf The input buffer to import from. + * \param buflen The length in bytes of \p buf. + * \param ext_rep The endianness of the number in the input buffer. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p r isn't + * large enough to hold the value in \p buf. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p ext_rep + * is invalid or the value in the buffer is not less than \p N. + */ +int mbedtls_mpi_mod_read(mbedtls_mpi_mod_residue *r, + const mbedtls_mpi_mod_modulus *N, + const unsigned char *buf, + size_t buflen, + mbedtls_mpi_mod_ext_rep ext_rep); + +/** Write a residue into a byte buffer. + * + * The modulus \p N must be the modulus associated with \p r (see + * mbedtls_mpi_mod_residue_setup() and mbedtls_mpi_mod_read()). + * + * The residue will be automatically converted from the internal representation + * based on the value of `N->int_rep` field. + * + * \warning If the buffer is smaller than `N->bits`, the number of + * leading zeroes is leaked through timing. If \p r is + * secret, the caller must ensure that \p buflen is at least + * (`N->bits`+7)/8. + * + * \param[in] r The address of the residue. It must have the same number of + * limbs as the modulus \p N. (\p r is an input parameter, but + * its value will be modified during execution and restored + * before the function returns.) + * \param[in] N The address of the modulus associated with \p r. + * \param[out] buf The output buffer to export to. + * \param buflen The length in bytes of \p buf. + * \param ext_rep The endianness in which the number should be written into + * the output buffer. + * + * \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 r (without leading + * zeroes). + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p ext_rep is invalid. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if couldn't allocate enough + * memory for conversion. Can occur only for moduli with + * MBEDTLS_MPI_MOD_REP_MONTGOMERY. + */ +int mbedtls_mpi_mod_write(const mbedtls_mpi_mod_residue *r, + const mbedtls_mpi_mod_modulus *N, + unsigned char *buf, + size_t buflen, + mbedtls_mpi_mod_ext_rep ext_rep); +/* END MERGE SLOT 7 */ + +/* BEGIN MERGE SLOT 8 */ + +/* END MERGE SLOT 8 */ + +/* BEGIN MERGE SLOT 9 */ + +/* END MERGE SLOT 9 */ + +/* BEGIN MERGE SLOT 10 */ + +/* END MERGE SLOT 10 */ + +#endif /* MBEDTLS_BIGNUM_MOD_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_mod_raw.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_mod_raw.c new file mode 100644 index 0000000..bf0cb25 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_mod_raw.c @@ -0,0 +1,306 @@ +/* + * Low-level modular bignum 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_BIGNUM_C) + +#include + +#include "mbedtls/error.h" +#include "mbedtls/platform_util.h" + +#include "mbedtls/platform.h" + +#include "bignum_core.h" +#include "bignum_mod_raw.h" +#include "bignum_mod.h" +#include "constant_time_internal.h" + +#include "bignum_mod_raw_invasive.h" + +void mbedtls_mpi_mod_raw_cond_assign(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_mod_modulus *N, + unsigned char assign) +{ + mbedtls_mpi_core_cond_assign(X, A, N->limbs, assign); +} + +void mbedtls_mpi_mod_raw_cond_swap(mbedtls_mpi_uint *X, + mbedtls_mpi_uint *Y, + const mbedtls_mpi_mod_modulus *N, + unsigned char swap) +{ + mbedtls_mpi_core_cond_swap(X, Y, N->limbs, swap); +} + +int mbedtls_mpi_mod_raw_read(mbedtls_mpi_uint *X, + const mbedtls_mpi_mod_modulus *N, + const unsigned char *input, + size_t input_length, + mbedtls_mpi_mod_ext_rep ext_rep) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + switch (ext_rep) { + case MBEDTLS_MPI_MOD_EXT_REP_LE: + ret = mbedtls_mpi_core_read_le(X, N->limbs, + input, input_length); + break; + case MBEDTLS_MPI_MOD_EXT_REP_BE: + ret = mbedtls_mpi_core_read_be(X, N->limbs, + input, input_length); + break; + default: + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + } + + if (ret != 0) { + goto cleanup; + } + + if (!mbedtls_mpi_core_lt_ct(X, N->p, N->limbs)) { + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + goto cleanup; + } + +cleanup: + + return ret; +} + +int mbedtls_mpi_mod_raw_write(const mbedtls_mpi_uint *A, + const mbedtls_mpi_mod_modulus *N, + unsigned char *output, + size_t output_length, + mbedtls_mpi_mod_ext_rep ext_rep) +{ + switch (ext_rep) { + case MBEDTLS_MPI_MOD_EXT_REP_LE: + return mbedtls_mpi_core_write_le(A, N->limbs, + output, output_length); + case MBEDTLS_MPI_MOD_EXT_REP_BE: + return mbedtls_mpi_core_write_be(A, N->limbs, + output, output_length); + default: + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + } +} + +/* BEGIN MERGE SLOT 1 */ + +/* END MERGE SLOT 1 */ + +/* BEGIN MERGE SLOT 2 */ + +void mbedtls_mpi_mod_raw_sub(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *B, + const mbedtls_mpi_mod_modulus *N) +{ + mbedtls_mpi_uint c = mbedtls_mpi_core_sub(X, A, B, N->limbs); + + (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) c); +} + +#if defined(MBEDTLS_TEST_HOOKS) + +MBEDTLS_STATIC_TESTABLE +void mbedtls_mpi_mod_raw_fix_quasi_reduction(mbedtls_mpi_uint *X, + const mbedtls_mpi_mod_modulus *N) +{ + mbedtls_mpi_uint c = mbedtls_mpi_core_sub(X, X, N->p, N->limbs); + + (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) c); +} + +#endif /* MBEDTLS_TEST_HOOKS */ + +void mbedtls_mpi_mod_raw_mul(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *B, + const mbedtls_mpi_mod_modulus *N, + mbedtls_mpi_uint *T) +{ + mbedtls_mpi_core_montmul(X, A, B, N->limbs, N->p, N->limbs, + N->rep.mont.mm, T); +} + +/* END MERGE SLOT 2 */ + +/* BEGIN MERGE SLOT 3 */ + +size_t mbedtls_mpi_mod_raw_inv_prime_working_limbs(size_t AN_limbs) +{ + /* mbedtls_mpi_mod_raw_inv_prime() needs a temporary for the exponent, + * which will be the same size as the modulus and input (AN_limbs), + * and additional space to pass to mbedtls_mpi_core_exp_mod(). */ + return AN_limbs + + mbedtls_mpi_core_exp_mod_working_limbs(AN_limbs, AN_limbs); +} + +void mbedtls_mpi_mod_raw_inv_prime(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *N, + size_t AN_limbs, + const mbedtls_mpi_uint *RR, + mbedtls_mpi_uint *T) +{ + /* Inversion by power: g^|G| = 1 => g^(-1) = g^(|G|-1), and + * |G| = N - 1, so we want + * g^(|G|-1) = g^(N - 2) + */ + + /* Use the first AN_limbs of T to hold N - 2 */ + mbedtls_mpi_uint *Nminus2 = T; + (void) mbedtls_mpi_core_sub_int(Nminus2, N, 2, AN_limbs); + + /* Rest of T is given to exp_mod for its working space */ + mbedtls_mpi_core_exp_mod(X, + A, N, AN_limbs, Nminus2, AN_limbs, + RR, T + AN_limbs); +} + +/* END MERGE SLOT 3 */ + +/* BEGIN MERGE SLOT 4 */ + +/* END MERGE SLOT 4 */ + +/* BEGIN MERGE SLOT 5 */ +void mbedtls_mpi_mod_raw_add(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *B, + const mbedtls_mpi_mod_modulus *N) +{ + mbedtls_mpi_uint carry, borrow; + carry = mbedtls_mpi_core_add(X, A, B, N->limbs); + borrow = mbedtls_mpi_core_sub(X, X, N->p, N->limbs); + (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) (carry ^ borrow)); +} +/* END MERGE SLOT 5 */ + +/* BEGIN MERGE SLOT 6 */ + +int mbedtls_mpi_mod_raw_canonical_to_modulus_rep( + mbedtls_mpi_uint *X, + const mbedtls_mpi_mod_modulus *N) +{ + switch (N->int_rep) { + case MBEDTLS_MPI_MOD_REP_MONTGOMERY: + return mbedtls_mpi_mod_raw_to_mont_rep(X, N); + case MBEDTLS_MPI_MOD_REP_OPT_RED: + return 0; + default: + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + } +} + +int mbedtls_mpi_mod_raw_modulus_to_canonical_rep( + mbedtls_mpi_uint *X, + const mbedtls_mpi_mod_modulus *N) +{ + switch (N->int_rep) { + case MBEDTLS_MPI_MOD_REP_MONTGOMERY: + return mbedtls_mpi_mod_raw_from_mont_rep(X, N); + case MBEDTLS_MPI_MOD_REP_OPT_RED: + return 0; + default: + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + } +} + +int mbedtls_mpi_mod_raw_random(mbedtls_mpi_uint *X, + mbedtls_mpi_uint min, + const mbedtls_mpi_mod_modulus *N, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) +{ + int ret = mbedtls_mpi_core_random(X, min, N->p, N->limbs, f_rng, p_rng); + if (ret != 0) { + return ret; + } + return mbedtls_mpi_mod_raw_canonical_to_modulus_rep(X, N); +} + +/* END MERGE SLOT 6 */ + +/* BEGIN MERGE SLOT 7 */ +int mbedtls_mpi_mod_raw_to_mont_rep(mbedtls_mpi_uint *X, + const mbedtls_mpi_mod_modulus *N) +{ + mbedtls_mpi_uint *T; + const size_t t_limbs = mbedtls_mpi_core_montmul_working_limbs(N->limbs); + + if ((T = (mbedtls_mpi_uint *) mbedtls_calloc(t_limbs, ciL)) == NULL) { + return MBEDTLS_ERR_MPI_ALLOC_FAILED; + } + + mbedtls_mpi_core_to_mont_rep(X, X, N->p, N->limbs, + N->rep.mont.mm, N->rep.mont.rr, T); + + mbedtls_platform_zeroize(T, t_limbs * ciL); + mbedtls_free(T); + return 0; +} + +int mbedtls_mpi_mod_raw_from_mont_rep(mbedtls_mpi_uint *X, + const mbedtls_mpi_mod_modulus *N) +{ + const size_t t_limbs = mbedtls_mpi_core_montmul_working_limbs(N->limbs); + mbedtls_mpi_uint *T; + + if ((T = (mbedtls_mpi_uint *) mbedtls_calloc(t_limbs, ciL)) == NULL) { + return MBEDTLS_ERR_MPI_ALLOC_FAILED; + } + + mbedtls_mpi_core_from_mont_rep(X, X, N->p, N->limbs, N->rep.mont.mm, T); + + mbedtls_platform_zeroize(T, t_limbs * ciL); + mbedtls_free(T); + return 0; +} + +void mbedtls_mpi_mod_raw_neg(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_mod_modulus *N) +{ + mbedtls_mpi_core_sub(X, N->p, A, N->limbs); + + /* If A=0 initially, then X=N now. Detect this by + * subtracting N and catching the carry. */ + mbedtls_mpi_uint borrow = mbedtls_mpi_core_sub(X, X, N->p, N->limbs); + (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) borrow); +} +/* END MERGE SLOT 7 */ + +/* BEGIN MERGE SLOT 8 */ + +/* END MERGE SLOT 8 */ + +/* BEGIN MERGE SLOT 9 */ + +/* END MERGE SLOT 9 */ + +/* BEGIN MERGE SLOT 10 */ + +/* END MERGE SLOT 10 */ + +#endif /* MBEDTLS_BIGNUM_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_mod_raw.h b/optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_mod_raw.h new file mode 100644 index 0000000..a32500f --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_mod_raw.h @@ -0,0 +1,464 @@ +/** + * Low-level modular bignum functions + * + * This interface should only be used by the higher-level modular bignum + * module (bignum_mod.c) and the ECP module (ecp.c, ecp_curves.c). All other + * modules should use the high-level modular bignum interface (bignum_mod.h) + * or the legacy bignum interface (bignum.h). + * + * This is a low-level interface to operations on integers modulo which + * has no protection against passing invalid arguments such as arrays of + * the wrong size. The functions in bignum_mod.h provide a higher-level + * interface that includes protections against accidental misuse, at the + * expense of code size and sometimes more cumbersome memory management. + * + * The functions in this module obey the following conventions unless + * explicitly indicated otherwise: + * - **Modulus parameters**: the modulus is passed as a pointer to a structure + * of type #mbedtls_mpi_mod_modulus. The structure must be set up with an + * array of limbs storing the bignum value of the modulus. The modulus must + * be odd and is assumed to have no leading zeroes. The modulus is usually + * named \c N and is usually input-only. + * - **Bignum parameters**: Bignums are passed as pointers to an array of + * limbs. A limb has the type #mbedtls_mpi_uint. Unless otherwise specified: + * - Bignum parameters called \c A, \c B, ... are inputs, and are not + * modified by the function. + * - Bignum parameters called \c X, \c Y are outputs or input-output. + * The initial content of output-only parameters is ignored. + * - \c T is a temporary storage area. The initial content of such a + * parameter is ignored and the final content is unspecified. + * - **Bignum sizes**: bignum sizes are usually expressed by the \c limbs + * member of the modulus argument. All bignum parameters must have the same + * number of limbs as the modulus. All bignum sizes must be at least 1 and + * must be significantly less than #SIZE_MAX. The behavior if a size is 0 is + * undefined. + * - **Bignum representation**: the representation of inputs and outputs is + * specified by the \c int_rep field of the modulus for arithmetic + * functions. Utility functions may allow for different representation. + * - **Parameter ordering**: for bignum parameters, outputs come before inputs. + * The modulus is passed after other bignum input parameters. Temporaries + * come last. + * - **Aliasing**: in general, output bignums may be aliased to one or more + * inputs. Modulus values may not be aliased to any other parameter. Outputs + * may not be aliased to one another. Temporaries may not be aliased to any + * other parameter. + * - **Overlap**: apart from aliasing of limb array pointers (where two + * arguments are equal pointers), overlap is not supported and may result + * in undefined behavior. + * - **Error handling**: This is a low-level module. Functions generally do not + * try to protect against invalid arguments such as nonsensical sizes or + * null pointers. Note that passing bignums with a different size than the + * modulus may lead to buffer overflows. Some functions which allocate + * memory or handle reading/writing of bignums will return an error if + * memory allocation fails or if buffer sizes are invalid. + * - **Modular representatives**: all functions expect inputs to be in the + * range [0, \c N - 1] and guarantee outputs in the range [0, \c N - 1]. If + * an input is out of range, outputs are fully unspecified, though bignum + * values out of range should not cause buffer overflows (beware that this is + * not extensively tested). + */ + +/* + * 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_MOD_RAW_H +#define MBEDTLS_BIGNUM_MOD_RAW_H + +#include "common.h" + +#if defined(MBEDTLS_BIGNUM_C) +#include "mbedtls/bignum.h" +#endif + +#include "bignum_mod.h" + +/** + * \brief Perform a safe conditional copy of an MPI which doesn't reveal + * whether the assignment was done or not. + * + * The size to copy is determined by \p N. + * + * \param[out] X The address of the destination MPI. + * This must be initialized. Must have enough limbs to + * store the full value of \p A. + * \param[in] A The address of the source MPI. This must be initialized. + * \param[in] N The address of the modulus related to \p X and \p A. + * \param assign The condition deciding whether to perform the + * assignment or not. Must be either 0 or 1: + * * \c 1: Perform the assignment `X = A`. + * * \c 0: Keep the original value of \p X. + * + * \note This function avoids leaking any information about whether + * the assignment was done or not. + * + * \warning If \p assign is neither 0 nor 1, the result of this function + * is indeterminate, and the resulting value in \p X might be + * neither its original value nor the value in \p A. + */ +void mbedtls_mpi_mod_raw_cond_assign(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_mod_modulus *N, + unsigned char assign); + +/** + * \brief Perform a safe conditional swap of two MPIs which doesn't reveal + * whether the swap was done or not. + * + * The size to swap is determined by \p N. + * + * \param[in,out] X The address of the first MPI. This must be initialized. + * \param[in,out] Y The address of the second MPI. This must be initialized. + * \param[in] N The address of the modulus related to \p X and \p Y. + * \param swap The condition deciding whether to perform + * the swap or not. Must be either 0 or 1: + * * \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 avoids leaking any information about whether + * the swap was done or not. + * + * \warning If \p swap is neither 0 nor 1, the result of this function + * is indeterminate, and both \p X and \p Y might end up with + * values different to either of the original ones. + */ +void mbedtls_mpi_mod_raw_cond_swap(mbedtls_mpi_uint *X, + mbedtls_mpi_uint *Y, + const mbedtls_mpi_mod_modulus *N, + unsigned char swap); + +/** Import X from unsigned binary data. + * + * The MPI needs to have enough limbs to store the full value (including any + * most significant zero bytes in the input). + * + * \param[out] X The address of the MPI. The size is determined by \p N. + * (In particular, it must have at least as many limbs as + * the modulus \p N.) + * \param[in] N The address of the modulus related to \p X. + * \param[in] input The input buffer to import from. + * \param input_length The length in bytes of \p input. + * \param ext_rep The endianness of the number in the input buffer. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p X isn't + * large enough to hold the value in \p input. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the external representation + * of \p N is invalid or \p X is not less than \p N. + */ +int mbedtls_mpi_mod_raw_read(mbedtls_mpi_uint *X, + const mbedtls_mpi_mod_modulus *N, + const unsigned char *input, + size_t input_length, + mbedtls_mpi_mod_ext_rep ext_rep); + +/** Export A into unsigned binary data. + * + * \param[in] A The address of the MPI. The size is determined by \p N. + * (In particular, it must have at least as many limbs as + * the modulus \p N.) + * \param[in] N The address of the modulus related to \p A. + * \param[out] output The output buffer to export to. + * \param output_length The length in bytes of \p output. + * \param ext_rep The endianness in which the number should be written into the output buffer. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p output isn't + * large enough to hold the value of \p A. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the external representation + * of \p N is invalid. + */ +int mbedtls_mpi_mod_raw_write(const mbedtls_mpi_uint *A, + const mbedtls_mpi_mod_modulus *N, + unsigned char *output, + size_t output_length, + mbedtls_mpi_mod_ext_rep ext_rep); + +/* BEGIN MERGE SLOT 1 */ + +/* END MERGE SLOT 1 */ + +/* BEGIN MERGE SLOT 2 */ + +/** \brief Subtract two MPIs, returning the residue modulo the specified + * modulus. + * + * The size of the operation is determined by \p N. \p A and \p B must have + * the same number of limbs as \p N. + * + * \p X may be aliased to \p A or \p B, or even both, but may not overlap + * either otherwise. + * + * \param[out] X The address of the result MPI. + * This must be initialized. Must have enough limbs to + * store the full value of the result. + * \param[in] A The address of the first MPI. This must be initialized. + * \param[in] B The address of the second MPI. This must be initialized. + * \param[in] N The address of the modulus. Used to perform a modulo + * operation on the result of the subtraction. + */ +void mbedtls_mpi_mod_raw_sub(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *B, + const mbedtls_mpi_mod_modulus *N); + +/** \brief Multiply two MPIs, returning the residue modulo the specified + * modulus. + * + * \note Currently handles the case when `N->int_rep` is + * MBEDTLS_MPI_MOD_REP_MONTGOMERY. + * + * The size of the operation is determined by \p N. \p A, \p B and \p X must + * all be associated with the modulus \p N and must all have the same number + * of limbs as \p N. + * + * \p X may be aliased to \p A or \p B, or even both, but may not overlap + * either otherwise. They may not alias \p N (since they must be in canonical + * form, they cannot == \p N). + * + * \param[out] X The address of the result MPI. Must have the same + * number of limbs as \p N. + * On successful completion, \p X contains the result of + * the multiplication `A * B * R^-1` mod N where + * `R = 2^(biL * N->limbs)`. + * \param[in] A The address of the first MPI. + * \param[in] B The address of the second MPI. + * \param[in] N The address of the modulus. Used to perform a modulo + * operation on the result of the multiplication. + * \param[in,out] T Temporary storage of size at least 2 * N->limbs + 1 + * limbs. Its initial content is unused and + * its final content is indeterminate. + * It must not alias or otherwise overlap any of the + * other parameters. + */ +void mbedtls_mpi_mod_raw_mul(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *B, + const mbedtls_mpi_mod_modulus *N, + mbedtls_mpi_uint *T); + +/* END MERGE SLOT 2 */ + +/* BEGIN MERGE SLOT 3 */ + +/** + * \brief Returns the number of limbs of working memory required for + * a call to `mbedtls_mpi_mod_raw_inv_prime()`. + * + * \note This will always be at least + * `mbedtls_mpi_core_montmul_working_limbs(AN_limbs)`, + * i.e. sufficient for a call to `mbedtls_mpi_core_montmul()`. + * + * \param AN_limbs The number of limbs in the input `A` and the modulus `N` + * (they must be the same size) that will be given to + * `mbedtls_mpi_mod_raw_inv_prime()`. + * + * \return The number of limbs of working memory required by + * `mbedtls_mpi_mod_raw_inv_prime()`. + */ +size_t mbedtls_mpi_mod_raw_inv_prime_working_limbs(size_t AN_limbs); + +/** + * \brief Perform fixed-width modular inversion of a Montgomery-form MPI with + * respect to a modulus \p N that must be prime. + * + * \p X may be aliased to \p A, but not to \p N or \p RR. + * + * \param[out] X The modular inverse of \p A with respect to \p N. + * Will be in Montgomery form. + * \param[in] A The number to calculate the modular inverse of. + * Must be in Montgomery form. Must not be 0. + * \param[in] N The modulus, as a little-endian array of length \p AN_limbs. + * Must be prime. + * \param AN_limbs The number of limbs in \p A, \p N and \p RR. + * \param[in] RR The precomputed residue of 2^{2*biL} modulo N, as a little- + * endian array of length \p AN_limbs. + * \param[in,out] T Temporary storage of at least the number of limbs returned + * by `mbedtls_mpi_mod_raw_inv_prime_working_limbs()`. + * Its initial content is unused and its final content is + * indeterminate. + * It must not alias or otherwise overlap any of the other + * parameters. + * It is up to the caller to zeroize \p T when it is no + * longer needed, and before freeing it if it was dynamically + * allocated. + */ +void mbedtls_mpi_mod_raw_inv_prime(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *N, + size_t AN_limbs, + const mbedtls_mpi_uint *RR, + mbedtls_mpi_uint *T); + +/* END MERGE SLOT 3 */ + +/* BEGIN MERGE SLOT 4 */ + +/* END MERGE SLOT 4 */ + +/* BEGIN MERGE SLOT 5 */ +/** + * \brief Perform a known-size modular addition. + * + * Calculate `A + B modulo N`. + * + * The number of limbs in each operand, and the result, is given by the + * modulus \p N. + * + * \p X may be aliased to \p A or \p B, or even both, but may not overlap + * either otherwise. + * + * \param[out] X The result of the modular addition. + * \param[in] A Little-endian presentation of the left operand. This + * must be smaller than \p N. + * \param[in] B Little-endian presentation of the right operand. This + * must be smaller than \p N. + * \param[in] N The address of the modulus. + */ +void mbedtls_mpi_mod_raw_add(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *B, + const mbedtls_mpi_mod_modulus *N); +/* END MERGE SLOT 5 */ + +/* BEGIN MERGE SLOT 6 */ + +/** Convert an MPI from canonical representation (little-endian limb array) + * to the representation associated with the modulus. + * + * \param[in,out] X The limb array to convert. + * It must have as many limbs as \p N. + * It is converted in place. + * If this function returns an error, the content of \p X + * is unspecified. + * \param[in] N The modulus structure. + * + * \return \c 0 if successful. + * Otherwise an \c MBEDTLS_ERR_MPI_xxx error code. + */ +int mbedtls_mpi_mod_raw_canonical_to_modulus_rep( + mbedtls_mpi_uint *X, + const mbedtls_mpi_mod_modulus *N); + +/** Convert an MPI from the representation associated with the modulus + * to canonical representation (little-endian limb array). + * + * \param[in,out] X The limb array to convert. + * It must have as many limbs as \p N. + * It is converted in place. + * If this function returns an error, the content of \p X + * is unspecified. + * \param[in] N The modulus structure. + * + * \return \c 0 if successful. + * Otherwise an \c MBEDTLS_ERR_MPI_xxx error code. + */ +int mbedtls_mpi_mod_raw_modulus_to_canonical_rep( + mbedtls_mpi_uint *X, + const mbedtls_mpi_mod_modulus *N); + +/** 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, in canonical representation modulo \p N. + * It must not be aliased with \p N or otherwise overlap it. + * \param min The minimum value to return. It must be strictly smaller + * than \b N. + * \param N The modulus. + * This is the upper bound of the output range, exclusive. + * \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_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. + */ +int mbedtls_mpi_mod_raw_random(mbedtls_mpi_uint *X, + mbedtls_mpi_uint min, + const mbedtls_mpi_mod_modulus *N, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng); + +/* END MERGE SLOT 6 */ + +/* BEGIN MERGE SLOT 7 */ +/** Convert an MPI into Montgomery form. + * + * \param X The address of the MPI. + * Must have the same number of limbs as \p N. + * \param N The address of the modulus, which gives the size of + * the base `R` = 2^(biL*N->limbs). + * + * \return \c 0 if successful. + */ +int mbedtls_mpi_mod_raw_to_mont_rep(mbedtls_mpi_uint *X, + const mbedtls_mpi_mod_modulus *N); + +/** Convert an MPI back from Montgomery representation. + * + * \param X The address of the MPI. + * Must have the same number of limbs as \p N. + * \param N The address of the modulus, which gives the size of + * the base `R`= 2^(biL*N->limbs). + * + * \return \c 0 if successful. + */ +int mbedtls_mpi_mod_raw_from_mont_rep(mbedtls_mpi_uint *X, + const mbedtls_mpi_mod_modulus *N); + +/** \brief Perform fixed width modular negation. + * + * The size of the operation is determined by \p N. \p A must have + * the same number of limbs as \p N. + * + * \p X may be aliased to \p A. + * + * \param[out] X The result of the modular negation. + * This must be initialized. + * \param[in] A Little-endian presentation of the input operand. This + * must be less than or equal to \p N. + * \param[in] N The modulus to use. + */ +void mbedtls_mpi_mod_raw_neg(mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_mod_modulus *N); +/* END MERGE SLOT 7 */ + +/* BEGIN MERGE SLOT 8 */ + +/* END MERGE SLOT 8 */ + +/* BEGIN MERGE SLOT 9 */ + +/* END MERGE SLOT 9 */ + +/* BEGIN MERGE SLOT 10 */ + +/* END MERGE SLOT 10 */ + +#endif /* MBEDTLS_BIGNUM_MOD_RAW_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_mod_raw_invasive.h b/optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_mod_raw_invasive.h new file mode 100644 index 0000000..ead8394 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/bignum_mod_raw_invasive.h @@ -0,0 +1,46 @@ +/** + * \file bignum_mod_raw_invasive.h + * + * \brief Function declarations for invasive functions of Low-level + * modular bignum. + */ +/** + * 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_MOD_RAW_INVASIVE_H +#define MBEDTLS_BIGNUM_MOD_RAW_INVASIVE_H + +#include "common.h" +#include "mbedtls/bignum.h" +#include "bignum_mod.h" + +#if defined(MBEDTLS_TEST_HOOKS) + +/** Convert the result of a quasi-reduction to its canonical representative. + * + * \param[in,out] X The address of the MPI to be converted. Must have the + * same number of limbs as \p N. The input value must + * be in range 0 <= X < 2N. + * \param[in] N The address of the modulus. + */ +MBEDTLS_STATIC_TESTABLE +void mbedtls_mpi_mod_raw_fix_quasi_reduction(mbedtls_mpi_uint *X, + const mbedtls_mpi_mod_modulus *N); + +#endif /* MBEDTLS_TEST_HOOKS */ + +#endif /* MBEDTLS_BIGNUM_MOD_RAW_INVASIVE_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/bn_mul.h b/optee/optee_os/lib/libmbedtls/mbedtls/library/bn_mul.h new file mode 100644 index 0000000..ab59fbd --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/bn_mul.h @@ -0,0 +1,1072 @@ +/** + * \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 + +#include "mbedtls/build_info.h" + +#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 */ + +/* *INDENT-OFF* */ +#if defined(MBEDTLS_HAVE_ASM) + +/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ +#if defined(__GNUC__) && \ + ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 ) + +/* + * GCC < 5.0 treated the x86 ebx (which is used for the GOT) as a + * fixed reserved register when building as PIC, leading to errors + * like: bn_mul.h:46:13: error: PIC register clobbered by 'ebx' in 'asm' + * + * This is fixed by an improved register allocator in GCC 5+. From the + * release notes: + * Register allocation improvements: Reuse of the PIC hard register, + * instead of using a fixed register, was implemented on x86/x86-64 + * targets. This improves generated PIC code performance as more hard + * registers can be used. + */ +#if defined(__GNUC__) && __GNUC__ < 5 && defined(__PIC__) +#define MULADDC_CANNOT_USE_EBX +#endif + +/* + * 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__) && !defined(MULADDC_CANNOT_USE_EBX) + +#define MULADDC_X1_INIT \ + { mbedtls_mpi_uint t; \ + 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_X1_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" + +#define MULADDC_X1_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" \ + ); } + +#if defined(MBEDTLS_HAVE_SSE2) + +#define MULADDC_X8_INIT MULADDC_X1_INIT + +#define MULADDC_X8_CORE \ + "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_X8_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" \ + ); } \ + +#endif /* SSE2 */ + +#endif /* i386 */ + +#if defined(__amd64__) || defined (__x86_64__) + +#define MULADDC_X1_INIT \ + asm( \ + "xorq %%r8, %%r8\n" + +#define MULADDC_X1_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_X1_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_X1_INIT \ + asm( + +#define MULADDC_X1_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_X1_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_X1_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_X1_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_X1_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_X8_INIT MULADDC_X1_INIT + +#define MULADDC_X8_CORE \ + "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" + +#define MULADDC_X8_STOP MULADDC_X1_STOP + +#endif /* MC68000 */ + +#if defined(__powerpc64__) || defined(__ppc64__) + +#if defined(__MACH__) && defined(__APPLE__) + +#define MULADDC_X1_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_X1_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_X1_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_X1_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_X1_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_X1_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_X1_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_X1_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_X1_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_X1_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_X1_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_X1_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_X1_INIT \ + asm( \ + "ldx %3, %%o0 \n\t" \ + "ldx %4, %%o1 \n\t" \ + "ld %5, %%o2 \n\t" \ + "ld %6, %%o3 \n\t" + +#define MULADDC_X1_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_X1_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_X1_INIT \ + asm( \ + "ld %3, %%o0 \n\t" \ + "ld %4, %%o1 \n\t" \ + "ld %5, %%o2 \n\t" \ + "ld %6, %%o3 \n\t" + +#define MULADDC_X1_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_X1_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_X1_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" + +#if(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) +#define MULADDC_LHUI \ + "lhui r9, r3, 0 \n\t" \ + "addi r3, r3, 2 \n\t" \ + "lhui r8, r3, 0 \n\t" +#else +#define MULADDC_LHUI \ + "lhui r8, r3, 0 \n\t" \ + "addi r3, r3, 2 \n\t" \ + "lhui r9, r3, 0 \n\t" +#endif + +#define MULADDC_X1_CORE \ + MULADDC_LHUI \ + "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_X1_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_X1_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_X1_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_X1_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_X1_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_X1_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_X1_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_X1_INIT \ + { \ + mbedtls_mpi_uint tmp_a, tmp_b; \ + asm volatile ( + +#define MULADDC_X1_CORE \ + ".p2align 2 \n\t" \ + "ldr %[a], [%[in]], #4 \n\t" \ + "ldr %[b], [%[acc]] \n\t" \ + "umaal %[b], %[carry], %[scalar], %[a] \n\t" \ + "str %[b], [%[acc]], #4 \n\t" + +#define MULADDC_X1_STOP \ + : [a] "=&r" (tmp_a), \ + [b] "=&r" (tmp_b), \ + [in] "+r" (s), \ + [acc] "+r" (d), \ + [carry] "+l" (c) \ + : [scalar] "r" (b) \ + : "memory" \ + ); \ + } + +#define MULADDC_X2_INIT \ + { \ + mbedtls_mpi_uint tmp_a0, tmp_b0; \ + mbedtls_mpi_uint tmp_a1, tmp_b1; \ + asm volatile ( + + /* - Make sure loop is 4-byte aligned to avoid stalls + * upon repeated non-word aligned instructions in + * some microarchitectures. + * - Don't use ldm with post-increment or back-to-back + * loads with post-increment and same address register + * to avoid stalls on some microarchitectures. + * - Bunch loads and stores to reduce latency on some + * microarchitectures. E.g., on Cortex-M4, the first + * in a series of load/store operations has latency + * 2 cycles, while subsequent loads/stores are single-cycle. */ +#define MULADDC_X2_CORE \ + ".p2align 2 \n\t" \ + "ldr %[a0], [%[in]], #+8 \n\t" \ + "ldr %[b0], [%[acc]], #+8 \n\t" \ + "ldr %[a1], [%[in], #-4] \n\t" \ + "ldr %[b1], [%[acc], #-4] \n\t" \ + "umaal %[b0], %[carry], %[scalar], %[a0] \n\t" \ + "umaal %[b1], %[carry], %[scalar], %[a1] \n\t" \ + "str %[b0], [%[acc], #-8] \n\t" \ + "str %[b1], [%[acc], #-4] \n\t" + +#define MULADDC_X2_STOP \ + : [a0] "=&r" (tmp_a0), \ + [b0] "=&r" (tmp_b0), \ + [a1] "=&r" (tmp_a1), \ + [b1] "=&r" (tmp_b1), \ + [in] "+r" (s), \ + [acc] "+r" (d), \ + [carry] "+l" (c) \ + : [scalar] "r" (b) \ + : "memory" \ + ); \ + } + +#else + +#define MULADDC_X1_INIT \ + asm( \ + "ldr r0, %3 \n\t" \ + "ldr r1, %4 \n\t" \ + "ldr r2, %5 \n\t" \ + "ldr r3, %6 \n\t" + +#define MULADDC_X1_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_X1_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_X1_INIT \ + asm( \ + "ldq $1, %3 \n\t" \ + "ldq $2, %4 \n\t" \ + "ldq $3, %5 \n\t" \ + "ldq $4, %6 \n\t" + +#define MULADDC_X1_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_X1_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_X1_INIT \ + asm( \ + "lw $10, %3 \n\t" \ + "lw $11, %4 \n\t" \ + "lw $12, %5 \n\t" \ + "lw $13, %6 \n\t" + +#define MULADDC_X1_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_X1_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_X1_INIT \ + __asm mov esi, s \ + __asm mov edi, d \ + __asm mov ecx, c \ + __asm mov ebx, b + +#define MULADDC_X1_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 + +#define MULADDC_X1_STOP \ + __asm mov c, ecx \ + __asm mov d, edi \ + __asm mov s, esi + +#if defined(MBEDTLS_HAVE_SSE2) + +#define EMIT __asm _emit + +#define MULADDC_X8_INIT MULADDC_X1_INIT + +#define MULADDC_X8_CORE \ + 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_X8_STOP \ + EMIT 0x0F EMIT 0x77 \ + __asm mov c, ecx \ + __asm mov d, edi \ + __asm mov s, esi + +#endif /* SSE2 */ +#endif /* MSVC */ + +#endif /* MBEDTLS_HAVE_ASM */ + +#if !defined(MULADDC_X1_CORE) +#if defined(MBEDTLS_HAVE_UDBL) + +#define MULADDC_X1_INIT \ +{ \ + mbedtls_t_udbl r; \ + mbedtls_mpi_uint r0, r1; + +#define MULADDC_X1_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_X1_STOP \ +} + +#else /* MBEDTLS_HAVE_UDBL */ + +#define MULADDC_X1_INIT \ +{ \ + mbedtls_mpi_uint s0, s1, b0, b1; \ + mbedtls_mpi_uint r0, r1, rx, ry; \ + b0 = ( b << biH ) >> biH; \ + b1 = ( b >> biH ); + +#define MULADDC_X1_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_X1_STOP \ +} + +#endif /* C (longlong) */ +#endif /* C (generic) */ + +#if !defined(MULADDC_X2_CORE) +#define MULADDC_X2_INIT MULADDC_X1_INIT +#define MULADDC_X2_STOP MULADDC_X1_STOP +#define MULADDC_X2_CORE MULADDC_X1_CORE MULADDC_X1_CORE +#endif /* MULADDC_X2_CORE */ + +#if !defined(MULADDC_X4_CORE) +#define MULADDC_X4_INIT MULADDC_X2_INIT +#define MULADDC_X4_STOP MULADDC_X2_STOP +#define MULADDC_X4_CORE MULADDC_X2_CORE MULADDC_X2_CORE +#endif /* MULADDC_X4_CORE */ + +#if !defined(MULADDC_X8_CORE) +#define MULADDC_X8_INIT MULADDC_X4_INIT +#define MULADDC_X8_STOP MULADDC_X4_STOP +#define MULADDC_X8_CORE MULADDC_X4_CORE MULADDC_X4_CORE +#endif /* MULADDC_X8_CORE */ + +/* *INDENT-ON* */ +#endif /* bn_mul.h */ 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..409727d --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/camellia.c @@ -0,0 +1,1056 @@ +/* + * 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 + +#include "mbedtls/platform.h" + +#if !defined(MBEDTLS_CAMELLIA_ALT) + +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) +{ + 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]; + + 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; + + 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]; + if (mode != MBEDTLS_CAMELLIA_ENCRYPT && mode != MBEDTLS_CAMELLIA_DECRYPT) { + return MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA; + } + + ((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) +{ + unsigned char temp[16]; + if (mode != MBEDTLS_CAMELLIA_ENCRYPT && mode != MBEDTLS_CAMELLIA_DECRYPT) { + return MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA; + } + + 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); + + mbedtls_xor(output, output, iv, 16); + + memcpy(iv, temp, 16); + + input += 16; + output += 16; + length -= 16; + } + } else { + while (length > 0) { + mbedtls_xor(output, input, iv, 16); + + 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; + if (mode != MBEDTLS_CAMELLIA_ENCRYPT && mode != MBEDTLS_CAMELLIA_DECRYPT) { + return MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA; + } + + 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; + + 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..36c999e --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ccm.c @@ -0,0 +1,729 @@ +/* + * 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_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ +#endif /* MBEDTLS_PLATFORM_C */ + +#if !defined(MBEDTLS_CCM_ALT) + + +/* + * Initialize context + */ +void mbedtls_ccm_init(mbedtls_ccm_context *ctx) +{ + 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; + + 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)); +} + +#define CCM_STATE__CLEAR 0 +#define CCM_STATE__STARTED (1 << 0) +#define CCM_STATE__LENGTHS_SET (1 << 1) +#define CCM_STATE__AUTH_DATA_STARTED (1 << 2) +#define CCM_STATE__AUTH_DATA_FINISHED (1 << 3) +#define CCM_STATE__ERROR (1 << 4) + +/* + * Encrypt or decrypt a partial block with CTR + */ +static int mbedtls_ccm_crypt(mbedtls_ccm_context *ctx, + size_t offset, size_t use_len, + const unsigned char *input, + unsigned char *output) +{ + size_t olen = 0; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char tmp_buf[16] = { 0 }; + + if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->ctr, 16, tmp_buf, + &olen)) != 0) { + ctx->state |= CCM_STATE__ERROR; + mbedtls_platform_zeroize(tmp_buf, sizeof(tmp_buf)); + return ret; + } + + mbedtls_xor(output, input, tmp_buf + offset, use_len); + + mbedtls_platform_zeroize(tmp_buf, sizeof(tmp_buf)); + return ret; +} + +static void mbedtls_ccm_clear_state(mbedtls_ccm_context *ctx) +{ + ctx->state = CCM_STATE__CLEAR; + memset(ctx->y, 0, 16); + memset(ctx->ctr, 0, 16); +} + +static int ccm_calculate_first_block_if_ready(mbedtls_ccm_context *ctx) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char i; + size_t len_left, olen; + + /* length calculation can be done only after both + * mbedtls_ccm_starts() and mbedtls_ccm_set_lengths() have been executed + */ + if (!(ctx->state & CCM_STATE__STARTED) || !(ctx->state & CCM_STATE__LENGTHS_SET)) { + return 0; + } + + /* CCM expects non-empty tag. + * CCM* allows empty tag. For CCM* without tag, ignore plaintext length. + */ + if (ctx->tag_len == 0) { + if (ctx->mode == MBEDTLS_CCM_STAR_ENCRYPT || ctx->mode == MBEDTLS_CCM_STAR_DECRYPT) { + ctx->plaintext_len = 0; + } else { + return MBEDTLS_ERR_CCM_BAD_INPUT; + } + } + + /* + * First block: + * 0 .. 0 flags + * 1 .. iv_len nonce (aka iv) - set by: mbedtls_ccm_starts() + * iv_len+1 .. 15 length + * + * With flags as (bits): + * 7 0 + * 6 add present? + * 5 .. 3 (t - 2) / 2 + * 2 .. 0 q - 1 + */ + ctx->y[0] |= (ctx->add_len > 0) << 6; + ctx->y[0] |= ((ctx->tag_len - 2) / 2) << 3; + ctx->y[0] |= ctx->q - 1; + + for (i = 0, len_left = ctx->plaintext_len; i < ctx->q; i++, len_left >>= 8) { + ctx->y[15-i] = MBEDTLS_BYTE_0(len_left); + } + + if (len_left > 0) { + ctx->state |= CCM_STATE__ERROR; + return MBEDTLS_ERR_CCM_BAD_INPUT; + } + + /* Start CBC-MAC with first block*/ + if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen)) != 0) { + ctx->state |= CCM_STATE__ERROR; + return ret; + } + + return 0; +} + +int mbedtls_ccm_starts(mbedtls_ccm_context *ctx, + int mode, + const unsigned char *iv, + size_t iv_len) +{ + /* Also implies q is within bounds */ + if (iv_len < 7 || iv_len > 13) { + return MBEDTLS_ERR_CCM_BAD_INPUT; + } + + ctx->mode = mode; + ctx->q = 16 - 1 - (unsigned char) iv_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 + */ + memset(ctx->ctr, 0, 16); + ctx->ctr[0] = ctx->q - 1; + memcpy(ctx->ctr + 1, iv, iv_len); + memset(ctx->ctr + 1 + iv_len, 0, ctx->q); + ctx->ctr[15] = 1; + + /* + * See ccm_calculate_first_block_if_ready() for block layout description + */ + memcpy(ctx->y + 1, iv, iv_len); + + ctx->state |= CCM_STATE__STARTED; + return ccm_calculate_first_block_if_ready(ctx); +} + +int mbedtls_ccm_set_lengths(mbedtls_ccm_context *ctx, + size_t total_ad_len, + size_t plaintext_len, + size_t tag_len) +{ + /* + * 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; + } + + if (total_ad_len >= 0xFF00) { + return MBEDTLS_ERR_CCM_BAD_INPUT; + } + + ctx->plaintext_len = plaintext_len; + ctx->add_len = total_ad_len; + ctx->tag_len = tag_len; + ctx->processed = 0; + + ctx->state |= CCM_STATE__LENGTHS_SET; + return ccm_calculate_first_block_if_ready(ctx); +} + +int mbedtls_ccm_update_ad(mbedtls_ccm_context *ctx, + const unsigned char *add, + size_t add_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t olen, use_len, offset; + + if (ctx->state & CCM_STATE__ERROR) { + return MBEDTLS_ERR_CCM_BAD_INPUT; + } + + if (add_len > 0) { + if (ctx->state & CCM_STATE__AUTH_DATA_FINISHED) { + return MBEDTLS_ERR_CCM_BAD_INPUT; + } + + if (!(ctx->state & CCM_STATE__AUTH_DATA_STARTED)) { + if (add_len > ctx->add_len) { + return MBEDTLS_ERR_CCM_BAD_INPUT; + } + + ctx->y[0] ^= (unsigned char) ((ctx->add_len >> 8) & 0xFF); + ctx->y[1] ^= (unsigned char) ((ctx->add_len) & 0xFF); + + ctx->state |= CCM_STATE__AUTH_DATA_STARTED; + } else if (ctx->processed + add_len > ctx->add_len) { + return MBEDTLS_ERR_CCM_BAD_INPUT; + } + + while (add_len > 0) { + offset = (ctx->processed + 2) % 16; /* account for y[0] and y[1] + * holding total auth data length */ + use_len = 16 - offset; + + if (use_len > add_len) { + use_len = add_len; + } + + mbedtls_xor(ctx->y + offset, ctx->y + offset, add, use_len); + + ctx->processed += use_len; + add_len -= use_len; + add += use_len; + + if (use_len + offset == 16 || ctx->processed == ctx->add_len) { + if ((ret = + mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen)) != 0) { + ctx->state |= CCM_STATE__ERROR; + return ret; + } + } + } + + if (ctx->processed == ctx->add_len) { + ctx->state |= CCM_STATE__AUTH_DATA_FINISHED; + ctx->processed = 0; // prepare for mbedtls_ccm_update() + } + } + + return 0; +} + +int mbedtls_ccm_update(mbedtls_ccm_context *ctx, + const unsigned char *input, size_t input_len, + unsigned char *output, size_t output_size, + size_t *output_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char i; + size_t use_len, offset, olen; + + unsigned char local_output[16]; + + if (ctx->state & CCM_STATE__ERROR) { + return MBEDTLS_ERR_CCM_BAD_INPUT; + } + + /* Check against plaintext length only if performing operation with + * authentication + */ + if (ctx->tag_len != 0 && ctx->processed + input_len > ctx->plaintext_len) { + return MBEDTLS_ERR_CCM_BAD_INPUT; + } + + if (output_size < input_len) { + return MBEDTLS_ERR_CCM_BAD_INPUT; + } + *output_len = input_len; + + ret = 0; + + while (input_len > 0) { + offset = ctx->processed % 16; + + use_len = 16 - offset; + + if (use_len > input_len) { + use_len = input_len; + } + + ctx->processed += use_len; + + if (ctx->mode == MBEDTLS_CCM_ENCRYPT || \ + ctx->mode == MBEDTLS_CCM_STAR_ENCRYPT) { + mbedtls_xor(ctx->y + offset, ctx->y + offset, input, use_len); + + if (use_len + offset == 16 || ctx->processed == ctx->plaintext_len) { + if ((ret = + mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen)) != 0) { + ctx->state |= CCM_STATE__ERROR; + goto exit; + } + } + + ret = mbedtls_ccm_crypt(ctx, offset, use_len, input, output); + if (ret != 0) { + goto exit; + } + } + + if (ctx->mode == MBEDTLS_CCM_DECRYPT || \ + ctx->mode == MBEDTLS_CCM_STAR_DECRYPT) { + /* Since output may be in shared memory, we cannot be sure that + * it will contain what we wrote to it. Therefore, we should avoid using + * it as input to any operations. + * Write decrypted data to local_output to avoid using output variable as + * input in the XOR operation for Y. + */ + ret = mbedtls_ccm_crypt(ctx, offset, use_len, input, local_output); + if (ret != 0) { + goto exit; + } + + mbedtls_xor(ctx->y + offset, ctx->y + offset, local_output, use_len); + + memcpy(output, local_output, use_len); + mbedtls_platform_zeroize(local_output, 16); + + if (use_len + offset == 16 || ctx->processed == ctx->plaintext_len) { + if ((ret = + mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen)) != 0) { + ctx->state |= CCM_STATE__ERROR; + goto exit; + } + } + } + + if (use_len + offset == 16 || ctx->processed == ctx->plaintext_len) { + for (i = 0; i < ctx->q; i++) { + if (++(ctx->ctr)[15-i] != 0) { + break; + } + } + } + + input_len -= use_len; + input += use_len; + output += use_len; + } + +exit: + mbedtls_platform_zeroize(local_output, 16); + + return ret; +} + +int mbedtls_ccm_finish(mbedtls_ccm_context *ctx, + unsigned char *tag, size_t tag_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char i; + + if (ctx->state & CCM_STATE__ERROR) { + return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + } + + if (ctx->add_len > 0 && !(ctx->state & CCM_STATE__AUTH_DATA_FINISHED)) { + return MBEDTLS_ERR_CCM_BAD_INPUT; + } + + if (ctx->plaintext_len > 0 && ctx->processed != ctx->plaintext_len) { + return MBEDTLS_ERR_CCM_BAD_INPUT; + } + + /* + * Authentication: reset counter and crypt/mask internal tag + */ + for (i = 0; i < ctx->q; i++) { + ctx->ctr[15-i] = 0; + } + + ret = mbedtls_ccm_crypt(ctx, 0, 16, ctx->y, ctx->y); + if (ret != 0) { + return ret; + } + if (tag != NULL) { + memcpy(tag, ctx->y, tag_len); + } + mbedtls_ccm_clear_state(ctx); + + return 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; + size_t olen; + + if ((ret = mbedtls_ccm_starts(ctx, mode, iv, iv_len)) != 0) { + return ret; + } + + if ((ret = mbedtls_ccm_set_lengths(ctx, add_len, length, tag_len)) != 0) { + return ret; + } + + if ((ret = mbedtls_ccm_update_ad(ctx, add, add_len)) != 0) { + return ret; + } + + if ((ret = mbedtls_ccm_update(ctx, input, length, + output, length, &olen)) != 0) { + return ret; + } + + if ((ret = mbedtls_ccm_finish(ctx, tag, tag_len)) != 0) { + return ret; + } + + 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) +{ + return ccm_auth_crypt(ctx, MBEDTLS_CCM_STAR_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) +{ + return ccm_auth_crypt(ctx, MBEDTLS_CCM_ENCRYPT, length, iv, iv_len, + add, add_len, input, output, tag, tag_len); +} + +/* + * Authenticated decryption + */ +static int mbedtls_ccm_compare_tags(const unsigned char *tag1, + const unsigned char *tag2, + size_t tag_len) +{ + unsigned char i; + int diff; + + /* Check tag in "constant-time" */ + for (diff = 0, i = 0; i < tag_len; i++) { + diff |= tag1[i] ^ tag2[i]; + } + + if (diff != 0) { + return MBEDTLS_ERR_CCM_AUTH_FAILED; + } + + return 0; +} + +static int ccm_auth_decrypt(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, + const unsigned char *tag, size_t tag_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char check_tag[16]; + + if ((ret = ccm_auth_crypt(ctx, mode, length, + iv, iv_len, add, add_len, + input, output, check_tag, tag_len)) != 0) { + return ret; + } + + if ((ret = mbedtls_ccm_compare_tags(tag, check_tag, tag_len)) != 0) { + mbedtls_platform_zeroize(output, length); + return ret; + } + + return 0; +} + +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) +{ + return ccm_auth_decrypt(ctx, MBEDTLS_CCM_STAR_DECRYPT, length, + iv, iv_len, add, add_len, + input, output, tag, tag_len); +} + +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) +{ + return ccm_auth_decrypt(ctx, MBEDTLS_CCM_DECRYPT, 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/chacha20.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/chacha20.c new file mode 100644 index 0000000..cbb01f4 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/chacha20.c @@ -0,0 +1,509 @@ +/** + * \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 + +#include "mbedtls/platform.h" + +#if !defined(MBEDTLS_CHACHA20_ALT) + +#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) +{ + 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 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) +{ + /* 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; + + /* 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]++; + + mbedtls_xor(output + offset, input + offset, ctx->keystream8, 64U); + + 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]++; + + mbedtls_xor(output + offset, input + offset, ctx->keystream8, size); + + 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; + + 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..0124d75 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/chachapoly.c @@ -0,0 +1,492 @@ +/** + * \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 + +#include "mbedtls/platform.h" + +#if !defined(MBEDTLS_CHACHAPOLY_ALT) + +#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) +{ + 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; + + 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]; + + /* 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) +{ + 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; + + 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]; + + 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]) +{ + 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; + + 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..58175e3 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/check_crypto_config.h @@ -0,0 +1,101 @@ +/** + * \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 + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_USE_PSA_CRYPTO) && \ + !(defined(PSA_WANT_ALG_SHA_1) || defined(PSA_WANT_ALG_SHA_256) || defined(PSA_WANT_ALG_SHA_512)) +#error "MBEDTLS_SSL_PROTO_TLS1_2 defined, but not all prerequisites" +#endif + +#if defined(PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS) && \ + !defined(PSA_WANT_ALG_SHA_256) +#error "PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS 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..2f57f95 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/cipher.c @@ -0,0 +1,1622 @@ +/** + * \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 "cipher_wrap.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 + +#include "mbedtls/platform.h" + +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) +{ + 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) +{ + 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) +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +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_DEPRECATED_REMOVED */ +#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) +{ + if (operation != MBEDTLS_ENCRYPT && operation != MBEDTLS_DECRYPT) { + return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; + } + 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_PLATFORM_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; + + 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 defined(MBEDTLS_GCM_C) + if (MBEDTLS_MODE_GCM == ctx->cipher_info->mode) { + return mbedtls_gcm_starts((mbedtls_gcm_context *) ctx->cipher_ctx, + ctx->operation, + iv, iv_len); + } +#endif + +#if defined(MBEDTLS_CCM_C) + if (MBEDTLS_MODE_CCM_STAR_NO_TAG == ctx->cipher_info->mode) { + int set_lengths_result; + int ccm_star_mode; + + set_lengths_result = mbedtls_ccm_set_lengths( + (mbedtls_ccm_context *) ctx->cipher_ctx, + 0, 0, 0); + if (set_lengths_result != 0) { + return set_lengths_result; + } + + if (ctx->operation == MBEDTLS_DECRYPT) { + ccm_star_mode = MBEDTLS_CCM_STAR_DECRYPT; + } else if (ctx->operation == MBEDTLS_ENCRYPT) { + ccm_star_mode = MBEDTLS_CCM_STAR_ENCRYPT; + } else { + return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; + } + + return mbedtls_ccm_starts((mbedtls_ccm_context *) ctx->cipher_ctx, + ccm_star_mode, + iv, iv_len); + } +#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) +{ + 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) +{ + 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_update_ad((mbedtls_gcm_context *) ctx->cipher_ctx, + 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 MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; +} +#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; + + 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) { + return mbedtls_gcm_update((mbedtls_gcm_context *) ctx->cipher_ctx, + input, ilen, + output, ilen, olen); + } +#endif + +#if defined(MBEDTLS_CCM_C) + if (ctx->cipher_info->mode == MBEDTLS_MODE_CCM_STAR_NO_TAG) { + return mbedtls_ccm_update((mbedtls_ccm_context *) ctx->cipher_ctx, + input, ilen, + output, ilen, olen); + } +#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) +{ + 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_CCM_STAR_NO_TAG == 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) +{ + 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) +{ + 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) { + size_t output_length; + /* The code here doesn't yet support alternative implementations + * that can delay up to a block of output. */ + return mbedtls_gcm_finish((mbedtls_gcm_context *) ctx->cipher_ctx, + NULL, 0, &output_length, + 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 MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; +} + +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; + + 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. */ + ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; + +#if defined(MBEDTLS_GCM_C) + if (MBEDTLS_MODE_GCM == ctx->cipher_info->mode) { + size_t output_length; + /* The code here doesn't yet support alternative implementations + * that can delay up to a block of output. */ + + 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, + NULL, 0, &output_length, + 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; + +#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_PLATFORM_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_PLATFORM_HW_ACCEL_FAILED; + } + } + + status = psa_cipher_update(&cipher_op, + input, ilen, + output, ilen, olen); + if (status != PSA_SUCCESS) { + return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + } + + status = psa_cipher_finish(&cipher_op, + output + *olen, ilen - *olen, + &part_len); + if (status != PSA_SUCCESS) { + return MBEDTLS_ERR_PLATFORM_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 used by + * 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_PLATFORM_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 used by + * 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_PLATFORM_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; +} +#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) +{ +#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) +{ +#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..fb36314 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/cipher_wrap.c @@ -0,0 +1,2346 @@ +/** + * \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 "cipher_wrap.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_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_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 + +#include "mbedtls/platform.h" + +#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 +}; + +static const mbedtls_cipher_info_t aes_128_ccm_star_no_tag_info = { + MBEDTLS_CIPHER_AES_128_CCM_STAR_NO_TAG, + MBEDTLS_MODE_CCM_STAR_NO_TAG, + 128, + "AES-128-CCM*-NO-TAG", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aes_info +}; + +static const mbedtls_cipher_info_t aes_192_ccm_star_no_tag_info = { + MBEDTLS_CIPHER_AES_192_CCM_STAR_NO_TAG, + MBEDTLS_MODE_CCM_STAR_NO_TAG, + 192, + "AES-192-CCM*-NO-TAG", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aes_info +}; + +static const mbedtls_cipher_info_t aes_256_ccm_star_no_tag_info = { + MBEDTLS_CIPHER_AES_256_CCM_STAR_NO_TAG, + MBEDTLS_MODE_CCM_STAR_NO_TAG, + 256, + "AES-256-CCM*-NO-TAG", + 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 +}; + +static const mbedtls_cipher_info_t camellia_128_ccm_star_no_tag_info = { + MBEDTLS_CIPHER_CAMELLIA_128_CCM_STAR_NO_TAG, + MBEDTLS_MODE_CCM_STAR_NO_TAG, + 128, + "CAMELLIA-128-CCM*-NO-TAG", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_ccm_star_no_tag_info = { + MBEDTLS_CIPHER_CAMELLIA_192_CCM_STAR_NO_TAG, + MBEDTLS_MODE_CCM_STAR_NO_TAG, + 192, + "CAMELLIA-192-CCM*-NO-TAG", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_ccm_star_no_tag_info = { + MBEDTLS_CIPHER_CAMELLIA_256_CCM_STAR_NO_TAG, + MBEDTLS_MODE_CCM_STAR_NO_TAG, + 256, + "CAMELLIA-256-CCM*-NO-TAG", + 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 +}; + +static const mbedtls_cipher_info_t aria_128_ccm_star_no_tag_info = { + MBEDTLS_CIPHER_ARIA_128_CCM_STAR_NO_TAG, + MBEDTLS_MODE_CCM_STAR_NO_TAG, + 128, + "ARIA-128-CCM*-NO-TAG", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aria_info +}; + +static const mbedtls_cipher_info_t aria_192_ccm_star_no_tag_info = { + MBEDTLS_CIPHER_ARIA_192_CCM_STAR_NO_TAG, + MBEDTLS_MODE_CCM_STAR_NO_TAG, + 192, + "ARIA-192-CCM*-NO-TAG", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aria_info +}; + +static const mbedtls_cipher_info_t aria_256_ccm_star_no_tag_info = { + MBEDTLS_CIPHER_ARIA_256_CCM_STAR_NO_TAG, + MBEDTLS_MODE_CCM_STAR_NO_TAG, + 256, + "ARIA-256-CCM*-NO-TAG", + 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_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 }, + { MBEDTLS_CIPHER_AES_128_CCM_STAR_NO_TAG, &aes_128_ccm_star_no_tag_info }, + { MBEDTLS_CIPHER_AES_192_CCM_STAR_NO_TAG, &aes_192_ccm_star_no_tag_info }, + { MBEDTLS_CIPHER_AES_256_CCM_STAR_NO_TAG, &aes_256_ccm_star_no_tag_info }, +#endif +#endif /* MBEDTLS_AES_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 }, + { MBEDTLS_CIPHER_CAMELLIA_128_CCM_STAR_NO_TAG, &camellia_128_ccm_star_no_tag_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_CCM_STAR_NO_TAG, &camellia_192_ccm_star_no_tag_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_CCM_STAR_NO_TAG, &camellia_256_ccm_star_no_tag_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 }, + { MBEDTLS_CIPHER_ARIA_128_CCM_STAR_NO_TAG, &aria_128_ccm_star_no_tag_info }, + { MBEDTLS_CIPHER_ARIA_192_CCM_STAR_NO_TAG, &aria_192_ccm_star_no_tag_info }, + { MBEDTLS_CIPHER_ARIA_256_CCM_STAR_NO_TAG, &aria_256_ccm_star_no_tag_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/cipher_wrap.h b/optee/optee_os/lib/libmbedtls/mbedtls/library/cipher_wrap.h new file mode 100644 index 0000000..49f5ff1 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/cipher_wrap.h @@ -0,0 +1,145 @@ +/** + * \file cipher_wrap.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 + +#include "mbedtls/build_info.h" + +#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; + mbedtls_svc_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/library/cmac.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/cmac.c new file mode 100644 index 0000000..17c7e49 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/cmac.c @@ -0,0 +1,1079 @@ +/** + * \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) + +/* + * 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); + + mbedtls_xor(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++) { + mbedtls_xor(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); + mbedtls_xor(M_last, M_last, K2, block_size); + } else { + /* Last block is complete block */ + mbedtls_xor(M_last, last_block, K1, block_size); + } + + + mbedtls_xor(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..eb159a7 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/common.h @@ -0,0 +1,167 @@ +/** + * \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 + +#include "mbedtls/build_info.h" +#include "alignment.h" + +#include +#include +#include +#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 + +#if defined(MBEDTLS_TEST_HOOKS) +extern void (*mbedtls_test_hook_test_fail)(const char *test, int line, const char *file); +#define MBEDTLS_TEST_HOOK_TEST_ASSERT(TEST) \ + do { \ + if ((!(TEST)) && ((*mbedtls_test_hook_test_fail) != NULL)) \ + { \ + (*mbedtls_test_hook_test_fail)( #TEST, __LINE__, __FILE__); \ + } \ + } while (0) +#else +#define MBEDTLS_TEST_HOOK_TEST_ASSERT(TEST) +#endif /* defined(MBEDTLS_TEST_HOOKS) */ + +/** Allow library to access its structs' private members. + * + * Although structs defined in header files are publicly available, + * their members are private and should not be accessed by the user. + */ +#define MBEDTLS_ALLOW_PRIVATE_ACCESS + +/** Return an offset into a buffer. + * + * This is just the addition of an offset to a pointer, except that this + * function also accepts an offset of 0 into a buffer whose pointer is null. + * (`p + n` has undefined behavior when `p` is null, even when `n == 0`. + * A null pointer is a valid buffer pointer when the size is 0, for example + * as the result of `malloc(0)` on some platforms.) + * + * \param p Pointer to a buffer of at least n bytes. + * This may be \p NULL if \p n is zero. + * \param n An offset in bytes. + * \return Pointer to offset \p n in the buffer \p p. + * Note that this is only a valid pointer if the size of the + * buffer is at least \p n + 1. + */ +static inline unsigned char *mbedtls_buffer_offset( + unsigned char *p, size_t n) +{ + return p == NULL ? NULL : p + n; +} + +/** Return an offset into a read-only buffer. + * + * Similar to mbedtls_buffer_offset(), but for const pointers. + * + * \param p Pointer to a buffer of at least n bytes. + * This may be \p NULL if \p n is zero. + * \param n An offset in bytes. + * \return Pointer to offset \p n in the buffer \p p. + * Note that this is only a valid pointer if the size of the + * buffer is at least \p n + 1. + */ +static inline const unsigned char *mbedtls_buffer_offset_const( + const unsigned char *p, size_t n) +{ + return p == NULL ? NULL : p + n; +} + +/** + * Perform a fast block XOR operation, such that + * r[i] = a[i] ^ b[i] where 0 <= i < n + * + * \param r Pointer to result (buffer of at least \p n bytes). \p r + * may be equal to either \p a or \p b, but behaviour when + * it overlaps in other ways is undefined. + * \param a Pointer to input (buffer of at least \p n bytes) + * \param b Pointer to input (buffer of at least \p n bytes) + * \param n Number of bytes to process. + */ +inline void mbedtls_xor(unsigned char *r, const unsigned char *a, const unsigned char *b, size_t n) +{ + size_t i = 0; +#if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS) + for (; (i + 4) <= n; i += 4) { + uint32_t x = mbedtls_get_unaligned_uint32(a + i) ^ mbedtls_get_unaligned_uint32(b + i); + mbedtls_put_unaligned_uint32(r + i, x); + } +#endif + for (; i < n; i++) { + r[i] = a[i] ^ b[i]; + } +} + +/* Fix MSVC C99 compatible issue + * MSVC support __func__ from visual studio 2015( 1900 ) + * Use MSVC predefine macro to avoid name check fail. + */ +#if (defined(_MSC_VER) && (_MSC_VER <= 1900)) +#define /*no-check-names*/ __func__ __FUNCTION__ +#endif + +/* Define `asm` for compilers which don't define it. */ +/* *INDENT-OFF* */ +#ifndef asm +#define asm __asm__ +#endif +/* *INDENT-ON* */ + +/* Always provide a static assert macro, so it can be used unconditionally. + * It will expand to nothing on some systems. + * Can be used outside functions (but don't add a trailing ';' in that case: + * the semicolon is included here to avoid triggering -Wextra-semi when + * MBEDTLS_STATIC_ASSERT() expands to nothing). + * Can't use the C11-style `defined(static_assert)` on FreeBSD, since it + * defines static_assert even with -std=c99, but then complains about it. + */ +#if defined(static_assert) && !defined(__FreeBSD__) +#define MBEDTLS_STATIC_ASSERT(expr, msg) static_assert(expr, msg); +#else +#define MBEDTLS_STATIC_ASSERT(expr, msg) +#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..552a918 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/constant_time.c @@ -0,0 +1,1042 @@ +/** + * 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" +#include "bignum_core.h" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) +#include "ssl_misc.h" +#endif + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif + +#if defined(MBEDTLS_BASE64_C) +#include "constant_time_invasive.h" +#endif + +#include +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \ + psa_to_ssl_errors, \ + psa_generic_status_to_mbedtls) +#endif + +/* + * Define MBEDTLS_EFFICIENT_UNALIGNED_VOLATILE_ACCESS where assembly is present to + * perform fast unaligned access to volatile data. + * + * This is needed because mbedtls_get_unaligned_uintXX etc don't support volatile + * memory accesses. + * + * Some of these definitions could be moved into alignment.h but for now they are + * only used here. + */ +#if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS) && defined(MBEDTLS_HAVE_ASM) +#if defined(__arm__) || defined(__thumb__) || defined(__thumb2__) || defined(__aarch64__) +#define MBEDTLS_EFFICIENT_UNALIGNED_VOLATILE_ACCESS +#endif +#endif + +#if defined(MBEDTLS_EFFICIENT_UNALIGNED_VOLATILE_ACCESS) +static inline uint32_t mbedtls_get_unaligned_volatile_uint32(volatile const unsigned char *p) +{ + /* This is UB, even where it's safe: + * return *((volatile uint32_t*)p); + * so instead the same thing is expressed in assembly below. + */ + uint32_t r; +#if defined(__arm__) || defined(__thumb__) || defined(__thumb2__) + asm volatile ("ldr %0, [%1]" : "=r" (r) : "r" (p) :); +#elif defined(__aarch64__) + asm volatile ("ldr %w0, [%1]" : "=r" (r) : "r" (p) :); +#endif + return r; +} +#endif /* MBEDTLS_EFFICIENT_UNALIGNED_VOLATILE_ACCESS */ + +int mbedtls_ct_memcmp(const void *a, + const void *b, + size_t n) +{ + size_t i = 0; + /* + * `A` and `B` are cast to volatile to ensure that the compiler + * generates code that always fully reads both buffers. + * Otherwise it could generate a test to exit early if `diff` has all + * bits set early in the loop. + */ + volatile const unsigned char *A = (volatile const unsigned char *) a; + volatile const unsigned char *B = (volatile const unsigned char *) b; + uint32_t diff = 0; + +#if defined(MBEDTLS_EFFICIENT_UNALIGNED_VOLATILE_ACCESS) + for (; (i + 4) <= n; i += 4) { + uint32_t x = mbedtls_get_unaligned_volatile_uint32(A + i); + uint32_t y = mbedtls_get_unaligned_volatile_uint32(B + i); + diff |= x ^ y; + } +#endif + + for (; 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_MAC) + +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_MAC */ + +#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; must be either 0 or 1. + * \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_MAC) + +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); + + /* dest[i] = c1 == c2 ? src[i] : dest[i] */ + size_t i = 0; +#if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS) + const uint32_t mask32 = (uint32_t) mbedtls_ct_size_mask(equal); + const unsigned char mask = (unsigned char) mask32 & 0xff; + + for (; (i + 4) <= len; i += 4) { + uint32_t a = mbedtls_get_unaligned_uint32(src + i) & mask32; + uint32_t b = mbedtls_get_unaligned_uint32(dest + i) & ~mask32; + mbedtls_put_unaligned_uint32(dest + i, a | b); + } +#else + const unsigned char mask = (unsigned char) mbedtls_ct_size_mask(equal); +#endif /* MBEDTLS_EFFICIENT_UNALIGNED_ACCESS */ + for (; 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); + } +} + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + +#if defined(PSA_WANT_ALG_SHA_384) +#define MAX_HASH_BLOCK_LENGTH PSA_HASH_BLOCK_LENGTH(PSA_ALG_SHA_384) +#elif defined(PSA_WANT_ALG_SHA_256) +#define MAX_HASH_BLOCK_LENGTH PSA_HASH_BLOCK_LENGTH(PSA_ALG_SHA_256) +#else /* See check_config.h */ +#define MAX_HASH_BLOCK_LENGTH PSA_HASH_BLOCK_LENGTH(PSA_ALG_SHA_1) +#endif + +int mbedtls_ct_hmac(mbedtls_svc_key_id_t key, + psa_algorithm_t mac_alg, + 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 psa_hash_clone() + * extension 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). + * + * We'll first compute ikey/okey, then 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. + */ + psa_algorithm_t hash_alg = PSA_ALG_HMAC_GET_HASH(mac_alg); + const size_t block_size = PSA_HASH_BLOCK_LENGTH(hash_alg); + unsigned char key_buf[MAX_HASH_BLOCK_LENGTH]; + const size_t hash_size = PSA_HASH_LENGTH(hash_alg); + psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; + size_t hash_length; + + unsigned char aux_out[PSA_HASH_MAX_SIZE]; + psa_hash_operation_t aux_operation = PSA_HASH_OPERATION_INIT; + size_t offset; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + size_t mac_key_length; + size_t i; + +#define PSA_CHK(func_call) \ + do { \ + status = (func_call); \ + if (status != PSA_SUCCESS) \ + goto cleanup; \ + } while (0) + + /* Export MAC key + * We assume key length is always exactly the output size + * which is never more than the block size, thus we use block_size + * as the key buffer size. + */ + PSA_CHK(psa_export_key(key, key_buf, block_size, &mac_key_length)); + + /* Calculate ikey */ + for (i = 0; i < mac_key_length; i++) { + key_buf[i] = (unsigned char) (key_buf[i] ^ 0x36); + } + for (; i < block_size; ++i) { + key_buf[i] = 0x36; + } + + PSA_CHK(psa_hash_setup(&operation, hash_alg)); + + /* Now compute inner_hash = HASH(ikey + msg) */ + PSA_CHK(psa_hash_update(&operation, key_buf, block_size)); + PSA_CHK(psa_hash_update(&operation, add_data, add_data_len)); + PSA_CHK(psa_hash_update(&operation, 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++) { + PSA_CHK(psa_hash_clone(&operation, &aux_operation)); + PSA_CHK(psa_hash_finish(&aux_operation, aux_out, + PSA_HASH_MAX_SIZE, &hash_length)); + /* 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) { + PSA_CHK(psa_hash_update(&operation, data + offset, 1)); + } + } + + /* Abort current operation to prepare for final operation */ + PSA_CHK(psa_hash_abort(&operation)); + + /* Calculate okey */ + for (i = 0; i < mac_key_length; i++) { + key_buf[i] = (unsigned char) ((key_buf[i] ^ 0x36) ^ 0x5C); + } + for (; i < block_size; ++i) { + key_buf[i] = 0x5C; + } + + /* Now compute HASH(okey + inner_hash) */ + PSA_CHK(psa_hash_setup(&operation, hash_alg)); + PSA_CHK(psa_hash_update(&operation, key_buf, block_size)); + PSA_CHK(psa_hash_update(&operation, output, hash_size)); + PSA_CHK(psa_hash_finish(&operation, output, hash_size, &hash_length)); + +#undef PSA_CHK + +cleanup: + mbedtls_platform_zeroize(key_buf, MAX_HASH_BLOCK_LENGTH); + mbedtls_platform_zeroize(aux_out, PSA_HASH_MAX_SIZE); + + psa_hash_abort(&operation); + psa_hash_abort(&aux_operation); + return PSA_TO_MBEDTLS_ERR(status); +} + +#undef MAX_HASH_BLOCK_LENGTH + +#else +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.2 only supports 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_USE_PSA_CRYPTO */ + +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ + +#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; + MPI_VALIDATE_RET(X != NULL); + MPI_VALIDATE_RET(Y != NULL); + + /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */ + mbedtls_mpi_uint 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_mpi_core_cond_assign(X->p, Y->p, Y->n, assign); + + for (size_t 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 = 0; + int s; + MPI_VALIDATE_RET(X != NULL); + MPI_VALIDATE_RET(Y != NULL); + + if (X == Y) { + return 0; + } + + 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); + + mbedtls_mpi_core_cond_swap(X->p, Y->p, X->n, swap); + +cleanup: + return ret; +} + +/* + * Compare unsigned values in constant time + */ +unsigned mbedtls_mpi_core_lt_ct(const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *B, + size_t limbs) +{ + unsigned ret, cond, done; + + /* The value of any of these variables is either 0 or 1 for the rest of + * their scope. */ + ret = cond = done = 0; + + for (size_t i = limbs; i > 0; i--) { + /* + * If B[i - 1] < A[i - 1] then A < B is false and the result must + * remain 0. + * + * 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(B[i - 1], A[i - 1]); + done |= cond; + + /* + * If A[i - 1] < B[i - 1] then A < B is true. + * + * 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(A[i - 1], B[i - 1]); + ret |= cond & (1 - done); + done |= cond; + } + + /* + * If all the limbs were equal, then the numbers are equal, A < B is false + * and leaving the result 0 is correct. + */ + + 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(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]; + + + /* 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; + } + + + /* 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..c4a32c7 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/constant_time_internal.h @@ -0,0 +1,363 @@ +/** + * 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 "ssl_misc.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_MAC) + +/** 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_MAC */ + +#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); + +/** + * \brief Check if one unsigned MPI is less than another in constant + * time. + * + * \param A The left-hand MPI. This must point to an array of limbs + * with the same allocated length as \p B. + * \param B The right-hand MPI. This must point to an array of limbs + * with the same allocated length as \p A. + * \param limbs The number of limbs in \p A and \p B. + * This must not be 0. + * + * \return The result of the comparison: + * \c 1 if \p A is less than \p B. + * \c 0 if \p A is greater than or equal to \p B. + */ +unsigned mbedtls_mpi_core_lt_ct(const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *B, + size_t limbs); +#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_MAC) + +/** 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. + */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) +int mbedtls_ct_hmac(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + 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); +#else +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_USE_PSA_CRYPTO */ + +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ + +#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 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(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..c176b28 --- /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..acc4208 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ctr_drbg.c @@ -0,0 +1,893 @@ +/* + * 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 + +#include "mbedtls/platform.h" + +/* + * CTR_DRBG context initialization + */ +void mbedtls_ctr_drbg_init(mbedtls_ctr_drbg_context *ctx) +{ + memset(ctx, 0, sizeof(mbedtls_ctr_drbg_context)); + mbedtls_aes_init(&ctx->aes_ctx); + /* 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; + } + + /* 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; + } + + /* 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) { + mbedtls_xor(chain, chain, p, MBEDTLS_CTR_DRBG_BLOCKSIZE); + 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(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; +} + +/* 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 + + 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; + } + + /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ + mbedtls_setbuf(f, NULL); + + 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; + } + + /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ + mbedtls_setbuf(f, NULL); + + 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(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..12559af --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/debug.c @@ -0,0 +1,389 @@ +/* + * 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) + +#include "mbedtls/platform.h" + +#include "mbedtls/debug.h" +#include "mbedtls/error.h" + +#include +#include +#include + +#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 it 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) && !defined(MBEDTLS_X509_REMOVE_INFO) +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 && MBEDTLS_X509_REMOVE_INFO */ + +#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..eaddf28 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/des.c @@ -0,0 +1,1054 @@ +/* + * 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 + +#include "mbedtls/platform.h" + +#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 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) { + mbedtls_xor(output, input, iv, 8); + + 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; + } + + mbedtls_xor(output, output, iv, 8); + + 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 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) { + mbedtls_xor(output, input, iv, 8); + + 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; + } + + mbedtls_xor(output, output, iv, 8); + + 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..94137a2 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/dhm.c @@ -0,0 +1,726 @@ +/* + * 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 + +#include "mbedtls/platform.h" + +#if !defined(MBEDTLS_DHM_ALT) + +/* + * 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) +{ + memset(ctx, 0, sizeof(mbedtls_dhm_context)); +} + +size_t mbedtls_dhm_get_bitlen(const mbedtls_dhm_context *ctx) +{ + return mbedtls_mpi_bitlen(&ctx->P); +} + +size_t mbedtls_dhm_get_len(const mbedtls_dhm_context *ctx) +{ + return mbedtls_mpi_size(&ctx->P); +} + +int mbedtls_dhm_get_value(const mbedtls_dhm_context *ctx, + mbedtls_dhm_parameter param, + mbedtls_mpi *dest) +{ + const mbedtls_mpi *src = NULL; + switch (param) { + case MBEDTLS_DHM_PARAM_P: + src = &ctx->P; + break; + case MBEDTLS_DHM_PARAM_G: + src = &ctx->G; + break; + case MBEDTLS_DHM_PARAM_X: + src = &ctx->X; + break; + case MBEDTLS_DHM_PARAM_GX: + src = &ctx->GX; + break; + case MBEDTLS_DHM_PARAM_GY: + src = &ctx->GY; + break; + case MBEDTLS_DHM_PARAM_K: + src = &ctx->K; + break; + default: + return MBEDTLS_ERR_DHM_BAD_INPUT_DATA; + } + return mbedtls_mpi_copy(dest, src); +} + +/* + * 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; + + 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; + } + + 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; + + 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; + +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; + + 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); + } + + 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; + + if (ilen < 1 || ilen > mbedtls_dhm_get_len(ctx)) { + 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; + + if (olen < 1 || olen > mbedtls_dhm_get_len(ctx)) { + 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; + + if (f_rng == NULL) { + return MBEDTLS_ERR_DHM_BAD_INPUT_DATA; + } + + if (output_size < mbedtls_dhm_get_len(ctx)) { + 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 */ + 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)); + + /* Do modular exponentiation */ + MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->K, &GYb, &ctx->X, + &ctx->P, &ctx->RP)); + + /* Unblind secret value */ + 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 */ + +#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; + +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; + } + /* The data loaded here is public, so don't bother disabling buffering. */ + + 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; + + 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..b529af5 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ecdh.c @@ -0,0 +1,697 @@ +/* + * 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 + +#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; + + int restarting = 0; +#if defined(MBEDTLS_ECP_RESTARTABLE) + restarting = (rs_ctx != NULL && rs_ctx->rsm != NULL); +#endif + /* If multiplication is in progress, we already generated a privkey */ + if (!restarting) { + 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) +{ + 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) +{ + 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) +{ +#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) +{ +#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) +{ + 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; +#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; + 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; + if (side != MBEDTLS_ECDH_OURS && side != MBEDTLS_ECDH_THEIRS) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + 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; +#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) +{ +#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; +#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..eb3c303 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ecdsa.c @@ -0,0 +1,879 @@ +/* + * 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 + +#include "mbedtls/platform.h" + +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#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) + */ +int mbedtls_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) +{ + /* Use the same RNG for both blinding and ephemeral key generation */ + return mbedtls_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 + * + * note: The f_rng_blind parameter must not be NULL. + * + */ +int mbedtls_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 + ret = mbedtls_ecdsa_sign_restartable(grp, r, s, d, buf, blen, + mbedtls_hmac_drbg_random, p_rng, + f_rng_blind, p_rng_blind, rs_ctx); +#endif /* MBEDTLS_ECDSA_SIGN_ALT */ + +cleanup: + mbedtls_hmac_drbg_free(&rng_ctx); + mbedtls_mpi_free(&h); + + ECDSA_RS_LEAVE(det); + + return ret; +} + +/* + * Deterministic signature wrapper + */ +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) +{ + return mbedtls_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) + */ +int mbedtls_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) +{ + return mbedtls_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 sig_size, + 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)); + + if (len > sig_size) { + return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; + } + + 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 sig_size, 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; + if (f_rng == NULL) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + mbedtls_mpi_init(&r); + mbedtls_mpi_init(&s); + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + MBEDTLS_MPI_CHK(mbedtls_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(mbedtls_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, sig_size, 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 sig_size, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) +{ + return mbedtls_ecdsa_write_signature_restartable( + ctx, md_alg, hash, hlen, sig, sig_size, slen, + f_rng, p_rng, NULL); +} + +/* + * 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) +{ + 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; + 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 = mbedtls_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; + 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; + 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) +{ + 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) +{ + 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..36c1327 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ecjpake.c @@ -0,0 +1,1259 @@ +/* + * 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" + +/* We use MD first if it's available (for compatibility reasons) + * and "fall back" to PSA otherwise (which needs psa_crypto_init()). */ +#if !defined(MBEDTLS_MD_C) +#include "psa/crypto.h" +#include "mbedtls/psa_util.h" +#if !defined(MBEDTLS_ECJPAKE_ALT) +#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \ + psa_to_md_errors, \ + psa_generic_status_to_mbedtls) +#endif /* !MBEDTLS_ECJPAKE_ALT */ +#endif /* !MBEDTLS_MD_C */ + +#include "hash_info.h" + +#include + +#if !defined(MBEDTLS_ECJPAKE_ALT) + +/* + * 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]) + +/** + * Helper to Compute a hash from md_type + */ +static int mbedtls_ecjpake_compute_hash(mbedtls_md_type_t md_type, + const unsigned char *input, size_t ilen, + unsigned char *output) +{ +#if defined(MBEDTLS_MD_C) + return mbedtls_md(mbedtls_md_info_from_type(md_type), + input, ilen, output); +#else + psa_algorithm_t alg = mbedtls_psa_translate_md(md_type); + psa_status_t status; + size_t out_size = PSA_HASH_LENGTH(alg); + size_t out_len; + + status = psa_hash_compute(alg, input, ilen, output, out_size, &out_len); + + return PSA_TO_MBEDTLS_ERR(status); +#endif /* !MBEDTLS_MD_C */ +} + +/* + * Initialize context + */ +void mbedtls_ecjpake_init(mbedtls_ecjpake_context *ctx) +{ + ctx->md_type = MBEDTLS_MD_NONE; + 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_type = MBEDTLS_MD_NONE; + 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; + + if (role != MBEDTLS_ECJPAKE_CLIENT && role != MBEDTLS_ECJPAKE_SERVER) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + ctx->role = role; + +#if defined(MBEDTLS_MD_C) + if ((mbedtls_md_info_from_type(hash)) == NULL) { + return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE; + } +#else + if (mbedtls_psa_translate_md(hash) == MBEDTLS_MD_NONE) { + return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE; + } +#endif + + ctx->md_type = hash; + + 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; +} + +int mbedtls_ecjpake_set_point_format(mbedtls_ecjpake_context *ctx, + int point_format) +{ + switch (point_format) { + case MBEDTLS_ECP_PF_UNCOMPRESSED: + case MBEDTLS_ECP_PF_COMPRESSED: + ctx->point_format = point_format; + return 0; + default: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } +} + +/* + * Check if context is ready for use + */ +int mbedtls_ecjpake_check(const mbedtls_ecjpake_context *ctx) +{ + if (ctx->md_type == MBEDTLS_MD_NONE || + 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_type_t md_type, + 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_HASH_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_ecjpake_compute_hash(md_type, + buf, p - buf, hash)); + + /* Turn it into an integer mod n */ + MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(h, hash, + mbedtls_hash_info_get_size(md_type))); + 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_type_t md_type, + 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_type, 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_type_t md_type, + 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_type, 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_type_t md_type, + 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_type, 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_type_t md_type, + 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_type, 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_type_t md_type, + 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_type, grp, pf, G, Xa, id, &p, end)); + MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_type, 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_type_t md_type, + 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_type, grp, pf, G, xm1, Xa, id, + &p, end, f_rng, p_rng)); + MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_type, 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) +{ + return ecjpake_kkpp_read(ctx->md_type, &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) +{ + return ecjpake_kkpp_write(ctx->md_type, &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 */ + + 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_type, &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; + + 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_type, &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) + */ +static int mbedtls_ecjpake_derive_k(mbedtls_ecjpake_context *ctx, + mbedtls_ecp_point *K, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi m_xm2_s, one; + + 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)); + +cleanup: + mbedtls_mpi_free(&m_xm2_s); + mbedtls_mpi_free(&one); + + return ret; +} + +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; + unsigned char kx[MBEDTLS_ECP_MAX_BYTES]; + size_t x_bytes; + + *olen = mbedtls_hash_info_get_size(ctx->md_type); + if (len < *olen) { + return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; + } + + mbedtls_ecp_point_init(&K); + + ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng); + if (ret) { + goto cleanup; + } + + /* 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_ecjpake_compute_hash(ctx->md_type, + kx, x_bytes, buf)); + +cleanup: + mbedtls_ecp_point_free(&K); + + return ret; +} + +int mbedtls_ecjpake_write_shared_key(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_ecp_point_init(&K); + + ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng); + if (ret) { + goto cleanup; + } + + ret = mbedtls_ecp_point_write_binary(&ctx->grp, &K, ctx->point_format, + olen, buf, len); + if (ret != 0) { + goto cleanup; + } + +cleanup: + mbedtls_ecp_point_free(&K); + + return ret; +} + +#undef ID_MINE +#undef ID_PEER + +#endif /* ! MBEDTLS_ECJPAKE_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +#include "mbedtls/platform.h" + +#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_shared_key[] = { + 0x04, 0x01, 0xab, 0xe9, 0xf2, 0xc7, 0x3a, 0x99, 0x14, 0xcb, 0x1f, 0x80, + 0xfb, 0x9d, 0xdb, 0x7e, 0x00, 0x12, 0xa8, 0x9c, 0x2f, 0x39, 0x27, 0x79, + 0xf9, 0x64, 0x40, 0x14, 0x75, 0xea, 0xc1, 0x31, 0x28, 0x43, 0x8f, 0xe1, + 0x12, 0x41, 0xd6, 0xc1, 0xe5, 0x5f, 0x7b, 0x80, 0x88, 0x94, 0xc9, 0xc0, + 0x27, 0xa3, 0x34, 0x41, 0xf5, 0xcb, 0xa1, 0xfe, 0x6c, 0xc7, 0xe6, 0x12, + 0x17, 0xc3, 0xde, 0x27, 0xb4, +}; + +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 +}; + +/* + * PRNG for test - !!!INSECURE NEVER USE IN PRODUCTION!!! + * + * This is the linear congruential generator from numerical recipes, + * except we only use the low byte as the output. See + * https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use + */ +static int self_test_rng(void *ctx, unsigned char *out, size_t len) +{ + static uint32_t state = 42; + + (void) ctx; + + for (size_t i = 0; i < len; i++) { + state = state * 1664525u + 1013904223u; + out[i] = (unsigned char) state; + } + + return 0; +} + +/* 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, self_test_rng, NULL)); + MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &ctx->Xm2, &ctx->xm2, + &ctx->grp.G, self_test_rng, 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); + + /* Server derives K as unsigned binary data */ + TEST_ASSERT(mbedtls_ecjpake_write_shared_key(&srv, + buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0); + + TEST_ASSERT(len == sizeof(ecjpake_test_shared_key)); + TEST_ASSERT(memcmp(buf, ecjpake_test_shared_key, 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); + + /* Client derives K as unsigned binary data */ + TEST_ASSERT(mbedtls_ecjpake_write_shared_key(&cli, + buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0); + + TEST_ASSERT(len == sizeof(ecjpake_test_shared_key)); + TEST_ASSERT(memcmp(buf, ecjpake_test_shared_key, 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..607d753 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ecp.c @@ -0,0 +1,3622 @@ +/* + * 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 "bn_mul.h" +#include "ecp_invasive.h" + +#include + +#if !defined(MBEDTLS_ECP_ALT) + +#include "mbedtls/platform.h" + +#include "ecp_internal_alt.h" + +#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_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; +}; + +/* + * 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; +} + +/* + * 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); + } + + 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) +{ + 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) +{ + 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 */ + +static void mpi_init_many(mbedtls_mpi *arr, size_t size) +{ + while (size--) { + mbedtls_mpi_init(arr++); + } +} + +static void mpi_free_many(mbedtls_mpi *arr, size_t size) +{ + while (size--) { + mbedtls_mpi_free(arr++); + } +} + +/* + * 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. + * + * Reminder: update profiles in x509_crt.c and ssl_tls.c when adding a new curve! + */ +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) +{ + 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) +{ + 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) +{ + 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)); +} + +/* + * Check that the comb table (grp->T) is static initialized. + */ +static int ecp_group_is_static_comb_table(const mbedtls_ecp_group *grp) +{ +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 + return grp->T != NULL && grp->T_size == 0; +#else + (void) grp; + return 0; +#endif +} + +/* + * 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->A); + mbedtls_mpi_free(&grp->B); + mbedtls_ecp_point_free(&grp->G); + } + + if (!ecp_group_is_static_comb_table(grp) && 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; + 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) +{ + 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; + 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) +{ + 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) +{ + 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; + 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; + if (format != MBEDTLS_ECP_PF_UNCOMPRESSED && + format != MBEDTLS_ECP_PF_COMPRESSED) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + 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; +} + +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) +static int mbedtls_ecp_sw_derive_y(const mbedtls_ecp_group *grp, + const mbedtls_mpi *X, + mbedtls_mpi *Y, + int parity_bit); +#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ + +/* + * 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; + 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 (ilen < 1 + plen) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&pt->X, buf + 1, plen)); + MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&pt->Z, 1)); + + if (buf[0] == 0x04) { + /* format == MBEDTLS_ECP_PF_UNCOMPRESSED */ + if (ilen != 1 + plen * 2) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + return mbedtls_mpi_read_binary(&pt->Y, buf + 1 + plen, plen); + } else if (buf[0] == 0x02 || buf[0] == 0x03) { + /* format == MBEDTLS_ECP_PF_COMPRESSED */ + if (ilen != 1 + plen) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + return mbedtls_ecp_sw_derive_y(grp, &pt->X, &pt->Y, + (buf[0] & 1)); + } else { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + } +#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; + /* + * 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; + if (format != MBEDTLS_ECP_PF_UNCOMPRESSED && + format != MBEDTLS_ECP_PF_COMPRESSED) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + /* + * 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; + 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; + /* + * 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; + 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) \ + do { \ + while ((N)->s < 0 && mbedtls_mpi_cmp_int((N), 0) != 0) \ + MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi((N), (N), &grp->P)); \ + } while (0) + +#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; +} + +static inline int mbedtls_mpi_mul_int_mod(const mbedtls_ecp_group *grp, + mbedtls_mpi *X, + const mbedtls_mpi *A, + mbedtls_mpi_uint c) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(X, A, c)); + MOD_ADD(X); +cleanup: + return ret; +} + +static inline int mbedtls_mpi_sub_int_mod(const mbedtls_ecp_group *grp, + mbedtls_mpi *X, + const mbedtls_mpi *A, + mbedtls_mpi_uint c) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(X, A, c)); + MOD_SUB(X); +cleanup: + return ret; +} + +#define MPI_ECP_SUB_INT(X, A, c) \ + MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int_mod(grp, X, A, c)) + +#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 */ + +/* + * Macro wrappers around ECP modular arithmetic + * + * Currently, these wrappers are defined via the bignum module. + */ + +#define MPI_ECP_ADD(X, A, B) \ + MBEDTLS_MPI_CHK(mbedtls_mpi_add_mod(grp, X, A, B)) + +#define MPI_ECP_SUB(X, A, B) \ + MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mod(grp, X, A, B)) + +#define MPI_ECP_MUL(X, A, B) \ + MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, X, A, B)) + +#define MPI_ECP_SQR(X, A) \ + MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, X, A, A)) + +#define MPI_ECP_MUL_INT(X, A, c) \ + MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int_mod(grp, X, A, c)) + +#define MPI_ECP_INV(dst, src) \ + MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod((dst), (src), &grp->P)) + +#define MPI_ECP_MOV(X, A) \ + MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A)) + +#define MPI_ECP_SHIFT_L(X, count) \ + MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l_mod(grp, X, count)) + +#define MPI_ECP_LSET(X, c) \ + MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, c)) + +#define MPI_ECP_CMP_INT(X, c) \ + mbedtls_mpi_cmp_int(X, c) + +#define MPI_ECP_CMP(X, Y) \ + mbedtls_mpi_cmp_mpi(X, Y) + +/* Needs f_rng, p_rng to be defined. */ +#define MPI_ECP_RAND(X) \ + MBEDTLS_MPI_CHK(mbedtls_mpi_random((X), 2, &grp->P, f_rng, p_rng)) + +/* Conditional negation + * Needs grp and a temporary MPI tmp to be defined. */ +#define MPI_ECP_COND_NEG(X, cond) \ + do \ + { \ + unsigned char nonzero = mbedtls_mpi_cmp_int((X), 0) != 0; \ + MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&tmp, &grp->P, (X))); \ + MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign((X), &tmp, \ + nonzero & cond)); \ + } while (0) + +#define MPI_ECP_NEG(X) MPI_ECP_COND_NEG((X), 1) + +#define MPI_ECP_VALID(X) \ + ((X)->p != NULL) + +#define MPI_ECP_COND_ASSIGN(X, Y, cond) \ + MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign((X), (Y), (cond))) + +#define MPI_ECP_COND_SWAP(X, Y, cond) \ + MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_swap((X), (Y), (cond))) + +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) + +/* + * Computes the right-hand side of the Short Weierstrass equation + * RHS = X^3 + A X + B + */ +static int ecp_sw_rhs(const mbedtls_ecp_group *grp, + mbedtls_mpi *rhs, + const mbedtls_mpi *X) +{ + int ret; + + /* Compute X^3 + A X + B as X (X^2 + A) + B */ + MPI_ECP_SQR(rhs, X); + + /* Special case for A = -3 */ + if (grp->A.p == NULL) { + MPI_ECP_SUB_INT(rhs, rhs, 3); + } else { + MPI_ECP_ADD(rhs, rhs, &grp->A); + } + + MPI_ECP_MUL(rhs, rhs, X); + MPI_ECP_ADD(rhs, rhs, &grp->B); + +cleanup: + return ret; +} + +/* + * Derive Y from X and a parity bit + */ +static int mbedtls_ecp_sw_derive_y(const mbedtls_ecp_group *grp, + const mbedtls_mpi *X, + mbedtls_mpi *Y, + int parity_bit) +{ + /* w = y^2 = x^3 + ax + b + * y = sqrt(w) = w^((p+1)/4) mod p (for prime p where p = 3 mod 4) + * + * Note: this method for extracting square root does not validate that w + * was indeed a square so this function will return garbage in Y if X + * does not correspond to a point on the curve. + */ + + /* Check prerequisite p = 3 mod 4 */ + if (mbedtls_mpi_get_bit(&grp->P, 0) != 1 || + mbedtls_mpi_get_bit(&grp->P, 1) != 1) { + return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + } + + int ret; + mbedtls_mpi exp; + mbedtls_mpi_init(&exp); + + /* use Y to store intermediate result, actually w above */ + MBEDTLS_MPI_CHK(ecp_sw_rhs(grp, Y, X)); + + /* w = y^2 */ /* Y contains y^2 intermediate result */ + /* exp = ((p+1)/4) */ + MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&exp, &grp->P, 1)); + MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&exp, 2)); + /* sqrt(w) = w^((p+1)/4) mod p (for prime p where p = 3 mod 4) */ + MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(Y, Y /*y^2*/, &exp, &grp->P, NULL)); + + /* check parity bit match or else invert Y */ + /* This quick inversion implementation is valid because Y != 0 for all + * Short Weierstrass curves supported by mbedtls, as each supported curve + * has an order that is a large prime, so each supported curve does not + * have any point of order 2, and a point with Y == 0 would be of order 2 */ + if (mbedtls_mpi_get_bit(Y, 0) != parity_bit) { + MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(Y, &grp->P, Y)); + } + +cleanup: + + mbedtls_mpi_free(&exp); + return ret; +} + +/* + * 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 (MPI_ECP_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 T; + mbedtls_mpi_init(&T); + + MPI_ECP_INV(&T, &pt->Z); /* T <- 1 / Z */ + MPI_ECP_MUL(&pt->Y, &pt->Y, &T); /* Y' <- Y*T = Y / Z */ + MPI_ECP_SQR(&T, &T); /* T <- T^2 = 1 / Z^2 */ + MPI_ECP_MUL(&pt->X, &pt->X, &T); /* X <- X * T = X / Z^2 */ + MPI_ECP_MUL(&pt->Y, &pt->Y, &T); /* Y'' <- Y' * T = Y / Z^3 */ + + MPI_ECP_LSET(&pt->Z, 1); + +cleanup: + + mbedtls_mpi_free(&T); + + 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, t; + + if ((c = mbedtls_calloc(T_size, sizeof(mbedtls_mpi))) == NULL) { + return MBEDTLS_ERR_ECP_ALLOC_FAILED; + } + + mbedtls_mpi_init(&t); + + mpi_init_many(c, T_size); + /* + * c[i] = Z_0 * ... * Z_i, i = 0,..,n := T_size-1 + */ + MPI_ECP_MOV(&c[0], &T[0]->Z); + for (i = 1; i < T_size; i++) { + MPI_ECP_MUL(&c[i], &c[i-1], &T[i]->Z); + } + + /* + * c[n] = 1 / (Z_0 * ... * Z_n) mod P + */ + MPI_ECP_INV(&c[T_size-1], &c[T_size-1]); + + for (i = T_size - 1;; i--) { + /* At the start of iteration i (note that i decrements), we have + * - c[j] = Z_0 * .... * Z_j for j < i, + * - c[j] = 1 / (Z_0 * .... * Z_j) for j == i, + * + * This is maintained via + * - c[i-1] <- c[i] * Z_i + * + * We also derive 1/Z_i = c[i] * c[i-1] for i>0 and use that + * to do the actual normalization. For i==0, we already have + * c[0] = 1 / Z_0. + */ + + if (i > 0) { + /* Compute 1/Z_i and establish invariant for the next iteration. */ + MPI_ECP_MUL(&t, &c[i], &c[i-1]); + MPI_ECP_MUL(&c[i-1], &c[i], &T[i]->Z); + } else { + MPI_ECP_MOV(&t, &c[0]); + } + + /* Now t holds 1 / Z_i; normalize as in ecp_normalize_jac() */ + MPI_ECP_MUL(&T[i]->Y, &T[i]->Y, &t); + MPI_ECP_SQR(&t, &t); + MPI_ECP_MUL(&T[i]->X, &T[i]->X, &t); + MPI_ECP_MUL(&T[i]->Y, &T[i]->Y, &t); + + /* + * 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)); + + MPI_ECP_LSET(&T[i]->Z, 1); + + if (i == 0) { + break; + } + } + +cleanup: + + mbedtls_mpi_free(&t); + mpi_free_many(c, T_size); + 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; + mbedtls_mpi tmp; + mbedtls_mpi_init(&tmp); + + MPI_ECP_COND_NEG(&Q->Y, inv); + +cleanup: + mbedtls_mpi_free(&tmp); + 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, + mbedtls_mpi tmp[4]) +{ +#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; + + /* Special case for A = -3 */ + if (grp->A.p == NULL) { + /* tmp[0] <- M = 3(X + Z^2)(X - Z^2) */ + MPI_ECP_SQR(&tmp[1], &P->Z); + MPI_ECP_ADD(&tmp[2], &P->X, &tmp[1]); + MPI_ECP_SUB(&tmp[3], &P->X, &tmp[1]); + MPI_ECP_MUL(&tmp[1], &tmp[2], &tmp[3]); + MPI_ECP_MUL_INT(&tmp[0], &tmp[1], 3); + } else { + /* tmp[0] <- M = 3.X^2 + A.Z^4 */ + MPI_ECP_SQR(&tmp[1], &P->X); + MPI_ECP_MUL_INT(&tmp[0], &tmp[1], 3); + + /* Optimize away for "koblitz" curves with A = 0 */ + if (MPI_ECP_CMP_INT(&grp->A, 0) != 0) { + /* M += A.Z^4 */ + MPI_ECP_SQR(&tmp[1], &P->Z); + MPI_ECP_SQR(&tmp[2], &tmp[1]); + MPI_ECP_MUL(&tmp[1], &tmp[2], &grp->A); + MPI_ECP_ADD(&tmp[0], &tmp[0], &tmp[1]); + } + } + + /* tmp[1] <- S = 4.X.Y^2 */ + MPI_ECP_SQR(&tmp[2], &P->Y); + MPI_ECP_SHIFT_L(&tmp[2], 1); + MPI_ECP_MUL(&tmp[1], &P->X, &tmp[2]); + MPI_ECP_SHIFT_L(&tmp[1], 1); + + /* tmp[3] <- U = 8.Y^4 */ + MPI_ECP_SQR(&tmp[3], &tmp[2]); + MPI_ECP_SHIFT_L(&tmp[3], 1); + + /* tmp[2] <- T = M^2 - 2.S */ + MPI_ECP_SQR(&tmp[2], &tmp[0]); + MPI_ECP_SUB(&tmp[2], &tmp[2], &tmp[1]); + MPI_ECP_SUB(&tmp[2], &tmp[2], &tmp[1]); + + /* tmp[1] <- S = M(S - T) - U */ + MPI_ECP_SUB(&tmp[1], &tmp[1], &tmp[2]); + MPI_ECP_MUL(&tmp[1], &tmp[1], &tmp[0]); + MPI_ECP_SUB(&tmp[1], &tmp[1], &tmp[3]); + + /* tmp[3] <- U = 2.Y.Z */ + MPI_ECP_MUL(&tmp[3], &P->Y, &P->Z); + MPI_ECP_SHIFT_L(&tmp[3], 1); + + /* Store results */ + MPI_ECP_MOV(&R->X, &tmp[2]); + MPI_ECP_MOV(&R->Y, &tmp[1]); + MPI_ECP_MOV(&R->Z, &tmp[3]); + +cleanup: + + 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. + * + * P,Q,R may alias, but only at the level of EC points: they must be either + * equal as pointers, or disjoint (including the coordinate data buffers). + * Fine-grained aliasing at the level of coordinates is not supported. + * + * 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. + * + * 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, + mbedtls_mpi tmp[4]) +{ +#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; + + /* NOTE: Aliasing between input and output is allowed, so one has to make + * sure that at the point X,Y,Z are written, {P,Q}->{X,Y,Z} are no + * longer read from. */ + mbedtls_mpi * const X = &R->X; + mbedtls_mpi * const Y = &R->Y; + mbedtls_mpi * const Z = &R->Z; + + if (!MPI_ECP_VALID(&Q->Z)) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + /* + * Trivial cases: P == 0 or Q == 0 (case 1) + */ + if (MPI_ECP_CMP_INT(&P->Z, 0) == 0) { + return mbedtls_ecp_copy(R, Q); + } + + if (MPI_ECP_CMP_INT(&Q->Z, 0) == 0) { + return mbedtls_ecp_copy(R, P); + } + + /* + * Make sure Q coordinates are normalized + */ + if (MPI_ECP_CMP_INT(&Q->Z, 1) != 0) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + MPI_ECP_SQR(&tmp[0], &P->Z); + MPI_ECP_MUL(&tmp[1], &tmp[0], &P->Z); + MPI_ECP_MUL(&tmp[0], &tmp[0], &Q->X); + MPI_ECP_MUL(&tmp[1], &tmp[1], &Q->Y); + MPI_ECP_SUB(&tmp[0], &tmp[0], &P->X); + MPI_ECP_SUB(&tmp[1], &tmp[1], &P->Y); + + /* Special cases (2) and (3) */ + if (MPI_ECP_CMP_INT(&tmp[0], 0) == 0) { + if (MPI_ECP_CMP_INT(&tmp[1], 0) == 0) { + ret = ecp_double_jac(grp, R, P, tmp); + goto cleanup; + } else { + ret = mbedtls_ecp_set_zero(R); + goto cleanup; + } + } + + /* {P,Q}->Z no longer used, so OK to write to Z even if there's aliasing. */ + MPI_ECP_MUL(Z, &P->Z, &tmp[0]); + MPI_ECP_SQR(&tmp[2], &tmp[0]); + MPI_ECP_MUL(&tmp[3], &tmp[2], &tmp[0]); + MPI_ECP_MUL(&tmp[2], &tmp[2], &P->X); + + MPI_ECP_MOV(&tmp[0], &tmp[2]); + MPI_ECP_SHIFT_L(&tmp[0], 1); + + /* {P,Q}->X no longer used, so OK to write to X even if there's aliasing. */ + MPI_ECP_SQR(X, &tmp[1]); + MPI_ECP_SUB(X, X, &tmp[0]); + MPI_ECP_SUB(X, X, &tmp[3]); + MPI_ECP_SUB(&tmp[2], &tmp[2], X); + MPI_ECP_MUL(&tmp[2], &tmp[2], &tmp[1]); + MPI_ECP_MUL(&tmp[3], &tmp[3], &P->Y); + /* {P,Q}->Y no longer used, so OK to write to Y even if there's aliasing. */ + MPI_ECP_SUB(Y, &tmp[2], &tmp[3]); + +cleanup: + + 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; + + mbedtls_mpi_init(&l); + + /* Generate l such that 1 < l < p */ + MPI_ECP_RAND(&l); + + /* Z' = l * Z */ + MPI_ECP_MUL(&pt->Z, &pt->Z, &l); + + /* Y' = l * Y */ + MPI_ECP_MUL(&pt->Y, &pt->Y, &l); + + /* X' = l^2 * X */ + MPI_ECP_SQR(&l, &l); + MPI_ECP_MUL(&pt->X, &pt->X, &l); + + /* Y'' = l^2 * Y' = l^3 * Y */ + MPI_ECP_MUL(&pt->Y, &pt->Y, &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_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] = { NULL }; + + mbedtls_mpi tmp[4]; + + mpi_init_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi)); + +#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, tmp)); + } + +#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 to allow them to be used in + * ecp_add_mixed() below, which requires one normalized input. + * + * 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], tmp)); + } + } + +#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)); + + /* Free Z coordinate (=1 after normalization) to save RAM. + * This makes T[i] invalid as mbedtls_ecp_points, but this is OK + * since from this point onwards, they are only accessed indirectly + * via the getter function ecp_select_comb() which does set the + * target's Z coordinate to 1. */ + for (i = 0; i < T_size; i++) { + mbedtls_mpi_free(&T[i].Z); + } + +cleanup: + + mpi_free_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi)); + +#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++) { + MPI_ECP_COND_ASSIGN(&R->X, &T[j].X, j == ii); + MPI_ECP_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)); + + MPI_ECP_LSET(&R->Z, 1); + +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; + mbedtls_mpi tmp[4]; + size_t i; + + mbedtls_ecp_point_init(&Txi); + mpi_init_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi)); + +#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])); + if (f_rng != 0) { + 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, tmp)); + MBEDTLS_MPI_CHK(ecp_select_comb(grp, &Txi, T, T_size, x[i])); + MBEDTLS_MPI_CHK(ecp_add_mixed(grp, R, R, &Txi, tmp)); + } + +cleanup: + + mbedtls_ecp_point_free(&Txi); + mpi_free_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi)); + +#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 (f_rng != 0) { + 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++; + } + + /* + * If static comb table may not be used (!p_eq_g) or static comb table does + * not exists, make sure w is within bounds. + * (The last test is useful only for very small curves in the test suite.) + * + * The user reduces MBEDTLS_ECP_WINDOW_SIZE does not changes the size of + * static comb table, because the size of static comb table is fixed when + * it is generated. + */ +#if (MBEDTLS_ECP_WINDOW_SIZE < 6) + if ((!p_eq_g || !ecp_group_is_static_comb_table(grp)) && 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; + + ECP_RS_ENTER(rsm); + + /* Is P the base point ? */ +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 + p_eq_g = (MPI_ECP_CMP(&P->Y, &grp->G.Y) == 0 && + MPI_ECP_CMP(&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: + + /* 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); + } + + /* prevent caller from using invalid value */ + int should_free_R = (ret != 0); +#if defined(MBEDTLS_ECP_RESTARTABLE) + /* don't free R while in progress in case R == P */ + if (ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { + should_free_R = 0; + } +#endif + if (should_free_R) { + 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; + MPI_ECP_INV(&P->Z, &P->Z); + MPI_ECP_MUL(&P->X, &P->X, &P->Z); + MPI_ECP_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 */ + MPI_ECP_RAND(&l); + + MPI_ECP_MUL(&P->X, &P->X, &l); + MPI_ECP_MUL(&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, + mbedtls_mpi T[4]) +{ +#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; + + MPI_ECP_ADD(&T[0], &P->X, &P->Z); /* Pp := PX + PZ */ + MPI_ECP_SUB(&T[1], &P->X, &P->Z); /* Pm := PX - PZ */ + MPI_ECP_ADD(&T[2], &Q->X, &Q->Z); /* Qp := QX + XZ */ + MPI_ECP_SUB(&T[3], &Q->X, &Q->Z); /* Qm := QX - QZ */ + MPI_ECP_MUL(&T[3], &T[3], &T[0]); /* Qm * Pp */ + MPI_ECP_MUL(&T[2], &T[2], &T[1]); /* Qp * Pm */ + MPI_ECP_SQR(&T[0], &T[0]); /* Pp^2 */ + MPI_ECP_SQR(&T[1], &T[1]); /* Pm^2 */ + MPI_ECP_MUL(&R->X, &T[0], &T[1]); /* Pp^2 * Pm^2 */ + MPI_ECP_SUB(&T[0], &T[0], &T[1]); /* Pp^2 - Pm^2 */ + MPI_ECP_MUL(&R->Z, &grp->A, &T[0]); /* A * (Pp^2 - Pm^2) */ + MPI_ECP_ADD(&R->Z, &T[1], &R->Z); /* [ A * (Pp^2-Pm^2) ] + Pm^2 */ + MPI_ECP_ADD(&S->X, &T[3], &T[2]); /* Qm*Pp + Qp*Pm */ + MPI_ECP_SQR(&S->X, &S->X); /* (Qm*Pp + Qp*Pm)^2 */ + MPI_ECP_SUB(&S->Z, &T[3], &T[2]); /* Qm*Pp - Qp*Pm */ + MPI_ECP_SQR(&S->Z, &S->Z); /* (Qm*Pp - Qp*Pm)^2 */ + MPI_ECP_MUL(&S->Z, d, &S->Z); /* d * ( Qm*Pp - Qp*Pm )^2 */ + MPI_ECP_MUL(&R->Z, &T[0], &R->Z); /* [A*(Pp^2-Pm^2)+Pm^2]*(Pp^2-Pm^2) */ + +cleanup: + + 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; + mbedtls_mpi tmp[4]; + mbedtls_ecp_point_init(&RP); mbedtls_mpi_init(&PX); + + mpi_init_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi)); + + if (f_rng == NULL) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + /* Save PX and read from P before writing to R, in case P == R */ + MPI_ECP_MOV(&PX, &P->X); + MBEDTLS_MPI_CHK(mbedtls_ecp_copy(&RP, P)); + + /* Set R to zero in modified x/z coordinates */ + MPI_ECP_LSET(&R->X, 1); + MPI_ECP_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 */ + MBEDTLS_MPI_CHK(ecp_randomize_mxz(grp, &RP, f_rng, p_rng)); + + /* Loop invariant: R = result so far, RP = R + P */ + i = grp->nbits + 1; /* one past the (zero-based) required msb for private keys */ + 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 + */ + MPI_ECP_COND_SWAP(&R->X, &RP.X, b); + MPI_ECP_COND_SWAP(&R->Z, &RP.Z, b); + MBEDTLS_MPI_CHK(ecp_double_add_mxz(grp, R, &RP, R, &RP, &PX, tmp)); + MPI_ECP_COND_SWAP(&R->X, &RP.X, b); + MPI_ECP_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. + */ + MBEDTLS_MPI_CHK(ecp_randomize_mxz(grp, R, f_rng, p_rng)); + MBEDTLS_MPI_CHK(ecp_normalize_mxz(grp, R)); + +cleanup: + mbedtls_ecp_point_free(&RP); mbedtls_mpi_free(&PX); + + mpi_free_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi)); + return ret; +} + +#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ + +/* + * Restartable multiplication R = m * P + * + * This internal function can be called without an RNG in case where we know + * the inputs are not sensitive. + */ +static int ecp_mul_restartable_internal(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 + +#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 */ + + int restarting = 0; +#if defined(MBEDTLS_ECP_RESTARTABLE) + restarting = (rs_ctx != NULL && rs_ctx->rsm != NULL); +#endif + /* skip argument check when restarting */ + if (!restarting) { + /* 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; +} + +/* + * 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) +{ + if (f_rng == NULL) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + return ecp_mul_restartable_internal(grp, R, m, P, f_rng, p_rng, rs_ctx); +} + +/* + * 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) +{ + 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^3 + A X + B + */ + MPI_ECP_SQR(&YY, &pt->Y); + MBEDTLS_MPI_CHK(ecp_sw_rhs(grp, &RHS, &pt->X)); + + if (MPI_ECP_CMP(&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; + mbedtls_mpi tmp; + mbedtls_mpi_init(&tmp); + + if (mbedtls_mpi_cmp_int(m, 0) == 0) { + MBEDTLS_MPI_CHK(mbedtls_ecp_check_pubkey(grp, P)); + MBEDTLS_MPI_CHK(mbedtls_ecp_set_zero(R)); + } else if (mbedtls_mpi_cmp_int(m, 1) == 0) { + MBEDTLS_MPI_CHK(mbedtls_ecp_check_pubkey(grp, P)); + MBEDTLS_MPI_CHK(mbedtls_ecp_copy(R, P)); + } else if (mbedtls_mpi_cmp_int(m, -1) == 0) { + MBEDTLS_MPI_CHK(mbedtls_ecp_check_pubkey(grp, P)); + MBEDTLS_MPI_CHK(mbedtls_ecp_copy(R, P)); + MPI_ECP_NEG(&R->Y); + } else { + MBEDTLS_MPI_CHK(ecp_mul_restartable_internal(grp, R, m, P, + NULL, NULL, rs_ctx)); + } + +cleanup: + mbedtls_mpi_free(&tmp); + + 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; + mbedtls_mpi tmp[4]; +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + char is_grp_capable = 0; +#endif + if (mbedtls_ecp_get_type(grp) != MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) { + return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + } + + mbedtls_ecp_point_init(&mP); + mpi_init_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi)); + + 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, tmp)); +#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: + + mpi_free_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi)); + +#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) +{ + 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, (n), (mbedtls_mpi_uint *)(p), 0} +#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) +{ + /* 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) +{ +#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) +{ +#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; + 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) +{ + 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; + 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 +#define ECP_CURVE448_KEY_SIZE 56 +/* + * 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; + + 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) { + /* + * Mask the key as mandated by RFC7748 for Curve25519 and Curve448. + */ + 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 if (grp_id == MBEDTLS_ECP_DP_CURVE448) { + if (buflen != ECP_CURVE448_KEY_SIZE) { + return MBEDTLS_ERR_ECP_INVALID_KEY; + } + + MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary_le(&key->d, buf, buflen)); + + /* Set the two 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)); + + /* Set the most significant bit to 1 */ + MBEDTLS_MPI_CHK( + mbedtls_mpi_set_bit(&key->d, + ECP_CURVE448_KEY_SIZE * 8 - 1, 1) + ); + } + } + +#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; + +#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; + } + + } else if (key->grp.id == MBEDTLS_ECP_DP_CURVE448) { + if (buflen < ECP_CURVE448_KEY_SIZE) { + return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; + } + } + MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary_le(&key->d, buf, buflen)); + } +#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 (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_point Q; + mbedtls_ecp_group grp; + 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, f_rng, p_rng)); + + 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; +} + +/* + * Export generic key-pair parameters. + */ +int mbedtls_ecp_export(const mbedtls_ecp_keypair *key, mbedtls_ecp_group *grp, + mbedtls_mpi *d, mbedtls_ecp_point *Q) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if ((ret = mbedtls_ecp_group_copy(grp, &key->grp)) != 0) { + return ret; + } + + if ((ret = mbedtls_mpi_copy(d, &key->d)) != 0) { + return ret; + } + + if ((ret = mbedtls_ecp_copy(Q, &key->Q)) != 0) { + return ret; + } + + return 0; +} + +#if defined(MBEDTLS_SELF_TEST) + +/* + * PRNG for test - !!!INSECURE NEVER USE IN PRODUCTION!!! + * + * This is the linear congruential generator from numerical recipes, + * except we only use the low byte as the output. See + * https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use + */ +static int self_test_rng(void *ctx, unsigned char *out, size_t len) +{ + static uint32_t state = 42; + + (void) ctx; + + for (size_t i = 0; i < len; i++) { + state = state * 1664525u + 1013904223u; + out[i] = (unsigned char) state; + } + + return 0; +} + +/* 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, self_test_rng, 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, self_test_rng, 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, self_test_rng, 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..f9b452b --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ecp_curves.c @@ -0,0 +1,5960 @@ +/* + * 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 "bn_mul.h" +#include "bignum_core.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) + +#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) + +#define ECP_POINT_INIT_XY_Z0(x, y) { \ + ECP_MPI_INIT_ARRAY(x), ECP_MPI_INIT_ARRAY(y), ECP_MPI_INIT(1, 0, NULL) } +#define ECP_POINT_INIT_XY_Z1(x, y) { \ + ECP_MPI_INIT_ARRAY(x), ECP_MPI_INIT_ARRAY(y), ECP_MPI_INIT(1, 1, mpi_one) } + +#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 +static mbedtls_mpi_uint mpi_one[] = { 1 }; +#endif + +/* + * 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), +}; +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint secp192r1_T_0_X[] = { + 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_T_0_Y[] = { + 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_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x9E, 0xE3, 0x60, 0x59, 0xD1, 0xC4, 0xC2), + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xBD, 0x22, 0xD7, 0x2D, 0x07, 0xBD, 0xB6), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x2A, 0xCF, 0x33, 0xF0, 0xBE, 0xD1, 0xED), +}; +static const mbedtls_mpi_uint secp192r1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x71, 0x4B, 0xA8, 0xED, 0x7E, 0xC9, 0x1A), + MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x2A, 0xF6, 0xDF, 0x0E, 0xE8, 0x4C, 0x0F), + MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x35, 0xF7, 0x8A, 0xC3, 0xEC, 0xDE, 0x1E), +}; +static const mbedtls_mpi_uint secp192r1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x67, 0xC2, 0x1D, 0x32, 0x8F, 0x10, 0xFB), + MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x2D, 0x17, 0xF3, 0xE4, 0xFE, 0xD8, 0x13), + MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x45, 0x10, 0x70, 0x2C, 0x3E, 0x52, 0x3E), +}; +static const mbedtls_mpi_uint secp192r1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xF1, 0x04, 0x5D, 0xEE, 0xD4, 0x56, 0xE6), + MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xB7, 0x38, 0x27, 0x61, 0xAA, 0x81, 0x87), + MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x37, 0xD7, 0x0E, 0x29, 0x0E, 0x11, 0x14), +}; +static const mbedtls_mpi_uint secp192r1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x35, 0x52, 0xC6, 0x31, 0xB7, 0x27, 0xF5), + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xD4, 0x15, 0x98, 0x0F, 0xE7, 0xF3, 0x6A), + MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x31, 0x70, 0x35, 0x09, 0xA0, 0x2B, 0xC2), +}; +static const mbedtls_mpi_uint secp192r1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x75, 0xA7, 0x4C, 0x88, 0xCF, 0x5B, 0xE4), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x17, 0x48, 0x8D, 0xF2, 0xF0, 0x86, 0xED), + MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xCF, 0xFE, 0x6B, 0xB0, 0xA5, 0x06, 0xAB), +}; +static const mbedtls_mpi_uint secp192r1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x6A, 0xDC, 0x9A, 0x6D, 0x7B, 0x47, 0x2E), + MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0xFC, 0x51, 0x12, 0x62, 0x66, 0x0B, 0x59), + MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x40, 0x93, 0xA0, 0xB5, 0x5A, 0x58, 0xD7), +}; +static const mbedtls_mpi_uint secp192r1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0xCB, 0xAF, 0xDC, 0x0B, 0xA1, 0x26, 0xFB), + MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x36, 0x9D, 0xA3, 0xD7, 0x3B, 0xAD, 0x39), + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x3B, 0x05, 0x9A, 0xA8, 0xAA, 0x69, 0xB2), +}; +static const mbedtls_mpi_uint secp192r1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xD9, 0xD1, 0x4D, 0x4A, 0x6E, 0x96, 0x1E), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x66, 0x32, 0x39, 0xC6, 0x57, 0x7D, 0xE6), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xA0, 0x36, 0xC2, 0x45, 0xF9, 0x00, 0x62), +}; +static const mbedtls_mpi_uint secp192r1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xEF, 0x59, 0x46, 0xDC, 0x60, 0xD9, 0x8F), + MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xB0, 0xE9, 0x41, 0xA4, 0x87, 0x76, 0x89), + MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0xD4, 0x0E, 0xB2, 0xFA, 0x16, 0x56, 0xDC), +}; +static const mbedtls_mpi_uint secp192r1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x62, 0xD2, 0xB1, 0x34, 0xB2, 0xF1, 0x06), + MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xED, 0x55, 0xC5, 0x47, 0xB5, 0x07, 0x15), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xF6, 0x2F, 0x94, 0xC3, 0xDD, 0x54, 0x2F), +}; +static const mbedtls_mpi_uint secp192r1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xA6, 0xD4, 0x8C, 0xA9, 0xCE, 0x4D, 0x2E), + MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x4B, 0x46, 0xCC, 0xB2, 0x55, 0xC8, 0xB2), + MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xAE, 0x31, 0xED, 0x89, 0x65, 0x59, 0x55), +}; +static const mbedtls_mpi_uint secp192r1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x0A, 0xD1, 0x1A, 0xC5, 0xF6, 0xEA, 0x43), + MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xFC, 0x0C, 0x1A, 0xFB, 0xA0, 0xC8, 0x70), + MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xFD, 0x53, 0x6F, 0x6D, 0xBF, 0xBA, 0xAF), +}; +static const mbedtls_mpi_uint secp192r1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xB0, 0x7D, 0x83, 0x96, 0xE3, 0xCB, 0x9D), + MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x6E, 0x55, 0x2C, 0x20, 0x53, 0x2F, 0x46), + MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0x66, 0x00, 0x17, 0x08, 0xFE, 0xAC, 0x31), +}; +static const mbedtls_mpi_uint secp192r1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x12, 0x97, 0x3A, 0xC7, 0x57, 0x45, 0xCD), + MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x25, 0x99, 0x00, 0xF6, 0x97, 0xB4, 0x64), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x74, 0xE6, 0xE6, 0xA3, 0xDF, 0x9C, 0xCC), +}; +static const mbedtls_mpi_uint secp192r1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xF4, 0x76, 0xD5, 0x5F, 0x2A, 0xFD, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x80, 0x7E, 0x3E, 0xE5, 0xE8, 0xD6, 0x63), + MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xAD, 0x1E, 0x70, 0x79, 0x3E, 0x3D, 0x83), +}; +static const mbedtls_mpi_uint secp192r1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x15, 0xBB, 0xB3, 0x42, 0x6A, 0xA1, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x58, 0xCB, 0x43, 0x25, 0x00, 0x14, 0x68), + MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x4E, 0x93, 0x11, 0xE0, 0x32, 0x54, 0x98), +}; +static const mbedtls_mpi_uint secp192r1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x52, 0xA2, 0xB4, 0x57, 0x32, 0xB9, 0x11), + MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x43, 0xA1, 0xB1, 0xFB, 0x01, 0xE1, 0xE7), + MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xFB, 0x5A, 0x11, 0xB8, 0xC2, 0x03, 0xE5), +}; +static const mbedtls_mpi_uint secp192r1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x2B, 0x71, 0x26, 0x4E, 0x7C, 0xC5, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xF5, 0xD3, 0xA8, 0xE4, 0x95, 0x48, 0x65), + MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xAE, 0xD9, 0x5D, 0x9F, 0x6A, 0x22, 0xAD), +}; +static const mbedtls_mpi_uint secp192r1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0xCC, 0xA3, 0x4D, 0xA0, 0x1C, 0x34, 0xEF), + MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x3C, 0x62, 0xF8, 0x5E, 0xA6, 0x58, 0x7D), + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x6E, 0x66, 0x8A, 0x3D, 0x17, 0xFF, 0x0F), +}; +static const mbedtls_mpi_uint secp192r1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xCD, 0xA8, 0xDD, 0xD1, 0x20, 0x5C, 0xEA), + MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0xFE, 0x17, 0xE2, 0xCF, 0xEA, 0x63, 0xDE), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x51, 0xC9, 0x16, 0xDE, 0xB4, 0xB2, 0xDD), +}; +static const mbedtls_mpi_uint secp192r1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xBE, 0x12, 0xD7, 0xA3, 0x0A, 0x50, 0x33), + MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0x87, 0xC5, 0x8A, 0x76, 0x57, 0x07, 0x60), + MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x1F, 0xC6, 0x1B, 0x66, 0xC4, 0x3D, 0x8A), +}; +static const mbedtls_mpi_uint secp192r1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xA4, 0x85, 0x13, 0x8F, 0xA7, 0x35, 0x19), + MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x0D, 0xFD, 0xFF, 0x1B, 0xD1, 0xD6, 0xEF), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x7A, 0xD0, 0xC3, 0xB4, 0xEF, 0x39, 0x66), +}; +static const mbedtls_mpi_uint secp192r1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xFE, 0xA5, 0x9C, 0x34, 0x30, 0x49, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0xC5, 0x39, 0x26, 0x06, 0xE3, 0x01, 0x17), + MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x2B, 0x66, 0xFC, 0x95, 0x5F, 0x35, 0xF7), +}; +static const mbedtls_mpi_uint secp192r1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xCF, 0x54, 0x63, 0x99, 0x57, 0x05, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x6F, 0x00, 0x5F, 0x65, 0x08, 0x47, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x2A, 0x90, 0x6D, 0x67, 0xC6, 0xBC, 0x45), +}; +static const mbedtls_mpi_uint secp192r1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x4D, 0x88, 0x0A, 0x35, 0x9E, 0x33, 0x9C), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x17, 0x0C, 0xF8, 0xE1, 0x7A, 0x49, 0x02), + MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x44, 0x06, 0x8F, 0x0B, 0x70, 0x2F, 0x71), +}; +static const mbedtls_mpi_uint secp192r1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x4B, 0xCB, 0xF9, 0x8E, 0x6A, 0xDA, 0x1B), + MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x43, 0xA1, 0x3F, 0xCE, 0x17, 0xD2, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x0D, 0xD2, 0x6C, 0x82, 0x37, 0xE5, 0xFC), +}; +static const mbedtls_mpi_uint secp192r1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x3C, 0xF4, 0x92, 0xB4, 0x8A, 0x95, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x96, 0xF1, 0x0A, 0x34, 0x2F, 0x74, 0x7E), + MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xA1, 0xAA, 0xBA, 0x86, 0x77, 0x4F, 0xA2), +}; +static const mbedtls_mpi_uint secp192r1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x7F, 0xEF, 0x60, 0x50, 0x80, 0xD7, 0xD4), + MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0xAC, 0xC9, 0xFE, 0xEC, 0x0A, 0x1A, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x2F, 0xBE, 0x91, 0xD7, 0xB7, 0x38, 0x48), +}; +static const mbedtls_mpi_uint secp192r1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xAE, 0x85, 0x98, 0xFE, 0x05, 0x7F, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xBE, 0xFD, 0x11, 0x31, 0x3D, 0x14, 0x13), + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x75, 0xE8, 0x30, 0x01, 0xCB, 0x9B, 0x1C), +}; +static const mbedtls_ecp_point secp192r1_T[16] = { + ECP_POINT_INIT_XY_Z1(secp192r1_T_0_X, secp192r1_T_0_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_1_X, secp192r1_T_1_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_2_X, secp192r1_T_2_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_3_X, secp192r1_T_3_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_4_X, secp192r1_T_4_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_5_X, secp192r1_T_5_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_6_X, secp192r1_T_6_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_7_X, secp192r1_T_7_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_8_X, secp192r1_T_8_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_9_X, secp192r1_T_9_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_10_X, secp192r1_T_10_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_11_X, secp192r1_T_11_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_12_X, secp192r1_T_12_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_13_X, secp192r1_T_13_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_14_X, secp192r1_T_14_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_15_X, secp192r1_T_15_Y), +}; +#else +#define secp192r1_T NULL +#endif +#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), +}; +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint secp224r1_T_0_X[] = { + 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_8(0xBD, 0x0C, 0x0E, 0xB7, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_0_Y[] = { + 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_8(0x88, 0x63, 0x37, 0xBD, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xF9, 0xB8, 0xD0, 0x3D, 0xD2, 0xD3, 0xFA), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xFD, 0x99, 0x26, 0x19, 0xFE, 0x13, 0x6E), + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x0E, 0x4C, 0x48, 0x7C, 0xA2, 0x17, 0x01), + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xA3, 0x13, 0x57, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x16, 0x5C, 0x8F, 0xAA, 0xED, 0x0F, 0x58), + MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0xC5, 0x43, 0x34, 0x93, 0x05, 0x2A, 0x4C), + MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0xE3, 0x6C, 0xCA, 0xC6, 0x14, 0xC2, 0x25), + MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x43, 0x6C, 0xD7, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x5A, 0x98, 0x1E, 0xC8, 0xA5, 0x42, 0xA3), + MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x49, 0x56, 0x78, 0xF8, 0xEF, 0xED, 0x65), + MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0xBB, 0x64, 0xB6, 0x4C, 0x54, 0x5F, 0xD1), + MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x0C, 0x33, 0xCC, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x79, 0xCB, 0x2E, 0x08, 0xFF, 0xD8, 0xE6), + MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0x1F, 0xD4, 0xD7, 0x57, 0xE9, 0x39, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xD6, 0x3B, 0x0A, 0x1C, 0x87, 0xB7, 0x6A), + MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x30, 0xD8, 0x05, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x79, 0x74, 0x9A, 0xE6, 0xBB, 0xC2, 0xC2), + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x5B, 0xA6, 0x67, 0xC1, 0x91, 0xE7, 0x64), + MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xDF, 0x38, 0x82, 0x19, 0x2C, 0x4C, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x2E, 0x39, 0xC5, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x36, 0x78, 0x4E, 0xAE, 0x5B, 0x02, 0x76), + MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xF6, 0x8B, 0xF8, 0xF4, 0x92, 0x6B, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x4D, 0x71, 0x35, 0xE7, 0x0C, 0x2C, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xA5, 0x1F, 0xAE, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x1C, 0x4B, 0xDF, 0x5B, 0xF2, 0x51, 0xB7), + MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x74, 0xB1, 0x5A, 0xC6, 0x0F, 0x0E, 0x61), + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x24, 0x09, 0x62, 0xAF, 0xFC, 0xDB, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0xE1, 0x80, 0x55, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x82, 0xFE, 0xAD, 0xC3, 0xE5, 0xCF, 0xD8), + MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xA2, 0x62, 0x17, 0x76, 0xF0, 0x5A, 0xFA), + MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xB8, 0xE5, 0xAC, 0xB7, 0x66, 0x38, 0xAA), + MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0xFD, 0x86, 0x05, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xD3, 0x0C, 0x3C, 0xD1, 0x66, 0xB0, 0xF1), + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x59, 0xB4, 0x8D, 0x90, 0x10, 0xB7, 0xA2), + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x47, 0x9B, 0xE6, 0x55, 0x8A, 0xE4, 0xEE), + MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x49, 0xDB, 0x78, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x97, 0xED, 0xDE, 0xFF, 0xB3, 0xDF, 0x48), + MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xB9, 0x83, 0xB7, 0xEB, 0xBE, 0x40, 0x8D), + MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xD3, 0xD3, 0xCD, 0x0E, 0x82, 0x79, 0x3D), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x83, 0x1B, 0xF0, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x22, 0xBB, 0x54, 0xD3, 0x31, 0x56, 0xFC), + MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x36, 0xE5, 0xE0, 0x89, 0x96, 0x8E, 0x71), + MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0xEF, 0x0A, 0xED, 0xD0, 0x11, 0x4A, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x00, 0x57, 0x27, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0xCA, 0x3D, 0xF7, 0x64, 0x9B, 0x6E, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xE3, 0x70, 0x6B, 0x41, 0xD7, 0xED, 0x8F), + MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x44, 0x44, 0x80, 0xCE, 0x13, 0x37, 0x92), + MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x73, 0x80, 0x79, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x4D, 0x70, 0x7D, 0x31, 0x0F, 0x1C, 0x58), + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x35, 0x88, 0x47, 0xC4, 0x24, 0x78, 0x3F), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xF0, 0xCD, 0x91, 0x81, 0xB3, 0xDE, 0xB6), + MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xCE, 0xC6, 0xF7, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x9C, 0x2D, 0xE8, 0xD2, 0x00, 0x8F, 0x10), + MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x5E, 0x7C, 0x0E, 0x0C, 0x6E, 0x58, 0x02), + MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x81, 0x21, 0xCE, 0x43, 0xF4, 0x24, 0x3D), + MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0xBC, 0xF0, 0xF4, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x10, 0xC2, 0x74, 0x4A, 0x8F, 0x8A, 0xCF), + MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x67, 0xF4, 0x2B, 0x38, 0x2B, 0x35, 0x17), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xE7, 0x0C, 0xA9, 0xFA, 0x77, 0x5C, 0xBD), + MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x33, 0x19, 0x2B, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x3E, 0x96, 0x22, 0x53, 0xE1, 0xE9, 0xBE), + MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x13, 0xBC, 0xA1, 0x16, 0xEC, 0x01, 0x1A), + MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x00, 0xC9, 0x7A, 0xC3, 0x73, 0xA5, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0xF4, 0x5E, 0xC1, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x95, 0xD6, 0xD9, 0x32, 0x30, 0x2B, 0xD0), + MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x42, 0x09, 0x05, 0x61, 0x2A, 0x7E, 0x82), + MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x84, 0xA2, 0x05, 0x88, 0x64, 0x65, 0xF9), + MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x2D, 0x90, 0xB3, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xE7, 0x2E, 0x85, 0x55, 0x80, 0x7C, 0x79), + MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xC1, 0xAC, 0x78, 0xB4, 0xAF, 0xFB, 0x6E), + MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0xC3, 0x28, 0x8E, 0x79, 0x18, 0x1F, 0x58), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x46, 0xCF, 0x49, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x5F, 0xA8, 0x6C, 0x46, 0x83, 0x43, 0xFA), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xA9, 0x93, 0x11, 0xB6, 0x07, 0x57, 0x74), + MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x2A, 0x9D, 0x03, 0x89, 0x7E, 0xD7, 0x3C), + MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x8C, 0x62, 0xCF, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0x2C, 0x13, 0x59, 0xCC, 0xFA, 0x84, 0x9E), + MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xB9, 0x48, 0xBC, 0x57, 0xC7, 0xB3, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x0A, 0x38, 0x24, 0x2E, 0x3A, 0x28, 0x25), + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x0A, 0x43, 0xB8, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x25, 0xAB, 0xC1, 0xEE, 0x70, 0x3C, 0xE1), + MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0xDB, 0x45, 0x1D, 0x4A, 0x80, 0x75, 0x35), + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x1F, 0x4D, 0x2D, 0x9A, 0x05, 0xF4, 0xCB), + MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x10, 0xF0, 0x5A, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x95, 0xE1, 0xDC, 0x15, 0x86, 0xC3, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0xDC, 0x27, 0xD1, 0x56, 0xA1, 0x14, 0x0D), + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x0B, 0xD6, 0x77, 0x4E, 0x44, 0xA2, 0xF8), + MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x42, 0x71, 0x1F, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x86, 0xB2, 0xB0, 0xC8, 0x2F, 0x7B, 0xFE), + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xEF, 0xCB, 0xDB, 0xBC, 0x9E, 0x3B, 0xC5), + MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x03, 0x86, 0xDD, 0x5B, 0xF5, 0x8D, 0x46), + MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x95, 0x79, 0xD6, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x32, 0x14, 0xDA, 0x9B, 0x4F, 0x07, 0x39), + MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x3E, 0xFB, 0x06, 0xEE, 0xA7, 0x40, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x1F, 0xDF, 0x71, 0x61, 0xFD, 0x8B, 0xBE), + MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x8B, 0xAB, 0x8B, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x34, 0xB3, 0xB4, 0xBC, 0x9F, 0xB0, 0x5E), + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x58, 0x48, 0xA8, 0x77, 0xBB, 0x13, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xC6, 0xF7, 0x34, 0xCC, 0x89, 0x21, 0x0A), + MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x33, 0xDD, 0x1F, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x81, 0xEF, 0xA4, 0xF2, 0x10, 0x0B, 0xCD), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xF7, 0x6E, 0x72, 0x4A, 0xDF, 0xDD, 0xE8), + MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x23, 0x0A, 0x53, 0x03, 0x16, 0x62, 0xD2), + MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x76, 0xFD, 0x3C, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x14, 0xA1, 0xFA, 0xA0, 0x18, 0xBE, 0x07), + MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x2A, 0xE1, 0xD7, 0xB0, 0x6C, 0xA0, 0xDE), + MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xC0, 0xB0, 0xC6, 0x63, 0x24, 0xCD, 0x4E), + MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x38, 0x2C, 0xB1, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xCD, 0x7D, 0x20, 0x0C, 0xFE, 0xAC, 0xC3), + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x97, 0x9F, 0xA2, 0xB6, 0x45, 0xF7, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x99, 0xF3, 0xD2, 0x20, 0x02, 0xEB, 0x04), + MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x18, 0x5B, 0x7B, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xDD, 0x77, 0x91, 0x60, 0xEA, 0xFD, 0xD3), + MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xD3, 0xB5, 0xD6, 0x90, 0x17, 0x0E, 0x1A), + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0xF4, 0x28, 0xC1, 0xF2, 0x53, 0xF6, 0x63), + MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0x58, 0xDC, 0x61, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224r1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x20, 0x01, 0xFB, 0xF1, 0xBD, 0x5F, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x7F, 0x06, 0xDA, 0x11, 0xCB, 0xBA, 0xA6), + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x41, 0x00, 0xA4, 0x1B, 0x30, 0x33, 0x79), + MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0xFF, 0x27, 0xCA, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_ecp_point secp224r1_T[16] = { + ECP_POINT_INIT_XY_Z1(secp224r1_T_0_X, secp224r1_T_0_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_1_X, secp224r1_T_1_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_2_X, secp224r1_T_2_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_3_X, secp224r1_T_3_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_4_X, secp224r1_T_4_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_5_X, secp224r1_T_5_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_6_X, secp224r1_T_6_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_7_X, secp224r1_T_7_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_8_X, secp224r1_T_8_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_9_X, secp224r1_T_9_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_10_X, secp224r1_T_10_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_11_X, secp224r1_T_11_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_12_X, secp224r1_T_12_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_13_X, secp224r1_T_13_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_14_X, secp224r1_T_14_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_15_X, secp224r1_T_15_Y), +}; +#else +#define secp224r1_T NULL +#endif +#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), +}; +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint secp256r1_T_0_X[] = { + 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_T_0_Y[] = { + 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_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xC8, 0xBA, 0x04, 0xB7, 0x4B, 0xD2, 0xF7), + MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0xC6, 0x23, 0x3A, 0xA0, 0x09, 0x3A, 0x59), + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x9D, 0x4C, 0xF9, 0x58, 0x23, 0xCC, 0xDF), + MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0xED, 0x7B, 0x29, 0x87, 0x0F, 0xFA, 0x3C), +}; +static const mbedtls_mpi_uint secp256r1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x69, 0xF2, 0x40, 0x0B, 0xA3, 0x98, 0xCE), + MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xA8, 0x48, 0x02, 0x0D, 0x1C, 0x12, 0x62), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xAF, 0x09, 0x83, 0x80, 0xAA, 0x58, 0xA7), + MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x12, 0xBE, 0x70, 0x94, 0x76, 0xE3, 0xE4), +}; +static const mbedtls_mpi_uint secp256r1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x7D, 0xEF, 0x86, 0xFF, 0xE3, 0x37, 0xDD), + MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x86, 0x8B, 0x08, 0x27, 0x7C, 0xD7, 0xF6), + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x54, 0x4C, 0x25, 0x4F, 0x9A, 0xFE, 0x28), + MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xFD, 0xF0, 0x6D, 0x37, 0x03, 0x69, 0xD6), +}; +static const mbedtls_mpi_uint secp256r1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xD5, 0xDA, 0xAD, 0x92, 0x49, 0xF0, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x73, 0x43, 0x9E, 0xAF, 0xA7, 0xD1, 0xF3), + MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x41, 0x07, 0xDF, 0x78, 0x95, 0x3E, 0xA1), + MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x3D, 0xD1, 0xE6, 0x3C, 0xA5, 0xE2, 0x20), +}; +static const mbedtls_mpi_uint secp256r1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x6A, 0x5D, 0x52, 0x35, 0xD7, 0xBF, 0xAE), + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0xA2, 0xBE, 0x96, 0xF4, 0xF8, 0x02, 0xC3), + MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x20, 0x49, 0x54, 0xEA, 0xB3, 0x82, 0xDB), + MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0xDB, 0xEA, 0x02, 0xD1, 0x75, 0x1C, 0x62), +}; +static const mbedtls_mpi_uint secp256r1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x85, 0xF4, 0x9E, 0x4C, 0xDC, 0x39, 0x89), + MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x6D, 0xC4, 0x57, 0xD8, 0x03, 0x5D, 0x22), + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x7F, 0x2D, 0x52, 0x6F, 0xC9, 0xDA, 0x4F), + MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x64, 0xFA, 0xB4, 0xFE, 0xA4, 0xC4, 0xD7), +}; +static const mbedtls_mpi_uint secp256r1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x37, 0xB9, 0xC0, 0xAA, 0x59, 0xC6, 0x8B), + MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x58, 0xD9, 0xED, 0x58, 0x99, 0x65, 0xF7), + MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x7D, 0x26, 0x8C, 0x4A, 0xF9, 0x05, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x73, 0x9A, 0xC9, 0xE7, 0x46, 0xDC, 0x00), +}; +static const mbedtls_mpi_uint secp256r1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xD0, 0x55, 0xDF, 0x00, 0x0A, 0xF5, 0x4A), + MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0xBF, 0x56, 0x81, 0x2D, 0x20, 0xEB, 0xB5), + MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xC1, 0x28, 0x52, 0xAB, 0xE3, 0xD1, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x34, 0x79, 0x45, 0x57, 0xA5, 0x12, 0x03), +}; +static const mbedtls_mpi_uint secp256r1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xCF, 0xB8, 0x7E, 0xF7, 0x92, 0x96, 0x8D), + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x01, 0x8C, 0x0D, 0x23, 0xF2, 0xE3, 0x05), + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x2E, 0xE3, 0x84, 0x52, 0x7A, 0x34, 0x76), + MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xA1, 0xB0, 0x15, 0x90, 0xE2, 0x53, 0x3C), +}; +static const mbedtls_mpi_uint secp256r1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x98, 0xE7, 0xFA, 0xA5, 0x7D, 0x8B, 0x53), + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x35, 0xD2, 0x00, 0xD1, 0x1B, 0x9F, 0x1B), + MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x69, 0x08, 0x9A, 0x72, 0xF0, 0xA9, 0x11), + MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0xFE, 0x0E, 0x14, 0xDA, 0x7C, 0x0E, 0xD3), +}; +static const mbedtls_mpi_uint secp256r1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xF6, 0xE8, 0xF8, 0x87, 0xF7, 0xFC, 0x6D), + MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xBE, 0x7F, 0x3F, 0x7A, 0x2B, 0xD7, 0x13), + MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0x32, 0xF2, 0x2D, 0x94, 0x6D, 0x42, 0xFD), + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x9A, 0xE3, 0x5F, 0x42, 0xBB, 0x84, 0xED), +}; +static const mbedtls_mpi_uint secp256r1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x95, 0x29, 0x73, 0xA1, 0x67, 0x3E, 0x02), + MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x30, 0x54, 0x35, 0x8E, 0x0A, 0xDD, 0x67), + MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xD7, 0xA1, 0x97, 0x61, 0x3B, 0xF8, 0x0C), + MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x33, 0x3C, 0x58, 0x55, 0x34, 0x23, 0xA3), +}; +static const mbedtls_mpi_uint secp256r1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x5D, 0x16, 0x5F, 0x7B, 0xBC, 0xBB, 0xCE), + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xEE, 0x4E, 0x8A, 0xC1, 0x51, 0xCC, 0x50), + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x0D, 0x4D, 0x1B, 0x53, 0x23, 0x1D, 0xB3), + MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x2A, 0x38, 0x66, 0x52, 0x84, 0xE1, 0x95), +}; +static const mbedtls_mpi_uint secp256r1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x9B, 0x83, 0x0A, 0x81, 0x4F, 0xAD, 0xAC), + MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xFF, 0x42, 0x41, 0x6E, 0xA9, 0xA2, 0xA0), + MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xA1, 0x4F, 0x1F, 0x89, 0x82, 0xAA, 0x3E), + MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0xB8, 0x0F, 0x6B, 0x8F, 0x8C, 0xD6, 0x68), +}; +static const mbedtls_mpi_uint secp256r1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0xB3, 0xBB, 0x51, 0x69, 0xA2, 0x11, 0x93), + MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x4F, 0x0F, 0x8D, 0xBD, 0x26, 0x0F, 0xE8), + MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xCB, 0xEC, 0x6B, 0x34, 0xC3, 0x3D, 0x9D), + MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x5D, 0x1E, 0x10, 0xD5, 0x44, 0xE2, 0x54), +}; +static const mbedtls_mpi_uint secp256r1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x9E, 0xB1, 0xF1, 0x6E, 0x4C, 0xAD, 0xB3), + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xE3, 0xC2, 0x58, 0xC0, 0xFB, 0x34, 0x43), + MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x9C, 0xDF, 0x35, 0x07, 0x41, 0xBD, 0x19), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x6E, 0x10, 0xEC, 0x0E, 0xEC, 0xBB, 0xD6), +}; +static const mbedtls_mpi_uint secp256r1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xCF, 0xEF, 0x3F, 0x83, 0x1A, 0x88, 0xE8), + MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x29, 0xB5, 0xB9, 0xE0, 0xC9, 0xA3, 0xAE), + MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x46, 0x1E, 0x77, 0xCD, 0x7E, 0xB3, 0x10), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x21, 0xD0, 0xD4, 0xA3, 0x16, 0x08, 0xEE), +}; +static const mbedtls_mpi_uint secp256r1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0xCA, 0xA8, 0xB3, 0xBF, 0x29, 0x99, 0x8E), + MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xF2, 0x05, 0xC1, 0xCF, 0x5D, 0x91, 0x48), + MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x01, 0x49, 0xDB, 0x82, 0xDF, 0x5F, 0x3A), + MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x06, 0x90, 0xAD, 0xE3, 0x38, 0xA4, 0xC4), +}; +static const mbedtls_mpi_uint secp256r1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xD2, 0x3A, 0xE8, 0x03, 0xC5, 0x6D, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x35, 0xD0, 0xAE, 0x1D, 0x7A, 0x9F, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x1E, 0xD2, 0xCB, 0xAC, 0x88, 0x27, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xB9, 0x9C, 0xE0, 0x31, 0xDD, 0x99, 0x86), +}; +static const mbedtls_mpi_uint secp256r1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xF9, 0x9B, 0x32, 0x96, 0x41, 0x58, 0x38), + MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x5A, 0x2A, 0xB8, 0x96, 0x0E, 0xB2, 0x4C), + MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x78, 0x2C, 0xC7, 0x08, 0x99, 0x19, 0x24), + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x59, 0x28, 0xE9, 0x84, 0x54, 0xE6, 0x16), +}; +static const mbedtls_mpi_uint secp256r1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x38, 0x30, 0xDB, 0x70, 0x2C, 0x0A, 0xA2), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x5C, 0x9D, 0xE9, 0xD5, 0x46, 0x0B, 0x5F), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x0B, 0x60, 0x4B, 0x37, 0x7D, 0xB9, 0xC9), + MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x24, 0xF3, 0x3D, 0x79, 0x7F, 0x6C, 0x18), +}; +static const mbedtls_mpi_uint secp256r1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x7F, 0xE5, 0x1C, 0x4F, 0x60, 0x24, 0xF7, 0x2A), + MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xD8, 0xE2, 0x91, 0x7F, 0x89, 0x49, 0x92), + MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0xA7, 0x2E, 0x8D, 0x6A, 0xB3, 0x39, 0x81), + MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x89, 0xB5, 0x9A, 0xB8, 0x8D, 0x42, 0x9C), +}; +static const mbedtls_mpi_uint secp256r1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0x45, 0xE6, 0x4B, 0x3F, 0x4F, 0x1E, 0x1F), + MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x65, 0x5E, 0x59, 0x22, 0xCC, 0x72, 0x5F), + MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x93, 0x1A, 0x27, 0x1E, 0x34, 0xC5, 0x5B), + MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0xF2, 0xA5, 0x58, 0x5C, 0x15, 0x2E, 0xC6), +}; +static const mbedtls_mpi_uint secp256r1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x7F, 0xBA, 0x58, 0x5A, 0x84, 0x6F, 0x5F), + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xA6, 0x36, 0x7E, 0xDC, 0xF7, 0xE1, 0x67), + MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x4D, 0xAA, 0xEE, 0x57, 0x76, 0x3A, 0xD3), + MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x7E, 0x26, 0x18, 0x22, 0x23, 0x9F, 0xFF), +}; +static const mbedtls_mpi_uint secp256r1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x4C, 0x64, 0xC7, 0x55, 0x02, 0x3F, 0xE3), + MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x02, 0x90, 0xBB, 0xC3, 0xEC, 0x30, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x6F, 0x64, 0xF4, 0x16, 0x69, 0x48, 0xA4), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x44, 0x9C, 0x95, 0x0C, 0x7D, 0x67, 0x5E), +}; +static const mbedtls_mpi_uint secp256r1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0x91, 0x8B, 0xD8, 0xD0, 0xD7, 0xE7, 0xE2), + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xF9, 0x48, 0x62, 0x6F, 0xA8, 0x93, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x3A, 0x99, 0x02, 0xD5, 0x0B, 0x3D, 0xE3), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xD3, 0x00, 0x31, 0xE6, 0x0C, 0x9F, 0x44), +}; +static const mbedtls_mpi_uint secp256r1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xB2, 0xAA, 0xFD, 0x88, 0x15, 0xDF, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0x35, 0x27, 0x31, 0x44, 0xCD, 0xC0, 0x68), + MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xF8, 0x91, 0xA5, 0x71, 0x94, 0x84, 0x2A), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xCB, 0xD0, 0x93, 0xE9, 0x88, 0xDA, 0xE4), +}; +static const mbedtls_mpi_uint secp256r1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xC6, 0x39, 0x16, 0x5D, 0xA3, 0x1E, 0x6D), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x07, 0x37, 0x26, 0x36, 0x2A, 0xFE, 0x60), + MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xBC, 0xF3, 0xD0, 0xDE, 0x50, 0xFC, 0x97), + MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x2E, 0x06, 0x10, 0x15, 0x4D, 0xFA, 0xF7), +}; +static const mbedtls_mpi_uint secp256r1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x65, 0x69, 0x5B, 0x66, 0xA2, 0x75, 0x2E), + MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x16, 0x00, 0x5A, 0xB0, 0x30, 0x25, 0x1A), + MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xFB, 0x86, 0x42, 0x80, 0xC1, 0xC4, 0x76), + MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x1D, 0x83, 0x8E, 0x94, 0x01, 0x5F, 0x82), +}; +static const mbedtls_mpi_uint secp256r1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x37, 0x70, 0xEF, 0x1F, 0xA1, 0xF0, 0xDB), + MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x10, 0x5B, 0xCE, 0xC4, 0x9B, 0x6F, 0x10), + MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x11, 0x11, 0x24, 0x4F, 0x4C, 0x79, 0x61), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x3A, 0x72, 0xBC, 0xFE, 0x72, 0x58, 0x43), +}; +static const mbedtls_ecp_point secp256r1_T[16] = { + ECP_POINT_INIT_XY_Z1(secp256r1_T_0_X, secp256r1_T_0_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_1_X, secp256r1_T_1_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_2_X, secp256r1_T_2_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_3_X, secp256r1_T_3_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_4_X, secp256r1_T_4_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_5_X, secp256r1_T_5_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_6_X, secp256r1_T_6_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_7_X, secp256r1_T_7_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_8_X, secp256r1_T_8_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_9_X, secp256r1_T_9_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_10_X, secp256r1_T_10_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_11_X, secp256r1_T_11_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_12_X, secp256r1_T_12_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_13_X, secp256r1_T_13_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_14_X, secp256r1_T_14_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_15_X, secp256r1_T_15_Y), +}; +#else +#define secp256r1_T NULL +#endif + +#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), +}; +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint secp384r1_T_0_X[] = { + 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_T_0_Y[] = { + 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_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x92, 0x00, 0x2C, 0x78, 0xDB, 0x1F, 0x37), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xF3, 0xEB, 0xB7, 0x06, 0xF7, 0xB6, 0xBC), + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xBC, 0x2C, 0xCF, 0xD8, 0xED, 0x53, 0xE7), + MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x75, 0x7B, 0xA3, 0xAB, 0xC3, 0x2C, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x9D, 0x78, 0x41, 0xF6, 0x76, 0x84, 0xAC), + MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x56, 0xE8, 0x52, 0xB3, 0xCB, 0xA8, 0xBD), +}; +static const mbedtls_mpi_uint secp384r1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xF2, 0xAE, 0xA4, 0xB6, 0x89, 0x1B, 0xDA), + MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x0F, 0xCE, 0x1C, 0x7C, 0xF6, 0x50, 0x4C), + MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0xEB, 0x90, 0xE6, 0x4D, 0xC7, 0xD4, 0x7A), + MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x49, 0x2D, 0x8A, 0x01, 0x99, 0x60, 0x94), + MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x80, 0x9B, 0x9B, 0x6A, 0xB0, 0x07, 0xD9), + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xA2, 0xEE, 0x59, 0xBE, 0x95, 0xBC, 0x23), +}; +static const mbedtls_mpi_uint secp384r1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x9D, 0x56, 0xAE, 0x59, 0xFB, 0x1F, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xAC, 0x91, 0x80, 0x87, 0xA8, 0x6E, 0x58), + MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x08, 0xA7, 0x08, 0x94, 0x32, 0xFC, 0x67), + MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x29, 0x9E, 0x84, 0xF4, 0xE5, 0x6E, 0x7E), + MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x21, 0xB9, 0x50, 0x24, 0xF8, 0x9C, 0xC7), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x04, 0x01, 0xC2, 0xFB, 0x77, 0x3E, 0xDE), +}; +static const mbedtls_mpi_uint secp384r1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x38, 0xEE, 0xE3, 0xC7, 0x9D, 0xEC, 0xA6), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x88, 0xCF, 0x43, 0xFA, 0x92, 0x5E, 0x8E), + MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xCA, 0x43, 0xF8, 0x3B, 0x49, 0x7E, 0x75), + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xE7, 0xEB, 0x17, 0x45, 0x86, 0xC2, 0xE1), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x69, 0x57, 0x32, 0xE0, 0x9C, 0xD1, 0x00), + MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x10, 0xB8, 0x4D, 0xB8, 0xF4, 0x0D, 0xE3), +}; +static const mbedtls_mpi_uint secp384r1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0xDC, 0x9A, 0xB2, 0x79, 0x39, 0x27, 0x16), + MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x71, 0xE4, 0x3B, 0x4D, 0x60, 0x0C, 0xA3), + MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xBD, 0x19, 0x40, 0xFA, 0x19, 0x2A, 0x5A), + MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xF8, 0x1E, 0x43, 0xA1, 0x50, 0x8D, 0xEF), + MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x18, 0x7C, 0x41, 0xFA, 0x7C, 0x1B, 0x58), + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x59, 0x24, 0xC4, 0xE9, 0xB7, 0xD3, 0xAD), +}; +static const mbedtls_mpi_uint secp384r1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x01, 0x3D, 0x63, 0x54, 0x45, 0x6F, 0xB7), + MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xB2, 0x19, 0xA3, 0x86, 0x1D, 0x42, 0x34), + MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x02, 0x87, 0x18, 0x92, 0x52, 0x1A, 0x71), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x18, 0xB1, 0x5D, 0x18, 0x1B, 0x37, 0xFE), + MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x74, 0x61, 0xBA, 0x18, 0xAF, 0x40, 0x30), + MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x7D, 0x3C, 0x52, 0x0F, 0x07, 0xB0, 0x6F), +}; +static const mbedtls_mpi_uint secp384r1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x39, 0x13, 0xAA, 0x60, 0x15, 0x99, 0x30), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x00, 0xCB, 0xC6, 0xB1, 0xDB, 0x97, 0x90), + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xFA, 0x60, 0xB8, 0x24, 0xE4, 0x7D, 0xD3), + MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x75, 0xB3, 0x70, 0xB2, 0x83, 0xB1, 0x9B), + MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xE3, 0x6C, 0xCD, 0x33, 0x62, 0x7A, 0x56), + MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x30, 0xDC, 0x0F, 0x9F, 0xBB, 0xB8, 0xAA), +}; +static const mbedtls_mpi_uint secp384r1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xD5, 0x0A, 0x60, 0x81, 0xB9, 0xC5, 0x16), + MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0xAA, 0x2F, 0xD6, 0xF2, 0x73, 0xDF, 0xEB), + MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x7B, 0x74, 0xC9, 0xB3, 0x5B, 0x95, 0x6D), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x04, 0xEB, 0x15, 0xC8, 0x5F, 0x00, 0xF6), + MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x50, 0x20, 0x28, 0xD1, 0x01, 0xAF, 0xF0), + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x6D, 0x4F, 0x31, 0x81, 0x2F, 0x94, 0x48), +}; +static const mbedtls_mpi_uint secp384r1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x2F, 0xD8, 0xB6, 0x63, 0x7C, 0xE9, 0x50), + MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x8C, 0xB9, 0x14, 0xD9, 0x37, 0x63, 0xDE), + MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x02, 0xB8, 0x46, 0xAD, 0xCE, 0x7B, 0x38), + MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x47, 0x2D, 0x66, 0xA7, 0xE9, 0x33, 0x23), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xF9, 0x93, 0x94, 0xA8, 0x48, 0xB3, 0x4F), + MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x4A, 0xAC, 0x51, 0x08, 0x72, 0x2F, 0x1A), +}; +static const mbedtls_mpi_uint secp384r1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0xAD, 0xA0, 0xF9, 0x81, 0xE1, 0x78, 0x97), + MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x9A, 0x63, 0xD8, 0xBA, 0x79, 0x1A, 0x17), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x31, 0x7B, 0x7A, 0x5A, 0x5D, 0x7D, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x96, 0x12, 0x4B, 0x19, 0x09, 0xE0, 0xB7), + MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x8A, 0x57, 0xEE, 0x4E, 0x6E, 0x7E, 0xEC), + MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x9D, 0x69, 0xDC, 0xB3, 0xDA, 0xD8, 0x08), +}; +static const mbedtls_mpi_uint secp384r1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x49, 0x03, 0x03, 0x33, 0x6F, 0x28, 0x4A), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xDB, 0xA7, 0x05, 0x8C, 0xF3, 0x4D, 0xFB), + MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x92, 0xB1, 0xA8, 0xEC, 0x0D, 0x64, 0x3B), + MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0xFC, 0xFD, 0xD0, 0x4B, 0x88, 0x1B, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x9C, 0x51, 0x69, 0xCE, 0x71, 0x73, 0xF5), + MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x5A, 0x14, 0x23, 0x1A, 0x46, 0x63, 0x5F), +}; +static const mbedtls_mpi_uint secp384r1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x4C, 0x70, 0x44, 0x18, 0xCD, 0xEF, 0xED), + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x49, 0xDD, 0x64, 0x7E, 0x7E, 0x4D, 0x92), + MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x32, 0x7C, 0x09, 0xD0, 0x3F, 0xD6, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xE0, 0x4F, 0x65, 0x0C, 0x7A, 0x54, 0x3E), + MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xFA, 0xFB, 0x4A, 0xB4, 0x79, 0x5A, 0x8C), + MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x5D, 0x1B, 0x2B, 0xDA, 0xBC, 0x9A, 0x74), +}; +static const mbedtls_mpi_uint secp384r1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xAC, 0x56, 0xF7, 0x5F, 0x51, 0x68, 0x0B), + MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xE0, 0x1D, 0xBC, 0x13, 0x4E, 0xAC, 0x03), + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xF5, 0xC5, 0xE6, 0xD2, 0x88, 0xBA, 0xCB), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x0E, 0x28, 0x23, 0x58, 0x67, 0xFA, 0xEE), + MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x80, 0x4B, 0xD8, 0xC4, 0xDF, 0x15, 0xE4), + MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x0E, 0x58, 0xE6, 0x2C, 0x59, 0xC2, 0x03), +}; +static const mbedtls_mpi_uint secp384r1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x26, 0x27, 0x99, 0x16, 0x2B, 0x22, 0x0B), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xF3, 0x8F, 0xC3, 0x2A, 0x9B, 0xFC, 0x38), + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x2E, 0x83, 0x3D, 0xFE, 0x9E, 0x3C, 0x1B), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x57, 0xCD, 0x2D, 0xC1, 0x49, 0x38, 0xB5), + MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x42, 0x8B, 0x33, 0x89, 0x1F, 0xEA, 0x01), + MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x1D, 0x13, 0xD7, 0x50, 0xBB, 0x3E, 0xEB), +}; +static const mbedtls_mpi_uint secp384r1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x9A, 0x52, 0xD2, 0x54, 0x7C, 0x97, 0xF2), + MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x33, 0x6E, 0xED, 0xD9, 0x87, 0x50, 0xC5), + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x35, 0x7E, 0x16, 0x40, 0x15, 0x83, 0xB8), + MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x2B, 0xA4, 0xAB, 0x03, 0x91, 0xEA, 0xFE), + MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x47, 0x39, 0xEF, 0x05, 0x59, 0xD0, 0x90), + MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x24, 0x0D, 0x76, 0x11, 0x53, 0x08, 0xAF), +}; +static const mbedtls_mpi_uint secp384r1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x2F, 0xDD, 0xBD, 0x50, 0x48, 0xB1, 0xE5), + MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x1C, 0x84, 0x55, 0x78, 0x14, 0xEB, 0xF6), + MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x5E, 0x3E, 0xA6, 0xAF, 0xF6, 0xC7, 0x04), + MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x11, 0xE2, 0x65, 0xCA, 0x41, 0x95, 0x3B), + MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x83, 0xD8, 0xE6, 0x4D, 0x22, 0x06, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x7F, 0x25, 0x2A, 0xAA, 0x28, 0x46, 0x97), +}; +static const mbedtls_mpi_uint secp384r1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xDB, 0x15, 0x56, 0x84, 0xCB, 0xC0, 0x56), + MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xDB, 0x0E, 0x08, 0xC9, 0xF5, 0xD4, 0x9E), + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x62, 0xD0, 0x1A, 0x7C, 0x13, 0xD5, 0x07), + MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xAD, 0x53, 0xE0, 0x32, 0x21, 0xA0, 0xC0), + MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x38, 0x81, 0x21, 0x23, 0x0E, 0xD2, 0xBB), + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x51, 0x05, 0xD0, 0x1E, 0x82, 0xA9, 0x71), +}; +static const mbedtls_mpi_uint secp384r1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xC3, 0x27, 0xBF, 0xC6, 0xAA, 0xB7, 0xB9), + MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x65, 0x45, 0xDF, 0xB9, 0x46, 0x17, 0x46), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x38, 0x3F, 0xB2, 0xB1, 0x5D, 0xCA, 0x1C), + MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x29, 0x6C, 0x63, 0xE9, 0xD7, 0x48, 0xB8), + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xF1, 0xD7, 0x99, 0x8C, 0xC2, 0x05, 0x99), + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xE6, 0x5E, 0x82, 0x6D, 0xE5, 0x7E, 0xD5), +}; +static const mbedtls_mpi_uint secp384r1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x61, 0xFA, 0x7D, 0x01, 0xDB, 0xB6, 0x63), + MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xC6, 0x58, 0x39, 0xF4, 0xC6, 0x82, 0x23), + MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x5A, 0x7A, 0x80, 0x08, 0xCD, 0xAA, 0xD8), + MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x8C, 0xC6, 0x3F, 0x3C, 0xA5, 0x68, 0xF4), + MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xF5, 0xD5, 0x17, 0xAE, 0x36, 0xD8, 0x8A), + MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xAD, 0x92, 0xC5, 0x57, 0x6C, 0xDA, 0x91), +}; +static const mbedtls_mpi_uint secp384r1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x67, 0x17, 0xC0, 0x40, 0x78, 0x8C, 0x84), + MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x9F, 0xF4, 0xAA, 0xDA, 0x5C, 0x7E, 0xB2), + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xDB, 0x42, 0x3E, 0x72, 0x64, 0xA0, 0x67), + MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xF9, 0x41, 0x17, 0x43, 0xE3, 0xE8, 0xA8), + MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xDD, 0xCC, 0x43, 0x7E, 0x16, 0x05, 0x03), + MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x4B, 0xCF, 0x48, 0x8F, 0x41, 0x90, 0xE5), +}; +static const mbedtls_mpi_uint secp384r1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x0C, 0x6B, 0x9D, 0x22, 0x04, 0xBC, 0x5C), + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x63, 0x79, 0x2F, 0x6A, 0x0E, 0x8A, 0xDE), + MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x67, 0x3F, 0x02, 0xB8, 0x91, 0x7F, 0x74), + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x14, 0x64, 0xA0, 0x33, 0xF4, 0x6B, 0x50), + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x44, 0x71, 0x87, 0xB8, 0x88, 0x3F, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x2B, 0x85, 0x05, 0xC5, 0x44, 0x53, 0x15), +}; +static const mbedtls_mpi_uint secp384r1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x2B, 0xFE, 0xD1, 0x1C, 0x73, 0xE3, 0x2E), + MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x33, 0xA1, 0xD3, 0x69, 0x1C, 0x9D, 0xD2), + MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x5A, 0xBA, 0xB6, 0xAE, 0x1B, 0x94, 0x04), + MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x74, 0x90, 0x5C, 0x57, 0xB0, 0x3A, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x2F, 0x93, 0x20, 0x24, 0x54, 0x1D, 0x8D), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x78, 0x9D, 0x71, 0x67, 0x5D, 0x49, 0x98), +}; +static const mbedtls_mpi_uint secp384r1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0xC8, 0x0E, 0x11, 0x8D, 0xE0, 0x8F, 0x69), + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x7F, 0x79, 0x6C, 0x5F, 0xB7, 0xBC, 0xB1), + MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xE1, 0x83, 0x3C, 0x12, 0xBB, 0xEE, 0x96), + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xC2, 0xC4, 0x1B, 0x41, 0x71, 0xB9, 0x17), + MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0xEE, 0xBB, 0x1D, 0x89, 0x50, 0x88, 0xF2), + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x1C, 0x55, 0x74, 0xEB, 0xDE, 0x92, 0x3F), +}; +static const mbedtls_mpi_uint secp384r1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x38, 0x92, 0x06, 0x19, 0xD0, 0xB3, 0xB2), + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x99, 0x26, 0xA3, 0x5F, 0xE2, 0xC1, 0x81), + MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0xFC, 0xFD, 0xC3, 0xB6, 0x26, 0x24, 0x8F), + MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xAD, 0xE7, 0x49, 0xB7, 0x64, 0x4B, 0x96), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x4E, 0x95, 0xAD, 0x07, 0xFE, 0xB6, 0x30), + MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x15, 0xE7, 0x2D, 0x19, 0xA9, 0x08, 0x10), +}; +static const mbedtls_mpi_uint secp384r1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xBD, 0xAC, 0x0A, 0x3F, 0x6B, 0xFF, 0xFA), + MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xE4, 0x74, 0x14, 0xD9, 0x70, 0x1D, 0x71), + MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xB0, 0x71, 0xBB, 0xD8, 0x18, 0x96, 0x2B), + MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0xB8, 0x19, 0x90, 0x80, 0xB5, 0xEE, 0x01), + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x21, 0x20, 0xA6, 0x17, 0x48, 0x03, 0x6F), + MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x1D, 0xBB, 0x6D, 0x94, 0x20, 0x34, 0xF1), +}; +static const mbedtls_mpi_uint secp384r1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x82, 0x67, 0x4B, 0x8E, 0x4E, 0xBE, 0xE2), + MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xDA, 0x77, 0xF8, 0x23, 0x55, 0x2B, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x02, 0xDE, 0x25, 0x35, 0x2D, 0x74, 0x51), + MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x0C, 0xB8, 0x0B, 0x39, 0xBA, 0xAD, 0x04), + MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0x0E, 0x28, 0x4D, 0xE1, 0x3D, 0xE4, 0x1B), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xEC, 0x0A, 0xD4, 0xB8, 0xC4, 0x8D, 0xB0), +}; +static const mbedtls_mpi_uint secp384r1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x68, 0xCE, 0xC2, 0x55, 0x4D, 0x0C, 0x6D), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x20, 0x93, 0x32, 0x90, 0xD6, 0xAE, 0x47), + MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x78, 0xAB, 0x43, 0x9E, 0xEB, 0x73, 0xAE), + MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x97, 0xC3, 0x83, 0xA6, 0x3C, 0xF1, 0xBF), + MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0x25, 0x25, 0x66, 0x08, 0x26, 0xFA, 0x4B), + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xFB, 0x44, 0x5D, 0x82, 0xEC, 0x3B, 0xAC), +}; +static const mbedtls_mpi_uint secp384r1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x90, 0xEA, 0xB5, 0x04, 0x99, 0xD0, 0x69), + MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0xF2, 0x22, 0xA0, 0xEB, 0xFD, 0x45, 0x87), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xA4, 0x81, 0x32, 0xFC, 0xFA, 0xEE, 0x5B), + MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xBB, 0xA4, 0x6A, 0x77, 0x41, 0x5C, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x1E, 0xAA, 0x4F, 0xF0, 0x10, 0xB3, 0x50), + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x74, 0x13, 0x14, 0x9E, 0x90, 0xD7, 0xE6), +}; +static const mbedtls_mpi_uint secp384r1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0xBD, 0x70, 0x4F, 0xA8, 0xD1, 0x06, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x4E, 0x2E, 0x68, 0xFC, 0x35, 0xFA, 0x50), + MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x53, 0x75, 0xED, 0xF2, 0x5F, 0xC2, 0xEB), + MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x87, 0x6B, 0x9F, 0x05, 0xE2, 0x22, 0x93), + MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x1A, 0xA8, 0xB7, 0x03, 0x9E, 0x6D, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0xD0, 0x69, 0x88, 0xA8, 0x39, 0x9E, 0x3A), +}; +static const mbedtls_mpi_uint secp384r1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xEF, 0x68, 0xFE, 0xEC, 0x24, 0x08, 0x15), + MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x06, 0x4B, 0x92, 0x0D, 0xB7, 0x34, 0x74), + MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xF4, 0xDD, 0x1A, 0xA0, 0x4A, 0xE4, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x63, 0x4F, 0x4F, 0xCE, 0xBB, 0xD6, 0xD3), + MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xEE, 0x8D, 0xDF, 0x3F, 0x73, 0xB7, 0xAC), + MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x06, 0xB6, 0x80, 0x4D, 0x81, 0xD9, 0x53), +}; +static const mbedtls_mpi_uint secp384r1_T_16_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0xF5, 0x13, 0xDF, 0x13, 0x19, 0x97, 0x94), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xF9, 0xB3, 0x33, 0x66, 0x82, 0x21, 0xFE), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xFC, 0x39, 0x16, 0x23, 0x43, 0x76, 0x0E), + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x48, 0x25, 0xA1, 0x64, 0x95, 0x1C, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0xAC, 0x15, 0x57, 0xD9, 0xDE, 0xA0, 0x28), + MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x5F, 0xB8, 0x3D, 0x48, 0x91, 0x24, 0xCC), +}; +static const mbedtls_mpi_uint secp384r1_T_16_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xF2, 0xC8, 0x54, 0xD1, 0x32, 0xBD, 0xC4), + MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x3B, 0xF0, 0xAA, 0x9D, 0xD8, 0xF4, 0x20), + MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0xC3, 0xBB, 0x6C, 0x66, 0xAC, 0x25, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x25, 0x10, 0xB2, 0xE1, 0x41, 0xDE, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xE8, 0x30, 0xB8, 0x37, 0xBC, 0x2A, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x57, 0x01, 0x4A, 0x1E, 0x78, 0x9F, 0x85), +}; +static const mbedtls_mpi_uint secp384r1_T_17_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x19, 0xCD, 0x12, 0x0B, 0x51, 0x4F, 0x56), + MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x4B, 0x3D, 0x24, 0xA4, 0x16, 0x59, 0x05), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xEB, 0xD3, 0x59, 0x2E, 0x75, 0x7C, 0x01), + MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xB9, 0xB4, 0xA5, 0xD9, 0x2E, 0x29, 0x4C), + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x16, 0x05, 0x75, 0x02, 0xB3, 0x06, 0xEE), + MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x7C, 0x9F, 0x79, 0x91, 0xF1, 0x4F, 0x23), +}; +static const mbedtls_mpi_uint secp384r1_T_17_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x98, 0x7C, 0x84, 0xE1, 0xFF, 0x30, 0x77), + MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0xE2, 0xC2, 0x5F, 0x55, 0x40, 0xBD, 0xCD), + MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x65, 0x87, 0x3F, 0xC4, 0xC2, 0x24, 0x57), + MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0x30, 0x0A, 0x60, 0x15, 0xD1, 0x24, 0x48), + MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x99, 0xD9, 0xB6, 0xAE, 0xB1, 0xAF, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x80, 0xEE, 0xA2, 0x0F, 0x74, 0xB9, 0xF3), +}; +static const mbedtls_mpi_uint secp384r1_T_18_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xE6, 0x0F, 0x37, 0xC1, 0x10, 0x99, 0x1E), + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xAD, 0x9D, 0x5D, 0x80, 0x01, 0xA6, 0xFE), + MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x0F, 0x10, 0x2A, 0x9D, 0x20, 0x38, 0xEB), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x60, 0xCB, 0xCE, 0x5A, 0xA0, 0xA7, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xCF, 0x14, 0xDF, 0xBF, 0xE5, 0x74, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x12, 0x1A, 0xDD, 0x59, 0x02, 0x5D, 0xC6), +}; +static const mbedtls_mpi_uint secp384r1_T_18_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xC9, 0xF8, 0xF5, 0xB6, 0x13, 0x4D, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x45, 0xB1, 0x93, 0xB3, 0xA2, 0x79, 0xDC), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xF6, 0xCF, 0xF7, 0xE6, 0x29, 0x9C, 0xCC), + MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x50, 0x65, 0x80, 0xBC, 0x59, 0x0A, 0x59), + MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xF0, 0x24, 0x35, 0xA2, 0x46, 0xF0, 0x0C), + MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x26, 0xC0, 0x9D, 0x61, 0x56, 0x62, 0x67), +}; +static const mbedtls_mpi_uint secp384r1_T_19_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xBB, 0xC2, 0x24, 0x43, 0x2E, 0x37, 0x54), + MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xF7, 0xCE, 0x35, 0xFC, 0x77, 0xF3, 0x3F), + MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x34, 0x96, 0xD5, 0x4A, 0x76, 0x9D, 0x6B), + MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x3B, 0x0F, 0xEA, 0xA8, 0x12, 0x0B, 0x22), + MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x3F, 0x5D, 0x2D, 0x1C, 0xD4, 0x9E, 0xFB), + MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x2E, 0xDD, 0xC7, 0x6E, 0xAB, 0xAF, 0xDC), +}; +static const mbedtls_mpi_uint secp384r1_T_19_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xB2, 0x7B, 0x0C, 0x9A, 0x83, 0x8E, 0x59), + MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x51, 0x90, 0x92, 0x79, 0x32, 0x19, 0xC3), + MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x89, 0xF9, 0xD0, 0xCF, 0x2C, 0xA5, 0x8F), + MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x50, 0x21, 0xDE, 0x50, 0x41, 0x9D, 0x81), + MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x7D, 0x2B, 0x9E, 0x9D, 0x95, 0xA8, 0xE3), + MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA5, 0x20, 0x87, 0x88, 0x97, 0x5F, 0xAA), +}; +static const mbedtls_mpi_uint secp384r1_T_20_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x59, 0xB4, 0x66, 0x7E, 0xE8, 0x5A, 0x60), + MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x5C, 0x7E, 0xB2, 0xAD, 0xD9, 0xC9, 0xDA), + MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x97, 0x49, 0xA3, 0x13, 0x83, 0x07, 0x2E), + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x26, 0xC7, 0x13, 0x35, 0x0D, 0xB0, 0x6B), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x60, 0xAB, 0xFA, 0x4B, 0x93, 0x18, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x2D, 0x1C, 0x31, 0x4C, 0xE4, 0x61, 0xAE), +}; +static const mbedtls_mpi_uint secp384r1_T_20_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0x4D, 0x1E, 0x51, 0x59, 0x6E, 0x91, 0xC5), + MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x54, 0x4D, 0x51, 0xED, 0x36, 0xCC, 0x60), + MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xA8, 0x56, 0xC7, 0x78, 0x27, 0x33, 0xC5), + MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xB7, 0x95, 0xC9, 0x8B, 0xC8, 0x6A, 0xBC), + MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xE9, 0x13, 0x96, 0xB3, 0xE1, 0xF9, 0xEE), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x46, 0xB0, 0x5E, 0xC3, 0x94, 0x03, 0x05), +}; +static const mbedtls_mpi_uint secp384r1_T_21_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x5B, 0x29, 0x30, 0x41, 0x1A, 0x9E, 0xB6), + MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xCA, 0x83, 0x31, 0x5B, 0xA7, 0xCB, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x41, 0x50, 0x44, 0x4D, 0x64, 0x31, 0x89), + MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0x84, 0xC2, 0x5D, 0x97, 0xA5, 0x3C, 0x18), + MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x0F, 0xA5, 0xFD, 0x8E, 0x5A, 0x47, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x58, 0x02, 0x2D, 0x40, 0xB1, 0x0B, 0xBA), +}; +static const mbedtls_mpi_uint secp384r1_T_21_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x33, 0x8C, 0x67, 0xCE, 0x23, 0x43, 0x99), + MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x53, 0x47, 0x72, 0x44, 0x1F, 0x5B, 0x2A), + MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xC1, 0xD9, 0xA4, 0x50, 0x88, 0x63, 0x18), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xF2, 0x75, 0x69, 0x73, 0x00, 0xC4, 0x31), + MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x90, 0x1D, 0xDF, 0x1A, 0x00, 0xD8, 0x69), + MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0xB1, 0x89, 0x48, 0xA8, 0x70, 0x62, 0xEF), +}; +static const mbedtls_mpi_uint secp384r1_T_22_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x8A, 0x55, 0x50, 0x7B, 0xEF, 0x8A, 0x3C), + MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x1B, 0x23, 0x48, 0x23, 0x63, 0x91, 0xB6), + MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x04, 0x54, 0x3C, 0x24, 0x9B, 0xC7, 0x9A), + MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x38, 0xC3, 0x84, 0xFB, 0xFF, 0x9F, 0x49), + MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x2A, 0xE0, 0x6D, 0x68, 0x8A, 0x5C, 0xCB), + MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x93, 0x53, 0x85, 0xA1, 0x0D, 0xAF, 0x63), +}; +static const mbedtls_mpi_uint secp384r1_T_22_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x88, 0x95, 0x4C, 0x0B, 0xD0, 0x06, 0x51), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xAF, 0x8D, 0x49, 0xA2, 0xC8, 0xB4, 0xE0), + MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x76, 0x53, 0x09, 0x88, 0x43, 0x87, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xA4, 0x77, 0x3F, 0x5E, 0x21, 0xB4, 0x0A), + MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x9E, 0x86, 0x64, 0xCC, 0x91, 0xC1, 0x77), + MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x17, 0x56, 0xCB, 0xC3, 0x7D, 0x5B, 0xB1), +}; +static const mbedtls_mpi_uint secp384r1_T_23_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x74, 0x9F, 0xB5, 0x91, 0x21, 0xB1, 0x1C), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xED, 0xE1, 0x11, 0xEF, 0x45, 0xAF, 0xC1), + MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x31, 0xBE, 0xB2, 0xBC, 0x72, 0x65, 0x1F), + MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x4B, 0x8C, 0x77, 0xCE, 0x1E, 0x42, 0xB5), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xC9, 0xAA, 0xB9, 0xD9, 0x86, 0x99, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x23, 0x80, 0xC6, 0x4E, 0x35, 0x0B, 0x6D), +}; +static const mbedtls_mpi_uint secp384r1_T_23_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xD8, 0xA2, 0x0A, 0x39, 0x32, 0x1D, 0x23), + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xC8, 0x86, 0xF1, 0x12, 0x9A, 0x4A, 0x05), + MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xF1, 0x7C, 0xAA, 0x70, 0x8E, 0xBC, 0x01), + MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x01, 0x47, 0x8F, 0xDD, 0x8B, 0xA5, 0xC8), + MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x08, 0x21, 0xF4, 0xAB, 0xC7, 0xF5, 0x96), + MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x76, 0xA5, 0x95, 0xC4, 0x0F, 0x88, 0x1D), +}; +static const mbedtls_mpi_uint secp384r1_T_24_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x42, 0x2A, 0x52, 0xCD, 0x75, 0x51, 0x49), + MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x36, 0xE5, 0x04, 0x2B, 0x44, 0xC6, 0xEF), + MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xEE, 0x16, 0x13, 0x07, 0x83, 0xB5, 0x30), + MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x59, 0xC6, 0xA2, 0x19, 0x05, 0xD3, 0xC6), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x8B, 0xA8, 0x16, 0x09, 0xB7, 0xEA, 0xD6), + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xEE, 0x14, 0xAF, 0xB5, 0xFD, 0xD0, 0xEF), +}; +static const mbedtls_mpi_uint secp384r1_T_24_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x7C, 0xCA, 0x71, 0x3E, 0x6E, 0x66, 0x75), + MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x31, 0x0E, 0x3F, 0xE5, 0x91, 0xC4, 0x7F), + MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x3D, 0xC2, 0x3E, 0x95, 0x37, 0x58, 0x2B), + MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x1F, 0x02, 0x03, 0xF3, 0xEF, 0xEE, 0x66), + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x5B, 0x1A, 0xFC, 0x38, 0xCD, 0xE8, 0x24), + MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x57, 0x42, 0x85, 0xC6, 0x21, 0x68, 0x71), +}; +static const mbedtls_mpi_uint secp384r1_T_25_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xA2, 0x4A, 0x66, 0xB1, 0x0A, 0xE6, 0xC0), + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x0C, 0x94, 0x9D, 0x5E, 0x99, 0xB2, 0xCE), + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x03, 0x40, 0xCA, 0xB2, 0xB3, 0x30, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x78, 0x48, 0x27, 0x34, 0x1E, 0xE2, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x72, 0x5B, 0xAC, 0xC1, 0x6D, 0xE3, 0x82), + MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xAB, 0x46, 0xCB, 0xEA, 0x5E, 0x4B, 0x0B), +}; +static const mbedtls_mpi_uint secp384r1_T_25_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x08, 0xAD, 0x4E, 0x51, 0x9F, 0x2A, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x5C, 0x7D, 0x4C, 0xD6, 0xCF, 0xDD, 0x02), + MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x76, 0x26, 0xE0, 0x8B, 0x10, 0xD9, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0xA7, 0x23, 0x4E, 0x5F, 0xD2, 0x42, 0x17), + MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xE5, 0xA4, 0xEC, 0x77, 0x21, 0x34, 0x28), + MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x14, 0x65, 0xEA, 0x4A, 0x85, 0xC3, 0x2F), +}; +static const mbedtls_mpi_uint secp384r1_T_26_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0xD8, 0x40, 0x27, 0x73, 0x15, 0x7E, 0x65), + MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xBB, 0x53, 0x7E, 0x0F, 0x40, 0xC8, 0xD4), + MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x37, 0x19, 0x73, 0xEF, 0x5A, 0x5E, 0x04), + MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x73, 0x2B, 0x49, 0x7E, 0xAC, 0x97, 0x5C), + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0xB2, 0xC3, 0x1E, 0x0E, 0xE7, 0xD2, 0x21), + MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x08, 0xD6, 0xDD, 0xAC, 0x21, 0xD6, 0x3E), +}; +static const mbedtls_mpi_uint secp384r1_T_26_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x26, 0xBE, 0x6D, 0x6D, 0xF2, 0x38, 0x3F), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x6C, 0x31, 0xA7, 0x49, 0x50, 0x3A, 0x89), + MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x99, 0xC6, 0xF5, 0xD2, 0xC2, 0x30, 0x5A), + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xE4, 0xF6, 0x8B, 0x8B, 0x97, 0xE9, 0xB2), + MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x21, 0xB7, 0x0D, 0xFC, 0x15, 0x54, 0x0B), + MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x83, 0x1C, 0xA4, 0xCD, 0x6B, 0x9D, 0xF2), +}; +static const mbedtls_mpi_uint secp384r1_T_27_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xE8, 0x4C, 0x48, 0xE4, 0xAA, 0x69, 0x93), + MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x7A, 0x27, 0xFC, 0x37, 0x96, 0x1A, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0xE7, 0x30, 0xA5, 0xCF, 0x13, 0x46, 0x5C), + MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xD8, 0xAF, 0x74, 0x23, 0x4D, 0x56, 0x84), + MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x3D, 0x44, 0x14, 0x1B, 0x97, 0x83, 0xF0), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x47, 0xD7, 0x5F, 0xFD, 0x98, 0x38, 0xF7), +}; +static const mbedtls_mpi_uint secp384r1_T_27_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x73, 0x64, 0x36, 0xFD, 0x7B, 0xC1, 0x15), + MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x5D, 0x32, 0xD2, 0x47, 0x94, 0x89, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xE9, 0x30, 0xAC, 0x06, 0xC8, 0x65, 0x04), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x6C, 0xB9, 0x1B, 0xF7, 0x61, 0x49, 0x53), + MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0xFF, 0x32, 0x43, 0x80, 0xDA, 0xA6, 0xB1), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xF8, 0x04, 0x01, 0x95, 0x35, 0xCE, 0x21), +}; +static const mbedtls_mpi_uint secp384r1_T_28_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x06, 0x46, 0x0D, 0x51, 0xE2, 0xD8, 0xAC), + MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x57, 0x1D, 0x6F, 0x79, 0xA0, 0xCD, 0xA6), + MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0xFB, 0x36, 0xCA, 0xAD, 0xF5, 0x9E, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x7A, 0x1D, 0x9E, 0x1D, 0x95, 0x48, 0xDC), + MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x26, 0xA5, 0xB7, 0x15, 0x2C, 0xC2, 0xC6), + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x42, 0x72, 0xAA, 0x11, 0xDC, 0xC9, 0xB6), +}; +static const mbedtls_mpi_uint secp384r1_T_28_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x6C, 0x64, 0xA7, 0x62, 0x3C, 0xAB, 0xD4), + MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x6A, 0x44, 0xD8, 0x60, 0xC0, 0xA8, 0x80), + MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x76, 0x58, 0x12, 0x57, 0x3C, 0x89, 0x46), + MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x4F, 0x83, 0xCE, 0xCB, 0xB8, 0xD0, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x84, 0x04, 0xB0, 0xAD, 0xEB, 0xFA, 0xDF), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xA4, 0xC3, 0x41, 0x44, 0x4E, 0x65, 0x3E), +}; +static const mbedtls_mpi_uint secp384r1_T_29_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x16, 0xA9, 0x1C, 0xE7, 0x65, 0x20, 0xC1), + MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x53, 0x32, 0xF8, 0xC0, 0xA6, 0xBD, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xF0, 0xE6, 0x57, 0x31, 0xCC, 0x26, 0x6F), + MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xE3, 0x54, 0x1C, 0x34, 0xD3, 0x17, 0xBC), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xAE, 0xED, 0xFB, 0xCD, 0xE7, 0x1E, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x16, 0x1C, 0x34, 0x40, 0x00, 0x1F, 0xB6), +}; +static const mbedtls_mpi_uint secp384r1_T_29_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x32, 0x00, 0xC2, 0xD4, 0x3B, 0x1A, 0x09), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xE0, 0x99, 0x8F, 0x0C, 0x4A, 0x16, 0x44), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x73, 0x18, 0x1B, 0xD4, 0x94, 0x29, 0x62), + MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xA4, 0x2D, 0xB1, 0x9D, 0x74, 0x32, 0x67), + MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0xF4, 0xB1, 0x0C, 0x37, 0x62, 0x8B, 0x66), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xFF, 0xDA, 0xE2, 0x35, 0xA3, 0xB6, 0x42), +}; +static const mbedtls_mpi_uint secp384r1_T_30_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x49, 0x99, 0x65, 0xC5, 0xED, 0x16, 0xEF), + MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x42, 0x9A, 0xF3, 0xA7, 0x4E, 0x6F, 0x2B), + MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x0A, 0x7E, 0xC0, 0xD7, 0x4E, 0x07, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x7A, 0x31, 0x69, 0xA6, 0xB9, 0x15, 0x34), + MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0xE0, 0x72, 0xA4, 0x3F, 0xB9, 0xF8, 0x0C), + MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x75, 0x32, 0x85, 0xA2, 0xDE, 0x37, 0x12), +}; +static const mbedtls_mpi_uint secp384r1_T_30_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xC0, 0x0D, 0xCF, 0x25, 0x41, 0xA4, 0xF4), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xFC, 0xB2, 0x48, 0xC3, 0x85, 0x83, 0x4B), + MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xBE, 0x0B, 0x58, 0x2D, 0x7A, 0x9A, 0x62), + MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0xF3, 0x81, 0x18, 0x1B, 0x74, 0x4F, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x43, 0xA3, 0x0A, 0x16, 0x8B, 0xA3, 0x1E), + MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x18, 0x81, 0x7B, 0x8D, 0xA2, 0x35, 0x77), +}; +static const mbedtls_mpi_uint secp384r1_T_31_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xC4, 0x3F, 0x2C, 0xE7, 0x5F, 0x99, 0x03), + MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x2B, 0xB7, 0xB6, 0xAD, 0x5A, 0x56, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x00, 0xA4, 0x48, 0xC8, 0xE8, 0xBA, 0xBF), + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xA1, 0xB5, 0x13, 0x5A, 0xCD, 0x99, 0x9C), + MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x95, 0xAD, 0xFC, 0xE2, 0x7E, 0xE7, 0xFE), + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x6B, 0xD1, 0x34, 0x99, 0x53, 0x63, 0x0B), +}; +static const mbedtls_mpi_uint secp384r1_T_31_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x8A, 0x77, 0x5D, 0x2B, 0xAB, 0x01, 0x28), + MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x85, 0xD0, 0xD5, 0x49, 0x83, 0x4D, 0x60), + MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0xC6, 0x91, 0x30, 0x3B, 0x00, 0xAF, 0x7A), + MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xAE, 0x61, 0x07, 0xE1, 0xB6, 0xE2, 0xC9), + MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x43, 0x41, 0xFE, 0x9B, 0xB6, 0xF0, 0xA5), + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x97, 0xAE, 0xAD, 0x89, 0x88, 0x9E, 0x41), +}; +static const mbedtls_ecp_point secp384r1_T[32] = { + ECP_POINT_INIT_XY_Z1(secp384r1_T_0_X, secp384r1_T_0_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_1_X, secp384r1_T_1_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_2_X, secp384r1_T_2_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_3_X, secp384r1_T_3_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_4_X, secp384r1_T_4_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_5_X, secp384r1_T_5_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_6_X, secp384r1_T_6_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_7_X, secp384r1_T_7_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_8_X, secp384r1_T_8_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_9_X, secp384r1_T_9_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_10_X, secp384r1_T_10_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_11_X, secp384r1_T_11_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_12_X, secp384r1_T_12_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_13_X, secp384r1_T_13_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_14_X, secp384r1_T_14_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_15_X, secp384r1_T_15_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_16_X, secp384r1_T_16_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_17_X, secp384r1_T_17_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_18_X, secp384r1_T_18_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_19_X, secp384r1_T_19_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_20_X, secp384r1_T_20_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_21_X, secp384r1_T_21_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_22_X, secp384r1_T_22_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_23_X, secp384r1_T_23_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_24_X, secp384r1_T_24_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_25_X, secp384r1_T_25_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_26_X, secp384r1_T_26_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_27_X, secp384r1_T_27_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_28_X, secp384r1_T_28_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_29_X, secp384r1_T_29_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_30_X, secp384r1_T_30_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_31_X, secp384r1_T_31_Y), +}; +#else +#define secp384r1_T NULL +#endif + +#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), +}; +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint secp521r1_T_0_X[] = { + 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_8(0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_0_Y[] = { + 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_8(0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xB1, 0x2D, 0xEB, 0x27, 0x2F, 0xE8, 0xDA), + MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x4B, 0x44, 0x25, 0xDB, 0x5C, 0x5F, 0x67), + MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x85, 0x28, 0x78, 0x2E, 0x75, 0x34, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x57, 0x0F, 0x73, 0x78, 0x7A, 0xE3, 0x53), + MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xD8, 0xEC, 0xDC, 0xDA, 0x04, 0xAD, 0xAB), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x8A, 0x09, 0xF3, 0x58, 0x79, 0xD8, 0x29), + MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x03, 0xCB, 0x50, 0x1A, 0x7F, 0x56, 0x00), + MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xA6, 0x78, 0x38, 0x85, 0x67, 0x0B, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xD5, 0xD2, 0x22, 0xC4, 0x00, 0x3B, 0xBA), + MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x93, 0x0E, 0x7B, 0x85, 0x51, 0xC3, 0x06), + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xA6, 0x5F, 0x54, 0x49, 0x02, 0x81, 0x78), + MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xE9, 0x6B, 0x3A, 0x92, 0xE7, 0x72, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x5F, 0x28, 0x9E, 0x91, 0x27, 0x88, 0xE3), + MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x28, 0x31, 0xB3, 0x84, 0xCA, 0x12, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xF9, 0xAC, 0x22, 0x10, 0x0A, 0x64, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xC6, 0x33, 0x1F, 0x69, 0x19, 0x18, 0xBF), + MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x48, 0xB8, 0xC7, 0x37, 0x5A, 0x00, 0x36), + MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xCC, 0x32, 0xE0, 0xEE, 0x03, 0xC2, 0xBA), + MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x29, 0xC2, 0xE4, 0x6E, 0x24, 0x20, 0x8D), + MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x6B, 0x7F, 0x7B, 0xF9, 0xB0, 0xB8, 0x13), + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x7B, 0x3C, 0xE1, 0x19, 0xA1, 0x23, 0x02), + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xE3, 0xC2, 0x53, 0xC0, 0x07, 0x13, 0xA9), + MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xFE, 0x36, 0x35, 0x9F, 0x5E, 0x59, 0xCE), + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x55, 0x89, 0x84, 0xBC, 0xEF, 0xA2, 0xC2), + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x1A, 0x08, 0x67, 0xB4, 0xE7, 0x22, 0xED), + MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x26, 0xDF, 0x81, 0x3C, 0x5F, 0x1C, 0xDA), + MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x4D, 0xD0, 0x0A, 0x48, 0x06, 0xF4, 0x48), + MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x18, 0x39, 0xF7, 0xD1, 0x20, 0x77, 0x8D), + MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0x8F, 0x44, 0x13, 0xCB, 0x78, 0x11, 0x11), + MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xE2, 0x49, 0xEA, 0x43, 0x79, 0x08, 0x39), + MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0xD1, 0xD8, 0x73, 0x2C, 0x71, 0x2F, 0x69), + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xE5, 0xE7, 0xF4, 0x46, 0xAB, 0x20, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x0B, 0xB9, 0x71, 0x1A, 0x27, 0xB7, 0xA7), + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xA2, 0x2C, 0xD1, 0xDA, 0xBC, 0xC1, 0xBD), + MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xA3, 0x10, 0x1F, 0x90, 0xF2, 0xA5, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xFB, 0x20, 0xF4, 0xC0, 0x70, 0xC0, 0xF5), + MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0xA7, 0x99, 0xF0, 0xA5, 0xD3, 0x09, 0xDD), + MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0xE8, 0x14, 0x39, 0xBE, 0xCB, 0x60, 0xAF), + MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0xD6, 0x14, 0xA9, 0xC9, 0x20, 0xC3, 0xEA), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xA8, 0x5B, 0xFD, 0x2D, 0x96, 0xBC, 0x78), + MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x04, 0x45, 0xBE, 0xCE, 0x75, 0x95, 0xF6), + MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0xDA, 0x58, 0x49, 0x35, 0x09, 0x8D, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xF0, 0xC0, 0x36, 0xF2, 0xA6, 0x2D, 0x14), + MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xFC, 0x3D, 0xA8, 0xFB, 0x3C, 0xD2, 0x51), + MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x4D, 0x71, 0x09, 0x18, 0x42, 0xF0, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xC1, 0xCE, 0x9E, 0x6A, 0x49, 0x60, 0x12), + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xB1, 0x00, 0xF7, 0xA1, 0x7A, 0x31, 0xB4), + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xC3, 0x86, 0xCD, 0x20, 0x4A, 0x17, 0x86), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xAB, 0x8B, 0x47, 0x8D, 0xAA, 0xA6, 0x5B), + MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x97, 0xF0, 0xBC, 0x2D, 0xDC, 0x9D, 0x84), + MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x86, 0xB0, 0x74, 0xB2, 0xF4, 0xF6, 0x67), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xBD, 0xAC, 0xE3, 0x8F, 0x43, 0x5C, 0xB1), + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xC3, 0xE2, 0x6E, 0x25, 0x49, 0xCD, 0x0B), + MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x5E, 0x08, 0xB3, 0xB9, 0xAC, 0x5F, 0xD1), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xB7, 0xD1, 0xF4, 0xDC, 0x19, 0xE9, 0xC8), + MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xE4, 0xFA, 0xE1, 0x36, 0x3E, 0xED, 0x6E), + MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x67, 0x92, 0x84, 0x6E, 0x48, 0x03, 0x51), + MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x95, 0xEF, 0x8F, 0xB2, 0x82, 0x6B, 0x1C), + MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xFA, 0xB9, 0x55, 0x23, 0xFE, 0x09, 0xB3), + MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x79, 0x85, 0x4B, 0x0E, 0xD4, 0x35, 0xDB), + MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x27, 0x45, 0x81, 0xE0, 0x88, 0x52, 0xAD), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x63, 0xA2, 0x4B, 0xBC, 0x5D, 0xB1, 0x92), + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x8C, 0x83, 0xD9, 0x3E, 0xD3, 0x42, 0xDA), + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x03, 0x3A, 0x31, 0xBA, 0xE9, 0x3A, 0xD1), + MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x10, 0xCD, 0x2D, 0x00, 0xFE, 0x32, 0xA7), + MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x6E, 0x1F, 0xDA, 0xF8, 0x6F, 0x4D, 0x03), + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x79, 0x7D, 0x09, 0xE5, 0xD3, 0x03, 0x21), + MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xC3, 0xBE, 0xDF, 0x07, 0x65, 0x49, 0xCC), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x57, 0x33, 0xEF, 0xAE, 0x4F, 0x04, 0x27), + MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0xE9, 0x9B, 0xFE, 0xBF, 0xE6, 0x85, 0xF6), + MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0xBA, 0xAA, 0x06, 0xC4, 0xC6, 0xB8, 0x57), + MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x83, 0x01, 0xA9, 0xF6, 0x51, 0xE7, 0xB8), + MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xA6, 0x15, 0x8E, 0xAB, 0x1F, 0x10, 0x87), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x08, 0x27, 0x1A, 0xA1, 0x21, 0xAD, 0xF5), + MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x09, 0x90, 0x6E, 0x50, 0x90, 0x9A, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x9A, 0xFE, 0xD7, 0xA1, 0xF5, 0xA2, 0x15), + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x7D, 0xE3, 0xDC, 0x21, 0xFB, 0xA4, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xBF, 0x07, 0xFF, 0x45, 0xDF, 0x51, 0x77), + MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x5C, 0x34, 0x02, 0x62, 0x9B, 0x08, 0x12), + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xCE, 0x9A, 0x6A, 0xEC, 0x75, 0xF6, 0x46), + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x59, 0xF4, 0x78, 0x3C, 0x60, 0xB1, 0x4A), + MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x37, 0x84, 0x6A, 0xDC, 0xF2, 0x9A, 0x7D), + MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x9A, 0x9A, 0x15, 0x36, 0xE0, 0x2B, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x38, 0x9C, 0x50, 0x3D, 0x1E, 0x37, 0x82), + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x79, 0xF0, 0x92, 0xF2, 0x8B, 0x18, 0x82), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xE0, 0x82, 0x1E, 0x80, 0x82, 0x4B, 0xD7), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xBB, 0x59, 0x6B, 0x8A, 0x77, 0x41, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xF9, 0xD4, 0xB8, 0x4A, 0x82, 0xCF, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x8C, 0xC8, 0x9B, 0x72, 0x9E, 0xF7, 0xF9), + MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0xCE, 0xE9, 0x77, 0x0A, 0x19, 0x59, 0x84), + MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xA1, 0x41, 0x6A, 0x72, 0x4B, 0xB4, 0xDC), + MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x35, 0x43, 0xE2, 0x8C, 0xBE, 0x0D, 0xE3), + MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xEB, 0xAD, 0xF3, 0xA9, 0xA6, 0x68, 0xA1), + MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x2F, 0xE2, 0x48, 0x0C, 0xDB, 0x1F, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x1E, 0x60, 0x9B, 0x2A, 0xD2, 0xC1, 0x3C), + MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x64, 0xB5, 0xD2, 0xF6, 0xF6, 0x6E, 0x22), + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x3D, 0x30, 0x78, 0x10, 0x18, 0x41, 0x51), + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x1D, 0x1C, 0xE0, 0x6D, 0x83, 0xD1, 0x93), + MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x03, 0x0B, 0xF5, 0x2F, 0x6C, 0x04, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x3E, 0xD5, 0xFC, 0x31, 0x5B, 0x3A, 0xEB), + MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x82, 0x2F, 0xFB, 0xFE, 0xF8, 0x76, 0x39), + MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x26, 0xDA, 0x9C, 0x36, 0xF5, 0x93, 0xD1), + MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0xE7, 0x6E, 0xD2, 0x7D, 0x81, 0x09, 0xC6), + MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x03, 0xF9, 0x58, 0x48, 0x24, 0xA2, 0xEE), + MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x79, 0x0C, 0x8E, 0x6B, 0x95, 0xF3, 0xC4), + MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x10, 0x5C, 0x87, 0x03, 0x39, 0xCF, 0x68), + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xF0, 0xF7, 0xC1, 0x07, 0xA4, 0xF4, 0x3F), + MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xE8, 0x02, 0x89, 0x65, 0xC4, 0x72, 0x36), + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x88, 0xEA, 0x96, 0x67, 0x0B, 0x5D, 0xDF), + MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x75, 0x60, 0xA8, 0xBD, 0x74, 0xDF, 0x68), + MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xE5, 0x71, 0x50, 0x67, 0xD0, 0xD2, 0xE6), + MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xFC, 0xE5, 0xC7, 0x77, 0xB0, 0x7F, 0x8C), + MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x86, 0x69, 0xCD, 0x0D, 0x9A, 0xBD, 0x66), + MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x17, 0xBC, 0xBB, 0x59, 0x85, 0x7D, 0x0E), + MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xA8, 0x76, 0xAC, 0x80, 0xA9, 0x72, 0xE0), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x78, 0xC1, 0xE2, 0x4D, 0xAF, 0xF9, 0x3C), + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x97, 0x8E, 0x74, 0xC4, 0x4B, 0xB2, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xD8, 0xF6, 0xF3, 0xAF, 0x2F, 0x52, 0xE5), + MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x57, 0xF4, 0xCE, 0xEE, 0x43, 0xED, 0x60), + MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x46, 0x38, 0xDE, 0x20, 0xFD, 0x59, 0x18), + MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x18, 0xE8, 0x58, 0xB9, 0x76, 0x2C, 0xE6), + MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x54, 0xE4, 0xFE, 0xC7, 0xBC, 0x31, 0x37), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xF8, 0x89, 0xEE, 0x70, 0xB5, 0xB0, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x22, 0x26, 0x9A, 0x53, 0xB9, 0x38, 0x0A), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xA7, 0x19, 0x8C, 0x74, 0x7E, 0x88, 0x46), + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xDA, 0x0A, 0xE8, 0xDA, 0xA5, 0xBE, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x5C, 0xF7, 0xB1, 0x0C, 0x72, 0xFB, 0x09), + MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xE2, 0x23, 0xE7, 0x46, 0xB7, 0xE0, 0x91), + MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x36, 0xBC, 0xBD, 0x48, 0x11, 0x8E, 0x72), + MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0xBB, 0xA1, 0xF7, 0x0B, 0x9E, 0xBF, 0xDF), + MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x28, 0xE1, 0xA2, 0x8F, 0xFC, 0xFC, 0xD6), + MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0xFE, 0x19, 0x0A, 0xE5, 0xE7, 0x69, 0x39), + MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xCD, 0x12, 0xF5, 0xBE, 0xD3, 0x04, 0xF1), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xA8, 0x0D, 0x81, 0x59, 0xC4, 0x79, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xF3, 0x4B, 0x92, 0x65, 0xC3, 0x31, 0xAD), + MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0xB5, 0x4F, 0x4D, 0x91, 0xD4, 0xE2, 0xB2), + MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x09, 0x41, 0x79, 0x1D, 0x4D, 0x0D, 0x33), + MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x31, 0x18, 0xBA, 0xA0, 0xF2, 0x6E, 0x7E), + MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x5B, 0x4D, 0x4F, 0xAF, 0xC9, 0x8C, 0xA1), + MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x99, 0x9C, 0x06, 0x68, 0xDE, 0xD8, 0x29), + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x04, 0xE1, 0xB5, 0x9D, 0x00, 0xBC, 0xB8), + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x95, 0x92, 0x8D, 0x72, 0xD3, 0x37, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x4B, 0x27, 0xA2, 0xE8, 0xA4, 0x26, 0xA1), + MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x45, 0x9C, 0xA9, 0xCB, 0x9F, 0xBA, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x7E, 0x1B, 0x64, 0xF4, 0xE8, 0xA5, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x20, 0xA9, 0xCA, 0xF3, 0x89, 0xE5, 0xE1), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xED, 0xFC, 0xAB, 0xD9, 0x0A, 0xB9, 0x07), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x6F, 0x46, 0x7C, 0xCD, 0x78, 0xFF, 0x05), + MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xAB, 0x71, 0x5A, 0x94, 0xAB, 0x20, 0x20), + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x2E, 0xEE, 0x87, 0x57, 0x1F, 0xAD, 0xD3), + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x4C, 0x3D, 0xFB, 0x7E, 0xA1, 0x8B, 0x07), + MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xCF, 0x07, 0x86, 0xBA, 0x53, 0x37, 0xCF), + MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x26, 0xB2, 0xB9, 0xE2, 0x91, 0xE3, 0xB5), + MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xC9, 0x54, 0x84, 0x08, 0x3D, 0x0B, 0xD2), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xA8, 0x77, 0x2F, 0x64, 0x45, 0x99, 0x4C), + MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x96, 0x16, 0x1F, 0xDB, 0x96, 0x28, 0x97), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x2B, 0x8D, 0xFF, 0xA2, 0x4F, 0x55, 0xD3), + MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0xE6, 0x48, 0xBD, 0x99, 0x3D, 0x12, 0x57), + MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x84, 0x59, 0xDA, 0xB9, 0xB6, 0x66, 0x12), + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x78, 0x41, 0x92, 0xDF, 0xF4, 0x3F, 0x63), + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x86, 0x6F, 0x4F, 0xBF, 0x67, 0xDF, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x2B, 0x1E, 0x5F, 0x00, 0xEA, 0xF6, 0x56), + MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xB9, 0x6A, 0x89, 0xD8, 0xC0, 0xD7, 0xA7), + MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x9A, 0x32, 0x23, 0xA0, 0x02, 0x91, 0x58), + MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x7F, 0x6A, 0x15, 0x64, 0x6A, 0x8B, 0xBB), + MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x57, 0x82, 0x58, 0xA9, 0x56, 0xB5, 0xFB), + MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x50, 0x92, 0x60, 0xCC, 0x81, 0x24, 0xA8), + MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x3D, 0xAD, 0xDA, 0xD9, 0x51, 0x3E, 0x57), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0xFE, 0x8F, 0xB0, 0x0B, 0xDE, 0x2E, 0x7E), + MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xD2, 0xBE, 0xEF, 0xAC, 0x76, 0x71, 0xA3), + MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xE8, 0x72, 0x0B, 0xAC, 0xFE, 0xCA, 0x5A), + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x5B, 0xC7, 0xFC, 0xE3, 0x3C, 0x7C, 0x4C), + MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x04, 0xA7, 0xB9, 0x9B, 0x93, 0xC0, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x48, 0x4B, 0x8E, 0x32, 0xC5, 0xF0, 0x6B), + MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x42, 0x07, 0xC1, 0xF2, 0xF1, 0x72, 0x5B), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x37, 0x54, 0x9C, 0x88, 0xD2, 0x62, 0xAA), + MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x19, 0x8A, 0x89, 0x58, 0xA2, 0x0F, 0xDB), + MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0xCC, 0x4C, 0x97, 0x30, 0x66, 0x34, 0x26), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x6A, 0x1E, 0x1F, 0xDB, 0xC9, 0x5E, 0x13), + MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x4D, 0x49, 0xFF, 0x9B, 0x9C, 0xAC, 0x9B), + MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0xE4, 0x4B, 0xF2, 0xD4, 0x1A, 0xD2, 0x78), + MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xDA, 0xE8, 0x61, 0x9F, 0xC8, 0x49, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xCB, 0xF2, 0x2D, 0x85, 0xF6, 0x8D, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xC5, 0xCD, 0x2C, 0x79, 0xC6, 0x0E, 0x4F), + MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x1D, 0x55, 0x0F, 0xF8, 0x22, 0x9F, 0x78), + MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x56, 0xBA, 0xE7, 0x57, 0x32, 0xEC, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x9A, 0xC6, 0x4C, 0x09, 0xC4, 0x52, 0x3F), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x1E, 0x6F, 0xF4, 0x7D, 0x27, 0xDD, 0xAF), + MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x11, 0x16, 0xEC, 0x79, 0x83, 0xAD, 0xAE), + MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x4E, 0x92, 0x1F, 0x19, 0x7D, 0x65, 0xDC), + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0xFF, 0x78, 0x15, 0x45, 0x63, 0x32, 0xE4), + MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x91, 0xD0, 0x78, 0x58, 0xDA, 0x50, 0x47), + MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0xDE, 0x40, 0xF6, 0x41, 0xB4, 0x3B, 0x95), + MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x8D, 0xE0, 0xE1, 0xA9, 0xF0, 0x35, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xD4, 0xBA, 0x7B, 0xCC, 0x1B, 0x3A, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x5A, 0x2E, 0x74, 0x47, 0x14, 0xC3, 0x4D), + MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xF0, 0x8B, 0x06, 0x15, 0x8E, 0x0E, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0xD2, 0xEB, 0x97, 0x50, 0x7D, 0x31, 0xFC), + MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x93, 0x4C, 0xDB, 0x97, 0x79, 0x44, 0xF5), + MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xA2, 0xA0, 0x0B, 0xC8, 0x3A, 0x8A, 0xF9), + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x50, 0x92, 0x9E, 0x24, 0x1F, 0xCB, 0x4C), + MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x16, 0xC9, 0xC5, 0x3D, 0x5A, 0xAF, 0x97), + MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xE3, 0x97, 0xE4, 0xA8, 0x50, 0xF6, 0x7E), + MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x57, 0x97, 0x42, 0x78, 0x92, 0x49, 0x0D), + MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0xEB, 0x62, 0x24, 0xFB, 0x8F, 0x32, 0xCF), + MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x0C, 0x36, 0x6E, 0x8F, 0xE8, 0xE8, 0x8E), + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xD3, 0x7C, 0xC7, 0x8D, 0x3F, 0x5C, 0xE1), + MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x64, 0x6A, 0x73, 0x10, 0x79, 0xB8, 0x5A), + MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xF9, 0xEF, 0xA5, 0x20, 0x4A, 0x5C, 0xA1), + MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xF3, 0xF4, 0x49, 0x5B, 0x73, 0xAA, 0x1B), + MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xF2, 0xEA, 0x0F, 0x00, 0xAD, 0x53, 0xAB), + MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xB8, 0x66, 0xED, 0xC4, 0x2B, 0x4C, 0x35), + MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x2F, 0xC1, 0x9A, 0x37, 0xD2, 0x7F, 0x58), + MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xA7, 0x81, 0x38, 0x64, 0xC9, 0x37, 0x38), + MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x3B, 0x6C, 0x9F, 0x5B, 0xD9, 0x8B, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x14, 0xD9, 0x08, 0xD8, 0xD2, 0x7E, 0x23), + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x71, 0xE6, 0x3D, 0xD1, 0xB0, 0xE7, 0xCD), + MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x81, 0x23, 0xEC, 0x2D, 0x42, 0x45, 0xE6), + MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x5B, 0x44, 0x6B, 0x89, 0x03, 0x67, 0x28), + MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x27, 0xAE, 0x80, 0x5A, 0x33, 0xBE, 0x11), + MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xB6, 0x64, 0x1A, 0xDF, 0xD3, 0x85, 0x91), + MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x8C, 0x22, 0xBA, 0xD0, 0xBD, 0xCC, 0xA0), + MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x3C, 0x01, 0x3A, 0xFF, 0x9D, 0xC7, 0x6B), + MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xC7, 0x64, 0xB4, 0x59, 0x4E, 0x9F, 0x22), + MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x34, 0x0A, 0x41, 0x94, 0xA8, 0xF2, 0xB7), + MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xD4, 0xE4, 0xF0, 0x97, 0x45, 0x6D, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0x1F, 0x4D, 0x6D, 0xFE, 0xA0, 0xC4, 0x84), + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x28, 0x5C, 0x40, 0xBB, 0x65, 0xD4, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xA8, 0x87, 0x35, 0x20, 0x3A, 0x89, 0x44), + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xFD, 0x4F, 0xAB, 0x2D, 0xD1, 0xD0, 0xC0), + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xE8, 0x00, 0xFC, 0x69, 0x52, 0xF8, 0xD5), + MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x9A, 0x99, 0xE1, 0xDC, 0x9C, 0x3F, 0xD9), + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x08, 0x98, 0xD9, 0xCA, 0x73, 0xD5, 0xA9), + MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x2C, 0xE0, 0xA7, 0x3E, 0x91, 0xD7, 0x87), + MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x04, 0xB0, 0x54, 0x09, 0xF4, 0x72, 0xB7), + MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xEE, 0x28, 0xCC, 0xE8, 0x50, 0x78, 0x20), + MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x91, 0x03, 0x76, 0xDB, 0x68, 0x24, 0x77), + MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xE0, 0x56, 0xB2, 0x5D, 0x12, 0xD3, 0xB5), + MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x42, 0x59, 0x8B, 0xDF, 0x67, 0xB5, 0xBE), + MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xCC, 0xE5, 0x31, 0x53, 0x7A, 0x46, 0xB3), + MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_16_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x8D, 0x59, 0xB5, 0x1B, 0x0F, 0xF4, 0xAF), + MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x2F, 0xD1, 0x2C, 0xE0, 0xD8, 0x04, 0xEF), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xF4, 0xD7, 0xBA, 0xB0, 0xA3, 0x7E, 0xC9), + MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x08, 0x51, 0x56, 0xA6, 0x76, 0x67, 0x33), + MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x17, 0x63, 0xFE, 0x56, 0xD0, 0xD9, 0x71), + MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0xF6, 0xC3, 0x14, 0x47, 0xC5, 0xA7, 0x31), + MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x4C, 0x80, 0xF6, 0xA2, 0x57, 0xA7, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xB3, 0x7B, 0xF8, 0x2F, 0xE1, 0x3E, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_16_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0xF4, 0xF9, 0x6B, 0x7B, 0x90, 0xDF, 0x30), + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x82, 0xEF, 0x62, 0xA1, 0x4C, 0x53, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x99, 0x76, 0x01, 0xBA, 0x8D, 0x0F, 0x54), + MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xF4, 0x58, 0x73, 0x56, 0xFE, 0xDD, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xCE, 0xF9, 0xE8, 0xA1, 0x34, 0xC3, 0x5B), + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x5F, 0xDC, 0x6A, 0x3D, 0xD8, 0x7F, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xF4, 0x51, 0xB8, 0xB8, 0xC1, 0xD7, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x7D, 0x58, 0xD1, 0xD4, 0x1B, 0x4D, 0x23), + MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_17_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x95, 0xDF, 0x00, 0xD8, 0x21, 0xDE, 0x94), + MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x47, 0x3C, 0xC3, 0xB2, 0x01, 0x53, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x17, 0x43, 0x23, 0xBD, 0xCA, 0x71, 0xF2), + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xBA, 0x0F, 0x4F, 0xDC, 0x41, 0x54, 0xBE), + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x39, 0x26, 0x70, 0x53, 0x32, 0x18, 0x11), + MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x46, 0x07, 0x97, 0x3A, 0x57, 0xE0, 0x01), + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x92, 0x4F, 0xCE, 0xDF, 0x25, 0x80, 0x26), + MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x6F, 0x9A, 0x03, 0x05, 0x4B, 0xD1, 0x47), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_17_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x01, 0x72, 0x30, 0x90, 0x17, 0x51, 0x20), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xFB, 0x41, 0x65, 0x5C, 0xB4, 0x2D, 0xEE), + MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xCD, 0xCD, 0xAA, 0x41, 0xCC, 0xBB, 0x07), + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xCE, 0x08, 0x0A, 0x63, 0xE9, 0xA2, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xA8, 0x21, 0x7F, 0x7A, 0x5B, 0x9B, 0x81), + MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x6B, 0x89, 0x44, 0x0A, 0x7F, 0x85, 0x5F), + MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xDE, 0x7C, 0x19, 0x5C, 0x65, 0x26, 0x61), + MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0xAC, 0x62, 0x29, 0x4A, 0xF1, 0xD0, 0x81), + MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_18_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x00, 0x40, 0x87, 0xEB, 0xA9, 0x58, 0x56), + MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x51, 0x0B, 0xFF, 0x56, 0x35, 0x51, 0xB3), + MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xAC, 0x08, 0x94, 0x71, 0xDA, 0xEC, 0x99), + MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x4D, 0xC5, 0x7B, 0x31, 0x8B, 0x8D, 0x5E), + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x05, 0xF1, 0x3E, 0x9E, 0x8F, 0x17, 0x8F), + MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x9C, 0x4B, 0x62, 0x94, 0xAD, 0x49, 0xFC), + MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xC9, 0xC6, 0x8F, 0xFD, 0x33, 0x44, 0x34), + MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x96, 0x17, 0x7F, 0x42, 0xBE, 0xF7, 0x0D), + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_18_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0x29, 0x39, 0x13, 0x08, 0x8D, 0x91, 0x47), + MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x79, 0xF9, 0x2F, 0xA9, 0x0A, 0xCF, 0xD6), + MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x87, 0x7A, 0xA3, 0x19, 0xAB, 0x55, 0xAD), + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x0B, 0x01, 0xC5, 0x56, 0x19, 0x9D, 0x9E), + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0xDE, 0x82, 0x3B, 0xEA, 0xD3, 0x0B, 0x8C), + MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x6B, 0xC7, 0xF3, 0x0F, 0x82, 0x87, 0x6C), + MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x2E, 0x23, 0xF2, 0x39, 0x9D, 0x49, 0x70), + MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0xDE, 0xAF, 0x7A, 0xEE, 0xB0, 0xDA, 0x70), + MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_19_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x4E, 0x2A, 0x50, 0xFD, 0x8E, 0xC0, 0xEB), + MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x0F, 0x7C, 0x76, 0x63, 0xD8, 0x89, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x2D, 0xB9, 0x4E, 0xF4, 0xEE, 0x85, 0xCF), + MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x95, 0x5C, 0x96, 0x5D, 0xAA, 0x59, 0x0B), + MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xDB, 0xD2, 0x68, 0x8E, 0x5A, 0x94, 0x60), + MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x02, 0xBF, 0x77, 0x9F, 0xB9, 0x4C, 0xC9), + MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xDC, 0xC0, 0xCF, 0x81, 0x1E, 0xC4, 0x6C), + MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xCC, 0x37, 0x86, 0xDC, 0xE2, 0x64, 0x72), + MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_19_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x30, 0xB1, 0x59, 0x20, 0x9D, 0x98, 0x28), + MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x0C, 0x9D, 0xF8, 0x20, 0xDC, 0x90, 0xBA), + MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xA0, 0xF4, 0xE7, 0x3E, 0x9C, 0x9E, 0xA2), + MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x25, 0xA2, 0xB0, 0x54, 0xCD, 0x2E, 0x33), + MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xD9, 0x42, 0xB0, 0x80, 0xB0, 0xA3, 0x38), + MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0xFE, 0x9D, 0x8D, 0x40, 0xFF, 0x27, 0x6D), + MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x9D, 0xA6, 0x88, 0x3A, 0x8B, 0x6F, 0x14), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x39, 0xEE, 0x1F, 0x3F, 0xB1, 0x4F, 0x63), + MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_20_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xD7, 0x9E, 0xFF, 0xD2, 0x35, 0x67, 0x03), + MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x4F, 0x15, 0x5D, 0xE3, 0xE8, 0x53, 0x86), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xF7, 0x24, 0x98, 0xA2, 0xCB, 0x11, 0x68), + MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x2E, 0x25, 0xE1, 0x94, 0xC5, 0xA3, 0x96), + MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x82, 0x6E, 0xBA, 0xE7, 0x43, 0x25, 0xB0), + MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x65, 0xB4, 0x49, 0x73, 0x18, 0x35, 0x54), + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x5B, 0xBC, 0x62, 0x86, 0x4C, 0xC1, 0xB7), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xF2, 0x95, 0xA2, 0xBB, 0xA2, 0x35, 0x65), + MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_20_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x59, 0x62, 0xB0, 0x4B, 0x1E, 0xB4, 0xD8), + MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x55, 0xCE, 0xB0, 0x69, 0xBA, 0x63, 0x10), + MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0x69, 0x86, 0xDB, 0x34, 0x7D, 0x68, 0x64), + MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x06, 0xCA, 0x55, 0x44, 0x36, 0x2B, 0xBA), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xD4, 0xC4, 0x3D, 0xCD, 0x9E, 0x69, 0xA4), + MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x44, 0xE4, 0xBF, 0x31, 0xE6, 0x40, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x4F, 0xFA, 0x75, 0xE3, 0xFB, 0x97, 0x0E), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xC0, 0xBD, 0x1C, 0x48, 0xB0, 0x26, 0xD0), + MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_21_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x7B, 0x32, 0xFA, 0xF2, 0x6D, 0x84, 0x8E), + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x21, 0x03, 0x1D, 0x0D, 0x22, 0x55, 0x67), + MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xF9, 0x42, 0x03, 0x9C, 0xC2, 0xCB, 0xBA), + MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xA1, 0x96, 0xD9, 0x9D, 0x11, 0x6F, 0xBE), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x40, 0x57, 0xEB, 0x40, 0x2D, 0xC0, 0x11), + MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x96, 0xBB, 0x4F, 0x2F, 0x23, 0xA8, 0x28), + MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x29, 0x85, 0x21, 0xA5, 0x50, 0x62, 0x06), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x7D, 0x92, 0xCF, 0x87, 0x0C, 0x22, 0xF9), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_21_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x0E, 0xA5, 0x32, 0x5B, 0xDF, 0x9C, 0xD5), + MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x96, 0x37, 0x2C, 0x88, 0x35, 0x30, 0xA1), + MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xB4, 0x69, 0xFF, 0xEB, 0xC6, 0x94, 0x08), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x55, 0x60, 0xAD, 0xAA, 0x58, 0x14, 0x88), + MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xFF, 0xF2, 0xB2, 0xD5, 0xA7, 0xD9, 0x27), + MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xAE, 0x54, 0xD2, 0x60, 0x31, 0xF3, 0x15), + MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x92, 0x83, 0xE3, 0xF1, 0x42, 0x83, 0x6E), + MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xD2, 0xC8, 0xB7, 0x76, 0x45, 0x7F, 0x7D), + MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_22_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x11, 0xA4, 0xFB, 0x7A, 0x01, 0xBC, 0xC8), + MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x27, 0x73, 0x8D, 0x02, 0x91, 0x27, 0x8E), + MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x62, 0xF6, 0xDD, 0x6B, 0xFA, 0x5B, 0xB9), + MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0xCA, 0xA2, 0x44, 0x2C, 0xF0, 0x28, 0xD8), + MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xF1, 0x7A, 0xA2, 0x42, 0x4C, 0x50, 0xC6), + MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x83, 0x3E, 0x50, 0xAB, 0x9C, 0xF7, 0x67), + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xED, 0x78, 0xCB, 0x76, 0x69, 0xDA, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x01, 0x1E, 0x43, 0x27, 0x47, 0x6E, 0xDA), + MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_22_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x4F, 0x54, 0xB9, 0x3E, 0xBD, 0xD5, 0x44), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x35, 0x40, 0x69, 0x7F, 0x74, 0x9D, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x06, 0x6F, 0x67, 0x68, 0x2B, 0x4D, 0x10), + MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x65, 0x41, 0xFC, 0x7C, 0x1E, 0xE8, 0xC8), + MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x79, 0x37, 0xAF, 0xFD, 0xD2, 0xDA, 0x4C), + MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xA8, 0x69, 0x56, 0x62, 0xA4, 0xE4, 0xA3), + MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x71, 0x73, 0x21, 0x8A, 0x17, 0x81, 0xA2), + MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x55, 0x8F, 0x7B, 0xB8, 0xAF, 0xF7, 0x86), + MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_23_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xD1, 0xBD, 0xBE, 0x8C, 0xBC, 0x60, 0x6E), + MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0xA6, 0x57, 0x8C, 0xAE, 0x5C, 0x19, 0xFE), + MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0x43, 0xE4, 0xD9, 0xD8, 0x7B, 0xE7, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xB9, 0xE4, 0x85, 0x7C, 0x2E, 0xFC, 0x20), + MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x2E, 0x01, 0x2A, 0x6D, 0x56, 0xBE, 0x97), + MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x0C, 0x25, 0x9B, 0xAE, 0x86, 0x37, 0x43), + MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x22, 0xB3, 0xCB, 0x99, 0x66, 0xB7, 0x9E), + MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xF7, 0x90, 0xF0, 0x1B, 0x09, 0x27, 0xF7), + MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_23_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x16, 0x08, 0xEF, 0x39, 0x64, 0x49, 0x31), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xA0, 0xE3, 0x97, 0xA9, 0x07, 0x54, 0x26), + MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xFF, 0xE2, 0x00, 0x07, 0x21, 0x88, 0x20), + MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xFD, 0x59, 0x53, 0x05, 0x6C, 0x42, 0x27), + MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0xF7, 0x39, 0x5C, 0x82, 0x36, 0xE8, 0x03), + MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0x83, 0xA8, 0xE2, 0xA8, 0x43, 0x07, 0x38), + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xAF, 0x2B, 0x79, 0xED, 0xD8, 0x39, 0x87), + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x20, 0x91, 0x7A, 0xC4, 0x07, 0xEF, 0x6C), + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_24_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x10, 0x2F, 0xAA, 0x0C, 0x94, 0x0E, 0x5A), + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x81, 0x87, 0x41, 0x23, 0xEB, 0x55, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x53, 0xCC, 0x79, 0xB6, 0xEB, 0x6C, 0xCC), + MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x77, 0x73, 0x9D, 0xFC, 0x64, 0x6F, 0x7F), + MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x40, 0xE3, 0x6D, 0x1C, 0x16, 0x71, 0x15), + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0xF4, 0x1B, 0xFF, 0x1C, 0x2F, 0xA5, 0xD7), + MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x0E, 0x0B, 0x11, 0xF4, 0x8D, 0x93, 0xAF), + MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xC5, 0x64, 0x6F, 0x24, 0x19, 0xF2, 0x9B), + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_24_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xB3, 0xAF, 0xA5, 0x0E, 0x4F, 0x5E, 0xE1), + MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0x77, 0xCA, 0xF2, 0x6D, 0xC5, 0xF6, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x18, 0x8E, 0x33, 0x68, 0x6C, 0xE8, 0xE0), + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x8B, 0x80, 0x90, 0x19, 0x7F, 0x90, 0x96), + MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x80, 0x6B, 0x68, 0xE2, 0x7D, 0xD4, 0xD0), + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xC1, 0x67, 0xB3, 0x72, 0xCB, 0xBF, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0xD5, 0xD3, 0x1D, 0x14, 0x58, 0x0A, 0x80), + MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x7A, 0x65, 0x98, 0xB3, 0x07, 0x4B, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_25_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x87, 0x0F, 0x5F, 0xCF, 0xA2, 0x01, 0x08), + MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xC9, 0xC8, 0x6E, 0x35, 0x87, 0xA5, 0x67), + MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x3E, 0x91, 0xA0, 0xAB, 0x24, 0x1E, 0xF2), + MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xBC, 0x02, 0x35, 0x70, 0xC1, 0x5F, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x59, 0xA0, 0x50, 0x04, 0x80, 0x52, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x56, 0x6E, 0x42, 0x8F, 0x8C, 0x91, 0x65), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xA2, 0xCB, 0xA5, 0xDE, 0x14, 0x24, 0x38), + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0xCB, 0x74, 0x28, 0xE6, 0xA7, 0xE7, 0xC3), + MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_25_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x73, 0xA8, 0x8F, 0x9E, 0x0E, 0x63, 0x96), + MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x1B, 0x77, 0xC7, 0xC1, 0x38, 0xF9, 0xDC), + MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x3C, 0xCF, 0xA8, 0x7A, 0xD7, 0xF3, 0xC4), + MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x5F, 0x9A, 0xC9, 0xAD, 0xE9, 0x1A, 0x93), + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0xCF, 0x2B, 0x5E, 0xD5, 0x81, 0x95, 0xA8), + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x88, 0x75, 0x29, 0x1F, 0xC7, 0xC7, 0xD0), + MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA9, 0x5A, 0x4D, 0x63, 0x95, 0xF9, 0x4E), + MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xCD, 0x04, 0x8F, 0xCD, 0x91, 0xDE, 0xC6), + MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_26_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xD4, 0xFD, 0x25, 0x11, 0x99, 0x6E, 0xEA), + MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x83, 0x01, 0x3D, 0xFB, 0x56, 0xA5, 0x4E), + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x3A, 0xDC, 0x74, 0xC2, 0xD7, 0xCF, 0xE8), + MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0xBD, 0xF1, 0xDD, 0xA3, 0x07, 0x03, 0xE2), + MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xBE, 0xE9, 0x2E, 0x58, 0x84, 0x66, 0xFC), + MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x20, 0x78, 0x37, 0x79, 0x0B, 0xA6, 0x64), + MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xF2, 0xAC, 0x65, 0xC8, 0xC9, 0x2F, 0x61), + MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x93, 0xE5, 0x0D, 0x0C, 0xC6, 0xB8, 0xCB), + MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_26_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xAD, 0x5C, 0x19, 0x12, 0x61, 0x0E, 0x25), + MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x4F, 0x0B, 0x1F, 0x49, 0x7E, 0xCD, 0x81), + MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x2E, 0x30, 0x61, 0xDB, 0x08, 0x68, 0x9B), + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x78, 0xAF, 0xB3, 0x08, 0xC1, 0x69, 0xE5), + MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x5F, 0x5D, 0xC1, 0x57, 0x6F, 0xD8, 0x34), + MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0xD3, 0x6A, 0xF7, 0xFD, 0x86, 0xE5, 0xB3), + MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x63, 0xBD, 0x70, 0x7B, 0x47, 0xE8, 0x6D), + MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x62, 0xC8, 0x7E, 0x9D, 0x11, 0x2B, 0xA5), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_27_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x84, 0xFD, 0xD5, 0x9A, 0x56, 0x7F, 0x5C), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xBB, 0xA4, 0x6F, 0x12, 0x6E, 0x4D, 0xF8), + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x08, 0xA1, 0x82, 0x9C, 0x62, 0x74, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x58, 0x22, 0x05, 0x1D, 0x15, 0x35, 0x79), + MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x88, 0xCF, 0x5C, 0x05, 0x78, 0xFB, 0x94), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x6B, 0x2F, 0x79, 0x09, 0x73, 0x67, 0xEC), + MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA0, 0x80, 0xD8, 0xE8, 0xEC, 0xFB, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xE7, 0x0B, 0xB7, 0x81, 0x48, 0x7B, 0xD9), + MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_27_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x53, 0xA9, 0xED, 0x61, 0x92, 0xD7, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x49, 0xD9, 0x5D, 0x9B, 0x4E, 0x89, 0x35), + MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x12, 0xEB, 0x9A, 0xC9, 0xCB, 0xC1, 0x95), + MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xDC, 0x95, 0x16, 0xFE, 0x29, 0x70, 0x01), + MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x33, 0xB1, 0xD6, 0x78, 0xB9, 0xE2, 0x36), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xCE, 0x88, 0xC3, 0xFD, 0x7A, 0x6B, 0xB8), + MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x1E, 0x50, 0x1E, 0xAF, 0xB1, 0x25, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xE7, 0xD7, 0xD5, 0xBD, 0x7A, 0x12, 0xF9), + MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_28_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xAA, 0xA2, 0x80, 0x5D, 0x8F, 0xCD, 0xC8), + MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x39, 0x79, 0x64, 0xA1, 0x67, 0x3C, 0xB7), + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xC7, 0x49, 0xFF, 0x7F, 0xAC, 0xAB, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x54, 0x3E, 0x83, 0xF0, 0x3D, 0xBC, 0xB5), + MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x92, 0x4A, 0x38, 0x42, 0x8A, 0xAB, 0xF6), + MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x0B, 0x4F, 0xEE, 0x9E, 0x92, 0xA5, 0xBE), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xDD, 0x19, 0x96, 0xF2, 0xF0, 0x6B, 0x2E), + MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xFC, 0xDD, 0xB2, 0x8A, 0xE5, 0x4C, 0x22), + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_28_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x06, 0x49, 0xAC, 0x99, 0x7E, 0xF8, 0x12), + MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xC8, 0x01, 0x51, 0xEA, 0xF6, 0x52, 0xE7), + MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x89, 0x66, 0x2B, 0x1F, 0x9B, 0x2A, 0xA3), + MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x0F, 0x95, 0x07, 0x2B, 0x6C, 0x6E, 0x9E), + MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xC3, 0xB4, 0xBB, 0x91, 0x1F, 0xA3, 0x72), + MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x6E, 0x54, 0x28, 0x7B, 0x9C, 0x79, 0x2E), + MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x45, 0xFF, 0xA6, 0xDA, 0xA2, 0x83, 0x71), + MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xDE, 0x8F, 0x17, 0x37, 0x82, 0xCB, 0xE2), + MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_29_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x94, 0x3F, 0x26, 0xC9, 0x1D, 0xD9, 0xAE), + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x97, 0x28, 0x20, 0xCD, 0xC1, 0xF3, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0xC9, 0xB5, 0x60, 0x9B, 0x1E, 0xDC, 0x74), + MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0xB9, 0x5B, 0x7D, 0xA0, 0xB2, 0x8C, 0xF0), + MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xD1, 0x42, 0xE6, 0x39, 0x33, 0x6D, 0xBB), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xC0, 0xFC, 0xD2, 0x14, 0x5D, 0x3E, 0x3C), + MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0x4A, 0x3E, 0x40, 0x16, 0x93, 0x15, 0xCF), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x24, 0xC1, 0x27, 0x27, 0xE5, 0x4B, 0xD8), + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_29_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x50, 0xD8, 0xBC, 0xC1, 0x46, 0x22, 0xBB), + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x0E, 0x60, 0xA1, 0xB3, 0x50, 0xD4, 0x86), + MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0xB1, 0x26, 0xB6, 0x6D, 0x47, 0x5A, 0x6F), + MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0xAC, 0x11, 0x35, 0x3E, 0xB9, 0xF4, 0x01), + MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x97, 0xFA, 0xBB, 0x6B, 0x39, 0x13, 0xD8), + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x7B, 0x34, 0x12, 0x75, 0x8E, 0x9B, 0xC6), + MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x9E, 0xCD, 0x29, 0xB6, 0xEF, 0x8D, 0x10), + MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xAC, 0xE9, 0x25, 0x27, 0xBB, 0x78, 0x47), + MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_30_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x7A, 0xA8, 0xD3, 0xE3, 0x66, 0xE5, 0x66), + MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x4C, 0xC4, 0x2C, 0x76, 0x81, 0x50, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x71, 0x08, 0xB8, 0x52, 0x7C, 0xAF, 0xDC), + MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x59, 0x24, 0xDD, 0xFB, 0x2F, 0xD0, 0xDA), + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xCD, 0x56, 0xE9, 0xAC, 0x91, 0xE6, 0xB9), + MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x64, 0x20, 0xC6, 0x9F, 0xE4, 0xEF, 0xDF), + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x2C, 0x8F, 0x8C, 0x97, 0xF6, 0x22, 0xC3), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xF4, 0x88, 0xAA, 0xA8, 0xD7, 0xA5, 0x68), + MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_30_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x6C, 0xAE, 0x83, 0xB1, 0x55, 0x55, 0xEE), + MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x67, 0x84, 0x47, 0x7C, 0x83, 0x5C, 0x89), + MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x10, 0x4D, 0xDD, 0x30, 0x60, 0xB0, 0xE6), + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xA7, 0x36, 0x76, 0x24, 0x32, 0x9F, 0x9D), + MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x42, 0x81, 0xFB, 0xA4, 0x2E, 0x13, 0x68), + MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x94, 0x91, 0xFF, 0x99, 0xA0, 0x09, 0x61), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x83, 0xA1, 0x76, 0xAF, 0x37, 0x5C, 0x77), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xA8, 0x04, 0x86, 0xC4, 0xA9, 0x79, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_31_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x8C, 0xC2, 0x34, 0xFB, 0x83, 0x28, 0x27), + MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x03, 0x7D, 0x5E, 0x9E, 0x0E, 0xB0, 0x22), + MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x02, 0x46, 0x7F, 0xB9, 0xAC, 0xBB, 0x23), + MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xED, 0x48, 0xC2, 0x96, 0x4D, 0x56, 0x27), + MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0xB5, 0xC5, 0xD1, 0xE6, 0x1C, 0x7E, 0x9B), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x2E, 0x18, 0x71, 0x2D, 0x7B, 0xD7, 0xB3), + MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x46, 0x9D, 0xDE, 0xAA, 0x78, 0x8E, 0xB1), + MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xD7, 0x69, 0x2E, 0xE1, 0xD9, 0x48, 0xDE), + MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp521r1_T_31_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xFF, 0x9E, 0x09, 0x22, 0x22, 0xE6, 0x8D), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x14, 0x28, 0x13, 0x1B, 0x62, 0x12, 0x22), + MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x7F, 0x67, 0x03, 0xB0, 0xC0, 0xF3, 0x05), + MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xC3, 0x0F, 0xFB, 0x25, 0x48, 0x3E, 0xF4), + MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x6E, 0x53, 0x98, 0x36, 0xB3, 0xD3, 0x94), + MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x81, 0x54, 0x22, 0xA4, 0xCC, 0xC1, 0x22), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xBA, 0xFC, 0xA9, 0xDF, 0x68, 0x86, 0x2B), + MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x92, 0x0E, 0xC3, 0xF2, 0x58, 0xE8, 0x51), + MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_ecp_point secp521r1_T[32] = { + ECP_POINT_INIT_XY_Z1(secp521r1_T_0_X, secp521r1_T_0_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_1_X, secp521r1_T_1_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_2_X, secp521r1_T_2_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_3_X, secp521r1_T_3_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_4_X, secp521r1_T_4_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_5_X, secp521r1_T_5_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_6_X, secp521r1_T_6_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_7_X, secp521r1_T_7_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_8_X, secp521r1_T_8_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_9_X, secp521r1_T_9_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_10_X, secp521r1_T_10_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_11_X, secp521r1_T_11_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_12_X, secp521r1_T_12_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_13_X, secp521r1_T_13_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_14_X, secp521r1_T_14_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_15_X, secp521r1_T_15_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_16_X, secp521r1_T_16_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_17_X, secp521r1_T_17_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_18_X, secp521r1_T_18_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_19_X, secp521r1_T_19_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_20_X, secp521r1_T_20_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_21_X, secp521r1_T_21_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_22_X, secp521r1_T_22_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_23_X, secp521r1_T_23_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_24_X, secp521r1_T_24_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_25_X, secp521r1_T_25_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_26_X, secp521r1_T_26_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_27_X, secp521r1_T_27_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_28_X, secp521r1_T_28_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_29_X, secp521r1_T_29_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_30_X, secp521r1_T_30_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_31_X, secp521r1_T_31_Y), +}; +#else +#define secp521r1_T NULL +#endif +#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), +}; + +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint secp192k1_T_0_X[] = { + 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_T_0_Y[] = { + 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_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x77, 0x3D, 0x0D, 0x85, 0x48, 0xA8, 0xA9), + MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x07, 0xDF, 0x1D, 0xB3, 0xB3, 0x01, 0x54), + MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x86, 0xF6, 0xAF, 0x19, 0x2A, 0x88, 0x2E), +}; +static const mbedtls_mpi_uint secp192k1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x90, 0xB6, 0x2F, 0x48, 0x36, 0x4C, 0x5B), + MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x11, 0x14, 0xA6, 0xCB, 0xBA, 0x15, 0xD9), + MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0xB0, 0xF2, 0xD4, 0xC9, 0xDA, 0xBA, 0xD7), +}; +static const mbedtls_mpi_uint secp192k1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0xC1, 0x9C, 0xE6, 0xBB, 0xFB, 0xCF, 0x23), + MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x19, 0xAC, 0x5A, 0xC9, 0x8A, 0x1C, 0x75), + MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xF6, 0x76, 0x86, 0x89, 0x27, 0x8D, 0x28), +}; +static const mbedtls_mpi_uint secp192k1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xE0, 0x6F, 0x34, 0xBA, 0x5E, 0xD3, 0x96), + MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0xDC, 0xA6, 0x87, 0xC9, 0x9D, 0xC0, 0x82), + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x11, 0x7E, 0xD6, 0xF7, 0x33, 0xFC, 0xE4), +}; +static const mbedtls_mpi_uint secp192k1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x37, 0x3E, 0xC0, 0x7F, 0x62, 0xE7, 0x54), + MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x3B, 0x69, 0x9D, 0x44, 0xBC, 0x82, 0x99), + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x84, 0xB3, 0x5F, 0x2B, 0xA5, 0x9E, 0x2C), +}; +static const mbedtls_mpi_uint secp192k1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x95, 0xEB, 0x4C, 0x04, 0xB4, 0xF4, 0x75), + MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xAD, 0x4B, 0xD5, 0x9A, 0xEB, 0xC4, 0x4E), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xB1, 0xC5, 0x59, 0xE3, 0xD5, 0x16, 0x2A), +}; +static const mbedtls_mpi_uint secp192k1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x2A, 0xCC, 0xAC, 0xD0, 0xEE, 0x50, 0xEC), + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x83, 0xE0, 0x5B, 0x14, 0x44, 0x52, 0x20), + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x15, 0x2D, 0x78, 0xF6, 0x51, 0x32, 0xCF), +}; +static const mbedtls_mpi_uint secp192k1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x36, 0x9B, 0xDD, 0xF8, 0xDD, 0xEF, 0xB2), + MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xB1, 0x6A, 0x2B, 0xAF, 0xEB, 0x2B, 0xB1), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x87, 0x7A, 0x66, 0x5D, 0x5B, 0xDF, 0x8F), +}; +static const mbedtls_mpi_uint secp192k1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x45, 0xE5, 0x81, 0x9B, 0xEB, 0x37, 0x23), + MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x29, 0xE2, 0x20, 0x64, 0x23, 0x6B, 0x6E), + MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x1D, 0x41, 0xE1, 0x9B, 0x61, 0x7B, 0xD9), +}; +static const mbedtls_mpi_uint secp192k1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x57, 0xA3, 0x0A, 0x13, 0xE4, 0x59, 0x15), + MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x6E, 0x4A, 0x48, 0x84, 0x90, 0xAC, 0xC7), + MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xB8, 0xF5, 0xF3, 0xDE, 0xA0, 0xA1, 0x1D), +}; +static const mbedtls_mpi_uint secp192k1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x32, 0x81, 0xA9, 0x91, 0x5A, 0x4E, 0x33), + MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0xA8, 0x90, 0xBE, 0x0F, 0xEC, 0xC0, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x30, 0xD7, 0x08, 0xAE, 0xC4, 0x3A, 0xA5), +}; +static const mbedtls_mpi_uint secp192k1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x55, 0xE3, 0x76, 0xB3, 0x64, 0x74, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x75, 0xD4, 0xDB, 0x98, 0xD7, 0x39, 0xAE), + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xEB, 0x8A, 0xAB, 0x16, 0xD9, 0xD4, 0x0B), +}; +static const mbedtls_mpi_uint secp192k1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xBE, 0xF9, 0xC7, 0xC7, 0xBA, 0xF3, 0xA1), + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x85, 0x59, 0xF3, 0x60, 0x41, 0x02, 0xD2), + MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x1C, 0x4A, 0xA4, 0xC7, 0xED, 0x66, 0xBC), +}; +static const mbedtls_mpi_uint secp192k1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x9C, 0x2E, 0x46, 0x52, 0x18, 0x87, 0x14), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x35, 0x5A, 0x75, 0xAC, 0x4D, 0x75, 0x91), + MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0x2F, 0xAC, 0xFC, 0xBC, 0xE6, 0x93, 0x5E), +}; +static const mbedtls_mpi_uint secp192k1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x4D, 0xC9, 0x18, 0xE9, 0x00, 0xEB, 0x33), + MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x69, 0x72, 0x07, 0x5A, 0x59, 0xA8, 0x26), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x65, 0x83, 0x20, 0x10, 0xF9, 0x69, 0x82), +}; +static const mbedtls_mpi_uint secp192k1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x56, 0x7F, 0x9F, 0xBF, 0x46, 0x0C, 0x7E), + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0xCF, 0xF0, 0xDC, 0xDF, 0x2D, 0xE6, 0xE5), + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0xF0, 0x72, 0x3A, 0x7A, 0x03, 0xE5, 0x22), +}; +static const mbedtls_mpi_uint secp192k1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xAA, 0x57, 0x13, 0x37, 0xA7, 0x2C, 0xD4), + MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xAC, 0xA2, 0x23, 0xF9, 0x84, 0x60, 0xD3), + MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xEB, 0x51, 0x70, 0x64, 0x78, 0xCA, 0x05), +}; +static const mbedtls_mpi_uint secp192k1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xCC, 0x30, 0x62, 0x93, 0x46, 0x13, 0xE9), + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x26, 0xCC, 0x6C, 0x3D, 0x5C, 0xDA, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xAA, 0xB8, 0x03, 0xA4, 0x1A, 0x00, 0x96), +}; +static const mbedtls_mpi_uint secp192k1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x9D, 0xE6, 0xCC, 0x4E, 0x2E, 0xC2, 0xD5), + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xC3, 0x8A, 0xAE, 0x6F, 0x40, 0x05, 0xEB), + MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x8F, 0x4A, 0x4D, 0x35, 0xD3, 0x50, 0x9D), +}; +static const mbedtls_mpi_uint secp192k1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xFD, 0x98, 0xAB, 0xC7, 0x03, 0xB4, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x40, 0xD2, 0x9F, 0xCA, 0xD0, 0x53, 0x00), + MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x84, 0x00, 0x6F, 0xC8, 0xAD, 0xED, 0x8D), +}; +static const mbedtls_mpi_uint secp192k1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xD3, 0x57, 0xD7, 0xC3, 0x07, 0xBD, 0xD7), + MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0xBA, 0x47, 0x1D, 0x3D, 0xEF, 0x98, 0x6C), + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xC0, 0x6C, 0x7F, 0x12, 0xEE, 0x9F, 0x67), +}; +static const mbedtls_mpi_uint secp192k1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x02, 0xDA, 0x79, 0xAA, 0xC9, 0x27, 0xC4), + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x79, 0xC7, 0x71, 0x84, 0xCB, 0xE5, 0x5A), + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x37, 0x06, 0xBA, 0xB5, 0xD5, 0x18, 0x4C), +}; +static const mbedtls_mpi_uint secp192k1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x65, 0x72, 0x6C, 0xF2, 0x63, 0x27, 0x6A), + MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xBC, 0x71, 0xDF, 0x75, 0xF8, 0x98, 0x4D), + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x70, 0x9B, 0xDC, 0xE7, 0x18, 0x71, 0xFF), +}; +static const mbedtls_mpi_uint secp192k1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x5B, 0x9F, 0x00, 0x5A, 0xB6, 0x80, 0x7A), + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xE0, 0xBB, 0xFC, 0x5E, 0x78, 0x9C, 0x89), + MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x03, 0x68, 0x83, 0x3D, 0x2E, 0x4C, 0xDD), +}; +static const mbedtls_mpi_uint secp192k1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x49, 0x23, 0xA8, 0xCB, 0x3B, 0x1A, 0xF6), + MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x3D, 0xA7, 0x46, 0xCF, 0x75, 0xB6, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xFD, 0x30, 0x01, 0xB6, 0xEF, 0xF9, 0xE8), +}; +static const mbedtls_mpi_uint secp192k1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xFA, 0xDA, 0xB8, 0x29, 0x42, 0xC9, 0xC7), + MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xD7, 0xA0, 0xE6, 0x6B, 0x86, 0x61, 0x39), + MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0xE9, 0xD3, 0x37, 0xD8, 0xE7, 0x35, 0xA9), +}; +static const mbedtls_mpi_uint secp192k1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xC8, 0x8E, 0xB1, 0xCB, 0xB1, 0xB5, 0x4D), + MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xD7, 0x46, 0x7D, 0xAF, 0xE2, 0xDC, 0xBB), + MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x46, 0xE7, 0xD8, 0x76, 0x31, 0x90, 0x76), +}; +static const mbedtls_mpi_uint secp192k1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xD3, 0xF4, 0x74, 0xE1, 0x67, 0xD8, 0x66), + MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x70, 0x3C, 0xC8, 0xAF, 0x5F, 0xF4, 0x58), + MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x4E, 0xED, 0x5C, 0x43, 0xB3, 0x16, 0x35), +}; +static const mbedtls_mpi_uint secp192k1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xAE, 0xD1, 0xDD, 0x31, 0x14, 0xD3, 0xF0), + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x14, 0x06, 0x13, 0x12, 0x1C, 0x81, 0xF5), + MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xF9, 0x0C, 0x91, 0xF7, 0x67, 0x59, 0x63), +}; +static const mbedtls_mpi_uint secp192k1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x91, 0xE2, 0xF4, 0x9D, 0xEB, 0x88, 0x87), + MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x82, 0x30, 0x9C, 0xAE, 0x18, 0x4D, 0xB7), + MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x79, 0xCF, 0x17, 0xA5, 0x1E, 0xE8, 0xC8), +}; +static const mbedtls_ecp_point secp192k1_T[16] = { + ECP_POINT_INIT_XY_Z1(secp192k1_T_0_X, secp192k1_T_0_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_1_X, secp192k1_T_1_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_2_X, secp192k1_T_2_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_3_X, secp192k1_T_3_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_4_X, secp192k1_T_4_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_5_X, secp192k1_T_5_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_6_X, secp192k1_T_6_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_7_X, secp192k1_T_7_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_8_X, secp192k1_T_8_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_9_X, secp192k1_T_9_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_10_X, secp192k1_T_10_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_11_X, secp192k1_T_11_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_12_X, secp192k1_T_12_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_13_X, secp192k1_T_13_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_14_X, secp192k1_T_14_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_15_X, secp192k1_T_15_Y), +}; +#else +#define secp192k1_T NULL +#endif + +#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), +}; + +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint secp224k1_T_0_X[] = { + 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_8(0x33, 0x5B, 0x45, 0xA1, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_0_Y[] = { + 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_8(0xED, 0x9F, 0x08, 0x7E, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x6C, 0x22, 0x22, 0x40, 0x89, 0xAE, 0x7A), + MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x92, 0xE1, 0x87, 0x56, 0x35, 0xAF, 0x9B), + MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xAF, 0x08, 0x35, 0x27, 0xEA, 0x04, 0xED), + MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x53, 0xFD, 0xCF, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xD0, 0x9F, 0x8D, 0xF3, 0x63, 0x54, 0x30), + MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0xDB, 0x0F, 0x61, 0x54, 0x26, 0xD1, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x21, 0xF7, 0x1B, 0xB5, 0x1D, 0xF6, 0x7E), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x05, 0xDA, 0x8F, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x26, 0x73, 0xBC, 0xE4, 0x29, 0x62, 0x56), + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x95, 0x17, 0x8B, 0xC3, 0x9B, 0xAC, 0xCC), + MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xDB, 0x77, 0xDF, 0xDD, 0x13, 0x04, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0xFC, 0x22, 0x93, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x65, 0xF1, 0x5A, 0x37, 0xEF, 0x79, 0xAD), + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x01, 0x37, 0xAC, 0x9A, 0x5B, 0x51, 0x65), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x75, 0x13, 0xA9, 0x4A, 0xAD, 0xFE, 0x9B), + MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x82, 0x6F, 0x66, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x5E, 0xF0, 0x40, 0xC3, 0xA6, 0xE2, 0x1E), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x9A, 0x6F, 0xCF, 0x11, 0x26, 0x66, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x73, 0xA8, 0xCF, 0x2B, 0x12, 0x36, 0x37), + MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xB3, 0x0A, 0x58, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x79, 0x00, 0x55, 0x04, 0x34, 0x90, 0x1A), + MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x54, 0x1C, 0xC2, 0x45, 0x0C, 0x1B, 0x23), + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x19, 0xAB, 0xA8, 0xFC, 0x73, 0xDC, 0xEE), + MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0xFB, 0x93, 0xCE, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x75, 0xD0, 0x66, 0x95, 0x86, 0xCA, 0x66), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xEA, 0x29, 0x16, 0x6A, 0x38, 0xDF, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA2, 0x36, 0x2F, 0xDC, 0xBB, 0x5E, 0xF7), + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x89, 0x59, 0x49, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xA3, 0x99, 0x9D, 0xB8, 0x77, 0x9D, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x93, 0x43, 0x47, 0xC6, 0x5C, 0xF9, 0xFD), + MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x00, 0x79, 0x42, 0x64, 0xB8, 0x25, 0x3E), + MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x54, 0xB4, 0x33, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x0C, 0x42, 0x90, 0x83, 0x0B, 0x31, 0x5F), + MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x2E, 0xAE, 0xC8, 0xC7, 0x5F, 0xD2, 0x70), + MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xBC, 0xAD, 0x41, 0xE7, 0x32, 0x3A, 0x81), + MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x97, 0x52, 0x83, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x13, 0x7A, 0xBD, 0xAE, 0x94, 0x60, 0xFD), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x9B, 0x95, 0xB4, 0x6E, 0x68, 0xB2, 0x1F), + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x49, 0xBE, 0x51, 0xFE, 0x66, 0x15, 0x74), + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x37, 0xE4, 0xFE, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x9B, 0xEE, 0x64, 0xC9, 0x1B, 0xBD, 0x77), + MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x5F, 0x34, 0xA9, 0x0B, 0xB7, 0x25, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x13, 0xB1, 0x38, 0xFB, 0x9D, 0x78, 0xED), + MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0xE7, 0x1B, 0xFA, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xB3, 0xB7, 0x44, 0x92, 0x6B, 0x00, 0x82), + MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x82, 0x44, 0x3E, 0x18, 0x1A, 0x58, 0x6A), + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0xF8, 0xC0, 0xE4, 0xEE, 0xC1, 0xBF, 0x44), + MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x32, 0x27, 0xB2, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x9A, 0x42, 0x62, 0x8B, 0x26, 0x54, 0x21), + MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x85, 0x74, 0xA0, 0x79, 0xA8, 0xEE, 0xBE), + MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x36, 0x60, 0xB3, 0x28, 0x4D, 0x55, 0xBE), + MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x27, 0x82, 0x29, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0xFC, 0x73, 0x77, 0xAF, 0x5C, 0xAC, 0x78), + MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0xED, 0xE5, 0xF6, 0x1D, 0xA8, 0x67, 0x43), + MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xDE, 0x33, 0x1C, 0xF1, 0x80, 0x73, 0xF8), + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xE2, 0xDE, 0x3C, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x3E, 0x6B, 0xFE, 0xF0, 0x04, 0x28, 0x01), + MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xB2, 0x14, 0x9D, 0x18, 0x11, 0x7D, 0x9D), + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xC4, 0xD6, 0x2E, 0x6E, 0x57, 0x4D, 0xE1), + MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x55, 0x1B, 0xDE, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xF7, 0x17, 0xBC, 0x45, 0xAB, 0x16, 0xAB), + MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xB0, 0xEF, 0x61, 0xE3, 0x20, 0x7C, 0xF8), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x85, 0x41, 0x4D, 0xF1, 0x7E, 0x4D, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xC2, 0x9B, 0x5E, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x2E, 0x49, 0x3D, 0x3E, 0x4B, 0xD3, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x2B, 0x9D, 0xD5, 0x27, 0xFA, 0xCA, 0xE0), + MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0xB3, 0x6A, 0xE0, 0x79, 0x14, 0x28, 0x0F), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x1E, 0xDC, 0xF5, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x44, 0x56, 0xCD, 0xFC, 0x9F, 0x09, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x8C, 0x59, 0xA4, 0x64, 0x2A, 0x3A, 0xED), + MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xA0, 0xB5, 0x86, 0x4E, 0x69, 0xDA, 0x06), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x8B, 0x11, 0x38, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x17, 0x16, 0x12, 0x17, 0xDC, 0x00, 0x7E), + MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x76, 0x24, 0x6C, 0x97, 0x2C, 0xB5, 0xF9), + MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x71, 0xE3, 0xB0, 0xBB, 0x4E, 0x50, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0x48, 0x26, 0xD5, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x5F, 0x28, 0xF6, 0x01, 0x5A, 0x60, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x95, 0xFE, 0xD0, 0xAD, 0x15, 0xD4, 0xD9), + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x5B, 0x7A, 0xFD, 0x80, 0xF7, 0x9F, 0x64), + MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xBC, 0x1B, 0xDF, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xE6, 0xDF, 0x14, 0x29, 0xF4, 0xD4, 0x14), + MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x12, 0xDD, 0xEC, 0x5B, 0x8A, 0x59, 0xE5), + MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x92, 0x3E, 0x35, 0x08, 0xE9, 0xCF, 0x0E), + MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x35, 0x29, 0x97, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xDB, 0xD6, 0x6A, 0xC5, 0x43, 0xA4, 0xA1), + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x33, 0x50, 0x61, 0x70, 0xA1, 0xE9, 0xCE), + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x15, 0x6E, 0x5F, 0x01, 0x0C, 0x8C, 0xFA), + MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0xA1, 0x9A, 0x9D, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xC6, 0xF7, 0xE2, 0x4A, 0xCD, 0x9B, 0x61), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x4D, 0x5A, 0xB8, 0xE2, 0x6D, 0xA6, 0x50), + MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x3F, 0xB6, 0x17, 0xE3, 0x2C, 0x6F, 0x65), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xA4, 0x59, 0x51, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x4F, 0x7C, 0x49, 0xCD, 0x6E, 0xEB, 0x3C), + MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0xC9, 0x1F, 0xB7, 0x4D, 0x98, 0xC7, 0x67), + MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0xFD, 0x98, 0x20, 0x95, 0xBB, 0x20, 0x3A), + MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xF2, 0x73, 0x92, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xEF, 0xFB, 0x30, 0xFA, 0x12, 0x1A, 0xB0), + MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0x4C, 0x24, 0xB4, 0x5B, 0xC9, 0x4C, 0x0F), + MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xDD, 0x5E, 0x84, 0x95, 0x4D, 0x26, 0xED), + MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xFA, 0xF9, 0x3A, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0xA3, 0x2E, 0x7A, 0xDC, 0xA7, 0x53, 0xA9), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x9F, 0x81, 0x84, 0xB2, 0x0D, 0xFE, 0x31), + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x89, 0x1B, 0x77, 0x0C, 0x89, 0x71, 0xEC), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xFF, 0x7F, 0xB2, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xE9, 0x2C, 0x79, 0xA6, 0x3C, 0xAD, 0x93), + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xE0, 0x23, 0x02, 0x86, 0x0F, 0x77, 0x2A), + MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x93, 0x6D, 0xE9, 0xF9, 0x3C, 0xBE, 0xB9), + MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xE7, 0x24, 0x92, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x3C, 0x5B, 0x4B, 0x1B, 0x25, 0x37, 0xD6), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xE8, 0x38, 0x1B, 0xA1, 0x5A, 0x2E, 0x68), + MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x19, 0xFD, 0xF4, 0x78, 0x01, 0x6B, 0x44), + MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0x69, 0x37, 0x4F, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0xE2, 0xBF, 0xD3, 0xEC, 0x95, 0x9C, 0x03), + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x7B, 0xFC, 0xD5, 0xD3, 0x25, 0x5E, 0x0F), + MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x55, 0x09, 0xA2, 0x58, 0x6A, 0xC9, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0xCC, 0x3B, 0xD9, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_mpi_uint secp224k1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0x08, 0x65, 0x5E, 0xCB, 0xAB, 0x48, 0xC8), + MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x79, 0x8B, 0xC0, 0x11, 0xC0, 0x69, 0x38), + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xE8, 0x8C, 0x4C, 0xC5, 0x28, 0xE4, 0xAE), + MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x1F, 0x34, 0x5C, 0x00, 0x00, 0x00, 0x00), +}; +static const mbedtls_ecp_point secp224k1_T[16] = { + ECP_POINT_INIT_XY_Z1(secp224k1_T_0_X, secp224k1_T_0_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_1_X, secp224k1_T_1_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_2_X, secp224k1_T_2_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_3_X, secp224k1_T_3_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_4_X, secp224k1_T_4_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_5_X, secp224k1_T_5_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_6_X, secp224k1_T_6_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_7_X, secp224k1_T_7_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_8_X, secp224k1_T_8_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_9_X, secp224k1_T_9_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_10_X, secp224k1_T_10_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_11_X, secp224k1_T_11_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_12_X, secp224k1_T_12_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_13_X, secp224k1_T_13_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_14_X, secp224k1_T_14_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_15_X, secp224k1_T_15_Y), +}; +#else +#define secp224k1_T NULL +#endif +#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), +}; + +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint secp256k1_T_0_X[] = { + 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_T_0_Y[] = { + 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_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xEE, 0xD7, 0x1E, 0x67, 0x86, 0x32, 0x74), + MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x73, 0xB1, 0xA9, 0xD5, 0xCC, 0x27, 0x78), + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x0E, 0x11, 0x01, 0x71, 0xFE, 0x92, 0x73), + MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x28, 0x63, 0x6D, 0x72, 0x09, 0xA6, 0xC0), +}; +static const mbedtls_mpi_uint secp256k1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xE1, 0x69, 0xDC, 0x3E, 0x2C, 0x75, 0xC3), + MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xB7, 0x3F, 0x30, 0x26, 0x3C, 0xDF, 0x8E), + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xBE, 0xB9, 0x5D, 0x0E, 0xE8, 0x5E, 0x14), + MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0xC3, 0x05, 0xD6, 0xB7, 0xD5, 0x24, 0xFC), +}; +static const mbedtls_mpi_uint secp256k1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0xCF, 0x7B, 0xDC, 0xCD, 0xC3, 0x39, 0x9D), + MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xDA, 0xB9, 0xE5, 0x64, 0xA7, 0x47, 0x91), + MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x46, 0xA8, 0x61, 0xF6, 0x23, 0xEB, 0x58), + MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xC1, 0xFF, 0xE4, 0x55, 0xD5, 0xC2, 0xBF), +}; +static const mbedtls_mpi_uint secp256k1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xBE, 0xB9, 0x59, 0x24, 0x13, 0x4A, 0x2A), + MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x45, 0x12, 0xDE, 0xBA, 0x4F, 0xEF, 0x56), + MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x08, 0xBF, 0xC1, 0x66, 0xAA, 0x0A, 0xBC), + MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xFE, 0x30, 0x55, 0x31, 0x86, 0xA7, 0xB4), +}; +static const mbedtls_mpi_uint secp256k1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xBF, 0x18, 0x81, 0x67, 0x27, 0x42, 0xBD), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x05, 0x83, 0xA4, 0xDD, 0x57, 0xD3, 0x50), + MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x63, 0xAB, 0xE4, 0x90, 0x70, 0xD0, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x5D, 0xFD, 0xA0, 0xEF, 0xCF, 0x1C, 0x54), +}; +static const mbedtls_mpi_uint secp256k1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x80, 0xE4, 0xF6, 0x09, 0xBC, 0x57, 0x90), + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x9F, 0x6E, 0x88, 0x54, 0x6E, 0x51, 0xF2), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x5F, 0x85, 0xFB, 0x84, 0x3E, 0x4A, 0xAA), + MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x19, 0xF5, 0x55, 0xC9, 0x07, 0xD8, 0xCE), +}; +static const mbedtls_mpi_uint secp256k1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0xB4, 0xC3, 0xD9, 0x5C, 0xA0, 0xD4, 0x90), + MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x30, 0xAF, 0x59, 0x9B, 0xF8, 0x04, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xA6, 0xFD, 0x66, 0x7B, 0xC3, 0x39, 0x85), + MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xBF, 0xF0, 0xC2, 0xE9, 0x71, 0xA4, 0x9E), +}; +static const mbedtls_mpi_uint secp256k1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x2D, 0xB9, 0x88, 0x28, 0xF1, 0xBE, 0x78), + MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xF3, 0x1A, 0x0E, 0xB9, 0x01, 0x66, 0x34), + MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0xA7, 0xA4, 0xF4, 0x05, 0xD0, 0xAA, 0x53), + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x39, 0x1E, 0x47, 0xE5, 0x68, 0xC8, 0xC0), +}; +static const mbedtls_mpi_uint secp256k1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0xB9, 0xFC, 0xE0, 0x33, 0x8A, 0x7D, 0x96), + MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x93, 0xA5, 0x53, 0x55, 0x16, 0xB4, 0x6E), + MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x5F, 0xEA, 0x9B, 0x29, 0x52, 0x71, 0xDA), + MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xF0, 0x24, 0xB8, 0x7D, 0xB7, 0xA0, 0x9B), +}; +static const mbedtls_mpi_uint secp256k1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x00, 0x27, 0xB2, 0xDF, 0x73, 0xA2, 0xE0), + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x2E, 0x4D, 0x7C, 0xDE, 0x7A, 0x23, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x65, 0x60, 0xC7, 0x97, 0x1E, 0xA4, 0x22), + MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x13, 0x5B, 0x77, 0x59, 0xCB, 0x36, 0xE1), +}; +static const mbedtls_mpi_uint secp256k1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xBC, 0x9F, 0x9E, 0x2D, 0x53, 0x2A, 0xA8), + MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x5F, 0x64, 0x9F, 0x1A, 0x19, 0xE6, 0x77), + MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x7B, 0x39, 0xD2, 0xDB, 0x85, 0x84, 0xD5), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xC7, 0x0D, 0x58, 0x6E, 0x3F, 0x52, 0x15), +}; +static const mbedtls_mpi_uint secp256k1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x68, 0x19, 0x0B, 0x68, 0xC9, 0x1E, 0xFB), + MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x4E, 0x21, 0x49, 0x3D, 0x55, 0xCC, 0x25), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xF9, 0x25, 0x45, 0x54, 0x45, 0xB1, 0x0F), + MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xB3, 0xF7, 0xCD, 0x80, 0xA4, 0x04, 0x05), +}; +static const mbedtls_mpi_uint secp256k1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x1E, 0x88, 0xC4, 0xAA, 0x18, 0x7E, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xAC, 0xD9, 0xB2, 0xA1, 0xC0, 0x71, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xA2, 0xF1, 0x15, 0xA6, 0x5F, 0x6C, 0x86), + MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x5B, 0x05, 0xBC, 0xB7, 0xC6, 0x4E, 0x72), +}; +static const mbedtls_mpi_uint secp256k1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x80, 0xF8, 0x5C, 0x20, 0x2A, 0xE1, 0xE2), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x48, 0x2E, 0x68, 0x82, 0x7F, 0xEB, 0x5F), + MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x3B, 0x25, 0xDB, 0x32, 0x4D, 0x88, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x6E, 0xA6, 0xB6, 0x6D, 0x62, 0x78, 0x22), +}; +static const mbedtls_mpi_uint secp256k1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x4D, 0x3E, 0x86, 0x58, 0xC3, 0xEB, 0xBA), + MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x89, 0x33, 0x18, 0x21, 0x1D, 0x9B, 0xE7), + MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x9D, 0xFF, 0xC3, 0x79, 0xC1, 0x88, 0xF8), + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xD4, 0x48, 0x53, 0xE8, 0xAD, 0x21, 0x16), +}; +static const mbedtls_mpi_uint secp256k1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x7B, 0xDE, 0xCB, 0xD8, 0x39, 0x17, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0xF3, 0x03, 0xF2, 0x5C, 0xBC, 0xC8, 0x8A), + MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xAE, 0x4C, 0xB0, 0x16, 0xA4, 0x93, 0x86), + MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x8B, 0x6B, 0xDC, 0xD7, 0x9A, 0x3E, 0x7E), +}; +static const mbedtls_mpi_uint secp256k1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x2D, 0x7A, 0xD2, 0x59, 0x05, 0xA2, 0x82), + MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x56, 0x09, 0x32, 0xF1, 0xE8, 0xE3, 0x72), + MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xCA, 0xE5, 0x2E, 0xF0, 0xFB, 0x18, 0x19), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x85, 0xA9, 0x23, 0x15, 0x31, 0x1F, 0x0E), +}; +static const mbedtls_mpi_uint secp256k1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xE5, 0xB1, 0x86, 0xB9, 0x6E, 0x8D, 0xD3), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x77, 0xFC, 0xC9, 0xA3, 0x3F, 0x89, 0xD2), + MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x6A, 0xDC, 0x25, 0xB0, 0xC7, 0x41, 0x54), + MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x11, 0x6B, 0xA6, 0x11, 0x62, 0xD4, 0x2D), +}; +static const mbedtls_mpi_uint secp256k1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x7D, 0x34, 0xB3, 0x20, 0x7F, 0x37, 0xAA), + MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0xD4, 0x45, 0xE8, 0xC2, 0xE9, 0xC5, 0xEA), + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x32, 0x3B, 0x25, 0x7E, 0x79, 0xAF, 0xE7), + MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0xE4, 0x54, 0x71, 0xBE, 0x35, 0x4E, 0xD0), +}; +static const mbedtls_mpi_uint secp256k1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x94, 0xDD, 0x8F, 0xB5, 0xC2, 0xDD, 0x75), + MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x49, 0xE9, 0x1C, 0x2F, 0x08, 0x49, 0xC6), + MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0xB6, 0x03, 0x88, 0x6F, 0xB8, 0x15, 0x67), + MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xD3, 0x1C, 0xF3, 0xA5, 0xEB, 0x79, 0x01), +}; +static const mbedtls_mpi_uint secp256k1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0xF9, 0x43, 0x88, 0x89, 0x0D, 0x06, 0xEA), + MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x2D, 0xF5, 0x98, 0x32, 0xF6, 0xB1, 0x05), + MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x73, 0x8F, 0x2B, 0x50, 0x27, 0x0A, 0xE7), + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xE3, 0xBD, 0x16, 0x05, 0xC8, 0x93, 0x12), +}; +static const mbedtls_mpi_uint secp256k1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x6A, 0xF7, 0xE3, 0x3D, 0xDE, 0x5F, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xA3, 0x9C, 0x22, 0x3C, 0x33, 0x36, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x24, 0x4C, 0x69, 0x45, 0x78, 0x14, 0xAE), + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xF8, 0xD4, 0xBF, 0xB8, 0xC0, 0xA1, 0x25), +}; +static const mbedtls_mpi_uint secp256k1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x88, 0xE1, 0x91, 0x03, 0xEB, 0xB3, 0x2B), + MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x11, 0xA1, 0xEF, 0x14, 0x0D, 0xC4, 0x7D), + MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xD4, 0x0D, 0x1D, 0x96, 0x33, 0x5C, 0x19), + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x45, 0x2A, 0x1A, 0xE6, 0x57, 0x04, 0x9B), +}; +static const mbedtls_mpi_uint secp256k1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xB5, 0xA7, 0x80, 0xE9, 0x93, 0x97, 0x8D), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xB9, 0x7C, 0xA0, 0xC9, 0x57, 0x26, 0x43), + MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0xEF, 0x56, 0xDA, 0x66, 0xF6, 0x1B, 0x9A), + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x89, 0x6B, 0x91, 0xE0, 0xA9, 0x65, 0x2B), +}; +static const mbedtls_mpi_uint secp256k1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x98, 0x96, 0x9B, 0x06, 0x7D, 0x5E, 0x5A), + MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xFA, 0xC1, 0x5F, 0x19, 0x37, 0x94, 0x9D), + MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xBE, 0x6B, 0x1A, 0x05, 0xE4, 0xBF, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0xCD, 0x5D, 0x35, 0xB4, 0x51, 0xF7, 0x64), +}; +static const mbedtls_mpi_uint secp256k1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xEF, 0x96, 0xDB, 0xF2, 0x61, 0x63, 0x59), + MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x04, 0x88, 0xC9, 0x9F, 0x1B, 0x94, 0xB9), + MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x30, 0x79, 0x7E, 0x24, 0xE7, 0x5F, 0xB8), + MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0xB8, 0x90, 0xB7, 0x94, 0x25, 0xBB, 0x0F), +}; +static const mbedtls_mpi_uint secp256k1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x79, 0xEA, 0xAD, 0xC0, 0x6D, 0x18, 0x57), + MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xA4, 0x58, 0x2A, 0x8D, 0x95, 0xB3, 0xE6), + MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xC4, 0xC2, 0x12, 0x0D, 0x79, 0xE2, 0x2B), + MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x6F, 0xBE, 0x97, 0x4D, 0xA4, 0x20, 0x07), +}; +static const mbedtls_mpi_uint secp256k1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x31, 0x71, 0xC6, 0xA6, 0x91, 0xEB, 0x1F), + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x9B, 0xA8, 0x4A, 0xE7, 0x77, 0xE1, 0xAA), + MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x06, 0xD3, 0x3D, 0x94, 0x30, 0xEF, 0x8C), + MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xDF, 0xCA, 0xFA, 0xF5, 0x28, 0xF8, 0xC9), +}; +static const mbedtls_mpi_uint secp256k1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0xE1, 0x32, 0xFD, 0x3E, 0x81, 0xF8, 0x11), + MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xF2, 0x4B, 0x1D, 0x19, 0xC9, 0x0F, 0xCC), + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xB1, 0x8A, 0x22, 0x8B, 0x05, 0x6B, 0x56), + MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x21, 0xEF, 0x30, 0xEC, 0x09, 0x2A, 0x89), +}; +static const mbedtls_mpi_uint secp256k1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x84, 0x4A, 0x46, 0x07, 0x6C, 0x3C, 0x4C), + MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x18, 0x3A, 0xF4, 0xCC, 0xF5, 0xB2, 0xF2), + MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x8F, 0xCD, 0x0A, 0x9C, 0xF4, 0xBD, 0x95), + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x89, 0x7F, 0x8A, 0xB1, 0x52, 0x3A, 0xAB), +}; +static const mbedtls_ecp_point secp256k1_T[16] = { + ECP_POINT_INIT_XY_Z1(secp256k1_T_0_X, secp256k1_T_0_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_1_X, secp256k1_T_1_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_2_X, secp256k1_T_2_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_3_X, secp256k1_T_3_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_4_X, secp256k1_T_4_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_5_X, secp256k1_T_5_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_6_X, secp256k1_T_6_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_7_X, secp256k1_T_7_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_8_X, secp256k1_T_8_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_9_X, secp256k1_T_9_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_10_X, secp256k1_T_10_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_11_X, secp256k1_T_11_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_12_X, secp256k1_T_12_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_13_X, secp256k1_T_13_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_14_X, secp256k1_T_14_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_15_X, secp256k1_T_15_Y), +}; +#else +#define secp256k1_T NULL +#endif +#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), +}; + +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint brainpoolP256r1_T_0_X[] = { + 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_T_0_Y[] = { + 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_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xA2, 0xED, 0x52, 0xC9, 0x8C, 0xE3, 0xA5), + MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0xC9, 0xC4, 0x87, 0x3F, 0x93, 0x7A, 0xD1), + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x12, 0x53, 0x61, 0x3E, 0x76, 0x08, 0xCB), + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x8C, 0x74, 0xF4, 0x08, 0xC3, 0x76, 0x80), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0xDD, 0x09, 0xA6, 0xED, 0xEE, 0xC4, 0x38), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xD9, 0xBE, 0x4B, 0xA5, 0xB7, 0x2B, 0x6E), + MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x20, 0x12, 0xCA, 0x0A, 0x38, 0x24, 0xAB), + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x72, 0x71, 0x90, 0x7A, 0x2E, 0xB7, 0x23), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x66, 0xA1, 0x93, 0x10, 0x2A, 0x51, 0x17), + MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x10, 0x11, 0x12, 0xBC, 0xB0, 0xB6, 0x93), + MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x58, 0xD7, 0x0A, 0x84, 0x05, 0xA3, 0x9C), + MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x8E, 0x95, 0x61, 0xD3, 0x0B, 0xDF, 0x36), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x92, 0x12, 0x0F, 0x5E, 0x87, 0x70, 0x1B), + MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0xE9, 0x9B, 0xEB, 0x3A, 0xFB, 0xCF, 0xC4), + MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0x92, 0xB9, 0xF7, 0x45, 0xD3, 0x06, 0xB6), + MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x28, 0x65, 0xE1, 0xC5, 0x6C, 0x57, 0x18), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x0E, 0x77, 0x01, 0x81, 0x9E, 0x38, 0x5C), + MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0xF0, 0xD5, 0xA5, 0x91, 0x2B, 0xDF, 0xC0), + MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xEE, 0xB6, 0x25, 0xD6, 0x98, 0xDE, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xA1, 0x55, 0x63, 0x39, 0xEB, 0xB5, 0x47), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0xD6, 0xB8, 0xE3, 0x13, 0xED, 0x7F, 0xA3), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xE8, 0xAE, 0x36, 0xB8, 0xCD, 0x19, 0x02), + MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x82, 0x83, 0x7A, 0x7B, 0x46, 0x56, 0xE8), + MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x60, 0x46, 0x15, 0x5A, 0xAC, 0x99, 0x30), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x61, 0x50, 0xC6, 0xFF, 0x10, 0x7D, 0x04), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x51, 0xDF, 0xA9, 0x7D, 0x78, 0x26, 0x74), + MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0x15, 0x9A, 0xF7, 0x01, 0xC1, 0xBB, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x0F, 0xE6, 0x2A, 0xBD, 0x4A, 0x9E, 0x87), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xF8, 0xD1, 0x77, 0xD2, 0x49, 0xB3, 0xDD), + MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x86, 0xFB, 0x9E, 0x1F, 0x5A, 0x60, 0x47), + MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xC4, 0x8D, 0xCD, 0x86, 0x61, 0x2F, 0xF9), + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xF6, 0xB9, 0xAC, 0x37, 0x9D, 0xE9, 0x28), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x77, 0xAA, 0x97, 0x9C, 0x0B, 0x04, 0x20), + MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0xA6, 0x60, 0x81, 0xCE, 0x25, 0x13, 0x3E), + MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x00, 0xF3, 0xBB, 0x82, 0x99, 0x95, 0xB7), + MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x5A, 0xCE, 0x90, 0x71, 0x38, 0x2F, 0x10), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x1A, 0xC0, 0x84, 0x27, 0xD6, 0x9D, 0xB7), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x37, 0x52, 0x16, 0x13, 0x0E, 0xCE, 0x92), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xBF, 0x5A, 0xDB, 0xDB, 0x6E, 0x1E, 0x69), + MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xB7, 0x5E, 0xF9, 0x86, 0xDD, 0x8A, 0x5C), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xAB, 0x5C, 0x8D, 0x1D, 0xF2, 0x2D, 0x1E), + MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0xC5, 0xF8, 0xF7, 0x1D, 0x96, 0x0B, 0x4D), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x4C, 0xA7, 0x45, 0x20, 0x6A, 0x1E, 0x5B), + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x5D, 0xEF, 0xDE, 0xEE, 0x39, 0x44, 0x19), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x2F, 0x6D, 0x52, 0xC9, 0x58, 0x60, 0xE8), + MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0xC9, 0x62, 0xCB, 0x38, 0x3C, 0x55, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xA5, 0x09, 0x10, 0x88, 0xDB, 0xE3, 0xBD), + MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xE0, 0x3C, 0xCE, 0x06, 0x0B, 0x4B, 0x5D), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x1D, 0xB4, 0x10, 0x76, 0x8F, 0xBA, 0x09), + MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x70, 0x5A, 0x07, 0xF5, 0x1A, 0x74, 0xC7), + MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xE9, 0x94, 0xA8, 0xC0, 0xD5, 0x4A, 0x4A), + MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x6D, 0xD4, 0xE8, 0x9B, 0xE9, 0x6D, 0x0E), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x00, 0x32, 0x41, 0x57, 0x84, 0x89, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xC7, 0x14, 0xEC, 0xE9, 0x27, 0xFF, 0xF3), + MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x67, 0x9E, 0xFB, 0xB6, 0xB8, 0x96, 0xF3), + MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x4A, 0xE3, 0x97, 0x4B, 0x58, 0xDE, 0x30), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0x1E, 0x5C, 0xF5, 0x7F, 0xD5, 0xD4, 0xAA), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x08, 0x7A, 0xF1, 0xBD, 0x89, 0xC7, 0x1E), + MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xF9, 0x11, 0x1B, 0xF5, 0x3C, 0x6D, 0x8C), + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x50, 0xE5, 0x69, 0x1D, 0x59, 0xFC, 0x0C), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x2F, 0xF8, 0x3F, 0xEC, 0x55, 0x99, 0x57), + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xA7, 0x29, 0x90, 0x43, 0x81, 0x31, 0x4C), + MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x18, 0x44, 0x50, 0x5D, 0x76, 0xCB, 0xDD), + MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xC5, 0x5B, 0x9A, 0x03, 0xE6, 0x17, 0x39), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x89, 0xFC, 0x55, 0x94, 0x91, 0x6A, 0xA2), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x46, 0x35, 0xF2, 0x3A, 0x42, 0x08, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0xD2, 0x76, 0x49, 0x42, 0x87, 0xD3, 0x7F), + MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xEA, 0xA0, 0x52, 0xF1, 0x6A, 0x30, 0x57), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0xB2, 0x57, 0xA3, 0x8A, 0x4D, 0x1B, 0x3C), + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0xA3, 0x99, 0x94, 0xB5, 0x3D, 0x64, 0x09), + MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xC3, 0xD7, 0x53, 0xF6, 0x49, 0x1C, 0x60), + MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x23, 0x41, 0x4D, 0xFB, 0x7A, 0x5C, 0x53), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xB8, 0x15, 0x65, 0x5C, 0x85, 0x94, 0xD7), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x37, 0xC7, 0xF8, 0x7E, 0xAE, 0x6C, 0x10), + MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xD8, 0x11, 0x54, 0x98, 0x44, 0xE3, 0xF1), + MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x4D, 0xA6, 0x4B, 0x28, 0xF2, 0x57, 0x9E), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xD0, 0xEB, 0x1E, 0xAA, 0x30, 0xD3, 0x6A), + MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x9B, 0x4D, 0xA7, 0x73, 0x6E, 0xB6, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x47, 0xF6, 0xED, 0x37, 0xEF, 0x71, 0x4D), + MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0xB5, 0x49, 0x61, 0x5E, 0x45, 0xF6, 0x4A), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x0E, 0xB3, 0x84, 0x3A, 0x63, 0x72, 0x84), + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x53, 0x5C, 0xA7, 0xC6, 0x2E, 0xAB, 0x9E), + MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x0F, 0x8F, 0x87, 0x50, 0x28, 0xB4, 0xAE), + MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x98, 0x4A, 0x98, 0x31, 0x86, 0xCA, 0x51), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xC9, 0xE2, 0xFD, 0x5D, 0x1F, 0xE8, 0xC2), + MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x90, 0x91, 0xC4, 0x84, 0xF0, 0xBA, 0xC5), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x5A, 0xB3, 0x4E, 0xFB, 0xE0, 0x57, 0xE8), + MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x0B, 0x90, 0xA6, 0xFD, 0x9D, 0x8E, 0x02), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x41, 0x8F, 0x31, 0xFA, 0x5A, 0xF6, 0x33), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xE9, 0xE3, 0xF6, 0xE0, 0x4A, 0xE7, 0xD2), + MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x4E, 0xCD, 0xA2, 0x22, 0x14, 0xD4, 0x12), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xED, 0x21, 0xB7, 0x0F, 0x53, 0x10, 0x17), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x06, 0x24, 0x2C, 0x4E, 0xD1, 0x1E, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x3F, 0xC1, 0x9F, 0xAB, 0xF0, 0x37, 0x95), + MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x5E, 0x12, 0xCE, 0x83, 0x1B, 0x2A, 0x18), + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x65, 0xCF, 0xE8, 0x5C, 0xA5, 0xA2, 0x70), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x86, 0x76, 0x3A, 0x94, 0xF6, 0x1D, 0xC1), + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xDA, 0xC9, 0xA6, 0x29, 0x93, 0x15, 0x10), + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x61, 0x6A, 0x7D, 0xC7, 0xA9, 0xF3, 0x76), + MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x03, 0x71, 0xA2, 0x15, 0xCE, 0x50, 0x72), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0xD0, 0xA8, 0x1E, 0x91, 0xC4, 0x4F, 0x24), + MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x4B, 0x7E, 0xD7, 0x71, 0x58, 0x7E, 0x1E), + MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x45, 0xAF, 0x2A, 0x18, 0x93, 0x95, 0x3B), + MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x8F, 0xC7, 0xFA, 0x4C, 0x7A, 0x86, 0x54), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0xAF, 0x68, 0x3A, 0x23, 0xC1, 0x2E, 0xBF), + MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x50, 0x11, 0x67, 0x39, 0xB9, 0xAF, 0x48), + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x86, 0xAA, 0x1E, 0x88, 0x21, 0x29, 0x8B), + MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x28, 0xA4, 0x9D, 0x89, 0xA9, 0x9A, 0x10), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xBA, 0x04, 0x67, 0xB7, 0x01, 0x40, 0x38), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xE9, 0x09, 0xA3, 0xCA, 0xA6, 0x37, 0xF6), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x97, 0xA8, 0xB6, 0x3C, 0xEE, 0x90, 0x3D), + MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xED, 0xC4, 0xF7, 0xC3, 0x95, 0xEC, 0x85), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x84, 0xBD, 0xEB, 0xD5, 0x64, 0xBB, 0x9D), + MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x9B, 0xE2, 0x28, 0x50, 0xC2, 0x72, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0xF2, 0x74, 0xD1, 0x26, 0xBF, 0x32, 0x68), + MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xCB, 0xAF, 0x72, 0xDB, 0x6D, 0x30, 0x98), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x50, 0x85, 0xF4, 0x2B, 0x48, 0xC1, 0xAD), + MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x28, 0xBB, 0x11, 0xBA, 0x5B, 0x22, 0x6C), + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xA1, 0xE5, 0x5C, 0xC9, 0x1D, 0x44, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xE8, 0xE6, 0x6F, 0xBB, 0xC1, 0x81, 0x7F), +}; +static const mbedtls_ecp_point brainpoolP256r1_T[16] = { + ECP_POINT_INIT_XY_Z1(brainpoolP256r1_T_0_X, brainpoolP256r1_T_0_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_1_X, brainpoolP256r1_T_1_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_2_X, brainpoolP256r1_T_2_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_3_X, brainpoolP256r1_T_3_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_4_X, brainpoolP256r1_T_4_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_5_X, brainpoolP256r1_T_5_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_6_X, brainpoolP256r1_T_6_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_7_X, brainpoolP256r1_T_7_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_8_X, brainpoolP256r1_T_8_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_9_X, brainpoolP256r1_T_9_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_10_X, brainpoolP256r1_T_10_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_11_X, brainpoolP256r1_T_11_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_12_X, brainpoolP256r1_T_12_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_13_X, brainpoolP256r1_T_13_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_14_X, brainpoolP256r1_T_14_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_15_X, brainpoolP256r1_T_15_Y), +}; +#else +#define brainpoolP256r1_T NULL +#endif + +#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), +}; + +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint brainpoolP384r1_T_0_X[] = { + 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_T_0_Y[] = { + 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_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0xD8, 0x8A, 0x54, 0x41, 0xD6, 0x6B, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x3B, 0xF1, 0x22, 0xFD, 0x2D, 0x4B, 0x03), + MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x55, 0xE3, 0x33, 0xF0, 0x73, 0x52, 0x5A), + MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x3F, 0x30, 0x26, 0xCA, 0x7F, 0x52, 0xA3), + MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x6E, 0x17, 0x9B, 0xD5, 0x2A, 0x4A, 0x31), + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xDA, 0x6B, 0xE5, 0x03, 0x07, 0x1D, 0x2E), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x7A, 0xAF, 0x98, 0xE3, 0xA4, 0xF6, 0x19), + MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x7D, 0xFE, 0x51, 0x40, 0x3B, 0x47, 0xD2), + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x88, 0xEC, 0xC4, 0xE2, 0x8F, 0xCB, 0xA4), + MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0xE2, 0x88, 0x2D, 0x4E, 0x50, 0xEB, 0x9A), + MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x54, 0x94, 0x5E, 0xF4, 0x7F, 0x3A, 0x04), + MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x07, 0x1C, 0xE1, 0xBD, 0x0F, 0xF8, 0x63), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x92, 0x28, 0x2E, 0x32, 0x04, 0xB1, 0x4D), + MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x82, 0x44, 0x43, 0x76, 0x0D, 0x55, 0xBF), + MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0xE3, 0xFF, 0x89, 0x46, 0xDE, 0x4E, 0xFE), + MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x22, 0xBB, 0x67, 0x1A, 0x81, 0xEE, 0x27), + MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x54, 0xE2, 0x7A, 0xAE, 0xDA, 0x2C, 0xD0), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x9A, 0x90, 0xAA, 0x6E, 0x8B, 0xCC, 0x5F), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x40, 0xAC, 0xED, 0x7D, 0x37, 0x87, 0xAC), + MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xF8, 0xB1, 0x80, 0x4C, 0x8C, 0x04, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x98, 0x2C, 0xAD, 0x30, 0x69, 0x35, 0xC0), + MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x2E, 0x00, 0x2F, 0x44, 0x8C, 0xF0, 0xC0), + MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x58, 0x07, 0xD7, 0xCD, 0x60, 0xA1, 0x5B), + MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xFB, 0x7B, 0x03, 0x05, 0x5E, 0x79, 0x73), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x17, 0xCE, 0x38, 0x4B, 0x5E, 0x5B, 0xC8), + MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x0E, 0x0A, 0x61, 0x9D, 0x7C, 0x62, 0x08), + MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0xF0, 0x98, 0x71, 0x7F, 0x17, 0x26, 0xD7), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xD3, 0xFA, 0x3C, 0xF0, 0x70, 0x07, 0x82), + MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x47, 0x5C, 0x09, 0x43, 0xB7, 0x65, 0x15), + MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xA9, 0xA7, 0x3E, 0xFA, 0xF3, 0xEC, 0x22), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x78, 0x22, 0x2B, 0x58, 0x71, 0xFA, 0xAA), + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x30, 0xCE, 0x6A, 0xB3, 0xB0, 0x4F, 0x83), + MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0x95, 0x20, 0xA9, 0x23, 0xC2, 0x65, 0xE7), + MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xCF, 0x03, 0x5B, 0x8A, 0x80, 0x44, 0xBB), + MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xF8, 0x91, 0xF7, 0xD5, 0xED, 0xEA, 0x81), + MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x5B, 0x16, 0x10, 0x25, 0xAC, 0x2A, 0x17), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xEC, 0xDC, 0xC4, 0x7B, 0x8C, 0x6B, 0xE9), + MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xBB, 0x1C, 0xD3, 0x5A, 0xEE, 0xD9, 0x97), + MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x5D, 0x30, 0x5E, 0xF7, 0xB2, 0x41, 0x9D), + MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xCE, 0x0F, 0x1A, 0xC6, 0x41, 0x64, 0x62), + MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x18, 0xE1, 0xE3, 0x82, 0x15, 0x66, 0x4B), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xE2, 0x24, 0x04, 0x72, 0x39, 0xA0, 0x7C), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x51, 0xA2, 0x58, 0x88, 0x62, 0xE1, 0x02), + MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xD2, 0x65, 0x14, 0xE9, 0x4C, 0x82, 0x30), + MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xE1, 0xAC, 0x87, 0xAE, 0x31, 0x1A, 0x7A), + MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x4F, 0x96, 0x1E, 0x85, 0x7A, 0xC3, 0x2B), + MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x86, 0xBB, 0xF0, 0xC0, 0x9D, 0x08, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x53, 0x03, 0x09, 0x80, 0x91, 0xEF, 0x68), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xD7, 0xAF, 0x6F, 0x69, 0x7B, 0x88, 0xA1), + MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x13, 0xE4, 0x30, 0xA2, 0x47, 0xB5, 0xC1), + MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xD2, 0xC0, 0xDD, 0x8A, 0x1C, 0x3C, 0xF2), + MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x8C, 0xB3, 0x4C, 0xBA, 0x8B, 0x6D, 0xCF), + MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0xC7, 0xA1, 0xA8, 0x6E, 0x3C, 0x4F, 0xF1), + MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x4A, 0x97, 0xC8, 0x03, 0x6F, 0x01, 0x82), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x18, 0x12, 0xA9, 0x39, 0xD5, 0x22, 0x26), + MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xA7, 0xC0, 0xBD, 0x9D, 0x8D, 0x78, 0x38), + MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xB3, 0xD0, 0x7F, 0xDF, 0xD0, 0x30, 0xDE), + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x25, 0x73, 0x96, 0xEC, 0xA8, 0x1D, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xD1, 0x65, 0x66, 0xDC, 0xD9, 0xCF, 0xDF), + MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0xED, 0x7B, 0x37, 0xAD, 0xE2, 0xBE, 0x2D), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x79, 0x42, 0x6A, 0x07, 0x66, 0xB1, 0xBD), + MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x53, 0x62, 0x65, 0x92, 0x09, 0x4C, 0xA1), + MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xAF, 0xC3, 0x03, 0xF6, 0xF4, 0x2D, 0x9B), + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xCA, 0x41, 0xD9, 0xA2, 0x69, 0x9B, 0xC9), + MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xB2, 0xA6, 0x8D, 0xE1, 0xAA, 0x61, 0x76), + MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xBA, 0x4D, 0x12, 0xB6, 0xBE, 0xF3, 0x7E), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xD9, 0x92, 0x22, 0x07, 0xCE, 0xC9, 0x26), + MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0xA1, 0x7C, 0x91, 0xDB, 0x32, 0xF7, 0xE5), + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x49, 0x4B, 0x6D, 0xFB, 0xD9, 0x70, 0x3B), + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xFB, 0x4E, 0x4C, 0x5E, 0x66, 0x81, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0xB3, 0xE1, 0x00, 0xB7, 0xD9, 0xCC, 0x58), + MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x36, 0x8B, 0xC4, 0x39, 0x20, 0xFD, 0x30), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x1F, 0x60, 0x03, 0xBB, 0xD7, 0x60, 0x57), + MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x3C, 0x62, 0xDD, 0x71, 0x95, 0xE9, 0x61), + MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x5B, 0x7A, 0x5F, 0x68, 0x81, 0xC5, 0x90), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xAF, 0xB5, 0xB9, 0x98, 0x42, 0x28, 0xA5), + MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x29, 0x8E, 0x11, 0x49, 0xB4, 0xD7, 0x20), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x3E, 0xD2, 0x30, 0xA1, 0xBA, 0xCA, 0x03), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x37, 0x64, 0x44, 0x2F, 0x03, 0xE5, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x42, 0xBC, 0xFF, 0xA2, 0x1A, 0x5F, 0x06), + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x04, 0xAB, 0x04, 0xE0, 0x24, 0xAD, 0x2A), + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x45, 0x17, 0x67, 0x1F, 0x3E, 0x53, 0xF8), + MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x0F, 0xB3, 0x1B, 0x57, 0x54, 0xC2, 0x03), + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xD3, 0xF8, 0xC4, 0x1B, 0x9B, 0xFA, 0x30), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x90, 0xFD, 0xFB, 0xCA, 0x49, 0x38, 0x4E), + MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0xCF, 0xC6, 0xDD, 0xF0, 0xFF, 0x8C, 0x11), + MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x69, 0x9D, 0xBD, 0x5F, 0x33, 0xE9, 0xB4), + MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x19, 0x82, 0x3D, 0xAC, 0x1C, 0x40, 0x23), + MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xC7, 0x02, 0x46, 0x14, 0x77, 0x00, 0xBE), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x05, 0xF2, 0x77, 0x3A, 0x66, 0x5C, 0x39), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xE6, 0x17, 0xDE, 0xB2, 0xA1, 0xE5, 0xB8), + MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x71, 0xEC, 0x9D, 0xD8, 0xF5, 0xD4, 0x66), + MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0xC6, 0x42, 0x5E, 0xE7, 0x18, 0xBA, 0xD0), + MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x21, 0x68, 0x5A, 0x26, 0xFB, 0xD7, 0x17), + MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x00, 0x5C, 0xBA, 0x8A, 0x34, 0xEC, 0x75), + MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x9C, 0x3C, 0xAF, 0x53, 0xE8, 0x65, 0x35), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xEF, 0x28, 0xDC, 0x67, 0x05, 0xC8, 0xDF), + MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x78, 0xC3, 0x85, 0x49, 0xA0, 0xBC, 0x0F), + MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x3E, 0x2D, 0xA0, 0xCF, 0xD4, 0x7A, 0xF5), + MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x93, 0xFE, 0x60, 0xB3, 0x6E, 0x99, 0xE2), + MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0xAD, 0x04, 0xE7, 0x49, 0xAF, 0x5E, 0xE3), + MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x7A, 0xED, 0xA6, 0x9E, 0x18, 0x09, 0x31), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x05, 0x94, 0x44, 0xDC, 0xB8, 0x85, 0x94), + MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xB7, 0x37, 0xC2, 0x50, 0x75, 0x15, 0xDA), + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xC6, 0x0F, 0xB2, 0xA9, 0x91, 0x3E, 0xE8), + MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x81, 0xAD, 0x25, 0xA1, 0x26, 0x73, 0x15), + MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xF1, 0xD1, 0x61, 0x7C, 0x76, 0x8F, 0x13), + MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xDB, 0x4A, 0xFF, 0x14, 0xA7, 0x48, 0x0B), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x73, 0xC6, 0xC2, 0xCC, 0xF1, 0x57, 0x04), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0xED, 0x73, 0x27, 0x70, 0x82, 0xB6, 0x5E), + MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xBA, 0xAC, 0x3A, 0xCF, 0xF4, 0xEA, 0xA6), + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xD6, 0xB1, 0x8F, 0x0E, 0x08, 0x2C, 0x5E), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xE3, 0x8F, 0x2F, 0x0E, 0xA1, 0xF3, 0x07), + MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0xF5, 0x7C, 0x9B, 0x29, 0x0A, 0xF6, 0x28), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0xEE, 0x17, 0x47, 0x34, 0x15, 0xA3, 0xAF), + MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xBE, 0x88, 0x48, 0xE7, 0xA2, 0xBB, 0xDE), + MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0xAD, 0xDC, 0x65, 0x61, 0x37, 0x0F, 0xC1), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x67, 0xAD, 0xA2, 0x3A, 0x1C, 0x91, 0x78), + MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x07, 0x0C, 0x3A, 0x41, 0x6E, 0x13, 0x28), + MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0xBD, 0x7E, 0xED, 0xAA, 0x14, 0xDD, 0x61), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0xDC, 0x20, 0x01, 0x72, 0x11, 0x48, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xC4, 0x7B, 0xF8, 0x62, 0x3D, 0xF0, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xC2, 0x3D, 0x2E, 0x52, 0xA3, 0x4A, 0x89), + MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xE2, 0x53, 0x46, 0x5E, 0x21, 0xF8, 0xCE), + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xC7, 0x8F, 0xA9, 0x26, 0x42, 0x32, 0x3A), + MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xA6, 0xA0, 0x8D, 0x4B, 0x9A, 0x19, 0x03), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xAB, 0x6D, 0x1E, 0xFB, 0xEE, 0x60, 0x0C), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x56, 0x3C, 0xC5, 0x5D, 0x10, 0x79, 0x1C), + MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0xBC, 0x41, 0x9F, 0x71, 0xEF, 0x02, 0xF9), + MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x36, 0xC4, 0xD0, 0x88, 0x9B, 0x32, 0xFC), + MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xD4, 0x5D, 0x17, 0x39, 0xE6, 0x22, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x26, 0x01, 0xCE, 0xBE, 0x4A, 0x9C, 0x27), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x6D, 0x11, 0xCA, 0x6C, 0x5A, 0x93, 0x0C), + MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x96, 0x26, 0xAF, 0x2F, 0xE4, 0x30, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xC1, 0x4C, 0xC6, 0x30, 0x1F, 0x5C, 0x04), + MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xB3, 0xE8, 0xFC, 0x35, 0xEB, 0x63, 0x6C), + MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x1D, 0xCA, 0xFC, 0x50, 0x36, 0x4B, 0x96), + MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x0E, 0x23, 0x5B, 0xAF, 0xEB, 0x2D, 0x31), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x88, 0xB6, 0xD7, 0x74, 0x4A, 0x23, 0xB6), + MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x66, 0xE2, 0xBB, 0x29, 0xA6, 0x4F, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x6F, 0x7E, 0x68, 0x6E, 0xA0, 0x14, 0x94), + MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x73, 0xD4, 0xE8, 0xAB, 0x5B, 0xF6, 0x0D), + MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xE0, 0x3C, 0x24, 0x00, 0x95, 0xE9, 0xAD), + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x0D, 0x4F, 0x81, 0xD0, 0xF2, 0x3F, 0x00), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x1D, 0xCD, 0x78, 0x39, 0xC4, 0x6B, 0xD9), + MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x45, 0xC7, 0xB8, 0x2F, 0xAA, 0x5D, 0xE3), + MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x8C, 0x6E, 0xA3, 0x24, 0xB2, 0xDB, 0x4B), + MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x2D, 0xD9, 0xF1, 0xC7, 0x9B, 0x8A, 0xAF), + MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0xE1, 0x2C, 0xB9, 0x40, 0x37, 0x91, 0x75), + MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x2C, 0xB5, 0x23, 0x03, 0x2B, 0xAF, 0x2F), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x9D, 0x5A, 0x20, 0x10, 0xA9, 0x84, 0xDA), + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x30, 0x89, 0x20, 0x13, 0xE9, 0xB2, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x6E, 0x52, 0xEB, 0x03, 0x18, 0x1F, 0xA6), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x9E, 0x1C, 0x35, 0x87, 0x92, 0x69, 0xC7), + MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0xC9, 0x88, 0xAF, 0xC6, 0x6C, 0x83, 0x72), + MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0xD5, 0x7A, 0x54, 0x34, 0x99, 0xB6, 0x6F), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0xAD, 0x45, 0x9B, 0x4B, 0x41, 0x4D, 0x50), + MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x5D, 0xAB, 0x7F, 0x35, 0x34, 0xE9, 0x29), + MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0xBE, 0x78, 0x34, 0x44, 0xF3, 0x4A, 0x87), + MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xDE, 0xE3, 0xC4, 0xEE, 0x0B, 0xF9, 0xEB), + MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x86, 0x16, 0x48, 0x32, 0xB8, 0x74, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xEE, 0x7C, 0xBA, 0xBD, 0x81, 0xE3, 0x55), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x6A, 0xFA, 0x84, 0xDA, 0xB8, 0xD5, 0x14), + MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0x9F, 0x8A, 0xD5, 0x1B, 0x2E, 0x1A, 0x0B), + MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x0C, 0x61, 0xE2, 0xFF, 0x5B, 0xE6, 0xD5), + MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0x62, 0xC1, 0x87, 0x53, 0x1B, 0x92, 0xA3), + MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x90, 0x00, 0xD1, 0x6A, 0x0C, 0x0E, 0x28), + MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x2E, 0xB5, 0x3B, 0x44, 0xB5, 0xA0, 0x78), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x5D, 0x02, 0x58, 0xB5, 0xBE, 0x45, 0x14), + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xEF, 0x8E, 0x90, 0x4D, 0x2A, 0x32, 0xAC), + MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x99, 0x75, 0x5C, 0x0A, 0x33, 0x8F, 0x36), + MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x6C, 0x95, 0xD4, 0x1F, 0xF3, 0xEB, 0xDA), + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xE4, 0x4C, 0x91, 0x20, 0xF3, 0x25, 0xEB), + MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x95, 0xEB, 0x29, 0x6F, 0x20, 0x34, 0x81), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x15, 0xE5, 0x13, 0x7E, 0x64, 0x8B, 0xAD), + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xBC, 0x0D, 0x18, 0x7E, 0x37, 0x9E, 0xFA), + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x82, 0x20, 0xF7, 0x2D, 0x7A, 0x77, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x29, 0xA2, 0xDB, 0x7A, 0xE6, 0x6F, 0xA5), + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xC6, 0x50, 0x5C, 0xBC, 0xE6, 0x4F, 0xBD), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x9F, 0xD5, 0xE8, 0xC5, 0x3D, 0xB7, 0x30), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_16_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x03, 0x55, 0x10, 0xDB, 0xA6, 0x8B, 0x22), + MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x17, 0xAE, 0x78, 0xC9, 0x1D, 0x43, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x35, 0x49, 0xD4, 0x47, 0x84, 0x8D, 0x20), + MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x95, 0x2F, 0xEA, 0xBC, 0xB4, 0x18, 0xB3), + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x48, 0xAE, 0x89, 0xF5, 0x65, 0x3D, 0x89), + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xF2, 0x2B, 0x20, 0xD1, 0x75, 0x50, 0x63), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_16_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xE6, 0x5C, 0x2C, 0xE0, 0x7D, 0xDF, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x07, 0x3E, 0xCE, 0x9F, 0x18, 0xB6, 0x05), + MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0xF8, 0xF0, 0xD5, 0xFA, 0x42, 0x1D, 0x6D), + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x6C, 0x1D, 0x03, 0xC9, 0x0E, 0x2B, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x18, 0x52, 0xA5, 0xB4, 0x63, 0xE1, 0x06), + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x0A, 0xD9, 0xC4, 0xFD, 0x16, 0x60, 0x54), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_17_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x7D, 0xDE, 0xDF, 0x4B, 0x4A, 0xB0, 0xCB), + MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x4E, 0x8C, 0x94, 0xC1, 0xE2, 0x85, 0xDF), + MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0xF0, 0xEA, 0xB5, 0x9B, 0x70, 0xEF, 0x10), + MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xC2, 0x39, 0x5D, 0xF3, 0x2C, 0xD9, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x1C, 0x2E, 0xCC, 0x2F, 0x54, 0x87, 0x80), + MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x72, 0xC7, 0xB5, 0x50, 0xA3, 0x84, 0x77), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_17_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xD1, 0xAF, 0xA9, 0xB4, 0x8B, 0x5D, 0xFA), + MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xF6, 0x52, 0x8A, 0xC3, 0x56, 0xA5, 0x5E), + MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x52, 0xFF, 0xEA, 0x05, 0x42, 0x77, 0x83), + MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x08, 0x90, 0x72, 0x86, 0xC4, 0xC3, 0xB8), + MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x15, 0xF8, 0xF1, 0x16, 0x67, 0xC6, 0xD5), + MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x87, 0xAC, 0x8F, 0x71, 0xEC, 0x83, 0x81), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_18_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xE1, 0xE6, 0x2D, 0x0E, 0x11, 0xA1, 0x62), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xE2, 0xA8, 0x32, 0xE6, 0xE3, 0x83, 0xD1), + MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x56, 0xE5, 0xCD, 0xB7, 0x2B, 0x67, 0x6F), + MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xED, 0xC9, 0x65, 0x6D, 0x87, 0xE1, 0x8E), + MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x8E, 0xFD, 0x9A, 0x53, 0x0E, 0xFA, 0xA3), + MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0x4C, 0x4A, 0xE2, 0x23, 0x84, 0xFA, 0x01), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_18_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xFE, 0x49, 0x81, 0xD1, 0x3E, 0xF4, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x72, 0xE0, 0xEF, 0x0D, 0xB8, 0x3E, 0x6F), + MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x00, 0x0F, 0x5F, 0xCE, 0x60, 0x72, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xCC, 0xD8, 0x03, 0x07, 0x6E, 0x5A, 0xCD), + MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x3A, 0x35, 0x50, 0x4E, 0x1F, 0xCA, 0x5F), + MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xEA, 0x88, 0x55, 0xBD, 0x6E, 0x05, 0x7F), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_19_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x6D, 0xF1, 0x97, 0xA6, 0x69, 0x39, 0x24), + MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x41, 0x99, 0xFF, 0x3B, 0xA1, 0x26, 0xEC), + MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x2F, 0x95, 0x80, 0x12, 0x4A, 0x1B, 0xCB), + MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xBF, 0x51, 0xAA, 0xAE, 0x2D, 0xDA, 0xCF), + MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x1C, 0xB3, 0x52, 0x36, 0x49, 0xD4, 0x86), + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xC1, 0x1F, 0x3A, 0xD3, 0x3E, 0x5C, 0x1A), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_19_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x51, 0xF7, 0x2B, 0xC8, 0xA9, 0xA7, 0x15), + MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x4E, 0x7F, 0x98, 0x41, 0x66, 0xB0, 0x03), + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x1D, 0xC0, 0x42, 0xCD, 0xF8, 0xC3, 0x2B), + MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x41, 0x91, 0x7D, 0xCC, 0x8B, 0xCC, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xAE, 0x76, 0xED, 0x56, 0x18, 0xC5, 0xAB), + MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x6A, 0x06, 0xA3, 0x7F, 0x65, 0x10, 0x1F), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_20_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xEC, 0x3C, 0x05, 0x05, 0xCA, 0xF6, 0xED), + MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0xCD, 0x02, 0x51, 0x12, 0x16, 0x3C, 0x63), + MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0xEB, 0xB3, 0x43, 0x7B, 0xDD, 0xB2, 0x7C), + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x59, 0x90, 0x41, 0xDB, 0xE4, 0xF5, 0x91), + MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x0E, 0x18, 0x2A, 0x5A, 0x83, 0x7C, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x37, 0xA1, 0x0D, 0xF1, 0x2F, 0x63, 0x79), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_20_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xC0, 0xFA, 0x6F, 0x1F, 0x67, 0xCF, 0xEC), + MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x34, 0x45, 0xBB, 0xF4, 0xF9, 0x9B, 0x89), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x69, 0xFE, 0x67, 0x1D, 0x64, 0x8F, 0xB9), + MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x39, 0xBF, 0xD8, 0xB3, 0xC7, 0xAD, 0x8A), + MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x93, 0xFF, 0xF3, 0x28, 0xFA, 0x39, 0xF6), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xF9, 0xC3, 0x85, 0x26, 0x7A, 0x88, 0x89), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_21_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xD5, 0x79, 0xD8, 0x11, 0xDE, 0xEB, 0x4E), + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x46, 0xA4, 0x6A, 0xDA, 0x74, 0x34, 0xA8), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xBD, 0xD3, 0xF5, 0x14, 0xEE, 0xFE, 0xAE), + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x4C, 0xA3, 0x71, 0x43, 0x65, 0xF8, 0x94), + MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x6C, 0x35, 0xFA, 0x90, 0x25, 0xD8, 0xE2), + MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x34, 0x84, 0x96, 0xA1, 0x43, 0x03, 0x4D), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_21_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x3B, 0x3B, 0x2F, 0xCA, 0x59, 0xF2, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x48, 0x24, 0x74, 0xD8, 0x72, 0x90, 0xA3), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x42, 0x74, 0x8C, 0x6F, 0x52, 0x19, 0x3D), + MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x9E, 0x41, 0x63, 0x68, 0x78, 0x4C, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0x94, 0xB6, 0x6B, 0x38, 0x52, 0xA8, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x30, 0x25, 0x93, 0xA1, 0x6F, 0x6E, 0x68), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_22_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x2F, 0x4B, 0x64, 0x79, 0x50, 0xFF, 0x01), + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x36, 0xED, 0x57, 0x39, 0x3B, 0xE7, 0xF3), + MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x85, 0xEA, 0x35, 0xD6, 0xC0, 0xA0, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x89, 0x3A, 0xCC, 0x22, 0x1C, 0x46, 0x02), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x7A, 0xB0, 0xA1, 0x1B, 0x69, 0x62, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xB8, 0x8A, 0x6C, 0x18, 0x85, 0x0D, 0x88), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_22_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xB6, 0x50, 0xE9, 0x4E, 0x7F, 0xE8, 0x07), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x5B, 0x5C, 0xD1, 0x4B, 0x11, 0x9A, 0xD8), + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x25, 0x56, 0x74, 0x51, 0x9C, 0xEC, 0x9C), + MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x7F, 0xB6, 0x8A, 0xCB, 0x3A, 0x10, 0x6A), + MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x33, 0x07, 0x01, 0xE9, 0x49, 0x59, 0xE6), + MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xA5, 0x2E, 0xF2, 0xBA, 0x32, 0x63, 0x44), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_23_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x06, 0x0B, 0xA5, 0x44, 0x27, 0x7F, 0x22), + MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x74, 0xAC, 0x0F, 0xCC, 0x4F, 0x13, 0x61), + MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xB1, 0xBF, 0x97, 0x49, 0xA5, 0x1C, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x64, 0x68, 0x7B, 0x0F, 0xCC, 0x77, 0xF8), + MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x39, 0xF9, 0x4E, 0x84, 0x9C, 0xF6, 0x96), + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xCF, 0x6D, 0xE2, 0xA1, 0x2D, 0xF9, 0x2B), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_23_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0xC4, 0x90, 0x57, 0x31, 0x01, 0x05, 0x5E), + MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x1E, 0xBB, 0xBF, 0x98, 0xA4, 0x7C, 0xE3), + MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0xE3, 0xA0, 0xB2, 0xCD, 0x39, 0x9A, 0x3F), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x34, 0x60, 0x7A, 0x89, 0x98, 0xB5, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0x20, 0x3D, 0x3A, 0x04, 0x8F, 0x5A, 0xAC), + MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x26, 0xB6, 0x49, 0x09, 0x9C, 0x0F, 0x59), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_24_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x66, 0xD2, 0x38, 0x2A, 0x62, 0x81, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0xC8, 0x20, 0x5E, 0x28, 0xA3, 0x81, 0xA7), + MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x31, 0xA4, 0xF1, 0xEA, 0x7D, 0x87, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0x2C, 0x99, 0x09, 0x6F, 0x63, 0xEB, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x76, 0xDA, 0x1A, 0x06, 0xBE, 0xDE, 0xA2), + MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x09, 0x2E, 0x75, 0x39, 0x30, 0x2D, 0x42), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_24_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x9B, 0xC1, 0x5A, 0x17, 0xC3, 0x8C, 0x31), + MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x8D, 0x94, 0x4D, 0x3D, 0xAB, 0x60, 0xD4), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFD, 0x1E, 0x0F, 0x43, 0xAE, 0x9D, 0x62), + MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0xF2, 0xF3, 0x20, 0x1B, 0xAA, 0xB7, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x5B, 0xA4, 0xF4, 0x90, 0x3B, 0xE3, 0x71), + MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x78, 0x72, 0xBD, 0x65, 0x09, 0x0B, 0x01), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_25_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x37, 0x2A, 0x6C, 0x16, 0x4F, 0x64, 0x59), + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0xCE, 0xA3, 0x90, 0xB4, 0x9A, 0xBC, 0xF7), + MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x38, 0x55, 0x63, 0x1D, 0x3A, 0x6E, 0x18), + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xB4, 0xAA, 0x99, 0x22, 0x45, 0x89, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x7C, 0x8C, 0xA6, 0x3D, 0xA7, 0x3E, 0xE8), + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x06, 0x42, 0xDC, 0xA6, 0xE3, 0xC6, 0x12), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_25_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x8C, 0x3D, 0x5D, 0x47, 0x31, 0x7C, 0xEB), + MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x85, 0xEE, 0x46, 0x7E, 0x13, 0x04, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x3C, 0x8B, 0x43, 0x2E, 0x74, 0xF5, 0xF6), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x88, 0x8E, 0x07, 0x29, 0x08, 0x03, 0x26), + MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x9B, 0x89, 0xEB, 0x08, 0xE8, 0x43, 0xB5), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x07, 0x67, 0xFD, 0xD9, 0x73, 0x6F, 0x18), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_26_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xEB, 0x21, 0x8D, 0x98, 0x43, 0x74, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xCC, 0x14, 0xD8, 0x08, 0xBB, 0xA6, 0xE3), + MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x98, 0xF2, 0x6A, 0x18, 0xC3, 0xDD, 0x9E), + MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x38, 0x91, 0xA0, 0x03, 0xF2, 0x04, 0x62), + MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xAF, 0xE8, 0xFD, 0xFB, 0x13, 0x70, 0x74), + MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x93, 0x87, 0x98, 0x4A, 0xE0, 0x00, 0x12), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_26_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x2E, 0x69, 0x9C, 0xA2, 0x2D, 0x03, 0x3F), + MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xFE, 0xF3, 0xB9, 0xC1, 0x85, 0x2A, 0xEE), + MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xFD, 0x86, 0xB1, 0xCD, 0xBF, 0x41, 0xB7), + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xD8, 0x9A, 0x21, 0xF3, 0xFE, 0xCB, 0xF1), + MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x78, 0x04, 0x60, 0xB7, 0xA9, 0xA2, 0x84), + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x1E, 0x66, 0x2A, 0x54, 0x51, 0xBD, 0x8B), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_27_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x16, 0x36, 0xEF, 0x61, 0x2D, 0xEE, 0x3B), + MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x5F, 0x88, 0xA0, 0x13, 0x12, 0xF7, 0x23), + MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xC6, 0xAD, 0x4A, 0x4A, 0x07, 0x01, 0x5B), + MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x74, 0xB1, 0x4F, 0xEB, 0xBD, 0xD5, 0x6B), + MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xF9, 0x71, 0xA2, 0x06, 0x4F, 0xD7, 0xBC), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x8B, 0x4D, 0x48, 0xE0, 0x98, 0xFB, 0x6A), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_27_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0xBA, 0x10, 0xA3, 0x0D, 0x52, 0xAC, 0x3A), + MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xD0, 0xE0, 0x36, 0xE6, 0x07, 0x3A, 0x30), + MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x80, 0xF0, 0xAA, 0x49, 0x22, 0x4B, 0xDD), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xC7, 0xAB, 0x1C, 0x89, 0xCD, 0x24, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x2A, 0xFC, 0xB3, 0x6D, 0x45, 0x96, 0x49), + MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0xE4, 0xDB, 0x52, 0x3F, 0xC4, 0xB4, 0x19), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_28_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0xCC, 0xC8, 0x7F, 0xBB, 0x6B, 0x87, 0x47), + MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x21, 0x3C, 0x69, 0x7D, 0x38, 0x57, 0x50), + MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x4C, 0x18, 0x3C, 0x53, 0xA5, 0x48, 0x6D), + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xC3, 0x64, 0x45, 0xDB, 0xC4, 0x6D, 0x15), + MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xCC, 0xD1, 0xBB, 0x17, 0xB8, 0x34, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x69, 0x71, 0xFA, 0xA0, 0x28, 0x4A, 0x3D), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_28_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xE8, 0x9E, 0x39, 0xEA, 0x8D, 0x38, 0xDB), + MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x9C, 0xBB, 0xCD, 0x80, 0x1A, 0xEE, 0xB7), + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xA0, 0x45, 0xBF, 0xD9, 0x22, 0x11, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x7C, 0x5C, 0xD9, 0xC0, 0x9F, 0x69, 0xF5), + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x8A, 0xA6, 0x79, 0x4E, 0x35, 0xB9, 0xD5), + MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x8B, 0x9A, 0x3E, 0xA1, 0xB8, 0x28, 0x10), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_29_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x2F, 0xEF, 0xBB, 0xA9, 0x72, 0x7F, 0xEA), + MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x34, 0xB7, 0x12, 0xB9, 0xE7, 0xC3, 0x2A), + MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x1D, 0xD9, 0x42, 0x77, 0x0C, 0x71, 0x6E), + MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x01, 0x59, 0xA7, 0x56, 0x03, 0x91, 0x8D), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x91, 0x99, 0x33, 0x30, 0x3E, 0xEF, 0x13), + MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0xC9, 0x5A, 0x9A, 0x54, 0x66, 0xF1, 0x70), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_29_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x2C, 0xB7, 0x6E, 0x71, 0x7D, 0x35, 0x30), + MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x0D, 0xEF, 0xD1, 0x2D, 0x99, 0x63, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x31, 0xAF, 0x2D, 0xC9, 0xC6, 0xC2, 0xAE), + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0xC0, 0xDF, 0x80, 0x54, 0xC4, 0xAC, 0xF3), + MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x6B, 0xA0, 0x84, 0x96, 0xF7, 0x31, 0xC8), + MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0xE2, 0x7C, 0x7A, 0x41, 0x45, 0x75, 0x6A), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_30_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xEE, 0x58, 0x31, 0xE8, 0x68, 0xD6, 0x76), + MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x2E, 0x48, 0xB7, 0x09, 0x9F, 0xD4, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xA9, 0x5C, 0xE7, 0x64, 0x43, 0x5D, 0xC9), + MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x58, 0x9F, 0x50, 0xAB, 0x68, 0xFF, 0x6D), + MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x88, 0x2D, 0xBA, 0x12, 0xBF, 0x8D, 0x7D), + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xDF, 0x6F, 0xB3, 0x75, 0xA4, 0x55, 0x73), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_30_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x17, 0x92, 0x39, 0xB7, 0x13, 0x37, 0x6F), + MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x43, 0x71, 0xA7, 0xCA, 0x17, 0x1B, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xB9, 0xB0, 0x78, 0xEF, 0xA0, 0xDA, 0x83), + MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x84, 0xF2, 0x0F, 0x85, 0xA2, 0xB6, 0x1F), + MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x65, 0x2E, 0x6E, 0x45, 0xB9, 0x4C, 0x3C), + MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x6A, 0x8C, 0x2B, 0x77, 0x96, 0x36, 0x22), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_31_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x7A, 0x13, 0x4A, 0x97, 0x63, 0x02, 0x10), + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x1E, 0x06, 0x03, 0x8F, 0xB9, 0xEE, 0x64), + MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0xEE, 0x8B, 0x89, 0xA9, 0x70, 0xDB, 0xCE), + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x7B, 0x81, 0xC9, 0x70, 0x8D, 0x62, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0xDA, 0x46, 0xF8, 0xF9, 0x3A, 0xBE, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x9C, 0x7A, 0x97, 0x62, 0xEB, 0xFA, 0x0F), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_31_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0x03, 0x3D, 0x3C, 0x46, 0x27, 0x9E, 0x65), + MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x08, 0x1C, 0xD5, 0x25, 0xAF, 0xE9, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x69, 0xDC, 0x59, 0xF4, 0x8A, 0x7C, 0x1F), + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x9A, 0x7A, 0x99, 0x21, 0x0C, 0x4E, 0xE3), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xCE, 0x85, 0x5F, 0xAC, 0xAA, 0x82, 0x10), + MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x57, 0x69, 0x90, 0x76, 0xF3, 0x53, 0x3F), +}; +static const mbedtls_ecp_point brainpoolP384r1_T[32] = { + ECP_POINT_INIT_XY_Z1(brainpoolP384r1_T_0_X, brainpoolP384r1_T_0_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_1_X, brainpoolP384r1_T_1_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_2_X, brainpoolP384r1_T_2_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_3_X, brainpoolP384r1_T_3_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_4_X, brainpoolP384r1_T_4_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_5_X, brainpoolP384r1_T_5_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_6_X, brainpoolP384r1_T_6_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_7_X, brainpoolP384r1_T_7_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_8_X, brainpoolP384r1_T_8_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_9_X, brainpoolP384r1_T_9_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_10_X, brainpoolP384r1_T_10_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_11_X, brainpoolP384r1_T_11_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_12_X, brainpoolP384r1_T_12_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_13_X, brainpoolP384r1_T_13_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_14_X, brainpoolP384r1_T_14_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_15_X, brainpoolP384r1_T_15_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_16_X, brainpoolP384r1_T_16_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_17_X, brainpoolP384r1_T_17_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_18_X, brainpoolP384r1_T_18_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_19_X, brainpoolP384r1_T_19_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_20_X, brainpoolP384r1_T_20_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_21_X, brainpoolP384r1_T_21_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_22_X, brainpoolP384r1_T_22_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_23_X, brainpoolP384r1_T_23_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_24_X, brainpoolP384r1_T_24_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_25_X, brainpoolP384r1_T_25_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_26_X, brainpoolP384r1_T_26_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_27_X, brainpoolP384r1_T_27_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_28_X, brainpoolP384r1_T_28_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_29_X, brainpoolP384r1_T_29_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_30_X, brainpoolP384r1_T_30_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_31_X, brainpoolP384r1_T_31_Y), +}; +#else +#define brainpoolP384r1_T NULL +#endif + +#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), +}; + +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint brainpoolP512r1_T_0_X[] = { + 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_T_0_Y[] = { + 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_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xE9, 0x6B, 0x8C, 0x6F, 0x9D, 0x88, 0x43), + MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x4F, 0x86, 0x96, 0xA7, 0x56, 0xD1, 0x37), + MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xAB, 0xFA, 0xEE, 0xA7, 0xF5, 0x0E, 0xA6), + MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x40, 0xEF, 0x9E, 0x6D, 0xD6, 0x32, 0x33), + MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xED, 0x56, 0x14, 0x57, 0x1A, 0x8D, 0x69), + MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xED, 0x4D, 0x3A, 0xFA, 0x71, 0x75, 0x6B), + MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xC5, 0x76, 0x1C, 0x14, 0xBE, 0xB5, 0xCD), + MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x5A, 0xCB, 0xE7, 0x36, 0x1D, 0x52, 0x1C), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x8D, 0x7A, 0xEB, 0xA3, 0x8B, 0xD5, 0xB0), + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xA3, 0x41, 0xF8, 0xAC, 0x9E, 0xAB, 0x74), + MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0xE3, 0x65, 0x0D, 0x1C, 0xFE, 0x09, 0x2B), + MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0xCA, 0x13, 0x3F, 0xC5, 0xF9, 0x7E, 0xEC), + MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x5D, 0x63, 0x28, 0xA6, 0x89, 0xD3, 0x91), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x95, 0x3F, 0x7A, 0x82, 0xD4, 0x77, 0xE3), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xBB, 0x92, 0x32, 0x00, 0xF4, 0x66, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x58, 0x31, 0xD1, 0x17, 0x9F, 0x2A, 0x22), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x36, 0xA9, 0xCD, 0x80, 0xA5, 0x2D, 0x78), + MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x44, 0xAB, 0xCE, 0x71, 0xFF, 0x0C, 0x9B), + MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x24, 0x58, 0x35, 0x5A, 0x21, 0x32, 0x93), + MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0xA6, 0x28, 0xF8, 0x7A, 0x97, 0xAE, 0x8B), + MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0xE7, 0x08, 0xFA, 0x47, 0xC9, 0x55, 0x09), + MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xAC, 0x2E, 0x84, 0xA4, 0xF5, 0x52, 0xC4), + MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x58, 0x05, 0x9D, 0xA7, 0xC8, 0x71, 0xBF), + MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x92, 0xB4, 0x92, 0xC1, 0x92, 0xEC, 0x6B), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x48, 0x2D, 0x79, 0x5E, 0x58, 0xE5, 0x69), + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x85, 0x26, 0xEC, 0xE9, 0x6E, 0xD4, 0x06), + MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x68, 0x26, 0x87, 0x38, 0xA2, 0xD2, 0x0B), + MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x17, 0x60, 0xCE, 0x75, 0xF8, 0xA5, 0x6F), + MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x51, 0xDB, 0xA9, 0xAE, 0x87, 0xF1, 0x15), + MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x49, 0x92, 0x3B, 0x19, 0x96, 0xF5, 0xB0), + MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0xD5, 0x52, 0x52, 0x8C, 0xCE, 0xFD, 0xFA), + MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x18, 0x0A, 0xE6, 0xF6, 0xAE, 0x08, 0x41), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x2B, 0xD8, 0x54, 0xCE, 0xB0, 0x57, 0xFE), + MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xB0, 0xF8, 0x9E, 0x03, 0x03, 0x3C, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x0E, 0x29, 0x29, 0x00, 0xF3, 0x70, 0xBF), + MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x33, 0x99, 0x0E, 0x00, 0x5D, 0xFE, 0x4B), + MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x2D, 0xF2, 0x59, 0x32, 0xCF, 0x03, 0xF4), + MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0xC9, 0x72, 0xAE, 0x0C, 0xEF, 0xD1, 0x5B), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x5A, 0x27, 0xBF, 0x2F, 0x45, 0xF9, 0x51), + MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xBE, 0xE5, 0x2C, 0xFF, 0x5B, 0x1E, 0x88), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0xAC, 0xBB, 0xD8, 0x83, 0xC2, 0x46, 0xF6), + MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xDC, 0xCE, 0x15, 0xB4, 0xEF, 0xCF, 0x46), + MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xDB, 0x5E, 0x94, 0x31, 0x0B, 0xB2, 0x7A), + MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xB9, 0xE3, 0xE3, 0x11, 0x71, 0x41, 0x1E), + MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xE3, 0x01, 0xB7, 0x7D, 0xBC, 0x65, 0xBE), + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x07, 0x65, 0x87, 0xA7, 0xE8, 0x48, 0xE3), + MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x48, 0x8F, 0xD4, 0x30, 0x8E, 0xB4, 0x6C), + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xE0, 0x73, 0xBE, 0x1E, 0xBF, 0x56, 0x36), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x0E, 0x5E, 0x87, 0xC5, 0xAB, 0x0E, 0x3C), + MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xF9, 0x5F, 0x80, 0x24, 0x4C, 0x2A, 0xF1), + MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0x15, 0x21, 0x54, 0x92, 0x84, 0x8D, 0x6A), + MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x8A, 0x47, 0x74, 0xDC, 0x42, 0xB1, 0xF8), + MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0xF7, 0x30, 0xFD, 0xC1, 0x9B, 0x0C, 0x5B), + MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x6C, 0xCC, 0xDF, 0xC5, 0xE3, 0xA9, 0xD5), + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x67, 0x59, 0x10, 0x5C, 0x51, 0x54, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x37, 0xFB, 0x6E, 0xB0, 0x78, 0x63, 0x8E), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0xEF, 0xC4, 0x39, 0x20, 0xF1, 0x46, 0x66), + MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x62, 0xAE, 0xFF, 0x10, 0xE4, 0xE2, 0xE9), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x5C, 0xF5, 0x2E, 0x22, 0x89, 0xE5, 0x82), + MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x0C, 0x29, 0xA8, 0x62, 0xAE, 0xDB, 0x65), + MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x9E, 0x0F, 0xCA, 0x87, 0x2A, 0x6F, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xDC, 0x9B, 0x9F, 0x65, 0xD4, 0xAD, 0x27), + MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xC3, 0x08, 0x0F, 0xCF, 0x67, 0xE9, 0xF4), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x5C, 0xD7, 0xFF, 0x41, 0x9C, 0xCB, 0x26), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x25, 0x05, 0x12, 0xAD, 0x73, 0x63, 0x90), + MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x99, 0x07, 0x86, 0x57, 0xE7, 0x94, 0xB1), + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x4B, 0xA5, 0xBF, 0x18, 0xA9, 0xEF, 0x6A), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x4C, 0xC4, 0x09, 0xF2, 0x2F, 0x0C, 0xAA), + MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x3A, 0x04, 0xEA, 0x89, 0x6C, 0x91, 0xB9), + MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x6C, 0x3A, 0xE7, 0xA3, 0xEC, 0x24, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xA1, 0x26, 0x21, 0x04, 0xE3, 0xB9, 0x40), + MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0x71, 0x4B, 0x7B, 0xC2, 0x89, 0xCD, 0xA2), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xB9, 0xA8, 0x9D, 0xFD, 0x00, 0x3A, 0x1F), + MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x41, 0x6C, 0xBB, 0x5A, 0xCA, 0x1F, 0x74), + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xD7, 0xE2, 0x6C, 0x6B, 0xA7, 0x48, 0xC9), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x19, 0xAD, 0xA7, 0xC1, 0x7E, 0x4F, 0x6E), + MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xF7, 0x19, 0x3C, 0x06, 0x74, 0x2C, 0x3A), + MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x23, 0x4F, 0x0C, 0x09, 0xB0, 0x80, 0x4A), + MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x74, 0x34, 0x08, 0x44, 0x7E, 0xA3, 0xDD), + MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xCC, 0x8D, 0x12, 0x6E, 0xE1, 0x3D, 0x0B), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x18, 0xB1, 0x71, 0x02, 0x93, 0xC2, 0xA4), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x89, 0x40, 0xE2, 0x1F, 0xE7, 0x5E, 0x68), + MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x8E, 0xAE, 0x89, 0x01, 0xD4, 0x0C, 0xEB), + MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xDA, 0x58, 0x70, 0x24, 0xF2, 0xE4, 0x5F), + MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0xC7, 0x1D, 0xD6, 0x4A, 0x6F, 0x66, 0x4F), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x1D, 0x7E, 0x4A, 0x2C, 0xCA, 0xEC, 0x3B), + MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x06, 0x7F, 0xA8, 0x99, 0xE4, 0xD3, 0x4E), + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x1D, 0x5A, 0xDF, 0x5E, 0x58, 0x36, 0x49), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xB9, 0x32, 0x69, 0x1F, 0x72, 0x2A, 0xB3), + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x73, 0xE2, 0x03, 0x39, 0x35, 0xAA, 0xA8), + MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x5E, 0x5D, 0x48, 0xEF, 0xAE, 0x30, 0xF5), + MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x7F, 0x60, 0x19, 0xAF, 0xEC, 0x9D, 0xFC), + MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xD9, 0x19, 0xE4, 0x1B, 0x56, 0x15, 0x5F), + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xD7, 0x33, 0x59, 0x1F, 0x43, 0x59, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xCE, 0xEE, 0xCA, 0xA4, 0x7F, 0x63, 0xD4), + MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x40, 0xC0, 0xF6, 0x19, 0x89, 0x43, 0x20), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x92, 0xEA, 0x07, 0x65, 0x79, 0x86, 0xD3), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xB7, 0x13, 0x75, 0xD3, 0xC5, 0x0A, 0xC9), + MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x9E, 0xFA, 0xE1, 0x1F, 0x0C, 0xF9, 0x74), + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x8C, 0xED, 0x5C, 0x21, 0xE9, 0x09, 0xDD), + MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x4D, 0xD8, 0x18, 0xC4, 0xF6, 0x36, 0x39), + MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xC9, 0xAC, 0x5C, 0xFA, 0x69, 0xA4, 0xA0), + MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x8C, 0x94, 0x1C, 0x7B, 0x71, 0x36, 0x58), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xBD, 0x46, 0xCE, 0xB7, 0x1D, 0x9C, 0x5E), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xD6, 0x96, 0x4B, 0xA6, 0x47, 0xEB, 0xE5), + MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0xF1, 0x5F, 0x15, 0xDE, 0x99, 0x6F, 0x66), + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xBD, 0xE5, 0x04, 0xB8, 0xE6, 0xC0, 0x0B), + MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xD3, 0xF0, 0x04, 0x00, 0xE4, 0x05, 0xDB), + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xF3, 0x06, 0xA3, 0x1A, 0xFF, 0xEA, 0x73), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x32, 0xAA, 0x99, 0x33, 0x09, 0xB6, 0x34), + MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xEF, 0xFC, 0x61, 0x10, 0x42, 0x31, 0x94), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xF1, 0xF4, 0x33, 0xCF, 0x28, 0x90, 0x9C), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xDE, 0xF9, 0x88, 0x87, 0x7B, 0xEB, 0xC9), + MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xB8, 0xDA, 0xFA, 0xDA, 0x3D, 0xA6, 0x17), + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xF0, 0x62, 0x82, 0x53, 0x32, 0x55, 0x03), + MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xA5, 0x32, 0x4A, 0x19, 0x11, 0x9C, 0x10), + MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xB3, 0x27, 0xE9, 0x75, 0x90, 0x05, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x1C, 0x90, 0x48, 0x77, 0x01, 0x85, 0x1B), + MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xD6, 0x9B, 0x84, 0xA8, 0xD7, 0xC5, 0x28), + MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x7A, 0xCB, 0xB3, 0x11, 0x46, 0xD7, 0x99), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x23, 0xBF, 0x75, 0x75, 0xA1, 0x95, 0x90), + MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x66, 0x5D, 0x34, 0x13, 0xA9, 0x03, 0xBE), + MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x80, 0x9D, 0x5F, 0xD2, 0x44, 0xE1, 0x62), + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x5D, 0xBD, 0xA8, 0xBF, 0xB4, 0x25, 0x1F), + MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x99, 0x1F, 0x53, 0xF1, 0x57, 0xDB, 0xE7), + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x7C, 0xE5, 0xC5, 0x51, 0x0B, 0x4C, 0x9B), + MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0xB0, 0x1A, 0x9C, 0x16, 0xB0, 0x32, 0x1F), + MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0xE3, 0xCF, 0xDD, 0x48, 0xB4, 0x7B, 0x33), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xDD, 0x9E, 0x3C, 0x98, 0x0E, 0x77, 0x65), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xAB, 0x01, 0xD3, 0x87, 0x74, 0x25, 0x4A), + MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0xA3, 0xE3, 0x76, 0x43, 0x87, 0x12, 0xBD), + MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0xB1, 0x3B, 0x60, 0x66, 0xEB, 0x98, 0x54), + MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x78, 0xC8, 0xD7, 0x4E, 0x75, 0xCA, 0x69), + MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xDF, 0x71, 0x19, 0xE7, 0x07, 0x36, 0xB5), + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xC9, 0xA8, 0x5F, 0x91, 0xBF, 0x47, 0xB2), + MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x96, 0x58, 0x96, 0x18, 0xB6, 0xFA, 0x01), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x2D, 0xA9, 0x9B, 0x86, 0xDB, 0x0C, 0x4C), + MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x0B, 0x2D, 0x56, 0x4A, 0xD3, 0x93, 0x8A), + MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x15, 0xE2, 0x65, 0x12, 0x86, 0x0E, 0xB2), + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x41, 0x4D, 0xC1, 0xCB, 0xE4, 0xC3, 0xD7), + MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x53, 0x10, 0xCA, 0xA3, 0xAC, 0x83, 0x26), + MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x01, 0x22, 0x96, 0x10, 0xAD, 0x69, 0xDB), + MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x46, 0x4E, 0xD8, 0xEA, 0xD6, 0x9D, 0xF3), + MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x2F, 0x7F, 0x62, 0x62, 0x80, 0xD0, 0x14), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xDA, 0x00, 0x63, 0x09, 0xBD, 0x6A, 0x83), + MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xD4, 0x6E, 0x48, 0x05, 0xB7, 0xF7, 0x17), + MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x4D, 0xD7, 0x00, 0x4A, 0x15, 0x27, 0x7A), + MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x15, 0xAA, 0x37, 0x27, 0x34, 0x18, 0x24), + MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x20, 0x2C, 0x84, 0x1B, 0x88, 0xBA, 0x05), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x09, 0xD6, 0x04, 0xA2, 0x60, 0x84, 0x72), + MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x04, 0x94, 0x08, 0xD4, 0xED, 0x47, 0xDB), + MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xF3, 0xE4, 0x3E, 0xB9, 0x5B, 0x35, 0x42), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0xD8, 0xB6, 0x80, 0xD6, 0xF1, 0x30, 0xDD), + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x14, 0xA6, 0x85, 0xEE, 0xA7, 0xD8, 0x61), + MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x49, 0x2A, 0x1E, 0x7C, 0xE9, 0x2D, 0xEC), + MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x87, 0x56, 0x91, 0x03, 0x77, 0x4D, 0x55), + MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0x52, 0xD4, 0xAA, 0xF7, 0xFA, 0xB0, 0xC5), + MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x5D, 0x11, 0x39, 0xB1, 0xE7, 0x76, 0xAD), + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x13, 0xBC, 0x37, 0x5D, 0x74, 0xCD, 0xC2), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x48, 0x14, 0x23, 0x30, 0xF8, 0x46, 0x37), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x27, 0xB0, 0xD9, 0xB2, 0x74, 0xB4, 0xC0), + MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xA6, 0xB9, 0x6F, 0x9F, 0x64, 0x36, 0x92), + MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0x2B, 0x78, 0x40, 0x05, 0x2B, 0x7B, 0xA9), + MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x68, 0x3A, 0xB6, 0x4A, 0xE2, 0xDB, 0xB8), + MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x33, 0xD7, 0x34, 0x8B, 0x25, 0x45, 0xEF), + MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0xCE, 0xA8, 0xC9, 0x01, 0xFB, 0x0E, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xF9, 0x51, 0x4C, 0x12, 0x9F, 0x60, 0xE4), + MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x85, 0xBD, 0x30, 0x37, 0x84, 0x39, 0x44), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x33, 0xAF, 0x2E, 0xB8, 0x2E, 0xCC, 0x3C), + MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xB1, 0x73, 0x59, 0x4E, 0x0C, 0x09, 0x4A), + MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x24, 0x89, 0x81, 0x12, 0xFF, 0xBB, 0x6E), + MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x37, 0x1A, 0x66, 0xEE, 0xED, 0xB6, 0x9B), + MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xBD, 0x04, 0x20, 0x5D, 0xFB, 0xBF, 0x95), + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xF8, 0x34, 0xA3, 0xFF, 0x45, 0xDE, 0x92), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x18, 0x73, 0xF1, 0x32, 0x25, 0x58, 0xEB), + MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0xC1, 0x14, 0xE3, 0x9E, 0x40, 0x0F, 0x12), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x07, 0x9D, 0x9C, 0x00, 0xF7, 0x56, 0x19), + MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xBA, 0x87, 0xF9, 0x15, 0x0C, 0x66, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x1F, 0xC1, 0x28, 0xB0, 0x47, 0x0D, 0xF5), + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xCA, 0x27, 0xEE, 0x4B, 0x23, 0x2B, 0x89), + MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0xB5, 0x68, 0xC8, 0x17, 0x5D, 0xC3, 0xAA), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x02, 0x08, 0xEE, 0x20, 0x9D, 0xEA, 0x64), + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x14, 0x50, 0xD4, 0x7D, 0x5F, 0xCF, 0xA0), + MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xFA, 0xF8, 0xA7, 0xC6, 0xDC, 0x14, 0x8C), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xBD, 0x0A, 0x1A, 0x18, 0x98, 0xDC, 0xB0), + MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x63, 0x02, 0xB7, 0xD5, 0x5B, 0x5A, 0xC6), + MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xB1, 0xD7, 0x4B, 0x15, 0x39, 0x61, 0x5D), + MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x32, 0xE1, 0x9E, 0x70, 0x1B, 0xCE, 0x51), + MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0xD8, 0x18, 0x83, 0x52, 0x9B, 0x6D, 0xA2), + MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x55, 0x56, 0x19, 0x34, 0xA4, 0xEA, 0xFC), + MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0xA9, 0x55, 0x80, 0xE3, 0x15, 0x36, 0x8B), + MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x06, 0xC8, 0x1D, 0x17, 0x0D, 0xAD, 0x16), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0xD6, 0xF0, 0xCC, 0xF3, 0x63, 0x53, 0xD2), + MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x5A, 0xDC, 0x46, 0xBD, 0x0D, 0xAD, 0x96), + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x2F, 0x11, 0x60, 0x15, 0x51, 0x4A, 0xEA), + MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xE3, 0x93, 0x38, 0xD5, 0x83, 0xAA, 0x0D), + MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xA6, 0xCC, 0xB1, 0xFD, 0xBB, 0x1A, 0x0F), + MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x54, 0xC8, 0x54, 0x6F, 0x79, 0x1A, 0x59), + MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x4A, 0xDA, 0x28, 0x92, 0x97, 0x9D, 0x7F), + MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x4B, 0xDB, 0xC7, 0x52, 0xC5, 0x66, 0x34), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x7E, 0x92, 0x53, 0x30, 0x93, 0xFD, 0xFF), + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x16, 0x6A, 0xB1, 0x91, 0x0A, 0xB4, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x9D, 0x40, 0x3F, 0xE3, 0xF1, 0x01, 0x46), + MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x0E, 0xD8, 0xED, 0x11, 0x8E, 0x4C, 0xED), + MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x4A, 0x1B, 0x88, 0xDF, 0x8D, 0x29, 0xE7), + MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x23, 0x21, 0x11, 0xAB, 0x77, 0x81, 0x62), + MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xAF, 0x11, 0xFA, 0xBA, 0x40, 0x63, 0xE7), + MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x6F, 0x8D, 0x80, 0xDF, 0x67, 0xF5, 0x44), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0x8B, 0xB7, 0x08, 0xF4, 0xD7, 0x2D, 0xA8), + MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x2B, 0x30, 0x02, 0x45, 0x71, 0x08, 0x49), + MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x3A, 0xCA, 0x50, 0xF6, 0xC2, 0x19, 0x8C), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xB9, 0x9B, 0x3E, 0x73, 0x95, 0x1D, 0x49), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x60, 0x59, 0x48, 0xCB, 0xD8, 0xD6, 0xAA), + MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xB9, 0x6C, 0x89, 0xAB, 0x99, 0xA8, 0xF8), + MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0xA1, 0x8B, 0x4E, 0x06, 0x19, 0xEC, 0x99), + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x95, 0x04, 0xCF, 0xD5, 0x94, 0xB3, 0x02), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x35, 0x93, 0x7C, 0xB3, 0xB8, 0x9E, 0x1B), + MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x45, 0x5C, 0x7E, 0xBF, 0x75, 0x81, 0x0F), + MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xE8, 0x24, 0xDF, 0xEC, 0x2F, 0x7D, 0xB9), + MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x8B, 0xD5, 0x6A, 0x9B, 0xA0, 0xE0, 0x4F), + MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xE3, 0x27, 0x82, 0xDE, 0xDD, 0xCA, 0x4B), + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x57, 0x56, 0x46, 0x05, 0x06, 0x01, 0x2E), + MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x35, 0xA7, 0x47, 0xE2, 0x6B, 0x2C, 0x4F), + MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x9D, 0x4C, 0xEC, 0x1F, 0x11, 0x75, 0x2B), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xAA, 0x41, 0xC1, 0xE9, 0x0E, 0xE9, 0xAA), + MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xCF, 0x9C, 0x4B, 0xE8, 0xED, 0x0A, 0x49), + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x73, 0xCA, 0x0C, 0x46, 0x0A, 0x9C, 0xE4), + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xE1, 0x9E, 0xBC, 0xFE, 0x44, 0x63, 0x6D), + MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x43, 0x71, 0xEE, 0xF8, 0xC1, 0x8C, 0x5C), + MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x4B, 0xF0, 0x69, 0x25, 0xBD, 0x71, 0x1A), + MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x9A, 0xFE, 0x82, 0xE7, 0xC1, 0xC1, 0xEE), + MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x5A, 0x6E, 0x5E, 0x97, 0x6A, 0x35, 0x8D), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x18, 0x6C, 0x7E, 0xB8, 0x9E, 0x57, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xB9, 0xC1, 0xD0, 0xFE, 0x78, 0xFB, 0x32), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x08, 0xAE, 0x46, 0x34, 0xEA, 0x7A, 0x7F), + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x1C, 0x56, 0xA9, 0x18, 0x37, 0xD4, 0x9E), + MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x63, 0xE9, 0x0A, 0xB6, 0x38, 0x3C, 0xC1), + MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x4F, 0xA4, 0x6E, 0x85, 0x31, 0x23, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0xAD, 0xC4, 0xC3, 0xB1, 0x4B, 0x1C, 0x82), + MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x56, 0x4A, 0x38, 0xB3, 0x6B, 0x6F, 0x2C), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_16_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0xC7, 0x19, 0xDE, 0x21, 0xED, 0x89, 0xD0), + MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xBE, 0xA6, 0xAE, 0xEB, 0x9D, 0xA7, 0x2A), + MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x0E, 0x13, 0x1E, 0x86, 0x57, 0xC3, 0x3B), + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x4B, 0x30, 0x46, 0x52, 0xC1, 0xEC, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xD5, 0x44, 0x31, 0x96, 0x3B, 0x26, 0x27), + MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x68, 0xA8, 0x67, 0x78, 0x39, 0xE8, 0x68), + MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x78, 0xB7, 0xDD, 0xF2, 0x58, 0xB6, 0x3D), + MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x3C, 0xB3, 0x26, 0xC4, 0x2C, 0x8C, 0xA5), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_16_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x24, 0xE5, 0x73, 0xEE, 0x9A, 0x02, 0xA9), + MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x6A, 0x65, 0x60, 0xF3, 0x62, 0xE3, 0xE9), + MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0x07, 0x84, 0xE6, 0x3B, 0x46, 0x65, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x8F, 0x0C, 0xB0, 0xE1, 0x04, 0x82, 0x9D), + MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x13, 0xBF, 0x3D, 0xA0, 0x48, 0xA2, 0x74), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x26, 0x76, 0x74, 0xAB, 0x0B, 0x29, 0xE8), + MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x6E, 0x5F, 0x03, 0x34, 0x7C, 0x38, 0xCE), + MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x72, 0xF9, 0x3B, 0x3C, 0xA4, 0xBC, 0x7C), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_17_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xCE, 0x18, 0x80, 0xB8, 0x24, 0x45, 0x81), + MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x09, 0x03, 0xB8, 0x06, 0x64, 0xF7, 0xEC), + MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x26, 0xB1, 0x10, 0x6D, 0x71, 0x12, 0x2E), + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x12, 0xC6, 0x6E, 0x1E, 0x6A, 0xC3, 0x80), + MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xD3, 0x0A, 0xDE, 0xD8, 0x6B, 0x04, 0x5C), + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x87, 0x5B, 0xAE, 0xDB, 0x3C, 0xC0, 0xC5), + MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0xF5, 0xF9, 0xC1, 0x9A, 0x89, 0xBB, 0x7E), + MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x69, 0x72, 0x8B, 0xAE, 0x32, 0x13, 0x11), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_17_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x16, 0x07, 0x50, 0xFA, 0x4C, 0xCF, 0xE8), + MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x50, 0x21, 0xE9, 0xDE, 0xEC, 0x7E, 0xDF), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x2F, 0xE8, 0x83, 0x30, 0x0B, 0x65, 0x0E), + MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x0B, 0x99, 0xAC, 0xC9, 0xBA, 0x6C, 0x2A), + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x59, 0x5A, 0x0D, 0x7B, 0x9E, 0x08, 0xAD), + MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x91, 0xB2, 0xDC, 0x90, 0xCE, 0x67, 0xED), + MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x93, 0x60, 0x0C, 0xD7, 0x1F, 0x2F, 0x17), + MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x7F, 0x9D, 0x40, 0xF8, 0x78, 0x7A, 0x54), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_18_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x22, 0x95, 0xE8, 0xEF, 0x31, 0x57, 0x35), + MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x88, 0x53, 0xFE, 0xAF, 0x7C, 0x47, 0x14), + MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xCE, 0xCC, 0x79, 0xE8, 0x9F, 0x8C, 0xC4), + MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x16, 0xDD, 0x77, 0x6E, 0x8A, 0x73, 0x97), + MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x07, 0x97, 0x21, 0x3B, 0xF8, 0x5F, 0xA8), + MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xB5, 0xD2, 0x81, 0x84, 0xF0, 0xE7, 0x9F), + MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x8F, 0x75, 0x09, 0x6A, 0x0E, 0x53, 0xAD), + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x4F, 0x70, 0x97, 0xC7, 0xAC, 0x7D, 0x3F), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_18_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x3C, 0x6A, 0xB4, 0x10, 0xA9, 0xC8, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xC5, 0xD6, 0x69, 0x16, 0xB8, 0xAC, 0x25), + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x44, 0xDC, 0xEB, 0x48, 0x54, 0x5D, 0x5F), + MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x48, 0x9B, 0xD7, 0x72, 0x69, 0xA4, 0x8A), + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x0D, 0x36, 0x9A, 0x66, 0x0B, 0xEC, 0x24), + MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xC6, 0xD4, 0xB6, 0x60, 0xE5, 0xC3, 0x3A), + MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x29, 0x42, 0xE0, 0x9D, 0xFD, 0x7C, 0x3E), + MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x10, 0xBA, 0x55, 0xBC, 0x3B, 0x38, 0x5D), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_19_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x66, 0xFA, 0x05, 0x73, 0x03, 0x1B, 0x69), + MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xA4, 0x66, 0x12, 0x96, 0x7B, 0x02, 0x4C), + MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0xB5, 0xDE, 0x6D, 0x98, 0xD1, 0xD5, 0xA8), + MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xF5, 0x44, 0xB8, 0x8E, 0xF6, 0x8C, 0x05), + MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x15, 0x2B, 0x72, 0xBC, 0x49, 0xE5, 0xDF), + MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x44, 0xD7, 0xDF, 0x8F, 0xEB, 0x8D, 0x80), + MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x64, 0x88, 0xAA, 0xB7, 0xE4, 0x70, 0x1D), + MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x14, 0xBB, 0xE9, 0x9B, 0xB9, 0x65, 0x5D), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_19_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x8E, 0x88, 0xF5, 0xF1, 0xC1, 0x89, 0xA2), + MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x30, 0x53, 0xE6, 0xFB, 0x2D, 0x82, 0xB4), + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xE4, 0xFF, 0xBA, 0x31, 0x79, 0xAB, 0xC2), + MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x09, 0xF7, 0xB7, 0x09, 0x78, 0x4C, 0x90), + MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xAE, 0xC2, 0x44, 0xDC, 0x17, 0x78, 0x47), + MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xD4, 0x17, 0x43, 0x19, 0x74, 0x9E, 0x23), + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x64, 0x3B, 0x73, 0xA2, 0x99, 0x27, 0x76), + MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x74, 0x36, 0x5F, 0xD3, 0x14, 0xB1, 0x31), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_20_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x07, 0xAB, 0xFD, 0x9B, 0x03, 0xC5, 0xD5), + MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xBE, 0xB0, 0x1D, 0xF2, 0x0C, 0x73, 0x73), + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xE7, 0x7B, 0x87, 0xD3, 0x34, 0xFD, 0xE2), + MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x25, 0x3D, 0xC7, 0x36, 0x83, 0x53, 0xDC), + MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x7C, 0xCF, 0x63, 0x55, 0x12, 0x11, 0xB0), + MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x34, 0x4D, 0x27, 0x92, 0xAC, 0x18, 0x16), + MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x42, 0x61, 0x9D, 0x2E, 0xFF, 0x13, 0x16), + MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0xDE, 0x92, 0x65, 0x57, 0x0D, 0xBC, 0x0A), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_20_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x7B, 0x6E, 0xC6, 0x2A, 0x21, 0x74, 0x0A), + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xA7, 0x53, 0x4D, 0x29, 0x36, 0xEF, 0xE5), + MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0xD6, 0x41, 0xC7, 0x99, 0xAD, 0x50, 0x53), + MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xAC, 0x41, 0x9F, 0xFB, 0x4C, 0x86, 0xF1), + MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xBB, 0xE6, 0x25, 0x28, 0xAA, 0xEB, 0x1E), + MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x04, 0xA2, 0xC3, 0xAA, 0x08, 0x8A, 0xCC), + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x2B, 0x5B, 0xE2, 0x8D, 0x76, 0xEA, 0x34), + MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x33, 0xD2, 0x21, 0x4D, 0x62, 0xE3, 0x8E), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_21_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x06, 0x8B, 0x2B, 0xC2, 0xC4, 0xB1, 0xD2), + MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xF5, 0xA1, 0xC0, 0x03, 0x6A, 0x29, 0x12), + MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xA9, 0xEF, 0x55, 0xB6, 0x1A, 0x9F, 0x6B), + MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x54, 0x32, 0xBE, 0x06, 0x43, 0xB5, 0xFD), + MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xD6, 0xD9, 0x20, 0x89, 0xBE, 0xD4, 0x1B), + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x26, 0x95, 0x10, 0xCE, 0xB4, 0x88, 0x79), + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xA6, 0x27, 0xAC, 0x32, 0xBA, 0xBD, 0xC7), + MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xA6, 0xAE, 0x9C, 0x7B, 0xBE, 0xA1, 0x63), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_21_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xCD, 0x4D, 0x3D, 0xDF, 0x96, 0xBB, 0x7D), + MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0xA7, 0x11, 0x06, 0xCC, 0x0E, 0x31, 0x81), + MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0xE4, 0xF4, 0xAD, 0x7B, 0x5F, 0xF1, 0xEF), + MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x54, 0xBE, 0xF4, 0x8A, 0x03, 0x47, 0xDF), + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x53, 0x00, 0x7F, 0xB0, 0x8A, 0x68, 0xA6), + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x16, 0xB1, 0x73, 0x6F, 0x5B, 0x0E, 0xC3), + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x32, 0xE3, 0x43, 0x64, 0x75, 0xFB, 0xFB), + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x18, 0x55, 0x8A, 0x4E, 0x6E, 0x35, 0x54), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_22_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x97, 0x15, 0x1E, 0xCB, 0xF2, 0x9C, 0xA5), + MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xD1, 0xBB, 0xF3, 0x70, 0xAD, 0x13, 0xAD), + MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x96, 0xA4, 0xC5, 0x5E, 0xDA, 0xD5, 0x57), + MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x81, 0xE9, 0x65, 0x66, 0x76, 0x47, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x35, 0x87, 0x06, 0x73, 0xCF, 0x34, 0xD2), + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x81, 0x15, 0x42, 0xA2, 0x79, 0x5B, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xA2, 0x7D, 0x09, 0x14, 0x64, 0xC6, 0xAE), + MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x6D, 0xC4, 0xED, 0xF1, 0xD6, 0xE9, 0x24), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_22_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xD5, 0xBB, 0x25, 0xA3, 0xDD, 0xA3, 0x88), + MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xF2, 0x68, 0x67, 0x39, 0x8F, 0x73, 0x93), + MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x76, 0x28, 0x89, 0xAD, 0x32, 0xE0, 0xDF), + MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x90, 0xCC, 0x57, 0x58, 0xAA, 0xC9, 0x75), + MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xD7, 0x43, 0xD2, 0xCE, 0x5E, 0xA0, 0x08), + MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xB0, 0xB8, 0xA4, 0x9E, 0x96, 0x26, 0x86), + MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x61, 0x1D, 0xF3, 0x65, 0x5E, 0x60, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x1E, 0x65, 0xED, 0xCF, 0x07, 0x60, 0x20), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_23_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x30, 0x17, 0x8A, 0x91, 0x88, 0x0A, 0xA4), + MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x7D, 0x18, 0xA4, 0xAC, 0x59, 0xFC, 0x5F), + MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x31, 0x8B, 0x25, 0x65, 0x39, 0x9A, 0xDC), + MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x16, 0x4B, 0x68, 0xBA, 0x59, 0x13, 0x2F), + MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xFD, 0xD3, 0xC5, 0x56, 0xC9, 0x8C, 0x5E), + MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xC6, 0x9F, 0xF4, 0xE6, 0xF7, 0xB4, 0x01), + MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x7C, 0x03, 0x00, 0x26, 0x9F, 0xD8, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x1D, 0x6E, 0x00, 0xB9, 0x00, 0x6E, 0x93), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_23_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x63, 0xDA, 0x03, 0x2B, 0xD5, 0x0B, 0xFE), + MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xFC, 0xE2, 0xC8, 0x47, 0xF0, 0xAE, 0xF2), + MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x4C, 0xF7, 0x50, 0x0C, 0x48, 0x06, 0x2A), + MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x2B, 0x32, 0x98, 0x0E, 0x7E, 0x61, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x02, 0x27, 0xFE, 0x75, 0x86, 0xDF, 0x24), + MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x30, 0xB1, 0x22, 0x32, 0x1B, 0xFE, 0x24), + MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x27, 0xF7, 0x78, 0x6F, 0xD7, 0xFD, 0xE4), + MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x78, 0xCC, 0xEA, 0xC0, 0x50, 0x24, 0x44), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_24_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x2B, 0x4F, 0x7F, 0x58, 0xE6, 0xC2, 0x70), + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x43, 0xD5, 0xA7, 0x35, 0x3C, 0x80, 0xB8), + MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x6D, 0x4B, 0x12, 0x00, 0x7B, 0xE6, 0xA6), + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x15, 0xBD, 0xD0, 0x9B, 0xCA, 0xAA, 0x81), + MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xCE, 0x9C, 0xE3, 0x8B, 0x60, 0x7A, 0x53), + MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xDA, 0x4B, 0x03, 0xA7, 0x8D, 0x43, 0x22), + MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xAF, 0x00, 0x2B, 0x32, 0xF0, 0x22, 0x68), + MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xD9, 0x99, 0x99, 0xBE, 0x43, 0x99, 0x3E), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_24_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x71, 0x41, 0xF4, 0xB5, 0xFD, 0xDD, 0x36), + MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xE2, 0x20, 0x4C, 0xD1, 0x2E, 0x1F, 0x06), + MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x43, 0x48, 0x76, 0x8A, 0x49, 0xAC, 0x87), + MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x1A, 0x55, 0xA8, 0xA3, 0xD4, 0x57, 0x75), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xA6, 0x84, 0x39, 0xC9, 0x13, 0xBB, 0x60), + MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0xFA, 0xA9, 0x70, 0xDE, 0x83, 0xDD, 0xC9), + MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0xC9, 0xD9, 0x3E, 0x44, 0x91, 0x68, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x9F, 0x85, 0x6D, 0xF7, 0x54, 0x36, 0x82), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_25_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x6B, 0xA6, 0xA3, 0xE5, 0xD4, 0x46, 0xDB), + MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x3E, 0xDC, 0x84, 0x7C, 0x7B, 0x24, 0x34), + MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xED, 0x7F, 0x86, 0x07, 0x6C, 0x57, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x06, 0xFE, 0x52, 0x12, 0x79, 0x69, 0x56), + MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0xD1, 0x44, 0x5F, 0x21, 0x3A, 0xC3, 0x84), + MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xD9, 0x4A, 0xC0, 0x75, 0xAB, 0x17, 0xAC), + MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x81, 0x94, 0xB6, 0x80, 0x6B, 0x6F, 0xC3), + MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xBE, 0x8E, 0xA5, 0xAA, 0xBC, 0x1E, 0x3E), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_25_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0xC7, 0x85, 0xA6, 0x59, 0x9B, 0xB1, 0x52), + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xCE, 0x40, 0xD1, 0xFB, 0xDF, 0x94, 0xF7), + MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xB8, 0x5E, 0xBF, 0x45, 0xA8, 0x2D, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x9C, 0x06, 0x1B, 0xA9, 0x57, 0xB9, 0x79), + MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xE9, 0xCE, 0xA2, 0xD3, 0x74, 0xA1, 0x3C), + MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x5F, 0x34, 0x78, 0xDB, 0xAE, 0x3A, 0x14), + MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x32, 0x84, 0x3E, 0x68, 0x6A, 0x43, 0x0F), + MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xBC, 0x39, 0x36, 0xA4, 0xC5, 0xBB, 0x11), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_26_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x07, 0xA2, 0xB5, 0xC9, 0x0F, 0x4D, 0x0F), + MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x1D, 0x67, 0xE6, 0xF1, 0x46, 0xEB, 0x71), + MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x41, 0x23, 0x95, 0xE7, 0xE0, 0x10, 0xDD), + MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x69, 0xFE, 0x68, 0x8C, 0xC6, 0x5F, 0xB6), + MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xB9, 0x2B, 0x3D, 0xD2, 0x4F, 0xD8, 0x1A), + MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x09, 0xF5, 0x5F, 0xCF, 0xF6, 0x91, 0x57), + MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x15, 0x42, 0x6B, 0x6D, 0xB5, 0xF3, 0xB6), + MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x56, 0x9D, 0xC5, 0xFF, 0xCA, 0x13, 0x9B), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_26_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x38, 0xE6, 0x23, 0x63, 0x48, 0x3C, 0xCA), + MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x68, 0x3C, 0xD1, 0x3B, 0xE9, 0x3B, 0x82), + MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x08, 0x54, 0x49, 0xD1, 0x46, 0x45, 0x13), + MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x70, 0x52, 0x6E, 0x79, 0xC4, 0x5E, 0x95), + MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xDF, 0xE8, 0x5A, 0x32, 0x81, 0xDA, 0xD3), + MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x2D, 0x94, 0x5B, 0xB5, 0x35, 0x9F, 0x0A), + MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x12, 0x8D, 0xC3, 0x36, 0x36, 0xB2, 0x2A), + MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x2F, 0x22, 0x38, 0x5B, 0x18, 0x4C, 0x35), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_27_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xC1, 0x22, 0x0E, 0xF0, 0x73, 0x11, 0x05), + MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xAE, 0xA4, 0x56, 0x18, 0x61, 0x66, 0x12), + MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xFB, 0x72, 0x08, 0x84, 0x38, 0x51, 0xB0), + MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x86, 0xA8, 0xB9, 0x31, 0x99, 0x29, 0xC3), + MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xFB, 0xC3, 0x42, 0xB3, 0xC7, 0x6F, 0x3A), + MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xF8, 0xE1, 0x09, 0xBE, 0x75, 0xB0, 0x22), + MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x7D, 0xFF, 0xF4, 0x99, 0xFC, 0x13, 0xAB), + MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x1B, 0x84, 0x81, 0x42, 0x22, 0xC6, 0x3D), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_27_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xE0, 0x37, 0xA4, 0xA0, 0x2F, 0x38, 0x7F), + MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x3D, 0xB7, 0x40, 0x2F, 0x39, 0x3C, 0x7A), + MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0x3B, 0x8A, 0x51, 0xAE, 0x40, 0x49, 0x7A), + MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x20, 0x9F, 0xDD, 0xA9, 0xD0, 0x77, 0xC7), + MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0x1D, 0x64, 0xDA, 0xA0, 0x53, 0xC7, 0x7D), + MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x7B, 0x66, 0x55, 0x94, 0xD1, 0x51, 0x44), + MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xA9, 0xB5, 0x5B, 0x38, 0x35, 0x40, 0xC0), + MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xC9, 0x0F, 0xF0, 0x73, 0x79, 0x43, 0x61), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_28_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x47, 0x45, 0x69, 0x80, 0x72, 0x72, 0x42), + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x11, 0x99, 0x59, 0xDB, 0x48, 0x80, 0x39), + MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x6E, 0x3D, 0xFC, 0x37, 0x15, 0xF4, 0xBF), + MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xBB, 0x5B, 0xA6, 0x35, 0x8D, 0x28, 0x20), + MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x1A, 0x3B, 0x2C, 0x8F, 0xD3, 0xAA, 0x2D), + MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x1C, 0x1A, 0xF8, 0x02, 0xD9, 0x7B, 0x41), + MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x69, 0xAC, 0xF8, 0x54, 0x31, 0x14, 0xA1), + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x8A, 0xE6, 0xDE, 0x58, 0xB9, 0xC4, 0x7A), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_28_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x83, 0x52, 0xFE, 0xF9, 0x7B, 0xE9, 0x1F), + MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xA2, 0x55, 0x46, 0x15, 0x49, 0xC1, 0x3A), + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xBC, 0x5C, 0x91, 0xBD, 0xB9, 0x9C, 0xF4), + MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xFD, 0xB1, 0x4E, 0x5F, 0x74, 0xEE, 0x53), + MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x8B, 0xD8, 0x8B, 0x17, 0x73, 0x1B, 0x96), + MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x92, 0xD7, 0x67, 0x06, 0xAD, 0x25, 0xCD), + MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x0F, 0x80, 0x24, 0xE2, 0x27, 0x5F, 0x8B), + MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x1C, 0xCE, 0xD0, 0x67, 0xCA, 0xD4, 0x0B), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_29_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0xF1, 0xDD, 0x33, 0x66, 0xF9, 0x05, 0xD6), + MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xE5, 0x6B, 0x79, 0xBD, 0x48, 0x42, 0xAA), + MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x14, 0x52, 0xE3, 0x53, 0xB4, 0x50, 0xD4), + MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x84, 0x6C, 0xCF, 0xDA, 0xB2, 0x20, 0x0A), + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xD6, 0x1A, 0xE5, 0xE2, 0x29, 0x70, 0xCE), + MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x61, 0xFE, 0xBB, 0x21, 0x82, 0xD1, 0xFE), + MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0xF0, 0x9C, 0x8B, 0x1A, 0x42, 0x30, 0x06), + MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0xD6, 0x49, 0x81, 0x92, 0xF1, 0xD0, 0x90), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_29_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x91, 0x93, 0x6A, 0xA6, 0x22, 0xE9, 0xD6), + MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0xDC, 0xC3, 0x69, 0x11, 0x95, 0x7D, 0xEC), + MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xA3, 0x9D, 0x87, 0x5E, 0x64, 0x41, 0xA2), + MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x87, 0x5A, 0x15, 0xBD, 0x6E, 0x3C, 0x8D), + MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x8D, 0x50, 0xCC, 0xCF, 0xB7, 0x8F, 0x0B), + MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x65, 0xCD, 0x31, 0x30, 0xF1, 0x68, 0x13), + MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x5C, 0x66, 0x67, 0x92, 0x30, 0x57, 0x95), + MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x9B, 0x01, 0x3D, 0x20, 0x8B, 0xD1, 0x0D), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_30_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0xC0, 0xE6, 0x4F, 0xDE, 0x62, 0xAB, 0xB3), + MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x48, 0xB3, 0x1C, 0x0F, 0x16, 0x93, 0x45), + MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x63, 0xBD, 0x1F, 0x16, 0x50, 0x56, 0x98), + MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x06, 0xBC, 0xE9, 0x27, 0x1C, 0x9A, 0x7B), + MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xFE, 0x21, 0xC5, 0x39, 0x55, 0xE1, 0xFD), + MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xA8, 0xD0, 0x96, 0x0E, 0xB5, 0xB2, 0x84), + MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xE7, 0x4B, 0xF3, 0x11, 0x0C, 0xC9, 0x5B), + MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x3A, 0xC4, 0x87, 0x71, 0xEE, 0xFA, 0x18), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_30_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x77, 0xEE, 0x81, 0x5E, 0x96, 0xEA, 0x4B), + MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xDF, 0xA9, 0xF4, 0x4F, 0x7C, 0xB2, 0x43), + MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0xD4, 0xDF, 0x35, 0x63, 0x47, 0x25, 0x8A), + MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x3D, 0xFF, 0xA4, 0x02, 0xC3, 0x95, 0x11), + MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x10, 0x78, 0xD1, 0x2B, 0xB7, 0xBE, 0x0E), + MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xE9, 0x57, 0xF9, 0xE0, 0xD8, 0xFC, 0xBC), + MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0xC4, 0x01, 0xD6, 0xB4, 0xE7, 0x78, 0xE2), + MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x6C, 0xB9, 0x13, 0xA4, 0xE8, 0x6D, 0x6F), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_31_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xB0, 0xC9, 0xCD, 0xBF, 0xA2, 0x1E, 0x63), + MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x4F, 0x86, 0x22, 0x9B, 0xEA, 0xE8, 0xBB), + MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x46, 0xDF, 0x43, 0xB9, 0x82, 0x2D, 0x0A), + MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x32, 0xF1, 0x4E, 0x95, 0x41, 0xAE, 0x8E), + MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x93, 0x26, 0xFC, 0xD3, 0x90, 0xDC, 0xEB), + MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x05, 0x45, 0xCA, 0xF9, 0x5A, 0x89, 0x93), + MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x82, 0x63, 0x4E, 0x55, 0x1D, 0x3A, 0x08), + MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x69, 0x52, 0x49, 0xE9, 0xED, 0x57, 0x34), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_31_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x64, 0xE9, 0xAC, 0x4C, 0x4A, 0xEA, 0x25), + MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xE9, 0x0B, 0x99, 0xE7, 0xF9, 0xA9, 0x2C), + MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x0C, 0xC1, 0xF4, 0x8D, 0x07, 0xB6, 0xB1), + MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x68, 0xFA, 0x35, 0xE4, 0x9E, 0xAE, 0xD9), + MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x2D, 0x1A, 0x13, 0x8E, 0x02, 0xE2, 0x63), + MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x38, 0x28, 0x86, 0x46, 0x7B, 0x3A, 0xE1), + MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x4C, 0x64, 0x59, 0x0A, 0xF9, 0x02, 0xC4), + MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x4F, 0x23, 0xA2, 0xC3, 0xD5, 0xEF, 0x42), +}; +static const mbedtls_ecp_point brainpoolP512r1_T[32] = { + ECP_POINT_INIT_XY_Z1(brainpoolP512r1_T_0_X, brainpoolP512r1_T_0_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_1_X, brainpoolP512r1_T_1_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_2_X, brainpoolP512r1_T_2_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_3_X, brainpoolP512r1_T_3_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_4_X, brainpoolP512r1_T_4_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_5_X, brainpoolP512r1_T_5_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_6_X, brainpoolP512r1_T_6_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_7_X, brainpoolP512r1_T_7_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_8_X, brainpoolP512r1_T_8_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_9_X, brainpoolP512r1_T_9_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_10_X, brainpoolP512r1_T_10_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_11_X, brainpoolP512r1_T_11_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_12_X, brainpoolP512r1_T_12_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_13_X, brainpoolP512r1_T_13_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_14_X, brainpoolP512r1_T_14_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_15_X, brainpoolP512r1_T_15_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_16_X, brainpoolP512r1_T_16_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_17_X, brainpoolP512r1_T_17_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_18_X, brainpoolP512r1_T_18_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_19_X, brainpoolP512r1_T_19_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_20_X, brainpoolP512r1_T_20_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_21_X, brainpoolP512r1_T_21_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_22_X, brainpoolP512r1_T_22_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_23_X, brainpoolP512r1_T_23_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_24_X, brainpoolP512r1_T_24_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_25_X, brainpoolP512r1_T_25_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_26_X, brainpoolP512r1_T_26_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_27_X, brainpoolP512r1_T_27_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_28_X, brainpoolP512r1_T_28_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_29_X, brainpoolP512r1_T_29_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_30_X, brainpoolP512r1_T_30_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_31_X, brainpoolP512r1_T_31_Y), +}; +#else +#define brainpoolP512r1_T NULL +#endif +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + + +#if defined(ECP_LOAD_GROUP) || defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || \ + defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) +/* + * 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 ), +}; +#define sm2_T NULL +#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; +} +#endif + +#if defined(ECP_LOAD_GROUP) +/* + * Set an MPI to static value 1 + */ +static inline void ecp_mpi_set1(mbedtls_mpi *X) +{ + X->s = 1; + X->n = 1; + X->p = mpi_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, + const mbedtls_ecp_point *T) +{ + 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; + + grp->T = (mbedtls_ecp_point *) T; + /* + * Set T_size to 0 to prevent T free by mbedtls_ecp_group_free. + */ + grp->T_size = 0; + + 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 *); +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn); +#endif +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +static int ecp_mod_p224(mbedtls_mpi *); +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p224_raw(mbedtls_mpi_uint *X, size_t X_limbs); +#endif +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +static int ecp_mod_p256(mbedtls_mpi *); +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p256_raw(mbedtls_mpi_uint *X, size_t X_limbs); +#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 *); +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p521_raw(mbedtls_mpi_uint *N_p, size_t N_n); +#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), \ + G ## _T \ + ) + +#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), \ + G ## _T \ + ) +#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; + +/* P = 2^255 - 19 */ +static const mbedtls_mpi_uint curve25519_p[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0xED, 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, 0X7F) +}; + +/* N = 2^252 + 27742317777372353535851937790883648493 */ +static const mbedtls_mpi_uint curve25519_n[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0XED, 0XD3, 0XF5, 0X5C, 0X1A, 0X63, 0X12, 0X58), + MBEDTLS_BYTES_TO_T_UINT_8(0XD6, 0X9C, 0XF7, 0XA2, 0XDE, 0XF9, 0XDE, 0X14), + MBEDTLS_BYTES_TO_T_UINT_8(0X00, 0X00, 0X00, 0X00, 0x00, 0x00, 0x00, 0x00), + MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10) +}; + +/* + * 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)); + + ecp_mpi_load(&grp->P, curve25519_p, sizeof(curve25519_p)); + + grp->pbits = mbedtls_mpi_bitlen(&grp->P); + + ecp_mpi_load(&grp->N, curve25519_n, sizeof(curve25519_n)); + + /* 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; + +/* P = 2^448 - 2^224 - 1 */ +static const mbedtls_mpi_uint curve448_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, 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), + MBEDTLS_BYTES_TO_T_UINT_8(0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00) +}; + +/* N = 2^446 - 13818066809895115352007386748515426880336692474882178609894547503885 */ +static const mbedtls_mpi_uint curve448_n[] = { + MBEDTLS_BYTES_TO_T_UINT_8(0XF3, 0X44, 0X58, 0XAB, 0X92, 0XC2, 0X78, 0X23), + MBEDTLS_BYTES_TO_T_UINT_8(0X55, 0X8F, 0XC5, 0X8D, 0X72, 0XC2, 0X6C, 0X21), + MBEDTLS_BYTES_TO_T_UINT_8(0X90, 0X36, 0XD6, 0XAE, 0X49, 0XDB, 0X4E, 0XC4), + MBEDTLS_BYTES_TO_T_UINT_8(0XE9, 0X23, 0XCA, 0X7C, 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, 0X3F), + MBEDTLS_BYTES_TO_T_UINT_8(0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00) +}; + +/* + * Specialized function for creating the Curve448 group + */ +static int ecp_use_curve448(mbedtls_ecp_group *grp) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* Actually ( A + 2 ) / 4 */ + MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->A, curve448_a24)); + + ecp_mpi_load(&grp->P, curve448_p, sizeof(curve448_p)); + 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); + + ecp_mpi_load(&grp->N, curve448_n, sizeof(curve448_n)); + + /* Actually, the required msb for private keys */ + grp->nbits = 447; + +cleanup: + 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) Np + (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 +#define RESET last_carry[0] = c; c = 0; p = Np +#define ADD_LAST add64(p, last_carry, &c) + +/* + * 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; + size_t expected_width = 2 * ((192 + biL - 1) / biL); + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); + ret = mbedtls_ecp_mod_p192_raw(N->p, expected_width); + +cleanup: + return ret; +} + +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn) +{ + mbedtls_mpi_uint c = 0, last_carry[WIDTH] = { 0 }; + mbedtls_mpi_uint *p, *end; + + if (Nn != 2*((192 + biL - 1)/biL)) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + p = Np; + end = p + Nn; + + ADD(3); ADD(5); NEXT; // A0 += A3 + A5 + ADD(3); ADD(4); ADD(5); NEXT; // A1 += A3 + A4 + A5 + ADD(4); ADD(5); // A2 += A4 + A5 + + RESET; + + /* Use the reduction for the carry as well: + * 2^192 * last_carry = 2^64 * last_carry + last_carry mod P192 + */ + ADD_LAST; NEXT; // A0 += last_carry + ADD_LAST; NEXT; // A1 += last_carry + + LAST; // A2 += carry + + return 0; +} + +#undef WIDTH +#undef A +#undef ADD +#undef NEXT +#undef LAST +#undef RESET +#undef ADD_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 X_limbs +#define A(j) X[j] +#define STORE32 X[i] = (mbedtls_mpi_uint) cur; +#define STORE0 X[i] = 0; + +#else /* 64 bit */ + +#define MAX32 X_limbs * 2 +#define A(j) \ + (j) % 2 ? \ + (uint32_t) (X[(j) / 2] >> 32) : \ + (uint32_t) (X[(j) / 2]) +#define STORE32 \ + if (i % 2) { \ + X[i/2] &= 0x00000000FFFFFFFF; \ + X[i/2] |= (uint64_t) (cur) << 32; \ + } else { \ + X[i/2] &= 0xFFFFFFFF00000000; \ + X[i/2] |= (uint32_t) cur; \ + } + +#define STORE0 \ + if (i % 2) { \ + X[i/2] &= 0x00000000FFFFFFFF; \ + } else { \ + X[i/2] &= 0xFFFFFFFF00000000; \ + } + +#endif + +static inline int8_t extract_carry(int64_t cur) +{ + return (int8_t) (cur >> 32); +} + +#define ADD(j) cur += A(j) +#define SUB(j) cur -= A(j) + +#define ADD_CARRY(cc) cur += (cc) +#define SUB_CARRY(cc) cur -= (cc) + +#define ADD_LAST ADD_CARRY(last_c) +#define SUB_LAST SUB_CARRY(last_c) + +/* + * Helpers for the main 'loop' + */ +#define INIT(b) \ + int8_t c = 0, last_c; \ + int64_t cur; \ + size_t i = 0; \ + LOAD32; + +#define NEXT \ + c = extract_carry(cur); \ + STORE32; i++; LOAD32; \ + ADD_CARRY(c); + +#define RESET \ + c = extract_carry(cur); \ + last_c = c; \ + STORE32; i = 0; LOAD32; \ + c = 0; \ + +#define LAST \ + c = extract_carry(cur); \ + STORE32; i++; \ + if (c != 0) \ + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; \ + while (i < MAX32) { STORE0; i++; } + +#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) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t expected_width = 2 * 224 / biL; + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); + ret = mbedtls_ecp_mod_p224_raw(N->p, expected_width); +cleanup: + return ret; +} + +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p224_raw(mbedtls_mpi_uint *X, size_t X_limbs) +{ + if (X_limbs != 2 * 224 / biL) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + 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); // A6 += -A13 + A10 + + RESET; + + /* Use 2^224 = P + 2^96 - 1 to modulo reduce the final carry */ + SUB_LAST; NEXT; // A0 -= last_c + ; NEXT; // A1 + ; NEXT; // A2 + ADD_LAST; NEXT; // A3 += last_c + ; NEXT; // A4 + ; NEXT; // A5 + // A6 + + /* The carry reduction cannot generate a carry + * (see commit 73e8553 for details)*/ + + LAST; + + return 0; +} + +#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) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t expected_width = 2 * 256 / biL; + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); + ret = mbedtls_ecp_mod_p256_raw(N->p, expected_width); +cleanup: + return ret; +} + +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p256_raw(mbedtls_mpi_uint *X, size_t X_limbs) +{ + if (X_limbs != 2 * 256 / biL) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + 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); // A7 + + RESET; + + /* Use 2^224 * (2^32 - 1) + 2^192 + 2^96 - 1 + * to modulo reduce the final carry. */ + ADD_LAST; NEXT; // A0 + ; NEXT; // A1 + ; NEXT; // A2 + SUB_LAST; NEXT; // A3 + ; NEXT; // A4 + ; NEXT; // A5 + SUB_LAST; NEXT; // A6 + ADD_LAST; // A7 + + RESET; + + /* Use 2^224 * (2^32 - 1) + 2^192 + 2^96 - 1 + * to modulo reduce the carry generated by the previous reduction. */ + ADD_LAST; NEXT; // A0 + ; NEXT; // A1 + ; NEXT; // A2 + SUB_LAST; NEXT; // A3 + ; NEXT; // A4 + ; NEXT; // A5 + SUB_LAST; NEXT; // A6 + ADD_LAST; // A7 + + LAST; + + return 0; +} + +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ + +#undef LOAD32 +#undef MAX32 +#undef A +#undef STORE32 +#undef STORE0 +#undef ADD +#undef SUB +#undef ADD_CARRY +#undef SUB_CARRY +#undef ADD_LAST +#undef SUB_LAST +#undef INIT +#undef NEXT +#undef RESET +#undef LAST + +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED || + MBEDTLS_ECP_DP_SECP256R1_ENABLED || + MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +#if 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); + +/* + * 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_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_SECP256R1_ENABLED || + MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +/* 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 = 2^521 - 1 (FIPS 186-3 D.2.5) + */ +static int ecp_mod_p521(mbedtls_mpi *N) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t expected_width = 2 * P521_WIDTH; + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); + ret = mbedtls_ecp_mod_p521_raw(N->p, expected_width); +cleanup: + return ret; +} + +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p521_raw(mbedtls_mpi_uint *X, size_t X_limbs) +{ + mbedtls_mpi_uint carry = 0; + + if (X_limbs != 2 * P521_WIDTH || X[2 * P521_WIDTH - 1] != 0) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + /* Step 1: Reduction to P521_WIDTH limbs */ + /* Helper references for bottom part of X */ + mbedtls_mpi_uint *X0 = X; + size_t X0_limbs = P521_WIDTH; + /* Helper references for top part of X */ + mbedtls_mpi_uint *X1 = X + X0_limbs; + size_t X1_limbs = X_limbs - X0_limbs; + /* Split X as X0 + 2^P521_WIDTH X1 and compute X0 + 2^(biL - 9) X1. + * (We are using that 2^P521_WIDTH = 2^(512 + biL) and that + * 2^(512 + biL) X1 = 2^(biL - 9) X1 mod P521.) + * The high order limb of the result will be held in carry and the rest + * in X0 (that is the result will be represented as + * 2^P521_WIDTH carry + X0). + * + * Also, note that the resulting carry is either 0 or 1: + * X0 < 2^P521_WIDTH = 2^(512 + biL) and X1 < 2^(P521_WIDTH-biL) = 2^512 + * therefore + * X0 + 2^(biL - 9) X1 < 2^(512 + biL) + 2^(512 + biL - 9) + * which in turn is less than 2 * 2^(512 + biL). + */ + mbedtls_mpi_uint shift = ((mbedtls_mpi_uint) 1u) << (biL - 9); + carry = mbedtls_mpi_core_mla(X0, X0_limbs, X1, X1_limbs, shift); + /* Set X to X0 (by clearing the top part). */ + memset(X1, 0, X1_limbs * sizeof(mbedtls_mpi_uint)); + + /* Step 2: Reduction modulo P521 + * + * At this point X is reduced to P521_WIDTH limbs. What remains is to add + * the carry (that is 2^P521_WIDTH carry) and to reduce mod P521. */ + + /* 2^P521_WIDTH carry = 2^(512 + biL) carry = 2^(biL - 9) carry mod P521. + * Also, recall that carry is either 0 or 1. */ + mbedtls_mpi_uint addend = carry << (biL - 9); + /* Keep the top 9 bits and reduce the rest, using 2^521 = 1 mod P521. */ + addend += (X[P521_WIDTH - 1] >> 9); + X[P521_WIDTH - 1] &= P521_MASK; + + /* Reuse the top part of X (already zeroed) as a helper array for + * carrying out the addition. */ + mbedtls_mpi_uint *addend_arr = X + P521_WIDTH; + addend_arr[0] = addend; + (void) mbedtls_mpi_core_add(X, X, addend_arr, P521_WIDTH); + /* Both addends were less than P521 therefore X < 2 * P521. (This also means + * that the result fit in P521_WIDTH limbs and there won't be any carry.) */ + + /* Clear the reused part of X. */ + addend_arr[0] = 0; + + return 0; +} + +#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^256 A1, return A0 + 38 * A1 + */ +static int ecp_mod_p255(mbedtls_mpi *N) +{ + mbedtls_mpi_uint Mp[P255_WIDTH]; + + /* Helper references for top part of N */ + mbedtls_mpi_uint * const NT_p = N->p + P255_WIDTH; + const size_t NT_n = N->n - P255_WIDTH; + if (N->n <= P255_WIDTH) { + return 0; + } + if (NT_n > P255_WIDTH) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + /* Split N as N + 2^256 M */ + memcpy(Mp, NT_p, sizeof(mbedtls_mpi_uint) * NT_n); + memset(NT_p, 0, sizeof(mbedtls_mpi_uint) * NT_n); + + /* N = A0 + 38 * A1 */ + mbedtls_mpi_core_mla(N->p, P255_WIDTH + 1, + Mp, NT_n, + 38); + + return 0; +} +#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 */ + +#if defined(MBEDTLS_TEST_HOOKS) +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_modulus_setup(mbedtls_mpi_mod_modulus *N, + const mbedtls_ecp_group_id id, + const mbedtls_ecp_curve_type ctype) +{ + mbedtls_mpi_uint *p = NULL; + size_t p_limbs; + + if (!(ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE || \ + ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_SCALAR)) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + switch (id) { +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + case MBEDTLS_ECP_DP_SECP192R1: + if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) { + p = (mbedtls_mpi_uint *) secp192r1_p; + p_limbs = CHARS_TO_LIMBS(sizeof(secp192r1_p)); + } else { + p = (mbedtls_mpi_uint *) secp192r1_n; + p_limbs = CHARS_TO_LIMBS(sizeof(secp192r1_n)); + } + break; +#endif + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + case MBEDTLS_ECP_DP_SECP224R1: + if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) { + p = (mbedtls_mpi_uint *) secp224r1_p; + p_limbs = CHARS_TO_LIMBS(sizeof(secp224r1_p)); + } else { + p = (mbedtls_mpi_uint *) secp224r1_n; + p_limbs = CHARS_TO_LIMBS(sizeof(secp224r1_n)); + } + break; +#endif + +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + case MBEDTLS_ECP_DP_SECP256R1: + if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) { + p = (mbedtls_mpi_uint *) secp256r1_p; + p_limbs = CHARS_TO_LIMBS(sizeof(secp256r1_p)); + } else { + p = (mbedtls_mpi_uint *) secp256r1_n; + p_limbs = CHARS_TO_LIMBS(sizeof(secp256r1_n)); + } + break; +#endif + +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + case MBEDTLS_ECP_DP_SECP384R1: + if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) { + p = (mbedtls_mpi_uint *) secp384r1_p; + p_limbs = CHARS_TO_LIMBS(sizeof(secp384r1_p)); + } else { + p = (mbedtls_mpi_uint *) secp384r1_n; + p_limbs = CHARS_TO_LIMBS(sizeof(secp384r1_n)); + } + break; +#endif + +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + case MBEDTLS_ECP_DP_SECP521R1: + if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) { + p = (mbedtls_mpi_uint *) secp521r1_p; + p_limbs = CHARS_TO_LIMBS(sizeof(secp521r1_p)); + } else { + p = (mbedtls_mpi_uint *) secp521r1_n; + p_limbs = CHARS_TO_LIMBS(sizeof(secp521r1_n)); + } + break; +#endif + +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + case MBEDTLS_ECP_DP_BP256R1: + if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) { + p = (mbedtls_mpi_uint *) brainpoolP256r1_p; + p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP256r1_p)); + } else { + p = (mbedtls_mpi_uint *) brainpoolP256r1_n; + p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP256r1_n)); + } + break; +#endif + +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + case MBEDTLS_ECP_DP_BP384R1: + if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) { + p = (mbedtls_mpi_uint *) brainpoolP384r1_p; + p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP384r1_p)); + } else { + p = (mbedtls_mpi_uint *) brainpoolP384r1_n; + p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP384r1_n)); + } + break; +#endif + +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + case MBEDTLS_ECP_DP_BP512R1: + if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) { + p = (mbedtls_mpi_uint *) brainpoolP512r1_p; + p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP512r1_p)); + } else { + p = (mbedtls_mpi_uint *) brainpoolP512r1_n; + p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP512r1_n)); + } + break; +#endif + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + case MBEDTLS_ECP_DP_CURVE25519: + if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) { + p = (mbedtls_mpi_uint *) curve25519_p; + p_limbs = CHARS_TO_LIMBS(sizeof(curve25519_p)); + } else { + p = (mbedtls_mpi_uint *) curve25519_n; + p_limbs = CHARS_TO_LIMBS(sizeof(curve25519_n)); + } + break; +#endif + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + case MBEDTLS_ECP_DP_SECP192K1: + if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) { + p = (mbedtls_mpi_uint *) secp192k1_p; + p_limbs = CHARS_TO_LIMBS(sizeof(secp192k1_p)); + } else { + p = (mbedtls_mpi_uint *) secp192k1_n; + p_limbs = CHARS_TO_LIMBS(sizeof(secp192k1_n)); + } + break; +#endif + +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + case MBEDTLS_ECP_DP_SECP224K1: + if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) { + p = (mbedtls_mpi_uint *) secp224k1_p; + p_limbs = CHARS_TO_LIMBS(sizeof(secp224k1_p)); + } else { + p = (mbedtls_mpi_uint *) secp224k1_n; + p_limbs = CHARS_TO_LIMBS(sizeof(secp224k1_n)); + } + break; +#endif + +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + case MBEDTLS_ECP_DP_SECP256K1: + if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) { + p = (mbedtls_mpi_uint *) secp256k1_p; + p_limbs = CHARS_TO_LIMBS(sizeof(secp256k1_p)); + } else { + p = (mbedtls_mpi_uint *) secp256k1_n; + p_limbs = CHARS_TO_LIMBS(sizeof(secp256k1_n)); + } + break; +#endif + +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) + case MBEDTLS_ECP_DP_CURVE448: + if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) { + p = (mbedtls_mpi_uint *) curve448_p; + p_limbs = CHARS_TO_LIMBS(sizeof(curve448_p)); + } else { + p = (mbedtls_mpi_uint *) curve448_n; + p_limbs = CHARS_TO_LIMBS(sizeof(curve448_n)); + } + break; +#endif + + default: + case MBEDTLS_ECP_DP_NONE: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + if (mbedtls_mpi_mod_modulus_setup(N, p, p_limbs, + MBEDTLS_MPI_MOD_REP_MONTGOMERY)) { + return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + } + return 0; +} +#endif /* MBEDTLS_TEST_HOOKS */ +#endif /* !MBEDTLS_ECP_ALT */ +#endif /* MBEDTLS_ECP_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/ecp_internal_alt.h b/optee/optee_os/lib/libmbedtls/mbedtls/library/ecp_internal_alt.h new file mode 100644 index 0000000..f663d67 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ecp_internal_alt.h @@ -0,0 +1,299 @@ +/** + * \file ecp_internal_alt.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 + +#include "mbedtls/build_info.h" + +#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_alt.h */ 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..cb16d23 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ecp_invasive.h @@ -0,0 +1,187 @@ +/** + * \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 "bignum_mod.h" +#include "mbedtls/ecp.h" + +#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_ECP_C) + +#if 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 */ + +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + +/** Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1) + * + * This operation expects a 384 bit MPI and the result of the reduction + * is a 192 bit MPI. + * + * \param[in,out] Np The address of the MPI to be converted. + * Must have twice as many limbs as the modulus. + * Upon return this holds the reduced value. The bitlength + * of the reduced value is the same as that of the modulus + * (192 bits). + * \param[in] Nn The length of \p Np in limbs. + */ +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn); + +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + +/** Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2) + * + * \param[in,out] X The address of the MPI to be converted. + * Must have exact limb size that stores a 448-bit MPI + * (double the bitlength of the modulus). + * Upon return holds the reduced value which is + * in range `0 <= X < 2 * N` (where N is the modulus). + * The bitlength of the reduced value is the same as + * that of the modulus (224 bits). + * \param[in] X_limbs The length of \p X in limbs. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X_limbs is not the + * limb size that sores a 448-bit MPI. + */ +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p224_raw(mbedtls_mpi_uint *X, size_t X_limbs); + +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + +/** Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3) + * + * \param[in,out] X The address of the MPI to be converted. + * Must have exact limb size that stores a 512-bit MPI + * (double the bitlength of the modulus). + * Upon return holds the reduced value which is + * in range `0 <= X < 2 * N` (where N is the modulus). + * The bitlength of the reduced value is the same as + * that of the modulus (256 bits). + * \param[in] X_limbs The length of \p X in limbs. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X_limbs is not the + * limb size that sores a 512-bit MPI. + */ +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p256_raw(mbedtls_mpi_uint *X, size_t X_limbs); + +#endif + +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + +/** Fast quasi-reduction modulo p521 = 2^521 - 1 (FIPS 186-3 D.2.5) + * + * \param[in,out] X The address of the MPI to be converted. + * Must have twice as many limbs as the modulus + * (the modulus is 521 bits long). Upon return this + * holds the reduced value. The reduced value is + * in range `0 <= X < 2 * N` (where N is the modulus). + * and its the bitlength is one plus the bitlength + * of the modulus. + * \param[in] X_limbs The length of \p X in limbs. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X_limbs does not have + * twice as many limbs as the modulus. + */ +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_mod_p521_raw(mbedtls_mpi_uint *X, size_t X_limbs); + +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + +/** Initialise a modulus with hard-coded const curve data. + * + * \note The caller is responsible for the \p N modulus' memory. + * mbedtls_mpi_mod_modulus_free(&N) should be invoked at the + * end of its lifecycle. + * + * \param[in,out] N The address of the modulus structure to populate. + * Must be initialized. + * \param[in] id The mbedtls_ecp_group_id for which to initialise the modulus. + * \param[in] ctype The mbedtls_ecp_curve_type identifier for a coordinate modulus (P) + * or a scalar modulus (N). + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the given MPIs do not + * have the correct number of limbs. + * + */ +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_modulus_setup(mbedtls_mpi_mod_modulus *N, + const mbedtls_ecp_group_id id, + const mbedtls_ecp_curve_type ctype); + +#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..e55410c --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/entropy.c @@ -0,0 +1,732 @@ +/* + * 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) + +#include "mbedtls/entropy.h" +#include "entropy_poll.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#include "mbedtls/platform.h" + +#include "mbedtls/platform.h" + + +#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 + + /* Reminder: Update ENTROPY_HAVE_STRONG in the test files + * when adding more strong entropy sources here. */ + +#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_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_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(data, len, tmp, 0)) != 0) { + goto cleanup; + } +#else + if ((ret = mbedtls_sha256(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(&ctx->accumulator, 0)) != 0) { + goto cleanup; + } else { + ctx->accumulator_started = 1; + } + if ((ret = mbedtls_sha512_update(&ctx->accumulator, header, 2)) != 0) { + goto cleanup; + } + ret = mbedtls_sha512_update(&ctx->accumulator, p, use_len); +#else + if (ctx->accumulator_started == 0 && + (ret = mbedtls_sha256_starts(&ctx->accumulator, 0)) != 0) { + goto cleanup; + } else { + ctx->accumulator_started = 1; + } + if ((ret = mbedtls_sha256_update(&ctx->accumulator, header, 2)) != 0) { + goto cleanup; + } + ret = mbedtls_sha256_update(&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(&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(&ctx->accumulator, 0)) != 0) { + goto exit; + } + if ((ret = mbedtls_sha512_update(&ctx->accumulator, buf, + MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0) { + goto exit; + } + + /* + * Perform second SHA-512 on entropy + */ + if ((ret = mbedtls_sha512(buf, MBEDTLS_ENTROPY_BLOCK_SIZE, + buf, 0)) != 0) { + goto exit; + } +#else /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ + if ((ret = mbedtls_sha256_finish(&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(&ctx->accumulator, 0)) != 0) { + goto exit; + } + if ((ret = mbedtls_sha256_update(&ctx->accumulator, buf, + MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0) { + goto exit; + } + + /* + * Perform second SHA-256 on entropy + */ + if ((ret = mbedtls_sha256(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; + } + + /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ + mbedtls_setbuf(f, NULL); + + 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; + } + + /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ + mbedtls_setbuf(f, NULL); + + 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) +/* + * 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; +} + +#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 that 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; + mbedtls_entropy_context ctx; + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; + unsigned char acc[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; + size_t i, j; + + if (verbose != 0) { + mbedtls_printf(" ENTROPY test: "); + } + + 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); + + 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..b5024c8 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/entropy_poll.c @@ -0,0 +1,239 @@ +/* + * 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 "entropy_poll.h" +#include "mbedtls/error.h" + +#if defined(MBEDTLS_TIMING_C) +#include "mbedtls/timing.h" +#endif +#include "mbedtls/platform.h" + +#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 mbedtls_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; + } + + /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ + mbedtls_setbuf(file, NULL); + + 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_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/entropy_poll.h b/optee/optee_os/lib/libmbedtls/mbedtls/library/entropy_poll.h new file mode 100644 index 0000000..3cfd4a4 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/entropy_poll.h @@ -0,0 +1,76 @@ +/** + * \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 + +#include "mbedtls/build_info.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Default thresholds for built-in sources, in bytes + */ +#define MBEDTLS_ENTROPY_MIN_PLATFORM 32 /**< Minimum for platform source */ +#if !defined(MBEDTLS_ENTROPY_MIN_HARDWARE) +#define MBEDTLS_ENTROPY_MIN_HARDWARE 32 /**< Minimum for the hardware source */ +#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_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 mbedtls_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/library/error.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/error.c new file mode 100644 index 0000000..85e3154 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/error.c @@ -0,0 +1,879 @@ +/* + * 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) + +#include "mbedtls/platform.h" + +#include +#include + +#if defined(MBEDTLS_AES_C) +#include "mbedtls/aes.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_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_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_PLATFORM_C) +#include "mbedtls/platform.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_LMS_C) +#include "mbedtls/lms.h" +#endif + +#if defined(MBEDTLS_MD_C) +#include "mbedtls/md.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_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_PKCS7_C) +#include "mbedtls/pkcs7.h" +#endif + +#if defined(MBEDTLS_POLY1305_C) +#include "mbedtls/poly1305.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 + + +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" ); +#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_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_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" ); +#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_BUFFER_TOO_SMALL): + return( "PK - The output buffer is too small" ); +#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_PKCS7_C) + case -(MBEDTLS_ERR_PKCS7_INVALID_FORMAT): + return( "PKCS7 - The format is invalid, e.g. different type expected" ); + case -(MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE): + return( "PKCS7 - Unavailable feature, e.g. anything other than signed data" ); + case -(MBEDTLS_ERR_PKCS7_INVALID_VERSION): + return( "PKCS7 - The PKCS #7 version element is invalid or cannot be parsed" ); + case -(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO): + return( "PKCS7 - The PKCS #7 content info is invalid or cannot be parsed" ); + case -(MBEDTLS_ERR_PKCS7_INVALID_ALG): + return( "PKCS7 - The algorithm tag or value is invalid or cannot be parsed" ); + case -(MBEDTLS_ERR_PKCS7_INVALID_CERT): + return( "PKCS7 - The certificate tag or value is invalid or cannot be parsed" ); + case -(MBEDTLS_ERR_PKCS7_INVALID_SIGNATURE): + return( "PKCS7 - Error parsing the signature" ); + case -(MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO): + return( "PKCS7 - Error parsing the signer's info" ); + case -(MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA): + return( "PKCS7 - Input invalid" ); + case -(MBEDTLS_ERR_PKCS7_ALLOC_FAILED): + return( "PKCS7 - Allocation of memory failed" ); + case -(MBEDTLS_ERR_PKCS7_VERIFY_FAIL): + return( "PKCS7 - Verification Failed" ); + case -(MBEDTLS_ERR_PKCS7_CERT_DATE_INVALID): + return( "PKCS7 - The PKCS #7 date issued/expired dates are invalid" ); +#endif /* MBEDTLS_PKCS7_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" ); +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_SSL_TLS_C) + case -(MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS): + return( "SSL - A cryptographic operation is in progress. Try again later" ); + 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_DECODE_ERROR): + return( "SSL - A message could not be parsed due to a syntactic error" ); + 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_UNSUPPORTED_EXTENSION): + return( "SSL - Client received an extended server hello containing an unsupported extension" ); + case -(MBEDTLS_ERR_SSL_NO_APPLICATION_PROTOCOL): + return( "SSL - No ALPN protocols supported that the client advertises" ); + 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_UNRECOGNIZED_NAME): + return( "SSL - No server could be identified matching the client's SNI" ); + 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_CERTIFICATE): + return( "SSL - Processing of the Certificate handshake message failed" ); + case -(MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET): + return( "SSL - * Received NewSessionTicket Post Handshake Message. This error code is experimental and may be changed or removed without notice" ); + case -(MBEDTLS_ERR_SSL_CANNOT_READ_EARLY_DATA): + return( "SSL - Not possible to read early data" ); + case -(MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA): + return( "SSL - Not possible to write early data" ); + 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_BAD_PROTOCOL_VERSION): + return( "SSL - Handshake protocol not within min/max boundaries" ); + case -(MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE): + return( "SSL - The handshake negotiation 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_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_ILLEGAL_PARAMETER): + return( "SSL - A field in a message was incorrect or inconsistent with other fields" ); + 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_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" ); +#endif /* MBEDTLS_AES_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" ); +#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_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" ); +#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" ); +#endif /* MBEDTLS_CCM_C */ + +#if defined(MBEDTLS_CHACHA20_C) + case -(MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA): + return( "CHACHA20 - Invalid input parameter(s)" ); +#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_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" ); +#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_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_GCM_C) + case -(MBEDTLS_ERR_GCM_AUTH_FAILED): + return( "GCM - Authenticated decryption failed" ); + case -(MBEDTLS_ERR_GCM_BAD_INPUT): + return( "GCM - Bad input parameters to function" ); + case -(MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL): + return( "GCM - An output buffer is too small" ); +#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_LMS_C) + case -(MBEDTLS_ERR_LMS_BAD_INPUT_DATA): + return( "LMS - Bad data has been input to an LMS function" ); + case -(MBEDTLS_ERR_LMS_OUT_OF_PRIVATE_KEYS): + return( "LMS - Specified LMS key has utilised all of its private keys" ); + case -(MBEDTLS_ERR_LMS_VERIFY_FAILED): + return( "LMS - LMS signature verification failed" ); + case -(MBEDTLS_ERR_LMS_ALLOC_FAILED): + return( "LMS - LMS failed to allocate space for a private key" ); + case -(MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL): + return( "LMS - Input/output buffer is too small to contain requited data" ); +#endif /* MBEDTLS_LMS_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_POLY1305_C) + case -(MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA): + return( "POLY1305 - Invalid input parameter(s)" ); +#endif /* MBEDTLS_POLY1305_C */ + +#if defined(MBEDTLS_SHA1_C) + 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_BAD_INPUT_DATA): + return( "SHA256 - SHA-256 input data was malformed" ); +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + 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_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 */ + /* 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 a dummy implementation when 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..71fcc35 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/gcm.c @@ -0,0 +1,1168 @@ +/* + * 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.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_AESNI_C) +#include "aesni.h" +#endif + +#if defined(MBEDTLS_AESCE_C) +#include "aesce.h" +#endif + +#if !defined(MBEDTLS_GCM_ALT) + +/* + * Initialize a context + */ +void mbedtls_gcm_init(mbedtls_gcm_context *ctx) +{ + 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_HAVE_CODE) + /* With CLMUL support, we need only h, not the rest of the table */ + if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) { + return 0; + } +#endif + +#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64) + if (mbedtls_aesce_has_support()) { + 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; + + if (keybits != 128 && keybits != 192 && keybits != 256) { + return MBEDTLS_ERR_GCM_BAD_INPUT; + } + + 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_HAVE_CODE) + if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) { + unsigned char h[16]; + + /* mbedtls_aesni_gcm_mult needs big-endian input */ + 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_HAVE_CODE */ + +#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64) + if (mbedtls_aesce_has_support()) { + unsigned char h[16]; + + /* mbedtls_aesce_gcm_mult needs big-endian input */ + 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_aesce_gcm_mult(output, x, h); + return; + } +#endif + + 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) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char work_buf[16]; + const unsigned char *p; + size_t use_len, olen = 0; + uint64_t iv_bits; + + /* IV is 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) { + 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; + + mbedtls_xor(ctx->y, ctx->y, p, use_len); + + gcm_mult(ctx, ctx->y, ctx->y); + + iv_len -= use_len; + p += use_len; + } + + mbedtls_xor(ctx->y, ctx->y, work_buf, 16); + + 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; + } + + return 0; +} + +/** + * mbedtls_gcm_context::buf contains the partial state of the computation of + * the authentication tag. + * mbedtls_gcm_context::add_len and mbedtls_gcm_context::len indicate + * different stages of the computation: + * * len == 0 && add_len == 0: initial state + * * len == 0 && add_len % 16 != 0: the first `add_len % 16` bytes have + * a partial block of AD that has been + * xored in but not yet multiplied in. + * * len == 0 && add_len % 16 == 0: the authentication tag is correct if + * the data ends now. + * * len % 16 != 0: the first `len % 16` bytes have + * a partial block of ciphertext that has + * been xored in but not yet multiplied in. + * * len > 0 && len % 16 == 0: the authentication tag is correct if + * the data ends now. + */ +int mbedtls_gcm_update_ad(mbedtls_gcm_context *ctx, + const unsigned char *add, size_t add_len) +{ + const unsigned char *p; + size_t use_len, offset; + + /* IV is limited to 2^64 bits, so 2^61 bytes */ + if ((uint64_t) add_len >> 61 != 0) { + return MBEDTLS_ERR_GCM_BAD_INPUT; + } + + offset = ctx->add_len % 16; + p = add; + + if (offset != 0) { + use_len = 16 - offset; + if (use_len > add_len) { + use_len = add_len; + } + + mbedtls_xor(ctx->buf + offset, ctx->buf + offset, p, use_len); + + if (offset + use_len == 16) { + gcm_mult(ctx, ctx->buf, ctx->buf); + } + + ctx->add_len += use_len; + add_len -= use_len; + p += use_len; + } + + ctx->add_len += add_len; + + while (add_len >= 16) { + mbedtls_xor(ctx->buf, ctx->buf, p, 16); + + gcm_mult(ctx, ctx->buf, ctx->buf); + + add_len -= 16; + p += 16; + } + + if (add_len > 0) { + mbedtls_xor(ctx->buf, ctx->buf, p, add_len); + } + + return 0; +} + +/* Increment the counter. */ +static void gcm_incr(unsigned char y[16]) +{ + size_t i; + for (i = 16; i > 12; i--) { + if (++y[i - 1] != 0) { + break; + } + } +} + +/* Calculate and apply the encryption mask. Process use_len bytes of data, + * starting at position offset in the mask block. */ +static int gcm_mask(mbedtls_gcm_context *ctx, + unsigned char ectr[16], + size_t offset, size_t use_len, + const unsigned char *input, + unsigned char *output) +{ + size_t olen = 0; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ectr, + &olen)) != 0) { + mbedtls_platform_zeroize(ectr, 16); + return ret; + } + + if (ctx->mode == MBEDTLS_GCM_DECRYPT) { + mbedtls_xor(ctx->buf + offset, ctx->buf + offset, input, use_len); + } + mbedtls_xor(output, ectr + offset, input, use_len); + if (ctx->mode == MBEDTLS_GCM_ENCRYPT) { + mbedtls_xor(ctx->buf + offset, ctx->buf + offset, output, use_len); + } + + return 0; +} + +int mbedtls_gcm_update(mbedtls_gcm_context *ctx, + const unsigned char *input, size_t input_length, + unsigned char *output, size_t output_size, + size_t *output_length) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const unsigned char *p = input; + unsigned char *out_p = output; + size_t offset; + unsigned char ectr[16] = { 0 }; + + if (output_size < input_length) { + return MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL; + } + *output_length = input_length; + + /* Exit early if input_length==0 so that we don't do any pointer arithmetic + * on a potentially null pointer. + * Returning early also means that the last partial block of AD remains + * untouched for mbedtls_gcm_finish */ + if (input_length == 0) { + return 0; + } + + if (output > input && (size_t) (output - input) < 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 + input_length < ctx->len || + (uint64_t) ctx->len + input_length > 0xFFFFFFFE0ull) { + return MBEDTLS_ERR_GCM_BAD_INPUT; + } + + if (ctx->len == 0 && ctx->add_len % 16 != 0) { + gcm_mult(ctx, ctx->buf, ctx->buf); + } + + offset = ctx->len % 16; + if (offset != 0) { + size_t use_len = 16 - offset; + if (use_len > input_length) { + use_len = input_length; + } + + if ((ret = gcm_mask(ctx, ectr, offset, use_len, p, out_p)) != 0) { + return ret; + } + + if (offset + use_len == 16) { + gcm_mult(ctx, ctx->buf, ctx->buf); + } + + ctx->len += use_len; + input_length -= use_len; + p += use_len; + out_p += use_len; + } + + ctx->len += input_length; + + while (input_length >= 16) { + gcm_incr(ctx->y); + if ((ret = gcm_mask(ctx, ectr, 0, 16, p, out_p)) != 0) { + return ret; + } + + gcm_mult(ctx, ctx->buf, ctx->buf); + + input_length -= 16; + p += 16; + out_p += 16; + } + + if (input_length > 0) { + gcm_incr(ctx->y); + if ((ret = gcm_mask(ctx, ectr, 0, input_length, p, out_p)) != 0) { + return ret; + } + } + + mbedtls_platform_zeroize(ectr, sizeof(ectr)); + return 0; +} + +int mbedtls_gcm_finish(mbedtls_gcm_context *ctx, + unsigned char *output, size_t output_size, + size_t *output_length, + unsigned char *tag, size_t tag_len) +{ + unsigned char work_buf[16]; + uint64_t orig_len; + uint64_t orig_add_len; + + /* We never pass any output in finish(). The output parameter exists only + * for the sake of alternative implementations. */ + (void) output; + (void) output_size; + *output_length = 0; + + orig_len = ctx->len * 8; + orig_add_len = ctx->add_len * 8; + + if (ctx->len == 0 && ctx->add_len % 16 != 0) { + gcm_mult(ctx, ctx->buf, ctx->buf); + } + + if (tag_len > 16 || tag_len < 4) { + return MBEDTLS_ERR_GCM_BAD_INPUT; + } + + if (ctx->len % 16 != 0) { + gcm_mult(ctx, ctx->buf, ctx->buf); + } + + 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); + + mbedtls_xor(ctx->buf, ctx->buf, work_buf, 16); + + gcm_mult(ctx, ctx->buf, ctx->buf); + + mbedtls_xor(tag, tag, ctx->buf, tag_len); + } + + 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; + size_t olen; + + if ((ret = mbedtls_gcm_starts(ctx, mode, iv, iv_len)) != 0) { + return ret; + } + + if ((ret = mbedtls_gcm_update_ad(ctx, add, add_len)) != 0) { + return ret; + } + + if ((ret = mbedtls_gcm_update(ctx, input, length, + output, length, &olen)) != 0) { + return ret; + } + + if ((ret = mbedtls_gcm_finish(ctx, NULL, 0, &olen, 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; + + 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; + size_t olen; + + if (verbose != 0) { +#if defined(MBEDTLS_GCM_ALT) + mbedtls_printf(" GCM note: alternative implementation.\n"); +#else /* MBEDTLS_GCM_ALT */ +#if defined(MBEDTLS_AESNI_HAVE_CODE) + if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) { + mbedtls_printf(" GCM note: using AESNI.\n"); + } else +#endif + mbedtls_printf(" GCM note: built-in implementation.\n"); +#endif /* MBEDTLS_GCM_ALT */ + } + + 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]); + if (ret != 0) { + goto exit; + } + + ret = mbedtls_gcm_update_ad(&ctx, + 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, + pt_test_data[pt_index_test_data[i]], + 32, + buf, sizeof(buf), &olen); + if (ret != 0) { + goto exit; + } + if (olen != 32) { + goto exit; + } + + ret = mbedtls_gcm_update(&ctx, + pt_test_data[pt_index_test_data[i]] + 32, + rest_len, + buf + 32, sizeof(buf) - 32, &olen); + if (ret != 0) { + goto exit; + } + if (olen != rest_len) { + goto exit; + } + } else { + ret = mbedtls_gcm_update(&ctx, + pt_test_data[pt_index_test_data[i]], + pt_len_test_data[i], + buf, sizeof(buf), &olen); + if (ret != 0) { + goto exit; + } + if (olen != pt_len_test_data[i]) { + goto exit; + } + } + + ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, 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]); + if (ret != 0) { + goto exit; + } + ret = mbedtls_gcm_update_ad(&ctx, + 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, + ct_test_data[j * 6 + i], 32, + buf, sizeof(buf), &olen); + if (ret != 0) { + goto exit; + } + if (olen != 32) { + goto exit; + } + + ret = mbedtls_gcm_update(&ctx, + ct_test_data[j * 6 + i] + 32, + rest_len, + buf + 32, sizeof(buf) - 32, &olen); + if (ret != 0) { + goto exit; + } + if (olen != rest_len) { + goto exit; + } + } else { + ret = mbedtls_gcm_update(&ctx, + ct_test_data[j * 6 + i], + pt_len_test_data[i], + buf, sizeof(buf), &olen); + if (ret != 0) { + goto exit; + } + if (olen != pt_len_test_data[i]) { + goto exit; + } + } + + ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, 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/hash_info.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/hash_info.c new file mode 100644 index 0000000..0e445b6 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/hash_info.c @@ -0,0 +1,123 @@ +/* + * Hash information that's independent from the crypto implementation. + * + * (See the corresponding header file for usage notes.) + */ +/* + * 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 "hash_info.h" +#include "mbedtls/legacy_or_psa.h" +#include "mbedtls/error.h" + +typedef struct { + psa_algorithm_t psa_alg; + mbedtls_md_type_t md_type; + unsigned char size; + unsigned char block_size; +} hash_entry; + +static const hash_entry hash_table[] = { +#if defined(MBEDTLS_HAS_ALG_MD5_VIA_LOWLEVEL_OR_PSA) + { PSA_ALG_MD5, MBEDTLS_MD_MD5, 16, 64 }, +#endif +#if defined(MBEDTLS_HAS_ALG_RIPEMD160_VIA_LOWLEVEL_OR_PSA) + { PSA_ALG_RIPEMD160, MBEDTLS_MD_RIPEMD160, 20, 64 }, +#endif +#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA) + { PSA_ALG_SHA_1, MBEDTLS_MD_SHA1, 20, 64 }, +#endif +#if defined(MBEDTLS_HAS_ALG_SHA_224_VIA_LOWLEVEL_OR_PSA) + { PSA_ALG_SHA_224, MBEDTLS_MD_SHA224, 28, 64 }, +#endif +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_LOWLEVEL_OR_PSA) + { PSA_ALG_SHA_256, MBEDTLS_MD_SHA256, 32, 64 }, +#endif +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_LOWLEVEL_OR_PSA) + { PSA_ALG_SHA_384, MBEDTLS_MD_SHA384, 48, 128 }, +#endif +#if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_LOWLEVEL_OR_PSA) + { PSA_ALG_SHA_512, MBEDTLS_MD_SHA512, 64, 128 }, +#endif + { PSA_ALG_NONE, MBEDTLS_MD_NONE, 0, 0 }, +}; + +/* Get size from MD type */ +unsigned char mbedtls_hash_info_get_size(mbedtls_md_type_t md_type) +{ + const hash_entry *entry = hash_table; + while (entry->md_type != MBEDTLS_MD_NONE && + entry->md_type != md_type) { + entry++; + } + + return entry->size; +} + +/* Get block size from MD type */ +unsigned char mbedtls_hash_info_get_block_size(mbedtls_md_type_t md_type) +{ + const hash_entry *entry = hash_table; + while (entry->md_type != MBEDTLS_MD_NONE && + entry->md_type != md_type) { + entry++; + } + + return entry->block_size; +} + +/* Get PSA from MD */ +psa_algorithm_t mbedtls_hash_info_psa_from_md(mbedtls_md_type_t md_type) +{ + const hash_entry *entry = hash_table; + while (entry->md_type != MBEDTLS_MD_NONE && + entry->md_type != md_type) { + entry++; + } + + return entry->psa_alg; +} + +/* Get MD from PSA */ +mbedtls_md_type_t mbedtls_hash_info_md_from_psa(psa_algorithm_t psa_alg) +{ + const hash_entry *entry = hash_table; + while (entry->md_type != MBEDTLS_MD_NONE && + entry->psa_alg != psa_alg) { + entry++; + } + + return entry->md_type; +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +int mbedtls_md_error_from_psa(psa_status_t status) +{ + switch (status) { + case PSA_SUCCESS: + return 0; + case PSA_ERROR_NOT_SUPPORTED: + return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE; + case PSA_ERROR_INVALID_ARGUMENT: + return MBEDTLS_ERR_MD_BAD_INPUT_DATA; + case PSA_ERROR_INSUFFICIENT_MEMORY: + return MBEDTLS_ERR_MD_ALLOC_FAILED; + default: + return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + } +} +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/hash_info.h b/optee/optee_os/lib/libmbedtls/mbedtls/library/hash_info.h new file mode 100644 index 0000000..f984c82 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/hash_info.h @@ -0,0 +1,101 @@ +/** + * Hash information that's independent from the crypto implementation. + * + * This can be used by: + * - code based on PSA + * - code based on the legacy API + * - code based on either of them depending on MBEDTLS_USE_PSA_CRYPTO + * - code based on either of them depending on what's available + * + * Note: this internal module will go away when everything becomes based on + * PSA Crypto; it is a helper for the transition while hash algorithms are + * still represented using mbedtls_md_type_t in most places even when PSA is + * used for the actual crypto computations. + * + * 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_HASH_INFO_H +#define MBEDTLS_HASH_INFO_H + +#include "common.h" + +#include "mbedtls/md.h" +#include "psa/crypto.h" +#include "mbedtls/platform_util.h" + +/** \def MBEDTLS_HASH_MAX_SIZE + * + * Maximum size of a hash based on configuration. + */ +#if defined(MBEDTLS_MD_C) && ( \ + !defined(MBEDTLS_PSA_CRYPTO_C) || \ + MBEDTLS_MD_MAX_SIZE >= PSA_HASH_MAX_SIZE) +#define MBEDTLS_HASH_MAX_SIZE MBEDTLS_MD_MAX_SIZE +#elif defined(MBEDTLS_PSA_CRYPTO_C) && ( \ + !defined(MBEDTLS_MD_C) || \ + PSA_HASH_MAX_SIZE >= MBEDTLS_MD_MAX_SIZE) +#define MBEDTLS_HASH_MAX_SIZE PSA_HASH_MAX_SIZE +#endif + +/** Get the output length of the given hash type from its MD type. + * + * \note To get the output length from the PSA alg, use \c PSA_HASH_LENGTH(). + * + * \param md_type The hash MD type. + * + * \return The output length in bytes, or 0 if not known. + */ +unsigned char mbedtls_hash_info_get_size(mbedtls_md_type_t md_type); + +/** Get the block size of the given hash type from its MD type. + * + * \note To get the output length from the PSA alg, use + * \c PSA_HASH_BLOCK_LENGTH(). + * + * \param md_type The hash MD type. + * + * \return The block size in bytes, or 0 if not known. + */ +unsigned char mbedtls_hash_info_get_block_size(mbedtls_md_type_t md_type); + +/** Get the PSA alg from the MD type. + * + * \param md_type The hash MD type. + * + * \return The corresponding PSA algorithm identifier, + * or PSA_ALG_NONE if not known. + */ +psa_algorithm_t mbedtls_hash_info_psa_from_md(mbedtls_md_type_t md_type); + +/** Get the MD type alg from the PSA algorithm identifier. + * + * \param psa_alg The PSA hash algorithm. + * + * \return The corresponding MD type, + * or MBEDTLS_MD_NONE if not known. + */ +mbedtls_md_type_t mbedtls_hash_info_md_from_psa(psa_algorithm_t psa_alg); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +/** Convert PSA status to MD error code. + * + * \param status PSA status. + * + * \return The corresponding MD error code, + */ +int MBEDTLS_DEPRECATED mbedtls_md_error_from_psa(psa_status_t status); +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ +#endif /* MBEDTLS_HASH_INFO_H */ 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..a3f071e --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/hkdf.c @@ -0,0 +1,173 @@ +/* + * 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..b157302 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/hmac_drbg.c @@ -0,0 +1,645 @@ +/* + * 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 + +#include "mbedtls/platform.h" + +/* + * 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(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; +} + +/* + * 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(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(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(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(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; + } + + /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ + mbedtls_setbuf(f, NULL); + + 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; + } + + /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ + mbedtls_setbuf(f, NULL); + + 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(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/lmots.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/lmots.c new file mode 100644 index 0000000..4061edd --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/lmots.c @@ -0,0 +1,825 @@ +/* + * The LM-OTS one-time public-key signature scheme + * + * 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 LM-OTS algorithm: + * + * [1] IETF RFC8554 + * D. McGrew, M. Curcio, S.Fluhrer + * https://datatracker.ietf.org/doc/html/rfc8554 + * + * [2] NIST Special Publication 800-208 + * David A. Cooper et. al. + * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-208.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_LMS_C) + +#include + +#include "lmots.h" + +#include "mbedtls/lms.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" +#include "mbedtls/psa_util.h" + +#include "psa/crypto.h" + +#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \ + psa_to_lms_errors, \ + psa_generic_status_to_mbedtls) + +#define PUBLIC_KEY_TYPE_OFFSET (0) +#define PUBLIC_KEY_I_KEY_ID_OFFSET (PUBLIC_KEY_TYPE_OFFSET + \ + MBEDTLS_LMOTS_TYPE_LEN) +#define PUBLIC_KEY_Q_LEAF_ID_OFFSET (PUBLIC_KEY_I_KEY_ID_OFFSET + \ + MBEDTLS_LMOTS_I_KEY_ID_LEN) +#define PUBLIC_KEY_KEY_HASH_OFFSET (PUBLIC_KEY_Q_LEAF_ID_OFFSET + \ + MBEDTLS_LMOTS_Q_LEAF_ID_LEN) + +/* We only support parameter sets that use 8-bit digits, as it does not require + * translation logic between digits and bytes */ +#define W_WINTERNITZ_PARAMETER (8u) +#define CHECKSUM_LEN (2) +#define I_DIGIT_IDX_LEN (2) +#define J_HASH_IDX_LEN (1) +#define D_CONST_LEN (2) + +#define DIGIT_MAX_VALUE ((1u << W_WINTERNITZ_PARAMETER) - 1u) + +#define D_CONST_LEN (2) +static const unsigned char D_PUBLIC_CONSTANT_BYTES[D_CONST_LEN] = { 0x80, 0x80 }; +static const unsigned char D_MESSAGE_CONSTANT_BYTES[D_CONST_LEN] = { 0x81, 0x81 }; + +#if defined(MBEDTLS_TEST_HOOKS) +int (*mbedtls_lmots_sign_private_key_invalidated_hook)(unsigned char *) = NULL; +#endif /* defined(MBEDTLS_TEST_HOOKS) */ + +void mbedtls_lms_unsigned_int_to_network_bytes(unsigned int val, size_t len, + unsigned char *bytes) +{ + size_t idx; + + for (idx = 0; idx < len; idx++) { + bytes[idx] = (val >> ((len - 1 - idx) * 8)) & 0xFF; + } +} + +unsigned int mbedtls_lms_network_bytes_to_unsigned_int(size_t len, + const unsigned char *bytes) +{ + size_t idx; + unsigned int val = 0; + + for (idx = 0; idx < len; idx++) { + val |= ((unsigned int) bytes[idx]) << (8 * (len - 1 - idx)); + } + + return val; +} + +/* Calculate the checksum digits that are appended to the end of the LMOTS digit + * string. See NIST SP800-208 section 3.1 or RFC8554 Algorithm 2 for details of + * the checksum algorithm. + * + * params The LMOTS parameter set, I and q values which + * describe the key being used. + * + * digest The digit string to create the digest from. As + * this does not contain a checksum, it is the same + * size as a hash output. + */ +static unsigned short lmots_checksum_calculate(const mbedtls_lmots_parameters_t *params, + const unsigned char *digest) +{ + size_t idx; + unsigned sum = 0; + + for (idx = 0; idx < MBEDTLS_LMOTS_N_HASH_LEN(params->type); idx++) { + sum += DIGIT_MAX_VALUE - digest[idx]; + } + + return sum; +} + +/* Create the string of digest digits (in the base determined by the Winternitz + * parameter with the checksum appended to the end (Q || cksm(Q)). See NIST + * SP800-208 section 3.1 or RFC8554 Algorithm 3 step 5 (also used in Algorithm + * 4b step 3) for details. + * + * params The LMOTS parameter set, I and q values which + * describe the key being used. + * + * msg The message that will be hashed to create the + * digest. + * + * msg_size The size of the message. + * + * C_random_value The random value that will be combined with the + * message digest. This is always the same size as a + * hash output for whichever hash algorithm is + * determined by the parameter set. + * + * output An output containing the digit string (+ + * checksum) of length P digits (in the case of + * MBEDTLS_LMOTS_SHA256_N32_W8, this means it is of + * size P bytes). + */ +static int create_digit_array_with_checksum(const mbedtls_lmots_parameters_t *params, + const unsigned char *msg, + size_t msg_len, + const unsigned char *C_random_value, + unsigned char *out) +{ + psa_hash_operation_t op = PSA_HASH_OPERATION_INIT; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t output_hash_len; + unsigned short checksum; + + status = psa_hash_setup(&op, PSA_ALG_SHA_256); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, params->I_key_identifier, + MBEDTLS_LMOTS_I_KEY_ID_LEN); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, params->q_leaf_identifier, + MBEDTLS_LMOTS_Q_LEAF_ID_LEN); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, D_MESSAGE_CONSTANT_BYTES, D_CONST_LEN); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, C_random_value, + MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(params->type)); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, msg, msg_len); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_finish(&op, out, + MBEDTLS_LMOTS_N_HASH_LEN(params->type), + &output_hash_len); + if (status != PSA_SUCCESS) { + goto exit; + } + + checksum = lmots_checksum_calculate(params, out); + mbedtls_lms_unsigned_int_to_network_bytes(checksum, CHECKSUM_LEN, + out + MBEDTLS_LMOTS_N_HASH_LEN(params->type)); + +exit: + psa_hash_abort(&op); + + return PSA_TO_MBEDTLS_ERR(status); +} + +/* Hash each element of the string of digits (+ checksum), producing a hash + * output for each element. This is used in several places (by varying the + * hash_idx_min/max_values) in order to calculate a public key from a private + * key (RFC8554 Algorithm 1 step 4), in order to sign a message (RFC8554 + * Algorithm 3 step 5), and to calculate a public key candidate from a + * signature and message (RFC8554 Algorithm 4b step 3). + * + * params The LMOTS parameter set, I and q values which + * describe the key being used. + * + * x_digit_array The array of digits (of size P, 34 in the case of + * MBEDTLS_LMOTS_SHA256_N32_W8). + * + * hash_idx_min_values An array of the starting values of the j iterator + * for each of the members of the digit array. If + * this value in NULL, then all iterators will start + * at 0. + * + * hash_idx_max_values An array of the upper bound values of the j + * iterator for each of the members of the digit + * array. If this value in NULL, then iterator is + * bounded to be less than 2^w - 1 (255 in the case + * of MBEDTLS_LMOTS_SHA256_N32_W8) + * + * output An array containing a hash output for each member + * of the digit string P. In the case of + * MBEDTLS_LMOTS_SHA256_N32_W8, this is of size 32 * + * 34. + */ +static int hash_digit_array(const mbedtls_lmots_parameters_t *params, + const unsigned char *x_digit_array, + const unsigned char *hash_idx_min_values, + const unsigned char *hash_idx_max_values, + unsigned char *output) +{ + unsigned int i_digit_idx; + unsigned char i_digit_idx_bytes[I_DIGIT_IDX_LEN]; + unsigned int j_hash_idx; + unsigned char j_hash_idx_bytes[J_HASH_IDX_LEN]; + unsigned int j_hash_idx_min; + unsigned int j_hash_idx_max; + psa_hash_operation_t op = PSA_HASH_OPERATION_INIT; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t output_hash_len; + unsigned char tmp_hash[MBEDTLS_LMOTS_N_HASH_LEN_MAX]; + + for (i_digit_idx = 0; + i_digit_idx < MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(params->type); + i_digit_idx++) { + + memcpy(tmp_hash, + &x_digit_array[i_digit_idx * MBEDTLS_LMOTS_N_HASH_LEN(params->type)], + MBEDTLS_LMOTS_N_HASH_LEN(params->type)); + + j_hash_idx_min = hash_idx_min_values != NULL ? + hash_idx_min_values[i_digit_idx] : 0; + j_hash_idx_max = hash_idx_max_values != NULL ? + hash_idx_max_values[i_digit_idx] : DIGIT_MAX_VALUE; + + for (j_hash_idx = j_hash_idx_min; + j_hash_idx < j_hash_idx_max; + j_hash_idx++) { + status = psa_hash_setup(&op, PSA_ALG_SHA_256); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, + params->I_key_identifier, + MBEDTLS_LMOTS_I_KEY_ID_LEN); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, + params->q_leaf_identifier, + MBEDTLS_LMOTS_Q_LEAF_ID_LEN); + if (status != PSA_SUCCESS) { + goto exit; + } + + mbedtls_lms_unsigned_int_to_network_bytes(i_digit_idx, + I_DIGIT_IDX_LEN, + i_digit_idx_bytes); + status = psa_hash_update(&op, i_digit_idx_bytes, I_DIGIT_IDX_LEN); + if (status != PSA_SUCCESS) { + goto exit; + } + + mbedtls_lms_unsigned_int_to_network_bytes(j_hash_idx, + J_HASH_IDX_LEN, + j_hash_idx_bytes); + status = psa_hash_update(&op, j_hash_idx_bytes, J_HASH_IDX_LEN); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, tmp_hash, + MBEDTLS_LMOTS_N_HASH_LEN(params->type)); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_finish(&op, tmp_hash, sizeof(tmp_hash), + &output_hash_len); + if (status != PSA_SUCCESS) { + goto exit; + } + + psa_hash_abort(&op); + } + + memcpy(&output[i_digit_idx * MBEDTLS_LMOTS_N_HASH_LEN(params->type)], + tmp_hash, MBEDTLS_LMOTS_N_HASH_LEN(params->type)); + } + +exit: + psa_hash_abort(&op); + mbedtls_platform_zeroize(tmp_hash, sizeof(tmp_hash)); + + return PSA_TO_MBEDTLS_ERR(status); +} + +/* Combine the hashes of the digit array into a public key. This is used in + * in order to calculate a public key from a private key (RFC8554 Algorithm 1 + * step 4), and to calculate a public key candidate from a signature and message + * (RFC8554 Algorithm 4b step 3). + * + * params The LMOTS parameter set, I and q values which describe + * the key being used. + * y_hashed_digits The array of hashes, one hash for each digit of the + * symbol array (which is of size P, 34 in the case of + * MBEDTLS_LMOTS_SHA256_N32_W8) + * + * pub_key The output public key (or candidate public key in + * case this is being run as part of signature + * verification), in the form of a hash output. + */ +static int public_key_from_hashed_digit_array(const mbedtls_lmots_parameters_t *params, + const unsigned char *y_hashed_digits, + unsigned char *pub_key) +{ + psa_hash_operation_t op = PSA_HASH_OPERATION_INIT; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t output_hash_len; + + status = psa_hash_setup(&op, PSA_ALG_SHA_256); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, + params->I_key_identifier, + MBEDTLS_LMOTS_I_KEY_ID_LEN); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, params->q_leaf_identifier, + MBEDTLS_LMOTS_Q_LEAF_ID_LEN); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, D_PUBLIC_CONSTANT_BYTES, D_CONST_LEN); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, y_hashed_digits, + MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(params->type) * + MBEDTLS_LMOTS_N_HASH_LEN(params->type)); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_finish(&op, pub_key, + MBEDTLS_LMOTS_N_HASH_LEN(params->type), + &output_hash_len); + if (status != PSA_SUCCESS) { + +exit: + psa_hash_abort(&op); + } + + return PSA_TO_MBEDTLS_ERR(status); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +int mbedtls_lms_error_from_psa(psa_status_t status) +{ + switch (status) { + case PSA_SUCCESS: + return 0; + case PSA_ERROR_HARDWARE_FAILURE: + return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + case PSA_ERROR_NOT_SUPPORTED: + return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED; + case PSA_ERROR_BUFFER_TOO_SMALL: + return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL; + case PSA_ERROR_INVALID_ARGUMENT: + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + default: + return MBEDTLS_ERR_ERROR_GENERIC_ERROR; + } +} +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +void mbedtls_lmots_public_init(mbedtls_lmots_public_t *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); +} + +void mbedtls_lmots_public_free(mbedtls_lmots_public_t *ctx) +{ + mbedtls_platform_zeroize(ctx, sizeof(*ctx)); +} + +int mbedtls_lmots_import_public_key(mbedtls_lmots_public_t *ctx, + const unsigned char *key, size_t key_len) +{ + if (key_len < MBEDTLS_LMOTS_SIG_TYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + ctx->params.type = + mbedtls_lms_network_bytes_to_unsigned_int(MBEDTLS_LMOTS_TYPE_LEN, + key + MBEDTLS_LMOTS_SIG_TYPE_OFFSET); + + if (key_len != MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type)) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + memcpy(ctx->params.I_key_identifier, + key + PUBLIC_KEY_I_KEY_ID_OFFSET, + MBEDTLS_LMOTS_I_KEY_ID_LEN); + + memcpy(ctx->params.q_leaf_identifier, + key + PUBLIC_KEY_Q_LEAF_ID_OFFSET, + MBEDTLS_LMOTS_Q_LEAF_ID_LEN); + + memcpy(ctx->public_key, + key + PUBLIC_KEY_KEY_HASH_OFFSET, + MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type)); + + ctx->have_public_key = 1; + + return 0; +} + +int mbedtls_lmots_export_public_key(const mbedtls_lmots_public_t *ctx, + unsigned char *key, size_t key_size, + size_t *key_len) +{ + if (key_size < MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type)) { + return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL; + } + + if (!ctx->have_public_key) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + mbedtls_lms_unsigned_int_to_network_bytes(ctx->params.type, + MBEDTLS_LMOTS_TYPE_LEN, + key + MBEDTLS_LMOTS_SIG_TYPE_OFFSET); + + memcpy(key + PUBLIC_KEY_I_KEY_ID_OFFSET, + ctx->params.I_key_identifier, + MBEDTLS_LMOTS_I_KEY_ID_LEN); + + memcpy(key + PUBLIC_KEY_Q_LEAF_ID_OFFSET, + ctx->params.q_leaf_identifier, + MBEDTLS_LMOTS_Q_LEAF_ID_LEN); + + memcpy(key + PUBLIC_KEY_KEY_HASH_OFFSET, ctx->public_key, + MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type)); + + if (key_len != NULL) { + *key_len = MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type); + } + + return 0; +} + +int mbedtls_lmots_calculate_public_key_candidate(const mbedtls_lmots_parameters_t *params, + const unsigned char *msg, + size_t msg_size, + const unsigned char *sig, + size_t sig_size, + unsigned char *out, + size_t out_size, + size_t *out_len) +{ + unsigned char tmp_digit_array[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX]; + unsigned char y_hashed_digits[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if (msg == NULL && msg_size != 0) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + if (sig_size != MBEDTLS_LMOTS_SIG_LEN(params->type) || + out_size < MBEDTLS_LMOTS_N_HASH_LEN(params->type)) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + ret = create_digit_array_with_checksum(params, msg, msg_size, + sig + MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET, + tmp_digit_array); + if (ret) { + return ret; + } + + ret = hash_digit_array(params, + sig + MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(params->type), + tmp_digit_array, NULL, (unsigned char *) y_hashed_digits); + if (ret) { + return ret; + } + + ret = public_key_from_hashed_digit_array(params, + (unsigned char *) y_hashed_digits, + out); + if (ret) { + return ret; + } + + if (out_len != NULL) { + *out_len = MBEDTLS_LMOTS_N_HASH_LEN(params->type); + } + + return 0; +} + +int mbedtls_lmots_verify(const mbedtls_lmots_public_t *ctx, + const unsigned char *msg, size_t msg_size, + const unsigned char *sig, size_t sig_size) +{ + unsigned char Kc_public_key_candidate[MBEDTLS_LMOTS_N_HASH_LEN_MAX]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if (msg == NULL && msg_size != 0) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + if (!ctx->have_public_key) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + if (ctx->params.type != MBEDTLS_LMOTS_SHA256_N32_W8) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + if (sig_size < MBEDTLS_LMOTS_SIG_TYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) { + return MBEDTLS_ERR_LMS_VERIFY_FAILED; + } + + if (mbedtls_lms_network_bytes_to_unsigned_int(MBEDTLS_LMOTS_TYPE_LEN, + sig + MBEDTLS_LMOTS_SIG_TYPE_OFFSET) != + MBEDTLS_LMOTS_SHA256_N32_W8) { + return MBEDTLS_ERR_LMS_VERIFY_FAILED; + } + + ret = mbedtls_lmots_calculate_public_key_candidate(&ctx->params, + msg, msg_size, sig, sig_size, + Kc_public_key_candidate, + MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type), + NULL); + if (ret) { + return MBEDTLS_ERR_LMS_VERIFY_FAILED; + } + + if (memcmp(&Kc_public_key_candidate, ctx->public_key, + sizeof(ctx->public_key))) { + return MBEDTLS_ERR_LMS_VERIFY_FAILED; + } + + return 0; +} + +#if defined(MBEDTLS_LMS_PRIVATE) + +void mbedtls_lmots_private_init(mbedtls_lmots_private_t *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); +} + +void mbedtls_lmots_private_free(mbedtls_lmots_private_t *ctx) +{ + mbedtls_platform_zeroize(ctx, + sizeof(*ctx)); +} + +int mbedtls_lmots_generate_private_key(mbedtls_lmots_private_t *ctx, + mbedtls_lmots_algorithm_type_t type, + const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN], + uint32_t q_leaf_identifier, + const unsigned char *seed, + size_t seed_size) +{ + psa_hash_operation_t op = PSA_HASH_OPERATION_INIT; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t output_hash_len; + unsigned int i_digit_idx; + unsigned char i_digit_idx_bytes[2]; + unsigned char const_bytes[1]; + + if (ctx->have_private_key) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + if (type != MBEDTLS_LMOTS_SHA256_N32_W8) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + ctx->params.type = type; + + memcpy(ctx->params.I_key_identifier, + I_key_identifier, + sizeof(ctx->params.I_key_identifier)); + + mbedtls_lms_unsigned_int_to_network_bytes(q_leaf_identifier, + MBEDTLS_LMOTS_Q_LEAF_ID_LEN, + ctx->params.q_leaf_identifier); + + mbedtls_lms_unsigned_int_to_network_bytes(0xFF, sizeof(const_bytes), + const_bytes); + + for (i_digit_idx = 0; + i_digit_idx < MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(ctx->params.type); + i_digit_idx++) { + status = psa_hash_setup(&op, PSA_ALG_SHA_256); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, + ctx->params.I_key_identifier, + sizeof(ctx->params.I_key_identifier)); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, + ctx->params.q_leaf_identifier, + MBEDTLS_LMOTS_Q_LEAF_ID_LEN); + if (status != PSA_SUCCESS) { + goto exit; + } + + mbedtls_lms_unsigned_int_to_network_bytes(i_digit_idx, I_DIGIT_IDX_LEN, + i_digit_idx_bytes); + status = psa_hash_update(&op, i_digit_idx_bytes, I_DIGIT_IDX_LEN); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, const_bytes, sizeof(const_bytes)); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, seed, seed_size); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_finish(&op, + ctx->private_key[i_digit_idx], + MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type), + &output_hash_len); + if (status != PSA_SUCCESS) { + goto exit; + } + + psa_hash_abort(&op); + } + + ctx->have_private_key = 1; + +exit: + psa_hash_abort(&op); + + return PSA_TO_MBEDTLS_ERR(status); +} + +int mbedtls_lmots_calculate_public_key(mbedtls_lmots_public_t *ctx, + const mbedtls_lmots_private_t *priv_ctx) +{ + unsigned char y_hashed_digits[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* Check that a private key is loaded */ + if (!priv_ctx->have_private_key) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + ret = hash_digit_array(&priv_ctx->params, + (unsigned char *) priv_ctx->private_key, NULL, + NULL, (unsigned char *) y_hashed_digits); + if (ret) { + goto exit; + } + + ret = public_key_from_hashed_digit_array(&priv_ctx->params, + (unsigned char *) y_hashed_digits, + ctx->public_key); + if (ret) { + goto exit; + } + + memcpy(&ctx->params, &priv_ctx->params, + sizeof(ctx->params)); + + ctx->have_public_key = 1; + +exit: + mbedtls_platform_zeroize(y_hashed_digits, sizeof(y_hashed_digits)); + + return ret; +} + +int mbedtls_lmots_sign(mbedtls_lmots_private_t *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, const unsigned char *msg, size_t msg_size, + unsigned char *sig, size_t sig_size, size_t *sig_len) +{ + unsigned char tmp_digit_array[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX]; + /* Create a temporary buffer to prepare the signature in. This allows us to + * finish creating a signature (ensuring the process doesn't fail), and then + * erase the private key **before** writing any data into the sig parameter + * buffer. If data were directly written into the sig buffer, it might leak + * a partial signature on failure, which effectively compromises the private + * key. + */ + unsigned char tmp_sig[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX]; + unsigned char tmp_c_random[MBEDTLS_LMOTS_N_HASH_LEN_MAX]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if (msg == NULL && msg_size != 0) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + if (sig_size < MBEDTLS_LMOTS_SIG_LEN(ctx->params.type)) { + return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL; + } + + /* Check that a private key is loaded */ + if (!ctx->have_private_key) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + ret = f_rng(p_rng, tmp_c_random, + MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type)); + if (ret) { + return ret; + } + + ret = create_digit_array_with_checksum(&ctx->params, + msg, msg_size, + tmp_c_random, + tmp_digit_array); + if (ret) { + goto exit; + } + + ret = hash_digit_array(&ctx->params, (unsigned char *) ctx->private_key, + NULL, tmp_digit_array, (unsigned char *) tmp_sig); + if (ret) { + goto exit; + } + + mbedtls_lms_unsigned_int_to_network_bytes(ctx->params.type, + MBEDTLS_LMOTS_TYPE_LEN, + sig + MBEDTLS_LMOTS_SIG_TYPE_OFFSET); + + /* Test hook to check if sig is being written to before we invalidate the + * private key. + */ +#if defined(MBEDTLS_TEST_HOOKS) + if (mbedtls_lmots_sign_private_key_invalidated_hook != NULL) { + ret = (*mbedtls_lmots_sign_private_key_invalidated_hook)(sig); + if (ret != 0) { + return ret; + } + } +#endif /* defined(MBEDTLS_TEST_HOOKS) */ + + /* We've got a valid signature now, so it's time to make sure the private + * key can't be reused. + */ + ctx->have_private_key = 0; + mbedtls_platform_zeroize(ctx->private_key, + sizeof(ctx->private_key)); + + memcpy(sig + MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET, tmp_c_random, + MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(ctx->params.type)); + + memcpy(sig + MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(ctx->params.type), tmp_sig, + MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(ctx->params.type) + * MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type)); + + if (sig_len != NULL) { + *sig_len = MBEDTLS_LMOTS_SIG_LEN(ctx->params.type); + } + + ret = 0; + +exit: + mbedtls_platform_zeroize(tmp_digit_array, sizeof(tmp_digit_array)); + mbedtls_platform_zeroize(tmp_sig, sizeof(tmp_sig)); + + return ret; +} + +#endif /* defined(MBEDTLS_LMS_PRIVATE) */ +#endif /* defined(MBEDTLS_LMS_C) */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/lmots.h b/optee/optee_os/lib/libmbedtls/mbedtls/library/lmots.h new file mode 100644 index 0000000..98d1941 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/lmots.h @@ -0,0 +1,323 @@ +/** + * \file lmots.h + * + * \brief This file provides an API for the LM-OTS post-quantum-safe one-time + * public-key signature scheme as defined in RFC8554 and NIST.SP.200-208. + * This implementation currently only supports a single parameter set + * MBEDTLS_LMOTS_SHA256_N32_W8 in order to reduce complexity. + */ +/* + * 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_LMOTS_H +#define MBEDTLS_LMOTS_H + +#include "mbedtls/build_info.h" + +#include "psa/crypto.h" + +#include "mbedtls/lms.h" + +#include +#include + + +#define MBEDTLS_LMOTS_PUBLIC_KEY_LEN(type) (MBEDTLS_LMOTS_TYPE_LEN + \ + MBEDTLS_LMOTS_I_KEY_ID_LEN + \ + MBEDTLS_LMOTS_Q_LEAF_ID_LEN + \ + MBEDTLS_LMOTS_N_HASH_LEN(type)) + +#define MBEDTLS_LMOTS_SIG_TYPE_OFFSET (0) +#define MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET (MBEDTLS_LMOTS_SIG_TYPE_OFFSET + \ + MBEDTLS_LMOTS_TYPE_LEN) +#define MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(type) (MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET + \ + MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(type)) + +#ifdef __cplusplus +extern "C" { +#endif + + +#if defined(MBEDTLS_TEST_HOOKS) +extern int (*mbedtls_lmots_sign_private_key_invalidated_hook)(unsigned char *); +#endif /* defined(MBEDTLS_TEST_HOOKS) */ + +/** + * \brief This function converts an unsigned int into a + * network-byte-order (big endian) string. + * + * \param val The unsigned integer value + * \param len The length of the string. + * \param bytes The string to output into. + */ +void mbedtls_lms_unsigned_int_to_network_bytes(unsigned int val, size_t len, + unsigned char *bytes); + +/** + * \brief This function converts a network-byte-order + * (big endian) string into an unsigned integer. + * + * \param len The length of the string. + * \param bytes The string. + * + * \return The corresponding LMS error code. + */ +unsigned int mbedtls_lms_network_bytes_to_unsigned_int(size_t len, + const unsigned char *bytes); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +/** + * \brief This function converts a \ref psa_status_t to a + * low-level LMS error code. + * + * \param status The psa_status_t to convert + * + * \return The corresponding LMS error code. + */ +int MBEDTLS_DEPRECATED mbedtls_lms_error_from_psa(psa_status_t status); +#endif + +/** + * \brief This function initializes a public LMOTS context + * + * \param ctx The uninitialized LMOTS context that will then be + * initialized. + */ +void mbedtls_lmots_public_init(mbedtls_lmots_public_t *ctx); + +/** + * \brief This function uninitializes a public LMOTS context + * + * \param ctx The initialized LMOTS context that will then be + * uninitialized. + */ +void mbedtls_lmots_public_free(mbedtls_lmots_public_t *ctx); + +/** + * \brief This function imports an LMOTS public key into a + * LMOTS context. + * + * \note Before this function is called, the context must + * have been initialized. + * + * \note See IETF RFC8554 for details of the encoding of + * this public key. + * + * \param ctx The initialized LMOTS context store the key in. + * \param key The buffer from which the key will be read. + * #MBEDTLS_LMOTS_PUBLIC_KEY_LEN bytes will be read + * from this. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lmots_import_public_key(mbedtls_lmots_public_t *ctx, + const unsigned char *key, size_t key_size); + +/** + * \brief This function exports an LMOTS public key from a + * LMOTS context that already contains a public key. + * + * \note Before this function is called, the context must + * have been initialized and the context must contain + * a public key. + * + * \note See IETF RFC8554 for details of the encoding of + * this public key. + * + * \param ctx The initialized LMOTS context that contains the + * public key. + * \param key The buffer into which the key will be output. Must + * be at least #MBEDTLS_LMOTS_PUBLIC_KEY_LEN in size. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lmots_export_public_key(const mbedtls_lmots_public_t *ctx, + unsigned char *key, size_t key_size, + size_t *key_len); + +/** + * \brief This function creates a candidate public key from + * an LMOTS signature. This can then be compared to + * the real public key to determine the validity of + * the signature. + * + * \note This function is exposed publicly to be used in LMS + * signature verification, it is expected that + * mbedtls_lmots_verify will be used for LMOTS + * signature verification. + * + * \param params The LMOTS parameter set, q and I values as an + * mbedtls_lmots_parameters_t struct. + * \param msg The buffer from which the message will be read. + * \param msg_size The size of the message that will be read. + * \param sig The buffer from which the signature will be read. + * #MBEDTLS_LMOTS_SIG_LEN bytes will be read from + * this. + * \param out The buffer where the candidate public key will be + * stored. Must be at least #MBEDTLS_LMOTS_N_HASH_LEN + * bytes in size. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lmots_calculate_public_key_candidate(const mbedtls_lmots_parameters_t *params, + const unsigned char *msg, + size_t msg_size, + const unsigned char *sig, + size_t sig_size, + unsigned char *out, + size_t out_size, + size_t *out_len); + +/** + * \brief This function verifies a LMOTS signature, using a + * LMOTS context that contains a public key. + * + * \warning This function is **not intended for use in + * production**, due to as-yet unsolved problems with + * handling stateful keys. The API for this function + * may change considerably in future versions. + * + * \note Before this function is called, the context must + * have been initialized and must contain a public key + * (either by import or calculation from a private + * key). + * + * \param ctx The initialized LMOTS context from which the public + * key will be read. + * \param msg The buffer from which the message will be read. + * \param msg_size The size of the message that will be read. + * \param sig The buf from which the signature will be read. + * #MBEDTLS_LMOTS_SIG_LEN bytes will be read from + * this. + * + * \return \c 0 on successful verification. + * \return A non-zero error code on failure. + */ +int mbedtls_lmots_verify(const mbedtls_lmots_public_t *ctx, + const unsigned char *msg, + size_t msg_size, const unsigned char *sig, + size_t sig_size); + +#if defined(MBEDTLS_LMS_PRIVATE) + +/** + * \brief This function initializes a private LMOTS context + * + * \param ctx The uninitialized LMOTS context that will then be + * initialized. + */ +void mbedtls_lmots_private_init(mbedtls_lmots_private_t *ctx); + +/** + * \brief This function uninitializes a private LMOTS context + * + * \param ctx The initialized LMOTS context that will then be + * uninitialized. + */ +void mbedtls_lmots_private_free(mbedtls_lmots_private_t *ctx); + +/** + * \brief This function calculates an LMOTS private key, and + * stores in into an LMOTS context. + * + * \warning This function is **not intended for use in + * production**, due to as-yet unsolved problems with + * handling stateful keys. The API for this function + * may change considerably in future versions. + * + * \note The seed must have at least 256 bits of entropy. + * + * \param ctx The initialized LMOTS context to generate the key + * into. + * \param I_key_identifier The key identifier of the key, as a 16-byte string. + * \param q_leaf_identifier The leaf identifier of key. If this LMOTS key is + * not being used as part of an LMS key, this should + * be set to 0. + * \param seed The seed used to deterministically generate the + * key. + * \param seed_size The length of the seed. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lmots_generate_private_key(mbedtls_lmots_private_t *ctx, + mbedtls_lmots_algorithm_type_t type, + const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN], + uint32_t q_leaf_identifier, + const unsigned char *seed, + size_t seed_size); + +/** + * \brief This function generates an LMOTS public key from a + * LMOTS context that already contains a private key. + * + * \note Before this function is called, the context must + * have been initialized and the context must contain + * a private key. + * + * \param ctx The initialized LMOTS context to generate the key + * from and store it into. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lmots_calculate_public_key(mbedtls_lmots_public_t *ctx, + const mbedtls_lmots_private_t *priv_ctx); + +/** + * \brief This function creates a LMOTS signature, using a + * LMOTS context that contains a private key. + * + * \note Before this function is called, the context must + * have been initialized and must contain a private + * key. + * + * \note LMOTS private keys can only be used once, otherwise + * attackers may be able to create forged signatures. + * If the signing operation is successful, the private + * key in the context will be erased, and no further + * signing will be possible until another private key + * is loaded + * + * \param ctx The initialized LMOTS context from which the + * private key will be read. + * \param f_rng The RNG function to be used for signature + * generation. + * \param p_rng The RNG context to be passed to f_rng + * \param msg The buffer from which the message will be read. + * \param msg_size The size of the message that will be read. + * \param sig The buf into which the signature will be stored. + * Must be at least #MBEDTLS_LMOTS_SIG_LEN in size. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_lmots_sign(mbedtls_lmots_private_t *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, const unsigned char *msg, size_t msg_size, + unsigned char *sig, size_t sig_size, size_t *sig_len); + +#endif /* defined(MBEDTLS_LMS_PRIVATE) */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_LMOTS_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/lms.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/lms.c new file mode 100644 index 0000000..acc3523 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/lms.c @@ -0,0 +1,783 @@ +/* + * The LMS stateful-hash public-key signature scheme + * + * 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 LMS algorithm: + * + * [1] IETF RFC8554 + * D. McGrew, M. Curcio, S.Fluhrer + * https://datatracker.ietf.org/doc/html/rfc8554 + * + * [2] NIST Special Publication 800-208 + * David A. Cooper et. al. + * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-208.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_LMS_C) + +#include + +#include "lmots.h" + +#include "psa/crypto.h" +#include "mbedtls/psa_util.h" +#include "mbedtls/lms.h" +#include "mbedtls/error.h" +#include "mbedtls/platform_util.h" + +#include "mbedtls/platform.h" + +#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \ + psa_to_lms_errors, \ + psa_generic_status_to_mbedtls) + +#define SIG_Q_LEAF_ID_OFFSET (0) +#define SIG_OTS_SIG_OFFSET (SIG_Q_LEAF_ID_OFFSET + \ + MBEDTLS_LMOTS_Q_LEAF_ID_LEN) +#define SIG_TYPE_OFFSET(otstype) (SIG_OTS_SIG_OFFSET + \ + MBEDTLS_LMOTS_SIG_LEN(otstype)) +#define SIG_PATH_OFFSET(otstype) (SIG_TYPE_OFFSET(otstype) + \ + MBEDTLS_LMS_TYPE_LEN) + +#define PUBLIC_KEY_TYPE_OFFSET (0) +#define PUBLIC_KEY_OTSTYPE_OFFSET (PUBLIC_KEY_TYPE_OFFSET + \ + MBEDTLS_LMS_TYPE_LEN) +#define PUBLIC_KEY_I_KEY_ID_OFFSET (PUBLIC_KEY_OTSTYPE_OFFSET + \ + MBEDTLS_LMOTS_TYPE_LEN) +#define PUBLIC_KEY_ROOT_NODE_OFFSET (PUBLIC_KEY_I_KEY_ID_OFFSET + \ + MBEDTLS_LMOTS_I_KEY_ID_LEN) + + +/* Currently only support H=10 */ +#define H_TREE_HEIGHT_MAX 10 +#define MERKLE_TREE_NODE_AM(type) ((size_t) 1 << (MBEDTLS_LMS_H_TREE_HEIGHT(type) + 1u)) +#define MERKLE_TREE_LEAF_NODE_AM(type) ((size_t) 1 << MBEDTLS_LMS_H_TREE_HEIGHT(type)) +#define MERKLE_TREE_INTERNAL_NODE_AM(type) ((size_t) 1 << MBEDTLS_LMS_H_TREE_HEIGHT(type)) + +#define D_CONST_LEN (2) +static const unsigned char D_LEAF_CONSTANT_BYTES[D_CONST_LEN] = { 0x82, 0x82 }; +static const unsigned char D_INTR_CONSTANT_BYTES[D_CONST_LEN] = { 0x83, 0x83 }; + + +/* Calculate the value of a leaf node of the Merkle tree (which is a hash of a + * public key and some other parameters like the leaf index). This function + * implements RFC8554 section 5.3, in the case where r >= 2^h. + * + * params The LMS parameter set, the underlying LMOTS + * parameter set, and I value which describe the key + * being used. + * + * pub_key The public key of the private whose index + * corresponds to the index of this leaf node. This + * is a hash output. + * + * r_node_idx The index of this node in the Merkle tree. Note + * that the root node of the Merkle tree is + * 1-indexed. + * + * out The output node value, which is a hash output. + */ +static int create_merkle_leaf_value(const mbedtls_lms_parameters_t *params, + unsigned char *pub_key, + unsigned int r_node_idx, + unsigned char *out) +{ + psa_hash_operation_t op; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t output_hash_len; + unsigned char r_node_idx_bytes[4]; + + op = psa_hash_operation_init(); + status = psa_hash_setup(&op, PSA_ALG_SHA_256); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, params->I_key_identifier, + MBEDTLS_LMOTS_I_KEY_ID_LEN); + if (status != PSA_SUCCESS) { + goto exit; + } + + mbedtls_lms_unsigned_int_to_network_bytes(r_node_idx, 4, r_node_idx_bytes); + status = psa_hash_update(&op, r_node_idx_bytes, 4); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, D_LEAF_CONSTANT_BYTES, D_CONST_LEN); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, pub_key, + MBEDTLS_LMOTS_N_HASH_LEN(params->otstype)); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_finish(&op, out, MBEDTLS_LMS_M_NODE_BYTES(params->type), + &output_hash_len); + if (status != PSA_SUCCESS) { + goto exit; + } + +exit: + psa_hash_abort(&op); + + return PSA_TO_MBEDTLS_ERR(status); +} + +/* Calculate the value of an internal node of the Merkle tree (which is a hash + * of a public key and some other parameters like the node index). This function + * implements RFC8554 section 5.3, in the case where r < 2^h. + * + * params The LMS parameter set, the underlying LMOTS + * parameter set, and I value which describe the key + * being used. + * + * left_node The value of the child of this node which is on + * the left-hand side. As with all nodes on the + * Merkle tree, this is a hash output. + * + * right_node The value of the child of this node which is on + * the right-hand side. As with all nodes on the + * Merkle tree, this is a hash output. + * + * r_node_idx The index of this node in the Merkle tree. Note + * that the root node of the Merkle tree is + * 1-indexed. + * + * out The output node value, which is a hash output. + */ +static int create_merkle_internal_value(const mbedtls_lms_parameters_t *params, + const unsigned char *left_node, + const unsigned char *right_node, + unsigned int r_node_idx, + unsigned char *out) +{ + psa_hash_operation_t op; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t output_hash_len; + unsigned char r_node_idx_bytes[4]; + + op = psa_hash_operation_init(); + status = psa_hash_setup(&op, PSA_ALG_SHA_256); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, params->I_key_identifier, + MBEDTLS_LMOTS_I_KEY_ID_LEN); + if (status != PSA_SUCCESS) { + goto exit; + } + + mbedtls_lms_unsigned_int_to_network_bytes(r_node_idx, 4, r_node_idx_bytes); + status = psa_hash_update(&op, r_node_idx_bytes, 4); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, D_INTR_CONSTANT_BYTES, D_CONST_LEN); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, left_node, + MBEDTLS_LMS_M_NODE_BYTES(params->type)); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_update(&op, right_node, + MBEDTLS_LMS_M_NODE_BYTES(params->type)); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_finish(&op, out, MBEDTLS_LMS_M_NODE_BYTES(params->type), + &output_hash_len); + if (status != PSA_SUCCESS) { + goto exit; + } + +exit: + psa_hash_abort(&op); + + return PSA_TO_MBEDTLS_ERR(status); +} + +void mbedtls_lms_public_init(mbedtls_lms_public_t *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); +} + +void mbedtls_lms_public_free(mbedtls_lms_public_t *ctx) +{ + mbedtls_platform_zeroize(ctx, sizeof(*ctx)); +} + +int mbedtls_lms_import_public_key(mbedtls_lms_public_t *ctx, + const unsigned char *key, size_t key_size) +{ + mbedtls_lms_algorithm_type_t type; + mbedtls_lmots_algorithm_type_t otstype; + + type = mbedtls_lms_network_bytes_to_unsigned_int(MBEDTLS_LMS_TYPE_LEN, + key + PUBLIC_KEY_TYPE_OFFSET); + if (type != MBEDTLS_LMS_SHA256_M32_H10) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + ctx->params.type = type; + + if (key_size != MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type)) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + otstype = mbedtls_lms_network_bytes_to_unsigned_int(MBEDTLS_LMOTS_TYPE_LEN, + key + PUBLIC_KEY_OTSTYPE_OFFSET); + if (otstype != MBEDTLS_LMOTS_SHA256_N32_W8) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + ctx->params.otstype = otstype; + + memcpy(ctx->params.I_key_identifier, + key + PUBLIC_KEY_I_KEY_ID_OFFSET, + MBEDTLS_LMOTS_I_KEY_ID_LEN); + memcpy(ctx->T_1_pub_key, key + PUBLIC_KEY_ROOT_NODE_OFFSET, + MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)); + + ctx->have_public_key = 1; + + return 0; +} + +int mbedtls_lms_export_public_key(const mbedtls_lms_public_t *ctx, + unsigned char *key, + size_t key_size, size_t *key_len) +{ + if (key_size < MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type)) { + return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL; + } + + if (!ctx->have_public_key) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + mbedtls_lms_unsigned_int_to_network_bytes( + ctx->params.type, + MBEDTLS_LMS_TYPE_LEN, key + PUBLIC_KEY_TYPE_OFFSET); + mbedtls_lms_unsigned_int_to_network_bytes(ctx->params.otstype, + MBEDTLS_LMOTS_TYPE_LEN, + key + PUBLIC_KEY_OTSTYPE_OFFSET); + memcpy(key + PUBLIC_KEY_I_KEY_ID_OFFSET, + ctx->params.I_key_identifier, + MBEDTLS_LMOTS_I_KEY_ID_LEN); + memcpy(key +PUBLIC_KEY_ROOT_NODE_OFFSET, + ctx->T_1_pub_key, + MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)); + + if (key_len != NULL) { + *key_len = MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type); + } + + return 0; +} + +int mbedtls_lms_verify(const mbedtls_lms_public_t *ctx, + const unsigned char *msg, size_t msg_size, + const unsigned char *sig, size_t sig_size) +{ + unsigned int q_leaf_identifier; + unsigned char Kc_candidate_ots_pub_key[MBEDTLS_LMOTS_N_HASH_LEN_MAX]; + unsigned char Tc_candidate_root_node[MBEDTLS_LMS_M_NODE_BYTES_MAX]; + unsigned int height; + unsigned int curr_node_id; + unsigned int parent_node_id; + const unsigned char *left_node; + const unsigned char *right_node; + mbedtls_lmots_parameters_t ots_params; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if (!ctx->have_public_key) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + if (ctx->params.type + != MBEDTLS_LMS_SHA256_M32_H10) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + if (ctx->params.otstype + != MBEDTLS_LMOTS_SHA256_N32_W8) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + if (sig_size != MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype)) { + return MBEDTLS_ERR_LMS_VERIFY_FAILED; + } + + if (sig_size < SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) { + return MBEDTLS_ERR_LMS_VERIFY_FAILED; + } + + if (mbedtls_lms_network_bytes_to_unsigned_int(MBEDTLS_LMOTS_TYPE_LEN, + sig + SIG_OTS_SIG_OFFSET + + MBEDTLS_LMOTS_SIG_TYPE_OFFSET) + != MBEDTLS_LMOTS_SHA256_N32_W8) { + return MBEDTLS_ERR_LMS_VERIFY_FAILED; + } + + if (sig_size < SIG_TYPE_OFFSET(ctx->params.otstype) + MBEDTLS_LMS_TYPE_LEN) { + return MBEDTLS_ERR_LMS_VERIFY_FAILED; + } + + if (mbedtls_lms_network_bytes_to_unsigned_int(MBEDTLS_LMS_TYPE_LEN, + sig + SIG_TYPE_OFFSET(ctx->params.otstype)) + != MBEDTLS_LMS_SHA256_M32_H10) { + return MBEDTLS_ERR_LMS_VERIFY_FAILED; + } + + + q_leaf_identifier = mbedtls_lms_network_bytes_to_unsigned_int( + MBEDTLS_LMOTS_Q_LEAF_ID_LEN, sig + SIG_Q_LEAF_ID_OFFSET); + + if (q_leaf_identifier >= MERKLE_TREE_LEAF_NODE_AM(ctx->params.type)) { + return MBEDTLS_ERR_LMS_VERIFY_FAILED; + } + + memcpy(ots_params.I_key_identifier, + ctx->params.I_key_identifier, + MBEDTLS_LMOTS_I_KEY_ID_LEN); + mbedtls_lms_unsigned_int_to_network_bytes(q_leaf_identifier, + MBEDTLS_LMOTS_Q_LEAF_ID_LEN, + ots_params.q_leaf_identifier); + ots_params.type = ctx->params.otstype; + + ret = mbedtls_lmots_calculate_public_key_candidate(&ots_params, + msg, + msg_size, + sig + SIG_OTS_SIG_OFFSET, + MBEDTLS_LMOTS_SIG_LEN(ctx->params.otstype), + Kc_candidate_ots_pub_key, + sizeof(Kc_candidate_ots_pub_key), + NULL); + if (ret != 0) { + return MBEDTLS_ERR_LMS_VERIFY_FAILED; + } + + create_merkle_leaf_value( + &ctx->params, + Kc_candidate_ots_pub_key, + MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + q_leaf_identifier, + Tc_candidate_root_node); + + curr_node_id = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + + q_leaf_identifier; + + for (height = 0; height < MBEDTLS_LMS_H_TREE_HEIGHT(ctx->params.type); + height++) { + parent_node_id = curr_node_id / 2; + + /* Left/right node ordering matters for the hash */ + if (curr_node_id & 1) { + left_node = sig + SIG_PATH_OFFSET(ctx->params.otstype) + + height * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type); + right_node = Tc_candidate_root_node; + } else { + left_node = Tc_candidate_root_node; + right_node = sig + SIG_PATH_OFFSET(ctx->params.otstype) + + height * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type); + } + + create_merkle_internal_value(&ctx->params, left_node, right_node, + parent_node_id, Tc_candidate_root_node); + + curr_node_id /= 2; + } + + if (memcmp(Tc_candidate_root_node, ctx->T_1_pub_key, + MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type))) { + return MBEDTLS_ERR_LMS_VERIFY_FAILED; + } + + return 0; +} + +#if defined(MBEDTLS_LMS_PRIVATE) + +/* Calculate a full Merkle tree based on a private key. This function + * implements RFC8554 section 5.3, and is used to generate a public key (as the + * public key is the root node of the Merkle tree). + * + * ctx The LMS private context, containing a parameter + * set and private key material consisting of both + * public and private OTS. + * + * tree The output tree, which is 2^(H + 1) hash outputs. + * In the case of H=10 we have 2048 tree nodes (of + * which 1024 of them are leaf nodes). Note that + * because the Merkle tree root is 1-indexed, the 0 + * index tree node is never used. + */ +static int calculate_merkle_tree(const mbedtls_lms_private_t *ctx, + unsigned char *tree) +{ + unsigned int priv_key_idx; + unsigned int r_node_idx; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* First create the leaf nodes, in ascending order */ + for (priv_key_idx = 0; + priv_key_idx < MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type); + priv_key_idx++) { + r_node_idx = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + priv_key_idx; + + ret = create_merkle_leaf_value(&ctx->params, + ctx->ots_public_keys[priv_key_idx].public_key, + r_node_idx, + &tree[r_node_idx * MBEDTLS_LMS_M_NODE_BYTES( + ctx->params.type)]); + if (ret != 0) { + return ret; + } + } + + /* Then the internal nodes, in reverse order so that we can guarantee the + * parent has been created */ + for (r_node_idx = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) - 1; + r_node_idx > 0; + r_node_idx--) { + ret = create_merkle_internal_value(&ctx->params, + &tree[(r_node_idx * 2) * + MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)], + &tree[(r_node_idx * 2 + 1) * + MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)], + r_node_idx, + &tree[r_node_idx * + MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)]); + if (ret != 0) { + return ret; + } + } + + return 0; +} + +/* Calculate a path from a leaf node of the Merkle tree to the root of the tree, + * and return the full path. This function implements RFC8554 section 5.4.1, as + * the Merkle path is the main component of an LMS signature. + * + * ctx The LMS private context, containing a parameter + * set and private key material consisting of both + * public and private OTS. + * + * leaf_node_id Which leaf node to calculate the path from. + * + * path The output path, which is H hash outputs. + */ +static int get_merkle_path(mbedtls_lms_private_t *ctx, + unsigned int leaf_node_id, + unsigned char *path) +{ + const size_t node_bytes = MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type); + unsigned int curr_node_id = leaf_node_id; + unsigned int adjacent_node_id; + unsigned char *tree = NULL; + unsigned int height; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + tree = mbedtls_calloc(MERKLE_TREE_NODE_AM(ctx->params.type), + node_bytes); + if (tree == NULL) { + return MBEDTLS_ERR_LMS_ALLOC_FAILED; + } + + ret = calculate_merkle_tree(ctx, tree); + if (ret != 0) { + goto exit; + } + + for (height = 0; height < MBEDTLS_LMS_H_TREE_HEIGHT(ctx->params.type); + height++) { + adjacent_node_id = curr_node_id ^ 1; + + memcpy(&path[height * node_bytes], + &tree[adjacent_node_id * node_bytes], node_bytes); + + curr_node_id >>= 1; + } + + ret = 0; + +exit: + mbedtls_platform_zeroize(tree, node_bytes * + MERKLE_TREE_NODE_AM(ctx->params.type)); + mbedtls_free(tree); + + return ret; +} + +void mbedtls_lms_private_init(mbedtls_lms_private_t *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); +} + +void mbedtls_lms_private_free(mbedtls_lms_private_t *ctx) +{ + unsigned int idx; + + if (ctx->have_private_key) { + if (ctx->ots_private_keys != NULL) { + for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) { + mbedtls_lmots_private_free(&ctx->ots_private_keys[idx]); + } + } + + if (ctx->ots_public_keys != NULL) { + for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) { + mbedtls_lmots_public_free(&ctx->ots_public_keys[idx]); + } + } + + mbedtls_free(ctx->ots_private_keys); + mbedtls_free(ctx->ots_public_keys); + } + + mbedtls_platform_zeroize(ctx, sizeof(*ctx)); +} + + +int mbedtls_lms_generate_private_key(mbedtls_lms_private_t *ctx, + mbedtls_lms_algorithm_type_t type, + mbedtls_lmots_algorithm_type_t otstype, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, const unsigned char *seed, + size_t seed_size) +{ + unsigned int idx = 0; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if (type != MBEDTLS_LMS_SHA256_M32_H10) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + if (otstype != MBEDTLS_LMOTS_SHA256_N32_W8) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + if (ctx->have_private_key) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + ctx->params.type = type; + ctx->params.otstype = otstype; + ctx->have_private_key = 1; + + ret = f_rng(p_rng, + ctx->params.I_key_identifier, + MBEDTLS_LMOTS_I_KEY_ID_LEN); + if (ret != 0) { + goto exit; + } + + /* Requires a cast to size_t to avoid an implicit cast warning on certain + * platforms (particularly Windows) */ + ctx->ots_private_keys = mbedtls_calloc((size_t) MERKLE_TREE_LEAF_NODE_AM(ctx->params.type), + sizeof(*ctx->ots_private_keys)); + if (ctx->ots_private_keys == NULL) { + ret = MBEDTLS_ERR_LMS_ALLOC_FAILED; + goto exit; + } + + /* Requires a cast to size_t to avoid an implicit cast warning on certain + * platforms (particularly Windows) */ + ctx->ots_public_keys = mbedtls_calloc((size_t) MERKLE_TREE_LEAF_NODE_AM(ctx->params.type), + sizeof(*ctx->ots_public_keys)); + if (ctx->ots_public_keys == NULL) { + ret = MBEDTLS_ERR_LMS_ALLOC_FAILED; + goto exit; + } + + for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) { + mbedtls_lmots_private_init(&ctx->ots_private_keys[idx]); + mbedtls_lmots_public_init(&ctx->ots_public_keys[idx]); + } + + + for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) { + ret = mbedtls_lmots_generate_private_key(&ctx->ots_private_keys[idx], + otstype, + ctx->params.I_key_identifier, + idx, seed, seed_size); + if (ret != 0) { + goto exit; + } + + ret = mbedtls_lmots_calculate_public_key(&ctx->ots_public_keys[idx], + &ctx->ots_private_keys[idx]); + if (ret != 0) { + goto exit; + } + } + + ctx->q_next_usable_key = 0; + +exit: + if (ret != 0) { + mbedtls_lms_private_free(ctx); + } + + return ret; +} + +int mbedtls_lms_calculate_public_key(mbedtls_lms_public_t *ctx, + const mbedtls_lms_private_t *priv_ctx) +{ + const size_t node_bytes = MBEDTLS_LMS_M_NODE_BYTES(priv_ctx->params.type); + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *tree = NULL; + + if (!priv_ctx->have_private_key) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + if (priv_ctx->params.type + != MBEDTLS_LMS_SHA256_M32_H10) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + if (priv_ctx->params.otstype + != MBEDTLS_LMOTS_SHA256_N32_W8) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + tree = mbedtls_calloc(MERKLE_TREE_NODE_AM(priv_ctx->params.type), + node_bytes); + if (tree == NULL) { + return MBEDTLS_ERR_LMS_ALLOC_FAILED; + } + + memcpy(&ctx->params, &priv_ctx->params, + sizeof(mbedtls_lmots_parameters_t)); + + ret = calculate_merkle_tree(priv_ctx, tree); + if (ret != 0) { + goto exit; + } + + /* Root node is always at position 1, due to 1-based indexing */ + memcpy(ctx->T_1_pub_key, &tree[node_bytes], node_bytes); + + ctx->have_public_key = 1; + + ret = 0; + +exit: + mbedtls_platform_zeroize(tree, node_bytes * + MERKLE_TREE_NODE_AM(priv_ctx->params.type)); + mbedtls_free(tree); + + return ret; +} + + +int mbedtls_lms_sign(mbedtls_lms_private_t *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, const unsigned char *msg, + unsigned int msg_size, unsigned char *sig, size_t sig_size, + size_t *sig_len) +{ + uint32_t q_leaf_identifier; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if (!ctx->have_private_key) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + if (sig_size < MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype)) { + return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL; + } + + if (ctx->params.type != MBEDTLS_LMS_SHA256_M32_H10) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + if (ctx->params.otstype + != MBEDTLS_LMOTS_SHA256_N32_W8) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + if (ctx->q_next_usable_key >= MERKLE_TREE_LEAF_NODE_AM(ctx->params.type)) { + return MBEDTLS_ERR_LMS_OUT_OF_PRIVATE_KEYS; + } + + + q_leaf_identifier = ctx->q_next_usable_key; + /* This new value must _always_ be written back to the disk before the + * signature is returned. + */ + ctx->q_next_usable_key += 1; + + if (MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype) + < SIG_OTS_SIG_OFFSET) { + return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; + } + + ret = mbedtls_lmots_sign(&ctx->ots_private_keys[q_leaf_identifier], + f_rng, + p_rng, + msg, + msg_size, + sig + SIG_OTS_SIG_OFFSET, + MBEDTLS_LMS_SIG_LEN(ctx->params.type, + ctx->params.otstype) - SIG_OTS_SIG_OFFSET, + NULL); + if (ret != 0) { + return ret; + } + + mbedtls_lms_unsigned_int_to_network_bytes(ctx->params.type, + MBEDTLS_LMS_TYPE_LEN, + sig + SIG_TYPE_OFFSET(ctx->params.otstype)); + mbedtls_lms_unsigned_int_to_network_bytes(q_leaf_identifier, + MBEDTLS_LMOTS_Q_LEAF_ID_LEN, + sig + SIG_Q_LEAF_ID_OFFSET); + + ret = get_merkle_path(ctx, + MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + q_leaf_identifier, + sig + SIG_PATH_OFFSET(ctx->params.otstype)); + if (ret != 0) { + return ret; + } + + if (sig_len != NULL) { + *sig_len = MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype); + } + + + return 0; +} + +#endif /* defined(MBEDTLS_LMS_PRIVATE) */ +#endif /* defined(MBEDTLS_LMS_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..89295de --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/md.c @@ -0,0 +1,973 @@ +/** + * \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" + +/* + * Availability of functions in this module is controlled by two + * feature macros: + * - MBEDTLS_MD_C enables the whole module; + * - MBEDTLS_MD_LIGHT enables only functions for hashing and accessing + * most hash metadata (everything except string names); is it + * automatically set whenever MBEDTLS_MD_C is defined. + * + * In this file, functions from MD_LIGHT are at the top, MD_C at the end. + * + * In the future we may want to change the contract of some functions + * (behaviour with NULL arguments) depending on whether MD_C is defined or + * only MD_LIGHT. Also, the exact scope of MD_LIGHT might vary. + * + * For these reasons, we're keeping MD_LIGHT internal for now. + */ +#if defined(MBEDTLS_MD_LIGHT) + +#include "mbedtls/md.h" +#include "md_wrap.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include "mbedtls/md5.h" +#include "mbedtls/ripemd160.h" +#include "mbedtls/sha1.h" +#include "mbedtls/sha256.h" +#include "mbedtls/sha512.h" + +#if defined(MBEDTLS_MD_SOME_PSA) +#include +#include "psa_crypto_core.h" +#endif + +#include "mbedtls/platform.h" + +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#if defined(MBEDTLS_MD_CAN_MD5) +const mbedtls_md_info_t mbedtls_md5_info = { + "MD5", + MBEDTLS_MD_MD5, + 16, + 64, +}; +#endif + +#if defined(MBEDTLS_MD_CAN_RIPEMD160) +const mbedtls_md_info_t mbedtls_ripemd160_info = { + "RIPEMD160", + MBEDTLS_MD_RIPEMD160, + 20, + 64, +}; +#endif + +#if defined(MBEDTLS_MD_CAN_SHA1) +const mbedtls_md_info_t mbedtls_sha1_info = { + "SHA1", + MBEDTLS_MD_SHA1, + 20, + 64, +}; +#endif + +#if defined(MBEDTLS_MD_CAN_SHA224) +const mbedtls_md_info_t mbedtls_sha224_info = { + "SHA224", + MBEDTLS_MD_SHA224, + 28, + 64, +}; +#endif + +#if defined(MBEDTLS_MD_CAN_SHA256) +const mbedtls_md_info_t mbedtls_sha256_info = { + "SHA256", + MBEDTLS_MD_SHA256, + 32, + 64, +}; +#endif + +#if defined(MBEDTLS_MD_CAN_SHA384) +const mbedtls_md_info_t mbedtls_sha384_info = { + "SHA384", + MBEDTLS_MD_SHA384, + 48, + 128, +}; +#endif + +#if defined(MBEDTLS_MD_CAN_SHA512) +const mbedtls_md_info_t mbedtls_sha512_info = { + "SHA512", + MBEDTLS_MD_SHA512, + 64, + 128, +}; +#endif + +const mbedtls_md_info_t *mbedtls_md_info_from_type(mbedtls_md_type_t md_type) +{ + switch (md_type) { +#if defined(MBEDTLS_MD_CAN_MD5) + case MBEDTLS_MD_MD5: + return &mbedtls_md5_info; +#endif +#if defined(MBEDTLS_MD_CAN_RIPEMD160) + case MBEDTLS_MD_RIPEMD160: + return &mbedtls_ripemd160_info; +#endif +#if defined(MBEDTLS_MD_CAN_SHA1) + case MBEDTLS_MD_SHA1: + return &mbedtls_sha1_info; +#endif +#if defined(MBEDTLS_MD_CAN_SHA224) + case MBEDTLS_MD_SHA224: + return &mbedtls_sha224_info; +#endif +#if defined(MBEDTLS_MD_CAN_SHA256) + case MBEDTLS_MD_SHA256: + return &mbedtls_sha256_info; +#endif +#if defined(MBEDTLS_MD_CAN_SHA384) + case MBEDTLS_MD_SHA384: + return &mbedtls_sha384_info; +#endif +#if defined(MBEDTLS_MD_CAN_SHA512) + case MBEDTLS_MD_SHA512: + return &mbedtls_sha512_info; +#endif + default: + return NULL; + } +} + +#if defined(MBEDTLS_MD_SOME_PSA) +static psa_algorithm_t psa_alg_of_md(const mbedtls_md_info_t *info) +{ + switch (info->type) { +#if defined(MBEDTLS_MD_MD5_VIA_PSA) + case MBEDTLS_MD_MD5: + return PSA_ALG_MD5; +#endif +#if defined(MBEDTLS_MD_RIPEMD160_VIA_PSA) + case MBEDTLS_MD_RIPEMD160: + return PSA_ALG_RIPEMD160; +#endif +#if defined(MBEDTLS_MD_SHA1_VIA_PSA) + case MBEDTLS_MD_SHA1: + return PSA_ALG_SHA_1; +#endif +#if defined(MBEDTLS_MD_SHA224_VIA_PSA) + case MBEDTLS_MD_SHA224: + return PSA_ALG_SHA_224; +#endif +#if defined(MBEDTLS_MD_SHA256_VIA_PSA) + case MBEDTLS_MD_SHA256: + return PSA_ALG_SHA_256; +#endif +#if defined(MBEDTLS_MD_SHA384_VIA_PSA) + case MBEDTLS_MD_SHA384: + return PSA_ALG_SHA_384; +#endif +#if defined(MBEDTLS_MD_SHA512_VIA_PSA) + case MBEDTLS_MD_SHA512: + return PSA_ALG_SHA_512; +#endif + default: + return PSA_ALG_NONE; + } +} + +static int md_can_use_psa(const mbedtls_md_info_t *info) +{ + psa_algorithm_t alg = psa_alg_of_md(info); + if (alg == PSA_ALG_NONE) { + return 0; + } + + return psa_can_do_hash(alg); +} + +static int mbedtls_md_error_from_psa(psa_status_t status) +{ + switch (status) { + case PSA_SUCCESS: + return 0; + case PSA_ERROR_NOT_SUPPORTED: + return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE; + case PSA_ERROR_INSUFFICIENT_MEMORY: + return MBEDTLS_ERR_MD_ALLOC_FAILED; + default: + return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + } +} +#endif /* MBEDTLS_MD_SOME_PSA */ + +void mbedtls_md_init(mbedtls_md_context_t *ctx) +{ + /* Note: this sets engine (if present) to MBEDTLS_MD_ENGINE_LEGACY */ + 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) { +#if defined(MBEDTLS_MD_SOME_PSA) + if (ctx->engine == MBEDTLS_MD_ENGINE_PSA) { + psa_hash_abort(ctx->md_ctx); + } else +#endif + switch (ctx->md_info->type) { +#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_SHA224_C) + case MBEDTLS_MD_SHA224: + mbedtls_sha256_free(ctx->md_ctx); + break; +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA256: + mbedtls_sha256_free(ctx->md_ctx); + break; +#endif +#if defined(MBEDTLS_SHA384_C) + case MBEDTLS_MD_SHA384: + mbedtls_sha512_free(ctx->md_ctx); + break; +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA512: + mbedtls_sha512_free(ctx->md_ctx); + break; +#endif + default: + /* Shouldn't happen */ + break; + } + mbedtls_free(ctx->md_ctx); + } + +#if defined(MBEDTLS_MD_C) + if (ctx->hmac_ctx != NULL) { + mbedtls_platform_zeroize(ctx->hmac_ctx, + 2 * ctx->md_info->block_size); + mbedtls_free(ctx->hmac_ctx); + } +#endif + + 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; + } + +#if defined(MBEDTLS_MD_SOME_PSA) + if (src->engine != dst->engine) { + /* This can happen with src set to legacy because PSA wasn't ready + * yet, and dst to PSA because it became ready in the meantime. + * We currently don't support that case (we'd need to re-allocate + * md_ctx to the size of the appropriate MD context). */ + return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE; + } + + if (src->engine == MBEDTLS_MD_ENGINE_PSA) { + psa_status_t status = psa_hash_clone(src->md_ctx, dst->md_ctx); + return mbedtls_md_error_from_psa(status); + } +#endif + + switch (src->md_info->type) { +#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_SHA224_C) + case MBEDTLS_MD_SHA224: + mbedtls_sha256_clone(dst->md_ctx, src->md_ctx); + break; +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA256: + mbedtls_sha256_clone(dst->md_ctx, src->md_ctx); + break; +#endif +#if defined(MBEDTLS_SHA384_C) + case MBEDTLS_MD_SHA384: + mbedtls_sha512_clone(dst->md_ctx, src->md_ctx); + break; +#endif +#if defined(MBEDTLS_SHA512_C) + 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; +} + +#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; +#if defined(MBEDTLS_MD_C) + ctx->hmac_ctx = NULL; +#else + if (hmac != 0) { + return MBEDTLS_ERR_MD_BAD_INPUT_DATA; + } +#endif + +#if defined(MBEDTLS_MD_SOME_PSA) + if (md_can_use_psa(ctx->md_info)) { + ctx->md_ctx = mbedtls_calloc(1, sizeof(psa_hash_operation_t)); + if (ctx->md_ctx == NULL) { + return MBEDTLS_ERR_MD_ALLOC_FAILED; + } + ctx->engine = MBEDTLS_MD_ENGINE_PSA; + } else +#endif + switch (md_info->type) { +#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_SHA224_C) + case MBEDTLS_MD_SHA224: + ALLOC(sha256); + break; +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA256: + ALLOC(sha256); + break; +#endif +#if defined(MBEDTLS_SHA384_C) + case MBEDTLS_MD_SHA384: + ALLOC(sha512); + break; +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA512: + ALLOC(sha512); + break; +#endif + default: + return MBEDTLS_ERR_MD_BAD_INPUT_DATA; + } + +#if defined(MBEDTLS_MD_C) + 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; + } + } +#endif + + 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; + } + +#if defined(MBEDTLS_MD_SOME_PSA) + if (ctx->engine == MBEDTLS_MD_ENGINE_PSA) { + psa_algorithm_t alg = psa_alg_of_md(ctx->md_info); + psa_hash_abort(ctx->md_ctx); + psa_status_t status = psa_hash_setup(ctx->md_ctx, alg); + return mbedtls_md_error_from_psa(status); + } +#endif + + switch (ctx->md_info->type) { +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return mbedtls_md5_starts(ctx->md_ctx); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return mbedtls_ripemd160_starts(ctx->md_ctx); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return mbedtls_sha1_starts(ctx->md_ctx); +#endif +#if defined(MBEDTLS_SHA224_C) + case MBEDTLS_MD_SHA224: + return mbedtls_sha256_starts(ctx->md_ctx, 1); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA256: + return mbedtls_sha256_starts(ctx->md_ctx, 0); +#endif +#if defined(MBEDTLS_SHA384_C) + case MBEDTLS_MD_SHA384: + return mbedtls_sha512_starts(ctx->md_ctx, 1); +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA512: + return mbedtls_sha512_starts(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; + } + +#if defined(MBEDTLS_MD_SOME_PSA) + if (ctx->engine == MBEDTLS_MD_ENGINE_PSA) { + psa_status_t status = psa_hash_update(ctx->md_ctx, input, ilen); + return mbedtls_md_error_from_psa(status); + } +#endif + + switch (ctx->md_info->type) { +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return mbedtls_md5_update(ctx->md_ctx, input, ilen); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return mbedtls_ripemd160_update(ctx->md_ctx, input, ilen); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return mbedtls_sha1_update(ctx->md_ctx, input, ilen); +#endif +#if defined(MBEDTLS_SHA224_C) + case MBEDTLS_MD_SHA224: + return mbedtls_sha256_update(ctx->md_ctx, input, ilen); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA256: + return mbedtls_sha256_update(ctx->md_ctx, input, ilen); +#endif +#if defined(MBEDTLS_SHA384_C) + case MBEDTLS_MD_SHA384: + return mbedtls_sha512_update(ctx->md_ctx, input, ilen); +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA512: + return mbedtls_sha512_update(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; + } + +#if defined(MBEDTLS_MD_SOME_PSA) + if (ctx->engine == MBEDTLS_MD_ENGINE_PSA) { + size_t size = ctx->md_info->size; + psa_status_t status = psa_hash_finish(ctx->md_ctx, + output, size, &size); + return mbedtls_md_error_from_psa(status); + } +#endif + + switch (ctx->md_info->type) { +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return mbedtls_md5_finish(ctx->md_ctx, output); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return mbedtls_ripemd160_finish(ctx->md_ctx, output); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return mbedtls_sha1_finish(ctx->md_ctx, output); +#endif +#if defined(MBEDTLS_SHA224_C) + case MBEDTLS_MD_SHA224: + return mbedtls_sha256_finish(ctx->md_ctx, output); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA256: + return mbedtls_sha256_finish(ctx->md_ctx, output); +#endif +#if defined(MBEDTLS_SHA384_C) + case MBEDTLS_MD_SHA384: + return mbedtls_sha512_finish(ctx->md_ctx, output); +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA512: + return mbedtls_sha512_finish(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; + } + +#if defined(MBEDTLS_MD_SOME_PSA) + if (md_can_use_psa(md_info)) { + size_t size = md_info->size; + psa_status_t status = psa_hash_compute(psa_alg_of_md(md_info), + input, ilen, + output, size, &size); + return mbedtls_md_error_from_psa(status); + } +#endif + + switch (md_info->type) { +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return mbedtls_md5(input, ilen, output); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return mbedtls_ripemd160(input, ilen, output); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return mbedtls_sha1(input, ilen, output); +#endif +#if defined(MBEDTLS_SHA224_C) + case MBEDTLS_MD_SHA224: + return mbedtls_sha256(input, ilen, output, 1); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA256: + return mbedtls_sha256(input, ilen, output, 0); +#endif +#if defined(MBEDTLS_SHA384_C) + case MBEDTLS_MD_SHA384: + return mbedtls_sha512(input, ilen, output, 1); +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA512: + return mbedtls_sha512(input, ilen, output, 0); +#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; +} + +/************************************************************************ + * Functions above this separator are part of MBEDTLS_MD_LIGHT, * + * functions below are only available when MBEDTLS_MD_C is set. * + ************************************************************************/ +#if defined(MBEDTLS_MD_C) + +/* + * Reminder: update profiles in x509_crt.c when adding a new hash! + */ +static const int supported_digests[] = { + +#if defined(MBEDTLS_MD_CAN_SHA512) + MBEDTLS_MD_SHA512, +#endif + +#if defined(MBEDTLS_MD_CAN_SHA384) + MBEDTLS_MD_SHA384, +#endif + +#if defined(MBEDTLS_MD_CAN_SHA256) + MBEDTLS_MD_SHA256, +#endif +#if defined(MBEDTLS_MD_CAN_SHA224) + MBEDTLS_MD_SHA224, +#endif + +#if defined(MBEDTLS_MD_CAN_SHA1) + MBEDTLS_MD_SHA1, +#endif + +#if defined(MBEDTLS_MD_CAN_RIPEMD160) + MBEDTLS_MD_RIPEMD160, +#endif + +#if defined(MBEDTLS_MD_CAN_MD5) + MBEDTLS_MD_MD5, +#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_MD_CAN_MD5) + if (!strcmp("MD5", md_name)) { + return mbedtls_md_info_from_type(MBEDTLS_MD_MD5); + } +#endif +#if defined(MBEDTLS_MD_CAN_RIPEMD160) + if (!strcmp("RIPEMD160", md_name)) { + return mbedtls_md_info_from_type(MBEDTLS_MD_RIPEMD160); + } +#endif +#if defined(MBEDTLS_MD_CAN_SHA1) + if (!strcmp("SHA1", md_name) || !strcmp("SHA", md_name)) { + return mbedtls_md_info_from_type(MBEDTLS_MD_SHA1); + } +#endif +#if defined(MBEDTLS_MD_CAN_SHA224) + if (!strcmp("SHA224", md_name)) { + return mbedtls_md_info_from_type(MBEDTLS_MD_SHA224); + } +#endif +#if defined(MBEDTLS_MD_CAN_SHA256) + if (!strcmp("SHA256", md_name)) { + return mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); + } +#endif +#if defined(MBEDTLS_MD_CAN_SHA384) + if (!strcmp("SHA384", md_name)) { + return mbedtls_md_info_from_type(MBEDTLS_MD_SHA384); + } +#endif +#if defined(MBEDTLS_MD_CAN_SHA512) + 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_ctx( + const mbedtls_md_context_t *ctx) +{ + if (ctx == NULL) { + return NULL; + } + + return ctx->MBEDTLS_PRIVATE(md_info); +} + +#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; + } + + /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ + mbedtls_setbuf(f, NULL); + + 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; + + 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); + + mbedtls_xor(ipad, ipad, key, keylen); + mbedtls_xor(opad, opad, key, keylen); + + 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; +} + +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 */ + +#endif /* MBEDTLS_MD_LIGHT */ 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..138a320 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/md5.c @@ -0,0 +1,434 @@ +/* + * 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 + +#include "mbedtls/platform.h" + +#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(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_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; +} + +#endif /* !MBEDTLS_MD5_PROCESS_ALT */ + +/* + * MD5 process buffer + */ +int mbedtls_md5_update(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; +} + +/* + * MD5 final digest + */ +int mbedtls_md5_finish(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; +} + +#endif /* !MBEDTLS_MD5_ALT */ + +/* + * output = MD5( input buffer ) + */ +int mbedtls_md5(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(&ctx)) != 0) { + goto exit; + } + + if ((ret = mbedtls_md5_update(&ctx, input, ilen)) != 0) { + goto exit; + } + + if ((ret = mbedtls_md5_finish(&ctx, output)) != 0) { + goto exit; + } + +exit: + mbedtls_md5_free(&ctx); + + return ret; +} + +#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(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/md_wrap.h b/optee/optee_os/lib/libmbedtls/mbedtls/library/md_wrap.h new file mode 100644 index 0000000..cd539b5 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/md_wrap.h @@ -0,0 +1,81 @@ +/** + * \file md_wrap.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 + +#include "mbedtls/build_info.h" + +#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_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_SHA224_C) +extern const mbedtls_md_info_t mbedtls_sha224_info; +#endif +#if defined(MBEDTLS_SHA256_C) +extern const mbedtls_md_info_t mbedtls_sha256_info; +#endif +#if defined(MBEDTLS_SHA384_C) +extern const mbedtls_md_info_t mbedtls_sha384_info; +#endif +#if defined(MBEDTLS_SHA512_C) +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/library/memory_buffer_alloc.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/memory_buffer_alloc.c new file mode 100644 index 0000000..e5052ce --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/memory_buffer_alloc.c @@ -0,0 +1,757 @@ +/* + * 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_count_get(size_t *alloc_count, size_t *free_count) +{ + *alloc_count = heap.alloc_count; + *free_count = heap.free_count; +} + +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..e63d08b --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/net_sockets.c @@ -0,0 +1,712 @@ +/* + * 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 mbedtls_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 mbedtls_config.h" +#endif + +#include "mbedtls/platform.h" + +#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..5817bf4 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/nist_kw.c @@ -0,0 +1,687 @@ +/* + * 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 + +#include "mbedtls/platform.h" + +#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..63b3df3 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/oid.c @@ -0,0 +1,885 @@ +/** + * \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 "mbedtls/pk.h" + +#include "mbedtls/legacy_or_psa.h" + +#include +#include + +#include "mbedtls/platform.h" + +/* + * Macro to automatically add the size of #define'd OIDs + */ +#define ADD_LEN(s) s, MBEDTLS_OID_SIZE(s) + +/* + * Macro to generate mbedtls_oid_descriptor_t + */ +#if !defined(MBEDTLS_X509_REMOVE_INFO) +#define OID_DESCRIPTOR(s, name, description) { ADD_LEN(s), name, description } +#define NULL_OID_DESCRIPTOR { NULL, 0, NULL, NULL } +#else +#define OID_DESCRIPTOR(s, name, description) { ADD_LEN(s) } +#define NULL_OID_DESCRIPTOR { NULL, 0 } +#endif + +/* + * 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; \ + } + +#if !defined(MBEDTLS_X509_REMOVE_INFO) +/* + * 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; \ + } +#endif /* MBEDTLS_X509_REMOVE_INFO */ + +/* + * 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[] = +{ + { + OID_DESCRIPTOR(MBEDTLS_OID_AT_CN, "id-at-commonName", "Common Name"), + "CN", + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_AT_COUNTRY, "id-at-countryName", "Country"), + "C", + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_AT_LOCALITY, "id-at-locality", "Locality"), + "L", + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_AT_STATE, "id-at-state", "State"), + "ST", + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_AT_ORGANIZATION, "id-at-organizationName", + "Organization"), + "O", + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_AT_ORG_UNIT, "id-at-organizationalUnitName", "Org Unit"), + "OU", + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_PKCS9_EMAIL, + "emailAddress", + "E-mail address"), + "emailAddress", + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_AT_SERIAL_NUMBER, + "id-at-serialNumber", + "Serial number"), + "serialNumber", + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_AT_POSTAL_ADDRESS, + "id-at-postalAddress", + "Postal address"), + "postalAddress", + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_AT_POSTAL_CODE, "id-at-postalCode", "Postal code"), + "postalCode", + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_AT_SUR_NAME, "id-at-surName", "Surname"), + "SN", + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_AT_GIVEN_NAME, "id-at-givenName", "Given name"), + "GN", + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_AT_INITIALS, "id-at-initials", "Initials"), + "initials", + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_AT_GENERATION_QUALIFIER, + "id-at-generationQualifier", + "Generation qualifier"), + "generationQualifier", + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_AT_TITLE, "id-at-title", "Title"), + "title", + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_AT_DN_QUALIFIER, + "id-at-dnQualifier", + "Distinguished Name qualifier"), + "dnQualifier", + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_AT_PSEUDONYM, "id-at-pseudonym", "Pseudonym"), + "pseudonym", + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_UID, "id-uid", "User Id"), + "uid", + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_DOMAIN_COMPONENT, + "id-domainComponent", + "Domain component"), + "DC", + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_AT_UNIQUE_IDENTIFIER, + "id-at-uniqueIdentifier", + "Unique Identifier"), + "uniqueIdentifier", + }, + { + NULL_OID_DESCRIPTOR, + 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[] = +{ + { + OID_DESCRIPTOR(MBEDTLS_OID_BASIC_CONSTRAINTS, + "id-ce-basicConstraints", + "Basic Constraints"), + MBEDTLS_OID_X509_EXT_BASIC_CONSTRAINTS, + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_KEY_USAGE, "id-ce-keyUsage", "Key Usage"), + MBEDTLS_OID_X509_EXT_KEY_USAGE, + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_EXTENDED_KEY_USAGE, + "id-ce-extKeyUsage", + "Extended Key Usage"), + MBEDTLS_OID_X509_EXT_EXTENDED_KEY_USAGE, + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_SUBJECT_ALT_NAME, + "id-ce-subjectAltName", + "Subject Alt Name"), + MBEDTLS_OID_X509_EXT_SUBJECT_ALT_NAME, + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_NS_CERT_TYPE, + "id-netscape-certtype", + "Netscape Certificate Type"), + MBEDTLS_OID_X509_EXT_NS_CERT_TYPE, + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_CERTIFICATE_POLICIES, + "id-ce-certificatePolicies", + "Certificate Policies"), + MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES, + }, + { + NULL_OID_DESCRIPTOR, + 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) + +#if !defined(MBEDTLS_X509_REMOVE_INFO) +static const mbedtls_oid_descriptor_t oid_ext_key_usage[] = +{ + OID_DESCRIPTOR(MBEDTLS_OID_SERVER_AUTH, + "id-kp-serverAuth", + "TLS Web Server Authentication"), + OID_DESCRIPTOR(MBEDTLS_OID_CLIENT_AUTH, + "id-kp-clientAuth", + "TLS Web Client Authentication"), + OID_DESCRIPTOR(MBEDTLS_OID_CODE_SIGNING, "id-kp-codeSigning", "Code Signing"), + OID_DESCRIPTOR(MBEDTLS_OID_EMAIL_PROTECTION, "id-kp-emailProtection", "E-mail Protection"), + OID_DESCRIPTOR(MBEDTLS_OID_TIME_STAMPING, "id-kp-timeStamping", "Time Stamping"), + OID_DESCRIPTOR(MBEDTLS_OID_OCSP_SIGNING, "id-kp-OCSPSigning", "OCSP Signing"), + OID_DESCRIPTOR(MBEDTLS_OID_WISUN_FAN, + "id-kp-wisun-fan-device", + "Wi-SUN Alliance Field Area Network (FAN)"), + NULL_OID_DESCRIPTOR, +}; + +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[] = +{ + OID_DESCRIPTOR(MBEDTLS_OID_ANY_POLICY, "anyPolicy", "Any Policy"), + NULL_OID_DESCRIPTOR, +}; + +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) +#endif /* MBEDTLS_X509_REMOVE_INFO */ + +/* + * 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_HAS_ALG_MD5_VIA_LOWLEVEL_OR_PSA) + { + OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_MD5, "md5WithRSAEncryption", "RSA with MD5"), + MBEDTLS_MD_MD5, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_HAS_ALG_MD5_VIA_LOWLEVEL_OR_PSA */ +#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA) + { + OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA1, "sha-1WithRSAEncryption", "RSA with SHA1"), + MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA */ +#if defined(MBEDTLS_HAS_ALG_SHA_224_VIA_LOWLEVEL_OR_PSA) + { + OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA224, "sha224WithRSAEncryption", + "RSA with SHA-224"), + MBEDTLS_MD_SHA224, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_HAS_ALG_SHA_224_VIA_LOWLEVEL_OR_PSA */ +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_LOWLEVEL_OR_PSA) + { + OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA256, "sha256WithRSAEncryption", + "RSA with SHA-256"), + MBEDTLS_MD_SHA256, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_LOWLEVEL_OR_PSA */ +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_LOWLEVEL_OR_PSA) + { + OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA384, "sha384WithRSAEncryption", + "RSA with SHA-384"), + MBEDTLS_MD_SHA384, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_LOWLEVEL_OR_PSA */ +#if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_LOWLEVEL_OR_PSA) + { + OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA512, "sha512WithRSAEncryption", + "RSA with SHA-512"), + MBEDTLS_MD_SHA512, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_HAS_ALG_SHA_512_VIA_LOWLEVEL_OR_PSA */ +#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA) + { + OID_DESCRIPTOR(MBEDTLS_OID_RSA_SHA_OBS, "sha-1WithRSAEncryption", "RSA with SHA1"), + MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA */ +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_PK_CAN_ECDSA_SOME) +#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA) + { + OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA1, "ecdsa-with-SHA1", "ECDSA with SHA1"), + MBEDTLS_MD_SHA1, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA */ +#if defined(MBEDTLS_HAS_ALG_SHA_224_VIA_LOWLEVEL_OR_PSA) + { + OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA224, "ecdsa-with-SHA224", "ECDSA with SHA224"), + MBEDTLS_MD_SHA224, MBEDTLS_PK_ECDSA, + }, +#endif +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_LOWLEVEL_OR_PSA) + { + OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA256, "ecdsa-with-SHA256", "ECDSA with SHA256"), + MBEDTLS_MD_SHA256, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_LOWLEVEL_OR_PSA */ +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_LOWLEVEL_OR_PSA) + { + OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA384, "ecdsa-with-SHA384", "ECDSA with SHA384"), + MBEDTLS_MD_SHA384, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_LOWLEVEL_OR_PSA */ +#if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_LOWLEVEL_OR_PSA) + { + OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA512, "ecdsa-with-SHA512", "ECDSA with SHA512"), + MBEDTLS_MD_SHA512, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_HAS_ALG_SHA_512_VIA_LOWLEVEL_OR_PSA */ +#endif /* MBEDTLS_PK_CAN_ECDSA_SOME */ +#if defined(MBEDTLS_RSA_C) + { + OID_DESCRIPTOR(MBEDTLS_OID_RSASSA_PSS, "RSASSA-PSS", "RSASSA-PSS"), + MBEDTLS_MD_NONE, MBEDTLS_PK_RSASSA_PSS, + }, +#endif /* MBEDTLS_RSA_C */ + { + NULL_OID_DESCRIPTOR, + MBEDTLS_MD_NONE, MBEDTLS_PK_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_sig_alg_t, sig_alg, oid_sig_alg) + +#if !defined(MBEDTLS_X509_REMOVE_INFO) +FN_OID_GET_DESCRIPTOR_ATTR1(mbedtls_oid_get_sig_alg_desc, + oid_sig_alg_t, + sig_alg, + const char *, + description) +#endif + +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) + +/* + * 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[] = +{ + { + OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_RSA, "rsaEncryption", "RSA"), + MBEDTLS_PK_RSA, + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_EC_ALG_UNRESTRICTED, "id-ecPublicKey", "Generic EC key"), + MBEDTLS_PK_ECKEY, + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_EC_ALG_ECDH, "id-ecDH", "EC key for ECDH"), + MBEDTLS_PK_ECKEY_DH, + }, + { + NULL_OID_DESCRIPTOR, + 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) + { + OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP192R1, "secp192r1", "secp192r1"), + MBEDTLS_ECP_DP_SECP192R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + { + OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP224R1, "secp224r1", "secp224r1"), + MBEDTLS_ECP_DP_SECP224R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + { + OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP256R1, "secp256r1", "secp256r1"), + MBEDTLS_ECP_DP_SECP256R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + { + OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP384R1, "secp384r1", "secp384r1"), + MBEDTLS_ECP_DP_SECP384R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + { + OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP521R1, "secp521r1", "secp521r1"), + MBEDTLS_ECP_DP_SECP521R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + { + OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP192K1, "secp192k1", "secp192k1"), + MBEDTLS_ECP_DP_SECP192K1, + }, +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + { + OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP224K1, "secp224k1", "secp224k1"), + MBEDTLS_ECP_DP_SECP224K1, + }, +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + { + OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP256K1, "secp256k1", "secp256k1"), + MBEDTLS_ECP_DP_SECP256K1, + }, +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + { + OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_BP256R1, "brainpoolP256r1", "brainpool256r1"), + MBEDTLS_ECP_DP_BP256R1, + }, +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + { + OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_BP384R1, "brainpoolP384r1", "brainpool384r1"), + MBEDTLS_ECP_DP_BP384R1, + }, +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + { + OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_BP512R1, "brainpoolP512r1", "brainpool512r1"), + MBEDTLS_ECP_DP_BP512R1, + }, +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + { + NULL_OID_DESCRIPTOR, + 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[] = +{ + { + OID_DESCRIPTOR(MBEDTLS_OID_DES_CBC, "desCBC", "DES-CBC"), + MBEDTLS_CIPHER_DES_CBC, + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_DES_EDE3_CBC, "des-ede3-cbc", "DES-EDE3-CBC"), + MBEDTLS_CIPHER_DES_EDE3_CBC, + }, + { + NULL_OID_DESCRIPTOR, + 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 */ + +/* + * 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_HAS_ALG_MD5_VIA_LOWLEVEL_OR_PSA) + { + OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_MD5, "id-md5", "MD5"), + MBEDTLS_MD_MD5, + }, +#endif +#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA) + { + OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA1, "id-sha1", "SHA-1"), + MBEDTLS_MD_SHA1, + }, +#endif +#if defined(MBEDTLS_HAS_ALG_SHA_224_VIA_LOWLEVEL_OR_PSA) + { + OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA224, "id-sha224", "SHA-224"), + MBEDTLS_MD_SHA224, + }, +#endif +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_LOWLEVEL_OR_PSA) + { + OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA256, "id-sha256", "SHA-256"), + MBEDTLS_MD_SHA256, + }, +#endif +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_LOWLEVEL_OR_PSA) + { + OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA384, "id-sha384", "SHA-384"), + MBEDTLS_MD_SHA384, + }, +#endif +#if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_LOWLEVEL_OR_PSA) + { + OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA512, "id-sha512", "SHA-512"), + MBEDTLS_MD_SHA512, + }, +#endif +#if defined(MBEDTLS_HAS_ALG_RIPEMD160_VIA_LOWLEVEL_OR_PSA) + { + OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_RIPEMD160, "id-ripemd160", "RIPEMD-160"), + MBEDTLS_MD_RIPEMD160, + }, +#endif + { + NULL_OID_DESCRIPTOR, + 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_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA) + { + OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA1, "hmacSHA1", "HMAC-SHA-1"), + MBEDTLS_MD_SHA1, + }, +#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA */ +#if defined(MBEDTLS_HAS_ALG_SHA_224_VIA_LOWLEVEL_OR_PSA) + { + OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA224, "hmacSHA224", "HMAC-SHA-224"), + MBEDTLS_MD_SHA224, + }, +#endif +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_LOWLEVEL_OR_PSA) + { + OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA256, "hmacSHA256", "HMAC-SHA-256"), + MBEDTLS_MD_SHA256, + }, +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_LOWLEVEL_OR_PSA */ +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_LOWLEVEL_OR_PSA) + { + OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA384, "hmacSHA384", "HMAC-SHA-384"), + MBEDTLS_MD_SHA384, + }, +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_LOWLEVEL_OR_PSA */ +#if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_LOWLEVEL_OR_PSA) + { + OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA512, "hmacSHA512", "HMAC-SHA-512"), + MBEDTLS_MD_SHA512, + }, +#endif /* MBEDTLS_HAS_ALG_SHA_512_VIA_LOWLEVEL_OR_PSA */ + { + NULL_OID_DESCRIPTOR, + 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) + +#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[] = +{ + { + OID_DESCRIPTOR(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, + }, + { + OID_DESCRIPTOR(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_OID_DESCRIPTOR, + 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 */ + +/* 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; + char *p = buf; + size_t n = size; + unsigned int value = 0; + + if (size > INT_MAX) { + /* Avoid overflow computing return value */ + return MBEDTLS_ERR_ASN1_INVALID_LENGTH; + } + + if (oid->len <= 0) { + /* OID must not be empty */ + return MBEDTLS_ERR_ASN1_OUT_OF_DATA; + } + + for (size_t i = 0; i < oid->len; i++) { + /* Prevent overflow in value. */ + if (value > (UINT_MAX >> 7)) { + return MBEDTLS_ERR_ASN1_INVALID_DATA; + } + if ((value == 0) && ((oid->p[i]) == 0x80)) { + /* Overlong encoding is not allowed */ + return MBEDTLS_ERR_ASN1_INVALID_DATA; + } + + value <<= 7; + value |= oid->p[i] & 0x7F; + + if (!(oid->p[i] & 0x80)) { + /* Last byte */ + if (n == size) { + int component1; + unsigned int component2; + /* First subidentifier contains first two OID components */ + if (value >= 80) { + component1 = '2'; + component2 = value - 80; + } else if (value >= 40) { + component1 = '1'; + component2 = value - 40; + } else { + component1 = '0'; + component2 = value; + } + ret = mbedtls_snprintf(p, n, "%c.%u", component1, component2); + } else { + ret = mbedtls_snprintf(p, n, ".%u", value); + } + if (ret < 2 || (size_t) ret >= n) { + return MBEDTLS_ERR_OID_BUF_TOO_SMALL; + } + n -= (size_t) ret; + p += ret; + value = 0; + } + } + + if (value != 0) { + /* Unterminated subidentifier */ + return MBEDTLS_ERR_ASN1_OUT_OF_DATA; + } + + 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..f42c40f --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/padlock.c @@ -0,0 +1,167 @@ +/* + * 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 "padlock.h" + +#include + +#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->buf + ctx->rk_offset; + + if (((long) rk & 15) != 0) { + return MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED; + } + + 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]; + + rk = ctx->buf + ctx->rk_offset; + + if (((long) input & 15) != 0 || + ((long) output & 15) != 0 || + ((long) rk & 15) != 0) { + return MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED; + } + + 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/padlock.h b/optee/optee_os/lib/libmbedtls/mbedtls/library/padlock.h new file mode 100644 index 0000000..b5f0d7d --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/padlock.h @@ -0,0 +1,120 @@ +/** + * \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 + +#include "mbedtls/build_info.h" + +#include "mbedtls/aes.h" + +#define MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED -0x0030 /**< Input data should be aligned. */ + +#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/library/pem.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/pem.c new file mode 100644 index 0000000..84bbb3d --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/pem.c @@ -0,0 +1,633 @@ +/* + * 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/md.h" +#include "mbedtls/cipher.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" +#include "hash_info.h" + +#include + +#include "mbedtls/platform.h" + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#endif + +#if !defined(MBEDTLS_MD5_C) +#include "mbedtls/psa_util.h" +#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \ + psa_to_md_errors, \ + psa_generic_status_to_mbedtls) +#endif + +#include "mbedtls/legacy_or_psa.h" + +#if defined(MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \ + defined(MBEDTLS_CIPHER_MODE_CBC) && \ + (defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C)) +#define PEM_RFC1421 +#endif /* MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA && + MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + +#if defined(MBEDTLS_PEM_PARSE_C) +void mbedtls_pem_init(mbedtls_pem_context *ctx) +{ + memset(ctx, 0, sizeof(mbedtls_pem_context)); +} + +#if defined(PEM_RFC1421) +/* + * 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; +} + +#if defined(MBEDTLS_MD5_C) +static int pem_pbkdf1(unsigned char *key, size_t keylen, + unsigned char *iv, + const unsigned char *pwd, size_t pwdlen) +{ + mbedtls_md_context_t md5_ctx; + const mbedtls_md_info_t *md5_info; + unsigned char md5sum[16]; + size_t use_len; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_md_init(&md5_ctx); + + /* Prepare the context. (setup() errors gracefully on NULL info.) */ + md5_info = mbedtls_md_info_from_type(MBEDTLS_MD_MD5); + if ((ret = mbedtls_md_setup(&md5_ctx, md5_info, 0)) != 0) { + goto exit; + } + + /* + * key[ 0..15] = MD5(pwd || IV) + */ + if ((ret = mbedtls_md_starts(&md5_ctx)) != 0) { + goto exit; + } + if ((ret = mbedtls_md_update(&md5_ctx, pwd, pwdlen)) != 0) { + goto exit; + } + if ((ret = mbedtls_md_update(&md5_ctx, iv, 8)) != 0) { + goto exit; + } + if ((ret = mbedtls_md_finish(&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_md_starts(&md5_ctx)) != 0) { + goto exit; + } + if ((ret = mbedtls_md_update(&md5_ctx, md5sum, 16)) != 0) { + goto exit; + } + if ((ret = mbedtls_md_update(&md5_ctx, pwd, pwdlen)) != 0) { + goto exit; + } + if ((ret = mbedtls_md_update(&md5_ctx, iv, 8)) != 0) { + goto exit; + } + if ((ret = mbedtls_md_finish(&md5_ctx, md5sum)) != 0) { + goto exit; + } + + use_len = 16; + if (keylen < 32) { + use_len = keylen - 16; + } + + memcpy(key + 16, md5sum, use_len); + +exit: + mbedtls_md_free(&md5_ctx); + mbedtls_platform_zeroize(md5sum, 16); + + return ret; +} +#else +static int pem_pbkdf1(unsigned char *key, size_t keylen, + unsigned char *iv, + const unsigned char *pwd, size_t pwdlen) +{ + unsigned char md5sum[16]; + psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; + size_t output_length = 0; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + + if ((status = psa_hash_setup(&operation, PSA_ALG_MD5)) != PSA_SUCCESS) { + goto exit; + } + + if ((status = psa_hash_update(&operation, pwd, pwdlen)) != PSA_SUCCESS) { + goto exit; + } + + if ((status = psa_hash_update(&operation, iv, 8)) != PSA_SUCCESS) { + goto exit; + } + + if ((status = psa_hash_finish(&operation, md5sum, + PSA_HASH_LENGTH(PSA_ALG_MD5), + &output_length)) != PSA_SUCCESS) { + goto exit; + } + + if ((status = psa_hash_abort(&operation)) != PSA_SUCCESS) { + goto exit; + } + + /* + * key[ 0..15] = MD5(pwd || IV) + */ + if (keylen <= 16) { + memcpy(key, md5sum, keylen); + goto exit; + } + + memcpy(key, md5sum, 16); + + /* + * key[16..23] = MD5(key[ 0..15] || pwd || IV]) + */ + if ((status = psa_hash_setup(&operation, PSA_ALG_MD5)) != PSA_SUCCESS) { + goto exit; + } + + if ((status = psa_hash_update(&operation, md5sum, 16)) != PSA_SUCCESS) { + goto exit; + } + + if ((status = psa_hash_update(&operation, pwd, pwdlen)) != PSA_SUCCESS) { + goto exit; + } + + if ((status = psa_hash_update(&operation, iv, 8)) != PSA_SUCCESS) { + goto exit; + } + + if ((status = psa_hash_finish(&operation, md5sum, + PSA_HASH_LENGTH(PSA_ALG_MD5), + &output_length)) != PSA_SUCCESS) { + goto exit; + } + + if ((status = psa_hash_abort(&operation)) != PSA_SUCCESS) { + goto exit; + } + + size_t use_len = 16; + if (keylen < 32) { + use_len = keylen - 16; + } + + memcpy(key + 16, md5sum, use_len); + +exit: + mbedtls_platform_zeroize(md5sum, 16); + + return PSA_TO_MBEDTLS_ERR(status); +} +#endif /* MBEDTLS_MD5_C */ + +#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 /* PEM_RFC1421 */ + +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(PEM_RFC1421) + unsigned char pem_iv[16]; + mbedtls_cipher_type_t enc_alg = MBEDTLS_CIPHER_NONE; +#else + ((void) pwd); + ((void) pwdlen); +#endif /* PEM_RFC1421 */ + + 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(PEM_RFC1421) + 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 /* PEM_RFC1421 */ + } + + 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(PEM_RFC1421) + 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 /* PEM_RFC1421 */ + } + + 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..5e18ad2 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/pk.c @@ -0,0 +1,960 @@ +/* + * 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 "pk_wrap.h" +#include "pkwrite.h" + +#include "hash_info.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_PSA_CRYPTO_C) +#include "mbedtls/psa_util.h" +#define PSA_PK_TO_MBEDTLS_ERR(status) psa_pk_status_to_mbedtls(status) +#define PSA_PK_RSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \ + psa_to_pk_rsa_errors, \ + psa_pk_status_to_mbedtls) +#define PSA_PK_ECDSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \ + psa_to_pk_ecdsa_errors, \ + psa_pk_status_to_mbedtls) +#endif + +#include +#include + +/* + * Initialise a mbedtls_pk_context + */ +void mbedtls_pk_init(mbedtls_pk_context *ctx) +{ + 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) +{ + 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_PK_CAN_ECDSA_SOME) + 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) +{ + 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 mbedtls_svc_key_id_t key) +{ + const mbedtls_pk_info_t *info = NULL; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + mbedtls_svc_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); + + if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type)) { + info = &mbedtls_pk_ecdsa_opaque_info; + } else if (type == PSA_KEY_TYPE_RSA_KEY_PAIR) { + info = &mbedtls_pk_rsa_opaque_info; + } else { + 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 = (mbedtls_svc_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; + + 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); +} + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/* + * Tell if a PK can do the operations of the given PSA algorithm + */ +int mbedtls_pk_can_do_ext(const mbedtls_pk_context *ctx, psa_algorithm_t alg, + psa_key_usage_t usage) +{ + psa_key_usage_t key_usage; + + /* 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; + } + + /* Filter out non allowed algorithms */ + if (PSA_ALG_IS_ECDSA(alg) == 0 && + PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) == 0 && + PSA_ALG_IS_RSA_PSS(alg) == 0 && + alg != PSA_ALG_RSA_PKCS1V15_CRYPT && + PSA_ALG_IS_ECDH(alg) == 0) { + return 0; + } + + /* Filter out non allowed usage flags */ + if (usage == 0 || + (usage & ~(PSA_KEY_USAGE_SIGN_HASH | + PSA_KEY_USAGE_DECRYPT | + PSA_KEY_USAGE_DERIVE)) != 0) { + return 0; + } + + /* Wildcard hash is not allowed */ + if (PSA_ALG_IS_SIGN_HASH(alg) && + PSA_ALG_SIGN_GET_HASH(alg) == PSA_ALG_ANY_HASH) { + return 0; + } + + if (mbedtls_pk_get_type(ctx) != MBEDTLS_PK_OPAQUE) { + mbedtls_pk_type_t type; + + if (PSA_ALG_IS_ECDSA(alg) || PSA_ALG_IS_ECDH(alg)) { + type = MBEDTLS_PK_ECKEY; + } else if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || + alg == PSA_ALG_RSA_PKCS1V15_CRYPT) { + type = MBEDTLS_PK_RSA; + } else if (PSA_ALG_IS_RSA_PSS(alg)) { + type = MBEDTLS_PK_RSASSA_PSS; + } else { + return 0; + } + + if (ctx->pk_info->can_do(type) == 0) { + return 0; + } + + switch (type) { + case MBEDTLS_PK_ECKEY: + key_usage = PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_DERIVE; + break; + case MBEDTLS_PK_RSA: + case MBEDTLS_PK_RSASSA_PSS: + key_usage = PSA_KEY_USAGE_SIGN_HASH | + PSA_KEY_USAGE_SIGN_MESSAGE | + PSA_KEY_USAGE_DECRYPT; + break; + default: + /* Should never happen */ + return 0; + } + + return (key_usage & usage) == usage; + } + + const mbedtls_svc_key_id_t *key = (const mbedtls_svc_key_id_t *) ctx->pk_ctx; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_algorithm_t key_alg, key_alg2; + psa_status_t status; + + status = psa_get_key_attributes(*key, &attributes); + if (status != PSA_SUCCESS) { + return 0; + } + + key_alg = psa_get_key_algorithm(&attributes); + key_alg2 = psa_get_key_enrollment_algorithm(&attributes); + key_usage = psa_get_key_usage_flags(&attributes); + psa_reset_key_attributes(&attributes); + + if ((key_usage & usage) != usage) { + return 0; + } + + /* + * Common case: the key alg or alg2 only allows alg. + * This will match PSA_ALG_RSA_PKCS1V15_CRYPT & PSA_ALG_IS_ECDH + * directly. + * This would also match ECDSA/RSA_PKCS1V15_SIGN/RSA_PSS with + * a fixed hash on key_alg/key_alg2. + */ + if (alg == key_alg || alg == key_alg2) { + return 1; + } + + /* + * If key_alg or key_alg2 is a hash-and-sign with a wildcard for the hash, + * and alg is the same hash-and-sign family with any hash, + * then alg is compliant with this key alg + */ + if (PSA_ALG_IS_SIGN_HASH(alg)) { + + if (PSA_ALG_IS_SIGN_HASH(key_alg) && + PSA_ALG_SIGN_GET_HASH(key_alg) == PSA_ALG_ANY_HASH && + (alg & ~PSA_ALG_HASH_MASK) == (key_alg & ~PSA_ALG_HASH_MASK)) { + return 1; + } + + if (PSA_ALG_IS_SIGN_HASH(key_alg2) && + PSA_ALG_SIGN_GET_HASH(key_alg2) == PSA_ALG_ANY_HASH && + (alg & ~PSA_ALG_HASH_MASK) == (key_alg2 & ~PSA_ALG_HASH_MASK)) { + return 1; + } + } + + return 0; +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +/* + * 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) +{ + if (*hash_len != 0) { + return 0; + } + + *hash_len = mbedtls_hash_info_get_size(md_alg); + + if (*hash_len == 0) { + return -1; + } + + 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) +{ + if ((md_alg != MBEDTLS_MD_NONE || hash_len != 0) && hash == NULL) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + 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) +{ + if ((md_alg != MBEDTLS_MD_NONE || hash_len != 0) && hash == NULL) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + 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) { + /* 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); + } + +#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 (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + if (options == NULL) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + pss_opts = (const mbedtls_pk_rsassa_pss_options *) options; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if (pss_opts->mgf1_hash_id == md_alg) { + unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES]; + unsigned char *p; + int key_len; + size_t signature_length; + psa_status_t status = PSA_ERROR_DATA_CORRUPT; + psa_status_t destruction_status = PSA_ERROR_DATA_CORRUPT; + + psa_algorithm_t psa_md_alg = mbedtls_hash_info_psa_from_md(md_alg); + mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_algorithm_t psa_sig_alg = PSA_ALG_RSA_PSS_ANY_SALT(psa_md_alg); + p = buf + sizeof(buf); + key_len = mbedtls_pk_write_pubkey(&p, buf, ctx); + + if (key_len < 0) { + return key_len; + } + + psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_PUBLIC_KEY); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH); + psa_set_key_algorithm(&attributes, psa_sig_alg); + + status = psa_import_key(&attributes, + buf + sizeof(buf) - key_len, key_len, + &key_id); + if (status != PSA_SUCCESS) { + psa_destroy_key(key_id); + return PSA_PK_TO_MBEDTLS_ERR(status); + } + + /* This function requires returning MBEDTLS_ERR_PK_SIG_LEN_MISMATCH + * on a valid signature with trailing data in a buffer, but + * mbedtls_psa_rsa_verify_hash requires the sig_len to be exact, + * so for this reason the passed sig_len is overwritten. Smaller + * signature lengths should not be accepted for verification. */ + signature_length = sig_len > mbedtls_pk_get_len(ctx) ? + mbedtls_pk_get_len(ctx) : sig_len; + status = psa_verify_hash(key_id, psa_sig_alg, hash, + hash_len, sig, signature_length); + destruction_status = psa_destroy_key(key_id); + + if (status == PSA_SUCCESS && sig_len > mbedtls_pk_get_len(ctx)) { + return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH; + } + + if (status == PSA_SUCCESS) { + status = destruction_status; + } + + return PSA_PK_RSA_TO_MBEDTLS_ERR(status); + } else +#endif + { + 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), + 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 */ +} + +/* + * 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_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_pk_restart_ctx *rs_ctx) +{ + if ((md_alg != MBEDTLS_MD_NONE || hash_len != 0) && hash == NULL) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + 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_size, 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_size, 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_size, 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_size, sig_len, + f_rng, p_rng, NULL); +} + +#if defined(MBEDTLS_PSA_CRYPTO_C) +/* + * Make a signature given a signature type. + */ +int mbedtls_pk_sign_ext(mbedtls_pk_type_t pk_type, + mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) +{ +#if defined(MBEDTLS_RSA_C) + psa_algorithm_t psa_md_alg; +#endif /* MBEDTLS_RSA_C */ + *sig_len = 0; + + if (ctx->pk_info == NULL) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + if (!mbedtls_pk_can_do(ctx, pk_type)) { + return MBEDTLS_ERR_PK_TYPE_MISMATCH; + } + + if (pk_type != MBEDTLS_PK_RSASSA_PSS) { + return mbedtls_pk_sign(ctx, md_alg, hash, hash_len, + sig, sig_size, sig_len, f_rng, p_rng); + } + +#if defined(MBEDTLS_RSA_C) + psa_md_alg = mbedtls_hash_info_psa_from_md(md_alg); + if (psa_md_alg == 0) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + if (mbedtls_pk_get_type(ctx) == MBEDTLS_PK_OPAQUE) { + const mbedtls_svc_key_id_t *key = (const mbedtls_svc_key_id_t *) ctx->pk_ctx; + psa_status_t status; + + status = psa_sign_hash(*key, PSA_ALG_RSA_PSS(psa_md_alg), + hash, hash_len, + sig, sig_size, sig_len); + return PSA_PK_RSA_TO_MBEDTLS_ERR(status); + } + + return mbedtls_pk_psa_rsa_sign_ext(PSA_ALG_RSA_PSS(psa_md_alg), + ctx->pk_ctx, hash, hash_len, + sig, sig_size, sig_len); +#else /* MBEDTLS_RSA_C */ + return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; +#endif /* !MBEDTLS_RSA_C */ + +} +#endif /* MBEDTLS_PSA_CRYPTO_C */ + +/* + * 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) +{ + 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) +{ + 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, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) +{ + if (pub->pk_info == NULL || + prv->pk_info == NULL) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + if (f_rng == 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, f_rng, p_rng); +} + +/* + * 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) +{ + 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 & RSA private keys. + */ +int mbedtls_pk_wrap_as_opaque(mbedtls_pk_context *pk, + mbedtls_svc_key_id_t *key, + psa_algorithm_t alg, + psa_key_usage_t usage, + psa_algorithm_t alg2) +{ +#if !defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_RSA_C) + ((void) pk); + ((void) key); + ((void) alg); + ((void) usage); + ((void) alg2); +#else +#if defined(MBEDTLS_ECP_C) + if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_ECKEY) { + 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; + psa_status_t status; + + /* export the private key material in the format PSA wants */ + ec = mbedtls_pk_ec(*pk); + d_len = PSA_BITS_TO_BYTES(ec->grp.nbits); + 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, usage); + psa_set_key_algorithm(&attributes, alg); + if (alg2 != PSA_ALG_NONE) { + psa_set_key_enrollment_algorithm(&attributes, alg2); + } + + /* import private key into PSA */ + status = psa_import_key(&attributes, d, d_len, key); + if (status != PSA_SUCCESS) { + return PSA_PK_TO_MBEDTLS_ERR(status); + } + + /* make PK context wrap the key slot */ + mbedtls_pk_free(pk); + mbedtls_pk_init(pk); + + return mbedtls_pk_setup_opaque(pk, *key); + } else +#endif /* MBEDTLS_ECP_C */ +#if defined(MBEDTLS_RSA_C) + if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_RSA) { + unsigned char buf[MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES]; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + int key_len; + psa_status_t status; + + /* export the private key material in the format PSA wants */ + key_len = mbedtls_pk_write_key_der(pk, buf, sizeof(buf)); + if (key_len <= 0) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + /* prepare the key attributes */ + psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR); + psa_set_key_bits(&attributes, mbedtls_pk_get_bitlen(pk)); + psa_set_key_usage_flags(&attributes, usage); + psa_set_key_algorithm(&attributes, alg); + if (alg2 != PSA_ALG_NONE) { + psa_set_key_enrollment_algorithm(&attributes, alg2); + } + + /* import private key into PSA */ + status = psa_import_key(&attributes, + buf + sizeof(buf) - key_len, + key_len, key); + + mbedtls_platform_zeroize(buf, sizeof(buf)); + + if (status != PSA_SUCCESS) { + return PSA_PK_TO_MBEDTLS_ERR(status); + } + + /* make PK context wrap the key slot */ + mbedtls_pk_free(pk); + mbedtls_pk_init(pk); + + return mbedtls_pk_setup_opaque(pk, *key); + } else +#endif /* MBEDTLS_RSA_C */ +#endif /* !MBEDTLS_ECP_C && !MBEDTLS_RSA_C */ + return MBEDTLS_ERR_PK_TYPE_MISMATCH; +} +#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..4d91f22 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/pk_wrap.c @@ -0,0 +1,1617 @@ +/* + * 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" + +#include "mbedtls/platform_util.h" + +#if defined(MBEDTLS_PK_C) +#include "pk_wrap.h" +#include "mbedtls/error.h" + +/* Even if RSA not activated, for the sake of RSA-alt */ +#include "mbedtls/rsa.h" + +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif + +#if defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdsa.h" +#endif + +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PSA_CRYPTO_C) +#include "pkwrite.h" +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_C) +#include "mbedtls/psa_util.h" +#define PSA_PK_TO_MBEDTLS_ERR(status) psa_pk_status_to_mbedtls(status) +#define PSA_PK_RSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \ + psa_to_pk_rsa_errors, \ + psa_pk_status_to_mbedtls) +#define PSA_PK_ECDSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \ + psa_to_pk_ecdsa_errors, \ + psa_pk_status_to_mbedtls) +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#include "hash_info.h" + +#if defined(MBEDTLS_PK_CAN_ECDSA_SOME) +#include "mbedtls/asn1write.h" +#include "mbedtls/asn1.h" +#endif +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#include "mbedtls/platform.h" + +#include +#include +#include + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_PSA_CRYPTO_C) +int mbedtls_pk_error_from_psa(psa_status_t status) +{ + switch (status) { + case PSA_SUCCESS: + return 0; + case PSA_ERROR_INVALID_HANDLE: + return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; + case PSA_ERROR_NOT_PERMITTED: + return MBEDTLS_ERR_ERROR_GENERIC_ERROR; + case PSA_ERROR_BUFFER_TOO_SMALL: + return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL; + case PSA_ERROR_NOT_SUPPORTED: + return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; + case PSA_ERROR_INVALID_ARGUMENT: + return MBEDTLS_ERR_PK_INVALID_ALG; + case PSA_ERROR_INSUFFICIENT_MEMORY: + return MBEDTLS_ERR_PK_ALLOC_FAILED; + case PSA_ERROR_BAD_STATE: + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + case PSA_ERROR_COMMUNICATION_FAILURE: + case PSA_ERROR_HARDWARE_FAILURE: + return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + case PSA_ERROR_DATA_CORRUPT: + case PSA_ERROR_DATA_INVALID: + case PSA_ERROR_STORAGE_FAILURE: + return MBEDTLS_ERR_PK_FILE_IO_ERROR; + case PSA_ERROR_CORRUPTION_DETECTED: + return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + default: + return MBEDTLS_ERR_ERROR_GENERIC_ERROR; + } +} + +#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) || \ + defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) +int mbedtls_pk_error_from_psa_rsa(psa_status_t status) +{ + switch (status) { + case PSA_ERROR_NOT_PERMITTED: + case PSA_ERROR_INVALID_ARGUMENT: + case PSA_ERROR_INVALID_HANDLE: + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + case PSA_ERROR_BUFFER_TOO_SMALL: + return MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; + case PSA_ERROR_INSUFFICIENT_ENTROPY: + return MBEDTLS_ERR_RSA_RNG_FAILED; + case PSA_ERROR_INVALID_SIGNATURE: + return MBEDTLS_ERR_RSA_VERIFY_FAILED; + case PSA_ERROR_INVALID_PADDING: + return MBEDTLS_ERR_RSA_INVALID_PADDING; + 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_BAD_STATE: + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + case PSA_ERROR_COMMUNICATION_FAILURE: + case PSA_ERROR_HARDWARE_FAILURE: + return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + case PSA_ERROR_DATA_CORRUPT: + case PSA_ERROR_DATA_INVALID: + case PSA_ERROR_STORAGE_FAILURE: + return MBEDTLS_ERR_PK_FILE_IO_ERROR; + case PSA_ERROR_CORRUPTION_DETECTED: + return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + default: + return MBEDTLS_ERR_ERROR_GENERIC_ERROR; + } +} +#endif /* PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY || PSA_WANT_KEY_TYPE_RSA_KEY_PAIR */ +#endif /* MBEDTLS_PSA_CRYPTO_C */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) +int mbedtls_pk_error_from_psa_ecdsa(psa_status_t status) +{ + switch (status) { + case PSA_ERROR_NOT_PERMITTED: + case PSA_ERROR_INVALID_ARGUMENT: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + case PSA_ERROR_INVALID_HANDLE: + return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + case PSA_ERROR_BUFFER_TOO_SMALL: + return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; + case PSA_ERROR_INSUFFICIENT_ENTROPY: + return MBEDTLS_ERR_ECP_RANDOM_FAILED; + case PSA_ERROR_INVALID_SIGNATURE: + return MBEDTLS_ERR_ECP_VERIFY_FAILED; + 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_BAD_STATE: + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + case PSA_ERROR_COMMUNICATION_FAILURE: + case PSA_ERROR_HARDWARE_FAILURE: + return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + case PSA_ERROR_DATA_CORRUPT: + case PSA_ERROR_DATA_INVALID: + case PSA_ERROR_STORAGE_FAILURE: + return MBEDTLS_ERR_PK_FILE_IO_ERROR; + case PSA_ERROR_CORRUPTION_DETECTED: + return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + default: + return MBEDTLS_ERR_ERROR_GENERIC_ERROR; + } +} +#endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */ +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#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); +} + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +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) +{ + mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) ctx; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_status_t status; + mbedtls_pk_context key; + int key_len; + unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES]; + psa_algorithm_t psa_alg_md = + PSA_ALG_RSA_PKCS1V15_SIGN(mbedtls_hash_info_psa_from_md(md_alg)); + size_t rsa_len = mbedtls_rsa_get_len(rsa); + + if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + if (sig_len < rsa_len) { + return MBEDTLS_ERR_RSA_VERIFY_FAILED; + } + + /* mbedtls_pk_write_pubkey_der() expects a full PK context; + * re-construct one to make it happy */ + key.pk_info = &mbedtls_rsa_info; + key.pk_ctx = ctx; + key_len = mbedtls_pk_write_pubkey_der(&key, buf, sizeof(buf)); + if (key_len <= 0) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH); + psa_set_key_algorithm(&attributes, psa_alg_md); + psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_PUBLIC_KEY); + + status = psa_import_key(&attributes, + buf + sizeof(buf) - key_len, key_len, + &key_id); + if (status != PSA_SUCCESS) { + ret = PSA_PK_TO_MBEDTLS_ERR(status); + goto cleanup; + } + + status = psa_verify_hash(key_id, psa_alg_md, hash, hash_len, + sig, sig_len); + if (status != PSA_SUCCESS) { + ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status); + goto cleanup; + } + ret = 0; + +cleanup: + status = psa_destroy_key(key_id); + if (ret == 0 && status != PSA_SUCCESS) { + ret = PSA_PK_TO_MBEDTLS_ERR(status); + } + + return ret; +} +#else +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 (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + if (sig_len < rsa_len) { + return MBEDTLS_ERR_RSA_VERIFY_FAILED; + } + + if ((ret = mbedtls_rsa_pkcs1_verify(rsa, 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; +} +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_C) +int mbedtls_pk_psa_rsa_sign_ext(psa_algorithm_t alg, + mbedtls_rsa_context *rsa_ctx, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, + size_t *sig_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_status_t status; + mbedtls_pk_context key; + int key_len; + unsigned char buf[MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES]; + mbedtls_pk_info_t pk_info = mbedtls_rsa_info; + + *sig_len = mbedtls_rsa_get_len(rsa_ctx); + if (sig_size < *sig_len) { + return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL; + } + + /* mbedtls_pk_write_key_der() expects a full PK context; + * re-construct one to make it happy */ + key.pk_info = &pk_info; + key.pk_ctx = rsa_ctx; + key_len = mbedtls_pk_write_key_der(&key, buf, sizeof(buf)); + if (key_len <= 0) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); + psa_set_key_algorithm(&attributes, alg); + psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR); + + status = psa_import_key(&attributes, + buf + sizeof(buf) - key_len, key_len, + &key_id); + if (status != PSA_SUCCESS) { + ret = PSA_PK_TO_MBEDTLS_ERR(status); + goto cleanup; + } + status = psa_sign_hash(key_id, alg, hash, hash_len, + sig, sig_size, sig_len); + if (status != PSA_SUCCESS) { + ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status); + goto cleanup; + } + + ret = 0; + +cleanup: + status = psa_destroy_key(key_id); + if (ret == 0 && status != PSA_SUCCESS) { + ret = PSA_PK_TO_MBEDTLS_ERR(status); + } + return ret; +} +#endif /* MBEDTLS_PSA_CRYPTO_C */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +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_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + ((void) f_rng); + ((void) p_rng); + + psa_algorithm_t psa_md_alg; + psa_md_alg = mbedtls_hash_info_psa_from_md(md_alg); + if (psa_md_alg == 0) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + return mbedtls_pk_psa_rsa_sign_ext(PSA_ALG_RSA_PKCS1V15_SIGN( + psa_md_alg), + ctx, hash, hash_len, + sig, sig_size, sig_len); +} +#else +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_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) ctx; + + if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + *sig_len = mbedtls_rsa_get_len(rsa); + if (sig_size < *sig_len) { + return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL; + } + + return mbedtls_rsa_pkcs1_sign(rsa, f_rng, p_rng, + md_alg, (unsigned int) hash_len, + hash, sig); +} +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +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; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_status_t status; + mbedtls_pk_context key; + int key_len; + unsigned char buf[MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES]; + + ((void) f_rng); + ((void) p_rng); + +#if !defined(MBEDTLS_RSA_ALT) + if (rsa->padding != MBEDTLS_RSA_PKCS_V15) { + return MBEDTLS_ERR_RSA_INVALID_PADDING; + } +#endif /* !MBEDTLS_RSA_ALT */ + + if (ilen != mbedtls_rsa_get_len(rsa)) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } + + /* mbedtls_pk_write_key_der() expects a full PK context; + * re-construct one to make it happy */ + key.pk_info = &mbedtls_rsa_info; + key.pk_ctx = ctx; + key_len = mbedtls_pk_write_key_der(&key, buf, sizeof(buf)); + if (key_len <= 0) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT); + psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_CRYPT); + + status = psa_import_key(&attributes, + buf + sizeof(buf) - key_len, key_len, + &key_id); + if (status != PSA_SUCCESS) { + ret = PSA_PK_TO_MBEDTLS_ERR(status); + goto cleanup; + } + + status = psa_asymmetric_decrypt(key_id, PSA_ALG_RSA_PKCS1V15_CRYPT, + input, ilen, + NULL, 0, + output, osize, olen); + if (status != PSA_SUCCESS) { + ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status); + goto cleanup; + } + + ret = 0; + +cleanup: + mbedtls_platform_zeroize(buf, sizeof(buf)); + status = psa_destroy_key(key_id); + if (ret == 0 && status != PSA_SUCCESS) { + ret = PSA_PK_TO_MBEDTLS_ERR(status); + } + + return ret; +} +#else +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, + olen, input, output, osize); +} +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +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; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_status_t status; + mbedtls_pk_context key; + int key_len; + unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES]; + + ((void) f_rng); + ((void) p_rng); + +#if !defined(MBEDTLS_RSA_ALT) + if (rsa->padding != MBEDTLS_RSA_PKCS_V15) { + return MBEDTLS_ERR_RSA_INVALID_PADDING; + } +#endif + + if (mbedtls_rsa_get_len(rsa) > osize) { + return MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; + } + + /* mbedtls_pk_write_pubkey_der() expects a full PK context; + * re-construct one to make it happy */ + key.pk_info = &mbedtls_rsa_info; + key.pk_ctx = ctx; + key_len = mbedtls_pk_write_pubkey_der(&key, buf, sizeof(buf)); + if (key_len <= 0) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT); + psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_CRYPT); + psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_PUBLIC_KEY); + + status = psa_import_key(&attributes, + buf + sizeof(buf) - key_len, key_len, + &key_id); + if (status != PSA_SUCCESS) { + ret = PSA_PK_TO_MBEDTLS_ERR(status); + goto cleanup; + } + + status = psa_asymmetric_encrypt(key_id, PSA_ALG_RSA_PKCS1V15_CRYPT, + input, ilen, + NULL, 0, + output, osize, olen); + if (status != PSA_SUCCESS) { + ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status); + goto cleanup; + } + + ret = 0; + +cleanup: + status = psa_destroy_key(key_id); + if (ret == 0 && status != PSA_SUCCESS) { + ret = PSA_PK_TO_MBEDTLS_ERR(status); + } + + return ret; +} +#else +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, + ilen, input, output); +} +#endif + +static int rsa_check_pair_wrap(const void *pub, const void *prv, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) +{ + (void) f_rng; + (void) p_rng; + 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); + } + + 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) +{ +#if defined(MBEDTLS_RSA_ALT) + /* Not supported */ + (void) ctx; + (void) items; +#else + 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); +#endif +} + +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_PK_CAN_ECDSA_VERIFY) +#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_ecp_keypair *ctx = ctx_arg; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_status_t status; + size_t key_len; + /* This buffer will initially contain the public key and then the signature + * but at different points in time. For all curves except secp224k1, which + * is not currently supported in PSA, the public key is one byte longer + * (header byte + 2 numbers, while the signature is only 2 numbers), + * so use that as the buffer size. */ + unsigned char buf[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH]; + unsigned char *p; + 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; + } + + 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); + + ret = mbedtls_ecp_point_write_binary(&ctx->grp, &ctx->Q, + MBEDTLS_ECP_PF_UNCOMPRESSED, + &key_len, buf, sizeof(buf)); + if (ret != 0) { + goto cleanup; + } + + status = psa_import_key(&attributes, + buf, key_len, + &key_id); + if (status != PSA_SUCCESS) { + ret = PSA_PK_TO_MBEDTLS_ERR(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; + } + + status = psa_verify_hash(key_id, psa_sig_md, + hash, hash_len, + buf, 2 * signature_part_size); + if (status != PSA_SUCCESS) { + ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); + goto cleanup; + } + + if (p != sig + sig_len) { + ret = MBEDTLS_ERR_PK_SIG_LEN_MISMATCH; + goto cleanup; + } + ret = 0; + +cleanup: + status = psa_destroy_key(key_id); + if (ret == 0 && status != PSA_SUCCESS) { + ret = PSA_PK_TO_MBEDTLS_ERR(status); + } + + 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 */ +#endif /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ + +#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN) +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/* + * 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_PLATFORM_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; +} + +static int ecdsa_sign_wrap(void *ctx_arg, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + mbedtls_ecp_keypair *ctx = ctx_arg; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_status_t status; + unsigned char buf[MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH]; +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + psa_algorithm_t psa_sig_md = + PSA_ALG_DETERMINISTIC_ECDSA(mbedtls_hash_info_psa_from_md(md_alg)); +#else + psa_algorithm_t psa_sig_md = + PSA_ALG_ECDSA(mbedtls_hash_info_psa_from_md(md_alg)); +#endif + size_t curve_bits; + psa_ecc_family_t curve = + mbedtls_ecc_group_to_psa(ctx->grp.id, &curve_bits); + size_t key_len = PSA_BITS_TO_BYTES(curve_bits); + + /* PSA has its own RNG */ + ((void) f_rng); + ((void) p_rng); + + if (curve == 0) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + if (key_len > sizeof(buf)) { + return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + } + ret = mbedtls_mpi_write_binary(&ctx->d, buf, key_len); + if (ret != 0) { + goto cleanup; + } + + psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(curve)); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); + psa_set_key_algorithm(&attributes, psa_sig_md); + + status = psa_import_key(&attributes, + buf, key_len, + &key_id); + if (status != PSA_SUCCESS) { + ret = PSA_PK_TO_MBEDTLS_ERR(status); + goto cleanup; + } + + status = psa_sign_hash(key_id, psa_sig_md, hash, hash_len, + sig, sig_size, sig_len); + if (status != PSA_SUCCESS) { + ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); + goto cleanup; + } + + ret = pk_ecdsa_sig_asn1_from_psa(sig, sig_len, sig_size); + +cleanup: + mbedtls_platform_zeroize(buf, sizeof(buf)); + status = psa_destroy_key(key_id); + if (ret == 0 && status != PSA_SUCCESS) { + ret = PSA_PK_TO_MBEDTLS_ERR(status); + } + + return ret; +} +#else /* 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_size, 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_size, sig_len, + f_rng, p_rng); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */ + +#if defined(MBEDTLS_ECDSA_C) && 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_size, 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_size, 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_size, sig_len, + f_rng, p_rng, &rs->ecdsa_rs)); + +cleanup: + return ret; +} +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +static int eckey_check_pair(const void *pub, const void *prv, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) +{ + return mbedtls_ecp_check_pub_priv((const mbedtls_ecp_keypair *) pub, + (const mbedtls_ecp_keypair *) prv, + f_rng, p_rng); +} + +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_PK_CAN_ECDSA_VERIFY) + ecdsa_verify_wrap, /* Compatible key structures */ +#else + NULL, +#endif +#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN) + ecdsa_sign_wrap, /* Compatible key structures */ +#else + NULL, +#endif +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + eckey_verify_rs_wrap, + eckey_sign_rs_wrap, +#endif + 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_PK_CAN_ECDSA_SOME) +static int ecdsa_can_do(mbedtls_pk_type_t type) +{ + return type == MBEDTLS_PK_ECDSA; +} + +#if defined(MBEDTLS_ECDSA_C) && 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_size, 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_size, sig_len, f_rng, p_rng, + (mbedtls_ecdsa_restart_ctx *) rs_ctx); + +} + +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_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +const mbedtls_pk_info_t mbedtls_ecdsa_info = { + MBEDTLS_PK_ECDSA, + "ECDSA", + eckey_get_bitlen, /* Compatible key structures */ + ecdsa_can_do, +#if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) + ecdsa_verify_wrap, /* Compatible key structures */ +#else + NULL, +#endif +#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN) + ecdsa_sign_wrap, /* Compatible key structures */ +#else + NULL, +#endif +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + ecdsa_verify_rs_wrap, + ecdsa_sign_rs_wrap, +#endif + NULL, + NULL, + eckey_check_pair, /* Compatible key structures */ + eckey_alloc_wrap, /* Compatible key structures */ + eckey_free_wrap, /* Compatible key structures */ +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + ecdsa_rs_alloc, + ecdsa_rs_free, +#endif + eckey_debug, /* Compatible key structures */ +}; +#endif /* MBEDTLS_PK_CAN_ECDSA_SOME */ + +#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_size, 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 (UINT_MAX < hash_len) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + *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; + } + if (*sig_len > sig_size) { + return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL; + } + + return rsa_alt->sign_func(rsa_alt->key, f_rng, p_rng, + 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, + olen, input, output, osize); +} + +#if defined(MBEDTLS_RSA_C) +static int rsa_alt_check_pair(const void *pub, const void *prv, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) +{ + 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, sizeof(sig), &sig_len, + f_rng, p_rng)) != 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(mbedtls_svc_key_id_t)); + + /* no _init() function to call, as calloc() already zeroized */ + + return ctx; +} + +static void pk_opaque_free_wrap(void *ctx) +{ + mbedtls_platform_zeroize(ctx, sizeof(mbedtls_svc_key_id_t)); + mbedtls_free(ctx); +} + +static size_t pk_opaque_get_bitlen(const void *ctx) +{ + const mbedtls_svc_key_id_t *key = (const mbedtls_svc_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_ecdsa_can_do(mbedtls_pk_type_t type) +{ + return type == MBEDTLS_PK_ECKEY || + type == MBEDTLS_PK_ECDSA; +} + +static int pk_opaque_rsa_can_do(mbedtls_pk_type_t type) +{ + return type == MBEDTLS_PK_RSA || + type == MBEDTLS_PK_RSASSA_PSS; +} + +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_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ +#if !defined(MBEDTLS_PK_CAN_ECDSA_SIGN) && !defined(MBEDTLS_RSA_C) + ((void) ctx); + ((void) md_alg); + ((void) hash); + ((void) hash_len); + ((void) sig); + ((void) sig_size); + ((void) sig_len); + ((void) f_rng); + ((void) p_rng); + return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; +#else /* !MBEDTLS_PK_CAN_ECDSA_SIGN && !MBEDTLS_RSA_C */ + const mbedtls_svc_key_id_t *key = (const mbedtls_svc_key_id_t *) ctx; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_algorithm_t alg; + psa_key_type_t type; + psa_status_t status; + + /* PSA has its own RNG */ + (void) f_rng; + (void) p_rng; + + status = psa_get_key_attributes(*key, &attributes); + if (status != PSA_SUCCESS) { + return PSA_PK_TO_MBEDTLS_ERR(status); + } + + type = psa_get_key_type(&attributes); + psa_reset_key_attributes(&attributes); + +#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN) + if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type)) { + alg = PSA_ALG_ECDSA(mbedtls_hash_info_psa_from_md(md_alg)); + } else +#endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */ +#if defined(MBEDTLS_RSA_C) + if (PSA_KEY_TYPE_IS_RSA(type)) { + alg = PSA_ALG_RSA_PKCS1V15_SIGN(mbedtls_hash_info_psa_from_md(md_alg)); + } else +#endif /* MBEDTLS_RSA_C */ + return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; + + /* make the signature */ + status = psa_sign_hash(*key, alg, hash, hash_len, + sig, sig_size, sig_len); + if (status != PSA_SUCCESS) { +#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN) + if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type)) { + return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); + } else +#endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */ +#if defined(MBEDTLS_RSA_C) + if (PSA_KEY_TYPE_IS_RSA(type)) { + return PSA_PK_RSA_TO_MBEDTLS_ERR(status); + } else +#endif /* MBEDTLS_RSA_C */ + return PSA_PK_TO_MBEDTLS_ERR(status); + } + +#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN) + if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type)) { + /* transcode it to ASN.1 sequence */ + return pk_ecdsa_sig_asn1_from_psa(sig, sig_len, sig_size); + } +#endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */ + + return 0; +#endif /* !MBEDTLS_PK_CAN_ECDSA_SIGN && !MBEDTLS_RSA_C */ +} + +const mbedtls_pk_info_t mbedtls_pk_ecdsa_opaque_info = { + MBEDTLS_PK_OPAQUE, + "Opaque", + pk_opaque_get_bitlen, + pk_opaque_ecdsa_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 - not relevant */ + NULL, /* encrypt - not relevant */ + 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 */ +}; + +#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) +static int pk_opaque_rsa_decrypt(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) +{ + const mbedtls_svc_key_id_t *key = (const mbedtls_svc_key_id_t *) ctx; + psa_status_t status; + + /* PSA has its own RNG */ + (void) f_rng; + (void) p_rng; + + status = psa_asymmetric_decrypt(*key, PSA_ALG_RSA_PKCS1V15_CRYPT, + input, ilen, + NULL, 0, + output, osize, olen); + if (status != PSA_SUCCESS) { + return PSA_PK_RSA_TO_MBEDTLS_ERR(status); + } + + return 0; +} +#endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR */ + +const mbedtls_pk_info_t mbedtls_pk_rsa_opaque_info = { + MBEDTLS_PK_OPAQUE, + "Opaque", + pk_opaque_get_bitlen, + pk_opaque_rsa_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 +#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) + pk_opaque_rsa_decrypt, +#else + NULL, /* decrypt - not available */ +#endif /* PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY */ + 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/pk_wrap.h b/optee/optee_os/lib/libmbedtls/mbedtls/library/pk_wrap.h new file mode 100644 index 0000000..c5cd4df --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/pk_wrap.h @@ -0,0 +1,168 @@ +/** + * \file pk_wrap.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 + +#include "mbedtls/build_info.h" + +#include "mbedtls/pk.h" + +#if defined(MBEDTLS_PSA_CRYPTO_C) +#include "psa/crypto.h" +#endif /* MBEDTLS_PSA_CRYPTO_C */ + +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_size, 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_size, 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, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng); + + /** 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_PK_CAN_ECDSA_SOME) +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_ecdsa_opaque_info; +extern const mbedtls_pk_info_t mbedtls_pk_rsa_opaque_info; + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) +int MBEDTLS_DEPRECATED mbedtls_pk_error_from_psa_ecdsa(psa_status_t status); +#endif +#endif + +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_PSA_CRYPTO_C) +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +int MBEDTLS_DEPRECATED mbedtls_pk_error_from_psa(psa_status_t status); + +#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) || \ + defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) +int MBEDTLS_DEPRECATED mbedtls_pk_error_from_psa_rsa(psa_status_t status); +#endif /* PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY || PSA_WANT_KEY_TYPE_RSA_KEY_PAIR */ +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_RSA_C) +int mbedtls_pk_psa_rsa_sign_ext(psa_algorithm_t psa_alg_md, + mbedtls_rsa_context *rsa_ctx, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, + size_t *sig_len); +#endif /* MBEDTLS_RSA_C */ + +#endif /* MBEDTLS_PSA_CRYPTO_C */ + +#endif /* MBEDTLS_PK_WRAP_H */ 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..8521483 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/pkcs12.c @@ -0,0 +1,454 @@ +/* + * 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_MD_C) +#include "mbedtls/psa_util.h" +#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \ + psa_to_md_errors, \ + psa_generic_status_to_mbedtls) +#endif + +#if defined(MBEDTLS_DES_C) +#include "mbedtls/des.h" +#endif + +#include "hash_info.h" +#include "mbedtls/psa_util.h" + +#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(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.*/ + } +} + + +static int calculate_hashes(mbedtls_md_type_t md_type, int iterations, + unsigned char *diversifier, unsigned char *salt_block, + unsigned char *pwd_block, unsigned char *hash_output, int use_salt, + int use_password, size_t hlen, size_t v) +{ +#if defined(MBEDTLS_MD_C) + int ret = -1; + size_t i; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + 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; + } + // 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; + } + } + +exit: + mbedtls_md_free(&md_ctx); + return ret; +#else + psa_hash_operation_t op = PSA_HASH_OPERATION_INIT; + psa_algorithm_t alg = mbedtls_psa_translate_md(md_type); + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t status_abort = PSA_ERROR_CORRUPTION_DETECTED; + size_t i, out_len, out_size = PSA_HASH_LENGTH(alg); + + if (alg == PSA_ALG_NONE) { + return MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE; + } + + if ((status = psa_hash_setup(&op, alg)) != PSA_SUCCESS) { + goto exit; + } + + // Calculate hash( diversifier || salt_block || pwd_block ) + if ((status = psa_hash_update(&op, diversifier, v)) != PSA_SUCCESS) { + goto exit; + } + + if (use_salt != 0) { + if ((status = psa_hash_update(&op, salt_block, v)) != PSA_SUCCESS) { + goto exit; + } + } + + if (use_password != 0) { + if ((status = psa_hash_update(&op, pwd_block, v)) != PSA_SUCCESS) { + goto exit; + } + } + + if ((status = psa_hash_finish(&op, hash_output, out_size, &out_len)) + != PSA_SUCCESS) { + goto exit; + } + + // Perform remaining ( iterations - 1 ) recursive hash calculations + for (i = 1; i < (size_t) iterations; i++) { + if ((status = psa_hash_compute(alg, hash_output, hlen, hash_output, + out_size, &out_len)) != PSA_SUCCESS) { + goto exit; + } + } + +exit: + status_abort = psa_hash_abort(&op); + if (status == PSA_SUCCESS) { + status = status_abort; + } + return PSA_TO_MBEDTLS_ERR(status); +#endif /* !MBEDTLS_MD_C */ +} + + +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] = { 0 }; + unsigned char hash_output[MBEDTLS_HASH_MAX_SIZE]; + unsigned char *p; + unsigned char c; + int use_password = 0; + int use_salt = 0; + + size_t hlen, use_len, v, i; + + // 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); + + hlen = mbedtls_hash_info_get_size(md_type); + + 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) { + if (calculate_hashes(md_type, iterations, diversifier, salt_block, + pwd_block, hash_output, use_salt, use_password, hlen, + v) != 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)); + + 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..f471b63 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/pkcs5.c @@ -0,0 +1,569 @@ +/** + * \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 + +#include "mbedtls/platform.h" + +#include "hash_info.h" +#include "mbedtls/psa_util.h" + +#if !defined(MBEDTLS_MD_C) +#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \ + psa_to_md_errors, \ + psa_generic_status_to_mbedtls) +#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_cipher_info_t *cipher_info; + 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; + } + + 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_cipher_init(&cipher_ctx); + + memcpy(iv, enc_scheme_params.p, enc_scheme_params.len); + + if ((ret = mbedtls_pkcs5_pbkdf2_hmac_ext(md_type, 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_cipher_free(&cipher_ctx); + + return ret; +} +#endif /* MBEDTLS_ASN1_PARSE_C */ + +#if defined(MBEDTLS_MD_C) +static int 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; + 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 + // + mbedtls_xor(work, work, md1, md_size); + } + + 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_DEPRECATED_REMOVED) +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) +{ + return pkcs5_pbkdf2_hmac(ctx, password, plen, salt, slen, iteration_count, + key_length, output); +} +#endif +#endif /* MBEDTLS_MD_C */ + +int mbedtls_pkcs5_pbkdf2_hmac_ext(mbedtls_md_type_t md_alg, + 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_MD_C) + mbedtls_md_context_t md_ctx; + const mbedtls_md_info_t *md_info = NULL; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + md_info = mbedtls_md_info_from_type(md_alg); + if (md_info == NULL) { + return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE; + } + + mbedtls_md_init(&md_ctx); + + if ((ret = mbedtls_md_setup(&md_ctx, md_info, 1)) != 0) { + goto exit; + } + ret = pkcs5_pbkdf2_hmac(&md_ctx, password, plen, salt, slen, + iteration_count, key_length, output); +exit: + mbedtls_md_free(&md_ctx); + return ret; +#else + unsigned int i; + unsigned char md1[PSA_HASH_MAX_SIZE]; + unsigned char work[PSA_HASH_MAX_SIZE]; + const unsigned char md_size = mbedtls_hash_info_get_size(md_alg); + psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; + + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t status_destruction = PSA_ERROR_CORRUPTION_DETECTED; + size_t use_len, out_len; + unsigned char *out_p = output; + unsigned char counter[4]; + mbedtls_svc_key_id_t psa_hmac_key = MBEDTLS_SVC_KEY_ID_INIT; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + const psa_algorithm_t alg = PSA_ALG_HMAC(mbedtls_hash_info_psa_from_md(md_alg)); + const size_t out_size = PSA_MAC_LENGTH(PSA_KEY_TYPE_HMAC, 0, alg); + + memset(counter, 0, sizeof(counter)); + counter[3] = 1; + + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE); + psa_set_key_algorithm(&attributes, alg); + psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC); + + if (key_length == 0) { + return 0; + } + if ((status = psa_import_key(&attributes, + password, plen, + &psa_hmac_key)) != PSA_SUCCESS) { + return MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA; + } + +#if UINT_MAX > 0xFFFFFFFF + if (iteration_count > 0xFFFFFFFF) { + return MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA; + } +#endif + + while (key_length) { + status = psa_mac_sign_setup(&operation, psa_hmac_key, + PSA_ALG_HMAC(alg)); + if (status != PSA_SUCCESS) { + goto cleanup; + } + // U1 ends up in work + if ((status = psa_mac_update(&operation, salt, slen)) != PSA_SUCCESS) { + goto cleanup; + } + + if ((status = psa_mac_update(&operation, counter, sizeof(counter))) != PSA_SUCCESS) { + goto cleanup; + } + + if ((status = psa_mac_sign_finish(&operation, work, out_size, &out_len)) + != PSA_SUCCESS) { + goto cleanup; + } + + memcpy(md1, work, out_len); + + for (i = 1; i < iteration_count; i++) { + // U2 ends up in md1 + // + status = psa_mac_sign_setup(&operation, psa_hmac_key, + PSA_ALG_HMAC(alg)); + if (status != PSA_SUCCESS) { + goto cleanup; + } + if ((status = psa_mac_update(&operation, md1, md_size)) != PSA_SUCCESS) { + goto cleanup; + } + if ((status = + psa_mac_sign_finish(&operation, md1, out_size, &out_len)) != PSA_SUCCESS) { + goto cleanup; + } + + // U1 xor U2 + // + mbedtls_xor(work, work, md1, md_size); + } + + 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, PSA_HASH_MAX_SIZE); + mbedtls_platform_zeroize(md1, PSA_HASH_MAX_SIZE); + status_destruction = psa_destroy_key(psa_hmac_key); + if (status == PSA_SUCCESS && status_destruction != PSA_SUCCESS) { + status = status_destruction; + } + status_destruction = psa_mac_abort(&operation); + if (status == PSA_SUCCESS && status_destruction != PSA_SUCCESS) { + status = status_destruction; + } + + return PSA_TO_MBEDTLS_ERR(status); +#endif /* !MBEDTLS_MD_C */ +} + +#if defined(MBEDTLS_SELF_TEST) + +#if !defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA) +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) +{ + int ret, i; + unsigned char key[64]; + + for (i = 0; i < MAX_TESTS; i++) { + if (verbose != 0) { + mbedtls_printf(" PBKDF2 (SHA1) #%d: ", i); + } + + ret = mbedtls_pkcs5_pbkdf2_hmac_ext(MBEDTLS_MD_SHA1, 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: + return ret; +} +#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA */ + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_PKCS5_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/pkcs7.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/pkcs7.c new file mode 100644 index 0000000..cf05afd --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/pkcs7.c @@ -0,0 +1,785 @@ +/* + * 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/build_info.h" +#if defined(MBEDTLS_PKCS7_C) +#include "mbedtls/pkcs7.h" +#include "mbedtls/x509.h" +#include "mbedtls/asn1.h" +#include "mbedtls/x509_crt.h" +#include "mbedtls/x509_crl.h" +#include "mbedtls/oid.h" +#include "mbedtls/error.h" + +#if defined(MBEDTLS_FS_IO) +#include +#include +#endif + +#include "mbedtls/platform.h" +#include "mbedtls/platform_util.h" + +#if defined(MBEDTLS_HAVE_TIME) +#include "mbedtls/platform_time.h" +#endif +#if defined(MBEDTLS_HAVE_TIME_DATE) +#include +#endif + +/** + * Initializes the mbedtls_pkcs7 structure. + */ +void mbedtls_pkcs7_init(mbedtls_pkcs7 *pkcs7) +{ + memset(pkcs7, 0, sizeof(*pkcs7)); +} + +static int pkcs7_get_next_content_len(unsigned char **p, unsigned char *end, + size_t *len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ret = mbedtls_asn1_get_tag(p, end, len, MBEDTLS_ASN1_CONSTRUCTED + | MBEDTLS_ASN1_CONTEXT_SPECIFIC); + if (ret != 0) { + ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret); + } else if ((size_t) (end - *p) != *len) { + ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + + return ret; +} + +/** + * version Version + * Version ::= INTEGER + **/ +static int pkcs7_get_version(unsigned char **p, unsigned char *end, int *ver) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ret = mbedtls_asn1_get_int(p, end, ver); + if (ret != 0) { + ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_VERSION, ret); + } + + /* If version != 1, return invalid version */ + if (*ver != MBEDTLS_PKCS7_SUPPORTED_VERSION) { + ret = MBEDTLS_ERR_PKCS7_INVALID_VERSION; + } + + return ret; +} + +/** + * ContentInfo ::= SEQUENCE { + * contentType ContentType, + * content + * [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL } + **/ +static int pkcs7_get_content_info_type(unsigned char **p, unsigned char *end, + unsigned char **seq_end, + mbedtls_pkcs7_buf *pkcs7) +{ + size_t len = 0; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *start = *p; + + ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED + | MBEDTLS_ASN1_SEQUENCE); + if (ret != 0) { + *p = start; + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret); + } + *seq_end = *p + len; + ret = mbedtls_asn1_get_tag(p, *seq_end, &len, MBEDTLS_ASN1_OID); + if (ret != 0) { + *p = start; + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret); + } + + pkcs7->tag = MBEDTLS_ASN1_OID; + pkcs7->len = len; + pkcs7->p = *p; + *p += len; + + return ret; +} + +/** + * DigestAlgorithmIdentifier ::= AlgorithmIdentifier + * + * This is from x509.h + **/ +static int pkcs7_get_digest_algorithm(unsigned char **p, 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) { + ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_ALG, ret); + } + + return ret; +} + +/** + * DigestAlgorithmIdentifiers :: SET of DigestAlgorithmIdentifier + **/ +static int pkcs7_get_digest_algorithm_set(unsigned char **p, + unsigned char *end, + mbedtls_x509_buf *alg) +{ + size_t len = 0; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED + | MBEDTLS_ASN1_SET); + if (ret != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_ALG, ret); + } + + end = *p + len; + + ret = mbedtls_asn1_get_alg_null(p, end, alg); + if (ret != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_ALG, ret); + } + + /** For now, it assumes there is only one digest algorithm specified **/ + if (*p != end) { + return MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE; + } + + return 0; +} + +/** + * certificates :: SET OF ExtendedCertificateOrCertificate, + * ExtendedCertificateOrCertificate ::= CHOICE { + * certificate Certificate -- x509, + * extendedCertificate[0] IMPLICIT ExtendedCertificate } + * Return number of certificates added to the signed data, + * 0 or higher is valid. + * Return negative error code for failure. + **/ +static int pkcs7_get_certificates(unsigned char **p, unsigned char *end, + mbedtls_x509_crt *certs) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len1 = 0; + size_t len2 = 0; + unsigned char *end_set, *end_cert, *start; + + ret = mbedtls_asn1_get_tag(p, end, &len1, MBEDTLS_ASN1_CONSTRUCTED + | MBEDTLS_ASN1_CONTEXT_SPECIFIC); + if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { + return 0; + } + if (ret != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret); + } + start = *p; + end_set = *p + len1; + + ret = mbedtls_asn1_get_tag(p, end_set, &len2, MBEDTLS_ASN1_CONSTRUCTED + | MBEDTLS_ASN1_SEQUENCE); + if (ret != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CERT, ret); + } + + end_cert = *p + len2; + + /* + * This is to verify that there is only one signer certificate. It seems it is + * not easy to differentiate between the chain vs different signer's certificate. + * So, we support only the root certificate and the single signer. + * The behaviour would be improved with addition of multiple signer support. + */ + if (end_cert != end_set) { + return MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE; + } + + if ((ret = mbedtls_x509_crt_parse_der(certs, start, len1)) < 0) { + return MBEDTLS_ERR_PKCS7_INVALID_CERT; + } + + *p = end_cert; + + /* + * Since in this version we strictly support single certificate, and reaching + * here implies we have parsed successfully, we return 1. + */ + return 1; +} + +/** + * EncryptedDigest ::= OCTET STRING + **/ +static int pkcs7_get_signature(unsigned char **p, unsigned char *end, + mbedtls_pkcs7_buf *signature) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING); + if (ret != 0) { + return ret; + } + + signature->tag = MBEDTLS_ASN1_OCTET_STRING; + signature->len = len; + signature->p = *p; + + *p = *p + len; + + return 0; +} + +static void pkcs7_free_signer_info(mbedtls_pkcs7_signer_info *signer) +{ + mbedtls_x509_name *name_cur; + mbedtls_x509_name *name_prv; + + if (signer == NULL) { + return; + } + + name_cur = signer->issuer.next; + while (name_cur != NULL) { + name_prv = name_cur; + name_cur = name_cur->next; + mbedtls_free(name_prv); + } + signer->issuer.next = NULL; +} + +/** + * SignerInfo ::= SEQUENCE { + * version Version; + * issuerAndSerialNumber IssuerAndSerialNumber, + * digestAlgorithm DigestAlgorithmIdentifier, + * authenticatedAttributes + * [0] IMPLICIT Attributes OPTIONAL, + * digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier, + * encryptedDigest EncryptedDigest, + * unauthenticatedAttributes + * [1] IMPLICIT Attributes OPTIONAL, + * Returns 0 if the signerInfo is valid. + * Return negative error code for failure. + * Structure must not contain vales for authenticatedAttributes + * and unauthenticatedAttributes. + **/ +static int pkcs7_get_signer_info(unsigned char **p, unsigned char *end, + mbedtls_pkcs7_signer_info *signer, + mbedtls_x509_buf *alg) +{ + unsigned char *end_signer, *end_issuer_and_sn; + int asn1_ret = 0, ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + asn1_ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED + | MBEDTLS_ASN1_SEQUENCE); + if (asn1_ret != 0) { + goto out; + } + + end_signer = *p + len; + + ret = pkcs7_get_version(p, end_signer, &signer->version); + if (ret != 0) { + goto out; + } + + asn1_ret = mbedtls_asn1_get_tag(p, end_signer, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + if (asn1_ret != 0) { + goto out; + } + + end_issuer_and_sn = *p + len; + /* Parsing IssuerAndSerialNumber */ + signer->issuer_raw.p = *p; + + asn1_ret = mbedtls_asn1_get_tag(p, end_issuer_and_sn, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + if (asn1_ret != 0) { + goto out; + } + + ret = mbedtls_x509_get_name(p, *p + len, &signer->issuer); + if (ret != 0) { + goto out; + } + + signer->issuer_raw.len = *p - signer->issuer_raw.p; + + ret = mbedtls_x509_get_serial(p, end_issuer_and_sn, &signer->serial); + if (ret != 0) { + goto out; + } + + /* ensure no extra or missing bytes */ + if (*p != end_issuer_and_sn) { + ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO; + goto out; + } + + ret = pkcs7_get_digest_algorithm(p, end_signer, &signer->alg_identifier); + if (ret != 0) { + goto out; + } + + /* Check that the digest algorithm used matches the one provided earlier */ + if (signer->alg_identifier.tag != alg->tag || + signer->alg_identifier.len != alg->len || + memcmp(signer->alg_identifier.p, alg->p, alg->len) != 0) { + ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO; + goto out; + } + + /* Assume authenticatedAttributes is nonexistent */ + ret = pkcs7_get_digest_algorithm(p, end_signer, &signer->sig_alg_identifier); + if (ret != 0) { + goto out; + } + + ret = pkcs7_get_signature(p, end_signer, &signer->sig); + if (ret != 0) { + goto out; + } + + /* Do not permit any unauthenticated attributes */ + if (*p != end_signer) { + ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO; + } + +out: + if (asn1_ret != 0 || ret != 0) { + pkcs7_free_signer_info(signer); + ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO, + asn1_ret); + } + + return ret; +} + +/** + * SignerInfos ::= SET of SignerInfo + * Return number of signers added to the signed data, + * 0 or higher is valid. + * Return negative error code for failure. + **/ +static int pkcs7_get_signers_info_set(unsigned char **p, unsigned char *end, + mbedtls_pkcs7_signer_info *signers_set, + mbedtls_x509_buf *digest_alg) +{ + unsigned char *end_set; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int count = 0; + size_t len = 0; + + ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED + | MBEDTLS_ASN1_SET); + if (ret != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO, ret); + } + + /* Detect zero signers */ + if (len == 0) { + return 0; + } + + end_set = *p + len; + + ret = pkcs7_get_signer_info(p, end_set, signers_set, digest_alg); + if (ret != 0) { + return ret; + } + count++; + + mbedtls_pkcs7_signer_info *prev = signers_set; + while (*p != end_set) { + mbedtls_pkcs7_signer_info *signer = + mbedtls_calloc(1, sizeof(mbedtls_pkcs7_signer_info)); + if (!signer) { + ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED; + goto cleanup; + } + + ret = pkcs7_get_signer_info(p, end_set, signer, digest_alg); + if (ret != 0) { + mbedtls_free(signer); + goto cleanup; + } + prev->next = signer; + prev = signer; + count++; + } + + return count; + +cleanup: + pkcs7_free_signer_info(signers_set); + mbedtls_pkcs7_signer_info *signer = signers_set->next; + while (signer != NULL) { + prev = signer; + signer = signer->next; + pkcs7_free_signer_info(prev); + mbedtls_free(prev); + } + signers_set->next = NULL; + return ret; +} + +/** + * SignedData ::= SEQUENCE { + * version Version, + * digestAlgorithms DigestAlgorithmIdentifiers, + * contentInfo ContentInfo, + * certificates + * [0] IMPLICIT ExtendedCertificatesAndCertificates + * OPTIONAL, + * crls + * [0] IMPLICIT CertificateRevocationLists OPTIONAL, + * signerInfos SignerInfos } + */ +static int pkcs7_get_signed_data(unsigned char *buf, size_t buflen, + mbedtls_pkcs7_signed_data *signed_data) +{ + unsigned char *p = buf; + unsigned char *end = buf + buflen; + unsigned char *end_content_info = NULL; + size_t len = 0; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_md_type_t md_alg; + + ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED + | MBEDTLS_ASN1_SEQUENCE); + if (ret != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret); + } + + if (p + len != end) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + + /* Get version of signed data */ + ret = pkcs7_get_version(&p, end, &signed_data->version); + if (ret != 0) { + return ret; + } + + /* Get digest algorithm */ + ret = pkcs7_get_digest_algorithm_set(&p, end, + &signed_data->digest_alg_identifiers); + if (ret != 0) { + return ret; + } + + ret = mbedtls_oid_get_md_alg(&signed_data->digest_alg_identifiers, &md_alg); + if (ret != 0) { + return MBEDTLS_ERR_PKCS7_INVALID_ALG; + } + + mbedtls_pkcs7_buf content_type; + memset(&content_type, 0, sizeof(content_type)); + ret = pkcs7_get_content_info_type(&p, end, &end_content_info, &content_type); + if (ret != 0) { + return ret; + } + if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS7_DATA, &content_type)) { + return MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO; + } + + if (p != end_content_info) { + /* Determine if valid content is present */ + ret = mbedtls_asn1_get_tag(&p, + end_content_info, + &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC); + if (ret != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret); + } + p += len; + if (p != end_content_info) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret); + } + /* Valid content is present - this is not supported */ + return MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE; + } + + /* Look for certificates, there may or may not be any */ + mbedtls_x509_crt_init(&signed_data->certs); + ret = pkcs7_get_certificates(&p, end, &signed_data->certs); + if (ret < 0) { + return ret; + } + + signed_data->no_of_certs = ret; + + /* + * Currently CRLs are not supported. If CRL exist, the parsing will fail + * at next step of getting signers info and return error as invalid + * signer info. + */ + + signed_data->no_of_crls = 0; + + /* Get signers info */ + ret = pkcs7_get_signers_info_set(&p, + end, + &signed_data->signers, + &signed_data->digest_alg_identifiers); + if (ret < 0) { + return ret; + } + + signed_data->no_of_signers = ret; + + /* Don't permit trailing data */ + if (p != end) { + return MBEDTLS_ERR_PKCS7_INVALID_FORMAT; + } + + return 0; +} + +int mbedtls_pkcs7_parse_der(mbedtls_pkcs7 *pkcs7, const unsigned char *buf, + const size_t buflen) +{ + unsigned char *p; + unsigned char *end; + size_t len = 0; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if (pkcs7 == NULL) { + return MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA; + } + + /* make an internal copy of the buffer for parsing */ + pkcs7->raw.p = p = mbedtls_calloc(1, buflen); + if (pkcs7->raw.p == NULL) { + ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED; + goto out; + } + memcpy(p, buf, buflen); + pkcs7->raw.len = buflen; + end = p + buflen; + + ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED + | MBEDTLS_ASN1_SEQUENCE); + if (ret != 0) { + ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret); + goto out; + } + + if ((size_t) (end - p) != len) { + ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + goto out; + } + + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID)) != 0) { + if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { + goto out; + } + p = pkcs7->raw.p; + len = buflen; + goto try_data; + } + + if (MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_SIGNED_DATA, p, len)) { + /* OID is not MBEDTLS_OID_PKCS7_SIGNED_DATA, which is the only supported feature */ + if (!MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_DATA, p, len) + || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_ENCRYPTED_DATA, p, len) + || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_ENVELOPED_DATA, p, len) + || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_SIGNED_AND_ENVELOPED_DATA, p, len) + || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_DIGESTED_DATA, p, len)) { + /* OID is valid according to the spec, but unsupported */ + ret = MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE; + } else { + /* OID is invalid according to the spec */ + ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA; + } + goto out; + } + + p += len; + + ret = pkcs7_get_next_content_len(&p, end, &len); + if (ret != 0) { + goto out; + } + + /* ensure no extra/missing data */ + if (p + len != end) { + ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA; + goto out; + } + +try_data: + ret = pkcs7_get_signed_data(p, len, &pkcs7->signed_data); + if (ret != 0) { + goto out; + } + + ret = MBEDTLS_PKCS7_SIGNED_DATA; + +out: + if (ret < 0) { + mbedtls_pkcs7_free(pkcs7); + } + + return ret; +} + +static int mbedtls_pkcs7_data_or_hash_verify(mbedtls_pkcs7 *pkcs7, + const mbedtls_x509_crt *cert, + const unsigned char *data, + size_t datalen, + const int is_data_hash) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *hash; + mbedtls_pk_context pk_cxt = cert->pk; + const mbedtls_md_info_t *md_info; + mbedtls_md_type_t md_alg; + mbedtls_pkcs7_signer_info *signer; + + if (pkcs7->signed_data.no_of_signers == 0) { + return MBEDTLS_ERR_PKCS7_INVALID_CERT; + } + + if (mbedtls_x509_time_is_past(&cert->valid_to) || + mbedtls_x509_time_is_future(&cert->valid_from)) { + return MBEDTLS_ERR_PKCS7_CERT_DATE_INVALID; + } + + ret = mbedtls_oid_get_md_alg(&pkcs7->signed_data.digest_alg_identifiers, &md_alg); + if (ret != 0) { + return ret; + } + + md_info = mbedtls_md_info_from_type(md_alg); + if (md_info == NULL) { + return MBEDTLS_ERR_PKCS7_VERIFY_FAIL; + } + + hash = mbedtls_calloc(mbedtls_md_get_size(md_info), 1); + if (hash == NULL) { + return MBEDTLS_ERR_PKCS7_ALLOC_FAILED; + } + + /* BEGIN must free hash before jumping out */ + if (is_data_hash) { + if (datalen != mbedtls_md_get_size(md_info)) { + ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL; + } else { + memcpy(hash, data, datalen); + } + } else { + ret = mbedtls_md(md_info, data, datalen, hash); + } + if (ret != 0) { + mbedtls_free(hash); + return MBEDTLS_ERR_PKCS7_VERIFY_FAIL; + } + + /* assume failure */ + ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL; + + /* + * Potential TODOs + * Currently we iterate over all signers and return success if any of them + * verify. + * + * However, we could make this better by checking against the certificate's + * identification and SignerIdentifier fields first. That would also allow + * us to distinguish between 'no signature for key' and 'signature for key + * failed to validate'. + */ + for (signer = &pkcs7->signed_data.signers; signer; signer = signer->next) { + ret = mbedtls_pk_verify(&pk_cxt, md_alg, hash, + mbedtls_md_get_size(md_info), + signer->sig.p, signer->sig.len); + + if (ret == 0) { + break; + } + } + + mbedtls_free(hash); + /* END must free hash before jumping out */ + return ret; +} + +int mbedtls_pkcs7_signed_data_verify(mbedtls_pkcs7 *pkcs7, + const mbedtls_x509_crt *cert, + const unsigned char *data, + size_t datalen) +{ + if (data == NULL) { + return MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA; + } + return mbedtls_pkcs7_data_or_hash_verify(pkcs7, cert, data, datalen, 0); +} + +int mbedtls_pkcs7_signed_hash_verify(mbedtls_pkcs7 *pkcs7, + const mbedtls_x509_crt *cert, + const unsigned char *hash, + size_t hashlen) +{ + if (hash == NULL) { + return MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA; + } + return mbedtls_pkcs7_data_or_hash_verify(pkcs7, cert, hash, hashlen, 1); +} + +/* + * Unallocate all pkcs7 data + */ +void mbedtls_pkcs7_free(mbedtls_pkcs7 *pkcs7) +{ + mbedtls_pkcs7_signer_info *signer_cur; + mbedtls_pkcs7_signer_info *signer_prev; + + if (pkcs7 == NULL || pkcs7->raw.p == NULL) { + return; + } + + mbedtls_free(pkcs7->raw.p); + + mbedtls_x509_crt_free(&pkcs7->signed_data.certs); + mbedtls_x509_crl_free(&pkcs7->signed_data.crl); + + signer_cur = pkcs7->signed_data.signers.next; + pkcs7_free_signer_info(&pkcs7->signed_data.signers); + while (signer_cur != NULL) { + signer_prev = signer_cur; + signer_cur = signer_prev->next; + pkcs7_free_signer_info(signer_prev); + mbedtls_free(signer_prev); + } + + pkcs7->raw.p = NULL; +} + +#endif 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..ccca692 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/pkparse.c @@ -0,0 +1,1528 @@ +/* + * 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 + +#include "mbedtls/platform.h" + +#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; + + if ((f = fopen(path, "rb")) == NULL) { + return MBEDTLS_ERR_PK_FILE_IO_ERROR; + } + + /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ + mbedtls_setbuf(f, NULL); + + 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 (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + 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; + } + + if (pwd == NULL) { + ret = mbedtls_pk_parse_key(ctx, buf, n, NULL, 0, f_rng, p_rng); + } else { + ret = mbedtls_pk_parse_key(ctx, buf, n, + (const unsigned char *) pwd, strlen(pwd), f_rng, p_rng); + } + + 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; + + 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: + /* The API respecting lifecycle for mbedtls_ecp_group struct is + * _init(), _load() and _free(). In pk_group_id_from_specified() the + * temporary grp breaks that flow and it's members are populated + * by pk_group_id_from_group(). As such mbedtls_ecp_group_free() + * which is assuming a group populated by _setup() may not clean-up + * properly -> Manually free it's members. + */ + mbedtls_mpi_free(&grp.N); + mbedtls_mpi_free(&grp.P); + mbedtls_mpi_free(&grp.A); + mbedtls_mpi_free(&grp.B); + mbedtls_ecp_point_free(&grp.G); + + 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; + + 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 (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int version, pubkey_done; + size_t len; + mbedtls_asn1_buf params = { 0, 0, NULL }; + 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, + f_rng, p_rng)) != 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 (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + 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; + +#if !defined(MBEDTLS_ECP_C) + (void) f_rng; + (void) p_rng; +#endif + + /* + * 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, f_rng, p_rng)) != 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 (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + 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 +#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, f_rng, p_rng); +} +#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 (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + 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 + + if (keylen == 0) { + return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; + } + +#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, + f_rng, p_rng)) != 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, f_rng, p_rng)) != 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, f_rng, p_rng)) != 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) + if (pwdlen != 0) { + 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, f_rng, p_rng); + + 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, f_rng, p_rng); + 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, f_rng, p_rng) == 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 + + if (keylen == 0) { + return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; + } + +#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..2194c97 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/pkwrite.c @@ -0,0 +1,538 @@ +/* + * 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_RSA_C) || defined(MBEDTLS_ECP_C) +#include "pkwrite.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 +#include "mbedtls/platform.h" + +#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; + +#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; + mbedtls_svc_key_id_t *key_id = (mbedtls_svc_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(const 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; + + if (size == 0) { + return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; + } + + 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; + mbedtls_svc_key_id_t key_id; + psa_ecc_family_t curve; + size_t bits; + + key_id = *((mbedtls_svc_key_id_t *) key->pk_ctx); + if (PSA_SUCCESS != psa_get_key_attributes(key_id, &attributes)) { + return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + } + key_type = psa_get_key_type(&attributes); + bits = psa_get_key_bits(&attributes); + psa_reset_key_attributes(&attributes); + + if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type)) { + 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; + } else if (PSA_KEY_TYPE_IS_RSA(key_type)) { + /* The rest of the function works as for legacy RSA contexts. */ + pk_type = MBEDTLS_PK_RSA; + } else { + return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; + } + } +#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(const mbedtls_pk_context *key, unsigned char *buf, size_t size) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *c; + size_t len = 0; + + if (size == 0) { + return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; + } + + 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" + +#define PUB_DER_MAX_BYTES \ + (MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES > MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES ? \ + MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES : MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES) +#define PRV_DER_MAX_BYTES \ + (MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES > MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES ? \ + MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES : MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES) + +int mbedtls_pk_write_pubkey_pem(const 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; + + 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(const 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; + + 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/pkwrite.h b/optee/optee_os/lib/libmbedtls/mbedtls/library/pkwrite.h new file mode 100644 index 0000000..8aebd0c --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/pkwrite.h @@ -0,0 +1,108 @@ +/** + * \file pkwrite.h + * + * \brief Internal defines shared by the PK write 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. + */ + +#ifndef MBEDTLS_PK_WRITE_H +#define MBEDTLS_PK_WRITE_H + +#include "mbedtls/build_info.h" + +#include "mbedtls/pk.h" + +/* + * 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 MBEDTLS_PK_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 MBEDTLS_MPI_MAX_SIZE_2 (MBEDTLS_MPI_MAX_SIZE / 2 + \ + MBEDTLS_MPI_MAX_SIZE % 2) +#define MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES (47 + 3 * MBEDTLS_MPI_MAX_SIZE \ + + 5 * MBEDTLS_MPI_MAX_SIZE_2) + +#else /* MBEDTLS_RSA_C */ + +#define MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES 0 +#define MBEDTLS_PK_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 MBEDTLS_PK_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 MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES (29 + 3 * MBEDTLS_ECP_MAX_BYTES) + +#else /* MBEDTLS_ECP_C */ + +#define MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES 0 +#define MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES 0 + +#endif /* MBEDTLS_ECP_C */ + +#endif /* MBEDTLS_PK_WRITE_H */ 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..b15b7b2 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/platform.c @@ -0,0 +1,414 @@ +/* + * 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_SETBUF_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_SETBUF) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static void platform_setbuf_uninit(FILE *stream, char *buf) +{ + ((void) stream); + ((void) buf); +} + +#define MBEDTLS_PLATFORM_STD_SETBUF platform_setbuf_uninit +#endif /* !MBEDTLS_PLATFORM_STD_SETBUF */ +void (*mbedtls_setbuf)(FILE *stream, char *buf) = MBEDTLS_PLATFORM_STD_SETBUF; + +int mbedtls_platform_set_setbuf(void (*setbuf_func)(FILE *stream, char *buf)) +{ + mbedtls_setbuf = setbuf_func; + return 0; +} +#endif /* MBEDTLS_PLATFORM_SETBUF_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; + } + + /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ + mbedtls_setbuf(file, NULL); + + 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; + } + + /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ + mbedtls_setbuf(file, NULL); + + 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..f891cd4 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/platform_util.c @@ -0,0 +1,221 @@ +/* + * 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 + * mbedtls_config.h, which pulls in glibc's features.h. Harmless on other platforms + * except OpenBSD, where it stops us accessing explicit_bzero. + */ +#if !defined(_POSIX_C_SOURCE) && !defined(__OpenBSD__) +#define _POSIX_C_SOURCE 200112L +#endif + +#if !defined(_GNU_SOURCE) +/* Clang requires this to get support for explicit_bzero */ +#define _GNU_SOURCE +#endif + +#include "common.h" + +#include "mbedtls/platform_util.h" +#include "mbedtls/platform.h" +#include "mbedtls/threading.h" + +#include + +#ifndef __STDC_WANT_LIB_EXT1__ +#define __STDC_WANT_LIB_EXT1__ 1 /* Ask for the C11 gmtime_s() and memset_s() if available */ +#endif +#include + +#if defined(_WIN32) +#include +#endif + +// Detect platforms known to support explicit_bzero() +#if defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 25) +#define MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO 1 +#elif (defined(__FreeBSD__) && (__FreeBSD_version >= 1100037)) || defined(__OpenBSD__) +#define MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO 1 +#endif + +#if !defined(MBEDTLS_PLATFORM_ZEROIZE_ALT) + +#undef HAVE_MEMORY_SANITIZER +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +#include +#define HAVE_MEMORY_SANITIZER +#endif +#endif + +/* + * Where possible, we try to detect the presence of a platform-provided + * secure memset, such as explicit_bzero(), that is safe against being optimized + * out, and use that. + * + * For other platforms, we provide an implementation that aims not to 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 + * the memset() call 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. + */ +#if !defined(MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO) && !defined(__STDC_LIB_EXT1__) \ + && !defined(_WIN32) +static void *(*const volatile memset_func)(void *, int, size_t) = memset; +#endif + +void mbedtls_platform_zeroize(void *buf, size_t len) +{ + MBEDTLS_INTERNAL_VALIDATE(len == 0 || buf != NULL); + + if (len > 0) { +#if defined(MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO) + explicit_bzero(buf, len); +#if defined(HAVE_MEMORY_SANITIZER) + /* You'd think that Msan would recognize explicit_bzero() as + * equivalent to bzero(), but it actually doesn't on several + * platforms, including Linux (Ubuntu 20.04). + * https://github.com/google/sanitizers/issues/1507 + * https://github.com/openssh/openssh-portable/commit/74433a19bb6f4cef607680fa4d1d7d81ca3826aa + */ + __msan_unpoison(buf, len); +#endif +#elif defined(__STDC_LIB_EXT1__) + memset_s(buf, len, 0, len); +#elif defined(_WIN32) + SecureZeroMemory(buf, len); +#else + memset_func(buf, 0, len); +#endif + } +} +#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)) || \ + (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)) +#define PLATFORM_UTIL_USE_GMTIME +#endif + +#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(PLATFORM_UTIL_USE_GMTIME) +#if defined(__STDC_LIB_EXT1__) + return (gmtime_s(tt, tm_buf) == 0) ? NULL : tm_buf; +#else + /* MSVC and mingw64 argument order and return value are inconsistent with the C11 standard */ + return (gmtime_s(tm_buf, tt) == 0) ? tm_buf : NULL; +#endif +#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 */ + +#if defined(MBEDTLS_TEST_HOOKS) +void (*mbedtls_test_hook_test_fail)(const char *, int, const char *); +#endif /* MBEDTLS_TEST_HOOKS */ + +/* + * Provide external definitions of some inline functions so that the compiler + * has the option to not inline them + */ +extern inline void mbedtls_xor(unsigned char *r, + const unsigned char *a, + const unsigned char *b, + size_t n); + +extern inline uint16_t mbedtls_get_unaligned_uint16(const void *p); + +extern inline void mbedtls_put_unaligned_uint16(void *p, uint16_t x); + +extern inline uint32_t mbedtls_get_unaligned_uint32(const void *p); + +extern inline void mbedtls_put_unaligned_uint32(void *p, uint32_t x); + +extern inline uint64_t mbedtls_get_unaligned_uint64(const void *p); + +extern inline void mbedtls_put_unaligned_uint64(void *p, uint64_t x); 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..f4e1d3f --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/poly1305.c @@ -0,0 +1,504 @@ +/** + * \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 + +#include "mbedtls/platform.h" + +#if !defined(MBEDTLS_POLY1305_ALT) + +#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) +{ + 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]) +{ + /* 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; + + 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]) +{ + /* 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; + + 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..ba97c1f --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ripemd160.c @@ -0,0 +1,498 @@ +/* + * 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 + +#include "mbedtls/platform.h" + +#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(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_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; +} + +#endif /* !MBEDTLS_RIPEMD160_PROCESS_ALT */ + +/* + * RIPEMD-160 process buffer + */ +int mbedtls_ripemd160_update(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; +} + +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(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(ctx, ripemd160_padding, padn); + if (ret != 0) { + return ret; + } + + ret = mbedtls_ripemd160_update(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; +} + +#endif /* ! MBEDTLS_RIPEMD160_ALT */ + +/* + * output = RIPEMD-160( input buffer ) + */ +int mbedtls_ripemd160(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(&ctx)) != 0) { + goto exit; + } + + if ((ret = mbedtls_ripemd160_update(&ctx, input, ilen)) != 0) { + goto exit; + } + + if ((ret = mbedtls_ripemd160_finish(&ctx, output)) != 0) { + goto exit; + } + +exit: + mbedtls_ripemd160_free(&ctx); + + return ret; +} + +#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(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..40dbcab --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/rsa.c @@ -0,0 +1,2588 @@ +/* + * 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 "rsa_alt_helpers.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 "hash_info.h" + +#include + +#if defined(MBEDTLS_PKCS1_V15) && !defined(__OpenBSD__) && !defined(__NetBSD__) +#include +#endif + +/* We use MD first if it's available (for compatibility reasons) + * and "fall back" to PSA otherwise (which needs psa_crypto_init()). */ +#if defined(MBEDTLS_PKCS1_V21) +#if !defined(MBEDTLS_MD_C) +#include "psa/crypto.h" +#include "mbedtls/psa_util.h" +#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \ + psa_to_md_errors, \ + psa_generic_status_to_mbedtls) +#endif /* !MBEDTLS_MD_C */ +#endif /* MBEDTLS_PKCS1_V21 */ + +#include "mbedtls/platform.h" + +#include + +#if !defined(MBEDTLS_RSA_ALT) + +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; + + 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; + + 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; + + 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; + + /* 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; + + /* 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; + + /* 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) +{ + memset(ctx, 0, sizeof(mbedtls_rsa_context)); + + ctx->padding = MBEDTLS_RSA_PKCS_V15; + ctx->hash_id = MBEDTLS_MD_NONE; + +#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 + */ +int mbedtls_rsa_set_padding(mbedtls_rsa_context *ctx, int padding, + mbedtls_md_type_t hash_id) +{ + switch (padding) { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + break; +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + break; +#endif + default: + return MBEDTLS_ERR_RSA_INVALID_PADDING; + } + +#if defined(MBEDTLS_PKCS1_V21) + if ((padding == MBEDTLS_RSA_PKCS_V21) && + (hash_id != MBEDTLS_MD_NONE)) { + /* Just make sure this hash is supported in this build. */ + if (mbedtls_hash_info_psa_from_md(hash_id) == PSA_ALG_NONE) { + return MBEDTLS_ERR_RSA_INVALID_PADDING; + } + } +#endif /* MBEDTLS_PKCS1_V21 */ + + ctx->padding = padding; + ctx->hash_id = hash_id; + + return 0; +} + +/* + * Get padding mode of initialized RSA context + */ +int mbedtls_rsa_get_padding_mode(const mbedtls_rsa_context *ctx) +{ + return ctx->padding; +} + +/* + * Get hash identifier of mbedtls_md_type_t type + */ +int mbedtls_rsa_get_md_alg(const mbedtls_rsa_context *ctx) +{ + return ctx->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; + + /* + * 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) +{ + 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) +{ + 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) +{ + 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; + + 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; + + if (f_rng == NULL) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } + + if (rsa_check_context(ctx, 1 /* private key checks */, + 1 /* blinding on */) != 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 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)); + + /* + * 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 */ + + /* + * 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 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_alg message digest to use + */ +static int mgf_mask(unsigned char *dst, size_t dlen, unsigned char *src, + size_t slen, mbedtls_md_type_t md_alg) +{ + unsigned char counter[4]; + unsigned char *p; + unsigned int hlen; + size_t i, use_len; + unsigned char mask[MBEDTLS_HASH_MAX_SIZE]; +#if defined(MBEDTLS_MD_C) + int ret = 0; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + + mbedtls_md_init(&md_ctx); + md_info = mbedtls_md_info_from_type(md_alg); + if (md_info == NULL) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } + + mbedtls_md_init(&md_ctx); + if ((ret = mbedtls_md_setup(&md_ctx, md_info, 0)) != 0) { + goto exit; + } + + hlen = mbedtls_md_get_size(md_info); +#else + psa_hash_operation_t op = PSA_HASH_OPERATION_INIT; + psa_algorithm_t alg = mbedtls_psa_translate_md(md_alg); + psa_status_t status = PSA_SUCCESS; + size_t out_len; + + hlen = PSA_HASH_LENGTH(alg); +#endif + + memset(mask, 0, sizeof(mask)); + memset(counter, 0, 4); + + /* Generate and apply dbMask */ + p = dst; + + while (dlen > 0) { + use_len = hlen; + if (dlen < hlen) { + use_len = dlen; + } + +#if defined(MBEDTLS_MD_C) + 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; + } +#else + if ((status = psa_hash_setup(&op, alg)) != PSA_SUCCESS) { + goto exit; + } + if ((status = psa_hash_update(&op, src, slen)) != PSA_SUCCESS) { + goto exit; + } + if ((status = psa_hash_update(&op, counter, 4)) != PSA_SUCCESS) { + goto exit; + } + status = psa_hash_finish(&op, mask, sizeof(mask), &out_len); + if (status != PSA_SUCCESS) { + goto exit; + } +#endif + + for (i = 0; i < use_len; ++i) { + *p++ ^= mask[i]; + } + + counter[3]++; + + dlen -= use_len; + } + +exit: + mbedtls_platform_zeroize(mask, sizeof(mask)); +#if defined(MBEDTLS_MD_C) + mbedtls_md_free(&md_ctx); + + return ret; +#else + psa_hash_abort(&op); + + return PSA_TO_MBEDTLS_ERR(status); +#endif +} + +/** + * Generate Hash(M') as in RFC 8017 page 43 points 5 and 6. + * + * \param hash the input hash + * \param hlen length of the input hash + * \param salt the input salt + * \param slen length of the input salt + * \param out the output buffer - must be large enough for \p md_alg + * \param md_alg message digest to use + */ +static int hash_mprime(const unsigned char *hash, size_t hlen, + const unsigned char *salt, size_t slen, + unsigned char *out, mbedtls_md_type_t md_alg) +{ + const unsigned char zeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + +#if defined(MBEDTLS_MD_C) + mbedtls_md_context_t md_ctx; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + 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; + } + + mbedtls_md_init(&md_ctx); + if ((ret = mbedtls_md_setup(&md_ctx, md_info, 0)) != 0) { + goto exit; + } + if ((ret = mbedtls_md_starts(&md_ctx)) != 0) { + goto exit; + } + if ((ret = mbedtls_md_update(&md_ctx, zeros, sizeof(zeros))) != 0) { + goto exit; + } + if ((ret = mbedtls_md_update(&md_ctx, hash, hlen)) != 0) { + goto exit; + } + if ((ret = mbedtls_md_update(&md_ctx, salt, slen)) != 0) { + goto exit; + } + if ((ret = mbedtls_md_finish(&md_ctx, out)) != 0) { + goto exit; + } + +exit: + mbedtls_md_free(&md_ctx); + + return ret; +#else + psa_hash_operation_t op = PSA_HASH_OPERATION_INIT; + psa_algorithm_t alg = mbedtls_psa_translate_md(md_alg); + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t out_size = PSA_HASH_LENGTH(alg); + size_t out_len; + + if ((status = psa_hash_setup(&op, alg)) != PSA_SUCCESS) { + goto exit; + } + if ((status = psa_hash_update(&op, zeros, sizeof(zeros))) != PSA_SUCCESS) { + goto exit; + } + if ((status = psa_hash_update(&op, hash, hlen)) != PSA_SUCCESS) { + goto exit; + } + if ((status = psa_hash_update(&op, salt, slen)) != PSA_SUCCESS) { + goto exit; + } + status = psa_hash_finish(&op, out, out_size, &out_len); + if (status != PSA_SUCCESS) { + goto exit; + } + +exit: + psa_hash_abort(&op); + + return PSA_TO_MBEDTLS_ERR(status); +#endif /* !MBEDTLS_MD_C */ +} + +/** + * Compute a hash. + * + * \param md_alg algorithm to use + * \param input input message to hash + * \param ilen input length + * \param output the output buffer - must be large enough for \p md_alg + */ +static int compute_hash(mbedtls_md_type_t md_alg, + const unsigned char *input, size_t ilen, + unsigned char *output) +{ +#if defined(MBEDTLS_MD_C) + const mbedtls_md_info_t *md_info; + + md_info = mbedtls_md_info_from_type(md_alg); + if (md_info == NULL) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } + + return mbedtls_md(md_info, input, ilen, output); +#else + psa_algorithm_t alg = mbedtls_psa_translate_md(md_alg); + psa_status_t status; + size_t out_size = PSA_HASH_LENGTH(alg); + size_t out_len; + + status = psa_hash_compute(alg, input, ilen, output, out_size, &out_len); + + return PSA_TO_MBEDTLS_ERR(status); +#endif /* !MBEDTLS_MD_C */ +} +#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, + 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; + + if (f_rng == NULL) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } + + hlen = mbedtls_hash_info_get_size((mbedtls_md_type_t) ctx->hash_id); + if (hlen == 0) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } + + olen = ctx->len; + + /* 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 */ + ret = compute_hash((mbedtls_md_type_t) ctx->hash_id, label, label_len, p); + if (ret != 0) { + return ret; + } + p += hlen; + p += olen - 2 * hlen - 2 - ilen; + *p++ = 1; + if (ilen != 0) { + memcpy(p, input, ilen); + } + + /* maskedDB: Apply dbMask to DB */ + if ((ret = mgf_mask(output + hlen + 1, olen - hlen - 1, output + 1, hlen, + ctx->hash_id)) != 0) { + return ret; + } + + /* maskedSeed: Apply seedMask to seed */ + if ((ret = mgf_mask(output + 1, hlen, output + hlen + 1, olen - hlen - 1, + ctx->hash_id)) != 0) { + return ret; + } + + return mbedtls_rsa_public(ctx, 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, 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; + + 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 (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++; + } + + *p++ = 0; + if (ilen != 0) { + memcpy(p, input, ilen); + } + + return mbedtls_rsa_public(ctx, 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, + size_t ilen, + const unsigned char *input, + unsigned char *output) +{ + 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, + 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, 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, + 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_HASH_MAX_SIZE]; + unsigned int hlen; + + /* + * Parameters sanity checks + */ + if (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; + } + + hlen = mbedtls_hash_info_get_size((mbedtls_md_type_t) ctx->hash_id); + if (hlen == 0) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } + + // checking for integer underflow + if (2 * hlen + 2 > ilen) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } + + /* + * RSA operation + */ + if( ctx->P.n == 0 ) + ret = mbedtls_rsa_private( ctx, NULL, NULL, input, buf ); + else + ret = mbedtls_rsa_private(ctx, f_rng, p_rng, input, buf); + + if (ret != 0) { + goto cleanup; + } + + /* + * Unmask data and generate lHash + */ + /* seed: Apply seedMask to maskedSeed */ + if ((ret = mgf_mask(buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1, + ctx->hash_id)) != 0 || + /* DB: Apply dbMask to maskedDB */ + (ret = mgf_mask(buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen, + ctx->hash_id)) != 0) { + goto cleanup; + } + + /* Generate lHash */ + ret = compute_hash((mbedtls_md_type_t) ctx->hash_id, + label, label_len, lhash); + if (ret != 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, + 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]; + + ilen = ctx->len; + + if (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 = mbedtls_rsa_private(ctx, f_rng, p_rng, input, buf); + + if (ret != 0) { + goto cleanup; + } + + ret = mbedtls_ct_rsaes_pkcs1_v15_unpadding(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, + size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len) +{ + 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, 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, 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, + 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; + + if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } + + if (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 */ + size_t exp_hashlen = mbedtls_hash_info_get_size(md_alg); + if (exp_hashlen == 0) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } + + if (hashlen != exp_hashlen) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } + } + + hlen = mbedtls_hash_info_get_size((mbedtls_md_type_t) ctx->hash_id); + if (hlen == 0) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } + + 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; + + /* Generate H = Hash( M' ) */ + ret = hash_mprime(hash, hashlen, salt, slen, p, ctx->hash_id); + if (ret != 0) { + return ret; + } + + /* Compensate for boundary condition when applying mask */ + if (msb % 8 == 0) { + offset = 1; + } + + /* maskedDB: Apply dbMask to DB */ + ret = mgf_mask(sig + offset, olen - hlen - 1 - offset, p, hlen, + ctx->hash_id); + if (ret != 0) { + return ret; + } + + msb = mbedtls_mpi_bitlen(&ctx->N) - 1; + sig[0] &= 0xFF >> (olen * 8 - msb); + + p += hlen; + *p++ = 0xBC; + + if (ctx->P.n == 0) + return mbedtls_rsa_private(ctx, NULL, NULL, sig, sig); + + return 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, 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, + 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, 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. Must match md_alg if that's not 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. + * - 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) { + unsigned char md_size = mbedtls_hash_info_get_size(md_alg); + if (md_size == 0) { + 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; + } + + if (hashlen != md_size) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } + + /* 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, + 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; + + if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } + + if (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; + } + + /* 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, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig) +{ + if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } + + 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, + 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, 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, + 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_HASH_MAX_SIZE]; + unsigned int hlen; + size_t observed_salt_len, msb; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE] = { 0 }; + + if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } + + siglen = ctx->len; + + if (siglen < 16 || siglen > sizeof(buf)) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } + + ret = mbedtls_rsa_public(ctx, 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 */ + size_t exp_hashlen = mbedtls_hash_info_get_size(md_alg); + if (exp_hashlen == 0) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } + + if (hashlen != exp_hashlen) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } + } + + hlen = mbedtls_hash_info_get_size(mgf1_hash_id); + if (hlen == 0) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } + + /* + * 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; + + ret = mgf_mask(p, siglen - hlen - 1, hash_start, hlen, mgf1_hash_id); + if (ret != 0) { + return ret; + } + + buf[0] &= 0xFF >> (siglen * 8 - msb); + + while (p < hash_start - 1 && *p == 0) { + p++; + } + + if (*p++ != 0x01) { + return MBEDTLS_ERR_RSA_INVALID_PADDING; + } + + observed_salt_len = hash_start - p; + + if (expected_salt_len != MBEDTLS_RSA_SALT_LEN_ANY && + observed_salt_len != (size_t) expected_salt_len) { + return MBEDTLS_ERR_RSA_INVALID_PADDING; + } + + /* + * Generate H = Hash( M' ) + */ + ret = hash_mprime(hash, hashlen, p, observed_salt_len, + result, mgf1_hash_id); + if (ret != 0) { + return ret; + } + + if (FTMN_CALLEE_DONE_MEMCMP(memcmp, hash_start, result, hlen) != 0) { + return MBEDTLS_ERR_RSA_VERIFY_FAILED; + } + + return 0; +} + +/* + * Simplified PKCS#1 v2.1 RSASSA-PSS-VERIFY function + */ +int mbedtls_rsa_rsassa_pss_verify(mbedtls_rsa_context *ctx, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig) +{ + mbedtls_md_type_t mgf1_hash_id; + if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } + + 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, + 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, + 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; + + if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } + + sig_len = ctx->len; + + /* + * 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 = mbedtls_rsa_public(ctx, 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, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig) +{ + if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } + + switch (ctx->padding) { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + return mbedtls_rsa_rsassa_pkcs1_v15_verify(ctx, md_alg, + hashlen, hash, sig); +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + return mbedtls_rsa_rsassa_pss_verify(ctx, 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; + + 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/md.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_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, + 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, + &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_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), + rsa_plaintext, PT_LEN, sha1sum) != 0) { + if (verbose != 0) { + mbedtls_printf("failed\n"); + } + + return 1; + } + + if (mbedtls_rsa_pkcs1_sign(&rsa, myrand, NULL, + MBEDTLS_MD_SHA1, 20, + 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, MBEDTLS_MD_SHA1, 20, + 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_alt_helpers.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/rsa_alt_helpers.c new file mode 100644 index 0000000..3451469 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/rsa_alt_helpers.c @@ -0,0 +1,459 @@ +/* + * 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 "rsa_alt_helpers.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; +} + +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; +} + +/* + * 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; +} + +/* + * 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; +} + +#endif /* MBEDTLS_RSA_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/rsa_alt_helpers.h b/optee/optee_os/lib/libmbedtls/mbedtls/library/rsa_alt_helpers.h new file mode 100644 index 0000000..3b22ba8 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/rsa_alt_helpers.h @@ -0,0 +1,220 @@ +/** + * \file rsa_alt_helpers.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 + +#include "mbedtls/build_info.h" + +#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_alt_helpers.h */ 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..4c9cbf5 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/sha1.c @@ -0,0 +1,489 @@ +/* + * 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 + +#include "mbedtls/platform.h" + +#if !defined(MBEDTLS_SHA1_ALT) + +void mbedtls_sha1_init(mbedtls_sha1_context *ctx) +{ + 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) +{ + *dst = *src; +} + +/* + * SHA-1 context setup + */ +int mbedtls_sha1_starts(mbedtls_sha1_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_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; + + 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; +} + +#endif /* !MBEDTLS_SHA1_PROCESS_ALT */ + +/* + * SHA-1 process buffer + */ +int mbedtls_sha1_update(mbedtls_sha1_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_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; +} + +/* + * SHA-1 final digest + */ +int mbedtls_sha1_finish(mbedtls_sha1_context *ctx, + unsigned char output[20]) +{ + 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_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; +} + +#endif /* !MBEDTLS_SHA1_ALT */ + +/* + * output = SHA-1( input buffer ) + */ +int mbedtls_sha1(const unsigned char *input, + size_t ilen, + unsigned char output[20]) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_sha1_context ctx; + + mbedtls_sha1_init(&ctx); + + if ((ret = mbedtls_sha1_starts(&ctx)) != 0) { + goto exit; + } + + if ((ret = mbedtls_sha1_update(&ctx, input, ilen)) != 0) { + goto exit; + } + + if ((ret = mbedtls_sha1_finish(&ctx, output)) != 0) { + goto exit; + } + +exit: + mbedtls_sha1_free(&ctx); + + return ret; +} + +#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(&ctx)) != 0) { + goto fail; + } + + if (i == 2) { + memset(buf, 'a', buflen = 1000); + + for (j = 0; j < 1000; j++) { + ret = mbedtls_sha1_update(&ctx, buf, buflen); + if (ret != 0) { + goto fail; + } + } + } else { + ret = mbedtls_sha1_update(&ctx, sha1_test_buf[i], + sha1_test_buflen[i]); + if (ret != 0) { + goto fail; + } + } + + if ((ret = mbedtls_sha1_finish(&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..08822f4 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/sha256.c @@ -0,0 +1,939 @@ +/* + * 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 + */ + +#if defined(__aarch64__) && !defined(__ARM_FEATURE_CRYPTO) && \ + defined(__clang__) && __clang_major__ >= 4 +/* TODO: Re-consider above after https://reviews.llvm.org/D131064 merged. + * + * The intrinsic declaration are guarded by predefined ACLE macros in clang: + * these are normally only enabled by the -march option on the command line. + * By defining the macros ourselves we gain access to those declarations without + * requiring -march on the command line. + * + * `arm_neon.h` could be included by any header file, so we put these defines + * at the top of this file, before any includes. + */ +#define __ARM_FEATURE_CRYPTO 1 +/* See: https://arm-software.github.io/acle/main/acle.html#cryptographic-extensions + * + * `__ARM_FEATURE_CRYPTO` is deprecated, but we need to continue to specify it + * for older compilers. + */ +#define __ARM_FEATURE_SHA2 1 +#define MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG +#endif + +#include "common.h" + +#if defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA224_C) + +#include "mbedtls/sha256.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#include "mbedtls/platform.h" + +#if defined(__aarch64__) +# if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT) || \ + defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY) +/* *INDENT-OFF* */ +# if !defined(__ARM_FEATURE_CRYPTO) || defined(MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG) +# if defined(__clang__) +# if __clang_major__ < 4 +# error "A more recent Clang is required for MBEDTLS_SHA256_USE_A64_CRYPTO_*" +# endif +# pragma clang attribute push (__attribute__((target("crypto"))), apply_to=function) +# define MBEDTLS_POP_TARGET_PRAGMA +# elif defined(__GNUC__) + /* FIXME: GCC 5 claims to support Armv8 Crypto Extensions, but some + * intrinsics are missing. Missing intrinsics could be worked around. + */ +# if __GNUC__ < 6 +# error "A more recent GCC is required for MBEDTLS_SHA256_USE_A64_CRYPTO_*" +# else +# pragma GCC push_options +# pragma GCC target ("arch=armv8-a+crypto") +# define MBEDTLS_POP_TARGET_PRAGMA +# endif +# else +# error "Only GCC and Clang supported for MBEDTLS_SHA256_USE_A64_CRYPTO_*" +# endif +# endif +/* *INDENT-ON* */ +# include +# endif +# if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT) +# if defined(__unix__) +# if defined(__linux__) +/* Our preferred method of detection is getauxval() */ +# include +# endif +/* Use SIGILL on Unix, and fall back to it on Linux */ +# include +# endif +# endif +#elif defined(_M_ARM64) +# if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT) || \ + defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY) +# include +# endif +#else +# undef MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY +# undef MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT +#endif + +#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT) +/* + * Capability detection code comes early, so we can disable + * MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT if no detection mechanism found + */ +#if defined(HWCAP_SHA2) +static int mbedtls_a64_crypto_sha256_determine_support(void) +{ + return (getauxval(AT_HWCAP) & HWCAP_SHA2) ? 1 : 0; +} +#elif defined(__APPLE__) +static int mbedtls_a64_crypto_sha256_determine_support(void) +{ + return 1; +} +#elif defined(_M_ARM64) +#define WIN32_LEAN_AND_MEAN +#include +#include + +static int mbedtls_a64_crypto_sha256_determine_support(void) +{ + return IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) ? + 1 : 0; +} +#elif defined(__unix__) && defined(SIG_SETMASK) +/* Detection with SIGILL, setjmp() and longjmp() */ +#include +#include + +static jmp_buf return_from_sigill; + +/* + * A64 SHA256 support detection via SIGILL + */ +static void sigill_handler(int signal) +{ + (void) signal; + longjmp(return_from_sigill, 1); +} + +static int mbedtls_a64_crypto_sha256_determine_support(void) +{ + struct sigaction old_action, new_action; + + sigset_t old_mask; + if (sigprocmask(0, NULL, &old_mask)) { + return 0; + } + + sigemptyset(&new_action.sa_mask); + new_action.sa_flags = 0; + new_action.sa_handler = sigill_handler; + + sigaction(SIGILL, &new_action, &old_action); + + static int ret = 0; + + if (setjmp(return_from_sigill) == 0) { /* First return only */ + /* If this traps, we will return a second time from setjmp() with 1 */ + asm ("sha256h q0, q0, v0.4s" : : : "v0"); + ret = 1; + } + + sigaction(SIGILL, &old_action, NULL); + sigprocmask(SIG_SETMASK, &old_mask, NULL); + + return ret; +} +#else +#warning "No mechanism to detect A64_CRYPTO found, using C code only" +#undef MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT +#endif /* HWCAP_SHA2, __APPLE__, __unix__ && SIG_SETMASK */ + +#endif /* MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT */ + +#if !defined(MBEDTLS_SHA256_ALT) + +#define SHA256_BLOCK_SIZE 64 + +void mbedtls_sha256_init(mbedtls_sha256_context *ctx) +{ + 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) +{ + *dst = *src; +} + +/* + * SHA-256 context setup + */ +int mbedtls_sha256_starts(mbedtls_sha256_context *ctx, int is224) +{ +#if defined(MBEDTLS_SHA224_C) && defined(MBEDTLS_SHA256_C) + if (is224 != 0 && is224 != 1) { + return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA; + } +#elif defined(MBEDTLS_SHA256_C) + if (is224 != 0) { + return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA; + } +#else /* defined MBEDTLS_SHA224_C only */ + if (is224 == 0) { + return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA; + } +#endif + + ctx->total[0] = 0; + ctx->total[1] = 0; + + if (is224 == 0) { +#if defined(MBEDTLS_SHA256_C) + 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; +#endif + } else { +#if defined(MBEDTLS_SHA224_C) + 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; +#endif + } + +#if defined(MBEDTLS_SHA224_C) + ctx->is224 = is224; +#endif + + return 0; +} + +#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, +}; + +#endif + +#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT) || \ + defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY) + +#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY) +# define mbedtls_internal_sha256_process_many_a64_crypto mbedtls_internal_sha256_process_many +# define mbedtls_internal_sha256_process_a64_crypto mbedtls_internal_sha256_process +#endif + +static size_t mbedtls_internal_sha256_process_many_a64_crypto( + mbedtls_sha256_context *ctx, const uint8_t *msg, size_t len) +{ + uint32x4_t abcd = vld1q_u32(&ctx->state[0]); + uint32x4_t efgh = vld1q_u32(&ctx->state[4]); + + size_t processed = 0; + + for (; + len >= SHA256_BLOCK_SIZE; + processed += SHA256_BLOCK_SIZE, + msg += SHA256_BLOCK_SIZE, + len -= SHA256_BLOCK_SIZE) { + uint32x4_t tmp, abcd_prev; + + uint32x4_t abcd_orig = abcd; + uint32x4_t efgh_orig = efgh; + + uint32x4_t sched0 = (uint32x4_t) vld1q_u8(msg + 16 * 0); + uint32x4_t sched1 = (uint32x4_t) vld1q_u8(msg + 16 * 1); + uint32x4_t sched2 = (uint32x4_t) vld1q_u8(msg + 16 * 2); + uint32x4_t sched3 = (uint32x4_t) vld1q_u8(msg + 16 * 3); + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ /* Will be true if not defined */ + /* Untested on BE */ + sched0 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched0))); + sched1 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched1))); + sched2 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched2))); + sched3 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched3))); +#endif + + /* Rounds 0 to 3 */ + tmp = vaddq_u32(sched0, vld1q_u32(&K[0])); + abcd_prev = abcd; + abcd = vsha256hq_u32(abcd_prev, efgh, tmp); + efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); + + /* Rounds 4 to 7 */ + tmp = vaddq_u32(sched1, vld1q_u32(&K[4])); + abcd_prev = abcd; + abcd = vsha256hq_u32(abcd_prev, efgh, tmp); + efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); + + /* Rounds 8 to 11 */ + tmp = vaddq_u32(sched2, vld1q_u32(&K[8])); + abcd_prev = abcd; + abcd = vsha256hq_u32(abcd_prev, efgh, tmp); + efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); + + /* Rounds 12 to 15 */ + tmp = vaddq_u32(sched3, vld1q_u32(&K[12])); + abcd_prev = abcd; + abcd = vsha256hq_u32(abcd_prev, efgh, tmp); + efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); + + for (int t = 16; t < 64; t += 16) { + /* Rounds t to t + 3 */ + sched0 = vsha256su1q_u32(vsha256su0q_u32(sched0, sched1), sched2, sched3); + tmp = vaddq_u32(sched0, vld1q_u32(&K[t])); + abcd_prev = abcd; + abcd = vsha256hq_u32(abcd_prev, efgh, tmp); + efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); + + /* Rounds t + 4 to t + 7 */ + sched1 = vsha256su1q_u32(vsha256su0q_u32(sched1, sched2), sched3, sched0); + tmp = vaddq_u32(sched1, vld1q_u32(&K[t + 4])); + abcd_prev = abcd; + abcd = vsha256hq_u32(abcd_prev, efgh, tmp); + efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); + + /* Rounds t + 8 to t + 11 */ + sched2 = vsha256su1q_u32(vsha256su0q_u32(sched2, sched3), sched0, sched1); + tmp = vaddq_u32(sched2, vld1q_u32(&K[t + 8])); + abcd_prev = abcd; + abcd = vsha256hq_u32(abcd_prev, efgh, tmp); + efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); + + /* Rounds t + 12 to t + 15 */ + sched3 = vsha256su1q_u32(vsha256su0q_u32(sched3, sched0), sched1, sched2); + tmp = vaddq_u32(sched3, vld1q_u32(&K[t + 12])); + abcd_prev = abcd; + abcd = vsha256hq_u32(abcd_prev, efgh, tmp); + efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); + } + + abcd = vaddq_u32(abcd, abcd_orig); + efgh = vaddq_u32(efgh, efgh_orig); + } + + vst1q_u32(&ctx->state[0], abcd); + vst1q_u32(&ctx->state[4], efgh); + + return processed; +} + +#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT) +/* + * This function is for internal use only if we are building both C and A64 + * versions, otherwise it is renamed to be the public mbedtls_internal_sha256_process() + */ +static +#endif +int mbedtls_internal_sha256_process_a64_crypto(mbedtls_sha256_context *ctx, + const unsigned char data[SHA256_BLOCK_SIZE]) +{ + return (mbedtls_internal_sha256_process_many_a64_crypto(ctx, data, + SHA256_BLOCK_SIZE) == + SHA256_BLOCK_SIZE) ? 0 : -1; +} + +#if defined(MBEDTLS_POP_TARGET_PRAGMA) +#if defined(__clang__) +#pragma clang attribute pop +#elif defined(__GNUC__) +#pragma GCC pop_options +#endif +#undef MBEDTLS_POP_TARGET_PRAGMA +#endif + +#endif /* MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT || MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY */ + +#if !defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT) +#define mbedtls_internal_sha256_process_many_c mbedtls_internal_sha256_process_many +#define mbedtls_internal_sha256_process_c mbedtls_internal_sha256_process +#endif + + +#if !defined(MBEDTLS_SHA256_PROCESS_ALT) && \ + !defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY) + +#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) + +#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT) +/* + * This function is for internal use only if we are building both C and A64 + * versions, otherwise it is renamed to be the public mbedtls_internal_sha256_process() + */ +static +#endif +int mbedtls_internal_sha256_process_c(mbedtls_sha256_context *ctx, + const unsigned char data[SHA256_BLOCK_SIZE]) +{ + struct { + uint32_t temp1, temp2, W[64]; + uint32_t A[8]; + } local; + + unsigned int i; + + 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; +} + +#endif /* !MBEDTLS_SHA256_PROCESS_ALT && !MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY */ + + +#if !defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY) + +static size_t mbedtls_internal_sha256_process_many_c( + mbedtls_sha256_context *ctx, const uint8_t *data, size_t len) +{ + size_t processed = 0; + + while (len >= SHA256_BLOCK_SIZE) { + if (mbedtls_internal_sha256_process_c(ctx, data) != 0) { + return 0; + } + + data += SHA256_BLOCK_SIZE; + len -= SHA256_BLOCK_SIZE; + + processed += SHA256_BLOCK_SIZE; + } + + return processed; +} + +#endif /* !MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY */ + + +#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT) + +static int mbedtls_a64_crypto_sha256_has_support(void) +{ + static int done = 0; + static int supported = 0; + + if (!done) { + supported = mbedtls_a64_crypto_sha256_determine_support(); + done = 1; + } + + return supported; +} + +static size_t mbedtls_internal_sha256_process_many(mbedtls_sha256_context *ctx, + const uint8_t *msg, size_t len) +{ + if (mbedtls_a64_crypto_sha256_has_support()) { + return mbedtls_internal_sha256_process_many_a64_crypto(ctx, msg, len); + } else { + return mbedtls_internal_sha256_process_many_c(ctx, msg, len); + } +} + +int mbedtls_internal_sha256_process(mbedtls_sha256_context *ctx, + const unsigned char data[SHA256_BLOCK_SIZE]) +{ + if (mbedtls_a64_crypto_sha256_has_support()) { + return mbedtls_internal_sha256_process_a64_crypto(ctx, data); + } else { + return mbedtls_internal_sha256_process_c(ctx, data); + } +} + +#endif /* MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT */ + + +/* + * SHA-256 process buffer + */ +int mbedtls_sha256_update(mbedtls_sha256_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 = SHA256_BLOCK_SIZE - 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 >= SHA256_BLOCK_SIZE) { + size_t processed = + mbedtls_internal_sha256_process_many(ctx, input, ilen); + if (processed < SHA256_BLOCK_SIZE) { + return MBEDTLS_ERR_ERROR_GENERIC_ERROR; + } + + input += processed; + ilen -= processed; + } + + if (ilen > 0) { + memcpy((void *) (ctx->buffer + left), input, ilen); + } + + return 0; +} + +/* + * SHA-256 final digest + */ +int mbedtls_sha256_finish(mbedtls_sha256_context *ctx, + unsigned char *output) +{ + 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, SHA256_BLOCK_SIZE - 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); + + int truncated = 0; +#if defined(MBEDTLS_SHA224_C) + truncated = ctx->is224; +#endif + if (!truncated) { + MBEDTLS_PUT_UINT32_BE(ctx->state[7], output, 28); + } + + return 0; +} + +#endif /* !MBEDTLS_SHA256_ALT */ + +/* + * output = SHA-256( input buffer ) + */ +int mbedtls_sha256(const unsigned char *input, + size_t ilen, + unsigned char *output, + int is224) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_sha256_context ctx; + +#if defined(MBEDTLS_SHA224_C) && defined(MBEDTLS_SHA256_C) + if (is224 != 0 && is224 != 1) { + return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA; + } +#elif defined(MBEDTLS_SHA256_C) + if (is224 != 0) { + return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA; + } +#else /* defined MBEDTLS_SHA224_C only */ + if (is224 == 0) { + return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA; + } +#endif + + mbedtls_sha256_init(&ctx); + + if ((ret = mbedtls_sha256_starts(&ctx, is224)) != 0) { + goto exit; + } + + if ((ret = mbedtls_sha256_update(&ctx, input, ilen)) != 0) { + goto exit; + } + + if ((ret = mbedtls_sha256_finish(&ctx, output)) != 0) { + goto exit; + } + +exit: + mbedtls_sha256_free(&ctx); + + return ret; +} + +#if defined(MBEDTLS_SELF_TEST) +/* + * FIPS-180-2 test vectors + */ +static const unsigned char sha_test_buf[3][57] = +{ + { "abc" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + { "" } +}; + +static const size_t sha_test_buflen[3] = +{ + 3, 56, 1000 +}; + +typedef const unsigned char (sha_test_sum_t)[32]; + +/* + * SHA-224 test vectors + */ +#if defined(MBEDTLS_SHA224_C) +static sha_test_sum_t sha224_test_sum[] = +{ + { 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 } +}; +#endif + +/* + * SHA-256 test vectors + */ +#if defined(MBEDTLS_SHA256_C) +static sha_test_sum_t sha256_test_sum[] = +{ + { 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 } +}; +#endif + +/* + * Checkup routine + */ +static int mbedtls_sha256_common_self_test(int verbose, int is224) +{ + int i, buflen, ret = 0; + unsigned char *buf; + unsigned char sha256sum[32]; + mbedtls_sha256_context ctx; + +#if defined(MBEDTLS_SHA224_C) && defined(MBEDTLS_SHA256_C) + sha_test_sum_t *sha_test_sum = (is224) ? sha224_test_sum : sha256_test_sum; +#elif defined(MBEDTLS_SHA256_C) + sha_test_sum_t *sha_test_sum = sha256_test_sum; +#else + sha_test_sum_t *sha_test_sum = sha224_test_sum; +#endif + + 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 < 3; i++) { + if (verbose != 0) { + mbedtls_printf(" SHA-%d test #%d: ", 256 - is224 * 32, i + 1); + } + + if ((ret = mbedtls_sha256_starts(&ctx, is224)) != 0) { + goto fail; + } + + if (i == 2) { + memset(buf, 'a', buflen = 1000); + + for (int j = 0; j < 1000; j++) { + ret = mbedtls_sha256_update(&ctx, buf, buflen); + if (ret != 0) { + goto fail; + } + } + + } else { + ret = mbedtls_sha256_update(&ctx, sha_test_buf[i], + sha_test_buflen[i]); + if (ret != 0) { + goto fail; + } + } + + if ((ret = mbedtls_sha256_finish(&ctx, sha256sum)) != 0) { + goto fail; + } + + + if (memcmp(sha256sum, sha_test_sum[i], 32 - is224 * 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; +} + +#if defined(MBEDTLS_SHA256_C) +int mbedtls_sha256_self_test(int verbose) +{ + return mbedtls_sha256_common_self_test(verbose, 0); +} +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA224_C) +int mbedtls_sha224_self_test(int verbose) +{ + return mbedtls_sha256_common_self_test(verbose, 1); +} +#endif /* MBEDTLS_SHA224_C */ + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_SHA256_C || MBEDTLS_SHA224_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..67acfee --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/sha512.c @@ -0,0 +1,1108 @@ +/* + * 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 + */ + +#if defined(__aarch64__) && !defined(__ARM_FEATURE_SHA512) && \ + defined(__clang__) && __clang_major__ >= 7 +/* TODO: Re-consider above after https://reviews.llvm.org/D131064 merged. + * + * The intrinsic declaration are guarded by predefined ACLE macros in clang: + * these are normally only enabled by the -march option on the command line. + * By defining the macros ourselves we gain access to those declarations without + * requiring -march on the command line. + * + * `arm_neon.h` could be included by any header file, so we put these defines + * at the top of this file, before any includes. + */ +#define __ARM_FEATURE_SHA512 1 +#define MBEDTLS_ENABLE_ARM_SHA3_EXTENSIONS_COMPILER_FLAG +#endif + +#include "common.h" + +#if defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_SHA384_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 + +#include "mbedtls/platform.h" + +#if defined(__aarch64__) +# if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) || \ + defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) +/* *INDENT-OFF* */ +/* + * Best performance comes from most recent compilers, with intrinsics and -O3. + * Must compile with -march=armv8.2-a+sha3, but we can't detect armv8.2-a, and + * can't always detect __ARM_FEATURE_SHA512 (notably clang 7-12). + * + * GCC < 8 won't work at all (lacks the sha512 instructions) + * GCC >= 8 uses intrinsics, sets __ARM_FEATURE_SHA512 + * + * Clang < 7 won't work at all (lacks the sha512 instructions) + * Clang 7-12 don't have intrinsics (but we work around that with inline + * assembler) or __ARM_FEATURE_SHA512 + * Clang == 13.0.0 same as clang 12 (only seen on macOS) + * Clang >= 13.0.1 has __ARM_FEATURE_SHA512 and intrinsics + */ +# if !defined(__ARM_FEATURE_SHA512) || defined(MBEDTLS_ENABLE_ARM_SHA3_EXTENSIONS_COMPILER_FLAG) + /* Test Clang first, as it defines __GNUC__ */ +# if defined(__clang__) +# if __clang_major__ < 7 +# error "A more recent Clang is required for MBEDTLS_SHA512_USE_A64_CRYPTO_*" +# else +# pragma clang attribute push (__attribute__((target("sha3"))), apply_to=function) +# define MBEDTLS_POP_TARGET_PRAGMA +# endif +# elif defined(__GNUC__) +# if __GNUC__ < 8 +# error "A more recent GCC is required for MBEDTLS_SHA512_USE_A64_CRYPTO_*" +# else +# pragma GCC push_options +# pragma GCC target ("arch=armv8.2-a+sha3") +# define MBEDTLS_POP_TARGET_PRAGMA +# endif +# else +# error "Only GCC and Clang supported for MBEDTLS_SHA512_USE_A64_CRYPTO_*" +# endif +# endif +/* *INDENT-ON* */ +# include +# endif +# if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) +# if defined(__unix__) +# if defined(__linux__) +/* Our preferred method of detection is getauxval() */ +# include +# endif +/* Use SIGILL on Unix, and fall back to it on Linux */ +# include +# endif +# endif +#elif defined(_M_ARM64) +# if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) || \ + defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) +# include +# endif +#else +# undef MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY +# undef MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT +#endif + +#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) +/* + * Capability detection code comes early, so we can disable + * MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT if no detection mechanism found + */ +#if defined(HWCAP_SHA512) +static int mbedtls_a64_crypto_sha512_determine_support(void) +{ + return (getauxval(AT_HWCAP) & HWCAP_SHA512) ? 1 : 0; +} +#elif defined(__APPLE__) +#include +#include + +static int mbedtls_a64_crypto_sha512_determine_support(void) +{ + int value = 0; + size_t value_len = sizeof(value); + + int ret = sysctlbyname("hw.optional.armv8_2_sha512", &value, &value_len, + NULL, 0); + return ret == 0 && value != 0; +} +#elif defined(_M_ARM64) +/* + * As of March 2022, there don't appear to be any PF_ARM_V8_* flags + * available to pass to IsProcessorFeaturePresent() to check for + * SHA-512 support. So we fall back to the C code only. + */ +#if defined(_MSC_VER) +#pragma message "No mechanism to detect A64_CRYPTO found, using C code only" +#else +#warning "No mechanism to detect A64_CRYPTO found, using C code only" +#endif +#elif defined(__unix__) && defined(SIG_SETMASK) +/* Detection with SIGILL, setjmp() and longjmp() */ +#include +#include + +static jmp_buf return_from_sigill; + +/* + * A64 SHA512 support detection via SIGILL + */ +static void sigill_handler(int signal) +{ + (void) signal; + longjmp(return_from_sigill, 1); +} + +static int mbedtls_a64_crypto_sha512_determine_support(void) +{ + struct sigaction old_action, new_action; + + sigset_t old_mask; + if (sigprocmask(0, NULL, &old_mask)) { + return 0; + } + + sigemptyset(&new_action.sa_mask); + new_action.sa_flags = 0; + new_action.sa_handler = sigill_handler; + + sigaction(SIGILL, &new_action, &old_action); + + static int ret = 0; + + if (setjmp(return_from_sigill) == 0) { /* First return only */ + /* If this traps, we will return a second time from setjmp() with 1 */ + asm ("sha512h q0, q0, v0.2d" : : : "v0"); + ret = 1; + } + + sigaction(SIGILL, &old_action, NULL); + sigprocmask(SIG_SETMASK, &old_mask, NULL); + + return ret; +} +#else +#warning "No mechanism to detect A64_CRYPTO found, using C code only" +#undef MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT +#endif /* HWCAP_SHA512, __APPLE__, __unix__ && SIG_SETMASK */ + +#endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT */ + +#if !defined(MBEDTLS_SHA512_ALT) + +#define SHA512_BLOCK_SIZE 128 + +#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) +{ + 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) +{ + *dst = *src; +} + +/* + * SHA-512 context setup + */ +int mbedtls_sha512_starts(mbedtls_sha512_context *ctx, int is384) +{ +#if defined(MBEDTLS_SHA384_C) && defined(MBEDTLS_SHA512_C) + if (is384 != 0 && is384 != 1) { + return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA; + } +#elif defined(MBEDTLS_SHA512_C) + if (is384 != 0) { + return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA; + } +#else /* defined MBEDTLS_SHA384_C only */ + if (is384 == 0) { + return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA; + } +#endif + + ctx->total[0] = 0; + ctx->total[1] = 0; + + if (is384 == 0) { +#if defined(MBEDTLS_SHA512_C) + 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); +#endif /* MBEDTLS_SHA512_C */ + } else { +#if defined(MBEDTLS_SHA384_C) + 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_SHA384_C */ + } + +#if defined(MBEDTLS_SHA384_C) + ctx->is384 = is384; +#endif + + return 0; +} + +#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) +}; +#endif + +#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) || \ + defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) + +#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) +# define mbedtls_internal_sha512_process_many_a64_crypto mbedtls_internal_sha512_process_many +# define mbedtls_internal_sha512_process_a64_crypto mbedtls_internal_sha512_process +#endif + +/* Accelerated SHA-512 implementation originally written by Simon Tatham for PuTTY, + * under the MIT licence; dual-licensed as Apache 2 with his kind permission. + */ + +#if defined(__clang__) && \ + (__clang_major__ < 13 || \ + (__clang_major__ == 13 && __clang_minor__ == 0 && __clang_patchlevel__ == 0)) +static inline uint64x2_t vsha512su0q_u64(uint64x2_t x, uint64x2_t y) +{ + asm ("sha512su0 %0.2D,%1.2D" : "+w" (x) : "w" (y)); + return x; +} +static inline uint64x2_t vsha512su1q_u64(uint64x2_t x, uint64x2_t y, uint64x2_t z) +{ + asm ("sha512su1 %0.2D,%1.2D,%2.2D" : "+w" (x) : "w" (y), "w" (z)); + return x; +} +static inline uint64x2_t vsha512hq_u64(uint64x2_t x, uint64x2_t y, uint64x2_t z) +{ + asm ("sha512h %0,%1,%2.2D" : "+w" (x) : "w" (y), "w" (z)); + return x; +} +static inline uint64x2_t vsha512h2q_u64(uint64x2_t x, uint64x2_t y, uint64x2_t z) +{ + asm ("sha512h2 %0,%1,%2.2D" : "+w" (x) : "w" (y), "w" (z)); + return x; +} +#endif /* __clang__ etc */ + +static size_t mbedtls_internal_sha512_process_many_a64_crypto( + mbedtls_sha512_context *ctx, const uint8_t *msg, size_t len) +{ + uint64x2_t ab = vld1q_u64(&ctx->state[0]); + uint64x2_t cd = vld1q_u64(&ctx->state[2]); + uint64x2_t ef = vld1q_u64(&ctx->state[4]); + uint64x2_t gh = vld1q_u64(&ctx->state[6]); + + size_t processed = 0; + + for (; + len >= SHA512_BLOCK_SIZE; + processed += SHA512_BLOCK_SIZE, + msg += SHA512_BLOCK_SIZE, + len -= SHA512_BLOCK_SIZE) { + uint64x2_t initial_sum, sum, intermed; + + uint64x2_t ab_orig = ab; + uint64x2_t cd_orig = cd; + uint64x2_t ef_orig = ef; + uint64x2_t gh_orig = gh; + + uint64x2_t s0 = (uint64x2_t) vld1q_u8(msg + 16 * 0); + uint64x2_t s1 = (uint64x2_t) vld1q_u8(msg + 16 * 1); + uint64x2_t s2 = (uint64x2_t) vld1q_u8(msg + 16 * 2); + uint64x2_t s3 = (uint64x2_t) vld1q_u8(msg + 16 * 3); + uint64x2_t s4 = (uint64x2_t) vld1q_u8(msg + 16 * 4); + uint64x2_t s5 = (uint64x2_t) vld1q_u8(msg + 16 * 5); + uint64x2_t s6 = (uint64x2_t) vld1q_u8(msg + 16 * 6); + uint64x2_t s7 = (uint64x2_t) vld1q_u8(msg + 16 * 7); + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ /* assume LE if these not defined; untested on BE */ + s0 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s0))); + s1 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s1))); + s2 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s2))); + s3 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s3))); + s4 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s4))); + s5 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s5))); + s6 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s6))); + s7 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s7))); +#endif + + /* Rounds 0 and 1 */ + initial_sum = vaddq_u64(s0, vld1q_u64(&K[0])); + sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), gh); + intermed = vsha512hq_u64(sum, vextq_u64(ef, gh, 1), vextq_u64(cd, ef, 1)); + gh = vsha512h2q_u64(intermed, cd, ab); + cd = vaddq_u64(cd, intermed); + + /* Rounds 2 and 3 */ + initial_sum = vaddq_u64(s1, vld1q_u64(&K[2])); + sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ef); + intermed = vsha512hq_u64(sum, vextq_u64(cd, ef, 1), vextq_u64(ab, cd, 1)); + ef = vsha512h2q_u64(intermed, ab, gh); + ab = vaddq_u64(ab, intermed); + + /* Rounds 4 and 5 */ + initial_sum = vaddq_u64(s2, vld1q_u64(&K[4])); + sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), cd); + intermed = vsha512hq_u64(sum, vextq_u64(ab, cd, 1), vextq_u64(gh, ab, 1)); + cd = vsha512h2q_u64(intermed, gh, ef); + gh = vaddq_u64(gh, intermed); + + /* Rounds 6 and 7 */ + initial_sum = vaddq_u64(s3, vld1q_u64(&K[6])); + sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ab); + intermed = vsha512hq_u64(sum, vextq_u64(gh, ab, 1), vextq_u64(ef, gh, 1)); + ab = vsha512h2q_u64(intermed, ef, cd); + ef = vaddq_u64(ef, intermed); + + /* Rounds 8 and 9 */ + initial_sum = vaddq_u64(s4, vld1q_u64(&K[8])); + sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), gh); + intermed = vsha512hq_u64(sum, vextq_u64(ef, gh, 1), vextq_u64(cd, ef, 1)); + gh = vsha512h2q_u64(intermed, cd, ab); + cd = vaddq_u64(cd, intermed); + + /* Rounds 10 and 11 */ + initial_sum = vaddq_u64(s5, vld1q_u64(&K[10])); + sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ef); + intermed = vsha512hq_u64(sum, vextq_u64(cd, ef, 1), vextq_u64(ab, cd, 1)); + ef = vsha512h2q_u64(intermed, ab, gh); + ab = vaddq_u64(ab, intermed); + + /* Rounds 12 and 13 */ + initial_sum = vaddq_u64(s6, vld1q_u64(&K[12])); + sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), cd); + intermed = vsha512hq_u64(sum, vextq_u64(ab, cd, 1), vextq_u64(gh, ab, 1)); + cd = vsha512h2q_u64(intermed, gh, ef); + gh = vaddq_u64(gh, intermed); + + /* Rounds 14 and 15 */ + initial_sum = vaddq_u64(s7, vld1q_u64(&K[14])); + sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ab); + intermed = vsha512hq_u64(sum, vextq_u64(gh, ab, 1), vextq_u64(ef, gh, 1)); + ab = vsha512h2q_u64(intermed, ef, cd); + ef = vaddq_u64(ef, intermed); + + for (unsigned int t = 16; t < 80; t += 16) { + /* Rounds t and t + 1 */ + s0 = vsha512su1q_u64(vsha512su0q_u64(s0, s1), s7, vextq_u64(s4, s5, 1)); + initial_sum = vaddq_u64(s0, vld1q_u64(&K[t])); + sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), gh); + intermed = vsha512hq_u64(sum, vextq_u64(ef, gh, 1), vextq_u64(cd, ef, 1)); + gh = vsha512h2q_u64(intermed, cd, ab); + cd = vaddq_u64(cd, intermed); + + /* Rounds t + 2 and t + 3 */ + s1 = vsha512su1q_u64(vsha512su0q_u64(s1, s2), s0, vextq_u64(s5, s6, 1)); + initial_sum = vaddq_u64(s1, vld1q_u64(&K[t + 2])); + sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ef); + intermed = vsha512hq_u64(sum, vextq_u64(cd, ef, 1), vextq_u64(ab, cd, 1)); + ef = vsha512h2q_u64(intermed, ab, gh); + ab = vaddq_u64(ab, intermed); + + /* Rounds t + 4 and t + 5 */ + s2 = vsha512su1q_u64(vsha512su0q_u64(s2, s3), s1, vextq_u64(s6, s7, 1)); + initial_sum = vaddq_u64(s2, vld1q_u64(&K[t + 4])); + sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), cd); + intermed = vsha512hq_u64(sum, vextq_u64(ab, cd, 1), vextq_u64(gh, ab, 1)); + cd = vsha512h2q_u64(intermed, gh, ef); + gh = vaddq_u64(gh, intermed); + + /* Rounds t + 6 and t + 7 */ + s3 = vsha512su1q_u64(vsha512su0q_u64(s3, s4), s2, vextq_u64(s7, s0, 1)); + initial_sum = vaddq_u64(s3, vld1q_u64(&K[t + 6])); + sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ab); + intermed = vsha512hq_u64(sum, vextq_u64(gh, ab, 1), vextq_u64(ef, gh, 1)); + ab = vsha512h2q_u64(intermed, ef, cd); + ef = vaddq_u64(ef, intermed); + + /* Rounds t + 8 and t + 9 */ + s4 = vsha512su1q_u64(vsha512su0q_u64(s4, s5), s3, vextq_u64(s0, s1, 1)); + initial_sum = vaddq_u64(s4, vld1q_u64(&K[t + 8])); + sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), gh); + intermed = vsha512hq_u64(sum, vextq_u64(ef, gh, 1), vextq_u64(cd, ef, 1)); + gh = vsha512h2q_u64(intermed, cd, ab); + cd = vaddq_u64(cd, intermed); + + /* Rounds t + 10 and t + 11 */ + s5 = vsha512su1q_u64(vsha512su0q_u64(s5, s6), s4, vextq_u64(s1, s2, 1)); + initial_sum = vaddq_u64(s5, vld1q_u64(&K[t + 10])); + sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ef); + intermed = vsha512hq_u64(sum, vextq_u64(cd, ef, 1), vextq_u64(ab, cd, 1)); + ef = vsha512h2q_u64(intermed, ab, gh); + ab = vaddq_u64(ab, intermed); + + /* Rounds t + 12 and t + 13 */ + s6 = vsha512su1q_u64(vsha512su0q_u64(s6, s7), s5, vextq_u64(s2, s3, 1)); + initial_sum = vaddq_u64(s6, vld1q_u64(&K[t + 12])); + sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), cd); + intermed = vsha512hq_u64(sum, vextq_u64(ab, cd, 1), vextq_u64(gh, ab, 1)); + cd = vsha512h2q_u64(intermed, gh, ef); + gh = vaddq_u64(gh, intermed); + + /* Rounds t + 14 and t + 15 */ + s7 = vsha512su1q_u64(vsha512su0q_u64(s7, s0), s6, vextq_u64(s3, s4, 1)); + initial_sum = vaddq_u64(s7, vld1q_u64(&K[t + 14])); + sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ab); + intermed = vsha512hq_u64(sum, vextq_u64(gh, ab, 1), vextq_u64(ef, gh, 1)); + ab = vsha512h2q_u64(intermed, ef, cd); + ef = vaddq_u64(ef, intermed); + } + + ab = vaddq_u64(ab, ab_orig); + cd = vaddq_u64(cd, cd_orig); + ef = vaddq_u64(ef, ef_orig); + gh = vaddq_u64(gh, gh_orig); + } + + vst1q_u64(&ctx->state[0], ab); + vst1q_u64(&ctx->state[2], cd); + vst1q_u64(&ctx->state[4], ef); + vst1q_u64(&ctx->state[6], gh); + + return processed; +} + +#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) +/* + * This function is for internal use only if we are building both C and A64 + * versions, otherwise it is renamed to be the public mbedtls_internal_sha512_process() + */ +static +#endif +int mbedtls_internal_sha512_process_a64_crypto(mbedtls_sha512_context *ctx, + const unsigned char data[SHA512_BLOCK_SIZE]) +{ + return (mbedtls_internal_sha512_process_many_a64_crypto(ctx, data, + SHA512_BLOCK_SIZE) == + SHA512_BLOCK_SIZE) ? 0 : -1; +} + +#if defined(MBEDTLS_POP_TARGET_PRAGMA) +#if defined(__clang__) +#pragma clang attribute pop +#elif defined(__GNUC__) +#pragma GCC pop_options +#endif +#undef MBEDTLS_POP_TARGET_PRAGMA +#endif + +#endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT || MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */ + + +#if !defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) +#define mbedtls_internal_sha512_process_many_c mbedtls_internal_sha512_process_many +#define mbedtls_internal_sha512_process_c mbedtls_internal_sha512_process +#endif + + +#if !defined(MBEDTLS_SHA512_PROCESS_ALT) && !defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) + +#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) +/* + * This function is for internal use only if we are building both C and A64 + * versions, otherwise it is renamed to be the public mbedtls_internal_sha512_process() + */ +static +#endif +int mbedtls_internal_sha512_process_c(mbedtls_sha512_context *ctx, + const unsigned char data[SHA512_BLOCK_SIZE]) +{ + int i; + struct { + uint64_t temp1, temp2, W[80]; + uint64_t A[8]; + } local; + +#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; +} + +#endif /* !MBEDTLS_SHA512_PROCESS_ALT && !MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */ + + +#if !defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) + +static size_t mbedtls_internal_sha512_process_many_c( + mbedtls_sha512_context *ctx, const uint8_t *data, size_t len) +{ + size_t processed = 0; + + while (len >= SHA512_BLOCK_SIZE) { + if (mbedtls_internal_sha512_process_c(ctx, data) != 0) { + return 0; + } + + data += SHA512_BLOCK_SIZE; + len -= SHA512_BLOCK_SIZE; + + processed += SHA512_BLOCK_SIZE; + } + + return processed; +} + +#endif /* !MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */ + + +#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) + +static int mbedtls_a64_crypto_sha512_has_support(void) +{ + static int done = 0; + static int supported = 0; + + if (!done) { + supported = mbedtls_a64_crypto_sha512_determine_support(); + done = 1; + } + + return supported; +} + +static size_t mbedtls_internal_sha512_process_many(mbedtls_sha512_context *ctx, + const uint8_t *msg, size_t len) +{ + if (mbedtls_a64_crypto_sha512_has_support()) { + return mbedtls_internal_sha512_process_many_a64_crypto(ctx, msg, len); + } else { + return mbedtls_internal_sha512_process_many_c(ctx, msg, len); + } +} + +int mbedtls_internal_sha512_process(mbedtls_sha512_context *ctx, + const unsigned char data[SHA512_BLOCK_SIZE]) +{ + if (mbedtls_a64_crypto_sha512_has_support()) { + return mbedtls_internal_sha512_process_a64_crypto(ctx, data); + } else { + return mbedtls_internal_sha512_process_c(ctx, data); + } +} + +#endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT */ + +/* + * SHA-512 process buffer + */ +int mbedtls_sha512_update(mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t fill; + unsigned int left; + + if (ilen == 0) { + return 0; + } + + left = (unsigned int) (ctx->total[0] & 0x7F); + fill = SHA512_BLOCK_SIZE - 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 >= SHA512_BLOCK_SIZE) { + size_t processed = + mbedtls_internal_sha512_process_many(ctx, input, ilen); + if (processed < SHA512_BLOCK_SIZE) { + return MBEDTLS_ERR_ERROR_GENERIC_ERROR; + } + + input += processed; + ilen -= processed; + } + + if (ilen > 0) { + memcpy((void *) (ctx->buffer + left), input, ilen); + } + + return 0; +} + +/* + * SHA-512 final digest + */ +int mbedtls_sha512_finish(mbedtls_sha512_context *ctx, + unsigned char *output) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned used; + uint64_t high, low; + + /* + * 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, SHA512_BLOCK_SIZE - 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); + + int truncated = 0; +#if defined(MBEDTLS_SHA384_C) + truncated = ctx->is384; +#endif + if (!truncated) { + sha512_put_uint64_be(ctx->state[6], output, 48); + sha512_put_uint64_be(ctx->state[7], output, 56); + } + + return 0; +} + +#endif /* !MBEDTLS_SHA512_ALT */ + +/* + * output = SHA-512( input buffer ) + */ +int mbedtls_sha512(const unsigned char *input, + size_t ilen, + unsigned char *output, + int is384) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_sha512_context ctx; + +#if defined(MBEDTLS_SHA384_C) && defined(MBEDTLS_SHA512_C) + if (is384 != 0 && is384 != 1) { + return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA; + } +#elif defined(MBEDTLS_SHA512_C) + if (is384 != 0) { + return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA; + } +#else /* defined MBEDTLS_SHA384_C only */ + if (is384 == 0) { + return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA; + } +#endif + + mbedtls_sha512_init(&ctx); + + if ((ret = mbedtls_sha512_starts(&ctx, is384)) != 0) { + goto exit; + } + + if ((ret = mbedtls_sha512_update(&ctx, input, ilen)) != 0) { + goto exit; + } + + if ((ret = mbedtls_sha512_finish(&ctx, output)) != 0) { + goto exit; + } + +exit: + mbedtls_sha512_free(&ctx); + + return ret; +} + +#if defined(MBEDTLS_SELF_TEST) + +/* + * FIPS-180-2 test vectors + */ +static const unsigned char sha_test_buf[3][113] = +{ + { "abc" }, + { + "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" + }, + { "" } +}; + +static const size_t sha_test_buflen[3] = +{ + 3, 112, 1000 +}; + +typedef const unsigned char (sha_test_sum_t)[64]; + +/* + * SHA-384 test vectors + */ +#if defined(MBEDTLS_SHA384_C) +static sha_test_sum_t sha384_test_sum[] = +{ + { 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_SHA384_C */ + +/* + * SHA-512 test vectors + */ +#if defined(MBEDTLS_SHA512_C) +static sha_test_sum_t sha512_test_sum[] = +{ + { 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 } +}; +#endif /* MBEDTLS_SHA512_C */ + +#define ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0])) + +static int mbedtls_sha512_common_self_test(int verbose, int is384) +{ + int i, buflen, ret = 0; + unsigned char *buf; + unsigned char sha512sum[64]; + mbedtls_sha512_context ctx; + +#if defined(MBEDTLS_SHA384_C) && defined(MBEDTLS_SHA512_C) + sha_test_sum_t *sha_test_sum = (is384) ? sha384_test_sum : sha512_test_sum; +#elif defined(MBEDTLS_SHA512_C) + sha_test_sum_t *sha_test_sum = sha512_test_sum; +#else + sha_test_sum_t *sha_test_sum = sha384_test_sum; +#endif + + 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 < 3; i++) { + if (verbose != 0) { + mbedtls_printf(" SHA-%d test #%d: ", 512 - is384 * 128, i + 1); + } + + if ((ret = mbedtls_sha512_starts(&ctx, is384)) != 0) { + goto fail; + } + + if (i == 2) { + memset(buf, 'a', buflen = 1000); + + for (int j = 0; j < 1000; j++) { + ret = mbedtls_sha512_update(&ctx, buf, buflen); + if (ret != 0) { + goto fail; + } + } + } else { + ret = mbedtls_sha512_update(&ctx, sha_test_buf[i], + sha_test_buflen[i]); + if (ret != 0) { + goto fail; + } + } + + if ((ret = mbedtls_sha512_finish(&ctx, sha512sum)) != 0) { + goto fail; + } + + if (memcmp(sha512sum, sha_test_sum[i], 64 - is384 * 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; +} + +#if defined(MBEDTLS_SHA512_C) +int mbedtls_sha512_self_test(int verbose) +{ + return mbedtls_sha512_common_self_test(verbose, 0); +} +#endif /* MBEDTLS_SHA512_C */ + +#if defined(MBEDTLS_SHA384_C) +int mbedtls_sha384_self_test(int verbose) +{ + return mbedtls_sha512_common_self_test(verbose, 1); +} +#endif /* MBEDTLS_SHA384_C */ + +#undef ARRAY_LENGTH + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_SHA512_C || MBEDTLS_SHA384_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..048c21d --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_cache.c @@ -0,0 +1,423 @@ +/* + * 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) + +#include "mbedtls/platform.h" + +#include "mbedtls/ssl_cache.h" +#include "ssl_misc.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 +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_cache_find_entry(mbedtls_ssl_cache_context *cache, + unsigned char const *session_id, + size_t session_id_len, + mbedtls_ssl_cache_entry **dst) +{ + int ret = 1; +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t t = mbedtls_time(NULL); +#endif + mbedtls_ssl_cache_entry *cur; + + for (cur = cache->chain; cur != NULL; cur = cur->next) { +#if defined(MBEDTLS_HAVE_TIME) + if (cache->timeout != 0 && + (int) (t - cur->timestamp) > cache->timeout) { + continue; + } +#endif + + if (session_id_len != cur->session_id_len || + memcmp(session_id, cur->session_id, + cur->session_id_len) != 0) { + continue; + } + + break; + } + + if (cur != NULL) { + *dst = cur; + ret = 0; + } + + return ret; +} + + +int mbedtls_ssl_cache_get(void *data, + unsigned char const *session_id, + size_t session_id_len, + mbedtls_ssl_session *session) +{ + int ret = 1; + mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data; + mbedtls_ssl_cache_entry *entry; + +#if defined(MBEDTLS_THREADING_C) + if ((ret = mbedtls_mutex_lock(&cache->mutex)) != 0) { + return ret; + } +#endif + + ret = ssl_cache_find_entry(cache, session_id, session_id_len, &entry); + if (ret != 0) { + goto exit; + } + + ret = mbedtls_ssl_session_load(session, + entry->session, + entry->session_len); + if (ret != 0) { + goto exit; + } + + ret = 0; + +exit: +#if defined(MBEDTLS_THREADING_C) + if (mbedtls_mutex_unlock(&cache->mutex) != 0) { + ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; + } +#endif + + return ret; +} + +/* zeroize a cache entry */ +static void ssl_cache_entry_zeroize(mbedtls_ssl_cache_entry *entry) +{ + if (entry == NULL) { + return; + } + + /* zeroize and free session structure */ + if (entry->session != NULL) { + mbedtls_platform_zeroize(entry->session, entry->session_len); + mbedtls_free(entry->session); + } + + /* zeroize the whole entry structure */ + mbedtls_platform_zeroize(entry, sizeof(mbedtls_ssl_cache_entry)); +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_cache_pick_writing_slot(mbedtls_ssl_cache_context *cache, + unsigned char const *session_id, + size_t session_id_len, + mbedtls_ssl_cache_entry **dst) +{ +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t t = mbedtls_time(NULL), oldest = 0; +#endif /* MBEDTLS_HAVE_TIME */ + + mbedtls_ssl_cache_entry *old = NULL; + int count = 0; + mbedtls_ssl_cache_entry *cur, *last; + + /* Check 1: Is there already an entry with the given session ID? + * + * If yes, overwrite it. + * + * If not, `count` will hold the size of the session cache + * at the end of this loop, and `last` will point to the last + * entry, both of which will be used later. */ + + last = NULL; + for (cur = cache->chain; cur != NULL; cur = cur->next) { + count++; + if (session_id_len == cur->session_id_len && + memcmp(session_id, cur->session_id, cur->session_id_len) == 0) { + goto found; + } + last = cur; + } + + /* Check 2: Is there an outdated entry in the cache? + * + * If so, overwrite it. + * + * If not, remember the oldest entry in `old` for later. + */ + +#if defined(MBEDTLS_HAVE_TIME) + for (cur = cache->chain; cur != NULL; cur = cur->next) { + if (cache->timeout != 0 && + (int) (t - cur->timestamp) > cache->timeout) { + goto found; + } + + if (oldest == 0 || cur->timestamp < oldest) { + oldest = cur->timestamp; + old = cur; + } + } +#endif /* MBEDTLS_HAVE_TIME */ + + /* Check 3: Is there free space in the cache? */ + + if (count < cache->max_entries) { + /* Create new entry */ + cur = mbedtls_calloc(1, sizeof(mbedtls_ssl_cache_entry)); + if (cur == NULL) { + return 1; + } + + /* Append to the end of the linked list. */ + if (last == NULL) { + cache->chain = cur; + } else { + last->next = cur; + } + + goto found; + } + + /* Last resort: The cache is full and doesn't contain any outdated + * elements. In this case, we evict the oldest one, judged by timestamp + * (if present) or cache-order. */ + +#if defined(MBEDTLS_HAVE_TIME) + if (old == NULL) { + /* This should only happen on an ill-configured cache + * with max_entries == 0. */ + return 1; + } +#else /* MBEDTLS_HAVE_TIME */ + /* Reuse first entry in chain, but move to last place. */ + if (cache->chain == NULL) { + return 1; + } + + old = cache->chain; + cache->chain = old->next; + old->next = NULL; + last->next = old; +#endif /* MBEDTLS_HAVE_TIME */ + + /* Now `old` points to the oldest entry to be overwritten. */ + cur = old; + +found: + + /* If we're reusing an entry, free it first. */ + if (cur->session != NULL) { + /* `ssl_cache_entry_zeroize` would break the chain, + * so we reuse `old` to record `next` temporarily. */ + old = cur->next; + ssl_cache_entry_zeroize(cur); + cur->next = old; + } + +#if defined(MBEDTLS_HAVE_TIME) + cur->timestamp = t; +#endif + + *dst = cur; + return 0; +} + +int mbedtls_ssl_cache_set(void *data, + unsigned char const *session_id, + size_t session_id_len, + const mbedtls_ssl_session *session) +{ + int ret = 1; + mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data; + mbedtls_ssl_cache_entry *cur; + + size_t session_serialized_len; + unsigned char *session_serialized = NULL; + +#if defined(MBEDTLS_THREADING_C) + if ((ret = mbedtls_mutex_lock(&cache->mutex)) != 0) { + return ret; + } +#endif + + ret = ssl_cache_pick_writing_slot(cache, + session_id, session_id_len, + &cur); + if (ret != 0) { + goto exit; + } + + /* Check how much space we need to serialize the session + * and allocate a sufficiently large buffer. */ + ret = mbedtls_ssl_session_save(session, NULL, 0, &session_serialized_len); + if (ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL) { + ret = 1; + goto exit; + } + + session_serialized = mbedtls_calloc(1, session_serialized_len); + if (session_serialized == NULL) { + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto exit; + } + + /* Now serialize the session into the allocated buffer. */ + ret = mbedtls_ssl_session_save(session, + session_serialized, + session_serialized_len, + &session_serialized_len); + if (ret != 0) { + goto exit; + } + + if (session_id_len > sizeof(cur->session_id)) { + ret = 1; + goto exit; + } + cur->session_id_len = session_id_len; + memcpy(cur->session_id, session_id, session_id_len); + + cur->session = session_serialized; + cur->session_len = session_serialized_len; + session_serialized = NULL; + + ret = 0; + +exit: +#if defined(MBEDTLS_THREADING_C) + if (mbedtls_mutex_unlock(&cache->mutex) != 0) { + ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; + } +#endif + + if (session_serialized != NULL) { + mbedtls_platform_zeroize(session_serialized, session_serialized_len); + mbedtls_free(session_serialized); + session_serialized = NULL; + } + + return ret; +} + +int mbedtls_ssl_cache_remove(void *data, + unsigned char const *session_id, + size_t session_id_len) +{ + int ret = 1; + mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data; + mbedtls_ssl_cache_entry *entry; + mbedtls_ssl_cache_entry *prev; + +#if defined(MBEDTLS_THREADING_C) + if ((ret = mbedtls_mutex_lock(&cache->mutex)) != 0) { + return ret; + } +#endif + + ret = ssl_cache_find_entry(cache, session_id, session_id_len, &entry); + /* No valid entry found, exit with success */ + if (ret != 0) { + ret = 0; + goto exit; + } + + /* Now we remove the entry from the chain */ + if (entry == cache->chain) { + cache->chain = entry->next; + goto free; + } + for (prev = cache->chain; prev->next != NULL; prev = prev->next) { + if (prev->next == entry) { + prev->next = entry->next; + break; + } + } + +free: + ssl_cache_entry_zeroize(entry); + mbedtls_free(entry); + ret = 0; + +exit: +#if defined(MBEDTLS_THREADING_C) + if (mbedtls_mutex_unlock(&cache->mutex) != 0) { + ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; + } +#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; + + ssl_cache_entry_zeroize(prv); + 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..501608a --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_ciphersuites.c @@ -0,0 +1,2058 @@ +/** + * \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) + +#include "mbedtls/platform.h" + +#include "mbedtls/ssl_ciphersuites.h" +#include "mbedtls/ssl.h" +#include "ssl_misc.h" + +#include "mbedtls/legacy_or_psa.h" + +#include + +/* + * Ordered from most preferred to least preferred in terms of security. + * + * Current rule (except 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 +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + /* TLS 1.3 ciphersuites */ + MBEDTLS_TLS1_3_CHACHA20_POLY1305_SHA256, + MBEDTLS_TLS1_3_AES_256_GCM_SHA384, + MBEDTLS_TLS1_3_AES_128_GCM_SHA256, + MBEDTLS_TLS1_3_AES_128_CCM_SHA256, + MBEDTLS_TLS1_3_AES_128_CCM_8_SHA256, +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + + /* 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, + + /* 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_SSL_PROTO_TLS1_3) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { MBEDTLS_TLS1_3_AES_256_GCM_SHA384, "TLS1-3-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, + MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */ + 0, + MBEDTLS_SSL_VERSION_TLS1_3, MBEDTLS_SSL_VERSION_TLS1_3 }, +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { MBEDTLS_TLS1_3_AES_128_GCM_SHA256, "TLS1-3-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */ + 0, + MBEDTLS_SSL_VERSION_TLS1_3, MBEDTLS_SSL_VERSION_TLS1_3 }, +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#endif /* MBEDTLS_GCM_C */ +#if defined(MBEDTLS_CCM_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { MBEDTLS_TLS1_3_AES_128_CCM_SHA256, "TLS1-3-AES-128-CCM-SHA256", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */ + 0, + MBEDTLS_SSL_VERSION_TLS1_3, MBEDTLS_SSL_VERSION_TLS1_3 }, + { MBEDTLS_TLS1_3_AES_128_CCM_8_SHA256, "TLS1-3-AES-128-CCM-8-SHA256", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */ + MBEDTLS_CIPHERSUITE_SHORT_TAG, + MBEDTLS_SSL_VERSION_TLS1_3, MBEDTLS_SSL_VERSION_TLS1_3 }, +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA && MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ +#if defined(MBEDTLS_CHACHAPOLY_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { MBEDTLS_TLS1_3_CHACHA20_POLY1305_SHA256, + "TLS1-3-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */ + 0, + MBEDTLS_SSL_VERSION_TLS1_3, MBEDTLS_SSL_VERSION_TLS1_3 }, +#endif /* MBEDTLS_CHACHAPOLY_C && MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + +#if defined(MBEDTLS_CHACHAPOLY_C) && \ + defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \ + 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif +#endif /* MBEDTLS_CHACHAPOLY_C && + MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA && + MBEDTLS_SSL_PROTO_TLS1_2 */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +#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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +#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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +#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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, + { 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_CIPHERSUITE_SHORT_TAG, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, + { 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_CIPHERSUITE_SHORT_TAG, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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_CIPHERSUITE_WEAK, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#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_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +#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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +#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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +#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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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_CIPHERSUITE_WEAK, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#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(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \ + 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA && MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +#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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, + + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, + + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, + { 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_CIPHERSUITE_SHORT_TAG, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, + { 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_CIPHERSUITE_SHORT_TAG, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, + + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ + +#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, + + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ + +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \ + 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA && MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +#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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, + + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ + +#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +#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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, + + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, + { 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_CIPHERSUITE_SHORT_TAG, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, + { 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_CIPHERSUITE_SHORT_TAG, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, + + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ + +#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, + + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ + +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +#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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +#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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +#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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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_CIPHERSUITE_WEAK, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#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_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +#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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +#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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +#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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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_CIPHERSUITE_WEAK, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#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_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ + +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ + +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ + +#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, + + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, + { 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_CIPHERSUITE_SHORT_TAG, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, + { 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_CIPHERSUITE_SHORT_TAG, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ + +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ + +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_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_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ + +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ + +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ + +#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, + + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, + { 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_CIPHERSUITE_SHORT_TAG, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, + { 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_CIPHERSUITE_SHORT_TAG, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ + +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ + +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_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_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ + +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ + +#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, + + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ + +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_CAMELLIA_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_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ + +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ + +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ + +#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, + + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ + +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ + +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_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_CIPHERSUITE_SHORT_TAG, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) +#if defined(MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { MBEDTLS_TLS_RSA_WITH_NULL_MD5, "TLS-RSA-WITH-NULL-MD5", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_MD5, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_CIPHERSUITE_WEAK, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif + +#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { MBEDTLS_TLS_RSA_WITH_NULL_SHA, "TLS-RSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_CIPHERSUITE_WEAK, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif + +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { MBEDTLS_TLS_RSA_WITH_NULL_SHA256, "TLS-RSA-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_CIPHERSUITE_WEAK, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) +#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { MBEDTLS_TLS_PSK_WITH_NULL_SHA, "TLS-PSK-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_CIPHERSUITE_WEAK, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ + +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { MBEDTLS_TLS_PSK_WITH_NULL_SHA256, "TLS-PSK-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_CIPHERSUITE_WEAK, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif + +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { MBEDTLS_TLS_PSK_WITH_NULL_SHA384, "TLS-PSK-WITH-NULL-SHA384", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_CIPHERSUITE_WEAK, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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_CIPHERSUITE_WEAK, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ + +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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_CIPHERSUITE_WEAK, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif + +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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_CIPHERSUITE_WEAK, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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_CIPHERSUITE_WEAK, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ + +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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_CIPHERSUITE_WEAK, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif + +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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_CIPHERSUITE_WEAK, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) +#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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_CIPHERSUITE_WEAK, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ + +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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_CIPHERSUITE_WEAK, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif + +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { 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_CIPHERSUITE_WEAK, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ + +#if defined(MBEDTLS_ARIA_C) + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \ + defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \ + defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \ + defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \ + defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \ + defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \ + defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \ + defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \ + defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \ + defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \ + defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \ + defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \ + defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \ + defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \ + defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \ + defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \ + defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \ + defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \ + defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \ + defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \ + defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)) + { 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, + 0, + MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, +#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 } +}; + +#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; + + 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; +} + +size_t mbedtls_ssl_ciphersuite_get_cipher_key_bitlen(const mbedtls_ssl_ciphersuite_t *info) +{ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_type_t key_type; + psa_algorithm_t alg; + size_t key_bits; + + status = mbedtls_ssl_cipher_to_psa(info->cipher, + info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16, + &alg, &key_type, &key_bits); + + if (status != PSA_SUCCESS) { + return 0; + } + + return key_bits; +#else + const mbedtls_cipher_info_t * const cipher_info = + mbedtls_cipher_info_from_type(info->cipher); + + return mbedtls_cipher_info_get_key_bitlen(cipher_info); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +} + +#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; + } +} + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +psa_algorithm_t mbedtls_ssl_get_ciphersuite_sig_pk_psa_alg(const mbedtls_ssl_ciphersuite_t *info) +{ + switch (info->key_exchange) { + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + return PSA_ALG_RSA_PKCS1V15_CRYPT; + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + return PSA_ALG_RSA_PKCS1V15_SIGN( + mbedtls_hash_info_psa_from_md(info->mac)); + + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return PSA_ALG_ECDSA(mbedtls_hash_info_psa_from_md(info->mac)); + + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + return PSA_ALG_ECDH; + + default: + return PSA_ALG_NONE; + } +} + +psa_key_usage_t mbedtls_ssl_get_ciphersuite_sig_pk_psa_usage(const mbedtls_ssl_ciphersuite_t *info) +{ + switch (info->key_exchange) { + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + return PSA_KEY_USAGE_DECRYPT; + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return PSA_KEY_USAGE_SIGN_HASH; + + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + return PSA_KEY_USAGE_DERIVE; + + default: + return 0; + } +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg(const mbedtls_ssl_ciphersuite_t *info) +{ + switch (info->key_exchange) { + 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_client.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_client.c new file mode 100644 index 0000000..ea64b21 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_client.c @@ -0,0 +1,999 @@ +/* + * TLS 1.2 and 1.3 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. + * + * This file is part of mbed TLS ( https://tls.mbed.org ) + */ + +#include "common.h" + +#if defined(MBEDTLS_SSL_CLI_C) +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) || defined(MBEDTLS_SSL_PROTO_TLS1_2) + +#include + +#include "mbedtls/debug.h" +#include "mbedtls/error.h" +#include "mbedtls/platform.h" + +#include "ssl_client.h" +#include "ssl_misc.h" +#include "ssl_tls13_keys.h" +#include "ssl_debug_helpers.h" + +#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; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_SERVERNAME); +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + return 0; +} +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_SSL_ALPN) +/* + * ssl_write_alpn_ext() + * + * Structure of the application_layer_protocol_negotiation extension in + * ClientHello: + * + * opaque ProtocolName<1..2^8-1>; + * + * struct { + * ProtocolName protocol_name_list<2..2^16-1> + * } ProtocolNameList; + * + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_alpn_ext(mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *out_len) +{ + unsigned char *p = buf; + + *out_len = 0; + + if (ssl->conf->alpn_list == NULL) { + return 0; + } + + MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding alpn extension")); + + + /* Check we have enough space for the extension type (2 bytes), the + * extension length (2 bytes) and the protocol_name_list length (2 bytes). + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6); + MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_ALPN, p, 0); + /* Skip writing extension and list length for now */ + p += 6; + + /* + * opaque ProtocolName<1..2^8-1>; + * + * struct { + * ProtocolName protocol_name_list<2..2^16-1> + * } ProtocolNameList; + */ + for (const char **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. + */ + size_t protocol_name_len = strlen(*cur); + + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 1 + protocol_name_len); + *p++ = (unsigned char) protocol_name_len; + memcpy(p, *cur, protocol_name_len); + p += protocol_name_len; + } + + *out_len = p - buf; + + /* List length = *out_len - 2 (ext_type) - 2 (ext_len) - 2 (list_len) */ + MBEDTLS_PUT_UINT16_BE(*out_len - 6, buf, 4); + + /* Extension length = *out_len - 2 (ext_type) - 2 (ext_len) */ + MBEDTLS_PUT_UINT16_BE(*out_len - 4, buf, 2); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_ALPN); +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + return 0; +} +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +/* + * Function for writing a supported groups (TLS 1.3) or supported elliptic + * curves (TLS 1.2) extension. + * + * The "extension_data" field of a supported groups extension contains a + * "NamedGroupList" value (TLS 1.3 RFC8446): + * enum { + * secp256r1(0x0017), secp384r1(0x0018), secp521r1(0x0019), + * x25519(0x001D), x448(0x001E), + * ffdhe2048(0x0100), ffdhe3072(0x0101), ffdhe4096(0x0102), + * ffdhe6144(0x0103), ffdhe8192(0x0104), + * ffdhe_private_use(0x01FC..0x01FF), + * ecdhe_private_use(0xFE00..0xFEFF), + * (0xFFFF) + * } NamedGroup; + * struct { + * NamedGroup named_group_list<2..2^16-1>; + * } NamedGroupList; + * + * The "extension_data" field of a supported elliptic curves extension contains + * a "NamedCurveList" value (TLS 1.2 RFC 8422): + * enum { + * deprecated(1..22), + * secp256r1 (23), secp384r1 (24), secp521r1 (25), + * x25519(29), x448(30), + * reserved (0xFE00..0xFEFF), + * deprecated(0xFF01..0xFF02), + * (0xFFFF) + * } NamedCurve; + * struct { + * NamedCurve named_curve_list<2..2^16-1> + * } NamedCurveList; + * + * The TLS 1.3 supported groups extension was defined to be a compatible + * generalization of the TLS 1.2 supported elliptic curves extension. They both + * share the same extension identifier. + * + * DHE groups are not supported yet. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_supported_groups_ext(mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *out_len) +{ + unsigned char *p = buf; + unsigned char *named_group_list; /* Start of named_group_list */ + size_t named_group_list_len; /* Length of named_group_list */ + const uint16_t *group_list = mbedtls_ssl_get_groups(ssl); + + *out_len = 0; + + MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding supported_groups extension")); + + /* Check if we have space for header and length fields: + * - extension_type (2 bytes) + * - extension_data_length (2 bytes) + * - named_group_list_length (2 bytes) + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6); + p += 6; + + named_group_list = p; + + if (group_list == NULL) { + return MBEDTLS_ERR_SSL_BAD_CONFIG; + } + + for (; *group_list != 0; group_list++) { + MBEDTLS_SSL_DEBUG_MSG(1, ("got supported group(%04x)", *group_list)); + +#if defined(MBEDTLS_ECP_C) + if ((mbedtls_ssl_conf_is_tls13_enabled(ssl->conf) && + mbedtls_ssl_tls13_named_group_is_ecdhe(*group_list)) || + (mbedtls_ssl_conf_is_tls12_enabled(ssl->conf) && + mbedtls_ssl_tls12_named_group_is_ecdhe(*group_list))) { + if (mbedtls_ssl_get_ecp_group_id_from_tls_id(*group_list) == + MBEDTLS_ECP_DP_NONE) { + continue; + } + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); + MBEDTLS_PUT_UINT16_BE(*group_list, p, 0); + p += 2; + MBEDTLS_SSL_DEBUG_MSG(3, ("NamedGroup: %s ( %x )", + mbedtls_ssl_get_curve_name_from_tls_id(*group_list), + *group_list)); + } +#endif /* MBEDTLS_ECP_C */ + /* Add DHE groups here */ + + } + + /* Length of named_group_list */ + named_group_list_len = p - named_group_list; + if (named_group_list_len == 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("No group available.")); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + /* Write extension_type */ + MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SUPPORTED_GROUPS, buf, 0); + /* Write extension_data_length */ + MBEDTLS_PUT_UINT16_BE(named_group_list_len + 2, buf, 2); + /* Write length of named_group_list */ + MBEDTLS_PUT_UINT16_BE(named_group_list_len, buf, 4); + + MBEDTLS_SSL_DEBUG_BUF(3, "Supported groups extension", + buf + 4, named_group_list_len + 2); + + *out_len = p - buf; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + mbedtls_ssl_tls13_set_hs_sent_ext_mask( + ssl, MBEDTLS_TLS_EXT_SUPPORTED_GROUPS); +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + + return 0; +} + +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || + MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_client_hello_cipher_suites( + mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + int *tls12_uses_ec, + size_t *out_len) +{ + unsigned char *p = buf; + const int *ciphersuite_list; + unsigned char *cipher_suites; /* Start of the cipher_suites list */ + size_t cipher_suites_len; + + *tls12_uses_ec = 0; + *out_len = 0; + + /* + * Ciphersuite list + * + * This is a list of the symmetric cipher options supported by + * the client, specifically the record protection algorithm + * ( including secret key length ) and a hash to be used with + * HKDF, in descending order of client preference. + */ + ciphersuite_list = ssl->conf->ciphersuite_list; + + /* Check there is space for the cipher suite list length (2 bytes). */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); + p += 2; + + /* Write cipher_suites + * CipherSuite cipher_suites<2..2^16-2>; + */ + cipher_suites = p; + for (size_t i = 0; ciphersuite_list[i] != 0; i++) { + int cipher_suite = ciphersuite_list[i]; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + + ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(cipher_suite); + + if (mbedtls_ssl_validate_ciphersuite(ssl, ciphersuite_info, + ssl->handshake->min_tls_version, + ssl->tls_version) != 0) { + continue; + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + (defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)) + *tls12_uses_ec |= mbedtls_ssl_ciphersuite_uses_ec(ciphersuite_info); +#endif + + MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, add ciphersuite: %04x, %s", + (unsigned int) cipher_suite, + ciphersuite_info->name)); + + /* Check there is space for the cipher suite identifier (2 bytes). */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); + MBEDTLS_PUT_UINT16_BE(cipher_suite, p, 0); + p += 2; + } + + /* + * Add TLS_EMPTY_RENEGOTIATION_INFO_SCSV + */ + int renegotiating = 0; +#if defined(MBEDTLS_SSL_RENEGOTIATION) + renegotiating = (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE); +#endif + if (!renegotiating) { + 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; + } + + /* Write the cipher_suites length in number of bytes */ + cipher_suites_len = p - cipher_suites; + MBEDTLS_PUT_UINT16_BE(cipher_suites_len, buf, 0); + MBEDTLS_SSL_DEBUG_MSG(3, + ("client hello, got %" MBEDTLS_PRINTF_SIZET " cipher suites", + cipher_suites_len/2)); + + /* Output the total length of cipher_suites field. */ + *out_len = p - buf; + + return 0; +} + +/* + * Structure of the TLS 1.3 ClientHello message: + * + * struct { + * ProtocolVersion legacy_version = 0x0303; // TLS v1.2 + * Random random; + * opaque legacy_session_id<0..32>; + * CipherSuite cipher_suites<2..2^16-2>; + * opaque legacy_compression_methods<1..2^8-1>; + * Extension extensions<8..2^16-1>; + * } ClientHello; + * + * Structure of the (D)TLS 1.2 ClientHello message: + * + * struct { + * ProtocolVersion client_version; + * Random random; + * SessionID session_id; + * opaque cookie<0..2^8-1>; // DTLS 1.2 ONLY + * CipherSuite cipher_suites<2..2^16-2>; + * CompressionMethod compression_methods<1..2^8-1>; + * select (extensions_present) { + * case false: + * struct {}; + * case true: + * Extension extensions<0..2^16-1>; + * }; + * } ClientHello; + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_client_hello_body(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len, + size_t *binders_len) +{ + int ret; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + unsigned char *p = buf; + unsigned char *p_extensions_len; /* Pointer to extensions length */ + size_t output_len; /* Length of buffer used by function */ + size_t extensions_len; /* Length of the list of extensions*/ + int tls12_uses_ec = 0; + + *out_len = 0; + *binders_len = 0; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + unsigned char propose_tls12 = + (handshake->min_tls_version <= MBEDTLS_SSL_VERSION_TLS1_2) + && + (MBEDTLS_SSL_VERSION_TLS1_2 <= ssl->tls_version); +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + unsigned char propose_tls13 = + (handshake->min_tls_version <= MBEDTLS_SSL_VERSION_TLS1_3) + && + (MBEDTLS_SSL_VERSION_TLS1_3 <= ssl->tls_version); +#endif + + /* + * Write client_version (TLS 1.2) or legacy_version (TLS 1.3) + * + * In all cases this is the TLS 1.2 version. + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); + mbedtls_ssl_write_version(p, ssl->conf->transport, + MBEDTLS_SSL_VERSION_TLS1_2); + p += 2; + + /* ... + * Random random; + * ... + * + * The random bytes have been prepared by ssl_prepare_client_hello() into + * the handshake->randbytes buffer and are copied here into the output + * buffer. + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, MBEDTLS_CLIENT_HELLO_RANDOM_LEN); + memcpy(p, handshake->randbytes, MBEDTLS_CLIENT_HELLO_RANDOM_LEN); + MBEDTLS_SSL_DEBUG_BUF(3, "client hello, random bytes", + p, MBEDTLS_CLIENT_HELLO_RANDOM_LEN); + p += MBEDTLS_CLIENT_HELLO_RANDOM_LEN; + + /* TLS 1.2: + * ... + * SessionID session_id; + * ... + * with + * opaque SessionID<0..32>; + * + * TLS 1.3: + * ... + * opaque legacy_session_id<0..32>; + * ... + * + * The (legacy) session identifier bytes have been prepared by + * ssl_prepare_client_hello() into the ssl->session_negotiate->id buffer + * and are copied here into the output buffer. + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, ssl->session_negotiate->id_len + 1); + *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_BUF(3, "session id", ssl->session_negotiate->id, + ssl->session_negotiate->id_len); + + /* DTLS 1.2 ONLY + * ... + * opaque cookie<0..2^8-1>; + * ... + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_DTLS) + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { +#if !defined(MBEDTLS_SSL_PROTO_TLS1_3) + uint8_t cookie_len = 0; +#else + uint16_t cookie_len = 0; +#endif /* !MBEDTLS_SSL_PROTO_TLS1_3 */ + + if (handshake->cookie != NULL) { + MBEDTLS_SSL_DEBUG_BUF(3, "client hello, cookie", + handshake->cookie, + handshake->cookie_len); + cookie_len = handshake->cookie_len; + } + + MBEDTLS_SSL_CHK_BUF_PTR(p, end, cookie_len + 1); + *p++ = (unsigned char) cookie_len; + if (cookie_len > 0) { + memcpy(p, handshake->cookie, cookie_len); + p += cookie_len; + } + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && MBEDTLS_SSL_PROTO_DTLS */ + + /* Write cipher_suites */ + ret = ssl_write_client_hello_cipher_suites(ssl, p, end, + &tls12_uses_ec, + &output_len); + if (ret != 0) { + return ret; + } + p += output_len; + + /* Write legacy_compression_methods (TLS 1.3) or + * compression_methods (TLS 1.2) + * + * For every TLS 1.3 ClientHello, this vector MUST contain exactly + * one byte set to zero, which corresponds to the 'null' compression + * method in prior versions of TLS. + * + * For TLS 1.2 ClientHello, for security reasons we do not support + * compression anymore, thus also just the 'null' compression method. + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); + *p++ = 1; + *p++ = MBEDTLS_SSL_COMPRESS_NULL; + + /* Write extensions */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + /* Keeping track of the included extensions */ + handshake->sent_extensions = MBEDTLS_SSL_EXT_MASK_NONE; +#endif + + /* First write extensions, then the total length */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); + p_extensions_len = p; + p += 2; + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + /* Write server name extension */ + ret = ssl_write_hostname_ext(ssl, p, end, &output_len); + if (ret != 0) { + return ret; + } + p += output_len; +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_SSL_ALPN) + ret = ssl_write_alpn_ext(ssl, p, end, &output_len); + if (ret != 0) { + return ret; + } + p += output_len; +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + if (propose_tls13) { + ret = mbedtls_ssl_tls13_write_client_hello_exts(ssl, p, end, + &output_len); + if (ret != 0) { + return ret; + } + p += output_len; + } +#endif + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if ( +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + (propose_tls13 && + mbedtls_ssl_conf_tls13_some_ephemeral_enabled(ssl)) || +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + (propose_tls12 && tls12_uses_ec) || +#endif + 0) { + ret = ssl_write_supported_groups_ext(ssl, p, end, &output_len); + if (ret != 0) { + return ret; + } + p += output_len; + } +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) + if ( +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + (propose_tls13 && mbedtls_ssl_conf_tls13_ephemeral_enabled(ssl)) || +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + propose_tls12 || +#endif + 0) { + ret = mbedtls_ssl_write_sig_alg_ext(ssl, p, end, &output_len); + if (ret != 0) { + return ret; + } + p += output_len; + } +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if (propose_tls12) { + ret = mbedtls_ssl_tls12_write_client_hello_exts(ssl, p, end, + tls12_uses_ec, + &output_len); + if (ret != 0) { + return ret; + } + p += output_len; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) + /* The "pre_shared_key" extension (RFC 8446 Section 4.2.11) + * MUST be the last extension in the ClientHello. + */ + if (propose_tls13 && mbedtls_ssl_conf_tls13_some_psk_enabled(ssl)) { + ret = mbedtls_ssl_tls13_write_identities_of_pre_shared_key_ext( + ssl, p, end, &output_len, binders_len); + if (ret != 0) { + return ret; + } + p += output_len; + } +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ + + /* Write the length of the list of extensions. */ + extensions_len = p - p_extensions_len - 2; + + if (extensions_len == 0) { + p = p_extensions_len; + } else { + MBEDTLS_PUT_UINT16_BE(extensions_len, p_extensions_len, 0); + MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, total extension length: %" \ + MBEDTLS_PRINTF_SIZET, extensions_len)); + MBEDTLS_SSL_DEBUG_BUF(3, "client hello extensions", + p_extensions_len, extensions_len); + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + MBEDTLS_SSL_PRINT_EXTS( + 3, MBEDTLS_SSL_HS_CLIENT_HELLO, handshake->sent_extensions); +#endif + + *out_len = p - buf; + return 0; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_generate_random(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *randbytes = ssl->handshake->randbytes; + size_t gmt_unix_time_len = 0; + + /* + * Generate the random bytes + * + * TLS 1.2 case: + * struct { + * uint32 gmt_unix_time; + * opaque random_bytes[28]; + * } Random; + * + * TLS 1.3 case: + * opaque Random[32]; + */ + if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2) { +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t gmt_unix_time = mbedtls_time(NULL); + MBEDTLS_PUT_UINT32_BE(gmt_unix_time, randbytes, 0); + gmt_unix_time_len = 4; + + MBEDTLS_SSL_DEBUG_MSG(3, + ("client hello, current time: %" MBEDTLS_PRINTF_LONGLONG, + (long long) gmt_unix_time)); +#endif /* MBEDTLS_HAVE_TIME */ + } + + ret = ssl->conf->f_rng(ssl->conf->p_rng, + randbytes + gmt_unix_time_len, + MBEDTLS_CLIENT_HELLO_RANDOM_LEN - gmt_unix_time_len); + return ret; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_prepare_client_hello(mbedtls_ssl_context *ssl) +{ + int ret; + size_t session_id_len; + mbedtls_ssl_session *session_negotiate = ssl->session_negotiate; + + if (session_negotiate == NULL) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ + defined(MBEDTLS_SSL_SESSION_TICKETS) && \ + defined(MBEDTLS_HAVE_TIME) + + /* Check if a tls13 ticket has been configured. */ + if (ssl->handshake->resume != 0 && + session_negotiate->tls_version == MBEDTLS_SSL_VERSION_TLS1_3 && + session_negotiate->ticket != NULL) { + mbedtls_time_t now = mbedtls_time(NULL); + uint64_t age = (uint64_t) (now - session_negotiate->ticket_received); + if (session_negotiate->ticket_received > now || + age > session_negotiate->ticket_lifetime) { + /* Without valid ticket, disable session resumption.*/ + MBEDTLS_SSL_DEBUG_MSG( + 3, ("Ticket expired, disable session resumption")); + ssl->handshake->resume = 0; + } + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 && + MBEDTLS_SSL_SESSION_TICKETS && + MBEDTLS_HAVE_TIME */ + + if (ssl->conf->f_rng == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("no RNG provided")); + return MBEDTLS_ERR_SSL_NO_RNG; + } + + /* Bet on the highest configured version if we are not in a TLS 1.2 + * renegotiation or session resumption. + */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) { + ssl->handshake->min_tls_version = ssl->tls_version; + } else +#endif + { + if (ssl->handshake->resume) { + ssl->tls_version = session_negotiate->tls_version; + ssl->handshake->min_tls_version = ssl->tls_version; + } else { + ssl->tls_version = ssl->conf->max_tls_version; + ssl->handshake->min_tls_version = ssl->conf->min_tls_version; + } + } + + /* + * Generate the random bytes, except when responding to a verify request + * where we MUST reuse the previously generated random bytes + * (RFC 6347 4.2.1). + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if ((ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) || + (ssl->handshake->cookie == NULL)) +#endif + { + ret = ssl_generate_random(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "Random bytes generation failed", ret); + return ret; + } + } + + /* + * Prepare session identifier. At that point, the length of the session + * identifier in the SSL context `ssl->session_negotiate->id_len` is equal + * to zero, except in the case of a TLS 1.2 session renegotiation or + * session resumption. + */ + session_id_len = session_negotiate->id_len; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2) { + if (session_id_len < 16 || session_id_len > 32 || +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE || +#endif + ssl->handshake->resume == 0) { + session_id_len = 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." + */ + int renegotiating = 0; +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) { + renegotiating = 1; + } +#endif + if (!renegotiating) { + if ((session_negotiate->ticket != NULL) && + (session_negotiate->ticket_len != 0)) { + session_id_len = 32; + } + } +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { + /* + * Create a legacy session identifier for the purpose of middlebox + * compatibility only if one has not been created already, which is + * the case if we are here for the TLS 1.3 second ClientHello. + * + * Versions of TLS before TLS 1.3 supported a "session resumption" + * feature which has been merged with pre-shared keys in TLS 1.3 + * version. A client which has a cached session ID set by a pre-TLS 1.3 + * server SHOULD set this field to that value. In compatibility mode, + * this field MUST be non-empty, so a client not offering a pre-TLS 1.3 + * session MUST generate a new 32-byte value. This value need not be + * random but SHOULD be unpredictable to avoid implementations fixating + * on a specific value (also known as ossification). Otherwise, it MUST + * be set as a zero-length vector ( i.e., a zero-valued single byte + * length field ). + */ + session_id_len = 32; + } +#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ + + if (session_id_len != session_negotiate->id_len) { + session_negotiate->id_len = session_id_len; + if (session_id_len > 0) { + ret = ssl->conf->f_rng(ssl->conf->p_rng, + session_negotiate->id, + session_id_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "creating session id failed", ret); + return ret; + } + } + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ + defined(MBEDTLS_SSL_SESSION_TICKETS) && \ + defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3 && + ssl->handshake->resume) { + int hostname_mismatch = ssl->hostname != NULL || + session_negotiate->hostname != NULL; + if (ssl->hostname != NULL && session_negotiate->hostname != NULL) { + hostname_mismatch = strcmp( + ssl->hostname, session_negotiate->hostname) != 0; + } + + if (hostname_mismatch) { + MBEDTLS_SSL_DEBUG_MSG( + 1, ("Hostname mismatch the session ticket, " + "disable session resumption.")); + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + } else { + return mbedtls_ssl_session_set_hostname(session_negotiate, + ssl->hostname); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 && + MBEDTLS_SSL_SESSION_TICKETS && + MBEDTLS_SSL_SERVER_NAME_INDICATION */ + + return 0; +} +/* + * Write ClientHello handshake message. + * Handler for MBEDTLS_SSL_CLIENT_HELLO + */ +int mbedtls_ssl_write_client_hello(mbedtls_ssl_context *ssl) +{ + int ret = 0; + unsigned char *buf; + size_t buf_len, msg_len, binders_len; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> write client hello")); + + MBEDTLS_SSL_PROC_CHK(ssl_prepare_client_hello(ssl)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg( + ssl, MBEDTLS_SSL_HS_CLIENT_HELLO, + &buf, &buf_len)); + + MBEDTLS_SSL_PROC_CHK(ssl_write_client_hello_body(ssl, buf, + buf + buf_len, + &msg_len, + &binders_len)); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_DTLS) + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { + ssl->out_msglen = msg_len + 4; + mbedtls_ssl_send_flight_completed(ssl); + + /* + * The two functions below may try to send data on the network and + * can return with the MBEDTLS_ERR_SSL_WANT_READ error code when they + * fail to do so and the transmission has to be retried later. In that + * case as in fatal error cases, we return immediately. But we must have + * set the handshake state to the next state at that point to ensure + * that we will not write and send again a ClientHello when we + * eventually succeed in sending the pending data. + */ + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_HELLO); + + if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret); + return ret; + } + + if ((ret = mbedtls_ssl_flight_transmit(ssl)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_flight_transmit", ret); + return ret; + } + } else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && MBEDTLS_SSL_PROTO_DTLS */ + { + + ret = mbedtls_ssl_add_hs_hdr_to_checksum(ssl, + MBEDTLS_SSL_HS_CLIENT_HELLO, + msg_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_add_hs_hdr_to_checksum", ret); + return ret; + } + ret = ssl->handshake->update_checksum(ssl, buf, msg_len - binders_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "update_checksum", ret); + return ret; + } +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) + if (binders_len > 0) { + MBEDTLS_SSL_PROC_CHK( + mbedtls_ssl_tls13_write_binders_of_pre_shared_key_ext( + ssl, buf + msg_len - binders_len, buf + msg_len)); + ret = ssl->handshake->update_checksum(ssl, buf + msg_len - binders_len, + binders_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "update_checksum", ret); + return ret; + } + } +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(ssl, + buf_len, + msg_len)); + + /* + * Set next state. Note that if TLS 1.3 is proposed, this may be + * overwritten by mbedtls_ssl_tls13_finalize_client_hello(). + */ + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_HELLO); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + if (ssl->handshake->min_tls_version <= MBEDTLS_SSL_VERSION_TLS1_3 && + MBEDTLS_SSL_VERSION_TLS1_3 <= ssl->tls_version) { + ret = mbedtls_ssl_tls13_finalize_client_hello(ssl); + } +#endif + } + +cleanup: + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= write client hello")); + return ret; +} + +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 || MBEDTLS_SSL_PROTO_TLS1_2 */ +#endif /* MBEDTLS_SSL_CLI_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_client.h b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_client.h new file mode 100644 index 0000000..f57bea3 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_client.h @@ -0,0 +1,34 @@ +/** + * TLS 1.2 and 1.3 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. + */ + +#ifndef MBEDTLS_SSL_CLIENT_H +#define MBEDTLS_SSL_CLIENT_H + +#include "common.h" + +#if defined(MBEDTLS_SSL_TLS_C) +#include "ssl_misc.h" +#endif + +#include + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_write_client_hello(mbedtls_ssl_context *ssl); + +#endif /* MBEDTLS_SSL_CLIENT_H */ 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..ef4d188 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_cookie.c @@ -0,0 +1,390 @@ +/* + * 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) + +#include "mbedtls/platform.h" + +#include "mbedtls/ssl_cookie.h" +#include "ssl_misc.h" +#include "mbedtls/error.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/constant_time.h" + +#include "mbedtls/legacy_or_psa.h" + +#include + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \ + psa_to_ssl_errors, \ + psa_generic_status_to_mbedtls) +#endif + +/* + * If DTLS is in use, then at least one of SHA-256 or SHA-384 is + * available. Try SHA-256 first as 384 wastes resources + */ +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_LOWLEVEL_OR_PSA) +#define COOKIE_MD MBEDTLS_MD_SHA256 +#define COOKIE_MD_OUTLEN 32 +#define COOKIE_HMAC_LEN 28 +#elif defined(MBEDTLS_HAS_ALG_SHA_384_VIA_LOWLEVEL_OR_PSA) +#define COOKIE_MD MBEDTLS_MD_SHA384 +#define COOKIE_MD_OUTLEN 48 +#define COOKIE_HMAC_LEN 28 +#else +#error "DTLS hello verify needs SHA-256 or SHA-384" +#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) +{ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + ctx->psa_hmac_key = MBEDTLS_SVC_KEY_ID_INIT; +#else + mbedtls_md_init(&ctx->hmac_ctx); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#if !defined(MBEDTLS_HAVE_TIME) + ctx->serial = 0; +#endif + ctx->timeout = MBEDTLS_SSL_COOKIE_TIMEOUT; + +#if !defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init(&ctx->mutex); +#endif +#endif /* !MBEDTLS_USE_PSA_CRYPTO */ +} + +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) +{ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_destroy_key(ctx->psa_hmac_key); +#else + mbedtls_md_free(&ctx->hmac_ctx); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free(&ctx->mutex); +#endif +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + 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) +{ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_algorithm_t alg; + + (void) f_rng; + (void) p_rng; + + alg = mbedtls_hash_info_psa_from_md(COOKIE_MD); + if (alg == 0) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + ctx->psa_hmac_alg = PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(alg), + COOKIE_HMAC_LEN); + + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_MESSAGE | + PSA_KEY_USAGE_SIGN_MESSAGE); + psa_set_key_algorithm(&attributes, ctx->psa_hmac_alg); + psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC); + psa_set_key_bits(&attributes, PSA_BYTES_TO_BITS(COOKIE_MD_OUTLEN)); + + if ((status = psa_generate_key(&attributes, + &ctx->psa_hmac_key)) != PSA_SUCCESS) { + return PSA_TO_MBEDTLS_ERR(status); + } +#else + 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)); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + return 0; +} + +#if !defined(MBEDTLS_USE_PSA_CRYPTO) +/* + * 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; +} +#endif /* !MBEDTLS_USE_PSA_CRYPTO */ + +/* + * 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) +{ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t sign_mac_length = 0; +#endif + 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_USE_PSA_CRYPTO) + status = psa_mac_sign_setup(&operation, ctx->psa_hmac_key, + ctx->psa_hmac_alg); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + goto exit; + } + + status = psa_mac_update(&operation, *p - 4, 4); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + goto exit; + } + + status = psa_mac_update(&operation, cli_id, cli_id_len); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + goto exit; + } + + status = psa_mac_sign_finish(&operation, *p, COOKIE_MD_OUTLEN, + &sign_mac_length); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + goto exit; + } + + *p += COOKIE_HMAC_LEN; + + ret = 0; +#else +#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 +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +exit: + status = psa_mac_abort(&operation); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + 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) +{ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; +#else + unsigned char ref_hmac[COOKIE_HMAC_LEN]; + unsigned char *p = ref_hmac; +#endif + int ret = 0; + 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_USE_PSA_CRYPTO) + status = psa_mac_verify_setup(&operation, ctx->psa_hmac_key, + ctx->psa_hmac_alg); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + goto exit; + } + + status = psa_mac_update(&operation, cookie, 4); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + goto exit; + } + + status = psa_mac_update(&operation, cli_id, + cli_id_len); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + goto exit; + } + + status = psa_mac_verify_finish(&operation, cookie + 4, + COOKIE_HMAC_LEN); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + goto exit; + } + + ret = 0; +#else +#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; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#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: +#if defined(MBEDTLS_USE_PSA_CRYPTO) + status = psa_mac_abort(&operation); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + } +#else + mbedtls_platform_zeroize(ref_hmac, sizeof(ref_hmac)); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + return ret; +} +#endif /* MBEDTLS_SSL_COOKIE_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_debug_helpers.h b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_debug_helpers.h new file mode 100644 index 0000000..5c22ed2 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_debug_helpers.h @@ -0,0 +1,90 @@ +/** + * \file ssl_debug_helpers.h + * + * \brief Automatically generated helper functions for debugging + */ +/* + * 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_DEBUG_HELPERS_H +#define MBEDTLS_SSL_DEBUG_HELPERS_H + +#include "common.h" + +#if defined(MBEDTLS_DEBUG_C) + +#include "mbedtls/ssl.h" +#include "ssl_misc.h" + + +const char *mbedtls_ssl_states_str(mbedtls_ssl_states in); + +const char *mbedtls_ssl_protocol_version_str(mbedtls_ssl_protocol_version in); + +const char *mbedtls_tls_prf_types_str(mbedtls_tls_prf_types in); + +const char *mbedtls_ssl_key_export_type_str(mbedtls_ssl_key_export_type in); + +const char *mbedtls_ssl_sig_alg_to_str(uint16_t in); + +const char *mbedtls_ssl_named_group_to_str(uint16_t in); + +const char *mbedtls_ssl_get_extension_name(unsigned int extension_type); + +void mbedtls_ssl_print_extensions(const mbedtls_ssl_context *ssl, + int level, const char *file, int line, + int hs_msg_type, uint32_t extensions_mask, + const char *extra); + +void mbedtls_ssl_print_extension(const mbedtls_ssl_context *ssl, + int level, const char *file, int line, + int hs_msg_type, unsigned int extension_type, + const char *extra_msg0, const char *extra_msg1); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) +void mbedtls_ssl_print_ticket_flags(const mbedtls_ssl_context *ssl, + int level, const char *file, int line, + unsigned int flags); +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS */ + +#define MBEDTLS_SSL_PRINT_EXTS(level, hs_msg_type, extensions_mask) \ + mbedtls_ssl_print_extensions(ssl, level, __FILE__, __LINE__, \ + hs_msg_type, extensions_mask, NULL) + +#define MBEDTLS_SSL_PRINT_EXT(level, hs_msg_type, extension_type, extra) \ + mbedtls_ssl_print_extension(ssl, level, __FILE__, __LINE__, \ + hs_msg_type, extension_type, \ + extra, NULL) + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) +#define MBEDTLS_SSL_PRINT_TICKET_FLAGS(level, flags) \ + mbedtls_ssl_print_ticket_flags(ssl, level, __FILE__, __LINE__, flags) +#endif + +#else + +#define MBEDTLS_SSL_PRINT_EXTS(level, hs_msg_type, extension_mask) + +#define MBEDTLS_SSL_PRINT_EXT(level, hs_msg_type, extension_type, extra) + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) +#define MBEDTLS_SSL_PRINT_TICKET_FLAGS(level, flags) +#endif + +#endif /* MBEDTLS_DEBUG_C */ + +#endif /* MBEDTLS_SSL_DEBUG_HELPERS_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_debug_helpers_generated.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_debug_helpers_generated.c new file mode 100644 index 0000000..9add9db --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_debug_helpers_generated.c @@ -0,0 +1,225 @@ +/* Automatically generated by generate_ssl_debug_helpers.py. DO NOT EDIT. */ + +/** + * \file ssl_debug_helpers_generated.c + * + * \brief Automatically generated helper functions for debugging + */ +/* + * 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) + +#include "ssl_debug_helpers.h" + + +const char *mbedtls_ssl_named_group_to_str( uint16_t in ) +{ + switch( in ) + { + case MBEDTLS_SSL_IANA_TLS_GROUP_SECP192K1: + return "secp192k1"; + case MBEDTLS_SSL_IANA_TLS_GROUP_SECP192R1: + return "secp192r1"; + case MBEDTLS_SSL_IANA_TLS_GROUP_SECP224K1: + return "secp224k1"; + case MBEDTLS_SSL_IANA_TLS_GROUP_SECP224R1: + return "secp224r1"; + case MBEDTLS_SSL_IANA_TLS_GROUP_SECP256K1: + return "secp256k1"; + case MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1: + return "secp256r1"; + case MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1: + return "secp384r1"; + case MBEDTLS_SSL_IANA_TLS_GROUP_SECP521R1: + return "secp521r1"; + case MBEDTLS_SSL_IANA_TLS_GROUP_BP256R1: + return "bp256r1"; + case MBEDTLS_SSL_IANA_TLS_GROUP_BP384R1: + return "bp384r1"; + case MBEDTLS_SSL_IANA_TLS_GROUP_BP512R1: + return "bp512r1"; + case MBEDTLS_SSL_IANA_TLS_GROUP_X25519: + return "x25519"; + case MBEDTLS_SSL_IANA_TLS_GROUP_X448: + return "x448"; + case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE2048: + return "ffdhe2048"; + case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE3072: + return "ffdhe3072"; + case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE4096: + return "ffdhe4096"; + case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE6144: + return "ffdhe6144"; + case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE8192: + return "ffdhe8192"; + }; + + return "UNKOWN"; +} +const char *mbedtls_ssl_sig_alg_to_str( uint16_t in ) +{ + switch( in ) + { + case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256: + return "rsa_pkcs1_sha256"; + case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384: + return "rsa_pkcs1_sha384"; + case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512: + return "rsa_pkcs1_sha512"; + case MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256: + return "ecdsa_secp256r1_sha256"; + case MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384: + return "ecdsa_secp384r1_sha384"; + case MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512: + return "ecdsa_secp521r1_sha512"; + case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256: + return "rsa_pss_rsae_sha256"; + case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384: + return "rsa_pss_rsae_sha384"; + case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512: + return "rsa_pss_rsae_sha512"; + case MBEDTLS_TLS1_3_SIG_ED25519: + return "ed25519"; + case MBEDTLS_TLS1_3_SIG_ED448: + return "ed448"; + case MBEDTLS_TLS1_3_SIG_RSA_PSS_PSS_SHA256: + return "rsa_pss_pss_sha256"; + case MBEDTLS_TLS1_3_SIG_RSA_PSS_PSS_SHA384: + return "rsa_pss_pss_sha384"; + case MBEDTLS_TLS1_3_SIG_RSA_PSS_PSS_SHA512: + return "rsa_pss_pss_sha512"; + case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA1: + return "rsa_pkcs1_sha1"; + case MBEDTLS_TLS1_3_SIG_ECDSA_SHA1: + return "ecdsa_sha1"; + case MBEDTLS_TLS1_3_SIG_NONE: + return "none"; + }; + + return "UNKNOWN"; +} +const char *mbedtls_ssl_states_str( mbedtls_ssl_states in ) +{ + const char * in_to_str[]= + { + [MBEDTLS_SSL_HELLO_REQUEST] = "MBEDTLS_SSL_HELLO_REQUEST", + [MBEDTLS_SSL_CLIENT_HELLO] = "MBEDTLS_SSL_CLIENT_HELLO", + [MBEDTLS_SSL_SERVER_HELLO] = "MBEDTLS_SSL_SERVER_HELLO", + [MBEDTLS_SSL_SERVER_CERTIFICATE] = "MBEDTLS_SSL_SERVER_CERTIFICATE", + [MBEDTLS_SSL_SERVER_KEY_EXCHANGE] = "MBEDTLS_SSL_SERVER_KEY_EXCHANGE", + [MBEDTLS_SSL_CERTIFICATE_REQUEST] = "MBEDTLS_SSL_CERTIFICATE_REQUEST", + [MBEDTLS_SSL_SERVER_HELLO_DONE] = "MBEDTLS_SSL_SERVER_HELLO_DONE", + [MBEDTLS_SSL_CLIENT_CERTIFICATE] = "MBEDTLS_SSL_CLIENT_CERTIFICATE", + [MBEDTLS_SSL_CLIENT_KEY_EXCHANGE] = "MBEDTLS_SSL_CLIENT_KEY_EXCHANGE", + [MBEDTLS_SSL_CERTIFICATE_VERIFY] = "MBEDTLS_SSL_CERTIFICATE_VERIFY", + [MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC] = "MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC", + [MBEDTLS_SSL_CLIENT_FINISHED] = "MBEDTLS_SSL_CLIENT_FINISHED", + [MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC] = "MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC", + [MBEDTLS_SSL_SERVER_FINISHED] = "MBEDTLS_SSL_SERVER_FINISHED", + [MBEDTLS_SSL_FLUSH_BUFFERS] = "MBEDTLS_SSL_FLUSH_BUFFERS", + [MBEDTLS_SSL_HANDSHAKE_WRAPUP] = "MBEDTLS_SSL_HANDSHAKE_WRAPUP", + [MBEDTLS_SSL_NEW_SESSION_TICKET] = "MBEDTLS_SSL_NEW_SESSION_TICKET", + [MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT] = "MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT", + [MBEDTLS_SSL_HELLO_RETRY_REQUEST] = "MBEDTLS_SSL_HELLO_RETRY_REQUEST", + [MBEDTLS_SSL_ENCRYPTED_EXTENSIONS] = "MBEDTLS_SSL_ENCRYPTED_EXTENSIONS", + [MBEDTLS_SSL_END_OF_EARLY_DATA] = "MBEDTLS_SSL_END_OF_EARLY_DATA", + [MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY] = "MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY", + [MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED] = "MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED", + [MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO] = "MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO", + [MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO] = "MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO", + [MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO] = "MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO", + [MBEDTLS_SSL_SERVER_CCS_AFTER_HELLO_RETRY_REQUEST] = "MBEDTLS_SSL_SERVER_CCS_AFTER_HELLO_RETRY_REQUEST", + [MBEDTLS_SSL_HANDSHAKE_OVER] = "MBEDTLS_SSL_HANDSHAKE_OVER", + [MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET] = "MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET", + [MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH] = "MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH", + }; + + if( in > ( sizeof( in_to_str )/sizeof( in_to_str[0]) - 1 ) || + in_to_str[ in ] == NULL ) + { + return "UNKNOWN_VALUE"; + } + return in_to_str[ in ]; +} + +const char *mbedtls_ssl_protocol_version_str( mbedtls_ssl_protocol_version in ) +{ + const char * in_to_str[]= + { + [MBEDTLS_SSL_VERSION_UNKNOWN] = "MBEDTLS_SSL_VERSION_UNKNOWN", + [MBEDTLS_SSL_VERSION_TLS1_2] = "MBEDTLS_SSL_VERSION_TLS1_2", + [MBEDTLS_SSL_VERSION_TLS1_3] = "MBEDTLS_SSL_VERSION_TLS1_3", + }; + + if( in > ( sizeof( in_to_str )/sizeof( in_to_str[0]) - 1 ) || + in_to_str[ in ] == NULL ) + { + return "UNKNOWN_VALUE"; + } + return in_to_str[ in ]; +} + +const char *mbedtls_tls_prf_types_str( mbedtls_tls_prf_types in ) +{ + const char * in_to_str[]= + { + [MBEDTLS_SSL_TLS_PRF_NONE] = "MBEDTLS_SSL_TLS_PRF_NONE", + [MBEDTLS_SSL_TLS_PRF_SHA384] = "MBEDTLS_SSL_TLS_PRF_SHA384", + [MBEDTLS_SSL_TLS_PRF_SHA256] = "MBEDTLS_SSL_TLS_PRF_SHA256", + [MBEDTLS_SSL_HKDF_EXPAND_SHA384] = "MBEDTLS_SSL_HKDF_EXPAND_SHA384", + [MBEDTLS_SSL_HKDF_EXPAND_SHA256] = "MBEDTLS_SSL_HKDF_EXPAND_SHA256", + }; + + if( in > ( sizeof( in_to_str )/sizeof( in_to_str[0]) - 1 ) || + in_to_str[ in ] == NULL ) + { + return "UNKNOWN_VALUE"; + } + return in_to_str[ in ]; +} + +const char *mbedtls_ssl_key_export_type_str( mbedtls_ssl_key_export_type in ) +{ + const char * in_to_str[]= + { + [MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET] = "MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET", +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + [MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_EARLY_SECRET] = "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_EARLY_SECRET", + [MBEDTLS_SSL_KEY_EXPORT_TLS1_3_EARLY_EXPORTER_SECRET] = "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_EARLY_EXPORTER_SECRET", + [MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_HANDSHAKE_TRAFFIC_SECRET] = "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_HANDSHAKE_TRAFFIC_SECRET", + [MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_HANDSHAKE_TRAFFIC_SECRET] = "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_HANDSHAKE_TRAFFIC_SECRET", + [MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_APPLICATION_TRAFFIC_SECRET] = "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_APPLICATION_TRAFFIC_SECRET", + [MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_APPLICATION_TRAFFIC_SECRET] = "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_APPLICATION_TRAFFIC_SECRET", +#endif + }; + + if( in > ( sizeof( in_to_str )/sizeof( in_to_str[0]) - 1 ) || + in_to_str[ in ] == NULL ) + { + return "UNKNOWN_VALUE"; + } + return in_to_str[ in ]; +} + + + +#endif /* MBEDTLS_DEBUG_C */ +/* End of automatically generated file. */ + diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_misc.h b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_misc.h new file mode 100644 index 0000000..6fe0414 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_misc.h @@ -0,0 +1,2769 @@ +/** + * \file ssl_misc.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_MISC_H +#define MBEDTLS_SSL_MISC_H + +#include "mbedtls/build_info.h" + +#include "mbedtls/ssl.h" +#include "mbedtls/cipher.h" + +#if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3) +#include "psa/crypto.h" +#include "mbedtls/psa_util.h" +#include "hash_info.h" +#endif +#include "mbedtls/legacy_or_psa.h" + +#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) && \ + !defined(MBEDTLS_USE_PSA_CRYPTO) +#include "mbedtls/ecjpake.h" +#endif + +#include "mbedtls/pk.h" +#include "common.h" + +/* 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) */ + +/* Faked handshake message identity for HelloRetryRequest. */ +#define MBEDTLS_SSL_TLS1_3_HS_HELLO_RETRY_REQUEST (-MBEDTLS_SSL_HS_SERVER_HELLO) + +/* + * Internal identity of handshake extensions + */ +#define MBEDTLS_SSL_EXT_ID_UNRECOGNIZED 0 +#define MBEDTLS_SSL_EXT_ID_SERVERNAME 1 +#define MBEDTLS_SSL_EXT_ID_SERVERNAME_HOSTNAME 1 +#define MBEDTLS_SSL_EXT_ID_MAX_FRAGMENT_LENGTH 2 +#define MBEDTLS_SSL_EXT_ID_STATUS_REQUEST 3 +#define MBEDTLS_SSL_EXT_ID_SUPPORTED_GROUPS 4 +#define MBEDTLS_SSL_EXT_ID_SUPPORTED_ELLIPTIC_CURVES 4 +#define MBEDTLS_SSL_EXT_ID_SIG_ALG 5 +#define MBEDTLS_SSL_EXT_ID_USE_SRTP 6 +#define MBEDTLS_SSL_EXT_ID_HEARTBEAT 7 +#define MBEDTLS_SSL_EXT_ID_ALPN 8 +#define MBEDTLS_SSL_EXT_ID_SCT 9 +#define MBEDTLS_SSL_EXT_ID_CLI_CERT_TYPE 10 +#define MBEDTLS_SSL_EXT_ID_SERV_CERT_TYPE 11 +#define MBEDTLS_SSL_EXT_ID_PADDING 12 +#define MBEDTLS_SSL_EXT_ID_PRE_SHARED_KEY 13 +#define MBEDTLS_SSL_EXT_ID_EARLY_DATA 14 +#define MBEDTLS_SSL_EXT_ID_SUPPORTED_VERSIONS 15 +#define MBEDTLS_SSL_EXT_ID_COOKIE 16 +#define MBEDTLS_SSL_EXT_ID_PSK_KEY_EXCHANGE_MODES 17 +#define MBEDTLS_SSL_EXT_ID_CERT_AUTH 18 +#define MBEDTLS_SSL_EXT_ID_OID_FILTERS 19 +#define MBEDTLS_SSL_EXT_ID_POST_HANDSHAKE_AUTH 20 +#define MBEDTLS_SSL_EXT_ID_SIG_ALG_CERT 21 +#define MBEDTLS_SSL_EXT_ID_KEY_SHARE 22 +#define MBEDTLS_SSL_EXT_ID_TRUNCATED_HMAC 23 +#define MBEDTLS_SSL_EXT_ID_SUPPORTED_POINT_FORMATS 24 +#define MBEDTLS_SSL_EXT_ID_ENCRYPT_THEN_MAC 25 +#define MBEDTLS_SSL_EXT_ID_EXTENDED_MASTER_SECRET 26 +#define MBEDTLS_SSL_EXT_ID_SESSION_TICKET 27 +#define MBEDTLS_SSL_EXT_ID_RECORD_SIZE_LIMIT 28 + +/* Utility for translating IANA extension type. */ +uint32_t mbedtls_ssl_get_extension_id(unsigned int extension_type); +uint32_t mbedtls_ssl_get_extension_mask(unsigned int extension_type); +/* Macros used to define mask constants */ +#define MBEDTLS_SSL_EXT_MASK(id) (1ULL << (MBEDTLS_SSL_EXT_ID_##id)) +/* Reset value of extension mask */ +#define MBEDTLS_SSL_EXT_MASK_NONE 0 + +/* In messages containing extension requests, we should ignore unrecognized + * extensions. In messages containing extension responses, unrecognized + * extensions should result in handshake abortion. Messages containing + * extension requests include ClientHello, CertificateRequest and + * NewSessionTicket. Messages containing extension responses include + * ServerHello, HelloRetryRequest, EncryptedExtensions and Certificate. + * + * RFC 8446 section 4.1.3 + * + * The ServerHello MUST only include extensions which are required to establish + * the cryptographic context and negotiate the protocol version. + * + * RFC 8446 section 4.2 + * + * If an implementation receives an extension which it recognizes and which is + * not specified for the message in which it appears, it MUST abort the handshake + * with an "illegal_parameter" alert. + */ + +/* Extensions that are not recognized by TLS 1.3 */ +#define MBEDTLS_SSL_TLS1_3_EXT_MASK_UNRECOGNIZED \ + (MBEDTLS_SSL_EXT_MASK(SUPPORTED_POINT_FORMATS) | \ + MBEDTLS_SSL_EXT_MASK(ENCRYPT_THEN_MAC) | \ + MBEDTLS_SSL_EXT_MASK(EXTENDED_MASTER_SECRET) | \ + MBEDTLS_SSL_EXT_MASK(SESSION_TICKET) | \ + MBEDTLS_SSL_EXT_MASK(TRUNCATED_HMAC) | \ + MBEDTLS_SSL_EXT_MASK(UNRECOGNIZED)) + +/* RFC 8446 section 4.2. Allowed extensions for ClientHello */ +#define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CH \ + (MBEDTLS_SSL_EXT_MASK(SERVERNAME) | \ + MBEDTLS_SSL_EXT_MASK(MAX_FRAGMENT_LENGTH) | \ + MBEDTLS_SSL_EXT_MASK(STATUS_REQUEST) | \ + MBEDTLS_SSL_EXT_MASK(SUPPORTED_GROUPS) | \ + MBEDTLS_SSL_EXT_MASK(SIG_ALG) | \ + MBEDTLS_SSL_EXT_MASK(USE_SRTP) | \ + MBEDTLS_SSL_EXT_MASK(HEARTBEAT) | \ + MBEDTLS_SSL_EXT_MASK(ALPN) | \ + MBEDTLS_SSL_EXT_MASK(SCT) | \ + MBEDTLS_SSL_EXT_MASK(CLI_CERT_TYPE) | \ + MBEDTLS_SSL_EXT_MASK(SERV_CERT_TYPE) | \ + MBEDTLS_SSL_EXT_MASK(PADDING) | \ + MBEDTLS_SSL_EXT_MASK(KEY_SHARE) | \ + MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY) | \ + MBEDTLS_SSL_EXT_MASK(PSK_KEY_EXCHANGE_MODES) | \ + MBEDTLS_SSL_EXT_MASK(EARLY_DATA) | \ + MBEDTLS_SSL_EXT_MASK(COOKIE) | \ + MBEDTLS_SSL_EXT_MASK(SUPPORTED_VERSIONS) | \ + MBEDTLS_SSL_EXT_MASK(CERT_AUTH) | \ + MBEDTLS_SSL_EXT_MASK(POST_HANDSHAKE_AUTH) | \ + MBEDTLS_SSL_EXT_MASK(SIG_ALG_CERT) | \ + MBEDTLS_SSL_EXT_MASK(RECORD_SIZE_LIMIT) | \ + MBEDTLS_SSL_TLS1_3_EXT_MASK_UNRECOGNIZED) + +/* RFC 8446 section 4.2. Allowed extensions for EncryptedExtensions */ +#define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_EE \ + (MBEDTLS_SSL_EXT_MASK(SERVERNAME) | \ + MBEDTLS_SSL_EXT_MASK(MAX_FRAGMENT_LENGTH) | \ + MBEDTLS_SSL_EXT_MASK(SUPPORTED_GROUPS) | \ + MBEDTLS_SSL_EXT_MASK(USE_SRTP) | \ + MBEDTLS_SSL_EXT_MASK(HEARTBEAT) | \ + MBEDTLS_SSL_EXT_MASK(ALPN) | \ + MBEDTLS_SSL_EXT_MASK(CLI_CERT_TYPE) | \ + MBEDTLS_SSL_EXT_MASK(SERV_CERT_TYPE) | \ + MBEDTLS_SSL_EXT_MASK(EARLY_DATA) | \ + MBEDTLS_SSL_EXT_MASK(RECORD_SIZE_LIMIT)) + +/* RFC 8446 section 4.2. Allowed extensions for CertificateRequest */ +#define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CR \ + (MBEDTLS_SSL_EXT_MASK(STATUS_REQUEST) | \ + MBEDTLS_SSL_EXT_MASK(SIG_ALG) | \ + MBEDTLS_SSL_EXT_MASK(SCT) | \ + MBEDTLS_SSL_EXT_MASK(CERT_AUTH) | \ + MBEDTLS_SSL_EXT_MASK(OID_FILTERS) | \ + MBEDTLS_SSL_EXT_MASK(SIG_ALG_CERT) | \ + MBEDTLS_SSL_TLS1_3_EXT_MASK_UNRECOGNIZED) + +/* RFC 8446 section 4.2. Allowed extensions for Certificate */ +#define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CT \ + (MBEDTLS_SSL_EXT_MASK(STATUS_REQUEST) | \ + MBEDTLS_SSL_EXT_MASK(SCT)) + +/* RFC 8446 section 4.2. Allowed extensions for ServerHello */ +#define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_SH \ + (MBEDTLS_SSL_EXT_MASK(KEY_SHARE) | \ + MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY) | \ + MBEDTLS_SSL_EXT_MASK(SUPPORTED_VERSIONS)) + +/* RFC 8446 section 4.2. Allowed extensions for HelloRetryRequest */ +#define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_HRR \ + (MBEDTLS_SSL_EXT_MASK(KEY_SHARE) | \ + MBEDTLS_SSL_EXT_MASK(COOKIE) | \ + MBEDTLS_SSL_EXT_MASK(SUPPORTED_VERSIONS)) + +/* RFC 8446 section 4.2. Allowed extensions for NewSessionTicket */ +#define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_NST \ + (MBEDTLS_SSL_EXT_MASK(EARLY_DATA) | \ + MBEDTLS_SSL_TLS1_3_EXT_MASK_UNRECOGNIZED) + +/* + * Helper macros for function call with return check. + */ +/* + * Exit when return non-zero value + */ +#define MBEDTLS_SSL_PROC_CHK(f) \ + do { \ + ret = (f); \ + if (ret != 0) \ + { \ + goto cleanup; \ + } \ + } while (0) +/* + * Exit when return negative value + */ +#define MBEDTLS_SSL_PROC_CHK_NEG(f) \ + do { \ + ret = (f); \ + if (ret < 0) \ + { \ + goto cleanup; \ + } \ + } while (0) + +/* + * 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). + */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + +/* 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 a ciphersuite using a + * stream cipher can be used. */ +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#define MBEDTLS_SSL_SOME_SUITES_USE_STREAM +#endif + +/* This macro determines whether the CBC construct used in TLS 1.2 is supported. */ +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) +#define MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC +#endif + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_STREAM) || \ + defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) +#define MBEDTLS_SSL_SOME_SUITES_USE_MAC +#endif + +/* This macro determines whether a ciphersuite uses Encrypt-then-MAC with CBC */ +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) && \ + defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +#define MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM +#endif + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) +/* Ciphersuites using HMAC */ +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +#define MBEDTLS_SSL_MAC_ADD 48 /* SHA-384 used for HMAC */ +#elif defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +#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_SUITES_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_TLS1_3_PADDING_GRANULARITY +#else +#define MBEDTLS_SSL_MAX_CID_EXPANSION 0 +#endif + +#define MBEDTLS_SSL_PAYLOAD_OVERHEAD (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 signature algorithms ext., RFC 5246/8446 */ +#define MBEDTLS_SSL_MAX_SIG_ALG_LIST_LEN 65534 + +/* Minimum size in bytes of list in signature algorithms ext., RFC 5246/8446 */ +#define MBEDTLS_SSL_MIN_SIG_ALG_LIST_LEN 2 + +/* Maximum size in bytes of list in supported elliptic curve ext., RFC 4492 */ +#define MBEDTLS_SSL_MAX_CURVE_LIST_LEN 65535 + +#define MBEDTLS_RECEIVED_SIG_ALGS_SIZE 20 + +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) + +#define MBEDTLS_TLS_SIG_NONE MBEDTLS_TLS1_3_SIG_NONE + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#define MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(sig, hash) ((hash << 8) | sig) +#define MBEDTLS_SSL_TLS12_SIG_ALG_FROM_SIG_AND_HASH_ALG(alg) (alg & 0xFF) +#define MBEDTLS_SSL_TLS12_HASH_ALG_FROM_SIG_AND_HASH_ALG(alg) (alg >> 8) +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ + +/* + * Check that we obey the standard's message size bounds + */ + +#if MBEDTLS_SSL_IN_CONTENT_LEN > 16384 +#error "Bad configuration - incoming record content too large." +#endif + +#if MBEDTLS_SSL_OUT_CONTENT_LEN > 16384 +#error "Bad configuration - outgoing record content too large." +#endif + +#if MBEDTLS_SSL_IN_PAYLOAD_LEN > MBEDTLS_SSL_IN_CONTENT_LEN + 2048 +#error "Bad configuration - incoming protected record payload too large." +#endif + +#if MBEDTLS_SSL_OUT_PAYLOAD_LEN > MBEDTLS_SSL_OUT_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 + +#define MBEDTLS_CLIENT_HELLO_RANDOM_LEN 32 +#define MBEDTLS_SERVER_HELLO_RANDOM_LEN 32 + +#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_out_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_IN_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_in_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); +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#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 + +/* + * 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. + */ +#if !defined(MBEDTLS_TEST_HOOKS) +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)); +} +#else +typedef struct { + const uint8_t *cur; + const uint8_t *end; + size_t need; +} mbedtls_ssl_chk_buf_ptr_args; + +void mbedtls_ssl_set_chk_buf_ptr_fail_args( + const uint8_t *cur, const uint8_t *end, size_t need); +void mbedtls_ssl_reset_chk_buf_ptr_fail_args(void); + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_cmp_chk_buf_ptr_fail_args(mbedtls_ssl_chk_buf_ptr_args *args); + +static inline int mbedtls_ssl_chk_buf_ptr(const uint8_t *cur, + const uint8_t *end, size_t need) +{ + if ((cur > end) || (need > (size_t) (end - cur))) { + mbedtls_ssl_set_chk_buf_ptr_fail_args(cur, end, need); + return 1; + } + return 0; +} +#endif /* MBEDTLS_TEST_HOOKS */ + +/** + * \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) + +/** + * \brief This macro checks if the remaining length in an input buffer is + * greater or equal than a needed length. If it is not the case, it + * returns #MBEDTLS_ERR_SSL_DECODE_ERROR error and pends a + * #MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR alert message. + * + * This is a function-like macro. It is guaranteed to evaluate each + * argument exactly once. + * + * \param cur Pointer to the current position in the buffer. + * \param end Pointer to one past the end of the buffer. + * \param need Needed length in bytes. + * + */ +#define MBEDTLS_SSL_CHK_BUF_READ_PTR(cur, end, need) \ + do { \ + if (mbedtls_ssl_chk_buf_ptr((cur), (end), (need)) != 0) \ + { \ + MBEDTLS_SSL_DEBUG_MSG(1, \ + ("missing input data in %s", __func__)); \ + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, \ + MBEDTLS_ERR_SSL_DECODE_ERROR); \ + return MBEDTLS_ERR_SSL_DECODE_ERROR; \ + } \ + } while (0) + +#ifdef __cplusplus +extern "C" { +#endif + +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; + +typedef struct { + unsigned char binder_key[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + unsigned char client_early_traffic_secret[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + unsigned char early_exporter_master_secret[MBEDTLS_TLS1_3_MD_MAX_SIZE]; +} mbedtls_ssl_tls13_early_secrets; + +typedef struct { + unsigned char client_handshake_traffic_secret[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + unsigned char server_handshake_traffic_secret[MBEDTLS_TLS1_3_MD_MAX_SIZE]; +} mbedtls_ssl_tls13_handshake_secrets; + +/* + * This structure contains the parameters only needed during handshake. + */ +struct mbedtls_ssl_handshake_params { + /* Frequently-used boolean or byte fields (placed early to take + * advantage of smaller code size for indirect access on Arm Thumb) */ + uint8_t resume; /*!< session resume indicator*/ + uint8_t cli_exts; /*!< client extension presence*/ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + uint8_t sni_authmode; /*!< authmode from SNI callback */ +#endif + +#if defined(MBEDTLS_SSL_SRV_C) + /* Flag indicating if a CertificateRequest message has been sent + * to the client or not. */ + uint8_t certificate_request_sent; +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + uint8_t new_session_ticket; /*!< use NewSessionTicket? */ +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_CLI_C) + /** Minimum TLS version to be negotiated. + * + * It is set up in the ClientHello writing preparation stage and used + * throughout the ClientHello writing. Not relevant anymore as soon as + * the protocol version has been negotiated thus as soon as the + * ServerHello is received. + * For a fresh handshake not linked to any previous handshake, it is + * equal to the configured minimum minor version to be negotiated. When + * renegotiating or resuming a session, it is equal to the previously + * negotiated minor version. + * + * There is no maximum TLS version field in this handshake context. + * From the start of the handshake, we need to define a current protocol + * version for the record layer which we define as the maximum TLS + * version to be negotiated. The `tls_version` field of the SSL context is + * used to store this maximum value until it contains the actual + * negotiated value. + */ + mbedtls_ssl_protocol_version min_tls_version; +#endif + +#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_DEPRECATED_REMOVED) + unsigned char group_list_heap_allocated; + unsigned char sig_algs_heap_allocated; +#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 + + mbedtls_ssl_ciphersuite_t const *ciphersuite_info; + + MBEDTLS_CHECK_RETURN_CRITICAL + int (*update_checksum)(mbedtls_ssl_context *, const unsigned char *, size_t); + MBEDTLS_CHECK_RETURN_CRITICAL + int (*calc_verify)(const mbedtls_ssl_context *, unsigned char *, size_t *); + MBEDTLS_CHECK_RETURN_CRITICAL + int (*calc_finished)(mbedtls_ssl_context *, unsigned char *, int); + mbedtls_ssl_tls_prf_cb *tls_prf; + + /* + * Handshake specific crypto variables + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + uint8_t key_exchange_mode; /*!< Selected key exchange mode */ + + /** Number of HelloRetryRequest messages received/sent from/to the server. */ + int hello_retry_request_count; + +#if defined(MBEDTLS_SSL_SRV_C) + /** selected_group of key_share extension in HelloRetryRequest message. */ + uint16_t hrr_selected_group; +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) + uint8_t tls13_kex_modes; /*!< Key exchange modes supported by the client */ +#endif +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + uint16_t new_session_tickets_count; /*!< number of session tickets */ +#endif +#endif /* MBEDTLS_SSL_SRV_C */ + +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) + uint16_t received_sig_algs[MBEDTLS_RECEIVED_SIG_ALGS_SIZE]; +#endif + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + const uint16_t *group_list; + const uint16_t *sig_algs; +#endif + +#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 in client and server code. 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) +#if !defined(MBEDTLS_USE_PSA_CRYPTO) + mbedtls_ecdh_context ecdh_ctx; /*!< ECDH key exchange */ +#endif /* !MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3) + psa_key_type_t ecdh_psa_type; + size_t ecdh_bits; + mbedtls_svc_key_id_t ecdh_psa_privkey; + uint8_t ecdh_psa_privkey_is_external; + unsigned char ecdh_psa_peerkey[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH]; + size_t ecdh_psa_peerkey_len; +#endif /* MBEDTLS_USE_PSA_CRYPTO || MBEDTLS_SSL_PROTO_TLS1_3 */ +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_pake_operation_t psa_pake_ctx; /*!< EC J-PAKE key exchange */ + mbedtls_svc_key_id_t psa_pake_password; + uint8_t psa_pake_ctx_is_ok; +#else + mbedtls_ecjpake_context ecjpake_ctx; /*!< EC J-PAKE key exchange */ +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#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) + uint16_t *curves_tls_id; /*!< List of TLS IDs of supported elliptic curves */ +#endif + +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + mbedtls_svc_key_id_t psk_opaque; /*!< Opaque PSK from the callback */ + uint8_t psk_opaque_is_internal; +#else + unsigned char *psk; /*!< PSK from the callback */ + size_t psk_len; /*!< Length of PSK from callback */ +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + uint16_t selected_identity; +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */ + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + mbedtls_x509_crt_restart_ctx ecrs_ctx; /*!< restart context */ +#endif + +#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_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 */ + + 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; + +#if defined(MBEDTLS_SSL_CLI_C) && \ + (defined(MBEDTLS_SSL_PROTO_DTLS) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_3)) + unsigned char *cookie; /*!< HelloVerifyRequest cookie for DTLS + * HelloRetryRequest cookie for TLS 1.3 */ +#if !defined(MBEDTLS_SSL_PROTO_TLS1_3) + /* RFC 6347 page 15 + ... + opaque cookie<0..2^8-1>; + ... + */ + uint8_t cookie_len; +#else + /* RFC 8446 page 39 + ... + opaque cookie<0..2^16-1>; + ... + If TLS1_3 is enabled, the max length is 2^16 - 1 + */ + uint16_t cookie_len; /*!< DTLS: HelloVerifyRequest cookie length + * TLS1_3: HelloRetryRequest cookie length */ +#endif +#endif /* MBEDTLS_SSL_CLI_C && + ( MBEDTLS_SSL_PROTO_DTLS || + MBEDTLS_SSL_PROTO_TLS1_3 ) */ +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_PROTO_DTLS) + unsigned char cookie_verify_result; /*!< Srv: flag for sending a cookie */ +#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + unsigned int out_msg_seq; /*!< Outgoing handshake sequence number */ + unsigned int in_msg_seq; /*!< Incoming handshake sequence number */ + + 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[MBEDTLS_SSL_SEQUENCE_NUMBER_LEN]; /*!< 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_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_operation_t fin_sha256_psa; +#else + mbedtls_md_context_t fin_sha256; +#endif +#endif +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_operation_t fin_sha384_psa; +#else + mbedtls_md_context_t fin_sha384; +#endif +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + uint16_t offered_group_id; /* The NamedGroup value for the group + * that is being used for ephemeral + * key exchange. + * + * On the client: Defaults to the first + * entry in the client's group list, + * but can be overwritten by the HRR. */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + +#if defined(MBEDTLS_SSL_CLI_C) + uint8_t client_auth; /*!< used to check if CertificateRequest has been + received from server side. If CertificateRequest + has been received, Certificate and CertificateVerify + should be sent to server */ +#endif /* MBEDTLS_SSL_CLI_C */ + /* + * State-local variables used during the processing + * of a specific handshake state. + */ + union { + /* Outgoing Finished message */ + struct { + uint8_t preparation_done; + + /* Buffer holding digest of the handshake up to + * but excluding the outgoing finished message. */ + unsigned char digest[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + size_t digest_len; + } finished_out; + + /* Incoming Finished message */ + struct { + uint8_t preparation_done; + + /* Buffer holding digest of the handshake up to but + * excluding the peer's incoming finished message. */ + unsigned char digest[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + size_t digest_len; + } finished_in; + + } state_local; + + /* End of state-local variables. */ + + unsigned char randbytes[MBEDTLS_CLIENT_HELLO_RANDOM_LEN + + MBEDTLS_SERVER_HELLO_RANDOM_LEN]; + /*!< random bytes */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + unsigned char premaster[MBEDTLS_PREMASTER_SIZE]; + /*!< premaster secret */ + size_t pmslen; /*!< premaster length */ +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + uint32_t sent_extensions; /*!< extensions sent by endpoint */ + uint32_t received_extensions; /*!< extensions received by endpoint */ + +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) + unsigned char certificate_request_context_len; + unsigned char *certificate_request_context; +#endif + + /** TLS 1.3 transform for encrypted handshake messages. */ + mbedtls_ssl_transform *transform_handshake; + union { + unsigned char early[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + unsigned char handshake[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + unsigned char app[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + } tls13_master_secrets; + + mbedtls_ssl_tls13_handshake_secrets tls13_hs_secrets; +#if defined(MBEDTLS_SSL_EARLY_DATA) + /** TLS 1.3 transform for early data and handshake messages. */ + mbedtls_ssl_transform *transform_earlydata; +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + +#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 */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + const unsigned char *sni_name; /*!< raw SNI */ + size_t sni_name_len; /*!< raw SNI len */ +#if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) + const mbedtls_x509_crt *dn_hints; /*!< acceptable client cert issuers */ +#endif +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ +}; + +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) + * For TLS 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) an implicit IV. It is static + * 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. + * + * 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, the MAC keys are not stored explicitly + * but maintained within md_ctx_{enc/dec}. + * - The mac_enc and mac_dec fields are unused for EAD transformations. + * - 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. + * - tls_version denotes the 2-byte 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_SUITES_USE_MAC) + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + mbedtls_svc_key_id_t psa_mac_enc; /*!< MAC (encryption) */ + mbedtls_svc_key_id_t psa_mac_dec; /*!< MAC (decryption) */ + psa_algorithm_t psa_mac_alg; /*!< psa MAC algorithm */ +#else + mbedtls_md_context_t md_ctx_enc; /*!< MAC (encryption) */ + mbedtls_md_context_t md_ctx_dec; /*!< MAC (decryption) */ +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + int encrypt_then_mac; /*!< flag for EtM activation */ +#endif + +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ + + mbedtls_ssl_protocol_version tls_version; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + mbedtls_svc_key_id_t psa_key_enc; /*!< psa encryption key */ + mbedtls_svc_key_id_t psa_key_dec; /*!< psa decryption key */ + psa_algorithm_t psa_alg; /*!< psa algorithm */ +#else + mbedtls_cipher_context_t cipher_ctx_enc; /*!< encryption context */ + mbedtls_cipher_context_t cipher_ctx_dec; /*!< decryption context */ +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + uint8_t in_cid_len; + uint8_t out_cid_len; + unsigned char in_cid[MBEDTLS_SSL_CID_IN_LEN_MAX]; + unsigned char out_cid[MBEDTLS_SSL_CID_OUT_LEN_MAX]; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +#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_tls12_populate_transform() */ + unsigned char randbytes[MBEDTLS_SERVER_HELLO_RANDOM_LEN + + MBEDTLS_CLIENT_HELLO_RANDOM_LEN]; + /*!< 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_SUITES_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 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[MBEDTLS_SSL_SEQUENCE_NUMBER_LEN]; /* 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) +/** + * \brief Given an SSL context and its associated configuration, write the TLS + * 1.2 specific extensions of the ClientHello message. + * + * \param[in] ssl SSL context + * \param[in] buf Base address of the buffer where to write the extensions + * \param[in] end End address of the buffer where to write the extensions + * \param uses_ec Whether one proposed ciphersuite uses an elliptic curve + * (<> 0) or not ( 0 ). + * \param[out] out_len Length of the data written into the buffer \p buf + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls12_write_client_hello_exts(mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + int uses_ec, + size_t *out_len); +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + +/** + * \brief Find the preferred hash for a given signature algorithm. + * + * \param[in] ssl SSL context + * \param[in] sig_alg A signature algorithm identifier as defined in the + * TLS 1.2 SignatureAlgorithm enumeration. + * + * \return The preferred hash algorithm for \p sig_alg. It is a hash algorithm + * identifier as defined in the TLS 1.2 HashAlgorithm enumeration. + */ +unsigned int mbedtls_ssl_tls12_get_preferred_hash_for_sig_alg( + mbedtls_ssl_context *ssl, + unsigned int sig_alg); + +#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); + +/* set inbound transform of ssl context */ +void mbedtls_ssl_set_inbound_transform(mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform); + +/* set outbound transform of ssl context */ +void mbedtls_ssl_set_outbound_transform(mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform); + +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); +static inline void mbedtls_ssl_handshake_set_state(mbedtls_ssl_context *ssl, + mbedtls_ssl_states state) +{ + ssl->state = (int) state; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_send_fatal_handshake_failure(mbedtls_ssl_context *ssl); + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_reset_checksum(mbedtls_ssl_context *ssl); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_derive_keys(mbedtls_ssl_context *ssl); +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +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); +MBEDTLS_CHECK_RETURN_CRITICAL +int 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); + +/* + * Write handshake message header + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_start_handshake_msg(mbedtls_ssl_context *ssl, unsigned hs_type, + unsigned char **buf, size_t *buf_len); + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_write_handshake_msg_ext(mbedtls_ssl_context *ssl, + int update_checksum, + int force_flush); +static inline int mbedtls_ssl_write_handshake_msg(mbedtls_ssl_context *ssl) +{ + return mbedtls_ssl_write_handshake_msg_ext(ssl, 1 /* update checksum */, 1 /* force flush */); +} + +/* + * Write handshake message tail + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_finish_handshake_msg(mbedtls_ssl_context *ssl, + size_t buf_len, size_t msg_len); + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_write_record(mbedtls_ssl_context *ssl, int 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); + +/* + * Update checksum of handshake messages. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_add_hs_msg_to_checksum(mbedtls_ssl_context *ssl, + unsigned hs_type, + unsigned char const *msg, + size_t msg_len); + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_add_hs_hdr_to_checksum(mbedtls_ssl_context *ssl, + unsigned hs_type, + size_t total_hs_len); + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +#if !defined(MBEDTLS_USE_PSA_CRYPTO) +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_psk_derive_premaster(mbedtls_ssl_context *ssl, + mbedtls_key_exchange_type_t key_ex); +#endif /* !MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED) +#if defined(MBEDTLS_SSL_CLI_C) +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_conf_has_static_psk(mbedtls_ssl_config const *conf); +#endif +#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 mbedtls_svc_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; +} +#else +/** + * 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; +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_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); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_set_calc_verify_md(mbedtls_ssl_context *ssl, int md); +#endif + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_check_curve_tls_id(const mbedtls_ssl_context *ssl, uint16_t tls_id); +#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); +#endif + +/** + * \brief Return PSA EC info for the specified TLS ID. + * + * \param tls_id The TLS ID to look for + * \param family If the TLD ID is supported, then proper \c psa_ecc_family_t + * value is returned here. Can be NULL. + * \param bits If the TLD ID is supported, then proper bit size is returned + * here. Can be NULL. + * \return PSA_SUCCESS if the TLS ID is supported, + * PSA_ERROR_NOT_SUPPORTED otherwise + * + * \note If either \c family or \c bits parameters are NULL, then + * the corresponding value is not returned. + * The function can be called with both parameters as NULL + * simply to check if a specific TLS ID is supported. + */ +int mbedtls_ssl_get_psa_curve_info_from_tls_id(uint16_t tls_id, + psa_ecc_family_t *family, + size_t *bits); + +/** + * \brief Return \c mbedtls_ecp_group_id for the specified TLS ID. + * + * \param tls_id The TLS ID to look for + * \return Proper \c mbedtls_ecp_group_id if the TLS ID is supported, + * or MBEDTLS_ECP_DP_NONE otherwise + */ +mbedtls_ecp_group_id mbedtls_ssl_get_ecp_group_id_from_tls_id(uint16_t tls_id); + +/** + * \brief Return TLS ID for the specified \c mbedtls_ecp_group_id. + * + * \param grp_id The \c mbedtls_ecp_group_id ID to look for + * \return Proper TLS ID if the \c mbedtls_ecp_group_id is supported, + * or 0 otherwise + */ +uint16_t mbedtls_ssl_get_tls_id_from_ecp_group_id(mbedtls_ecp_group_id grp_id); + +#if defined(MBEDTLS_DEBUG_C) +/** + * \brief Return EC's name for the specified TLS ID. + * + * \param tls_id The TLS ID to look for + * \return A pointer to a const string with the proper name. If TLS + * ID is not supported, a NULL pointer is returned instead. + */ +const char *mbedtls_ssl_get_curve_name_from_tls_id(uint16_t tls_id); +#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(unsigned char version[2], int transport, + mbedtls_ssl_protocol_version tls_version); +uint16_t mbedtls_ssl_read_version(const unsigned char version[2], + int transport); + +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_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_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); +void mbedtls_ssl_session_reset_msg_layer(mbedtls_ssl_context *ssl, + int partial); + +/* + * Send pending alert + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_handle_pending_alert(mbedtls_ssl_context *ssl); + +/* + * Set pending fatal alert flag. + */ +void mbedtls_ssl_pend_fatal_alert(mbedtls_ssl_context *ssl, + unsigned char alert_type, + int alert_reason); + +/* Alias of mbedtls_ssl_pend_fatal_alert */ +#define MBEDTLS_SSL_PEND_FATAL_ALERT(type, user_return_value) \ + mbedtls_ssl_pend_fatal_alert(ssl, type, user_return_value) + +#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 */ + +/** + * ssl utils functions for checking configuration. + */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) +static inline int mbedtls_ssl_conf_is_tls13_only(const mbedtls_ssl_config *conf) +{ + return conf->min_tls_version == MBEDTLS_SSL_VERSION_TLS1_3 && + conf->max_tls_version == MBEDTLS_SSL_VERSION_TLS1_3; +} + +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +static inline int mbedtls_ssl_conf_is_tls12_only(const mbedtls_ssl_config *conf) +{ + return conf->min_tls_version == MBEDTLS_SSL_VERSION_TLS1_2 && + conf->max_tls_version == MBEDTLS_SSL_VERSION_TLS1_2; +} + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +static inline int mbedtls_ssl_conf_is_tls13_enabled(const mbedtls_ssl_config *conf) +{ +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + return conf->min_tls_version <= MBEDTLS_SSL_VERSION_TLS1_3 && + conf->max_tls_version >= MBEDTLS_SSL_VERSION_TLS1_3; +#else + ((void) conf); + return 0; +#endif +} + +static inline int mbedtls_ssl_conf_is_tls12_enabled(const mbedtls_ssl_config *conf) +{ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + return conf->min_tls_version <= MBEDTLS_SSL_VERSION_TLS1_2 && + conf->max_tls_version >= MBEDTLS_SSL_VERSION_TLS1_2; +#else + ((void) conf); + return 0; +#endif +} + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_TLS1_3) +static inline int mbedtls_ssl_conf_is_hybrid_tls12_tls13(const mbedtls_ssl_config *conf) +{ + return conf->min_tls_version == MBEDTLS_SSL_VERSION_TLS1_2 && + conf->max_tls_version == MBEDTLS_SSL_VERSION_TLS1_3; +} +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && MBEDTLS_SSL_PROTO_TLS1_3 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) +extern const uint8_t mbedtls_ssl_tls13_hello_retry_request_magic[ + MBEDTLS_SERVER_HELLO_RANDOM_LEN]; +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_process_finished_message(mbedtls_ssl_context *ssl); +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_write_finished_message(mbedtls_ssl_context *ssl); +void mbedtls_ssl_tls13_handshake_wrapup(mbedtls_ssl_context *ssl); + +/** + * \brief Given an SSL context and its associated configuration, write the TLS + * 1.3 specific extensions of the ClientHello message. + * + * \param[in] ssl SSL context + * \param[in] buf Base address of the buffer where to write the extensions + * \param[in] end End address of the buffer where to write the extensions + * \param[out] out_len Length of the data written into the buffer \p buf + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_write_client_hello_exts(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len); + +/** + * \brief TLS 1.3 client side state machine entry + * + * \param ssl SSL context + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_handshake_client_step(mbedtls_ssl_context *ssl); + +/** + * \brief TLS 1.3 server side state machine entry + * + * \param ssl SSL context + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_handshake_server_step(mbedtls_ssl_context *ssl); + + +/* + * Helper functions around key exchange modes. + */ +static inline unsigned mbedtls_ssl_conf_tls13_check_kex_modes(mbedtls_ssl_context *ssl, + int kex_mode_mask) +{ + return (ssl->conf->tls13_kex_modes & kex_mode_mask) != 0; +} + +static inline int mbedtls_ssl_conf_tls13_psk_enabled(mbedtls_ssl_context *ssl) +{ + return mbedtls_ssl_conf_tls13_check_kex_modes(ssl, + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK); +} + +static inline int mbedtls_ssl_conf_tls13_psk_ephemeral_enabled(mbedtls_ssl_context *ssl) +{ + return mbedtls_ssl_conf_tls13_check_kex_modes(ssl, + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL); +} + +static inline int mbedtls_ssl_conf_tls13_ephemeral_enabled(mbedtls_ssl_context *ssl) +{ + return mbedtls_ssl_conf_tls13_check_kex_modes(ssl, + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL); +} + +static inline int mbedtls_ssl_conf_tls13_some_ephemeral_enabled(mbedtls_ssl_context *ssl) +{ + return mbedtls_ssl_conf_tls13_check_kex_modes(ssl, + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ALL); +} + +static inline int mbedtls_ssl_conf_tls13_some_psk_enabled(mbedtls_ssl_context *ssl) +{ + return mbedtls_ssl_conf_tls13_check_kex_modes(ssl, + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL); +} + +#if defined(MBEDTLS_SSL_SRV_C) && \ + defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) +/** + * Given a list of key exchange modes, check if at least one of them is + * supported. + * + * \param[in] ssl SSL context + * \param kex_modes_mask Mask of the key exchange modes to check + * + * \return 0 if at least one of the key exchange modes is supported, + * !=0 otherwise. + */ +static inline unsigned mbedtls_ssl_tls13_check_kex_modes(mbedtls_ssl_context *ssl, + int kex_modes_mask) +{ + return (ssl->handshake->tls13_kex_modes & kex_modes_mask) == 0; +} + +static inline int mbedtls_ssl_tls13_psk_enabled(mbedtls_ssl_context *ssl) +{ + return !mbedtls_ssl_tls13_check_kex_modes(ssl, + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK); +} + +static inline int mbedtls_ssl_tls13_psk_ephemeral_enabled( + mbedtls_ssl_context *ssl) +{ + return !mbedtls_ssl_tls13_check_kex_modes(ssl, + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL); +} + +static inline int mbedtls_ssl_tls13_ephemeral_enabled(mbedtls_ssl_context *ssl) +{ + return !mbedtls_ssl_tls13_check_kex_modes(ssl, + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL); +} + +static inline int mbedtls_ssl_tls13_some_ephemeral_enabled(mbedtls_ssl_context *ssl) +{ + return !mbedtls_ssl_tls13_check_kex_modes(ssl, + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ALL); +} + +static inline int mbedtls_ssl_tls13_some_psk_enabled(mbedtls_ssl_context *ssl) +{ + return !mbedtls_ssl_tls13_check_kex_modes(ssl, + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL); +} +#endif /* MBEDTLS_SSL_SRV_C && + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ + +/* + * Helper functions for extensions checking. + */ + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_check_received_extension( + mbedtls_ssl_context *ssl, + int hs_msg_type, + unsigned int received_extension_type, + uint32_t hs_msg_allowed_extensions_mask); + +static inline void mbedtls_ssl_tls13_set_hs_sent_ext_mask( + mbedtls_ssl_context *ssl, unsigned int extension_type) +{ + ssl->handshake->sent_extensions |= + mbedtls_ssl_get_extension_mask(extension_type); +} + +/* + * Helper functions to check the selected key exchange mode. + */ +static inline int mbedtls_ssl_tls13_key_exchange_mode_check( + mbedtls_ssl_context *ssl, int kex_mask) +{ + return (ssl->handshake->key_exchange_mode & kex_mask) != 0; +} + +static inline int mbedtls_ssl_tls13_key_exchange_mode_with_psk( + mbedtls_ssl_context *ssl) +{ + return mbedtls_ssl_tls13_key_exchange_mode_check(ssl, + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL); +} + +static inline int mbedtls_ssl_tls13_key_exchange_mode_with_ephemeral( + mbedtls_ssl_context *ssl) +{ + return mbedtls_ssl_tls13_key_exchange_mode_check(ssl, + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ALL); +} + +/* + * Fetch TLS 1.3 handshake message header + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_fetch_handshake_msg(mbedtls_ssl_context *ssl, + unsigned hs_type, + unsigned char **buf, + size_t *buf_len); + +/* + * Handler of TLS 1.3 server certificate message + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_process_certificate(mbedtls_ssl_context *ssl); + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) +/* + * Handler of TLS 1.3 write Certificate message + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_write_certificate(mbedtls_ssl_context *ssl); + +/* + * Handler of TLS 1.3 write Certificate Verify message + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_write_certificate_verify(mbedtls_ssl_context *ssl); + +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ + +/* + * Generic handler of Certificate Verify + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_process_certificate_verify(mbedtls_ssl_context *ssl); + +/* + * Write of dummy-CCS's for middlebox compatibility + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_write_change_cipher_spec(mbedtls_ssl_context *ssl); + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_reset_transcript_for_hrr(mbedtls_ssl_context *ssl); + +#if defined(MBEDTLS_ECDH_C) +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_generate_and_write_ecdh_key_exchange( + mbedtls_ssl_context *ssl, + uint16_t named_group, + unsigned char *buf, + unsigned char *end, + size_t *out_len); +#endif /* MBEDTLS_ECDH_C */ + +#if defined(MBEDTLS_SSL_EARLY_DATA) +int mbedtls_ssl_tls13_write_early_data_ext(mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *out_len); +#endif /* MBEDTLS_SSL_EARLY_DATA */ + +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) +/* + * Write Signature Algorithm extension + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_write_sig_alg_ext(mbedtls_ssl_context *ssl, unsigned char *buf, + const unsigned char *end, size_t *out_len); +/* + * Parse TLS Signature Algorithm extension + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_parse_sig_alg_ext(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end); +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ + +/* Get handshake transcript */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_get_handshake_transcript(mbedtls_ssl_context *ssl, + const mbedtls_md_type_t md, + unsigned char *dst, + size_t dst_len, + size_t *olen); + +/* + * Return supported groups. + * + * In future, invocations can be changed to ssl->conf->group_list + * when mbedtls_ssl_conf_curves() is deleted. + * + * ssl->handshake->group_list is either a translation of curve_list to IANA TLS group + * identifiers when mbedtls_ssl_conf_curves() has been used, or a pointer to + * ssl->conf->group_list when mbedtls_ssl_conf_groups() has been more recently invoked. + * + */ +static inline const void *mbedtls_ssl_get_groups(const mbedtls_ssl_context *ssl) +{ + #if defined(MBEDTLS_DEPRECATED_REMOVED) || !defined(MBEDTLS_ECP_C) + return ssl->conf->group_list; + #else + if ((ssl->handshake != NULL) && (ssl->handshake->group_list != NULL)) { + return ssl->handshake->group_list; + } else { + return ssl->conf->group_list; + } + #endif +} + +/* + * Helper functions for NamedGroup. + */ +static inline int mbedtls_ssl_tls12_named_group_is_ecdhe(uint16_t named_group) +{ + /* + * RFC 8422 section 5.1.1 + */ + return named_group == MBEDTLS_SSL_IANA_TLS_GROUP_X25519 || + named_group == MBEDTLS_SSL_IANA_TLS_GROUP_BP256R1 || + named_group == MBEDTLS_SSL_IANA_TLS_GROUP_BP384R1 || + named_group == MBEDTLS_SSL_IANA_TLS_GROUP_BP512R1 || + named_group == MBEDTLS_SSL_IANA_TLS_GROUP_X448 || + /* Below deprecated curves should be removed with notice to users */ + named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP192K1 || + named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP192R1 || + named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP224K1 || + named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP224R1 || + named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP256K1 || + named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1 || + named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1 || + named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP521R1; +} + +static inline int mbedtls_ssl_tls13_named_group_is_ecdhe(uint16_t named_group) +{ + return named_group == MBEDTLS_SSL_IANA_TLS_GROUP_X25519 || + named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1 || + named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1 || + named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP521R1 || + named_group == MBEDTLS_SSL_IANA_TLS_GROUP_X448; +} + +static inline int mbedtls_ssl_tls13_named_group_is_dhe(uint16_t named_group) +{ + return named_group >= MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE2048 && + named_group <= MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE8192; +} + +static inline int mbedtls_ssl_named_group_is_offered( + const mbedtls_ssl_context *ssl, uint16_t named_group) +{ + const uint16_t *group_list = mbedtls_ssl_get_groups(ssl); + + if (group_list == NULL) { + return 0; + } + + for (; *group_list != 0; group_list++) { + if (*group_list == named_group) { + return 1; + } + } + + return 0; +} + +static inline int mbedtls_ssl_named_group_is_supported(uint16_t named_group) +{ +#if defined(MBEDTLS_ECDH_C) + if (mbedtls_ssl_tls13_named_group_is_ecdhe(named_group)) { + if (mbedtls_ssl_get_ecp_group_id_from_tls_id(named_group) != + MBEDTLS_ECP_DP_NONE) { + return 1; + } + } +#else + ((void) named_group); +#endif /* MBEDTLS_ECDH_C */ + return 0; +} + +/* + * Return supported signature algorithms. + * + * In future, invocations can be changed to ssl->conf->sig_algs when + * mbedtls_ssl_conf_sig_hashes() is deleted. + * + * ssl->handshake->sig_algs is either a translation of sig_hashes to IANA TLS + * signature algorithm identifiers when mbedtls_ssl_conf_sig_hashes() has been + * used, or a pointer to ssl->conf->sig_algs when mbedtls_ssl_conf_sig_algs() has + * been more recently invoked. + * + */ +static inline const void *mbedtls_ssl_get_sig_algs( + const mbedtls_ssl_context *ssl) +{ +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + if (ssl->handshake != NULL && + ssl->handshake->sig_algs_heap_allocated == 1 && + ssl->handshake->sig_algs != NULL) { + return ssl->handshake->sig_algs; + } +#endif + return ssl->conf->sig_algs; + +#else /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ + + ((void) ssl); + return NULL; +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ +} + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) +static inline int mbedtls_ssl_sig_alg_is_received(const mbedtls_ssl_context *ssl, + uint16_t own_sig_alg) +{ + const uint16_t *sig_alg = ssl->handshake->received_sig_algs; + if (sig_alg == NULL) { + return 0; + } + + for (; *sig_alg != MBEDTLS_TLS_SIG_NONE; sig_alg++) { + if (*sig_alg == own_sig_alg) { + return 1; + } + } + return 0; +} + +static inline int mbedtls_ssl_tls13_sig_alg_for_cert_verify_is_supported( + const uint16_t sig_alg) +{ + switch (sig_alg) { +#if defined(MBEDTLS_PK_CAN_ECDSA_SOME) +#if defined(PSA_WANT_ALG_SHA_256) && defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + case MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256: + break; +#endif /* PSA_WANT_ALG_SHA_256 && MBEDTLS_ECP_DP_SECP256R1_ENABLED */ +#if defined(PSA_WANT_ALG_SHA_384) && defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + case MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384: + break; +#endif /* PSA_WANT_ALG_SHA_384 && MBEDTLS_ECP_DP_SECP384R1_ENABLED */ +#if defined(PSA_WANT_ALG_SHA_512) && defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + case MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512: + break; +#endif /* PSA_WANT_ALG_SHA_512 && MBEDTLS_ECP_DP_SECP521R1_ENABLED */ +#endif /* MBEDTLS_PK_CAN_ECDSA_SOME */ + +#if defined(MBEDTLS_PKCS1_V21) +#if defined(PSA_WANT_ALG_SHA_256) + case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256: + break; +#endif /* PSA_WANT_ALG_SHA_256 */ +#if defined(PSA_WANT_ALG_SHA_384) + case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384: + break; +#endif /* PSA_WANT_ALG_SHA_384 */ +#if defined(PSA_WANT_ALG_SHA_512) + case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512: + break; +#endif /* PSA_WANT_ALG_SHA_512 */ +#endif /* MBEDTLS_PKCS1_V21 */ + default: + return 0; + } + return 1; + +} + +static inline int mbedtls_ssl_tls13_sig_alg_is_supported( + const uint16_t sig_alg) +{ + switch (sig_alg) { +#if defined(MBEDTLS_PKCS1_V15) +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256: + break; +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384: + break; +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512: + break; +#endif /* MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#endif /* MBEDTLS_PKCS1_V15 */ + default: + return mbedtls_ssl_tls13_sig_alg_for_cert_verify_is_supported( + sig_alg); + } + return 1; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_check_sig_alg_cert_key_match(uint16_t sig_alg, + mbedtls_pk_context *key); +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ + +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) +static inline int mbedtls_ssl_sig_alg_is_offered(const mbedtls_ssl_context *ssl, + uint16_t proposed_sig_alg) +{ + const uint16_t *sig_alg = mbedtls_ssl_get_sig_algs(ssl); + if (sig_alg == NULL) { + return 0; + } + + for (; *sig_alg != MBEDTLS_TLS_SIG_NONE; sig_alg++) { + if (*sig_alg == proposed_sig_alg) { + return 1; + } + } + return 0; +} + +static inline int mbedtls_ssl_get_pk_type_and_md_alg_from_sig_alg( + uint16_t sig_alg, mbedtls_pk_type_t *pk_type, mbedtls_md_type_t *md_alg) +{ + *pk_type = mbedtls_ssl_pk_alg_from_sig(sig_alg & 0xff); + *md_alg = mbedtls_ssl_md_alg_from_hash((sig_alg >> 8) & 0xff); + + if (*pk_type != MBEDTLS_PK_NONE && *md_alg != MBEDTLS_MD_NONE) { + return 0; + } + + switch (sig_alg) { +#if defined(MBEDTLS_PKCS1_V21) +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256: + *md_alg = MBEDTLS_MD_SHA256; + *pk_type = MBEDTLS_PK_RSASSA_PSS; + break; +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384: + *md_alg = MBEDTLS_MD_SHA384; + *pk_type = MBEDTLS_PK_RSASSA_PSS; + break; +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512: + *md_alg = MBEDTLS_MD_SHA512; + *pk_type = MBEDTLS_PK_RSASSA_PSS; + break; +#endif /* MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ +#endif /* MBEDTLS_PKCS1_V21 */ + default: + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + } + return 0; +} + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +static inline int mbedtls_ssl_tls12_sig_alg_is_supported( + const uint16_t sig_alg) +{ + /* High byte is hash */ + unsigned char hash = MBEDTLS_BYTE_1(sig_alg); + unsigned char sig = MBEDTLS_BYTE_0(sig_alg); + + switch (hash) { +#if defined(MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + case MBEDTLS_SSL_HASH_MD5: + break; +#endif + +#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + case MBEDTLS_SSL_HASH_SHA1: + break; +#endif + +#if defined(MBEDTLS_HAS_ALG_SHA_224_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + case MBEDTLS_SSL_HASH_SHA224: + break; +#endif + +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + case MBEDTLS_SSL_HASH_SHA256: + break; +#endif + +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + case MBEDTLS_SSL_HASH_SHA384: + break; +#endif + +#if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + case MBEDTLS_SSL_HASH_SHA512: + break; +#endif + + default: + return 0; + } + + switch (sig) { +#if defined(MBEDTLS_RSA_C) + case MBEDTLS_SSL_SIG_RSA: + break; +#endif + +#if defined(MBEDTLS_PK_CAN_ECDSA_SOME) + case MBEDTLS_SSL_SIG_ECDSA: + break; +#endif + + default: + return 0; + } + + return 1; +} +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +static inline int mbedtls_ssl_sig_alg_is_supported( + const mbedtls_ssl_context *ssl, + const uint16_t sig_alg) +{ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2) { + return mbedtls_ssl_tls12_sig_alg_is_supported(sig_alg); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) + if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { + return mbedtls_ssl_tls13_sig_alg_is_supported(sig_alg); + } +#endif + ((void) ssl); + ((void) sig_alg); + return 0; +} +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3) +/* Corresponding PSA algorithm for MBEDTLS_CIPHER_NULL. + * Same value is used for PSA_ALG_CATEGORY_CIPHER, hence it is + * guaranteed to not be a valid PSA algorithm identifier. + */ +#define MBEDTLS_SSL_NULL_CIPHER 0x04000000 + +/** + * \brief Translate mbedtls cipher type/taglen pair to psa: + * algorithm, key type and key size. + * + * \param mbedtls_cipher_type [in] given mbedtls cipher type + * \param taglen [in] given tag length + * 0 - default tag length + * \param alg [out] corresponding PSA alg + * There is no corresponding PSA + * alg for MBEDTLS_CIPHER_NULL, so + * in this case MBEDTLS_SSL_NULL_CIPHER + * is returned via this parameter + * \param key_type [out] corresponding PSA key type + * \param key_size [out] corresponding PSA key size + * + * \return PSA_SUCCESS on success or PSA_ERROR_NOT_SUPPORTED if + * conversion is not supported. + */ +psa_status_t mbedtls_ssl_cipher_to_psa(mbedtls_cipher_type_t mbedtls_cipher_type, + size_t taglen, + psa_algorithm_t *alg, + psa_key_type_t *key_type, + size_t *key_size); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +/** + * \brief Convert given PSA status to mbedtls error code. + * + * \param status [in] given PSA status + * + * \return corresponding mbedtls error code + */ +static inline MBEDTLS_DEPRECATED int psa_ssl_status_to_mbedtls(psa_status_t status) +{ + switch (status) { + case PSA_SUCCESS: + return 0; + case PSA_ERROR_INSUFFICIENT_MEMORY: + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + case PSA_ERROR_NOT_SUPPORTED: + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + case PSA_ERROR_INVALID_SIGNATURE: + return MBEDTLS_ERR_SSL_INVALID_MAC; + case PSA_ERROR_INVALID_ARGUMENT: + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + case PSA_ERROR_BAD_STATE: + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + case PSA_ERROR_BUFFER_TOO_SMALL: + return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; + default: + return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + } +} +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ +#endif /* MBEDTLS_USE_PSA_CRYPTO || MBEDTLS_SSL_PROTO_TLS1_3 */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ + defined(MBEDTLS_USE_PSA_CRYPTO) + +typedef enum { + MBEDTLS_ECJPAKE_ROUND_ONE, + MBEDTLS_ECJPAKE_ROUND_TWO +} mbedtls_ecjpake_rounds_t; + +/** + * \brief Parse the provided input buffer for getting the first round + * of key exchange. This code is common between server and client + * + * \param pake_ctx [in] the PAKE's operation/context structure + * \param buf [in] input buffer to parse + * \param len [in] length of the input buffer + * \param round [in] either MBEDTLS_ECJPAKE_ROUND_ONE or + * MBEDTLS_ECJPAKE_ROUND_TWO + * + * \return 0 on success or a negative error code in case of failure + */ +int mbedtls_psa_ecjpake_read_round( + psa_pake_operation_t *pake_ctx, + const unsigned char *buf, + size_t len, mbedtls_ecjpake_rounds_t round); + +/** + * \brief Write the first round of key exchange into the provided output + * buffer. This code is common between server and client + * + * \param pake_ctx [in] the PAKE's operation/context structure + * \param buf [out] the output buffer in which data will be written to + * \param len [in] length of the output buffer + * \param olen [out] the length of the data really written on the buffer + * \param round [in] either MBEDTLS_ECJPAKE_ROUND_ONE or + * MBEDTLS_ECJPAKE_ROUND_TWO + * + * \return 0 on success or a negative error code in case of failure + */ +int mbedtls_psa_ecjpake_write_round( + psa_pake_operation_t *pake_ctx, + unsigned char *buf, + size_t len, size_t *olen, + mbedtls_ecjpake_rounds_t round); + +#endif //MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED && MBEDTLS_USE_PSA_CRYPTO + +/** + * \brief TLS record protection modes + */ +typedef enum { + MBEDTLS_SSL_MODE_STREAM = 0, + MBEDTLS_SSL_MODE_CBC, + MBEDTLS_SSL_MODE_CBC_ETM, + MBEDTLS_SSL_MODE_AEAD +} mbedtls_ssl_mode_t; + +mbedtls_ssl_mode_t mbedtls_ssl_get_mode_from_transform( + const mbedtls_ssl_transform *transform); + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) +mbedtls_ssl_mode_t mbedtls_ssl_get_mode_from_ciphersuite( + int encrypt_then_mac, + const mbedtls_ssl_ciphersuite_t *suite); +#else +mbedtls_ssl_mode_t mbedtls_ssl_get_mode_from_ciphersuite( + const mbedtls_ssl_ciphersuite_t *suite); +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */ + +#if defined(MBEDTLS_ECDH_C) + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_read_public_ecdhe_share(mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t buf_len); + +#endif /* MBEDTLS_ECDH_C */ + +static inline int mbedtls_ssl_tls13_cipher_suite_is_offered( + mbedtls_ssl_context *ssl, int cipher_suite) +{ + const int *ciphersuite_list = ssl->conf->ciphersuite_list; + + /* Check whether we have offered this ciphersuite */ + for (size_t i = 0; ciphersuite_list[i] != 0; i++) { + if (ciphersuite_list[i] == cipher_suite) { + return 1; + } + } + return 0; +} + +/** + * \brief Validate cipher suite against config in SSL context. + * + * \param ssl SSL context + * \param suite_info Cipher suite to validate + * \param min_tls_version Minimal TLS version to accept a cipher suite + * \param max_tls_version Maximal TLS version to accept a cipher suite + * + * \return 0 if valid, negative value otherwise. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_validate_ciphersuite( + const mbedtls_ssl_context *ssl, + const mbedtls_ssl_ciphersuite_t *suite_info, + mbedtls_ssl_protocol_version min_tls_version, + mbedtls_ssl_protocol_version max_tls_version); + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_parse_server_name_ext(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end); +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) +#define MBEDTLS_SSL_RECORD_SIZE_LIMIT_EXTENSION_DATA_LENGTH (2) +#define MBEDTLS_SSL_RECORD_SIZE_LIMIT_MIN (64) + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_parse_record_size_limit_ext(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end); +#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ + +#if defined(MBEDTLS_SSL_ALPN) +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_parse_alpn_ext(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end); + + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_write_alpn_ext(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len); +#endif /* MBEDTLS_SSL_ALPN */ + +#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 + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) +/** + * \brief Given an SSL context and its associated configuration, write the TLS + * 1.3 specific Pre-Shared key extension. + * + * \param[in] ssl SSL context + * \param[in] buf Base address of the buffer where to write the extension + * \param[in] end End address of the buffer where to write the extension + * \param[out] out_len Length in bytes of the Pre-Shared key extension: data + * written into the buffer \p buf by this function plus + * the length of the binders to be written. + * \param[out] binders_len Length of the binders to be written at the end of + * the extension. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_write_identities_of_pre_shared_key_ext( + mbedtls_ssl_context *ssl, + unsigned char *buf, unsigned char *end, + size_t *out_len, size_t *binders_len); + +/** + * \brief Given an SSL context and its associated configuration, write the TLS + * 1.3 specific Pre-Shared key extension binders at the end of the + * ClientHello. + * + * \param[in] ssl SSL context + * \param[in] buf Base address of the buffer where to write the binders + * \param[in] end End address of the buffer where to write the binders + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_write_binders_of_pre_shared_key_ext( + mbedtls_ssl_context *ssl, + unsigned char *buf, unsigned char *end); +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ + defined(MBEDTLS_SSL_SESSION_TICKETS) && \ + defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && \ + defined(MBEDTLS_SSL_CLI_C) +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_session_set_hostname(mbedtls_ssl_session *session, + const char *hostname); +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) +static inline unsigned int mbedtls_ssl_session_get_ticket_flags( + mbedtls_ssl_session *session, unsigned int flags) +{ + return session->ticket_flags & + (flags & MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK); +} + +static inline void mbedtls_ssl_session_set_ticket_flags( + mbedtls_ssl_session *session, unsigned int flags) +{ + session->ticket_flags |= (flags & MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK); +} + +static inline void mbedtls_ssl_session_clear_ticket_flags( + mbedtls_ssl_session *session, unsigned int flags) +{ + session->ticket_flags &= ~(flags & MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK); +} +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_PROTO_TLS1_3) +int mbedtls_ssl_tls13_finalize_client_hello(mbedtls_ssl_context *ssl); +#endif + +#endif /* ssl_misc.h */ 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..18c19f9 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_msg.c @@ -0,0 +1,5917 @@ +/* + * 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. + */ +/* + * http://www.ietf.org/rfc/rfc2246.txt + * http://www.ietf.org/rfc/rfc4346.txt + */ + +#include "common.h" + +#if defined(MBEDTLS_SSL_TLS_C) + +#include "mbedtls/platform.h" + +#include "mbedtls/ssl.h" +#include "ssl_misc.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 + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \ + psa_to_ssl_errors, \ + psa_generic_status_to_mbedtls) +#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; +} + +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 + * there doesn't seem to be a usecase for it. + */ + 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; +} + +#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 */ + +/* + * Encryption/decryption functions + */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) || defined(MBEDTLS_SSL_PROTO_TLS1_3) + +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 */ + +/* The size of the `add_data` structure depends on various + * factors, namely + * + * 1) CID functionality disabled + * + * additional_data = + * 8: seq_num + + * 1: type + + * 2: version + + * 2: length of inner plaintext + + * + * size = 13 bytes + * + * 2) CID functionality based on RFC 9146 enabled + * + * size = 8 + 1 + 1 + 1 + 2 + 2 + 6 + 2 + CID-length + * = 23 + CID-length + * + * 3) CID functionality based on legacy CID version + according to draft-ietf-tls-dtls-connection-id-05 + * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05 + * + * size = 13 + 1 + CID-length + * + * More information about the CID usage: + * + * Per Section 5.3 of draft-ietf-tls-dtls-connection-id-05 the + * size of the additional data structure is calculated as: + * + * additional_data = + * 8: seq_num + + * 1: tls12_cid + + * 2: DTLSCipherText.version + + * n: cid + + * 1: cid_length + + * 2: length_of_DTLSInnerPlaintext + * + * Per RFC 9146 the size of the add_data structure is calculated as: + * + * additional_data = + * 8: seq_num_placeholder + + * 1: tls12_cid + + * 1: cid_length + + * 1: tls12_cid + + * 2: DTLSCiphertext.version + + * 2: epoch + + * 6: sequence_number + + * n: cid + + * 2: length_of_DTLSInnerPlaintext + * + */ +static void ssl_extract_add_data_from_record(unsigned char *add_data, + size_t *add_data_len, + mbedtls_record *rec, + mbedtls_ssl_protocol_version + tls_version, + size_t taglen) +{ + /* Several types of ciphers have been defined for use with TLS and DTLS, + * and the MAC calculations for those ciphers differ slightly. Further + * variants were added when the CID functionality was added with RFC 9146. + * This implementations also considers the use of a legacy version of the + * CID specification published in draft-ietf-tls-dtls-connection-id-05, + * which is used in deployments. + * + * We will distinguish between the non-CID and the CID cases below. + * + * --- Non-CID cases --- + * + * Quoting RFC 5246 (TLS 1.2): + * + * additional_data = seq_num + TLSCompressed.type + + * TLSCompressed.version + TLSCompressed.length; + * + * For TLS 1.3, the record sequence number is dropped from the AAD + * and encoded within the nonce of the AEAD operation instead. + * Moreover, the additional data involves the length of the TLS + * ciphertext, not the TLS plaintext as in earlier versions. + * Quoting RFC 8446 (TLS 1.3): + * + * additional_data = TLSCiphertext.opaque_type || + * TLSCiphertext.legacy_record_version || + * TLSCiphertext.length + * + * We pass the tag length to this function in order to compute the + * ciphertext length from the inner plaintext length rec->data_len via + * + * TLSCiphertext.length = TLSInnerPlaintext.length + taglen. + * + * --- CID cases --- + * + * RFC 9146 uses a common pattern when constructing the data + * passed into a MAC / AEAD cipher. + * + * Data concatenation for MACs used with block ciphers with + * Encrypt-then-MAC Processing (with CID): + * + * data = seq_num_placeholder + + * tls12_cid + + * cid_length + + * tls12_cid + + * DTLSCiphertext.version + + * epoch + + * sequence_number + + * cid + + * DTLSCiphertext.length + + * IV + + * ENC(content + padding + padding_length) + * + * Data concatenation for MACs used with block ciphers (with CID): + * + * data = seq_num_placeholder + + * tls12_cid + + * cid_length + + * tls12_cid + + * DTLSCiphertext.version + + * epoch + + * sequence_number + + * cid + + * length_of_DTLSInnerPlaintext + + * DTLSInnerPlaintext.content + + * DTLSInnerPlaintext.real_type + + * DTLSInnerPlaintext.zeros + * + * AEAD ciphers use the following additional data calculation (with CIDs): + * + * additional_data = seq_num_placeholder + + * tls12_cid + + * cid_length + + * tls12_cid + + * DTLSCiphertext.version + + * epoch + + * sequence_number + + * cid + + * length_of_DTLSInnerPlaintext + * + * Section 5.3 of draft-ietf-tls-dtls-connection-id-05 (for legacy CID use) + * defines the additional data calculation as follows: + * + * additional_data = seq_num + + * tls12_cid + + * DTLSCipherText.version + + * cid + + * cid_length + + * length_of_DTLSInnerPlaintext + */ + + unsigned char *cur = add_data; + size_t ad_len_field = rec->data_len; + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ + MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT == 0 + const unsigned char seq_num_placeholder[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + if (tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { + /* In TLS 1.3, the AAD contains the length of the TLSCiphertext, + * which differs from the length of the TLSInnerPlaintext + * by the length of the authentication tag. */ + ad_len_field += taglen; + } else +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + { + ((void) tls_version); + ((void) taglen); + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ + MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT == 0 + if (rec->cid_len != 0) { + // seq_num_placeholder + memcpy(cur, seq_num_placeholder, sizeof(seq_num_placeholder)); + cur += sizeof(seq_num_placeholder); + + // tls12_cid type + *cur = rec->type; + cur++; + + // cid_length + *cur = rec->cid_len; + cur++; + } else +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + { + // epoch + sequence number + memcpy(cur, rec->ctr, sizeof(rec->ctr)); + cur += sizeof(rec->ctr); + } + } + + // type + *cur = rec->type; + cur++; + + // version + memcpy(cur, rec->ver, sizeof(rec->ver)); + cur += sizeof(rec->ver); + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ + MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT == 1 + + if (rec->cid_len != 0) { + // CID + memcpy(cur, rec->cid, rec->cid_len); + cur += rec->cid_len; + + // cid_length + *cur = rec->cid_len; + cur++; + + // length of inner plaintext + MBEDTLS_PUT_UINT16_BE(ad_len_field, cur, 0); + cur += 2; + } else +#elif defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ + MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT == 0 + + if (rec->cid_len != 0) { + // epoch + sequence number + memcpy(cur, rec->ctr, sizeof(rec->ctr)); + cur += sizeof(rec->ctr); + + // CID + memcpy(cur, rec->cid, rec->cid_len); + cur += rec->cid_len; + + // length of inner plaintext + MBEDTLS_PUT_UINT16_BE(ad_len_field, cur, 0); + cur += 2; + } else +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + { + MBEDTLS_PUT_UINT16_BE(ad_len_field, cur, 0); + cur += 2; + } + + *add_data_len = cur - add_data; +} + +#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) +{ + /* 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; + mbedtls_xor(dst_iv, dst_iv, dynamic_iv, dynamic_iv_len); +} +#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_ssl_mode_t ssl_mode; + int auth_done = 0; + unsigned char *data; + /* For an explanation of the additional data length see + * the description of ssl_extract_add_data_from_record(). + */ +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + unsigned char add_data[23 + MBEDTLS_SSL_CID_OUT_LEN_MAX]; +#else + unsigned char add_data[13]; +#endif + 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.2. */ +#if !(defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) && \ + 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; + } + + ssl_mode = mbedtls_ssl_get_mode_from_transform(transform); + + 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); + + 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) + if (transform->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { + size_t padding = + ssl_compute_padding_length(rec->data_len, + MBEDTLS_SSL_CID_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 */ + +#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_TLS1_3_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_SUITES_USE_MAC) + if (ssl_mode == MBEDTLS_SSL_MODE_STREAM || + ssl_mode == MBEDTLS_SSL_MODE_CBC) { + 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_TLS1_2) + unsigned char mac[MBEDTLS_SSL_MAC_ADD]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t sign_mac_length = 0; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + ssl_extract_add_data_from_record(add_data, &add_data_len, rec, + transform->tls_version, + transform->taglen); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + status = psa_mac_sign_setup(&operation, transform->psa_mac_enc, + transform->psa_mac_alg); + if (status != PSA_SUCCESS) { + goto hmac_failed_etm_disabled; + } + + status = psa_mac_update(&operation, add_data, add_data_len); + if (status != PSA_SUCCESS) { + goto hmac_failed_etm_disabled; + } + + status = psa_mac_update(&operation, data, rec->data_len); + if (status != PSA_SUCCESS) { + goto hmac_failed_etm_disabled; + } + + status = psa_mac_sign_finish(&operation, mac, MBEDTLS_SSL_MAC_ADD, + &sign_mac_length); + if (status != PSA_SUCCESS) { + goto hmac_failed_etm_disabled; + } +#else + 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; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + memcpy(data + rec->data_len, mac, transform->maclen); +#endif + + MBEDTLS_SSL_DEBUG_BUF(4, "computed mac", data + rec->data_len, + transform->maclen); + + rec->data_len += transform->maclen; + post_avail -= transform->maclen; + auth_done++; + +hmac_failed_etm_disabled: + mbedtls_platform_zeroize(mac, transform->maclen); +#if defined(MBEDTLS_USE_PSA_CRYPTO) + ret = PSA_TO_MBEDTLS_ERR(status); + status = psa_mac_abort(&operation); + if (ret == 0 && status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_hmac_xxx", ret); + return ret; + } + } +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ + + /* + * Encrypt + */ +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_STREAM) + if (ssl_mode == MBEDTLS_SSL_MODE_STREAM) { + MBEDTLS_SSL_DEBUG_MSG(3, ("before encrypt: msglen = %" MBEDTLS_PRINTF_SIZET ", " + "including %d bytes of padding", + rec->data_len, 0)); + + /* The only supported stream cipher is "NULL", + * so there's nothing to do here.*/ + } else +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_STREAM */ + +#if defined(MBEDTLS_GCM_C) || \ + defined(MBEDTLS_CCM_C) || \ + defined(MBEDTLS_CHACHAPOLY_C) + if (ssl_mode == MBEDTLS_SSL_MODE_AEAD) { + 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); +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* 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->tls_version, + transform->taglen); + + 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 defined(MBEDTLS_USE_PSA_CRYPTO) + status = psa_aead_encrypt(transform->psa_key_enc, + transform->psa_alg, + iv, transform->ivlen, + add_data, add_data_len, + data, rec->data_len, + data, rec->buf_len - (data - rec->buf), + &rec->data_len); + + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_encrypt_buf", ret); + return ret; + } +#else + 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_ext", ret); + return ret; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + 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 (ssl_mode == MBEDTLS_SSL_MODE_CBC || + ssl_mode == MBEDTLS_SSL_MODE_CBC_ETM) { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t padlen, i; + size_t olen; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t part_len; + psa_cipher_operation_t cipher_op = PSA_CIPHER_OPERATION_INIT; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + /* 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_2) + /* + * Prepend per-record IV for block cipher in TLS v1.2 as per + * Method 1 (6.2.3.2. in RFC4346 and RFC5246) + */ + 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_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 defined(MBEDTLS_USE_PSA_CRYPTO) + status = psa_cipher_encrypt_setup(&cipher_op, + transform->psa_key_enc, transform->psa_alg); + + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_encrypt_setup", ret); + return ret; + } + + status = psa_cipher_set_iv(&cipher_op, transform->iv_enc, transform->ivlen); + + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_set_iv", ret); + return ret; + + } + + status = psa_cipher_update(&cipher_op, + data, rec->data_len, + data, rec->data_len, &olen); + + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_update", ret); + return ret; + + } + + status = psa_cipher_finish(&cipher_op, + data + olen, rec->data_len - olen, + &part_len); + + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_finish", ret); + return ret; + + } + + olen += part_len; +#else + 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; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + if (rec->data_len != olen) { + MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + 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]; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; + size_t sign_mac_length = 0; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + /* MAC(MAC_write_key, add_data, IV, 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->tls_version, + transform->taglen); + + MBEDTLS_SSL_DEBUG_MSG(3, ("using encrypt then mac")); + MBEDTLS_SSL_DEBUG_BUF(4, "MAC'd meta-data", add_data, + add_data_len); +#if defined(MBEDTLS_USE_PSA_CRYPTO) + status = psa_mac_sign_setup(&operation, transform->psa_mac_enc, + transform->psa_mac_alg); + if (status != PSA_SUCCESS) { + goto hmac_failed_etm_enabled; + } + + status = psa_mac_update(&operation, add_data, add_data_len); + if (status != PSA_SUCCESS) { + goto hmac_failed_etm_enabled; + } + + status = psa_mac_update(&operation, data, rec->data_len); + if (status != PSA_SUCCESS) { + goto hmac_failed_etm_enabled; + } + + status = psa_mac_sign_finish(&operation, mac, MBEDTLS_SSL_MAC_ADD, + &sign_mac_length); + if (status != PSA_SUCCESS) { + goto hmac_failed_etm_enabled; + } +#else + + 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; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + 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 defined(MBEDTLS_USE_PSA_CRYPTO) + ret = PSA_TO_MBEDTLS_ERR(status); + status = psa_mac_abort(&operation); + if (ret == 0 && status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + 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) +{ +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) || defined(MBEDTLS_CIPHER_MODE_AEAD) + size_t olen; +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC || MBEDTLS_CIPHER_MODE_AEAD */ + mbedtls_ssl_mode_t ssl_mode; + int ret; + + int auth_done = 0; +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) + size_t padlen = 0, correct = 1; +#endif + unsigned char *data; + /* For an explanation of the additional data length see + * the description of ssl_extract_add_data_from_record(). + */ +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + unsigned char add_data[23 + MBEDTLS_SSL_CID_IN_LEN_MAX]; +#else + unsigned char add_data[13]; +#endif + 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; + ssl_mode = mbedtls_ssl_get_mode_from_transform(transform); + +#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_SSL_SOME_SUITES_USE_STREAM) + if (ssl_mode == MBEDTLS_SSL_MODE_STREAM) { + /* The only supported stream cipher is "NULL", + * so there's nothing to do here.*/ + } else +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_STREAM */ +#if defined(MBEDTLS_GCM_C) || \ + defined(MBEDTLS_CCM_C) || \ + defined(MBEDTLS_CHACHAPOLY_C) + if (ssl_mode == MBEDTLS_SSL_MODE_AEAD) { + unsigned char iv[12]; + unsigned char *dynamic_iv; + size_t dynamic_iv_len; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + /* + * 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->tls_version, + transform->taglen); + 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_ext() 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 defined(MBEDTLS_USE_PSA_CRYPTO) + status = psa_aead_decrypt(transform->psa_key_dec, + transform->psa_alg, + iv, transform->ivlen, + add_data, add_data_len, + data, rec->data_len + transform->taglen, + data, rec->buf_len - (data - rec->buf), + &olen); + + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_aead_decrypt", ret); + return ret; + } +#else + 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_ext", ret); + + if (ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED) { + return MBEDTLS_ERR_SSL_INVALID_MAC; + } + + return ret; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + 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 (ssl_mode == MBEDTLS_SSL_MODE_CBC || + ssl_mode == MBEDTLS_SSL_MODE_CBC_ETM) { + size_t minlen = 0; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t part_len; + psa_cipher_operation_t cipher_op = PSA_CIPHER_OPERATION_INIT; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + /* + * Check immediate ciphertext sanity + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_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 (ssl_mode == MBEDTLS_SSL_MODE_CBC_ETM) { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; +#else + unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD]; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + 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->tls_version, + transform->taglen); + + /* Calculate expected MAC. */ + MBEDTLS_SSL_DEBUG_BUF(4, "MAC'd meta-data", add_data, + add_data_len); +#if defined(MBEDTLS_USE_PSA_CRYPTO) + status = psa_mac_verify_setup(&operation, transform->psa_mac_dec, + transform->psa_mac_alg); + if (status != PSA_SUCCESS) { + goto hmac_failed_etm_enabled; + } + + status = psa_mac_update(&operation, add_data, add_data_len); + if (status != PSA_SUCCESS) { + goto hmac_failed_etm_enabled; + } + + status = psa_mac_update(&operation, data, rec->data_len); + if (status != PSA_SUCCESS) { + goto hmac_failed_etm_enabled; + } + + /* Compare expected MAC with MAC at the end of the record. */ + status = psa_mac_verify_finish(&operation, data + rec->data_len, + transform->maclen); + if (status != PSA_SUCCESS) { + goto hmac_failed_etm_enabled; + } +#else + 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; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + auth_done++; + +hmac_failed_etm_enabled: +#if defined(MBEDTLS_USE_PSA_CRYPTO) + ret = PSA_TO_MBEDTLS_ERR(status); + status = psa_mac_abort(&operation); + if (ret == 0 && status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + } +#else + mbedtls_platform_zeroize(mac_expect, transform->maclen); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + 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_2) + /* + * Initialize for prepended IV for block cipher in TLS v1.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_2 */ + + /* We still have data_len % ivlen == 0 and data_len >= ivlen here. */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + status = psa_cipher_decrypt_setup(&cipher_op, + transform->psa_key_dec, transform->psa_alg); + + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_decrypt_setup", ret); + return ret; + } + + status = psa_cipher_set_iv(&cipher_op, transform->iv_dec, transform->ivlen); + + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_set_iv", ret); + return ret; + } + + status = psa_cipher_update(&cipher_op, + data, rec->data_len, + data, rec->data_len, &olen); + + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_update", ret); + return ret; + } + + status = psa_cipher_finish(&cipher_op, + data + olen, rec->data_len - olen, + &part_len); + + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_finish", ret); + return ret; + } + + olen += part_len; +#else + + 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; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + /* 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; + } + + /* 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_TLS1_2) + /* 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); + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + /* 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_SUITES_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->tls_version, + transform->taglen); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* + * 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; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + ret = mbedtls_ct_hmac(transform->psa_mac_dec, + transform->psa_mac_alg, + add_data, add_data_len, + data, rec->data_len, min_len, max_len, + mac_expect); +#else + ret = mbedtls_ct_hmac(&transform->md_ctx_dec, + add_data, add_data_len, + data, rec->data_len, min_len, max_len, + mac_expect); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + 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); +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#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_SUITES_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) + if (transform->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { + /* 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 */ + +#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 + +/* + * 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() ")); + 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 (mbedtls_ssl_is_handshake_over(ssl) == 0) { + 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) { + 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() ")); + 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) { + 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[MBEDTLS_SSL_SEQUENCE_NUMBER_LEN]; + + 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, sizeof(tmp_out_ctr)); + memcpy(ssl->cur_out_ctr, ssl->handshake->alt_out_ctr, + sizeof(ssl->cur_out_ctr)); + memcpy(ssl->handshake->alt_out_ctr, tmp_out_ctr, + sizeof(ssl->handshake->alt_out_ctr)); + + /* Adjust to the newly activated transform */ + mbedtls_ssl_update_out_pointers(ssl, ssl->transform_out); + + 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); + + int 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 (mbedtls_ssl_is_handshake_over(ssl) == 1) { + 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 + */ +int mbedtls_ssl_start_handshake_msg(mbedtls_ssl_context *ssl, unsigned hs_type, + unsigned char **buf, size_t *buf_len) +{ + /* + * Reserve 4 bytes for handshake header. ( Section 4,RFC 8446 ) + * ... + * HandshakeType msg_type; + * uint24 length; + * ... + */ + *buf = ssl->out_msg + 4; + *buf_len = MBEDTLS_SSL_OUT_CONTENT_LEN - 4; + + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = hs_type; + + return 0; +} + +/* + * 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_ext(mbedtls_ssl_context *ssl, + int update_checksum, + int force_flush) +{ + 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) { + 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 && update_checksum != 0) { + ret = ssl->handshake->update_checksum(ssl, ssl->out_msg, + ssl->out_msglen); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "update_checksum", ret); + return ret; + } + } + } + + /* 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, force_flush)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_record", ret); + return ret; + } + } + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= write handshake message")); + + return 0; +} + +int mbedtls_ssl_finish_handshake_msg(mbedtls_ssl_context *ssl, + size_t buf_len, size_t msg_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t msg_with_header_len; + ((void) buf_len); + + /* Add reserved 4 bytes for handshake header */ + msg_with_header_len = msg_len + 4; + ssl->out_msglen = msg_with_header_len; + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_write_handshake_msg_ext(ssl, 0, 0)); + +cleanup: + return ret; +} + +/* + * 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, int force_flush) +{ + int ret, done = 0; + size_t len = ssl->out_msglen; + int flush = force_flush; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> write record")); + + 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_protocol_version tls_ver = ssl->tls_version; +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + /* TLS 1.3 still uses the TLS 1.2 version identifier + * for backwards compatibility. */ + if (tls_ver == MBEDTLS_SSL_VERSION_TLS1_3) { + tls_ver = MBEDTLS_SSL_VERSION_TLS1_2; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + mbedtls_ssl_write_version(ssl->out_hdr + 1, ssl->conf->transport, + tls_ver); + + memcpy(ssl->out_ctr, ssl->cur_out_ctr, MBEDTLS_SSL_SEQUENCE_NUMBER_LEN); + 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, sizeof(rec.ctr)); + mbedtls_ssl_write_version(rec.ver, ssl->conf->transport, tls_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 if 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 && + ((mbedtls_ssl_is_handshake_over(ssl) == 0 && + recv_msg_seq != ssl->handshake->in_msg_seq) || + (mbedtls_ssl_is_handshake_over(ssl) == 1 && + 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; +} + +int mbedtls_ssl_update_handshake_status(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + + if (mbedtls_ssl_is_handshake_over(ssl) == 0 && hs != NULL) { + ret = ssl->handshake->update_checksum(ssl, ssl->in_msg, ssl->in_hslen); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "update_checksum", ret); + return ret; + } + } + + /* 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 + return 0; +} + +/* + * 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, epoch, fragment_offset; + 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_DECODE_ERROR; + } + + epoch = MBEDTLS_GET_UINT16_BE(in, 3); + fragment_offset = MBEDTLS_GET_UINT24_BE(in, 19); + + if (in[0] != MBEDTLS_SSL_MSG_HANDSHAKE || epoch != 0 || + fragment_offset != 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) epoch, + (unsigned) fragment_offset)); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + 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_DECODE_ERROR; + } + 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_DECODE_ERROR; + } + + 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) +{ + mbedtls_ssl_protocol_version tls_version; + + 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 outer_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]; + tls_version = mbedtls_ssl_read_version(buf + rec_hdr_version_offset, + ssl->conf->transport); + + if (tls_version > ssl->conf->max_tls_version) { + MBEDTLS_SSL_DEBUG_MSG(1, ("TLS version mismatch: got %u, expected max %u", + (unsigned) tls_version, + (unsigned) ssl->conf->max_tls_version)); + + 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 = [0x%x], msglen = %" MBEDTLS_PRINTF_SIZET, + rec->type, (unsigned) tls_version, 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 && + mbedtls_ssl_is_handshake_over(ssl) == 1 && + 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); + + /* + * In TLS 1.3, always treat ChangeCipherSpec records + * as unencrypted. The only thing we do with them is + * check the length and content and ignore them. + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + if (ssl->transform_in != NULL && + ssl->transform_in->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { + if (rec->type == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC) { + done = 1; + } + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + + 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->tls_version == MBEDTLS_SSL_VERSION_TLS1_2 + && 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 = MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; + 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) { + int dtls_have_buffered = 0; +#if defined(MBEDTLS_SSL_PROTO_DTLS) + + /* 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) { + dtls_have_buffered = 1; + } + } + +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + if (dtls_have_buffered == 0) { + 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) { + ret = mbedtls_ssl_update_handshake_status(ssl); + if (0 != ret) { + MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ssl_update_handshake_status"), ret); + return ret; + } + } + } 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_message")); + + 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 (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; + } + + /* 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); + + 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 defined(MBEDTLS_SSL_PROTO_TLS1_3) + if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + MBEDTLS_SSL_DEBUG_MSG(1, + ("Ignore ChangeCipherSpec in TLS 1.3 compatibility mode")); + return MBEDTLS_ERR_SSL_CONTINUE_PROCESSING; +#else + MBEDTLS_SSL_DEBUG_MSG(1, + ("ChangeCipherSpec invalid in TLS 1.3 without compatibility mode")); + return MBEDTLS_ERR_SSL_INVALID_RECORD; +#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + } + + 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 no renegotiation alert")); + /* Will be handled when trying to parse ServerHello */ + return 0; + } +#endif + /* 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 && + mbedtls_ssl_is_handshake_over(ssl) == 0 +#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 && + mbedtls_ssl_is_handshake_over(ssl) == 1) { + 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")); +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + ssl->transform_in = ssl->transform_negotiate; +#endif + 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, MBEDTLS_SSL_SEQUENCE_NUMBER_LEN); + + mbedtls_ssl_update_in_pointers(ssl); + + 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) +{ + 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 + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; + 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 + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + ssl->out_iv = ssl->out_len + 2; + } else +#endif + { + 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 + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; + ssl->in_len = ssl->in_cid; /* Default: no CID */ +#else /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + ssl->in_len = ssl->in_ctr + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + ssl->in_iv = ssl->in_len + 2; + } else +#endif + { + ssl->in_ctr = ssl->in_hdr - MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; + 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_ctr = ssl->out_buf; + 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; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT; + psa_key_type_t key_type; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + size_t out_hdr_len = mbedtls_ssl_out_hdr_len(ssl); + + if (transform == NULL) { + return (int) out_hdr_len; + } + + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if (transform->psa_alg == PSA_ALG_GCM || + transform->psa_alg == PSA_ALG_CCM || + transform->psa_alg == PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 8) || + transform->psa_alg == PSA_ALG_CHACHA20_POLY1305 || + transform->psa_alg == MBEDTLS_SSL_NULL_CIPHER) { + transform_expansion = transform->minlen; + } else if (transform->psa_alg == PSA_ALG_CBC_NO_PADDING) { + (void) psa_get_key_attributes(transform->psa_key_enc, &attr); + key_type = psa_get_key_type(&attr); + + block_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type); + + /* 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.2 or higher, an explicit IV is added + * after the record header. */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + transform_expansion += block_size; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + } else { + MBEDTLS_SSL_DEBUG_MSG(1, + ("Unsupported psa_alg spotted in mbedtls_ssl_get_record_expansion()")); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } +#else + 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.2 or higher, an explicit IV is added + * after the record header. */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + transform_expansion += block_size; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + break; + + default: + MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#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 (mbedtls_ssl_is_handshake_over(ssl) == 0 || + 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], + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN - ep_len); + out_ctr_cmp = memcmp(&ssl->cur_out_ctr[ep_len], + &ssl->conf->renego_period[ep_len], + sizeof(ssl->cur_out_ctr) - 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 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_check_new_session_ticket(mbedtls_ssl_context *ssl) +{ + + if ((ssl->in_hslen == mbedtls_ssl_hs_hdr_len(ssl)) || + (ssl->in_msg[0] != MBEDTLS_SSL_HS_NEW_SESSION_TICKET)) { + return 0; + } + + ssl->keep_current_message = 1; + + MBEDTLS_SSL_DEBUG_MSG(3, ("NewSessionTicket received")); + mbedtls_ssl_handshake_set_state(ssl, + MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET); + + return MBEDTLS_ERR_SSL_WANT_READ; +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_handle_hs_message_post_handshake(mbedtls_ssl_context *ssl) +{ + + MBEDTLS_SSL_DEBUG_MSG(3, ("received post-handshake message")); + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { + int ret = ssl_tls13_check_new_session_ticket(ssl); + if (ret != 0) { + return ret; + } + } +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + + /* Fail in all other cases. */ + return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; +} +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +/* This function is called from mbedtls_ssl_read() when a handshake message is + * received after the initial handshake. In this context, handshake messages + * may only be sent for the purpose of initiating renegotiations. + * + * This function is introduced as a separate helper since the handling + * of post-handshake handshake messages changes significantly in TLS 1.3, + * and having a helper function allows to distinguish between TLS <= 1.2 and + * TLS 1.3 in the future without bloating the logic of mbedtls_ssl_read(). + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls12_handle_hs_message_post_handshake(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* + * - 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) { + return 0; + } +#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) { + return 0; + } +#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 ((ret = mbedtls_ssl_send_alert_message(ssl, + MBEDTLS_SSL_ALERT_LEVEL_WARNING, + MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION)) != 0) { + return ret; + } + } + + return 0; +} +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_handle_hs_message_post_handshake(mbedtls_ssl_context *ssl) +{ + /* Check protocol version and dispatch accordingly. */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { + return ssl_tls13_handle_hs_message_post_handshake(ssl); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if (ssl->tls_version <= MBEDTLS_SSL_VERSION_TLS1_2) { + return ssl_tls12_handle_hs_message_post_handshake(ssl); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + /* Should never happen */ + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; +} + +/* + * 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) { + ret = ssl_handle_hs_message_post_handshake(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "ssl_handle_hs_message_post_handshake", + ret); + return ret; + } + + /* At this point, we don't know whether the renegotiation triggered + * by the post-handshake message 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 cases, 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 (mbedtls_ssl_is_handshake_over(ssl) == 1) { + 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; + + if (len != 0) { + 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; + if (len > 0) { + 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 (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; + } + } + + ret = ssl_write_real(ssl, buf, len); + + 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 (mbedtls_ssl_is_handshake_over(ssl) == 1) { + 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_USE_PSA_CRYPTO) + psa_destroy_key(transform->psa_key_enc); + psa_destroy_key(transform->psa_key_dec); +#else + mbedtls_cipher_free(&transform->cipher_ctx_enc); + mbedtls_cipher_free(&transform->cipher_ctx_dec); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_destroy_key(transform->psa_mac_enc); + psa_destroy_key(transform->psa_mac_dec); +#else + mbedtls_md_free(&transform->md_ctx_enc); + mbedtls_md_free(&transform->md_ctx_dec); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif + + mbedtls_platform_zeroize(transform, sizeof(mbedtls_ssl_transform)); +} + +void mbedtls_ssl_set_inbound_transform(mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform) +{ + ssl->transform_in = transform; + memset(ssl->in_ctr, 0, MBEDTLS_SSL_SEQUENCE_NUMBER_LEN); +} + +void mbedtls_ssl_set_outbound_transform(mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform) +{ + ssl->transform_out = transform; + memset(ssl->cur_out_ctr, 0, sizeof(ssl->cur_out_ctr)); +} + +#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, map as follows, then use 1's complement (v -> ~v): + * 1.x <-> 3.x+1 for x != 0 (DTLS 1.2 based on TLS 1.2) + * DTLS 1.0 is stored as TLS 1.1 internally + */ +void mbedtls_ssl_write_version(unsigned char version[2], int transport, + mbedtls_ssl_protocol_version tls_version) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if (transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { + tls_version = + ~(tls_version - (tls_version == 0x0302 ? 0x0202 : 0x0201)); + } +#else + ((void) transport); +#endif + MBEDTLS_PUT_UINT16_BE(tls_version, version, 0); +} + +uint16_t mbedtls_ssl_read_version(const unsigned char version[2], + int transport) +{ + uint16_t tls_version = MBEDTLS_GET_UINT16_BE(version, 0); +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if (transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { + tls_version = + ~(tls_version - (tls_version == 0xfeff ? 0x0202 : 0x0201)); + } +#else + ((void) transport); +#endif + return tls_version; +} + +/* + * Send pending fatal alert. + * 0, No alert message. + * !0, if mbedtls_ssl_send_alert_message() returned in error, the error code it + * returned, ssl->alert_reason otherwise. + */ +int mbedtls_ssl_handle_pending_alert(mbedtls_ssl_context *ssl) +{ + int ret; + + /* No pending alert, return success*/ + if (ssl->send_alert == 0) { + return 0; + } + + ret = mbedtls_ssl_send_alert_message(ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + ssl->alert_type); + + /* If mbedtls_ssl_send_alert_message() returned with MBEDTLS_ERR_SSL_WANT_WRITE, + * do not clear the alert to be able to send it later. + */ + if (ret != MBEDTLS_ERR_SSL_WANT_WRITE) { + ssl->send_alert = 0; + } + + if (ret != 0) { + return ret; + } + + return ssl->alert_reason; +} + +/* + * Set pending fatal alert flag. + */ +void mbedtls_ssl_pend_fatal_alert(mbedtls_ssl_context *ssl, + unsigned char alert_type, + int alert_reason) +{ + ssl->send_alert = 1; + ssl->alert_type = alert_type; + ssl->alert_reason = alert_reason; +} + +#endif /* MBEDTLS_SSL_TLS_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..7d07d19 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_ticket.c @@ -0,0 +1,546 @@ +/* + * 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) + +#include "mbedtls/platform.h" + +#include "ssl_misc.h" +#include "mbedtls/ssl_ticket.h" +#include "mbedtls/error.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \ + psa_to_ssl_errors, \ + psa_generic_status_to_mbedtls) +#endif + +/* + * 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 MBEDTLS_SSL_TICKET_MAX_KEY_BYTES + +#define TICKET_KEY_NAME_BYTES MBEDTLS_SSL_TICKET_KEY_NAME_BYTES +#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] = { 0 }; + mbedtls_ssl_ticket_key *key = ctx->keys + index; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; +#endif + +#if defined(MBEDTLS_HAVE_TIME) + key->generation_time = 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; + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_set_key_usage_flags(&attributes, + PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT); + psa_set_key_algorithm(&attributes, key->alg); + psa_set_key_type(&attributes, key->key_type); + psa_set_key_bits(&attributes, key->key_bits); + + ret = PSA_TO_MBEDTLS_ERR( + psa_import_key(&attributes, buf, + PSA_BITS_TO_BYTES(key->key_bits), + &key->key)); +#else + /* 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); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + 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) { + mbedtls_time_t current_time = mbedtls_time(NULL); + mbedtls_time_t key_time = ctx->keys[ctx->active].generation_time; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; +#endif + + if (current_time >= key_time && + (uint64_t) (current_time - key_time) < ctx->ticket_lifetime) { + return 0; + } + + ctx->active = 1 - ctx->active; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if ((status = psa_destroy_key(ctx->keys[ctx->active].key)) != PSA_SUCCESS) { + return PSA_TO_MBEDTLS_ERR(status); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + return ssl_ticket_gen_key(ctx, ctx->active); + } else +#endif /* MBEDTLS_HAVE_TIME */ + return 0; +} + +/* + * Rotate active session ticket encryption key + */ +int mbedtls_ssl_ticket_rotate(mbedtls_ssl_ticket_context *ctx, + const unsigned char *name, size_t nlength, + const unsigned char *k, size_t klength, + uint32_t lifetime) +{ + const unsigned char idx = 1 - ctx->active; + mbedtls_ssl_ticket_key * const key = ctx->keys + idx; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + const size_t bitlen = key->key_bits; +#else + const int bitlen = mbedtls_cipher_get_key_bitlen(&key->ctx); +#endif + + if (nlength < TICKET_KEY_NAME_BYTES || klength * 8 < (size_t) bitlen) { + return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if ((status = psa_destroy_key(key->key)) != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + return ret; + } + + psa_set_key_usage_flags(&attributes, + PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT); + psa_set_key_algorithm(&attributes, key->alg); + psa_set_key_type(&attributes, key->key_type); + psa_set_key_bits(&attributes, key->key_bits); + + if ((status = psa_import_key(&attributes, k, + PSA_BITS_TO_BYTES(key->key_bits), + &key->key)) != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + return ret; + } +#else + ret = mbedtls_cipher_setkey(&key->ctx, k, bitlen, MBEDTLS_ENCRYPT); + if (ret != 0) { + return ret; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + ctx->active = idx; + ctx->ticket_lifetime = lifetime; + memcpy(key->name, name, TICKET_KEY_NAME_BYTES); +#if defined(MBEDTLS_HAVE_TIME) + key->generation_time = mbedtls_time(NULL); +#endif + 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; + size_t key_bits; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_algorithm_t alg; + psa_key_type_t key_type; +#else + const mbedtls_cipher_info_t *cipher_info; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if (mbedtls_ssl_cipher_to_psa(cipher, TICKET_AUTH_TAG_BYTES, + &alg, &key_type, &key_bits) != PSA_SUCCESS) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + if (PSA_ALG_IS_AEAD(alg) == 0) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } +#else + cipher_info = mbedtls_cipher_info_from_type(cipher); + + if (mbedtls_cipher_info_get_mode(cipher_info) != MBEDTLS_MODE_GCM && + mbedtls_cipher_info_get_mode(cipher_info) != MBEDTLS_MODE_CCM && + mbedtls_cipher_info_get_mode(cipher_info) != MBEDTLS_MODE_CHACHAPOLY) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + key_bits = mbedtls_cipher_info_get_key_bitlen(cipher_info); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + if (key_bits > 8 * MAX_KEY_BYTES) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + ctx->f_rng = f_rng; + ctx->p_rng = p_rng; + + ctx->ticket_lifetime = lifetime; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + ctx->keys[0].alg = alg; + ctx->keys[0].key_type = key_type; + ctx->keys[0].key_bits = key_bits; + + ctx->keys[1].alg = alg; + ctx->keys[1].key_type = key_type; + ctx->keys[1].key_bits = key_bits; +#else + if ((ret = mbedtls_cipher_setup(&ctx->keys[0].ctx, cipher_info)) != 0) { + return ret; + } + + if ((ret = mbedtls_cipher_setup(&ctx->keys[1].ctx, cipher_info)) != 0) { + return ret; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + 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; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; +#endif + + *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 defined(MBEDTLS_USE_PSA_CRYPTO) + if ((status = psa_aead_encrypt(key->key, key->alg, iv, TICKET_IV_BYTES, + key_name, TICKET_ADD_DATA_LEN, + state, clear_len, + state, end - state, + &ciph_len)) != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + goto cleanup; + } +#else + 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; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + 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 defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; +#endif + + 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 defined(MBEDTLS_USE_PSA_CRYPTO) + if ((status = psa_aead_decrypt(key->key, key->alg, iv, TICKET_IV_BYTES, + key_name, TICKET_ADD_DATA_LEN, + ticket, enc_len + TICKET_AUTH_TAG_BYTES, + ticket, enc_len, &clear_len)) != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + goto cleanup; + } +#else + 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; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + 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) +{ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_destroy_key(ctx->keys[0].key); + psa_destroy_key(ctx->keys[1].key); +#else + mbedtls_cipher_free(&ctx->keys[0].ctx); + mbedtls_cipher_free(&ctx->keys[1].ctx); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#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..a6129da --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls.c @@ -0,0 +1,9695 @@ +/* + * TLS 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. + */ +/* + * http://www.ietf.org/rfc/rfc2246.txt + * http://www.ietf.org/rfc/rfc4346.txt + */ + +#include "common.h" + +#if defined(MBEDTLS_SSL_TLS_C) + +#include "mbedtls/platform.h" + +#include "mbedtls/ssl.h" +#include "ssl_client.h" +#include "ssl_debug_helpers.h" +#include "ssl_misc.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 +#include "mbedtls/legacy_or_psa.h" + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#include "mbedtls/oid.h" +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \ + psa_to_ssl_errors, \ + psa_generic_status_to_mbedtls) +#define PSA_TO_MD_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \ + psa_to_md_errors, \ + psa_generic_status_to_mbedtls) +#endif + +#if defined(MBEDTLS_TEST_HOOKS) +static mbedtls_ssl_chk_buf_ptr_args chk_buf_ptr_fail_args; + +void mbedtls_ssl_set_chk_buf_ptr_fail_args( + const uint8_t *cur, const uint8_t *end, size_t need) +{ + chk_buf_ptr_fail_args.cur = cur; + chk_buf_ptr_fail_args.end = end; + chk_buf_ptr_fail_args.need = need; +} + +void mbedtls_ssl_reset_chk_buf_ptr_fail_args(void) +{ + memset(&chk_buf_ptr_fail_args, 0, sizeof(chk_buf_ptr_fail_args)); +} + +int mbedtls_ssl_cmp_chk_buf_ptr_fail_args(mbedtls_ssl_chk_buf_ptr_args *args) +{ + return (chk_buf_ptr_fail_args.cur != args->cur) || + (chk_buf_ptr_fail_args.end != args->end) || + (chk_buf_ptr_fail_args.need != args->need); +} +#endif /* MBEDTLS_TEST_HOOKS */ + +#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_own_cid(mbedtls_ssl_context *ssl, + int *enabled, + unsigned char own_cid[MBEDTLS_SSL_CID_OUT_LEN_MAX], + size_t *own_cid_len) +{ + *enabled = MBEDTLS_SSL_CID_DISABLED; + + if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + /* We report MBEDTLS_SSL_CID_DISABLED in case the CID length is + * zero as this is indistinguishable from not requesting to use + * the CID extension. */ + if (ssl->own_cid_len == 0 || ssl->negotiate_cid == MBEDTLS_SSL_CID_DISABLED) { + return 0; + } + + if (own_cid_len != NULL) { + *own_cid_len = ssl->own_cid_len; + if (own_cid != NULL) { + memcpy(own_cid, ssl->own_cid, ssl->own_cid_len); + } + } + + *enabled = MBEDTLS_SSL_CID_ENABLED; + + 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 || + mbedtls_ssl_is_handshake_over(ssl) == 0) { + 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; +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ + defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + dst->hostname = NULL; +#endif +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + +#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); + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ + defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if (src->endpoint == MBEDTLS_SSL_IS_CLIENT) { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ret = mbedtls_ssl_session_set_hostname(dst, src->hostname); + if (ret != 0) { + return ret; + } + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 && + MBEDTLS_SSL_SERVER_NAME_INDICATION */ +#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 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) +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); + +#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ + +/* 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); + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls12_populate_transform(mbedtls_ssl_transform *transform, + int ciphersuite, + const unsigned char master[48], +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) + int encrypt_then_mac, +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */ + ssl_tls_prf_t tls_prf, + const unsigned char randbytes[64], + mbedtls_ssl_protocol_version tls_version, + unsigned endpoint, + const mbedtls_ssl_context *ssl); + +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +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); +static int ssl_calc_verify_tls_sha256(const mbedtls_ssl_context *, unsigned char *, size_t *); +static int ssl_calc_finished_tls_sha256(mbedtls_ssl_context *, unsigned char *, int); + +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/ + +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +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); + +static int ssl_calc_verify_tls_sha384(const mbedtls_ssl_context *, unsigned char *, size_t *); +static int ssl_calc_finished_tls_sha384(mbedtls_ssl_context *, unsigned char *, int); +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/ + +static size_t ssl_tls12_session_save(const mbedtls_ssl_session *session, + unsigned char *buf, + size_t buf_len); + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls12_session_load(mbedtls_ssl_session *session, + const unsigned char *buf, + size_t len); +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +static int ssl_update_checksum_start(mbedtls_ssl_context *, const unsigned char *, size_t); + +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +static int ssl_update_checksum_sha256(mbedtls_ssl_context *, const unsigned char *, size_t); +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/ + +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +static int ssl_update_checksum_sha384(mbedtls_ssl_context *, const unsigned char *, size_t); +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/ + +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_TLS1_2) +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + case MBEDTLS_SSL_TLS_PRF_SHA384: + tls_prf = tls_prf_sha384; + break; +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/ +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + case MBEDTLS_SSL_TLS_PRF_SHA256: + tls_prf = tls_prf_sha256; + break; +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + default: + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + } + + return tls_prf(secret, slen, label, random, rlen, dstbuf, dlen); +} + +#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 */ + +uint32_t mbedtls_ssl_get_extension_id(unsigned int extension_type) +{ + switch (extension_type) { + case MBEDTLS_TLS_EXT_SERVERNAME: + return MBEDTLS_SSL_EXT_ID_SERVERNAME; + + case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH: + return MBEDTLS_SSL_EXT_ID_MAX_FRAGMENT_LENGTH; + + case MBEDTLS_TLS_EXT_STATUS_REQUEST: + return MBEDTLS_SSL_EXT_ID_STATUS_REQUEST; + + case MBEDTLS_TLS_EXT_SUPPORTED_GROUPS: + return MBEDTLS_SSL_EXT_ID_SUPPORTED_GROUPS; + + case MBEDTLS_TLS_EXT_SIG_ALG: + return MBEDTLS_SSL_EXT_ID_SIG_ALG; + + case MBEDTLS_TLS_EXT_USE_SRTP: + return MBEDTLS_SSL_EXT_ID_USE_SRTP; + + case MBEDTLS_TLS_EXT_HEARTBEAT: + return MBEDTLS_SSL_EXT_ID_HEARTBEAT; + + case MBEDTLS_TLS_EXT_ALPN: + return MBEDTLS_SSL_EXT_ID_ALPN; + + case MBEDTLS_TLS_EXT_SCT: + return MBEDTLS_SSL_EXT_ID_SCT; + + case MBEDTLS_TLS_EXT_CLI_CERT_TYPE: + return MBEDTLS_SSL_EXT_ID_CLI_CERT_TYPE; + + case MBEDTLS_TLS_EXT_SERV_CERT_TYPE: + return MBEDTLS_SSL_EXT_ID_SERV_CERT_TYPE; + + case MBEDTLS_TLS_EXT_PADDING: + return MBEDTLS_SSL_EXT_ID_PADDING; + + case MBEDTLS_TLS_EXT_PRE_SHARED_KEY: + return MBEDTLS_SSL_EXT_ID_PRE_SHARED_KEY; + + case MBEDTLS_TLS_EXT_EARLY_DATA: + return MBEDTLS_SSL_EXT_ID_EARLY_DATA; + + case MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS: + return MBEDTLS_SSL_EXT_ID_SUPPORTED_VERSIONS; + + case MBEDTLS_TLS_EXT_COOKIE: + return MBEDTLS_SSL_EXT_ID_COOKIE; + + case MBEDTLS_TLS_EXT_PSK_KEY_EXCHANGE_MODES: + return MBEDTLS_SSL_EXT_ID_PSK_KEY_EXCHANGE_MODES; + + case MBEDTLS_TLS_EXT_CERT_AUTH: + return MBEDTLS_SSL_EXT_ID_CERT_AUTH; + + case MBEDTLS_TLS_EXT_OID_FILTERS: + return MBEDTLS_SSL_EXT_ID_OID_FILTERS; + + case MBEDTLS_TLS_EXT_POST_HANDSHAKE_AUTH: + return MBEDTLS_SSL_EXT_ID_POST_HANDSHAKE_AUTH; + + case MBEDTLS_TLS_EXT_SIG_ALG_CERT: + return MBEDTLS_SSL_EXT_ID_SIG_ALG_CERT; + + case MBEDTLS_TLS_EXT_KEY_SHARE: + return MBEDTLS_SSL_EXT_ID_KEY_SHARE; + + case MBEDTLS_TLS_EXT_TRUNCATED_HMAC: + return MBEDTLS_SSL_EXT_ID_TRUNCATED_HMAC; + + case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS: + return MBEDTLS_SSL_EXT_ID_SUPPORTED_POINT_FORMATS; + + case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC: + return MBEDTLS_SSL_EXT_ID_ENCRYPT_THEN_MAC; + + case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET: + return MBEDTLS_SSL_EXT_ID_EXTENDED_MASTER_SECRET; + + case MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT: + return MBEDTLS_SSL_EXT_ID_RECORD_SIZE_LIMIT; + + case MBEDTLS_TLS_EXT_SESSION_TICKET: + return MBEDTLS_SSL_EXT_ID_SESSION_TICKET; + + } + + return MBEDTLS_SSL_EXT_ID_UNRECOGNIZED; +} + +uint32_t mbedtls_ssl_get_extension_mask(unsigned int extension_type) +{ + return 1 << mbedtls_ssl_get_extension_id(extension_type); +} + +#if defined(MBEDTLS_DEBUG_C) +static const char *extension_name_table[] = { + [MBEDTLS_SSL_EXT_ID_UNRECOGNIZED] = "unrecognized", + [MBEDTLS_SSL_EXT_ID_SERVERNAME] = "server_name", + [MBEDTLS_SSL_EXT_ID_MAX_FRAGMENT_LENGTH] = "max_fragment_length", + [MBEDTLS_SSL_EXT_ID_STATUS_REQUEST] = "status_request", + [MBEDTLS_SSL_EXT_ID_SUPPORTED_GROUPS] = "supported_groups", + [MBEDTLS_SSL_EXT_ID_SIG_ALG] = "signature_algorithms", + [MBEDTLS_SSL_EXT_ID_USE_SRTP] = "use_srtp", + [MBEDTLS_SSL_EXT_ID_HEARTBEAT] = "heartbeat", + [MBEDTLS_SSL_EXT_ID_ALPN] = "application_layer_protocol_negotiation", + [MBEDTLS_SSL_EXT_ID_SCT] = "signed_certificate_timestamp", + [MBEDTLS_SSL_EXT_ID_CLI_CERT_TYPE] = "client_certificate_type", + [MBEDTLS_SSL_EXT_ID_SERV_CERT_TYPE] = "server_certificate_type", + [MBEDTLS_SSL_EXT_ID_PADDING] = "padding", + [MBEDTLS_SSL_EXT_ID_PRE_SHARED_KEY] = "pre_shared_key", + [MBEDTLS_SSL_EXT_ID_EARLY_DATA] = "early_data", + [MBEDTLS_SSL_EXT_ID_SUPPORTED_VERSIONS] = "supported_versions", + [MBEDTLS_SSL_EXT_ID_COOKIE] = "cookie", + [MBEDTLS_SSL_EXT_ID_PSK_KEY_EXCHANGE_MODES] = "psk_key_exchange_modes", + [MBEDTLS_SSL_EXT_ID_CERT_AUTH] = "certificate_authorities", + [MBEDTLS_SSL_EXT_ID_OID_FILTERS] = "oid_filters", + [MBEDTLS_SSL_EXT_ID_POST_HANDSHAKE_AUTH] = "post_handshake_auth", + [MBEDTLS_SSL_EXT_ID_SIG_ALG_CERT] = "signature_algorithms_cert", + [MBEDTLS_SSL_EXT_ID_KEY_SHARE] = "key_share", + [MBEDTLS_SSL_EXT_ID_TRUNCATED_HMAC] = "truncated_hmac", + [MBEDTLS_SSL_EXT_ID_SUPPORTED_POINT_FORMATS] = "supported_point_formats", + [MBEDTLS_SSL_EXT_ID_ENCRYPT_THEN_MAC] = "encrypt_then_mac", + [MBEDTLS_SSL_EXT_ID_EXTENDED_MASTER_SECRET] = "extended_master_secret", + [MBEDTLS_SSL_EXT_ID_SESSION_TICKET] = "session_ticket", + [MBEDTLS_SSL_EXT_ID_RECORD_SIZE_LIMIT] = "record_size_limit" +}; + +static unsigned int extension_type_table[] = { + [MBEDTLS_SSL_EXT_ID_UNRECOGNIZED] = 0xff, + [MBEDTLS_SSL_EXT_ID_SERVERNAME] = MBEDTLS_TLS_EXT_SERVERNAME, + [MBEDTLS_SSL_EXT_ID_MAX_FRAGMENT_LENGTH] = MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH, + [MBEDTLS_SSL_EXT_ID_STATUS_REQUEST] = MBEDTLS_TLS_EXT_STATUS_REQUEST, + [MBEDTLS_SSL_EXT_ID_SUPPORTED_GROUPS] = MBEDTLS_TLS_EXT_SUPPORTED_GROUPS, + [MBEDTLS_SSL_EXT_ID_SIG_ALG] = MBEDTLS_TLS_EXT_SIG_ALG, + [MBEDTLS_SSL_EXT_ID_USE_SRTP] = MBEDTLS_TLS_EXT_USE_SRTP, + [MBEDTLS_SSL_EXT_ID_HEARTBEAT] = MBEDTLS_TLS_EXT_HEARTBEAT, + [MBEDTLS_SSL_EXT_ID_ALPN] = MBEDTLS_TLS_EXT_ALPN, + [MBEDTLS_SSL_EXT_ID_SCT] = MBEDTLS_TLS_EXT_SCT, + [MBEDTLS_SSL_EXT_ID_CLI_CERT_TYPE] = MBEDTLS_TLS_EXT_CLI_CERT_TYPE, + [MBEDTLS_SSL_EXT_ID_SERV_CERT_TYPE] = MBEDTLS_TLS_EXT_SERV_CERT_TYPE, + [MBEDTLS_SSL_EXT_ID_PADDING] = MBEDTLS_TLS_EXT_PADDING, + [MBEDTLS_SSL_EXT_ID_PRE_SHARED_KEY] = MBEDTLS_TLS_EXT_PRE_SHARED_KEY, + [MBEDTLS_SSL_EXT_ID_EARLY_DATA] = MBEDTLS_TLS_EXT_EARLY_DATA, + [MBEDTLS_SSL_EXT_ID_SUPPORTED_VERSIONS] = MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS, + [MBEDTLS_SSL_EXT_ID_COOKIE] = MBEDTLS_TLS_EXT_COOKIE, + [MBEDTLS_SSL_EXT_ID_PSK_KEY_EXCHANGE_MODES] = MBEDTLS_TLS_EXT_PSK_KEY_EXCHANGE_MODES, + [MBEDTLS_SSL_EXT_ID_CERT_AUTH] = MBEDTLS_TLS_EXT_CERT_AUTH, + [MBEDTLS_SSL_EXT_ID_OID_FILTERS] = MBEDTLS_TLS_EXT_OID_FILTERS, + [MBEDTLS_SSL_EXT_ID_POST_HANDSHAKE_AUTH] = MBEDTLS_TLS_EXT_POST_HANDSHAKE_AUTH, + [MBEDTLS_SSL_EXT_ID_SIG_ALG_CERT] = MBEDTLS_TLS_EXT_SIG_ALG_CERT, + [MBEDTLS_SSL_EXT_ID_KEY_SHARE] = MBEDTLS_TLS_EXT_KEY_SHARE, + [MBEDTLS_SSL_EXT_ID_TRUNCATED_HMAC] = MBEDTLS_TLS_EXT_TRUNCATED_HMAC, + [MBEDTLS_SSL_EXT_ID_SUPPORTED_POINT_FORMATS] = MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS, + [MBEDTLS_SSL_EXT_ID_ENCRYPT_THEN_MAC] = MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC, + [MBEDTLS_SSL_EXT_ID_EXTENDED_MASTER_SECRET] = MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET, + [MBEDTLS_SSL_EXT_ID_SESSION_TICKET] = MBEDTLS_TLS_EXT_SESSION_TICKET, + [MBEDTLS_SSL_EXT_ID_RECORD_SIZE_LIMIT] = MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT +}; + +const char *mbedtls_ssl_get_extension_name(unsigned int extension_type) +{ + return extension_name_table[ + mbedtls_ssl_get_extension_id(extension_type)]; +} + +static const char *ssl_tls13_get_hs_msg_name(int hs_msg_type) +{ + switch (hs_msg_type) { + case MBEDTLS_SSL_HS_CLIENT_HELLO: + return "ClientHello"; + case MBEDTLS_SSL_HS_SERVER_HELLO: + return "ServerHello"; + case MBEDTLS_SSL_TLS1_3_HS_HELLO_RETRY_REQUEST: + return "HelloRetryRequest"; + case MBEDTLS_SSL_HS_NEW_SESSION_TICKET: + return "NewSessionTicket"; + case MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS: + return "EncryptedExtensions"; + case MBEDTLS_SSL_HS_CERTIFICATE: + return "Certificate"; + case MBEDTLS_SSL_HS_CERTIFICATE_REQUEST: + return "CertificateRequest"; + } + return "Unknown"; +} + +void mbedtls_ssl_print_extension(const mbedtls_ssl_context *ssl, + int level, const char *file, int line, + int hs_msg_type, unsigned int extension_type, + const char *extra_msg0, const char *extra_msg1) +{ + const char *extra_msg; + if (extra_msg0 && extra_msg1) { + mbedtls_debug_print_msg( + ssl, level, file, line, + "%s: %s(%u) extension %s %s.", + ssl_tls13_get_hs_msg_name(hs_msg_type), + mbedtls_ssl_get_extension_name(extension_type), + extension_type, + extra_msg0, extra_msg1); + return; + } + + extra_msg = extra_msg0 ? extra_msg0 : extra_msg1; + if (extra_msg) { + mbedtls_debug_print_msg( + ssl, level, file, line, + "%s: %s(%u) extension %s.", ssl_tls13_get_hs_msg_name(hs_msg_type), + mbedtls_ssl_get_extension_name(extension_type), extension_type, + extra_msg); + return; + } + + mbedtls_debug_print_msg( + ssl, level, file, line, + "%s: %s(%u) extension.", ssl_tls13_get_hs_msg_name(hs_msg_type), + mbedtls_ssl_get_extension_name(extension_type), extension_type); +} + +void mbedtls_ssl_print_extensions(const mbedtls_ssl_context *ssl, + int level, const char *file, int line, + int hs_msg_type, uint32_t extensions_mask, + const char *extra) +{ + + for (unsigned i = 0; + i < sizeof(extension_name_table) / sizeof(extension_name_table[0]); + i++) { + mbedtls_ssl_print_extension( + ssl, level, file, line, hs_msg_type, extension_type_table[i], + extensions_mask & (1 << i) ? "exists" : "does not exist", extra); + } +} + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) +#define ARRAY_LENGTH(a) (sizeof(a) / sizeof(*(a))) + +static const char *ticket_flag_name_table[] = +{ + [0] = "ALLOW_PSK_RESUMPTION", + [2] = "ALLOW_PSK_EPHEMERAL_RESUMPTION", + [3] = "ALLOW_EARLY_DATA", +}; + +void mbedtls_ssl_print_ticket_flags(const mbedtls_ssl_context *ssl, + int level, const char *file, int line, + unsigned int flags) +{ + size_t i; + + mbedtls_debug_print_msg(ssl, level, file, line, + "print ticket_flags (0x%02x)", flags); + + flags = flags & MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK; + + for (i = 0; i < ARRAY_LENGTH(ticket_flag_name_table); i++) { + if ((flags & (1 << i))) { + mbedtls_debug_print_msg(ssl, level, file, line, "- %s is set.", + ticket_flag_name_table[i]); + } + } +} +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS */ + +#endif /* MBEDTLS_DEBUG_C */ + +void mbedtls_ssl_optimize_checksum(mbedtls_ssl_context *ssl, + const mbedtls_ssl_ciphersuite_t *ciphersuite_info) +{ + ((void) ciphersuite_info); + +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + if (ciphersuite_info->mac == MBEDTLS_MD_SHA384) { + ssl->handshake->update_checksum = ssl_update_checksum_sha384; + } else +#endif +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + if (ciphersuite_info->mac != MBEDTLS_MD_SHA384) { + ssl->handshake->update_checksum = ssl_update_checksum_sha256; + } else +#endif + { + MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); + return; + } +} + +int mbedtls_ssl_add_hs_hdr_to_checksum(mbedtls_ssl_context *ssl, + unsigned hs_type, + size_t total_hs_len) +{ + unsigned char hs_hdr[4]; + + /* Build HS header for checksum update. */ + hs_hdr[0] = MBEDTLS_BYTE_0(hs_type); + hs_hdr[1] = MBEDTLS_BYTE_2(total_hs_len); + hs_hdr[2] = MBEDTLS_BYTE_1(total_hs_len); + hs_hdr[3] = MBEDTLS_BYTE_0(total_hs_len); + + return ssl->handshake->update_checksum(ssl, hs_hdr, sizeof(hs_hdr)); +} + +int mbedtls_ssl_add_hs_msg_to_checksum(mbedtls_ssl_context *ssl, + unsigned hs_type, + unsigned char const *msg, + size_t msg_len) +{ + int ret; + ret = mbedtls_ssl_add_hs_hdr_to_checksum(ssl, hs_type, msg_len); + if (ret != 0) { + return ret; + } + return ssl->handshake->update_checksum(ssl, msg, msg_len); +} + +int mbedtls_ssl_reset_checksum(mbedtls_ssl_context *ssl) +{ +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) || \ + defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status; +#else + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; +#endif +#else /* SHA-256 or SHA-384 */ + ((void) ssl); +#endif /* SHA-256 or SHA-384 */ +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + status = psa_hash_abort(&ssl->handshake->fin_sha256_psa); + if (status != PSA_SUCCESS) { + return PSA_TO_MD_ERR(status); + } + status = psa_hash_setup(&ssl->handshake->fin_sha256_psa, PSA_ALG_SHA_256); + if (status != PSA_SUCCESS) { + return PSA_TO_MD_ERR(status); + } +#else + mbedtls_md_free(&ssl->handshake->fin_sha256); + mbedtls_md_init(&ssl->handshake->fin_sha256); + ret = mbedtls_md_setup(&ssl->handshake->fin_sha256, + mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), + 0); + if (ret != 0) { + return ret; + } + ret = mbedtls_md_starts(&ssl->handshake->fin_sha256); + if (ret != 0) { + return ret; + } +#endif +#endif +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + status = psa_hash_abort(&ssl->handshake->fin_sha384_psa); + if (status != PSA_SUCCESS) { + return PSA_TO_MD_ERR(status); + } + status = psa_hash_setup(&ssl->handshake->fin_sha384_psa, PSA_ALG_SHA_384); + if (status != PSA_SUCCESS) { + return PSA_TO_MD_ERR(status); + } +#else + mbedtls_md_free(&ssl->handshake->fin_sha384); + mbedtls_md_init(&ssl->handshake->fin_sha384); + ret = mbedtls_md_setup(&ssl->handshake->fin_sha384, + mbedtls_md_info_from_type(MBEDTLS_MD_SHA384), 0); + if (ret != 0) { + return ret; + } + ret = mbedtls_md_starts(&ssl->handshake->fin_sha384); + if (ret != 0) { + return ret; + } +#endif +#endif + return 0; +} + +static int ssl_update_checksum_start(mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len) +{ +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) || \ + defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status; +#else + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; +#endif +#else /* SHA-256 or SHA-384 */ + ((void) ssl); + (void) buf; + (void) len; +#endif /* SHA-256 or SHA-384 */ +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + status = psa_hash_update(&ssl->handshake->fin_sha256_psa, buf, len); + if (status != PSA_SUCCESS) { + return PSA_TO_MD_ERR(status); + } +#else + ret = mbedtls_md_update(&ssl->handshake->fin_sha256, buf, len); + if (ret != 0) { + return ret; + } +#endif +#endif +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + status = psa_hash_update(&ssl->handshake->fin_sha384_psa, buf, len); + if (status != PSA_SUCCESS) { + return PSA_TO_MD_ERR(status); + } +#else + ret = mbedtls_md_update(&ssl->handshake->fin_sha384, buf, len); + if (ret != 0) { + return ret; + } +#endif +#endif + return 0; +} + +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +static int ssl_update_checksum_sha256(mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len) +{ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + return PSA_TO_MD_ERR(psa_hash_update( + &ssl->handshake->fin_sha256_psa, buf, len)); +#else + return mbedtls_md_update(&ssl->handshake->fin_sha256, buf, len); +#endif +} +#endif + +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +static int ssl_update_checksum_sha384(mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len) +{ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + return PSA_TO_MD_ERR(psa_hash_update( + &ssl->handshake->fin_sha384_psa, buf, len)); +#else + return mbedtls_md_update(&ssl->handshake->fin_sha384, buf, len); +#endif +} +#endif + +static void ssl_handshake_params_init(mbedtls_ssl_handshake_params *handshake) +{ + memset(handshake, 0, sizeof(mbedtls_ssl_handshake_params)); + +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + handshake->fin_sha256_psa = psa_hash_operation_init(); +#else + mbedtls_md_init(&handshake->fin_sha256); +#endif +#endif +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + handshake->fin_sha384_psa = psa_hash_operation_init(); +#else + mbedtls_md_init(&handshake->fin_sha384); +#endif +#endif + + handshake->update_checksum = ssl_update_checksum_start; + +#if defined(MBEDTLS_DHM_C) + mbedtls_dhm_init(&handshake->dhm_ctx); +#endif +#if !defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_ECDH_C) + mbedtls_ecdh_init(&handshake->ecdh_ctx); +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + handshake->psa_pake_ctx = psa_pake_operation_init(); + handshake->psa_pake_password = MBEDTLS_SVC_KEY_ID_INIT; +#else + mbedtls_ecjpake_init(&handshake->ecjpake_ctx); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#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)); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + transform->psa_key_enc = MBEDTLS_SVC_KEY_ID_INIT; + transform->psa_key_dec = MBEDTLS_SVC_KEY_ID_INIT; +#else + mbedtls_cipher_init(&transform->cipher_ctx_enc); + mbedtls_cipher_init(&transform->cipher_ctx_dec); +#endif + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + transform->psa_mac_enc = MBEDTLS_SVC_KEY_ID_INIT; + transform->psa_mac_dec = MBEDTLS_SVC_KEY_ID_INIT; +#else + mbedtls_md_init(&transform->md_ctx_enc); + mbedtls_md_init(&transform->md_ctx_dec); +#endif +#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) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* Clear old handshake information if present */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if (ssl->transform_negotiate) { + mbedtls_ssl_transform_free(ssl->transform_negotiate); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + if (ssl->session_negotiate) { + mbedtls_ssl_session_free(ssl->session_negotiate); + } + if (ssl->handshake) { + mbedtls_ssl_handshake_free(ssl); + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* + * 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)); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + 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 || +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + ssl->transform_negotiate == NULL || +#endif + ssl->session_negotiate == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("alloc() of ssl sub-contexts failed")); + + mbedtls_free(ssl->handshake); + ssl->handshake = NULL; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + mbedtls_free(ssl->transform_negotiate); + ssl->transform_negotiate = NULL; +#endif + + mbedtls_free(ssl->session_negotiate); + ssl->session_negotiate = NULL; + + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } + + /* Initialize structures */ + mbedtls_ssl_session_init(ssl->session_negotiate); + ssl_handshake_params_init(ssl->handshake); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + mbedtls_ssl_transform_init(ssl->transform_negotiate); +#endif + + /* Setup handshake checksums */ + ret = mbedtls_ssl_reset_checksum(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_reset_checksum", ret); + return ret; + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ + defined(MBEDTLS_SSL_SRV_C) && \ + defined(MBEDTLS_SSL_SESSION_TICKETS) + ssl->handshake->new_session_tickets_count = + ssl->conf->new_session_tickets_count; +#endif + +#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 + +/* + * curve_list is translated to IANA TLS group identifiers here because + * mbedtls_ssl_conf_curves returns void and so can't return + * any error codes. + */ +#if defined(MBEDTLS_ECP_C) +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + /* Heap allocate and translate curve_list from internal to IANA group ids */ + if (ssl->conf->curve_list != NULL) { + size_t length; + const mbedtls_ecp_group_id *curve_list = ssl->conf->curve_list; + + for (length = 0; (curve_list[length] != MBEDTLS_ECP_DP_NONE) && + (length < MBEDTLS_ECP_DP_MAX); length++) { + } + + /* Leave room for zero termination */ + uint16_t *group_list = mbedtls_calloc(length + 1, sizeof(uint16_t)); + if (group_list == NULL) { + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } + + for (size_t i = 0; i < length; i++) { + uint16_t tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id( + curve_list[i]); + if (tls_id == 0) { + mbedtls_free(group_list); + return MBEDTLS_ERR_SSL_BAD_CONFIG; + } + group_list[i] = tls_id; + } + + group_list[length] = 0; + + ssl->handshake->group_list = group_list; + ssl->handshake->group_list_heap_allocated = 1; + } else { + ssl->handshake->group_list = ssl->conf->group_list; + ssl->handshake->group_list_heap_allocated = 0; + } +#endif /* MBEDTLS_DEPRECATED_REMOVED */ +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* Heap allocate and translate sig_hashes from internal hash identifiers to + signature algorithms IANA identifiers. */ + if (mbedtls_ssl_conf_is_tls12_only(ssl->conf) && + ssl->conf->sig_hashes != NULL) { + const int *md; + const int *sig_hashes = ssl->conf->sig_hashes; + size_t sig_algs_len = 0; + uint16_t *p; + + MBEDTLS_STATIC_ASSERT(MBEDTLS_SSL_MAX_SIG_ALG_LIST_LEN + <= (SIZE_MAX - (2 * sizeof(uint16_t))), + "MBEDTLS_SSL_MAX_SIG_ALG_LIST_LEN too big"); + + for (md = sig_hashes; *md != MBEDTLS_MD_NONE; md++) { + if (mbedtls_ssl_hash_from_md_alg(*md) == MBEDTLS_SSL_HASH_NONE) { + continue; + } +#if defined(MBEDTLS_PK_CAN_ECDSA_SOME) + sig_algs_len += sizeof(uint16_t); +#endif + +#if defined(MBEDTLS_RSA_C) + sig_algs_len += sizeof(uint16_t); +#endif + if (sig_algs_len > MBEDTLS_SSL_MAX_SIG_ALG_LIST_LEN) { + return MBEDTLS_ERR_SSL_BAD_CONFIG; + } + } + + if (sig_algs_len < MBEDTLS_SSL_MIN_SIG_ALG_LIST_LEN) { + return MBEDTLS_ERR_SSL_BAD_CONFIG; + } + + ssl->handshake->sig_algs = mbedtls_calloc(1, sig_algs_len + + sizeof(uint16_t)); + if (ssl->handshake->sig_algs == NULL) { + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } + + p = (uint16_t *) ssl->handshake->sig_algs; + for (md = sig_hashes; *md != MBEDTLS_MD_NONE; md++) { + unsigned char hash = mbedtls_ssl_hash_from_md_alg(*md); + if (hash == MBEDTLS_SSL_HASH_NONE) { + continue; + } +#if defined(MBEDTLS_PK_CAN_ECDSA_SOME) + *p = ((hash << 8) | MBEDTLS_SSL_SIG_ECDSA); + p++; +#endif +#if defined(MBEDTLS_RSA_C) + *p = ((hash << 8) | MBEDTLS_SSL_SIG_RSA); + p++; +#endif + } + *p = MBEDTLS_TLS_SIG_NONE; + ssl->handshake->sig_algs_heap_allocated = 1; + } else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + { + ssl->handshake->sig_algs_heap_allocated = 0; + } +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ + 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)); +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_conf_version_check(const mbedtls_ssl_context *ssl) +{ + const mbedtls_ssl_config *conf = ssl->conf; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + if (mbedtls_ssl_conf_is_tls13_only(conf)) { + if (conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { + MBEDTLS_SSL_DEBUG_MSG(1, ("DTLS 1.3 is not yet supported.")); + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + } + + MBEDTLS_SSL_DEBUG_MSG(4, ("The SSL configuration is tls13 only.")); + return 0; + } +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if (mbedtls_ssl_conf_is_tls12_only(conf)) { + MBEDTLS_SSL_DEBUG_MSG(4, ("The SSL configuration is tls12 only.")); + return 0; + } +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_TLS1_3) + if (mbedtls_ssl_conf_is_hybrid_tls12_tls13(conf)) { + if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { + MBEDTLS_SSL_DEBUG_MSG(1, ("DTLS not yet supported in Hybrid TLS 1.3 + TLS 1.2")); + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + } + + if (conf->endpoint == MBEDTLS_SSL_IS_SERVER) { + MBEDTLS_SSL_DEBUG_MSG(1, ("TLS 1.3 server is not supported yet.")); + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + } + + + MBEDTLS_SSL_DEBUG_MSG(4, ("The SSL configuration is TLS 1.3 or TLS 1.2.")); + return 0; + } +#endif + + MBEDTLS_SSL_DEBUG_MSG(1, ("The SSL configuration is invalid.")); + return MBEDTLS_ERR_SSL_BAD_CONFIG; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_conf_check(const mbedtls_ssl_context *ssl) +{ + int ret; + ret = ssl_conf_version_check(ssl); + if (ret != 0) { + return ret; + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + /* RFC 8446 section 4.4.3 + * + * If the verification fails, the receiver MUST terminate the handshake with + * a "decrypt_error" alert. + * + * If the client is configured as TLS 1.3 only with optional verify, return + * bad config. + * + */ + if (mbedtls_ssl_conf_tls13_ephemeral_enabled( + (mbedtls_ssl_context *) ssl) && + ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && + ssl->conf->max_tls_version == MBEDTLS_SSL_VERSION_TLS1_3 && + ssl->conf->min_tls_version == MBEDTLS_SSL_VERSION_TLS1_3 && + ssl->conf->authmode == MBEDTLS_SSL_VERIFY_OPTIONAL) { + MBEDTLS_SSL_DEBUG_MSG( + 1, ("Optional verify auth mode " + "is not available for TLS 1.3 client")); + return MBEDTLS_ERR_SSL_BAD_CONFIG; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + + /* Space for further checks */ + + return 0; +} + +/* + * 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; + + if ((ret = ssl_conf_check(ssl)) != 0) { + return ret; + } + + /* + * 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.) + */ +void mbedtls_ssl_session_reset_msg_layer(mbedtls_ssl_context *ssl, + int partial) +{ +#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) + partial = 0; +#endif + + /* Cancel any possibly running timer */ + mbedtls_ssl_set_timer(ssl, 0); + + mbedtls_ssl_reset_in_out_pointers(ssl); + + /* Reset incoming message parsing */ + ssl->in_offt = NULL; + ssl->nb_zero = 0; + ssl->in_msgtype = 0; + ssl->in_msglen = 0; + ssl->in_hslen = 0; + ssl->keep_current_message = 0; + ssl->transform_in = NULL; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + ssl->next_record_offset = 0; + ssl->in_epoch = 0; +#endif + + /* Keep current datagram if partial == 1 */ + if (partial == 0) { + ssl->in_left = 0; + memset(ssl->in_buf, 0, in_buf_len); + } + + ssl->send_alert = 0; + + /* Reset outgoing message writing */ + ssl->out_msgtype = 0; + ssl->out_msglen = 0; + ssl->out_left = 0; + memset(ssl->out_buf, 0, out_buf_len); + memset(ssl->cur_out_ctr, 0, sizeof(ssl->cur_out_ctr)); + ssl->transform_out = NULL; + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + mbedtls_ssl_dtls_replay_reset(ssl); +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if (ssl->transform) { + mbedtls_ssl_transform_free(ssl->transform); + mbedtls_free(ssl->transform); + ssl->transform = NULL; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + mbedtls_ssl_transform_free(ssl->transform_application); + mbedtls_free(ssl->transform_application); + ssl->transform_application = NULL; + + if (ssl->handshake != NULL) { +#if defined(MBEDTLS_SSL_EARLY_DATA) + mbedtls_ssl_transform_free(ssl->handshake->transform_earlydata); + mbedtls_free(ssl->handshake->transform_earlydata); + ssl->handshake->transform_earlydata = NULL; +#endif + + mbedtls_ssl_transform_free(ssl->handshake->transform_handshake); + mbedtls_free(ssl->handshake->transform_handshake); + ssl->handshake->transform_handshake = NULL; + } + +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ +} + +int mbedtls_ssl_session_reset_int(mbedtls_ssl_context *ssl, int partial) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ssl->state = MBEDTLS_SSL_HELLO_REQUEST; + + mbedtls_ssl_session_reset_msg_layer(ssl, partial); + + /* Reset renegotiation state */ +#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->session_in = NULL; + ssl->session_out = 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) + int free_cli_id = 1; +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) + free_cli_id = (partial == 0); +#endif + if (free_cli_id) { + 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 + +void mbedtls_ssl_conf_dtls_badmac_limit(mbedtls_ssl_config *conf, unsigned limit) +{ + conf->badmac_limit = limit; +} + +#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, + mbedtls_ssl_cache_get_t *f_get_cache, + mbedtls_ssl_cache_set_t *f_set_cache) +{ + 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 (ssl->handshake->resume == 1) { + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + if (session->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + mbedtls_ssl_ciphersuite_from_id(session->ciphersuite); + + if (mbedtls_ssl_validate_ciphersuite( + ssl, ciphersuite_info, MBEDTLS_SSL_VERSION_TLS1_3, + MBEDTLS_SSL_VERSION_TLS1_3) != 0) { + MBEDTLS_SSL_DEBUG_MSG(4, ("%d is not a valid TLS 1.3 ciphersuite.", + session->ciphersuite)); + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + + 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 = ciphersuites; +} + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) +void mbedtls_ssl_conf_tls13_key_exchange_modes(mbedtls_ssl_config *conf, + const int kex_modes) +{ + conf->tls13_kex_modes = kex_modes & MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_ALL; +} + +#if defined(MBEDTLS_SSL_EARLY_DATA) +void mbedtls_ssl_tls13_conf_early_data(mbedtls_ssl_config *conf, + int early_data_enabled) +{ + conf->early_data_enabled = early_data_enabled; +} + +#if defined(MBEDTLS_SSL_SRV_C) +void mbedtls_ssl_tls13_conf_max_early_data_size( + mbedtls_ssl_config *conf, uint32_t max_early_data_size) +{ + conf->max_early_data_size = max_early_data_size; +} +#endif /* MBEDTLS_SSL_SRV_C */ + +#endif /* MBEDTLS_SSL_EARLY_DATA */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + +#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; +} + +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; + } +} + +/* 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; + + if (cert == NULL) { + /* Free list if cert is null */ + ssl_key_cert_free(*head); + *head = NULL; + return 0; + } + + 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 if 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) +const unsigned char *mbedtls_ssl_get_hs_sni(mbedtls_ssl_context *ssl, + size_t *name_len) +{ + *name_len = ssl->handshake->sni_name_len; + return ssl->handshake->sni_name; +} + +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; +} + +#if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) +void mbedtls_ssl_set_hs_dn_hints(mbedtls_ssl_context *ssl, + const mbedtls_x509_crt *crt) +{ + ssl->handshake->dn_hints = crt; +} +#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ + +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) + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +static const uint8_t jpake_server_id[] = { 's', 'e', 'r', 'v', 'e', 'r' }; +static const uint8_t jpake_client_id[] = { 'c', 'l', 'i', 'e', 'n', 't' }; + +static psa_status_t mbedtls_ssl_set_hs_ecjpake_password_common( + mbedtls_ssl_context *ssl, + mbedtls_svc_key_id_t pwd) +{ + psa_status_t status; + psa_pake_cipher_suite_t cipher_suite = psa_pake_cipher_suite_init(); + const uint8_t *user = NULL; + size_t user_len = 0; + const uint8_t *peer = NULL; + size_t peer_len = 0; + psa_pake_cs_set_algorithm(&cipher_suite, PSA_ALG_JPAKE); + psa_pake_cs_set_primitive(&cipher_suite, + PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, + PSA_ECC_FAMILY_SECP_R1, + 256)); + psa_pake_cs_set_hash(&cipher_suite, PSA_ALG_SHA_256); + + status = psa_pake_setup(&ssl->handshake->psa_pake_ctx, &cipher_suite); + if (status != PSA_SUCCESS) { + return status; + } + + if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { + user = jpake_server_id; + user_len = sizeof(jpake_server_id); + peer = jpake_client_id; + peer_len = sizeof(jpake_client_id); + } else { + user = jpake_client_id; + user_len = sizeof(jpake_client_id); + peer = jpake_server_id; + peer_len = sizeof(jpake_server_id); + } + + status = psa_pake_set_user(&ssl->handshake->psa_pake_ctx, user, user_len); + if (status != PSA_SUCCESS) { + return status; + } + + status = psa_pake_set_peer(&ssl->handshake->psa_pake_ctx, peer, peer_len); + if (status != PSA_SUCCESS) { + return status; + } + + status = psa_pake_set_password_key(&ssl->handshake->psa_pake_ctx, pwd); + if (status != PSA_SUCCESS) { + return status; + } + + ssl->handshake->psa_pake_ctx_is_ok = 1; + + return PSA_SUCCESS; +} + +int mbedtls_ssl_set_hs_ecjpake_password(mbedtls_ssl_context *ssl, + const unsigned char *pw, + size_t pw_len) +{ + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_status_t status; + + if (ssl->handshake == NULL || ssl->conf == NULL) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + /* Empty password is not valid */ + if ((pw == NULL) || (pw_len == 0)) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE); + psa_set_key_algorithm(&attributes, PSA_ALG_JPAKE); + psa_set_key_type(&attributes, PSA_KEY_TYPE_PASSWORD); + + status = psa_import_key(&attributes, pw, pw_len, + &ssl->handshake->psa_pake_password); + if (status != PSA_SUCCESS) { + return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + } + + status = mbedtls_ssl_set_hs_ecjpake_password_common(ssl, + ssl->handshake->psa_pake_password); + if (status != PSA_SUCCESS) { + psa_destroy_key(ssl->handshake->psa_pake_password); + psa_pake_abort(&ssl->handshake->psa_pake_ctx); + return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + } + + return 0; +} + +int mbedtls_ssl_set_hs_ecjpake_password_opaque(mbedtls_ssl_context *ssl, + mbedtls_svc_key_id_t pwd) +{ + psa_status_t status; + + if (ssl->handshake == NULL || ssl->conf == NULL) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + if (mbedtls_svc_key_id_is_null(pwd)) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + status = mbedtls_ssl_set_hs_ecjpake_password_common(ssl, pwd); + if (status != PSA_SUCCESS) { + psa_pake_abort(&ssl->handshake->psa_pake_ctx); + return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + } + + return 0; +} +#else /* MBEDTLS_USE_PSA_CRYPTO */ +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; + } + + /* Empty password is not valid */ + if ((pw == NULL) || (pw_len == 0)) { + 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_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED) +int mbedtls_ssl_conf_has_static_psk(mbedtls_ssl_config const *conf) +{ + if (conf->psk_identity == NULL || + conf->psk_identity_len == 0) { + return 0; + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if (!mbedtls_svc_key_id_is_null(conf->psk_opaque)) { + return 1; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + if (conf->psk != NULL && conf->psk_len != 0) { + return 1; + } + + return 0; +} + +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; + } +#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 == 0 || + (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; + + /* We currently only support one PSK, raw or opaque. */ + if (mbedtls_ssl_conf_has_static_psk(conf)) { + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + } + + /* 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)) { + /* The maintenance of the external PSK key slot is the + * user's responsibility. */ + if (ssl->handshake->psk_opaque_is_internal) { + psa_destroy_key(ssl->handshake->psk_opaque); + ssl->handshake->psk_opaque_is_internal = 0; + } + ssl->handshake->psk_opaque = MBEDTLS_SVC_KEY_ID_INIT; + } +#else + 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; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +} + +int mbedtls_ssl_set_hs_psk(mbedtls_ssl_context *ssl, + const unsigned char *psk, size_t psk_len) +{ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_key_attributes_t key_attributes = psa_key_attributes_init(); + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_algorithm_t alg = PSA_ALG_NONE; + mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + 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 defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2) { + if (ssl->handshake->ciphersuite_info->mac == 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); + } + psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { + alg = PSA_ALG_HKDF_EXTRACT(PSA_ALG_ANY_HASH); + psa_set_key_usage_flags(&key_attributes, + PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + + psa_set_key_algorithm(&key_attributes, alg); + psa_set_key_type(&key_attributes, PSA_KEY_TYPE_DERIVE); + + status = psa_import_key(&key_attributes, psk, psk_len, &key); + if (status != PSA_SUCCESS) { + return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + } + + /* Allow calling psa_destroy_key() on psk remove */ + ssl->handshake->psk_opaque_is_internal = 1; + return mbedtls_ssl_set_hs_psk_opaque(ssl, key); +#else + 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; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +} + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +int mbedtls_ssl_conf_psk_opaque(mbedtls_ssl_config *conf, + mbedtls_svc_key_id_t psk, + const unsigned char *psk_identity, + size_t psk_identity_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* We currently only support one PSK, raw or opaque. */ + if (mbedtls_ssl_conf_has_static_psk(conf)) { + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + } + + /* 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, + mbedtls_svc_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 */ + +#if defined(MBEDTLS_SSL_SRV_C) +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_SSL_SRV_C */ + +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +static mbedtls_ssl_mode_t mbedtls_ssl_get_base_mode( + psa_algorithm_t alg) +{ +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) + if (alg == PSA_ALG_CBC_NO_PADDING) { + return MBEDTLS_SSL_MODE_CBC; + } +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ + if (PSA_ALG_IS_AEAD(alg)) { + return MBEDTLS_SSL_MODE_AEAD; + } + return MBEDTLS_SSL_MODE_STREAM; +} + +#else /* MBEDTLS_USE_PSA_CRYPTO */ + +static mbedtls_ssl_mode_t mbedtls_ssl_get_base_mode( + mbedtls_cipher_mode_t mode) +{ +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) + if (mode == MBEDTLS_MODE_CBC) { + return MBEDTLS_SSL_MODE_CBC; + } +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ + +#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) { + return MBEDTLS_SSL_MODE_AEAD; + } +#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C */ + + return MBEDTLS_SSL_MODE_STREAM; +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +static mbedtls_ssl_mode_t mbedtls_ssl_get_actual_mode( + mbedtls_ssl_mode_t base_mode, + int encrypt_then_mac) +{ +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) + if (encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED && + base_mode == MBEDTLS_SSL_MODE_CBC) { + return MBEDTLS_SSL_MODE_CBC_ETM; + } +#else + (void) encrypt_then_mac; +#endif + return base_mode; +} + +mbedtls_ssl_mode_t mbedtls_ssl_get_mode_from_transform( + const mbedtls_ssl_transform *transform) +{ + mbedtls_ssl_mode_t base_mode = mbedtls_ssl_get_base_mode( +#if defined(MBEDTLS_USE_PSA_CRYPTO) + transform->psa_alg +#else + mbedtls_cipher_get_cipher_mode(&transform->cipher_ctx_enc) +#endif + ); + + int encrypt_then_mac = 0; +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) + encrypt_then_mac = transform->encrypt_then_mac; +#endif + return mbedtls_ssl_get_actual_mode(base_mode, encrypt_then_mac); +} + +mbedtls_ssl_mode_t mbedtls_ssl_get_mode_from_ciphersuite( +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) + int encrypt_then_mac, +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */ + const mbedtls_ssl_ciphersuite_t *suite) +{ + mbedtls_ssl_mode_t base_mode = MBEDTLS_SSL_MODE_STREAM; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status; + psa_algorithm_t alg; + psa_key_type_t type; + size_t size; + status = mbedtls_ssl_cipher_to_psa(suite->cipher, 0, &alg, &type, &size); + if (status == PSA_SUCCESS) { + base_mode = mbedtls_ssl_get_base_mode(alg); + } +#else + const mbedtls_cipher_info_t *cipher = + mbedtls_cipher_info_from_type(suite->cipher); + if (cipher != NULL) { + base_mode = + mbedtls_ssl_get_base_mode( + mbedtls_cipher_info_get_mode(cipher)); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if !defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) + int encrypt_then_mac = 0; +#endif + return mbedtls_ssl_get_actual_mode(base_mode, encrypt_then_mac); +} + +#if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3) + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) +/* Serialization of TLS 1.3 sessions: + * + * struct { + * opaque hostname<0..2^16-1>; + * uint64 ticket_received; + * uint32 ticket_lifetime; + * opaque ticket<1..2^16-1>; + * } ClientOnlyData; + * + * struct { + * uint8 endpoint; + * uint8 ciphersuite[2]; + * uint32 ticket_age_add; + * uint8 ticket_flags; + * opaque resumption_key<0..255>; + * select ( endpoint ) { + * case client: ClientOnlyData; + * case server: uint64 start_time; + * }; + * } serialized_session_tls13; + * + */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_session_save(const mbedtls_ssl_session *session, + unsigned char *buf, + size_t buf_len, + size_t *olen) +{ + unsigned char *p = buf; +#if defined(MBEDTLS_SSL_CLI_C) && \ + defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + size_t hostname_len = (session->hostname == NULL) ? + 0 : strlen(session->hostname) + 1; +#endif + size_t needed = 1 /* endpoint */ + + 2 /* ciphersuite */ + + 4 /* ticket_age_add */ + + 1 /* ticket_flags */ + + 1; /* resumption_key length */ + *olen = 0; + + if (session->resumption_key_len > MBEDTLS_SSL_TLS1_3_TICKET_RESUMPTION_KEY_LEN) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + needed += session->resumption_key_len; /* resumption_key */ + +#if defined(MBEDTLS_HAVE_TIME) + needed += 8; /* start_time or ticket_received */ +#endif + +#if defined(MBEDTLS_SSL_CLI_C) + if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) { +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + needed += 2 /* hostname_len */ + + hostname_len; /* hostname */ +#endif + + needed += 4 /* ticket_lifetime */ + + 2; /* ticket_len */ + + /* Check size_t overflow */ + if (session->ticket_len > SIZE_MAX - needed) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + needed += session->ticket_len; /* ticket */ + } +#endif /* MBEDTLS_SSL_CLI_C */ + + *olen = needed; + if (needed > buf_len) { + return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; + } + + p[0] = session->endpoint; + MBEDTLS_PUT_UINT16_BE(session->ciphersuite, p, 1); + MBEDTLS_PUT_UINT32_BE(session->ticket_age_add, p, 3); + p[7] = session->ticket_flags; + + /* save resumption_key */ + p[8] = session->resumption_key_len; + p += 9; + memcpy(p, session->resumption_key, session->resumption_key_len); + p += session->resumption_key_len; + +#if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_SRV_C) + if (session->endpoint == MBEDTLS_SSL_IS_SERVER) { + MBEDTLS_PUT_UINT64_BE((uint64_t) session->start, p, 0); + p += 8; + } +#endif /* MBEDTLS_HAVE_TIME */ + +#if defined(MBEDTLS_SSL_CLI_C) + if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) { +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + MBEDTLS_PUT_UINT16_BE(hostname_len, p, 0); + p += 2; + if (hostname_len > 0) { + /* save host name */ + memcpy(p, session->hostname, hostname_len); + p += hostname_len; + } +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_HAVE_TIME) + MBEDTLS_PUT_UINT64_BE((uint64_t) session->ticket_received, p, 0); + p += 8; +#endif + MBEDTLS_PUT_UINT32_BE(session->ticket_lifetime, p, 0); + p += 4; + + MBEDTLS_PUT_UINT16_BE(session->ticket_len, p, 0); + p += 2; + + if (session->ticket != NULL && session->ticket_len > 0) { + memcpy(p, session->ticket, session->ticket_len); + p += session->ticket_len; + } + } +#endif /* MBEDTLS_SSL_CLI_C */ + return 0; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_session_load(mbedtls_ssl_session *session, + const unsigned char *buf, + size_t len) +{ + const unsigned char *p = buf; + const unsigned char *end = buf + len; + + if (end - p < 9) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + session->endpoint = p[0]; + session->ciphersuite = MBEDTLS_GET_UINT16_BE(p, 1); + session->ticket_age_add = MBEDTLS_GET_UINT32_BE(p, 3); + session->ticket_flags = p[7]; + + /* load resumption_key */ + session->resumption_key_len = p[8]; + p += 9; + + if (end - p < session->resumption_key_len) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + if (sizeof(session->resumption_key) < session->resumption_key_len) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + memcpy(session->resumption_key, p, session->resumption_key_len); + p += session->resumption_key_len; + +#if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_SRV_C) + if (session->endpoint == MBEDTLS_SSL_IS_SERVER) { + if (end - p < 8) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + session->start = MBEDTLS_GET_UINT64_BE(p, 0); + p += 8; + } +#endif /* MBEDTLS_HAVE_TIME */ + +#if defined(MBEDTLS_SSL_CLI_C) + if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) { +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && \ + defined(MBEDTLS_SSL_SESSION_TICKETS) + size_t hostname_len; + /* load host name */ + if (end - p < 2) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + hostname_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + + if (end - p < (long int) hostname_len) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + if (hostname_len > 0) { + session->hostname = mbedtls_calloc(1, hostname_len); + if (session->hostname == NULL) { + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } + memcpy(session->hostname, p, hostname_len); + p += hostname_len; + } +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION && + MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_HAVE_TIME) + if (end - p < 8) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + session->ticket_received = MBEDTLS_GET_UINT64_BE(p, 0); + p += 8; +#endif + if (end - p < 4) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + session->ticket_lifetime = MBEDTLS_GET_UINT32_BE(p, 0); + p += 4; + + if (end - p < 2) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + session->ticket_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + + if (end - p < (long int) session->ticket_len) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + if (session->ticket_len > 0) { + 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; + } + } +#endif /* MBEDTLS_SSL_CLI_C */ + + return 0; + +} +#else /* MBEDTLS_SSL_SESSION_TICKETS */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_session_save(const mbedtls_ssl_session *session, + unsigned char *buf, + size_t buf_len, + size_t *olen) +{ + ((void) session); + ((void) buf); + ((void) buf_len); + *olen = 0; + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; +} + +static int ssl_tls13_session_load(const mbedtls_ssl_session *session, + unsigned char *buf, + size_t buf_len) +{ + ((void) session); + ((void) buf); + ((void) buf_len); + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; +} +#endif /* !MBEDTLS_SSL_SESSION_TICKETS */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + +psa_status_t mbedtls_ssl_cipher_to_psa(mbedtls_cipher_type_t mbedtls_cipher_type, + size_t taglen, + psa_algorithm_t *alg, + psa_key_type_t *key_type, + size_t *key_size) +{ + switch (mbedtls_cipher_type) { + case MBEDTLS_CIPHER_AES_128_CBC: + *alg = PSA_ALG_CBC_NO_PADDING; + *key_type = PSA_KEY_TYPE_AES; + *key_size = 128; + break; + case MBEDTLS_CIPHER_AES_128_CCM: + *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM; + *key_type = PSA_KEY_TYPE_AES; + *key_size = 128; + break; + case MBEDTLS_CIPHER_AES_128_GCM: + *alg = PSA_ALG_GCM; + *key_type = PSA_KEY_TYPE_AES; + *key_size = 128; + break; + case MBEDTLS_CIPHER_AES_192_CCM: + *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM; + *key_type = PSA_KEY_TYPE_AES; + *key_size = 192; + break; + case MBEDTLS_CIPHER_AES_192_GCM: + *alg = PSA_ALG_GCM; + *key_type = PSA_KEY_TYPE_AES; + *key_size = 192; + break; + case MBEDTLS_CIPHER_AES_256_CBC: + *alg = PSA_ALG_CBC_NO_PADDING; + *key_type = PSA_KEY_TYPE_AES; + *key_size = 256; + break; + case MBEDTLS_CIPHER_AES_256_CCM: + *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM; + *key_type = PSA_KEY_TYPE_AES; + *key_size = 256; + break; + case MBEDTLS_CIPHER_AES_256_GCM: + *alg = PSA_ALG_GCM; + *key_type = PSA_KEY_TYPE_AES; + *key_size = 256; + break; + case MBEDTLS_CIPHER_ARIA_128_CBC: + *alg = PSA_ALG_CBC_NO_PADDING; + *key_type = PSA_KEY_TYPE_ARIA; + *key_size = 128; + break; + case MBEDTLS_CIPHER_ARIA_128_CCM: + *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM; + *key_type = PSA_KEY_TYPE_ARIA; + *key_size = 128; + break; + case MBEDTLS_CIPHER_ARIA_128_GCM: + *alg = PSA_ALG_GCM; + *key_type = PSA_KEY_TYPE_ARIA; + *key_size = 128; + break; + case MBEDTLS_CIPHER_ARIA_192_CCM: + *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM; + *key_type = PSA_KEY_TYPE_ARIA; + *key_size = 192; + break; + case MBEDTLS_CIPHER_ARIA_192_GCM: + *alg = PSA_ALG_GCM; + *key_type = PSA_KEY_TYPE_ARIA; + *key_size = 192; + break; + case MBEDTLS_CIPHER_ARIA_256_CBC: + *alg = PSA_ALG_CBC_NO_PADDING; + *key_type = PSA_KEY_TYPE_ARIA; + *key_size = 256; + break; + case MBEDTLS_CIPHER_ARIA_256_CCM: + *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM; + *key_type = PSA_KEY_TYPE_ARIA; + *key_size = 256; + break; + case MBEDTLS_CIPHER_ARIA_256_GCM: + *alg = PSA_ALG_GCM; + *key_type = PSA_KEY_TYPE_ARIA; + *key_size = 256; + break; + case MBEDTLS_CIPHER_CAMELLIA_128_CBC: + *alg = PSA_ALG_CBC_NO_PADDING; + *key_type = PSA_KEY_TYPE_CAMELLIA; + *key_size = 128; + break; + case MBEDTLS_CIPHER_CAMELLIA_128_CCM: + *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM; + *key_type = PSA_KEY_TYPE_CAMELLIA; + *key_size = 128; + break; + case MBEDTLS_CIPHER_CAMELLIA_128_GCM: + *alg = PSA_ALG_GCM; + *key_type = PSA_KEY_TYPE_CAMELLIA; + *key_size = 128; + break; + case MBEDTLS_CIPHER_CAMELLIA_192_CCM: + *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM; + *key_type = PSA_KEY_TYPE_CAMELLIA; + *key_size = 192; + break; + case MBEDTLS_CIPHER_CAMELLIA_192_GCM: + *alg = PSA_ALG_GCM; + *key_type = PSA_KEY_TYPE_CAMELLIA; + *key_size = 192; + break; + case MBEDTLS_CIPHER_CAMELLIA_256_CBC: + *alg = PSA_ALG_CBC_NO_PADDING; + *key_type = PSA_KEY_TYPE_CAMELLIA; + *key_size = 256; + break; + case MBEDTLS_CIPHER_CAMELLIA_256_CCM: + *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM; + *key_type = PSA_KEY_TYPE_CAMELLIA; + *key_size = 256; + break; + case MBEDTLS_CIPHER_CAMELLIA_256_GCM: + *alg = PSA_ALG_GCM; + *key_type = PSA_KEY_TYPE_CAMELLIA; + *key_size = 256; + break; + case MBEDTLS_CIPHER_CHACHA20_POLY1305: + *alg = PSA_ALG_CHACHA20_POLY1305; + *key_type = PSA_KEY_TYPE_CHACHA20; + *key_size = 256; + break; + case MBEDTLS_CIPHER_NULL: + *alg = MBEDTLS_SSL_NULL_CIPHER; + *key_type = 0; + *key_size = 0; + break; + default: + return PSA_ERROR_NOT_SUPPORTED; + } + + return PSA_SUCCESS; +} +#endif /* MBEDTLS_USE_PSA_CRYPTO || MBEDTLS_SSL_PROTO_TLS1_3 */ + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) +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_dhm_get_value(dhm_ctx, MBEDTLS_DHM_PARAM_P, + &conf->dhm_P)) != 0 || + (ret = mbedtls_dhm_get_value(dhm_ctx, MBEDTLS_DHM_PARAM_G, + &conf->dhm_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_SSL_HANDSHAKE_WITH_CERT_ENABLED) +#if !defined(MBEDTLS_DEPRECATED_REMOVED) && defined(MBEDTLS_SSL_PROTO_TLS1_2) +/* + * 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_DEPRECATED_REMOVED && MBEDTLS_SSL_PROTO_TLS1_2 */ + +/* Configure allowed signature algorithms for handshake */ +void mbedtls_ssl_conf_sig_algs(mbedtls_ssl_config *conf, + const uint16_t *sig_algs) +{ +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + conf->sig_hashes = NULL; +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + conf->sig_algs = sig_algs; +} +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ + +#if defined(MBEDTLS_ECP_C) +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +/* + * Set the allowed elliptic curves + * + * mbedtls_ssl_setup() takes the provided list + * and translates it to a list of IANA TLS group identifiers, + * stored in ssl->handshake->group_list. + * + */ +void mbedtls_ssl_conf_curves(mbedtls_ssl_config *conf, + const mbedtls_ecp_group_id *curve_list) +{ + conf->curve_list = curve_list; + conf->group_list = NULL; +} +#endif /* MBEDTLS_DEPRECATED_REMOVED */ +#endif /* MBEDTLS_ECP_C */ + +/* + * Set the allowed groups + */ +void mbedtls_ssl_conf_groups(mbedtls_ssl_config *conf, + const uint16_t *group_list) +{ +#if defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_DEPRECATED_REMOVED) + conf->curve_list = NULL; +#endif + conf->group_list = group_list; +} + +#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 */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ssl_conf_max_version(mbedtls_ssl_config *conf, int major, int minor) +{ + conf->max_tls_version = (major << 8) | minor; +} + +void mbedtls_ssl_conf_min_version(mbedtls_ssl_config *conf, int major, int minor) +{ + conf->min_tls_version = (major << 8) | minor; +} +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +#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_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 */ + +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) + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) +void mbedtls_ssl_conf_new_session_tickets(mbedtls_ssl_config *conf, + uint16_t num_tickets) +{ + conf->new_session_tickets_count = num_tickets; +} +#endif + +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 */ + +void mbedtls_ssl_set_export_keys_cb(mbedtls_ssl_context *ssl, + mbedtls_ssl_export_keys_t *f_export_keys, + void *p_export_keys) +{ + ssl->f_export_keys = f_export_keys; + ssl->p_export_keys = p_export_keys; +} + +#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; +} + +int mbedtls_ssl_get_ciphersuite_id_from_ssl(const mbedtls_ssl_context *ssl) +{ + if (ssl == NULL || ssl->session == NULL) { + return 0; + } + + return ssl->session->ciphersuite; +} + +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->tls_version) { + case MBEDTLS_SSL_VERSION_TLS1_2: + return "DTLSv1.2"; + default: + return "unknown (DTLS)"; + } + } +#endif + + switch (ssl->tls_version) { + case MBEDTLS_SSL_VERSION_TLS1_2: + return "TLSv1.2"; + case MBEDTLS_SSL_VERSION_TLS1_3: + return "TLSv1.3"; + 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_IN_CONTENT_LEN; + size_t read_mfl; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* 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); + } +#endif + + /* 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; +} +#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; +} + +int mbedtls_ssl_get_max_in_record_payload(const mbedtls_ssl_context *ssl) +{ + size_t max_len = MBEDTLS_SSL_IN_CONTENT_LEN; + +#if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + (void) ssl; +#endif + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + const size_t mfl = mbedtls_ssl_get_input_max_frag_len(ssl); + + if (max_len > mfl) { + max_len = mfl; + } +#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) +{ + int ret; + + if (ssl == NULL || + dst == NULL || + ssl->session == NULL || + ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + /* Since Mbed TLS 3.0, mbedtls_ssl_get_session() is no longer + * idempotent: Each session can only be exported once. + * + * (This is in preparation for TLS 1.3 support where we will + * need the ability to export multiple sessions (aka tickets), + * which will be achieved by calling mbedtls_ssl_get_session() + * multiple times until it fails.) + * + * Check whether we have already exported the current session, + * and fail if so. + */ + if (ssl->session->exported == 1) { + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + } + + ret = mbedtls_ssl_session_copy(dst, ssl->session); + if (ret != 0) { + return ret; + } + + /* Remember that we've exported the session. */ + ssl->session->exported = 1; + return 0; +} +#endif /* MBEDTLS_SSL_CLI_C */ + +/* + * 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_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_ETM_BIT 4 +#define SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT 5 + +#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_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) + * + * struct { + * + * opaque mbedtls_version[3]; // library version: major, minor, patch + * opaque session_format[2]; // library-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. + * + * uint8_t minor_ver; // Protocol minor version. Possible values: + * // - TLS 1.2 (0x0303) + * // - TLS 1.3 (0x0304) + * + * select (serialized_session.tls_version) { + * + * case MBEDTLS_SSL_VERSION_TLS1_2: + * serialized_session_tls12 data; + * case MBEDTLS_SSL_VERSION_TLS1_3: + * serialized_session_tls13 data; + * + * }; + * + * } serialized_session; + * + */ + +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; + size_t remaining_len; +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + size_t out_len; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; +#endif + if (session == NULL) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + if (!omit_header) { + /* + * Add Mbed TLS 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); + } + } + + /* + * TLS version identifier + */ + used += 1; + if (used <= buf_len) { + *p++ = MBEDTLS_BYTE_0(session->tls_version); + } + + /* Forward to version-specific serialization routine. */ + remaining_len = (buf_len >= used) ? buf_len - used : 0; + switch (session->tls_version) { +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + case MBEDTLS_SSL_VERSION_TLS1_2: + used += ssl_tls12_session_save(session, p, remaining_len); + break; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + case MBEDTLS_SSL_VERSION_TLS1_3: + ret = ssl_tls13_session_save(session, p, remaining_len, &out_len); + if (ret != 0 && ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL) { + return ret; + } + used += out_len; + break; +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + + default: + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + } + + *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; + size_t remaining_len; + + + if (session == NULL) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + if (!omit_header) { + /* + * Check Mbed TLS 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); + } + + /* + * TLS version identifier + */ + if (1 > (size_t) (end - p)) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + session->tls_version = 0x0300 | *p++; + + /* Dispatch according to TLS version. */ + remaining_len = (end - p); + switch (session->tls_version) { +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + case MBEDTLS_SSL_VERSION_TLS1_2: + return ssl_tls12_session_load(session, p, remaining_len); +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + case MBEDTLS_SSL_VERSION_TLS1_3: + return ssl_tls13_session_load(session, p, remaining_len); +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + + default: + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } +} + +/* + * 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 + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_prepare_handshake_step(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* + * We may have not been able to send to the peer all the handshake data + * that were written into the output buffer by the previous handshake step, + * if the write to the network callback returned with the + * #MBEDTLS_ERR_SSL_WANT_WRITE error code. + * We proceed to the next handshake step only when all data from the + * previous one have been sent to the peer, thus we make sure that this is + * the case here by calling `mbedtls_ssl_flush_output()`. The function may + * return with the #MBEDTLS_ERR_SSL_WANT_WRITE error code in which case + * we have to wait before to go ahead. + * In the case of TLS 1.3, handshake step handlers do not send data to the + * peer. Data are only sent here and through + * `mbedtls_ssl_handle_pending_alert` in case an error that triggered an + * alert occurred. + */ + 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 */ + + return ret; +} + +int mbedtls_ssl_handshake_step(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if (ssl == NULL || + ssl->conf == NULL || + ssl->handshake == NULL || + ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + ret = ssl_prepare_handshake_step(ssl); + if (ret != 0) { + return ret; + } + + ret = mbedtls_ssl_handle_pending_alert(ssl); + if (ret != 0) { + goto cleanup; + } + + /* If ssl->conf->endpoint is not one of MBEDTLS_SSL_IS_CLIENT or + * MBEDTLS_SSL_IS_SERVER, this is the return code we give */ + ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + +#if defined(MBEDTLS_SSL_CLI_C) + if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { + MBEDTLS_SSL_DEBUG_MSG(2, ("client state: %s", + mbedtls_ssl_states_str(ssl->state))); + + switch (ssl->state) { + case MBEDTLS_SSL_HELLO_REQUEST: + ssl->state = MBEDTLS_SSL_CLIENT_HELLO; + ret = 0; + break; + + case MBEDTLS_SSL_CLIENT_HELLO: + ret = mbedtls_ssl_write_client_hello(ssl); + break; + + default: +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_TLS1_3) + if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { + ret = mbedtls_ssl_tls13_handshake_client_step(ssl); + } else { + ret = mbedtls_ssl_handshake_client_step(ssl); + } +#elif defined(MBEDTLS_SSL_PROTO_TLS1_2) + ret = mbedtls_ssl_handshake_client_step(ssl); +#else + ret = mbedtls_ssl_tls13_handshake_client_step(ssl); +#endif + } + } +#endif +#if defined(MBEDTLS_SSL_SRV_C) + if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + if (mbedtls_ssl_conf_is_tls13_only(ssl->conf)) { + ret = mbedtls_ssl_tls13_handshake_server_step(ssl); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if (mbedtls_ssl_conf_is_tls12_only(ssl->conf)) { + ret = mbedtls_ssl_handshake_server_step(ssl); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + } +#endif + + if (ret != 0) { + /* handshake_step return error. And it is same + * with alert_reason. + */ + if (ssl->send_alert) { + ret = mbedtls_ssl_handle_pending_alert(ssl); + goto cleanup; + } + } + +cleanup: + 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 (mbedtls_ssl_is_handshake_over(ssl) == 0) { + 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 (mbedtls_ssl_is_handshake_over(ssl) == 0) { + 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 */ + +void mbedtls_ssl_handshake_free(mbedtls_ssl_context *ssl) +{ + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + if (handshake == NULL) { + return; + } + +#if defined(MBEDTLS_ECP_C) +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + if (ssl->handshake->group_list_heap_allocated) { + mbedtls_free((void *) handshake->group_list); + } + handshake->group_list = NULL; +#endif /* MBEDTLS_DEPRECATED_REMOVED */ +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + if (ssl->handshake->sig_algs_heap_allocated) { + mbedtls_free((void *) handshake->sig_algs); + } + handshake->sig_algs = NULL; +#endif /* MBEDTLS_DEPRECATED_REMOVED */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + if (ssl->handshake->certificate_request_context) { + mbedtls_free((void *) handshake->certificate_request_context); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ + +#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_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_abort(&handshake->fin_sha256_psa); +#else + mbedtls_md_free(&handshake->fin_sha256); +#endif +#endif +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_abort(&handshake->fin_sha384_psa); +#else + mbedtls_md_free(&handshake->fin_sha384); +#endif +#endif + +#if defined(MBEDTLS_DHM_C) + mbedtls_dhm_free(&handshake->dhm_ctx); +#endif +#if !defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_ECDH_C) + mbedtls_ecdh_free(&handshake->ecdh_ctx); +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_pake_abort(&handshake->psa_pake_ctx); + /* + * Opaque keys are not stored in the handshake's data and it's the user + * responsibility to destroy them. Clear ones, instead, are created by + * the TLS library and should be destroyed at the same level + */ + if (!mbedtls_svc_key_id_is_null(handshake->psa_pake_password)) { + psa_destroy_key(handshake->psa_pake_password); + } + handshake->psa_pake_password = MBEDTLS_SVC_KEY_ID_INIT; +#else + mbedtls_ecjpake_free(&handshake->ecjpake_ctx); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#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_tls_id); +#endif + +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if (!mbedtls_svc_key_id_is_null(ssl->handshake->psk_opaque)) { + /* The maintenance of the external PSK key slot is the + * user's responsibility. */ + if (ssl->handshake->psk_opaque_is_internal) { + psa_destroy_key(ssl->handshake->psk_opaque); + ssl->handshake->psk_opaque_is_internal = 0; + } + ssl->handshake->psk_opaque = MBEDTLS_SVC_KEY_ID_INIT; + } +#else + if (handshake->psk != NULL) { + mbedtls_platform_zeroize(handshake->psk, handshake->psk_len); + mbedtls_free(handshake->psk); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */ + +#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 + */ + ssl_key_cert_free(handshake->sni_key_cert); +#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_CLI_C) && \ + (defined(MBEDTLS_SSL_PROTO_DTLS) || defined(MBEDTLS_SSL_PROTO_TLS1_3)) + mbedtls_free(handshake->cookie); +#endif /* MBEDTLS_SSL_CLI_C && + ( MBEDTLS_SSL_PROTO_DTLS || MBEDTLS_SSL_PROTO_TLS1_3 ) */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + mbedtls_ssl_flight_free(handshake->flight); + mbedtls_ssl_buffering_free(ssl); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_ECDH_C) && \ + (defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3)) + if (handshake->ecdh_psa_privkey_is_external == 0) { + psa_destroy_key(handshake->ecdh_psa_privkey); + } +#endif /* MBEDTLS_ECDH_C && MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + mbedtls_ssl_transform_free(handshake->transform_handshake); + mbedtls_free(handshake->transform_handshake); +#if defined(MBEDTLS_SSL_EARLY_DATA) + mbedtls_ssl_transform_free(handshake->transform_earlydata); + mbedtls_free(handshake->transform_earlydata); +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + + +#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 + + /* mbedtls_platform_zeroize MUST be last one in this function */ + mbedtls_platform_zeroize(handshake, + sizeof(mbedtls_ssl_handshake_params)); +} + +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) +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ + defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + mbedtls_free(session->hostname); +#endif + 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 */ + +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT 1u + +#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 (mbedtls_ssl_is_handshake_over(ssl) == 0) { + 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 DTLS, 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->tls_version != MBEDTLS_SSL_VERSION_TLS1_2) { + 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 + */ + used += 4; + if (used <= buf_len) { + MBEDTLS_PUT_UINT32_BE(ssl->badmac_seen, p, 0); + p += 4; + } + +#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 += MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; + if (used <= buf_len) { + memcpy(p, ssl->cur_out_ctr, MBEDTLS_SSL_SEQUENCE_NUMBER_LEN); + p += MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; + } + +#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); +} + +/* + * 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; +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + tls_prf_fn prf_func = NULL; +#endif + + /* + * 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_tls_version < MBEDTLS_SSL_VERSION_TLS1_2 || + ssl->conf->min_tls_version > MBEDTLS_SSL_VERSION_TLS1_2 || +#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(). */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + ssl->transform = ssl->transform_negotiate; + ssl->transform_in = ssl->transform; + ssl->transform_out = ssl->transform; + ssl->transform_negotiate = NULL; +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + prf_func = ssl_tls12prf_from_cs(ssl->session->ciphersuite); + if (prf_func == NULL) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + /* Read random bytes and populate structure */ + if ((size_t) (end - p) < sizeof(ssl->transform->randbytes)) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + ret = ssl_tls12_populate_transform(ssl->transform, + ssl->session->ciphersuite, + ssl->session->master, +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) + ssl->session->encrypt_then_mac, +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */ + prf_func, + p, /* currently pointing to randbytes */ + MBEDTLS_SSL_VERSION_TLS1_2, /* (D)TLS 1.2 is forced */ + ssl->conf->endpoint, + ssl); + if (ret != 0) { + return ret; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + 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 ((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; + +#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) < sizeof(ssl->cur_out_ctr)) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + memcpy(ssl->cur_out_ctr, p, sizeof(ssl->cur_out_ctr)); + p += sizeof(ssl->cur_out_ctr); + +#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->tls_version = MBEDTLS_SSL_VERSION_TLS1_2; + + /* 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 (ssl->transform) { + mbedtls_ssl_transform_free(ssl->transform); + mbedtls_free(ssl->transform); + } + + if (ssl->handshake) { + mbedtls_ssl_handshake_free(ssl); + mbedtls_free(ssl->handshake); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + mbedtls_ssl_transform_free(ssl->transform_negotiate); + mbedtls_free(ssl->transform_negotiate); +#endif + + mbedtls_ssl_session_free(ssl->session_negotiate); + mbedtls_free(ssl->session_negotiate); + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + mbedtls_ssl_transform_free(ssl->transform_application); + mbedtls_free(ssl->transform_application); +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + + 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_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)); +} + +/* + * Initialize mbedtls_ssl_config + */ +void mbedtls_ssl_config_init(mbedtls_ssl_config *conf) +{ + memset(conf, 0, sizeof(mbedtls_ssl_config)); +} + +/* The selection should be the same as mbedtls_x509_crt_profile_default in + * x509_crt.c, plus Montgomery curves for ECDHE. Here, the order matters: + * curves with a lower resource usage come first. + * See the documentation of mbedtls_ssl_conf_curves() for what we promise + * about this list. + */ +static uint16_t ssl_preset_default_groups[] = { +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + MBEDTLS_SSL_IANA_TLS_GROUP_X25519, +#endif +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1, +#endif +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1, +#endif +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) + MBEDTLS_SSL_IANA_TLS_GROUP_X448, +#endif +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + MBEDTLS_SSL_IANA_TLS_GROUP_SECP521R1, +#endif +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + MBEDTLS_SSL_IANA_TLS_GROUP_BP256R1, +#endif +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + MBEDTLS_SSL_IANA_TLS_GROUP_BP384R1, +#endif +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + MBEDTLS_SSL_IANA_TLS_GROUP_BP512R1, +#endif + MBEDTLS_SSL_IANA_TLS_GROUP_NONE +}; + +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_SSL_HANDSHAKE_WITH_CERT_ENABLED) + +/* NOTICE: + * For ssl_preset_*_sig_algs and ssl_tls12_preset_*_sig_algs, the following + * rules SHOULD be upheld. + * - No duplicate entries. + * - But if there is a good reason, do not change the order of the algorithms. + * - ssl_tls12_preset* is for TLS 1.2 use only. + * - ssl_preset_* is for TLS 1.3 only or hybrid TLS 1.3/1.2 handshakes. + */ +static uint16_t ssl_preset_default_sig_algs[] = { + +#if defined(MBEDTLS_PK_CAN_ECDSA_SOME) && \ + defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \ + defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256, +#endif /* MBEDTLS_PK_CAN_ECDSA_SOME && MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA && + MBEDTLS_ECP_DP_SECP256R1_ENABLED */ + +#if defined(MBEDTLS_PK_CAN_ECDSA_SOME) && \ + defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \ + defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384, +#endif /* MBEDTLS_PK_CAN_ECDSA_SOME && MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA&& + MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +#if defined(MBEDTLS_PK_CAN_ECDSA_SOME) && \ + defined(MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \ + defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512, +#endif /* MBEDTLS_PK_CAN_ECDSA_SOME && MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA&& + MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \ + defined(MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512, +#endif \ + /* MBEDTLS_X509_RSASSA_PSS_SUPPORT && MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \ + defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384, +#endif \ + /* MBEDTLS_X509_RSASSA_PSS_SUPPORT && MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \ + defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256, +#endif \ + /* MBEDTLS_X509_RSASSA_PSS_SUPPORT && MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ + +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512, +#endif /* MBEDTLS_RSA_C && MBEDTLS_SHA512_C */ + +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384, +#endif /* MBEDTLS_RSA_C && MBEDTLS_SHA384_C */ + +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256, +#endif /* MBEDTLS_RSA_C && MBEDTLS_SHA256_C */ + + MBEDTLS_TLS_SIG_NONE +}; + +/* NOTICE: see above */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +static uint16_t ssl_tls12_preset_default_sig_algs[] = { +#if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +#if defined(MBEDTLS_PK_CAN_ECDSA_SOME) + MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA512), +#endif +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512, +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ +#if defined(MBEDTLS_RSA_C) + MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, MBEDTLS_SSL_HASH_SHA512), +#endif +#endif /* MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/ +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +#if defined(MBEDTLS_PK_CAN_ECDSA_SOME) + MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA384), +#endif +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384, +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ +#if defined(MBEDTLS_RSA_C) + MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, MBEDTLS_SSL_HASH_SHA384), +#endif +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/ +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +#if defined(MBEDTLS_PK_CAN_ECDSA_SOME) + MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA256), +#endif +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256, +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ +#if defined(MBEDTLS_RSA_C) + MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, MBEDTLS_SSL_HASH_SHA256), +#endif +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/ + MBEDTLS_TLS_SIG_NONE +}; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +/* NOTICE: see above */ +static uint16_t ssl_preset_suiteb_sig_algs[] = { + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \ + defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256, +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA&& + MBEDTLS_ECP_DP_SECP256R1_ENABLED */ + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \ + defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384, +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA&& + MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \ + defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256, +#endif \ + /* MBEDTLS_X509_RSASSA_PSS_SUPPORT && MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/ + +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256, +#endif /* MBEDTLS_RSA_C && MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/ + + MBEDTLS_TLS_SIG_NONE +}; + +/* NOTICE: see above */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +static uint16_t ssl_tls12_preset_suiteb_sig_algs[] = { +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +#if defined(MBEDTLS_ECDSA_C) + MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA256), +#endif +#if defined(MBEDTLS_RSA_C) + MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, MBEDTLS_SSL_HASH_SHA256), +#endif +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/ +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +#if defined(MBEDTLS_ECDSA_C) + MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA384), +#endif +#if defined(MBEDTLS_RSA_C) + MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, MBEDTLS_SSL_HASH_SHA384), +#endif +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/ + MBEDTLS_TLS_SIG_NONE +}; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ + +static uint16_t ssl_preset_suiteb_groups[] = { +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1, +#endif +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1, +#endif + MBEDTLS_SSL_IANA_TLS_GROUP_NONE +}; + +#if defined(MBEDTLS_DEBUG_C) && defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) +/* Function for checking `ssl_preset_*_sig_algs` and `ssl_tls12_preset_*_sig_algs` + * to make sure there are no duplicated signature algorithm entries. */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_check_no_sig_alg_duplication(uint16_t *sig_algs) +{ + size_t i, j; + int ret = 0; + + for (i = 0; sig_algs[i] != MBEDTLS_TLS_SIG_NONE; i++) { + for (j = 0; j < i; j++) { + if (sig_algs[i] != sig_algs[j]) { + continue; + } + mbedtls_printf(" entry(%04x,%" MBEDTLS_PRINTF_SIZET + ") is duplicated at %" MBEDTLS_PRINTF_SIZET "\n", + sig_algs[i], j, i); + ret = -1; + } + } + return ret; +} + +#endif /* MBEDTLS_DEBUG_C && MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ + +/* + * 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 + +#if defined(MBEDTLS_DEBUG_C) && defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) + if (ssl_check_no_sig_alg_duplication(ssl_preset_suiteb_sig_algs)) { + mbedtls_printf("ssl_preset_suiteb_sig_algs has duplicated entries\n"); + return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + } + + if (ssl_check_no_sig_alg_duplication(ssl_preset_default_sig_algs)) { + mbedtls_printf("ssl_preset_default_sig_algs has duplicated entries\n"); + return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if (ssl_check_no_sig_alg_duplication(ssl_tls12_preset_suiteb_sig_algs)) { + mbedtls_printf("ssl_tls12_preset_suiteb_sig_algs has duplicated entries\n"); + return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + } + + if (ssl_check_no_sig_alg_duplication(ssl_tls12_preset_default_sig_algs)) { + mbedtls_printf("ssl_tls12_preset_default_sig_algs has duplicated entries\n"); + return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +#endif /* MBEDTLS_DEBUG_C && MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ + + /* 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_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_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; + conf->respect_cli_pref = MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_SERVER; +#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 + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + +#if defined(MBEDTLS_SSL_EARLY_DATA) + mbedtls_ssl_tls13_conf_early_data(conf, MBEDTLS_SSL_EARLY_DATA_DISABLED); +#if defined(MBEDTLS_SSL_SRV_C) + mbedtls_ssl_tls13_conf_max_early_data_size( + conf, MBEDTLS_SSL_MAX_EARLY_DATA_SIZE); +#endif +#endif /* MBEDTLS_SSL_EARLY_DATA */ + +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SESSION_TICKETS) + mbedtls_ssl_conf_new_session_tickets( + conf, MBEDTLS_SSL_TLS1_3_DEFAULT_NEW_SESSION_TICKETS); +#endif + /* + * Allow all TLS 1.3 key exchange modes by default. + */ + conf->tls13_kex_modes = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_ALL; +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + + if (transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + conf->min_tls_version = MBEDTLS_SSL_VERSION_TLS1_2; + conf->max_tls_version = MBEDTLS_SSL_VERSION_TLS1_2; +#else + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; +#endif + } else { +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_TLS1_3) + if (endpoint == MBEDTLS_SSL_IS_CLIENT) { + conf->min_tls_version = MBEDTLS_SSL_VERSION_TLS1_2; + conf->max_tls_version = MBEDTLS_SSL_VERSION_TLS1_3; + } else { + /* Hybrid TLS 1.2 / 1.3 is not supported on server side yet */ + conf->min_tls_version = MBEDTLS_SSL_VERSION_TLS1_2; + conf->max_tls_version = MBEDTLS_SSL_VERSION_TLS1_2; + } +#elif defined(MBEDTLS_SSL_PROTO_TLS1_3) + conf->min_tls_version = MBEDTLS_SSL_VERSION_TLS1_3; + conf->max_tls_version = MBEDTLS_SSL_VERSION_TLS1_3; +#elif defined(MBEDTLS_SSL_PROTO_TLS1_2) + conf->min_tls_version = MBEDTLS_SSL_VERSION_TLS1_2; + conf->max_tls_version = MBEDTLS_SSL_VERSION_TLS1_2; +#else + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; +#endif + } + + /* + * Preset-specific defaults + */ + switch (preset) { + /* + * NSA Suite B + */ + case MBEDTLS_SSL_PRESET_SUITEB: + + conf->ciphersuite_list = ssl_preset_suiteb_ciphersuites; + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + conf->cert_profile = &mbedtls_x509_crt_profile_suiteb; +#endif + +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if (mbedtls_ssl_conf_is_tls12_only(conf)) { + conf->sig_algs = ssl_tls12_preset_suiteb_sig_algs; + } else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + conf->sig_algs = ssl_preset_suiteb_sig_algs; +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ + +#if defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_DEPRECATED_REMOVED) + conf->curve_list = NULL; +#endif + conf->group_list = ssl_preset_suiteb_groups; + break; + + /* + * Default + */ + default: + + conf->ciphersuite_list = mbedtls_ssl_list_ciphersuites(); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + conf->cert_profile = &mbedtls_x509_crt_profile_default; +#endif + +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if (mbedtls_ssl_conf_is_tls12_only(conf)) { + conf->sig_algs = ssl_tls12_preset_default_sig_algs; + } else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + conf->sig_algs = ssl_preset_default_sig_algs; +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ + +#if defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_DEPRECATED_REMOVED) + conf->curve_list = NULL; +#endif + conf->group_list = ssl_preset_default_groups; + +#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_SSL_HANDSHAKE_WITH_PSK_ENABLED) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if (!mbedtls_svc_key_id_is_null(conf->psk_opaque)) { + conf->psk_opaque = MBEDTLS_SVC_KEY_ID_INIT; + } +#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; + } + + 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 /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */ + +#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_PK_CAN_ECDSA_SOME)) +/* + * 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_PK_CAN_ECDSA_SOME) + 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_PK_CAN_ECDSA_SOME) + case MBEDTLS_SSL_SIG_ECDSA: + return MBEDTLS_PK_ECDSA; +#endif + default: + return MBEDTLS_PK_NONE; + } +} +#endif /* MBEDTLS_PK_C && ( MBEDTLS_RSA_C || MBEDTLS_PK_CAN_ECDSA_SOME ) */ + +/* + * 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_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + case MBEDTLS_SSL_HASH_MD5: + return MBEDTLS_MD_MD5; +#endif +#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + case MBEDTLS_SSL_HASH_SHA1: + return MBEDTLS_MD_SHA1; +#endif +#if defined(MBEDTLS_HAS_ALG_SHA_224_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + case MBEDTLS_SSL_HASH_SHA224: + return MBEDTLS_MD_SHA224; +#endif +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + case MBEDTLS_SSL_HASH_SHA256: + return MBEDTLS_MD_SHA256; +#endif +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + case MBEDTLS_SSL_HASH_SHA384: + return MBEDTLS_MD_SHA384; +#endif +#if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + 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_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + case MBEDTLS_MD_MD5: + return MBEDTLS_SSL_HASH_MD5; +#endif +#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + case MBEDTLS_MD_SHA1: + return MBEDTLS_SSL_HASH_SHA1; +#endif +#if defined(MBEDTLS_HAS_ALG_SHA_224_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + case MBEDTLS_MD_SHA224: + return MBEDTLS_SSL_HASH_SHA224; +#endif +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + case MBEDTLS_MD_SHA256: + return MBEDTLS_SSL_HASH_SHA256; +#endif +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + case MBEDTLS_MD_SHA384: + return MBEDTLS_SSL_HASH_SHA384; +#endif +#if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + case MBEDTLS_MD_SHA512: + return MBEDTLS_SSL_HASH_SHA512; +#endif + default: + return MBEDTLS_SSL_HASH_NONE; + } +} + +/* + * 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_tls_id(const mbedtls_ssl_context *ssl, uint16_t tls_id) +{ + const uint16_t *group_list = mbedtls_ssl_get_groups(ssl); + + if (group_list == NULL) { + return -1; + } + + for (; *group_list != 0; group_list++) { + if (*group_list == tls_id) { + return 0; + } + } + + return -1; +} + +#if defined(MBEDTLS_ECP_C) +/* + * Same as mbedtls_ssl_check_curve_tls_id() but with a mbedtls_ecp_group_id. + */ +int mbedtls_ssl_check_curve(const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id) +{ + uint16_t tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(grp_id); + + if (tls_id == 0) { + return -1; + } + + return mbedtls_ssl_check_curve_tls_id(ssl, tls_id); +} +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_DEBUG_C) +#define EC_NAME(_name_) _name_ +#else +#define EC_NAME(_name_) NULL +#endif + +static const struct { + uint16_t tls_id; + mbedtls_ecp_group_id ecp_group_id; + psa_ecc_family_t psa_family; + uint16_t bits; + const char *name; +} tls_id_match_table[] = +{ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_521) + { 25, MBEDTLS_ECP_DP_SECP521R1, PSA_ECC_FAMILY_SECP_R1, 521, EC_NAME("secp521r1") }, +#endif +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512) + { 28, MBEDTLS_ECP_DP_BP512R1, PSA_ECC_FAMILY_BRAINPOOL_P_R1, 512, EC_NAME("brainpoolP512r1") }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_384) + { 24, MBEDTLS_ECP_DP_SECP384R1, PSA_ECC_FAMILY_SECP_R1, 384, EC_NAME("secp384r1") }, +#endif +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384) + { 27, MBEDTLS_ECP_DP_BP384R1, PSA_ECC_FAMILY_BRAINPOOL_P_R1, 384, EC_NAME("brainpoolP384r1") }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_256) + { 23, MBEDTLS_ECP_DP_SECP256R1, PSA_ECC_FAMILY_SECP_R1, 256, EC_NAME("secp256r1") }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) || defined(PSA_WANT_ECC_SECP_K1_256) + { 22, MBEDTLS_ECP_DP_SECP256K1, PSA_ECC_FAMILY_SECP_K1, 256, EC_NAME("secp256k1") }, +#endif +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256) + { 26, MBEDTLS_ECP_DP_BP256R1, PSA_ECC_FAMILY_BRAINPOOL_P_R1, 256, EC_NAME("brainpoolP256r1") }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_224) + { 21, MBEDTLS_ECP_DP_SECP224R1, PSA_ECC_FAMILY_SECP_R1, 224, EC_NAME("secp224r1") }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || defined(PSA_WANT_ECC_SECP_K1_224) + { 20, MBEDTLS_ECP_DP_SECP224K1, PSA_ECC_FAMILY_SECP_K1, 224, EC_NAME("secp224k1") }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_192) + { 19, MBEDTLS_ECP_DP_SECP192R1, PSA_ECC_FAMILY_SECP_R1, 192, EC_NAME("secp192r1") }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || defined(PSA_WANT_ECC_SECP_K1_192) + { 18, MBEDTLS_ECP_DP_SECP192K1, PSA_ECC_FAMILY_SECP_K1, 192, EC_NAME("secp192k1") }, +#endif +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || defined(PSA_WANT_ECC_MONTGOMERY_255) + { 29, MBEDTLS_ECP_DP_CURVE25519, PSA_ECC_FAMILY_MONTGOMERY, 255, EC_NAME("x25519") }, +#endif +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) || defined(PSA_WANT_ECC_MONTGOMERY_448) + { 30, MBEDTLS_ECP_DP_CURVE448, PSA_ECC_FAMILY_MONTGOMERY, 448, EC_NAME("x448") }, +#endif + { 0, MBEDTLS_ECP_DP_NONE, 0, 0, NULL }, +}; + +int mbedtls_ssl_get_psa_curve_info_from_tls_id(uint16_t tls_id, + psa_ecc_family_t *family, + size_t *bits) +{ + for (int i = 0; tls_id_match_table[i].tls_id != 0; i++) { + if (tls_id_match_table[i].tls_id == tls_id) { + if (family != NULL) { + *family = tls_id_match_table[i].psa_family; + } + if (bits != NULL) { + *bits = tls_id_match_table[i].bits; + } + return PSA_SUCCESS; + } + } + + return PSA_ERROR_NOT_SUPPORTED; +} + +mbedtls_ecp_group_id mbedtls_ssl_get_ecp_group_id_from_tls_id(uint16_t tls_id) +{ + for (int i = 0; tls_id_match_table[i].tls_id != 0; i++) { + if (tls_id_match_table[i].tls_id == tls_id) { + return tls_id_match_table[i].ecp_group_id; + } + } + + return MBEDTLS_ECP_DP_NONE; +} + +uint16_t mbedtls_ssl_get_tls_id_from_ecp_group_id(mbedtls_ecp_group_id grp_id) +{ + for (int i = 0; tls_id_match_table[i].ecp_group_id != MBEDTLS_ECP_DP_NONE; + i++) { + if (tls_id_match_table[i].ecp_group_id == grp_id) { + return tls_id_match_table[i].tls_id; + } + } + + return 0; +} + +#if defined(MBEDTLS_DEBUG_C) +const char *mbedtls_ssl_get_curve_name_from_tls_id(uint16_t tls_id) +{ + for (int i = 0; tls_id_match_table[i].tls_id != 0; i++) { + if (tls_id_match_table[i].tls_id == tls_id) { + return tls_id_match_table[i].name; + } + } + + return NULL; +} +#endif + +#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; + int usage = 0; + const char *ext_oid; + size_t ext_len; + + 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; + } + + 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; + } + + return ret; +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +int mbedtls_ssl_get_handshake_transcript(mbedtls_ssl_context *ssl, + const mbedtls_md_type_t md, + unsigned char *dst, + size_t dst_len, + size_t *olen) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_hash_operation_t *hash_operation_to_clone; + psa_hash_operation_t hash_operation = psa_hash_operation_init(); + + *olen = 0; + + switch (md) { +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + case MBEDTLS_MD_SHA384: + hash_operation_to_clone = &ssl->handshake->fin_sha384_psa; + break; +#endif + +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + case MBEDTLS_MD_SHA256: + hash_operation_to_clone = &ssl->handshake->fin_sha256_psa; + break; +#endif + + default: + goto exit; + } + + status = psa_hash_clone(hash_operation_to_clone, &hash_operation); + if (status != PSA_SUCCESS) { + goto exit; + } + + status = psa_hash_finish(&hash_operation, dst, dst_len, olen); + if (status != PSA_SUCCESS) { + goto exit; + } + +exit: +#if !defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \ + !defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + (void) ssl; +#endif + return PSA_TO_MBEDTLS_ERR(status); +} +#else /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_get_handshake_transcript_sha384(mbedtls_ssl_context *ssl, + unsigned char *dst, + size_t dst_len, + size_t *olen) +{ + int ret; + mbedtls_md_context_t sha384; + + if (dst_len < 48) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + mbedtls_md_init(&sha384); + ret = mbedtls_md_setup(&sha384, mbedtls_md_info_from_type(MBEDTLS_MD_SHA384), 0); + if (ret != 0) { + goto exit; + } + ret = mbedtls_md_clone(&sha384, &ssl->handshake->fin_sha384); + if (ret != 0) { + goto exit; + } + + if ((ret = mbedtls_md_finish(&sha384, dst)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_finish", ret); + goto exit; + } + + *olen = 48; + +exit: + + mbedtls_md_free(&sha384); + return ret; +} +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ + +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_get_handshake_transcript_sha256(mbedtls_ssl_context *ssl, + unsigned char *dst, + size_t dst_len, + size_t *olen) +{ + int ret; + mbedtls_md_context_t sha256; + + if (dst_len < 32) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + mbedtls_md_init(&sha256); + ret = mbedtls_md_setup(&sha256, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 0); + if (ret != 0) { + goto exit; + } + ret = mbedtls_md_clone(&sha256, &ssl->handshake->fin_sha256); + if (ret != 0) { + goto exit; + } + + if ((ret = mbedtls_md_finish(&sha256, dst)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_finish", ret); + goto exit; + } + + *olen = 32; + +exit: + + mbedtls_md_free(&sha256); + return ret; +} +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ + +int mbedtls_ssl_get_handshake_transcript(mbedtls_ssl_context *ssl, + const mbedtls_md_type_t md, + unsigned char *dst, + size_t dst_len, + size_t *olen) +{ + switch (md) { + +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + case MBEDTLS_MD_SHA384: + return ssl_get_handshake_transcript_sha384(ssl, dst, dst_len, olen); +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/ + +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + case MBEDTLS_MD_SHA256: + return ssl_get_handshake_transcript_sha256(ssl, dst, dst_len, olen); +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/ + + default: +#if !defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \ + !defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + (void) ssl; + (void) dst; + (void) dst_len; + (void) olen; +#endif + break; + } + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; +} + +#endif /* !MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) +/* mbedtls_ssl_parse_sig_alg_ext() + * + * The `extension_data` field of signature algorithm contains a `SignatureSchemeList` + * value (TLS 1.3 RFC8446): + * enum { + * .... + * ecdsa_secp256r1_sha256( 0x0403 ), + * ecdsa_secp384r1_sha384( 0x0503 ), + * ecdsa_secp521r1_sha512( 0x0603 ), + * .... + * } SignatureScheme; + * + * struct { + * SignatureScheme supported_signature_algorithms<2..2^16-2>; + * } SignatureSchemeList; + * + * The `extension_data` field of signature algorithm contains a `SignatureAndHashAlgorithm` + * value (TLS 1.2 RFC5246): + * 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>; + * + * The TLS 1.3 signature algorithm extension was defined to be a compatible + * generalization of the TLS 1.2 signature algorithm extension. + * `SignatureAndHashAlgorithm` field of TLS 1.2 can be represented by + * `SignatureScheme` field of TLS 1.3 + * + */ +int mbedtls_ssl_parse_sig_alg_ext(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + const unsigned char *p = buf; + size_t supported_sig_algs_len = 0; + const unsigned char *supported_sig_algs_end; + uint16_t sig_alg; + uint32_t common_idx = 0; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + supported_sig_algs_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + + memset(ssl->handshake->received_sig_algs, 0, + sizeof(ssl->handshake->received_sig_algs)); + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, supported_sig_algs_len); + supported_sig_algs_end = p + supported_sig_algs_len; + while (p < supported_sig_algs_end) { + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, supported_sig_algs_end, 2); + sig_alg = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + MBEDTLS_SSL_DEBUG_MSG(4, ("received signature algorithm: 0x%x %s", + sig_alg, + mbedtls_ssl_sig_alg_to_str(sig_alg))); +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2 && + (!(mbedtls_ssl_sig_alg_is_supported(ssl, sig_alg) && + mbedtls_ssl_sig_alg_is_offered(ssl, sig_alg)))) { + continue; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + MBEDTLS_SSL_DEBUG_MSG(4, ("valid signature algorithm: %s", + mbedtls_ssl_sig_alg_to_str(sig_alg))); + + if (common_idx + 1 < MBEDTLS_RECEIVED_SIG_ALGS_SIZE) { + ssl->handshake->received_sig_algs[common_idx] = sig_alg; + common_idx += 1; + } + } + /* Check that we consumed all the message. */ + if (p != end) { + MBEDTLS_SSL_DEBUG_MSG(1, + ("Signature algorithms extension length misaligned")); + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, + MBEDTLS_ERR_SSL_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + if (common_idx == 0) { + MBEDTLS_SSL_DEBUG_MSG(3, ("no signature algorithm in common")); + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, + MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + + ssl->handshake->received_sig_algs[common_idx] = MBEDTLS_TLS_SIG_NONE; + return 0; +} + +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ + +#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, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const unsigned char *raw_psk, size_t raw_psk_length, + const unsigned char *seed, size_t seed_length, + const unsigned char *label, size_t label_length, + const unsigned char *other_secret, + size_t other_secret_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 (other_secret != NULL) { + status = psa_key_derivation_input_bytes(derivation, + PSA_KEY_DERIVATION_INPUT_OTHER_SECRET, + other_secret, other_secret_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, + raw_psk, raw_psk_length); + } 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; +} + +#if defined(PSA_WANT_ALG_SHA_384) || \ + defined(PSA_WANT_ALG_SHA_256) +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; + mbedtls_svc_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, + NULL, 0, + random, rlen, + (unsigned char const *) label, + (size_t) strlen(label), + NULL, 0, + 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; +} +#endif /* PSA_WANT_ALG_SHA_256 || PSA_WANT_ALG_SHA_384 */ +#else /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_MD_C) && \ + (defined(MBEDTLS_SHA256_C) || \ + defined(MBEDTLS_SHA384_C)) +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); + + if (tmp != NULL) { + mbedtls_platform_zeroize(tmp, tmp_len); + } + + mbedtls_platform_zeroize(h_i, sizeof(h_i)); + + mbedtls_free(tmp); + + return ret; +} +#endif /* MBEDTLS_MD_C && ( MBEDTLS_SHA256_C || MBEDTLS_SHA384_C ) */ +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +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_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/ + +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +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_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/ + +/* + * Set appropriate PRF function and other SSL / TLS1.2 functions + * + * Inputs: + * - 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, + mbedtls_md_type_t hash) +{ +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + if (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_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { + (void) hash; + handshake->tls_prf = tls_prf_sha256; + handshake->calc_verify = ssl_calc_verify_tls_sha256; + handshake->calc_finished = ssl_calc_finished_tls_sha256; + } +#else + { + (void) handshake; + (void) hash; + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } +#endif + + 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 + session_negotiate) + * PSA-PSA: 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 seed 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 *seed = handshake->randbytes; + size_t seed_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"; + seed = session_hash; + ret = handshake->calc_verify(ssl, session_hash, &seed_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "calc_verify", ret); + } + + MBEDTLS_SSL_DEBUG_BUF(3, "session hash for extended master secret", + session_hash, seed_len); + } +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) + if (mbedtls_ssl_ciphersuite_uses_psk(handshake->ciphersuite_info) == 1) { + /* Perform PSK-to-MS expansion in a single step. */ + psa_status_t status; + psa_algorithm_t alg; + mbedtls_svc_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); + } + + size_t other_secret_len = 0; + unsigned char *other_secret = NULL; + + switch (handshake->ciphersuite_info->key_exchange) { + /* Provide other secret. + * Other secret is stored in premaster, where first 2 bytes hold the + * length of the other key. + */ + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + /* For RSA-PSK other key length is always 48 bytes. */ + other_secret_len = 48; + other_secret = handshake->premaster + 2; + break; + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + case MBEDTLS_KEY_EXCHANGE_DHE_PSK: + other_secret_len = MBEDTLS_GET_UINT16_BE(handshake->premaster, 0); + other_secret = handshake->premaster + 2; + break; + default: + break; + } + + status = setup_psa_key_derivation(&derivation, psk, alg, + ssl->conf->psk, ssl->conf->psk_len, + seed, seed_len, + (unsigned char const *) lbl, + (size_t) strlen(lbl), + other_secret, other_secret_len, + 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 + { +#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if (handshake->ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE) { + psa_status_t status; + psa_algorithm_t alg = PSA_ALG_TLS12_ECJPAKE_TO_PMS; + psa_key_derivation_operation_t derivation = + PSA_KEY_DERIVATION_OPERATION_INIT; + + MBEDTLS_SSL_DEBUG_MSG(2, ("perform PSA-based PMS KDF for ECJPAKE")); + + handshake->pmslen = PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE; + + status = psa_key_derivation_setup(&derivation, alg); + if (status != PSA_SUCCESS) { + return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + } + + status = psa_key_derivation_set_capacity(&derivation, + PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE); + if (status != PSA_SUCCESS) { + psa_key_derivation_abort(&derivation); + return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + } + + status = psa_pake_get_implicit_key(&handshake->psa_pake_ctx, + &derivation); + if (status != PSA_SUCCESS) { + psa_key_derivation_abort(&derivation); + return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + } + + status = psa_key_derivation_output_bytes(&derivation, + handshake->premaster, + handshake->pmslen); + 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; + } + } +#endif + ret = handshake->tls_prf(handshake->premaster, handshake->pmslen, + lbl, seed, seed_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, + 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_tls12_populate_transform(ssl->transform_negotiate, + ssl->session_negotiate->ciphersuite, + ssl->session_negotiate->master, +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) + ssl->session_negotiate->encrypt_then_mac, +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */ + ssl->handshake->tls_prf, + ssl->handshake->randbytes, + ssl->tls_version, + ssl->conf->endpoint, + ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls12_populate_transform", ret); + return ret; + } + + /* We no longer need Server/ClientHello.random values */ + mbedtls_platform_zeroize(ssl->handshake->randbytes, + sizeof(ssl->handshake->randbytes)); + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= derive keys")); + + return 0; +} + +int mbedtls_ssl_set_calc_verify_md(mbedtls_ssl_context *ssl, int md) +{ + switch (md) { +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + case MBEDTLS_SSL_HASH_SHA384: + ssl->handshake->calc_verify = ssl_calc_verify_tls_sha384; + break; +#endif +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + case MBEDTLS_SSL_HASH_SHA256: + ssl->handshake->calc_verify = ssl_calc_verify_tls_sha256; + break; +#endif + default: + return -1; + } +#if !defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \ + !defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + (void) ssl; +#endif + return 0; +} + +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +int 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) { + goto exit; + } + + status = psa_hash_finish(&sha256_psa, hash, 32, &hash_size); + if (status != PSA_SUCCESS) { + goto exit; + } + + *hlen = 32; + MBEDTLS_SSL_DEBUG_BUF(3, "PSA calculated verify result", hash, *hlen); + MBEDTLS_SSL_DEBUG_MSG(2, ("<= PSA calc verify")); + +exit: + psa_hash_abort(&sha256_psa); + return PSA_TO_MD_ERR(status); +#else + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_md_context_t sha256; + + mbedtls_md_init(&sha256); + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc verify sha256")); + + ret = mbedtls_md_setup(&sha256, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 0); + if (ret != 0) { + goto exit; + } + ret = mbedtls_md_clone(&sha256, &ssl->handshake->fin_sha256); + if (ret != 0) { + goto exit; + } + + ret = mbedtls_md_finish(&sha256, hash); + if (ret != 0) { + goto exit; + } + + *hlen = 32; + + MBEDTLS_SSL_DEBUG_BUF(3, "calculated verify result", hash, *hlen); + MBEDTLS_SSL_DEBUG_MSG(2, ("<= calc verify")); + +exit: + mbedtls_md_free(&sha256); + return ret; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +} +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ + +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +int 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) { + goto exit; + } + + status = psa_hash_finish(&sha384_psa, hash, 48, &hash_size); + if (status != PSA_SUCCESS) { + goto exit; + } + + *hlen = 48; + MBEDTLS_SSL_DEBUG_BUF(3, "PSA calculated verify result", hash, *hlen); + MBEDTLS_SSL_DEBUG_MSG(2, ("<= PSA calc verify")); + +exit: + psa_hash_abort(&sha384_psa); + return PSA_TO_MD_ERR(status); +#else + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_md_context_t sha384; + + mbedtls_md_init(&sha384); + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc verify sha384")); + + ret = mbedtls_md_setup(&sha384, mbedtls_md_info_from_type(MBEDTLS_MD_SHA384), 0); + if (ret != 0) { + goto exit; + } + ret = mbedtls_md_clone(&sha384, &ssl->handshake->fin_sha384); + if (ret != 0) { + goto exit; + } + + ret = mbedtls_md_finish(&sha384, hash); + if (ret != 0) { + goto exit; + } + + *hlen = 48; + + MBEDTLS_SSL_DEBUG_BUF(3, "calculated verify result", hash, *hlen); + MBEDTLS_SSL_DEBUG_MSG(2, ("<= calc verify")); + +exit: + mbedtls_md_free(&sha384); + return ret; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +} +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ + +#if !defined(MBEDTLS_USE_PSA_CRYPTO) && \ + 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; + int psk_ret = mbedtls_ssl_get_psk(ssl, &psk, &psk_len); + + if (psk_ret == MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED) { + /* + * This should never happen because the existence of a PSK is always + * checked before calling this function. + * + * The exception is opaque DHE-PSK. For DHE-PSK fill premaster with + * the shared secret without PSK. + */ + if (key_ex != MBEDTLS_KEY_EXCHANGE_DHE_PSK) { + 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_USE_PSA_CRYPTO && 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 */ + +/* + * 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->handshake->client_auth == 0) { + MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate")); + ssl->state++; + return 0; + } + } +#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) { + /* Should never happen because we shouldn't have picked the + * ciphersuite if we don't have a certificate. */ + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + } +#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_BUFFER_TOO_SMALL; + } + + 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; + + 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) { + 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_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_DECODE_ERROR; + } + + 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_DECODE_ERROR; + } + + /* 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_DECODE_ERROR; + } + /* 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_UNSUPPORTED_CERT); + return MBEDTLS_ERR_SSL_BAD_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_DECODE_ERROR; + } + + /* 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_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 (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, ("peer has no certificate")); + return 0; + } + return -1; +} +#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)) { + /* and in the unlikely case the above assumption no longer holds + * we are making sure that pk_ec() here does not return a NULL + */ + const mbedtls_ecp_keypair *ec = mbedtls_pk_ec(*pk); + if (ec == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("mbedtls_pk_ec() returned NULL")); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + if (mbedtls_ssl_check_curve(ssl, ec->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_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_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_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 */ + +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +static int 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 + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_md_context_t 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) { + goto exit; + } + + status = psa_hash_finish(&sha256_psa, padbuf, sizeof(padbuf), &hash_size); + if (status != PSA_SUCCESS) { + goto exit; + } + MBEDTLS_SSL_DEBUG_BUF(3, "PSA calculated padbuf", padbuf, 32); +#else + + mbedtls_md_init(&sha256); + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc finished tls sha256")); + + ret = mbedtls_md_setup(&sha256, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 0); + if (ret != 0) { + goto exit; + } + ret = mbedtls_md_clone(&sha256, &ssl->handshake->fin_sha256); + if (ret != 0) { + goto exit; + } + + /* + * TLSv1.2: + * hash = PRF( master, finished_label, + * Hash( handshake ) )[0.11] + */ + + ret = mbedtls_md_finish(&sha256, padbuf); + if (ret != 0) { + goto exit; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + MBEDTLS_SSL_DEBUG_BUF(4, "finished sha256 output", padbuf, 32); + + 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")); + +exit: +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_abort(&sha256_psa); + return PSA_TO_MD_ERR(status); +#else + mbedtls_md_free(&sha256); + return ret; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +} +#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/ + + +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +static int 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 + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_md_context_t sha384; +#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) { + goto exit; + } + + status = psa_hash_finish(&sha384_psa, padbuf, sizeof(padbuf), &hash_size); + if (status != PSA_SUCCESS) { + goto exit; + } + MBEDTLS_SSL_DEBUG_BUF(3, "PSA calculated padbuf", padbuf, 48); +#else + mbedtls_md_init(&sha384); + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc finished tls sha384")); + + ret = mbedtls_md_setup(&sha384, mbedtls_md_info_from_type(MBEDTLS_MD_SHA384), 0); + if (ret != 0) { + goto exit; + } + ret = mbedtls_md_clone(&sha384, &ssl->handshake->fin_sha384); + if (ret != 0) { + goto exit; + } + + /* + * TLSv1.2: + * hash = PRF( master, finished_label, + * Hash( handshake ) )[0.11] + */ + + ret = mbedtls_md_finish(&sha384, padbuf); + if (ret != 0) { + goto exit; + } +#endif + + MBEDTLS_SSL_DEBUG_BUF(4, "finished sha384 output", padbuf, 48); + + 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")); + +exit: +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_abort(&sha384_psa); + return PSA_TO_MD_ERR(status); +#else + mbedtls_md_free(&sha384); + return ret; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +} +#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/ + +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->id, + ssl->session->id_len, + 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_HANDSHAKE_OVER; + + 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); + + ret = ssl->handshake->calc_finished(ssl, ssl->out_msg + 4, ssl->conf->endpoint); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "calc_finished", ret); + } + + /* + * 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 = 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, + sizeof(ssl->handshake->alt_out_ctr)); + + /* Set sequence_number to zero */ + memset(&ssl->cur_out_ctr[2], 0, sizeof(ssl->cur_out_ctr) - 2); + + + /* 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, sizeof(ssl->cur_out_ctr)); + + ssl->transform_out = ssl->transform_negotiate; + ssl->session_out = ssl->session_negotiate; + +#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; +} + +#define SSL_MAX_HASH_LEN 12 + +int mbedtls_ssl_parse_finished(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned int hash_len = 12; + unsigned char buf[SSL_MAX_HASH_LEN]; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse finished")); + + ret = ssl->handshake->calc_finished(ssl, buf, ssl->conf->endpoint ^ 1); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "calc_finished", ret); + } + + 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) { + 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_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_DECODE_ERROR; + 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_HANDSHAKE_FAILURE; + 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; +} + +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) +/* + * Helper to get TLS 1.2 PRF from ciphersuite + * (Duplicates bits of logic from ssl_set_handshake_prfs().) + */ +static tls_prf_fn ssl_tls12prf_from_cs(int ciphersuite_id) +{ + const mbedtls_ssl_ciphersuite_t * const ciphersuite_info = + mbedtls_ssl_ciphersuite_from_id(ciphersuite_id); +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + if (ciphersuite_info != NULL && ciphersuite_info->mac == MBEDTLS_MD_SHA384) { + return tls_prf_sha384; + } else +#endif +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + { + if (ciphersuite_info != NULL && ciphersuite_info->mac == MBEDTLS_MD_SHA256) { + return tls_prf_sha256; + } + } +#endif +#if !defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \ + !defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + (void) ciphersuite_info; +#endif + + return NULL; +} +#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ + +static mbedtls_tls_prf_types tls_prf_get_type(mbedtls_ssl_tls_prf_cb *tls_prf) +{ + ((void) tls_prf); +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + if (tls_prf == tls_prf_sha384) { + return MBEDTLS_SSL_TLS_PRF_SHA384; + } else +#endif +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) + if (tls_prf == tls_prf_sha256) { + return MBEDTLS_SSL_TLS_PRF_SHA256; + } else +#endif + return MBEDTLS_SSL_TLS_PRF_NONE; +} + +/* + * 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] tls_prf: pointer to PRF to use for key derivation + * - [in] randbytes: buffer holding ServerHello.random + ClientHello.random + * - [in] tls_version: TLS version + * - [in] endpoint: client or server + * - [in] ssl: used for: + * - ssl->conf->{f,p}_export_keys + * [in] optionally used for: + * - MBEDTLS_DEBUG_C: ssl->conf->{f,p}_dbg + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls12_populate_transform(mbedtls_ssl_transform *transform, + int ciphersuite, + const unsigned char master[48], +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) + int encrypt_then_mac, +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */ + ssl_tls_prf_t tls_prf, + const unsigned char randbytes[64], + mbedtls_ssl_protocol_version tls_version, + unsigned endpoint, + const mbedtls_ssl_context *ssl) +{ + int ret = 0; + 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; + size_t keylen; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + mbedtls_ssl_mode_t ssl_mode; +#if !defined(MBEDTLS_USE_PSA_CRYPTO) + const mbedtls_cipher_info_t *cipher_info; + const mbedtls_md_info_t *md_info; +#endif /* !MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_key_type_t key_type; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_algorithm_t alg; + psa_algorithm_t mac_alg = 0; + size_t key_bits; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; +#endif + +#if !defined(MBEDTLS_DEBUG_C) && \ + !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + if (ssl->f_export_keys == NULL) { + ssl = NULL; /* make sure we don't use it except for these cases */ + (void) ssl; + } +#endif + + /* + * Some data just needs copying into the structure + */ +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) + transform->encrypt_then_mac = encrypt_then_mac; +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */ + transform->tls_version = tls_version; + +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) + memcpy(transform->randbytes, randbytes, sizeof(transform->randbytes)); +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + if (tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { + /* At the moment, we keep TLS <= 1.2 and TLS 1.3 transform + * generation separate. This should never happen. */ + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + + /* + * 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; + } + + ssl_mode = mbedtls_ssl_get_mode_from_ciphersuite( +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) + encrypt_then_mac, +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */ + ciphersuite_info); + + if (ssl_mode == MBEDTLS_SSL_MODE_AEAD) { + transform->taglen = + ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16; + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if ((status = mbedtls_ssl_cipher_to_psa(ciphersuite_info->cipher, + transform->taglen, + &alg, + &key_type, + &key_bits)) != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_cipher_to_psa", ret); + goto end; + } +#else + 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; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + mac_alg = mbedtls_hash_info_psa_from_md(ciphersuite_info->mac); + if (mac_alg == 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("mbedtls_hash_info_psa_from_md for %u not found", + (unsigned) ciphersuite_info->mac)); + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } +#else + 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; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#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. + */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + keylen = PSA_BITS_TO_BYTES(key_bits); +#else + keylen = mbedtls_cipher_info_get_key_bitlen(cipher_info) / 8; +#endif + +#if defined(MBEDTLS_GCM_C) || \ + defined(MBEDTLS_CCM_C) || \ + defined(MBEDTLS_CHACHAPOLY_C) + if (ssl_mode == MBEDTLS_SSL_MODE_AEAD) { + size_t explicit_ivlen; + + transform->maclen = 0; + mac_key_len = 0; + + /* 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; + + int is_chachapoly = 0; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + is_chachapoly = (key_type == PSA_KEY_TYPE_CHACHA20); +#else + is_chachapoly = (mbedtls_cipher_info_get_mode(cipher_info) + == MBEDTLS_MODE_CHACHAPOLY); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + if (is_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_SUITES_USE_MAC) + if (ssl_mode == MBEDTLS_SSL_MODE_STREAM || + ssl_mode == MBEDTLS_SSL_MODE_CBC || + ssl_mode == MBEDTLS_SSL_MODE_CBC_ETM) { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + size_t block_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type); +#else + size_t block_size = cipher_info->block_size; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /* Get MAC length */ + mac_key_len = PSA_HASH_LENGTH(mac_alg); +#else + /* 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); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + transform->maclen = mac_key_len; + + /* IV length */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + transform->ivlen = PSA_CIPHER_IV_LENGTH(key_type, alg); +#else + transform->ivlen = cipher_info->iv_size; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + /* Minimum length */ + if (ssl_mode == MBEDTLS_SSL_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 + */ +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if (ssl_mode == MBEDTLS_SSL_MODE_CBC_ETM) { + transform->minlen = transform->maclen + + block_size; + } else +#endif + { + transform->minlen = transform->maclen + + block_size + - transform->maclen % block_size; + } + + if (tls_version == MBEDTLS_SSL_VERSION_TLS1_2) { + transform->minlen += transform->ivlen; + } else { + MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + goto end; + } + } + } else +#endif /* MBEDTLS_SSL_SOME_SUITES_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; + + 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; + + 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 (ssl != NULL && ssl->f_export_keys != NULL) { + ssl->f_export_keys(ssl->p_export_keys, + MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET, + master, 48, + randbytes + 32, + randbytes, + tls_prf_get_type(tls_prf)); + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + transform->psa_alg = alg; + + if (alg != MBEDTLS_SSL_NULL_CIPHER) { + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT); + psa_set_key_algorithm(&attributes, alg); + psa_set_key_type(&attributes, key_type); + + if ((status = psa_import_key(&attributes, + key1, + PSA_BITS_TO_BYTES(key_bits), + &transform->psa_key_enc)) != PSA_SUCCESS) { + MBEDTLS_SSL_DEBUG_RET(3, "psa_import_key", (int) status); + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_import_key", ret); + goto end; + } + + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT); + + if ((status = psa_import_key(&attributes, + key2, + PSA_BITS_TO_BYTES(key_bits), + &transform->psa_key_dec)) != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_import_key", ret); + goto end; + } + } +#else + if ((ret = mbedtls_cipher_setup(&transform->cipher_ctx_enc, + cipher_info)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setup", ret); + goto end; + } + + 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, + (int) mbedtls_cipher_info_get_key_bitlen(cipher_info), + MBEDTLS_ENCRYPT)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setkey", ret); + goto end; + } + + if ((ret = mbedtls_cipher_setkey(&transform->cipher_ctx_dec, key2, + (int) mbedtls_cipher_info_get_key_bitlen(cipher_info), + MBEDTLS_DECRYPT)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setkey", ret); + goto end; + } + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + if (mbedtls_cipher_info_get_mode(cipher_info) == 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 */ +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) + /* For HMAC-based ciphersuites, initialize the HMAC transforms. + For AEAD-based ciphersuites, there is nothing to do here. */ + if (mac_key_len != 0) { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + transform->psa_mac_alg = PSA_ALG_HMAC(mac_alg); + + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE); + psa_set_key_algorithm(&attributes, PSA_ALG_HMAC(mac_alg)); + psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC); + + if ((status = psa_import_key(&attributes, + mac_enc, mac_key_len, + &transform->psa_mac_enc)) != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_import_mac_key", ret); + goto end; + } + + if ((transform->psa_alg == MBEDTLS_SSL_NULL_CIPHER) || + ((transform->psa_alg == PSA_ALG_CBC_NO_PADDING) +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) + && (transform->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED) +#endif + )) { + /* mbedtls_ct_hmac() requires the key to be exportable */ + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_EXPORT | + PSA_KEY_USAGE_VERIFY_HASH); + } else { + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH); + } + + if ((status = psa_import_key(&attributes, + mac_dec, mac_key_len, + &transform->psa_mac_dec)) != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_import_mac_key", ret); + goto end; + } +#else + 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; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + } +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ + + ((void) mac_dec); + ((void) mac_enc); + +end: + mbedtls_platform_zeroize(keyblk, sizeof(keyblk)); + return ret; +} + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ + defined(MBEDTLS_USE_PSA_CRYPTO) +int mbedtls_psa_ecjpake_read_round( + psa_pake_operation_t *pake_ctx, + const unsigned char *buf, + size_t len, mbedtls_ecjpake_rounds_t round) +{ + psa_status_t status; + size_t input_offset = 0; + /* + * At round one repeat the KEY_SHARE, ZK_PUBLIC & ZF_PROOF twice + * At round two perform a single cycle + */ + unsigned int remaining_steps = (round == MBEDTLS_ECJPAKE_ROUND_ONE) ? 2 : 1; + + for (; remaining_steps > 0; remaining_steps--) { + for (psa_pake_step_t step = PSA_PAKE_STEP_KEY_SHARE; + step <= PSA_PAKE_STEP_ZK_PROOF; + ++step) { + /* Length is stored at the first byte */ + size_t length = buf[input_offset]; + input_offset += 1; + + if (input_offset + length > len) { + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + + status = psa_pake_input(pake_ctx, step, + buf + input_offset, length); + if (status != PSA_SUCCESS) { + return PSA_TO_MBEDTLS_ERR(status); + } + + input_offset += length; + } + } + + if (input_offset != len) { + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + + return 0; +} + +int mbedtls_psa_ecjpake_write_round( + psa_pake_operation_t *pake_ctx, + unsigned char *buf, + size_t len, size_t *olen, + mbedtls_ecjpake_rounds_t round) +{ + psa_status_t status; + size_t output_offset = 0; + size_t output_len; + /* + * At round one repeat the KEY_SHARE, ZK_PUBLIC & ZF_PROOF twice + * At round two perform a single cycle + */ + unsigned int remaining_steps = (round == MBEDTLS_ECJPAKE_ROUND_ONE) ? 2 : 1; + + for (; remaining_steps > 0; remaining_steps--) { + for (psa_pake_step_t step = PSA_PAKE_STEP_KEY_SHARE; + step <= PSA_PAKE_STEP_ZK_PROOF; + ++step) { + /* + * For each step, prepend 1 byte with the length of the data as + * given by psa_pake_output(). + */ + status = psa_pake_output(pake_ctx, step, + buf + output_offset + 1, + len - output_offset - 1, + &output_len); + if (status != PSA_SUCCESS) { + return PSA_TO_MBEDTLS_ERR(status); + } + + *(buf + output_offset) = (uint8_t) output_len; + + output_offset += output_len + 1; + } + } + + *olen = output_offset; + + return 0; +} +#endif //MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED && MBEDTLS_USE_PSA_CRYPTO + +#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_hash_info_psa_from_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_PLATFORM_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 */ + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + +/* Find the preferred hash for a given signature algorithm. */ +unsigned int mbedtls_ssl_tls12_get_preferred_hash_for_sig_alg( + mbedtls_ssl_context *ssl, + unsigned int sig_alg) +{ + unsigned int i; + uint16_t *received_sig_algs = ssl->handshake->received_sig_algs; + + if (sig_alg == MBEDTLS_SSL_SIG_ANON) { + return MBEDTLS_SSL_HASH_NONE; + } + + for (i = 0; received_sig_algs[i] != MBEDTLS_TLS_SIG_NONE; i++) { + unsigned int hash_alg_received = + MBEDTLS_SSL_TLS12_HASH_ALG_FROM_SIG_AND_HASH_ALG( + received_sig_algs[i]); + unsigned int sig_alg_received = + MBEDTLS_SSL_TLS12_SIG_ALG_FROM_SIG_AND_HASH_ALG( + received_sig_algs[i]); + + if (sig_alg == sig_alg_received) { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if (ssl->handshake->key_cert && ssl->handshake->key_cert->key) { + psa_algorithm_t psa_hash_alg = + mbedtls_hash_info_psa_from_md(hash_alg_received); + + if (sig_alg_received == MBEDTLS_SSL_SIG_ECDSA && + !mbedtls_pk_can_do_ext(ssl->handshake->key_cert->key, + PSA_ALG_ECDSA(psa_hash_alg), + PSA_KEY_USAGE_SIGN_HASH)) { + continue; + } + + if (sig_alg_received == MBEDTLS_SSL_SIG_RSA && + !mbedtls_pk_can_do_ext(ssl->handshake->key_cert->key, + PSA_ALG_RSA_PKCS1V15_SIGN( + psa_hash_alg), + PSA_KEY_USAGE_SIGN_HASH)) { + continue; + } + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + return hash_alg_received; + } + } + + return MBEDTLS_SSL_HASH_NONE; +} + +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +/* Serialization of TLS 1.2 sessions: + * + * struct { + * uint64 start_time; + * uint8 ciphersuite[2]; // defined by the standard + * 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 encrypt_then_mac; // 0 or 1 + * } serialized_session_tls12; + * + */ +static size_t ssl_tls12_session_save(const mbedtls_ssl_session *session, + unsigned char *buf, + size_t buf_len) +{ + 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 */ + + /* + * 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 /* 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->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_ENCRYPT_THEN_MAC) + used += 1; + + if (used <= buf_len) { + *p++ = MBEDTLS_BYTE_0(session->encrypt_then_mac); + } +#endif + + return used; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls12_session_load(mbedtls_ssl_session *session, + const unsigned char *buf, + size_t 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 */ + + const unsigned char *p = buf; + const unsigned char * const end = buf + len; + + /* + * 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 + 32 + 48 + 4 > (size_t) (end - p)) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + session->ciphersuite = (p[0] << 8) | p[1]; + p += 2; + + 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_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; +} +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +int mbedtls_ssl_validate_ciphersuite( + const mbedtls_ssl_context *ssl, + const mbedtls_ssl_ciphersuite_t *suite_info, + mbedtls_ssl_protocol_version min_tls_version, + mbedtls_ssl_protocol_version max_tls_version) +{ + (void) ssl; + + if (suite_info == NULL) { + return -1; + } + + if ((suite_info->min_tls_version > max_tls_version) || + (suite_info->max_tls_version < min_tls_version)) { + return -1; + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_CLI_C) +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if (suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && + ssl->handshake->psa_pake_ctx_is_ok != 1) +#else + if (suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && + mbedtls_ecjpake_check(&ssl->handshake->ecjpake_ctx) != 0) +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + { + 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) && + mbedtls_ssl_conf_has_static_psk(ssl->conf) == 0) { + return -1; + } +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + return 0; +} + +#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) +/* + * Function for writing a signature algorithm extension. + * + * The `extension_data` field of signature algorithm contains a `SignatureSchemeList` + * value (TLS 1.3 RFC8446): + * enum { + * .... + * ecdsa_secp256r1_sha256( 0x0403 ), + * ecdsa_secp384r1_sha384( 0x0503 ), + * ecdsa_secp521r1_sha512( 0x0603 ), + * .... + * } SignatureScheme; + * + * struct { + * SignatureScheme supported_signature_algorithms<2..2^16-2>; + * } SignatureSchemeList; + * + * The `extension_data` field of signature algorithm contains a `SignatureAndHashAlgorithm` + * value (TLS 1.2 RFC5246): + * 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>; + * + * The TLS 1.3 signature algorithm extension was defined to be a compatible + * generalization of the TLS 1.2 signature algorithm extension. + * `SignatureAndHashAlgorithm` field of TLS 1.2 can be represented by + * `SignatureScheme` field of TLS 1.3 + * + */ +int mbedtls_ssl_write_sig_alg_ext(mbedtls_ssl_context *ssl, unsigned char *buf, + const unsigned char *end, size_t *out_len) +{ + unsigned char *p = buf; + unsigned char *supported_sig_alg; /* Start of supported_signature_algorithms */ + size_t supported_sig_alg_len = 0; /* Length of supported_signature_algorithms */ + + *out_len = 0; + + MBEDTLS_SSL_DEBUG_MSG(3, ("adding signature_algorithms extension")); + + /* Check if we have space for header and length field: + * - extension_type (2 bytes) + * - extension_data_length (2 bytes) + * - supported_signature_algorithms_length (2 bytes) + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6); + p += 6; + + /* + * Write supported_signature_algorithms + */ + supported_sig_alg = p; + const uint16_t *sig_alg = mbedtls_ssl_get_sig_algs(ssl); + if (sig_alg == NULL) { + return MBEDTLS_ERR_SSL_BAD_CONFIG; + } + + for (; *sig_alg != MBEDTLS_TLS1_3_SIG_NONE; sig_alg++) { + MBEDTLS_SSL_DEBUG_MSG(3, ("got signature scheme [%x] %s", + *sig_alg, + mbedtls_ssl_sig_alg_to_str(*sig_alg))); + if (!mbedtls_ssl_sig_alg_is_supported(ssl, *sig_alg)) { + continue; + } + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); + MBEDTLS_PUT_UINT16_BE(*sig_alg, p, 0); + p += 2; + MBEDTLS_SSL_DEBUG_MSG(3, ("sent signature scheme [%x] %s", + *sig_alg, + mbedtls_ssl_sig_alg_to_str(*sig_alg))); + } + + /* Length of supported_signature_algorithms */ + supported_sig_alg_len = p - supported_sig_alg; + if (supported_sig_alg_len == 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("No signature algorithms defined.")); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SIG_ALG, buf, 0); + MBEDTLS_PUT_UINT16_BE(supported_sig_alg_len + 2, buf, 2); + MBEDTLS_PUT_UINT16_BE(supported_sig_alg_len, buf, 4); + + *out_len = p - buf; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_SIG_ALG); +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + + return 0; +} +#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +/* + * mbedtls_ssl_parse_server_name_ext + * + * Structure of server_name extension: + * + * enum { + * host_name(0), (255) + * } NameType; + * opaque HostName<1..2^16-1>; + * + * struct { + * NameType name_type; + * select (name_type) { + * case host_name: HostName; + * } name; + * } ServerName; + * struct { + * ServerName server_name_list<1..2^16-1> + * } ServerNameList; + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_parse_server_name_ext(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const unsigned char *p = buf; + size_t server_name_list_len, hostname_len; + const unsigned char *server_name_list_end; + + MBEDTLS_SSL_DEBUG_MSG(3, ("parse ServerName extension")); + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + server_name_list_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, server_name_list_len); + server_name_list_end = p + server_name_list_len; + while (p < server_name_list_end) { + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, server_name_list_end, 3); + hostname_len = MBEDTLS_GET_UINT16_BE(p, 1); + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, server_name_list_end, + hostname_len + 3); + + if (p[0] == MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME) { + /* sni_name is intended to be used only during the parsing of the + * ClientHello message (it is reset to NULL before the end of + * the message parsing). Thus it is ok to just point to the + * reception buffer and not make a copy of it. + */ + ssl->handshake->sni_name = p + 3; + ssl->handshake->sni_name_len = hostname_len; + if (ssl->conf->f_sni == NULL) { + return 0; + } + 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_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME, + MBEDTLS_ERR_SSL_UNRECOGNIZED_NAME); + return MBEDTLS_ERR_SSL_UNRECOGNIZED_NAME; + } + return 0; + } + + p += hostname_len + 3; + } + + return 0; +} +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_SSL_ALPN) +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_parse_alpn_ext(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + const unsigned char *p = buf; + size_t protocol_name_list_len; + const unsigned char *protocol_name_list; + const unsigned char *protocol_name_list_end; + size_t protocol_name_len; + + /* If ALPN not configured, just ignore the extension */ + if (ssl->conf->alpn_list == NULL) { + return 0; + } + + /* + * RFC7301, section 3.1 + * opaque ProtocolName<1..2^8-1>; + * + * struct { + * ProtocolName protocol_name_list<2..2^16-1> + * } ProtocolNameList; + */ + + /* + * protocol_name_list_len 2 bytes + * protocol_name_len 1 bytes + * protocol_name >=1 byte + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 4); + + protocol_name_list_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, protocol_name_list_len); + protocol_name_list = p; + protocol_name_list_end = p + protocol_name_list_len; + + /* Validate peer's list (lengths) */ + while (p < protocol_name_list_end) { + protocol_name_len = *p++; + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, protocol_name_list_end, + protocol_name_len); + if (protocol_name_len == 0) { + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + + p += protocol_name_len; + } + + /* Use our order of preference */ + for (const char **alpn = ssl->conf->alpn_list; *alpn != NULL; alpn++) { + size_t const alpn_len = strlen(*alpn); + p = protocol_name_list; + while (p < protocol_name_list_end) { + protocol_name_len = *p++; + if (protocol_name_len == alpn_len && + memcmp(p, *alpn, alpn_len) == 0) { + ssl->alpn_chosen = *alpn; + return 0; + } + + p += protocol_name_len; + } + } + + /* If we get here, no match was found */ + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL, + MBEDTLS_ERR_SSL_NO_APPLICATION_PROTOCOL); + return MBEDTLS_ERR_SSL_NO_APPLICATION_PROTOCOL; +} + +int mbedtls_ssl_write_alpn_ext(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len) +{ + unsigned char *p = buf; + size_t protocol_name_len; + *out_len = 0; + + if (ssl->alpn_chosen == NULL) { + return 0; + } + + protocol_name_len = strlen(ssl->alpn_chosen); + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 7 + protocol_name_len); + + MBEDTLS_SSL_DEBUG_MSG(3, ("server side, 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, p, 0); + + *out_len = 7 + protocol_name_len; + + MBEDTLS_PUT_UINT16_BE(protocol_name_len + 3, p, 2); + MBEDTLS_PUT_UINT16_BE(protocol_name_len + 1, p, 4); + /* Note: the length of the chosen protocol has been checked to be less + * than 255 bytes in `mbedtls_ssl_conf_alpn_protocols`. + */ + p[6] = MBEDTLS_BYTE_0(protocol_name_len); + + memcpy(p + 7, ssl->alpn_chosen, protocol_name_len); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_ALPN); +#endif + + return 0; +} +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ + defined(MBEDTLS_SSL_SESSION_TICKETS) && \ + defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && \ + defined(MBEDTLS_SSL_CLI_C) +int mbedtls_ssl_session_set_hostname(mbedtls_ssl_session *session, + 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 (session->hostname != NULL) { + mbedtls_platform_zeroize(session->hostname, + strlen(session->hostname)); + mbedtls_free(session->hostname); + } + + /* Passing NULL as hostname shall clear the old one */ + if (hostname == NULL) { + session->hostname = NULL; + } else { + session->hostname = mbedtls_calloc(1, hostname_len + 1); + if (session->hostname == NULL) { + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } + + memcpy(session->hostname, hostname, hostname_len); + } + + return 0; +} +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 && + MBEDTLS_SSL_SESSION_TICKETS && + MBEDTLS_SSL_SERVER_NAME_INDICATION && + MBEDTLS_SSL_CLI_C */ + +#endif /* MBEDTLS_SSL_TLS_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls12_client.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls12_client.c new file mode 100644 index 0000000..890e9a9 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls12_client.c @@ -0,0 +1,3600 @@ +/* + * TLS 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) && defined(MBEDTLS_SSL_PROTO_TLS1_2) + +#include "mbedtls/platform.h" + +#include "mbedtls/ssl.h" +#include "ssl_client.h" +#include "ssl_misc.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" +#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \ + psa_to_ssl_errors, \ + psa_generic_status_to_mbedtls) +#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 + +#include "hash_info.h" + +#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 a 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 */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + +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 = 0; + + *olen = 0; + + /* Skip costly extension if we can't use EC J-PAKE anyway */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if (ssl->handshake->psa_pake_ctx_is_ok != 1) { + return 0; + } +#else + if (mbedtls_ecjpake_check(&ssl->handshake->ecjpake_ctx) != 0) { + return 0; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + 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")); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + ret = mbedtls_psa_ecjpake_write_round(&ssl->handshake->psa_pake_ctx, + p + 2, end - p - 2, &kkpp_len, + MBEDTLS_ECJPAKE_ROUND_ONE); + if (ret != 0) { + psa_destroy_key(ssl->handshake->psa_pake_password); + psa_pake_abort(&ssl->handshake->psa_pake_ctx); + MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_output", ret); + return ret; + } +#else + 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; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + 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; + + /* + * 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_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) { + 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) { + 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_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 */ + +int mbedtls_ssl_tls12_write_client_hello_exts(mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + int uses_ec, + size_t *out_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = buf; + size_t ext_len = 0; + + (void) ssl; + (void) end; + (void) uses_ec; + (void) ret; + (void) ext_len; + + *out_len = 0; + + /* 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, end, &ext_len)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_renegotiation_ext", ret); + return ret; + } + p += ext_len; +#endif + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if (uses_ec) { + if ((ret = ssl_write_supported_point_formats_ext(ssl, p, end, + &ext_len)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_supported_point_formats_ext", ret); + return ret; + } + p += ext_len; + } +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if ((ret = ssl_write_ecjpake_kkpp_ext(ssl, p, end, &ext_len)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_ecjpake_kkpp_ext", ret); + return ret; + } + p += ext_len; +#endif + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + if ((ret = ssl_write_cid_ext(ssl, p, end, &ext_len)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_cid_ext", ret); + return ret; + } + p += ext_len; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + if ((ret = ssl_write_max_fragment_length_ext(ssl, p, end, + &ext_len)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_max_fragment_length_ext", ret); + return ret; + } + p += ext_len; +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if ((ret = ssl_write_encrypt_then_mac_ext(ssl, p, end, &ext_len)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_encrypt_then_mac_ext", ret); + return ret; + } + p += ext_len; +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + if ((ret = ssl_write_extended_ms_ext(ssl, p, end, &ext_len)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_extended_ms_ext", ret); + return ret; + } + p += ext_len; +#endif + +#if defined(MBEDTLS_SSL_DTLS_SRTP) + if ((ret = ssl_write_use_srtp_ext(ssl, p, end, &ext_len)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_use_srtp_ext", ret); + return ret; + } + p += ext_len; +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if ((ret = ssl_write_session_ticket_ext(ssl, p, end, &ext_len)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_session_ticket_ext", ret); + return ret; + } + p += ext_len; +#endif + + *out_len = p - buf; + + 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_HANDSHAKE_FAILURE; + } + } 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_HANDSHAKE_FAILURE; + } + + 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_ILLEGAL_PARAMETER; + } + + 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; + + 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_UNSUPPORTED_EXTENSION; + } + + 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_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + 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_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + + 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_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + 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 || + 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_UNSUPPORTED_EXTENSION; + } + + ((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 || + 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_UNSUPPORTED_EXTENSION; + } + + ((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_UNSUPPORTED_EXTENSION; + } + + ((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_DECODE_ERROR; + } + 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_USE_PSA_CRYPTO) && \ + (defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C)) + ssl->handshake->ecdh_ctx.point_format = p[0]; +#endif /* !MBEDTLS_USE_PSA_CRYPTO && + ( MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C ) */ +#if !defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + mbedtls_ecjpake_set_point_format(&ssl->handshake->ecjpake_ctx, + p[0]); +#endif /* !MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + 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_HANDSHAKE_FAILURE; +} +#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 defined(MBEDTLS_USE_PSA_CRYPTO) + if ((ret = mbedtls_psa_ecjpake_read_round( + &ssl->handshake->psa_pake_ctx, buf, len, + MBEDTLS_ECJPAKE_ROUND_ONE)) != 0) { + psa_destroy_key(ssl->handshake->psa_pake_password); + psa_pake_abort(&ssl->handshake->psa_pake_ctx); + + MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_input round one", ret); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); + return ret; + } + + return 0; +#else + 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_USE_PSA_CRYPTO */ +} +#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_UNSUPPORTED_EXTENSION; + } + + /* + * 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_DECODE_ERROR; + } + + 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_DECODE_ERROR; + } + + 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_DECODE_ERROR; + } + + /* 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_HANDSHAKE_FAILURE; +} +#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_DECODE_ERROR; + } + + /* + * 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_DECODE_ERROR; + } + + 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_HANDSHAKE_FAILURE; + } + + /* 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_ILLEGAL_PARAMETER; + } +#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) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + const unsigned char *p = ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl); + uint16_t dtls_legacy_version; + +#if !defined(MBEDTLS_SSL_PROTO_TLS1_3) + uint8_t cookie_len; +#else + uint16_t cookie_len; +#endif + + 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_DECODE_ERROR; + } + + /* + * struct { + * ProtocolVersion server_version; + * opaque cookie<0..2^8-1>; + * } HelloVerifyRequest; + */ + MBEDTLS_SSL_DEBUG_BUF(3, "server version", p, 2); + dtls_legacy_version = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + + /* + * Since the RFC is not clear on this point, accept DTLS 1.0 (0xfeff) + * The DTLS 1.3 (current draft) renames ProtocolVersion server_version to + * legacy_version and locks the value of legacy_version to 0xfefd (DTLS 1.2) + */ + if (dtls_legacy_version != 0xfefd && dtls_legacy_version != 0xfeff) { + 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_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_DECODE_ERROR; + } + MBEDTLS_SSL_DEBUG_BUF(3, "cookie", p, cookie_len); + + mbedtls_free(ssl->handshake->cookie); + + ssl->handshake->cookie = mbedtls_calloc(1, cookie_len); + if (ssl->handshake->cookie == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("alloc failed (%d bytes)", cookie_len)); + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } + + memcpy(ssl->handshake->cookie, p, cookie_len); + ssl->handshake->cookie_len = cookie_len; + + /* Start over at ClientHello */ + ssl->state = MBEDTLS_SSL_CLIENT_HELLO; + ret = mbedtls_ssl_reset_checksum(ssl); + if (0 != ret) { + MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ssl_reset_checksum"), ret); + return ret; + } + + 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_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->cookie); + ssl->handshake->cookie = NULL; + ssl->handshake->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_DECODE_ERROR; + } + + /* + * 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, 2); + ssl->tls_version = mbedtls_ssl_read_version(buf, ssl->conf->transport); + ssl->session_negotiate->tls_version = ssl->tls_version; + + if (ssl->tls_version < ssl->conf->min_tls_version || + ssl->tls_version > ssl->conf->max_tls_version) { + MBEDTLS_SSL_DEBUG_MSG(1, + ( + "server version out of bounds - min: [0x%x], server: [0x%x], max: [0x%x]", + (unsigned) ssl->conf->min_tls_version, + (unsigned) ssl->tls_version, + (unsigned) ssl->conf->max_tls_version)); + + mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION); + + return MBEDTLS_ERR_SSL_BAD_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_DECODE_ERROR; + } + + 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_DECODE_ERROR; + } + } 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_DECODE_ERROR; + } + + /* ciphersuite (used later) */ + i = (buf[35 + n] << 8) | buf[36 + n]; + + /* + * Read and check compression + */ + comp = buf[37 + n]; + + if (comp != MBEDTLS_SSL_COMPRESS_NULL) { + 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->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->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[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_ILLEGAL_PARAMETER; + } + + if (ssl->conf->ciphersuite_list[i++] == + ssl->session_negotiate->ciphersuite) { + break; + } + } + + suite_info = mbedtls_ssl_ciphersuite_from_id( + ssl->session_negotiate->ciphersuite); + if (mbedtls_ssl_validate_ciphersuite(ssl, suite_info, ssl->tls_version, + ssl->tls_version) != 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_HANDSHAKE_FAILURE); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + + 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->tls_version == MBEDTLS_SSL_VERSION_TLS1_2) { + ssl->handshake->ecrs_enabled = 1; + } +#endif + + if (comp != MBEDTLS_SSL_COMPRESS_NULL) { + 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_ILLEGAL_PARAMETER; + } + + 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_DECODE_ERROR; + } + + 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_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_DECODE_ERROR; + } + } + + /* + * 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_HANDSHAKE_FAILURE; + } + + 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_dhm_get_bitlen(&ssl->handshake->dhm_ctx); + 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_HANDSHAKE_FAILURE; + } + + 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_USE_PSA_CRYPTO) +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_server_ecdh_params(mbedtls_ssl_context *ssl, + unsigned char **p, + unsigned char *end) +{ + uint16_t tls_id; + uint8_t ecpoint_len; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + psa_ecc_family_t ec_psa_family = 0; + size_t ec_bits = 0; + + /* + * struct { + * ECParameters curve_params; + * ECPoint public; + * } ServerECDHParams; + * + * 1 curve_type (must be "named_curve") + * 2..3 NamedCurve + * 4 ECPoint.len + * 5+ ECPoint contents + */ + if (end - *p < 4) { + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + /* First byte is curve_type; only named_curve is handled */ + if (*(*p)++ != MBEDTLS_ECP_TLS_NAMED_CURVE) { + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + + /* 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) { + MBEDTLS_SSL_DEBUG_MSG(2, + ("bad server key exchange message (ECDHE curve): %u", + (unsigned) tls_id)); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + + /* Convert EC's TLS ID to PSA key type. */ + if (mbedtls_ssl_get_psa_curve_info_from_tls_id(tls_id, &ec_psa_family, + &ec_bits) == PSA_ERROR_NOT_SUPPORTED) { + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + handshake->ecdh_psa_type = PSA_KEY_TYPE_ECC_KEY_PAIR(ec_psa_family); + handshake->ecdh_bits = ec_bits; + + /* Keep a copy of the peer's public key */ + ecpoint_len = *(*p)++; + if ((size_t) (end - *p) < ecpoint_len) { + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + if (ecpoint_len > sizeof(handshake->ecdh_psa_peerkey)) { + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + + memcpy(handshake->ecdh_psa_peerkey, *p, ecpoint_len); + handshake->ecdh_psa_peerkey_len = ecpoint_len; + *p += ecpoint_len; + + return 0; +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ +#else +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_check_server_ecdh_params(const mbedtls_ssl_context *ssl) +{ + uint16_t tls_id; + 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 + + tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(grp_id); + if (tls_id == 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + MBEDTLS_SSL_DEBUG_MSG(2, ("ECDH curve: %s", + mbedtls_ssl_get_curve_name_from_tls_id(tls_id))); + + if (mbedtls_ssl_check_curve(ssl, grp_id) != 0) { + 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_ECDH_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_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_HANDSHAKE_FAILURE; + } + + return ret; +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || \ + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || \ + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ +#endif /* !MBEDTLS_USE_PSA_CRYPTO */ +#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_DECODE_ERROR; + } + 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_DECODE_ERROR; + } + + /* + * Note: we currently ignore the PSK identity hint, as we only allow one + * PSK to be provisioned 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 = 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(p, ssl->conf->transport, + MBEDTLS_SSL_VERSION_TLS1_2); + + 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 (len_bytes == 2) { + MBEDTLS_PUT_UINT16_BE(*olen, ssl->out_msg, offset); + *olen += 2; + } + +#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_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 defined(MBEDTLS_USE_PSA_CRYPTO) + size_t olen = 0; + uint16_t tls_id = 0; + psa_ecc_family_t ecc_family; + + if (mbedtls_ssl_check_curve(ssl, peer_key->grp.id) != 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad server certificate (ECDH curve)")); + return MBEDTLS_ERR_SSL_BAD_CERTIFICATE; + } + + tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(peer_key->grp.id); + if (tls_id == 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("ECC group %u not suported", + peer_key->grp.id)); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + + /* If the above conversion to TLS ID was fine, then also this one will be, + so there is no need to check the return value here */ + mbedtls_ssl_get_psa_curve_info_from_tls_id(tls_id, &ecc_family, + &ssl->handshake->ecdh_bits); + + ssl->handshake->ecdh_psa_type = PSA_KEY_TYPE_ECC_KEY_PAIR(ecc_family); + + /* Store peer's public key in psa format. */ + ret = mbedtls_ecp_point_write_binary(&peer_key->grp, &peer_key->Q, + MBEDTLS_ECP_PF_UNCOMPRESSED, &olen, + ssl->handshake->ecdh_psa_peerkey, + MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH); + + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ecp_point_write_binary"), ret); + return ret; + } + + ssl->handshake->ecdh_psa_peerkey_len = olen; +#else + 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_CERTIFICATE; + } +#endif +#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_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + } /* 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_ILLEGAL_PARAMETER; + } + } else +#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_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_ILLEGAL_PARAMETER; + } + } 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) { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /* + * The first 3 bytes are: + * [0] MBEDTLS_ECP_TLS_NAMED_CURVE + * [1, 2] elliptic curve's TLS ID + * + * However since we only support secp256r1 for now, we check only + * that TLS ID here + */ + uint16_t read_tls_id = MBEDTLS_GET_UINT16_BE(p, 1); + uint16_t exp_tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id( + MBEDTLS_ECP_DP_SECP256R1); + + if (exp_tls_id == 0) { + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + } + + if ((*p != MBEDTLS_ECP_TLS_NAMED_CURVE) || + (read_tls_id != exp_tls_id)) { + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + + p += 3; + + if ((ret = mbedtls_psa_ecjpake_read_round( + &ssl->handshake->psa_pake_ctx, p, end - p, + MBEDTLS_ECJPAKE_ROUND_TWO)) != 0) { + psa_destroy_key(ssl->handshake->psa_pake_password); + psa_pake_abort(&ssl->handshake->psa_pake_ctx); + + MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_input round two", ret); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } +#else + 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_HANDSHAKE_FAILURE); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + } 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; + unsigned char hash[MBEDTLS_HASH_MAX_SIZE]; + + 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; + uint16_t sig_alg; + + 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 */ + + /* + * Handle the digitally-signed structure + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + sig_alg = MBEDTLS_GET_UINT16_BE(p, 0); + if (mbedtls_ssl_get_pk_type_and_md_alg_from_sig_alg( + sig_alg, &pk_alg, &md_alg) != 0 && + !mbedtls_ssl_sig_alg_is_offered(ssl, sig_alg) && + !mbedtls_ssl_sig_alg_is_supported(ssl, sig_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_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + p += 2; + + 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_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + + /* + * 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_DECODE_ERROR; + } + 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_DECODE_ERROR; + } + + MBEDTLS_SSL_DEBUG_BUF(3, "signature", p, sig_len); + + /* + * Compute the hash that has been signed + */ + 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 { + MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + MBEDTLS_SSL_DEBUG_BUF(3, "parameters hash", hash, hashlen); + + /* + * 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 defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + if (pk_alg == MBEDTLS_PK_RSASSA_PSS) { + mbedtls_pk_rsassa_pss_options rsassa_pss_options; + rsassa_pss_options.mgf1_hash_id = md_alg; + rsassa_pss_options.expected_salt_len = + mbedtls_hash_info_get_size(md_alg); + if (rsassa_pss_options.expected_salt_len == 0) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + ret = mbedtls_pk_verify_ext(pk_alg, &rsassa_pss_options, + peer_pk, + md_alg, hash, hashlen, + p, sig_len); + } else +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ + ret = mbedtls_pk_verify_restartable(peer_pk, + md_alg, hash, hashlen, p, sig_len, rs_ctx); + + if (ret != 0) { + int send_alert_msg = 1; +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + send_alert_msg = (ret != MBEDTLS_ERR_ECP_IN_PROGRESS); +#endif + if (send_alert_msg) { + 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; + size_t sig_alg_len; +#if defined(MBEDTLS_DEBUG_C) + unsigned char *sig_alg; + unsigned char *dn; +#endif + + 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->handshake->client_auth = + (ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE_REQUEST); + + MBEDTLS_SSL_DEBUG_MSG(3, ("got %s certificate request", + ssl->handshake->client_auth ? "a" : "no")); + + if (ssl->handshake->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_DECODE_ERROR; + } + 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_DECODE_ERROR; + } + + /* supported_signature_algorithms */ + sig_alg_len = ((buf[mbedtls_ssl_hs_hdr_len(ssl) + 1 + n] << 8) + | (buf[mbedtls_ssl_hs_hdr_len(ssl) + 2 + n])); + + /* + * 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_DECODE_ERROR; + } + +#if defined(MBEDTLS_DEBUG_C) + sig_alg = buf + mbedtls_ssl_hs_hdr_len(ssl) + 3 + n; + for (size_t i = 0; i < sig_alg_len; i += 2) { + MBEDTLS_SSL_DEBUG_MSG(3, + ("Supported Signature Algorithm found: %02x %02x", + sig_alg[i], sig_alg[i + 1])); + } +#endif + + n += 2 + sig_alg_len; + + /* 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_DECODE_ERROR; + } + +#if defined(MBEDTLS_DEBUG_C) + dn = buf + mbedtls_ssl_hs_hdr_len(ssl) + 3 + n - dn_len; + for (size_t i = 0, dni_len = 0; i < dn_len; i += 2 + dni_len) { + unsigned char *p = dn + i + 2; + mbedtls_x509_name name; + size_t asn1_len; + char s[MBEDTLS_X509_MAX_DN_NAME_SIZE]; + memset(&name, 0, sizeof(name)); + dni_len = MBEDTLS_GET_UINT16_BE(dn + i, 0); + if (dni_len > dn_len - i - 2 || + mbedtls_asn1_get_tag(&p, p + dni_len, &asn1_len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0 || + mbedtls_x509_get_name(&p, p + asn1_len, &name) != 0) { + 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_DECODE_ERROR; + } + MBEDTLS_SSL_DEBUG_MSG(3, + ("DN hint: %.*s", + mbedtls_x509_dn_gets(s, sizeof(s), &name), s)); + mbedtls_asn1_free_named_data_list_shallow(name.next); + } +#endif + +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_DECODE_ERROR; + } + + 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 = mbedtls_dhm_get_len(&ssl->handshake->dhm_ctx); + + MBEDTLS_PUT_UINT16_BE(content_len, ssl->out_msg, 4); + header_len = 6; + + ret = mbedtls_dhm_make_public(&ssl->handshake->dhm_ctx, + (int) mbedtls_dhm_get_len(&ssl->handshake->dhm_ctx), + &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_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 defined(MBEDTLS_USE_PSA_CRYPTO) + 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; + + 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. + * The export format is an ECPoint structure as expected by TLS, + * but we just need to add a length byte before that. */ + unsigned char *own_pubkey = ssl->out_msg + header_len + 1; + unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; + size_t own_pubkey_max_len = (size_t) (end - own_pubkey); + size_t own_pubkey_len; + + status = psa_export_public_key(handshake->ecdh_psa_privkey, + own_pubkey, own_pubkey_max_len, + &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; + } + + ssl->out_msg[header_len] = (unsigned char) own_pubkey_len; + content_len = own_pubkey_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 + /* + * 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); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + } 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_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK) { + 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; + + /* + * opaque psk_identity<0..2^16-1>; + */ + if (mbedtls_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; + } + + /* uint16 to store content length */ + const size_t content_len_size = 2; + + header_len = 4; + + if (header_len + content_len_size + ssl->conf->psk_identity_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; + } + + unsigned char *p = ssl->out_msg + header_len; + + *p++ = MBEDTLS_BYTE_1(ssl->conf->psk_identity_len); + *p++ = MBEDTLS_BYTE_0(ssl->conf->psk_identity_len); + header_len += content_len_size; + + memcpy(p, ssl->conf->psk_identity, + ssl->conf->psk_identity_len); + p += ssl->conf->psk_identity_len; + + header_len += ssl->conf->psk_identity_len; + + 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 PSA_TO_MBEDTLS_ERR(status); + } + + /* Export the public part of the ECDH private key from PSA. + * The export format is an ECPoint structure as expected by TLS, + * but we just need to add a length byte before that. */ + unsigned char *own_pubkey = p + 1; + unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; + size_t own_pubkey_max_len = (size_t) (end - own_pubkey); + size_t own_pubkey_len = 0; + + status = psa_export_public_key(handshake->ecdh_psa_privkey, + own_pubkey, own_pubkey_max_len, + &own_pubkey_len); + if (status != PSA_SUCCESS) { + psa_destroy_key(handshake->ecdh_psa_privkey); + handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; + return PSA_TO_MBEDTLS_ERR(status); + } + + *p = (unsigned char) own_pubkey_len; + content_len = own_pubkey_len + 1; + + /* As RFC 5489 section 2, the premaster secret is formed as follows: + * - a uint16 containing the length (in octets) of the ECDH computation + * - the octet string produced by the ECDH computation + * - a uint16 containing the length (in octets) of the PSK + * - the PSK itself + */ + unsigned char *pms = ssl->handshake->premaster; + const unsigned char * const pms_end = pms + + sizeof(ssl->handshake->premaster); + /* uint16 to store length (in octets) of the ECDH computation */ + const size_t zlen_size = 2; + size_t zlen = 0; + + /* Perform ECDH computation after the uint16 reserved for the length */ + status = psa_raw_key_agreement(PSA_ALG_ECDH, + handshake->ecdh_psa_privkey, + handshake->ecdh_psa_peerkey, + handshake->ecdh_psa_peerkey_len, + pms + zlen_size, + pms_end - (pms + zlen_size), + &zlen); + + destruction_status = psa_destroy_key(handshake->ecdh_psa_privkey); + handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; + + if (status != PSA_SUCCESS) { + return PSA_TO_MBEDTLS_ERR(status); + } else if (destruction_status != PSA_SUCCESS) { + return PSA_TO_MBEDTLS_ERR(destruction_status); + } + + /* Write the ECDH computation length before the ECDH computation */ + MBEDTLS_PUT_UINT16_BE(zlen, pms, 0); + pms += zlen_size + zlen; + } else +#endif /* MBEDTLS_USE_PSA_CRYPTO && + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_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 (mbedtls_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 ((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) { + /* + * ClientDiffieHellmanPublic public (DHM send G^X mod P) + */ + content_len = mbedtls_dhm_get_len(&ssl->handshake->dhm_ctx); + + 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_dhm_get_len(&ssl->handshake->dhm_ctx), + &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; + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + unsigned char *pms = ssl->handshake->premaster; + unsigned char *pms_end = pms + sizeof(ssl->handshake->premaster); + size_t pms_len; + + /* Write length only when we know the actual value */ + if ((ret = mbedtls_dhm_calc_secret(&ssl->handshake->dhm_ctx, + pms + 2, pms_end - (pms + 2), &pms_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(pms_len, pms, 0); + pms += 2 + pms_len; + + MBEDTLS_SSL_DEBUG_MPI(3, "DHM: K ", &ssl->handshake->dhm_ctx.K); +#endif + } else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if !defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK) { + /* + * 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_USE_PSA_CRYPTO && 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) + 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; + } +#endif /* !MBEDTLS_USE_PSA_CRYPTO */ + } 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; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + unsigned char *out_p = ssl->out_msg + header_len; + unsigned char *end_p = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN - + header_len; + ret = mbedtls_psa_ecjpake_write_round(&ssl->handshake->psa_pake_ctx, + out_p, end_p - out_p, &content_len, + MBEDTLS_ECJPAKE_ROUND_TWO); + if (ret != 0) { + psa_destroy_key(ssl->handshake->psa_pake_password); + psa_pake_abort(&ssl->handshake->psa_pake_ctx); + MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_output", ret); + return ret; + } +#else + 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; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + } 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; +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t out_buf_len = ssl->out_buf_len - (ssl->out_msg - ssl->out_buf); +#else + size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN - (ssl->out_msg - ssl->out_buf); +#endif + + 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->handshake->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 + + ret = ssl->handshake->calc_verify(ssl, hash, &hashlen); + if (0 != ret) { + MBEDTLS_SSL_DEBUG_RET(1, ("calc_verify"), ret); + return ret; + } + + /* + * 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; + +#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, + out_buf_len - 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_DECODE_ERROR; + } + + 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_DECODE_ERROR; + } + + 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; + + /* 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_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 = mbedtls_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_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 && MBEDTLS_SSL_PROTO_TLS1_2 */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls12_server.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls12_server.c new file mode 100644 index 0000000..631331d --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls12_server.c @@ -0,0 +1,4341 @@ +/* + * TLS 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) && defined(MBEDTLS_SSL_PROTO_TLS1_2) + +#include "mbedtls/platform.h" + +#include "mbedtls/ssl.h" +#include "ssl_misc.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 "hash_info.h" + +#include + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \ + psa_to_ssl_errors, \ + psa_generic_status_to_mbedtls) +#endif + +#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_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 defined(MBEDTLS_USE_PSA_CRYPTO) + if (!mbedtls_svc_key_id_is_null(conf->psk_opaque)) { + return 1; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + if (conf->psk != NULL && conf->psk_len != 0) { + return 1; + } + + return 0; +} +#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_HANDSHAKE_FAILURE; + } + } 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_HANDSHAKE_FAILURE; + } + + ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; + } + + return 0; +} + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +/* + * Function for parsing a supported groups (TLS 1.3) or supported elliptic + * curves (TLS 1.2) extension. + * + * The "extension_data" field of a supported groups extension contains a + * "NamedGroupList" value (TLS 1.3 RFC8446): + * enum { + * secp256r1(0x0017), secp384r1(0x0018), secp521r1(0x0019), + * x25519(0x001D), x448(0x001E), + * ffdhe2048(0x0100), ffdhe3072(0x0101), ffdhe4096(0x0102), + * ffdhe6144(0x0103), ffdhe8192(0x0104), + * ffdhe_private_use(0x01FC..0x01FF), + * ecdhe_private_use(0xFE00..0xFEFF), + * (0xFFFF) + * } NamedGroup; + * struct { + * NamedGroup named_group_list<2..2^16-1>; + * } NamedGroupList; + * + * The "extension_data" field of a supported elliptic curves extension contains + * a "NamedCurveList" value (TLS 1.2 RFC 8422): + * enum { + * deprecated(1..22), + * secp256r1 (23), secp384r1 (24), secp521r1 (25), + * x25519(29), x448(30), + * reserved (0xFE00..0xFEFF), + * deprecated(0xFF01..0xFF02), + * (0xFFFF) + * } NamedCurve; + * struct { + * NamedCurve named_curve_list<2..2^16-1> + * } NamedCurveList; + * + * The TLS 1.3 supported groups extension was defined to be a compatible + * generalization of the TLS 1.2 supported elliptic curves extension. They both + * share the same extension identifier. + * + * DHE groups are not supported yet. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_supported_groups_ext(mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len) +{ + size_t list_size, our_size; + const unsigned char *p; + uint16_t *curves_tls_id; + + 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_DECODE_ERROR; + } + 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_DECODE_ERROR; + } + + /* Should never happen unless client duplicates the extension */ + if (ssl->handshake->curves_tls_id != 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_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + + /* 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_tls_id = mbedtls_calloc(our_size, + sizeof(*curves_tls_id))) == 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_tls_id = curves_tls_id; + + p = buf + 2; + while (list_size > 0 && our_size > 1) { + uint16_t curr_tls_id = MBEDTLS_GET_UINT16_BE(p, 0); + + if (mbedtls_ssl_get_ecp_group_id_from_tls_id(curr_tls_id) != + MBEDTLS_ECP_DP_NONE) { + *curves_tls_id++ = curr_tls_id; + 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_DECODE_ERROR; + } + 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_USE_PSA_CRYPTO) && \ + (defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C)) + ssl->handshake->ecdh_ctx.point_format = p[0]; +#endif /* !MBEDTLS_USE_PSA_CRYPTO && + ( MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C ) */ +#if !defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + mbedtls_ecjpake_set_point_format(&ssl->handshake->ecjpake_ctx, + p[0]); +#endif /* !MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + 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 defined(MBEDTLS_USE_PSA_CRYPTO) + if (ssl->handshake->psa_pake_ctx_is_ok != 1) +#else + if (mbedtls_ecjpake_check(&ssl->handshake->ecjpake_ctx) != 0) +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + { + MBEDTLS_SSL_DEBUG_MSG(3, ("skip ecjpake kkpp extension")); + return 0; + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if ((ret = mbedtls_psa_ecjpake_read_round( + &ssl->handshake->psa_pake_ctx, buf, len, + MBEDTLS_ECJPAKE_ROUND_ONE)) != 0) { + psa_destroy_key(ssl->handshake->psa_pake_password); + psa_pake_abort(&ssl->handshake->psa_pake_ctx); + + MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_input round one", ret); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); + + return ret; + } +#else + 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; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + /* 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_ILLEGAL_PARAMETER; + } + + 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_ILLEGAL_PARAMETER; + } + + /* + * 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_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + 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_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + /* 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_ILLEGAL_PARAMETER; + } + + 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_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_DECODE_ERROR; + } + + ((void) buf); + + if (ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED) { + 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_DECODE_ERROR; + } + + ((void) buf); + + if (ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED) { + 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_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_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + 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_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + /* + * 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_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + /* 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, + uint16_t *curves_tls_id) +{ + uint16_t *curr_tls_id = curves_tls_id; + mbedtls_ecp_group_id grp_id = mbedtls_pk_ec(*pk)->grp.id; + mbedtls_ecp_group_id curr_grp_id; + + while (*curr_tls_id != 0) { + curr_grp_id = mbedtls_ssl_get_ecp_group_id_from_tls_id(*curr_tls_id); + if (curr_grp_id == grp_id) { + return 0; + } + curr_tls_id++; + } + + 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; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_algorithm_t pk_alg = + mbedtls_ssl_get_ciphersuite_sig_pk_psa_alg(ciphersuite_info); + psa_key_usage_t pk_usage = + mbedtls_ssl_get_ciphersuite_sig_pk_psa_usage(ciphersuite_info); +#else + mbedtls_pk_type_t pk_alg = + mbedtls_ssl_get_ciphersuite_sig_pk_alg(ciphersuite_info); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + 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; + + int pk_alg_is_none = 0; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + pk_alg_is_none = (pk_alg == PSA_ALG_NONE); +#else + pk_alg_is_none = (pk_alg == MBEDTLS_PK_NONE); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if (pk_alg_is_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); + + int key_type_matches = 0; +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + key_type_matches = ((ssl->conf->f_async_sign_start != NULL || + ssl->conf->f_async_decrypt_start != NULL || + mbedtls_pk_can_do_ext(cur->key, pk_alg, pk_usage)) && + mbedtls_pk_can_do_ext(&cur->cert->pk, pk_alg, pk_usage)); +#else + key_type_matches = ( + mbedtls_pk_can_do_ext(cur->key, pk_alg, pk_usage)); +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ +#else + key_type_matches = mbedtls_pk_can_do(&cur->cert->pk, pk_alg); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if (!key_type_matches) { + 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_tls_id) != 0) { + MBEDTLS_SSL_DEBUG_MSG(3, ("certificate mismatch: elliptic curve")); + continue; + } +#endif + + /* If we get there, we got a winner */ + break; + } + + /* 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_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_tls_version > ssl->tls_version || + suite_info->max_tls_version < ssl->tls_version) { + MBEDTLS_SSL_DEBUG_MSG(3, ("ciphersuite mismatch: version")); + return 0; + } + +#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_tls_id == NULL || + ssl->handshake->curves_tls_id[0] == 0)) { + 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_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 + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + /* If the ciphersuite requires signing, check whether + * a suitable hash algorithm is present. */ + sig_type = mbedtls_ssl_get_ciphersuite_sig_alg(suite_info); + if (sig_type != MBEDTLS_PK_NONE && + mbedtls_ssl_tls12_get_preferred_hash_for_sig_alg( + ssl, mbedtls_ssl_sig_from_pk_alg(sig_type)) == MBEDTLS_SSL_HASH_NONE) { + MBEDTLS_SSL_DEBUG_MSG(3, ("ciphersuite mismatch: no suitable hash algorithm " + "for signature algorithm %u", (unsigned) sig_type)); + return 0; + } + +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + + *ciphersuite_info = suite_info; + return 0; +} + +/* 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; + + /* 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_KEY_EXCHANGE_WITH_CERT_ENABLED) + int sig_hash_alg_ext_present = 0; +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse client hello")); + + int renegotiating; + +#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. + */ + renegotiating = 0; +#if defined(MBEDTLS_SSL_RENEGOTIATION) + renegotiating = (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE); +#endif + if (!renegotiating) { + 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; + + MBEDTLS_SSL_DEBUG_BUF(4, "record header", buf, mbedtls_ssl_in_hdr_len(ssl)); + + /* + * 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, 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_UNEXPECTED_MESSAGE; + } + + MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, message len.: %d", + (ssl->in_len[0] << 8) | ssl->in_len[1])); + + MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, protocol version: [%d:%d]", + buf[1], buf[2])); + + /* 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_ILLEGAL_PARAMETER; + } + + memcpy(&ssl->cur_out_ctr[2], ssl->in_ctr + 2, + sizeof(ssl->cur_out_ctr) - 2); + +#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_ILLEGAL_PARAMETER; + } + + 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); + + ret = ssl->handshake->update_checksum(ssl, buf, msg_len); + if (0 != ret) { + MBEDTLS_SSL_DEBUG_RET(1, ("update_checksum"), ret); + return ret; + } + + /* + * 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_DECODE_ERROR; + } + + 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_UNEXPECTED_MESSAGE; + } + { + size_t handshake_len = MBEDTLS_GET_UINT24_BE(buf, 1); + MBEDTLS_SSL_DEBUG_MSG(3, ("client hello v3, handshake len.: %u", + (unsigned) handshake_len)); + + /* The record layer has a record size limit of 2^14 - 1 and + * fragmentation is not supported, so buf[1] should be zero. */ + if (buf[1] != 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message: %u != 0", + (unsigned) buf[1])); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + /* We don't support fragmentation of ClientHello (yet?) */ + if (msg_len != mbedtls_ssl_hs_hdr_len(ssl) + handshake_len) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message: %u != %u + %u", + (unsigned) msg_len, + (unsigned) mbedtls_ssl_hs_hdr_len(ssl), + (unsigned) handshake_len)); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + } + +#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_DECODE_ERROR; + } + + 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 + */ + size_t fragment_offset, fragment_length, length; + fragment_offset = MBEDTLS_GET_UINT24_BE(ssl->in_msg, 6); + fragment_length = MBEDTLS_GET_UINT24_BE(ssl->in_msg, 9); + length = MBEDTLS_GET_UINT24_BE(ssl->in_msg, 1); + MBEDTLS_SSL_DEBUG_MSG( + 4, ("fragment_offset=%u fragment_length=%u length=%u", + (unsigned) fragment_offset, (unsigned) fragment_length, + (unsigned) length)); + if (fragment_offset != 0 || length != fragment_length) { + 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_DECODE_ERROR; + } + + /* + * Check and save the protocol version + */ + MBEDTLS_SSL_DEBUG_BUF(3, "client hello, version", buf, 2); + + ssl->tls_version = mbedtls_ssl_read_version(buf, ssl->conf->transport); + ssl->session_negotiate->tls_version = ssl->tls_version; + + if (ssl->tls_version != MBEDTLS_SSL_VERSION_TLS1_2) { + MBEDTLS_SSL_DEBUG_MSG(1, ("server only supports TLS 1.2")); + mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION); + return MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION; + } + + /* + * 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_DECODE_ERROR; + } + + 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_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + 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->cookie_verify_result = 1; + } else { + MBEDTLS_SSL_DEBUG_MSG(2, ("cookie verification passed")); + ssl->handshake->cookie_verify_result = 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_DECODE_ERROR; + } + + 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_DECODE_ERROR; + } + + MBEDTLS_SSL_DEBUG_BUF(3, "client hello, ciphersuitelist", + buf + ciph_offset + 2, ciph_len); + + /* + * Check the compression algorithm's length. + * The list contents are ignored because implementing + * MBEDTLS_SSL_COMPRESS_NULL is mandatory and is the only + * option supported by Mbed TLS. + */ + 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_DECODE_ERROR; + } + + MBEDTLS_SSL_DEBUG_BUF(3, "client hello, compression", + buf + comp_offset + 1, comp_len); + + /* + * 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_DECODE_ERROR; + } + + 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_DECODE_ERROR; + } + } 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_DECODE_ERROR; + } + 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_DECODE_ERROR; + } + switch (ext_id) { +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + case MBEDTLS_TLS_EXT_SERVERNAME: + MBEDTLS_SSL_DEBUG_MSG(3, ("found ServerName extension")); + ret = mbedtls_ssl_parse_server_name_ext(ssl, ext + 4, + 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_KEY_EXCHANGE_WITH_CERT_ENABLED) + case MBEDTLS_TLS_EXT_SIG_ALG: + MBEDTLS_SSL_DEBUG_MSG(3, ("found signature_algorithms extension")); + + ret = mbedtls_ssl_parse_sig_alg_ext(ssl, ext + 4, ext + 4 + ext_size); + if (ret != 0) { + return ret; + } + + sig_hash_alg_ext_present = 1; + break; +#endif /* 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_GROUPS: + MBEDTLS_SSL_DEBUG_MSG(3, ("found supported elliptic curves extension")); + + ret = ssl_parse_supported_groups_ext(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_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_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")); + + 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 = mbedtls_ssl_parse_alpn_ext(ssl, ext + 4, + 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_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) { + uint16_t *received_sig_algs = ssl->handshake->received_sig_algs; + const uint16_t default_sig_algs[] = { +#if defined(MBEDTLS_ECDSA_C) + MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, + MBEDTLS_SSL_HASH_SHA1), +#endif +#if defined(MBEDTLS_RSA_C) + MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, + MBEDTLS_SSL_HASH_SHA1), +#endif + MBEDTLS_TLS_SIG_NONE + }; + + MBEDTLS_STATIC_ASSERT(sizeof(default_sig_algs) / sizeof(default_sig_algs[0]) + <= MBEDTLS_RECEIVED_SIG_ALGS_SIZE, + "default_sig_algs is too big"); + + memcpy(received_sig_algs, default_sig_algs, sizeof(default_sig_algs)); + } + +#endif /* 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_HANDSHAKE_FAILURE; + } +#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_HANDSHAKE_FAILURE; + } + + /* + * Server certification selection (after processing TLS extensions) + */ + if (ssl->conf->f_cert_cb && (ret = ssl->conf->f_cert_cb(ssl)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "f_cert_cb", ret); + return ret; + } +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + ssl->handshake->sni_name = NULL; + ssl->handshake->sni_name_len = 0; +#endif + + /* + * 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 + * or certificate from server certificate selection callback.) + */ + got_common_suite = 0; + ciphersuites = ssl->conf->ciphersuite_list; + ciphersuite_info = NULL; + + if (ssl->conf->respect_cli_pref == MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_CLIENT) { + for (j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2) { + for (i = 0; ciphersuites[i] != 0; i++) { + 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; + } + } + } + } else { + for (i = 0; ciphersuites[i] != 0; i++) { + for (j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2) { + 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_HANDSHAKE_FAILURE; + } 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_HANDSHAKE_FAILURE; + } + +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_KEY_EXCHANGE_WITH_CERT_ENABLED) + mbedtls_pk_type_t sig_alg = mbedtls_ssl_get_ciphersuite_sig_alg(ciphersuite_info); + if (sig_alg != MBEDTLS_PK_NONE) { + unsigned int sig_hash = mbedtls_ssl_tls12_get_preferred_hash_for_sig_alg( + ssl, mbedtls_ssl_sig_from_pk_alg(sig_alg)); + MBEDTLS_SSL_DEBUG_MSG(3, ("client hello v3, signature_algorithm ext: %u", + sig_hash)); + } 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_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")); + + /* + * 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_SOME_SUITES_USE_CBC_ETM) +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; + + /* + * 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." + */ + suite = mbedtls_ssl_ciphersuite_from_id( + ssl->session_negotiate->ciphersuite); + if (suite == NULL) { + ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_DISABLED; + } else { + mbedtls_ssl_mode_t ssl_mode = + mbedtls_ssl_get_mode_from_ciphersuite( + ssl->session_negotiate->encrypt_then_mac, + suite); + + if (ssl_mode != MBEDTLS_SSL_MODE_CBC_ETM) { + 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_SOME_SUITES_USE_CBC_ETM */ + +#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) { + *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; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + ret = mbedtls_psa_ecjpake_write_round(&ssl->handshake->psa_pake_ctx, + p + 2, end - p - 2, &kkpp_len, + MBEDTLS_ECJPAKE_ROUND_ONE); + if (ret != 0) { + psa_destroy_key(ssl->handshake->psa_pake_password); + psa_pake_abort(&ssl->handshake->psa_pake_ctx); + MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_output", ret); + return; + } +#else + 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; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + MBEDTLS_PUT_UINT16_BE(kkpp_len, p, 0); + p += 2; + + *olen = kkpp_len + 4; +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#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(p, ssl->conf->transport, ssl->tls_version); + 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); + + ret = ssl->conf->f_get_cache(ssl->conf->p_cache, + session->id, + session->id_len, + &session_tmp); + if (ret != 0) { + goto exit; + } + + if (session->ciphersuite != session_tmp.ciphersuite) { + /* 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->cookie_verify_result != 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(p, ssl->conf->transport, ssl->tls_version); + 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(MBEDTLS_SSL_COMPRESS_NULL); + + 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) MBEDTLS_SSL_COMPRESS_NULL)); + + /* + * 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_DTLS_CONNECTION_ID) + ssl_write_cid_ext(ssl, p + 2 + ext_len, &olen); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) + 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) + const mbedtls_ssl_ciphersuite_t *suite = + mbedtls_ssl_ciphersuite_from_id(ssl->session_negotiate->ciphersuite); + if (suite != NULL && mbedtls_ssl_ciphersuite_uses_ec(suite)) { + 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) + unsigned char *end = buf + MBEDTLS_SSL_OUT_CONTENT_LEN - 4; + if ((ret = mbedtls_ssl_write_alpn_ext(ssl, p + 2 + ext_len, end, &olen)) + != 0) { + return ret; + } + + 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; + } + + 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; + + /* + * 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; + */ + const uint16_t *sig_alg = mbedtls_ssl_get_sig_algs(ssl); + if (sig_alg == NULL) { + return MBEDTLS_ERR_SSL_BAD_CONFIG; + } + + for (; *sig_alg != MBEDTLS_TLS_SIG_NONE; sig_alg++) { + unsigned char hash = MBEDTLS_BYTE_1(*sig_alg); + + if (mbedtls_ssl_set_calc_verify_md(ssl, hash)) { + continue; + } + if (!mbedtls_ssl_sig_alg_is_supported(ssl, *sig_alg)) { + continue; + } + + /* Write elements at offsets starting from 1 (offset 0 is for the + * length). Thus the offset of each element is the length of the + * partial list including that element. */ + sa_len += 2; + MBEDTLS_PUT_UINT16_BE(*sig_alg, p, sa_len); + + } + + /* Fill in list length. */ + MBEDTLS_PUT_UINT16_BE(sa_len, p, 0); + sa_len += 2; + p += sa_len; + + /* + * 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_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if (ssl->handshake->dn_hints != NULL) { + crt = ssl->handshake->dn_hints; + } else +#endif + if (ssl->conf->dn_hints != NULL) { + crt = ssl->conf->dn_hints; + } else +#endif +#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_USE_PSA_CRYPTO) && \ + (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; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + unsigned char buf[ + PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)]; + psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT; + uint16_t tls_id = 0; + psa_ecc_family_t ecc_family; + size_t key_len; + mbedtls_pk_context *pk; + mbedtls_ecp_keypair *key; + + pk = mbedtls_ssl_own_key(ssl); + + if (pk == NULL) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + switch (mbedtls_pk_get_type(pk)) { + case MBEDTLS_PK_OPAQUE: + if (!mbedtls_pk_can_do(pk, MBEDTLS_PK_ECKEY)) { + return MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH; + } + + ssl->handshake->ecdh_psa_privkey = + *((mbedtls_svc_key_id_t *) pk->pk_ctx); + + /* Key should not be destroyed in the TLS library */ + ssl->handshake->ecdh_psa_privkey_is_external = 1; + + status = psa_get_key_attributes(ssl->handshake->ecdh_psa_privkey, + &key_attributes); + if (status != PSA_SUCCESS) { + ssl->handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; + return PSA_TO_MBEDTLS_ERR(status); + } + + ssl->handshake->ecdh_psa_type = psa_get_key_type(&key_attributes); + ssl->handshake->ecdh_bits = psa_get_key_bits(&key_attributes); + + psa_reset_key_attributes(&key_attributes); + + ret = 0; + break; + case MBEDTLS_PK_ECKEY: + case MBEDTLS_PK_ECKEY_DH: + case MBEDTLS_PK_ECDSA: + key = mbedtls_pk_ec(*pk); + if (key == NULL) { + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(key->grp.id); + if (tls_id == 0) { + /* This elliptic curve is not supported */ + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + + /* If the above conversion to TLS ID was fine, then also this one will + be, so there is no need to check the return value here */ + mbedtls_ssl_get_psa_curve_info_from_tls_id(tls_id, &ecc_family, + &ssl->handshake->ecdh_bits); + + ssl->handshake->ecdh_psa_type = PSA_KEY_TYPE_ECC_KEY_PAIR(ecc_family); + + 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, + PSA_KEY_TYPE_ECC_KEY_PAIR(ssl->handshake->ecdh_psa_type)); + psa_set_key_bits(&key_attributes, ssl->handshake->ecdh_bits); + + key_len = PSA_BITS_TO_BYTES(key->grp.pbits); + ret = mbedtls_ecp_write_key(key, buf, key_len); + if (ret != 0) { + goto cleanup; + } + + status = psa_import_key(&key_attributes, buf, key_len, + &ssl->handshake->ecdh_psa_privkey); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + goto cleanup; + } + + ret = 0; + break; + default: + ret = MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH; + } + +cleanup: + mbedtls_platform_zeroize(buf, sizeof(buf)); + + return ret; +} +#elif 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_pk_context *private_key = mbedtls_ssl_own_key(ssl); + if (private_key == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("got no server private key")); + return MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED; + } + + if (!mbedtls_pk_can_do(private_key, MBEDTLS_PK_ECKEY)) { + 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(*mbedtls_ssl_own_key(ssl)), + 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 */ + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t out_buf_len = ssl->out_buf_len - (ssl->out_msg - ssl->out_buf); +#else + size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN - (ssl->out_msg - ssl->out_buf); +#endif +#endif + + 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; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + unsigned char *out_p = ssl->out_msg + ssl->out_msglen; + unsigned char *end_p = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN - + ssl->out_msglen; + size_t output_offset = 0; + size_t output_len = 0; + + /* + * The first 3 bytes are: + * [0] MBEDTLS_ECP_TLS_NAMED_CURVE + * [1, 2] elliptic curve's TLS ID + * + * However since we only support secp256r1 for now, we hardcode its + * TLS ID here + */ + uint16_t tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id( + MBEDTLS_ECP_DP_SECP256R1); + if (tls_id == 0) { + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + } + *out_p = MBEDTLS_ECP_TLS_NAMED_CURVE; + MBEDTLS_PUT_UINT16_BE(tls_id, out_p, 1); + output_offset += 3; + + ret = mbedtls_psa_ecjpake_write_round(&ssl->handshake->psa_pake_ctx, + out_p + output_offset, + end_p - out_p - output_offset, &output_len, + MBEDTLS_ECJPAKE_ROUND_TWO); + if (ret != 0) { + psa_destroy_key(ssl->handshake->psa_pake_password); + psa_pake_abort(&ssl->handshake->psa_pake_ctx); + MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_output", ret); + return ret; + } + + output_offset += output_len; + ssl->out_msglen += output_offset; +#else + 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_USE_PSA_CRYPTO */ + } +#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_dhm_get_len(&ssl->handshake->dhm_ctx), + 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; + */ + uint16_t *curr_tls_id = ssl->handshake->curves_tls_id; + const uint16_t *group_list = mbedtls_ssl_get_groups(ssl); + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + /* Match our preference list against the offered curves */ + if ((group_list == NULL) || (curr_tls_id == NULL)) { + return MBEDTLS_ERR_SSL_BAD_CONFIG; + } + for (; *group_list != 0; group_list++) { + for (curr_tls_id = ssl->handshake->curves_tls_id; + *curr_tls_id != 0; curr_tls_id++) { + if (*curr_tls_id == *group_list) { + goto curve_matching_done; + } + } + } + +curve_matching_done: + if (*curr_tls_id == 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("no matching curve for ECDHE")); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + + MBEDTLS_SSL_DEBUG_MSG(2, ("ECDHE curve: %s", + mbedtls_ssl_get_curve_name_from_tls_id(*curr_tls_id))); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status = PSA_ERROR_GENERIC_ERROR; + psa_key_attributes_t key_attributes; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + uint8_t *p = ssl->out_msg + ssl->out_msglen; + const size_t header_size = 4; // curve_type(1), namedcurve(2), + // data length(1) + const size_t data_length_size = 1; + psa_ecc_family_t ec_psa_family = 0; + size_t ec_bits = 0; + + MBEDTLS_SSL_DEBUG_MSG(1, ("Perform PSA-based ECDH computation.")); + + /* Convert EC's TLS ID to PSA key type. */ + if (mbedtls_ssl_get_psa_curve_info_from_tls_id(*curr_tls_id, + &ec_psa_family, + &ec_bits) == PSA_ERROR_NOT_SUPPORTED) { + MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid ecc group parse.")); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + handshake->ecdh_psa_type = PSA_KEY_TYPE_ECC_KEY_PAIR(ec_psa_family); + handshake->ecdh_bits = ec_bits; + + 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); + + /* + * ECParameters curve_params + * + * First byte is curve_type, always named_curve + */ + *p++ = MBEDTLS_ECP_TLS_NAMED_CURVE; + + /* + * Next two bytes are the namedcurve value + */ + MBEDTLS_PUT_UINT16_BE(*curr_tls_id, p, 0); + p += 2; + + /* Generate ECDH private key. */ + status = psa_generate_key(&key_attributes, + &handshake->ecdh_psa_privkey); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_generate_key", ret); + return ret; + } + + /* + * ECPoint public + * + * First byte is data length. + * It will be filled later. p holds now the data length location. + */ + + /* Export the public part of the ECDH private key from PSA. + * Make one byte space for the length. + */ + unsigned char *own_pubkey = p + data_length_size; + + size_t own_pubkey_max_len = (size_t) (MBEDTLS_SSL_OUT_CONTENT_LEN + - (own_pubkey - ssl->out_msg)); + + status = psa_export_public_key(handshake->ecdh_psa_privkey, + own_pubkey, own_pubkey_max_len, + &len); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_export_public_key", ret); + (void) psa_destroy_key(handshake->ecdh_psa_privkey); + handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; + return ret; + } + + /* Store the length of the exported public key. */ + *p = (uint8_t) len; + + /* Determine full message length. */ + len += header_size; +#else + mbedtls_ecp_group_id curr_grp_id = + mbedtls_ssl_get_ecp_group_id_from_tls_id(*curr_tls_id); + + if ((ret = mbedtls_ecdh_setup(&ssl->handshake->ecdh_ctx, + curr_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; + } + + MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Q); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) + dig_signed = ssl->out_msg + ssl->out_msglen; +#endif + + ssl->out_msglen += len; + } +#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)) { + if (dig_signed == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + size_t dig_signed_len = ssl->out_msg + ssl->out_msglen - dig_signed; + size_t hashlen = 0; + unsigned char hash[MBEDTLS_HASH_MAX_SIZE]; + + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* + * 2.1: Choose hash algorithm: + * For TLS 1.2, obey signature-hash-algorithm extension + * to choose appropriate hash. + */ + + mbedtls_pk_type_t sig_alg = + mbedtls_ssl_get_ciphersuite_sig_pk_alg(ciphersuite_info); + + unsigned int sig_hash = + mbedtls_ssl_tls12_get_preferred_hash_for_sig_alg( + ssl, mbedtls_ssl_sig_from_pk_alg(sig_alg)); + + mbedtls_md_type_t md_alg = mbedtls_ssl_md_alg_from_hash(sig_hash); + + /* 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_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; + } + + MBEDTLS_SSL_DEBUG_MSG(3, ("pick hash algorithm %u for signing", (unsigned) md_alg)); + + /* + * 2.2: Compute the hash to be signed + */ + 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 { + 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 + */ + /* + * 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); + +#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, + out_buf_len - 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_DECODE_ERROR; + } + + 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_DECODE_ERROR; + } + + 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_DECODE_ERROR; + } + + *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_x509_crt *own_cert = mbedtls_ssl_own_cert(ssl); + if (own_cert == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("got no local certificate")); + return MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE; + } + mbedtls_pk_context *public_key = &own_cert->pk; + mbedtls_pk_context *private_key = mbedtls_ssl_own_key(ssl); + 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 (p + 2 > end) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message")); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + 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_DECODE_ERROR; + } + + if (p + len != end) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message")); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + /* + * 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(ver, ssl->conf->transport, + ssl->session_negotiate->tls_version); + + /* 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_DECODE_ERROR; + } + + 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_DECODE_ERROR; + } + + 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_UNEXPECTED_MESSAGE; + } + + 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_UNEXPECTED_MESSAGE; + } + +#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_DECODE_ERROR; + } + + 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_DECODE_ERROR; + } + + 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 defined(MBEDTLS_USE_PSA_CRYPTO) + size_t data_len = (size_t) (*p++); + size_t buf_len = (size_t) (end - p); + psa_status_t status = PSA_ERROR_GENERIC_ERROR; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + MBEDTLS_SSL_DEBUG_MSG(1, ("Read the peer's public key.")); + + /* + * We must have at least two bytes (1 for length, at least 1 for data) + */ + if (buf_len < 2) { + MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid buffer length")); + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + if (data_len < 1 || data_len > buf_len) { + MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid data length")); + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } + + /* Store peer's ECDH public key. */ + memcpy(handshake->ecdh_psa_peerkey, p, data_len); + handshake->ecdh_psa_peerkey_len = data_len; + + /* 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, + handshake->premaster, sizeof(handshake->premaster), + &handshake->pmslen); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_raw_key_agreement", ret); + if (handshake->ecdh_psa_privkey_is_external == 0) { + (void) psa_destroy_key(handshake->ecdh_psa_privkey); + } + handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; + return ret; + } + + if (handshake->ecdh_psa_privkey_is_external == 0) { + status = psa_destroy_key(handshake->ecdh_psa_privkey); + + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_destroy_key", ret); + return ret; + } + } + handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; +#else + 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_DECODE_ERROR; + } + + 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_DECODE_ERROR; + } + + MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Z); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + } 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_DECODE_ERROR; + } + +#if !defined(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; + } +#endif /* !MBEDTLS_USE_PSA_CRYPTO */ + } 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 ((ret = ssl_parse_encrypted_pms(ssl, p, end, 2)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, ("ssl_parse_encrypted_pms"), ret); + return ret; + } + +#if !defined(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; + } +#endif /* !MBEDTLS_USE_PSA_CRYPTO */ + } 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 (p != end) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange")); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + unsigned char *pms = ssl->handshake->premaster; + unsigned char *pms_end = pms + sizeof(ssl->handshake->premaster); + size_t pms_len; + + /* Write length only when we know the actual value */ + if ((ret = mbedtls_dhm_calc_secret(&ssl->handshake->dhm_ctx, + pms + 2, pms_end - (pms + 2), &pms_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(pms_len, pms, 0); + pms += 2 + pms_len; + + MBEDTLS_SSL_DEBUG_MPI(3, "DHM: K ", &ssl->handshake->dhm_ctx.K); +#else + 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; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + } 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) + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t destruction_status = PSA_ERROR_CORRUPTION_DETECTED; + uint8_t ecpoint_len; + + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + if ((ret = ssl_parse_client_psk_identity(ssl, &p, end)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, ("ssl_parse_client_psk_identity"), ret); + psa_destroy_key(handshake->ecdh_psa_privkey); + handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; + return ret; + } + + /* Keep a copy of the peer's public key */ + if (p >= end) { + psa_destroy_key(handshake->ecdh_psa_privkey); + handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + ecpoint_len = *(p++); + if ((size_t) (end - p) < ecpoint_len) { + psa_destroy_key(handshake->ecdh_psa_privkey); + handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + if (ecpoint_len > sizeof(handshake->ecdh_psa_peerkey)) { + psa_destroy_key(handshake->ecdh_psa_privkey); + handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + + memcpy(handshake->ecdh_psa_peerkey, p, ecpoint_len); + handshake->ecdh_psa_peerkey_len = ecpoint_len; + p += ecpoint_len; + + /* As RFC 5489 section 2, the premaster secret is formed as follows: + * - a uint16 containing the length (in octets) of the ECDH computation + * - the octet string produced by the ECDH computation + * - a uint16 containing the length (in octets) of the PSK + * - the PSK itself + */ + unsigned char *psm = ssl->handshake->premaster; + const unsigned char * const psm_end = + psm + sizeof(ssl->handshake->premaster); + /* uint16 to store length (in octets) of the ECDH computation */ + const size_t zlen_size = 2; + size_t zlen = 0; + + /* 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, + psm + zlen_size, + psm_end - (psm + zlen_size), + &zlen); + + destruction_status = psa_destroy_key(handshake->ecdh_psa_privkey); + handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; + + if (status != PSA_SUCCESS) { + return PSA_TO_MBEDTLS_ERR(status); + } else if (destruction_status != PSA_SUCCESS) { + return PSA_TO_MBEDTLS_ERR(destruction_status); + } + + /* Write the ECDH computation length before the ECDH computation */ + MBEDTLS_PUT_UINT16_BE(zlen, psm, 0); + psm += zlen_size + zlen; + +#else /* MBEDTLS_USE_PSA_CRYPTO */ + 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_DECODE_ERROR; + } + + 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; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + } 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) { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if ((ret = mbedtls_psa_ecjpake_read_round( + &ssl->handshake->psa_pake_ctx, p, end - p, + MBEDTLS_ECJPAKE_ROUND_TWO)) != 0) { + psa_destroy_key(ssl->handshake->psa_pake_password); + psa_pake_abort(&ssl->handshake->psa_pake_ctx); + + MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_input round two", ret); + return ret; + } +#else + 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_INTERNAL_ERROR; + } + + 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; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + } 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; + mbedtls_pk_type_t pk_alg; + 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_UNEXPECTED_MESSAGE; + } + + 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 (i + 2 > ssl->in_hslen) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate verify message")); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + /* + * 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_ILLEGAL_PARAMETER; + } + +#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_ILLEGAL_PARAMETER; + } + + /* + * 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_ILLEGAL_PARAMETER; + } + + i++; + + if (i + 2 > ssl->in_hslen) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate verify message")); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + 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_DECODE_ERROR; + } + + /* Calculate hash and verify signature */ + { + size_t dummy_hlen; + ret = ssl->handshake->calc_verify(ssl, hash, &dummy_hlen); + if (0 != ret) { + MBEDTLS_SSL_DEBUG_RET(1, ("calc_verify"), ret); + return ret; + } + } + + 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; + } + + ret = mbedtls_ssl_update_handshake_status(ssl); + if (0 != ret) { + MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ssl_update_handshake_status"), ret); + return ret; + } + + 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; + + MBEDTLS_SSL_DEBUG_MSG(2, ("server state: %d", ssl->state)); + + 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; +} + +void mbedtls_ssl_conf_preference_order(mbedtls_ssl_config *conf, int order) +{ + conf->respect_cli_pref = order; +} + +#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_PROTO_TLS1_2 */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_client.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_client.c new file mode 100644 index 0000000..a7feced --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_client.c @@ -0,0 +1,3064 @@ +/* + * TLS 1.3 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. + * + * This file is part of mbed TLS ( https://tls.mbed.org ) + */ + +#include "common.h" + +#if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_PROTO_TLS1_3) + +#include + +#include "mbedtls/debug.h" +#include "mbedtls/error.h" +#include "mbedtls/platform.h" + +#include "ssl_misc.h" +#include "ssl_client.h" +#include "ssl_tls13_keys.h" +#include "ssl_debug_helpers.h" + +#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \ + psa_to_ssl_errors, \ + psa_generic_status_to_mbedtls) + +/* Write extensions */ + +/* + * ssl_tls13_write_supported_versions_ext(): + * + * struct { + * ProtocolVersion versions<2..254>; + * } SupportedVersions; + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_supported_versions_ext(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len) +{ + unsigned char *p = buf; + unsigned char versions_len = (ssl->handshake->min_tls_version <= + MBEDTLS_SSL_VERSION_TLS1_2) ? 4 : 2; + + *out_len = 0; + + MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding supported versions extension")); + + /* Check if we have space to write the extension: + * - extension_type (2 bytes) + * - extension_data_length (2 bytes) + * - versions_length (1 byte ) + * - versions (2 or 4 bytes) + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 5 + versions_len); + + MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS, p, 0); + MBEDTLS_PUT_UINT16_BE(versions_len + 1, p, 2); + p += 4; + + /* Length of versions */ + *p++ = versions_len; + + /* Write values of supported versions. + * They are defined by the configuration. + * Currently, we advertise only TLS 1.3 or both TLS 1.3 and TLS 1.2. + */ + mbedtls_ssl_write_version(p, MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_VERSION_TLS1_3); + MBEDTLS_SSL_DEBUG_MSG(3, ("supported version: [3:4]")); + + + if (ssl->handshake->min_tls_version <= MBEDTLS_SSL_VERSION_TLS1_2) { + mbedtls_ssl_write_version(p + 2, MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_VERSION_TLS1_2); + MBEDTLS_SSL_DEBUG_MSG(3, ("supported version: [3:3]")); + } + + *out_len = 5 + versions_len; + + mbedtls_ssl_tls13_set_hs_sent_ext_mask( + ssl, MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS); + + return 0; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_supported_versions_ext(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + ((void) ssl); + + MBEDTLS_SSL_CHK_BUF_READ_PTR(buf, end, 2); + if (mbedtls_ssl_read_version(buf, ssl->conf->transport) != + MBEDTLS_SSL_VERSION_TLS1_3) { + MBEDTLS_SSL_DEBUG_MSG(1, ("unexpected version")); + + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + + if (&buf[2] != end) { + MBEDTLS_SSL_DEBUG_MSG(1, ("supported_versions ext data length incorrect")); + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, + MBEDTLS_ERR_SSL_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + return 0; +} + +#if defined(MBEDTLS_SSL_ALPN) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_alpn_ext(mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len) +{ + const unsigned char *p = buf; + const unsigned char *end = buf + len; + size_t protocol_name_list_len, protocol_name_len; + const unsigned char *protocol_name_list_end; + + /* If we didn't send it, the server shouldn't send it */ + if (ssl->conf->alpn_list == NULL) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + /* + * opaque ProtocolName<1..2^8-1>; + * + * struct { + * ProtocolName protocol_name_list<2..2^16-1> + * } ProtocolNameList; + * + * the "ProtocolNameList" MUST contain exactly one "ProtocolName" + */ + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + protocol_name_list_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, protocol_name_list_len); + protocol_name_list_end = p + protocol_name_list_len; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, protocol_name_list_end, 1); + protocol_name_len = *p++; + + /* Check that the server chosen protocol was in our list and save it */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, protocol_name_list_end, protocol_name_len); + for (const char **alpn = ssl->conf->alpn_list; *alpn != NULL; alpn++) { + if (protocol_name_len == strlen(*alpn) && + memcmp(p, *alpn, protocol_name_len) == 0) { + ssl->alpn_chosen = *alpn; + return 0; + } + } + + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; +} +#endif /* MBEDTLS_SSL_ALPN */ + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_reset_key_share(mbedtls_ssl_context *ssl) +{ + uint16_t group_id = ssl->handshake->offered_group_id; + + if (group_id == 0) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + +#if defined(MBEDTLS_ECDH_C) + if (mbedtls_ssl_tls13_named_group_is_ecdhe(group_id)) { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + /* Destroy generated private key. */ + status = psa_destroy_key(ssl->handshake->ecdh_psa_privkey); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_destroy_key", ret); + return ret; + } + + ssl->handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; + return 0; + } else +#endif /* MBEDTLS_ECDH_C */ + if (0 /* other KEMs? */) { + /* Do something */ + } + + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; +} + +/* + * Functions for writing key_share extension. + */ +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_get_default_group_id(mbedtls_ssl_context *ssl, + uint16_t *group_id) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + + +#if defined(MBEDTLS_ECDH_C) + const uint16_t *group_list = mbedtls_ssl_get_groups(ssl); + /* Pick first available ECDHE group compatible with TLS 1.3 */ + if (group_list == NULL) { + return MBEDTLS_ERR_SSL_BAD_CONFIG; + } + + for (; *group_list != 0; group_list++) { + if ((mbedtls_ssl_get_psa_curve_info_from_tls_id(*group_list, + NULL, NULL) == PSA_SUCCESS) && + mbedtls_ssl_tls13_named_group_is_ecdhe(*group_list)) { + *group_id = *group_list; + return 0; + } + } +#else + ((void) ssl); + ((void) group_id); +#endif /* MBEDTLS_ECDH_C */ + + /* + * Add DHE named groups here. + * Pick first available DHE group compatible with TLS 1.3 + */ + + return ret; +} + +/* + * ssl_tls13_write_key_share_ext + * + * Structure of key_share extension in ClientHello: + * + * struct { + * NamedGroup group; + * opaque key_exchange<1..2^16-1>; + * } KeyShareEntry; + * struct { + * KeyShareEntry client_shares<0..2^16-1>; + * } KeyShareClientHello; + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_key_share_ext(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len) +{ + unsigned char *p = buf; + unsigned char *client_shares; /* Start of client_shares */ + size_t client_shares_len; /* Length of client_shares */ + uint16_t group_id; + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + + *out_len = 0; + + /* Check if we have space for header and length fields: + * - extension_type (2 bytes) + * - extension_data_length (2 bytes) + * - client_shares_length (2 bytes) + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6); + p += 6; + + MBEDTLS_SSL_DEBUG_MSG(3, ("client hello: adding key share extension")); + + /* HRR could already have requested something else. */ + group_id = ssl->handshake->offered_group_id; + if (!mbedtls_ssl_tls13_named_group_is_ecdhe(group_id) && + !mbedtls_ssl_tls13_named_group_is_dhe(group_id)) { + MBEDTLS_SSL_PROC_CHK(ssl_tls13_get_default_group_id(ssl, + &group_id)); + } + + /* + * Dispatch to type-specific key generation function. + * + * So far, we're only supporting ECDHE. With the introduction + * of PQC KEMs, we'll want to have multiple branches, one per + * type of KEM, and dispatch to the corresponding crypto. And + * only one key share entry is allowed. + */ + client_shares = p; +#if defined(MBEDTLS_ECDH_C) + if (mbedtls_ssl_tls13_named_group_is_ecdhe(group_id)) { + /* Pointer to group */ + unsigned char *group = p; + /* Length of key_exchange */ + size_t key_exchange_len = 0; + + /* Check there is space for header of KeyShareEntry + * - group (2 bytes) + * - key_exchange_length (2 bytes) + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4); + p += 4; + ret = mbedtls_ssl_tls13_generate_and_write_ecdh_key_exchange( + ssl, group_id, p, end, &key_exchange_len); + p += key_exchange_len; + if (ret != 0) { + return ret; + } + + /* Write group */ + MBEDTLS_PUT_UINT16_BE(group_id, group, 0); + /* Write key_exchange_length */ + MBEDTLS_PUT_UINT16_BE(key_exchange_len, group, 2); + } else +#endif /* MBEDTLS_ECDH_C */ + if (0 /* other KEMs? */) { + /* Do something */ + } else { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + /* Length of client_shares */ + client_shares_len = p - client_shares; + if (client_shares_len == 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("No key share defined.")); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + /* Write extension_type */ + MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_KEY_SHARE, buf, 0); + /* Write extension_data_length */ + MBEDTLS_PUT_UINT16_BE(client_shares_len + 2, buf, 2); + /* Write client_shares_length */ + MBEDTLS_PUT_UINT16_BE(client_shares_len, buf, 4); + + /* Update offered_group_id field */ + ssl->handshake->offered_group_id = group_id; + + /* Output the total length of key_share extension. */ + *out_len = p - buf; + + MBEDTLS_SSL_DEBUG_BUF(3, "client hello, key_share extension", buf, *out_len); + + mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_KEY_SHARE); + +cleanup: + + return ret; +} +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */ + +/* + * ssl_tls13_parse_hrr_key_share_ext() + * Parse key_share extension in Hello Retry Request + * + * struct { + * NamedGroup selected_group; + * } KeyShareHelloRetryRequest; + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_hrr_key_share_ext(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ +#if defined(MBEDTLS_ECDH_C) + const unsigned char *p = buf; + int selected_group; + int found = 0; + + const uint16_t *group_list = mbedtls_ssl_get_groups(ssl); + if (group_list == NULL) { + return MBEDTLS_ERR_SSL_BAD_CONFIG; + } + + MBEDTLS_SSL_DEBUG_BUF(3, "key_share extension", p, end - buf); + + /* Read selected_group */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + selected_group = MBEDTLS_GET_UINT16_BE(p, 0); + MBEDTLS_SSL_DEBUG_MSG(3, ("selected_group ( %d )", selected_group)); + + /* Upon receipt of this extension in a HelloRetryRequest, the client + * MUST first verify that the selected_group field corresponds to a + * group which was provided in the "supported_groups" extension in the + * original ClientHello. + * The supported_group was based on the info in ssl->conf->group_list. + * + * If the server provided a key share that was not sent in the ClientHello + * then the client MUST abort the handshake with an "illegal_parameter" alert. + */ + for (; *group_list != 0; group_list++) { + if ((mbedtls_ssl_get_psa_curve_info_from_tls_id(*group_list, + NULL, NULL) == PSA_ERROR_NOT_SUPPORTED) || + *group_list != selected_group) { + continue; + } + + /* We found a match */ + found = 1; + break; + } + + /* Client MUST verify that the selected_group field does not + * correspond to a group which was provided in the "key_share" + * extension in the original ClientHello. If the server sent an + * HRR message with a key share already provided in the + * ClientHello then the client MUST abort the handshake with + * an "illegal_parameter" alert. + */ + if (found == 0 || selected_group == ssl->handshake->offered_group_id) { + MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid key share in HRR")); + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + + /* Remember server's preference for next ClientHello */ + ssl->handshake->offered_group_id = selected_group; + + return 0; +#else + (void) ssl; + (void) buf; + (void) end; + return MBEDTLS_ERR_SSL_BAD_CONFIG; +#endif +} + +/* + * ssl_tls13_parse_key_share_ext() + * Parse key_share extension in Server Hello + * + * struct { + * KeyShareEntry server_share; + * } KeyShareServerHello; + * struct { + * NamedGroup group; + * opaque key_exchange<1..2^16-1>; + * } KeyShareEntry; + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_key_share_ext(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const unsigned char *p = buf; + uint16_t group, offered_group; + + /* ... + * NamedGroup group; (2 bytes) + * ... + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + group = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + + /* Check that the chosen group matches the one we offered. */ + offered_group = ssl->handshake->offered_group_id; + if (offered_group != group) { + MBEDTLS_SSL_DEBUG_MSG(1, + ("Invalid server key share, our group %u, their group %u", + (unsigned) offered_group, (unsigned) group)); + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, + MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + +#if defined(MBEDTLS_ECDH_C) + if (mbedtls_ssl_tls13_named_group_is_ecdhe(group)) { + if (mbedtls_ssl_get_psa_curve_info_from_tls_id(group, NULL, NULL) + == PSA_ERROR_NOT_SUPPORTED) { + MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid TLS curve group id")); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + MBEDTLS_SSL_DEBUG_MSG(2, ("ECDH curve: %s", + mbedtls_ssl_get_curve_name_from_tls_id(group))); + + ret = mbedtls_ssl_tls13_read_public_ecdhe_share(ssl, p, end - p); + if (ret != 0) { + return ret; + } + } else +#endif /* MBEDTLS_ECDH_C */ + if (0 /* other KEMs? */) { + /* Do something */ + } else { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + return ret; +} + +/* + * ssl_tls13_parse_cookie_ext() + * Parse cookie extension in Hello Retry Request + * + * struct { + * opaque cookie<1..2^16-1>; + * } Cookie; + * + * When sending a HelloRetryRequest, the server MAY provide a "cookie" + * extension to the client (this is an exception to the usual rule that + * the only extensions that may be sent are those that appear in the + * ClientHello). When sending the new ClientHello, the client MUST copy + * the contents of the extension received in the HelloRetryRequest into + * a "cookie" extension in the new ClientHello. Clients MUST NOT use + * cookies in their initial ClientHello in subsequent connections. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_cookie_ext(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + uint16_t cookie_len; + const unsigned char *p = buf; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + /* Retrieve length field of cookie */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + cookie_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, cookie_len); + MBEDTLS_SSL_DEBUG_BUF(3, "cookie extension", p, cookie_len); + + mbedtls_free(handshake->cookie); + handshake->cookie_len = 0; + handshake->cookie = mbedtls_calloc(1, cookie_len); + if (handshake->cookie == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, + ("alloc failed ( %ud bytes )", + cookie_len)); + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } + + memcpy(handshake->cookie, p, cookie_len); + handshake->cookie_len = cookie_len; + + return 0; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_cookie_ext(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len) +{ + unsigned char *p = buf; + *out_len = 0; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + if (handshake->cookie == NULL) { + MBEDTLS_SSL_DEBUG_MSG(3, ("no cookie to send; skip extension")); + return 0; + } + + MBEDTLS_SSL_DEBUG_BUF(3, "client hello, cookie", + handshake->cookie, + handshake->cookie_len); + + MBEDTLS_SSL_CHK_BUF_PTR(p, end, handshake->cookie_len + 6); + + MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding cookie extension")); + + MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_COOKIE, p, 0); + MBEDTLS_PUT_UINT16_BE(handshake->cookie_len + 2, p, 2); + MBEDTLS_PUT_UINT16_BE(handshake->cookie_len, p, 4); + p += 6; + + /* Cookie */ + memcpy(p, handshake->cookie, handshake->cookie_len); + + *out_len = handshake->cookie_len + 6; + + mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_COOKIE); + + return 0; +} + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) +/* + * ssl_tls13_write_psk_key_exchange_modes_ext() structure: + * + * enum { psk_ke( 0 ), psk_dhe_ke( 1 ), ( 255 ) } PskKeyExchangeMode; + * + * struct { + * PskKeyExchangeMode ke_modes<1..255>; + * } PskKeyExchangeModes; + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_psk_key_exchange_modes_ext(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len) +{ + unsigned char *p = buf; + int ke_modes_len = 0; + + ((void) ke_modes_len); + *out_len = 0; + + /* Skip writing extension if no PSK key exchange mode + * is enabled in the config. + */ + if (!mbedtls_ssl_conf_tls13_some_psk_enabled(ssl)) { + MBEDTLS_SSL_DEBUG_MSG(3, ("skip psk_key_exchange_modes extension")); + return 0; + } + + /* Require 7 bytes of data, otherwise fail, + * even if extension might be shorter. + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 7); + MBEDTLS_SSL_DEBUG_MSG( + 3, ("client hello, adding psk_key_exchange_modes extension")); + + MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_PSK_KEY_EXCHANGE_MODES, p, 0); + + /* Skip extension length (2 bytes) and + * ke_modes length (1 byte) for now. + */ + p += 5; + + if (mbedtls_ssl_conf_tls13_psk_ephemeral_enabled(ssl)) { + *p++ = MBEDTLS_SSL_TLS1_3_PSK_MODE_ECDHE; + ke_modes_len++; + + MBEDTLS_SSL_DEBUG_MSG(4, ("Adding PSK-ECDHE key exchange mode")); + } + + if (mbedtls_ssl_conf_tls13_psk_enabled(ssl)) { + *p++ = MBEDTLS_SSL_TLS1_3_PSK_MODE_PURE; + ke_modes_len++; + + MBEDTLS_SSL_DEBUG_MSG(4, ("Adding pure PSK key exchange mode")); + } + + /* Now write the extension and ke_modes length */ + MBEDTLS_PUT_UINT16_BE(ke_modes_len + 1, buf, 2); + buf[4] = ke_modes_len; + + *out_len = p - buf; + + mbedtls_ssl_tls13_set_hs_sent_ext_mask( + ssl, MBEDTLS_TLS_EXT_PSK_KEY_EXCHANGE_MODES); + + return 0; +} + +static psa_algorithm_t ssl_tls13_get_ciphersuite_hash_alg(int ciphersuite) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = NULL; + ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(ciphersuite); + + if (ciphersuite_info != NULL) { + return mbedtls_psa_translate_md(ciphersuite_info->mac); + } + + return PSA_ALG_NONE; +} + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +static int ssl_tls13_has_configured_ticket(mbedtls_ssl_context *ssl) +{ + mbedtls_ssl_session *session = ssl->session_negotiate; + return ssl->handshake->resume && + session != NULL && session->ticket != NULL && + mbedtls_ssl_conf_tls13_check_kex_modes( + ssl, mbedtls_ssl_session_get_ticket_flags( + session, MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL)); +} + +#if defined(MBEDTLS_SSL_EARLY_DATA) +static int ssl_tls13_early_data_has_valid_ticket(mbedtls_ssl_context *ssl) +{ + mbedtls_ssl_session *session = ssl->session_negotiate; + return ssl->handshake->resume && + session->tls_version == MBEDTLS_SSL_VERSION_TLS1_3 && + (session->ticket_flags & + MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA) && + mbedtls_ssl_tls13_cipher_suite_is_offered( + ssl, session->ciphersuite); +} +#endif + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_ticket_get_identity(mbedtls_ssl_context *ssl, + psa_algorithm_t *hash_alg, + const unsigned char **identity, + size_t *identity_len) +{ + mbedtls_ssl_session *session = ssl->session_negotiate; + + if (!ssl_tls13_has_configured_ticket(ssl)) { + return -1; + } + + *hash_alg = ssl_tls13_get_ciphersuite_hash_alg(session->ciphersuite); + *identity = session->ticket; + *identity_len = session->ticket_len; + return 0; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_ticket_get_psk(mbedtls_ssl_context *ssl, + psa_algorithm_t *hash_alg, + const unsigned char **psk, + size_t *psk_len) +{ + + mbedtls_ssl_session *session = ssl->session_negotiate; + + if (!ssl_tls13_has_configured_ticket(ssl)) { + return -1; + } + + *hash_alg = ssl_tls13_get_ciphersuite_hash_alg(session->ciphersuite); + *psk = session->resumption_key; + *psk_len = session->resumption_key_len; + + return 0; +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_psk_get_identity(mbedtls_ssl_context *ssl, + psa_algorithm_t *hash_alg, + const unsigned char **identity, + size_t *identity_len) +{ + + if (!mbedtls_ssl_conf_has_static_psk(ssl->conf)) { + return -1; + } + + *hash_alg = PSA_ALG_SHA_256; + *identity = ssl->conf->psk_identity; + *identity_len = ssl->conf->psk_identity_len; + return 0; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_psk_get_psk(mbedtls_ssl_context *ssl, + psa_algorithm_t *hash_alg, + const unsigned char **psk, + size_t *psk_len) +{ + + if (!mbedtls_ssl_conf_has_static_psk(ssl->conf)) { + return -1; + } + + *hash_alg = PSA_ALG_SHA_256; + *psk = ssl->conf->psk; + *psk_len = ssl->conf->psk_len; + return 0; +} + +static int ssl_tls13_get_configured_psk_count(mbedtls_ssl_context *ssl) +{ + int configured_psk_count = 0; +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if (ssl_tls13_has_configured_ticket(ssl)) { + MBEDTLS_SSL_DEBUG_MSG(3, ("Ticket is configured")); + configured_psk_count++; + } +#endif + if (mbedtls_ssl_conf_has_static_psk(ssl->conf)) { + MBEDTLS_SSL_DEBUG_MSG(3, ("PSK is configured")); + configured_psk_count++; + } + return configured_psk_count; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_identity(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + const unsigned char *identity, + size_t identity_len, + uint32_t obfuscated_ticket_age, + size_t *out_len) +{ + ((void) ssl); + *out_len = 0; + + /* + * - identity_len (2 bytes) + * - identity (psk_identity_len bytes) + * - obfuscated_ticket_age (4 bytes) + */ + MBEDTLS_SSL_CHK_BUF_PTR(buf, end, 6 + identity_len); + + MBEDTLS_PUT_UINT16_BE(identity_len, buf, 0); + memcpy(buf + 2, identity, identity_len); + MBEDTLS_PUT_UINT32_BE(obfuscated_ticket_age, buf, 2 + identity_len); + + MBEDTLS_SSL_DEBUG_BUF(4, "write identity", buf, 6 + identity_len); + + *out_len = 6 + identity_len; + + return 0; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_binder(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + int psk_type, + psa_algorithm_t hash_alg, + const unsigned char *psk, + size_t psk_len, + size_t *out_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char binder_len; + unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + size_t transcript_len = 0; + + *out_len = 0; + + binder_len = PSA_HASH_LENGTH(hash_alg); + + /* + * - binder_len (1 bytes) + * - binder (binder_len bytes) + */ + MBEDTLS_SSL_CHK_BUF_PTR(buf, end, 1 + binder_len); + + buf[0] = binder_len; + + /* Get current state of handshake transcript. */ + ret = mbedtls_ssl_get_handshake_transcript( + ssl, mbedtls_hash_info_md_from_psa(hash_alg), + transcript, sizeof(transcript), &transcript_len); + if (ret != 0) { + return ret; + } + + ret = mbedtls_ssl_tls13_create_psk_binder(ssl, hash_alg, + psk, psk_len, psk_type, + transcript, buf + 1); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_create_psk_binder", ret); + return ret; + } + MBEDTLS_SSL_DEBUG_BUF(4, "write binder", buf, 1 + binder_len); + + *out_len = 1 + binder_len; + + return 0; +} + +/* + * mbedtls_ssl_tls13_write_identities_of_pre_shared_key_ext() structure: + * + * struct { + * opaque identity<1..2^16-1>; + * uint32 obfuscated_ticket_age; + * } PskIdentity; + * + * opaque PskBinderEntry<32..255>; + * + * struct { + * PskIdentity identities<7..2^16-1>; + * PskBinderEntry binders<33..2^16-1>; + * } OfferedPsks; + * + * struct { + * select (Handshake.msg_type) { + * case client_hello: OfferedPsks; + * ... + * }; + * } PreSharedKeyExtension; + * + */ +int mbedtls_ssl_tls13_write_identities_of_pre_shared_key_ext( + mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, + size_t *out_len, size_t *binders_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int configured_psk_count = 0; + unsigned char *p = buf; + psa_algorithm_t hash_alg = PSA_ALG_NONE; + const unsigned char *identity; + size_t identity_len; + size_t l_binders_len = 0; + size_t output_len; + + *out_len = 0; + *binders_len = 0; + + /* Check if we have any PSKs to offer. If no, skip pre_shared_key */ + configured_psk_count = ssl_tls13_get_configured_psk_count(ssl); + if (configured_psk_count == 0) { + MBEDTLS_SSL_DEBUG_MSG(3, ("skip pre_shared_key extensions")); + return 0; + } + + MBEDTLS_SSL_DEBUG_MSG(4, ("Pre-configured PSK number = %d", + configured_psk_count)); + + /* Check if we have space to write the extension, binders included. + * - extension_type (2 bytes) + * - extension_data_len (2 bytes) + * - identities_len (2 bytes) + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6); + p += 6; + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if (ssl_tls13_ticket_get_identity( + ssl, &hash_alg, &identity, &identity_len) == 0) { +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t now = mbedtls_time(NULL); + mbedtls_ssl_session *session = ssl->session_negotiate; + uint32_t obfuscated_ticket_age = + (uint32_t) (now - session->ticket_received); + + /* + * The ticket timestamp is in seconds but the ticket age is in + * milliseconds. If the ticket was received at the end of a second and + * re-used here just at the beginning of the next second, the computed + * age `now - session->ticket_received` is equal to 1s thus 1000 ms + * while the actual age could be just a few milliseconds or tens of + * milliseconds. If the server has more accurate ticket timestamps + * (typically timestamps in milliseconds), as part of the processing of + * the ClientHello, it may compute a ticket lifetime smaller than the + * one computed here and potentially reject the ticket. To avoid that, + * remove one second to the ticket age if possible. + */ + if (obfuscated_ticket_age > 0) { + obfuscated_ticket_age -= 1; + } + + obfuscated_ticket_age *= 1000; + obfuscated_ticket_age += session->ticket_age_add; + + ret = ssl_tls13_write_identity(ssl, p, end, + identity, identity_len, + obfuscated_ticket_age, + &output_len); +#else + ret = ssl_tls13_write_identity(ssl, p, end, identity, identity_len, + 0, &output_len); +#endif /* MBEDTLS_HAVE_TIME */ + if (ret != 0) { + return ret; + } + + p += output_len; + l_binders_len += 1 + PSA_HASH_LENGTH(hash_alg); + } +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + + if (ssl_tls13_psk_get_identity( + ssl, &hash_alg, &identity, &identity_len) == 0) { + + ret = ssl_tls13_write_identity(ssl, p, end, identity, identity_len, 0, + &output_len); + if (ret != 0) { + return ret; + } + + p += output_len; + l_binders_len += 1 + PSA_HASH_LENGTH(hash_alg); + } + + MBEDTLS_SSL_DEBUG_MSG(3, + ("client hello, adding pre_shared_key extension, " + "omitting PSK binder list")); + + /* Take into account the two bytes for the length of the binders. */ + l_binders_len += 2; + /* Check if there is enough space for binders */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, l_binders_len); + + /* + * - extension_type (2 bytes) + * - extension_data_len (2 bytes) + * - identities_len (2 bytes) + */ + MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_PRE_SHARED_KEY, buf, 0); + MBEDTLS_PUT_UINT16_BE(p - buf - 4 + l_binders_len, buf, 2); + MBEDTLS_PUT_UINT16_BE(p - buf - 6, buf, 4); + + *out_len = (p - buf) + l_binders_len; + *binders_len = l_binders_len; + + MBEDTLS_SSL_DEBUG_BUF(3, "pre_shared_key identities", buf, p - buf); + + return 0; +} + +int mbedtls_ssl_tls13_write_binders_of_pre_shared_key_ext( + mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = buf; + psa_algorithm_t hash_alg = PSA_ALG_NONE; + const unsigned char *psk; + size_t psk_len; + size_t output_len; + + /* Check if we have space to write binders_len. + * - binders_len (2 bytes) + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); + p += 2; + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if (ssl_tls13_ticket_get_psk(ssl, &hash_alg, &psk, &psk_len) == 0) { + + ret = ssl_tls13_write_binder(ssl, p, end, + MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION, + hash_alg, psk, psk_len, + &output_len); + if (ret != 0) { + return ret; + } + p += output_len; + } +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + + if (ssl_tls13_psk_get_psk(ssl, &hash_alg, &psk, &psk_len) == 0) { + + ret = ssl_tls13_write_binder(ssl, p, end, + MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL, + hash_alg, psk, psk_len, + &output_len); + if (ret != 0) { + return ret; + } + p += output_len; + } + + MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding PSK binder list.")); + + /* + * - binders_len (2 bytes) + */ + MBEDTLS_PUT_UINT16_BE(p - buf - 2, buf, 0); + + MBEDTLS_SSL_DEBUG_BUF(3, "pre_shared_key binders", buf, p - buf); + + mbedtls_ssl_tls13_set_hs_sent_ext_mask( + ssl, MBEDTLS_TLS_EXT_PRE_SHARED_KEY); + + return 0; +} + +/* + * struct { + * opaque identity<1..2^16-1>; + * uint32 obfuscated_ticket_age; + * } PskIdentity; + * + * opaque PskBinderEntry<32..255>; + * + * struct { + * + * select (Handshake.msg_type) { + * ... + * case server_hello: uint16 selected_identity; + * }; + * + * } PreSharedKeyExtension; + * + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_server_pre_shared_key_ext(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int selected_identity; + const unsigned char *psk; + size_t psk_len; + psa_algorithm_t hash_alg; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(buf, end, 2); + selected_identity = MBEDTLS_GET_UINT16_BE(buf, 0); + ssl->handshake->selected_identity = (uint16_t) selected_identity; + + MBEDTLS_SSL_DEBUG_MSG(3, ("selected_identity = %d", selected_identity)); + + if (selected_identity >= ssl_tls13_get_configured_psk_count(ssl)) { + MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid PSK identity.")); + + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if (selected_identity == 0 && ssl_tls13_has_configured_ticket(ssl)) { + ret = ssl_tls13_ticket_get_psk(ssl, &hash_alg, &psk, &psk_len); + } else +#endif + if (mbedtls_ssl_conf_has_static_psk(ssl->conf)) { + ret = ssl_tls13_psk_get_psk(ssl, &hash_alg, &psk, &psk_len); + } else { + MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + if (ret != 0) { + return ret; + } + + if (mbedtls_psa_translate_md(ssl->handshake->ciphersuite_info->mac) + != hash_alg) { + MBEDTLS_SSL_DEBUG_MSG( + 1, ("Invalid ciphersuite for external psk.")); + + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + + ret = mbedtls_ssl_set_hs_psk(ssl, psk, psk_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_set_hs_psk", ret); + return ret; + } + + return 0; +} +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ + +int mbedtls_ssl_tls13_write_client_hello_exts(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = buf; + size_t ext_len; + + *out_len = 0; + + /* Write supported_versions extension + * + * Supported Versions Extension is mandatory with TLS 1.3. + */ + ret = ssl_tls13_write_supported_versions_ext(ssl, p, end, &ext_len); + if (ret != 0) { + return ret; + } + p += ext_len; + + /* Echo the cookie if the server provided one in its preceding + * HelloRetryRequest message. + */ + ret = ssl_tls13_write_cookie_ext(ssl, p, end, &ext_len); + if (ret != 0) { + return ret; + } + p += ext_len; + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) + if (mbedtls_ssl_conf_tls13_some_ephemeral_enabled(ssl)) { + ret = ssl_tls13_write_key_share_ext(ssl, p, end, &ext_len); + if (ret != 0) { + return ret; + } + p += ext_len; + } +#endif + +#if defined(MBEDTLS_SSL_EARLY_DATA) + if (mbedtls_ssl_conf_tls13_some_psk_enabled(ssl) && + ssl_tls13_early_data_has_valid_ticket(ssl) && + ssl->conf->early_data_enabled == MBEDTLS_SSL_EARLY_DATA_ENABLED) { + ret = mbedtls_ssl_tls13_write_early_data_ext(ssl, p, end, &ext_len); + if (ret != 0) { + return ret; + } + p += ext_len; + + /* Initializes the status to `rejected`. It will be updated to + * `accepted` if the EncryptedExtension message contain an early data + * indication extension. + */ + ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED; + } else { + MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write early_data extension")); + ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT; + } +#endif /* MBEDTLS_SSL_EARLY_DATA */ + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) + /* For PSK-based key exchange we need the pre_shared_key extension + * and the psk_key_exchange_modes extension. + * + * The pre_shared_key extension MUST be the last extension in the + * ClientHello. Servers MUST check that it is the last extension and + * otherwise fail the handshake with an "illegal_parameter" alert. + * + * Add the psk_key_exchange_modes extension. + */ + ret = ssl_tls13_write_psk_key_exchange_modes_ext(ssl, p, end, &ext_len); + if (ret != 0) { + return ret; + } + p += ext_len; +#endif + + *out_len = p - buf; + + return 0; +} + +int mbedtls_ssl_tls13_finalize_client_hello(mbedtls_ssl_context *ssl) +{ + ((void) ssl); + +#if defined(MBEDTLS_SSL_EARLY_DATA) + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + psa_algorithm_t hash_alg = PSA_ALG_NONE; + const unsigned char *psk; + size_t psk_len; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + + if (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED) { +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + mbedtls_ssl_handshake_set_state( + ssl, MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO); +#endif + MBEDTLS_SSL_DEBUG_MSG( + 1, ("Set hs psk for early data when writing the first psk")); + + ret = ssl_tls13_ticket_get_psk(ssl, &hash_alg, &psk, &psk_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET( + 1, "ssl_tls13_ticket_get_psk", ret); + return ret; + } + + ret = mbedtls_ssl_set_hs_psk(ssl, psk, psk_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_set_hs_psk", ret); + return ret; + } + + /* + * Early data are going to be encrypted using the ciphersuite + * associated with the pre-shared key used for the handshake. + * Note that if the server rejects early data, the handshake + * based on the pre-shared key may complete successfully + * with a selected ciphersuite different from the ciphersuite + * associated with the pre-shared key. Only the hashes of the + * two ciphersuites have to be the same. In that case, the + * encrypted handshake data and application data are + * encrypted using a different ciphersuite than the one used for + * the rejected early data. + */ + ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( + ssl->session_negotiate->ciphersuite); + ssl->handshake->ciphersuite_info = ciphersuite_info; + + /* Enable psk and psk_ephemeral to make stage early happy */ + ssl->handshake->key_exchange_mode = + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL; + + /* Start the TLS 1.3 key schedule: + * Set the PSK and derive early secret. + */ + ret = mbedtls_ssl_tls13_key_schedule_stage_early(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET( + 1, "mbedtls_ssl_tls13_key_schedule_stage_early", ret); + return ret; + } + + /* Derive early data key material */ + ret = mbedtls_ssl_tls13_compute_early_transform(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET( + 1, "mbedtls_ssl_tls13_compute_early_transform", ret); + return ret; + } + + } +#endif /* MBEDTLS_SSL_EARLY_DATA */ + return 0; +} +/* + * Functions for parsing and processing Server Hello + */ + +/** + * \brief Detect if the ServerHello contains a supported_versions extension + * or not. + * + * \param[in] ssl SSL context + * \param[in] buf Buffer containing the ServerHello message + * \param[in] end End of the buffer containing the ServerHello message + * + * \return 0 if the ServerHello does not contain a supported_versions extension + * \return 1 if the ServerHello contains a supported_versions extension + * \return A negative value if an error occurred while parsing the ServerHello. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_is_supported_versions_ext_present( + mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + const unsigned char *p = buf; + size_t legacy_session_id_echo_len; + size_t extensions_len; + const unsigned char *extensions_end; + + /* + * Check there is enough data to access the legacy_session_id_echo vector + * length: + * - legacy_version 2 bytes + * - random MBEDTLS_SERVER_HELLO_RANDOM_LEN bytes + * - legacy_session_id_echo length 1 byte + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, MBEDTLS_SERVER_HELLO_RANDOM_LEN + 3); + p += MBEDTLS_SERVER_HELLO_RANDOM_LEN + 2; + legacy_session_id_echo_len = *p; + + /* + * Jump to the extensions, jumping over: + * - legacy_session_id_echo (legacy_session_id_echo_len + 1) bytes + * - cipher_suite 2 bytes + * - legacy_compression_method 1 byte + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, legacy_session_id_echo_len + 4); + p += legacy_session_id_echo_len + 4; + + /* Case of no extension */ + if (p == end) { + return 0; + } + + /* ... + * Extension extensions<6..2^16-1>; + * ... + * struct { + * ExtensionType extension_type; (2 bytes) + * opaque extension_data<0..2^16-1>; + * } Extension; + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + extensions_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + + /* Check extensions do not go beyond the buffer of data. */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len); + extensions_end = p + extensions_len; + + while (p < extensions_end) { + unsigned int extension_type; + size_t extension_data_len; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4); + extension_type = MBEDTLS_GET_UINT16_BE(p, 0); + extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2); + p += 4; + + if (extension_type == MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS) { + return 1; + } + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len); + p += extension_data_len; + } + + return 0; +} + +/* Returns a negative value on failure, and otherwise + * - 1 if the last eight bytes of the ServerHello random bytes indicate that + * the server is TLS 1.3 capable but negotiating TLS 1.2 or below. + * - 0 otherwise + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_is_downgrade_negotiation(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + /* First seven bytes of the magic downgrade strings, see RFC 8446 4.1.3 */ + static const unsigned char magic_downgrade_string[] = + { 0x44, 0x4F, 0x57, 0x4E, 0x47, 0x52, 0x44 }; + const unsigned char *last_eight_bytes_of_random; + unsigned char last_byte_of_random; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(buf, end, MBEDTLS_SERVER_HELLO_RANDOM_LEN + 2); + last_eight_bytes_of_random = buf + 2 + MBEDTLS_SERVER_HELLO_RANDOM_LEN - 8; + + if (memcmp(last_eight_bytes_of_random, + magic_downgrade_string, + sizeof(magic_downgrade_string)) == 0) { + last_byte_of_random = last_eight_bytes_of_random[7]; + return last_byte_of_random == 0 || + last_byte_of_random == 1; + } + + return 0; +} + +/* Returns a negative value on failure, and otherwise + * - SSL_SERVER_HELLO or + * - SSL_SERVER_HELLO_HRR + * to indicate which message is expected and to be parsed next. + */ +#define SSL_SERVER_HELLO 0 +#define SSL_SERVER_HELLO_HRR 1 +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_server_hello_is_hrr(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + + /* Check whether this message is a HelloRetryRequest ( HRR ) message. + * + * Server Hello and HRR are only distinguished by Random set to the + * special value of the SHA-256 of "HelloRetryRequest". + * + * struct { + * ProtocolVersion legacy_version = 0x0303; + * Random random; + * opaque legacy_session_id_echo<0..32>; + * CipherSuite cipher_suite; + * uint8 legacy_compression_method = 0; + * Extension extensions<6..2^16-1>; + * } ServerHello; + * + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(buf, end, + 2 + sizeof(mbedtls_ssl_tls13_hello_retry_request_magic)); + + if (memcmp(buf + 2, mbedtls_ssl_tls13_hello_retry_request_magic, + sizeof(mbedtls_ssl_tls13_hello_retry_request_magic)) == 0) { + return SSL_SERVER_HELLO_HRR; + } + + return SSL_SERVER_HELLO; +} + +/* + * Returns a negative value on failure, and otherwise + * - SSL_SERVER_HELLO or + * - SSL_SERVER_HELLO_HRR or + * - SSL_SERVER_HELLO_TLS1_2 + */ +#define SSL_SERVER_HELLO_TLS1_2 2 +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_preprocess_server_hello(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_is_supported_versions_ext_present( + ssl, buf, end)); + + if (ret == 0) { + MBEDTLS_SSL_PROC_CHK_NEG( + ssl_tls13_is_downgrade_negotiation(ssl, buf, end)); + + /* If the server is negotiating TLS 1.2 or below and: + * . we did not propose TLS 1.2 or + * . the server responded it is TLS 1.3 capable but negotiating a lower + * version of the protocol and thus we are under downgrade attack + * abort the handshake with an "illegal parameter" alert. + */ + if (handshake->min_tls_version > MBEDTLS_SSL_VERSION_TLS1_2 || ret) { + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + + ssl->keep_current_message = 1; + ssl->tls_version = MBEDTLS_SSL_VERSION_TLS1_2; + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl, + MBEDTLS_SSL_HS_SERVER_HELLO, + buf, (size_t) (end - buf))); + + if (mbedtls_ssl_conf_tls13_some_ephemeral_enabled(ssl)) { + ret = ssl_tls13_reset_key_share(ssl); + if (ret != 0) { + return ret; + } + } + + return SSL_SERVER_HELLO_TLS1_2; + } + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + ssl->session_negotiate->endpoint = ssl->conf->endpoint; + ssl->session_negotiate->tls_version = ssl->tls_version; +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + + handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE; + + ret = ssl_server_hello_is_hrr(ssl, buf, end); + switch (ret) { + case SSL_SERVER_HELLO: + MBEDTLS_SSL_DEBUG_MSG(2, ("received ServerHello message")); + break; + case SSL_SERVER_HELLO_HRR: + MBEDTLS_SSL_DEBUG_MSG(2, ("received HelloRetryRequest message")); + /* If a client receives a second + * HelloRetryRequest in the same connection (i.e., where the ClientHello + * was itself in response to a HelloRetryRequest), it MUST abort the + * handshake with an "unexpected_message" alert. + */ + if (handshake->hello_retry_request_count > 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("Multiple HRRs received")); + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE, + MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE); + return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; + } + /* + * Clients must abort the handshake with an "illegal_parameter" + * alert if the HelloRetryRequest would not result in any change + * in the ClientHello. + * In a PSK only key exchange that what we expect. + */ + if (!mbedtls_ssl_conf_tls13_some_ephemeral_enabled(ssl)) { + MBEDTLS_SSL_DEBUG_MSG(1, + ("Unexpected HRR in pure PSK key exchange.")); + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + + handshake->hello_retry_request_count++; + + break; + } + +cleanup: + + return ret; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_check_server_hello_session_id_echo(mbedtls_ssl_context *ssl, + const unsigned char **buf, + const unsigned char *end) +{ + const unsigned char *p = *buf; + size_t legacy_session_id_echo_len; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 1); + legacy_session_id_echo_len = *p++; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, legacy_session_id_echo_len); + + /* legacy_session_id_echo */ + if (ssl->session_negotiate->id_len != legacy_session_id_echo_len || + memcmp(ssl->session_negotiate->id, p, legacy_session_id_echo_len) != 0) { + MBEDTLS_SSL_DEBUG_BUF(3, "Expected Session ID", + ssl->session_negotiate->id, + ssl->session_negotiate->id_len); + MBEDTLS_SSL_DEBUG_BUF(3, "Received Session ID", p, + legacy_session_id_echo_len); + + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + + p += legacy_session_id_echo_len; + *buf = p; + + MBEDTLS_SSL_DEBUG_BUF(3, "Session ID", ssl->session_negotiate->id, + ssl->session_negotiate->id_len); + return 0; +} + +/* Parse ServerHello message and configure context + * + * struct { + * ProtocolVersion legacy_version = 0x0303; // TLS 1.2 + * Random random; + * opaque legacy_session_id_echo<0..32>; + * CipherSuite cipher_suite; + * uint8 legacy_compression_method = 0; + * Extension extensions<6..2^16-1>; + * } ServerHello; + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_server_hello(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end, + int is_hrr) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const unsigned char *p = buf; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + size_t extensions_len; + const unsigned char *extensions_end; + uint16_t cipher_suite; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + int fatal_alert = 0; + uint32_t allowed_extensions_mask; + int hs_msg_type = is_hrr ? MBEDTLS_SSL_TLS1_3_HS_HELLO_RETRY_REQUEST : + MBEDTLS_SSL_HS_SERVER_HELLO; + + /* + * Check there is space for minimal fields + * + * - legacy_version ( 2 bytes) + * - random (MBEDTLS_SERVER_HELLO_RANDOM_LEN bytes) + * - legacy_session_id_echo ( 1 byte ), minimum size + * - cipher_suite ( 2 bytes) + * - legacy_compression_method ( 1 byte ) + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, MBEDTLS_SERVER_HELLO_RANDOM_LEN + 6); + + MBEDTLS_SSL_DEBUG_BUF(4, "server hello", p, end - p); + MBEDTLS_SSL_DEBUG_BUF(3, "server hello, version", p, 2); + + /* ... + * ProtocolVersion legacy_version = 0x0303; // TLS 1.2 + * ... + * with ProtocolVersion defined as: + * uint16 ProtocolVersion; + */ + if (mbedtls_ssl_read_version(p, ssl->conf->transport) != + MBEDTLS_SSL_VERSION_TLS1_2) { + MBEDTLS_SSL_DEBUG_MSG(1, ("Unsupported version of TLS.")); + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION, + MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION); + ret = MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION; + goto cleanup; + } + p += 2; + + /* ... + * Random random; + * ... + * with Random defined as: + * opaque Random[MBEDTLS_SERVER_HELLO_RANDOM_LEN]; + */ + if (!is_hrr) { + memcpy(&handshake->randbytes[MBEDTLS_CLIENT_HELLO_RANDOM_LEN], p, + MBEDTLS_SERVER_HELLO_RANDOM_LEN); + MBEDTLS_SSL_DEBUG_BUF(3, "server hello, random bytes", + p, MBEDTLS_SERVER_HELLO_RANDOM_LEN); + } + p += MBEDTLS_SERVER_HELLO_RANDOM_LEN; + + /* ... + * opaque legacy_session_id_echo<0..32>; + * ... + */ + if (ssl_tls13_check_server_hello_session_id_echo(ssl, &p, end) != 0) { + fatal_alert = MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER; + goto cleanup; + } + + /* ... + * CipherSuite cipher_suite; + * ... + * with CipherSuite defined as: + * uint8 CipherSuite[2]; + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + cipher_suite = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + + + ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(cipher_suite); + /* + * Check whether this ciphersuite is valid and offered. + */ + if ((mbedtls_ssl_validate_ciphersuite(ssl, ciphersuite_info, + ssl->tls_version, + ssl->tls_version) != 0) || + !mbedtls_ssl_tls13_cipher_suite_is_offered(ssl, cipher_suite)) { + fatal_alert = MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER; + } + /* + * If we received an HRR before and that the proposed selected + * ciphersuite in this server hello is not the same as the one + * proposed in the HRR, we abort the handshake and send an + * "illegal_parameter" alert. + */ + else if ((!is_hrr) && (handshake->hello_retry_request_count > 0) && + (cipher_suite != ssl->session_negotiate->ciphersuite)) { + fatal_alert = MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER; + } + + if (fatal_alert == MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER) { + MBEDTLS_SSL_DEBUG_MSG(1, ("invalid ciphersuite(%04x) parameter", + cipher_suite)); + goto cleanup; + } + + /* Configure ciphersuites */ + mbedtls_ssl_optimize_checksum(ssl, ciphersuite_info); + + handshake->ciphersuite_info = ciphersuite_info; + MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, chosen ciphersuite: ( %04x ) - %s", + cipher_suite, ciphersuite_info->name)); + +#if defined(MBEDTLS_HAVE_TIME) + ssl->session_negotiate->start = time(NULL); +#endif /* MBEDTLS_HAVE_TIME */ + + /* ... + * uint8 legacy_compression_method = 0; + * ... + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 1); + if (p[0] != MBEDTLS_SSL_COMPRESS_NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad legacy compression method")); + fatal_alert = MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER; + goto cleanup; + } + p++; + + /* ... + * Extension extensions<6..2^16-1>; + * ... + * struct { + * ExtensionType extension_type; (2 bytes) + * opaque extension_data<0..2^16-1>; + * } Extension; + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + extensions_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + + /* Check extensions do not go beyond the buffer of data. */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len); + extensions_end = p + extensions_len; + + MBEDTLS_SSL_DEBUG_BUF(3, "server hello extensions", p, extensions_len); + + handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE; + allowed_extensions_mask = is_hrr ? + MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_HRR : + MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_SH; + + while (p < extensions_end) { + unsigned int extension_type; + size_t extension_data_len; + const unsigned char *extension_data_end; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4); + extension_type = MBEDTLS_GET_UINT16_BE(p, 0); + extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2); + p += 4; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len); + extension_data_end = p + extension_data_len; + + ret = mbedtls_ssl_tls13_check_received_extension( + ssl, hs_msg_type, extension_type, allowed_extensions_mask); + if (ret != 0) { + return ret; + } + + switch (extension_type) { + case MBEDTLS_TLS_EXT_COOKIE: + + ret = ssl_tls13_parse_cookie_ext(ssl, + p, extension_data_end); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, + "ssl_tls13_parse_cookie_ext", + ret); + goto cleanup; + } + break; + + case MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS: + ret = ssl_tls13_parse_supported_versions_ext(ssl, + p, + extension_data_end); + if (ret != 0) { + goto cleanup; + } + break; + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) + case MBEDTLS_TLS_EXT_PRE_SHARED_KEY: + MBEDTLS_SSL_DEBUG_MSG(3, ("found pre_shared_key extension")); + + if ((ret = ssl_tls13_parse_server_pre_shared_key_ext( + ssl, p, extension_data_end)) != 0) { + MBEDTLS_SSL_DEBUG_RET( + 1, ("ssl_tls13_parse_server_pre_shared_key_ext"), ret); + return ret; + } + break; +#endif + + case MBEDTLS_TLS_EXT_KEY_SHARE: + MBEDTLS_SSL_DEBUG_MSG(3, ("found key_shares extension")); + if (!mbedtls_ssl_conf_tls13_some_ephemeral_enabled(ssl)) { + fatal_alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT; + goto cleanup; + } + + if (is_hrr) { + ret = ssl_tls13_parse_hrr_key_share_ext(ssl, + p, extension_data_end); + } else { + ret = ssl_tls13_parse_key_share_ext(ssl, + p, extension_data_end); + } + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, + "ssl_tls13_parse_key_share_ext", + ret); + goto cleanup; + } + break; + + default: + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + goto cleanup; + } + + p += extension_data_len; + } + + MBEDTLS_SSL_PRINT_EXTS(3, hs_msg_type, handshake->received_extensions); + +cleanup: + + if (fatal_alert == MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT) { + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT, + MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION); + ret = MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION; + } else if (fatal_alert == MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER) { + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + ret = MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + return ret; +} + +#if defined(MBEDTLS_DEBUG_C) +static const char *ssl_tls13_get_kex_mode_str(int mode) +{ + switch (mode) { + case MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK: + return "psk"; + case MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL: + return "ephemeral"; + case MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL: + return "psk_ephemeral"; + default: + return "unknown mode"; + } +} +#endif /* MBEDTLS_DEBUG_C */ + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_postprocess_server_hello(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + /* Determine the key exchange mode: + * 1) If both the pre_shared_key and key_share extensions were received + * then the key exchange mode is PSK with EPHEMERAL. + * 2) If only the pre_shared_key extension was received then the key + * exchange mode is PSK-only. + * 3) If only the key_share extension was received then the key + * exchange mode is EPHEMERAL-only. + */ + switch (handshake->received_extensions & + (MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY) | MBEDTLS_SSL_EXT_MASK(KEY_SHARE))) { + /* Only the pre_shared_key extension was received */ + case MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY): + handshake->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK; + break; + + /* Only the key_share extension was received */ + case MBEDTLS_SSL_EXT_MASK(KEY_SHARE): + handshake->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL; + break; + + /* Both the pre_shared_key and key_share extensions were received */ + case (MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY) | MBEDTLS_SSL_EXT_MASK(KEY_SHARE)): + handshake->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL; + break; + + /* Neither pre_shared_key nor key_share extension was received */ + default: + MBEDTLS_SSL_DEBUG_MSG(1, ("Unknown key exchange.")); + ret = MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + goto cleanup; + } +#if defined(MBEDTLS_SSL_EARLY_DATA) + if (handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(EARLY_DATA) && + (handshake->selected_identity != 0 || + handshake->ciphersuite_info->id != + ssl->session_negotiate->ciphersuite)) { + /* RFC8446 4.2.11 + * If the server supplies an "early_data" extension, the + * client MUST verify that the server's selected_identity + * is 0. If any other value is returned, the client MUST + * abort the handshake with an "illegal_parameter" alert. + * + * RFC 8446 4.2.10 + * In order to accept early data, the server MUST have accepted a PSK + * cipher suite and selected the first key offered in the client's + * "pre_shared_key" extension. In addition, it MUST verify that the + * following values are the same as those associated with the + * selected PSK: + * - The TLS version number + * - The selected cipher suite + * - The selected ALPN [RFC7301] protocol, if any + * + * We check here that when early data is involved the server + * selected the cipher suite associated to the pre-shared key + * as it must have. + */ + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } +#endif + + if (!mbedtls_ssl_conf_tls13_check_kex_modes( + ssl, handshake->key_exchange_mode)) { + ret = MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + MBEDTLS_SSL_DEBUG_MSG(2, + ("Key exchange mode(%s) is not supported.", + ssl_tls13_get_kex_mode_str(handshake->key_exchange_mode))); + goto cleanup; + } + + MBEDTLS_SSL_DEBUG_MSG(3, + ("Selected key exchange mode: %s", + ssl_tls13_get_kex_mode_str(handshake->key_exchange_mode))); + + /* Start the TLS 1.3 key scheduling if not already done. + * + * If we proposed early data then we have already derived an + * early secret using the selected PSK and its associated hash. + * It means that if the negotiated key exchange mode is psk or + * psk_ephemeral, we have already correctly computed the + * early secret and thus we do not do it again. In all other + * cases we compute it here. + */ +#if defined(MBEDTLS_SSL_EARLY_DATA) + if (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT || + handshake->key_exchange_mode == + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL) +#endif + { + ret = mbedtls_ssl_tls13_key_schedule_stage_early(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET( + 1, "mbedtls_ssl_tls13_key_schedule_stage_early", ret); + goto cleanup; + } + } + + ret = mbedtls_ssl_tls13_compute_handshake_transform(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, + "mbedtls_ssl_tls13_compute_handshake_transform", + ret); + goto cleanup; + } + + mbedtls_ssl_set_inbound_transform(ssl, handshake->transform_handshake); + MBEDTLS_SSL_DEBUG_MSG(1, ("Switch to handshake keys for inbound traffic")); + ssl->session_negotiate->ciphersuite = handshake->ciphersuite_info->id; + ssl->session_in = ssl->session_negotiate; + +cleanup: + if (ret != 0) { + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, + MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); + } + + return ret; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_postprocess_hrr(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_ssl_session_reset_msg_layer(ssl, 0); + + /* + * We are going to re-generate a shared secret corresponding to the group + * selected by the server, which is different from the group for which we + * generated a shared secret in the first client hello. + * Thus, reset the shared secret. + */ + ret = ssl_tls13_reset_key_share(ssl); + if (ret != 0) { + return ret; + } + + ssl->session_negotiate->ciphersuite = ssl->handshake->ciphersuite_info->id; + return 0; +} + +/* + * Wait and parse ServerHello handshake message. + * Handler for MBEDTLS_SSL_SERVER_HELLO + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_process_server_hello(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *buf = NULL; + size_t buf_len = 0; + int is_hrr = 0; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> %s", __func__)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg(ssl, + MBEDTLS_SSL_HS_SERVER_HELLO, + &buf, &buf_len)); + + ret = ssl_tls13_preprocess_server_hello(ssl, buf, buf + buf_len); + if (ret < 0) { + goto cleanup; + } else { + is_hrr = (ret == SSL_SERVER_HELLO_HRR); + } + + if (ret == SSL_SERVER_HELLO_TLS1_2) { + ret = 0; + goto cleanup; + } + + MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_server_hello(ssl, buf, + buf + buf_len, + is_hrr)); + if (is_hrr) { + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_reset_transcript_for_hrr(ssl)); + } + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl, + MBEDTLS_SSL_HS_SERVER_HELLO, buf, + buf_len)); + + if (is_hrr) { + MBEDTLS_SSL_PROC_CHK(ssl_tls13_postprocess_hrr(ssl)); +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + /* If not offering early data, the client sends a dummy CCS record + * immediately before its second flight. This may either be before + * its second ClientHello or before its encrypted handshake flight. + */ + mbedtls_ssl_handshake_set_state(ssl, + MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO); +#else + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO); +#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ + } else { + MBEDTLS_SSL_PROC_CHK(ssl_tls13_postprocess_server_hello(ssl)); + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS); + } + +cleanup: + MBEDTLS_SSL_DEBUG_MSG(2, ("<= %s ( %s )", __func__, + is_hrr ? "HelloRetryRequest" : "ServerHello")); + return ret; +} + +/* + * + * Handler for MBEDTLS_SSL_ENCRYPTED_EXTENSIONS + * + * The EncryptedExtensions message contains any extensions which + * should be protected, i.e., any which are not needed to establish + * the cryptographic context. + */ + +/* Parse EncryptedExtensions message + * struct { + * Extension extensions<0..2^16-1>; + * } EncryptedExtensions; + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_encrypted_extensions(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + int ret = 0; + size_t extensions_len; + const unsigned char *p = buf; + const unsigned char *extensions_end; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + extensions_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len); + extensions_end = p + extensions_len; + + MBEDTLS_SSL_DEBUG_BUF(3, "encrypted extensions", p, extensions_len); + + handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE; + + while (p < extensions_end) { + unsigned int extension_type; + size_t extension_data_len; + + /* + * struct { + * ExtensionType extension_type; (2 bytes) + * opaque extension_data<0..2^16-1>; + * } Extension; + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4); + extension_type = MBEDTLS_GET_UINT16_BE(p, 0); + extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2); + p += 4; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len); + + ret = mbedtls_ssl_tls13_check_received_extension( + ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, extension_type, + MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_EE); + if (ret != 0) { + return ret; + } + + switch (extension_type) { +#if defined(MBEDTLS_SSL_ALPN) + case MBEDTLS_TLS_EXT_ALPN: + MBEDTLS_SSL_DEBUG_MSG(3, ("found alpn extension")); + + if ((ret = ssl_tls13_parse_alpn_ext(ssl, p, (size_t) extension_data_len)) != 0) { + return ret; + } + + break; +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_SSL_EARLY_DATA) + case MBEDTLS_TLS_EXT_EARLY_DATA: + + if (extension_data_len != 0) { + /* The message must be empty. */ + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, + MBEDTLS_ERR_SSL_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + break; +#endif /* MBEDTLS_SSL_EARLY_DATA */ + +#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) + case MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT: + MBEDTLS_SSL_DEBUG_MSG(3, ("found record_size_limit extension")); + + ret = mbedtls_ssl_tls13_parse_record_size_limit_ext(ssl, p, p + extension_data_len); + + /* TODO: Return unconditionally here until we handle the record size limit correctly. + * Once handled correctly, only return in case of errors. */ + return ret; + + break; +#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ + + default: + MBEDTLS_SSL_PRINT_EXT( + 3, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, + extension_type, "( ignored )"); + break; + } + + p += extension_data_len; + } + + MBEDTLS_SSL_PRINT_EXTS(3, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, + handshake->received_extensions); + + /* Check that we consumed all the message. */ + if (p != end) { + MBEDTLS_SSL_DEBUG_MSG(1, ("EncryptedExtension lengths misaligned")); + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, + MBEDTLS_ERR_SSL_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + return ret; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_process_encrypted_extensions(mbedtls_ssl_context *ssl) +{ + int ret; + unsigned char *buf; + size_t buf_len; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse encrypted extensions")); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg(ssl, + MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, + &buf, &buf_len)); + + /* Process the message contents */ + MBEDTLS_SSL_PROC_CHK( + ssl_tls13_parse_encrypted_extensions(ssl, buf, buf + buf_len)); + +#if defined(MBEDTLS_SSL_EARLY_DATA) + if (ssl->handshake->received_extensions & + MBEDTLS_SSL_EXT_MASK(EARLY_DATA)) { + ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED; + } +#endif + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl, + MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, + buf, buf_len)); + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) + if (mbedtls_ssl_tls13_key_exchange_mode_with_psk(ssl)) { + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_FINISHED); + } else { + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CERTIFICATE_REQUEST); + } +#else + ((void) ssl); + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_FINISHED); +#endif + +cleanup: + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse encrypted extensions")); + return ret; + +} + +/* + * Handler for MBEDTLS_SSL_END_OF_EARLY_DATA + * + * RFC 8446 section 4.5 + * + * struct {} EndOfEarlyData; + * + * If the server sent an "early_data" extension in EncryptedExtensions, the + * client MUST send an EndOfEarlyData message after receiving the server + * Finished. Otherwise, the client MUST NOT send an EndOfEarlyData message. + */ + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_end_of_early_data(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *buf = NULL; + size_t buf_len; + MBEDTLS_SSL_DEBUG_MSG(2, ("=> write EndOfEarlyData")); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg( + ssl, MBEDTLS_SSL_HS_END_OF_EARLY_DATA, + &buf, &buf_len)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_hdr_to_checksum( + ssl, MBEDTLS_SSL_HS_END_OF_EARLY_DATA, 0)); + + MBEDTLS_SSL_PROC_CHK( + mbedtls_ssl_finish_handshake_msg(ssl, buf_len, 0)); + + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE); + +cleanup: + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= write EndOfEarlyData")); + return ret; +} + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) +/* + * STATE HANDLING: CertificateRequest + * + */ +#define SSL_CERTIFICATE_REQUEST_EXPECT_REQUEST 0 +#define SSL_CERTIFICATE_REQUEST_SKIP 1 +/* Coordination: + * Deals with the ambiguity of not knowing if a CertificateRequest + * will be sent. Returns a negative code on failure, or + * - SSL_CERTIFICATE_REQUEST_EXPECT_REQUEST + * - SSL_CERTIFICATE_REQUEST_SKIP + * indicating if a Certificate Request is expected or not. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_certificate_request_coordinate(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if ((ret = mbedtls_ssl_read_record(ssl, 0)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret); + return ret; + } + ssl->keep_current_message = 1; + + if ((ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE) && + (ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE_REQUEST)) { + MBEDTLS_SSL_DEBUG_MSG(3, ("got a certificate request")); + return SSL_CERTIFICATE_REQUEST_EXPECT_REQUEST; + } + + MBEDTLS_SSL_DEBUG_MSG(3, ("got no certificate request")); + + return SSL_CERTIFICATE_REQUEST_SKIP; +} + +/* + * ssl_tls13_parse_certificate_request() + * Parse certificate request + * struct { + * opaque certificate_request_context<0..2^8-1>; + * Extension extensions<2..2^16-1>; + * } CertificateRequest; + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_certificate_request(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const unsigned char *p = buf; + size_t certificate_request_context_len = 0; + size_t extensions_len = 0; + const unsigned char *extensions_end; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + /* ... + * opaque certificate_request_context<0..2^8-1> + * ... + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 1); + certificate_request_context_len = (size_t) p[0]; + p += 1; + + if (certificate_request_context_len > 0) { + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, certificate_request_context_len); + MBEDTLS_SSL_DEBUG_BUF(3, "Certificate Request Context", + p, certificate_request_context_len); + + handshake->certificate_request_context = + mbedtls_calloc(1, certificate_request_context_len); + if (handshake->certificate_request_context == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("buffer too small")); + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } + memcpy(handshake->certificate_request_context, p, + certificate_request_context_len); + p += certificate_request_context_len; + } + + /* ... + * Extension extensions<2..2^16-1>; + * ... + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + extensions_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len); + extensions_end = p + extensions_len; + + handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE; + + while (p < extensions_end) { + unsigned int extension_type; + size_t extension_data_len; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4); + extension_type = MBEDTLS_GET_UINT16_BE(p, 0); + extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2); + p += 4; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len); + + ret = mbedtls_ssl_tls13_check_received_extension( + ssl, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, extension_type, + MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CR); + if (ret != 0) { + return ret; + } + + switch (extension_type) { + case MBEDTLS_TLS_EXT_SIG_ALG: + MBEDTLS_SSL_DEBUG_MSG(3, + ("found signature algorithms extension")); + ret = mbedtls_ssl_parse_sig_alg_ext(ssl, p, + p + extension_data_len); + if (ret != 0) { + return ret; + } + + break; + + default: + MBEDTLS_SSL_PRINT_EXT( + 3, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, + extension_type, "( ignored )"); + break; + } + + p += extension_data_len; + } + + MBEDTLS_SSL_PRINT_EXTS(3, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, + handshake->received_extensions); + + /* Check that we consumed all the message. */ + if (p != end) { + MBEDTLS_SSL_DEBUG_MSG(1, + ("CertificateRequest misaligned")); + goto decode_error; + } + + /* RFC 8446 section 4.3.2 + * + * The "signature_algorithms" extension MUST be specified + */ + if ((handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(SIG_ALG)) == 0) { + MBEDTLS_SSL_DEBUG_MSG(3, + ("no signature algorithms extension found")); + goto decode_error; + } + + ssl->handshake->client_auth = 1; + return 0; + +decode_error: + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, + MBEDTLS_ERR_SSL_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; +} + +/* + * Handler for MBEDTLS_SSL_CERTIFICATE_REQUEST + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_process_certificate_request(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate request")); + + MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_certificate_request_coordinate(ssl)); + + if (ret == SSL_CERTIFICATE_REQUEST_EXPECT_REQUEST) { + unsigned char *buf; + size_t buf_len; + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg(ssl, + MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, + &buf, &buf_len)); + + MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_certificate_request(ssl, + buf, buf + buf_len)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl, + MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, + buf, buf_len)); + } else if (ret == SSL_CERTIFICATE_REQUEST_SKIP) { + ret = 0; + } else { + MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + goto cleanup; + } + + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_CERTIFICATE); + +cleanup: + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse certificate request")); + return ret; +} + +/* + * Handler for MBEDTLS_SSL_SERVER_CERTIFICATE + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_process_server_certificate(mbedtls_ssl_context *ssl) +{ + int ret; + + ret = mbedtls_ssl_tls13_process_certificate(ssl); + if (ret != 0) { + return ret; + } + + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CERTIFICATE_VERIFY); + return 0; +} + +/* + * Handler for MBEDTLS_SSL_CERTIFICATE_VERIFY + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_process_certificate_verify(mbedtls_ssl_context *ssl) +{ + int ret; + + ret = mbedtls_ssl_tls13_process_certificate_verify(ssl); + if (ret != 0) { + return ret; + } + + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_FINISHED); + return 0; +} +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ + +/* + * Handler for MBEDTLS_SSL_SERVER_FINISHED + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_process_server_finished(mbedtls_ssl_context *ssl) +{ + int ret; + + ret = mbedtls_ssl_tls13_process_finished_message(ssl); + if (ret != 0) { + return ret; + } + + ret = mbedtls_ssl_tls13_compute_application_transform(ssl); + if (ret != 0) { + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, + MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); + return ret; + } + +#if defined(MBEDTLS_SSL_EARLY_DATA) + if (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED) { + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_END_OF_EARLY_DATA); + } else if (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED) { + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE); + } else +#endif /* MBEDTLS_SSL_EARLY_DATA */ + { +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + mbedtls_ssl_handshake_set_state( + ssl, MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED); +#else + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE); +#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ + } + + return 0; +} + +/* + * Handler for MBEDTLS_SSL_CLIENT_CERTIFICATE + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_client_certificate(mbedtls_ssl_context *ssl) +{ + int non_empty_certificate_msg = 0; + + MBEDTLS_SSL_DEBUG_MSG(1, + ("Switch to handshake traffic keys for outbound traffic")); + mbedtls_ssl_set_outbound_transform(ssl, ssl->handshake->transform_handshake); + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) + if (ssl->handshake->client_auth) { + int ret = mbedtls_ssl_tls13_write_certificate(ssl); + if (ret != 0) { + return ret; + } + + if (mbedtls_ssl_own_cert(ssl) != NULL) { + non_empty_certificate_msg = 1; + } + } else { + MBEDTLS_SSL_DEBUG_MSG(2, ("skip write certificate")); + } +#endif + + if (non_empty_certificate_msg) { + mbedtls_ssl_handshake_set_state(ssl, + MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY); + } else { + MBEDTLS_SSL_DEBUG_MSG(2, ("skip write certificate verify")); + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_FINISHED); + } + + return 0; +} + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) +/* + * Handler for MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_client_certificate_verify(mbedtls_ssl_context *ssl) +{ + int ret = mbedtls_ssl_tls13_write_certificate_verify(ssl); + + if (ret == 0) { + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_FINISHED); + } + + return ret; +} +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ + +/* + * Handler for MBEDTLS_SSL_CLIENT_FINISHED + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_client_finished(mbedtls_ssl_context *ssl) +{ + int ret; + + ret = mbedtls_ssl_tls13_write_finished_message(ssl); + if (ret != 0) { + return ret; + } + + ret = mbedtls_ssl_tls13_compute_resumption_master_secret(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, + "mbedtls_ssl_tls13_compute_resumption_master_secret ", ret); + return ret; + } + + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_FLUSH_BUFFERS); + return 0; +} + +/* + * Handler for MBEDTLS_SSL_FLUSH_BUFFERS + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_flush_buffers(mbedtls_ssl_context *ssl) +{ + MBEDTLS_SSL_DEBUG_MSG(2, ("handshake: done")); + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_WRAPUP); + return 0; +} + +/* + * Handler for MBEDTLS_SSL_HANDSHAKE_WRAPUP + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_handshake_wrapup(mbedtls_ssl_context *ssl) +{ + + mbedtls_ssl_tls13_handshake_wrapup(ssl); + + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_OVER); + return 0; +} + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_new_session_ticket_exts(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + const unsigned char *p = buf; + + + handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE; + + while (p < end) { + unsigned int extension_type; + size_t extension_data_len; + int ret; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 4); + extension_type = MBEDTLS_GET_UINT16_BE(p, 0); + extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2); + p += 4; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extension_data_len); + + ret = mbedtls_ssl_tls13_check_received_extension( + ssl, MBEDTLS_SSL_HS_NEW_SESSION_TICKET, extension_type, + MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_NST); + if (ret != 0) { + return ret; + } + + switch (extension_type) { +#if defined(MBEDTLS_SSL_EARLY_DATA) + case MBEDTLS_TLS_EXT_EARLY_DATA: + if (extension_data_len != 4) { + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, + MBEDTLS_ERR_SSL_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + if (ssl->session != NULL) { + ssl->session->ticket_flags |= + MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA; + } + break; +#endif /* MBEDTLS_SSL_EARLY_DATA */ + + default: + MBEDTLS_SSL_PRINT_EXT( + 3, MBEDTLS_SSL_HS_NEW_SESSION_TICKET, + extension_type, "( ignored )"); + break; + } + + p += extension_data_len; + } + + MBEDTLS_SSL_PRINT_EXTS(3, MBEDTLS_SSL_HS_NEW_SESSION_TICKET, + handshake->received_extensions); + + return 0; +} + +/* + * From RFC8446, page 74 + * + * struct { + * uint32 ticket_lifetime; + * uint32 ticket_age_add; + * opaque ticket_nonce<0..255>; + * opaque ticket<1..2^16-1>; + * Extension extensions<0..2^16-2>; + * } NewSessionTicket; + * + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_new_session_ticket(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + unsigned char **ticket_nonce, + size_t *ticket_nonce_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = buf; + mbedtls_ssl_session *session = ssl->session; + size_t ticket_len; + unsigned char *ticket; + size_t extensions_len; + + *ticket_nonce = NULL; + *ticket_nonce_len = 0; + /* + * ticket_lifetime 4 bytes + * ticket_age_add 4 bytes + * ticket_nonce_len 1 byte + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 9); + + session->ticket_lifetime = MBEDTLS_GET_UINT32_BE(p, 0); + MBEDTLS_SSL_DEBUG_MSG(3, + ("ticket_lifetime: %u", + (unsigned int) session->ticket_lifetime)); + + session->ticket_age_add = MBEDTLS_GET_UINT32_BE(p, 4); + MBEDTLS_SSL_DEBUG_MSG(3, + ("ticket_age_add: %u", + (unsigned int) session->ticket_age_add)); + + *ticket_nonce_len = p[8]; + p += 9; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, *ticket_nonce_len); + *ticket_nonce = p; + MBEDTLS_SSL_DEBUG_BUF(3, "ticket_nonce:", *ticket_nonce, *ticket_nonce_len); + p += *ticket_nonce_len; + + /* Ticket */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + ticket_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, ticket_len); + MBEDTLS_SSL_DEBUG_BUF(3, "received ticket", p, ticket_len); + + /* Check if we previously received a ticket already. */ + if (session->ticket != NULL || session->ticket_len > 0) { + mbedtls_free(session->ticket); + session->ticket = NULL; + session->ticket_len = 0; + } + + if ((ticket = mbedtls_calloc(1, ticket_len)) == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("ticket alloc failed")); + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } + memcpy(ticket, p, ticket_len); + p += ticket_len; + session->ticket = ticket; + session->ticket_len = ticket_len; + + /* Clear all flags in ticket_flags */ + mbedtls_ssl_session_clear_ticket_flags( + session, MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK); + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + extensions_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len); + + MBEDTLS_SSL_DEBUG_BUF(3, "ticket extension", p, extensions_len); + + ret = ssl_tls13_parse_new_session_ticket_exts(ssl, p, p + extensions_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, + "ssl_tls13_parse_new_session_ticket_exts", + ret); + return ret; + } + + /* session has been updated, allow export */ + session->exported = 0; + + return 0; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_postprocess_new_session_ticket(mbedtls_ssl_context *ssl, + unsigned char *ticket_nonce, + size_t ticket_nonce_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_session *session = ssl->session; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + psa_algorithm_t psa_hash_alg; + int hash_length; + +#if defined(MBEDTLS_HAVE_TIME) + /* Store ticket creation time */ + session->ticket_received = mbedtls_time(NULL); +#endif + + ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(session->ciphersuite); + if (ciphersuite_info == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + psa_hash_alg = mbedtls_psa_translate_md(ciphersuite_info->mac); + hash_length = PSA_HASH_LENGTH(psa_hash_alg); + if (hash_length == -1 || + (size_t) hash_length > sizeof(session->resumption_key)) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + + MBEDTLS_SSL_DEBUG_BUF(3, "resumption_master_secret", + session->app_secrets.resumption_master_secret, + hash_length); + + /* Compute resumption key + * + * HKDF-Expand-Label( resumption_master_secret, + * "resumption", ticket_nonce, Hash.length ) + */ + ret = mbedtls_ssl_tls13_hkdf_expand_label( + psa_hash_alg, + session->app_secrets.resumption_master_secret, + hash_length, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(resumption), + ticket_nonce, + ticket_nonce_len, + session->resumption_key, + hash_length); + + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(2, + "Creating the ticket-resumed PSK failed", + ret); + return ret; + } + + session->resumption_key_len = hash_length; + + MBEDTLS_SSL_DEBUG_BUF(3, "Ticket-resumed PSK", + session->resumption_key, + session->resumption_key_len); + + /* Set ticket_flags depends on the selected key exchange modes */ + mbedtls_ssl_session_set_ticket_flags( + session, ssl->conf->tls13_kex_modes); + MBEDTLS_SSL_PRINT_TICKET_FLAGS(4, session->ticket_flags); + + return 0; +} + +/* + * Handler for MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_process_new_session_ticket(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *buf; + size_t buf_len; + unsigned char *ticket_nonce; + size_t ticket_nonce_len; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse new session ticket")); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( + ssl, MBEDTLS_SSL_HS_NEW_SESSION_TICKET, + &buf, &buf_len)); + + MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_new_session_ticket( + ssl, buf, buf + buf_len, + &ticket_nonce, &ticket_nonce_len)); + + MBEDTLS_SSL_PROC_CHK(ssl_tls13_postprocess_new_session_ticket( + ssl, ticket_nonce, ticket_nonce_len)); + + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_OVER); + +cleanup: + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse new session ticket")); + return ret; +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +int mbedtls_ssl_tls13_handshake_client_step(mbedtls_ssl_context *ssl) +{ + int ret = 0; + + switch (ssl->state) { + case MBEDTLS_SSL_HELLO_REQUEST: + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO); + break; + + case MBEDTLS_SSL_CLIENT_HELLO: + ret = mbedtls_ssl_write_client_hello(ssl); + break; + + case MBEDTLS_SSL_SERVER_HELLO: + ret = ssl_tls13_process_server_hello(ssl); + break; + + case MBEDTLS_SSL_ENCRYPTED_EXTENSIONS: + ret = ssl_tls13_process_encrypted_extensions(ssl); + break; + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) + case MBEDTLS_SSL_CERTIFICATE_REQUEST: + ret = ssl_tls13_process_certificate_request(ssl); + break; + + case MBEDTLS_SSL_SERVER_CERTIFICATE: + ret = ssl_tls13_process_server_certificate(ssl); + break; + + case MBEDTLS_SSL_CERTIFICATE_VERIFY: + ret = ssl_tls13_process_certificate_verify(ssl); + break; +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ + + case MBEDTLS_SSL_SERVER_FINISHED: + ret = ssl_tls13_process_server_finished(ssl); + break; + + case MBEDTLS_SSL_END_OF_EARLY_DATA: + ret = ssl_tls13_write_end_of_early_data(ssl); + break; + + case MBEDTLS_SSL_CLIENT_CERTIFICATE: + ret = ssl_tls13_write_client_certificate(ssl); + break; + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) + case MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY: + ret = ssl_tls13_write_client_certificate_verify(ssl); + break; +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ + + case MBEDTLS_SSL_CLIENT_FINISHED: + ret = ssl_tls13_write_client_finished(ssl); + break; + + case MBEDTLS_SSL_FLUSH_BUFFERS: + ret = ssl_tls13_flush_buffers(ssl); + break; + + case MBEDTLS_SSL_HANDSHAKE_WRAPUP: + ret = ssl_tls13_handshake_wrapup(ssl); + break; + + /* + * Injection of dummy-CCS's for middlebox compatibility + */ +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + case MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO: + ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl); + if (ret == 0) { + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO); + } + break; + + case MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED: + ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl); + if (ret == 0) { + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE); + } + break; + + case MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO: + ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl); + if (ret == 0) { + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_HELLO); + +#if defined(MBEDTLS_SSL_EARLY_DATA) + MBEDTLS_SSL_DEBUG_MSG( + 1, ("Switch to early data keys for outbound traffic")); + mbedtls_ssl_set_outbound_transform( + ssl, ssl->handshake->transform_earlydata); +#endif + } + break; +#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + case MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET: + ret = ssl_tls13_process_new_session_ticket(ssl); + if (ret != 0) { + break; + } + ret = MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET; + break; +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + + 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 && MBEDTLS_SSL_PROTO_TLS1_3 */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_generic.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_generic.c new file mode 100644 index 0000000..669a90a --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_generic.c @@ -0,0 +1,1627 @@ +/* + * TLS 1.3 functionality shared between client and server + * + * 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) && defined(MBEDTLS_SSL_PROTO_TLS1_3) + +#include + +#include "mbedtls/error.h" +#include "mbedtls/debug.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform.h" +#include "mbedtls/constant_time.h" +#include "psa/crypto.h" +#include "mbedtls/psa_util.h" + +#include "ssl_misc.h" +#include "ssl_tls13_invasive.h" +#include "ssl_tls13_keys.h" +#include "ssl_debug_helpers.h" + +#include "psa/crypto.h" +#include "mbedtls/psa_util.h" + +#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \ + psa_to_ssl_errors, \ + psa_generic_status_to_mbedtls) + +const uint8_t mbedtls_ssl_tls13_hello_retry_request_magic[ + MBEDTLS_SERVER_HELLO_RANDOM_LEN] = +{ 0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11, + 0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91, + 0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E, + 0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C }; + +int mbedtls_ssl_tls13_fetch_handshake_msg(mbedtls_ssl_context *ssl, + unsigned hs_type, + unsigned char **buf, + size_t *buf_len) +{ + int ret; + + if ((ret = mbedtls_ssl_read_record(ssl, 0)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret); + goto cleanup; + } + + if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE || + ssl->in_msg[0] != hs_type) { + MBEDTLS_SSL_DEBUG_MSG(1, ("Receive unexpected handshake message.")); + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE, + MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE); + ret = MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; + goto cleanup; + } + + /* + * Jump handshake header (4 bytes, see Section 4 of RFC 8446). + * ... + * HandshakeType msg_type; + * uint24 length; + * ... + */ + *buf = ssl->in_msg + 4; + *buf_len = ssl->in_hslen - 4; + +cleanup: + + return ret; +} + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) +/* + * STATE HANDLING: Read CertificateVerify + */ +/* Macro to express the maximum length of the verify structure. + * + * The structure is computed per TLS 1.3 specification as: + * - 64 bytes of octet 32, + * - 33 bytes for the context string + * (which is either "TLS 1.3, client CertificateVerify" + * or "TLS 1.3, server CertificateVerify"), + * - 1 byte for the octet 0x0, which serves as a separator, + * - 32 or 48 bytes for the Transcript-Hash(Handshake Context, Certificate) + * (depending on the size of the transcript_hash) + * + * This results in a total size of + * - 130 bytes for a SHA256-based transcript hash, or + * (64 + 33 + 1 + 32 bytes) + * - 146 bytes for a SHA384-based transcript hash. + * (64 + 33 + 1 + 48 bytes) + * + */ +#define SSL_VERIFY_STRUCT_MAX_SIZE (64 + \ + 33 + \ + 1 + \ + MBEDTLS_TLS1_3_MD_MAX_SIZE \ + ) + +/* + * The ssl_tls13_create_verify_structure() creates the verify structure. + * As input, it requires the transcript hash. + * + * The caller has to ensure that the buffer has size at least + * SSL_VERIFY_STRUCT_MAX_SIZE bytes. + */ +static void ssl_tls13_create_verify_structure(const unsigned char *transcript_hash, + size_t transcript_hash_len, + unsigned char *verify_buffer, + size_t *verify_buffer_len, + int from) +{ + size_t idx; + + /* RFC 8446, Section 4.4.3: + * + * The digital signature [in the CertificateVerify message] is then + * computed over the concatenation of: + * - A string that consists of octet 32 (0x20) repeated 64 times + * - The context string + * - A single 0 byte which serves as the separator + * - The content to be signed + */ + memset(verify_buffer, 0x20, 64); + idx = 64; + + if (from == MBEDTLS_SSL_IS_CLIENT) { + memcpy(verify_buffer + idx, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(client_cv)); + idx += MBEDTLS_SSL_TLS1_3_LBL_LEN(client_cv); + } else { /* from == MBEDTLS_SSL_IS_SERVER */ + memcpy(verify_buffer + idx, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(server_cv)); + idx += MBEDTLS_SSL_TLS1_3_LBL_LEN(server_cv); + } + + verify_buffer[idx++] = 0x0; + + memcpy(verify_buffer + idx, transcript_hash, transcript_hash_len); + idx += transcript_hash_len; + + *verify_buffer_len = idx; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_certificate_verify(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end, + const unsigned char *verify_buffer, + size_t verify_buffer_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + const unsigned char *p = buf; + uint16_t algorithm; + size_t signature_len; + mbedtls_pk_type_t sig_alg; + mbedtls_md_type_t md_alg; + psa_algorithm_t hash_alg = PSA_ALG_NONE; + unsigned char verify_hash[PSA_HASH_MAX_SIZE]; + size_t verify_hash_len; + + void const *options = NULL; +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + mbedtls_pk_rsassa_pss_options rsassa_pss_options; +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ + + /* + * struct { + * SignatureScheme algorithm; + * opaque signature<0..2^16-1>; + * } CertificateVerify; + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + algorithm = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + + /* RFC 8446 section 4.4.3 + * + * If the CertificateVerify message is sent by a server, the signature algorithm + * MUST be one offered in the client's "signature_algorithms" extension unless + * no valid certificate chain can be produced without unsupported algorithms + * + * RFC 8446 section 4.4.2.2 + * + * If the client cannot construct an acceptable chain using the provided + * certificates and decides to abort the handshake, then it MUST abort the handshake + * with an appropriate certificate-related alert (by default, "unsupported_certificate"). + * + * Check if algorithm is an offered signature algorithm. + */ + if (!mbedtls_ssl_sig_alg_is_offered(ssl, algorithm)) { + /* algorithm not in offered signature algorithms list */ + MBEDTLS_SSL_DEBUG_MSG(1, ("Received signature algorithm(%04x) is not " + "offered.", + (unsigned int) algorithm)); + goto error; + } + + if (mbedtls_ssl_get_pk_type_and_md_alg_from_sig_alg( + algorithm, &sig_alg, &md_alg) != 0) { + goto error; + } + + hash_alg = mbedtls_hash_info_psa_from_md(md_alg); + if (hash_alg == 0) { + goto error; + } + + MBEDTLS_SSL_DEBUG_MSG(3, ("Certificate Verify: Signature algorithm ( %04x )", + (unsigned int) algorithm)); + + /* + * Check the certificate's key type matches the signature alg + */ + if (!mbedtls_pk_can_do(&ssl->session_negotiate->peer_cert->pk, sig_alg)) { + MBEDTLS_SSL_DEBUG_MSG(1, ("signature algorithm doesn't match cert key")); + goto error; + } + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + signature_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, signature_len); + + status = psa_hash_compute(hash_alg, + verify_buffer, + verify_buffer_len, + verify_hash, + sizeof(verify_hash), + &verify_hash_len); + if (status != PSA_SUCCESS) { + MBEDTLS_SSL_DEBUG_RET(1, "hash computation PSA error", status); + goto error; + } + + MBEDTLS_SSL_DEBUG_BUF(3, "verify hash", verify_hash, verify_hash_len); +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + if (sig_alg == MBEDTLS_PK_RSASSA_PSS) { + rsassa_pss_options.mgf1_hash_id = md_alg; + + rsassa_pss_options.expected_salt_len = PSA_HASH_LENGTH(hash_alg); + options = (const void *) &rsassa_pss_options; + } +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ + + if ((ret = mbedtls_pk_verify_ext(sig_alg, options, + &ssl->session_negotiate->peer_cert->pk, + md_alg, verify_hash, verify_hash_len, + p, signature_len)) == 0) { + return 0; + } + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_pk_verify_ext", ret); + +error: + /* RFC 8446 section 4.4.3 + * + * If the verification fails, the receiver MUST terminate the handshake + * with a "decrypt_error" alert. + */ + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR, + MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + +} +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ + +int mbedtls_ssl_tls13_process_certificate_verify(mbedtls_ssl_context *ssl) +{ + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char verify_buffer[SSL_VERIFY_STRUCT_MAX_SIZE]; + size_t verify_buffer_len; + unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + size_t transcript_len; + unsigned char *buf; + size_t buf_len; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate verify")); + + MBEDTLS_SSL_PROC_CHK( + mbedtls_ssl_tls13_fetch_handshake_msg(ssl, + MBEDTLS_SSL_HS_CERTIFICATE_VERIFY, &buf, &buf_len)); + + /* Need to calculate the hash of the transcript first + * before reading the message since otherwise it gets + * included in the transcript + */ + ret = mbedtls_ssl_get_handshake_transcript(ssl, + ssl->handshake->ciphersuite_info->mac, + transcript, sizeof(transcript), + &transcript_len); + if (ret != 0) { + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR, + MBEDTLS_ERR_SSL_INTERNAL_ERROR); + return ret; + } + + MBEDTLS_SSL_DEBUG_BUF(3, "handshake hash", transcript, transcript_len); + + /* Create verify structure */ + ssl_tls13_create_verify_structure(transcript, + transcript_len, + verify_buffer, + &verify_buffer_len, + (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) ? + MBEDTLS_SSL_IS_SERVER : + MBEDTLS_SSL_IS_CLIENT); + + /* Process the message contents */ + MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_certificate_verify(ssl, buf, + buf + buf_len, verify_buffer, + verify_buffer_len)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl, + MBEDTLS_SSL_HS_CERTIFICATE_VERIFY, + buf, buf_len)); + +cleanup: + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse certificate verify")); + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_process_certificate_verify", ret); + return ret; +#else + ((void) ssl); + MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ +} + +/* + * + * STATE HANDLING: Incoming Certificate. + * + */ + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) +/* + * Structure of Certificate message: + * + * enum { + * X509(0), + * RawPublicKey(2), + * (255) + * } CertificateType; + * + * struct { + * select (certificate_type) { + * case RawPublicKey: + * * From RFC 7250 ASN.1_subjectPublicKeyInfo * + * opaque ASN1_subjectPublicKeyInfo<1..2^24-1>; + * case X509: + * opaque cert_data<1..2^24-1>; + * }; + * Extension extensions<0..2^16-1>; + * } CertificateEntry; + * + * struct { + * opaque certificate_request_context<0..2^8-1>; + * CertificateEntry certificate_list<0..2^24-1>; + * } Certificate; + * + */ + +/* Parse certificate chain send by the server. */ +MBEDTLS_CHECK_RETURN_CRITICAL +MBEDTLS_STATIC_TESTABLE +int mbedtls_ssl_tls13_parse_certificate(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t certificate_request_context_len = 0; + size_t certificate_list_len = 0; + const unsigned char *p = buf; + const unsigned char *certificate_list_end; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 4); + certificate_request_context_len = p[0]; + certificate_list_len = MBEDTLS_GET_UINT24_BE(p, 1); + p += 4; + + /* In theory, the certificate list can be up to 2^24 Bytes, but we don't + * support anything beyond 2^16 = 64K. + */ + if ((certificate_request_context_len != 0) || + (certificate_list_len >= 0x10000)) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message")); + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, + MBEDTLS_ERR_SSL_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + /* In case we tried to reuse a session but it failed */ + if (ssl->session_negotiate->peer_cert != NULL) { + mbedtls_x509_crt_free(ssl->session_negotiate->peer_cert); + mbedtls_free(ssl->session_negotiate->peer_cert); + } + + if (certificate_list_len == 0) { + ssl->session_negotiate->peer_cert = NULL; + ret = 0; + goto exit; + } + + if ((ssl->session_negotiate->peer_cert = + mbedtls_calloc(1, sizeof(mbedtls_x509_crt))) == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("alloc( %" MBEDTLS_PRINTF_SIZET " bytes ) failed", + sizeof(mbedtls_x509_crt))); + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR, + MBEDTLS_ERR_SSL_ALLOC_FAILED); + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } + + mbedtls_x509_crt_init(ssl->session_negotiate->peer_cert); + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, certificate_list_len); + certificate_list_end = p + certificate_list_len; + while (p < certificate_list_end) { + size_t cert_data_len, extensions_len; + const unsigned char *extensions_end; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, certificate_list_end, 3); + cert_data_len = MBEDTLS_GET_UINT24_BE(p, 0); + p += 3; + + /* In theory, the CRT can be up to 2^24 Bytes, but we don't support + * anything beyond 2^16 = 64K. Otherwise as in the TLS 1.2 code, + * check that we have a minimum of 128 bytes of data, this is not + * clear why we need that though. + */ + if ((cert_data_len < 128) || (cert_data_len >= 0x10000)) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad Certificate message")); + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, + MBEDTLS_ERR_SSL_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, certificate_list_end, cert_data_len); + ret = mbedtls_x509_crt_parse_der(ssl->session_negotiate->peer_cert, + p, cert_data_len); + + switch (ret) { + case 0: /*ok*/ + break; + 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: + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR, + MBEDTLS_ERR_X509_ALLOC_FAILED); + MBEDTLS_SSL_DEBUG_RET(1, " mbedtls_x509_crt_parse_der", ret); + return ret; + + case MBEDTLS_ERR_X509_UNKNOWN_VERSION: + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT, + MBEDTLS_ERR_X509_UNKNOWN_VERSION); + MBEDTLS_SSL_DEBUG_RET(1, " mbedtls_x509_crt_parse_der", ret); + return ret; + + default: + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_BAD_CERT, + ret); + MBEDTLS_SSL_DEBUG_RET(1, " mbedtls_x509_crt_parse_der", ret); + return ret; + } + + p += cert_data_len; + + /* Certificate extensions length */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, certificate_list_end, 2); + extensions_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, certificate_list_end, extensions_len); + + extensions_end = p + extensions_len; + handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE; + + while (p < extensions_end) { + unsigned int extension_type; + size_t extension_data_len; + + /* + * struct { + * ExtensionType extension_type; (2 bytes) + * opaque extension_data<0..2^16-1>; + * } Extension; + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4); + extension_type = MBEDTLS_GET_UINT16_BE(p, 0); + extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2); + p += 4; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len); + + ret = mbedtls_ssl_tls13_check_received_extension( + ssl, MBEDTLS_SSL_HS_CERTIFICATE, extension_type, + MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CT); + if (ret != 0) { + return ret; + } + + switch (extension_type) { + default: + MBEDTLS_SSL_PRINT_EXT( + 3, MBEDTLS_SSL_HS_CERTIFICATE, + extension_type, "( ignored )"); + break; + } + + p += extension_data_len; + } + + MBEDTLS_SSL_PRINT_EXTS(3, MBEDTLS_SSL_HS_CERTIFICATE, + handshake->received_extensions); + } + +exit: + /* Check that all the message is consumed. */ + if (p != end) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad Certificate message")); + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, + MBEDTLS_ERR_SSL_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + MBEDTLS_SSL_DEBUG_CRT(3, "peer certificate", ssl->session_negotiate->peer_cert); + + return ret; +} +#else +MBEDTLS_CHECK_RETURN_CRITICAL +MBEDTLS_STATIC_TESTABLE +int mbedtls_ssl_tls13_parse_certificate(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + ((void) ssl); + ((void) buf); + ((void) end); + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; +} +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) +/* Validate certificate chain sent by the server. */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_validate_certificate(mbedtls_ssl_context *ssl) +{ + int ret = 0; + int authmode = MBEDTLS_SSL_VERIFY_REQUIRED; + mbedtls_x509_crt *ca_chain; + mbedtls_x509_crl *ca_crl; + const char *ext_oid; + size_t ext_len; + uint32_t verify_result = 0; + + /* If SNI was used, overwrite authentication mode + * from the configuration. */ +#if defined(MBEDTLS_SSL_SRV_C) + if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { +#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; + } +#endif + + /* + * If the peer hasn't sent a certificate ( i.e. it sent + * an empty certificate chain ), this is reflected in the peer CRT + * structure being unset. + * Check for that and handle it depending on the + * authentication mode. + */ + if (ssl->session_negotiate->peer_cert == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("peer has no certificate")); + +#if defined(MBEDTLS_SSL_SRV_C) + if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { + /* The client was asked for a certificate but didn't send + * one. The client should know what's going on, so we + * don't send an alert. + */ + ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; + if (authmode == MBEDTLS_SSL_VERIFY_OPTIONAL) { + return 0; + } else { + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_NO_CERT, + MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE); + return MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE; + } + } +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_CLI_C) + if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_NO_CERT, + MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE); + return MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE; + } +#endif /* MBEDTLS_SSL_CLI_C */ + } + +#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 /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + { + ca_chain = ssl->conf->ca_chain; + ca_crl = ssl->conf->ca_crl; + } + + /* + * Main check: verify certificate + */ + ret = mbedtls_x509_crt_verify_with_profile( + ssl->session_negotiate->peer_cert, + ca_chain, ca_crl, + ssl->conf->cert_profile, + ssl->hostname, + &verify_result, + ssl->conf->f_vrfy, ssl->conf->p_vrfy); + + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "x509_verify_cert", ret); + } + + /* + * Secondary checks: always done, but change 'ret' only if it was 0 + */ + if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { + 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_key_usage( + ssl->session_negotiate->peer_cert, + MBEDTLS_X509_KU_DIGITAL_SIGNATURE) != 0) || + (mbedtls_x509_crt_check_extended_key_usage( + ssl->session_negotiate->peer_cert, + ext_oid, ext_len) != 0)) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate (usage extensions)")); + if (ret == 0) { + ret = MBEDTLS_ERR_SSL_BAD_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 + * mbedtls_ssl_tls13_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_CERTIFICATE)) { + ret = 0; + } + + if (ca_chain == NULL && authmode == MBEDTLS_SSL_VERIFY_REQUIRED) { + MBEDTLS_SSL_DEBUG_MSG(1, ("got no CA chain")); + ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED; + } + + if (ret != 0) { + /* 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 (verify_result & MBEDTLS_X509_BADCERT_OTHER) { + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED, ret); + } else if (verify_result & MBEDTLS_X509_BADCERT_CN_MISMATCH) { + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_BAD_CERT, ret); + } else if (verify_result & (MBEDTLS_X509_BADCERT_KEY_USAGE | + MBEDTLS_X509_BADCERT_EXT_KEY_USAGE | + MBEDTLS_X509_BADCERT_NS_CERT_TYPE | + MBEDTLS_X509_BADCERT_BAD_PK | + MBEDTLS_X509_BADCERT_BAD_KEY)) { + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT, ret); + } else if (verify_result & MBEDTLS_X509_BADCERT_EXPIRED) { + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED, ret); + } else if (verify_result & MBEDTLS_X509_BADCERT_REVOKED) { + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED, ret); + } else if (verify_result & MBEDTLS_X509_BADCERT_NOT_TRUSTED) { + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA, ret); + } else { + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN, ret); + } + } + +#if defined(MBEDTLS_DEBUG_C) + if (verify_result != 0) { + MBEDTLS_SSL_DEBUG_MSG(3, ("! Certificate verification flags %08x", + (unsigned int) verify_result)); + } else { + MBEDTLS_SSL_DEBUG_MSG(3, ("Certificate verification flags clear")); + } +#endif /* MBEDTLS_DEBUG_C */ + + ssl->session_negotiate->verify_result = verify_result; + return ret; +} +#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_validate_certificate(mbedtls_ssl_context *ssl) +{ + ((void) ssl); + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; +} +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ + +int mbedtls_ssl_tls13_process_certificate(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate")); + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) + unsigned char *buf; + size_t buf_len; + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( + ssl, MBEDTLS_SSL_HS_CERTIFICATE, + &buf, &buf_len)); + + /* Parse the certificate chain sent by the peer. */ + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_parse_certificate(ssl, buf, + buf + buf_len)); + /* Validate the certificate chain and set the verification results. */ + MBEDTLS_SSL_PROC_CHK(ssl_tls13_validate_certificate(ssl)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl, + MBEDTLS_SSL_HS_CERTIFICATE, buf, + buf_len)); + +cleanup: +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse certificate")); + return ret; +} +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) +/* + * enum { + * X509(0), + * RawPublicKey(2), + * (255) + * } CertificateType; + * + * struct { + * select (certificate_type) { + * case RawPublicKey: + * // From RFC 7250 ASN.1_subjectPublicKeyInfo + * opaque ASN1_subjectPublicKeyInfo<1..2^24-1>; + * + * case X509: + * opaque cert_data<1..2^24-1>; + * }; + * Extension extensions<0..2^16-1>; + * } CertificateEntry; + * + * struct { + * opaque certificate_request_context<0..2^8-1>; + * CertificateEntry certificate_list<0..2^24-1>; + * } Certificate; + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_certificate_body(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len) +{ + const mbedtls_x509_crt *crt = mbedtls_ssl_own_cert(ssl); + unsigned char *p = buf; + unsigned char *certificate_request_context = + ssl->handshake->certificate_request_context; + unsigned char certificate_request_context_len = + ssl->handshake->certificate_request_context_len; + unsigned char *p_certificate_list_len; + + + /* ... + * opaque certificate_request_context<0..2^8-1>; + * ... + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, certificate_request_context_len + 1); + *p++ = certificate_request_context_len; + if (certificate_request_context_len > 0) { + memcpy(p, certificate_request_context, certificate_request_context_len); + p += certificate_request_context_len; + } + + /* ... + * CertificateEntry certificate_list<0..2^24-1>; + * ... + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 3); + p_certificate_list_len = p; + p += 3; + + MBEDTLS_SSL_DEBUG_CRT(3, "own certificate", crt); + + while (crt != NULL) { + size_t cert_data_len = crt->raw.len; + + MBEDTLS_SSL_CHK_BUF_PTR(p, end, cert_data_len + 3 + 2); + MBEDTLS_PUT_UINT24_BE(cert_data_len, p, 0); + p += 3; + + memcpy(p, crt->raw.p, cert_data_len); + p += cert_data_len; + crt = crt->next; + + /* Currently, we don't have any certificate extensions defined. + * Hence, we are sending an empty extension with length zero. + */ + MBEDTLS_PUT_UINT16_BE(0, p, 0); + p += 2; + } + + MBEDTLS_PUT_UINT24_BE(p - p_certificate_list_len - 3, + p_certificate_list_len, 0); + + *out_len = p - buf; + + MBEDTLS_SSL_PRINT_EXTS( + 3, MBEDTLS_SSL_HS_CERTIFICATE, ssl->handshake->sent_extensions); + + return 0; +} + +int mbedtls_ssl_tls13_write_certificate(mbedtls_ssl_context *ssl) +{ + int ret; + unsigned char *buf; + size_t buf_len, msg_len; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate")); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(ssl, + MBEDTLS_SSL_HS_CERTIFICATE, &buf, + &buf_len)); + + MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_certificate_body(ssl, + buf, + buf + buf_len, + &msg_len)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl, + MBEDTLS_SSL_HS_CERTIFICATE, buf, + msg_len)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg( + ssl, buf_len, msg_len)); +cleanup: + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= write certificate")); + return ret; +} + +/* + * STATE HANDLING: Output Certificate Verify + */ +int mbedtls_ssl_tls13_check_sig_alg_cert_key_match(uint16_t sig_alg, + mbedtls_pk_context *key) +{ + mbedtls_pk_type_t pk_type = mbedtls_ssl_sig_from_pk(key); + size_t key_size = mbedtls_pk_get_bitlen(key); + + switch (pk_type) { + case MBEDTLS_SSL_SIG_ECDSA: + switch (key_size) { + case 256: + return + sig_alg == MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256; + + case 384: + return + sig_alg == MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384; + + case 521: + return + sig_alg == MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512; + default: + break; + } + break; + + case MBEDTLS_SSL_SIG_RSA: + switch (sig_alg) { + case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256: /* Intentional fallthrough */ + case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384: /* Intentional fallthrough */ + case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512: + return 1; + + default: + break; + } + break; + + default: + break; + } + + return 0; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_certificate_verify_body(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = buf; + mbedtls_pk_context *own_key; + + unsigned char handshake_hash[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + size_t handshake_hash_len; + unsigned char verify_buffer[SSL_VERIFY_STRUCT_MAX_SIZE]; + size_t verify_buffer_len; + + uint16_t *sig_alg = ssl->handshake->received_sig_algs; + size_t signature_len = 0; + + *out_len = 0; + + own_key = mbedtls_ssl_own_key(ssl); + if (own_key == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + ret = mbedtls_ssl_get_handshake_transcript(ssl, + ssl->handshake->ciphersuite_info->mac, + handshake_hash, + sizeof(handshake_hash), + &handshake_hash_len); + if (ret != 0) { + return ret; + } + + MBEDTLS_SSL_DEBUG_BUF(3, "handshake hash", + handshake_hash, + handshake_hash_len); + + ssl_tls13_create_verify_structure(handshake_hash, handshake_hash_len, + verify_buffer, &verify_buffer_len, + ssl->conf->endpoint); + + /* + * struct { + * SignatureScheme algorithm; + * opaque signature<0..2^16-1>; + * } CertificateVerify; + */ + /* Check there is space for the algorithm identifier (2 bytes) and the + * signature length (2 bytes). + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4); + + for (; *sig_alg != MBEDTLS_TLS1_3_SIG_NONE; sig_alg++) { + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_pk_type_t pk_type = MBEDTLS_PK_NONE; + mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; + psa_algorithm_t psa_algorithm = PSA_ALG_NONE; + unsigned char verify_hash[PSA_HASH_MAX_SIZE]; + size_t verify_hash_len; + + if (!mbedtls_ssl_sig_alg_is_offered(ssl, *sig_alg)) { + continue; + } + + if (!mbedtls_ssl_tls13_sig_alg_for_cert_verify_is_supported(*sig_alg)) { + continue; + } + + if (!mbedtls_ssl_tls13_check_sig_alg_cert_key_match(*sig_alg, own_key)) { + continue; + } + + if (mbedtls_ssl_get_pk_type_and_md_alg_from_sig_alg( + *sig_alg, &pk_type, &md_alg) != 0) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + /* Hash verify buffer with indicated hash function */ + psa_algorithm = mbedtls_hash_info_psa_from_md(md_alg); + status = psa_hash_compute(psa_algorithm, + verify_buffer, + verify_buffer_len, + verify_hash, sizeof(verify_hash), + &verify_hash_len); + if (status != PSA_SUCCESS) { + return PSA_TO_MBEDTLS_ERR(status); + } + + MBEDTLS_SSL_DEBUG_BUF(3, "verify hash", verify_hash, verify_hash_len); + + if ((ret = mbedtls_pk_sign_ext(pk_type, own_key, + md_alg, verify_hash, verify_hash_len, + p + 4, (size_t) (end - (p + 4)), &signature_len, + ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { + MBEDTLS_SSL_DEBUG_MSG(2, ("CertificateVerify signature failed with %s", + mbedtls_ssl_sig_alg_to_str(*sig_alg))); + MBEDTLS_SSL_DEBUG_RET(2, "mbedtls_pk_sign_ext", ret); + + /* The signature failed. This is possible if the private key + * was not suitable for the signature operation as purposely we + * did not check its suitability completely. Let's try with + * another signature algorithm. + */ + continue; + } + + MBEDTLS_SSL_DEBUG_MSG(2, ("CertificateVerify signature with %s", + mbedtls_ssl_sig_alg_to_str(*sig_alg))); + + break; + } + + if (*sig_alg == MBEDTLS_TLS1_3_SIG_NONE) { + MBEDTLS_SSL_DEBUG_MSG(1, ("no suitable signature algorithm")); + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, + MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + + MBEDTLS_PUT_UINT16_BE(*sig_alg, p, 0); + MBEDTLS_PUT_UINT16_BE(signature_len, p, 2); + + *out_len = 4 + signature_len; + + return 0; +} + +int mbedtls_ssl_tls13_write_certificate_verify(mbedtls_ssl_context *ssl) +{ + int ret = 0; + unsigned char *buf; + size_t buf_len, msg_len; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate verify")); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(ssl, + MBEDTLS_SSL_HS_CERTIFICATE_VERIFY, &buf, + &buf_len)); + + MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_certificate_verify_body( + ssl, buf, buf + buf_len, &msg_len)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl, + MBEDTLS_SSL_HS_CERTIFICATE_VERIFY, buf, + msg_len)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg( + ssl, buf_len, msg_len)); + +cleanup: + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= write certificate verify")); + return ret; +} + +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ + +/* + * + * STATE HANDLING: Incoming Finished message. + */ +/* + * Implementation + */ + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_preprocess_finished_message(mbedtls_ssl_context *ssl) +{ + int ret; + + ret = mbedtls_ssl_tls13_calculate_verify_data(ssl, + ssl->handshake->state_local.finished_in.digest, + sizeof(ssl->handshake->state_local.finished_in. + digest), + &ssl->handshake->state_local.finished_in.digest_len, + ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ? + MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_calculate_verify_data", ret); + return ret; + } + + return 0; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_finished_message(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + /* + * struct { + * opaque verify_data[Hash.length]; + * } Finished; + */ + const unsigned char *expected_verify_data = + ssl->handshake->state_local.finished_in.digest; + size_t expected_verify_data_len = + ssl->handshake->state_local.finished_in.digest_len; + /* Structural validation */ + if ((size_t) (end - buf) != expected_verify_data_len) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad finished message")); + + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, + MBEDTLS_ERR_SSL_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + MBEDTLS_SSL_DEBUG_BUF(4, "verify_data (self-computed):", + expected_verify_data, + expected_verify_data_len); + MBEDTLS_SSL_DEBUG_BUF(4, "verify_data (received message):", buf, + expected_verify_data_len); + + /* Semantic validation */ + if (mbedtls_ct_memcmp(buf, + expected_verify_data, + expected_verify_data_len) != 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad finished message")); + + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR, + MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + return 0; +} + +int mbedtls_ssl_tls13_process_finished_message(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *buf; + size_t buf_len; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse finished message")); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg(ssl, + MBEDTLS_SSL_HS_FINISHED, + &buf, &buf_len)); + + /* Preprocessing step: Compute handshake digest */ + MBEDTLS_SSL_PROC_CHK(ssl_tls13_preprocess_finished_message(ssl)); + + MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_finished_message(ssl, buf, buf + buf_len)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl, + MBEDTLS_SSL_HS_FINISHED, buf, buf_len)); + +cleanup: + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse finished message")); + return ret; +} + +/* + * + * STATE HANDLING: Write and send Finished message. + * + */ +/* + * Implement + */ + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_prepare_finished_message(mbedtls_ssl_context *ssl) +{ + int ret; + + /* Compute transcript of handshake up to now. */ + ret = mbedtls_ssl_tls13_calculate_verify_data(ssl, + ssl->handshake->state_local.finished_out.digest, + sizeof(ssl->handshake->state_local.finished_out. + digest), + &ssl->handshake->state_local.finished_out.digest_len, + ssl->conf->endpoint); + + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "calculate_verify_data failed", ret); + return ret; + } + + return 0; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_finished_message_body(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len) +{ + size_t verify_data_len = ssl->handshake->state_local.finished_out.digest_len; + /* + * struct { + * opaque verify_data[Hash.length]; + * } Finished; + */ + MBEDTLS_SSL_CHK_BUF_PTR(buf, end, verify_data_len); + + memcpy(buf, ssl->handshake->state_local.finished_out.digest, + verify_data_len); + + *out_len = verify_data_len; + return 0; +} + +/* Main entry point: orchestrates the other functions */ +int mbedtls_ssl_tls13_write_finished_message(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *buf; + size_t buf_len, msg_len; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> write finished message")); + + MBEDTLS_SSL_PROC_CHK(ssl_tls13_prepare_finished_message(ssl)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(ssl, + MBEDTLS_SSL_HS_FINISHED, &buf, &buf_len)); + + MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_finished_message_body( + ssl, buf, buf + buf_len, &msg_len)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl, + MBEDTLS_SSL_HS_FINISHED, buf, msg_len)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg( + ssl, buf_len, msg_len)); +cleanup: + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= write finished message")); + return ret; +} + +void mbedtls_ssl_tls13_handshake_wrapup(mbedtls_ssl_context *ssl) +{ + + MBEDTLS_SSL_DEBUG_MSG(3, ("=> handshake wrapup")); + + MBEDTLS_SSL_DEBUG_MSG(1, ("Switch to application keys for inbound traffic")); + mbedtls_ssl_set_inbound_transform(ssl, ssl->transform_application); + + MBEDTLS_SSL_DEBUG_MSG(1, ("Switch to application keys for outbound traffic")); + mbedtls_ssl_set_outbound_transform(ssl, ssl->transform_application); + + /* + * Free the previous session and switch to the current one. + */ + if (ssl->session) { + mbedtls_ssl_session_free(ssl->session); + mbedtls_free(ssl->session); + } + ssl->session = ssl->session_negotiate; + ssl->session_negotiate = NULL; + + MBEDTLS_SSL_DEBUG_MSG(3, ("<= handshake wrapup")); +} + +/* + * + * STATE HANDLING: Write ChangeCipherSpec + * + */ +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_change_cipher_spec_body(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *olen) +{ + ((void) ssl); + + MBEDTLS_SSL_CHK_BUF_PTR(buf, end, 1); + buf[0] = 1; + *olen = 1; + + return 0; +} + +int mbedtls_ssl_tls13_write_change_cipher_spec(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> write change cipher spec")); + + /* Write CCS message */ + MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_change_cipher_spec_body( + ssl, ssl->out_msg, + ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN, + &ssl->out_msglen)); + + ssl->out_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC; + + /* Dispatch message */ + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_write_record(ssl, 0)); + +cleanup: + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= write change cipher spec")); + return ret; +} + +#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ + +/* Early Data Indication Extension + * + * struct { + * select ( Handshake.msg_type ) { + * ... + * case client_hello: Empty; + * case encrypted_extensions: Empty; + * }; + * } EarlyDataIndication; + */ +#if defined(MBEDTLS_SSL_EARLY_DATA) +int mbedtls_ssl_tls13_write_early_data_ext(mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *out_len) +{ + unsigned char *p = buf; + *out_len = 0; + ((void) ssl); + + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4); + + MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_EARLY_DATA, p, 0); + MBEDTLS_PUT_UINT16_BE(0, p, 2); + + *out_len = 4; + + mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_EARLY_DATA); + + return 0; +} +#endif /* MBEDTLS_SSL_EARLY_DATA */ + +/* Reset SSL context and update hash for handling HRR. + * + * Replace Transcript-Hash(X) by + * Transcript-Hash( message_hash || + * 00 00 Hash.length || + * X ) + * A few states of the handshake are preserved, including: + * - session ID + * - session ticket + * - negotiated ciphersuite + */ +int mbedtls_ssl_reset_transcript_for_hrr(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char hash_transcript[PSA_HASH_MAX_SIZE + 4]; + size_t hash_len; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG(3, ("Reset SSL session for HRR")); + + ret = mbedtls_ssl_get_handshake_transcript(ssl, ciphersuite_info->mac, + hash_transcript + 4, + PSA_HASH_MAX_SIZE, + &hash_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_get_handshake_transcript", ret); + return ret; + } + + hash_transcript[0] = MBEDTLS_SSL_HS_MESSAGE_HASH; + hash_transcript[1] = 0; + hash_transcript[2] = 0; + hash_transcript[3] = (unsigned char) hash_len; + + hash_len += 4; + + MBEDTLS_SSL_DEBUG_BUF(4, "Truncated handshake transcript", + hash_transcript, hash_len); + + /* Reset running hash and replace it with a hash of the transcript */ + ret = mbedtls_ssl_reset_checksum(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_reset_checksum", ret); + return ret; + } + ret = ssl->handshake->update_checksum(ssl, hash_transcript, hash_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "update_checksum", ret); + return ret; + } + + return ret; +} + +#if defined(MBEDTLS_ECDH_C) + +int mbedtls_ssl_tls13_read_public_ecdhe_share(mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t buf_len) +{ + uint8_t *p = (uint8_t *) buf; + const uint8_t *end = buf + buf_len; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + /* Get size of the TLS opaque key_exchange field of the KeyShareEntry struct. */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + uint16_t peerkey_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + + /* Check if key size is consistent with given buffer length. */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, peerkey_len); + + /* Store peer's ECDH public key. */ + memcpy(handshake->ecdh_psa_peerkey, p, peerkey_len); + handshake->ecdh_psa_peerkey_len = peerkey_len; + + return 0; +} + +int mbedtls_ssl_tls13_generate_and_write_ecdh_key_exchange( + mbedtls_ssl_context *ssl, + uint16_t named_group, + unsigned char *buf, + unsigned char *end, + size_t *out_len) +{ + psa_status_t status = PSA_ERROR_GENERIC_ERROR; + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + psa_key_attributes_t key_attributes; + size_t own_pubkey_len; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + psa_ecc_family_t ec_psa_family = 0; + size_t ec_bits = 0; + + MBEDTLS_SSL_DEBUG_MSG(1, ("Perform PSA-based ECDH computation.")); + + /* Convert EC's TLS ID to PSA key type. */ + if (mbedtls_ssl_get_psa_curve_info_from_tls_id(named_group, + &ec_psa_family, + &ec_bits) == PSA_ERROR_NOT_SUPPORTED) { + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + handshake->ecdh_psa_type = PSA_KEY_TYPE_ECC_KEY_PAIR(ec_psa_family); + ssl->handshake->ecdh_bits = ec_bits; + + 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) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_generate_key", ret); + return ret; + + } + + /* Export the public part of the ECDH private key from PSA. */ + status = psa_export_public_key(handshake->ecdh_psa_privkey, + buf, (size_t) (end - buf), + &own_pubkey_len); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_export_public_key", ret); + return ret; + + } + + *out_len = own_pubkey_len; + + return 0; +} +#endif /* MBEDTLS_ECDH_C */ + +/* RFC 8446 section 4.2 + * + * If an implementation receives an extension which it recognizes and which is + * not specified for the message in which it appears, it MUST abort the handshake + * with an "illegal_parameter" alert. + * + */ +int mbedtls_ssl_tls13_check_received_extension( + mbedtls_ssl_context *ssl, + int hs_msg_type, + unsigned int received_extension_type, + uint32_t hs_msg_allowed_extensions_mask) +{ + uint32_t extension_mask = mbedtls_ssl_get_extension_mask( + received_extension_type); + + MBEDTLS_SSL_PRINT_EXT( + 3, hs_msg_type, received_extension_type, "received"); + + if ((extension_mask & hs_msg_allowed_extensions_mask) == 0) { + MBEDTLS_SSL_PRINT_EXT( + 3, hs_msg_type, received_extension_type, "is illegal"); + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + + ssl->handshake->received_extensions |= extension_mask; + /* + * If it is a message containing extension responses, check that we + * previously sent the extension. + */ + switch (hs_msg_type) { + case MBEDTLS_SSL_HS_SERVER_HELLO: + case MBEDTLS_SSL_TLS1_3_HS_HELLO_RETRY_REQUEST: + case MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS: + case MBEDTLS_SSL_HS_CERTIFICATE: + /* Check if the received extension is sent by peer message.*/ + if ((ssl->handshake->sent_extensions & extension_mask) != 0) { + return 0; + } + break; + default: + return 0; + } + + MBEDTLS_SSL_PRINT_EXT( + 3, hs_msg_type, received_extension_type, "is unsupported"); + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT, + MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION); + return MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION; +} + +#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) +/* RFC 8449, section 4: + * + * The ExtensionData of the "record_size_limit" extension is + * RecordSizeLimit: + * uint16 RecordSizeLimit; + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_parse_record_size_limit_ext(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + const unsigned char *p = buf; + uint16_t record_size_limit; + const size_t extension_data_len = end - buf; + + if (extension_data_len != MBEDTLS_SSL_RECORD_SIZE_LIMIT_EXTENSION_DATA_LENGTH) { + MBEDTLS_SSL_DEBUG_MSG(2, + ("record_size_limit extension has invalid length: %" + MBEDTLS_PRINTF_SIZET " Bytes", + extension_data_len)); + + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + record_size_limit = MBEDTLS_GET_UINT16_BE(p, 0); + + MBEDTLS_SSL_DEBUG_MSG(2, ("RecordSizeLimit: %u Bytes", record_size_limit)); + + /* RFC 8449, section 4 + * + * Endpoints MUST NOT send a "record_size_limit" extension with a value + * smaller than 64. An endpoint MUST treat receipt of a smaller value + * as a fatal error and generate an "illegal_parameter" alert. + */ + if (record_size_limit < MBEDTLS_SSL_RECORD_SIZE_LIMIT_MIN) { + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + + MBEDTLS_SSL_DEBUG_MSG(2, + ( + "record_size_limit extension is still in development. Aborting handshake.")); + + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT, + MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION); + return MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION; +} +#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ + +#endif /* MBEDTLS_SSL_TLS_C && MBEDTLS_SSL_PROTO_TLS1_3 */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_invasive.h b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_invasive.h new file mode 100644 index 0000000..3fb79a9 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_invasive.h @@ -0,0 +1,35 @@ +/* + * 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_TLS13_INVASIVE_H +#define MBEDTLS_SSL_TLS13_INVASIVE_H + +#include "common.h" + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + +#include "psa/crypto.h" + +#if defined(MBEDTLS_TEST_HOOKS) +int mbedtls_ssl_tls13_parse_certificate(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end); +#endif /* MBEDTLS_TEST_HOOKS */ + +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + +#endif /* MBEDTLS_SSL_TLS13_INVASIVE_H */ 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..6edce50 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_keys.c @@ -0,0 +1,1861 @@ +/* + * 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) + +#include +#include + +#include "mbedtls/hkdf.h" +#include "mbedtls/debug.h" +#include "mbedtls/error.h" +#include "mbedtls/platform.h" + +#include "ssl_misc.h" +#include "ssl_tls13_keys.h" +#include "ssl_tls13_invasive.h" + +#include "psa/crypto.h" + +#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \ + psa_to_ssl_errors, \ + psa_generic_status_to_mbedtls) + +#define MBEDTLS_SSL_TLS1_3_LABEL(name, string) \ + .name = string, + +struct mbedtls_ssl_tls13_labels_struct const mbedtls_ssl_tls13_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, label_len): 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, ctx_len): 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. + * - dst_len: Pointer at which to store the actual length of + * the HkdfLabel structure on success. + */ + +static const char tls13_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(tls13_label_prefix) + \ + MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN, \ + MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN) + +static void ssl_tls13_hkdf_encode_label( + size_t desired_length, + const unsigned char *label, size_t label_len, + const unsigned char *ctx, size_t ctx_len, + unsigned char *dst, size_t *dst_len) +{ + size_t total_label_len = + sizeof(tls13_label_prefix) + label_len; + size_t total_hkdf_lbl_len = + SSL_TLS1_3_KEY_SCHEDULE_HKDF_LABEL_LEN(total_label_len, ctx_len); + + 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_tls13_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, tls13_label_prefix, sizeof(tls13_label_prefix)); + p += sizeof(tls13_label_prefix); + memcpy(p, label, label_len); + p += label_len; + + /* Add context value */ + *p++ = MBEDTLS_BYTE_0(ctx_len); + if (ctx_len != 0) { + memcpy(p, ctx, ctx_len); + } + + /* Return total length to the caller. */ + *dst_len = total_hkdf_lbl_len; +} + +int mbedtls_ssl_tls13_hkdf_expand_label( + psa_algorithm_t hash_alg, + const unsigned char *secret, size_t secret_len, + const unsigned char *label, size_t label_len, + const unsigned char *ctx, size_t ctx_len, + unsigned char *buf, size_t buf_len) +{ + unsigned char hkdf_label[SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN]; + size_t hkdf_label_len = 0; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_derivation_operation_t operation = + PSA_KEY_DERIVATION_OPERATION_INIT; + + if (label_len > 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 (ctx_len > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN) { + /* Should not happen, as above. */ + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + if (buf_len > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN) { + /* Should not happen, as above. */ + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + if (!PSA_ALG_IS_HASH(hash_alg)) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + ssl_tls13_hkdf_encode_label(buf_len, + label, label_len, + ctx, ctx_len, + hkdf_label, + &hkdf_label_len); + + status = psa_key_derivation_setup(&operation, PSA_ALG_HKDF_EXPAND(hash_alg)); + + if (status != PSA_SUCCESS) { + goto cleanup; + } + + status = psa_key_derivation_input_bytes(&operation, + PSA_KEY_DERIVATION_INPUT_SECRET, + secret, + secret_len); + + if (status != PSA_SUCCESS) { + goto cleanup; + } + + status = psa_key_derivation_input_bytes(&operation, + PSA_KEY_DERIVATION_INPUT_INFO, + hkdf_label, + hkdf_label_len); + + if (status != PSA_SUCCESS) { + goto cleanup; + } + + status = psa_key_derivation_output_bytes(&operation, + buf, + buf_len); + + if (status != PSA_SUCCESS) { + goto cleanup; + } + +cleanup: + abort_status = psa_key_derivation_abort(&operation); + status = (status == PSA_SUCCESS ? abort_status : status); + mbedtls_platform_zeroize(hkdf_label, hkdf_label_len); + return PSA_TO_MBEDTLS_ERR(status); +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_make_traffic_key( + psa_algorithm_t hash_alg, + const unsigned char *secret, size_t secret_len, + unsigned char *key, size_t key_len, + unsigned char *iv, size_t iv_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ret = mbedtls_ssl_tls13_hkdf_expand_label( + hash_alg, + secret, secret_len, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(key), + NULL, 0, + key, key_len); + if (ret != 0) { + return ret; + } + + ret = mbedtls_ssl_tls13_hkdf_expand_label( + hash_alg, + secret, secret_len, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(iv), + NULL, 0, + iv, iv_len); + return ret; +} + +/* + * 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_tls13_make_traffic_keys( + psa_algorithm_t hash_alg, + const unsigned char *client_secret, + const unsigned char *server_secret, size_t secret_len, + size_t key_len, size_t iv_len, + mbedtls_ssl_key_set *keys) +{ + int ret = 0; + + ret = ssl_tls13_make_traffic_key( + hash_alg, client_secret, secret_len, + keys->client_write_key, key_len, + keys->client_write_iv, iv_len); + if (ret != 0) { + return ret; + } + + ret = ssl_tls13_make_traffic_key( + hash_alg, server_secret, secret_len, + keys->server_write_key, key_len, + 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_tls13_derive_secret( + psa_algorithm_t hash_alg, + const unsigned char *secret, size_t secret_len, + const unsigned char *label, size_t label_len, + const unsigned char *ctx, size_t ctx_len, + int ctx_hashed, + unsigned char *dstbuf, size_t dstbuf_len) +{ + int ret; + unsigned char hashed_context[PSA_HASH_MAX_SIZE]; + if (ctx_hashed == MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED) { + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + status = psa_hash_compute(hash_alg, ctx, ctx_len, hashed_context, + PSA_HASH_LENGTH(hash_alg), &ctx_len); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + return ret; + } + } else { + if (ctx_len > 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, ctx_len); + } + + return mbedtls_ssl_tls13_hkdf_expand_label(hash_alg, + secret, secret_len, + label, label_len, + hashed_context, ctx_len, + dstbuf, dstbuf_len); + +} + +int mbedtls_ssl_tls13_evolve_secret( + psa_algorithm_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; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED; + size_t hlen; + unsigned char tmp_secret[PSA_MAC_MAX_SIZE] = { 0 }; + const unsigned char all_zeroes_input[MBEDTLS_TLS1_3_MD_MAX_SIZE] = { 0 }; + const unsigned char *l_input = NULL; + size_t l_input_len; + + psa_key_derivation_operation_t operation = + PSA_KEY_DERIVATION_OPERATION_INIT; + + if (!PSA_ALG_IS_HASH(hash_alg)) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + hlen = PSA_HASH_LENGTH(hash_alg); + + /* For non-initial runs, call Derive-Secret( ., "derived", "") + * on the old secret. */ + if (secret_old != NULL) { + ret = mbedtls_ssl_tls13_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; + } + } + + ret = 0; + + if (input != NULL && input_len != 0) { + l_input = input; + l_input_len = input_len; + } else { + l_input = all_zeroes_input; + l_input_len = hlen; + } + + status = psa_key_derivation_setup(&operation, + PSA_ALG_HKDF_EXTRACT(hash_alg)); + + if (status != PSA_SUCCESS) { + goto cleanup; + } + + status = psa_key_derivation_input_bytes(&operation, + PSA_KEY_DERIVATION_INPUT_SALT, + tmp_secret, + hlen); + + if (status != PSA_SUCCESS) { + goto cleanup; + } + + status = psa_key_derivation_input_bytes(&operation, + PSA_KEY_DERIVATION_INPUT_SECRET, + l_input, l_input_len); + + if (status != PSA_SUCCESS) { + goto cleanup; + } + + status = psa_key_derivation_output_bytes(&operation, + secret_new, + PSA_HASH_LENGTH(hash_alg)); + + if (status != PSA_SUCCESS) { + goto cleanup; + } + +cleanup: + abort_status = psa_key_derivation_abort(&operation); + status = (status == PSA_SUCCESS ? abort_status : status); + ret = (ret == 0 ? PSA_TO_MBEDTLS_ERR(status) : ret); + mbedtls_platform_zeroize(tmp_secret, sizeof(tmp_secret)); + return ret; +} + +int mbedtls_ssl_tls13_derive_early_secrets( + psa_algorithm_t hash_alg, + unsigned char const *early_secret, + unsigned char const *transcript, size_t transcript_len, + mbedtls_ssl_tls13_early_secrets *derived) +{ + int ret; + size_t const hash_len = PSA_HASH_LENGTH(hash_alg); + + /* We should never call this function with an unknown hash, + * but add an assertion anyway. */ + if (!PSA_ALG_IS_HASH(hash_alg)) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + /* + * 0 + * | + * v + * PSK -> HKDF-Extract = Early Secret + * | + * +-----> Derive-Secret(., "c e traffic", ClientHello) + * | = client_early_traffic_secret + * | + * +-----> Derive-Secret(., "e exp master", ClientHello) + * | = early_exporter_master_secret + * v + */ + + /* Create client_early_traffic_secret */ + ret = mbedtls_ssl_tls13_derive_secret(hash_alg, + early_secret, hash_len, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(c_e_traffic), + transcript, transcript_len, + MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, + derived->client_early_traffic_secret, + hash_len); + if (ret != 0) { + return ret; + } + + /* Create early exporter */ + ret = mbedtls_ssl_tls13_derive_secret(hash_alg, + early_secret, hash_len, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(e_exp_master), + transcript, transcript_len, + MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, + derived->early_exporter_master_secret, + hash_len); + if (ret != 0) { + return ret; + } + + return 0; +} + +int mbedtls_ssl_tls13_derive_handshake_secrets( + psa_algorithm_t hash_alg, + unsigned char const *handshake_secret, + unsigned char const *transcript, size_t transcript_len, + mbedtls_ssl_tls13_handshake_secrets *derived) +{ + int ret; + size_t const hash_len = PSA_HASH_LENGTH(hash_alg); + + /* We should never call this function with an unknown hash, + * but add an assertion anyway. */ + if (!PSA_ALG_IS_HASH(hash_alg)) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + /* + * + * Handshake Secret + * | + * +-----> Derive-Secret( ., "c hs traffic", + * | ClientHello...ServerHello ) + * | = client_handshake_traffic_secret + * | + * +-----> Derive-Secret( ., "s hs traffic", + * | ClientHello...ServerHello ) + * | = server_handshake_traffic_secret + * + */ + + /* + * Compute client_handshake_traffic_secret with + * Derive-Secret( ., "c hs traffic", ClientHello...ServerHello ) + */ + + ret = mbedtls_ssl_tls13_derive_secret(hash_alg, + handshake_secret, hash_len, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(c_hs_traffic), + transcript, transcript_len, + MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, + derived->client_handshake_traffic_secret, + hash_len); + if (ret != 0) { + return ret; + } + + /* + * Compute server_handshake_traffic_secret with + * Derive-Secret( ., "s hs traffic", ClientHello...ServerHello ) + */ + + ret = mbedtls_ssl_tls13_derive_secret(hash_alg, + handshake_secret, hash_len, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(s_hs_traffic), + transcript, transcript_len, + MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, + derived->server_handshake_traffic_secret, + hash_len); + if (ret != 0) { + return ret; + } + + return 0; +} + +int mbedtls_ssl_tls13_derive_application_secrets( + psa_algorithm_t hash_alg, + unsigned char const *application_secret, + unsigned char const *transcript, size_t transcript_len, + mbedtls_ssl_tls13_application_secrets *derived) +{ + int ret; + size_t const hash_len = PSA_HASH_LENGTH(hash_alg); + + /* We should never call this function with an unknown hash, + * but add an assertion anyway. */ + if (!PSA_ALG_IS_HASH(hash_alg)) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + /* Generate {client,server}_application_traffic_secret_0 + * + * Master Secret + * | + * +-----> Derive-Secret( ., "c ap traffic", + * | ClientHello...server Finished ) + * | = client_application_traffic_secret_0 + * | + * +-----> Derive-Secret( ., "s ap traffic", + * | ClientHello...Server Finished ) + * | = server_application_traffic_secret_0 + * | + * +-----> Derive-Secret( ., "exp master", + * | ClientHello...server Finished) + * | = exporter_master_secret + * + */ + + ret = mbedtls_ssl_tls13_derive_secret(hash_alg, + application_secret, hash_len, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(c_ap_traffic), + transcript, transcript_len, + MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, + derived->client_application_traffic_secret_N, + hash_len); + if (ret != 0) { + return ret; + } + + ret = mbedtls_ssl_tls13_derive_secret(hash_alg, + application_secret, hash_len, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(s_ap_traffic), + transcript, transcript_len, + MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, + derived->server_application_traffic_secret_N, + hash_len); + if (ret != 0) { + return ret; + } + + ret = mbedtls_ssl_tls13_derive_secret(hash_alg, + application_secret, hash_len, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(exp_master), + transcript, transcript_len, + MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, + derived->exporter_master_secret, + hash_len); + if (ret != 0) { + return ret; + } + + return 0; +} + +/* Generate resumption_master_secret for use with the ticket exchange. + * + * This is not integrated with mbedtls_ssl_tls13_derive_application_secrets() + * because it uses the transcript hash up to and including ClientFinished. */ +int mbedtls_ssl_tls13_derive_resumption_master_secret( + psa_algorithm_t hash_alg, + unsigned char const *application_secret, + unsigned char const *transcript, size_t transcript_len, + mbedtls_ssl_tls13_application_secrets *derived) +{ + int ret; + size_t const hash_len = PSA_HASH_LENGTH(hash_alg); + + /* We should never call this function with an unknown hash, + * but add an assertion anyway. */ + if (!PSA_ALG_IS_HASH(hash_alg)) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + ret = mbedtls_ssl_tls13_derive_secret(hash_alg, + application_secret, hash_len, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(res_master), + transcript, transcript_len, + MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, + derived->resumption_master_secret, + hash_len); + + if (ret != 0) { + return ret; + } + + return 0; +} + +/** + * \brief Transition into application stage of TLS 1.3 key schedule. + * + * The TLS 1.3 key schedule can be viewed as a simple state machine + * with states Initial -> Early -> Handshake -> Application, and + * this function represents the Handshake -> Application transition. + * + * In the handshake stage, ssl_tls13_generate_application_keys() + * can be used to derive the handshake traffic keys. + * + * \param ssl The SSL context to operate on. This must be in key schedule + * stage \c Handshake. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_key_schedule_stage_application(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + psa_algorithm_t const hash_alg = mbedtls_hash_info_psa_from_md( + handshake->ciphersuite_info->mac); + + /* + * Compute MasterSecret + */ + ret = mbedtls_ssl_tls13_evolve_secret(hash_alg, + handshake->tls13_master_secrets.handshake, + NULL, 0, + handshake->tls13_master_secrets.app); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_evolve_secret", ret); + return ret; + } + + MBEDTLS_SSL_DEBUG_BUF(4, "Master secret", + handshake->tls13_master_secrets.app, PSA_HASH_LENGTH(hash_alg)); + + return 0; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_calc_finished_core(psa_algorithm_t hash_alg, + unsigned char const *base_key, + unsigned char const *transcript, + unsigned char *dst, + size_t *dst_len) +{ + mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t hash_len = PSA_HASH_LENGTH(hash_alg); + unsigned char finished_key[PSA_MAC_MAX_SIZE]; + int ret; + psa_algorithm_t alg; + + /* We should never call this function with an unknown hash, + * but add an assertion anyway. */ + if (!PSA_ALG_IS_HASH(hash_alg)) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + /* TLS 1.3 Finished message + * + * struct { + * opaque verify_data[Hash.length]; + * } Finished; + * + * verify_data = + * HMAC( finished_key, + * Hash( Handshake Context + + * Certificate* + + * CertificateVerify* ) + * ) + * + * finished_key = + * HKDF-Expand-Label( BaseKey, "finished", "", Hash.length ) + */ + + ret = mbedtls_ssl_tls13_hkdf_expand_label( + hash_alg, base_key, hash_len, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(finished), + NULL, 0, + finished_key, hash_len); + if (ret != 0) { + goto exit; + } + + alg = PSA_ALG_HMAC(hash_alg); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE); + psa_set_key_algorithm(&attributes, alg); + psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC); + + status = psa_import_key(&attributes, finished_key, hash_len, &key); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + goto exit; + } + + status = psa_mac_compute(key, alg, transcript, hash_len, + dst, hash_len, dst_len); + ret = PSA_TO_MBEDTLS_ERR(status); + +exit: + + status = psa_destroy_key(key); + if (ret == 0) { + ret = PSA_TO_MBEDTLS_ERR(status); + } + + mbedtls_platform_zeroize(finished_key, sizeof(finished_key)); + + return ret; +} + +int mbedtls_ssl_tls13_calculate_verify_data(mbedtls_ssl_context *ssl, + unsigned char *dst, + size_t dst_len, + size_t *actual_len, + int from) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + size_t transcript_len; + + unsigned char *base_key = NULL; + size_t base_key_len = 0; + mbedtls_ssl_tls13_handshake_secrets *tls13_hs_secrets = + &ssl->handshake->tls13_hs_secrets; + + mbedtls_md_type_t const md_type = ssl->handshake->ciphersuite_info->mac; + + psa_algorithm_t hash_alg = mbedtls_hash_info_psa_from_md( + ssl->handshake->ciphersuite_info->mac); + size_t const hash_len = PSA_HASH_LENGTH(hash_alg); + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> mbedtls_ssl_tls13_calculate_verify_data")); + + if (from == MBEDTLS_SSL_IS_CLIENT) { + base_key = tls13_hs_secrets->client_handshake_traffic_secret; + base_key_len = sizeof(tls13_hs_secrets->client_handshake_traffic_secret); + } else { + base_key = tls13_hs_secrets->server_handshake_traffic_secret; + base_key_len = sizeof(tls13_hs_secrets->server_handshake_traffic_secret); + } + + if (dst_len < hash_len) { + ret = MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; + goto exit; + } + + ret = mbedtls_ssl_get_handshake_transcript(ssl, md_type, + transcript, sizeof(transcript), + &transcript_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_get_handshake_transcript", ret); + goto exit; + } + MBEDTLS_SSL_DEBUG_BUF(4, "handshake hash", transcript, transcript_len); + + ret = ssl_tls13_calc_finished_core(hash_alg, base_key, transcript, dst, actual_len); + if (ret != 0) { + goto exit; + } + + MBEDTLS_SSL_DEBUG_BUF(3, "verify_data for finished message", dst, hash_len); + MBEDTLS_SSL_DEBUG_MSG(2, ("<= mbedtls_ssl_tls13_calculate_verify_data")); + +exit: + /* Erase handshake secrets */ + mbedtls_platform_zeroize(base_key, base_key_len); + mbedtls_platform_zeroize(transcript, sizeof(transcript)); + return ret; +} + +int mbedtls_ssl_tls13_create_psk_binder(mbedtls_ssl_context *ssl, + const psa_algorithm_t hash_alg, + unsigned char const *psk, size_t psk_len, + int psk_type, + unsigned char const *transcript, + unsigned char *result) +{ + int ret = 0; + unsigned char binder_key[PSA_MAC_MAX_SIZE]; + unsigned char early_secret[PSA_MAC_MAX_SIZE]; + size_t const hash_len = PSA_HASH_LENGTH(hash_alg); + size_t actual_len; + +#if !defined(MBEDTLS_DEBUG_C) + ssl = NULL; /* make sure we don't use it except for debug */ + ((void) ssl); +#endif + + /* We should never call this function with an unknown hash, + * but add an assertion anyway. */ + if (!PSA_ALG_IS_HASH(hash_alg)) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + /* + * 0 + * | + * v + * PSK -> HKDF-Extract = Early Secret + * | + * +-----> Derive-Secret(., "ext binder" | "res binder", "") + * | = binder_key + * v + */ + + ret = mbedtls_ssl_tls13_evolve_secret(hash_alg, + NULL, /* Old secret */ + psk, psk_len, /* Input */ + early_secret); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_evolve_secret", ret); + goto exit; + } + + MBEDTLS_SSL_DEBUG_BUF(4, "mbedtls_ssl_tls13_create_psk_binder", + early_secret, hash_len); + + if (psk_type == MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION) { + ret = mbedtls_ssl_tls13_derive_secret(hash_alg, + early_secret, hash_len, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(res_binder), + NULL, 0, MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED, + binder_key, hash_len); + MBEDTLS_SSL_DEBUG_MSG(4, ("Derive Early Secret with 'res binder'")); + } else { + ret = mbedtls_ssl_tls13_derive_secret(hash_alg, + early_secret, hash_len, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(ext_binder), + NULL, 0, MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED, + binder_key, hash_len); + MBEDTLS_SSL_DEBUG_MSG(4, ("Derive Early Secret with 'ext binder'")); + } + + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_derive_secret", ret); + goto exit; + } + + /* + * The binding_value is computed in the same way as the Finished message + * but with the BaseKey being the binder_key. + */ + + ret = ssl_tls13_calc_finished_core(hash_alg, binder_key, transcript, + result, &actual_len); + if (ret != 0) { + goto exit; + } + + MBEDTLS_SSL_DEBUG_BUF(3, "psk binder", result, actual_len); + +exit: + + mbedtls_platform_zeroize(early_secret, sizeof(early_secret)); + mbedtls_platform_zeroize(binder_key, sizeof(binder_key)); + return ret; +} + +int mbedtls_ssl_tls13_populate_transform(mbedtls_ssl_transform *transform, + int endpoint, + int ciphersuite, + mbedtls_ssl_key_set const *traffic_keys, + mbedtls_ssl_context *ssl /* DEBUG ONLY */) +{ +#if !defined(MBEDTLS_USE_PSA_CRYPTO) + int ret; + mbedtls_cipher_info_t const *cipher_info; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + unsigned char const *key_enc; + unsigned char const *iv_enc; + unsigned char const *key_dec; + unsigned char const *iv_dec; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_key_type_t key_type; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_algorithm_t alg; + size_t key_bits; + psa_status_t status = PSA_SUCCESS; +#endif + +#if !defined(MBEDTLS_DEBUG_C) + ssl = NULL; /* make sure we don't use it except for those cases */ + (void) ssl; +#endif + + 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; + } + +#if !defined(MBEDTLS_USE_PSA_CRYPTO) + 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; + } + + /* + * Setup cipher contexts in target transform + */ + if ((ret = mbedtls_cipher_setup(&transform->cipher_ctx_enc, + cipher_info)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setup", ret); + return ret; + } + + if ((ret = mbedtls_cipher_setup(&transform->cipher_ctx_dec, + cipher_info)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setup", ret); + return ret; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_SSL_SRV_C) + if (endpoint == MBEDTLS_SSL_IS_SERVER) { + key_enc = traffic_keys->server_write_key; + key_dec = traffic_keys->client_write_key; + iv_enc = traffic_keys->server_write_iv; + iv_dec = traffic_keys->client_write_iv; + } else +#endif /* MBEDTLS_SSL_SRV_C */ +#if defined(MBEDTLS_SSL_CLI_C) + if (endpoint == MBEDTLS_SSL_IS_CLIENT) { + key_enc = traffic_keys->client_write_key; + key_dec = traffic_keys->server_write_key; + iv_enc = traffic_keys->client_write_iv; + iv_dec = traffic_keys->server_write_iv; + } else +#endif /* MBEDTLS_SSL_CLI_C */ + { + /* should not happen */ + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + memcpy(transform->iv_enc, iv_enc, traffic_keys->iv_len); + memcpy(transform->iv_dec, iv_dec, traffic_keys->iv_len); + +#if !defined(MBEDTLS_USE_PSA_CRYPTO) + if ((ret = mbedtls_cipher_setkey(&transform->cipher_ctx_enc, + key_enc, cipher_info->key_bitlen, + MBEDTLS_ENCRYPT)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setkey", ret); + return ret; + } + + if ((ret = mbedtls_cipher_setkey(&transform->cipher_ctx_dec, + key_dec, cipher_info->key_bitlen, + MBEDTLS_DECRYPT)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setkey", ret); + return ret; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + /* + * Setup other fields in SSL transform + */ + + if ((ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG) != 0) { + transform->taglen = 8; + } else { + transform->taglen = 16; + } + + transform->ivlen = traffic_keys->iv_len; + transform->maclen = 0; + transform->fixed_ivlen = transform->ivlen; + transform->tls_version = MBEDTLS_SSL_VERSION_TLS1_3; + + /* We add the true record content type (1 Byte) to the plaintext and + * then pad to the configured granularity. The minimum length of the + * type-extended and padded plaintext is therefore the padding + * granularity. */ + transform->minlen = + transform->taglen + MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /* + * Setup psa keys and alg + */ + if ((status = mbedtls_ssl_cipher_to_psa(ciphersuite_info->cipher, + transform->taglen, + &alg, + &key_type, + &key_bits)) != PSA_SUCCESS) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_cipher_to_psa", PSA_TO_MBEDTLS_ERR(status)); + return PSA_TO_MBEDTLS_ERR(status); + } + + transform->psa_alg = alg; + + if (alg != MBEDTLS_SSL_NULL_CIPHER) { + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT); + psa_set_key_algorithm(&attributes, alg); + psa_set_key_type(&attributes, key_type); + + if ((status = psa_import_key(&attributes, + key_enc, + PSA_BITS_TO_BYTES(key_bits), + &transform->psa_key_enc)) != PSA_SUCCESS) { + MBEDTLS_SSL_DEBUG_RET(1, "psa_import_key", PSA_TO_MBEDTLS_ERR(status)); + return PSA_TO_MBEDTLS_ERR(status); + } + + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT); + + if ((status = psa_import_key(&attributes, + key_dec, + PSA_BITS_TO_BYTES(key_bits), + &transform->psa_key_dec)) != PSA_SUCCESS) { + MBEDTLS_SSL_DEBUG_RET(1, "psa_import_key", PSA_TO_MBEDTLS_ERR(status)); + return PSA_TO_MBEDTLS_ERR(status); + } + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + return 0; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_get_cipher_key_info( + const mbedtls_ssl_ciphersuite_t *ciphersuite_info, + size_t *key_len, size_t *iv_len) +{ + psa_key_type_t key_type; + psa_algorithm_t alg; + size_t taglen; + size_t key_bits; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + if (ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG) { + taglen = 8; + } else { + taglen = 16; + } + + status = mbedtls_ssl_cipher_to_psa(ciphersuite_info->cipher, taglen, + &alg, &key_type, &key_bits); + if (status != PSA_SUCCESS) { + return PSA_TO_MBEDTLS_ERR(status); + } + + *key_len = PSA_BITS_TO_BYTES(key_bits); + + /* TLS 1.3 only have AEAD ciphers, IV length is unconditionally 12 bytes */ + *iv_len = 12; + + return 0; +} + +#if defined(MBEDTLS_SSL_EARLY_DATA) +/* + * ssl_tls13_generate_early_key() generates the key necessary for protecting + * the early application data and handshake messages as described in section 7 + * of RFC 8446. + * + * NOTE: Only one key is generated, the key for the traffic from the client to + * the server. The TLS 1.3 specification does not define a secret and thus + * a key for server early traffic. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_generate_early_key(mbedtls_ssl_context *ssl, + mbedtls_ssl_key_set *traffic_keys) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_md_type_t md_type; + psa_algorithm_t hash_alg; + size_t hash_len; + unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + size_t transcript_len; + size_t key_len; + size_t iv_len; + mbedtls_ssl_tls13_early_secrets tls13_early_secrets; + + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = handshake->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> ssl_tls13_generate_early_key")); + + ret = ssl_tls13_get_cipher_key_info(ciphersuite_info, &key_len, &iv_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_get_cipher_key_info", ret); + goto cleanup; + } + + md_type = ciphersuite_info->mac; + + hash_alg = mbedtls_hash_info_psa_from_md(ciphersuite_info->mac); + hash_len = PSA_HASH_LENGTH(hash_alg); + + ret = mbedtls_ssl_get_handshake_transcript(ssl, md_type, + transcript, + sizeof(transcript), + &transcript_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, + "mbedtls_ssl_get_handshake_transcript", + ret); + goto cleanup; + } + + ret = mbedtls_ssl_tls13_derive_early_secrets( + hash_alg, handshake->tls13_master_secrets.early, + transcript, transcript_len, &tls13_early_secrets); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET( + 1, "mbedtls_ssl_tls13_derive_early_secrets", ret); + goto cleanup; + } + + MBEDTLS_SSL_DEBUG_BUF( + 4, "Client early traffic secret", + tls13_early_secrets.client_early_traffic_secret, hash_len); + + /* + * Export client handshake traffic secret + */ + if (ssl->f_export_keys != NULL) { + ssl->f_export_keys( + ssl->p_export_keys, + MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_EARLY_SECRET, + tls13_early_secrets.client_early_traffic_secret, + hash_len, + handshake->randbytes, + handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN, + MBEDTLS_SSL_TLS_PRF_NONE /* TODO: FIX! */); + } + + ret = ssl_tls13_make_traffic_key( + hash_alg, + tls13_early_secrets.client_early_traffic_secret, + hash_len, traffic_keys->client_write_key, key_len, + traffic_keys->client_write_iv, iv_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_make_traffic_key", ret); + goto cleanup; + } + traffic_keys->key_len = key_len; + traffic_keys->iv_len = iv_len; + + MBEDTLS_SSL_DEBUG_BUF(4, "client early write_key", + traffic_keys->client_write_key, + traffic_keys->key_len); + + MBEDTLS_SSL_DEBUG_BUF(4, "client early write_iv", + traffic_keys->client_write_iv, + traffic_keys->iv_len); + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= ssl_tls13_generate_early_key")); + +cleanup: + /* Erase early secrets and transcript */ + mbedtls_platform_zeroize( + &tls13_early_secrets, sizeof(mbedtls_ssl_tls13_early_secrets)); + mbedtls_platform_zeroize(transcript, sizeof(transcript)); + return ret; +} + +int mbedtls_ssl_tls13_compute_early_transform(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_key_set traffic_keys; + mbedtls_ssl_transform *transform_earlydata = NULL; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + /* Next evolution in key schedule: Establish early_data secret and + * key material. */ + ret = ssl_tls13_generate_early_key(ssl, &traffic_keys); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_generate_early_key", + ret); + goto cleanup; + } + + transform_earlydata = mbedtls_calloc(1, sizeof(mbedtls_ssl_transform)); + if (transform_earlydata == NULL) { + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto cleanup; + } + + ret = mbedtls_ssl_tls13_populate_transform( + transform_earlydata, + ssl->conf->endpoint, + handshake->ciphersuite_info->id, + &traffic_keys, + ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_populate_transform", ret); + goto cleanup; + } + handshake->transform_earlydata = transform_earlydata; + +cleanup: + mbedtls_platform_zeroize(&traffic_keys, sizeof(traffic_keys)); + if (ret != 0) { + mbedtls_free(transform_earlydata); + } + + return ret; +} +#endif /* MBEDTLS_SSL_EARLY_DATA */ + +int mbedtls_ssl_tls13_key_schedule_stage_early(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + psa_algorithm_t hash_alg; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + unsigned char *psk = NULL; + size_t psk_len = 0; + + if (handshake->ciphersuite_info == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("cipher suite info not found")); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + hash_alg = mbedtls_hash_info_psa_from_md(handshake->ciphersuite_info->mac); +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) + if (mbedtls_ssl_tls13_key_exchange_mode_with_psk(ssl)) { + ret = mbedtls_ssl_tls13_export_handshake_psk(ssl, &psk, &psk_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_export_handshake_psk", + ret); + return ret; + } + } +#endif + + ret = mbedtls_ssl_tls13_evolve_secret(hash_alg, NULL, psk, psk_len, + handshake->tls13_master_secrets.early); +#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) + mbedtls_free((void *) psk); +#endif + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_evolve_secret", ret); + return ret; + } + + MBEDTLS_SSL_DEBUG_BUF(4, "mbedtls_ssl_tls13_key_schedule_stage_early", + handshake->tls13_master_secrets.early, + PSA_HASH_LENGTH(hash_alg)); + return 0; +} + +/** + * \brief Compute TLS 1.3 handshake traffic keys. + * + * ssl_tls13_generate_handshake_keys() generates keys necessary for + * protecting the handshake messages, as described in Section 7 of + * RFC 8446. + * + * \param ssl The SSL context to operate on. This must be in + * key schedule stage \c Handshake, see + * ssl_tls13_key_schedule_stage_handshake(). + * \param traffic_keys The address at which to store the handshake traffic + * keys. This must be writable but may be uninitialized. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_generate_handshake_keys(mbedtls_ssl_context *ssl, + mbedtls_ssl_key_set *traffic_keys) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_md_type_t md_type; + psa_algorithm_t hash_alg; + size_t hash_len; + unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + size_t transcript_len; + size_t key_len; + size_t iv_len; + + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = handshake->ciphersuite_info; + mbedtls_ssl_tls13_handshake_secrets *tls13_hs_secrets = &handshake->tls13_hs_secrets; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> ssl_tls13_generate_handshake_keys")); + + ret = ssl_tls13_get_cipher_key_info(ciphersuite_info, &key_len, &iv_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_get_cipher_key_info", ret); + return ret; + } + + md_type = ciphersuite_info->mac; + + hash_alg = mbedtls_hash_info_psa_from_md(ciphersuite_info->mac); + hash_len = PSA_HASH_LENGTH(hash_alg); + + ret = mbedtls_ssl_get_handshake_transcript(ssl, md_type, + transcript, + sizeof(transcript), + &transcript_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, + "mbedtls_ssl_get_handshake_transcript", + ret); + return ret; + } + + ret = mbedtls_ssl_tls13_derive_handshake_secrets(hash_alg, + handshake->tls13_master_secrets.handshake, + transcript, transcript_len, tls13_hs_secrets); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_derive_handshake_secrets", + ret); + return ret; + } + + MBEDTLS_SSL_DEBUG_BUF(4, "Client handshake traffic secret", + tls13_hs_secrets->client_handshake_traffic_secret, + hash_len); + MBEDTLS_SSL_DEBUG_BUF(4, "Server handshake traffic secret", + tls13_hs_secrets->server_handshake_traffic_secret, + hash_len); + + /* + * Export client handshake traffic secret + */ + if (ssl->f_export_keys != NULL) { + ssl->f_export_keys(ssl->p_export_keys, + MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_HANDSHAKE_TRAFFIC_SECRET, + tls13_hs_secrets->client_handshake_traffic_secret, + hash_len, + handshake->randbytes, + handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN, + MBEDTLS_SSL_TLS_PRF_NONE /* TODO: FIX! */); + + ssl->f_export_keys(ssl->p_export_keys, + MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_HANDSHAKE_TRAFFIC_SECRET, + tls13_hs_secrets->server_handshake_traffic_secret, + hash_len, + handshake->randbytes, + handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN, + MBEDTLS_SSL_TLS_PRF_NONE /* TODO: FIX! */); + } + + ret = mbedtls_ssl_tls13_make_traffic_keys(hash_alg, + tls13_hs_secrets->client_handshake_traffic_secret, + tls13_hs_secrets->server_handshake_traffic_secret, + hash_len, key_len, iv_len, traffic_keys); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_make_traffic_keys", ret); + goto exit; + } + + MBEDTLS_SSL_DEBUG_BUF(4, "client_handshake write_key", + traffic_keys->client_write_key, + traffic_keys->key_len); + + MBEDTLS_SSL_DEBUG_BUF(4, "server_handshake write_key", + traffic_keys->server_write_key, + traffic_keys->key_len); + + MBEDTLS_SSL_DEBUG_BUF(4, "client_handshake write_iv", + traffic_keys->client_write_iv, + traffic_keys->iv_len); + + MBEDTLS_SSL_DEBUG_BUF(4, "server_handshake write_iv", + traffic_keys->server_write_iv, + traffic_keys->iv_len); + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= ssl_tls13_generate_handshake_keys")); + +exit: + + return ret; +} + +/** + * \brief Transition into handshake stage of TLS 1.3 key schedule. + * + * The TLS 1.3 key schedule can be viewed as a simple state machine + * with states Initial -> Early -> Handshake -> Application, and + * this function represents the Early -> Handshake transition. + * + * In the handshake stage, ssl_tls13_generate_handshake_keys() + * can be used to derive the handshake traffic keys. + * + * \param ssl The SSL context to operate on. This must be in key schedule + * stage \c Early. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_key_schedule_stage_handshake(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + psa_algorithm_t const hash_alg = mbedtls_hash_info_psa_from_md( + handshake->ciphersuite_info->mac); + unsigned char *shared_secret = NULL; + size_t shared_secret_len = 0; + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) + /* + * Compute ECDHE secret used to compute the handshake secret from which + * client_handshake_traffic_secret and server_handshake_traffic_secret + * are derived in the handshake secret derivation stage. + */ + if (mbedtls_ssl_tls13_key_exchange_mode_with_ephemeral(ssl)) { + if (mbedtls_ssl_tls13_named_group_is_ecdhe(handshake->offered_group_id)) { +#if defined(MBEDTLS_ECDH_C) + /* Compute ECDH shared secret. */ + psa_status_t status = PSA_ERROR_GENERIC_ERROR; + psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT; + + status = psa_get_key_attributes(handshake->ecdh_psa_privkey, + &key_attributes); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + } + + shared_secret_len = PSA_BITS_TO_BYTES( + psa_get_key_bits(&key_attributes)); + shared_secret = mbedtls_calloc(1, shared_secret_len); + if (shared_secret == NULL) { + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } + + status = psa_raw_key_agreement( + PSA_ALG_ECDH, handshake->ecdh_psa_privkey, + handshake->ecdh_psa_peerkey, handshake->ecdh_psa_peerkey_len, + shared_secret, shared_secret_len, &shared_secret_len); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_raw_key_agreement", ret); + goto cleanup; + } + + status = psa_destroy_key(handshake->ecdh_psa_privkey); + if (status != PSA_SUCCESS) { + ret = PSA_TO_MBEDTLS_ERR(status); + MBEDTLS_SSL_DEBUG_RET(1, "psa_destroy_key", ret); + goto cleanup; + } + + handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; +#endif /* MBEDTLS_ECDH_C */ + } else { + MBEDTLS_SSL_DEBUG_MSG(1, ("Group not supported.")); + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + } + } +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */ + + /* + * Compute the Handshake Secret + */ + ret = mbedtls_ssl_tls13_evolve_secret(hash_alg, + handshake->tls13_master_secrets.early, + shared_secret, shared_secret_len, + handshake->tls13_master_secrets.handshake); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_evolve_secret", ret); + goto cleanup; + } + + MBEDTLS_SSL_DEBUG_BUF(4, "Handshake secret", + handshake->tls13_master_secrets.handshake, + PSA_HASH_LENGTH(hash_alg)); + +cleanup: + if (shared_secret != NULL) { + mbedtls_platform_zeroize(shared_secret, shared_secret_len); + mbedtls_free(shared_secret); + } + + return ret; +} + +/** + * \brief Compute TLS 1.3 application traffic keys. + * + * ssl_tls13_generate_application_keys() generates application traffic + * keys, since any record following a 1-RTT Finished message MUST be + * encrypted under the application traffic key. + * + * \param ssl The SSL context to operate on. This must be in + * key schedule stage \c Application, see + * ssl_tls13_key_schedule_stage_application(). + * \param traffic_keys The address at which to store the application traffic + * keys. This must be writable but may be uninitialized. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_generate_application_keys( + mbedtls_ssl_context *ssl, + mbedtls_ssl_key_set *traffic_keys) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + /* Address at which to store the application secrets */ + mbedtls_ssl_tls13_application_secrets * const app_secrets = + &ssl->session_negotiate->app_secrets; + + /* Holding the transcript up to and including the ServerFinished */ + unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + size_t transcript_len; + + /* Variables relating to the hash for the chosen ciphersuite. */ + mbedtls_md_type_t md_type; + + psa_algorithm_t hash_alg; + size_t hash_len; + + /* Variables relating to the cipher for the chosen ciphersuite. */ + size_t key_len, iv_len; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> derive application traffic keys")); + + /* Extract basic information about hash and ciphersuite */ + + ret = ssl_tls13_get_cipher_key_info(handshake->ciphersuite_info, + &key_len, &iv_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_get_cipher_key_info", ret); + goto cleanup; + } + + md_type = handshake->ciphersuite_info->mac; + + hash_alg = mbedtls_hash_info_psa_from_md(handshake->ciphersuite_info->mac); + hash_len = PSA_HASH_LENGTH(hash_alg); + + /* Compute current handshake transcript. It's the caller's responsibility + * to call this at the right time, that is, after the ServerFinished. */ + + ret = mbedtls_ssl_get_handshake_transcript(ssl, md_type, + transcript, sizeof(transcript), + &transcript_len); + if (ret != 0) { + goto cleanup; + } + + /* Compute application secrets from master secret and transcript hash. */ + + ret = mbedtls_ssl_tls13_derive_application_secrets(hash_alg, + handshake->tls13_master_secrets.app, + transcript, transcript_len, + app_secrets); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, + "mbedtls_ssl_tls13_derive_application_secrets", ret); + goto cleanup; + } + + /* Derive first epoch of IV + Key for application traffic. */ + + ret = mbedtls_ssl_tls13_make_traffic_keys(hash_alg, + app_secrets->client_application_traffic_secret_N, + app_secrets->server_application_traffic_secret_N, + hash_len, key_len, iv_len, traffic_keys); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_make_traffic_keys", ret); + goto cleanup; + } + + MBEDTLS_SSL_DEBUG_BUF(4, "Client application traffic secret", + app_secrets->client_application_traffic_secret_N, + hash_len); + + MBEDTLS_SSL_DEBUG_BUF(4, "Server application traffic secret", + app_secrets->server_application_traffic_secret_N, + hash_len); + + /* + * Export client/server application traffic secret 0 + */ + if (ssl->f_export_keys != NULL) { + ssl->f_export_keys(ssl->p_export_keys, + MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_APPLICATION_TRAFFIC_SECRET, + app_secrets->client_application_traffic_secret_N, hash_len, + handshake->randbytes, + handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN, + MBEDTLS_SSL_TLS_PRF_NONE /* TODO: this should be replaced by + a new constant for TLS 1.3! */); + + ssl->f_export_keys(ssl->p_export_keys, + MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_APPLICATION_TRAFFIC_SECRET, + app_secrets->server_application_traffic_secret_N, hash_len, + handshake->randbytes, + handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN, + MBEDTLS_SSL_TLS_PRF_NONE /* TODO: this should be replaced by + a new constant for TLS 1.3! */); + } + + MBEDTLS_SSL_DEBUG_BUF(4, "client application_write_key:", + traffic_keys->client_write_key, key_len); + MBEDTLS_SSL_DEBUG_BUF(4, "server application write key", + traffic_keys->server_write_key, key_len); + MBEDTLS_SSL_DEBUG_BUF(4, "client application write IV", + traffic_keys->client_write_iv, iv_len); + MBEDTLS_SSL_DEBUG_BUF(4, "server application write IV", + traffic_keys->server_write_iv, iv_len); + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= derive application traffic keys")); + +cleanup: + /* randbytes is not used again */ + mbedtls_platform_zeroize(ssl->handshake->randbytes, + sizeof(ssl->handshake->randbytes)); + + mbedtls_platform_zeroize(transcript, sizeof(transcript)); + return ret; +} + +int mbedtls_ssl_tls13_compute_handshake_transform(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_key_set traffic_keys; + mbedtls_ssl_transform *transform_handshake = NULL; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + /* Compute handshake secret */ + ret = ssl_tls13_key_schedule_stage_handshake(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_derive_master_secret", ret); + goto cleanup; + } + + /* Next evolution in key schedule: Establish handshake secret and + * key material. */ + ret = ssl_tls13_generate_handshake_keys(ssl, &traffic_keys); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_generate_handshake_keys", + ret); + goto cleanup; + } + + transform_handshake = mbedtls_calloc(1, sizeof(mbedtls_ssl_transform)); + if (transform_handshake == NULL) { + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto cleanup; + } + + ret = mbedtls_ssl_tls13_populate_transform( + transform_handshake, + ssl->conf->endpoint, + handshake->ciphersuite_info->id, + &traffic_keys, + ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_populate_transform", ret); + goto cleanup; + } + handshake->transform_handshake = transform_handshake; + +cleanup: + mbedtls_platform_zeroize(&traffic_keys, sizeof(traffic_keys)); + if (ret != 0) { + mbedtls_free(transform_handshake); + } + + return ret; +} + +int mbedtls_ssl_tls13_compute_resumption_master_secret(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_md_type_t md_type; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + size_t transcript_len; + + MBEDTLS_SSL_DEBUG_MSG(2, + ("=> mbedtls_ssl_tls13_compute_resumption_master_secret")); + + md_type = handshake->ciphersuite_info->mac; + + ret = mbedtls_ssl_get_handshake_transcript(ssl, md_type, + transcript, sizeof(transcript), + &transcript_len); + if (ret != 0) { + return ret; + } + + ret = mbedtls_ssl_tls13_derive_resumption_master_secret( + mbedtls_psa_translate_md(md_type), + handshake->tls13_master_secrets.app, + transcript, transcript_len, + &ssl->session_negotiate->app_secrets); + if (ret != 0) { + return ret; + } + + /* Erase master secrets */ + mbedtls_platform_zeroize(&handshake->tls13_master_secrets, + sizeof(handshake->tls13_master_secrets)); + + MBEDTLS_SSL_DEBUG_BUF(4, "Resumption master secret", + ssl->session_negotiate->app_secrets.resumption_master_secret, + PSA_HASH_LENGTH(mbedtls_psa_translate_md(md_type))); + + MBEDTLS_SSL_DEBUG_MSG(2, + ("<= mbedtls_ssl_tls13_compute_resumption_master_secret")); + return 0; +} + +int mbedtls_ssl_tls13_compute_application_transform(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_key_set traffic_keys; + mbedtls_ssl_transform *transform_application = NULL; + + ret = ssl_tls13_key_schedule_stage_application(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, + "ssl_tls13_key_schedule_stage_application", ret); + goto cleanup; + } + + ret = ssl_tls13_generate_application_keys(ssl, &traffic_keys); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, + "ssl_tls13_generate_application_keys", ret); + goto cleanup; + } + + transform_application = + mbedtls_calloc(1, sizeof(mbedtls_ssl_transform)); + if (transform_application == NULL) { + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto cleanup; + } + + ret = mbedtls_ssl_tls13_populate_transform( + transform_application, + ssl->conf->endpoint, + ssl->handshake->ciphersuite_info->id, + &traffic_keys, + ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_populate_transform", ret); + goto cleanup; + } + + ssl->transform_application = transform_application; + +cleanup: + + mbedtls_platform_zeroize(&traffic_keys, sizeof(traffic_keys)); + if (ret != 0) { + mbedtls_free(transform_application); + } + return ret; +} + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) +int mbedtls_ssl_tls13_export_handshake_psk(mbedtls_ssl_context *ssl, + unsigned char **psk, + size_t *psk_len) +{ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + *psk_len = 0; + *psk = NULL; + + if (mbedtls_svc_key_id_is_null(ssl->handshake->psk_opaque)) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + status = psa_get_key_attributes(ssl->handshake->psk_opaque, &key_attributes); + if (status != PSA_SUCCESS) { + return PSA_TO_MBEDTLS_ERR(status); + } + + *psk_len = PSA_BITS_TO_BYTES(psa_get_key_bits(&key_attributes)); + *psk = mbedtls_calloc(1, *psk_len); + if (*psk == NULL) { + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } + + status = psa_export_key(ssl->handshake->psk_opaque, + (uint8_t *) *psk, *psk_len, psk_len); + if (status != PSA_SUCCESS) { + mbedtls_free((void *) *psk); + *psk = NULL; + return PSA_TO_MBEDTLS_ERR(status); + } + return 0; +#else + *psk = ssl->handshake->psk; + *psk_len = ssl->handshake->psk_len; + if (*psk == NULL) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + return 0; +#endif /* !MBEDTLS_USE_PSA_CRYPTO */ +} +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ + +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ 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..21e9b4d --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_keys.h @@ -0,0 +1,663 @@ +/* + * 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_tls13_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") \ + MBEDTLS_SSL_TLS1_3_LABEL(client_cv, "TLS 1.3, client CertificateVerify") \ + MBEDTLS_SSL_TLS1_3_LABEL(server_cv, "TLS 1.3, server CertificateVerify") + +#define MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED 0 +#define MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED 1 + +#define MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL 0 +#define MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION 1 + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + +#define MBEDTLS_SSL_TLS1_3_LABEL(name, string) \ + const unsigned char name [sizeof(string) - 1]; + +union mbedtls_ssl_tls13_labels_union { + MBEDTLS_SSL_TLS1_3_LABEL_LIST +}; +struct mbedtls_ssl_tls13_labels_struct { + MBEDTLS_SSL_TLS1_3_LABEL_LIST +}; +#undef MBEDTLS_SSL_TLS1_3_LABEL + +extern const struct mbedtls_ssl_tls13_labels_struct mbedtls_ssl_tls13_labels; + +#define MBEDTLS_SSL_TLS1_3_LBL_LEN(LABEL) \ + sizeof(mbedtls_ssl_tls13_labels.LABEL) + +#define MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(LABEL) \ + mbedtls_ssl_tls13_labels.LABEL, \ + MBEDTLS_SSL_TLS1_3_LBL_LEN(LABEL) + +#define MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN \ + sizeof(union mbedtls_ssl_tls13_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 \ + PSA_HASH_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_tls13_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 secret_len Bytes. + * \param secret_len 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 label_len Bytes. + * \param label_len 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 ctx_len Bytes. + * \param ctx_len 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 buf_len Bytes. + * \param buf_len The desired size of the expanded secret in Bytes. + * + * \returns \c 0 on success. + * \return A negative error code on failure. + */ + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_hkdf_expand_label( + psa_algorithm_t hash_alg, + const unsigned char *secret, size_t secret_len, + const unsigned char *label, size_t label_len, + const unsigned char *ctx, size_t ctx_len, + unsigned char *buf, size_t buf_len); + +/** + * \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 secret_len Bytes + * \param server_secret The server traffic secret. + * This must be a readable buffer of size + * \p secret_len Bytes + * \param secret_len 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. + */ + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_make_traffic_keys( + psa_algorithm_t hash_alg, + const unsigned char *client_secret, + const unsigned char *server_secret, size_t secret_len, + size_t key_len, size_t iv_len, + mbedtls_ssl_key_set *keys); + +/** + * \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 secret_len Bytes. + * \param secret_len 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 label_len Bytes. + * \param label_len 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 ctx_hashed. + * \param ctx_len The length of \p ctx in Bytes. + * \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 dtsbuf_len Bytes. + * \param dstbuf_len The length of \p dstbuf in Bytes. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_derive_secret( + psa_algorithm_t hash_alg, + const unsigned char *secret, size_t secret_len, + const unsigned char *label, size_t label_len, + const unsigned char *ctx, size_t ctx_len, + int ctx_hashed, + unsigned char *dstbuf, size_t dstbuf_len); + +/** + * \brief Derive TLS 1.3 early data key material from early secret. + * + * This is a small wrapper invoking mbedtls_ssl_tls13_derive_secret() + * with the appropriate labels. + * + * + * Early Secret + * | + * +-----> Derive-Secret(., "c e traffic", ClientHello) + * | = client_early_traffic_secret + * | + * +-----> Derive-Secret(., "e exp master", ClientHello) + * . = early_exporter_master_secret + * . + * . + * + * + * \note To obtain the actual key and IV for the early data traffic, + * the client secret derived by this function need to be + * further processed by mbedtls_ssl_tls13_make_traffic_keys(). + * + * \note The binder key, which is also generated from the early secret, + * is omitted here. Its calculation is part of the separate routine + * mbedtls_ssl_tls13_create_psk_binder(). + * + * \param hash_alg The hash algorithm associated with the PSK for which + * early data key material is being derived. + * \param early_secret The early secret from which the early data key material + * should be derived. This must be a readable buffer whose + * length is the digest size of the hash algorithm + * represented by \p md_size. + * \param transcript The transcript of the handshake so far, calculated with + * respect to \p hash_alg. This must be a readable buffer + * whose length is the digest size of the hash algorithm + * represented by \p md_size. + * \param derived The address of the structure in which to store + * the early data key material. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_derive_early_secrets( + psa_algorithm_t hash_alg, + unsigned char const *early_secret, + unsigned char const *transcript, size_t transcript_len, + mbedtls_ssl_tls13_early_secrets *derived); + +/** + * \brief Derive TLS 1.3 handshake key material from the handshake secret. + * + * This is a small wrapper invoking mbedtls_ssl_tls13_derive_secret() + * with the appropriate labels from the standard. + * + * + * Handshake Secret + * | + * +-----> Derive-Secret( ., "c hs traffic", + * | ClientHello...ServerHello ) + * | = client_handshake_traffic_secret + * | + * +-----> Derive-Secret( ., "s hs traffic", + * . ClientHello...ServerHello ) + * . = server_handshake_traffic_secret + * . + * + * + * \note To obtain the actual key and IV for the encrypted handshake traffic, + * the client and server secret derived by this function need to be + * further processed by mbedtls_ssl_tls13_make_traffic_keys(). + * + * \param hash_alg The hash algorithm associated with the ciphersuite + * that's being used for the connection. + * \param handshake_secret The handshake secret from which the handshake key + * material should be derived. This must be a readable + * buffer whose length is the digest size of the hash + * algorithm represented by \p md_size. + * \param transcript The transcript of the handshake so far, calculated + * with respect to \p hash_alg. This must be a readable + * buffer whose length is the digest size of the hash + * algorithm represented by \p md_size. + * \param derived The address of the structure in which to + * store the handshake key material. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_derive_handshake_secrets( + psa_algorithm_t hash_alg, + unsigned char const *handshake_secret, + unsigned char const *transcript, size_t transcript_len, + mbedtls_ssl_tls13_handshake_secrets *derived); + +/** + * \brief Derive TLS 1.3 application key material from the master secret. + * + * This is a small wrapper invoking mbedtls_ssl_tls13_derive_secret() + * with the appropriate labels from the standard. + * + * + * Master Secret + * | + * +-----> Derive-Secret( ., "c ap traffic", + * | ClientHello...server Finished ) + * | = client_application_traffic_secret_0 + * | + * +-----> Derive-Secret( ., "s ap traffic", + * | ClientHello...Server Finished ) + * | = server_application_traffic_secret_0 + * | + * +-----> Derive-Secret( ., "exp master", + * . ClientHello...server Finished) + * . = exporter_master_secret + * . + * + * + * \note To obtain the actual key and IV for the (0-th) application traffic, + * the client and server secret derived by this function need to be + * further processed by mbedtls_ssl_tls13_make_traffic_keys(). + * + * \param hash_alg The hash algorithm associated with the ciphersuite + * that's being used for the connection. + * \param master_secret The master secret from which the application key + * material should be derived. This must be a readable + * buffer whose length is the digest size of the hash + * algorithm represented by \p md_size. + * \param transcript The transcript of the handshake up to and including + * the ServerFinished message, calculated with respect + * to \p hash_alg. This must be a readable buffer whose + * length is the digest size of the hash algorithm + * represented by \p hash_alg. + * \param derived The address of the structure in which to + * store the application key material. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_derive_application_secrets( + psa_algorithm_t hash_alg, + unsigned char const *master_secret, + unsigned char const *transcript, size_t transcript_len, + mbedtls_ssl_tls13_application_secrets *derived); + +/** + * \brief Derive TLS 1.3 resumption master secret from the master secret. + * + * This is a small wrapper invoking mbedtls_ssl_tls13_derive_secret() + * with the appropriate labels from the standard. + * + * \param hash_alg The hash algorithm used in the application for which + * key material is being derived. + * \param application_secret The application secret from which the resumption master + * secret should be derived. This must be a readable + * buffer whose length is the digest size of the hash + * algorithm represented by \p md_size. + * \param transcript The transcript of the handshake up to and including + * the ClientFinished message, calculated with respect + * to \p hash_alg. This must be a readable buffer whose + * length is the digest size of the hash algorithm + * represented by \p hash_alg. + * \param transcript_len The length of \p transcript in Bytes. + * \param derived The address of the structure in which to + * store the resumption master secret. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_derive_resumption_master_secret( + psa_algorithm_t hash_alg, + unsigned char const *application_secret, + unsigned char const *transcript, size_t transcript_len, + mbedtls_ssl_tls13_application_secrets *derived); + +/** + * \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_tls13_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. + */ + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_evolve_secret( + psa_algorithm_t hash_alg, + const unsigned char *secret_old, + const unsigned char *input, size_t input_len, + unsigned char *secret_new); + +/** + * \brief Calculate a TLS 1.3 PSK binder. + * + * \param ssl The SSL context. This is used for debugging only and may + * be \c NULL if MBEDTLS_DEBUG_C is disabled. + * \param hash_alg The hash algorithm associated to the PSK \p psk. + * \param psk The buffer holding the PSK for which to create a binder. + * \param psk_len The size of \p psk in bytes. + * \param psk_type This indicates whether the PSK \p psk is externally + * provisioned (#MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL) or a + * resumption PSK (#MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION). + * \param transcript The handshake transcript up to the point where the + * PSK binder calculation happens. This must be readable, + * and its size must be equal to the digest size of + * the hash algorithm represented by \p hash_alg. + * \param result The address at which to store the PSK binder on success. + * This must be writable, and its size must be equal to the + * digest size of the hash algorithm represented by + * \p hash_alg. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_create_psk_binder(mbedtls_ssl_context *ssl, + const psa_algorithm_t hash_alg, + unsigned char const *psk, size_t psk_len, + int psk_type, + unsigned char const *transcript, + unsigned char *result); + +/** + * \bref Setup an SSL transform structure representing the + * record protection mechanism used by TLS 1.3 + * + * \param transform The SSL transform structure to be created. This must have + * been initialized through mbedtls_ssl_transform_init() and + * not used in any other way prior to calling this function. + * In particular, this function does not clean up the + * transform structure prior to installing the new keys. + * \param endpoint Indicates whether the transform is for the client + * (value #MBEDTLS_SSL_IS_CLIENT) or the server + * (value #MBEDTLS_SSL_IS_SERVER). + * \param ciphersuite The numerical identifier for the ciphersuite to use. + * This must be one of the identifiers listed in + * ssl_ciphersuites.h. + * \param traffic_keys The key material to use. No reference is stored in + * the SSL transform being generated, and the caller + * should destroy the key material afterwards. + * \param ssl (Debug-only) The SSL context to use for debug output + * in case of failure. This parameter is only needed if + * #MBEDTLS_DEBUG_C is set, and is ignored otherwise. + * + * \return \c 0 on success. In this case, \p transform is ready to + * be used with mbedtls_ssl_transform_decrypt() and + * mbedtls_ssl_transform_encrypt(). + * \return A negative error code on failure. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_populate_transform(mbedtls_ssl_transform *transform, + int endpoint, + int ciphersuite, + mbedtls_ssl_key_set const *traffic_keys, + mbedtls_ssl_context *ssl); + +/* + * TLS 1.3 key schedule evolutions + * + * Early -> Handshake -> Application + * + * Small wrappers around mbedtls_ssl_tls13_evolve_secret(). + */ + +/** + * \brief Begin TLS 1.3 key schedule by calculating early secret. + * + * The TLS 1.3 key schedule can be viewed as a simple state machine + * with states Initial -> Early -> Handshake -> Application, and + * this function represents the Initial -> Early transition. + * + * \param ssl The SSL context to operate on. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_key_schedule_stage_early(mbedtls_ssl_context *ssl); + +/** + * \brief Compute TLS 1.3 resumption master secret. + * + * \param ssl The SSL context to operate on. This must be in + * key schedule stage \c Application, see + * mbedtls_ssl_tls13_key_schedule_stage_application(). + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_compute_resumption_master_secret(mbedtls_ssl_context *ssl); + +/** + * \brief Calculate the verify_data value for the client or server TLS 1.3 + * Finished message. + * + * \param ssl The SSL context to operate on. This must be in + * key schedule stage \c Handshake, see + * mbedtls_ssl_tls13_key_schedule_stage_application(). + * \param dst The address at which to write the verify_data value. + * \param dst_len The size of \p dst in bytes. + * \param actual_len The address at which to store the amount of data + * actually written to \p dst upon success. + * \param which The message to calculate the `verify_data` for: + * - #MBEDTLS_SSL_IS_CLIENT for the Client's Finished message + * - #MBEDTLS_SSL_IS_SERVER for the Server's Finished message + * + * \note Both client and server call this function twice, once to + * generate their own Finished message, and once to verify the + * peer's Finished message. + + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_calculate_verify_data(mbedtls_ssl_context *ssl, + unsigned char *dst, + size_t dst_len, + size_t *actual_len, + int which); + +#if defined(MBEDTLS_SSL_EARLY_DATA) +/** + * \brief Compute TLS 1.3 early transform + * + * \param ssl The SSL context to operate on. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + * + * \warning The function does not compute the early master secret. Call + * mbedtls_ssl_tls13_key_schedule_stage_early() before to + * call this function to generate the early master secret. + * \note For a client/server endpoint, the function computes only the + * encryption/decryption part of the transform as the decryption/ + * encryption part is not defined by the specification (no early + * traffic from the server to the client). + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_compute_early_transform(mbedtls_ssl_context *ssl); +#endif /* MBEDTLS_SSL_EARLY_DATA */ + +/** + * \brief Compute TLS 1.3 handshake transform + * + * \param ssl The SSL context to operate on. The early secret must have been + * computed. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_compute_handshake_transform(mbedtls_ssl_context *ssl); + +/** + * \brief Compute TLS 1.3 application transform + * + * \param ssl The SSL context to operate on. The early secret must have been + * computed. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_compute_application_transform(mbedtls_ssl_context *ssl); + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) +/** + * \brief Export TLS 1.3 PSK from handshake context + * + * \param[in] ssl The SSL context to operate on. + * \param[out] psk PSK output pointer. + * \param[out] psk_len Length of PSK. + * + * \returns \c 0 if there is a configured PSK and it was exported + * successfully. + * \returns A negative error code on failure. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_tls13_export_handshake_psk(mbedtls_ssl_context *ssl, + unsigned char **psk, + size_t *psk_len); +#endif + +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + +#endif /* MBEDTLS_SSL_TLS1_3_KEYS_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_server.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_server.c new file mode 100644 index 0000000..b5a0c9e --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_server.c @@ -0,0 +1,3084 @@ +/* + * TLS 1.3 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) && defined(MBEDTLS_SSL_PROTO_TLS1_3) + +#include "mbedtls/debug.h" +#include "mbedtls/error.h" +#include "mbedtls/platform.h" +#include "mbedtls/constant_time.h" + +#include "ssl_misc.h" +#include "ssl_tls13_keys.h" +#include "ssl_debug_helpers.h" + + +static const mbedtls_ssl_ciphersuite_t *ssl_tls13_validate_peer_ciphersuite( + mbedtls_ssl_context *ssl, + unsigned int cipher_suite) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + if (!mbedtls_ssl_tls13_cipher_suite_is_offered(ssl, cipher_suite)) { + return NULL; + } + + ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(cipher_suite); + if ((mbedtls_ssl_validate_ciphersuite(ssl, ciphersuite_info, + ssl->tls_version, + ssl->tls_version) != 0)) { + return NULL; + } + return ciphersuite_info; +} + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) +/* From RFC 8446: + * + * enum { psk_ke(0), psk_dhe_ke(1), (255) } PskKeyExchangeMode; + * struct { + * PskKeyExchangeMode ke_modes<1..255>; + * } PskKeyExchangeModes; + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_key_exchange_modes_ext(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + const unsigned char *p = buf; + size_t ke_modes_len; + int ke_modes = 0; + + /* Read ke_modes length (1 Byte) */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 1); + ke_modes_len = *p++; + /* Currently, there are only two PSK modes, so even without looking + * at the content, something's wrong if the list has more than 2 items. */ + if (ke_modes_len > 2) { + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, ke_modes_len); + + while (ke_modes_len-- != 0) { + switch (*p++) { + case MBEDTLS_SSL_TLS1_3_PSK_MODE_PURE: + ke_modes |= MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK; + MBEDTLS_SSL_DEBUG_MSG(3, ("Found PSK KEX MODE")); + break; + case MBEDTLS_SSL_TLS1_3_PSK_MODE_ECDHE: + ke_modes |= MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL; + MBEDTLS_SSL_DEBUG_MSG(3, ("Found PSK_EPHEMERAL KEX MODE")); + break; + default: + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + } + + ssl->handshake->tls13_kex_modes = ke_modes; + return 0; +} + +#define SSL_TLS1_3_OFFERED_PSK_NOT_MATCH 1 +#define SSL_TLS1_3_OFFERED_PSK_MATCH 0 + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_offered_psks_check_identity_match_ticket( + mbedtls_ssl_context *ssl, + const unsigned char *identity, + size_t identity_len, + uint32_t obfuscated_ticket_age, + mbedtls_ssl_session *session) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *ticket_buffer; +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t now; + uint64_t age_in_s; + int64_t age_diff_in_ms; +#endif + + ((void) obfuscated_ticket_age); + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> check_identity_match_ticket")); + + /* Ticket parser is not configured, Skip */ + if (ssl->conf->f_ticket_parse == NULL || identity_len == 0) { + return 0; + } + + /* We create a copy of the encrypted ticket since the ticket parsing + * function is allowed to use its input buffer as an output buffer + * (in-place decryption). We do, however, need the original buffer for + * computing the PSK binder value. + */ + ticket_buffer = mbedtls_calloc(1, identity_len); + if (ticket_buffer == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("buffer too small")); + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } + memcpy(ticket_buffer, identity, identity_len); + + if ((ret = ssl->conf->f_ticket_parse(ssl->conf->p_ticket, + session, + ticket_buffer, identity_len)) != 0) { + 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, "ticket_parse", ret); + } + } + + /* We delete the temporary buffer */ + mbedtls_free(ticket_buffer); + + if (ret != 0) { + goto exit; + } + + /* RFC 8446 section 4.2.9 + * + * Servers SHOULD NOT send NewSessionTicket with tickets that are not + * compatible with the advertised modes; however, if a server does so, + * the impact will just be that the client's attempts at resumption fail. + * + * We regard the ticket with incompatible key exchange modes as not match. + */ + ret = MBEDTLS_ERR_ERROR_GENERIC_ERROR; + MBEDTLS_SSL_PRINT_TICKET_FLAGS(4, + session->ticket_flags); + if (mbedtls_ssl_tls13_check_kex_modes( + ssl, + mbedtls_ssl_session_get_ticket_flags( + session, + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL))) { + MBEDTLS_SSL_DEBUG_MSG(3, ("No suitable key exchange mode")); + goto exit; + } + + ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED; +#if defined(MBEDTLS_HAVE_TIME) + now = mbedtls_time(NULL); + + if (now < session->start) { + MBEDTLS_SSL_DEBUG_MSG( + 3, ("Invalid ticket start time ( now=%" MBEDTLS_PRINTF_LONGLONG + ", start=%" MBEDTLS_PRINTF_LONGLONG " )", + (long long) now, (long long) session->start)); + goto exit; + } + + age_in_s = (uint64_t) (now - session->start); + + /* RFC 8446 section 4.6.1 + * + * Servers MUST NOT use any value greater than 604800 seconds (7 days). + * + * RFC 8446 section 4.2.11.1 + * + * Clients MUST NOT attempt to use tickets which have ages greater than + * the "ticket_lifetime" value which was provided with the ticket. + * + * For time being, the age MUST be less than 604800 seconds (7 days). + */ + if (age_in_s > 604800) { + MBEDTLS_SSL_DEBUG_MSG( + 3, ("Ticket age exceeds limitation ticket_age=%lu", + (long unsigned int) age_in_s)); + goto exit; + } + + /* RFC 8446 section 4.2.10 + * + * For PSKs provisioned via NewSessionTicket, a server MUST validate that + * the ticket age for the selected PSK identity (computed by subtracting + * ticket_age_add from PskIdentity.obfuscated_ticket_age modulo 2^32) is + * within a small tolerance of the time since the ticket was issued. + * + * NOTE: When `now == session->start`, `age_diff_in_ms` may be negative + * as the age units are different on the server (s) and in the + * client (ms) side. Add a -1000 ms tolerance window to take this + * into account. + */ + age_diff_in_ms = age_in_s * 1000; + age_diff_in_ms -= (obfuscated_ticket_age - session->ticket_age_add); + if (age_diff_in_ms <= -1000 || + age_diff_in_ms > MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE) { + MBEDTLS_SSL_DEBUG_MSG( + 3, ("Ticket age outside tolerance window ( diff=%d )", + (int) age_diff_in_ms)); + goto exit; + } + + ret = 0; + +#endif /* MBEDTLS_HAVE_TIME */ + +exit: + if (ret != 0) { + mbedtls_ssl_session_free(session); + } + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= check_identity_match_ticket")); + return ret; +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_offered_psks_check_identity_match( + mbedtls_ssl_context *ssl, + const unsigned char *identity, + size_t identity_len, + uint32_t obfuscated_ticket_age, + int *psk_type, + mbedtls_ssl_session *session) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ((void) session); + ((void) obfuscated_ticket_age); + *psk_type = MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL; + + MBEDTLS_SSL_DEBUG_BUF(4, "identity", identity, identity_len); + ssl->handshake->resume = 0; + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if (ssl_tls13_offered_psks_check_identity_match_ticket( + ssl, identity, identity_len, obfuscated_ticket_age, + session) == SSL_TLS1_3_OFFERED_PSK_MATCH) { + ssl->handshake->resume = 1; + *psk_type = MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION; + ret = mbedtls_ssl_set_hs_psk(ssl, + session->resumption_key, + session->resumption_key_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_set_hs_psk", ret); + return ret; + } + + MBEDTLS_SSL_DEBUG_BUF(4, "Ticket-resumed PSK:", + session->resumption_key, + session->resumption_key_len); + MBEDTLS_SSL_DEBUG_MSG(4, ("ticket: obfuscated_ticket_age: %u", + (unsigned) obfuscated_ticket_age)); + return SSL_TLS1_3_OFFERED_PSK_MATCH; + } +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + + /* Check identity with external configured function */ + if (ssl->conf->f_psk != NULL) { + if (ssl->conf->f_psk( + ssl->conf->p_psk, ssl, identity, identity_len) == 0) { + return SSL_TLS1_3_OFFERED_PSK_MATCH; + } + return SSL_TLS1_3_OFFERED_PSK_NOT_MATCH; + } + + MBEDTLS_SSL_DEBUG_BUF(5, "identity", identity, identity_len); + /* Check identity with pre-configured psk */ + if (ssl->conf->psk_identity != NULL && + identity_len == ssl->conf->psk_identity_len && + mbedtls_ct_memcmp(ssl->conf->psk_identity, + identity, identity_len) == 0) { + ret = mbedtls_ssl_set_hs_psk(ssl, ssl->conf->psk, ssl->conf->psk_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_set_hs_psk", ret); + return ret; + } + return SSL_TLS1_3_OFFERED_PSK_MATCH; + } + + return SSL_TLS1_3_OFFERED_PSK_NOT_MATCH; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_offered_psks_check_binder_match(mbedtls_ssl_context *ssl, + const unsigned char *binder, + size_t binder_len, + int psk_type, + psa_algorithm_t psk_hash_alg) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + unsigned char transcript[PSA_HASH_MAX_SIZE]; + size_t transcript_len; + unsigned char *psk; + size_t psk_len; + unsigned char server_computed_binder[PSA_HASH_MAX_SIZE]; + + /* Get current state of handshake transcript. */ + ret = mbedtls_ssl_get_handshake_transcript( + ssl, mbedtls_hash_info_md_from_psa(psk_hash_alg), + transcript, sizeof(transcript), &transcript_len); + if (ret != 0) { + return ret; + } + + ret = mbedtls_ssl_tls13_export_handshake_psk(ssl, &psk, &psk_len); + if (ret != 0) { + return ret; + } + + ret = mbedtls_ssl_tls13_create_psk_binder(ssl, psk_hash_alg, + psk, psk_len, psk_type, + transcript, + server_computed_binder); +#if defined(MBEDTLS_USE_PSA_CRYPTO) + mbedtls_free((void *) psk); +#endif + if (ret != 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("PSK binder calculation failed.")); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + + MBEDTLS_SSL_DEBUG_BUF(3, "psk binder ( computed ): ", + server_computed_binder, transcript_len); + MBEDTLS_SSL_DEBUG_BUF(3, "psk binder ( received ): ", binder, binder_len); + + if (mbedtls_ct_memcmp(server_computed_binder, binder, binder_len) == 0) { + return SSL_TLS1_3_OFFERED_PSK_MATCH; + } + + mbedtls_platform_zeroize(server_computed_binder, + sizeof(server_computed_binder)); + return SSL_TLS1_3_OFFERED_PSK_NOT_MATCH; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_select_ciphersuite_for_psk( + mbedtls_ssl_context *ssl, + const unsigned char *cipher_suites, + const unsigned char *cipher_suites_end, + uint16_t *selected_ciphersuite, + const mbedtls_ssl_ciphersuite_t **selected_ciphersuite_info) +{ + psa_algorithm_t psk_hash_alg = PSA_ALG_SHA_256; + + *selected_ciphersuite = 0; + *selected_ciphersuite_info = NULL; + + /* RFC 8446, page 55. + * + * For externally established PSKs, the Hash algorithm MUST be set when the + * PSK is established or default to SHA-256 if no such algorithm is defined. + * + */ + + /* + * Search for a matching ciphersuite + */ + for (const unsigned char *p = cipher_suites; + p < cipher_suites_end; p += 2) { + uint16_t cipher_suite; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + + cipher_suite = MBEDTLS_GET_UINT16_BE(p, 0); + ciphersuite_info = ssl_tls13_validate_peer_ciphersuite(ssl, + cipher_suite); + if (ciphersuite_info == NULL) { + continue; + } + + /* MAC of selected ciphersuite MUST be same with PSK binder if exist. + * Otherwise, client should reject. + */ + if (psk_hash_alg == mbedtls_psa_translate_md(ciphersuite_info->mac)) { + *selected_ciphersuite = cipher_suite; + *selected_ciphersuite_info = ciphersuite_info; + return 0; + } + } + MBEDTLS_SSL_DEBUG_MSG(2, ("No matched ciphersuite")); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; +} + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_select_ciphersuite_for_resumption( + mbedtls_ssl_context *ssl, + const unsigned char *cipher_suites, + const unsigned char *cipher_suites_end, + mbedtls_ssl_session *session, + uint16_t *selected_ciphersuite, + const mbedtls_ssl_ciphersuite_t **selected_ciphersuite_info) +{ + + *selected_ciphersuite = 0; + *selected_ciphersuite_info = NULL; + for (const unsigned char *p = cipher_suites; p < cipher_suites_end; p += 2) { + uint16_t cipher_suite = MBEDTLS_GET_UINT16_BE(p, 0); + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + + if (cipher_suite != session->ciphersuite) { + continue; + } + + ciphersuite_info = ssl_tls13_validate_peer_ciphersuite(ssl, + cipher_suite); + if (ciphersuite_info == NULL) { + continue; + } + + *selected_ciphersuite = cipher_suite; + *selected_ciphersuite_info = ciphersuite_info; + + return 0; + } + + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_session_copy_ticket(mbedtls_ssl_session *dst, + const mbedtls_ssl_session *src) +{ + dst->ticket_age_add = src->ticket_age_add; + dst->ticket_flags = src->ticket_flags; + dst->resumption_key_len = src->resumption_key_len; + if (src->resumption_key_len == 0) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + memcpy(dst->resumption_key, src->resumption_key, src->resumption_key_len); + + return 0; +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +/* Parser for pre_shared_key extension in client hello + * struct { + * opaque identity<1..2^16-1>; + * uint32 obfuscated_ticket_age; + * } PskIdentity; + * + * opaque PskBinderEntry<32..255>; + * + * struct { + * PskIdentity identities<7..2^16-1>; + * PskBinderEntry binders<33..2^16-1>; + * } OfferedPsks; + * + * struct { + * select (Handshake.msg_type) { + * case client_hello: OfferedPsks; + * .... + * }; + * } PreSharedKeyExtension; + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_pre_shared_key_ext(mbedtls_ssl_context *ssl, + const unsigned char *pre_shared_key_ext, + const unsigned char *pre_shared_key_ext_end, + const unsigned char *ciphersuites, + const unsigned char *ciphersuites_end) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const unsigned char *identities = pre_shared_key_ext; + const unsigned char *p_identity_len; + size_t identities_len; + const unsigned char *identities_end; + const unsigned char *binders; + const unsigned char *p_binder_len; + size_t binders_len; + const unsigned char *binders_end; + int matched_identity = -1; + int identity_id = -1; + + MBEDTLS_SSL_DEBUG_BUF(3, "pre_shared_key extension", + pre_shared_key_ext, + pre_shared_key_ext_end - pre_shared_key_ext); + + /* identities_len 2 bytes + * identities_data >= 7 bytes + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(identities, pre_shared_key_ext_end, 7 + 2); + identities_len = MBEDTLS_GET_UINT16_BE(identities, 0); + p_identity_len = identities + 2; + MBEDTLS_SSL_CHK_BUF_READ_PTR(p_identity_len, pre_shared_key_ext_end, + identities_len); + identities_end = p_identity_len + identities_len; + + /* binders_len 2 bytes + * binders >= 33 bytes + */ + binders = identities_end; + MBEDTLS_SSL_CHK_BUF_READ_PTR(binders, pre_shared_key_ext_end, 33 + 2); + binders_len = MBEDTLS_GET_UINT16_BE(binders, 0); + p_binder_len = binders + 2; + MBEDTLS_SSL_CHK_BUF_READ_PTR(p_binder_len, pre_shared_key_ext_end, binders_len); + binders_end = p_binder_len + binders_len; + + ret = ssl->handshake->update_checksum(ssl, pre_shared_key_ext, + identities_end - pre_shared_key_ext); + if (0 != ret) { + MBEDTLS_SSL_DEBUG_RET(1, ("update_checksum"), ret); + return ret; + } + + while (p_identity_len < identities_end && p_binder_len < binders_end) { + const unsigned char *identity; + size_t identity_len; + uint32_t obfuscated_ticket_age; + const unsigned char *binder; + size_t binder_len; + int psk_type; + uint16_t cipher_suite; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + mbedtls_ssl_session session; + mbedtls_ssl_session_init(&session); +#endif + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p_identity_len, identities_end, 2 + 1 + 4); + identity_len = MBEDTLS_GET_UINT16_BE(p_identity_len, 0); + identity = p_identity_len + 2; + MBEDTLS_SSL_CHK_BUF_READ_PTR(identity, identities_end, identity_len + 4); + obfuscated_ticket_age = MBEDTLS_GET_UINT32_BE(identity, identity_len); + p_identity_len += identity_len + 6; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p_binder_len, binders_end, 1 + 32); + binder_len = *p_binder_len; + binder = p_binder_len + 1; + MBEDTLS_SSL_CHK_BUF_READ_PTR(binder, binders_end, binder_len); + p_binder_len += binder_len + 1; + + identity_id++; + if (matched_identity != -1) { + continue; + } + + ret = ssl_tls13_offered_psks_check_identity_match( + ssl, identity, identity_len, obfuscated_ticket_age, + &psk_type, &session); + if (ret != SSL_TLS1_3_OFFERED_PSK_MATCH) { + continue; + } + + MBEDTLS_SSL_DEBUG_MSG(4, ("found matched identity")); + switch (psk_type) { + case MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL: + ret = ssl_tls13_select_ciphersuite_for_psk( + ssl, ciphersuites, ciphersuites_end, + &cipher_suite, &ciphersuite_info); + break; + case MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION: +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + ret = ssl_tls13_select_ciphersuite_for_resumption( + ssl, ciphersuites, ciphersuites_end, &session, + &cipher_suite, &ciphersuite_info); + if (ret != 0) { + mbedtls_ssl_session_free(&session); + } +#else + ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; +#endif + break; + default: + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + if (ret != 0) { + /* See below, no cipher_suite available, abort handshake */ + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR, + MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); + MBEDTLS_SSL_DEBUG_RET( + 2, "ssl_tls13_select_ciphersuite", ret); + return ret; + } + + ret = ssl_tls13_offered_psks_check_binder_match( + ssl, binder, binder_len, psk_type, + mbedtls_psa_translate_md(ciphersuite_info->mac)); + if (ret != SSL_TLS1_3_OFFERED_PSK_MATCH) { + /* For security reasons, the handshake should be aborted when we + * fail to validate a binder value. See RFC 8446 section 4.2.11.2 + * and appendix E.6. */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + mbedtls_ssl_session_free(&session); +#endif + MBEDTLS_SSL_DEBUG_MSG(3, ("Invalid binder.")); + MBEDTLS_SSL_DEBUG_RET(1, + "ssl_tls13_offered_psks_check_binder_match", ret); + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR, + MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); + return ret; + } + + matched_identity = identity_id; + + /* Update handshake parameters */ + ssl->handshake->ciphersuite_info = ciphersuite_info; + ssl->session_negotiate->ciphersuite = cipher_suite; + MBEDTLS_SSL_DEBUG_MSG(2, ("overwrite ciphersuite: %04x - %s", + cipher_suite, ciphersuite_info->name)); +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if (psk_type == MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION) { + ret = ssl_tls13_session_copy_ticket(ssl->session_negotiate, + &session); + mbedtls_ssl_session_free(&session); + if (ret != 0) { + return ret; + } + } +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + } + + if (p_identity_len != identities_end || p_binder_len != binders_end) { + MBEDTLS_SSL_DEBUG_MSG(3, ("pre_shared_key extension decode error")); + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, + MBEDTLS_ERR_SSL_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + /* Update the handshake transcript with the binder list. */ + ret = ssl->handshake->update_checksum(ssl, + identities_end, + (size_t) (binders_end - identities_end)); + if (0 != ret) { + MBEDTLS_SSL_DEBUG_RET(1, ("update_checksum"), ret); + return ret; + } + if (matched_identity == -1) { + MBEDTLS_SSL_DEBUG_MSG(3, ("No matched PSK or ticket.")); + return MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY; + } + + ssl->handshake->selected_identity = (uint16_t) matched_identity; + MBEDTLS_SSL_DEBUG_MSG(3, ("Pre shared key found")); + + return 0; +} + +/* + * struct { + * select ( Handshake.msg_type ) { + * .... + * case server_hello: + * uint16 selected_identity; + * } + * } PreSharedKeyExtension; + */ +static int ssl_tls13_write_server_pre_shared_key_ext(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *olen) +{ + unsigned char *p = (unsigned char *) buf; + + *olen = 0; + + int not_using_psk = 0; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + not_using_psk = (mbedtls_svc_key_id_is_null(ssl->handshake->psk_opaque)); +#else + not_using_psk = (ssl->handshake->psk == NULL); +#endif + if (not_using_psk) { + /* We shouldn't have called this extension writer unless we've + * chosen to use a PSK. */ + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, adding pre_shared_key extension")); + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6); + + MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_PRE_SHARED_KEY, p, 0); + MBEDTLS_PUT_UINT16_BE(2, p, 2); + + MBEDTLS_PUT_UINT16_BE(ssl->handshake->selected_identity, p, 4); + + *olen = 6; + + MBEDTLS_SSL_DEBUG_MSG(4, ("sent selected_identity: %u", + ssl->handshake->selected_identity)); + + mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_PRE_SHARED_KEY); + + return 0; +} + +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ + +/* From RFC 8446: + * struct { + * ProtocolVersion versions<2..254>; + * } SupportedVersions; + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_supported_versions_ext(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + const unsigned char *p = buf; + size_t versions_len; + const unsigned char *versions_end; + uint16_t tls_version; + int tls13_supported = 0; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 1); + versions_len = p[0]; + p += 1; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, versions_len); + versions_end = p + versions_len; + while (p < versions_end) { + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, versions_end, 2); + tls_version = mbedtls_ssl_read_version(p, ssl->conf->transport); + p += 2; + + /* In this implementation we only support TLS 1.3 and DTLS 1.3. */ + if (tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { + tls13_supported = 1; + break; + } + } + + if (!tls13_supported) { + MBEDTLS_SSL_DEBUG_MSG(1, ("TLS 1.3 is not supported by the client")); + + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION, + MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION); + return MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION; + } + + MBEDTLS_SSL_DEBUG_MSG(1, ("Negotiated version. Supported is [%04x]", + (unsigned int) tls_version)); + + return 0; +} + +#if defined(MBEDTLS_ECDH_C) +/* + * + * From RFC 8446: + * enum { + * ... (0xFFFF) + * } NamedGroup; + * struct { + * NamedGroup named_group_list<2..2^16-1>; + * } NamedGroupList; + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_supported_groups_ext(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + const unsigned char *p = buf; + size_t named_group_list_len; + const unsigned char *named_group_list_end; + + MBEDTLS_SSL_DEBUG_BUF(3, "supported_groups extension", p, end - buf); + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + named_group_list_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, named_group_list_len); + named_group_list_end = p + named_group_list_len; + ssl->handshake->hrr_selected_group = 0; + + while (p < named_group_list_end) { + uint16_t named_group; + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, named_group_list_end, 2); + named_group = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + + MBEDTLS_SSL_DEBUG_MSG(2, + ("got named group: %s(%04x)", + mbedtls_ssl_named_group_to_str(named_group), + named_group)); + + if (!mbedtls_ssl_named_group_is_offered(ssl, named_group) || + !mbedtls_ssl_named_group_is_supported(named_group) || + ssl->handshake->hrr_selected_group != 0) { + continue; + } + + MBEDTLS_SSL_DEBUG_MSG(2, + ("add named group %s(%04x) into received list.", + mbedtls_ssl_named_group_to_str(named_group), + named_group)); + + ssl->handshake->hrr_selected_group = named_group; + } + + return 0; + +} +#endif /* MBEDTLS_ECDH_C */ + +#define SSL_TLS1_3_PARSE_KEY_SHARES_EXT_NO_MATCH 1 + +#if defined(MBEDTLS_ECDH_C) +/* + * ssl_tls13_parse_key_shares_ext() verifies whether the information in the + * extension is correct and stores the first acceptable key share and its associated group. + * + * Possible return values are: + * - 0: Successful processing of the client provided key share extension. + * - SSL_TLS1_3_PARSE_KEY_SHARES_EXT_NO_MATCH: The key shares provided by the client + * does not match a group supported by the server. A HelloRetryRequest will + * be needed. + * - A negative value for fatal errors. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_key_shares_ext(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char const *p = buf; + unsigned char const *client_shares_end; + size_t client_shares_len; + + /* From RFC 8446: + * + * struct { + * KeyShareEntry client_shares<0..2^16-1>; + * } KeyShareClientHello; + * + */ + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); + client_shares_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, client_shares_len); + + ssl->handshake->offered_group_id = 0; + client_shares_end = p + client_shares_len; + + /* We try to find a suitable key share entry and copy it to the + * handshake context. Later, we have to find out whether we can do + * something with the provided key share or whether we have to + * dismiss it and send a HelloRetryRequest message. + */ + + while (p < client_shares_end) { + uint16_t group; + size_t key_exchange_len; + const unsigned char *key_exchange; + + /* + * struct { + * NamedGroup group; + * opaque key_exchange<1..2^16-1>; + * } KeyShareEntry; + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, client_shares_end, 4); + group = MBEDTLS_GET_UINT16_BE(p, 0); + key_exchange_len = MBEDTLS_GET_UINT16_BE(p, 2); + p += 4; + key_exchange = p; + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, client_shares_end, key_exchange_len); + p += key_exchange_len; + + /* Continue parsing even if we have already found a match, + * for input validation purposes. + */ + if (!mbedtls_ssl_named_group_is_offered(ssl, group) || + !mbedtls_ssl_named_group_is_supported(group) || + ssl->handshake->offered_group_id != 0) { + continue; + } + + /* + * For now, we only support ECDHE groups. + */ + if (mbedtls_ssl_tls13_named_group_is_ecdhe(group)) { + MBEDTLS_SSL_DEBUG_MSG(2, ("ECDH group: %s (%04x)", + mbedtls_ssl_named_group_to_str(group), + group)); + ret = mbedtls_ssl_tls13_read_public_ecdhe_share( + ssl, key_exchange - 2, key_exchange_len + 2); + if (ret != 0) { + return ret; + } + + } else { + MBEDTLS_SSL_DEBUG_MSG(4, ("Unrecognized NamedGroup %u", + (unsigned) group)); + continue; + } + + ssl->handshake->offered_group_id = group; + } + + + if (ssl->handshake->offered_group_id == 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("no matching key share")); + return SSL_TLS1_3_PARSE_KEY_SHARES_EXT_NO_MATCH; + } + return 0; +} +#endif /* MBEDTLS_ECDH_C */ + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_client_hello_has_exts(mbedtls_ssl_context *ssl, + int exts_mask) +{ + int masked = ssl->handshake->received_extensions & exts_mask; + return masked == exts_mask; +} + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_client_hello_has_exts_for_ephemeral_key_exchange( + mbedtls_ssl_context *ssl) +{ + return ssl_tls13_client_hello_has_exts( + ssl, + MBEDTLS_SSL_EXT_MASK(SUPPORTED_GROUPS) | + MBEDTLS_SSL_EXT_MASK(KEY_SHARE) | + MBEDTLS_SSL_EXT_MASK(SIG_ALG)); +} +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_client_hello_has_exts_for_psk_key_exchange( + mbedtls_ssl_context *ssl) +{ + return ssl_tls13_client_hello_has_exts( + ssl, + MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY) | + MBEDTLS_SSL_EXT_MASK(PSK_KEY_EXCHANGE_MODES)); +} +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED */ + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_client_hello_has_exts_for_psk_ephemeral_key_exchange( + mbedtls_ssl_context *ssl) +{ + return ssl_tls13_client_hello_has_exts( + ssl, + MBEDTLS_SSL_EXT_MASK(SUPPORTED_GROUPS) | + MBEDTLS_SSL_EXT_MASK(KEY_SHARE) | + MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY) | + MBEDTLS_SSL_EXT_MASK(PSK_KEY_EXCHANGE_MODES)); +} +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED */ + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_check_ephemeral_key_exchange(mbedtls_ssl_context *ssl) +{ +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) + return mbedtls_ssl_conf_tls13_ephemeral_enabled(ssl) && + ssl_tls13_client_hello_has_exts_for_ephemeral_key_exchange(ssl); +#else + ((void) ssl); + return 0; +#endif +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_check_psk_key_exchange(mbedtls_ssl_context *ssl) +{ +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED) + return mbedtls_ssl_conf_tls13_psk_enabled(ssl) && + mbedtls_ssl_tls13_psk_enabled(ssl) && + ssl_tls13_client_hello_has_exts_for_psk_key_exchange(ssl); +#else + ((void) ssl); + return 0; +#endif +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_check_psk_ephemeral_key_exchange(mbedtls_ssl_context *ssl) +{ +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED) + return mbedtls_ssl_conf_tls13_psk_ephemeral_enabled(ssl) && + mbedtls_ssl_tls13_psk_ephemeral_enabled(ssl) && + ssl_tls13_client_hello_has_exts_for_psk_ephemeral_key_exchange(ssl); +#else + ((void) ssl); + return 0; +#endif +} + +static int ssl_tls13_determine_key_exchange_mode(mbedtls_ssl_context *ssl) +{ + /* + * Determine the key exchange algorithm to use. + * There are three types of key exchanges supported in TLS 1.3: + * - (EC)DH with ECDSA, + * - (EC)DH with PSK, + * - plain PSK. + * + * The PSK-based key exchanges may additionally be used with 0-RTT. + * + * Our built-in order of preference is + * 1 ) (EC)DHE-PSK Mode ( psk_ephemeral ) + * 2 ) Certificate Mode ( ephemeral ) + * 3 ) Plain PSK Mode ( psk ) + */ + + ssl->handshake->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_NONE; + + if (ssl_tls13_check_psk_ephemeral_key_exchange(ssl)) { + ssl->handshake->key_exchange_mode = + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL; + MBEDTLS_SSL_DEBUG_MSG(2, ("key exchange mode: psk_ephemeral")); + } else + if (ssl_tls13_check_ephemeral_key_exchange(ssl)) { + ssl->handshake->key_exchange_mode = + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL; + MBEDTLS_SSL_DEBUG_MSG(2, ("key exchange mode: ephemeral")); + } else + if (ssl_tls13_check_psk_key_exchange(ssl)) { + ssl->handshake->key_exchange_mode = + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK; + MBEDTLS_SSL_DEBUG_MSG(2, ("key exchange mode: psk")); + } else { + MBEDTLS_SSL_DEBUG_MSG( + 1, + ("ClientHello message misses mandatory extensions.")); + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_MISSING_EXTENSION, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + + return 0; + +} + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ + defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +static psa_algorithm_t ssl_tls13_iana_sig_alg_to_psa_alg(uint16_t sig_alg) +{ + switch (sig_alg) { + case MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256: + return PSA_ALG_ECDSA(PSA_ALG_SHA_256); + case MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384: + return PSA_ALG_ECDSA(PSA_ALG_SHA_384); + case MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512: + return PSA_ALG_ECDSA(PSA_ALG_SHA_512); + case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256: + return PSA_ALG_RSA_PSS(PSA_ALG_SHA_256); + case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384: + return PSA_ALG_RSA_PSS(PSA_ALG_SHA_384); + case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512: + return PSA_ALG_RSA_PSS(PSA_ALG_SHA_512); + case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256: + return PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256); + case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384: + return PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_384); + case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512: + return PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_512); + default: + return PSA_ALG_NONE; + } +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +/* + * Pick best ( private key, certificate chain ) pair based on the signature + * algorithms supported by the client. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_pick_key_cert(mbedtls_ssl_context *ssl) +{ + mbedtls_ssl_key_cert *key_cert, *key_cert_list; + const uint16_t *sig_alg = ssl->handshake->received_sig_algs; + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if (ssl->handshake->sni_key_cert != NULL) { + key_cert_list = ssl->handshake->sni_key_cert; + } else +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + key_cert_list = ssl->conf->key_cert; + + if (key_cert_list == NULL) { + MBEDTLS_SSL_DEBUG_MSG(3, ("server has no certificate")); + return -1; + } + + for (; *sig_alg != MBEDTLS_TLS1_3_SIG_NONE; sig_alg++) { + if (!mbedtls_ssl_sig_alg_is_offered(ssl, *sig_alg)) { + continue; + } + + if (!mbedtls_ssl_tls13_sig_alg_for_cert_verify_is_supported(*sig_alg)) { + continue; + } + + for (key_cert = key_cert_list; key_cert != NULL; + key_cert = key_cert->next) { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_algorithm_t psa_alg = PSA_ALG_NONE; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + MBEDTLS_SSL_DEBUG_CRT(3, "certificate (chain) candidate", + key_cert->cert); + + /* + * This avoids sending the client a cert it'll reject based on + * keyUsage or other extensions. + */ + if (mbedtls_x509_crt_check_key_usage( + key_cert->cert, MBEDTLS_X509_KU_DIGITAL_SIGNATURE) != 0 || + mbedtls_x509_crt_check_extended_key_usage( + key_cert->cert, MBEDTLS_OID_SERVER_AUTH, + MBEDTLS_OID_SIZE(MBEDTLS_OID_SERVER_AUTH)) != 0) { + MBEDTLS_SSL_DEBUG_MSG(3, ("certificate mismatch: " + "(extended) key usage extension")); + continue; + } + + MBEDTLS_SSL_DEBUG_MSG(3, + ("ssl_tls13_pick_key_cert:" + "check signature algorithm %s [%04x]", + mbedtls_ssl_sig_alg_to_str(*sig_alg), + *sig_alg)); +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_alg = ssl_tls13_iana_sig_alg_to_psa_alg(*sig_alg); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + if (mbedtls_ssl_tls13_check_sig_alg_cert_key_match( + *sig_alg, &key_cert->cert->pk) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + && psa_alg != PSA_ALG_NONE && + mbedtls_pk_can_do_ext(&key_cert->cert->pk, psa_alg, + PSA_KEY_USAGE_SIGN_HASH) == 1 +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + ) { + ssl->handshake->key_cert = key_cert; + MBEDTLS_SSL_DEBUG_MSG(3, + ("ssl_tls13_pick_key_cert:" + "selected signature algorithm" + " %s [%04x]", + mbedtls_ssl_sig_alg_to_str(*sig_alg), + *sig_alg)); + MBEDTLS_SSL_DEBUG_CRT( + 3, "selected certificate (chain)", + ssl->handshake->key_cert->cert); + return 0; + } + } + } + + MBEDTLS_SSL_DEBUG_MSG(2, ("ssl_tls13_pick_key_cert:" + "no suitable certificate found")); + return -1; +} +#endif /* MBEDTLS_X509_CRT_PARSE_C && + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ + +/* + * + * STATE HANDLING: ClientHello + * + * There are three possible classes of outcomes when parsing the ClientHello: + * + * 1) The ClientHello was well-formed and matched the server's configuration. + * + * In this case, the server progresses to sending its ServerHello. + * + * 2) The ClientHello was well-formed but didn't match the server's + * configuration. + * + * For example, the client might not have offered a key share which + * the server supports, or the server might require a cookie. + * + * In this case, the server sends a HelloRetryRequest. + * + * 3) The ClientHello was ill-formed + * + * In this case, we abort the handshake. + * + */ + +/* + * Structure of this message: + * + * uint16 ProtocolVersion; + * opaque Random[32]; + * uint8 CipherSuite[2]; // Cryptographic suite selector + * + * struct { + * ProtocolVersion legacy_version = 0x0303; // TLS v1.2 + * Random random; + * opaque legacy_session_id<0..32>; + * CipherSuite cipher_suites<2..2^16-2>; + * opaque legacy_compression_methods<1..2^8-1>; + * Extension extensions<8..2^16-1>; + * } ClientHello; + */ + +#define SSL_CLIENT_HELLO_OK 0 +#define SSL_CLIENT_HELLO_HRR_REQUIRED 1 + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_parse_client_hello(mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const unsigned char *p = buf; + size_t legacy_session_id_len; + size_t cipher_suites_len; + const unsigned char *cipher_suites_end; + size_t extensions_len; + const unsigned char *extensions_end; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + int hrr_required = 0; + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) + const unsigned char *cipher_suites; + const unsigned char *pre_shared_key_ext = NULL; + const unsigned char *pre_shared_key_ext_end = NULL; +#endif + + /* + * ClientHello layout: + * 0 . 1 protocol version + * 2 . 33 random bytes + * 34 . 34 session id length ( 1 byte ) + * 35 . 34+x session id + * .. . .. 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. + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 38); + + /* ... + * ProtocolVersion legacy_version = 0x0303; // TLS 1.2 + * ... + * with ProtocolVersion defined as: + * uint16 ProtocolVersion; + */ + if (mbedtls_ssl_read_version(p, ssl->conf->transport) != + MBEDTLS_SSL_VERSION_TLS1_2) { + MBEDTLS_SSL_DEBUG_MSG(1, ("Unsupported version of TLS.")); + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION, + MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION); + return MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION; + } + p += 2; + + /* + * Only support TLS 1.3 currently, temporarily set the version. + */ + ssl->tls_version = MBEDTLS_SSL_VERSION_TLS1_3; + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + /* Store minor version for later use with ticket serialization. */ + ssl->session_negotiate->tls_version = MBEDTLS_SSL_VERSION_TLS1_3; + ssl->session_negotiate->endpoint = ssl->conf->endpoint; +#endif + + /* ... + * Random random; + * ... + * with Random defined as: + * opaque Random[32]; + */ + MBEDTLS_SSL_DEBUG_BUF(3, "client hello, random bytes", + p, MBEDTLS_CLIENT_HELLO_RANDOM_LEN); + + memcpy(&handshake->randbytes[0], p, MBEDTLS_CLIENT_HELLO_RANDOM_LEN); + p += MBEDTLS_CLIENT_HELLO_RANDOM_LEN; + + /* ... + * opaque legacy_session_id<0..32>; + * ... + */ + legacy_session_id_len = p[0]; + p++; + + if (legacy_session_id_len > sizeof(ssl->session_negotiate->id)) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + ssl->session_negotiate->id_len = legacy_session_id_len; + MBEDTLS_SSL_DEBUG_BUF(3, "client hello, session id", + p, legacy_session_id_len); + /* + * Check we have enough data for the legacy session identifier + * and the ciphersuite list length. + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, legacy_session_id_len + 2); + + memcpy(&ssl->session_negotiate->id[0], p, legacy_session_id_len); + p += legacy_session_id_len; + + cipher_suites_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + + /* + * The length of the ciphersuite list has to be even. + */ + if (cipher_suites_len & 1) { + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, + MBEDTLS_ERR_SSL_DECODE_ERROR); + return MBEDTLS_ERR_SSL_DECODE_ERROR; + } + + /* Check we have enough data for the ciphersuite list, the legacy + * compression methods and the length of the extensions. + * + * cipher_suites cipher_suites_len bytes + * legacy_compression_methods 2 bytes + * extensions_len 2 bytes + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, cipher_suites_len + 2 + 2); + + /* ... + * CipherSuite cipher_suites<2..2^16-2>; + * ... + * with CipherSuite defined as: + * uint8 CipherSuite[2]; + */ +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) + cipher_suites = p; +#endif + cipher_suites_end = p + cipher_suites_len; + MBEDTLS_SSL_DEBUG_BUF(3, "client hello, ciphersuitelist", + p, cipher_suites_len); + + /* + * Search for a matching ciphersuite + */ + for (; p < cipher_suites_end; p += 2) { + uint16_t cipher_suite; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + + /* + * "cipher_suite_end - p is even" is an invariant of the loop. As + * cipher_suites_end - p > 0, we have cipher_suites_end - p >= 2 and + * it is thus safe to read two bytes. + */ + cipher_suite = MBEDTLS_GET_UINT16_BE(p, 0); + ciphersuite_info = ssl_tls13_validate_peer_ciphersuite( + ssl, cipher_suite); + if (ciphersuite_info == NULL) { + continue; + } + + ssl->session_negotiate->ciphersuite = cipher_suite; + handshake->ciphersuite_info = ciphersuite_info; + MBEDTLS_SSL_DEBUG_MSG(2, ("selected ciphersuite: %04x - %s", + cipher_suite, + ciphersuite_info->name)); + break; + } + + if (handshake->ciphersuite_info == NULL) { + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, + MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + p = cipher_suites_end; + + /* ... + * opaque legacy_compression_methods<1..2^8-1>; + * ... + */ + if (p[0] != 1 || p[1] != MBEDTLS_SSL_COMPRESS_NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("bad legacy compression method")); + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + p += 2; + + /* ... + * Extension extensions<8..2^16-1>; + * ... + * with Extension defined as: + * struct { + * ExtensionType extension_type; + * opaque extension_data<0..2^16-1>; + * } Extension; + */ + extensions_len = MBEDTLS_GET_UINT16_BE(p, 0); + p += 2; + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len); + extensions_end = p + extensions_len; + + MBEDTLS_SSL_DEBUG_BUF(3, "client hello extensions", p, extensions_len); + + handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE; + + while (p < extensions_end) { + unsigned int extension_type; + size_t extension_data_len; + const unsigned char *extension_data_end; + + /* RFC 8446, section 4.2.11 + * + * The "pre_shared_key" extension MUST be the last extension in the + * ClientHello (this facilitates implementation as described below). + * Servers MUST check that it is the last extension and otherwise fail + * the handshake with an "illegal_parameter" alert. + */ + if (handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY)) { + MBEDTLS_SSL_DEBUG_MSG( + 3, ("pre_shared_key is not last extension.")); + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4); + extension_type = MBEDTLS_GET_UINT16_BE(p, 0); + extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2); + p += 4; + + MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len); + extension_data_end = p + extension_data_len; + + ret = mbedtls_ssl_tls13_check_received_extension( + ssl, MBEDTLS_SSL_HS_CLIENT_HELLO, extension_type, + MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CH); + if (ret != 0) { + return ret; + } + + switch (extension_type) { +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + case MBEDTLS_TLS_EXT_SERVERNAME: + MBEDTLS_SSL_DEBUG_MSG(3, ("found ServerName extension")); + ret = mbedtls_ssl_parse_server_name_ext(ssl, p, + extension_data_end); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET( + 1, "mbedtls_ssl_parse_servername_ext", ret); + return ret; + } + break; +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_ECDH_C) + case MBEDTLS_TLS_EXT_SUPPORTED_GROUPS: + MBEDTLS_SSL_DEBUG_MSG(3, ("found supported group extension")); + + /* Supported Groups Extension + * + * When sent by the client, the "supported_groups" extension + * indicates the named groups which the client supports, + * ordered from most preferred to least preferred. + */ + ret = ssl_tls13_parse_supported_groups_ext( + ssl, p, extension_data_end); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, + "mbedtls_ssl_parse_supported_groups_ext", ret); + return ret; + } + + break; +#endif /* MBEDTLS_ECDH_C */ + +#if defined(MBEDTLS_ECDH_C) + case MBEDTLS_TLS_EXT_KEY_SHARE: + MBEDTLS_SSL_DEBUG_MSG(3, ("found key share extension")); + + /* + * Key Share Extension + * + * When sent by the client, the "key_share" extension + * contains the endpoint's cryptographic parameters for + * ECDHE/DHE key establishment methods. + */ + ret = ssl_tls13_parse_key_shares_ext( + ssl, p, extension_data_end); + if (ret == SSL_TLS1_3_PARSE_KEY_SHARES_EXT_NO_MATCH) { + MBEDTLS_SSL_DEBUG_MSG(2, ("HRR needed ")); + hrr_required = 1; + } + + if (ret < 0) { + MBEDTLS_SSL_DEBUG_RET( + 1, "ssl_tls13_parse_key_shares_ext", ret); + return ret; + } + + break; +#endif /* MBEDTLS_ECDH_C */ + + case MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS: + MBEDTLS_SSL_DEBUG_MSG(3, ("found supported versions extension")); + + ret = ssl_tls13_parse_supported_versions_ext( + ssl, p, extension_data_end); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, + ("ssl_tls13_parse_supported_versions_ext"), ret); + return ret; + } + break; + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) + case MBEDTLS_TLS_EXT_PSK_KEY_EXCHANGE_MODES: + MBEDTLS_SSL_DEBUG_MSG(3, ("found psk key exchange modes extension")); + + ret = ssl_tls13_parse_key_exchange_modes_ext( + ssl, p, extension_data_end); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET( + 1, "ssl_tls13_parse_key_exchange_modes_ext", ret); + return ret; + } + + break; +#endif + + case MBEDTLS_TLS_EXT_PRE_SHARED_KEY: + MBEDTLS_SSL_DEBUG_MSG(3, ("found pre_shared_key extension")); + if ((handshake->received_extensions & + MBEDTLS_SSL_EXT_MASK(PSK_KEY_EXCHANGE_MODES)) == 0) { + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; + } +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) + /* Delay processing of the PSK identity once we have + * found out which algorithms to use. We keep a pointer + * to the buffer and the size for later processing. + */ + pre_shared_key_ext = p; + pre_shared_key_ext_end = extension_data_end; +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ + break; + +#if defined(MBEDTLS_SSL_ALPN) + case MBEDTLS_TLS_EXT_ALPN: + MBEDTLS_SSL_DEBUG_MSG(3, ("found alpn extension")); + + ret = mbedtls_ssl_parse_alpn_ext(ssl, p, extension_data_end); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET( + 1, ("mbedtls_ssl_parse_alpn_ext"), ret); + return ret; + } + break; +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) + case MBEDTLS_TLS_EXT_SIG_ALG: + MBEDTLS_SSL_DEBUG_MSG(3, ("found signature_algorithms extension")); + + ret = mbedtls_ssl_parse_sig_alg_ext( + ssl, p, extension_data_end); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_MSG(1, + ( + "ssl_parse_supported_signature_algorithms_server_ext ( %d )", + ret)); + return ret; + } + break; +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ + +#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) + case MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT: + MBEDTLS_SSL_DEBUG_MSG(3, ("found record_size_limit extension")); + + ret = mbedtls_ssl_tls13_parse_record_size_limit_ext(ssl, p, extension_data_end); + + /* TODO: Return unconditionally here until we handle the record size limit correctly. + * Once handled correctly, only return in case of errors. */ + return ret; + + break; +#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ + + default: + MBEDTLS_SSL_PRINT_EXT( + 3, MBEDTLS_SSL_HS_CLIENT_HELLO, + extension_type, "( ignored )"); + break; + } + + p += extension_data_len; + } + + MBEDTLS_SSL_PRINT_EXTS(3, MBEDTLS_SSL_HS_CLIENT_HELLO, + handshake->received_extensions); + + ret = mbedtls_ssl_add_hs_hdr_to_checksum(ssl, + MBEDTLS_SSL_HS_CLIENT_HELLO, + p - buf); + if (0 != ret) { + MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ssl_add_hs_hdr_to_checksum"), ret); + return ret; + } + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) + /* Update checksum with either + * - The entire content of the CH message, if no PSK extension is present + * - The content up to but excluding the PSK extension, if present. + */ + /* If we've settled on a PSK-based exchange, parse PSK identity ext */ + if (mbedtls_ssl_tls13_some_psk_enabled(ssl) && + mbedtls_ssl_conf_tls13_some_psk_enabled(ssl) && + (handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY))) { + ret = handshake->update_checksum(ssl, buf, + pre_shared_key_ext - buf); + if (0 != ret) { + MBEDTLS_SSL_DEBUG_RET(1, ("update_checksum"), ret); + return ret; + } + ret = ssl_tls13_parse_pre_shared_key_ext(ssl, + pre_shared_key_ext, + pre_shared_key_ext_end, + cipher_suites, + cipher_suites_end); + if (ret == MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY) { + handshake->received_extensions &= ~MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY); + } else if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET( + 1, "ssl_tls13_parse_pre_shared_key_ext", ret); + return ret; + } + } else +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ + { + ret = handshake->update_checksum(ssl, buf, p - buf); + if (0 != ret) { + MBEDTLS_SSL_DEBUG_RET(1, ("update_checksum"), ret); + return ret; + } + } + + ret = ssl_tls13_determine_key_exchange_mode(ssl); + if (ret < 0) { + return ret; + } + + mbedtls_ssl_optimize_checksum(ssl, handshake->ciphersuite_info); + + return hrr_required ? SSL_CLIENT_HELLO_HRR_REQUIRED : SSL_CLIENT_HELLO_OK; +} + +/* Update the handshake state machine */ + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_postprocess_client_hello(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* + * Server certificate selection + */ + if (ssl->conf->f_cert_cb && (ret = ssl->conf->f_cert_cb(ssl)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "f_cert_cb", ret); + return ret; + } +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + ssl->handshake->sni_name = NULL; + ssl->handshake->sni_name_len = 0; +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + + ret = mbedtls_ssl_tls13_key_schedule_stage_early(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, + "mbedtls_ssl_tls1_3_key_schedule_stage_early", ret); + return ret; + } + + return 0; + +} + +/* + * Main entry point from the state machine; orchestrates the otherfunctions. + */ + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_process_client_hello(mbedtls_ssl_context *ssl) +{ + + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *buf = NULL; + size_t buflen = 0; + int parse_client_hello_ret; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse client hello")); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( + ssl, MBEDTLS_SSL_HS_CLIENT_HELLO, + &buf, &buflen)); + + MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_parse_client_hello(ssl, buf, + buf + buflen)); + parse_client_hello_ret = ret; /* Store return value of parse_client_hello, + * only SSL_CLIENT_HELLO_OK or + * SSL_CLIENT_HELLO_HRR_REQUIRED at this + * stage as negative error codes are handled + * by MBEDTLS_SSL_PROC_CHK_NEG. */ + + MBEDTLS_SSL_PROC_CHK(ssl_tls13_postprocess_client_hello(ssl)); + + if (parse_client_hello_ret == SSL_CLIENT_HELLO_OK) { + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_HELLO); + } else { + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HELLO_RETRY_REQUEST); + } + +cleanup: + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse client hello")); + return ret; +} + +/* + * Handler for MBEDTLS_SSL_SERVER_HELLO + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_prepare_server_hello(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *server_randbytes = + ssl->handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN; + if (ssl->conf->f_rng == NULL) { + MBEDTLS_SSL_DEBUG_MSG(1, ("no RNG provided")); + return MBEDTLS_ERR_SSL_NO_RNG; + } + + if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, server_randbytes, + MBEDTLS_SERVER_HELLO_RANDOM_LEN)) != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "f_rng", ret); + return ret; + } + + MBEDTLS_SSL_DEBUG_BUF(3, "server hello, random bytes", server_randbytes, + MBEDTLS_SERVER_HELLO_RANDOM_LEN); + +#if defined(MBEDTLS_HAVE_TIME) + ssl->session_negotiate->start = time(NULL); +#endif /* MBEDTLS_HAVE_TIME */ + + return ret; +} + +/* + * ssl_tls13_write_server_hello_supported_versions_ext (): + * + * struct { + * ProtocolVersion selected_version; + * } SupportedVersions; + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_server_hello_supported_versions_ext( + mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len) +{ + *out_len = 0; + + MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, write selected version")); + + /* Check if we have space to write the extension: + * - extension_type (2 bytes) + * - extension_data_length (2 bytes) + * - selected_version (2 bytes) + */ + MBEDTLS_SSL_CHK_BUF_PTR(buf, end, 6); + + MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS, buf, 0); + + MBEDTLS_PUT_UINT16_BE(2, buf, 2); + + mbedtls_ssl_write_version(buf + 4, + ssl->conf->transport, + ssl->tls_version); + + MBEDTLS_SSL_DEBUG_MSG(3, ("supported version: [%04x]", + ssl->tls_version)); + + *out_len = 6; + + mbedtls_ssl_tls13_set_hs_sent_ext_mask( + ssl, MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS); + + return 0; +} + + + +/* Generate and export a single key share. For hybrid KEMs, this can + * be called multiple times with the different components of the hybrid. */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_generate_and_write_key_share(mbedtls_ssl_context *ssl, + uint16_t named_group, + unsigned char *buf, + unsigned char *end, + size_t *out_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + *out_len = 0; + +#if defined(MBEDTLS_ECDH_C) + if (mbedtls_ssl_tls13_named_group_is_ecdhe(named_group)) { + ret = mbedtls_ssl_tls13_generate_and_write_ecdh_key_exchange( + ssl, named_group, buf, end, out_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET( + 1, "mbedtls_ssl_tls13_generate_and_write_ecdh_key_exchange", + ret); + return ret; + } + } else +#endif /* MBEDTLS_ECDH_C */ + if (0 /* Other kinds of KEMs */) { + } else { + ((void) ssl); + ((void) named_group); + ((void) buf); + ((void) end); + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + return ret; +} + +/* + * ssl_tls13_write_key_share_ext + * + * Structure of key_share extension in ServerHello: + * + * struct { + * NamedGroup group; + * opaque key_exchange<1..2^16-1>; + * } KeyShareEntry; + * struct { + * KeyShareEntry server_share; + * } KeyShareServerHello; + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_key_share_ext(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = buf; + uint16_t group = ssl->handshake->offered_group_id; + unsigned char *server_share = buf + 4; + size_t key_exchange_length; + + *out_len = 0; + + MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, adding key share extension")); + + MBEDTLS_SSL_DEBUG_MSG(2, ("server hello, write selected_group: %s (%04x)", + mbedtls_ssl_named_group_to_str(group), + group)); + + /* Check if we have space for header and length fields: + * - extension_type (2 bytes) + * - extension_data_length (2 bytes) + * - group (2 bytes) + * - key_exchange_length (2 bytes) + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 8); + MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_KEY_SHARE, p, 0); + MBEDTLS_PUT_UINT16_BE(group, server_share, 0); + p += 8; + + /* When we introduce PQC-ECDHE hybrids, we'll want to call this + * function multiple times. */ + ret = ssl_tls13_generate_and_write_key_share( + ssl, group, server_share + 4, end, &key_exchange_length); + if (ret != 0) { + return ret; + } + p += key_exchange_length; + + MBEDTLS_PUT_UINT16_BE(key_exchange_length, server_share + 2, 0); + + MBEDTLS_PUT_UINT16_BE(p - server_share, buf, 2); + + *out_len = p - buf; + + mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_KEY_SHARE); + + return 0; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_hrr_key_share_ext(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len) +{ + uint16_t selected_group = ssl->handshake->hrr_selected_group; + /* key_share Extension + * + * struct { + * select (Handshake.msg_type) { + * ... + * case hello_retry_request: + * NamedGroup selected_group; + * ... + * }; + * } KeyShare; + */ + + *out_len = 0; + + /* + * For a pure PSK key exchange, there is no group to agree upon. The purpose + * of the HRR is then to transmit a cookie to force the client to demonstrate + * reachability at their apparent network address (primarily useful for DTLS). + */ + if (!mbedtls_ssl_tls13_key_exchange_mode_with_ephemeral(ssl)) { + return 0; + } + + /* We should only send the key_share extension if the client's initial + * key share was not acceptable. */ + if (ssl->handshake->offered_group_id != 0) { + MBEDTLS_SSL_DEBUG_MSG(4, ("Skip key_share extension in HRR")); + return 0; + } + + if (selected_group == 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("no matching named group found")); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + + /* Check if we have enough space: + * - extension_type (2 bytes) + * - extension_data_length (2 bytes) + * - selected_group (2 bytes) + */ + MBEDTLS_SSL_CHK_BUF_PTR(buf, end, 6); + + MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_KEY_SHARE, buf, 0); + MBEDTLS_PUT_UINT16_BE(2, buf, 2); + MBEDTLS_PUT_UINT16_BE(selected_group, buf, 4); + + MBEDTLS_SSL_DEBUG_MSG(3, + ("HRR selected_group: %s (%x)", + mbedtls_ssl_named_group_to_str(selected_group), + selected_group)); + + *out_len = 6; + + mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_KEY_SHARE); + + return 0; +} + +/* + * Structure of ServerHello message: + * + * struct { + * ProtocolVersion legacy_version = 0x0303; // TLS v1.2 + * Random random; + * opaque legacy_session_id_echo<0..32>; + * CipherSuite cipher_suite; + * uint8 legacy_compression_method = 0; + * Extension extensions<6..2^16-1>; + * } ServerHello; + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_server_hello_body(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len, + int is_hrr) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = buf; + unsigned char *p_extensions_len; + size_t output_len; + + *out_len = 0; + ssl->handshake->sent_extensions = MBEDTLS_SSL_EXT_MASK_NONE; + + /* ... + * ProtocolVersion legacy_version = 0x0303; // TLS 1.2 + * ... + * with ProtocolVersion defined as: + * uint16 ProtocolVersion; + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); + MBEDTLS_PUT_UINT16_BE(0x0303, p, 0); + p += 2; + + /* ... + * Random random; + * ... + * with Random defined as: + * opaque Random[MBEDTLS_SERVER_HELLO_RANDOM_LEN]; + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, MBEDTLS_SERVER_HELLO_RANDOM_LEN); + if (is_hrr) { + memcpy(p, mbedtls_ssl_tls13_hello_retry_request_magic, + MBEDTLS_SERVER_HELLO_RANDOM_LEN); + } else { + memcpy(p, &ssl->handshake->randbytes[MBEDTLS_CLIENT_HELLO_RANDOM_LEN], + MBEDTLS_SERVER_HELLO_RANDOM_LEN); + } + MBEDTLS_SSL_DEBUG_BUF(3, "server hello, random bytes", + p, MBEDTLS_SERVER_HELLO_RANDOM_LEN); + p += MBEDTLS_SERVER_HELLO_RANDOM_LEN; + + /* ... + * opaque legacy_session_id_echo<0..32>; + * ... + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 1 + ssl->session_negotiate->id_len); + *p++ = (unsigned char) ssl->session_negotiate->id_len; + if (ssl->session_negotiate->id_len > 0) { + memcpy(p, &ssl->session_negotiate->id[0], + ssl->session_negotiate->id_len); + p += ssl->session_negotiate->id_len; + + MBEDTLS_SSL_DEBUG_BUF(3, "session id", ssl->session_negotiate->id, + ssl->session_negotiate->id_len); + } + + /* ... + * CipherSuite cipher_suite; + * ... + * with CipherSuite defined as: + * uint8 CipherSuite[2]; + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); + MBEDTLS_PUT_UINT16_BE(ssl->session_negotiate->ciphersuite, p, 0); + p += 2; + MBEDTLS_SSL_DEBUG_MSG(3, + ("server hello, chosen ciphersuite: %s ( id=%d )", + mbedtls_ssl_get_ciphersuite_name( + ssl->session_negotiate->ciphersuite), + ssl->session_negotiate->ciphersuite)); + + /* ... + * uint8 legacy_compression_method = 0; + * ... + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 1); + *p++ = MBEDTLS_SSL_COMPRESS_NULL; + + /* ... + * Extension extensions<6..2^16-1>; + * ... + * struct { + * ExtensionType extension_type; (2 bytes) + * opaque extension_data<0..2^16-1>; + * } Extension; + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); + p_extensions_len = p; + p += 2; + + if ((ret = ssl_tls13_write_server_hello_supported_versions_ext( + ssl, p, end, &output_len)) != 0) { + MBEDTLS_SSL_DEBUG_RET( + 1, "ssl_tls13_write_server_hello_supported_versions_ext", ret); + return ret; + } + p += output_len; + + if (mbedtls_ssl_tls13_key_exchange_mode_with_ephemeral(ssl)) { + if (is_hrr) { + ret = ssl_tls13_write_hrr_key_share_ext(ssl, p, end, &output_len); + } else { + ret = ssl_tls13_write_key_share_ext(ssl, p, end, &output_len); + } + if (ret != 0) { + return ret; + } + p += output_len; + } + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) + if (!is_hrr && mbedtls_ssl_tls13_key_exchange_mode_with_psk(ssl)) { + ret = ssl_tls13_write_server_pre_shared_key_ext(ssl, p, end, &output_len); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_write_server_pre_shared_key_ext", + ret); + return ret; + } + p += output_len; + } +#endif + + MBEDTLS_PUT_UINT16_BE(p - p_extensions_len - 2, p_extensions_len, 0); + + MBEDTLS_SSL_DEBUG_BUF(4, "server hello extensions", + p_extensions_len, p - p_extensions_len); + + *out_len = p - buf; + + MBEDTLS_SSL_DEBUG_BUF(3, "server hello", buf, *out_len); + + MBEDTLS_SSL_PRINT_EXTS( + 3, is_hrr ? MBEDTLS_SSL_TLS1_3_HS_HELLO_RETRY_REQUEST : + MBEDTLS_SSL_HS_SERVER_HELLO, + ssl->handshake->sent_extensions); + + return ret; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_finalize_server_hello(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ret = mbedtls_ssl_tls13_compute_handshake_transform(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, + "mbedtls_ssl_tls13_compute_handshake_transform", + ret); + return ret; + } + + return ret; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_server_hello(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *buf; + size_t buf_len, msg_len; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> write server hello")); + + MBEDTLS_SSL_PROC_CHK(ssl_tls13_prepare_server_hello(ssl)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(ssl, + MBEDTLS_SSL_HS_SERVER_HELLO, &buf, + &buf_len)); + + MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_server_hello_body(ssl, buf, + buf + buf_len, + &msg_len, + 0)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( + ssl, MBEDTLS_SSL_HS_SERVER_HELLO, buf, msg_len)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg( + ssl, buf_len, msg_len)); + + MBEDTLS_SSL_PROC_CHK(ssl_tls13_finalize_server_hello(ssl)); + +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + /* The server sends a dummy change_cipher_spec record immediately + * after its first handshake message. This may either be after + * a ServerHello or a HelloRetryRequest. + */ + mbedtls_ssl_handshake_set_state( + ssl, MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO); +#else + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS); +#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ + +cleanup: + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= write server hello")); + return ret; +} + + +/* + * Handler for MBEDTLS_SSL_HELLO_RETRY_REQUEST + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_prepare_hello_retry_request(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + if (ssl->handshake->hello_retry_request_count > 0) { + MBEDTLS_SSL_DEBUG_MSG(1, ("Too many HRRs")); + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, + MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + + /* + * Create stateless transcript hash for HRR + */ + MBEDTLS_SSL_DEBUG_MSG(4, ("Reset transcript for HRR")); + ret = mbedtls_ssl_reset_transcript_for_hrr(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_reset_transcript_for_hrr", ret); + return ret; + } + mbedtls_ssl_session_reset_msg_layer(ssl, 0); + + return 0; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_hello_retry_request(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *buf; + size_t buf_len, msg_len; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> write hello retry request")); + + MBEDTLS_SSL_PROC_CHK(ssl_tls13_prepare_hello_retry_request(ssl)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg( + ssl, MBEDTLS_SSL_HS_SERVER_HELLO, + &buf, &buf_len)); + + MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_server_hello_body(ssl, buf, + buf + buf_len, + &msg_len, + 1)); + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( + ssl, MBEDTLS_SSL_HS_SERVER_HELLO, buf, msg_len)); + + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(ssl, buf_len, + msg_len)); + + ssl->handshake->hello_retry_request_count++; + +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + /* The server sends a dummy change_cipher_spec record immediately + * after its first handshake message. This may either be after + * a ServerHello or a HelloRetryRequest. + */ + mbedtls_ssl_handshake_set_state( + ssl, MBEDTLS_SSL_SERVER_CCS_AFTER_HELLO_RETRY_REQUEST); +#else + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO); +#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ + +cleanup: + MBEDTLS_SSL_DEBUG_MSG(2, ("<= write hello retry request")); + return ret; +} + +/* + * Handler for MBEDTLS_SSL_ENCRYPTED_EXTENSIONS + */ + +/* + * struct { + * Extension extensions<0..2 ^ 16 - 1>; + * } EncryptedExtensions; + * + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_encrypted_extensions_body(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = buf; + size_t extensions_len = 0; + unsigned char *p_extensions_len; + size_t output_len; + + *out_len = 0; + + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); + p_extensions_len = p; + p += 2; + + ((void) ssl); + ((void) ret); + ((void) output_len); + +#if defined(MBEDTLS_SSL_ALPN) + ret = mbedtls_ssl_write_alpn_ext(ssl, p, end, &output_len); + if (ret != 0) { + return ret; + } + p += output_len; +#endif /* MBEDTLS_SSL_ALPN */ + + extensions_len = (p - p_extensions_len) - 2; + MBEDTLS_PUT_UINT16_BE(extensions_len, p_extensions_len, 0); + + *out_len = p - buf; + + MBEDTLS_SSL_DEBUG_BUF(4, "encrypted extensions", buf, *out_len); + + MBEDTLS_SSL_PRINT_EXTS( + 3, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, ssl->handshake->sent_extensions); + + return 0; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_encrypted_extensions(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *buf; + size_t buf_len, msg_len; + + mbedtls_ssl_set_outbound_transform(ssl, + ssl->handshake->transform_handshake); + MBEDTLS_SSL_DEBUG_MSG( + 3, ("switching to handshake transform for outbound data")); + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> write encrypted extensions")); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(ssl, + MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, &buf, + &buf_len)); + + MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_encrypted_extensions_body( + ssl, buf, buf + buf_len, &msg_len)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( + ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, buf, msg_len)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg( + ssl, buf_len, msg_len)); + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) + if (mbedtls_ssl_tls13_key_exchange_mode_with_psk(ssl)) { + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_FINISHED); + } else { + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CERTIFICATE_REQUEST); + } +#else + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_FINISHED); +#endif + +cleanup: + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= write encrypted extensions")); + return ret; +} + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) +#define SSL_CERTIFICATE_REQUEST_SEND_REQUEST 0 +#define SSL_CERTIFICATE_REQUEST_SKIP 1 +/* Coordination: + * Check whether a CertificateRequest message should be written. + * Returns a negative code on failure, or + * - SSL_CERTIFICATE_REQUEST_SEND_REQUEST + * - SSL_CERTIFICATE_REQUEST_SKIP + * indicating if the writing of the CertificateRequest + * should be skipped or not. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_certificate_request_coordinate(mbedtls_ssl_context *ssl) +{ + int authmode; + +#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 (authmode == MBEDTLS_SSL_VERIFY_NONE) { + ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_SKIP_VERIFY; + return SSL_CERTIFICATE_REQUEST_SKIP; + } + + ssl->handshake->certificate_request_sent = 1; + + return SSL_CERTIFICATE_REQUEST_SEND_REQUEST; +} + +/* + * struct { + * opaque certificate_request_context<0..2^8-1>; + * Extension extensions<2..2^16-1>; + * } CertificateRequest; + * + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_certificate_request_body(mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *out_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = buf; + size_t output_len = 0; + unsigned char *p_extensions_len; + + *out_len = 0; + + /* Check if we have enough space: + * - certificate_request_context (1 byte) + * - extensions length (2 bytes) + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 3); + + /* + * Write certificate_request_context + */ + /* + * We use a zero length context for the normal handshake + * messages. For post-authentication handshake messages + * this request context would be set to a non-zero value. + */ + *p++ = 0x0; + + /* + * Write extensions + */ + /* The extensions must contain the signature_algorithms. */ + p_extensions_len = p; + p += 2; + ret = mbedtls_ssl_write_sig_alg_ext(ssl, p, end, &output_len); + if (ret != 0) { + return ret; + } + + p += output_len; + MBEDTLS_PUT_UINT16_BE(p - p_extensions_len - 2, p_extensions_len, 0); + + *out_len = p - buf; + + MBEDTLS_SSL_PRINT_EXTS( + 3, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, ssl->handshake->sent_extensions); + + return 0; +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_certificate_request(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate request")); + + MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_certificate_request_coordinate(ssl)); + + if (ret == SSL_CERTIFICATE_REQUEST_SEND_REQUEST) { + unsigned char *buf; + size_t buf_len, msg_len; + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(ssl, + MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, + &buf, &buf_len)); + + MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_certificate_request_body( + ssl, buf, buf + buf_len, &msg_len)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( + ssl, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, buf, msg_len)); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg( + ssl, buf_len, msg_len)); + } else if (ret == SSL_CERTIFICATE_REQUEST_SKIP) { + MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate request")); + ret = 0; + } else { + MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + goto cleanup; + } + + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_CERTIFICATE); +cleanup: + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= write certificate request")); + return ret; +} + +/* + * Handler for MBEDTLS_SSL_SERVER_CERTIFICATE + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_server_certificate(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + if ((ssl_tls13_pick_key_cert(ssl) != 0) || + mbedtls_ssl_own_cert(ssl) == NULL) { + MBEDTLS_SSL_DEBUG_MSG(2, ("No certificate available.")); + MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, + MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + ret = mbedtls_ssl_tls13_write_certificate(ssl); + if (ret != 0) { + return ret; + } + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CERTIFICATE_VERIFY); + return 0; +} + +/* + * Handler for MBEDTLS_SSL_CERTIFICATE_VERIFY + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_certificate_verify(mbedtls_ssl_context *ssl) +{ + int ret = mbedtls_ssl_tls13_write_certificate_verify(ssl); + if (ret != 0) { + return ret; + } + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_FINISHED); + return 0; +} +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ + +/* + * Handler for MBEDTLS_SSL_SERVER_FINISHED + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_server_finished(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ret = mbedtls_ssl_tls13_write_finished_message(ssl); + if (ret != 0) { + return ret; + } + + ret = mbedtls_ssl_tls13_compute_application_transform(ssl); + if (ret != 0) { + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, + MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); + return ret; + } + + MBEDTLS_SSL_DEBUG_MSG(1, ("Switch to handshake keys for inbound traffic")); + mbedtls_ssl_set_inbound_transform(ssl, ssl->handshake->transform_handshake); + + if (ssl->handshake->certificate_request_sent) { + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE); + } else { + MBEDTLS_SSL_DEBUG_MSG(2, ("skip parse certificate")); + MBEDTLS_SSL_DEBUG_MSG(2, ("skip parse certificate verify")); + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_FINISHED); + } + + return 0; +} + +/* + * Handler for MBEDTLS_SSL_CLIENT_FINISHED + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_process_client_finished(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ret = mbedtls_ssl_tls13_process_finished_message(ssl); + if (ret != 0) { + return ret; + } + + ret = mbedtls_ssl_tls13_compute_resumption_master_secret(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, + "mbedtls_ssl_tls13_compute_resumption_master_secret", ret); + } + + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_WRAPUP); + return 0; +} + +/* + * Handler for MBEDTLS_SSL_HANDSHAKE_WRAPUP + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_handshake_wrapup(mbedtls_ssl_context *ssl) +{ + MBEDTLS_SSL_DEBUG_MSG(2, ("handshake: done")); + + mbedtls_ssl_tls13_handshake_wrapup(ssl); + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && \ + defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) +/* TODO: Remove the check of SOME_PSK_ENABLED since SESSION_TICKETS requires + * SOME_PSK_ENABLED to be enabled. Here is just to make CI happy. It is + * expected to be resolved with issue#6395. + */ + /* Sent NewSessionTicket message only when client supports PSK */ + if (mbedtls_ssl_tls13_some_psk_enabled(ssl)) { + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET); + } else +#endif + { + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_OVER); + } + return 0; +} + +/* + * Handler for MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET + */ +#define SSL_NEW_SESSION_TICKET_SKIP 0 +#define SSL_NEW_SESSION_TICKET_WRITE 1 +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_new_session_ticket_coordinate(mbedtls_ssl_context *ssl) +{ + /* Check whether the use of session tickets is enabled */ + if (ssl->conf->f_ticket_write == NULL) { + MBEDTLS_SSL_DEBUG_MSG(2, ("NewSessionTicket: disabled," + " callback is not set")); + return SSL_NEW_SESSION_TICKET_SKIP; + } + if (ssl->conf->new_session_tickets_count == 0) { + MBEDTLS_SSL_DEBUG_MSG(2, ("NewSessionTicket: disabled," + " configured count is zero")); + return SSL_NEW_SESSION_TICKET_SKIP; + } + + if (ssl->handshake->new_session_tickets_count == 0) { + MBEDTLS_SSL_DEBUG_MSG(2, ("NewSessionTicket: all tickets have " + "been sent.")); + return SSL_NEW_SESSION_TICKET_SKIP; + } + + return SSL_NEW_SESSION_TICKET_WRITE; +} + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_prepare_new_session_ticket(mbedtls_ssl_context *ssl, + unsigned char *ticket_nonce, + size_t ticket_nonce_size) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_session *session = ssl->session; + mbedtls_ssl_ciphersuite_t *ciphersuite_info; + psa_algorithm_t psa_hash_alg; + int hash_length; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> prepare NewSessionTicket msg")); + +#if defined(MBEDTLS_HAVE_TIME) + session->start = mbedtls_time(NULL); +#endif + + /* Set ticket_flags depends on the advertised psk key exchange mode */ + mbedtls_ssl_session_clear_ticket_flags( + session, MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK); +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) + mbedtls_ssl_session_set_ticket_flags( + session, ssl->handshake->tls13_kex_modes); +#endif + MBEDTLS_SSL_PRINT_TICKET_FLAGS(4, session->ticket_flags); + + /* Generate ticket_age_add */ + if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, + (unsigned char *) &session->ticket_age_add, + sizeof(session->ticket_age_add)) != 0)) { + MBEDTLS_SSL_DEBUG_RET(1, "generate_ticket_age_add", ret); + return ret; + } + MBEDTLS_SSL_DEBUG_MSG(3, ("ticket_age_add: %u", + (unsigned int) session->ticket_age_add)); + + /* Generate ticket_nonce */ + ret = ssl->conf->f_rng(ssl->conf->p_rng, ticket_nonce, ticket_nonce_size); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "generate_ticket_nonce", ret); + return ret; + } + MBEDTLS_SSL_DEBUG_BUF(3, "ticket_nonce:", + ticket_nonce, ticket_nonce_size); + + ciphersuite_info = + (mbedtls_ssl_ciphersuite_t *) ssl->handshake->ciphersuite_info; + psa_hash_alg = mbedtls_psa_translate_md(ciphersuite_info->mac); + hash_length = PSA_HASH_LENGTH(psa_hash_alg); + if (hash_length == -1 || + (size_t) hash_length > sizeof(session->resumption_key)) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + /* In this code the psk key length equals the length of the hash */ + session->resumption_key_len = hash_length; + session->ciphersuite = ciphersuite_info->id; + + /* Compute resumption key + * + * HKDF-Expand-Label( resumption_master_secret, + * "resumption", ticket_nonce, Hash.length ) + */ + ret = mbedtls_ssl_tls13_hkdf_expand_label( + psa_hash_alg, + session->app_secrets.resumption_master_secret, + hash_length, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(resumption), + ticket_nonce, + ticket_nonce_size, + session->resumption_key, + hash_length); + + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(2, + "Creating the ticket-resumed PSK failed", + ret); + return ret; + } + MBEDTLS_SSL_DEBUG_BUF(3, "Ticket-resumed PSK", + session->resumption_key, + session->resumption_key_len); + + MBEDTLS_SSL_DEBUG_BUF(3, "resumption_master_secret", + session->app_secrets.resumption_master_secret, + hash_length); + + return 0; +} + +/* This function creates a NewSessionTicket message in the following format: + * + * struct { + * uint32 ticket_lifetime; + * uint32 ticket_age_add; + * opaque ticket_nonce<0..255>; + * opaque ticket<1..2^16-1>; + * Extension extensions<0..2^16-2>; + * } NewSessionTicket; + * + * The ticket inside the NewSessionTicket message is an encrypted container + * carrying the necessary information so that the server is later able to + * re-start the communication. + * + * The following fields are placed inside the ticket by the + * f_ticket_write() function: + * + * - creation time (start) + * - flags (flags) + * - age add (ticket_age_add) + * - key (key) + * - key length (key_len) + * - ciphersuite (ciphersuite) + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_tls13_write_new_session_ticket_body(mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len, + unsigned char *ticket_nonce, + size_t ticket_nonce_size) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = buf; + mbedtls_ssl_session *session = ssl->session; + size_t ticket_len; + uint32_t ticket_lifetime; + + *out_len = 0; + MBEDTLS_SSL_DEBUG_MSG(2, ("=> write NewSessionTicket msg")); + + /* + * ticket_lifetime 4 bytes + * ticket_age_add 4 bytes + * ticket_nonce 1 + ticket_nonce_size bytes + * ticket >=2 bytes + */ + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4 + 4 + 1 + ticket_nonce_size + 2); + + /* Generate ticket and ticket_lifetime */ + ret = ssl->conf->f_ticket_write(ssl->conf->p_ticket, + session, + p + 9 + ticket_nonce_size + 2, + end, + &ticket_len, + &ticket_lifetime); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "write_ticket", ret); + return ret; + } + /* RFC 8446 4.6.1 + * ticket_lifetime: Indicates the lifetime in seconds as a 32-bit + * unsigned integer in network byte order from the time of ticket + * issuance. Servers MUST NOT use any value greater than + * 604800 seconds (7 days). The value of zero indicates that the + * ticket should be discarded immediately. Clients MUST NOT cache + * tickets for longer than 7 days, regardless of the ticket_lifetime, + * and MAY delete tickets earlier based on local policy. A server + * MAY treat a ticket as valid for a shorter period of time than what + * is stated in the ticket_lifetime. + */ + if (ticket_lifetime > 604800) { + ticket_lifetime = 604800; + } + MBEDTLS_PUT_UINT32_BE(ticket_lifetime, p, 0); + MBEDTLS_SSL_DEBUG_MSG(3, ("ticket_lifetime: %u", + (unsigned int) ticket_lifetime)); + + /* Write ticket_age_add */ + MBEDTLS_PUT_UINT32_BE(session->ticket_age_add, p, 4); + MBEDTLS_SSL_DEBUG_MSG(3, ("ticket_age_add: %u", + (unsigned int) session->ticket_age_add)); + + /* Write ticket_nonce */ + p[8] = (unsigned char) ticket_nonce_size; + if (ticket_nonce_size > 0) { + memcpy(p + 9, ticket_nonce, ticket_nonce_size); + } + p += 9 + ticket_nonce_size; + + /* Write ticket */ + MBEDTLS_PUT_UINT16_BE(ticket_len, p, 0); + p += 2; + MBEDTLS_SSL_DEBUG_BUF(4, "ticket", p, ticket_len); + p += ticket_len; + + /* Ticket Extensions + * + * Note: We currently don't have any extensions. + * Set length to zero. + */ + ssl->handshake->sent_extensions = MBEDTLS_SSL_EXT_MASK_NONE; + + MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); + MBEDTLS_PUT_UINT16_BE(0, p, 0); + p += 2; + + *out_len = p - buf; + MBEDTLS_SSL_DEBUG_BUF(4, "ticket", buf, *out_len); + MBEDTLS_SSL_DEBUG_MSG(2, ("<= write new session ticket")); + + MBEDTLS_SSL_PRINT_EXTS( + 3, MBEDTLS_SSL_HS_NEW_SESSION_TICKET, ssl->handshake->sent_extensions); + + return 0; +} + +/* + * Handler for MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET + */ +static int ssl_tls13_write_new_session_ticket(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_write_new_session_ticket_coordinate(ssl)); + + if (ret == SSL_NEW_SESSION_TICKET_WRITE) { + unsigned char ticket_nonce[MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH]; + unsigned char *buf; + size_t buf_len, msg_len; + + MBEDTLS_SSL_PROC_CHK(ssl_tls13_prepare_new_session_ticket( + ssl, ticket_nonce, sizeof(ticket_nonce))); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(ssl, + MBEDTLS_SSL_HS_NEW_SESSION_TICKET, + &buf, &buf_len)); + + MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_new_session_ticket_body( + ssl, buf, buf + buf_len, &msg_len, + ticket_nonce, sizeof(ticket_nonce))); + + MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg( + ssl, buf_len, msg_len)); + + /* Limit session tickets count to one when resumption connection. + * + * See document of mbedtls_ssl_conf_new_session_tickets. + */ + if (ssl->handshake->resume == 1) { + ssl->handshake->new_session_tickets_count = 0; + } else { + ssl->handshake->new_session_tickets_count--; + } + + mbedtls_ssl_handshake_set_state( + ssl, MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH); + } else { + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_OVER); + } + +cleanup: + + return ret; +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +/* + * TLS 1.3 State Machine -- server side + */ +int mbedtls_ssl_tls13_handshake_server_step(mbedtls_ssl_context *ssl) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if (ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER || ssl->handshake == NULL) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + MBEDTLS_SSL_DEBUG_MSG(2, ("tls13 server state: %s(%d)", + mbedtls_ssl_states_str(ssl->state), + ssl->state)); + + switch (ssl->state) { + /* start state */ + case MBEDTLS_SSL_HELLO_REQUEST: + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO); + ret = 0; + break; + + case MBEDTLS_SSL_CLIENT_HELLO: + ret = ssl_tls13_process_client_hello(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_process_client_hello", ret); + } + break; + + case MBEDTLS_SSL_HELLO_RETRY_REQUEST: + ret = ssl_tls13_write_hello_retry_request(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_write_hello_retry_request", ret); + return ret; + } + break; + + case MBEDTLS_SSL_SERVER_HELLO: + ret = ssl_tls13_write_server_hello(ssl); + break; + + case MBEDTLS_SSL_ENCRYPTED_EXTENSIONS: + ret = ssl_tls13_write_encrypted_extensions(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_write_encrypted_extensions", ret); + return ret; + } + break; + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) + case MBEDTLS_SSL_CERTIFICATE_REQUEST: + ret = ssl_tls13_write_certificate_request(ssl); + break; + + case MBEDTLS_SSL_SERVER_CERTIFICATE: + ret = ssl_tls13_write_server_certificate(ssl); + break; + + case MBEDTLS_SSL_CERTIFICATE_VERIFY: + ret = ssl_tls13_write_certificate_verify(ssl); + break; +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ + + /* + * Injection of dummy-CCS's for middlebox compatibility + */ +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + case MBEDTLS_SSL_SERVER_CCS_AFTER_HELLO_RETRY_REQUEST: + ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl); + if (ret == 0) { + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO); + } + break; + + case MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO: + ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl); + if (ret == 0) { + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS); + } + break; +#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ + + case MBEDTLS_SSL_SERVER_FINISHED: + ret = ssl_tls13_write_server_finished(ssl); + break; + + case MBEDTLS_SSL_CLIENT_FINISHED: + ret = ssl_tls13_process_client_finished(ssl); + break; + + case MBEDTLS_SSL_HANDSHAKE_WRAPUP: + ret = ssl_tls13_handshake_wrapup(ssl); + break; + +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) + case MBEDTLS_SSL_CLIENT_CERTIFICATE: + ret = mbedtls_ssl_tls13_process_certificate(ssl); + if (ret == 0) { + if (ssl->session_negotiate->peer_cert != NULL) { + mbedtls_ssl_handshake_set_state( + ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY); + } else { + MBEDTLS_SSL_DEBUG_MSG(2, ("skip parse certificate verify")); + mbedtls_ssl_handshake_set_state( + ssl, MBEDTLS_SSL_CLIENT_FINISHED); + } + } + break; + + case MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY: + ret = mbedtls_ssl_tls13_process_certificate_verify(ssl); + if (ret == 0) { + mbedtls_ssl_handshake_set_state( + ssl, MBEDTLS_SSL_CLIENT_FINISHED); + } + break; +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + case MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET: + ret = ssl_tls13_write_new_session_ticket(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, + "ssl_tls13_write_new_session_ticket ", + ret); + } + break; + case MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH: + /* This state is necessary to do the flush of the New Session + * Ticket message written in MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET + * as part of ssl_prepare_handshake_step. + */ + ret = 0; + + if (ssl->handshake->new_session_tickets_count == 0) { + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_OVER); + } else { + mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET); + } + break; + +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + + default: + MBEDTLS_SSL_DEBUG_MSG(1, ("invalid state %d", ssl->state)); + return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + } + + return ret; +} + +#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_PROTO_TLS1_3 */ 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..130c696 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/threading.c @@ -0,0 +1,193 @@ +/* + * 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 + * mbedtls_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..6852033 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/timing.c @@ -0,0 +1,166 @@ +/* + * 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_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 mbedtls_config.h" +#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 */ + +/** + * \brief Return the elapsed time in milliseconds + * + * \warning May change without notice + * + * \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. + */ +#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; + } +} + +#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; + } +} + +#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; +} + +/* + * Get the final delay. + */ +uint32_t mbedtls_timing_get_final_delay( + const mbedtls_timing_delay_context *data) +{ + return data->fin_ms; +} +#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..4f78c9c --- /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..0a6ff22 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/version_features.c @@ -0,0 +1,808 @@ +/* + * 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_SETBUF_ALT) + "MBEDTLS_PLATFORM_SETBUF_ALT", +#endif /* MBEDTLS_PLATFORM_SETBUF_ALT */ +#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_TIMING_ALT) + "MBEDTLS_TIMING_ALT", +#endif /* MBEDTLS_TIMING_ALT */ +#if defined(MBEDTLS_AES_ALT) + "MBEDTLS_AES_ALT", +#endif /* MBEDTLS_AES_ALT */ +#if defined(MBEDTLS_ARIA_ALT) + "MBEDTLS_ARIA_ALT", +#endif /* MBEDTLS_ARIA_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_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_ECP_ALT) + "MBEDTLS_ECP_ALT", +#endif /* MBEDTLS_ECP_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_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_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_RESTARTABLE) + "MBEDTLS_ECP_RESTARTABLE", +#endif /* MBEDTLS_ECP_RESTARTABLE */ +#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_SSL_ALL_ALERT_MESSAGES) + "MBEDTLS_SSL_ALL_ALERT_MESSAGES", +#endif /* MBEDTLS_SSL_ALL_ALERT_MESSAGES */ +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + "MBEDTLS_SSL_DTLS_CONNECTION_ID", +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT) + "MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT", +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT */ +#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_KEEP_PEER_CERTIFICATE) + "MBEDTLS_SSL_KEEP_PEER_CERTIFICATE", +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + "MBEDTLS_SSL_RENEGOTIATION", +#endif /* MBEDTLS_SSL_RENEGOTIATION */ +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + "MBEDTLS_SSL_MAX_FRAGMENT_LENGTH", +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ +#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) + "MBEDTLS_SSL_RECORD_SIZE_LIMIT", +#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ +#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) + "MBEDTLS_SSL_PROTO_TLS1_3", +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + "MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE", +#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED) + "MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED", +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED */ +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) + "MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED", +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ +#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED) + "MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED", +#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED */ +#if defined(MBEDTLS_SSL_EARLY_DATA) + "MBEDTLS_SSL_EARLY_DATA", +#endif /* MBEDTLS_SSL_EARLY_DATA */ +#if defined(MBEDTLS_SSL_MAX_EARLY_DATA_SIZE) + "MBEDTLS_SSL_MAX_EARLY_DATA_SIZE", +#endif /* MBEDTLS_SSL_MAX_EARLY_DATA_SIZE */ +#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_SESSION_TICKETS) + "MBEDTLS_SSL_SESSION_TICKETS", +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + "MBEDTLS_SSL_SERVER_NAME_INDICATION", +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ +#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_TRUSTED_CERTIFICATE_CALLBACK) + "MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK", +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ +#if defined(MBEDTLS_X509_REMOVE_INFO) + "MBEDTLS_X509_REMOVE_INFO", +#endif /* MBEDTLS_X509_REMOVE_INFO */ +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + "MBEDTLS_X509_RSASSA_PSS_SUPPORT", +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ +#if defined(MBEDTLS_AESNI_C) + "MBEDTLS_AESNI_C", +#endif /* MBEDTLS_AESNI_C */ +#if defined(MBEDTLS_AESCE_C) + "MBEDTLS_AESCE_C", +#endif /* MBEDTLS_AESCE_C */ +#if defined(MBEDTLS_AES_C) + "MBEDTLS_AES_C", +#endif /* MBEDTLS_AES_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_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_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_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_LMS_C) + "MBEDTLS_LMS_C", +#endif /* MBEDTLS_LMS_C */ +#if defined(MBEDTLS_LMS_PRIVATE) + "MBEDTLS_LMS_PRIVATE", +#endif /* MBEDTLS_LMS_PRIVATE */ +#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_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_PKCS7_C) + "MBEDTLS_PKCS7_C", +#endif /* MBEDTLS_PKCS7_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_SHA224_C) + "MBEDTLS_SHA224_C", +#endif /* MBEDTLS_SHA224_C */ +#if defined(MBEDTLS_SHA256_C) + "MBEDTLS_SHA256_C", +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT) + "MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT", +#endif /* MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT */ +#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY) + "MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY", +#endif /* MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY */ +#if defined(MBEDTLS_SHA384_C) + "MBEDTLS_SHA384_C", +#endif /* MBEDTLS_SHA384_C */ +#if defined(MBEDTLS_SHA512_C) + "MBEDTLS_SHA512_C", +#endif /* MBEDTLS_SHA512_C */ +#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) + "MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT", +#endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT */ +#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) + "MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY", +#endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */ +#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 */ +#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..fc13b92 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/x509.c @@ -0,0 +1,1641 @@ +/* + * 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 + +#include "mbedtls/platform.h" + +#if defined(MBEDTLS_HAVE_TIME) +#include "mbedtls/platform_time.h" +#endif +#if defined(MBEDTLS_HAVE_TIME_DATE) +#include "mbedtls/platform_util.h" +#include +#endif + +#include "mbedtls/legacy_or_psa.h" + +#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; +} + +/* + * Convert md type to string + */ +static inline const char *md_type_to_string(mbedtls_md_type_t md_alg) +{ + switch (md_alg) { +#if defined(MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA) + case MBEDTLS_MD_MD5: + return "MD5"; +#endif +#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA) + case MBEDTLS_MD_SHA1: + return "SHA1"; +#endif +#if defined(MBEDTLS_HAS_ALG_SHA_224_VIA_MD_OR_PSA) + case MBEDTLS_MD_SHA224: + return "SHA224"; +#endif +#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA) + case MBEDTLS_MD_SHA256: + return "SHA256"; +#endif +#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA) + case MBEDTLS_MD_SHA384: + return "SHA384"; +#endif +#if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA) + case MBEDTLS_MD_SHA512: + return "SHA512"; +#endif +#if defined(MBEDTLS_HAS_ALG_RIPEMD160_VIA_MD_OR_PSA) + case MBEDTLS_MD_RIPEMD160: + return "RIPEMD160"; +#endif + case MBEDTLS_MD_NONE: + return NULL; + default: + return NULL; + } +} + +#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. Enforce 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(). + * + * On success, this function may allocate a linked list starting at cur->next + * that must later be free'd by the caller using mbedtls_free(). In error + * cases, this function frees all allocated memory internally and the caller + * has no freeing responsibilities. + */ +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; + mbedtls_x509_name *head = cur; + + /* 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) { + ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret); + goto error; + } + + end_set = *p + set_len; + + while (1) { + if ((ret = x509_get_attr_type_value(p, end_set, cur)) != 0) { + goto error; + } + + 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) { + ret = MBEDTLS_ERR_X509_ALLOC_FAILED; + goto error; + } + + 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) { + ret = MBEDTLS_ERR_X509_ALLOC_FAILED; + goto error; + } + + cur = cur->next; + } + +error: + /* Skip the first element as we did not allocate it */ + mbedtls_asn1_free_named_data_list_shallow(head->next); + head->next = NULL; + + return ret; +} + +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); +} + +#if !defined(MBEDTLS_X509_REMOVE_INFO) +/* + * 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; + + pss_opts = (const mbedtls_pk_rsassa_pss_options *) sig_opts; + + const char *name = md_type_to_string(md_alg); + const char *mgf_name = md_type_to_string(pss_opts->mgf1_hash_id); + + ret = mbedtls_snprintf(p, n, " (%s, MGF1-%s, 0x%02X)", + name ? name : "???", + mgf_name ? mgf_name : "???", + (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); +} +#endif /* MBEDTLS_X509_REMOVE_INFO */ + +/* + * 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 */ + +/* Common functions for parsing CRT and CSR. */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) || defined(MBEDTLS_X509_CSR_PARSE_C) +/* + * 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; + } + + 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 (end != p + len) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + + 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); + } + + 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; + + 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) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + 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 } + * + * We list all types, but use the following GeneralName types from RFC 5280: + * "dnsName", "uniformResourceIdentifier" and "hardware_module_name" + * of type "otherName", as defined in RFC 4108. + */ +int mbedtls_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_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; + mbedtls_x509_buf tmp_san_buf; + memset(&dummy_san_buf, 0, sizeof(dummy_san_buf)); + + tmp_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); + } + + tmp_san_buf.p = *p; + tmp_san_buf.len = tag_len; + + if ((tmp_san_buf.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(&tmp_san_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_asn1_sequence_free(subject_alt_name->next); + 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; + } + + cur->buf = tmp_san_buf; + *p += tmp_san_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; +} + +int mbedtls_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); + } + + /* A bitstring with no flags set is still technically valid, as it will mean + that the certificate has no designated purpose at the time of creation. */ + if (bs.len == 0) { + *ns_cert_type = 0; + return 0; + } + + 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; +} + +int mbedtls_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); + } + + /* A bitstring with no flags set is still technically valid, as it will mean + that the certificate has no designated purpose at the time of creation. */ + if (bs.len == 0) { + *key_usage = 0; + return 0; + } + + /* 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; +} + +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; + /* + * uniformResourceIdentifier + */ + case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER): + { + memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name)); + san->type = MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER; + + memcpy(&san->san.unstructured_name, + san_buf, sizeof(*san_buf)); + + } + 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; + + /* + * RFC822 Name + */ + case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_RFC822_NAME): + { + memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name)); + san->type = MBEDTLS_X509_SAN_RFC822_NAME; + memcpy(&san->san.unstructured_name, san_buf, sizeof(*san_buf)); + } + break; + + /* + * Type not supported + */ + default: + return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; + } + return 0; +} + +#if !defined(MBEDTLS_X509_REMOVE_INFO) +int mbedtls_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 i; + 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; + + for (i = 0; i < other_name->value.hardware_module_name.val.len; i++) { + ret = mbedtls_snprintf(p, + n, + "%02X", + other_name->value.hardware_module_name.val.p[i]); + MBEDTLS_X509_SAFE_SNPRINTF; + } + }/* MBEDTLS_OID_ON_HW_MODULE_NAME */ + } + break; + /* + * uniformResourceIdentifier + */ + case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER: + { + ret = mbedtls_snprintf(p, n, "\n%s uniformResourceIdentifier : ", 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; + /* + * dNSName + * RFC822 Name + */ + case MBEDTLS_X509_SAN_DNS_NAME: + case MBEDTLS_X509_SAN_RFC822_NAME: + { + const char *dns_name = "dNSName"; + const char *rfc822_name = "rfc822Name"; + + ret = mbedtls_snprintf(p, n, + "\n%s %s : ", + prefix, + san.type == + MBEDTLS_X509_SAN_DNS_NAME ? dns_name : rfc822_name); + 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; +} + +#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); + +int mbedtls_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); + +int mbedtls_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; +} +#endif /* MBEDTLS_X509_REMOVE_INFO */ +#endif /* MBEDTLS_X509_CRT_PARSE_C || MBEDTLS_X509_CSR_PARSE_C */ +#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..50db956 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/x509_create.c @@ -0,0 +1,368 @@ +/* + * 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..f644203 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/x509_crl.c @@ -0,0 +1,727 @@ +/* + * X.509 Certificate 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 + +#include "mbedtls/platform.h" + +#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 */ + +#if !defined(MBEDTLS_X509_REMOVE_INFO) +/* + * 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); +} +#endif /* MBEDTLS_X509_REMOVE_INFO */ + +/* + * 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_crl_entry *entry_cur; + mbedtls_x509_crl_entry *entry_prv; + + while (crl_cur != NULL) { +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + mbedtls_free(crl_cur->sig_opts); +#endif + + mbedtls_asn1_free_named_data_list_shallow(crl_cur->issuer.next); + + 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_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); + } + } +} + +#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..cf62532 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/x509_crt.c @@ -0,0 +1,2889 @@ +/* + * 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 /* MBEDTLS_USE_PSA_CRYPTO */ +#include "hash_info.h" + +#include "mbedtls/platform.h" + +#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 +#if defined(__MBED__) +#include +#else +#include +#endif /* __MBED__ */ +#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 = +{ + /* Hashes from SHA-256 and above. Note that this selection + * should be aligned with ssl_preset_default_hashes in ssl_tls.c. */ + 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. Note that this selection + * should be aligned with ssl_preset_default_curves in ssl_tls.c. */ + 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) | + 0, +#else + 0, +#endif + 2048, +}; + +/* Next-generation profile. Currently identical to the default, but may + * be tightened at any time. */ +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, +}; + +/* + * Empty / all-forbidden profile + */ +const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_none = +{ + 0, + 0, + 0, + (uint32_t) -1, +}; + +/* + * 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; +} + +/* + * 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; +} + +/* + * 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. + */ + 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 (is_critical) { + /* Data is marked as critical: fail */ + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); + } + 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 = mbedtls_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 = mbedtls_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 = mbedtls_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 (is_critical) { + return ret; + } else + /* + * 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 (is_critical) { + return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; + } else { + *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 (crt->version == 3) { + 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, + -1, + p, (int) len, + 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) { + if (errno == ENOENT) { + /* Broken symbolic link - ignore this entry. + stat(2) will return this error for either (a) a dangling + symlink or (b) a missing file. + Given that we have just obtained the filename from readdir, + assume that it does exist and therefore treat this as a + dangling symlink. */ + continue; + } else { + /* Some other file error; report the error. */ + 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 */ + +#if !defined(MBEDTLS_X509_REMOVE_INFO) +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 = mbedtls_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 = mbedtls_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 = mbedtls_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; +}; + +#define X509_CRT_ERROR_INFO(err, err_str, info) { err, info }, +static const struct x509_crt_verify_string x509_crt_verify_strings[] = { + MBEDTLS_X509_CRT_ERROR_INFO_LIST + { 0, NULL } +}; +#undef X509_CRT_ERROR_INFO + +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); +} +#endif /* MBEDTLS_X509_REMOVE_INFO */ + +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; +} + +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; +} + +#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_HASH_MAX_SIZE]; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_algorithm_t psa_algorithm; +#else + const mbedtls_md_info_t *md_info; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + size_t hash_length; + + 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 (mbedtls_x509_crt_check_key_usage(ca, + MBEDTLS_X509_KU_CRL_SIGN) != 0) { + flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; + break; + } + + /* + * 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; + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_algorithm = mbedtls_hash_info_psa_from_md(crl_list->sig_md); + if (psa_hash_compute(psa_algorithm, + crl_list->tbs.p, + crl_list->tbs.len, + hash, + sizeof(hash), + &hash_length) != PSA_SUCCESS) { + /* Note: this can't happen except after an internal error */ + flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; + break; + } +#else + md_info = mbedtls_md_info_from_type(crl_list->sig_md); + hash_length = mbedtls_md_get_size(md_info); + 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; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + 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, hash_length, + 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) +{ + size_t hash_len; + unsigned char hash[MBEDTLS_HASH_MAX_SIZE]; +#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_algorithm_t hash_alg = mbedtls_hash_info_psa_from_md(child->sig_md); + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + status = psa_hash_compute(hash_alg, + child->tbs.p, + child->tbs.len, + hash, + sizeof(hash), + &hash_len); + if (status != PSA_SUCCESS) { + return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + } + +#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 (need_ca_bit && + mbedtls_x509_crt_check_key_usage(parent, MBEDTLS_X509_KU_KEY_CERT_SIGN) != 0) { + return -1; + } + + 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; + + while (cert_cur != NULL) { + mbedtls_pk_free(&cert_cur->pk); + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + mbedtls_free(cert_cur->sig_opts); +#endif + + mbedtls_asn1_free_named_data_list_shallow(cert_cur->issuer.next); + mbedtls_asn1_free_named_data_list_shallow(cert_cur->subject.next); + mbedtls_asn1_sequence_free(cert_cur->ext_key_usage.next); + mbedtls_asn1_sequence_free(cert_cur->subject_alt_names.next); + mbedtls_asn1_sequence_free(cert_cur->certificate_policies.next); + + 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_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); + } + } +} + +#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..cd117cb --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/x509_csr.c @@ -0,0 +1,588 @@ +/* + * 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 + +#include "mbedtls/platform.h" + +#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 CSR extension requests in DER format + */ +static int x509_csr_parse_extensions(mbedtls_x509_csr *csr, + unsigned char **p, const unsigned char *end) +{ + int ret; + size_t len; + unsigned char *end_ext_data; + while (*p < end) { + mbedtls_x509_buf extn_oid = { 0, 0, NULL }; + int ext_type = 0; + + /* Read 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 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; + + /* 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); + } + + if (*p + len != end_ext_data) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + + /* + * Detect supported extensions and skip unsupported extensions + */ + ret = mbedtls_oid_get_x509_ext_type(&extn_oid, &ext_type); + + if (ret == 0) { + /* Forbid repeated extensions */ + if ((csr->ext_types & ext_type) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_INVALID_DATA); + } + + csr->ext_types |= ext_type; + + switch (ext_type) { + case MBEDTLS_X509_EXT_KEY_USAGE: + /* Parse key usage */ + if ((ret = mbedtls_x509_get_key_usage(p, end_ext_data, + &csr->key_usage)) != 0) { + return ret; + } + break; + + case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME: + /* Parse subject alt name */ + if ((ret = mbedtls_x509_get_subject_alt_name(p, end_ext_data, + &csr->subject_alt_names)) != 0) { + return ret; + } + break; + + case MBEDTLS_X509_EXT_NS_CERT_TYPE: + /* Parse netscape certificate type */ + if ((ret = mbedtls_x509_get_ns_cert_type(p, end_ext_data, + &csr->ns_cert_type)) != 0) { + return ret; + } + break; + default: + break; + } + } + *p = end_ext_data; + } + + if (*p != end) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + + return 0; +} + +/* + * Parse CSR attributes in DER format + */ +static int x509_csr_parse_attributes(mbedtls_x509_csr *csr, + const unsigned char *start, const unsigned char *end) +{ + int ret; + size_t len; + unsigned char *end_attr_data; + unsigned char **p = (unsigned char **) &start; + + while (*p < end) { + mbedtls_x509_buf attr_oid = { 0, 0, NULL }; + + 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_attr_data = *p + len; + + /* Get attribute ID */ + if ((ret = mbedtls_asn1_get_tag(p, end_attr_data, &attr_oid.len, + MBEDTLS_ASN1_OID)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); + } + + attr_oid.tag = MBEDTLS_ASN1_OID; + attr_oid.p = *p; + *p += attr_oid.len; + + /* Check that this is an extension-request attribute */ + if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS9_CSR_EXT_REQ, &attr_oid) == 0) { + if ((ret = mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)) != 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 = x509_csr_parse_extensions(csr, p, *p + len)) != 0) { + return ret; + } + + if (*p != end_attr_data) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + } + + *p = end_attr_data; + } + + if (*p != end) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + + 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); + } + + if ((ret = x509_csr_parse_attributes(csr, p, p + len)) != 0) { + mbedtls_x509_csr_free(csr); + return 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 */ + +#if !defined(MBEDTLS_X509_REMOVE_INFO) +#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; + + /* + * Optional extensions + */ + + if (csr->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) { + ret = mbedtls_snprintf(p, n, "\n%ssubject alt name :", prefix); + MBEDTLS_X509_SAFE_SNPRINTF; + + if ((ret = mbedtls_x509_info_subject_alt_name(&p, &n, + &csr->subject_alt_names, + prefix)) != 0) { + return ret; + } + } + + if (csr->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE) { + ret = mbedtls_snprintf(p, n, "\n%scert. type : ", prefix); + MBEDTLS_X509_SAFE_SNPRINTF; + + if ((ret = mbedtls_x509_info_cert_type(&p, &n, csr->ns_cert_type)) != 0) { + return ret; + } + } + + if (csr->ext_types & MBEDTLS_X509_EXT_KEY_USAGE) { + ret = mbedtls_snprintf(p, n, "\n%skey usage : ", prefix); + MBEDTLS_X509_SAFE_SNPRINTF; + + if ((ret = mbedtls_x509_info_key_usage(&p, &n, csr->key_usage)) != 0) { + return ret; + } + } + + if (csr->ext_types != 0) { + ret = mbedtls_snprintf(p, n, "\n"); + MBEDTLS_X509_SAFE_SNPRINTF; + } + + return (int) (size - n); +} +#endif /* MBEDTLS_X509_REMOVE_INFO */ + +/* + * 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) +{ + if (csr == NULL) { + return; + } + + mbedtls_pk_free(&csr->pk); + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + mbedtls_free(csr->sig_opts); +#endif + + mbedtls_asn1_free_named_data_list_shallow(csr->subject.next); + mbedtls_asn1_sequence_free(csr->subject_alt_names.next); + + 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..f481155 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/x509write_crt.c @@ -0,0 +1,674 @@ +/* + * 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/md.h" + +#include + +#if defined(MBEDTLS_PEM_WRITE_C) +#include "mbedtls/pem.h" +#endif /* MBEDTLS_PEM_WRITE_C */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#include "mbedtls/psa_util.h" +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#include "hash_info.h" +#include "mbedtls/legacy_or_psa.h" + +void mbedtls_x509write_crt_init(mbedtls_x509write_cert *ctx) +{ + memset(ctx, 0, sizeof(mbedtls_x509write_cert)); + + ctx->version = MBEDTLS_X509_CRT_VERSION_3; +} + +void mbedtls_x509write_crt_free(mbedtls_x509write_cert *ctx) +{ + 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); +} + +#if defined(MBEDTLS_BIGNUM_C) && !defined(MBEDTLS_DEPRECATED_REMOVED) +int mbedtls_x509write_crt_set_serial(mbedtls_x509write_cert *ctx, + const mbedtls_mpi *serial) +{ + int ret; + size_t tmp_len; + + /* Ensure that the MPI value fits into the buffer */ + tmp_len = mbedtls_mpi_size(serial); + if (tmp_len > MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN) { + return MBEDTLS_ERR_X509_BAD_INPUT_DATA; + } + + ctx->serial_len = tmp_len; + + ret = mbedtls_mpi_write_binary(serial, ctx->serial, tmp_len); + if (ret < 0) { + return ret; + } + + return 0; +} +#endif // MBEDTLS_BIGNUM_C && !MBEDTLS_DEPRECATED_REMOVED + +int mbedtls_x509write_crt_set_serial_raw(mbedtls_x509write_cert *ctx, + unsigned char *serial, size_t serial_len) +{ + if (serial_len > MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN) { + return MBEDTLS_ERR_X509_BAD_INPUT_DATA; + } + + ctx->serial_len = serial_len; + memcpy(ctx->serial, serial, serial_len); + + 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_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA) +static int mbedtls_x509write_crt_set_key_identifier(mbedtls_x509write_cert *ctx, + int is_ca, + unsigned char tag) +{ + 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; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t hash_length; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + memset(buf, 0, sizeof(buf)); + MBEDTLS_ASN1_CHK_ADD(len, + mbedtls_pk_write_pubkey(&c, + buf, + is_ca ? + ctx->issuer_key : + ctx->subject_key)); + + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + status = psa_hash_compute(PSA_ALG_SHA_1, + buf + sizeof(buf) - len, + len, + buf + sizeof(buf) - 20, + 20, + &hash_length); + if (status != PSA_SUCCESS) { + return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + } +#else + ret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), + buf + sizeof(buf) - len, len, + buf + sizeof(buf) - 20); + if (ret != 0) { + return ret; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + 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, tag)); + + if (is_ca) { // writes AuthorityKeyIdentifier 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_SEQUENCE)); + } + + if (is_ca) { + 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); + } else { + 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_subject_key_identifier(mbedtls_x509write_cert *ctx) +{ + return mbedtls_x509write_crt_set_key_identifier(ctx, + 0, + MBEDTLS_ASN1_OCTET_STRING); +} + +int mbedtls_x509write_crt_set_authority_key_identifier(mbedtls_x509write_cert *ctx) +{ + return mbedtls_x509write_crt_set_key_identifier(ctx, + 1, + (MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0)); +} +#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */ + +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_ext_key_usage(mbedtls_x509write_cert *ctx, + const mbedtls_asn1_sequence *exts) +{ + unsigned char buf[256]; + unsigned char *c = buf + sizeof(buf); + int ret; + size_t len = 0; + const mbedtls_asn1_sequence *last_ext = NULL; + const mbedtls_asn1_sequence *ext; + + memset(buf, 0, sizeof(buf)); + + /* We need at least one extension: SEQUENCE SIZE (1..MAX) OF KeyPurposeId */ + if (exts == NULL) { + return MBEDTLS_ERR_X509_BAD_INPUT_DATA; + } + + /* Iterate over exts backwards, so we write them out in the requested order */ + while (last_ext != exts) { + for (ext = exts; ext->next != last_ext; ext = ext->next) { + } + if (ext->buf.tag != MBEDTLS_ASN1_OID) { + return MBEDTLS_ERR_X509_BAD_INPUT_DATA; + } + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(&c, buf, ext->buf.p, ext->buf.len)); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, ext->buf.len)); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_OID)); + last_ext = ext; + } + + 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_EXTENDED_KEY_USAGE, + MBEDTLS_OID_SIZE(MBEDTLS_OID_EXTENDED_KEY_USAGE), + 1, c, len); +} + +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 sig[MBEDTLS_PK_SIGNATURE_MAX_SIZE]; + size_t hash_length = 0; + unsigned char hash[MBEDTLS_HASH_MAX_SIZE]; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_algorithm_t psa_algorithm; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + 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 + * + * Written data is: + * - "ctx->serial_len" bytes for the raw serial buffer + * - if MSb of "serial" is 1, then prepend an extra 0x00 byte + * - 1 byte for the length + * - 1 byte for the TAG + */ + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(&c, buf, + ctx->serial, ctx->serial_len)); + if (*c & 0x80) { + if (c - buf < 1) { + return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; + } + *(--c) = 0x0; + len++; + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, + ctx->serial_len + 1)); + } else { + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, + ctx->serial_len)); + } + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, + MBEDTLS_ASN1_INTEGER)); + + /* + * 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 defined(MBEDTLS_USE_PSA_CRYPTO) + psa_algorithm = mbedtls_hash_info_psa_from_md(ctx->md_alg); + + status = psa_hash_compute(psa_algorithm, + c, + len, + hash, + sizeof(hash), + &hash_length); + if (status != PSA_SUCCESS) { + return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + } +#else + if ((ret = mbedtls_md(mbedtls_md_info_from_type(ctx->md_alg), c, + len, hash)) != 0) { + return ret; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + + if ((ret = mbedtls_pk_sign(ctx->issuer_key, ctx->md_alg, + hash, hash_length, sig, sizeof(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..deb6617 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/x509write_csr.c @@ -0,0 +1,436 @@ +/* + * 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.h" +#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 /* MBEDTLS_USE_PSA_CRYPTO */ +#include "hash_info.h" + +#include +#include + +#if defined(MBEDTLS_PEM_WRITE_C) +#include "mbedtls/pem.h" +#endif + +#include "mbedtls/platform.h" + +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, + 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_csr_set_subject_alternative_name(mbedtls_x509write_csr *ctx, + const mbedtls_x509_san_list *san_list) +{ + int ret = 0; + const mbedtls_x509_san_list *cur; + unsigned char *buf; + unsigned char *p; + size_t len; + size_t buflen = 0; + + /* Determine the maximum size of the SubjectAltName list */ + for (cur = san_list; cur != NULL; cur = cur->next) { + /* Calculate size of the required buffer */ + switch (cur->node.type) { + case MBEDTLS_X509_SAN_DNS_NAME: + case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER: + case MBEDTLS_X509_SAN_IP_ADDRESS: + /* length of value for each name entry, + * maximum 4 bytes for the length field, + * 1 byte for the tag/type. + */ + buflen += cur->node.san.unstructured_name.len + 4 + 1; + break; + + default: + /* Not supported - skip. */ + break; + } + } + + /* Add the extra length field and tag */ + buflen += 4 + 1; + + /* Allocate buffer */ + buf = mbedtls_calloc(1, buflen); + if (buf == NULL) { + return MBEDTLS_ERR_ASN1_ALLOC_FAILED; + } + + mbedtls_platform_zeroize(buf, buflen); + p = buf + buflen; + + /* Write ASN.1-based structure */ + cur = san_list; + len = 0; + while (cur != NULL) { + switch (cur->node.type) { + case MBEDTLS_X509_SAN_DNS_NAME: + case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER: + case MBEDTLS_X509_SAN_IP_ADDRESS: + { + const unsigned char *unstructured_name = + (const unsigned char *) cur->node.san.unstructured_name.p; + size_t unstructured_name_len = cur->node.san.unstructured_name.len; + + MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, + mbedtls_asn1_write_raw_buffer( + &p, buf, + unstructured_name, unstructured_name_len)); + MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, mbedtls_asn1_write_len( + &p, buf, unstructured_name_len)); + MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, + mbedtls_asn1_write_tag( + &p, buf, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | cur->node.type)); + } + break; + default: + /* Skip unsupported names. */ + break; + } + cur = cur->next; + } + + MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, mbedtls_asn1_write_len(&p, buf, len)); + MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, + mbedtls_asn1_write_tag(&p, buf, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE)); + + ret = mbedtls_x509write_csr_set_extension( + ctx, + MBEDTLS_OID_SUBJECT_ALT_NAME, + MBEDTLS_OID_SIZE(MBEDTLS_OID_SUBJECT_ALT_NAME), + 0, + buf + buflen - len, + len); + + /* If we exceeded the allocated buffer it means that maximum size of the SubjectAltName list + * was incorrectly calculated and memory is corrupted. */ + if (p < buf) { + ret = MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; + } + +cleanup: + mbedtls_free(buf); + return ret; +} + +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), + 0, 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), + 0, 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, size_t sig_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[MBEDTLS_HASH_MAX_SIZE]; + 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) + size_t hash_len; + psa_algorithm_t hash_alg = mbedtls_hash_info_psa_from_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_compute(hash_alg, + c, + len, + hash, + sizeof(hash), + &hash_len) != PSA_SUCCESS) { + return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + } +#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_size, &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, MBEDTLS_PK_SIGNATURE_MAX_SIZE, + 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/sub.mk b/optee/optee_os/lib/libmbedtls/sub.mk new file mode 100644 index 0000000..05951c0 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/sub.mk @@ -0,0 +1,141 @@ +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 += aesce.c +SRCS_CRYPTO += aesni.c +SRCS_CRYPTO += aria.c +SRCS_CRYPTO += asn1parse.c +SRCS_CRYPTO += asn1write.c +SRCS_CRYPTO += base64.c +SRCS_CRYPTO += bignum.c +SRCS_CRYPTO += bignum_core.c +SRCS_CRYPTO += bignum_mod_raw.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 += hash_info.c +SRCS_CRYPTO += hkdf.c +SRCS_CRYPTO += hmac_drbg.c +SRCS_CRYPTO += lmots.c +SRCS_CRYPTO += lms.c +SRCS_CRYPTO += md.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 += pkcs7.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.c +SRCS_CRYPTO += rsa_alt_helpers.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 +else +SRCS_CRYPTO += aes.c +SRCS_CRYPTO += aesni.c +SRCS_CRYPTO += asn1parse.c +SRCS_CRYPTO += asn1write.c +SRCS_CRYPTO += bignum.c +SRCS_CRYPTO += bignum_core.c +SRCS_CRYPTO += bignum_mod_raw.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 += hash_info.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.c +SRCS_CRYPTO += rsa_alt_helpers.c +SRCS_CRYPTO += sha1.c +SRCS_CRYPTO += sha256.c +SRCS_CRYPTO += sha512.c +endif + +# OBJS_X509 +SRCS_X509 := +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_client.c +SRCS_TLS += ssl_ciphersuites.c +SRCS_TLS += ssl_cookie.c +SRCS_TLS += ssl_debug_helpers_generated.c +SRCS_TLS += ssl_ticket.c +SRCS_TLS += ssl_tls.c +SRCS_TLS += ssl_tls12_client.c +SRCS_TLS += ssl_tls12_server.c +SRCS_TLS += ssl_tls13_client.c +SRCS_TLS += ssl_tls13_generic.c +SRCS_TLS += ssl_tls13_server.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 +cflags-lib-y += -Wno-unused-function + +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..79d135b --- /dev/null +++ b/optee/optee_os/lib/libunw/include/unw/unwind.h @@ -0,0 +1,157 @@ +/* SPDX-License-Identifier: (BSD-2-Clause AND MIT-CMU) */ +/*- + * Copyright (c) 2023 Andes Technology Corporation + * 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 + +/* The state of the unwind process */ +struct unwind_state_riscv { + unsigned long fp; + unsigned long pc; +}; + +#if (defined(RV32) || defined(RV64)) && defined(CFG_UNWIND) +/* + * Unwind 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_riscv(struct unwind_state_riscv *state, + vaddr_t stack, size_t stack_size); + +void print_stack_riscv(struct unwind_state_riscv *state, + vaddr_t stack, size_t stack_size); +#else +static inline bool unwind_stack_riscv(struct unwind_state_riscv *state __unused, + vaddr_t stack __unused, + size_t stack_size __unused) +{ + return false; +} + +static inline void print_stack_riscv(struct unwind_state_riscv *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..831c9c2 --- /dev/null +++ b/optee/optee_os/lib/libunw/sub.mk @@ -0,0 +1,10 @@ +global-incdirs-y += include +ifeq ($(CFG_UNWIND),y) +ifeq (arm,$(ARCH)) +srcs-y += unwind_arm32.c +endif +srcs-$(CFG_ARM64_$(sm)) += unwind_arm64.c +ifeq (riscv,$(ARCH)) +srcs-y += unwind_riscv.c +endif +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..b6e6cd1 --- /dev/null +++ b/optee/optee_os/lib/libunw/unwind_arm64.c @@ -0,0 +1,95 @@ +// 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 +#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) +{ + vaddr_t va = 0; + int width = 8; + + trace_printf_helper_raw(TRACE_ERROR, true, "Call stack:"); + + ftrace_map_lr(&state->pc); + do { + va = memtag_strip_tag_vaddr((void *)state->pc); + trace_printf_helper_raw(TRACE_ERROR, true, " 0x%0*"PRIxVA, + width, va); + } while (unwind_stack_arm64(state, stack, stack_size)); +} diff --git a/optee/optee_os/lib/libunw/unwind_riscv.c b/optee/optee_os/lib/libunw/unwind_riscv.c new file mode 100644 index 0000000..e777015 --- /dev/null +++ b/optee/optee_os/lib/libunw/unwind_riscv.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: BSD-2-Clause +/*- + * Copyright (c) 2023 Andes Technology Corporation + * Copyright (c) 2015-2019 Linaro Limited + * Copyright (c) 2015 The FreeBSD Foundation + */ + +#include +#include +#include +#include +#include +#include + +void __weak ftrace_map_lr(uint64_t *lr __unused) +{ +} + +bool unwind_stack_riscv(struct unwind_state_riscv *frame, + vaddr_t stack, size_t stack_size) +{ + vaddr_t fp = frame->fp; + struct unwind_state_riscv *caller_state = NULL; + + if (fp < stack) + return false; + if (fp > stack + stack_size) + return false; + + /* + * | ..... | ^ unwind upwards + * | ..... | | + * +=============+ <--+ | +======= caller FP ==========+ + * | RA | | | + * +-------------+ | | + * | caller FP | ---|-+ ^ + * +-------------+ | caller stack frame + * | ..... | | v + * | ..... | | + * | ..... | | + * +=============+ | +== caller SP / trapped FP ==+ + * | RA | | + * +-------------+ | + * | caller FP | ---+ ^ + * +-------------+ trapped stack frame + * | ..... | v + * | ..... | + * | ..... | + * +=============+ +======== trapped SP ========+ + * | + * | grow downwards + * V + */ + + /* Get caller FP and RA */ + caller_state = (struct unwind_state_riscv *)fp - 1; + frame->fp = caller_state->fp; + frame->pc = caller_state->pc; + + ftrace_map_lr(&frame->pc); + + frame->pc -= 4; + + return true; +} + +void print_stack_riscv(struct unwind_state_riscv *state, + vaddr_t stack, size_t stack_size) +{ + int width = sizeof(unsigned long); + + trace_printf_helper_raw(TRACE_ERROR, true, "Call stack:"); + + ftrace_map_lr(&state->pc); + do { + trace_printf_helper_raw(TRACE_ERROR, true, " 0x%0*"PRIxVA, + width, state->pc); + } while (unwind_stack_riscv(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..d45ec52 --- /dev/null +++ b/optee/optee_os/lib/libutee/arch/riscv/utee_syscalls_rv.S @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2023 Andes Technology Corporation + * 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, : + /* The stack pointer is always kept 16-byte aligned */ + add sp, sp, -16 + /* Save return address and frame pointer to stack */ +#if defined(RV32) + sw s0, 8(sp) + sw ra, 12(sp) +#elif defined(RV64) + sd s0, 0(sp) + sd ra, 8(sp) +#endif + /* Assign a1 as stack pointer for scall_save_panic_stack() */ + mv a1, sp + /* Use tail call here because we will not return from it */ + tail __utee_panic + /* Not reached */ + 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..8fe481c --- /dev/null +++ b/optee/optee_os/lib/libutee/include/elf_common.h @@ -0,0 +1,1059 @@ +/* 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_UNKNOWN 0x00000000 +#define EF_ARM_ABI_V5 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_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_dek_blob.h b/optee/optee_os/lib/libutee/include/pta_imx_dek_blob.h new file mode 100644 index 0000000..afea562 --- /dev/null +++ b/optee/optee_os/lib/libutee/include/pta_imx_dek_blob.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2019 NXP + * + * brief PTA DEK Blob interface identification. + */ +#ifndef __PTA_IMX_DEK_BLOB_H__ +#define __PTA_IMX_DEK_BLOB_H__ + +#define PTA_DEK_BLOB_UUID {0xef477737, 0x0db1, 0x4a9d, \ + {0x84, 0x37, 0xf2, 0xf5, 0x35, 0xc0, 0xbd, 0x92} } + +/* HAB DEK Blob encapsulation */ +#define PTA_IMX_DEK_BLOB_CMD_GENERATE 0 + +#endif /* __PTA_IMX_DEK_BLOB_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_ftpm_helper.h b/optee/optee_os/lib/libutee/include/pta_jetson_ftpm_helper.h new file mode 100644 index 0000000..a95f92b --- /dev/null +++ b/optee/optee_os/lib/libutee/include/pta_jetson_ftpm_helper.h @@ -0,0 +1,147 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. + */ + +#ifndef __JETSON_FTPM_HELPER_PTA_H__ +#define __JETSON_FTPM_HELPER_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 : {6c879517-2dfc-4663-863d-4896e8ccbe3a} + */ +#define FTPM_HELPER_PTA_UUID \ + { 0x6c879517, 0x2dfc, 0x4663, \ + {0x86, 0x3d, 0x48, 0x96, 0xe8, 0xcc, 0xbe, 0x3a} } + +/* Jetson fTPM helper PTA version */ +#define FTPM_HELPER_PTA_VERSION_MAJOR 2 +#define FTPM_HELPER_PTA_VERSION_MINOR 0 + +#define FTPM_HELPER_PTA_NS_STATE_NOT_READY 0xff000001 +#define FTPM_HELPER_PTA_NS_STATE_READY 0xff000002 +#define FTPM_HELPER_PTA_OFFLINE_PROV_MODE 0xff00000a +#define FTPM_HELPER_PTA_ONLINE_PROV_MODE 0xff00000b +#define FTPM_HELPER_PTA_UNKNOWN_PROV_MODE 0xff00000c + +#define FTPM_HELPER_PTA_ECID_LENGTH 8U +#define FTPM_HELPER_PTA_SN_LENGTH 10U +/* EK Certificate buffer size */ +#define FTPM_HELPER_PTA_EK_CERT_BUF_SIZE 2048U +/* EK CSR buffer size */ +#define FTPM_EK_CSR_BUF_SIZE 2048U +/* EK CSR signature buffer size */ +#define FTPM_EK_CSR_SIG_SIZE 80U + +/* + * FTPM_HELPER_PTA_CMD_PING_NS - Ping NS world is ready for TEE services. + * param[0] out (value) a: normal world status + * param[1] unused + * param[2] unused + * param[3] unused + */ +#define FTPM_HELPER_PTA_CMD_PING_NS 0xffff0001 + +/* + * FTPM_HELPER_PTA_CMD_QUERY_SN - Query the device serial number + * param[0] out (memref) data buffer and size + * param[1] unused + * param[2] unused + * param[3] unused + */ +#define FTPM_HELPER_PTA_CMD_QUERY_SN 0xffff0002 + +/* + * FTPM_HELPER_PTA_CMD_QUERY_ECID - Query the device ECID + * param[0] out (memref) data buffer and size + * param[1] unused + * param[2] unused + * param[3] unused + */ +#define FTPM_HELPER_PTA_CMD_QUERY_ECID 0xffff0003 + +/* + * FTPM_HELPER_PTA_CMD_QUERY_PROV_MODE - Query the fTPM provisioning mode. + * param[0] out (value) a: The defined value of provisioning mode. + * param[1] out (value) a: The version major number. + * param[2] out (value) a: The version major minor. + * param[3] unused + */ +#define FTPM_HELPER_PTA_CMD_QUERY_PROV_MODE 0xffff0004 + +/* + * FTPM_HELPER_PTA_CMD_GET_RSA_EK_CERT - Get the fTPM RSA EK Certificate + * param[0] out (memref) data buffer and size + * param[1] unused + * param[2] unused + * param[3] unused + */ +#define FTPM_HELPER_PTA_CMD_GET_RSA_EK_CERT 0xffff0005 + +/* + * FTPM_HELPER_PTA_CMD_GET_EC_EK_CERT - Get the fTPM EC EK Certificate + * param[0] out (memref) data buffer and size + * param[1] unused + * param[2] unused + * param[3] unused + */ +#define FTPM_HELPER_PTA_CMD_GET_EC_EK_CERT 0xffff0006 + +/* + * FTPM_HELPER_PTA_CMD_GET_SID_CERT - Get the Silicon ID Certificate + * param[0] out (memref) data buffer and size + * param[1] unused + * param[2] unused + * param[3] unused + */ +#define FTPM_HELPER_PTA_CMD_GET_SID_CERT 0xffff0007 + +/* + * FTPM_HELPER_PTA_CMD_GET_FW_ID_CERT - Get the Firmware ID Certificate + * param[0] out (memref) data buffer and size + * param[1] unused + * param[2] unused + * param[3] unused + */ +#define FTPM_HELPER_PTA_CMD_GET_FW_ID_CERT 0xffff0008 + +/* + * FTPM_HELPER_PTA_CMD_GET_RSA_EK_CSR - Get the fTPM RSA EK CSR + * param[0] out (memref) data buffer and size + * param[1] unused + * param[2] unused + * param[3] unused + */ +#define FTPM_HELPER_PTA_CMD_GET_RSA_EK_CSR 0xffff0009 + +/* + * FTPM_HELPER_PTA_CMD_GET_EC_EK_CSR - Get the fTPM EC EK CSR + * param[0] out (memref) data buffer and size + * param[1] unused + * param[2] unused + * param[3] unused + */ +#define FTPM_HELPER_PTA_CMD_GET_EC_EK_CSR 0xffff000a + +/* + * FTPM_HELPER_PTA_CMD_SIGN_EK_CSR - Receive the hash of EK CSR and sign it + * param[0] in (memref) the EK CSR digest buffer and size + * param[1] out (memref) the EK CSR signature buffer and size + * param[2] unused + * param[3] unused + */ +#define FTPM_HELPER_PTA_CMD_SIGN_EK_CSR 0xffff000b + +/* + * FTPM_HELPER_PTA_CMD_INJECT_EPS - Set the EPS explicitly from outside + * param[0] in (memref) eps buffer and size + * param[1] unused + * param[2] unused + * param[3] unused + */ +#define FTPM_HELPER_PTA_CMD_INJECT_EPS 0xffff000c + +#endif /* __JETSON_FTPM_HELPER_PTA_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..790a341 --- /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-2024, 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_DEVICE_ID_CERT, + EKB_USER_KEY_UEFI_VAR_AUTH, + EKB_USER_KEY_NUM_MAX, +} 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_stats.h b/optee/optee_os/lib/libutee/include/pta_stats.h new file mode 100644 index 0000000..f95d3ac --- /dev/null +++ b/optee/optee_os/lib/libutee/include/pta_stats.h @@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2023, STMicroelectronics + * Copyright (C) 2022, Microchip + */ +#ifndef __PTA_STATS_H +#define __PTA_STATS_H + +#include +#include + +#define STATS_UUID \ + { 0xd96a5b40, 0xe2c7, 0xb1af, \ + { 0x87, 0x94, 0x10, 0x02, 0xa5, 0xd5, 0xc6, 0x1b } } + +/* + * STATS_CMD_PAGER_STATS - Get statistics on pager + * + * [out] value[0].a Number of unlocked pages + * [out] value[0].b Page pool size + * [out] value[1].a R/O faults since last stats dump + * [out] value[1].b R/W faults since last stats dump + * [out] value[2].a Hidden faults since last stats dump + * [out] value[2].b Zi pages released since last stats dump + */ +#define STATS_CMD_PAGER_STATS 0 + +/* + * STATS_CMD_ALLOC_STATS - Get statistics on core heap allocations + * + * [in] value[0].a ID of allocator(s) to get stats from (ALLOC_ID_*) + * [out] memref[0] Array of struct pta_stats_alloc instances + */ +#define STATS_CMD_ALLOC_STATS 1 + +#define ALLOC_ID_ALL 0 /* All allocators */ +#define ALLOC_ID_HEAP 1 /* Core heap allocator */ +#define ALLOC_ID_PUBLIC_DDR 2 /* Public DDR allocator (deprecated) */ +#define ALLOC_ID_TA_RAM 3 /* TA_RAM allocator */ +#define ALLOC_ID_NEXUS_HEAP 4 /* Nexus heap allocator */ +#define STATS_NB_POOLS 5 + +#define TEE_ALLOCATOR_DESC_LENGTH 32 + +struct pta_stats_alloc { + 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 */ +}; + +/* + * STATS_CMD_MEMLEAK_STATS - Print memory leakage info to console + */ +#define STATS_CMD_MEMLEAK_STATS 2 + +/* + * STATS_CMD_TA_STATS - Get information on TA instances + * + * [out] memref[0] Array of struct pta_stats_ta per loaded TA + */ +#define STATS_CMD_TA_STATS 3 + +struct pta_stats_ta { + TEE_UUID uuid; + uint32_t panicked; /* True if TA has panicked */ + uint32_t sess_num; /* Number of opened session */ + struct pta_stats_alloc heap; +}; + +/* + * STATS_CMD_GET_TIME - Get both REE time and TEE time + * + * [out] value[0].a REE time as seen by OP-TEE in seconds + * [out] value[0].b REE time as seen by OP-TEE, milliseconds part + * [out] value[1].a TEE system time in seconds + * [out] value[1].b TEE system time, milliseconds part + */ +#define STATS_CMD_GET_TIME 4 + +/* + * STATS_CMD_PRINT_DRIVER_INFO - Print device drivers information to console + * + * [in] value[0].a Target driver, one of STATS_DRIVER_TYPE_* + */ +#define STATS_CMD_PRINT_DRIVER_INFO 5 + +#define STATS_DRIVER_TYPE_CLOCK 0 +#define STATS_DRIVER_TYPE_REGULATOR 1 + +#endif /*__PTA_STATS_H*/ 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/pta_widevine.h b/optee/optee_os/lib/libutee/include/pta_widevine.h new file mode 100644 index 0000000..f76a5fc --- /dev/null +++ b/optee/optee_os/lib/libutee/include/pta_widevine.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2023, The ChromiumOS Authors + */ + +#ifndef __PTA_WIDEVINE_H +#define __PTA_WIDEVINE_H + +/* + * Interface to the widevine pseudo-TA, which is used for passing parameters + * for widevine TA. + */ +#define PTA_WIDEVINE_UUID \ + { \ + 0x721f4da9, 0xda05, 0x40d4, \ + { \ + 0xa1, 0xa3, 0x83, 0x77, 0xc1, 0xe0, 0x8b, 0x0a \ + } \ + } + +/* + * PTA_WIDEVINE_GET_TPM_PUBKEY - Get Widevine TPM public key + * PTA_WIDEVINE_GET_WIDEVINE_PRIVKEY - Get Widevine private key + * + * [out] memref[0] Retrieved key data + * + * Return codes: + * TEE_SUCCESS - Invoke command success + * TEE_ERROR_BAD_PARAMETERS - Incorrect parameters + * TEE_ERROR_SHORT_BUFFER - Output buffer size is too small + * TEE_ERROR_NO_DATA - Requested data not available + */ +#define PTA_WIDEVINE_GET_TPM_PUBKEY 0 +#define PTA_WIDEVINE_GET_WIDEVINE_PRIVKEY 1 + +#endif /* __PTA_WIDEVINE_H */ diff --git a/optee/optee_os/lib/libutee/include/remoteproc_pta.h b/optee/optee_os/lib/libutee/include/remoteproc_pta.h new file mode 100644 index 0000000..e4be4be --- /dev/null +++ b/optee/optee_os/lib/libutee/include/remoteproc_pta.h @@ -0,0 +1,150 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2023, STMicroelectronics + */ + +#ifndef __REMOTEPROC_PTA_H +#define __REMOTEPROC_PTA_H + +#include +#include + +/* + * Interface to the pseudo TA which provides platform implementation + * of the remote processor management + */ + +#define PTA_RPROC_UUID { 0x54af4a68, 0x19be, 0x40d7, \ + { 0xbb, 0xe6, 0x89, 0x50, 0x35, 0x0a, 0x87, 0x44 } } + +/* Hardware capability: firmware format */ +#define PTA_RPROC_HWCAP_FMT_ELF BIT32(0) + +/* Hardware capability: image protection method */ +/* The platform supports load of segment with hash protection */ +#define PTA_RPROC_HWCAP_PROT_HASH_TABLE BIT32(0) + +/** + * struct rproc_pta_key_info - public key information + * @algo: Algorithm, defined by public key algorithms TEE_ALG_* + * @info_size: Byte size of @info + * @info: Append key information data + */ +struct rproc_pta_key_info { + uint32_t algo; + uint32_t info_size; + uint8_t info[]; +}; + +static inline size_t rproc_pta_keyinfo_size(struct rproc_pta_key_info *keyinf) +{ + size_t s = 0; + + if (!keyinf || ADD_OVERFLOW(sizeof(*keyinf), keyinf->info_size, &s)) + return 0; + + return s; +} + +/* + * Platform capabilities. + * + * Get Platform firmware loader service capabilities. + * + * [in] params[0].value.a: Unique 32bit remote processor identifier + * [out] params[1].value.a: Firmware format (PTA_RPROC_HWCAP_FMT_*) + * [out] params[2].value.a: Image protection method (PTA_RPROC_HWCAP_PROT_*) + */ +#define PTA_RPROC_HW_CAPABILITIES 1 + +/* + * Firmware loading. + * + * Optional service to implement only in case of proprietary format. + * + * [in] params[0].value.a: Unique 32bit remote processor identifier + * [in] params[1].memref: Loadable firmware image + */ +#define PTA_RPROC_FIRMWARE_LOAD 2 + +/* + * Load a segment with a SHA256 hash. + * + * This command is used when the platform secure memory is too constrained to + * save the whole firmware image. Upon segment load, a successful completion + * ensures the loaded image complies with the provided hash. + * + * [in] params[0].value.a: Unique 32bit remote processor identifier + * [in] params[1].memref: Section data to load + * [in] params[2].value.a: 32bit LSB load device segment address + * [in] params[2].value.b: 32bit MSB load device segment address + * [in] params[3].memref: Expected hash (SHA256) of the payload + */ +#define PTA_RPROC_LOAD_SEGMENT_SHA256 3 + +/* + * Memory set. + * + * Fill a remote device memory with requested value. this is used for instance + * to clear a memory on the remote firmware load. + * + * [in] params[0].value.a: Unique 32bit remote processor identifier + * [in] params[1].value.a: 32bit LSB device memory address + * [in] params[1].value.b: 32bit MSB device memory address + * [in] params[2].value.a: 32bit LSB device memory size + * [in] params[2].value.b: 32bit MSB device memory size + * [in] params[3].value.a: Byte value to be set + */ +#define PTA_RPROC_SET_MEMORY 4 + +/* + * Firmware start. + * + * Start up a successfully loaded remote processor firmware. + * + * [in] params[0].value.a: Unique 32bit remote processor identifier + */ +#define PTA_RPROC_FIRMWARE_START 5 + +/* + * Firmware stop. + * + * Stop of the remote processor firmware and release/clean resources. + * After the command successful completion, remote processor firmware must be + * reloaded prior being started again. + * + * [in] params[0].value.a: Unique 32bit remote processor identifier + */ +#define PTA_RPROC_FIRMWARE_STOP 6 + +/* + * Firmware device to physical address conversion. + * + * Convert the physical address corresponding to an address got from the + * firmware address layout. + * + * [in] params[0].value.a: Unique 32bit remote processor identifier + * [in] params[1].value.a: 32bit LSB Device memory address + * [in] params[1].value.b: 32bit MSB Device memory address + * [in] params[2].value.a: 32bit LSB Device memory size + * [in] params[2].value.b: 32bit MSB Device memory size + * [out] params[3].value.a: 32bit LSB converted physical address + * [out] params[3].value.b: 32bit MSB converted physical address + */ +#define PTA_RPROC_FIRMWARE_DA_TO_PA 7 + +/* + * Verify the firmware digest against a signature + * + * Return TEE_SUCCESS if the signature is verified, + * TEE_ERROR_SIGNATURE_INVALID when signature is not valid, + * another error code for other error cases. + * + * [in] params[0].value.a: Unique 32bit remote processor identifier + * [in] params[1].memref: Key information (refer to @rproc_pta_key_info) + * [in] params[2].memref: Digest of the firmware authenticated data + * [in] params[3].memref: Signature of the firmware authenticated data + */ +#define PTA_RPROC_VERIFY_DIGEST 8 + +#endif /* __REMOTEPROC_PTA_H */ diff --git a/optee/optee_os/lib/libutee/include/riscv_user_sysreg.h b/optee/optee_os/lib/libutee/include/riscv_user_sysreg.h new file mode 100644 index 0000000..eed5d97 --- /dev/null +++ b/optee/optee_os/lib/libutee/include/riscv_user_sysreg.h @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2023 Andes Technology Corporation + */ +#ifndef RISCV_USER_SYSREG_H +#define RISCV_USER_SYSREG_H + +#include + +#define read_csr(csr) \ + ({ \ + register unsigned long v; \ + asm volatile ("csrr %0, " #csr : "=r"(v) : : "memory"); \ + v; \ + }) + +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 RV32 + do { + hi = read_csr(timeh); + lo = read_csr(time); + } while (hi != read_csr(timeh)); + + time = SHIFT_U64(hi, 32) | lo; +#else /*RV64*/ + time = read_csr(time); +#endif /*RV32*/ + + return time; +} + +/* These barriers need to enforce ordering on both devices and memory. */ +static inline __noprof void mb(void) +{ + asm volatile ("fence" : : : "memory"); +} + +static inline __noprof uint64_t barrier_read_counter_timer(void) +{ + mb(); /* Get timer value after pending operations have completed */ + return read_time(); +} + +static inline __noprof uint32_t read_cntfrq(void) +{ + return CFG_RISCV_MTIME_RATE; +} + +#endif /* RISCV_USER_SYSREG_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..cf1d3ed --- /dev/null +++ b/optee/optee_os/lib/libutee/include/tee_arith_internal.h @@ -0,0 +1,54 @@ +/* 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 + +/*------------------------------------------------------------ + * + * 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..056b94c --- /dev/null +++ b/optee/optee_os/lib/libutee/include/user_ta_header.h @@ -0,0 +1,155 @@ +/* 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_idx; /* Current entry in the (circular) 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 */ + bool overflow; /* Circular buffer has wrapped */ +}; + +/* 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 */ + USER_TA_PROP_TYPE_INVALID, /* invalid value */ +}; + +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..6c3248d --- /dev/null +++ b/optee/optee_os/lib/libutee/include/utee_defines.h @@ -0,0 +1,362 @@ +/* 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_MAIN_ALGO_X448 0x49 + + +#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; + case TEE_ALG_X448: + return TEE_MAIN_ALGO_X448; + 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_LITTLE_ENDIAN(x) ((uint64_t)(x)) +#define TEE_U32_FROM_LITTLE_ENDIAN(x) ((uint32_t)(x)) +#define TEE_U16_FROM_LITTLE_ENDIAN(x) ((uint16_t)(x)) +#define TEE_U64_TO_LITTLE_ENDIAN(x) ((uint64_t)(x)) +#define TEE_U32_TO_LITTLE_ENDIAN(x) ((uint32_t)(x)) +#define TEE_U16_TO_LITTLE_ENDIAN(x) ((uint16_t)(x)) +#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..07e1f7e --- /dev/null +++ b/optee/optee_os/lib/libutee/sub.mk @@ -0,0 +1,30 @@ +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 +cppflags-tee_api_arith_mpi.c-y += -DMBEDTLS_ALLOW_PRIVATE_ACCESS +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..4c9b240 --- /dev/null +++ b/optee/optee_os/lib/libutee/tee_api.c @@ -0,0 +1,813 @@ +// 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) { + void *ret = NULL; + + if (addr_is_in_no_share_heap(buffer)) + ret = TEE_NULL_SIZED_NO_SHARE_VA; + else + ret = TEE_NULL_SIZED_VA; + + TEE_Free(buffer); + + return ret; + } + + 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..1d08ae1 --- /dev/null +++ b/optee/optee_os/lib/libutee/tee_api_arith_mpi.c @@ -0,0 +1,1014 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2018, Linaro limited + * Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MPI_MEMPOOL_SIZE (16 * 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; +} + +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) +{ + int rc; + mbedtls_mpi mpi_op; + + get_mpi(&mpi_op, op); + + rc = mbedtls_mpi_is_prime_ext(&mpi_op, MAX(confidenceLevel, 80U), + 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..752425a --- /dev/null +++ b/optee/optee_os/lib/libutee/tee_api_operations.c @@ -0,0 +1,2710 @@ +// 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 */ + 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; + /* 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..5f33e2c --- /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 = TEE_ERROR_GENERIC; + size_t l = 0; + enum user_ta_prop_type type = USER_TA_PROP_TYPE_INVALID; + void *tmp_buf = 0; + uint32_t tmp_len = 0; + uint32_t uint32_val = 0; + bool bool_val = false; + TEE_Identity *p_identity_val = NULL; + + 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..b33953f --- /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 pta_stats_alloc 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/mcount_rv.S b/optee/optee_os/lib/libutils/ext/arch/riscv/mcount_rv.S new file mode 100644 index 0000000..a9f8db2 --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/arch/riscv/mcount_rv.S @@ -0,0 +1,122 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2023 Andes Technology Corporation + * Copyright (c) 2016, Linaro Limited + */ + +#include + +#if defined(CFG_FTRACE_SUPPORT) + +/* + * Convert return address to call site address by subtracting the size of one + * instruction. + */ +.macro adjust_pc rd, rn + addi \rd, \rn, -4 +.endm + +#ifdef RV32 + +/* Get instrumented function's pc value */ +.macro get_pc reg + LDR \reg, REGOFF(3)(sp) + addi \reg, \reg, -4 +.endm + +/* Get instrumented function's ra address pointer */ +.macro get_ra_addr reg + LDR \reg, REGOFF(2)(sp) + addi \reg, \reg, -4 +.endm + +#else /* RV64 */ + +/* Get instrumented function's pc value */ +.macro get_pc reg + LDR \reg, REGOFF(1)(sp) + addi \reg, \reg, -4 +.endm + +/* Get instrumented function's ra address pointer */ +.macro get_ra_addr reg + LDR \reg, REGOFF(0)(sp) + addi \reg, \reg, -8 +.endm + +#endif /* RV32 */ + +/* + * 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. + * a0 contains the value of ra 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 ra. + * Then we call: + * void __mcount_internal(void *frompc, void *selfpc); + */ +FUNC _mcount, : + addi sp, sp, -16 + /* Save ra and s0(fp) onto stack */ +#ifdef RV32 + STR ra, REGOFF(3)(sp) + STR s0, REGOFF(2)(sp) +#else + STR ra, REGOFF(1)(sp) + STR s0, REGOFF(0)(sp) +#endif + /* Setup frame pointer */ + addi s0, sp, 16 +#ifdef CFG_FTRACE_SUPPORT + get_pc a0 + get_ra_addr a1 + call ftrace_enter +#endif + /* Restore ra and s0(fp) from stack */ +#ifdef RV32 + LDR s0, REGOFF(2)(sp) + LDR ra, REGOFF(3)(sp) +#else + LDR s0, REGOFF(0)(sp) + LDR ra, REGOFF(1)(sp) +#endif + addi sp, sp, 16 + ret +END_FUNC _mcount + +#ifdef CFG_FTRACE_SUPPORT +FUNC __ftrace_return, : + /* Save return value regs */ + addi sp, sp, -REGOFF(8) + STR a0, REGOFF(0)(sp) + STR a1, REGOFF(1)(sp) + STR a2, REGOFF(2)(sp) + STR a3, REGOFF(3)(sp) + STR a4, REGOFF(4)(sp) + STR a5, REGOFF(5)(sp) + STR a6, REGOFF(6)(sp) + STR a7, REGOFF(7)(sp) + + /* Get return address of parent func */ + call ftrace_return + mv ra, a0 + + /* Restore return value regs */ + LDR a0, REGOFF(0)(sp) + LDR a1, REGOFF(1)(sp) + LDR a2, REGOFF(2)(sp) + LDR a3, REGOFF(3)(sp) + LDR a4, REGOFF(4)(sp) + LDR a5, REGOFF(5)(sp) + LDR a6, REGOFF(6)(sp) + LDR a7, REGOFF(7)(sp) + addi sp, sp, REGOFF(8) + + ret +END_FUNC __ftrace_return +#endif + +#endif /* CFG_FTRACE_SUPPORT */ 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..01a1d58 --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/arch/riscv/sub.mk @@ -0,0 +1,4 @@ +srcs-y+= atomic_rv.S +ifneq ($(sm),ldelf) # TA, core +srcs-y += mcount_rv.S +endif 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..d7984e7 --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/ftrace/ftrace.c @@ -0,0 +1,150 @@ +// 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 +#include +#if defined(__KERNEL__) +#if defined(ARM32) || defined(ARM64) +#include +#elif defined(RV32) || defined(RV64) +#include +#endif +#include +#include +#include +#include +#else +#if defined(ARM32) || defined(ARM64) +#include +#elif defined(RV32) || defined(RV64) +#include +#endif +#include +#include +#endif +#include "ftrace.h" + +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 (!is_ta_ctx(s->ctx) || to_ta_ctx(s->ctx)->panicked) + 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 +} + +static void __noprof add_elem(struct ftrace_buf *fbuf, uint8_t level, + uint64_t val) +{ + uint64_t *elem = NULL; + size_t idx = fbuf->curr_idx; + + /* Make sure the topmost byte doesn't contain useful information */ + assert(!(val >> 56)); + + elem = (uint64_t *)((vaddr_t)fbuf + fbuf->buf_off) + idx; + *elem = SHIFT_U64(level, 56) | val; + + idx++; + if ((idx + 1) * sizeof(*elem) > fbuf->max_size) { + idx = 0; + fbuf->overflow = true; + } + + fbuf->curr_idx = idx; +} + +void __noprof ftrace_enter(unsigned long pc, unsigned long *lr) +{ + uint64_t now = barrier_read_counter_timer(); + struct ftrace_buf *fbuf = get_fbuf(); + + if (!fbuf || !fbuf->buf_off || !fbuf->max_size) + return; + + add_elem(fbuf, fbuf->ret_idx + 1, pc); + + if (fbuf->ret_idx < FTRACE_RETFUNC_DEPTH) { + fbuf->ret_stack[fbuf->ret_idx] = *lr; + fbuf->begin_time[fbuf->ret_idx] = now; + 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; +} + +unsigned long __noprof ftrace_return(void) +{ + uint64_t now = barrier_read_counter_timer(); + struct ftrace_buf *fbuf = get_fbuf(); + uint64_t start = 0; + uint64_t elapsed = 0; + + /* Check for valid return index */ + if (!fbuf || !fbuf->ret_idx || fbuf->ret_idx > FTRACE_RETFUNC_DEPTH) + return 0; + + fbuf->ret_idx--; + start = fbuf->begin_time[fbuf->ret_idx]; + elapsed = (now - start) * 1000000000 / read_cntfrq(); + add_elem(fbuf, 0, elapsed); + + 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..ff1c4b8 --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/include/asm.S @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2020, Linaro Limited + */ + +#if defined(__aarch64__) +#include +#elif defined(__riscv) +#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..47e8838 --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/include/compiler.h @@ -0,0 +1,287 @@ +/* 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 + +#ifndef __clang__ +#define __no_stackprot __attribute__((__optimize__ ("-fno-stack-protector"))) +#else +#define __no_stackprot +#endif + +#define __inhibit_loop_to_libcall \ + __attribute__ ((__optimize__ ("-fno-tree-loop-distribute-patterns"))) +#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..06a6f7f --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/include/fault_mitigation.h @@ -0,0 +1,690 @@ +/* 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__) + if (thread_get_id_may_fail() >= 0) + return &thread_get_tsd()->ftmn_arg; + else + return &thread_get_core_local()->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/riscv.S b/optee/optee_os/lib/libutils/ext/include/riscv.S new file mode 100644 index 0000000..62d5b47 --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/include/riscv.S @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2023 Andes Technology Corporation + */ + +#if __riscv_xlen == 32 +#define STR sw +#define LDR lw +#define REGOFF(x) ((x) * 4) +#elif __riscv_xlen == 64 +#define STR sd +#define LDR ld +#define REGOFF(x) ((x) * 8) +#endif 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..548c165 --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/include/speculation_barrier.h @@ -0,0 +1,574 @@ +/* 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)) + +#elif defined(RV32) || defined(RV64) + +#define __load_no_speculate1(__ptr, __low, __high, __failval, __cmpptr, __sz) \ +(__extension__ ({ \ + __typeof__ (0 + (*(__ptr))) __nln_val; \ + asm volatile ( \ + "fence\trw,rw\n\t" \ + "fence.i\n\t" \ + "fence\tr,r\n\t" \ + "l" __sz "\t%[__v], %[__p]\n" \ + /* The value we have loaded. */ \ + : [__v] "=&r" (__nln_val) \ + : \ + /* The memory location from which we will load. */ \ + [__p] "m" (*(__ptr)) \ + : ); \ + (__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, "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, "w"); \ + break; \ + case 8: \ + __nl_val = __load_no_speculate1 (__ptr, __low, __high, \ + __failval, __cmpptr, "d"); \ + 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..6ea6dcc --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/include/trace.h @@ -0,0 +1,153 @@ +/* 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); +int trace_ext_get_guest_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..aedd508 --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/include/util.h @@ -0,0 +1,208 @@ +/* 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 uint32_t high32_from_64(uint64_t val) +{ + return val >> 32; +} + +static inline uint32_t low32_from_64(uint64_t val) +{ + return val; +} + +static inline void reg_pair_from_64(uint64_t val, uint32_t *reg0, + uint32_t *reg1) +{ + *reg0 = high32_from_64(val); + *reg1 = low32_from_64(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..e12962f --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/mempool.c @@ -0,0 +1,188 @@ +// 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 +#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 pta_stats_alloc 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) +{ + if (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..259e4a7 --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/trace.c @@ -0,0 +1,311 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#if defined(__KERNEL__) +#include +#endif + +#include +#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); +} + +static int print_guest_id(char *buf, size_t bs) +{ + if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) + return snprintk(buf, bs, "%d ", trace_ext_get_guest_id()); + else + return 0; + + +} +#else /* defined(__KERNEL__) */ +static int print_core_id(char *buf __unused, size_t bs __unused) +{ + return 0; +} + +static int print_guest_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 current guest ID or 0 for Nexus */ + res = print_guest_id(buf + boffs, sizeof(buf) - boffs); + if (res < 0) + return; + boffs += res; + + /* 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..6335b6b --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_divmod.c @@ -0,0 +1,153 @@ +// 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); + */ + +#include + +/* 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 __no_stackprot __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 __no_stackprot __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..acb75c5 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/riscv/setjmp_rv.S @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2023 Andes Technology Corporation + * Copyright 2022-2023 NXP + */ +#include + +/* 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 +#ifdef RV32 + STR ra, REGOFF(3)(sp) + STR s0, REGOFF(2)(sp) +#else + STR ra, REGOFF(1)(sp) + STR s0, REGOFF(0)(sp) +#endif + addi s0, sp, 16 + addi a0, a0, REGOFF(14) + call ftrace_setjmp +#ifdef RV32 + LDR s0, REGOFF(2)(sp) + LDR ra, REGOFF(3)(sp) +#else + LDR s0, REGOFF(0)(sp) + LDR ra, REGOFF(1)(sp) +#endif + 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, -REGOFF(4) + STR a0, REGOFF(0)(sp) + STR a1, REGOFF(1)(sp) + STR s0, REGOFF(2)(sp) + STR ra, REGOFF(3)(sp) + addi s0, sp, REGOFF(4) + addi a0, a0, REGOFF(14) + call ftrace_longjmp + LDR a0, REGOFF(0)(sp) + LDR a1, REGOFF(1)(sp) + LDR s0, REGOFF(2)(sp) + LDR ra, REGOFF(3)(sp) + addi sp, sp, REGOFF(4) +#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..1b26f93 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/bget_malloc.c @@ -0,0 +1,1141 @@ +// 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 +#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 pta_stats_alloc 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 pta_stats_alloc *stats) +{ + uint32_t exceptions = malloc_lock(ctx); + + raw_malloc_get_stats(ctx, stats); + malloc_unlock(ctx, exceptions); +} + +void malloc_get_stats(struct pta_stats_alloc *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_unchecked(p, old_ptr, old_sz); +#ifndef __KERNEL__ + /* User space reallocations are always zeroed */ + memset_unchecked((uint8_t *)p + old_sz, 0, s - old_sz); +#endif + } else { + memcpy_unchecked(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", + 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 pta_stats_alloc *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 pta_stats_alloc *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..19738eb --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/include/assert.h @@ -0,0 +1,77 @@ +/* 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(); +} + +static inline void _runtime_assert_trap(const char *expr_str, const char *file, + const int line, const char *func) +{ + volatile bool do_break = true; + + _assert_log(expr_str, file, line, func); + if (do_break) + _assert_break(); +} + +/* + * runtime_assert() behaves as assert() except that it doesn't tell the + * compiler it will never return. This can be used to avoid the warning: + * error: function might be candidate for attribute ‘noreturn’ + */ +#ifdef NDEBUG +#define assert(expr) ((void)0) +#define runtime_assert(expr) ((void)0) +#else +#define assert(expr) \ + ((expr) ? (void)0 : _assert_trap(#expr, __FILE__, __LINE__, __func__)) +#define runtime_assert(expr) \ + ((expr) ? (void)0 : \ + _runtime_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..4e405c0 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/include/malloc.h @@ -0,0 +1,168 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#ifndef __MALLOC_H +#define __MALLOC_H + +#include +#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 */ +void malloc_get_stats(struct pta_stats_alloc *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 pta_stats_alloc *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 pta_stats_alloc *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..cb1e868 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/include/setjmp.h @@ -0,0 +1,79 @@ +/* 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 + +#if defined(RV64) || defined(RV32) +/* + * Callee preserved registers: + * s0-s11, ra, sp + * One additional value used in case ftrace + * is enabled to restore ftrace return stack. + */ +#define _JBLEN 15 +#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/fcntl.h b/optee/optee_os/lib/libutils/isoc/include/sys/fcntl.h new file mode 100644 index 0000000..8ff7698 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/include/sys/fcntl.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 1994-2009 Red Hat, Inc. All rights reserved. + */ + +#ifndef _SYS_FCNTL_H_ +#define _SYS_FCNTL_H_ + +#define _FAPPEND 0x0008 /* append (writes guaranteed at the end) */ +#define _FCREAT 0x0200 /* open with file create */ +#define _FTRUNC 0x0400 /* open with truncation */ + +/* + * Flag values for open(2) and fcntl(2) + */ +#define O_RDONLY 0 /* +1 == FREAD */ +#define O_WRONLY 1 /* +1 == FWRITE */ +#define O_RDWR 2 /* +1 == FREAD|FWRITE */ +#define O_APPEND _FAPPEND +#define O_CREAT _FCREAT +#define O_TRUNC _FTRUNC + +#endif /* _SYS_FCNTL_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..65cd4a5 --- /dev/null +++ b/optee/optee_os/mk/aosp_optee.mk @@ -0,0 +1,195 @@ +########################################################## +## 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) +ifneq ($(local_optee_ta_target),) +TA_TARGET := $(local_optee_ta_target) +else +TA_TARGET := $(OPTEE_TA_TARGETS) +endif +TA_DEV_KIT_DIR := $(OPTEE_OS_OUT_DIR)/export-$(TA_TARGET) +ABS_TA_DEV_KIT_DIR := $(ABS_OPTEE_OS_OUT_DIR)/export-$(TA_TARGET) + +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))) + +OPTEE_TA_DEV_KIT_MK := $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk + +$(OPTEE_TA_DEV_KIT_MK) : $(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 + +########################################################### +## similar to the $(OPTEE_BIN) target above, use condition +## check to make $(OPTEE_TA_DEV_KIT_MK) for different ta +## targets only be defined once +########################################################### +ifeq ($(filter $(TA_TARGET),$(BUILD_TA_DEV_KIT_DEFINED)),) +BUILD_TA_DEV_KIT_DEFINED := $(TA_TARGET) $(BUILD_TA_DEV_KIT_DEFINED) +$(OPTEE_TA_DEV_KIT_MK): PRIVATE_TA_TARGET := $(TA_TARGET) +$(OPTEE_TA_DEV_KIT_MK): + @echo "Start building ta_dev_kit ($(PRIVATE_TA_TARGET))..." + +$(HOST_MAKE) -C $(TOP_ROOT_ABS)/$(OPTEE_OS_DIR) \ + O=$(ABS_OPTEE_OS_OUT_DIR) \ + CFG_USER_TA_TARGETS=$(PRIVATE_TA_TARGET) \ + CFG_ARM64_core=$(OPTEE_CFG_ARM64_CORE) \ + PLATFORM=$(OPTEE_PLATFORM) \ + PLATFORM_FLAVOR=$(OPTEE_PLATFORM_FLAVOR) \ + $(CROSS_COMPILE_LINE) \ + $(OPTEE_EXTRA_FLAGS) ta_dev_kit + @echo "Finished building ta_dev_kit ($(PRIVATE_TA_TARGET))..." +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) + +define ta_class +$(if $(filter %.ta,$1),EXECUTABLES,STATIC_LIBRARIES) +endef + +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 := $(call ta_class,$(local_module)) +LOCAL_MODULE_TAGS := optional +LOCAL_REQUIRED_MODULES := $(local_module_deps) + +TA_TMP_DIR := $(addsuffix _$(TA_TARGET), $(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 += $(call intermediates-dir-for,$(call ta_class,$(dep)),$(dep))/$(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): PRIVATE_TA_DEV_KIT_DIR := $(ABS_TA_DEV_KIT_DIR) +$(TA_TMP_FILE): $(OPTEE_TA_DEV_KIT_MK) + @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=$(PRIVATE_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) + +# To get ta elf files for early-ta, +# copy them to $(PRODUCT_OUT)/unsigned/ on host +ifeq ($(call ta_class,$(local_module)),EXECUTABLES) +include $(CLEAR_VARS) +LOCAL_MODULE := $(local_module).unsigned +LOCAL_PREBUILT_MODULE_FILE := $(OPTEE_TA_OUT_DIR)/$(LOCAL_MODULE) +LOCAL_MODULE_PATH := $(PRODUCT_OUT)/unsigned +LOCAL_MODULE_CLASS := $(call ta_class,$(local_module)) +LOCAL_MODULE_TAGS := optional + +TA_TMP_STRIPPED_ELF_FILE := $(patsubst %.ta,%.stripped.elf,$(TA_TMP_FILE)) +$(TA_TMP_STRIPPED_ELF_FILE): $(TA_TMP_FILE) + +$(LOCAL_PREBUILT_MODULE_FILE): $(TA_TMP_STRIPPED_ELF_FILE) + @mkdir -p $(dir $@) + cp -vf $< $@ + +include $(BUILD_PREBUILT) +endif # to get ta elf files for early-ta + +local_module_deps := +local_optee_ta_target := +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..715e8e4 --- /dev/null +++ b/optee/optee_os/mk/cc-option.mk @@ -0,0 +1,17 @@ +_cc-option-supported = $(if $(shell $(CC$(sm)) -Werror $(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..449b1c2 --- /dev/null +++ b/optee/optee_os/mk/checkconf.mk @@ -0,0 +1,183 @@ +# 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 + +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..b3d807b --- /dev/null +++ b/optee/optee_os/mk/compile.mk @@ -0,0 +1,308 @@ +# 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 +comp-cflags-warns-high += $(call cc-option,-Wpacked-not-aligned) +comp-cflags-warns-high += $(call cc-option,-Waddress-of-packed-member) +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..e45803d --- /dev/null +++ b/optee/optee_os/mk/config.mk @@ -0,0 +1,1237 @@ +# 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 +ifeq ($(ARCH),arm) +CROSS_COMPILE ?= arm-linux-gnueabihf- +CROSS_COMPILE64 ?= aarch64-linux-gnu- +endif +ifeq ($(ARCH),riscv) +CROSS_COMPILE ?= riscv-linux-gnu- +CROSS_COMPILE64 ?= riscv64-linux-gnu- +endif +CROSS_COMPILE32 ?= $(CROSS_COMPILE) +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 ?= 4 +CFG_OPTEE_REVISION_MINOR ?= 2 +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: +# 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. +# Intended to be used for testing only since it weakens storage security. +# Warning: If enabled for release build then it will break rollback protection +# of TAs and the entire REE FS secure storage. +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 + +ifeq (y-y,$(CFG_CORE_SANITIZE_KADDRESS)-$(CFG_CORE_ASLR)) +$(error CFG_CORE_SANITIZE_KADDRESS and CFG_CORE_ASLR are not compatible) +endif + +# 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 ($(filter y,$(CFG_EMBED_DTB) $(CFG_CORE_SEL1_SPMC) $(CFG_CORE_SEL2_SPMC) \ + $(CFG_CORE_EL3_SPMC)),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 + +# This option enables OP-TEE to support boot arguments handover via Transfer +# List defined in Firmware Handoff specification. +# Note: This is an experimental feature and incompatible ABI changes can be +# expected. It should be off by default until Firmware Handoff specification +# has a stable release. +# This feature requires the support of Device Tree. +CFG_TRANSFER_LIST ?= n +ifeq ($(CFG_TRANSFER_LIST),y) +$(call force,CFG_DT,y) +$(call force,CFG_EXTERNAL_DT,y) +$(call force,CFG_MAP_EXT_DT_SECURE,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 embedded DT driver probing tests. +# This also requires embedding a DTB with expected content. +# Default 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_GPIO ?= 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_WITH_STATS when enabled embeds PTA statistics service to allow non-secure +# clients to retrieve debug and statistics information on core and loaded TAs. +CFG_WITH_STATS ?= n + +# 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 for all functions compiled with -pg to +# /tmp/ftrace-.out (path is defined in tee-supplicant). +CFG_FTRACE_SUPPORT ?= n + +# 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 + +# 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) + +# When enabled, CFG_NS_VIRTUALIZATION embeds support for virtualization in +# the non-secure world. OP-TEE will not work without a compatible hypervisor +# in the non-secure world if this option is enabled. +# +# CFG_VIRTUALIZATION served the same purpose as CFG_NS_VIRTUALIZATION but is +# deprecated as the configuration switch name was ambiguous regarding which +# world has virtualization enabled. +ifneq (undefined,$(flavor CFG_VIRTUALIZATION)) +$(info WARNING: CFG_VIRTUALIZATION is deprecated, use CFG_NS_VIRTUALIZATION instead) +CFG_NS_VIRTUALIZATION ?= $(CFG_VIRTUALIZATION) +ifneq ($(CFG_NS_VIRTUALIZATION),$(CFG_VIRTUALIZATION)) +$(error Inconsistent CFG_NS_VIRTUALIZATION=$(CFG_NS_VIRTUALIZATION) and CFG_VIRTUALIZATION=$(CFG_VIRTUALIZATION)) +endif +endif # CFG_VIRTUALIZATION defined +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 + +# When enabled, CFG_SCMI_MSG_USE_CLK embeds SCMI clocks registering services for +# the platform SCMI server and implements the platform plat_scmi_clock_*() +# functions. +CFG_SCMI_MSG_USE_CLK ?= n +$(eval $(call cfg-depends-all,CFG_SCMI_MSG_USE_CLK,CFG_DRIVERS_CLK CFG_SCMI_MSG_DRIVERS)) + +# 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_PRINT_TREE embeds a helper function to print the clock tree +# state on OP-TEE core console with the debug trace 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) +CFG_DRIVERS_CLK_PRINT_TREE ?= n + +$(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_GPIO embeds a GPIO controller framework in +# OP-TEE core to provide GPIO support for drivers. +CFG_DRIVERS_GPIO ?= n + +# When enabled, CFG_DRIVERS_I2C provides I2C controller and devices support. +CFG_DRIVERS_I2C ?= n + +# When enabled, CFG_DRIVERS_NVMEM provides a framework to register nvmem +# providers and allow consumer drivers to get NVMEM cells using the Device Tree. +CFG_DRIVERS_NVMEM ?= n + +# When enabled, CFG_DRIVERS_PINCTRL embeds a pin muxing controller framework in +# OP-TEE core to provide drivers a way to apply pin muxing configurations based +# on device-tree. +CFG_DRIVERS_PINCTRL ?= n + +# When enabled, CFG_DRIVERS_REGULATOR embeds a voltage regulator framework in +# OP-TEE core to provide drivers a common regulator interface and describe +# the regulators dependencies using an embedded device tree. +# +# When enabled, CFG_REGULATOR_FIXED embeds a voltage regulator driver for +# DT compatible "regulator-fixed" devices. +# +# When enabled, CFG_REGULATOR_GPIO embeds a voltage regulator driver for +# DT compatible "regulator-gpio" devices. +# +# CFG_DRIVERS_REGULATOR_PRINT_TREE embeds a helper function to print the +# regulator tree state on OP-TEE core console with the info trace level. +CFG_DRIVERS_REGULATOR ?= n +CFG_DRIVERS_REGULATOR_PRINT_TREE ?= n +CFG_REGULATOR_FIXED ?= n +CFG_REGULATOR_GPIO ?= n + +$(eval $(call cfg-enable-all-depends,CFG_REGULATOR_FIXED, \ + CFG_DRIVERS_REGULATOR CFG_DT)) +$(eval $(call cfg-enable-all-depends,CFG_REGULATOR_GPIO, \ + CFG_DRIVERS_REGULATOR CFG_DT CFG_DRIVERS_GPIO)) + +# When enabled, CFG_INSECURE permits insecure configuration of OP-TEE core +# and shows a print (info level) when booting up the device that +# indicates that the board runs a standard developer configuration. +# +# A developer configuration doesn't necessarily have 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 served the same purpose as CFG_INSECURE but is deprecated. +ifneq (undefined,$(flavor CFG_WARN_INSECURE)) +$(info WARNING: CFG_WARN_INSECURE is deprecated, use CFG_INSECURE instead) +CFG_INSECURE ?= $(CFG_WARN_INSECURE) +ifneq ($(CFG_INSECURE),$(CFG_WARN_INSECURE)) +$(error Inconsistent CFG_INSECURE=$(CFG_INSECURE) and CFG_WARN_INSECURE=$(CFG_WARN_INSECURE)) +endif +endif # CFG_WARN_INSECURE defined +CFG_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 + +# Privileged Access Never (PAN, part of the ARMv8.1 Extensions) can be +# used to restrict accesses to unprivileged memory from privileged mode. +# For RISC-V architecture, CSR {m|s}status.SUM bit is used to implement PAN. +CFG_PAN ?= n + +$(eval $(call cfg-depends-one,CFG_PAN,CFG_ARM64_core CFG_RV64_core CFG_RV32_core)) + +ifeq ($(filter y, $(CFG_CORE_SEL1_SPMC) $(CFG_CORE_SEL2_SPMC) \ + $(CFG_CORE_EL3_SPMC)),y) +# FF-A case, handled via the FF-A ABI +CFG_CORE_ASYNC_NOTIF ?= y +$(call force,_CFG_CORE_ASYNC_NOTIF_DEFAULT_IMPL,n) +else +# CFG_CORE_ASYNC_NOTIF is defined by the platform to enable support +# for sending asynchronous notifications to normal world. +# Interrupt ID must be configurged by the platform too. Currently is only +# CFG_CORE_ASYNC_NOTIF_GIC_INTID defined. +CFG_CORE_ASYNC_NOTIF ?= n +$(call force,_CFG_CORE_ASYNC_NOTIF_DEFAULT_IMPL,$(CFG_CORE_ASYNC_NOTIF)) +endif + +# Enable callout service +CFG_CALLOUT ?= $(CFG_CORE_ASYNC_NOTIF) + +# Enable notification based test watchdog +CFG_NOTIF_TEST_WD ?= $(CFG_ENABLE_EMBEDDED_TESTS) +$(eval $(call cfg-depends-all,CFG_NOTIF_TEST_WD,CFG_CALLOUT \ + CFG_CORE_ASYNC_NOTIF)) + +$(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 +CFG_WDT_SM_HANDLER ?= n + +$(eval $(call cfg-enable-all-depends,CFG_WDT_SM_HANDLER,CFG_WDT)) + +# When CFG_WDT_SM_HANDLER=y, SMC function ID 0x82003D06 default implements +# arm-smc-wdt service. Platform can also override this ID with a platform +# specific SMC function ID to access arm-smc-wdt service thanks to +# optional config switch CFG_WDT_SM_HANDLER_ID. +CFG_WDT_SM_HANDLER_ID ?= 0x82003D06 + +# 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 + +# Enable a hardware pbkdf2 function +# By default use standard pbkdf2 implementation +CFG_CRYPTO_HW_PBKDF2 ?= n +$(eval $(call cfg-depends-all,CFG_CRYPTO_HW_PBKDF2,CFG_CRYPTO_PBKDF2)) + +# CFG_HALT_CORES_ON_PANIC, when enabled, makes any call to panic() halt the +# other cores. The feature currently relies on GIC device to trap the other +# cores using an SGI interrupt specified by CFG_HALT_CORES_ON_PANIC_SGI. +CFG_HALT_CORES_ON_PANIC ?= n +CFG_HALT_CORES_ON_PANIC_SGI ?= 15 +$(eval $(call cfg-depends-all,CFG_HALT_CORES_ON_PANIC,CFG_GIC)) + +# Enable automatic discovery of maximal PA supported by the hardware and +# use that. Provides easier configuration of virtual platforms where the +# maximal PA can vary. +CFG_AUTO_MAX_PA_BITS ?= n + +# CFG_DRIVERS_REMOTEPROC, when enabled, embeds support for remote processor +# management including generic DT bindings for the configuration. +CFG_DRIVERS_REMOTEPROC ?= n + +# CFG_REMOTEPROC_PTA, when enabled, embeds remote processor management PTA +# service. +CFG_REMOTEPROC_PTA ?= n + +# When enabled, CFG_WIDEVINE_HUK uses the widevine HUK provided by secure +# DTB as OP-TEE HUK. +CFG_WIDEVINE_HUK ?= n +$(eval $(call cfg-depends-all,CFG_WIDEVINE_HUK,CFG_DT)) + +# When enabled, CFG_WIDEVINE_PTA embeds a PTA that exposes the keys under +# DT node "/options/op-tee/widevine" to some specific TAs. +CFG_WIDEVINE_PTA ?= n +$(eval $(call cfg-depends-all,CFG_WIDEVINE_PTA,CFG_DT CFG_WIDEVINE_HUK)) + +# CFG_SEMIHOSTING_CONSOLE, when enabled, embeds a semihosting console driver. +# When CFG_SEMIHOSTING_CONSOLE_FILE=NULL, OP-TEE console reads/writes +# trace messages from/to the debug terminal of the semihosting host computer. +# When CFG_SEMIHOSTING_CONSOLE_FILE="{your_log_file}", OP-TEE console +# outputs trace messages to that file. Output to "optee.log" by default. +CFG_SEMIHOSTING_CONSOLE ?= n +ifeq ($(CFG_SEMIHOSTING_CONSOLE),y) +$(call force,CFG_SEMIHOSTING,y) +endif +CFG_SEMIHOSTING_CONSOLE_FILE ?= "optee.log" +ifeq ($(CFG_SEMIHOSTING_CONSOLE_FILE),) +$(error CFG_SEMIHOSTING_CONSOLE_FILE cannot be empty) +endif + +# Semihosting is a debugging mechanism that enables code running on an embedded +# system (also called the target) to communicate with and use the I/O of the +# host computer. +CFG_SEMIHOSTING ?= 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..315cae2 --- /dev/null +++ b/optee/optee_os/mk/lib.mk @@ -0,0 +1,103 @@ +# 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) +ifneq (,$(objs)) +libnames := $(libname) $(libnames) +libdeps := $(lib-libfile) $(libdeps) +endif + +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/macros.mk b/optee/optee_os/mk/macros.mk new file mode 100644 index 0000000..277ecf2 --- /dev/null +++ b/optee/optee_os/mk/macros.mk @@ -0,0 +1,9 @@ +# 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 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..5dd95e63db64fdbd19a5249a20909785bcf660e5 GIT binary patch literal 399780 zcmdqK3!GHdl`p)js)4paL_|fxq^o@eItez|yc}n!eqd0EV%tef;!Ic3T|kF^KNP_U z)r6TL6MqSeAjJ4+)X4=V_g?1?nX&Gep-D`}%w)cs8($=vSPkfy8D~BdQE8R*{r~sg zt7_G$D#T>w_uX&KudB~F|GoCwYp?w{`>eh8K2=vI`dZihZp9VR{A2#2#Y<|hTw1$y zVKiD}gY^Gsbjgw$2Sno)#)Re?Qynk-)qTSl{rhy(nA80}f2T30`|U&;`gf?=82$Ta zq^EwNi4aYG7p*j*)BSF}#e_=z?#!5w{QhLC3B8}+1CN@J{Px{yLi+dPeJ1p82Y;V^H{e5^HpAMD*{6Gfm_-`HdM9IfGx><&7rq_q%gU z8GkElOr5GcfAWGUyRYW|H@^vyHdFBXV8%>X@`Rai-6}KT_pUDd zZG6Q{kl)Y=GvVL+_e8mwaJt{mE;SR5gU0_RmTfb?#;-rw(%N@N&p>xeBH7a3)jnYI zkinj|#6U71YwKRq-j(Rc2m6x!$v|8HE$fqaXuAIPwFQX~E5ed+0aJp7Y+KuV)+PIb zj6GVA1CJLb=>vj^dbnh=iT*pfT3cGzC0p0G^bh1~%g1#jr6h5oB2Q~~*FbW^Kuc?) zqobv@BhlaQGFAi^k%|QQw2FkBCLNdaB5?|{Sdyr8!hvkMO1D1Q*Of#*eWsD4!5-r) zWFX8-=i;qPbhULPTe^FaeTjkg?k*!7*1Ag9(wXd36|XJX*M3_;{r0G6Bv*r7d||dutL6sGs${zoXkW1d_daKm3N=nN zsBU6f*RJF{p``q73P?fI0#+oEw!$>pS_&(-%9I2bOCY~O=OXo?AiFz*QhKydDj$%| z{op`*M@yowePCTnva^3JRcs;DXsRRczO(x_+c{f;zT|DmK2UeG_vffOl4}N9`q#DN ze|J~1Wwq$)tmdT>n( zo+E>cYO@fo2_Ym4F&kiK*ibu@{r!ox$(FYEwaI>n*}gGpT3cIN(4Y1t*P>askg6lu zwRXTJ18LdL+t&_u5B9T(clX`lDGgg+vUN4YwB1L`>W=Q#^-PrkJ$>D+NDF1sGiY_A zK~({Q^e!kHtCdwUpBHrKy8fQ-_ActUrFF0mT@6!DwwV&a#9f3=w2tREi$4se!_`Brh7}&VQ0*C2@qNGts}^t8Gnp zUrW!z1@nFBLCUtiuC+PY`#bSC#ux+nVG}_(xOc8y(_(pe#(WO3M|BdmVC0mbOlxfu zWk8|QG%DFZfo3Uv)dM0AIM-GTiR9AOfozmOb=KT;buN}NTgBSe&Md2J#b-cku>f>P zgFP+e#ZqL6=bkkj!uUGsOBp(I5uifSGaeduJ31!G9!F5^{_(@$VmM--CKf`AM#`%` zZls330}t?ibUGYt={~_d!unjVQc^;6WR{{>dgR6j6{?II+@Qu#SHzk3^=)g4%Gui8 zbBC)sXoPrB0b%4V%H%c-C$+dk6r!(JfT|mEmCiJ7ITA@u_7#i_oEFaL{ zjb{hM^#v&XN7rq>H|p+bVV8TlaNm4S!vR`GmmB2a71)^^Sl8W#R4|N34todN`;w+u zSXM_+2r4Zfb@tf-;@0lABs-b`bW4eT*HPo~l3bfam1M6?VgX!FO~eL)6?>Azz+fMn zRd-(--q!FA#|P`W+gp--ecgRt*Zs*FFQZb=&BL`WOH2_ls%-0X-KKl8n%gYG*3g--O~IEw`WHNU zp$0tp+WDH=(uRQ#d4RVIL%`auWLwLcj=}zQE&YA1rwe9mN`;{p2T@%d+P8KOLhXIT z-4HMs(8d>M4ofUu3&vx8YdX4b_oDmEk%ASErCOA|r(^3yFM%xCe73A>U%-@=0!h)C z*Z}r}U3lH(fJw!5gAQL7Z5Zz{w(1h(`O}w7*r6~Rf*+{l6H*9_J#7N6sH{>HtM;z$ z!2yoFY%u8=IKU?=dWtm|RFsknJ$&Cl$xxUU+WXh(U=i95=#;qfY`=Z*cH3z%uNo^H zX|E?~cATwgDL*@9u&_iu2@a%h?@RP>9JxA&2gi}jG<$Lp(mgSK*3sJXMvQqm@HCbn zuiWzVQy84Dpu%ul>|M994|G}e2{|Z#RO8Fu1!YG^q%jU7LCb1iqWvDUuV0=kBK6_5 zH5=D+M5oizxu#{XA5F(!_YC&+bmLL$Z*A4>gnrSkg)(<5#5u&$+cIJ6L|O5jf?Y~y zqN{xk-yT{A`Z`>NT<=~S@qhsxU&r0^)XRplMo6cPljvJ(NDVr)PoJvPv0Oklrfr=* z>ps}>e=h>t4k4_6R;j2G0;Vkr4$6X@vyPUa5+;T0g%2r;$c=JC)+NKIqalML>>Yy= z+^Ln*^Cm?J&Jt8a>eddv%I0)lilhW*8(n%BcFokR?s7dp31UZQA3^MnRhabXUEO_n zJ3wMGypsSgA^EsopSo_pO(a*WD1qx8?1RJ)J8cgIt-CYos(-4Gq3vi|AR1n1U9DH_ zT*CS}paPwoP86Gv^j&$e@_HdASR_=&3*HPyDzMcJf>2TR`Mp>H|H5G566{0m)0gio z>>H$30X>&UeliJX!E#W9o?{jI&OSfC36hP_)PQFtuU!XTl)rMTNi0iPcha= zda||M6ceLt&p!bB+pfXRmfP_dm3&|jW{naw{Ji6ys!=w)()w+Q!;j zt%<*AZ52}V&+VKCI4x2C;Oc=szH`0@9o{HhUQf#{xuFMnf;IBJrRz(!4Ze4>Z7`&q z5n+GtAnHsB;l$Ekq~STeyC&gHHoCLUYrYH@1-W7o_~kdWO?Caak_Y(c-`$Be{mA4&lZKb zBIulw@2XO8xAe*d9*bA_H=l%?ot)Qwg&=mik+v|6ISYW>tkIP!H`WL1RcOi1~?S>P=Dl3CaK}LkmTS>9GKjvYnI8HRe`~_+gsz6~bY7 za?W?=s$%(v_}#i@NWuE|Uz^;WpvJ@%7_)H9 zoMp<5`B+24Rna;1gY6w{ecjyy(FHXNYUb4}nHya?@5*^KIR=3%vMV#c7!SbqHd0gq zV?;q5UT!p#xE~wQ27KvGnVa@PU@H z@X}?*tdC7H&BL=|=}KdIGZ#KMD`vt=6Q7Tzrs>5{Ldy`UuF(Al$qM0>R1{)doP{2a^v0!rg=0nZM)ii2SO-Cb-v{~Tvx{GHnLxYZ~1_&W6Y#%II( z-zZB>&qU6zMt*>>&Pnsu2h3RHBdMk^^1c`8 zAkQhTi`b`(HzV~&O5;S6OcJtW)`mAQa`tHrs<7AkFS)O=E^eDy8=4M7?g@J zlX?FnbR=@br^eF9A{QPwTpvr9fxqw?37LhIA&zpd3Tb!O6X;LV zzlHb`=P>Hhx5LZlh9;TX@1Tw~OfmD@LF`F+`>W3y2Q zpo?`W16}9<_Q#y+i$4je2zq^*MyFW8t&+Lq=QI zGvV;kQPi2Ei(+FB&)L?LLA@XPyRSAKyDF46X2yaH>UnHhEIm?h(znk-y}!z&nUB9k z-l!kS!E(EFe0+BXb%G=%U9gd20Pbz&_2 zuralacWjvfj|cC~pdM!)cI_{2%)-%Sv2}c$L&)Dl$RFb!?e_V* z(u_q>Z{kx?FHo+TR@Y~}$u>FBEIeu3{LJbE_)%|^VT5fmGP8PYecAr6qKz5oep$q< z&p?+^f6cxy9d7W%G@zh9S5p|4DIu{~XQ;Amu)?FUncTWKy@kA9iUOV zUwdtNaXyqw$GIJOfxgoRq0_f2OzneV^9xfR+qm~^(>#FoDf%LBhGi}{H-%?@Y~w3$ zk2f>_)Y;h0p&iE~7eNmfR-?Z-5b^C6eSTjGa%4UgOUKSKwYZ4uuO&aCFGrQF+VZX3DRTuY@au* zSCW@|ksj+v^tJJYZ=#+Fz7sf}5!L?{XXan6zWx44cMco^~b8i4TPh92N zF55+leTnar(f^LQXNlRl8U3h18E-~k%4dl@yZL;Q=TIDREu8NHv2HjErjIhr?@OlvAj0e%@^V!EV$eZ$` zt~7HjapK+agImB4eZxWWApNLMk905EG-G2w#W@3g{V$%8hRAf(;~bCV`uD%h_J6OV zY+s6;XU7eVGh=U;;g>-@ny@66-im(jkSSZg7x%|OGh=3KtQmd$AEM8D1brUE4kK>{ zeR?J8a22j&(Z)2#0*5gcpnh1_qNtB4^iiV2v#3wxoq5jS*_4T-W;xw|+x8`+#*GVX z*cbA{n8!DeC-&>F<9sIXjng0mkI=>@Q?}uQp$|-{G;?r2)1t<#;9$9KYR&xSQz+SvW&4@|1Rd*V(+D7z=Ja(B4*xkkiz z)<&5cV+aFwhe>#S#dCGpz{x$hoBXlo>UW3h`OlarSU%$Uzrb_dRN>zZF`l9j#{oa- zX&&c`K;6`y`=>r|cKzK`c22I}RdLT*%lAy$UEXu=gs)D#`6oZFuQ>AD@?4VF<5o#f zcSH-@Ll)$)yL`{2uTH#o0{LEt2tWC8F3!|EDpE8tsT&*_V}25s!r?Pa578$#=ECdA znsV8I?8OZb_6YO<4mg`7$l9a+Qc5+FjwgXBu{e8>gD5 zo_^-1KdS}#t3K`za19+r?=O2GQh#@NXQ(Y3_nPb#X-;#H)%&+Cuy6{G2sj0gvn}8S zR)MUqVUxpc{q*4x6MTa==3*N*$*9+_EVqc^+i2ktF@-jb%RnY=MaNiF0>8EdehcvF zkbjlWf^9RvK39VN^Cj?mO5po}lmDY$)waz5`&J41XFdIPUj(-O0Q;8`^rt-is&ZW5 zu=Nn%VLv6a$c*sbOWY_?X)i}J#aIzQ>vHdT;XAi z$D|161Zecxb?DD}?&pMbGvB=6|U1gscrhAvdwI22; zTIsEHz-{5c~{{VDgLwl^#t(uMQ4!}0bKgSeF0qhG3hsi zkMvgu!Iy{N(l5Ohz@`5=oy8e*gNb=(Y<8Y!$&>3^*7PMhlTM1?{C^ZID0=Wo76ZoP z)(Ur)|GF&^qb-|NK8Bw@_ISc=z7SYkOvhJ??0D~Tj|ZRB_XW}w-d@deYd+$6{<`t! z`}AwF9NmSa9}VD=zMQW@xLj+}$Inpy8-09TSIK9@$BzaAM1PXjb+{;||ETYLwtGVA zpG{uk%Xpiz2a>QcGQN@b_&|!oekB;6e1p0tgH^sWZU`tRaBKU3V(}mK@_(Al)Des? z&o9i8T5I}y+tN8(#^cOw>5r+7JZ5EynW=aRo!ay_xpz0%t}=Lkv-V%uc1Q7Ez8Q9n zM_~VrUu2pSct0Gv(0r5c!F3m!g|un$y|dD+>O~nhZ^L_7*wo!*?WEI8?_#`Hei0bo zy|u0M)TZy+_p-2wJ6gPFzXF@;r$A5J0Btz@MTU#pluts=_^I(cn=%R&cHj%DllRuo z9Vv&M2k(sgXkP(F+wpjX>D>$4@yHa|Sb@=od^9ql`dDP<0jOi=$Yir{7&f((DPLs% zrZG+XsQH_+G~-4hV16|zJsuFr2YNf zO&efOh{Kkk^+$b*4ykLthaW{g_FCDTZM>Au(ayGSHD(9xJYoDsSJ?RrHnAPlgXTlt z#K`Mk@oxMOba9k6(->^mus4Mxk@Q~9SDZJ+#-;v-%=V_x?lAOFIXw=WVt9AG)gkpv zos0f5Vc5KAi$@*%-{Ac)>{%?272J9^ylI9$eWWE^FC@WSYU7;N10WkToNdk zs`k~9YvY2Jnn;B)WJIoq6?=Ppp#i^#fU~ZInP>3L zFb-@AjW~-gXiq1$8|PqqI{`a!26diuIkX|#xt4QHGwsByQU0`Zk7DkHcA$l@5ii7C z%0s_uOpl_jBv4mcVDlKVb5W)`0a@y%ZC|wa?Z)&n=qV0-8QRtm^fSD%ZY%~{i!sP| zGs2MX6l}?8HwSS}k6^BXaE_$)91?g+8;wAwElNMfpr4~& zKTMnTgJqFH9;xRj+NIWY6nUer>%gD+`ZLfo-lI5EkN=Ib1OF$SnIF!<7_@Wzc9@vi z!8Q*Wn%M5y=7;{+%~>)o`8)u6vE>b;ex2In?0FN=4qmr&Hs-*g8E7kPXRz4~!*;kD z&wvE#C+pvc?c2P~)6SJRyIc6({CXN^T^Y{VH%r-1+1G?lq7Jj};<*sIt8T3BSL3L= z*dz$gp#N9rZ@4gjRd>7mQ5P?OmS?e79!DKNhUdr2k+N#cnf&5XZ=;MNZ);$qWS{#Y z?7Or##*x=l*c_aMe7ubIwg&BO+)P|QihQ)fM!6aFEdjb?;1z+qo6+WC2-^&~4?`yn zuw8COxwXx_W@8m_$UlQRrz|!MbZs-2Z)AOCn8=B1tdMJ88%=bq?T*%LxNJidt~$x+ zWrNYduKvNEp6MeWOS^mZ)LCufIsul^iX?144cgwbcqnhzk4dK)J!@8dz-y?~#A5p^0fi9_2^ zx8YvKbUhqU)lFS>f5ii5)!$vdb5g^uiT6ynZck))8BB@FG`fm`4BK6{CqnA*jkF2o zY?U87J^2l!p8N;T9jPaS>;2iE;icLutWazXYSp< z#?y*SE@t6>lKn^87@1-*Tb~;$dqaQ{ivx(_Zx`efd}A}l@hQal-XBu*Vn4aW<5HjG z{o1_~O|*KZ1ln#8!9y>2xOC4dVe|Aa>VZhbY@wJNGPK>vVe2t&ZpKe!lrWxGm%wi; zfq%IK{`C?#1}8<+{ay+Dxf1xlmB1$=tIV(D)3z1R{uc0J`JG<^UtR+LYze# zp}JeVaK640SJAZ2q zyUYWU_`MYnUo*|wkZE7WN=&GOR%DR5d*;BIl^;c0;6YoV>kHleh&x$ay_#pA38bIl zX?Uu|JrCl#FMC?y7dR68Uu=2jAzb&$Cp`W60bFd&q}RP;IiGzvNU!lJ9;ZCg=aMd} za4pXYh08OZ^aBdl`I3Hw{4XM*KWaHHz(IVLyR`prEps=-#ePcURfYeSBeDOlRyOMo zD*R4`S1SC7$AkKL!Q(;w99Q(bw!*n{}R3cpL? zTL0frIG>qvJm&FWz8?2@Fkeq7dWyWlGx~v|*Z2{S2lLh8ZTIvyy-b9`d7Hv7SGbg^ z*sLXJpT7`XoAI-Z{zOkrk^#Pu;OIZOWE9q{lNZL0r>;BC2j62{KK?|!l)w{-#^Z?tGM3F=Du{{ z`}bcTuF44zvzN~1o`IdK0d}~DzWX(6-y5QBfPSH&?TezY@u6ZI48!lWuHuVLq0jB> zqs@SJ7BlU^S+pI94dK+LL;Gphp-qSW@S%(0%kJzx*2aq@ci^{^^rto*wl;UMF^Ii~ zXZqAO8v4|htw-9;DYIpI+}m1PH+*n<6k%hj{PX-{%iR0|d;<@>fjI{8i+yaifn8>X^)r1N{J)C(i=$=-{ETi+yhi`CYyw%a|Je_>8uf+Cee14xmnoI|LE$^4fHx(+d4IXZC<@s%GV~ZEs z*y=uw^$C7{;IBdZI&5t833ugPxSrrmlnv)%IG;qD+X(!CY0HaF_3H`FHVfCl&if*4 zXmb!oTCOX23w0ziCx0Gj7t*56>1&-qTcM9S@39u7I*NIPqwo{li#o{iAx@umt`V?y zS>@ZWG3~$4wE3eg9Ch-*YUqt~7o+u7e>NSAzZQ;0EgRM=E3%NqL!6 zxS*`6E=V=K;mhDV(ES$p`AeTMjJ~BF_S>VF$6(%u;PXF_ol7dzg-+)s=!*S_wi%C3 zbM<0B(n(<*0iIq9QdmFm_qfl-jTXu{IyoofgP?r_Wp_W$NmUnZpM|)r)6$Xa6VC0qdSec-|M;_Cx&DJ~dN2Bp8EBWZp|8fg2iFC# z55ZVrJ<7BBn4f!~T{n(0`2uYAoKG145bX6IHe;F3qCdC<{Y8smJF;yabPF>rZayKe zE!y=U-?M!#_>3I`5ArL;hwCd|QaZ8iGZW70qptci?OvtDcK9=0Cg4#}mS|7XcAq*8 z?cU2l2Y$>e*A*4hKi6|`?Uk$xqbT!H=$>md{u*-CL*`4~)H=X(P3tSM(AE14^zf?JK?brHnH_CS;^>n&Ke88X zkZm08_`Q9_^}GqnCuI9Cvy*GPvh8amUp7AX>wY^YALm6Vr+)Ub%qT18JTlN1pV^$# zLI3oNM)bpN_~E(LoW$G*`;0?q3w4+a;oOHoJ||)vvK-@(2^fdGXeO*rpqymxqYl@0 z9s_-L6|SXC4CDE1+k(ndHV@IVY@M!ZEK;XcoTo5u`8VW=b&$H(JaidR4?_*Px;hG4 zsjDvkx#to4i`Sutqj>(g^@AZ>N5{v_(tA&#p4#?}LXb&zL#4J_7vm+m!I z(RON%RzypQP_G@#0b(bK)Im!C~6h$r^fGni*2>uH|9o@=B% zN#12K?!W}i)M@vJ9|&Flv!71oEyI`a0>>@mpkVz(1D7B)a*;wi zCiH&%ljn~3)f|)82JUYKk4Nz1frlXH8fCqPUk`G_?r@Wy^bD*AY0O&>GFb5(q?E*N ze9l}AmNM74A!PZ-@1OF(mjo7oxRhh1#+9W-27$}DD4`Q8~ywy{U0Ck{7*RkcAZ7z-Qmv)?Mk^o_#FJi z?!Cd$=k(RMtBlJ!WUY-YdvBqYh8F-Y;M-cgSXVcu^#t&ZdT?q?(n#@GqJP( zvB#x-UF!Mm@_5|ei(U9(k8kt1*tP${o{Jh6S57Z-% zpX0}Ti7i>^8CGl#+3DvupF@5N{HHOIz`-_L45y907*3x7&XHz(UAKJ;cwSS2{u3qe z_7eD=CGedk@UH`>JTXoX;E?{|Z%fcW=jlg$m9u>h;&E<^d`7&jSNhIL$Y(J<%qoFb z11FyzZ=AG!5BN8fpub7zy^V7NGl65E1pQY${cE0H`k(*m@oD}^pOrc9shOQEE*u8T zYwzz%U=thvVCF7v*l-V<$6{yBdDx3@0AU3WO}D$XA0*^vpcmFGP;<@;mn_kDi}LOk z>$&RM#aAlI+Prz}h4b@xURk3k7hbtY-_4dxtg$s5}R$2B~HbI@^%I-K(ha-jzk12ZUC(guhG%9+H>p6F=pF0&F%|E61X#6fkPyX9&sxS&EdW{cz zJXkLK6d%q18;Xy{4=Q@{=eUo@gRX6BWJ2KjQIVx=$$lGS7pjDSjM7dX3Nacu>x$$AfY%QS?lz z$Cu01ieBR}j|b&!Q+%}k*C{?4?@{#RFYQr$RHT0s9QzyDBbe@X#YgksSt8y06g|_u z#pm}CMX&KkJswOK^Lbf$E_0XmzxYZ7^}ol{2lbD+M0=24r@K$lYy44_u5OPf6)rj> zoKXCA z`JPn#H9p0Uk42xaczI-QXL$OcJWCWG&HrkT2lddX=$YRUpYBRUukl+w9!&S3 z!au6?Abr008cERA{z7nhp57Y3U-S3-0(izh=j6Rq_{e+J3ZDv8AyD8YkdkyQX_yrf6@B}MFY67lk-gomupSB-^bS&uY4*NA&Td=2E3+6LN z{e27epBwVmjKg0BJ{O#0m3uwccns-Bkp5<*KLXxQA}-g3rEtx4VZwJa_(Ji`n~}C) z4`Y5&c*%cz(nMu#JW_4axi6?v{{&C1x2KgRT`gu_4=Ru{P2fcnC zRQlP9v>sIYdGLMeXB6p&kp422{xX&RGL`-^pZ+qH{t(h%rqW;bKGPTdLD#j^R|@(n zr7P;J6?3zqvqunz`Z--3nakzc$v*@Ap%V1(HFYJ=6g_7}O!|lcT=O8t`4b+uxRb?V z{(6bRSm}A_xTrt&(Ab?GyVReV#&&-_$De2541L%`Fn?S06axAmIfp`d3VSjOqA&9U zAa`s3yGQYFzQ+~UAkc;^hv<>dPUr3E6C2-E66yx(>O5oorfjaf%qfBYP6>Qf34Cn{{PVzVc|k57(ziWag8q9Y@RvLv*@H{^z6oW;^L0rH z{C9v;9*j}!A$)$n1pObBz-4`5?z1O$3plJZlxYMzFJXh-{77!@pzt&F_QR2!?oh^m zetIJS`EPUt(A;|QToTxdEQI7B5#2KHH^&vz(>Sr9b2IKhGBDx;y)w z32zRt$V!Fl*K`?okdJlD@^oS=Bko^|ZAe`4(a+lsg*!hD2lOahy;5e!w&d@|mX7c- zMSs4(=4r%VlV1E&2tA>2G5-*HQsFcGHBUcKxb`yWrcVeDraRkR+W#_FLtM{w z&QSCpRP-wp9##0Q3a?Ulhr%yb_y&bvqHwW2Ql3i{o>KIeDf}*l(;g;=*s96rLjvOb zq@tgz@D~(bt#I*mBA*W{{G_7)h{E4h_(v5kh8psjr|>EMxla5Fg-=s>jl!>1xVF2& zZeb7dxl+-~o_53+DxAJ3JcuuHm-hd#!j~xg5rr>RxYQ-F*bB&OjQKmOk==! z$XvO*D;!&vvN1pDJI@h}Q+d!9$aKnigG2fnwkhJCj6wF`c)r--i!B?(wn3i1ZhWyZ zOMMc?l73VGf0p#+Tx!os+0!-<-R4zeH{yo8g4vb$k7;6Di~a<@4i^}bo0tIpyv;vc zM*KbX&uJEkFZwT*Hls+n^>E?|2TlI`1>={p@zyW^hs^1_JC|3v=DC!OcZGilep(ab zTJ$dP6<5AL8}Iy@rB^Pp*5EVWvvP^*;A1vnw|+LN*5AnfWM*1yEXH-S*xL+mRZSq@ zncZIu-{2YY*yibGEPesj=wQ7N)~Fn?bXbRo3?9tV<9@HuW6d1D<*>Ozz60a-Hq&ct zWG#?k@xLe-8$0jnw+8UJKc?7?afPA!y;+y{rlo+kWQz;`{xiZ0~`4>ehp0U z+Zv*uXhr#AQ<2k8=B$~Exh4l|bgElYvEE_mgL>Kvdp%`8pL&9=crU-31U+36GdrlO z<5+K|bu|oKeRE^w&4bX_gW>w#82IGY=(ulbG4J^8F!92*t)U+|9dK{FoDN+)%CQh~ z80he{JbswdBl&P`RswZ`*Hxx+L4x&3eIG>g5}jB5@BH;qqHFSy?}`vR;`RM(R^Pex zPF$CKB2recudA%P-hg%J_uy9wVIGqiq{_ zV{cRJnfranaA+85V9(D(dra>->;*cU!hW`>_uHoWbn(qOrc0fC2j3;a^JRO6b$K}C z+p(Du*&2I{>-keC)2cFaF6U4Z*wd0akDZIY4{`tO-tgQ*=-cWbugE!!@8&o;&#`ho z1UdOFDC!4kG#^5{tV5k({z=~B7jgMG)a?)k^S_M+b<-})u!|Dc1B zUkdN3miL!HLq3eh{7@&%$HUW6wyDsL(8{VWq27$KA0husk)H5B3=I1vSh+Z_H*D%| zqW)Guwh`?A`v_^ln|%4Lqs;hMEbV^e;YHB3QFh4r-w}4GJk~q<`grq;n3FpEF1{ZG z-9TR3KiGaUmA^JQ)aKeY`v&NguXV03VIG0qN}i^%m%6_eb>$HDM~n_B>`; z{v6+k%Ec>OhhK&Dj0oS!esqQ9S8w;iq>NVYkUa%_c*8l_Z>0rqs;vc`2DsR^8O~i0k;)vow@%&26LmbN5z}izk;%fT%UaBLyI_;_zSFY zEhZz=G3BWyeydEU(dl`|PK{$t?}gRxa2-6(Z+3rtF3*c9Qj2-!?~~KFEq68jrSncWTif?r;d$LA&JgMA2}=^SgZ-5q{6 z$BTPHi%u>!!%dxDC-F&KLw#X2&hy`aE-uEN7(dx~j;#|Hyz!MqZ{izltamyuTfvL_ zRv7Hb64b#vp6{EHkI&tO?{8wPTzi4tQzchlH81%Np6JB&gAw!x7gRGJGDaB+4cUH* z`%vikx?e06w=O)?^b5$WugLRaJTpGC>FnumN6wy`ROz#hp5@d36!0zB z>s*gBZJWcs4U|Ere=%r9Zw7U#SRL4_>eB_FCl879jO$PAzU$m?hV}GpPZQMhB;do? zqd5Bxg0=nZv-mzVjQ+`>zPayLx_1V7$BE!QiFI)ZKctIyB{MestMPB5joCgigR}Q> z@$0|4@mX(t-KV=NyO_JZ3u~>r*TNLuAN}Y@qn(3TSPd&mPe&3fz6aJNutK}Nub;aK zyWYYj3Dq`D-WS z((#t;(_AgEip^2Ua`=HUBgr@phtrReS(eb;BNZpmJmHjr;%L>zWbLcY7m@B86{exFkNa9@|(uDgc8yTbfJ z;|<)MyT0NX>?!WjS()9rd#WWPk#(@k*i_)_!9vh$^s(mro=C&)@Sf0ZkSw>*A7r$X z&Sai&Jj#Dwz6K}2J)suFkY)D>o`#>y#V{Ejui$s9@NjA8zSX##Us|MUgvm;Nx3P{N zQ@qiB8xcDi_@Ml6F3Oh~um4(EultDN^G(^Pbh|T;>+fxSx3sjAdxNgO=c(FW7vh{>A|DP$dDu3Ab0dDlAN6%X z=HRF&;!$=GIBflNmq<4_!yxGv;(dst*YR@@!y|lA<5&S28#@%M+a{823;{$Pe8NZP2 zIUS}ciml^!e17wF{HKr{+jHp%laiL_uD)kFLwz(>I1%9g3n)i z`e}Y{&Gt)(`gbMh0}o*LQO>|a+4+yaO)LA9%^yqzVHryZ8w@#HvNUQz{gMTX^8|jM?o_zulT!SdU!lj^4toUiyUpXlbZ4Xg z<3aplcWM92egwh%%D67bUwk=4Z&I$ec>bav!P`{2RVrP~%h)5B?p=zH)`RR{An6LL z`xL!@G})kiCDMJmM7l>5AD!;2ik|%Cx%Zl)*Z2vK2lb!v<2~XsW}=|-JR^RomE8T) z>)W+FGyD)VST47CoO~`*d=4u7a)s+}A!z=3ow>&KI&+P8_@Swki`3Tvk4t?Je5=QU z`qAsmsm~1Z!9%Yz*Z3aA=R=Ov{(n-*qvh1!Jka>lik|#$@#((cagkr}S5&%HD&0AZ zj3Zc|KjQIVc`Z@&yp;Yfrsy@k(&ItBtyA2b=h zeFtkiF8Y!Brq|(91i_amJ|A)-*#9w)2j#h?!Vv}QgM8mOSRZ8nPLby%_6Vl?h~lH`$)k#%`IY|tF-5QOCp{iax5GOQ2h;8Gcrd>Mik|$p`+hT} z=rz9G$?U*w1(4zGQ6$Z{B&<}OcW5qBZ+1zv#*#@B6tVUL~5|Hee^|J*-G zSI##fNUn2K*cZUZ*BGyZv}-&Tlwaca1OkHcClH@Hjp3({auzI(5&Pe*_uxE)#20%Z zc%=ab7*^D`I^Pzw5psgKs=TH1{10`d#3A%5nJL6r*MO{D$;6WH^es>OaIc4qk?j zjQ9^6t}X6YT8tO!9v=mTKC27xtq4D7{xs64ls)gEBiZjh@>sq7UT}@nkd9*IkwGn;DG5J?pu5y^c%y8Gozy1KGPYw`ct^ zFE?cu`K|2mp>p3?h#WYI{9KH(g}>YZw8HcR>?Pj{zv3bIG$5Uw!zha(_%O) z)Qw$?@Wg@o^tW&Le}4JUU9bMK3g13Y90;cq*qdOe9==t78X9vxsLnSa10Rlev-->P zA?p#9bh>KW>8bHTSj zVxb+>QC8P4!Osb@F@EuHyJ(*;zX!k7k=cpwQB>o5JXS8swi@-X1^#j)r~~Wpi`@rb zEchrr312<>Vexw}qtIs=boU0@gw-qjWirrf>QBSz4E##y%Y?B+b2)ynU-f1t!58nI zaC&q)d``;14?dzlN86)+*@O3n)BMIpOAJ1G$m_Alh1P#7(PVbS7nmJ?1m9McTkIcp zHSs$Y@{N{%K%9FJpZ+}J&!)do!+d=UG?35M&6nUaP5;ke9UFQ+r@OyU^k%q-Kj70j z+CK+v<)x-Kj((tW4)!R4u9(Na1AY`b%s^K|$Xn`xaC*F%GhW)8Q0v57ck`2&RI+RI<>KaTdnZ*jBT&|fc79!pQ(Nt#8<|+&6}>m~vs}E8vO#_OEA| zgFimkEKL1LY|MW91Uyh5cCx;RKN9OazkzaU)Aw!PeF*ii3jT}ayI%YTK_hic=)lMI zc_#M_n$R!ZH+fjc*glyS`3K|jxuIov5#`zB#PhR>V_%BDwd*{G^FcX;w|HO-`w;->h z_`Qs8cTtYFP+l)z3E$=^=HTW?S#J#WHNNSh>3lA*9F zRsqXY;CiZAnwf5PTm_%M@#(m}!0dPdb!HU&jz(rzQ`Xdl@Q~8K3P6Tp+oo=9w0yR??zs9 znUSs+7{apkAlSFmy_)l5WL)~rk#{T3yP)?VzuyBsYW-JdRZF?mooCLCF>hh>rO)6z zeqGg)cTbMz=RGp(!E$drQuEoGvPd4DJ!{+0j zdZ@%1)Av~)JMQfx>y8d#|DnSiKg`5)5bd4c{i#D=^J{(g2hU3>kG${x6#0fz=nYqH z8OY7GB|PgjNykthjz=QZ%lvnK%J7|^IG)!N@SUGV+ZUFtufy7cQ=1;&Pde!{&qqE! zG0hzOGxUp3pnrY@{qrHLBiIZ7Q}&DO6XWRHU^C11iR*a%t2*n$jK13Tudl=3xh~oW zzvu7)?&EYA@!KAnwj*|FW4it$jp<{R^gUcQcgtO7ZptiKwD;fY(p(p__uoS4q3XtT zqPi@-EMT(;voKXbm#BQKkDRnKqTe7GW%{`S;R zdNbBe>_s1)TF{t|FDOfoOb?}p|Fk|maxu>6cPdS!H)@~TWxd0Yn|(tR=WHE{75e_x zZOrMK^#kt_GuV&r#d8k*AI3)PU!U053P18JpHv~AP?__Uw)+v}^QkRntP=S$@KcRbH}e|pH{A^KJ%W56M!w_7?{|GY_&Lt(14gb3r5_5H z@7ViLJ)WW0?C8C*$j5Rv$(5y7!KJz5Wg2eWJ^MI0qhh%NwFSgR8NT zIlL3sMmv&SYX{chvqXb%%^OI1Z$9@jmUHsU|AbHW6GkS$mrMul=t)*UK6?be#e=l% zr+7SnPWYboTSk^n++){vJ2AXNXE7hu0KIYpRo;z|t})4J;lgi0dAu{R79N}GYeuDf zIn_6e8kaX+`^n|+@eL!buj?DHu>xp?1@+}=vieN6wynd~AT7CkIz3xlrpWhUF zTos*DKiJ;U*4GUe-~}}cYUb4}nHya??@D}^!5`E7S?})_117eTkI?u~H+9wh6%U+M ze|P!LNe#Ou-byb&=c9OC?vkI=k+0pjx%gW>?}I#hU&@BN!#9A?es@QIOXpIM+~w)5 zebv*$KXYg3(~R*nUGA(ep5+HxI}chH{6^9ByThM7%{Pj=DxPbYygctiMK?T$IPvG| zcVjTa{K~w290Lu=y*+gQ^asvezH90|XJ51PoV%wr?U}rLO5MF@eYGO_^iy@#Ww3!R zh>#DocTd}S4oMm3V--(7Rqul)ugqO5vfWemO#W)cy=RfU9^{T696|4!^tJM~?EMSR z*O9SMul!p1eUmz0c>Wrm>w;9*KmAmLrY4c%4PKK!@zm4wtbG23>)(U0{`nVj{DZW0 zFFZd7Dw28jeJnrkCy8>tS;|?yue1ljV%vKRx;EFlvTLB*YSYdMcTc?i>8I#jX>~by zr6@J~m8tv7ADDzvTKU}ar=G6Ad*aRsE1)sa{bYhu%`?yb^k?-`vr%@38R@#`>fo#S zbRdi&&=sXFd9eEbNBVFw;bK0Sc(&v46WsRN{hMJ=lq&z=17G`m+I9=9+T%4oinN`@ z9)Hc_w#@6iRqkZ|5NGmP z=es?=&fmNI8?)ErDUV;|&;Q-y!~TA{KYz>PkNJD*i^o6U$8>*a?{fY%KlXUW63lZ_EgG;vjXK;jGp_h6vO8Or>~>5L-8f~SPA-1mcUDWi|G$a z(C_l;MtzmGeJgVI-%8N`T?zb13H+53_&dPu{&qCl5FV%NT=c~IVHF*w| zSLTH+$h*sTwp^rnE?KC*mb9csr@mzIA`U04$nu#Z_kp84=SGlVjDeLJ$yWPuADqN% zPk*qe=zz)ueEHO^d;m#!X%9dSk_10(8Zx+|jO!9DjF+Di1Z2HJJG*a7GQ(K_*~;E4 zkI90ZlFhtdMd>|o3qFIbH@C+(*xd23)_u?Oec*)(eWea4@O`{{d&9QQcq;5Gd# z3fJ_ndYtLb_SZbgeqEBT1eJr1M=;$f9+z|-721%(b-LO&QKuXC^uf7#?IWo9q)PDL z>2Z;NgBNIzqNjcYzfYyB<#|l;(dj;}_-OnIMNj^>_;i1u=r#U=$AkKha{PmXxb`J| zLg7(M;r_ucWshLF9QQcOMa%h$qNhCa+my;AxH@DiPQE)Zetx@@QW}jo;<@Nc|W6h_9ivQ^Cd8FevA2?~6h_s^nay za4lzt$AkLp@p!Nt#V1eXl>Tk2qNhFu->%Zt?Nof`DCgx$&Rfgf4e<{te1pe>a^C6j zpqyJ3J>{7Lemw3{^cug<<3W8st#B=;d~+r!f0-Ybh<;)|-ExmhISMY{s3D&@PDJ~E zw&J7fNmTLC_#8#gd`Ukp`*umXf@7}K9>M%Ru5i9<$nm7Ys|3XPRfX&FI^pqPd7bol zu)K^PpNZaX5xsd_T{j}h(d0d`*g3Ei)Odl?|yqB!-&qu*izWxmaaCtxY z&*ppgiZ4IW_cXciXO3O@$cy=VIc@MS$kKnXno-5RJIvY>S+|J$VFIq)F-Hsp0{F8p zrY!mqT#@Im8-G6HlIH^a^dafPXC?0t`2~(4l-IsGWNBZU>MqB!h`W&Z0pFD$Q56CR>2A$sxFc0dAcA8@GS6xCbuur;E z_J1(`6${<&kx_rVm+#%u1+qWonfu74{?GlB^ySR`o8>x3WlUV(sOumt?~BzMiNDXsu&*n92xJe}O7i*DIA4FagKqm)=U0{WeXKes z)pP=L>Eyw^vUnZjk;MLY;wzb$R?43?kZ#t`H0S4eqRj1c_XhS0q<5M=L&LI z|K<_;Yy0~Q=%{!2q*fn=9^fCfn|Xc%IQ?1}CwCTJxqQ;c@YE*f6P~ZDnbih9ypqql z^GfSV^Pn%M-g^;yCc<|yy#Ec(%*oufkc-$2;(&`%Hv+n&tEKfvi5zaY7&NJ_9=X7Fu6Q=z0wPk<3@T%+#JhSgsyA zT~J=($vxV19T5LZ*+(y5Kd4J1IsFV>aC-f44>;jN8IPmOd4S(h@w&)%t9)2zm)5n!hd#}< zUAHAV+S{Ua%Wsat@u-e^MC$!(5naKvGfEsBoW%!_AJvZ#&6Nt6Zt5XC=2^*s84e3OpL<#?lDVRiwwUor919AC^w*1mRp>=td!XYTc-= z-CkvTEElXP=2`pc)bE;j&xFR^WqTrRh?Lt4Y*p@N1EL)9@x2_m{k-bApI0My-fG|u zT`Rs;_Sxs@oAKkHziyhRqNzjYm zgL^5$H~reor5o~kYj&%?m(O`J)LyAQ3u@=rDo=*mJWqz&E46<@?ZO3`a?t{t)a`If zP4cmV&RWt6`XtzgMzQBaYb(E^*MZG6CDc6~PrKWZBWdYO4y@~LYjN8kC0ct2+xwEH zyJsK?HwpVNwqI-OgCD^_a&2D%>0k>@KIPQoO#}`^16hC46iY`uAzZ3{$EA|buhTr) zxT7bYZY85K5RYbi(Eg6S&$GuiegzWLC!lPN#n5R8XJ!}0O@i_IV z@r|Po`A(VClNCO1F-1>#1aDO7YI))% z(rr_Gv>w(edh$>CbY)&i>Y?DN66rpva9!Vi=<#5EJL2(Reak35y1t432lcG$+et;Q z>)UMqJRrTUSC=YW*Q<{xJnD78(@KvA%aPy7g8Ah3k6qg2Hvajw@W}>x9B(tjY|ppl~>-H(idh z2UxHiv85+m#^ee=D9_rW`B{z5s$}x?qmd)apem^+_#fkd_19- zapmb|dNA-w%qy7g`M-Owni+vtvEW#reJ`te%{bPqg_Q0M6_V}hdW&cZj0a%a8t408S z{+5p)4d9ZloJ-A@|J271M9<1C_!?Z0S5W?pkH1F}@)3gaCx90#|3`ge+~DKA-}&+l zzEg<%f}H|B?4Klk={rdlEPEy?em9wb{DE6jYEEsA@3ec!OdY}axjD6-^@%gstEP6z zk{UO)e&%y(+hxOV$Pu%$$eda_JBIGP!E3WA@3pjC?+e=R2foE+HdNjm!?)Pp1>a0$ zb~T=T+v_mrFp4>e4Aw$JJ)9%5=TX?{IUh(I?;D)UI&cDUNE7E=8hEC#=Y-J9IR<`? zkDJTm+?UKVaGko??n5SeQx)=`z&d))Q3UBur7yw#iZW_Tp z0XuQce913wjsp5;y?T>#N6<0nJnAt=!Fdarrx>yGhnx$UVduIIVJ`FAvl=$;L%kUG z`p=drz8S^&j2S4;-F8mR&sq5SG0yA6>>QGtcaiuh%!TIW&Rkf^%?Iw}8flcNn!oh> zDq%kcr^{TJ+w&zi$MzEHVs>6_x|_>Dob6jNuZS~$tY-zhM=^g%dBSK%q@mpWZY1X& zf66m-{=C=gsZIYg+kQC*_d0Zn?~S>+IP5j?Cg$ASJX{&(;U*jy!~Rh}Mmw>3ZiSw& zaPx3c*6k}|V=tquUqaa*NB)jM4t@)cSV>Qwld1D{(N( z|B-Vb92?|DdiKWtn}Pp&PD5-d3@kQh@?jgxzo^*j+`nRTAdbFp0L(p1^&E)2$2wWZ`g;s>aVfHPE)AK z2uweq@3ZUtZo_iL_WqXcHhl5oG+#R?W|u#${r@+!?swgW(Qym&lAG%Ab1J9nv|CF} zZRAakIOc9%LaQs6fSMWC1fBTc#Me?>=l9F+LB{voDfE>MwC^%V}2h+D0NajG#QXDtc|Z z(rf*+9$r)Q8n5*)m6S)Gp_Enj{U@$%S5JHTpx(4?SnDmL_-nms+pyM~whe2&P4VqB zs5iYfQ0r}`rw{5)+nBZ9u2%dtE;eA=#`NpD*nopJvjNYCHZV=ULE+k#cBe{L+sKC% zuAd=gzCQ|-OCTrhr(0RG(J<3|Iyq$}r}5H8o6^sY11UnyJKb{~IF zfO$~<1QKNxiRr{~J>qStagVe7+0G@t^sQtc)E%SD@tuYAi?pS&pAN<^WlNh@K`zGZ z3dkS0Eon=Odizz6W0U4fmbPkHHhHgSv8Da( z{-b#Rwm!l5wlAnk?o<2{-c_@F^RO>w&X0L- zw1`ioN<+WPGri+JKdsn<^?0R8N3ef&J@y5)dnV#NKROZl_418IA_tE5yR?{h+TYCh zcyp#QmKK@}Y#4HVYSXv&za;vydnZS*KOcOEt-osMz|lw<>}+m--@Vw=mpo~UOTktV z$NsdN`zn?i?C&@nHt7+B$6pSmX(tk!LGYXMFCh%AGwbU-bV*Pbg>m!sk@LT&t<=g2 z`C+T6{>uyTeR=G!96itNubi1~7INR@k(pR$u;GJ!Rrszt>9YGRe(QR=p2$(N)!t(bZFAIz4Z)rjgMB6S^>F%VIJATN zBq#hH#${%E(?jqbk4?n))xkHoM>BnnMSsqo<@RV!dEP1RAL+06(ym$}ovlb`8`60h zwwOcZvEEVG>#9JTfxdhmTYpR=uLxcxvMWldpU%4H!N4qbgmp#Gt zASGmPgzTS&?EK!mv;XCEB7C03K8xI=xfG8!@K^yJUk45HW!oZso6$FKXS?5uwi(8G z^ora*&i9{&-=*MJ3x3?2ImfSX59!hKQ%#hOy8Mx*#ooZM$=mPSGi~X6hAwh8#?OOR z@25*S;n?5dqbu!JqjCk_(Wa$FxGxB53Tpsr(59<-*#Oc`qR{p zm{#I*@g-Z<#g|l>@O6pLMVFW|vtu*b1oYj!`pvp@6zMRn)nV+li9Q0h`{H}V59fT% ztD5rrf>Gox81FFj`me|@!~VseNyB{=f+KeP8|0b=YIw z9B2bg6~arPZoP|20Eg>7ZrIsd4y00 zqfzXG44eD#{|Mdjn77@({(RZ~qmw4jrA#uXBmKYJV{YR>2KHpqFzl~v-2cPfyMRY^ zUH9U9W+WjH#xjV9F$p8UHpq@GumqCB4M!tk%Ya`X$4=r@GkSoC00~LhGWeDeki;qe z8WF_P*a({>NZ0+>H^B{Ror`dMQ`)+%>j&UR>X874)V_@$*dPO$|L?aSGkcC^FwWzD z|6kAd&75=AS$plZ*IxU*_S$C8fw`->dd^$ZzdLYMc@(~QIk;Et-J;&Je5g3hJ}foQ zZPNKF^nhvoN6_N)Vcfa4@=M%pnREa~I$YBs{{O;v>WTTq=El)i;JE>8+mB;@d?ME0 zxb_yrdf62EMMs^Mi}rUneWC+af^s&c6XgPR-&3gj2;YM>DEc}+2z|;$9Zi4gr9<0i zR%JK?Rl~%7-*B{#s7Kerr}@>;y#UUa=#Tok4#NL^WbM#t7(Z1oENqP`_Ha)e_K}^q zfOZ0BEUbn9a&^XnTH81X|L$${rwg240Ot(Sg>)*J_Qqv;XmMhhia;JV9Y5-X$OZcQ z_jLD-RsE&j^U=b-vCaVf;>KtO2m9wO`G(TPUdaD-;F9)H-1+|6XN2w3VHt*bc(Hi) z+#iqUppA=kQddk}-WF7Nq)Ff8sy;~U-*D~YBlM9_KXmgvkdJ*>D;?+b%<_Pf6d{h&&u5&fEqAlmzh z=nn)@=Y^3@|2Xt@q~43XAO0xNLw$r_BdLpzz!!TP@YrW!e_SBN3Qox zqR(jP_#X6Gs85kw(a%8qq>K8z0%2a}8dVs4^!w7g7=I_~Q})ZMzsP=Acwr}extqF) zd<>kAZexEd$aOZP_etQhU&i`#59;X?qf{M690&RS$*u6OZ}r7Y-HAAR!XHNqgh@|t z+Mx85G{)1zeUp?y_bC_@QIH;ay)DV%R{!zRR2}+M%;_a9Bb*6Im4iTJeEAKgN(k5XP)yA;hw>4 z@oc0L_2?*-hmyw;-dH|w*E}*!l({pcZYJ?zAJB8}x#<4Rn-kA|U|ggxOkM`l2jyj3 zeLOE82CmWR@NXJsQs3LoMdjHgq}5{6@(_tBT>3sokrq`E=J}$}w_hciT^6ZCR)Ct66{E^ZH{v>!Csm;DOvF&QP%_r4Wzo^Ar}`heK94)vitGXe43q4Q<;XVBTx z5SLG`jq41qGx|2h;~Zn-CXrdFBaX{{b}TKC!TDVhj^kqN9LG&U*JIUNb->+r z@OP^H5vk5WU_I?R2O$^r{O@%R0>-hXUql;}SlYrv2J3Qnyp2qD4g&kn$5F2BGY;mU zFU0-+Y4}A@r^os@{e?+sJ)(8&$lhzx zdYDeOb-vv2!V|Dbszmua`Q6>);X7m)`s2ewIG^bd=*l~?0jg}pdep)VU}5@GDH zcZ?{Q4BC6~TmKhBiixux;~e5_z}R}v7>u=Hv$Z?JGtf5D+p}&A#>JO8Gs74|jYb&u zgTwg7{siXza%5VOZqi3zy_@Bf_Bik#hQ677W{j#!V|nZ!Iw+4lCsZDP3|%CBhFAOk zRoF1b9}~sc`YPJoKnCHza0cFnjA(1*)pZ5qKa2iJ1Y;+jVF0@h$<)$UJ@?=O}c3FmcvjLg%M=MZs?1VQ#E|dB*(Oo=_Gt z2gxb-8N~x-#CZl^rYL0I@SXYd6Trw5c{kpVIO^{Fb{TQBY7{Bw37uI{s z56&-`eA$WTSUyGum(@LQVeE-8l+*WZ-07oC%W7+I+(gYV@GD9Q=VovhT;jv$tzY}e z^(#NQIFey0_Jk+WARUsq*kKa<&XWv2>i`MK4|cnKo_I+&)j<<79X#NHo6_On#~(X} zLndGHJ?O9rq{li}qNc%5?pHO|gj#CV#&*!EUKVO@_BT|03mXAJiWsncl2O#uVo!Xn zk}u)SP1QHnG`HBtSxEegu$3f!?Ta`C1Gk5&8IOs>KlP4#7A){rtwMsAuC4`JD^}Mw zHN>{>%lO?qF&|@k0;j~QmbLh68ju&1+hXMV(iN^#O0@ovkT(3f*^d{09|gQA$_IDMUc_ZMne;!5@-Y$BdB<2~?&b_hR`*K5zCntXTF?%oPEg8C2I| zPo~VkxW59BTh-_%{+GxH7r3eD` z81Zq*HT*&TFmB)Gtxq_zW$Cb^Nl|0;K{?UBUp6!uQC|?L&zDoA4N3O#l1S-eR#guc`&{B{F27KJ`FFL z$6LwXypExphuudpt~_=$fFo`w-rMX0b$HATx#zh%G2zp&mKm_-=&^Y^khHbcN9$yf z0exoaVNg9VUp!ve@kY=tN0vj z!@C_}Y#ZJ$Y8pS%aKC;x@ckO@Xt=2dpV#pFG(1<|$v5eT^}E6UcMWI!yt36zyoWpS zr7q)H$x(<;HM|#hUItDZM&ch+U}5YG$7uNbF8CA;XELzArxRK{%4R+*e>hCie6^EKSa?SE-_xrUo~87!IYw$h(J+;;m##B1_evnX$UDd7K^0-grG zlhGNI0)7MFw0$=6G`4FcDe&(~0k25`e=r67`+zfE%%92YyiRmy3jAjbzAmb=9Yh$+ zu_aCK%PHWeQ^3=G$?0ULfM1^iUXlV1TZp85K9B4@xUm6y zM9cHd|eD9cpy(G0w$DIB?F}7;37ml-=N^OICzhRyEZctNeJUH`XoY;N{|nA{7?chZ_~n zuw4li-jwi`Z@UsIoNgbOR5;UiNK{x{WbF@_nV;}BeWv|wM#5X6O><^J;+q}A%%Vb@ zN%$YjcSM{Jmw#8c*qQtsKAF2T-YJe_u@?{xP z(=rfy<3p90?+R67W}&8Gd1&d1%1})WzBaptnr5g=RZtTV%t|%THS$V&q?IhuYTOHw zJOGTDh*5BYw$vxHO}%XRH~p!nEqtcSz@O1@H$THcmlxsJsYm%A zwBXlU@a-Dz=5v>ZyZPL2;gg?yP3wS#Z^NI{a5tY0+HGEh-=H4lKMV!rMfi;tyw`%8 zIQiK@`^Jm-)77K=x6g&LZ~ED${WE%E;IlQpJ6&}a9h?3#4R_14 z#lolDf@A{M!xp{`e^kTW@pf2r?0C%{5_i0NEqu~9`nS&&uYn&(5$_8Y9XsB`79AV@ zqJ__R!}#%f)xx*or!?H1Ub8oW@S79~`EUH^xb^vI62;|~L$8LLd_Swu#0wTa9}WDl zhP(MOeoNf^bn5;s;f0zuZ!cJITmMg3@R=6=c?)i*H(T#9Abq=BS=O)Nt}|*YhVVxGn#jOvMlJZTNW&ck^kS-?{nB85&O)`H79IHJtc1 z+?>nh=F`#mgv$wTMONHp(YMQEg+j6>hP&fEV9~MZn{&n7@_)g?CwlSf_k=~qj`x&B$A-Ue z;WOS=E$6cqz72S>#HQddQeSVlmksKYi=-BXxelc<| z%X7AdyXA=` z2zi-wnS5Me;oJFpzlOWhwZWoe%k2@1jty_O@JZj)C)+K28@^A&-SHl_=-BjMwCLDy zu37Lh>3u}&^IH}^<2CU2G~6ApU+<+O{02!;{oSwOZuti_+%5k)3!m{mqxHGb!nfgJ z4R`ai*P>&mcb`SahCgHBlfJ3P4p{g${IG_*<9*4ZW7B`tqGQ9~vhYcNs+Ru=3*UyH z)^K;c=Pf!meKU#WmUCvd${&;O_vv`ed1Sc{b_%=LW!`=CEzXiAXUuMB={-4osH=p}8+|B267C!korS<0p3*Uyn zs^M-v-?He~_SHry=Sx#JzK7uMYA&DL;tddFG#q<^2z7r%vX z!}B%V9q$B$jFMcfrkiNxsg1gKySF_PO9@UBvi6G5BWv^R==Cr+HZOUNhHG`yp@n$b6|ecAv(LPy^o4P$;iv2PXT&I~hi7#B z*r1be8U76)4!-hPt4R#E{7UusXRZ$>yg@9-1H;>O8NdBVFNFK~VqGR)bH5wk%(I0i zerXocZD11I#Tw>fQykXevH33Ha`PX;*JSzMt0!mtnmOh_ho~m}I8BwG-Es5Neb}JM zt5=t2)}d4JbB8BQ7mI+PUZrB;x|hsZms?is798s!S(Gksyq zn(_Jl%D!)eh4>vZf&UTWGM=yS!4&M-2x6bfBuKkxPo$bKe^vmqFolqt0*B6_94Sye$fss${*VH}(>@$q} zb%0I%fb`#~{K@t$QhN`X&R*<;EB-WENM6VrX0=~7yhN~f|0wv0+^hDqU5sWM_RjVB z#D1g^GQpl3>>=geV#=al%R%npgk0!LU^n)RU5p-O06t`T-$7bLB*}S^H7c$D8}#Ta zmHuhtdtV3p?)U_G#QlQY^GaO}W4|f(pbbQ_ln)QgD;4^nTilmIIdD&c@!zpW?;*jS z^KQ)N?I)co@aTBjrJiSEe@icXHc;muL0&t4=kAH)peNX;9fSjcd|yz$+`Hn3 zj)lMD4CI1#+Yh`w0{gim@OcqI8406|aBo+5tG8z~zOy{V{ao04bd;Y9@G;U6B8&T( z$|3huafabnqz!TUK{FTeg%NKbLU}Q7 zxj*F)?)L!JuiqoMGtXmt>#-koQv9Pbcq7S|* zSU+{*&i&7Qkn>ukKNtDtv+66t+8~n<%5Vr%UDc464|{u=H{35DOP}0_t@h1-oB58t z_6POe*govPXMM-|qYw2Y%1bx*)H8k5ht3Pp0*3jHrTf3eek%Js%G}wmJ@#h5mK85$ z#{G7@zoF$sf5N70xaE~>Z#d5D>@hOyg+K2q$gC1F3*p&={hTu)vm+=6tm`Q=?jb#q+aVWc}aQq|?yb3b6}sI}w80OYlB?ajuIgYqZkMcw8Bocfly zcQc8fn)wPZf-;wU@1|Y9db>}fZbe-n%Nouo?v6%9@j3V>0FQ;8XhUBC?`vhN{)JVZ(B?C z&DwKRcH6CU7gc=5wjXadR(M0Pwx+idUGbO2V_eNMcfOcsH9mS+)7eLA z@x3J!i`-jsr`l2?$5O`Tx{CK5H5zWpg@HF|_q1iUvL@ve~D+p(MOh-nOfPU;hhRB^i+*}OJ?h? z()EYix?{j2^+!h=yZtN${N)tz{{Wn}$L)FoL6&d8SO!%d25VZt%0g)?mnUm&XW`rMMhll9weVeV7 zmHc3iHFg;rQa3*p8sE*&G7UF!eo0emwD9?8;4K>Nmh+>!%i!kcISqI7)2rcbevVoA zjOwiB=Pe80hDS8q&5vzcYU`(M%Q;EY<_+hI$%}OC{C(PjPgW@Mf4_#i({(_@-RZ(y zhP;fNvk?!k!xlc%W#F%BxI10fXUbqwZ?9I5^55vNS?e>OX6pw7Z`bb~Zn!Qd=o-k& z;G2F$kqd764`CPF(R@Gcf}8%pF&Esl`|r8nrrrOqwpJO|`KQG{sISL5ibdWr2>Skv z?m(Z_^}**|tL$~fYshP{o7a?Um6sZRIw+Cmj2K1rV8VaJ6`^6vfE}Ro*{Gumjep%Z z{4@qo4<@_;m*auq^9?}Xf2za#U2qexx!;ZN=GjJl#crIe4{qGWI=q|zV>-M&E+ZK? z{~^GV<^Mii`5$8-T%UKX@+EEH(W~1xzLKPge;kS8O0`yLYznS)CCr`vD?md>A?caF zu#TY70QB7*{>E7ae*2m}b5>EoO~nPpIO%dmVgB^#{+sXwfByOTGYf!PJfldXU%KD^ zpcSbj`EZbKNa9i^j$HinmE=DE+<{AwnlAjl>8He7GXDj{@JVe+#Ep%SYD3N3QCbc2 z&gO@fw}h&2Z)sBZI`cH>5MgXfU0%DQMce?_NVPZIddEFqLXW+=-WA91@yfc5veHd< zjDiz;N_?=gNq)%1KVfbOIr8h^KX>?RfkJ)%eZyamu%zj(TO7c6`Q?B7&%|%;h4^Hi z<5)rj?HB9Wjm!6BT4TcR(_z^J^LMFbJ5xtw=4dpTLA<6a+v9ckxh9~#yZP5cw`6+!I6BJGdX@9J0FwlTJ&@5UiXb)eJP0bl3<2f_w{2P zmTMNiG_3u4;2&77k*IZWt|bQ3u>-RjK-=YUAE#V1{eKW*`!a@}mg;B_+((!h1f@aJ7OgI-|f zZ6WhIVciV&7nHlbW*vfmPvS+ur@e00v|`Cc7k#YtnuT}V`WcHgh#)@eqKcW?DxL&> ziEAa|b=`T!WA=kdE0x{oJb=I6ekKi=(|8uQpbw*SW!Fe6vUwnQ)2t>IS zaI1O1=c)KnnR&^&?jmak3TyB`+5P-&wY$Yobd$Ed_>`=zX5E=M!z2NE{@Yzss&C2W z?G+t&3#$5Z_PqTVMM7|lNVv%_dk!Jl{JEn4htHqigm^ihY%ZxMc)1Nfqf_P^@AsvE zH>QBEPXVWXFy4F}wbU!Xx>Df(oyLD(cv3lf3Q;=Y;0gI1FU0x@ORhEe7*($y24Ul)8Uz}%2x8P|O+{PcL;pE4xIWgD^7TlB> z!i_&T;+wKVc#-aa5pMH;zXiAFo9uZ^o1Z$3PyTJV+2dm5;Af<`%>1TFuU|ri*kHwL zrz_QbP>l{}=66gvanA>t@^G<{LsRXt&<%rz4^0g<@U6jt#`GJC#0~0I+>mNiaf75% zTUWWbDYU#+bNBn-{0Pb{b=Qy%V7#_#d8xO-by2GMm+g99YdeYK`n>Zm$6WC$Dls)S zuPNtWE;amgP$G*nVieVb2|wQjH@c^jB^-R`vzy(ix(U27MR)@)*WvRGK;Q4x;r%YS ziPzlk#&`25J{-a~jm-%ZNFz5`^csWGil^D0|!&zaH9&B0L zFs7-*y#)6FY+7-@d(IRwJrg*k6T}rInF3?6w7fYu51<;~1L3r8C_)8odFN!}+zZ%1 z&VgN?2k+iYbU82%@P;RzMO-T*=c5%N(91=ou{Cr)|{7n;u=iL&` zlP}Hr5I)%|DtZ4j3ZA@*ryMc84(}zy#T9`xF|rbI=i-}#^wAcRW3zQI*GVfA2N2&% zSe#ejuHw%2Y)s1*)6%j%)1c&=<_Pg_n~4uH;yG@IK8+T5H;A(@<9QBjl_MD2&B3^- z592bMXAx29chT5)(W$=CE|>9P(qvOw@5BSNZGRC5dD0eVsq3>0pp9^3{UCG96ccT#y(QI)1idXx+9E5l=UkLP>% z0_7AQNt;aOKhI_$kKYE5Ver_2bQwO^f!<{BIR!N1d`>Dl2%C7tXFB*yua7{dd7hrh zU*;+7@mKpH6WT^kLK=Pp+SlTI4xCZd{f-c_9F?Ux#cvDmyQRpl4G#}lv_8$3SDGV= zm{-3>dE+^Jm=W9P!}sdeiHlG_7So=X{6~D@@zj+F@+?-bXdMe+-$INB$nbvypSnX^ z)44+Qq(gsDwo!(B^?Om*JVF`4W;KFyJm%m&8MdqZ)(aVvb|2zkK9nFV-z)WubLS4L6dCnD1kFrOdfqwT)V%7+rNgT6{%hgOI|V&KI#-q` zzD7!WaHMfJ;y5>?I8NBl-7Y$cxE2` z8h6s>4|Qx)C*o%Qx8Vm}TbOpZst9%b73=-JJm|qn*45Py2VbF1Z@~BT-bowz{fF63 z@gB5&8-No6P9MJeg|C~ktg`7T{JS>*-_RsJaY$FvRB_&I=rK;4p5eC={HC36eZ}`y z<160h>Rw6T6?`QZ{7;!6iYJc~#V6J}KfxTyU$EZ2I$IP6!{MEiazwHB;c<(64`(l$ zG@Q?wiza7^Vn52{q%=`Xey8AhGM?@5lYqnUSIaOuJZQ@Bpg9Tg`4O+t9r9@G=CMDZ z#|wM&i7X#zE9OvN&`t;;7Me4N?emIZ5W*pA?Az7Nc*BLEv$Svu@j#Bs+U3nlE^W!k zba(7IG{Q`ukLwD&2s6*8JrX2gj(QXi>w6LIsHo+2AMxz@H%_-Ho7j>q-r%s;O3dp* zJZDLI>|F6`Q8x+OtDhS!*a7{VukU``U)0ZU@&45j*^ha@G3-q`xQ7##Hv!_f^L>89 zb&7vw#QCPe!D}{uI&J&-9T#C!G;F(ssJXr(4J#*1`{`%$7~L(}CR?K?y)pRzjk!MM z)+2ooPih`SC(89T*<7EZ;~vSv-y6c(bA9$aM6x+OMduHn)0>QV?KwT8t1|&-9=b2| z!z6yb{$O-^k%4>F2cy?D8vcxiOWg+SAq~$?Q}{-2J2bpq!yDCSIX5i%)LCHSH*a;m?>k0lf1XhOA}0cV((~skeNz2UUY+1`CP` zr8`=8)#9Gca~oI2-jyd;T{kt=K2Y0)ifY-?=9XB6wXAkAT*uZe#ec(!+RCb>@lOxb z!Z&SmB@fVvp=($}O-%x*dU+$9#nvnhtw;cCFSt7Xs#S~WR&~|Pf*2B>3Bs2ch&G}i zr^FN+1DiQ74Hm=ogM02TTf@yI`N+V)D_K5MRUM#1!%pL?#*>i#&A69?@=mN*w`hlPUhn^rV?Sr*I`Am) zKH2_`xsa2j2O9(K4Q4$5iaXlV^yMe+4wK1;&Lux0B~D z4oF`SY7e`dO9GtyxWD}@!@0XTP_*%k_sZ)~xG)c;&h2cwqvZ#TCpXR6)ae~N|MZ3E z{@s{^+JoWDnG9!TbB42tb5OM7;J){_<$YYHe3s2%wk|!X#(t(y-VZ#}pMIZV^uElpZE4$mfgRpk zwx(~%nApj1|~=`6`a{N_nvk_*0IlKJOTbVPl?7 zZmL~^J=Hudq7r9JE@`O~4=inJVRyQ*?jdQ)E_iB)>TF zKkjQ)zYfxkRDH!dJr)h>fNawlkGrkEM#J6h^(f!?JP$F3WH?(n4RmOVh?eKLh>mAb|L-Lkp@Uy_A4W4N!yLaGOM_#3BB zmv-}}!}eKywdpf(3Xnv;blcnZFU6T~>S zp1N6n5hyN&O)LamklP9y+GP_))`)c@g(I%W6=_*qU-jj$A77FK9IRQ)L7yu!S*_hT z2uB||rcJ)E=5GeA%d!6>{d@V+@&@YDy3RGHclBjubRB_=ifarO4>Z;wBn#&sgD$K~Wb@Rzrojm&ZeCUP$MCTDT*c5Df6a6Ui zMfs5SZ`ij2uY4w)ePBMLn8!1VwTj=YbX1@;laKe|KSL@|j@j2bfub1dXRyYy{6?wxLGT;ecCadv{|RFpMl=?`Nm>xReZ1)YtdLQ`!om}g|jG&pFk!e%^C2G zRQVP{-gRi&T+8mo_$qCPGr<0~SFlWk7lzRnrmWG2mp;lk*6@Bm&{g%9-Y(Brr^oyK zQat;*yx%XwJq`D{xTkl)XV$DB?BsK?=GgC>@RM8|D}+vVduWX4@q@1CCi-{+t+A*V zszmV_*vki@^HpQSKxhViXpQZD2(V9%rgt&^i0?`%fASHgFDLy@{ipvt!{aK1f!wv; zoBLS#&auo|&=1lF6T&h5igr$d-dhEY(gDbAA)WLUoI%(io`b)G-Nz$XJHJX)97otEz2dqjzYO~j;aQnEK~#`-FyPd|Y&x{-TCMi%WxP9a^BxDGoK{to?zcB1b74+pUR$=>3cv7(^xX6~~&>xObn~*nRiYTN` z2JxL~L!*1$^V2bAhJ1o3-y9#8Bc2fAf7Uy0{>R{VJkrMc*8^P)A?+|gxw{&C*tMG|?yO_aRR(b2C2zpNONcgHD6@v(V*e zG#zchDAZx&x;d92kXJ#(-Rno)> z6E3XzhkYDF2cfs(Kcj{Bz^^3nqOzO~#^e5$WA9=A$9J8cF=EX8Pkggkub=2KIt&OlEp_|eG+$9NKcN}z(&ukm0lWU=K)X{W&ugrnX7s|+5+_53Og0f~iCF?jm|2=%Dp^lb%QUx9* z95keUfM4?63VQGrblnNeYq0*`!Y?25HvoC9McU|(GvwrM?1OGn z7RNxJXf=3Twb&}P+xMTsJLg@ghk}HFYDH>lSsn}Ew@ha#&(l%rVaJ| zMhCw>-;gfq`$43=9CL5|h~uEwThF$bbqsZ%vhGA(6&M5hfH4nQ#vViblzAiWtUvj@ z9M898iGn?8&fP5kkBpMb;<8_XLsbUt!P!$BUU*vf7Z{%Uct2?DMxEIE5%L0b@B3}E zfc4nFz;_(K6Q8&XfhW_7x`KISr?&>_b=Xe;?+gR}v&i=_dt5=}?M!m4=ZO%`P z)^(REYo8!I>)tBp-a*9IDZE)?T*>P1LB4)nr#dJnCn0y7C0lTCHf)tp&ilT*dpyfG z>Vj`kADq5uMH7e)XN#*gFIJ(=RWX^y5n29NXtIN_crPV+8+H7&!dqB%5E*5 zS^ilcur4q<$u#AI)e2p&`F zP2bIf^@jSvHf9O#EPE`QvYtMVHssxC;Y849dJWxIp$C)$b?G3&=yw?>`?l=Yim+$X zFM;O+UG}9z_bJ(#bQoD0-Tf=j`8DeITS!mqDdYSx-q{Z_^5-`bH^1-J_|z4{-#e(6 zg@16F@hnh0a4weposV!gVMOQPeQs_4ZLqA?BR-Qi&yY7uH%Qawtrg!dMnCkG!Sw49 zW+KK9=EuGb+AQhI7vsqa=ykF8rLy8GX&0Bq{$WlpWWu&5g7|qiVR`4=`a7V}@5_kw z=MIg8Pty(XzlnYweUFxmM4J&QEuJ(?pd4nPK4QNceZ4uJ;xgy}%drE$!4Z7h10Sip zccMSqIb7`jA^M!PxVL2^EXIDaE(X0Sw1a_RqHxY|=R@XeAIkcV&~JWQ45?p#IrmTo zieWQVa1d?69^ii>c^s1`$1HO^nA=u;TgHtI?TC9!USv*5vHvpEk)Xrxors$}Qs%^y zZ3u8MIaq*iUBQeix~iV^Y}$h{55re|2Yv7#h=I}2(FbNa1J5S(sp%J5j|WtI^4$rl zK5fwJ=?QwJyk%UbEvEje@s3(c@C$_ld(cdU;*muvrCeo+x z>>OPO9Kf^T?IiSwVM&Aa3Td!zX*--4o-#3EFsU^N|IjZI@pl7%>53a0R<-zH*s&O{ zOKY2&8k&ZIhA1s9^-CMM<+UwKtK%O^<}UIpQR+~Z(!Cz}jZ8NsQ^5kAd7~mPg@z9}VOB$q8R86EV z)C@v??n?4ctq!fYw#C0{MPsODnq-#zO5dwXu@m<}81^w98F^!Ub@Sv|eqh${n@r!$ z{;O+DFj1!YO%+nck|gXM4J*E6sLJz?{qA&IEF-pi$Zbt+jXycEOxQ&v72~&req8;` zg{3PVfLLq%%}v!e)-<S@Qd&OOzijD>T9f?{e4|N7>TrrR$*|_n4hOR+ z9>c7h{DSYA2Kf$m1eMY=9YFF@Zt93CiO?BFrO{0y@XNALb4#U+u2N;*V0bJ@GJ3H< zI$TKl*kx8$;!OAu%%kdRaWMAcrA@Ho(ih`3r;#VeSBN$qB&$+kl6VO|PO^1;sn#qT z^>+t%vu268LateMdLGYtVpL%B$c`(@wq$R;eA|famzC}qzBB8wVY`NU{|xJlZ@%^V z8%K|s4dJ2&!3@3k@C+Jp-?ydoeLHWPx8msB*dFo`F^{&}y!2^XmeSj8V4F7p$GBN@ zkAmz1{Em@6F3cG*9_hQcbo20ztS!T~4h_(C@7H!@G`v3V-+vWja73f|&d)nC9v|_< zWpiIg@O;oP_E8%+xnDA(-Sha!C$1>loZWGGVB7HRS$A%|Y|Dt{JBRKV=Kb!G*Gk@a z9ZR%FkI8jb;1X@ih^?0qQ-&LMOUbjEb8}`QQrCE0{*c-2xWYxd^Mu1qi0$h@HpZvc?{@-O#5X~(l z4E(uPJhAU(2Jsg2@OASL(DZa<^W|NxiJ5(}1rQmpefTwc<)e^$49&VX7qM^SqIc!C zv}Fj-Y*w<9>)Tw_zB2*B6>maI$%I+YF5i}hwQ&UI*ZKUCbvypl>Nr->OOBSR=aQoV z`IT~qT&-s?uh>iZPj&iJu8Ds^#>`j}FF#&wU%;ju5i8jm_bh%eMuPHL{c&xMbWC_z zmI0e@;5vU~`BXtbKSMvoZ;Jk4_!6Ml_R88kO0Ibko~=o6jf>ZM{0N^a-{SuG*l{Pk zT*Jrc`)&;n>UXnd_g5O;s^MIN<%Ri5NoTu!6CzjN|3Slh_4{OfXZ^u=Pw98F=FQh+ z_SQ-cf4IH%Nzga4(NW9WCn?~Ve@u%1g%t1^Dc~5iC#AC_1$=!9czX)?<0;_Jq<|j+ zoHi9fpOQit@4Swtz<(zNJQI4HOrBQ(PWlmal6lGc9QXVb_>RVJ)QW8CvTvlor|ksk zKcn%@Uh2&$@PCp5{!$9K%eF*zYE=J1nVH!A0o@mATGCAGlR-To)4h=08-|lT64}qO zeOVOGu-*!%7uatz5*#7BoGZ^vz?^Qq%`Bc}z0FFXIV-seYyH$C;i$B+`l{ z=o2S%2m*6@JAmO!cX>^=#+*FIHV-s|vI|LdEv2H^f>NT1d0k#1T{znkRN-P#T+A@Z zl79l(W*(-IGE#MHhTd0%@;M9Td^`)RzRv1gcx|{}!%4@qkqkf8qGR(}kOE$0(a9wNeX)M! z<(7l7O*4EdEcj&5_-^?uu;Aq1TtO?|Nd}1fs}_8U1uxU>j)~XEr(DC`^0`aH-STZBK=DFc#EqI=Ve;`x6xbc^9oQ7))G#%t?ajV>f^evF|e;dZ)ehO2no@Nf$FUJZAr zYoCU@)AfvnPtj7pcpb3tZTMjgcc<&Ti;gKTLhnm3@-gsC4JVz+DoXip_A$8mpJ36k z>lw^*%gf{ox?J*_V&O}b(eT+;ymr1Uu;8}*H>7~?(r`DQof__z^V1eS`8llE6#FfF z8{VtoZaKeX(Xr+5szt|!zh&W*ez}hKgoSUzPiwe4Ucc_g5^l>UU&GyUD9~`X9A;bi zjQ0`E54IA^%jk)L!#G`DZhqP|ocmp_S19s-ncDa&%li!$ydwqt1r2xCw=ZhAyS{zZ zqGQ*$Z&`4=zJ1Sv+x4v(lrUX4T6|8?gB8L}+s@BL7Tm6f9SiQa=#*)=J6+`(?oQVN zi%zaZr&Gh-`MX!c-TC{ph0pxu_>R|p3*UynpyBTPJ!a8K&}WN|4L@PwlfJQCf6v0V z;pa8n9q({GAwjq;hawGk%VD;LyXD|m_>7n1P+sL0z74-$!`=L}Saj_4wpw&-_y!A~ z^i4nVQ48OO@6vF0y!$LVHvOk9IyQX2g-`mXKlhx4Z^K{IaCf|>?3ld*lo_vlb&KtX zZPf2(qTJw{dBwL}_+}pAdaaKJ-;DoF|IonAIKM^bn}M70{O8}h@c(ZgdB=2qXt9~< z$-JiA_uB4PD5tbC@J115DsXIE!M-oyy4$P2V%$MXfFzgBrq~zO@ud0thM$hGq&WjW z`!eyv;5Feg{2M+TeC4wXO&rcq!Hf?|^%hURc`wHU!y7#|@E5Vj&dV?V<9{YzbH5v( z%yS$IX9w!=HjK}1+{GH^=Kp;iew<6NCjEwP2oLPSI|iWdt-A5ur{9_X>~fp%roTsi z+;KBV=9T=1k48N{U^kNEdv|!!bg>8s#t*tt{jH0*JN;DeWa0f^l4N4@;OcF#{BE3n zQ?cK=K5H*U;Z5d{f=k~^aTl4?mm}}SkNM9M_BL=I!#UW2(B2+rTmectQNf#)jNtL*~aHrQOo`A|Ii!8>`D z_7vQo3fm@Q3!?TKDErcQ+7fNMiErb9Ry%&1Ue)#mcJ!*b8;S?uIy|k%N5M z2OGKO5uyqEqbrI_3pO4(A1%blRQi51`*cwbb8>tF`#rAg-VIuvumkV-!DiU==HOiW zocWX~ya4+w{Mdub_zo)jTA9wiv(buAK8Y4`?{mwF3AB-g zja`n}XY%q_5H5(ck>6bMh%|>026nR0f2AKk1-%w;PSz3csQJadoQ)5hju!qL^iF7* z+kE7KUc!DAq{E~k0v)*6w--Q@_GHiFKKQ(G>_3s^(<95|TIk9K?8OMf=99Xy1-4<^ zU{giA$)h+on>PGAV54q$FeV<${IP9y6NV57}52_l!FtVy1{c_HL+uu9nqqo%vAA9iK51;##% zo+8?+LbvwA2DlEkXdTeCAn>uL1bRC9}qk_R27B0U0uG%4HSg5|;MqgZUVTeO0spr@S2S-?3uCA|)&3%P}T@q=`H-o-l2l zQC2DM-QLml^ddtgpkSi|eclV5VjdrXemNho4vfc3-pH4+d1GF6BJS^@ypa#u z>LO3)cfuFmr&1>4^Qar+V7J{b_dSf2Y5ymkc0c&{Gf#m--q1*1SB1KVym8+H#x3A& z-25}x+fV-Q`8bO5taQQH>HQG=GVVS98I`_P=?Ah2FxrbjPh|aiMAxr||Bd+e31HvD z{Up+d=AU@&8)y@YpVr@nZFR~P)r9-+3#Oht$0$?uhM2Ol5)L{?x+=GGzewx@5)2<%8J?HIaw*f-&4fK*@}a*uujxz~=+ z#XxZLu#TY&u`OeJ`i?XbSO)ZfMAt}J0T*CIkRgbRXrIP!g6^1g_#_|kbEt2nO-5k5 zZ(CaFPR|bS%3;Tj(wZe}p}fP4Mw<`0T^;Q7&;aB}+`QMPfIpA|{(}_oAE$u- zQwn$_1^j#p_)y3_8UHLB$>4=4;I{xy8-q@kC0w#h;eLM#{A4x*sOsW}Dr1$IRi9p| ztqv_)mRJ|YoKrMg%l3uSXZ}eR>gyg<+?aLjKjLD&S&X;V=c`ls-Y~eag?j)J8VI%c zov{8da|3QL^__FD*3eGerQt;``28BrIWc=$q{f0{Uv%tZo5G9udKyB$V=N{w!V{(k z@Xm{HV@JjJObad>P6BZa*KjwV*%rQO(}+(zUZiissgJxkcdD2BC#tQ>T_;n=s49+y!^g9F?W~i1EL`mKP-O18tZOt}SKD|~SBooN1J`0V zuX4SMG=Jal(-D?5-E*O>I(~k)FT=m#!@);B>tx1Ijju?%AHa_$yg@9-1H+pwN#NGUd5I$M{Z`X>#^zmZ;f1bI}14PC} zn?GKh3uU`u;y2|y)m-Q!41f!M@e(fAtEB1H9R`SK{u>iQ50>?f(`Oc1Q=$IPnhTvi zD_RsuikWAbXn#2NJY@l^Ku z@pjk<#@P&O&kdQecm(6wPcio7oT2&I{9@iS=A#4tEinC*ISt8_b3?tDckshE2kc4q zPtJk=2f4QpXGVzZm1WzV)j{mr#<)B07nmdR;7ouyy*P6O^9{||M>__4WwCD;b6{h- z`$u^;^-Wg(FoKxJ?VHa%zN6|hG2alm6=}sY=L>V8o<}eT$Zv-*rvyJ0JvYJpd+ivp z@;1C5Agn4|V|*J9qT|G3zcdmzv= z8TgAahxg7azOIw^4xI)S?FhmTA=V2AR*h8r^PCJrFRl+g@wt4=r|?`5mDluHGfK|a ze+nNpoZ}yZy^qngmre7)7bWIe;45QHckZ>K=-gAtW8lyS%5mRSY7QU6I-`@EA5wGN z%8v=dvRvF->e+Pmrwlt5;bi_H@04E^^brb`KM?Oq`UvQ2kp2Qz9)^yg2FQXxpp}O) z&&c@teB))@oIAb=a=0HqraywYqyeM}H1keizxi&4fv$ypX;~&d#tj|WxC=0bap3>K z#09@-(mw$9nqT)kp0P)E{Y0ddbc?^_8wvWn*~$GmHXC_Xey6rvMQ6E!J{M;ivNZo-W2|zLTd5F$g*6A_<;7KhvJPF8E%vhw@ZcW2!5Qd38Pu&^{c&xi(wVML`JVI&|5%nd9%nJU8Ug13yUg zBM?fXlgctb^Q(UkT_k{YIbKp0w+_!%7aQhm4F2-i0;l8+qI<#@C-heeMZDKj3R5 z2tQp|SIRrTnPoc-ZQcar1?t=-@ixx`J&P=1{g3%#@7Lw|I=xs+q0F9#%srX(fihm^ z*(_adLiiR&T}^oIaP4OVFp=i;oQ7-!+R8Ba{~5wl*X?xu6JS-qWge9Xr>7KQsLK)X z7|lALK+CFun2mSgq}Gea@5zsXNdqQwFFr)T05&_S|)1fV#u7 zvJ?5vvSQYr;B!dw%sS0H(@)w7)Q776ODrcWBP=WN@}bI4oSrHl3A%7ye2q$#F;%8a zSxSW)Pp|DK&(nPx`c5BkOf%Q1SSNLkhp(g6B?Eoq#eUZDD(yo04)b3r_WO~axyYx9 zIRDEJzgUxSHdBdc!&yY|frd3M(hDvu8SueZ+dAmdA^f%?f0&>2mk>r-B@X4wGFjUl z=wW<66s<1@|0dA$xBkpUUZ?!-S%{;u_41~fSo3wD@2yqCHjP18^v|SzlOET$f@pVw zpz&qIGYPmRP1RK;144|L5$yK%Jof`HeAbOeUX0D_)8)g2uR_>B>t!RWfG6nF1-x*b z68)^69Pq$%&K#^$wLRtZ_~9R|WQ3SW8kEhKN66{a4uQK|XTv(A7wPusGDJCG-K?83 zV0^6iOqsUVb&QX^DAs(>q278Md9eof$KYdVqEo)|5Y_@o6LoD~C(0yg^*+gUIrRAm z%MdeTdV@Tr94Rk`-GjQS4{I`=^Fl?Km>JoL^TKjL>pbw_cQ0=b%5V$POkX@F&_5tO zuGy|f-#Co3(W7gJbg{fvql`w^W_Cr_4wY@qCul2KKG}AD^=!0o-JgMm2?hhdzLqlNznTp#?!%^4+- z?$Pj5Gd?e4l+(jJmHtJLXTL;#XW+ZZTMxebk+(RwwP)r>(L%;aJ$Vqc+I(L4LW2(! z$g*Ip=z-&{vAfaNz`0iy)a$kp;%@46HQw8XspnqEvJJ9C8(vReJ{?}~{M87Dx+5=u z_(_-RT1>|yd`3IGM#DDfJ8`(S7slP)zEO8kAFv+Ad2!mG3G)6R+BB9I_8V9p;jgh9 z^$~15(z`bR7KA@a*5#2bv7i0N;|Oo+v5$Qjc^>Gov>QPkOW%6^=r0{d-OIEy4?XCo zv3~89wjU_JphX%CM_k$0wD8-|4e4Dggj(&t}_mpmghd4cK z>v~a6=)Z$)jfsOka`;Yv<)%+a9(m3o>)Z=#eiG}yFmIWMXHf?-f0-Y=!xxYb_7pTv|*W!+P$HATW%-63jDj8TmLHP_Sfj%4F(I#{g@5**B`T{w5 z_pB)yD0vWd`4q7~x6|p_GbM9Y$^QuSv}M=L8Vj06-}*5QP0XC;SobhL7!UJ_ahm*LdX4W-%0>09|3&s?$S=zv?|th=rDSq&ai;6dUuV5Q=9BuF++#f?;k#FXKe;_L5i7{3eWfjKvC!x#z^#XO?@UEv& z|2>I$f#}+-uC-$Ahde(F_DlnjH)XkL|Hhpq185@#`hJ^<^c!0$H6Ek<`fk;>RP&vI zt2TQ#or5n(B}3@iUyGhw5I%ympIagZo`gKY0(JPC&^1iWF^r%-MrO`3w=mQU=C(!rY<;+GLkaww~ zdj_;f^SnjRfn5>9lIC&pg76FzfqdEjq`x@IGkvNvfU_1C9!Gxr&^{P`oDbvtc+jt) zKD4>=pSp1t`5lhIzaaI3I?41p$oun1Lx1yd*&Z{U;on9JS*B02ydWPw{;78pY+j&4 zwELJKZLm%vF7m;8AN6;|xxaRL-uyq&LKEg<_z~3m)H#MR`eyE+`MLD&%fEsQ;K%D6 z%H%ux{-65JI^|tHqn&&k_b+FJN6v+A(f2REodAqw*^D_N5;rGrHgG1Un17=muhY~$ z$cOVf?2FPzVl?XOie9U9g>5cvwK~z}_rhOwtrs?Gk9t@B27Mea+CsF6-F=t?Lz&q0 zG3@(J-YI%EqPzq#_rrOtkazIhPXs)3TpIzuJTHV}^D~-H&PSa9KgNeF#~|PnWft>7 zl1E>+&EG-IAMFBBKUehP{0=z|gipJW=CKcRRO~yQ27e!czqdctc5c>u6nU_DGBUfc z=6}leO7GUtgzrm<}rBm4b!yF@)>n!;$y_?^FX z=!+{Gtg+n_AiML>TfzA!d^?N&!GUXl3wyXA@37mN2>B1ahI5i*p^qBSweamhqN9>>L z8=rM@jp!-!rDx$>$Q}ptQ*+>>)en7#P3oq%kca)~?;`GaT?$)SjzuIbU6-OA?Dk^5 z&eXTmRmzrS#BN8`xF9FijgfC(0A+!#&`WXRMMJzw{%AI3dpopijTLgtNZl zJ(x+|Fuu$cZ{&yc7=~jY(2};L8o%HS+5+|ugE@|V$c8?0r7qyxE`;;Qa>_iIfHvhS%#lD3K$G->Y!kKa zP!~D=tHK!kJmg5+vsuHtFfNq10%I}a_P>j{G~fl$_Oid!hqjEk#OsIdkZvDva?!r_ z;T`snif2t<@_;aguJe98O)@>qL!^y#=x?+SX==k5pZxV9O}*$t8NE~G)aaSM->bq( zJ^nHJW~gVW*Jv9msDt$FOI=$mWgXAI^QbQvC-cFBZ|9MpQM6IK)3++~mu23EXVxuz z7JLSrZDAC=k?vi9kuUS>hd!M|+kknzn6Jyp7&DZj9jFRoz6AXBV*FK!GvR}{M?jBt z2zbfik7E>jKKPGK@7Ji8PNH6T$A>)$;PqPYbpq|?ZuIpIk)KRw8tUNgKFk3IP>+x& z!z0reUGMw13u`=G7ci&&(IPMAuVg#a(pxg=PvBQJHw|#W(Og&Ao@Xl z$MKBz)t~*f)zw%7If%K{Hq4t6{%hHX!d?d7Sj^=?Z=s{~pUSl@jGOWpr=M$C;Ij&P zQG#{3IkP=0r()hJ1Ldp3n=$XzbTR9~ni8yI1u(x`iaGEy%mvNuI*0O!bZ=t5uwDL4 z9Pmxw@*f}f$i5xc5xZEIdNVs0Mx#T!JZOKyJnt$x3_j?y@EhJ0MR}@5-Ag_>p8AgH zT*$Pjxk--i*++!`UeI}Gqv-h*;|=0+9+z-aFNja0h3v29;;dv3>U;XJWd3n(hW#A+ zu|&93wzr?@i7uOgaoK+83h-{$zW4H@_7@hQzpyfCH%g<AT9FHk?VcUJQG*xcG^#769@hiuD) zkGo?>!6g0anGbUTg88crl7_9ysx@owv7_R8#1~|IxFoN)jCjfO`1mKTWF$OQ>{fjb zj1W8zjB;<+_*(99KYe9eeOuDXwtKdD@0FIvrLnY1TjRqz+HO}+uXaKE%S@)U8QU*6cr9Z$R`N1XSUot}3LDRCil!nRy+BTQ&NZaWP zJmw8i^tR)|c?s`AJO?_@XnJt8%5+-35O1L`#JM}Ob`1aO_RF@7DA_giv0)D@OJkW% zW6#{_q31;7IMMh`q)WyBe)QOzZ@}>@rUqwIPVK ztxL$K+qMtgHcV!b%&aoz({h>B5IiD6R;ePAI-{gpK9l5_e?D1u20<6Rb_9${aH+{~ z^(r0(pV((1uamd8f!x}tRFs2w@wTgPr0S1lC) zt`*;W%M|2@hsayTZ5>Pe9XUHkF$k&nvOKRHfonveNuweX| z>>^ionMZx}H7L$&$^u{FzN&eD#KJArb=N%>F4HNPK3p9to$q@d|Kby02y7X@73mze zeeB%Fa(0a>?YL_5g!^}n-Z5s`8?VoM^%b2?Wv2hWXY+)Ps~CXzJI3rB%^;-WZH0%% zK$i0Oc)Rr0=ncU^we^J9; zP<33yQ^Lw7uz6g^*ua)CTSu2}%h^7vY{$r*SCl@M-7xG||DI6V%H04>Ir)uI{3&hn zvEGMES8DQE{jpuLZR}+|2^i~6!k%?GY}P>OxX$4Xt7%|TYY{^wikdpO1*Gjod6_*|11Uka0>Xb6!2&Y_()_) zvUu}Tz|l_@w3+YKWzxvMDh2+!6!5*84(89~W%B*G6!`y~0)8w7{B#QVP~>;A^nNh~ z{N@z!TLGsW-q-xgb{Z)Oroa!UfWxtPQhuJ&^vyZpr<9lk&OnjzIztsewwrkTrxbMF zNCD@5?__fDqCHCnr!6?s`_ga~udyY+H3j}1Dd21`NyqqsknIsjhEw4GCX^uLnGt9Oy4B8GNOtV+`m`egEAQ_&YTI zUE1K@;Qv(${GV(5PK|HciPtndqT#Zw0RO*9L1!rRH5vczy)CtJTT82`t*&VfRW>hO z0=L?=%W5j&1AP@XaM01V{s!0E*wPVdUNN0$D?%-+;6YLaTVC7T99jYwluMV?!lyR; zCa!9v3(Xi&h0UW`8UBW)%}t>j^66Vq`dWOTwz?7?5m(nXH6*~Qmp5XMP0iBK3L&HA zNv}&+wA3!CZHnP>y9xa?s;Gz|Q9&`rBwRu^G{Mz;s0D5r>q0RPk&0V*RIG+O{Yo&= z($Iv^ihw&FYYPl$D^H<~4Zy0z5wz8-;5bvd+k}72+L{@Kh0}{G)mJz=Z&=<4-x__BNrI5-bn3RM#>2iL{y7$ltoyUQ@M|sCs#2OK1s?_2n7BF^y=d zg;Wt@+0y2gWNtt8t}T@fILu(xvQQJ8pVq9ZZsBplI+w7is~TTgYAc~K%i(EWmk9kC zkybZ8B<#FYcuCT$R8wWO@!y#kJB}Ox%U0}3dDNm_S{+JYw1I(JC?H*cbtz*35ZtZ> zd9qwcB^5XiS)!YA%rY4Zss*j+tPnL#E0!SWirOYAhvnGk1|uVp9jG(~8@~d%G6~KbH%W?Sgl7{8A zIQ4nZcO=2=-vd@{E2^y)2o^Qbilr?=n0l9cf$VzJ^n(b$0`;%CrsAC!;hfMkSBnK7 zWq`Qvvf#R@l3!m;0pE^xoEPcqCQQEPpdI8zxV=}cA_aVV3b^fO)23tmX}almqTS)e zJy*JmBH#CFIQMkfa5D}h9XatOv4uFV@d>|D!+4vZ`&)$Dd)V&RaPAeHVByzjc##X< zYSFRxbcHRr?Z?xM;}|dIj$>D+g+DF^#k__E_gio?&Lf>%3*KwtPqN_HYalP;PqEj$JPHT5!8u^jdJcT%_qtB|p=!Qz}@}QV&Lw6c}(Du{5&k+=2X}6qJT?&-eO)p*xmv`&qWXT zQ|9G^`Q^O0(Y!Rc;r9u+q-Vc?OM0FZaGC!F5BSRhF7Z^DmkiP)$H{sFck?-B;BG#@ zB=F1@{5d7ya$dhD;BsDH6mU7OL*`|Ibjs&lv4Dp}yF zeg1;Lf1QBO5b*m1+z~#J{WM0b22f3c?74SI%PuNTz<_`<_Dgl@8 zA)5tU&TIQEU}G*=R8{80!k;qN&${4YzXN#J1@AEMTF}R2@mRU|E*CsJz{zL7<7|E_ zKdv?SEZoX{54+%2?z`T6ui5-oE<4_QH(9uqvp(s9Te<0R7yKo&z6TAx7LQv#YT@?f z_X$^iE7yF^1-J6cmt1fwzx>p(Fd$ar=7VY)wqC58cEcCH{CRx8Ls&Tt+q*=k)zw!o z$4-HDPG@|I{~?rR7n{$s1g5Y#drU6=fXO+|ESx4}eHcHPV&*0HDf8Yt1UFfa`D{tp zaqwM(a5D^W=A>>{y%uhUqrKE?AaQ=u@>~;%Q?6-5e#+Eu9=`{9wS`eFuveZknz!JSTQBt% z?8+G0%-9C0$}q3CTSmR^I^(bnqi>Y8U*u8xMA0U{Q?&mC+MfyE_X(hpd%QmYTe@Yi z%{{Wsv1_FLqV?svw8`-?qCec7+FvUx{{!$7cBQZr478H2JAPbR!nmc3dmA6CG9o`l z`$qYjt#70CYh+&fLxkXG5TTvoy|DELFKu1c-^j3oT z#t@qqez43#AFuEr*jA57`f9N**zA)34f|y)WdRkP24#lpkN118-CgaX0=^R zPj9t#(Wkr%elh#*QO)<}!^RVKyIr8I97`=@JhRMpw29^39Gwo|{4Kwy|I@M&+r}~< z>u7xPKSEWVC}WFDn7gj9$cI31cjg zm!$t*j3xHVS(IhJkawiFr&{%}Z{Eb%VY}EjvR~rx5ps{CZ5X$DZeblE{k@nE^nKTH z5a9Dbm>g##X(x&`!NRWKHQLk--!DC%KvUPX&N$ID2_A>xS5F>yArITp1wQIL;IZ}f z3NikS&J8_(aBiAc@+y2h_ z=y1*Adi_59fAP-$yJrwbqHuyLoOot_3D@%);8pNrh`=;71|O9;e1oz<2is}alf*iL zzU_o~HoFY@mJRB|BK|1jdZ^4b*;V**b<2$1eTFd4C|r zCf44nv*7s~hzFlN9(@!TpFaj`NgTNDg8hF9))>B7rqvIc->6@%^>O7qoPxLXjZQy;j&t4~wmL}D{ zdz32t06fP%thtE6LAp%;T>!ti-b9}d-04%1MR~MUpRTI7jd5yZzz8j&Aw=kP`YZ@EK8ac7915 zIAV-hfjJlbVOhH#-#>w$&p)X4=pTITCx#$?0%*@wk;XiXIr5NnktddxIQ)4cz!iD3 zw}4~N(zX6Or9B%l-d=|PGRGxE06RH0{{myf@#8VEj?6e=yXbF~4IlL6*cqKa{x9Hf zfahrE1U`dD!?z6M6VJ{7;>|N|KrlDllZ&;j9{mylylg~lET6sb4Q->HJo$YJz658m z4t6hrZ^`hnQ|$AFb)JH~eq&o+jKa}0xa-XjlqwCf)EiC5fA zdCj;1Heaf>A_D%z;H&0O!eXux#z$i~-dpt+USU)mUAdAF=kq{Z_()dx50b(*XF;8XT+7@`-v5NRt(a93#{i&^qZ}Ndr`2DZ2x3y zpCiVKaDH!o?)ug^{2WN{Te$;U$6?%@!2Bo86AtnnWl-Bj<)6=YA^M~vhD*N24PRzH zr+4ES%b0AP!0}e@^{p+4&GwDO1Dba|PoG=*(`TX$1Hg+Mtm)WCL-0VqYr;3=EO6cY zTfVb^CgM48eJlNMZJBdV^I1n84sv+$G@e_i`}^;r4CgcMpQL}+a8)47*}65oC_{R) z-{Ia3s-OjYW9*hZ__lo9G5bZ=_+cE2C3*}w>zN!|Hv!J^_yrufZf}4eT;y-d+8_6C z{CRGUYJ41VUVNu|tN5HdQ52hlFBqmD1Dv-W-qF$?s% z)a~@oL&$5NAAC0OUf$+#N$E>{ao(--jcOxawwZjq1enA>5&hO^@pmGI3f5Vcv}EOqxsKUMX!V+qJ*`=@3MNG`(rJ3CW!U`Bjr;8j8@s3f zUjuW>r~mb_3xD>Yx@l_q>qoy7n{?0AcX~fGZTZ88-tHal{su=o`y?wP=mV4&AK^Vj zIRlgQ9a@TOE3-Jmo6=SvUOBr5T)!uH)3Ma?<>~M9RXW;OUyX&d+Gio&Q8A!fPn<|k zQJB)lFQJ@%1UJ#V{}sm>s%=V}$|3uO;2TC*dJs{S_Q< zh*En=_XVZcrt>5K={Yjc(on8_BS^zSK|_SqYeGs{qyL*ax;`8_Zsv{aNnsgptQVwk zLjd?ay!I;HgKT52mt-Vz%kQmp zw-`7NseAw&{GZ+jU;*&kxhASqU&jS)qb)1+oB-@@kNn^Dfd7>T{234UaS!-A9&p-r zrK11OJ>dABOPT*W9`F_qI6mZ3;`s&O+NRtL2|bTN`$>=dXFcFPe`@@n@qo|rfYUc1 z6@L&1Dbb`E}osZU84=rQ`&7C1YUO5 zFfrAJ#VIX~g=x9Vj5wv~ZByfh=(>c3wdIo5@PM|ar48B+xy$?*53hG?YfmP zb4EArgcsYb+^^6uU}JJ?c9jgG;UZ4&jFYHc~c!s=-t3RyzPU<^4-C?VKvRN zQ+Gn`+WyAfw&5Ha+IheXCC3z58v@s%lv91uayX?WI2hK~THRWZ_q(Bt(YObTQyZ`g zhHDdOEO!aLI@f1o)=97`*8gE2?1C>faO&8NxtoSO<^g}n1745vOvFRIl1)|zPB>r6 z6A9}M6XDV}VU>VqI$898d{5}a{Km{kUq370vR=d;*2&F>4g+`d;kdvf^_JtYelf9L zW2U38XBfB}&r*>;N9T0@-6!B<1pG+>m-t^2aG4*nQJqMSI!Y^6gy%chmo#$S=pkc>({Ns5dmkxgebqZf(-t>*QXO-@U#)C-BI5eNn(C zi+Zo7@d6U-mH8tAKE=tR|F0Kt$v0`MF4qUW!H2;w;l;uxUBXv+z;_9_?3eulF8ig$ zz}@}wn8+{tGXK@W<~?8VXQ_Zs74Y=}ezkxeX-I3wVn7x_cNre4x% z*Y*MEN59Cw(VQpXxX*OaIV5c2tS`(NbKmB--vyu4=1WccFEaKr?Fr$?CYZ;JfhrX? zXB!Rw>oHOD_| zGR|cok=*5{&$_1I~J?V5e4Yb}) z`w8fHd()kLqpa={-^XTO9mj4Zf_&PJ>V#@WHM@AfNtbnO36iz~j%@{PFcD|g?5X3} ze4c?$(C(=t_x{m#m!J>!ntIQV5Nu5|vG3R!?uUaqXy25Dn6@FtwM`2%-euu4Xv^8t zsyQ-@_CAQ`uJzQ}ZM}1>O%Cjq03%&xwAGpe{i@1rIDxpt%>Qh!i9-xJFKv23+oUqT z6MKJD8}@P8!#2=H%HD@v;+_`9RtBzJeqX~gWqCV%7kjIi?=1DsXrC@)&VPp^b)NiP z+VsO#+B0?|KBTqXI)gToN7{aCqOaNSZ$V7pthPMpR%48rI2y5_N2N{a?G3i}PIqhx zTF@4J@9#YOIqY+w`EPAJoPOdyEG>FJBx7%ce6)Az{E5?Vy#GF6Ru7y!T0F^pUM_9= zspbpI(3a<9U{pTz;EOvEgCCFAofro@x0^lEIVQksVN>Rmwe6o1^fmq?ct0`C*BHVv zZ>VpPAA7}3P=4&ghB%m+s(6m_zjL&=w@QU4?tqPaGZL0&i zSmzely^;6Wd*ZH1*ni?6Y-ZVST5oOIa0YQenOEC3(`GIZ)bX3Y23v%lCSP-L*Y?Gv z6=R&^26z$YzS8IfCqxR0}rP?GUx{8N-ulmmq1Z~pROCn^Y{U$j>lM$ zh{w2GXq>-jmCstY^D^@zh4p{<4dAHh!f`1Eu*FqITso}deBiRdBFlFVdLXU*p}>Q| zTTCp;=uJBCG-YLN&077zGF5BUG-0e{Q` z-tGbCm`+7!7vR(*w&2KQ$LSfIr^{UHCkars3sq)|C0sorCV_xXOz`=Bf zf!lp%^?U(*j|ZN=@qoKyZaJ%xqXxy=#V9*QQwCkrDk?*(tCw%UCi2zOiV9}`k#~)6 zT2rHIbj6%cB&2!MeH?3~R*rL#xon_4U+pefVN6*^weLPoE9s zZ;LiHn7~ZS5xi?{;jEb^7+2Zcj|^V~N)nN$tol>JgpODb2bcyrX|}7MLk3Pcp&WNy zx0xsx<@>r#*O?Q-rT*eZ0hf9Z&Qm7l&vZ`p|5fIk@GJpeFW~Y!VzYotIqgLOHzFzx zc^P<_h+pcJY)n8mAG%F`Hy_>=cqAXJoY2jOpqYn+OFm=@xa7km0hfHZTEHbA3Its8 z0q-$7x#i^6XP0mzde`~tO@6oh-0C+8m-%V`!NhircTV;HO7o~AypJ4Pz@>iY1pyBU zJnss)aj(>O;X|bp@k>0G1}mqvsO&hj@D_8!9xdFiyT{G_1l+XqT^HQ0qaP*((cZiL zL?P?eP%bj9Y5lsH(~9BZt1rDJB>%-ez>|$U&osBs8bFwrJovnRdrj_RPI(}@sGqFB zOCD_Hh^#{<;*jZTT%_S=hC$-i<(8j`62!^(8kubQD$sKT3(3cEh{le@6W4Gac*9!Qc;=8^R z{sPXo{-Czdh_bux$>P53{??<|(?Z+bUsR3tfStwnJ@(RdFkYSm<^yr&s@^!-B1A{>O z_7O(80{sph+0p1W!VdV;8oTk`KLxUa`+=_;Z9_hN&mNI)Cwkbyi}pHuC68?*&CE|c z{BEbrfId3i$P-5!Dchh7;L@gl*76w(vw5wLl)b-wpc=Vth#I+dm>StTzo2**j-&Y{^CuMdVjouSc?Z3B!I(j6Q7HYFW3kT@_m~+;AFx~%Y`hP9f5ysH^C-}l ziC+)oFx=lTUIQPUas~fJm3aa5oe2!c?*zZj-8;Co6Et`J4fbFP!8d6PWJiC8@c^Hi z*wel{;SZCK_qP)6_eB3*wwL_?Ugk&Olk=E=+*IcAW8e3VvTJta27(P*MgrW+Ami}| z#x1~}C;8p*jnrk~tIGTb)VPKk?jhO~Zg28urGEqMKLEeeybF#$>JjXhng@TE+3*7TvpcYT?6)B|;kdAU z#C~Z8jQc*(|L;wlcS9b<{bYHx{l`4Kw*ACDC9W3$bH;*dmNn`xe)#;E)6G*$ctf=F+Agw_XpK)k*XrUgi#^DiPv$y2hO91s4rEf4X|>QdJvZEb6z6#7X;j#E`O>E6 z^_V0Ll-uP(rq=tDzWeA{d2bhFq1;c0d*AWA2|kZJ^4Gfu^F_NDi&Kjabs4-gpHXQTL7;Z z5x$E)MsqIaHco;3G4ih!?YY>OsImy>|AceyU5@+oMQQ;q%Bs)7{|3HLZS-;Tp*QsN|Eo5CULO%Sz(Fc)ND%!&{R6%5QSq~nv zha=ysXm7bjC49>xk5sguU*h<&vmVOV75vxfd$;U|7446s?cIA2e;_?F`-loQkhU}6 zyANZU`wpGuTtwc3;LTl!GMdXK&;Nz>?~F~SPom?89s#ap;2ZNT1I;Rb;p_`d16w=4 zq~KetcAj3MdhWcrtfwnIYsxEHzTDSum2^d>Bz+vi@UvV0GJn?&m&6L8x?kiTMi`5FZzJ|^7(US$x9HEz{8V|O&sVgQ&wm9zbfIk#e_AvBp5AzU zaO=rYSyOC3#o;r@K8Uk_z~3K$mKOLo?nA%Fe{{vHJiK`AsO#@%lsbcjRkjJ!$Y8t=X8ngk$ii8H0@1psL-{V)d62)1bd~c&4DF8tnq1p*9S&rTsywL zs3KjBoP#m;C}3wWuDZdW$oxog?tA`5$hpxM*fSPC;Ap4}sj5?`cZwR@5QmSgy%#}! zlTc6YP+!Ajz+*}+fGoR_Z90Y66w&c&^oRHHwDsfWxR?> z1Jt6@95u2Wzs`H$mmCP}xV3B&bOo9DZ(+T!!+d!Y&x|($3VY6Fx1AmYA5`tLJOr?@ z`ETP{)_t$Tk4UyEJO!R~|MkKt@4)Z+Z9ISOgB~Yx2=gB8T!#0DPCb8o`6uq-bJ&+3 zTToMs=!!$=s~B4_u{bzJ6-*hd7U4a#@U2m*;OIcb?FKSqqf}K0x{6JM)W|$MGv@fl zHDGVNf?TY#2Q$DA;N_ZmkiPezciTifSD@?2wYm=Y{N{#`cPMmT=-;i`&NC?&>*nJa zcm9wX`8b|S3b?c?;Ey|zHvXAQL`IS44&fiqbaz4u>#0v74vtsqIG8Vlea_Bc z4()>eRc^EHSan!!cSXYS8y{^+=@nz7!ejt9nn-LfD+WC7Y@^Ib}#`)HQvB9;J^AdZV z_B^TYJL{Y+vkEY-DKBIFS&4JPSK!FCob|kcHK7*c@&KP@=!flTYUFk`7X1}$ICP@7 zssKK$%=a4d*=N943{I|TRXArJ;$39$+PZHt`Pi=cIFEx4`D~MGDsi!0e6BrR2QoH6IRq!a*IvbzM*s0EXM3rqe9Zko#_o}O zM(iEVLi>j9PbV6)y;Par2h3zo_y3PyzM{9nVs7T7+az*W1R7+kDdp7-uDkQ7_i+lP zYkAgdAf0J5|6M;U^l!M#HD03~&<}a8hIrLW%a*>$!Sm^TCno?cbvric zd4Y=({OlaE_js)IfZyr?-{b-RrU(3x2mA*f@E1MczxIIhVUwy|1Hpn+@G&0n5)b%| zfNR~F5#;DOiaNdabGp;y51ApP=PdGn*8~3n5BLu};IDeXf9nAc;Dsg?AF=>vyB1RT zg=FVgjz@mCE{;xBdMg{M<7(-c2o=z6E0)7W4yq-y(*#slawieJ+Xyz2u}ZuCTB_=r z+y1z_wOGAW!kO{Y>Fc~b7~$h)b$Hdw=v8Ok*(?QOBOKT?+8t~to~H_M1-94`YBixk z1DN@(FKBYtkA#yZJ@Ke0bnhm#@-CNuCGpseTj1-Mps@emK9-g~d%{>?A4f<@Tf)%} zTCBd*og9s0immuA^NGjQt0XxnSk%jSf-F$s?wIPuHzeM-Qk&dfeTnV&Br zHjThF6X8;4cC~+J$A>Axu858rM1z=fz=y=dU>{yJ{p?*57kJblKSfXnfAUclve%N*!1k#sum z2+lQPaq2|49B(rOyw7+OaM{0W1zhs&J`ebL0S`GO=>O8!PR`$Nn^zaonJ4n^HxCfP z%_BwM&BV(+6X79!=KQ-(z$Xa!S`YXW0xsu8hk(oWzANA|zg8BZJ~#a#Dv=Ca^791& zm-vr+z=Njo?)jBw;O==b)WAuPoL_d|5XK>&+?-flvVHHfuYwkC z-%HK|FO!Aa_kd5WWBxC4ISPSxHo**EoH;3Mj!Wer1We9ZX7SQ3$IRrjzPKDltS9k) z#KK5d;YYYxz6jE3ud7}QH|(~T>S~-3=O-;c6J?2W7Jf3>`sEnreM`TkBMcbNXW%E( z-x~Tu5{PqK&K~Cpn9TaGm)ZWWoATx{l|W(Rw5PdlSo&?oui}J{g0Kac<8d>IBIcU? z$FjD(eRi@Pt}1ki-T*xiobS3!5XN9}(dC%^9P|pjI z+~udwDxUpubi*ar6cl`1-LPEX!HQ73%P5=nQ#H zJ@5HIK-*^0xJ`7oL%wO7$V@mKXJ$ zNZ>!$+mBDD&h}P4cK7IU7B}&BgU;c=9R|E{t8`I3A#9M13cXE$`>{ua|GRu4zr2IEB@{X_4bb6l%1cB7~#GO)CL6Y}B-IduZ+-vS;* z2Kw4JK|gXc^h=Kod1Y+uV+b2m$sMsc4i=kZM#qT z(&s=QHhBQr@j+=j*VU~$KD26>2pnuf7`7N2GC(i*bsjpE+m{7(d~?JR#k|SJ7)MM? z*pEPeqInua+t^p+DcU~u5OhK0C)>IKJVm^(!(5kN_m6p}1$GLE=M5ar+D|z1kvEnv z+p<+Vg5HnreA?H{HnQI$n7eW0{UzX*Z++$#_<3oQ!^3gE?=67u(&#PzoOeij2=h1V zgI>hY&Vk;mZyWy3v_auM>eB13ionJKeS`Ouog6>tcjy;mi=$t2bWW1i@1maFo3qCe zx8@7-aZTWu+iP$~1b;gGYU&}ZMI39dV;!r+`7;>1q5tef{}t_^9{LTGXWgWSb>rAP zAcQ!@z)dUW{O_73GfZ4*I$bX@2y z+=6lPD315~%V56d)VmyOChKVwm#6wv(66K7}2JWwu0+%2n!`OPvh{lsc@g3J z^qkU?4#b|0V7!EYXW8?Eo1+tg&5vb=TUlpCrfPk32*!PpucxNW*8@4#&fC8k?s*3F zkT+-#-ftb9x#q8qr|w+aXMALtzdf=|x83Oj$;WYAlmFg%u9-Yrke|4kP>YCOkJvM7`YdN-4U;l+G zH(VWB6*VUatbA9U2CdO&z&V7P1gVa2c6|rle!yztNd@1q7K({FO^hjL97(Gkx-LUu zk8&dn0;#j7{>*-ZzsQf;(qTJ&4`)0wvh4m5yM~uNFl_e~H|$N{GqmiX!4D28-9Knw z+B_STSHw`>>0@qY-ZOM>`h!Cr8oV!U{~)6Ahm&D`twU#N`c21O?c58HLcyuE|>3@O{4{=m@khXy^ER=$70zJdOm9d*6dODCL8V?O48 zVCe4jJwx^melYE!LHh>oA3#LQXdj?!`x(#&&4>GbEV`&`?Zd+!xuWd;p}W%O?n&D_ zXu>m8!z=sCx3*KQoM_(;V zr!j%f3fEZcefm{?BM&%-P%1p{dccRGKT_p~EGi}Z&phDsJ>a)`!2b^q_-+sQ zUjt6tgBe^Ck@VV#<8vPQx#py5SEs@Ak`d18H3@iVH$?m~=W(j^S^{{l2cBVACsN_R z$^%~H0iOpr>kS*-kX?)D2bl^#?AskWO@6&jksluUf8+uG4-a@hn~i$LQc75B@O8kN zV$gqDz8)l8keh^0b zLl0AxY(pP2j8A9xA+R^p-MMCM!W@H^9(A<|+YMplQBzY>o#3L&kvn0!aoZXMZ%+BT z=4H^)$BmnkJP8_5^(!$BIq#zx6dwua!{Vh zt>axN;LsentHh+7QYO@G9|-SpeNmsu~L!<0xs)4?80yJKP%ue|4Rn$uD9C* zzl~$;Ztoe9U$*O_s8_;e9Anwu@#gvL9#?>I=RQ;Ya+j- z$15K48I#{lPlYK=c*vs&k6V$0iPt`Y3BWf`6ml_j(|@QaOit< zqHW7m0q++1KQG`RD&Uda>)vDocdvUh44m}Hb-P%=<+@!d;C61YzFP!*8UZH71l);1 zc! z_Wk_03vS=Hi_JQ3^V|1r8?VE{?fbB`RkZM!>F-Z%bM)UVu0@VCm;*oE@BUu4M{zUw zY&?FlhpactVM1=kxk`8dKbdU&YYF4I>AnQ`YMc@0CoMnI;GC7f=$zR4?{mQ|{g#d} z?(^IXpG5As;ag1t;+)v>7F>xFmY-n(=2&iQcS0_>t=AqG;l4eWS!+yr3FEmt?{Wik z(_e4PyBO=HKZ^4F^bO-D(<$?^^n?Mj|GA{w@^)<^J?^?$q<$p-L+(Z7NL()X{_8GJ zoGuapLEJF&QheTp+}(awldAmA5V1J&80XCS?=C<6ni(Y_k!E7&qJnEm3QA^#LbD2I z%$ymz24|tr%o#I^Xth*OSXAs}zx=os){cu5gf$sq@FQLImIqzBKG-bOT{#K**zZ-e z$F5R^dGuEg(_cLk{_0uqS0ADM)sMpWmp z=!?1~Fs9+eRjTUBz?k$F_&{z!{Dm4^Q^!~{0Y0?Q?aiUTs`5E8LyaG86nxz~Nfkh% z^YgL*_7<;?7B8#ME6&sL9DEJ*snqct6xut{vG+JWK@|){{`Sve4{q?|FU#|HFs26E z@dj+UPQiAI*N?-m_Jb4tX4>&sUvT=o(%1O(-(YX`nlXHJ*~NBJ--H)ZjcVf55rN-z4g90u-giUm)&-&BF@9Bm?}$b5z`(Zcpz{S4+`;xi-nqc9|7Lhjb$SiGp?Bv4oCN55M>(kGa@(mpX0%7a>$Pd{Pee3$x99Ibyb>mXgb zu@^M)zK#2gukgV={^l2;`{kTsIXkbqtB16nUy-fnljgPYt>zlWHS{RjdLFS}&J7xZ zSVP%U{uRE%ww?b1+&uqh90yKRBNPXb0>aQ|zJ;la!M#)FXv-Wh zdBZsF0>3Q$LBcO1X1{%RlsZ(tAJ}(+Z=>_6L-m(F9C{?T?EcU0`b@uRvzA)7-Ew;}*Pc`)PIOUFmoo94;7_RobH4A~ZypXQsdQA%_u8O7@(NCvULE}F>q%FqK zVf>gV+u-+*P1diHa3dDcx2*jD;qo)we$xRyvjQ&pa9+SAKQk%tL~`?4`fbYm+eLoakKF<;WobkC987_KynxGo zlzx@6U0yP?k1wP8FLH!)nyo@OV#xHfz6b-xWS>LMRsXftOD6T6nRHgBHy8+5k6Wg2 zm4UnE0zWhSxAod1ameH)le*mUGl7gaXGo+tx8*}FxUJtFzkvJpTxNauGU@-4Den@U zsP|0y4v7@!mVXvJA19nTVGA(Fh*_-cTqXahezD~(oV2^^CJL)lYB4v50LGuYJn_2w z4j{FVnUNlLF~@bOxCW#uztPbDRgES2&s~1{HP_4%BB77oJIlJWg)Uzvv{qCa)}(|X zUjrvD<2^h{dGd_tKK?sws$L@RQgJW!J0>YewV#9gU1kF|hpuL5e7w+n*!tBkY_!+X zm2CQ_I^$YH-npk%*aNHRHk~66{|R$*EUfSL|K~1GofgOcCoRvlia6bCO&Bnykp7?i zXY04eLfo?F$y`cBE1N){KuW|9wd`BCP4KagBf2+6noP-FFCb2*}7N`}M;m(%F*< z?^io_7p1me?|{!7ZP{rv545}X9HPDa=(hMo$6tc`D(ym9$Wq#PKY6rv@X7s@Xg6;6 z3}QLTTAebNZFY$ zpYc)SUvhluTHu=%!oE=(Aa{x2ReQpTaQn7VfI+q~=LF*WzJnk97=0=|d(f-EtNyv!Fz{kKEra~EXNuK?E%Vai)L1~E|~*Qth__eIDGS(f?e zqYxTiRS}wWE?@xcGYy#w*YS)}{ z)&7MXRS<6gAIeoDug9TnEs!J6ga0S_Q#xE_bRw>0#hUT(3(0JNEL{5|BJL_=xMTD2 zB>-R6vH9JQah*LjxD`GtQ$lR#4SEdjoDI6ifmcbIo%n~{kb$vX5v?~E-Ny2y$=z<2 zr>s!lOB@}!=EV|@ch-#*M!T6l)*AMOuw=*^}V`O&BLCjsm z-o@erpUtw?@n|n(w%RX7`eTbT1#_5qA~@35 zi1K6}^&CcwVtlXe`~v#181$ag{b=4}3jj?SwCb&nw3?$2NIYfVl3J>^t4Y(fJ&=oW~R4lSv;m zXa0`P=iL1Ob2l69yVkVt72Q6k|17O+Lqx|{we1^s8SQg$Y{vMm3S>@wrtAwlYR+Jv zI@E<<^J_*{Z)w(jW%w7z+7?3p+c|3UxaTUz0mlR9yyX+(NlooSJnTu})4l9}qYtq- z{2J!aW?`2gH@DA4&MON)M>u%ManE^BfH|-UbAAJO^t#{Icpu{w^ErX|^laB?ta&*Y zJEu|R)gh{2Y#@6q2a138-9^|PJAts@fk+xdBh{dw~dx*Z>mA0p|9JN0O~NTYm?u^ja~q&azXaIn5x5L@_} zvTJuZ>s3zv-|0R|t^>9|5Qkwj^g4~(hlKAcMVw$hvm$!_{nPdMxY|b_J=#=x9%#ys2#`a|$} z?t)I5xY%yeI8Ke5>Oa+s_YT$m?`)$PTb9?CLuU-@x256Z(D@vE1}z^;L8n6>pXW*X zUiFVl--LIduvtUZ`@L11w^h17l4Hu^nGQVE6@KYb?;i4ydlK+^fw_*q+*{zp0ZI0? zEgM2vp1%ei)n_yw2fw|aqhSt@Eo>BEd@k8JI-J)i&-+8gIr}3G*L)tXzodP~m4`3n zM}BEr8J*O3RiHzyoa0%XL*J$MaV+QFi*p}H+dXLho`H*`OICz;c;n%rkEGvVeYs}% zlHXX54bgbq@q({sz}`xR3SPmW!T#09j$^CI>woj>S6}NNFIdJ3UdZfUKYnZpcC}k5rdaug8h~BvSWPSTb+~AbiGgI@nhuzv$G*2ydBd`;NjBr3SCUc7B1KHRNL~E zbaPDqA3Er7y#+3`CpRU_mBK&J#wJeSEl=LpFm9Nch+xcfAZH;mJ9PppKY{GS{l)Fz zP9@90GZKll^i5-MDSguPcraN~>EjCYJtH*ki%O-^>pA&9eH`A|sLPIJS#6~Ue2E8q zjR$ScGXuWOpN7ET}2X3%r#Pod$8)-@&kdH#q#L(py!GuvZ>wOFq12;O=(Wc(Cqvy(jR4in1Q?7`;>vZ+xx7*Biq{{;Ih5a*GsndHIZMo_gw*(?L8ylvb`4t zT()uO`%&I4>=zr~pK#eP#R8A)mr4Pb{jyNNWxp&HaM`XW z4BXwWrwrWPu4e@v*{%)&m+i7XKJIqCCi2U6y({3dU1tPbw(FvR%XW>Ya?0>u!mZDq zyS-~oes_B}3OusC(q~V$cc;iN`*FX3%l1Ag;Ih4k1zfiGIRTgL>K1T0{)h7W6v^G* z90PZ^H)P=MaXVSSWqXSST((#G3d;6YiTtv?w+OgwZ>@mK_HGw&+1@7wT;@OJ0Uv7Y zQrKRZKjZ-)@31rB+h#6Rtqa~^Z%k{t^S1TTWzd_iU*{a_?b&7Rwd|!s|1aKSxz_N* zHcR$3VP1AW=S{}2DbH>ItNYoFTxHoln+TD&Mp1+I8VT2*56!a`@e3=o7eLMinuAi(^h2e zSo&?oui}KSeqjqR$6_n4h|=3{cHxk+*ea+l}wd${ITqYX3r`%wg;DQH#CDnCzHbZn6xFhgnd>|FYzJv zpaGS-#j|M?uCPQdG6r&2|a`pZh9zze(a#xm^jictW) zm1@Vh*qH-g7psf1dSUu&v@rgt(GP3inTd|>-0@{`Ue(^&uPfIcR?1-IDNSZTZkV+7w&620ba8oI>CGR zR<)nVRqYe}YIb-8e9>m8#upJ|5x!n}e?sni%lfeAWd`@TjZi;}Uk7l9L2I12%zn3V zz*>5-Un^i2STA@Lf<80;hhFTp>+FeZY2oqGro)N2jI=9ZY(|!)K8xdn24^%z( zd<5R;u(A?gnJQR;aq$nO@I~wjx6gs^-O5tu{t1jf{%Y=m4F|>-{iwEvRn@Ke;hy{q z;75CN)xd^R^PT+L%yruJs_Lf-@v~7!?c2`YnOlCV+OZU5v{c}g1bm$XzE)PKs;%R3 zj##Lt%2m|~`0LeR@6Ro;F$v8?+(}$>FVH!#KY4Mwsu}FjlB_`VGFbq!aASsm0DsK>*TU_lFF@OC1eGyNSyd$AYs zpQFvdF{iSy_!;=E<*KZPgYk!u<{#d8>`vUzN&0OUC;ymPhX1n7m5TbB(&}HS5%LqkW8lZFN_dHvP<5KVCoZ zbF2&bx#0=#)N=jIL;r{e)SdX|UIhEg1>3@*9ST02Kl{6!SJ z@4u|>3%1URSKQRsceHHA)%G5|Xb~whL@vHQY8ZQU0_8u=s{#-S-PEl1Y zWtcOVdyJFJK4iPebLfndeTF{FGrYnYUBJF$d}G@$>?h{8JahP!zOvDHSD-p*3OY5&^MpOdhpY*n%Ol@RlSZm^aPHagWtfMd>rG4bM8W5KzkDz_ZW<39{3SYJ3jeSE}@4-3;d2~@MkUJ}K zH}zg&>lw5HI<2V zpy5Tt!1vFK6d%F)3iuvljE{t`a`Sfl%G99w+uqA9MqK-<5O~*#xautXI`XC=Mm^pq z7F@tJ9$2F}KFUz%1m&N~IQECXY9r@mg1f-ek8-*%lkL%w+$Hk&5nir=x?r>kHS_Us_iF|Yp)-=eU1atz_s@v ze2dxFdEsk!gfNe}KGByv*Z7iOz#4EuuZ01ug#qZ{xp#vz7QX}iIq$L0J7C|yv2qV+ z`7-9s3G~@{=(bs=8{@=@2|cE5-;G~Jy(YS_3 z(Kk`dn>@^uZ73JRT1xwe8t`B==#GZ-^mA+<-sw0F723mgah%X*f@{Kjz~uT(n2yhm z_A(#F-A??PkC`?0mUF$>3wdrU_faP8156(rF@3NV>qH21lKoJw#-)cBEGrJ;SBCM1 zuax>WApq2UjX*u4LWeZ&0AUVHV6|M9E21T6TEUoB=BWE;}A!^c9l%!4By8oqDX z{ws*>?$=)ZD*Tf#FS8#zI4`*D+)b~(b|b6t-#mmH8_&gF$h^EkU)8+!YB{g4=kYuq z=V@p;!$p^}1*HU5Y9O-ctk>(SMf!i4^Z&J1HGjPRv0FaAUrHb)x=&-9p~nZXPQ{Nl z8!-}wr2F4Fh3vp6V9YfSc*Y?0hZCC0X2Z$<>1{UV0{;kB;!0e6Qo(QcfZyu@|DFf@ zZ$02Y@qoYS0l(-0&jH_4(SM}}yvPGS&jbD!fYVlFgdYST>3NIedXM~n=>dPp1OBuJ z9N+aR+tuv>ciWuQSep}^&`+vn!zx6*uU;Qrp)_R8Z7@91*V9%ut&2JqD8fUVuHH29 zFrLy3W?Huqp>C7GRsZPw8JntD>uu4Rgki}a*K8$WjH0bmM1$Qf>3wzrCQW2pUt<@| zpPFUhk#_ZV_C`)vxY(Gpw0O~54pgsNxwbi zKv>?URclh)&J^oW*;(1oUAvjE= zv zo1!{jw}DgVFX3{p-8`Ms`L~Kn10*+|wFd6Sv(dmwkHoXr1J8aBJlLa2CpVs}hdOXK zJvLsbo1Oxb-;HOZ2cFFa?#8p-1CJf^jEQ0%oti+tZ!lT7eQ$!yLMIEi&)X04?fw6f zuF}RgHO=g^_7di$t2|{E(Y(WzK3Ex(o>YYR4zq|bOf*A$Y=b6Wk@_R0tJ-f)sfBCw~^I{N%H6?b>-scj! zDeilAM(C#IPOfPGMt-pU;Knf-bCkdFD0Li0hN4=0&FHf}`xkC4HF9~xlyvqXeL>6G z4{pqXZ-^iJdIlS**E)ijlGJN`e>CL47XyteM?<~^8QJ~W>TvHJa~tyDKl(m&cGUYE zQ8OCjepPiJen(VJBL+&<6WA}eMWroL8?!TFkZT7ZOQGy#>y+4H(nK1!Lq3Hgf4kz4 zc~}{>-FNLsFx&|Lo2q3um-R#t^UoK840D8$sY2G*FTV;k9)&+!9CElQ%CuZn(SB$` zMf>B^D%!VA2txLH_wOg5eC(=V`!}Wq+rw##?}|ZQ<(nB>3|Zr?(A!rnLu^jp#?NGg z)n{f!ei&@us`FN~AAw#h4SrO_y$v|?hUXM9j%PJ|WifPT)gW&KxT+BcG>W}1x1+5m zkhk`gVEaThHY0CXWl^5GZ!u*xU*jkRE%Z0q7K{Dd`Y>(H zuV}v~Lp47D+_8+b<_*BjeR@$hBi-kc~Kp99(b`@Mz4OFWTvWx6~9QD~tD0vL}1%$zKB>N(8>%lbep%V1~H+er#_(Q6=>Nl>B7MgL5al|_2K?Vn2aGdG9 z3VR}QyxDP>Hzb+gJ&ss@I?A)(b{je1UL47ji9NlA6C*4e(Ea%LfX6YHSmtV+vroep zt7q%J3n%*yny%)p;7L^USpe12pGmS&uL$A9y0Ya&>{a2ZLRUc$Nf=X zb2nmw4uGC?La=4AZy?6Dv7_J~nIY(*C<|pwPuoxQS#xw)|6=S6GNDhSZ|k^x@+$(o z@1woB3svJmtVvt%4wuCI;gVm$1_B>98Hn$jq14z}F~2I=dbiR#i*Kry#V6s**{%H$ zsaqHiT}&q9i~jr#_}-tp$C*E*sSEKd*>6dGP=DG;^QBD=eT=(`ufHLAqE7nyy>Dc` z|HyNUA(r_m&q4bO=1AC4oO52;pWH)}b_%qe=t3XPfzFR{kAvu|IQH?)+*sOUZClQa zM2v_~Mf)$?qWnFd1&-wo?tn27oJ)iL=(Qp2j-raZnGoI<~Sd(5KrW#{d zOI{y~v4EHcakSN+%X#VO%$J>o9SP<&^%;2>qp@Ys(J>AJ@-hy>L99Qdi!np?fH!Dw zMztEGz za#tzldAR+Kv#OnAmUD%)N4^I=(y;Opj#-XZj@!uh{D1{Y7=PsZf9r2Qyv*10^zA-8 zAE9e{Kevcu#I8q}prhj$OLpGa=PKL2Efe+`oGU2D^5N6DMZZUW;BO}07K4|3?7%qX zn!+`RN8)v|Ig00f6lM8tf|a5$0=jt~MH@&z+hf~+d?gXI;opFRJks+B zJR+|wpWHl&V!RSR>0$k(gFIMkXyW;8I7gej{8!bNS2t}~yLQdG^>wwOC38cImz0Je zdJ3(AU~YZA-hGp$m8!UNb@aBCHTq`ln!2XY>NV>_2*?zw{0d=|RW*gy)irKdxel0? zuUQv@jO+H5wY*prUD0GdwUw=a1wt!V*Vb(etzWYS8-T7`Q5Twg<%TIHCB$glwu?Radj# zNI+SKfiqBMt;2$9E1J_JnEO_sm$*k{HEY)1S-p0{vQ^lc%94!yaEaTnR@Y{Mz*L7U zno*Y-y=#Q79dAx|EmpyepY@F!nyd9p_S<41UMQh!O71uLWhkb8@iJ9YWxE3p1fz7V zwUGJp!cU)G>`m%quHr4nlh=Yulc4lv`W!CBF;ut9&~%s|3Z=td@;yBEkuhcW=j<9? z@j&+OtUZ}~N0mRA@zBT{_YdDU;w!Jc3OD5c_*GK7^^%WSZBAy~H)8*A;#f{KQJ>7| zj!vnJIwfSn5mj!)&&m+BUzcqEJhplToQF*_hK21`p4`ZDiEc;L9)ImI?c40QEZY`; zQQy^`$Jn%Uk6-UX3U_5dN{^XFdmPA$Kc()9)uz%pWomkiAW@$?|MX&z_>vYkaGENP zu!F}407Z7nNmK20IoZJNIHZh&sR%#jFVUxg*E%yZRP_8qoe_`xR(BP}8mQGF^p>twlQxQ77mH@i z>T^{hudb0-g~fex78Qw{vw@}Gs@rGV!5VCB*mvQF9;asQoe8xL^+MR)Z%u7-XG8;{ zQ+Fbp@NZt*fbAinKU=ZpwmR$rm{i8$allm{2)(sz34~N9X`L0auU)fp_4?}DHmq8| za_y=lX+q=VJXiQ2K?P`W|0v7oj~Vzexn;%$4p_Nmz1JBy^K&&hZmv0RnV4U~7dqg6 zx}BE{+~Tq8!^;A0VdMtjM|231}O=sM|DchDhC8=u?q9heGf;Z-O) z@=m45KgQI>gY^!o3u<*$yzq`G~0*~b9bq4OP zH!SkA-lt5xl_I}{FEwy?y&VEB`PnVtl0O$c;MUK%AK&;sgXE?^)4=Vx3hP|hH%#Ow z{T4piz}@s0yYLt^>N*!53l9rCQfDarmaRU7Wv(U>NUT@tvZSt0>ge{1{JBn1{on4T z)sH_$=hlxu25$Lt-ryQ9^0O)npKRc6{wx)6*}qQ+c%Gp1MFE%e9~W?$U;2eg{O_4T zOnM|9%Ui2EvQ_UjCl+p>gN)n3WZ@(1E6u0%i~Dc3SKHN83Wzj9ob%L6=d{thU|GL@ z>Kw>2yN1}g>!ovA<*Ju;F&VZy7x?d`bGqE}GY!sJ35?E(^_%55k;&3;!C~CwxmnH= zS$CQj$-hiMoD*B#f-7;t@-r;J9LE|RZO8?;_1fbi+_&d4>laLU3FEmt?{Wik(;qhF zce)C=>5rm3m##2=GKI~wRgC3J&} ze%Ga^&gwox|5_3wlDqu$f>{NQ4$AreQ97%_f{!1ox5a*}fR3=HC6&%9p#8j>g6go5 zN9IEo3>hkIvVHlbkd;xsb`G*(pwRwvA^3IO{)&GJXrnzXh`Hd60b#fUi#ihCFkzU)x~F5Fel9;NbP+lT{=2Is;*g z|2fE;S@%iEBUkK)oV6vRd3h}NS+-xt6V|bc5lc9oG&}xkb49%!(6OzAY*OQed=#IX zRRa+-@m{raao0V=W_jU_T|A_=dC`9> zaQ+<5zX|>f!a0-=qivhMkMl~^l5xFCOMe|cX=x~rXZg;@LF?l&)%@li!)M)~2BrVi z(&f+o4e}=2=+9U26#9}Y5PK3bcea!E+NUudxDQlvJUBX6j@Rw*_oScbX^dIyF{tBP za@?MSkH8s>+4F$`ZCm^cwaggr!c|-Rm5mYf{g$%IMqe25QK5sdIy~wRVnOYTna{c- z1J&U?@DwpcdhY*KV9M6{>dx3S>|Y0eDC#+=_uw3`%hw79W6YdgZ00OkDRR z^u4w(^R7gUQ?!qBBH5pP^%NFol2=*z)EOsmT;(1QsmpH#{V$S-hGyz7I6f>ddAzjg zeyW>X{%-5%V~fw2{!6Y4 zKhgT23KdyI{+t4Tx-q|MmkrV58GfDl9nfcP+3jz4mr2%_nXgcn<-x&eZXVb*$f=9# z2>p9HeCqI}P0kwP|8{B5X{;mE)gOZIomyDh!!-_d?Ar1jAMPdRbVs226~MKu*!fBh zIiKeg2QQDVTvb>51tFSdzUeo8sbcQZg`w!G6>HY5Twi}%XvW4XH-0w8P;&IPO&=mH(9c=E4~OvMdr25S zCd#1KMC;a8vo+QA(WZJB+2R4|$fo-l_kM&>Ld&RA*aUyHzoq`hUk2HZcee6Meh|En+m0&yfk&M#j921(9dA8TGT zvCNl=!@~oG%qG`oCDd6hX+0~pzQwOuE19ka{3z+XE!CzbRSdJ z#&jM3l{tPV<@fvHa)PFPNMf=7Kggo(cj9EUmon#&;R)YInfUFHN){b9@P#-s+41>B zoHKvDh9+%kZ!z%u3|xM<{wZbAx1v5Ni`Mf8uy5gK=b9l&ANF~`S&n#~GMV*U!Fh*) zcW~|?={bSpZ}3Zn|33lOvR^!unBw|BJS{Qc2!GGO^?1d-iGZiVlaL8Ftz6+H6E2)x zq{^3krK-Gg+ROqWU%WUi#Xk|a9TN3_gZW+>M zlYufMyhkQd%$yOPmVhSxo>;GxtiEumTcx}H;-SGV;znh*G19#VJ?e%TD77{tq zb0R(8x5V`7WpL{#*;d^>3mY)k>lhkfk(n$6#0q2#X+0c z!;o}J_)8x3hRyooZf}KwyW4B`B(&qF!_-?P^0QtGuQzaadv^-BeO3_FQwHv)=di#p z`S3H5pY_Ix1nDJ_U&3EDa5p_N*5!Byh5m2Pt?bj@vi)q~PnjD}n4^W;=YZ9%Tlfe= zN0pgh7XF@re`-7a|8BBXc7jOmXPB34buWcsNFl=)%GSs-I|l67xyr!JFvpdXR=Mi6 zaKmWz1$%8wWb42NDqH#Fn?+bro>aA4Pd~aTq_D zo;3r-&bN;%TeYz$l^_OST#@vSIqc%H+EAl&#Jf>6BV43*+2fetJPc z!N-!V78QPMe}KJ|PMH+eM@O~_JtJ&WecI-8!p3m>m52{TStN+8x>9Y|=Pj_83ut(t zf#)cm*%=7Hu2sue$dl%#~2ZP~7v_F0kJYb$*1D0pn^8ax6E^t*<>HGLT=K$hm z3@?>h#=%=krbwV-O>PjCvI`=WQ%;=2MIjUrFilGiYDSl7ATOC&qTR%9HrXiCMKUXE zsxh;&JE)~iR#sM0D!=Dl`+X0K%{g9X>ihqHW_{r7wV(a2cfISr_FC_Hw}G<-vd&Z9 z73+am%R!y4MBY>`u+~7U;BU1K>cBcHeaqf~bd&Bb$q^2JIOJ%9waY9cJeuMnS=!tP zc@`M8w8lw%@o%lWV$D+GZaBlf#?&(HBp0oV>g6T2>wZ9)J>W9dXW+bs8|6ZIoyGQ{ z{OesuL$Ho0>sHoUa$wgiK$tOk@Y|$ec|zn~?`3 zR}Ritz%IwyO|a)xfwjCu;8bQQSfhRsGCE8%!He%lIg@d%cO>k>cVV)ThtNA$c8ok& zgIr*Ajm<{>QT`jq%Oi7MRBL;?6fdVL|6brz4>>Zh_8d;Op1_O3lC2wixJ`#gPA5KF zwKY>1HSm`~`7m1i?P7Z$clGu@M&0*W?z-h=M##U*QO~8URNbs^d5&S# z1_0p-y9 z_JT&8>A-VKpWCWqPMqbS{K2`T>qrhshha9auQr&rd`EfeJdztDhhdCwPyNkj)b63{ zo@w}cpkA(}GNv;pbl#*Ca(#$$7#)Lj#fH>wLRtp=(lSoUKWcMSx1rac){xwsceGwD z@_mkVeUi~m?;X`lPkQ>gK5^pc3ATmQb_QX`Tr@?5WmyxW+wTFhay&}O|RJPEy%W> zlBP844qNFjQ958J9aN>mvOmz$GJ{&)%`3<&1%-NEFa=fz0xd3({RYbsU7*zm!ig1@ zDy&GD-cl~3r$}`Mw6!y`a&xls4O-4%l(OQui@`h&%NCb3tUOP^bEROdIGz!GF)SS!;cUVrlIH=?`1$ z34vcc0_h1`^gPkmqM&zAT00ddI!@7yyZJ#cz7A(x>VedYF^qedPNsqBjL%|R=rb9w zWSr`lxIk;Omi+&{o^TN&(br}r9l_RS?+3juo5;8!2)>Q^r!t{x8}NT0gr4eiApV_z zD>?a{LbVm}7{Iu!UCBG&`9b(x!t~V`kjSZaKptftr7$B)_0Rs*+*zdLn~^bjMnP6a z#-O2b!}OKexZ%3qZhTCOyI6fiH~zd9&*IKA=(FH0OsnLg|DAdai!0P=1^ku~JqTj= z<(U2IaTbjg+m`*d>aq!M+2M-nu3!7NMc+$#3rBqxxgN-WeNE6*sD04_6e{Pd3xjTANOvtKmBRRK_V@U4K$v+tumywOt+G z!F)tcH_NnBi61eY~Nd%PPl5hZ6&uY9k_9$kn+n?8DtNn=O zk?;biz(e7sUJ5Sy>23k|D)Gv7JaF;rq*xOO=`3u zGkmy3dEz!^)^Hml8B8UJ=O|5&Oq<3*1WfM2WQQ1?KRAjJkUF>#fL`2 zmd^f8EBQrKf!-}GKL7o@CA~B2@0O~3fFyf;bdfyKi;Y`ld z(8uxnT6&09ceKt&Jpa@1LlBmD+UFQ`z{vHrF8*JUU*s_Hg#0`d`swzuPtqw5B)r_G zz(e6<1duC7;Ff#7O1yF%4_y2@sXGuDfHv41L&B4My0gpg#lt{z3^$L9lKzvOW5~Pz zI!*`8F~}~h#4mhq9n*u(uUi>6q@tmA;oldx*3@O>>Z4*n?@n zxe5edY+$cO_TuVbi-vUO>oIpwy7R{w_bGbm1N5=q4P44Z^}QEa>)>PAmOX_F<|t2p z&#~SziD@r6OPb(gcbgXaha!6*o9px}&|HG%4EmTWV^TbD$wLb3cf9T?)~v0Mz+=%< z8H368mU=Tv3p26{r+M=VGQ8Q@#W^J<{=@qI6~E^7JsPuks;#2wq=3#|(}ImrCmMbTVj-UPF+#$- zZBj`5avj0pZDcq|6WB>Od3rfKgxSZqjZ83H2>B}cC-BAa1R5iXn4zBk^lB{O1rHQA z@jgI5aBdd39sKlf4WROH=29Zrnd&O=}`QHF@etB(HYT$(08G4_0;2hAjXq?vSpb9oduKc zeb6!43cZR9x2eu<)=j3G*iWH$#Vp;-zz( zpW_T-u)K2M+n9PjQCP|!S6g4&v&0Aa?gGt5_zmP$DDgejlIv+;bXKqqSIR^B4}lI0 z__feY`#iw9L>K5hoyfWbcu^Tc=L&jG)y+Crt9sh>PV9P4kc;%3lJlnIl$5sCxyUal zoLPXzJ0Zn?&hD7!_B6UaK9-DLp?gwFu3@5M{KSj@PLaX#EDCv(i~U~4yVaWVQXd;Cz< zHiDlaZM9;Pg~LiMO=2Cp5e9F25O^w!ZC~G!c3@xMDP?-vGt+C+EDe`DBIpjr?dv;l zXt-787O;$~qR8WBx)mC(^RH%HN#|XezABT6_aEVv01kLPvV#Q6YL!+m50*Dh>7Oxc@^v( z=@3U$q=hA~J^bMK*!YuqM~WRjSP$n)A2oqXwt8z zGXZ3$gx*DVWA5z0I|SL<0SmQUaoP9jYE{TL=I~@Vu zr^@k;A+|aw4B0-X^8*b$?Y_><*D6C8&Put-QGgdQpXbK zW$(S~H!~4KRv4BzmpaHK!zE<-R}^{2z4xx_W3$1JoN5ovbM>*bJ1Y9Z%43lQ{H3<@ z|HT~L+Kbd@RhD?a*WPF(r#>22n!CICUdn@R1I^KYt3A`<;IGfoRrv$E3jfrH+Fc%i zK=}2*iO)6;pvs>7JQpv9x@n>HvA_V9Y~zLu)92%{Lsk6_J|D;T8twD%78|NTTZiAi zvVHD3mF1SXp_}g|9rih<%=PSZ-dP;ZKKGP8MvAw^T-z2e-x@14T*fhisu`Df`POfr z#UAfQCa}l5N5fl`CpA1cdwNCB+0Oq=jb5KSyBQZbsgEJohjF_+!RFMtRxtk_wA8Qv zwYjs&`NGL<)y9I&om050l6SU~ojdz%@k;!5cpx57J+x01Pc(e6xwC}-Pv_1DSWxQ6 zbf>o&!m0idX$;+Hu0Ky^-5N$-Nxxi!&7D*1lVRo~;e>6lxwC|?6hgk*<@W-oX|Bo7 zXbM2GZUkEaH-bH%{*lW&!4Z$z57M|4A7*F5B*$O|M33TxKa|YJm zQP0w8k6FiQt~%0fOcy;l*b_;|cTS>5f?r$Ocfb|rtfPJ4Mf(Y++t&l(w-2Zq`ODfoUFi%foxyy9=k5l=P##@6`qI?PFTVuy z>bxlh({Oxngyrquw`hPn>W_XCcG?$-=@ZPyTdwx^o%-HA)oH2ACj8{$@K603xr6l6 zJXc-pNb~FRHLojQWzBSnm&|dgy^tepmhv^X9lmXKp|`ia3sUzfJzvz`T-+gg17`}OAw5e1ct-CYYH z5RP`H=CCFQP;~Nkd+8fO!E&Uhk$zx1F zcvm6DwLS=bfN`4hYD0k4C*T>)VRbwl_vDD4#zk=*7$#6!Z9pIi$5iB#$zVdVbB;oa)4`A6cF>v%j8 ze>0U~d>aT1KpSk1e1OAO=uF|a%kKq-xl5}#GVCNP=dms)y}mq)Gt}fO_1h8nm-uB~ zalARQ)IS!ZRbElwW`DmT+CwaVkp$$cJzGn2rW9j`KRf4oHAOz|_lDz#i9MndpCik+ zlSu?q$zftl>qK%_W?^oK{8w{Fn!hHwjjH*WyXJ(GZ4e{h4gHf0kMUhKuA_3Z52@!( zP5$Rmu=kPE0kp8a^CIl*V4j%P+b|kwuIOgnO_^67nez{28=7owV=b(*4&N0-`NXaI zWM!In;`7Cku=^1OyF(-o#8fij>bKnzmG4V?7kZ(hZR!=+n_M@fG zssIwC*)uF1NZi^$%b!B zX47dCGSyO?8YSC)~2L0uoqO$)m@{rQV{Vyn-oiH2%D- z9CzOm^|8oi%iW3ybeCP(yaRz-vePnzH!kRw?qg&l;~Lxy2Kk?XH|ruPGVnD0Ct{4!ihda z2F$=LTcAX5INdFq15Kd#*WjRFMa+5P{Yfs6MyUUQ&Si3ADCg(ep&8 znN+>s>1zve_P-Zs^!+r!Ek3O)3e_J6a!6dWkLF|;DQwQ-(;B}NbPkPP=7v`?F86ZH zV4UJ7Cph_CE#4vtk@I=_+ogq5{d8#b!iVZB;d1ZOipYf%Hg;#F>klp7n}x;&#pyuK z)#3z(MKK2#eP2=957l47NiK4tQ}zV>5ejMf^K20OU%-h^1a-`C(k>d{Cwv{_mFg*e zw8^nrN@-zdCq72Eo)ZUK=@vQ0irkrMnBb9k(9rmpAqGvcGic;d9vYC8hsGq3lV6QD z*8ZjPPAx3V$48C5S*3KM)Eb&NjzD8pi^UVaDEK&q1f}7urT(FYSnRcrG)o@fN^2HY zTeU!`=d@;_a?|zM5$Gaguaun}bmRJ3jGH%a@HH=F> zxH-&Y8m^~n9pjP@LN7X%gzNMhnckic+k)`lq4C%G?9u2c|4o*2zeca)hZwiV+l|{L zrB~0lGa0wntMx(XHwK~CzXz)GXK@V&;w3qUvwYGo3f`ab7!DwK4C6W$ zu3p3Se2_I$k!LH@MR2}KdSe)u@)3IBYX+gu)o_wW;w#c{U7j;J9$91MTYtF;Uc?Wi zpAlTfosBj=GVc6lYp+-@_YR_Sk%QnHG_??h+zj$+U~!?~|958=-AFfOE#;ThqHQ>A8y1)`%AFC*k{eB2A z;%Q&2mGBqXA{6-rHaR?ZW4Ne z+{h(7+LL|~( zz^hz6S4cPC%SG~Cu5bPssGj%Oq=Bw_)d5NrT;*LMd4vW zN^6yQ0AfdN%^p73T6H}wCc*t;UHrfH^wWESz3hoN)p~(2?(>JV zJofN|#C=|j8*WHU%urgTJ}>^{&x@|(w2%a*62r17K(@z8pF`P& zh7Iv~M*pEnhA|W*^jh7u9`>hc%~{r($<9FHKod*BW^GxzG2O&^f z@GzYz!z5f*t}(t0>y)=*Ez^N#KBGJh>w?!AxTiS%_Vn@0bM&gAI;Q(2e*HU$&>LAx zJb&zBeJgOJ5kWfKYgOEkWuA)5dEF|=M|vVZcA>RkOW(S|bt>s>DE$$^DZN&lmTheB zX=d%WyoUS#m-rh(e4X*_g6MjzvpYh}#we`8l5UHM^tQ!6+3Gj2uIfXYN3JoZ*U`Fu z#L6C2hW;|u)`07UGOXkHF5xRx_ATu1!`EY7s15&~Ye*zdkX{*m zjeVwJ7}$$}`|oX7(Ato`Rw3m^V?5=X-CYhK5ROWy_{4AkDW|F+^iK!DKMaDC4z60; zVE(H7;qM1LkUSR$!AqEryweDuB|+$GgW$WE&pKSmNxeE6guV*~tUz*}4P50vuH>XH zjtWA5RS;ZT@*0w!sSKQ*sK53$metQjk;Z#mD4Y zJ}tPOLT1yCouc6SqI?+o%E~A#%9u7|YH1MuezKy%yn<4T(jJFmls(g1oL!P}9I|Qt z&65C>{MfXvR+2@}cT6wqZ^Bq;{rx=YE6HmM z)n9qHB)kIw>=y8qaGqu>WSNHZ^j9GdYPjBRM9+x$&<3`+Zn!5$YcBfQ#~q9ly{><> zOrt-|3aWl(O^4{aY4`z+k98i#dMIl*L{D=~ac*wUgiD^#Gx5v2w9rexDY)DxGlAgi z`2I#4F8$eh8!r9RRvYf0K%cZdyZ^iQY!caxf699M2xtN$*N5}jx@+CX27A}82)9DW zS_{1sP&^F#%Rbn&6wT(3UWJUUdRbd)WapQu+PrPjsU>d-%ceLr>~mZ%FJAe%U*5y`+?L znguYG*Th`o6w3F?dC(|44GzDClh@;hRq*hvU5g?+>H!UKeS&@)PlX<^!!0 zwr$+T>U*vC0ZUh1-i1;^U}vY%p}u)U?`2=${On%5lZkFW>Fb+_hu+VA#F<);(@1a| zbqRe9Goj9TXc+0Q)Z?3Ey+TM=iuCeBqWe0G_{7{j!{ZX6mG=?KZE zZ&Z=4{%2%|2;p8ajB$HS_w5H=VbO?ZJJQz`N=}_T@Iy~1VHfZQR~w4=c4Wiil}8=Z z!|}fAJIm2T#!+&70f={s&!4~1L$SD{Ae z?F$huYf`rf^`Ol%!p`XhI!gCS=mVK3ld?0zi|e5~Q^)UZeGK}pm-S7pMEEKG6vle< zJ=p?;+|-<^s5~eQ6khBAlDtReY*cz~>V`8D=z+tc^Hl;%j5XH0pCH3{><4ee-!Zd zoZZHiIq@FcdBW`8uyZx<;zPsBlZM}pz2@oWv*v6c>|Ie<;!*AFGHw@SMqi@pOBYv{ zb9&)9ow@$CWONN|IoJLS-L869_h?#AXv|NpIWlLf(vvGUqi)Z1o;t3V;k-QuSIS>E z$`$RaD#LJm<#rnJfn5AmmXC5{hJe#fIB zdZH5^?}9J#Q`G~)DR1Q&(UQHXMvb1n$M*s1wobE!X*OHDj8V{J@)qZn=3?5Im*vhW zE-oyl?(edTCZuPio*N4jGRpD&dBfvc+{ee#AO@FN48w+`u%C(`#Y43F^I~IK-Vcv! zaSx-KE$$J%bcnlu=}h|cR<>JxGkZWwe#d@3Jnop!5nq7kB{^9|h&i8=V~nCtb*m3@ zTj?8}Y~7SK9n*b%oag(~TvNX}r|@XW9j}@<%)DXWGNY*7rHP3hbM%!bwAO4)yC?D>+8?@WZ=w{w=cQtkC)D! zcBA)i1HOED_1w4K`QUi+A0zjVHZ>g{d_qzLCu(!U3zO$Ie*ElXS5#*%dFz(;ZJhTW z{^;Dd`hW1J@5`?_?a=AVQbv3@v)=<-a{m0_uZKH!3SV>N^z|tZ-<;lk#n^3s{WW3- zj*PW%NB{A}$6q{|QholW?bqJ1ZD?ZR+E4D=_|cbJZXdbhizm)|?Qola#{A{!r(fIN z@x81SuNR#cKK-Uk?=|jyB{%7bH&;b}@qq7({^d=B&z<+m&HdMUuADd`<%j<={DB*v zeXcS2%wIMXbgSHxyWrouqkitt{+}0>r_H)Mb=>|7hdzAHo4@o9xjV=FX|!?k_a8Ql z-rRS>`kd>B-rB9>>Z`gWU{^Z+-c}qNoKgd>fVje$Vee{A}UFXU7!$t8v=1 zw?Edf?C)n8hn|i-PWp?kxNuV9B{luJCoc4MFMBLvY|p3ODG&eiho3xi%hGu(YK*)) zYR{VY!0>7PPx*7<+|(};KRb2s^tNB8U%9^XQy+FO+t8`^WA8jNpt5I=>9>qEx(sQv zf5J)9r)}34XK-l+BzF8dqb9DK=zDGNM_1=Wj`&@tY%`wrBHf?F@e#YYK zGSYW$TRS+hBK(cMkA~)Dz7sZnRo5rC&$#-Xp`~Su#$Gc!^7Zp8zW@8`@HdW*SsXs` z(#?OX>NjK4HTO>(&_9U$Pe-0sF!iyJzK{HC#NVIHFMBEC{EArTmmxVh?_4|9J@mQD zH#A%@>)P#(`kcnU{_EkN4*ucW%kQe)KWowc{)cyTe(JlY2c3O_bbTKA(OW7q)< zDdlnDk48+ryzM{d*3Zg)qf24ac~||^XZ0Chr)B+P#O$+EF5EPE`bXc+em3T-Z^AE| zSiNrM<4F%yFT3xoy=RNg7~ez~yfiffWzUeu}P z*Q-8S^-axl7fx3mphJrc}~a!`@Xv1#eePHP|~Z*-$vwkFM4uS(w5mzK6lOy ztE#RX)Ft%bx%W(+7nktzw6Zz98pb3i&dq!7@1G`YJKN~_=)NDW>HFFXw)m&tkudv# zXS@&pTzOWNlyy4&k#oL(wRZ1|k6k+R@Z#4`hW6v|3#TkI zQ#V}ukIz5p-}d<|-)TShE`MUr^E(H9kbQMj?4T8wT({`vuU8g5^TBB^u0KEXn}gfh z-r0119w+_@A%LirruL?@cxT zn$_#b_icYR`aCqJN44?tH5HNNo&NUmrx#tEk#g-duaDb#+u2!9y#4w)gV!8L51aMo zS*MKH8GhGs^6xkAPv*Qd@0CB^acYMPio@Hz75ZfL<`-7qdHLVYzNJf5&bR-lYCPq( zhsrNb9kJu9kTtJ<((A4M{p5Ok!ZYco9Z0@$@P?Zj+I+nI;XxH0AG+|X%y(~GpWs~b z(QAuGY*@JTm()u-^*l5CK<>XrH?4knMEQmnN9I?IePHk0?=Ii{QQ7N9J3Jq;Z(qOq zxS{WjS^MoRf7>;7$CGE>_Cn7Y?#9gzPI~IAJD2?H-L%XN?FSs)KQX&uMd;;?RRj8W z95W_rW>tBoq? zu7B*WPks0BsORS{|8>I7jcK<&x8=^yH+}KFW7ym6!sq^d?=5FVM?7@Ts}WEBrT_>{k!JXSu@u@cHOJ*q>X+%Z_u3$zg2&7 z)75Qf93B{R)i*!Qh)JB?wD(uv6)*Ptc+%7_FCLftL(DTD=>BKlzj4!&1*Z*|^mD^o z`EPvOt?7<7f4_bE6Se=Gd(}S&j!PMQxO~HtwV$5du>1Mmn@1#1cz*d?v6<;}55>Rq z;g%zJ9~#r6tGDNCn`e&ha_-l6rcdgb{_5b6yt|LrpI}9(#RTR*x%mxv9L5xF{E`c6 zy?36uJo2vPQPqFH+5BephsD?2^Yp1dY+Qe9)t%q9ZMd>~!ub7j7tJ{>t?v2rpW4(W zzT~rtKMsuh?%UCkJMvRU(k$9V#`=Lbo$fYqs)1Q3)^s_IVJn-&sitoAhU_bNa)LO^L$J==0FDP2L zx_Gl$@xtQkSH3+t^#t za`h`$Cj8~LL2us|ee>3@-`OAi?b=&j@Abm%p~LQc>eaJ;a6evJ(DVGv+aI}i*`Iz+ zte=-2J^Tvi_kZ4W#ek_J(ytv}e0{qOLr?$o;-&ot7XJDEWt;B0>*E234)%P$|MIRk ze)-{$F3%j;Sl7<;)LT90mftsfRL>hL|J^YoSQ=iOIi2G?EU+@ zU-!n#18}@drN6}zot+2rC)o4DSHBX!bM1&ld!PR5`75qpw(z-}o?+|Wn6U1r^WVDQ z!n3z~#^s;>_V*0~lg1u;?u*Z}9yGt7>AI=>+^^27KDa7j^v-3QmtMX*Y1h#nW%u5> z_p6IS2wuOo{S`%)@y%{cw)ep-rXb~Qr8-e|KHjrgCXq!Nj$$tT1aL${`Gw0 zC1HB>o4WqsMtftD9(}*7hFDdpI|k>gChv_lN{M?d3yh z`#qe!eDruDUH9ibAutpBU?SR5Bz(^>4jJYR#d7Dv7+b`*mw5;vj?Z&SNy*F$stX+Qm zQPR%$lRy3BgAbK@7J?Ask1A)X; z(IyHX;xXES5M0mzL=1iWkxE9;AL?g*Pu(p`uRwaUmSO}t|7Yz@va)hZa_lv>UOu(x zTjR91t)Ks^V_y9jmwUNVJtBG^iz;{$<0dx{d2a3fh8cBSq1_yA64TeyL;>!AbusdA zCH~tuX?2WW&v+##LHN&SJR;m86#kWr$MC={{7J8t_`7+at+Rp|YZlqANq!2*&gaoyQ_R9xhkaPk>-h5c))>m-8R0-ynvTmJk$}hLA!SG{yYN zXSmJDwsu9}&GP&53p1zYmCnxK{S-XQEXpWS+b#y*U>m7)i2o)wrujzg{>T$+Yp6L4 z_KD<1Z7T7Nwc~`F0&E!}rdUO0-Oz@W{|N{Ul@hh7RAL=wq(qfwCxQJ8Bs@(@Lfw^6V0?ib7FCmJ(Qn^Onvi&Vli& z!s6^a+~oL+j?Rx+b;*Lb87f;%Iv&Fz=v!>z}PKgBhi=}jBHk@-t|6+Sx|FVg5KKl}6jEDb0A z;Y{zd;lmkUX2YfbtG3~}Ouxp4ui^f3oekf~_)ZNcIVJt|8cuRP#$DPz8-75#I<6;@ z57K|j`8C1gINk^weIMr2&4%YPZfZEmnZk0UXgJB~E^z}A;BIEmPxQ}t^_o-Y+ z&RmvL&b3N;RgpZYC<2u^z|A&kya?~hOtk>NzNGNbHIkn zw;RH_KNS8l|BA5TMa)OeM+yA_p0~Jd^bt&-qTvLsVL4MZoaCIyd?wm(ALB(fT;`9n zY`EC0^V#rl<^vnD%8C3jjIYyhl5?v?W^B}Ok~5XZ37OXlA0Oj8ZS+D{Z^PFy{XQFh zfbZoh{M}67jjx20ocmZ#c`oz@^XaeAll&&*rXA<{0X;qCgpZHuCEb3U>E#BX+H;ME*&osCZ&0^AB4QJSp z_9T3&`9Xz^-p%+j8*VawCSOIjoNxW}9KlohLAH%v@?n7umvQ2EItTuLe&pMY^idH~ zS?bQ@n`Ev}@+?9;d<~|99^tkKhI9R(=@@yb4v_0+U4owXhR$d}$L##i2Es=?xf}4~ zCmNpg-H2zbKcwZ6ejvscp~x?=33Bpt^R@!xcO%!!i9BDH2NGWHFNKG~+vSg-1w*)X z%*VQG&Of#mL$M%_9HKhcttYo6v; z5BR4($ik|G6Iwa1ZO=ampK1#r@=N#|;0cs|PqanhVM0njO`RpYq@UQ^`BZ-1#i(5X{q4`8&kPoo_^-nM;v;jCYQU$8^uFsue4SAim5I>X z$4HSz`uvHk15P@~NPDH5oN^H{$bC5t$}mI)zE`?g`1685s9@c|LA(RcgUe( zW`tQAx-?gWL&-uikvyw@ZAy2wS)k%HjyA>7H?dTjpqEZ*>eJ2q1>lHXU$6+1^His{G%X0oq@<=`6D4e<~r#v!^QIVR`O>-eov*Z2gRF& zG$cXZq!iCa%0Eg+MmWAx0Gph>;O_+)RGK&in$`EtW- zw)2`e)%JZa#7%YShY6!Qj*@MlJoe9rv-s2`plW^K9C0iFJ+=t#qvk0#mP zUAedi>DrT=2hq-OHl?=AWqc=jHo3D|dxmlE@*Jnx_;Xfh4V34VjoZDhGuB4I<|)n= zG#=V)+4ik>bz4jAliDn`6|xggY9}QBsVQ+A4cKS!qV4{iHM-_O zq)X2)!t^{IF~{g!-^+piq(`*K>>bjwPJn;yZk%rjMS4PDr`6fZIxB?ySv=yGrZ|e1 z@`BP%eH8JbJm?2I1e6Cj+tc_9`Y~^|l^1k&KYPflk}s9sb1q_$aiiq*f= zbN@o^!rjiY+i+yg7Ins=tE!hyWs8{VW}teR1U@7q)h9RC%RZDAV^#5KxZ-RlY&>+0 zuG8|K+Bwx5%JbdSH=+J)g&dUslZWO;4 zW^|%*b)e0cck*rbp}kP~M#ea&Uxc$O687|5E9?f>#9>!JrcLdP>EUR@8$!%s)L)~X zR?#;^D9_zE5A_WAB46S+b%ZTw^l4ED<3M^oLp#Kph-KS?&x}Z3ksO~P?-!$Aqq947 zZil`XPBQFvogVE)Jr519P7A^J#OL8V=SUOMYAiOvo6hQB4J3V-!yMXzJ_7Wx4Xo26 zj2f3haQz&74V)!gptXsp%dC1(kMdGBIBaq*Mn5R>-46Mv95Mzvr`P;MHiV6FnJ5D) zlMIvrW*zMvmF3In+bPn{*Bl7m&gX(ooH8^(}LfSL!a++ZV62e~U50ay8l?T@wd zT=UXy37wZlZ4~jXhb`vXFpOP$FsFD0^*RjW*JtQ6Fpo+P$M`$O2pjjMt6y}a!;|(*xi#m;GX;iQ2oM)0TFHOq3EAp}n>JIfM zbk1|6(KY{6)VV$pNwdq5CsbC}_|>&@9rCagdAxE2@)L6yD}TGH{Kfg}^!hf<`MdZm zW4z?C19I(x&GooGJC>t-ZbKV>v|-rF<&j3*zun>HFJAEVa9&5E4%Jcpg1oA~(QN+o zf~-`ZNSG74n4Y+4EcupVAd&_A#yojK7!1%;{;(wNh$U>OWegdQ|Js|v72Id7ZeuImvr3y zVcUI1j=~05F@mo*v!Jkens=%jp9ac?;B*WTX5c3mj!=Xaon`+Ok@(|NbQxLRBHB*% zQ%)G2anWVz857bI)32D20kiLlTV`GR)1ObBzYQyDaGN5qNk zRhTQtlKJ@Mu6sg~Km6dzc01osY(GjVC;1t1*k%*v%Uu>9h%^iT10DE*Q~N`S9nJf~ z?{AZ|C~R>k8M+ebTuVX{mpSfsI!9YdQvNRsC%yaL`#Y1C%JWQ1F^U6rG>MO5=%>h1 z6o`-VaSg{!esXkujxi}K!nOsV6T7z;P(V1MJH&LDPbo)O2g-Z6JFJT_30F5`%BC)- zc@)V?cH*rxkMjGHN%qU%dpEB|s+NQ-by3O^?{;4Ne&W0DjU(W0@Qnk1^pVQ>NS@J_ zKHMnMhf7}KoZPGrN8ep$Q(~6 zIfh4ZmAvss3eQIT6TQ%#$q(OTyom3m&-*B=QDq?r|E;-s$QU#UulQfBkdHUb*j7eimlf|#U5K(YSCc&WFz z6v>K#2{Qi{?V_dJ0(!z}FX*&3joxDD@6DhomQoBX%2p=!T0bbwo0^e1V=^US#?Uyw z5+VEq;fWv8v<9;aGrTz^5os~E->T7*Jd(fLG#=oBV@38R~e18!BZk`f}oJEL-Tpz|oPQeEUb$q8rPx+61D&_WQ^g4c!aeICi@%U|zx0G>vycHTf@sHtnD>Zr@U%|LN-W`mS zUBoC$boIMm!+UGEo5y>i@2laHI8%uK01dxU!=p9)4Gq`n_i4CJpUevYcK#DJT&JJP zxYVCnkc(Uq<5GVFFV*;*W09)g${>7TvrIWVpJhS##I(2Q?ef<#ZkKZl<97aAH9qH9 zEY&aetd+C#FXj0VmDkxCy)OtZ^J398k{~jU2rm7kTm_eYDVqZdUdi{fY`Dy$W&SAi zGLM#eEw~JZk8yblF7xO*8!q!`nTHC!%$N7s=w)6kI`cv=^Iy@W5?toLeRy0DT;{(r zjtDOE*5_>WGH?CObhQ4D%!0a6o|J{$t#RoZhRMD=xSq*_2=VYWm@d}7ZWh5TW=z$a z;^FScKWFL3I1hJLApE{zi&q|Sam%eb$45Mah3DbPPj9~;f+xf?)=y!1wsHJ-+9DMB z1vWuWey$EyVElS$fevn&b@Bg7cmY!2q3|&R@bwUfciV7@SFYpnT>Ls|H#*=Pz}aah zgN87>{1Sev?SWl>FTzrun)uh9C(^p}afDRlZQ22T`acQ2XS$D1TT3+eMBshI3`MA1JvBTY#J8@kok0!LK z1Tm49$cf{ehZULaS7LYaYjL)WWTw#Rv9nkAf!5;afvd$^2?uSFiCH)>S8~I&Qg0@% zrN!1YSA4M2U23Rr7#V{yOG=DE!TL#N{oh=y^Ps`|Mmukv{1Rr*AyYkV{bLVL z<2}{)|1|tSge9K#zQqJa&aHl%eF$(9y`GI5>6h|eV|(7VS+V$rKu|Y zpJ>~bIl6r;vd15+ZFghB(Hy^A?BV^@66WJiq-_rw63?ys#M^d-HhDIcAeNqE)|p1< z%^^nI0_Z7R3|)he(<;&~o^jTMFziW|8OC(z3Dxd(g+yE8M4%CudP)x|$!-`Dw_ZwP_@9&G#m(BAs~ z4Zh`FK7=6QO&Gh>~ zCwYEk&I>iWBt1$u%(0ei62H>abhi(-b0=UAy!>G^p#l5sqgH zXV$KUjzX_`vo^_Xj?d_3OuvZs#+ANa7xj&wBXc%Wb5(oamOja5rBgjxz!S#nc7BAuKh)bF}>(3wS?uNak`L$XIDw1F-a>^HX`4ZXRtuEz8) zVJCU7@8%v`!l4_`)_5iyWzo(ws+!uT+0u zPs|aW40#@eJjtqEI`UJHuVYBR!w4C-*VPBMxE=WqK%P;MXMq8IALtCthdiPWOS*~~ z(C4N2sNN+i9STdAWFO+8{Ghye@#m)X_57_VszXxGo9oBp&9Thw@ z_@Ec#c>6N_@|z3VU*ukKjCiyRc_s%@>h>sQDIpzsaW(-6=H(T&}9gZOz6n zple*w*R0uhc88jUJ(ED!v1b2#2k2n`x=q^}6XllDHxbVxY8vJ{tHvmrPTL#NnC?++cuK9HI8!cF8uGW-p$Q`XWw`YKuiUi>K9 zn5U!JXm&8xdl6SDl?`-h>QMhOk(Uo3Og3~YNiWa?yW%h5p8Sa@$F9&(TnSy9QJ~$W z^t0%b$iB4Fen#y*;Jbk0d&yNr@m13pf%>)xc!MiqEyaBY{11YLp4UMyX$$)kVT0WX z-b6DWG-YmcdeqlV=~5n2o>DG&1*&`t|Hdk)SUpq!-4sJtkxDM%~j-^I8tcKOn3aBXmPfF7ci z7Z|^A-%;h=9~G_WNI9w~PxOAY{DtOzbSP-4&Bx)o3vH_x+K_>|ZXCGjoz<`>-y7}L z=|&sC7(V*2=bg#ui}tueqrd23#4mJJY|lcUH-&W;iFQ|Rzm3k2itR*4dXQ7lXEm`N zWFGpgeXfeMk&f{EFHuLv7;VN)L7UizKD7z+jaQ5|?KeXQlXzw^&z#&|8|Q;xFYq1> zo_#wS@zk%4=I4ZO%I&?;6Kp5KiAbqwPC4E3<4vymQ%c76cbFQKz+r>!QwVHMj= z@b!W3Xz<+xz61V%{tPn6c?lZhl0iEUv@X!j2W<#wS0dec(4RIy>tcC{whU=Gcq@7 zBh?M+uQ8`<+znk;8jnLzUQ|YpAf6vv7*DTs4QNJUztqfP!rxX-~DI|gy?b@j!#)+YZUjO7nh&Rwk6!m*f;>+lTrR@hf^wj;BboN?X-dBi;iYWyaF4PWmy7WBvN;pso5$rR~(`REHVyKAgcI?3rt^ z)ekHL^$cTgS|;#N%;o4R*r~v&t;}~+Y_CV%lJ-)8dQIgq*~q&R<4 za~#SOoCCml7$0QN^P}#l=bb&!X~&tA=w~vGXv&XGTn0zxY^d2!;nA+4^e((B0rAIc}>lc=0l#|=v#ULFQfh%W3r5; zkQKVF&iq}YjH-rFj;e}2V=>M-YZ4>Mmsj+;2>uX^r@pj`K4WSq9hJ!`z#KJqUNEla zz*tw!Z38c<`DSET&B8M;t@-!hHZ=>nUW_p>6k}X?%~eQe{h_8f(!V`2=UIP!rMV^5 z(;ty{l;0154(}q-Cgyg~Cy%DNW?eVTIWg~Ro+DcGL88OrmZGD1rU&m+y^#0w=>23L zzKv=a=OlGQUSX`mJLYuvK8)Sr=4_gaHgv&!1#w=VWK``!x+9V9?9(uBy4zK=8Rve= zR^yvCXB&;au15N;(0RrjR?!#;mxuO~$@gxY37Nf$Vmd(dJ%rAP(Amx1=NYvPkwzoEFYUq{{MVyRccU+e_Mz<(O$Pb_x+lLA{U(h? zBsYEMNY!U`*5DOYpMOA_=sQspQWD+Sc~f$r^<9!TI|mx=@Z^-XLpbH=dEzMdH1CwW zEKAee!V^hd%1uxG%2e)LZ;1+@nUhoCh5{EU*bAd(dKH8JA#q5){4)Pi;fDzid~%pz}6xQ}R`-#Lo+4nBGaU+laidc--ejrBU8 z?LRMW%c-l^Mb5kP;pms2-lM*=GJKuqk@1f$9e&9Nv2&k#YWHcfo`a+vgmvne_ zQ`S!nAD(^Lr zlojc+3k!0Hg&wd4!Q?y`v&%JBUz*;1>##rG@!pP)Z=HNkL&>}qO|egG_@(E+Rt}!n z_1*iXthsc@oV;_Uosx9xmXMOd-7~ii?Rnjro9`RB>aO>y9{-|qr-478b9iyokY1a! zFWLG)#uY2aKQ*B+f8(Ow&;Q%}Q}>y}m+o%5bIq;``!BsKVc~?nXI=Zk+Ko34JbaJi zoYezgF8}!44IP8Zr|R$Vw}2uzpY(GDgvtKfI(|+V?H7>4+(9|QOv`Jm;Hw)~$$QM* z)R_dboeEv?t4RO6qmkG?2JkF;2B-KZc68qta=&ZTBIjbq6@D%CW_@+gQCyEv065a2 zCD#Z4b>xAoci|_o<2vVk{qFCZw5ZSG-q-mVQP_P%1Sfh{l$OH^F^n6DpZ-m3=(I0& zI1@>i{XI)}-f)9N&J`$~g~X1Pj{7>_-zg7NlqftOj{j7aP3eUtc1*pm-TiHo7KJZv zle8pkX{hsRji=MpZb(L~Jt?Q>Z?z30xz{tcjHnYkdYVsQED4`PJXvPNEXWVBIQcz3 z%H-D0<*yOV&nP{Cc89tECH;AE>%@a=pgqA@^&D>_HW!b3;^Sdfs;&W}0fX>V&O}u& zfE6>oj`z()Zx1ly#cH6p$P=f#OG+DgXV{6O%>88;bs^YvL=iBCP>W3K9V zE+gFU7mp>+f3H{n8W@sZx8%FjwLOg2afH&INw38!OMbwY&cKOJjMD;y-{2th^nGxm zuV;E`!zDrJZwZ1|2f?3W{-Vbt?fgx~jSiNas;$GjKL{Tun&K4gj7dn4K{5>}O?~E5QuKEH5eJ==q|0k<6Fk)EdV*Q%aG=``H zfEhS;S28HCq}V$shBWDqId}#gd3aKF?3 z#F}H0Nd?VYkbNceWp;}liPK8KzNLuTaYHh6j1t9J z>AY(cc?CEesR~f(*tgc=&&oR1nTVDu{S-N3B=)7=l6>gA7fjBZB6aAP=MYpXG_859 z4z19dWHpWR06Z=7in;(eYAmQ9a zs3$v_p7b+y`j0hSr>Fje9L3ws@>;)WkK`m?>kebDhU(icfITwhgumbeZS-rHKE_5bc$|%X8`BTB z(F<-|m9ytVGUN7q*r(A`7S$SL@ljFUWi{pn-lbBOu$xA74?M&r}Zicz$Uvx$>W1+z3iZReNfLueE&AZ0J+RYG=J0m;D>!_; zEr4BqFTw{Z|E*_Rk*0EZDu3EYknqyS(PMku6f&0y!ihN?4VNU6Jv{NW*BwAc5qE4~ z*qGar6Vz60w*kcE_~#?Cif<^wk?Z`KGiH(s^>NQf;PCy>lRY2NzpEt+{hG>a=}_Bk zCDwyr zeNJaWwGU~4T|>-^)9ayovh@3qD&Jg3E!j__{oHvDD<2kLZ#0(Ag)PX~(5iXPqy(3{ zIxWiR8e2Zss9oy(L(Tk)9krR*5A+p>R{4sdOS$&8wEF96ib-zY2uE%Gw!fy8_AnYf zBaB)-U6Ljp)6)vsEAg*%k3UBlpjougn`;aHOZl`Cw050`gD&UVdXy>Ie9eR%(55C=O%wDD=C!XJioO2YT}T`0XS|5LblO*q z$G-NDDBsm15^Ecf4-LqN4ASw1E`ksH=Jj};&qO(uL-#xbIzA2K43yEz<@MNO^(;jB zR2b7eWQ!MNY|?dsW#6(Kx(?-`#`-LTt%lvZd125|L-;6!CD}cs?~8JeLVa7+(V1Xy z*$x1YhRdlQAf4EYEe{hrdX|m>bdTeS_bTWg5pSJu19TKJ4ja>7!``|Bb-CekqZR-D z&|QW;$XePzCpn-y8b|SDo>l}ckFYiSB4%N<$#U!&|*17;`9Bau+`9gN`=&I{= z(-{WYuP2?GdepsDb0Y8tm6%tEJ zbEXxQx=Rb)iUiBjIi>EIh=iogn(8enaTjJ@hYzYLaVr?z0FC~f>ya_NB$rxk68`Je5H)7rAkxjZx{O4RJijV4QJWAAoe z`u=GDma%0i&N87!R@El8dmkp|WIuUoyZ2L??~+?Q8~1+l-OeOHH0PuFEp>9_w$S8D z-&4MHNmy>XcSnhVw=3Jdo7g_lf8Q~c_MMl6(H8W$cM-Hd{y)Y)xi$2YNX{z;373N=S zmxhJD+n_yTsuSdTSr_9{TnR7Ydwz8?u3@}_aeY4|&>pju5C8oha~|TOJxg(_z2N31 z{6`3=U2hA5-xCCXJP2MF1m771{}Q;`Tc!34r`i{JAbKDuz2kmUa|DM zSY;nei^}SvTkNG~O~XFn6t#JYPj4DL?x`M?5DL%oqnQ*>-4#d(;BC= zae|)HaDCb04Gq`Z{vHjNF^!-Y@Fhq5yIWrMTcqLoUZU)IQhIec4=_EYOUDm0F8R}+ z z#<)G+sTwY09I=|E;d*`3ZI8J*PP#nE^!9vP!?-=))@k&VKWmtm*f10M1>d5{qqig3 z3#D}RVjgsn?_JsDSx=F{+2z^Fxa6nIqu$Wy$t(Ca#_jnjQw)2&Av~3^$J>E%iFc=x z4lmCdJw+vWAI9zRO5K*Vd1gb0Je3n%#`Ss|F5_SaZtp@by+vT6g;XSqhcD7!Gr!MFJ zvG+D$QdL*l=&q{nrlAS82#Cl?HK0PrXp7BX;)LoSu@zzv+QcMIx~hK=!e7&XA>bE^ zwqr2yW||QMjY@-L0^Hm?&KTH_IALQoys7@$aMX9#@^T>y+_x4x!;| zTT5r+1W(>2Yuw)r@E>>$mGSQr{#!kgd<^=(V)8UqYGg(CSsh4|^4o*EYVuWQE#se~ zlO%+nAQSkfJvhqvA%|N&9(F7!3+tT$+i#G4t*6`z@*R~MXYD0j4LNfW^m}|7XX9~) zO_e>A8>V2df-+OC4{RQ4Hm-*}`_MZ)JMCm#5$LPP%t-8y(?%E0VIjXeF&4Ay0o~Eu zdO(D>fFM(XZiPL`vC)m~BI|4UPQu!zquVI3^~3whwUVDj_&B!~mGklBZ~YT^$C*6R zW7xrU1-|pV7WsE_Q@7rr?hfD^?Ql@$N?uh){}OPOd-`i6Op6}K5Sa!%JIQqr^q-wu zK;u!IjnuTD9ToDFhRjc&*IWB4?pzno_-uk7$m*=S+}))m)-$qeB)$w^&j#7}hPasp z(HkcLPTXaUTfoRgQ_E%XRVx-Qy%o~0g)K{0((px7OWbaHbp?n1oD1uFNowiB`8-r) zop>fH!sZ;O)3sF!rg{12ESmAIb#xjljmVVhAYP#?rfO5+Jw?}3SO2ZgK2!BP#Vmkx zCJ3qq0WPV=pZ6iF#h)MH2aU=!kWS;r>kva1?;sNP~vCcL2HDafYena=ZFWcPoC ztj496446E|*vIy7d7OiMvKmLHe+PPzrIN!ne@H2x%*1{F_%f5rK;M^{*zy3Z7C$XJ zc+6fm<0&8B5`y0bob(gSI9#?I;C?rL`RF_tg6|5!pA5lY3c*i?;6uP)K7PtWaFv1R z_FzoLm$l{*hE!Ho@E*@g2MC_Sxl{m7O^1j3 z?sX2qaL-l8xbKu_;!f`B04=A%xsJ*_bgnZ^{CCS;`BD5y!GqyG>*0R5M?&xk;Ez{u zPUg!_d^$Qdq~Sr1&GcFzbXd=Q+?TcZbJNx0p8WeVo(>Q9Wjvi8K2ih4z01RW8P6^c z_hmefc(`k09WmWEPkwwnZ0@M#LFaBLSSxQTeX7P67O~%5Uml-PPfN{woxa`!4Yx z58xWE-oxgCdY&QR-G=33VRJ$Czt4A!=OF(nU`G*K`e=3&v&0!*U+j>(Ek-vuEeY_cb#r7IO)nMGIu<4otdk> z;bFq^lfeGB5<3^v{ScvZnLE#5E;F_O^FD7b13$SrjLvC3{#@n{nNv(dd^N8hVch>e zFxGedO|YccjKi2aHx_q@%Gd|=={NOT%t%A3fZX$~`^NFjA9LIE0yZ7LQv8C~^#JnW zH-+HKL-0F8@V^bg|1kuAAp{SOiFu4~QS*Fv>JzJk7^Mo79aOp{vOmQD)`rAEc{Z#+ z&Hxs1kK@OSZ5G>0y(Y*5$5uXGAvnh@Y#;Svo#91XL}K>6*8V$OM70)~8aDY5t-9b<9-Z6UDQJ9}nOfzTQ8L z@A~XJEzJk!ar=3}WN45jq5kJ&5%-|!r!d>Sd}9_}wATKHLjbnE>R)lP84MdxPIrUE zgOWJ@g8swCEE6O{j*ysl1(St!E|_<8K2pXBU-JC&G3cK%KiG0@T9Rt&yGK1lem!;a z)U%dfkMt&83CoYluibuAC!cn<&Lhw{mBK#LvBRMIEK)ob`_-45?!@%t*vH*qR{yqR zRASAc0oy<^THXbHl`2oAj%Mx;jbmT&Sjd>mD&3xLtko{3pC0I6eb>)XJA!bla6h&7@!d_ywAJlo_re;dJF^G6XU8QI(`&GQcwBR0dJOu>$03Y$u=l+S zdxytWU@v(*J-21`1w$W)zVGJJ+BH4cH+wPm(mr0CSdKVhZ!qQ2X0M53Z!+|1_k4cz zq%qh>YaqkU+>;)4YV83V2P9D^esPwd>|w0kM4>nD2PRt50Nt`Xpby)iY*J_H zg>{WqKldMt9`$RFsT*tcYk$Ai?4!=`?XWSv193A|>uaK78iT#EQs zp`La@*K*nF^M_UqGyBuO@7-IEIKy7~8)?LEJM=8iKpnXY&s-PMH67kLuh9MA4ATJX zy2R{147${T#&CF6fpwL?KI=6oAIN8`$9o9M2I^IL@_eqzpv+(mXBEoFqZgXV&7hkG zk5HH}W&Hx`!$m#6z*M#a8;AOe@DD;aZFxI*zgp;QCmmbdm%EUUR_`lxqf_teu~FC(g?v;!mZVQTmPwo` zNQ^Xlx!%;fqJB{d`okIC9j5&tB-$s(qRdd&uG8NavpPbZu0==pb%fKH)wMVlwhjuR zYqy}J20B^G5MG(+S&V{KhiRW%09}aVp_eokX+KyC+7Yy2WrK_7prW3 zst!`}S_MDk>wM~19qsnS$A_ExO-o15<2o4isk?dsop(4(L_dt1;wzaCOB0-a%zZp+ zz7~PsG}hG)LFaEzH2R(1X!MP;^p^YE!B<~>p-#V~O-tCTXIfHUD0LR*)1k|9;-@pi zNI}2k`_Om#Jaob0%#P*rg~s#C`7IJ{xB84>D>kdocmwDcqFx?Bc+|_v@WS-1YIvGf zY`0hjzsS5roP+HT%V`?=Y3as($C_spb*%yYR8I^g3i*UILi>WY4(qLSGZyVW*9sfa z&b{~l|d|Ae%CojN6lp)4m(?!bEP9R)Kd!W#12Z=(+?#GPfo z7I&qe#91WPk58kHDLv9B%?m(tJ?in-p~sNCd z{gA(x@eJCo{Y*x({m}ZRzU#dV>wv7=YIvtkK@T|UJl}r-Ix~^}ucEv%zjwbuJ;(*K zaIORTMB}!MW7KB#Ab$aF$K@#t)Ezq>-&h72-}lj0+=TZYgv&4sHuP3s%H@f?shq3<7Gf%zH6L|&BJ&B&krlcE7FwRy_yIu?yve?YQ4>N|_y&0S`XTF-9(p z^PEFj<;r3=@`Q1y`5d%a=22)__r|qsqxD+|XWRAD{Dr-bS^#vOc$JIb_-c{V| zI-nCWh!Q8!CUjbNPA8G2C(Ca(xIVO;V#w24)+)7BFqc>}*A%S2D01Q8F=jk4ofEC( zchP%TO}&RVX3tbu8GVA^d2uo_b4clf(T5@pvM*qk+-DClJgQ-3Qmu50i|e_(YVkvV zWv`K(eEH`$YBoDXgzgN-=RrXKT0va?L-2|a z{JIeQ%OUvJLhy75zAXg*NeKRO2+lJB`QkeeAJ}Ubd2_akNj$DIA6* z$r**W{R*~vP+cIEE@s_+RR5*)^14|;t$g0OohzsLS{1LHI?4Ms=}P~E&!md!{$$)}DTh@=Hq`r40l2(I)M-{8^F zu?gu+kba2t{rvi+;MC(ekq+fLB6u(zjtL%2hqpZUOsaiC=Y;3p#|yX+gNyw5>7Zpy z_i;H_Zoa{1#nbXZ$Dvsq^muJ>x2$^|KRzA6b^MqVe@aLDf5@TirMUM04+L=S{~rn9 z+W(*Z8tR|7-my~2KS|DhW16rv)wB$x=g0u+Z10=svVF_0MrQX->*g zbPwwPXaJXLXZ`R~0zdkfW))BFnkE|t9#TN=>R;hHJkWoI0&;&|{Ko^h#$WF@;=4Zk zPT%u4EO;M+Zs&{tApa-Ce0fBBp@?dau2>Ezyu z@y+eCpr4?B(iA6jmc5=j*F9=~ryl~*3EhXbOB$W;zdYhPK&*>ezD&$NO zHjukrYiGU>t<|dw3CoAuhxYB#^ufrSJLVoRU2R8W1Im#O!^)sDCk>rBleSZw=5lvXjXk6gdz#31TGbPIP zi*wTlcYt0LYihKkOnNcUTL)XpuY=B56a7d#gl0j?uBnYNxBZrK$V@CfigL?8CT-Fs zP0Cp3GWAsFcdTu-SfNYTl%&IUb7Cqg&vM$@?S?#;e8;b@d!{U6rpF7-^oaw_ z#urm%X^?5s6I7ds+K+M@z|2anpPFcUKPq-1pI2g+cp7o z@51_am5E53P-bnDmKoR&g#FEbK^mkZxw^{mpwBL=TMYH~cM0$s$2wXBYicu|gl;s} zE3752Hxs5*fwyWr5Af2m&zd!8ag7CQH?qbODUV|PujjDYm_VBKLbn~7(oJ2o88(J{ z28P2vBi33FuiU!IlWvd5X{7X}woOJq?8)efX&#iwOJV)F~w za>a#_1m1bwgCE_O%ADEe6|f)T$9(N~`GXBBJGA2tCp3e3GpqFm8gN=#8>~3TeWlzC zBBeH{Ut6~1atIk$tc2jN)mdh7P9Qs4xoSnjt;?1*8;3ZpHX==OP&0-&P;9fbr7g9x zMMYW~grIa|&4#RKS&SvMhUS*r7Q#}Bqm$JO!?~uPCzX<~e-XfSE*Hc#eS>sfk#rBb zzgq$e;t5YyA;U$R<|M($sRG z4mJF^0&>^z_5Nw#`s_P>>J0f0+kdP6_xVKetm&ul^>|>M5(>zDD-#^oYIn2qG|F() z|46~fJG-smg*`U*Qke*+E9{(t{uxX#?dh>X9Cq`?yMk%OI-1XasmzbQTl_`~2gw$$v`@x1OM<+wie z8MlWAo^=o8Mm%rIV9cmvERMr^FutMt4D{rZZac?ed8OW1@{8X_)79T?8FU&m4y1hq zZg2R)+#9ZqH{!5yJk{Kc?q)^&hMQ*3&dzk*ce|(o&7e-%DL=XnhdU`68pWK{3c!L> zMJV6A_t4()bf=;m9qotxu^sydtrK(Ttj>+eX33ar0-$Ncadq>r%6+GDOpf!o0f2XY z3cFZ#|CD1ehMR9a--+$|H%QFf{x!;ipd$@{d$s?LPJf(hCjL77aPh-5^Vi`uai$2) z@4UvkoBhwXuI|G9`0MJm2*E$oW%C&r+ZZhqmI?Wrk2~F~yKepHjoIw@tiMiy%4t(8 za|@@H)24Y#td-NIT$R7f_gOi0wIWygbA1%YNPccs3SY#f*|mt4SIYZ+_g9O1;=cQY z;FRkRm1o}e$#anYV}b|iJn6aj!_~b)L4IBo_rY+FcyxR|kA;N$mgk<~#^wEl+%;Uq z3lL9U!EnRIikfaZR@8EF_G7$1^YsBq7neHy>qgj^?-33}a6uknFV=THYTk`>u(?F= zV85^Hx#BE)3$PQuJ`i*$6oRmh`6gvUa1R{H*F9H*ZZFFto{|Q z!vmdGC?I!iShrVP-t{K1^+W7N{1j6+y#F>In8z*KH98IQe?t5x@y)-2{HO4dS)K45 z;d!KV4H_@zKgWmaU-Lg-*d%qcFq9EK1_R^xFz7#Q%sEZU-*OW3E+LmiNHbXW__0p- zZ_T=N4?+J|OqqOEW6sK}&i>5TR&PT@R_D9NlFka+&jdx)`f@frS-fJgx z_s4NQ;Qgl9ZtMZrV_-)E_@bvEGk<(U;#=$VJ;*`Ik}7(DavJkC7yz}^YNW%?v>{$WHC@3HoSJXgXq4=$a| zBGmnQrqdCGr)M6b*>oCf(+THfN)nxEn@&7iGFH-ww7;+*zAuUMG3_`DgUWT|IM6=~ z`tIC{%LjXIMb5+M8IJLGPyaZ(r@sk%`Wq!5NMGg3@7X+n-4^Bn!a{kLGhHt26UTY( zf$`!uH>PKvq~FQm*?jtK@8o`ZPr^P$#>OA#0bpAM^`ZO__WtwC&8M)|Lc2IUv60pW1F9fokhWxW4%kyJ^D3dK=}fsa&e7q_ z70!Uzboys2pFV{AP#zdQ_xICw56dHY|2<^d3^zkrH~d@qc7O)_b>bIl*QQMDnb7aA zL7z5l`231IbA9F7Yi^i(Lv38Q>Kl32qX3@02Nfg6os&<)j75CHDi~#0cq?pDOyool zSI#~}*8RL|;+Qu&_W{?2TPxwPZE15(Oqr!gdLqsYx)D7Br=Jg&k_aw;E||o-_EngN z_m#C|1Mz%y3zxV>SwToK3+{X4T(XA0~ZjUY>^rCOpq58!aYWNLzkh}%I+wtSo z$quG!$Rm*lM?5sVcJt7C&)rhG^_-cT&bwz=+q2Igj2B*f?s;nWdn9ttuubQw1G@ek zH2J~CgE%OerCR?i-F$xx>VL%?^gPRqKO1n|jj%Uz)%W63y}xJO=7TuNH#c?kr33d! zag68BO?CfNLhv~5y!`!c`R1UG{>Pt#-hi;Q%-MkDFByX07J_dM!T&x4|ECcAjS##y z1b1_#h|&D8WfyLzBMbAz>-rGo0p`lE%>vyf8M-er8Y9$>&)H2G^TC|_ctu>ZDu}`y~X{uMmIHihS)A7O(36;Xga3*;Fu<|oI)dOa-Vf z8uwl+WBH)0qE2v~i#yk_k03bdsQifEnmydL70$BW0 z{=d;DwA`Ft`ACR=iDuSyg$x-!n?>A%$^;ay!vkqmC?NNx;y)h1HC(;li0}IBJN;h& zA&dPSbQ>m9=@kDj`b6;@8k)< zuc3P`Cx{%Q)kP!wAM`K1rPZcGMLJpCf0g<7Tuz#D)fBhs^33;Ku5QW(FX`-LDqO=m zggIgcbIbz;W-nzJY22gGQ&Ww-cv0x4iN(`%YoVKF8+6mume#CU51lnp=zeH`ZVu=g zs^?t(5Z3IX*w^$^(>}BYbNzLzFKWwR9y$(k5bk?R<9RG}*E9@H{B}Lp?=WvQm~TfT zT~p(Op=%;xHg;o8acn{L#0=(QGa!G-jC1=b`A%5~=ctFlZw7N>()pQbpL+!Qe8@)% ze7^=eu^nbW`6b|kXaBnqPFXTB{Rs5FR42@h2)8nYu(;M(W}@HaJX>{&kQZGe#90~Z zK81Ll&Mo$QW_go6U*!fej4^}F@(qYH>5esSUDS^U-KzUB6T;onCMxa6hSB2pDx9&` zFz-T`8R+W4UQxRidnV!2KY7>yhH8Ap1PSLQouR70-Cd?SrB z<>v^>Vgd4RTdi4s9c<=qn{Ad4I&Z_=yM}I z{S*h^v~rHZ^4DU6%a!Pe16ZC!M%7a{e&3Fmd9(mDda#$a1Mw<=-)&~lqSwJw0o-;Cc+*qU$>SGDDOa;LvB>BeCl&?DEg^Sam zMTZf;2xMiokpk!n8ecvGx`8@Oq-1^PcSiZVe;d62E94$A*l^f`JM|0oB95_>y;=XS zS^opF{%I?r0JJZS3;^v*A&V_8s^>_Hjyk{BEdSZ|sV~`FLSyqq^Ww@u2 zzj2h;$gmBNH(?E5%I+AX%L0}qNvHJKcIR$fdtY}_mzZy-*6z>Bh@EUWvgbWpHbz(( z8s) zDo^a+_cvx^&pq@vcw+A|gLV!30tTDOrUZHau(NTS;QM)a{|EO@+Fd1P^5HvXPdoxT zhn6MwN6yEd)#B0fMqb6Xcj!Dbc;r0Dm&>aX5y)X9EqKIi#!|)n%t}E%jQmwV|%J;7yfMrbnBQnbf3T$bOYp`DfB(l&)YU? zB!1`@pdT%<25naTcG%Z#y1j57Wra-h^!vS)OjpVh8P+{0f7At~?|+SV>f+-2-SX`_ zxNBR?I~GTv$IV}7Fnf-p{<18+7mGpOSpfQ6TZojuk3KVkxVDR}k=0){6L0%M1Z5{Z zcjZuL13D+$bbD{LENhsj*8X@m>iXMbM}B^d%6)s+74Gg`SA^dH{EBzijdn6$guln? zt!gm)kAshGn_$P9ZQNG0y|gcG%eg6k_#(3x{o#J36Ur0z8e_|57ut2ETlZg>`rew_ zMeA{AJhpw$EI)zulkSnA^Ec>6N0|DbM!EhGTaHOpJ=QpuC!tqr9nzgL(m34pm%0AJ z)(6siA3Q)tTiy#h*6R?j9f;RcSYt_opPs8C8((d5^@H-;ZrH`9-Rvh|7k&FsQ`uWn zy(l%5eAVpkS&RM)`FrTQ);-53(=~ocxMv%(8?tb=A=`29LAZs(H_SbPd}&8Ja);S4 zH-bKY2HMEogPpq+?1!)a9ma7eM!`%F4Uu>tw%AdU#%JSXdCJb z+s~vivzk$lj#?c;MOgQ-I)p|gQIB-ZCsH?V-?n?XJ=V5i^%>M91N~Sj&_*9wnW8>3 z)XN1ZyG@{tG+h+KGxwA?f%Xy9QLZV;p7K#FBPp+*#_PuJBQ4f>whi0SHaVJwi|&$s ztFQZu_rY@c@&o9j*aot_VtJ+hAH;i;m7!y-L)^y_z%WL&>m)voG5RpJ$rHdc%L2e`q+c`FzfIj+;_j>EMBmH56yiXf>ap$*2 z{U4yQG*5Cle^Jw_55E>*B{e3eH0kV z@`165Z^Voldg7DVt6xy{%wd%29+dCQRnh6BUkBO=<`3u}!*g7oX>XljlaIf}v$h?) zpIZBmyN@An*>-SU2<-ye2yL&-o_EQoZLf;TcWuJBv=DtN^6yow-5f#teAuq53`hQt zaC(`t>nK0Nu*eMSM!u~d%(7}0EkIk7#5$=bu;rVsAS!aru zr%`8aElAwhi}BzwxHX6i`DOdSHBsuXT0hpMkwJMobg9z;R)+aP0^^T$=*zmGcQYgL z&b6aIvu({f=*3JT+}$XDanyD46i3(t;Ro+SZ#AZ*7xlat?+Ju`2M%&$Fl}ym$VJeew5)^dF#fQi1wi3;PszzPr^TSk8#}V z_j#w*I)3B$&aqM#?vLX>!+i6%ud&>YH0S;!-Zf88t^J7|zfh;&`{N=uPub>EXCT+U zde8?wjJ90Yz28G#A3|U7D$dIti4|d-U^ap8$*-dAIRf`b7qMJpe1WxR>eJJDlI0OP z%TBFzdcnv;?;Yk}kAc?fcFbA?y2a(Te65Y_K2>8jZorw7BJ_7SYqtMr34Rz$KZ7;F zQ){bs!|z6&rv>BV%BDLHBjd92_t5XyJ_B(&fjFF8RIvLb!u=iM@xhA1-5-Dt$j&++ zz}jpkHrlpX+SeyzY`0v$|61(A@}sd);PnEe!AO*8lrNNLthXb+&JD)}`kcEf&A?b> zQSI&zR$PO&!ljGzduDF^@#k@rbw935|Bs6AhluY7;FIGgjvITYqMbl~CaJe{D&`}x z(V_9AJI7~OT->;eZs6ATd#@th4CdXsPP_iH^>fk2>mFUSxgSl7dECGKiIgJ@TTTxn zK3Yy$MvowGUq#-&cbN9!oSgvHeU#5Ve)%j!`RYJ9vvES3=k`OmdZhK^|1VEbTc7{z z%2Ri)JoQXJ`|{-4pCZhc3sKhDuJvty7NA@dNc(dH?avXk9q32PIe+_m>)VEsUZu^_i zcE`pgq}}m!d>**w49bZ|OXI5T&mnL8!?uTgrPV`;c80o3nSTYiv)@EHnaeRS+ZOhd zN4$QK{o2n^zWi~g?I*2{XKjBxJ<|v)BW*m(Q)qc{dZ%p}`a{abskJ|~W1g_`px<43 z7wUF6G#J|7Y)lx-MhrFbNvSPOJ#C8TDN~bJpa_c<{8G2H;(y) zS&p^Pde-&VP{;q)n4$g{V<+<92*wwOq<%9GHBYEl)UV?ij1T=W2m7PkSh#QgxVEx? zeGkhw$O5usj6Y@_*D+yOesV5w5@Qf`r)lT%*NqQt|JQeX@e%b~>U9&w6woirvTs-> zuSlE>jG0bbr~NTet~`t?H_2#r98vYv@bZw0n;TpCdB^w#->XNPwkF8ujv}rDaCZ96 z(a<+Nx^&*p&9F%wX5^$F6kjy&804}Y=FU+&O+opc*vDCjwS^6s8@~=2?TiS{*JJ+s znkUaavfz?^(PC4{cB2|&ea^|#kO@8^&zW-}JB57t63kzIJq)q}%qzyDf2l4^AMA+# z{Qhkw`kNleTP}&F4@MJ^HJhT}#IX+Yv*N^5=*b>>F=PXeL+&ts^+kAYpWBhXX3cuY zCzpaPdB* z^{^*u*3Uii;rUaw%)bHo?AJhlU1ZRrftZgxWd_cA9kN))^*6Bz77VdTR&gLNq6LoH~IPuH$lkGL}3xyO$(3G&(vOw%HXIUduNI-CnKRnwoS zNzeT`(tI28topKo^6Jt%M|~ULb|C)W!X0}|ZzTOwRW<1aT=V?HKhf)W>F&?kfo_)XLt9tn3Z4 zpZnJ%T;#8g>O2@uOeL2mCh9u4lqO+J(2r4>m)oCjvU~>o2~&VBV9^{0NdV*fQ)q`+e_1ytpuCi&&5aCW2IMZgP^ON8pN`hQm`C|Q66yDI=wJW&oPu(- zJMdGak6SZ}*!1C=(XH5Lt@)z*(OCz#**aKILjC9l>7#PbBIv6(h~G7`ZZm`HS>RE5 z|6BC=mUoo%UEpyB{xbgD?d(11}1FrQe zBke2Wqh$pBialp*klx)`W9M3XJMUOauZAs>i(zA?Ch7FVKaM)xgD_*Vwm!~VThCx^ zy$m?RYJhBwHe(nDe;Pj5x=}{0Y=C1ZY;?@^>Awl|>7b+Q<;*|*Q7=4Yzd8oP7-tV< zrAg@0kB`8*#8}AmVY|lmJ&?gSLcU!Mn-C41k>y>G{TsA*;9*l5{Wr(nI<}?1VJKsy z!?8Wx&@bHE@q9JP&mCfy;t0z0HK_AUj}1tVYf+}>Bkx(~d3K=L6wbQF*7@<}j|1y4 zg(Y{u<^|(WjdZTnei!u9uw9V=ZH7nLdKBj^lHjF`*ezx#s&qNeE3h7oN0{5#ry>lV zS9ld+vTtKMLz@%%&MTC8?Mw=`P(<5NV@lMVK~W_AyxIqmmalNgI=!kGVOKmVx0Y2aF@*$G8=I&|67) ztfpTId1lk-KYAzg*)K;;;I|!V1-T%`ztQq~j4>NQXEFT0i@D!dNe6ZE7OAUW<{j_+ z_C-8v+2@^g=(Sj65BmhxfuqPfuK!>1e(#nH=2}0*UWx9fVIK$Utv^HEO`z^}{oCVh zk0am8P;R;r=bqSrJ*-B+AeK*>ejZxgUU)s(-W)s~XC(j?@ zHX?4>*1Yb;LG3z3o=QyT9E0_jXHC*0uttZmOS;fZZ686sRAw*hVHv`G7jfk}OX}ye zEi%0P+gP7tzjsH`%!%y#(vYD@|FB&LApN$C-0e;jQU z=J9)&#z|8=B@Q~tC(QIT{FcEl){}-tF}~*cE4F85WYro2H>}@&yFva^|74~oet*ss zp6SnkSImR$S_j(}?bGj=1U*cjhF-4QWAn%_`R_nH$$z_vepmVL`dx1&^O<}dB|W4y z*9^1__-n_MeZGhAum*%OFal+3METD5oGq&Efo3x8V#J4;$=gvLGqz1ce~vcLt;adJ z57NIpSGW_n#q*b=C1H6{uJL9ri(l`G5-pT(1`7#c3 zIF8Y;gU-2k&|h=i=P-EIxxoUAW!YbjM;JR1*VqTQPNlmH+@%(e9$J<#=W;Cy`eW<2 zBhHLF>Dv52xI1>3jpS2#PyEiE8}rk(>!iczj%!F!&|sPELVEb_l9-no5k}bsTXv>7iW5JP-B!?{V*W z$E~?BoijZ91`NErHYL-)O{q$>Tl-~K#qYniS2e0ZAc$*Iinwxv4grcmbCJ^^Y&;sw$H)3DBBD2+rs@Rl4b?GX9_m54Q5-+b~y62 zTs!RhVWOS?a;;ehL_%c`r5Rmy&l^pQeT{t=VH83Zsme_PtsN%&KD+8 z9@n94X_=#&4APGI!F2QcW!4Y6*YxxKq`@o4D@lw;Qy9BcLDrG_pNZ*oUxmEn7>G8i zQv8nkmAb^$xpBzTc7wJC?H%-TmTW`2mOz_djC!qd8@5e{F&{)b_%-fPRlEmd^c419 zG=VnfCU;@o81?!_wkgnQ`CaBc?d`GrUAQ1Mtr5R!bK&*T1!df8w{b?oyj_KMf;Q#2 zuONlJ1IYhPUFgrrH`YJTZv_2_ZG+C+^Tl_2w{#;fZ5p7i|2w|ZJ>>&Tw|{W&uFjNJkokl;Yd%m*%-MLLG4<|j^p2}dqR_0XiUWP{+Q?RDYa!a1rhH*ax z{F_-cnH+bM`1SNQnUqe>WvE#w6J{5RA!QGmf?#6{6yUYQ7ty#x+?tzU zD2`u5!a*)}OP4ME6pm-b-Eq+Pgo{@oda3y!qQyjUn-%T}~FXLOgx4bF8TQbH%scOGeV1oHcD zTD)wj3xVgjdNcPMuo#ioKWlU{aBB@P(QPaq&1UJ+;mCF?DtRNYZ@*?w85)R^I129ZoZ;y6GD48J|k=yP0lqjdwST zEtcoFho$pin*^)$+_B^2eE)-n6x3%izyH`wRmkPdxS98M&u)(>ZiPw^ej8_r({Yi|xthd``ZA zQ_$7oyQFT*;H@P!A4Tzcx~P8knW`6GsAfof{Q@IhGV_HOftxvCwV7#*3-T=TJ?Fte z4-Krjr+CwVn$1P`7S?Pj*b19vxyV+PwDfsf)aMN(SPu0}4)YQ;lMfDlsHA#JQT088 zHVvG)x%l1z^FYw$i#^+SOn9(mrD{lgCJnz`_iz8sv?Y&_pWEv#{wqBat0A$PEk#=k zYwjz!KUVYo=mU`yIC}Y&mwv^g<6?lVFW_k2A~fH0G;JBHW;v>6A**F^sJXA`{=%B? z7d#NVxgX8BL7J?Cj|k0HM>Cg}*Dx*NMdHjjss7JDW}GTm_Hg~N;)MNKrbB4XCSlE+ zSuSsg?Ue7w+;^AP*}Orn=kg}WR19WJ?j2`kLF2g4JL2elRK9#6NROG~(;E*OwS^>P zOusxq`L0Kfu!ykTS}g7!pkv=29_$9*8({&^;skBRl8^MaQ~cR>x5{fPs%h?Tj_2?5 zS$|B|SHz!fi))9(Ygy(cUF-1uL;3zJp23eTOV!zWSlo8;V`WRt~q<-r~ktXt|f{XQ+& zD}MVg*fjEni|$ScM!RRcm|laa!seDcBUt*_ec7 z!)SWYb7+5EyHNLB-R9_Z&t0=QTK$~u3tNT8K9B$nYkzVs(qxFKE~&Qns*(ggZ54OZ zT$@?(V9`T`HZ0Kl(sMV!r3By}s)tmNkc@w{35t#3xRZ|ZF-q`<1+S3zv2y==!Ecs#)j2Nr)(aHapg;3othE_a@_xBRof;JVb^ zti3nlw!Q*W{vngM?vvtvg1F}`pRN>_ZXaJ)$`uGt)7T5rB!FAJoWjp|`A9o)#M6Su z1^+eDn(4kXV`}&r4nFd^pAv#!AA&c7mQ5cXI>%+l zzPLBRz2%bwPh6S~9fBtXf6IL~4~5YGyAb>*A^7tl_!}WO3TNJQ7#)I71kQNPIma<> z+hRP{gt+I}IA1z16gmm{*edDp*MdJH_*;VipMrOt+c(^&1@EL34A*RTGmxKIJ~M(J z6Z~A1C-VO^8)RHZ+|67rc=s>|C_i%quaJh}0dc=b=?Jdv(4B&}j&Kfd7Wcc=z2MIZ z{xiWJu~MttytYU1^hoCrulD*-@Xi1}5@S5Zt4r{1FC9m% z2yy?N5PXNwNl1e_P3Zqb@U-AM{(4UEE(o4^?Q}Quj^K0R4zOb{JPt(Hl8^r}A^2xQ z@Hrv)vJm`s;I^EPbNuXcH*;Tz`@Q16bi8w@{lhPn&czP5V>CRz5khAm+Npf;Ef2x} z5;*xxONXQ7wRjqoE2yGPiF+`m8H`P;|HF>J9Mr+EIecmdkcrK?* zndZGs?PDu=df&Hco>k$g6<7LJg{M!sGDl@<#Z;f>bcEpRuCkh~mbEoEEScZ1YDG(% zk!KaK%Ik`SYg){bR4Y|~smt7}I?f^1J;HGYm?4I3Ts7Y?$(N*-E}Y-8Vr4_q%C^PM z8Z%QCV%}A)SyRBxsg)^BX7^=@^@AMj!#ovl+9*x-hVuRe%_@q)bt?e3U?a zBhB!c-vO*m<6CnZmJr%3Z)VA=l`X5?qtIK@vU0&PsRo1oHc2`g}BPO~L-D=khW?UAv0#(S+SX1H9*T4G30zqqQpc;V8PR2z&&tXhh-9wa2|rSHtG zPvj$TYts@Yd|o=FkZlXllF>p!K;8uH1XDi(E=Mou>Bof9(TYIcN1l?Lt z^D>(ol0Oa0(5TE`yzJ`@ZcPb9?Pp|#?clPDhYeVELNLsq5QFMW&^+N~)kuXdJ<(%c zhGnsdLAIhrhdHdiWy>`=lFIp2GxlSuuZ4C$=spJE`GIMWmoJx)AL&GbDZqS?7j^H+ z5Y)a`gy0-k^P>Ap-J|`l_wcxfH+y)Qhp+VTu^#>u#(}&@{}T6T|LZW0;zgVr^YvPZ z@e(iMGBmaC9|}&Lg)+6YxEbhf)IsRuYPXtnE^|)oKWuH)YN&hO({az1OSqndRd-!C} z{SgnZ@bI@he2Ryk@bIY~Ze*TMespff&zFVZT^{~vkIqvbex-*W7d%*QPY50?52Z3W z(sHPCrD5`*hx_^XfQS3#;Vr>~`FLFLU_O56(ed-KK;#$X$Ir)7 z5BKx2(!;Oz_)mDapO1AO?&sqi5BKx&_7MCn5BKwNq{vgq|6h9i)CwNV$2!4-`Iz+F zv)z#7GR>ZQA73DNFds*Y94DABalwQ6GC^?C@$;p^!~J}@+Qa>Pxy8e0c9C5R(rUgFFQl<(ZgI|&t-xK^RYtkU_RD)?*06l?YZ~yIf4iCvEY2iL@-~9 z1rO#+sooV7?>-59Z6wo_jz2Z}HswcvA3SzU;cdF~M=mERUakBF`m$y@x*?f*%RN zi)BHLbUx?NsStTC@f$pRv4>Z9cxl|d1k-1j;KB5{%yZ9lnB%;g3eUZdR|+0XpG_V< zPiXMA&%^6Id_tLfA)Pu8@AB}QJba&r`}Cjk@Gp4o=g6R+^sn>qjE8^G!{799pS}+I zNyq2EOC|%%moIsA9uYj4{(A)vrvGD}dq16@^xXUS(}D-n{}qpp3@t5J8IO*SAM@Ok z{sM`^Tb_F#|4{H?xQk_QPuwqu1s6Ml!E$?<;6e8fc=(rv7v2hF5<>SkdidQQKHI~8 zqGJr_?d-w+OE3aI^4}6kO9m@dX~8KItHnMuywy(O=-< zO&-2l@L+kqUGQK%>hRn%eG#nXrfuMT(1((e*n+aYz| zE%=WD?scC_cL3LYF3$#V-RE*Ffa^Y&4+FUFbGco@SAKM#%Oe3?_p?ARi@nr+cZqv{ zEP(6&uQvmDsZ`3rvA%SYf+qvG?)%sqz!Rm;ekslv11YCmqkzezwrTF_bJ>Gz;%COM*!FT3wr~&wrfuXaNUpaU(IID zkEA_yxs#Kl={u))tTG7&J#0PC-PvrgiIHS8GVQc$62zriJIDBcGZ3zRkY-9> z?b-rq{-OS_gkRE}l%?n%-jeWBfdG|%g%fbjXKD7FXZ+tRoi_I?`j`4wtPT%!qWzHK z84+H^6_C4<(>uo=`rOB9kYK>Sx}7ingZwK)Zv_|*yxP7!U;cN=pcFcD?8W>ah@bk` z{3q}I!Up!%H2mS}rYBs3@#A`0&_6#1^B$0Sq?-T82le1y`=!;n!1MVpZgL*9zZdWQ z{9iF;>eRS*oz7;?l<8-0hqzm0M&u!38F4mqsIP$MydQ?BKf0RdvCVSoAg_ikl7hvF z={4p;6l>~*Gs_!G+eeKx&K8TFb61^Us@JY4o!H+2_rHdo0))fq|FB}5)x8wwZ<~Qr z7ZY`l5qD?gAM2xI2YVu|j-6ox%-(x=9=QnmV?GU?9lU=H=eKb_H`z{`5YWpt*xVS$ zx#@w>1(sTxm_7z!;%x8aB+f*qao&0i?CL3DJ%EG!BaA9=g zoO>B~q+N&g&;g)vK&70VT!VA(uxoJ#-MP-oS=i=pENcAUxBCr;7G`UbXt(3K#iywGDJp#6%wxX|98= zs`iV+>9(8&UFsm9-Sh}(c6~D!kFrsLcw8DD-m8~Ema5hS_${>F9I1#fqRms|9+xeBEOC@+_ENLA&nHUsODAJHqXb zj-C{SzOGO`W`VH6^q7@N9>$S}Md%xLG{RO1^f_!tUr~s%zEj${OVDR*haM-UMH=nk zd$yd@1_^W|!A1=I(0+{l4t-Hp9}f78pdOcLJ+|#3+{1nh(~fTAg6Vq~^%({H8QWf- z2YpP#Y+kVLy$>4*X7%|)yUNRXT>N_#&8%!VSwS9u?4}WI+ z!|f=uYy)AB&Dx^r`X=fy@}GQlLFWnE5a`l8f4hWNhVZr{JktM9;2CL`sPh7TY0#1ltf>f-#mW|vs>uB5WpEezcJ1}5B~ypj5~jQbkrbk zIKH5Ld(us#eR1)A!p1w-M?YcvXt=SuB(mGt;^De5p!4EW*VcS4URC88S%?2H9T{}H zvTfDUChSmaj;~DJ8t2|+YWY~X3`P?NF>GGcr9rndue+gYwx?CY>BQ*s)wWJJl9^y#brfV2^oCO9PlNr!}-*YC}QkSTolYtiC96;ovcLUxbdu zWyozYoqk;{ep+!)$n$Itn5*3RVS5hrmh4%~+|%{<#x@t!(nkA@&p(G_{Z%|HTJ`*M zRxbf8%8Qpm4w* z^BgjVr;mA%ohkyZ-%?QhLJgb{sFwSdg4xeK|3Wn(2FClAf|+#Y_N!fnO3us1A7{z4 z=T5K9#uYZ-8Cv*75`W6Gpu=p?!f1evd}ljZq4S;XB%1H+rE@O=A3BnY69Ar3)C=Qz zdriPU@wj{Kv;Q&Q8AV6`xxVd%yZ0G--iXQm>EPLs z;MVhxOgo{Ge|P>_ZSrqkvC_{#rb?e<5=elrrxs=p_snl=X_50Vp_|jQg-D~{XZtye zXOe%oxMnugJ=*`(@*Koh!W}Q-t}k%!6Hxwnag9xu9qfC;!)1BF;;kO;+GGox4IZvz z1b*4-;TJfk_Wvotxz@?M>YPH}R-?Y%W zU2u)B;+Rv}i*)?_-Q?kZ{_gbf@j{!oM+Db!x5~G@f@`>n@AK&R;X+5fy~vL&AKCZI zB(sV8#d5`g(E-H3C9|5BNO&&VR~LH#RShX?xCa;f;|#eZA@ zxofz34_kX%mX!eXC7}KkosS1%LH=9CzwQN6_d)(s_`obqr~|pbD4ob^c|Y5=x2Na< z*DlFeuD!7z(C|m{BQ9oBFz<=C%GsI+0uc+wKWy!7jtoLtNzA)~{;$Adnz!@@(aY3n zl~+x#oL(7^PnukD<(2WPD){}%ii#j$*|8xL^5Z&=b54 zIbnHmYj3C4?#tTua(bbijj!!xW^Wv88t*`7{Bg*)GGidZ7>0EP*lPxZMpy zI|TbEl-J)i2KLA9#(LNdklRneIs^0qZvd7lpniB$p2E6W1hReFAzcf3{RfvoUSFL! z*>#E8%QYp^NI||yyMY@hdxxAc39(5RuCH|$r{^}pe;MwH z!Df1VV0vy*zUn~TC;!wl$?ufdu?A>_?7Orf*3#o9o%$bW0=%JwytnvLtIHyLYtxGzuDxU?l7j8_l%ngPCwk>)9+KjW47Eb=4` zUU}~@%d2LYxR?GC#>u`<}2GF@$j;ISIEuM3LW555XMi@@ivp>H1R{q+OE=WDQC zGlTY{@cu2>6eyLJP_y@2Sbs7iL#E8wK!&^? z>4!E8+t-{78Q(Xh?!Y?K*!F{W!2JR6*m$X3%eMAQT0RN;@nhTPK900~9c$7NH(QYqf(&bhkxz*YJl$BFIdIj2tI#@KnH{SI}Ob?-j7F9XfqPLy@nLC|=9i0>ER8|!8->SPma zVo)c25_!fokw(~Tlwtov3`ta`k@;>uZOLdFxxWCSg+D@dnUGJNUs6*WoWa8G^4P8VNjp7 z-i^UGEo&zc*9>gE^0&tF4cdFSpq%{rc=9(6_p$ERdncnewCh?v zZh&{8P9)K%aLuM{u$lbAvEIrgXf{KG7S3lQNNG}2Y-UHHUsvTGRUVM*s^8a)wpyY zad|<1{6@U0#$4Gr!qgvnhii3ijf?S49)@k5-sCg&4d`#-ep6$loNZt`+Q7VPm;w7p zr(44$&9!J-$pfDwQU(s8?TVqzrkxJ<1MIJkfHunj+t;u%z_l*sb5z=|4Dz-fdHpiV zTc0u->6qIHjNxuW8fsX_{x^dC!}E5~njsKdmPhAnm3h zo{bp0R6pVD7jSy-ZKXE8+R>N5$uT| zzqbE)x_9z0xM!VWyFvaJA}sptfFHX10R6-qU@Y^ifzj?7`#gN>>~QPGSsNV(raIcI zoL{=x_$=xP=_~{`3p)0{-j-@@UAXkt_*W`cU%dLS;%zNf+fST2kK(PVw$u`w(fjjH}+H_-(1ht6DxCr{_VSYp<}i%~{uc36ydc0Ni^{BR}P@P&)zv zvQ;0_u!zhxK+Dn!M|aVxuZz|esC|ONm8r(XEvH|a%+787waFJja-<_`7LfC*A?e72 zr4OA`bI*`XpV&P3-jXjpQ270#Yqk#DGN|VM0rwS04`H40S1(n)@^UTJwdQnc%Okw2 z&n<(t4!p1U{sG@FdZ3Ubmr~id_3G(izy5_6U;5QGue_XtK7vAQLWIs=ex=%{eT~De z_c4i5-W%FrG^KC%=KC1SJ44|dEZ;1QI7(ffE8p6no91wlweRKRyX30>m2b_^(Gh{8 z=Y=vMf6b7x3tnsp{53;wx&{7q#%Z0}KllCPuNh7QHGj>}mM>s8ixxR2E#H%4(>hwz@N2c*5!tSCnK4 zEstin>_TOz3MG1S>v>?)YEdg$w`Y)5FbvVkU-x^&lINh_= zoPZy%TFBAhgKo9NpPkcgHrqfkIpD@%iCTL*S>+cufIyy z6^K6@2scd-*NcI0(-t)*)>0sagXx30arV-+AL8*W zn$tB;yv)NBBKr=e^IIP7hpT$C=zgq6r$R=0nlJjP(!>4oJWX)TFLi&lhx_hl3(j!; z@?7uHXTGyP<#n@1$H$W%opH{o{nxzKHJsi_6?hEt@`YThHLr>;P zb2%GBb9v*673T7`WqhIYD=(j>ujX>-XkF5>6i#7(s^#))Z@B4G*unrCOP5Zo9}Z?lQoJdebBybG(XkhNBdAMYy1^X;UQoCLzZPPZKFw!O@#Va zocsjCrpGiFb#Nu6{G9C?5B84Rt0F)=7=N}65`^<0|NDf0?HBZ8(Ek-vubl4IY~26p z)_5u_ubSjsp7|P&o>3+b3Cl>re8LPihp~p!KC*r8w@0{*y7wW*tC`5j1p}I zZ=-GAODKzuS{tb8A~U52ymDRY0?4nqj+KP0q^#IrTVwj*ZrD|%Jf$A{;C}~qkU5rf zjq5_t=JRNTl>|Q#@G}Pd6u|al4{T~~i z)8$=*5^Lfgz;-C|lCp2|z;KbzA1Q-Z8bN=gPur+Wi%e|v9?}{Hx{aVqxmE(@n>Osb zQNC*-&!mmh1(09PMEP#7PW$yd=Rq0ccpHXWlez?9sJ(iXG3Gnx!TL~!aK=eJva}&%T)VDdUVCBt!LK55NNGIIl=nR!Ed1rY69I% zw6KJ0R?UbP_U=|TBVJ>`a}DxlKH^n?{CF)kzI==+TC@voPYUtsFp-iOXj|5Irbjg) zK23VYR9gUTNR>7jDK&u(F%4|DUvUYVrNjJo)~uPmCn@BN`>BhG@oy&kr1*^V`!j24WnU2_0uIg>nZhBfJRUo+EL z=f{qlz90SSD=*VnxJsGH|8l)e|| z!L((im*xlG^T|xFvJRO+{jZpjiK6$(xi2>UJX1gClXdc2J{c>=yp&ybif3C!@cd=` zw2a9od!uMRAAVN|&I**z{VzlCH$w0tBxOE2V?yvm2#!VnymVSZ@KqsrUzy+%wfjNw zRog-+8*gfC0tmJ6D^@KQ?eGv7dh#fKRe4~a-P=wQmuF{vQ(o=ze+2m-34=^Nee-$b zYrYT-zW#`EK2WowG}u9bwE$R~@Bt)CU%?v+3NEz?L)n3Ue(Dvx^CB+O3;RAkYHt?z z%aiUe3(6p#_1yciiDMp)K}hz}b3UZw%i4yC?2IxLzc!B)oU#%hA1yfP_;vhh5BFtr zb3ELa%{2?I;cA>!mxhL`_+pQaAMOTen#hkY!+%j8UVd`J?Y)vYf4)yyMCspLh+zkB`B*{3U`1=hM3H zAD{bNLN1GOOhKA|sQ)loj)w2cNg1f}uY4qc@mb3O9__V6(k(9UdQ*RTzYZVtS>5pd zzXj4=zXjcX6(5L6Goa3l%CJiV9+ZD|_$55BswEVV`|3})2aOl=kABs^*0FqH(`T17 zBCWz0ivvjp{ZqaZ%sW8Y{m$(H{sXU8PMgpFF5!OxiFsGh{}ofOIy+emw&R|yET+P1 zU=o%W-EaHj?0#GBt?j|w`VjPAaPEB7xzKHa@jT@qe6Pmd!*?+c$dsDB3GB5UGaLK8 z&c*y=NR{1R3mx|L$;O)LNRZ0g=GRPrzSLB9!9Qgq!0g`HZeZ^tj2_PEeq;9E`tR5q zx~_0{<^gkK@4BMh)K}BHZoux|b;Y}1KL>ltx}g68VPA*+f+H~R8E-ZW&0xMXX0XFI zK)#Xzz2wov{`e>}h0pYpM7Y>jTYqdQXgmP7*hfN{N(#I-Mhi9$h;+{7zS9EC(_+In z9ITEf_H*B9Zhxqon^X35bl3*y=qa-MB%4kD{h@bYZtm|7ZO6Ra?u#-T^6!f>8|>cD z*D?PK)5j6R9I!>^faLLxVH*zq5c6d6=k}U9{))g~3;0uA5sjFuQa1K#Y^;?XR3oiw zz@Gs<-3P_==iIppe7=W$mQ1UjnuygqU}XN?jrpX%_bZM(<=ma=oGvV$qB>SozH(~q zFRVPL1^J1(%r2<2Bd{kYa-EyMs~^%(f0&WY)jid#F>h=fTeZLEaAae0X4U=^;O*o% zbMhMq`%r_~uRLbJW3swxf8-yW?iVXJfE-NuJUI@!FMfB{M zzoYltLtn%G*>>|iTgI+U4k*7J?$0EQ^Z>{U!7JnPJp6nE`+@0?abdi)><)-`wN>3+ zHIZewtTk4C1KhHVZ)G^wBTb&krAgQOy_1tSARS}V%Sn4=%nZ$Z*X(CHB!*z`Ch7(0 zPlVs5K~?*i4vY(BvkaU2R~y?CCr?mcg_e*1r*|^>A-(rvBg@Ca?|ZgfjVRxTeQ?}Q z`D4iIxUZD@KC=E$-uBsVX8#iSq5lVPx4J<*x9W!JkhF3gr$1yB_(A(A`zdpD6IQ-6 zLiS|l@U-2NNxwNPgT0pwFCQK5%S?i&6zb?0>^H=j&-yZXo_MUco^nFg3(8tGPM-n) zY-1vD%X&2pd!d>l@KF25FRo2HQFMxfIVIl@A(j=2-7! zy62un)(wVz5_vow`Frz!_EwU{YXvSZ`|L?ZUNTRWPS?@i$uFJit!(^W;^d(ZdiOF< z=$`&r23Sw%o^et?=GETGbjR=?MjYqWRmJVbjur6<+z>Z0?`}Hmr#sC)xD^XhvJXxt zgl<2a+X?rF$%5Dz=~$tTW16ZVoskEJK6GyNJ*At@x%S>qY#uUaYsr?u(N)k`@!|`j ze}azqee;leKS9T{@lo|)27gK!4a3bRbGg7WBohz&?Ec)GgIx8$^2tyfo&Ezy z$kZ`L%;El+HlK{f(fRoM(LRN6{rzY*|ABoDzf$~y7X;OL@%9k>uS4*MLhwgI@P7@# zGa>kgAvoux`QnAep}hD_A^5@&ysxas*4AaMEAngsn^aMuBA)(rS~h*1cC!`tFwytQ z)QUwggt&D6!dp$BonkpNr`BR>?p5ueLTo}JBALmvB`oJf4W%+baZj&HR@~aaPb+d3 z6+IUVmr{R$wRreP7XW#|Xk*yc0v$#oNRvcFL10;sIZiPD;~wtIY|xR}E4Yv4W)IhS z5*^+m_;8d9zm-UOxbI%)T;#`>VeA$6#C@5N>Np_o%Ua?xu_ErvcvJ^L5P!vU@5_EF zJXwxUM`b^xYzMQN&xO4VkJA=_2 zpy^ZEU<<7&gPO#g<}?(Im&7J}7(kNR9wK-_C3D_)t?%1=?KOKVv?qOfx}In6|Nr0r zTi^QDef?{F>s!9dH&=D0{`1XMssCy}Fx+dKpmHRD@m`{dJLe9F{QkIrZ`8k#<<&d- zSMeWLLb+0PR(0{(Ut`<(N!F@f5aPWv}oZNF|-6DUB<&yae{a-b$ zvfRyGx&KenJDOH8weoD|x{iAdUc!o^b6wARb6sX9)}VJDvfr#u$7jRH#0N>*2A-5S zm4H4@FV?6z_eFcG7u|yS1AM>T^JHT09g8`?GOqNMFGm+VgYK;x-+g@tp$mj{_7Z#- z#>}3BW8&R!uaBkPE{VVTNDAL|GfnK5`!Ppg=MP|;(YLkC_qv~zb{kKxb~c#%)i_nbKmJs8mN-TJD?Ceo57+Ig@2 zehb4v@(j<*(>R{BAM{o9JqbI#oHNPAJCUC^<^C?dPdQfr+nGC4=t9jz%+28%yOsNx zlk=+!hEC{?)x1JlUP;TJZwufA^2z3f=vm?WxpXG357N(vzQ{vI?wql2^9r@VOOBd7*O6+|YWzLv22S*k}7Hs*HDZc>oLLVS3>U8lp^Ci!? zA6WzW>R=n7eqQa@>vzrl`t#$>GnDh>ckS@BRjJJ4wVBb6C6ALdUEwT3AUP56-ou z%bnH1a(j=Hps9U#OQjh!Vp{y&L6sLEZIUA~uZ;P$W2I){G(0m+{|x1adAbhoW+Ls9 zDEmJ^8qGx7{Qz}uCem#n(~b2IdtdRb`KziC)pw1D&fh@He?-8C^BBF@&pH;@$OxT> z%$AF?>fY*s$P=H}FJR|@?`cQX#ua$S8pNtkq3Ehz>mB*S5ox`YSQ#6&qL@i6!SBt#@;^ ztVc&7dopG!G%oZ*KJ-Js^_WMp{vb2uJ&OIKhBCu1<%P|7>-Q+^3Xq=uBLh)h;Gh2L z(QYdJ=dnkc`9l7b@tcef>NLy2nqT*AA2Tj}()68(%%Hrf z38-g~aVBJ_g&yk67tu!JYRf0qSs3@r5%+yRgwAUmvL1l#0@Q1j^$=wJG2f#eZ96xE zF9Obd-3NX>Xg`(yN#HEQlpzZJvZ@s28NRbr(i8)$3brAd)?)?lhV6Ie2jzJWbA`z( z5_cj!P$$i>i!U_g-~MS|`GzXA1!y0)8q>NCdb2NLo^)$L;_bD#t{<5=Recn8wxo63?DH2yi>mG#54+ICkg2DK=Mju7-EggwH&HbEu4-VE zHzMzt_gcOg=K9MMr;fsIMl`uGQy-;lcVjM<^o`M$gOu&*M9~7qne?LXPW(2Rc%)zZv35#wKFb09Fx?+Uy7S65jQFE?)_fg}G^HJV%D}pmgbZ3I zqlvHftH%k*8((d#-I*Vt?5EIH(66=uS|6k4t9DGnG``fPZ(*sQE*b{u8BVTxpL!!x z?DS2<4B{hToxX5 z`Mm$1953b(<+6Eb0w z%y)ToflZ(2H_YA{YoZH!VdeGM!wsUj zQ~EoExE(@220p`y@%g#nIf^!h@9{IAThYFOLNnTj`+Oz;^ww^a|_L( zj~~~7H9Lg2bVc(WE6B;sSK_spg=L_o(Qaj}v7&HM1wmQ?=I#wT%VHr4yOGq zv4c=WYX;Rcgh2BGx6v5FXJ`lEj-R~#nKyoV4QwF1`dZow0^fdtTDm@ZEuPg3LiJBx zzZTXDNH^=JZ&WJ`wc@$FUwF<>UauN*E&gW>x!(RSvHxGT|Mm7i`bB$jh7_ulLv*ow z`5AlpefwW+|J_`FQa-+AYRRU-<{a4e0Fxx?cOltta&2mu4N-*gLg&1ruRmV350#f|S;Tiq7T7ug>`DA`@%h_4`1kYRKgomtDi2-& zIdX+NA`kvMz$t&36nHK7Ulbg6`K(iXt>E(lT-La>S#;LS^$7;Iu>_OVO49s6#`eLq z@^bHKdf5#BY1%aJsd7q%w7pnAYHCM6;1s4a4RX_prjE>$EJ`)E2*lMXwBOcB!Q!UI zWewSDV@_fvpxEN?wq}|YZ%ca?*c#r30h)&96^#O=<>I=NVCghN@xx7dIQghM?D6;Mk9oLHuWL_XxFe*AC9Z8D!0gP^Ab%2Tvb1n_(%`evrmcpa<&vYqA*_f2~K*yTy^Kc59HzV zvfyDkdBdY;zO;y}hdp{9KPfon@yp58lG&l09eMDLf`{?lo`?R8JUHf1tqa4|J^CTO zO6bFI?-o2vpZh#|ro$XbpUobG(oL8Cgzb;N zW;!PieoG!)d4_AIn;8h4;@XdIcW@fletZMupi_G7A0G;E?H|7t;Mza_cU!ByRnpz1 zPXDn6%K)3igc8WLNIC;;U(a@}_OT#bWiQFDk7gq7Se3)I-ZS;jaU^+8!OwSH5`L!- z;$E5!>xZur_|d;~gSd09O!V4o6p*X>S9lI?=)X(>x&Ep6j|aHMU#~aez25tze|np4;cH*Y<}}QEKxT>i zP%=*k@&}K3*J_i}32Hw=o^+xAtENq#;?`c>|0k{0PR7vJQJ%Sthyz{(6IP0Z8ES@@ zLzrt>g!z3y>A9Dx;CY=qf8s<0m=sywh-02J+O$fNj`fbt#}XFFVDi}S!ZiF%ej~g7 zJj^L4My_vLH?A3!rBkIs=h{olce%c)F9XhRD|MPSvjJ$@>N{R<#*g&+PU(|^$8n`o zJo}rg;f}ht2CG%LiXT_<;UnJ+?xlQ!`JWc)Z;H%^(#QDxxK9oVBF}dR<<`2&K3;|a zgwx~T5Fc;fx^EJnK3^YSCiL28YdSK$=@gIKC;XlDUcdjO&3z&tL z`d{O#K)${>C5`(WA!M7$a5R6kExkf;ueq^4mf8RQf0>f*-cdgC{P+6TzF6~BL)7r& z3dmK%*XwTs*L$DzKL5eH4{3j2{D*yEr}&xY`Q@#qpTgJUCRbmm_Wk_y=U7|)Yx+~3 zFl_Qp@egjE2+W~5f1&?;eWBV(+Ce6s3*&!2-i3Kb@)iOA!1K%7(EnA_%PMmAg+Ozi zi7~lydWBP5I`h8pmfy<=k+8Q;Z;84)SkGMAjWy^ASdT9ro@kBZ{ufy1jIJ6nEQYnS z6xK6pU{9tCI!4r?iD7*uigP21fo+2ygSDH{#+_5oHAwPHVy_Z)CZf>avCp`VCE*Wi z8uV8SeWRGcbCG*aK?j22SpMA^JTCYLSc~EM7kTZ6U-~;l4E$2OLY|-DdV2MDJUuMz zHH2Oeb$h;D&^;|~3Wrsi0mCZHpkY%ZFHU<9XZ~WGxtH>*4$0}&&)dCbCf+rF9rhYs zXa-H8zDY0icLqee<`?h`jzZ{*l-TjZ=G(Ex#I-loiJ0{xcUA(DxN`&7Pu*{G3S*8i z4A`nFr92VrcO-9veRSk+c_R$?-TcyrKbm$SWO*0o+9x5;GtmJVc?u!VP{`rQ!?S#K zjfvMtXXpI=v97iwSdZeKqX}3G!(O4uUC3XQLsZe^{Be?Zn*OI(@7v+txwS>wuDSv? zv`jLi`>`Kq2&2ww95>VN>DBvf+WFxpv8KoP&FqGL1HxqfMi5W6K@(-1&93>}(^!Q) ziDSzndm~YQZ)3#TG2&jtBazHr#4*^5Xhv{Nd5pDpQ;)8)u5;}pJO@0EI3-|D-0FKl zUkA2`K8T|{GK^@%=bbqd`-sW#&bM!p`Gd4R6BL4;<-g8VLY?h5L?X%dRA%iwKJ7tBCv2d_EQzLTSm3zJdp5t)V zM;~;0egQpyE%|+Fv4Gs-<#NHc_cO%I&SBdHktun`K#P8$8~uT{StV$1T{=L& zG7(9qL(d;(r$e{jUQGu-_D@%vo7O<*Z9DRSI&8(a0H=(%A{=}V_MlAoGDXq$@{Dx$ zLDY4MLPy{wT%W`BpZJWnoVre<5g+RIrKErJ)8q8&zYF@S0;?BHozdITCLBWBK^Y)Ay{Jp23;=+m_9A3>O=%ggT-+4-GM zrtX;89Yve@B>E}#Ka5Wd{ZTdgp_w1WY~A3wE|KxcgV0~KXIr6Ox6VPih@q~p`KX|k zV}id*f-7t_pI_f}HF#bZENa$V*#r7wpU>*G%N4<|7QMSbei2s4E*# zmvvm#v%!`16maSZY8^VgI-_@g65*dfx^TSrF4BwkBzjOET>XjpX;z+=!_$dB3>gnu zJ#DwAn=}kx_3EiRKimtOGWg-MJW}tU>F~}4=F~gT8Sk5E&>y%q4~@re)VsYsCk)TN zDb@OmkC%#`nJ7z@u3alcy<9WNw0;9&CsDT6Ofjv`{X&zsg5+TjH6f6ug510Pege&mI}?t6x9^O{o7f;X|1r~97y7ht`3 zz7Y4vaL@dXqO8ouI0AMFKYbKsbUkD$#@yLf)Y)&KEf|3M@m#=W`4{BiJ0D8H_X86(=%JgB_oxqt# zJF))-Z9>MzLoN2e^hHN5?H&Ed$gR=X(nBbphd|Tg(P(%YemY!~QGTB>UG&}Sk}g_a z>!rN%8+;AM%1s>SpuDn<(SEVkvwf%&96vEXuR%R?=M-k_7e5W#EUb4=$#_%i**E7j zI6I;k|G#kehy^T%S0=`MEs8PNckeD*Fm}$E=`Y+}xZnuRl*AhF49aj6XHFKf9^(F9 zZ_Li`lmg`W7@VQU?--t$bS=U?hBC)*7uNIjkdb5JWAeR1TQa0$d%$sdVPwFNeHdpC z*z^_K9_aT=;dPBx&NtB(4EWNB1rriuzt)HP^gQGIrJ@Dn&NVXze5r836@$$TeBaC% zKWFUp4WQkM_Uaoblk9`{qnv7){G@tzI2J2CfxPhh;}iMH=M9$zNb{1hAQUf_yz8f$OIb@3$8XmzadvVI+V1ZSFw^P~SA1_QjbdzBhcJ?3 zk_Yi^QBena&OwY@QftfE1&{|i$D7)#qIS%|u}Tzjm7KRWd!7S$0ch`uWRFkw7p=8p z@g#8OiSDzjLtJLIV9bpAW5-m>3R)-NK4Ky=rs8*E4BwtWX5fy2H0_1zA%_xVf^p84C8%ZG28)>=9pw=XLJ67S9(V9kAzqQ!*M$kJI-5TlTm+xhS^j2*#t#?-Vk~SW0Q(y?RVPtOD8jB zj9@QZ5_Oql<^;yzER(hJO*BBtAofp9P9YtYr%4oSsypG*$EF3ww@eFz{I&TBo@>FA z`H3-OMJ;$TpGM30h&1pwtQzN}nmn{D({YJA)098U8)JOsJ<}AlHo^Xx&wCKwvpyb0 z+dP)}gWqg~!+L4(E?qC-SL@|-S}*aP#Cl12@jW@D81*vI`IW5vNQg`&sFzXLmamN! zRyNwYIbi88P#-jnY`S+9WT*T76*X}0||6E}X>9CF_VJ8%4;Z;PRQ zdVCk)8@0l=^WGRg&9lq3SB(4q_p<9A;|)9A7u$9Rd35jb{Ou0+IZ{x=|fQ7$&Ui7_0@6?w4^F+WfT zZ5=9>bYF~gPZ@*uK3@8BNq5$De)q3IddB1o=31$1W=Xwmzpp`A+J`#*Jod`6jG5De zrZM~&=8_K~zw7Yb!}()|TL3H_u8gA?ZUW)H$#4-4%X5Pb*NvkJB)>D^x^Yx8Vx}Ry zR?gcQS4LgiksOd!hI@)#xy)DIY#t%L{N6s3c3aDvmY3&Fxw8q--jq|uF606GW>Y?E zFYU(12faUyb%)=wkQ4RDo&T%-l*(=r{mW?GNGJPd^lkL7bui>%+ZoKSvz=MQJ{ls1I@JJQLElwi?QTMl<$v|i~WBu=7Tt{`vKC}o+XWZ>9zB#nSS$4l+g?E zO#q$B&R0;!*^Y2sraL+?D<4XJ%eA-9yw`_0X1srLV81#!tHQ;XapnHZC$22VD9;CxcEioEyG#T(H-5fm!8J8EetzB!vudgr&YxQY!}AM2x1gph z-q_ZLO*V^~I@EVx7q>Mp=M7c0K`3#t z_?(;5oEN(dM!JzG-&v$izR#}2kxucBrsa*WU^Fofjqnb8lxdub+F6I1I{M|7-oA9< zq<1X2_t2+kZ)#oInW~SS*1FPM|7g9HNbTH2v z8W-0=XFV%FVRZ?+wx}cz{>xjIHFhwzOuvRWQV^T6R!)dpAC5N@bY*+IsbN{8^VN^k z(anasy-j@(XOsLkZ0Iq}mc|t=`v(xYn)bTIjU9KoBWsQ94}c^! z%j;IvNXbHuJAYXl5o|ed_-&wP39qpwoG;ww1Z;Bsv)Z%^&5vE|eHa25ld zuZG6ko9Y`KBZo+VRH5<8;YgN_wq`_)<*jBVcV38d{A|2!`BF<{{llqgYDn{IZ(dBp zU`!6Dg(TtFZ5AvQhAj$q+PMuEX@8DuQ(LPhvfYnCQT!OmF~K&oV6EO}7HQ}loxhz! zSbg%AJ?p>7{zC^MkFMMSc|RRj>c!A;uMYOll|4T2i2+sj7i^AIKM;K|a)WnV@GaiG zvoW>A`ZUHS^o{2gJsy1`a^uhb*;)QrQm(`vlY7k^V!H&Z#XyFRI#n;&J7ccq zb(Z7(S&#Q&dC&Z!qo4Qfoy6tlY(I?a2*wc(;|cPd_xL$a46eGraPy$*2L?VkVD^@R z7VZqxje!m6d&-DT(YmC&nAx~ujBefZeEc4YRX-fP5lmmt>^E%8exzKg=WWwumbag> zn!6@vZ;8(F<+?5{*Le7SOJqn<65sFa2MWFjZ$EasEN%LXko4V6+Qlw?u9Y-p`oZq0 zb@!2HQ}+A20jX^{eoP{)S{`^(#p6_}c%I5!p1o4d!&K(jV^Uy-Q;(OMnG4h({Q`NrmV_Vi-JQ4+tf1$hN{bw=wP3p>Gz6eeVxV?9O z7=IdnKj{JQT`t|%DfT@xAlp^ok$lv@Z3BTZ|A;3CIeJ^(+^xx_qwDyGnvp0Y@Z;}4 zEfyYag2&~V@u5rNM|!pibT0nJ{14m{XL+K-H=}ir;h#9mKHXq<;bfo1SIILM{^<7L zNBU0t!~wN)-xGYhJZrcw3*Ifb(jOAs)-&8+BJYn2{=Phqkn67nFOsa(_zuN0LckD}_!n6Fv-44%28Ze#!2=J@=__Ypsga5W7x(irp2JovYPQ};WC zD_w`Xm>&qP{d7|BUZt1zSLp}hnS5#`>D1rlf@8hVx~qlHWWkZe)-?!zqu?!qYdvjH zdMWrxp9(PT5bAl=MCq>1B2Asq_k`^{hnjiL^dp7n%%+v)w@ z6*IDU&X_vIe^-`G>Foutm|pJf1+SPs-Isbsh5v3wrSGqzqS6mx`eaEe+3Mhbdbv*- z_X#wqV#ZV@l}{j3UteFdyw4NPmWT)+yEWWpC|T;4 zpxd+VaK*fB>TT_HHDnIk%QYR%{7~Z5NB^KWF_Qjfgng36mbx}2%d^#8VPUpn<#Jp2 zG#)IBx5GXPr!rdV8ff@AJlCG_P%_NotkeM0JLc`tXNJZ5W68XY^`zCDafyN>vm5zk z>^^NBmi@Wwuw0*d{ok0YrG4N&*72^2+JF5v;eJ~gvRM2Up(pO|S-Dkk?!)!zYdzej zZxEc}PVmBg%)@}*@B1Z@PhPXVLEGj8_ILoqi49a67Dgt?icqnJMUw*suZc-jS zgHrsk;Gvw)O8-xMvhd(#qxAowJh~4(lt=fWlb+$eD7+pMKALWde@pOCp5q?w%afGC zN_s!t_DBb>;U1H4pA}rgRs03P$){3idD$QX<&e)t!9zZsf`@!wmhlVma*zK+8NU#p z=Hc@^oZnjN-YRl;p*+V059N7Z@KBy*G7bvmdDg>cXrQ?2xQXHVWABqf&-Ta1SIM}E z^nQDFx8Ri1#|!1diS&N^GgNTW`}kOo-c}vFryK9l`}jn`8DGC0E)V#W37@M2K8nxH z!{;dv_v`g`kB=YUtA{&z!}uly597Pgqi4KyynBmB@8h=$9>#Y`z(>F1S^_?b-<^lg z29J-Q@AnBFmWNaxyhuLC!*m!fc$f|&JbK2rTko+E&y~pG4%k!*QRl}GR68v=Tj zbEDv4I_&Z2v*PRV_wfTBJ;T-cmX|$xAAe2oFx*k{eHo@h+{4L7<*)T{KRuTS9+tPc zGVv7hpC@>j&I>(yhTARW|5lIQ$Cn8n#_Obqe;Rz$70N_XD9=#ALwSaK^bB{S$TP~L z_wn(9hw@DKa9^JL^56#q59NGW@KDazJbKD=T;x3L(fjyG!9zIRx!}kTa*2k^@Pf0rL4)9uu zmyQROzs`5*cujGg@A@dUqW1!zz z%3tTf^t(xMo$tC;(nE2b?|LJ^b-wGP056hp*b+%U<)h=ay8~S3yP))Fozm-k*Wm!y z`L5a0*(<%ycb&ZrhPLL0x{kU@?Hz5CCrvk#+@qQFpJbXLj#xA6I;i{M23$TRfc zDgHzH@Od))Qm!fZ`A+?FUetFgzZ7>HZ{ABWOq0HNxx0lvW|mX`3eLd|Ny-$E>sRCM zMlOOnT0SV-o4orp5pH(I{in>m`cq^vZit2Q?}|H$c|n4O^4EckBnd~J{@?yP?lvKe zng47;)W7C`uCT4oan8RMOn#P*&*7gugDi3$KkY8q1DWN*__MhPNG$!a-*w(vvV3RK zUE!;yPbrUkE^QyFBDYP5%1Wg_bDI#gGDc*W2^+Ap3Bj|MqC9V4-yc`ngGW@Y-6zuWN1fIx(Cgj=wHfga{8y3> z^aTGH`iw_^$Ly_we&zSfz#%_3(N@geElfh!lKc6%&(DDWU-tEF!JdZFTAWv4_4lFQ z*wbtEybmJW&3u=HZuimON$f=#8-4Jz%_7`wW{%n=2d_|L^QzdTIP2-z|+}wp}7u}1ZHZ*EQZqgq@8uC5qsaHvwG1&Vj@d)x` zPkN6S&)u>6IUx`CSoQS{*nvHizbb$&g}%OlJCN?D;&HRk?F%zIljq@#m=QR;Vl;H< zN0{=NJU3y4S=bA|Nu*Ih_q_)zaNYsxW@kNgk`EVmzy01z19tS@KXAvPn?E%nRbY14 zEHkZpq8APs5qn@H_kMBD?eoz6d>Fc@hZaOO_1=uUMtT-wU*XzOX5opO6MHdkbov9c+`-0L#cbL5?=xp~gY{*f^GPml| zVLga{@kGOD>&iU>6`sxzRSv!v0M30k#ZN$6V!(Ar6Nj`+Ug02y!#b_7D2Xxp$R$XXw8L z=aHa(YP{b;e64@%n_?Me+}{;>yFTozNT&_2UB3t(VH@M8H+Xj9hkX?N&k0&v;&i1+e+uRL zdhp5}*Nrwm{tfce1_JZr#J~2HeAJ-ngaursnujH`}bANw+ z&4MyJ3%^p%UH~05Zu|Sca(UWEHGR-dT~o`lrusUn4I5L}(124Ec;{UE%0)cbHVrkc z(4|24p5Z`a+BCF4DY#)}nlS4Dr0uOMx%z27n~@*d>TS?zZCe3FWmOF~;D?1tGODph zYcI#5Y2EU6XMmgwtt*$UYzM#Pi&w6wX~QqQwtHquq(x5bygH;=smWGFoyI?;X5uSOL+uar*7{o|{x9L4?rXr{zA2XHGOi&yd%L3#q^Oy3-fYby|*x>6ms)WKip4cjv%5 zb6`*9!1m<8bUoG&BNfnDfpYwj?7xDJpO&{W$V1({Zjn{X93OM({<(SI@JrN~nV=`1 zKx10lC2S3zdQ^ztu*NGo-eb�Cj{sB z6P+x@*!x^MV=lh`ah7`_Q9dY7S%4=5PXu_D-BdK& zPPfXo-%!&@_YO4;qCG=p6x+kqSj(!mdC&9(=#X4@;E~;l>8KU$9XNr!1$tJ>Iny1a zHK8iYr+Ioxl@(=^GkQvu6_clkvQ3~Nwh|myGnvF@>e`mi|+ZIB%pd8b2j$M{wFMByy)RFZD{#u z-^00mpZe>7Day`^vXx^9}2GFz9{qu z0(!+qN!O?J+KVaI$qLt zM)_-h9j;Yrf1MP5O0WI(<^b3JTH7n7*Z%t1fL{A+ZGV(r`|HC2z4q7t-PVTY$~eU3 zTK_Q@>n59&gc8VgSCP9Zl=g;e157fOJvyyJSKywwG>3d;-F-p0ic7NVW8Sr)Gxa|i zoXB%Znxnhvl<@y0z*T;gBZ2q4m+m4>ofJY@B1z-wUx7Keq5m=k{m5> zEkF6zhUT2-!mke^7RDcQhW*MOeICEi`EPNT^nd98s_ErZy``b}C#?-lE-#<%=+As@ zXuB7Ogq0+L?+$l%Ms$FkdmH}$@@$NBWP=;V{WtlI@5Vb}3OgZkeLM543TlE#QFDay ze>P`c#NmhEV(Ro8?Ro&xjOi8z}vqk8{-Tfkh@^iw=vA2U}246d1y;9g7=o?#z#rv9~$ z3EOz}AI}rM%JJKHulGLbGXKH54{7tA388JF@>$jGsGuvWzo9bV2 z%HuU*cyjI`xyD6cHu?O8{`0l*d&J)tg^yms_~&cm=ZH{$pdRHK`oC&=<&3jw#oOoI@Uj=C{s!kg5YNRw0z2X= zM;tb(8$pNiXV)Gvui04(n?eIYqigIv7dU$2N3a%XQW;yt`%42mTzIc*p|FLDweRmi zmtcRw+%&U0V(n)3wwq0~AFMX?Sf);|e$M7M%g_5rTc*W_UK;!L&FVTp|3cS&u@>;F z7hngs8*BI{pbIfN)_suc!K3dhc)#{Zv*}^1FSAZ0hB|!{*2_CkFJB#GroDGw^-H8x z+uP>|E#@;Slz%Pi@Ap9ebJ*&t!}$>17rFaF+|w`XBjd>WNZpO+ab^6thOYG`fjVv1 zs7ViA+c)--J#2anK1k0-XS^7nApQ%{?57*><2C z_Uy@zxMC<9<##~Ggl$edQdsHNd#6w0>eMvIMmu_SU!6Tc{cHO`I=}vD{1_k7M!WBw z|2*`0UO*abK%6yf*a(J-g|3rF``HWYIge$~Y-U|kI@>0A=MSt+DB*W>(JI=&_P2xK)>{7^AtSjpZ3hRdEq~W@Of6y zK7@ZSt{)&B4#h^6MsOYt{r4ig0@!a`XS(Jmd5#Xkr0zm3bZ@qxtfin^ftlwisdlq> z56bvQuNF<%8ohAo$v-uF-~D}a%AoC|JUy^cok0Gi)|9?P$uKw-#_$nIeYiovuzA0r> z$|jXfpAerhX(|>N#TCibw?VcLm=1^So^R0$siIzpwOur8OBAMvs$PZdD61TjF&-@ zHH6qM;&674x38~4b(MKrqIbROX^n_UrUzqAs_V}2tVRv_+^evGruroTZZ@&KlC<-G4#h+3Jfv<|@jl z=XCsL`c2LaG0-wavv*5oq5B*={!L#%{(2jFbv4Qi7(m-b#eg{~? zBLH3B*3U`~bTvE+GtkxWtkzUkOv%#RsPHV)z+{fE<56Cj#l^Q_Q&};sT!oXK&~+68 z(twI|ZZ*yjOis;@I`o7~Y8scf-zNT?{TZ)o)Q%-fZ6i-lCutK}5_Rw=>X2lTx?i8C ziYm(+m$L&l3||DIUD3u>9o7VA6VzCoVbK;AKDcmw^&toM!w-14Unk$sgBPM4(Q*Bm zt)R9eLj~tLwvQKi^lrpry<5Zoyd%Ajj~9B%&yPZN69o_HXA7?Kbc=^M9zEqze6HXj zf7NYNKEft#3qa$gIO`uB>3#V(dg1!`V|l`TDi5FSdHC$|=ov4~Z=IV|ITe2~Pq+s> zKE9l)=Mtv#8y-Ew)$(*$a1B@SlX=2TNq?v5e2j?*cUW-cqxf5bGrzPiA^luwSBd-O zc04{(=!lPSxAuRPhs!oPi>sas>G6G>cB;=pT-QPPvXGI7BObSR?r*r@VR;xKc$l7X zkDj*)@S_{=(fhdSxiDP6UR>?*@$)g^@$vCnJbHU8;oj=e`*^M3VYsUV5952c$HxzM zqesu%xP;s3(fjygf`{R%9t!c%HpSfE`!X~lKE}gely&t`&L0XM=F4jyy%j;^OnLM^ z{+8gOoI?wp5Mj7Qf`{Rb^61HbiG(}WqxbQ0!NYL1tcGiL9g-%B>$sESemcc5__S`f zyQFa)$7sGOeYZ^v5TEs$;D7Nw%96g44E@Gz`PK+A7<5j`|9=t$sA4Ic06Fiad3K)hKSC;fPa1JI>R;hGxS{_t1>|~4{Ko@a z!`16ec(3<9=_O3?94@3?3>spg{BiNG{j9PI<*&mFb}0!Z(5rMhtK^yNxSpu~wNJ_w zHoY7e%72r#P0C053H|3=qbw_;Z)5&3h;Z;|zx$-BI}h@|N(9vLgT4&?Uj@UGXR}5* zV~UcWxgJWb7ihu?l0aG_CC+TBM@3Ix$?oju48juP*u}J=OmkOU8^r7vFH(oZ`7bW;7 z7M8DsecS&p^nWEtSl<7={wKmOd4_FE0vKJ~{%8I)e7#oSmELElP$&Hd?>?mEbFNaO z{_ugAlTv9Z#(QGtXJq7+UeDQ zzGEwF8|Z%c)KqioNVC~HXNWbw-U&ZAL(HAijk8I2MiXWe&-&$>Sf~R7a?&KNC`@J=&IM&*A zJ%#IEZhg$z2{^s_CA${(QEzlp^iy0z8nsjP98UFKjJ2Y5^P^Y?PkrC)Jv1b;7i(F& zu?D;|S&esbDX8ymLWh?;-39??Kp<|K!DZ{^|KU_>OC6#CWf3cwt;L4j1s8Hm=KZk1^u; zedGhzlX&iu=Es{@k6eTN!1wS%u0L%+`fo^@P1Vpr7>NADdi+kV;iBA>e&v?i_OL9> z#t-2S56c31l8!Wd&*#&t|I)6Dj>Va?n&*9eSRd`f`e+~4NBhpfZwP)v@jG`%-yN_y z038UsR{y-&g!T8G$bZE7qMfm5*L;+x`8^kA))Tw2mdH42TAW_}Bb$E((XN9>KwDs* zdpm~wqKyQs8`|_fvc~K^Ty0ME{)4kM(9>(rtKHdm^T-K(FP-b9^F{sAS@|;^sVhQ# z2JD~5`Nr$!Gk#1nrWeyF7N?w8!y95wQNLg<*5i>bo0GKXFob7HJKY7Gi@kFY{1c;p z;y#Z$=g+36U-y{4;WOn)ArCaIY2$%mqTK96xVupX)8(0El)5u22l*wOD*tfhi*?k4 z@SnCJ;lBrNo!^f|iU7s&;}vdzJQwhK2IC6xmUsX09Lv?QXFo(Y-dzm8wGwi_k&Q0a zSfY<#@x-`m?jO5(%ry^|JTQ9pL&aO-)sI~E@a5M&cIl&|a7qRjO@8t^)=koDPrITd ze_-^3C0pVT6+e9WBbPlo>ak17XPHN?i%|$7BqwQ=l0po|={1pSwp@w5CHEYI(#_+a zbQUSz&pPjT;=0y3&qMp<#N5F4y`HX>zTTT?^dT zt=9TjC-^*igws0tCEROV?F;$ah%5Od^;wd98=iB~e;*w9-KPZm1xD$;k;OdZy#CRI+J zIz5{S7Iqdl-G)Q*z_l#jtF{%l@ze!e+{#au7bk^O{45>h;abg za}osP(kIgodDDzD3VDb_V?zznuDR__gG=4ArrTEVh6{C$j~=w(c@z4@ZH*cj`DQb# z$N8Vl^#Kp@xa1C`VFS*WY;3bDlv19xUUCnI|9$wFyyrZ$KMv{=ob%8={*mDPR=iN| zdC`4U#C5Ho_^o)RBYv^Fwg0t(GhA&O_@Y5@hU?=Uf`|OO^5D;Uc)Biv|BD{(uM3Sr z{iO@jAuf2B4$$|tj_K+8CilF=!`*%$hrcLzm~KVV-i7h<_jUX7mwEKQ{7Db@<$-Qu zPC4;iVjaUB<8JN0?vErs*2Bk2W-z{2czC&oYoE#2vpw9WA0>WueLz{21^7I9o*m#x zd440nwck4);M%_xKyEq>SNpMB0$lqs_IEzL_G1qPxb|b;3UKYmbRAX0jZ3;54(PT2 zc|X7tLjQ3Se`rPOCiR>B`%gCN>XOUEab*') + + 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..166774a --- /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) + eval "$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/derive_rpmb_key.py b/optee/optee_os/scripts/derive_rpmb_key.py new file mode 100755 index 0000000..13f9a93 --- /dev/null +++ b/optee/optee_os/scripts/derive_rpmb_key.py @@ -0,0 +1,134 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2023, Linaro Limited +# + +import sys + + +def hex_parse(str): + try: + h = bytes.fromhex(str) + except ValueError as e: + try: + # Try to pad with a '0' nibble in front + h = bytes.fromhex('0' + str) + print('Odd number of nibbles in hexadecimal string', + file=sys.stderr) + raise e + except ValueError: + raise e + return h + + +def get_args(): + import argparse + import textwrap + + parser = argparse.ArgumentParser( + allow_abbrev=False, + description='''Derive an RPMB key from the Hardware Unique Key used + by OP-TEE and the CID of the RPMB.''', + epilog='''Note that the derived key matches what the + __huk_subkey_derive() would produce. If huk_subkey_derive() + is overridden to call another function, please don't use + this script''') + + parser.add_argument('--quiet', action='store_true', default=False, + help='''Gives only the hexstring of the RPMB key as + output, intended for scripting''') + parser.add_argument('--testkey', action='store_true', default=False, + help='''Outputs the hardcoded test key''') + parser.add_argument('--huk', type=hex_parse, + help='''Hardware Unique Key (16 bytes), as returned + by the platform specific function + tee_otp_get_hw_unique_key() in OP-TEE''') + parser.add_argument('--cid', type=hex_parse, help='CID (16 bytes)') + parser.add_argument('--compat', action='store_true', default=False, + help='''Generates a backwards compatible key, + only to be used if OP-TEE is build with + CFG_CORE_HUK_SUBKEY_COMPAT=y''') + + return parser.parse_args() + + +def derive_key(huk, cid, compat): + import struct + from cryptography.hazmat.primitives import hashes, hmac + + # Prepare the CID and Clear the PRV (Product revision) and CRC (CRC7 + # checksum) fields as OP-TEE does. + data = bytearray(cid) + data[9] = 0 + data[15] = 0 + + # This is how __huk_subkey_derive() is implemented, if huk_subkey_derive() + # is overridden the key derived here may not match what OP-TEE is using + # + # HUK is as tee_otp_get_hw_unique_key() in OP-TEE returns it + h = hmac.HMAC(huk, hashes.SHA256()) + if not compat: + usage_word = struct.pack(' FTRACE\x00\x01 ... +# +# is an array of 64-bit integers. +# - When the topmost byte is 0, the entry indicates a function return and the +# remaining bytes are a duration in nanoseconds. +# - A non-zero value is a stack depth, indicating a function entry, and the +# remaining bytes are the function's address. + +import sys + + +line = "" +curr_depth = 0 + + +def usage(): + print(f"Usage: {sys.argv[0]} ftrace.out") + print("Converts a ftrace file to text. Output is written to stdout.") + sys.exit(0) + + +def format_time(ns): + if ns < 1000000: + us = ns / 1000 + return f"{us:7.3f} us" + else: + ms = ns / 1000000 + return f"{ms:7.3f} ms" + + +def display(depth, val): + global line, curr_depth + if depth != 0: + curr_depth = depth + if line != "": + line = line.replace("TIME", " " * 10) + " {" + print(line) + line = "" + line = f" TIME | {depth:3} | " + " " * depth + f"0x{val:016x}()" + else: + if line != "": + line = line.replace("TIME", format_time(val)) + print(line) + line = "" + else: + if curr_depth != 0: + curr_depth = curr_depth - 1 + print(" " + format_time(val) + f" | {curr_depth:3} | " + + " " * curr_depth + "}") + + +def main(): + if len(sys.argv) < 2: + usage() + with open(sys.argv[1], 'rb') as f: + s = f.read() + magic = s.find(b'FTRACE\x00\x01') + if magic == -1: + print("Magic not found", file=sys.stderr) + sys.exit(1) + print(s[:magic].rstrip(b'\x00').decode()) + s = s[magic + 8:] + for i in range(0, len(s), 8): + elem = int.from_bytes(s[i:i + 8], byteorder="little", signed=False) + depth = elem >> 56 + val = elem & 0xFFFFFFFFFFFFFF + display(depth, val) + + +if __name__ == "__main__": + main() diff --git a/optee/optee_os/scripts/gen_compile_commands.py b/optee/optee_os/scripts/gen_compile_commands.py new file mode 100755 index 0000000..1d2b49e --- /dev/null +++ b/optee/optee_os/scripts/gen_compile_commands.py @@ -0,0 +1,237 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (C) Google LLC, 2018 +# +# Author: Tom Roeder +# Ported and modified for U-Boot by Joao Marcos Costa +# Briefly documented at doc/build/gen_compile_commands.rst +# +# Ported and modified for OP-TEE by Joakim Bech +"""A tool for generating compile_commands.json in OP-TEE.""" + +import argparse +import json +import logging +import os +import re +import subprocess +import sys + +_DEFAULT_OUTPUT = 'compile_commands.json' +_DEFAULT_LOG_LEVEL = 'WARNING' + +_FILENAME_PATTERN = r'^\..*\.cmd$' +_LINE_PATTERN = r'^old-cmd[^ ]* := (?:/usr/bin/ccache )?(.*) -c (\S+)' + +_VALID_LOG_LEVELS = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'] +# The tools/ directory adopts a different build system, and produces .cmd +# files in a different format. Do not support it. +_EXCLUDE_DIRS = ['.git', 'Documentation', 'include', 'tools'] + + +def parse_arguments(): + """Sets up and parses command-line arguments. + + Returns: + log_level: A logging level to filter log output. + directory: The work directory where the objects were built. + ar: Command used for parsing .a archives. + output: Where to write the compile-commands JSON file. + paths: The list of files/directories to handle to find .cmd files. + """ + usage = 'Creates a compile_commands.json database from OP-TEE .cmd files' + parser = argparse.ArgumentParser(description=usage) + + directory_help = ('specify the output directory used for the OP-TEE build ' + '(defaults to the working directory)') + parser.add_argument('-d', '--directory', type=str, default='.', + help=directory_help) + + output_help = ('path to the output command database (defaults to ' + + _DEFAULT_OUTPUT + ')') + parser.add_argument('-o', '--output', type=str, default=_DEFAULT_OUTPUT, + help=output_help) + + log_level_help = ('the level of log messages to produce (defaults to ' + + _DEFAULT_LOG_LEVEL + ')') + parser.add_argument('--log_level', choices=_VALID_LOG_LEVELS, + default=_DEFAULT_LOG_LEVEL, help=log_level_help) + + ar_help = 'command used for parsing .a archives' + parser.add_argument('-a', '--ar', type=str, default='llvm-ar', + help=ar_help) + + paths_help = ('directories to search or files to parse ' + '(files should be *.o, *.a, or modules.order). ' + 'If nothing is specified, the current directory is searched') + parser.add_argument('paths', type=str, nargs='*', help=paths_help) + + args = parser.parse_args() + + return (args.log_level, + os.path.abspath(args.directory), + args.output, + args.ar, + args.paths if len(args.paths) > 0 else [args.directory]) + + +def cmdfiles_in_dir(directory): + """Generate the iterator of .cmd files found under the directory. + + Walk under the given directory, and yield every .cmd file found. + + Args: + directory: The directory to search for .cmd files. + + Yields: + The path to a .cmd file. + """ + + filename_matcher = re.compile(_FILENAME_PATTERN) + exclude_dirs = [os.path.join(directory, d) for d in _EXCLUDE_DIRS] + + for dirpath, dirnames, filenames in os.walk(directory, topdown=True): + # Prune unwanted directories. + if dirpath in exclude_dirs: + dirnames[:] = [] + continue + + for filename in filenames: + if filename_matcher.match(filename): + yield os.path.join(dirpath, filename) + + +def to_cmdfile(path): + """Return the path of .cmd file used for the given build artifact + + Args: + Path: file path + + Returns: + The path to .cmd file + """ + dir, base = os.path.split(path) + return os.path.join(dir, '.' + base + '.cmd') + + +def cmdfiles_for_a(archive, ar): + """Generate the iterator of .cmd files associated with the archive. + + Parse the given archive, and yield every .cmd file used to build it. + + Args: + archive: The archive to parse + + Yields: + The path to every .cmd file found + """ + for obj in subprocess.check_output([ar, '-t', archive]).decode().split(): + yield to_cmdfile(obj) + + +def cmdfiles_for_modorder(modorder): + """Generate the iterator of .cmd files associated with the modules.order. + + Parse the given modules.order, and yield every .cmd file used to build the + contained modules. + + Args: + modorder: The modules.order file to parse + + Yields: + The path to every .cmd file found + """ + with open(modorder) as f: + for line in f: + obj = line.rstrip() + base, ext = os.path.splitext(obj) + if ext != '.o': + sys.exit('{}: module path must end with .o'.format(obj)) + mod = base + '.mod' + # Read from *.mod, to get a list of objects that compose the + # module. + with open(mod) as m: + for mod_line in m: + yield to_cmdfile(mod_line.rstrip()) + + +def process_line(root_directory, command_prefix, file_path): + """Extracts information from a .cmd line and creates an entry from it. + + Args: + root_directory: The directory that was searched for .cmd files. Usually + used directly in the "directory" entry in compile_commands.json. + command_prefix: The extracted command line, up to the last element. + file_path: The .c file from the end of the extracted command. + Usually relative to root_directory, but sometimes absolute. + + Returns: + An entry to append to compile_commands. + + Raises: + ValueError: Could not find the extracted file based on file_path and + root_directory or file_directory. + """ + # The .cmd files are intended to be included directly by Make, so they + # escape the pound sign '#', either as '\#' or '$(pound)' (depending on the + # kernel version). The compile_commands.json file is not interpreted + # by Make, so this code replaces the escaped version with '#'. + prefix = command_prefix.replace('\#', '#').replace('$(pound)', '#') # noqa: W605 + + # Use os.path.abspath() to normalize the path resolving '.' and '..' . + abs_path = os.path.abspath(os.path.join(root_directory, file_path)) + if not os.path.exists(abs_path): + raise ValueError('File %s not found' % abs_path) + return { + 'directory': root_directory, + 'file': abs_path, + 'command': prefix + file_path, + } + + +def main(): + """Walks through the directory and finds and parses .cmd files.""" + log_level, directory, output, ar, paths = parse_arguments() + + level = getattr(logging, log_level) + logging.basicConfig(format='%(levelname)s: %(message)s', level=level) + + line_matcher = re.compile(_LINE_PATTERN) + + compile_commands = [] + + for path in paths: + # If 'path' is a directory, handle all .cmd files under it. + # Otherwise, handle .cmd files associated with the file. + # built-in objects are linked via vmlinux.a + # Modules are listed in modules.order. + if os.path.isdir(path): + cmdfiles = cmdfiles_in_dir(path) + elif path.endswith('.a'): + cmdfiles = cmdfiles_for_a(path, ar) + elif path.endswith('modules.order'): + cmdfiles = cmdfiles_for_modorder(path) + else: + sys.exit('{}: unknown file type'.format(path)) + + for cmdfile in cmdfiles: + with open(cmdfile, 'rt') as f: + try: + result = line_matcher.match(f.readline()) + if result: + entry = process_line(directory, result.group(1), + result.group(2)) + compile_commands.append(entry) + except ValueError as err: + logging.info('Could not add line from %s: %s', + cmdfile, err) + except AttributeError as err: + continue + + with open(output, 'wt') as f: + json.dump(compile_commands, f, indent=2, sort_keys=True) + + +if __name__ == '__main__': + main() 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/sign_rproc_fw.py b/optee/optee_os/scripts/sign_rproc_fw.py new file mode 100755 index 0000000..7bff20b --- /dev/null +++ b/optee/optee_os/scripts/sign_rproc_fw.py @@ -0,0 +1,508 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (C) 2023, STMicroelectronics +# + +try: + from elftools.elf.elffile import ELFFile + from elftools.elf.sections import SymbolTableSection + from elftools.elf.enums import ENUM_P_TYPE_ARM + from elftools.elf.enums import * +except ImportError: + print(""" +*** +ERROR: "pyelftools" python module is not installed or version < 0.25. +*** +""") + raise + +try: + from Cryptodome.Hash import SHA256 + from Cryptodome.Signature import pkcs1_15 + from Cryptodome.PublicKey import RSA + from Cryptodome.Signature import DSS + from Cryptodome.PublicKey import ECC +except ImportError: + print(""" + *** + ERROR: "pycryptodomex" python module should be installed. + *** + """) + raise + +import os +import sys +import struct +import logging +import binascii + +# Generated file structure: +# +# -----+-------------+ +# / | Magic | 32-bit word, magic value equal to +# / +-------------+ 0x3543A468 +# / +-------------+ +# / | version | 32-bit word, version of the format +# / +-------------+ +# +-----------+ +-------------+ +# | Header | | TLV size | 32-bit word, size of the TLV +# +-----------+ +-------------+ (aligned on 64-bit), in bytes. +# \ +-------------+ +# \ | sign size | 32-bit word, size of the signature +# \ +-------------+ (aligned on 64-bit), in bytes. +# \ +-------------+ +# \ | images size | 32-bit word, size of the images to +# -----+-------------+ load (aligned on 64-bit), in bytes. +# +# +-------------+ Information used to authenticate the +# | TLV | images and boot the remote processor, +# | | stored in Type-Length-Value format. +# +-------------+ 'Type' and 'Length' are 32-bit words. +# +# +-------------+ +# | Signature | Signature of the header and the TLV. +# +-------------+ +# +# +-------------+ +# | Firmware | +# | image 1 | +# +-------------+ +# ... +# +-------------+ +# | Firmware | +# | image n | +# +-------------+ + +# Generic type definitions +TLV_TYPES = { + 'SIGNTYPE': 0x00000001, # algorithm used for signature + 'HASHTYPE': 0x00000002, # algorithm used for computing segment's hash + 'NUM_IMG': 0x00000003, # number of images to load + 'IMGTYPE': 0x00000004, # array of type of images to load + 'IMGSIZE': 0x00000005, # array of the size of the images to load + 'HASHTABLE': 0x000000010, # segment hash table for authentication + 'PKEYINFO': 0x0000000011, # information to retrieve signature key +} + +GENERIC_TLV_TYPE_RANGE = range(0x00000000, 0x00010000) +PLATFORM_TLV_TYPE_RANGE = range(0x00010000, 0x00020000) + +HEADER_MAGIC = 0x3543A468 + +logging.basicConfig(stream=sys.stderr, level=logging.INFO) + +ENUM_HASH_TYPE = dict( + SHA256=1, +) + +ENUM_SIGNATURE_TYPE = dict( + RSA=1, + ECC=2, +) + +ENUM_BINARY_TYPE = dict( + ELF=1, +) + + +def dump_buffer(buf, step=16, name="", logger=logging.debug, indent=""): + logger("%s%s:" % (indent, name)) + for i in range(0, len(buf), step): + logger("%s " % (indent) + " ". + join(["%02X" % c for c in buf[i:i+step]])) + logger("\n") + + +class TLV(): + def __init__(self): + self.buf = bytearray() + self.tlvs = {} + + def add(self, kind, payload): + """ + Add a TLV record. Argument type is either the type scalar ID or a + matching string defined in TLV_TYPES. + """ + if isinstance(kind, int): + buf = struct.pack('II', kind, len(payload)) + else: + buf = struct.pack('II', TLV_TYPES[kind], len(payload)) + + # Ensure that each TLV is 64-bit aligned + align_64b = (len(payload) + len(buf)) % 8 + self.buf += buf + self.buf += payload + if align_64b: + self.buf += bytearray(8 - align_64b) + + def add_plat_tlv(self, cust_tlv): + # Get list of custom protected TLVs from the command-line + for tlv in cust_tlv: + type_id = int(tlv[0], 0) + + if type_id not in PLATFORM_TLV_TYPE_RANGE: + raise Exception('TLV %s not in range' % hex(type_id)) + + value = tlv[1] + if value.startswith('0x'): + int_val = int(value[2:], 16) + self.tlvs[type_id] = int_val.to_bytes(4, 'little') + else: + self.tlvs[type_id] = value.encode('utf-8') + + if self.tlvs is not None: + for type_id, value in self.tlvs.items(): + self.add(type_id, value) + + def get(self): + """ + Get a byte-array that concatenates all the TLV added. + """ + if len(self.buf) == 0: + return bytes() + return bytes(self.buf) + + +class RSA_Signature(object): + + def __init__(self, key): + self._hasher = SHA256.new() + self.signer = pkcs1_15.new(key) + + def hash_compute(self, segment): + self._hasher.update(segment) + + def sign(self): + return self.signer.sign(self._hasher) + + +class ECC_Signature(object): + + def __init__(self, key): + self._hasher = SHA256.new() + self.signer = DSS.new(key, 'fips-186-3') + + def hash_compute(self, segment): + self._hasher.update(segment) + + def sign(self): + return self.signer.sign(self._hasher) + + +Signature = { + 1: RSA_Signature, + 2: ECC_Signature, +} + + +class SegmentHashStruct: + pass + + +class SegmentHash(object): + ''' + Hash table based on Elf program segments + ''' + def __init__(self, img): + self._num_segments = img.num_segments() + self._pack_fmt = '<%dL' % 8 + self.img = img + self.hashProgTable = bytes() + self._offset = 0 + + def get_table(self): + ''' + Create a segment hash table containing for each segment: + - the segments header + - a hash of the segment + ''' + h = SHA256.new() + seg = SegmentHashStruct() + self.size = (h.digest_size + 32) * self._num_segments + logging.debug("hash section size %d" % self.size) + del h + self.buf = bytearray(self.size) + self._bufview_ = memoryview(self.buf) + + for i in range(self._num_segments): + h = SHA256.new() + segment = self.img.get_segment(i) + seg.header = self.img.get_segment(i).header + logging.debug("compute hash for segment offset %s" % seg.header) + h.update(segment.data()) + seg.hash = h.digest() + logging.debug("hash computed: %s" % seg.hash) + del h + struct.pack_into('0x[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]*) [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. 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-' + elif b'RISC-V,' in output[0]: + if b'32-bit' in output[0]: + self._arch = 'riscv32-unknown-linux-gnu-' + elif b'64-bit' in output[0]: + self._arch = 'riscv64-unknown-linux-gnu-' + + 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 + + def symbol_plus_offset(self, addr): + ret = '' + prevsize = 0 + 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) + if elf is None: + return '' + 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) + if elf is None: + return '' + 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..de0fa61 --- /dev/null +++ b/optee/optee_os/ta/arch/arm/ta.ld.S @@ -0,0 +1,103 @@ +#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 { + .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..f807675 --- /dev/null +++ b/optee/optee_os/ta/arch/riscv/ta.ld.S @@ -0,0 +1,96 @@ +/* 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 + +#define MCOUNT_SYM _mcount + +#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..207cf7c --- /dev/null +++ b/optee/optee_os/ta/avb/entry.c @@ -0,0 +1,401 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* Copyright (c) 2018, Linaro Limited */ + +#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..b00f220 --- /dev/null +++ b/optee/optee_os/ta/link.mk @@ -0,0 +1,124 @@ +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: FORCE + @$(cmd-echo-silent) ' GEN $@' + $(q)mkdir -p $(dir $@) + $(q)echo "{" >$@.tmp + $(q)echo "__elf_phdr_info;" >>$@.tmp +ifeq ($(CFG_FTRACE_SUPPORT),y) + $(q)echo "__ftrace_info;" >>$@.tmp +endif + $(q)echo "trace_ext_prefix;" >>$@.tmp + $(q)echo "trace_level;" >>$@.tmp + $(q)echo "ta_head;" >>$@.tmp + $(q)echo "};" >>$@.tmp + $(q)$(call mv-if-changed,$@.tmp,$@) +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[]; +}; + +#define PKCS11_CKA_VENDOR_DEFINED 0x80000000UL + +/** + * The PKCS11_CKF_ARRAY_ATTRIBUTE flag identifies an attribute which + * consists of an array of values. + */ +#define PKCS11_CKF_ARRAY_ATTRIBUTE 0x40000000UL + +/* + * OP-TEE's vendor specific PKCS#11 attribute allocation + * + * bit 31 - PKCS11_CKA_VENDOR_DEFINED + * bit 30 - PKCS11_CKF_ARRAY_ATTRIBUTE - works like in normal attributes + * bit 24-29 - reserved in case PKCS#11 standard starts to use them + * bit 16-23 - allocated for OP-TEE attribute flags + * bit 0-15 - allocated for attribute identifier + */ + +/* OP-TEE attribute flags */ + +/** + * Flags mask for checking if OP-TEE attribute flags are set. + */ +#define PKCS11_CKA_OPTEE_FLAGS_MASK (PKCS11_CKA_VENDOR_DEFINED | \ + 0x00FF0000UL) + +/** + * PKCS11_CKA_OPTEE_FLAGS_HIDDEN defines attribute that will not be exported + * from PKCS11 TA to its client. From client application point of view the + * attribute does not exist. + */ +#define PKCS11_CKA_OPTEE_FLAGS_HIDDEN (PKCS11_CKA_VENDOR_DEFINED | \ + 0x00010000UL) + +/* + * 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, + PKCS11_CKA_WRAP_TEMPLATE = PKCS11_CKF_ARRAY_ATTRIBUTE | + 0x0211, + PKCS11_CKA_UNWRAP_TEMPLATE = PKCS11_CKF_ARRAY_ATTRIBUTE | + 0x0212, + PKCS11_CKA_DERIVE_TEMPLATE = PKCS11_CKF_ARRAY_ATTRIBUTE | + 0x0213, + 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, + PKCS11_CKA_ALLOWED_MECHANISMS = PKCS11_CKF_ARRAY_ATTRIBUTE | + 0x0600, + + /* Vendor specific attributes */ + + /** + * TEE Internal API requires to have EC public key information + * available for private key operations. As EC private key object + * should not include CKA_EC_POINT include hidden one so that it does + * not need to be calculated on each operation. + */ + PKCS11_CKA_OPTEE_HIDDEN_EC_POINT = PKCS11_CKA_VENDOR_DEFINED | + PKCS11_CKA_OPTEE_FLAGS_HIDDEN | + 0x0000, + + /* 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_GCM = 0x01087, + 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..8f6071c --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/attributes.c @@ -0,0 +1,460 @@ +// 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 "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)); + + /* Hidden attributes cannot be matched */ + if (attribute_is_hidden(&pkcs11_ref)) + return false; + + 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..e9d0e1c --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/handle.c @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014-2020, Linaro Limited + */ + +#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 + +/* Specific pointer ~0 denotes a still allocated but invalid handle */ +#define INVALID_HANDLE_PTR ((void *)~0) + +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 || ptr == INVALID_HANDLE_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; +} + +static bool handle_is_valid(struct handle_db *db, uint32_t handle) +{ + return db && handle && handle < db->max_ptrs; +} + +void *handle_put(struct handle_db *db, uint32_t handle) +{ + void *p = NULL; + + if (!handle_is_valid(db, handle)) + return NULL; + + p = db->ptrs[handle]; + db->ptrs[handle] = NULL; + return p; +} + +void *handle_lookup(struct handle_db *db, uint32_t handle) +{ + if (!handle_is_valid(db, handle) || + db->ptrs[handle] == INVALID_HANDLE_PTR) + return NULL; + + return db->ptrs[handle]; +} + +void handle_invalidate(struct handle_db *db, uint32_t handle) +{ + if (handle_is_valid(db, handle)) { + if (!db->ptrs[handle]) + TEE_Panic(TEE_ERROR_GENERIC); + + db->ptrs[handle] = INVALID_HANDLE_PTR; + } +} + +uint32_t handle_lookup_handle(struct handle_db *db, void *ptr) +{ + uint32_t n = 0; + + if (ptr && ptr != INVALID_HANDLE_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..9ab9019 --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/handle.h @@ -0,0 +1,53 @@ +/* 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); + +/* Invalidate the reference referred by an allocated handle */ +void handle_invalidate(struct handle_db *db, uint32_t handle); + +#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..bbd2b68 --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/object.c @@ -0,0 +1,1285 @@ +// 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); + + token_invalidate_object_handles(obj); + } 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; + + /* Set key check value attribute */ + rc = set_check_value_attr(&head); + 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; + + /* Treat hidden attributes as missing attributes */ + if (attribute_is_hidden(&cli_head)) { + cli_head.size = PKCS11_CK_UNAVAILABLE_INFORMATION; + TEE_MemMove(&cli_ref->size, &cli_head.size, + sizeof(cli_head.size)); + attr_type_invalid = 1; + continue; + } + + /* 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; + struct obj_attrs *head_new = NULL; + struct obj_attrs *head_old = 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; + + /* Create new object attributes to modify */ + 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); + + /* + * 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(&head_new, head); + if (rc) + goto out; + + /* Set key check value attribute */ + rc = set_check_value_attr(&head_new); + if (rc) + goto out; + + /* Update the object */ + head_old = obj->attributes; + obj->attributes = head_new; + head_new = NULL; + + if (get_bool(obj->attributes, PKCS11_CKA_TOKEN)) { + rc = update_persistent_object_attributes(obj); + if (rc) { + obj->attributes = head_old; + goto out; + } + } + + TEE_Free(head_old); + + DMSG("PKCS11 session %"PRIu32": set attributes %#"PRIx32, + session->handle, object_handle); + +out: + TEE_Free(head); + TEE_Free(head_new); + 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; + + /* Set key check value attribute */ + rc = set_check_value_attr(&head_new); + 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..d0aa5f0 --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/pkcs11_attributes.c @@ -0,0 +1,3039 @@ +// 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_attributes.h" +#include "pkcs11_helpers.h" +#include "pkcs11_token.h" +#include "processing.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 __maybe_unused, + 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_START_DATE, + PKCS11_CKA_END_DATE, PKCS11_CKA_PUBLIC_KEY_INFO, +#ifdef CFG_PKCS11_TA_CHECK_VALUE_ATTRIBUTE + /* Consider KCV attribute only when supported */ + PKCS11_CKA_CHECK_VALUE, +#endif +}; + +/* + * 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, +#ifdef CFG_PKCS11_TA_CHECK_VALUE_ATTRIBUTE + /* Consider KCV attribute only when supported */ + PKCS11_CKA_CHECK_VALUE, +#endif +}; + +/* 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_pub_key_rsa_generated_attributes(struct obj_attrs **out, + struct obj_attrs *temp, + enum processing_func function) +{ + uint32_t key_bits = 0; + void *a_ptr = NULL; + uint32_t a_size = 0; + + if (function != PKCS11_FUNCTION_IMPORT) + return PKCS11_CKR_OK; + + /* Calculate CKA_MODULUS_BITS */ + + if (get_attribute_ptr(temp, PKCS11_CKA_MODULUS, + &a_ptr, &a_size) || !a_ptr) { + EMSG("No CKA_MODULUS attribute found in public key"); + return PKCS11_CKR_ATTRIBUTE_TYPE_INVALID; + } + + key_bits = a_size * 8; + + return add_attribute(out, PKCS11_CKA_MODULUS_BITS, &key_bits, + sizeof(key_bits)); +} + +static enum pkcs11_rc +create_pub_key_generated_attributes(struct obj_attrs **out, + struct obj_attrs *temp, + enum processing_func function) +{ + enum pkcs11_rc rc = PKCS11_CKR_OK; + + switch (get_key_type(*out)) { + case PKCS11_CKK_RSA: + rc = create_pub_key_rsa_generated_attributes(out, temp, + function); + break; + default: + /* no-op */ + break; + } + + return rc; +} + +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 int mbd_rand(void *rng_state __unused, unsigned char *output, size_t len) +{ + TEE_GenerateRandom(output, len); + return 0; +} + +static enum pkcs11_rc +create_ec_priv_key_hidden_attributes(struct obj_attrs **out, + struct obj_attrs *temp, + enum processing_func function) +{ + struct mbedtls_ecp_keypair key_pair = { }; + mbedtls_ecp_group_id ec_curve = MBEDTLS_ECP_DP_NONE; + mbedtls_ecp_group key_pair_grp = { }; + mbedtls_ecp_point key_pair_Q = { }; + mbedtls_mpi key_pair_d = { }; + size_t buflen = 0; + uint8_t *buf = NULL; + size_t asnbuflen = 0; + uint8_t *asnbuf = NULL; + uint8_t *ptr = NULL; + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + int tee_size = 0; + int tee_curve = 0; + void *a_ptr = NULL; + uint32_t a_size = 0; + int ret = 0; + + if (function != PKCS11_FUNCTION_IMPORT) + return PKCS11_CKR_OK; + + /* + * TEE internal API requires that for private key operations there + * needs to be also public key available. + * + * Generate hidden EC point from private key. + */ + + if (get_attribute_ptr(temp, PKCS11_CKA_EC_PARAMS, + &a_ptr, &a_size) || !a_ptr) { + EMSG("No EC_PARAMS attribute found in private key"); + return PKCS11_CKR_ATTRIBUTE_TYPE_INVALID; + } + + /* Just valdiate that curve is found */ + tee_size = ec_params2tee_keysize(a_ptr, a_size); + if (!tee_size) { + EMSG("Unsupported EC_PARAMS curve"); + return PKCS11_CKR_CURVE_NOT_SUPPORTED; + } + + tee_curve = ec_params2tee_curve(a_ptr, a_size); + + switch (tee_curve) { + case TEE_ECC_CURVE_NIST_P192: + ec_curve = MBEDTLS_ECP_DP_SECP192R1; + break; + case TEE_ECC_CURVE_NIST_P224: + ec_curve = MBEDTLS_ECP_DP_SECP224R1; + break; + case TEE_ECC_CURVE_NIST_P256: + ec_curve = MBEDTLS_ECP_DP_SECP256R1; + break; + case TEE_ECC_CURVE_NIST_P384: + ec_curve = MBEDTLS_ECP_DP_SECP384R1; + break; + case TEE_ECC_CURVE_NIST_P521: + ec_curve = MBEDTLS_ECP_DP_SECP521R1; + break; + default: + EMSG("Failed to map EC_PARAMS to supported curve"); + return PKCS11_CKR_CURVE_NOT_SUPPORTED; + } + + if (get_attribute_ptr(temp, PKCS11_CKA_VALUE, + &a_ptr, &a_size) || !a_ptr) { + EMSG("No VALUE attribute found in private key"); + return PKCS11_CKR_ATTRIBUTE_TYPE_INVALID; + } + + mbedtls_ecp_keypair_init(&key_pair); + mbedtls_ecp_group_init(&key_pair_grp); + mbedtls_mpi_init(&key_pair_d); + mbedtls_ecp_point_init(&key_pair_Q); + + ret = mbedtls_ecp_read_key(ec_curve, &key_pair, a_ptr, a_size); + if (ret) { + EMSG("Failed to parse CKA_VALUE"); + rc = PKCS11_CKR_ATTRIBUTE_TYPE_INVALID; + goto out; + } + + ret = mbedtls_ecp_export(&key_pair, &key_pair_grp, &key_pair_d, + &key_pair_Q); + if (ret) { + EMSG("Failed to export key"); + goto out; + } + + ret = mbedtls_ecp_mul(&key_pair_grp, &key_pair_Q, &key_pair_d, + &key_pair_grp.G, mbd_rand, NULL); + if (ret) { + EMSG("Failed to create public key"); + goto out; + } + + ret = mbedtls_ecp_check_privkey(&key_pair_grp, &key_pair_d); + if (ret) { + EMSG("Failed to verify private key"); + goto out; + } + + ret = mbedtls_ecp_check_pubkey(&key_pair_grp, &key_pair_Q); + if (ret) { + EMSG("Failed to verify public key"); + goto out; + } + + ret = mbedtls_ecp_point_write_binary(&key_pair_grp, &key_pair_Q, + MBEDTLS_ECP_PF_UNCOMPRESSED, + &buflen, NULL, 0); + if (ret != MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL) { + EMSG("Failed to determine size of binary public key"); + goto out; + } + + buf = TEE_Malloc(buflen, TEE_MALLOC_FILL_ZERO); + if (!buf) { + EMSG("Failed to allocate memory for public key"); + rc = PKCS11_CKR_DEVICE_MEMORY; + goto out; + } + + asnbuflen = 1 /* octet string */ + 5 /* length */ + buflen; + + asnbuf = TEE_Malloc(asnbuflen, TEE_MALLOC_FILL_ZERO); + if (!asnbuf) { + EMSG("Failed to allocate memory for public key"); + rc = PKCS11_CKR_DEVICE_MEMORY; + goto out; + } + + ret = mbedtls_ecp_point_write_binary(&key_pair_grp, &key_pair_Q, + MBEDTLS_ECP_PF_UNCOMPRESSED, + &buflen, buf, buflen); + if (ret) { + EMSG("Failed to write binary public key"); + goto out; + } + + /* Note: ASN.1 writing works backwards */ + ptr = asnbuf + asnbuflen; + + ret = mbedtls_asn1_write_octet_string(&ptr, asnbuf, buf, buflen); + if (ret < 0) { + EMSG("Failed to write asn1 public key"); + goto out; + } + + rc = add_attribute(out, PKCS11_CKA_OPTEE_HIDDEN_EC_POINT, ptr, + (size_t)ret); + +out: + TEE_Free(asnbuf); + TEE_Free(buf); + mbedtls_ecp_keypair_free(&key_pair); + mbedtls_ecp_group_free(&key_pair_grp); + mbedtls_mpi_free(&key_pair_d); + mbedtls_ecp_point_free(&key_pair_Q); + + return rc; +} + +static enum pkcs11_rc +create_priv_key_hidden_attributes(struct obj_attrs **out, + struct obj_attrs *temp, + enum processing_func function) +{ + enum pkcs11_rc rc = PKCS11_CKR_OK; + + switch (get_key_type(*out)) { + case PKCS11_CKK_EC: + rc = create_ec_priv_key_hidden_attributes(out, temp, function); + break; + default: + /* no-op */ + break; + } + + return rc; +} + +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); + if (rc) + goto out; + rc = create_pub_key_generated_attributes(&attrs, temp, + function); + break; + case PKCS11_CKO_PRIVATE_KEY: + rc = create_priv_key_attributes(&attrs, temp); + if (rc) + goto out; + rc = create_priv_key_hidden_attributes(&attrs, temp, function); + 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; + } + + 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 __maybe_unused) +{ + /* + * 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_GCM: + 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 (attribute_is_hidden(req_attr)) + return false; + + 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: + case PKCS11_CKA_CHECK_VALUE: + 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; + + /* Protect hidden attributes */ + if (attribute_is_hidden(&cli_ref)) + return PKCS11_CKR_ATTRIBUTE_TYPE_INVALID; + + /* + * 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; + + rc = add_attribute(head, PKCS11_CKA_VALUE, data, key_length); + if (rc) + return rc; + + return set_check_value_attr(head); +} + +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, mbd_rand, NULL); + if (mbedtls_rc) { + rc = PKCS11_CKR_ARGUMENTS_BAD; + goto out; + } + + rsa = mbedtls_pk_rsa(pk); + if (!rsa) { + rc = PKCS11_CKR_GENERAL_ERROR; + goto out; + } + + 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); + if (!rsa) { + rc = PKCS11_CKR_GENERAL_ERROR; + goto out; + } + + 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); +} + +/* + * The key check value is derived from the object by taking the first + * three bytes of the SHA-1 hash of the object's CKA_VALUE attribute. + */ +static enum pkcs11_rc compute_check_value_with_sha1(void *key, + uint32_t key_size, + void *kcv) +{ + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + TEE_Result res = TEE_ERROR_GENERIC; + TEE_OperationHandle op = TEE_HANDLE_NULL; + size_t buf_size = TEE_MAX_HASH_SIZE; + uint8_t *buf = NULL; + + assert(key && kcv); + + res = TEE_AllocateOperation(&op, TEE_ALG_SHA1, TEE_MODE_DIGEST, 0); + rc = tee2pkcs_error(res); + if (rc != PKCS11_CKR_OK) + goto out; + + buf = TEE_Malloc(buf_size, TEE_MALLOC_FILL_ZERO); + if (!buf) { + rc = PKCS11_CKR_DEVICE_MEMORY; + goto out; + } + + res = TEE_DigestDoFinal(op, key, key_size, buf, &buf_size); + rc = tee2pkcs_error(res); + if (rc != PKCS11_CKR_OK) + goto out; + + TEE_MemMove(kcv, buf, PKCS11_CKA_CHECK_VALUE_SIZE); + +out: + TEE_Free(buf); + TEE_FreeOperation(op); + + return rc; +} + +/* + * The key check value that is calculated as follows: + * 1) Take a buffer of the cipher block size of binary zeros (0x00). + * 2) Encrypt this block in ECB mode. + * 3) Take the first three bytes of cipher text as the check value. + */ +static enum pkcs11_rc compute_check_value_with_ecb(void *key, uint32_t key_size, + void *kcv) +{ + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + TEE_Result res = TEE_ERROR_GENERIC; + TEE_OperationHandle op = TEE_HANDLE_NULL; + TEE_ObjectHandle hkey = TEE_HANDLE_NULL; + TEE_Attribute attr = { }; + uint8_t buf[TEE_AES_BLOCK_SIZE] = { }; + size_t buf_size = sizeof(buf); + + assert(key && kcv); + + res = TEE_AllocateOperation(&op, TEE_ALG_AES_ECB_NOPAD, + TEE_MODE_ENCRYPT, key_size * 8); + rc = tee2pkcs_error(res); + if (rc != PKCS11_CKR_OK) + goto out; + + res = TEE_AllocateTransientObject(TEE_TYPE_AES, key_size * 8, &hkey); + rc = tee2pkcs_error(res); + if (rc != PKCS11_CKR_OK) + goto out; + + TEE_InitRefAttribute(&attr, TEE_ATTR_SECRET_VALUE, key, key_size); + + res = TEE_PopulateTransientObject(hkey, &attr, 1); + rc = tee2pkcs_error(res); + if (rc != PKCS11_CKR_OK) + goto out; + + res = TEE_SetOperationKey(op, hkey); + rc = tee2pkcs_error(res); + if (rc != PKCS11_CKR_OK) + goto out; + + TEE_CipherInit(op, NULL, 0); + + res = TEE_CipherDoFinal(op, buf, buf_size, buf, &buf_size); + rc = tee2pkcs_error(res); + if (rc != PKCS11_CKR_OK) + goto out; + + TEE_MemMove(kcv, buf, PKCS11_CKA_CHECK_VALUE_SIZE); + +out: + TEE_FreeTransientObject(hkey); + TEE_FreeOperation(op); + + return rc; +} + +enum pkcs11_rc set_check_value_attr(struct obj_attrs **head) +{ + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + uint32_t val_len = 0; + uint32_t kcv2_len = 0; + void *val = NULL; + uint8_t kcv[PKCS11_CKA_CHECK_VALUE_SIZE] = { }; + void *kcv2 = NULL; + + assert(head && *head); + + if (!IS_ENABLED(CFG_PKCS11_TA_CHECK_VALUE_ATTRIBUTE)) + return PKCS11_CKR_OK; + + switch (get_class(*head)) { + case PKCS11_CKO_SECRET_KEY: + case PKCS11_CKO_CERTIFICATE: + break; + default: + /* Nothing to do */ + return PKCS11_CKR_OK; + } + + /* Check whether CKA_CHECK_VALUE has been provided in the template */ + rc = get_attribute_ptr(*head, PKCS11_CKA_CHECK_VALUE, &kcv2, &kcv2_len); + + if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND) + return PKCS11_CKR_GENERAL_ERROR; + + /* + * The generation of the KCV may be prevented by the application + * supplying the attribute in the template as a no-value (0 length) + * entry. + */ + if (rc == PKCS11_CKR_OK && !kcv2_len) + return PKCS11_CKR_OK; + + if (rc == PKCS11_CKR_OK && kcv2_len != PKCS11_CKA_CHECK_VALUE_SIZE) + return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID; + + /* Get key CKA_VALUE */ + rc = get_attribute_ptr(*head, PKCS11_CKA_VALUE, &val, &val_len); + if (rc) + return rc; + + if (get_class(*head) == PKCS11_CKO_SECRET_KEY) { + switch (get_key_type(*head)) { + case PKCS11_CKK_AES: + rc = compute_check_value_with_ecb(val, val_len, kcv); + break; + case PKCS11_CKK_GENERIC_SECRET: + 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: + rc = compute_check_value_with_sha1(val, val_len, kcv); + break; + default: + rc = PKCS11_CKR_TEMPLATE_INCONSISTENT; + break; + } + } else { + rc = compute_check_value_with_sha1(val, val_len, kcv); + } + + if (rc) + return rc; + + /* + * If the computed KCV does not match the provided one + * then return CKR_ATTRIBUTE_VALUE_INVALID + */ + if (kcv2_len) { + /* Provided KCV value shall match the computed one */ + if (TEE_MemCompare(kcv2, kcv, PKCS11_CKA_CHECK_VALUE_SIZE)) + rc = PKCS11_CKR_ATTRIBUTE_VALUE_INVALID; + } else { + rc = add_attribute(head, PKCS11_CKA_CHECK_VALUE, kcv, + PKCS11_CKA_CHECK_VALUE_SIZE); + } + + return rc; +} 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..60cff66 --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/pkcs11_attributes.h @@ -0,0 +1,227 @@ +/* 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 + +#include "serializer.h" + +/* The key check value (KCV) attribute for objects is 3 bytes */ +#define PKCS11_CKA_CHECK_VALUE_SIZE U(3) + +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); + +static inline bool attribute_is_hidden(struct pkcs11_attribute_head *req_attr) +{ + return (req_attr->id & PKCS11_CKA_OPTEE_FLAGS_HIDDEN) == + PKCS11_CKA_OPTEE_FLAGS_HIDDEN; +} + +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); +/* + * Check an object's check value (Checksum) + * @head: Object attribute where to find KCV to be checked + * Return a pkcs11_rv compliant value + */ +enum pkcs11_rc set_check_value_attr(struct obj_attrs **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..364c7e6 --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/pkcs11_helpers.c @@ -0,0 +1,844 @@ +// 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_OPTEE_HIDDEN_EC_POINT, 0), + 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; + + /* + * For private keys we need EC public key for TEE operations so + * first try to get hidden EC POINT and as backwards + * compatibility also check for CKA_EC_POINT. + * + * For public keys we only have CKA_EC_POINT but there is no + * harm to check for hidden one too. + */ + if (get_attribute_ptr(obj->attributes, + PKCS11_CKA_OPTEE_HIDDEN_EC_POINT, + &a_ptr, &a_size)) { + if (get_attribute_ptr(obj->attributes, + PKCS11_CKA_EC_POINT, + &a_ptr, &a_size)) { + /* + * Without EC public key we cannot proceed. + */ + 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..23ecbc7 --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/pkcs11_token.c @@ -0,0 +1,1671 @@ +// 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); +} + +void token_invalidate_object_handles(struct pkcs11_object *obj) +{ + struct pkcs11_client *client = NULL; + uint32_t handle = 0; + + TAILQ_FOREACH(client, &pkcs11_client_list, link) { + handle = handle_lookup_handle(&client->object_handle_db, obj); + if (handle) + handle_invalidate(&client->object_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_op_handle2 = 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; + struct token_persistent_main *db = token->db_main; + enum pkcs11_rc rc = PKCS11_CKR_OK; + + assert(db->flags & PKCS11_CKFT_TOKEN_INITIALIZED); + + if (IS_ENABLED(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) && + db->flags & PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH) + return verify_identity_auth(token, PKCS11_CKU_SO); + + if (db->flags & PKCS11_CKFT_SO_PIN_LOCKED) + return PKCS11_CKR_PIN_LOCKED; + + /* + * Preset the counter and flags conservatively in the database so that + * the tentative is saved whatever happens next. + */ + db->flags |= PKCS11_CKFT_SO_PIN_COUNT_LOW; + db->so_pin_count++; + + if (db->so_pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX - 1) + db->flags |= PKCS11_CKFT_SO_PIN_FINAL_TRY; + else if (db->so_pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX) + db->flags |= PKCS11_CKFT_SO_PIN_LOCKED; + + update_persistent_db(token); + + rc = verify_pin(PKCS11_CKU_SO, pin, pin_size, + db->so_pin_salt, + db->so_pin_hash); + if (rc == PKCS11_CKR_PIN_INCORRECT) { + if (db->flags & PKCS11_CKFT_SO_PIN_LOCKED) + return PKCS11_CKR_PIN_LOCKED; + + return PKCS11_CKR_PIN_INCORRECT; + } + + if (rc) + db->so_pin_count--; + else + db->so_pin_count = 0; + + db->flags &= ~PKCS11_CKFT_SO_PIN_LOCKED; + if (db->so_pin_count < PKCS11_TOKEN_SO_PIN_COUNT_MAX - 1) { + db->flags &= ~PKCS11_CKFT_SO_PIN_FINAL_TRY; + if (!db->so_pin_count) + db->flags &= ~PKCS11_CKFT_SO_PIN_COUNT_LOW; + } + + update_persistent_db(token); + + return rc; +} + +static enum pkcs11_rc check_user_pin(struct pkcs11_session *session, + uint8_t *pin, size_t pin_size) +{ + struct ck_token *token = session->token; + struct token_persistent_main *db = token->db_main; + enum pkcs11_rc rc = PKCS11_CKR_OK; + + if (!(db->flags & PKCS11_CKFT_USER_PIN_INITIALIZED)) + return PKCS11_CKR_USER_PIN_NOT_INITIALIZED; + + if (IS_ENABLED(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) && + db->flags & PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH) + return verify_identity_auth(token, PKCS11_CKU_USER); + + assert(db->user_pin_salt); + + if (db->flags & PKCS11_CKFT_USER_PIN_LOCKED) + return PKCS11_CKR_PIN_LOCKED; + + /* + * Preset the counter and flags conservatively in the database so that + * the tentative is saved whatever happens next. + */ + db->flags |= PKCS11_CKFT_USER_PIN_COUNT_LOW; + db->user_pin_count++; + + if (db->user_pin_count == PKCS11_TOKEN_USER_PIN_COUNT_MAX - 1) + db->flags |= PKCS11_CKFT_USER_PIN_FINAL_TRY; + else if (db->user_pin_count == PKCS11_TOKEN_USER_PIN_COUNT_MAX) + db->flags |= PKCS11_CKFT_USER_PIN_LOCKED; + + update_persistent_db(token); + + rc = verify_pin(PKCS11_CKU_USER, pin, pin_size, + db->user_pin_salt, + db->user_pin_hash); + if (rc == PKCS11_CKR_PIN_INCORRECT) { + if (db->flags & PKCS11_CKFT_USER_PIN_LOCKED) + return PKCS11_CKR_PIN_LOCKED; + + return PKCS11_CKR_PIN_INCORRECT; + } + + if (rc) + db->user_pin_count--; + else + db->user_pin_count = 0; + + db->flags &= ~PKCS11_CKFT_USER_PIN_LOCKED; + if (db->user_pin_count < PKCS11_TOKEN_USER_PIN_COUNT_MAX - 1) { + db->flags &= ~PKCS11_CKFT_USER_PIN_FINAL_TRY; + if (!db->user_pin_count) + db->flags &= ~PKCS11_CKFT_USER_PIN_COUNT_LOW; + } + + update_persistent_db(token); + + return rc; +} + +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..42563e0 --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/pkcs11_token.h @@ -0,0 +1,355 @@ +/* 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_op_handle2 - second handle for specific operations or TEE_HANDLE_NULL + * @tee_hash_algo - hash algorithm identifier. + * @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; + TEE_OperationHandle tee_op_handle2; + uint32_t tee_hash_algo; + 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; +} + +/* Invalidate any handle referring the object since the object no more exists */ +void token_invalidate_object_handles(struct pkcs11_object *obj); + +/* 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..6ce078d --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/processing.c @@ -0,0 +1,1297 @@ +// 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; + + switch (session->processing->mecha_type) { + case PKCS11_CKM_AES_GCM: + tee_release_gcm_operation(session); + break; + default: + break; + } + + if (session->processing->tee_op_handle != TEE_HANDLE_NULL) { + TEE_FreeOperation(session->processing->tee_op_handle); + session->processing->tee_op_handle = TEE_HANDLE_NULL; + } + + if (session->processing->tee_op_handle2 != TEE_HANDLE_NULL) { + TEE_FreeOperation(session->processing->tee_op_handle2); + session->processing->tee_op_handle2 = 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; + uint32_t data_size = 0; + uint32_t value_len = 0; + void *value = NULL; + void *data = 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); + + if (rc == PKCS11_CKR_OK) + rc = set_check_value_attr(head); + + 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..5443266 --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/processing.h @@ -0,0 +1,286 @@ +/* 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(enum pkcs11_mechanism_id 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); + +enum pkcs11_rc tee_ae_decrypt_update(struct pkcs11_session *session, + void *in, size_t in_size); + +enum pkcs11_rc tee_ae_decrypt_final(struct pkcs11_session *session, + void *out, size_t *out_size); + +enum pkcs11_rc tee_ae_encrypt_final(struct pkcs11_session *session, + void *out, size_t *out_size); + +void tee_release_gcm_operation(struct pkcs11_session *session); + +enum pkcs11_rc tee_init_gcm_operation(struct pkcs11_session *session, + void *proc_params, size_t params_size); + +enum pkcs11_rc tee_ae_reinit_gcm_operation(struct pkcs11_session *session); + +/* 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..e795a54 --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/processing_aes.c @@ -0,0 +1,567 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2018-2020, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include + +#include "pkcs11_helpers.h" +#include "pkcs11_token.h" +#include "processing.h" +#include "serializer.h" + +/* + * Authenticated ciphering: (AES GCM) + * + * As per PKCS#11, GCM decryption shall not reveal the data until the + * decryption is completed and the MAC verified. The pkcs11 TA retains the + * ciphered data until the operation is completed. Therefore every chunk of + * decrypted data is saved in a allocated buffer during AE update processing + * and only copied into the client's output buffer at AE finalization when + * tag is authenticated. + * + * As per PKCS#11, GCM decryption expect the tag data to be provided + * inside the input data for C_DecryptUpdate() and friends, appended to the + * input encyprted data hence we do not know which is the last call to + * C_DecryptUpdate() where last bytes are not ciphered data but the requested + * tag bytes for message autehntication. To handle this, the TA saves + * the last input data bytes (length is defined by the tag byte size) in the + * AE context and waits the C_DecryptFinal() to either treat these as data + * bytes or tag/MAC bytes. Refer to pending_tag and pending_size in struct + * ae_aes_context. + */ + +/* + * struct out_data_ref - AE decyrption output data chunks + * @size - byte size of the allocated buffer + * @data - pointer to allocated data + */ +struct out_data_ref { + size_t size; + void *data; +}; + +/* + * struct ae_aes_context - Extra context data got AE operations + * @tag_byte_len - Tag size in byte + * @pending_tag - Input data that could be the appended tag + * @pending_size - Size of pending input data that could be the tag + * @out_data - Pointer to an array of output data references. + * @out_count - Number of buffer references in out_data + */ +struct ae_aes_context { + size_t tag_byte_len; + char *pending_tag; + size_t pending_size; + struct out_data_ref *out_data; + size_t out_count; +}; + +static enum pkcs11_rc init_ae_aes_context(struct ae_aes_context *ctx) +{ + struct out_data_ref *out_data = NULL; + char *pending_tag = NULL; + + assert(!ctx->out_data && !ctx->out_count && + !ctx->pending_tag && !ctx->pending_size); + + out_data = TEE_Malloc(sizeof(*out_data), TEE_MALLOC_FILL_ZERO); + pending_tag = TEE_Malloc(ctx->tag_byte_len, TEE_MALLOC_FILL_ZERO); + + if (!out_data || !pending_tag) { + TEE_Free(out_data); + TEE_Free(pending_tag); + return PKCS11_CKR_DEVICE_MEMORY; + } + + ctx->pending_tag = pending_tag; + ctx->out_data = out_data; + + return PKCS11_CKR_OK; +} + +static void release_ae_aes_context(struct ae_aes_context *ctx) +{ + size_t n = 0; + + for (n = 0; n < ctx->out_count; n++) + TEE_Free(ctx->out_data[n].data); + + TEE_Free(ctx->out_data); + ctx->out_data = NULL; + ctx->out_count = 0; + + TEE_Free(ctx->pending_tag); + ctx->pending_tag = NULL; + ctx->pending_size = 0; +} + +/* + * This function feeds the AE decryption processing with client + * input data. There are 2 constraints to consider. + * + * Firstly we don't know yet which are the ciphered data and which are + * the tag data. GP TEE Internal API function requires we split data and + * tag when TEE_AEDecryptFinal() will be called. + * + * Secondly any generated data must be kept in the TA and only revealed + * once tag if succefully processed. + */ +enum pkcs11_rc tee_ae_decrypt_update(struct pkcs11_session *session, + void *in, size_t in_size) +{ + struct ae_aes_context *ctx = session->processing->extra_ctx; + TEE_Result res = TEE_ERROR_GENERIC; + enum pkcs11_rc rc = PKCS11_CKR_OK; + size_t data_len = 0; + size_t ct_size = 0; + void *ptr = NULL; + char *ct = NULL; + + if (!in_size) + return PKCS11_CKR_OK; + + if (!in) + return PKCS11_CKR_ARGUMENTS_BAD; + + /* + * Save the last input bytes in case they are the tag + * bytes and not ciphered data bytes to be decrypted. + */ + + if (ctx->pending_size + in_size <= ctx->tag_byte_len) { + /* + * Data bytes are all potential tag bytes. + * We only need to update the pending_tag buffer, + * and cannot treat any byte as data byte. + */ + TEE_MemMove(ctx->pending_tag + ctx->pending_size, in, in_size); + + ctx->pending_size += in_size; + + return PKCS11_CKR_OK; + } + + /* Size of data that are not potential tag in pending and input data */ + data_len = in_size + ctx->pending_size - ctx->tag_byte_len; + + /* Process pending bytes that are effective data byte */ + if (ctx->pending_size && + (ctx->pending_size + in_size) >= ctx->tag_byte_len) { + uint32_t len = MIN(data_len, ctx->pending_size); + + res = TEE_AEUpdate(session->processing->tee_op_handle, + ctx->pending_tag, len, NULL, &ct_size); + if (res && res != TEE_ERROR_SHORT_BUFFER) { + rc = tee2pkcs_error(res); + goto out; + } + assert(res == TEE_ERROR_SHORT_BUFFER || !ct_size); + + /* + * If output data to store (not revealed yet), redo with + * an allocated temporary reference. + */ + if (ct_size) { + ct = TEE_Malloc(ct_size, TEE_MALLOC_FILL_ZERO); + if (!ct) { + rc = PKCS11_CKR_DEVICE_MEMORY; + goto out; + } + + res = TEE_AEUpdate(session->processing->tee_op_handle, + ctx->pending_tag, len, ct, &ct_size); + if (res) { + rc = tee2pkcs_error(res); + goto out; + } + assert(ct_size); + } + + /* Save potential tag bytes for later */ + TEE_MemMove(ctx->pending_tag, ctx->pending_tag + len, + ctx->pending_size - len); + + ctx->pending_size -= len; + data_len -= len; + } + + /* Process input data that are not potential tag bytes */ + if (data_len) { + size_t size = 0; + + res = TEE_AEUpdate(session->processing->tee_op_handle, + in, data_len, NULL, &size); + if (res != TEE_ERROR_SHORT_BUFFER && + (res != TEE_SUCCESS || size)) { + /* This is not expected */ + rc = PKCS11_CKR_GENERAL_ERROR; + goto out; + } + + if (size) { + ptr = TEE_Realloc(ct, ct_size + size); + if (!ptr) { + rc = PKCS11_CKR_DEVICE_MEMORY; + goto out; + } + ct = ptr; + + res = TEE_AEUpdate(session->processing->tee_op_handle, + in, data_len, ct + ct_size, &size); + if (res) { + rc = tee2pkcs_error(res); + goto out; + } + + ct_size += size; + } + } + + /* Update pending tag in context if any */ + data_len = in_size - data_len; + if (data_len > (ctx->tag_byte_len - ctx->pending_size)) { + /* This is not expected */ + rc = PKCS11_CKR_GENERAL_ERROR; + goto out; + } + + if (data_len) { + TEE_MemMove(ctx->pending_tag + ctx->pending_size, + (char *)in + in_size - data_len, data_len); + + ctx->pending_size += data_len; + } + + /* Save output data reference in the context */ + if (ct_size) { + ptr = TEE_Realloc(ctx->out_data, (ctx->out_count + 1) * + sizeof(struct out_data_ref)); + if (!ptr) { + rc = PKCS11_CKR_DEVICE_MEMORY; + goto out; + } + ctx->out_data = ptr; + ctx->out_data[ctx->out_count].size = ct_size; + ctx->out_data[ctx->out_count].data = ct; + ctx->out_count++; + } + + rc = PKCS11_CKR_OK; + +out: + if (rc) + TEE_Free(ct); + + return rc; +} + +static enum pkcs11_rc reveal_ae_data(struct ae_aes_context *ctx, + void *out, size_t *out_size) +{ + uint32_t req_size = 0; + char *out_ptr = out; + size_t n = 0; + + for (req_size = 0, n = 0; n < ctx->out_count; n++) + req_size += ctx->out_data[n].size; + + if (*out_size < req_size) { + *out_size = req_size; + return PKCS11_CKR_BUFFER_TOO_SMALL; + } + + if (!out_ptr) + return PKCS11_CKR_ARGUMENTS_BAD; + + for (n = 0; n < ctx->out_count; n++) { + TEE_MemMove(out_ptr, ctx->out_data[n].data, + ctx->out_data[n].size); + out_ptr += ctx->out_data[n].size; + } + + release_ae_aes_context(ctx); + + *out_size = req_size; + + return PKCS11_CKR_OK; +} + +enum pkcs11_rc tee_ae_decrypt_final(struct pkcs11_session *session, + void *out, size_t *out_size) +{ + struct ae_aes_context *ctx = session->processing->extra_ctx; + TEE_Result res = TEE_ERROR_GENERIC; + enum pkcs11_rc rc = 0; + void *data_ptr = NULL; + size_t data_size = 0; + + if (!out_size) { + DMSG("Expect at least a buffer for the output data"); + return PKCS11_CKR_ARGUMENTS_BAD; + } + + /* Final is already completed, only need to output the data */ + if (!ctx->pending_tag) + return reveal_ae_data(ctx, out, out_size); + + if (ctx->pending_size != ctx->tag_byte_len) { + DMSG("Not enough samples: %zu/%zu", + ctx->pending_size, ctx->tag_byte_len); + return PKCS11_CKR_ENCRYPTED_DATA_LEN_RANGE; + } + + /* Query tag size if any */ + data_size = 0; + res = TEE_AEDecryptFinal(session->processing->tee_op_handle, + NULL, 0, NULL, &data_size, + ctx->pending_tag, ctx->tag_byte_len); + + if (res == TEE_ERROR_SHORT_BUFFER) { + data_ptr = TEE_Malloc(data_size, TEE_MALLOC_FILL_ZERO); + if (!data_ptr) { + rc = PKCS11_CKR_DEVICE_MEMORY; + goto out; + } + + res = TEE_AEDecryptFinal(session->processing->tee_op_handle, + NULL, 0, data_ptr, &data_size, + ctx->pending_tag, ctx->tag_byte_len); + assert(res || data_size); + } + + /* AE decryption is completed */ + TEE_Free(ctx->pending_tag); + ctx->pending_tag = NULL; + + rc = tee2pkcs_error(res); + if (rc) + goto out; + + if (data_ptr) { + void *tmp_ptr = NULL; + + tmp_ptr = TEE_Realloc(ctx->out_data, (ctx->out_count + 1) * + sizeof(struct out_data_ref)); + if (!tmp_ptr) { + rc = PKCS11_CKR_DEVICE_MEMORY; + goto out; + } + ctx->out_data = tmp_ptr; + ctx->out_data[ctx->out_count].size = data_size; + ctx->out_data[ctx->out_count].data = data_ptr; + ctx->out_count++; + + data_ptr = NULL; + } + + rc = reveal_ae_data(ctx, out, out_size); + +out: + TEE_Free(data_ptr); + + return rc; +} + +enum pkcs11_rc tee_ae_encrypt_final(struct pkcs11_session *session, + void *out, size_t *out_size) +{ + struct ae_aes_context *ctx = session->processing->extra_ctx; + TEE_Result res = TEE_ERROR_GENERIC; + uint8_t *tag = NULL; + size_t tag_len = 0; + size_t size = 0; + + if (!out || !out_size) + return PKCS11_CKR_ARGUMENTS_BAD; + + /* Check the required sizes (warning: 2 output len: data + tag) */ + res = TEE_AEEncryptFinal(session->processing->tee_op_handle, + NULL, 0, NULL, &size, + &tag, &tag_len); + + if (tag_len != ctx->tag_byte_len || + (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER)) { + EMSG("Unexpected tag length %zu/%zu or rc 0x%" PRIx32, + tag_len, ctx->tag_byte_len, res); + return PKCS11_CKR_GENERAL_ERROR; + } + + if (*out_size < size + tag_len) { + *out_size = size + tag_len; + return PKCS11_CKR_BUFFER_TOO_SMALL; + } + + /* Process data and tag input the client output buffer */ + tag = (uint8_t *)out + size; + + res = TEE_AEEncryptFinal(session->processing->tee_op_handle, + NULL, 0, out, &size, tag, &tag_len); + + if (tag_len != ctx->tag_byte_len) { + EMSG("Unexpected tag length"); + return PKCS11_CKR_GENERAL_ERROR; + } + + if (!res) + *out_size = size + tag_len; + + return tee2pkcs_error(res); +} + +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; +} + +enum pkcs11_rc tee_init_gcm_operation(struct pkcs11_session *session, + void *proc_params, size_t params_size) +{ + struct ae_aes_context *params = NULL; + enum pkcs11_rc rc = PKCS11_CKR_OK; + struct serialargs args = { }; + /* GCM parameters */ + uint32_t tag_bitlen = 0; + uint32_t tag_len = 0; + uint32_t iv_len = 0; + void *iv = NULL; + uint32_t aad_len = 0; + void *aad = NULL; + + TEE_MemFill(&args, 0, sizeof(args)); + + if (!proc_params) + return PKCS11_CKR_ARGUMENTS_BAD; + + serialargs_init(&args, proc_params, params_size); + + rc = serialargs_get(&args, &iv_len, sizeof(uint32_t)); + if (rc) + goto out; + + rc = serialargs_get_ptr(&args, &iv, iv_len); + if (rc) + goto out; + + rc = serialargs_get(&args, &aad_len, sizeof(uint32_t)); + if (rc) + goto out; + + rc = serialargs_get_ptr(&args, &aad, aad_len); + if (rc) + goto out; + + rc = serialargs_get(&args, &tag_bitlen, sizeof(uint32_t)); + if (rc) + goto out; + + tag_len = ROUNDUP(tag_bitlen, 8) / 8; + + /* As per pkcs#11 mechanism specification */ + if (tag_bitlen > 128 || !iv_len || iv_len > 256) { + DMSG("Invalid parameters: tag_bit_len %"PRIu32 + ", iv_len %"PRIu32, tag_bitlen, iv_len); + rc = PKCS11_CKR_MECHANISM_PARAM_INVALID; + goto out; + } + + params = TEE_Malloc(sizeof(*params), TEE_MALLOC_FILL_ZERO); + if (!params) { + rc = PKCS11_CKR_DEVICE_MEMORY; + goto out; + } + + /* Store the byte round up byte length for the tag */ + params->tag_byte_len = tag_len; + rc = init_ae_aes_context(params); + if (rc) + goto out; + + /* Session processing owns the active processing params */ + assert(!session->processing->extra_ctx); + session->processing->extra_ctx = params; + + TEE_AEInit(session->processing->tee_op_handle, + iv, iv_len, tag_bitlen, 0, 0); + + if (aad_len) + TEE_AEUpdateAAD(session->processing->tee_op_handle, + aad, aad_len); + + /* + * Save initialized operation state to reset to this state + * on one-shot AE request that queries its output buffer size. + */ + TEE_CopyOperation(session->processing->tee_op_handle2, + session->processing->tee_op_handle); + + rc = PKCS11_CKR_OK; + +out: + if (rc && params) { + release_ae_aes_context(params); + TEE_Free(params); + } + + return rc; +} + +/* Release extra resources related to the GCM processing*/ +void tee_release_gcm_operation(struct pkcs11_session *session) +{ + struct ae_aes_context *ctx = session->processing->extra_ctx; + + release_ae_aes_context(ctx); + TEE_Free(session->processing->extra_ctx); + session->processing->extra_ctx = NULL; +} + +/* Reset processing state to the state it was after initialization */ +enum pkcs11_rc tee_ae_reinit_gcm_operation(struct pkcs11_session *session) +{ + struct ae_aes_context *ctx = session->processing->extra_ctx; + + TEE_CopyOperation(session->processing->tee_op_handle, + session->processing->tee_op_handle2); + + release_ae_aes_context(ctx); + + return init_ae_aes_context(ctx); +} 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..786c544 --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/processing_asymm.c @@ -0,0 +1,1110 @@ +// 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_op_handle2 == 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_op_handle2, + 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_op_handle2 != TEE_HANDLE_NULL) { + TEE_FreeOperation(session->processing->tee_op_handle2); + processing->tee_op_handle2 = 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_op_handle2 != TEE_HANDLE_NULL); + + TEE_DigestUpdate(proc->tee_op_handle2, 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_op_handle2 != 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_op_handle2, 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..adf9b5e --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/processing_ec.c @@ -0,0 +1,965 @@ +// 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++; + + /* + * Standard does not have CKA_EC_POINT for EC private keys + * but that is required by TEE internal API. First try to get + * hidden EC POINT and for backwards compatibility then try to + * get CKA_EC_POINT value. + */ + + if (pkcs2tee_load_attr(&attrs[count], + TEE_ATTR_ECC_PUBLIC_VALUE_X, + obj, PKCS11_CKA_OPTEE_HIDDEN_EC_POINT)) + count++; + else 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_OPTEE_HIDDEN_EC_POINT)) + count++; + else 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 PKCS11_CKA_OPTEE_HIDDEN_EC_POINT to private key object and + * standard PKCS11_CKA_EC_POINT to public key objects as + * TEE_PopulateTransientObject requires public x/y values + * for TEE_TYPE_ECDSA_KEYPAIR. + */ + rc = add_attribute(priv_head, PKCS11_CKA_OPTEE_HIDDEN_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..093c61d --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/processing_symm.c @@ -0,0 +1,1243 @@ +// 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_GCM: + 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_GCM, TEE_ALG_AES_GCM }, + { 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 && + session->processing->tee_op_handle2 == 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; + + if (res == TEE_SUCCESS || params->id == PKCS11_CKM_AES_GCM) { + /* + * Allocate a 2nd operation handler to save the operation state + * on AES GCM one-shot processing that queries the output + * buffer size. This is needed as we will need to reset and + * re-init the TEE operation once we report the expected output + * buffer size to client that we call again the AE processing + * function. + */ + TEE_OperationHandle *hdl = &session->processing->tee_op_handle2; + + res = TEE_AllocateOperation(hdl, algo, mode, size); + } + + 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_GCM: + rc = tee_init_gcm_operation(session, + 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; + size_t ae_out_size = 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; + ae_out_size = out_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; + case PKCS11_CKM_AES_GCM: + if (step == PKCS11_FUNC_STEP_FINAL) + break; + + switch (function) { + case PKCS11_FUNCTION_ENCRYPT: + res = TEE_AEUpdate(proc->tee_op_handle, + in_buf, in_size, out_buf, &out_size); + + output_data = true; + rc = tee2pkcs_error(res); + if (rc && rc != PKCS11_CKR_BUFFER_TOO_SMALL) + return rc; + if (step == PKCS11_FUNC_STEP_ONESHOT) { + if (rc == PKCS11_CKR_BUFFER_TOO_SMALL) { + /* Return output data size incl. tag*/ + out_size += 16; + goto out; + } + out_buf = (char *)out_buf + out_size; + /* Remaining space for the tag data */ + ae_out_size -= out_size; + } + break; + case PKCS11_FUNCTION_DECRYPT: + rc = tee_ae_decrypt_update(session, in_buf, in_size); + assert(rc != PKCS11_CKR_BUFFER_TOO_SMALL); + if (rc) + return rc; + /* Do not output decrypted data until tag is verified */ + out_size = 0; + output_data = true; + 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 (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: + 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(proc->extra_ctx); + hmac_len = *(uint32_t *)proc->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; + case PKCS11_CKM_AES_GCM: + switch (function) { + case PKCS11_FUNCTION_ENCRYPT: + rc = tee_ae_encrypt_final(session, out_buf, + &ae_out_size); + output_data = true; + if (step == PKCS11_FUNC_STEP_ONESHOT) + out_size += ae_out_size; + else + out_size = ae_out_size; + break; + case PKCS11_FUNCTION_DECRYPT: + /* Now we're ready to reveal data */ + out_size = ae_out_size; + rc = tee_ae_decrypt_final(session, out_buf, &out_size); + output_data = true; + break; + default: + TEE_Panic(function); + break; + } + + if (step == PKCS11_FUNC_STEP_ONESHOT && + rc == PKCS11_CKR_BUFFER_TOO_SMALL) { + enum pkcs11_rc rc2 = PKCS11_CKR_OK; + + /* + * Change operation state to its initial state + * as client will likely request again the + * one-shot processing but possibly with + * different input data. + */ + rc2 = tee_ae_reinit_gcm_operation(session); + if (rc2) + return rc2; + } + 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..1328332 --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/sanitize_object.c @@ -0,0 +1,430 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017-2020, Linaro Limited + */ + +#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..b6cc0ed --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/token_capabilities.c @@ -0,0 +1,465 @@ +// 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_GCM, 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_GCM, 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_GCM: + 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..aa66ee0 --- /dev/null +++ b/optee/optee_os/ta/pkcs11/sub.mk @@ -0,0 +1,18 @@ +# 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 + +# When enabled, embed support for object checksum value computation +CFG_PKCS11_TA_CHECK_VALUE_ATTRIBUTE ?= y + +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/remoteproc/Makefile b/optee/optee_os/ta/remoteproc/Makefile new file mode 100644 index 0000000..0d1a501 --- /dev/null +++ b/optee/optee_os/ta/remoteproc/Makefile @@ -0,0 +1,18 @@ +# The UUID for the Trusted Application +BINARY=80a4c275-0a47-4905-8285-1486a9771a08 + +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/remoteproc/include/ta_remoteproc.h b/optee/optee_os/ta/remoteproc/include/ta_remoteproc.h new file mode 100644 index 0000000..71a1545 --- /dev/null +++ b/optee/optee_os/ta/remoteproc/include/ta_remoteproc.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2023, STMicroelectronics + */ + +#ifndef TA_REMOTEPROC_H +#define TA_REMOTEPROC_H + +/* + * This UUID is generated with uuidgen + * the ITU-T UUID generator at http://www.itu.int/ITU-T/asn1/uuid.html + */ +#define TA_REMOTEPROC_UUID { 0x80a4c275, 0x0a47, 0x4905, \ + { 0x82, 0x85, 0x14, 0x86, 0xa9, 0x77, 0x1a, 0x08} } + +/* The command IDs implemented in this TA */ + +/* + * Authentication of the firmware and load in the remote processor memory. + * + * [in] params[0].value.a: Unique 32bit remote processor identifier + * [in] params[1].memref: buffer containing the image of the firmware + */ +#define TA_RPROC_CMD_LOAD_FW 1 + +/* + * Start the remote processor. + * + * [in] params[0].value.a: Unique 32bit remote processor identifier + */ +#define TA_RPROC_CMD_START_FW 2 + +/* + * Stop the remote processor. + * + * [in] params[0].value.a: Unique 32bit remote processor identifier + */ +#define TA_RPROC_CMD_STOP_FW 3 + +/* + * Return the physical address of the resource table, or 0 if not found + * No check is done to verify that the address returned is accessible by the + * non-secure world. If the resource table is loaded in a protected memory, + * then accesses from non-secure world will likely fail. + * + * [in] params[0].value.a: Unique 32bit remote processor identifier + * [out] params[1].value.a: 32bit LSB resource table memory address + * [out] params[1].value.b: 32bit MSB resource table memory address + * [out] params[2].value.a: 32bit LSB resource table memory size + * [out] params[2].value.b: 32bit MSB resource table memory size + */ +#define TA_RPROC_CMD_GET_RSC_TABLE 4 + +/* + * Get remote processor firmware core dump. If found, return either + * TEE_SUCCESS on successful completion or TEE_ERROR_SHORT_BUFFER if output + * buffer is too short to store the core dump. + * + * [in] params[0].value.a: Unique 32bit remote processor identifier + * [out] params[1].memref: Core dump, if found + */ +#define TA_RPROC_CMD_GET_COREDUMP 5 + +#endif /*TA_REMOTEPROC_H*/ diff --git a/optee/optee_os/ta/remoteproc/src/elf_parser.c b/optee/optee_os/ta/remoteproc/src/elf_parser.c new file mode 100644 index 0000000..0cd0bc6 --- /dev/null +++ b/optee/optee_os/ta/remoteproc/src/elf_parser.c @@ -0,0 +1,175 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2023, STMicroelectronics + */ + +#include +#include +#include +#include +#include +#include + +static bool va_in_fwm_image_range(void *va, uint8_t *fw, size_t fw_size) +{ + uint8_t *vaddr = va; + + return vaddr >= fw && vaddr < fw + fw_size; +} + +TEE_Result e32_parse_ehdr(uint8_t *fw, size_t size) +{ + Elf32_Ehdr *ehdr = (Elf32_Ehdr *)(void *)fw; + + if (!fw || !IS_ALIGNED_WITH_TYPE(fw, uint32_t)) { + EMSG("Invalid firmware address"); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (size < sizeof(Elf32_Ehdr) || + size < (ehdr->e_shoff + sizeof(Elf32_Shdr))) + return TEE_ERROR_BAD_FORMAT; + + if (!IS_ELF(*ehdr) || + ehdr->e_ident[EI_VERSION] != EV_CURRENT || + ehdr->e_ident[EI_CLASS] != ELFCLASS32 || + ehdr->e_phentsize != sizeof(Elf32_Phdr) || + ehdr->e_shentsize != sizeof(Elf32_Shdr)) { + EMSG("Invalid header"); + return TEE_ERROR_BAD_FORMAT; + } + + if (ehdr->e_phnum == 0) { + EMSG("No loadable segment found"); + return TEE_ERROR_BAD_FORMAT; + } + + return TEE_SUCCESS; +} + +TEE_Result e32_parser_load_elf_image(uint8_t *fw, size_t fw_size, + TEE_Result (*load_seg)(uint8_t *src, + uint32_t size, + uint32_t da, + uint32_t mem_size, + void *priv), + void *priv_data) +{ + Elf32_Ehdr *ehdr = (Elf32_Ehdr *)(void *)fw; + Elf32_Phdr *phdr = (void *)((int8_t *)ehdr + ehdr->e_phoff); + TEE_Result res = TEE_SUCCESS; + unsigned int i = 0; + + if (!load_seg || fw + fw_size <= fw) + return TEE_ERROR_BAD_PARAMETERS; + + if (!IS_ALIGNED_WITH_TYPE(phdr, uint32_t) || + !va_in_fwm_image_range(phdr, fw, fw_size)) + return TEE_ERROR_BAD_FORMAT; + + for (i = 0; i < ehdr->e_phnum; i++, phdr++) { + uint32_t dst = phdr->p_paddr; + uint8_t *src = NULL; + + if (phdr->p_type != PT_LOAD) + continue; + + if (!va_in_fwm_image_range((void *)((vaddr_t)(phdr + 1) - 1), + fw, fw_size)) + return TEE_ERROR_BAD_FORMAT; + + src = (uint8_t *)fw + phdr->p_offset; + + if (!va_in_fwm_image_range(src, fw, fw_size) || + !va_in_fwm_image_range(src + phdr->p_filesz, fw, fw_size)) + return TEE_ERROR_BAD_FORMAT; + + res = load_seg(src, phdr->p_filesz, dst, phdr->p_memsz, + priv_data); + if (res) + return res; + } + + return TEE_SUCCESS; +} + +TEE_Result e32_parser_find_rsc_table(uint8_t *fw, size_t fw_size, + Elf32_Addr *rsc_addr, + Elf32_Word *rsc_size) +{ + Elf32_Shdr *shdr = NULL; + unsigned int i = 0; + char *name_table = NULL; + struct resource_table *table = NULL; + Elf32_Ehdr *ehdr = (Elf32_Ehdr *)(void *)fw; + uint8_t *elf_data = fw; + + if (fw + fw_size <= fw || fw + ehdr->e_shoff < fw) + return TEE_ERROR_BAD_PARAMETERS; + + shdr = (void *)(fw + ehdr->e_shoff); + if (!IS_ALIGNED_WITH_TYPE(shdr, uint32_t) || + !va_in_fwm_image_range(shdr, fw, fw_size)) + return TEE_ERROR_BAD_FORMAT; + + name_table = (char *)elf_data + shdr[ehdr->e_shstrndx].sh_offset; + if (!va_in_fwm_image_range(name_table, fw, fw_size)) + return TEE_ERROR_BAD_FORMAT; + + for (i = 0; i < ehdr->e_shnum; i++, shdr++) { + size_t size = shdr->sh_size; + size_t offset = shdr->sh_offset; + size_t s = 0; + + if (!va_in_fwm_image_range(shdr, fw, fw_size)) + return TEE_ERROR_BAD_FORMAT; + + if (strcmp(name_table + shdr->sh_name, ".resource_table")) + continue; + + if (!shdr->sh_size) + return TEE_ERROR_NO_DATA; + + if (offset + size > fw_size || offset + size < size) { + EMSG("Resource table truncated"); + return TEE_ERROR_BAD_FORMAT; + } + + if (sizeof(struct resource_table) > size) { + EMSG("No header found in resource table"); + return TEE_ERROR_BAD_FORMAT; + } + + table = (struct resource_table *)(void *)(elf_data + offset); + if (!IS_ALIGNED_WITH_TYPE(table, uint32_t)) + return TEE_ERROR_CORRUPT_OBJECT; + + if (table->ver != 1) { + EMSG("Unsupported firmware version %"PRId32, + table->ver); + return TEE_ERROR_BAD_FORMAT; + } + + if (table->reserved[0] || table->reserved[1]) { + EMSG("Non zero reserved bytes"); + return TEE_ERROR_BAD_FORMAT; + } + + if (MUL_OVERFLOW(table->num, sizeof(*table->offset), &s) || + ADD_OVERFLOW(s, sizeof(struct resource_table), &s) || + s > size) { + EMSG("Resource table incomplete"); + return TEE_ERROR_BAD_FORMAT; + } + + DMSG("Resource table address %#"PRIx32", size %"PRIu32, + shdr->sh_addr, shdr->sh_size); + + *rsc_addr = shdr->sh_addr; + *rsc_size = shdr->sh_size; + + return TEE_SUCCESS; + } + + return TEE_ERROR_NO_DATA; +} diff --git a/optee/optee_os/ta/remoteproc/src/elf_parser.h b/optee/optee_os/ta/remoteproc/src/elf_parser.h new file mode 100644 index 0000000..1bd658f --- /dev/null +++ b/optee/optee_os/ta/remoteproc/src/elf_parser.h @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2023, STMicroelectronics + */ + +#ifndef ELF_PARSER_H +#define ELF_PARSER_H + +#include +#include +#include + +/** + * struct resource_table - firmware resource table header + * @ver: version number + * @num: number of resource entries + * @reserved: reserved (must be zero) + * @offset: array of offsets pointing at the various resource entries + * + * A resource table is essentially a list of system resources required + * by the remote processor. It may also include configuration entries. + * If needed, the remote processor firmware should contain this table + * as a dedicated ".resource_table" ELF section. + * + * This structure shall be consistent with the Linux kernel structure + * definition from include/linux/remoteproc.h. + * + * The resource_table structure does not need to be packed in OP-TEE. The ELF + * parser does not access the system resources structures that follow this + * structure in shared memory (no memory alignment constraint on structures). + */ +struct resource_table { + uint32_t ver; + uint32_t num; + uint32_t reserved[2]; + uint32_t offset[]; +}; + +struct fw_elf32 { + uintptr_t e_entry; + uintptr_t e_phoff; + uintptr_t e_shoff; + uint32_t e_phnum; + uint32_t e_shnum; + uint32_t e_phentsize; + uint32_t e_shentsize; + + Elf32_Phdr *phdr; + Elf32_Shdr *shdr; +}; + +/* + * e32_parse_ehdr() - Check and parse the ELF header + * + * @fw: Firmware ELF file image + * @size: Byte size of firmware ELF file image + * Return TEE_SUCCESS or appropriate error. + */ +TEE_Result e32_parse_ehdr(uint8_t *fw, size_t size); + +/* + * e32_parser_load_elf_image() - simple ELF loader + * @fw: Firmware ELF file image + * @fw_size: Firmware ELF file image byte size + * @load_seg: Callback for loading a firmware image segment into device memory + * @priv_data: Private data passed to @load_seg callback. + * Return TEE_SUCCESS or appropriate error. + */ +TEE_Result e32_parser_load_elf_image(uint8_t *fw, size_t fw_size, + TEE_Result (*load_seg)(uint8_t *src, + uint32_t size, + uint32_t da, + uint32_t mem_size, + void *priv), + void *priv_data); + +/* + * e32_parser_find_rsc_table() - find resource table in an ELF image + * @fw: Firmware ELF file image + * @fw_size: Firmware ELF file image byte size + * @rsc_addr: Output resource table address from the remote proc perspective + * @rsc_size: Output resource table size + * Return TEE_SUCCESS if found, + * TEE_ERROR_NO_DATA if not found, + * or appropriate error. + */ +TEE_Result e32_parser_find_rsc_table(uint8_t *fw, size_t fw_size, + Elf32_Addr *rsc_addr, + Elf32_Word *rsc_size); + +#endif /*ELF_PARSER_H*/ diff --git a/optee/optee_os/ta/remoteproc/src/remoteproc_core.c b/optee/optee_os/ta/remoteproc/src/remoteproc_core.c new file mode 100644 index 0000000..6a112d9 --- /dev/null +++ b/optee/optee_os/ta/remoteproc/src/remoteproc_core.c @@ -0,0 +1,1107 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2023, STMicroelectronics + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * The remoteproc Trusted Application is in charge of authenticating and loading + * images signed by the scripts/sign_rproc_fw.py. The TA is also in charge of + * starting and stopping the remote processor. + * The structure of the signed image is: + * + * -----+-------------+ + * / | Magic | 32-bit word, magic value equal to + * / +-------------+ 0x3543A468 + * / +-------------+ + * / | version | 32-bit word, version of the format + * / +-------------+ + * +-----------+ +-------------+ + * | Header | | TLV size | 32-bit word, size of the TLV + * +-----------+ +-------------+ (aligned on 64-bit), in bytes. + * \ +-------------+ + * \ | sign size | 32-bit word, size of the signature + * \ +-------------+ (aligned on 64-bit), in bytes. + * \ +-------------+ + * \ | images size | 32-bit word, size of the images to + * -----+-------------+ load (aligned on 64-bit), in bytes. + * + * +-------------+ Information used to authenticate the + * | TLV | images and boot the remote processor, + * | | stored in Type-Length-Value format. + * +-------------+ 'Type' and 'Length' are 32-bit words. + * + * +-------------+ + * | Signature | Signature of the header and the TLV. + * +-------------+ + * + * +-------------+ + * | Firmware | + * | image 1 | + * +-------------+ + * ... + * +-------------+ + * | Firmware | + * | image n | + * +-------------+ + */ + +/* Firmware state */ +enum remoteproc_state { + REMOTEPROC_OFF = 0, + REMOTEPROC_LOADED, + REMOTEPROC_STARTED, +}; + +#define RPROC_HDR_MAGIC 0x3543A468 +#define HEADER_VERSION 1 + +/* Supported signature algorithm */ +enum remoteproc_sign_type { + RPROC_RSASSA_PKCS1_v1_5_SHA256 = 1, + RPROC_ECDSA_SHA256 = 2, +}; + +enum remoteproc_img_type { + REMOTEPROC_ELF_TYPE = 1, + REMOTEPROC_INVALID_TYPE = 0xFF +}; + +/* remoteproc_tlv structure offsets */ +#define RPROC_TLV_LENGTH_OF U(0x04) +#define RPROC_TLV_VALUE_OF U(0x08) + +/* TLV types */ +#define RPROC_TLV_SIGNTYPE U(0x00000001) +#define RPROC_TLV_HASHTYPE U(0x00000002) +#define RPROC_TLV_NUM_IMG U(0x00000003) +#define RPROC_TLV_IMGTYPE U(0x00000004) +#define RPROC_TLV_IMGSIZE U(0x00000005) +#define RPROC_TLV_HASHTABLE U(0x00000010) +#define RPROC_TLV_PKEYINFO U(0x00000011) + +#define RPROC_PLAT_TLV_TYPE_MIN U(0x00010000) +#define RPROC_PLAT_TLV_TYPE_MAX U(0x00020000) + +#define RPROC_TLV_SIGNTYPE_LGTH U(1) + +#define ROUNDUP_64(x) ROUNDUP((x), sizeof(uint64_t)) + +/* + * struct remoteproc_tlv - Type-Length-Value structure + * @type: type of data + * @length: size of the data. + * @value: pointer to the data. + */ +struct remoteproc_tlv { + uint32_t type; + uint32_t length; + uint8_t value[]; +}; + +/* + * struct remoteproc_segment - program header with hash structure + * @phdr: program header + * @hash: hash associated to the program segment. + */ +struct remoteproc_segment { + Elf32_Phdr phdr; + uint8_t hash[TEE_SHA256_HASH_SIZE]; +}; + +/* + * struct remoteproc_fw_hdr - firmware header + * @magic: Magic number, must be equal to RPROC_HDR_MAGIC + * @version: Version of the header (must be 1) + * @tlv_len: Generic meta data chunk (TLV format) + * @sign_len: Signature chunk byte length + * @img_len: Firmware image chunk byte length + */ +struct remoteproc_fw_hdr { + uint32_t magic; + uint32_t version; + uint32_t tlv_len; + uint32_t sign_len; + uint32_t img_len; +}; + +#define FW_TLV_PTR(img, hdr) ((img) + sizeof(*(hdr))) +#define FW_SIGN_PTR(img, hdr) ({ \ + struct remoteproc_fw_hdr *__hdr = (hdr); \ + \ + FW_TLV_PTR((img), __hdr) + ROUNDUP_64(__hdr->tlv_len); \ + }) +#define FW_IMG_PTR(img, hdr) ({ \ + struct remoteproc_fw_hdr *___hdr = (hdr); \ + \ + FW_SIGN_PTR((img), ___hdr) + ROUNDUP_64(___hdr->sign_len); \ + }) + +/* + * struct remoteproc_sig_algo - signature algorithm information + * @sign_type: Header signature type + * @id: Signature algorithm identifier TEE_ALG_* + * @hash_len: Signature hash length + */ +struct remoteproc_sig_algo { + enum remoteproc_sign_type sign_type; + uint32_t id; + size_t hash_len; +}; + +/* + * struct remoteproc_context - firmware context + * @rproc_id: Unique Id of the processor + * @sec_cpy: Location of a secure copy of the header, TLVs and signature + * @tlvs: Location of a secure copy of the firmware TLVs + * @tlvs_sz: Byte size of the firmware TLVs blob. + * @fw_img: Firmware image + * @fw_img_sz: Byte size of the firmware image + * @hash_table: Location of a copy of the segment's hash table + * @nb_segment: number of segment to load + * @rsc_pa: Physical address of the firmware resource table + * @rsc_size: Byte size of the firmware resource table + * @state: Remote-processor state + * @hw_fmt: Image format capabilities of the remoteproc PTA + * @hw_img_prot: Image protection capabilities of the remoteproc PTA + * @link: Linked list element + */ +struct remoteproc_context { + uint32_t rproc_id; + uint8_t *sec_cpy; + uint8_t *tlvs; + size_t tlvs_sz; + uint8_t *fw_img; + size_t fw_img_sz; + struct remoteproc_segment *hash_table; + uint32_t nb_segment; + paddr_t rsc_pa; + size_t rsc_size; + enum remoteproc_state state; + uint32_t hw_fmt; + uint32_t hw_img_prot; + TAILQ_ENTRY(remoteproc_context) link; +}; + +TAILQ_HEAD(remoteproc_firmware_head, remoteproc_context); + +static struct remoteproc_firmware_head firmware_head = + TAILQ_HEAD_INITIALIZER(firmware_head); + +static const struct remoteproc_sig_algo rproc_ta_sign_algo[] = { + { + .sign_type = RPROC_RSASSA_PKCS1_v1_5_SHA256, + .id = TEE_ALG_RSASSA_PKCS1_V1_5_SHA256, + .hash_len = TEE_SHA256_HASH_SIZE, + }, + { + .sign_type = RPROC_ECDSA_SHA256, + .id = TEE_ALG_ECDSA_P256, + .hash_len = TEE_SHA256_HASH_SIZE, + }, +}; + +static size_t session_refcount; +static TEE_TASessionHandle pta_session; + +static void remoteproc_header_dump(struct remoteproc_fw_hdr __maybe_unused *hdr) +{ + DMSG("magic :\t%#"PRIx32, hdr->magic); + DMSG("version :\t%#"PRIx32, hdr->version); + DMSG("tlv_len :\t%#"PRIx32, hdr->tlv_len); + DMSG("sign_len :\t%#"PRIx32, hdr->sign_len); + DMSG("img_len :\t%#"PRIx32, hdr->img_len); +} + +static TEE_Result remoteproc_get_tlv(void *tlv_chunk, size_t tlv_size, + uint16_t type, uint8_t **value, + size_t *length) +{ + uint8_t *p_tlv = (uint8_t *)tlv_chunk; + uint8_t *p_end_tlv = p_tlv + tlv_size; + uint32_t tlv_type = 0; + uint32_t tlv_length = 0; + uint32_t tlv_v = 0; + + *value = NULL; + *length = 0; + + /* Parse the TLV area */ + while (p_tlv < p_end_tlv) { + memcpy(&tlv_v, p_tlv, sizeof(tlv_v)); + tlv_type = TEE_U32_FROM_LITTLE_ENDIAN(tlv_v); + memcpy(&tlv_v, p_tlv + RPROC_TLV_LENGTH_OF, sizeof(tlv_v)); + tlv_length = TEE_U32_FROM_LITTLE_ENDIAN(tlv_v); + if (tlv_type == type) { + /* The specified TLV has been found */ + DMSG("TLV type %#"PRIx32" found, size %#"PRIx32, + type, tlv_length); + *value = &p_tlv[RPROC_TLV_VALUE_OF]; + *length = tlv_length; + if (tlv_length) + return TEE_SUCCESS; + else + return TEE_ERROR_NO_DATA; + } + p_tlv += ROUNDUP_64(sizeof(struct remoteproc_tlv) + tlv_length); + } + + return TEE_ERROR_NO_DATA; +} + +static struct remoteproc_context *remoteproc_find_firmware(uint32_t rproc_id) +{ + struct remoteproc_context *ctx = NULL; + + TAILQ_FOREACH(ctx, &firmware_head, link) + if (ctx->rproc_id == rproc_id) + return ctx; + + return NULL; +} + +static struct remoteproc_context *remoteproc_add_firmware(uint32_t rproc_id) +{ + struct remoteproc_context *ctx = NULL; + + ctx = TEE_Malloc(sizeof(*ctx), TEE_MALLOC_FILL_ZERO); + if (!ctx) + return NULL; + + ctx->rproc_id = rproc_id; + + TAILQ_INSERT_TAIL(&firmware_head, ctx, link); + + return ctx; +} + +static const struct remoteproc_sig_algo *remoteproc_get_algo(uint32_t sign_type) +{ + unsigned int i = 0; + + for (i = 0; i < ARRAY_SIZE(rproc_ta_sign_algo); i++) + if (sign_type == rproc_ta_sign_algo[i].sign_type) + return &rproc_ta_sign_algo[i]; + + return NULL; +} + +static TEE_Result remoteproc_pta_verify(struct remoteproc_context *ctx, + const struct remoteproc_sig_algo *algo, + uint8_t *hash, uint32_t hash_len) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct remoteproc_fw_hdr *hdr = (void *)ctx->sec_cpy; + struct rproc_pta_key_info *keyinfo = NULL; + uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT); + TEE_Param params[TEE_NUM_PARAMS] = { }; + size_t length = 0; + uint8_t *tlv_keyinfo = NULL; + uint8_t *sign = NULL; + + res = remoteproc_get_tlv(ctx->tlvs, hdr->tlv_len, + RPROC_TLV_PKEYINFO, &tlv_keyinfo, + &length); + if (res != TEE_SUCCESS && res != TEE_ERROR_NO_DATA) + return res; + + keyinfo = TEE_Malloc(sizeof(*keyinfo) + length, TEE_MALLOC_FILL_ZERO); + if (!keyinfo) + return TEE_ERROR_OUT_OF_MEMORY; + + keyinfo->algo = algo->id; + keyinfo->info_size = length; + memcpy(keyinfo->info, tlv_keyinfo, length); + + sign = FW_SIGN_PTR(ctx->sec_cpy, hdr); + + params[0].value.a = ctx->rproc_id; + params[1].memref.buffer = keyinfo; + params[1].memref.size = rproc_pta_keyinfo_size(keyinfo); + params[2].memref.buffer = hash; + params[2].memref.size = hash_len; + params[3].memref.buffer = sign; + params[3].memref.size = hdr->sign_len; + + res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE, + PTA_RPROC_VERIFY_DIGEST, + param_types, params, NULL); + if (res != TEE_SUCCESS) + EMSG("Failed to verify signature, res = %#"PRIx32, res); + + TEE_Free(keyinfo); + + return res; +} + +static TEE_Result +remoteproc_save_fw_header_and_tlvs(struct remoteproc_context *ctx, + void *fw_orig, uint32_t fw_orig_size) +{ + struct remoteproc_fw_hdr *hdr = fw_orig; + uint32_t length = 0; + + if (!IS_ALIGNED_WITH_TYPE(fw_orig, struct remoteproc_fw_hdr)) + return TEE_ERROR_BAD_PARAMETERS; + + if (ADD_OVERFLOW(sizeof(*hdr), ROUNDUP_64(hdr->tlv_len), &length) || + ADD_OVERFLOW(length, ROUNDUP_64(hdr->sign_len), &length)) + return TEE_ERROR_BAD_PARAMETERS; + + if (fw_orig_size <= length || !hdr->sign_len || !hdr->tlv_len) + return TEE_ERROR_BAD_PARAMETERS; + + remoteproc_header_dump(hdr); + + /* Copy the header, the TLVs and the signature in secure memory */ + ctx->sec_cpy = TEE_Malloc(length, TEE_MALLOC_FILL_ZERO); + if (!ctx->sec_cpy) + return TEE_ERROR_OUT_OF_MEMORY; + + memcpy(ctx->sec_cpy, fw_orig, length); + + return TEE_SUCCESS; +} + +static TEE_Result remoteproc_verify_signature(struct remoteproc_context *ctx) +{ + TEE_OperationHandle op = TEE_HANDLE_NULL; + struct remoteproc_fw_hdr *hdr = (void *)ctx->sec_cpy; + const struct remoteproc_sig_algo *algo = NULL; + TEE_Result res = TEE_ERROR_GENERIC; + uint8_t *tlv_sign_algo = NULL; + size_t length = 0; + uint8_t *hash = NULL; + size_t hash_len = 0; + + /* Get the algo type from TLV data */ + res = remoteproc_get_tlv(ctx->tlvs, hdr->tlv_len, RPROC_TLV_SIGNTYPE, + &tlv_sign_algo, &length); + + if (res != TEE_SUCCESS || length != RPROC_TLV_SIGNTYPE_LGTH) + return TEE_ERROR_BAD_PARAMETERS; + + algo = remoteproc_get_algo(*tlv_sign_algo); + if (!algo) { + EMSG("Unsupported signature type %"PRId8, *tlv_sign_algo); + return TEE_ERROR_NOT_SUPPORTED; + } + + /* Compute the header and TLVs hashes */ + hash_len = algo->hash_len; + hash = TEE_Malloc(hash_len, TEE_MALLOC_FILL_ZERO); + if (!hash) + return TEE_ERROR_OUT_OF_MEMORY; + + res = TEE_AllocateOperation(&op, TEE_ALG_SHA256, TEE_MODE_DIGEST, 0); + if (res != TEE_SUCCESS) + goto free_hash; + + TEE_DigestUpdate(op, hdr, sizeof(*hdr)); + res = TEE_DigestDoFinal(op, ctx->tlvs, ROUNDUP_64(hdr->tlv_len), + hash, &hash_len); + + if (res != TEE_SUCCESS) + goto out; + + /* + * This implementation could be enhanced by providing alternative to + * verify the signature in the TA. This could be done for instance by + * getting the key object from secure storage. + */ + + /* By default ask the remoteproc PTA to verify the signature. */ + res = remoteproc_pta_verify(ctx, algo, hash, hash_len); + +out: + TEE_FreeOperation(op); +free_hash: + TEE_Free(hash); + + return res; +} + +static TEE_Result remoteproc_verify_header(struct remoteproc_context *ctx, + uint32_t fw_orig_size) +{ + struct remoteproc_fw_hdr *hdr = (void *)ctx->sec_cpy; + uint32_t size = 0; + + if (hdr->magic != RPROC_HDR_MAGIC) + return TEE_ERROR_BAD_PARAMETERS; + + if (hdr->version != HEADER_VERSION) + return TEE_ERROR_BAD_PARAMETERS; + + /* + * The offsets are aligned to 64 bits format. While the length of each + * chunks are the effective length, excluding the alignment padding + * bytes. + */ + if (ADD_OVERFLOW(sizeof(*hdr), ROUNDUP_64(hdr->sign_len), &size) || + ADD_OVERFLOW(size, ROUNDUP_64(hdr->img_len), &size) || + ADD_OVERFLOW(size, ROUNDUP_64(hdr->tlv_len), &size) || + fw_orig_size != size) + return TEE_ERROR_BAD_PARAMETERS; + + return TEE_SUCCESS; +} + +static TEE_Result get_rproc_pta_capabilities(struct remoteproc_context *ctx) +{ + uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE); + TEE_Param params[TEE_NUM_PARAMS] = { }; + TEE_Result res = TEE_ERROR_GENERIC; + + params[0].value.a = ctx->rproc_id; + + res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE, + PTA_RPROC_HW_CAPABILITIES, + param_types, params, NULL); + if (res) + return res; + + ctx->hw_fmt = params[1].value.a; + ctx->hw_img_prot = params[2].value.a; + + return TEE_SUCCESS; +} + +static TEE_Result remoteproc_verify_firmware(struct remoteproc_context *ctx, + uint8_t *fw_orig, + uint32_t fw_orig_size) +{ + struct remoteproc_fw_hdr *hdr = NULL; + TEE_Result res = TEE_ERROR_GENERIC; + + res = get_rproc_pta_capabilities(ctx); + if (res) + return res; + + /* Secure the firmware image depending on strategy */ + if (!(ctx->hw_img_prot & PTA_RPROC_HWCAP_PROT_HASH_TABLE) || + ctx->hw_fmt != PTA_RPROC_HWCAP_FMT_ELF) { + /* + * Only hash table for ELF format support implemented + * in a first step. + */ + return TEE_ERROR_NOT_IMPLEMENTED; + } + + res = remoteproc_save_fw_header_and_tlvs(ctx, fw_orig, fw_orig_size); + if (res) + return res; + + res = remoteproc_verify_header(ctx, fw_orig_size); + if (res) + goto free_sec_cpy; + + hdr = (void *)ctx->sec_cpy; + ctx->tlvs_sz = hdr->tlv_len; + ctx->tlvs = FW_TLV_PTR(ctx->sec_cpy, hdr); + + res = remoteproc_verify_signature(ctx); + if (res) + goto free_sec_cpy; + + /* Store location of the loadable binary in non-secure memory */ + ctx->fw_img_sz = hdr->img_len; + ctx->fw_img = FW_IMG_PTR(fw_orig, hdr); + + DMSG("Firmware images addr: %p size: %zu", ctx->fw_img, + ctx->fw_img_sz); + + return TEE_SUCCESS; + +free_sec_cpy: + TEE_Free(ctx->sec_cpy); + ctx->sec_cpy = NULL; + + return res; +} + +static paddr_t remoteproc_da_to_pa(uint32_t da, size_t size, + struct remoteproc_context *ctx) +{ + uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT); + TEE_Param params[TEE_NUM_PARAMS] = { }; + TEE_Result res = TEE_ERROR_GENERIC; + paddr_t pa = 0; + + /* + * The ELF file contains remote processor device addresses, that refer + * to the remote processor memory space. + * A translation is needed to get the corresponding physical address. + */ + + params[0].value.a = ctx->rproc_id; + params[1].value.a = da; + params[2].value.a = size; + + res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE, + PTA_RPROC_FIRMWARE_DA_TO_PA, + param_types, params, NULL); + if (res != TEE_SUCCESS) { + EMSG("Failed to translate device address %#"PRIx32, da); + return 0; + } + + pa = (paddr_t)reg_pair_to_64(params[3].value.b, params[3].value.a); + + /* Assert that the pa address is not 0 */ + assert(pa); + + return pa; +} + +static TEE_Result remoteproc_parse_rsc_table(struct remoteproc_context *ctx, + uint8_t *fw_img, size_t fw_img_sz, + paddr_t *rsc_pa, + size_t *rsc_size) +{ + uint32_t da = 0; + TEE_Result res = TEE_ERROR_GENERIC; + Elf32_Word size = 0; + + res = e32_parser_find_rsc_table(fw_img, fw_img_sz, &da, &size); + if (res) + return res; + + DMSG("Resource table device address %#"PRIx32" size %#"PRIx32, + da, size); + + *rsc_pa = remoteproc_da_to_pa(da, size, ctx); + if (!*rsc_pa) + return TEE_ERROR_ACCESS_DENIED; + + *rsc_size = size; + + return TEE_SUCCESS; +} + +static TEE_Result get_hash_table(struct remoteproc_context *ctx) +{ + TEE_Result res = TEE_ERROR_GENERIC; + uint8_t *tlv_hash = NULL; + struct remoteproc_segment *hash_table = NULL; + size_t length = 0; + + /* Get the segment's hash table from TLV data */ + res = remoteproc_get_tlv(ctx->tlvs, ctx->tlvs_sz, RPROC_TLV_HASHTABLE, + &tlv_hash, &length); + if (res) + return res; + + if (length % sizeof(struct remoteproc_segment)) + return TEE_ERROR_BAD_PARAMETERS; + + /* We can not ensure that tlv_hash is memory aligned so make a copy */ + hash_table = TEE_Malloc(length, TEE_MALLOC_FILL_ZERO); + if (!hash_table) + return TEE_ERROR_OUT_OF_MEMORY; + + memcpy(hash_table, tlv_hash, length); + + ctx->hash_table = hash_table; + ctx->nb_segment = length / sizeof(struct remoteproc_segment); + + return TEE_SUCCESS; +} + +static TEE_Result get_tlv_images_type(struct remoteproc_context *ctx, + uint8_t num_img, uint8_t idx, + uint8_t *img_type) +{ + TEE_Result res = TEE_ERROR_GENERIC; + uint8_t *tlv_value = NULL; + size_t length = 0; + + /* Get the type of the image to load, from TLV data */ + res = remoteproc_get_tlv(ctx->tlvs, ctx->tlvs_sz, RPROC_TLV_IMGTYPE, + &tlv_value, &length); + if (res) + return res; + + if (length != (sizeof(*img_type) * num_img)) + return TEE_ERROR_BAD_PARAMETERS; + + *img_type = tlv_value[idx]; + + return TEE_SUCCESS; +} + +static TEE_Result get_tlv_images_size(struct remoteproc_context *ctx, + uint8_t num_img, uint8_t idx, + uint32_t *img_size) +{ + TEE_Result res = TEE_ERROR_GENERIC; + uint8_t *tlv_value = NULL; + uint32_t tlv_v = 0; + size_t length = 0; + + /* Get the size of the image to load, from TLV data */ + res = remoteproc_get_tlv(ctx->tlvs, ctx->tlvs_sz, RPROC_TLV_IMGSIZE, + &tlv_value, &length); + if (res) + return res; + + if (length != (sizeof(*img_size) * num_img)) + return TEE_ERROR_BAD_PARAMETERS; + + memcpy(&tlv_v, &tlv_value[sizeof(*img_size) * idx], sizeof(tlv_v)); + *img_size = TEE_U32_FROM_LITTLE_ENDIAN(tlv_v); + + return TEE_SUCCESS; +} + +static TEE_Result get_segment_hash(struct remoteproc_context *ctx, uint8_t *src, + uint32_t size, uint32_t da, + uint32_t mem_size, uint8_t **hash) +{ + struct remoteproc_segment *peh = NULL; + unsigned int i = 0; + unsigned int nb_entry = ctx->nb_segment; + + peh = (void *)(ctx->hash_table); + + for (i = 0; i < nb_entry; peh++, i++) { + if (peh->phdr.p_paddr != da) + continue; + + /* + * Segment metadata are read from a non-secure memory. + * Validate them using hash table data stored in secure memory. + */ + if (peh->phdr.p_type != PT_LOAD) + return TEE_ERROR_BAD_PARAMETERS; + + if (peh->phdr.p_filesz != size || peh->phdr.p_memsz != mem_size) + return TEE_ERROR_BAD_PARAMETERS; + + if (src < ctx->fw_img || + src > (ctx->fw_img + ctx->fw_img_sz) || + (src + peh->phdr.p_filesz) > (ctx->fw_img + ctx->fw_img_sz)) + return TEE_ERROR_BAD_PARAMETERS; + + *hash = peh->hash; + + return TEE_SUCCESS; + } + + return TEE_ERROR_NO_DATA; +} + +static TEE_Result remoteproc_load_segment(uint8_t *src, uint32_t size, + uint32_t da, uint32_t mem_size, + void *priv) +{ + struct remoteproc_context *ctx = priv; + uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT); + TEE_Param params[TEE_NUM_PARAMS] = { }; + TEE_Result res = TEE_ERROR_GENERIC; + uint8_t *hash = NULL; + + /* + * Invoke platform remoteproc PTA to load the segment in remote + * processor memory which is not mapped in the TA space. + */ + + DMSG("Load segment %#"PRIx32" size %"PRIu32" (%"PRIu32")", da, size, + mem_size); + + res = get_segment_hash(ctx, src, size, da, mem_size, &hash); + if (res) + return res; + + params[0].value.a = ctx->rproc_id; + params[1].memref.buffer = src; + params[1].memref.size = size; + params[2].value.a = da; + params[3].memref.buffer = hash; + params[3].memref.size = TEE_SHA256_HASH_SIZE; + + if (size) { + res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE, + PTA_RPROC_LOAD_SEGMENT_SHA256, + param_types, params, NULL); + if (res != TEE_SUCCESS) { + EMSG("Fails to load segment, res = 0x%#"PRIx32, res); + return res; + } + } + + /* Fill the rest of the memory with 0 */ + if (size < mem_size) { + param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT); + params[1].value.a = da + size; + params[2].value.a = mem_size - size; + params[3].value.a = 0; + + res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE, + PTA_RPROC_SET_MEMORY, + param_types, params, NULL); + if (res != TEE_SUCCESS) + EMSG("Fails to clear segment, res = %#"PRIx32, res); + } + + return res; +} + +static TEE_Result remoteproc_load_elf(struct remoteproc_context *ctx) +{ + TEE_Result res = TEE_ERROR_GENERIC; + unsigned int num_img = 0; + unsigned int i = 0; + uint8_t img_type = REMOTEPROC_INVALID_TYPE; + uint32_t img_size = 0; + uint8_t *tlv = NULL; + int32_t offset = 0; + size_t length = 0; + paddr_t rsc_pa = 0; + size_t rsc_size = 0; + + res = e32_parse_ehdr(ctx->fw_img, ctx->fw_img_sz); + if (res) { + EMSG("Failed to parse firmware, res = %#"PRIx32, res); + return res; + } + + res = get_hash_table(ctx); + if (res) + return res; + + /* Get the number of firmware images to load */ + res = remoteproc_get_tlv(ctx->tlvs, ctx->tlvs_sz, RPROC_TLV_NUM_IMG, + &tlv, &length); + if (res) + goto out; + if (length != sizeof(uint8_t)) { + res = TEE_ERROR_BAD_FORMAT; + goto out; + } + + num_img = *tlv; + if (!num_img) { + res = TEE_ERROR_NO_DATA; + goto out; + } + + /* + * Initialize resource table with zero. These values will be returned if + * no optional resource table is found in images. + */ + ctx->rsc_pa = 0; + ctx->rsc_size = 0; + + for (i = 0; i < num_img; i++) { + res = get_tlv_images_type(ctx, num_img, i, &img_type); + if (res) + goto out; + if (img_type != REMOTEPROC_ELF_TYPE) { + res = TEE_ERROR_BAD_FORMAT; + goto out; + } + + res = get_tlv_images_size(ctx, num_img, i, &img_size); + if (res) + goto out; + + res = e32_parser_load_elf_image(ctx->fw_img + offset, img_size, + remoteproc_load_segment, ctx); + if (res) + goto out; + + /* Take opportunity to get the resource table address */ + res = remoteproc_parse_rsc_table(ctx, ctx->fw_img + offset, + img_size, &rsc_pa, &rsc_size); + if (res != TEE_SUCCESS && res != TEE_ERROR_NO_DATA) + goto out; + + if (res == TEE_SUCCESS) { + /* + * Only one resource table is supported, check that no + * other one has been declared in a previously loaded + * firmware. + */ + if (ctx->rsc_pa || ctx->rsc_size) { + EMSG("More than one resource table found"); + res = TEE_ERROR_BAD_FORMAT; + goto out; + } + ctx->rsc_pa = rsc_pa; + ctx->rsc_size = rsc_size; + } else { + /* + * No resource table found. Force to TEE_SUCCESS as the + * resource table is optional. + */ + res = TEE_SUCCESS; + } + offset += img_size; + } + +out: + /* Should we clean-up the memories in case of fail ? */ + TEE_Free(ctx->hash_table); + ctx->hash_table = NULL; + + return res; +} + +static TEE_Result remoteproc_load_fw(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); + struct remoteproc_context *ctx = NULL; + uint32_t rproc_id = params[0].value.a; + TEE_Result res = TEE_ERROR_GENERIC; + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + ctx = remoteproc_find_firmware(rproc_id); + if (!ctx) + ctx = remoteproc_add_firmware(rproc_id); + if (!ctx) + return TEE_ERROR_OUT_OF_MEMORY; + + /* The firmware is already loaded, do nothing */ + if (ctx->state == REMOTEPROC_LOADED) + return TEE_SUCCESS; + + if (ctx->state != REMOTEPROC_OFF) + return TEE_ERROR_BAD_STATE; + + if (!params[1].memref.buffer || !params[1].memref.size) + return TEE_ERROR_BAD_PARAMETERS; + + DMSG("Got base addr: %p size %#zx", params[1].memref.buffer, + params[1].memref.size); + + res = remoteproc_verify_firmware(ctx, params[1].memref.buffer, + params[1].memref.size); + if (res) { + EMSG("Can't Authenticate the firmware (res = %#"PRIx32")", res); + goto out; + } + + res = remoteproc_load_elf(ctx); + if (res) + goto out; + + ctx->state = REMOTEPROC_LOADED; + +out: + /* Clear reference to firmware image from shared memory */ + ctx->fw_img = NULL; + ctx->fw_img_sz = 0; + ctx->nb_segment = 0; + + /* Free allocated memories */ + TEE_Free(ctx->sec_cpy); + ctx->sec_cpy = NULL; + + return res; +} + +static TEE_Result remoteproc_start_fw(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); + struct remoteproc_context *ctx = NULL; + uint32_t rproc_id = params[0].value.a; + TEE_Result res = TEE_ERROR_GENERIC; + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + ctx = remoteproc_find_firmware(rproc_id); + if (!ctx) + return TEE_ERROR_BAD_PARAMETERS; + + switch (ctx->state) { + case REMOTEPROC_OFF: + res = TEE_ERROR_BAD_STATE; + break; + case REMOTEPROC_STARTED: + res = TEE_SUCCESS; + break; + case REMOTEPROC_LOADED: + res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE, + PTA_RPROC_FIRMWARE_START, + pt, params, NULL); + if (res == TEE_SUCCESS) + ctx->state = REMOTEPROC_STARTED; + break; + default: + res = TEE_ERROR_BAD_STATE; + } + + return res; +} + +static TEE_Result remoteproc_stop_fw(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); + struct remoteproc_context *ctx = NULL; + uint32_t rproc_id = params[0].value.a; + TEE_Result res = TEE_ERROR_GENERIC; + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + ctx = remoteproc_find_firmware(rproc_id); + if (!ctx) + return TEE_ERROR_BAD_PARAMETERS; + + switch (ctx->state) { + case REMOTEPROC_LOADED: + res = TEE_ERROR_BAD_STATE; + break; + case REMOTEPROC_OFF: + res = TEE_SUCCESS; + break; + case REMOTEPROC_STARTED: + res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE, + PTA_RPROC_FIRMWARE_STOP, + pt, params, NULL); + if (res == TEE_SUCCESS) + ctx->state = REMOTEPROC_OFF; + break; + default: + res = TEE_ERROR_BAD_STATE; + } + + return res; +} + +static TEE_Result remoteproc_get_rsc_table(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_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE); + struct remoteproc_context *ctx = NULL; + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + ctx = remoteproc_find_firmware(params[0].value.a); + if (!ctx) + return TEE_ERROR_BAD_PARAMETERS; + + if (ctx->state == REMOTEPROC_OFF) + return TEE_ERROR_BAD_STATE; + + reg_pair_from_64((uint64_t)ctx->rsc_pa, + ¶ms[1].value.b, ¶ms[1].value.a); + reg_pair_from_64((uint64_t)ctx->rsc_size, + ¶ms[2].value.b, ¶ms[2].value.a); + + return TEE_SUCCESS; +} + +TEE_Result TA_CreateEntryPoint(void) +{ + return TEE_SUCCESS; +} + +void TA_DestroyEntryPoint(void) +{ +} + +/* + * TA_OpenSessionEntryPoint: open a TA session associated to a remote processor + * to manage. + * + * [in] params[0].value.a: Unique 32bit remote processor identifier + */ +TEE_Result TA_OpenSessionEntryPoint(uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS], + void **sess __unused) +{ + static const TEE_UUID uuid = PTA_RPROC_UUID; + TEE_Result res = TEE_ERROR_GENERIC; + 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); + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + if (!session_refcount) { + res = TEE_OpenTASession(&uuid, TEE_TIMEOUT_INFINITE, pt, params, + &pta_session, NULL); + if (res) + return res; + } + + session_refcount++; + + return TEE_SUCCESS; +} + +void TA_CloseSessionEntryPoint(void *sess __unused) +{ + session_refcount--; + + if (!session_refcount) + TEE_CloseTASession(pta_session); +} + +TEE_Result TA_InvokeCommandEntryPoint(void *sess __unused, uint32_t cmd_id, + uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS]) +{ + switch (cmd_id) { + case TA_RPROC_CMD_LOAD_FW: + return remoteproc_load_fw(pt, params); + case TA_RPROC_CMD_START_FW: + return remoteproc_start_fw(pt, params); + case TA_RPROC_CMD_STOP_FW: + return remoteproc_stop_fw(pt, params); + case TA_RPROC_CMD_GET_RSC_TABLE: + return remoteproc_get_rsc_table(pt, params); + case TA_RPROC_CMD_GET_COREDUMP: + return TEE_ERROR_NOT_IMPLEMENTED; + default: + return TEE_ERROR_BAD_PARAMETERS; + } +} diff --git a/optee/optee_os/ta/remoteproc/src/sub.mk b/optee/optee_os/ta/remoteproc/src/sub.mk new file mode 100644 index 0000000..81ba566 --- /dev/null +++ b/optee/optee_os/ta/remoteproc/src/sub.mk @@ -0,0 +1,2 @@ +srcs-y += remoteproc_core.c +srcs-y += elf_parser.c diff --git a/optee/optee_os/ta/remoteproc/src/user_ta_header_defines.h b/optee/optee_os/ta/remoteproc/src/user_ta_header_defines.h new file mode 100644 index 0000000..d303cb0 --- /dev/null +++ b/optee/optee_os/ta/remoteproc/src/user_ta_header_defines.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2023 STMicroelectronics + */ + +#ifndef USER_TA_HEADER_DEFINES_H +#define USER_TA_HEADER_DEFINES_H + +#include + +#define TA_UUID TA_REMOTEPROC_UUID + +#define TA_FLAGS (TA_FLAG_DEVICE_ENUM | \ + TA_FLAG_SINGLE_INSTANCE | \ + TA_FLAG_INSTANCE_KEEP_ALIVE) + +/* Provisioned stack size */ +#define TA_STACK_SIZE (4 * 1024) + +/* Provisioned heap size for TEE_Malloc() and friends */ +#define TA_DATA_SIZE CFG_REMOTEPROC_TA_HEAP_SIZE + +/* The gpd.ta.version property */ +#define TA_VERSION "1.0" + +/* The gpd.ta.description property */ +#define TA_DESCRIPTION "remote processor firmware management" + +#endif /* USER_TA_HEADER_DEFINES_H */ diff --git a/optee/optee_os/ta/remoteproc/sub.mk b/optee/optee_os/ta/remoteproc/sub.mk new file mode 100644 index 0000000..ae78d61 --- /dev/null +++ b/optee/optee_os/ta/remoteproc/sub.mk @@ -0,0 +1,3 @@ +global-incdirs-y += include +global-incdirs-y += src +subdirs-y += src diff --git a/optee/optee_os/ta/remoteproc/user_ta.mk b/optee/optee_os/ta/remoteproc/user_ta.mk new file mode 100644 index 0000000..84721ff --- /dev/null +++ b/optee/optee_os/ta/remoteproc/user_ta.mk @@ -0,0 +1,4 @@ +user-ta-uuid := 80a4c275-0a47-4905-8285-1486a9771a08 + +# REMOTEPROC TA heap size can be customized if 4kB is not enough +CFG_REMOTEPROC_TA_HEAP_SIZE ?= (4 * 1024) diff --git a/optee/optee_os/ta/ta.mk b/optee/optee_os/ta/ta.mk new file mode 100644 index 0000000..ac46890 --- /dev/null +++ b/optee/optee_os/ta/ta.mk @@ -0,0 +1,218 @@ +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 +# +# 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 mk/macros.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 := $(TA_SIGN_KEY) +# default_ta.pem is a symlink to default.pem, for backwards compatibility. +# If default_ta.pem is used, copy both files. +ifeq ($(TA_SIGN_KEY),keys/default_ta.pem) +ta-keys += keys/default.pem +endif + +$(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 \ + scripts/sign_rproc_fw.py scripts/ftrace_format.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..20086d2 --- /dev/null +++ b/optee/optee_test/.github/workflows/ci.yml @@ -0,0 +1,36 @@ +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: Remove /__t/* + run: rm -rf /__t/* + - 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..51a817a --- /dev/null +++ b/optee/optee_test/Android.mk @@ -0,0 +1,173 @@ +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 \ + asym_perf.c \ + benchmark_1000.c \ + benchmark_2000.c \ + clear_storage.c \ + regression_4000.c \ + regression_4100.c \ + regression_5000.c \ + regression_6000.c \ + regression_8000.c \ + regression_8100.c \ + hash_perf.c \ + stats.c \ + symm_cipher_perf.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/crypto_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)/ta/subkey1/include \ + $(LOCAL_PATH)/ta/subkey2/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/supp_plugin/CMakeLists.txt b/optee/optee_test/host/supp_plugin/CMakeLists.txt new file mode 100644 index 0000000..6b75a74 --- /dev/null +++ b/optee/optee_test/host/supp_plugin/CMakeLists.txt @@ -0,0 +1,11 @@ +project (f07bfc66-958c-4a15-99c0-260e4e7375dd.plugin C) + +set (CFG_TEE_PLUGIN_LOAD_PATH "/usr/lib/tee-supplicant/plugins/") +set (CMAKE_SHARED_LIBRARY_PREFIX "") + +add_library(${PROJECT_NAME} SHARED test_supp_plugin.c) +target_include_directories(${PROJECT_NAME} PRIVATE ./include) + +target_link_libraries (${PROJECT_NAME} PRIVATE teec) + +install (TARGETS ${PROJECT_NAME} DESTINATION ${CFG_TEE_PLUGIN_LOAD_PATH}) diff --git a/optee/optee_test/host/supp_plugin/Makefile b/optee/optee_test/host/supp_plugin/Makefile new file mode 100644 index 0000000..2439010 --- /dev/null +++ b/optee/optee_test/host/supp_plugin/Makefile @@ -0,0 +1,24 @@ +PLUGIN_UUID = f07bfc66-958c-4a15-99c0-260e4e7375dd + +PLUGIN = $(PLUGIN_UUID).plugin +PLUGIN_SRS = $(wildcard ./*.c) +PLUGIN_OBJ = $(patsubst %.c, $(O)/supp_plugin/%.o, $(PLUGIN_SRS)) +PLUGIN_INCLUDES_DIR = $(CURDIR)/include $(OPTEE_CLIENT_EXPORT)/include + +PLUGIN_INCLUDES = $(addprefix -I, $(PLUGIN_INCLUDES_DIR)) +PLUGIN_CCFLAGS = $(CFLAGS) -Wall -fPIC +PLUGIN_LDFLAGS = $(LDFLAGS) -shared + +CC ?= $(CROSS_COMPILE)gcc + +$(O)/supp_plugin/$(PLUGIN): $(PLUGIN_OBJ) + $(q)$(CC) $(PLUGIN_LDFLAGS) $(PLUGIN_OBJ) -o $@ + +$(O)/supp_plugin/%.o: $(CURDIR)/%.c + $(q)mkdir -p $(O)/supp_plugin + @echo ' CC $<' + $(q)$(CC) $(PLUGIN_INCLUDES) $(PLUGIN_CCFLAGS) -c $< -o $@ + +.PHONY: clean +clean: + $(q)$(RM) -rf $(O)/supp_plugin/ diff --git a/optee/optee_test/host/supp_plugin/include/test_supp_plugin.h b/optee/optee_test/host/supp_plugin/include/test_supp_plugin.h new file mode 100644 index 0000000..2e7e961 --- /dev/null +++ b/optee/optee_test/host/supp_plugin/include/test_supp_plugin.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021 Open Mobile Platform LLC + */ + +#ifndef TEST_SUPP_PLUGIN_H +#define TEST_SUPP_PLUGIN_H + +#define TEST_PLUGIN_UUID { 0xf07bfc66, 0x958c, 0x4a15, \ + { 0x99, 0xc0, 0x26, 0x0e, 0x4e, 0x73, 0x75, 0xdd } } + +#define TEST_PLUGIN_CMD_PING 0 +#define TEST_PLUGIN_CMD_PASS_VALUES 1 +#define TEST_PLUGIN_CMD_WRITE_ARR 2 +#define TEST_PLUGIN_CMD_GET_ARR 3 + +#endif /* TEST_SUPP_PLUGIN_H */ diff --git a/optee/optee_test/host/supp_plugin/test_supp_plugin.c b/optee/optee_test/host/supp_plugin/test_supp_plugin.c new file mode 100644 index 0000000..56e79b1 --- /dev/null +++ b/optee/optee_test/host/supp_plugin/test_supp_plugin.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021, Open Mobile Platform LLC + */ + +#include +#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..0fb5f3a --- /dev/null +++ b/optee/optee_test/host/xtest/CMakeLists.txt @@ -0,0 +1,149 @@ +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 -DOPENSSL_API_COMPAT=10100) + 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 + asym_perf.c + benchmark_1000.c + benchmark_2000.c + clear_storage.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 + symm_cipher_perf.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..1f07f67 --- /dev/null +++ b/optee/optee_test/host/xtest/Makefile @@ -0,0 +1,234 @@ +# 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 -DOPENSSL_API_COMPAT=10100 +LDFLAGS += -lcrypto +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 \ + asym_perf.c \ + benchmark_1000.c \ + benchmark_2000.c \ + clear_storage.c \ + regression_4000.c \ + regression_4100.c \ + regression_5000.c \ + regression_6000.c \ + regression_8000.c \ + regression_8100.c \ + hash_perf.c \ + stats.c \ + symm_cipher_perf.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/crypto_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_gcm_counter_overflow_test_decrypt.h b/optee/optee_test/host/xtest/aes_gcm_counter_overflow_test_decrypt.h new file mode 100644 index 0000000..52c685d --- /dev/null +++ b/optee/optee_test/host/xtest/aes_gcm_counter_overflow_test_decrypt.h @@ -0,0 +1,689 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright 2024 NXP + */ + +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_DECRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, }, + .key_len = 16, + .nonce = (const uint8_t []){ 0xf9, 0x5f, 0xde, 0x4a, 0x75, 0x19, 0x13, 0x20, 0x2a, 0xee, 0xee, 0x32, 0xa0, 0xb5, 0x57, 0x53, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x00, 0x07, 0x8d, 0x10, 0x9d, 0x92, 0x14, 0x3f, 0xcd, 0x5d, 0xf5, 0x67, 0x21, 0xb8, 0x84, 0xfa, 0xc6, 0x4a, 0xc7, 0x76, 0x2c, 0xc0, 0x9e, 0xea, 0x2a, 0x3c, 0x68, 0xe9, 0x2a, 0x17, 0xbd, 0xb5, 0x75, 0xf8, 0x7b, 0xda, 0x18, 0xbe, 0x56, 0x4e, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x15, 0x2a, 0x65, 0x04, 0x5f, 0xe6, 0x74, 0xf9, 0x76, 0x27, 0x42, 0x7a, 0xf5, 0xbe, 0x22, 0xda, }, + .tag_len = 16, + .line = __LINE__, + .id = 77 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_DECRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, }, + .key_len = 16, + .nonce = (const uint8_t []){ 0x7b, 0x95, 0xb8, 0xc3, 0x56, 0x81, 0x0a, 0x84, 0x71, 0x1d, 0x68, 0x15, 0x0a, 0x1b, 0x77, 0x50, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x84, 0xd4, 0xc9, 0xc0, 0x8b, 0x4f, 0x48, 0x28, 0x61, 0xe3, 0xa9, 0xc6, 0xc3, 0x5b, 0xc4, 0xd9, 0x1d, 0xf9, 0x27, 0x37, 0x45, 0x13, 0xbf, 0xd4, 0x9f, 0x43, 0x6b, 0xd7, 0x3f, 0x32, 0x52, 0x85, 0xda, 0xef, 0x4f, 0xf7, 0xe1, 0x3d, 0x46, 0xa6, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x21, 0x3a, 0x3c, 0xb9, 0x38, 0x55, 0xd1, 0x8e, 0x69, 0x33, 0x7e, 0xee, 0x66, 0xae, 0xec, 0x07, }, + .tag_len = 16, + .line = __LINE__, + .id = 78 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_DECRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, }, + .key_len = 16, + .nonce = (const uint8_t []){ 0x1a, 0x55, 0x2e, 0x67, 0xcd, 0xc4, 0xdc, 0x1a, 0x33, 0xb8, 0x24, 0x87, 0x4e, 0xbf, 0x0b, 0xed, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x94, 0x8c, 0xa3, 0x7a, 0x8e, 0x66, 0x49, 0xe8, 0x8a, 0xef, 0xfb, 0x1c, 0x59, 0x8f, 0x36, 0x07, 0x00, 0x77, 0x02, 0x41, 0x7e, 0xa0, 0xe0, 0xbc, 0x3c, 0x60, 0xad, 0x5a, 0x94, 0x98, 0x86, 0xde, 0x96, 0x8c, 0xf5, 0x3e, 0xa6, 0x46, 0x2a, 0xed, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x99, 0xb3, 0x81, 0xbf, 0xa2, 0xaf, 0x97, 0x51, 0xc3, 0x9d, 0x1b, 0x6e, 0x86, 0xd1, 0xbe, 0x6a, }, + .tag_len = 16, + .line = __LINE__, + .id = 79 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_DECRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, }, + .key_len = 16, + .nonce = (const uint8_t []){ 0xdd, 0x9d, 0x0b, 0x4a, 0x0c, 0x3d, 0x68, 0x15, 0x24, 0xbf, 0xfc, 0xa3, 0x1d, 0x90, 0x76, 0x61, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x64, 0xb1, 0x93, 0x14, 0xc3, 0x1a, 0xf4, 0x5a, 0xcc, 0xdf, 0x7e, 0x3c, 0x4d, 0xb7, 0x9f, 0x0d, 0x94, 0x8c, 0xa3, 0x7a, 0x8e, 0x66, 0x49, 0xe8, 0x8a, 0xef, 0xfb, 0x1c, 0x59, 0x8f, 0x36, 0x07, 0x00, 0x77, 0x02, 0x41, 0x7e, 0xa0, 0xe0, 0xbc, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x52, 0x81, 0xef, 0xc7, 0xf1, 0x3a, 0xc8, 0xe1, 0x4c, 0xcf, 0x5d, 0xca, 0x7b, 0xfb, 0xfd, 0xd1, }, + .tag_len = 16, + .line = __LINE__, + .id = 80 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_DECRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, }, + .key_len = 16, + .nonce = (const uint8_t []){ 0x57, 0xc5, 0x64, 0x3c, 0x4e, 0x37, 0xb4, 0x04, 0x1d, 0xb7, 0x94, 0xcf, 0xe8, 0xe1, 0xf0, 0xf4, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x2b, 0xb6, 0x9c, 0x3e, 0x5d, 0x1f, 0x91, 0x81, 0x5c, 0x6b, 0x87, 0xa0, 0xd5, 0xbb, 0xea, 0x71, 0x64, 0xb1, 0x93, 0x14, 0xc3, 0x1a, 0xf4, 0x5a, 0xcc, 0xdf, 0x7e, 0x3c, 0x4d, 0xb7, 0x9f, 0x0d, 0x94, 0x8c, 0xa3, 0x7a, 0x8e, 0x66, 0x49, 0xe8, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0xa3, 0xea, 0x2c, 0x09, 0xee, 0x4f, 0x8c, 0x8a, 0x12, 0xf4, 0x5c, 0xdd, 0xf9, 0xae, 0xff, 0x81, }, + .tag_len = 16, + .line = __LINE__, + .id = 81 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_DECRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, }, + .key_len = 16, + .nonce = (const uint8_t []){ 0x99, 0x82, 0x1c, 0x2d, 0xd5, 0xda, 0xec, 0xde, 0xd0, 0x73, 0x00, 0xf5, 0x77, 0xf7, 0xaf, 0xf1, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x12, 0x7a, 0xf9, 0xb3, 0x9e, 0xcd, 0xfc, 0x57, 0xbb, 0x11, 0xa2, 0x84, 0x7c, 0x7c, 0x2d, 0x3d, 0x8f, 0x93, 0x8f, 0x40, 0xf8, 0x77, 0xe0, 0xc4, 0xaf, 0x37, 0xd0, 0xfe, 0x9a, 0xf0, 0x33, 0x05, 0x2b, 0xd5, 0x37, 0xc4, 0xae, 0x97, 0x8f, 0x60, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x07, 0xeb, 0x2f, 0xe4, 0xa9, 0x58, 0xf8, 0x43, 0x4d, 0x40, 0x68, 0x48, 0x99, 0x50, 0x7c, 0x7c, }, + .tag_len = 16, + .line = __LINE__, + .id = 82 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_DECRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, }, + .key_len = 16, + .nonce = (const uint8_t []){ 0x5e, 0x4a, 0x39, 0x00, 0x14, 0x23, 0x58, 0xd1, 0xc7, 0x74, 0xd8, 0xd1, 0x24, 0xd8, 0xd2, 0x7d, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x0c, 0xf6, 0xae, 0x47, 0x15, 0x6b, 0x14, 0xdc, 0xe0, 0x3c, 0x8a, 0x07, 0xa2, 0xe1, 0x72, 0xb1, 0x12, 0x7a, 0xf9, 0xb3, 0x9e, 0xcd, 0xfc, 0x57, 0xbb, 0x11, 0xa2, 0x84, 0x7c, 0x7c, 0x2d, 0x3d, 0x8f, 0x93, 0x8f, 0x40, 0xf8, 0x77, 0xe0, 0xc4, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0xf1, 0x45, 0xc2, 0xdc, 0xaf, 0x33, 0x9e, 0xed, 0xe4, 0x27, 0xbe, 0x93, 0x43, 0x57, 0xea, 0xc0, }, + .tag_len = 16, + .line = __LINE__, + .id = 83 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_DECRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, }, + .key_len = 16, + .nonce = (const uint8_t []){ 0xd4, 0x12, 0x56, 0x76, 0x56, 0x29, 0x84, 0xc0, 0xfe, 0x7c, 0xb0, 0xbd, 0xd1, 0xa9, 0x54, 0xe8, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0xf0, 0xc6, 0xff, 0xc1, 0x8b, 0xd4, 0x6d, 0xf5, 0x56, 0x91, 0x85, 0xa9, 0xaf, 0xd1, 0x69, 0xeb, 0x0c, 0xf6, 0xae, 0x47, 0x15, 0x6b, 0x14, 0xdc, 0xe0, 0x3c, 0x8a, 0x07, 0xa2, 0xe1, 0x72, 0xb1, 0x12, 0x7a, 0xf9, 0xb3, 0x9e, 0xcd, 0xfc, 0x57, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0xfa, 0xcd, 0x0b, 0xfe, 0x87, 0x01, 0xb7, 0xb4, 0xa2, 0xba, 0x96, 0xd9, 0x8a, 0xf5, 0x2b, 0xd9, }, + .tag_len = 16, + .line = __LINE__, + .id = 84 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_DECRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, }, + .key_len = 16, + .nonce = (const uint8_t []){ 0xb9, 0x7e, 0xc6, 0x2a, 0x5e, 0x59, 0x00, 0xcc, 0xf9, 0xe4, 0xbe, 0x33, 0x2e, 0x33, 0x60, 0x91, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0xd6, 0x92, 0x8e, 0x09, 0x4c, 0x06, 0xe0, 0xa7, 0xc4, 0xdb, 0x42, 0x18, 0x4c, 0xf7, 0x52, 0x9e, 0x95, 0xde, 0x88, 0xb7, 0x67, 0xed, 0xeb, 0xe9, 0xb3, 0x43, 0x00, 0x0b, 0xe3, 0xda, 0xb4, 0x7e, 0xa0, 0x8b, 0x74, 0x42, 0x93, 0xee, 0xd6, 0x98, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0xa0, 0x3e, 0x72, 0x9d, 0xcf, 0xd7, 0xa0, 0x31, 0x55, 0x65, 0x5f, 0xec, 0xe8, 0xaf, 0xfd, 0x7e, }, + .tag_len = 16, + .line = __LINE__, + .id = 85 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_DECRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, }, + .key_len = 16, + .nonce = (const uint8_t []){ 0x7e, 0xb6, 0xe3, 0x07, 0x9f, 0xa0, 0xb4, 0xc3, 0xee, 0xe3, 0x66, 0x17, 0x7d, 0x1c, 0x1d, 0x1d, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0xd8, 0x2c, 0xe5, 0x87, 0x71, 0xbf, 0x64, 0x87, 0x11, 0x6b, 0xf8, 0xe9, 0x64, 0x21, 0x87, 0x7e, 0xd6, 0x92, 0x8e, 0x09, 0x4c, 0x06, 0xe0, 0xa7, 0xc4, 0xdb, 0x42, 0x18, 0x4c, 0xf7, 0x52, 0x9e, 0x95, 0xde, 0x88, 0xb7, 0x67, 0xed, 0xeb, 0xe9, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x1e, 0x43, 0x92, 0x68, 0x28, 0xbc, 0x9a, 0x16, 0x14, 0xc7, 0xb1, 0x63, 0x90, 0x96, 0xc1, 0x95, }, + .tag_len = 16, + .line = __LINE__, + .id = 86 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_DECRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, }, + .key_len = 16, + .nonce = (const uint8_t []){ 0x03, 0x14, 0xfc, 0xd1, 0x0f, 0xdd, 0x67, 0x5d, 0x3c, 0x61, 0x29, 0x62, 0xc9, 0x31, 0xf6, 0x35, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0xa1, 0x97, 0xa3, 0x7a, 0x5d, 0x79, 0x69, 0x70, 0x78, 0x53, 0x6b, 0xc2, 0x7f, 0xe4, 0x6c, 0xd8, 0xd4, 0x75, 0x52, 0x6d, 0x90, 0x44, 0xaa, 0x94, 0xf0, 0x88, 0xa0, 0x54, 0xf8, 0xe3, 0x80, 0xc6, 0x4f, 0x79, 0x41, 0x47, 0x95, 0xc6, 0x14, 0x80, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0xf0, 0x8b, 0xad, 0xdf, 0x0b, 0x52, 0x85, 0xc9, 0x1f, 0xc0, 0x6a, 0x67, 0xfe, 0x47, 0x08, 0xca, }, + .tag_len = 16, + .line = __LINE__, + .id = 87 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_DECRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, }, + .key_len = 16, + .nonce = (const uint8_t []){ 0xc4, 0xdc, 0xd9, 0xfc, 0xce, 0x24, 0xd3, 0x52, 0x2b, 0x66, 0xf1, 0x46, 0x9a, 0x1e, 0x8b, 0xb9, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x14, 0x9f, 0xde, 0x9a, 0xbb, 0xd3, 0xa4, 0x3c, 0x25, 0x48, 0x57, 0x5e, 0x0d, 0xb9, 0xfb, 0x84, 0xa1, 0x97, 0xa3, 0x7a, 0x5d, 0x79, 0x69, 0x70, 0x78, 0x53, 0x6b, 0xc2, 0x7f, 0xe4, 0x6c, 0xd8, 0xd4, 0x75, 0x52, 0x6d, 0x90, 0x44, 0xaa, 0x94, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x62, 0xa4, 0xb6, 0x87, 0x5c, 0x28, 0x83, 0x45, 0xd6, 0xa4, 0x54, 0x39, 0x9e, 0xac, 0x1a, 0xfa, }, + .tag_len = 16, + .line = __LINE__, + .id = 88 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_DECRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, }, + .key_len = 24, + .nonce = (const uint8_t []){ 0x02, 0x9e, 0x0e, 0x77, 0x7d, 0xb0, 0x92, 0xb1, 0x25, 0x35, 0xd0, 0x43, 0x01, 0x2f, 0x09, 0xba, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0xf8, 0x3c, 0xee, 0x46, 0x73, 0x36, 0xe1, 0xa0, 0x9b, 0x75, 0xf2, 0x4e, 0x9b, 0x43, 0x85, 0xc9, 0x9c, 0x13, 0xe6, 0xaf, 0x72, 0x22, 0x56, 0xa6, 0x61, 0x29, 0xec, 0xe9, 0x61, 0xfe, 0x80, 0x3b, 0x16, 0x7b, 0xad, 0x20, 0x6f, 0x50, 0x17, 0xfb, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x09, 0x33, 0x8a, 0x42, 0xf0, 0xac, 0xc1, 0x4f, 0x97, 0xc0, 0x64, 0xf5, 0x2f, 0x5f, 0x16, 0x88, }, + .tag_len = 16, + .line = __LINE__, + .id = 157 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_DECRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, }, + .key_len = 24, + .nonce = (const uint8_t []){ 0xf1, 0xbe, 0x3b, 0x06, 0xb7, 0xfe, 0xac, 0x07, 0xe7, 0xea, 0xb6, 0x29, 0xf5, 0x56, 0x04, 0x7b, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x0b, 0x32, 0xb6, 0x48, 0xa2, 0xc2, 0x8e, 0x9e, 0xdd, 0x7c, 0xee, 0x08, 0xee, 0xeb, 0x90, 0x00, 0x34, 0xca, 0xe7, 0x21, 0x5e, 0x5a, 0xb1, 0xe2, 0x01, 0xbd, 0x2e, 0xed, 0x10, 0x32, 0xc5, 0xa9, 0x78, 0x66, 0xba, 0x58, 0x2a, 0x34, 0x58, 0xa4, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x90, 0xbe, 0x36, 0x06, 0xde, 0x58, 0xbd, 0x77, 0x8f, 0xa5, 0xbe, 0xff, 0x4a, 0x41, 0x02, 0xbd, }, + .tag_len = 16, + .line = __LINE__, + .id = 158 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_DECRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, }, + .key_len = 24, + .nonce = (const uint8_t []){ 0xde, 0x9e, 0xb6, 0x3b, 0x1d, 0xae, 0xd3, 0x21, 0xa1, 0x1b, 0x75, 0x47, 0xcc, 0x9e, 0x22, 0x3c, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x57, 0x5e, 0x2e, 0xce, 0xc2, 0xb3, 0xc7, 0x2d, 0x4e, 0x80, 0x83, 0x0d, 0x0d, 0x85, 0x9a, 0xd9, 0xe4, 0x2c, 0x29, 0xc4, 0xa6, 0x8d, 0x8d, 0x9d, 0x8d, 0x23, 0x43, 0x4d, 0xe2, 0xcd, 0x07, 0x73, 0x3b, 0xe4, 0x9d, 0x62, 0xac, 0x1a, 0xe0, 0x85, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x6e, 0x4d, 0x63, 0x96, 0x12, 0x5a, 0x10, 0xdf, 0x54, 0x43, 0xbd, 0x0c, 0xbc, 0x85, 0x66, 0xd1, }, + .tag_len = 16, + .line = __LINE__, + .id = 159 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_DECRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, }, + .key_len = 24, + .nonce = (const uint8_t []){ 0x40, 0xbb, 0x0a, 0xbe, 0xbc, 0x48, 0x3f, 0xf6, 0xd5, 0x67, 0x12, 0x41, 0xff, 0x5d, 0x66, 0xc6, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x2a, 0x81, 0x88, 0x88, 0xd1, 0xf0, 0x9f, 0x32, 0xaa, 0x7b, 0xee, 0xdd, 0x28, 0x69, 0xb4, 0x46, 0x57, 0x5e, 0x2e, 0xce, 0xc2, 0xb3, 0xc7, 0x2d, 0x4e, 0x80, 0x83, 0x0d, 0x0d, 0x85, 0x9a, 0xd9, 0xe4, 0x2c, 0x29, 0xc4, 0xa6, 0x8d, 0x8d, 0x9d, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0xdc, 0x48, 0x1f, 0x17, 0x25, 0x45, 0x26, 0x8e, 0xff, 0x63, 0xab, 0x04, 0x90, 0x40, 0x3d, 0xc3, }, + .tag_len = 16, + .line = __LINE__, + .id = 160 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_DECRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, }, + .key_len = 24, + .nonce = (const uint8_t []){ 0x20, 0xd5, 0xcf, 0x30, 0x5e, 0x63, 0x0a, 0x8f, 0x49, 0xe3, 0xbb, 0x4b, 0xab, 0x18, 0xab, 0xc9, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x96, 0xd3, 0x6b, 0x79, 0x5f, 0x8e, 0x7e, 0xdf, 0x6a, 0x8e, 0x0d, 0xbc, 0xd2, 0x0d, 0x6c, 0x07, 0x2a, 0x81, 0x88, 0x88, 0xd1, 0xf0, 0x9f, 0x32, 0xaa, 0x7b, 0xee, 0xdd, 0x28, 0x69, 0xb4, 0x46, 0x57, 0x5e, 0x2e, 0xce, 0xc2, 0xb3, 0xc7, 0x2d, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x8a, 0x3a, 0x22, 0xbf, 0x25, 0x92, 0x95, 0x8b, 0x93, 0x02, 0x92, 0xaa, 0x47, 0xf5, 0x90, 0xe8, }, + .tag_len = 16, + .line = __LINE__, + .id = 161 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_DECRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, }, + .key_len = 24, + .nonce = (const uint8_t []){ 0x25, 0x53, 0x58, 0xa7, 0x1a, 0x0e, 0x57, 0x31, 0xf6, 0xdd, 0x6c, 0xe2, 0x8e, 0x15, 0x8a, 0xe6, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0xcf, 0xce, 0x3d, 0x92, 0x0f, 0x0e, 0x01, 0xf0, 0xbb, 0x49, 0xa7, 0x51, 0x95, 0x5b, 0x23, 0x6d, 0x1b, 0x88, 0x7b, 0xae, 0xfd, 0x25, 0xc4, 0x7f, 0x41, 0x30, 0x3c, 0x46, 0xd5, 0xc7, 0xbf, 0x9c, 0xa4, 0xc2, 0xc4, 0x5a, 0x8f, 0x1e, 0x66, 0x56, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x2d, 0xb9, 0xdc, 0x1b, 0x7f, 0xd3, 0x15, 0xdf, 0x1c, 0x95, 0x43, 0x24, 0x32, 0xfc, 0xf4, 0x74, }, + .tag_len = 16, + .line = __LINE__, + .id = 162 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_DECRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, }, + .key_len = 24, + .nonce = (const uint8_t []){ 0xbb, 0x76, 0xe4, 0x22, 0xbb, 0xe8, 0xbb, 0xe6, 0x82, 0xa1, 0x0b, 0xe4, 0xbd, 0xd6, 0xce, 0x1c, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x69, 0xa2, 0x41, 0x69, 0x79, 0x2e, 0x9a, 0x07, 0xf6, 0xe6, 0xf4, 0x73, 0x6f, 0xa9, 0x72, 0xdc, 0xcf, 0xce, 0x3d, 0x92, 0x0f, 0x0e, 0x01, 0xf0, 0xbb, 0x49, 0xa7, 0x51, 0x95, 0x5b, 0x23, 0x6d, 0x1b, 0x88, 0x7b, 0xae, 0xfd, 0x25, 0xc4, 0x7f, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x82, 0xad, 0x96, 0x7f, 0x7a, 0xc1, 0x90, 0x84, 0x35, 0x4f, 0x69, 0xa7, 0x51, 0x44, 0x3f, 0xb2, }, + .tag_len = 16, + .line = __LINE__, + .id = 163 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_DECRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, }, + .key_len = 24, + .nonce = (const uint8_t []){ 0xdb, 0x18, 0x21, 0xac, 0x59, 0xc3, 0x8e, 0x9f, 0x1e, 0x25, 0xa2, 0xee, 0xe9, 0x93, 0x03, 0x13, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x4e, 0x44, 0x17, 0xa8, 0x3b, 0xea, 0xc1, 0xeb, 0x7e, 0x24, 0x45, 0x6a, 0x05, 0xf6, 0xba, 0x55, 0x69, 0xa2, 0x41, 0x69, 0x79, 0x2e, 0x9a, 0x07, 0xf6, 0xe6, 0xf4, 0x73, 0x6f, 0xa9, 0x72, 0xdc, 0xcf, 0xce, 0x3d, 0x92, 0x0f, 0x0e, 0x01, 0xf0, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x47, 0x2d, 0x5d, 0xd5, 0x82, 0xdc, 0x05, 0xef, 0x5f, 0xc4, 0x96, 0xb6, 0x12, 0x02, 0x3c, 0xb2, }, + .tag_len = 16, + .line = __LINE__, + .id = 164 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_DECRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, }, + .key_len = 24, + .nonce = (const uint8_t []){ 0xf7, 0xa0, 0x2e, 0xcc, 0xa0, 0x30, 0x64, 0xb2, 0xef, 0x3c, 0xce, 0x9f, 0xea, 0xb7, 0x9f, 0x07, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x6f, 0x8e, 0x17, 0x4e, 0xfc, 0xa3, 0x09, 0x72, 0x99, 0xf7, 0x84, 0xef, 0xd4, 0xca, 0xff, 0x0b, 0xf1, 0x68, 0xc3, 0xe5, 0x16, 0x5b, 0x9a, 0xd3, 0xd2, 0x00, 0x62, 0x00, 0x98, 0x48, 0x04, 0x4e, 0xef, 0x8f, 0x31, 0xf7, 0xd2, 0xfe, 0xad, 0x05, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0xca, 0xff, 0x72, 0x38, 0x26, 0xdf, 0x15, 0x09, 0x34, 0xae, 0xe3, 0x20, 0x1b, 0xa1, 0x75, 0xe7, }, + .tag_len = 16, + .line = __LINE__, + .id = 165 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_DECRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, }, + .key_len = 24, + .nonce = (const uint8_t []){ 0x69, 0x85, 0x92, 0x49, 0x01, 0xd6, 0x88, 0x65, 0x9b, 0x40, 0xa9, 0x99, 0xd9, 0x74, 0xdb, 0xfd, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0xaf, 0x19, 0x30, 0x90, 0xce, 0x3d, 0x43, 0xa3, 0x88, 0xa1, 0xd2, 0x94, 0xa0, 0x96, 0x16, 0x90, 0x6f, 0x8e, 0x17, 0x4e, 0xfc, 0xa3, 0x09, 0x72, 0x99, 0xf7, 0x84, 0xef, 0xd4, 0xca, 0xff, 0x0b, 0xf1, 0x68, 0xc3, 0xe5, 0x16, 0x5b, 0x9a, 0xd3, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x3b, 0x08, 0x95, 0x8b, 0xe1, 0x28, 0x6c, 0x2b, 0x4a, 0xcb, 0xa0, 0x2b, 0x36, 0x74, 0xad, 0xb2, }, + .tag_len = 16, + .line = __LINE__, + .id = 166 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_DECRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, }, + .key_len = 24, + .nonce = (const uint8_t []){ 0x3f, 0x11, 0x88, 0x54, 0x6c, 0x65, 0xed, 0x0f, 0xc5, 0x5e, 0x75, 0x03, 0x2c, 0x68, 0xee, 0x44, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x5d, 0xec, 0xcf, 0x83, 0x8b, 0x2c, 0xf5, 0xf8, 0x69, 0xc9, 0x0d, 0x2a, 0x61, 0x11, 0x60, 0xb1, 0xe5, 0x78, 0xab, 0x81, 0x21, 0xb9, 0x37, 0x35, 0xcb, 0xa4, 0xa1, 0x93, 0x06, 0x47, 0xb8, 0xc4, 0xc8, 0x4b, 0xf7, 0x76, 0x33, 0x3e, 0xe4, 0x5a, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0xc1, 0x4d, 0x52, 0x20, 0x8f, 0x0f, 0x51, 0xb8, 0x16, 0xa4, 0x89, 0x71, 0xea, 0xf8, 0xff, 0x7e, }, + .tag_len = 16, + .line = __LINE__, + .id = 167 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_DECRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, }, + .key_len = 24, + .nonce = (const uint8_t []){ 0xa1, 0x34, 0x34, 0xd1, 0xcd, 0x83, 0x01, 0xd8, 0xb1, 0x22, 0x12, 0x05, 0x1f, 0xab, 0xaa, 0xbe, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0xd2, 0xca, 0xe1, 0x68, 0x4a, 0xa4, 0x07, 0xa1, 0x3a, 0x2e, 0x2d, 0xa5, 0x35, 0x7e, 0x29, 0xf5, 0x5d, 0xec, 0xcf, 0x83, 0x8b, 0x2c, 0xf5, 0xf8, 0x69, 0xc9, 0x0d, 0x2a, 0x61, 0x11, 0x60, 0xb1, 0xe5, 0x78, 0xab, 0x81, 0x21, 0xb9, 0x37, 0x35, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0xea, 0x2d, 0x01, 0x80, 0x99, 0xcd, 0x79, 0x25, 0xc5, 0x07, 0xce, 0xf0, 0xce, 0xdd, 0xb0, 0xae, }, + .tag_len = 16, + .line = __LINE__, + .id = 168 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_DECRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, 0x98, 0xa9, 0xba, 0xcb, 0xdc, 0xed, 0xfe, 0x0f, }, + .key_len = 32, + .nonce = (const uint8_t []){ 0x5c, 0x2e, 0xa9, 0xb6, 0x95, 0xfc, 0xf6, 0xe2, 0x64, 0xb9, 0x60, 0x74, 0xd6, 0xbf, 0xa5, 0x72, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x28, 0xe1, 0xc5, 0x23, 0x2f, 0x4e, 0xe8, 0x16, 0x1d, 0xbe, 0x4c, 0x03, 0x63, 0x09, 0xe0, 0xb3, 0x25, 0x4e, 0x92, 0x12, 0xbe, 0xf0, 0xa9, 0x34, 0x31, 0xce, 0x5e, 0x56, 0x04, 0xc8, 0xf6, 0xa7, 0x3c, 0x18, 0xa3, 0x18, 0x30, 0x18, 0xb7, 0x70, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0xd5, 0x80, 0x8a, 0x1b, 0xd1, 0x1a, 0x01, 0x12, 0x9b, 0xf3, 0xc6, 0x91, 0x9a, 0xff, 0x23, 0x39, }, + .tag_len = 16, + .line = __LINE__, + .id = 240 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_DECRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, 0x98, 0xa9, 0xba, 0xcb, 0xdc, 0xed, 0xfe, 0x0f, }, + .key_len = 32, + .nonce = (const uint8_t []){ 0x57, 0xb3, 0xa8, 0x1f, 0x2c, 0x36, 0xb6, 0xb0, 0x65, 0x77, 0xca, 0x0f, 0xba, 0xb8, 0xfa, 0x8e, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0xcc, 0xee, 0xbe, 0xb4, 0xfe, 0x4c, 0xd9, 0x0c, 0x51, 0x4e, 0x52, 0xd2, 0x32, 0x7a, 0x2e, 0xcd, 0x75, 0x39, 0x36, 0x61, 0x00, 0x6c, 0xf2, 0x47, 0x6d, 0x86, 0x20, 0x14, 0x9a, 0xef, 0x3d, 0x1c, 0xdc, 0xe4, 0x91, 0xff, 0xf3, 0xe7, 0xa7, 0xa3, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x81, 0x32, 0xe8, 0x65, 0xb6, 0x9d, 0x64, 0xef, 0x37, 0xdb, 0x26, 0x1f, 0x80, 0xcb, 0xbe, 0x24, }, + .tag_len = 16, + .line = __LINE__, + .id = 241 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_DECRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, 0x98, 0xa9, 0xba, 0xcb, 0xdc, 0xed, 0xfe, 0x0f, }, + .key_len = 32, + .nonce = (const uint8_t []){ 0xce, 0x20, 0xa7, 0xe8, 0x70, 0x69, 0x6a, 0x5e, 0x68, 0x53, 0x3c, 0x46, 0x5b, 0xad, 0x2b, 0xa1, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x4f, 0x43, 0x50, 0x56, 0x5d, 0x91, 0xd9, 0xaa, 0x8c, 0x5f, 0x40, 0x48, 0x55, 0x04, 0x92, 0xad, 0x6d, 0x6f, 0xda, 0xbf, 0x66, 0xda, 0x5d, 0x1e, 0x2a, 0xf7, 0xbf, 0xe1, 0xa8, 0xaa, 0xda, 0xa0, 0xba, 0xa3, 0xde, 0x38, 0xa4, 0x1d, 0x97, 0x13, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x15, 0x5d, 0xa6, 0x44, 0x1e, 0xc0, 0x71, 0xef, 0x2d, 0x8e, 0x6c, 0xff, 0xba, 0xcc, 0x1c, 0x7c, }, + .tag_len = 16, + .line = __LINE__, + .id = 242 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_DECRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, 0x98, 0xa9, 0xba, 0xcb, 0xdc, 0xed, 0xfe, 0x0f, }, + .key_len = 32, + .nonce = (const uint8_t []){ 0x91, 0x8e, 0x3c, 0x19, 0xdb, 0xdf, 0xee, 0x2d, 0xb1, 0x81, 0x56, 0xc5, 0xb9, 0x3f, 0x3d, 0x75, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x83, 0x16, 0xa5, 0x31, 0x67, 0xb6, 0xde, 0x1a, 0x75, 0x75, 0x70, 0x06, 0x93, 0xff, 0xef, 0x27, 0x4f, 0x43, 0x50, 0x56, 0x5d, 0x91, 0xd9, 0xaa, 0x8c, 0x5f, 0x40, 0x48, 0x55, 0x04, 0x92, 0xad, 0x6d, 0x6f, 0xda, 0xbf, 0x66, 0xda, 0x5d, 0x1e, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x6c, 0x57, 0x4a, 0xa6, 0xa2, 0x49, 0x0c, 0xc3, 0xb2, 0xf2, 0xf8, 0xf0, 0xff, 0xbc, 0x56, 0xc4, }, + .tag_len = 16, + .line = __LINE__, + .id = 243 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_DECRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, 0x98, 0xa9, 0xba, 0xcb, 0xdc, 0xed, 0xfe, 0x0f, }, + .key_len = 32, + .nonce = (const uint8_t []){ 0x71, 0x7d, 0x90, 0x0b, 0x27, 0x04, 0x62, 0xb9, 0xdb, 0xf7, 0xe9, 0x41, 0x9e, 0x89, 0x06, 0x09, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x51, 0x75, 0x92, 0x75, 0x13, 0xe7, 0x51, 0xeb, 0x30, 0x9f, 0x45, 0xbc, 0x2e, 0xf2, 0x25, 0xf2, 0x83, 0x16, 0xa5, 0x31, 0x67, 0xb6, 0xde, 0x1a, 0x75, 0x75, 0x70, 0x06, 0x93, 0xff, 0xef, 0x27, 0x4f, 0x43, 0x50, 0x56, 0x5d, 0x91, 0xd9, 0xaa, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x80, 0x82, 0xa7, 0x61, 0xe1, 0xd7, 0x55, 0x34, 0x4b, 0xf2, 0x96, 0x22, 0x14, 0x4e, 0x7d, 0x39, }, + .tag_len = 16, + .line = __LINE__, + .id = 244 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_DECRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, 0x98, 0xa9, 0xba, 0xcb, 0xdc, 0xed, 0xfe, 0x0f, }, + .key_len = 32, + .nonce = (const uint8_t []){ 0xec, 0xd5, 0x21, 0x20, 0xaf, 0x24, 0x0e, 0x9b, 0x4b, 0xf3, 0xb9, 0xd1, 0xee, 0xb4, 0x94, 0x34, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x36, 0xb3, 0xfb, 0xec, 0xd0, 0x91, 0x78, 0xd0, 0x45, 0x27, 0xfb, 0x37, 0x54, 0x4f, 0x55, 0x79, 0xd2, 0x0d, 0x60, 0xa4, 0x12, 0x66, 0xf6, 0x85, 0xc4, 0x80, 0x98, 0xe1, 0xa5, 0x28, 0x04, 0xca, 0x38, 0x7d, 0x90, 0x70, 0x9d, 0x32, 0x68, 0xdd, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x03, 0x3e, 0x0e, 0xf2, 0x95, 0x3e, 0xbf, 0xd8, 0x42, 0x57, 0x37, 0xc7, 0xd3, 0x93, 0xf8, 0x9a, }, + .tag_len = 16, + .line = __LINE__, + .id = 245 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_DECRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, 0x98, 0xa9, 0xba, 0xcb, 0xdc, 0xed, 0xfe, 0x0f, }, + .key_len = 32, + .nonce = (const uint8_t []){ 0xb3, 0x7b, 0xba, 0xd1, 0x04, 0x92, 0x8a, 0xe8, 0x92, 0x21, 0xd3, 0x52, 0x0c, 0x26, 0x82, 0xe0, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x16, 0x92, 0x9b, 0x77, 0x30, 0x51, 0xf1, 0x2b, 0x0a, 0xda, 0xc9, 0x5f, 0x65, 0xe2, 0x1a, 0x7f, 0x36, 0xb3, 0xfb, 0xec, 0xd0, 0x91, 0x78, 0xd0, 0x45, 0x27, 0xfb, 0x37, 0x54, 0x4f, 0x55, 0x79, 0xd2, 0x0d, 0x60, 0xa4, 0x12, 0x66, 0xf6, 0x85, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0xca, 0x44, 0x8b, 0xb7, 0xe5, 0x2e, 0x89, 0x7e, 0xca, 0x23, 0x4e, 0xf3, 0x43, 0xd0, 0x57, 0xd0, }, + .tag_len = 16, + .line = __LINE__, + .id = 246 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_DECRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, 0x98, 0xa9, 0xba, 0xcb, 0xdc, 0xed, 0xfe, 0x0f, }, + .key_len = 32, + .nonce = (const uint8_t []){ 0x53, 0x88, 0x16, 0xc3, 0xf8, 0x49, 0x06, 0x7c, 0xf8, 0x57, 0x6c, 0xd6, 0x2b, 0x90, 0xb9, 0x9c, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x6d, 0x3f, 0xae, 0xfa, 0xf6, 0x91, 0xd5, 0x81, 0x63, 0x84, 0x6f, 0x8d, 0x4b, 0x9f, 0xfd, 0x59, 0x16, 0x92, 0x9b, 0x77, 0x30, 0x51, 0xf1, 0x2b, 0x0a, 0xda, 0xc9, 0x5f, 0x65, 0xe2, 0x1a, 0x7f, 0x36, 0xb3, 0xfb, 0xec, 0xd0, 0x91, 0x78, 0xd0, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x84, 0xf4, 0x97, 0x40, 0xe6, 0x75, 0x7f, 0x63, 0xdd, 0x0d, 0xf7, 0xcb, 0x76, 0x56, 0xd0, 0xef, }, + .tag_len = 16, + .line = __LINE__, + .id = 247 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_DECRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, 0x98, 0xa9, 0xba, 0xcb, 0xdc, 0xed, 0xfe, 0x0f, }, + .key_len = 32, + .nonce = (const uint8_t []){ 0xd1, 0x0e, 0x63, 0x19, 0x43, 0xcd, 0x3b, 0xda, 0xba, 0xba, 0xb2, 0xbb, 0xd1, 0x39, 0x51, 0xc0, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0xd6, 0x01, 0x96, 0xc2, 0xd1, 0x4f, 0xcf, 0x30, 0xc0, 0x99, 0x1d, 0x27, 0x21, 0xdd, 0xc5, 0x2d, 0x38, 0x5f, 0x40, 0x7a, 0x16, 0x69, 0x1d, 0xad, 0xe8, 0x2c, 0x90, 0x23, 0xc8, 0x55, 0xfd, 0x8e, 0x2e, 0x8f, 0xbb, 0x56, 0x21, 0x02, 0xf0, 0x18, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x87, 0x7e, 0x15, 0xd9, 0x88, 0x9e, 0x69, 0xa9, 0x9f, 0xcc, 0x6d, 0x72, 0x74, 0x65, 0xc3, 0x91, }, + .tag_len = 16, + .line = __LINE__, + .id = 248 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_DECRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, 0x98, 0xa9, 0xba, 0xcb, 0xdc, 0xed, 0xfe, 0x0f, }, + .key_len = 32, + .nonce = (const uint8_t []){ 0x8e, 0xa0, 0xf8, 0xe8, 0xe8, 0x7b, 0xbf, 0xa9, 0x63, 0x68, 0xd8, 0x38, 0x33, 0xab, 0x47, 0x14, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x94, 0x8f, 0xbc, 0xec, 0xa1, 0x2a, 0x6e, 0x4f, 0xab, 0xb7, 0x9b, 0x6d, 0x96, 0x5e, 0x33, 0x6f, 0xd6, 0x01, 0x96, 0xc2, 0xd1, 0x4f, 0xcf, 0x30, 0xc0, 0x99, 0x1d, 0x27, 0x21, 0xdd, 0xc5, 0x2d, 0x38, 0x5f, 0x40, 0x7a, 0x16, 0x69, 0x1d, 0xad, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0xcd, 0x57, 0x57, 0x62, 0x69, 0x45, 0x97, 0x6b, 0xa9, 0xf0, 0x26, 0x4b, 0xd6, 0xbe, 0xe8, 0x94, }, + .tag_len = 16, + .line = __LINE__, + .id = 249 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_DECRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, 0x98, 0xa9, 0xba, 0xcb, 0xdc, 0xed, 0xfe, 0x0f, }, + .key_len = 32, + .nonce = (const uint8_t []){ 0x7b, 0x2d, 0xf4, 0xfb, 0xed, 0x1d, 0xe2, 0x72, 0x7e, 0xb2, 0x48, 0x98, 0xe5, 0xde, 0xab, 0xb9, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0xa1, 0xa0, 0x12, 0x06, 0x60, 0xff, 0x52, 0xe6, 0xb1, 0x70, 0x0b, 0x12, 0xc5, 0x4d, 0x2d, 0x33, 0xb9, 0x4b, 0x00, 0xcd, 0x78, 0x82, 0xd8, 0x85, 0x7d, 0x84, 0xe6, 0xe1, 0x83, 0xa1, 0xde, 0xa6, 0xee, 0x85, 0xa7, 0xda, 0x84, 0xfb, 0xc3, 0x5d, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0xb0, 0x15, 0xd7, 0x2d, 0xa6, 0x2c, 0x81, 0xcb, 0x4d, 0x26, 0x72, 0x53, 0xb2, 0x0d, 0xb9, 0xe5, }, + .tag_len = 16, + .line = __LINE__, + .id = 250 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_DECRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, 0x98, 0xa9, 0xba, 0xcb, 0xdc, 0xed, 0xfe, 0x0f, }, + .key_len = 32, + .nonce = (const uint8_t []){ 0x24, 0x83, 0x6f, 0x0a, 0x46, 0xab, 0x66, 0x01, 0xa7, 0x60, 0x22, 0x1b, 0x07, 0x4c, 0xbd, 0x6d, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x5e, 0x34, 0x34, 0xb4, 0x5e, 0xdb, 0xf0, 0xd1, 0xf6, 0xe0, 0x2d, 0x11, 0x44, 0xdb, 0xf8, 0x67, 0xa1, 0xa0, 0x12, 0x06, 0x60, 0xff, 0x52, 0xe6, 0xb1, 0x70, 0x0b, 0x12, 0xc5, 0x4d, 0x2d, 0x33, 0xb9, 0x4b, 0x00, 0xcd, 0x78, 0x82, 0xd8, 0x85, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0xee, 0x74, 0xcc, 0xb3, 0x0d, 0x64, 0x9e, 0xbf, 0x69, 0x16, 0xd0, 0x5a, 0x7d, 0xbe, 0x56, 0x96, }, + .tag_len = 16, + .line = __LINE__, + .id = 251 +}, diff --git a/optee/optee_test/host/xtest/aes_gcm_counter_overflow_test_encrypt.h b/optee/optee_test/host/xtest/aes_gcm_counter_overflow_test_encrypt.h new file mode 100644 index 0000000..a2237a7 --- /dev/null +++ b/optee/optee_test/host/xtest/aes_gcm_counter_overflow_test_encrypt.h @@ -0,0 +1,689 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright 2024 NXP + */ + +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_ENCRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, }, + .key_len = 16, + .nonce = (const uint8_t []){ 0xf9, 0x5f, 0xde, 0x4a, 0x75, 0x19, 0x13, 0x20, 0x2a, 0xee, 0xee, 0x32, 0xa0, 0xb5, 0x57, 0x53, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x00, 0x07, 0x8d, 0x10, 0x9d, 0x92, 0x14, 0x3f, 0xcd, 0x5d, 0xf5, 0x67, 0x21, 0xb8, 0x84, 0xfa, 0xc6, 0x4a, 0xc7, 0x76, 0x2c, 0xc0, 0x9e, 0xea, 0x2a, 0x3c, 0x68, 0xe9, 0x2a, 0x17, 0xbd, 0xb5, 0x75, 0xf8, 0x7b, 0xda, 0x18, 0xbe, 0x56, 0x4e, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x15, 0x2a, 0x65, 0x04, 0x5f, 0xe6, 0x74, 0xf9, 0x76, 0x27, 0x42, 0x7a, 0xf5, 0xbe, 0x22, 0xda, }, + .tag_len = 16, + .line = __LINE__, + .id = 77 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_ENCRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, }, + .key_len = 16, + .nonce = (const uint8_t []){ 0x7b, 0x95, 0xb8, 0xc3, 0x56, 0x81, 0x0a, 0x84, 0x71, 0x1d, 0x68, 0x15, 0x0a, 0x1b, 0x77, 0x50, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x84, 0xd4, 0xc9, 0xc0, 0x8b, 0x4f, 0x48, 0x28, 0x61, 0xe3, 0xa9, 0xc6, 0xc3, 0x5b, 0xc4, 0xd9, 0x1d, 0xf9, 0x27, 0x37, 0x45, 0x13, 0xbf, 0xd4, 0x9f, 0x43, 0x6b, 0xd7, 0x3f, 0x32, 0x52, 0x85, 0xda, 0xef, 0x4f, 0xf7, 0xe1, 0x3d, 0x46, 0xa6, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x21, 0x3a, 0x3c, 0xb9, 0x38, 0x55, 0xd1, 0x8e, 0x69, 0x33, 0x7e, 0xee, 0x66, 0xae, 0xec, 0x07, }, + .tag_len = 16, + .line = __LINE__, + .id = 78 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_ENCRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, }, + .key_len = 16, + .nonce = (const uint8_t []){ 0x1a, 0x55, 0x2e, 0x67, 0xcd, 0xc4, 0xdc, 0x1a, 0x33, 0xb8, 0x24, 0x87, 0x4e, 0xbf, 0x0b, 0xed, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x94, 0x8c, 0xa3, 0x7a, 0x8e, 0x66, 0x49, 0xe8, 0x8a, 0xef, 0xfb, 0x1c, 0x59, 0x8f, 0x36, 0x07, 0x00, 0x77, 0x02, 0x41, 0x7e, 0xa0, 0xe0, 0xbc, 0x3c, 0x60, 0xad, 0x5a, 0x94, 0x98, 0x86, 0xde, 0x96, 0x8c, 0xf5, 0x3e, 0xa6, 0x46, 0x2a, 0xed, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x99, 0xb3, 0x81, 0xbf, 0xa2, 0xaf, 0x97, 0x51, 0xc3, 0x9d, 0x1b, 0x6e, 0x86, 0xd1, 0xbe, 0x6a, }, + .tag_len = 16, + .line = __LINE__, + .id = 79 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_ENCRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, }, + .key_len = 16, + .nonce = (const uint8_t []){ 0xdd, 0x9d, 0x0b, 0x4a, 0x0c, 0x3d, 0x68, 0x15, 0x24, 0xbf, 0xfc, 0xa3, 0x1d, 0x90, 0x76, 0x61, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x64, 0xb1, 0x93, 0x14, 0xc3, 0x1a, 0xf4, 0x5a, 0xcc, 0xdf, 0x7e, 0x3c, 0x4d, 0xb7, 0x9f, 0x0d, 0x94, 0x8c, 0xa3, 0x7a, 0x8e, 0x66, 0x49, 0xe8, 0x8a, 0xef, 0xfb, 0x1c, 0x59, 0x8f, 0x36, 0x07, 0x00, 0x77, 0x02, 0x41, 0x7e, 0xa0, 0xe0, 0xbc, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x52, 0x81, 0xef, 0xc7, 0xf1, 0x3a, 0xc8, 0xe1, 0x4c, 0xcf, 0x5d, 0xca, 0x7b, 0xfb, 0xfd, 0xd1, }, + .tag_len = 16, + .line = __LINE__, + .id = 80 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_ENCRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, }, + .key_len = 16, + .nonce = (const uint8_t []){ 0x57, 0xc5, 0x64, 0x3c, 0x4e, 0x37, 0xb4, 0x04, 0x1d, 0xb7, 0x94, 0xcf, 0xe8, 0xe1, 0xf0, 0xf4, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x2b, 0xb6, 0x9c, 0x3e, 0x5d, 0x1f, 0x91, 0x81, 0x5c, 0x6b, 0x87, 0xa0, 0xd5, 0xbb, 0xea, 0x71, 0x64, 0xb1, 0x93, 0x14, 0xc3, 0x1a, 0xf4, 0x5a, 0xcc, 0xdf, 0x7e, 0x3c, 0x4d, 0xb7, 0x9f, 0x0d, 0x94, 0x8c, 0xa3, 0x7a, 0x8e, 0x66, 0x49, 0xe8, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0xa3, 0xea, 0x2c, 0x09, 0xee, 0x4f, 0x8c, 0x8a, 0x12, 0xf4, 0x5c, 0xdd, 0xf9, 0xae, 0xff, 0x81, }, + .tag_len = 16, + .line = __LINE__, + .id = 81 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_ENCRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, }, + .key_len = 16, + .nonce = (const uint8_t []){ 0x99, 0x82, 0x1c, 0x2d, 0xd5, 0xda, 0xec, 0xde, 0xd0, 0x73, 0x00, 0xf5, 0x77, 0xf7, 0xaf, 0xf1, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x12, 0x7a, 0xf9, 0xb3, 0x9e, 0xcd, 0xfc, 0x57, 0xbb, 0x11, 0xa2, 0x84, 0x7c, 0x7c, 0x2d, 0x3d, 0x8f, 0x93, 0x8f, 0x40, 0xf8, 0x77, 0xe0, 0xc4, 0xaf, 0x37, 0xd0, 0xfe, 0x9a, 0xf0, 0x33, 0x05, 0x2b, 0xd5, 0x37, 0xc4, 0xae, 0x97, 0x8f, 0x60, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x07, 0xeb, 0x2f, 0xe4, 0xa9, 0x58, 0xf8, 0x43, 0x4d, 0x40, 0x68, 0x48, 0x99, 0x50, 0x7c, 0x7c, }, + .tag_len = 16, + .line = __LINE__, + .id = 82 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_ENCRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, }, + .key_len = 16, + .nonce = (const uint8_t []){ 0x5e, 0x4a, 0x39, 0x00, 0x14, 0x23, 0x58, 0xd1, 0xc7, 0x74, 0xd8, 0xd1, 0x24, 0xd8, 0xd2, 0x7d, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x0c, 0xf6, 0xae, 0x47, 0x15, 0x6b, 0x14, 0xdc, 0xe0, 0x3c, 0x8a, 0x07, 0xa2, 0xe1, 0x72, 0xb1, 0x12, 0x7a, 0xf9, 0xb3, 0x9e, 0xcd, 0xfc, 0x57, 0xbb, 0x11, 0xa2, 0x84, 0x7c, 0x7c, 0x2d, 0x3d, 0x8f, 0x93, 0x8f, 0x40, 0xf8, 0x77, 0xe0, 0xc4, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0xf1, 0x45, 0xc2, 0xdc, 0xaf, 0x33, 0x9e, 0xed, 0xe4, 0x27, 0xbe, 0x93, 0x43, 0x57, 0xea, 0xc0, }, + .tag_len = 16, + .line = __LINE__, + .id = 83 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_ENCRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, }, + .key_len = 16, + .nonce = (const uint8_t []){ 0xd4, 0x12, 0x56, 0x76, 0x56, 0x29, 0x84, 0xc0, 0xfe, 0x7c, 0xb0, 0xbd, 0xd1, 0xa9, 0x54, 0xe8, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0xf0, 0xc6, 0xff, 0xc1, 0x8b, 0xd4, 0x6d, 0xf5, 0x56, 0x91, 0x85, 0xa9, 0xaf, 0xd1, 0x69, 0xeb, 0x0c, 0xf6, 0xae, 0x47, 0x15, 0x6b, 0x14, 0xdc, 0xe0, 0x3c, 0x8a, 0x07, 0xa2, 0xe1, 0x72, 0xb1, 0x12, 0x7a, 0xf9, 0xb3, 0x9e, 0xcd, 0xfc, 0x57, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0xfa, 0xcd, 0x0b, 0xfe, 0x87, 0x01, 0xb7, 0xb4, 0xa2, 0xba, 0x96, 0xd9, 0x8a, 0xf5, 0x2b, 0xd9, }, + .tag_len = 16, + .line = __LINE__, + .id = 84 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_ENCRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, }, + .key_len = 16, + .nonce = (const uint8_t []){ 0xb9, 0x7e, 0xc6, 0x2a, 0x5e, 0x59, 0x00, 0xcc, 0xf9, 0xe4, 0xbe, 0x33, 0x2e, 0x33, 0x60, 0x91, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0xd6, 0x92, 0x8e, 0x09, 0x4c, 0x06, 0xe0, 0xa7, 0xc4, 0xdb, 0x42, 0x18, 0x4c, 0xf7, 0x52, 0x9e, 0x95, 0xde, 0x88, 0xb7, 0x67, 0xed, 0xeb, 0xe9, 0xb3, 0x43, 0x00, 0x0b, 0xe3, 0xda, 0xb4, 0x7e, 0xa0, 0x8b, 0x74, 0x42, 0x93, 0xee, 0xd6, 0x98, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0xa0, 0x3e, 0x72, 0x9d, 0xcf, 0xd7, 0xa0, 0x31, 0x55, 0x65, 0x5f, 0xec, 0xe8, 0xaf, 0xfd, 0x7e, }, + .tag_len = 16, + .line = __LINE__, + .id = 85 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_ENCRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, }, + .key_len = 16, + .nonce = (const uint8_t []){ 0x7e, 0xb6, 0xe3, 0x07, 0x9f, 0xa0, 0xb4, 0xc3, 0xee, 0xe3, 0x66, 0x17, 0x7d, 0x1c, 0x1d, 0x1d, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0xd8, 0x2c, 0xe5, 0x87, 0x71, 0xbf, 0x64, 0x87, 0x11, 0x6b, 0xf8, 0xe9, 0x64, 0x21, 0x87, 0x7e, 0xd6, 0x92, 0x8e, 0x09, 0x4c, 0x06, 0xe0, 0xa7, 0xc4, 0xdb, 0x42, 0x18, 0x4c, 0xf7, 0x52, 0x9e, 0x95, 0xde, 0x88, 0xb7, 0x67, 0xed, 0xeb, 0xe9, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x1e, 0x43, 0x92, 0x68, 0x28, 0xbc, 0x9a, 0x16, 0x14, 0xc7, 0xb1, 0x63, 0x90, 0x96, 0xc1, 0x95, }, + .tag_len = 16, + .line = __LINE__, + .id = 86 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_ENCRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, }, + .key_len = 16, + .nonce = (const uint8_t []){ 0x03, 0x14, 0xfc, 0xd1, 0x0f, 0xdd, 0x67, 0x5d, 0x3c, 0x61, 0x29, 0x62, 0xc9, 0x31, 0xf6, 0x35, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0xa1, 0x97, 0xa3, 0x7a, 0x5d, 0x79, 0x69, 0x70, 0x78, 0x53, 0x6b, 0xc2, 0x7f, 0xe4, 0x6c, 0xd8, 0xd4, 0x75, 0x52, 0x6d, 0x90, 0x44, 0xaa, 0x94, 0xf0, 0x88, 0xa0, 0x54, 0xf8, 0xe3, 0x80, 0xc6, 0x4f, 0x79, 0x41, 0x47, 0x95, 0xc6, 0x14, 0x80, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0xf0, 0x8b, 0xad, 0xdf, 0x0b, 0x52, 0x85, 0xc9, 0x1f, 0xc0, 0x6a, 0x67, 0xfe, 0x47, 0x08, 0xca, }, + .tag_len = 16, + .line = __LINE__, + .id = 87 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_ENCRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, }, + .key_len = 16, + .nonce = (const uint8_t []){ 0xc4, 0xdc, 0xd9, 0xfc, 0xce, 0x24, 0xd3, 0x52, 0x2b, 0x66, 0xf1, 0x46, 0x9a, 0x1e, 0x8b, 0xb9, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x14, 0x9f, 0xde, 0x9a, 0xbb, 0xd3, 0xa4, 0x3c, 0x25, 0x48, 0x57, 0x5e, 0x0d, 0xb9, 0xfb, 0x84, 0xa1, 0x97, 0xa3, 0x7a, 0x5d, 0x79, 0x69, 0x70, 0x78, 0x53, 0x6b, 0xc2, 0x7f, 0xe4, 0x6c, 0xd8, 0xd4, 0x75, 0x52, 0x6d, 0x90, 0x44, 0xaa, 0x94, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x62, 0xa4, 0xb6, 0x87, 0x5c, 0x28, 0x83, 0x45, 0xd6, 0xa4, 0x54, 0x39, 0x9e, 0xac, 0x1a, 0xfa, }, + .tag_len = 16, + .line = __LINE__, + .id = 88 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_ENCRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, }, + .key_len = 24, + .nonce = (const uint8_t []){ 0x02, 0x9e, 0x0e, 0x77, 0x7d, 0xb0, 0x92, 0xb1, 0x25, 0x35, 0xd0, 0x43, 0x01, 0x2f, 0x09, 0xba, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0xf8, 0x3c, 0xee, 0x46, 0x73, 0x36, 0xe1, 0xa0, 0x9b, 0x75, 0xf2, 0x4e, 0x9b, 0x43, 0x85, 0xc9, 0x9c, 0x13, 0xe6, 0xaf, 0x72, 0x22, 0x56, 0xa6, 0x61, 0x29, 0xec, 0xe9, 0x61, 0xfe, 0x80, 0x3b, 0x16, 0x7b, 0xad, 0x20, 0x6f, 0x50, 0x17, 0xfb, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x09, 0x33, 0x8a, 0x42, 0xf0, 0xac, 0xc1, 0x4f, 0x97, 0xc0, 0x64, 0xf5, 0x2f, 0x5f, 0x16, 0x88, }, + .tag_len = 16, + .line = __LINE__, + .id = 157 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_ENCRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, }, + .key_len = 24, + .nonce = (const uint8_t []){ 0xf1, 0xbe, 0x3b, 0x06, 0xb7, 0xfe, 0xac, 0x07, 0xe7, 0xea, 0xb6, 0x29, 0xf5, 0x56, 0x04, 0x7b, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x0b, 0x32, 0xb6, 0x48, 0xa2, 0xc2, 0x8e, 0x9e, 0xdd, 0x7c, 0xee, 0x08, 0xee, 0xeb, 0x90, 0x00, 0x34, 0xca, 0xe7, 0x21, 0x5e, 0x5a, 0xb1, 0xe2, 0x01, 0xbd, 0x2e, 0xed, 0x10, 0x32, 0xc5, 0xa9, 0x78, 0x66, 0xba, 0x58, 0x2a, 0x34, 0x58, 0xa4, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x90, 0xbe, 0x36, 0x06, 0xde, 0x58, 0xbd, 0x77, 0x8f, 0xa5, 0xbe, 0xff, 0x4a, 0x41, 0x02, 0xbd, }, + .tag_len = 16, + .line = __LINE__, + .id = 158 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_ENCRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, }, + .key_len = 24, + .nonce = (const uint8_t []){ 0xde, 0x9e, 0xb6, 0x3b, 0x1d, 0xae, 0xd3, 0x21, 0xa1, 0x1b, 0x75, 0x47, 0xcc, 0x9e, 0x22, 0x3c, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x57, 0x5e, 0x2e, 0xce, 0xc2, 0xb3, 0xc7, 0x2d, 0x4e, 0x80, 0x83, 0x0d, 0x0d, 0x85, 0x9a, 0xd9, 0xe4, 0x2c, 0x29, 0xc4, 0xa6, 0x8d, 0x8d, 0x9d, 0x8d, 0x23, 0x43, 0x4d, 0xe2, 0xcd, 0x07, 0x73, 0x3b, 0xe4, 0x9d, 0x62, 0xac, 0x1a, 0xe0, 0x85, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x6e, 0x4d, 0x63, 0x96, 0x12, 0x5a, 0x10, 0xdf, 0x54, 0x43, 0xbd, 0x0c, 0xbc, 0x85, 0x66, 0xd1, }, + .tag_len = 16, + .line = __LINE__, + .id = 159 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_ENCRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, }, + .key_len = 24, + .nonce = (const uint8_t []){ 0x40, 0xbb, 0x0a, 0xbe, 0xbc, 0x48, 0x3f, 0xf6, 0xd5, 0x67, 0x12, 0x41, 0xff, 0x5d, 0x66, 0xc6, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x2a, 0x81, 0x88, 0x88, 0xd1, 0xf0, 0x9f, 0x32, 0xaa, 0x7b, 0xee, 0xdd, 0x28, 0x69, 0xb4, 0x46, 0x57, 0x5e, 0x2e, 0xce, 0xc2, 0xb3, 0xc7, 0x2d, 0x4e, 0x80, 0x83, 0x0d, 0x0d, 0x85, 0x9a, 0xd9, 0xe4, 0x2c, 0x29, 0xc4, 0xa6, 0x8d, 0x8d, 0x9d, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0xdc, 0x48, 0x1f, 0x17, 0x25, 0x45, 0x26, 0x8e, 0xff, 0x63, 0xab, 0x04, 0x90, 0x40, 0x3d, 0xc3, }, + .tag_len = 16, + .line = __LINE__, + .id = 160 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_ENCRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, }, + .key_len = 24, + .nonce = (const uint8_t []){ 0x20, 0xd5, 0xcf, 0x30, 0x5e, 0x63, 0x0a, 0x8f, 0x49, 0xe3, 0xbb, 0x4b, 0xab, 0x18, 0xab, 0xc9, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x96, 0xd3, 0x6b, 0x79, 0x5f, 0x8e, 0x7e, 0xdf, 0x6a, 0x8e, 0x0d, 0xbc, 0xd2, 0x0d, 0x6c, 0x07, 0x2a, 0x81, 0x88, 0x88, 0xd1, 0xf0, 0x9f, 0x32, 0xaa, 0x7b, 0xee, 0xdd, 0x28, 0x69, 0xb4, 0x46, 0x57, 0x5e, 0x2e, 0xce, 0xc2, 0xb3, 0xc7, 0x2d, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x8a, 0x3a, 0x22, 0xbf, 0x25, 0x92, 0x95, 0x8b, 0x93, 0x02, 0x92, 0xaa, 0x47, 0xf5, 0x90, 0xe8, }, + .tag_len = 16, + .line = __LINE__, + .id = 161 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_ENCRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, }, + .key_len = 24, + .nonce = (const uint8_t []){ 0x25, 0x53, 0x58, 0xa7, 0x1a, 0x0e, 0x57, 0x31, 0xf6, 0xdd, 0x6c, 0xe2, 0x8e, 0x15, 0x8a, 0xe6, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0xcf, 0xce, 0x3d, 0x92, 0x0f, 0x0e, 0x01, 0xf0, 0xbb, 0x49, 0xa7, 0x51, 0x95, 0x5b, 0x23, 0x6d, 0x1b, 0x88, 0x7b, 0xae, 0xfd, 0x25, 0xc4, 0x7f, 0x41, 0x30, 0x3c, 0x46, 0xd5, 0xc7, 0xbf, 0x9c, 0xa4, 0xc2, 0xc4, 0x5a, 0x8f, 0x1e, 0x66, 0x56, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x2d, 0xb9, 0xdc, 0x1b, 0x7f, 0xd3, 0x15, 0xdf, 0x1c, 0x95, 0x43, 0x24, 0x32, 0xfc, 0xf4, 0x74, }, + .tag_len = 16, + .line = __LINE__, + .id = 162 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_ENCRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, }, + .key_len = 24, + .nonce = (const uint8_t []){ 0xbb, 0x76, 0xe4, 0x22, 0xbb, 0xe8, 0xbb, 0xe6, 0x82, 0xa1, 0x0b, 0xe4, 0xbd, 0xd6, 0xce, 0x1c, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x69, 0xa2, 0x41, 0x69, 0x79, 0x2e, 0x9a, 0x07, 0xf6, 0xe6, 0xf4, 0x73, 0x6f, 0xa9, 0x72, 0xdc, 0xcf, 0xce, 0x3d, 0x92, 0x0f, 0x0e, 0x01, 0xf0, 0xbb, 0x49, 0xa7, 0x51, 0x95, 0x5b, 0x23, 0x6d, 0x1b, 0x88, 0x7b, 0xae, 0xfd, 0x25, 0xc4, 0x7f, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x82, 0xad, 0x96, 0x7f, 0x7a, 0xc1, 0x90, 0x84, 0x35, 0x4f, 0x69, 0xa7, 0x51, 0x44, 0x3f, 0xb2, }, + .tag_len = 16, + .line = __LINE__, + .id = 163 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_ENCRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, }, + .key_len = 24, + .nonce = (const uint8_t []){ 0xdb, 0x18, 0x21, 0xac, 0x59, 0xc3, 0x8e, 0x9f, 0x1e, 0x25, 0xa2, 0xee, 0xe9, 0x93, 0x03, 0x13, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x4e, 0x44, 0x17, 0xa8, 0x3b, 0xea, 0xc1, 0xeb, 0x7e, 0x24, 0x45, 0x6a, 0x05, 0xf6, 0xba, 0x55, 0x69, 0xa2, 0x41, 0x69, 0x79, 0x2e, 0x9a, 0x07, 0xf6, 0xe6, 0xf4, 0x73, 0x6f, 0xa9, 0x72, 0xdc, 0xcf, 0xce, 0x3d, 0x92, 0x0f, 0x0e, 0x01, 0xf0, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x47, 0x2d, 0x5d, 0xd5, 0x82, 0xdc, 0x05, 0xef, 0x5f, 0xc4, 0x96, 0xb6, 0x12, 0x02, 0x3c, 0xb2, }, + .tag_len = 16, + .line = __LINE__, + .id = 164 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_ENCRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, }, + .key_len = 24, + .nonce = (const uint8_t []){ 0xf7, 0xa0, 0x2e, 0xcc, 0xa0, 0x30, 0x64, 0xb2, 0xef, 0x3c, 0xce, 0x9f, 0xea, 0xb7, 0x9f, 0x07, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x6f, 0x8e, 0x17, 0x4e, 0xfc, 0xa3, 0x09, 0x72, 0x99, 0xf7, 0x84, 0xef, 0xd4, 0xca, 0xff, 0x0b, 0xf1, 0x68, 0xc3, 0xe5, 0x16, 0x5b, 0x9a, 0xd3, 0xd2, 0x00, 0x62, 0x00, 0x98, 0x48, 0x04, 0x4e, 0xef, 0x8f, 0x31, 0xf7, 0xd2, 0xfe, 0xad, 0x05, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0xca, 0xff, 0x72, 0x38, 0x26, 0xdf, 0x15, 0x09, 0x34, 0xae, 0xe3, 0x20, 0x1b, 0xa1, 0x75, 0xe7, }, + .tag_len = 16, + .line = __LINE__, + .id = 165 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_ENCRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, }, + .key_len = 24, + .nonce = (const uint8_t []){ 0x69, 0x85, 0x92, 0x49, 0x01, 0xd6, 0x88, 0x65, 0x9b, 0x40, 0xa9, 0x99, 0xd9, 0x74, 0xdb, 0xfd, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0xaf, 0x19, 0x30, 0x90, 0xce, 0x3d, 0x43, 0xa3, 0x88, 0xa1, 0xd2, 0x94, 0xa0, 0x96, 0x16, 0x90, 0x6f, 0x8e, 0x17, 0x4e, 0xfc, 0xa3, 0x09, 0x72, 0x99, 0xf7, 0x84, 0xef, 0xd4, 0xca, 0xff, 0x0b, 0xf1, 0x68, 0xc3, 0xe5, 0x16, 0x5b, 0x9a, 0xd3, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x3b, 0x08, 0x95, 0x8b, 0xe1, 0x28, 0x6c, 0x2b, 0x4a, 0xcb, 0xa0, 0x2b, 0x36, 0x74, 0xad, 0xb2, }, + .tag_len = 16, + .line = __LINE__, + .id = 166 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_ENCRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, }, + .key_len = 24, + .nonce = (const uint8_t []){ 0x3f, 0x11, 0x88, 0x54, 0x6c, 0x65, 0xed, 0x0f, 0xc5, 0x5e, 0x75, 0x03, 0x2c, 0x68, 0xee, 0x44, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x5d, 0xec, 0xcf, 0x83, 0x8b, 0x2c, 0xf5, 0xf8, 0x69, 0xc9, 0x0d, 0x2a, 0x61, 0x11, 0x60, 0xb1, 0xe5, 0x78, 0xab, 0x81, 0x21, 0xb9, 0x37, 0x35, 0xcb, 0xa4, 0xa1, 0x93, 0x06, 0x47, 0xb8, 0xc4, 0xc8, 0x4b, 0xf7, 0x76, 0x33, 0x3e, 0xe4, 0x5a, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0xc1, 0x4d, 0x52, 0x20, 0x8f, 0x0f, 0x51, 0xb8, 0x16, 0xa4, 0x89, 0x71, 0xea, 0xf8, 0xff, 0x7e, }, + .tag_len = 16, + .line = __LINE__, + .id = 167 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_ENCRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, }, + .key_len = 24, + .nonce = (const uint8_t []){ 0xa1, 0x34, 0x34, 0xd1, 0xcd, 0x83, 0x01, 0xd8, 0xb1, 0x22, 0x12, 0x05, 0x1f, 0xab, 0xaa, 0xbe, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0xd2, 0xca, 0xe1, 0x68, 0x4a, 0xa4, 0x07, 0xa1, 0x3a, 0x2e, 0x2d, 0xa5, 0x35, 0x7e, 0x29, 0xf5, 0x5d, 0xec, 0xcf, 0x83, 0x8b, 0x2c, 0xf5, 0xf8, 0x69, 0xc9, 0x0d, 0x2a, 0x61, 0x11, 0x60, 0xb1, 0xe5, 0x78, 0xab, 0x81, 0x21, 0xb9, 0x37, 0x35, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0xea, 0x2d, 0x01, 0x80, 0x99, 0xcd, 0x79, 0x25, 0xc5, 0x07, 0xce, 0xf0, 0xce, 0xdd, 0xb0, 0xae, }, + .tag_len = 16, + .line = __LINE__, + .id = 168 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_ENCRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, 0x98, 0xa9, 0xba, 0xcb, 0xdc, 0xed, 0xfe, 0x0f, }, + .key_len = 32, + .nonce = (const uint8_t []){ 0x5c, 0x2e, 0xa9, 0xb6, 0x95, 0xfc, 0xf6, 0xe2, 0x64, 0xb9, 0x60, 0x74, 0xd6, 0xbf, 0xa5, 0x72, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x28, 0xe1, 0xc5, 0x23, 0x2f, 0x4e, 0xe8, 0x16, 0x1d, 0xbe, 0x4c, 0x03, 0x63, 0x09, 0xe0, 0xb3, 0x25, 0x4e, 0x92, 0x12, 0xbe, 0xf0, 0xa9, 0x34, 0x31, 0xce, 0x5e, 0x56, 0x04, 0xc8, 0xf6, 0xa7, 0x3c, 0x18, 0xa3, 0x18, 0x30, 0x18, 0xb7, 0x70, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0xd5, 0x80, 0x8a, 0x1b, 0xd1, 0x1a, 0x01, 0x12, 0x9b, 0xf3, 0xc6, 0x91, 0x9a, 0xff, 0x23, 0x39, }, + .tag_len = 16, + .line = __LINE__, + .id = 240 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_ENCRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, 0x98, 0xa9, 0xba, 0xcb, 0xdc, 0xed, 0xfe, 0x0f, }, + .key_len = 32, + .nonce = (const uint8_t []){ 0x57, 0xb3, 0xa8, 0x1f, 0x2c, 0x36, 0xb6, 0xb0, 0x65, 0x77, 0xca, 0x0f, 0xba, 0xb8, 0xfa, 0x8e, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0xcc, 0xee, 0xbe, 0xb4, 0xfe, 0x4c, 0xd9, 0x0c, 0x51, 0x4e, 0x52, 0xd2, 0x32, 0x7a, 0x2e, 0xcd, 0x75, 0x39, 0x36, 0x61, 0x00, 0x6c, 0xf2, 0x47, 0x6d, 0x86, 0x20, 0x14, 0x9a, 0xef, 0x3d, 0x1c, 0xdc, 0xe4, 0x91, 0xff, 0xf3, 0xe7, 0xa7, 0xa3, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x81, 0x32, 0xe8, 0x65, 0xb6, 0x9d, 0x64, 0xef, 0x37, 0xdb, 0x26, 0x1f, 0x80, 0xcb, 0xbe, 0x24, }, + .tag_len = 16, + .line = __LINE__, + .id = 241 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_ENCRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, 0x98, 0xa9, 0xba, 0xcb, 0xdc, 0xed, 0xfe, 0x0f, }, + .key_len = 32, + .nonce = (const uint8_t []){ 0xce, 0x20, 0xa7, 0xe8, 0x70, 0x69, 0x6a, 0x5e, 0x68, 0x53, 0x3c, 0x46, 0x5b, 0xad, 0x2b, 0xa1, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x4f, 0x43, 0x50, 0x56, 0x5d, 0x91, 0xd9, 0xaa, 0x8c, 0x5f, 0x40, 0x48, 0x55, 0x04, 0x92, 0xad, 0x6d, 0x6f, 0xda, 0xbf, 0x66, 0xda, 0x5d, 0x1e, 0x2a, 0xf7, 0xbf, 0xe1, 0xa8, 0xaa, 0xda, 0xa0, 0xba, 0xa3, 0xde, 0x38, 0xa4, 0x1d, 0x97, 0x13, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x15, 0x5d, 0xa6, 0x44, 0x1e, 0xc0, 0x71, 0xef, 0x2d, 0x8e, 0x6c, 0xff, 0xba, 0xcc, 0x1c, 0x7c, }, + .tag_len = 16, + .line = __LINE__, + .id = 242 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_ENCRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, 0x98, 0xa9, 0xba, 0xcb, 0xdc, 0xed, 0xfe, 0x0f, }, + .key_len = 32, + .nonce = (const uint8_t []){ 0x91, 0x8e, 0x3c, 0x19, 0xdb, 0xdf, 0xee, 0x2d, 0xb1, 0x81, 0x56, 0xc5, 0xb9, 0x3f, 0x3d, 0x75, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x83, 0x16, 0xa5, 0x31, 0x67, 0xb6, 0xde, 0x1a, 0x75, 0x75, 0x70, 0x06, 0x93, 0xff, 0xef, 0x27, 0x4f, 0x43, 0x50, 0x56, 0x5d, 0x91, 0xd9, 0xaa, 0x8c, 0x5f, 0x40, 0x48, 0x55, 0x04, 0x92, 0xad, 0x6d, 0x6f, 0xda, 0xbf, 0x66, 0xda, 0x5d, 0x1e, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x6c, 0x57, 0x4a, 0xa6, 0xa2, 0x49, 0x0c, 0xc3, 0xb2, 0xf2, 0xf8, 0xf0, 0xff, 0xbc, 0x56, 0xc4, }, + .tag_len = 16, + .line = __LINE__, + .id = 243 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_ENCRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, 0x98, 0xa9, 0xba, 0xcb, 0xdc, 0xed, 0xfe, 0x0f, }, + .key_len = 32, + .nonce = (const uint8_t []){ 0x71, 0x7d, 0x90, 0x0b, 0x27, 0x04, 0x62, 0xb9, 0xdb, 0xf7, 0xe9, 0x41, 0x9e, 0x89, 0x06, 0x09, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x51, 0x75, 0x92, 0x75, 0x13, 0xe7, 0x51, 0xeb, 0x30, 0x9f, 0x45, 0xbc, 0x2e, 0xf2, 0x25, 0xf2, 0x83, 0x16, 0xa5, 0x31, 0x67, 0xb6, 0xde, 0x1a, 0x75, 0x75, 0x70, 0x06, 0x93, 0xff, 0xef, 0x27, 0x4f, 0x43, 0x50, 0x56, 0x5d, 0x91, 0xd9, 0xaa, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x80, 0x82, 0xa7, 0x61, 0xe1, 0xd7, 0x55, 0x34, 0x4b, 0xf2, 0x96, 0x22, 0x14, 0x4e, 0x7d, 0x39, }, + .tag_len = 16, + .line = __LINE__, + .id = 244 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_ENCRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, 0x98, 0xa9, 0xba, 0xcb, 0xdc, 0xed, 0xfe, 0x0f, }, + .key_len = 32, + .nonce = (const uint8_t []){ 0xec, 0xd5, 0x21, 0x20, 0xaf, 0x24, 0x0e, 0x9b, 0x4b, 0xf3, 0xb9, 0xd1, 0xee, 0xb4, 0x94, 0x34, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x36, 0xb3, 0xfb, 0xec, 0xd0, 0x91, 0x78, 0xd0, 0x45, 0x27, 0xfb, 0x37, 0x54, 0x4f, 0x55, 0x79, 0xd2, 0x0d, 0x60, 0xa4, 0x12, 0x66, 0xf6, 0x85, 0xc4, 0x80, 0x98, 0xe1, 0xa5, 0x28, 0x04, 0xca, 0x38, 0x7d, 0x90, 0x70, 0x9d, 0x32, 0x68, 0xdd, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x03, 0x3e, 0x0e, 0xf2, 0x95, 0x3e, 0xbf, 0xd8, 0x42, 0x57, 0x37, 0xc7, 0xd3, 0x93, 0xf8, 0x9a, }, + .tag_len = 16, + .line = __LINE__, + .id = 245 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_ENCRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, 0x98, 0xa9, 0xba, 0xcb, 0xdc, 0xed, 0xfe, 0x0f, }, + .key_len = 32, + .nonce = (const uint8_t []){ 0xb3, 0x7b, 0xba, 0xd1, 0x04, 0x92, 0x8a, 0xe8, 0x92, 0x21, 0xd3, 0x52, 0x0c, 0x26, 0x82, 0xe0, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x16, 0x92, 0x9b, 0x77, 0x30, 0x51, 0xf1, 0x2b, 0x0a, 0xda, 0xc9, 0x5f, 0x65, 0xe2, 0x1a, 0x7f, 0x36, 0xb3, 0xfb, 0xec, 0xd0, 0x91, 0x78, 0xd0, 0x45, 0x27, 0xfb, 0x37, 0x54, 0x4f, 0x55, 0x79, 0xd2, 0x0d, 0x60, 0xa4, 0x12, 0x66, 0xf6, 0x85, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0xca, 0x44, 0x8b, 0xb7, 0xe5, 0x2e, 0x89, 0x7e, 0xca, 0x23, 0x4e, 0xf3, 0x43, 0xd0, 0x57, 0xd0, }, + .tag_len = 16, + .line = __LINE__, + .id = 246 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_ENCRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, 0x98, 0xa9, 0xba, 0xcb, 0xdc, 0xed, 0xfe, 0x0f, }, + .key_len = 32, + .nonce = (const uint8_t []){ 0x53, 0x88, 0x16, 0xc3, 0xf8, 0x49, 0x06, 0x7c, 0xf8, 0x57, 0x6c, 0xd6, 0x2b, 0x90, 0xb9, 0x9c, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x6d, 0x3f, 0xae, 0xfa, 0xf6, 0x91, 0xd5, 0x81, 0x63, 0x84, 0x6f, 0x8d, 0x4b, 0x9f, 0xfd, 0x59, 0x16, 0x92, 0x9b, 0x77, 0x30, 0x51, 0xf1, 0x2b, 0x0a, 0xda, 0xc9, 0x5f, 0x65, 0xe2, 0x1a, 0x7f, 0x36, 0xb3, 0xfb, 0xec, 0xd0, 0x91, 0x78, 0xd0, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x84, 0xf4, 0x97, 0x40, 0xe6, 0x75, 0x7f, 0x63, 0xdd, 0x0d, 0xf7, 0xcb, 0x76, 0x56, 0xd0, 0xef, }, + .tag_len = 16, + .line = __LINE__, + .id = 247 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_ENCRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, 0x98, 0xa9, 0xba, 0xcb, 0xdc, 0xed, 0xfe, 0x0f, }, + .key_len = 32, + .nonce = (const uint8_t []){ 0xd1, 0x0e, 0x63, 0x19, 0x43, 0xcd, 0x3b, 0xda, 0xba, 0xba, 0xb2, 0xbb, 0xd1, 0x39, 0x51, 0xc0, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0xd6, 0x01, 0x96, 0xc2, 0xd1, 0x4f, 0xcf, 0x30, 0xc0, 0x99, 0x1d, 0x27, 0x21, 0xdd, 0xc5, 0x2d, 0x38, 0x5f, 0x40, 0x7a, 0x16, 0x69, 0x1d, 0xad, 0xe8, 0x2c, 0x90, 0x23, 0xc8, 0x55, 0xfd, 0x8e, 0x2e, 0x8f, 0xbb, 0x56, 0x21, 0x02, 0xf0, 0x18, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0x87, 0x7e, 0x15, 0xd9, 0x88, 0x9e, 0x69, 0xa9, 0x9f, 0xcc, 0x6d, 0x72, 0x74, 0x65, 0xc3, 0x91, }, + .tag_len = 16, + .line = __LINE__, + .id = 248 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_ENCRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, 0x98, 0xa9, 0xba, 0xcb, 0xdc, 0xed, 0xfe, 0x0f, }, + .key_len = 32, + .nonce = (const uint8_t []){ 0x8e, 0xa0, 0xf8, 0xe8, 0xe8, 0x7b, 0xbf, 0xa9, 0x63, 0x68, 0xd8, 0x38, 0x33, 0xab, 0x47, 0x14, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x94, 0x8f, 0xbc, 0xec, 0xa1, 0x2a, 0x6e, 0x4f, 0xab, 0xb7, 0x9b, 0x6d, 0x96, 0x5e, 0x33, 0x6f, 0xd6, 0x01, 0x96, 0xc2, 0xd1, 0x4f, 0xcf, 0x30, 0xc0, 0x99, 0x1d, 0x27, 0x21, 0xdd, 0xc5, 0x2d, 0x38, 0x5f, 0x40, 0x7a, 0x16, 0x69, 0x1d, 0xad, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0xcd, 0x57, 0x57, 0x62, 0x69, 0x45, 0x97, 0x6b, 0xa9, 0xf0, 0x26, 0x4b, 0xd6, 0xbe, 0xe8, 0x94, }, + .tag_len = 16, + .line = __LINE__, + .id = 249 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_ENCRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, 0x98, 0xa9, 0xba, 0xcb, 0xdc, 0xed, 0xfe, 0x0f, }, + .key_len = 32, + .nonce = (const uint8_t []){ 0x7b, 0x2d, 0xf4, 0xfb, 0xed, 0x1d, 0xe2, 0x72, 0x7e, 0xb2, 0x48, 0x98, 0xe5, 0xde, 0xab, 0xb9, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0xa1, 0xa0, 0x12, 0x06, 0x60, 0xff, 0x52, 0xe6, 0xb1, 0x70, 0x0b, 0x12, 0xc5, 0x4d, 0x2d, 0x33, 0xb9, 0x4b, 0x00, 0xcd, 0x78, 0x82, 0xd8, 0x85, 0x7d, 0x84, 0xe6, 0xe1, 0x83, 0xa1, 0xde, 0xa6, 0xee, 0x85, 0xa7, 0xda, 0x84, 0xfb, 0xc3, 0x5d, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0xb0, 0x15, 0xd7, 0x2d, 0xa6, 0x2c, 0x81, 0xcb, 0x4d, 0x26, 0x72, 0x53, 0xb2, 0x0d, 0xb9, 0xe5, }, + .tag_len = 16, + .line = __LINE__, + .id = 250 +}, +{ + .algo = TEE_ALG_AES_GCM, .mode = TEE_MODE_ENCRYPT, .key_type = TEE_TYPE_AES, + .key = (const uint8_t []){ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, 0x98, 0xa9, 0xba, 0xcb, 0xdc, 0xed, 0xfe, 0x0f, }, + .key_len = 32, + .nonce = (const uint8_t []){ 0x24, 0x83, 0x6f, 0x0a, 0x46, 0xab, 0x66, 0x01, 0xa7, 0x60, 0x22, 0x1b, 0x07, 0x4c, 0xbd, 0x6d, }, + .nonce_len = 16, + .aad_incr = 0, + .aad = NULL, + .aad_len = 0, + .in_incr = 0, + .ptx = (const uint8_t []){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + .ptx_len = 40, + .ctx = (const uint8_t []){ 0x5e, 0x34, 0x34, 0xb4, 0x5e, 0xdb, 0xf0, 0xd1, 0xf6, 0xe0, 0x2d, 0x11, 0x44, 0xdb, 0xf8, 0x67, 0xa1, 0xa0, 0x12, 0x06, 0x60, 0xff, 0x52, 0xe6, 0xb1, 0x70, 0x0b, 0x12, 0xc5, 0x4d, 0x2d, 0x33, 0xb9, 0x4b, 0x00, 0xcd, 0x78, 0x82, 0xd8, 0x85, }, + .ctx_len = 40, + .tag = (const uint8_t []){ 0xee, 0x74, 0xcc, 0xb3, 0x0d, 0x64, 0x9e, 0xbf, 0x69, 0x16, 0xd0, 0x5a, 0x7d, 0xbe, 0x56, 0x96, }, + .tag_len = 16, + .line = __LINE__, + .id = 251 +}, diff --git a/optee/optee_test/host/xtest/asym_perf.c b/optee/optee_test/host/xtest/asym_perf.c new file mode 100644 index 0000000..915c763 --- /dev/null +++ b/optee/optee_test/host/xtest/asym_perf.c @@ -0,0 +1,966 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2024, Huawei Technologies Co., Ltd + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "crypto_common.h" +#include "xtest_helpers.h" + +static TEEC_Context ctx; +static TEEC_Session sess; + +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 TEEC_SharedMemory hash_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); +} + +#define CHECK(res, name, action) do { \ + if ((res) != 0) { \ + printf(name ": 0x%08x", (res)); \ + action \ + } \ + } while(0) + +static void open_ta(void) +{ + TEEC_UUID uuid = TA_CRYPTO_PERF_UUID; + TEEC_Result res = TEEC_ERROR_GENERIC; + 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); +} + +static void close_ta(void) +{ + TEEC_CloseSession(&sess); + TEEC_FinalizeContext(&ctx); +} + +/* + * 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 = x; + 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 void usage(const char *progname, uint32_t width_bits, uint32_t main_algo, + uint32_t mode, uint32_t salt_len, uint32_t size, + uint32_t crypto_algo, int warmup, uint32_t l, uint32_t n) +{ + fprintf(stderr, "Usage: %s [-h]\n", progname); + fprintf(stderr, "Usage: %s [-a] [-k SIZE]", progname); + fprintf(stderr, " [-a algo] [-n LOOP] [-r|--no-inited] [-d WIDTH_BITS]"); + fprintf(stderr, " [-k SIZE] [-a crypto_algo] [-s salt_len] [-v [-v]] [-w SEC]"); + fprintf(stderr, "\n"); + fprintf(stderr, "Asymmetric performance testing tool for OP-TEE\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Options:\n"); + fprintf(stderr, " -h|--help Print this help and exit\n"); + fprintf(stderr, " -a ALGO Asymmetric algorithm [DH]\n"); + fprintf(stderr, " DH, RSA_GENKEYPAIR, RSA_NOPAD_ENCRYPT, RSA_NOPAD_DECRYPT\n"); + fprintf(stderr, " RSAES_PKCS1_V1_5_ENCRYPT, RSAES_PKCS1_V1_5_DECRYPT\n"); + fprintf(stderr, " RSAES_PKCS1_OAEP_SHA1_ENCRYPT, RSAES_PKCS1_OAEP_SHA1_DECRYPT\n"); + fprintf(stderr, " RSAES_PKCS1_OAEP_SHA224_ENCRYPT, RSAES_PKCS1_OAEP_SHA224_DECRYPT\n"); + fprintf(stderr, " RSAES_PKCS1_OAEP_SHA256_ENCRYPT, RSAES_PKCS1_OAEP_SHA256_DECRYPT\n"); + fprintf(stderr, " RSAES_PKCS1_OAEP_SHA384_ENCRYPT, RSAES_PKCS1_OAEP_SHA384_DECRYPT\n"); + fprintf(stderr, " RSAES_PKCS1_OAEP_SHA512_ENCRYPT, RSAES_PKCS1_OAEP_SHA512_DECRYPT\n"); + fprintf(stderr, " RSASSA_PKCS1_V1_5_SHA1_SIGN, RSASSA_PKCS1_V1_5_SHA1_VERIFY\n"); + fprintf(stderr, " RSASSA_PKCS1_V1_5_SHA224_SIGN, RSASSA_PKCS1_V1_5_SHA224_VERIFY\n"); + fprintf(stderr, " RSASSA_PKCS1_V1_5_SHA256_SIGN, RSASSA_PKCS1_V1_5_SHA256_VERIFY\n"); + fprintf(stderr, " RSASSA_PKCS1_V1_5_SHA384_SIGN, RSASSA_PKCS1_V1_5_SHA384_VERIFY\n"); + fprintf(stderr, " RSASSA_PKCS1_V1_5_SHA512_SIGN, RSASSA_PKCS1_V1_5_SHA512_VERIFY\n"); + fprintf(stderr, " RSASSA_PKCS1_PSS_MGF1_SHA1_SIGN, RSASSA_PKCS1_PSS_MGF1_SHA1_VERIFY\n"); + fprintf(stderr, " RSASSA_PKCS1_PSS_MGF1_SHA224_SIGN, RSASSA_PKCS1_PSS_MGF1_SHA224_VERIFY\n"); + fprintf(stderr, " RSASSA_PKCS1_PSS_MGF1_SHA256_SIGN, RSASSA_PKCS1_PSS_MGF1_SHA256_VERIFY\n"); + fprintf(stderr, " RSASSA_PKCS1_PSS_MGF1_SHA384_SIGN, RSASSA_PKCS1_PSS_MGF1_SHA384_VERIFY\n"); + fprintf(stderr, " RSASSA_PKCS1_PSS_MGF1_SHA512_SIGN, RSASSA_PKCS1_PSS_MGF1_SHA512_VERIFY\n"); + fprintf(stderr, " ECDSA_SIGN, ECDSA_VERIFY, ECDH, X25519\n"); + fprintf(stderr, " -l LOOP Inner loop iterations [%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, " -k SIZE Plaintext byte length [%u]\n", size); + fprintf(stderr, " -d WIDTH_BITS Private key size in bits [%u]\n", width_bits); + fprintf(stderr, " ECC: 192, 224, 256, 384 or 521, DH: <= 2048, RSA: <= 4096\n"); + fprintf(stderr, " -s SALT_LEN Salt length in bytes (only when ALGO is one of RSA SSA_PKCS1_PSS_*)[%u]\n", salt_len); + fprintf(stderr, " -w|--warmup SEC Warm-up time in seconds: execute a busy loop before [%d]\n", warmup); + fprintf(stderr, " -v Be verbose (use twice for greater effect)\n"); +} + +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) +{ + allocate_shm(&in_shm, sz); + allocate_shm(&out_shm, TEE_MAX_OUT_SIZE); + allocate_shm(&hash_shm, TEE_MAX_HASH_SIZE); +} + +static void free_shm(void) +{ + TEEC_ReleaseSharedMemory(&in_shm); + TEEC_ReleaseSharedMemory(&out_shm); + TEEC_ReleaseSharedMemory(&hash_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 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_obj(int width_bits, uint32_t main_algo) +{ + uint32_t cmd = TA_CRYPTO_PERF_CMD_ASYM_PREPARE_OBJ; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + TEEC_Result res = TEEC_ERROR_GENERIC; + uint32_t ret_origin = 0; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, TEEC_NONE, + TEEC_NONE); + op.params[0].value.a = main_algo; + op.params[0].value.b = width_bits; + + res = TEEC_InvokeCommand(&sess, cmd, &op, &ret_origin); + check_res(res, "TEEC_InvokeCommand()", &ret_origin); +} + +static void prepare_hash(int size, uint32_t main_algo) +{ + uint32_t cmd = TA_CRYPTO_PERF_CMD_ASYM_PREPARE_HASH; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + TEEC_Result res = TEEC_ERROR_GENERIC; + uint32_t ret_origin = 0; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, + TEEC_MEMREF_PARTIAL_INOUT, TEEC_NONE); + op.params[0].value.a = main_algo; + op.params[1].memref.parent = &in_shm; + op.params[1].memref.size = size; + op.params[2].memref.parent = &hash_shm; + op.params[2].memref.size = hash_shm.size; + + res = TEEC_InvokeCommand(&sess, cmd, &op, &ret_origin); + check_res(res, "TEEC_InvokeCommand()", &ret_origin); + hash_shm.size = op.params[2].memref.size; +} + +static void prepare_attrs(uint8_t *buf, size_t blen) +{ + uint32_t cmd = TA_CRYPTO_PERF_CMD_ASYM_PREPARE_ATTRS; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + TEEC_Result res = TEEC_ERROR_GENERIC; + uint32_t ret_origin = 0; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INOUT, + TEEC_NONE, TEEC_NONE, TEEC_NONE); + + op.params[0].tmpref.buffer = buf; + op.params[0].tmpref.size = blen; + + res = TEEC_InvokeCommand(&sess, cmd, &op, &ret_origin); + check_res(res, "TEEC_InvokeCommand()", &ret_origin); +} + +static void free_attrs(void) +{ + uint32_t cmd = TA_CRYPTO_PERF_CMD_ASYM_FREE_ATTRS; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + TEEC_Result res = TEEC_ERROR_GENERIC; + uint32_t ret_origin = 0; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, + TEEC_NONE, TEEC_NONE); + + res = TEEC_InvokeCommand(&sess, cmd, &op, &ret_origin); + check_res(res, "TEEC_InvokeCommand()", &ret_origin); +} + +static void prepare_keypair(int width_bits, uint8_t *buf, size_t blen, + uint32_t mode, uint32_t algo, uint32_t main_algo) +{ + uint32_t cmd = TA_CRYPTO_PERF_CMD_ASYM_PREPARE_KEYPAIR; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + TEEC_Result res = TEEC_ERROR_GENERIC; + uint32_t ret_origin = 0; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_INPUT, + TEEC_MEMREF_TEMP_INPUT, TEEC_NONE); + op.params[0].value.a = width_bits; + op.params[0].value.b = mode; + op.params[1].value.a = main_algo; + op.params[1].value.b = algo; + op.params[2].tmpref.buffer = buf; + op.params[2].tmpref.size = blen; + + res = TEEC_InvokeCommand(&sess, cmd, &op, &ret_origin); + check_res(res, "TEEC_InvokeCommand()", &ret_origin); +} + +static void prepare_enc_sign(uint32_t size, uint32_t mode, + uint8_t *buf, uint32_t blen) +{ + uint32_t cmd = TA_CRYPTO_PERF_CMD_ASYM_PREPARE_ENC_SIGN; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + TEEC_Result res = TEEC_ERROR_GENERIC; + uint32_t ret_origin = 0; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_PARTIAL_INPUT, + TEEC_MEMREF_PARTIAL_OUTPUT, + TEEC_VALUE_INPUT, + TEEC_MEMREF_TEMP_INPUT); + op.params[0].memref.parent = (mode == MODE_DECRYPT) ? + &in_shm : &hash_shm; + op.params[0].memref.size = (mode == MODE_DECRYPT) ? + size : hash_shm.size; + op.params[1].memref.parent = &out_shm; + op.params[1].memref.size = out_shm.size; + op.params[2].value.a = mode; + op.params[3].tmpref.buffer = buf; + op.params[3].tmpref.size = blen; + + res = TEEC_InvokeCommand(&sess, cmd, &op, &ret_origin); + check_res(res, "TEEC_InvokeCommand()", &ret_origin); + out_shm.size = op.params[1].memref.size; +} + +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 uint32_t get_curve_id(uint32_t width_bits) +{ + switch (width_bits) { + case ECC_CURVE_192: + return TEE_ECC_CURVE_NIST_P192; + case ECC_CURVE_224: + return TEE_ECC_CURVE_NIST_P224; + case ECC_CURVE_256: + return TEE_ECC_CURVE_NIST_P256; + case ECC_CURVE_384: + return TEE_ECC_CURVE_NIST_P384; + case ECC_CURVE_521: + return TEE_ECC_CURVE_NIST_P521; + default: + fprintf(stderr, "ECC curve is not supported!\n"); + } + + return TEE_CRYPTO_ELEMENT_NONE; +} + +static int asym_perf_run_test(int mode, size_t size, uint32_t n, + uint32_t l, int is_random, uint32_t warmup, + uint32_t verbosity, uint32_t width_bits, + uint32_t main_algo, uint32_t salt_len, + uint32_t algo) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t cmd = TA_CRYPTO_PERF_CMD_ASYM_PROCESS; + TEEC_Result res = TEEC_ERROR_GENERIC; + uint8_t keygen_dh_p[DH_MAX_SIZE] = { }; + uint8_t keygen_dh_g[DH_G_SIZE] = { }; + TEE_Attribute params[4] = { }; + size_t param_count = 0; + uint32_t curve_id = TEE_CRYPTO_ELEMENT_NONE; + struct statistics stats = { }; + struct timespec ts = { }; + struct timespec t0 = { }; + struct timespec t1 = { }; + uint32_t ret_origin = 0; + uint8_t *buf = NULL; + size_t blen = 0; + double sd = 0; + int n0 = n; + + if (clock_getres(CLOCK_MONOTONIC, &ts) < 0) { + perror("clock_getres"); + return -1; + } + + verbose("random=%s, ", yesno(is_random == CRYPTO_USE_RANDOM)); + verbose("inner loops=%u, loops=%u, warm-up=%u s\n", l, n, warmup); + vverbose("Clock resolution is %jd ns\n", (intmax_t)ts.tv_sec * + 1000000000 + ts.tv_nsec); + + open_ta(); + + alloc_buffers(size); + if (is_random == CRYPTO_USE_ZEROS) + memset((uint8_t *)in_shm.buffer, 0, size); + else + read_random(in_shm.buffer, size); + if (mode == MODE_DECRYPT && main_algo == ALGO_RSA) { + /* Ensure N > M */ + ((unsigned char *)(in_shm.buffer))[0] = 0x00; + } + + switch (main_algo) { + case ALGO_DH: + read_random(keygen_dh_p, BITS_TO_BYTES(width_bits)); + read_random(keygen_dh_g, DH_G_SIZE); + /* make sure the p is full width */ + keygen_dh_p[0] |= 0x2; + /* make sure keygen_dh_p is odd */ + keygen_dh_p[BITS_TO_BYTES(width_bits) - 1] |= 0x1; + + xtest_add_attr(¶m_count, params, TEE_ATTR_DH_PRIME, + keygen_dh_p, BITS_TO_BYTES(width_bits)); + xtest_add_attr(¶m_count, params, TEE_ATTR_DH_BASE, + keygen_dh_g, DH_G_SIZE); + break; + case ALGO_ECDSA: + case ALGO_ECDH: + curve_id = get_curve_id(width_bits); + if (curve_id == TEE_CRYPTO_ELEMENT_NONE) + goto out; + xtest_add_attr_value(¶m_count, params, TEE_ATTR_ECC_CURVE, + curve_id, 0); + break; + case ALGO_X25519: + width_bits = WIDTH_BITS_25519; + break; + default: + break; + } + + prepare_obj(width_bits, main_algo); + + res = pack_attrs(params, param_count, &buf, &blen); + CHECK(res, "pack_attrs", goto out;); + + if (mode == MODE_GENKEYPAIR) { + if (blen) + prepare_attrs(buf, blen); + + cmd = TA_CRYPTO_PERF_CMD_ASYM_PROCESS_GEN_KEYPAIR; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_NONE, TEEC_NONE, + TEEC_NONE); + op.params[0].value.a = width_bits; + op.params[0].value.b = l; + } else { + prepare_keypair(width_bits, buf, blen, mode, algo, main_algo); + + if (mode == MODE_SIGN || mode == MODE_VERIFY) + prepare_hash(size, main_algo); + + if (main_algo == ALGO_RSA && algo >= RSASSA_PKCS1_PSS_MGF1_SHA1) { + params[0].attributeID = TEE_ATTR_RSA_PSS_SALT_LENGTH; + params[0].content.value.a = salt_len; + params[0].content.value.b = 0; + param_count = 1; + res = pack_attrs(params, param_count, &buf, &blen); + CHECK(res, "pack_attrs", goto out;); + } + + if (blen) + prepare_attrs(buf, blen); + + cmd = TA_CRYPTO_PERF_CMD_ASYM_PROCESS; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, + TEEC_MEMREF_PARTIAL_OUTPUT, + TEEC_NONE); + + op.params[0].value.a = l; + op.params[0].value.b = mode; + + switch (mode) { + case MODE_ENCRYPT: + op.params[1].memref.parent = &in_shm; + op.params[1].memref.size = size; + op.params[2].memref.parent = &out_shm; + op.params[2].memref.size = out_shm.size; + break; + case MODE_SIGN: + op.params[1].memref.parent = &hash_shm; + op.params[1].memref.size = hash_shm.size; + op.params[2].memref.parent = &out_shm; + op.params[2].memref.size = out_shm.size; + break; + case MODE_DECRYPT: + prepare_enc_sign(size, mode, buf, blen); + op.params[1].memref.parent = &out_shm; + op.params[1].memref.size = out_shm.size; + op.params[2].memref.parent = &in_shm; + op.params[2].memref.size = size; + break; + case MODE_VERIFY: + prepare_enc_sign(size, mode, buf, blen); + op.params[1].memref.parent = &hash_shm; + op.params[1].memref.size = hash_shm.size; + op.params[2].memref.parent = &out_shm; + op.params[2].memref.size = out_shm.size; + break; + default: + fprintf(stderr, "Unexpected mode value\n"); + goto out; + } + } + + if (warmup) + do_warmup(warmup); + + while (n-- > 0) { + if (mode == MODE_ENCRYPT && main_algo == ALGO_RSA) { + /* Ensure N > M */ + ((unsigned char *)(in_shm.buffer))[0] = 0x00; + /* + * Avoid the problem that the last encryption result is + * shorter than the plaintext. + */ + op.params[3].memref.size = out_shm.size; + } + + get_current_time(&t0); + + res = TEEC_InvokeCommand(&sess, cmd, &op, &ret_origin); + + check_res(res, "TEEC_InvokeCommand()", &ret_origin); + + get_current_time(&t1); + + update_stats(&stats, timespec_diff_ns(&t0, &t1)); + if (n % (n0 / 10) == 0) + vverbose("#"); + } + + vverbose("\n"); + sd = stddev(&stats); + printf("%.3f ms/op\n", stats.m / 1000000 / l); + 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)); + +out: + free_attrs(); + free(buf); + free_shm(); + close_ta(); + return res; +} + +#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], width_bits, main_algo, mode, \ + salt_len, size, crypto_algo, warmup, l, n) + +static int get_rsa_hash_len(uint32_t algo) +{ + switch (algo) { + case RSAES_PKCS1_OAEP_SHA1: + case RSASSA_PKCS1_V1_5_SHA1: + case RSASSA_PKCS1_PSS_MGF1_SHA1: + return SHA1_LEN; + case RSAES_PKCS1_OAEP_SHA224: + case RSASSA_PKCS1_V1_5_SHA224: + case RSASSA_PKCS1_PSS_MGF1_SHA224: + return SHA224_LEN; + case RSAES_PKCS1_OAEP_SHA256: + case RSASSA_PKCS1_V1_5_SHA256: + case RSASSA_PKCS1_PSS_MGF1_SHA256: + return SHA256_LEN; + case RSAES_PKCS1_OAEP_SHA384: + case RSASSA_PKCS1_V1_5_SHA384: + case RSASSA_PKCS1_PSS_MGF1_SHA384: + return SHA384_LEN; + case RSAES_PKCS1_OAEP_SHA512: + case RSASSA_PKCS1_V1_5_SHA512: + case RSASSA_PKCS1_PSS_MGF1_SHA512: + return SHA512_LEN; + default: + fprintf(stderr, "The algo[%u] is not valid!\n", algo); + } + + return -1; +} + +static int check_rsa_cipher_params(uint32_t crypto_algo, int width_bits, int size) +{ + int width_bytes = BITS_TO_BYTES(width_bits); + int hash_len = 0; + + if (crypto_algo == RSA_NOPAD) { + if (size > width_bytes) { + fprintf(stderr, "The size or algo is not valid!\n"); + return -1; + } + } else if (crypto_algo == RSAES_PKCS1_V1_5) { + if ((size + PKCS_V1_5_MIN) > width_bytes) { + fprintf(stderr, "The size or algo is not valid!\n"); + return -1; + } + } else if (crypto_algo > RSAES_PKCS1_V1_5) { + hash_len = get_rsa_hash_len(crypto_algo); + if (hash_len == -1) + return -1; + + if (OAEP_HASH_LEN(hash_len) >= (width_bytes - OAEP_OTHER_LEN)) { + fprintf(stderr, "The width_bits or algo is not valid!\n"); + return -1; + } else if (size > (width_bytes - OAEP_HASH_LEN(hash_len) - + OAEP_OTHER_LEN)) { + fprintf(stderr, "The size or algo is not valid!\n"); + return -1; + } + } else { + return -1; + } + + return 0; +} + +static int check_rsa_hash_params(uint32_t crypto_algo, int width_bits, int size, + int salt_len) +{ + int width_bytes = BITS_TO_BYTES(width_bits); + int salt_temp = 0; + int hash_len = get_rsa_hash_len(crypto_algo); + + if (hash_len == -1) + return -1; + + switch (crypto_algo) { + case RSASSA_PKCS1_V1_5_SHA1: + if (width_bytes < hash_len + DERCODE_SHA1_LEN + PKCS_V1_5_MIN) { + fprintf(stderr, "The size or algo is not valid!\n"); + return -1; + } + return 0; + case RSASSA_PKCS1_V1_5_SHA224: + case RSASSA_PKCS1_V1_5_SHA256: + case RSASSA_PKCS1_V1_5_SHA384: + case RSASSA_PKCS1_V1_5_SHA512: + if (width_bytes < hash_len + DERCODE_SHA_LEN + PKCS_V1_5_MIN) { + fprintf(stderr, "The size or algo is not valid!\n"); + return -1; + } + return 0; + case RSASSA_PKCS1_PSS_MGF1_SHA1: + case RSASSA_PKCS1_PSS_MGF1_SHA224: + case RSASSA_PKCS1_PSS_MGF1_SHA256: + case RSASSA_PKCS1_PSS_MGF1_SHA384: + case RSASSA_PKCS1_PSS_MGF1_SHA512: + salt_temp = (salt_len == 0 ? hash_len : salt_len); + if (salt_temp > width_bytes || + width_bytes < hash_len + salt_temp + PSS_OTHER_LEN) { + fprintf(stderr, "The size or algo is not valid!\n"); + return -1; + } + return 0; + default: + return -1; + } +} + +int asym_perf_runner_cmd_parser(int argc, char *argv[]) +{ + int verbosity = CRYPTO_DEF_VERBOSITY; + int is_random = CRYPTO_USE_ZEROS; + unsigned int n = CRYPTO_DEF_COUNT / 10; + unsigned int l = CRYPTO_DEF_LOOPS; + int warmup = CRYPTO_DEF_WARMUP; + int mode = MODE_GENKEYPAIR; + int width_bits = 2048; + int main_algo = ALGO_DH; + int crypto_algo = -1; + int size = 256; + int salt_len = 0; + int i = 0; + + /* 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], "-a")) { + NEXT_ARG(i); + if (!strcasecmp(argv[i], "DH")) { + main_algo = ALGO_DH; + mode = MODE_GENKEYPAIR; + } else if (!strcasecmp(argv[i], "RSA_GENKEYPAIR")) { + main_algo = ALGO_RSA; + mode = MODE_GENKEYPAIR; + } else if (!strcasecmp(argv[i], "RSA_NOPAD_ENCRYPT")) { + main_algo = ALGO_RSA; + mode = MODE_ENCRYPT; + crypto_algo = RSA_NOPAD; + } else if (!strcasecmp(argv[i], "RSA_NOPAD_DECRYPT")) { + main_algo = ALGO_RSA; + mode = MODE_DECRYPT; + crypto_algo = RSA_NOPAD; + } else if (!strcasecmp(argv[i], "RSAES_PKCS1_V1_5_ENCRYPT")) { + main_algo = ALGO_RSA; + mode = MODE_ENCRYPT; + crypto_algo = RSAES_PKCS1_V1_5; + size -= PKCS_V1_5_MIN; + } else if (!strcasecmp(argv[i], "RSAES_PKCS1_V1_5_DECRYPT")) { + main_algo = ALGO_RSA; + mode = MODE_DECRYPT; + crypto_algo = RSAES_PKCS1_V1_5; + size -= PKCS_V1_5_MIN; + } else if (!strcasecmp(argv[i], "RSAES_PKCS1_OAEP_SHA1_ENCRYPT")) { + main_algo = ALGO_RSA; + mode = MODE_ENCRYPT; + crypto_algo = RSAES_PKCS1_OAEP_SHA1; + size -= OAEP_HASH_LEN(SHA1_LEN) + OAEP_OTHER_LEN; + } else if (!strcasecmp(argv[i], "RSAES_PKCS1_OAEP_SHA1_DECRYPT")) { + main_algo = ALGO_RSA; + mode = MODE_DECRYPT; + crypto_algo = RSAES_PKCS1_OAEP_SHA1; + size -= OAEP_HASH_LEN(SHA1_LEN) + OAEP_OTHER_LEN; + } else if (!strcasecmp(argv[i], "RSAES_PKCS1_OAEP_SHA224_ENCRYPT")) { + main_algo = ALGO_RSA; + mode = MODE_ENCRYPT; + crypto_algo = RSAES_PKCS1_OAEP_SHA224; + size -= OAEP_HASH_LEN(SHA224_LEN) + OAEP_OTHER_LEN; + } else if (!strcasecmp(argv[i], "RSAES_PKCS1_OAEP_SHA224_DECRYPT")) { + main_algo = ALGO_RSA; + mode = MODE_DECRYPT; + crypto_algo = RSAES_PKCS1_OAEP_SHA224; + size -= OAEP_HASH_LEN(SHA224_LEN) + OAEP_OTHER_LEN; + } else if (!strcasecmp(argv[i], "RSAES_PKCS1_OAEP_SHA256_ENCRYPT")) { + main_algo = ALGO_RSA; + mode = MODE_ENCRYPT; + crypto_algo = RSAES_PKCS1_OAEP_SHA256; + size -= OAEP_HASH_LEN(SHA256_LEN) + OAEP_OTHER_LEN; + } else if (!strcasecmp(argv[i], "RSAES_PKCS1_OAEP_SHA256_DECRYPT")) { + main_algo = ALGO_RSA; + mode = MODE_DECRYPT; + crypto_algo = RSAES_PKCS1_OAEP_SHA256; + size -= OAEP_HASH_LEN(SHA256_LEN) + OAEP_OTHER_LEN; + } else if (!strcasecmp(argv[i], "RSAES_PKCS1_OAEP_SHA384_ENCRYPT")) { + main_algo = ALGO_RSA; + mode = MODE_ENCRYPT; + crypto_algo = RSAES_PKCS1_OAEP_SHA384; + size -= OAEP_HASH_LEN(SHA384_LEN) + OAEP_OTHER_LEN; + } else if (!strcasecmp(argv[i], "RSAES_PKCS1_OAEP_SHA384_DECRYPT")) { + main_algo = ALGO_RSA; + mode = MODE_DECRYPT; + crypto_algo = RSAES_PKCS1_OAEP_SHA384; + size -= OAEP_HASH_LEN(SHA384_LEN) + OAEP_OTHER_LEN; + } else if (!strcasecmp(argv[i], "RSAES_PKCS1_OAEP_SHA512_ENCRYPT")) { + main_algo = ALGO_RSA; + mode = MODE_ENCRYPT; + crypto_algo = RSAES_PKCS1_OAEP_SHA512; + size -= OAEP_HASH_LEN(SHA512_LEN) + OAEP_OTHER_LEN; + } else if (!strcasecmp(argv[i], "RSAES_PKCS1_OAEP_SHA512_DECRYPT")) { + main_algo = ALGO_RSA; + mode = MODE_DECRYPT; + crypto_algo = RSAES_PKCS1_OAEP_SHA512; + size -= OAEP_HASH_LEN(SHA512_LEN) + OAEP_OTHER_LEN; + } else if (!strcasecmp(argv[i], "RSASSA_PKCS1_V1_5_SHA1_SIGN")) { + main_algo = ALGO_RSA; + mode = MODE_SIGN; + crypto_algo = RSASSA_PKCS1_V1_5_SHA1; + } else if (!strcasecmp(argv[i], "RSASSA_PKCS1_V1_5_SHA1_VERIFY")) { + main_algo = ALGO_RSA; + mode = MODE_VERIFY; + crypto_algo = RSASSA_PKCS1_V1_5_SHA1; + } else if (!strcasecmp(argv[i], "RSASSA_PKCS1_V1_5_SHA224_SIGN")) { + main_algo = ALGO_RSA; + mode = MODE_SIGN; + crypto_algo = RSASSA_PKCS1_V1_5_SHA224; + } else if (!strcasecmp(argv[i], "RSASSA_PKCS1_V1_5_SHA224_VERIFY")) { + main_algo = ALGO_RSA; + mode = MODE_VERIFY; + crypto_algo = RSASSA_PKCS1_V1_5_SHA224; + } else if (!strcasecmp(argv[i], "RSASSA_PKCS1_V1_5_SHA256_SIGN")) { + main_algo = ALGO_RSA; + mode = MODE_SIGN; + crypto_algo = RSASSA_PKCS1_V1_5_SHA256; + } else if (!strcasecmp(argv[i], "RSASSA_PKCS1_V1_5_SHA256_VERIFY")) { + main_algo = ALGO_RSA; + mode = MODE_VERIFY; + crypto_algo = RSASSA_PKCS1_V1_5_SHA256; + } else if (!strcasecmp(argv[i], "RSASSA_PKCS1_V1_5_SHA384_SIGN")) { + main_algo = ALGO_RSA; + mode = MODE_SIGN; + crypto_algo = RSASSA_PKCS1_V1_5_SHA384; + } else if (!strcasecmp(argv[i], "RSASSA_PKCS1_V1_5_SHA384_VERIFY")) { + main_algo = ALGO_RSA; + mode = MODE_VERIFY; + crypto_algo = RSASSA_PKCS1_V1_5_SHA384; + } else if (!strcasecmp(argv[i], "RSASSA_PKCS1_V1_5_SHA512_SIGN")) { + main_algo = ALGO_RSA; + mode = MODE_SIGN; + crypto_algo = RSASSA_PKCS1_V1_5_SHA512; + } else if (!strcasecmp(argv[i], "RSASSA_PKCS1_V1_5_SHA512_VERIFY")) { + main_algo = ALGO_RSA; + mode = MODE_VERIFY; + crypto_algo = RSASSA_PKCS1_V1_5_SHA512; + } else if (!strcasecmp(argv[i], "RSASSA_PKCS1_PSS_MGF1_SHA1_SIGN")) { + main_algo = ALGO_RSA; + mode = MODE_SIGN; + crypto_algo = RSASSA_PKCS1_PSS_MGF1_SHA1; + } else if (!strcasecmp(argv[i], "RSASSA_PKCS1_PSS_MGF1_SHA1_VERIFY")) { + main_algo = ALGO_RSA; + mode = MODE_VERIFY; + crypto_algo = RSASSA_PKCS1_PSS_MGF1_SHA1; + } else if (!strcasecmp(argv[i], "RSASSA_PKCS1_PSS_MGF1_SHA224_SIGN")) { + main_algo = ALGO_RSA; + mode = MODE_SIGN; + crypto_algo = RSASSA_PKCS1_PSS_MGF1_SHA224; + } else if (!strcasecmp(argv[i], "RSASSA_PKCS1_PSS_MGF1_SHA224_VERIFY")) { + main_algo = ALGO_RSA; + mode = MODE_VERIFY; + crypto_algo = RSASSA_PKCS1_PSS_MGF1_SHA224; + } else if (!strcasecmp(argv[i], "RSASSA_PKCS1_PSS_MGF1_SHA256_SIGN")) { + main_algo = ALGO_RSA; + mode = MODE_SIGN; + crypto_algo = RSASSA_PKCS1_PSS_MGF1_SHA256; + } else if (!strcasecmp(argv[i], "RSASSA_PKCS1_PSS_MGF1_SHA256_VERIFY")) { + main_algo = ALGO_RSA; + mode = MODE_VERIFY; + crypto_algo = RSASSA_PKCS1_PSS_MGF1_SHA256; + } else if (!strcasecmp(argv[i], "RSASSA_PKCS1_PSS_MGF1_SHA384_SIGN")) { + main_algo = ALGO_RSA; + mode = MODE_SIGN; + crypto_algo = RSASSA_PKCS1_PSS_MGF1_SHA384; + } else if (!strcasecmp(argv[i], "RSASSA_PKCS1_PSS_MGF1_SHA384_VERIFY")) { + main_algo = ALGO_RSA; + mode = MODE_VERIFY; + crypto_algo = RSASSA_PKCS1_PSS_MGF1_SHA384; + } else if (!strcasecmp(argv[i], "RSASSA_PKCS1_PSS_MGF1_SHA512_SIGN")) { + main_algo = ALGO_RSA; + mode = MODE_SIGN; + crypto_algo = RSASSA_PKCS1_PSS_MGF1_SHA512; + } else if (!strcasecmp(argv[i], "RSASSA_PKCS1_PSS_MGF1_SHA512_VERIFY")) { + main_algo = ALGO_RSA; + mode = MODE_VERIFY; + crypto_algo = RSASSA_PKCS1_PSS_MGF1_SHA512; + } else if (!strcasecmp(argv[i], "ECDSA_SIGN")) { + main_algo = ALGO_ECDSA; + mode = MODE_SIGN; + width_bits = 256; + } else if (!strcasecmp(argv[i], "ECDSA_VERIFY")) { + main_algo = ALGO_ECDSA; + mode = MODE_VERIFY; + width_bits = 256; + } else if (!strcasecmp(argv[i], "ECDH")) { + main_algo = ALGO_ECDH; + width_bits = 256; + mode = MODE_GENKEYPAIR; + } else if (!strcasecmp(argv[i], "X25519")) { + main_algo = ALGO_X25519; + width_bits = 256; + mode = MODE_GENKEYPAIR; + } else { + fprintf(stderr, "%s, invalid main_algo\n", + argv[0]); + USAGE(); + return 1; + } + } else if (!strcmp(argv[i], "-l")) { + NEXT_ARG(i); + l = atoi(argv[i]); + } else if (!strcmp(argv[i], "-n")) { + NEXT_ARG(i); + n = atoi(argv[i]); + } else if (!strcmp(argv[i], "--random") || + !strcmp(argv[i], "-r")) { + is_random = CRYPTO_USE_RANDOM; + } else if (!strcmp(argv[i], "-k")) { + NEXT_ARG(i); + size = atoi(argv[i]); + } else if (!strcmp(argv[i], "-d")) { + NEXT_ARG(i); + width_bits = atoi(argv[i]); + } else if (!strcmp(argv[i], "-s")) { + NEXT_ARG(i); + salt_len = 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 (main_algo == ALGO_RSA) { + if (mode == MODE_ENCRYPT || mode == MODE_DECRYPT) { + if (check_rsa_cipher_params(crypto_algo, width_bits, size)) { + USAGE(); + return -1; + } + } else if (mode == MODE_SIGN || mode == MODE_VERIFY) { + if (check_rsa_hash_params(crypto_algo, width_bits, size, + salt_len)) { + USAGE(); + return -1; + } + } + } + + if (mode == MODE_GENKEYPAIR) + size = BITS_TO_BYTES(width_bits); + + return asym_perf_run_test(mode, size, n, l, is_random, warmup, + verbosity, width_bits, main_algo, + salt_len, crypto_algo); +} 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/clear_storage.c b/optee/optee_test/host/xtest/clear_storage.c new file mode 100644 index 0000000..3dcf195 --- /dev/null +++ b/optee/optee_test/host/xtest/clear_storage.c @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023, Linaro Limited + */ + +#include +#include +#include +#include +#include + +#include "clear_storage.h" + +static int clear_storage_for_ta(TEEC_UUID *uuid) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Context ctx = { }; + TEEC_Session sess = { }; + TEEC_Operation op = { }; + 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); + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, + TEEC_NONE); + res = TEEC_InvokeCommand(&sess, TA_STORAGE_CMD_CLEAR_STORAGE, &op, &eo); + if (res) + errx(EXIT_FAILURE, + "TEEC_InvokeCommand: res %#"PRIx32" err_orig %#"PRIx32, + res, eo); + + TEEC_CloseSession(&sess); + TEEC_FinalizeContext(&ctx); + return 0; +} + +int clear_storage(void) +{ + TEEC_UUID uuid[] = { TA_STORAGE_UUID, TA_STORAGE2_UUID }; + size_t i = 0; + int res = 0; + + for (i = 0; i < ARRAY_SIZE(uuid); i++) { + res = clear_storage_for_ta(uuid + i); + if (res) + break; + } + return res; +} diff --git a/optee/optee_test/host/xtest/clear_storage.h b/optee/optee_test/host/xtest/clear_storage.h new file mode 100644 index 0000000..9f049f7 --- /dev/null +++ b/optee/optee_test/host/xtest/clear_storage.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2023, Linaro Limited + */ + +#ifndef CLEAR_STORAGE_H +#define CLEAR_STORAGE_H + +int clear_storage(void); + +#endif /*CLEAR_STORAGE_H*/ 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..b6de3f9 --- /dev/null +++ b/optee/optee_test/host/xtest/crypto_common.h @@ -0,0 +1,53 @@ +/* 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_crypto_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); +int asym_perf_runner_cmd_parser(int argc, char *argv[]); + +#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..a52fb02 --- /dev/null +++ b/optee/optee_test/host/xtest/ffa_spmc_1000.c @@ -0,0 +1,534 @@ +// 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/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..a032419 --- /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->imp.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..b2c6984 --- /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->imp.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->imp.ctx, &shm1); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return res; + + res = TEEC_AllocateSharedMemory(s->imp.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->imp.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->imp.ctx, SHARE_MEM01, partd_length, + TEEC_MEM_INPUT, partd_length, + part_data, mem01_exit) + ALLOCATE_SHARED_MEMORY(s->imp.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->imp.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->imp.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->imp.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->imp.ctx, SHARE_MEM01, partd_length, + TEEC_MEM_INPUT, partd_length, + part_data, mem01_exit) + ALLOCATE_SHARED_MEMORY(s->imp.ctx, SHARE_MEM02, partd_length, + TEEC_MEM_OUTPUT, mem02_exit) + ALLOCATE_SHARED_MEMORY(s->imp.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->imp.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->imp.ctx, SHARE_MEM02, partd_length, + TEEC_MEM_OUTPUT, mem02_exit) + ALLOCATE_SHARED_MEMORY(s->imp.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->imp.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->imp.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->imp.ctx, SHARE_MEM01, partd_length, + TEEC_MEM_INPUT, partd_length, + part_data, mem01_exit) + ALLOCATE_SHARED_MEMORY(s->imp.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->imp.ctx, SHARE_MEM01, + saved_digest.size, + TEEC_MEM_INPUT, saved_digest.size, + saved_digest.buffer, mem01_exit) + ALLOCATE_SHARED_MEMORY(s->imp.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->imp.ctx, SHARE_MEM01, fdata_length, + TEEC_MEM_INPUT, + saved_digest.size, saved_digest.buffer, mem01_exit) + ALLOCATE_SHARED_MEMORY(s->imp.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->imp.ctx, SHARE_MEM01, fdata_length, + TEEC_MEM_INPUT, fdata_length, + full_data, mem01_exit) + + + ALLOCATE_SHARED_MEMORY(s->imp.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->imp.ctx, SHARE_MEM01, + buffer_asym_encrypted.size, + TEEC_MEM_INPUT, + buffer_asym_encrypted.size, + buffer_asym_encrypted.buffer, mem01_exit) + ALLOCATE_SHARED_MEMORY(s->imp.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->imp.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->imp.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->imp.ctx, SHARE_MEM01, partd_length, + TEEC_MEM_INPUT, partd_length, + part_data, mem01_exit) + ALLOCATE_SHARED_MEMORY(s->imp.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->imp.ctx, SHARE_MEM01, partd_length, + TEEC_MEM_INPUT, partd_length, + part_data, mem01_exit) + ALLOCATE_SHARED_MEMORY(s->imp.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->imp.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->imp.ctx, SHARE_MEM01, partd_length, + TEEC_MEM_INPUT, partd_length, + part_data, mem01_exit) + ALLOCATE_SHARED_MEMORY(s->imp.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->imp.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->imp.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->imp.ctx, SHARE_MEM04, fdata_length, + TEEC_MEM_INPUT, fdata_length, + full_data, mem04_exit) + ALLOCATE_SHARED_MEMORY(s->imp.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->imp.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->imp.ctx, SHARE_MEM04, fdata_length, + TEEC_MEM_INPUT, fdata_length, + full_data, mem04_exit) + ALLOCATE_SHARED_MEMORY(s->imp.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->imp.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..7406d33 --- /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->imp.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->imp.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->imp.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->imp.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->imp.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->imp.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->imp.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->imp.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..dba833e --- /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->imp.ctx, SHARE_MEM01, BIG_SIZE, + TEEC_MEM_INPUT, nameLen, name, mem01_exit) + + if (kindBuffer == TOO_SHORT_BUFFER) { + ALLOCATE_SHARED_MEMORY(sess->imp.ctx, SHARE_MEM02, 1, + TEEC_MEM_OUTPUT, mem02_exit) + } else { + ALLOCATE_SHARED_MEMORY(sess->imp.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->imp.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->imp.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->imp.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->imp.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->imp.ctx, SHARE_MEM01, 1, + TEEC_MEM_OUTPUT, mem01_exit) + } else { + ALLOCATE_SHARED_MEMORY(sess->imp.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->imp.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..e2f2f3c --- /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->imp.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->imp.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->imp.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/patches/0016-TEE_Crypto_API.xml.patch b/optee/optee_test/host/xtest/gp/patches/0016-TEE_Crypto_API.xml.patch new file mode 100644 index 0000000..562874c --- /dev/null +++ b/optee/optee_test/host/xtest/gp/patches/0016-TEE_Crypto_API.xml.patch @@ -0,0 +1,134 @@ +From e1e4ae13b9c5fb9928c94e05f0fa5c17769fd5bd Mon Sep 17 00:00:00 2001 +From: Jerome Forissier +Date: Fri, 3 Nov 2023 10:41:57 +0100 +Subject: [PATCH] TEE_Crypto_API.xml + +Disabling cases: + +- Invoke_Crypto_AllocateOperation_TEE_ALG_MD5_size_not_appropriate (3b-4d-15) +- Invoke_Crypto_AllocateOperation_TEE_ALG_SHA1_size_not_appropriate (3b-86-3d) +- Invoke_Crypto_AllocateOperation_TEE_ALG_SHA224_size_not_appropriate (3b-91-91) +- Invoke_Crypto_AllocateOperation_TEE_ALG_SHA256_size_not_appropriate (3b-c6-3c) +- Invoke_Crypto_AllocateOperation_TEE_ALG_SHA384_size_not_appropriate (3b-b0-94) +- Invoke_Crypto_AllocateOperation_TEE_ALG_SHA512_size_not_appropriate (3b-f6-b8) + +These tests assume that TEE_AllocateOperation() must reject non-zero +values for maxKeySize when the algorithm is MD5 or SHA (since the +parameter is not applicable). But The GlobalPlatform TEE Internal Core +API v1.1.2 has clarified the requirement, see: + + 6.2.1 TEE_AllocateOperation + + [...] The parameter maxKeySize MUST be a valid value as defined in Table + 5-9 for the algorithm, for algorithms referenced in Table 5-9. For all + other algorithms, the maxKeySize parameter may have any value. + +Link: https://github.com/OP-TEE/optee_os/pull/6416 +Signed-off-by: Jerome Forissier +--- + packages/Crypto/xmlstable/TEE_Crypto_API.xml | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/packages/Crypto/xmlstable/TEE_Crypto_API.xml b/packages/Crypto/xmlstable/TEE_Crypto_API.xml +index b824637..b1cd7b0 100644 +--- a/packages/Crypto/xmlstable/TEE_Crypto_API.xml ++++ b/packages/Crypto/xmlstable/TEE_Crypto_API.xml +@@ -149178,6 +149178,7 @@ + + + ++ + + + +@@ -156360,6 +156362,7 @@ + + + ++ + + + +@@ -156738,6 +156742,7 @@ + + + ++ + + + +@@ -157116,6 +157122,7 @@ + + + ++ + + + +@@ -157494,6 +157502,7 @@ + + + ++ + + + +@@ -157872,6 +157882,7 @@ + + + ++ + + + +-- +2.34.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..32457f1 --- /dev/null +++ b/optee/optee_test/host/xtest/hash_perf.c @@ -0,0 +1,496 @@ +// 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" +#include "xtest_test.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_CRYPTO_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_CRYPTO_PERF_CMD_HASH_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_CRYPTO_PERF_CMD_HASH_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 *applet_optname, + /* Default params */ + int algo, size_t size, int warmup, int l, int n) +{ + fprintf(stderr, "Usage: %s %s [-h]\n", xtest_progname, applet_optname); + fprintf(stderr, "Usage: %s %s [-a ALGO] [-l LOOP] [-n LOOP] [-r] [-s SIZE]", + xtest_progname, applet_optname); + 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: %s: missing argument\n", \ + xtest_progname, 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 %s, invalid algorithm\n", + xtest_progname, 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 %s: invalid argument: %s\n", + xtest_progname, 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..07fc044 --- /dev/null +++ b/optee/optee_test/host/xtest/pkcs11_1000.c @@ -0,0 +1,10019 @@ +// 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 "pkcs11_1000.h" +#include "xtest_test.h" +#include "xtest_helpers.h" +#include "xtest_uuid_helpers.h" + +#include + +/* AES GCM tag size in bytes */ +#define AES_GCM_TAG_SIZE 16 + +/* + * 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 const CK_GCM_PARAMS cktest_aes_gcm_params = { + .pIv = (CK_BYTE_PTR)cktest_aes128_iv, + .ulIvLen = sizeof(cktest_aes128_iv), + .ulTagBits = AES_GCM_TAG_SIZE * 8, +}; +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_gcm_mechanism = { + CKM_AES_GCM, + (CK_BYTE_PTR)&cktest_aes_gcm_params, sizeof(cktest_aes_gcm_params), +}; +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; + + /** + * OP-TEE's PKCS#11 implementaion always responds with + * CK_UNAVAILABLE_INFORMATION for fields: + * + * - ulMaxSessionCount + * - ulMaxRwSessionCount + * - ulTotalPublicMemory + * - ulFreePublicMemory + * + * Verify that CK_UNAVAILABLE_INFORMATION is correctly + * translated (32 bit vs 64 bit difference). + */ + + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, + token_info.ulMaxSessionCount, ==, + CK_UNAVAILABLE_INFORMATION)) + goto out; + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, + token_info.ulMaxRwSessionCount, ==, + CK_UNAVAILABLE_INFORMATION)) + goto out; + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, + token_info.ulTotalPublicMemory, ==, + CK_UNAVAILABLE_INFORMATION)) + goto out; + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, + token_info.ulFreePublicMemory, ==, + CK_UNAVAILABLE_INFORMATION)) + 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; +} + +#ifdef OPENSSL_FOUND +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; +} +#endif /*OPENSSL_FOUND*/ + +static void xtest_pkcs11_test_1003(ADBG_Case_t *c) +{ +#ifdef OPENSSL_FOUND + 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); +#else /*!OPENSSL_FOUND*/ + UNUSED(c); + /* xtest_uuid_v5() depends on OpenSSL */ + Do_ADBG_Log("OpenSSL not available, skipping test 1003"); +#endif /*OPENSSL_FOUND*/ +} +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 || rv == CKR_HOST_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, +}; +static const CK_MECHANISM_TYPE allowed_only_aes_gcm[] = { + CKM_AES_GCM, +}; +static const CK_MECHANISM_TYPE allowed_not_aes_gcm[] = { + CKM_AES_ECB, CKM_AES_CBC, CKM_AES_CBC_PAD, CKM_AES_CTS, + CKM_AES_CTR, 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); +CK_KEY_ALLOWED_AES_TEST(cktest_aes_only_gcm, allowed_only_aes_gcm); +CK_KEY_ALLOWED_AES_TEST(cktest_aes_not_gcm, allowed_not_aes_gcm); + +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), + CKTEST_KEY_MECHA(cktest_aes_only_gcm, &cktest_aes_gcm_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), + CKTEST_KEY_MECHA(cktest_aes_not_gcm, &cktest_aes_gcm_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); + +CK_KEY_ALLOWED_AES_ENC_TEST(cktest_aes_enc_only_gcm, allowed_only_aes_gcm); + +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; + + /* Encrypt only AES GCM key */ + rv = cipher_init_final(c, session, + cktest_aes_enc_only_gcm, + ARRAY_SIZE(cktest_aes_enc_only_gcm), + &cktest_aes_gcm_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_gcm, + ARRAY_SIZE(cktest_aes_enc_only_gcm), + &cktest_aes_gcm_mechanism, + TEE_MODE_DECRYPT, + 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 || rv == CKR_HOST_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 || rv == CKR_HOST_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 || rv == CKR_HOST_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 || rv == CKR_HOST_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"); + +#ifdef OPENSSL_FOUND +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; +} +#endif /*OPENSSL_FOUND*/ + +#define GID_STR_LEN 13 + +static void xtest_pkcs11_test_1027(ADBG_Case_t *c) +{ +#ifdef OPENSSL_FOUND + 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")); +#else /*!OPENSSL_FOUND*/ + UNUSED(c); + /* xtest_uuid_v5() depends on OpenSSL */ + Do_ADBG_Log("OpenSSL not available, skipping test 1027"); +#endif /*OPENSSL_FOUND*/ +} +ADBG_CASE_DEFINE(pkcs11, 1027, xtest_pkcs11_test_1027, + "PKCS11: Login to PKCS#11 token with ACL based authentication"); + +int xtest_pkcs11_1028_destroy_token_object(void) +{ + /* These attributes match cktest_token_object which is to find */ + CK_ATTRIBUTE find_token_template[] = { + { 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) }, + }; + CK_SESSION_HANDLE session = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE obj_handle[2] = { }; + CK_RV rv = CKR_GENERAL_ERROR; + CK_ULONG hdl_count = 0; + CK_ULONG obj_size = 0; + CK_SLOT_ID slot = 0; + int ret = 1; + + rv = init_lib_and_find_token_slot(&slot, PIN_AUTH); + if (rv != CKR_OK) + return 1; + + rv = C_OpenSession(slot, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL, 0, &session); + if (rv != CKR_OK) + goto out_lib; + + /* + * We expect to find a single matching object so that it is + * the very one we're about to destroy. + */ + rv = C_FindObjectsInit(session, find_token_template, ARRAY_SIZE(find_token_template)); + if (rv != CKR_OK) + goto out_session; + + rv = C_FindObjects(session, obj_handle, ARRAY_SIZE(obj_handle), &hdl_count); + if (rv != CKR_OK || hdl_count != 1) + goto out_session; + + rv = C_FindObjectsFinal(session); + if (rv != CKR_OK) + goto out_session; + + /* Session B destroys the token object, session A shall not reach it */ + rv = C_DestroyObject(session, obj_handle[0]); + if (rv != CKR_OK) + goto out_session; + + rv = C_GetObjectSize(session, obj_handle[0], &obj_size); + if (rv == CKR_OBJECT_HANDLE_INVALID) + ret = 0; + +out_session: + C_CloseSession(session); +out_lib: + close_lib(); + + return ret; +} + +/* + * This test involves 2 client sessions towards the PKCS11 token. + * + * Session A (implementation below) creates a token object then executes an + * application that opens session B to destroy the object after what session A + * gets a invalid object handle result when reusing its object handle. + * + * Session B sequence is implemented by function + * xtest_pkcs11_1028_destroy_token_object() that must be called from another + * process so that cryptoki library sees it as a different client and + * generates another handle for the same object. + */ +static void xtest_pkcs11_test_1028(ADBG_Case_t *c) +{ + CK_SESSION_HANDLE session = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE obj_handle = CK_INVALID_HANDLE; + CK_RV rv = CKR_GENERAL_ERROR; + CK_ULONG obj_size = 0; + CK_SLOT_ID slot = 0; + char cmd_opt[] = "--pkcs11-1028-destroy-token-object"; + char *cmdline = NULL; + int cmdline_size = 0; + int ret = 0; + + rv = init_lib_and_find_token_slot(&slot, PIN_AUTH); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return; + + cmdline_size = snprintf(NULL, 0, "%s %s", xtest_progname, cmd_opt) + 1; + if (!ADBG_EXPECT_COMPARE_SIGNED(c, cmdline_size, >, 0)) + goto out_lib; + cmdline = malloc(cmdline_size); + if (!ADBG_EXPECT_NOT_NULL(c, cmdline)) + goto out_lib; + snprintf(cmdline, cmdline_size, "%s %s", xtest_progname, cmd_opt); + + /* Session A creates a token object */ + rv = C_OpenSession(slot, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL, 0, &session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out_lib; + + rv = C_CreateObject(session, cktest_token_object, ARRAY_SIZE(cktest_token_object), + &obj_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out_session; + + rv = C_GetObjectSize(session, obj_handle, &obj_size); + if (!ADBG_EXPECT_CK_OK(c, rv)) { + rv = C_DestroyObject(session, obj_handle); + ADBG_EXPECT_CK_OK(c, rv); + goto out_session; + } + + ret = system(cmdline); + ADBG_EXPECT(c, ret, 0); + + /* Session B has deleted the object: session A handle shall no more be valid */ + rv = C_GetObjectSize(session, obj_handle, &obj_size); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_OBJECT_HANDLE_INVALID, rv)) { + rv = C_DestroyObject(session, obj_handle); + ADBG_EXPECT_CK_OK(c, rv); + } + +out_session: + rv = C_CloseSession(session); + ADBG_EXPECT_CK_OK(c, rv); +out_lib: + rv = close_lib(); + ADBG_EXPECT_CK_OK(c, rv); + + free(cmdline); +} +ADBG_CASE_DEFINE(pkcs11, 1028, xtest_pkcs11_test_1028, + "PKCS11: destroy PKCS#11 objects handled by another session"); + +/* + * This test involves PKCS11_CKA_CHECK_VALUE when enabled, as per the spec, + * the attribute can be either the legitimate value recomputed by the PKCS#11 + * token or a zero-sized value called a no-value for when client does not want + * the attribute to set in an object. This test invokes Cryptoki API functions + * C_GenerateKey(), C_CreateObject(), C_CopyObject(), C_SetAttributeValue(), + * C_UnwrapKey() and C_DeriveKey() to perform check value computation and + * This test query the value using C_GetAttributeValue(). + */ +static void xtest_pkcs11_test_1029(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; + CK_OBJECT_HANDLE key_handle_cp = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE unwrapped_key_handle = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE derived_key_handle = CK_INVALID_HANDLE; + uint8_t ciphertext[16] = { 0 }; + CK_ULONG ciphertext_len = 0; + uint8_t plaintext[16] = { 0 }; + CK_BYTE kcv[3] = { 0 }; + CK_BYTE import_aes128_key[] = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 + }; + CK_BYTE import_aes128_kcv_valid[] = { 0x08, 0xbd, 0x28 }; + CK_BYTE import_aes128_kcv_invalid[] = { 0xba, 0xaa, 0xad }; + CK_BYTE unwrapped_key_kcv_valid[] = { 0xa2, 0x25, 0x17 }; + CK_ATTRIBUTE import_aes_key_template[] = { + { CKA_TOKEN, &(CK_BBOOL){CK_TRUE}, 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_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_FALSE}, sizeof(CK_BBOOL) }, + { CKA_DECRYPT, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) }, + { 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_VALUE, &import_aes128_key, sizeof(import_aes128_key) }, + { CKA_CHECK_VALUE, &import_aes128_kcv_valid, + sizeof(import_aes128_kcv_valid) }, + }; + CK_ATTRIBUTE import_aes_key_template_novalue[] = { + { CKA_TOKEN, &(CK_BBOOL){CK_TRUE}, 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_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_FALSE}, sizeof(CK_BBOOL) }, + { CKA_DECRYPT, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) }, + { 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_VALUE, &import_aes128_key, sizeof(import_aes128_key) }, + { CKA_CHECK_VALUE, NULL, 0 }, + }; + CK_ATTRIBUTE import_aes_key_template_invalid[] = { + { CKA_TOKEN, &(CK_BBOOL){CK_TRUE}, 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_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_FALSE}, sizeof(CK_BBOOL) }, + { CKA_DECRYPT, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) }, + { 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_VALUE, &import_aes128_key, sizeof(import_aes128_key) }, + { CKA_CHECK_VALUE, &import_aes128_kcv_invalid, + sizeof(import_aes128_kcv_invalid) }, + }; + CK_ATTRIBUTE kcv_attr_template[] = { + { CKA_CHECK_VALUE, &kcv, sizeof(kcv) }, + }; + CK_ATTRIBUTE template_kcv_no_value[] = { + { CKA_CHECK_VALUE, &kcv, 0 }, + }; + CK_ATTRIBUTE template_kcv_invalid[] = { + { CKA_CHECK_VALUE, &import_aes128_kcv_invalid, + sizeof(import_aes128_kcv_invalid) }, + }; + CK_KEY_DERIVATION_STRING_DATA key_derv_param = { 0 }; + uint8_t derive_buf[16] = { 0 }; + size_t derive_buf_size = sizeof(derive_buf); + CK_MECHANISM mech_derive = { 0 }; + CK_ATTRIBUTE derived_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_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) }, + { CKA_CHECK_VALUE, NULL, 0 }, + }; + CK_ATTRIBUTE unwrap_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_EXTRACTABLE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_SENSITIVE, &(CK_BBOOL){ CK_FALSE}, sizeof(CK_BBOOL) }, + { CKA_CHECK_VALUE, &unwrapped_key_kcv_valid, + sizeof(unwrapped_key_kcv_valid)}, + }; + 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 = C_OpenSession(slot, session_flags, NULL, 0, &session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out_lib; + + /* + * Generate a key and get key check value attribute. + * If none is found, the feature is not supported: skip tests. + * If found, check it matches the expected value, computed from + * secrete key value. + */ + Do_ADBG_BeginSubCase(c, "Compute KCV on C_GenerateKey()"); + + 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 out_subcase; + + memset(&kcv, 0, sizeof(kcv)); + kcv_attr_template[0].pValue = kcv; + kcv_attr_template[0].ulValueLen = sizeof(kcv); + rv = C_GetAttributeValue(session, key_handle, kcv_attr_template, + ARRAY_SIZE(kcv_attr_template)); + + if (rv == CKR_ATTRIBUTE_TYPE_INVALID) { + Do_ADBG_Log("Skip check value attribute tests: not supported"); + goto out_destr_obj; + } + + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out_destr_obj; + + /* Generate the 3 bytes KCV using key value */ + rv = C_EncryptInit(session, &cktest_aes_ecb_mechanism, key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out_destr_obj; + + memset(ciphertext, 0, sizeof(ciphertext)); + memset(plaintext, 0, sizeof(plaintext)); + + ciphertext_len = sizeof(ciphertext); + + rv = C_Encrypt(session, plaintext, sizeof(plaintext), ciphertext, + &ciphertext_len); + + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_BUFFER(c, ciphertext, sizeof(kcv), + kcv, sizeof(kcv))) + goto out_destr_obj; + + rv = C_DestroyObject(session, key_handle); + key_handle = CK_INVALID_HANDLE; + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out_destr_obj; + + Do_ADBG_EndSubCase(c, NULL); + + /* + * Import an object with a non-value KCV + */ + Do_ADBG_BeginSubCase(c, "Set no-value KCV on C_CreateObject()"); + + rv = C_CreateObject(session, import_aes_key_template_novalue, + ARRAY_SIZE(import_aes_key_template_novalue), + &key_handle); + + if (ADBG_EXPECT_CK_OK(c, rv)) { + kcv_attr_template[0].pValue = kcv; + kcv_attr_template[0].ulValueLen = sizeof(kcv); + rv = C_GetAttributeValue(session, key_handle, kcv_attr_template, + ARRAY_SIZE(kcv_attr_template)); + if (ADBG_EXPECT_CK_OK(c, rv)) + ADBG_EXPECT_COMPARE_UNSIGNED(c, + kcv_attr_template[0].ulValueLen, ==, 0); + + rv = C_DestroyObject(session, key_handle); + ADBG_EXPECT_CK_OK(c, rv); + key_handle = CK_INVALID_HANDLE; + } + + Do_ADBG_EndSubCase(c, NULL); + + /* + * Import an object with an invalid KCV + */ + Do_ADBG_BeginSubCase(c, "Set invalid KCV on C_CreateObject()"); + + rv = C_CreateObject(session, import_aes_key_template_invalid, + ARRAY_SIZE(import_aes_key_template_invalid), + &key_handle); + + if (!ADBG_EXPECT_NOT(c, CKR_OK, rv)) { + /* Unlikely the object withas created */ + rv = C_DestroyObject(session, key_handle); + ADBG_EXPECT_CK_OK(c, rv); + key_handle = CK_INVALID_HANDLE; + } + + Do_ADBG_EndSubCase(c, NULL); + + /* + * Import an object with a wellformed precomputed KCV value + * The object will be reused. + */ + Do_ADBG_BeginSubCase(c, "Set KCV on C_CreateObject()"); + + rv = C_CreateObject(session, import_aes_key_template, + ARRAY_SIZE(import_aes_key_template), &key_handle); + + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out_destr_obj; + + memset(&kcv, 0, sizeof(kcv)); + kcv_attr_template[0].pValue = kcv; + kcv_attr_template[0].ulValueLen = sizeof(kcv); + rv = C_GetAttributeValue(session, key_handle, kcv_attr_template, + ARRAY_SIZE(kcv_attr_template)); + + if (ADBG_EXPECT_CK_OK(c, rv)) + ADBG_EXPECT_BUFFER(c, import_aes128_kcv_valid, + sizeof(import_aes128_kcv_valid), + kcv, sizeof(kcv)); + + Do_ADBG_EndSubCase(c, NULL); + + /* + * Copy wellformed AES key object with its KCV value which + * should still match. + */ + Do_ADBG_BeginSubCase(c, "Copy and recompute KCV on C_CopyObject()"); + + rv = C_CopyObject(session, key_handle, NULL, 0, &key_handle_cp); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out_destr_obj; + + memset(&kcv, 0, sizeof(kcv)); + kcv_attr_template[0].pValue = kcv; + kcv_attr_template[0].ulValueLen = sizeof(kcv); + rv = C_GetAttributeValue(session, key_handle, kcv_attr_template, + ARRAY_SIZE(kcv_attr_template)); + if (ADBG_EXPECT_CK_OK(c, rv)) + ADBG_EXPECT_BUFFER(c, import_aes128_kcv_valid, + sizeof(import_aes128_kcv_valid), + kcv, sizeof(kcv)); + + ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, key_handle_cp)); + key_handle_cp = CK_INVALID_HANDLE; + Do_ADBG_EndSubCase(c, NULL); + + /* + * Copy wellformed AES key object replacing its KCV value with + * a no-value value. + */ + Do_ADBG_BeginSubCase(c, "Set no-value KCV on C_CopyObject()"); + + rv = C_CopyObject(session, key_handle, template_kcv_no_value, + ARRAY_SIZE(template_kcv_no_value), &key_handle_cp); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out_destr_obj; + + memset(&kcv, 0, sizeof(kcv)); + kcv_attr_template[0].pValue = kcv; + kcv_attr_template[0].ulValueLen = sizeof(kcv); + rv = C_GetAttributeValue(session, key_handle_cp, kcv_attr_template, + ARRAY_SIZE(kcv_attr_template)); + if (ADBG_EXPECT_CK_OK(c, rv)) + ADBG_EXPECT_COMPARE_UNSIGNED(c, kcv_attr_template[0].ulValueLen, + ==, 0); + + ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, key_handle_cp)); + key_handle_cp = CK_INVALID_HANDLE; + Do_ADBG_EndSubCase(c, NULL); + + /* + * Copy wellformed AES key object replacing its KCV value with + * an invalid value. + */ + Do_ADBG_BeginSubCase(c, "Set invalid KCV on C_CopyObject()"); + + rv = C_CopyObject(session, key_handle, template_kcv_invalid, + ARRAY_SIZE(template_kcv_invalid), &key_handle_cp); + + if (!ADBG_EXPECT_CK_RESULT(c, CKR_ATTRIBUTE_VALUE_INVALID, rv)) + goto out_destr_obj; + + Do_ADBG_EndSubCase(c, NULL); + + /* + * Derive the key and check its KCV is degerated + */ + Do_ADBG_BeginSubCase(c, "Compute KCV on C_DeriveKey()"); + + key_derv_param.pData = derive_buf; + key_derv_param.ulLen = derive_buf_size; + mech_derive.mechanism = CKM_AES_ECB_ENCRYPT_DATA; + mech_derive.pParameter = &key_derv_param; + mech_derive.ulParameterLen = sizeof(key_derv_param); + + rv = C_DeriveKey(session, &mech_derive, key_handle, + derived_key_template, + ARRAY_SIZE(derived_key_template), + &derived_key_handle); + + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out_destr_obj; + + memset(&kcv, 0, sizeof(kcv)); + kcv_attr_template[0].pValue = kcv; + kcv_attr_template[0].ulValueLen = sizeof(kcv); + rv = C_GetAttributeValue(session, derived_key_handle, kcv_attr_template, + ARRAY_SIZE(kcv_attr_template)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out_destr_obj; + + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, + kcv_attr_template[0].ulValueLen, ==, 0)) + goto out_destr_obj; + + Do_ADBG_EndSubCase(c, NULL); + + /* + * Warp and unwrap and AES key, check its KCV value is generated. + */ + Do_ADBG_BeginSubCase(c, "Compute KCV on C_UnwrapKey()"); + + size = sizeof(buf); + + rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, key_handle, + derived_key_handle, buf, &size); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, size, <=, sizeof(buf))) + goto out_destr_obj; + + rv = C_UnwrapKey(session, &cktest_aes_ecb_mechanism, key_handle, buf, + size, unwrap_template, ARRAY_SIZE(unwrap_template), + &unwrapped_key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out_destr_obj; + + /* Save KCV for later use */ + kcv_attr_template[0].pValue = &ciphertext; + kcv_attr_template[0].ulValueLen = sizeof(ciphertext); + rv = C_GetAttributeValue(session, unwrapped_key_handle, + kcv_attr_template, + ARRAY_SIZE(kcv_attr_template)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out_destr_obj; + + Do_ADBG_EndSubCase(c, NULL); + + /* + * Replace KCV value with no-value: should succeed + */ + Do_ADBG_BeginSubCase(c, "Destroy KCV using C_SetAttributeValue()"); + + rv = C_SetAttributeValue(session, unwrapped_key_handle, + template_kcv_no_value, + ARRAY_SIZE(template_kcv_no_value)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out_destr_obj; + + memset(&kcv, 0, sizeof(kcv)); + kcv_attr_template[0].pValue = &kcv; + kcv_attr_template[0].ulValueLen = sizeof(kcv); + rv = C_GetAttributeValue(session, unwrapped_key_handle, + kcv_attr_template, + ARRAY_SIZE(kcv_attr_template)); + + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out_destr_obj; + ADBG_EXPECT_COMPARE_UNSIGNED(c, kcv_attr_template[0].ulValueLen, ==, 0); + + Do_ADBG_EndSubCase(c, NULL); + + /* + * Replace KCV value with an invalid value: should fail + */ + Do_ADBG_BeginSubCase(c, "Create an invalid KCV using C_SetAttributeValue()"); + + memset(&kcv, 0, sizeof(kcv)); + kcv_attr_template[0].pValue = &kcv; + kcv_attr_template[0].ulValueLen = sizeof(kcv); + rv = C_GetAttributeValue(session, unwrapped_key_handle, + kcv_attr_template, + ARRAY_SIZE(kcv_attr_template)); + + + rv = C_SetAttributeValue(session, unwrapped_key_handle, + template_kcv_invalid, + ARRAY_SIZE(template_kcv_invalid)); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_ATTRIBUTE_VALUE_INVALID, rv)) + goto out_destr_obj; + + /* Check object's KCV is still no-value */ + memset(&kcv, 0, sizeof(kcv)); + kcv_attr_template[0].pValue = &kcv; + kcv_attr_template[0].ulValueLen = sizeof(kcv); + rv = C_GetAttributeValue(session, unwrapped_key_handle, + kcv_attr_template, + ARRAY_SIZE(kcv_attr_template)); + + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out_destr_obj; + ADBG_EXPECT_COMPARE_UNSIGNED(c, kcv_attr_template[0].ulValueLen, ==, 0); + + Do_ADBG_EndSubCase(c, NULL); + + /* + * Replace KCV value no-value with valid value but wrong size: should + * fail + */ + Do_ADBG_BeginSubCase(c, "Set KCV of invalid size using C_SetAttributeValue()"); + + /* Valid value but bigger value size */ + kcv_attr_template[0].pValue = &ciphertext; + kcv_attr_template[0].ulValueLen = sizeof(kcv) + 1; + + rv = C_SetAttributeValue(session, unwrapped_key_handle, + kcv_attr_template, + ARRAY_SIZE(kcv_attr_template)); + if (!ADBG_EXPECT_NOT(c, CKR_OK, rv)) + goto out_destr_obj; + + /* Valid value but lower value size */ + kcv_attr_template[0].pValue = &ciphertext; + kcv_attr_template[0].ulValueLen = sizeof(kcv) - 1; + + rv = C_SetAttributeValue(session, unwrapped_key_handle, + kcv_attr_template, + ARRAY_SIZE(kcv_attr_template)); + if (!ADBG_EXPECT_NOT(c, CKR_OK, rv)) + goto out_destr_obj; + + /* Check object's KCV is still no-value */ + memset(&kcv, 0, sizeof(kcv)); + kcv_attr_template[0].pValue = &kcv; + kcv_attr_template[0].ulValueLen = sizeof(kcv); + rv = C_GetAttributeValue(session, unwrapped_key_handle, + kcv_attr_template, + ARRAY_SIZE(kcv_attr_template)); + + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out_destr_obj; + ADBG_EXPECT_COMPARE_UNSIGNED(c, kcv_attr_template[0].ulValueLen, ==, 0); + + Do_ADBG_EndSubCase(c, NULL); + + /* + * Replace KCV value no-value with valid value: should succeed + */ + Do_ADBG_BeginSubCase(c, "Set valid KCV using C_SetAttributeValue()"); + + kcv_attr_template[0].pValue = &ciphertext; + kcv_attr_template[0].ulValueLen = sizeof(kcv); + + rv = C_SetAttributeValue(session, unwrapped_key_handle, + kcv_attr_template, + ARRAY_SIZE(kcv_attr_template)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out_destr_obj; + + /* Check KCV is the expected one */ + memset(&kcv, 0, sizeof(kcv)); + kcv_attr_template[0].pValue = &kcv; + kcv_attr_template[0].ulValueLen = sizeof(kcv); + rv = C_GetAttributeValue(session, unwrapped_key_handle, + kcv_attr_template, + ARRAY_SIZE(kcv_attr_template)); + if (ADBG_EXPECT_CK_OK(c, rv)) + ADBG_EXPECT_BUFFER(c, ciphertext, sizeof(kcv), + kcv, sizeof(kcv)); + +out_destr_obj: + if (key_handle != CK_INVALID_HANDLE) + ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, key_handle)); + if (key_handle_cp != CK_INVALID_HANDLE) + ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, key_handle_cp)); + if (unwrapped_key_handle != CK_INVALID_HANDLE) + ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, unwrapped_key_handle)); + if (derived_key_handle != CK_INVALID_HANDLE) + ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, derived_key_handle)); +out_subcase: + Do_ADBG_EndSubCase(c, NULL); + ADBG_EXPECT_CK_OK(c, C_CloseSession(session)); +out_lib: + ADBG_EXPECT_CK_OK(c, close_lib()); +} +ADBG_CASE_DEFINE(pkcs11, 1029, xtest_pkcs11_test_1029, + "PKCS11: Test support for object checksum value computation"); + +struct aes_gcm_test { + int line_id; + CK_ATTRIBUTE_PTR attr_key; + CK_ULONG attr_count; + CK_MECHANISM_PTR mechanism; + const uint8_t *ctx; + size_t ctx_len; + const uint8_t *ptx; + size_t ptx_len; + const uint8_t *tag; + size_t tag_len; +}; + +#define MAKE_AES_GCM_TEST_CASE(_vect_) \ + static CK_GCM_PARAMS cktest_aes_gcm_params##_vect_ = { \ + .pIv = (CK_BYTE_PTR)ae_data_aes_gcm_vect##_vect_##_nonce,\ + .ulIvLen = sizeof(ae_data_aes_gcm_vect##_vect_##_nonce),\ + .ulIvBits = 0, \ + .pAAD = (CK_BYTE_PTR)ae_data_aes_gcm_vect##_vect_##_aad,\ + .ulAADLen = (ae_data_aes_gcm_vect##_vect_##_aad == NULL) ? 0 : \ + sizeof(ae_data_aes_gcm_vect##_vect_##_aad), \ + .ulTagBits = AES_GCM_TAG_SIZE * 8, \ + }; \ + \ + static CK_MECHANISM cktest_aes_gcm_mechanism##_vect_ = { \ + .mechanism = CKM_AES_GCM, \ + .pParameter = (CK_BYTE_PTR)&cktest_aes_gcm_params##_vect_,\ + .ulParameterLen = sizeof(cktest_aes_gcm_params##_vect_),\ + }; \ + \ + static CK_ATTRIBUTE cktest_aes_gcm_key##_vect_[] = { \ + { CKA_ENCRYPT, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) },\ + { CKA_DECRYPT, &(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 *)(ae_data_aes_gcm_vect##_vect_##_key),\ + sizeof(ae_data_aes_gcm_vect##_vect_##_key) }, \ + }; \ + \ + static const struct aes_gcm_test aes_gcm_test_case_##_vect_ = { \ + .line_id = __LINE__, \ + .attr_key = cktest_aes_gcm_key##_vect_, \ + .attr_count = ARRAY_SIZE(cktest_aes_gcm_key##_vect_), \ + .mechanism = &cktest_aes_gcm_mechanism##_vect_, \ + .ctx = ae_data_aes_gcm_vect##_vect_##_ctx, \ + .ctx_len = (ae_data_aes_gcm_vect##_vect_##_ctx == NULL) ? 0 : \ + sizeof(ae_data_aes_gcm_vect##_vect_##_ctx), \ + .ptx = ae_data_aes_gcm_vect##_vect_##_ptx, \ + .ptx_len = (ae_data_aes_gcm_vect##_vect_##_ptx == NULL) ? 0 : \ + sizeof(ae_data_aes_gcm_vect##_vect_##_ptx), \ + .tag = ae_data_aes_gcm_vect##_vect_##_tag, \ + .tag_len = sizeof(ae_data_aes_gcm_vect##_vect_##_tag) \ + } + +MAKE_AES_GCM_TEST_CASE(1); +MAKE_AES_GCM_TEST_CASE(2); +MAKE_AES_GCM_TEST_CASE(3); +MAKE_AES_GCM_TEST_CASE(4); +MAKE_AES_GCM_TEST_CASE(5); +MAKE_AES_GCM_TEST_CASE(6); +MAKE_AES_GCM_TEST_CASE(7); +MAKE_AES_GCM_TEST_CASE(8); +MAKE_AES_GCM_TEST_CASE(9); +MAKE_AES_GCM_TEST_CASE(10); +MAKE_AES_GCM_TEST_CASE(11); +MAKE_AES_GCM_TEST_CASE(12); +MAKE_AES_GCM_TEST_CASE(13); +MAKE_AES_GCM_TEST_CASE(14); +MAKE_AES_GCM_TEST_CASE(15); +MAKE_AES_GCM_TEST_CASE(16); +MAKE_AES_GCM_TEST_CASE(17); +MAKE_AES_GCM_TEST_CASE(18); + +static const struct aes_gcm_test cktest_aes_gcm_cases[] = { + aes_gcm_test_case_1, aes_gcm_test_case_2, aes_gcm_test_case_3, + aes_gcm_test_case_4, aes_gcm_test_case_5, aes_gcm_test_case_6, + aes_gcm_test_case_7, aes_gcm_test_case_8, aes_gcm_test_case_9, + aes_gcm_test_case_10, aes_gcm_test_case_11, aes_gcm_test_case_12, + aes_gcm_test_case_13, aes_gcm_test_case_14, aes_gcm_test_case_15, + aes_gcm_test_case_16, aes_gcm_test_case_17, aes_gcm_test_case_18, +}; + +#define CHUNK_SIZE 6 + +static void xtest_pkcs11_test_1030(ADBG_Case_t *c) +{ + CK_RV rv = CKR_OK; + 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; + const struct aes_gcm_test *test = NULL; + size_t n = 0; + size_t proc_len = 0; + size_t total_len = 0; + size_t saved_size = 0; + uint8_t chunk[CHUNK_SIZE] = { 0 }; + uint8_t out[512] = { 0 }; + uint8_t in[512] = { 0 }; + CK_ULONG chunk_len = 0; + CK_ULONG out_size = 0; + CK_ULONG in_size = 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_close_lib; + + for (n = 0; n < ARRAY_SIZE(cktest_aes_gcm_cases); n++) { + test = cktest_aes_gcm_cases + n; + + Do_ADBG_BeginSubCase(c, "AES-GCM case %zu (line ID %d)", n, + test->line_id); + + rv = C_CreateObject(session, test->attr_key, test->attr_count, + &key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_subcase; + + /* + * Test 1: encrypt with multi stage operation C_EncryptUpdate() + */ + total_len = 0; + memset(out, 0, sizeof(out)); + + rv = C_EncryptInit(session, test->mechanism, key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + /* Encrypt plain text data, if any */ + if (test->ptx) { + /* Get output buffer size for plaintext encryption */ + out_size = 0; + rv = C_EncryptUpdate(session, (void *)test->ptx, + test->ptx_len, NULL, &out_size); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, out_size, <=, + sizeof(out))) + goto err_destr_obj; + + /* Encrypt plain text */ + rv = C_EncryptUpdate(session, (void *)test->ptx, + test->ptx_len, out, &out_size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + total_len += out_size; + } + + /* Finalize to get the tag: 1st get tag size then get tag data */ + out_size = 0; + rv = C_EncryptFinal(session, NULL, &out_size); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_OK, rv)) + goto err_destr_obj; + saved_size = out_size; + out_size = 0; + rv = C_EncryptFinal(session, out + total_len, &out_size); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_BUFFER_TOO_SMALL, rv)) + goto err_destr_obj; + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, out_size, ==, saved_size)) + goto err_destr_obj; + rv = C_EncryptFinal(session, out + total_len, &out_size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, out_size, ==, saved_size)) + goto err_destr_obj; + + total_len += out_size; + + /* Check ciphertext and tag */ + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, + test->ctx_len + test->tag_len, + ==, total_len)) + goto err_destr_obj; + + if (!ADBG_EXPECT_BUFFER(c, test->tag, test->tag_len, + out + test->ctx_len, test->tag_len)) + goto err_destr_obj; + + if (!ADBG_EXPECT_BUFFER(c, test->ctx, test->ctx_len, out, + test->ctx_len)) + goto err_destr_obj; + + /* + * Test 2: decrypt with multi stage operation C_DecryptUpdate() + */ + rv = C_DecryptInit(session, test->mechanism, key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + /* Concat ciphertext and tag */ + memcpy(in, test->ctx, test->ctx_len); + memcpy(in + test->ctx_len, test->tag, test->tag_len); + in_size = test->ctx_len + test->tag_len; + + /* Process decryption, when don't expect output data */ + out_size = sizeof(out); + rv = C_DecryptUpdate(session, (void *)in, in_size, out, + &out_size); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, out_size, ==, 0)) + goto err_destr_obj; + + /* Finalize and check MAC (get size then get data) */ + out_size = 0; + rv = C_DecryptFinal(session, NULL, &out_size); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, out_size, ==, + test->ptx_len)) + goto err_destr_obj; + + /* Get data only if there are plaintext data */ + if (out_size) { + rv = C_DecryptFinal(session, out, &out_size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + if (!ADBG_EXPECT_BUFFER(c, test->ptx, test->ptx_len, + out, out_size)) + goto err_destr_obj; + } + + /* + * Test 3: encrypt with mult-stage opetation C_EncryptUpdate() + * by 6 bytes chunks of plain text. + */ + rv = C_EncryptInit(session, test->mechanism, key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + proc_len = 0; + total_len = 0; + chunk_len = 0; + memset(chunk, 0, CHUNK_SIZE); + + while (proc_len < test->ptx_len) { + if (test->ptx_len - proc_len > CHUNK_SIZE) + chunk_len = CHUNK_SIZE; + else + chunk_len = test->ptx_len - proc_len; + + memcpy(chunk, test->ptx + proc_len, chunk_len); + + out_size = sizeof(out) - total_len; + rv = C_EncryptUpdate(session, chunk, chunk_len, + out + total_len, &out_size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + proc_len += chunk_len; + total_len += out_size; + } + + /* Finalize tag computing, but get output size first */ + out_size = 0; + rv = C_EncryptFinal(session, out + total_len, &out_size); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_BUFFER_TOO_SMALL, rv)) + goto err_destr_obj; + saved_size = out_size; + /* Test another way to get remaining data */ + out_size = 1; + rv = C_EncryptFinal(session, NULL, &out_size); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_OK, rv)) + goto err_destr_obj; + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, out_size, ==, saved_size)) + goto err_destr_obj; + + /* Now really finalize and get remaining data and tag */ + rv = C_EncryptFinal(session, out + total_len, &out_size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + total_len += out_size; + + /* Check ciphertext and tag */ + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, + test->ctx_len + test->tag_len, + ==, total_len)) + goto err_destr_obj; + + if (!ADBG_EXPECT_BUFFER(c, test->tag, test->tag_len, + out + test->ctx_len, test->tag_len)) + goto err_destr_obj; + + if (test->ctx && + !ADBG_EXPECT_BUFFER(c, test->ctx, test->ctx_len, out, + test->ctx_len)) + goto err_destr_obj; + + /* + * Test 4: decrypt with multi-stage operation C_DecryptUpdate() + * by 6 bytes chunks of plain text. + */ + rv = C_DecryptInit(session, test->mechanism, key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + /* Process ptx in 8-byte chunks */ + proc_len = 0; + total_len = 0; + chunk_len = 0; + while (proc_len < test->ctx_len) { + if (test->ctx_len - proc_len > CHUNK_SIZE) + chunk_len = CHUNK_SIZE; + else + chunk_len = test->ctx_len - proc_len; + + memcpy(chunk, test->ctx + proc_len, chunk_len); + + /* Decrypt the chunk, no output data expected */ + out_size = 1; + rv = C_DecryptUpdate(session, chunk, chunk_len, + out, &out_size); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, out_size, + ==, 0)) + goto err_destr_obj; + + proc_len += chunk_len; + } + + /* Decrypt the tag */ + out_size = sizeof(out); + in_size = test->tag_len; + rv = C_DecryptUpdate(session, (void *)test->tag, in_size, + out, &out_size); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, out_size, ==, 0)) + goto err_destr_obj; + + /* Check Plaintext (get output size then the data, if any) */ + out_size = 0; + rv = C_DecryptFinal(session, NULL, &out_size); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_OK, rv)) + goto err_destr_obj; + + if (out_size) { + saved_size = out_size; + out_size = 0; + rv = C_DecryptFinal(session, out, &out_size); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_BUFFER_TOO_SMALL, rv)) + goto err_destr_obj; + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, out_size, ==, + saved_size)) + goto err_destr_obj; + + rv = C_DecryptFinal(session, out, &out_size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, out_size, ==, + saved_size)) + goto err_destr_obj; + } + + /* Check output is expected plaintext */ + if (!ADBG_EXPECT_BUFFER(c, test->ptx, test->ptx_len, + out, out_size)) + goto err_destr_obj; + + /* + * Test 5: encrypt with one-shot operation C_Encrypt() + */ + rv = C_EncryptInit(session, test->mechanism, key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + /* Get output buffer size */ + out_size = 0; + rv = C_Encrypt(session, (void *)test->ptx, test->ptx_len, NULL, + &out_size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + if (out_size) { + saved_size = out_size; + + /* Test too short buffer case to get output data size */ + out_size = 1; + rv = C_Encrypt(session, (void *)test->ptx, + test->ptx_len, out, &out_size); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_BUFFER_TOO_SMALL, rv)) + goto err_destr_obj; + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, out_size, ==, + saved_size)) + goto err_destr_obj; + + /* Test NULL ref with non-zero size to get output data size */ + out_size = sizeof(out); + rv = C_Encrypt(session, (void *)test->ptx, + test->ptx_len, NULL, &out_size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, out_size, ==, + saved_size)) + goto err_destr_obj; + + /* Encrypt the whole plain text in one shot */ + memset(out, 0, out_size); + rv = C_Encrypt(session, (void *)test->ptx, + test->ptx_len, out, &out_size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, out_size, ==, + saved_size)) + goto err_destr_obj; + } + + /* Check Ciphertext + tag */ + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, + test->ctx_len + test->tag_len, + ==, out_size)) + goto err_destr_obj; + + if (!ADBG_EXPECT_BUFFER(c, test->ctx, test->ctx_len, out, + test->ctx_len)) + goto err_destr_obj; + + if (!ADBG_EXPECT_BUFFER(c, test->tag, test->tag_len, + out + test->ctx_len, test->tag_len)) + goto err_destr_obj; + + /* + * Test 6 decrypt with one shot operation C_Decrypt() + */ + rv = C_DecryptInit(session, test->mechanism, key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + /* Concat ciphertext and tag */ + memcpy(in, test->ctx, test->ctx_len); + memcpy(in + test->ctx_len, test->tag, test->tag_len); + in_size = test->ctx_len + test->tag_len; + + /* Test NULL output buffer ref to get output data size */ + out_size = 0; + rv = C_Decrypt(session, (void *)in, in_size, NULL, &out_size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + if (out_size) { + saved_size = out_size; + + /* Test too short buffer case to get output data size */ + out_size = 0; + rv = C_Decrypt(session, (void *)in, in_size, out, + &out_size); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_BUFFER_TOO_SMALL, rv)) + goto err_destr_obj; + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, out_size, ==, + saved_size)) + goto err_destr_obj; + + /* Test NULL ref with non-zero size to get output data size */ + out_size = 42; + rv = C_Decrypt(session, (void *)in, in_size, NULL, + &out_size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, out_size, ==, + saved_size)) + goto err_destr_obj; + + /* Decrypt the whole cipher text and tag in one shot */ + memset(out, 0, out_size); + rv = C_Decrypt(session, (void *)in, in_size, out, + &out_size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, out_size, ==, + saved_size)) + goto err_destr_obj; + } + + /* Check Plaintext */ + if (!ADBG_EXPECT_BUFFER(c, test->ptx, test->ptx_len, out, + out_size)) + goto err_destr_obj; + + /* + * Test 7 decrypt altered data + */ + if (test->ptx && test->ctx) { + rv = C_DecryptInit(session, test->mechanism, + key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + /* Concat ciphertext and tag */ + memcpy(in, test->ctx, test->ctx_len); + memcpy(in + test->ctx_len, test->tag, test->tag_len); + in_size = test->ctx_len + test->tag_len; + + /* Alter ciphertext and try to decrypt */ + in[0] ^= 1; + out_size = sizeof(out); + rv = C_Decrypt(session, (void *)in, in_size, out, + &out_size); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_SIGNATURE_INVALID, + rv)) + goto err_destr_obj; + + /* Restore ciphertext, alter tag and try to decrypt */ + rv = C_DecryptInit(session, test->mechanism, + key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + in[0] ^= 1; + in[test->ctx_len] ^= 1; + out_size = sizeof(out); + rv = C_Decrypt(session, (void *)in, in_size, out, + &out_size); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_SIGNATURE_INVALID, + rv)) + goto err_destr_obj; + } + + /* + * We're done, release resources use by the subcase test + */ + rv = C_DestroyObject(session, key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_subcase; + + Do_ADBG_EndSubCase(c, NULL); + } + goto out; + +err_destr_obj: + ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, key_handle)); +err_subcase: + Do_ADBG_EndSubCase(c, NULL); +out: + ADBG_EXPECT_CK_OK(c, C_CloseSession(session)); +out_close_lib: + ADBG_EXPECT_CK_OK(c, close_lib()); +} +ADBG_CASE_DEFINE(pkcs11, 1030, xtest_pkcs11_test_1030, + "PKCS11: Test AES-GCM Encryption/Decryption"); diff --git a/optee/optee_test/host/xtest/pkcs11_1000.h b/optee/optee_test/host/xtest/pkcs11_1000.h new file mode 100644 index 0000000..0d19748 --- /dev/null +++ b/optee/optee_test/host/xtest/pkcs11_1000.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2023, Linaro Limited + */ + +#ifndef XTEST_PKCS11_1000_H +#define XTEST_PKCS11_1000_H + +/* Helper function for finding and detroying a token object */ +int xtest_pkcs11_1028_destroy_token_object(void); + +#endif /*XTEST_PKCS11_1000_H*/ 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..9981d01 --- /dev/null +++ b/optee/optee_test/host/xtest/regression_1000.c @@ -0,0 +1,3363 @@ +// 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 "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; + int dummy = 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)); + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_INOUT, + TEEC_MEMREF_TEMP_OUTPUT, + TEEC_NONE); + + op.params[0].tmpref.buffer = &dummy; + op.params[0].tmpref.size = 0; + + op.params[1].tmpref.buffer = &dummy; + op.params[1].tmpref.size = 0; + + op.params[2].tmpref.buffer = &dummy; + op.params[2].tmpref.size = 0; + + (void)ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_TA2TA_MEMREF_SIZE0, + &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.imp.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"); + return; + } + ADBG_EXPECT_TEEC_SUCCESS(c, res); + if (!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; + } + + TEEC_CloseSession(&session); + + 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"); + +struct test_1040_thread_arg { + TEEC_Result res; + pthread_t thr; +}; + +static void *test_1040_thread(void *arg) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + struct test_1040_thread_arg *a = arg; + TEEC_Result res = TEEC_SUCCESS; + uint32_t err_orig = 0; + TEEC_Session session = { }; + size_t loop_count = 100; + size_t n = 0; + + if (level == 0) + loop_count /= 2; + + while (n < loop_count) { + res = xtest_teec_open_session(&session, &sims_test_ta_uuid, + NULL, &err_orig); + if (res) { + if (res == TEEC_ERROR_TARGET_DEAD) + continue; + a->res = res; + return NULL; + } + + memset(&op, 0, sizeof(op)); + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_NONE, TEEC_NONE, + TEEC_NONE); + res = TEEC_InvokeCommand(&session, TA_SIMS_CMD_PANIC, &op, + &err_orig); + TEEC_CloseSession(&session); + if (res != TEEC_ERROR_TARGET_DEAD) { + if (res) + a->res = res; + else + a->res = TEEC_ERROR_GENERIC; + return NULL; + } + n++; + } + a->res = TEEC_SUCCESS; + return NULL; +} + +static void xtest_tee_test_1040(ADBG_Case_t *c) +{ + struct test_1040_thread_arg arg[NUM_THREADS] = { }; + size_t nt = NUM_THREADS; + size_t n = 0; + + Do_ADBG_BeginSubCase(c, "Concurent invoke with panic in TA"); + for (n = 0; n < nt; n++) { + if (!ADBG_EXPECT(c, 0, pthread_create(&arg[n].thr, NULL, + test_1040_thread, + arg + n))) + nt = n; /* break loop and start cleanup */ + } + for (n = 0; n < nt; n++) { + ADBG_EXPECT(c, 0, pthread_join(arg[n].thr, NULL)); + ADBG_EXPECT_TEEC_SUCCESS(c, arg[n].res); + } + Do_ADBG_EndSubCase(c, "Concurent invoke with panic in TA"); +} +ADBG_CASE_DEFINE(regression, 1040, xtest_tee_test_1040, + "Test panic in concurrent open/invoke/close session"); 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..5e81211 --- /dev/null +++ b/optee/optee_test/host/xtest/regression_4000.c @@ -0,0 +1,6200 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2021, SumUp Services GmbH + * Copyright 2023 NXP + */ + +#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), + XTEST_MAC_CMAC_CASE(vect13, 1), + + { 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; + uint32_t id; +}; + + +#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__, 0 }, \ + { (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__, 0 } + +#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 +#include "aes_gcm_counter_overflow_test_encrypt.h" +#include "aes_gcm_counter_overflow_test_decrypt.h" +}; + +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++) { + if (ae_cases[n].id) + Do_ADBG_BeginSubCase(c, "AE case %d algo 0x%x line %d id %d", + (int)n, (unsigned int)ae_cases[n].algo, + (int)ae_cases[n].line, + (unsigned int)ae_cases[n].id); + else + 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; + uint32_t sha1_algo_id = TEE_ALG_SHA1; + + 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(sha1_algo_id); + algo_params[0].content.ref.buffer = + &sha1_algo_id; + 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 is_caam_black_key(uint8_t *buf, size_t size) +{ + /* + * This value is a magic number for the a CAAM Black key. This value + * must match the value defined in optee-os + * core/drivers/crypto/caam/caam_key.c + */ + const uint8_t magic_number[4] = {0xFB, 0xBF, 0xAF, 0xCA}; + + if (size < sizeof(magic_number)) + return false; + + return !memcmp(buf, magic_number, sizeof(magic_number)); +} + +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; + + /* + * Check for CAAM black key header. If the buffer holds + * a CAAM black key, do not check the key size as the + * buffer size and the key size do not match. + */ + if (attrs[m].keysize_check && + !is_caam_black_key(out, out_size)) + 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..ae469b3 --- /dev/null +++ b/optee/optee_test/host/xtest/regression_4000_data.h @@ -0,0 +1,9070 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2021, SumUp Services GmbH + * Copyright 2023 NXP + */ + +#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 +}; + +#define mac_cmac_vect13_key mac_cmac_vect1_key +static const uint8_t mac_cmac_vect13_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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, +}; + +static const uint8_t mac_cmac_vect13_out[] = { + 0xF6, 0xDC, 0xBF, 0x9A, 0x5A, 0x3E, 0x1E, 0xF9, + 0x7B, 0xE1, 0x02, 0x08, 0x5B, 0xF4, 0x19, 0x7F, +}; + +/* + * 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..86462ba --- /dev/null +++ b/optee/optee_test/host/xtest/regression_6000.c @@ -0,0 +1,2318 @@ +// 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)"); + +static void xtest_tee_test_6021_single(ADBG_Case_t *c, uint32_t storage_id) +{ + const uint32_t flags = TEE_DATA_FLAG_ACCESS_READ | + TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_ACCESS_WRITE_META; + TEEC_Result res = TEEC_ERROR_GENERIC; + TEE_ObjectInfo obj_info = { }; + uint32_t ou = 0xffffffff; + TEEC_Session sess = { }; + uint32_t orig = 0; + uint32_t obj = 0; + + 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), + flags | TEE_DATA_FLAG_OVERWRITE, 0, + data_00, sizeof(data_00), &obj, storage_id); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto exit; + + res = fs_get_obj_info(&sess, obj, &obj_info); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto exit; + ADBG_EXPECT_COMPARE_UNSIGNED(c, obj_info.objectUsage, ==, ou); + + ou &= ~TEE_USAGE_EXTRACTABLE; + res = fs_restrict_usage(&sess, obj, ou); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto exit; + + res = fs_get_obj_info(&sess, obj, &obj_info); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto exit; + ADBG_EXPECT_COMPARE_UNSIGNED(c, obj_info.objectUsage, ==, ou); + + ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, obj)); + 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), flags, &obj, storage_id); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto exit; + + res = fs_get_obj_info(&sess, obj, &obj_info); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto exit; + ADBG_EXPECT_COMPARE_UNSIGNED(c, obj_info.objectUsage, ==, ou); + +exit: + ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj)); + TEEC_CloseSession(&sess); + return; +} +DEFINE_TEST_MULTIPLE_STORAGE_IDS(xtest_tee_test_6021) +ADBG_CASE_DEFINE(regression, 6021, xtest_tee_test_6021, + "Modify and check persistent object usage"); 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..45a7c0e --- /dev/null +++ b/optee/optee_test/host/xtest/sdp_basic.c @@ -0,0 +1,698 @@ +// 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 *applet_optname, size_t size, int loop, + const char *heap_name) +{ + fprintf(stderr, "Usage: %s %s [OPTION]\n", xtest_progname, applet_optname); + 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: %s: missing argument\n", \ + xtest_progname, 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 %s: invalid argument: %s\n", + xtest_progname, 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..fb16d55 --- /dev/null +++ b/optee/optee_test/host/xtest/stats.c @@ -0,0 +1,371 @@ +// 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 +#include "xtest_helpers.h" +#include "xtest_test.h" +#include "stats.h" + +static int usage(void) +{ + fprintf(stderr, "Usage: %s --stats [OPTION]\n", xtest_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"); + fprintf(stderr, " --time Print REE and TEE time\n"); + fprintf(stderr, " --clocks Dump clock tree on secure console\n"); + fprintf(stderr, " --regulators Dump regulator tree on secure console\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 pta_stats_alloc *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 pta_stats_ta *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_num); + 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); +} + +static int stat_system_time(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_NONE, TEEC_NONE); + res = TEEC_InvokeCommand(&sess, STATS_CMD_GET_TIME, &op, &eo); + if (res != TEEC_SUCCESS) + errx(EXIT_FAILURE, + "TEEC_InvokeCommand: res %#"PRIx32" err_orig %#"PRIx32, + res, eo); + + printf("REE time: %"PRId32" seconds, %"PRId32" milliseconds\n", + op.params[0].value.a, op.params[0].value.b); + printf("TEE time: %"PRId32" seconds, %"PRId32" milliseconds\n", + op.params[1].value.a, op.params[1].value.b); + + return close_sess(&ctx, &sess); +} + +static int stat_driver_info(int argc, int driver_type) +{ + TEEC_Context ctx = { }; + TEEC_Session sess = { }; + TEEC_Result res = TEEC_ERROR_GENERIC; + uint32_t eo = 0; + TEEC_Operation op = { }; + + if (argc != 1) + return usage(); + + open_sess(&ctx, &sess); + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_NONE, TEEC_NONE, TEEC_NONE); + op.params[0].value.a = driver_type; + + res = TEEC_InvokeCommand(&sess, STATS_CMD_PRINT_DRIVER_INFO, &op, &eo); + if (res != TEEC_SUCCESS) + errx(EXIT_FAILURE, + "TEEC_InvokeCommand(): res %#"PRIx32" err_orig %#"PRIx32, + res, eo); + + 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); + if (!strcmp(argv[1], "--time")) + return stat_system_time(argc - 1, argv + 1); + if (!strcmp(argv[1], "--clocks")) + return stat_driver_info(argc - 1, + STATS_DRIVER_TYPE_CLOCK); + if (!strcmp(argv[1], "--regulators")) + return stat_driver_info(argc - 1, + STATS_DRIVER_TYPE_REGULATOR); + } + + 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/symm_cipher_perf.c b/optee/optee_test/host/xtest/symm_cipher_perf.c new file mode 100644 index 0000000..906391b --- /dev/null +++ b/optee/optee_test/host/xtest/symm_cipher_perf.c @@ -0,0 +1,753 @@ +// 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 + +#include "crypto_common.h" +#include "xtest_helpers.h" +#include "xtest_test.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_CRYPTO_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 *cipher_str(uint32_t algo) +{ + switch (algo) { + case TA_AES_ECB: + case TA_AES_CBC: + case TA_AES_CTR: + case TA_AES_XTS: + case TA_AES_GCM: + return "AES"; + case TA_SM4_ECB: + case TA_SM4_CBC: + case TA_SM4_CTR: + case TA_SM4_XTS: + return "SM4"; + default: + return "???"; + } +} + +static const char *mode_str(uint32_t algo) +{ + switch (algo) { + case TA_AES_ECB: + case TA_SM4_ECB: + return "ECB"; + case TA_AES_CBC: + case TA_SM4_CBC: + return "CBC"; + case TA_AES_CTR: + case TA_SM4_CTR: + return "CTR"; + case TA_AES_XTS: + case TA_SM4_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 *applet_optname, int keysize, int algo, + size_t size, size_t unit, int warmup, unsigned int l, + unsigned int n) +{ + fprintf(stderr, "Usage: %s %s [-h]\n", xtest_progname, applet_optname); + fprintf(stderr, "Usage: %s %s [-d] [-i] [-k SIZE]", xtest_progname, applet_optname); + fprintf(stderr, " [-l LOOP] [-c CIPHER] [-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/SM4 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, " -c CIPHER cipher: AES, SM4 [%s]\n", cipher_str(algo)); + fprintf(stderr, " -m MODE mode: ECB, CBC, CTR, XTS, GCM [%s]\n", mode_str(algo)); + 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 algo) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + uint32_t ret_origin = 0; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t cmd = TA_CRYPTO_PERF_CMD_CIPHER_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 = algo; + 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 algo, 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_CRYPTO_PERF_CMD_CIPHER_PROCESS_SDP : + TA_CRYPTO_PERF_CMD_CIPHER_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, algo); + + 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(algo), (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: %s: missing argument\n", \ + xtest_progname, argv[0], argv[i - 1]); \ + return 1; \ + } \ + } while (0); + +#define USAGE() usage(argv[0], keysize, algo, size, unit, warmup, l, n) + +static int get_symm_algo(int cipher, int mode) +{ + if (cipher == AES) { + switch (mode) { + case ECB: + return TA_AES_ECB; + case CBC: + return TA_AES_CBC; + case CTR: + return TA_AES_CTR; + case XTS: + return TA_AES_XTS; + case GCM: + return TA_AES_GCM; + default: + return -1; + } + } else if (cipher == SM4) { + switch (mode) { + case ECB: + return TA_SM4_ECB; + case CBC: + return TA_SM4_CBC; + case CTR: + return TA_SM4_CTR; + case XTS: + return TA_SM4_XTS; + default: + return -1; + } + } else { + return -1; + } +} + +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 cipher = AES; + int mode = ECB; + int algo = -1; + /* 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 %s: invalid key size\n", + xtest_progname, argv[0]); + USAGE(); + return 1; + } + } else if (!strcmp(argv[i], "-l")) { + NEXT_ARG(i); + l = atoi(argv[i]); + } else if (!strcmp(argv[i], "-c")) { + NEXT_ARG(i); + if (!strcasecmp(argv[i], "SM4")) + cipher = SM4; + else if (!strcasecmp(argv[i], "AES")) + cipher = AES; + else { + fprintf(stderr, "%s %s, invalid cipher\n", + xtest_progname, argv[0]); + USAGE(); + return 1; + } + } else if (!strcmp(argv[i], "-m")) { + NEXT_ARG(i); + if (!strcasecmp(argv[i], "ECB")) + mode = ECB; + else if (!strcasecmp(argv[i], "CBC")) + mode = CBC; + else if (!strcasecmp(argv[i], "CTR")) + mode = CTR; + else if (!strcasecmp(argv[i], "XTS")) + mode = XTS; + else if (!strcasecmp(argv[i], "GCM")) + mode = GCM; + else { + fprintf(stderr, "%s %s, invalid mode\n", + xtest_progname, 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 %s: invalid argument: %s\n", + xtest_progname, argv[0], argv[i]); + USAGE(); + return 1; + } + } + + algo = get_symm_algo(cipher, mode); + assert(algo != -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(algo, keysize, decrypt, size, unit, n, l, + input_data_init, in_place, warmup, verbosity); + + return 0; +} 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..62aef61 --- /dev/null +++ b/optee/optee_test/host/xtest/xtest_main.c @@ -0,0 +1,292 @@ +// 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 "clear_storage.h" +#include "crypto_common.h" +#include "install_ta.h" +#include "pkcs11_1000.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_progname; +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"); + printf("\t--asym-perf [opts] Asym 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 +#ifdef CFG_PKCS11_TA + printf("\t--pkcs11-1028-destroy-token-object Used internally by pkcs11_1028\n"); +#endif + printf("\t--stats [opts] Various statistics ('-h' for usage)\n"); + printf("\t--clear-storage Delete any persistent objects that may have been\n"); + printf("\t left over by a previous run of this application\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(); + + /* Reference xtest command name for global use */ + xtest_progname = argv[0]; + + 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]); + else if (argc > 1 && !strcmp(argv[1], "--asym-perf")) + return asym_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 +#ifdef CFG_PKCS11_TA + else if (argc == 2 && !strcmp(argv[1], "--pkcs11-1028-destroy-token-object")) + return xtest_pkcs11_1028_destroy_token_object(); +#endif + else if (argc > 1 && !strcmp(argv[1], "--stats")) + return stats_runner_cmd_parser(argc - 1, &argv[1]); + else if (argc == 2 && !strcmp(argv[1], "--clear-storage")) + return clear_storage(); + + 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..0b21ef1 --- /dev/null +++ b/optee/optee_test/host/xtest/xtest_test.h @@ -0,0 +1,147 @@ +/* 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; +extern char *xtest_progname; + +#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..2e1d8e2 --- /dev/null +++ b/optee/optee_test/host/xtest/xtest_uuid_helpers.c @@ -0,0 +1,175 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019, Linaro Limited + */ + +#include +#include +#ifdef OPENSSL_FOUND +#include +#endif +#include +#include +#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/aes_gcm_test.py b/optee/optee_test/scripts/aes_gcm_test.py new file mode 100644 index 0000000..1c13e0d --- /dev/null +++ b/optee/optee_test/scripts/aes_gcm_test.py @@ -0,0 +1,80 @@ +# importing the module +import json + +modes = {'encrypt': 0, 'decrypt': 1} + + +def to_compound_str(name, val): + assert len(val) % 2 == 0, "Only even sized values supported" + if len(val) > 0: + import re + a = re.findall('..', val) + b = name + " = (const uint8_t []){ " + for s in a: + b += "0x" + s + ", " + b += "},\n\t" + name + "_len = " + repr((int)(len(val) / 2)) + "," + else: + b = name + " = NULL,\n\t" + name + "_len = 0," + return b + + +def generate_case(outf, tv, mode): + outf.write('{\n\t.algo = TEE_ALG_AES_GCM, .mode = ' + mode + + ', .key_type = TEE_TYPE_AES,\n') + outf.write('\t' + to_compound_str('.key', tv['key']) + '\n') + outf.write('\t' + to_compound_str('.nonce', tv['iv']) + '\n') + outf.write('\t.aad_incr = 0,\n') + outf.write('\t' + to_compound_str('.aad', tv['aad']) + '\n') + outf.write('\t.in_incr = 0,\n') + outf.write('\t' + to_compound_str('.ptx', tv['msg']) + '\n') + outf.write('\t' + to_compound_str('.ctx', tv['ct']) + '\n') + outf.write('\t' + to_compound_str('.tag', tv['tag']) + '\n') + outf.write('\t.line = __LINE__,\n') + outf.write('\t.id = ' + repr(tv['tcId']) + '\n},\n') + + +def get_args(): + import argparse + + parser = argparse.ArgumentParser() + + parser.add_argument('--inf', required=True, + type=argparse.FileType('r'), + help='Name of input json 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') + + return parser.parse_args() + + +# Convert google/wycheproof AES GCM test vectors to xtest AE test cases +def main(): + args = get_args() + inf = args.inf + outf = args.outf + + outf.write("/* SPDX-License-Identifier: Apache-2.0 */\n") + outf.write("/*\n") + outf.write(" * Copyright 2024 NXP\n") + outf.write(" */\n\n") + + if args.mode == "encrypt": + mode = "TEE_MODE_ENCRYPT" + else: + mode = "TEE_MODE_DECRYPT" + + data = json.load(inf) + + for tg in data['testGroups']: + for tv in tg['tests']: + if tv['result'] == 'valid' and 'CounterWrap' in tv['flags']: + generate_case(outf, tv, mode) + + +if __name__ == "__main__": + main() 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..cef4598 --- /dev/null +++ b/optee/optee_test/scripts/rsp_to_gcm_test.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2017, Linaro Limited +# + +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..7d1316f --- /dev/null +++ b/optee/optee_test/ta/CMakeLists.txt @@ -0,0 +1,27 @@ +project (xtest-ta-headers C) + +add_library(${PROJECT_NAME} INTERFACE) + +target_include_directories(${PROJECT_NAME} + INTERFACE include + INTERFACE concurrent/include + INTERFACE concurrent_large/include + INTERFACE create_fail_test/include + INTERFACE crypt/include + INTERFACE crypto_perf/include + INTERFACE enc_fs/include + INTERFACE os_test/include + INTERFACE rpc_test/include + INTERFACE sdp_basic/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..d85c9bc --- /dev/null +++ b/optee/optee_test/ta/Makefile @@ -0,0 +1,63 @@ +# 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 \ + crypto_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/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..f7670bf --- /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); + + 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, NULL, NULL); + 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.MBEDTLS_PRIVATE(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/crypto_perf/Android.mk b/optee/optee_test/ta/crypto_perf/Android.mk new file mode 100644 index 0000000..1763ae1 --- /dev/null +++ b/optee/optee_test/ta/crypto_perf/Android.mk @@ -0,0 +1,4 @@ +LOCAL_PATH := $(call my-dir) + +local_module := 02a42f43-d8b7-4a57-aa4d-87bd9b5587cb.ta +include $(BUILD_OPTEE_MK) diff --git a/optee/optee_test/ta/crypto_perf/Makefile b/optee/optee_test/ta/crypto_perf/Makefile new file mode 100644 index 0000000..830a53b --- /dev/null +++ b/optee/optee_test/ta/crypto_perf/Makefile @@ -0,0 +1,4 @@ +BINARY = 02a42f43-d8b7-4a57-aa4d-87bd9b5587cb + +include ../ta_common.mk + diff --git a/optee/optee_test/ta/crypto_perf/include/ta_crypto_perf.h b/optee/optee_test/ta/crypto_perf/include/ta_crypto_perf.h new file mode 100644 index 0000000..4d0b6c0 --- /dev/null +++ b/optee/optee_test/ta/crypto_perf/include/ta_crypto_perf.h @@ -0,0 +1,147 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + */ + +#ifndef TA_CRYPTO_PERF_H +#define TA_CRYPTO_PERF_H + +#define TA_CRYPTO_PERF_UUID { 0x02a42f43, 0xd8b7, 0x4a57, \ + { 0xaa, 0x4d, 0x87, 0xbd, 0x9b, 0x55, 0x87, 0xcb } } + +/* + * Commands implemented by the TA + */ + +#define TA_CRYPTO_PERF_CMD_CIPHER_PREPARE_KEY 0 +#define TA_CRYPTO_PERF_CMD_CIPHER_PROCESS 1 +#define TA_CRYPTO_PERF_CMD_CIPHER_PROCESS_SDP 2 +#define TA_CRYPTO_PERF_CMD_HASH_PREPARE_OP 3 +#define TA_CRYPTO_PERF_CMD_HASH_PROCESS 4 +#define TA_CRYPTO_PERF_CMD_ASYM_PREPARE_OBJ 5 +#define TA_CRYPTO_PERF_CMD_ASYM_PREPARE_HASH 6 +#define TA_CRYPTO_PERF_CMD_ASYM_PREPARE_KEYPAIR 7 +#define TA_CRYPTO_PERF_CMD_ASYM_PREPARE_ENC_SIGN 8 +#define TA_CRYPTO_PERF_CMD_ASYM_PREPARE_ATTRS 9 +#define TA_CRYPTO_PERF_CMD_ASYM_PROCESS_GEN_KEYPAIR 10 +#define TA_CRYPTO_PERF_CMD_ASYM_PROCESS 11 +#define TA_CRYPTO_PERF_CMD_ASYM_FREE_ATTRS 12 + +/* + * 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 +#define TA_SM4_ECB 5 +#define TA_SM4_CBC 6 +#define TA_SM4_CTR 7 +#define TA_SM4_XTS 8 + +/* + * AES key sizes + */ +#define AES_128 128 +#define AES_192 192 +#define AES_256 256 + +/* + * Supported hash 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 + +/* + * Asymmetric cryptographic algorithms + */ +#define PKCS_V1_5_MIN 11 +#define BITS_TO_BYTES(len) (((len) + 7) / 8) +#define OAEP_HASH_LEN(hsz) ((hsz) * 2) +#define OAEP_OTHER_LEN 2 +#define PSS_OTHER_LEN 2 + +#define DERCODE_SHA1_LEN 15 +#define DERCODE_SHA_LEN 19 +#define SHA1_LEN 20 +#define SHA224_LEN 28 +#define SHA256_LEN 32 +#define SHA384_LEN 48 +#define SHA512_LEN 64 + +#define WIDTH_BITS_25519 256 + +#define ECC_CURVE_192 192 +#define ECC_CURVE_224 224 +#define ECC_CURVE_256 256 +#define ECC_CURVE_384 384 +#define ECC_CURVE_521 521 + +#define TEE_MAX_OUT_SIZE 4096 + +#define DH_MAX_SIZE 4096 +#define DH_G_SIZE 1 + +enum symm_cipher { + AES = 0, + SM4 = 1, +}; + +enum symm_mode { + ECB = 0, + CBC = 1, + CTR = 2, + XTS = 3, + GCM = 4, +}; + +enum asym_algorithm { + ALGO_DH = 1, + ALGO_RSA = 2, + ALGO_ECDSA = 3, + ALGO_ECDH = 4, + ALGO_X25519 = 5, +}; + +enum asym_cipher_mode { + MODE_ENCRYPT = 0, + MODE_DECRYPT = 1, + MODE_SIGN = 2, + MODE_VERIFY = 3, + MODE_GENKEYPAIR = 4, +}; + +enum rsa_mode { + RSA_NOPAD = 0, + RSAES_PKCS1_V1_5 = 1, + RSAES_PKCS1_OAEP_SHA1 = 2, + RSAES_PKCS1_OAEP_SHA224 = 3, + RSAES_PKCS1_OAEP_SHA256 = 4, + RSAES_PKCS1_OAEP_SHA384 = 5, + RSAES_PKCS1_OAEP_SHA512 = 6, + RSASSA_PKCS1_V1_5_SHA1 = 7, + RSASSA_PKCS1_V1_5_SHA224 = 8, + RSASSA_PKCS1_V1_5_SHA256 = 9, + RSASSA_PKCS1_V1_5_SHA384 = 10, + RSASSA_PKCS1_V1_5_SHA512 = 11, + RSASSA_PKCS1_PSS_MGF1_SHA1 = 12, + RSASSA_PKCS1_PSS_MGF1_SHA224 = 13, + RSASSA_PKCS1_PSS_MGF1_SHA256 = 14, + RSASSA_PKCS1_PSS_MGF1_SHA384 = 15, + RSASSA_PKCS1_PSS_MGF1_SHA512 = 16, +}; + +#endif /* TA_CRYPTO_PERF_H */ diff --git a/optee/optee_test/ta/crypto_perf/include/ta_crypto_perf_priv.h b/optee/optee_test/ta/crypto_perf/include/ta_crypto_perf_priv.h new file mode 100644 index 0000000..5959cc2 --- /dev/null +++ b/optee/optee_test/ta/crypto_perf/include/ta_crypto_perf_priv.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + */ + +#ifndef TA_CRYPTO_PERF_PRIV_H +#define TA_CRYPTO_PERF_PRIV_H + +#include + +TEE_Result cmd_cipher_prepare_key(uint32_t param_types, TEE_Param params[4]); +TEE_Result cmd_cipher_process(uint32_t param_types, TEE_Param params[4], + bool sdp); +TEE_Result cmd_hash_prepare_op(uint32_t param_types, TEE_Param params[4]); +TEE_Result cmd_hash_process(uint32_t param_types, TEE_Param params[4]); +TEE_Result cmd_asym_process_keypair(uint32_t param_types, TEE_Param params[4]); +TEE_Result cmd_asym_process_rsa_ecc(uint32_t param_types, TEE_Param params[4]); +TEE_Result cmd_asym_prepare_obj(uint32_t param_types, TEE_Param params[4]); +TEE_Result cmd_asym_prepare_keypair(uint32_t param_types, TEE_Param params[4]); +TEE_Result cmd_asym_prepare_hash(uint32_t param_types, TEE_Param params[4]); +TEE_Result cmd_asym_prepare_enc_sign(uint32_t param_types, TEE_Param params[4]); +TEE_Result cmd_asym_prepare_attrs(uint32_t param_types, TEE_Param params[4]); +TEE_Result cmd_asym_free_attrs(uint32_t param_types, TEE_Param params[4]); +void cmd_clean_obj(void); +void cmd_clean_res(void); + +#endif /* TA_CRYPTO_PERF_PRIV_H */ diff --git a/optee/optee_test/ta/crypto_perf/include/user_ta_header_defines.h b/optee/optee_test/ta/crypto_perf/include/user_ta_header_defines.h new file mode 100644 index 0000000..dd8cc08 --- /dev/null +++ b/optee/optee_test/ta/crypto_perf/include/user_ta_header_defines.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + */ + +#ifndef USER_TA_HEADER_DEFINES_H +#define USER_TA_HEADER_DEFINES_H + +#include "ta_crypto_perf.h" + +#define TA_UUID TA_CRYPTO_PERF_UUID + +#define TA_FLAGS 0 + +#define TA_STACK_SIZE (2 * 1024) +#define TA_DATA_SIZE (32 * 1024) + +#endif diff --git a/optee/optee_test/ta/crypto_perf/sub.mk b/optee/optee_test/ta/crypto_perf/sub.mk new file mode 100644 index 0000000..2555292 --- /dev/null +++ b/optee/optee_test/ta/crypto_perf/sub.mk @@ -0,0 +1,3 @@ +global-incdirs-y += include +srcs-y += ta_entry.c +srcs-y += ta_crypto_perf.c diff --git a/optee/optee_test/ta/crypto_perf/ta_crypto_perf.c b/optee/optee_test/ta/crypto_perf/ta_crypto_perf.c new file mode 100644 index 0000000..df52d02 --- /dev/null +++ b/optee/optee_test/ta/crypto_perf/ta_crypto_perf.c @@ -0,0 +1,992 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "ta_crypto_perf.h" +#include "ta_crypto_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; +static uint32_t algo; +static TEE_OperationHandle crypto_op_enc_sign = TEE_HANDLE_NULL; +static TEE_ObjectHandle crypto_obj = TEE_HANDLE_NULL; +static TEE_Attribute *asym_perf_attrs; +static uint32_t asym_perf_attr_count; +static uint8_t *crypto_buf; + +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_cipher_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_cipher_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_ObjectType objectType; + 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 cipher_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 cipher_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; + objectType = TEE_TYPE_AES; + use_iv = 0; + break; + case TA_AES_CBC: + algo = TEE_ALG_AES_CBC_NOPAD; + objectType = TEE_TYPE_AES; + use_iv = 1; + break; + case TA_AES_CTR: + algo = TEE_ALG_AES_CTR; + objectType = TEE_TYPE_AES; + use_iv = 1; + break; + case TA_AES_XTS: + algo = TEE_ALG_AES_XTS; + objectType = TEE_TYPE_AES; + use_iv = 1; + op_keysize *= 2; + break; + case TA_AES_GCM: + algo = TEE_ALG_AES_GCM; + objectType = TEE_TYPE_AES; + use_iv = 1; + break; + case TA_SM4_ECB: + algo = TEE_ALG_SM4_ECB_NOPAD; + objectType = TEE_TYPE_SM4; + use_iv = 0; + break; + case TA_SM4_CBC: + algo = TEE_ALG_SM4_CBC_NOPAD; + objectType = TEE_TYPE_SM4; + use_iv = 1; + break; + case TA_SM4_CTR: + algo = TEE_ALG_SM4_CTR; + objectType = TEE_TYPE_SM4; + use_iv = 1; + break; + case TA_SM4_XTS: + algo = TEE_ALG_SM4_XTS; + objectType = TEE_TYPE_SM4; + use_iv = 1; + op_keysize *= 2; + 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(objectType, keysize, &hkey); + CHECK(res, "TEE_AllocateTransientObject", return res;); + + attr.attributeID = TEE_ATTR_SECRET_VALUE; + attr.content.ref.buffer = cipher_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 || algo == TEE_ALG_SM4_XTS) { + res = TEE_AllocateTransientObject(objectType, keysize, &hkey2); + CHECK(res, "TEE_AllocateTransientObject", return res;); + + attr.content.ref.buffer = cipher_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; + } +} + +static bool is_mac(uint32_t hash_algo) +{ + switch (hash_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_hash_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(crypto_op, &info); + + if (is_mac(info.algorithm)) { + while (n--) { + TEE_MACInit(crypto_op, NULL, 0); + res = TEE_MACComputeFinal(crypto_op, in, insz, out, &outsz); + CHECK(res, "TEE_MACComputeFinal", return res;); + } + } else { + while (n--) { + res = TEE_DigestDoFinal(crypto_op, in, insz, out, &outsz); + CHECK(res, "TEE_DigestDoFinal", return res;); + } + } + + return TEE_SUCCESS; +} + +TEE_Result cmd_hash_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 hash_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: + hash_algo = TEE_ALG_SHA1; + break; + case TA_SHA_SHA224: + hash_algo = TEE_ALG_SHA224; + break; + case TA_SHA_SHA256: + hash_algo = TEE_ALG_SHA256; + break; + case TA_SHA_SHA384: + hash_algo = TEE_ALG_SHA384; + break; + case TA_SHA_SHA512: + hash_algo = TEE_ALG_SHA512; + break; + case TA_SM3: + hash_algo = TEE_ALG_SM3; + break; + case TA_HMAC_SHA1: + key_type = TEE_TYPE_HMAC_SHA1; + hash_algo = TEE_ALG_HMAC_SHA1; + max_key_size = 512; + break; + case TA_HMAC_SHA224: + key_type = TEE_TYPE_HMAC_SHA224; + hash_algo = TEE_ALG_HMAC_SHA224; + max_key_size = 512; + break; + case TA_HMAC_SHA256: + key_type = TEE_TYPE_HMAC_SHA256; + hash_algo = TEE_ALG_HMAC_SHA256; + max_key_size = 512; + break; + case TA_HMAC_SHA384: + key_type = TEE_TYPE_HMAC_SHA384; + hash_algo = TEE_ALG_HMAC_SHA384; + max_key_size = 1024; + break; + case TA_HMAC_SHA512: + key_type = TEE_TYPE_HMAC_SHA512; + hash_algo = TEE_ALG_HMAC_SHA512; + max_key_size = 1024; + break; + case TA_HMAC_SM3: + key_type = TEE_TYPE_HMAC_SM3; + hash_algo = TEE_ALG_HMAC_SM3; + max_key_size = 512; + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + + if (crypto_op) + TEE_FreeOperation(crypto_op); + + if (is_mac(hash_algo)) { + res = TEE_AllocateOperation(&crypto_op, hash_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(crypto_op, hkey); + CHECK(res, "TEE_SetOperationKey", return res;); + + TEE_FreeTransientObject(hkey); + } else { + res = TEE_AllocateOperation(&crypto_op, hash_algo, TEE_MODE_DIGEST, 0); + CHECK(res, "TEE_AllocateOperation", return res;); + } + 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 (!IS_ALIGNED_WITH_TYPE(buf, uint32_t) || 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 = 0; + + 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 = 0; + + 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; + } + } + +out: + if (res == TEE_SUCCESS) { + *attrs = a; + *attr_count = num_attrs; + } else { + TEE_Free(a); + } + return res; +} + +static TEE_Result get_rsa_cipher_algo(uint32_t algo_type) +{ + switch (algo_type) { + case RSA_NOPAD: + algo = TEE_ALG_RSA_NOPAD; + break; + case RSAES_PKCS1_V1_5: + algo = TEE_ALG_RSAES_PKCS1_V1_5; + break; + case RSAES_PKCS1_OAEP_SHA1: + algo = TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1; + break; + case RSAES_PKCS1_OAEP_SHA224: + algo = TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224; + break; + case RSAES_PKCS1_OAEP_SHA256: + algo = TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256; + break; + case RSAES_PKCS1_OAEP_SHA384: + algo = TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384; + break; + case RSAES_PKCS1_OAEP_SHA512: + algo = TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512; + break; + default: + EMSG("RSA enc or dec error algo_type"); + return TEE_ERROR_BAD_PARAMETERS; + } + + return TEE_SUCCESS; +} + +static TEE_Result get_rsa_hash_algo(uint32_t algo_type) +{ + switch (algo_type) { + case RSASSA_PKCS1_V1_5_SHA1: + algo = TEE_ALG_RSASSA_PKCS1_V1_5_SHA1; + break; + case RSASSA_PKCS1_V1_5_SHA224: + algo = TEE_ALG_RSASSA_PKCS1_V1_5_SHA224; + break; + case RSASSA_PKCS1_V1_5_SHA256: + algo = TEE_ALG_RSASSA_PKCS1_V1_5_SHA256; + break; + case RSASSA_PKCS1_V1_5_SHA384: + algo = TEE_ALG_RSASSA_PKCS1_V1_5_SHA384; + break; + case RSASSA_PKCS1_V1_5_SHA512: + algo = TEE_ALG_RSASSA_PKCS1_V1_5_SHA512; + break; + case RSASSA_PKCS1_PSS_MGF1_SHA1: + algo = TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1; + break; + case RSASSA_PKCS1_PSS_MGF1_SHA224: + algo = TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224; + break; + case RSASSA_PKCS1_PSS_MGF1_SHA256: + algo = TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256; + break; + case RSASSA_PKCS1_PSS_MGF1_SHA384: + algo = TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384; + break; + case RSASSA_PKCS1_PSS_MGF1_SHA512: + algo = TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512; + break; + default: + EMSG("RSA sign or verify error algo_type"); + return TEE_ERROR_BAD_PARAMETERS; + } + + return TEE_SUCCESS; +} + +static TEE_Result get_ecdsa_hash_algo(uint32_t width_bits) +{ + switch (width_bits) { + case ECC_CURVE_192: + algo = __OPTEE_ALG_ECDSA_P192; + break; + case ECC_CURVE_224: + algo = __OPTEE_ALG_ECDSA_P224; + break; + case ECC_CURVE_256: + algo = __OPTEE_ALG_ECDSA_P256; + break; + case ECC_CURVE_384: + algo = __OPTEE_ALG_ECDSA_P384; + break; + case ECC_CURVE_521: + algo = __OPTEE_ALG_ECDSA_P521; + break; + default: + EMSG("ECDSA sign or verify error width_bits"); + return TEE_ERROR_BAD_PARAMETERS; + } + + return TEE_SUCCESS; +} + +static TEE_Result get_algo(uint32_t tee_type, uint32_t mode, + uint32_t width_bits, uint32_t algo_type) +{ + TEE_Result res = TEE_SUCCESS; + + if (tee_type == ALGO_RSA) { + if (mode == MODE_ENCRYPT || mode == MODE_DECRYPT) { + res = get_rsa_cipher_algo(algo_type); + } else if (mode == MODE_SIGN || mode == MODE_VERIFY) { + res = get_rsa_hash_algo(algo_type); + } else { + EMSG("RSA error mode"); + res = TEE_ERROR_BAD_PARAMETERS; + } + } else if (tee_type == ALGO_ECDSA) { + if (mode == MODE_SIGN || mode == MODE_VERIFY) { + res = get_ecdsa_hash_algo(width_bits); + } else { + EMSG("ECDSA error mode"); + res = TEE_ERROR_BAD_PARAMETERS; + } + } else { + res = TEE_ERROR_BAD_PARAMETERS; + } + + return res; +} + +static uint32_t get_keypair_type(uint32_t value) +{ + switch (value) { + case ALGO_DH: + return TEE_TYPE_DH_KEYPAIR; + case ALGO_RSA: + return TEE_TYPE_RSA_KEYPAIR; + case ALGO_ECDSA: + return TEE_TYPE_ECDSA_KEYPAIR; + case ALGO_ECDH: + return TEE_TYPE_ECDH_KEYPAIR; + case ALGO_X25519: + return TEE_TYPE_X25519_KEYPAIR; + default: + EMSG("The algo[%"PRIu32"] is not valid", value); + return TEE_TYPE_ILLEGAL_VALUE; + } +} + +TEE_Result cmd_asym_prepare_attrs(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (param_types != exp_param_types) + return TEE_ERROR_BAD_PARAMETERS; + + crypto_buf = TEE_Malloc(params[0].memref.size, 0); + if (!crypto_buf) + return TEE_ERROR_OUT_OF_MEMORY; + memcpy(crypto_buf, params[0].memref.buffer, params[0].memref.size); + + return unpack_attrs(crypto_buf, params[0].memref.size, + &asym_perf_attrs, &asym_perf_attr_count); +} + +TEE_Result cmd_asym_free_attrs(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 (param_types != exp_param_types) + return TEE_ERROR_BAD_PARAMETERS; + + TEE_Free(asym_perf_attrs); + asym_perf_attrs = NULL; + TEE_Free(crypto_buf); + crypto_buf = NULL; + + return TEE_SUCCESS; +} + +TEE_Result cmd_asym_process_keypair(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result res = TEE_ERROR_GENERIC; + int width_bits = 0; + int n = 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 (param_types != exp_param_types) + return TEE_ERROR_BAD_PARAMETERS; + + width_bits = params[0].value.a; + n = params[0].value.b; + + while (n--) { + res = TEE_GenerateKey(crypto_obj, width_bits, asym_perf_attrs, + asym_perf_attr_count); + CHECK(res, "TEE_GenerateKey()", break;); + TEE_ResetTransientObject(crypto_obj); + } + + return res; +} + +TEE_Result cmd_asym_process_rsa_ecc(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result res = TEE_ERROR_GENERIC; + int n = 0; + uint32_t mode = 0; + uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE); + size_t dummy_size = params[2].memref.size; + TEE_Result (*do_asym)(TEE_OperationHandle, const TEE_Attribute *, + uint32_t, const void *, size_t, void *, + size_t *) = NULL; + + if (param_types != exp_param_types) + return TEE_ERROR_BAD_PARAMETERS; + + n = params[0].value.a; + mode = params[0].value.b; + + if (mode == MODE_VERIFY) { + while (n--) { + res = TEE_AsymmetricVerifyDigest(crypto_op, + asym_perf_attrs, + asym_perf_attr_count, + params[1].memref.buffer, + params[1].memref.size, + params[2].memref.buffer, + dummy_size); + + CHECK(res, "TEE processing failed", break;); + } + } else { + if (mode == MODE_ENCRYPT) + do_asym = TEE_AsymmetricEncrypt; + else if (mode == MODE_DECRYPT) + do_asym = TEE_AsymmetricDecrypt; + else if (mode == MODE_SIGN) + do_asym = TEE_AsymmetricSignDigest; + else + return TEE_ERROR_BAD_PARAMETERS; + while (n--) { + res = do_asym(crypto_op, asym_perf_attrs, + asym_perf_attr_count, + params[1].memref.buffer, + params[1].memref.size, + params[2].memref.buffer, &dummy_size); + + CHECK(res, "TEE processing failed", break;); + } + } + + return res; +} + +TEE_Result cmd_asym_prepare_obj(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result res = TEE_ERROR_GENERIC; + uint32_t tee_type = TEE_TYPE_ILLEGAL_VALUE; + 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; + + tee_type = get_keypair_type(params[0].value.a); + if (tee_type == TEE_TYPE_ILLEGAL_VALUE) + return TEE_ERROR_BAD_PARAMETERS; + + cmd_clean_obj(); + res = TEE_AllocateTransientObject(tee_type, params[0].value.b, + &crypto_obj); + CHECK(res, "TEE_AllocateTransientObject()", return res;); + + return TEE_SUCCESS; +} + +TEE_Result cmd_asym_prepare_keypair(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result res = TEE_ERROR_GENERIC; + TEE_Attribute *attrs = NULL; + uint32_t attr_count = 0; + uint32_t width_bits = 0; + uint32_t algo_type = 0; + uint32_t tee_type = 0; + uint32_t mode = 0; + uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_NONE); + + if (param_types != exp_param_types) + return TEE_ERROR_BAD_PARAMETERS; + + mode = params[0].value.b; + width_bits = params[0].value.a; + tee_type = params[1].value.a; + algo_type = params[1].value.b; + + if (get_algo(tee_type, mode, width_bits, algo_type)) + return TEE_ERROR_BAD_PARAMETERS; + + res = unpack_attrs(params[2].memref.buffer, params[2].memref.size, + &attrs, &attr_count); + if (res != TEE_SUCCESS) + return res; + + res = TEE_GenerateKey(crypto_obj, width_bits, attrs, attr_count); + CHECK(res, "TEE_GenerateKey()", goto out;); + + cmd_clean_res(); + res = TEE_AllocateOperation(&crypto_op, algo, mode, width_bits); + CHECK(res, "TEE_AllocateOperation()", goto out;); + + res = TEE_SetOperationKey(crypto_op, crypto_obj); + CHECK(res, "TEE_SetOperationKey()", goto out;); + + if (mode == MODE_DECRYPT) { + res = TEE_AllocateOperation(&crypto_op_enc_sign, algo, + MODE_ENCRYPT, width_bits); + CHECK(res, "TEE_AllocateOperation()", goto out;); + + res = TEE_SetOperationKey(crypto_op_enc_sign, crypto_obj); + CHECK(res, "TEE_SetOperationKey()", goto out;); + } else if (mode == MODE_VERIFY) { + res = TEE_AllocateOperation(&crypto_op_enc_sign, algo, + MODE_SIGN, width_bits); + CHECK(res, "TEE_AllocateOperation()", goto out;); + + res = TEE_SetOperationKey(crypto_op_enc_sign, crypto_obj); + CHECK(res, "TEE_SetOperationKey()", goto out;); + } + +out: + TEE_Free(attrs); + + return res; +} + +TEE_Result cmd_asym_prepare_hash(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result res = TEE_ERROR_GENERIC; + TEE_OperationHandle hash_op = NULL; + uint32_t hash_algo = 0; + uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE); + + if (param_types != exp_param_types) + return TEE_ERROR_BAD_PARAMETERS; + + if (params[0].value.a == ALGO_ECDSA) + hash_algo = TEE_ALG_SHA1; + else + hash_algo = TEE_ALG_HASH_ALGO(TEE_ALG_GET_DIGEST_HASH(algo)); + + res = TEE_AllocateOperation(&hash_op, hash_algo, TEE_MODE_DIGEST, 0); + CHECK(res, "TEE_AllocateOperation()", return res;); + + res = TEE_DigestDoFinal(hash_op, params[1].memref.buffer, + params[1].memref.size, params[2].memref.buffer, + ¶ms[2].memref.size); + TEE_FreeOperation(hash_op); + CHECK(res, "TEE_DigestDoFinal()", return res;); + + return TEE_SUCCESS; +} + +TEE_Result cmd_asym_prepare_enc_sign(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result res = TEE_ERROR_GENERIC; + TEE_Attribute *attrs = NULL; + uint32_t attr_count = 0; + uint32_t mode = 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_MEMREF_INPUT); + + if (param_types != exp_param_types) + return TEE_ERROR_BAD_PARAMETERS; + + mode = params[2].value.a; + res = unpack_attrs(params[3].memref.buffer, params[3].memref.size, + &attrs, &attr_count); + if (res != TEE_SUCCESS) + return res; + + if (mode == MODE_DECRYPT) + res = TEE_AsymmetricEncrypt(crypto_op_enc_sign, NULL, 0, + params[0].memref.buffer, + params[0].memref.size, + params[1].memref.buffer, + ¶ms[1].memref.size); + else + res = TEE_AsymmetricSignDigest(crypto_op_enc_sign, attrs, + attr_count, + params[0].memref.buffer, + params[0].memref.size, + params[1].memref.buffer, + ¶ms[1].memref.size); + + TEE_Free(attrs); + if (mode == MODE_DECRYPT) + CHECK(res, "TEE_AsymmetricEncrypt", return res;); + else + CHECK(res, "TEE_AsymmetricSignDigest", return res;); + + return TEE_SUCCESS; +} + +void cmd_clean_obj(void) +{ + if (crypto_obj) + TEE_FreeTransientObject(crypto_obj); + crypto_obj = TEE_HANDLE_NULL; +} + +void cmd_clean_res(void) +{ + if (crypto_op) + TEE_FreeOperation(crypto_op); + if (crypto_op_enc_sign) { + TEE_FreeOperation(crypto_op_enc_sign); + crypto_op_enc_sign = NULL; + } +} diff --git a/optee/optee_test/ta/crypto_perf/ta_entry.c b/optee/optee_test/ta/crypto_perf/ta_entry.c new file mode 100644 index 0000000..450f33d --- /dev/null +++ b/optee/optee_test/ta/crypto_perf/ta_entry.c @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015, Linaro Limited + + */ + +#include +#include + +#include "ta_crypto_perf.h" +#include "ta_crypto_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(); + cmd_clean_obj(); +} + +/* 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_CRYPTO_PERF_CMD_CIPHER_PREPARE_KEY: + return cmd_cipher_prepare_key(nParamTypes, pParams); + + case TA_CRYPTO_PERF_CMD_CIPHER_PROCESS: + return cmd_cipher_process(nParamTypes, pParams, false); + case TA_CRYPTO_PERF_CMD_CIPHER_PROCESS_SDP: +#ifdef CFG_SECURE_DATA_PATH + return cmd_cipher_process(nParamTypes, pParams, true); +#else + EMSG("Invalid SDP commands: TA was built without SDP support"); + return TEE_ERROR_NOT_SUPPORTED; +#endif + case TA_CRYPTO_PERF_CMD_HASH_PREPARE_OP: + return cmd_hash_prepare_op(nParamTypes, pParams); + case TA_CRYPTO_PERF_CMD_HASH_PROCESS: + return cmd_hash_process(nParamTypes, pParams); + case TA_CRYPTO_PERF_CMD_ASYM_PROCESS_GEN_KEYPAIR: + return cmd_asym_process_keypair(nParamTypes, pParams); + case TA_CRYPTO_PERF_CMD_ASYM_PREPARE_ATTRS: + return cmd_asym_prepare_attrs(nParamTypes, pParams); + case TA_CRYPTO_PERF_CMD_ASYM_PROCESS: + return cmd_asym_process_rsa_ecc(nParamTypes, pParams); + case TA_CRYPTO_PERF_CMD_ASYM_PREPARE_KEYPAIR: + return cmd_asym_prepare_keypair(nParamTypes, pParams); + case TA_CRYPTO_PERF_CMD_ASYM_PREPARE_HASH: + return cmd_asym_prepare_hash(nParamTypes, pParams); + case TA_CRYPTO_PERF_CMD_ASYM_PREPARE_OBJ: + return cmd_asym_prepare_obj(nParamTypes, pParams); + case TA_CRYPTO_PERF_CMD_ASYM_PREPARE_ENC_SIGN: + return cmd_asym_prepare_enc_sign(nParamTypes, pParams); + case TA_CRYPTO_PERF_CMD_ASYM_FREE_ATTRS: + return cmd_asym_free_attrs(nParamTypes, pParams); + + default: + return TEE_ERROR_BAD_PARAMETERS; + } +} 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/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..f494f5c --- /dev/null +++ b/optee/optee_test/ta/include/ta_storage.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ + +#include + +#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 +#define TA_STORAGE_CMD_CLEAR_STORAGE 26 + +#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..62c2378 --- /dev/null +++ b/optee/optee_test/ta/os_test/include/os_test.h @@ -0,0 +1,50 @@ +/* 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_ta2ta_memref_size0(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..93785e2 --- /dev/null +++ b/optee/optee_test/ta/os_test/include/ta_os_test.h @@ -0,0 +1,51 @@ +/* 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 +#define TA_OS_TEST_CMD_TA2TA_MEMREF_SIZE0 37 + +#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..e0256e1 --- /dev/null +++ b/optee/optee_test/ta/os_test/include/tb_asserts.h @@ -0,0 +1,153 @@ +/* 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", \ + __LINE__, __FILE__); \ + EMSG("Message: %s", 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", \ + __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", \ + __LINE__, __FILE__); \ + EMSG("short == 0, but size != 0"); \ + HALT; \ + } else if (__mpanum_size((mpanum)src) > 1) { \ + EMSG("Assertion failed at line %d in file:\n%s", \ + __LINE__, __FILE__); \ + EMSG("size > 1, cannot be equal to a short."); \ + HALT; \ + } else if ( \ + (int)(__mpanum_lsw((mpanum)src)*__mpanum_sign((mpanum)src)) != \ + (int)(short)) { \ + EMSG("Assertion failed at line %d in file:\n%s", \ + __LINE__, __FILE__); \ + EMSG("short == %d, but src == %d", (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", (a), (b)); \ + HALT; \ + }; \ +} 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."); \ + 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."); \ + 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."); \ + 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."); \ + 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."); \ + 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."); \ + 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."); \ + 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..53e6d60 --- /dev/null +++ b/optee/optee_test/ta/os_test/include/tb_macros.h @@ -0,0 +1,57 @@ +/* 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) \ + MSG("\n*********** TESTBENCH ***********" \ + "\n*** RUNNING: <<< %s >>>" \ + "\n*********************************", str) + +#define TB_FOOTER(str) \ + MSG("\n*********** TESTBENCH ***********" \ + "\n*** PASSED: <<< %s >>>" \ + "\n*********************************", str) + +#define TB_INFO(str) MSG("*** INFO : %s \n", (str)) + +#define HALT \ + { \ + EMSG("\n*** FAILED ***" \ + "\nTestbench halted at line %d in function %s"; \ + MSG("\nWaiting for keypress to enable debugging."); \ + TEE_Panic(0); \ + } + +#define STARTING \ + MSG("\n*********** TESTBENCH ***********" \ + "\n*** For the GlobalPlatform Math API" \ + "\n*********************************") + +#define ALL_PASSED \ + MSG("\n*********** TESTBENCH ***********" \ + "\n*** ALL TESTS PASSED ***" \ + "\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) + +#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..6cdd91f --- /dev/null +++ b/optee/optee_test/ta/os_test/os_test.c @@ -0,0 +1,1603 @@ +// 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 %#"PRIx32, 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", 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\"", + nbuf, vbuf); + return TEE_ERROR_GENERIC; + } + + DMSG("Found \"%s\" value \"%s\"", 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", + 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 %#"PRIx32, + nbuf, 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 %#"PRIx32, + nbuf, 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 %#"PRIx32, + nbuf, 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 %#"PRIx32, + nbuf, 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\"", + 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"); + 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 %#"PRIx32, res); + return TEE_ERROR_GENERIC; + } + + MSG("Getting properties for current TA"); + res = print_properties(h, TEE_PROPSET_CURRENT_TA, p_attrs, num_p_attrs); + if (res != TEE_SUCCESS) + goto cleanup_return; + + MSG("Getting properties for current client"); + res = print_properties(h, TEE_PROPSET_CURRENT_CLIENT, p_attrs, + num_p_attrs); + if (res != TEE_SUCCESS) + goto cleanup_return; + + MSG("Getting properties for implementation"); + 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", 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_BAD_PARAMETERS; + + /* 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("TEE_OpenTASession() failed: %#"PRIx32, res); + return res; + } + + 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("TEE_InvokeTACommand() failed: %#"PRIx32, res); + + 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); + MSG("system time %"PRIu32".%03"PRIx32, sys_t.seconds, sys_t.millis); + + TEE_GetREETime(&t); + MSG("REE time %"PRIu32".%03"PRIu32, t.seconds, t.millis); + + res = TEE_GetTAPersistentTime(&t); + switch (res) { + case TEE_SUCCESS: + MSG("Stored TA time %"PRIu32".%03"PRIu32, t.seconds, t.millis); + break; + case TEE_ERROR_OVERFLOW: + EMSG("Stored TA time overflowed %"PRIu32".%03"PRIu32, + t.seconds, t.millis); + break; + case TEE_ERROR_TIME_NOT_SET: + EMSG("TA time not stored"); + break; + case TEE_ERROR_TIME_NEEDS_RESET: + EMSG("TA time needs reset"); + break; + default: + return res; + } + + res = TEE_SetTAPersistentTime(&null_time); + if (res != TEE_SUCCESS) { + EMSG("TEE_SetTAPersistentTime() failed%#"PRIx32, res); + return res; + } + + res = TEE_GetTAPersistentTime(&t); + if (res != TEE_SUCCESS) { + EMSG("TEE_GetTAPersistentTime() for null time: failed %#"PRIx32, + res); + return res; + } + MSG("TA time %"PRIu32".%03"PRIu32, t.seconds, 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 %"PRIu32".%03"PRIu32, t.seconds, + t.millis); + return TEE_ERROR_BAD_STATE; + } + + res = TEE_SetTAPersistentTime(&wrap_time); + if (res != TEE_SUCCESS) { + EMSG("TEE_SetTAPersistentTime() wrap: failed %#"PRIx32, res); + return res; + } + + res = TEE_Wait(1000); + if (res != TEE_SUCCESS) + EMSG("TEE_Wait() wrap: failed %#"PRIx32, res); + + res = TEE_GetTAPersistentTime(&t); + if (res != TEE_ERROR_OVERFLOW) { + EMSG("TEE_GetTAPersistentTime(): failed %#"PRIx32, res); + return TEE_ERROR_BAD_STATE; + } + MSG("TA time %"PRIu32".%03"PRIu32, t.seconds, t.millis); + + if (t.seconds > 1) { + EMSG("Unexpected wrapped time %"PRIu32".%03"PRIu32, t.seconds, + 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; + + MSG("enter"); + + 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; + + MSG("enter"); + /* + * 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("bad parameters"); + return TEE_ERROR_BAD_PARAMETERS; + } + + res = TEE_OpenTASession(&os_test_uuid, TEE_TIMEOUT_INFINITE, 0, NULL, + &sess, &ret_orig); + if (res != TEE_SUCCESS) { + EMSG("TEE_OpenTASession() failed %#"PRIx32, res); + 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("TEE_InvokeTACommand(): res %#"PRIx32" ret_orig %#"PRIx32, + res, 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; + + DMSG("ta_entry_client: enter"); + + 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("TEE_OpenTASession() failed %#"PRIx32, res); + goto cleanup_free; + } + + 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("TEE_InvokeTACommand() failed %#"PRIx32, res); + goto cleanup_close_session; + } + + if (TEE_MemCompare(sha256_out, out, sizeof(sha256_out)) != 0) { + EMSG("out parameter failed"); + res = TEE_ERROR_GENERIC; + goto cleanup_close_session; + } + +cleanup_close_session: + TEE_CloseTASession(sess); +cleanup_free: + TEE_Free(in); + 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_BAD_PARAMETERS; + + 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; + + MSG("waiting %"PRId32, 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_BAD_PARAMETERS; + + 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_BAD_PARAMETERS; + + res = TEE_OpenTASession(&test_uuid, TEE_TIMEOUT_INFINITE, 0, NULL, + &sess, &ret_orig); + if (res != TEE_SUCCESS) { + EMSG("TEE_OpenTASession failed"); + return res; + } + + 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; +} +#undef TA2TA_BUF_SIZE + +TEE_Result ta_entry_ta2ta_memref_size0(uint32_t param_types, TEE_Param params[4]) +{ + static const TEE_UUID test_uuid = TA_OS_TEST_UUID; + TEE_TASessionHandle sess = TEE_HANDLE_NULL; + uint32_t ret_orig = 0; + TEE_Result res = TEE_ERROR_GENERIC; + + if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE)) + return TEE_ERROR_BAD_PARAMETERS; + + /* + * This test expects all memory references to be non-NULL but + * all sizes to be zero. + */ + 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) + return TEE_ERROR_BAD_PARAMETERS; + + res = TEE_OpenTASession(&test_uuid, TEE_TIMEOUT_INFINITE, 0, NULL, + &sess, &ret_orig); + if (res != TEE_SUCCESS) { + EMSG("TEE_OpenTASession failed"); + return res; + } + + /* + * TA basically does nothing. The actual test just consists + * into validating that passing non-NULL memref of size zero + * does not panic. + */ + res = TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE, + TA_OS_TEST_CMD_TA2TA_MEMREF_MIX, + param_types, params, &ret_orig); + + 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_BAD_PARAMETERS; + + bufsize = params[0].memref.size; + if (params[1].memref.size != bufsize || + params[2].memref.size != bufsize) + return TEE_ERROR_BAD_PARAMETERS; + + 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..5600f3d --- /dev/null +++ b/optee/optee_test/ta/os_test/sub.mk @@ -0,0 +1,31 @@ +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 +aflags-$(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..56f3ef0 --- /dev/null +++ b/optee/optee_test/ta/os_test/ta_entry.c @@ -0,0 +1,187 @@ +// 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"); + 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; + TEE_UnmaskCancellation(); + + 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_SIZE0: + return ta_entry_ta2ta_memref_size0(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..23fc31c --- /dev/null +++ b/optee/optee_test/ta/rpc_test/ta_rpc.c @@ -0,0 +1,164 @@ +// 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("TEE_OpenTASession() returned %#"PRIx32, 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("TEE_InvokeTACommand() returned %#"PRIx32, 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..7682cd2 --- /dev/null +++ b/optee/optee_test/ta/sdp_basic/ta_sdp_basic.c @@ -0,0 +1,367 @@ +// 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 %#"PRIx32, 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 %#"PRIx32, 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 %#"PRIx32, 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, %zu) failed: %#"PRIx32, + 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, %zu) failed: %#"PRIx32, + 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 %#"PRIx32, 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, %zu) failed: %#"PRIx32, + 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, %zu) failed: %#"PRIx32, + 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 %#"PRIx32, 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 %#"PRIx32, 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, %zu) failed: %#"PRIx32, + 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"); + 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 %#"PRIx32"/%"PRIu32, + 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"); + 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 %#"PRIx32"/%"PRIu32, + 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..50a99d6 --- /dev/null +++ b/optee/optee_test/ta/storage/include/storage.h @@ -0,0 +1,45 @@ +/* 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]); +TEE_Result ta_storage_cmd_clear_storage(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..10ef0bd --- /dev/null +++ b/optee/optee_test/ta/storage/storage.c @@ -0,0 +1,740 @@ +// 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 +#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 cleanup3; + } + + 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 cleanup3; + } + + 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; +} + +static TEE_Result clear_storage(uint32_t storage_id) +{ + TEE_ObjectEnumHandle oe = TEE_HANDLE_NULL; + TEE_Result enum_res = TEE_ERROR_GENERIC; + TEE_ObjectHandle o = TEE_HANDLE_NULL; + TEE_Result res = TEE_ERROR_GENERIC; + TEE_UUID __maybe_unused uuid = TA_UUID; + TEE_ObjectInfo oi = { }; + size_t obj_id_sz = 0; + void *obj_id = NULL; + size_t i = 0; + + IMSG("Clearing TA storage (UUID: %pUl, storage ID: 0x%x)", + (void *)&uuid, storage_id); + res = TEE_AllocatePersistentObjectEnumerator(&oe); + if (res) + return res; + res = TEE_StartPersistentObjectEnumerator(oe, storage_id); + if (res == TEE_ERROR_ITEM_NOT_FOUND) { + IMSG("No object found"); + res = TEE_SUCCESS; + goto out; + } + if (res) + goto out; + obj_id = TEE_Malloc(TEE_OBJECT_ID_MAX_LEN, 0); + if (!obj_id) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + while (true) { + enum_res = TEE_GetNextPersistentObject(oe, &oi, obj_id, + &obj_id_sz); + if (enum_res == TEE_ERROR_ITEM_NOT_FOUND) + break; + if (enum_res) { + res = enum_res; + break; + } + IMSG("Deleting persistent object #%zu", i); + res = TEE_OpenPersistentObject(storage_id, obj_id, obj_id_sz, + TEE_DATA_FLAG_ACCESS_WRITE_META, + &o); + if (res) + break; + TEE_CloseAndDeletePersistentObject1(o); + i++; + } + +out: + TEE_FreePersistentObjectEnumerator(oe); + TEE_Free(obj_id); + return res; +} + +TEE_Result ta_storage_cmd_clear_storage(uint32_t param_types, + TEE_Param params[4]) +{ + uint32_t id[] = { TEE_STORAGE_PRIVATE_REE, TEE_STORAGE_PRIVATE_RPMB }; + TEE_Result res = TEE_ERROR_GENERIC; + size_t i = 0; + + (void)param_types; + (void)params; + + for (i = 0; i < sizeof(id) / sizeof(id[0]); i++) { + res = clear_storage(id[i]); + if (res) + break; + } + 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..f3a93db --- /dev/null +++ b/optee/optee_test/ta/storage/ta_entry.c @@ -0,0 +1,128 @@ +// 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); + + case TA_STORAGE_CMD_CLEAR_STORAGE: + return ta_storage_cmd_clear_storage(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..de8d1ef --- /dev/null +++ b/optee/optee_test/ta/storage_benchmark/benchmark.c @@ -0,0 +1,405 @@ +// 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=%#"PRIx32, 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=%#"PRIx32, 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=%#"PRIx32, 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: %"PRIu32".%"PRIu32"(s), stop: %"PRIu32".%"PRIu32"(s), delta: %"PRIu32"(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=%#"PRIx32, 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: %"PRIu32".%"PRIu32"(s), stop: %"PRIu32".%"PRIu32"(s), delta: %"PRIu32"(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=%#"PRIx32, 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=%#"PRIx32, 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: %"PRIu32".%"PRIu32"(s), stop: %"PRIu32".%"PRIu32"(s), delta: %"PRIu32"(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=%#"PRIx32, 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=%#"PRIx32, 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", + 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=%#"PRIx32, 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=%#"PRIx32, 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/cpubl-payload-dec/LICENSE b/optee/samples/cpubl-payload-dec/LICENSE new file mode 100644 index 0000000..8eb17b3 --- /dev/null +++ b/optee/samples/cpubl-payload-dec/LICENSE @@ -0,0 +1,23 @@ +Copyright (c) 2023 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 the source code must retain the above copyright notice, +this list of conditions, and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions, and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (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/cpubl-payload-dec/Makefile b/optee/samples/cpubl-payload-dec/Makefile new file mode 100644 index 0000000..9912522 --- /dev/null +++ b/optee/samples/cpubl-payload-dec/Makefile @@ -0,0 +1,25 @@ +# Copyright (c) 2023, 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)/early_ta/$(TARGET_DIR) + +.PHONY: clean +clean: + $(MAKE) -C ta \ + TA_DEV_KIT_DIR=$(TA_DEV_KIT_DIR) \ + O=$(O)/early_ta/$(TARGET_DIR) \ + clean diff --git a/optee/samples/cpubl-payload-dec/ta/Makefile b/optee/samples/cpubl-payload-dec/ta/Makefile new file mode 100644 index 0000000..1288df1 --- /dev/null +++ b/optee/samples/cpubl-payload-dec/ta/Makefile @@ -0,0 +1,7 @@ +# Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause + +# The UUID for the Trusted Application +BINARY=0e35e2c9-b329-4ad9-a2f5-8ca9bbbd7713 + +include $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk diff --git a/optee/samples/cpubl-payload-dec/ta/entry.c b/optee/samples/cpubl-payload-dec/ta/entry.c new file mode 100644 index 0000000..ee03556 --- /dev/null +++ b/optee/samples/cpubl-payload-dec/ta/entry.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2023, NVIDIA Corporation & AFFILIATES. All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include + +#include +#include +#include + +#define JETSON_USER_KEY_TA_UUID \ + { 0xe9e156e8, 0xe161, 0x4c8a, \ + {0x91, 0xa9, 0x0b, 0xba, 0x5e, 0x24, 0x7e, 0xe8} } + +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) +{ +} + +static TEE_Result is_user_key_exists(uint32_t types, TEE_Param in_params[TEE_NUM_PARAMS]) +{ + TEE_Result res = TEE_ERROR_GENERIC; + TEE_TASessionHandle sess = TEE_HANDLE_NULL; + uint32_t ret_orig = 0; + 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 != types) { + EMSG("bad parameters types!\n"); + return TEE_ERROR_BAD_PARAMETERS; + } + + res = TEE_OpenTASession(&(const TEE_UUID)JETSON_USER_KEY_TA_UUID, + TEE_TIMEOUT_INFINITE, 0, NULL, &sess, + &ret_orig); + if (res) { + EMSG("TEE_OpenTASession failed with res = 0x%08x\n", res); + return res; + } + + res = TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE, + JETSON_USER_KEY_CMD_IS_KEY_EXISTS, + types, in_params, &ret_orig); + if (res) { + EMSG("TEE_InvokeTACommand failed with res = 0x%08x\n", res); + } + + TEE_CloseTASession(sess); + + return res; +} + +static TEE_Result decrypt_image(uint32_t types, TEE_Param in_params[TEE_NUM_PARAMS]) +{ + TEE_Result res = TEE_ERROR_GENERIC; + TEE_TASessionHandle sess = TEE_HANDLE_NULL; + uint32_t ret_orig = 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 != types) { + EMSG("bad parameters types!\n"); + return TEE_ERROR_BAD_PARAMETERS; + } + + res = TEE_OpenTASession(&(const TEE_UUID)JETSON_USER_KEY_TA_UUID, + TEE_TIMEOUT_INFINITE, 0, NULL, &sess, + &ret_orig); + if (res) { + EMSG("TEE_OpenTASession failed with res = 0x%08x\n", res); + return res; + } + + res = TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE, + JETSON_USER_KEY_CMD_DECRYPT_CPUBL_PAYLOAD, + types, in_params, &ret_orig); + if (res) { + EMSG("TEE_InvokeTACommand failed with res = 0x%08x\n", res); + } + + TEE_CloseTASession(sess); + + return res; +} + +TEE_Result TA_InvokeCommandEntryPoint(void *sess __unused, uint32_t cmd, + uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS]) +{ + switch (cmd) { + case CPUBL_PAYLOAD_DECRYPTION_CMD_IS_USER_KEY_EXISTS: + return is_user_key_exists(pt, params); + case CPUBL_PAYLOAD_DECRYPTION_CMD_DECRYPT_IMAGE: + return decrypt_image(pt, params); + default: + return TEE_ERROR_NOT_SUPPORTED; + } +} diff --git a/optee/samples/cpubl-payload-dec/ta/include/ta_cpubl_dec.h b/optee/samples/cpubl-payload-dec/ta/include/ta_cpubl_dec.h new file mode 100644 index 0000000..ab8e6a0 --- /dev/null +++ b/optee/samples/cpubl-payload-dec/ta/include/ta_cpubl_dec.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2018, Linaro Limited + * Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. + * */ + +#ifndef __TA_CPUBL_PAYLOAD_DECRYPTION_H +#define __TA_CPUBL_PAYLOAD_DECRYPTION_H + +#define TA_CPUBL_PAYLOAD_DECRYPTION_UUID { 0x0e35e2c9, 0xb329, 0x4ad9, \ + { 0xa2, 0xf5, 0x8c, 0xa9, 0xbb, 0xbd, 0x77, 0x13 } } + +#define CPUBL_PAYLOAD_DECRYPTION_CMD_IS_USER_KEY_EXISTS 0 + +#define CPUBL_PAYLOAD_DECRYPTION_CMD_DECRYPT_IMAGE 1 + +#endif /* __TA_CPUBL_PAYLOAD_DECRYPTION_H */ diff --git a/optee/samples/cpubl-payload-dec/ta/sub.mk b/optee/samples/cpubl-payload-dec/ta/sub.mk new file mode 100644 index 0000000..f1b35c0 --- /dev/null +++ b/optee/samples/cpubl-payload-dec/ta/sub.mk @@ -0,0 +1,3 @@ +global-incdirs-y += include +global-incdirs-y += . +srcs-y += entry.c diff --git a/optee/samples/cpubl-payload-dec/ta/user_ta.mk b/optee/samples/cpubl-payload-dec/ta/user_ta.mk new file mode 100644 index 0000000..a0c3140 --- /dev/null +++ b/optee/samples/cpubl-payload-dec/ta/user_ta.mk @@ -0,0 +1,2 @@ +user-ta-uuid := 0e35e2c9-b329-4ad9-a2f5-8ca9bbbd7713 +user-ta-version := 0 diff --git a/optee/samples/cpubl-payload-dec/ta/user_ta_header_defines.h b/optee/samples/cpubl-payload-dec/ta/user_ta_header_defines.h new file mode 100644 index 0000000..b05a4ee --- /dev/null +++ b/optee/samples/cpubl-payload-dec/ta/user_ta_header_defines.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023, 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 TA_CPUBL_PAYLOAD_DECRYPTION_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/samples/ftpm-helper/LICENSE b/optee/samples/ftpm-helper/LICENSE new file mode 100644 index 0000000..4658ee9 --- /dev/null +++ b/optee/samples/ftpm-helper/LICENSE @@ -0,0 +1,23 @@ +Copyright (c) 2023-2024 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 the source code must retain the above copyright notice, +this list of conditions, and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions, and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (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/ftpm-helper/Makefile b/optee/samples/ftpm-helper/Makefile new file mode 100644 index 0000000..1069464 --- /dev/null +++ b/optee/samples/ftpm-helper/Makefile @@ -0,0 +1,35 @@ +# Copyright (c) 2023-2024, 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)/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 + +.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)/ca/$(TARGET_DIR) diff --git a/optee/samples/ftpm-helper/README.md b/optee/samples/ftpm-helper/README.md new file mode 100644 index 0000000..611c3fe --- /dev/null +++ b/optee/samples/ftpm-helper/README.md @@ -0,0 +1,1872 @@ +# Overview of the Firmware TPM implementation on Jetson + +__Applies to__ the Jetson AGX Orin, the Jetson Orin NX series, and the Jetson Orin Nano series. + +Before you begin, please reference the TCG website for the TPM specification and knowledge. +- [TCG TPM2 Brief Overview](https://trustedcomputinggroup.org/wp-content/uploads/2019_TCG_TPM2_BriefOverview_DR02web.pdf) +- [TPM 2.0 Specification](https://trustedcomputinggroup.org/resource/tpm-library-specification/) +- [TCG Documentation Portal](https://trustedcomputinggroup.org/resources/?) + +The Firmware TPM (__fTPM__) implementation is done by leveraging the official [TCG reference implementation of the TPM 2.0 specification](https://github.com/Microsoft/ms-tpm-20-ref). The reference implementation includes a sample fTPM Trusted Application (TA) designed to be executed with OP-TEE. + +A fundamental difference exists between a discrete TPM (DTPM) and fTPM. A DTPM or a TPM chip has been provisioned by the TPM vendor or manufacturer with the Endorsement Key (EK) certificate, which is the TPM identification that can be used for TPM attestation. Without this certificate, the TPM is not useful, because trust can not be constructed between the TPM user and the services that rely on TPM. + +To create a trustworthy fTPM entity on different devices, you need to provision it with a per-device unique ID, the EK certificate, and this needs to be done during the device manufacturing process. + +The fTPM implementation on Jetson includes two sample applications: +- fTPM TA from [ms-tpm-20-ref](https://github.com/Microsoft/ms-tpm-20-ref). +- fTPM helper applications + - The helper applications provide the functionalities for the provisioning process. + +# The fTPM Provisioning + +The fTPM provisioning refers to the process of configuring and initializing a firmware-based Trusted Platform Module (TPM) on a Jetson device. + +fTPM provisioning involves several steps: +- Initialization: The fTPM TA is initialized by the Trusted OS (OP-TEE) during the early secure boot stage. +- Configuration: The fTPM is configured with the settings such as Endorsement Primary Seed (EPS), EK certificate, owner password, and other parameters. +- Key generation: The fTPM generates a unique EK and storage root key (SRK), which are used to secure sensitive data. + +The benefits of fTPM provisioning includes: +- Improved security: By securing sensitive data and ensuring the integrity of the device's boot process, fTPM provisioning helps prevent unauthorized access or manipulation. +- Compliance: fTPM provisioning can help the device complies with the requirements from the remote service providers, such as TPM attestation. +- Trust: By providing a secure foundation for devices, fTPM provisioning helps establish trust between devices, networks, and users. + +The fTPM provisioning process we designed to make the Jetson device deal with the fTPM manufacturer Certificate Authority (CA) server. There are two kinds of provisioning methods: offline provisioning and online provisioning. + +- Offline provisioning method + - The offline provisioning method needs the fTPM manufacturer to pre-generate the EK certificates and encode it into the Encrypted Keyblob (**EKB**). This process needs to be completed during the device manufacturing process. When the device boots up, You can use a provisioning tool to query the EK certificates from EKB and store them in the fTPM non-volatile (NV) memory. +- Online provisioning method (Not available yet in the implementation) + - The online provisioning method depends on a three-way handshake protocol between the CA and the device to validate the device identity, sign, and issue the EK certificate. + +## Preparation before the fTPM provisioning process (Offline method) + +### The Prerequisites of the fTPM Owner +- Here is a list of the tasks that the fTPM owner can complete: + - This role is identical to the DTPM vendor or manufacturer and is the Original Design Manufacturer (ODM) of the fTPM provisioning support. + - It should be a third-party service provider with expertise in fTPM production. + - It should be able to set up a secure environment to work with the fTPM provisioning process. + - The CA server held by the fTPM owner should be acknowledged by the popular cloud service provider with which devices are designed to be enrolled. + - It should meet the requirements for preparing and generating materials for fusing the devices and keeping them secure. + - It should support multiple Original Equipment Manufacturers (OEMs) which means that the fTPM owner should work with multiple OEMs and maintain and isolate the materials for different OEMs. +- The requirements of the material preparation and the generation work. + - The per-device basis KDK0, Device_SN, Silicon_ID, and Silicon_ID public key generation. + - This can be done by running the kdk_gen.py KDK Gen tool, where: + - KDK0 is a secret per-device unique 256-bit random value. + - SN is a per-device unique serial number. + - OEM_ID is an OEM_ID number for different OEMs. + - Device_SN is the concatenation of OEM_ID and SN where OEM_ID and SN are in the big-endian form. + - The public key of Silicon_ID + - This public key can be used for the fTPM provisioning tool to verify the materials signed by the Silicon_ID private key. + - The public key is generated by Silicon_ID_Seed where: + - Silicon_ID is KDF(key=KDK0, Device_SN). + - The asymmetric key pair of SiliconID is ECC_P256_key_gen(seed=Silicon_ID). + - The private key should be dropped immediately. + - ==Note==: The KDK0 should be discarded after the corresponding fuseblob, the EK, and the EK-associated certificate are generated. + - The per-device basis fuseblob generation. + - This task can be completed by running the FSKP tool (fskp_fuseburn.py). + - Here is a list of the properties that are related to the fTPM: + - Fuse_ODM_INFO is ${OEM_ID}. + - Fuse_ODMID0/1 is ${SN}. + - Fuse_KDK0 is ${KDK0}. + - The KDK0 should be discarded after a corresponding fuseblob and EK are generated. The purpose of not keeping it in storage is to avoid potential leaks. + - The per-device basis fTPM EKB generation. + - This task can be completed by running the odm_ekb_gen.py ODM EKB Gen tool. + - Here are the fTPM EKB properties: + - EPS Seed is 256-bit random number that will be used for the EPS deriving process. + - The EK Certificate Signing Request (CSR). + - The EK CSR will be generated and sent to the CA for signing. + - EK Certificate + - The EK Certificate will be issued by the CA after signing the CSR. + - EKB is per-device EKB image with the following fTPM properties: + - Device_SN, EPS Seed + - EK certificates (RSA and EC) + - The database generated by the fTPM manufacturer: + - ${Device_SN} + - $(Silicon_ID_PUB_KEY) + - ${EPS_Seed} + - ${EK_Cert} + +```mermaid +--- +title: The preparation work of the fTPM owner. +--- +graph TB + subgraph Materials [Generate the materials] + direction LR + dev_sn1[[Device_SN]] ~~~ oem_kdk1[[KDK0]] ~~~ pub_key1[[Silicon_ID_PUB_KEY]] ~~~ eps_seed1[[EPS_Seed]] + dev_sn2[[00100001]] ~~~ oem_kdk2[[0x11aa22...]] ~~~ pub_key2[[0x1133...]] ~~~ eps_seed2[[0x5a6b...]] + dev_sn3[[00100002]] ~~~ oem_kdk3[[0x22bb33...]] ~~~ pub_key3[[0x2233...]] ~~~ eps_seed3[[0x5a6b...]] + dev_sn4[[00200001]] ~~~ oem_kdk4[[0xaa11bb...]] ~~~ pub_key4[[0x55eeff...]] ~~~ eps_seed4[[0x5a6b...]] + dev_sn5[[00200002]] ~~~ oem_kdk5[[0x99bbcc...]] ~~~ pub_key5[[0x33bbdd...]] ~~~ eps_seed5[[0x5a6b...]] + dev_sn6[[00300001]] ~~~ oem_kdk6[[0x33ddee...]] ~~~ pub_key6[[0x9e2b8c...]] ~~~ eps_seed6[[0x5a6b...]] + dev_sn7[[00300002]] ~~~ oem_kdk7[[0x22bbcc...]] ~~~ pub_key7[[0x1dfd32...]] ~~~ eps_seed7[[0x5a6b...]] + end + + DataBase[("${Device_SN}-${Silicon_ID_PUB_KEY}-${EPS_Seed}
EKCert-${Device_SN}
Fuseblob-${Device_SN}")] + FskpTool{{FSKP Tool}} + Fuseblobs[["Fuseblob-${Device_SN}"]] + fTPMGenEKCSRTool{{fTPM Gen EK CSR Tool}} + fTPMManuCA{{fTPM Manufacturer CA}} + EKCSRs[["EKCSR-${Device_SN}-${EPS_Seed}"]] + EKCerts[["EKCert-${Device_SN}"]] + + Materials --"Store in the database"--> DataBase + + Materials --> fTPMGenEKCSRTool + fTPMGenEKCSRTool --> EKCSRs + EKCSRs --"Send to the CA"--> fTPMManuCA + fTPMManuCA --> EKCerts + EKCerts --> DataBase + + Materials --> FskpTool + FskpTool --"Generate per-device fuseblobs"--> Fuseblobs + Fuseblobs --> DataBase +``` + +### Signing the EK CSRs +After the per-device EK CSR has been generated, the EK CSR needs to be signed by the fTPM manufacturer CA, and the CA returns the EK certificate. The EK should support two algorithms RSA and EC. During the preparation period, the fTPM owner should prepare two EK CSRs for the two algorithms and store the two certificates in the storage. + +This file name format is "ek_\${CERT_TYPE}\_\${KEY_TYPE}\-\${OEM_ID}\-\${SN}.der". +- CERT_TYPE: csr or cert. +- KEY_TYPE: rsa or ec. +- OEM_ID and SN: same as the definition above. +```mermaid +graph LR + fTPMServer(fTPM Manufacturer Server) + fTPMCA(fTPM Manufacturer CA) + + EKCSR[[EK CSR
ek_csr_rsa-0102-1122334455667788.der
ek_csr_ec-0102-1122334455667788.der]] + EKCert[[EK Certificate
ek_cert_rsa-0102-1122334455667788.der
ek_cert_ec-01020-1122334455667788.der]] + + fTPMServer --> fTPMCA + fTPMServer ~~~ EKCSR + EKCSR ~~~ fTPMCA + + fTPMCA --> fTPMServer + fTPMServer ~~~ EKCert + EKCert ~~~ fTPMCA +``` + +### Generating per-device EKB +The offline provision method aims to create a per-device EKB image with the device's fTPM properties: + +- Device_SN, EPS Seed +- Two certificates (RSA and EC). + +The ODM EKB Gen Tool encodes the fTPM properties into the EKB image and the output of the per-device EKB images is saved as an unencrypted binary file with the OEM_ID and SN as the filename index. + +```mermaid +graph LR + subgraph HW [KDK DB] + direction LR + kdk_db(kdk_db) + end + subgraph TOOL [Tool] + GenEkbTool(ODM EKB Gen Tool) + end + subgraph EKB [EKB] + direction LR + DevSN(Device_SN) + EPSSeed(EPS Seed) + EKCertRsa(EK Cert RSA) + EKCertEc(EK Cert EC) + end + subgraph EKB_list [fTPM_EKB list] + direction LR + ekb1[["ftpm_ekb_${OEM_ID}-${SN}.bin"]] + ekb2[[ftpm_ekb_0102-1122334455667788.bin]] + ekb3[[ftpm_ekb_0102-1122334455667789.bin]] + ekb4[[ftpm_ekb_0102-1122334455667790.bin]] + end + + HW --> TOOL --> EKB ~~~ EKB_list +``` + +> [!Note] Here is some important information about the EKB contents: +> - EKB also contains device manufacturer (OEM) defined keys such as the UEFI payloads encryption key, the UEFI variable authentication key, and the disk encryption key (called user keys in general). After the per-device-based fTPM property EKB, which is called fTPM_EKB, is generated in plain binary form by the fTPM manufacturer (by running odm_ekb_gen.py), the ftpm_EKB is sent to the device manufacturer so that the user keys can be added by running oem_ekb_gen.py by the device manufacturer. +> - The final result EKB that contains the fTPM_EKB, and user keys is encrypted and signed by K1-derived keys. K1 is owned by the device manufacturer and is burned to OEM_K1 fuse through OEM_fuseblob. +> - [The fTPM Production Flow](#the-ftpm-production-flow) section provides more information about fuseblob generation and burning by using the FSKP tool. + +## The Key Derivation Process to support fTPM + +This section provides a list of the prerequisites to use Jetson Secure Bootloaders. The fTPM provisioning process relies on the secure boot support on the Jetson platform. The secure boot function should construct Hardware Root of Trust (HROT) and Root of Trust for Measurement (RTM) because they are needed for the device attestation in the fTPM provisioning process. + +The Trusted Computing Base (TCB) of the Jetson platform consists of the security-relevant components that have been loaded at the stage of the secure boot chain. +```mermaid +graph LR + subgraph HW [Hardware] + fuse(FUSE) + end + subgraph ROM [ROM] + direction LR + PSCROM(PSCROM) + BootROM(BootROM) + PSCBL(PSCBL) + MB1(MB1) + end + subgraph FMC [FMC] + MB2(MB2) + end + subgraph FW [Firmware] + TOS(TOS
fTPM TA) + end + + HW ~~~ ROM ~~~ FMC ~~~ FW +``` +- The role in the secure boot chain + - The hardware and ROM are the HROT of secure boot and also the ROT and RTM of the secure boot on the device. + - FUSE + - KDK0: A secure fuse slot on Jetson Orin. It will be used to derive the Silicon ID Seed. + - ROM + - This includes the ROM and ROM extension code. + - PSCROM and BootROM are the static and fixed codes stored in the ROM. + - PSCBL and MB1 are the ROM extension code to execute the bottom half of the initial boot. + - First Mutable Code (FMC) + - MB2 is the boot loader that handles the construction of the components for fTPM provisioning support. + - Firmware + - Trusted OS (TOS) is the trusted firmware that includes ARM Trusted Firmware (ATF), OP-TEE OS with the fTPM, and fTPM helper TAs. + +### Silicon ID Provisioning Flow in Secure Boot + +The Silicon ID Seed provisioning flow along the TCBs in the secure boot chain. There are three layers: +- Hardware and ROM (PSCROM, BootROM, PSCBL, and MB1). +- FMC (MB2). +- Firmware (TOS). + +The purpose of this flow is to generate a Silicon ID seed, fTPM seed, the signature of MB2 event log, and the signature of TOS event log. The security mechanism of the key generation flow uses the TZ-SE, which is the hardware Security Engine in the TrustZone, but the keyslot is not accessible by the CPU. The Silicon ID key pair and the signatures of the event logs are generated by MB2 and are passed to OP-TEE using encrypted TZ memory and are used to identify the device and the firmware status during the fTPM provisioning process (if needed). + +The Silicon ID generation flow: +- In the PSCBL layer: + - Silicon_ID is the KDF(key=KDK0, Device_SN) + - The Device_SN is a unique number that comprises an OEM_ID and a unique SN. +- In the MB2 layer: + - fTPM Seed + - The fTPM Seed is KDF(key=Silicon_ID, constant str1). + - Silicon ID Key Seed. + - The Silicon ID Key Seed is KDF(key=Silicon_ID, constant str2). + - The Silicon_ID key pair. + - The Silicon_IDkey pair is f(ECC, NIST P256)KEYGEN(seed=Silicon_ID_Key_Seed). + - The signature of the MB2 event log. + - The Event_log_MB2.sig is f(ECDSA)SIGN(key=Silicon_IDpriv key, digest=SHA512(MB2)). + - The signature of the TOS event log. + - The Event_log_TOS.sig is f(ECDSA)SIGN(key=Silicon_IDpriv key, digest=SHA512(TOS)). + +### EPS Derivation Flow in the OP-TEE OS Layer + +The Endorsement Primary Seed (EPS) is the ROT of the fTPM entity and is tied with the EK, which can be used to attest the TPM identity and the keys generated by the TPM. The EPS is derived from the TOS layer of TCB in the Jetson device. The fTPM helper PTA in the OP-TEE OS implements the EPS derivation process by using the fTPM Seed from the bootloader and the fTPM property EPS_Seed in the EKB. + +The EPS will be injected into fTPM TA during the TA's first start-up time and stored in NV memory. + +- In the fTPM helper PTA layer: + - Here is the EPS derivation flow: + 1. Device_SN is fuse_read(ODMID, ODM_INFO). + 2. fTPM Root Seed + - The fTPM Root Seed is KDF(key=fTPM_Seed, constant str). + 3. EPS + - The EPS is KDF(key=fTPM_Root_Seed, info=Device_SN, salt=EPS_Seed). + + +> [!Note] +> - The EPS Seed is a random number that is generated by odm_ekb_gen.py and stored in EKB. + +## The fTPM Production Flow + +The fTPM production flow is the design of provisioning an EK certificate by the fTPM manufacturer who owns the CA and fTPM manufacturing server and is qualified to issue the certificate. This should be done in a secure environment during the fTPM manufacturing process. + +Here are the requirements of the fTPM Manufacturer Server: +- This server should be a secure environment and have Hardware Secure Module (HSM) support. +- This server is responsible for generating the materials for fTPM production. + +Here are the requirements of the fTPM Manufacturer CA: +- A CA ==MUST== verify fTPM residency of a key before signing a certificate. This can be done by verifying the signature of the EK CSR. +- The CA ==SHOULD== support a standard certificate transport protocol that provides protection from replay attacks and provides confidentiality and integrity. + +~~~mermaid +sequenceDiagram + participant odm as fTPM Design Manufacturer
(ODM)
fTPM Manufacturer Server + participant oem as OEM Manufacturer
OEM Manufacturer Server + participant oem_factory as OEM Manufacturer Factory + + critical + Note over odm: ODM Fuseblob Generation + Note over odm: 1. Generating keys and Materials owned by ODM
(ODM_KDK0, PKC, SBK, OEM_ID, and SN, etc.) + Note over odm: 2. Generating ODM fuseblob
The fuseblob is encrypted and signed by ODM owned fskp key (or fskp expansion key). + Note over odm: 3. Storing fuseblobs in the database
(ODM_fuseblob_db) + end + + critical + Note over oem: OEM Fustblob Generation + Note over oem: 1. Generating OEM K1 and K2 keys + Note over oem: 2. Generating OEM fuseblob + end + + critical + Note over odm: ODM EKB Generation Phase 1 + Note over odm: 1. Generating EPS Seed and EK Certificates + Note over odm: 2. Generating EKB_ftpm_db + end + + odm->>oem: Send EKB_ftpm_db to OEM + + critical + Note over oem: OEM EKB Generation + Note over oem: 1. Generating the user-defined keys in EKB + Note over oem: 2. Merging the EKB_ftpm_db from ODM and
the user-defined keys. + Note over oem: 3. Encrypting the EKB image by OEM K1. + Note over oem: 4. Output the EKB_final_db + end + + oem->>odm: Send EKB_final_db to ODM + + critical + Note over odm: ODM EKB Generation Phase 2 + Note over odm: 1. Storing the EKB_final_db + end + + critical + Note over odm: ODM packages Generation + Note over odm: 1. Generating the QSPI Image + Note over odm: 2. Signing and encrypting the EKB_final_db by using PKC and SBK keys and output EKB_db.signed + Note over odm: 3. Generating per OEM basis package
ODM_fuseblob_db, QSPI image, and EKB_db.signed + end + + odm->>oem: Send the above packages to OEM + + critical + Note over oem: OEM packages Generation + Note over oem: 1. Generating complete QSPI image package + Note over oem: 2. Generating mass storage (eMMC or NVMe ) image package + end + + oem->>oem_factory: Deliver the packages to the factory + + Note over oem_factory: Running FSKP tool
Burn the OEM owned fuse: OEM_fuseblob + + Note over oem_factory: Running FSKP tool
Burn the per device basis fuse: ODM_fuseblob_db + + Note over oem_factory: Running flashing tool
1. flashing images to QSPI and mass storage.
2. flashing the per device specific EKB from EKB_db.signed. +~~~ + +The diagram shows the fTPM production flow. + +Here are the roles in the diagram: +- The fTPM Design Manufacturer (aka ODM): + - Is the owner of the fTPM manufacturer server and the fTPM manufacturer CA. + - Delivers the fTPM packages to OEM. +- The OEM Manufacturer: + - Owns the OEM defined fuse keys. + - Owns the user-defined keys in EKB. + - Owns the OS bootloader e.g. UEFI and UEFI payloads such as L4TLauncher. + - Owns Platform Vendor (PV) keys that encrypt and sign UEFI image. + - Generates the packages for production. +- The OEM Manufacturer Factory assembles, fuses, and flashes the devices. + +Here is the fTPM production flow: +- ODM Fuseblob Generation + - The keys and materials, such as ODM_KDK0, SN, PKC, and SBK keys, which are owned by ODM are generated. + - The SECURITY_INFO and SECURITY_MODE fuses are owned by ODM as well. Please reference [Generating the Corresponding fuseblobs](#generating-the-corresponding-fuseblobs) section. + - The ODM fuseblob is generated. + - Run the "KDK Gen Tool" (kdk_gen.py) to generate **ODM_KDK_db**. (db means database.) + - Run the fuse burn tool (fskp_fuseburn.py) with ODM_KDK_db and PKC, SBK keys as input. + - The ODM fskp key will be used as the signing and encryption key to generate the ODM signed **ODM_fuseblob_db**. + - The fuseblobs are stored in the database. + - The fuseblob database (ODM_fuseblob_db) is a list of individual files, such as odm_fuseblob-${Device_SN}.bin. + +- OEM Fuseblob Generation + - The fuse keys owned by OEM such as OEM_K1 and OEM_K2. + - The PSC_ODM_STATIC fuse is owned by OEM as well. + - The OEM fuseblob is generated. + - Run the fuse burn tool (fskp_fuseburn.py) with the OEM fuse configuration XML file. + - The field such as OEM_K1, OEM_K2, PSC_ODM_STATIC, etc, should be filled in the configuration file. + - The OEM fskp key will be used as the signing and encryption key to generate the OEM signed **OEM_fuseblob**. + +- The ODM EKB Generation Phase 1. + - The EPS Seed and EK Certificates are generated. + - This will use the fTPM Gen CSR tool to generate the fTPM EK CSR. + - The EK CSR should be delivered to the CA and signed by the CA. + - The CA returns the EK certificate. + - The **EKB_ftpm_db** is generated. + - Run the ODM EKB Gen tool (odm_ekb_gen.py) with the ODM_KDK_db as the input. + - Send the **EKB_ftpm_db** to OEM. + +- OEM EKB Generation + - The user-defined keys that will be encoded into EKB are generated. + - Run the OEM EKB Gen tool (oem_ekb_gen.py) to merge the EKB_ftpm_db and user-defined keys. + - Use the OEM_K1 key as the encryption key to generate OEM encrypted **EKB_final_db**. + - Send the **EKB_final_db** to ODM. + +- ODM EKB Generation Phase 2 + - Receiving and storing the EKB_final_db. + +- ODM Packages Generation + - Generating the QSPI image, for example, you can run the flashing tool with PKC and SBK keys to generate, sign, and encrypt images for all partitions on QSPI. + - ==Note:== The generated UEFI and EKB are used only as placeholders. The final UEFI is generated and signed by OEM, and the final EKB is loaded from EKB_final_db. + - Sign and encrypt the EKB_final_db by using PKC and SBK keys and output EKB_db.signed. + - Generate the per-OEM packages. + - ODM_fuseblob_db, QSPI image, and EKB_db.signed + + > [!Note] Here is some important information: + > - ODM_fuseblob_db contains a list of encrypted and signed fuseblobs including odm_fuseblob--, odm_fuseblob--, and so on. + > - EKB_db.signed contains a list of PKC and SBK signed and encrypted EKB such as ekb--.signed, ekb--.signed, and so on. + > - It is a one-to-one mapping between odm_fuseblob-- and ekb--, and the flashing tool ensures ekb-- is only flashed to the device with fuseblob-- burned. + - Send the packages to OEM. + +- OEM Packages Generation + - Generate the complete QSPI image package. + - Generate the mass storage (eMMC or NVMe) image package. + - Deliver the package to the factory. + +- OEM Factory + - Burn the OEM fuseblob. + - Burn the per-device basis ODM fuseblob. + - Flash the device. + - Flash the QSPI and the mass storage. + - Flash the per-device basis EKB image. + +### The fTPM Production Flow when ODM and OEM are in the same entity + +The fTPM production flow involves collaboration between ODMs and OEMs to create and generate per-device basis fuse blobs and images. However, there is a case where the same entity is capable of playing both ODM and OEM roles, In other words, it can handle the fTPM functional design, EK certificate signing, device image signing, and device manufacturing. In such cases, the UEFI PV key feature can be skipped, simplifying the fTPM production flow. The same PKC key used to sign low-level firmwares is also used to sign the UEFI image. For detailed flow and command samples, please refer to Appendix B. + +## The Software Architecture to Support fTPM Provisioning +~~~mermaid +graph LR + subgraph optee [OP-TEE] + direction TB + subgraph sel0 [S-EL0] + direction LR + ftpm_helper_ta(fTPM Helper TA) + ftpm_ta(fTPM TA) + ftpm_helper_ta ~~~ ftpm_ta + end + subgraph sel1 [S-EL1] + ftpm_helper_pta(fTPM Helper PTA) + end + end + subgraph el0 [EL0] + direction LR + ftpm_prov_script(fTPM provisioning script) + ftpm_helper_ca(fTPM Helper CA) + ftpm_prov_script ~~~ ftpm_helper_ca + end + + el0 ~~~ sel0 +~~~ + +The SW Components +- fTPM provisioning script + - This sample script handles the fTPM provisioning process on the Jetson device. + - The provisioning process on the device. + - Querying the EK certificates from the EKB. + - Storing the EK certificate to the fTPM NV memory. + - Taking ownership of the fTPM. + - Creating EK accordingly with the default EK handles. + - The provisioning process only needs to be activated once. + - This script should be bundled with the fTPM support package provided by the fTPM design manufacturer (ODM). +- The fTPM helper TA/CA and PTA + - They are the applications designed for fTPM provisioning support. + - fTPM helper CA + - The fTPM helper CA provides the command line interface (CLI) for the script to query the EK certificates from the EKB. + - fTPM helper TA + - The fTPM helper TA provides the interfaces to support the fTPM helper CA. + - It helps to query SN, event log signatures, and EK certificates. + - fTPM helper PTA + - The fTPM helper PTA helps to gather the fTPM properties from MB2 and EKB. + - The fTPM helper PTA retrieves Device SN from the fuse and makes sure it matches with the Device SN in EKB. + - The EPS derivation function will be executed by the PTA. +- fTPM TA + - The fTPM TA should support the TPM2 functionalities defined by TCG. + - The TPM2 function in the fTPM TA should be a black box. It should NOT provide any interface other than TCG defined to access the TPM internal functions. + - The fTPM TA gets the EPS from the fTPM helper PTA during the first startup time and stores the EPS in the NV memory. + +## The fTPM Provisioning and Activation Flow + +~~~mermaid +sequenceDiagram + participant pscbl as PSCBL + participant mb2 as MB2 + participant fhpta as fTPM-helper PTA + participant fta as fTPM TA + participant fhta as fTPM-helper TA + participant fhca as fTPM-helper CA + participant usrspace as User Space + + box Secure Bootloaders + participant pscbl + participant mb2 + end + + box Secure World + participant fhpta + participant fhta + participant fta + end + + box Normal World + participant fhca + participant usrspace + end + + Note left of pscbl: Device Power On + + critical + Note over pscbl: Silicon_ID Derivation + Note over pscbl: 1. Silicon_ID = KDF(KDK0, Device_SN) + end + + critical + Note over mb2: fTPM_Seed Derivation + Note over mb2: 1. fTPM_Seed = KDF(Silicon_ID, const str1) + Note over mb2: 2. Generating the Silicon_ID key pair + Note over mb2: 3. Signing the MB2 event log + Note over mb2: 4. Signing the TOS event log + end + + critical + Note over mb2: fTPM MeasuredBoot Support + Note over mb2: 1. Packaging the MB2 and TOS event log
into tpm_event_log buffer. + end + + mb2->>fhpta: Delivering the OP-TEE DTB + Note over mb2,fhpta: The OP-TEE DTB includes:
1. fTPM_Seed
2. Silicon_ID public key
3. Signature of the MB2 event log
4. Signature of the TOS event log
5. The tpm_event_log buffer + + Note left of fhpta: OP-TEE OS Boots Up + + critical + Note over fhpta: Launching the fTPM TA + fhpta->>fta: Launching the fTPM TA + end + + critical + Note over fta: fTPM Measured Boot Support + Note over fta: 1. Parsing the tpm_event_log buffer
2. Updating the MB2 and TOS event log into PCR0
via tpm2_pcrextend command + end + + critical + Note over fhpta: Gathering the fTPM Data from OP-TEE DTB and EKB + Note over fhpta: The fTPM content in DTB:
1. fTPM_Seed
2. Silicon_ID public key
3. Signature of the MB2 event log
4. Signature of the TOS event log + Note over fhpta: The fTPM content in EKB:
1. Device_SN
2. EPS Seed
3. EK Certificates + end + + Note over usrspace: Kernel Boots Up To User Space + Note over usrspace: Starting up the fTPM TA
Inserting the fTPM Driver Module
(Running "modprobe tpm_ftpm_tee") + + usrspace->>fta: Initializing the fTPM TA + + critical + Note over fta: Initializing fTPM TA + Note over fta: Provisioning EPS
(Only needs to be done at 1st startup time for initial provisioning)
1. Invoking the EPS derivation function + fta->>fhpta: Invoking the EPS derivation function + Note over fhpta: Processing the EPS derivation function
1. Device_SN = fuse_read(ODMID, ODMINFO)
2. fTPM Root Seed = KDF(key=fTPM_Seed, const str)
3. EPS = KDF(key=fTPM_Root_Seed, info=Device_SN, salt=EPS_Seed) + fhpta->>fta: Returning EPS + Note over fta: 2. Storing EPS in fTPM NV memory + end + + critical + Note over usrspace: fTPM EK Provisioning and Activation
(Running ftpm_device_provisioning.sh) + Note over usrspace: 1. Querying EK Certificates + + usrspace ->>fhca: Querying EK Certificates + fhca->>fhta: Querying EK Certificates + fhta->>fhpta: Querying EK Certificates + fhpta->>fhta: Returning EK Certificates + fhta->>fhca: Returning EK Certificates + fhca->>usrspace: Returning EK Certificates + + Note over usrspace: 2. Taking the ownership of the fTPM
(Setting up the authentication value for the fTPM owner) + + usrspace->>fta: Sending tpm2_changeauth command + + Note over usrspace: 3. Creating EK + + usrspace->>fta: Sending tpm2_createek command + + Note over usrspace: 4. Validating the EK public keys + + Note over usrspace: 5. Writing the EK certificates into fTPM NV memory + + usrspace->>fta: Sending tpm2_nvwrite command + + Note over usrspace: fTPM has been provisioned and activated. + end +~~~ + +# Cheat Sheet + +## Jetson BSP Installation +> [!Note] Jetson BSP Installation +> 1. Download the latest BSP from [Jetson Linux Archive | NVIDIA Developer](https://developer.nvidia.com/embedded/jetson-linux-archive). +> - The Jetson BSP: jetson\_linux\_${rel_ver}_aarch64.tbz2 +> - The sample root filesystem: tegra\_linux\_sample-root-filesystem_${rel_ver}_aarch64.tbz2 +> - The public source tarball: public_sources.tbz2 +> - The toolchain (Optional): aarch64--glibc--stable-${rel_date}.tar.gz +> - The overlay package (Optional): ftpm_${rel_ver}_overlay_release.tbz2 +> - Only needed for overlay release. +> 2. Download the FSKP package. +> - This is a partner release package. Please download it separately. +> 3. Create a ${BSP_TOP} folder. +> ~~~ +> mkdir ${BSP_TOP} +> cd ${BSP_TOP} +> ~~~ +> 4. Install the BSP. +> a. Untar the BSP package. +> ~~~ +> tar jvxf ~/Downloads/jetson_linux_${rel_ver}_aarch64.tbz2 +> ~~~ +> b. Untar the BSP source package. +> ~~~ +> tar jvxf ~/Downloads/public_sources.tbz2 +> ~~~ +> c. Untar the sample RootFS. +> ~~~ +> cd Linux_for_Tegra/rootfs +> sudo tar jvxpf ~/Downloads/tegra_linux_sample-root-filesystem_${rel_ver}_aarch64.tbz2 +> ~~~ +> d. Untar the overlay package. +> ~~~ +> cd ${BSP_TOP} +> tar jvxf ~/Downloads/ftpm_${rel_ver}_overlay_release.tbz2 +> ~~~ +> e. Apply the BSP packages. +> ~~~ +> cd Linux_for_Tegra +> sudo ./apply_binaries.sh +> ~~~ +> f. Install the FSKP packages. +> ~~~ +> cd ${ODM_BSP_TOP} +> tar jvxf ~/Downloads/fskp_partner_t234_${rel_ver}_aarch64.tbz2 +> ~~~ +> g. Untar the ATF and OP-TEE source tarball. +> ~~~ +> cd Linux_for_Tegra/source/ +> tar jvxf atf_src.tbz2 +> tar jvxf nvidia-jetson-optee-source.tbz2 +> cd ../ +> ~~~ + +## Set up the server to run the fTPM production scripts + +- Install the required Python modules +~~~ +sudo apt-get update +sudo apt-get install python3-pip +sudo apt-get remove python3-cryptography +sudo pip3 install asn1crypto +sudo pip3 install cryptography +sudo pip3 install ecdsa +sudo pip3 install numpy +sudo pip3 install oscrypto +sudo pip3 install pyaes +sudo pip3 install pycryptodome +sudo pip3 install pycryptodomex +~~~ +- Fix the issue of asn1crypto manually ([Ref link](https://github.com/wbond/asn1crypto/issues/260)) + - Apply the fix below into "/usr/local/lib/python\/dist-packages/asn1crypto/x509.py". +~~~ +diff --git a/asn1crypto/x509.py b/asn1crypto/x509.py +index 8cfb2c78be27..761594e1a77d 100644 +--- a/asn1crypto/x509.py ++++ b/asn1crypto/x509.py +@@ -686,12 +686,12 @@ class NameTypeAndValue(Sequence): + 'domain_component': DNSName, + 'name_distinguisher': DirectoryString, + 'organization_identifier': DirectoryString, +- 'tpm_manufacturer': UTF8String, +- 'tpm_model': UTF8String, +- 'tpm_version': UTF8String, +- 'platform_manufacturer': UTF8String, +- 'platform_model': UTF8String, +- 'platform_version': UTF8String, ++ 'tpm_manufacturer': DirectoryString, ++ 'tpm_model': DirectoryString, ++ 'tpm_version': DirectoryString, ++ 'platform_manufacturer': DirectoryString, ++ 'platform_model': DirectoryString, ++ 'platform_version': DirectoryString, + 'user_id': DirectoryString, + } +~~~ + +## Supporting Production with fTPM +This section provides information about supporting production with fTPM. + +Here are the prerequisites to Enabling fTPM with HW Silicon ID support: + +- The KDK0 is the root key and must be burned with a 256-bit per-device unique secret value. +- The FUSE_BOOT_SECURITY_INFO must be burned with the following bits: + +| Bits | Description | +| ----- | --------------------------------------------------------------------------------------------------- | +| [2:0] | The authentication scheme field cannot be zero or over 101b.
It must be a valid PKC auth scheme. | +| [9] | OEM key valid. This bit must be 1. | +| [11] | OEM key function. This bit must be 1 to enable the KDF of the OEM fuse key. | +| [13] | OEM key function. This bit must be 1 to enable the KDF of the Silicon ID generation. | + +## KDK Database and Fuseblobs Generation + +This section provides information about generating the KDK database (DB) and fuseblobs. + +### Installing FSKP package + +> [!Note] +> - Before you install the FSKP package: +> - Assume the Jetson Linux BSP has been installed on the host machine +> - Copy "fskp\_partner\_t234\_${rel_version}\_aarch64.tbz2" to ${BSP_TOP} +> ~~~ +> # Install the FSKP package +> cd Linux_for_Tegra +> tar jvxf ${BSP_TOP}/fskp_partner_t234_${rel_version}_aarch64_tbz2 +> cd l4t/tools/flashtools/fuseburn +> ~~~ +> - Before running FSKP tool, install the following Python modules: +> ~~~ +> sudo pip3 install ecdsa +> sudo pip3 install pyaes +> ~~~ + +### Generating kdk-db and the corresponding Silicon ID Public Keys + +> [!Tip] To generate kdk-db and the corresponding Silicon ID Public Keys, run kdk_gen.py. +> ~~~ +> # Command line interface of "kdk_gen.py". +> kdk_gen.py [-h] [--oem_id ${OEM_ID}] [--sn ${SN}] [--num_devices ${NUM_OF_DEVICES}] +> ~~~ +> +> For example, to generate five kdk entries, run the following command. +> ~~~ +> kdk_gen.py --oem_id 0x102 --sn 0x100000002 --num_devices 5 +> ~~~ + +The above example will generate the following files: +- kdk_db_0102-0000000100000002-5.csv +- pubkey_db_0102-0000000100000002-5.csv + +> [!Important] Here is some important information: +> - The KDK database will be used to generate fuseblobs. +> - Here is the content of the KDK database: +> ~~~ +> cat kdk_db_0102-0000000100000002-5.csv +> 0102 0000000100000002 681a8d62bffb803e9b1068eb4e14af3e440b5a73d0e81d161d2817c24dac41a6 +> 0102 0000000100000003 bfec6db0ddab599b2a34d01ab9e641e3b735d7ead9649579689ed535c73d2053 +> 0102 0000000100000004 801575a8ecd51955f8efcc840af0b6f94a4a0d1e2745f97122d46873c83bd751 +> 0102 0000000100000005 a8d49348cbbf34814b387c7189187a1c98fe03a254503e879232765651dcf0ee +> 0102 0000000100000006 a8e20c2e0309a6564d0c694c75fcce9b21b846c54dc3b6343a8c276bbbd2dca5 +> # where the first two columns are oem-id and SN, and the last column is the randomly generated KDK value. +> ~~~ + +> [!Important] Here are the corresponding Silicon ID public keys: +> - The Silicon ID public key database can be used by the fTPM manufacturer CA to verify the device identity during the fTPM provisioning process. +> - The content of the Silicon ID public key database: +> ~~~ +> cat pubkey_db_0102-0000000100000002-5.csv +> 0102 0000000100000002 435ec556a1e23e9a676b8471ff2b2c25ca262bbc7f581abd69de025198cb56d157882fc257c4f544b206796dadf8257d5c4638e70bf8a2f13d9a2b7a30b57c0a +> 0102 0000000100000003 c25aef9b683cc4a2579bf634e35d42ee40b5e31dccef5dad7a16ab8b860dc2ec25a20ed6391edd8aa871cfa999acf57af1f81f1226e74569b2f3fff549bc0809 +> 0102 0000000100000004 b603792a8d28ed60d5b7a6ac604fb56dfbff475cd225665253c58670c19d9b27ea1e0ec21de9ade7d798d0ada7a180c9625b72c6ec5b6074a265e4e8a90b0f6a +> 0102 0000000100000005 7c43b790f97769f86839be2ceaedbbba244d727c311d28c21a8f8ff9a911173d53753cb207ee5f7e11298fed41d603731fe709255f17b2fdf0c7113f15d97e11 +> 0102 0000000100000006 ddc67040dbf78afd4a05581dacef51cd2c8cf0554c532b5ffda54f398f98f1136170fcd39ade40ba04db3ece703e0414eb6060cb10de0d7373e2b3a6c1b251ac +> # where the first two columns are oem-id and SN, and the last column is the corresponding silicon-id public key. +> ~~~ + +### Generating the Corresponding fuseblobs + +- Creating a template fuse configuration XML file called fuse_temp.xml like the following template file. + - Note that ODM and OEM should follow the different template files. + +#### The ODM fuse configuration template +~~~ + + + + + + + + + + + + + +~~~ + +#### The OEM fuse configuration template +~~~ + + + + + +~~~ + +> [!Note] +> - The field "0x<...>" must be replaced with proper values before running fskp_fuseburn.py. + +> [!Tip] To generate fuseblobs, run fskp_fuseburn.py. +> - For example, you can use the kdk db generated above to create five fuseblobs for AGX Orin. +> - Example for ODM: +> ~~~ +> sudo ./fskp_fuseburn.py -f fuse_temp_odm.xml \ +>                         --test \ +>                         --skipfskpkey \ +>                         --multi-blob ftpm_kdk/kdk_db_0102-0000000100000002-5.csv \ +>                         -g odm_out/ \ +>                         -c 0x23 \ +>                         --board-spec orin-agx-board-spec.txt \ +>                         -B ../../../../jetson-agx-orin-devkit.conf +>  +> # Create a tarball to send to the FACTORY. +> tar cf odm_out_0102-0000000100000002-5.tar odm_out/ +> ~~~ +> - Example for OEM: +> ~~~ +> sudo ./fskp_fuseburn.py -f fuse_temp_oem.xml \ +> --test \ +> --skipfskpkey \ +> -g oem_out/ \ +> -c 0x23 \ +> --board-spec orin-agx-board-spec.txt \ +> -B ../../../../jetson-agx-orin-devkit.conf +> +> # Create a tarball to send to the FACTORY. +> tar cf oem_out.tar oem_out/ +> ~~~ +> Here are the command-line interface options: +> - -f +> - With the fuse template file, a list of corresponding fuse configurations will be generated and stored in the ftpm_kdk directory. In this example, a file list like the following is generated: +> - fusexml_0102-0000000100000002.xml +> - ... +> - fusexml_0102-0000000100000006.xml +> - --test +> - This indicates the generated fuseblob will only do a dry run. To actually burn the fuses, replace --test with -b. +> - --skipfskpkey +> - This indicates that no fskp key is used, which means the fuseblobs generated are not encrypted. As a result, this option is used only for testing. +> - To generate encrypted fuseblobs for securely burning fuses at the factory, replace --skipfskpkey with the following: +> - -i \ --key \ or with +> - --key-exp --fskpcfg +> - --multi-blob +> - Use the content from the pre-generated KDK DB to fill in the template fuse configuration XML file. +> - --g \/\ +> - This indicates the generated fuseblob folder. At the factory, the fuseblob are the only binaries needed to burn fuses. +> - For example, you can specify "-g fuse/out". The fuseblob folders generated will be: +> - fuse/out_- +> - fuse/out_0102-0000000100000002 +> - ... +> - fuse/out_0102-0000000100000006 +> - -c \ +> - This indicates the NVIDIA Tegra SoC chip ID. +> - --board-spec +> - This defines the board spec such as BOARDID, SKU, and so on. +> - -B +> - This specifies the low-level boot components, configs, and dtbs that are used for the board to burn the fuses. + +## Generating ODM EKB + +The following scripts are hooked by the ODM EKB Gen tool to generate the EK CSR and sign the EK certificate: +- "ftpm_manufacturer_gen_ek_csr.sh" +- "ftpm_manufacturer_ca_simulator.sh" + - This is the script for signing the EK CSR. The fTPM manufacturer should customize the script to meet the requirements of the CA server. + +> [!Tip] Run odm_ekb_gen.py +> ~~~ +> # Command line interface of "odm_ekb_gen.py" +> odm_ekb_gen.py [-h] [--kdk_db ${KDK_DB}] +> +> # For example, to generate the EKB_ftpm_db, run the following command. +> odm_ekb_gen.py --kdk_db ftpm_kdk/kdk_db_0102-0000000100000002-5.csv +> ~~~ + +By default, the output of the ODM EKB DB will be stored in the "odm_out" folder. The ODM should package them and deliver them to the OEM. + +## Generating OEM EKB +The OEM unpacks the ODM EKB DB and generates the EKB final DB. This will generate per-device basis EKS images that are authenticated and encrypted by the OEM K1 derivation keys. + +> [!Tip] Run oem_ekb_gen.py +> - The OEM EKB Gen tool is a wrapper of the Gen EKB script (gen_ekb.py) from the hwkey-agent sample application. +> - Move the Gen EKB script to the same folder as the OEM EKB Gen tool. +> ~~~ +> oem_ekb_gen.py -oem_k1_key oem_k1.key \ +> -in_sym_key sym_t234.key \ +> -in_sym_key2 sym2_t234.key \ +> -in_auth_key auth_t234.key \ +> -in_ftpm_odm_ekb odm_out +> ~~~ +> Here are the command-line interface options: +> - -oem_k1_key or -oem_k2_key +> - The root key of the EKB encryption and authentication key. By default, it uses k1. +> - -in_sym_key +> - The user-defined key for UEFI payloads (such as kernel, kernel-dtb) encryption. +> - -in_sym_key2 +> - The user-defined key for disk encryption support. +> - -in_auth_key +> - The user-defined key for UEFI variable authentication. +> - -in_ftpm_odm_ekb \ +> - The path where the EKB_ftpm_db is located. + +The generated per-device EKS images are stored in the "oem_out" folder. The OEM should package them and deliver them back to ODM. + +## ODM Packages Generation + +### Signing and Encrypting the EKB_final_db + +> [!Tip] Run l4t_sign_image.sh +> - Please refer to the help option for detailed usage. +> - Unpack the EKB_final_db to the oem_out folder. +> - The encrypted and signed EKB\_final\_db are in oem\_out/signed folder. These encrypted/signed eks\_-.signed files are packaged to deliver to the OEM. +> ~~~ +> cd Linux_for_Tegra +> ./l4t_sign_image.sh --chip \ +> --key \ +> --encrypt_key \ +> --mass-ekb oem_out \ +> --type data \ +> --split False +> +> # Packaging the encrypted/signed eks files. +> tar cf eks_--.tar --directory=oem_out/signed/ . +> ~~~ + +### Generating the ODM QSPI Image + +> [!Tip] Run l4t_initrd_flash.sh +> - Please refer to the README file (${BSP_TOP}/Linux_for_Tegra/tools/kernel_flash/README_initrd_flash.txt) and the help option for detailed usage. +> - Run l4t_initrd_flash.sh with --odm-image-gen, using PKC and SBK as the signing and encryption keys, and pv.crt as the UEFI signing public key to generate **lbc_odm.tar.gz (lower boot components)**. +> ~~~ +> cd Linux_for_Tegra +> sudo BOARDID= FAB= BOARDSKU= CHIP_SKU= RAMCODE_ID= \ +> ./tools/kernel_flash/l4t_initrd_flash.sh \ +> --odm-image-gen \ +> --showlogs \ +> --network usb0 \ +> --no-flash \ +> -u \ +> -v \ +> --pv-crt \ +> \ +> internal +> ~~~ + +## OEM Packages Generation + +### Generating the OEM QSPI Image + +> [!Tip] Generating UPI (User Partition Image) +> - Using UEFI keys to generate the UPI. This will output **upi_odm.tar.gz**. +> - Please refer to the README file (${BSP_TOP}/Linux_for_Tegra/tools/README_uefi_secureboot.txt) to generate the UEFI key configuration file. +> ~~~ +> cd Linux_for_Tegra +> sudo ./tools/gen_uefi_default_keys_dts.sh +> sudo BOARDID= FAB= BOARDSKU= CHIP_SKU= RAMCODE_ID= \ +> ./tools/kernel_flash/l4t_initrd_flash.sh \ +> --mass-storage-only +> --showlogs \ +> --network usb0 \ +> --no-flash \ +> --uefi-keys \ +> --uefi-enc \ +> \ +> internal +> ~~~ + +> [!Tip] Generating UEFI Image +> - Using flash.sh with PV signing key (-u), PV encryption key (--pv-enc), and UEFI payload signing key (--uefi-keys) to generate the PV signed and encrypted UEFI image. +> ~~~ +> cd Linux_for_Tegra +> sudo BOARDID= FAB= BOARDSKU= CHIP_SKU= RAMCODE_ID= \ +> ./flash.sh \ +> -k A_cpu-bootloader \ +> --no-flash \ +> -u \ +> --pv-enc \ +> --uefi-keys \ +> --uefi-enc \ +> \ +> internal +> ~~~ + +### Generating the Factory Package + +> [!Tip] Generating the factory tarball +> ~~~ +> cd Linux_for_tegra +> +> # Untar the LBC tarball +> sudo tar xvzf lbc_odm.tar.gz +> +> # Untar the UPI tarball +> sudo tar xvzf upi_oem.tar.gz +> +> cd tools/kernel_flash/images/internal/ +> +> # Copy the PV signed/encrypted UEFI image to the same folder +> sudo cp ${BSP_TOP}/Linux_for_Tegra/bootloader/uefi_jetson_with_dtb_aligned_blob_w_bin_sigheader_encrypt.bin.signed ./ +> +> # Record the UEFI image file size +> ls -l uefi_jetson_with_dtb_aligned_blob_w_bin_sigheader_encrypt.bin.signed +> +> # Record the sha1sum +> sha1sum uefi_jetson_with_dtb_aligned_blob_w_bin_sigheader_encrypt.bin.signed +> +> # Edit the A/B_cpu-bootloader with PV signed/encrypted file size and sha1Sum +> sudo vim flash.idx +> +> # Untar EKB_final_db received from ODM (e.g., eks_0102-0000000100000002-5.tar) +> sudo mkdir ekb_db +> cd ekb_db +> sudo tar xf ${ODM}/eks_0102-0000000100000002-5.tar +> +> # Package the factory tarball +> cd ${BSP_TOP}/Linux_for_Tegra +> sudo tar zvcf factory.tar.gz \ +> tools/kernel_flash/initrdflashparam.txt \ +> tools/kernel_flash/initrdflashimgmap.txt \ +> tools/kernel_flash/images/ +> +> # Send the factory image to the factory +> ~~~ + +## Factory burning fuses and flashing devices flow + +### Burning Fuseblob on a Device + +> [!Tip] +> 1. Install L4T BSP and fskp package on the fuse burning host at the factory. +> 2. Untar the fuseblob. +> 3. Burn the OEM fuseblob. +> 4. Burn the ODM fuseblob. +> +> ~~~ +> # Ex. Burn the OEM fuseblob: +> sudo ./fskp_fuseburn.py -P ./oem_out \ +> -c 0x23 \ +> --board-spec orin-agx-board-spec.txt \ +> -B ../../../../jetson-agx-orin-devkit.conf +> +> # Ex. Burn the ODM fuseblob: +> sudo ./fskp_fuseburn.py -P ./odm_out \ +> -c 0x23 \ +> --board-spec orin-agx-board-spec.txt \ +> -B ../../../../jetson-agx-orin-devkit.conf +> +> # Note: +> # 1. In this case, it is a dry run. No fuses are actually burned. +> # 2. Make sure the ODM fuseblob is burned after the OEM fuseblob is burned. +> # This is because the ODM fuseblob contains Security Mode fuse bit. Once burned, no other fuses can be burned. +> ~~~ + +### Burning Fuseblobs to Multiple Devices + +> [!Tip] Run fskp_massfuseburn.py and fskp_multiblobfuse.py respectively +> - The same steps as burning a single device. +> +> ~~~ +> # Ex. Burn the OEM mass fuseblobs: +> # Untar the tarball, oem_out.tar, received from the OEM. +> sudo ./fskp_massfuseburn.py --skipconfirmation \ +> --burnfuse \ +> -P ./oem_out \ +> -c 0x23 \ +> --board-spec orin-agx-board-spec.txt \ +> -B ../../../../jetson-agx-orin-devkit.conf +> +> # Ex. Burn the ODM mass fuseblobs: +> # Untar the tarball, odm_out_0102-0000000100000002-5.tar, received from the ODM. +> sudo ./fskp_multiblobfuse.py --out ./odm_out \ +> --oem_id 0x0102 \ +> --sn 0x0000000100000002 \ +> --num_devices 5 \ +> --board-spec orin-agx-board-spec.txt \ +> -B ../../../../jetson-agx-orin-devkit.conf +> ~~~ + +### Flashing the Devices + +> [!Tip] +> 1. Install L4T BSP on the host to flash the devices. +> 2. Untar the factory package. +> 3. Flash the devices. +> ~~~ +> cd ${BSP_TOP}/Linux_for_Tegra +> +> # Untar the factory tarball +> sudo tar zvxf factory.tar.gz +> cp tools/kernel_flash/images/rcmboot/* bootloader/ +> +> # Flash the devices +> sudo ./tools/kernel_flash/l4t_initrd_flash.sh \ +> --flash-only \ +> --showlogs \ +> --network usb0 \ +> --ekb-pair \ +> \ +> internal +> ~~~ + +## Running the fTPM Provisioning Script on the Jetson Device + +- The fTPM provisioning script handles the process of provisioning the fTPM on the Jetson device. This involves querying EK certificates from the Encrypted Key Block (EKB), storing the EK certificate in the fTPM Non-Volatile (NV) memory, taking ownership of the fTPM, and creating EK accordingly with default EK handles. +- The fTPM helper TA/CA and PTA are applications designed to support fTPM provisioning. These components provide interfaces for querying SN, event log signatures, and EK certificates. +- The fTPM TA supports TPM2 functionalities defined by the Trusted Computing Group (TCG). It receives EPS from the fTPM helper PTA during the first startup time and stores it in NV memory with the provisioning process. + +### Rebuilding and Updating the TOS Image for fTPM Support + +To customize the fTPM function on your Jetson device, you may need to rebuild and update the Trusted Operation System (TOS) image. Follow these steps to ensure a secure environment for your application. +> [!Tip] +> 1. Download the source package from [Jetson Linux Archive](https://developer.nvidia.com/embedded/jetson-linux-archive). +> 2. To rebuild the TOS image, refer to the README file in the OP-TEE or ATF source package. Additionally, manually add the "-t" option to enable fTPM feature. +> ~~~ +> ./optee_src_build.sh -p t234 -t +> +> # Update the TOS image after rebuild. +> cp tos.img ${ODM_BSP_TOP}/Linux_for_Tegra/bootloader/tos-optee_t234.img +> ~~~ +> 3. Re-flash the device with the new TOS image. +> 4. Preparing the fTPM provisioning folder +> - If you need to use fTPM, create a provisioning folder and copy the necessary file into it. +> ~~~ +> # Create a "ftpm_prov" folder. +> mkdir -p ftpm_prov +> +> # Copy the provisioning script into the folder. +> scp optee/samples/ftpm-helper/host/tool/ftpm_device_provision.sh ${REMOTE_DEVICE}:${DEST_PROV_DIR}/ftpm_prov +> ~~~ +> - Note: The ${REMOTE_DEVICE} and {DEST_PROV_DIR} variables should be replaced with the actual device's IP address and provisioning directory, respectively. + +### Running the fTPM Provisioning Script +> [!Note] +> 1. Load the fTPM driver module. +> ~~~ +> sudo modprobe tpm_ftpm_tee +> ~~~ +> 2. Provision and activate the fTPM by running the ftpm_device_provision.sh script. +> - This script completes the following tasks: +> - Queries the EK Certificates (RSA and EC) and stores them in the fTPM NV memory. +> - Sets up the fTPM authorization. +> +> ~~~ +> cd ftpm_prov +> sudo ./ftpm_device_provision.sh -r ek_cert_rsa.der -e ek_cert_ec.der -p owner +> ~~~ +> +> - Here are the command-line interface options: +> - -r \ +> - This is the must-have option to save the RSA EK certificate after querying from EKB. +> - -e \ +> - This is the must-have option to save the EC EK certificate after querying from EKB. +> - -p \ +> - This is the must-have option of the fTPM authorization value. + +## Verifying the fTPM EK + +With the offline provision method, the fTPM EKs are pre-generated by the fTPM production scripts. The ODM EKB Gen Tool provides a __verify__ mode, which can help the fTPM manufacturer validate the fTPM EKs before shipping the EKB images to the OEM. The mode is completed by comparing the fTPM EK public keys generated by fTPM production script with the EK public keys generated by the fTPM TA. + +Before you verify the fTPM EK, ensure that you have the following: +- A dedicated Jetson device. + - To verify the fTPM EK, you need to set up a Jetson device with custom fTPM helper TA and the CA. +- A secure environment. + - The intermediate data for fTPM EK verification should be kept in a secure environment, and you need to remove the data after the verification is complete. + +### Generating the fTPM EK Verification Data +The intermediate data for fTPM EK verification can be generated by running the ODM EKB Gen Tool with the __--verify__ option. The output data is only for fTPM EK verification. + +> [!Tip] +> ~~~ +> odm_ekb_gen.py --kdk_db ftpm_kdk/kdk_db-01020000000100000002-5.csv --verify +> ~~~ + +The odm_ekb_gen.py creates the "ftpm_keys.txt" file in the output folder when --verify is set. + +This file contains the following components: +- Device SN +- EPS +- RSA EK public key +- EC EK public key + +### Setting up a Dedicated Jetson Device +To enable the fTPM EK verification function on Jetson device, you need to rebuild OP-TEE with the __CFG_JETSON_FTPM_HELPER_INJECT_EPS__ configuration. This is a custom configuration only for fTPM EK verification, and this configuration should not be enabled in the OP-TEE production build. + +To enable the fTPM EK verification function, change the "optee_src_build.sh" script: +~~~ +diff --git a/optee_src_build.sh b/optee_src_build.sh +index 383a4d3d9df4..c99500da89f4 100755 +--- a/optee_src_build.sh ++++ b/optee_src_build.sh +@@ -94,7 +94,8 @@ function build_optee_sources { + if [ "${ENABLE_FTPM_BUILD}" == "yes" ]; then + optee_config="CFG_CORE_TPM_EVENT_LOG=y \ + CFG_REE_STATE=y \ +- CFG_JETSON_FTPM_HELPER_PTA=y" ++ CFG_JETSON_FTPM_HELPER_PTA=y \ ++ CFG_JETSON_FTPM_HELPER_INJECT_EPS=y" + early_tas="${build_dir}/early_ta/cpubl-payload-dec/0e35e2c9-b329-4ad9-a2f5-8ca9bbbd7713.stripped.elf \ + ${build_dir}/early_ta/ftpm-helper/a6a3a74a-77cb-433a-990c-1dfb8a3fbc4c.stripped.elf \ + ${build_dir}/early_ta/luks-srv/b83d14a8-7128-49df-9624-35f14f65ca6c.stripped.elf \ +~~~ +After this process is complete, rebuild OP-TEE, generate the TOS image again, and flash the TOS image to the board. + +### Verifying the fTPM EKs + +> [!Tip] To verify the RSA and EC EK public keys on a Jetson Orin device, run the ftpm_offline_provisioning_verify.sh script: +> 1. Copy the "ftpm_keys.txt" to the Jetson Orin device. +> ~~~ +> scp ${SRC_VERIFY_DIR}/ftpm_keys.txt ${REMOTE_DEVICE}:${DEST_VERIFY_DIR}/ftpm_prov +> ~~~ +> 2. Copy the "ftpm_offline_provisioning_verify.sh" script from in the optee source directory to the Jetson Orin device. +> ~~~ +> scp optee/samples/ftpm-helper/host/tool/ftpm_offline_provisioning_verify.sh ${REMOTE_DEVICE}:/location/to/ftpm_prov +> ~~~ +> 3. Copy the custom nvftpm-helper-app to the Jetson Orin device. +> ~~~ +> scp optee/build/t234/ca/ftpm-helper/nvftpm-helper-app ${REMOTE_DEVICE}:/location/to/ftpm_prov +> ~~~ +> 4. Run ftpm_offline_provisioning_verify.sh on the Jetson Orin device. +> ~~~ +> cd ${DEST_VERIFY_DIR}/ftpm_prov +> sudo ./ftpm_offline_provisioning_verify.sh +> ~~~ + +Appendix A: The Overall Command Reference Flow for fTPM Manufacturing Support +----------------------------------------------------------------------------- + +# The ODM Workflow + +> [!Note] The ODM Preparation Work +> 1. [Jetson BSP Installation](#jetson-bsp-installation) +> 2. [Rebuild and Update the TOS Image for fTPM Support (Optional)](#rebuilding-and-updating-the-tos-image-for-ftpm-support). +> 3. Retrieve the OEM's "pv_key.crt" and store at "~/oem_keys/uefi_keys/pv_key.crt". +> 4. Assume that the ODM's own keys are stored at: +> ~~~ +> ~/odm_keys/rsa3k.pem +> ~/odm_keys/sbk-32.key +> ~~~ + +> [!Note] ODM EKB Generation +> 1. Generate the ODM EKB DB +> ~~~ +> cd ${BSP_TOP}/Linux_for_Tegra/source/optee/samples/ftpm-helper/host/tool +> ./kdk_gen.py --oem_id 0x21 --sn 0x1000218000 --num_devices 2 +> ./odm_ekb_gen.py --kdk_db ftpm_kdk/kdk_db_0021-0000001000218000-2.csv +> tar cf odm_out_0021-0000001000218000-2.tar odm_out/ +> ~~~ +> 2. The ODM sends the "odm_out_0021-0000001000218000-2.tar" to the OEM. +> - The OEM will then add OEM/user_defined keys into EKB. +> - Encrypted the updated EKB. +> - Generate the EKB tarball. +> - And then send the tarball back to ODM +> 3. The ODM waits to receive the "oem_out_0021-0000001000218000-2.tar" from the OEM. +> ~~~ +> cd ${BSP_TOP}/Linux_for_Tegra/ +> tar xvf oem_out_0021-0000001000218000-2.tar +> # The tarball is untared at the "oem_out" folder. +> +> # Singing and generating the final ekb_db. +> ./l4t_sign_image.sh --chip 0x23 \ +> --key ~/odm_keys/rsa3k.pem \ +> --encrypt_key ~/odm_keys/sbk-32.key \ +> --mass-ekb oem_out \ +> --type data \ +> --split False +> tar cf eks_0021-0000001000218000-2.tar --directory=oem_out/signed . +> ~~~ +> 4. The ODM sends the "eks_0021-0000001000218000-2.tar" to the OEM. + +> [!Note] ODM Fuseblob Generation +> ~~~ +> cd ${BSP_TOP}/Linux_for_Tegra +> cd l4t/tools/flashtools/fuseburn/ +> sudo ./fskp_fuseburn.py -f odm_fuse_template.xml \ +> --multi-blob ${ODM_BSP_TOP}/Linux_for_Tegra/source/optee/samples/ftpm-helper/host/tool/ftpm_kdk/kdk_db_0021-0000001000218000-2.csv +> --test \ +> -i 63 \ +> --key-exp fskp_ak.bin fskp_ek.bin \ +> --fskpcfg fskp_conf.txt \ +> -g fuseblob/odm_out \ +> -c 0x23 \ +> --board-spec orin-agx-board-spec.txt \ +> -B ../../../../jetson-agx-orin-devkit.conf +> tar cf fuseblob_odm_out_0021-0000001000218000-2.tar fuseblob/ +> ~~~ +> - Note: The parameters used in this command are for reference only. They should be replaced with the user's specific fskp keys and board. +> - The ODM sends "fuseblob_odm_out_0021-0000001000218000-2.tar" to the OEM. + +> [!Note] QSPI Image Generation (aka lower boot components: lbc) +> - AGX Orin with eMMC as the RootFS storage +> ~~~ +> cd ${BSP_TOP}/Linux_for_Tegra +> sudo BOARDID= FAB= BOARDSKU= CHIP_SKU= RAMCODE_ID= \ +> ./tools/kernel_flash/l4t_initrd_flash.sh \ +> --odm-image-gen \ +> --showlogs \ +> --network usb0 \ +> --no-flash \ +> -u ~/odm_keys/rsa3k.pem \ +> -v ~/odm_keys/sbk-32.key \ +> --pv-crt ~/oem_keys/uefi_keys/pv_key.crt \ +> jetson-agx-orin-devkit \ +> internal +> ~~~ +> - AGX Orin with NVMe as the RootFS storage +> ~~~ +> sudo BOARDID= FAB= BOARDSKU= CHIP_SKU= RAMCODE_ID= \ +> ./tools/kernel_flash/l4t_initrd_flash.sh \ +> --odm-image-gen \ +> --showlogs \ +> --network usb0 \ +> --no-flash \ +> -c bootloader/t186ref/cfg/flash_t234_qspi.xml \ +> -u ~/odm_keys/rsa3k.pem \ +> -v ~/odm_keys/sbk-32.key \ +> --pv-crt ~/oem_keys/uefi_keys/pv_key.crt \ +> jetson-agx-orin-devkit \ +> internal +> ~~~ +> - Orin Nano with NVMe as the RootFS storage +> ~~~ +> sudo BOARDID= FAB= BOARDSKU= CHIP_SKU= RAMCODE_ID= \ +> ./tools/kernel_flash/l4t_initrd_flash.sh \ +> --odm-image-gen \ +> --showlogs \ +> --network usb0 \ +> --no-flash \ +> -p "-c bootloader/t186ref/cfg/flash_t234_qspi.xml" \ +> -u ~/odm_keys/rsa3k.pem \ +> -v ~/odm_keys/sbk-32.key \ +> --pv-crt ~/oem_keys/uefi_keys/pv_key.crt \ +> jetson-orin-nano-devkit \ +> internal +> ~~~ +> - The output from the above command is "lbc_odm.tar.gz". +> - The ODM sends it to the OEM. + +# The OEM Workflow + +> [!Note] The OEM Preparation Work +> 1. [Jetson BSP Installation](#jetson-bsp-installation) +> 2. Assume that the OEM's user defined keys (for ekb generation) are stored at: +> ~~~ +> ~/oem_keys/oem_k1.key +> ~/oem_keys/fv_ekb_t234 +> ~/oem_keys/sym_t234.key +> ~/oem_keys/sym2_t234.key +> ~/oem_keys/auth_t234.key +> ~~~ +> 3. OEM's PV keys (for UEFI/cpu-bootloader image signing and encryption) are stored at: +> ~~~ +> ~/oem_keys/pv_keys/rsa_priv-3k-pv.pem +> ~/oem_keys/pv_keys/pv_key.crt (This public key is shared with the ODM.) +> ~/oem_keys/pv_keys/pv_enc_k2.key (This is OEM_K2 fuse value.) +> ~~~ +> 4. OEM's uefi keys (for UEFI payloads such as kernel/kernel-dtb signing and encryption) are stored at: +> ~~~ +> ~/oem_keys/uefi_keys/uefi_keys.conf +> ~/odm_keys/uefi_keys/uefi_enc.key +> ~~~ + +> [!Note] OEM Fuseblob Generation +> 1. Generating the OEM fuseblob +> ~~~ +> cd ${BSP_TOP}/Linux_for_Tegra +> cd l4t/tools/flashtools/fuseburn/ +> sudo ./fskp_fuseburn.py --skipfskpkey \ +> -c 0x23 \ +> -g fuseblob/oem_out \ +> --test \ +> -f oem_fuse_template.xml \ +> --board-spec orin-agx-board-spec.txt \ +> -B ../../../../jetson-agx-orin-devkit.conf +> tar cf fuseblob_oem_out.tar fuseblob/oem_out +> ~~~ +> +> 2. The OEM sends "fuseblob_oem_out.tar" to the FACTORY. +> 3. The OEM receives ODM fuseblob db from the ODM. +> 4. The OEM sends "fuseblob_odm_out_0021-0000001000218000-2.tar" to the FACTORY. + +> [!Note] OEM EKB Generation +> 1. Receiving and untar "odm_out_0021-0000001000218000-2.tar" from the ODM. +> ~~~ +> cd ${BSP_TOP}/Linux_for_Tegra/source/optee/samples/ftpm-helper/host/tool/ +> cp ${BSP_TOP}/odm_out_0021-0000001000218000-2.tar ./ +> tar xf odm_out_0021-0000001000218000-2.tar +> ~~~ +> 2. Adding the OEM user defined keys into ekb. +> ~~~ +> cp ../../../hwkey-agent/host/tool/gen_ekb/gen_ekb.py ./ +> ./oem_ekb_gen.py -oem_k1 ~/oem_keys/oem_k1.key \ +> -in_sym_key ~/oem_keys/sym_t234.key \ +> -in_sym_key2 ~/oem_keys/sym2_t234.key \ +> -in_auth_key ~/oem_keys/auth_t234.key \ +> -in_ftpm_odm_ekb odm_out +> tar cf oem_out_0021-0000001000218000-2.tar oem_out/ +> ~~~ +> 3. Sending "oem_out_0021-0000001000218000-2.tar" to the ODM. +> - Note: The result from Step 3 here is the image that ODM awaits at Step 3 in the "ODM EKB Generation" flow, as described earlier. + +> [!Note] UPI Image Generation (aka User Partition Image: UPI) +> ~~~ +> cd ${BSP_TOP}/Linux_for_Tegra +> sudo ./tools/gen_uefi_default_keys_dts.sh ~/oem_keys/uefi_keys/uefi_keys.conf +> ~~~ +> - Note: In the commands below, the key in --uefi-enc \ option is used for UEFI payload encryption. This key value is the sym_t234.key defined and added into the EKB by the OEM. +> - AGX Orin with eMMC as the RootFS storage +> ~~~ +> sudo BOARDID= FAB= BOARDSKU= CHIP_SKU= RAMCODE_ID= \ +> ./tools/kernel_flash/l4t_initrd_flash.sh \ +> --mass-storage-only \ +> --showlogs \ +> --network usb0 \ +> --no-flash \ +> --uefi-keys ~/oem_keys/uefi_keys/uefi_keys.conf \ +> --uefi-enc ~/oem_keys/uefi_keys/uefi_enc.key \ +> jetson-agx-orin-devkit \ +> internal +> ~~~ +> - AGX Orin with NVMe as the RootFS storage +> ~~~ +> sudo BOARDID= FAB= BOARDSKU= CHIP_SKU= RAMCODE_ID= \ +> ./tools/kernel_flash/l4t_initrd_flash.sh \ +> --mass-storage-only \ +> --showlogs \ +> --network usb0 \ +> --no-flash \ +> --external-device nvme0n1p1 \ +> --external-only \ +> -c ./tools/kernel_flash/flash_l4t_t234_nvme.xml \ +> --uefi-keys ~/oem_keys/uefi_keys/uefi_keys.conf \ +> --uefi-enc ~/oem_keys/uefi_keys/uefi_enc.key \ +> jetson-agx-orin-devkit \ +> nvme0n1p1 +> ~~~ +> - Orin Nano with NVMe as the RootFS storage +> ~~~ +> sudo BOARDID= FAB= BOARDSKU= CHIP_SKU= RAMCODE_ID= \ +> ./tools/kernel_flash/l4t_initrd_flash.sh \ +> --mass-storage-only \ +> --showlogs \ +> --network usb0 \ +> --no-flash \ +> --external-device nvme0n1p1 \ +> --external-only \ +> -c ./tools/kernel_flash/flash_l4t_t234_nvme.xml \ +> --uefi-keys ~/oem_keys/uefi_keys/uefi_keys.conf \ +> --uefi-enc ~/oem_keys/uefi_keys/uefi_enc.key \ +> jetson-orin-nano-devkit \ +> nvme0n1p1 +> ~~~ +> - The output from the above command is "upi_oem.tar.gz". + +> [!Note] UEFI Image Generation +> ~~~ +> cd ${OEM_BSP_TOP}/Linux_for_Tegra +> sudo BOARDID= FAB= BOARDSKU= CHIP_SKU= RAMCODE_ID= \ +> ./flash.sh -k A_cpu-bootloader \ +> --no-flash \ +> -u ~/oem_keys/pv_keys/rsa_priv-3k-pv.pem \ +> --pv-enc ~/oem_keys/pv_keys/pv_enc_k2.key \ +> --uefi-keys ~/oem_keys/uefi_keys/uefi_keys.conf \ +> --uefi-enc ~/oem_keys/uefi_keys/uefi_enc.key \ +> jetson-agx-orin-devkit \ +> internal +> ~~~ +> - The output from the above command is "uefi_jetson_with_dtb_aligned_blob_w_bin_sigheader_encrypt.bin.signed". + +> [!Note] Final Factory tarball Generation +> ~~~ +> cd ${BSP_TOP}/Linux_for_Tegra +> sudo tar zvxf lbc_odm.tar.gz +> sudo tar zvxf upi_oem.tar.gz +> cd tools/kernel_flash/images/internal/ +> sudo cp ${BSP_TOP}/Linux_for_Tegra/bootloader/uefi_jetson_with_dtb_aligned_blob_w_bin_sigheader_encrypt.bin.signed ./ +> +> # Record the UEFI image file size +> ls -l uefi_jetson_with_dtb_aligned_blob_w_bin_sigheader_encrypt.bin.signed +> +> # Record the sha1sum +> sha1sum uefi_jetson_with_dtb_aligned_blob_w_bin_sigheader_encrypt.bin.signed +> +> # Edit the A/B_cpu-bootloader with PV signed/encrypted file size and sha1Sum +> sudo vim flash.idx +> +> # Untar EKB_final_db received from ODM (i.e., eks_0021-0000001000218000-2.tar) +> sudo mkdir ekb_db +> cd ekb_db +> sudo tar xf ${OEM_BSP_TOP}/eks_0021-0000001000218000-2.tar +> +> # Package the factory tarball +> cd ${BSP_TOP}/Linux_for_Tegra +> sudo tar zvcf factory.tar.gz \ +> tools/kernel_flash/initrdflashparam.txt \ +> tools/kernel_flash/initrdflashimgmap.txt \ +> tools/kernel_flash/images/ +> ~~~ +> - Send the "factory.tar.gz" to the factory. + +# The Factory Workflow + +> [!Note] The Factory Preparation Work +> 1. [Jetson BSP Installation](#jetson-bsp-installation) + +## Fuse Burning + +> [!Note] Fuse burning +> 1. Receiving the OEM and ODM fuseblob from the OEM. +> ~~~ +> cd ${BSP_TOP}/Linux_for_Tegra +> cp fuseblob_oem_out.tar l4t/tools/flashtools/fuseburn/ +> cp fuseblob_odm_out_0021-0000001000218000-2.tar l4t/tools/flashtools/fuseburn/ +> cd l4t/tools/flashtools/fuseburn +> tar xf fuseblob_oem_out.tar +> tar xf fuseblob_odm_out_0021-0000001000218000-2.tar +> ~~~ +> +> > [!Caution] +> > - Burn the OEM fuseblob first, then burn the ODM fuseblob. +> > - There are two examples here, fusing the fuses to each target one by one or fusing fuses to multiple targets in one command. Please choose one of them to apply. +> +> 2. Fusing the fuses to each target. +> - Fusing the OEM fuses to each target. +> ~~~ +> sudo ./fskp_fuseburn.py -c 0x23 \ +> -P fuseblob/oem_out/ \ +> --board-spec orin-agx-board-spec.txt \ +> -B ../../../../jetson-agx-orin-devkit.conf +> ~~~ +> - The command above burns the OEM fuses on device 1. +> - Repeating the same command on device 2. +> - Fusing the ODM fuses to each target. +> ~~~ +> sudo ./fskp_fuseburn.py -c 0x23 \ +> -P fuseblob/odm_out_0021-0000001000218000/ \ +> --board-spec orin-agx-board-spec.txt \ +> -B ../../../../jetson-agx-orin-devkit.conf +> # The command above burns the ODM fuses on device 1. +> +> sudo ./fskp_fuseburn.py -c 0x23 \ +> -P fuseblob/odm_out_0021-0000001000218001/ \ +> --board-spec orin-agx-board-spec.txt \ +> -B ../../../../jetson-agx-orin-devkit.conf +> # The command above burns the ODM fuses on device 2. +> ~~~ +> +> 3. Fusing the fuses to multiple targets in one command. +> - Note: You need to make sure all the devices are connected to the same host and are in recovery mode. +> - Fusing the OEM fuses to multiple targets in one command. +> ~~~ +> sudo ./fskp_massfuseburn.py --skipconfirmation \ +> --burnfuse \ +> --board-spec orin-agx-board-spec.txt \ +> -P fuseblob/oem_out \ +> -c 0x23 \ +> -B ../../../../jetson-agx-orin-devkit.conf +> ~~~ +> - Fusing the ODM fuses to multiple targets in one command. +> ~~~ +> sudo ./fskp_multiblobfuse.py --out fuseblob/odm_out \ +> --oem_id 0x0021 \ +> --sn 0x0000001000218000 \ +> --num_devices 2 \ +> --board-spec orin-agx-board-spec.txt \ +> -B ../../../../jetson-agx-orin-devkit.conf +> ~~~ + +## Flashing Images + +> [!Note] Flashing Images +> ~~~ +> cd ${BSP_TOP}/Linux_for_Tegra +> sudo tar zvxf factory.tar.gz +> cp tools/kernel_flash/images/rcmboot/* bootloader/ +> ~~~ +> - AGX Orin with eMMC as the RootFS storage +> ~~~ +> sudo ./tools/kernel_flash/l4t_initrd_flash.sh \ +> --flash-only \ +> --showlogs \ +> --network usb0 \ +> --ekb-pair \ +> jetson-agx-orin-devkit \ +> internal +> ~~~ +> - AGX Orin with NVMe as the RootFS storage +> ~~~ +> sudo ./tools/kernel_flash/l4t_initrd_flash.sh \ +> --flash-only \ +> --showlogs \ +> --network usb0 \ +> --ekb-pair \ +> jetson-agx-orin-devkit \ +> nvme0n1p1 +> ~~~ +> - Orin Nano with NVMe as the RootFS storage +> ~~~ +> sudo ./tools/kernel_flash/l4t_initrd_flash.sh \ +> --flash-only \ +> --showlogs \ +> --network usb0 \ +> --ekb-pair \ +> jetson-orin-nano-devkit \ +> nvme0n1p1 +> ~~~ + +Appendix B: Handle The fTPM Manufacturing Flow In One Entity +------------------------------------------------------------ + +# The Following Steps Work For An Entity That Behaves As both ODM and OEM + +## The Preparation Work + +> [!Note] The Preparation Work +> 1. [Jetson BSP Installation](#jetson-bsp-installation) +> 2. [Rebuild and Update the TOS Image for fTPM Support (Optional)](#rebuilding-and-updating-the-tos-image-for-ftpm-support). +> 3. Assume that the ODM's own keys are stored at: +> ~~~ +> ~/odm_keys/rsa3k.pem +> ~/odm_keys/sbk-32.key +> ~~~ +> 4. Assume that the ODM's fskp fusing files are stored at: +> ~~~ +> ~/odm_fskp/odm_fuse_template.xml +> ~/odm_fskp/fskp_ak.bin +> ~/odm_fskp/fskp_ek.bin +> ~/odm_fskp/fskp_conf.txt +> ~~~ +> 5. Assume that the ODM's user defined keys (for EKB generation) are stored at: +> ~~~ +> ~/oem_keys/oem_k1.key +> ~/oem_keys/sym_t234.key +> ~/oem_keys/sym2_t234.key +> ~/oem_keys/auth_t234.key +> ~~~ +> 6. Assume that the OEM's UEFI keys (for UEFI payloads such as kernel/kernel-dtb signing and encryuption) are store at: +> ~~~ +> ~/oem_keys/uefi_keys/uefi_keys.conf +> ~/oem_keys/uefi_keys/uefi_enc.key +> ~~~ +> 7. Assume that the OEM's fuse template are stored at: +> ~~~ +> ~/oem_keys/oem_fuse_template.xml +> ~~~ + +## EKB Generation + +> [!Note] EKB Generation +> 1. Generate the EKB DB with KDK-based EK certificates. +> ~~~ +> cd ${BSP_TOP}/Linux_for_Tegra/source/optee/samples/ftpm-helper/host/tool +> ./kdk_gen.py --oem_id 0x21 --sn 0x1000218000 --num_devices 2 +> ./odm_ekb_gen.py --kdk_db ftpm_kdk/kdk_db_0021-0000001000218000-2.csv +> ~~~ +> 2. Add user keys to EKB. +> ~~~ +> cp ../../../hwkey-agent/host/tool/gen_ekb/gen_ekb.py ./ +> ./oem_ekb_gen.py -oem_k1_key ~/oem_keys/oem_k1.key \ +> -in_sym_key ~/oem_keys/sym_t234.key \ +> -in_sym_key2 ~/oem_keys/sym2_t234.key \ +> -in_auth_key ~/oem_keys/auth_t234.key \ +> -in_ftpm_odm_ekb odm_out +> # The outputs from the above command are stored at the oem_out folder. +> cp -r oem_out/ ${BSP_TOP} +> ~~~ +> - oem_k1.key: "OemK1" value in the OEM fuse template xml +> - sym_t234.key: UEFI payloads (such as kernel, kernel-dtb) encryption key +> - sym2_t234.key: disk encryption key +> - auth_t234.key: UEFI variables authentication key +> 3. Signing and generating the final ekb_db. +> ~~~ +> cd ${BSP_TOP}/Linux_for_Tegra +> ./l4t_sign_image.sh --chip 0x23 \ +> --key ~/odm_keys/rsa3k.pem \ +> --encrypt_key ~/odm_keys/sbk-32.key \ +> --mass-ekb ${BSP_TOP}/oem_out \ +> --type data \ +> --split False +> ~~~ +> - The encrypted/signed final ekb_db images are stored at the "{BSP_TOP}/oem_out/signed" folder. + +## Fuseblob Generation + +> [!Note] Fuseblob Generation +> - To create a new fuse template, merge the contents of `odm_fuse_template.xml` and `oem_fuse_template.xml`, naming the resulting file as `odem_fuse_template.xml`. +> - Please note that when merging these templates, place the content from `oem_fust_template.xml` before that of `odm_fuse_template.xml`. +> - This ensures that the fuse named "SecurityMode" remains the last entry in the merged template. +> ~~~ +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> ~~~ +> ~~~ +> cd ${BSP_TOP}/Linux_for_Tegra +> cd l4t/tools/flashtools/fuseburn/ +> sudo ./fskp_fuseburn.py -f ~/odm_fskp/odem_fuse_template.xml \ +> --multi-blob ${BSP_TOP}/Linux_for_Tegra/source/optee/samples/ftpm-helper/host/tool/ftpm_kdk/kdk_db_0021-0000001000218000-2.csv +> --test \ +> -i 63 \ +> --key-exp ~/odm_fskp/fskp_ak.bin ~/odm_fskp/fskp_ek.bin \ +> --fskpcfg ~/odm_fskp/fskp_conf.txt \ +> -g fuseblob/odm_out \ +> -c 0x23 \ +> --board-spec orin-agx-board-spec.txt \ +> -B ../../../../jetson-agx-orin-devkit.conf +> # The outputs generated by the above command are stored at the "fuseblob/odm_out" folder. +> tar cf fuseblob_odm_out_0021-0000001000218000-2.tar fuseblob/ +> ~~~ +> - Note: The parameters used in this command are for reference only. They should be replaced with the user's specific fskp keys and board. +> - Note: The "--test" option indicates the generated fuse blob will only do a dry run. To actually burn the fuses, replace --test with --burnfuse. +> - Sending "fuseblob_odm_out_0021-0000001000218000-2.tar" to the FACTORY. +> - Please follow the Fusing the ODM Fuses of the [Fuse Burning](#fuse-burning) process in Appendix A. + +## Flash Image Generation +- Followings are example commands to generate flash images (LBC + UPI) for different target configurations: + - AGX Orin with eMMC as rootfs + - AGX Orin with NVMe as rootfs + - Orin Nano with NVMe as rootfs + +> [!Note] +> 1. Unlike ODM and OEM are separate entities where the UEFI image generated by ODM is only a placeholder. Here, the UEFI image generated by the LBC generating command (with --odm-image-gen option) is the final UEFI image. In order to enable UEFI Secureboot feature at flashing time, option --uefi-keys must be provided in the command line so that all keys required by UEFI can be built in along with the UEFI image. +> 2. The UEFI image is encrypted and signed by the sbk key (-v option) and pkc key (-u option). +> 3. In the commands to generate upi_oem.tar.gz, the key in --uefi-enc option is used for UEFI payload encryption. This key value is the sym_t234.key used in the EKB generation. +> 4. Enable UEFI secure boot feature: +> ~~~ +> cd ${BSP_TOP}/Linux_for_Tegra +> sudo ./tools/gen_uefi_default_keys_dts.sh ~/oem_keys/uefi_keys/uefi_keys.conf +> ~~~ + +> [!Note] AGX Orin with eMMC as the RootFS storage +> - QSPI image generation (aka lower boot components: lbc) +> ~~~ +> cd ${BSP_TOP}/Linux_for_Tegra +> sudo rm -rf tools/kernel_flash/images/ +> sudo BOARDID= FAB= BOARDSKU= CHIP_SKU= RAMCODE_ID= \ +> ./tools/kernel_flash/l4t_initrd_flash.sh \ +> --odm-image-gen \ +> --showlogs \ +> --network usb0 \ +> --no-flash \ +> -u ~/odm_keys/rsa3k.pem \ +> -v ~/odm_keys/sbk-32.key \ +> --uefi-keys ~/oem_keys/uefi_keys/uefi_keys.conf \ +> -p "-c bootloader/generic/cfg/flash_t234_qspi.xml" \ +> jetson-agx-orin-devkit \ +> internal +> ~~~ +> - UPI image generation (aka User Partition Image: UPI) +> ~~~ +> sudo BOARDID= FAB= BOARDSKU= CHIP_SKU= RAMCODE_ID= \ +> ./tools/kernel_flash/l4t_initrd_flash.sh \ +> --mass-storage-only \ +> --showlogs \ +> --network usb0 \ +> --no-flash \ +> --uefi-keys ~/oem_keys/uefi_keys/uefi_keys.conf \ +> --uefi-enc ~/oem_keys/uefi_keys/uefi_enc.key \ +> jetson-agx-orin-devkit \ +> internal +> ~~~ +> - The output from the above commands are "lbc_odm.tar.gz" and "upi_oem.tar.gz". + +> [!Note] AGX Orin with NVMe as the RootFS storage +> - QSPI image generation (aka lower boot components: lbc) +> ~~~ +> cd ${BSP_TOP}/Linux_for_Tegra +> sudo rm -rf tools/kernel_flash/images/ +> sudo BOARDID= FAB= BOARDSKU= CHIP_SKU= RAMCODE_ID= \ +> ./tools/kernel_flash/l4t_initrd_flash.sh \ +> --odm-image-gen \ +> --showlogs \ +> --network usb0 \ +> --no-flash \ +> -u ~/odm_keys/rsa3k.pem \ +> -v ~/odm_keys/sbk-32.key \ +> --uefi-keys ~/oem_keys/uefi_keys/uefi_keys.conf \ +> -p "-c bootloader/generic/cfg/flash_t234_qspi.xml" \ +> jetson-agx-orin-devkit \ +> internal +> ~~~ +> - UPI image generation (aka User Partition Image: UPI) +> ~~~ +> sudo BOARDID= FAB= BOARDSKU= CHIP_SKU= RAMCODE_ID= \ +> ./tools/kernel_flash/l4t_initrd_flash.sh \ +> --mass-storage-only \ +> --showlogs \ +> --network usb0 \ +> --no-flash \ +> --external-device nvme0n1p1 \ +> --external-only \ +> -c ./tools/kernel_flash/flash_l4t_t234_nvme.xml \ +> --uefi-keys ~/oem_keys/uefi_keys/uefi_keys.conf \ +> --uefi-enc ~/oem_keys/uefi_keys/uefi_enc.key \ +> jetson-agx-orin-devkit \ +> nvme0n1p1 +> ~~~ +> - The output from the above commands are "lbc_odm.tar.gz" and "upi_oem.tar.gz". + +> [!Note] Orin Nano with NVMe as the RootFS storage +> - QSPI image generation (aka lower boot components: lbc) +> ~~~ +> cd ${BSP_TOP}/Linux_for_Tegra +> sudo rm -rf tools/kernel_flash/images/ +> sudo BOARDID= FAB= BOARDSKU= CHIP_SKU= RAMCODE_ID= \ +> ./tools/kernel_flash/l4t_initrd_flash.sh \ +> --odm-image-gen \ +> --showlogs \ +> --network usb0 \ +> --no-flash \ +> -u ~/odm_keys/rsa3k.pem \ +> -v ~/odm_keys/sbk-32.key \ +> --uefi-keys ~/oem_keys/uefi_keys/uefi_keys.conf \ +> -p "-c bootloader/generic/cfg/flash_t234_qspi.xml" \ +> jetson-orin-nano-devkit \ +> internal +> ~~~ +> - UPI image generation (aka User Partition Image: UPI) +> ~~~ +> sudo BOARDID= FAB= BOARDSKU= CHIP_SKU= RAMCODE_ID= \ +> ./tools/kernel_flash/l4t_initrd_flash.sh \ +> --mass-storage-only \ +> --showlogs \ +> --network usb0 \ +> --no-flash \ +> --external-device nvme0n1p1 \ +> --external-only \ +> -c ./tools/kernel_flash/flash_l4t_t234_nvme.xml \ +> --uefi-keys ~/oem_keys/uefi_keys/uefi_keys.conf \ +> --uefi-enc ~/oem_keys/uefi_keys/uefi_enc.key \ +> jetson-orin-nano-devkit \ +> nvme0n1p1 +> ~~~ +> - The output from the above commands are "lbc_odm.tar.gz" and "upi_oem.tar.gz". + +## Factory tarball Generation + +> [!Note] Final Factory tarball Generation +> ~~~ +> cd ${BSP_TOP}/Linux_for_Tegra +> +> sudo tar zvxf lbc_odm.tar.gz +> +> sudo tar zvxf upi_oem.tar.gz +> +> sudo mkdir -p tools/kernel_flash/images/internal/ekb_db +> +> sudo cp ${BSP_TOP}/oem_out/signed/* tools/kernel_flash/images/internal/ekb_db +> +> sudo tar zvcf factory.tar.gz \ +> tools/kernel_flash/initrdflashparam.txt \ +> tools/kernel_flash/initrdflashimgmap.txt \ +> tools/kernel_flash/images/ +> ~~~ +> - Sending the factory.tar.gz to FACTORY. +> - Please follow the [Flashing Images](#flashing-images) process in Appendix A. diff --git a/optee/samples/ftpm-helper/host/Makefile b/optee/samples/ftpm-helper/host/Makefile new file mode 100644 index 0000000..33ca6da --- /dev/null +++ b/optee/samples/ftpm-helper/host/Makefile @@ -0,0 +1,39 @@ +# Copyright (c) 2023-2024, 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 +STRIP ?= $(CROSS_COMPILE)strip + +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 = ftpm_helper_ca.c +OBJS = $(patsubst %.c,$(O)/%.o,$(SRCS)) +BINARY = nvftpm-helper-app + +.PHONY: all install +all: $(BINARY) install + +$(BINARY): $(OBJS) + $(CC) -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/ftpm-helper/host/ftpm_helper_ca.c b/optee/samples/ftpm-helper/host/ftpm_helper_ca.c new file mode 100644 index 0000000..1395527 --- /dev/null +++ b/optee/samples/ftpm-helper/host/ftpm_helper_ca.c @@ -0,0 +1,716 @@ +/* + * Copyright (c) 2023-2024, 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 FTPM_HELPER_GET_RSA_EK_CERT (1 << 0) +#define FTPM_HELPER_GET_EC_EK_CERT (1 << 1) +#define FTPM_HELPER_GET_SILICON_ID_CERT (1 << 2) +#define FTPM_HELPER_GET_FIRMWARE_ID_CERT (1 << 3) +#define FTPM_HELPER_GET_RSA_EK_CSR (1 << 4) +#define FTPM_HELPER_GET_EC_EK_CSR (1 << 5) +#define FTPM_HELPER_QUERY_ECID (1 << 6) +#define FTPM_HELPER_QUERY_SN (1 << 7) +#define FTPM_HELPER_QUERY_PROV_MODE (1 << 8) +#define FTPM_HELPER_QUERY_VERSION (1 << 9) +#define FTPM_HELPER_SIGN_EK_CSR (1 << 10) +#define FTPM_HELPER_RET_SIGNED_EK_CSR (1 << 11) +#define FTPM_HELPER_INJECT_EPS (1 << 12) + +#define INVALID_OPT_FOR_OFFLINE_PROV_MODE (FTPM_HELPER_GET_SILICON_ID_CERT | \ + FTPM_HELPER_GET_RSA_EK_CSR | \ + FTPM_HELPER_GET_EC_EK_CSR | \ + FTPM_HELPER_SIGN_EK_CSR | \ + FTPM_HELPER_RET_SIGNED_EK_CSR) +#define INVALID_OPT_FOR_ONLINE_PROV_MODE (FTPM_HELPER_GET_RSA_EK_CERT | \ + FTPM_HELPER_GET_EC_EK_CERT) + +static struct argp_option options[] = { + {0, 'a', "OUTFILE", 0, "Output file of the fTPM RSA EK Certificate (Offline Provision Mode)."}, + {0, 'b', "OUTFILE", 0, "Output file of the fTPM EC EK Certificate (Offline Provision Mode)."}, + {0, 'c', "OUTFILE", 0, "Output file of the Silicon ID Certificate (Online Provision Mode)."}, + {0, 'd', "OUTFILE", 0, "Output file of the Firmware ID Certificate"}, + {0, 'e', "OUTFILE", 0, "Output file of the fTPM RSA EK CSR (Online Provision Mode)."}, + {0, 'f', "OUTFILE", 0, "Output file of the fTPM EC EK CSR (Online Provision Mode)."}, + {0, 'g', NULL, 0, "Query the device ECID value"}, + {0, 'h', NULL, 0, "Query the device serial number."}, + {0, 'i', NULL, 0, "Query the provisioning mode."}, + {0, 'j', NULL, 0, "Query the version."}, + {0, 'k', "INFILE", 0, "Sign the EK CSR (Online Provision Mode)."}, + {0, 'l', "OUTFILE", 0, "Output of the signed EK CSR file (Online Provision Mode)."}, + {0, 'm', "EPS", 0, "Inject an EPS(starts with \"0x\", 64 bytes, big endian) into fTPM."}, + { 0 }, +}; + +struct arguments { + uint32_t ftpm_helper_options; + char *out_rsa_ek_cert; + char *out_ec_ek_cert; + char *out_sid_cert; + char *out_fw_id_cert; + char *out_rsa_ek_csr; + char *out_ec_ek_csr; + char *in_sign_ek_csr; + char *out_signed_ek_csr; + char *inject_eps_value; +}; + +typedef struct ftpm_helper_ca_ctx { + TEEC_Context ctx; + TEEC_Session sess; + struct arguments *argus; + FILE *fd_out_rsa_ek_cert; + FILE *fd_out_ec_ek_cert; + FILE *fd_out_sid_cert; + FILE *fd_out_fw_id_cert; + FILE *fd_out_rsa_ek_csr; + FILE *fd_out_ec_ek_csr; + FILE *fd_in_ek_csr; + FILE *fd_out_signed_ek_csr; + uint32_t prov_mode; + uint32_t ver_major; + uint32_t ver_minor; +} ftpm_helper_ca_ctx_t; +static ftpm_helper_ca_ctx_t ca_sess; + +static error_t parse_opt(int key, char *arg, struct argp_state *state) +{ + struct arguments *argus = state->input; + + switch (key) { + case 'a': + argus->ftpm_helper_options |= FTPM_HELPER_GET_RSA_EK_CERT; + if (arg) + argus->out_rsa_ek_cert = arg; + break; + case 'b': + argus->ftpm_helper_options |= FTPM_HELPER_GET_EC_EK_CERT; + if (arg) + argus->out_ec_ek_cert = arg; + break; + case 'c': + argus->ftpm_helper_options |= FTPM_HELPER_GET_SILICON_ID_CERT; + if (arg) + argus->out_sid_cert = arg; + break; + case 'd': + argus->ftpm_helper_options |= FTPM_HELPER_GET_FIRMWARE_ID_CERT; + if (arg) + argus->out_fw_id_cert = arg; + break; + case 'e': + argus->ftpm_helper_options |= FTPM_HELPER_GET_RSA_EK_CSR; + if (arg) + argus->out_rsa_ek_csr = arg; + break; + case 'f': + argus->ftpm_helper_options |= FTPM_HELPER_GET_EC_EK_CSR; + if (arg) + argus->out_ec_ek_csr = arg; + break; + case 'g': + argus->ftpm_helper_options |= FTPM_HELPER_QUERY_ECID; + break; + case 'h': + argus->ftpm_helper_options |= FTPM_HELPER_QUERY_SN; + break; + case 'i': + argus->ftpm_helper_options |= FTPM_HELPER_QUERY_PROV_MODE; + break; + case 'j': + argus->ftpm_helper_options |= FTPM_HELPER_QUERY_VERSION; + break; + case 'k': + argus->ftpm_helper_options |= FTPM_HELPER_SIGN_EK_CSR; + if (arg) + argus->in_sign_ek_csr = arg; + break; + case 'l': + argus->ftpm_helper_options |= FTPM_HELPER_RET_SIGNED_EK_CSR; + if (arg) + argus->out_signed_ek_csr = arg; + break; + case 'm': + argus->ftpm_helper_options |= FTPM_HELPER_INJECT_EPS; + if (arg) + argus->inject_eps_value = arg; + break; + case ARGP_KEY_END: + if (argus->ftpm_helper_options == 0) + argp_usage(state); + break; + case ARGP_KEY_ARG: + if (state->argc <= 1) + argp_usage(state); + default: + return ARGP_ERR_UNKNOWN; + } + return 0; +} + +static struct argp argp = { options, parse_opt, NULL, 0, 0, 0, 0 }; + +static TEEC_Result prepare_tee_session(ftpm_helper_ca_ctx_t *ctx) +{ + TEEC_UUID uuid = FTPM_HELPER_TA_UUID; + uint32_t origin; + TEEC_Result rc; + + rc = TEEC_InitializeContext(NULL, &ctx->ctx); + if (TEEC_SUCCESS != rc) + goto tee_session_fail; + + rc = TEEC_OpenSession(&ctx->ctx, &ctx->sess, &uuid, + TEEC_LOGIN_PUBLIC, NULL, NULL, &origin); + + if (TEEC_SUCCESS != rc) + TEEC_FinalizeContext(&ctx->ctx); + +tee_session_fail: + return rc; +} + +static void terminate_tee_session(ftpm_helper_ca_ctx_t *ctx) +{ + struct arguments *argus = ctx->argus; + + TEEC_CloseSession(&ctx->sess); + TEEC_FinalizeContext(&ctx->ctx); + + if (FTPM_HELPER_GET_RSA_EK_CERT & argus->ftpm_helper_options) { + if (NULL != ctx->fd_out_rsa_ek_cert) + fclose(ctx->fd_out_rsa_ek_cert); + } + + if (FTPM_HELPER_GET_EC_EK_CERT & argus->ftpm_helper_options) { + if (NULL != ctx->fd_out_ec_ek_cert) + fclose(ctx->fd_out_ec_ek_cert); + } + + if (FTPM_HELPER_GET_SILICON_ID_CERT & argus->ftpm_helper_options) { + if (NULL != ctx->fd_out_sid_cert) + fclose(ctx->fd_out_sid_cert); + } + + if (FTPM_HELPER_GET_FIRMWARE_ID_CERT & argus->ftpm_helper_options) { + if (NULL != ctx->fd_out_fw_id_cert) + fclose(ctx->fd_out_fw_id_cert); + } + + if (FTPM_HELPER_GET_RSA_EK_CSR & argus->ftpm_helper_options) { + if (NULL != ctx->fd_out_rsa_ek_csr) + fclose(ctx->fd_out_rsa_ek_csr); + } + + if (FTPM_HELPER_GET_EC_EK_CSR & argus->ftpm_helper_options) { + if (NULL != ctx->fd_in_ek_csr) + fclose(ctx->fd_in_ek_csr); + } + + if (FTPM_HELPER_SIGN_EK_CSR & argus->ftpm_helper_options) { + if (NULL != ctx->fd_out_signed_ek_csr) + fclose(ctx->fd_out_signed_ek_csr); + } +} + +static void fail_handler(int i) +{ + terminate_tee_session(&ca_sess); + + exit(i); +} + +static int get_file_size(FILE *fptr) +{ + size_t file_len; + + fseek(fptr, 0, SEEK_END); + file_len = ftell(fptr); + rewind(fptr); + + return file_len; +} + +static void ca_query_prov_mode(void) +{ + TEEC_Operation op; + TEEC_Result rc; + uint32_t cmd, origin; + + memset(&op, 0, sizeof(op)); + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, + TEEC_VALUE_OUTPUT, + TEEC_VALUE_OUTPUT, + TEEC_NONE); + cmd = FTPM_HELPER_TA_CMD_QUERY_PROV_MODE; + + /* Send command to TA. */ + rc = TEEC_InvokeCommand(&ca_sess.sess, cmd, &op, &origin); + if (rc != TEEC_SUCCESS) { + fprintf(stderr, "%s: TEEC_InvokeCommand failed 0x%x origin 0x%x\n", + __func__, rc, origin); + return; + } + + if (op.params[0].value.a == FTPM_PROV_MODE_OFFLINE || + op.params[0].value.a == FTPM_PROV_MODE_ONLINE) + ca_sess.prov_mode = op.params[0].value.a; + + ca_sess.ver_major = op.params[1].value.a; + ca_sess.ver_minor = op.params[2].value.a; +} + +static void ca_query_ecid(void) +{ + TEEC_Operation op; + TEEC_Result rc; + uint8_t *ecid_buf = NULL; + uint32_t cmd, origin; + + ecid_buf = calloc(1, FTPM_HELPER_TA_ECID_LENGTH); + if (!ecid_buf) { + fprintf(stderr, "%s: out of memory.\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 = ecid_buf; + op.params[0].tmpref.size = FTPM_HELPER_TA_ECID_LENGTH; + cmd = FTPM_HELPER_TA_CMD_QUERY_ECID; + + /* Send command to TA. */ + rc = TEEC_InvokeCommand(&ca_sess.sess, cmd, &op, &origin); + if (rc != TEEC_SUCCESS) { + fprintf(stderr, "%s: TEEC_InvokeCommand failed 0x%x origin 0x%x\n", + __func__, rc, origin); + goto out; + } + + fprintf(stdout, "%16lx", *(uint64_t*)&ecid_buf[0]); + fprintf(stdout, "\n"); + +out: + free(ecid_buf); +} + +static void ca_query_sn(void) +{ + TEEC_Operation op; + TEEC_Result rc; + uint8_t *sn_buf = NULL; + uint32_t cmd, origin; + int i = 0; + + sn_buf = calloc(1, FTPM_HELPER_TA_SN_LENGTH); + if (!sn_buf) { + fprintf(stderr, "%s: out of memory.\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 = sn_buf; + op.params[0].tmpref.size = FTPM_HELPER_TA_SN_LENGTH; + cmd = FTPM_HELPER_TA_CMD_QUERY_SN; + + /* Send command to TA. */ + rc = TEEC_InvokeCommand(&ca_sess.sess, cmd, &op, &origin); + if (rc != TEEC_SUCCESS) { + fprintf(stderr, "%s: TEEC_InvokeCommand failed 0x%x origin 0x%x\n", + __func__, rc, origin); + goto out; + } + + for (i = 0; i < FTPM_HELPER_TA_SN_LENGTH; i++) + fprintf(stdout, "%02x", sn_buf[i]); + fprintf(stdout, "\n"); + +out: + free(sn_buf); +} + +static TEEC_Result ca_query_ftpm_prop(uint32_t ta_cmd, + uint32_t buf_size, + FILE *out_fptr) +{ + TEEC_Operation op; + TEEC_Result rc; + uint8_t *buf = NULL; + uint32_t cmd, origin; + + if (!out_fptr) { + fprintf(stderr, "%s: invalid file ptr.\n", __func__); + return TEEC_ERROR_BAD_PARAMETERS; + } + + buf = calloc(1, buf_size); + if (!buf) { + fprintf(stderr, "%s: out of memory.\n", __func__); + return TEEC_ERROR_OUT_OF_MEMORY; + } + + 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 = buf; + op.params[0].tmpref.size = buf_size; + cmd = ta_cmd; + + /* Send command to TA. */ + rc = TEEC_InvokeCommand(&ca_sess.sess, cmd, &op, &origin); + if (rc != TEEC_SUCCESS) { + fprintf(stderr, "%s: TEEC_InvokeCommand failed 0x%x origin 0x%x\n", + __func__, rc, origin); + goto out; + } + + /* Store the property. */ + if (op.params[0].tmpref.size > 0) + fwrite(buf, op.params[0].tmpref.size, 1, out_fptr); + +out: + free(buf); + + return rc; +} + +static void ca_sign_ek_csr(FILE *in_csr_fptr, FILE *out_csr_fptr) +{ + TEEC_Operation op; + TEEC_Result rc; + uint8_t *csr_buf = NULL; + uint32_t csr_file_len; + uint32_t cmd, origin; + int f_rc; + + if (!in_csr_fptr || !out_csr_fptr) { + fprintf(stderr, "%s: invalid file ptr.\n", __func__); + return; + } + + /* Check the csr file size. */ + csr_file_len = get_file_size(in_csr_fptr); + if (csr_file_len > FTPM_EK_CSR_BUF_SIZE) { + fprintf(stderr, "%s: invalid temp EK CSR file size.\n", __func__); + return; + } + + csr_buf = calloc(1, FTPM_EK_CSR_BUF_SIZE); + if (!csr_buf) { + fprintf(stderr, "%s: out of memory.\n", __func__); + return; + } + + f_rc = fread(csr_buf, 1, csr_file_len, in_csr_fptr); + if (f_rc < 0) { + fprintf(stderr, "%s: fail to read the CSR file.\n", __func__); + goto out; + } + + memset(&op, 0, sizeof(op)); + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INOUT, + TEEC_NONE, + TEEC_NONE, + TEEC_NONE); + op.params[0].tmpref.buffer = csr_buf; + op.params[0].tmpref.size = csr_file_len; + cmd = FTPM_HELPER_TA_CMD_SIGN_EK_CSR; + + /* Send command to TA. */ + rc = TEEC_InvokeCommand(&ca_sess.sess, cmd, &op, &origin); + if (rc != TEEC_SUCCESS) { + fprintf(stderr, "%s: TEEC_InvokeCommand failed 0x%x origin 0x%x\n", + __func__, rc, origin); + goto out; + } + + /* Store the updated EK CSR. */ + if (op.params[0].tmpref.size > 0) + fwrite(csr_buf, op.params[0].tmpref.size, 1, out_csr_fptr); + +out: + free(csr_buf); +} + +static TEEC_Result ca_inject_eps(uint8_t *eps, int eps_len) +{ + TEEC_Operation op; + TEEC_Result rc = TEEC_SUCCESS; + uint32_t cmd, origin; + + if (eps == NULL || eps_len != FTPM_HELPER_TA_EPS_BYTES) + return TEEC_ERROR_BAD_PARAMETERS; + + memset(&op, 0, sizeof(op)); + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_NONE, + TEEC_NONE, + TEEC_NONE); + op.params[0].tmpref.buffer = eps; + op.params[0].tmpref.size = eps_len; + cmd = FTPM_HELPER_TA_CMD_INJECT_EPS; + + /* Send command to TA. */ + rc = TEEC_InvokeCommand(&ca_sess.sess, cmd, &op, &origin); + if (rc != TEEC_SUCCESS) { + fprintf(stderr, "%s: TEEC_InvokeCommand failed 0x%x origin 0x%x\n", + __func__, rc, origin); + goto out; + } + +out: + return rc; +} + +static int hex_char_to_nibble(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 TEEC_ERROR_BAD_PARAMETERS; +} + +static TEEC_Result parse_eps_value(const char *input, uint8_t *eps, int eps_len) +{ + int i, j; + int high, low; + int eps_string_len = FTPM_HELPER_TA_EPS_BYTES * 2 + 2; + + if (input == NULL || eps == NULL || eps_len != FTPM_HELPER_TA_EPS_BYTES) { + fprintf(stderr, "Invalid EPS parameters or length.\n"); + return TEEC_ERROR_BAD_PARAMETERS; + } + + if (strlen(input) != eps_string_len) { + fprintf(stderr, "Invalid length of the EPS string. The length must be %d\n", eps_string_len); + return TEEC_ERROR_BAD_PARAMETERS; + } + + if (input[0] != '0' || (input[1] != 'x' && input[1] != 'X')) { + fprintf(stderr, "The EPS value must start with \'0x\'.\n"); + return TEEC_ERROR_BAD_PARAMETERS; + } + + memset(eps, 0, eps_len); + for (i = 2, j = 0; i < (eps_len * 2 + 2) && j < eps_len; i += 2, j++) { + high = hex_char_to_nibble(input[i]); + low = hex_char_to_nibble(input[i + 1]); + + if (high == TEEC_ERROR_BAD_PARAMETERS || low == TEEC_ERROR_BAD_PARAMETERS) { + fprintf(stderr, "Invalid EPS hex string.\n"); + return TEEC_ERROR_BAD_PARAMETERS; + } + + eps[j] = (high << 4) | low; + } + + return TEEC_SUCCESS; +} + +void handle_ftpm_helper_options(ftpm_helper_ca_ctx_t *ctx) +{ + struct arguments *argus = ctx->argus; + TEEC_Result rc = TEEC_SUCCESS; + uint8_t eps[FTPM_HELPER_TA_EPS_BYTES]; + + if (FTPM_HELPER_GET_RSA_EK_CERT & argus->ftpm_helper_options) { + if (!argus->out_rsa_ek_cert) { + fprintf(stderr, "Error: missing -a option.\n"); + fail_handler(1); + } + + ctx->fd_out_rsa_ek_cert = fopen(argus->out_rsa_ek_cert, "wb"); + rc = ca_query_ftpm_prop(FTPM_HELPER_TA_CMD_GET_RSA_EK_CERT, + FTPM_EK_CERT_BUF_SIZE, + ctx->fd_out_rsa_ek_cert); + if (rc != TEEC_SUCCESS) + fail_handler(1); + } + + if (FTPM_HELPER_GET_EC_EK_CERT & argus->ftpm_helper_options) { + if (!argus->out_ec_ek_cert) { + fprintf(stderr, "Error: missing -b option.\n"); + fail_handler(1); + } + + ctx->fd_out_ec_ek_cert = fopen(argus->out_ec_ek_cert, "wb"); + rc = ca_query_ftpm_prop(FTPM_HELPER_TA_CMD_GET_EC_EK_CERT, + FTPM_EK_CERT_BUF_SIZE, + ctx->fd_out_ec_ek_cert); + if (rc != TEEC_SUCCESS) + fail_handler(1); + } + + if (FTPM_HELPER_GET_SILICON_ID_CERT & argus->ftpm_helper_options) { + if (!argus->out_sid_cert) { + fprintf(stderr, "Error: missing -c option.\n"); + fail_handler(1); + } + + ctx->fd_out_sid_cert = fopen(argus->out_sid_cert, "wb"); + rc = ca_query_ftpm_prop(FTPM_HELPER_TA_CMD_GET_SID_CERT, + FTPM_EK_CERT_BUF_SIZE, + ctx->fd_out_sid_cert); + if (rc != TEEC_SUCCESS) + fail_handler(1); + } + + if (FTPM_HELPER_GET_FIRMWARE_ID_CERT & argus->ftpm_helper_options) { + if (!argus->out_fw_id_cert) { + fprintf(stderr, "Error: missing -d option.\n"); + fail_handler(1); + } + + ctx->fd_out_fw_id_cert = fopen(argus->out_fw_id_cert, "wb"); + rc = ca_query_ftpm_prop(FTPM_HELPER_TA_CMD_GET_FW_ID_CERT, + FTPM_EK_CERT_BUF_SIZE, + ctx->fd_out_fw_id_cert); + if (rc != TEEC_SUCCESS) + fail_handler(1); + } + + if (FTPM_HELPER_GET_RSA_EK_CSR & argus->ftpm_helper_options) { + if (!argus->out_rsa_ek_csr) { + fprintf(stderr, "Error: missing -e option.\n"); + fail_handler(1); + } + + ctx->fd_out_rsa_ek_csr = fopen(argus->out_rsa_ek_csr, "wb"); + rc = ca_query_ftpm_prop(FTPM_HELPER_TA_CMD_GET_RSA_EK_CSR, + FTPM_EK_CERT_BUF_SIZE, + ctx->fd_out_rsa_ek_csr); + if (rc != TEEC_SUCCESS) + fail_handler(1); + } + + if (FTPM_HELPER_GET_EC_EK_CSR & argus->ftpm_helper_options) { + if (!argus->out_ec_ek_csr) { + fprintf(stderr, "Error: missing -f option.\n"); + fail_handler(1); + } + + ctx->fd_out_ec_ek_csr = fopen(argus->out_ec_ek_csr, "wb"); + rc = ca_query_ftpm_prop(FTPM_HELPER_TA_CMD_GET_EC_EK_CSR, + FTPM_EK_CERT_BUF_SIZE, + ctx->fd_out_ec_ek_csr); + if (rc != TEEC_SUCCESS) + fail_handler(1); + } + + if (FTPM_HELPER_SIGN_EK_CSR & argus->ftpm_helper_options) { + if (!argus->in_sign_ek_csr || !argus->out_signed_ek_csr) { + fprintf(stderr, "Error: missing -k or -l option.\n"); + fail_handler(1); + } + + ctx->fd_in_ek_csr = fopen(argus->in_sign_ek_csr, "rb"); + ctx->fd_out_signed_ek_csr = fopen(argus->out_signed_ek_csr, "wb"); + ca_sign_ek_csr(ctx->fd_in_ek_csr, + ctx->fd_out_signed_ek_csr); + } + + if (FTPM_HELPER_QUERY_ECID & argus->ftpm_helper_options) + ca_query_ecid(); + + if (FTPM_HELPER_QUERY_SN & argus->ftpm_helper_options) + ca_query_sn(); + + if (FTPM_HELPER_QUERY_PROV_MODE & argus->ftpm_helper_options) { + if (ctx->prov_mode == FTPM_PROV_MODE_OFFLINE) + fprintf(stdout, "offline\n"); + else if (ctx->prov_mode == FTPM_PROV_MODE_ONLINE) + fprintf(stdout, "online\n"); + else + fprintf(stdout, "unknown\n"); + } + + if (FTPM_HELPER_QUERY_VERSION & argus->ftpm_helper_options) + fprintf(stdout, "%d.%d\n", ctx->ver_major, ctx->ver_minor); + + if (FTPM_HELPER_INJECT_EPS & argus->ftpm_helper_options) { + if (!argus->inject_eps_value) { + fprintf(stderr, "Error: missing -g option.\n"); + fail_handler(1); + } + + rc = parse_eps_value(argus->inject_eps_value, eps, FTPM_HELPER_TA_EPS_BYTES); + if (rc != TEEC_SUCCESS) + fail_handler(1); + + rc = ca_inject_eps(eps, FTPM_HELPER_TA_EPS_BYTES); + if (rc != TEEC_SUCCESS) + fail_handler(1); + } +} + +int main(int argc, char *argv[]) +{ + struct arguments argus; + + /* Initialize the arguments */ + memset(&argus, 0, sizeof(struct arguments)); + + /* 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; + + ca_sess.prov_mode = FTPM_PROV_MODE_UNKNOWN; + ca_query_prov_mode(); + + /* Check the device provision mode */ + if (ca_sess.prov_mode == FTPM_PROV_MODE_UNKNOWN) { + fprintf(stderr, "Invalid provision mode!\n"); + goto err_out; + } + + /* Check the command inputs */ + if (ca_sess.prov_mode == FTPM_PROV_MODE_OFFLINE && + argus.ftpm_helper_options & INVALID_OPT_FOR_OFFLINE_PROV_MODE) { + fprintf(stderr, "Invalid command for offline provision mode!\n"); + argp_help(&argp, stderr, 0, NULL); + goto err_out; + } + + if (ca_sess.prov_mode == FTPM_PROV_MODE_ONLINE && + argus.ftpm_helper_options & INVALID_OPT_FOR_ONLINE_PROV_MODE) { + fprintf(stderr, "Invalid command for online provision mode!\n"); + argp_help(&argp, stderr, 0, NULL); + goto err_out; + } + + handle_ftpm_helper_options(&ca_sess); + +err_out: + terminate_tee_session(&ca_sess); + + return 0; +} diff --git a/optee/samples/ftpm-helper/host/tool/conf/ftpm_i_ca_sim.config b/optee/samples/ftpm-helper/host/tool/conf/ftpm_i_ca_sim.config new file mode 100644 index 0000000..928c037 --- /dev/null +++ b/optee/samples/ftpm-helper/host/tool/conf/ftpm_i_ca_sim.config @@ -0,0 +1,22 @@ +# Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause + +[req] +encrypt_key = no +prompt = no +utf8 = yes +string_mask = utf8only +distinguished_name = dn +x509_extensions = ca_ext + +[ca_ext] +keyUsage = critical, keyCertSign, cRLSign +basicConstraints = CA:true +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer + +[dn] +organizationName = "fTPM CA Sim C01" +organizationalUnitName = "fTPM Manufacturer CA Sim I01" +commonName = "fTPM Sim Intermediate CA" +C = "US" diff --git a/optee/samples/ftpm-helper/host/tool/conf/ftpm_root_ca_sim.config b/optee/samples/ftpm-helper/host/tool/conf/ftpm_root_ca_sim.config new file mode 100644 index 0000000..6f4a52b --- /dev/null +++ b/optee/samples/ftpm-helper/host/tool/conf/ftpm_root_ca_sim.config @@ -0,0 +1,21 @@ +# Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause + +[req] +encrypt_key = no +prompt = no +utf8 = yes +string_mask = utf8only +distinguished_name = dn +x509_extensions = ca_ext + +[ca_ext] +keyUsage = critical, keyCertSign, cRLSign +basicConstraints = CA:true +subjectKeyIdentifier = hash + +[dn] +organizationName = "fTPM CA Sim C01" +organizationalUnitName = "fTPM Manufacturer CA Sim R01" +commonName = "fTPM Sim Root CA" +C = "US" diff --git a/optee/samples/ftpm-helper/host/tool/ftpm_device_provision.sh b/optee/samples/ftpm-helper/host/tool/ftpm_device_provision.sh new file mode 100755 index 0000000..f406150 --- /dev/null +++ b/optee/samples/ftpm-helper/host/tool/ftpm_device_provision.sh @@ -0,0 +1,154 @@ +#!/bin/bash + +# Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause + +set -e + +export TPM2TOOLS_TCTI="device:/dev/tpmrm0" + +# fTPM helper CA +NV_FTPM_HELPER_APP="nvftpm-helper-app" + +# fTPM temp out folder +FTPM_TEMP_OUT="ftpm_temp_out" + +# fTPM temp files +FTPM_EKB_RSA_EK_PUB_KEY="${FTPM_TEMP_OUT}/ekb_rsa_ek_pub_key.pem" +FTPM_EKB_EC_EK_PUB_KEY="${FTPM_TEMP_OUT}/ekb_ec_ek_pub_key.pem" +FTPM_RSA_EK_PUB_KEY="${FTPM_TEMP_OUT}/rsa_ek_pub_key.pem" +FTPM_EC_EK_PUB_KEY="${FTPM_TEMP_OUT}/ec_ek_pub_key.pem" + +# TPM NV handles +RSA_EK_HANDLE="0x81010001" +EC_EK_HANDLE="0x81010002" +RSA_EK_CERT_HANDLE="0x01c00002" +EC_EK_CERT_HANDLE="0x01c0000a" + +# TPM EK cert attribute +EK_CERT_ATTR="ppwrite|writedefine|ppread|ownerread|authread|no_da|platformcreate" + +SCRIPT_NAME="$(basename "${0}")" + +function usage { + cat << EOM +Usage: ./${SCRIPT_NAME} [OPTIONS] + +This script helps to provision fTPM via EKB. +The required options: + -r The RSA EK certificate file name that extracts from EKB. (Must) + -e The EC EK certificate file name that extracts from EKB. (Must) + -p The fTPM owner password. (Must) + -h Shows this help. +EOM +} + +function handle_null_ekb { + echo "[ftpm device]: fTPM provisioning failed." + exit 1 +} + +function ftpm_provisioning() { + echo "[fTPM device]: === fTPM device provisioning ===" + + # Extract the EK certificates from EKB + echo "[fTPM device]: === Extracting the EK Certs from EKB ===" + trap handle_null_ekb ERR + ${NV_FTPM_HELPER_APP} -a "${FTPM_RSA_EK_CERT}" -b "${FTPM_EC_EK_CERT}" + + # Extract the EK public keys from the certificates + openssl x509 -inform DER -pubkey -noout -in ${FTPM_RSA_EK_CERT} > ${FTPM_EKB_RSA_EK_PUB_KEY} + openssl x509 -inform DER -pubkey -noout -in ${FTPM_EC_EK_CERT} > ${FTPM_EKB_EC_EK_PUB_KEY} + + # Clean up fTPM + echo "[fTPM device]: === Clean up fTPM. ===" + tpm2_clear + + # Take the ownership of the fTPM + echo "[fTPM device]: === Take the ownership of fTPM. ===" + tpm2_changeauth -c o ${FTPM_OWNER_PW} + tpm2_changeauth -c e ${FTPM_OWNER_PW} + + # Create EK + tpm2_createek -c ${RSA_EK_HANDLE} -G rsa -w ${FTPM_OWNER_PW} -P ${FTPM_OWNER_PW} -f pem -u ${FTPM_RSA_EK_PUB_KEY} + tpm2_createek -c ${EC_EK_HANDLE} -G ecc -w ${FTPM_OWNER_PW} -P ${FTPM_OWNER_PW} -f pem -u ${FTPM_EC_EK_PUB_KEY} + + # Validate the EK public keys + echo "[fTPM device]: === Validate the EK public keys. ===" + _rsa_pubkey_diff="${FTPM_RSA_EK_PUB_KEY}.diff" + _ec_pubkey_diff="${FTPM_EC_EK_PUB_KEY}.diff" + diff ${FTPM_EKB_RSA_EK_PUB_KEY} ${FTPM_RSA_EK_PUB_KEY} > ${_rsa_pubkey_diff}; sync; + diff ${FTPM_EKB_EC_EK_PUB_KEY} ${FTPM_EC_EK_PUB_KEY} > ${_ec_pubkey_diff}; sync; + if [ -s ${_rsa_pubkey_diff} ] || [ -s ${_ec_pubkey_diff} ]; then + echo "[fTPM device]: The EK keys are invalid. Stop provisioning!!" + exit 1 + fi + + # Store the TPM EK certificate info fTPM NVMem + echo "[fTPM device]: === Store the EK certificates. ===" + _rsa_ek_cert_size=$(wc -c < ${FTPM_RSA_EK_CERT}) + tpm2_nvdefine ${RSA_EK_CERT_HANDLE} -C p -a ${EK_CERT_ATTR} -s ${_rsa_ek_cert_size} + tpm2_nvwrite ${RSA_EK_CERT_HANDLE} -C p -i ${FTPM_RSA_EK_CERT} + + _ec_ek_cert_size=$(wc -c < ${FTPM_EC_EK_CERT}) + tpm2_nvdefine ${EC_EK_CERT_HANDLE} -C p -a ${EK_CERT_ATTR} -s ${_ec_ek_cert_size} + tpm2_nvwrite ${EC_EK_CERT_HANDLE} -C p -i ${FTPM_EC_EK_CERT} + + # Check the EK certificate in NV + RSA_EK_CERT_IN_NV="${FTPM_RSA_EK_CERT}.ftpm_nv" + EC_EK_CERT_IN_NV="${FTPM_EC_EK_CERT}.ftpm_nv" + tpm2_nvread ${RSA_EK_CERT_HANDLE} -s ${_rsa_ek_cert_size} -o ${RSA_EK_CERT_IN_NV} + tpm2_nvread ${EC_EK_CERT_HANDLE} -s ${_ec_ek_cert_size} -o ${EC_EK_CERT_IN_NV} + + _rsa_result="${RSA_EK_CERT_IN_NV}.diff" + _ec_result="${EC_EK_CERT_IN_NV}.diff" + diff ${FTPM_RSA_EK_CERT} ${RSA_EK_CERT_IN_NV} > ${_rsa_result}; sync; + diff ${FTPM_EC_EK_CERT} ${EC_EK_CERT_IN_NV} > ${_ec_result}; sync; + if [ -s ${_rsa_result} ] || [ -s ${_ec_result} ]; then + echo "[fTPM device]: EK certificate has not been written in NV!!" + exti 1 + else + echo "[fTPM device]: EK certificate saved in NV successuflly." + fi + + # Empty separator line + echo "" +} + +if [ "${1}" == "" ]; then + usage + exit 1 +fi + +while getopts "hr:e:p:" OPTION +do + case $OPTION in + h) + usage + exit 0 + ;; + r) + FTPM_RSA_EK_CERT="${OPTARG}" + ;; + e) + FTPM_EC_EK_CERT="${OPTARG}" + ;; + p) + FTPM_OWNER_PW="${OPTARG}" + ;; + *) + usage + exit 1 + ;; + esac +done + +if [ "${FTPM_RSA_EK_CERT}" == "" ] || + [ "${FTPM_EC_EK_CERT}" == "" ] || + [ "${FTPM_OWNER_PW}" == "" ]; then + usage + exit 1 +fi + +mkdir -p ${FTPM_TEMP_OUT} +ftpm_provisioning diff --git a/optee/samples/ftpm-helper/host/tool/ftpm_manufacturer_ca_sign_sid_csr.py b/optee/samples/ftpm-helper/host/tool/ftpm_manufacturer_ca_sign_sid_csr.py new file mode 100755 index 0000000..b1fdd8e --- /dev/null +++ b/optee/samples/ftpm-helper/host/tool/ftpm_manufacturer_ca_sign_sid_csr.py @@ -0,0 +1,163 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause + +# +# Required Python modules: +# sudo apt-get update +# sudo apt-get install python3-pip +# python3 -m pip install asn1crypto (version 1.5.1) +# python3 -m pip install oscrypto (version 1.3.0) +# + +import argparse +import datetime +import os +import sys +import textwrap + +from asn1crypto import csr, pem, util, x509 +from oscrypto import asymmetric, errors + +class fTPM_CA_Sign_Silicon_ID_CSR: + def __init__(self, sid_csr, ca_cert, ca_priv_key, sid_cert_file_prefix, out_path): + # Loading the Silicon ID CSR + self.sid_csr = csr.CertificationRequest.load(sid_csr) + self.sid_csr_cri = self.sid_csr['certification_request_info'] + self.sid_pub_key = asymmetric.load_public_key(self.sid_csr_cri['subject_pk_info']) + self.sid_key_algo = self.sid_pub_key.algorithm + + # Loading CA properties + if pem.detect(ca_cert): + _, _, _ca_cert_der = pem.unarmor(ca_cert) + else: + _ca_cert_der = ca_cert + self.ca_cert = x509.Certificate.load(_ca_cert_der) + self.ca_priv_key = asymmetric.load_private_key(ca_priv_key) + + # Preparing the Silicon ID cert file + self.sid_cert_file = out_path + "/" + sid_cert_file_prefix + ".der" + self.sid_cert_fout = open(self.sid_cert_file, "wb") + + def verify_sid_csr(self): + _sig = self.sid_csr['signature'].native + + if self.sid_key_algo == 'rsa': + verify_func = asymmetric.rsa_pkcs1v15_verify + elif self.sid_key_algo == 'ec': + verify_func = asymmetric.ecdsa_verify + else: + raise Exception("[CA Sim]: *** fTPM Manufacturer CA simulation: The Silicon ID CSR public key is invalid!!") + + try: + verify_func(self.sid_pub_key, _sig, self.sid_csr_cri.dump(), "sha256") + except(errors.SignatureError): + raise Exception("[CA Sim]: *** fTPM Manufacturer CA simulation: The Silicon CSR verification failed!!") + + def gen_sid_cert(self): + # Subject name + _sid_subject = self.sid_csr_cri['subject'] + # Public key info + _sid_pk_info = self.sid_csr_cri['subject_pk_info'] + # Authority key identifier + _ca_key_id = self.ca_cert.key_identifier_value + + # Extensions + _extensions = self.sid_csr_cri['attributes'][0]['values'][0] + _ext = [] + for i in range(len(_extensions)): + _extn_value = _extensions[i]['extn_value'].native + + _ext.append({ + "extn_id" : _extensions[i]['extn_id'].native, + "critical" : _extensions[i]['critical'].native, + "extn_value": _extn_value + }) + + _ext.extend([ + { + "extn_id" : "authority_key_identifier", + "extn_value" : { "key_identifier" : _ca_key_id }, + } + ]) + + # Signature Algorithm + if self.ca_priv_key.algorithm == 'rsa': + _sig_algo = "sha256_rsa" + elif self.ca_priv_key.algorithm == 'ec': + _sig_algo = "sha256_ecdsa" + else: + raise Exception("Error: The CA private key is invalid.") + + _sid_tbs = x509.TbsCertificate( + { + "version" : "v3", + "serial_number" : util.int_from_bytes(_sid_subject.sha1), + "signature" : { "algorithm" : _sig_algo }, + "issuer" : self.ca_cert.subject, + "validity" : { + "not_before" : x509.UTCTime(datetime.datetime(2023, 6, 1, 0, 0, tzinfo=datetime.timezone.utc)), + "not_after" : x509.GeneralizedTime(datetime.datetime(2050, 12, 31, 23, 59, 59, tzinfo=datetime.timezone.utc)), + }, + "subject" : _sid_subject, + "subject_public_key_info" : _sid_pk_info, + "extensions" : _ext, + } + ) + + # Signing the certificate + if self.ca_priv_key.algorithm == 'rsa': + sign_func = asymmetric.rsa_pkcs1v15_sign + elif self.ca_priv_key.algorithm == 'ec': + sign_func = asymmetric.ecdsa_sign + + _signature = sign_func(self.ca_priv_key, _sid_tbs.dump(), "sha256") + + self.sid_cert = x509.Certificate( + { + "tbs_certificate" : _sid_tbs, + "signature_algorithm" : { "algorithm" : _sig_algo }, + "signature_value" : _signature, + } + ) + + self.sid_cert_fout.write(self.sid_cert.dump()) + self.sid_cert_fout.close() + + return self.sid_cert_file + +def main(): + parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter, + description=textwrap.dedent(''' + fTPM Manufacturer CA Simulator for signing the Device Silicon ID CSR. + * Input: The Silicon ID CSR. + * Input: The CA Certificate. + * Input: The CA private key. + * Input: The output path to store the Silicon ID certificate. + * Output: The Silicon ID certificate. + ''')) + + parser.add_argument('--sid_csr', type=str, required=True, help="The Silicon ID CSR hex string in DER format.") + parser.add_argument('--ca_cert', type=str, required=True, help="The CA certificate file in PEM format.") + parser.add_argument('--ca_private_key', type=str, required=True, help="The fTPM CA private key.") + parser.add_argument('--sid_cert', type=str, required=True, help="The prefix of Silicon ID certificate file name. This outputs the certificate in DER format.") + parser.add_argument('--out_path', type=str, required=True, help="The output folder of the result.") + + args = parser.parse_args() + + if not os.path.exists(args.out_path): + os.makedirs(args.out_path) + + ftpm_ca = fTPM_CA_Sign_Silicon_ID_CSR(sid_csr = bytes.fromhex(args.sid_csr), + ca_cert = open(args.ca_cert, "rb").read(), + ca_priv_key = open(args.ca_private_key, "rb").read(), + sid_cert_file_prefix = args.sid_cert, + out_path = args.out_path) + ftpm_ca.verify_sid_csr() + + output_sid_cert_file = ftpm_ca.gen_sid_cert() + sys.stdout.write(output_sid_cert_file) + +if __name__ == "__main__": + main() diff --git a/optee/samples/ftpm-helper/host/tool/ftpm_manufacturer_ca_sign_sid_csr.sh b/optee/samples/ftpm-helper/host/tool/ftpm_manufacturer_ca_sign_sid_csr.sh new file mode 100755 index 0000000..fdf91e2 --- /dev/null +++ b/optee/samples/ftpm-helper/host/tool/ftpm_manufacturer_ca_sign_sid_csr.sh @@ -0,0 +1,152 @@ +#!/bin/bash + +# Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause + +# +# Required Python modules: +# sudo apt-get update +# sudo apt-get install python3-pip +# python3 -m pip install asn1crypto (version 1.5.1) +# python3 -m pip install oscrypto (version 1.3.0) +# + +set -e + +# Place to store local configuration files +CONF_PATH="./conf" + +# Place to store the local output files (e.g. Silicon ID certificates) +CA_OUT_PATH="./ca_out" + +# The prefix of the Silicon ID Cert file name: sid_cert-${SN} +SID_CERT_FILE_PREFIX="sid_cert" + +CA_SIM_PYTHON_SCRIPT="./ftpm_manufacturer_ca_sign_sid_csr.py" + +# fTPM Manufacturer CA certificates (optional) +# This is for simulation purposes only. +ROOT_CA_PRIV_KEY="${CA_OUT_PATH}/root_ca_test_priv_key.pem" +ROOT_CA_CONF="${CONF_PATH}/ftpm_root_ca_sim.config" +ROOT_CA_CERT="${CA_OUT_PATH}/root_ca_test_cert.pem" +ROOT_CA_CERT_TXT="${CA_OUT_PATH}/root_ca_test_cert.txt" + +I_CA_PRIV_KEY="${CA_OUT_PATH}/i_ca_test_priv_key.pem" +I_CA_CONF="${CONF_PATH}/ftpm_i_ca_sim.config" +I_CA_CSR="${CA_OUT_PATH}/i_ca_test_csr.pem" +I_CA_CERT="${CA_OUT_PATH}/i_ca_test_cert.pem" +I_CA_CERT_TXT="${CA_OUT_PATH}/i_ca_test_cert.txt" + +SCRIPT_NAME="$(basename "${0}")" + +function usage { + cat << EOM +Usage: ./${SCRIPT_NAME} [OPTIONS] + +This script simulates an fTPM manufacturer CA to sign the Device Silicon ID CSR and return the certificate. +The required options: + -i The Silicon ID CSR in hex string of DER format. (Must) + -s The Serial Number of the Silicon ID CSR. (Must) + -h Shows this help. +EOM +} + +function gen_simulation_ca() { + echo "[CA Sim]: === Creating self-signed Root CA Certificate. ===" + # Generate the root CA private key + openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 \ + -pkeyopt ec_param_enc:named_curve -out ${ROOT_CA_PRIV_KEY} 2>/dev/null + # Generate the root CA certificate + openssl req -batch -verbose -new -sha256 -x509 -days 365 \ + -config ${ROOT_CA_CONF} -key ${ROOT_CA_PRIV_KEY} -out ${ROOT_CA_CERT} 2>/dev/null + openssl x509 -inform PEM -in ${ROOT_CA_CERT} -text -noout > ${ROOT_CA_CERT_TXT} + + echo "[CA Sim]: === Creating Intermediate CA Certificate. ===" + # Generate the ICA private key + + # RSA2K key for the ICA + openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out ${I_CA_PRIV_KEY} 2>/dev/null + + # EC P-256 key for the ICA + #openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 \ + # -pkeyopt ec_param_enc:named_curve -out ${I_CA_PRIV_KEY} 2>/dev/null + + # Generate the ICA CSR + openssl req -sha256 -new -key ${I_CA_PRIV_KEY} -config ${I_CA_CONF} -out ${I_CA_CSR} + # Sign the ICA CSR + openssl x509 -in ${I_CA_CSR} -req -keyform PEM -CA ${ROOT_CA_CERT} -CAkey ${ROOT_CA_PRIV_KEY} \ + -CAcreateserial -sha256 -days 365 -extensions ca_ext -extfile ${I_CA_CONF} \ + -out ${I_CA_CERT} 2>/dev/null + openssl x509 -inform PEM -in ${I_CA_CERT} -text -noout > ${I_CA_CERT_TXT} + + echo "[CA Sim]: === Verifying the CA Certificates ===" + openssl verify -CAfile ${ROOT_CA_CERT} ${I_CA_CERT} 2>/dev/null + + # Empty separator line + echo "" +} + +function ca_sign_sid_csr() { + _sid_csr="${1}" + _prefix_sid_cert_file="${SID_CERT_FILE_PREFIX}-${SN}" + + echo "[CA Sim]: === fTPM Manufacturer CA simulation stage: Signing Silicon ID CSR ===" + CA_SIGN_CSR_CMD="${CA_SIM_PYTHON_SCRIPT} --out_path ${CA_OUT_PATH} \ + --sid_csr ${_sid_csr} \ + --ca_cert ${I_CA_CERT} \ + --ca_private_key ${I_CA_PRIV_KEY} \ + --sid_cert ${_prefix_sid_cert_file}" + + _sid_cert_file=$(${CA_SIGN_CSR_CMD}) + + echo "[CA Sim]: === fTPM Manufacturer CA simulation: The Silicon ID CSR verification passed!!" + echo "[CA Sim]: === fTPM Manufacturer CA simulation: The Silicon ID Cert generation has done!!" + # Dump the Silicon ID certificate + openssl x509 -inform DER -text -noout -in "${_sid_cert_file}" + + # CA verifies the cert chain + echo "[CA Sim]: === Verify the Silicon ID certificate chain: ${_sid_cert_file} ===" + _temp_sid_cert_pem_file="${CA_OUT_PATH}/temp_sid_cert.pem" + openssl x509 -inform DER -outform PEM -in "${_sid_cert_file}" -out "${_temp_sid_cert_pem_file}" + openssl verify -CAfile ${ROOT_CA_CERT} -untrusted ${I_CA_CERT} -show_chain ${_temp_sid_cert_pem_file} 2>/dev/null + + echo "" +} + +mkdir -p ${CA_OUT_PATH} + +if [ "${1}" == "" ]; then + usage + exit 1 +fi + +while getopts "hi:s:" OPTION +do + case $OPTION in + h) + usage + exit 0 + ;; + i) + SID_CSR_DER_HEX_STR="${OPTARG}" + ;; + s) + SN="${OPTARG}" + ;; + *) + usage + exit 1 + ;; + esac +done + +if [ "${SN}" == "" ]; then + usage + exit 1 +fi + +if [ ! -f ${ROOT_CA_CERT} ] || [ ! -f ${I_CA_CERT} ] || [ ! -f ${I_CA_PRIV_KEY} ]; then + gen_simulation_ca +fi + +ca_sign_sid_csr ${SID_CSR_DER_HEX_STR} diff --git a/optee/samples/ftpm-helper/host/tool/ftpm_manufacturer_ca_simulator.py b/optee/samples/ftpm-helper/host/tool/ftpm_manufacturer_ca_simulator.py new file mode 100755 index 0000000..8b71af0 --- /dev/null +++ b/optee/samples/ftpm-helper/host/tool/ftpm_manufacturer_ca_simulator.py @@ -0,0 +1,184 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause + +# +# Required Python modules: +# sudo apt-get update +# sudo apt-get install python3-pip +# python3 -m pip install asn1crypto (version 1.5.1) +# python3 -m pip install oscrypto (version 1.3.0) +# + +import argparse +import datetime +import filecmp +import os +import sys +import textwrap + +from asn1crypto import csr, pem, util, x509 +from oscrypto import asymmetric, errors + +class fTPM_CA_Sign_EK_CSR: + def __init__(self, ek_csr, ca_cert, ca_priv_key, ek_cert_file_prefix, out_path): + # Loading the EK CSR + self.ek_csr = csr.CertificationRequest.load(ek_csr) + self.ek_csr_cri = self.ek_csr['certification_request_info'] + self.ek_pub_key = asymmetric.load_public_key(self.ek_csr_cri['subject_pk_info']) + self.ek_algo = self.ek_pub_key.algorithm + + # Loading CA properties + if pem.detect(ca_cert): + _, _, _ca_cert_der = pem.unarmor(ca_cert) + else: + _ca_cert_der = ca_cert + self.ca_cert = x509.Certificate.load(_ca_cert_der) + self.ca_priv_key = asymmetric.load_private_key(ca_priv_key) + + # Preparing the EK cert file + self.ek_cert_file = out_path + "/" + ek_cert_file_prefix + ".der" + self.ek_cert_fout = open(self.ek_cert_file, "wb") + + def verify_ek_csr(self): + _sig = self.ek_csr['signature'].native + + if self.ek_algo == 'rsa': + verify_func = asymmetric.rsa_pkcs1v15_verify + elif self.ek_algo == 'ec': + verify_func = asymmetric.ecdsa_verify + else: + raise Exception("[CA Sim]: *** fTPM Manufacturer CA simulation: The EK CSR public key is invalid!!") + + try: + verify_func(self.ek_pub_key, _sig, self.ek_csr_cri.dump(), "sha256") + except(errors.SignatureError): + raise Exception("[CA Sim]: *** fTPM Manufacturer CA simulation: The EK CSR verification failed!!") + + def gen_ek_cert(self): + # https://trustedcomputinggroup.org/wp-content/uploads/TCG-EK-Credential-Profile-V-2.5-R2_published.pdf + + # EK cert subject name + _ek_subject = self.ek_csr['certification_request_info']['subject'] + # EK public key info + _ek_pk_info = self.ek_csr['certification_request_info']['subject_pk_info'] + # Authority key identifier + _ca_key_id = self.ca_cert.key_identifier_value + + # Extensions + _extensions = self.ek_csr['certification_request_info']['attributes'][0]['values'][0] + _ek_ext = [] + for i in range(len(_extensions)): + if _extensions[i]['extn_id'].native == "subject_alt_name": + _alt_names = _extensions[i]['extn_value'].native + _sub_alt_name = x509.Name.build( + { + "tpm_manufacturer" : _alt_names[0]['tpm_manufacturer'], + "tpm_model" : _alt_names[0]['tpm_model'], + "tpm_version" : _alt_names[0]['tpm_version'] + } + ) + + _extn_value = x509.GeneralNames([ + x509.GeneralName( + name = "directory_name", + value = _sub_alt_name, + ) + ]) + else: + _extn_value = _extensions[i]['extn_value'].native + + _ek_ext.append({ + "extn_id" : _extensions[i]['extn_id'].native, + "critical" : _extensions[i]['critical'].native, + "extn_value": _extn_value + }) + + _ek_ext.extend([ + { + "extn_id" : "authority_key_identifier", + "extn_value" : { "key_identifier" : _ca_key_id }, + } + ]) + + # Signature Algorithm + if self.ca_priv_key.algorithm == 'rsa': + _sig_algo = "sha256_rsa" + elif self.ca_priv_key.algorithm == 'ec': + _sig_algo = "sha256_ecdsa" + else: + raise Exception("Error: The CA private key is invalid.") + + _ek_tbs = x509.TbsCertificate( + { + "version" : "v3", + "serial_number" : util.int_from_bytes(_ek_subject.sha1), + "signature" : { "algorithm" : _sig_algo }, + "issuer" : self.ca_cert.subject, + "validity" : { + "not_before" : x509.UTCTime(datetime.datetime(2023, 6, 1, 0, 0, tzinfo=datetime.timezone.utc)), + "not_after" : x509.GeneralizedTime(datetime.datetime(2033, 12, 31, 23, 59, 59, tzinfo=datetime.timezone.utc)), + }, + "subject" : _ek_subject, + "subject_public_key_info" : _ek_pk_info, + "extensions" : _ek_ext, + } + ) + + # Signing the EK certificate + if self.ca_priv_key.algorithm == 'rsa': + sign_func = asymmetric.rsa_pkcs1v15_sign + elif self.ca_priv_key.algorithm == 'ec': + sign_func = asymmetric.ecdsa_sign + + _signature = sign_func(self.ca_priv_key, _ek_tbs.dump(), "sha256") + + self.ek_cert = x509.Certificate( + { + "tbs_certificate" : _ek_tbs, + "signature_algorithm" : { "algorithm" : _sig_algo }, + "signature_value" : _signature, + } + ) + + self.ek_cert_fout.write(self.ek_cert.dump()) + self.ek_cert_fout.close() + + return self.ek_cert_file + +def main(): + parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter, + description=textwrap.dedent(''' + fTPM Manufacturer CA Simulator for signing the EK CSR. + * Input: The EK CSR. + * Input: The CA Certificate. + * Input: The CA private key. + * Input: The output path to store the EK certificate. + * Output: The EK certificate. + ''')) + + parser.add_argument('--ek_csr', type=str, required=True, help="The EK CSR file in DER format.") + parser.add_argument('--ca_cert', type=str, required=True, help="The CA certificate file in PEM format.") + parser.add_argument('--ca_private_key', type=str, required=True, help="The fTPM CA private key.") + parser.add_argument('--ek_cert', type=str, required=True, help="The prefix of EK certificate file name. This outputs the certificate in DER format.") + parser.add_argument('--out_path', type=str, required=True, help="The output folder of the result.") + + args = parser.parse_args() + + if not os.path.exists(args.out_path): + os.makedirs(args.out_path) + + ftpm_ca = fTPM_CA_Sign_EK_CSR(ek_csr = open(args.ek_csr, "rb").read(), + ca_cert = open(args.ca_cert, "rb").read(), + ca_priv_key = open(args.ca_private_key, "rb").read(), + ek_cert_file_prefix = args.ek_cert, + out_path = args.out_path) + ftpm_ca.verify_ek_csr() + + output_ek_cert_file = ftpm_ca.gen_ek_cert() + sys.stdout.write(output_ek_cert_file) + + +if __name__ == "__main__": + main() diff --git a/optee/samples/ftpm-helper/host/tool/ftpm_manufacturer_ca_simulator.sh b/optee/samples/ftpm-helper/host/tool/ftpm_manufacturer_ca_simulator.sh new file mode 100755 index 0000000..3868c18 --- /dev/null +++ b/optee/samples/ftpm-helper/host/tool/ftpm_manufacturer_ca_simulator.sh @@ -0,0 +1,158 @@ +#!/bin/bash + +# Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause + +# +# Required Python modules: +# sudo apt-get update +# sudo apt-get install python3-pip +# python3 -m pip install asn1crypto (version 1.5.1) +# python3 -m pip install oscrypto (version 1.3.0) +# + +set -e + +# Place to store local configuration files +CONF_PATH="./conf" + +# Place to store the local output files (e.g. EK certificates) +CA_OUT_PATH="./ca_out" + +# Place to store the fTPM input files (e.g. EK CSR files) +FTPM_OUT_PATH="./ftpm_out" + +# The prefix of the EK Cert file name: ek_cert_${ALGO}-${SN} +EK_CERT_FILE_PREFIX="ek_cert_" + +CA_SIM_PYTHON_SCRIPT="./ftpm_manufacturer_ca_simulator.py" + +# fTPM Manufacturer CA certificates (optional) +# This is for simulation purposes only. +ROOT_CA_PRIV_KEY="${CA_OUT_PATH}/root_ca_test_priv_key.pem" +ROOT_CA_CONF="${CONF_PATH}/ftpm_root_ca_sim.config" +ROOT_CA_CERT="${CA_OUT_PATH}/root_ca_test_cert.pem" +ROOT_CA_CERT_TXT="${CA_OUT_PATH}/root_ca_test_cert.txt" + +I_CA_PRIV_KEY="${CA_OUT_PATH}/i_ca_test_priv_key.pem" +I_CA_CONF="${CONF_PATH}/ftpm_i_ca_sim.config" +I_CA_CSR="${CA_OUT_PATH}/i_ca_test_csr.pem" +I_CA_CERT="${CA_OUT_PATH}/i_ca_test_cert.pem" +I_CA_CERT_TXT="${CA_OUT_PATH}/i_ca_test_cert.txt" + +SCRIPT_NAME="$(basename "${0}")" + +function usage { + cat << EOM +Usage: ./${SCRIPT_NAME} [OPTIONS] + +This script simulates an fTPM manufacturer CA to sign the fTPM EK CSR and return the certificate. +The required options: + -s The Serial Number of the EK CSR. (Must) + -h Shows this help. +EOM +} + +function gen_simulation_ca() { + echo "[CA Sim]: === Creating self-signed Root CA Certificate. ===" + # Generate the root CA private key + openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 \ + -pkeyopt ec_param_enc:named_curve -out ${ROOT_CA_PRIV_KEY} 2>/dev/null + # Generate the root CA certificate + openssl req -batch -verbose -new -sha256 -x509 -days 365 \ + -config ${ROOT_CA_CONF} -key ${ROOT_CA_PRIV_KEY} -out ${ROOT_CA_CERT} 2>/dev/null + openssl x509 -inform PEM -in ${ROOT_CA_CERT} -text -noout > ${ROOT_CA_CERT_TXT} + + echo "[CA Sim]: === Creating Intermediate CA Certificate. ===" + # Generate the ICA private key + # RSA2K key for the ICA + openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out ${I_CA_PRIV_KEY} 2>/dev/null + + # EC P-256 key for the ICA + #openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 \ + # -pkeyopt ec_param_enc:named_curve -out ${I_CA_PRIV_KEY} 2>/dev/null + + # Generate the ICA CSR + openssl req -sha256 -new -key ${I_CA_PRIV_KEY} -config ${I_CA_CONF} -out ${I_CA_CSR} + # Sign the ICA CSR + openssl x509 -in ${I_CA_CSR} -req -keyform PEM -CA ${ROOT_CA_CERT} -CAkey ${ROOT_CA_PRIV_KEY} \ + -CAcreateserial -sha256 -days 365 -extensions ca_ext -extfile ${I_CA_CONF} \ + -out ${I_CA_CERT} 2>/dev/null + openssl x509 -inform PEM -in ${I_CA_CERT} -text -noout > ${I_CA_CERT_TXT} + + echo "[CA Sim]: === Verifying the CA Certificates ===" + openssl verify -CAfile ${ROOT_CA_CERT} ${I_CA_CERT} 2>/dev/null + + # Empty separator line + echo "" +} + +function ca_sign_ek_csr() { + _ek_type="${1}" + _ek_csr="${2}" + _prefix_ek_cert_file="${EK_CERT_FILE_PREFIX}${_ek_type}-${SN}" + + echo "[CA Sim]: === fTPM Manufacturer CA simulation stage: Signing ${_ek_csr} ===" + CA_SIGN_CSR_CMD="${CA_SIM_PYTHON_SCRIPT} --out_path ${CA_OUT_PATH} \ + --ek_csr ${_ek_csr} \ + --ca_cert ${I_CA_CERT} \ + --ca_private_key ${I_CA_PRIV_KEY} \ + --ek_cert ${_prefix_ek_cert_file}" + + _ek_cert_file=$(${CA_SIGN_CSR_CMD}) + + echo "[CA Sim]: === fTPM Manufacturer CA simulation: The EK CSR verification passed!!" + echo "[CA Sim]: === fTPM Manufacturer CA simulation: The EK Cert generation has done!!" + # Dump the EK certificate + openssl x509 -inform DER -text -noout -in "${_ek_cert_file}" + + # CA verifies the cert chain + echo "[CA Sim]: === Verify the EK certificate chain: ${_ek_cert_file} ===" + _temp_ek_cert_pem_file="${CA_OUT_PATH}/temp_ek_cert.pem" + openssl x509 -inform DER -outform PEM -in "${_ek_cert_file}" -out "${_temp_ek_cert_pem_file}" + openssl verify -CAfile ${ROOT_CA_CERT} -untrusted ${I_CA_CERT} -show_chain ${_temp_ek_cert_pem_file} 2>/dev/null + + echo "" +} + +mkdir -p ${CA_OUT_PATH} + +if [ "${1}" == "" ]; then + usage + exit 1 +fi + +while getopts "hs:" OPTION +do + case $OPTION in + h) + usage + exit 0 + ;; + s) + SN="${OPTARG}" + ;; + *) + usage + exit 1 + ;; + esac +done + +if [ "${SN}" == "" ]; then + usage + exit 1 +fi + +# EK CSR file +EK_CSR_EC_FILE="ek_csr_ec-${SN}.der" +EK_CSR_RSA_FILE="ek_csr_rsa-${SN}.der" +FTPM_EK_CSR_EC_FILE="${FTPM_OUT_PATH}/${EK_CSR_EC_FILE}" +FTPM_EK_CSR_RSA_FILE="${FTPM_OUT_PATH}/${EK_CSR_RSA_FILE}" + +if [ ! -f ${ROOT_CA_CERT} ] || [ ! -f ${I_CA_CERT} ] || [ ! -f ${I_CA_PRIV_KEY} ]; then + gen_simulation_ca +fi + +ca_sign_ek_csr "ec" ${FTPM_EK_CSR_EC_FILE} +ca_sign_ek_csr "rsa" ${FTPM_EK_CSR_RSA_FILE} diff --git a/optee/samples/ftpm-helper/host/tool/ftpm_manufacturer_gen_ek_csr.sh b/optee/samples/ftpm-helper/host/tool/ftpm_manufacturer_gen_ek_csr.sh new file mode 100755 index 0000000..97c188b --- /dev/null +++ b/optee/samples/ftpm-helper/host/tool/ftpm_manufacturer_gen_ek_csr.sh @@ -0,0 +1,110 @@ +#!/bin/bash + +# Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause + +# Required Python modules: +# sudo apt-get update +# sudo apt-get install python3-pip +# python3 -m pip install asn1crypto (version 1.5.1) +# python3 -m pip install ecdsa (version 1.14.0) +# python3 -m pip install numpy (version 1.24.4) +# python3 -m pip install oscrypto (version 1.3.0) +# python3 -m pip install pyaes (version 1.6.1) +# python3 -m pip install pycryptodomex (version 3.19.0) + +set -e + +# Place to store the fTPM output files (e.g. EK CSR files) +FTPM_OUT_PATH="./ftpm_out" + +# Variables for EK CSR +SUBJECT_COMMON_NAME="_ftpm-ek-cert" +SUBJECT_ORG_NAME="ftpm corp" +SUBJECT_COUNTRY_NAME="US" + +# The prefix of EK CSR file name: ek_csr +PREFIX_EK_CSR_FILE_NAME="ek_csr" + +# fTPM Gen EK CSR TOOL +FTPM_GEN_EK_CSR_PYTHON_SCRIPT="./ftpm_manufacturer_gen_ek_csr_tool.py" + +SCRIPT_NAME="$(basename "${0}")" + +function usage { + cat << EOM +Usage: ./${SCRIPT_NAME} [OPTIONS] + +This script helps to generate fTPM EK CSRs. +The required options: + -s The Serial Number of the EK CSR. (Must) + -e The EPS for fTPM to generate EK. This should be 64 bytes (128 digits) hex format string. (Must) + -h Shows this help. +EOM +} + +function gen_ek_csr() { + local _ek_csr_file + + _ek_csr_file="${PREFIX_EK_CSR_FILE_NAME}" + + # Generate the EK CSR + echo "[fTPM tool]: === Generating the EK CSR ===" + ${FTPM_GEN_EK_CSR_PYTHON_SCRIPT} --out_path "${FTPM_OUT_PATH}" \ + --subject_cn "${SN}${SUBJECT_COMMON_NAME}" \ + --subject_on "${SUBJECT_ORG_NAME}" \ + --subject_Cn "${SUBJECT_COUNTRY_NAME}" \ + --sn "${SN}" \ + --ek_csr "${_ek_csr_file}" \ + --eps "${EPS}" + + # Dump the EK CSR template + echo "[fTPM device]: === Dump the RSA EK CSR ===" + openssl req -inform DER -text -noout -in ${FTPM_OUT_PATH}/${_ek_csr_file}_rsa-${SN}.der + echo "[fTPM device]: === Dump the EC EK CSR ===" + openssl req -inform DER -text -noout -in ${FTPM_OUT_PATH}/${_ek_csr_file}_ec-${SN}.der + + # Empty separator line + echo "" +} + +mkdir -p ${FTPM_OUT_PATH} + +if [ "${1}" == "" ]; then + usage + exit 1 +fi + +while getopts "hs:e:" OPTION +do + case $OPTION in + h) + usage + exit 0 + ;; + s) + SN="${OPTARG}" + ;; + e) + EPS="${OPTARG}" + ;; + *) + usage + exit 1 + ;; + esac +done + +if [ "${SN}" == "" ] || [ "${EPS}" == "" ]; then + usage + exit 1 +fi + +EPS_LEN=${#EPS} + +if [ ${EPS_LEN} != 128 ]; then + echo "Error: wrong EPS ${EPS_LEN} length." + exit 1 +fi + +gen_ek_csr diff --git a/optee/samples/ftpm-helper/host/tool/ftpm_manufacturer_gen_ek_csr_tool.py b/optee/samples/ftpm-helper/host/tool/ftpm_manufacturer_gen_ek_csr_tool.py new file mode 100755 index 0000000..04e3a00 --- /dev/null +++ b/optee/samples/ftpm-helper/host/tool/ftpm_manufacturer_gen_ek_csr_tool.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause + +# Required Python modules: +# sudo apt-get update +# sudo apt-get install python3-pip +# sudo agp-get remove python3-cryptography +# python3 -m pip install asn1crypto (version 1.5.1) +# python3 -m pip install cryptography (version 41.0.1) +# python3 -m pip install ecdsa (version 1.14.0) +# python3 -m pip install numpy (version 1.24.4) +# python3 -m pip install oscrypto (version 1.3.0) +# python3 -m pip install pyaes (version 1.6.1) +# python3 -m pip install pycryptodomex (version 3.19.0) + +import argparse +import os +import textwrap + +from ecdsa import NIST256p +from lib.aes_drbg import AES_DRBG +from lib.ftpm_ek import RSA2K_Gen_Key, EC_Gen_Key +from lib.ftpm_ek_csr import fTPM_Gen_EK_CSR + +class fTPM_EK_CSR_Tool: + def __init__(self, key_type, eps_seed): + _magic_purpose_str = "5072696d617279204f626a656374204372656174696f6e00" + _magic_rsa_name_str = "000b32503929a1287eedaa3e89d932f9b51a6f92abd0fa57721ffa6fc041e04f7498" + _magic_ec_name_str = "000b0f1277a2f3f382e7f75db466fac234182a8d62f97dfbaae7b06fdf52bda51467" + + if key_type == 'rsa' or key_type == 'ec': + self.key_type = key_type + else: + raise Exception("fTPM_Create_EK: Invalid key type!!") + + self.eps = eps_seed + self.drbg = AES_DRBG(256) + + _magic_purpose_hex = bytes.fromhex(_magic_purpose_str) + if key_type == 'rsa': + _magic_name_hex = bytes.fromhex(_magic_rsa_name_str) + elif key_type == 'ec': + _magic_name_hex = bytes.fromhex(_magic_ec_name_str) + + self.drbg.df_instantiate_seeded(self.eps, _magic_purpose_hex, _magic_name_hex) + + if key_type == 'rsa': + rsa_gen_key = RSA2K_Gen_Key(2048, self.drbg.df_drbg_generate) + self.ek_priv_key, self.ek_pub_key = rsa_gen_key.generate_key_pair() + elif key_type == 'ec': + ec_gen_key = EC_Gen_Key(NIST256p, self.drbg.df_drbg_generate) + self.ek_priv_key, self.ek_pub_key = ec_gen_key.gen_ecdsa_keypair_by_extra_random_bits(NIST256p, self.drbg.df_drbg_generate) + + def generate_ek_csr(self, subject_cn, subject_on, subject_Cn, ek_csr_file_name): + ek_csr = fTPM_Gen_EK_CSR(subject_cn, subject_on, subject_Cn, ek_csr_file_name, self.ek_priv_key, self.ek_pub_key) + ek_csr.build_csr() + +def main(): + parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter, + description=textwrap.dedent(''' + fTPM tool creates the EK CSR. + To generate a per-device EK CSR, please follow the input requirements. + * Input: The X.509 common name property. + * Input: The X.509 organization name property. + * Input: The X.509 country name property. + * Input: The serial number. + * Input: The 64 bytes EPS seed in hex format string. + * Output: The prefix of EK CSR file name. This will output the EK CSR files (RSA and EC) in DER format. + ''')) + + parser.add_argument('--out_path', type=str, required=True, help="The output folder of the result.") + + parser.add_argument('--subject_cn', type=str, required=True, help="The subject common name of the CSR.") + parser.add_argument('--subject_on', type=str, required=True, help="The subject organization name of the CSR.") + parser.add_argument('--subject_Cn', type=str, required=True, help="The subject country name of the CSR.") + parser.add_argument('--sn', type=str, required=True, help="The serial number.") + parser.add_argument('--ek_csr', type=str, required=True, help="The prefix of EK CSR file name.") + parser.add_argument('--eps', type=str, required=True, help="The EPS of the fTPM.") + + args = parser.parse_args() + + _eps = bytes.fromhex(args.eps) + if (len(_eps) != 64): + raise Exception("Error: Invalid EPS length.") + + if not os.path.exists(args.out_path): + os.makedirs(args.out_path) + + _ek_key_type_ec = "ec" + _ek_key_type_rsa = "rsa" + + print("[fTPM Gen EK CSR TOOL]: Generating fTPM RSA EK CSR") + ftpm_rsa_ek_csr = fTPM_EK_CSR_Tool(_ek_key_type_rsa, _eps) + ftpm_rsa_ek_csr.generate_ek_csr(args.subject_cn, args.subject_on, args.subject_Cn, args.out_path + "/" + args.ek_csr + "_" + _ek_key_type_rsa + "-" + args.sn + ".der") + + print("[fTPM Gen EK CSR TOOL]: Generating fTPM EC EK CSR") + ftpm_ec_ek_csr = fTPM_EK_CSR_Tool(_ek_key_type_ec, _eps) + ftpm_ec_ek_csr.generate_ek_csr(args.subject_cn, args.subject_on, args.subject_Cn, args.out_path + "/" + args.ek_csr + "_" + _ek_key_type_ec + "-" + args.sn + ".der") + +if __name__ == "__main__": + main() diff --git a/optee/samples/ftpm-helper/host/tool/ftpm_offline_provisioning_verify.sh b/optee/samples/ftpm-helper/host/tool/ftpm_offline_provisioning_verify.sh new file mode 100755 index 0000000..6c16c3f --- /dev/null +++ b/optee/samples/ftpm-helper/host/tool/ftpm_offline_provisioning_verify.sh @@ -0,0 +1,87 @@ +#!/bin/bash + +# Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause + +FTPM_KEYS="ftpm_keys.txt" +CA_APP="nvftpm-helper-app" +RSA_EK_HANDLE="0x81010001" +ECC_EK_HANDLE="0x81010002" +EK_PUBKEY_FTPM="ek_pub_ftpm.key" +EK_PUBKEY_PROVISION="ek_pub_provision.key" + +# Running state +# 0: initial +# 1: read device sn +# 2: read eps +# 3: read rsa EK public key +# 4: read ec EK public key +state=0 +sn="" +eps="" +rsa_ek_pubkey="" +ec_ek_pubkey="" + +while IFS= read -r line; do + if [ -z "${line}" ]; then + echo "Injecting EPS for sn: ${sn}..." + if ${CA_APP} -g "0x${eps}"; then + tpm2_changeeps + else + break + fi + + echo -n "Verifying the RSA EK public key for sn: ${sn}... " + echo -e "${rsa_ek_pubkey}" > ${EK_PUBKEY_PROVISION} + tpm2_createek -c ${RSA_EK_HANDLE} -G rsa -u ${EK_PUBKEY_FTPM} -f pem + if diff -B -Z ${EK_PUBKEY_FTPM} ${EK_PUBKEY_PROVISION} >& /dev/null; then + echo "PASS" + else + echo "FAIL" + break + fi + + echo -n "Verifying the ECC EK public key for sn: ${sn}... " + echo -e "${ec_ek_pubkey}" > ${EK_PUBKEY_PROVISION} + tpm2_createek -c ${ECC_EK_HANDLE} -G ecc -u ${EK_PUBKEY_FTPM} -f pem + if diff -B -Z ${EK_PUBKEY_FTPM} ${EK_PUBKEY_PROVISION} >& /dev/null; then + echo "PASS" + else + echo "FAIL" + break + fi + + state=0 + sn="" + eps="" + rsa_ek_pubkey="" + ec_ek_pubkey="" + continue + fi + + if [ "${line}" == "# device_sn" ]; then + state=1 + continue + fi + if [ "${line}" == "# eps" ]; then + state=2 + continue + fi + if [ "${line}" == "# rsa_ek_pubkey" ]; then + state=3 + continue + fi + if [ "${line}" == "# ec_ek_pubkey" ]; then + state=4 + continue + fi + + case ${state} in + 1) sn="${line}";; + 2) eps="${line}";; + 3) rsa_ek_pubkey="${rsa_ek_pubkey}${line}\n";; + 4) ec_ek_pubkey="${ec_ek_pubkey}${line}\n";; + *) echo "Invalid state found: ${state}."; break;; + esac + +done < "${FTPM_KEYS}" diff --git a/optee/samples/ftpm-helper/host/tool/ftpm_test_local_attestation.sh b/optee/samples/ftpm-helper/host/tool/ftpm_test_local_attestation.sh new file mode 100755 index 0000000..5cc5c0a --- /dev/null +++ b/optee/samples/ftpm-helper/host/tool/ftpm_test_local_attestation.sh @@ -0,0 +1,133 @@ +#!/bin/bash + +# Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause + +set -e + +export TPM2TOOLS_TCTI="device:/dev/tpmrm0" + +AK_OWNER_PW="ak_test" + +AK_ALG="rsa" +HASH_ALG="sha256" +SIGN_ALG="rsassa" +EK_ECC_HANDLE="0x81010002" + +FTPM_TEST_OUTPATH="./ftpm_test_out" + +SCRIPT_NAME="$(basename "${0}")" + +function usage { + cat << EOM +Usage: ./${SCRIPT_NAME} [OPTIONS] + +This script helps to do a local fTPM attestation test. +The required options: + -p The fTPM owner password. (Must) + -h Shows this help. +EOM +} + +function ftpm_attestation_test() { + local _ak_alg=${1} + local _hash_alg=${2} + local _sign_alg=${3} + local _ek_handle=${EK_ECC_HANDLE} + local _ak_ctx="${FTPM_TEST_OUTPATH}/ak.ctx" + local _ak_pub_key_pem="${FTPM_TEST_OUTPATH}/ak_pub_key.pem" + local _ak_pub_key_data="${FTPM_TEST_OUTPATH}/ak_pub_key.dat" + local _ek_pub_key_der="${FTPM_TEST_OUTPATH}/ek_pub_key.der" + local _nonce="${FTPM_TEST_OUTPATH}/nonce_plain" + local _nonce_enc="${FTPM_TEST_OUTPATH}/nonce_encrypted" + local _nonce_dec="${FTPM_TEST_OUTPATH}/nonce_decrypted" + local _sess_ctx="${FTPM_TEST_OUTPATH}/sess.ctx" + local _result="${FTPM_TEST_OUTPATH}/nonce.diff" + local _quote_test1_hash_alg="sha512" + local _quote_test2_hash_alg="sha384" + local _quote_msg="${FTPM_TEST_OUTPATH}/quote.msg" + local _quote_sig="${FTPM_TEST_OUTPATH}/quote.sig" + local _quote_pcr_out="${FTPM_TEST_OUTPATH}/quote_pcr.out" + + echo "[fTPM device]: === local attestation test ===" + echo "[fTPM device]: Creating ${_ak_alg} AK with sign alg ${_sign_alg} for testing." + tpm2_createak -C ${_ek_handle} -c ${_ak_ctx} -G ${_ak_alg} -g ${_hash_alg} -s ${_sign_alg} \ + -f pem -u ${_ak_pub_key_pem} -p ${AK_OWNER_PW} -P ${EK_OWNER_PW} + tpm2_readpublic -c ${_ak_ctx} > ${_ak_pub_key_data} + _ak_name=$(cat ${_ak_pub_key_data} | grep "^name:" | awk '{print $2}'); + + echo "[fTPM device]: Make Credential by ${_ak_alg} EK pub key and associated with AK." + tpm2_readpublic -c ${_ek_handle} -o ${_ek_pub_key_der} > ${_ak_pub_key_data} + tpm2_getrandom -o ${_nonce} 64 + tpm2_makecredential -T none -e ${_ek_pub_key_der} -s ${_nonce} -n ${_ak_name} -o ${_nonce_enc} + + echo "[fTPM device]: Active Credential and verify the result." + tpm2_startauthsession --policy-session -S ${_sess_ctx} -g ${_hash_alg} + tpm2_policysecret -S ${_sess_ctx} -c 0x4000000B ${EK_OWNER_PW} + + tpm2_activatecredential -c ${_ak_ctx} -C ${_ek_handle} -i ${_nonce_enc} -o ${_nonce_dec} -P "session:${_sess_ctx}" -p ${AK_OWNER_PW}; + + tpm2_flushcontext ${_sess_ctx} + + diff ${_nonce} ${_nonce_dec} > ${_result}; sync; + if [ -s ${_result} ]; then + echo "[fTPM device]: local attestation test failed!!" + exti 1 + else + echo "[fTPM device]: local attestation test successed." + fi + + # Empty separator line + echo "" + + echo "[fTPM device]: === local test: Quote verifying PCR SHA512 Bank 0 ===" + echo "[fTPM device]: Client generating quote." + tpm2_quote -c ${_ak_ctx} -l ${_quote_test1_hash_alg}:0 -q ${_nonce} -g ${_hash_alg} -m ${_quote_msg} -s ${_quote_sig} \ + -o ${_quote_pcr_out} -p ${AK_OWNER_PW} + echo "[fTPM device]: Server verifying quote." + tpm2_checkquote -u ${_ak_pub_key_pem} -g ${_hash_alg} -q ${_nonce} -m ${_quote_msg} -s ${_quote_sig} -f ${_quote_pcr_out} + + # Empty separator line + echo "" + + echo "[fTPM device]: === local test: Quote verifying PCR SHA384 Bank 0 ~ 7 ===" + echo "[fTPM device]: Client generating quote." + tpm2_quote -c ${_ak_ctx} -l ${_quote_test2_hash_alg}:0,1,2,3,4,5,6,7 -q ${_nonce} -g ${_hash_alg} -m ${_quote_msg} -s ${_quote_sig} \ + -o ${_quote_pcr_out} -p ${AK_OWNER_PW} + echo "[fTPM device]: Server verifying quote." + tpm2_checkquote -u ${_ak_pub_key_pem} -g ${_hash_alg} -q ${_nonce} -m ${_quote_msg} -s ${_quote_sig} -f ${_quote_pcr_out} + + # Empty separator line + echo "" +} + +if [ "${1}" == "" ]; then + usage + exit 1 +fi + +while getopts "hp:" OPTION +do + case $OPTION in + h) + usage + exit 0 + ;; + p) + EK_OWNER_PW="${OPTARG}" + ;; + *) + usage + exit 1 + ;; + esac +done + +if [ "${EK_OWNER_PW}" == "" ]; then + usage + exit 1 +fi + +mkdir -p ${FTPM_TEST_OUTPATH} + +ftpm_attestation_test "${AK_ALG}" "${HASH_ALG}" "${SIGN_ALG}" diff --git a/optee/samples/ftpm-helper/host/tool/kdk_gen.py b/optee/samples/ftpm-helper/host/tool/kdk_gen.py new file mode 100755 index 0000000..e3d4536 --- /dev/null +++ b/optee/samples/ftpm-helper/host/tool/kdk_gen.py @@ -0,0 +1,267 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause + +import argparse +import csv +import os,binascii +import errno +from cryptography.hazmat.primitives import hmac, hashes +from cryptography.hazmat.primitives.kdf import kbkdf +from cryptography.hazmat.backends import default_backend +from ecdsa import NIST256p, SigningKey +from lib.aes_drbg import AES_DRBG +from lib.silicon_id_csr import Device_Gen_Silicon_ID_CSR + +def encode(data: str, is_hex: bool, desc: str) -> bytes: + encoded_str = b"\x00" + if is_hex: + # Convert hex string to bytes + try: + encoded_str = bytes.fromhex(data) + except ValueError as e: + raise ValueError("Assumed hex=True, but {}:{} is invalid hex!".format(desc, e)) from e + else: + # Encode as ASCII bytes + try: + encoded_str = data.encode("ascii") + except UnicodeError as e: + raise ValueError("Assumed hex=False, but {}:{} is invalid ASCII!".format(desc, e)) from e + return encoded_str + +def kdf(kdk: bytes, label: bytes, context: bytes, L: int = 256, rlen: int = 32, order = None) -> bytes: + """Derive KDF from root key and NIST SP800-108 input (label and context).""" + if not context: + context = b"\x00" + + if order is None: + order = kbkdf.CounterLocation.BeforeFixed + + hkdf = kbkdf.KBKDFHMAC( + algorithm=hashes.SHA256(), + mode=kbkdf.Mode.CounterMode, + length=L // 8, + rlen=rlen // 8, + llen=4, + location=order, + label=label, + context=context, + fixed=None, + backend=default_backend(), + ) + return hkdf.derive(kdk) + +# This function uses the algorithm defined in NIST SP800-56Ar3, +# 5.6.1.2.2 Key Pair Generation by Testing Candidates, +# to generate an ECDSA private key from a given seed +def gen_ecdsa_private_key(seed: bytes): + if seed is None: + raise ValueError("No seed is provided when generating ECDSA private key!") + + drbg = AES_DRBG(256) + # For AES-256 CTR-DRBG, the seed size is 48 bytes + # Refer to NIST SP800-90Ar1, 10.2.1 CTR_DRBG + if len(seed) < 48: + seed = seed + b"\x00" * (48 - len(seed)) + drbg.instantiate(seed) + + retries = 100 + i = 0 + while True: + key = drbg.generate(64) + key = key[0:32] + int_key = int.from_bytes(key, "big") + if int_key > 0 and int_key < NIST256p.order: + # print("An ECDSA private key is generated: " + key.hex() + ". Rounds: " + str(i + 1)) + break + + i += 1 + if i >= retries: + return b'' + + return key + +def convert_sn_endian(sn: bytes) -> bytes: + # The device SN is 10 bytes, and has the format: + # + # oem_id is stored in fuse "odm_info" which is a 4-byte fuse + # All 4-byte or less Tegra fuses are stored in little-endian so we need + # to convert the endian of oem_id in device SN before doing the key calculation + # The left 8 bytes don't have an endian issue - it is big-endian everywhere + result = bytearray(sn) + result[0] = sn[1] + result[1] = sn[0] + return bytes(result) + +def gen_silicon_id_pubkey_and_csr(kdk: str, sn: bytes, gen_csr: bool, + csr_common_name: str, csr_org_name: str, csr_country_name: str): + # Prepare the SILICON ID key pair + kdk_nrk = kdf(encode(kdk, True, "KDK"), encode("NRK", False, "Label"), encode("00", True, "Context")) + silicon_id = kdf(kdk_nrk, encode("ECA_SEED", False, "Label"), convert_sn_endian(sn)) + + silicon_id_asym_origin = kdf(silicon_id, encode("Asym", False, "Label"), + encode("00", True, "Context")) + hm = hmac.HMAC(silicon_id_asym_origin, hashes.SHA256(), backend=default_backend()) + hm.update("Asym".encode(encoding="utf8")) + silicon_id_asym = hm.finalize() + + ecdsa_key = gen_ecdsa_private_key(silicon_id_asym) + if len(ecdsa_key) == 0: + return "" + silicon_id_private_key = SigningKey.from_string(ecdsa_key, curve=NIST256p) + silicon_id_public_key = silicon_id_private_key.get_verifying_key() + # print("Silicon ID private key: \n" + silicon_id_private_key.to_pem().decode("ascii")) + # print("Silicon ID public key: \n" + silicon_id_public_key.to_pem().decode("ascii")) + + if not gen_csr: + return silicon_id_public_key.to_string().hex() + else: + silicon_id_csr = Device_Gen_Silicon_ID_CSR(csr_common_name, csr_org_name, csr_country_name, + silicon_id_private_key.to_der(), + silicon_id_public_key.to_der()) + return silicon_id_public_key.to_string().hex(), silicon_id_csr.build_csr() + +def clean(input): + tmpFile = "tmp.csv" + with open(input, "r") as file, open(tmpFile, "w") as outFile: + reader = csv.reader(file, delimiter=' ') + writer = csv.writer(outFile, delimiter=' ') + for row in reader: + colValues = [] + for col in row: + colValues.append(col.lower()) + del colValues[-1] + writer.writerow(colValues) + os.rename(tmpFile, input) + +def get_device_sn(oem_id: int, sn: int) -> bytes: + device_sn = oem_id.to_bytes(2, "big") + sn_high = (sn >> 32).to_bytes(4, "big") + sn_low = (sn & 0xffffffff).to_bytes(4, "big") + device_sn += sn_high + device_sn += sn_low + return device_sn + +def main(): + parser = argparse.ArgumentParser(description='The KDK db generation tool.') + parser.add_argument('--oem_id', help='The ID of the OEM vendor. A positive 16-bit integer in hex format') + parser.add_argument('--sn', help='The beginning of device serial number. A positive 64-bit unsigned integer in hex format') + parser.add_argument('--num_devices', type=int, help='the number of devices') + parser.add_argument("--destroy", action='store', help='destroy the kdk database') + parser.add_argument("--preset", help='use the preset KDK database(for testing purpose only)') + parser.add_argument("--prov_mode", type=str, default="offline", help="The fTPM provisioning mode (offline or online). The default is offline.") + parser.add_argument("--silicon_id_csr_cn", type=str, default="Silicon-ID-ECA", help="The common name of the Silicon ID CSR (Certificate Signing Request).") + parser.add_argument("--silicon_id_csr_og", type=str, default="fTPM Corp", help="The organization name of the Silicon ID CSR (Certificate Signing Request).") + parser.add_argument("--silicon_id_csr_Cn", type=str, default="US", help="The country name of the Silicon ID CSR (Certificate Signing Request).") + + args = parser.parse_args() + if args.destroy != None and (args.oem_id or args.sn): + parser.print_help() + return + + if not (args.destroy or args.oem_id or args.sn or args.num_devices): + parser.print_help() + return + + if not args.destroy: + if not args.oem_id.lower().startswith("0x") or not args.sn.lower().startswith("0x"): + raise ValueError("parameter in hex format needs to start with \"0x\"") + args.oem_id = int(args.oem_id, 16) + args.sn = int(args.sn, 16) + if args.oem_id < 0 or args.oem_id.bit_length() > 16: + raise ValueError("oem_id must be a 16-bit integer") + if args.sn < 0 or args.sn.bit_length() > 64: + raise ValueError("sn must be a 64-bit integer") + if args.preset != None and not os.path.isfile(args.preset): + raise ValueError("Invalid preset KDK database") + + if args.destroy: + clean(args.destroy) + return + + # OEM_ID: + # Starting device SN: + # Num_devices: + output_dir="ftpm_kdk" + if not os.path.exists(output_dir): + try: + os.makedirs(output_dir) + except OSError as e: + if e.errno != errno.EEXIST: + raise e + elif not os.path.isdir(output_dir): + print(str(output_dir) + " is not a directory or does not exist") + raise NotADirectoryError + elif not os.access(output_dir, os.W_OK): + print("Write access denied on ", output_dir) + raise PermissionError + + preset_kdks = [] + if args.preset != None: + with open(args.preset, 'r') as file: + preset_kdks = file.readlines() + if len(preset_kdks) != args.num_devices: + raise ValueError("The number of preset KDKs is not equal to the number of devices") + + for i in range(0, len(preset_kdks)): + device_kdk = preset_kdks[i].strip() + if device_kdk.startswith("0x") or device_kdk.startswith("0X"): + device_kdk = device_kdk[2:] + if len(device_kdk) != 64: + raise ValueError("Invalid preset KDK@" + str(i + 1) + " found: " + preset_kdks[i]) + preset_kdks[i] = device_kdk + + device_sn = get_device_sn(args.oem_id, args.sn) + kdkfilename='ftpm_kdk/kdk_db_{}-{}-{}.csv'.format(device_sn.hex()[:4], device_sn.hex()[4:], args.num_devices) + pubkeyfilename='ftpm_kdk/pubkey_db_{}-{}-{}.csv'.format(device_sn.hex()[:4], device_sn.hex()[4:], args.num_devices) + if (args.prov_mode == "online"): + # Add Silicon ID CSR DB for online provisioning mode + silicon_id_csr_filename = 'ftpm_kdk/silicon_id_csr_db_{}-{}-{}.csv'.format(device_sn.hex()[:4], device_sn.hex()[4:], args.num_devices) + silicon_id_csr_file = open(silicon_id_csr_filename, "w", newline='') + silicon_id_csr_writer = csv.writer(silicon_id_csr_file, delimiter=' ', quotechar='|', quoting=csv.QUOTE_MINIMAL) + + with open(kdkfilename, 'w', newline='') as kdkfile, open(pubkeyfilename, 'w', newline='') as pubkeyfile: + writer = csv.writer(kdkfile, delimiter=' ', + quotechar='|', quoting=csv.QUOTE_MINIMAL) + pubkeywriter=csv.writer(pubkeyfile, delimiter=' ', + quotechar='|', quoting=csv.QUOTE_MINIMAL) + + for i in range(0, args.num_devices): + if len(preset_kdks) > 0: + device_kdk = preset_kdks[i] + else: + device_kdk = binascii.b2a_hex(os.urandom(32)).decode() + + # The device SN is 10 bytes: + # OEM_ID is burnt into the fuse ODM_INFO + # High 32 bits of SN is burnt into the fuse ODM_ID0 + # Low 32 bits of SN is burnt into the fuse ODM_ID1 + device_sn = get_device_sn(args.oem_id, args.sn + i) + + while True: + if (args.prov_mode == "online"): + silicon_id_csr_cn = '{}_{}'.format(device_sn.hex(), args.silicon_id_csr_cn) + device_pubkey, silicon_id_csr = gen_silicon_id_pubkey_and_csr(device_kdk, device_sn, True, + silicon_id_csr_cn, + args.silicon_id_csr_og, + args.silicon_id_csr_Cn) + else: + device_pubkey = gen_silicon_id_pubkey_and_csr(device_kdk, device_sn, False, "", "", "") + + if len(device_pubkey) == 0: + print("Generate ECDSA key pair using KDK: " + device_kdk + " failed. Will start over.") + device_kdk = binascii.b2a_hex(os.urandom(32)).decode() + else: + break + + writer.writerow(["{}".format(device_sn.hex()[:4]), + "{}".format(device_sn.hex()[4:]), device_kdk]) + pubkeywriter.writerow(["{}".format(device_sn.hex()[:4]), + "{}".format(device_sn.hex()[4:]), device_pubkey]) + if (args.prov_mode == "online"): + silicon_id_csr_writer.writerow(["{}".format(device_sn.hex()[:4]), + "{}".format(device_sn.hex()[4:]), silicon_id_csr]) + +if __name__ == '__main__': + main() diff --git a/optee/samples/ftpm-helper/host/tool/lib/aes_drbg.py b/optee/samples/ftpm-helper/host/tool/lib/aes_drbg.py new file mode 100644 index 0000000..e82d693 --- /dev/null +++ b/optee/samples/ftpm-helper/host/tool/lib/aes_drbg.py @@ -0,0 +1,435 @@ +#MIT License + +#Copyright (c) 2019 Samuele Cornell +# Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: MIT + +#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. + +# The AES DRBG source refers to the link below. +# https://github.com/popcornell/pyAES_DRBG +# To support derivation function based DRBG same as fTPM implementation below. +# https://github.com/microsoft/ms-tpm-20-ref/blob/main/TPMCmd/tpm/src/crypt/CryptRand.c +# This implementation adds extra functions to support that. + +import pyaes +import struct +import numpy as np + +class AES_DRBG(object): + """AES based DRBG class compliant with SP-900 80A NIST standard. + This implementation follows closely the above Specification in order to be as clear as possible. + + Constructor requires only the specification of the desired AES version (128/192 or 256 Keylen): + + Parameters + ---------- + keylen : keylength in bits for AES block cipher used in the DRBG + + Returns + ------- + drbg_object + + + The DRBG has 3 main methods: + + 1 INSTANTIATE: initialize and instantiate the DRBG + 2 RESEED: reseed the DRBG (this must be done every 2**48 calls) + 3 GENERATE obtain pseudo-random bits from DRBG + + """ + + def __init__(self, keylen): + + self.keylen = keylen + + self.reseed_counter = 0 + self.key = False + self.V = False + + self.outlen = 16 # same for all + + if keylen == 256: + self.seedlen = 48 + self.keylen = 32 + + + elif keylen == 192: + self.seedlen = 40 + self.keylen = 24 + + elif keylen == 128: + self.seedlen = 32 + self.keylen = 16 + + + else: + raise ValueError("Keylen not supported") + + self.reseed_interval = 2 ** 48 # same for all + + def instantiate(self, entropy_in, per_string=b''): + ''' + Method handling initialization of the DRBG (see Specification) + + Parameters + ---------- + entropy_in : hex byterray (e.g. \xFF\xF1....etc (len = seedlen_bits /8)) + full entropy seed for DRBG, it must be seedlen bits + + per_string : hex byterray (e.g. \xFF\xF1....etc (len must be less or equal seedlen)) + additional input which will be xored with the input entropy for added security (optional) + + Returns + ------- + + + ''' + + if len(per_string) != 0: + + temp = len(per_string) # NB len is in bytes + + if temp < self.seedlen: + + per_string = per_string + b"\x00" * (self.seedlen - temp) # pad + + else: + + raise ValueError("Length of personalization string must be equal or less than seedlen") + + else: + + per_string = b"\x00" * self.seedlen + + seed_material = int(entropy_in.hex(), 16) ^ int(per_string.hex(), 16) + seed_material = seed_material.to_bytes(self.seedlen, byteorder='big', signed=False) + + self.key = b"\x00" * self.keylen + self.V = b"\x00" * self.outlen + + self.aes = pyaes.AESModeOfOperationECB(self.key) + + self._update(seed_material) + + self.reseed_counter = 1 + + def _update(self, provided_data): + ''' + DRBG internal Update function (see Specification) + + Parameters + ---------- + provided_data : hex byterray (e.g. \xFF\xF1....etc (len = seedlen_bits /8)) + input data to the update function (it is ensured in other methods is seedlen bits) + + + Returns + ------- + + ''' + + temp = b"" + + while (len(temp) < self.seedlen): + # increment V + self.V = (int(self.V.hex(), 16) + 1) % 2 ** (self.outlen * 8) + self.V = self.V.to_bytes(self.outlen, byteorder='big', signed=False) + + output_block = self.aes.encrypt(self.V) # generate keystream + + temp = temp + output_block # concat keystream + + temp = temp[0:self.seedlen] + + temp = int(temp.hex(), 16) ^ int(provided_data.hex(), 16) # xor keystream + temp = temp.to_bytes(self.seedlen, byteorder='big', signed=False) + + self.key = temp[0:self.keylen] + + self.V = temp[-self.outlen:] + + self.aes = pyaes.AESModeOfOperationECB(self.key) # update the key + + def reseed(self, entropy_in, add_in=b''): + + ''' + DRBG Reseed function (see Specification) + Similar to instantiate except the previous DRBG state (self.key, self.V, self.reseed_counter) is + preserved and updated with full entropy. + + Parameters + ---------- + entropy_in : hex byterray (e.g. \xFF\xF1....etc (len = seedlen_bits /8)) + full entropy seed for DRBG, it must be seedlen bits + + add_in : hex byterray (e.g. \xFF\xF1....etc (len must be less or equal seedlen)) + additional input which will be xored with the input entropy for added security (optional) + + Returns + ------- + ''' + + if len(add_in) != 0: + + temp = len(add_in) # NB len is in bytes + + if temp < self.seedlen: + + add_in = add_in + b"\x00" * (self.seedlen - temp) # pad + + else: + + raise ValueError("Length of personalization string must be equal or less than seedlen") + + else: + + add_in = b"\x00" * self.seedlen + + seed_material = int(entropy_in.hex(), 16) ^ int(add_in.hex(), 16) + seed_material = seed_material.to_bytes(self.seedlen, byteorder='big', signed=False) + + self._update(seed_material) + + self.reseed_counter = 1 + + def generate(self, req_bytes, add_in=b''): + ''' DRBG Generate Funtion (see Specification) + returns req_bytes pseudo-random bits from the DRBG + + Parameters + ---------- + req_bytes : int + number of bytes requested from the DRBG + + add_in : hex byterray (e.g. \xFF\xF1....etc (len must be less or equal seedlen)) + additional input which will be xored with the output of DRBG (optional) + + Returns + ------- + returned_bytes: hex byterray (e.g. \xFF\xF1....etc (len is req_bytes)) + pseudo-random bytes from DRBG ready to be used in whatever application + + ''' + + if self.reseed_counter > self.reseed_interval: + raise Warning("the DBRG should be reseeded !!!") + + if len(add_in) != 0: + + temp = len(add_in) + + if temp < self.seedlen: + add_in = add_in + b"\x00" * (temp - self.seedlen) + + self._update(add_in) + else: + + add_in = b"\x00" * self.seedlen + + temp = b'' + + while (len(temp) < req_bytes): + self.V = (int(self.V.hex(), 16) + 1) % 2 ** (self.outlen * 8) + self.V = self.V.to_bytes(self.outlen, byteorder='big', signed=False) + + output_block = self.aes.encrypt(self.V) + + temp = temp + output_block + + returned_bytes = temp[0:req_bytes] + + self._update(add_in) + + self.reseed_counter = self.reseed_counter + 1 + + return returned_bytes + + def _df_end(self): + ''' + Return the result of the derivation function computation. + ''' + # Padding the final input data + self.df_result_seed = bytearray(self.seedlen) + self.df_buf[self.df_contents] = 0x80 + self.df_contents += 1 + + while (self.df_contents < self.df_iv_size): + self.df_buf[self.df_contents] = 0x0 + self.df_contents += 1 + + self._df_compute() + + # Update the final result + _seed_idx = 0 + for i in range(self.df_count): + _iv_temp = np.array(self.df_iv[i][0:self.df_iv_size], dtype = '>B') + _iv_temp = _iv_temp.tobytes() + + self.df_result_seed[_seed_idx:(_seed_idx + self.df_iv_size)] = _iv_temp[:] + _seed_idx += self.df_iv_size + + return self.df_result_seed + + def _df_update(self, data, size): + ''' + Update the derivation function with the input data. + ''' + _data_idx = 0 + + while (size > 0): + _to_fill = self.df_iv_size - self.df_contents + + if (size < _to_fill): + _to_fill = size + + self.df_buf[self.df_contents:(self.df_contents + _to_fill)] = data[_data_idx:(_data_idx + _to_fill)] + + size -= _to_fill + _data_idx += _to_fill + + self.df_contents += _to_fill + if (self.df_contents == self.df_iv_size): + self._df_compute() + + def _df_compute(self): + ''' + Update the derivation function. + ''' + _temp = bytearray(self.df_iv_size) + # Incremental update the DF IV + for i in range(self.df_count): + + _iv_temp = np.array(self.df_iv[i][0:self.df_iv_size], dtype = '>B') + _iv_temp = _iv_temp.tobytes() + + _iv_xor = bytes([_a ^ _b for _a, _b in zip(self.df_buf, _iv_temp)]) + _iv_xor = bytes([_a ^ _b for _a, _b in zip(_iv_xor, _temp)]) + + _iv_update = self.df_aes.encrypt(_iv_xor) + + _temp = _iv_xor + for j in range(self.df_iv_size): + self.df_iv[i][j] = _iv_update[j] + + self.df_buf = bytearray(self.df_iv_size) + self.df_contents = 0 + + def _df_start(self, input_len): + ''' + Initialize the derivation function. + ''' + self.df_count = 3 + self.dfkey_len = self.keylen + self.dfkey = bytearray(self.keylen) + self.df_iv_size = 16 + self.df_iv = np.zeros((self.df_count, self.df_iv_size)) + self.df_buf = bytearray(self.df_iv_size) + + # Set up the DF key + for i in range(self.dfkey_len): + self.dfkey[i] = i + + self.df_aes = pyaes.AESModeOfOperationECB(self.dfkey) + + # Create the first chaining value + for i in range(self.df_count): + self.df_iv[i][3] = i + + self._df_compute() + + # Initialize the first 64 bits of the IV + _init = struct.pack(">II", input_len, self.seedlen) + for i in range(len(_init)): + self.df_iv[0][i] = _init[i] + + self.df_contents = 4 + + def _df_encrypt_drbg(self, req_bytes, iv): + _temp = b"" + + while (len(_temp) < req_bytes): + iv = (int(iv.hex(), 16) + 1) + iv = iv.to_bytes(self.outlen, byteorder='big') + + _output_block = self.df_aes.encrypt(iv) + + _temp = _temp + _output_block + + _returned_bytes = _temp[0:req_bytes] + + return _returned_bytes, iv + + def _df_drbg_update(self, refresh_key, provided_data = b""): + _df_drbg_key = bytearray(self.keylen) + _df_drbg_iv = bytearray(self.df_iv_size) + + if (refresh_key): + self.df_aes = pyaes.AESModeOfOperationECB(_df_drbg_key) + else: + _df_drbg_iv[0:self.df_iv_size] = self.df_drbg_seed[self.keylen:] + + _df_drbg_temp, _df_drbg_updated_iv = self._df_encrypt_drbg(self.seedlen, _df_drbg_iv) + + if (len(provided_data) > 0): + _df_drbg_result = bytes([_a ^ _b for _a, _b in zip(_df_drbg_temp, provided_data)]) + self.df_drbg_seed[:] = _df_drbg_result[:] + else: + self.df_drbg_seed[:] = _df_drbg_temp[:] + + def _df_drbg_reseed(self): + self._df_drbg_update(True, self.df_result_seed) + self.df_reseed_counter = 1 + + def df_instantiate_seeded(self, seed, purpose, name): + ''' + Function to instantiate the RNG from seed values. + ''' + if self.keylen != 32 and self.seedlen != 48: + raise Exception("Invalid key len for DF DRBG (Only support 256-bit key).") + + self.df_drbg_seed = bytearray(self.seedlen) + total_len = len(seed) + len(purpose) + len(name) + + self._df_start(total_len) + self._df_update(seed, len(seed)) + self._df_update(purpose, len(purpose)) + self._df_update(name, len(name)) + self._df_end() + + self._df_drbg_reseed() + + def df_drbg_generate(self, req_bytes): + ''' + Function to generate random bytes. + ''' + _df_drbg_key = bytearray(self.keylen) + _df_drbg_iv = bytearray(self.df_iv_size) + _df_drbg_key[0:self.keylen] = self.df_drbg_seed[0:self.keylen] + _df_drbg_iv[0:self.df_iv_size] = self.df_drbg_seed[self.keylen:] + + self.df_aes = pyaes.AESModeOfOperationECB(_df_drbg_key) + + _df_drbg_gen_result, _df_drbg_update_iv = self._df_encrypt_drbg(req_bytes, _df_drbg_iv) + + self.df_drbg_seed[self.keylen:] = _df_drbg_update_iv[0:self.df_iv_size] + + self._df_drbg_update(False) + + return _df_drbg_gen_result diff --git a/optee/samples/ftpm-helper/host/tool/lib/ftpm_ek.py b/optee/samples/ftpm-helper/host/tool/lib/ftpm_ek.py new file mode 100644 index 0000000..58ae567 --- /dev/null +++ b/optee/samples/ftpm-helper/host/tool/lib/ftpm_ek.py @@ -0,0 +1,676 @@ +# Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause + +from Cryptodome.PublicKey.RSA import RsaKey +from Cryptodome.Math.Numbers import Integer +from ecdsa import SigningKey, util +import numpy as np + +class EC_Gen_Key: + def __init__(self, curve, rand_func): + self.curve = curve + self.rand_rand_func = rand_func + + # This function uses the method defined in FIPS 186-4, + # section B.4.1 Key Pair Generation Using Extra Random Bits, + # to generate an ECDSA private key. + def gen_ecdsa_keypair_by_extra_random_bits(self, curve, rand_func): + _req_seed_len = util.orderlen(curve.order) + 8 + + _extra_random = rand_func(_req_seed_len) + _minus_1 = curve.order - 1 + _extra_random = int(_extra_random.hex(), 16) % _minus_1 + _d = _extra_random + 1 + _d_hex = _d.to_bytes(util.orderlen(curve.order), byteorder='big') + + _ec_priv_key = SigningKey.from_string(_d_hex, curve) + _ec_pub_key = _ec_priv_key.get_verifying_key() + + return _ec_priv_key.to_der(), _ec_pub_key.to_der() + +class RSA2K_Gen_Key: + def __init__(self, key_len_bits, rand_func): + self.exponent = 65537 + self.rand_func = rand_func + self.key_size_in_bits = key_len_bits + + def generate_key_pair(self): + q = Integer(0) + e = Integer(self.exponent) + + for (_trial) in range(100): + # Get p and q + p = self._generate_prime() + + p = Integer.from_bytes(p) + + if (q == 0): + q = p + continue + + if (p > q): + d = p - q + else: + d = q - p + + def _Msb(data): + ret = -1 + _temp = int(data.hex(), 16) + if (_temp & 0xffff0000): + ret += 16 + _temp >>= 16 + if (_temp & 0x0000ff00): + ret += 8 + _temp >>= 8 + if (_temp & 0x000000f0): + ret += 4 + _temp >>= 4 + if (_temp & 0x0000000c): + ret += 2 + _temp >>= 2 + if (_temp & 0x00000002): + ret += 1 + _temp >>= 1 + return (ret + _temp) + + _pq_sub = d.to_bytes(d.size_in_bytes(), 'big') + _pq_sub_msw = bytearray(4) + _pq_sub_msw[:] = _pq_sub[0:4] + _pq_sub_msb = _Msb(_pq_sub_msw) + ((d.size_in_bytes() // 4) - 1) * 32 + + if (_pq_sub_msb < 100): + continue + else: + break + + n = p * q + lcm = (p - 1).lcm(q - 1) + d = e.inverse(lcm) + + if (p > q): + p, q = q, p + + u = p.inverse(q) + + self.rsa_key = RsaKey(n = n, e = e, d = d, p = p, q = q, u = u) + + return self.rsa_key.export_key(format='DER'), self.rsa_key.public_key().export_key(format='DER') + + def _generate_prime(self): + _found = False + _random_in_bytes = ((self.key_size_in_bits // 2) + 7) >> 3 + + while (not _found): + _prime = self.rand_func(_random_in_bytes) + _prime = self._adjust_prime_candidate(_prime) + _found, _prime = self._prime_select_with_sieve(_prime) + + return _prime + + def _adjust_prime_candidate(self, prime): + _msw = bytearray(4) + _adjusted_prime = bytearray(len(prime)) + + _adjusted_prime[:] = prime[:] + _msw[:] = prime[0:4] + _msw = int(_msw.hex(), 16) + _adjusted = (_msw >> 16) * 0x4AFB + _adjusted += ((_msw & 0xFFFF) * 0x4AFB) >> 16 + _adjusted += 0xB5050000 + _adjusted = _adjusted.to_bytes(4, 'big') + _adjusted_prime[0:4] = _adjusted[0:4] + _adjusted_prime[len(_adjusted_prime) - 1] |= 1 + + return _adjusted_prime + + def _prime_select_with_sieve(self, candidate): + _first = bytearray(4) + _first[:] = candidate[(len(candidate) - 4):len(candidate)] + _first = (int(_first.hex(), 16) | 0x80000000).to_bytes(4, 'big') + + self.prime_markers_count = 6 + self.prime_markers = (8167, 17881, 28183, 38891, 49871, 60961) + _requested_primes = 4096 # ues the first 4k primes + _requested_primes = (_requested_primes - 1) / 1024 + self.prime_limit = self.prime_markers[int(_requested_primes)] + self.prime_limit >>= 1 + + candidate = self._prime_sieve(candidate) + _candidate_int = int(candidate.hex(), 16) + + _ones = self.bits_in_field_after_sieve + + while (_ones > 0): + _n = (int(_first.hex(), 16) % _ones) + 1 + _chosen = self._find_nth_set_bit(_n) + + # Set the trial prime + _test = _candidate_int + (_chosen * 2) + _mod_e = _test % self.exponent + + if ((_mod_e != 0) and (_mod_e != 1)): + if (self._miller_rabin_test(_test)): + return True, _test.to_bytes(len(candidate), 'big') + + self._clear_bit_in_field(_chosen) + _ones -= 1 + + return False, candidate + + def _prime_sieve(self, candidate): + _candidate_int = int(candidate.hex(), 16) + self.field = bytearray(2048) + _field_size = len(self.field) + _field_size_in_bits = _field_size * 8 + _seed_values_size = len(seed_values) + _sieve_marks = np.array([[31, 7], # prime, count + [73, 5], + [241, 4], + [1621, 3], + [65535, 2]]) + + _adjust = _candidate_int % 105 + if (_adjust & 1): + _adjust += 105 + _candidate_int -= _adjust + + _i = _field_size + _idx = 0 + while (_i >= _seed_values_size ): + self.field[(_idx):(_idx + _seed_values_size)] = seed_values[:_seed_values_size] + _idx += _seed_values_size + _i -= _seed_values_size + + if (_i != 0): + self.field[(_idx):(_idx + _i)] = seed_values[:_i] + + def next_prime(last_prime): + if (last_prime == 0): + return 0 + last_prime >>= 1 + last_prime += 1 + while (last_prime <= self.prime_limit): + if (((prime_table[last_prime >> 3] >> (last_prime & 0x7)) & 1) == 1): + return ((last_prime << 1) + 1) + last_prime += 1 + return 0 + + _iter = 7 + _mark = 0 + _count = _sieve_marks[_mark][1] + _stop = _sieve_marks[_mark][0] + _list = np.arange(8, dtype = np.uintc) + + _done = False + _iter = next_prime(_iter) + _composite = _iter + + while (_composite != 0): + _next = 0 + i = int(_count) + _list[i] = _composite + + i -= 1 + + while (i > 0): + _iter = next_prime(_iter) + _next = _iter + _list[i] = _next + + if (_next != 0): + _composite *= _next + i -= 1 + + _composite = _candidate_int % _composite + + i = int(_count) + while (i > 0): + _next = _list[i] + if (_next == 0): + _done = True + break + + _r = _composite % _next + + if (_r & 1): + _j = (_next - _r) // 2 + elif (_r == 0): + _j = 0 + else: + _j = _next - (_r // 2) + + while (_j < _field_size_in_bits): + self._clear_bit_in_field(_j) + _j += _next + + i -= 1 + + if (_done): + break + + if (_next >= _stop): + _mark += 1 + _count = _sieve_marks[_mark][1] + _stop = _sieve_marks[_mark][0] + + _iter = next_prime(_iter) + _composite = _iter + + + self.bits_in_field_after_sieve = bin(int(self.field.hex(), 16)).count("1") + + return _candidate_int.to_bytes(len(candidate), 'big') + + def _clear_bit_in_field(self, bit_num): + self.field[bit_num >> 3] &= ~(1 << (bit_num & 7)) + + def _find_nth_set_bit(self, n): + _i = 0 + _sum = 0 + _ret_value = 0 + _bits_in_nibble = bytearray([0x00, 0x01, 0x01, 0x02, + 0x01, 0x02, 0x02, 0x03, + 0x01, 0x02, 0x02, 0x03, + 0x02, 0x03, 0x03, 0x04]) + + def bits_in_byte(byte): + return (_bits_in_nibble[byte & 0xf] + _bits_in_nibble[((byte >> 4) & 0xf)]) + + while ((_i < len(self.field)) and (_sum < n)): + _sum += bits_in_byte(self.field[_i]) + _i += 1 + + _i -= 1 + _ret_value = _i * 8 - 1 + _sel = self.field[_i] + _sum -= bits_in_byte(_sel) + + while ((_sel != 0) and (_sum != n)): + if (_sel & 1): + _sum += 1 + _ret_value += 1 + _sel >>= 1 + + return _ret_value + + # Miller Rabin test from FIPS 186-3 + def _miller_rabin_test(self, test): + _iter = 5 # for RSA 2K + _wm1 = test - 1 + + # _m = _wm1 / 2^_a + _m = Integer(_wm1) + _a = 0 + while _m.is_even(): + _m >>= 1 + _a += 1 + + _m = int(_m.to_bytes().hex(), 16) + _w_len = test.bit_length() + + for _i in range(_iter): + + _fit_random_range = False + while (not _fit_random_range): + _b = self.rand_func(int(_w_len / 8)) + if (not ((int(_b.hex(), 16) <= 1) or (int(_b.hex(), 16) >= _wm1))): + _fit_random_range = True + + _b = int(_b.hex(), 16) + + # _z = _b^_m mod test + _z = pow(_b, _m, test) + if _z in (1, _wm1): + continue + + _j = 1 + while (_j < _a): + # _z = _z^2 mod test + _z = pow(_z, 2, test) + _j += 1 + if _z == _wm1: + break + if _z == 1: + return False + else: + return False + + return True + +# The tables refer to the official TPM 2.0 reference implementation to +# implement the same RSA key generation function. +# https://github.com/microsoft/ms-tpm-20-ref/blob/main/TPMCmd/tpm/src/crypt/CryptPrimeSieve.c +# https://github.com/microsoft/ms-tpm-20-ref/blob/main/TPMCmd/tpm/src/crypt/PrimeData.c + +seed_values = ( + 0x16, 0x29, 0xcb, 0xa4, 0x65, 0xda, 0x30, 0x6c, 0x99, 0x96, + 0x4c, 0x53, 0xa2, 0x2d, 0x52, 0x96, 0x49, 0xcb, 0xb4, 0x61, + 0xd8, 0x32, 0x2d, 0x99, 0xa6, 0x44, 0x5b, 0xa4, 0x2c, 0x93, + 0x96, 0x69, 0xc3, 0xb0, 0x65, 0x5a, 0x32, 0x4d, 0x89, 0xb6, + 0x48, 0x59, 0x26, 0x2d, 0xd3, 0x86, 0x61, 0xcb, 0xb4, 0x64, + 0x9a, 0x12, 0x6d, 0x91, 0xb2, 0x4c, 0x5a, 0xa6, 0x0d, 0xc3, + 0x96, 0x69, 0xc9, 0x34, 0x25, 0xda, 0x22, 0x65, 0x99, 0xb4, + 0x4c, 0x1b, 0x86, 0x2d, 0xd3, 0x92, 0x69, 0x4a, 0xb4, 0x45, + 0xca, 0x32, 0x69, 0x99, 0x36, 0x0c, 0x5b, 0xa6, 0x25, 0xd3, + 0x94, 0x68, 0x8b, 0x94, 0x65, 0xd2, 0x32, 0x6d, 0x18, 0xb6, + 0x4c, 0x4b, 0xa6, 0x29, 0xd1 +) + +prime_table = ( + 0x6e, 0xcb, 0xb4, 0x64, 0x9a, 0x12, 0x6d, 0x81, 0x32, 0x4c, 0x4a, 0x86, 0x0d, + 0x82, 0x96, 0x21, 0xc9, 0x34, 0x04, 0x5a, 0x20, 0x61, 0x89, 0xa4, 0x44, 0x11, + 0x86, 0x29, 0xd1, 0x82, 0x28, 0x4a, 0x30, 0x40, 0x42, 0x32, 0x21, 0x99, 0x34, + 0x08, 0x4b, 0x06, 0x25, 0x42, 0x84, 0x48, 0x8a, 0x14, 0x05, 0x42, 0x30, 0x6c, + 0x08, 0xb4, 0x40, 0x0b, 0xa0, 0x08, 0x51, 0x12, 0x28, 0x89, 0x04, 0x65, 0x98, + 0x30, 0x4c, 0x80, 0x96, 0x44, 0x12, 0x80, 0x21, 0x42, 0x12, 0x41, 0xc9, 0x04, + 0x21, 0xc0, 0x32, 0x2d, 0x98, 0x00, 0x00, 0x49, 0x04, 0x08, 0x81, 0x96, 0x68, + 0x82, 0xb0, 0x25, 0x08, 0x22, 0x48, 0x89, 0xa2, 0x40, 0x59, 0x26, 0x04, 0x90, + 0x06, 0x40, 0x43, 0x30, 0x44, 0x92, 0x00, 0x69, 0x10, 0x82, 0x08, 0x08, 0xa4, + 0x0d, 0x41, 0x12, 0x60, 0xc0, 0x00, 0x24, 0xd2, 0x22, 0x61, 0x08, 0x84, 0x04, + 0x1b, 0x82, 0x01, 0xd3, 0x10, 0x01, 0x02, 0xa0, 0x44, 0xc0, 0x22, 0x60, 0x91, + 0x14, 0x0c, 0x40, 0xa6, 0x04, 0xd2, 0x94, 0x20, 0x09, 0x94, 0x20, 0x52, 0x00, + 0x08, 0x10, 0xa2, 0x4c, 0x00, 0x82, 0x01, 0x51, 0x10, 0x08, 0x8b, 0xa4, 0x25, + 0x9a, 0x30, 0x44, 0x81, 0x10, 0x4c, 0x03, 0x02, 0x25, 0x52, 0x80, 0x08, 0x49, + 0x84, 0x20, 0x50, 0x32, 0x00, 0x18, 0xa2, 0x40, 0x11, 0x24, 0x28, 0x01, 0x84, + 0x01, 0x01, 0xa0, 0x41, 0x0a, 0x12, 0x45, 0x00, 0x36, 0x08, 0x00, 0x26, 0x29, + 0x83, 0x82, 0x61, 0xc0, 0x80, 0x04, 0x10, 0x10, 0x6d, 0x00, 0x22, 0x48, 0x58, + 0x26, 0x0c, 0xc2, 0x10, 0x48, 0x89, 0x24, 0x20, 0x58, 0x20, 0x45, 0x88, 0x24, + 0x00, 0x19, 0x02, 0x25, 0xc0, 0x10, 0x68, 0x08, 0x14, 0x01, 0xca, 0x32, 0x28, + 0x80, 0x00, 0x04, 0x4b, 0x26, 0x00, 0x13, 0x90, 0x60, 0x82, 0x80, 0x25, 0xd0, + 0x00, 0x01, 0x10, 0x32, 0x0c, 0x43, 0x86, 0x21, 0x11, 0x00, 0x08, 0x43, 0x24, + 0x04, 0x48, 0x10, 0x0c, 0x90, 0x92, 0x00, 0x43, 0x20, 0x2d, 0x00, 0x06, 0x09, + 0x88, 0x24, 0x40, 0xc0, 0x32, 0x09, 0x09, 0x82, 0x00, 0x53, 0x80, 0x08, 0x80, + 0x96, 0x41, 0x81, 0x00, 0x40, 0x48, 0x10, 0x48, 0x08, 0x96, 0x48, 0x58, 0x20, + 0x29, 0xc3, 0x80, 0x20, 0x02, 0x94, 0x60, 0x92, 0x00, 0x20, 0x81, 0x22, 0x44, + 0x10, 0xa0, 0x05, 0x40, 0x90, 0x01, 0x49, 0x20, 0x04, 0x0a, 0x00, 0x24, 0x89, + 0x34, 0x48, 0x13, 0x80, 0x2c, 0xc0, 0x82, 0x29, 0x00, 0x24, 0x45, 0x08, 0x00, + 0x08, 0x98, 0x36, 0x04, 0x52, 0x84, 0x04, 0xd0, 0x04, 0x00, 0x8a, 0x90, 0x44, + 0x82, 0x32, 0x65, 0x18, 0x90, 0x00, 0x0a, 0x02, 0x01, 0x40, 0x02, 0x28, 0x40, + 0xa4, 0x04, 0x92, 0x30, 0x04, 0x11, 0x86, 0x08, 0x42, 0x00, 0x2c, 0x52, 0x04, + 0x08, 0xc9, 0x84, 0x60, 0x48, 0x12, 0x09, 0x99, 0x24, 0x44, 0x00, 0x24, 0x00, + 0x03, 0x14, 0x21, 0x00, 0x10, 0x01, 0x1a, 0x32, 0x05, 0x88, 0x20, 0x40, 0x40, + 0x06, 0x09, 0xc3, 0x84, 0x40, 0x01, 0x30, 0x60, 0x18, 0x02, 0x68, 0x11, 0x90, + 0x0c, 0x02, 0xa2, 0x04, 0x00, 0x86, 0x29, 0x89, 0x14, 0x24, 0x82, 0x02, 0x41, + 0x08, 0x80, 0x04, 0x19, 0x80, 0x08, 0x10, 0x12, 0x68, 0x42, 0xa4, 0x04, 0x00, + 0x02, 0x61, 0x10, 0x06, 0x0c, 0x10, 0x00, 0x01, 0x12, 0x10, 0x20, 0x03, 0x94, + 0x21, 0x42, 0x12, 0x65, 0x18, 0x94, 0x0c, 0x0a, 0x04, 0x28, 0x01, 0x14, 0x29, + 0x0a, 0xa4, 0x40, 0xd0, 0x00, 0x40, 0x01, 0x90, 0x04, 0x41, 0x20, 0x2d, 0x40, + 0x82, 0x48, 0xc1, 0x20, 0x00, 0x10, 0x30, 0x01, 0x08, 0x24, 0x04, 0x59, 0x84, + 0x24, 0x00, 0x02, 0x29, 0x82, 0x00, 0x61, 0x58, 0x02, 0x48, 0x81, 0x16, 0x48, + 0x10, 0x00, 0x21, 0x11, 0x06, 0x00, 0xca, 0xa0, 0x40, 0x02, 0x00, 0x04, 0x91, + 0xb0, 0x00, 0x42, 0x04, 0x0c, 0x81, 0x06, 0x09, 0x48, 0x14, 0x25, 0x92, 0x20, + 0x25, 0x11, 0xa0, 0x00, 0x0a, 0x86, 0x0c, 0xc1, 0x02, 0x48, 0x00, 0x20, 0x45, + 0x08, 0x32, 0x00, 0x98, 0x06, 0x04, 0x13, 0x22, 0x00, 0x82, 0x04, 0x48, 0x81, + 0x14, 0x44, 0x82, 0x12, 0x24, 0x18, 0x10, 0x40, 0x43, 0x80, 0x28, 0xd0, 0x04, + 0x20, 0x81, 0x24, 0x64, 0xd8, 0x00, 0x2c, 0x09, 0x12, 0x08, 0x41, 0xa2, 0x00, + 0x00, 0x02, 0x41, 0xca, 0x20, 0x41, 0xc0, 0x10, 0x01, 0x18, 0xa4, 0x04, 0x18, + 0xa4, 0x20, 0x12, 0x94, 0x20, 0x83, 0xa0, 0x40, 0x02, 0x32, 0x44, 0x80, 0x04, + 0x00, 0x18, 0x00, 0x0c, 0x40, 0x86, 0x60, 0x8a, 0x00, 0x64, 0x88, 0x12, 0x05, + 0x01, 0x82, 0x00, 0x4a, 0xa2, 0x01, 0xc1, 0x10, 0x61, 0x09, 0x04, 0x01, 0x88, + 0x00, 0x60, 0x01, 0xb4, 0x40, 0x08, 0x06, 0x01, 0x03, 0x80, 0x08, 0x40, 0x94, + 0x04, 0x8a, 0x20, 0x29, 0x80, 0x02, 0x0c, 0x52, 0x02, 0x01, 0x42, 0x84, 0x00, + 0x80, 0x84, 0x64, 0x02, 0x32, 0x48, 0x00, 0x30, 0x44, 0x40, 0x22, 0x21, 0x00, + 0x02, 0x08, 0xc3, 0xa0, 0x04, 0xd0, 0x20, 0x40, 0x18, 0x16, 0x40, 0x40, 0x00, + 0x28, 0x52, 0x90, 0x08, 0x82, 0x14, 0x01, 0x18, 0x10, 0x08, 0x09, 0x82, 0x40, + 0x0a, 0xa0, 0x20, 0x93, 0x80, 0x08, 0xc0, 0x00, 0x20, 0x52, 0x00, 0x05, 0x01, + 0x10, 0x40, 0x11, 0x06, 0x0c, 0x82, 0x00, 0x00, 0x4b, 0x90, 0x44, 0x9a, 0x00, + 0x28, 0x80, 0x90, 0x04, 0x4a, 0x06, 0x09, 0x43, 0x02, 0x28, 0x00, 0x34, 0x01, + 0x18, 0x00, 0x65, 0x09, 0x80, 0x44, 0x03, 0x00, 0x24, 0x02, 0x82, 0x61, 0x48, + 0x14, 0x41, 0x00, 0x12, 0x28, 0x00, 0x34, 0x08, 0x51, 0x04, 0x05, 0x12, 0x90, + 0x28, 0x89, 0x84, 0x60, 0x12, 0x10, 0x49, 0x10, 0x26, 0x40, 0x49, 0x82, 0x00, + 0x91, 0x10, 0x01, 0x0a, 0x24, 0x40, 0x88, 0x10, 0x4c, 0x10, 0x04, 0x00, 0x50, + 0xa2, 0x2c, 0x40, 0x90, 0x48, 0x0a, 0xb0, 0x01, 0x50, 0x12, 0x08, 0x00, 0xa4, + 0x04, 0x09, 0xa0, 0x28, 0x92, 0x02, 0x00, 0x43, 0x10, 0x21, 0x02, 0x20, 0x41, + 0x81, 0x32, 0x00, 0x08, 0x04, 0x0c, 0x52, 0x00, 0x21, 0x49, 0x84, 0x20, 0x10, + 0x02, 0x01, 0x81, 0x10, 0x48, 0x40, 0x22, 0x01, 0x01, 0x84, 0x69, 0xc1, 0x30, + 0x01, 0xc8, 0x02, 0x44, 0x88, 0x00, 0x0c, 0x01, 0x02, 0x2d, 0xc0, 0x12, 0x61, + 0x00, 0xa0, 0x00, 0xc0, 0x30, 0x40, 0x01, 0x12, 0x08, 0x0b, 0x20, 0x00, 0x80, + 0x94, 0x40, 0x01, 0x84, 0x40, 0x00, 0x32, 0x00, 0x10, 0x84, 0x00, 0x0b, 0x24, + 0x00, 0x01, 0x06, 0x29, 0x8a, 0x84, 0x41, 0x80, 0x10, 0x08, 0x08, 0x94, 0x4c, + 0x03, 0x80, 0x01, 0x40, 0x96, 0x40, 0x41, 0x20, 0x20, 0x50, 0x22, 0x25, 0x89, + 0xa2, 0x40, 0x40, 0xa4, 0x20, 0x02, 0x86, 0x28, 0x01, 0x20, 0x21, 0x4a, 0x10, + 0x08, 0x00, 0x14, 0x08, 0x40, 0x04, 0x25, 0x42, 0x02, 0x21, 0x43, 0x10, 0x04, + 0x92, 0x00, 0x21, 0x11, 0xa0, 0x4c, 0x18, 0x22, 0x09, 0x03, 0x84, 0x41, 0x89, + 0x10, 0x04, 0x82, 0x22, 0x24, 0x01, 0x14, 0x08, 0x08, 0x84, 0x08, 0xc1, 0x00, + 0x09, 0x42, 0xb0, 0x41, 0x8a, 0x02, 0x00, 0x80, 0x36, 0x04, 0x49, 0xa0, 0x24, + 0x91, 0x00, 0x00, 0x02, 0x94, 0x41, 0x92, 0x02, 0x01, 0x08, 0x06, 0x08, 0x09, + 0x00, 0x01, 0xd0, 0x16, 0x28, 0x89, 0x80, 0x60, 0x00, 0x00, 0x68, 0x01, 0x90, + 0x0c, 0x50, 0x20, 0x01, 0x40, 0x80, 0x40, 0x42, 0x30, 0x41, 0x00, 0x20, 0x25, + 0x81, 0x06, 0x40, 0x49, 0x00, 0x08, 0x01, 0x12, 0x49, 0x00, 0xa0, 0x20, 0x18, + 0x30, 0x05, 0x01, 0xa6, 0x00, 0x10, 0x24, 0x28, 0x00, 0x02, 0x20, 0xc8, 0x20, + 0x00, 0x88, 0x12, 0x0c, 0x90, 0x92, 0x00, 0x02, 0x26, 0x01, 0x42, 0x16, 0x49, + 0x00, 0x04, 0x24, 0x42, 0x02, 0x01, 0x88, 0x80, 0x0c, 0x1a, 0x80, 0x08, 0x10, + 0x00, 0x60, 0x02, 0x94, 0x44, 0x88, 0x00, 0x69, 0x11, 0x30, 0x08, 0x12, 0xa0, + 0x24, 0x13, 0x84, 0x00, 0x82, 0x00, 0x65, 0xc0, 0x10, 0x28, 0x00, 0x30, 0x04, + 0x03, 0x20, 0x01, 0x11, 0x06, 0x01, 0xc8, 0x80, 0x00, 0xc2, 0x20, 0x08, 0x10, + 0x82, 0x0c, 0x13, 0x02, 0x0c, 0x52, 0x06, 0x40, 0x00, 0xb0, 0x61, 0x40, 0x10, + 0x01, 0x98, 0x86, 0x04, 0x10, 0x84, 0x08, 0x92, 0x14, 0x60, 0x41, 0x80, 0x41, + 0x1a, 0x10, 0x04, 0x81, 0x22, 0x40, 0x41, 0x20, 0x29, 0x52, 0x00, 0x41, 0x08, + 0x34, 0x60, 0x10, 0x00, 0x28, 0x01, 0x10, 0x40, 0x00, 0x84, 0x08, 0x42, 0x90, + 0x20, 0x48, 0x04, 0x04, 0x52, 0x02, 0x00, 0x08, 0x20, 0x04, 0x00, 0x82, 0x0d, + 0x00, 0x82, 0x40, 0x02, 0x10, 0x05, 0x48, 0x20, 0x40, 0x99, 0x00, 0x00, 0x01, + 0x06, 0x24, 0xc0, 0x00, 0x68, 0x82, 0x04, 0x21, 0x12, 0x10, 0x44, 0x08, 0x04, + 0x00, 0x40, 0xa6, 0x20, 0xd0, 0x16, 0x09, 0xc9, 0x24, 0x41, 0x02, 0x20, 0x0c, + 0x09, 0x92, 0x40, 0x12, 0x00, 0x00, 0x40, 0x00, 0x09, 0x43, 0x84, 0x20, 0x98, + 0x02, 0x01, 0x11, 0x24, 0x00, 0x43, 0x24, 0x00, 0x03, 0x90, 0x08, 0x41, 0x30, + 0x24, 0x58, 0x20, 0x4c, 0x80, 0x82, 0x08, 0x10, 0x24, 0x25, 0x81, 0x06, 0x41, + 0x09, 0x10, 0x20, 0x18, 0x10, 0x44, 0x80, 0x10, 0x00, 0x4a, 0x24, 0x0d, 0x01, + 0x94, 0x28, 0x80, 0x30, 0x00, 0xc0, 0x02, 0x60, 0x10, 0x84, 0x0c, 0x02, 0x00, + 0x09, 0x02, 0x82, 0x01, 0x08, 0x10, 0x04, 0xc2, 0x20, 0x68, 0x09, 0x06, 0x04, + 0x18, 0x00, 0x00, 0x11, 0x90, 0x08, 0x0b, 0x10, 0x21, 0x82, 0x02, 0x0c, 0x10, + 0xb6, 0x08, 0x00, 0x26, 0x00, 0x41, 0x02, 0x01, 0x4a, 0x24, 0x21, 0x1a, 0x20, + 0x24, 0x80, 0x00, 0x44, 0x02, 0x00, 0x2d, 0x40, 0x02, 0x00, 0x8b, 0x94, 0x20, + 0x10, 0x00, 0x20, 0x90, 0xa6, 0x40, 0x13, 0x00, 0x2c, 0x11, 0x86, 0x61, 0x01, + 0x80, 0x41, 0x10, 0x02, 0x04, 0x81, 0x30, 0x48, 0x48, 0x20, 0x28, 0x50, 0x80, + 0x21, 0x8a, 0x10, 0x04, 0x08, 0x10, 0x09, 0x10, 0x10, 0x48, 0x42, 0xa0, 0x0c, + 0x82, 0x92, 0x60, 0xc0, 0x20, 0x05, 0xd2, 0x20, 0x40, 0x01, 0x00, 0x04, 0x08, + 0x82, 0x2d, 0x82, 0x02, 0x00, 0x48, 0x80, 0x41, 0x48, 0x10, 0x00, 0x91, 0x04, + 0x04, 0x03, 0x84, 0x00, 0xc2, 0x04, 0x68, 0x00, 0x00, 0x64, 0xc0, 0x22, 0x40, + 0x08, 0x32, 0x44, 0x09, 0x86, 0x00, 0x91, 0x02, 0x28, 0x01, 0x00, 0x64, 0x48, + 0x00, 0x24, 0x10, 0x90, 0x00, 0x43, 0x00, 0x21, 0x52, 0x86, 0x41, 0x8b, 0x90, + 0x20, 0x40, 0x20, 0x08, 0x88, 0x04, 0x44, 0x13, 0x20, 0x00, 0x02, 0x84, 0x60, + 0x81, 0x90, 0x24, 0x40, 0x30, 0x00, 0x08, 0x10, 0x08, 0x08, 0x02, 0x01, 0x10, + 0x04, 0x20, 0x43, 0xb4, 0x40, 0x90, 0x12, 0x68, 0x01, 0x80, 0x4c, 0x18, 0x00, + 0x08, 0xc0, 0x12, 0x49, 0x40, 0x10, 0x24, 0x1a, 0x00, 0x41, 0x89, 0x24, 0x4c, + 0x10, 0x00, 0x04, 0x52, 0x10, 0x09, 0x4a, 0x20, 0x41, 0x48, 0x22, 0x69, 0x11, + 0x14, 0x08, 0x10, 0x06, 0x24, 0x80, 0x84, 0x28, 0x00, 0x10, 0x00, 0x40, 0x10, + 0x01, 0x08, 0x26, 0x08, 0x48, 0x06, 0x28, 0x00, 0x14, 0x01, 0x42, 0x84, 0x04, + 0x0a, 0x20, 0x00, 0x01, 0x82, 0x08, 0x00, 0x82, 0x24, 0x12, 0x04, 0x40, 0x40, + 0xa0, 0x40, 0x90, 0x10, 0x04, 0x90, 0x22, 0x40, 0x10, 0x20, 0x2c, 0x80, 0x10, + 0x28, 0x43, 0x00, 0x04, 0x58, 0x00, 0x01, 0x81, 0x10, 0x48, 0x09, 0x20, 0x21, + 0x83, 0x04, 0x00, 0x42, 0xa4, 0x44, 0x00, 0x00, 0x6c, 0x10, 0xa0, 0x44, 0x48, + 0x80, 0x00, 0x83, 0x80, 0x48, 0xc9, 0x00, 0x00, 0x00, 0x02, 0x05, 0x10, 0xb0, + 0x04, 0x13, 0x04, 0x29, 0x10, 0x92, 0x40, 0x08, 0x04, 0x44, 0x82, 0x22, 0x00, + 0x19, 0x20, 0x00, 0x19, 0x20, 0x01, 0x81, 0x90, 0x60, 0x8a, 0x00, 0x41, 0xc0, + 0x02, 0x45, 0x10, 0x04, 0x00, 0x02, 0xa2, 0x09, 0x40, 0x10, 0x21, 0x49, 0x20, + 0x01, 0x42, 0x30, 0x2c, 0x00, 0x14, 0x44, 0x01, 0x22, 0x04, 0x02, 0x92, 0x08, + 0x89, 0x04, 0x21, 0x80, 0x10, 0x05, 0x01, 0x20, 0x40, 0x41, 0x80, 0x04, 0x00, + 0x12, 0x09, 0x40, 0xb0, 0x64, 0x58, 0x32, 0x01, 0x08, 0x90, 0x00, 0x41, 0x04, + 0x09, 0xc1, 0x80, 0x61, 0x08, 0x90, 0x00, 0x9a, 0x00, 0x24, 0x01, 0x12, 0x08, + 0x02, 0x26, 0x05, 0x82, 0x06, 0x08, 0x08, 0x00, 0x20, 0x48, 0x20, 0x00, 0x18, + 0x24, 0x48, 0x03, 0x02, 0x00, 0x11, 0x00, 0x09, 0x00, 0x84, 0x01, 0x4a, 0x10, + 0x01, 0x98, 0x00, 0x04, 0x18, 0x86, 0x00, 0xc0, 0x00, 0x20, 0x81, 0x80, 0x04, + 0x10, 0x30, 0x05, 0x00, 0xb4, 0x0c, 0x4a, 0x82, 0x29, 0x91, 0x02, 0x28, 0x00, + 0x20, 0x44, 0xc0, 0x00, 0x2c, 0x91, 0x80, 0x40, 0x01, 0xa2, 0x00, 0x12, 0x04, + 0x09, 0xc3, 0x20, 0x00, 0x08, 0x02, 0x0c, 0x10, 0x22, 0x04, 0x00, 0x00, 0x2c, + 0x11, 0x86, 0x00, 0xc0, 0x00, 0x00, 0x12, 0x32, 0x40, 0x89, 0x80, 0x40, 0x40, + 0x02, 0x05, 0x50, 0x86, 0x60, 0x82, 0xa4, 0x60, 0x0a, 0x12, 0x4d, 0x80, 0x90, + 0x08, 0x12, 0x80, 0x09, 0x02, 0x14, 0x48, 0x01, 0x24, 0x20, 0x8a, 0x00, 0x44, + 0x90, 0x04, 0x04, 0x01, 0x02, 0x00, 0xd1, 0x12, 0x00, 0x0a, 0x04, 0x40, 0x00, + 0x32, 0x21, 0x81, 0x24, 0x08, 0x19, 0x84, 0x20, 0x02, 0x04, 0x08, 0x89, 0x80, + 0x24, 0x02, 0x02, 0x68, 0x18, 0x82, 0x44, 0x42, 0x00, 0x21, 0x40, 0x00, 0x28, + 0x01, 0x80, 0x45, 0x82, 0x20, 0x40, 0x11, 0x80, 0x0c, 0x02, 0x00, 0x24, 0x40, + 0x90, 0x01, 0x40, 0x20, 0x20, 0x50, 0x20, 0x28, 0x19, 0x00, 0x40, 0x09, 0x20, + 0x08, 0x80, 0x04, 0x60, 0x40, 0x80, 0x20, 0x08, 0x30, 0x49, 0x09, 0x34, 0x00, + 0x11, 0x24, 0x24, 0x82, 0x00, 0x41, 0xc2, 0x00, 0x04, 0x92, 0x02, 0x24, 0x80, + 0x00, 0x0c, 0x02, 0xa0, 0x00, 0x01, 0x06, 0x60, 0x41, 0x04, 0x21, 0xd0, 0x00, + 0x01, 0x01, 0x00, 0x48, 0x12, 0x84, 0x04, 0x91, 0x12, 0x08, 0x00, 0x24, 0x44, + 0x00, 0x12, 0x41, 0x18, 0x26, 0x0c, 0x41, 0x80, 0x00, 0x52, 0x04, 0x20, 0x09, + 0x00, 0x24, 0x90, 0x20, 0x48, 0x18, 0x02, 0x00, 0x03, 0xa2, 0x09, 0xd0, 0x14, + 0x00, 0x8a, 0x84, 0x25, 0x4a, 0x00, 0x20, 0x98, 0x14, 0x40, 0x00, 0xa2, 0x05, + 0x00, 0x00, 0x00, 0x40, 0x14, 0x01, 0x58, 0x20, 0x2c, 0x80, 0x84, 0x00, 0x09, + 0x20, 0x20, 0x91, 0x02, 0x08, 0x02, 0xb0, 0x41, 0x08, 0x30, 0x00, 0x09, 0x10, + 0x00, 0x18, 0x02, 0x21, 0x02, 0x02, 0x00, 0x00, 0x24, 0x44, 0x08, 0x12, 0x60, + 0x00, 0xb2, 0x44, 0x12, 0x02, 0x0c, 0xc0, 0x80, 0x40, 0xc8, 0x20, 0x04, 0x50, + 0x20, 0x05, 0x00, 0xb0, 0x04, 0x0b, 0x04, 0x29, 0x53, 0x00, 0x61, 0x48, 0x30, + 0x00, 0x82, 0x20, 0x29, 0x00, 0x16, 0x00, 0x53, 0x22, 0x20, 0x43, 0x10, 0x48, + 0x00, 0x80, 0x04, 0xd2, 0x00, 0x40, 0x00, 0xa2, 0x44, 0x03, 0x80, 0x29, 0x00, + 0x04, 0x08, 0xc0, 0x04, 0x64, 0x40, 0x30, 0x28, 0x09, 0x84, 0x44, 0x50, 0x80, + 0x21, 0x02, 0x92, 0x00, 0xc0, 0x10, 0x60, 0x88, 0x22, 0x08, 0x80, 0x00, 0x00, + 0x18, 0x84, 0x04, 0x83, 0x96, 0x00, 0x81, 0x20, 0x05, 0x02, 0x00, 0x45, 0x88, + 0x84, 0x00, 0x51, 0x20, 0x20, 0x51, 0x86, 0x41, 0x4b, 0x94, 0x00, 0x80, 0x00, + 0x08, 0x11, 0x20, 0x4c, 0x58, 0x80, 0x04, 0x03, 0x06, 0x20, 0x89, 0x00, 0x05, + 0x08, 0x22, 0x05, 0x90, 0x00, 0x40, 0x00, 0x82, 0x09, 0x50, 0x00, 0x00, 0x00, + 0xa0, 0x41, 0xc2, 0x20, 0x08, 0x00, 0x16, 0x08, 0x40, 0x26, 0x21, 0xd0, 0x90, + 0x08, 0x81, 0x90, 0x41, 0x00, 0x02, 0x44, 0x08, 0x10, 0x0c, 0x0a, 0x86, 0x09, + 0x90, 0x04, 0x00, 0xc8, 0xa0, 0x04, 0x08, 0x30, 0x20, 0x89, 0x84, 0x00, 0x11, + 0x22, 0x2c, 0x40, 0x00, 0x08, 0x02, 0xb0, 0x01, 0x48, 0x02, 0x01, 0x09, 0x20, + 0x04, 0x03, 0x04, 0x00, 0x80, 0x02, 0x60, 0x42, 0x30, 0x21, 0x4a, 0x10, 0x44, + 0x09, 0x02, 0x00, 0x01, 0x24, 0x00, 0x12, 0x82, 0x21, 0x80, 0xa4, 0x20, 0x10, + 0x02, 0x04, 0x91, 0xa0, 0x40, 0x18, 0x04, 0x00, 0x02, 0x06, 0x69, 0x09, 0x00, + 0x05, 0x58, 0x02, 0x01, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x03, 0x92, 0x20, + 0x00, 0x34, 0x01, 0xc8, 0x20, 0x48, 0x08, 0x30, 0x08, 0x42, 0x80, 0x20, 0x91, + 0x90, 0x68, 0x01, 0x04, 0x40, 0x12, 0x02, 0x61, 0x00, 0x12, 0x08, 0x01, 0xa0, + 0x00, 0x11, 0x04, 0x21, 0x48, 0x04, 0x24, 0x92, 0x00, 0x0c, 0x01, 0x84, 0x04, + 0x00, 0x00, 0x01, 0x12, 0x96, 0x40, 0x01, 0xa0, 0x41, 0x88, 0x22, 0x28, 0x88, + 0x00, 0x44, 0x42, 0x80, 0x24, 0x12, 0x14, 0x01, 0x42, 0x90, 0x60, 0x1a, 0x10, + 0x04, 0x81, 0x10, 0x48, 0x08, 0x06, 0x29, 0x83, 0x02, 0x40, 0x02, 0x24, 0x64, + 0x80, 0x10, 0x05, 0x80, 0x10, 0x40, 0x02, 0x02, 0x08, 0x42, 0x84, 0x01, 0x09, + 0x20, 0x04, 0x50, 0x00, 0x60, 0x11, 0x30, 0x40, 0x13, 0x02, 0x04, 0x81, 0x00, + 0x09, 0x08, 0x20, 0x45, 0x4a, 0x10, 0x61, 0x90, 0x26, 0x0c, 0x08, 0x02, 0x21, + 0x91, 0x00, 0x60, 0x02, 0x04, 0x00, 0x02, 0x00, 0x0c, 0x08, 0x06, 0x08, 0x48, + 0x84, 0x08, 0x11, 0x02, 0x00, 0x80, 0xa4, 0x00, 0x5a, 0x20, 0x00, 0x88, 0x04, + 0x04, 0x02, 0x00, 0x09, 0x00, 0x14, 0x08, 0x49, 0x14, 0x20, 0xc8, 0x00, 0x04, + 0x91, 0xa0, 0x40, 0x59, 0x80, 0x00, 0x12, 0x10, 0x00, 0x80, 0x80, 0x65, 0x00, + 0x00, 0x04, 0x00, 0x80, 0x40, 0x19, 0x00, 0x21, 0x03, 0x84, 0x60, 0xc0, 0x04, + 0x24, 0x1a, 0x12, 0x61, 0x80, 0x80, 0x08, 0x02, 0x04, 0x09, 0x42, 0x12, 0x20, + 0x08, 0x34, 0x04, 0x90, 0x20, 0x01, 0x01, 0xa0, 0x00, 0x0b, 0x00, 0x08, 0x91, + 0x92, 0x40, 0x02, 0x34, 0x40, 0x88, 0x10, 0x61, 0x19, 0x02, 0x00, 0x40, 0x04, + 0x25, 0xc0, 0x80, 0x68, 0x08, 0x04, 0x21, 0x80, 0x22, 0x04, 0x00, 0xa0, 0x0c, + 0x01, 0x84, 0x20, 0x41, 0x00, 0x08, 0x8a, 0x00, 0x20, 0x8a, 0x00, 0x48, 0x88, + 0x04, 0x04, 0x11, 0x82, 0x08, 0x40, 0x86, 0x09, 0x49, 0xa4, 0x40, 0x00, 0x10, + 0x01, 0x01, 0xa2, 0x04, 0x50, 0x80, 0x0c, 0x80, 0x00, 0x48, 0x82, 0xa0, 0x01, + 0x18, 0x12, 0x41, 0x01, 0x04, 0x48, 0x41, 0x00, 0x24, 0x01, 0x00, 0x00, 0x88, + 0x14, 0x00, 0x02, 0x00, 0x68, 0x01, 0x20, 0x08, 0x4a, 0x22, 0x08, 0x83, 0x80, + 0x00, 0x89, 0x04, 0x01, 0xc2, 0x00, 0x00, 0x00, 0x34, 0x04, 0x00, 0x82, 0x28, + 0x02, 0x02, 0x41, 0x4a, 0x90, 0x05, 0x82, 0x02, 0x09, 0x80, 0x24, 0x04, 0x41, + 0x00, 0x01, 0x92, 0x80, 0x28, 0x01, 0x14, 0x00, 0x50, 0x20, 0x4c, 0x10, 0xb0, + 0x04, 0x43, 0xa4, 0x21, 0x90, 0x04, 0x01, 0x02, 0x00, 0x44, 0x48, 0x00, 0x64, + 0x08, 0x06, 0x00, 0x42, 0x20, 0x08, 0x02, 0x92, 0x01, 0x4a, 0x00, 0x20, 0x50, + 0x32, 0x25, 0x90, 0x22, 0x04, 0x09, 0x00, 0x08, 0x11, 0x80, 0x21, 0x01, 0x10, + 0x05, 0x00, 0x32, 0x08, 0x88, 0x94, 0x08, 0x08, 0x24, 0x0d, 0xc1, 0x80, 0x40, + 0x0b, 0x20, 0x40, 0x18, 0x12, 0x04, 0x00, 0x22, 0x40, 0x10, 0x26, 0x05, 0xc1, + 0x82, 0x00, 0x01, 0x30, 0x24, 0x02, 0x22, 0x41, 0x08, 0x24, 0x48, 0x1a, 0x00, + 0x25, 0xd2, 0x12, 0x28, 0x42, 0x00, 0x04, 0x40, 0x30, 0x41, 0x00, 0x02, 0x00, + 0x13, 0x20, 0x24, 0xd1, 0x84, 0x08, 0x89, 0x80, 0x04, 0x52, 0x00, 0x44, 0x18, + 0xa4, 0x00, 0x00, 0x06, 0x20, 0x91, 0x10, 0x09, 0x42, 0x20, 0x24, 0x40, 0x30, + 0x28, 0x00, 0x84, 0x40, 0x40, 0x80, 0x08, 0x10, 0x04, 0x09, 0x08, 0x04, 0x40, + 0x08, 0x22, 0x00, 0x19, 0x02, 0x00, 0x00, 0x80, 0x2c, 0x02, 0x02, 0x21, 0x01, + 0x90, 0x20, 0x40, 0x00, 0x0c, 0x00, 0x34, 0x48, 0x58, 0x20, 0x01, 0x43, 0x04, + 0x20, 0x80, 0x14, 0x00, 0x90, 0x00, 0x6d, 0x11, 0x00, 0x00, 0x40, 0x20, 0x00, + 0x03, 0x10, 0x40, 0x88, 0x30, 0x05, 0x4a, 0x00, 0x65, 0x10, 0x24, 0x08, 0x18, + 0x84, 0x28, 0x03, 0x80, 0x20, 0x42, 0xb0, 0x40, 0x00, 0x10, 0x69, 0x19, 0x04, + 0x00, 0x00, 0x80, 0x04, 0xc2, 0x04, 0x00, 0x01, 0x00, 0x05, 0x00, 0x22, 0x25, + 0x08, 0x96, 0x04, 0x02, 0x22, 0x00, 0xd0, 0x10, 0x29, 0x01, 0xa0, 0x60, 0x08, + 0x10, 0x04, 0x01, 0x16, 0x44, 0x10, 0x02, 0x28, 0x02, 0x82, 0x48, 0x40, 0x84, + 0x20, 0x90, 0x22, 0x28, 0x80, 0x04, 0x00, 0x40, 0x04, 0x24, 0x00, 0x80, 0x29, + 0x03, 0x10, 0x60, 0x48, 0x00, 0x00, 0x81, 0xa0, 0x00, 0x51, 0x20, 0x0c, 0xd1, + 0x00, 0x01, 0x41, 0x20, 0x04, 0x92, 0x00, 0x00, 0x10, 0x92, 0x00, 0x42, 0x04, + 0x05, 0x01, 0x86, 0x40, 0x80, 0x10, 0x20, 0x52, 0x20, 0x21, 0x00, 0x10, 0x48, + 0x0a, 0x02, 0x00, 0xd0, 0x12, 0x41, 0x48, 0x80, 0x04, 0x00, 0x00, 0x48, 0x09, + 0x22, 0x04, 0x00, 0x24, 0x00, 0x43, 0x10, 0x60, 0x0a, 0x00, 0x44, 0x12, 0x20, + 0x2c, 0x08, 0x20, 0x44, 0x00, 0x84, 0x09, 0x40, 0x06, 0x08, 0xc1, 0x00, 0x40, + 0x80, 0x20, 0x00, 0x98, 0x12, 0x48, 0x10, 0xa2, 0x20, 0x00, 0x84, 0x48, 0xc0, + 0x10, 0x20, 0x90, 0x12, 0x08, 0x98, 0x82, 0x00, 0x0a, 0xa0, 0x04, 0x03, 0x00, + 0x28, 0xc3, 0x00, 0x44, 0x42, 0x10, 0x04, 0x08, 0x04, 0x40, 0x00, 0x00, 0x05, + 0x10, 0x00, 0x21, 0x03, 0x80, 0x04, 0x88, 0x12, 0x69, 0x10, 0x00, 0x04, 0x08, + 0x04, 0x04, 0x02, 0x84, 0x48, 0x49, 0x04, 0x20, 0x18, 0x02, 0x64, 0x80, 0x30, + 0x08, 0x01, 0x02, 0x00, 0x52, 0x12, 0x49, 0x08, 0x20, 0x41, 0x88, 0x10, 0x48, + 0x08, 0x34, 0x00, 0x01, 0x86, 0x05, 0xd0, 0x00, 0x00, 0x83, 0x84, 0x21, 0x40, + 0x02, 0x41, 0x10, 0x80, 0x48, 0x40, 0xa2, 0x20, 0x51, 0x00, 0x00, 0x49, 0x00, + 0x01, 0x90, 0x20, 0x40, 0x18, 0x02, 0x40, 0x02, 0x22, 0x05, 0x40, 0x80, 0x08, + 0x82, 0x10, 0x20, 0x18, 0x00, 0x05, 0x01, 0x82, 0x40, 0x58, 0x00, 0x04, 0x81, + 0x90, 0x29, 0x01, 0xa0, 0x64, 0x00, 0x22, 0x40, 0x01, 0xa2, 0x00, 0x18, 0x04, + 0x0d, 0x00, 0x00, 0x60, 0x80, 0x94, 0x60, 0x82, 0x10, 0x0d, 0x80, 0x30, 0x0c, + 0x12, 0x20, 0x00, 0x00, 0x12, 0x40, 0xc0, 0x20, 0x21, 0x58, 0x02, 0x41, 0x10, + 0x80, 0x44, 0x03, 0x02, 0x04, 0x13, 0x90, 0x29, 0x08, 0x00, 0x44, 0xc0, 0x00, + 0x21, 0x00, 0x26, 0x00, 0x1a, 0x80, 0x01, 0x13, 0x14, 0x20, 0x0a, 0x14, 0x20, + 0x00, 0x32, 0x61, 0x08, 0x00, 0x40, 0x42, 0x20, 0x09, 0x80, 0x06, 0x01, 0x81, + 0x80, 0x60, 0x42, 0x00, 0x68, 0x90, 0x82, 0x08, 0x42, 0x80, 0x04, 0x02, 0x80, + 0x09, 0x0b, 0x04, 0x00, 0x98, 0x00, 0x0c, 0x81, 0x06, 0x44, 0x48, 0x84, 0x28, + 0x03, 0x92, 0x00, 0x01, 0x80, 0x40, 0x0a, 0x00, 0x0c, 0x81, 0x02, 0x08, 0x51, + 0x04, 0x28, 0x90, 0x02, 0x20, 0x09, 0x10, 0x60, 0x00, 0x00, 0x09, 0x81, 0xa0, + 0x0c, 0x00, 0xa4, 0x09, 0x00, 0x02, 0x28, 0x80, 0x20, 0x00, 0x02, 0x02, 0x04, + 0x81, 0x14, 0x04, 0x00, 0x04, 0x09, 0x11, 0x12, 0x60, 0x40, 0x20, 0x01, 0x48, + 0x30, 0x40, 0x11, 0x00, 0x08, 0x0a, 0x86, 0x00, 0x00, 0x04, 0x60, 0x81, 0x04, + 0x01, 0xd0, 0x02, 0x41, 0x18, 0x90, 0x00, 0x0a, 0x20, 0x00, 0xc1, 0x06, 0x01, + 0x08, 0x80, 0x64, 0xca, 0x10, 0x04, 0x99, 0x80, 0x48, 0x01, 0x82, 0x20, 0x50, + 0x90, 0x48, 0x80, 0x84, 0x20, 0x90, 0x22, 0x00, 0x19, 0x00, 0x04, 0x18, 0x20, + 0x24, 0x10, 0x86, 0x40, 0xc2, 0x00, 0x24, 0x12, 0x10, 0x44, 0x00, 0x16, 0x08, + 0x10, 0x24, 0x00, 0x12, 0x06, 0x01, 0x08, 0x90, 0x00, 0x12, 0x02, 0x4d, 0x10, + 0x80, 0x40, 0x50, 0x22, 0x00, 0x43, 0x10, 0x01, 0x00, 0x30, 0x21, 0x0a, 0x00, + 0x00, 0x01, 0x14, 0x00, 0x10, 0x84, 0x04, 0xc1, 0x10, 0x29, 0x0a, 0x00, 0x01, + 0x8a, 0x00, 0x20, 0x01, 0x12, 0x0c, 0x49, 0x20, 0x04, 0x81, 0x00, 0x48, 0x01, + 0x04, 0x60, 0x80, 0x12, 0x0c, 0x08, 0x10, 0x48, 0x4a, 0x04, 0x28, 0x10, 0x00, + 0x28, 0x40, 0x84, 0x45, 0x50, 0x10, 0x60, 0x10, 0x06, 0x44, 0x01, 0x80, 0x09, + 0x00, 0x86, 0x01, 0x42, 0xa0, 0x00, 0x90, 0x00, 0x05, 0x90, 0x22, 0x40, 0x41, + 0x00, 0x08, 0x80, 0x02, 0x08, 0xc0, 0x00, 0x01, 0x58, 0x30, 0x49, 0x09, 0x14, + 0x00, 0x41, 0x02, 0x0c, 0x02, 0x80, 0x40, 0x89, 0x00, 0x24, 0x08, 0x10, 0x05, + 0x90, 0x32, 0x40, 0x0a, 0x82, 0x08, 0x00, 0x12, 0x61, 0x00, 0x04, 0x21, 0x00, + 0x22, 0x04, 0x10, 0x24, 0x08, 0x0a, 0x04, 0x01, 0x10, 0x00, 0x20, 0x40, 0x84, + 0x04, 0x88, 0x22, 0x20, 0x90, 0x12, 0x00, 0x53, 0x06, 0x24, 0x01, 0x04, 0x40, + 0x0b, 0x14, 0x60, 0x82, 0x02, 0x0d, 0x10, 0x90, 0x0c, 0x08, 0x20, 0x09, 0x00, + 0x14, 0x09, 0x80, 0x80, 0x24, 0x82, 0x00, 0x40, 0x01, 0x02, 0x44, 0x01, 0x20, + 0x0c, 0x40, 0x84, 0x40, 0x0a, 0x10, 0x41, 0x00, 0x30, 0x05, 0x09, 0x80, 0x44, + 0x08, 0x20, 0x20, 0x02, 0x00, 0x49, 0x43, 0x20, 0x21, 0x00, 0x20, 0x00, 0x01, + 0xb6, 0x08, 0x40, 0x04, 0x08, 0x02, 0x80, 0x01, 0x41, 0x80, 0x40, 0x08, 0x10, + 0x24, 0x00, 0x20, 0x04, 0x12, 0x86, 0x09, 0xc0, 0x12, 0x21, 0x81, 0x14, 0x04, + 0x00, 0x02, 0x20, 0x89, 0xb4, 0x44, 0x12, 0x80, 0x00, 0xd1, 0x00, 0x69, 0x40, + 0x80, 0x00, 0x42, 0x12, 0x00, 0x18, 0x04, 0x00, 0x49, 0x06, 0x21, 0x02, 0x04, + 0x28, 0x02, 0x84, 0x01, 0xc0, 0x10, 0x68, 0x00, 0x20, 0x08, 0x40, 0x00, 0x08, + 0x91, 0x10, 0x01, 0x81, 0x24, 0x04, 0xd2, 0x10, 0x4c, 0x88, 0x86, 0x00, 0x10, + 0x80, 0x0c, 0x02, 0x14, 0x00, 0x8a, 0x90, 0x40, 0x18, 0x20, 0x21, 0x80, 0xa4, + 0x00, 0x58, 0x24, 0x20, 0x10, 0x10, 0x60, 0xc1, 0x30, 0x41, 0x48, 0x02, 0x48, + 0x09, 0x00, 0x40, 0x09, 0x02, 0x05, 0x11, 0x82, 0x20, 0x4a, 0x20, 0x24, 0x18, + 0x02, 0x0c, 0x10, 0x22, 0x0c, 0x0a, 0x04, 0x00, 0x03, 0x06, 0x48, 0x48, 0x04, + 0x04, 0x02, 0x00, 0x21, 0x80, 0x84, 0x00, 0x18, 0x00, 0x0c, 0x02, 0x12, 0x01, + 0x00, 0x14, 0x05, 0x82, 0x10, 0x41, 0x89, 0x12, 0x08, 0x40, 0xa4, 0x21, 0x01, + 0x84, 0x48, 0x02, 0x10, 0x60, 0x40, 0x02, 0x28, 0x00, 0x14, 0x08, 0x40, 0xa0, + 0x20, 0x51, 0x12, 0x00, 0xc2, 0x00, 0x01, 0x1a, 0x30, 0x40, 0x89, 0x12, 0x4c, + 0x02, 0x80, 0x00, 0x00, 0x14, 0x01, 0x01, 0xa0, 0x21, 0x18, 0x22, 0x21, 0x18, + 0x06, 0x40, 0x01, 0x80, 0x00, 0x90, 0x04, 0x48, 0x02, 0x30, 0x04, 0x08, 0x00, + 0x05, 0x88, 0x24, 0x08, 0x48, 0x04, 0x24, 0x02, 0x06, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x10, 0x65, 0x11, 0x90, 0x00, 0x0a, 0x82, 0x04, 0xc3, 0x04, 0x60, 0x48, + 0x24, 0x04, 0x92, 0x02, 0x44, 0x88, 0x80, 0x40, 0x18, 0x06, 0x29, 0x80, 0x10, + 0x01, 0x00, 0x00, 0x44, 0xc8, 0x10, 0x21, 0x89, 0x30, 0x00, 0x4b, 0xa0, 0x01, + 0x10, 0x14, 0x00, 0x02, 0x94, 0x40, 0x00, 0x20, 0x65, 0x00, 0xa2, 0x0c, 0x40, + 0x22, 0x20, 0x81, 0x12, 0x20, 0x82, 0x04, 0x01, 0x10, 0x00, 0x08, 0x88, 0x00, + 0x00, 0x11, 0x80, 0x04, 0x42, 0x80, 0x40, 0x41, 0x14, 0x00, 0x40, 0x32, 0x2c, + 0x80, 0x24, 0x04, 0x19, 0x00, 0x00, 0x91, 0x00, 0x20, 0x83, 0x00, 0x05, 0x40, + 0x20, 0x09, 0x01, 0x84, 0x40, 0x40, 0x20, 0x20, 0x11, 0x00, 0x40, 0x41, 0x90, + 0x20, 0x00, 0x00, 0x40, 0x90, 0x92, 0x48, 0x18, 0x06, 0x08, 0x81, 0x80, 0x48, + 0x01, 0x34, 0x24, 0x10, 0x20, 0x04, 0x00, 0x20, 0x04, 0x18, 0x06, 0x2d, 0x90, + 0x10, 0x01, 0x00, 0x90, 0x00, 0x0a, 0x22, 0x01, 0x00, 0x22, 0x00, 0x11, 0x84, + 0x01, 0x01, 0x00, 0x20, 0x88, 0x00, 0x44, 0x00, 0x22, 0x01, 0x00, 0xa6, 0x40, + 0x02, 0x06, 0x20, 0x11, 0x00, 0x01, 0xc8, 0xa0, 0x04, 0x8a, 0x00, 0x28, 0x19, + 0x80, 0x00, 0x52, 0xa0, 0x24, 0x12, 0x12, 0x09, 0x08, 0x24, 0x01, 0x48, 0x00, + 0x04, 0x00, 0x24, 0x40, 0x02, 0x84, 0x08, 0x00, 0x04, 0x48, 0x40, 0x90, 0x60, + 0x0a, 0x22, 0x01, 0x88, 0x14, 0x08, 0x01, 0x02, 0x08, 0xd3, 0x00, 0x20, 0xc0, + 0x90, 0x24, 0x10, 0x00, 0x00, 0x01, 0xb0, 0x08, 0x0a, 0xa0, 0x00, 0x80, 0x00, + 0x01, 0x09, 0x00, 0x20, 0x52, 0x02, 0x25, 0x00, 0x24, 0x04, 0x02, 0x84, 0x24, + 0x10, 0x92, 0x40, 0x02, 0xa0, 0x40, 0x00, 0x22, 0x08, 0x11, 0x04, 0x08, 0x01, + 0x22, 0x00, 0x42, 0x14, 0x00, 0x09, 0x90, 0x21, 0x00, 0x30, 0x6c, 0x00, 0x00, + 0x0c, 0x00, 0x22, 0x09, 0x90, 0x10, 0x28, 0x40, 0x00, 0x20, 0xc0, 0x20, 0x00, + 0x90, 0x00, 0x40, 0x01, 0x82, 0x05, 0x12, 0x12, 0x09, 0xc1, 0x04, 0x61, 0x80, + 0x02, 0x28, 0x81, 0x24, 0x00, 0x49, 0x04, 0x08, 0x10, 0x86, 0x29, 0x41, 0x80, + 0x21, 0x0a, 0x30, 0x49, 0x88, 0x90, 0x00, 0x41, 0x04, 0x29, 0x81, 0x80, 0x41, + 0x09, 0x00, 0x40, 0x12, 0x10, 0x40, 0x00, 0x10, 0x40, 0x48, 0x02, 0x05, 0x80, + 0x02, 0x21, 0x40, 0x20, 0x00, 0x58, 0x20, 0x60, 0x00, 0x90, 0x48, 0x00, 0x80, + 0x28, 0xc0, 0x80, 0x48, 0x00, 0x00, 0x44, 0x80, 0x02, 0x00, 0x09, 0x06, 0x00, + 0x12, 0x02, 0x01, 0x00, 0x10, 0x08, 0x83, 0x10, 0x45, 0x12, 0x00, 0x2c, 0x08, + 0x04, 0x44, 0x00, 0x20, 0x20, 0xc0, 0x10, 0x20, 0x01, 0x00, 0x05, 0xc8, 0x20, + 0x04, 0x98, 0x10, 0x08, 0x10, 0x00, 0x24, 0x02, 0x16, 0x40, 0x88, 0x00, 0x61, + 0x88, 0x12, 0x24, 0x80, 0xa6, 0x00, 0x42, 0x00, 0x08, 0x10, 0x06, 0x48, 0x40, + 0xa0, 0x00, 0x50, 0x20, 0x04, 0x81, 0xa4, 0x40, 0x18, 0x00, 0x08, 0x10, 0x80, + 0x01, 0x01 +) diff --git a/optee/samples/ftpm-helper/host/tool/lib/ftpm_ek_csr.py b/optee/samples/ftpm-helper/host/tool/lib/ftpm_ek_csr.py new file mode 100644 index 0000000..af9bf00 --- /dev/null +++ b/optee/samples/ftpm-helper/host/tool/lib/ftpm_ek_csr.py @@ -0,0 +1,124 @@ +# Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause + +from asn1crypto import csr, keys, x509 +from oscrypto import asymmetric + +class fTPM_Gen_EK_CSR(): + def __init__(self, common_name, org_name, country_name, ek_csr_file, ek_priv_key_der, ek_pub_key_der): + # setup subject info + self.cn = common_name + self.org_name = org_name + self.Cn = country_name + + # Load EK key pair + self.ek_priv_key = asymmetric.load_private_key(ek_priv_key_der) + self.ek_pub_key_raw = keys.PublicKeyInfo.load(ek_pub_key_der) + self.ek_pub_key = asymmetric.load_public_key(ek_pub_key_der) + + # Open EK CSR file + self.ek_csr_fout = open(ek_csr_file, "wb") + + def build_csr(self): + # https://trustedcomputinggroup.org/wp-content/uploads/TCG-EK-Credential-Profile-V-2.5-R2_published.pdf + _csr_subject = x509.Name.build( + { + "common_name" : self.cn, + "organization_name" : self.org_name, + "country_name" : self.Cn, + } + ) + + _csr_pub_key_info = self.ek_pub_key_raw + + # https://github.com/microsoft/ms-tpm-20-ref/blob/main/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/reference/include/VendorString.h + _csr_subject_alt_name = x509.Name.build( + { + "tpm_manufacturer" : u"id:4D534654", + "tpm_model" : u"SSE fTPM", + "tpm_version" : u"id:20180710", + } + ) + + _csr_extensions = [] + + if self.ek_pub_key.algorithm == "rsa": + _csr_extensions.append( + { + "extn_id" : "key_usage", + "critical" : True, + "extn_value" : x509.KeyUsage(set(['key_encipherment'])), + } + ) + elif self.ek_pub_key.algorithm == "ec": + _csr_extensions.append( + { + "extn_id" : "key_usage", + "critical" : True, + "extn_value" : x509.KeyUsage(set(['digital_signature', 'key_agreement'])), + } + ) + else: + raise Exception("Error: Unknown TPM EK algorithm.") + + _csr_extensions.extend([ + { + "extn_id" : "basic_constraints", + "critical" : True, + "extn_value" : { "ca" : False }, + }, + { + "extn_id" : "subject_alt_name", + "critical" : False, + "extn_value" : x509.GeneralNames([ + x509.GeneralName( + name = "directory_name", + value = _csr_subject_alt_name + ) + ]) + } + ]) + + _csr_attributes = [] + _csr_attributes.append( + { + "type" : "extension_request", + "values" : [_csr_extensions], + } + ) + + _csr_info = csr.CertificationRequestInfo( + { + "version" : "v1", + "subject" : _csr_subject, + "subject_pk_info" : _csr_pub_key_info, + "attributes" : _csr_attributes, + } + ) + + # Generate a temporary EC private key for signing the CSR. + # The CSR will be resigned later in the TPM helper TA by the silicon ID private key. + #_csr_temp_pub_key, _csr_temp_priv_key = asymmetric.generate_pair("ec", curve="secp256r1") + #_signature = asymmetric.ecdsa_sign(_csr_temp_priv_key, _csr_info.dump(), "sha256") + + # Signing the EK CSR + if self.ek_priv_key.algorithm == 'rsa': + _sig_algo = "sha256_rsa" + sign_func = asymmetric.rsa_pkcs1v15_sign + elif self.ek_priv_key.algorithm == 'ec': + _sig_algo = "sha256_ecdsa" + sign_func = asymmetric.ecdsa_sign + else: + raise Exception("Error: The EK private key is invalid.") + + _signature = sign_func(self.ek_priv_key, _csr_info.dump(), "sha256") + + self.ek_csr = csr.CertificationRequest( + { + "certification_request_info" : _csr_info, + "signature_algorithm" : { "algorithm" : _sig_algo }, + "signature" : _signature, + } + ) + + self.ek_csr_fout.write(self.ek_csr.dump()) diff --git a/optee/samples/ftpm-helper/host/tool/lib/silicon_id_csr.py b/optee/samples/ftpm-helper/host/tool/lib/silicon_id_csr.py new file mode 100644 index 0000000..4edd789 --- /dev/null +++ b/optee/samples/ftpm-helper/host/tool/lib/silicon_id_csr.py @@ -0,0 +1,86 @@ +# Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause + +from asn1crypto import csr, keys, x509 +from oscrypto import asymmetric + +class Device_Gen_Silicon_ID_CSR(): + def __init__(self, common_name, org_name, country_name, sid_priv_key_der, sid_pub_key_der): + # setup subject info + self.cn = common_name + self.org_name = org_name + self.Cn = country_name + + # Load Silicon ID key pair + self.sid_priv_key = asymmetric.load_private_key(sid_priv_key_der) + self.sid_pub_key_raw = keys.PublicKeyInfo.load(sid_pub_key_der) + + def build_csr(self): + _csr_subject = x509.Name.build( + { + "common_name" : self.cn, + "organization_name" : self.org_name, + "country_name" : self.Cn, + } + ) + + _csr_pub_key_info = self.sid_pub_key_raw + + _csr_extensions = [] + _csr_extensions.extend([ + { + "extn_id" : "basic_constraints", + "critical" : True, + "extn_value" : { "ca" : True, "path_len_constraint" : 0 }, + }, + { + "extn_id" : "key_usage", + "critical" : True, + "extn_value" : x509.KeyUsage(set(['key_cert_sign'])), + }, + { + "extn_id" : "key_identifier", + "extn_value" : _csr_pub_key_info.sha1, + } + ]) + + _csr_attributes = [] + _csr_attributes.append( + { + "type" : "extension_request", + "values" : [_csr_extensions], + } + ) + + _csr_info = csr.CertificationRequestInfo( + { + "version" : "v1", + "subject" : _csr_subject, + "subject_pk_info" : _csr_pub_key_info, + "attributes" : _csr_attributes, + } + ) + + # Signing the CSR + if self.sid_priv_key.algorithm == 'rsa': + _sig_algo = "sha256_rsa" + sign_func = asymmetric.rsa_pkcs1v15_sign + elif self.sid_priv_key.algorithm == 'ec': + _sig_algo = "sha256_ecdsa" + sign_func = asymmetric.ecdsa_sign + else: + raise Exception("Error: The Silicon ID private key is invalid.") + + _signature = sign_func(self.sid_priv_key, _csr_info.dump(), "sha256") + + self.csr = csr.CertificationRequest( + { + "certification_request_info" : _csr_info, + "signature_algorithm" : { "algorithm" : _sig_algo }, + "signature" : _signature, + } + ) + + csr_bin = bytearray(self.csr.dump()) + + return csr_bin.hex() diff --git a/optee/samples/ftpm-helper/host/tool/odm_ekb_gen.py b/optee/samples/ftpm-helper/host/tool/odm_ekb_gen.py new file mode 100755 index 0000000..1b0bf48 --- /dev/null +++ b/optee/samples/ftpm-helper/host/tool/odm_ekb_gen.py @@ -0,0 +1,439 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause + +import argparse +import csv +import os +import sys +import subprocess +import struct +import shutil +from typing import Tuple +from typing import Optional +from io import TextIOWrapper +from cryptography.hazmat.primitives import hmac, hashes +from cryptography.hazmat.primitives.kdf import kbkdf +from cryptography.hazmat.primitives.kdf import hkdf +from cryptography.hazmat.backends import default_backend + + +SUCCESS = 0 +FAILED = 1 +output_dir = "odm_out" +output_file_template = output_dir + "/ftpm_eks_{}.img" +output_verify_file = output_dir + "/ftpm_keys.txt" +cmd_gen_ek_csr = "./ftpm_manufacturer_gen_ek_csr.sh" +cmd_gen_ek_certs = "./ftpm_manufacturer_ca_simulator.sh" +cmd_openssl = "openssl" +cmd_sign_sid_csr = "./ftpm_manufacturer_ca_sign_sid_csr.sh" +ca_output_dir = "ca_out" +ek_cert_rsa_template = ca_output_dir + "/ek_cert_rsa-{}.der" +ek_cert_ec_template = ca_output_dir + "/ek_cert_ec-{}.der" +sid_cert_template = ca_output_dir + "/sid_cert-{}.der" +ftpm_output_dir = "ftpm_out" +ek_csr_rsa_template = ftpm_output_dir + "/ek_csr_rsa-{}.der" +ek_csr_ec_template = ftpm_output_dir + "/ek_csr_ec-{}.der" + +class Context: + def __init__(self): + self.kdk_db: str = "" + self.verify: bool = False + self.fh_ftpm_keys: Optional[TextIOWrapper] = None + + +def encode(data: str, is_hex: bool) -> bytes: + result = b'' + if is_hex: + # Convert hex string to bytes + try: + result = bytes.fromhex(data) + except Exception as e: + print("Converting hex string: ", data, " to bytes failed: ", e) + result = b'' + else: + # Encode as ASCII bytes + try: + result = data.encode("ascii") + except Exception as e: + print("Converting non hex string: ", data, " to bytes failed: ", e) + result = b'' + return result + +def kdf(kdk: bytes, label: bytes, context: bytes, L: int = 256, rlen: int = 32, order = None) -> bytes: + """Derive KDF from root key and NIST SP800-108 input (label and context).""" + if not context: + context = b"\x00" + + if order is None: + order = kbkdf.CounterLocation.BeforeFixed + + hkdf = kbkdf.KBKDFHMAC( + algorithm=hashes.SHA256(), + mode=kbkdf.Mode.CounterMode, + length=L // 8, + rlen=rlen // 8, + llen=4, + location=order, + label=label, + context=context, + fixed=None, + backend=default_backend(), + ) + return hkdf.derive(kdk) + +def display_device_sn(sn: bytes) -> str: + sn_hex = sn.hex() + return "{}-{}".format(sn_hex[:4], sn_hex[4:]) + +def convert_sn_endian(sn: bytes) -> bytes: + # The device SN is 10 bytes, and has the format: + # + # oem_id is stored in fuse "odm_info" which is a 4-byte fuse + # All 4-byte or less Tegra fuses are stored in little-endian so we need + # to convert the endian of oem_id in device SN before doing the key calculation + # The left 8 bytes don't have an endian issue - it is big-endian everywhere + result = bytearray(sn) + result[0] = sn[1] + result[1] = sn[0] + return bytes(result) + +def gen_silicon_id(kdk: str, sn: bytes) -> bytes: + kdk_nrk = kdf(encode(kdk, True), encode("NRK", False), encode("00", True)) + # Only in PSC_BL1, sn is treated as little-endian when calculating the key + # For all other places that SN involves, we require SN to be big-endian + silicon_id = kdf(kdk_nrk, encode("ECA_SEED", False), convert_sn_endian(sn)) + return silicon_id + +def gen_ftpm_eps_contents(silicon_id: bytes, sn: bytes) -> Tuple[bytes, bytes]: + ftpm_seed_origin = kdf(silicon_id, encode("fTPM", False), encode("00", True)) + hm = hmac.HMAC(ftpm_seed_origin, hashes.SHA256(), backend=default_backend()) + hm.update("fTPM".encode(encoding="utf8")) + ftpm_seed = hm.finalize() + + root_seed_hkdf = hkdf.HKDF(algorithm=hashes.SHA256(), length=64, + salt=encode("00", True), + info=encode("Root_Seed", False)) + root_seed = root_seed_hkdf.derive(ftpm_seed) + + eps_seed = os.urandom(32) + eps_hkdf = hkdf.HKDF(algorithm=hashes.SHA256(), length=64, salt=eps_seed, info=sn) + eps = eps_hkdf.derive(root_seed) + return eps_seed, eps + +def generate_ftpm_ekb_contents(sn: bytes, eps_seed: bytes, online_prov: bool) -> bytes: + # File format + # content size | magic id | version major | version minor + # tag | length | value + # tag | length | value + # ...... + # end-tag(\0\0\0\0) | end-tag-len(\0\0\0\0) + + magic_id = b"NVFTPM\0\0" + version_major = 1 + version_minor = 1 + tag_sn = 1 + tag_eps_seed = 2 + tag_ek_cert_rsa = 3 + tag_ek_cert_ec = 4 + tag_sid_cert = 5 + tag_ek_csr_rsa = 6 + tag_ek_csr_ec = 7 + + ek_cert_rsa_file = ek_cert_rsa_template.format(display_device_sn(sn)) + ek_cert_ec_file = ek_cert_ec_template.format(display_device_sn(sn)) + if online_prov: + sid_cert_file = sid_cert_template.format(display_device_sn(sn)) + ek_csr_rsa_file = ek_csr_rsa_template.format(display_device_sn(sn)) + ek_csr_ec_file = ek_csr_ec_template.format(display_device_sn(sn)) + + if not online_prov: + if not os.path.exists(ek_cert_rsa_file): + raise Exception("RSA EK certificate can't be found.") + if not os.path.exists(ek_cert_ec_file): + raise Exception("EC EK certificate can't be found.") + + with open(ek_cert_rsa_file, "rb") as fd: + ek_cert_rsa = fd.read() + with open(ek_cert_ec_file, "rb") as fd: + ek_cert_ec = fd.read() + else: + if not os.path.exists(sid_cert_file): + raise Exception("Silicon ID certificate can't be found.") + if not os.path.exists(ek_csr_rsa_file): + raise Exception("RSA EK CSR can't be found.") + if not os.path.exists(ek_csr_ec_file): + raise Exception("EC EK CSR can't be found.") + + with open(sid_cert_file, "rb") as fd: + sid_cert = fd.read() + with open(ek_csr_rsa_file, "rb") as fd: + ek_csr_rsa = fd.read() + with open(ek_csr_ec_file, "rb") as fd: + ek_csr_ec = fd.read() + + content_size = 12 # magic ID + version major + version minor + content_size += 8 + len(sn) + content_size += 8 + len(eps_seed) + if not online_prov: + content_size += 8 + len(ek_cert_rsa) + content_size += 8 + len(ek_cert_ec) + else: + content_size += 8 + len(sid_cert) + content_size += 8 + len(ek_csr_rsa) + content_size += 8 + len(ek_csr_ec) + content_size += 8 # end tag and end tag length + + header_fmt = " bool: + sn_string = display_device_sn(sn) + if context.fh_ftpm_keys == None: + print("Invalid fTPM keys file handle. Device SN: ", sn_string) + return False + + ek_cert_rsa_file = ek_cert_rsa_template.format(sn_string) + ek_cert_ec_file = ek_cert_ec_template.format(sn_string) + + cmd = [cmd_openssl] + cmd.extend(["x509"]) + cmd.extend(["-inform", "der"]) + cmd.extend(["-in", ek_cert_rsa_file]) + cmd.extend(["-pubkey"]) + cmd.extend(["-noout"]) + rsa_ek_pubkey = run_command(cmd) + + cmd = [cmd_openssl] + cmd.extend(["x509"]) + cmd.extend(["-inform", "der"]) + cmd.extend(["-in", ek_cert_ec_file]) + cmd.extend(["-pubkey"]) + cmd.extend(["-noout"]) + ec_ek_pubkey = run_command(cmd) + + context.fh_ftpm_keys.write("# device_sn\n") + context.fh_ftpm_keys.write("{}\n".format(sn_string)) + context.fh_ftpm_keys.write("# eps\n") + context.fh_ftpm_keys.write("{}\n".format(eps.hex())) + context.fh_ftpm_keys.write("# rsa_ek_pubkey\n") + context.fh_ftpm_keys.write(rsa_ek_pubkey) + context.fh_ftpm_keys.write("# ec_ek_pubkey\n") + context.fh_ftpm_keys.write(ec_ek_pubkey) + context.fh_ftpm_keys.write("\n") + + return True + +def run_command(cmd) -> str: + print("Running command: ", " ".join(cmd)) + + try: + # Run the command and capture its output, error, and return code + result = subprocess.run(cmd, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, universal_newlines=True) + output = result.stdout + error = result.stderr + return_code = result.returncode + except subprocess.CalledProcessError as e: + print("Run command error: ", e) + raise e + + if return_code != 0: + print(output) + print(error) + raise ValueError("Running command failed with error: {}".format(return_code)) + return output + +def initialize(kdk_db: str, verify: bool) -> Optional[Context]: + if kdk_db == None or not os.path.isfile(kdk_db): + print("The KDK db file can't be found.") + return None + kdk_db_path = os.path.abspath(kdk_db) + + # Set the working directory + try: + wd = os.path.dirname(os.path.abspath(__file__)) + os.chdir(wd) + except Exception as e: + print("Changing current working directory failed.") + print(e) + return None + + if os.path.exists(output_dir) and not os.path.isdir(output_dir): + print("Creating the output folder: ", output_dir, " failed. File exists.") + return None + if os.path.exists(output_dir): + print("Cleaning the output directory...") + try: + shutil.rmtree(output_dir) + except Exception as e: + print("Cleaning the output folder: ", output_dir, " failed.") + return None + + try: + os.makedirs(output_dir) + except Exception as e: + print("Creating the output folder: ", output_dir, " failed.") + return None + + fh_ftpm_keys = None + if verify: + try: + fh_ftpm_keys = open(output_verify_file, 'w', newline='') + except Exception as e: + print("Creating the verify output file failed: ", e) + return None + + context = Context() + context.kdk_db = kdk_db_path + context.verify = verify + if verify: + context.fh_ftpm_keys = fh_ftpm_keys + return context + +def handle_rows_in_kdk_and_sid_csr_db(row_kdk_db, row_sid_csr_db, online_prov: bool, context): + try: + oem_id = int(row_kdk_db[0], 16) + sn = int(row_kdk_db[1], 16) + except Exception: + print("Warning: Illegal oem_id(", row_kdk_db[0], ") or sn(", row_kdk_db[1], "), ignored.") + return + + if oem_id.bit_length() > 16: + print("Warning: oem_id: ", oem_id, " must be a 16-bit integer, ignored.") + return + if sn.bit_length() > 64: + print("Warning: sn: ", sn, " must be a 64-bit integer, ignored.") + return + + if online_prov: + oem_id_from_sid_csr_db = int(row_sid_csr_db[0], 16) + sn_from_sid_csr_db = int(row_sid_csr_db[1], 16) + + if oem_id != oem_id_from_sid_csr_db or sn != sn_from_sid_csr_db: + print("Warning: The KDK and Silicon ID CSR database doesn't match.") + return + + device_sid_csr = row_sid_csr_db[2] + + device_kdk = row_kdk_db[2] + # device_sn is a combination of oem_id and sn + device_sn = oem_id.to_bytes(2, "big") + sn_high = (sn >> 32).to_bytes(4, "big") + sn_low = (sn & 0xffffffff).to_bytes(4, "big") + device_sn += sn_high + device_sn += sn_low + + print("Creating odm EKB outputs for device: ", display_device_sn(device_sn)) + silicon_id = gen_silicon_id(device_kdk, device_sn) + ftpm_eps_seed, ftpm_eps = gen_ftpm_eps_contents(silicon_id, device_sn) + + try: + if not online_prov: + # Generate EK CSRs: ek_csr_rsa-{device_sn}.der and ek_csr_ec-{device_sn}.der + cmd = [cmd_gen_ek_csr] + cmd.extend(["-s", display_device_sn(device_sn)]) + cmd.extend(["-e", ftpm_eps.hex()]) + run_command(cmd) + + # Generate EK certificates by signing the CSRs generated above + cmd = [cmd_gen_ek_certs] + cmd.extend(["-s", display_device_sn(device_sn)]) + run_command(cmd) + else: + # Generate EK CSRs: ek_csr_rsa-{device_sn}.der and ek_csr_ec-{device_sn}.der + cmd = [cmd_gen_ek_csr] + cmd.extend(["-s", display_device_sn(device_sn)]) + cmd.extend(["-e", ftpm_eps.hex()]) + run_command(cmd) + + # Sign Silicon ID CSR + cmd = [cmd_sign_sid_csr] + cmd.extend(["-i", device_sid_csr]) + cmd.extend(["-s", display_device_sn(device_sn)]) + run_command(cmd) + except Exception: + return + + # Generate EKB DB files for per-device basis. + # The content of the EKB DB file: + # Offline provision mode: + # - SN (Serial Number) + # - fTPM EPS Seed + # - RSA EK Certificate + # - EC EK Certificate + # Online provision mode: + # - SN (Serial Number) + # - fTPM EPS Seed + # - Silicon ID Certificate + # - RSA EK CSR + # - EC EK CSR + # + # The EKB DB files will be parsed by oem_ekb_gen.py to generate the final EKB images. + # + blob = generate_ftpm_ekb_contents(device_sn, ftpm_eps_seed, online_prov) + fn_ftpm_ekb = output_file_template.format(display_device_sn(device_sn)) + with open(fn_ftpm_ekb, "wb") as fh_ftpm_ekb: + fh_ftpm_ekb.write(blob) + + if context.verify: + generate_ftpm_keys(device_sn, ftpm_eps, context) + +def main() -> int: + parser = argparse.ArgumentParser(description='The tool used by ODM to generate fTPM SN, EPS Seed and certificates.') + parser.add_argument('--kdk_db', help='The csv file which contains the KDK list.') + parser.add_argument("--prov_mode", type=str, default="offline", help="The fTPM provisioning mode (offline or online). The default is offline.") + parser.add_argument("--silicon_id_csr_db", help="The csv file of the Silicon ID CSRs that is needed when prov_mode is online.") + parser.add_argument("--verify", action="store_const", const=True, help='Save fTPM keys to verify on a Jetson device.') + + args = parser.parse_args() + + if (args.prov_mode == "online" and not args.silicon_id_csr_db): + parser.print_help() + return + + context = initialize(args.kdk_db, args.verify) + if context == None: + return FAILED + + # fh: file handle, cr: csv reader + if (args.prov_mode == "online"): + fh_sid_csr_db = open(args.silicon_id_csr_db, 'r', newline='') + cr_sid_db = csv.reader(fh_sid_csr_db, delimiter=' ', quotechar='|', quoting=csv.QUOTE_MINIMAL) + else: + cr_sid_db = "" + + with open(args.kdk_db, mode='r', newline='') as fh_kdk_db: + cr_kdk_db = csv.reader(fh_kdk_db, delimiter=' ', quotechar='|', quoting=csv.QUOTE_MINIMAL) + + if (args.prov_mode == "online"): + for row_kdk_db, row_sid_csr_db in zip(cr_kdk_db, cr_sid_db): + if not handle_rows_in_kdk_and_sid_csr_db(row_kdk_db, row_sid_csr_db, True, context): + continue + else: + for row_kdk_db in cr_kdk_db: + if not handle_rows_in_kdk_and_sid_csr_db(row_kdk_db, [], False, context): + continue + + if context.fh_ftpm_keys != None: + context.fh_ftpm_keys.close() + return SUCCESS + + +if __name__ == '__main__': + ret_code = main() + sys.exit(ret_code) diff --git a/optee/samples/ftpm-helper/host/tool/oem_ekb_gen.py b/optee/samples/ftpm-helper/host/tool/oem_ekb_gen.py new file mode 100755 index 0000000..cc9541b --- /dev/null +++ b/optee/samples/ftpm-helper/host/tool/oem_ekb_gen.py @@ -0,0 +1,259 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause + +import argparse +import os +import sys +import subprocess +import struct +import shutil +from typing import Optional + + +SUCCESS = 0 +FAILED = 1 +output_dir = "oem_out" +output_file_template = output_dir + "/eks_{}.img" +cmd_gen_ekb = "./gen_ekb.py" +# Temp files to store EPS seed, +# RSA EK certificate and EC EK certificate for offline provision mode, and +# RSA EK CSR, EK EK CSR, and Silicon ID certificate for online provision mode. +temp_eps_seed = output_dir + "/temp_eps_seed.hex" +temp_rsa_cert = output_dir + "/temp_rsa_cert.der" +temp_ec_cert = output_dir + "/temp_ec_cert.der" +temp_rsa_csr = output_dir + "/temp_rsa_csr.der" +temp_ec_csr = output_dir + "/temp_ec_csr.der" +temp_sid_cert = output_dir + "/temp_sid_cert.der" + +class Context: + def __init__(self): + self.odm_ekb: str = "" + + +def initialize(odm_ekb: str) -> Optional[Context]: + if odm_ekb == None or not os.path.isdir(odm_ekb): + print("The fTPM ODM EKB directory can't be found.") + return None + odm_ekb_path = os.path.abspath(odm_ekb) + + # Set the working directory + try: + wd = os.path.dirname(os.path.abspath(__file__)) + os.chdir(wd) + except Exception as e: + print("Changing current working directory failed.") + print(e) + return None + + if os.path.exists(output_dir) and not os.path.isdir(output_dir): + print("Creating the output folder: ", output_dir, " failed. File exists.") + return None + if os.path.exists(output_dir): + print("Cleaning the output directory...") + try: + shutil.rmtree(output_dir) + except Exception as e: + print("Cleaning the output folder: ", output_dir, " failed.") + return None + + try: + os.makedirs(output_dir) + except Exception as e: + print("Creating the output folder: ", output_dir, " failed.") + return None + + context = Context() + context.odm_ekb = odm_ekb_path + return context + +# Return SN and create 3 temp files +def handle_odm_ekb_file(name: str, online_prov: bool) -> str: + result = "" + file_valid = True + eps_seed_found = False + rsa_cert_found = False + ec_cert_found = False + sid_cert_found = False + rsa_csr_found = False + ec_csr_found = False + + with open(name, 'rb') as file: + # File format + # content size | magic id | version major | version minor + # tag | length | value + # tag | length | value + # ...... + # end-tag(\0\0\0\0) | end-tag-len(\0\0\0\0) + magic_id = b"NVFTPM\0\0" + version_major = 1 + version_minor = 1 + tag_sn = 1 + tag_eps_seed = 2 + tag_rsa_ek_cert = 3 + tag_ec_ek_cert = 4 + tag_sid_cert = 5 + tag_rsa_ek_csr = 6 + tag_ec_ek_csr = 7 + + total_len, magic, major, minor = struct.unpack(" str: + print("Running command: ", " ".join(cmd)) + + try: + # Run the command and capture its output, error, and return code + result = subprocess.run(cmd, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, universal_newlines=True) + output = result.stdout + error = result.stderr + return_code = result.returncode + except subprocess.CalledProcessError as e: + print("Run command error: ", e) + raise e + + if return_code != 0: + print(output) + print(error) + raise ValueError("Running command failed with error: {}".format(return_code)) + return output + +def finalize(): + if os.path.exists(temp_eps_seed): + os.remove(temp_eps_seed) + if os.path.exists(temp_rsa_cert): + os.remove(temp_rsa_cert) + if os.path.exists(temp_ec_cert): + os.remove(temp_ec_cert) + +def display_device_sn(sn: str) -> str: + return "{}-{}".format(sn[:4], sn[4:]) + +def main() -> int: + parser = argparse.ArgumentParser(description='The tool used by OEM to generate the EKB images.') + parser.add_argument('-oem_k1_key', required=False, help="oem_k1 key (32 bytes) file in hex format") + parser.add_argument('-oem_k2_key', required=False, help="oem_k2 key (32 bytes) file in hex format") + parser.add_argument('-in_sym_key', required=False, help="32-byte symmetric key file in hex format") + parser.add_argument('-in_sym_key2', required=False, help="16-byte symmetric key file in hex format") + parser.add_argument('-in_auth_key', required=False, help="16-byte symmetric key file in hex format") + parser.add_argument('-in_ftpm_odm_ekb', required=True, help="The directory which saves ODM EKB files") + parser.add_argument("-prov_mode", type=str, default="offline", help="The fTPM provisioning mode (offline or online). The default is offline.") + + args = parser.parse_args() + context = initialize(args.in_ftpm_odm_ekb) + if context == None: + return FAILED + + if (args.prov_mode == "online"): + online_prov = True + else: + online_prov = False + + for dirpath, _, filenames in os.walk(context.odm_ekb): + for filename in filenames: + fn_target = os.path.join(dirpath, filename) + print("Parsing ODM EKB file: ", fn_target) + device_sn = handle_odm_ekb_file(fn_target, online_prov) + if len(device_sn) == 0: + continue + + # Generate the final EKB image for this device + cmd = [cmd_gen_ekb] + cmd.extend(["-chip", "t234"]) + if args.oem_k1_key != None: + cmd.extend(["-oem_k1_key", args.oem_k1_key]) + if args.oem_k2_key != None: + cmd.extend(["-oem_k2_key", args.oem_k2_key]) + if args.in_sym_key != None: + cmd.extend(["-in_sym_key", args.in_sym_key]) + if args.in_sym_key2 != None: + cmd.extend(["-in_sym_key2", args.in_sym_key2]) + if args.in_auth_key != None: + cmd.extend(["-in_auth_key", args.in_auth_key]) + + cmd.extend(["-in_ftpm_sn", device_sn]) + cmd.extend(["-in_ftpm_eps_seed", temp_eps_seed]) + if not online_prov: + cmd.extend(["-in_ftpm_rsa_ek_cert", temp_rsa_cert]) + cmd.extend(["-in_ftpm_ec_ek_cert", temp_ec_cert]) + else: + cmd.extend(["-in_sid_cert", temp_sid_cert]) + cmd.extend(["-in_ftpm_rsa_ek_csr", temp_rsa_csr]) + cmd.extend(["-in_ftpm_ec_ek_csr", temp_ec_csr]) + cmd.extend(["-out", output_file_template.format(display_device_sn(device_sn))]) + run_command(cmd) + + finalize() + return SUCCESS + + +if __name__ == '__main__': + ret_code = main() + sys.exit(ret_code) diff --git a/optee/samples/ftpm-helper/ta/Makefile b/optee/samples/ftpm-helper/ta/Makefile new file mode 100644 index 0000000..713ae43 --- /dev/null +++ b/optee/samples/ftpm-helper/ta/Makefile @@ -0,0 +1,7 @@ +# Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause + +# The UUID for the ftpm-helper TA +BINARY=a6a3a74a-77cb-433a-990c-1dfb8a3fbc4c + +include $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk diff --git a/optee/samples/ftpm-helper/ta/ftpm_helper_ta.c b/optee/samples/ftpm-helper/ta/ftpm_helper_ta.c new file mode 100644 index 0000000..85030ca --- /dev/null +++ b/optee/samples/ftpm-helper/ta/ftpm_helper_ta.c @@ -0,0 +1,480 @@ +/* + * Copyright (c) 2023-2024, NVIDIA Corporation & AFFILIATES. All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#ifdef CFG_JETSON_FTPM_HELPER_PTA +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* EK CSR structure */ +typedef struct ek_csr_t { + uint8_t *csr_head; + uint32_t csr_total_len; + uint8_t *tbs_ptr; + uint32_t tbs_len; + uint32_t sig_len; +} ek_csr_t; + +static TEE_Result invoke_ftpm_helper_pta(uint32_t cmd_id, + uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + static TEE_TASessionHandle pta_sess = TEE_HANDLE_NULL; + const TEE_UUID uuid = FTPM_HELPER_PTA_UUID; + + if (TEE_HANDLE_NULL == pta_sess) { + TEE_Result rc = TEE_OpenTASession(&uuid, TEE_TIMEOUT_INFINITE, + 0, NULL, &pta_sess, NULL); + + if (rc) + return rc; + } + + return TEE_InvokeTACommand(pta_sess, TEE_TIMEOUT_INFINITE, cmd_id, + param_types, params, NULL); +} + +static TEE_Result calc_csr_tbs_hash(const uint8_t *tbs_ptr, uint32_t tbs_len, + uint8_t *hash, size_t *hash_len) +{ + TEE_OperationHandle hash_op = TEE_HANDLE_NULL; + TEE_Result rc = TEE_SUCCESS; + + /* Calculate the digest of the CSR TBS */ + rc = TEE_AllocateOperation(&hash_op, TEE_ALG_SHA256, TEE_MODE_DIGEST, 0); + if (rc != TEE_SUCCESS) + return rc; + + rc = TEE_DigestDoFinal(hash_op, tbs_ptr, tbs_len, hash, hash_len); + TEE_FreeOperation(hash_op); + + return rc; +} + +static TEE_Result sign_csr_digest(uint8_t *tbs_digest, uint32_t digest_len, + uint8_t *sig, uint32_t *sig_len) +{ + uint32_t pt; + TEE_Param pta_params[TEE_NUM_PARAMS] = { }; + TEE_Result rc = TEE_SUCCESS; + mbedtls_mpi r; + mbedtls_mpi s; + uint32_t r_len; + uint8_t buf[MBEDTLS_ECDSA_MAX_LEN] = { 0 }; + uint8_t *p = buf + sizeof(buf); + uint32_t len = 0; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* The input parameters. */ + pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if ((TEE_SHA256_HASH_SIZE != digest_len) || + (FTPM_EK_CSR_SIG_SIZE != *sig_len)) + return TEE_ERROR_BAD_PARAMETERS; + + pta_params[0].memref.buffer = tbs_digest; + pta_params[0].memref.size = digest_len; + pta_params[1].memref.buffer = sig; + pta_params[1].memref.size = *sig_len; + + rc = invoke_ftpm_helper_pta(FTPM_HELPER_PTA_CMD_SIGN_EK_CSR, + pt, pta_params); + if (rc != TEE_SUCCESS) + return rc; + + /* Convert the signature to ASN1 format. */ + r_len = pta_params[1].memref.size / 2; + mbedtls_mpi_init(&r); + mbedtls_mpi_init(&s); + + mbedtls_mpi_read_binary(&r, sig, r_len); + mbedtls_mpi_read_binary(&s, sig + r_len, r_len); + + 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)); + + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, buf, 0)); // unused bits + 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_BIT_STRING)); + + if (len <= FTPM_EK_CSR_SIG_SIZE) { + memcpy(sig, p, len); + *sig_len = len; + } else { + rc = TEE_ERROR_SHORT_BUFFER; + } + + mbedtls_mpi_free(&r); + mbedtls_mpi_free(&s); + + return rc; +} + +static TEE_Result resign_ek_csr(uint8_t *ek_csr_ptr, size_t *ek_csr_len) +{ + ek_csr_t ek_csr; + uint8_t *csr_ptr, *csr_end; + size_t csr_len; + uint8_t *hash_buf = NULL; + size_t hash_len; + uint8_t *oid_sig_buf = NULL; + uint8_t *oid_sig_buf_update = NULL; + uint32_t oid_sig_len = FTPM_EK_CSR_SIG_SIZE + 20; + uint32_t final_oid_sig_len = 0; + uint8_t *sig_buf = NULL; + uint32_t sig_len[1]; + uint32_t len_diff = 0; + char oid_sig_alg_ecdsa_sha256[] = MBEDTLS_OID_ECDSA_SHA256; + TEE_Result rc = TEE_SUCCESS; + int ret; + + if (!ek_csr_ptr || !ek_csr_len[0]) + return TEE_ERROR_NO_DATA; + + csr_len = *ek_csr_len; + csr_ptr = ek_csr_ptr; + csr_end = csr_ptr + csr_len; + + /* Allocate buffers. */ + hash_buf = calloc(1, TEE_SHA256_HASH_SIZE); + if (!hash_buf) { + rc = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + oid_sig_buf = calloc(1, oid_sig_len); + if (!oid_sig_buf) { + rc = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + sig_buf = calloc(1, FTPM_EK_CSR_SIG_SIZE); + if (!sig_buf) { + rc = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + ek_csr.csr_head = csr_ptr; + ek_csr.csr_total_len = csr_len; + + /* Certification Request */ + ret = mbedtls_asn1_get_tag(&csr_ptr, csr_end, &csr_len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + if (ret != 0) { + rc = TEE_ERROR_BAD_FORMAT; + goto out; + } + + ek_csr.tbs_ptr = csr_ptr; + + /* Certificate Request Info */ + ret = mbedtls_asn1_get_tag(&csr_ptr, csr_end, &csr_len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + if (ret != 0) { + rc = TEE_ERROR_BAD_FORMAT; + goto out; + } + + ek_csr.tbs_len = csr_len + 4; // ASN1 SEQUENCE offset + + /* Calculate the hash of TBS */ + hash_len = TEE_SHA256_HASH_SIZE; + rc = calc_csr_tbs_hash(ek_csr.tbs_ptr, ek_csr.tbs_len, + hash_buf, &hash_len); + if (rc != TEE_SUCCESS) + goto out; + + /* Sign EK CSR */ + sig_len[0] = FTPM_EK_CSR_SIG_SIZE; + rc = sign_csr_digest(hash_buf, hash_len, + sig_buf, &sig_len[0]); + + /* Update Signature Algorithm and Signature. */ + csr_ptr += csr_len; + ek_csr.sig_len = ek_csr.csr_total_len - ek_csr.tbs_len - 4; + memset(csr_ptr, 0, ek_csr.sig_len); + + /* Len of Sig_alg and Sig = header len(4) + OID len of Ecdsa_sha256(8) + Sig_len */ + oid_sig_buf_update = oid_sig_buf + 4 + sizeof(oid_sig_alg_ecdsa_sha256) - 1 + sig_len[0]; + + /* Update signature. */ + MBEDTLS_ASN1_CHK_ADD(final_oid_sig_len, + mbedtls_asn1_write_raw_buffer(&oid_sig_buf_update, + oid_sig_buf, + (const unsigned char *) sig_buf, + sig_len[0])); + /* Update OID of Sig_alg (ECDSA_SHA256). */ + MBEDTLS_ASN1_CHK_ADD(final_oid_sig_len, + mbedtls_asn1_write_oid(&oid_sig_buf_update, + oid_sig_buf, + oid_sig_alg_ecdsa_sha256, + sizeof(oid_sig_alg_ecdsa_sha256) - 1)); + + /* Update len of Sig_alg. */ + MBEDTLS_ASN1_CHK_ADD(final_oid_sig_len, + mbedtls_asn1_write_len(&oid_sig_buf_update, + oid_sig_buf, + sizeof(oid_sig_alg_ecdsa_sha256) - 1 + 2)); + + /* Update header of ASN1 SEQ. */ + MBEDTLS_ASN1_CHK_ADD(final_oid_sig_len, + mbedtls_asn1_write_tag(&oid_sig_buf_update, + oid_sig_buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); + + memcpy(csr_ptr, oid_sig_buf, final_oid_sig_len); + + /* Update the CSR length. */ + if (ek_csr.sig_len > final_oid_sig_len) { + len_diff = ek_csr.sig_len - final_oid_sig_len; + ek_csr.csr_total_len -= len_diff; + } else if (ek_csr.sig_len < final_oid_sig_len) { + len_diff = final_oid_sig_len - ek_csr.sig_len; + ek_csr.csr_total_len += len_diff; + } + + if (len_diff != 0) { + /* Update the CSR length. */ + uint8_t *buf = ek_csr.csr_head; + uint8_t *p = buf + 4; // ASN1 SEQUENCE offset + uint32_t len = 0; + + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, buf, ek_csr.csr_total_len - 4)); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); + + if (len != 4) { + rc = TEE_ERROR_SHORT_BUFFER; + goto out; + } + } + + *ek_csr_len = ek_csr.csr_total_len; + +out: + if (!hash_buf) + free(hash_buf); + if (!oid_sig_buf) + free(oid_sig_buf); + if (!sig_buf) + free(sig_buf); + + return rc; +} + +static TEE_Result sign_ek_csr(uint32_t ptypes, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result rc = TEE_SUCCESS; + uint32_t exp_pt; + + /* Validate the input parameters. */ + 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 != ptypes) + return TEE_ERROR_BAD_PARAMETERS; + + if (FTPM_EK_CSR_BUF_SIZE < params[0].memref.size) + return TEE_ERROR_BAD_PARAMETERS; + + resign_ek_csr(params[0].memref.buffer, ¶ms[0].memref.size); + + return rc; +} + +static TEE_Result query_pta(uint32_t cmd_id, + uint32_t data_len, + uint32_t ptypes, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint32_t exp_pt; + uint32_t data_out_pt0, data_out_pt1, data_out_pt2; + TEE_Param pta_params[TEE_NUM_PARAMS] = { }; + TEE_Result rc = TEE_SUCCESS; + + if (cmd_id == FTPM_HELPER_PTA_CMD_QUERY_PROV_MODE) { + data_out_pt0 = TEE_PARAM_TYPE_VALUE_OUTPUT; + data_out_pt1 = TEE_PARAM_TYPE_VALUE_OUTPUT; + data_out_pt2 = TEE_PARAM_TYPE_VALUE_OUTPUT; + } else { + data_out_pt0 = TEE_PARAM_TYPE_MEMREF_OUTPUT; + data_out_pt1 = TEE_PARAM_TYPE_NONE; + data_out_pt2 = TEE_PARAM_TYPE_NONE; + } + + /* Validate the input parameters. */ + exp_pt = TEE_PARAM_TYPES(data_out_pt0, + data_out_pt1, + data_out_pt2, + TEE_PARAM_TYPE_NONE); + + if (exp_pt != ptypes) + return TEE_ERROR_BAD_PARAMETERS; + + if (data_out_pt0 == TEE_PARAM_TYPE_MEMREF_OUTPUT && + data_len != params[0].memref.size) + return TEE_ERROR_BAD_PARAMETERS; + + if (data_out_pt0 == TEE_PARAM_TYPE_MEMREF_OUTPUT) { + pta_params[0].memref.buffer = params[0].memref.buffer; + pta_params[0].memref.size = params[0].memref.size; + } + + rc = invoke_ftpm_helper_pta(cmd_id, + exp_pt, pta_params); + if (rc != TEE_SUCCESS) + return rc; + + if (data_out_pt0 == TEE_PARAM_TYPE_MEMREF_OUTPUT) { + params[0].memref.size = pta_params[0].memref.size; + } else { + params[0].value.a = pta_params[0].value.a; + params[1].value.a = pta_params[1].value.a; + params[2].value.a = pta_params[2].value.a; + } + + return rc; +} + +#if defined(CFG_JETSON_FTPM_HELPER_INJECT_EPS) +static TEE_Result ta_inject_eps(uint32_t ptypes, TEE_Param params[TEE_NUM_PARAMS]) +{ + uint32_t exp_pt; + + /* Validate the input parameters. */ + 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 != ptypes) + return TEE_ERROR_BAD_PARAMETERS; + + if (params[0].memref.size != FTPM_HELPER_TA_EPS_BYTES) + return TEE_ERROR_BAD_PARAMETERS; + + return invoke_ftpm_helper_pta(FTPM_HELPER_PTA_CMD_INJECT_EPS, exp_pt, params); +} +#else +static TEE_Result ta_inject_eps(uint32_t __unused ptypes, + TEE_Param __unused params[TEE_NUM_PARAMS]) +{ + return TEE_ERROR_NOT_SUPPORTED; +} +#endif + +TEE_Result TA_CreateEntryPoint(void) +{ + TEE_Result rc = TEE_SUCCESS; + + return rc; +} + +void TA_DestroyEntryPoint(void) +{ +} + +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 __unused cmd, + uint32_t __unused param_types, + TEE_Param __unused params[TEE_NUM_PARAMS]) +{ + switch (cmd) { + case FTPM_HELPER_TA_CMD_QUERY_SN: + return query_pta(FTPM_HELPER_PTA_CMD_QUERY_SN, + FTPM_HELPER_TA_SN_LENGTH, + param_types, params); + case FTPM_HELPER_TA_CMD_QUERY_ECID: + return query_pta(FTPM_HELPER_PTA_CMD_QUERY_ECID, + FTPM_HELPER_TA_ECID_LENGTH, + param_types, params); + case FTPM_HELPER_TA_CMD_QUERY_PROV_MODE: + return query_pta(FTPM_HELPER_PTA_CMD_QUERY_PROV_MODE, + 0, param_types, params); + case FTPM_HELPER_TA_CMD_GET_RSA_EK_CERT: + return query_pta(FTPM_HELPER_PTA_CMD_GET_RSA_EK_CERT, + FTPM_EK_CERT_BUF_SIZE, param_types, params); + case FTPM_HELPER_TA_CMD_GET_EC_EK_CERT: + return query_pta(FTPM_HELPER_PTA_CMD_GET_EC_EK_CERT, + FTPM_EK_CERT_BUF_SIZE, param_types, params); + case FTPM_HELPER_TA_CMD_GET_SID_CERT: + return query_pta(FTPM_HELPER_PTA_CMD_GET_SID_CERT, + FTPM_EK_CERT_BUF_SIZE, param_types, params); + case FTPM_HELPER_TA_CMD_GET_FW_ID_CERT: + return query_pta(FTPM_HELPER_PTA_CMD_GET_FW_ID_CERT, + FTPM_EK_CERT_BUF_SIZE, param_types, params); + case FTPM_HELPER_TA_CMD_GET_RSA_EK_CSR: + return query_pta(FTPM_HELPER_PTA_CMD_GET_RSA_EK_CSR, + FTPM_EK_CERT_BUF_SIZE, param_types, params); + case FTPM_HELPER_TA_CMD_GET_EC_EK_CSR: + return query_pta(FTPM_HELPER_PTA_CMD_GET_EC_EK_CSR, + FTPM_EK_CERT_BUF_SIZE, param_types, params); + case FTPM_HELPER_TA_CMD_SIGN_EK_CSR: + return sign_ek_csr(param_types, params); + case FTPM_HELPER_TA_CMD_INJECT_EPS: + return ta_inject_eps(param_types, params); + default: + return TEE_ERROR_NOT_SUPPORTED; + } +} +#else /* CFG_JETSON_FTPM_HELPER_PTA */ +TEE_Result TA_CreateEntryPoint(void) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +void TA_DestroyEntryPoint(void) +{ +} + +TEE_Result TA_OpenSessionEntryPoint(uint32_t __unused param_types, + TEE_Param __unused params[TEE_NUM_PARAMS], + void __unused **session) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +void TA_CloseSessionEntryPoint(void __unused *session) +{ +} + +TEE_Result TA_InvokeCommandEntryPoint(void __unused *session, + uint32_t __unused cmd, + uint32_t __unused param_types, + TEE_Param __unused params[TEE_NUM_PARAMS]) +{ + return TEE_ERROR_NOT_SUPPORTED; +} +#endif /* CFG_JETSON_FTPM_HELPER_PTA */ diff --git a/optee/samples/ftpm-helper/ta/include/ftpm_helper_ta.h b/optee/samples/ftpm-helper/ta/include/ftpm_helper_ta.h new file mode 100644 index 0000000..35701c2 --- /dev/null +++ b/optee/samples/ftpm-helper/ta/include/ftpm_helper_ta.h @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2023-2024, NVIDIA Corporation & AFFILIATES. All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef __FTPM_HELPER_TA_H__ +#define __FTPM_HELPER_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 : {a6a3a74a-77cb-433a-990c-1dfb8a3fbc4c} + */ +#define FTPM_HELPER_TA_UUID \ + { 0xa6a3a74a, 0x77cb, 0x433a, \ + { 0x99, 0x0c, 0x1d, 0xfb, 0x8a, 0x3f, 0xbc, 0x4c} } + +#define FTPM_HELPER_TA_ECID_LENGTH 8U +#define FTPM_HELPER_TA_SN_LENGTH 10U +#define FTPM_HELPER_TA_EPS_BITS 512U +#define FTPM_HELPER_TA_EPS_BYTES (FTPM_HELPER_TA_EPS_BITS / 8U) + +/* EK Certificate buffer size */ +#define FTPM_EK_CERT_BUF_SIZE 2048U +/* EK CSR buffer size */ +#define FTPM_EK_CSR_BUF_SIZE 2048U + +/* fTPM Provisioning mode */ +#define FTPM_PROV_MODE_OFFLINE 0xff00000a +#define FTPM_PROV_MODE_ONLINE 0xff00000b +#define FTPM_PROV_MODE_UNKNOWN 0xff00000c + +/* + * FTPM_HELPER_TA_CMD_QUERY_SN - Query the device serial number + * param[0] out (memref) data buffer and size + * param[1] unused + * param[2] unused + * param[3] unused + */ +#define FTPM_HELPER_TA_CMD_QUERY_SN 0xff000001 + +/* + * FTPM_HELPER_TA_CMD_QUERY_ECID - Query the device ECID + * param[0] out (memref) data buffer and size + * param[1] unused + * param[2] unused + * param[3] unused + */ +#define FTPM_HELPER_TA_CMD_QUERY_ECID 0xff000002 + +/* + * FTPM_HELPER_TA_CMD_QUERY_PROV_MODE - Query the provisioning mode + * param[0] out (value) a: The defined value of provisioning scheme. + * param[1] out (value) a: The version major number. + * param[2] out (value) a: The version minor number. + * param[3] unused + */ +#define FTPM_HELPER_TA_CMD_QUERY_PROV_MODE 0xff000003 + +/* + * FTPM_HELPER_TA_CMD_GET_RSA_EK_CERT - Get the fTPM RSA EK Certificate + * param[0] out (memref) data buffer and size + * param[1] unused + * param[2] unused + * param[3] unused + */ +#define FTPM_HELPER_TA_CMD_GET_RSA_EK_CERT 0xff000004 + +/* + * FTPM_HELPER_TA_CMD_GET_EC_EK_CERT - Get the fTPM EC EK Certificate + * param[0] out (memref) data buffer and size + * param[1] unused + * param[2] unused + * param[3] unused + */ +#define FTPM_HELPER_TA_CMD_GET_EC_EK_CERT 0xff000005 + +/* + * FTPM_HELPER_TA_CMD_GET_SID_CERT - Get the Silicon ID Certificate + * param[0] out (memref) data buffer and size + * param[1] unused + * param[2] unused + * param[3] unused + */ +#define FTPM_HELPER_TA_CMD_GET_SID_CERT 0xffff0006 + +/* + * FTPM_HELPER_TA_CMD_GET_FW_ID_CERT - Get the Firmware ID Certificate + * param[0] out (memref) data buffer and size + * param[1] unused + * param[2] unused + * param[3] unused + */ +#define FTPM_HELPER_TA_CMD_GET_FW_ID_CERT 0xffff0007 + +/* + * FTPM_HELPER_TA_CMD_GET_RSA_EK_CSR - Get the fTPM RSA EK CSR + * param[0] out (memref) data buffer and size + * param[1] unused + * param[2] unused + * param[3] unused + */ +#define FTPM_HELPER_TA_CMD_GET_RSA_EK_CSR 0xffff0008 + +/* + * FTPM_HELPER_TA_CMD_GET_EC_EK_CSR - Get the fTPM EC EK CSR + * param[0] out (memref) data buffer and size + * param[1] unused + * param[2] unused + * param[3] unused + */ +#define FTPM_HELPER_TA_CMD_GET_EC_EK_CSR 0xffff0009 + +/* + * FTPM_HELPER_TA_CMD_SIGN_EK_CSR - Receive the EK CSR and sign it + * param[0] in/out (memref) data buffer and size + * param[1] unused + * param[2] unused + * param[3] unused + */ +#define FTPM_HELPER_TA_CMD_SIGN_EK_CSR 0xffff000a + +/* + * FTPM_HELPER_TA_CMD_INJECT_EPS - Inject an EPS into fTPM + * param[0] in (memref) the buffer contains EPS + * param[1] unused + * param[2] unused + * param[3] unused + */ +#define FTPM_HELPER_TA_CMD_INJECT_EPS 0xff00000b + +#endif /* __FTPM_HELPER_TA_H__ */ diff --git a/optee/samples/ftpm-helper/ta/sub.mk b/optee/samples/ftpm-helper/ta/sub.mk new file mode 100644 index 0000000..a22def3 --- /dev/null +++ b/optee/samples/ftpm-helper/ta/sub.mk @@ -0,0 +1,6 @@ +# Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause + +global-incdirs-y += include +cflags-y += -I$(TA_DEV_KIT_DIR)/host_include +srcs-y += ftpm_helper_ta.c diff --git a/optee/samples/ftpm-helper/ta/user_ta_header_defines.h b/optee/samples/ftpm-helper/ta/user_ta_header_defines.h new file mode 100644 index 0000000..89ba98b --- /dev/null +++ b/optee/samples/ftpm-helper/ta/user_ta_header_defines.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023-2024, 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 FTPM_HELPER_TA_UUID +#define TA_FLAGS (TA_FLAG_SINGLE_INSTANCE | \ + TA_FLAG_INSTANCE_KEEP_ALIVE) +#define TA_STACK_SIZE (2 * 1024) +#define TA_DATA_SIZE (4 * 1024) + +#endif /* __USER_TA_HEADER_DEFINES_H__ */ 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..13b0882 --- /dev/null +++ b/optee/samples/hwkey-agent/host/tool/gen_ekb/README @@ -0,0 +1,143 @@ +# Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause +********************************************************************** + 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 +contains an EKB header (this data included EKB size, Magic, Major, +Minor, FV and MAC), a content header (this data included Content size, +Content magic, a Reserved field and IV) and encrypted user keys or +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 + +---------------------------------------------------------------------- +EKB layout +---------------------------------------------------------------------- + +Note that you can define a specific mechanism to encapsulate the EKB +contents depending on the requirement. Shown here is a reference +implementation. + +----------------------------------------------------------- +| EKB_size | Magic | Major | Minor | +| (4 bytes) | (8 bytes) | (2 bytes) | (2 bytes) | +----------------------------------------------------------- +| FV (16 bytes) | +----------------------------------------------------------- +| MAC (16 bytes) | +----------------------------------------------------------- +| Content_size | Content_magic | Reserved | +| (4 bytes) | (4 bytes) | (8 bytes) | +----------------------------------------------------------- +| IV (16 bytes) | +----------------------------------------------------------- +| Key1_tag | Key1_len | Key1 | +| (4 bytes) | (4 bytes) | (Key1_len) | +----------------------------------------------------------- +| Key2_tag | Key2_len | Key2 | +| (4 bytes) | (4 bytes) | (Key2_len) | +----------------------------------------------------------- +| ... | +----------------------------------------------------------- +| End_tag1(\0\0\0\0) | End_tag2 (\0\0\0\0) | +----------------------------------------------------------- + +* Each row in the first five rows occupies 16 bytes +* Each row aftet "IV" is not fixed legnth +* The key 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 EKB root key(EKB_RK) + * Generate a random fixed vector (FV), and also save it to FV field + of EKB header. + * Deriving EBK_RK from fuse key(T234: OEM_K1) + * EKB_RK = AES-128-ECB(fuse_key, FV) +* Generate EKB_EK and EKB_AK 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 + * Generate a random initial vector (IV), and also save it to IV field + of EKB content header + * Content_ciphertext = AES-128-CBC(EKB_EK, IV, Content_plaintext) + * EKB_content = EKB_content_header + Content_ciphertext +* Acquire message authentication code (MAC) + * MAC = AES-CMAC(EKB_AK, EKB_content) + * Save MAC to MAC field of EKB header +* Generate EKB blob (eks.img) + * EKB = EKB_header + EKB_content + +---------------------------------------------------------------------- +Default EKB Binary +---------------------------------------------------------------------- + +The default EKB binary is located at: +/bootloader/eks_t234.img + +---------------------------------------------------------------------- +How to use the gen_ekb.py +---------------------------------------------------------------------- + +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: t234 +-oem_k1_key: 32-byte OEM key 1 key file in hex format +-in_sym_key: 32-byte UEFI payload encryption key file in hex format +-in_sym_key2: 16-byte disk encryption key file in hex format +-in_auth_key: 16-byte UEFI variable authentication key file in hex format +-in_ftpm_sn: 20 bytes fTPM serial number in hex string +-in_ftpm_eps_seed: fTPM EPS seed file in hex format +-in_ftpm_rsa_ek_cert: fTPM RSA EK cert in DER format +-in_ftpm_ec_ek_cert: fTPM EC EK cert in DER format +-in_sid_cert: the device silicon ID cert in DER format +-in_ftpm_rsa_ek_csr: fTPM RSA EK csr in DER format +-in_ftpm_ec_ek_csr: fTPM EC EK csr in DER format +-out: where the eks image file is stored + +Following the command for example. + +$ python3 gen_ekb.py + -chip t234 \ + -oem_k1_key oem_k1.key \ + -in_sym_key sym_t234.key \ + -in_sym_key2 sym2_t234.key \ + -in_auth_key auth_t234.key \ + -in_ftpm_sn 00000000000000000000 \ + -in_ftpm_eps_seed ftpm_eps_seed_file \ + -in_ftpm_rsa_ek_cert ftpm_rsa_ek_cert.der \ + -in_ftpm_ec_ek_cert ftpm_ec_ek_cert.der \ + -in_sid_cert sid_cert.der \ + -in_ftpm_rsa_ek_csr ftpm_rsa_ek_csr.der \ + -in_ftpm_ec_ek_csr ftpm_ec_ek_csr.der \ + -out eks_t234.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..a59dc34 --- /dev/null +++ b/optee/samples/hwkey-agent/host/tool/gen_ekb/example.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +# Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause + +# [T234 example] +# Fill your OEM_K1 fuse key value +# echo "0000000000000000000000000000000000000000000000000000000000000000" > oem_k1.key + +# Generate user-defined symmetric key files +# A random generate key is recommended for production, and a specified key is recommended for testing +# For each key, there are reference examples for generating random key and specifying keys. +# openssl rand -rand /dev/urandom -hex 32 > sym_t234.key # kernel/kernel-dtb encryption key +# echo "0000000000000000000000000000000000000000000000000000000000000000" > sym_t234.key +# openssl rand -rand /dev/urandom -hex 16 > sym2_t234.key # disk encryption key +# echo "00000000000000000000000000000000" > sym2_t234.key +# openssl rand -rand /dev/urandom -hex 16 > auth_t234.key # uefi variables authentication key +# echo "00000000000000000000000000000000" > auth_t234.key + +python3 gen_ekb.py -chip t234 -oem_k1_key oem_k1.key \ + -in_sym_key sym_t234.key \ + -in_sym_key2 sym2_t234.key \ + -in_auth_key auth_t234.key \ + -in_ftpm_sn 00000000000000000000 \ + -in_ftpm_eps_seed ftpm_eps_seed_file \ + -in_ftpm_rsa_ek_cert ftpm_rsa_ek_cert.der \ + -in_ftpm_ec_ek_cert ftpm_ec_ek_cert.der \ + -in_sid_cert sid_cert.der \ + -in_ftpm_rsa_ek_csr ftpm_rsa_ek_csr.der \ + -in_ftpm_ec_ek_csr ftpm_ec_ek_csr.der \ + -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..f20f47a --- /dev/null +++ b/optee/samples/hwkey-agent/host/tool/gen_ekb/gen_ekb.py @@ -0,0 +1,271 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2021-2024, 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) +# 1.5: Add encoding fTPM serial number (SN), EPS seed and two fTPM EK Certificates (RSA and EC) support +# 1.6: Add encoding support for device Silicon ID certificate, fTPM RSA, and EC EK CSR +# + +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 + +# EKB verison number upgrade strategy +# Increment major version number when changing EKB header +# Increment minor version number when changing EKB content + +# EKB version +# Version 1.0: Initial version +# Version 2.0: Add fv to the ekb header +version_major = 2 +version_minor = 0 + +# EKB key types +ekb_kernel_encryption_key = 1; +ekb_disk_encryption_key = 2; +ekb_uefi_var_auth_key = 4; +ekb_ftpm_sn = 91; +ekb_ftpm_eps_seed = 92; +ekb_ftpm_rsa_ek_cert = 93; +ekb_ftpm_ec_ek_cert = 94; +ekb_sid_cert = 95; +ekb_ftpm_rsa_ek_csr = 96; +ekb_ftpm_ec_ek_csr = 97; + +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, fv, 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(fv) + 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(fv) + 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 + fv + 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() + content = content.decode('utf-8') + if content.startswith(('0x', '0X')): + key = codecs.decode(content[2:], 'hex') + else: + 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 +#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_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE); + TEE_Param pta_params[TEE_NUM_PARAMS] = { }; + TEE_Attribute attr; + uint32_t mode; + char label_str_for_hwkey_agent_key[] = "hwkey-agent-encryption-key"; + + /* Generate hwkey-agent encryption key. */ + pta_params[0].value.a = EKB_USER_KEY_DISK_ENCRYPTION; + pta_params[1].memref.buffer = label_str_for_hwkey_agent_key; + pta_params[1].memref.size = strlen(label_str_for_hwkey_agent_key); + pta_params[2].memref.buffer = sess->ekb_key; + pta_params[2].memref.size = AES128_KEY_BYTE_SIZE; + rc = invoke_jetson_user_key_pta(JETSON_USER_KEY_CMD_GEN_UNIQUE_KEY_BY_EKB, + 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/samples/ms-tpm-20-ref/.clang-format b/optee/samples/ms-tpm-20-ref/.clang-format new file mode 100644 index 0000000..26658ad --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/.clang-format @@ -0,0 +1,97 @@ +--- +Language: Cpp +BasedOnStyle: Microsoft +AccessModifierOffset: -4 +# AlwaysBreak & BlockIndent are buggy +# AlwaysBreak: https://github.com/llvm/llvm-project/issues/57241 +# BlockIndent: https://github.com/llvm/llvm-project/issues/57250 +# Align is widely the default and seems to work more reasonably. +AlignAfterOpenBracket: Align +AlignConsecutiveMacros: Consecutive +AlignConsecutiveAssignments: AcrossEmptyLines +AlignConsecutiveBitFields: AcrossEmptyLines +AlignConsecutiveDeclarations: AcrossEmptyLines +AlignEscapedNewlines: Left +AlignOperands: Align +BreakBeforeBinaryOperators: NonAssignment +# style Microsoft is actually for C# but TPM code base historically uses ~80 chars +ColumnLimit: 86 +# don't break after return types, though clang-format seems to have some issues +# with this and still breaks after TPM_RC and some other types. +# open issue with LLVM, no confirmation or workaround identified yet. +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +# we prefer one parameter per line since many parameters have comments +# and binpacking will create extra inconsistency +BinPackArguments: false +BinPackParameters: false +# Microsft standard C/C++ braces +BreakBeforeBraces: Allman +IncludeBlocks: Preserve +IndentCaseLabels: true +IndentCaseBlocks: false +IndentGotoLabels: false +# Before hash can misalign comments when IndentWidth and PPIndentWidth differ. +IndentPPDirectives: AfterHash +IndentWidth: 4 +PPIndentWidth: 2 +# resist line-length excursions +PenaltyExcessCharacter: 100000 +# prefer not to break after '='' and '(' for function calls +# can still happen based on length of components +PenaltyBreakAssignment: 10 +PenaltyBreakBeforeFirstCallParameter: 1000 +# prefer to break a string constant rather than wrap the entire set of +# array brackets and equal sign. If this is too high, can produce this: +# const char somereallylongvariablename +# [] = "...." +# which is really weird. +PenaltyBreakString: 10 +PenaltyBreakOpenParenthesis: 1 +# really dislike breaking after bare return type, wastes vertical space. +PenaltyReturnTypeOnItsOwnLine: 100000000 +# FOO* bar, not FOO *bar +PointerAlignment: Left +# don't touch comments that might have MD tables or other +# complex snippets +ReflowComments: false +# don't sort includes because we can't be sure includes are order-agnostic. +SortIncludes: false +SpaceAroundPointerQualifiers: Default +SpacesBeforeTrailingComments: 2 +SpacesInConditionalStatement: false +# current code is inconsistent, but a simple search for "if (" and "if(" +# shows false to be most consistent with existing TPM code by +# about 2-to-1 +SpaceBeforeParens: false +StatementMacros: + - _Acquires_exclusive_lock_ + - _Acquires_lock_ + - _Function_class_ + - _IRQL_requires_ + - _Must_inspect_result_ + - _No_competing_thread_ + - _Post_same_lock_ + - _Post_writable_byte_size_ + - _Pre_satisfies_ + - _Releases_lock_ + - _Requires_exclusive_lock_held_ + - _Requires_lock_held_ + - _Requires_lock_not_held_ + - _Requires_shared_lock_held_ + - _Ret_maybenull_ + - _Success_ + - _Use_decl_annotations_ + - "DLPENTRY\n" +TabWidth: 4 +TypenameMacros: + - BN_STRUCT_DEF +DeriveLineEnding: false +UseCRLF: false +UseTab: Never +WhitespaceSensitiveMacros: + - STRINGIZE + - LIB_QUOTE + - LIB_INCLUDE2 + - PROFILE_QUOTE +... diff --git a/optee/samples/ms-tpm-20-ref/.travis.yml b/optee/samples/ms-tpm-20-ref/.travis.yml new file mode 100644 index 0000000..92b333d --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/.travis.yml @@ -0,0 +1,38 @@ +language: c +dist: bionic +compiler: + - clang + - gcc + +addons: + apt: + packages: + - autoconf-archive + +arch: + - amd64 + - arm64 + - s390x + +matrix: + include: + - compiler: clang + env: CONF_OPT="--host=i686-pc-linux-gnu" CFLAGS="-m32" LDFLAGS="-m32" + - compiler: gcc + env: CONF_OPT="--host=i686-pc-linux-gnu" CFLAGS="-m32" LDFLAGS="-m32" + +before_install: + - | + if [ $LDFLAGS = "-m32" ]; then + sudo dpkg --add-architecture i386 + sudo apt-get update + sudo apt-get install gcc-multilib libssl-dev:i386 + fi + +before_script: + - cd TPMCmd + +script: + - ./bootstrap + - ./configure ${CONF_OPT} + - make --jobs=$(($(nproc)*3/2)) distcheck diff --git a/optee/samples/ms-tpm-20-ref/CONTRIBUTING.md b/optee/samples/ms-tpm-20-ref/CONTRIBUTING.md new file mode 100644 index 0000000..824d12a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/CONTRIBUTING.md @@ -0,0 +1,42 @@ +# Guidelines for reporting bugs: +Non-security-critical bugs can be filed on the Issues tracker: + +https://github.com/Microsoft/ms-tpm-20-ref/issues + +Security sensitive bugs should be reported to secure@microsoft.com + +# Guideline for submitting changes: + +This repository tracks official TPM Library Specification releases and errata from +the Trusted Computing Group: + +https://trustedcomputinggroup.org/tpm-library-specification/ + +All changes to core TPM logic, particularly changes to files in +TPMCmd/tpm and its subdirectories, must be approved by TCG voting +members. Github pull requests may be used to propose changes, but changes +will not be incorporated without TCG member approval. + +Other changes (e.g. new files or changes to TPMCmd/Platform or TPMCmd/Simulator), +particularly to support new platforms, scenarios, build environments or +crypto-libraries, will be considered if they are expected to be widely useful. + +Contributors that wish to be involved in +the future evolution of the TPM specification and reference implementation +should consider joining the Trusted Computing Group. Information about +membership and liaison programs is available at https://trustedcomputinggroup.org/membership/ + +# Contributing + +This project welcomes contributions and suggestions. Most contributions require you to +agree to a Contributor License Agreement (CLA) declaring that you have the right to, +and actually do, grant us the rights to use your contribution. For details, visit +https://cla.microsoft.com. + +When you submit a pull request, a CLA-bot will automatically determine whether you need +to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the +instructions provided by the bot. You will only need to do this once across all repositories using our CLA. + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). +For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) +or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. diff --git a/optee/samples/ms-tpm-20-ref/CppProperties.json b/optee/samples/ms-tpm-20-ref/CppProperties.json new file mode 100644 index 0000000..659bf4e --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/CppProperties.json @@ -0,0 +1,21 @@ +{ + "configurations": [ + { + "inheritEnvironments": [ + "msvc_x86" + ], + "name": "x86-Debug", + "includePath": [ + "${env.INCLUDE}", + "${workspaceRoot}\\**" + ], + "defines": [ + "WIN32", + "_DEBUG", + "UNICODE", + "_UNICODE" + ], + "intelliSenseMode": "windows-msvc-x86" + } + ] +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/LICENSE b/optee/samples/ms-tpm-20-ref/LICENSE new file mode 100644 index 0000000..3dea085 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/LICENSE @@ -0,0 +1,17 @@ +Microsoft Reference Implementation for TPM 2.0 + +The copyright in this software is being made available under the BSD License, included below. This software may be subject to other third party and contributor rights, including patent rights, and no such rights are granted under this license. + +Copyright (c) Microsoft Corporation + +All rights reserved. + +BSD License + +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. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (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/ms-tpm-20-ref/README.md b/optee/samples/ms-tpm-20-ref/README.md new file mode 100644 index 0000000..04a3689 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/README.md @@ -0,0 +1,67 @@ +# Official TPM 2.0 Reference Implementation (by Microsoft) # + +[![Build Status](https://travis-ci.org/Microsoft/ms-tpm-20-ref.svg?branch=master)](https://travis-ci.org/Microsoft/ms-tpm-20-ref) + +This is the official TCG reference implementation of the [TPM 2.0 Specification](https://trustedcomputinggroup.org/tpm-library-specification). The project contains complete source code of the reference implementation with a Microsoft Visual Studio solution and Linux autotools build scripts. + +See the definition of the `SPEC_VERSION`, `SPEC_YEAR` and `SPEC_DAY_OF_YEAR` values in the [TpmTypes.h](TPMCmd/tpm/include/TpmTypes.h) header for the exact revision/date of the TPM 2.0 specification, which the given source tree snapshot corresponds to. + +The reference implementation can be directly used via the [TPM 2.0 simulator](TPMCmd/Simulator) that emulates a TPM 2.0 device and can be accessed via a custom TCP based protocol. The simplest way to work with the simulator is to use a [TSS library](https://github.com/Microsoft/TSS.MSR) for the programming language of your choice - C#/.Net, C++, Java, Python, JavaScript/Node.js are currently supported. The C language TSS implementing the TCG's TSS API specifiaction is available [here](https://github.com/tpm2-software/tpm2-tss). + +## Windows build ## + +Windows build is implemented as a Visual Studio 2017 solution. Before building it: + +* Setup one or both of the following underlying cryptographic libraries: + + ### OpenSSL library ### + + 1. Create `TPMCmd/lib` folder and place a static OpenSSL library (`libcrypto.lib`) built for the `x86` architecture there. For the `x64` architecture use the `TPMCmd/lib/x64` folder. + + The static libs can be either static libraries proper, or import libraries accompanying the corresponding DLLs. In the latter case you'll need to ensure that ther is a matching copy of the OpenSSL DLL in the standard Windows search path, so that it is available when you run the simulator executable (e.g. copy it into the same folder where `simulator.exe` is located). + + Recommended version of OpenSSL is `1.1.1d` or higher. + + 2. Create `TPMCmd/OsslInclude/openssl` folder and copy there the contents of the `openssl/include/openssl` folder in the OpenSSL source tree used to build the OpenSSL library. + + If you enable SM{2,3,4} algorithms in `TpmProfile.h`, the build may fail because of missing `SM{2,3,4}.h` headers. In this case you will need to manually copy them over from OpenSSL's `include/crypt` folder. + + 3. Build the solution with either Debug or Release as the active configuration. + + ### Wolfcrypt library (wolfSSL) ### + + 1. WolfSSL is included as a submodule. Initialize and update the submodule to fetch the project and checkout the appropriate commit. + + > git submodule init + > git submodule update + + The current commit will point the minimum recommended version of wolfSSL. Moving to a more recent tag or commit should also be supported but might not be tested. + + 2. Build the solution with either WolfDebug or WolfRelease as the active configuration, either from inside the Visual Studio or with the following command line: + + > msbuild TPMCmd\simulator.sln /p:Configuration=WolfDebug + +* If necessary, update the definitions of the following macros in the [VendorString.h](TPMCmd/tpm/include/VendorString.h) header: `MANUFACTURER`, `VENDOR_STRING_1`, `FIRMWARE_V1 and FIRMWARE_V2` + +## Linux build + +Follows the common `./bootstrap && ./configure && make` convention. + +Note that autotools scripts require the following prerequisite packages: `autoconf-archive`, `pkg-config`, and sometimes `build-essential` and `automake`. Their absence is not automatically detected. The build also needs `gcc` and `libssl-dev` packages. + +Similarly to the Windows build, if you enable SM{2,3,4} algorithms in `TpmProfile.h`, the build may fail because of missing `SM{2,3,4}.h` headers. In this case you will need to manually copy them over from OpenSSL's `include/crypt` folder. + +## Mac OS X build + +As with the Linux build, use `./bootstrap`, `./configure`, and `make`. +If you used Homebrew to install OpenSSL, you may need to include its path in `PKG_CONFIG_PATH`. +OS X compilers treat uninitialized global variables as +[common symbols](https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/MachOTopics/1-Articles/executing_files.html), +which can be eliminated with the `-fno-common` compiler option. +Future updates to the autotools configurations may automate one or both of these steps. + +``` +./bootstrap +PKG_CONFIG_PATH="/usr/local/opt/openssl/lib/pkgconfig" EXTRA_CFLAGS=-fno-common ./configure +make +``` diff --git a/optee/samples/ms-tpm-20-ref/SECURITY.md b/optee/samples/ms-tpm-20-ref/SECURITY.md new file mode 100644 index 0000000..869fdfe --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/SECURITY.md @@ -0,0 +1,41 @@ + + +## Security + +Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). + +If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. + +## Reporting Security Issues + +**Please do not report security vulnerabilities through public GitHub issues.** + +Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). + +If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). + +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). + +Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: + + * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) + * Full paths of source file(s) related to the manifestation of the issue + * The location of the affected source code (tag/branch/commit or direct URL) + * Any special configuration required to reproduce the issue + * Step-by-step instructions to reproduce the issue + * Proof-of-concept or exploit code (if possible) + * Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. + +## Preferred Languages + +We prefer all communications to be in English. + +## Policy + +Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). + + diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/README.md b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/README.md new file mode 100644 index 0000000..cb8f7c9 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/README.md @@ -0,0 +1,112 @@ +MS-IoT fTPM +=========== +## Trusted firmware for Windows based AArch32 (32-bit) ARM SoC's +Please see the [build-firmware document](https://github.com/ms-iot/imx-iotcore/blob/develop/Documentation/build-firmware.md) in the iMX IoT Core repo for additional information on including this TA in an IoT Core image for iMX boards. + +## Included TAs + +### fTPM TA +The fTPM Trusted Application (TA) provides a secure firmware implementation of a TPM using the MS reference implementation. +Platform specific code is copied and modified locally in [`optee_ta/fTPM/platform`](./optee_ta/fTPM/platform), while [`/fTPM/reference`](./fTPM/reference) contains files to support WolfSSL, control the fTPM's functionality, and define basic types, which may not be found in OpTEE. + +See the reference implementation for more details. + +--- + +## Extra Installation Steps + +The secure firmware utilizes the OP-TEE implementation of the Global Platform specifications. The OP-TEE project is +not duplicated in this repository but is obtained directly from the public release. The build of OP-TEE is based on a +native Linux build, however the following installation steps allow OP-TEE to be built under Windows using WSL. Only the optee_os +repository is relevant for trusted firmware use - the optee_client & optee_linuxdriver repositories are integration +components for Linux and can serve as a reference for the Windows equivalent components. Note that optee_linuxdriver +is GPL. + +OpTEE generates a build environment for trusted applications which is based on Make (See TA_DEV_KIT_DIR in the build directions). +This build environment places several constraints on how the code is organized, which are explained in the relevant makefiles. +See the [optee_os documentation](https://github.com/OP-TEE/optee_os/blob/master/documentation/build_system.md) for details about how OpTEE build works. + +#### 1. Enable Windows Subsystem for Linux +See instructions [here](https://docs.microsoft.com/en-us/windows/wsl/install-win10): + +#### 2. Launch Bash +Search for "bash" in the start menu, OR press Windows key + 'R', then type bash. +Update if needed. + +In WSL: +```sh +sudo apt-get update +``` + +#### 3. Install the ARM tool chain +Install the ARM toolchain to a directory of your choice. +```sh +cd ~ +wget https://releases.linaro.org/components/toolchain/binaries/6.4-2017.11/arm-linux-gnueabihf/gcc-linaro-6.4.1-2017.11-x86_64_arm-linux-gnueabihf.tar.xz +tar xf gcc-linaro-6.4.1-2017.11-x86_64_arm-linux-gnueabihf.tar.xz +rm gcc-linaro-6.4.1-2017.11-x86_64_arm-linux-gnueabihf.tar.xz +``` + +#### 4. Clone the OpTEE OS source code +If you do not already have a version of the OP-TEE OS repo cloned on your machine you may run: +```sh +cd ~ +git clone https://github.com/ms-iot/ms-iot-optee_os.git +``` + +#### 5. Build OP-TEE OS for the target platform + +`TA_CROSS_COMPILE` should point to the ARM toolchain installed in [step 3](#3-install-the-arm-tool-chain). + +```sh +cd ~/optee_os +CROSS_COMPILE=~/gcc-linaro-6.4.1-2017.11-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf- make PLATFORM=imx-mx6qhmbedge CFG_TEE_CORE_LOG_LEVEL=4 CFG_REE_FS=n CFG_RPMB_FS=y CFG_RPMB_TESTKEY=y CFG_RPMB_WRITE_KEY=y -j20 +``` +Additional information on Microsoft IoT fork of OP-TEE OS can be found [here](https://github.com/ms-iot/ms-iot-optee_os). + +#### 6. Clone the ms-tpm-20-ref source code +```sh +cd ~ +git clone https://github.com/Microsoft/ms-tpm-20-ref.git +``` + +#### 7. Initialize the git submodules +```sh +cd ~/ms-tpm-20-ref +git submodule init +git submodule update +``` + +--- + +## Building the TPM + +#### 1. Build the Firmware TPM Trusted Application +`TA_CROSS_COMPILE` should point to the ARM toolchain installed in [step 3](#3-install-the-arm-tool-chain). + +`TA_DEV_KIT_DIR` should point to the directory the optee_os TA devkit was compiled to in [step 5](#6-clone-the-ms-tpm-20-ref-source-code +). + +`-j` increases the parallelism of the build process. + +```sh +cd ~/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta +TA_CPU=cortex-a9 TA_CROSS_COMPILE=~/gcc-linaro-6.4.1-2017.11-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf- TA_DEV_KIT_DIR=~/optee_os/out/arm-plat-imx/export-ta_arm32 CFG_TEE_TA_LOG_LEVEL=2 make -j20 +``` +Debugging options you may want to add: + +`CFG_TEE_TA_LOG_LEVEL=3` 1 is fatal errors only, other values increase debug tracing output. + +`CFG_TA_DEBUG=y` Turns on debug output from the TAs, and enables extra correctness checks in the fTPM TA. + +#### 2. Measured Boot support +The fTPM Trusted Application includes support for Measured Boot. This feature allows the TA to read a TPM Event Log compatible with the specification in Section 5 of the +[TCG EFI Protocol Specification](https://trustedcomputinggroup.org/wp-content/uploads/EFI-Protocol-Specification-rev13-160330final.pdf). The event log is read and extended during the TA initialization. + +Measure Boot support requires OpTEE System Call ```PTA_SYSTEM_GET_TPM_EVENT_LOG```, available since [OpTEE 3.10.0](https://github.com/OP-TEE/optee_os/tree/3.10.0). + +Flags related to Measured Boot support: + +`CFG_TA_MEASURED_BOOT`: Controls whether Measured Boot is enabled (`CFG_TA_MEASURED_BOOT=y`) or disabled (by default). +`CFG_TA_EVENT_LOG_SIZE`: Maximum size in bytes allowed for the Event Log. Defaults to 1024 bytes. + diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/Makefile b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/Makefile new file mode 100644 index 0000000..c579fa8 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/Makefile @@ -0,0 +1,25 @@ + +export V?=0 + +# Input variables +# CROSS_COMPILE: The cross compiler. +# TA_DEV_KIT_DIR: The base directory of the TA-devkit +# OPTEE_OS_DIR: The base directory of the optee_os +# O: The base directory for build objects filetree. + +.PHONY: all +all: + $(MAKE) -C fTPM \ + CROSS_COMPILE=$(CROSS_COMPILE) \ + TA_DEV_KIT_DIR=$(TA_DEV_KIT_DIR) \ + OPTEE_OS_DIR=$(OPTEE_OS_DIR) \ + O=$(O)/early_ta/ms-tpm || exit 1 + +.PHONY: clean +clean: + $(MAKE) -C fTPM \ + CROSS_COMPILE=$(CROSS_COMPILE) \ + TA_DEV_KIT_DIR=$(TA_DEV_KIT_DIR) \ + OPTEE_OS_DIR=$(OPTEE_OS_DIR) \ + O=$(O)/early_ta/ms-tpm \ + clean || exit 1 diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/Makefile b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/Makefile new file mode 100644 index 0000000..b49ca9b --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/Makefile @@ -0,0 +1,37 @@ +BINARY=bc50d971-d4c9-42c4-82cb-343fb7f37896 + +TPM_ROOT_PATH := ../../../../ +WARNS := 0 +NOWERROR := 0 +CFG_TA_MEASURED_BOOT ?= n +CFG_TA_DEBUG ?= n +CFG_TEE_TA_LOG_LEVEL ?= 0 +CFG_TA_EVENT_LOG_SIZE ?= 1024 +CFG_USE_PLATFORM_EPS ?= n +TA_CPU ?= cortex-a57+fp+simd+crypto+crc + +cflags-y += -DTHIRTY_TWO_BIT \ + -D_ARM_ \ + -w \ + -Wno-strict-prototypes \ + -mcpu=$(TA_CPU) \ + -Wstack-protector + +ifeq ($(CFG_TA_MEASURED_BOOT),y) +cflags-y += -DEVENT_LOG_SIZE=$(CFG_TA_EVENT_LOG_SIZE) +cflags-y += -DMEASURED_BOOT +endif + +ifeq ($(CFG_TA_DEBUG),y) +cflags-y += -DfTPMDebug=1 +cflags-y += -DDBG=1 +cflags-y += -DDEBUG +endif + +include $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk + +ifeq ($(CFG_ARM64_ta_arm64),y) +cflags-y += -mstrict-align +else +cflags-y += -mno-unaligned-access +endif diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/fTPM.c b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/fTPM.c new file mode 100644 index 0000000..72384c5 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/fTPM.c @@ -0,0 +1,589 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * Copyright (c) Arm Limited. + * Copyright (c) 2023-2024, NVIDIA Corporation & AFFILIATES. All rights reserved. + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 STR_TRACE_USER_TA "fTPM" + +#include +#include +#include +#include +#include +#include +#include + +#include "fTPM.h" + +#define TA_ALL_PARAM_TYPE(type) TEE_PARAM_TYPES(type, type, type, type) + +// +// Ensure we have only one active session +// +static bool fTPMSessionActive = false; + +// +// Initialization +// +bool fTPMInitialized = false; + +#ifdef MEASURED_BOOT +// +// Initialization of the TPM event log +// +static bool tpmEventLogProcessed = false; +#endif // MEASURED_BOOT + +// +// Partial initialization flags of fTPM at early boot stage +// +static bool fTPMEarlyInit = false; +static bool fTPMEarlyInitDone = false; +static bool fTPMNSInitReady = false; + +// +// Local (SW) command buffer +// +static uint8_t fTPMCommand[MAX_COMMAND_SIZE]; + +// +// A subset of TPM return codes (see TpmTypes.h) +// +typedef uint32_t TPM_RC; +#define RC_VER1 (TPM_RC) (0x100) +#define TPM_RC_SUCCESS (TPM_RC) (0x000) +#define TPM_RC_FAILURE (TPM_RC) (RC_VER1+0x001) + +// +// Helper function to read response codes from TPM responses +// +static uint32_t fTPMResponseCode(uint32_t ResponseSize, + uint8_t *ResponseBuffer) +{ + uint32_t ResponseCode; + union { + uint32_t Data; + uint8_t Index[4]; + } Value; + + // In case of too-small response size, assume failure. + if (ResponseSize < 0xA) { + return TPM_RC_FAILURE; + } + + Value.Index[0] = ResponseBuffer[6]; + Value.Index[1] = ResponseBuffer[7]; + Value.Index[2] = ResponseBuffer[8]; + Value.Index[3] = ResponseBuffer[9]; + ResponseCode = SwapBytes32(Value.Data); + + return ResponseCode; +} + +static TEE_Result invoke_ftpm_helper_pta(uint32_t cmd_id, + uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + static TEE_TASessionHandle fth_pta_sess = TEE_HANDLE_NULL; + const TEE_UUID ftpm_helper_pta_uuid = FTPM_HELPER_PTA_UUID; + TEE_Result rc = TEE_SUCCESS; + + if (fth_pta_sess == TEE_HANDLE_NULL) { + rc = TEE_OpenTASession(&ftpm_helper_pta_uuid, TEE_TIMEOUT_INFINITE, + 0, NULL, &fth_pta_sess, NULL); + if (rc) + return rc; + } + + return TEE_InvokeTACommand(fth_pta_sess, TEE_TIMEOUT_INFINITE, + cmd_id, + param_types, params, NULL); +} + +// +// Helper function to ping normal world +// +static TEE_Result ping_ns_world(void) +{ + TEE_Result rc = TEE_SUCCESS; + const uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + TEE_Param params[TEE_NUM_PARAMS] = {0}; + + rc = invoke_ftpm_helper_pta(FTPM_HELPER_PTA_CMD_PING_NS, + param_types, params); + if (rc) + return rc; + + if (params[0].value.a == FTPM_HELPER_PTA_NS_STATE_READY) + rc = TEE_SUCCESS; + else + rc = TEE_ERROR_BAD_STATE; + + return rc; +} + +#ifdef MEASURED_BOOT +static TEE_Result get_tpm_event_log(unsigned char *buf, size_t *len) +{ + 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; + 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}; + + res = TEE_OpenTASession(&system_uuid, TEE_TIMEOUT_INFINITE, + 0, NULL, &session, &ret_origin); + if (res != TEE_SUCCESS) + return res; + + params[0].memref.buffer = (void *)buf; + params[0].memref.size = *len; + + res = TEE_InvokeTACommand(session, TEE_TIMEOUT_INFINITE, + PTA_SYSTEM_GET_TPM_EVENT_LOG, + param_types, params, &ret_origin); + + *len = params[0].memref.size; + + TEE_CloseTASession(session); + + return res; +} +#endif // MEASURED_BOOT + +// +// Called when TA instance is created. This is the first call to the TA. +// +TEE_Result TA_CreateEntryPoint(void) +{ + #define STARTUP_SIZE 0x0C + + uint8_t startupClear[STARTUP_SIZE] = { 0x80, 0x01, 0x00, 0x00, 0x00, 0x0c, + 0x00, 0x00, 0x01, 0x44, 0x00, 0x00 }; + uint8_t startupState[STARTUP_SIZE] = { 0x80, 0x01, 0x00, 0x00, 0x00, 0x0c, + 0x00, 0x00, 0x01, 0x44, 0x00, 0x01 }; + uint32_t respLen; + uint8_t *respBuf; +#ifdef MEASURED_BOOT + unsigned char tpm_event_log_buf[EVENT_LOG_SIZE]; + size_t tpm_event_log_len = EVENT_LOG_SIZE; +#endif + +#ifdef fTPMDebug + DMSG("Entry Point\n"); +#endif + + if (TEE_SUCCESS == ping_ns_world()) { + _plat__SetNvAvail(); + _plat__SetTimerAvail(); + fTPMEarlyInit = false; + if (fTPMEarlyInitDone) { + // Clear the init flag to do the normal init again. + fTPMInitialized = false; + // Non-secure world OP-TEE services are ready to connect. + fTPMNSInitReady = true; + } + } else { + _plat__ClearNvAvail(); + _plat__ClearTimerAvail(); + + // If we've been here before, don't init again. + if (fTPMEarlyInitDone) + return TEE_SUCCESS; + + fTPMEarlyInit = true; + } + + // If we've been here before, don't init again. + if (fTPMInitialized) { + // We may have had TA_DestroyEntryPoint called but we didn't + // actually get torn down. Re-NVEnable, just in case. + if (_plat__NVEnable(NULL) == 0) { + TEE_Panic(TEE_ERROR_BAD_STATE); + } + return TEE_SUCCESS; + } + + // Initialize NV admin state + _admin__NvInitState(); + + // If we fail to open fTPM storage we cannot continue. + if (_plat__NVEnable(NULL) == 0) { + TEE_Panic(TEE_ERROR_BAD_STATE); + } + +#ifdef fTPMDebug + DMSG("NVEnable Complete\n"); +#endif + + // This only occurs when there is no previous NV state, i.e., on first + // boot, after recovering from data loss, we reset the platform, etc. + if (_plat__NvNeedsManufacture()) { +#ifdef fTPMDebug + DMSG("TPM_Manufacture\n"); +#endif + TPM_Manufacture(1); + } + + // Init PCR for measured boot support during early boot stage. + if (fTPMEarlyInit) + PCRSimStart(); + + // "Power-On" the platform + _plat__Signal_PowerOn(); + + // Internal init for reference implementation + _TPM_Init(); + +#ifdef fTPMDebug + DMSG("Init Complete\n"); +#endif + + // Startup with state + if (g_chipFlags.fields.TpmStatePresent) { + + // Re-use request buffer for response (ignored) + respBuf = startupState; + respLen = STARTUP_SIZE; + + ExecuteCommand(STARTUP_SIZE, startupState, &respLen, &respBuf); + if (fTPMResponseCode(respLen, respBuf) == TPM_RC_SUCCESS) { + goto Exit; + } + +#ifdef fTPMDebug + DMSG("Fall through to startup clear\n"); +#endif + + goto Clear; + } + +#ifdef fTPMDebug + DMSG("No TPM state present\n"); +#endif + +Clear: + // Re-use request buffer for response (ignored) + respBuf = startupClear; + respLen = STARTUP_SIZE; + + // Fall back to a Startup Clear + ExecuteCommand(STARTUP_SIZE, startupClear, &respLen, &respBuf); + + if (fTPMNSInitReady) { + // Restore TPM state after NS world OP-TEE services ready and + // TPM startup complete. + PCRBankRestore(); + } + +Exit: + // Init is complete, indicate so in fTPM admin state. + g_chipFlags.fields.TpmStatePresent = 1; + _admin__SaveChipFlags(); + + // Initialization complete + fTPMInitialized = true; + // Early initialization complete + if (fTPMEarlyInit) + fTPMEarlyInitDone = true; + +#ifdef MEASURED_BOOT + if (tpmEventLogProcessed) + goto Measured_boot_done; + + // Extend existing TPM Event Log. + if (get_tpm_event_log(tpm_event_log_buf, + &tpm_event_log_len) == TEE_SUCCESS) + { + +#ifdef fTPMDebug + // Dump the event log + unsigned char* buff = tpm_event_log_buf; + size_t buff_len = tpm_event_log_len; + MSG("Preparing to extend the following TPM Event Log:"); + dump_event_log(tpm_event_log_buf, tpm_event_log_len); +#endif + process_eventlog(tpm_event_log_buf, tpm_event_log_len); + tpmEventLogProcessed = true; + } + +Measured_boot_done: +#endif + + return TEE_SUCCESS; +} + + +// +// Called when TA instance destroyed. This is the last call in the TA. +// +void TA_DestroyEntryPoint(void) +{ + // We should only see this called after the OS has shutdown and there + // will be no further commands sent to the TPM. Right now, just close + // our storage object, becasue the TPM driver should have already + // shutdown cleanly. + _plat__NVDisable(); + return; +} + + +// +// Called when a new session is opened to the TA. +// +TEE_Result TA_OpenSessionEntryPoint(uint32_t param_types, + TEE_Param params[4], + void **sess_ctx) +{ + uint32_t exp_param_types = TA_ALL_PARAM_TYPE(TEE_PARAM_TYPE_NONE); + + // Unreferenced parameters + UNREFERENCED_PARAMETER(params); + UNREFERENCED_PARAMETER(sess_ctx); + + // Validate parameter types + if (param_types != exp_param_types) { + return TEE_ERROR_BAD_PARAMETERS; + } + + // Only one active session to the fTPM is permitted + if (fTPMSessionActive) { + return TEE_ERROR_ACCESS_CONFLICT; + } + + // Active session + fTPMSessionActive = true; + + // Check normal world status to re-init fTPM + if (fTPMEarlyInitDone && + (TEE_SUCCESS == ping_ns_world())) + TA_CreateEntryPoint(); + + // If return value != TEE_SUCCESS the session will not be created. + return TEE_SUCCESS; +} + + +// +// Called when a session is closed. +// +void TA_CloseSessionEntryPoint(void *sess_ctx) +{ + // Unused parameter(s) + UNREFERENCED_PARAMETER(sess_ctx); + + // Save the PCR banks in the early boot stage + if (fTPMEarlyInitDone && + (TEE_ERROR_BAD_STATE == ping_ns_world())) + PCRBankSave(); + + // Clear active session + if (fTPMSessionActive) { + fTPMSessionActive = false; + } +} + +// +// Called to handle command submission. +// +static TEE_Result fTPM_Submit_Command(uint32_t param_types, + TEE_Param params[4] +) +{ + uint8_t *cmdBuf, *respBuf; + uint32_t cmdLen, respLen; + uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + // Validate parameter types + if (param_types != exp_param_types) { +#ifdef fTPMDebug + IMSG("Bad param type(s)\n"); +#endif + return TEE_ERROR_BAD_PARAMETERS; + } + + // Sanity check our buffer sizes + if ((params[0].memref.size == 0) || + (params[1].memref.size == 0) || + (params[0].memref.size > MAX_COMMAND_SIZE) || + (params[1].memref.size > MAX_RESPONSE_SIZE)) { +#ifdef fTPMDebug + IMSG("Bad param size(s)\n"); +#endif + return TEE_ERROR_BAD_PARAMETERS; + } + + // Copy command locally + memcpy(fTPMCommand, params[0].memref.buffer, params[0].memref.size); + + // Pull the command length from the actual TPM command. The memref size + // field descibes the buffer containing the command, not the command. + cmdBuf = fTPMCommand; + cmdLen = BYTE_ARRAY_TO_UINT32((uint8_t *)&(cmdBuf[2])); + + // Sanity check cmd length included in TPM command + if (cmdLen > params[0].memref.size) { + return TEE_ERROR_BAD_PARAMETERS; + } + + respBuf = (uint8_t *)(params[1].memref.buffer); + respLen = params[1].memref.size; + + // Check if this is a PPI Command + if (!_admin__PPICommand(cmdLen, cmdBuf, &respLen, &respBuf)) { + // If not, pass through to TPM + ExecuteCommand(cmdLen, cmdBuf, &respLen, &respBuf); + } + + // Unfortunately, this cannot be done until after we have our response in + // hand. We will, however, make an effort to return at least a portion of + // the response along with TEE_ERROR_SHORT_BUFFER. + if (respLen > params[1].memref.size) + { +#ifdef fTPMDebug + IMSG("Insufficient buffer length RS: 0x%x > BL: 0x%x\n", respLen, params[1].memref.size); +#endif + return TEE_ERROR_SHORT_BUFFER; + } + +#ifdef fTPMDebug + DMSG("Success, RS: 0x%x\n", respLen); +#endif + + return TEE_SUCCESS; +} + +// +// Called to handle PPI commands +// +static TEE_Result fTPM_Emulate_PPI(uint32_t param_types, + TEE_Param params[4] +) +{ + uint8_t *cmdBuf, *respBuf; + uint32_t cmdLen, respLen; + uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + // Validate parameter types + if (param_types != exp_param_types) { +#ifdef fTPMDebug + IMSG("Bad param type(s)\n"); +#endif + return TEE_ERROR_BAD_PARAMETERS; + } + + // Sanity check our buffer sizes + if ((params[0].memref.size == 0) || + (params[1].memref.size == 0) || + (params[0].memref.size > MAX_COMMAND_SIZE) || + (params[1].memref.size > MAX_RESPONSE_SIZE)) { +#ifdef fTPMDebug + IMSG("Bad param size(s)\n"); +#endif + return TEE_ERROR_BAD_PARAMETERS; + } + + // Copy command locally + memcpy(fTPMCommand, params[0].memref.buffer, params[0].memref.size); + + cmdBuf = fTPMCommand; + cmdLen = params[0].memref.size; + + respBuf = (uint8_t *)(params[1].memref.buffer); + respLen = params[1].memref.size; + + // Pass along to platform PPI processing + if (_admin__PPIRequest(cmdLen, cmdBuf, &respLen, &respBuf)) { +#ifdef fTPMDebug + DMSG("Handled PPI command via TA interface\n"); +#endif + } + else { +#ifdef fTPMDebug + IMSG("Failed to handle PPI command via TA interface\n"); +#endif + } + + if (respLen > params[1].memref.size) { +#ifdef fTPMDebug + IMSG("Insufficient buffer length RS: 0x%x > BL: 0x%x\n", respLen, params[1].memref.size); +#endif + return TEE_ERROR_SHORT_BUFFER; + } + + params[1].memref.size = respLen; + return TEE_SUCCESS; +} + +// +// Called when a TA is invoked. Note, paramters come from normal world. +// +TEE_Result TA_InvokeCommandEntryPoint(void *sess_ctx, + uint32_t cmd_id, + uint32_t param_types, + TEE_Param params[4]) +{ + // Unused parameter(s) + UNREFERENCED_PARAMETER(sess_ctx); + + // Handle command invocation + switch (cmd_id) { + + case TA_FTPM_SUBMIT_COMMAND: { + return fTPM_Submit_Command(param_types, params); + } + + case TA_FTPM_EMULATE_PPI: { + return fTPM_Emulate_PPI(param_types, params); + } + + default: { + return TEE_ERROR_BAD_PARAMETERS; + } + } +} diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/Wolf/TpmToWolfHash.h b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/Wolf/TpmToWolfHash.h new file mode 100644 index 0000000..4ce0352 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/Wolf/TpmToWolfHash.h @@ -0,0 +1,199 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//** Introduction +// +// This header file is used to 'splice' the wolfcrypt hash code into the TPM code. +// +#ifndef HASH_LIB_DEFINED +#define HASH_LIB_DEFINED + +#define HASH_LIB_WOLF + +#define HASH_ALIGNMENT RADIX_BYTES + +#ifndef WOLFSSL_USER_SETTINGS +#define WOLFSSL_USER_SETTINGS +#endif + +#if ALG_SHA384 || ALG_SHA512 +#define WOLFSSL_SHA512 +#endif + +#if ALG_SM3_256 +#undef ALG_SM3_256 +#define ALG_SM3_256 ALG_NO +//#error "SM3 is not available" +#endif + +#include +#include +#include + + +//*************************************************************** +//** Links to the wolfcrypt HASH code +//*************************************************************** + +// Redefine the internal name used for each of the hash state structures to the +// name used by the library. +// These defines need to be known in all parts of the TPM so that the structure +// sizes can be properly computed when needed. + +#define tpmHashStateSHA1_t wc_Sha +#define tpmHashStateSHA256_t wc_Sha256 +#define tpmHashStateSHA384_t wc_Sha512 +#define tpmHashStateSHA512_t wc_Sha512 + +#if ALG_SM3 +# error "The version of WolfCrypt used by this code does not support SM3" +#endif + +// The defines below are only needed when compiling CryptHash.c or CryptSmac.c. +// This isolation is primarily to avoid name space collision. However, if there +// is a real collision, it will likely show up when the linker tries to put things +// together. + +#ifdef _CRYPT_HASH_C_ + +typedef BYTE *PBYTE; +typedef const BYTE *PCBYTE; + +// Define the interface between CryptHash.c to the functions provided by the +// library. For each method, define the calling parameters of the method and then +// define how the method is invoked in CryptHash.c. +// +// All hashes are required to have the same calling sequence. If they don't, create +// a simple adaptation function that converts from the "standard" form of the call +// to the form used by the specific hash (and then send a nasty letter to the +// person who wrote the hash function for the library). +// +// The macro that calls the method also defines how the +// parameters get swizzled between the default form (in CryptHash.c)and the +// library form. +// +// Initialize the hash context +#define HASH_START_METHOD_DEF void (HASH_START_METHOD)(PANY_HASH_STATE state) +#define HASH_START(hashState) \ + ((hashState)->def->method.start)(&(hashState)->state); + +// Add data to the hash +#define HASH_DATA_METHOD_DEF \ + void (HASH_DATA_METHOD)(PANY_HASH_STATE state, \ + PCBYTE buffer, \ + size_t size) +#define HASH_DATA(hashState, dInSize, dIn) \ + ((hashState)->def->method.data)(&(hashState)->state, dIn, dInSize) + +// Finalize the hash and get the digest +#define HASH_END_METHOD_DEF \ + void (HASH_END_METHOD)(PANY_HASH_STATE state, BYTE *buffer) +#define HASH_END(hashState, buffer) \ + ((hashState)->def->method.end)(&(hashState)->state, buffer) + +// Copy the hash context +// Note: For import, export, and copy, memcpy() is used since there is no +// reformatting necessary between the internal and external forms. +#define HASH_STATE_COPY_METHOD_DEF \ + void (HASH_STATE_COPY_METHOD)(PANY_HASH_STATE to, \ + PCANY_HASH_STATE from, \ + size_t size) +#define HASH_STATE_COPY(hashStateOut, hashStateIn) \ + ((hashStateIn)->def->method.copy)(&(hashStateOut)->state, \ + &(hashStateIn)->state, \ + (hashStateIn)->def->contextSize) + +// Copy (with reformatting when necessary) an internal hash structure to an +// external blob +#define HASH_STATE_EXPORT_METHOD_DEF \ + void (HASH_STATE_EXPORT_METHOD)(BYTE *to, \ + PCANY_HASH_STATE from, \ + size_t size) +#define HASH_STATE_EXPORT(to, hashStateFrom) \ + ((hashStateFrom)->def->method.copyOut) \ + (&(((BYTE *)(to))[offsetof(HASH_STATE, state)]), \ + &(hashStateFrom)->state, \ + (hashStateFrom)->def->contextSize) + +// Copy from an external blob to an internal formate (with reformatting when +// necessary +#define HASH_STATE_IMPORT_METHOD_DEF \ + void (HASH_STATE_IMPORT_METHOD)(PANY_HASH_STATE to, \ + const BYTE *from, \ + size_t size) +#define HASH_STATE_IMPORT(hashStateTo, from) \ + ((hashStateTo)->def->method.copyIn) \ + (&(hashStateTo)->state, \ + &(((const BYTE *)(from))[offsetof(HASH_STATE, state)]),\ + (hashStateTo)->def->contextSize) + + +// Function aliases. The code in CryptHash.c uses the internal designation for the +// functions. These need to be translated to the function names of the library. +// Internal External +// Designation Designation +#define tpmHashStart_SHA1 wc_InitSha // external name of the + // initialization method +#define tpmHashData_SHA1 wc_ShaUpdate +#define tpmHashEnd_SHA1 wc_ShaFinal +#define tpmHashStateCopy_SHA1 memcpy +#define tpmHashStateExport_SHA1 memcpy +#define tpmHashStateImport_SHA1 memcpy +#define tpmHashStart_SHA256 wc_InitSha256 +#define tpmHashData_SHA256 wc_Sha256Update +#define tpmHashEnd_SHA256 wc_Sha256Final +#define tpmHashStateCopy_SHA256 memcpy +#define tpmHashStateExport_SHA256 memcpy +#define tpmHashStateImport_SHA256 memcpy +#define tpmHashStart_SHA384 wc_InitSha384 +#define tpmHashData_SHA384 wc_Sha384Update +#define tpmHashEnd_SHA384 wc_Sha384Final +#define tpmHashStateCopy_SHA384 memcpy +#define tpmHashStateExport_SHA384 memcpy +#define tpmHashStateImport_SHA384 memcpy +#define tpmHashStart_SHA512 wc_InitSha512 +#define tpmHashData_SHA512 wc_Sha512Update +#define tpmHashEnd_SHA512 wc_Sha512Final +#define tpmHashStateCopy_SHA512 memcpy +#define tpmHashStateExport_SHA512 memcpy +#define tpmHashStateImport_SHA512 memcpy + +#endif // _CRYPT_HASH_C_ + +#define LibHashInit() +// This definition would change if there were something to report +#define HashLibSimulationEnd() + +#endif // HASH_LIB_DEFINED diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/Wolf/TpmToWolfMath.h b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/Wolf/TpmToWolfMath.h new file mode 100644 index 0000000..1543499 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/Wolf/TpmToWolfMath.h @@ -0,0 +1,91 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//** Introduction +// This file contains the structure definitions used for ECC in the LibTomCrypt +// version of the code. These definitions would change, based on the library. +// The ECC-related structures that cross the TPM interface are defined +// in TpmTypes.h +// + +#ifndef MATH_LIB_DEFINED +#define MATH_LIB_DEFINED + +#define MATH_LIB_WOLF + +#if ALG_ECC +#define HAVE_ECC +#endif + +#include +#include + +#define MP_VAR(name) \ + mp_int _##name; \ + mp_int *name = MpInitialize(&_##name); + +// Allocate a mp_int and initialize with the values in a mp_int* initializer +#define MP_INITIALIZED(name, initializer) \ + MP_VAR(name); \ + BnToWolf(name, initializer); + +#define POINT_CREATE(name, initializer) \ + ecc_point *name = EcPointInitialized(initializer); + +#define POINT_DELETE(name) \ + wc_ecc_del_point(name); \ + name = NULL; + +typedef ECC_CURVE_DATA bnCurve_t; + +typedef bnCurve_t *bigCurve; + +#define AccessCurveData(E) (E) + +#define CURVE_INITIALIZED(name, initializer) \ + bnCurve_t *name = (ECC_CURVE_DATA *)GetCurveData(initializer) + +#define CURVE_FREE(E) + +#include "TpmToWolfSupport_fp.h" + +#define WOLF_ENTER() + +#define WOLF_LEAVE() + +// This definition would change if there were something to report +#define MathLibSimulationEnd() + +#endif // MATH_LIB_DEFINED diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/Wolf/TpmToWolfSym.h b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/Wolf/TpmToWolfSym.h new file mode 100644 index 0000000..0c042eb --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/Wolf/TpmToWolfSym.h @@ -0,0 +1,120 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//** Introduction +// +// This header file is used to 'splice' the wolfcrypt library into the TPM code. + +#ifndef SYM_LIB_DEFINED +#define SYM_LIB_DEFINED + +#define SYM_LIB_WOLF + +#define SYM_ALIGNMENT RADIX_BYTES + +#include +#include + +//*************************************************************** +//** Links to the wolfCrypt AES code +//*************************************************************** +#if ALG_SM4 +#undef ALG_SM4 +#define ALG_SM4 ALG_NO +//#error "SM4 is not available" +#endif + +#if ALG_CAMELLIA +#undef ALG_CAMELLIA +#define ALG_CAMELLIA ALG_NO +//#error "Camellia is not available" +#endif + +// Define the order of parameters to the library functions that do block encryption +// and decryption. +typedef void(*TpmCryptSetSymKeyCall_t)( + void *keySchedule, + BYTE *out, + const BYTE *in + ); + +// The Crypt functions that call the block encryption function use the parameters +// in the order: +// 1) keySchedule +// 2) in buffer +// 3) out buffer +// Since wolfcrypt uses the order in encryptoCall_t above, need to swizzle the +// values to the order required by the library. +#define SWIZZLE(keySchedule, in, out) \ + (void *)(keySchedule), (BYTE *)(out), (const BYTE *)(in) + +// Macros to set up the encryption/decryption key schedules +// +// AES: +#define TpmCryptSetEncryptKeyAES(key, keySizeInBits, schedule) \ + wc_AesSetKeyDirect((tpmKeyScheduleAES *)(schedule), key, BITS_TO_BYTES(keySizeInBits), 0, AES_ENCRYPTION) +#define TpmCryptSetDecryptKeyAES(key, keySizeInBits, schedule) \ + wc_AesSetKeyDirect((tpmKeyScheduleAES *)(schedule), key, BITS_TO_BYTES(keySizeInBits), 0, AES_DECRYPTION) + +// TDES: +#define TpmCryptSetEncryptKeyTDES(key, keySizeInBits, schedule) \ + TDES_setup_encrypt_key((key), (keySizeInBits), (tpmKeyScheduleTDES *)(schedule)) +#define TpmCryptSetDecryptKeyTDES(key, keySizeInBits, schedule) \ + TDES_setup_decrypt_key((key), (keySizeInBits), (tpmKeyScheduleTDES *)(schedule)) + +// Macros to alias encryption calls to specific algorithms. This should be used +// sparingly. Currently, only used by CryptRand.c +// +// When using these calls, to call the AES block encryption code, the caller +// should use: +// TpmCryptEncryptAES(SWIZZLE(keySchedule, in, out)); +#define TpmCryptEncryptAES wc_AesEncryptDirect +#define TpmCryptDecryptAES wc_AesDecryptDirect +#define tpmKeyScheduleAES Aes + +#define TpmCryptEncryptTDES TDES_encrypt +#define TpmCryptDecryptTDES TDES_decrypt +#define tpmKeyScheduleTDES Des3 + +typedef union tpmCryptKeySchedule_t tpmCryptKeySchedule_t; + +#if ALG_TDES +#include "TpmToWolfDesSupport_fp.h" +#endif + +// This definition would change if there were something to report +#define SymLibSimulationEnd() + +#endif // SYM_LIB_DEFINED diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/Wolf/user_settings.h b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/Wolf/user_settings.h new file mode 100644 index 0000000..de0dfd3 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/Wolf/user_settings.h @@ -0,0 +1,108 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +/* TPM specific preprocessor flags for wolfcrypt */ + + +#ifndef WOLF_CRYPT_USER_SETTINGS_H +#define WOLF_CRYPT_USER_SETTINGS_H + +#include + +/* Remove the automatic setting of the default I/O functions EmbedSend() + and EmbedReceive(). */ +#define WOLFSSL_USER_IO + +/* Avoid naming conflicts */ +#define NO_OLD_WC_NAMES + +/* Use stack based fast math for all big integer math */ +#define USE_FAST_MATH +#define TFM_TIMING_RESISTANT + +/* Expose direct encryption functions */ +#define WOLFSSL_AES_DIRECT + +/* Enable/Disable algorithm support based on TPM implementation header */ +#if ALG_SHA256 + #define WOLFSSL_SHA256 +#endif +#if ALG_SHA384 || ALG_SHA512 + #define WOLFSSL_SHA384 + #define WOLFSSL_SHA512 +#endif +#if ALG_TDES + #define WOLFSSL_DES_ECB +#endif +#if ALG_RSA + /* Turn on RSA key generation functionality */ + #define WOLFSSL_KEY_GEN +#endif +#if ALG_ECC || defined(WOLFSSL_LIB) + #define HAVE_ECC + + /* Expose additional ECC primitives */ + #define WOLFSSL_PUBLIC_ECC_ADD_DBL + #define ECC_TIMING_RESISTANT + + /* Enables Shamir calc method */ + #define ECC_SHAMIR + + /* The TPM only needs low level ECC crypto */ + #define NO_ECC_SIGN + #define NO_ECC_VERIFY + #define NO_ECC_SECP + + #undef ECC_BN_P256 + #undef ECC_SM2_P256 + #undef ECC_BN_P638 + #define ECC_BN_P256 NO + #define ECC_SM2_P256 NO + #define ECC_BN_P638 NO + +#endif + +/* Disable explicit RSA. The TPM support for RSA is dependent only on TFM */ +#define NO_RSA +#define NO_RC4 +#define NO_ASN + +/* Enable debug wolf library check */ +//#define LIBRARY_COMPATIBILITY_CHECK + +#define WOLFSSL_ + +#endif // WOLF_CRYPT_USER_SETTINGS_H diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/fTPM.h b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/fTPM.h new file mode 100644 index 0000000..6d6b1a0 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/fTPM.h @@ -0,0 +1,106 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 FTPM_TA_H +#define FTPM_TA_H + +#include + +/* This UUID is generated with uuidgen */ +#define TA_FTPM_UUID { 0xBC50D971, 0xD4C9, 0x42C4, \ + {0x82, 0xCB, 0x34, 0x3F, 0xB7, 0xF3, 0x78, 0x96}} + +/* The TAFs ID implemented in this TA */ +#define TA_FTPM_SUBMIT_COMMAND (0) +#define TA_FTPM_EMULATE_PPI (1) + +// +// These must match values from reference/TPM/include/TpmProfile.h +// +#define MAX_COMMAND_SIZE 4096 +#define MAX_RESPONSE_SIZE 4096 + +// +// Macro for intentionally unreferenced parameters +// +#define UNREFERENCED_PARAMETER(_Parameter_) (void)(_Parameter_) + +// +// Shorthand for TA functions taking uniform arg types +// +#define TA_ALL_PARAM_TYPE(a) TEE_PARAM_TYPES((a), (a), (a), (a)) + +// +// Used to extract size field from TPM command buffers +// +#define BYTE_ARRAY_TO_UINT32(b) (uint32_t)( ((b)[0] << 24) \ + + ((b)[1] << 16) \ + + ((b)[2] << 8 ) \ + + (b)[3]) +// +// Entrypoint for reference implemntation +// +extern void ExecuteCommand( + uint32_t requestSize, // IN: command buffer size + unsigned char *request, // IN: command buffer + uint32_t *responseSize, // OUT: response buffer size + unsigned char **response // OUT: response buffer + ); + +// +// External functions supporting TPM initialization +// +extern int _plat__NVEnable(void *platParameter); +extern int TPM_Manufacture(bool firstTime); +extern bool _plat__NvNeedsManufacture(void); +extern void _TPM_Init(void); +extern void _plat__Signal_PowerOn(void); +extern void _plat__NVDisable(void); +extern void _admin__SaveChipFlags(void); + +// +// External types/data supporting TPM initialization +// +typedef union { + uint32_t flags; + struct { + uint32_t Remanufacture : 1; // Perform a TPM_Remanufacture() on startup (SET by default) + uint32_t TpmStatePresent : 1; // Init TPM and NV with contents of TpmState and NVState on startup + uint32_t Reserved : 30; + } fields; +} TPM_CHIP_STATE; + +extern TPM_CHIP_STATE g_chipFlags; +#endif /* FTPM_TA_H */ \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/fTPM_event_log.h b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/fTPM_event_log.h new file mode 100644 index 0000000..18618ac --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/fTPM_event_log.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _FTPM_EVENT_LOG_ +#define _FTPM_EVENT_LOG_ + +bool process_eventlog(const unsigned char *const buf, const size_t log_size); +void dump_event_log(uint8_t *log_addr, size_t log_size); + +#endif /* _FTPM_EVENT_LOG_*/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/fTPM_event_log_private.h b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/fTPM_event_log_private.h new file mode 100644 index 0000000..f972fc7 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/fTPM_event_log_private.h @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _FTPM_EVENT_LOG_PRIVATE_H +#define _FTPM_EVENT_LOG_PRIVATE_H + +#include +#include + +#define TCG_STARTUP_LOCALITY_SIGNATURE "StartupLocality" + +/* Event types */ +#define EV_PREBOOT_CERT 0x00000000 +#define EV_POST_CODE 0x00000001 +#define EV_NO_ACTION 0x00000003 +#define EV_SEPARATOR 0x00000004 +#define EV_ACTION 0x00000005 +#define EV_S_CRTM_CONTENTS 0x00000007 +#define EV_S_CRTM_VERSION 0x00000008 +#define EV_CPU_MICROCODE 0x00000009 +#define EV_PLATFORM_CONFIG_FLAGS 0x0000000A +#define EV_TABLE_OF_DEVICES 0x0000000B +#define EV_COMPACT_HASH 0x0000000C +#define EV_NONHOST_CODE 0x0000000F +#define EV_NONHOST_CONFIG 0x00000010 +#define EV_NONHOST_INFO 0x00000011 +#define EV_OMIT_BOOT_DEVICE_EVENTS 0x00000012 + +/* + * Section 5.3 of TCG EFI Protocol Specification. Family 2.0. + * Level 00 Revision 00.13 + * March 30, 2016 + */ +#define HEADER_DIGEST_SIZE 20 + +/* + * Section 4.40 of Trusted Platform Module Library. Part 1. + * Level 00 Revision 01.38. September 29, 2016. + */ +#define TPM_RS_PW 0x40000009 +#define AUTH_SIZE 0x00000009 + +#define TPM_PCR_EXTEND 0x00000182 +#define TPM_ST_SESS 0x8002 + +#pragma pack(1) + +/* + * Log Header Entry Data + * Ref. Table 14 TCG_EfiSpecIdEventAlgorithmSize + * TCG PC Client Platform Firmware Profile 9.4.5.1 + */ + +typedef struct tcg_efi_spec_id_event_algorithm_size { + /* Algorithm ID (hashAlg) of the Hash used by BIOS */ + uint16_t algorithm_id; + /* The size of the digest produced by the implemented Hash algorithm */ + uint16_t digest_size; +} id_event_algorithm_size_t; + +/* + * TCG_EfiSpecIdEvent structure + * Ref. Table 15 TCG_EfiSpecIdEvent + * TCG PC Client Platform Firmware Profile 9.4.5.1 + */ + +typedef struct id_event_struct_header { + /* + * The NUL-terminated ASCII string "Spec ID Event03". + * SHALL be set to {0x53, 0x70, 0x65, 0x63, 0x20, 0x49, 0x44, + * 0x20, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x33, 0x00}. + */ + uint8_t signature[16]; + + /* + * The value for the Platform Class. + * The enumeration is defined in the TCG ACPI Specification Client + * Common Header. + */ + uint32_t platform_class; + + /* + * The PC Client Platform Profile Specification minor version number + * this BIOS supports. + * Any BIOS supporting this version (2.0) MUST set this value to 0x00. + */ + uint8_t spec_version_minor; + + /* + * The PC Client Platform Profile Specification major version number + * this BIOS supports. + * Any BIOS supporting this version (2.0) MUST set this value to 0x02. + */ + uint8_t spec_version_major; + + /* + * The PC Client Platform Profile Specification errata version number + * this BIOS supports. + * Any BIOS supporting this version (2.0) MUST set this value to 0x02. + */ + uint8_t spec_errata; + + /* + * Specifies the size of the UINTN fields used in various data + * structures used in this specification. + * 0x01 indicates UINT32 and 0x02 indicates UINT64. + */ + uint8_t uintn_size; + + /* + * The number of Hash algorithms in the digestSizes field. + * This field MUST be set to a value of 0x01 or greater. + */ + uint32_t number_of_algorithms; + + /* + * Each TCG_EfiSpecIdEventAlgorithmSize SHALL contain an algorithmId + * and digestSize for each hash algorithm used in the TCG_PCR_EVENT2 + * structure, the first of which is a Hash algorithmID and the second + * is the size of the respective digest. + */ + id_event_algorithm_size_t digest_size[]; /* number_of_algorithms */ +} id_event_struct_header_t; + +typedef struct id_event_struct_data { + /* + * Size in bytes of the VendorInfo field. + * Maximum value MUST be FFh bytes. + */ + uint8_t vendor_info_size; + + /* + * Provided for use by Platform Firmware implementer. The value might + * be used, for example, to provide more detailed information about the + * specific BIOS such as BIOS revision numbers, etc. The values within + * this field are not standardized and are implementer-specific. + * Platform-specific or -unique information MUST NOT be provided in + * this field. + * + */ + uint8_t vendor_info[]; /* [vendorInfoSize] */ +} id_event_struct_data_t; + +typedef struct tcg_efi_spec_id_event_struct { + id_event_struct_header_t struct_header; + id_event_struct_data_t struct_data; +} id_event_struct_t; + +typedef uint16_t TPM_ST; +typedef uint32_t TPM_CC; +typedef uint32_t TPM_HANDLE; +typedef TPM_HANDLE TPMI_DH_PCR; + +typedef struct { + TPM_ST tag; + uint32_t paramSize; + TPM_CC commandCode; +} TPM2_COMMAND_HEADER; + +typedef struct { + TPM2_COMMAND_HEADER Header; + TPMI_DH_PCR PcrHandle; + uint32_t AuthorizationSize; + TPMS_AUTH_COMMAND AuthSessionPcr; + TPML_DIGEST_VALUES DigestValues; +} TPM2_PCR_EXTEND_COMMAND; + +/* + * PCR Event Header + * TCG EFI Protocol Specification + * 5.3 Event Log Header + */ +typedef struct { + /* PCRIndex: + * The PCR Index to which this event is extended + */ + uint32_t pcr_index; + + /* EventType: + * SHALL be an EV_NO_ACTION event + */ + uint32_t event_type; + + /* SHALL be 20 Bytes of 0x00 */ + uint8_t digest[SHA1_DIGEST_SIZE]; + + /* The size of the event */ + uint32_t event_size; + + /* SHALL be a TCG_EfiSpecIdEvent */ + uint8_t event[]; /* [event_data_size] */ +} tcg_pcr_event_t; + +typedef struct { + tcg_pcr_event_t header; + id_event_struct_header_t struct_header; +} id_event_headers_t; + +/* TPMT_HA Structure */ +typedef struct { + /* Selector of the hash contained in the digest that implies + * the size of the digest + */ + uint16_t algorithm_id; /* AlgorithmId */ + + /* Digest, depends on AlgorithmId */ + uint8_t digest[]; /* Digest[] */ +} tpmt_ha; + +/* + * TPML_DIGEST_VALUES Structure + */ +typedef struct { + /* The number of digests in the list */ + uint32_t count; /* Count */ + + /* The list of tagged digests, as sent to the TPM as part of a + * TPM2_PCR_Extend or as received from a TPM2_PCR_Event command + */ + tpmt_ha digests[]; /* Digests[Count] */ /* FIXME: TPM_TA@TpmTypes.h */ +} tpml_digest_values; + +/* + * TCG_PCR_EVENT2 header + */ +typedef struct { + /* The PCR Index to which this event was extended */ + uint32_t pcr_index; /* PCRIndex */ + + /* Type of event */ + uint32_t event_type; /* EventType */ + + /* Digests: + * A counted list of tagged digests, which contain the digest of + * the event data (or external data) for all active PCR banks + */ + tpml_digest_values digests; /* Digests */ +} event2_header_t; + +typedef struct event2_data { + /* The size of the event data */ + uint32_t event_size; /* EventSize */ + + /* The data of the event */ + uint8_t event[]; /* Event[EventSize] */ +} event2_data_t; + +/* + * Startup Locality Event + * Ref. TCG PC Client Platform Firmware Profile 9.4.5.3 + */ +typedef struct { + /* + * The NUL-terminated ASCII string "StartupLocality" SHALL be + * set to {0x53 0x74 0x61 0x72 0x74 0x75 0x70 0x4C 0x6F 0x63 + * 0x61 0x6C 0x69 0x74 0x79 0x00} + */ + uint8_t signature[16]; + + /* The Locality Indicator which sent the TPM2_Startup command */ + uint8_t startup_locality; +} startup_locality_event_t; + +#pragma pack() + +#endif /* _FTPM_EVENT_LOG_PRIVATE_H */ diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/fTPM_helpers.h b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/fTPM_helpers.h new file mode 100644 index 0000000..31bbaae --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/fTPM_helpers.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserverd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _FTPM_HELPERS_ +#define _FTPM_HELPERS_ + +#include + +uint16_t SwapBytes16(uint16_t Value); +uint32_t SwapBytes32(uint32_t Value); + +#endif /* _FTPM_HELPERS_ */ diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/lib/mbedtls_ltc/sub.mk b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/lib/mbedtls_ltc/sub.mk new file mode 100644 index 0000000..b997f68 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/lib/mbedtls_ltc/sub.mk @@ -0,0 +1,24 @@ +# Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause + +# This links to the LTC ECC functions from the OPTEE OS. +# The under laying of the ECC functions are the MP wrappers that are provided by MbedTLS MPI. +# See TPMCmd/tpm/src/crypt/Mbedtls/Mbedtls_mpi_Ltc_desc.c + +LTC_ROOT := $(OPTEE_OS_DIR)/core/lib/libtomcrypt/src/ + +USER_CUSTOM_INCLUDES = -include ./user_custom.h + +cflags-y += -DARGTYPE=4 -DLTC_MAX_ECC=521 $(USER_CUSTOM_INCLUDES) + +global-incdirs-y += ./ +global-incdirs_ext-y += $(LTC_ROOT)/headers + +srcs-y += $(LTC_ROOT)/math/multi.c +srcs-y += $(LTC_ROOT)/pk/ecc/ltc_ecc_is_point_at_infinity.c +srcs-y += $(LTC_ROOT)/pk/ecc/ltc_ecc_map.c +srcs-y += $(LTC_ROOT)/pk/ecc/ltc_ecc_mul2add.c +srcs-y += $(LTC_ROOT)/pk/ecc/ltc_ecc_mulmod_timing.c +srcs-y += $(LTC_ROOT)/pk/ecc/ltc_ecc_points.c +srcs-y += $(LTC_ROOT)/pk/ecc/ltc_ecc_projective_add_point.c +srcs-y += $(LTC_ROOT)/pk/ecc/ltc_ecc_projective_dbl_point.c diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/lib/mbedtls_ltc/user_custom.h b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/lib/mbedtls_ltc/user_custom.h new file mode 100644 index 0000000..968afa5 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/lib/mbedtls_ltc/user_custom.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023-2024, NVIDIA Corporation & AFFILIATES. All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef __USER_CUSTOM_H__ +#define __USER_CUSTOM_H__ + +#include + +typedef uint64_t clock_t; + +#endif diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/lib/sub.mk b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/lib/sub.mk new file mode 100644 index 0000000..a061d95 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/lib/sub.mk @@ -0,0 +1,2 @@ +subdirs-y += mbedtls_ltc +subdirs-y += tpm diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/lib/tpm/sub.mk b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/lib/tpm/sub.mk new file mode 100644 index 0000000..ee82016 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/lib/tpm/sub.mk @@ -0,0 +1,258 @@ +FTPM_FLAGS = -DGCC -DUSE_MBEDTLS -DSIMULATION=NO -DVTPM -D_ARM_ -DTHIRTY_TWO_BIT +FTPM_DEBUG = -DCOMPILER_CHECKS=YES -DfTPMDebug -DRUNTIME_SIZE_CHECKS -DLIBRARY_COMPATIBILITY_CHECK -DCERTIFYX509_DEBUG=YES +FTPM_RELEASE = -DCOMPILER_CHECKS=NO -DRUNTIME_SIZE_CHECKS=NO -DLIBRARY_COMPATIBILITY_CHECK=NO -DCERTIFYX509_DEBUG=NO + +# +# The fTPM needs to overwrite some of the header files used in the reference implementation. The search order GCC +# uses is dependent on the order the '-I/include/path' arguments are passed in. This is depended on the optee_os build +# system which makes it brittle. Force including these files here will make sure the correct files are used first. +# + +FTPM_INCLUDES = -include ./reference/include/VendorString.h \ + -include ./reference/include/TpmProfile.h \ + -include ./platform/include/Platform.h + +# +# The TPM causes a few warnings when compiled with GCC which are not critical. +# + +FTPM_WARNING_SUPPRESS = -Wno-cast-align \ + -Wno-cast-function-type \ + -Wno-implicit-fallthrough \ + -Wno-missing-braces \ + -Wno-sign-compare \ + -Wno-suggest-attribute=noreturn \ + -Wno-switch-default + +cflags-y += $(FTPM_FLAGS) $(FTPM_INCLUDES) $(FTPM_WARNING_SUPPRESS) + +ifeq ($(CFG_USE_PLATFORM_EPS),y) +cflags-y += -DUSE_PLATFORM_EPS=YES +endif + +ifeq ($(CFG_TA_DEBUG),y) +cflags-y += $(FTPM_DEBUG) +else +cflags-y += $(FTPM_RELEASE) +endif + +TPM_ROOT = $(abspath $(TPM_ROOT_PATH)) + +global-incdirs_ext-y += $(TPM_ROOT)/TPMCmd/tpm/include +global-incdirs_ext-y += $(TPM_ROOT)/TPMCmd/tpm/include/Mbedtls +global-incdirs_ext-y += $(TPM_ROOT)/TPMCmd/tpm/include/prototypes +global-incdirs_ext-y += $(TPM_ROOT)/TPMCmd/Platform/include + +# +# Generated in Ubuntu using: +# find -name *.c | sort | while read line; do echo XXXX$line; done | \ +# sed -e 's/XXXX.\//srcs-y += $(TPM_ROOT)\/TPMCmd\/tpm\/src\//g' +# This may need to be updated if there are any changes to the reference +# implementation. + +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/X509/TpmASN1.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/X509/X509_ECC.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/X509/X509_RSA.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/X509/X509_spt.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Asymmetric/ECC_Decrypt.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Asymmetric/ECC_Encrypt.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Asymmetric/ECC_Parameters.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Asymmetric/ECDH_KeyGen.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Asymmetric/ECDH_ZGen.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Asymmetric/EC_Ephemeral.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Asymmetric/RSA_Decrypt.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Asymmetric/RSA_Encrypt.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Asymmetric/ZGen_2Phase.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/AttachedComponent/AC_GetCapability.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/AttachedComponent/AC_Send.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/AttachedComponent/AC_spt.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/AttachedComponent/Policy_AC_SendSelect.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Attestation/Attest_spt.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Attestation/Certify.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Attestation/CertifyCreation.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Attestation/CertifyX509.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Attestation/GetCommandAuditDigest.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Attestation/GetSessionAuditDigest.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Attestation/GetTime.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Attestation/Quote.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Capability/GetCapability.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Capability/TestParms.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/ClockTimer/ACT_SetTimeout.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/ClockTimer/ACT_spt.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/ClockTimer/ClockRateAdjust.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/ClockTimer/ClockSet.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/ClockTimer/ReadClock.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/CommandAudit/SetCommandCodeAuditStatus.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Context/ContextLoad.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Context/ContextSave.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Context/Context_spt.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Context/EvictControl.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Context/FlushContext.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/DA/DictionaryAttackLockReset.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/DA/DictionaryAttackParameters.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Duplication/Duplicate.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Duplication/Import.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Duplication/Rewrap.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/EA/PolicyAuthValue.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/EA/PolicyAuthorize.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/EA/PolicyAuthorizeNV.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/EA/PolicyCommandCode.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/EA/PolicyCounterTimer.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/EA/PolicyCpHash.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/EA/PolicyDuplicationSelect.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/EA/PolicyGetDigest.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/EA/PolicyLocality.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/EA/PolicyNV.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/EA/PolicyNameHash.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/EA/PolicyNvWritten.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/EA/PolicyOR.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/EA/PolicyPCR.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/EA/PolicyPassword.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/EA/PolicyPhysicalPresence.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/EA/PolicySecret.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/EA/PolicySigned.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/EA/PolicyTemplate.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/EA/PolicyTicket.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/EA/Policy_spt.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Ecdaa/Commit.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/FieldUpgrade/FieldUpgradeData.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/FieldUpgrade/FieldUpgradeStart.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/FieldUpgrade/FirmwareRead.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/HashHMAC/EventSequenceComplete.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/HashHMAC/HMAC_Start.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/HashHMAC/HashSequenceStart.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/HashHMAC/MAC_Start.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/HashHMAC/SequenceComplete.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/HashHMAC/SequenceUpdate.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Hierarchy/ChangeEPS.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Hierarchy/ChangePPS.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Hierarchy/Clear.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Hierarchy/ClearControl.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Hierarchy/CreatePrimary.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Hierarchy/HierarchyChangeAuth.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Hierarchy/HierarchyControl.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Hierarchy/SetPrimaryPolicy.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Misc/PP_Commands.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Misc/SetAlgorithmSet.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/NVStorage/NV_Certify.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/NVStorage/NV_ChangeAuth.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/NVStorage/NV_DefineSpace.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/NVStorage/NV_Extend.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/NVStorage/NV_GlobalWriteLock.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/NVStorage/NV_Increment.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/NVStorage/NV_Read.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/NVStorage/NV_ReadLock.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/NVStorage/NV_ReadPublic.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/NVStorage/NV_SetBits.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/NVStorage/NV_UndefineSpace.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/NVStorage/NV_UndefineSpaceSpecial.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/NVStorage/NV_Write.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/NVStorage/NV_WriteLock.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/NVStorage/NV_spt.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Object/ActivateCredential.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Object/Create.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Object/CreateLoaded.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Object/Load.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Object/LoadExternal.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Object/MakeCredential.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Object/ObjectChangeAuth.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Object/Object_spt.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Object/ReadPublic.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Object/Unseal.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/PCR/PCR_Allocate.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/PCR/PCR_Event.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/PCR/PCR_Extend.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/PCR/PCR_Read.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/PCR/PCR_Reset.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/PCR/PCR_SetAuthPolicy.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/PCR/PCR_SetAuthValue.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Random/GetRandom.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Random/StirRandom.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Session/PolicyRestart.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Session/StartAuthSession.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Signature/Sign.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Signature/VerifySignature.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Startup/Shutdown.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Startup/Startup.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Symmetric/EncryptDecrypt.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Symmetric/EncryptDecrypt2.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Symmetric/EncryptDecrypt_spt.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Symmetric/HMAC.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Symmetric/Hash.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Symmetric/MAC.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Testing/GetTestResult.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Testing/IncrementalSelfTest.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Testing/SelfTest.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/command/Vendor/Vendor_TCG_Test.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/crypt/AlgorithmTests.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/crypt/BnConvert.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/crypt/BnMath.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/crypt/BnMemory.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/crypt/CryptCmac.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/crypt/CryptDes.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/crypt/CryptEccCrypt.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/crypt/CryptEccData.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/crypt/CryptEccKeyExchange.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/crypt/CryptEccMain.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/crypt/CryptEccSignature.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/crypt/CryptHash.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/crypt/CryptPrime.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/crypt/CryptPrimeSieve.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/crypt/CryptRand.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/crypt/CryptRsa.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/crypt/CryptSelfTest.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/crypt/CryptSmac.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/crypt/CryptSym.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/crypt/CryptUtil.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/crypt/Mbedtls/Mbedtls_mpi_Ltc_desc.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/crypt/Mbedtls/TpmToMbedtlsMath.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/crypt/Mbedtls/TpmToMbedtlsSupport.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/crypt/PrimeData.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/crypt/RsaKeyCache.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/crypt/Ticket.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/crypt/ltc/TpmToLtcDesSupport.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/crypt/ltc/TpmToLtcMath.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/crypt/ltc/TpmToLtcSupport.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/crypt/ossl/TpmToOsslDesSupport.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/crypt/ossl/TpmToOsslMath.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/crypt/ossl/TpmToOsslSupport.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/crypt/wolf/TpmToWolfDesSupport.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/crypt/wolf/TpmToWolfMath.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/crypt/wolf/TpmToWolfSupport.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/events/_TPM_Hash_Data.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/events/_TPM_Hash_End.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/events/_TPM_Hash_Start.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/events/_TPM_Init.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/main/CommandDispatcher.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/main/ExecCommand.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/main/SessionProcess.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/subsystem/CommandAudit.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/subsystem/DA.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/subsystem/Hierarchy.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/subsystem/NvDynamic.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/subsystem/NvReserved.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/subsystem/Object.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/subsystem/PCR.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/subsystem/PP.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/subsystem/Session.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/subsystem/Time.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/support/AlgorithmCap.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/support/Bits.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/support/CommandCodeAttributes.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/support/Entity.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/support/Global.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/support/Handle.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/support/IoBuffers.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/support/Locality.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/support/Manufacture.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/support/Marshal.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/support/MathOnByteBuffers.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/support/Memory.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/support/Power.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/support/PropertyCap.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/support/Response.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/support/ResponseCodeProcessing.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/support/TableDrivenMarshal.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/support/TableMarshalData.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/support/TpmFail.c +srcs-y += $(TPM_ROOT)/TPMCmd/tpm/src/support/TpmSizeChecks.c diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/lib/wolf/sub.mk b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/lib/wolf/sub.mk new file mode 100644 index 0000000..0a43f46 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/lib/wolf/sub.mk @@ -0,0 +1,58 @@ + +WOLF_SSL_FLAGS = -DSINGLE_THREADED \ + -DNO_WOLFSSL_CLIENT \ + -DNO_WOLFSSL_SERVER \ + -DOPENSSL_EXTRA \ + -DNO_FILESYSTEM \ + -DWOLFSSL_USER_SETTINGS \ + -DTIME_OVERRIDES \ + -DSTRING_USER \ + -DCTYPE_USER \ + -DCERTIFYX509_DEBUG=NO + +# +# Wolfcrypt has multiple unused functions, unfortunately the OPTEE build system can only turn off compiler flags for +# files in the same directory as the sub.mk file. It is not possible to place sub.mk files in the git submodules without +# creating a new fork of each submodule repo. To avoid spurious warnings these warnings are disabled here globally. +# + +WOLF_WARNING_SUPPRESS = -Wno-unused-function + +cflags-y += $(WOLF_SSL_FLAGS) $(WOLF_WARNING_SUPPRESS) + +# +# For the purposes of this command the current working directory is the makefile root (/fTPM) folder, +# but the symlink will be created relative to THIS directory so the source requires an extra '../../'. +# +./lib/wolf/wolf_symlink: + @echo Checking symlink to the WolfSSL folder: $(abspath $(WOLF_ROOT)) + @if [ -L ./lib/wolf/wolf_symlink ] ; \ + then \ + echo Symlink already established ; \ + else \ + echo Establishing symlink. ; \ + ln -s ../../$(WOLF_ROOT) ./lib/wolf/wolf_symlink; \ + fi + +.PHONY: remove_wolf_symlink +remove_wolf_symlink: + @if [ -e ./lib/wolf/wolf_symlink ] ; \ + then \ + unlink ./lib/wolf/wolf_symlink ; \ + echo Clearing symlink to the Wolf folder: $(abspath $(WOLF_ROOT)) ; \ + fi + +global-incdirs-y += wolf_symlink + +srcs-y += wolf_symlink/wolfcrypt/src/aes.c +srcs-y += wolf_symlink/wolfcrypt/src/asn.c +srcs-y += wolf_symlink/wolfcrypt/src/ecc.c +srcs-y += wolf_symlink/wolfcrypt/src/integer.c +srcs-y += wolf_symlink/wolfcrypt/src/memory.c +srcs-y += wolf_symlink/wolfcrypt/src/sha.c +srcs-y += wolf_symlink/wolfcrypt/src/sha256.c +srcs-y += wolf_symlink/wolfcrypt/src/sha512.c +srcs-y += wolf_symlink/wolfcrypt/src/tfm.c +srcs-y += wolf_symlink/wolfcrypt/src/wolfmath.c +srcs-y += wolf_symlink/wolfcrypt/src/des3.c +srcs-y += wolf_symlink/wolfcrypt/src/random.c diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/AdminPPI.c b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/AdminPPI.c new file mode 100644 index 0000000..01d382d --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/AdminPPI.c @@ -0,0 +1,426 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//**Introduction +// This file contains the emulated Physical Presence Interface. + +#include "assert.h" +#include "Admin.h" +#include "string.h" + +#include +#include + +#define TPM_CC_EmulatePPI 0x200001FF + +// +// Hand marshaling, unmarshaling, and maximally sized structures for EmulatePPI +// +#pragma pack (push, 1) +typedef struct { + TPM_ST tag; + UINT32 paramSize; + TPM_CC commandCode; +} TPM2_COMMAND_HEADER; + +typedef struct { + TPM_ST tag; + UINT32 paramSize; + TPM_RC responseCode; +} TPM2_RESPONSE_HEADER; + +typedef struct{ + UINT32 FunctionIndex; + UINT32 Op; +} EmulatePPI_In; + +typedef struct{ + UINT32 Result1; + UINT32 Result2; + UINT32 Result3; +} EmulatePPI_Out; + +typedef struct{ + TPM2_COMMAND_HEADER header; + EmulatePPI_In inputParameters; +} TPM2_EmulatePPI_cmd_t; + +typedef struct{ + TPM2_RESPONSE_HEADER header; + EmulatePPI_Out outputParameters; +} TPM2_EmulatePPI_res_t; +#pragma pack (pop) + +FTPM_PPI_STATE s_PPIState; + +extern int _plat__NvCommit(void); + +static void +ExecutePPICommand( + _In_ UINT32 FunctionIndex, + _In_ UINT32 Op, + _Out_ UINT32 *Result1, + _Out_ UINT32 *Result2, + _Out_ UINT32 *Result3 + ) +{ + UINT32 retVal1 = 0; + UINT32 retVal2 = 0; + UINT32 retVal3 = 0; + + _admin__RestorePPIState(); + + memset(Result1, 0, sizeof(UINT32)); + memset(Result2, 0, sizeof(UINT32)); + memset(Result3, 0, sizeof(UINT32)); + + switch (FunctionIndex) { + case FTPM_PPI_CMD_QUERY: + retVal1 = 0x1AB; // Per PPI 1.2 specification + break; + + case FTPM_PPI_CMD_VERSION: + retVal1 = FTPM_PPI_VERSION; // String "1.2" + break; + + case FTPM_PPI_CMD_SUBMIT_OP_REQ: + case FTPM_PPI_CMD_GET_PLATFORM_ACTION: + retVal1 = 2; // Reboot/General Failure + break; + + case FTPM_PPI_CMD_GET_PENDING_OP: + retVal1 = 0; // Success + retVal2 = s_PPIState.PendingPseudoOp; + break; + + case FTPM_PPI_CMD_RETURN_OP_RESP: + retVal1 = 0; // Success + retVal2 = s_PPIState.PseudoOpFromLastBoot; + retVal3 = s_PPIState.ReturnResponse; + break; + + case FTPM_PPI_CMD_SUBMIT_USER_LANG: + retVal1 = 3; // Not Implemented + break; + + case FTPM_PPI_CMD_SUBMIT_OP_REQ2: + switch (Op) { + case FTPM_PPI_OP_NOP: + case FTPM_PPI_OP_ENABLE: + case FTPM_PPI_OP_DISABLE: + case FTPM_PPI_OP_ACTIVATE: + case FTPM_PPI_OP_DEACTIVATE: + case FTPM_PPI_OP_CLEAR: // Causes Clear + case FTPM_PPI_OP_E_A: + case FTPM_PPI_OP_D_D: + case FTPM_PPI_OP_OWNERINSTALL_TRUE: + case FTPM_PPI_OP_OWNERINSTALL_FALSE: + case FTPM_PPI_OP_E_A_OI_TRUE: + case FTPM_PPI_OP_OI_FALSE_D_D: + case FTPM_PPI_OP_FIELD_UPGRADE: + case FTPM_PPI_OP_OPERATOR_AUTH: + case FTPM_PPI_OP_C_E_A: // Causes Clear + case FTPM_PPI_OP_SET_NO_PROV_FALSE: + case FTPM_PPI_OP_SET_NO_PROV_TRUE: + case FTPM_PPI_OP_SET_NO_MAINT_FALSE: + case FTPM_PPI_OP_SET_NO_MAINT_TRUE: + case FTPM_PPI_OP_E_A_C: // Causes Clear + case FTPM_PPI_OP_E_A_C_E_A: // Causes Clear + retVal1 = 0; // Success + s_PPIState.PendingPseudoOp = Op; + _admin__SavePPIState(); + break; + + case FTPM_PPI_OP_SET_NO_CLEAR_FALSE: + case FTPM_PPI_OP_SET_NO_CLEAR_TRUE: + default: + retVal1 = 1; // Not Implemented + break; + } + break; + + case FTPM_PPI_CMD_GET_USER_CONF: + switch (Op) { + case FTPM_PPI_OP_NOP: + case FTPM_PPI_OP_ENABLE: + case FTPM_PPI_OP_DISABLE: + case FTPM_PPI_OP_ACTIVATE: + case FTPM_PPI_OP_DEACTIVATE: + case FTPM_PPI_OP_E_A: + case FTPM_PPI_OP_D_D: + case FTPM_PPI_OP_OWNERINSTALL_TRUE: + case FTPM_PPI_OP_OWNERINSTALL_FALSE: + case FTPM_PPI_OP_E_A_OI_TRUE: + case FTPM_PPI_OP_OI_FALSE_D_D: + retVal1 = 4; // Allowed and PP user NOT required + break; + + case FTPM_PPI_OP_CLEAR: + case FTPM_PPI_OP_C_E_A: + case FTPM_PPI_OP_E_A_C: + case FTPM_PPI_OP_E_A_C_E_A: + retVal1 = 3; // Allowed and PP user required + break; + + default: + retVal1 = 0; // Not Implemented + break; + } + break; + + default: + break; + } + + memcpy(Result1, &retVal1, sizeof(UINT32)); + memcpy(Result2, &retVal2, sizeof(UINT32)); + memcpy(Result3, &retVal3, sizeof(UINT32)); +} + +static TPM2_EmulatePPI_res_t PPIResponse; + +#pragma warning(push) +#pragma warning(disable:28196) +// +// The fTPM TA (OpTEE) may receive, from the TrEE driver, a PPI request +// thru it's ACPI inteface rather than via the TPM_Emulate_PPI command +// we're used to. This function creates a well formes TPM_Emulate_PPI +// command and forwards the request on to _admin__PPICommand to handle. +// +// Return: +// 0 - Omproperly formatted PPI command. +// Otherwise - Return from _admin__PPICommand +// +int +_admin__PPIRequest( + UINT32 CommandSize, + __in_ecount(CommandSize) UINT8 *CommandBuffer, + UINT32 *ResponseSize, + __deref_out_ecount(*ResponseSize) UINT8 **ResponseBuffer + ) +{ + TPM2_EmulatePPI_cmd_t cmd; + TPM2_EmulatePPI_res_t rsp; + TPM2_EmulatePPI_res_t *rspPtr = &rsp; + UINT32 rspLen = sizeof(TPM2_EmulatePPI_res_t); + UINT8 *CmdBuffer; + + // Drop request if CommandSize is invalid + if (CommandSize < sizeof(UINT32)) { + return 0; + } + + CmdBuffer = CommandBuffer; + + cmd.header.tag = __builtin_bswap16(TPM_ST_NO_SESSIONS); + cmd.header.paramSize = __builtin_bswap32(sizeof(TPM2_EmulatePPI_cmd_t)); + cmd.header.commandCode = __builtin_bswap32(TPM_CC_EmulatePPI); + + cmd.inputParameters.FunctionIndex = BYTE_ARRAY_TO_UINT32(CmdBuffer); + CmdBuffer += sizeof(UINT32); + CommandSize -= sizeof(UINT32); + + // Parameter checking is done in _admin__PPICommand but we still need + // to sanity check the size field so as not to overrun CommandBuffer. + if (CommandSize > 0) { + + if (CommandSize < sizeof(UINT32)) + return 0; + + cmd.inputParameters.Op = BYTE_ARRAY_TO_UINT32(CmdBuffer); + } + + if (!_admin__PPICommand(sizeof(TPM2_EmulatePPI_cmd_t), + (UINT8 *)&cmd, + &rspLen, + (UINT8**)&rspPtr)) { + return 0; + } + + memcpy(*ResponseBuffer, &(rsp.outputParameters.Result1), (rspLen - sizeof(TPM2_RESPONSE_HEADER))); + *ResponseSize = (rspLen - sizeof(TPM2_RESPONSE_HEADER)); + return 1; +} + +// +// Return: +// 1 - Command has been consumed +// 0 - Not a properly formated PPI command, caller should pass through to TPM +// +int +_admin__PPICommand( + UINT32 CommandSize, + __in_ecount(CommandSize) UINT8 *CommandBuffer, + UINT32 *ResponseSize, + __deref_out_ecount(*ResponseSize) UINT8 **ResponseBuffer +) +{ + TPM2_EmulatePPI_cmd_t cmd; + UINT8 *CmdBuffer; + UINT32 FunctionIndex; + UINT32 Op; + UINT32 NumberResults = 0; + UINT16 Tag; + + memset(&PPIResponse, 0, sizeof(PPIResponse)); + memset(&cmd, 0, sizeof(cmd)); + + CmdBuffer = CommandBuffer; + + if (CommandSize < sizeof(TPM2_COMMAND_HEADER)) { + PPIResponse.header.responseCode = TPM_RC_COMMAND_SIZE; + goto Exit; + } + + cmd.header.tag = BYTE_ARRAY_TO_UINT16(CmdBuffer); + CmdBuffer += sizeof(UINT16); + CommandSize -= sizeof(UINT16); + + cmd.header.paramSize = BYTE_ARRAY_TO_UINT32(CmdBuffer); + CmdBuffer += sizeof(UINT32); + CommandSize -= sizeof(UINT32); + + cmd.header.commandCode = BYTE_ARRAY_TO_UINT32(CmdBuffer); + CmdBuffer += sizeof(UINT32); + CommandSize -= sizeof(UINT32); + + // + // First check that this must be the command we want to execute + // + if (cmd.header.commandCode != TPM_CC_EmulatePPI) { + return 0; + } + + // + // Must not be a session + // + if (cmd.header.tag != TPM_ST_NO_SESSIONS) { + PPIResponse.header.responseCode = TPM_RC_BAD_TAG; + goto Exit; + } + + // + // Must have enough command space left + // + if (cmd.header.paramSize < CommandSize) { + PPIResponse.header.responseCode = TPM_RC_COMMAND_SIZE; + goto Exit; + } + + if (CommandSize < sizeof(UINT32)) { + PPIResponse.header.responseCode = TPM_RC_COMMAND_SIZE; + goto Exit; + } + + FunctionIndex = BYTE_ARRAY_TO_UINT32(CmdBuffer); + CmdBuffer += sizeof(UINT32); + CommandSize -= sizeof(UINT32); + + switch (FunctionIndex) { + case FTPM_PPI_CMD_QUERY: + case FTPM_PPI_CMD_VERSION: + case FTPM_PPI_CMD_SUBMIT_OP_REQ: + case FTPM_PPI_CMD_GET_PLATFORM_ACTION: + case FTPM_PPI_CMD_SUBMIT_USER_LANG: + NumberResults = 1; + Op = 0; + break; + + case FTPM_PPI_CMD_GET_PENDING_OP: + NumberResults = 2; + Op = 0; + break; + + case FTPM_PPI_CMD_RETURN_OP_RESP: + NumberResults = 3; + Op = 0; + break; + + case FTPM_PPI_CMD_SUBMIT_OP_REQ2: + case FTPM_PPI_CMD_GET_USER_CONF: + NumberResults = 1; + + if (CommandSize < sizeof(UINT32)) { + PPIResponse.header.responseCode = TPM_RC_COMMAND_SIZE; + goto Exit; + } + + Op = BYTE_ARRAY_TO_UINT32(CmdBuffer); + CmdBuffer += sizeof(UINT32); + CommandSize -= sizeof(UINT32); + break; + + default: + NumberResults = 0; + PPIResponse.header.responseCode = TPM_RC_FAILURE; + goto Exit; + } + + + ExecutePPICommand(FunctionIndex, + Op, +#pragma warning (push) +#pragma warning (disable:4366) // The result of unary '&' may be unaligned + &PPIResponse.outputParameters.Result1, + &PPIResponse.outputParameters.Result2, + &PPIResponse.outputParameters.Result3); +#pragma warning (pop) + + PPIResponse.header.responseCode = TPM_RC_SUCCESS; + +Exit: + if (PPIResponse.header.responseCode != TPM_RC_SUCCESS) { + NumberResults = 0; + } + + *ResponseSize = sizeof(TPM2_RESPONSE_HEADER) + (NumberResults * sizeof(UINT32)); + + // + // Fill in tag, and size + // + Tag = TPM_ST_NO_SESSIONS; + PPIResponse.header.tag = BYTE_ARRAY_TO_UINT16((BYTE *)&Tag); + PPIResponse.header.paramSize = BYTE_ARRAY_TO_UINT32((BYTE *)ResponseSize); + PPIResponse.header.responseCode = BYTE_ARRAY_TO_UINT32((BYTE *)&PPIResponse.header.responseCode); + + // + // Results are in host byte order + // + memcpy(*ResponseBuffer, &PPIResponse, (sizeof(PPIResponse) < *ResponseSize) ? sizeof(PPIResponse) : *ResponseSize); + + return 1; +} +#pragma warning(pop) + diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/Cancel.c b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/Cancel.c new file mode 100644 index 0000000..304a070 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/Cancel.c @@ -0,0 +1,80 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Description +// +// This module simulates the cancel pins on the TPM. +// +//** Includes, Typedefs, Structures, and Defines +#include "PlatformData.h" +#include "Platform_fp.h" + +//** Functions + +//***_plat__IsCanceled() +// Check if the cancel flag is set +// return type: BOOL +// TRUE(1) if cancel flag is set +// FALSE(0) if cancel flag is not set +LIB_EXPORT int +_plat__IsCanceled( + void + ) +{ + // return cancel flag + return s_isCanceled; +} + +//***_plat__SetCancel() + +// Set cancel flag. +LIB_EXPORT void +_plat__SetCancel( + void + ) +{ + s_isCanceled = TRUE; + return; +} + +//***_plat__ClearCancel() +// Clear cancel flag +LIB_EXPORT void +_plat__ClearCancel( + void + ) +{ + s_isCanceled = FALSE; + return; +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/Clock.c b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/Clock.c new file mode 100644 index 0000000..c0ef751 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/Clock.c @@ -0,0 +1,348 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * Copyright (c) 2023-2024, NVIDIA Corporation & AFFILIATES. All rights reserved. + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Description +// +// This file contains the routines that are used by the simulator to mimic +// a hardware clock on a TPM. +// +// In this implementation, all the time values are measured in millisecond. +// However, the precision of the clock functions may be implementation dependent. + +//** Includes and Data Definitions +#include "PlatformData.h" +#include "Platform_fp.h" +#include "TpmFail_fp.h" +#include +#include + +//** Simulator Functions +//*** Introduction +// This set of functions is intended to be called by the simulator environment in +// order to simulate hardware events. + +// +// This is the system timer available flag to indicate that the timer is available +// for the running stage. +// +static BOOL s_TimerAvail = FALSE; + +// +// This is the tick to simulate the timer when the system timer is not available yet. +// +static uint32_t s_Tick = 0; +static uint32_t s_TickTime = 20; // 20 ms + +//***_plat__TimerReset() +// This function sets current system clock time as t0 for counting TPM time. +// This function is called at a power on event to reset the clock. When the clock +// is reset, the indication that the clock was stopped is also set. +LIB_EXPORT void +_plat__TimerReset( + void + ) +{ +TEE_Result Result; + TEE_Time Time = { 0 }; + + // Reset our TA persistent time, this affects all instances. + if (s_TimerAvail) + Result = TEE_SetTAPersistentTime(&Time); + else + Result = TEE_SUCCESS; + + // Nothing we can do on failure here. + assert(Result == TEE_SUCCESS); + + s_adjustRate = 0; + s_lastSystemTime = 0; + s_tpmTime = 0; + s_adjustRate = CLOCK_NOMINAL; + s_timerReset = TRUE; + s_timerStopped = TRUE; + + return; +} + +//*** _plat__TimerRestart() +// This function should be called in order to simulate the restart of the timer +// should it be stopped while power is still applied. +LIB_EXPORT void +_plat__TimerRestart( + void + ) +{ + s_timerStopped = TRUE; + return; +} + +//** Functions Used by TPM +//*** Introduction +// These functions are called by the TPM code. They should be replaced by +// appropriated hardware functions. + +#include +TEE_Time debugTime; + +//*** _plat__RealTime() +// This is another, probably futile, attempt to define a portable function +// that will return a 64-bit clock value that has mSec resolution. +uint64_t +_plat__RealTime( + void +) +{ + TEE_Result Result; + TEE_Time Time; + uint64_t Elapsed, Temp; + + if (s_TimerAvail) { + Result = TEE_GetTAPersistentTime(&Time); + } else { + s_Tick++; + Time.millis = s_Tick * s_TickTime; + Time.seconds = Time.millis / 1000; + Time.millis = Time.millis % 1000; + Result = TEE_SUCCESS; + } + + // Error conditions from GetTime may be resolved with a clock reset + if ((Result == TEE_ERROR_TIME_NOT_SET) || + (Result == TEE_ERROR_TIME_NEEDS_RESET)) { + // + // REVISIT: Since error conditions from get time may be resolved + // by resetting time. Determine if, when this happens, we see + // an issue with timing in the reference implementaiton. + // + _plat__TimerReset(); + + Result = TEE_GetTAPersistentTime(&Time); + // If the reset didn't resolve the error condision, give up. + assert(Result == TEE_SUCCESS); + } + assert(Result == TEE_SUCCESS); + + Elapsed = ((Time.seconds * 1000) + (Time.millis)); + + return Elapsed; +} + +//***_plat__TimerRead() +// This function provides access to the tick timer of the platform. The TPM code +// uses this value to drive the TPM Clock. +// +// The tick timer is supposed to run when power is applied to the device. This timer +// should not be reset by time events including _TPM_Init. It should only be reset +// when TPM power is re-applied. +// +// If the TPM is run in a protected environment, that environment may provide the +// tick time to the TPM as long as the time provided by the environment is not +// allowed to go backwards. If the time provided by the system can go backwards +// during a power discontinuity, then the _plat__Signal_PowerOn should call +// _plat__TimerReset(). +LIB_EXPORT uint64_t +_plat__TimerRead( + void + ) +{ +#ifdef HARDWARE_CLOCK +#error "need a defintion for reading the hardware clock" + return HARDWARE_CLOCK +#else + clock64_t timeDiff; + clock64_t adjustedTimeDiff; + clock64_t timeNow; + clock64_t readjustedTimeDiff; + + // This produces a timeNow that is basically locked to the system clock. + timeNow = _plat__RealTime(); + + // if this hasn't been initialized, initialize it + if(s_lastSystemTime == 0) + { + s_lastSystemTime = timeNow; + if (s_TimerAvail) + TEE_GetSystemTime(&debugTime); + s_lastReportedTime = 0; + s_realTimePrevious = 0; + } + // The system time can bounce around and that's OK as long as we don't allow + // time to go backwards. When the time does appear to go backwards, set + // lastSystemTime to be the new value and then update the reported time. + if(timeNow < s_lastReportedTime) + s_lastSystemTime = timeNow; + s_lastReportedTime = s_lastReportedTime + timeNow - s_lastSystemTime; + s_lastSystemTime = timeNow; + timeNow = s_lastReportedTime; + + // The code above produces a timeNow that is similar to the value returned + // by Clock(). The difference is that timeNow does not max out, and it is + // at a ms. rate rather than at a CLOCKS_PER_SEC rate. The code below + // uses that value and does the rate adjustment on the time value. + // If there is no difference in time, then skip all the computations + if(s_realTimePrevious >= timeNow) + return s_tpmTime; + // Compute the amount of time since the last update of the system clock + timeDiff = timeNow - s_realTimePrevious; + + // Do the time rate adjustment and conversion from CLOCKS_PER_SEC to mSec + adjustedTimeDiff = (timeDiff * CLOCK_NOMINAL) / ((uint64_t)s_adjustRate); + + // update the TPM time with the adjusted timeDiff + s_tpmTime += (clock64_t)adjustedTimeDiff; + + // Might have some rounding error that would loose CLOCKS. See what is not + // being used. As mentioned above, this could result in putting back more than + // is taken out. Here, we are trying to recreate timeDiff. + readjustedTimeDiff = (adjustedTimeDiff * (uint64_t)s_adjustRate ) + / CLOCK_NOMINAL; + + // adjusted is now converted back to being the amount we should advance the + // previous sampled time. It should always be less than or equal to timeDiff. + // That is, we could not have use more time than we started with. + s_realTimePrevious = s_realTimePrevious + readjustedTimeDiff; + +#ifdef DEBUGGING_TIME + // Put this in so that TPM time will pass much faster than real time when + // doing debug. + // A value of 1000 for DEBUG_TIME_MULTIPLER will make each ms into a second + // A good value might be 100 + return (s_tpmTime * DEBUG_TIME_MULTIPLIER); +#endif + return s_tpmTime; +#endif +} + + + +//*** _plat__TimerWasReset() +// This function is used to interrogate the flag indicating if the tick timer has +// been reset. +// +// If the resetFlag parameter is SET, then the flag will be CLEAR before the +// function returns. +LIB_EXPORT BOOL +_plat__TimerWasReset( + void + ) +{ + BOOL retVal = s_timerReset; + s_timerReset = FALSE; + return retVal; +} + +//*** _plat__TimerWasStopped() +// This function is used to interrogate the flag indicating if the tick timer has +// been stopped. If so, this is typically a reason to roll the nonce. +// +// This function will CLEAR the s_timerStopped flag before returning. This provides +// functionality that is similar to status register that is cleared when read. This +// is the model used here because it is the one that has the most impact on the TPM +// code as the flag can only be accessed by one entity in the TPM. Any other +// implementation of the hardware can be made to look like a read-once register. +LIB_EXPORT BOOL +_plat__TimerWasStopped( + void + ) +{ + BOOL retVal = s_timerStopped; + s_timerStopped = FALSE; + return retVal; +} + +//***_plat__ClockAdjustRate() +// Adjust the clock rate +LIB_EXPORT void +_plat__ClockAdjustRate( + int adjust // IN: the adjust number. It could be positive + // or negative + ) +{ + // We expect the caller should only use a fixed set of constant values to + // adjust the rate + switch(adjust) + { + case CLOCK_ADJUST_COARSE: + s_adjustRate += CLOCK_ADJUST_COARSE; + break; + case -CLOCK_ADJUST_COARSE: + s_adjustRate -= CLOCK_ADJUST_COARSE; + break; + case CLOCK_ADJUST_MEDIUM: + s_adjustRate += CLOCK_ADJUST_MEDIUM; + break; + case -CLOCK_ADJUST_MEDIUM: + s_adjustRate -= CLOCK_ADJUST_MEDIUM; + break; + case CLOCK_ADJUST_FINE: + s_adjustRate += CLOCK_ADJUST_FINE; + break; + case -CLOCK_ADJUST_FINE: + s_adjustRate -= CLOCK_ADJUST_FINE; + break; + default: + // ignore any other values; + break; + } + + if(s_adjustRate > (CLOCK_NOMINAL + CLOCK_ADJUST_LIMIT)) + s_adjustRate = CLOCK_NOMINAL + CLOCK_ADJUST_LIMIT; + if(s_adjustRate < (CLOCK_NOMINAL - CLOCK_ADJUST_LIMIT)) + s_adjustRate = CLOCK_NOMINAL - CLOCK_ADJUST_LIMIT; + + return; +} + +//***_plat__SetTimerAvail() +// Set the current system timer to available. +LIB_EXPORT void +_plat__SetTimerAvail( + void + ) +{ + s_TimerAvail = TRUE; + return; +} + +//***_plat__ClearTimerAvail() +// Set the current system timer to unavailable. +LIB_EXPORT void +_plat__ClearTimerAvail( + void + ) +{ + s_TimerAvail = FALSE; + return; +} diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/DebugHelpers.c b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/DebugHelpers.c new file mode 100644 index 0000000..095920c --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/DebugHelpers.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2023-2024, NVIDIA Corporation & AFFILIATES. All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include "Platform.h" + +#if CERTIFYX509_DEBUG + +//*** DebugFileInit() +// Return Type: int +// 0 success +// != 0 error +int DebugFileInit(void) +{ + return 0; +} + +//*** DebugDumpBuffer() +void DebugDumpBuffer(int size, unsigned char *buf, const char *identifier) +{ + int i; + + if (identifier) + printf("%s\n", identifier); + + if (buf) { + for (i = 0; i < size; i++) { + if (((i % 16) == 0) && (i)) + printf("\n"); + printf(" %02X", buf[i]); + } + + if ((size % 16) != 0) + printf("\n"); + } +} + +#endif // CERTIFYX509_DEBUG diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/EPS.c b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/EPS.c new file mode 100644 index 0000000..4793efe --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/EPS.c @@ -0,0 +1,91 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// +// Platform Endorsement Primary Seed +// + +#include "TpmError.h" +#include "Admin.h" + +#include +#include + +#define TEE_EPS_SIZE (256/2) // From TPM2B_RSA_TEST_PRIME in Hierarchy.c + +void +_plat__GetEPS(UINT16 Size, uint8_t *EndorsementSeed) +{ + TEE_Result Result = TEE_ERROR_ITEM_NOT_FOUND; + uint8_t EPS[TEE_EPS_SIZE] = { 0 }; + size_t EPSLen; + + IMSG("Size=%" PRIu16 "",Size); + IMSG("EPS=%d",TEE_EPS_SIZE); + + pAssert(Size <= (TEE_EPS_SIZE)); + EPSLen = Size; + + Result = TEE_GetPropertyAsBinaryBlock(TEE_PROPSET_TEE_IMPLEMENTATION, + "com.microsoft.ta.endorsementSeed", + EPS, + &EPSLen); + + if ((EPSLen < Size) || (Result != TEE_SUCCESS)) { + // We failed to access the property. We can't continue without it + // and we can't just fail to manufacture, so randomize EPS and + // continue. If necessary, fTPM TA storage can be cleared, or the + // TA updated, and we can trigger remanufacture and try again. + _plat__GetEntropy(EndorsementSeed, TEE_EPS_SIZE); + return; + } + + memcpy(EndorsementSeed, EPS, Size); + +#ifdef fTPMDebug + { + uint32_t x; + uint8_t *seed = EndorsementSeed; + DMSG("TEE_GetProperty 0x%x, seedLen 0x%x\n", Result, Size); + for (x = 0; x < Size; x = x + 8) { + DMSG(" seed(%2.2d): %2.2x,%2.2x,%2.2x,%2.2x,%2.2x,%2.2x,%2.2x,%2.2x\n", x, + seed[x + 0], seed[x + 1], seed[x + 2], seed[x + 3], + seed[x + 4], seed[x + 5], seed[x + 6], seed[x + 7]); + } + } +#endif + + return; +} diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/Entropy.c b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/Entropy.c new file mode 100644 index 0000000..3ca2fed --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/Entropy.c @@ -0,0 +1,128 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Includes and Local Values + +#define _CRT_RAND_S +#include +#include +#include "PlatformData.h" +#include "Platform_fp.h" +#include + +#include + +#ifdef _MSC_VER +#include +#else +#include +#endif + +// This is the last 32-bits of hardware entropy produced. We have to check to +// see that two consecutive 32-bit values are not the same because +// (according to FIPS 140-2, annex C +// +// 1. If each call to a RNG produces blocks of n bits (where n > 15), the first +// n-bit block generated after power-up, initialization, or reset shall not be +// used, but shall be saved for comparison with the next n-bit block to be +// generated. Each subsequent generation of an n-bit block shall be compared with +// the previously generated block. The test shall fail if any two compared n-bit +// blocks are equal. +extern uint32_t lastEntropy; + +//** Functions + +//*** rand32() +// Local function to get a 32-bit random number +static uint32_t +rand32( + void +) +{ + + uint32_t rndNum; + TEE_GenerateRandom((void *)(&rndNum), sizeof(uint32_t)); + return rndNum; +} + + +//** _plat__GetEntropy() +// This function is used to get available hardware entropy. In a hardware +// implementation of this function, there would be no call to the system +// to get entropy. +// return type: int32_t +// < 0 hardware failure of the entropy generator, this is sticky +// >= 0 the returned amount of entropy (bytes) +// +LIB_EXPORT int32_t +_plat__GetEntropy( + unsigned char *entropy, // output buffer + uint32_t amount // amount requested +) +{ + uint32_t rndNum; + int32_t ret; + + if(amount == 0) + { + lastEntropy = rand32(); + ret = 0; + } + else + { + rndNum = rand32(); + if(rndNum == lastEntropy) + { + ret = -1; + } + else + { + lastEntropy = rndNum; + // Each process will have its random number generator initialized according + // to the process id and the initialization time. This is not a lot of + // entropy so, to add a bit more, XOR the current time value into the + // returned entropy value. + // NOTE: the reason for including the time here rather than have it in + // in the value assigned to lastEntropy is that rand() could be broken and + // using the time would in the lastEntropy value would hide this. + rndNum ^= (uint32_t)_plat__RealTime(); + + // Only provide entropy 32 bits at a time to test the ability + // of the caller to deal with partial results. + ret = MIN(amount, sizeof(rndNum)); + memcpy(entropy, &rndNum, ret); + } + } + return ret; +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/EventLogPrint.c b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/EventLogPrint.c new file mode 100644 index 0000000..9c95c30 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/EventLogPrint.c @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifdef EVENT_LOG_LEVEL +#undef EVENT_LOG_LEVEL +#endif + +#ifdef LOG_LEVEL +#undef LOG_LEVEL +#endif + +#define EVENT_LOG_LEVEL 1 +#define LOG_LEVEL 1 + +#if LOG_LEVEL >= EVENT_LOG_LEVEL + +/* + * Print TCG_EfiSpecIDEventStruct + * + * @param[in/out] log_addr Pointer to Event Log + * @param[in/out] log_size Pointer to Event Log size + */ +static void id_event_print(uint8_t **log_addr, size_t *log_size) +{ + unsigned int i; + uint8_t info_size, *info_size_ptr; + void *ptr = *log_addr; + id_event_headers_t *event = (id_event_headers_t *)ptr; + id_event_algorithm_size_t *alg_ptr; + uint32_t event_size, number_of_algorithms; + size_t digest_len; + const uint8_t *end_ptr = *log_addr + *log_size; + char str_buf[1024]; + + assert(*log_size >= sizeof(id_event_headers_t)); + + /* The fields of the event log header are defined to be PCRIndex of 0, + * EventType of EV_NO_ACTION, Digest of 20 bytes of 0, and + * Event content defined as TCG_EfiSpecIDEventStruct. + */ + MSG("TCG_EfiSpecIDEvent:\n"); + MSG(" PCRIndex : %u\n", event->header.pcr_index); + MSG(" EventType : %u\n", event->header.event_type); + str_buf[0] = 0; + snprintf(str_buf, 1024, " Digest :"); + for (i = 0U; i < sizeof(event->header.digest); ++i) { + uint8_t val = event->header.digest[i]; + + snprintf(str_buf, 1024, "%s %02x", str_buf, val); + if ((i & U(0xF)) == 0U) { + MSG("%s\n", str_buf); + str_buf[0] = 0; + snprintf(str_buf, 1024, "\t\t\t :"); + } + } + MSG("%s\n", str_buf); + str_buf[0] = 0; + + /* EventSize */ + event_size = event->header.event_size; + MSG(" EventSize : %u\n", event_size); + + MSG(" Signature : %s\n", + event->struct_header.signature); + MSG(" PlatformClass : %u\n", + event->struct_header.platform_class); + MSG(" SpecVersion : %u.%u.%u\n", + event->struct_header.spec_version_major, + event->struct_header.spec_version_minor, + event->struct_header.spec_errata); + MSG(" UintnSize : %u\n", + event->struct_header.uintn_size); + + /* NumberOfAlgorithms */ + number_of_algorithms = event->struct_header.number_of_algorithms; + MSG(" NumberOfAlgorithms : %u\n", number_of_algorithms); + + /* Address of DigestSizes[] */ + alg_ptr = event->struct_header.digest_size; + + /* Size of DigestSizes[] */ + digest_len = number_of_algorithms * sizeof(id_event_algorithm_size_t); + + assert(((uint8_t *)alg_ptr + digest_len) <= end_ptr); + + MSG(" DigestSizes :\n"); + for (i = 0U; i < number_of_algorithms; ++i) { + snprintf(str_buf, 1024, " #%u AlgorithmId : SHA", i); + uint16_t algorithm_id = alg_ptr[i].algorithm_id; + + switch (algorithm_id) { + case TPM_ALG_SHA256: + snprintf(str_buf, 1024, "%s256\n", str_buf); + break; + case TPM_ALG_SHA384: + snprintf(str_buf, 1024, "%s384\n", str_buf); + break; + case TPM_ALG_SHA512: + snprintf(str_buf, 1024, "%s512\n", str_buf); + break; + default: + snprintf(str_buf, 1024, "%s?\n", str_buf); + EMSG("Algorithm 0x%x not found\n", algorithm_id); + assert(false); + } + + MSG("%s", str_buf); + MSG(" DigestSize : %u\n", + alg_ptr[i].digest_size); + str_buf[0] = 0; + } + + /* Address of VendorInfoSize */ + info_size_ptr = (uint8_t *)alg_ptr + digest_len; + assert(info_size_ptr <= end_ptr); + + info_size = *info_size_ptr++; + MSG(" VendorInfoSize : %u\n", info_size); + + /* Check VendorInfo end address */ + assert((info_size_ptr + info_size) <= end_ptr); + + /* Check EventSize */ + assert(event_size == (sizeof(id_event_struct_t) + + digest_len + info_size)); + if (info_size != 0U) { + snprintf(str_buf, 1024, " VendorInfo :"); + for (i = 0U; i < info_size; ++i) { + snprintf(str_buf, 1024, "%s %02x", str_buf, + *info_size_ptr++); + } + MSG("%s\n", str_buf); + str_buf[0] = 0; + } + + *log_size -= (uintptr_t)info_size_ptr - (uintptr_t)*log_addr; + *log_addr = info_size_ptr; +} + +/* + * Print TCG_PCR_EVENT2 + * + * @param[in/out] log_addr Pointer to Event Log + * @param[in/out] log_size Pointer to Event Log size + */ +static void event2_print(uint8_t **log_addr, size_t *log_size) +{ + uint32_t event_size, count; + size_t sha_size, digests_size = 0U; + void *ptr = *log_addr; + char str_buf[1024]; + + const uint8_t *end_ptr = *log_addr + *log_size; + + assert(*log_size >= sizeof(event2_header_t)); + + MSG("PCR_Event2:\n"); + MSG(" PCRIndex : %u\n", + ((event2_header_t *)ptr)->pcr_index); + MSG(" EventType : %u\n", + ((event2_header_t *)ptr)->event_type); + + count = ((event2_header_t *)ptr)->digests.count; + MSG(" Digests Count : %u\n", count); + + /* Address of TCG_PCR_EVENT2.Digests[] */ + ptr = (uint8_t *)ptr + sizeof(event2_header_t); + assert(((uintptr_t)ptr <= (uintptr_t)end_ptr) && (count != 0U)); + + str_buf[0] = 0; + for (unsigned int i = 0U; i < count; ++i) { + /* Check AlgorithmId address */ + assert(((uint8_t *)ptr + offsetof(tpmt_ha, digest)) <= end_ptr); + + snprintf(str_buf, 1024, " #%u AlgorithmId : SHA", i); + switch (((tpmt_ha *)ptr)->algorithm_id) { + case TPM_ALG_SHA256: + sha_size = SHA256_DIGEST_SIZE; + snprintf(str_buf, 1024, "%s256\n", str_buf); + break; + case TPM_ALG_SHA384: + sha_size = SHA384_DIGEST_SIZE; + snprintf(str_buf, 1024, "%s384\n", str_buf); + break; + case TPM_ALG_SHA512: + sha_size = SHA512_DIGEST_SIZE; + snprintf(str_buf, 1024, "%s512\n", str_buf); + break; + default: + snprintf(str_buf, 1024, "%s?\n", str_buf); + EMSG("Algorithm 0x%x not found\n", + ((tpmt_ha *)ptr)->algorithm_id); + assert(true); + } + MSG("%s", str_buf); + str_buf[0] = 0; + + /* End of Digest[] */ + ptr = (uint8_t *)ptr + offsetof(tpmt_ha, digest); + assert(((uint8_t *)ptr + sha_size) <= end_ptr); + + /* Total size of all digests */ + digests_size += sha_size; + + snprintf(str_buf, 1024, " Digest :"); + for (unsigned int j = 0U; j < sha_size; ++j) { + snprintf(str_buf, 1024, "%s %02x", str_buf, + *(uint8_t *)ptr++); + if ((j & U(0xF)) == U(0xF)) { + MSG("%s\n", str_buf); + str_buf[0] = 0; + if (j < (sha_size - 1U)) { + snprintf(str_buf, 1024, "\t\t\t :"); + } + } + } + } + + /* TCG_PCR_EVENT2.EventSize */ + assert(((uint8_t *)ptr + offsetof(event2_data_t, event)) <= end_ptr); + + event_size = ((event2_data_t *)ptr)->event_size; + MSG(" EventSize : %u\n", event_size); + + /* Address of TCG_PCR_EVENT2.Event[EventSize] */ + ptr = (uint8_t *)ptr + offsetof(event2_data_t, event); + + /* End of TCG_PCR_EVENT2.Event[EventSize] */ + assert(((uint8_t *)ptr + event_size) <= end_ptr); + + if ((event_size == sizeof(startup_locality_event_t)) && + (strcmp((const char *)ptr, TCG_STARTUP_LOCALITY_SIGNATURE) == 0)) { + MSG(" Signature : %s\n", + ((startup_locality_event_t *)ptr)->signature); + MSG(" StartupLocality : %u\n", + ((startup_locality_event_t *)ptr)->startup_locality); + } else { + MSG(" Event : %s\n", (uint8_t *)ptr); + } + + *log_size -= (uintptr_t)ptr + event_size - (uintptr_t)*log_addr; + *log_addr = (uint8_t *)ptr + event_size; +} +#endif /* LOG_LEVEL >= EVENT_LOG_LEVEL */ + +/* + * Print Event Log + * + * @param[in] log_addr Pointer to Event Log + * @param[in] log_size Event Log size + */ +void dump_event_log(uint8_t *log_addr, size_t log_size) +{ +#if LOG_LEVEL >= EVENT_LOG_LEVEL + assert(log_addr != NULL); + + /* Print TCG_EfiSpecIDEvent */ + id_event_print(&log_addr, &log_size); + + while (log_size != 0U) { + event2_print(&log_addr, &log_size); + } +#endif +} diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/LocalityPlat.c b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/LocalityPlat.c new file mode 100644 index 0000000..1d74c57 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/LocalityPlat.c @@ -0,0 +1,65 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Includes + +#include "PlatformData.h" +#include "Platform_fp.h" + +//** Functions + +//***_plat__LocalityGet() +// Get the most recent command locality in locality value form. +// This is an integer value for locality and not a locality structure +// The locality can be 0-4 or 32-255. 5-31 is not allowed. +LIB_EXPORT unsigned char +_plat__LocalityGet( + void + ) +{ + return s_locality; +} + +//***_plat__LocalitySet() +// Set the most recent command locality in locality value form +LIB_EXPORT void +_plat__LocalitySet( + unsigned char locality + ) +{ + if(locality > 4 && locality < 32) + locality = 0; + s_locality = locality; + return; +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/NVMem.c b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/NVMem.c new file mode 100644 index 0000000..4335d43 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/NVMem.c @@ -0,0 +1,666 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * Copyright (c) 2023-2024, NVIDIA Corporation & AFFILIATES. All rights reserved. + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Description +// +// This file contains the NV read and write access methods. This implementation +// uses RAM/file and does not manage the RAM/file as NV blocks. +// The implementation may become more sophisticated over time. +// + +#include "TpmError.h" +#include "Admin.h" +#include "VendorString.h" +#include "stdint.h" +#include "malloc.h" +#include "string.h" + +#include +#include + +// +// Overall size of NV, not just the TPM's NV storage +// +#define NV_CHIP_MEMORY_SIZE (NV_MEMORY_SIZE + NV_TPM_STATE_SIZE) + +// +// OpTEE still has an all or nothing approach to reads/writes. To provide +// more performant access to storage, break up NV accross 1Kbyte blocks. +// +// Note that NV_CHIP_MEMORY_SIZE *MUST* be a factor of NV_BLOCK_SIZE. +// +#define NV_BLOCK_SIZE 0x200 +#define NV_BLOCK_COUNT ((NV_CHIP_MEMORY_SIZE) / (NV_BLOCK_SIZE)) + +// +// For cleaner descriptor validation +// +#define IS_VALID(a) ((a) != (TEE_HANDLE_NULL)) + +// +// Storage flags +// +#define TA_STORAGE_FLAGS (TEE_DATA_FLAG_ACCESS_READ | \ + TEE_DATA_FLAG_ACCESS_WRITE | \ + TEE_DATA_FLAG_ACCESS_WRITE_META) + +// +// The base Object ID for fTPM storage +// +static const UINT32 s_StorageObjectID = 0x54504D00; // 'TPM00' + +// +// Object handle list for persistent storage objects containing NV +// +static TEE_ObjectHandle s_NVStore[NV_BLOCK_COUNT] = { TEE_HANDLE_NULL }; + +// +// Bitmap for NV blocks. Moving from UINT64 requires change to NV_DIRTY_ALL. +// +static UINT64 s_blockMap = 0x0ULL; + +// +// Shortcut for 'dirty'ing all NV blocks. Note the type. +// +#if NV_BLOCK_COUNT < 64 +#define NV_DIRTY_ALL ((UINT64)((0x1ULL << NV_BLOCK_COUNT) - 1)) +#elif NV_BLOCK_COUNT == 64 +#define NV_DIRTY_ALL (~(0x0ULL)) +#else +#error "NV block count exceeds 64 bit block map. Adjust block or NV size." +#endif + +// +// NV state +// +static BOOL s_NVChipFileNeedsManufacture = FALSE; +static BOOL s_NVInitialized = FALSE; +static UCHAR s_NV[NV_CHIP_MEMORY_SIZE]; + +// +// Firmware revision +// +static const UINT32 firmwareV1 = FIRMWARE_V1; +static const UINT32 firmwareV2 = FIRMWARE_V2; + +// +// Revision fro NVChip +// +static UINT64 s_chipRevision = 0; + +// +// This offset puts the revision field immediately following the TPM Admin +// state. The Admin space in NV is down to ~16 bytes but is padded out to +// 256bytes to avoid alignment issues and allow for growth. +// +#define NV_CHIP_REVISION_OFFSET ((NV_MEMORY_SIZE) + (TPM_STATE_SIZE)) + +// +// This is the NVMem available flag to indicate that the NVMem is available +// for the running stage. +// +static BOOL s_NvMemAvail = FALSE; + +VOID +_plat__NvInitFromStorage() +{ + DMSG("_plat__NvInitFromStorage()"); + UINT32 i; + BOOL initialized; + UINT32 objID; + size_t bytesRead; + TEE_Result Result; + + // Don't initialize NvMem if it's not available. + if (FALSE == s_NvMemAvail) { + s_NVInitialized = TRUE; + return; + } + + // Don't re-initialize. + if (s_NVInitialized) { + return; + } + + // + // If the NV file is successfully read from the storage then + // initialized must be set. We are setting initialized to true + // here but if an error is encountered reading the NV file it will + // be reset. + // + + initialized = TRUE; + + // Collect storage objects and init NV. + for (i = 0; i < NV_BLOCK_COUNT; i++) { + + // Form storage object ID for this block. + objID = s_StorageObjectID + i; + + // Attempt to open TEE persistent storage object. + Result = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE, + (void *)&objID, + sizeof(objID), + TA_STORAGE_FLAGS, + &s_NVStore[i]); + + // If the open failed, try to create this storage object. + if (Result != TEE_SUCCESS) { + + // There was an error, fail the init, NVEnable can retry. + if (Result != TEE_ERROR_ITEM_NOT_FOUND) { +#ifdef fTPMDebug + DMSG("Failed to open fTPM storage object"); +#endif + goto Error; + } + + // Storage object was not found, create it. + Result = TEE_CreatePersistentObject(TEE_STORAGE_PRIVATE, + (void *)&objID, + sizeof(objID), + TA_STORAGE_FLAGS, + NULL, + (void *)&(s_NV[i * NV_BLOCK_SIZE]), + NV_BLOCK_SIZE, + &s_NVStore[i]); + + // There was an error, fail the init, NVEnable can retry. + if (Result != TEE_SUCCESS) { +#ifdef fTPMDebug + DMSG("Failed to create fTPM storage object"); +#endif + goto Error; + } + + // A clean storage object was created, we must (re)manufacture. + s_NVChipFileNeedsManufacture = TRUE; + + // To ensure NV is consistent, force a write back of all NV blocks + s_blockMap = NV_DIRTY_ALL; + + // Need to re-initialize + initialized = FALSE; + +#ifdef fTPMDebug + IMSG("Created fTPM storage object, i: 0x%x, s: 0x%x, id: 0x%x, h:0x%x\n", + i, NV_BLOCK_SIZE, objID, s_NVStore[i]); +#endif + } + else { + // Successful open, now read fTPM storage object. + Result = TEE_ReadObjectData(s_NVStore[i], + (void *)&(s_NV[i * NV_BLOCK_SIZE]), + NV_BLOCK_SIZE, + &bytesRead); + + // Give up on failed or incomplete reads. + if ((Result != TEE_SUCCESS) || (bytesRead != NV_BLOCK_SIZE)) { +#ifdef fTPMDebug + DMSG("Failed to read fTPM storage object"); +#endif + goto Error; + } + +#ifdef fTPMDebug + IMSG("Read fTPM storage object, i: 0x%x, s: 0x%x, id: 0x%x, h:0x%x\n", + i, bytesRead, objID, s_NVStore[i]); +#endif + } + } + + // Storage objects are open and valid, next validate revision + s_chipRevision = ((((UINT64)firmwareV2) << 32) | (firmwareV1)); + if ((s_chipRevision != *(UINT64*)&(s_NV[NV_CHIP_REVISION_OFFSET]))) { + + // Failure to validate revision, re-init. + memset(s_NV, 0, NV_CHIP_MEMORY_SIZE); + + // Dirty the block map, we're going to re-init. + s_blockMap = NV_DIRTY_ALL; + + // Init with proper revision + s_chipRevision = ((((UINT64)firmwareV2) << 32) | (firmwareV1)); + *(UINT64*)&(s_NV[NV_CHIP_REVISION_OFFSET]) = s_chipRevision; + +#ifdef fTPMDebug + DMSG("Failed to validate revision."); +#endif + + // Force (re)manufacture. + s_NVChipFileNeedsManufacture = TRUE; + + // Need to re-initialize + initialized = FALSE; + + return; + } + + s_NVInitialized = initialized; + + return; + +Error: + s_NVInitialized = FALSE; + for (i = 0; i < NV_BLOCK_COUNT; i++) { + if (IS_VALID(s_NVStore[i])) { + TEE_CloseObject(s_NVStore[i]); + s_NVStore[i] = TEE_HANDLE_NULL; + } + } + + return; +} + + +static void +_plat__NvWriteBack() +{ + UINT32 i; + UINT32 objID; + TEE_Result Result; + + // Exit if no dirty blocks. + if ((!s_blockMap) || (!s_NVInitialized) || (!s_NvMemAvail)) { + return; + } + +#ifdef fTPMDebug + DMSG("bMap: 0x%x\n", s_blockMap); +#endif + + // Write dirty blocks. + for (i = 0; i < NV_BLOCK_COUNT; i++) { + + if ((s_blockMap & (0x1ULL << i))) { + + // Form storage object ID for this block. + objID = s_StorageObjectID + i; + + // Move data position associated with handle to start of block. + Result = TEE_SeekObjectData(s_NVStore[i], 0, TEE_DATA_SEEK_SET); + if (Result != TEE_SUCCESS) { + goto Error; + } + + // Write out this block. + Result = TEE_WriteObjectData(s_NVStore[i], + (void *)&(s_NV[i * NV_BLOCK_SIZE]), + NV_BLOCK_SIZE); + if (Result != TEE_SUCCESS) { + goto Error; + } + + // Force storage stack to update its backing store + TEE_CloseObject(s_NVStore[i]); + + Result = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE, + (void *)&objID, + sizeof(objID), + TA_STORAGE_FLAGS, + &s_NVStore[i]); + // Success? + if (Result != TEE_SUCCESS) { + goto Error; + } + + // Clear dirty bit. + s_blockMap &= ~(0x1ULL << i); + } + } + + return; + +Error: + // Error path. +#ifdef fTPMDebug + DMSG("NV write back failed"); +#endif + s_NVInitialized = FALSE; + for (i = 0; i < NV_BLOCK_COUNT; i++) { + if (IS_VALID(s_NVStore[i])) { + TEE_CloseObject(s_NVStore[i]); + s_NVStore[i] = TEE_HANDLE_NULL; + } + } + + return; +} + + +BOOL +_plat__NvNeedsManufacture() +{ + return s_NVChipFileNeedsManufacture; +} + +//***_plat__NVEnable() +// Enable NV memory. +// +// This version just pulls in data from a file. In a real TPM, with NV on chip, +// this function would verify the integrity of the saved context. If the NV +// memory was not on chip but was in something like RPMB, the NV state would be +// read in, decrypted and integrity checked. +// +// The recovery from an integrity failure depends on where the error occurred. It +// it was in the state that is discarded by TPM Reset, then the error is +// recoverable if the TPM is reset. Otherwise, the TPM must go into failure mode. +// return type: int +// 0 if success +// > 0 if receive recoverable error +// <0 if unrecoverable error +LIB_EXPORT int +_plat__NVEnable( + void *platParameter // IN: platform specific parameters + ) +{ + UNREFERENCED_PARAMETER(platParameter); + DMSG("_plat__NVEnable()"); + + + UINT32 retVal = 0; + UINT32 firmwareV1 = FIRMWARE_V1; + UINT32 firmwareV2 = FIRMWARE_V2; + + // Don't re-open the backing store. + if (s_NVInitialized) { + return 0; + } + + // Clear NV + memset(s_NV, 0, NV_CHIP_MEMORY_SIZE); + + // Prepare for potential failure to retreieve NV from storage + s_chipRevision = ((((UINT64)firmwareV2) << 32) | (firmwareV1)); + *(UINT64*)&(s_NV[NV_CHIP_REVISION_OFFSET]) = s_chipRevision; + + // Pick up our NV memory. + _plat__NvInitFromStorage(); + + // Were we successful? + if (!s_NVInitialized) { + // Arriving here means one of two things: Either there existed no + // NV state before we came along and we just (re)initialized our + // storage. Or there is an error condition preventing us from + // accessing storage. Check which is the case. + if (s_NVChipFileNeedsManufacture == FALSE) { + // This condition means we cannot access storage. However, it + // isn't up to the platform layer to decide what to do in this + // case. The decision to proceed is made in the fTPM init code + // in TA_CreateEntryPoint. Here, we're going to make sure that, + // should we decide not to just TEE_Panic, we can continue + // execution after (re)manufacture. Later an attempt at re-init + // can be made by calling _plat__NvInitFromStorage again. + retVal = 0; + } + else { + retVal = 1; + } + + // Going to manufacture, zero flags + g_chipFlags.flags = 0; + + // Save flags + _admin__SaveChipFlags(); + + // Now we're done + if (s_NvMemAvail) + s_NVInitialized = TRUE; + + return retVal; + } + else { + // In the transition out of UEFI to Windows, we may not tear down + // the TA. We close out one session and start another. This means + // our s_NVChipFileNeedsManufacture flag, if set, will be stale. + // Make sure we don't re-manufacture. + s_NVChipFileNeedsManufacture = FALSE; + + // We successfully initialized NV now pickup TPM state. + _admin__RestoreChipFlags(); + + // Success + retVal = 1; + } + + return retVal; +} + +//***_plat__NVDisable() +// Disable NV memory +LIB_EXPORT void +_plat__NVDisable( + void + ) +{ + UINT32 i; + + if (!s_NVInitialized) { + return; + } + + // Final write + _plat__NvWriteBack(); + + // Close out all handles + for (i = 0; i < NV_BLOCK_COUNT; i++) { + if (IS_VALID(s_NVStore[i])) { + TEE_CloseObject(s_NVStore[i]); + s_NVStore[i] = TEE_HANDLE_NULL; + } + } + + // We're no longer init-ed + s_NVInitialized = FALSE; + + return; +} + +//***_plat__IsNvAvailable() +// Check if NV is available +// return type: int +// 0 NV is available +// 1 NV is not available due to write failure +// 2 NV is not available due to rate limit +LIB_EXPORT int +_plat__IsNvAvailable( + void + ) +{ + // This is not enabled for OpTEE TA. Storage is always available. + return 0; +} + + + +//***_plat__NvMemoryRead() +// Function: Read a chunk of NV memory +LIB_EXPORT void +_plat__NvMemoryRead( + unsigned int startOffset, // IN: read start + unsigned int size, // IN: size of bytes to read + void *data // OUT: data buffer + ) +{ + pAssert((startOffset + size) <= NV_CHIP_MEMORY_SIZE); + pAssert(s_NV != NULL); + + memcpy(data, &s_NV[startOffset], size); +} + +//*** _plat__NvIsDifferent() +// This function checks to see if the NV is different from the test value. This is +// so that NV will not be written if it has not changed. +// return value: int +// TRUE(1) the NV location is different from the test value +// FALSE(0) the NV location is the same as the test value +LIB_EXPORT int +_plat__NvIsDifferent( + unsigned int startOffset, // IN: read start + unsigned int size, // IN: size of bytes to read + void *data // IN: data buffer + ) +{ + return (memcmp(&s_NV[startOffset], data, size) != 0); +} + +static +void +_plat__MarkDirtyBlocks ( + unsigned int startOffset, + unsigned int size +) +{ + unsigned int blockEnd; + unsigned int blockStart; + unsigned int i; + + // + // Integer math will round down to the start of the block. + // blockEnd is actually the last block + 1. + // + + blockStart = startOffset / NV_BLOCK_SIZE; + blockEnd = (startOffset + size) / NV_BLOCK_SIZE; + if ((startOffset + size) % NV_BLOCK_SIZE != 0) { + blockEnd += 1; + } + + for (i = blockStart; i < blockEnd; i++) { + s_blockMap |= (0x1ULL << i); + } +} + +//***_plat__NvMemoryWrite() +// This function is used to update NV memory. The "write" is to a memory copy of +// NV. At the end of the current command, any changes are written to +// the actual NV memory. +// NOTE: A useful optimization would be for this code to compare the current +// contents of NV with the local copy and note the blocks that have changed. Then +// only write those blocks when _plat__NvCommit() is called. +LIB_EXPORT void +_plat__NvMemoryWrite( + unsigned int startOffset, // IN: write start + unsigned int size, // IN: size of bytes to write + void *data // OUT: data buffer + ) +{ + pAssert(startOffset + size <= NV_CHIP_MEMORY_SIZE); + pAssert(s_NV != NULL); + + _plat__MarkDirtyBlocks(startOffset, size); + memcpy(&s_NV[startOffset], data, size); +} + +//***_plat__NvMemoryClear() +// Function is used to set a range of NV memory bytes to an implementation-dependent +// value. The value represents the erase state of the memory. +LIB_EXPORT void +_plat__NvMemoryClear( + unsigned int start, // IN: clear start + unsigned int size // IN: number of bytes to clear + ) +{ + pAssert(start + size <= NV_MEMORY_SIZE); + + _plat__MarkDirtyBlocks(start, size); + memset(&s_NV[start], 0, size); +} + +//***_plat__NvMemoryMove() +// Function: Move a chunk of NV memory from source to destination +// This function should ensure that if there overlap, the original data is +// copied before it is written +LIB_EXPORT void +_plat__NvMemoryMove( + unsigned int sourceOffset, // IN: source offset + unsigned int destOffset, // IN: destination offset + unsigned int size // IN: size of data being moved + ) +{ + pAssert(sourceOffset + size <= NV_CHIP_MEMORY_SIZE); + pAssert(destOffset + size <= NV_CHIP_MEMORY_SIZE); + pAssert(s_NV != NULL); + + _plat__MarkDirtyBlocks(sourceOffset, size); + _plat__MarkDirtyBlocks(destOffset, size); + + memmove(&s_NV[destOffset], &s_NV[sourceOffset], size); +} + +//***_plat__NvCommit() +// This function writes the local copy of NV to NV for permanent store. It will write +// NV_MEMORY_SIZE bytes to NV. If a file is use, the entire file is written. +// return type: int +// 0 NV write success +// non-0 NV write fail +LIB_EXPORT int +_plat__NvCommit( + void + ) +{ + _plat__NvWriteBack(); + return 0; +} + +//***_plat__SetNvAvail() +// Set the current NV state to available. This function is for testing purpose +// only. It is not part of the platform NV logic +LIB_EXPORT void +_plat__SetNvAvail( + void + ) +{ + s_NvMemAvail = TRUE; + + // Re-set the initialize values when NVMem is available. + s_NVChipFileNeedsManufacture = FALSE; + s_NVInitialized = FALSE; + + return; +} + +//***_plat__ClearNvAvail() +// Set the current NV state to unavailable. This function is for testing purpose +// only. It is not part of the platform NV logic +LIB_EXPORT void +_plat__ClearNvAvail( + void + ) +{ + s_NvMemAvail = FALSE; + + return; +} diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/NvAdmin.c b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/NvAdmin.c new file mode 100644 index 0000000..2576001 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/NvAdmin.c @@ -0,0 +1,151 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//**Includes +// Force Global.h contents inclusion +#define GLOBAL_C + +#include "Admin.h" + +//**Types, Structures, and Defines +// +// List of pre-defined address of TPM state data +// +static UINT32 s_stateAddr[NV_TPM_STATE_LAST]; + +// +// List of pre-defined TPM state data size in byte +// +static UINT32 s_stateSize[NV_TPM_STATE_LAST]; + +// +// The current chip state +// +TPM_CHIP_STATE g_chipFlags; + +// +// The current PPI state +// +extern FTPM_PPI_STATE s_PPIState; + +//***_admin__NvInitState() +// Initialize the state NV runtime state values +void +_admin__NvInitState() +{ + UINT16 i; + UINT32 stateAddr; + + // + // Initialize TPM saved runtime state + // + s_stateSize[NV_TPM_STATE_FLAGS] = sizeof(TPM_CHIP_STATE); + s_stateSize[NV_TPM_STATE_PPI] = sizeof(FTPM_PPI_STATE); + + // + // Initialize TPM state data addresses. Stored after the main NV space. + // + stateAddr = NV_MEMORY_SIZE; + for (i = 0; i < NV_TPM_STATE_LAST; i++) { + s_stateAddr[i] = stateAddr; + stateAddr += s_stateSize[i]; + } + + pAssert(stateAddr <= (NV_MEMORY_SIZE + NV_TPM_STATE_SIZE)); +} + +//***_admin__SaveChipFlags() +// Save the g_chipFlags runtime state +void +_admin__SaveChipFlags() +{ + _admin__NvWriteState(NV_TPM_STATE_FLAGS, &g_chipFlags); +} + +//***_admin__RestoreChipFlags() +// Restore the g_chipFlags runtime state +void +_admin__RestoreChipFlags() +{ + _admin__NvReadState(NV_TPM_STATE_FLAGS, &g_chipFlags); +} + +//***_admin__SavePPIState() +// Save the s_PPIState runtime state +void +_admin__SavePPIState() +{ + _admin__NvWriteState(NV_TPM_STATE_PPI, &s_PPIState); + + _plat__NvCommit(); +} + +//***_admin__RestorePPIState() +// Restore the s_PPIState runtime state +void +_admin__RestorePPIState() +{ + _admin__NvReadState(NV_TPM_STATE_PPI, &s_PPIState); +} + +//***_admin__NvReadState() +// Read TPM state data from NV memory to RAM +void +_admin__NvReadState( + NV_TPM_STATE type, // IN: type of state data + void *buffer // OUT: data buffer + ) +{ + // Input type should be valid + pAssert(type >= 0 && type < NV_TPM_STATE_LAST); + + _plat__NvMemoryRead(s_stateAddr[type], s_stateSize[type], buffer); + return; +} + +//***_admin__NvWriteState() +// Write TPM state data to NV memory +void +_admin__NvWriteState( + NV_TPM_STATE type, // IN: type of state data + void *buffer // IN: data buffer + ) +{ + // Input type should be valid + pAssert(type >= 0 && type < NV_TPM_STATE_LAST); + + _plat__NvMemoryWrite(s_stateAddr[type], s_stateSize[type], buffer); + return; +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/PPPlat.c b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/PPPlat.c new file mode 100644 index 0000000..8b837a1 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/PPPlat.c @@ -0,0 +1,80 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Description + +// This module simulates the physical presence interface pins on the TPM. + +//** Includes +#include "PlatformData.h" +#include "Platform_fp.h" + +//** Functions + +//***_plat__PhysicalPresenceAsserted() +// Check if physical presence is signaled +// return type: int +// TRUE(1) if physical presence is signaled +// FALSE(0) if physical presence is not signaled +LIB_EXPORT int +_plat__PhysicalPresenceAsserted( + void + ) +{ + // Do not know how to check physical presence without real hardware. + // so always return TRUE; + return s_physicalPresence; +} + +//***_plat__Signal_PhysicalPresenceOn() +// Signal physical presence on +LIB_EXPORT void +_plat__Signal_PhysicalPresenceOn( + void + ) +{ + s_physicalPresence = TRUE; + return; +} + +//***_plat__Signal_PhysicalPresenceOff() +// Signal physical presence off +LIB_EXPORT void +_plat__Signal_PhysicalPresenceOff( + void + ) +{ + s_physicalPresence = FALSE; + return; +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/PlatformACT.c b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/PlatformACT.c new file mode 100644 index 0000000..9528b08 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/PlatformACT.c @@ -0,0 +1,345 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Includes +#include "Platform.h" + +//** Global variables +#define DEFINE_ACT(N) ACT_DATA ACT_##N; +FOR_EACH_ACT(DEFINE_ACT) + +int actTicksAllowed; + +//** Functions + +//*** ActSignal() +// Function called when there is an ACT event to signal or unsignal +static void +ActSignal( + P_ACT_DATA actData, + int on +) +{ + if(actData == NULL) + return; + // If this is to turn a signal on, don't do anything if it is already on. If this + // is to turn the signal off, do it anyway because this might be for + // initialization. + if(on && (actData->signaled == TRUE)) + return; + actData->signaled = (uint8_t)on; + + // If there is an action, then replace the "Do something" with the correct action. + // It should test 'on' to see if it is turning the signal on or off. + switch(actData->number) + { +#if RH_ACT_0 + case 0: // Do something + return; +#endif +#if RH_ACT_1 + case 1: // Do something + return; +#endif +#if RH_ACT_2 + case 2: // Do something + return; +#endif +#if RH_ACT_3 + case 3: // Do something + return; +#endif +#if RH_ACT_4 + case 4: // Do something + return; +#endif +#if RH_ACT_5 + case 5: // Do something + return; +#endif +#if RH_ACT_6 + case 6: // Do something + return; +#endif +#if RH_ACT_7 + case 7: // Do something + return; +#endif +#if RH_ACT_8 + case 8: // Do something + return; +#endif +#if RH_ACT_9 + case 9: // Do something + return; +#endif +#if RH_ACT_A + case 0xA: // Do something + return; +#endif +#if RH_ACT_B + case 0xB: + // Do something + return; +#endif +#if RH_ACT_C + case 0xC: // Do something + return; +#endif +#if RH_ACT_D + case 0xD: // Do something + return; +#endif +#if RH_ACT_E + case 0xE: // Do something + return; +#endif +#if RH_ACT_F + case 0xF: // Do something + return; +#endif + default: + return; + } +} + +//*** ActGetDataPointer() +static P_ACT_DATA +ActGetDataPointer( + uint32_t act +) +{ + +#define RETURN_ACT_POINTER(N) if(0x##N == act) return &ACT_##N; + + FOR_EACH_ACT(RETURN_ACT_POINTER) + + return (P_ACT_DATA)NULL; +} + +//*** _plat__ACT_GetImplemented() +// This function tests to see if an ACT is implemented. It is a belt and suspenders +// function because the TPM should not be calling to manipulate an ACT that is not +// implemented. However, this could help the simulator code which doesn't necessarily +// know if an ACT is implemented or not. +LIB_EXPORT int +_plat__ACT_GetImplemented( + uint32_t act +) +{ + return (ActGetDataPointer(act) != NULL); +} + +//*** _plat__ACT_GetRemaining() +// This function returns the remaining time. If an update is pending, 'newValue' is +// returned. Otherwise, the current counter value is returned. Note that since the +// timers keep running, the returned value can get stale immediately. The actual count +// value will be no greater than the returned value. +LIB_EXPORT uint32_t +_plat__ACT_GetRemaining( + uint32_t act //IN: the ACT selector +) +{ + P_ACT_DATA actData = ActGetDataPointer(act); + uint32_t remain; +// + if(actData == NULL) + return 0; + remain = actData->remaining; + if(actData->pending) + remain = actData->newValue; + return remain; +} + +//*** _plat__ACT_GetSignaled() +LIB_EXPORT int +_plat__ACT_GetSignaled( + uint32_t act //IN: number of ACT to check +) +{ + P_ACT_DATA actData = ActGetDataPointer(act); +// + if(actData == NULL) + return 0; + return (int )actData->signaled; +} + +//*** _plat__ACT_SetSignaled() +LIB_EXPORT void +_plat__ACT_SetSignaled( + uint32_t act, + int on +) +{ + ActSignal(ActGetDataPointer(act), on); +} + +//*** _plat__ACT_GetPending() +LIB_EXPORT int +_plat__ACT_GetPending( + uint32_t act //IN: number of ACT to check +) +{ + P_ACT_DATA actData = ActGetDataPointer(act); +// + if(actData == NULL) + return 0; + return (int )actData->pending; +} + + +//*** _plat__ACT_UpdateCounter() +// This function is used to write the newValue for the counter. If an update is +// pending, then no update occurs and the function returns FALSE. If 'setSignaled' +// is TRUE, then the ACT signaled state is SET and if 'newValue' is 0, nothing +// is posted. +LIB_EXPORT int +_plat__ACT_UpdateCounter( + uint32_t act, // IN: ACT to update + uint32_t newValue // IN: the value to post +) +{ + P_ACT_DATA actData = ActGetDataPointer(act); + // + if(actData == NULL) + // actData doesn't exist but pretend update is pending rather than indicate + // that a retry is necessary. + return TRUE; + // if an update is pending then return FALSE so that there will be a retry + if(actData->pending != 0) + return FALSE; + actData->newValue = newValue; + actData->pending = TRUE; + + return TRUE; +} + +//***_plat__ACT_EnableTicks() +// This enables and disables the processing of the once-per-second ticks. This should +// be turned off ('enable' = FALSE) by _TPM_Init and turned on ('enable' = TRUE) by +// TPM2_Startup() after all the initializations have completed. +LIB_EXPORT void +_plat__ACT_EnableTicks( + int enable +) +{ + actTicksAllowed = enable; +} + +//*** ActDecrement() +// If 'newValue' is non-zero it is copied to 'remaining' and then 'newValue' is +// set to zero. Then 'remaining' is decremented by one if it is not already zero. If +// the value is decremented to zero, then the associated event is signaled. If setting +// 'remaining' causes it to be greater than 1, then the signal associated with the ACT +// is turned off. +static void +ActDecrement( + P_ACT_DATA actData +) +{ + // Check to see if there is an update pending + if(actData->pending) + { + // If this update will cause the count to go from non-zero to zero, set + // the newValue to 1 so that it will timeout when decremented below. + if((actData->newValue == 0) && (actData->remaining != 0)) + actData->newValue = 1; + actData->remaining = actData->newValue; + + // Update processed + actData->pending = 0; + } + // no update so countdown if the count is non-zero but not max + if((actData->remaining != 0) && (actData->remaining != UINT32_MAX)) + { + // If this countdown causes the count to go to zero, then turn the signal for + // the ACT on. + if((actData->remaining -= 1) == 0) + ActSignal(actData, TRUE); + } + // If the current value of the counter is non-zero, then the signal should be + // off. + if(actData->signaled && (actData->remaining > 0)) + ActSignal(actData, FALSE); +} + +//*** _plat__ACT_Tick() +// This processes the once-per-second clock tick from the hardware. This is set up +// for the simulator to use the control interface to send ticks to the TPM. These +// ticks do not have to be on a per second basis. They can be as slow or as fast as +// desired so that the simulation can be tested. +LIB_EXPORT void +_plat__ACT_Tick( + void +) +{ + // Ticks processing is turned off at certain times just to make sure that nothing + // strange is happening before pointers and things are + if(actTicksAllowed) + { + // Handle the update for each counter. +#define DECREMENT_COUNT(N) ActDecrement(&ACT_##N); + + FOR_EACH_ACT(DECREMENT_COUNT) + } +} + +//*** ActZero() +// This function initializes a single ACT +static void +ActZero( + uint32_t act, + P_ACT_DATA actData +) +{ + actData->remaining = 0; + actData->newValue = 0; + actData->pending = 0; + actData->number = (uint8_t)act; + ActSignal(actData, FALSE); +} + +//***_plat__ACT_Initialize() +// This function initializes the ACT hardware and data structures +LIB_EXPORT int +_plat__ACT_Initialize( + void +) +{ + actTicksAllowed = 0; +#define ZERO_ACT(N) ActZero(0x##N, &ACT_##N); + FOR_EACH_ACT(ZERO_ACT) + + return TRUE; +} diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/PlatformData.c b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/PlatformData.c new file mode 100644 index 0000000..5fcc9db --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/PlatformData.c @@ -0,0 +1,82 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Description +// This file will instance the TPM variables that are not stack allocated. The +// descriptions for these variables are in Global.h for this project. + +//** Includes +#include "TpmProfile.h" +#include "PlatformData.h" + +// From Cancel.c +BOOL s_isCanceled; + +// From Clock.c +unsigned int s_adjustRate; +BOOL s_timerReset; +BOOL s_timerStopped; + +#ifndef HARDWARE_CLOCK +clock64_t s_realTimePrevious; +clock64_t s_tpmTime; + +clock64_t s_lastSystemTime; +clock64_t s_lastReportedTime; + + +#endif + + +// From LocalityPlat.c +unsigned char s_locality; + +// From Power.c +BOOL s_powerLost; + +// From Entropy.c +// This values is used to determine if the entropy generator is broken. If two +// consecutive values are the same, then the entropy generator is considered to be +// broken. +uint32_t lastEntropy; + + +// For NVMem.c +unsigned char s_NV[NV_MEMORY_SIZE]; +BOOL s_NvIsAvailable; +BOOL s_NV_unrecoverable; +BOOL s_NV_recoverable; + +// From PPPlat.c +BOOL s_physicalPresence; \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/PowerPlat.c b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/PowerPlat.c new file mode 100644 index 0000000..c562d44 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/PowerPlat.c @@ -0,0 +1,113 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Includes and Function Prototypes + +#include "PlatformData.h" +#include "Platform_fp.h" +#include "_TPM_Init_fp.h" + +//** Functions + +//***_plat__Signal_PowerOn() +// Signal platform power on +LIB_EXPORT int +_plat__Signal_PowerOn( + void + ) +{ + // Reset the timer + _plat__TimerReset(); + + // Need to indicate that we lost power + s_powerLost = TRUE; + + return 0; +} + +//*** _plat__WasPowerLost() +// Test whether power was lost before a _TPM_Init. +// +// This function will clear the "hardware" indication of power loss before return. +// This means that there can only be one spot in the TPM code where this value +// gets read. This method is used here as it is the most difficult to manage in the +// TPM code and, if the hardware actually works this way, it is hard to make it +// look like anything else. So, the burden is placed on the TPM code rather than the +// platform code +// return type: int +// TRUE(1) power was lost +// FALSE(0) power was not lost +LIB_EXPORT int +_plat__WasPowerLost( + void + ) +{ + BOOL retVal = s_powerLost; + s_powerLost = FALSE; + return retVal; +} + +//*** _plat_Signal_Reset() +// This a TPM reset without a power loss. +LIB_EXPORT int +_plat__Signal_Reset( + void + ) +{ + // Initialize locality + s_locality = 0; + + // Command cancel + s_isCanceled = FALSE; + + _TPM_Init(); + + // if we are doing reset but did not have a power failure, then we should + // not need to reload NV ... + + return 0; +} + +//***_plat__Signal_PowerOff() +// Signal platform power off +LIB_EXPORT void +_plat__Signal_PowerOff( + void + ) +{ + // Prepare NV memory for power off + _plat__NVDisable(); + + return; +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/RunCommand.c b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/RunCommand.c new file mode 100644 index 0000000..3fdd51f --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/RunCommand.c @@ -0,0 +1,90 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//**Introduction +// This module provides the platform specific entry and fail processing. The +// _plat__RunCommand() function is used to call to ExecuteCommand() in the TPM code. +// This function does whatever processing is necessary to set up the platform +// in anticipation of the call to the TPM including settup for error processing. +// +// The _plat__Fail() function is called when there is a failure in the TPM. The TPM +// code will have set the flag to indicate that the TPM is in failure mode. +// This call will then recursively call ExecuteCommand in order to build the +// failure mode response. When ExecuteCommand() returns to _plat__Fail(), the +// platform will do some platform specif operation to return to the environment in +// which the TPM is executing. For a simulator, setjmp/longjmp is used. For an OS, +// a system exit to the OS would be appropriate. + +//** Includes and locals +#include "PlatformData.h" +#include "Platform_fp.h" +#include +#include "ExecCommand_fp.h" + +#include +#include + +jmp_buf s_jumpBuffer; + +//** Functions + +//***_plat__RunCommand() +// This version of RunCommand will set up a jum_buf and call ExecuteCommand(). If +// the command executes without failing, it will return and RunCommand will return. +// If there is a failure in the command, then _plat__Fail() is called and it will +// longjump back to RunCommand which will call ExecuteCommand again. However, this +// time, the TPM will be in failure mode so ExecuteCommand will simply build +// a failure response and return. +LIB_EXPORT void +_plat__RunCommand( + uint32_t requestSize, // IN: command buffer size + unsigned char *request, // IN: command buffer + uint32_t *responseSize, // IN/OUT: response buffer size + unsigned char **response // IN/OUT: response buffer + ) +{ + setjmp(s_jumpBuffer); + ExecuteCommand(requestSize, request, responseSize, response); +} + + +//***_plat__Fail() +// This is the platform depended failure exit for the TPM. +LIB_EXPORT NORETURN void +_plat__Fail( + void + ) +{ + TEE_Panic(TEE_ERROR_BAD_STATE); +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/Unique.c b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/Unique.c new file mode 100644 index 0000000..4702670 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/Unique.c @@ -0,0 +1,102 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// In some implementations of the TPM, the hardware can provide a secret +// value to the TPM. This secret value is statistically unique to the +// instance of the TPM. Typical uses of this value are to provide +// personalization to the random number generation and as a shared secret +// between the TPM and the manufacturer. + +//** Includes +#include "PlatformData.h" +#include "Platform_fp.h" + +#include +#include + +//static TEE_UUID deviceUniqueValue = { 0 }; +static char *deviceUniqueValue[sizeof(TEE_UUID)+1]; +static bool initializedUniqueValue = false; + +//** _plat__GetUnique() +// This function is used to access the platform-specific unique value. +// This function places the unique value in the provided buffer ('b') +// and returns the number of bytes transferred. The function will not +// copy more data than 'bSize'. +// NOTE: If a platform unique value has unequal distribution of uniqueness +// and 'bSize' is smaller than the size of the unique value, the 'bSize' +// portion with the most uniqueness should be returned. +LIB_EXPORT uint32_t +_plat__GetUnique( + uint32_t which, // authorities (0) or details + uint32_t bSize, // size of the buffer + unsigned char *b // output buffer + ) +{ + const char *from = (char *)&deviceUniqueValue; + uint32_t uSize = sizeof(TEE_UUID) + 1; + uint32_t retVal = 0; + TEE_Result teeResult; + + // Check if we've initialized our unique platform value. + if (!initializedUniqueValue) { + teeResult = TEE_GetPropertyAsUUID(TEE_PROPSET_TEE_IMPLEMENTATION, + "gpd.tee.deviceID", + (TEE_UUID*)&deviceUniqueValue); + assert(teeResult == TEE_SUCCESS); + } + deviceUniqueValue[uSize-1] = '\0'; + + if(which == 0) // the authorities value + { + for(retVal = 0; + *from != 0 && retVal < bSize; + retVal++) + { + *b++ = *from++; + } + } + else + { + b = &b[((bSize < uSize) ? bSize : uSize) - 1]; + for(retVal = 0; + *from != 0 && retVal < bSize; + retVal++) + { + *b-- = *from++; + } + } + return retVal; +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/fTPM_event_log.c b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/fTPM_event_log.c new file mode 100644 index 0000000..27f52b4 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/fTPM_event_log.c @@ -0,0 +1,391 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Global variables. + */ +static bool log_extended = false; +static id_event_struct_header_t *event_header_ptr; + +static int check_header_digest(const unsigned char *const digest) +{ + /* + * Checks the header digest according to section 5.3 of + * TCG EFI Protocol Specification. Family 2.0. Level 00 Revision 00.13 + * March 30, 2016. + */ + + unsigned int i; + + for (i = 0U; i < HEADER_DIGEST_SIZE; i++) { + if (digest[i] != 0) { + return 0; + } + } + + return 1; +} + +/* + * Function to process a TPM event log header. + * + * @buf_index Offset where the header is expected to start in the event log. + * @buf Pointer to a buffer where the TPM event log is. + * @log_size Size of the TPM event log. + * + * The function returns the offset on the event log after the header. + */ +static unsigned int process_header(unsigned int buf_index, + const unsigned char *const buf, + const size_t log_size) +{ + uint32_t event_size; + uint32_t digest_size; + uint8_t vendor_info_size; + + if (buf_index + sizeof(tcg_pcr_event_t) + sizeof(id_event_struct_header_t) + >= log_size) { +#ifdef fTPMDebug + EMSG("TPM Event log header extends beyond the scope of the event log buffer\n"); +#endif + } + + /* + * Check PcrIndex. + */ + if (*((uint32_t *)(buf + buf_index)) != 0U) { + /* + * 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 + */ + return 0U; + } + buf_index += sizeof(uint32_t); + + /* + * Check EventType + */ + if (*((uint32_t *)(buf + buf_index)) != EV_NO_ACTION) { + /* + * 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 + */ + return 0U; + } + buf_index += sizeof(uint32_t); + + if (!check_header_digest(buf + buf_index)) { + return 0U; + } + + buf_index += HEADER_DIGEST_SIZE; + + memcpy(&event_size, buf + buf_index, sizeof(event_size)); + buf_index += sizeof(event_size); + + event_header_ptr = (id_event_struct_header_t *)(buf + buf_index); + + buf_index += sizeof(id_event_struct_header_t); + + digest_size = (event_header_ptr->number_of_algorithms * + sizeof(id_event_algorithm_size_t)); + + if (buf_index + digest_size >= log_size) { +#ifdef fTPMDebug + EMSG("TPM Event log header extends beyond the scope of the event log buffer\n"); +#endif + event_header_ptr = NULL; + return 0U; + } + + buf_index += digest_size; + + if (buf_index + sizeof(vendor_info_size) >= log_size) { +#ifdef fTPMDebug + EMSG("TPM Event log header extends beyond the scope of the event log buffer\n"); +#endif + event_header_ptr = NULL; + return 0U; + } + + memcpy(&vendor_info_size, buf + buf_index, sizeof(vendor_info_size)); + + if (digest_size + vendor_info_size + sizeof(vendor_info_size) + + sizeof(id_event_struct_header_t) != event_size) { +#ifdef fTPMDebug + EMSG("The parsed event size does not match the event size on the header\n"); +#endif + return 0U; + } + + buf_index += sizeof(vendor_info_size); + + if (buf_index + vendor_info_size > log_size) { +#ifdef fTPMDebug + EMSG("Event size larger than the log size\n"); +#endif + event_header_ptr = NULL; + return 0U; + } + + /* + * Skips the vendor info. + */ + buf_index += vendor_info_size; + + return buf_index; +} + +/* + * Function to proccess (and extend) an event from the TPM event log. + * + * @buf_index Offset where the event is expected to start in the event log. + * @buf Pointer to a buffer where the TPM event log is. + * @log_size Size of the TPM event log. + * + * The function returns the offset of the next event in the TPM event log + * or 0 if fails. + */ +static unsigned int process_event(unsigned int buf_index, + const unsigned char *const buf, + const size_t log_size) +{ + TPM2_PCR_EXTEND_COMMAND cmd; + unsigned char *digest_array; + uint32_t count; + uint32_t event_size; + uint16_t alg_id; + unsigned int digest_size; + unsigned int i; + unsigned char *response; + uint32_t resplen; + event2_header_t event; + void *cmd_end = (void *)(&cmd + 1); + + if (buf_index + sizeof(event2_header_t) >= log_size) { +#ifdef fTPMDebug + EMSG("Event header size larger than the log size\n"); +#endif + return 0U; + } + + memcpy(&event, buf + buf_index, sizeof(event2_header_t)); + buf_index += sizeof(event2_header_t); + + if (event.digests.count > HASH_COUNT) { +#ifdef fTPMDebug + EMSG("Number of digests on this event exceeds the maximum allowed\n"); +#endif + return 0U; + } + + memset(&cmd, 0, sizeof(TPM2_PCR_EXTEND_COMMAND)); + + cmd.Header.paramSize = sizeof(cmd.PcrHandle) + + sizeof(cmd.AuthorizationSize) + + sizeof(cmd.Header); + + cmd.PcrHandle = SwapBytes32(event.pcr_index); + + cmd.Header.commandCode = SwapBytes32(TPM_PCR_EXTEND); + cmd.Header.tag = SwapBytes16(TPM_ST_SESS); + + /* + * We are not using authorization sessions in this prototype code so + * populate the auth session info based on how it is handled in + * CopyAuthSessionCommand() with a NULL auth session. See + * SecurityPkg/Library/Tpm2CommandLib/Tpm2Help.c in EDK2. + */ + cmd.AuthSessionPcr.sessionHandle = SwapBytes32(TPM_RS_PW); + cmd.AuthSessionPcr.nonce.b.size = 0U; + *((uint8_t *)&cmd.AuthSessionPcr.sessionAttributes) = 0U; + cmd.AuthSessionPcr.hmac.b.size = 0U; + cmd.AuthorizationSize = SwapBytes32(AUTH_SIZE); + cmd.Header.paramSize += (AUTH_SIZE); + + /* + * As we are not using authorization sessions for this prototype, + * AuthSessionPcr is empty and therefore the digests are allocated + * straight after the empty AuthSessionPcr structure, so make the + * pointer for the digests to point right after the empty + * AuthSessionPcr structure. + */ + digest_array = ((uint8_t *)&cmd.AuthSessionPcr) + AUTH_SIZE; + + /* + * Populate the digest. + */ + count = SwapBytes32(event.digests.count); + memcpy(digest_array, &count, sizeof(count)); + digest_array += sizeof(count); + + cmd.Header.paramSize += sizeof(count); + + for (i = 0U; i < event.digests.count; i++) { + unsigned int j; + + if (buf_index + sizeof(alg_id) >= log_size) { + return 0U; + } + memcpy(&alg_id, buf + buf_index, sizeof(alg_id)); + alg_id = SwapBytes16(alg_id); + buf_index += sizeof(alg_id); + /* + * Algorithm ID. + */ + if ((void *)(digest_array + sizeof(alg_id)) >= cmd_end) { +#ifdef fTPMDebug + EMSG("Not enough space for digest %u of %u\n", i, + event.digests.count); +#endif + return 0U; + } + memcpy(digest_array, &alg_id, sizeof(alg_id)); + digest_array += sizeof(alg_id); + cmd.Header.paramSize += sizeof(alg_id); + + for (j = 0U; j < event_header_ptr->number_of_algorithms; j++) { + if (SwapBytes16(alg_id) == + event_header_ptr->digest_size[i].algorithm_id) { + digest_size = event_header_ptr->digest_size[i].digest_size; + break; + } + } + + if (j > event_header_ptr->number_of_algorithms) { +#ifdef fTPMDebug + EMSG("Algorithm ID %i not found\n", alg_id); +#endif + return 0U; + } + + cmd.Header.paramSize += digest_size; + + if (buf_index + digest_size >= log_size || + digest_size > (sizeof(TPMT_HA) - sizeof(TPMI_ALG_HASH))) { + /* + * Sanity check: If the log extends beyond the + * maximum size of the log buffer or if the digest is + * bigger than the allocated space on the command structure, abort. + */ +#ifdef fTPMDebug + EMSG("Log extends beyond the maximum size of the log buffer.\n"); + EMSG("alg_id = %i\n", alg_id); + EMSG("log_size = %i\n", log_size); + EMSG("buf_index = %i, digest_size = %i\n", buf_index, digest_size); + EMSG("TPMH_HA = %i\n", sizeof(TPMT_HA)); + EMSG("TPMI_ALG_HASH = %i\n", sizeof(TPMI_ALG_HASH)); +#endif + return 0U; + } + memcpy(digest_array, buf + buf_index, digest_size); + digest_array += digest_size; + buf_index += digest_size; + } + + cmd.Header.paramSize = SwapBytes32(cmd.Header.paramSize); + + if (buf_index + sizeof(event2_data_t) > log_size) { + return 0U; + } + memcpy(&event_size, buf + buf_index, sizeof(event_size)); + buf_index += sizeof(event_size); + buf_index += event_size; + + if (buf_index > log_size) { +#ifdef fTPMDebug + EMSG("The event log extends beyond the log buffer:"); + EMSG("\tbuf_index = %i, log_size = %i\n", buf_index, log_size); +#endif + return 0U; + } + + resplen = 1024; + response = (unsigned char *)malloc(resplen); + + if (response == NULL) { +#ifdef fTPMDebug + EMSG("Not enough memory to allocate a response\n"); +#endif + return 0U; + } + + memset(response, 0, resplen); + + ExecuteCommand(SwapBytes32(cmd.Header.paramSize), &cmd, + &resplen, &response); + +#ifdef fTPMDebug + uint16_t ret_tag; + uint32_t resp_size; + uint32_t tpm_rc; + + memcpy(&ret_tag, response, sizeof(ret_tag)); + memcpy(&resp_size, response + sizeof(ret_tag), sizeof(resp_size)); + memcpy(&tpm_rc, response + sizeof(ret_tag) + sizeof(resp_size), + sizeof(tpm_rc)); + + MSG("TPM2_PCR_EXTEND_COMMAND returned value:\n"); + MSG("\tret_tag = 0x%.4x, size = 0x%.8x, rc = 0x%.8x\n", + SwapBytes16(ret_tag), SwapBytes32(resp_size), SwapBytes32(tpm_rc)); +#endif + + free(response); + + return buf_index; +} + +bool process_eventlog(const unsigned char *const buf, const size_t log_size) +{ + unsigned int buf_index = 0U; + unsigned int event_count = 0U; + + if (log_extended == true) { +#ifdef fTPMDebug + MSG("The event log has already been extended. Ignoring\n"); +#endif + return false; + } + + log_extended = true; + buf_index = process_header(buf_index, buf, log_size); + if (buf_index == 0) { +#ifdef fTPMDebug + EMSG("Fail to process TPM event log header. Skiping.\n"); +#endif + return false; + } + + while (buf_index < log_size) { + /* + * Process the rest of the Event Log. + */ + buf_index = process_event(buf_index, buf, log_size); + event_count++; + } + +#ifdef fTPMDebug + MSG("%i Event logs processed\n", event_count); +#endif + + event_header_ptr = NULL; + + return true; +} diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/fTPM_helpers.c b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/fTPM_helpers.c new file mode 100644 index 0000000..9836861 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/fTPM_helpers.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +// +// Helper functions for byte ordering of TPM commands/responses +// +uint16_t SwapBytes16(uint16_t Value) +{ + return (uint16_t)((Value << 8) | (Value >> 8)); +} + +uint32_t SwapBytes32(uint32_t Value) +{ + uint32_t LowerBytes; + uint32_t HigherBytes; + + LowerBytes = (uint32_t)SwapBytes16((uint16_t)Value); + HigherBytes = (uint32_t)SwapBytes16((uint16_t)(Value >> 16)); + + return (LowerBytes << 16 | HigherBytes); +} diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/include/Admin.h b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/include/Admin.h new file mode 100644 index 0000000..84efcaf --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/include/Admin.h @@ -0,0 +1,230 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//**Introduction +/* + This file contains the admin interfaces. +*/ + +#ifndef _ADMIN_H +#define _ADMIN_H + +//**Includes +#include +#include +#include "swap.h" +#include "TpmProfile.h" +#include "TpmSal.h" +#include "TpmError.h" + +// Parameter reference and types from ref impl headers +#ifndef UNREFERENCED_PARAMETER +#define UNREFERENCED_PARAMETER(a) do { (void)(a); } while (0) +#endif + +#define FAIL(errorCode) (TpmFail(__FUNCTION__, __LINE__, errorCode)) + +#if defined(EMPTY_ASSERT) +#define pAssert(a) ((void)0) +#else +#define pAssert(a) \ + do { \ + if (!(a)) { \ + EMSG("## ASSERT:" #a "##\n"); \ + FAIL(FATAL_ERROR_PARAMETER); \ + } \ + } while (0) +#endif + +#if defined(__GNUC__) +typedef unsigned char UCHAR; +typedef unsigned char * PUCHAR; +typedef void VOID; +typedef void * PVOID; +#endif + +// Admin space tacked on to NV, padded out to NV_BLOCK_SIZE alignment. +#define NV_TPM_STATE_SIZE 0x200 + +// Actual size of Admin space used. (See note in NVMem.c) +#define TPM_STATE_SIZE 0x10 + +// Select TPM types/defines for AdminPPI.c +typedef UINT16 TPM_ST; +#define TPM_ST_NO_SESSIONS (TPM_ST)(0x8001) + +typedef UINT32 TPM_RC; +#define TPM_RC_SUCCESS (TPM_RC)(0x000) +#define RC_VER1 (TPM_RC)(0x100) +#define TPM_RC_BAD_TAG (TPM_RC)(0x01E) +#define TPM_RC_FAILURE (TPM_RC)(RC_VER1+0x001) +#define TPM_RC_COMMAND_SIZE (TPM_RC)(RC_VER1+0x042) + +// Chip flags +typedef union { + UINT32 flags; + struct { + UINT32 Remanufacture : 1; // Ignored on OpTEE platforms + UINT32 TpmStatePresent : 1; // Set when sate present (startup STATE) + UINT32 Reserved : 30; + } fields; +} TPM_CHIP_STATE; + +// +// The current NV Chip state +// +extern TPM_CHIP_STATE g_chipFlags; + +// +// Simulated Physical Presence Interface (PPI) +// +#define FTPM_PPI_CMD_QUERY 0 +#define FTPM_PPI_CMD_VERSION 1 +#define FTPM_PPI_CMD_SUBMIT_OP_REQ 2 +#define FTPM_PPI_CMD_GET_PENDING_OP 3 +#define FTPM_PPI_CMD_GET_PLATFORM_ACTION 4 +#define FTPM_PPI_CMD_RETURN_OP_RESP 5 +#define FTPM_PPI_CMD_SUBMIT_USER_LANG 6 +#define FTPM_PPI_CMD_SUBMIT_OP_REQ2 7 +#define FTPM_PPI_CMD_GET_USER_CONF 8 + +#define FTPM_PPI_OP_NOP 0 +#define FTPM_PPI_OP_ENABLE 1 +#define FTPM_PPI_OP_DISABLE 2 +#define FTPM_PPI_OP_ACTIVATE 3 +#define FTPM_PPI_OP_DEACTIVATE 4 +#define FTPM_PPI_OP_CLEAR 5 +#define FTPM_PPI_OP_E_A 6 +#define FTPM_PPI_OP_D_D 7 +#define FTPM_PPI_OP_OWNERINSTALL_TRUE 8 +#define FTPM_PPI_OP_OWNERINSTALL_FALSE 9 +#define FTPM_PPI_OP_E_A_OI_TRUE 10 +#define FTPM_PPI_OP_OI_FALSE_D_D 11 +#define FTPM_PPI_OP_FIELD_UPGRADE 12 +#define FTPM_PPI_OP_OPERATOR_AUTH 13 +#define FTPM_PPI_OP_C_E_A 14 +#define FTPM_PPI_OP_SET_NO_PROV_FALSE 15 +#define FTPM_PPI_OP_SET_NO_PROV_TRUE 16 +#define FTPM_PPI_OP_SET_NO_CLEAR_FALSE 17 +#define FTPM_PPI_OP_SET_NO_CLEAR_TRUE 18 +#define FTPM_PPI_OP_SET_NO_MAINT_FALSE 19 +#define FTPM_PPI_OP_SET_NO_MAINT_TRUE 20 +#define FTPM_PPI_OP_E_A_C 21 +#define FTPM_PPI_OP_E_A_C_E_A 22 +#define FTPM_PPI_OP_RESERVED_FIRST 23 +#define FTPM_PPI_OP_RESERVED_LAST 127 +#define FTPM_PPI_OP_VENDOR_FIRST 128 + +#define FTPM_PPI_VERSION 0x00322E31 // "1.2" + +#define FTPM_PPI_OP_NOT_IMPLEMENTED 0xFFFFFFFF // Any Op other than E_A_C_E_A + +#pragma pack(1) +typedef struct { + UINT32 PendingPseudoOp; + UINT32 PseudoOpFromLastBoot; + UINT32 ReturnResponse; +} FTPM_PPI_STATE; +#pragma pack() + +// +// The types of TPM runtime state stored to NV +// +typedef enum { + NV_TPM_STATE_FLAGS = 0, + NV_TPM_STATE_PPI, + NV_TPM_STATE_LAST // A mark of the end of the TPM state +} NV_TPM_STATE; + +//***_admin__NvInitState() +// Initialize the NV admin state +void +_admin__NvInitState(); + +//***_admin__NvReadState() +// Read TPM state data from NV memory to RAM +void +_admin__NvReadState( + NV_TPM_STATE type, // IN: type of state data + void *buffer // OUT: data buffer + ); + +//***_admin__NvWriteState() +// Write TPM state data to NV memory +void +_admin__NvWriteState( + NV_TPM_STATE type, // IN: type of state data + void *buffer // IN: data buffer + ); + +// +// Save and restore runtime state +// + + +//***_admin__SaveChipFlags() +// Save the g_chipFlags runtime state +void +_admin__SaveChipFlags(); + +//***_admin__RestoreChipFlags() +// Restore the g_chipFlags runtime state +void +_admin__RestoreChipFlags(); + +//***_admin__SavePPIState() +// Save the s_PPIState runtime state +void +_admin__SavePPIState(); + +//***_admin__RestorePPIState() +// Restore the s_PPIState runtime state +void +_admin__RestorePPIState(); + +//***_admin__PPICommand() +// Returns 1 when PPI command has been consumed +// Returns 0 when it is not a properly formated PPI command, +// caller should pass through to TPM +// +int +_admin__PPICommand( + UINT32 CommandSize, + __in_ecount(CommandSize) UINT8 *CommandBuffer, + UINT32 *ResponseSize, + __deref_out_ecount(*ResponseSize) UINT8 **ResponseBuffer +); + +#endif diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/include/Platform.h b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/include/Platform.h new file mode 100644 index 0000000..b95a193 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/include/Platform.h @@ -0,0 +1,52 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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_H_ +#define _PLATFORM_H_ + +#include "TpmBuildSwitches.h" +#include "BaseTypes.h" +#include "TPMB.h" +#include "MinMax.h" + +#include "TpmProfile.h" + +#include "PlatformACT.h" +#include "PlatformClock.h" +#include "PlatformData.h" +#include "Platform_fp.h" + + +#endif // _PLATFORM_H_ diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/include/PlatformData.h b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/include/PlatformData.h new file mode 100644 index 0000000..f05493b --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/include/PlatformData.h @@ -0,0 +1,137 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 contains the instance data for the Platform module. It is collected +// in this file so that the state of the module is easier to manage. + +#ifndef _PLATFORM_DATA_H_ +#define _PLATFORM_DATA_H_ + + +#include "TpmProfile.h" + +// From Cancel.c +// Cancel flag. It is initialized as FALSE, which indicate the command is not +// being canceled +extern int s_isCanceled; + +#ifndef HARDWARE_CLOCK +typedef uint64_t clock64_t; +// This is the value returned the last time that the system clock was read. This +// is only relevant for a simulator or virtual TPM. +extern clock64_t s_realTimePrevious; + +// These values are used to try to synthesize a long lived version of clock(). +extern clock64_t s_lastSystemTime; +extern clock64_t s_lastReportedTime; + +// This is the rate adjusted value that is the equivalent of what would be read from +// a hardware register that produced rate adjusted time. +extern clock64_t s_tpmTime; +#endif // HARDWARE_CLOCK + +// This value indicates that the timer was reset +extern BOOL s_timerReset; +// This value indicates that the timer was stopped. It causes a clock discontinuity. +extern BOOL s_timerStopped; + +// CLOCK_NOMINAL is the number of hardware ticks per mS. A value of 300000 means +// that the nominal clock rate used to drive the hardware clock is 30 MHz. The +// adjustment rates are used to determine the conversion of the hardware ticks to +// internal hardware clock value. In practice, we would expect that there woudl be +// a hardware register will accumulated mS. It would be incremented by the output +// of a pre-scaler. The pre-scaler would divide the ticks from the clock by some +// value that would compensate for the difference between clock time and real time. +// The code in Clock does the emulation of this function. +#define CLOCK_NOMINAL 30000 +// A 1% change in rate is 300 counts +#define CLOCK_ADJUST_COARSE 300 +// A 0.1% change in rate is 30 counts +#define CLOCK_ADJUST_MEDIUM 30 +// A minimum change in rate is 1 count +#define CLOCK_ADJUST_FINE 1 +// The clock tolerance is +/-15% (4500 counts) +// Allow some guard band (16.7%) +#define CLOCK_ADJUST_LIMIT 5000 + +// This variable records the time when _plat__TimerReset is called. This mechanism +// allow us to subtract the time when TPM is power off from the total +// time reported by clock() function +extern uint64_t s_initClock; + +// This variable records the timer adjustment factor. +extern unsigned int s_adjustRate; + +// For LocalityPlat.c +// Locality of current command +extern unsigned char s_locality; + +// For NVMem.c +// Choose if the NV memory should be backed by RAM or by file. +// If this macro is defined, then a file is used as NV. If it is not defined, +// then RAM is used to back NV memory. Comment out to use RAM. + +#if (!defined VTPM) || ((VTPM != NO) && (VTPM != YES)) +# undef VTPM +# define VTPM YES // Default: Either YES or NO +#endif + +// For a simulation, use a file to back up the NV +#if (!defined FILE_BACKED_NV) || ((FILE_BACKED_NV != NO) && (FILE_BACKED_NV != YES)) +# undef FILE_BACKED_NV +# define FILE_BACKED_NV (VTPM && YES) // Default: Either YES or NO +#endif + +#if !SIMULATION +# undef FILE_BACKED_NV +# define FILE_BACKED_NV NO +#endif // SIMULATION + +extern unsigned char s_NV[NV_MEMORY_SIZE]; +extern BOOL s_NvIsAvailable; +extern BOOL s_NV_unrecoverable; +extern BOOL s_NV_recoverable; + + +// For PPPlat.c +// Physical presence. It is initialized to FALSE +extern BOOL s_physicalPresence; + +// From Power +extern BOOL s_powerLost; + +// For Entropy.c +extern uint32_t lastEntropy; + +#endif // _PLATFORM_DATA_H_ diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/include/Platform_fp.h b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/include/Platform_fp.h new file mode 100644 index 0000000..12bec53 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/platform/include/Platform_fp.h @@ -0,0 +1,529 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * Copyright (c) 2023-2024, NVIDIA Corporation & AFFILIATES. All rights reserved. + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Aug 7, 2018 Time: 03:39:35PM + */ + +#ifndef _PLATFORM_FP_H_ +#define _PLATFORM_FP_H_ + +//** From EPS.c + +LIB_EXPORT void +_plat__GetEPS(UINT16 Size, uint8_t *EndorsementSeed); + +//** From Cancel.c + +//***_plat__IsCanceled() +// Check if the cancel flag is set +// return type: BOOL +// TRUE(1) if cancel flag is set +// FALSE(0) if cancel flag is not set +LIB_EXPORT int +_plat__IsCanceled( + void + ); + +// Set cancel flag. +LIB_EXPORT void +_plat__SetCancel( + void + ); + +//***_plat__ClearCancel() +// Clear cancel flag +LIB_EXPORT void +_plat__ClearCancel( + void + ); + + +//** From Clock.c + +//***_plat__TimerReset() +// This function sets current system clock time as t0 for counting TPM time. +// This function is called at a power on event to reset the clock. When the clock +// is reset, the indication that the clock was stopped is also set. +LIB_EXPORT void +_plat__TimerReset( + void + ); + +//*** _plat__TimerRestart() +// This function should be called in order to simulate the restart of the timer +// should it be stopped while power is still applied. +LIB_EXPORT void +_plat__TimerRestart( + void + ); + +//*** _plat__RealTime() +// This is another, probably futile, attempt to define a portable function +// that will return a 64-bit clock value that has mSec resolution. +uint64_t +_plat__RealTime( + void +); + +//***_plat__TimerRead() +// This function provides access to the tick timer of the platform. The TPM code +// uses this value to drive the TPM Clock. +// +// The tick timer is supposed to run when power is applied to the device. This timer +// should not be reset by time events including _TPM_Init. It should only be reset +// when TPM power is re-applied. +// +// If the TPM is run in a protected environment, that environment may provide the +// tick time to the TPM as long as the time provided by the environment is not +// allowed to go backwards. If the time provided by the system can go backwards +// during a power discontinuity, then the _plat__Signal_PowerOn should call +// _plat__TimerReset(). +LIB_EXPORT uint64_t +_plat__TimerRead( + void + ); + +//*** _plat__TimerWasReset() +// This function is used to interrogate the flag indicating if the tick timer has +// been reset. +// +// If the resetFlag parameter is SET, then the flag will be CLEAR before the +// function returns. +LIB_EXPORT BOOL +_plat__TimerWasReset( + void + ); + +//*** _plat__TimerWasStopped() +// This function is used to interrogate the flag indicating if the tick timer has +// been stopped. If so, this is typically a reason to roll the nonce. +// +// This function will CLEAR the s_timerStopped flag before returning. This provides +// functionality that is similar to status register that is cleared when read. This +// is the model used here because it is the one that has the most impact on the TPM +// code as the flag can only be accessed by one entity in the TPM. Any other +// implementation of the hardware can be made to look like a read-once register. +LIB_EXPORT BOOL +_plat__TimerWasStopped( + void + ); + +//***_plat__ClockAdjustRate() +// Adjust the clock rate +LIB_EXPORT void +_plat__ClockAdjustRate( + int adjust // IN: the adjust number. It could be positive + // or negative + ); + +//***_plat__SetTimerAvail() +// Set the current system timer to available. +LIB_EXPORT void +_plat__SetTimerAvail( + void + ); + +//***_plat__ClearTimerAvail() +// Set the current system timer to unavailable. +LIB_EXPORT void +_plat__ClearTimerAvail( + void + ); + +//** From Entropy.c + +//** _plat__GetEntropy() +// This function is used to get available hardware entropy. In a hardware +// implementation of this function, there would be no call to the system +// to get entropy. +// return type: int32_t +// < 0 hardware failure of the entropy generator, this is sticky +// >= 0 the returned amount of entropy (bytes) +// +LIB_EXPORT int32_t +_plat__GetEntropy( + unsigned char *entropy, // output buffer + uint32_t amount // amount requested + ); + + +//** From LocalityPlat.c + +//***_plat__LocalityGet() +// Get the most recent command locality in locality value form. +// This is an integer value for locality and not a locality structure +// The locality can be 0-4 or 32-255. 5-31 is not allowed. +LIB_EXPORT unsigned char +_plat__LocalityGet( + void + ); + +//***_plat__LocalitySet() +// Set the most recent command locality in locality value form +LIB_EXPORT void +_plat__LocalitySet( + unsigned char locality + ); + + +//** From NVMem.c + +//*** _plat__NvErrors() +// This function is used by the simulator to set the error flags in the NV +// subsystem to simulate an error in the NV loading process +LIB_EXPORT void +_plat__NvErrors( + int recoverable, + int unrecoverable + ); + +//***_plat__NVEnable() +// Enable NV memory. +// +// This version just pulls in data from a file. In a real TPM, with NV on chip, +// this function would verify the integrity of the saved context. If the NV +// memory was not on chip but was in something like RPMB, the NV state would be +// read in, decrypted and integrity checked. +// +// The recovery from an integrity failure depends on where the error occurred. It +// it was in the state that is discarded by TPM Reset, then the error is +// recoverable if the TPM is reset. Otherwise, the TPM must go into failure mode. +// return type: int +// 0 if success +// > 0 if receive recoverable error +// <0 if unrecoverable error +LIB_EXPORT int +_plat__NVEnable( + void *platParameter // IN: platform specific parameters + ); + +//***_plat__NVDisable() +// Disable NV memory +LIB_EXPORT void +_plat__NVDisable( + void + ); + +//***_plat__IsNvAvailable() +// Check if NV is available +// return type: int +// 0 NV is available +// 1 NV is not available due to write failure +// 2 NV is not available due to rate limit +LIB_EXPORT int +_plat__IsNvAvailable( + void + ); + +//***_plat__NvMemoryRead() +// Function: Read a chunk of NV memory +LIB_EXPORT void +_plat__NvMemoryRead( + unsigned int startOffset, // IN: read start + unsigned int size, // IN: size of bytes to read + void *data // OUT: data buffer + ); + +//*** _plat__NvIsDifferent() +// This function checks to see if the NV is different from the test value. This is +// so that NV will not be written if it has not changed. +// return value: int +// TRUE(1) the NV location is different from the test value +// FALSE(0) the NV location is the same as the test value +LIB_EXPORT int +_plat__NvIsDifferent( + unsigned int startOffset, // IN: read start + unsigned int size, // IN: size of bytes to read + void *data // IN: data buffer + ); + +//***_plat__NvMemoryWrite() +// This function is used to update NV memory. The "write" is to a memory copy of +// NV. At the end of the current command, any changes are written to +// the actual NV memory. +// NOTE: A useful optimization would be for this code to compare the current +// contents of NV with the local copy and note the blocks that have changed. Then +// only write those blocks when _plat__NvCommit() is called. +LIB_EXPORT int +_plat__NvMemoryWrite( + unsigned int startOffset, // IN: write start + unsigned int size, // IN: size of bytes to write + void *data // OUT: data buffer + ); + +//***_plat__NvMemoryClear() +// Function is used to set a range of NV memory bytes to an implementation-dependent +// value. The value represents the erase state of the memory. +LIB_EXPORT void +_plat__NvMemoryClear( + unsigned int start, // IN: clear start + unsigned int size // IN: number of bytes to clear + ); + +//***_plat__NvMemoryMove() +// Function: Move a chunk of NV memory from source to destination +// This function should ensure that if there overlap, the original data is +// copied before it is written +LIB_EXPORT void +_plat__NvMemoryMove( + unsigned int sourceOffset, // IN: source offset + unsigned int destOffset, // IN: destination offset + unsigned int size // IN: size of data being moved + ); + +//***_plat__NvCommit() +// This function writes the local copy of NV to NV for permanent store. It will write +// NV_MEMORY_SIZE bytes to NV. If a file is use, the entire file is written. +// return type: int +// 0 NV write success +// non-0 NV write fail +LIB_EXPORT int +_plat__NvCommit( + void + ); + +//***_plat__SetNvAvail() +// Set the current NV state to available. This function is for testing purpose +// only. It is not part of the platform NV logic +LIB_EXPORT void +_plat__SetNvAvail( + void + ); + +//***_plat__ClearNvAvail() +// Set the current NV state to unavailable. This function is for testing purpose +// only. It is not part of the platform NV logic +LIB_EXPORT void +_plat__ClearNvAvail( + void + ); + + +//** From PowerPlat.c + +//***_plat__Signal_PowerOn() +// Signal platform power on +LIB_EXPORT int +_plat__Signal_PowerOn( + void + ); + +//*** _plat__WasPowerLost() +// Test whether power was lost before a _TPM_Init. +// +// This function will clear the "hardware" indication of power loss before return. +// This means that there can only be one spot in the TPM code where this value +// gets read. This method is used here as it is the most difficult to manage in the +// TPM code and, if the hardware actually works this way, it is hard to make it +// look like anything else. So, the burden is placed on the TPM code rather than the +// platform code +// return type: int +// TRUE(1) power was lost +// FALSE(0) power was not lost +LIB_EXPORT int +_plat__WasPowerLost( + void + ); + +//*** _plat_Signal_Reset() +// This a TPM reset without a power loss. +LIB_EXPORT int +_plat__Signal_Reset( + void + ); + +//***_plat__Signal_PowerOff() +// Signal platform power off +LIB_EXPORT void +_plat__Signal_PowerOff( + void + ); + + +//** From PPPlat.c + +//***_plat__PhysicalPresenceAsserted() +// Check if physical presence is signaled +// return type: int +// TRUE(1) if physical presence is signaled +// FALSE(0) if physical presence is not signaled +LIB_EXPORT int +_plat__PhysicalPresenceAsserted( + void + ); + +//***_plat__Signal_PhysicalPresenceOn() +// Signal physical presence on +LIB_EXPORT void +_plat__Signal_PhysicalPresenceOn( + void + ); + +//***_plat__Signal_PhysicalPresenceOff() +// Signal physical presence off +LIB_EXPORT void +_plat__Signal_PhysicalPresenceOff( + void + ); + + +//*** _plat__ACT_UpdateCounter() +// This function is used to write the newValue for the counter. If an update is +// pending, then no update occurs and the function returns FALSE. If 'setSignaled' +// is TRUE, then the ACT signaled state is SET and if 'newValue' is 0, nothing +// is posted. +LIB_EXPORT int +_plat__ACT_UpdateCounter( + uint32_t act, // IN: ACT to update + uint32_t newValue // IN: the value to post +); + +//*** _plat__ACT_SetSignaled() +LIB_EXPORT void +_plat__ACT_SetSignaled( + uint32_t act, + int on +); + +//***_plat__ACT_Initialize() +// This function initializes the ACT hardware and data structures +LIB_EXPORT int +_plat__ACT_Initialize( + void +); + +//***_plat__ACT_EnableTicks() +// This enables and disables the processing of the once-per-second ticks. This should +// be turned off ('enable' = FALSE) by _TPM_Init and turned on ('enable' = TRUE) by +// TPM2_Startup() after all the initializations have completed. +LIB_EXPORT void +_plat__ACT_EnableTicks( + int enable +); + +//*** _plat__ACT_GetRemaining() +// This function returns the remaining time. If an update is pending, 'newValue' is +// returned. Otherwise, the current counter value is returned. Note that since the +// timers keep running, the returned value can get stale immediately. The actual count +// value will be no greater than the returned value. +LIB_EXPORT uint32_t +_plat__ACT_GetRemaining( + uint32_t act //IN: the ACT selector +); + +//*** _plat__ACT_GetSignaled() +LIB_EXPORT int +_plat__ACT_GetSignaled( + uint32_t act //IN: number of ACT to check +); + +//*** _plat__ACT_GetImplemented() +// This function tests to see if an ACT is implemented. It is a belt and suspenders +// function because the TPM should not be calling to manipulate an ACT that is not +// implemented. However, this could help the simulator code which doesn't necessarily +// know if an ACT is implemented or not. +LIB_EXPORT int +_plat__ACT_GetImplemented( + uint32_t act +); + +//** From RunCommand.c + +//***_plat__RunCommand() +// This version of RunCommand will set up a jum_buf and call ExecuteCommand(). If +// the command executes without failing, it will return and RunCommand will return. +// If there is a failure in the command, then _plat__Fail() is called and it will +// longjump back to RunCommand which will call ExecuteCommand again. However, this +// time, the TPM will be in failure mode so ExecuteCommand will simply build +// a failure response and return. +LIB_EXPORT void +_plat__RunCommand( + uint32_t requestSize, // IN: command buffer size + unsigned char *request, // IN: command buffer + uint32_t *responseSize, // IN/OUT: response buffer size + unsigned char **response // IN/OUT: response buffer + ); + +//***_plat__Fail() +// This is the platform depended failure exit for the TPM. +LIB_EXPORT NORETURN void +_plat__Fail( + void + ); + + +//** From Unique.c + +//** _plat__GetUnique() +// This function is used to access the platform-specific unique value. +// This function places the unique value in the provided buffer ('b') +// and returns the number of bytes transferred. The function will not +// copy more data than 'bSize'. +// NOTE: If a platform unique value has unequal distribution of uniqueness +// and 'bSize' is smaller than the size of the unique value, the 'bSize' +// portion with the most uniqueness should be returned. +LIB_EXPORT uint32_t +_plat__GetUnique( + uint32_t which, // authorities (0) or details + uint32_t bSize, // size of the buffer + unsigned char *b // output buffer + ); + +//** From DebugHelpers.c + +#if CERTIFYX509_DEBUG + +//*** DebugFileInit() +// This function opens the file used to hold the debug data. +// Return Type: int +// 0 success +// != 0 error +int +DebugFileInit( + void +); + +//*** DebugDumpBuffer() +void +DebugDumpBuffer( + int size, + unsigned char *buf, + const char *identifier +); +#endif // CERTIFYX509_DEBUG + +#endif // _PLATFORM_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/reference/RuntimeSupport.c b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/reference/RuntimeSupport.c new file mode 100644 index 0000000..0998f05 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/reference/RuntimeSupport.c @@ -0,0 +1,84 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +/** + * Implementation of tolower() commonly found in ctype.h + * Returns an ASCII character, changing to lowercase if the character is + * in the range 'A'-'Z'. + */ + +int tolower (int c) +{ + if(c >= 'A' && c <= 'Z') + { + c -= ('A' - 'a'); + } + return c; +} + +int toupper (int c) +{ + if(c >= 'a' && c <= 'z') + { + c += ('A' - 'a'); + } + return c; +} + +int strncasecmp(const char *str1, const char *str2, size_t n) +{ + size_t i = 0; + for(i = 0; i < n && str1[i] && str2[i]; i++) + { + char delta = tolower(str1[i]) - tolower(str2[i]); + if (delta != 0) + { + return delta; + } + } + return 0; +} + +#ifdef CUSTOM_RAND_GENERATE_BLOCK +#include +int wolfRand(unsigned char* output, unsigned int sz) +{ + TEE_GenerateRandom((void *)output, (uint32_t)sz); + + return 0; +} +#endif \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/reference/include/RuntimeSupport.h b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/reference/include/RuntimeSupport.h new file mode 100644 index 0000000..0607f1e --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/reference/include/RuntimeSupport.h @@ -0,0 +1,94 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * Copyright (c) 2023-2024, NVIDIA Corporation & AFFILIATES. All rights reserved. + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 _RUNTIMESUPPORT_H_ +#define _RUNTIMESUPPORT_H_ + +// OPTEE provides simple versions of these headers +#include +#include +#include +#include + +typedef uint64_t clock_t; + +#ifndef XMEMCPY +#define XMEMCPY memcpy +#endif + +#ifndef XMEMSET +#define XMEMSET memset +#endif + +#ifndef XSTRLEN +#define XSTRLEN(str) strlen((str)) +#endif + +#ifndef XSTRNCPY +#define XSTRNCPY(str1,str2,n) strncpy((str1),(str2),(n)) +#endif + +#ifndef XSTRNCASECMP +int strncasecmp(const char *str1, const char *str2, size_t n); +#define XSTRNCASECMP(str1,str2,n) strncasecmp((str1),(str2),(n)) +#endif + +#ifndef XSTRNCMP +#define XSTRNCMP(str1,str2,n) strncmp((str1),(str2),(n)) +#endif + +#ifndef XMEMCMP +#define XMEMCMP memcmp +#endif + +#ifndef XTOUPPER +int toupper (int c); +#define XTOUPPER(str1) toupper((str1)) +#endif + +#ifndef XTOLOWER +int tolower (int c); +#define XTOLOWER(str1) tolower((str1)) +#endif + +#undef WC_NO_HASHDRBG +#define WC_NO_HASHDRBG + +/* Bypass P-RNG and use only HW RNG */ +extern int wolfRand(unsigned char* output, unsigned int sz); +#undef CUSTOM_RAND_GENERATE_BLOCK +#define CUSTOM_RAND_GENERATE_BLOCK wolfRand +#endif diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/reference/include/TpmProfile.h b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/reference/include/TpmProfile.h new file mode 100644 index 0000000..fc21a88 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/reference/include/TpmProfile.h @@ -0,0 +1,804 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * Copyright (c) 2023-2024, NVIDIA Corporation & AFFILIATES. All rights reserved. + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 4, 2020 Time: 02:36:43PM + */ + +#ifndef _TPM_PROFILE_H_ +#define _TPM_PROFILE_H_ + +#include "RuntimeSupport.h" + +#include +#include +#include + +#undef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) + +#undef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +// Table 2:4 - Defines for Logic Values +#undef TRUE +#define TRUE 1 +#undef FALSE +#define FALSE 0 +#undef YES +#define YES 1 +#undef NO +#define NO 0 +#undef SET +#define SET 1 +#undef CLEAR +#define CLEAR 0 + +// Table 0:1 - Defines for Processor Values +#ifndef BIG_ENDIAN_TPM +#define BIG_ENDIAN_TPM NO +#endif +#ifndef LITTLE_ENDIAN_TPM +#define LITTLE_ENDIAN_TPM !BIG_ENDIAN_TPM +#endif +#ifndef MOST_SIGNIFICANT_BIT_0 +#define MOST_SIGNIFICANT_BIT_0 NO +#endif +#ifndef LEAST_SIGNIFICANT_BIT_0 +#define LEAST_SIGNIFICANT_BIT_0 !MOST_SIGNIFICANT_BIT_0 +#endif +#ifndef AUTO_ALIGN +#define AUTO_ALIGN NO +#endif + +// Table 0:4 - Defines for Implemented Curves +#ifndef ECC_NIST_P192 +#define ECC_NIST_P192 NO +#endif +#ifndef ECC_NIST_P224 +#define ECC_NIST_P224 NO +#endif +#ifndef ECC_NIST_P256 +#define ECC_NIST_P256 YES +#endif +#ifndef ECC_NIST_P384 +#define ECC_NIST_P384 YES +#endif +#ifndef ECC_NIST_P521 +#define ECC_NIST_P521 YES +#endif +#ifndef ECC_BN_P256 +#define ECC_BN_P256 YES +#endif +#ifndef ECC_BN_P638 +#define ECC_BN_P638 NO +#endif +#ifndef ECC_SM2_P256 +#define ECC_SM2_P256 YES +#endif + +// Table 0:6 - Defines for Implemented ACT +#ifndef RH_ACT_0 +#define RH_ACT_0 YES +#endif +#ifndef RH_ACT_1 +#define RH_ACT_1 NO +#endif +#ifndef RH_ACT_A +#define RH_ACT_A YES +#endif + +typedef UINT32 TPM_CC; + +// Table 0:7 - Defines for Implementation Values +#ifndef FIELD_UPGRADE_IMPLEMENTED +#define FIELD_UPGRADE_IMPLEMENTED NO +#endif +#ifdef USE_MBEDTLS +#define HASH_LIB Mbedtls +#define SYM_LIB Mbedtls +#define MATH_LIB Mbedtls +#elif defined(USE_WOLFCRYPT) +#define HASH_LIB Wolf +#define SYM_LIB Wolf +#define MATH_LIB Wolf +#else +#define HASH_LIB Ossl +#define SYM_LIB Ossl +#define MATH_LIB Ossl +#endif +#ifndef IMPLEMENTATION_PCR +#define IMPLEMENTATION_PCR 24 +#endif +#ifndef PLATFORM_PCR +#define PLATFORM_PCR 24 +#endif +#ifndef DRTM_PCR +#define DRTM_PCR 17 +#endif +#ifndef HCRTM_PCR +#define HCRTM_PCR 0 +#endif +#ifndef NUM_LOCALITIES +#define NUM_LOCALITIES 5 +#endif +#ifndef MAX_HANDLE_NUM +#define MAX_HANDLE_NUM 3 +#endif +#ifndef MAX_ACTIVE_SESSIONS +#define MAX_ACTIVE_SESSIONS 64 +#endif +#ifndef CONTEXT_SLOT +#define CONTEXT_SLOT UINT16 +#endif +#ifndef MAX_LOADED_SESSIONS +#define MAX_LOADED_SESSIONS 3 +#endif +#ifndef MAX_SESSION_NUM +#define MAX_SESSION_NUM 3 +#endif +#ifndef MAX_LOADED_OBJECTS +#define MAX_LOADED_OBJECTS 3 +#endif +#ifndef MIN_EVICT_OBJECTS +#define MIN_EVICT_OBJECTS 2 +#endif +#ifndef NUM_POLICY_PCR_GROUP +#define NUM_POLICY_PCR_GROUP 1 +#endif +#ifndef NUM_AUTHVALUE_PCR_GROUP +#define NUM_AUTHVALUE_PCR_GROUP 1 +#endif +#ifndef MAX_CONTEXT_SIZE +#define MAX_CONTEXT_SIZE 2256 +#endif +#ifndef MAX_DIGEST_BUFFER +#define MAX_DIGEST_BUFFER 1024 +#endif +#ifndef MAX_NV_INDEX_SIZE +#define MAX_NV_INDEX_SIZE 2048 +#endif +#ifndef MAX_NV_BUFFER_SIZE +#define MAX_NV_BUFFER_SIZE 1024 +#endif +#ifndef MAX_CAP_BUFFER +#define MAX_CAP_BUFFER 1024 +#endif +#ifndef NV_MEMORY_SIZE +#define NV_MEMORY_SIZE 16384 +#endif +#ifndef MIN_COUNTER_INDICES +#define MIN_COUNTER_INDICES 8 +#endif +#ifndef NUM_STATIC_PCR +#define NUM_STATIC_PCR 16 +#endif +#ifndef MAX_ALG_LIST_SIZE +#define MAX_ALG_LIST_SIZE 64 +#endif +#ifndef PRIMARY_SEED_SIZE +#define PRIMARY_SEED_SIZE 32 +#endif +#ifndef CONTEXT_ENCRYPT_ALGORITHM +#define CONTEXT_ENCRYPT_ALGORITHM AES +#endif +#ifndef NV_CLOCK_UPDATE_INTERVAL +#define NV_CLOCK_UPDATE_INTERVAL 12 +#endif +#ifndef NUM_POLICY_PCR +#define NUM_POLICY_PCR 1 +#endif +#ifndef MAX_COMMAND_SIZE +#define MAX_COMMAND_SIZE 4096 +#endif +#ifndef MAX_RESPONSE_SIZE +#define MAX_RESPONSE_SIZE 4096 +#endif +#ifndef ORDERLY_BITS +#define ORDERLY_BITS 8 +#endif +#ifndef MAX_SYM_DATA +#define MAX_SYM_DATA 128 +#endif +#ifndef MAX_RNG_ENTROPY_SIZE +#define MAX_RNG_ENTROPY_SIZE 64 +#endif +#ifndef RAM_INDEX_SPACE +#define RAM_INDEX_SPACE 512 +#endif +#ifndef RSA_DEFAULT_PUBLIC_EXPONENT +#define RSA_DEFAULT_PUBLIC_EXPONENT 0x00010001 +#endif +#ifndef ENABLE_PCR_NO_INCREMENT +#define ENABLE_PCR_NO_INCREMENT YES +#endif +#ifndef CRT_FORMAT_RSA +#define CRT_FORMAT_RSA YES +#endif +#ifndef VENDOR_COMMAND_COUNT +#define VENDOR_COMMAND_COUNT 0 +#endif +#ifndef MAX_VENDOR_BUFFER_SIZE +#define MAX_VENDOR_BUFFER_SIZE 1024 +#endif +#ifndef SIZE_OF_X509_SERIAL_NUMBER +#define SIZE_OF_X509_SERIAL_NUMBER 20 +#endif +#ifndef PRIVATE_VENDOR_SPECIFIC_BYTES +#define PRIVATE_VENDOR_SPECIFIC_BYTES RSA_PRIVATE_SIZE +#endif + +// Table 0:2 - Defines for Implemented Algorithms +#ifndef ALG_AES +#define ALG_AES ALG_YES +#endif +#ifndef ALG_CAMELLIA +#define ALG_CAMELLIA ALG_NO +#endif +#ifndef ALG_CBC +#define ALG_CBC ALG_YES +#endif +#ifndef ALG_CFB +#define ALG_CFB ALG_YES +#endif +#ifndef ALG_CMAC +#define ALG_CMAC ALG_YES +#endif +#ifndef ALG_CTR +#define ALG_CTR ALG_YES +#endif +#ifndef ALG_ECB +#define ALG_ECB ALG_YES +#endif +#ifndef ALG_ECC +#define ALG_ECC ALG_YES +#endif +#ifndef ALG_ECDAA +#define ALG_ECDAA (ALG_YES && ALG_ECC) +#endif +#ifndef ALG_ECDH +#define ALG_ECDH (ALG_YES && ALG_ECC) +#endif +#ifndef ALG_ECDSA +#define ALG_ECDSA (ALG_YES && ALG_ECC) +#endif +#ifndef ALG_ECMQV +#define ALG_ECMQV (ALG_NO && ALG_ECC) +#endif +#ifndef ALG_ECSCHNORR +#define ALG_ECSCHNORR (ALG_YES && ALG_ECC) +#endif +#ifndef ALG_HMAC +#define ALG_HMAC ALG_YES +#endif +#ifndef ALG_KDF1_SP800_108 +#define ALG_KDF1_SP800_108 ALG_YES +#endif +#ifndef ALG_KDF1_SP800_56A +#define ALG_KDF1_SP800_56A (ALG_YES && ALG_ECC) +#endif +#ifndef ALG_KDF2 +#define ALG_KDF2 ALG_NO +#endif +#ifndef ALG_KEYEDHASH +#define ALG_KEYEDHASH ALG_YES +#endif +#ifndef ALG_MGF1 +#define ALG_MGF1 ALG_YES +#endif +#ifndef ALG_OAEP +#define ALG_OAEP (ALG_YES && ALG_RSA) +#endif +#ifndef ALG_OFB +#define ALG_OFB ALG_YES +#endif +#ifndef ALG_RSA +#define ALG_RSA ALG_YES +#endif +#ifndef ALG_RSAES +#define ALG_RSAES (ALG_YES && ALG_RSA) +#endif +#ifndef ALG_RSAPSS +#define ALG_RSAPSS (ALG_YES && ALG_RSA) +#endif +#ifndef ALG_RSASSA +#define ALG_RSASSA (ALG_YES && ALG_RSA) +#endif +#ifndef ALG_SHA +#define ALG_SHA ALG_NO /* Not specified by vendor */ +#endif +#ifndef ALG_SHA1 +#define ALG_SHA1 ALG_YES +#endif +#ifndef ALG_SHA256 +#define ALG_SHA256 ALG_YES +#endif +#ifndef ALG_SHA384 +#define ALG_SHA384 ALG_YES +#endif +#ifndef ALG_SHA3_256 +#define ALG_SHA3_256 ALG_NO /* Not specified by vendor */ +#endif +#ifndef ALG_SHA3_384 +#define ALG_SHA3_384 ALG_NO /* Not specified by vendor */ +#endif +#ifndef ALG_SHA3_512 +#define ALG_SHA3_512 ALG_NO /* Not specified by vendor */ +#endif +#ifndef ALG_SHA512 +#define ALG_SHA512 ALG_YES +#endif +#ifndef ALG_SM2 +#define ALG_SM2 (ALG_NO && ALG_ECC) +#endif +#ifndef ALG_SM3_256 +#define ALG_SM3_256 ALG_NO +#endif +#ifndef ALG_SM4 +#define ALG_SM4 ALG_NO +#endif +#ifndef ALG_SYMCIPHER +#define ALG_SYMCIPHER ALG_YES +#endif +#ifndef ALG_TDES +#define ALG_TDES ALG_NO +#endif +#ifndef ALG_XOR +#define ALG_XOR ALG_YES +#endif + +// Table 1:3 - Defines for RSA Asymmetric Cipher Algorithm Constants +#ifndef RSA_1024 +#define RSA_1024 (ALG_RSA && NO) +#endif +#ifndef RSA_2048 +#define RSA_2048 (ALG_RSA && YES) +#endif +#ifndef RSA_3072 +#define RSA_3072 (ALG_RSA && YES) +#endif +#ifndef RSA_4096 +#define RSA_4096 (ALG_RSA && YES) +#endif +#ifndef RSA_16384 +#define RSA_16384 (ALG_RSA && NO) +#endif + +// Table 1:21 - Defines for AES Symmetric Cipher Algorithm Constants +#ifndef AES_128 +#define AES_128 (ALG_AES && YES) +#endif +#ifndef AES_192 +#define AES_192 (ALG_AES && NO) +#endif +#ifndef AES_256 +#define AES_256 (ALG_AES && YES) +#endif + +// Table 1:22 - Defines for SM4 Symmetric Cipher Algorithm Constants +#ifndef SM4_128 +#define SM4_128 (ALG_SM4 && YES) +#endif + +// Table 1:23 - Defines for CAMELLIA Symmetric Cipher Algorithm Constants +#ifndef CAMELLIA_128 +#define CAMELLIA_128 (ALG_CAMELLIA && YES) +#endif +#ifndef CAMELLIA_192 +#define CAMELLIA_192 (ALG_CAMELLIA && NO) +#endif +#ifndef CAMELLIA_256 +#define CAMELLIA_256 (ALG_CAMELLIA && YES) +#endif + +// Table 1:24 - Defines for TDES Symmetric Cipher Algorithm Constants +#ifndef TDES_128 +#define TDES_128 (ALG_TDES && YES) +#endif +#ifndef TDES_192 +#define TDES_192 (ALG_TDES && YES) +#endif + +// Table 0:5 - Defines for Implemented Commands +#ifndef CC_ACT_SetTimeout +#define CC_ACT_SetTimeout CC_YES +#endif +#ifndef CC_AC_GetCapability +#define CC_AC_GetCapability CC_YES +#endif +#ifndef CC_AC_Send +#define CC_AC_Send CC_YES +#endif +#ifndef CC_ActivateCredential +#define CC_ActivateCredential CC_YES +#endif +#ifndef CC_Certify +#define CC_Certify CC_YES +#endif +#ifndef CC_CertifyCreation +#define CC_CertifyCreation CC_YES +#endif +#ifndef CC_CertifyX509 +#define CC_CertifyX509 CC_YES +#endif +#ifndef CC_ChangeEPS +#define CC_ChangeEPS CC_YES +#endif +#ifndef CC_ChangePPS +#define CC_ChangePPS CC_YES +#endif +#ifndef CC_Clear +#define CC_Clear CC_YES +#endif +#ifndef CC_ClearControl +#define CC_ClearControl CC_YES +#endif +#ifndef CC_ClockRateAdjust +#define CC_ClockRateAdjust CC_YES +#endif +#ifndef CC_ClockSet +#define CC_ClockSet CC_YES +#endif +#ifndef CC_Commit +#define CC_Commit (CC_YES && ALG_ECC) +#endif +#ifndef CC_ContextLoad +#define CC_ContextLoad CC_YES +#endif +#ifndef CC_ContextSave +#define CC_ContextSave CC_YES +#endif +#ifndef CC_Create +#define CC_Create CC_YES +#endif +#ifndef CC_CreateLoaded +#define CC_CreateLoaded CC_YES +#endif +#ifndef CC_CreatePrimary +#define CC_CreatePrimary CC_YES +#endif +#ifndef CC_DictionaryAttackLockReset +#define CC_DictionaryAttackLockReset CC_YES +#endif +#ifndef CC_DictionaryAttackParameters +#define CC_DictionaryAttackParameters CC_YES +#endif +#ifndef CC_Duplicate +#define CC_Duplicate CC_YES +#endif +#ifndef CC_ECC_Decrypt +#define CC_ECC_Decrypt (CC_YES && ALG_ECC) +#endif +#ifndef CC_ECC_Encrypt +#define CC_ECC_Encrypt (CC_YES && ALG_ECC) +#endif +#ifndef CC_ECC_Parameters +#define CC_ECC_Parameters (CC_YES && ALG_ECC) +#endif +#ifndef CC_ECDH_KeyGen +#define CC_ECDH_KeyGen (CC_YES && ALG_ECC) +#endif +#ifndef CC_ECDH_ZGen +#define CC_ECDH_ZGen (CC_YES && ALG_ECC) +#endif +#ifndef CC_EC_Ephemeral +#define CC_EC_Ephemeral (CC_YES && ALG_ECC) +#endif +#ifndef CC_EncryptDecrypt +#define CC_EncryptDecrypt CC_YES +#endif +#ifndef CC_EncryptDecrypt2 +#define CC_EncryptDecrypt2 CC_YES +#endif +#ifndef CC_EventSequenceComplete +#define CC_EventSequenceComplete CC_YES +#endif +#ifndef CC_EvictControl +#define CC_EvictControl CC_YES +#endif +#ifndef CC_FieldUpgradeData +#define CC_FieldUpgradeData CC_NO +#endif +#ifndef CC_FieldUpgradeStart +#define CC_FieldUpgradeStart CC_NO +#endif +#ifndef CC_FirmwareRead +#define CC_FirmwareRead CC_NO +#endif +#ifndef CC_FlushContext +#define CC_FlushContext CC_YES +#endif +#ifndef CC_GetCapability +#define CC_GetCapability CC_YES +#endif +#ifndef CC_GetCommandAuditDigest +#define CC_GetCommandAuditDigest CC_YES +#endif +#ifndef CC_GetRandom +#define CC_GetRandom CC_YES +#endif +#ifndef CC_GetSessionAuditDigest +#define CC_GetSessionAuditDigest CC_YES +#endif +#ifndef CC_GetTestResult +#define CC_GetTestResult CC_YES +#endif +#ifndef CC_GetTime +#define CC_GetTime CC_YES +#endif +#ifndef CC_HMAC +#define CC_HMAC (CC_YES && !ALG_CMAC) +#endif +#ifndef CC_HMAC_Start +#define CC_HMAC_Start (CC_YES && !ALG_CMAC) +#endif +#ifndef CC_Hash +#define CC_Hash CC_YES +#endif +#ifndef CC_HashSequenceStart +#define CC_HashSequenceStart CC_YES +#endif +#ifndef CC_HierarchyChangeAuth +#define CC_HierarchyChangeAuth CC_YES +#endif +#ifndef CC_HierarchyControl +#define CC_HierarchyControl CC_YES +#endif +#ifndef CC_Import +#define CC_Import CC_YES +#endif +#ifndef CC_IncrementalSelfTest +#define CC_IncrementalSelfTest CC_YES +#endif +#ifndef CC_Load +#define CC_Load CC_YES +#endif +#ifndef CC_LoadExternal +#define CC_LoadExternal CC_YES +#endif +#ifndef CC_MAC +#define CC_MAC (CC_YES && ALG_CMAC) +#endif +#ifndef CC_MAC_Start +#define CC_MAC_Start (CC_YES && ALG_CMAC) +#endif +#ifndef CC_MakeCredential +#define CC_MakeCredential CC_YES +#endif +#ifndef CC_NV_Certify +#define CC_NV_Certify CC_YES +#endif +#ifndef CC_NV_ChangeAuth +#define CC_NV_ChangeAuth CC_YES +#endif +#ifndef CC_NV_DefineSpace +#define CC_NV_DefineSpace CC_YES +#endif +#ifndef CC_NV_Extend +#define CC_NV_Extend CC_YES +#endif +#ifndef CC_NV_GlobalWriteLock +#define CC_NV_GlobalWriteLock CC_YES +#endif +#ifndef CC_NV_Increment +#define CC_NV_Increment CC_YES +#endif +#ifndef CC_NV_Read +#define CC_NV_Read CC_YES +#endif +#ifndef CC_NV_ReadLock +#define CC_NV_ReadLock CC_YES +#endif +#ifndef CC_NV_ReadPublic +#define CC_NV_ReadPublic CC_YES +#endif +#ifndef CC_NV_SetBits +#define CC_NV_SetBits CC_YES +#endif +#ifndef CC_NV_UndefineSpace +#define CC_NV_UndefineSpace CC_YES +#endif +#ifndef CC_NV_UndefineSpaceSpecial +#define CC_NV_UndefineSpaceSpecial CC_YES +#endif +#ifndef CC_NV_Write +#define CC_NV_Write CC_YES +#endif +#ifndef CC_NV_WriteLock +#define CC_NV_WriteLock CC_YES +#endif +#ifndef CC_ObjectChangeAuth +#define CC_ObjectChangeAuth CC_YES +#endif +#ifndef CC_PCR_Allocate +#define CC_PCR_Allocate CC_YES +#endif +#ifndef CC_PCR_Event +#define CC_PCR_Event CC_YES +#endif +#ifndef CC_PCR_Extend +#define CC_PCR_Extend CC_YES +#endif +#ifndef CC_PCR_Read +#define CC_PCR_Read CC_YES +#endif +#ifndef CC_PCR_Reset +#define CC_PCR_Reset CC_YES +#endif +#ifndef CC_PCR_SetAuthPolicy +#define CC_PCR_SetAuthPolicy CC_YES +#endif +#ifndef CC_PCR_SetAuthValue +#define CC_PCR_SetAuthValue CC_YES +#endif +#ifndef CC_PP_Commands +#define CC_PP_Commands CC_YES +#endif +#ifndef CC_PolicyAuthValue +#define CC_PolicyAuthValue CC_YES +#endif +#ifndef CC_PolicyAuthorize +#define CC_PolicyAuthorize CC_YES +#endif +#ifndef CC_PolicyAuthorizeNV +#define CC_PolicyAuthorizeNV CC_YES +#endif +#ifndef CC_PolicyCommandCode +#define CC_PolicyCommandCode CC_YES +#endif +#ifndef CC_PolicyCounterTimer +#define CC_PolicyCounterTimer CC_YES +#endif +#ifndef CC_PolicyCpHash +#define CC_PolicyCpHash CC_YES +#endif +#ifndef CC_PolicyDuplicationSelect +#define CC_PolicyDuplicationSelect CC_YES +#endif +#ifndef CC_PolicyGetDigest +#define CC_PolicyGetDigest CC_YES +#endif +#ifndef CC_PolicyLocality +#define CC_PolicyLocality CC_YES +#endif +#ifndef CC_PolicyNV +#define CC_PolicyNV CC_YES +#endif +#ifndef CC_PolicyNameHash +#define CC_PolicyNameHash CC_YES +#endif +#ifndef CC_PolicyNvWritten +#define CC_PolicyNvWritten CC_YES +#endif +#ifndef CC_PolicyOR +#define CC_PolicyOR CC_YES +#endif +#ifndef CC_PolicyPCR +#define CC_PolicyPCR CC_YES +#endif +#ifndef CC_PolicyPassword +#define CC_PolicyPassword CC_YES +#endif +#ifndef CC_PolicyPhysicalPresence +#define CC_PolicyPhysicalPresence CC_YES +#endif +#ifndef CC_PolicyRestart +#define CC_PolicyRestart CC_YES +#endif +#ifndef CC_PolicySecret +#define CC_PolicySecret CC_YES +#endif +#ifndef CC_PolicySigned +#define CC_PolicySigned CC_YES +#endif +#ifndef CC_PolicyTemplate +#define CC_PolicyTemplate CC_YES +#endif +#ifndef CC_PolicyTicket +#define CC_PolicyTicket CC_YES +#endif +#ifndef CC_Policy_AC_SendSelect +#define CC_Policy_AC_SendSelect CC_YES +#endif +#ifndef CC_Quote +#define CC_Quote CC_YES +#endif +#ifndef CC_RSA_Decrypt +#define CC_RSA_Decrypt (CC_YES && ALG_RSA) +#endif +#ifndef CC_RSA_Encrypt +#define CC_RSA_Encrypt (CC_YES && ALG_RSA) +#endif +#ifndef CC_ReadClock +#define CC_ReadClock CC_YES +#endif +#ifndef CC_ReadPublic +#define CC_ReadPublic CC_YES +#endif +#ifndef CC_Rewrap +#define CC_Rewrap CC_YES +#endif +#ifndef CC_SelfTest +#define CC_SelfTest CC_YES +#endif +#ifndef CC_SequenceComplete +#define CC_SequenceComplete CC_YES +#endif +#ifndef CC_SequenceUpdate +#define CC_SequenceUpdate CC_YES +#endif +#ifndef CC_SetAlgorithmSet +#define CC_SetAlgorithmSet CC_YES +#endif +#ifndef CC_SetCommandCodeAuditStatus +#define CC_SetCommandCodeAuditStatus CC_YES +#endif +#ifndef CC_SetPrimaryPolicy +#define CC_SetPrimaryPolicy CC_YES +#endif +#ifndef CC_Shutdown +#define CC_Shutdown CC_YES +#endif +#ifndef CC_Sign +#define CC_Sign CC_YES +#endif +#ifndef CC_StartAuthSession +#define CC_StartAuthSession CC_YES +#endif +#ifndef CC_Startup +#define CC_Startup CC_YES +#endif +#ifndef CC_StirRandom +#define CC_StirRandom CC_YES +#endif +#ifndef CC_TestParms +#define CC_TestParms CC_YES +#endif +#ifndef CC_Unseal +#define CC_Unseal CC_YES +#endif +#ifndef CC_Vendor_TCG_Test +#define CC_Vendor_TCG_Test CC_YES +#endif +#ifndef CC_VerifySignature +#define CC_VerifySignature CC_YES +#endif +#ifndef CC_ZGen_2Phase +#define CC_ZGen_2Phase (CC_YES && ALG_ECC) +#endif + + +#endif // _TPM_PROFILE_H_ diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/reference/include/TpmSal.h b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/reference/include/TpmSal.h new file mode 100644 index 0000000..020ac0d --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/reference/include/TpmSal.h @@ -0,0 +1,115 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*** +* TpmSal.h provides a set of #defines that allow SymCrypt to be built +* in VS. +* +****/ + +#ifndef _TPM_SAL_H_ +#define _TPM_SAL_H_ + +#ifndef _Out_writes_bytes_ + +#define _Out_writes_( cbData ) +#define _Out_writes_bytes_( cbData ) +#define _Out_writes_opt_( cbData ) +#define _Out_writes_to_(n, c) +#define _In_reads_( cbBytes ) +#define _In_reads_opt_( cbAuthData ) +#define _In_reads_bytes_(size) +#define _Inout_updates_( nStates ) +#define _Inout_updates_bytes_(size) +#define _Field_size_( size ) +#define _Field_range_( min, max ) +#define _Writable_elements_(c) +#define _Ret_writes_bytes_to_(n, c) + +#define _Analysis_assume_(x) +#define _Analysis_noreturn_ + +#define _Use_decl_annotations_ + +#define __success(x) + +#define __assume +#define __analysis_assume +#define _In_ +#define _Out_ +#define __in +#define __in_opt +#define __in_bcount(x) +#define __in_bcount_opt(x) +#define __in_ecount(x) +#define __in_ecount_opt(x) +#define __in_xcount(x) +#define __out +#define __out_ecount(x) +#define __out_ecount_opt(x) +#define __out_ecount_full(x) +#define __out_ecount_part(x, y) +#define __out_bcount(x) +#define __out_bcount_part_opt(x, y) +#define __out_bcount_full(x) +#define __out_xcount(x) +#define __out_xcount_opt(x) +#define __out_ecount_part(x, y) +#define __out_ecount_part_opt(x, y) +#define __out_opt +#define __inout_ecount(x) +#define __inout_bcount(x) +#define __bound +#define __inout +#define __inout_opt +#define __inout_ecount_opt(x) +#define __deref_out_ecount(x) +#define __deref_opt_out_ecount(x) +#define __field_ecount(x) +#define _Post_invalid_ +#define _Pre_maybenull_ +#define __checkReturn +#define _In_bytecount_(x) + +#endif /* no SAL macros defined */ + +#ifndef _Interlocked_operand_ + +#define _Interlocked_operand_ + +#endif + + +#endif diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/reference/include/VendorString.h b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/reference/include/VendorString.h new file mode 100644 index 0000000..b2b798e --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/reference/include/VendorString.h @@ -0,0 +1,93 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 _VENDOR_STRING_H +#define _VENDOR_STRING_H + +// Define up to 4-byte values for MANUFACTURER. This value defines the response +// for TPM_PT_MANUFACTURER in TPM2_GetCapability. +// The following line should be un-commented and a vendor specific string +// should be provided here. +#define MANUFACTURER "MSFT" + +// The following #if macro may be deleted after a proper MANUFACTURER is provided. +#ifndef MANUFACTURER +#error MANUFACTURER is not provided. \ +Please modify include\VendorString.h to provide a specific \ +manufacturer name. +#endif + +// Define up to 4, 4-byte values. The values must each be 4 bytes long and the last +// value used may contain trailing zeros. +// These values define the response for TPM_PT_VENDOR_STRING_(1-4) +// in TPM2_GetCapability. +// The following line should be un-commented and a vendor specific string +// should be provided here. +// The vendor strings 2-4 may also be defined as appropriately. +#define VENDOR_STRING_1 "SSE " +#define VENDOR_STRING_2 "fTPM" +//#define VENDOR_STRING_3 +//#define VENDOR_STRING_4 + +// The following #if macro may be deleted after a proper VENDOR_STRING_1 +// is provided. +#ifndef VENDOR_STRING_1 +#error VENDOR_STRING_1 is not provided. \ +Please modify include\VendorString.h to provide a vendor specific \ +string. +#endif + +// the more significant 32-bits of a vendor-specific value +// indicating the version of the firmware +// The following line should be un-commented and a vendor-specific firmware V1 +// should be provided here. +// The FIRMWARE_V2 may also be defined as appropriate. + +//Date of last update: (0xYYYMMDD) +#define FIRMWARE_V1 (0x20180710) +// the less significant 32-bits of a vendor-specific value +// indicating the version of the firmware + +//Time of last update: (0x00HHMMSS) +#define FIRMWARE_V2 (0x00105300) + +// The following #if macro may be deleted after a proper FIRMWARE_V1 is provided. +#ifndef FIRMWARE_V1 +#error FIRMWARE_V1 is not provided. \ +Please modify include\VendorString.h to provide a vendor-specific firmware \ +version +#endif + +#endif diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/reference/include/bool.h b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/reference/include/bool.h new file mode 100644 index 0000000..60b55ee --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/reference/include/bool.h @@ -0,0 +1,51 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 _BOOL_H +#define _BOOL_H + +#if defined(TRUE) +#undef TRUE +#endif + +#if defined FALSE +#undef FALSE +#endif + +typedef int BOOL; +#define FALSE ((BOOL)0) +#define TRUE ((BOOL)1) + +#endif diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/sub.mk b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/sub.mk new file mode 100644 index 0000000..885d537 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/sub.mk @@ -0,0 +1,31 @@ +subdirs-y += lib + +global-incdirs-y += include +global-incdirs-y += reference/include +global-incdirs-y += platform/include + +srcs-y += platform/AdminPPI.c +srcs-y += platform/Cancel.c +srcs-y += platform/Clock.c +srcs-y += platform/DebugHelpers.c +srcs-y += platform/Entropy.c +srcs-y += platform/LocalityPlat.c +srcs-y += platform/NvAdmin.c +srcs-y += platform/NVMem.c +srcs-y += platform/PowerPlat.c +srcs-y += platform/PlatformData.c +srcs-y += platform/PPPlat.c +srcs-y += platform/RunCommand.c +srcs-y += platform/Unique.c +srcs-y += platform/EPS.c +srcs-y += platform/PlatformACT.c +srcs-y += reference/RuntimeSupport.c +srcs-y += platform/fTPM_helpers.c + +srcs-y += fTPM.c + +ifeq ($(CFG_TA_MEASURED_BOOT),y) +# Support for Trusted Firmware Measured Boot. +srcs-y += platform/fTPM_event_log.c +srcs-y += platform/EventLogPrint.c +endif diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/user_ta_header_defines.h b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/user_ta_header_defines.h new file mode 100644 index 0000000..92c33c1 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/user_ta_header_defines.h @@ -0,0 +1,56 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 name of this file must not be modified + */ + +#ifndef USER_TA_HEADER_DEFINES_H +#define USER_TA_HEADER_DEFINES_H + +#include + +#define TA_UUID TA_FTPM_UUID + +#define TA_FLAGS (TA_FLAG_SINGLE_INSTANCE | TA_FLAG_INSTANCE_KEEP_ALIVE) +#define TA_STACK_SIZE (64 * 1024) +#define TA_DATA_SIZE (32 * 1024) + +#define TA_CURRENT_TA_EXT_PROPERTIES \ + { "gp.ta.description", USER_TA_PROP_TYPE_STRING, \ + "fTPM TA" }, \ + { "gp.ta.version", USER_TA_PROP_TYPE_U32, &(const uint32_t){ 0x0010 } } + +#endif /*USER_TA_HEADER_DEFINES_H*/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/ta_prod_signing_scripts/README.md b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/ta_prod_signing_scripts/README.md new file mode 100644 index 0000000..4d992b9 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/ta_prod_signing_scripts/README.md @@ -0,0 +1,17 @@ +# Microsoft Production TA Signing Scripts + +##### The Python scripts `generate_digest.py` and `stitch_ta.py` are used to production sign Microsoft-built TAs. + +## Usage + +1. Compile the TAs as usual. +2. Take the `*.stripped.elf` file (TA with no signature), and run the following Python script. +This script will generate the digest (hash) for the unsigned TA. The digest will be stored in `6b51f84e-a93d-456c-ab0e29ad8f264a47.dig` in the same folder as the TA. The digest will be in ASCII Base64 format. +``` +c:\Python34\python.exe "generate_digest.py" --in "6b51f84e-a93d-456c-ab0e29ad8f264a47.stripped.elf" +``` +3. Send the `*.dig` file to the Security team for them to sign. They will return a `*.dig.signed` file. +4. Run the following Python script to generate the final Production-signed TA (`6b51f84e-a93d-456c-ab0e29ad8f264a47_signed.ta`): +``` +c:\Python34\python.exe "stitch_ta.py" --in "6b51f84e-a93d-456c-ab0e29ad8f264a47.stripped.elf" --dig "6b51f84e-a93d-456c-ab0e29ad8f264a47.dig" --sig "6b51f84e-a93d-456c-ab0e29ad8f264a47.dig.signed" --out "6b51f84e-a93d-456c-ab0e29ad8f264a47_signed.ta" +``` \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/ta_prod_signing_scripts/generate_digest.py b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/ta_prod_signing_scripts/generate_digest.py new file mode 100644 index 0000000..18dbd1c --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/ARM32-FirmwareTPM/ta_prod_signing_scripts/generate_digest.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python +# +# 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. +# + +def get_args(): + from argparse import ArgumentParser + + parser = ArgumentParser() + parser.add_argument('--in', required=True, dest='inf', \ + help='Name of input file (unsigned TA)') + return parser.parse_args() + +def assert_file_exists(fname): + import os.path + + if(os.path.isfile(fname)): + return True + else: + raise FileNotFoundError('File ' + fname + ' was not found') + +def main(): + from Crypto.Signature import PKCS1_v1_5 + from Crypto.Hash import SHA256 + from Crypto.PublicKey import RSA + import struct, base64, os.path, sys + + args = get_args() + + assert_file_exists(args.inf) + + # Read input file (unsigned TA) + f = open(args.inf, 'rb') + img = f.read() + f.close() + + h = SHA256.new() + + digest_len = h.digest_size + #We plan to use RSA 2048 bit keys so signature is 256 bytes + sig_len = 256 #len(signer.sign(h)) + img_size = len(img) + + magic = 0x4f545348 # SHDR_MAGIC + img_type = 0 # SHDR_TA + algo = 0x70004830 # TEE_ALG_RSASSA_PKCS1_V1_5_SHA256 + shdr = struct.pack(' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/.mxproject b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/.mxproject new file mode 100644 index 0000000..c5963d6 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/.mxproject @@ -0,0 +1,14 @@ +[PreviousGenFiles] +HeaderPath=D:/VS/brianTPM/Samples/Nucleo-TPM/L476RG/Inc +HeaderFiles=usb_device.h;usbd_conf.h;usbd_desc.h;usbd_cdc_if.h;stm32l4xx_it.h;stm32l4xx_hal_conf.h;main.h; +SourcePath=D:/VS/brianTPM/Samples/Nucleo-TPM/L476RG/Src +SourceFiles=usb_device.c;usbd_conf.c;usbd_desc.c;usbd_cdc_if.c;stm32l4xx_it.c;stm32l4xx_hal_msp.c;main.c; + +[PreviousLibFiles] +LibFiles=Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pcd.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pcd_ex.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_usb.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rng.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rtc.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rtc_ex.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_tim.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_tim_ex.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_uart.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_uart_ex.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_def.h;Drivers/STM32L4xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_i2c.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_i2c_ex.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rcc.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rcc_ex.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash_ex.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash_ramfunc.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_gpio.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_gpio_ex.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_dma.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_dma_ex.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pwr.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pwr_ex.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_cortex.h;Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_core.h;Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ctlreq.h;Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_def.h;Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ioreq.h;Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc/usbd_cdc.h;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pcd.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pcd_ex.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_usb.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rng.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rtc.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rtc_ex.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_tim.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_tim_ex.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_uart.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_uart_ex.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_i2c.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_i2c_ex.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rcc.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rcc_ex.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash_ex.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash_ramfunc.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_gpio.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_dma.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_dma_ex.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pwr.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pwr_ex.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_cortex.c;Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c;Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c;Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c;Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c;Drivers/CMSIS/Device/ST/STM32L4xx/Include/stm32l476xx.h;Drivers/CMSIS/Device/ST/STM32L4xx/Include/stm32l4xx.h;Drivers/CMSIS/Device/ST/STM32L4xx/Include/system_stm32l4xx.h;Drivers/CMSIS/Device/ST/STM32L4xx/Source/Templates/system_stm32l4xx.c;Drivers/CMSIS/Include/arm_common_tables.h;Drivers/CMSIS/Include/arm_const_structs.h;Drivers/CMSIS/Include/arm_math.h;Drivers/CMSIS/Include/cmsis_armcc.h;Drivers/CMSIS/Include/cmsis_armcc_V6.h;Drivers/CMSIS/Include/cmsis_gcc.h;Drivers/CMSIS/Include/core_cm0.h;Drivers/CMSIS/Include/core_cm0plus.h;Drivers/CMSIS/Include/core_cm3.h;Drivers/CMSIS/Include/core_cm4.h;Drivers/CMSIS/Include/core_cm7.h;Drivers/CMSIS/Include/core_cmFunc.h;Drivers/CMSIS/Include/core_cmInstr.h;Drivers/CMSIS/Include/core_cmSimd.h;Drivers/CMSIS/Include/core_sc000.h;Drivers/CMSIS/Include/core_sc300.h; + +[PreviousUsedTStudioFiles] +SourceFiles=..\Src\main.c;..\Src\usb_device.c;..\Src\usbd_conf.c;..\Src\usbd_desc.c;..\Src\usbd_cdc_if.c;..\Src\stm32l4xx_it.c;..\Src\stm32l4xx_hal_msp.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pcd.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pcd_ex.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_usb.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rng.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rtc.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rtc_ex.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_tim.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_tim_ex.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_uart.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_uart_ex.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_i2c.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_i2c_ex.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rcc.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rcc_ex.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash_ex.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash_ramfunc.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_gpio.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_dma.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_dma_ex.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pwr.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pwr_ex.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_cortex.c;../Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c;../Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c;../Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c;../Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c;../\Src/system_stm32l4xx.c;../Drivers/CMSIS/Device/ST/STM32L4xx/Source/Templates/system_stm32l4xx.c;null;../Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c;../Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c;../Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c;../Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c; +HeaderPath=..\Drivers\STM32L4xx_HAL_Driver\Inc;..\Drivers\STM32L4xx_HAL_Driver\Inc\Legacy;..\Middlewares\ST\STM32_USB_Device_Library\Core\Inc;..\Middlewares\ST\STM32_USB_Device_Library\Class\CDC\Inc;..\Drivers\CMSIS\Device\ST\STM32L4xx\Include;..\Drivers\CMSIS\Include;..\Inc; +CDefines=__weak:__attribute__((weak));__packed:__attribute__((__packed__)); + diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/.project b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/.project new file mode 100644 index 0000000..faceb25 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/.project @@ -0,0 +1,155 @@ + + + Nucleo-L476RG + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + ?children? + ?name?=outputEntries\|?children?=?name?=entry\\\\\\\|\\\|\|| + + + ?name? + + + + org.eclipse.cdt.make.core.append_environment + true + + + org.eclipse.cdt.make.core.buildArguments + + + + org.eclipse.cdt.make.core.buildCommand + make + + + org.eclipse.cdt.make.core.buildLocation + ${workspace_loc:/STM32100B-EVAL/Debug} + + + org.eclipse.cdt.make.core.contents + org.eclipse.cdt.make.core.activeConfigSettings + + + org.eclipse.cdt.make.core.enableAutoBuild + false + + + org.eclipse.cdt.make.core.enableCleanBuild + true + + + org.eclipse.cdt.make.core.enableFullBuild + true + + + org.eclipse.cdt.make.core.stopOnError + true + + + org.eclipse.cdt.make.core.useDefaultBuildCmd + true + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + + + Inc/Platform + 2 + PARENT-1-PROJECT_LOC/Shared/Platform/include + + + Inc/TPMCmd + 2 + PARENT-3-PROJECT_LOC/TPMCmd/tpm/include + + + Inc/TPMDevice + 2 + PARENT-1-PROJECT_LOC/Shared/TPMDevice/include + + + Middlewares/Platform + 2 + PARENT-1-PROJECT_LOC/Shared/Platform/src + + + Middlewares/TPMCmd + 2 + PARENT-3-PROJECT_LOC/TPMCmd/tpm/src + + + Middlewares/TPMDevice + 2 + PARENT-1-PROJECT_LOC/Shared/TPMDevice/src + + + Src/syscalls.c + 1 + PARENT-1-PROJECT_LOC../Shared/syscalls.c + + + Middlewares/WolfCypt/aes.c + 1 + PARENT-3-PROJECT_LOC/external/wolfssl/wolfcrypt/src/aes.c + + + Middlewares/WolfCypt/ecc.c + 1 + PARENT-3-PROJECT_LOC/external/wolfssl/wolfcrypt/src/ecc.c + + + Middlewares/WolfCypt/integer.c + 1 + PARENT-3-PROJECT_LOC/external/wolfssl/wolfcrypt/src/integer.c + + + Middlewares/WolfCypt/memory.c + 1 + PARENT-3-PROJECT_LOC/external/wolfssl/wolfcrypt/src/memory.c + + + Middlewares/WolfCypt/sha.c + 1 + PARENT-3-PROJECT_LOC/external/wolfssl/wolfcrypt/src/sha.c + + + Middlewares/WolfCypt/sha256.c + 1 + PARENT-3-PROJECT_LOC/external/wolfssl/wolfcrypt/src/sha256.c + + + Middlewares/WolfCypt/sha512.c + 1 + PARENT-3-PROJECT_LOC/external/wolfssl/wolfcrypt/src/sha512.c + + + Middlewares/WolfCypt/tfm.c + 1 + PARENT-3-PROJECT_LOC/external/wolfssl/wolfcrypt/src/tfm.c + + + Middlewares/WolfCypt/wolfmath.c + 1 + PARENT-3-PROJECT_LOC/external/wolfssl/wolfcrypt/src/wolfmath.c + + + diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/.settings/com.atollic.truestudio.debug.hardware_device.prefs b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/.settings/com.atollic.truestudio.debug.hardware_device.prefs new file mode 100644 index 0000000..f3ef444 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/.settings/com.atollic.truestudio.debug.hardware_device.prefs @@ -0,0 +1,11 @@ +BOARD=None +CODE_LOCATION=FLASH +ENDIAN=Little-endian +MCU=STM32L476RG +MCU_VENDOR=STMicroelectronics +MODEL=Lite +PROBE=ST-LINK +PROJECT_FORMAT_VERSION=2 +TARGET=ARM\u00AE +VERSION=4.1.0 +eclipse.preferences.version=1 diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/.settings/language.settings.xml b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/.settings/language.settings.xml new file mode 100644 index 0000000..175a203 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/.settings/language.settings.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/.settings/org.eclipse.cdt.managedbuilder.core.prefs b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/.settings/org.eclipse.cdt.managedbuilder.core.prefs new file mode 100644 index 0000000..66eb673 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/.settings/org.eclipse.cdt.managedbuilder.core.prefs @@ -0,0 +1,11 @@ +eclipse.preferences.version=1 +environment/buildEnvironmentInclude/com.atollic.truestudio.exe.debug.1518366166/CPATH/delimiter=; +environment/buildEnvironmentInclude/com.atollic.truestudio.exe.debug.1518366166/CPATH/operation=remove +environment/buildEnvironmentInclude/com.atollic.truestudio.exe.debug.1518366166/C_INCLUDE_PATH/delimiter=; +environment/buildEnvironmentInclude/com.atollic.truestudio.exe.debug.1518366166/C_INCLUDE_PATH/operation=remove +environment/buildEnvironmentInclude/com.atollic.truestudio.exe.debug.1518366166/append=true +environment/buildEnvironmentInclude/com.atollic.truestudio.exe.debug.1518366166/appendContributed=true +environment/buildEnvironmentLibrary/com.atollic.truestudio.exe.debug.1518366166/LIBRARY_PATH/delimiter=; +environment/buildEnvironmentLibrary/com.atollic.truestudio.exe.debug.1518366166/LIBRARY_PATH/operation=remove +environment/buildEnvironmentLibrary/com.atollic.truestudio.exe.debug.1518366166/append=true +environment/buildEnvironmentLibrary/com.atollic.truestudio.exe.debug.1518366166/appendContributed=true diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Device/ST/STM32L4xx/Include/stm32l476xx.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Device/ST/STM32L4xx/Include/stm32l476xx.h new file mode 100644 index 0000000..5e8e62d --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Device/ST/STM32L4xx/Include/stm32l476xx.h @@ -0,0 +1,18537 @@ +/** + ****************************************************************************** + * @file stm32l476xx.h + * @author MCD Application Team + * @brief CMSIS STM32L476xx Device Peripheral Access Layer Header File. + * + * This file contains: + * - Data structures and the address mapping for all peripherals + * - Peripheral's registers declarations and bits definition + * - Macros to access peripheral’s registers hardware + * + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS_Device + * @{ + */ + +/** @addtogroup stm32l476xx + * @{ + */ + +#ifndef __STM32L476xx_H +#define __STM32L476xx_H + +#ifdef __cplusplus + extern "C" { +#endif /* __cplusplus */ + +/** @addtogroup Configuration_section_for_CMSIS + * @{ + */ + +/** + * @brief Configuration of the Cortex-M4 Processor and Core Peripherals + */ +#define __CM4_REV 0x0001 /*!< Cortex-M4 revision r0p1 */ +#define __MPU_PRESENT 1 /*!< STM32L4XX provides an MPU */ +#define __NVIC_PRIO_BITS 4 /*!< STM32L4XX uses 4 Bits for the Priority Levels */ +#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */ +#define __FPU_PRESENT 1 /*!< FPU present */ + +/** + * @} + */ + +/** @addtogroup Peripheral_interrupt_number_definition + * @{ + */ + +/** + * @brief STM32L4XX Interrupt Number Definition, according to the selected device + * in @ref Library_configuration_section + */ +typedef enum +{ +/****** Cortex-M4 Processor Exceptions Numbers ****************************************************************/ + NonMaskableInt_IRQn = -14, /*!< 2 Cortex-M4 Non Maskable Interrupt */ + HardFault_IRQn = -13, /*!< 3 Cortex-M4 Hard Fault Interrupt */ + MemoryManagement_IRQn = -12, /*!< 4 Cortex-M4 Memory Management Interrupt */ + BusFault_IRQn = -11, /*!< 5 Cortex-M4 Bus Fault Interrupt */ + UsageFault_IRQn = -10, /*!< 6 Cortex-M4 Usage Fault Interrupt */ + SVCall_IRQn = -5, /*!< 11 Cortex-M4 SV Call Interrupt */ + DebugMonitor_IRQn = -4, /*!< 12 Cortex-M4 Debug Monitor Interrupt */ + PendSV_IRQn = -2, /*!< 14 Cortex-M4 Pend SV Interrupt */ + SysTick_IRQn = -1, /*!< 15 Cortex-M4 System Tick Interrupt */ +/****** STM32 specific Interrupt Numbers **********************************************************************/ + WWDG_IRQn = 0, /*!< Window WatchDog Interrupt */ + PVD_PVM_IRQn = 1, /*!< PVD/PVM1/PVM2/PVM3/PVM4 through EXTI Line detection Interrupts */ + TAMP_STAMP_IRQn = 2, /*!< Tamper and TimeStamp interrupts through the EXTI line */ + RTC_WKUP_IRQn = 3, /*!< RTC Wakeup interrupt through the EXTI line */ + FLASH_IRQn = 4, /*!< FLASH global Interrupt */ + RCC_IRQn = 5, /*!< RCC global Interrupt */ + EXTI0_IRQn = 6, /*!< EXTI Line0 Interrupt */ + EXTI1_IRQn = 7, /*!< EXTI Line1 Interrupt */ + EXTI2_IRQn = 8, /*!< EXTI Line2 Interrupt */ + EXTI3_IRQn = 9, /*!< EXTI Line3 Interrupt */ + EXTI4_IRQn = 10, /*!< EXTI Line4 Interrupt */ + DMA1_Channel1_IRQn = 11, /*!< DMA1 Channel 1 global Interrupt */ + DMA1_Channel2_IRQn = 12, /*!< DMA1 Channel 2 global Interrupt */ + DMA1_Channel3_IRQn = 13, /*!< DMA1 Channel 3 global Interrupt */ + DMA1_Channel4_IRQn = 14, /*!< DMA1 Channel 4 global Interrupt */ + DMA1_Channel5_IRQn = 15, /*!< DMA1 Channel 5 global Interrupt */ + DMA1_Channel6_IRQn = 16, /*!< DMA1 Channel 6 global Interrupt */ + DMA1_Channel7_IRQn = 17, /*!< DMA1 Channel 7 global Interrupt */ + ADC1_2_IRQn = 18, /*!< ADC1, ADC2 SAR global Interrupts */ + CAN1_TX_IRQn = 19, /*!< CAN1 TX Interrupt */ + CAN1_RX0_IRQn = 20, /*!< CAN1 RX0 Interrupt */ + CAN1_RX1_IRQn = 21, /*!< CAN1 RX1 Interrupt */ + CAN1_SCE_IRQn = 22, /*!< CAN1 SCE Interrupt */ + EXTI9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */ + TIM1_BRK_TIM15_IRQn = 24, /*!< TIM1 Break interrupt and TIM15 global interrupt */ + TIM1_UP_TIM16_IRQn = 25, /*!< TIM1 Update Interrupt and TIM16 global interrupt */ + TIM1_TRG_COM_TIM17_IRQn = 26, /*!< TIM1 Trigger and Commutation Interrupt and TIM17 global interrupt */ + TIM1_CC_IRQn = 27, /*!< TIM1 Capture Compare Interrupt */ + TIM2_IRQn = 28, /*!< TIM2 global Interrupt */ + TIM3_IRQn = 29, /*!< TIM3 global Interrupt */ + TIM4_IRQn = 30, /*!< TIM4 global Interrupt */ + I2C1_EV_IRQn = 31, /*!< I2C1 Event Interrupt */ + I2C1_ER_IRQn = 32, /*!< I2C1 Error Interrupt */ + I2C2_EV_IRQn = 33, /*!< I2C2 Event Interrupt */ + I2C2_ER_IRQn = 34, /*!< I2C2 Error Interrupt */ + SPI1_IRQn = 35, /*!< SPI1 global Interrupt */ + SPI2_IRQn = 36, /*!< SPI2 global Interrupt */ + USART1_IRQn = 37, /*!< USART1 global Interrupt */ + USART2_IRQn = 38, /*!< USART2 global Interrupt */ + USART3_IRQn = 39, /*!< USART3 global Interrupt */ + EXTI15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */ + RTC_Alarm_IRQn = 41, /*!< RTC Alarm (A and B) through EXTI Line Interrupt */ + DFSDM1_FLT3_IRQn = 42, /*!< DFSDM1 Filter 3 global Interrupt */ + TIM8_BRK_IRQn = 43, /*!< TIM8 Break Interrupt */ + TIM8_UP_IRQn = 44, /*!< TIM8 Update Interrupt */ + TIM8_TRG_COM_IRQn = 45, /*!< TIM8 Trigger and Commutation Interrupt */ + TIM8_CC_IRQn = 46, /*!< TIM8 Capture Compare Interrupt */ + ADC3_IRQn = 47, /*!< ADC3 global Interrupt */ + FMC_IRQn = 48, /*!< FMC global Interrupt */ + SDMMC1_IRQn = 49, /*!< SDMMC1 global Interrupt */ + TIM5_IRQn = 50, /*!< TIM5 global Interrupt */ + SPI3_IRQn = 51, /*!< SPI3 global Interrupt */ + UART4_IRQn = 52, /*!< UART4 global Interrupt */ + UART5_IRQn = 53, /*!< UART5 global Interrupt */ + TIM6_DAC_IRQn = 54, /*!< TIM6 global and DAC1&2 underrun error interrupts */ + TIM7_IRQn = 55, /*!< TIM7 global interrupt */ + DMA2_Channel1_IRQn = 56, /*!< DMA2 Channel 1 global Interrupt */ + DMA2_Channel2_IRQn = 57, /*!< DMA2 Channel 2 global Interrupt */ + DMA2_Channel3_IRQn = 58, /*!< DMA2 Channel 3 global Interrupt */ + DMA2_Channel4_IRQn = 59, /*!< DMA2 Channel 4 global Interrupt */ + DMA2_Channel5_IRQn = 60, /*!< DMA2 Channel 5 global Interrupt */ + DFSDM1_FLT0_IRQn = 61, /*!< DFSDM1 Filter 0 global Interrupt */ + DFSDM1_FLT1_IRQn = 62, /*!< DFSDM1 Filter 1 global Interrupt */ + DFSDM1_FLT2_IRQn = 63, /*!< DFSDM1 Filter 2 global Interrupt */ + COMP_IRQn = 64, /*!< COMP1 and COMP2 Interrupts */ + LPTIM1_IRQn = 65, /*!< LP TIM1 interrupt */ + LPTIM2_IRQn = 66, /*!< LP TIM2 interrupt */ + OTG_FS_IRQn = 67, /*!< USB OTG FS global Interrupt */ + DMA2_Channel6_IRQn = 68, /*!< DMA2 Channel 6 global interrupt */ + DMA2_Channel7_IRQn = 69, /*!< DMA2 Channel 7 global interrupt */ + LPUART1_IRQn = 70, /*!< LP UART1 interrupt */ + QUADSPI_IRQn = 71, /*!< Quad SPI global interrupt */ + I2C3_EV_IRQn = 72, /*!< I2C3 event interrupt */ + I2C3_ER_IRQn = 73, /*!< I2C3 error interrupt */ + SAI1_IRQn = 74, /*!< Serial Audio Interface 1 global interrupt */ + SAI2_IRQn = 75, /*!< Serial Audio Interface 2 global interrupt */ + SWPMI1_IRQn = 76, /*!< Serial Wire Interface 1 global interrupt */ + TSC_IRQn = 77, /*!< Touch Sense Controller global interrupt */ + LCD_IRQn = 78, /*!< LCD global interrupt */ + RNG_IRQn = 80, /*!< RNG global interrupt */ + FPU_IRQn = 81 /*!< FPU global interrupt */ +} IRQn_Type; + +/** + * @} + */ + +#include "core_cm4.h" /* Cortex-M4 processor and core peripherals */ +#include "system_stm32l4xx.h" +#include + +/** @addtogroup Peripheral_registers_structures + * @{ + */ + +/** + * @brief Analog to Digital Converter + */ + +typedef struct +{ + __IO uint32_t ISR; /*!< ADC interrupt and status register, Address offset: 0x00 */ + __IO uint32_t IER; /*!< ADC interrupt enable register, Address offset: 0x04 */ + __IO uint32_t CR; /*!< ADC control register, Address offset: 0x08 */ + __IO uint32_t CFGR; /*!< ADC configuration register 1, Address offset: 0x0C */ + __IO uint32_t CFGR2; /*!< ADC configuration register 2, Address offset: 0x10 */ + __IO uint32_t SMPR1; /*!< ADC sampling time register 1, Address offset: 0x14 */ + __IO uint32_t SMPR2; /*!< ADC sampling time register 2, Address offset: 0x18 */ + uint32_t RESERVED1; /*!< Reserved, 0x1C */ + __IO uint32_t TR1; /*!< ADC analog watchdog 1 threshold register, Address offset: 0x20 */ + __IO uint32_t TR2; /*!< ADC analog watchdog 2 threshold register, Address offset: 0x24 */ + __IO uint32_t TR3; /*!< ADC analog watchdog 3 threshold register, Address offset: 0x28 */ + uint32_t RESERVED2; /*!< Reserved, 0x2C */ + __IO uint32_t SQR1; /*!< ADC group regular sequencer register 1, Address offset: 0x30 */ + __IO uint32_t SQR2; /*!< ADC group regular sequencer register 2, Address offset: 0x34 */ + __IO uint32_t SQR3; /*!< ADC group regular sequencer register 3, Address offset: 0x38 */ + __IO uint32_t SQR4; /*!< ADC group regular sequencer register 4, Address offset: 0x3C */ + __IO uint32_t DR; /*!< ADC group regular data register, Address offset: 0x40 */ + uint32_t RESERVED3; /*!< Reserved, 0x44 */ + uint32_t RESERVED4; /*!< Reserved, 0x48 */ + __IO uint32_t JSQR; /*!< ADC group injected sequencer register, Address offset: 0x4C */ + uint32_t RESERVED5[4]; /*!< Reserved, 0x50 - 0x5C */ + __IO uint32_t OFR1; /*!< ADC offset register 1, Address offset: 0x60 */ + __IO uint32_t OFR2; /*!< ADC offset register 2, Address offset: 0x64 */ + __IO uint32_t OFR3; /*!< ADC offset register 3, Address offset: 0x68 */ + __IO uint32_t OFR4; /*!< ADC offset register 4, Address offset: 0x6C */ + uint32_t RESERVED6[4]; /*!< Reserved, 0x70 - 0x7C */ + __IO uint32_t JDR1; /*!< ADC group injected rank 1 data register, Address offset: 0x80 */ + __IO uint32_t JDR2; /*!< ADC group injected rank 2 data register, Address offset: 0x84 */ + __IO uint32_t JDR3; /*!< ADC group injected rank 3 data register, Address offset: 0x88 */ + __IO uint32_t JDR4; /*!< ADC group injected rank 4 data register, Address offset: 0x8C */ + uint32_t RESERVED7[4]; /*!< Reserved, 0x090 - 0x09C */ + __IO uint32_t AWD2CR; /*!< ADC analog watchdog 1 configuration register, Address offset: 0xA0 */ + __IO uint32_t AWD3CR; /*!< ADC analog watchdog 3 Configuration Register, Address offset: 0xA4 */ + uint32_t RESERVED8; /*!< Reserved, 0x0A8 */ + uint32_t RESERVED9; /*!< Reserved, 0x0AC */ + __IO uint32_t DIFSEL; /*!< ADC differential mode selection register, Address offset: 0xB0 */ + __IO uint32_t CALFACT; /*!< ADC calibration factors, Address offset: 0xB4 */ + +} ADC_TypeDef; + +typedef struct +{ + __IO uint32_t CSR; /*!< ADC common status register, Address offset: ADC1 base address + 0x300 */ + uint32_t RESERVED; /*!< Reserved, Address offset: ADC1 base address + 0x304 */ + __IO uint32_t CCR; /*!< ADC common configuration register, Address offset: ADC1 base address + 0x308 */ + __IO uint32_t CDR; /*!< ADC common group regular data register Address offset: ADC1 base address + 0x30C */ +} ADC_Common_TypeDef; + + +/** + * @brief Controller Area Network TxMailBox + */ + +typedef struct +{ + __IO uint32_t TIR; /*!< CAN TX mailbox identifier register */ + __IO uint32_t TDTR; /*!< CAN mailbox data length control and time stamp register */ + __IO uint32_t TDLR; /*!< CAN mailbox data low register */ + __IO uint32_t TDHR; /*!< CAN mailbox data high register */ +} CAN_TxMailBox_TypeDef; + +/** + * @brief Controller Area Network FIFOMailBox + */ + +typedef struct +{ + __IO uint32_t RIR; /*!< CAN receive FIFO mailbox identifier register */ + __IO uint32_t RDTR; /*!< CAN receive FIFO mailbox data length control and time stamp register */ + __IO uint32_t RDLR; /*!< CAN receive FIFO mailbox data low register */ + __IO uint32_t RDHR; /*!< CAN receive FIFO mailbox data high register */ +} CAN_FIFOMailBox_TypeDef; + +/** + * @brief Controller Area Network FilterRegister + */ + +typedef struct +{ + __IO uint32_t FR1; /*!< CAN Filter bank register 1 */ + __IO uint32_t FR2; /*!< CAN Filter bank register 1 */ +} CAN_FilterRegister_TypeDef; + +/** + * @brief Controller Area Network + */ + +typedef struct +{ + __IO uint32_t MCR; /*!< CAN master control register, Address offset: 0x00 */ + __IO uint32_t MSR; /*!< CAN master status register, Address offset: 0x04 */ + __IO uint32_t TSR; /*!< CAN transmit status register, Address offset: 0x08 */ + __IO uint32_t RF0R; /*!< CAN receive FIFO 0 register, Address offset: 0x0C */ + __IO uint32_t RF1R; /*!< CAN receive FIFO 1 register, Address offset: 0x10 */ + __IO uint32_t IER; /*!< CAN interrupt enable register, Address offset: 0x14 */ + __IO uint32_t ESR; /*!< CAN error status register, Address offset: 0x18 */ + __IO uint32_t BTR; /*!< CAN bit timing register, Address offset: 0x1C */ + uint32_t RESERVED0[88]; /*!< Reserved, 0x020 - 0x17F */ + CAN_TxMailBox_TypeDef sTxMailBox[3]; /*!< CAN Tx MailBox, Address offset: 0x180 - 0x1AC */ + CAN_FIFOMailBox_TypeDef sFIFOMailBox[2]; /*!< CAN FIFO MailBox, Address offset: 0x1B0 - 0x1CC */ + uint32_t RESERVED1[12]; /*!< Reserved, 0x1D0 - 0x1FF */ + __IO uint32_t FMR; /*!< CAN filter master register, Address offset: 0x200 */ + __IO uint32_t FM1R; /*!< CAN filter mode register, Address offset: 0x204 */ + uint32_t RESERVED2; /*!< Reserved, 0x208 */ + __IO uint32_t FS1R; /*!< CAN filter scale register, Address offset: 0x20C */ + uint32_t RESERVED3; /*!< Reserved, 0x210 */ + __IO uint32_t FFA1R; /*!< CAN filter FIFO assignment register, Address offset: 0x214 */ + uint32_t RESERVED4; /*!< Reserved, 0x218 */ + __IO uint32_t FA1R; /*!< CAN filter activation register, Address offset: 0x21C */ + uint32_t RESERVED5[8]; /*!< Reserved, 0x220-0x23F */ + CAN_FilterRegister_TypeDef sFilterRegister[28]; /*!< CAN Filter Register, Address offset: 0x240-0x31C */ +} CAN_TypeDef; + + +/** + * @brief Comparator + */ + +typedef struct +{ + __IO uint32_t CSR; /*!< COMP control and status register, Address offset: 0x00 */ +} COMP_TypeDef; + +typedef struct +{ + __IO uint32_t CSR; /*!< COMP control and status register, used for bits common to several COMP instances, Address offset: 0x00 */ +} COMP_Common_TypeDef; + +/** + * @brief CRC calculation unit + */ + +typedef struct +{ + __IO uint32_t DR; /*!< CRC Data register, Address offset: 0x00 */ + __IO uint8_t IDR; /*!< CRC Independent data register, Address offset: 0x04 */ + uint8_t RESERVED0; /*!< Reserved, 0x05 */ + uint16_t RESERVED1; /*!< Reserved, 0x06 */ + __IO uint32_t CR; /*!< CRC Control register, Address offset: 0x08 */ + uint32_t RESERVED2; /*!< Reserved, 0x0C */ + __IO uint32_t INIT; /*!< Initial CRC value register, Address offset: 0x10 */ + __IO uint32_t POL; /*!< CRC polynomial register, Address offset: 0x14 */ +} CRC_TypeDef; + +/** + * @brief Digital to Analog Converter + */ + +typedef struct +{ + __IO uint32_t CR; /*!< DAC control register, Address offset: 0x00 */ + __IO uint32_t SWTRIGR; /*!< DAC software trigger register, Address offset: 0x04 */ + __IO uint32_t DHR12R1; /*!< DAC channel1 12-bit right-aligned data holding register, Address offset: 0x08 */ + __IO uint32_t DHR12L1; /*!< DAC channel1 12-bit left aligned data holding register, Address offset: 0x0C */ + __IO uint32_t DHR8R1; /*!< DAC channel1 8-bit right aligned data holding register, Address offset: 0x10 */ + __IO uint32_t DHR12R2; /*!< DAC channel2 12-bit right aligned data holding register, Address offset: 0x14 */ + __IO uint32_t DHR12L2; /*!< DAC channel2 12-bit left aligned data holding register, Address offset: 0x18 */ + __IO uint32_t DHR8R2; /*!< DAC channel2 8-bit right-aligned data holding register, Address offset: 0x1C */ + __IO uint32_t DHR12RD; /*!< Dual DAC 12-bit right-aligned data holding register, Address offset: 0x20 */ + __IO uint32_t DHR12LD; /*!< DUAL DAC 12-bit left aligned data holding register, Address offset: 0x24 */ + __IO uint32_t DHR8RD; /*!< DUAL DAC 8-bit right aligned data holding register, Address offset: 0x28 */ + __IO uint32_t DOR1; /*!< DAC channel1 data output register, Address offset: 0x2C */ + __IO uint32_t DOR2; /*!< DAC channel2 data output register, Address offset: 0x30 */ + __IO uint32_t SR; /*!< DAC status register, Address offset: 0x34 */ + __IO uint32_t CCR; /*!< DAC calibration control register, Address offset: 0x38 */ + __IO uint32_t MCR; /*!< DAC mode control register, Address offset: 0x3C */ + __IO uint32_t SHSR1; /*!< DAC Sample and Hold sample time register 1, Address offset: 0x40 */ + __IO uint32_t SHSR2; /*!< DAC Sample and Hold sample time register 2, Address offset: 0x44 */ + __IO uint32_t SHHR; /*!< DAC Sample and Hold hold time register, Address offset: 0x48 */ + __IO uint32_t SHRR; /*!< DAC Sample and Hold refresh time register, Address offset: 0x4C */ +} DAC_TypeDef; + +/** + * @brief DFSDM module registers + */ +typedef struct +{ + __IO uint32_t FLTCR1; /*!< DFSDM control register1, Address offset: 0x100 */ + __IO uint32_t FLTCR2; /*!< DFSDM control register2, Address offset: 0x104 */ + __IO uint32_t FLTISR; /*!< DFSDM interrupt and status register, Address offset: 0x108 */ + __IO uint32_t FLTICR; /*!< DFSDM interrupt flag clear register, Address offset: 0x10C */ + __IO uint32_t FLTJCHGR; /*!< DFSDM injected channel group selection register, Address offset: 0x110 */ + __IO uint32_t FLTFCR; /*!< DFSDM filter control register, Address offset: 0x114 */ + __IO uint32_t FLTJDATAR; /*!< DFSDM data register for injected group, Address offset: 0x118 */ + __IO uint32_t FLTRDATAR; /*!< DFSDM data register for regular group, Address offset: 0x11C */ + __IO uint32_t FLTAWHTR; /*!< DFSDM analog watchdog high threshold register, Address offset: 0x120 */ + __IO uint32_t FLTAWLTR; /*!< DFSDM analog watchdog low threshold register, Address offset: 0x124 */ + __IO uint32_t FLTAWSR; /*!< DFSDM analog watchdog status register Address offset: 0x128 */ + __IO uint32_t FLTAWCFR; /*!< DFSDM analog watchdog clear flag register Address offset: 0x12C */ + __IO uint32_t FLTEXMAX; /*!< DFSDM extreme detector maximum register, Address offset: 0x130 */ + __IO uint32_t FLTEXMIN; /*!< DFSDM extreme detector minimum register Address offset: 0x134 */ + __IO uint32_t FLTCNVTIMR; /*!< DFSDM conversion timer, Address offset: 0x138 */ +} DFSDM_Filter_TypeDef; + +/** + * @brief DFSDM channel configuration registers + */ +typedef struct +{ + __IO uint32_t CHCFGR1; /*!< DFSDM channel configuration register1, Address offset: 0x00 */ + __IO uint32_t CHCFGR2; /*!< DFSDM channel configuration register2, Address offset: 0x04 */ + __IO uint32_t CHAWSCDR; /*!< DFSDM channel analog watchdog and + short circuit detector register, Address offset: 0x08 */ + __IO uint32_t CHWDATAR; /*!< DFSDM channel watchdog filter data register, Address offset: 0x0C */ + __IO uint32_t CHDATINR; /*!< DFSDM channel data input register, Address offset: 0x10 */ +} DFSDM_Channel_TypeDef; + +/** + * @brief Debug MCU + */ + +typedef struct +{ + __IO uint32_t IDCODE; /*!< MCU device ID code, Address offset: 0x00 */ + __IO uint32_t CR; /*!< Debug MCU configuration register, Address offset: 0x04 */ + __IO uint32_t APB1FZR1; /*!< Debug MCU APB1 freeze register 1, Address offset: 0x08 */ + __IO uint32_t APB1FZR2; /*!< Debug MCU APB1 freeze register 2, Address offset: 0x0C */ + __IO uint32_t APB2FZ; /*!< Debug MCU APB2 freeze register, Address offset: 0x10 */ +} DBGMCU_TypeDef; + + +/** + * @brief DMA Controller + */ + +typedef struct +{ + __IO uint32_t CCR; /*!< DMA channel x configuration register */ + __IO uint32_t CNDTR; /*!< DMA channel x number of data register */ + __IO uint32_t CPAR; /*!< DMA channel x peripheral address register */ + __IO uint32_t CMAR; /*!< DMA channel x memory address register */ +} DMA_Channel_TypeDef; + +typedef struct +{ + __IO uint32_t ISR; /*!< DMA interrupt status register, Address offset: 0x00 */ + __IO uint32_t IFCR; /*!< DMA interrupt flag clear register, Address offset: 0x04 */ +} DMA_TypeDef; + +typedef struct +{ + __IO uint32_t CSELR; /*!< DMA channel selection register */ +} DMA_Request_TypeDef; + +/* Legacy define */ +#define DMA_request_TypeDef DMA_Request_TypeDef + + +/** + * @brief External Interrupt/Event Controller + */ + +typedef struct +{ + __IO uint32_t IMR1; /*!< EXTI Interrupt mask register 1, Address offset: 0x00 */ + __IO uint32_t EMR1; /*!< EXTI Event mask register 1, Address offset: 0x04 */ + __IO uint32_t RTSR1; /*!< EXTI Rising trigger selection register 1, Address offset: 0x08 */ + __IO uint32_t FTSR1; /*!< EXTI Falling trigger selection register 1, Address offset: 0x0C */ + __IO uint32_t SWIER1; /*!< EXTI Software interrupt event register 1, Address offset: 0x10 */ + __IO uint32_t PR1; /*!< EXTI Pending register 1, Address offset: 0x14 */ + uint32_t RESERVED1; /*!< Reserved, 0x18 */ + uint32_t RESERVED2; /*!< Reserved, 0x1C */ + __IO uint32_t IMR2; /*!< EXTI Interrupt mask register 2, Address offset: 0x20 */ + __IO uint32_t EMR2; /*!< EXTI Event mask register 2, Address offset: 0x24 */ + __IO uint32_t RTSR2; /*!< EXTI Rising trigger selection register 2, Address offset: 0x28 */ + __IO uint32_t FTSR2; /*!< EXTI Falling trigger selection register 2, Address offset: 0x2C */ + __IO uint32_t SWIER2; /*!< EXTI Software interrupt event register 2, Address offset: 0x30 */ + __IO uint32_t PR2; /*!< EXTI Pending register 2, Address offset: 0x34 */ +} EXTI_TypeDef; + + +/** + * @brief Firewall + */ + +typedef struct +{ + __IO uint32_t CSSA; /*!< Code Segment Start Address register, Address offset: 0x00 */ + __IO uint32_t CSL; /*!< Code Segment Length register, Address offset: 0x04 */ + __IO uint32_t NVDSSA; /*!< NON volatile data Segment Start Address register, Address offset: 0x08 */ + __IO uint32_t NVDSL; /*!< NON volatile data Segment Length register, Address offset: 0x0C */ + __IO uint32_t VDSSA ; /*!< Volatile data Segment Start Address register, Address offset: 0x10 */ + __IO uint32_t VDSL ; /*!< Volatile data Segment Length register, Address offset: 0x14 */ + uint32_t RESERVED1; /*!< Reserved1, Address offset: 0x18 */ + uint32_t RESERVED2; /*!< Reserved2, Address offset: 0x1C */ + __IO uint32_t CR ; /*!< Configuration register, Address offset: 0x20 */ +} FIREWALL_TypeDef; + + +/** + * @brief FLASH Registers + */ + +typedef struct +{ + __IO uint32_t ACR; /*!< FLASH access control register, Address offset: 0x00 */ + __IO uint32_t PDKEYR; /*!< FLASH power down key register, Address offset: 0x04 */ + __IO uint32_t KEYR; /*!< FLASH key register, Address offset: 0x08 */ + __IO uint32_t OPTKEYR; /*!< FLASH option key register, Address offset: 0x0C */ + __IO uint32_t SR; /*!< FLASH status register, Address offset: 0x10 */ + __IO uint32_t CR; /*!< FLASH control register, Address offset: 0x14 */ + __IO uint32_t ECCR; /*!< FLASH ECC register, Address offset: 0x18 */ + __IO uint32_t RESERVED1; /*!< Reserved1, Address offset: 0x1C */ + __IO uint32_t OPTR; /*!< FLASH option register, Address offset: 0x20 */ + __IO uint32_t PCROP1SR; /*!< FLASH bank1 PCROP start address register, Address offset: 0x24 */ + __IO uint32_t PCROP1ER; /*!< FLASH bank1 PCROP end address register, Address offset: 0x28 */ + __IO uint32_t WRP1AR; /*!< FLASH bank1 WRP area A address register, Address offset: 0x2C */ + __IO uint32_t WRP1BR; /*!< FLASH bank1 WRP area B address register, Address offset: 0x30 */ + uint32_t RESERVED2[4]; /*!< Reserved2, Address offset: 0x34-0x40 */ + __IO uint32_t PCROP2SR; /*!< FLASH bank2 PCROP start address register, Address offset: 0x44 */ + __IO uint32_t PCROP2ER; /*!< FLASH bank2 PCROP end address register, Address offset: 0x48 */ + __IO uint32_t WRP2AR; /*!< FLASH bank2 WRP area A address register, Address offset: 0x4C */ + __IO uint32_t WRP2BR; /*!< FLASH bank2 WRP area B address register, Address offset: 0x50 */ +} FLASH_TypeDef; + + +/** + * @brief Flexible Memory Controller + */ + +typedef struct +{ + __IO uint32_t BTCR[8]; /*!< NOR/PSRAM chip-select control register(BCR) and chip-select timing register(BTR), Address offset: 0x00-1C */ +} FMC_Bank1_TypeDef; + +/** + * @brief Flexible Memory Controller Bank1E + */ + +typedef struct +{ + __IO uint32_t BWTR[7]; /*!< NOR/PSRAM write timing registers, Address offset: 0x104-0x11C */ +} FMC_Bank1E_TypeDef; + +/** + * @brief Flexible Memory Controller Bank3 + */ + +typedef struct +{ + __IO uint32_t PCR; /*!< NAND Flash control register, Address offset: 0x80 */ + __IO uint32_t SR; /*!< NAND Flash FIFO status and interrupt register, Address offset: 0x84 */ + __IO uint32_t PMEM; /*!< NAND Flash Common memory space timing register, Address offset: 0x88 */ + __IO uint32_t PATT; /*!< NAND Flash Attribute memory space timing register, Address offset: 0x8C */ + uint32_t RESERVED0; /*!< Reserved, 0x90 */ + __IO uint32_t ECCR; /*!< NAND Flash ECC result registers, Address offset: 0x94 */ +} FMC_Bank3_TypeDef; + +/** + * @brief General Purpose I/O + */ + +typedef struct +{ + __IO uint32_t MODER; /*!< GPIO port mode register, Address offset: 0x00 */ + __IO uint32_t OTYPER; /*!< GPIO port output type register, Address offset: 0x04 */ + __IO uint32_t OSPEEDR; /*!< GPIO port output speed register, Address offset: 0x08 */ + __IO uint32_t PUPDR; /*!< GPIO port pull-up/pull-down register, Address offset: 0x0C */ + __IO uint32_t IDR; /*!< GPIO port input data register, Address offset: 0x10 */ + __IO uint32_t ODR; /*!< GPIO port output data register, Address offset: 0x14 */ + __IO uint32_t BSRR; /*!< GPIO port bit set/reset register, Address offset: 0x18 */ + __IO uint32_t LCKR; /*!< GPIO port configuration lock register, Address offset: 0x1C */ + __IO uint32_t AFR[2]; /*!< GPIO alternate function registers, Address offset: 0x20-0x24 */ + __IO uint32_t BRR; /*!< GPIO Bit Reset register, Address offset: 0x28 */ + __IO uint32_t ASCR; /*!< GPIO analog switch control register, Address offset: 0x2C */ + +} GPIO_TypeDef; + + +/** + * @brief Inter-integrated Circuit Interface + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< I2C Control register 1, Address offset: 0x00 */ + __IO uint32_t CR2; /*!< I2C Control register 2, Address offset: 0x04 */ + __IO uint32_t OAR1; /*!< I2C Own address 1 register, Address offset: 0x08 */ + __IO uint32_t OAR2; /*!< I2C Own address 2 register, Address offset: 0x0C */ + __IO uint32_t TIMINGR; /*!< I2C Timing register, Address offset: 0x10 */ + __IO uint32_t TIMEOUTR; /*!< I2C Timeout register, Address offset: 0x14 */ + __IO uint32_t ISR; /*!< I2C Interrupt and status register, Address offset: 0x18 */ + __IO uint32_t ICR; /*!< I2C Interrupt clear register, Address offset: 0x1C */ + __IO uint32_t PECR; /*!< I2C PEC register, Address offset: 0x20 */ + __IO uint32_t RXDR; /*!< I2C Receive data register, Address offset: 0x24 */ + __IO uint32_t TXDR; /*!< I2C Transmit data register, Address offset: 0x28 */ +} I2C_TypeDef; + +/** + * @brief Independent WATCHDOG + */ + +typedef struct +{ + __IO uint32_t KR; /*!< IWDG Key register, Address offset: 0x00 */ + __IO uint32_t PR; /*!< IWDG Prescaler register, Address offset: 0x04 */ + __IO uint32_t RLR; /*!< IWDG Reload register, Address offset: 0x08 */ + __IO uint32_t SR; /*!< IWDG Status register, Address offset: 0x0C */ + __IO uint32_t WINR; /*!< IWDG Window register, Address offset: 0x10 */ +} IWDG_TypeDef; + +/** + * @brief LCD + */ + +typedef struct +{ + __IO uint32_t CR; /*!< LCD control register, Address offset: 0x00 */ + __IO uint32_t FCR; /*!< LCD frame control register, Address offset: 0x04 */ + __IO uint32_t SR; /*!< LCD status register, Address offset: 0x08 */ + __IO uint32_t CLR; /*!< LCD clear register, Address offset: 0x0C */ + uint32_t RESERVED; /*!< Reserved, Address offset: 0x10 */ + __IO uint32_t RAM[16]; /*!< LCD display memory, Address offset: 0x14-0x50 */ +} LCD_TypeDef; + +/** + * @brief LPTIMER + */ +typedef struct +{ + __IO uint32_t ISR; /*!< LPTIM Interrupt and Status register, Address offset: 0x00 */ + __IO uint32_t ICR; /*!< LPTIM Interrupt Clear register, Address offset: 0x04 */ + __IO uint32_t IER; /*!< LPTIM Interrupt Enable register, Address offset: 0x08 */ + __IO uint32_t CFGR; /*!< LPTIM Configuration register, Address offset: 0x0C */ + __IO uint32_t CR; /*!< LPTIM Control register, Address offset: 0x10 */ + __IO uint32_t CMP; /*!< LPTIM Compare register, Address offset: 0x14 */ + __IO uint32_t ARR; /*!< LPTIM Autoreload register, Address offset: 0x18 */ + __IO uint32_t CNT; /*!< LPTIM Counter register, Address offset: 0x1C */ + __IO uint32_t OR; /*!< LPTIM Option register, Address offset: 0x20 */ +} LPTIM_TypeDef; + +/** + * @brief Operational Amplifier (OPAMP) + */ + +typedef struct +{ + __IO uint32_t CSR; /*!< OPAMP control/status register, Address offset: 0x00 */ + __IO uint32_t OTR; /*!< OPAMP offset trimming register for normal mode, Address offset: 0x04 */ + __IO uint32_t LPOTR; /*!< OPAMP offset trimming register for low power mode, Address offset: 0x08 */ +} OPAMP_TypeDef; + +typedef struct +{ + __IO uint32_t CSR; /*!< OPAMP control/status register, used for bits common to several OPAMP instances, Address offset: 0x00 */ +} OPAMP_Common_TypeDef; + +/** + * @brief Power Control + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< PWR power control register 1, Address offset: 0x00 */ + __IO uint32_t CR2; /*!< PWR power control register 2, Address offset: 0x04 */ + __IO uint32_t CR3; /*!< PWR power control register 3, Address offset: 0x08 */ + __IO uint32_t CR4; /*!< PWR power control register 4, Address offset: 0x0C */ + __IO uint32_t SR1; /*!< PWR power status register 1, Address offset: 0x10 */ + __IO uint32_t SR2; /*!< PWR power status register 2, Address offset: 0x14 */ + __IO uint32_t SCR; /*!< PWR power status reset register, Address offset: 0x18 */ + uint32_t RESERVED; /*!< Reserved, Address offset: 0x1C */ + __IO uint32_t PUCRA; /*!< Pull_up control register of portA, Address offset: 0x20 */ + __IO uint32_t PDCRA; /*!< Pull_Down control register of portA, Address offset: 0x24 */ + __IO uint32_t PUCRB; /*!< Pull_up control register of portB, Address offset: 0x28 */ + __IO uint32_t PDCRB; /*!< Pull_Down control register of portB, Address offset: 0x2C */ + __IO uint32_t PUCRC; /*!< Pull_up control register of portC, Address offset: 0x30 */ + __IO uint32_t PDCRC; /*!< Pull_Down control register of portC, Address offset: 0x34 */ + __IO uint32_t PUCRD; /*!< Pull_up control register of portD, Address offset: 0x38 */ + __IO uint32_t PDCRD; /*!< Pull_Down control register of portD, Address offset: 0x3C */ + __IO uint32_t PUCRE; /*!< Pull_up control register of portE, Address offset: 0x40 */ + __IO uint32_t PDCRE; /*!< Pull_Down control register of portE, Address offset: 0x44 */ + __IO uint32_t PUCRF; /*!< Pull_up control register of portF, Address offset: 0x48 */ + __IO uint32_t PDCRF; /*!< Pull_Down control register of portF, Address offset: 0x4C */ + __IO uint32_t PUCRG; /*!< Pull_up control register of portG, Address offset: 0x50 */ + __IO uint32_t PDCRG; /*!< Pull_Down control register of portG, Address offset: 0x54 */ + __IO uint32_t PUCRH; /*!< Pull_up control register of portH, Address offset: 0x58 */ + __IO uint32_t PDCRH; /*!< Pull_Down control register of portH, Address offset: 0x5C */ +} PWR_TypeDef; + + +/** + * @brief QUAD Serial Peripheral Interface + */ + +typedef struct +{ + __IO uint32_t CR; /*!< QUADSPI Control register, Address offset: 0x00 */ + __IO uint32_t DCR; /*!< QUADSPI Device Configuration register, Address offset: 0x04 */ + __IO uint32_t SR; /*!< QUADSPI Status register, Address offset: 0x08 */ + __IO uint32_t FCR; /*!< QUADSPI Flag Clear register, Address offset: 0x0C */ + __IO uint32_t DLR; /*!< QUADSPI Data Length register, Address offset: 0x10 */ + __IO uint32_t CCR; /*!< QUADSPI Communication Configuration register, Address offset: 0x14 */ + __IO uint32_t AR; /*!< QUADSPI Address register, Address offset: 0x18 */ + __IO uint32_t ABR; /*!< QUADSPI Alternate Bytes register, Address offset: 0x1C */ + __IO uint32_t DR; /*!< QUADSPI Data register, Address offset: 0x20 */ + __IO uint32_t PSMKR; /*!< QUADSPI Polling Status Mask register, Address offset: 0x24 */ + __IO uint32_t PSMAR; /*!< QUADSPI Polling Status Match register, Address offset: 0x28 */ + __IO uint32_t PIR; /*!< QUADSPI Polling Interval register, Address offset: 0x2C */ + __IO uint32_t LPTR; /*!< QUADSPI Low Power Timeout register, Address offset: 0x30 */ +} QUADSPI_TypeDef; + + +/** + * @brief Reset and Clock Control + */ + +typedef struct +{ + __IO uint32_t CR; /*!< RCC clock control register, Address offset: 0x00 */ + __IO uint32_t ICSCR; /*!< RCC internal clock sources calibration register, Address offset: 0x04 */ + __IO uint32_t CFGR; /*!< RCC clock configuration register, Address offset: 0x08 */ + __IO uint32_t PLLCFGR; /*!< RCC system PLL configuration register, Address offset: 0x0C */ + __IO uint32_t PLLSAI1CFGR; /*!< RCC PLL SAI1 configuration register, Address offset: 0x10 */ + __IO uint32_t PLLSAI2CFGR; /*!< RCC PLL SAI2 configuration register, Address offset: 0x14 */ + __IO uint32_t CIER; /*!< RCC clock interrupt enable register, Address offset: 0x18 */ + __IO uint32_t CIFR; /*!< RCC clock interrupt flag register, Address offset: 0x1C */ + __IO uint32_t CICR; /*!< RCC clock interrupt clear register, Address offset: 0x20 */ + uint32_t RESERVED0; /*!< Reserved, Address offset: 0x24 */ + __IO uint32_t AHB1RSTR; /*!< RCC AHB1 peripheral reset register, Address offset: 0x28 */ + __IO uint32_t AHB2RSTR; /*!< RCC AHB2 peripheral reset register, Address offset: 0x2C */ + __IO uint32_t AHB3RSTR; /*!< RCC AHB3 peripheral reset register, Address offset: 0x30 */ + uint32_t RESERVED1; /*!< Reserved, Address offset: 0x34 */ + __IO uint32_t APB1RSTR1; /*!< RCC APB1 peripheral reset register 1, Address offset: 0x38 */ + __IO uint32_t APB1RSTR2; /*!< RCC APB1 peripheral reset register 2, Address offset: 0x3C */ + __IO uint32_t APB2RSTR; /*!< RCC APB2 peripheral reset register, Address offset: 0x40 */ + uint32_t RESERVED2; /*!< Reserved, Address offset: 0x44 */ + __IO uint32_t AHB1ENR; /*!< RCC AHB1 peripheral clocks enable register, Address offset: 0x48 */ + __IO uint32_t AHB2ENR; /*!< RCC AHB2 peripheral clocks enable register, Address offset: 0x4C */ + __IO uint32_t AHB3ENR; /*!< RCC AHB3 peripheral clocks enable register, Address offset: 0x50 */ + uint32_t RESERVED3; /*!< Reserved, Address offset: 0x54 */ + __IO uint32_t APB1ENR1; /*!< RCC APB1 peripheral clocks enable register 1, Address offset: 0x58 */ + __IO uint32_t APB1ENR2; /*!< RCC APB1 peripheral clocks enable register 2, Address offset: 0x5C */ + __IO uint32_t APB2ENR; /*!< RCC APB2 peripheral clocks enable register, Address offset: 0x60 */ + uint32_t RESERVED4; /*!< Reserved, Address offset: 0x64 */ + __IO uint32_t AHB1SMENR; /*!< RCC AHB1 peripheral clocks enable in sleep and stop modes register, Address offset: 0x68 */ + __IO uint32_t AHB2SMENR; /*!< RCC AHB2 peripheral clocks enable in sleep and stop modes register, Address offset: 0x6C */ + __IO uint32_t AHB3SMENR; /*!< RCC AHB3 peripheral clocks enable in sleep and stop modes register, Address offset: 0x70 */ + uint32_t RESERVED5; /*!< Reserved, Address offset: 0x74 */ + __IO uint32_t APB1SMENR1; /*!< RCC APB1 peripheral clocks enable in sleep mode and stop modes register 1, Address offset: 0x78 */ + __IO uint32_t APB1SMENR2; /*!< RCC APB1 peripheral clocks enable in sleep mode and stop modes register 2, Address offset: 0x7C */ + __IO uint32_t APB2SMENR; /*!< RCC APB2 peripheral clocks enable in sleep mode and stop modes register, Address offset: 0x80 */ + uint32_t RESERVED6; /*!< Reserved, Address offset: 0x84 */ + __IO uint32_t CCIPR; /*!< RCC peripherals independent clock configuration register, Address offset: 0x88 */ + uint32_t RESERVED7; /*!< Reserved, Address offset: 0x8C */ + __IO uint32_t BDCR; /*!< RCC backup domain control register, Address offset: 0x90 */ + __IO uint32_t CSR; /*!< RCC clock control & status register, Address offset: 0x94 */ +} RCC_TypeDef; + +/** + * @brief Real-Time Clock + */ + +typedef struct +{ + __IO uint32_t TR; /*!< RTC time register, Address offset: 0x00 */ + __IO uint32_t DR; /*!< RTC date register, Address offset: 0x04 */ + __IO uint32_t CR; /*!< RTC control register, Address offset: 0x08 */ + __IO uint32_t ISR; /*!< RTC initialization and status register, Address offset: 0x0C */ + __IO uint32_t PRER; /*!< RTC prescaler register, Address offset: 0x10 */ + __IO uint32_t WUTR; /*!< RTC wakeup timer register, Address offset: 0x14 */ + uint32_t reserved; /*!< Reserved */ + __IO uint32_t ALRMAR; /*!< RTC alarm A register, Address offset: 0x1C */ + __IO uint32_t ALRMBR; /*!< RTC alarm B register, Address offset: 0x20 */ + __IO uint32_t WPR; /*!< RTC write protection register, Address offset: 0x24 */ + __IO uint32_t SSR; /*!< RTC sub second register, Address offset: 0x28 */ + __IO uint32_t SHIFTR; /*!< RTC shift control register, Address offset: 0x2C */ + __IO uint32_t TSTR; /*!< RTC time stamp time register, Address offset: 0x30 */ + __IO uint32_t TSDR; /*!< RTC time stamp date register, Address offset: 0x34 */ + __IO uint32_t TSSSR; /*!< RTC time-stamp sub second register, Address offset: 0x38 */ + __IO uint32_t CALR; /*!< RTC calibration register, Address offset: 0x3C */ + __IO uint32_t TAMPCR; /*!< RTC tamper configuration register, Address offset: 0x40 */ + __IO uint32_t ALRMASSR; /*!< RTC alarm A sub second register, Address offset: 0x44 */ + __IO uint32_t ALRMBSSR; /*!< RTC alarm B sub second register, Address offset: 0x48 */ + __IO uint32_t OR; /*!< RTC option register, Address offset: 0x4C */ + __IO uint32_t BKP0R; /*!< RTC backup register 0, Address offset: 0x50 */ + __IO uint32_t BKP1R; /*!< RTC backup register 1, Address offset: 0x54 */ + __IO uint32_t BKP2R; /*!< RTC backup register 2, Address offset: 0x58 */ + __IO uint32_t BKP3R; /*!< RTC backup register 3, Address offset: 0x5C */ + __IO uint32_t BKP4R; /*!< RTC backup register 4, Address offset: 0x60 */ + __IO uint32_t BKP5R; /*!< RTC backup register 5, Address offset: 0x64 */ + __IO uint32_t BKP6R; /*!< RTC backup register 6, Address offset: 0x68 */ + __IO uint32_t BKP7R; /*!< RTC backup register 7, Address offset: 0x6C */ + __IO uint32_t BKP8R; /*!< RTC backup register 8, Address offset: 0x70 */ + __IO uint32_t BKP9R; /*!< RTC backup register 9, Address offset: 0x74 */ + __IO uint32_t BKP10R; /*!< RTC backup register 10, Address offset: 0x78 */ + __IO uint32_t BKP11R; /*!< RTC backup register 11, Address offset: 0x7C */ + __IO uint32_t BKP12R; /*!< RTC backup register 12, Address offset: 0x80 */ + __IO uint32_t BKP13R; /*!< RTC backup register 13, Address offset: 0x84 */ + __IO uint32_t BKP14R; /*!< RTC backup register 14, Address offset: 0x88 */ + __IO uint32_t BKP15R; /*!< RTC backup register 15, Address offset: 0x8C */ + __IO uint32_t BKP16R; /*!< RTC backup register 16, Address offset: 0x90 */ + __IO uint32_t BKP17R; /*!< RTC backup register 17, Address offset: 0x94 */ + __IO uint32_t BKP18R; /*!< RTC backup register 18, Address offset: 0x98 */ + __IO uint32_t BKP19R; /*!< RTC backup register 19, Address offset: 0x9C */ + __IO uint32_t BKP20R; /*!< RTC backup register 20, Address offset: 0xA0 */ + __IO uint32_t BKP21R; /*!< RTC backup register 21, Address offset: 0xA4 */ + __IO uint32_t BKP22R; /*!< RTC backup register 22, Address offset: 0xA8 */ + __IO uint32_t BKP23R; /*!< RTC backup register 23, Address offset: 0xAC */ + __IO uint32_t BKP24R; /*!< RTC backup register 24, Address offset: 0xB0 */ + __IO uint32_t BKP25R; /*!< RTC backup register 25, Address offset: 0xB4 */ + __IO uint32_t BKP26R; /*!< RTC backup register 26, Address offset: 0xB8 */ + __IO uint32_t BKP27R; /*!< RTC backup register 27, Address offset: 0xBC */ + __IO uint32_t BKP28R; /*!< RTC backup register 28, Address offset: 0xC0 */ + __IO uint32_t BKP29R; /*!< RTC backup register 29, Address offset: 0xC4 */ + __IO uint32_t BKP30R; /*!< RTC backup register 30, Address offset: 0xC8 */ + __IO uint32_t BKP31R; /*!< RTC backup register 31, Address offset: 0xCC */ +} RTC_TypeDef; + + +/** + * @brief Serial Audio Interface + */ + +typedef struct +{ + __IO uint32_t GCR; /*!< SAI global configuration register, Address offset: 0x00 */ +} SAI_TypeDef; + +typedef struct +{ + __IO uint32_t CR1; /*!< SAI block x configuration register 1, Address offset: 0x04 */ + __IO uint32_t CR2; /*!< SAI block x configuration register 2, Address offset: 0x08 */ + __IO uint32_t FRCR; /*!< SAI block x frame configuration register, Address offset: 0x0C */ + __IO uint32_t SLOTR; /*!< SAI block x slot register, Address offset: 0x10 */ + __IO uint32_t IMR; /*!< SAI block x interrupt mask register, Address offset: 0x14 */ + __IO uint32_t SR; /*!< SAI block x status register, Address offset: 0x18 */ + __IO uint32_t CLRFR; /*!< SAI block x clear flag register, Address offset: 0x1C */ + __IO uint32_t DR; /*!< SAI block x data register, Address offset: 0x20 */ +} SAI_Block_TypeDef; + + +/** + * @brief Secure digital input/output Interface + */ + +typedef struct +{ + __IO uint32_t POWER; /*!< SDMMC power control register, Address offset: 0x00 */ + __IO uint32_t CLKCR; /*!< SDMMC clock control register, Address offset: 0x04 */ + __IO uint32_t ARG; /*!< SDMMC argument register, Address offset: 0x08 */ + __IO uint32_t CMD; /*!< SDMMC command register, Address offset: 0x0C */ + __I uint32_t RESPCMD; /*!< SDMMC command response register, Address offset: 0x10 */ + __I uint32_t RESP1; /*!< SDMMC response 1 register, Address offset: 0x14 */ + __I uint32_t RESP2; /*!< SDMMC response 2 register, Address offset: 0x18 */ + __I uint32_t RESP3; /*!< SDMMC response 3 register, Address offset: 0x1C */ + __I uint32_t RESP4; /*!< SDMMC response 4 register, Address offset: 0x20 */ + __IO uint32_t DTIMER; /*!< SDMMC data timer register, Address offset: 0x24 */ + __IO uint32_t DLEN; /*!< SDMMC data length register, Address offset: 0x28 */ + __IO uint32_t DCTRL; /*!< SDMMC data control register, Address offset: 0x2C */ + __I uint32_t DCOUNT; /*!< SDMMC data counter register, Address offset: 0x30 */ + __I uint32_t STA; /*!< SDMMC status register, Address offset: 0x34 */ + __IO uint32_t ICR; /*!< SDMMC interrupt clear register, Address offset: 0x38 */ + __IO uint32_t MASK; /*!< SDMMC mask register, Address offset: 0x3C */ + uint32_t RESERVED0[2]; /*!< Reserved, 0x40-0x44 */ + __I uint32_t FIFOCNT; /*!< SDMMC FIFO counter register, Address offset: 0x48 */ + uint32_t RESERVED1[13]; /*!< Reserved, 0x4C-0x7C */ + __IO uint32_t FIFO; /*!< SDMMC data FIFO register, Address offset: 0x80 */ +} SDMMC_TypeDef; + + +/** + * @brief Serial Peripheral Interface + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< SPI Control register 1, Address offset: 0x00 */ + __IO uint32_t CR2; /*!< SPI Control register 2, Address offset: 0x04 */ + __IO uint32_t SR; /*!< SPI Status register, Address offset: 0x08 */ + __IO uint32_t DR; /*!< SPI data register, Address offset: 0x0C */ + __IO uint32_t CRCPR; /*!< SPI CRC polynomial register, Address offset: 0x10 */ + __IO uint32_t RXCRCR; /*!< SPI Rx CRC register, Address offset: 0x14 */ + __IO uint32_t TXCRCR; /*!< SPI Tx CRC register, Address offset: 0x18 */ +} SPI_TypeDef; + + +/** + * @brief Single Wire Protocol Master Interface SPWMI + */ + +typedef struct +{ + __IO uint32_t CR; /*!< SWPMI Configuration/Control register, Address offset: 0x00 */ + __IO uint32_t BRR; /*!< SWPMI bitrate register, Address offset: 0x04 */ + uint32_t RESERVED1; /*!< Reserved, 0x08 */ + __IO uint32_t ISR; /*!< SWPMI Interrupt and Status register, Address offset: 0x0C */ + __IO uint32_t ICR; /*!< SWPMI Interrupt Flag Clear register, Address offset: 0x10 */ + __IO uint32_t IER; /*!< SWPMI Interrupt Enable register, Address offset: 0x14 */ + __IO uint32_t RFL; /*!< SWPMI Receive Frame Length register, Address offset: 0x18 */ + __IO uint32_t TDR; /*!< SWPMI Transmit data register, Address offset: 0x1C */ + __IO uint32_t RDR; /*!< SWPMI Receive data register, Address offset: 0x20 */ + __IO uint32_t OR; /*!< SWPMI Option register, Address offset: 0x24 */ +} SWPMI_TypeDef; + + +/** + * @brief System configuration controller + */ + +typedef struct +{ + __IO uint32_t MEMRMP; /*!< SYSCFG memory remap register, Address offset: 0x00 */ + __IO uint32_t CFGR1; /*!< SYSCFG configuration register 1, Address offset: 0x04 */ + __IO uint32_t EXTICR[4]; /*!< SYSCFG external interrupt configuration registers, Address offset: 0x08-0x14 */ + __IO uint32_t SCSR; /*!< SYSCFG SRAM2 control and status register, Address offset: 0x18 */ + __IO uint32_t CFGR2; /*!< SYSCFG configuration register 2, Address offset: 0x1C */ + __IO uint32_t SWPR; /*!< SYSCFG SRAM2 write protection register, Address offset: 0x20 */ + __IO uint32_t SKR; /*!< SYSCFG SRAM2 key register, Address offset: 0x24 */ +} SYSCFG_TypeDef; + + +/** + * @brief TIM + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< TIM control register 1, Address offset: 0x00 */ + __IO uint32_t CR2; /*!< TIM control register 2, Address offset: 0x04 */ + __IO uint32_t SMCR; /*!< TIM slave mode control register, Address offset: 0x08 */ + __IO uint32_t DIER; /*!< TIM DMA/interrupt enable register, Address offset: 0x0C */ + __IO uint32_t SR; /*!< TIM status register, Address offset: 0x10 */ + __IO uint32_t EGR; /*!< TIM event generation register, Address offset: 0x14 */ + __IO uint32_t CCMR1; /*!< TIM capture/compare mode register 1, Address offset: 0x18 */ + __IO uint32_t CCMR2; /*!< TIM capture/compare mode register 2, Address offset: 0x1C */ + __IO uint32_t CCER; /*!< TIM capture/compare enable register, Address offset: 0x20 */ + __IO uint32_t CNT; /*!< TIM counter register, Address offset: 0x24 */ + __IO uint32_t PSC; /*!< TIM prescaler, Address offset: 0x28 */ + __IO uint32_t ARR; /*!< TIM auto-reload register, Address offset: 0x2C */ + __IO uint32_t RCR; /*!< TIM repetition counter register, Address offset: 0x30 */ + __IO uint32_t CCR1; /*!< TIM capture/compare register 1, Address offset: 0x34 */ + __IO uint32_t CCR2; /*!< TIM capture/compare register 2, Address offset: 0x38 */ + __IO uint32_t CCR3; /*!< TIM capture/compare register 3, Address offset: 0x3C */ + __IO uint32_t CCR4; /*!< TIM capture/compare register 4, Address offset: 0x40 */ + __IO uint32_t BDTR; /*!< TIM break and dead-time register, Address offset: 0x44 */ + __IO uint32_t DCR; /*!< TIM DMA control register, Address offset: 0x48 */ + __IO uint32_t DMAR; /*!< TIM DMA address for full transfer, Address offset: 0x4C */ + __IO uint32_t OR1; /*!< TIM option register 1, Address offset: 0x50 */ + __IO uint32_t CCMR3; /*!< TIM capture/compare mode register 3, Address offset: 0x54 */ + __IO uint32_t CCR5; /*!< TIM capture/compare register5, Address offset: 0x58 */ + __IO uint32_t CCR6; /*!< TIM capture/compare register6, Address offset: 0x5C */ + __IO uint32_t OR2; /*!< TIM option register 2, Address offset: 0x60 */ + __IO uint32_t OR3; /*!< TIM option register 3, Address offset: 0x64 */ +} TIM_TypeDef; + + +/** + * @brief Touch Sensing Controller (TSC) + */ + +typedef struct +{ + __IO uint32_t CR; /*!< TSC control register, Address offset: 0x00 */ + __IO uint32_t IER; /*!< TSC interrupt enable register, Address offset: 0x04 */ + __IO uint32_t ICR; /*!< TSC interrupt clear register, Address offset: 0x08 */ + __IO uint32_t ISR; /*!< TSC interrupt status register, Address offset: 0x0C */ + __IO uint32_t IOHCR; /*!< TSC I/O hysteresis control register, Address offset: 0x10 */ + uint32_t RESERVED1; /*!< Reserved, Address offset: 0x14 */ + __IO uint32_t IOASCR; /*!< TSC I/O analog switch control register, Address offset: 0x18 */ + uint32_t RESERVED2; /*!< Reserved, Address offset: 0x1C */ + __IO uint32_t IOSCR; /*!< TSC I/O sampling control register, Address offset: 0x20 */ + uint32_t RESERVED3; /*!< Reserved, Address offset: 0x24 */ + __IO uint32_t IOCCR; /*!< TSC I/O channel control register, Address offset: 0x28 */ + uint32_t RESERVED4; /*!< Reserved, Address offset: 0x2C */ + __IO uint32_t IOGCSR; /*!< TSC I/O group control status register, Address offset: 0x30 */ + __IO uint32_t IOGXCR[8]; /*!< TSC I/O group x counter register, Address offset: 0x34-50 */ +} TSC_TypeDef; + +/** + * @brief Universal Synchronous Asynchronous Receiver Transmitter + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< USART Control register 1, Address offset: 0x00 */ + __IO uint32_t CR2; /*!< USART Control register 2, Address offset: 0x04 */ + __IO uint32_t CR3; /*!< USART Control register 3, Address offset: 0x08 */ + __IO uint32_t BRR; /*!< USART Baud rate register, Address offset: 0x0C */ + __IO uint16_t GTPR; /*!< USART Guard time and prescaler register, Address offset: 0x10 */ + uint16_t RESERVED2; /*!< Reserved, 0x12 */ + __IO uint32_t RTOR; /*!< USART Receiver Time Out register, Address offset: 0x14 */ + __IO uint16_t RQR; /*!< USART Request register, Address offset: 0x18 */ + uint16_t RESERVED3; /*!< Reserved, 0x1A */ + __IO uint32_t ISR; /*!< USART Interrupt and status register, Address offset: 0x1C */ + __IO uint32_t ICR; /*!< USART Interrupt flag Clear register, Address offset: 0x20 */ + __IO uint16_t RDR; /*!< USART Receive Data register, Address offset: 0x24 */ + uint16_t RESERVED4; /*!< Reserved, 0x26 */ + __IO uint16_t TDR; /*!< USART Transmit Data register, Address offset: 0x28 */ + uint16_t RESERVED5; /*!< Reserved, 0x2A */ +} USART_TypeDef; + +/** + * @brief VREFBUF + */ + +typedef struct +{ + __IO uint32_t CSR; /*!< VREFBUF control and status register, Address offset: 0x00 */ + __IO uint32_t CCR; /*!< VREFBUF calibration and control register, Address offset: 0x04 */ +} VREFBUF_TypeDef; + +/** + * @brief Window WATCHDOG + */ + +typedef struct +{ + __IO uint32_t CR; /*!< WWDG Control register, Address offset: 0x00 */ + __IO uint32_t CFR; /*!< WWDG Configuration register, Address offset: 0x04 */ + __IO uint32_t SR; /*!< WWDG Status register, Address offset: 0x08 */ +} WWDG_TypeDef; + +/** + * @brief RNG + */ + +typedef struct +{ + __IO uint32_t CR; /*!< RNG control register, Address offset: 0x00 */ + __IO uint32_t SR; /*!< RNG status register, Address offset: 0x04 */ + __IO uint32_t DR; /*!< RNG data register, Address offset: 0x08 */ +} RNG_TypeDef; + +/** + * @brief USB_OTG_Core_register + */ +typedef struct +{ + __IO uint32_t GOTGCTL; /*!< USB_OTG Control and Status Register 000h*/ + __IO uint32_t GOTGINT; /*!< USB_OTG Interrupt Register 004h*/ + __IO uint32_t GAHBCFG; /*!< Core AHB Configuration Register 008h*/ + __IO uint32_t GUSBCFG; /*!< Core USB Configuration Register 00Ch*/ + __IO uint32_t GRSTCTL; /*!< Core Reset Register 010h*/ + __IO uint32_t GINTSTS; /*!< Core Interrupt Register 014h*/ + __IO uint32_t GINTMSK; /*!< Core Interrupt Mask Register 018h*/ + __IO uint32_t GRXSTSR; /*!< Receive Sts Q Read Register 01Ch*/ + __IO uint32_t GRXSTSP; /*!< Receive Sts Q Read & POP Register 020h*/ + __IO uint32_t GRXFSIZ; /* Receive FIFO Size Register 024h*/ + __IO uint32_t DIEPTXF0_HNPTXFSIZ; /*!< EP0 / Non Periodic Tx FIFO Size Register 028h*/ + __IO uint32_t HNPTXSTS; /*!< Non Periodic Tx FIFO/Queue Sts reg 02Ch*/ + uint32_t Reserved30[2]; /* Reserved 030h*/ + __IO uint32_t GCCFG; /* General Purpose IO Register 038h*/ + __IO uint32_t CID; /* User ID Register 03Ch*/ + __IO uint32_t GSNPSID; /* USB_OTG core ID 040h*/ + __IO uint32_t GHWCFG1; /* User HW config1 044h*/ + __IO uint32_t GHWCFG2; /* User HW config2 048h*/ + __IO uint32_t GHWCFG3; /* User HW config3 04Ch*/ + uint32_t Reserved6; /* Reserved 050h*/ + __IO uint32_t GLPMCFG; /* LPM Register 054h*/ + __IO uint32_t GPWRDN; /* Power Down Register 058h*/ + __IO uint32_t GDFIFOCFG; /* DFIFO Software Config Register 05Ch*/ + __IO uint32_t GADPCTL; /* ADP Timer, Control and Status Register 60Ch*/ + uint32_t Reserved43[39]; /* Reserved 058h-0FFh*/ + __IO uint32_t HPTXFSIZ; /* Host Periodic Tx FIFO Size Reg 100h*/ + __IO uint32_t DIEPTXF[0x0F]; /* dev Periodic Transmit FIFO */ +} USB_OTG_GlobalTypeDef; + +/** + * @brief USB_OTG_device_Registers + */ +typedef struct +{ + __IO uint32_t DCFG; /* dev Configuration Register 800h*/ + __IO uint32_t DCTL; /* dev Control Register 804h*/ + __IO uint32_t DSTS; /* dev Status Register (RO) 808h*/ + uint32_t Reserved0C; /* Reserved 80Ch*/ + __IO uint32_t DIEPMSK; /* dev IN Endpoint Mask 810h*/ + __IO uint32_t DOEPMSK; /* dev OUT Endpoint Mask 814h*/ + __IO uint32_t DAINT; /* dev All Endpoints Itr Reg 818h*/ + __IO uint32_t DAINTMSK; /* dev All Endpoints Itr Mask 81Ch*/ + uint32_t Reserved20; /* Reserved 820h*/ + uint32_t Reserved9; /* Reserved 824h*/ + __IO uint32_t DVBUSDIS; /* dev VBUS discharge Register 828h*/ + __IO uint32_t DVBUSPULSE; /* dev VBUS Pulse Register 82Ch*/ + __IO uint32_t DTHRCTL; /* dev thr 830h*/ + __IO uint32_t DIEPEMPMSK; /* dev empty msk 834h*/ + __IO uint32_t DEACHINT; /* dedicated EP interrupt 838h*/ + __IO uint32_t DEACHMSK; /* dedicated EP msk 83Ch*/ + uint32_t Reserved40; /* dedicated EP mask 840h*/ + __IO uint32_t DINEP1MSK; /* dedicated EP mask 844h*/ + uint32_t Reserved44[15]; /* Reserved 844-87Ch*/ + __IO uint32_t DOUTEP1MSK; /* dedicated EP msk 884h*/ +} USB_OTG_DeviceTypeDef; + +/** + * @brief USB_OTG_IN_Endpoint-Specific_Register + */ +typedef struct +{ + __IO uint32_t DIEPCTL; /* dev IN Endpoint Control Reg 900h + (ep_num * 20h) + 00h*/ + uint32_t Reserved04; /* Reserved 900h + (ep_num * 20h) + 04h*/ + __IO uint32_t DIEPINT; /* dev IN Endpoint Itr Reg 900h + (ep_num * 20h) + 08h*/ + uint32_t Reserved0C; /* Reserved 900h + (ep_num * 20h) + 0Ch*/ + __IO uint32_t DIEPTSIZ; /* IN Endpoint Txfer Size 900h + (ep_num * 20h) + 10h*/ + __IO uint32_t DIEPDMA; /* IN Endpoint DMA Address Reg 900h + (ep_num * 20h) + 14h*/ + __IO uint32_t DTXFSTS; /*IN Endpoint Tx FIFO Status Reg 900h + (ep_num * 20h) + 18h*/ + uint32_t Reserved18; /* Reserved 900h+(ep_num*20h)+1Ch-900h+ (ep_num * 20h) + 1Ch*/ +} USB_OTG_INEndpointTypeDef; + +/** + * @brief USB_OTG_OUT_Endpoint-Specific_Registers + */ +typedef struct +{ + __IO uint32_t DOEPCTL; /* dev OUT Endpoint Control Reg B00h + (ep_num * 20h) + 00h*/ + uint32_t Reserved04; /* Reserved B00h + (ep_num * 20h) + 04h*/ + __IO uint32_t DOEPINT; /* dev OUT Endpoint Itr Reg B00h + (ep_num * 20h) + 08h*/ + uint32_t Reserved0C; /* Reserved B00h + (ep_num * 20h) + 0Ch*/ + __IO uint32_t DOEPTSIZ; /* dev OUT Endpoint Txfer Size B00h + (ep_num * 20h) + 10h*/ + __IO uint32_t DOEPDMA; /* dev OUT Endpoint DMA Address B00h + (ep_num * 20h) + 14h*/ + uint32_t Reserved18[2]; /* Reserved B00h + (ep_num * 20h) + 18h - B00h + (ep_num * 20h) + 1Ch*/ +} USB_OTG_OUTEndpointTypeDef; + +/** + * @brief USB_OTG_Host_Mode_Register_Structures + */ +typedef struct +{ + __IO uint32_t HCFG; /* Host Configuration Register 400h*/ + __IO uint32_t HFIR; /* Host Frame Interval Register 404h*/ + __IO uint32_t HFNUM; /* Host Frame Nbr/Frame Remaining 408h*/ + uint32_t Reserved40C; /* Reserved 40Ch*/ + __IO uint32_t HPTXSTS; /* Host Periodic Tx FIFO/ Queue Status 410h*/ + __IO uint32_t HAINT; /* Host All Channels Interrupt Register 414h*/ + __IO uint32_t HAINTMSK; /* Host All Channels Interrupt Mask 418h*/ +} USB_OTG_HostTypeDef; + +/** + * @brief USB_OTG_Host_Channel_Specific_Registers + */ +typedef struct +{ + __IO uint32_t HCCHAR; + __IO uint32_t HCSPLT; + __IO uint32_t HCINT; + __IO uint32_t HCINTMSK; + __IO uint32_t HCTSIZ; + __IO uint32_t HCDMA; + uint32_t Reserved[2]; +} USB_OTG_HostChannelTypeDef; + +/** + * @} + */ + +/** @addtogroup Peripheral_memory_map + * @{ + */ +#define FLASH_BASE ((uint32_t)0x08000000U) /*!< FLASH(up to 1 MB) base address */ +#define SRAM1_BASE ((uint32_t)0x20000000U) /*!< SRAM1(up to 96 KB) base address */ +#define SRAM2_BASE ((uint32_t)0x10000000U) /*!< SRAM2(32 KB) base address */ +#define PERIPH_BASE ((uint32_t)0x40000000U) /*!< Peripheral base address */ +#define FMC_BASE ((uint32_t)0x60000000U) /*!< FMC base address */ +#define QSPI_BASE ((uint32_t)0x90000000U) /*!< QUADSPI memories accessible over AHB base address */ + +#define FMC_R_BASE ((uint32_t)0xA0000000U) /*!< FMC control registers base address */ +#define QSPI_R_BASE ((uint32_t)0xA0001000U) /*!< QUADSPI control registers base address */ +#define SRAM1_BB_BASE ((uint32_t)0x22000000U) /*!< SRAM1(96 KB) base address in the bit-band region */ +#define PERIPH_BB_BASE ((uint32_t)0x42000000U) /*!< Peripheral base address in the bit-band region */ + +/* Legacy defines */ +#define SRAM_BASE SRAM1_BASE +#define SRAM_BB_BASE SRAM1_BB_BASE + +#define SRAM1_SIZE_MAX ((uint32_t)0x00018000U) /*!< maximum SRAM1 size (up to 96 KBytes) */ +#define SRAM2_SIZE ((uint32_t)0x00008000U) /*!< SRAM2 size (32 KBytes) */ + +/*!< Peripheral memory map */ +#define APB1PERIPH_BASE PERIPH_BASE +#define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000U) +#define AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000U) +#define AHB2PERIPH_BASE (PERIPH_BASE + 0x08000000U) + +#define FMC_BANK1 FMC_BASE +#define FMC_BANK1_1 FMC_BANK1 +#define FMC_BANK1_2 (FMC_BANK1 + 0x04000000U) +#define FMC_BANK1_3 (FMC_BANK1 + 0x08000000U) +#define FMC_BANK1_4 (FMC_BANK1 + 0x0C000000U) +#define FMC_BANK3 (FMC_BASE + 0x20000000U) + +/*!< APB1 peripherals */ +#define TIM2_BASE (APB1PERIPH_BASE + 0x0000U) +#define TIM3_BASE (APB1PERIPH_BASE + 0x0400U) +#define TIM4_BASE (APB1PERIPH_BASE + 0x0800U) +#define TIM5_BASE (APB1PERIPH_BASE + 0x0C00U) +#define TIM6_BASE (APB1PERIPH_BASE + 0x1000U) +#define TIM7_BASE (APB1PERIPH_BASE + 0x1400U) +#define LCD_BASE (APB1PERIPH_BASE + 0x2400U) +#define RTC_BASE (APB1PERIPH_BASE + 0x2800U) +#define WWDG_BASE (APB1PERIPH_BASE + 0x2C00U) +#define IWDG_BASE (APB1PERIPH_BASE + 0x3000U) +#define SPI2_BASE (APB1PERIPH_BASE + 0x3800U) +#define SPI3_BASE (APB1PERIPH_BASE + 0x3C00U) +#define USART2_BASE (APB1PERIPH_BASE + 0x4400U) +#define USART3_BASE (APB1PERIPH_BASE + 0x4800U) +#define UART4_BASE (APB1PERIPH_BASE + 0x4C00U) +#define UART5_BASE (APB1PERIPH_BASE + 0x5000U) +#define I2C1_BASE (APB1PERIPH_BASE + 0x5400U) +#define I2C2_BASE (APB1PERIPH_BASE + 0x5800U) +#define I2C3_BASE (APB1PERIPH_BASE + 0x5C00U) +#define CAN1_BASE (APB1PERIPH_BASE + 0x6400U) +#define PWR_BASE (APB1PERIPH_BASE + 0x7000U) +#define DAC_BASE (APB1PERIPH_BASE + 0x7400U) +#define DAC1_BASE (APB1PERIPH_BASE + 0x7400U) +#define OPAMP_BASE (APB1PERIPH_BASE + 0x7800U) +#define OPAMP1_BASE (APB1PERIPH_BASE + 0x7800U) +#define OPAMP2_BASE (APB1PERIPH_BASE + 0x7810U) +#define LPTIM1_BASE (APB1PERIPH_BASE + 0x7C00U) +#define LPUART1_BASE (APB1PERIPH_BASE + 0x8000U) +#define SWPMI1_BASE (APB1PERIPH_BASE + 0x8800U) +#define LPTIM2_BASE (APB1PERIPH_BASE + 0x9400U) + + +/*!< APB2 peripherals */ +#define SYSCFG_BASE (APB2PERIPH_BASE + 0x0000U) +#define VREFBUF_BASE (APB2PERIPH_BASE + 0x0030U) +#define COMP1_BASE (APB2PERIPH_BASE + 0x0200U) +#define COMP2_BASE (APB2PERIPH_BASE + 0x0204U) +#define EXTI_BASE (APB2PERIPH_BASE + 0x0400U) +#define FIREWALL_BASE (APB2PERIPH_BASE + 0x1C00U) +#define SDMMC1_BASE (APB2PERIPH_BASE + 0x2800U) +#define TIM1_BASE (APB2PERIPH_BASE + 0x2C00U) +#define SPI1_BASE (APB2PERIPH_BASE + 0x3000U) +#define TIM8_BASE (APB2PERIPH_BASE + 0x3400U) +#define USART1_BASE (APB2PERIPH_BASE + 0x3800U) +#define TIM15_BASE (APB2PERIPH_BASE + 0x4000U) +#define TIM16_BASE (APB2PERIPH_BASE + 0x4400U) +#define TIM17_BASE (APB2PERIPH_BASE + 0x4800U) +#define SAI1_BASE (APB2PERIPH_BASE + 0x5400U) +#define SAI1_Block_A_BASE (SAI1_BASE + 0x004) +#define SAI1_Block_B_BASE (SAI1_BASE + 0x024) +#define SAI2_BASE (APB2PERIPH_BASE + 0x5800U) +#define SAI2_Block_A_BASE (SAI2_BASE + 0x004) +#define SAI2_Block_B_BASE (SAI2_BASE + 0x024) +#define DFSDM1_BASE (APB2PERIPH_BASE + 0x6000U) +#define DFSDM1_Channel0_BASE (DFSDM1_BASE + 0x00) +#define DFSDM1_Channel1_BASE (DFSDM1_BASE + 0x20) +#define DFSDM1_Channel2_BASE (DFSDM1_BASE + 0x40) +#define DFSDM1_Channel3_BASE (DFSDM1_BASE + 0x60) +#define DFSDM1_Channel4_BASE (DFSDM1_BASE + 0x80) +#define DFSDM1_Channel5_BASE (DFSDM1_BASE + 0xA0) +#define DFSDM1_Channel6_BASE (DFSDM1_BASE + 0xC0) +#define DFSDM1_Channel7_BASE (DFSDM1_BASE + 0xE0) +#define DFSDM1_Filter0_BASE (DFSDM1_BASE + 0x100) +#define DFSDM1_Filter1_BASE (DFSDM1_BASE + 0x180) +#define DFSDM1_Filter2_BASE (DFSDM1_BASE + 0x200) +#define DFSDM1_Filter3_BASE (DFSDM1_BASE + 0x280) + +/*!< AHB1 peripherals */ +#define DMA1_BASE (AHB1PERIPH_BASE) +#define DMA2_BASE (AHB1PERIPH_BASE + 0x0400U) +#define RCC_BASE (AHB1PERIPH_BASE + 0x1000U) +#define FLASH_R_BASE (AHB1PERIPH_BASE + 0x2000U) +#define CRC_BASE (AHB1PERIPH_BASE + 0x3000U) +#define TSC_BASE (AHB1PERIPH_BASE + 0x4000U) + + +#define DMA1_Channel1_BASE (DMA1_BASE + 0x0008U) +#define DMA1_Channel2_BASE (DMA1_BASE + 0x001CU) +#define DMA1_Channel3_BASE (DMA1_BASE + 0x0030U) +#define DMA1_Channel4_BASE (DMA1_BASE + 0x0044U) +#define DMA1_Channel5_BASE (DMA1_BASE + 0x0058U) +#define DMA1_Channel6_BASE (DMA1_BASE + 0x006CU) +#define DMA1_Channel7_BASE (DMA1_BASE + 0x0080U) +#define DMA1_CSELR_BASE (DMA1_BASE + 0x00A8U) + + +#define DMA2_Channel1_BASE (DMA2_BASE + 0x0008U) +#define DMA2_Channel2_BASE (DMA2_BASE + 0x001CU) +#define DMA2_Channel3_BASE (DMA2_BASE + 0x0030U) +#define DMA2_Channel4_BASE (DMA2_BASE + 0x0044U) +#define DMA2_Channel5_BASE (DMA2_BASE + 0x0058U) +#define DMA2_Channel6_BASE (DMA2_BASE + 0x006CU) +#define DMA2_Channel7_BASE (DMA2_BASE + 0x0080U) +#define DMA2_CSELR_BASE (DMA2_BASE + 0x00A8U) + + +/*!< AHB2 peripherals */ +#define GPIOA_BASE (AHB2PERIPH_BASE + 0x0000U) +#define GPIOB_BASE (AHB2PERIPH_BASE + 0x0400U) +#define GPIOC_BASE (AHB2PERIPH_BASE + 0x0800U) +#define GPIOD_BASE (AHB2PERIPH_BASE + 0x0C00U) +#define GPIOE_BASE (AHB2PERIPH_BASE + 0x1000U) +#define GPIOF_BASE (AHB2PERIPH_BASE + 0x1400U) +#define GPIOG_BASE (AHB2PERIPH_BASE + 0x1800U) +#define GPIOH_BASE (AHB2PERIPH_BASE + 0x1C00U) + +#define USBOTG_BASE (AHB2PERIPH_BASE + 0x08000000U) + +#define ADC1_BASE (AHB2PERIPH_BASE + 0x08040000U) +#define ADC2_BASE (AHB2PERIPH_BASE + 0x08040100U) +#define ADC3_BASE (AHB2PERIPH_BASE + 0x08040200U) +#define ADC123_COMMON_BASE (AHB2PERIPH_BASE + 0x08040300U) + + +#define RNG_BASE (AHB2PERIPH_BASE + 0x08060800U) + + +/*!< FMC Banks registers base address */ +#define FMC_Bank1_R_BASE (FMC_R_BASE + 0x0000U) +#define FMC_Bank1E_R_BASE (FMC_R_BASE + 0x0104U) +#define FMC_Bank3_R_BASE (FMC_R_BASE + 0x0080U) + +/* Debug MCU registers base address */ +#define DBGMCU_BASE ((uint32_t)0xE0042000U) + +/*!< USB registers base address */ +#define USB_OTG_FS_PERIPH_BASE ((uint32_t)0x50000000U) + +#define USB_OTG_GLOBAL_BASE ((uint32_t)0x00000000U) +#define USB_OTG_DEVICE_BASE ((uint32_t)0x00000800U) +#define USB_OTG_IN_ENDPOINT_BASE ((uint32_t)0x00000900U) +#define USB_OTG_OUT_ENDPOINT_BASE ((uint32_t)0x00000B00U) +#define USB_OTG_EP_REG_SIZE ((uint32_t)0x00000020U) +#define USB_OTG_HOST_BASE ((uint32_t)0x00000400U) +#define USB_OTG_HOST_PORT_BASE ((uint32_t)0x00000440U) +#define USB_OTG_HOST_CHANNEL_BASE ((uint32_t)0x00000500U) +#define USB_OTG_HOST_CHANNEL_SIZE ((uint32_t)0x00000020U) +#define USB_OTG_PCGCCTL_BASE ((uint32_t)0x00000E00U) +#define USB_OTG_FIFO_BASE ((uint32_t)0x00001000U) +#define USB_OTG_FIFO_SIZE ((uint32_t)0x00001000U) + + +#define PACKAGE_BASE ((uint32_t)0x1FFF7500U) /*!< Package data register base address */ +#define UID_BASE ((uint32_t)0x1FFF7590U) /*!< Unique device ID register base address */ +#define FLASHSIZE_BASE ((uint32_t)0x1FFF75E0U) /*!< Flash size data register base address */ +/** + * @} + */ + +/** @addtogroup Peripheral_declaration + * @{ + */ +#define TIM2 ((TIM_TypeDef *) TIM2_BASE) +#define TIM3 ((TIM_TypeDef *) TIM3_BASE) +#define TIM4 ((TIM_TypeDef *) TIM4_BASE) +#define TIM5 ((TIM_TypeDef *) TIM5_BASE) +#define TIM6 ((TIM_TypeDef *) TIM6_BASE) +#define TIM7 ((TIM_TypeDef *) TIM7_BASE) +#define LCD ((LCD_TypeDef *) LCD_BASE) +#define RTC ((RTC_TypeDef *) RTC_BASE) +#define WWDG ((WWDG_TypeDef *) WWDG_BASE) +#define IWDG ((IWDG_TypeDef *) IWDG_BASE) +#define SPI2 ((SPI_TypeDef *) SPI2_BASE) +#define SPI3 ((SPI_TypeDef *) SPI3_BASE) +#define USART2 ((USART_TypeDef *) USART2_BASE) +#define USART3 ((USART_TypeDef *) USART3_BASE) +#define UART4 ((USART_TypeDef *) UART4_BASE) +#define UART5 ((USART_TypeDef *) UART5_BASE) +#define I2C1 ((I2C_TypeDef *) I2C1_BASE) +#define I2C2 ((I2C_TypeDef *) I2C2_BASE) +#define I2C3 ((I2C_TypeDef *) I2C3_BASE) +#define CAN ((CAN_TypeDef *) CAN1_BASE) +#define CAN1 ((CAN_TypeDef *) CAN1_BASE) +#define PWR ((PWR_TypeDef *) PWR_BASE) +#define DAC ((DAC_TypeDef *) DAC1_BASE) +#define DAC1 ((DAC_TypeDef *) DAC1_BASE) +#define OPAMP ((OPAMP_TypeDef *) OPAMP_BASE) +#define OPAMP1 ((OPAMP_TypeDef *) OPAMP1_BASE) +#define OPAMP2 ((OPAMP_TypeDef *) OPAMP2_BASE) +#define OPAMP12_COMMON ((OPAMP_Common_TypeDef *) OPAMP1_BASE) +#define LPTIM1 ((LPTIM_TypeDef *) LPTIM1_BASE) +#define LPUART1 ((USART_TypeDef *) LPUART1_BASE) +#define SWPMI1 ((SWPMI_TypeDef *) SWPMI1_BASE) +#define LPTIM2 ((LPTIM_TypeDef *) LPTIM2_BASE) + +#define SYSCFG ((SYSCFG_TypeDef *) SYSCFG_BASE) +#define VREFBUF ((VREFBUF_TypeDef *) VREFBUF_BASE) +#define COMP1 ((COMP_TypeDef *) COMP1_BASE) +#define COMP2 ((COMP_TypeDef *) COMP2_BASE) +#define COMP12_COMMON ((COMP_Common_TypeDef *) COMP2_BASE) +#define EXTI ((EXTI_TypeDef *) EXTI_BASE) +#define FIREWALL ((FIREWALL_TypeDef *) FIREWALL_BASE) +#define SDMMC1 ((SDMMC_TypeDef *) SDMMC1_BASE) +#define TIM1 ((TIM_TypeDef *) TIM1_BASE) +#define SPI1 ((SPI_TypeDef *) SPI1_BASE) +#define TIM8 ((TIM_TypeDef *) TIM8_BASE) +#define USART1 ((USART_TypeDef *) USART1_BASE) +#define TIM15 ((TIM_TypeDef *) TIM15_BASE) +#define TIM16 ((TIM_TypeDef *) TIM16_BASE) +#define TIM17 ((TIM_TypeDef *) TIM17_BASE) +#define SAI1 ((SAI_TypeDef *) SAI1_BASE) +#define SAI1_Block_A ((SAI_Block_TypeDef *)SAI1_Block_A_BASE) +#define SAI1_Block_B ((SAI_Block_TypeDef *)SAI1_Block_B_BASE) +#define SAI2 ((SAI_TypeDef *) SAI2_BASE) +#define SAI2_Block_A ((SAI_Block_TypeDef *)SAI2_Block_A_BASE) +#define SAI2_Block_B ((SAI_Block_TypeDef *)SAI2_Block_B_BASE) +#define DFSDM1_Channel0 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel0_BASE) +#define DFSDM1_Channel1 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel1_BASE) +#define DFSDM1_Channel2 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel2_BASE) +#define DFSDM1_Channel3 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel3_BASE) +#define DFSDM1_Channel4 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel4_BASE) +#define DFSDM1_Channel5 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel5_BASE) +#define DFSDM1_Channel6 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel6_BASE) +#define DFSDM1_Channel7 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel7_BASE) +#define DFSDM1_Filter0 ((DFSDM_Filter_TypeDef *) DFSDM1_Filter0_BASE) +#define DFSDM1_Filter1 ((DFSDM_Filter_TypeDef *) DFSDM1_Filter1_BASE) +#define DFSDM1_Filter2 ((DFSDM_Filter_TypeDef *) DFSDM1_Filter2_BASE) +#define DFSDM1_Filter3 ((DFSDM_Filter_TypeDef *) DFSDM1_Filter3_BASE) +/* Aliases to keep compatibility after DFSDM renaming */ +#define DFSDM_Channel0 DFSDM1_Channel0 +#define DFSDM_Channel1 DFSDM1_Channel1 +#define DFSDM_Channel2 DFSDM1_Channel2 +#define DFSDM_Channel3 DFSDM1_Channel3 +#define DFSDM_Channel4 DFSDM1_Channel4 +#define DFSDM_Channel5 DFSDM1_Channel5 +#define DFSDM_Channel6 DFSDM1_Channel6 +#define DFSDM_Channel7 DFSDM1_Channel7 +#define DFSDM_Filter0 DFSDM1_Filter0 +#define DFSDM_Filter1 DFSDM1_Filter1 +#define DFSDM_Filter2 DFSDM1_Filter2 +#define DFSDM_Filter3 DFSDM1_Filter3 +#define DMA1 ((DMA_TypeDef *) DMA1_BASE) +#define DMA2 ((DMA_TypeDef *) DMA2_BASE) +#define RCC ((RCC_TypeDef *) RCC_BASE) +#define FLASH ((FLASH_TypeDef *) FLASH_R_BASE) +#define CRC ((CRC_TypeDef *) CRC_BASE) +#define TSC ((TSC_TypeDef *) TSC_BASE) + +#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE) +#define GPIOB ((GPIO_TypeDef *) GPIOB_BASE) +#define GPIOC ((GPIO_TypeDef *) GPIOC_BASE) +#define GPIOD ((GPIO_TypeDef *) GPIOD_BASE) +#define GPIOE ((GPIO_TypeDef *) GPIOE_BASE) +#define GPIOF ((GPIO_TypeDef *) GPIOF_BASE) +#define GPIOG ((GPIO_TypeDef *) GPIOG_BASE) +#define GPIOH ((GPIO_TypeDef *) GPIOH_BASE) +#define ADC1 ((ADC_TypeDef *) ADC1_BASE) +#define ADC2 ((ADC_TypeDef *) ADC2_BASE) +#define ADC3 ((ADC_TypeDef *) ADC3_BASE) +#define ADC123_COMMON ((ADC_Common_TypeDef *) ADC123_COMMON_BASE) +#define RNG ((RNG_TypeDef *) RNG_BASE) + + +#define DMA1_Channel1 ((DMA_Channel_TypeDef *) DMA1_Channel1_BASE) +#define DMA1_Channel2 ((DMA_Channel_TypeDef *) DMA1_Channel2_BASE) +#define DMA1_Channel3 ((DMA_Channel_TypeDef *) DMA1_Channel3_BASE) +#define DMA1_Channel4 ((DMA_Channel_TypeDef *) DMA1_Channel4_BASE) +#define DMA1_Channel5 ((DMA_Channel_TypeDef *) DMA1_Channel5_BASE) +#define DMA1_Channel6 ((DMA_Channel_TypeDef *) DMA1_Channel6_BASE) +#define DMA1_Channel7 ((DMA_Channel_TypeDef *) DMA1_Channel7_BASE) +#define DMA1_CSELR ((DMA_Request_TypeDef *) DMA1_CSELR_BASE) + + +#define DMA2_Channel1 ((DMA_Channel_TypeDef *) DMA2_Channel1_BASE) +#define DMA2_Channel2 ((DMA_Channel_TypeDef *) DMA2_Channel2_BASE) +#define DMA2_Channel3 ((DMA_Channel_TypeDef *) DMA2_Channel3_BASE) +#define DMA2_Channel4 ((DMA_Channel_TypeDef *) DMA2_Channel4_BASE) +#define DMA2_Channel5 ((DMA_Channel_TypeDef *) DMA2_Channel5_BASE) +#define DMA2_Channel6 ((DMA_Channel_TypeDef *) DMA2_Channel6_BASE) +#define DMA2_Channel7 ((DMA_Channel_TypeDef *) DMA2_Channel7_BASE) +#define DMA2_CSELR ((DMA_Request_TypeDef *) DMA2_CSELR_BASE) + + +#define FMC_Bank1_R ((FMC_Bank1_TypeDef *) FMC_Bank1_R_BASE) +#define FMC_Bank1E_R ((FMC_Bank1E_TypeDef *) FMC_Bank1E_R_BASE) +#define FMC_Bank3_R ((FMC_Bank3_TypeDef *) FMC_Bank3_R_BASE) + +#define QUADSPI ((QUADSPI_TypeDef *) QSPI_R_BASE) + +#define DBGMCU ((DBGMCU_TypeDef *) DBGMCU_BASE) + +#define USB_OTG_FS ((USB_OTG_GlobalTypeDef *) USB_OTG_FS_PERIPH_BASE) +/** + * @} + */ + +/** @addtogroup Exported_constants + * @{ + */ + +/** @addtogroup Peripheral_Registers_Bits_Definition + * @{ + */ + +/******************************************************************************/ +/* Peripheral Registers_Bits_Definition */ +/******************************************************************************/ + +/******************************************************************************/ +/* */ +/* Analog to Digital Converter */ +/* */ +/******************************************************************************/ + +/* + * @brief Specific device feature definitions (not present on all devices in the STM32L4 serie) + */ +#define ADC_MULTIMODE_SUPPORT /*!< ADC feature available only on specific devices: multimode available on devices with several ADC instances */ + +/******************** Bit definition for ADC_ISR register *******************/ +#define ADC_ISR_ADRDY_Pos (0U) +#define ADC_ISR_ADRDY_Msk (0x1U << ADC_ISR_ADRDY_Pos) /*!< 0x00000001 */ +#define ADC_ISR_ADRDY ADC_ISR_ADRDY_Msk /*!< ADC ready flag */ +#define ADC_ISR_EOSMP_Pos (1U) +#define ADC_ISR_EOSMP_Msk (0x1U << ADC_ISR_EOSMP_Pos) /*!< 0x00000002 */ +#define ADC_ISR_EOSMP ADC_ISR_EOSMP_Msk /*!< ADC group regular end of sampling flag */ +#define ADC_ISR_EOC_Pos (2U) +#define ADC_ISR_EOC_Msk (0x1U << ADC_ISR_EOC_Pos) /*!< 0x00000004 */ +#define ADC_ISR_EOC ADC_ISR_EOC_Msk /*!< ADC group regular end of unitary conversion flag */ +#define ADC_ISR_EOS_Pos (3U) +#define ADC_ISR_EOS_Msk (0x1U << ADC_ISR_EOS_Pos) /*!< 0x00000008 */ +#define ADC_ISR_EOS ADC_ISR_EOS_Msk /*!< ADC group regular end of sequence conversions flag */ +#define ADC_ISR_OVR_Pos (4U) +#define ADC_ISR_OVR_Msk (0x1U << ADC_ISR_OVR_Pos) /*!< 0x00000010 */ +#define ADC_ISR_OVR ADC_ISR_OVR_Msk /*!< ADC group regular overrun flag */ +#define ADC_ISR_JEOC_Pos (5U) +#define ADC_ISR_JEOC_Msk (0x1U << ADC_ISR_JEOC_Pos) /*!< 0x00000020 */ +#define ADC_ISR_JEOC ADC_ISR_JEOC_Msk /*!< ADC group injected end of unitary conversion flag */ +#define ADC_ISR_JEOS_Pos (6U) +#define ADC_ISR_JEOS_Msk (0x1U << ADC_ISR_JEOS_Pos) /*!< 0x00000040 */ +#define ADC_ISR_JEOS ADC_ISR_JEOS_Msk /*!< ADC group injected end of sequence conversions flag */ +#define ADC_ISR_AWD1_Pos (7U) +#define ADC_ISR_AWD1_Msk (0x1U << ADC_ISR_AWD1_Pos) /*!< 0x00000080 */ +#define ADC_ISR_AWD1 ADC_ISR_AWD1_Msk /*!< ADC analog watchdog 1 flag */ +#define ADC_ISR_AWD2_Pos (8U) +#define ADC_ISR_AWD2_Msk (0x1U << ADC_ISR_AWD2_Pos) /*!< 0x00000100 */ +#define ADC_ISR_AWD2 ADC_ISR_AWD2_Msk /*!< ADC analog watchdog 2 flag */ +#define ADC_ISR_AWD3_Pos (9U) +#define ADC_ISR_AWD3_Msk (0x1U << ADC_ISR_AWD3_Pos) /*!< 0x00000200 */ +#define ADC_ISR_AWD3 ADC_ISR_AWD3_Msk /*!< ADC analog watchdog 3 flag */ +#define ADC_ISR_JQOVF_Pos (10U) +#define ADC_ISR_JQOVF_Msk (0x1U << ADC_ISR_JQOVF_Pos) /*!< 0x00000400 */ +#define ADC_ISR_JQOVF ADC_ISR_JQOVF_Msk /*!< ADC group injected contexts queue overflow flag */ + +/******************** Bit definition for ADC_IER register *******************/ +#define ADC_IER_ADRDYIE_Pos (0U) +#define ADC_IER_ADRDYIE_Msk (0x1U << ADC_IER_ADRDYIE_Pos) /*!< 0x00000001 */ +#define ADC_IER_ADRDYIE ADC_IER_ADRDYIE_Msk /*!< ADC ready interrupt */ +#define ADC_IER_EOSMPIE_Pos (1U) +#define ADC_IER_EOSMPIE_Msk (0x1U << ADC_IER_EOSMPIE_Pos) /*!< 0x00000002 */ +#define ADC_IER_EOSMPIE ADC_IER_EOSMPIE_Msk /*!< ADC group regular end of sampling interrupt */ +#define ADC_IER_EOCIE_Pos (2U) +#define ADC_IER_EOCIE_Msk (0x1U << ADC_IER_EOCIE_Pos) /*!< 0x00000004 */ +#define ADC_IER_EOCIE ADC_IER_EOCIE_Msk /*!< ADC group regular end of unitary conversion interrupt */ +#define ADC_IER_EOSIE_Pos (3U) +#define ADC_IER_EOSIE_Msk (0x1U << ADC_IER_EOSIE_Pos) /*!< 0x00000008 */ +#define ADC_IER_EOSIE ADC_IER_EOSIE_Msk /*!< ADC group regular end of sequence conversions interrupt */ +#define ADC_IER_OVRIE_Pos (4U) +#define ADC_IER_OVRIE_Msk (0x1U << ADC_IER_OVRIE_Pos) /*!< 0x00000010 */ +#define ADC_IER_OVRIE ADC_IER_OVRIE_Msk /*!< ADC group regular overrun interrupt */ +#define ADC_IER_JEOCIE_Pos (5U) +#define ADC_IER_JEOCIE_Msk (0x1U << ADC_IER_JEOCIE_Pos) /*!< 0x00000020 */ +#define ADC_IER_JEOCIE ADC_IER_JEOCIE_Msk /*!< ADC group injected end of unitary conversion interrupt */ +#define ADC_IER_JEOSIE_Pos (6U) +#define ADC_IER_JEOSIE_Msk (0x1U << ADC_IER_JEOSIE_Pos) /*!< 0x00000040 */ +#define ADC_IER_JEOSIE ADC_IER_JEOSIE_Msk /*!< ADC group injected end of sequence conversions interrupt */ +#define ADC_IER_AWD1IE_Pos (7U) +#define ADC_IER_AWD1IE_Msk (0x1U << ADC_IER_AWD1IE_Pos) /*!< 0x00000080 */ +#define ADC_IER_AWD1IE ADC_IER_AWD1IE_Msk /*!< ADC analog watchdog 1 interrupt */ +#define ADC_IER_AWD2IE_Pos (8U) +#define ADC_IER_AWD2IE_Msk (0x1U << ADC_IER_AWD2IE_Pos) /*!< 0x00000100 */ +#define ADC_IER_AWD2IE ADC_IER_AWD2IE_Msk /*!< ADC analog watchdog 2 interrupt */ +#define ADC_IER_AWD3IE_Pos (9U) +#define ADC_IER_AWD3IE_Msk (0x1U << ADC_IER_AWD3IE_Pos) /*!< 0x00000200 */ +#define ADC_IER_AWD3IE ADC_IER_AWD3IE_Msk /*!< ADC analog watchdog 3 interrupt */ +#define ADC_IER_JQOVFIE_Pos (10U) +#define ADC_IER_JQOVFIE_Msk (0x1U << ADC_IER_JQOVFIE_Pos) /*!< 0x00000400 */ +#define ADC_IER_JQOVFIE ADC_IER_JQOVFIE_Msk /*!< ADC group injected contexts queue overflow interrupt */ + +/* Legacy defines */ +#define ADC_IER_ADRDY (ADC_IER_ADRDYIE) +#define ADC_IER_EOSMP (ADC_IER_EOSMPIE) +#define ADC_IER_EOC (ADC_IER_EOCIE) +#define ADC_IER_EOS (ADC_IER_EOSIE) +#define ADC_IER_OVR (ADC_IER_OVRIE) +#define ADC_IER_JEOC (ADC_IER_JEOCIE) +#define ADC_IER_JEOS (ADC_IER_JEOSIE) +#define ADC_IER_AWD1 (ADC_IER_AWD1IE) +#define ADC_IER_AWD2 (ADC_IER_AWD2IE) +#define ADC_IER_AWD3 (ADC_IER_AWD3IE) +#define ADC_IER_JQOVF (ADC_IER_JQOVFIE) + +/******************** Bit definition for ADC_CR register ********************/ +#define ADC_CR_ADEN_Pos (0U) +#define ADC_CR_ADEN_Msk (0x1U << ADC_CR_ADEN_Pos) /*!< 0x00000001 */ +#define ADC_CR_ADEN ADC_CR_ADEN_Msk /*!< ADC enable */ +#define ADC_CR_ADDIS_Pos (1U) +#define ADC_CR_ADDIS_Msk (0x1U << ADC_CR_ADDIS_Pos) /*!< 0x00000002 */ +#define ADC_CR_ADDIS ADC_CR_ADDIS_Msk /*!< ADC disable */ +#define ADC_CR_ADSTART_Pos (2U) +#define ADC_CR_ADSTART_Msk (0x1U << ADC_CR_ADSTART_Pos) /*!< 0x00000004 */ +#define ADC_CR_ADSTART ADC_CR_ADSTART_Msk /*!< ADC group regular conversion start */ +#define ADC_CR_JADSTART_Pos (3U) +#define ADC_CR_JADSTART_Msk (0x1U << ADC_CR_JADSTART_Pos) /*!< 0x00000008 */ +#define ADC_CR_JADSTART ADC_CR_JADSTART_Msk /*!< ADC group injected conversion start */ +#define ADC_CR_ADSTP_Pos (4U) +#define ADC_CR_ADSTP_Msk (0x1U << ADC_CR_ADSTP_Pos) /*!< 0x00000010 */ +#define ADC_CR_ADSTP ADC_CR_ADSTP_Msk /*!< ADC group regular conversion stop */ +#define ADC_CR_JADSTP_Pos (5U) +#define ADC_CR_JADSTP_Msk (0x1U << ADC_CR_JADSTP_Pos) /*!< 0x00000020 */ +#define ADC_CR_JADSTP ADC_CR_JADSTP_Msk /*!< ADC group injected conversion stop */ +#define ADC_CR_ADVREGEN_Pos (28U) +#define ADC_CR_ADVREGEN_Msk (0x1U << ADC_CR_ADVREGEN_Pos) /*!< 0x10000000 */ +#define ADC_CR_ADVREGEN ADC_CR_ADVREGEN_Msk /*!< ADC voltage regulator enable */ +#define ADC_CR_DEEPPWD_Pos (29U) +#define ADC_CR_DEEPPWD_Msk (0x1U << ADC_CR_DEEPPWD_Pos) /*!< 0x20000000 */ +#define ADC_CR_DEEPPWD ADC_CR_DEEPPWD_Msk /*!< ADC deep power down enable */ +#define ADC_CR_ADCALDIF_Pos (30U) +#define ADC_CR_ADCALDIF_Msk (0x1U << ADC_CR_ADCALDIF_Pos) /*!< 0x40000000 */ +#define ADC_CR_ADCALDIF ADC_CR_ADCALDIF_Msk /*!< ADC differential mode for calibration */ +#define ADC_CR_ADCAL_Pos (31U) +#define ADC_CR_ADCAL_Msk (0x1U << ADC_CR_ADCAL_Pos) /*!< 0x80000000 */ +#define ADC_CR_ADCAL ADC_CR_ADCAL_Msk /*!< ADC calibration */ + +/******************** Bit definition for ADC_CFGR register ******************/ +#define ADC_CFGR_DMAEN_Pos (0U) +#define ADC_CFGR_DMAEN_Msk (0x1U << ADC_CFGR_DMAEN_Pos) /*!< 0x00000001 */ +#define ADC_CFGR_DMAEN ADC_CFGR_DMAEN_Msk /*!< ADC DMA transfer enable */ +#define ADC_CFGR_DMACFG_Pos (1U) +#define ADC_CFGR_DMACFG_Msk (0x1U << ADC_CFGR_DMACFG_Pos) /*!< 0x00000002 */ +#define ADC_CFGR_DMACFG ADC_CFGR_DMACFG_Msk /*!< ADC DMA transfer configuration */ + +#define ADC_CFGR_RES_Pos (3U) +#define ADC_CFGR_RES_Msk (0x3U << ADC_CFGR_RES_Pos) /*!< 0x00000018 */ +#define ADC_CFGR_RES ADC_CFGR_RES_Msk /*!< ADC data resolution */ +#define ADC_CFGR_RES_0 (0x1U << ADC_CFGR_RES_Pos) /*!< 0x00000008 */ +#define ADC_CFGR_RES_1 (0x2U << ADC_CFGR_RES_Pos) /*!< 0x00000010 */ + +#define ADC_CFGR_ALIGN_Pos (5U) +#define ADC_CFGR_ALIGN_Msk (0x1U << ADC_CFGR_ALIGN_Pos) /*!< 0x00000020 */ +#define ADC_CFGR_ALIGN ADC_CFGR_ALIGN_Msk /*!< ADC data alignement */ + +#define ADC_CFGR_EXTSEL_Pos (6U) +#define ADC_CFGR_EXTSEL_Msk (0xFU << ADC_CFGR_EXTSEL_Pos) /*!< 0x000003C0 */ +#define ADC_CFGR_EXTSEL ADC_CFGR_EXTSEL_Msk /*!< ADC group regular external trigger source */ +#define ADC_CFGR_EXTSEL_0 (0x1U << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000040 */ +#define ADC_CFGR_EXTSEL_1 (0x2U << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000080 */ +#define ADC_CFGR_EXTSEL_2 (0x4U << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000100 */ +#define ADC_CFGR_EXTSEL_3 (0x8U << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000200 */ + +#define ADC_CFGR_EXTEN_Pos (10U) +#define ADC_CFGR_EXTEN_Msk (0x3U << ADC_CFGR_EXTEN_Pos) /*!< 0x00000C00 */ +#define ADC_CFGR_EXTEN ADC_CFGR_EXTEN_Msk /*!< ADC group regular external trigger polarity */ +#define ADC_CFGR_EXTEN_0 (0x1U << ADC_CFGR_EXTEN_Pos) /*!< 0x00000400 */ +#define ADC_CFGR_EXTEN_1 (0x2U << ADC_CFGR_EXTEN_Pos) /*!< 0x00000800 */ + +#define ADC_CFGR_OVRMOD_Pos (12U) +#define ADC_CFGR_OVRMOD_Msk (0x1U << ADC_CFGR_OVRMOD_Pos) /*!< 0x00001000 */ +#define ADC_CFGR_OVRMOD ADC_CFGR_OVRMOD_Msk /*!< ADC group regular overrun configuration */ +#define ADC_CFGR_CONT_Pos (13U) +#define ADC_CFGR_CONT_Msk (0x1U << ADC_CFGR_CONT_Pos) /*!< 0x00002000 */ +#define ADC_CFGR_CONT ADC_CFGR_CONT_Msk /*!< ADC group regular continuous conversion mode */ +#define ADC_CFGR_AUTDLY_Pos (14U) +#define ADC_CFGR_AUTDLY_Msk (0x1U << ADC_CFGR_AUTDLY_Pos) /*!< 0x00004000 */ +#define ADC_CFGR_AUTDLY ADC_CFGR_AUTDLY_Msk /*!< ADC low power auto wait */ + +#define ADC_CFGR_DISCEN_Pos (16U) +#define ADC_CFGR_DISCEN_Msk (0x1U << ADC_CFGR_DISCEN_Pos) /*!< 0x00010000 */ +#define ADC_CFGR_DISCEN ADC_CFGR_DISCEN_Msk /*!< ADC group regular sequencer discontinuous mode */ + +#define ADC_CFGR_DISCNUM_Pos (17U) +#define ADC_CFGR_DISCNUM_Msk (0x7U << ADC_CFGR_DISCNUM_Pos) /*!< 0x000E0000 */ +#define ADC_CFGR_DISCNUM ADC_CFGR_DISCNUM_Msk /*!< ADC group regular sequencer discontinuous number of ranks */ +#define ADC_CFGR_DISCNUM_0 (0x1U << ADC_CFGR_DISCNUM_Pos) /*!< 0x00020000 */ +#define ADC_CFGR_DISCNUM_1 (0x2U << ADC_CFGR_DISCNUM_Pos) /*!< 0x00040000 */ +#define ADC_CFGR_DISCNUM_2 (0x4U << ADC_CFGR_DISCNUM_Pos) /*!< 0x00080000 */ + +#define ADC_CFGR_JDISCEN_Pos (20U) +#define ADC_CFGR_JDISCEN_Msk (0x1U << ADC_CFGR_JDISCEN_Pos) /*!< 0x00100000 */ +#define ADC_CFGR_JDISCEN ADC_CFGR_JDISCEN_Msk /*!< ADC group injected sequencer discontinuous mode */ +#define ADC_CFGR_JQM_Pos (21U) +#define ADC_CFGR_JQM_Msk (0x1U << ADC_CFGR_JQM_Pos) /*!< 0x00200000 */ +#define ADC_CFGR_JQM ADC_CFGR_JQM_Msk /*!< ADC group injected contexts queue mode */ +#define ADC_CFGR_AWD1SGL_Pos (22U) +#define ADC_CFGR_AWD1SGL_Msk (0x1U << ADC_CFGR_AWD1SGL_Pos) /*!< 0x00400000 */ +#define ADC_CFGR_AWD1SGL ADC_CFGR_AWD1SGL_Msk /*!< ADC analog watchdog 1 monitoring a single channel or all channels */ +#define ADC_CFGR_AWD1EN_Pos (23U) +#define ADC_CFGR_AWD1EN_Msk (0x1U << ADC_CFGR_AWD1EN_Pos) /*!< 0x00800000 */ +#define ADC_CFGR_AWD1EN ADC_CFGR_AWD1EN_Msk /*!< ADC analog watchdog 1 enable on scope ADC group regular */ +#define ADC_CFGR_JAWD1EN_Pos (24U) +#define ADC_CFGR_JAWD1EN_Msk (0x1U << ADC_CFGR_JAWD1EN_Pos) /*!< 0x01000000 */ +#define ADC_CFGR_JAWD1EN ADC_CFGR_JAWD1EN_Msk /*!< ADC analog watchdog 1 enable on scope ADC group injected */ +#define ADC_CFGR_JAUTO_Pos (25U) +#define ADC_CFGR_JAUTO_Msk (0x1U << ADC_CFGR_JAUTO_Pos) /*!< 0x02000000 */ +#define ADC_CFGR_JAUTO ADC_CFGR_JAUTO_Msk /*!< ADC group injected automatic trigger mode */ + +#define ADC_CFGR_AWD1CH_Pos (26U) +#define ADC_CFGR_AWD1CH_Msk (0x1FU << ADC_CFGR_AWD1CH_Pos) /*!< 0x7C000000 */ +#define ADC_CFGR_AWD1CH ADC_CFGR_AWD1CH_Msk /*!< ADC analog watchdog 1 monitored channel selection */ +#define ADC_CFGR_AWD1CH_0 (0x01U << ADC_CFGR_AWD1CH_Pos) /*!< 0x04000000 */ +#define ADC_CFGR_AWD1CH_1 (0x02U << ADC_CFGR_AWD1CH_Pos) /*!< 0x08000000 */ +#define ADC_CFGR_AWD1CH_2 (0x04U << ADC_CFGR_AWD1CH_Pos) /*!< 0x10000000 */ +#define ADC_CFGR_AWD1CH_3 (0x08U << ADC_CFGR_AWD1CH_Pos) /*!< 0x20000000 */ +#define ADC_CFGR_AWD1CH_4 (0x10U << ADC_CFGR_AWD1CH_Pos) /*!< 0x40000000 */ + +#define ADC_CFGR_JQDIS_Pos (31U) +#define ADC_CFGR_JQDIS_Msk (0x1U << ADC_CFGR_JQDIS_Pos) /*!< 0x80000000 */ +#define ADC_CFGR_JQDIS ADC_CFGR_JQDIS_Msk /*!< ADC group injected contexts queue disable */ + +/******************** Bit definition for ADC_CFGR2 register *****************/ +#define ADC_CFGR2_ROVSE_Pos (0U) +#define ADC_CFGR2_ROVSE_Msk (0x1U << ADC_CFGR2_ROVSE_Pos) /*!< 0x00000001 */ +#define ADC_CFGR2_ROVSE ADC_CFGR2_ROVSE_Msk /*!< ADC oversampler enable on scope ADC group regular */ +#define ADC_CFGR2_JOVSE_Pos (1U) +#define ADC_CFGR2_JOVSE_Msk (0x1U << ADC_CFGR2_JOVSE_Pos) /*!< 0x00000002 */ +#define ADC_CFGR2_JOVSE ADC_CFGR2_JOVSE_Msk /*!< ADC oversampler enable on scope ADC group injected */ + +#define ADC_CFGR2_OVSR_Pos (2U) +#define ADC_CFGR2_OVSR_Msk (0x7U << ADC_CFGR2_OVSR_Pos) /*!< 0x0000001C */ +#define ADC_CFGR2_OVSR ADC_CFGR2_OVSR_Msk /*!< ADC oversampling ratio */ +#define ADC_CFGR2_OVSR_0 (0x1U << ADC_CFGR2_OVSR_Pos) /*!< 0x00000004 */ +#define ADC_CFGR2_OVSR_1 (0x2U << ADC_CFGR2_OVSR_Pos) /*!< 0x00000008 */ +#define ADC_CFGR2_OVSR_2 (0x4U << ADC_CFGR2_OVSR_Pos) /*!< 0x00000010 */ + +#define ADC_CFGR2_OVSS_Pos (5U) +#define ADC_CFGR2_OVSS_Msk (0xFU << ADC_CFGR2_OVSS_Pos) /*!< 0x000001E0 */ +#define ADC_CFGR2_OVSS ADC_CFGR2_OVSS_Msk /*!< ADC oversampling shift */ +#define ADC_CFGR2_OVSS_0 (0x1U << ADC_CFGR2_OVSS_Pos) /*!< 0x00000020 */ +#define ADC_CFGR2_OVSS_1 (0x2U << ADC_CFGR2_OVSS_Pos) /*!< 0x00000040 */ +#define ADC_CFGR2_OVSS_2 (0x4U << ADC_CFGR2_OVSS_Pos) /*!< 0x00000080 */ +#define ADC_CFGR2_OVSS_3 (0x8U << ADC_CFGR2_OVSS_Pos) /*!< 0x00000100 */ + +#define ADC_CFGR2_TROVS_Pos (9U) +#define ADC_CFGR2_TROVS_Msk (0x1U << ADC_CFGR2_TROVS_Pos) /*!< 0x00000200 */ +#define ADC_CFGR2_TROVS ADC_CFGR2_TROVS_Msk /*!< ADC oversampling discontinuous mode (triggered mode) for ADC group regular */ +#define ADC_CFGR2_ROVSM_Pos (10U) +#define ADC_CFGR2_ROVSM_Msk (0x1U << ADC_CFGR2_ROVSM_Pos) /*!< 0x00000400 */ +#define ADC_CFGR2_ROVSM ADC_CFGR2_ROVSM_Msk /*!< ADC oversampling mode managing interlaced conversions of ADC group regular and group injected */ + +/******************** Bit definition for ADC_SMPR1 register *****************/ +#define ADC_SMPR1_SMP0_Pos (0U) +#define ADC_SMPR1_SMP0_Msk (0x7U << ADC_SMPR1_SMP0_Pos) /*!< 0x00000007 */ +#define ADC_SMPR1_SMP0 ADC_SMPR1_SMP0_Msk /*!< ADC channel 0 sampling time selection */ +#define ADC_SMPR1_SMP0_0 (0x1U << ADC_SMPR1_SMP0_Pos) /*!< 0x00000001 */ +#define ADC_SMPR1_SMP0_1 (0x2U << ADC_SMPR1_SMP0_Pos) /*!< 0x00000002 */ +#define ADC_SMPR1_SMP0_2 (0x4U << ADC_SMPR1_SMP0_Pos) /*!< 0x00000004 */ + +#define ADC_SMPR1_SMP1_Pos (3U) +#define ADC_SMPR1_SMP1_Msk (0x7U << ADC_SMPR1_SMP1_Pos) /*!< 0x00000038 */ +#define ADC_SMPR1_SMP1 ADC_SMPR1_SMP1_Msk /*!< ADC channel 1 sampling time selection */ +#define ADC_SMPR1_SMP1_0 (0x1U << ADC_SMPR1_SMP1_Pos) /*!< 0x00000008 */ +#define ADC_SMPR1_SMP1_1 (0x2U << ADC_SMPR1_SMP1_Pos) /*!< 0x00000010 */ +#define ADC_SMPR1_SMP1_2 (0x4U << ADC_SMPR1_SMP1_Pos) /*!< 0x00000020 */ + +#define ADC_SMPR1_SMP2_Pos (6U) +#define ADC_SMPR1_SMP2_Msk (0x7U << ADC_SMPR1_SMP2_Pos) /*!< 0x000001C0 */ +#define ADC_SMPR1_SMP2 ADC_SMPR1_SMP2_Msk /*!< ADC channel 2 sampling time selection */ +#define ADC_SMPR1_SMP2_0 (0x1U << ADC_SMPR1_SMP2_Pos) /*!< 0x00000040 */ +#define ADC_SMPR1_SMP2_1 (0x2U << ADC_SMPR1_SMP2_Pos) /*!< 0x00000080 */ +#define ADC_SMPR1_SMP2_2 (0x4U << ADC_SMPR1_SMP2_Pos) /*!< 0x00000100 */ + +#define ADC_SMPR1_SMP3_Pos (9U) +#define ADC_SMPR1_SMP3_Msk (0x7U << ADC_SMPR1_SMP3_Pos) /*!< 0x00000E00 */ +#define ADC_SMPR1_SMP3 ADC_SMPR1_SMP3_Msk /*!< ADC channel 3 sampling time selection */ +#define ADC_SMPR1_SMP3_0 (0x1U << ADC_SMPR1_SMP3_Pos) /*!< 0x00000200 */ +#define ADC_SMPR1_SMP3_1 (0x2U << ADC_SMPR1_SMP3_Pos) /*!< 0x00000400 */ +#define ADC_SMPR1_SMP3_2 (0x4U << ADC_SMPR1_SMP3_Pos) /*!< 0x00000800 */ + +#define ADC_SMPR1_SMP4_Pos (12U) +#define ADC_SMPR1_SMP4_Msk (0x7U << ADC_SMPR1_SMP4_Pos) /*!< 0x00007000 */ +#define ADC_SMPR1_SMP4 ADC_SMPR1_SMP4_Msk /*!< ADC channel 4 sampling time selection */ +#define ADC_SMPR1_SMP4_0 (0x1U << ADC_SMPR1_SMP4_Pos) /*!< 0x00001000 */ +#define ADC_SMPR1_SMP4_1 (0x2U << ADC_SMPR1_SMP4_Pos) /*!< 0x00002000 */ +#define ADC_SMPR1_SMP4_2 (0x4U << ADC_SMPR1_SMP4_Pos) /*!< 0x00004000 */ + +#define ADC_SMPR1_SMP5_Pos (15U) +#define ADC_SMPR1_SMP5_Msk (0x7U << ADC_SMPR1_SMP5_Pos) /*!< 0x00038000 */ +#define ADC_SMPR1_SMP5 ADC_SMPR1_SMP5_Msk /*!< ADC channel 5 sampling time selection */ +#define ADC_SMPR1_SMP5_0 (0x1U << ADC_SMPR1_SMP5_Pos) /*!< 0x00008000 */ +#define ADC_SMPR1_SMP5_1 (0x2U << ADC_SMPR1_SMP5_Pos) /*!< 0x00010000 */ +#define ADC_SMPR1_SMP5_2 (0x4U << ADC_SMPR1_SMP5_Pos) /*!< 0x00020000 */ + +#define ADC_SMPR1_SMP6_Pos (18U) +#define ADC_SMPR1_SMP6_Msk (0x7U << ADC_SMPR1_SMP6_Pos) /*!< 0x001C0000 */ +#define ADC_SMPR1_SMP6 ADC_SMPR1_SMP6_Msk /*!< ADC channel 6 sampling time selection */ +#define ADC_SMPR1_SMP6_0 (0x1U << ADC_SMPR1_SMP6_Pos) /*!< 0x00040000 */ +#define ADC_SMPR1_SMP6_1 (0x2U << ADC_SMPR1_SMP6_Pos) /*!< 0x00080000 */ +#define ADC_SMPR1_SMP6_2 (0x4U << ADC_SMPR1_SMP6_Pos) /*!< 0x00100000 */ + +#define ADC_SMPR1_SMP7_Pos (21U) +#define ADC_SMPR1_SMP7_Msk (0x7U << ADC_SMPR1_SMP7_Pos) /*!< 0x00E00000 */ +#define ADC_SMPR1_SMP7 ADC_SMPR1_SMP7_Msk /*!< ADC channel 7 sampling time selection */ +#define ADC_SMPR1_SMP7_0 (0x1U << ADC_SMPR1_SMP7_Pos) /*!< 0x00200000 */ +#define ADC_SMPR1_SMP7_1 (0x2U << ADC_SMPR1_SMP7_Pos) /*!< 0x00400000 */ +#define ADC_SMPR1_SMP7_2 (0x4U << ADC_SMPR1_SMP7_Pos) /*!< 0x00800000 */ + +#define ADC_SMPR1_SMP8_Pos (24U) +#define ADC_SMPR1_SMP8_Msk (0x7U << ADC_SMPR1_SMP8_Pos) /*!< 0x07000000 */ +#define ADC_SMPR1_SMP8 ADC_SMPR1_SMP8_Msk /*!< ADC channel 8 sampling time selection */ +#define ADC_SMPR1_SMP8_0 (0x1U << ADC_SMPR1_SMP8_Pos) /*!< 0x01000000 */ +#define ADC_SMPR1_SMP8_1 (0x2U << ADC_SMPR1_SMP8_Pos) /*!< 0x02000000 */ +#define ADC_SMPR1_SMP8_2 (0x4U << ADC_SMPR1_SMP8_Pos) /*!< 0x04000000 */ + +#define ADC_SMPR1_SMP9_Pos (27U) +#define ADC_SMPR1_SMP9_Msk (0x7U << ADC_SMPR1_SMP9_Pos) /*!< 0x38000000 */ +#define ADC_SMPR1_SMP9 ADC_SMPR1_SMP9_Msk /*!< ADC channel 9 sampling time selection */ +#define ADC_SMPR1_SMP9_0 (0x1U << ADC_SMPR1_SMP9_Pos) /*!< 0x08000000 */ +#define ADC_SMPR1_SMP9_1 (0x2U << ADC_SMPR1_SMP9_Pos) /*!< 0x10000000 */ +#define ADC_SMPR1_SMP9_2 (0x4U << ADC_SMPR1_SMP9_Pos) /*!< 0x20000000 */ + +/******************** Bit definition for ADC_SMPR2 register *****************/ +#define ADC_SMPR2_SMP10_Pos (0U) +#define ADC_SMPR2_SMP10_Msk (0x7U << ADC_SMPR2_SMP10_Pos) /*!< 0x00000007 */ +#define ADC_SMPR2_SMP10 ADC_SMPR2_SMP10_Msk /*!< ADC channel 10 sampling time selection */ +#define ADC_SMPR2_SMP10_0 (0x1U << ADC_SMPR2_SMP10_Pos) /*!< 0x00000001 */ +#define ADC_SMPR2_SMP10_1 (0x2U << ADC_SMPR2_SMP10_Pos) /*!< 0x00000002 */ +#define ADC_SMPR2_SMP10_2 (0x4U << ADC_SMPR2_SMP10_Pos) /*!< 0x00000004 */ + +#define ADC_SMPR2_SMP11_Pos (3U) +#define ADC_SMPR2_SMP11_Msk (0x7U << ADC_SMPR2_SMP11_Pos) /*!< 0x00000038 */ +#define ADC_SMPR2_SMP11 ADC_SMPR2_SMP11_Msk /*!< ADC channel 11 sampling time selection */ +#define ADC_SMPR2_SMP11_0 (0x1U << ADC_SMPR2_SMP11_Pos) /*!< 0x00000008 */ +#define ADC_SMPR2_SMP11_1 (0x2U << ADC_SMPR2_SMP11_Pos) /*!< 0x00000010 */ +#define ADC_SMPR2_SMP11_2 (0x4U << ADC_SMPR2_SMP11_Pos) /*!< 0x00000020 */ + +#define ADC_SMPR2_SMP12_Pos (6U) +#define ADC_SMPR2_SMP12_Msk (0x7U << ADC_SMPR2_SMP12_Pos) /*!< 0x000001C0 */ +#define ADC_SMPR2_SMP12 ADC_SMPR2_SMP12_Msk /*!< ADC channel 12 sampling time selection */ +#define ADC_SMPR2_SMP12_0 (0x1U << ADC_SMPR2_SMP12_Pos) /*!< 0x00000040 */ +#define ADC_SMPR2_SMP12_1 (0x2U << ADC_SMPR2_SMP12_Pos) /*!< 0x00000080 */ +#define ADC_SMPR2_SMP12_2 (0x4U << ADC_SMPR2_SMP12_Pos) /*!< 0x00000100 */ + +#define ADC_SMPR2_SMP13_Pos (9U) +#define ADC_SMPR2_SMP13_Msk (0x7U << ADC_SMPR2_SMP13_Pos) /*!< 0x00000E00 */ +#define ADC_SMPR2_SMP13 ADC_SMPR2_SMP13_Msk /*!< ADC channel 13 sampling time selection */ +#define ADC_SMPR2_SMP13_0 (0x1U << ADC_SMPR2_SMP13_Pos) /*!< 0x00000200 */ +#define ADC_SMPR2_SMP13_1 (0x2U << ADC_SMPR2_SMP13_Pos) /*!< 0x00000400 */ +#define ADC_SMPR2_SMP13_2 (0x4U << ADC_SMPR2_SMP13_Pos) /*!< 0x00000800 */ + +#define ADC_SMPR2_SMP14_Pos (12U) +#define ADC_SMPR2_SMP14_Msk (0x7U << ADC_SMPR2_SMP14_Pos) /*!< 0x00007000 */ +#define ADC_SMPR2_SMP14 ADC_SMPR2_SMP14_Msk /*!< ADC channel 14 sampling time selection */ +#define ADC_SMPR2_SMP14_0 (0x1U << ADC_SMPR2_SMP14_Pos) /*!< 0x00001000 */ +#define ADC_SMPR2_SMP14_1 (0x2U << ADC_SMPR2_SMP14_Pos) /*!< 0x00002000 */ +#define ADC_SMPR2_SMP14_2 (0x4U << ADC_SMPR2_SMP14_Pos) /*!< 0x00004000 */ + +#define ADC_SMPR2_SMP15_Pos (15U) +#define ADC_SMPR2_SMP15_Msk (0x7U << ADC_SMPR2_SMP15_Pos) /*!< 0x00038000 */ +#define ADC_SMPR2_SMP15 ADC_SMPR2_SMP15_Msk /*!< ADC channel 15 sampling time selection */ +#define ADC_SMPR2_SMP15_0 (0x1U << ADC_SMPR2_SMP15_Pos) /*!< 0x00008000 */ +#define ADC_SMPR2_SMP15_1 (0x2U << ADC_SMPR2_SMP15_Pos) /*!< 0x00010000 */ +#define ADC_SMPR2_SMP15_2 (0x4U << ADC_SMPR2_SMP15_Pos) /*!< 0x00020000 */ + +#define ADC_SMPR2_SMP16_Pos (18U) +#define ADC_SMPR2_SMP16_Msk (0x7U << ADC_SMPR2_SMP16_Pos) /*!< 0x001C0000 */ +#define ADC_SMPR2_SMP16 ADC_SMPR2_SMP16_Msk /*!< ADC channel 16 sampling time selection */ +#define ADC_SMPR2_SMP16_0 (0x1U << ADC_SMPR2_SMP16_Pos) /*!< 0x00040000 */ +#define ADC_SMPR2_SMP16_1 (0x2U << ADC_SMPR2_SMP16_Pos) /*!< 0x00080000 */ +#define ADC_SMPR2_SMP16_2 (0x4U << ADC_SMPR2_SMP16_Pos) /*!< 0x00100000 */ + +#define ADC_SMPR2_SMP17_Pos (21U) +#define ADC_SMPR2_SMP17_Msk (0x7U << ADC_SMPR2_SMP17_Pos) /*!< 0x00E00000 */ +#define ADC_SMPR2_SMP17 ADC_SMPR2_SMP17_Msk /*!< ADC channel 17 sampling time selection */ +#define ADC_SMPR2_SMP17_0 (0x1U << ADC_SMPR2_SMP17_Pos) /*!< 0x00200000 */ +#define ADC_SMPR2_SMP17_1 (0x2U << ADC_SMPR2_SMP17_Pos) /*!< 0x00400000 */ +#define ADC_SMPR2_SMP17_2 (0x4U << ADC_SMPR2_SMP17_Pos) /*!< 0x00800000 */ + +#define ADC_SMPR2_SMP18_Pos (24U) +#define ADC_SMPR2_SMP18_Msk (0x7U << ADC_SMPR2_SMP18_Pos) /*!< 0x07000000 */ +#define ADC_SMPR2_SMP18 ADC_SMPR2_SMP18_Msk /*!< ADC channel 18 sampling time selection */ +#define ADC_SMPR2_SMP18_0 (0x1U << ADC_SMPR2_SMP18_Pos) /*!< 0x01000000 */ +#define ADC_SMPR2_SMP18_1 (0x2U << ADC_SMPR2_SMP18_Pos) /*!< 0x02000000 */ +#define ADC_SMPR2_SMP18_2 (0x4U << ADC_SMPR2_SMP18_Pos) /*!< 0x04000000 */ + +/******************** Bit definition for ADC_TR1 register *******************/ +#define ADC_TR1_LT1_Pos (0U) +#define ADC_TR1_LT1_Msk (0xFFFU << ADC_TR1_LT1_Pos) /*!< 0x00000FFF */ +#define ADC_TR1_LT1 ADC_TR1_LT1_Msk /*!< ADC analog watchdog 1 threshold low */ +#define ADC_TR1_LT1_0 (0x001U << ADC_TR1_LT1_Pos) /*!< 0x00000001 */ +#define ADC_TR1_LT1_1 (0x002U << ADC_TR1_LT1_Pos) /*!< 0x00000002 */ +#define ADC_TR1_LT1_2 (0x004U << ADC_TR1_LT1_Pos) /*!< 0x00000004 */ +#define ADC_TR1_LT1_3 (0x008U << ADC_TR1_LT1_Pos) /*!< 0x00000008 */ +#define ADC_TR1_LT1_4 (0x010U << ADC_TR1_LT1_Pos) /*!< 0x00000010 */ +#define ADC_TR1_LT1_5 (0x020U << ADC_TR1_LT1_Pos) /*!< 0x00000020 */ +#define ADC_TR1_LT1_6 (0x040U << ADC_TR1_LT1_Pos) /*!< 0x00000040 */ +#define ADC_TR1_LT1_7 (0x080U << ADC_TR1_LT1_Pos) /*!< 0x00000080 */ +#define ADC_TR1_LT1_8 (0x100U << ADC_TR1_LT1_Pos) /*!< 0x00000100 */ +#define ADC_TR1_LT1_9 (0x200U << ADC_TR1_LT1_Pos) /*!< 0x00000200 */ +#define ADC_TR1_LT1_10 (0x400U << ADC_TR1_LT1_Pos) /*!< 0x00000400 */ +#define ADC_TR1_LT1_11 (0x800U << ADC_TR1_LT1_Pos) /*!< 0x00000800 */ + +#define ADC_TR1_HT1_Pos (16U) +#define ADC_TR1_HT1_Msk (0xFFFU << ADC_TR1_HT1_Pos) /*!< 0x0FFF0000 */ +#define ADC_TR1_HT1 ADC_TR1_HT1_Msk /*!< ADC Analog watchdog 1 threshold high */ +#define ADC_TR1_HT1_0 (0x001U << ADC_TR1_HT1_Pos) /*!< 0x00010000 */ +#define ADC_TR1_HT1_1 (0x002U << ADC_TR1_HT1_Pos) /*!< 0x00020000 */ +#define ADC_TR1_HT1_2 (0x004U << ADC_TR1_HT1_Pos) /*!< 0x00040000 */ +#define ADC_TR1_HT1_3 (0x008U << ADC_TR1_HT1_Pos) /*!< 0x00080000 */ +#define ADC_TR1_HT1_4 (0x010U << ADC_TR1_HT1_Pos) /*!< 0x00100000 */ +#define ADC_TR1_HT1_5 (0x020U << ADC_TR1_HT1_Pos) /*!< 0x00200000 */ +#define ADC_TR1_HT1_6 (0x040U << ADC_TR1_HT1_Pos) /*!< 0x00400000 */ +#define ADC_TR1_HT1_7 (0x080U << ADC_TR1_HT1_Pos) /*!< 0x00800000 */ +#define ADC_TR1_HT1_8 (0x100U << ADC_TR1_HT1_Pos) /*!< 0x01000000 */ +#define ADC_TR1_HT1_9 (0x200U << ADC_TR1_HT1_Pos) /*!< 0x02000000 */ +#define ADC_TR1_HT1_10 (0x400U << ADC_TR1_HT1_Pos) /*!< 0x04000000 */ +#define ADC_TR1_HT1_11 (0x800U << ADC_TR1_HT1_Pos) /*!< 0x08000000 */ + +/******************** Bit definition for ADC_TR2 register *******************/ +#define ADC_TR2_LT2_Pos (0U) +#define ADC_TR2_LT2_Msk (0xFFU << ADC_TR2_LT2_Pos) /*!< 0x000000FF */ +#define ADC_TR2_LT2 ADC_TR2_LT2_Msk /*!< ADC analog watchdog 2 threshold low */ +#define ADC_TR2_LT2_0 (0x01U << ADC_TR2_LT2_Pos) /*!< 0x00000001 */ +#define ADC_TR2_LT2_1 (0x02U << ADC_TR2_LT2_Pos) /*!< 0x00000002 */ +#define ADC_TR2_LT2_2 (0x04U << ADC_TR2_LT2_Pos) /*!< 0x00000004 */ +#define ADC_TR2_LT2_3 (0x08U << ADC_TR2_LT2_Pos) /*!< 0x00000008 */ +#define ADC_TR2_LT2_4 (0x10U << ADC_TR2_LT2_Pos) /*!< 0x00000010 */ +#define ADC_TR2_LT2_5 (0x20U << ADC_TR2_LT2_Pos) /*!< 0x00000020 */ +#define ADC_TR2_LT2_6 (0x40U << ADC_TR2_LT2_Pos) /*!< 0x00000040 */ +#define ADC_TR2_LT2_7 (0x80U << ADC_TR2_LT2_Pos) /*!< 0x00000080 */ + +#define ADC_TR2_HT2_Pos (16U) +#define ADC_TR2_HT2_Msk (0xFFU << ADC_TR2_HT2_Pos) /*!< 0x00FF0000 */ +#define ADC_TR2_HT2 ADC_TR2_HT2_Msk /*!< ADC analog watchdog 2 threshold high */ +#define ADC_TR2_HT2_0 (0x01U << ADC_TR2_HT2_Pos) /*!< 0x00010000 */ +#define ADC_TR2_HT2_1 (0x02U << ADC_TR2_HT2_Pos) /*!< 0x00020000 */ +#define ADC_TR2_HT2_2 (0x04U << ADC_TR2_HT2_Pos) /*!< 0x00040000 */ +#define ADC_TR2_HT2_3 (0x08U << ADC_TR2_HT2_Pos) /*!< 0x00080000 */ +#define ADC_TR2_HT2_4 (0x10U << ADC_TR2_HT2_Pos) /*!< 0x00100000 */ +#define ADC_TR2_HT2_5 (0x20U << ADC_TR2_HT2_Pos) /*!< 0x00200000 */ +#define ADC_TR2_HT2_6 (0x40U << ADC_TR2_HT2_Pos) /*!< 0x00400000 */ +#define ADC_TR2_HT2_7 (0x80U << ADC_TR2_HT2_Pos) /*!< 0x00800000 */ + +/******************** Bit definition for ADC_TR3 register *******************/ +#define ADC_TR3_LT3_Pos (0U) +#define ADC_TR3_LT3_Msk (0xFFU << ADC_TR3_LT3_Pos) /*!< 0x000000FF */ +#define ADC_TR3_LT3 ADC_TR3_LT3_Msk /*!< ADC analog watchdog 3 threshold low */ +#define ADC_TR3_LT3_0 (0x01U << ADC_TR3_LT3_Pos) /*!< 0x00000001 */ +#define ADC_TR3_LT3_1 (0x02U << ADC_TR3_LT3_Pos) /*!< 0x00000002 */ +#define ADC_TR3_LT3_2 (0x04U << ADC_TR3_LT3_Pos) /*!< 0x00000004 */ +#define ADC_TR3_LT3_3 (0x08U << ADC_TR3_LT3_Pos) /*!< 0x00000008 */ +#define ADC_TR3_LT3_4 (0x10U << ADC_TR3_LT3_Pos) /*!< 0x00000010 */ +#define ADC_TR3_LT3_5 (0x20U << ADC_TR3_LT3_Pos) /*!< 0x00000020 */ +#define ADC_TR3_LT3_6 (0x40U << ADC_TR3_LT3_Pos) /*!< 0x00000040 */ +#define ADC_TR3_LT3_7 (0x80U << ADC_TR3_LT3_Pos) /*!< 0x00000080 */ + +#define ADC_TR3_HT3_Pos (16U) +#define ADC_TR3_HT3_Msk (0xFFU << ADC_TR3_HT3_Pos) /*!< 0x00FF0000 */ +#define ADC_TR3_HT3 ADC_TR3_HT3_Msk /*!< ADC analog watchdog 3 threshold high */ +#define ADC_TR3_HT3_0 (0x01U << ADC_TR3_HT3_Pos) /*!< 0x00010000 */ +#define ADC_TR3_HT3_1 (0x02U << ADC_TR3_HT3_Pos) /*!< 0x00020000 */ +#define ADC_TR3_HT3_2 (0x04U << ADC_TR3_HT3_Pos) /*!< 0x00040000 */ +#define ADC_TR3_HT3_3 (0x08U << ADC_TR3_HT3_Pos) /*!< 0x00080000 */ +#define ADC_TR3_HT3_4 (0x10U << ADC_TR3_HT3_Pos) /*!< 0x00100000 */ +#define ADC_TR3_HT3_5 (0x20U << ADC_TR3_HT3_Pos) /*!< 0x00200000 */ +#define ADC_TR3_HT3_6 (0x40U << ADC_TR3_HT3_Pos) /*!< 0x00400000 */ +#define ADC_TR3_HT3_7 (0x80U << ADC_TR3_HT3_Pos) /*!< 0x00800000 */ + +/******************** Bit definition for ADC_SQR1 register ******************/ +#define ADC_SQR1_L_Pos (0U) +#define ADC_SQR1_L_Msk (0xFU << ADC_SQR1_L_Pos) /*!< 0x0000000F */ +#define ADC_SQR1_L ADC_SQR1_L_Msk /*!< ADC group regular sequencer scan length */ +#define ADC_SQR1_L_0 (0x1U << ADC_SQR1_L_Pos) /*!< 0x00000001 */ +#define ADC_SQR1_L_1 (0x2U << ADC_SQR1_L_Pos) /*!< 0x00000002 */ +#define ADC_SQR1_L_2 (0x4U << ADC_SQR1_L_Pos) /*!< 0x00000004 */ +#define ADC_SQR1_L_3 (0x8U << ADC_SQR1_L_Pos) /*!< 0x00000008 */ + +#define ADC_SQR1_SQ1_Pos (6U) +#define ADC_SQR1_SQ1_Msk (0x1FU << ADC_SQR1_SQ1_Pos) /*!< 0x000007C0 */ +#define ADC_SQR1_SQ1 ADC_SQR1_SQ1_Msk /*!< ADC group regular sequencer rank 1 */ +#define ADC_SQR1_SQ1_0 (0x01U << ADC_SQR1_SQ1_Pos) /*!< 0x00000040 */ +#define ADC_SQR1_SQ1_1 (0x02U << ADC_SQR1_SQ1_Pos) /*!< 0x00000080 */ +#define ADC_SQR1_SQ1_2 (0x04U << ADC_SQR1_SQ1_Pos) /*!< 0x00000100 */ +#define ADC_SQR1_SQ1_3 (0x08U << ADC_SQR1_SQ1_Pos) /*!< 0x00000200 */ +#define ADC_SQR1_SQ1_4 (0x10U << ADC_SQR1_SQ1_Pos) /*!< 0x00000400 */ + +#define ADC_SQR1_SQ2_Pos (12U) +#define ADC_SQR1_SQ2_Msk (0x1FU << ADC_SQR1_SQ2_Pos) /*!< 0x0001F000 */ +#define ADC_SQR1_SQ2 ADC_SQR1_SQ2_Msk /*!< ADC group regular sequencer rank 2 */ +#define ADC_SQR1_SQ2_0 (0x01U << ADC_SQR1_SQ2_Pos) /*!< 0x00001000 */ +#define ADC_SQR1_SQ2_1 (0x02U << ADC_SQR1_SQ2_Pos) /*!< 0x00002000 */ +#define ADC_SQR1_SQ2_2 (0x04U << ADC_SQR1_SQ2_Pos) /*!< 0x00004000 */ +#define ADC_SQR1_SQ2_3 (0x08U << ADC_SQR1_SQ2_Pos) /*!< 0x00008000 */ +#define ADC_SQR1_SQ2_4 (0x10U << ADC_SQR1_SQ2_Pos) /*!< 0x00010000 */ + +#define ADC_SQR1_SQ3_Pos (18U) +#define ADC_SQR1_SQ3_Msk (0x1FU << ADC_SQR1_SQ3_Pos) /*!< 0x007C0000 */ +#define ADC_SQR1_SQ3 ADC_SQR1_SQ3_Msk /*!< ADC group regular sequencer rank 3 */ +#define ADC_SQR1_SQ3_0 (0x01U << ADC_SQR1_SQ3_Pos) /*!< 0x00040000 */ +#define ADC_SQR1_SQ3_1 (0x02U << ADC_SQR1_SQ3_Pos) /*!< 0x00080000 */ +#define ADC_SQR1_SQ3_2 (0x04U << ADC_SQR1_SQ3_Pos) /*!< 0x00100000 */ +#define ADC_SQR1_SQ3_3 (0x08U << ADC_SQR1_SQ3_Pos) /*!< 0x00200000 */ +#define ADC_SQR1_SQ3_4 (0x10U << ADC_SQR1_SQ3_Pos) /*!< 0x00400000 */ + +#define ADC_SQR1_SQ4_Pos (24U) +#define ADC_SQR1_SQ4_Msk (0x1FU << ADC_SQR1_SQ4_Pos) /*!< 0x1F000000 */ +#define ADC_SQR1_SQ4 ADC_SQR1_SQ4_Msk /*!< ADC group regular sequencer rank 4 */ +#define ADC_SQR1_SQ4_0 (0x01U << ADC_SQR1_SQ4_Pos) /*!< 0x01000000 */ +#define ADC_SQR1_SQ4_1 (0x02U << ADC_SQR1_SQ4_Pos) /*!< 0x02000000 */ +#define ADC_SQR1_SQ4_2 (0x04U << ADC_SQR1_SQ4_Pos) /*!< 0x04000000 */ +#define ADC_SQR1_SQ4_3 (0x08U << ADC_SQR1_SQ4_Pos) /*!< 0x08000000 */ +#define ADC_SQR1_SQ4_4 (0x10U << ADC_SQR1_SQ4_Pos) /*!< 0x10000000 */ + +/******************** Bit definition for ADC_SQR2 register ******************/ +#define ADC_SQR2_SQ5_Pos (0U) +#define ADC_SQR2_SQ5_Msk (0x1FU << ADC_SQR2_SQ5_Pos) /*!< 0x0000001F */ +#define ADC_SQR2_SQ5 ADC_SQR2_SQ5_Msk /*!< ADC group regular sequencer rank 5 */ +#define ADC_SQR2_SQ5_0 (0x01U << ADC_SQR2_SQ5_Pos) /*!< 0x00000001 */ +#define ADC_SQR2_SQ5_1 (0x02U << ADC_SQR2_SQ5_Pos) /*!< 0x00000002 */ +#define ADC_SQR2_SQ5_2 (0x04U << ADC_SQR2_SQ5_Pos) /*!< 0x00000004 */ +#define ADC_SQR2_SQ5_3 (0x08U << ADC_SQR2_SQ5_Pos) /*!< 0x00000008 */ +#define ADC_SQR2_SQ5_4 (0x10U << ADC_SQR2_SQ5_Pos) /*!< 0x00000010 */ + +#define ADC_SQR2_SQ6_Pos (6U) +#define ADC_SQR2_SQ6_Msk (0x1FU << ADC_SQR2_SQ6_Pos) /*!< 0x000007C0 */ +#define ADC_SQR2_SQ6 ADC_SQR2_SQ6_Msk /*!< ADC group regular sequencer rank 6 */ +#define ADC_SQR2_SQ6_0 (0x01U << ADC_SQR2_SQ6_Pos) /*!< 0x00000040 */ +#define ADC_SQR2_SQ6_1 (0x02U << ADC_SQR2_SQ6_Pos) /*!< 0x00000080 */ +#define ADC_SQR2_SQ6_2 (0x04U << ADC_SQR2_SQ6_Pos) /*!< 0x00000100 */ +#define ADC_SQR2_SQ6_3 (0x08U << ADC_SQR2_SQ6_Pos) /*!< 0x00000200 */ +#define ADC_SQR2_SQ6_4 (0x10U << ADC_SQR2_SQ6_Pos) /*!< 0x00000400 */ + +#define ADC_SQR2_SQ7_Pos (12U) +#define ADC_SQR2_SQ7_Msk (0x1FU << ADC_SQR2_SQ7_Pos) /*!< 0x0001F000 */ +#define ADC_SQR2_SQ7 ADC_SQR2_SQ7_Msk /*!< ADC group regular sequencer rank 7 */ +#define ADC_SQR2_SQ7_0 (0x01U << ADC_SQR2_SQ7_Pos) /*!< 0x00001000 */ +#define ADC_SQR2_SQ7_1 (0x02U << ADC_SQR2_SQ7_Pos) /*!< 0x00002000 */ +#define ADC_SQR2_SQ7_2 (0x04U << ADC_SQR2_SQ7_Pos) /*!< 0x00004000 */ +#define ADC_SQR2_SQ7_3 (0x08U << ADC_SQR2_SQ7_Pos) /*!< 0x00008000 */ +#define ADC_SQR2_SQ7_4 (0x10U << ADC_SQR2_SQ7_Pos) /*!< 0x00010000 */ + +#define ADC_SQR2_SQ8_Pos (18U) +#define ADC_SQR2_SQ8_Msk (0x1FU << ADC_SQR2_SQ8_Pos) /*!< 0x007C0000 */ +#define ADC_SQR2_SQ8 ADC_SQR2_SQ8_Msk /*!< ADC group regular sequencer rank 8 */ +#define ADC_SQR2_SQ8_0 (0x01U << ADC_SQR2_SQ8_Pos) /*!< 0x00040000 */ +#define ADC_SQR2_SQ8_1 (0x02U << ADC_SQR2_SQ8_Pos) /*!< 0x00080000 */ +#define ADC_SQR2_SQ8_2 (0x04U << ADC_SQR2_SQ8_Pos) /*!< 0x00100000 */ +#define ADC_SQR2_SQ8_3 (0x08U << ADC_SQR2_SQ8_Pos) /*!< 0x00200000 */ +#define ADC_SQR2_SQ8_4 (0x10U << ADC_SQR2_SQ8_Pos) /*!< 0x00400000 */ + +#define ADC_SQR2_SQ9_Pos (24U) +#define ADC_SQR2_SQ9_Msk (0x1FU << ADC_SQR2_SQ9_Pos) /*!< 0x1F000000 */ +#define ADC_SQR2_SQ9 ADC_SQR2_SQ9_Msk /*!< ADC group regular sequencer rank 9 */ +#define ADC_SQR2_SQ9_0 (0x01U << ADC_SQR2_SQ9_Pos) /*!< 0x01000000 */ +#define ADC_SQR2_SQ9_1 (0x02U << ADC_SQR2_SQ9_Pos) /*!< 0x02000000 */ +#define ADC_SQR2_SQ9_2 (0x04U << ADC_SQR2_SQ9_Pos) /*!< 0x04000000 */ +#define ADC_SQR2_SQ9_3 (0x08U << ADC_SQR2_SQ9_Pos) /*!< 0x08000000 */ +#define ADC_SQR2_SQ9_4 (0x10U << ADC_SQR2_SQ9_Pos) /*!< 0x10000000 */ + +/******************** Bit definition for ADC_SQR3 register ******************/ +#define ADC_SQR3_SQ10_Pos (0U) +#define ADC_SQR3_SQ10_Msk (0x1FU << ADC_SQR3_SQ10_Pos) /*!< 0x0000001F */ +#define ADC_SQR3_SQ10 ADC_SQR3_SQ10_Msk /*!< ADC group regular sequencer rank 10 */ +#define ADC_SQR3_SQ10_0 (0x01U << ADC_SQR3_SQ10_Pos) /*!< 0x00000001 */ +#define ADC_SQR3_SQ10_1 (0x02U << ADC_SQR3_SQ10_Pos) /*!< 0x00000002 */ +#define ADC_SQR3_SQ10_2 (0x04U << ADC_SQR3_SQ10_Pos) /*!< 0x00000004 */ +#define ADC_SQR3_SQ10_3 (0x08U << ADC_SQR3_SQ10_Pos) /*!< 0x00000008 */ +#define ADC_SQR3_SQ10_4 (0x10U << ADC_SQR3_SQ10_Pos) /*!< 0x00000010 */ + +#define ADC_SQR3_SQ11_Pos (6U) +#define ADC_SQR3_SQ11_Msk (0x1FU << ADC_SQR3_SQ11_Pos) /*!< 0x000007C0 */ +#define ADC_SQR3_SQ11 ADC_SQR3_SQ11_Msk /*!< ADC group regular sequencer rank 11 */ +#define ADC_SQR3_SQ11_0 (0x01U << ADC_SQR3_SQ11_Pos) /*!< 0x00000040 */ +#define ADC_SQR3_SQ11_1 (0x02U << ADC_SQR3_SQ11_Pos) /*!< 0x00000080 */ +#define ADC_SQR3_SQ11_2 (0x04U << ADC_SQR3_SQ11_Pos) /*!< 0x00000100 */ +#define ADC_SQR3_SQ11_3 (0x08U << ADC_SQR3_SQ11_Pos) /*!< 0x00000200 */ +#define ADC_SQR3_SQ11_4 (0x10U << ADC_SQR3_SQ11_Pos) /*!< 0x00000400 */ + +#define ADC_SQR3_SQ12_Pos (12U) +#define ADC_SQR3_SQ12_Msk (0x1FU << ADC_SQR3_SQ12_Pos) /*!< 0x0001F000 */ +#define ADC_SQR3_SQ12 ADC_SQR3_SQ12_Msk /*!< ADC group regular sequencer rank 12 */ +#define ADC_SQR3_SQ12_0 (0x01U << ADC_SQR3_SQ12_Pos) /*!< 0x00001000 */ +#define ADC_SQR3_SQ12_1 (0x02U << ADC_SQR3_SQ12_Pos) /*!< 0x00002000 */ +#define ADC_SQR3_SQ12_2 (0x04U << ADC_SQR3_SQ12_Pos) /*!< 0x00004000 */ +#define ADC_SQR3_SQ12_3 (0x08U << ADC_SQR3_SQ12_Pos) /*!< 0x00008000 */ +#define ADC_SQR3_SQ12_4 (0x10U << ADC_SQR3_SQ12_Pos) /*!< 0x00010000 */ + +#define ADC_SQR3_SQ13_Pos (18U) +#define ADC_SQR3_SQ13_Msk (0x1FU << ADC_SQR3_SQ13_Pos) /*!< 0x007C0000 */ +#define ADC_SQR3_SQ13 ADC_SQR3_SQ13_Msk /*!< ADC group regular sequencer rank 13 */ +#define ADC_SQR3_SQ13_0 (0x01U << ADC_SQR3_SQ13_Pos) /*!< 0x00040000 */ +#define ADC_SQR3_SQ13_1 (0x02U << ADC_SQR3_SQ13_Pos) /*!< 0x00080000 */ +#define ADC_SQR3_SQ13_2 (0x04U << ADC_SQR3_SQ13_Pos) /*!< 0x00100000 */ +#define ADC_SQR3_SQ13_3 (0x08U << ADC_SQR3_SQ13_Pos) /*!< 0x00200000 */ +#define ADC_SQR3_SQ13_4 (0x10U << ADC_SQR3_SQ13_Pos) /*!< 0x00400000 */ + +#define ADC_SQR3_SQ14_Pos (24U) +#define ADC_SQR3_SQ14_Msk (0x1FU << ADC_SQR3_SQ14_Pos) /*!< 0x1F000000 */ +#define ADC_SQR3_SQ14 ADC_SQR3_SQ14_Msk /*!< ADC group regular sequencer rank 14 */ +#define ADC_SQR3_SQ14_0 (0x01U << ADC_SQR3_SQ14_Pos) /*!< 0x01000000 */ +#define ADC_SQR3_SQ14_1 (0x02U << ADC_SQR3_SQ14_Pos) /*!< 0x02000000 */ +#define ADC_SQR3_SQ14_2 (0x04U << ADC_SQR3_SQ14_Pos) /*!< 0x04000000 */ +#define ADC_SQR3_SQ14_3 (0x08U << ADC_SQR3_SQ14_Pos) /*!< 0x08000000 */ +#define ADC_SQR3_SQ14_4 (0x10U << ADC_SQR3_SQ14_Pos) /*!< 0x10000000 */ + +/******************** Bit definition for ADC_SQR4 register ******************/ +#define ADC_SQR4_SQ15_Pos (0U) +#define ADC_SQR4_SQ15_Msk (0x1FU << ADC_SQR4_SQ15_Pos) /*!< 0x0000001F */ +#define ADC_SQR4_SQ15 ADC_SQR4_SQ15_Msk /*!< ADC group regular sequencer rank 15 */ +#define ADC_SQR4_SQ15_0 (0x01U << ADC_SQR4_SQ15_Pos) /*!< 0x00000001 */ +#define ADC_SQR4_SQ15_1 (0x02U << ADC_SQR4_SQ15_Pos) /*!< 0x00000002 */ +#define ADC_SQR4_SQ15_2 (0x04U << ADC_SQR4_SQ15_Pos) /*!< 0x00000004 */ +#define ADC_SQR4_SQ15_3 (0x08U << ADC_SQR4_SQ15_Pos) /*!< 0x00000008 */ +#define ADC_SQR4_SQ15_4 (0x10U << ADC_SQR4_SQ15_Pos) /*!< 0x00000010 */ + +#define ADC_SQR4_SQ16_Pos (6U) +#define ADC_SQR4_SQ16_Msk (0x1FU << ADC_SQR4_SQ16_Pos) /*!< 0x000007C0 */ +#define ADC_SQR4_SQ16 ADC_SQR4_SQ16_Msk /*!< ADC group regular sequencer rank 16 */ +#define ADC_SQR4_SQ16_0 (0x01U << ADC_SQR4_SQ16_Pos) /*!< 0x00000040 */ +#define ADC_SQR4_SQ16_1 (0x02U << ADC_SQR4_SQ16_Pos) /*!< 0x00000080 */ +#define ADC_SQR4_SQ16_2 (0x04U << ADC_SQR4_SQ16_Pos) /*!< 0x00000100 */ +#define ADC_SQR4_SQ16_3 (0x08U << ADC_SQR4_SQ16_Pos) /*!< 0x00000200 */ +#define ADC_SQR4_SQ16_4 (0x10U << ADC_SQR4_SQ16_Pos) /*!< 0x00000400 */ + +/******************** Bit definition for ADC_DR register ********************/ +#define ADC_DR_RDATA_Pos (0U) +#define ADC_DR_RDATA_Msk (0xFFFFU << ADC_DR_RDATA_Pos) /*!< 0x0000FFFF */ +#define ADC_DR_RDATA ADC_DR_RDATA_Msk /*!< ADC group regular conversion data */ +#define ADC_DR_RDATA_0 (0x0001U << ADC_DR_RDATA_Pos) /*!< 0x00000001 */ +#define ADC_DR_RDATA_1 (0x0002U << ADC_DR_RDATA_Pos) /*!< 0x00000002 */ +#define ADC_DR_RDATA_2 (0x0004U << ADC_DR_RDATA_Pos) /*!< 0x00000004 */ +#define ADC_DR_RDATA_3 (0x0008U << ADC_DR_RDATA_Pos) /*!< 0x00000008 */ +#define ADC_DR_RDATA_4 (0x0010U << ADC_DR_RDATA_Pos) /*!< 0x00000010 */ +#define ADC_DR_RDATA_5 (0x0020U << ADC_DR_RDATA_Pos) /*!< 0x00000020 */ +#define ADC_DR_RDATA_6 (0x0040U << ADC_DR_RDATA_Pos) /*!< 0x00000040 */ +#define ADC_DR_RDATA_7 (0x0080U << ADC_DR_RDATA_Pos) /*!< 0x00000080 */ +#define ADC_DR_RDATA_8 (0x0100U << ADC_DR_RDATA_Pos) /*!< 0x00000100 */ +#define ADC_DR_RDATA_9 (0x0200U << ADC_DR_RDATA_Pos) /*!< 0x00000200 */ +#define ADC_DR_RDATA_10 (0x0400U << ADC_DR_RDATA_Pos) /*!< 0x00000400 */ +#define ADC_DR_RDATA_11 (0x0800U << ADC_DR_RDATA_Pos) /*!< 0x00000800 */ +#define ADC_DR_RDATA_12 (0x1000U << ADC_DR_RDATA_Pos) /*!< 0x00001000 */ +#define ADC_DR_RDATA_13 (0x2000U << ADC_DR_RDATA_Pos) /*!< 0x00002000 */ +#define ADC_DR_RDATA_14 (0x4000U << ADC_DR_RDATA_Pos) /*!< 0x00004000 */ +#define ADC_DR_RDATA_15 (0x8000U << ADC_DR_RDATA_Pos) /*!< 0x00008000 */ + +/******************** Bit definition for ADC_JSQR register ******************/ +#define ADC_JSQR_JL_Pos (0U) +#define ADC_JSQR_JL_Msk (0x3U << ADC_JSQR_JL_Pos) /*!< 0x00000003 */ +#define ADC_JSQR_JL ADC_JSQR_JL_Msk /*!< ADC group injected sequencer scan length */ +#define ADC_JSQR_JL_0 (0x1U << ADC_JSQR_JL_Pos) /*!< 0x00000001 */ +#define ADC_JSQR_JL_1 (0x2U << ADC_JSQR_JL_Pos) /*!< 0x00000002 */ + +#define ADC_JSQR_JEXTSEL_Pos (2U) +#define ADC_JSQR_JEXTSEL_Msk (0xFU << ADC_JSQR_JEXTSEL_Pos) /*!< 0x0000003C */ +#define ADC_JSQR_JEXTSEL ADC_JSQR_JEXTSEL_Msk /*!< ADC group injected external trigger source */ +#define ADC_JSQR_JEXTSEL_0 (0x1U << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000004 */ +#define ADC_JSQR_JEXTSEL_1 (0x2U << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000008 */ +#define ADC_JSQR_JEXTSEL_2 (0x4U << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000010 */ +#define ADC_JSQR_JEXTSEL_3 (0x8U << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000020 */ + +#define ADC_JSQR_JEXTEN_Pos (6U) +#define ADC_JSQR_JEXTEN_Msk (0x3U << ADC_JSQR_JEXTEN_Pos) /*!< 0x000000C0 */ +#define ADC_JSQR_JEXTEN ADC_JSQR_JEXTEN_Msk /*!< ADC group injected external trigger polarity */ +#define ADC_JSQR_JEXTEN_0 (0x1U << ADC_JSQR_JEXTEN_Pos) /*!< 0x00000040 */ +#define ADC_JSQR_JEXTEN_1 (0x2U << ADC_JSQR_JEXTEN_Pos) /*!< 0x00000080 */ + +#define ADC_JSQR_JSQ1_Pos (8U) +#define ADC_JSQR_JSQ1_Msk (0x1FU << ADC_JSQR_JSQ1_Pos) /*!< 0x00001F00 */ +#define ADC_JSQR_JSQ1 ADC_JSQR_JSQ1_Msk /*!< ADC group injected sequencer rank 1 */ +#define ADC_JSQR_JSQ1_0 (0x01U << ADC_JSQR_JSQ1_Pos) /*!< 0x00000100 */ +#define ADC_JSQR_JSQ1_1 (0x02U << ADC_JSQR_JSQ1_Pos) /*!< 0x00000200 */ +#define ADC_JSQR_JSQ1_2 (0x04U << ADC_JSQR_JSQ1_Pos) /*!< 0x00000400 */ +#define ADC_JSQR_JSQ1_3 (0x08U << ADC_JSQR_JSQ1_Pos) /*!< 0x00000800 */ +#define ADC_JSQR_JSQ1_4 (0x10U << ADC_JSQR_JSQ1_Pos) /*!< 0x00001000 */ + +#define ADC_JSQR_JSQ2_Pos (14U) +#define ADC_JSQR_JSQ2_Msk (0x1FU << ADC_JSQR_JSQ2_Pos) /*!< 0x0007C000 */ +#define ADC_JSQR_JSQ2 ADC_JSQR_JSQ2_Msk /*!< ADC group injected sequencer rank 2 */ +#define ADC_JSQR_JSQ2_0 (0x01U << ADC_JSQR_JSQ2_Pos) /*!< 0x00004000 */ +#define ADC_JSQR_JSQ2_1 (0x02U << ADC_JSQR_JSQ2_Pos) /*!< 0x00008000 */ +#define ADC_JSQR_JSQ2_2 (0x04U << ADC_JSQR_JSQ2_Pos) /*!< 0x00010000 */ +#define ADC_JSQR_JSQ2_3 (0x08U << ADC_JSQR_JSQ2_Pos) /*!< 0x00020000 */ +#define ADC_JSQR_JSQ2_4 (0x10U << ADC_JSQR_JSQ2_Pos) /*!< 0x00040000 */ + +#define ADC_JSQR_JSQ3_Pos (20U) +#define ADC_JSQR_JSQ3_Msk (0x1FU << ADC_JSQR_JSQ3_Pos) /*!< 0x01F00000 */ +#define ADC_JSQR_JSQ3 ADC_JSQR_JSQ3_Msk /*!< ADC group injected sequencer rank 3 */ +#define ADC_JSQR_JSQ3_0 (0x01U << ADC_JSQR_JSQ3_Pos) /*!< 0x00100000 */ +#define ADC_JSQR_JSQ3_1 (0x02U << ADC_JSQR_JSQ3_Pos) /*!< 0x00200000 */ +#define ADC_JSQR_JSQ3_2 (0x04U << ADC_JSQR_JSQ3_Pos) /*!< 0x00400000 */ +#define ADC_JSQR_JSQ3_3 (0x08U << ADC_JSQR_JSQ3_Pos) /*!< 0x00800000 */ +#define ADC_JSQR_JSQ3_4 (0x10U << ADC_JSQR_JSQ3_Pos) /*!< 0x01000000 */ + +#define ADC_JSQR_JSQ4_Pos (26U) +#define ADC_JSQR_JSQ4_Msk (0x1FU << ADC_JSQR_JSQ4_Pos) /*!< 0x7C000000 */ +#define ADC_JSQR_JSQ4 ADC_JSQR_JSQ4_Msk /*!< ADC group injected sequencer rank 4 */ +#define ADC_JSQR_JSQ4_0 (0x01U << ADC_JSQR_JSQ4_Pos) /*!< 0x04000000 */ +#define ADC_JSQR_JSQ4_1 (0x02U << ADC_JSQR_JSQ4_Pos) /*!< 0x08000000 */ +#define ADC_JSQR_JSQ4_2 (0x04U << ADC_JSQR_JSQ4_Pos) /*!< 0x10000000 */ +#define ADC_JSQR_JSQ4_3 (0x08U << ADC_JSQR_JSQ4_Pos) /*!< 0x20000000 */ +#define ADC_JSQR_JSQ4_4 (0x10U << ADC_JSQR_JSQ4_Pos) /*!< 0x40000000 */ + +/******************** Bit definition for ADC_OFR1 register ******************/ +#define ADC_OFR1_OFFSET1_Pos (0U) +#define ADC_OFR1_OFFSET1_Msk (0xFFFU << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000FFF */ +#define ADC_OFR1_OFFSET1 ADC_OFR1_OFFSET1_Msk /*!< ADC offset number 1 offset level */ +#define ADC_OFR1_OFFSET1_0 (0x001U << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000001 */ +#define ADC_OFR1_OFFSET1_1 (0x002U << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000002 */ +#define ADC_OFR1_OFFSET1_2 (0x004U << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000004 */ +#define ADC_OFR1_OFFSET1_3 (0x008U << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000008 */ +#define ADC_OFR1_OFFSET1_4 (0x010U << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000010 */ +#define ADC_OFR1_OFFSET1_5 (0x020U << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000020 */ +#define ADC_OFR1_OFFSET1_6 (0x040U << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000040 */ +#define ADC_OFR1_OFFSET1_7 (0x080U << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000080 */ +#define ADC_OFR1_OFFSET1_8 (0x100U << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000100 */ +#define ADC_OFR1_OFFSET1_9 (0x200U << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000200 */ +#define ADC_OFR1_OFFSET1_10 (0x400U << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000400 */ +#define ADC_OFR1_OFFSET1_11 (0x800U << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000800 */ + +#define ADC_OFR1_OFFSET1_CH_Pos (26U) +#define ADC_OFR1_OFFSET1_CH_Msk (0x1FU << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x7C000000 */ +#define ADC_OFR1_OFFSET1_CH ADC_OFR1_OFFSET1_CH_Msk /*!< ADC offset number 1 channel selection */ +#define ADC_OFR1_OFFSET1_CH_0 (0x01U << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x04000000 */ +#define ADC_OFR1_OFFSET1_CH_1 (0x02U << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x08000000 */ +#define ADC_OFR1_OFFSET1_CH_2 (0x04U << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x10000000 */ +#define ADC_OFR1_OFFSET1_CH_3 (0x08U << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x20000000 */ +#define ADC_OFR1_OFFSET1_CH_4 (0x10U << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x40000000 */ + +#define ADC_OFR1_OFFSET1_EN_Pos (31U) +#define ADC_OFR1_OFFSET1_EN_Msk (0x1U << ADC_OFR1_OFFSET1_EN_Pos) /*!< 0x80000000 */ +#define ADC_OFR1_OFFSET1_EN ADC_OFR1_OFFSET1_EN_Msk /*!< ADC offset number 1 enable */ + +/******************** Bit definition for ADC_OFR2 register ******************/ +#define ADC_OFR2_OFFSET2_Pos (0U) +#define ADC_OFR2_OFFSET2_Msk (0xFFFU << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000FFF */ +#define ADC_OFR2_OFFSET2 ADC_OFR2_OFFSET2_Msk /*!< ADC offset number 2 offset level */ +#define ADC_OFR2_OFFSET2_0 (0x001U << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000001 */ +#define ADC_OFR2_OFFSET2_1 (0x002U << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000002 */ +#define ADC_OFR2_OFFSET2_2 (0x004U << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000004 */ +#define ADC_OFR2_OFFSET2_3 (0x008U << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000008 */ +#define ADC_OFR2_OFFSET2_4 (0x010U << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000010 */ +#define ADC_OFR2_OFFSET2_5 (0x020U << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000020 */ +#define ADC_OFR2_OFFSET2_6 (0x040U << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000040 */ +#define ADC_OFR2_OFFSET2_7 (0x080U << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000080 */ +#define ADC_OFR2_OFFSET2_8 (0x100U << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000100 */ +#define ADC_OFR2_OFFSET2_9 (0x200U << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000200 */ +#define ADC_OFR2_OFFSET2_10 (0x400U << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000400 */ +#define ADC_OFR2_OFFSET2_11 (0x800U << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000800 */ + +#define ADC_OFR2_OFFSET2_CH_Pos (26U) +#define ADC_OFR2_OFFSET2_CH_Msk (0x1FU << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x7C000000 */ +#define ADC_OFR2_OFFSET2_CH ADC_OFR2_OFFSET2_CH_Msk /*!< ADC offset number 2 channel selection */ +#define ADC_OFR2_OFFSET2_CH_0 (0x01U << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x04000000 */ +#define ADC_OFR2_OFFSET2_CH_1 (0x02U << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x08000000 */ +#define ADC_OFR2_OFFSET2_CH_2 (0x04U << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x10000000 */ +#define ADC_OFR2_OFFSET2_CH_3 (0x08U << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x20000000 */ +#define ADC_OFR2_OFFSET2_CH_4 (0x10U << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x40000000 */ + +#define ADC_OFR2_OFFSET2_EN_Pos (31U) +#define ADC_OFR2_OFFSET2_EN_Msk (0x1U << ADC_OFR2_OFFSET2_EN_Pos) /*!< 0x80000000 */ +#define ADC_OFR2_OFFSET2_EN ADC_OFR2_OFFSET2_EN_Msk /*!< ADC offset number 2 enable */ + +/******************** Bit definition for ADC_OFR3 register ******************/ +#define ADC_OFR3_OFFSET3_Pos (0U) +#define ADC_OFR3_OFFSET3_Msk (0xFFFU << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000FFF */ +#define ADC_OFR3_OFFSET3 ADC_OFR3_OFFSET3_Msk /*!< ADC offset number 3 offset level */ +#define ADC_OFR3_OFFSET3_0 (0x001U << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000001 */ +#define ADC_OFR3_OFFSET3_1 (0x002U << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000002 */ +#define ADC_OFR3_OFFSET3_2 (0x004U << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000004 */ +#define ADC_OFR3_OFFSET3_3 (0x008U << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000008 */ +#define ADC_OFR3_OFFSET3_4 (0x010U << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000010 */ +#define ADC_OFR3_OFFSET3_5 (0x020U << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000020 */ +#define ADC_OFR3_OFFSET3_6 (0x040U << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000040 */ +#define ADC_OFR3_OFFSET3_7 (0x080U << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000080 */ +#define ADC_OFR3_OFFSET3_8 (0x100U << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000100 */ +#define ADC_OFR3_OFFSET3_9 (0x200U << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000200 */ +#define ADC_OFR3_OFFSET3_10 (0x400U << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000400 */ +#define ADC_OFR3_OFFSET3_11 (0x800U << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000800 */ + +#define ADC_OFR3_OFFSET3_CH_Pos (26U) +#define ADC_OFR3_OFFSET3_CH_Msk (0x1FU << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x7C000000 */ +#define ADC_OFR3_OFFSET3_CH ADC_OFR3_OFFSET3_CH_Msk /*!< ADC offset number 3 channel selection */ +#define ADC_OFR3_OFFSET3_CH_0 (0x01U << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x04000000 */ +#define ADC_OFR3_OFFSET3_CH_1 (0x02U << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x08000000 */ +#define ADC_OFR3_OFFSET3_CH_2 (0x04U << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x10000000 */ +#define ADC_OFR3_OFFSET3_CH_3 (0x08U << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x20000000 */ +#define ADC_OFR3_OFFSET3_CH_4 (0x10U << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x40000000 */ + +#define ADC_OFR3_OFFSET3_EN_Pos (31U) +#define ADC_OFR3_OFFSET3_EN_Msk (0x1U << ADC_OFR3_OFFSET3_EN_Pos) /*!< 0x80000000 */ +#define ADC_OFR3_OFFSET3_EN ADC_OFR3_OFFSET3_EN_Msk /*!< ADC offset number 3 enable */ + +/******************** Bit definition for ADC_OFR4 register ******************/ +#define ADC_OFR4_OFFSET4_Pos (0U) +#define ADC_OFR4_OFFSET4_Msk (0xFFFU << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000FFF */ +#define ADC_OFR4_OFFSET4 ADC_OFR4_OFFSET4_Msk /*!< ADC offset number 4 offset level */ +#define ADC_OFR4_OFFSET4_0 (0x001U << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000001 */ +#define ADC_OFR4_OFFSET4_1 (0x002U << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000002 */ +#define ADC_OFR4_OFFSET4_2 (0x004U << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000004 */ +#define ADC_OFR4_OFFSET4_3 (0x008U << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000008 */ +#define ADC_OFR4_OFFSET4_4 (0x010U << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000010 */ +#define ADC_OFR4_OFFSET4_5 (0x020U << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000020 */ +#define ADC_OFR4_OFFSET4_6 (0x040U << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000040 */ +#define ADC_OFR4_OFFSET4_7 (0x080U << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000080 */ +#define ADC_OFR4_OFFSET4_8 (0x100U << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000100 */ +#define ADC_OFR4_OFFSET4_9 (0x200U << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000200 */ +#define ADC_OFR4_OFFSET4_10 (0x400U << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000400 */ +#define ADC_OFR4_OFFSET4_11 (0x800U << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000800 */ + +#define ADC_OFR4_OFFSET4_CH_Pos (26U) +#define ADC_OFR4_OFFSET4_CH_Msk (0x1FU << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x7C000000 */ +#define ADC_OFR4_OFFSET4_CH ADC_OFR4_OFFSET4_CH_Msk /*!< ADC offset number 4 channel selection */ +#define ADC_OFR4_OFFSET4_CH_0 (0x01U << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x04000000 */ +#define ADC_OFR4_OFFSET4_CH_1 (0x02U << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x08000000 */ +#define ADC_OFR4_OFFSET4_CH_2 (0x04U << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x10000000 */ +#define ADC_OFR4_OFFSET4_CH_3 (0x08U << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x20000000 */ +#define ADC_OFR4_OFFSET4_CH_4 (0x10U << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x40000000 */ + +#define ADC_OFR4_OFFSET4_EN_Pos (31U) +#define ADC_OFR4_OFFSET4_EN_Msk (0x1U << ADC_OFR4_OFFSET4_EN_Pos) /*!< 0x80000000 */ +#define ADC_OFR4_OFFSET4_EN ADC_OFR4_OFFSET4_EN_Msk /*!< ADC offset number 4 enable */ + +/******************** Bit definition for ADC_JDR1 register ******************/ +#define ADC_JDR1_JDATA_Pos (0U) +#define ADC_JDR1_JDATA_Msk (0xFFFFU << ADC_JDR1_JDATA_Pos) /*!< 0x0000FFFF */ +#define ADC_JDR1_JDATA ADC_JDR1_JDATA_Msk /*!< ADC group injected sequencer rank 1 conversion data */ +#define ADC_JDR1_JDATA_0 (0x0001U << ADC_JDR1_JDATA_Pos) /*!< 0x00000001 */ +#define ADC_JDR1_JDATA_1 (0x0002U << ADC_JDR1_JDATA_Pos) /*!< 0x00000002 */ +#define ADC_JDR1_JDATA_2 (0x0004U << ADC_JDR1_JDATA_Pos) /*!< 0x00000004 */ +#define ADC_JDR1_JDATA_3 (0x0008U << ADC_JDR1_JDATA_Pos) /*!< 0x00000008 */ +#define ADC_JDR1_JDATA_4 (0x0010U << ADC_JDR1_JDATA_Pos) /*!< 0x00000010 */ +#define ADC_JDR1_JDATA_5 (0x0020U << ADC_JDR1_JDATA_Pos) /*!< 0x00000020 */ +#define ADC_JDR1_JDATA_6 (0x0040U << ADC_JDR1_JDATA_Pos) /*!< 0x00000040 */ +#define ADC_JDR1_JDATA_7 (0x0080U << ADC_JDR1_JDATA_Pos) /*!< 0x00000080 */ +#define ADC_JDR1_JDATA_8 (0x0100U << ADC_JDR1_JDATA_Pos) /*!< 0x00000100 */ +#define ADC_JDR1_JDATA_9 (0x0200U << ADC_JDR1_JDATA_Pos) /*!< 0x00000200 */ +#define ADC_JDR1_JDATA_10 (0x0400U << ADC_JDR1_JDATA_Pos) /*!< 0x00000400 */ +#define ADC_JDR1_JDATA_11 (0x0800U << ADC_JDR1_JDATA_Pos) /*!< 0x00000800 */ +#define ADC_JDR1_JDATA_12 (0x1000U << ADC_JDR1_JDATA_Pos) /*!< 0x00001000 */ +#define ADC_JDR1_JDATA_13 (0x2000U << ADC_JDR1_JDATA_Pos) /*!< 0x00002000 */ +#define ADC_JDR1_JDATA_14 (0x4000U << ADC_JDR1_JDATA_Pos) /*!< 0x00004000 */ +#define ADC_JDR1_JDATA_15 (0x8000U << ADC_JDR1_JDATA_Pos) /*!< 0x00008000 */ + +/******************** Bit definition for ADC_JDR2 register ******************/ +#define ADC_JDR2_JDATA_Pos (0U) +#define ADC_JDR2_JDATA_Msk (0xFFFFU << ADC_JDR2_JDATA_Pos) /*!< 0x0000FFFF */ +#define ADC_JDR2_JDATA ADC_JDR2_JDATA_Msk /*!< ADC group injected sequencer rank 2 conversion data */ +#define ADC_JDR2_JDATA_0 (0x0001U << ADC_JDR2_JDATA_Pos) /*!< 0x00000001 */ +#define ADC_JDR2_JDATA_1 (0x0002U << ADC_JDR2_JDATA_Pos) /*!< 0x00000002 */ +#define ADC_JDR2_JDATA_2 (0x0004U << ADC_JDR2_JDATA_Pos) /*!< 0x00000004 */ +#define ADC_JDR2_JDATA_3 (0x0008U << ADC_JDR2_JDATA_Pos) /*!< 0x00000008 */ +#define ADC_JDR2_JDATA_4 (0x0010U << ADC_JDR2_JDATA_Pos) /*!< 0x00000010 */ +#define ADC_JDR2_JDATA_5 (0x0020U << ADC_JDR2_JDATA_Pos) /*!< 0x00000020 */ +#define ADC_JDR2_JDATA_6 (0x0040U << ADC_JDR2_JDATA_Pos) /*!< 0x00000040 */ +#define ADC_JDR2_JDATA_7 (0x0080U << ADC_JDR2_JDATA_Pos) /*!< 0x00000080 */ +#define ADC_JDR2_JDATA_8 (0x0100U << ADC_JDR2_JDATA_Pos) /*!< 0x00000100 */ +#define ADC_JDR2_JDATA_9 (0x0200U << ADC_JDR2_JDATA_Pos) /*!< 0x00000200 */ +#define ADC_JDR2_JDATA_10 (0x0400U << ADC_JDR2_JDATA_Pos) /*!< 0x00000400 */ +#define ADC_JDR2_JDATA_11 (0x0800U << ADC_JDR2_JDATA_Pos) /*!< 0x00000800 */ +#define ADC_JDR2_JDATA_12 (0x1000U << ADC_JDR2_JDATA_Pos) /*!< 0x00001000 */ +#define ADC_JDR2_JDATA_13 (0x2000U << ADC_JDR2_JDATA_Pos) /*!< 0x00002000 */ +#define ADC_JDR2_JDATA_14 (0x4000U << ADC_JDR2_JDATA_Pos) /*!< 0x00004000 */ +#define ADC_JDR2_JDATA_15 (0x8000U << ADC_JDR2_JDATA_Pos) /*!< 0x00008000 */ + +/******************** Bit definition for ADC_JDR3 register ******************/ +#define ADC_JDR3_JDATA_Pos (0U) +#define ADC_JDR3_JDATA_Msk (0xFFFFU << ADC_JDR3_JDATA_Pos) /*!< 0x0000FFFF */ +#define ADC_JDR3_JDATA ADC_JDR3_JDATA_Msk /*!< ADC group injected sequencer rank 3 conversion data */ +#define ADC_JDR3_JDATA_0 (0x0001U << ADC_JDR3_JDATA_Pos) /*!< 0x00000001 */ +#define ADC_JDR3_JDATA_1 (0x0002U << ADC_JDR3_JDATA_Pos) /*!< 0x00000002 */ +#define ADC_JDR3_JDATA_2 (0x0004U << ADC_JDR3_JDATA_Pos) /*!< 0x00000004 */ +#define ADC_JDR3_JDATA_3 (0x0008U << ADC_JDR3_JDATA_Pos) /*!< 0x00000008 */ +#define ADC_JDR3_JDATA_4 (0x0010U << ADC_JDR3_JDATA_Pos) /*!< 0x00000010 */ +#define ADC_JDR3_JDATA_5 (0x0020U << ADC_JDR3_JDATA_Pos) /*!< 0x00000020 */ +#define ADC_JDR3_JDATA_6 (0x0040U << ADC_JDR3_JDATA_Pos) /*!< 0x00000040 */ +#define ADC_JDR3_JDATA_7 (0x0080U << ADC_JDR3_JDATA_Pos) /*!< 0x00000080 */ +#define ADC_JDR3_JDATA_8 (0x0100U << ADC_JDR3_JDATA_Pos) /*!< 0x00000100 */ +#define ADC_JDR3_JDATA_9 (0x0200U << ADC_JDR3_JDATA_Pos) /*!< 0x00000200 */ +#define ADC_JDR3_JDATA_10 (0x0400U << ADC_JDR3_JDATA_Pos) /*!< 0x00000400 */ +#define ADC_JDR3_JDATA_11 (0x0800U << ADC_JDR3_JDATA_Pos) /*!< 0x00000800 */ +#define ADC_JDR3_JDATA_12 (0x1000U << ADC_JDR3_JDATA_Pos) /*!< 0x00001000 */ +#define ADC_JDR3_JDATA_13 (0x2000U << ADC_JDR3_JDATA_Pos) /*!< 0x00002000 */ +#define ADC_JDR3_JDATA_14 (0x4000U << ADC_JDR3_JDATA_Pos) /*!< 0x00004000 */ +#define ADC_JDR3_JDATA_15 (0x8000U << ADC_JDR3_JDATA_Pos) /*!< 0x00008000 */ + +/******************** Bit definition for ADC_JDR4 register ******************/ +#define ADC_JDR4_JDATA_Pos (0U) +#define ADC_JDR4_JDATA_Msk (0xFFFFU << ADC_JDR4_JDATA_Pos) /*!< 0x0000FFFF */ +#define ADC_JDR4_JDATA ADC_JDR4_JDATA_Msk /*!< ADC group injected sequencer rank 4 conversion data */ +#define ADC_JDR4_JDATA_0 (0x0001U << ADC_JDR4_JDATA_Pos) /*!< 0x00000001 */ +#define ADC_JDR4_JDATA_1 (0x0002U << ADC_JDR4_JDATA_Pos) /*!< 0x00000002 */ +#define ADC_JDR4_JDATA_2 (0x0004U << ADC_JDR4_JDATA_Pos) /*!< 0x00000004 */ +#define ADC_JDR4_JDATA_3 (0x0008U << ADC_JDR4_JDATA_Pos) /*!< 0x00000008 */ +#define ADC_JDR4_JDATA_4 (0x0010U << ADC_JDR4_JDATA_Pos) /*!< 0x00000010 */ +#define ADC_JDR4_JDATA_5 (0x0020U << ADC_JDR4_JDATA_Pos) /*!< 0x00000020 */ +#define ADC_JDR4_JDATA_6 (0x0040U << ADC_JDR4_JDATA_Pos) /*!< 0x00000040 */ +#define ADC_JDR4_JDATA_7 (0x0080U << ADC_JDR4_JDATA_Pos) /*!< 0x00000080 */ +#define ADC_JDR4_JDATA_8 (0x0100U << ADC_JDR4_JDATA_Pos) /*!< 0x00000100 */ +#define ADC_JDR4_JDATA_9 (0x0200U << ADC_JDR4_JDATA_Pos) /*!< 0x00000200 */ +#define ADC_JDR4_JDATA_10 (0x0400U << ADC_JDR4_JDATA_Pos) /*!< 0x00000400 */ +#define ADC_JDR4_JDATA_11 (0x0800U << ADC_JDR4_JDATA_Pos) /*!< 0x00000800 */ +#define ADC_JDR4_JDATA_12 (0x1000U << ADC_JDR4_JDATA_Pos) /*!< 0x00001000 */ +#define ADC_JDR4_JDATA_13 (0x2000U << ADC_JDR4_JDATA_Pos) /*!< 0x00002000 */ +#define ADC_JDR4_JDATA_14 (0x4000U << ADC_JDR4_JDATA_Pos) /*!< 0x00004000 */ +#define ADC_JDR4_JDATA_15 (0x8000U << ADC_JDR4_JDATA_Pos) /*!< 0x00008000 */ + +/******************** Bit definition for ADC_AWD2CR register ****************/ +#define ADC_AWD2CR_AWD2CH_Pos (0U) +#define ADC_AWD2CR_AWD2CH_Msk (0x7FFFFU << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x0007FFFF */ +#define ADC_AWD2CR_AWD2CH ADC_AWD2CR_AWD2CH_Msk /*!< ADC analog watchdog 2 monitored channel selection */ +#define ADC_AWD2CR_AWD2CH_0 (0x00001U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000001 */ +#define ADC_AWD2CR_AWD2CH_1 (0x00002U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000002 */ +#define ADC_AWD2CR_AWD2CH_2 (0x00004U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000004 */ +#define ADC_AWD2CR_AWD2CH_3 (0x00008U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000008 */ +#define ADC_AWD2CR_AWD2CH_4 (0x00010U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000010 */ +#define ADC_AWD2CR_AWD2CH_5 (0x00020U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000020 */ +#define ADC_AWD2CR_AWD2CH_6 (0x00040U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000040 */ +#define ADC_AWD2CR_AWD2CH_7 (0x00080U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000080 */ +#define ADC_AWD2CR_AWD2CH_8 (0x00100U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000100 */ +#define ADC_AWD2CR_AWD2CH_9 (0x00200U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000200 */ +#define ADC_AWD2CR_AWD2CH_10 (0x00400U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000400 */ +#define ADC_AWD2CR_AWD2CH_11 (0x00800U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000800 */ +#define ADC_AWD2CR_AWD2CH_12 (0x01000U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00001000 */ +#define ADC_AWD2CR_AWD2CH_13 (0x02000U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00002000 */ +#define ADC_AWD2CR_AWD2CH_14 (0x04000U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00004000 */ +#define ADC_AWD2CR_AWD2CH_15 (0x08000U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00008000 */ +#define ADC_AWD2CR_AWD2CH_16 (0x10000U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00010000 */ +#define ADC_AWD2CR_AWD2CH_17 (0x20000U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00020000 */ +#define ADC_AWD2CR_AWD2CH_18 (0x40000U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00040000 */ + +/******************** Bit definition for ADC_AWD3CR register ****************/ +#define ADC_AWD3CR_AWD3CH_Pos (0U) +#define ADC_AWD3CR_AWD3CH_Msk (0x7FFFFU << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x0007FFFF */ +#define ADC_AWD3CR_AWD3CH ADC_AWD3CR_AWD3CH_Msk /*!< ADC analog watchdog 3 monitored channel selection */ +#define ADC_AWD3CR_AWD3CH_0 (0x00001U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000001 */ +#define ADC_AWD3CR_AWD3CH_1 (0x00002U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000002 */ +#define ADC_AWD3CR_AWD3CH_2 (0x00004U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000004 */ +#define ADC_AWD3CR_AWD3CH_3 (0x00008U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000008 */ +#define ADC_AWD3CR_AWD3CH_4 (0x00010U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000010 */ +#define ADC_AWD3CR_AWD3CH_5 (0x00020U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000020 */ +#define ADC_AWD3CR_AWD3CH_6 (0x00040U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000040 */ +#define ADC_AWD3CR_AWD3CH_7 (0x00080U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000080 */ +#define ADC_AWD3CR_AWD3CH_8 (0x00100U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000100 */ +#define ADC_AWD3CR_AWD3CH_9 (0x00200U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000200 */ +#define ADC_AWD3CR_AWD3CH_10 (0x00400U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000400 */ +#define ADC_AWD3CR_AWD3CH_11 (0x00800U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000800 */ +#define ADC_AWD3CR_AWD3CH_12 (0x01000U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00001000 */ +#define ADC_AWD3CR_AWD3CH_13 (0x02000U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00002000 */ +#define ADC_AWD3CR_AWD3CH_14 (0x04000U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00004000 */ +#define ADC_AWD3CR_AWD3CH_15 (0x08000U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00008000 */ +#define ADC_AWD3CR_AWD3CH_16 (0x10000U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00010000 */ +#define ADC_AWD3CR_AWD3CH_17 (0x20000U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00020000 */ +#define ADC_AWD3CR_AWD3CH_18 (0x40000U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00040000 */ + +/******************** Bit definition for ADC_DIFSEL register ****************/ +#define ADC_DIFSEL_DIFSEL_Pos (0U) +#define ADC_DIFSEL_DIFSEL_Msk (0x7FFFFU << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x0007FFFF */ +#define ADC_DIFSEL_DIFSEL ADC_DIFSEL_DIFSEL_Msk /*!< ADC channel differential or single-ended mode */ +#define ADC_DIFSEL_DIFSEL_0 (0x00001U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000001 */ +#define ADC_DIFSEL_DIFSEL_1 (0x00002U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000002 */ +#define ADC_DIFSEL_DIFSEL_2 (0x00004U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000004 */ +#define ADC_DIFSEL_DIFSEL_3 (0x00008U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000008 */ +#define ADC_DIFSEL_DIFSEL_4 (0x00010U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000010 */ +#define ADC_DIFSEL_DIFSEL_5 (0x00020U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000020 */ +#define ADC_DIFSEL_DIFSEL_6 (0x00040U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000040 */ +#define ADC_DIFSEL_DIFSEL_7 (0x00080U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000080 */ +#define ADC_DIFSEL_DIFSEL_8 (0x00100U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000100 */ +#define ADC_DIFSEL_DIFSEL_9 (0x00200U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000200 */ +#define ADC_DIFSEL_DIFSEL_10 (0x00400U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000400 */ +#define ADC_DIFSEL_DIFSEL_11 (0x00800U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000800 */ +#define ADC_DIFSEL_DIFSEL_12 (0x01000U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00001000 */ +#define ADC_DIFSEL_DIFSEL_13 (0x02000U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00002000 */ +#define ADC_DIFSEL_DIFSEL_14 (0x04000U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00004000 */ +#define ADC_DIFSEL_DIFSEL_15 (0x08000U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00008000 */ +#define ADC_DIFSEL_DIFSEL_16 (0x10000U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00010000 */ +#define ADC_DIFSEL_DIFSEL_17 (0x20000U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00020000 */ +#define ADC_DIFSEL_DIFSEL_18 (0x40000U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00040000 */ + +/******************** Bit definition for ADC_CALFACT register ***************/ +#define ADC_CALFACT_CALFACT_S_Pos (0U) +#define ADC_CALFACT_CALFACT_S_Msk (0x7FU << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x0000007F */ +#define ADC_CALFACT_CALFACT_S ADC_CALFACT_CALFACT_S_Msk /*!< ADC calibration factor in single-ended mode */ +#define ADC_CALFACT_CALFACT_S_0 (0x01U << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000001 */ +#define ADC_CALFACT_CALFACT_S_1 (0x02U << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000002 */ +#define ADC_CALFACT_CALFACT_S_2 (0x04U << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000004 */ +#define ADC_CALFACT_CALFACT_S_3 (0x08U << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000008 */ +#define ADC_CALFACT_CALFACT_S_4 (0x10U << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000010 */ +#define ADC_CALFACT_CALFACT_S_5 (0x20U << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000020 */ +#define ADC_CALFACT_CALFACT_S_6 (0x40U << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000040 */ + +#define ADC_CALFACT_CALFACT_D_Pos (16U) +#define ADC_CALFACT_CALFACT_D_Msk (0x7FU << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x007F0000 */ +#define ADC_CALFACT_CALFACT_D ADC_CALFACT_CALFACT_D_Msk /*!< ADC calibration factor in differential mode */ +#define ADC_CALFACT_CALFACT_D_0 (0x01U << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00010000 */ +#define ADC_CALFACT_CALFACT_D_1 (0x02U << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00020000 */ +#define ADC_CALFACT_CALFACT_D_2 (0x04U << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00040000 */ +#define ADC_CALFACT_CALFACT_D_3 (0x08U << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00080000 */ +#define ADC_CALFACT_CALFACT_D_4 (0x10U << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00100000 */ +#define ADC_CALFACT_CALFACT_D_5 (0x20U << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00200000 */ +#define ADC_CALFACT_CALFACT_D_6 (0x40U << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00400000 */ + +/************************* ADC Common registers *****************************/ +/******************** Bit definition for ADC_CSR register *******************/ +#define ADC_CSR_ADRDY_MST_Pos (0U) +#define ADC_CSR_ADRDY_MST_Msk (0x1U << ADC_CSR_ADRDY_MST_Pos) /*!< 0x00000001 */ +#define ADC_CSR_ADRDY_MST ADC_CSR_ADRDY_MST_Msk /*!< ADC multimode master ready flag */ +#define ADC_CSR_EOSMP_MST_Pos (1U) +#define ADC_CSR_EOSMP_MST_Msk (0x1U << ADC_CSR_EOSMP_MST_Pos) /*!< 0x00000002 */ +#define ADC_CSR_EOSMP_MST ADC_CSR_EOSMP_MST_Msk /*!< ADC multimode master group regular end of sampling flag */ +#define ADC_CSR_EOC_MST_Pos (2U) +#define ADC_CSR_EOC_MST_Msk (0x1U << ADC_CSR_EOC_MST_Pos) /*!< 0x00000004 */ +#define ADC_CSR_EOC_MST ADC_CSR_EOC_MST_Msk /*!< ADC multimode master group regular end of unitary conversion flag */ +#define ADC_CSR_EOS_MST_Pos (3U) +#define ADC_CSR_EOS_MST_Msk (0x1U << ADC_CSR_EOS_MST_Pos) /*!< 0x00000008 */ +#define ADC_CSR_EOS_MST ADC_CSR_EOS_MST_Msk /*!< ADC multimode master group regular end of sequence conversions flag */ +#define ADC_CSR_OVR_MST_Pos (4U) +#define ADC_CSR_OVR_MST_Msk (0x1U << ADC_CSR_OVR_MST_Pos) /*!< 0x00000010 */ +#define ADC_CSR_OVR_MST ADC_CSR_OVR_MST_Msk /*!< ADC multimode master group regular overrun flag */ +#define ADC_CSR_JEOC_MST_Pos (5U) +#define ADC_CSR_JEOC_MST_Msk (0x1U << ADC_CSR_JEOC_MST_Pos) /*!< 0x00000020 */ +#define ADC_CSR_JEOC_MST ADC_CSR_JEOC_MST_Msk /*!< ADC multimode master group injected end of unitary conversion flag */ +#define ADC_CSR_JEOS_MST_Pos (6U) +#define ADC_CSR_JEOS_MST_Msk (0x1U << ADC_CSR_JEOS_MST_Pos) /*!< 0x00000040 */ +#define ADC_CSR_JEOS_MST ADC_CSR_JEOS_MST_Msk /*!< ADC multimode master group injected end of sequence conversions flag */ +#define ADC_CSR_AWD1_MST_Pos (7U) +#define ADC_CSR_AWD1_MST_Msk (0x1U << ADC_CSR_AWD1_MST_Pos) /*!< 0x00000080 */ +#define ADC_CSR_AWD1_MST ADC_CSR_AWD1_MST_Msk /*!< ADC multimode master analog watchdog 1 flag */ +#define ADC_CSR_AWD2_MST_Pos (8U) +#define ADC_CSR_AWD2_MST_Msk (0x1U << ADC_CSR_AWD2_MST_Pos) /*!< 0x00000100 */ +#define ADC_CSR_AWD2_MST ADC_CSR_AWD2_MST_Msk /*!< ADC multimode master analog watchdog 2 flag */ +#define ADC_CSR_AWD3_MST_Pos (9U) +#define ADC_CSR_AWD3_MST_Msk (0x1U << ADC_CSR_AWD3_MST_Pos) /*!< 0x00000200 */ +#define ADC_CSR_AWD3_MST ADC_CSR_AWD3_MST_Msk /*!< ADC multimode master analog watchdog 3 flag */ +#define ADC_CSR_JQOVF_MST_Pos (10U) +#define ADC_CSR_JQOVF_MST_Msk (0x1U << ADC_CSR_JQOVF_MST_Pos) /*!< 0x00000400 */ +#define ADC_CSR_JQOVF_MST ADC_CSR_JQOVF_MST_Msk /*!< ADC multimode master group injected contexts queue overflow flag */ + +#define ADC_CSR_ADRDY_SLV_Pos (16U) +#define ADC_CSR_ADRDY_SLV_Msk (0x1U << ADC_CSR_ADRDY_SLV_Pos) /*!< 0x00010000 */ +#define ADC_CSR_ADRDY_SLV ADC_CSR_ADRDY_SLV_Msk /*!< ADC multimode slave ready flag */ +#define ADC_CSR_EOSMP_SLV_Pos (17U) +#define ADC_CSR_EOSMP_SLV_Msk (0x1U << ADC_CSR_EOSMP_SLV_Pos) /*!< 0x00020000 */ +#define ADC_CSR_EOSMP_SLV ADC_CSR_EOSMP_SLV_Msk /*!< ADC multimode slave group regular end of sampling flag */ +#define ADC_CSR_EOC_SLV_Pos (18U) +#define ADC_CSR_EOC_SLV_Msk (0x1U << ADC_CSR_EOC_SLV_Pos) /*!< 0x00040000 */ +#define ADC_CSR_EOC_SLV ADC_CSR_EOC_SLV_Msk /*!< ADC multimode slave group regular end of unitary conversion flag */ +#define ADC_CSR_EOS_SLV_Pos (19U) +#define ADC_CSR_EOS_SLV_Msk (0x1U << ADC_CSR_EOS_SLV_Pos) /*!< 0x00080000 */ +#define ADC_CSR_EOS_SLV ADC_CSR_EOS_SLV_Msk /*!< ADC multimode slave group regular end of sequence conversions flag */ +#define ADC_CSR_OVR_SLV_Pos (20U) +#define ADC_CSR_OVR_SLV_Msk (0x1U << ADC_CSR_OVR_SLV_Pos) /*!< 0x00100000 */ +#define ADC_CSR_OVR_SLV ADC_CSR_OVR_SLV_Msk /*!< ADC multimode slave group regular overrun flag */ +#define ADC_CSR_JEOC_SLV_Pos (21U) +#define ADC_CSR_JEOC_SLV_Msk (0x1U << ADC_CSR_JEOC_SLV_Pos) /*!< 0x00200000 */ +#define ADC_CSR_JEOC_SLV ADC_CSR_JEOC_SLV_Msk /*!< ADC multimode slave group injected end of unitary conversion flag */ +#define ADC_CSR_JEOS_SLV_Pos (22U) +#define ADC_CSR_JEOS_SLV_Msk (0x1U << ADC_CSR_JEOS_SLV_Pos) /*!< 0x00400000 */ +#define ADC_CSR_JEOS_SLV ADC_CSR_JEOS_SLV_Msk /*!< ADC multimode slave group injected end of sequence conversions flag */ +#define ADC_CSR_AWD1_SLV_Pos (23U) +#define ADC_CSR_AWD1_SLV_Msk (0x1U << ADC_CSR_AWD1_SLV_Pos) /*!< 0x00800000 */ +#define ADC_CSR_AWD1_SLV ADC_CSR_AWD1_SLV_Msk /*!< ADC multimode slave analog watchdog 1 flag */ +#define ADC_CSR_AWD2_SLV_Pos (24U) +#define ADC_CSR_AWD2_SLV_Msk (0x1U << ADC_CSR_AWD2_SLV_Pos) /*!< 0x01000000 */ +#define ADC_CSR_AWD2_SLV ADC_CSR_AWD2_SLV_Msk /*!< ADC multimode slave analog watchdog 2 flag */ +#define ADC_CSR_AWD3_SLV_Pos (25U) +#define ADC_CSR_AWD3_SLV_Msk (0x1U << ADC_CSR_AWD3_SLV_Pos) /*!< 0x02000000 */ +#define ADC_CSR_AWD3_SLV ADC_CSR_AWD3_SLV_Msk /*!< ADC multimode slave analog watchdog 3 flag */ +#define ADC_CSR_JQOVF_SLV_Pos (26U) +#define ADC_CSR_JQOVF_SLV_Msk (0x1U << ADC_CSR_JQOVF_SLV_Pos) /*!< 0x04000000 */ +#define ADC_CSR_JQOVF_SLV ADC_CSR_JQOVF_SLV_Msk /*!< ADC multimode slave group injected contexts queue overflow flag */ + +/******************** Bit definition for ADC_CCR register *******************/ +#define ADC_CCR_DUAL_Pos (0U) +#define ADC_CCR_DUAL_Msk (0x1FU << ADC_CCR_DUAL_Pos) /*!< 0x0000001F */ +#define ADC_CCR_DUAL ADC_CCR_DUAL_Msk /*!< ADC multimode mode selection */ +#define ADC_CCR_DUAL_0 (0x01U << ADC_CCR_DUAL_Pos) /*!< 0x00000001 */ +#define ADC_CCR_DUAL_1 (0x02U << ADC_CCR_DUAL_Pos) /*!< 0x00000002 */ +#define ADC_CCR_DUAL_2 (0x04U << ADC_CCR_DUAL_Pos) /*!< 0x00000004 */ +#define ADC_CCR_DUAL_3 (0x08U << ADC_CCR_DUAL_Pos) /*!< 0x00000008 */ +#define ADC_CCR_DUAL_4 (0x10U << ADC_CCR_DUAL_Pos) /*!< 0x00000010 */ + +#define ADC_CCR_DELAY_Pos (8U) +#define ADC_CCR_DELAY_Msk (0xFU << ADC_CCR_DELAY_Pos) /*!< 0x00000F00 */ +#define ADC_CCR_DELAY ADC_CCR_DELAY_Msk /*!< ADC multimode delay between 2 sampling phases */ +#define ADC_CCR_DELAY_0 (0x1U << ADC_CCR_DELAY_Pos) /*!< 0x00000100 */ +#define ADC_CCR_DELAY_1 (0x2U << ADC_CCR_DELAY_Pos) /*!< 0x00000200 */ +#define ADC_CCR_DELAY_2 (0x4U << ADC_CCR_DELAY_Pos) /*!< 0x00000400 */ +#define ADC_CCR_DELAY_3 (0x8U << ADC_CCR_DELAY_Pos) /*!< 0x00000800 */ + +#define ADC_CCR_DMACFG_Pos (13U) +#define ADC_CCR_DMACFG_Msk (0x1U << ADC_CCR_DMACFG_Pos) /*!< 0x00002000 */ +#define ADC_CCR_DMACFG ADC_CCR_DMACFG_Msk /*!< ADC multimode DMA transfer configuration */ + +#define ADC_CCR_MDMA_Pos (14U) +#define ADC_CCR_MDMA_Msk (0x3U << ADC_CCR_MDMA_Pos) /*!< 0x0000C000 */ +#define ADC_CCR_MDMA ADC_CCR_MDMA_Msk /*!< ADC multimode DMA transfer enable */ +#define ADC_CCR_MDMA_0 (0x1U << ADC_CCR_MDMA_Pos) /*!< 0x00004000 */ +#define ADC_CCR_MDMA_1 (0x2U << ADC_CCR_MDMA_Pos) /*!< 0x00008000 */ + +#define ADC_CCR_CKMODE_Pos (16U) +#define ADC_CCR_CKMODE_Msk (0x3U << ADC_CCR_CKMODE_Pos) /*!< 0x00030000 */ +#define ADC_CCR_CKMODE ADC_CCR_CKMODE_Msk /*!< ADC common clock source and prescaler (prescaler only for clock source synchronous) */ +#define ADC_CCR_CKMODE_0 (0x1U << ADC_CCR_CKMODE_Pos) /*!< 0x00010000 */ +#define ADC_CCR_CKMODE_1 (0x2U << ADC_CCR_CKMODE_Pos) /*!< 0x00020000 */ + +#define ADC_CCR_PRESC_Pos (18U) +#define ADC_CCR_PRESC_Msk (0xFU << ADC_CCR_PRESC_Pos) /*!< 0x003C0000 */ +#define ADC_CCR_PRESC ADC_CCR_PRESC_Msk /*!< ADC common clock prescaler, only for clock source asynchronous */ +#define ADC_CCR_PRESC_0 (0x1U << ADC_CCR_PRESC_Pos) /*!< 0x00040000 */ +#define ADC_CCR_PRESC_1 (0x2U << ADC_CCR_PRESC_Pos) /*!< 0x00080000 */ +#define ADC_CCR_PRESC_2 (0x4U << ADC_CCR_PRESC_Pos) /*!< 0x00100000 */ +#define ADC_CCR_PRESC_3 (0x8U << ADC_CCR_PRESC_Pos) /*!< 0x00200000 */ + +#define ADC_CCR_VREFEN_Pos (22U) +#define ADC_CCR_VREFEN_Msk (0x1U << ADC_CCR_VREFEN_Pos) /*!< 0x00400000 */ +#define ADC_CCR_VREFEN ADC_CCR_VREFEN_Msk /*!< ADC internal path to VrefInt enable */ +#define ADC_CCR_TSEN_Pos (23U) +#define ADC_CCR_TSEN_Msk (0x1U << ADC_CCR_TSEN_Pos) /*!< 0x00800000 */ +#define ADC_CCR_TSEN ADC_CCR_TSEN_Msk /*!< ADC internal path to temperature sensor enable */ +#define ADC_CCR_VBATEN_Pos (24U) +#define ADC_CCR_VBATEN_Msk (0x1U << ADC_CCR_VBATEN_Pos) /*!< 0x01000000 */ +#define ADC_CCR_VBATEN ADC_CCR_VBATEN_Msk /*!< ADC internal path to battery voltage enable */ + +/******************** Bit definition for ADC_CDR register *******************/ +#define ADC_CDR_RDATA_MST_Pos (0U) +#define ADC_CDR_RDATA_MST_Msk (0xFFFFU << ADC_CDR_RDATA_MST_Pos) /*!< 0x0000FFFF */ +#define ADC_CDR_RDATA_MST ADC_CDR_RDATA_MST_Msk /*!< ADC multimode master group regular conversion data */ +#define ADC_CDR_RDATA_MST_0 (0x0001U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000001 */ +#define ADC_CDR_RDATA_MST_1 (0x0002U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000002 */ +#define ADC_CDR_RDATA_MST_2 (0x0004U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000004 */ +#define ADC_CDR_RDATA_MST_3 (0x0008U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000008 */ +#define ADC_CDR_RDATA_MST_4 (0x0010U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000010 */ +#define ADC_CDR_RDATA_MST_5 (0x0020U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000020 */ +#define ADC_CDR_RDATA_MST_6 (0x0040U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000040 */ +#define ADC_CDR_RDATA_MST_7 (0x0080U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000080 */ +#define ADC_CDR_RDATA_MST_8 (0x0100U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000100 */ +#define ADC_CDR_RDATA_MST_9 (0x0200U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000200 */ +#define ADC_CDR_RDATA_MST_10 (0x0400U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000400 */ +#define ADC_CDR_RDATA_MST_11 (0x0800U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000800 */ +#define ADC_CDR_RDATA_MST_12 (0x1000U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00001000 */ +#define ADC_CDR_RDATA_MST_13 (0x2000U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00002000 */ +#define ADC_CDR_RDATA_MST_14 (0x4000U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00004000 */ +#define ADC_CDR_RDATA_MST_15 (0x8000U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00008000 */ + +#define ADC_CDR_RDATA_SLV_Pos (16U) +#define ADC_CDR_RDATA_SLV_Msk (0xFFFFU << ADC_CDR_RDATA_SLV_Pos) /*!< 0xFFFF0000 */ +#define ADC_CDR_RDATA_SLV ADC_CDR_RDATA_SLV_Msk /*!< ADC multimode slave group regular conversion data */ +#define ADC_CDR_RDATA_SLV_0 (0x0001U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x00010000 */ +#define ADC_CDR_RDATA_SLV_1 (0x0002U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x00020000 */ +#define ADC_CDR_RDATA_SLV_2 (0x0004U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x00040000 */ +#define ADC_CDR_RDATA_SLV_3 (0x0008U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x00080000 */ +#define ADC_CDR_RDATA_SLV_4 (0x0010U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x00100000 */ +#define ADC_CDR_RDATA_SLV_5 (0x0020U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x00200000 */ +#define ADC_CDR_RDATA_SLV_6 (0x0040U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x00400000 */ +#define ADC_CDR_RDATA_SLV_7 (0x0080U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x00800000 */ +#define ADC_CDR_RDATA_SLV_8 (0x0100U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x01000000 */ +#define ADC_CDR_RDATA_SLV_9 (0x0200U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x02000000 */ +#define ADC_CDR_RDATA_SLV_10 (0x0400U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x04000000 */ +#define ADC_CDR_RDATA_SLV_11 (0x0800U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x08000000 */ +#define ADC_CDR_RDATA_SLV_12 (0x1000U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x10000000 */ +#define ADC_CDR_RDATA_SLV_13 (0x2000U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x20000000 */ +#define ADC_CDR_RDATA_SLV_14 (0x4000U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x40000000 */ +#define ADC_CDR_RDATA_SLV_15 (0x8000U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x80000000 */ + +/******************************************************************************/ +/* */ +/* Controller Area Network */ +/* */ +/******************************************************************************/ +/*!*/ +#define DAC_CR_CEN1_Pos (14U) +#define DAC_CR_CEN1_Msk (0x1U << DAC_CR_CEN1_Pos) /*!< 0x00004000 */ +#define DAC_CR_CEN1 DAC_CR_CEN1_Msk /*!*/ + +#define DAC_CR_EN2_Pos (16U) +#define DAC_CR_EN2_Msk (0x1U << DAC_CR_EN2_Pos) /*!< 0x00010000 */ +#define DAC_CR_EN2 DAC_CR_EN2_Msk /*!*/ +#define DAC_CR_CEN2_Pos (30U) +#define DAC_CR_CEN2_Msk (0x1U << DAC_CR_CEN2_Pos) /*!< 0x40000000 */ +#define DAC_CR_CEN2 DAC_CR_CEN2_Msk /*!*/ + +/***************** Bit definition for DAC_SWTRIGR register ******************/ +#define DAC_SWTRIGR_SWTRIG1_Pos (0U) +#define DAC_SWTRIGR_SWTRIG1_Msk (0x1U << DAC_SWTRIGR_SWTRIG1_Pos) /*!< 0x00000001 */ +#define DAC_SWTRIGR_SWTRIG1 DAC_SWTRIGR_SWTRIG1_Msk /*!
© COPYRIGHT(c) 2017 STMicroelectronics
+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32l4xx + * @{ + */ + +#ifndef __STM32L4xx_H +#define __STM32L4xx_H + +#ifdef __cplusplus + extern "C" { +#endif /* __cplusplus */ + +/** @addtogroup Library_configuration_section + * @{ + */ + +/** + * @brief STM32 Family + */ +#if !defined (STM32L4) +#define STM32L4 +#endif /* STM32L4 */ + +/* Uncomment the line below according to the target STM32L4 device used in your + application + */ + +#if !defined (STM32L431xx) && !defined (STM32L432xx) && !defined (STM32L433xx) && !defined (STM32L442xx) && !defined (STM32L443xx) && \ + !defined (STM32L451xx) && !defined (STM32L452xx) && !defined (STM32L462xx) && \ + !defined (STM32L471xx) && !defined (STM32L475xx) && !defined (STM32L476xx) && !defined (STM32L485xx) && !defined (STM32L486xx) && \ + !defined (STM32L496xx) && !defined (STM32L4A6xx) && \ + !defined (STM32L4R5xx) && !defined (STM32L4R7xx) && !defined (STM32L4R9xx) && !defined (STM32L4S5xx) && !defined (STM32L4S7xx) && !defined (STM32L4S9xx) + /* #define STM32L431xx */ /*!< STM32L431xx Devices */ + /* #define STM32L432xx */ /*!< STM32L432xx Devices */ + /* #define STM32L433xx */ /*!< STM32L433xx Devices */ + /* #define STM32L442xx */ /*!< STM32L442xx Devices */ + /* #define STM32L443xx */ /*!< STM32L443xx Devices */ + /* #define STM32L451xx */ /*!< STM32L451xx Devices */ + /* #define STM32L452xx */ /*!< STM32L452xx Devices */ + /* #define STM32L462xx */ /*!< STM32L462xx Devices */ + /* #define STM32L471xx */ /*!< STM32L471xx Devices */ + /* #define STM32L475xx */ /*!< STM32L475xx Devices */ + /* #define STM32L476xx */ /*!< STM32L476xx Devices */ + /* #define STM32L485xx */ /*!< STM32L485xx Devices */ + /* #define STM32L486xx */ /*!< STM32L486xx Devices */ + /* #define STM32L496xx */ /*!< STM32L496xx Devices */ + /* #define STM32L4A6xx */ /*!< STM32L4A6xx Devices */ + /* #define STM32L4R5xx */ /*!< STM32L4R5xx Devices */ + /* #define STM32L4R7xx */ /*!< STM32L4R7xx Devices */ + /* #define STM32L4R9xx */ /*!< STM32L4R9xx Devices */ + /* #define STM32L4S5xx */ /*!< STM32L4S5xx Devices */ + /* #define STM32L4S7xx */ /*!< STM32L4S7xx Devices */ + /* #define STM32L4S9xx */ /*!< STM32L4S9xx Devices */ +#endif + +/* Tip: To avoid modifying this file each time you need to switch between these + devices, you can define the device in your toolchain compiler preprocessor. + */ +#if !defined (USE_HAL_DRIVER) +/** + * @brief Comment the line below if you will not use the peripherals drivers. + In this case, these drivers will not be included and the application code will + be based on direct access to peripherals registers + */ + /*#define USE_HAL_DRIVER */ +#endif /* USE_HAL_DRIVER */ + +/** + * @brief CMSIS Device version number + */ +#define __STM32L4_CMSIS_VERSION_MAIN (0x01) /*!< [31:24] main version */ +#define __STM32L4_CMSIS_VERSION_SUB1 (0x04) /*!< [23:16] sub1 version */ +#define __STM32L4_CMSIS_VERSION_SUB2 (0x02) /*!< [15:8] sub2 version */ +#define __STM32L4_CMSIS_VERSION_RC (0x00) /*!< [7:0] release candidate */ +#define __STM32L4_CMSIS_VERSION ((__STM32L4_CMSIS_VERSION_MAIN << 24)\ + |(__STM32L4_CMSIS_VERSION_SUB1 << 16)\ + |(__STM32L4_CMSIS_VERSION_SUB2 << 8 )\ + |(__STM32L4_CMSIS_VERSION_RC)) + +/** + * @} + */ + +/** @addtogroup Device_Included + * @{ + */ + +#if defined(STM32L431xx) + #include "stm32l431xx.h" +#elif defined(STM32L432xx) + #include "stm32l432xx.h" +#elif defined(STM32L433xx) + #include "stm32l433xx.h" +#elif defined(STM32L442xx) + #include "stm32l442xx.h" +#elif defined(STM32L443xx) + #include "stm32l443xx.h" +#elif defined(STM32L451xx) + #include "stm32l451xx.h" +#elif defined(STM32L452xx) + #include "stm32l452xx.h" +#elif defined(STM32L462xx) + #include "stm32l462xx.h" +#elif defined(STM32L471xx) + #include "stm32l471xx.h" +#elif defined(STM32L475xx) + #include "stm32l475xx.h" +#elif defined(STM32L476xx) + #include "stm32l476xx.h" +#elif defined(STM32L485xx) + #include "stm32l485xx.h" +#elif defined(STM32L486xx) + #include "stm32l486xx.h" +#elif defined(STM32L496xx) + #include "stm32l496xx.h" +#elif defined(STM32L4A6xx) + #include "stm32l4a6xx.h" +#elif defined(STM32L4R5xx) + #include "stm32l4r5xx.h" +#elif defined(STM32L4R7xx) + #include "stm32l4r7xx.h" +#elif defined(STM32L4R9xx) + #include "stm32l4r9xx.h" +#elif defined(STM32L4S5xx) + #include "stm32l4s5xx.h" +#elif defined(STM32L4S7xx) + #include "stm32l4s7xx.h" +#elif defined(STM32L4S9xx) + #include "stm32l4s9xx.h" +#else + #error "Please select first the target STM32L4xx device used in your application (in stm32l4xx.h file)" +#endif + +/** + * @} + */ + +/** @addtogroup Exported_types + * @{ + */ +typedef enum +{ + RESET = 0, + SET = !RESET +} FlagStatus, ITStatus; + +typedef enum +{ + DISABLE = 0, + ENABLE = !DISABLE +} FunctionalState; +#define IS_FUNCTIONAL_STATE(STATE) (((STATE) == DISABLE) || ((STATE) == ENABLE)) + +typedef enum +{ + ERROR = 0, + SUCCESS = !ERROR +} ErrorStatus; + +/** + * @} + */ + + +/** @addtogroup Exported_macros + * @{ + */ +#define SET_BIT(REG, BIT) ((REG) |= (BIT)) + +#define CLEAR_BIT(REG, BIT) ((REG) &= ~(BIT)) + +#define READ_BIT(REG, BIT) ((REG) & (BIT)) + +#define CLEAR_REG(REG) ((REG) = (0x0)) + +#define WRITE_REG(REG, VAL) ((REG) = (VAL)) + +#define READ_REG(REG) ((REG)) + +#define MODIFY_REG(REG, CLEARMASK, SETMASK) WRITE_REG((REG), (((READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK))) + +#define POSITION_VAL(VAL) (__CLZ(__RBIT(VAL))) + + +/** + * @} + */ + +#if defined (USE_HAL_DRIVER) + #include "stm32l4xx_hal.h" +#endif /* USE_HAL_DRIVER */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __STM32L4xx_H */ +/** + * @} + */ + +/** + * @} + */ + + + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Device/ST/STM32L4xx/Include/system_stm32l4xx.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Device/ST/STM32L4xx/Include/system_stm32l4xx.h new file mode 100644 index 0000000..e6e4376 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Device/ST/STM32L4xx/Include/system_stm32l4xx.h @@ -0,0 +1,123 @@ +/** + ****************************************************************************** + * @file system_stm32l4xx.h + * @author MCD Application Team + * @brief CMSIS Cortex-M4 Device System Source File for STM32L4xx devices. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32l4xx_system + * @{ + */ + +/** + * @brief Define to prevent recursive inclusion + */ +#ifndef __SYSTEM_STM32L4XX_H +#define __SYSTEM_STM32L4XX_H + +#ifdef __cplusplus + extern "C" { +#endif + +/** @addtogroup STM32L4xx_System_Includes + * @{ + */ + +/** + * @} + */ + + +/** @addtogroup STM32L4xx_System_Exported_Variables + * @{ + */ + /* The SystemCoreClock variable is updated in three ways: + 1) by calling CMSIS function SystemCoreClockUpdate() + 2) by calling HAL API function HAL_RCC_GetSysClockFreq() + 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency + Note: If you use this function to configure the system clock; then there + is no need to call the 2 first functions listed above, since SystemCoreClock + variable is updated automatically. + */ +extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */ + +extern const uint8_t AHBPrescTable[16]; /*!< AHB prescalers table values */ +extern const uint8_t APBPrescTable[8]; /*!< APB prescalers table values */ +extern const uint32_t MSIRangeTable[12]; /*!< MSI ranges table values */ + +/** + * @} + */ + +/** @addtogroup STM32L4xx_System_Exported_Constants + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32L4xx_System_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32L4xx_System_Exported_Functions + * @{ + */ + +extern void SystemInit(void); +extern void SystemCoreClockUpdate(void); +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /*__SYSTEM_STM32L4XX_H */ + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/arm_common_tables.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/arm_common_tables.h new file mode 100644 index 0000000..8742a56 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/arm_common_tables.h @@ -0,0 +1,136 @@ +/* ---------------------------------------------------------------------- +* Copyright (C) 2010-2014 ARM Limited. All rights reserved. +* +* $Date: 19. October 2015 +* $Revision: V.1.4.5 a +* +* Project: CMSIS DSP Library +* Title: arm_common_tables.h +* +* Description: This file has extern declaration for common tables like Bitreverse, reciprocal etc which are used across different functions +* +* Target Processor: Cortex-M4/Cortex-M3 +* +* 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 LIMITED nor the names of its 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 _ARM_COMMON_TABLES_H +#define _ARM_COMMON_TABLES_H + +#include "arm_math.h" + +extern const uint16_t armBitRevTable[1024]; +extern const q15_t armRecipTableQ15[64]; +extern const q31_t armRecipTableQ31[64]; +/* extern const q31_t realCoefAQ31[1024]; */ +/* extern const q31_t realCoefBQ31[1024]; */ +extern const float32_t twiddleCoef_16[32]; +extern const float32_t twiddleCoef_32[64]; +extern const float32_t twiddleCoef_64[128]; +extern const float32_t twiddleCoef_128[256]; +extern const float32_t twiddleCoef_256[512]; +extern const float32_t twiddleCoef_512[1024]; +extern const float32_t twiddleCoef_1024[2048]; +extern const float32_t twiddleCoef_2048[4096]; +extern const float32_t twiddleCoef_4096[8192]; +#define twiddleCoef twiddleCoef_4096 +extern const q31_t twiddleCoef_16_q31[24]; +extern const q31_t twiddleCoef_32_q31[48]; +extern const q31_t twiddleCoef_64_q31[96]; +extern const q31_t twiddleCoef_128_q31[192]; +extern const q31_t twiddleCoef_256_q31[384]; +extern const q31_t twiddleCoef_512_q31[768]; +extern const q31_t twiddleCoef_1024_q31[1536]; +extern const q31_t twiddleCoef_2048_q31[3072]; +extern const q31_t twiddleCoef_4096_q31[6144]; +extern const q15_t twiddleCoef_16_q15[24]; +extern const q15_t twiddleCoef_32_q15[48]; +extern const q15_t twiddleCoef_64_q15[96]; +extern const q15_t twiddleCoef_128_q15[192]; +extern const q15_t twiddleCoef_256_q15[384]; +extern const q15_t twiddleCoef_512_q15[768]; +extern const q15_t twiddleCoef_1024_q15[1536]; +extern const q15_t twiddleCoef_2048_q15[3072]; +extern const q15_t twiddleCoef_4096_q15[6144]; +extern const float32_t twiddleCoef_rfft_32[32]; +extern const float32_t twiddleCoef_rfft_64[64]; +extern const float32_t twiddleCoef_rfft_128[128]; +extern const float32_t twiddleCoef_rfft_256[256]; +extern const float32_t twiddleCoef_rfft_512[512]; +extern const float32_t twiddleCoef_rfft_1024[1024]; +extern const float32_t twiddleCoef_rfft_2048[2048]; +extern const float32_t twiddleCoef_rfft_4096[4096]; + + +/* floating-point bit reversal tables */ +#define ARMBITREVINDEXTABLE__16_TABLE_LENGTH ((uint16_t)20 ) +#define ARMBITREVINDEXTABLE__32_TABLE_LENGTH ((uint16_t)48 ) +#define ARMBITREVINDEXTABLE__64_TABLE_LENGTH ((uint16_t)56 ) +#define ARMBITREVINDEXTABLE_128_TABLE_LENGTH ((uint16_t)208 ) +#define ARMBITREVINDEXTABLE_256_TABLE_LENGTH ((uint16_t)440 ) +#define ARMBITREVINDEXTABLE_512_TABLE_LENGTH ((uint16_t)448 ) +#define ARMBITREVINDEXTABLE1024_TABLE_LENGTH ((uint16_t)1800) +#define ARMBITREVINDEXTABLE2048_TABLE_LENGTH ((uint16_t)3808) +#define ARMBITREVINDEXTABLE4096_TABLE_LENGTH ((uint16_t)4032) + +extern const uint16_t armBitRevIndexTable16[ARMBITREVINDEXTABLE__16_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable32[ARMBITREVINDEXTABLE__32_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable64[ARMBITREVINDEXTABLE__64_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable128[ARMBITREVINDEXTABLE_128_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable256[ARMBITREVINDEXTABLE_256_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable512[ARMBITREVINDEXTABLE_512_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable1024[ARMBITREVINDEXTABLE1024_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable2048[ARMBITREVINDEXTABLE2048_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable4096[ARMBITREVINDEXTABLE4096_TABLE_LENGTH]; + +/* fixed-point bit reversal tables */ +#define ARMBITREVINDEXTABLE_FIXED___16_TABLE_LENGTH ((uint16_t)12 ) +#define ARMBITREVINDEXTABLE_FIXED___32_TABLE_LENGTH ((uint16_t)24 ) +#define ARMBITREVINDEXTABLE_FIXED___64_TABLE_LENGTH ((uint16_t)56 ) +#define ARMBITREVINDEXTABLE_FIXED__128_TABLE_LENGTH ((uint16_t)112 ) +#define ARMBITREVINDEXTABLE_FIXED__256_TABLE_LENGTH ((uint16_t)240 ) +#define ARMBITREVINDEXTABLE_FIXED__512_TABLE_LENGTH ((uint16_t)480 ) +#define ARMBITREVINDEXTABLE_FIXED_1024_TABLE_LENGTH ((uint16_t)992 ) +#define ARMBITREVINDEXTABLE_FIXED_2048_TABLE_LENGTH ((uint16_t)1984) +#define ARMBITREVINDEXTABLE_FIXED_4096_TABLE_LENGTH ((uint16_t)4032) + +extern const uint16_t armBitRevIndexTable_fixed_16[ARMBITREVINDEXTABLE_FIXED___16_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable_fixed_32[ARMBITREVINDEXTABLE_FIXED___32_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable_fixed_64[ARMBITREVINDEXTABLE_FIXED___64_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable_fixed_128[ARMBITREVINDEXTABLE_FIXED__128_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable_fixed_256[ARMBITREVINDEXTABLE_FIXED__256_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable_fixed_512[ARMBITREVINDEXTABLE_FIXED__512_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable_fixed_1024[ARMBITREVINDEXTABLE_FIXED_1024_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable_fixed_2048[ARMBITREVINDEXTABLE_FIXED_2048_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable_fixed_4096[ARMBITREVINDEXTABLE_FIXED_4096_TABLE_LENGTH]; + +/* Tables for Fast Math Sine and Cosine */ +extern const float32_t sinTable_f32[FAST_MATH_TABLE_SIZE + 1]; +extern const q31_t sinTable_q31[FAST_MATH_TABLE_SIZE + 1]; +extern const q15_t sinTable_q15[FAST_MATH_TABLE_SIZE + 1]; + +#endif /* ARM_COMMON_TABLES_H */ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/arm_const_structs.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/arm_const_structs.h new file mode 100644 index 0000000..726d06e --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/arm_const_structs.h @@ -0,0 +1,79 @@ +/* ---------------------------------------------------------------------- +* Copyright (C) 2010-2014 ARM Limited. All rights reserved. +* +* $Date: 19. March 2015 +* $Revision: V.1.4.5 +* +* Project: CMSIS DSP Library +* Title: arm_const_structs.h +* +* Description: This file has constant structs that are initialized for +* user convenience. For example, some can be given as +* arguments to the arm_cfft_f32() function. +* +* Target Processor: Cortex-M4/Cortex-M3 +* +* 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 LIMITED nor the names of its 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 _ARM_CONST_STRUCTS_H +#define _ARM_CONST_STRUCTS_H + +#include "arm_math.h" +#include "arm_common_tables.h" + + extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len16; + extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len32; + extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len64; + extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len128; + extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len256; + extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len512; + extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len1024; + extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len2048; + extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len4096; + + extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len16; + extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len32; + extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len64; + extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len128; + extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len256; + extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len512; + extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len1024; + extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len2048; + extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len4096; + + extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len16; + extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len32; + extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len64; + extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len128; + extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len256; + extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len512; + extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len1024; + extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len2048; + extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len4096; + +#endif diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/arm_math.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/arm_math.h new file mode 100644 index 0000000..d33f8a9 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/arm_math.h @@ -0,0 +1,7154 @@ +/* ---------------------------------------------------------------------- +* Copyright (C) 2010-2015 ARM Limited. All rights reserved. +* +* $Date: 20. October 2015 +* $Revision: V1.4.5 b +* +* Project: CMSIS DSP Library +* Title: arm_math.h +* +* Description: Public header file for CMSIS DSP Library +* +* Target Processor: Cortex-M7/Cortex-M4/Cortex-M3/Cortex-M0 +* +* 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 LIMITED nor the names of its 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. + * -------------------------------------------------------------------- */ + +/** + \mainpage CMSIS DSP Software Library + * + * Introduction + * ------------ + * + * This user manual describes the CMSIS DSP software library, + * a suite of common signal processing functions for use on Cortex-M processor based devices. + * + * The library is divided into a number of functions each covering a specific category: + * - Basic math functions + * - Fast math functions + * - Complex math functions + * - Filters + * - Matrix functions + * - Transforms + * - Motor control functions + * - Statistical functions + * - Support functions + * - Interpolation functions + * + * The library has separate functions for operating on 8-bit integers, 16-bit integers, + * 32-bit integer and 32-bit floating-point values. + * + * Using the Library + * ------------ + * + * The library installer contains prebuilt versions of the libraries in the Lib folder. + * - arm_cortexM7lfdp_math.lib (Little endian and Double Precision Floating Point Unit on Cortex-M7) + * - arm_cortexM7bfdp_math.lib (Big endian and Double Precision Floating Point Unit on Cortex-M7) + * - arm_cortexM7lfsp_math.lib (Little endian and Single Precision Floating Point Unit on Cortex-M7) + * - arm_cortexM7bfsp_math.lib (Big endian and Single Precision Floating Point Unit on Cortex-M7) + * - arm_cortexM7l_math.lib (Little endian on Cortex-M7) + * - arm_cortexM7b_math.lib (Big endian on Cortex-M7) + * - arm_cortexM4lf_math.lib (Little endian and Floating Point Unit on Cortex-M4) + * - arm_cortexM4bf_math.lib (Big endian and Floating Point Unit on Cortex-M4) + * - arm_cortexM4l_math.lib (Little endian on Cortex-M4) + * - arm_cortexM4b_math.lib (Big endian on Cortex-M4) + * - arm_cortexM3l_math.lib (Little endian on Cortex-M3) + * - arm_cortexM3b_math.lib (Big endian on Cortex-M3) + * - arm_cortexM0l_math.lib (Little endian on Cortex-M0 / CortexM0+) + * - arm_cortexM0b_math.lib (Big endian on Cortex-M0 / CortexM0+) + * + * The library functions are declared in the public file arm_math.h which is placed in the Include folder. + * Simply include this file and link the appropriate library in the application and begin calling the library functions. The Library supports single + * public header file arm_math.h for Cortex-M7/M4/M3/M0/M0+ with little endian and big endian. Same header file will be used for floating point unit(FPU) variants. + * Define the appropriate pre processor MACRO ARM_MATH_CM7 or ARM_MATH_CM4 or ARM_MATH_CM3 or + * ARM_MATH_CM0 or ARM_MATH_CM0PLUS depending on the target processor in the application. + * + * Examples + * -------- + * + * The library ships with a number of examples which demonstrate how to use the library functions. + * + * Toolchain Support + * ------------ + * + * The library has been developed and tested with MDK-ARM version 5.14.0.0 + * The library is being tested in GCC and IAR toolchains and updates on this activity will be made available shortly. + * + * Building the Library + * ------------ + * + * The library installer contains a project file to re build libraries on MDK-ARM Tool chain in the CMSIS\\DSP_Lib\\Source\\ARM folder. + * - arm_cortexM_math.uvprojx + * + * + * The libraries can be built by opening the arm_cortexM_math.uvprojx project in MDK-ARM, selecting a specific target, and defining the optional pre processor MACROs detailed above. + * + * Pre-processor Macros + * ------------ + * + * Each library project have differant pre-processor macros. + * + * - UNALIGNED_SUPPORT_DISABLE: + * + * Define macro UNALIGNED_SUPPORT_DISABLE, If the silicon does not support unaligned memory access + * + * - ARM_MATH_BIG_ENDIAN: + * + * Define macro ARM_MATH_BIG_ENDIAN to build the library for big endian targets. By default library builds for little endian targets. + * + * - ARM_MATH_MATRIX_CHECK: + * + * Define macro ARM_MATH_MATRIX_CHECK for checking on the input and output sizes of matrices + * + * - ARM_MATH_ROUNDING: + * + * Define macro ARM_MATH_ROUNDING for rounding on support functions + * + * - ARM_MATH_CMx: + * + * Define macro ARM_MATH_CM4 for building the library on Cortex-M4 target, ARM_MATH_CM3 for building library on Cortex-M3 target + * and ARM_MATH_CM0 for building library on Cortex-M0 target, ARM_MATH_CM0PLUS for building library on Cortex-M0+ target, and + * ARM_MATH_CM7 for building the library on cortex-M7. + * + * - __FPU_PRESENT: + * + * Initialize macro __FPU_PRESENT = 1 when building on FPU supported Targets. Enable this macro for M4bf and M4lf libraries + * + *
+ * CMSIS-DSP in ARM::CMSIS Pack + * ----------------------------- + * + * The following files relevant to CMSIS-DSP are present in the ARM::CMSIS Pack directories: + * |File/Folder |Content | + * |------------------------------|------------------------------------------------------------------------| + * |\b CMSIS\\Documentation\\DSP | This documentation | + * |\b CMSIS\\DSP_Lib | Software license agreement (license.txt) | + * |\b CMSIS\\DSP_Lib\\Examples | Example projects demonstrating the usage of the library functions | + * |\b CMSIS\\DSP_Lib\\Source | Source files for rebuilding the library | + * + *
+ * Revision History of CMSIS-DSP + * ------------ + * Please refer to \ref ChangeLog_pg. + * + * Copyright Notice + * ------------ + * + * Copyright (C) 2010-2015 ARM Limited. All rights reserved. + */ + + +/** + * @defgroup groupMath Basic Math Functions + */ + +/** + * @defgroup groupFastMath Fast Math Functions + * This set of functions provides a fast approximation to sine, cosine, and square root. + * As compared to most of the other functions in the CMSIS math library, the fast math functions + * operate on individual values and not arrays. + * There are separate functions for Q15, Q31, and floating-point data. + * + */ + +/** + * @defgroup groupCmplxMath Complex Math Functions + * This set of functions operates on complex data vectors. + * The data in the complex arrays is stored in an interleaved fashion + * (real, imag, real, imag, ...). + * In the API functions, the number of samples in a complex array refers + * to the number of complex values; the array contains twice this number of + * real values. + */ + +/** + * @defgroup groupFilters Filtering Functions + */ + +/** + * @defgroup groupMatrix Matrix Functions + * + * This set of functions provides basic matrix math operations. + * The functions operate on matrix data structures. For example, + * the type + * definition for the floating-point matrix structure is shown + * below: + *
+ *     typedef struct
+ *     {
+ *       uint16_t numRows;     // number of rows of the matrix.
+ *       uint16_t numCols;     // number of columns of the matrix.
+ *       float32_t *pData;     // points to the data of the matrix.
+ *     } arm_matrix_instance_f32;
+ * 
+ * There are similar definitions for Q15 and Q31 data types. + * + * The structure specifies the size of the matrix and then points to + * an array of data. The array is of size numRows X numCols + * and the values are arranged in row order. That is, the + * matrix element (i, j) is stored at: + *
+ *     pData[i*numCols + j]
+ * 
+ * + * \par Init Functions + * There is an associated initialization function for each type of matrix + * data structure. + * The initialization function sets the values of the internal structure fields. + * Refer to the function arm_mat_init_f32(), arm_mat_init_q31() + * and arm_mat_init_q15() for floating-point, Q31 and Q15 types, respectively. + * + * \par + * Use of the initialization function is optional. However, if initialization function is used + * then the instance structure cannot be placed into a const data section. + * To place the instance structure in a const data + * section, manually initialize the data structure. For example: + *
+ * arm_matrix_instance_f32 S = {nRows, nColumns, pData};
+ * arm_matrix_instance_q31 S = {nRows, nColumns, pData};
+ * arm_matrix_instance_q15 S = {nRows, nColumns, pData};
+ * 
+ * where nRows specifies the number of rows, nColumns + * specifies the number of columns, and pData points to the + * data array. + * + * \par Size Checking + * By default all of the matrix functions perform size checking on the input and + * output matrices. For example, the matrix addition function verifies that the + * two input matrices and the output matrix all have the same number of rows and + * columns. If the size check fails the functions return: + *
+ *     ARM_MATH_SIZE_MISMATCH
+ * 
+ * Otherwise the functions return + *
+ *     ARM_MATH_SUCCESS
+ * 
+ * There is some overhead associated with this matrix size checking. + * The matrix size checking is enabled via the \#define + *
+ *     ARM_MATH_MATRIX_CHECK
+ * 
+ * within the library project settings. By default this macro is defined + * and size checking is enabled. By changing the project settings and + * undefining this macro size checking is eliminated and the functions + * run a bit faster. With size checking disabled the functions always + * return ARM_MATH_SUCCESS. + */ + +/** + * @defgroup groupTransforms Transform Functions + */ + +/** + * @defgroup groupController Controller Functions + */ + +/** + * @defgroup groupStats Statistics Functions + */ +/** + * @defgroup groupSupport Support Functions + */ + +/** + * @defgroup groupInterpolation Interpolation Functions + * These functions perform 1- and 2-dimensional interpolation of data. + * Linear interpolation is used for 1-dimensional data and + * bilinear interpolation is used for 2-dimensional data. + */ + +/** + * @defgroup groupExamples Examples + */ +#ifndef _ARM_MATH_H +#define _ARM_MATH_H + +/* ignore some GCC warnings */ +#if defined ( __GNUC__ ) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-conversion" +#pragma GCC diagnostic ignored "-Wconversion" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +#define __CMSIS_GENERIC /* disable NVIC and Systick functions */ + +#if defined(ARM_MATH_CM7) + #include "core_cm7.h" +#elif defined (ARM_MATH_CM4) + #include "core_cm4.h" +#elif defined (ARM_MATH_CM3) + #include "core_cm3.h" +#elif defined (ARM_MATH_CM0) + #include "core_cm0.h" + #define ARM_MATH_CM0_FAMILY +#elif defined (ARM_MATH_CM0PLUS) + #include "core_cm0plus.h" + #define ARM_MATH_CM0_FAMILY +#else + #error "Define according the used Cortex core ARM_MATH_CM7, ARM_MATH_CM4, ARM_MATH_CM3, ARM_MATH_CM0PLUS or ARM_MATH_CM0" +#endif + +#undef __CMSIS_GENERIC /* enable NVIC and Systick functions */ +#include "string.h" +#include "math.h" +#ifdef __cplusplus +extern "C" +{ +#endif + + + /** + * @brief Macros required for reciprocal calculation in Normalized LMS + */ + +#define DELTA_Q31 (0x100) +#define DELTA_Q15 0x5 +#define INDEX_MASK 0x0000003F +#ifndef PI +#define PI 3.14159265358979f +#endif + + /** + * @brief Macros required for SINE and COSINE Fast math approximations + */ + +#define FAST_MATH_TABLE_SIZE 512 +#define FAST_MATH_Q31_SHIFT (32 - 10) +#define FAST_MATH_Q15_SHIFT (16 - 10) +#define CONTROLLER_Q31_SHIFT (32 - 9) +#define TABLE_SIZE 256 +#define TABLE_SPACING_Q31 0x400000 +#define TABLE_SPACING_Q15 0x80 + + /** + * @brief Macros required for SINE and COSINE Controller functions + */ + /* 1.31(q31) Fixed value of 2/360 */ + /* -1 to +1 is divided into 360 values so total spacing is (2/360) */ +#define INPUT_SPACING 0xB60B61 + + /** + * @brief Macro for Unaligned Support + */ +#ifndef UNALIGNED_SUPPORT_DISABLE + #define ALIGN4 +#else + #if defined (__GNUC__) + #define ALIGN4 __attribute__((aligned(4))) + #else + #define ALIGN4 __align(4) + #endif +#endif /* #ifndef UNALIGNED_SUPPORT_DISABLE */ + + /** + * @brief Error status returned by some functions in the library. + */ + + typedef enum + { + ARM_MATH_SUCCESS = 0, /**< No error */ + ARM_MATH_ARGUMENT_ERROR = -1, /**< One or more arguments are incorrect */ + ARM_MATH_LENGTH_ERROR = -2, /**< Length of data buffer is incorrect */ + ARM_MATH_SIZE_MISMATCH = -3, /**< Size of matrices is not compatible with the operation. */ + ARM_MATH_NANINF = -4, /**< Not-a-number (NaN) or infinity is generated */ + ARM_MATH_SINGULAR = -5, /**< Generated by matrix inversion if the input matrix is singular and cannot be inverted. */ + ARM_MATH_TEST_FAILURE = -6 /**< Test Failed */ + } arm_status; + + /** + * @brief 8-bit fractional data type in 1.7 format. + */ + typedef int8_t q7_t; + + /** + * @brief 16-bit fractional data type in 1.15 format. + */ + typedef int16_t q15_t; + + /** + * @brief 32-bit fractional data type in 1.31 format. + */ + typedef int32_t q31_t; + + /** + * @brief 64-bit fractional data type in 1.63 format. + */ + typedef int64_t q63_t; + + /** + * @brief 32-bit floating-point type definition. + */ + typedef float float32_t; + + /** + * @brief 64-bit floating-point type definition. + */ + typedef double float64_t; + + /** + * @brief definition to read/write two 16 bit values. + */ +#if defined __CC_ARM + #define __SIMD32_TYPE int32_t __packed + #define CMSIS_UNUSED __attribute__((unused)) + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #define __SIMD32_TYPE int32_t + #define CMSIS_UNUSED __attribute__((unused)) + +#elif defined __GNUC__ + #define __SIMD32_TYPE int32_t + #define CMSIS_UNUSED __attribute__((unused)) + +#elif defined __ICCARM__ + #define __SIMD32_TYPE int32_t __packed + #define CMSIS_UNUSED + +#elif defined __CSMC__ + #define __SIMD32_TYPE int32_t + #define CMSIS_UNUSED + +#elif defined __TASKING__ + #define __SIMD32_TYPE __unaligned int32_t + #define CMSIS_UNUSED + +#else + #error Unknown compiler +#endif + +#define __SIMD32(addr) (*(__SIMD32_TYPE **) & (addr)) +#define __SIMD32_CONST(addr) ((__SIMD32_TYPE *)(addr)) +#define _SIMD32_OFFSET(addr) (*(__SIMD32_TYPE *) (addr)) +#define __SIMD64(addr) (*(int64_t **) & (addr)) + +#if defined (ARM_MATH_CM3) || defined (ARM_MATH_CM0_FAMILY) + /** + * @brief definition to pack two 16 bit values. + */ +#define __PKHBT(ARG1, ARG2, ARG3) ( (((int32_t)(ARG1) << 0) & (int32_t)0x0000FFFF) | \ + (((int32_t)(ARG2) << ARG3) & (int32_t)0xFFFF0000) ) +#define __PKHTB(ARG1, ARG2, ARG3) ( (((int32_t)(ARG1) << 0) & (int32_t)0xFFFF0000) | \ + (((int32_t)(ARG2) >> ARG3) & (int32_t)0x0000FFFF) ) + +#endif + + + /** + * @brief definition to pack four 8 bit values. + */ +#ifndef ARM_MATH_BIG_ENDIAN + +#define __PACKq7(v0,v1,v2,v3) ( (((int32_t)(v0) << 0) & (int32_t)0x000000FF) | \ + (((int32_t)(v1) << 8) & (int32_t)0x0000FF00) | \ + (((int32_t)(v2) << 16) & (int32_t)0x00FF0000) | \ + (((int32_t)(v3) << 24) & (int32_t)0xFF000000) ) +#else + +#define __PACKq7(v0,v1,v2,v3) ( (((int32_t)(v3) << 0) & (int32_t)0x000000FF) | \ + (((int32_t)(v2) << 8) & (int32_t)0x0000FF00) | \ + (((int32_t)(v1) << 16) & (int32_t)0x00FF0000) | \ + (((int32_t)(v0) << 24) & (int32_t)0xFF000000) ) + +#endif + + + /** + * @brief Clips Q63 to Q31 values. + */ + static __INLINE q31_t clip_q63_to_q31( + q63_t x) + { + return ((q31_t) (x >> 32) != ((q31_t) x >> 31)) ? + ((0x7FFFFFFF ^ ((q31_t) (x >> 63)))) : (q31_t) x; + } + + /** + * @brief Clips Q63 to Q15 values. + */ + static __INLINE q15_t clip_q63_to_q15( + q63_t x) + { + return ((q31_t) (x >> 32) != ((q31_t) x >> 31)) ? + ((0x7FFF ^ ((q15_t) (x >> 63)))) : (q15_t) (x >> 15); + } + + /** + * @brief Clips Q31 to Q7 values. + */ + static __INLINE q7_t clip_q31_to_q7( + q31_t x) + { + return ((q31_t) (x >> 24) != ((q31_t) x >> 23)) ? + ((0x7F ^ ((q7_t) (x >> 31)))) : (q7_t) x; + } + + /** + * @brief Clips Q31 to Q15 values. + */ + static __INLINE q15_t clip_q31_to_q15( + q31_t x) + { + return ((q31_t) (x >> 16) != ((q31_t) x >> 15)) ? + ((0x7FFF ^ ((q15_t) (x >> 31)))) : (q15_t) x; + } + + /** + * @brief Multiplies 32 X 64 and returns 32 bit result in 2.30 format. + */ + + static __INLINE q63_t mult32x64( + q63_t x, + q31_t y) + { + return ((((q63_t) (x & 0x00000000FFFFFFFF) * y) >> 32) + + (((q63_t) (x >> 32) * y))); + } + +/* + #if defined (ARM_MATH_CM0_FAMILY) && defined ( __CC_ARM ) + #define __CLZ __clz + #endif + */ +/* note: function can be removed when all toolchain support __CLZ for Cortex-M0 */ +#if defined (ARM_MATH_CM0_FAMILY) && ((defined (__ICCARM__)) ) + static __INLINE uint32_t __CLZ( + q31_t data); + + static __INLINE uint32_t __CLZ( + q31_t data) + { + uint32_t count = 0; + uint32_t mask = 0x80000000; + + while((data & mask) == 0) + { + count += 1u; + mask = mask >> 1u; + } + + return (count); + } +#endif + + /** + * @brief Function to Calculates 1/in (reciprocal) value of Q31 Data type. + */ + + static __INLINE uint32_t arm_recip_q31( + q31_t in, + q31_t * dst, + q31_t * pRecipTable) + { + q31_t out; + uint32_t tempVal; + uint32_t index, i; + uint32_t signBits; + + if(in > 0) + { + signBits = ((uint32_t) (__CLZ( in) - 1)); + } + else + { + signBits = ((uint32_t) (__CLZ(-in) - 1)); + } + + /* Convert input sample to 1.31 format */ + in = (in << signBits); + + /* calculation of index for initial approximated Val */ + index = (uint32_t)(in >> 24); + index = (index & INDEX_MASK); + + /* 1.31 with exp 1 */ + out = pRecipTable[index]; + + /* calculation of reciprocal value */ + /* running approximation for two iterations */ + for (i = 0u; i < 2u; i++) + { + tempVal = (uint32_t) (((q63_t) in * out) >> 31); + tempVal = 0x7FFFFFFFu - tempVal; + /* 1.31 with exp 1 */ + /* out = (q31_t) (((q63_t) out * tempVal) >> 30); */ + out = clip_q63_to_q31(((q63_t) out * tempVal) >> 30); + } + + /* write output */ + *dst = out; + + /* return num of signbits of out = 1/in value */ + return (signBits + 1u); + } + + + /** + * @brief Function to Calculates 1/in (reciprocal) value of Q15 Data type. + */ + static __INLINE uint32_t arm_recip_q15( + q15_t in, + q15_t * dst, + q15_t * pRecipTable) + { + q15_t out = 0; + uint32_t tempVal = 0; + uint32_t index = 0, i = 0; + uint32_t signBits = 0; + + if(in > 0) + { + signBits = ((uint32_t)(__CLZ( in) - 17)); + } + else + { + signBits = ((uint32_t)(__CLZ(-in) - 17)); + } + + /* Convert input sample to 1.15 format */ + in = (in << signBits); + + /* calculation of index for initial approximated Val */ + index = (uint32_t)(in >> 8); + index = (index & INDEX_MASK); + + /* 1.15 with exp 1 */ + out = pRecipTable[index]; + + /* calculation of reciprocal value */ + /* running approximation for two iterations */ + for (i = 0u; i < 2u; i++) + { + tempVal = (uint32_t) (((q31_t) in * out) >> 15); + tempVal = 0x7FFFu - tempVal; + /* 1.15 with exp 1 */ + out = (q15_t) (((q31_t) out * tempVal) >> 14); + /* out = clip_q31_to_q15(((q31_t) out * tempVal) >> 14); */ + } + + /* write output */ + *dst = out; + + /* return num of signbits of out = 1/in value */ + return (signBits + 1); + } + + + /* + * @brief C custom defined intrinisic function for only M0 processors + */ +#if defined(ARM_MATH_CM0_FAMILY) + static __INLINE q31_t __SSAT( + q31_t x, + uint32_t y) + { + int32_t posMax, negMin; + uint32_t i; + + posMax = 1; + for (i = 0; i < (y - 1); i++) + { + posMax = posMax * 2; + } + + if(x > 0) + { + posMax = (posMax - 1); + + if(x > posMax) + { + x = posMax; + } + } + else + { + negMin = -posMax; + + if(x < negMin) + { + x = negMin; + } + } + return (x); + } +#endif /* end of ARM_MATH_CM0_FAMILY */ + + + /* + * @brief C custom defined intrinsic function for M3 and M0 processors + */ +#if defined (ARM_MATH_CM3) || defined (ARM_MATH_CM0_FAMILY) + + /* + * @brief C custom defined QADD8 for M3 and M0 processors + */ + static __INLINE uint32_t __QADD8( + uint32_t x, + uint32_t y) + { + q31_t r, s, t, u; + + r = __SSAT(((((q31_t)x << 24) >> 24) + (((q31_t)y << 24) >> 24)), 8) & (int32_t)0x000000FF; + s = __SSAT(((((q31_t)x << 16) >> 24) + (((q31_t)y << 16) >> 24)), 8) & (int32_t)0x000000FF; + t = __SSAT(((((q31_t)x << 8) >> 24) + (((q31_t)y << 8) >> 24)), 8) & (int32_t)0x000000FF; + u = __SSAT(((((q31_t)x ) >> 24) + (((q31_t)y ) >> 24)), 8) & (int32_t)0x000000FF; + + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r ))); + } + + + /* + * @brief C custom defined QSUB8 for M3 and M0 processors + */ + static __INLINE uint32_t __QSUB8( + uint32_t x, + uint32_t y) + { + q31_t r, s, t, u; + + r = __SSAT(((((q31_t)x << 24) >> 24) - (((q31_t)y << 24) >> 24)), 8) & (int32_t)0x000000FF; + s = __SSAT(((((q31_t)x << 16) >> 24) - (((q31_t)y << 16) >> 24)), 8) & (int32_t)0x000000FF; + t = __SSAT(((((q31_t)x << 8) >> 24) - (((q31_t)y << 8) >> 24)), 8) & (int32_t)0x000000FF; + u = __SSAT(((((q31_t)x ) >> 24) - (((q31_t)y ) >> 24)), 8) & (int32_t)0x000000FF; + + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r ))); + } + + + /* + * @brief C custom defined QADD16 for M3 and M0 processors + */ + static __INLINE uint32_t __QADD16( + uint32_t x, + uint32_t y) + { +/* q31_t r, s; without initialisation 'arm_offset_q15 test' fails but 'intrinsic' tests pass! for armCC */ + q31_t r = 0, s = 0; + + r = __SSAT(((((q31_t)x << 16) >> 16) + (((q31_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((q31_t)x ) >> 16) + (((q31_t)y ) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined SHADD16 for M3 and M0 processors + */ + static __INLINE uint32_t __SHADD16( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = (((((q31_t)x << 16) >> 16) + (((q31_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((q31_t)x ) >> 16) + (((q31_t)y ) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined QSUB16 for M3 and M0 processors + */ + static __INLINE uint32_t __QSUB16( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = __SSAT(((((q31_t)x << 16) >> 16) - (((q31_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((q31_t)x ) >> 16) - (((q31_t)y ) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined SHSUB16 for M3 and M0 processors + */ + static __INLINE uint32_t __SHSUB16( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = (((((q31_t)x << 16) >> 16) - (((q31_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((q31_t)x ) >> 16) - (((q31_t)y ) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined QASX for M3 and M0 processors + */ + static __INLINE uint32_t __QASX( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = __SSAT(((((q31_t)x << 16) >> 16) - (((q31_t)y ) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((q31_t)x ) >> 16) + (((q31_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined SHASX for M3 and M0 processors + */ + static __INLINE uint32_t __SHASX( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = (((((q31_t)x << 16) >> 16) - (((q31_t)y ) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((q31_t)x ) >> 16) + (((q31_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined QSAX for M3 and M0 processors + */ + static __INLINE uint32_t __QSAX( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = __SSAT(((((q31_t)x << 16) >> 16) + (((q31_t)y ) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((q31_t)x ) >> 16) - (((q31_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined SHSAX for M3 and M0 processors + */ + static __INLINE uint32_t __SHSAX( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = (((((q31_t)x << 16) >> 16) + (((q31_t)y ) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((q31_t)x ) >> 16) - (((q31_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined SMUSDX for M3 and M0 processors + */ + static __INLINE uint32_t __SMUSDX( + uint32_t x, + uint32_t y) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) - + ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) )); + } + + /* + * @brief C custom defined SMUADX for M3 and M0 processors + */ + static __INLINE uint32_t __SMUADX( + uint32_t x, + uint32_t y) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) )); + } + + + /* + * @brief C custom defined QADD for M3 and M0 processors + */ + static __INLINE int32_t __QADD( + int32_t x, + int32_t y) + { + return ((int32_t)(clip_q63_to_q31((q63_t)x + (q31_t)y))); + } + + + /* + * @brief C custom defined QSUB for M3 and M0 processors + */ + static __INLINE int32_t __QSUB( + int32_t x, + int32_t y) + { + return ((int32_t)(clip_q63_to_q31((q63_t)x - (q31_t)y))); + } + + + /* + * @brief C custom defined SMLAD for M3 and M0 processors + */ + static __INLINE uint32_t __SMLAD( + uint32_t x, + uint32_t y, + uint32_t sum) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y << 16) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y ) >> 16)) + + ( ((q31_t)sum ) ) )); + } + + + /* + * @brief C custom defined SMLADX for M3 and M0 processors + */ + static __INLINE uint32_t __SMLADX( + uint32_t x, + uint32_t y, + uint32_t sum) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) + + ( ((q31_t)sum ) ) )); + } + + + /* + * @brief C custom defined SMLSDX for M3 and M0 processors + */ + static __INLINE uint32_t __SMLSDX( + uint32_t x, + uint32_t y, + uint32_t sum) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) - + ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) + + ( ((q31_t)sum ) ) )); + } + + + /* + * @brief C custom defined SMLALD for M3 and M0 processors + */ + static __INLINE uint64_t __SMLALD( + uint32_t x, + uint32_t y, + uint64_t sum) + { +/* return (sum + ((q15_t) (x >> 16) * (q15_t) (y >> 16)) + ((q15_t) x * (q15_t) y)); */ + return ((uint64_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y << 16) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y ) >> 16)) + + ( ((q63_t)sum ) ) )); + } + + + /* + * @brief C custom defined SMLALDX for M3 and M0 processors + */ + static __INLINE uint64_t __SMLALDX( + uint32_t x, + uint32_t y, + uint64_t sum) + { +/* return (sum + ((q15_t) (x >> 16) * (q15_t) y)) + ((q15_t) x * (q15_t) (y >> 16)); */ + return ((uint64_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) + + ( ((q63_t)sum ) ) )); + } + + + /* + * @brief C custom defined SMUAD for M3 and M0 processors + */ + static __INLINE uint32_t __SMUAD( + uint32_t x, + uint32_t y) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y << 16) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y ) >> 16)) )); + } + + + /* + * @brief C custom defined SMUSD for M3 and M0 processors + */ + static __INLINE uint32_t __SMUSD( + uint32_t x, + uint32_t y) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y << 16) >> 16)) - + ((((q31_t)x ) >> 16) * (((q31_t)y ) >> 16)) )); + } + + + /* + * @brief C custom defined SXTB16 for M3 and M0 processors + */ + static __INLINE uint32_t __SXTB16( + uint32_t x) + { + return ((uint32_t)(((((q31_t)x << 24) >> 24) & (q31_t)0x0000FFFF) | + ((((q31_t)x << 8) >> 8) & (q31_t)0xFFFF0000) )); + } + +#endif /* defined (ARM_MATH_CM3) || defined (ARM_MATH_CM0_FAMILY) */ + + + /** + * @brief Instance structure for the Q7 FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of filter coefficients in the filter. */ + q7_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q7_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + } arm_fir_instance_q7; + + /** + * @brief Instance structure for the Q15 FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of filter coefficients in the filter. */ + q15_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + } arm_fir_instance_q15; + + /** + * @brief Instance structure for the Q31 FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of filter coefficients in the filter. */ + q31_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + } arm_fir_instance_q31; + + /** + * @brief Instance structure for the floating-point FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of filter coefficients in the filter. */ + float32_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + } arm_fir_instance_f32; + + + /** + * @brief Processing function for the Q7 FIR filter. + * @param[in] S points to an instance of the Q7 FIR filter structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_q7( + const arm_fir_instance_q7 * S, + q7_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q7 FIR filter. + * @param[in,out] S points to an instance of the Q7 FIR structure. + * @param[in] numTaps Number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of samples that are processed. + */ + void arm_fir_init_q7( + arm_fir_instance_q7 * S, + uint16_t numTaps, + q7_t * pCoeffs, + q7_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q15 FIR filter. + * @param[in] S points to an instance of the Q15 FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_q15( + const arm_fir_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Processing function for the fast Q15 FIR filter for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q15 FIR filter structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_fast_q15( + const arm_fir_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q15 FIR filter. + * @param[in,out] S points to an instance of the Q15 FIR filter structure. + * @param[in] numTaps Number of filter coefficients in the filter. Must be even and greater than or equal to 4. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of samples that are processed at a time. + * @return The function returns ARM_MATH_SUCCESS if initialization was successful or ARM_MATH_ARGUMENT_ERROR if + * numTaps is not a supported value. + */ + arm_status arm_fir_init_q15( + arm_fir_instance_q15 * S, + uint16_t numTaps, + q15_t * pCoeffs, + q15_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 FIR filter. + * @param[in] S points to an instance of the Q31 FIR filter structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_q31( + const arm_fir_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Processing function for the fast Q31 FIR filter for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q31 FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_fast_q31( + const arm_fir_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 FIR filter. + * @param[in,out] S points to an instance of the Q31 FIR structure. + * @param[in] numTaps Number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of samples that are processed at a time. + */ + void arm_fir_init_q31( + arm_fir_instance_q31 * S, + uint16_t numTaps, + q31_t * pCoeffs, + q31_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the floating-point FIR filter. + * @param[in] S points to an instance of the floating-point FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_f32( + const arm_fir_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point FIR filter. + * @param[in,out] S points to an instance of the floating-point FIR filter structure. + * @param[in] numTaps Number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of samples that are processed at a time. + */ + void arm_fir_init_f32( + arm_fir_instance_f32 * S, + uint16_t numTaps, + float32_t * pCoeffs, + float32_t * pState, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q15 Biquad cascade filter. + */ + typedef struct + { + int8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + q15_t *pState; /**< Points to the array of state coefficients. The array is of length 4*numStages. */ + q15_t *pCoeffs; /**< Points to the array of coefficients. The array is of length 5*numStages. */ + int8_t postShift; /**< Additional shift, in bits, applied to each output sample. */ + } arm_biquad_casd_df1_inst_q15; + + /** + * @brief Instance structure for the Q31 Biquad cascade filter. + */ + typedef struct + { + uint32_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + q31_t *pState; /**< Points to the array of state coefficients. The array is of length 4*numStages. */ + q31_t *pCoeffs; /**< Points to the array of coefficients. The array is of length 5*numStages. */ + uint8_t postShift; /**< Additional shift, in bits, applied to each output sample. */ + } arm_biquad_casd_df1_inst_q31; + + /** + * @brief Instance structure for the floating-point Biquad cascade filter. + */ + typedef struct + { + uint32_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + float32_t *pState; /**< Points to the array of state coefficients. The array is of length 4*numStages. */ + float32_t *pCoeffs; /**< Points to the array of coefficients. The array is of length 5*numStages. */ + } arm_biquad_casd_df1_inst_f32; + + + /** + * @brief Processing function for the Q15 Biquad cascade filter. + * @param[in] S points to an instance of the Q15 Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df1_q15( + const arm_biquad_casd_df1_inst_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q15 Biquad cascade filter. + * @param[in,out] S points to an instance of the Q15 Biquad cascade structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] postShift Shift to be applied to the output. Varies according to the coefficients format + */ + void arm_biquad_cascade_df1_init_q15( + arm_biquad_casd_df1_inst_q15 * S, + uint8_t numStages, + q15_t * pCoeffs, + q15_t * pState, + int8_t postShift); + + + /** + * @brief Fast but less precise processing function for the Q15 Biquad cascade filter for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q15 Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df1_fast_q15( + const arm_biquad_casd_df1_inst_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 Biquad cascade filter + * @param[in] S points to an instance of the Q31 Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df1_q31( + const arm_biquad_casd_df1_inst_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Fast but less precise processing function for the Q31 Biquad cascade filter for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q31 Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df1_fast_q31( + const arm_biquad_casd_df1_inst_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 Biquad cascade filter. + * @param[in,out] S points to an instance of the Q31 Biquad cascade structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] postShift Shift to be applied to the output. Varies according to the coefficients format + */ + void arm_biquad_cascade_df1_init_q31( + arm_biquad_casd_df1_inst_q31 * S, + uint8_t numStages, + q31_t * pCoeffs, + q31_t * pState, + int8_t postShift); + + + /** + * @brief Processing function for the floating-point Biquad cascade filter. + * @param[in] S points to an instance of the floating-point Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df1_f32( + const arm_biquad_casd_df1_inst_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point Biquad cascade filter. + * @param[in,out] S points to an instance of the floating-point Biquad cascade structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + */ + void arm_biquad_cascade_df1_init_f32( + arm_biquad_casd_df1_inst_f32 * S, + uint8_t numStages, + float32_t * pCoeffs, + float32_t * pState); + + + /** + * @brief Instance structure for the floating-point matrix structure. + */ + typedef struct + { + uint16_t numRows; /**< number of rows of the matrix. */ + uint16_t numCols; /**< number of columns of the matrix. */ + float32_t *pData; /**< points to the data of the matrix. */ + } arm_matrix_instance_f32; + + + /** + * @brief Instance structure for the floating-point matrix structure. + */ + typedef struct + { + uint16_t numRows; /**< number of rows of the matrix. */ + uint16_t numCols; /**< number of columns of the matrix. */ + float64_t *pData; /**< points to the data of the matrix. */ + } arm_matrix_instance_f64; + + /** + * @brief Instance structure for the Q15 matrix structure. + */ + typedef struct + { + uint16_t numRows; /**< number of rows of the matrix. */ + uint16_t numCols; /**< number of columns of the matrix. */ + q15_t *pData; /**< points to the data of the matrix. */ + } arm_matrix_instance_q15; + + /** + * @brief Instance structure for the Q31 matrix structure. + */ + typedef struct + { + uint16_t numRows; /**< number of rows of the matrix. */ + uint16_t numCols; /**< number of columns of the matrix. */ + q31_t *pData; /**< points to the data of the matrix. */ + } arm_matrix_instance_q31; + + + /** + * @brief Floating-point matrix addition. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_add_f32( + const arm_matrix_instance_f32 * pSrcA, + const arm_matrix_instance_f32 * pSrcB, + arm_matrix_instance_f32 * pDst); + + + /** + * @brief Q15 matrix addition. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_add_q15( + const arm_matrix_instance_q15 * pSrcA, + const arm_matrix_instance_q15 * pSrcB, + arm_matrix_instance_q15 * pDst); + + + /** + * @brief Q31 matrix addition. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_add_q31( + const arm_matrix_instance_q31 * pSrcA, + const arm_matrix_instance_q31 * pSrcB, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Floating-point, complex, matrix multiplication. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_cmplx_mult_f32( + const arm_matrix_instance_f32 * pSrcA, + const arm_matrix_instance_f32 * pSrcB, + arm_matrix_instance_f32 * pDst); + + + /** + * @brief Q15, complex, matrix multiplication. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_cmplx_mult_q15( + const arm_matrix_instance_q15 * pSrcA, + const arm_matrix_instance_q15 * pSrcB, + arm_matrix_instance_q15 * pDst, + q15_t * pScratch); + + + /** + * @brief Q31, complex, matrix multiplication. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_cmplx_mult_q31( + const arm_matrix_instance_q31 * pSrcA, + const arm_matrix_instance_q31 * pSrcB, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Floating-point matrix transpose. + * @param[in] pSrc points to the input matrix + * @param[out] pDst points to the output matrix + * @return The function returns either ARM_MATH_SIZE_MISMATCH + * or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_trans_f32( + const arm_matrix_instance_f32 * pSrc, + arm_matrix_instance_f32 * pDst); + + + /** + * @brief Q15 matrix transpose. + * @param[in] pSrc points to the input matrix + * @param[out] pDst points to the output matrix + * @return The function returns either ARM_MATH_SIZE_MISMATCH + * or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_trans_q15( + const arm_matrix_instance_q15 * pSrc, + arm_matrix_instance_q15 * pDst); + + + /** + * @brief Q31 matrix transpose. + * @param[in] pSrc points to the input matrix + * @param[out] pDst points to the output matrix + * @return The function returns either ARM_MATH_SIZE_MISMATCH + * or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_trans_q31( + const arm_matrix_instance_q31 * pSrc, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Floating-point matrix multiplication + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_mult_f32( + const arm_matrix_instance_f32 * pSrcA, + const arm_matrix_instance_f32 * pSrcB, + arm_matrix_instance_f32 * pDst); + + + /** + * @brief Q15 matrix multiplication + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @param[in] pState points to the array for storing intermediate results + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_mult_q15( + const arm_matrix_instance_q15 * pSrcA, + const arm_matrix_instance_q15 * pSrcB, + arm_matrix_instance_q15 * pDst, + q15_t * pState); + + + /** + * @brief Q15 matrix multiplication (fast variant) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @param[in] pState points to the array for storing intermediate results + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_mult_fast_q15( + const arm_matrix_instance_q15 * pSrcA, + const arm_matrix_instance_q15 * pSrcB, + arm_matrix_instance_q15 * pDst, + q15_t * pState); + + + /** + * @brief Q31 matrix multiplication + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_mult_q31( + const arm_matrix_instance_q31 * pSrcA, + const arm_matrix_instance_q31 * pSrcB, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Q31 matrix multiplication (fast variant) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_mult_fast_q31( + const arm_matrix_instance_q31 * pSrcA, + const arm_matrix_instance_q31 * pSrcB, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Floating-point matrix subtraction + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_sub_f32( + const arm_matrix_instance_f32 * pSrcA, + const arm_matrix_instance_f32 * pSrcB, + arm_matrix_instance_f32 * pDst); + + + /** + * @brief Q15 matrix subtraction + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_sub_q15( + const arm_matrix_instance_q15 * pSrcA, + const arm_matrix_instance_q15 * pSrcB, + arm_matrix_instance_q15 * pDst); + + + /** + * @brief Q31 matrix subtraction + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_sub_q31( + const arm_matrix_instance_q31 * pSrcA, + const arm_matrix_instance_q31 * pSrcB, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Floating-point matrix scaling. + * @param[in] pSrc points to the input matrix + * @param[in] scale scale factor + * @param[out] pDst points to the output matrix + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_scale_f32( + const arm_matrix_instance_f32 * pSrc, + float32_t scale, + arm_matrix_instance_f32 * pDst); + + + /** + * @brief Q15 matrix scaling. + * @param[in] pSrc points to input matrix + * @param[in] scaleFract fractional portion of the scale factor + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to output matrix + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_scale_q15( + const arm_matrix_instance_q15 * pSrc, + q15_t scaleFract, + int32_t shift, + arm_matrix_instance_q15 * pDst); + + + /** + * @brief Q31 matrix scaling. + * @param[in] pSrc points to input matrix + * @param[in] scaleFract fractional portion of the scale factor + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_scale_q31( + const arm_matrix_instance_q31 * pSrc, + q31_t scaleFract, + int32_t shift, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Q31 matrix initialization. + * @param[in,out] S points to an instance of the floating-point matrix structure. + * @param[in] nRows number of rows in the matrix. + * @param[in] nColumns number of columns in the matrix. + * @param[in] pData points to the matrix data array. + */ + void arm_mat_init_q31( + arm_matrix_instance_q31 * S, + uint16_t nRows, + uint16_t nColumns, + q31_t * pData); + + + /** + * @brief Q15 matrix initialization. + * @param[in,out] S points to an instance of the floating-point matrix structure. + * @param[in] nRows number of rows in the matrix. + * @param[in] nColumns number of columns in the matrix. + * @param[in] pData points to the matrix data array. + */ + void arm_mat_init_q15( + arm_matrix_instance_q15 * S, + uint16_t nRows, + uint16_t nColumns, + q15_t * pData); + + + /** + * @brief Floating-point matrix initialization. + * @param[in,out] S points to an instance of the floating-point matrix structure. + * @param[in] nRows number of rows in the matrix. + * @param[in] nColumns number of columns in the matrix. + * @param[in] pData points to the matrix data array. + */ + void arm_mat_init_f32( + arm_matrix_instance_f32 * S, + uint16_t nRows, + uint16_t nColumns, + float32_t * pData); + + + + /** + * @brief Instance structure for the Q15 PID Control. + */ + typedef struct + { + q15_t A0; /**< The derived gain, A0 = Kp + Ki + Kd . */ +#ifdef ARM_MATH_CM0_FAMILY + q15_t A1; + q15_t A2; +#else + q31_t A1; /**< The derived gain A1 = -Kp - 2Kd | Kd.*/ +#endif + q15_t state[3]; /**< The state array of length 3. */ + q15_t Kp; /**< The proportional gain. */ + q15_t Ki; /**< The integral gain. */ + q15_t Kd; /**< The derivative gain. */ + } arm_pid_instance_q15; + + /** + * @brief Instance structure for the Q31 PID Control. + */ + typedef struct + { + q31_t A0; /**< The derived gain, A0 = Kp + Ki + Kd . */ + q31_t A1; /**< The derived gain, A1 = -Kp - 2Kd. */ + q31_t A2; /**< The derived gain, A2 = Kd . */ + q31_t state[3]; /**< The state array of length 3. */ + q31_t Kp; /**< The proportional gain. */ + q31_t Ki; /**< The integral gain. */ + q31_t Kd; /**< The derivative gain. */ + } arm_pid_instance_q31; + + /** + * @brief Instance structure for the floating-point PID Control. + */ + typedef struct + { + float32_t A0; /**< The derived gain, A0 = Kp + Ki + Kd . */ + float32_t A1; /**< The derived gain, A1 = -Kp - 2Kd. */ + float32_t A2; /**< The derived gain, A2 = Kd . */ + float32_t state[3]; /**< The state array of length 3. */ + float32_t Kp; /**< The proportional gain. */ + float32_t Ki; /**< The integral gain. */ + float32_t Kd; /**< The derivative gain. */ + } arm_pid_instance_f32; + + + + /** + * @brief Initialization function for the floating-point PID Control. + * @param[in,out] S points to an instance of the PID structure. + * @param[in] resetStateFlag flag to reset the state. 0 = no change in state 1 = reset the state. + */ + void arm_pid_init_f32( + arm_pid_instance_f32 * S, + int32_t resetStateFlag); + + + /** + * @brief Reset function for the floating-point PID Control. + * @param[in,out] S is an instance of the floating-point PID Control structure + */ + void arm_pid_reset_f32( + arm_pid_instance_f32 * S); + + + /** + * @brief Initialization function for the Q31 PID Control. + * @param[in,out] S points to an instance of the Q15 PID structure. + * @param[in] resetStateFlag flag to reset the state. 0 = no change in state 1 = reset the state. + */ + void arm_pid_init_q31( + arm_pid_instance_q31 * S, + int32_t resetStateFlag); + + + /** + * @brief Reset function for the Q31 PID Control. + * @param[in,out] S points to an instance of the Q31 PID Control structure + */ + + void arm_pid_reset_q31( + arm_pid_instance_q31 * S); + + + /** + * @brief Initialization function for the Q15 PID Control. + * @param[in,out] S points to an instance of the Q15 PID structure. + * @param[in] resetStateFlag flag to reset the state. 0 = no change in state 1 = reset the state. + */ + void arm_pid_init_q15( + arm_pid_instance_q15 * S, + int32_t resetStateFlag); + + + /** + * @brief Reset function for the Q15 PID Control. + * @param[in,out] S points to an instance of the q15 PID Control structure + */ + void arm_pid_reset_q15( + arm_pid_instance_q15 * S); + + + /** + * @brief Instance structure for the floating-point Linear Interpolate function. + */ + typedef struct + { + uint32_t nValues; /**< nValues */ + float32_t x1; /**< x1 */ + float32_t xSpacing; /**< xSpacing */ + float32_t *pYData; /**< pointer to the table of Y values */ + } arm_linear_interp_instance_f32; + + /** + * @brief Instance structure for the floating-point bilinear interpolation function. + */ + typedef struct + { + uint16_t numRows; /**< number of rows in the data table. */ + uint16_t numCols; /**< number of columns in the data table. */ + float32_t *pData; /**< points to the data table. */ + } arm_bilinear_interp_instance_f32; + + /** + * @brief Instance structure for the Q31 bilinear interpolation function. + */ + typedef struct + { + uint16_t numRows; /**< number of rows in the data table. */ + uint16_t numCols; /**< number of columns in the data table. */ + q31_t *pData; /**< points to the data table. */ + } arm_bilinear_interp_instance_q31; + + /** + * @brief Instance structure for the Q15 bilinear interpolation function. + */ + typedef struct + { + uint16_t numRows; /**< number of rows in the data table. */ + uint16_t numCols; /**< number of columns in the data table. */ + q15_t *pData; /**< points to the data table. */ + } arm_bilinear_interp_instance_q15; + + /** + * @brief Instance structure for the Q15 bilinear interpolation function. + */ + typedef struct + { + uint16_t numRows; /**< number of rows in the data table. */ + uint16_t numCols; /**< number of columns in the data table. */ + q7_t *pData; /**< points to the data table. */ + } arm_bilinear_interp_instance_q7; + + + /** + * @brief Q7 vector multiplication. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_mult_q7( + q7_t * pSrcA, + q7_t * pSrcB, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q15 vector multiplication. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_mult_q15( + q15_t * pSrcA, + q15_t * pSrcB, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q31 vector multiplication. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_mult_q31( + q31_t * pSrcA, + q31_t * pSrcB, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Floating-point vector multiplication. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_mult_f32( + float32_t * pSrcA, + float32_t * pSrcB, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q15 CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + q15_t *pTwiddle; /**< points to the Sin twiddle factor table. */ + uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + } arm_cfft_radix2_instance_q15; + +/* Deprecated */ + arm_status arm_cfft_radix2_init_q15( + arm_cfft_radix2_instance_q15 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + +/* Deprecated */ + void arm_cfft_radix2_q15( + const arm_cfft_radix2_instance_q15 * S, + q15_t * pSrc); + + + /** + * @brief Instance structure for the Q15 CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + q15_t *pTwiddle; /**< points to the twiddle factor table. */ + uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + } arm_cfft_radix4_instance_q15; + +/* Deprecated */ + arm_status arm_cfft_radix4_init_q15( + arm_cfft_radix4_instance_q15 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + +/* Deprecated */ + void arm_cfft_radix4_q15( + const arm_cfft_radix4_instance_q15 * S, + q15_t * pSrc); + + /** + * @brief Instance structure for the Radix-2 Q31 CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + q31_t *pTwiddle; /**< points to the Twiddle factor table. */ + uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + } arm_cfft_radix2_instance_q31; + +/* Deprecated */ + arm_status arm_cfft_radix2_init_q31( + arm_cfft_radix2_instance_q31 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + +/* Deprecated */ + void arm_cfft_radix2_q31( + const arm_cfft_radix2_instance_q31 * S, + q31_t * pSrc); + + /** + * @brief Instance structure for the Q31 CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + q31_t *pTwiddle; /**< points to the twiddle factor table. */ + uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + } arm_cfft_radix4_instance_q31; + +/* Deprecated */ + void arm_cfft_radix4_q31( + const arm_cfft_radix4_instance_q31 * S, + q31_t * pSrc); + +/* Deprecated */ + arm_status arm_cfft_radix4_init_q31( + arm_cfft_radix4_instance_q31 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + + /** + * @brief Instance structure for the floating-point CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + float32_t *pTwiddle; /**< points to the Twiddle factor table. */ + uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + float32_t onebyfftLen; /**< value of 1/fftLen. */ + } arm_cfft_radix2_instance_f32; + +/* Deprecated */ + arm_status arm_cfft_radix2_init_f32( + arm_cfft_radix2_instance_f32 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + +/* Deprecated */ + void arm_cfft_radix2_f32( + const arm_cfft_radix2_instance_f32 * S, + float32_t * pSrc); + + /** + * @brief Instance structure for the floating-point CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + float32_t *pTwiddle; /**< points to the Twiddle factor table. */ + uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + float32_t onebyfftLen; /**< value of 1/fftLen. */ + } arm_cfft_radix4_instance_f32; + +/* Deprecated */ + arm_status arm_cfft_radix4_init_f32( + arm_cfft_radix4_instance_f32 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + +/* Deprecated */ + void arm_cfft_radix4_f32( + const arm_cfft_radix4_instance_f32 * S, + float32_t * pSrc); + + /** + * @brief Instance structure for the fixed-point CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + const q15_t *pTwiddle; /**< points to the Twiddle factor table. */ + const uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t bitRevLength; /**< bit reversal table length. */ + } arm_cfft_instance_q15; + +void arm_cfft_q15( + const arm_cfft_instance_q15 * S, + q15_t * p1, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + + /** + * @brief Instance structure for the fixed-point CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + const q31_t *pTwiddle; /**< points to the Twiddle factor table. */ + const uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t bitRevLength; /**< bit reversal table length. */ + } arm_cfft_instance_q31; + +void arm_cfft_q31( + const arm_cfft_instance_q31 * S, + q31_t * p1, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + + /** + * @brief Instance structure for the floating-point CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + const float32_t *pTwiddle; /**< points to the Twiddle factor table. */ + const uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t bitRevLength; /**< bit reversal table length. */ + } arm_cfft_instance_f32; + + void arm_cfft_f32( + const arm_cfft_instance_f32 * S, + float32_t * p1, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + + /** + * @brief Instance structure for the Q15 RFFT/RIFFT function. + */ + typedef struct + { + uint32_t fftLenReal; /**< length of the real FFT. */ + uint8_t ifftFlagR; /**< flag that selects forward (ifftFlagR=0) or inverse (ifftFlagR=1) transform. */ + uint8_t bitReverseFlagR; /**< flag that enables (bitReverseFlagR=1) or disables (bitReverseFlagR=0) bit reversal of output. */ + uint32_t twidCoefRModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + q15_t *pTwiddleAReal; /**< points to the real twiddle factor table. */ + q15_t *pTwiddleBReal; /**< points to the imag twiddle factor table. */ + const arm_cfft_instance_q15 *pCfft; /**< points to the complex FFT instance. */ + } arm_rfft_instance_q15; + + arm_status arm_rfft_init_q15( + arm_rfft_instance_q15 * S, + uint32_t fftLenReal, + uint32_t ifftFlagR, + uint32_t bitReverseFlag); + + void arm_rfft_q15( + const arm_rfft_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst); + + /** + * @brief Instance structure for the Q31 RFFT/RIFFT function. + */ + typedef struct + { + uint32_t fftLenReal; /**< length of the real FFT. */ + uint8_t ifftFlagR; /**< flag that selects forward (ifftFlagR=0) or inverse (ifftFlagR=1) transform. */ + uint8_t bitReverseFlagR; /**< flag that enables (bitReverseFlagR=1) or disables (bitReverseFlagR=0) bit reversal of output. */ + uint32_t twidCoefRModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + q31_t *pTwiddleAReal; /**< points to the real twiddle factor table. */ + q31_t *pTwiddleBReal; /**< points to the imag twiddle factor table. */ + const arm_cfft_instance_q31 *pCfft; /**< points to the complex FFT instance. */ + } arm_rfft_instance_q31; + + arm_status arm_rfft_init_q31( + arm_rfft_instance_q31 * S, + uint32_t fftLenReal, + uint32_t ifftFlagR, + uint32_t bitReverseFlag); + + void arm_rfft_q31( + const arm_rfft_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst); + + /** + * @brief Instance structure for the floating-point RFFT/RIFFT function. + */ + typedef struct + { + uint32_t fftLenReal; /**< length of the real FFT. */ + uint16_t fftLenBy2; /**< length of the complex FFT. */ + uint8_t ifftFlagR; /**< flag that selects forward (ifftFlagR=0) or inverse (ifftFlagR=1) transform. */ + uint8_t bitReverseFlagR; /**< flag that enables (bitReverseFlagR=1) or disables (bitReverseFlagR=0) bit reversal of output. */ + uint32_t twidCoefRModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + float32_t *pTwiddleAReal; /**< points to the real twiddle factor table. */ + float32_t *pTwiddleBReal; /**< points to the imag twiddle factor table. */ + arm_cfft_radix4_instance_f32 *pCfft; /**< points to the complex FFT instance. */ + } arm_rfft_instance_f32; + + arm_status arm_rfft_init_f32( + arm_rfft_instance_f32 * S, + arm_cfft_radix4_instance_f32 * S_CFFT, + uint32_t fftLenReal, + uint32_t ifftFlagR, + uint32_t bitReverseFlag); + + void arm_rfft_f32( + const arm_rfft_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst); + + /** + * @brief Instance structure for the floating-point RFFT/RIFFT function. + */ +typedef struct + { + arm_cfft_instance_f32 Sint; /**< Internal CFFT structure. */ + uint16_t fftLenRFFT; /**< length of the real sequence */ + float32_t * pTwiddleRFFT; /**< Twiddle factors real stage */ + } arm_rfft_fast_instance_f32 ; + +arm_status arm_rfft_fast_init_f32 ( + arm_rfft_fast_instance_f32 * S, + uint16_t fftLen); + +void arm_rfft_fast_f32( + arm_rfft_fast_instance_f32 * S, + float32_t * p, float32_t * pOut, + uint8_t ifftFlag); + + /** + * @brief Instance structure for the floating-point DCT4/IDCT4 function. + */ + typedef struct + { + uint16_t N; /**< length of the DCT4. */ + uint16_t Nby2; /**< half of the length of the DCT4. */ + float32_t normalize; /**< normalizing factor. */ + float32_t *pTwiddle; /**< points to the twiddle factor table. */ + float32_t *pCosFactor; /**< points to the cosFactor table. */ + arm_rfft_instance_f32 *pRfft; /**< points to the real FFT instance. */ + arm_cfft_radix4_instance_f32 *pCfft; /**< points to the complex FFT instance. */ + } arm_dct4_instance_f32; + + + /** + * @brief Initialization function for the floating-point DCT4/IDCT4. + * @param[in,out] S points to an instance of floating-point DCT4/IDCT4 structure. + * @param[in] S_RFFT points to an instance of floating-point RFFT/RIFFT structure. + * @param[in] S_CFFT points to an instance of floating-point CFFT/CIFFT structure. + * @param[in] N length of the DCT4. + * @param[in] Nby2 half of the length of the DCT4. + * @param[in] normalize normalizing factor. + * @return arm_status function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if fftLenReal is not a supported transform length. + */ + arm_status arm_dct4_init_f32( + arm_dct4_instance_f32 * S, + arm_rfft_instance_f32 * S_RFFT, + arm_cfft_radix4_instance_f32 * S_CFFT, + uint16_t N, + uint16_t Nby2, + float32_t normalize); + + + /** + * @brief Processing function for the floating-point DCT4/IDCT4. + * @param[in] S points to an instance of the floating-point DCT4/IDCT4 structure. + * @param[in] pState points to state buffer. + * @param[in,out] pInlineBuffer points to the in-place input and output buffer. + */ + void arm_dct4_f32( + const arm_dct4_instance_f32 * S, + float32_t * pState, + float32_t * pInlineBuffer); + + + /** + * @brief Instance structure for the Q31 DCT4/IDCT4 function. + */ + typedef struct + { + uint16_t N; /**< length of the DCT4. */ + uint16_t Nby2; /**< half of the length of the DCT4. */ + q31_t normalize; /**< normalizing factor. */ + q31_t *pTwiddle; /**< points to the twiddle factor table. */ + q31_t *pCosFactor; /**< points to the cosFactor table. */ + arm_rfft_instance_q31 *pRfft; /**< points to the real FFT instance. */ + arm_cfft_radix4_instance_q31 *pCfft; /**< points to the complex FFT instance. */ + } arm_dct4_instance_q31; + + + /** + * @brief Initialization function for the Q31 DCT4/IDCT4. + * @param[in,out] S points to an instance of Q31 DCT4/IDCT4 structure. + * @param[in] S_RFFT points to an instance of Q31 RFFT/RIFFT structure + * @param[in] S_CFFT points to an instance of Q31 CFFT/CIFFT structure + * @param[in] N length of the DCT4. + * @param[in] Nby2 half of the length of the DCT4. + * @param[in] normalize normalizing factor. + * @return arm_status function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if N is not a supported transform length. + */ + arm_status arm_dct4_init_q31( + arm_dct4_instance_q31 * S, + arm_rfft_instance_q31 * S_RFFT, + arm_cfft_radix4_instance_q31 * S_CFFT, + uint16_t N, + uint16_t Nby2, + q31_t normalize); + + + /** + * @brief Processing function for the Q31 DCT4/IDCT4. + * @param[in] S points to an instance of the Q31 DCT4 structure. + * @param[in] pState points to state buffer. + * @param[in,out] pInlineBuffer points to the in-place input and output buffer. + */ + void arm_dct4_q31( + const arm_dct4_instance_q31 * S, + q31_t * pState, + q31_t * pInlineBuffer); + + + /** + * @brief Instance structure for the Q15 DCT4/IDCT4 function. + */ + typedef struct + { + uint16_t N; /**< length of the DCT4. */ + uint16_t Nby2; /**< half of the length of the DCT4. */ + q15_t normalize; /**< normalizing factor. */ + q15_t *pTwiddle; /**< points to the twiddle factor table. */ + q15_t *pCosFactor; /**< points to the cosFactor table. */ + arm_rfft_instance_q15 *pRfft; /**< points to the real FFT instance. */ + arm_cfft_radix4_instance_q15 *pCfft; /**< points to the complex FFT instance. */ + } arm_dct4_instance_q15; + + + /** + * @brief Initialization function for the Q15 DCT4/IDCT4. + * @param[in,out] S points to an instance of Q15 DCT4/IDCT4 structure. + * @param[in] S_RFFT points to an instance of Q15 RFFT/RIFFT structure. + * @param[in] S_CFFT points to an instance of Q15 CFFT/CIFFT structure. + * @param[in] N length of the DCT4. + * @param[in] Nby2 half of the length of the DCT4. + * @param[in] normalize normalizing factor. + * @return arm_status function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if N is not a supported transform length. + */ + arm_status arm_dct4_init_q15( + arm_dct4_instance_q15 * S, + arm_rfft_instance_q15 * S_RFFT, + arm_cfft_radix4_instance_q15 * S_CFFT, + uint16_t N, + uint16_t Nby2, + q15_t normalize); + + + /** + * @brief Processing function for the Q15 DCT4/IDCT4. + * @param[in] S points to an instance of the Q15 DCT4 structure. + * @param[in] pState points to state buffer. + * @param[in,out] pInlineBuffer points to the in-place input and output buffer. + */ + void arm_dct4_q15( + const arm_dct4_instance_q15 * S, + q15_t * pState, + q15_t * pInlineBuffer); + + + /** + * @brief Floating-point vector addition. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_add_f32( + float32_t * pSrcA, + float32_t * pSrcB, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q7 vector addition. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_add_q7( + q7_t * pSrcA, + q7_t * pSrcB, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q15 vector addition. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_add_q15( + q15_t * pSrcA, + q15_t * pSrcB, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q31 vector addition. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_add_q31( + q31_t * pSrcA, + q31_t * pSrcB, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Floating-point vector subtraction. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_sub_f32( + float32_t * pSrcA, + float32_t * pSrcB, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q7 vector subtraction. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_sub_q7( + q7_t * pSrcA, + q7_t * pSrcB, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q15 vector subtraction. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_sub_q15( + q15_t * pSrcA, + q15_t * pSrcB, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q31 vector subtraction. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_sub_q31( + q31_t * pSrcA, + q31_t * pSrcB, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Multiplies a floating-point vector by a scalar. + * @param[in] pSrc points to the input vector + * @param[in] scale scale factor to be applied + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_scale_f32( + float32_t * pSrc, + float32_t scale, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Multiplies a Q7 vector by a scalar. + * @param[in] pSrc points to the input vector + * @param[in] scaleFract fractional portion of the scale value + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_scale_q7( + q7_t * pSrc, + q7_t scaleFract, + int8_t shift, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Multiplies a Q15 vector by a scalar. + * @param[in] pSrc points to the input vector + * @param[in] scaleFract fractional portion of the scale value + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_scale_q15( + q15_t * pSrc, + q15_t scaleFract, + int8_t shift, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Multiplies a Q31 vector by a scalar. + * @param[in] pSrc points to the input vector + * @param[in] scaleFract fractional portion of the scale value + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_scale_q31( + q31_t * pSrc, + q31_t scaleFract, + int8_t shift, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q7 vector absolute value. + * @param[in] pSrc points to the input buffer + * @param[out] pDst points to the output buffer + * @param[in] blockSize number of samples in each vector + */ + void arm_abs_q7( + q7_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Floating-point vector absolute value. + * @param[in] pSrc points to the input buffer + * @param[out] pDst points to the output buffer + * @param[in] blockSize number of samples in each vector + */ + void arm_abs_f32( + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q15 vector absolute value. + * @param[in] pSrc points to the input buffer + * @param[out] pDst points to the output buffer + * @param[in] blockSize number of samples in each vector + */ + void arm_abs_q15( + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q31 vector absolute value. + * @param[in] pSrc points to the input buffer + * @param[out] pDst points to the output buffer + * @param[in] blockSize number of samples in each vector + */ + void arm_abs_q31( + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Dot product of floating-point vectors. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] blockSize number of samples in each vector + * @param[out] result output result returned here + */ + void arm_dot_prod_f32( + float32_t * pSrcA, + float32_t * pSrcB, + uint32_t blockSize, + float32_t * result); + + + /** + * @brief Dot product of Q7 vectors. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] blockSize number of samples in each vector + * @param[out] result output result returned here + */ + void arm_dot_prod_q7( + q7_t * pSrcA, + q7_t * pSrcB, + uint32_t blockSize, + q31_t * result); + + + /** + * @brief Dot product of Q15 vectors. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] blockSize number of samples in each vector + * @param[out] result output result returned here + */ + void arm_dot_prod_q15( + q15_t * pSrcA, + q15_t * pSrcB, + uint32_t blockSize, + q63_t * result); + + + /** + * @brief Dot product of Q31 vectors. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] blockSize number of samples in each vector + * @param[out] result output result returned here + */ + void arm_dot_prod_q31( + q31_t * pSrcA, + q31_t * pSrcB, + uint32_t blockSize, + q63_t * result); + + + /** + * @brief Shifts the elements of a Q7 vector a specified number of bits. + * @param[in] pSrc points to the input vector + * @param[in] shiftBits number of bits to shift. A positive value shifts left; a negative value shifts right. + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_shift_q7( + q7_t * pSrc, + int8_t shiftBits, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Shifts the elements of a Q15 vector a specified number of bits. + * @param[in] pSrc points to the input vector + * @param[in] shiftBits number of bits to shift. A positive value shifts left; a negative value shifts right. + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_shift_q15( + q15_t * pSrc, + int8_t shiftBits, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Shifts the elements of a Q31 vector a specified number of bits. + * @param[in] pSrc points to the input vector + * @param[in] shiftBits number of bits to shift. A positive value shifts left; a negative value shifts right. + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_shift_q31( + q31_t * pSrc, + int8_t shiftBits, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Adds a constant offset to a floating-point vector. + * @param[in] pSrc points to the input vector + * @param[in] offset is the offset to be added + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_offset_f32( + float32_t * pSrc, + float32_t offset, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Adds a constant offset to a Q7 vector. + * @param[in] pSrc points to the input vector + * @param[in] offset is the offset to be added + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_offset_q7( + q7_t * pSrc, + q7_t offset, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Adds a constant offset to a Q15 vector. + * @param[in] pSrc points to the input vector + * @param[in] offset is the offset to be added + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_offset_q15( + q15_t * pSrc, + q15_t offset, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Adds a constant offset to a Q31 vector. + * @param[in] pSrc points to the input vector + * @param[in] offset is the offset to be added + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_offset_q31( + q31_t * pSrc, + q31_t offset, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Negates the elements of a floating-point vector. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_negate_f32( + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Negates the elements of a Q7 vector. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_negate_q7( + q7_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Negates the elements of a Q15 vector. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_negate_q15( + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Negates the elements of a Q31 vector. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_negate_q31( + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Copies the elements of a floating-point vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_copy_f32( + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Copies the elements of a Q7 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_copy_q7( + q7_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Copies the elements of a Q15 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_copy_q15( + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Copies the elements of a Q31 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_copy_q31( + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Fills a constant value into a floating-point vector. + * @param[in] value input value to be filled + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_fill_f32( + float32_t value, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Fills a constant value into a Q7 vector. + * @param[in] value input value to be filled + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_fill_q7( + q7_t value, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Fills a constant value into a Q15 vector. + * @param[in] value input value to be filled + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_fill_q15( + q15_t value, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Fills a constant value into a Q31 vector. + * @param[in] value input value to be filled + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_fill_q31( + q31_t value, + q31_t * pDst, + uint32_t blockSize); + + +/** + * @brief Convolution of floating-point sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the location where the output result is written. Length srcALen+srcBLen-1. + */ + void arm_conv_f32( + float32_t * pSrcA, + uint32_t srcALen, + float32_t * pSrcB, + uint32_t srcBLen, + float32_t * pDst); + + + /** + * @brief Convolution of Q15 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + * @param[in] pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer of size min(srcALen, srcBLen). + */ + void arm_conv_opt_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + q15_t * pScratch1, + q15_t * pScratch2); + + +/** + * @brief Convolution of Q15 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the location where the output result is written. Length srcALen+srcBLen-1. + */ + void arm_conv_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst); + + + /** + * @brief Convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + */ + void arm_conv_fast_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst); + + + /** + * @brief Convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + * @param[in] pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer of size min(srcALen, srcBLen). + */ + void arm_conv_fast_opt_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + q15_t * pScratch1, + q15_t * pScratch2); + + + /** + * @brief Convolution of Q31 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + */ + void arm_conv_q31( + q31_t * pSrcA, + uint32_t srcALen, + q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst); + + + /** + * @brief Convolution of Q31 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + */ + void arm_conv_fast_q31( + q31_t * pSrcA, + uint32_t srcALen, + q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst); + + + /** + * @brief Convolution of Q7 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + * @param[in] pScratch1 points to scratch buffer(of type q15_t) of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer (of type q15_t) of size min(srcALen, srcBLen). + */ + void arm_conv_opt_q7( + q7_t * pSrcA, + uint32_t srcALen, + q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst, + q15_t * pScratch1, + q15_t * pScratch2); + + + /** + * @brief Convolution of Q7 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + */ + void arm_conv_q7( + q7_t * pSrcA, + uint32_t srcALen, + q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst); + + + /** + * @brief Partial convolution of floating-point sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_f32( + float32_t * pSrcA, + uint32_t srcALen, + float32_t * pSrcB, + uint32_t srcBLen, + float32_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Partial convolution of Q15 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @param[in] pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer of size min(srcALen, srcBLen). + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_opt_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + uint32_t firstIndex, + uint32_t numPoints, + q15_t * pScratch1, + q15_t * pScratch2); + + + /** + * @brief Partial convolution of Q15 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Partial convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_fast_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Partial convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @param[in] pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer of size min(srcALen, srcBLen). + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_fast_opt_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + uint32_t firstIndex, + uint32_t numPoints, + q15_t * pScratch1, + q15_t * pScratch2); + + + /** + * @brief Partial convolution of Q31 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_q31( + q31_t * pSrcA, + uint32_t srcALen, + q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Partial convolution of Q31 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_fast_q31( + q31_t * pSrcA, + uint32_t srcALen, + q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Partial convolution of Q7 sequences + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @param[in] pScratch1 points to scratch buffer(of type q15_t) of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer (of type q15_t) of size min(srcALen, srcBLen). + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_opt_q7( + q7_t * pSrcA, + uint32_t srcALen, + q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst, + uint32_t firstIndex, + uint32_t numPoints, + q15_t * pScratch1, + q15_t * pScratch2); + + +/** + * @brief Partial convolution of Q7 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_q7( + q7_t * pSrcA, + uint32_t srcALen, + q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Instance structure for the Q15 FIR decimator. + */ + typedef struct + { + uint8_t M; /**< decimation factor. */ + uint16_t numTaps; /**< number of coefficients in the filter. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + q15_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + } arm_fir_decimate_instance_q15; + + /** + * @brief Instance structure for the Q31 FIR decimator. + */ + typedef struct + { + uint8_t M; /**< decimation factor. */ + uint16_t numTaps; /**< number of coefficients in the filter. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + q31_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + } arm_fir_decimate_instance_q31; + + /** + * @brief Instance structure for the floating-point FIR decimator. + */ + typedef struct + { + uint8_t M; /**< decimation factor. */ + uint16_t numTaps; /**< number of coefficients in the filter. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + float32_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + } arm_fir_decimate_instance_f32; + + + /** + * @brief Processing function for the floating-point FIR decimator. + * @param[in] S points to an instance of the floating-point FIR decimator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_decimate_f32( + const arm_fir_decimate_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point FIR decimator. + * @param[in,out] S points to an instance of the floating-point FIR decimator structure. + * @param[in] numTaps number of coefficients in the filter. + * @param[in] M decimation factor. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * blockSize is not a multiple of M. + */ + arm_status arm_fir_decimate_init_f32( + arm_fir_decimate_instance_f32 * S, + uint16_t numTaps, + uint8_t M, + float32_t * pCoeffs, + float32_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q15 FIR decimator. + * @param[in] S points to an instance of the Q15 FIR decimator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_decimate_q15( + const arm_fir_decimate_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q15 FIR decimator (fast variant) for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q15 FIR decimator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_decimate_fast_q15( + const arm_fir_decimate_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q15 FIR decimator. + * @param[in,out] S points to an instance of the Q15 FIR decimator structure. + * @param[in] numTaps number of coefficients in the filter. + * @param[in] M decimation factor. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * blockSize is not a multiple of M. + */ + arm_status arm_fir_decimate_init_q15( + arm_fir_decimate_instance_q15 * S, + uint16_t numTaps, + uint8_t M, + q15_t * pCoeffs, + q15_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 FIR decimator. + * @param[in] S points to an instance of the Q31 FIR decimator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_decimate_q31( + const arm_fir_decimate_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + /** + * @brief Processing function for the Q31 FIR decimator (fast variant) for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q31 FIR decimator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_decimate_fast_q31( + arm_fir_decimate_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 FIR decimator. + * @param[in,out] S points to an instance of the Q31 FIR decimator structure. + * @param[in] numTaps number of coefficients in the filter. + * @param[in] M decimation factor. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * blockSize is not a multiple of M. + */ + arm_status arm_fir_decimate_init_q31( + arm_fir_decimate_instance_q31 * S, + uint16_t numTaps, + uint8_t M, + q31_t * pCoeffs, + q31_t * pState, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q15 FIR interpolator. + */ + typedef struct + { + uint8_t L; /**< upsample factor. */ + uint16_t phaseLength; /**< length of each polyphase filter component. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length L*phaseLength. */ + q15_t *pState; /**< points to the state variable array. The array is of length blockSize+phaseLength-1. */ + } arm_fir_interpolate_instance_q15; + + /** + * @brief Instance structure for the Q31 FIR interpolator. + */ + typedef struct + { + uint8_t L; /**< upsample factor. */ + uint16_t phaseLength; /**< length of each polyphase filter component. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length L*phaseLength. */ + q31_t *pState; /**< points to the state variable array. The array is of length blockSize+phaseLength-1. */ + } arm_fir_interpolate_instance_q31; + + /** + * @brief Instance structure for the floating-point FIR interpolator. + */ + typedef struct + { + uint8_t L; /**< upsample factor. */ + uint16_t phaseLength; /**< length of each polyphase filter component. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length L*phaseLength. */ + float32_t *pState; /**< points to the state variable array. The array is of length phaseLength+numTaps-1. */ + } arm_fir_interpolate_instance_f32; + + + /** + * @brief Processing function for the Q15 FIR interpolator. + * @param[in] S points to an instance of the Q15 FIR interpolator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_interpolate_q15( + const arm_fir_interpolate_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q15 FIR interpolator. + * @param[in,out] S points to an instance of the Q15 FIR interpolator structure. + * @param[in] L upsample factor. + * @param[in] numTaps number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficient buffer. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * the filter length numTaps is not a multiple of the interpolation factor L. + */ + arm_status arm_fir_interpolate_init_q15( + arm_fir_interpolate_instance_q15 * S, + uint8_t L, + uint16_t numTaps, + q15_t * pCoeffs, + q15_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 FIR interpolator. + * @param[in] S points to an instance of the Q15 FIR interpolator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_interpolate_q31( + const arm_fir_interpolate_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 FIR interpolator. + * @param[in,out] S points to an instance of the Q31 FIR interpolator structure. + * @param[in] L upsample factor. + * @param[in] numTaps number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficient buffer. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * the filter length numTaps is not a multiple of the interpolation factor L. + */ + arm_status arm_fir_interpolate_init_q31( + arm_fir_interpolate_instance_q31 * S, + uint8_t L, + uint16_t numTaps, + q31_t * pCoeffs, + q31_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the floating-point FIR interpolator. + * @param[in] S points to an instance of the floating-point FIR interpolator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_interpolate_f32( + const arm_fir_interpolate_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point FIR interpolator. + * @param[in,out] S points to an instance of the floating-point FIR interpolator structure. + * @param[in] L upsample factor. + * @param[in] numTaps number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficient buffer. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * the filter length numTaps is not a multiple of the interpolation factor L. + */ + arm_status arm_fir_interpolate_init_f32( + arm_fir_interpolate_instance_f32 * S, + uint8_t L, + uint16_t numTaps, + float32_t * pCoeffs, + float32_t * pState, + uint32_t blockSize); + + + /** + * @brief Instance structure for the high precision Q31 Biquad cascade filter. + */ + typedef struct + { + uint8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + q63_t *pState; /**< points to the array of state coefficients. The array is of length 4*numStages. */ + q31_t *pCoeffs; /**< points to the array of coefficients. The array is of length 5*numStages. */ + uint8_t postShift; /**< additional shift, in bits, applied to each output sample. */ + } arm_biquad_cas_df1_32x64_ins_q31; + + + /** + * @param[in] S points to an instance of the high precision Q31 Biquad cascade filter structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cas_df1_32x64_q31( + const arm_biquad_cas_df1_32x64_ins_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @param[in,out] S points to an instance of the high precision Q31 Biquad cascade filter structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] postShift shift to be applied to the output. Varies according to the coefficients format + */ + void arm_biquad_cas_df1_32x64_init_q31( + arm_biquad_cas_df1_32x64_ins_q31 * S, + uint8_t numStages, + q31_t * pCoeffs, + q63_t * pState, + uint8_t postShift); + + + /** + * @brief Instance structure for the floating-point transposed direct form II Biquad cascade filter. + */ + typedef struct + { + uint8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + float32_t *pState; /**< points to the array of state coefficients. The array is of length 2*numStages. */ + float32_t *pCoeffs; /**< points to the array of coefficients. The array is of length 5*numStages. */ + } arm_biquad_cascade_df2T_instance_f32; + + /** + * @brief Instance structure for the floating-point transposed direct form II Biquad cascade filter. + */ + typedef struct + { + uint8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + float32_t *pState; /**< points to the array of state coefficients. The array is of length 4*numStages. */ + float32_t *pCoeffs; /**< points to the array of coefficients. The array is of length 5*numStages. */ + } arm_biquad_cascade_stereo_df2T_instance_f32; + + /** + * @brief Instance structure for the floating-point transposed direct form II Biquad cascade filter. + */ + typedef struct + { + uint8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + float64_t *pState; /**< points to the array of state coefficients. The array is of length 2*numStages. */ + float64_t *pCoeffs; /**< points to the array of coefficients. The array is of length 5*numStages. */ + } arm_biquad_cascade_df2T_instance_f64; + + + /** + * @brief Processing function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in] S points to an instance of the filter data structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df2T_f32( + const arm_biquad_cascade_df2T_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Processing function for the floating-point transposed direct form II Biquad cascade filter. 2 channels + * @param[in] S points to an instance of the filter data structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_stereo_df2T_f32( + const arm_biquad_cascade_stereo_df2T_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Processing function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in] S points to an instance of the filter data structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df2T_f64( + const arm_biquad_cascade_df2T_instance_f64 * S, + float64_t * pSrc, + float64_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in,out] S points to an instance of the filter data structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + */ + void arm_biquad_cascade_df2T_init_f32( + arm_biquad_cascade_df2T_instance_f32 * S, + uint8_t numStages, + float32_t * pCoeffs, + float32_t * pState); + + + /** + * @brief Initialization function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in,out] S points to an instance of the filter data structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + */ + void arm_biquad_cascade_stereo_df2T_init_f32( + arm_biquad_cascade_stereo_df2T_instance_f32 * S, + uint8_t numStages, + float32_t * pCoeffs, + float32_t * pState); + + + /** + * @brief Initialization function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in,out] S points to an instance of the filter data structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + */ + void arm_biquad_cascade_df2T_init_f64( + arm_biquad_cascade_df2T_instance_f64 * S, + uint8_t numStages, + float64_t * pCoeffs, + float64_t * pState); + + + /** + * @brief Instance structure for the Q15 FIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of filter stages. */ + q15_t *pState; /**< points to the state variable array. The array is of length numStages. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numStages. */ + } arm_fir_lattice_instance_q15; + + /** + * @brief Instance structure for the Q31 FIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of filter stages. */ + q31_t *pState; /**< points to the state variable array. The array is of length numStages. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numStages. */ + } arm_fir_lattice_instance_q31; + + /** + * @brief Instance structure for the floating-point FIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of filter stages. */ + float32_t *pState; /**< points to the state variable array. The array is of length numStages. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numStages. */ + } arm_fir_lattice_instance_f32; + + + /** + * @brief Initialization function for the Q15 FIR lattice filter. + * @param[in] S points to an instance of the Q15 FIR lattice structure. + * @param[in] numStages number of filter stages. + * @param[in] pCoeffs points to the coefficient buffer. The array is of length numStages. + * @param[in] pState points to the state buffer. The array is of length numStages. + */ + void arm_fir_lattice_init_q15( + arm_fir_lattice_instance_q15 * S, + uint16_t numStages, + q15_t * pCoeffs, + q15_t * pState); + + + /** + * @brief Processing function for the Q15 FIR lattice filter. + * @param[in] S points to an instance of the Q15 FIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_lattice_q15( + const arm_fir_lattice_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 FIR lattice filter. + * @param[in] S points to an instance of the Q31 FIR lattice structure. + * @param[in] numStages number of filter stages. + * @param[in] pCoeffs points to the coefficient buffer. The array is of length numStages. + * @param[in] pState points to the state buffer. The array is of length numStages. + */ + void arm_fir_lattice_init_q31( + arm_fir_lattice_instance_q31 * S, + uint16_t numStages, + q31_t * pCoeffs, + q31_t * pState); + + + /** + * @brief Processing function for the Q31 FIR lattice filter. + * @param[in] S points to an instance of the Q31 FIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_fir_lattice_q31( + const arm_fir_lattice_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + +/** + * @brief Initialization function for the floating-point FIR lattice filter. + * @param[in] S points to an instance of the floating-point FIR lattice structure. + * @param[in] numStages number of filter stages. + * @param[in] pCoeffs points to the coefficient buffer. The array is of length numStages. + * @param[in] pState points to the state buffer. The array is of length numStages. + */ + void arm_fir_lattice_init_f32( + arm_fir_lattice_instance_f32 * S, + uint16_t numStages, + float32_t * pCoeffs, + float32_t * pState); + + + /** + * @brief Processing function for the floating-point FIR lattice filter. + * @param[in] S points to an instance of the floating-point FIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_fir_lattice_f32( + const arm_fir_lattice_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q15 IIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of stages in the filter. */ + q15_t *pState; /**< points to the state variable array. The array is of length numStages+blockSize. */ + q15_t *pkCoeffs; /**< points to the reflection coefficient array. The array is of length numStages. */ + q15_t *pvCoeffs; /**< points to the ladder coefficient array. The array is of length numStages+1. */ + } arm_iir_lattice_instance_q15; + + /** + * @brief Instance structure for the Q31 IIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of stages in the filter. */ + q31_t *pState; /**< points to the state variable array. The array is of length numStages+blockSize. */ + q31_t *pkCoeffs; /**< points to the reflection coefficient array. The array is of length numStages. */ + q31_t *pvCoeffs; /**< points to the ladder coefficient array. The array is of length numStages+1. */ + } arm_iir_lattice_instance_q31; + + /** + * @brief Instance structure for the floating-point IIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of stages in the filter. */ + float32_t *pState; /**< points to the state variable array. The array is of length numStages+blockSize. */ + float32_t *pkCoeffs; /**< points to the reflection coefficient array. The array is of length numStages. */ + float32_t *pvCoeffs; /**< points to the ladder coefficient array. The array is of length numStages+1. */ + } arm_iir_lattice_instance_f32; + + + /** + * @brief Processing function for the floating-point IIR lattice filter. + * @param[in] S points to an instance of the floating-point IIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_iir_lattice_f32( + const arm_iir_lattice_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point IIR lattice filter. + * @param[in] S points to an instance of the floating-point IIR lattice structure. + * @param[in] numStages number of stages in the filter. + * @param[in] pkCoeffs points to the reflection coefficient buffer. The array is of length numStages. + * @param[in] pvCoeffs points to the ladder coefficient buffer. The array is of length numStages+1. + * @param[in] pState points to the state buffer. The array is of length numStages+blockSize-1. + * @param[in] blockSize number of samples to process. + */ + void arm_iir_lattice_init_f32( + arm_iir_lattice_instance_f32 * S, + uint16_t numStages, + float32_t * pkCoeffs, + float32_t * pvCoeffs, + float32_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 IIR lattice filter. + * @param[in] S points to an instance of the Q31 IIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_iir_lattice_q31( + const arm_iir_lattice_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 IIR lattice filter. + * @param[in] S points to an instance of the Q31 IIR lattice structure. + * @param[in] numStages number of stages in the filter. + * @param[in] pkCoeffs points to the reflection coefficient buffer. The array is of length numStages. + * @param[in] pvCoeffs points to the ladder coefficient buffer. The array is of length numStages+1. + * @param[in] pState points to the state buffer. The array is of length numStages+blockSize. + * @param[in] blockSize number of samples to process. + */ + void arm_iir_lattice_init_q31( + arm_iir_lattice_instance_q31 * S, + uint16_t numStages, + q31_t * pkCoeffs, + q31_t * pvCoeffs, + q31_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q15 IIR lattice filter. + * @param[in] S points to an instance of the Q15 IIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_iir_lattice_q15( + const arm_iir_lattice_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + +/** + * @brief Initialization function for the Q15 IIR lattice filter. + * @param[in] S points to an instance of the fixed-point Q15 IIR lattice structure. + * @param[in] numStages number of stages in the filter. + * @param[in] pkCoeffs points to reflection coefficient buffer. The array is of length numStages. + * @param[in] pvCoeffs points to ladder coefficient buffer. The array is of length numStages+1. + * @param[in] pState points to state buffer. The array is of length numStages+blockSize. + * @param[in] blockSize number of samples to process per call. + */ + void arm_iir_lattice_init_q15( + arm_iir_lattice_instance_q15 * S, + uint16_t numStages, + q15_t * pkCoeffs, + q15_t * pvCoeffs, + q15_t * pState, + uint32_t blockSize); + + + /** + * @brief Instance structure for the floating-point LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + float32_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + float32_t mu; /**< step size that controls filter coefficient updates. */ + } arm_lms_instance_f32; + + + /** + * @brief Processing function for floating-point LMS filter. + * @param[in] S points to an instance of the floating-point LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_f32( + const arm_lms_instance_f32 * S, + float32_t * pSrc, + float32_t * pRef, + float32_t * pOut, + float32_t * pErr, + uint32_t blockSize); + + + /** + * @brief Initialization function for floating-point LMS filter. + * @param[in] S points to an instance of the floating-point LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to the coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_init_f32( + arm_lms_instance_f32 * S, + uint16_t numTaps, + float32_t * pCoeffs, + float32_t * pState, + float32_t mu, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q15 LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + q15_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + q15_t mu; /**< step size that controls filter coefficient updates. */ + uint32_t postShift; /**< bit shift applied to coefficients. */ + } arm_lms_instance_q15; + + + /** + * @brief Initialization function for the Q15 LMS filter. + * @param[in] S points to an instance of the Q15 LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to the coefficient buffer. + * @param[in] pState points to the state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + * @param[in] postShift bit shift applied to coefficients. + */ + void arm_lms_init_q15( + arm_lms_instance_q15 * S, + uint16_t numTaps, + q15_t * pCoeffs, + q15_t * pState, + q15_t mu, + uint32_t blockSize, + uint32_t postShift); + + + /** + * @brief Processing function for Q15 LMS filter. + * @param[in] S points to an instance of the Q15 LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_q15( + const arm_lms_instance_q15 * S, + q15_t * pSrc, + q15_t * pRef, + q15_t * pOut, + q15_t * pErr, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q31 LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + q31_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + q31_t mu; /**< step size that controls filter coefficient updates. */ + uint32_t postShift; /**< bit shift applied to coefficients. */ + } arm_lms_instance_q31; + + + /** + * @brief Processing function for Q31 LMS filter. + * @param[in] S points to an instance of the Q15 LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_q31( + const arm_lms_instance_q31 * S, + q31_t * pSrc, + q31_t * pRef, + q31_t * pOut, + q31_t * pErr, + uint32_t blockSize); + + + /** + * @brief Initialization function for Q31 LMS filter. + * @param[in] S points to an instance of the Q31 LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + * @param[in] postShift bit shift applied to coefficients. + */ + void arm_lms_init_q31( + arm_lms_instance_q31 * S, + uint16_t numTaps, + q31_t * pCoeffs, + q31_t * pState, + q31_t mu, + uint32_t blockSize, + uint32_t postShift); + + + /** + * @brief Instance structure for the floating-point normalized LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + float32_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + float32_t mu; /**< step size that control filter coefficient updates. */ + float32_t energy; /**< saves previous frame energy. */ + float32_t x0; /**< saves previous input sample. */ + } arm_lms_norm_instance_f32; + + + /** + * @brief Processing function for floating-point normalized LMS filter. + * @param[in] S points to an instance of the floating-point normalized LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_norm_f32( + arm_lms_norm_instance_f32 * S, + float32_t * pSrc, + float32_t * pRef, + float32_t * pOut, + float32_t * pErr, + uint32_t blockSize); + + + /** + * @brief Initialization function for floating-point normalized LMS filter. + * @param[in] S points to an instance of the floating-point LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_norm_init_f32( + arm_lms_norm_instance_f32 * S, + uint16_t numTaps, + float32_t * pCoeffs, + float32_t * pState, + float32_t mu, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q31 normalized LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + q31_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + q31_t mu; /**< step size that controls filter coefficient updates. */ + uint8_t postShift; /**< bit shift applied to coefficients. */ + q31_t *recipTable; /**< points to the reciprocal initial value table. */ + q31_t energy; /**< saves previous frame energy. */ + q31_t x0; /**< saves previous input sample. */ + } arm_lms_norm_instance_q31; + + + /** + * @brief Processing function for Q31 normalized LMS filter. + * @param[in] S points to an instance of the Q31 normalized LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_norm_q31( + arm_lms_norm_instance_q31 * S, + q31_t * pSrc, + q31_t * pRef, + q31_t * pOut, + q31_t * pErr, + uint32_t blockSize); + + + /** + * @brief Initialization function for Q31 normalized LMS filter. + * @param[in] S points to an instance of the Q31 normalized LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + * @param[in] postShift bit shift applied to coefficients. + */ + void arm_lms_norm_init_q31( + arm_lms_norm_instance_q31 * S, + uint16_t numTaps, + q31_t * pCoeffs, + q31_t * pState, + q31_t mu, + uint32_t blockSize, + uint8_t postShift); + + + /** + * @brief Instance structure for the Q15 normalized LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< Number of coefficients in the filter. */ + q15_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + q15_t mu; /**< step size that controls filter coefficient updates. */ + uint8_t postShift; /**< bit shift applied to coefficients. */ + q15_t *recipTable; /**< Points to the reciprocal initial value table. */ + q15_t energy; /**< saves previous frame energy. */ + q15_t x0; /**< saves previous input sample. */ + } arm_lms_norm_instance_q15; + + + /** + * @brief Processing function for Q15 normalized LMS filter. + * @param[in] S points to an instance of the Q15 normalized LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_norm_q15( + arm_lms_norm_instance_q15 * S, + q15_t * pSrc, + q15_t * pRef, + q15_t * pOut, + q15_t * pErr, + uint32_t blockSize); + + + /** + * @brief Initialization function for Q15 normalized LMS filter. + * @param[in] S points to an instance of the Q15 normalized LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + * @param[in] postShift bit shift applied to coefficients. + */ + void arm_lms_norm_init_q15( + arm_lms_norm_instance_q15 * S, + uint16_t numTaps, + q15_t * pCoeffs, + q15_t * pState, + q15_t mu, + uint32_t blockSize, + uint8_t postShift); + + + /** + * @brief Correlation of floating-point sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + void arm_correlate_f32( + float32_t * pSrcA, + uint32_t srcALen, + float32_t * pSrcB, + uint32_t srcBLen, + float32_t * pDst); + + + /** + * @brief Correlation of Q15 sequences + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + * @param[in] pScratch points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + */ + void arm_correlate_opt_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + q15_t * pScratch); + + + /** + * @brief Correlation of Q15 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + + void arm_correlate_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst); + + + /** + * @brief Correlation of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + + void arm_correlate_fast_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst); + + + /** + * @brief Correlation of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + * @param[in] pScratch points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + */ + void arm_correlate_fast_opt_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + q15_t * pScratch); + + + /** + * @brief Correlation of Q31 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + void arm_correlate_q31( + q31_t * pSrcA, + uint32_t srcALen, + q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst); + + + /** + * @brief Correlation of Q31 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + void arm_correlate_fast_q31( + q31_t * pSrcA, + uint32_t srcALen, + q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst); + + + /** + * @brief Correlation of Q7 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + * @param[in] pScratch1 points to scratch buffer(of type q15_t) of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer (of type q15_t) of size min(srcALen, srcBLen). + */ + void arm_correlate_opt_q7( + q7_t * pSrcA, + uint32_t srcALen, + q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst, + q15_t * pScratch1, + q15_t * pScratch2); + + + /** + * @brief Correlation of Q7 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + void arm_correlate_q7( + q7_t * pSrcA, + uint32_t srcALen, + q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst); + + + /** + * @brief Instance structure for the floating-point sparse FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + uint16_t stateIndex; /**< state buffer index. Points to the oldest sample in the state buffer. */ + float32_t *pState; /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + uint16_t maxDelay; /**< maximum offset specified by the pTapDelay array. */ + int32_t *pTapDelay; /**< points to the array of delay values. The array is of length numTaps. */ + } arm_fir_sparse_instance_f32; + + /** + * @brief Instance structure for the Q31 sparse FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + uint16_t stateIndex; /**< state buffer index. Points to the oldest sample in the state buffer. */ + q31_t *pState; /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + uint16_t maxDelay; /**< maximum offset specified by the pTapDelay array. */ + int32_t *pTapDelay; /**< points to the array of delay values. The array is of length numTaps. */ + } arm_fir_sparse_instance_q31; + + /** + * @brief Instance structure for the Q15 sparse FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + uint16_t stateIndex; /**< state buffer index. Points to the oldest sample in the state buffer. */ + q15_t *pState; /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + uint16_t maxDelay; /**< maximum offset specified by the pTapDelay array. */ + int32_t *pTapDelay; /**< points to the array of delay values. The array is of length numTaps. */ + } arm_fir_sparse_instance_q15; + + /** + * @brief Instance structure for the Q7 sparse FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + uint16_t stateIndex; /**< state buffer index. Points to the oldest sample in the state buffer. */ + q7_t *pState; /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */ + q7_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + uint16_t maxDelay; /**< maximum offset specified by the pTapDelay array. */ + int32_t *pTapDelay; /**< points to the array of delay values. The array is of length numTaps. */ + } arm_fir_sparse_instance_q7; + + + /** + * @brief Processing function for the floating-point sparse FIR filter. + * @param[in] S points to an instance of the floating-point sparse FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] pScratchIn points to a temporary buffer of size blockSize. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_sparse_f32( + arm_fir_sparse_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + float32_t * pScratchIn, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point sparse FIR filter. + * @param[in,out] S points to an instance of the floating-point sparse FIR structure. + * @param[in] numTaps number of nonzero coefficients in the filter. + * @param[in] pCoeffs points to the array of filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] pTapDelay points to the array of offset times. + * @param[in] maxDelay maximum offset time supported. + * @param[in] blockSize number of samples that will be processed per block. + */ + void arm_fir_sparse_init_f32( + arm_fir_sparse_instance_f32 * S, + uint16_t numTaps, + float32_t * pCoeffs, + float32_t * pState, + int32_t * pTapDelay, + uint16_t maxDelay, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 sparse FIR filter. + * @param[in] S points to an instance of the Q31 sparse FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] pScratchIn points to a temporary buffer of size blockSize. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_sparse_q31( + arm_fir_sparse_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + q31_t * pScratchIn, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 sparse FIR filter. + * @param[in,out] S points to an instance of the Q31 sparse FIR structure. + * @param[in] numTaps number of nonzero coefficients in the filter. + * @param[in] pCoeffs points to the array of filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] pTapDelay points to the array of offset times. + * @param[in] maxDelay maximum offset time supported. + * @param[in] blockSize number of samples that will be processed per block. + */ + void arm_fir_sparse_init_q31( + arm_fir_sparse_instance_q31 * S, + uint16_t numTaps, + q31_t * pCoeffs, + q31_t * pState, + int32_t * pTapDelay, + uint16_t maxDelay, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q15 sparse FIR filter. + * @param[in] S points to an instance of the Q15 sparse FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] pScratchIn points to a temporary buffer of size blockSize. + * @param[in] pScratchOut points to a temporary buffer of size blockSize. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_sparse_q15( + arm_fir_sparse_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + q15_t * pScratchIn, + q31_t * pScratchOut, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q15 sparse FIR filter. + * @param[in,out] S points to an instance of the Q15 sparse FIR structure. + * @param[in] numTaps number of nonzero coefficients in the filter. + * @param[in] pCoeffs points to the array of filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] pTapDelay points to the array of offset times. + * @param[in] maxDelay maximum offset time supported. + * @param[in] blockSize number of samples that will be processed per block. + */ + void arm_fir_sparse_init_q15( + arm_fir_sparse_instance_q15 * S, + uint16_t numTaps, + q15_t * pCoeffs, + q15_t * pState, + int32_t * pTapDelay, + uint16_t maxDelay, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q7 sparse FIR filter. + * @param[in] S points to an instance of the Q7 sparse FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] pScratchIn points to a temporary buffer of size blockSize. + * @param[in] pScratchOut points to a temporary buffer of size blockSize. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_sparse_q7( + arm_fir_sparse_instance_q7 * S, + q7_t * pSrc, + q7_t * pDst, + q7_t * pScratchIn, + q31_t * pScratchOut, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q7 sparse FIR filter. + * @param[in,out] S points to an instance of the Q7 sparse FIR structure. + * @param[in] numTaps number of nonzero coefficients in the filter. + * @param[in] pCoeffs points to the array of filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] pTapDelay points to the array of offset times. + * @param[in] maxDelay maximum offset time supported. + * @param[in] blockSize number of samples that will be processed per block. + */ + void arm_fir_sparse_init_q7( + arm_fir_sparse_instance_q7 * S, + uint16_t numTaps, + q7_t * pCoeffs, + q7_t * pState, + int32_t * pTapDelay, + uint16_t maxDelay, + uint32_t blockSize); + + + /** + * @brief Floating-point sin_cos function. + * @param[in] theta input value in degrees + * @param[out] pSinVal points to the processed sine output. + * @param[out] pCosVal points to the processed cos output. + */ + void arm_sin_cos_f32( + float32_t theta, + float32_t * pSinVal, + float32_t * pCosVal); + + + /** + * @brief Q31 sin_cos function. + * @param[in] theta scaled input value in degrees + * @param[out] pSinVal points to the processed sine output. + * @param[out] pCosVal points to the processed cosine output. + */ + void arm_sin_cos_q31( + q31_t theta, + q31_t * pSinVal, + q31_t * pCosVal); + + + /** + * @brief Floating-point complex conjugate. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_conj_f32( + float32_t * pSrc, + float32_t * pDst, + uint32_t numSamples); + + /** + * @brief Q31 complex conjugate. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_conj_q31( + q31_t * pSrc, + q31_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q15 complex conjugate. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_conj_q15( + q15_t * pSrc, + q15_t * pDst, + uint32_t numSamples); + + + /** + * @brief Floating-point complex magnitude squared + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_squared_f32( + float32_t * pSrc, + float32_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q31 complex magnitude squared + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_squared_q31( + q31_t * pSrc, + q31_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q15 complex magnitude squared + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_squared_q15( + q15_t * pSrc, + q15_t * pDst, + uint32_t numSamples); + + + /** + * @ingroup groupController + */ + + /** + * @defgroup PID PID Motor Control + * + * A Proportional Integral Derivative (PID) controller is a generic feedback control + * loop mechanism widely used in industrial control systems. + * A PID controller is the most commonly used type of feedback controller. + * + * This set of functions implements (PID) controllers + * for Q15, Q31, and floating-point data types. The functions operate on a single sample + * of data and each call to the function returns a single processed value. + * S points to an instance of the PID control data structure. in + * is the input sample value. The functions return the output value. + * + * \par Algorithm: + *
+   *    y[n] = y[n-1] + A0 * x[n] + A1 * x[n-1] + A2 * x[n-2]
+   *    A0 = Kp + Ki + Kd
+   *    A1 = (-Kp ) - (2 * Kd )
+   *    A2 = Kd  
+ * + * \par + * where \c Kp is proportional constant, \c Ki is Integral constant and \c Kd is Derivative constant + * + * \par + * \image html PID.gif "Proportional Integral Derivative Controller" + * + * \par + * The PID controller calculates an "error" value as the difference between + * the measured output and the reference input. + * The controller attempts to minimize the error by adjusting the process control inputs. + * The proportional value determines the reaction to the current error, + * the integral value determines the reaction based on the sum of recent errors, + * and the derivative value determines the reaction based on the rate at which the error has been changing. + * + * \par Instance Structure + * The Gains A0, A1, A2 and state variables for a PID controller are stored together in an instance data structure. + * A separate instance structure must be defined for each PID Controller. + * There are separate instance structure declarations for each of the 3 supported data types. + * + * \par Reset Functions + * There is also an associated reset function for each data type which clears the state array. + * + * \par Initialization Functions + * There is also an associated initialization function for each data type. + * The initialization function performs the following operations: + * - Initializes the Gains A0, A1, A2 from Kp,Ki, Kd gains. + * - Zeros out the values in the state buffer. + * + * \par + * Instance structure cannot be placed into a const data section and it is recommended to use the initialization function. + * + * \par Fixed-Point Behavior + * Care must be taken when using the fixed-point versions of the PID Controller functions. + * In particular, the overflow and saturation behavior of the accumulator used in each function must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ + + /** + * @addtogroup PID + * @{ + */ + + /** + * @brief Process function for the floating-point PID Control. + * @param[in,out] S is an instance of the floating-point PID Control structure + * @param[in] in input sample to process + * @return out processed output sample. + */ + static __INLINE float32_t arm_pid_f32( + arm_pid_instance_f32 * S, + float32_t in) + { + float32_t out; + + /* y[n] = y[n-1] + A0 * x[n] + A1 * x[n-1] + A2 * x[n-2] */ + out = (S->A0 * in) + + (S->A1 * S->state[0]) + (S->A2 * S->state[1]) + (S->state[2]); + + /* Update state */ + S->state[1] = S->state[0]; + S->state[0] = in; + S->state[2] = out; + + /* return to application */ + return (out); + + } + + /** + * @brief Process function for the Q31 PID Control. + * @param[in,out] S points to an instance of the Q31 PID Control structure + * @param[in] in input sample to process + * @return out processed output sample. + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using an internal 64-bit accumulator. + * The accumulator has a 2.62 format and maintains full precision of the intermediate multiplication results but provides only a single guard bit. + * Thus, if the accumulator result overflows it wraps around rather than clip. + * In order to avoid overflows completely the input signal must be scaled down by 2 bits as there are four additions. + * After all multiply-accumulates are performed, the 2.62 accumulator is truncated to 1.32 format and then saturated to 1.31 format. + */ + static __INLINE q31_t arm_pid_q31( + arm_pid_instance_q31 * S, + q31_t in) + { + q63_t acc; + q31_t out; + + /* acc = A0 * x[n] */ + acc = (q63_t) S->A0 * in; + + /* acc += A1 * x[n-1] */ + acc += (q63_t) S->A1 * S->state[0]; + + /* acc += A2 * x[n-2] */ + acc += (q63_t) S->A2 * S->state[1]; + + /* convert output to 1.31 format to add y[n-1] */ + out = (q31_t) (acc >> 31u); + + /* out += y[n-1] */ + out += S->state[2]; + + /* Update state */ + S->state[1] = S->state[0]; + S->state[0] = in; + S->state[2] = out; + + /* return to application */ + return (out); + } + + + /** + * @brief Process function for the Q15 PID Control. + * @param[in,out] S points to an instance of the Q15 PID Control structure + * @param[in] in input sample to process + * @return out processed output sample. + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using a 64-bit internal accumulator. + * Both Gains and state variables are represented in 1.15 format and multiplications yield a 2.30 result. + * The 2.30 intermediate results are accumulated in a 64-bit accumulator in 34.30 format. + * There is no risk of internal overflow with this approach and the full precision of intermediate multiplications is preserved. + * After all additions have been performed, the accumulator is truncated to 34.15 format by discarding low 15 bits. + * Lastly, the accumulator is saturated to yield a result in 1.15 format. + */ + static __INLINE q15_t arm_pid_q15( + arm_pid_instance_q15 * S, + q15_t in) + { + q63_t acc; + q15_t out; + +#ifndef ARM_MATH_CM0_FAMILY + __SIMD32_TYPE *vstate; + + /* Implementation of PID controller */ + + /* acc = A0 * x[n] */ + acc = (q31_t) __SMUAD((uint32_t)S->A0, (uint32_t)in); + + /* acc += A1 * x[n-1] + A2 * x[n-2] */ + vstate = __SIMD32_CONST(S->state); + acc = (q63_t)__SMLALD((uint32_t)S->A1, (uint32_t)*vstate, (uint64_t)acc); +#else + /* acc = A0 * x[n] */ + acc = ((q31_t) S->A0) * in; + + /* acc += A1 * x[n-1] + A2 * x[n-2] */ + acc += (q31_t) S->A1 * S->state[0]; + acc += (q31_t) S->A2 * S->state[1]; +#endif + + /* acc += y[n-1] */ + acc += (q31_t) S->state[2] << 15; + + /* saturate the output */ + out = (q15_t) (__SSAT((acc >> 15), 16)); + + /* Update state */ + S->state[1] = S->state[0]; + S->state[0] = in; + S->state[2] = out; + + /* return to application */ + return (out); + } + + /** + * @} end of PID group + */ + + + /** + * @brief Floating-point matrix inverse. + * @param[in] src points to the instance of the input floating-point matrix structure. + * @param[out] dst points to the instance of the output floating-point matrix structure. + * @return The function returns ARM_MATH_SIZE_MISMATCH, if the dimensions do not match. + * If the input matrix is singular (does not have an inverse), then the algorithm terminates and returns error status ARM_MATH_SINGULAR. + */ + arm_status arm_mat_inverse_f32( + const arm_matrix_instance_f32 * src, + arm_matrix_instance_f32 * dst); + + + /** + * @brief Floating-point matrix inverse. + * @param[in] src points to the instance of the input floating-point matrix structure. + * @param[out] dst points to the instance of the output floating-point matrix structure. + * @return The function returns ARM_MATH_SIZE_MISMATCH, if the dimensions do not match. + * If the input matrix is singular (does not have an inverse), then the algorithm terminates and returns error status ARM_MATH_SINGULAR. + */ + arm_status arm_mat_inverse_f64( + const arm_matrix_instance_f64 * src, + arm_matrix_instance_f64 * dst); + + + + /** + * @ingroup groupController + */ + + /** + * @defgroup clarke Vector Clarke Transform + * Forward Clarke transform converts the instantaneous stator phases into a two-coordinate time invariant vector. + * Generally the Clarke transform uses three-phase currents Ia, Ib and Ic to calculate currents + * in the two-phase orthogonal stator axis Ialpha and Ibeta. + * When Ialpha is superposed with Ia as shown in the figure below + * \image html clarke.gif Stator current space vector and its components in (a,b). + * and Ia + Ib + Ic = 0, in this condition Ialpha and Ibeta + * can be calculated using only Ia and Ib. + * + * The function operates on a single sample of data and each call to the function returns the processed output. + * The library provides separate functions for Q31 and floating-point data types. + * \par Algorithm + * \image html clarkeFormula.gif + * where Ia and Ib are the instantaneous stator phases and + * pIalpha and pIbeta are the two coordinates of time invariant vector. + * \par Fixed-Point Behavior + * Care must be taken when using the Q31 version of the Clarke transform. + * In particular, the overflow and saturation behavior of the accumulator used must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ + + /** + * @addtogroup clarke + * @{ + */ + + /** + * + * @brief Floating-point Clarke transform + * @param[in] Ia input three-phase coordinate a + * @param[in] Ib input three-phase coordinate b + * @param[out] pIalpha points to output two-phase orthogonal vector axis alpha + * @param[out] pIbeta points to output two-phase orthogonal vector axis beta + */ + static __INLINE void arm_clarke_f32( + float32_t Ia, + float32_t Ib, + float32_t * pIalpha, + float32_t * pIbeta) + { + /* Calculate pIalpha using the equation, pIalpha = Ia */ + *pIalpha = Ia; + + /* Calculate pIbeta using the equation, pIbeta = (1/sqrt(3)) * Ia + (2/sqrt(3)) * Ib */ + *pIbeta = ((float32_t) 0.57735026919 * Ia + (float32_t) 1.15470053838 * Ib); + } + + + /** + * @brief Clarke transform for Q31 version + * @param[in] Ia input three-phase coordinate a + * @param[in] Ib input three-phase coordinate b + * @param[out] pIalpha points to output two-phase orthogonal vector axis alpha + * @param[out] pIbeta points to output two-phase orthogonal vector axis beta + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using an internal 32-bit accumulator. + * The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format. + * There is saturation on the addition, hence there is no risk of overflow. + */ + static __INLINE void arm_clarke_q31( + q31_t Ia, + q31_t Ib, + q31_t * pIalpha, + q31_t * pIbeta) + { + q31_t product1, product2; /* Temporary variables used to store intermediate results */ + + /* Calculating pIalpha from Ia by equation pIalpha = Ia */ + *pIalpha = Ia; + + /* Intermediate product is calculated by (1/(sqrt(3)) * Ia) */ + product1 = (q31_t) (((q63_t) Ia * 0x24F34E8B) >> 30); + + /* Intermediate product is calculated by (2/sqrt(3) * Ib) */ + product2 = (q31_t) (((q63_t) Ib * 0x49E69D16) >> 30); + + /* pIbeta is calculated by adding the intermediate products */ + *pIbeta = __QADD(product1, product2); + } + + /** + * @} end of clarke group + */ + + /** + * @brief Converts the elements of the Q7 vector to Q31 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_q7_to_q31( + q7_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + + /** + * @ingroup groupController + */ + + /** + * @defgroup inv_clarke Vector Inverse Clarke Transform + * Inverse Clarke transform converts the two-coordinate time invariant vector into instantaneous stator phases. + * + * The function operates on a single sample of data and each call to the function returns the processed output. + * The library provides separate functions for Q31 and floating-point data types. + * \par Algorithm + * \image html clarkeInvFormula.gif + * where pIa and pIb are the instantaneous stator phases and + * Ialpha and Ibeta are the two coordinates of time invariant vector. + * \par Fixed-Point Behavior + * Care must be taken when using the Q31 version of the Clarke transform. + * In particular, the overflow and saturation behavior of the accumulator used must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ + + /** + * @addtogroup inv_clarke + * @{ + */ + + /** + * @brief Floating-point Inverse Clarke transform + * @param[in] Ialpha input two-phase orthogonal vector axis alpha + * @param[in] Ibeta input two-phase orthogonal vector axis beta + * @param[out] pIa points to output three-phase coordinate a + * @param[out] pIb points to output three-phase coordinate b + */ + static __INLINE void arm_inv_clarke_f32( + float32_t Ialpha, + float32_t Ibeta, + float32_t * pIa, + float32_t * pIb) + { + /* Calculating pIa from Ialpha by equation pIa = Ialpha */ + *pIa = Ialpha; + + /* Calculating pIb from Ialpha and Ibeta by equation pIb = -(1/2) * Ialpha + (sqrt(3)/2) * Ibeta */ + *pIb = -0.5f * Ialpha + 0.8660254039f * Ibeta; + } + + + /** + * @brief Inverse Clarke transform for Q31 version + * @param[in] Ialpha input two-phase orthogonal vector axis alpha + * @param[in] Ibeta input two-phase orthogonal vector axis beta + * @param[out] pIa points to output three-phase coordinate a + * @param[out] pIb points to output three-phase coordinate b + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using an internal 32-bit accumulator. + * The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format. + * There is saturation on the subtraction, hence there is no risk of overflow. + */ + static __INLINE void arm_inv_clarke_q31( + q31_t Ialpha, + q31_t Ibeta, + q31_t * pIa, + q31_t * pIb) + { + q31_t product1, product2; /* Temporary variables used to store intermediate results */ + + /* Calculating pIa from Ialpha by equation pIa = Ialpha */ + *pIa = Ialpha; + + /* Intermediate product is calculated by (1/(2*sqrt(3)) * Ia) */ + product1 = (q31_t) (((q63_t) (Ialpha) * (0x40000000)) >> 31); + + /* Intermediate product is calculated by (1/sqrt(3) * pIb) */ + product2 = (q31_t) (((q63_t) (Ibeta) * (0x6ED9EBA1)) >> 31); + + /* pIb is calculated by subtracting the products */ + *pIb = __QSUB(product2, product1); + } + + /** + * @} end of inv_clarke group + */ + + /** + * @brief Converts the elements of the Q7 vector to Q15 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_q7_to_q15( + q7_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + + /** + * @ingroup groupController + */ + + /** + * @defgroup park Vector Park Transform + * + * Forward Park transform converts the input two-coordinate vector to flux and torque components. + * The Park transform can be used to realize the transformation of the Ialpha and the Ibeta currents + * from the stationary to the moving reference frame and control the spatial relationship between + * the stator vector current and rotor flux vector. + * If we consider the d axis aligned with the rotor flux, the diagram below shows the + * current vector and the relationship from the two reference frames: + * \image html park.gif "Stator current space vector and its component in (a,b) and in the d,q rotating reference frame" + * + * The function operates on a single sample of data and each call to the function returns the processed output. + * The library provides separate functions for Q31 and floating-point data types. + * \par Algorithm + * \image html parkFormula.gif + * where Ialpha and Ibeta are the stator vector components, + * pId and pIq are rotor vector components and cosVal and sinVal are the + * cosine and sine values of theta (rotor flux position). + * \par Fixed-Point Behavior + * Care must be taken when using the Q31 version of the Park transform. + * In particular, the overflow and saturation behavior of the accumulator used must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ + + /** + * @addtogroup park + * @{ + */ + + /** + * @brief Floating-point Park transform + * @param[in] Ialpha input two-phase vector coordinate alpha + * @param[in] Ibeta input two-phase vector coordinate beta + * @param[out] pId points to output rotor reference frame d + * @param[out] pIq points to output rotor reference frame q + * @param[in] sinVal sine value of rotation angle theta + * @param[in] cosVal cosine value of rotation angle theta + * + * The function implements the forward Park transform. + * + */ + static __INLINE void arm_park_f32( + float32_t Ialpha, + float32_t Ibeta, + float32_t * pId, + float32_t * pIq, + float32_t sinVal, + float32_t cosVal) + { + /* Calculate pId using the equation, pId = Ialpha * cosVal + Ibeta * sinVal */ + *pId = Ialpha * cosVal + Ibeta * sinVal; + + /* Calculate pIq using the equation, pIq = - Ialpha * sinVal + Ibeta * cosVal */ + *pIq = -Ialpha * sinVal + Ibeta * cosVal; + } + + + /** + * @brief Park transform for Q31 version + * @param[in] Ialpha input two-phase vector coordinate alpha + * @param[in] Ibeta input two-phase vector coordinate beta + * @param[out] pId points to output rotor reference frame d + * @param[out] pIq points to output rotor reference frame q + * @param[in] sinVal sine value of rotation angle theta + * @param[in] cosVal cosine value of rotation angle theta + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using an internal 32-bit accumulator. + * The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format. + * There is saturation on the addition and subtraction, hence there is no risk of overflow. + */ + static __INLINE void arm_park_q31( + q31_t Ialpha, + q31_t Ibeta, + q31_t * pId, + q31_t * pIq, + q31_t sinVal, + q31_t cosVal) + { + q31_t product1, product2; /* Temporary variables used to store intermediate results */ + q31_t product3, product4; /* Temporary variables used to store intermediate results */ + + /* Intermediate product is calculated by (Ialpha * cosVal) */ + product1 = (q31_t) (((q63_t) (Ialpha) * (cosVal)) >> 31); + + /* Intermediate product is calculated by (Ibeta * sinVal) */ + product2 = (q31_t) (((q63_t) (Ibeta) * (sinVal)) >> 31); + + + /* Intermediate product is calculated by (Ialpha * sinVal) */ + product3 = (q31_t) (((q63_t) (Ialpha) * (sinVal)) >> 31); + + /* Intermediate product is calculated by (Ibeta * cosVal) */ + product4 = (q31_t) (((q63_t) (Ibeta) * (cosVal)) >> 31); + + /* Calculate pId by adding the two intermediate products 1 and 2 */ + *pId = __QADD(product1, product2); + + /* Calculate pIq by subtracting the two intermediate products 3 from 4 */ + *pIq = __QSUB(product4, product3); + } + + /** + * @} end of park group + */ + + /** + * @brief Converts the elements of the Q7 vector to floating-point vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q7_to_float( + q7_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @ingroup groupController + */ + + /** + * @defgroup inv_park Vector Inverse Park transform + * Inverse Park transform converts the input flux and torque components to two-coordinate vector. + * + * The function operates on a single sample of data and each call to the function returns the processed output. + * The library provides separate functions for Q31 and floating-point data types. + * \par Algorithm + * \image html parkInvFormula.gif + * where pIalpha and pIbeta are the stator vector components, + * Id and Iq are rotor vector components and cosVal and sinVal are the + * cosine and sine values of theta (rotor flux position). + * \par Fixed-Point Behavior + * Care must be taken when using the Q31 version of the Park transform. + * In particular, the overflow and saturation behavior of the accumulator used must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ + + /** + * @addtogroup inv_park + * @{ + */ + + /** + * @brief Floating-point Inverse Park transform + * @param[in] Id input coordinate of rotor reference frame d + * @param[in] Iq input coordinate of rotor reference frame q + * @param[out] pIalpha points to output two-phase orthogonal vector axis alpha + * @param[out] pIbeta points to output two-phase orthogonal vector axis beta + * @param[in] sinVal sine value of rotation angle theta + * @param[in] cosVal cosine value of rotation angle theta + */ + static __INLINE void arm_inv_park_f32( + float32_t Id, + float32_t Iq, + float32_t * pIalpha, + float32_t * pIbeta, + float32_t sinVal, + float32_t cosVal) + { + /* Calculate pIalpha using the equation, pIalpha = Id * cosVal - Iq * sinVal */ + *pIalpha = Id * cosVal - Iq * sinVal; + + /* Calculate pIbeta using the equation, pIbeta = Id * sinVal + Iq * cosVal */ + *pIbeta = Id * sinVal + Iq * cosVal; + } + + + /** + * @brief Inverse Park transform for Q31 version + * @param[in] Id input coordinate of rotor reference frame d + * @param[in] Iq input coordinate of rotor reference frame q + * @param[out] pIalpha points to output two-phase orthogonal vector axis alpha + * @param[out] pIbeta points to output two-phase orthogonal vector axis beta + * @param[in] sinVal sine value of rotation angle theta + * @param[in] cosVal cosine value of rotation angle theta + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using an internal 32-bit accumulator. + * The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format. + * There is saturation on the addition, hence there is no risk of overflow. + */ + static __INLINE void arm_inv_park_q31( + q31_t Id, + q31_t Iq, + q31_t * pIalpha, + q31_t * pIbeta, + q31_t sinVal, + q31_t cosVal) + { + q31_t product1, product2; /* Temporary variables used to store intermediate results */ + q31_t product3, product4; /* Temporary variables used to store intermediate results */ + + /* Intermediate product is calculated by (Id * cosVal) */ + product1 = (q31_t) (((q63_t) (Id) * (cosVal)) >> 31); + + /* Intermediate product is calculated by (Iq * sinVal) */ + product2 = (q31_t) (((q63_t) (Iq) * (sinVal)) >> 31); + + + /* Intermediate product is calculated by (Id * sinVal) */ + product3 = (q31_t) (((q63_t) (Id) * (sinVal)) >> 31); + + /* Intermediate product is calculated by (Iq * cosVal) */ + product4 = (q31_t) (((q63_t) (Iq) * (cosVal)) >> 31); + + /* Calculate pIalpha by using the two intermediate products 1 and 2 */ + *pIalpha = __QSUB(product1, product2); + + /* Calculate pIbeta by using the two intermediate products 3 and 4 */ + *pIbeta = __QADD(product4, product3); + } + + /** + * @} end of Inverse park group + */ + + + /** + * @brief Converts the elements of the Q31 vector to floating-point vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q31_to_float( + q31_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + /** + * @ingroup groupInterpolation + */ + + /** + * @defgroup LinearInterpolate Linear Interpolation + * + * Linear interpolation is a method of curve fitting using linear polynomials. + * Linear interpolation works by effectively drawing a straight line between two neighboring samples and returning the appropriate point along that line + * + * \par + * \image html LinearInterp.gif "Linear interpolation" + * + * \par + * A Linear Interpolate function calculates an output value(y), for the input(x) + * using linear interpolation of the input values x0, x1( nearest input values) and the output values y0 and y1(nearest output values) + * + * \par Algorithm: + *
+   *       y = y0 + (x - x0) * ((y1 - y0)/(x1-x0))
+   *       where x0, x1 are nearest values of input x
+   *             y0, y1 are nearest values to output y
+   * 
+ * + * \par + * This set of functions implements Linear interpolation process + * for Q7, Q15, Q31, and floating-point data types. The functions operate on a single + * sample of data and each call to the function returns a single processed value. + * S points to an instance of the Linear Interpolate function data structure. + * x is the input sample value. The functions returns the output value. + * + * \par + * if x is outside of the table boundary, Linear interpolation returns first value of the table + * if x is below input range and returns last value of table if x is above range. + */ + + /** + * @addtogroup LinearInterpolate + * @{ + */ + + /** + * @brief Process function for the floating-point Linear Interpolation Function. + * @param[in,out] S is an instance of the floating-point Linear Interpolation structure + * @param[in] x input sample to process + * @return y processed output sample. + * + */ + static __INLINE float32_t arm_linear_interp_f32( + arm_linear_interp_instance_f32 * S, + float32_t x) + { + float32_t y; + float32_t x0, x1; /* Nearest input values */ + float32_t y0, y1; /* Nearest output values */ + float32_t xSpacing = S->xSpacing; /* spacing between input values */ + int32_t i; /* Index variable */ + float32_t *pYData = S->pYData; /* pointer to output table */ + + /* Calculation of index */ + i = (int32_t) ((x - S->x1) / xSpacing); + + if(i < 0) + { + /* Iniatilize output for below specified range as least output value of table */ + y = pYData[0]; + } + else if((uint32_t)i >= S->nValues) + { + /* Iniatilize output for above specified range as last output value of table */ + y = pYData[S->nValues - 1]; + } + else + { + /* Calculation of nearest input values */ + x0 = S->x1 + i * xSpacing; + x1 = S->x1 + (i + 1) * xSpacing; + + /* Read of nearest output values */ + y0 = pYData[i]; + y1 = pYData[i + 1]; + + /* Calculation of output */ + y = y0 + (x - x0) * ((y1 - y0) / (x1 - x0)); + + } + + /* returns output value */ + return (y); + } + + + /** + * + * @brief Process function for the Q31 Linear Interpolation Function. + * @param[in] pYData pointer to Q31 Linear Interpolation table + * @param[in] x input sample to process + * @param[in] nValues number of table values + * @return y processed output sample. + * + * \par + * Input sample x is in 12.20 format which contains 12 bits for table index and 20 bits for fractional part. + * This function can support maximum of table size 2^12. + * + */ + static __INLINE q31_t arm_linear_interp_q31( + q31_t * pYData, + q31_t x, + uint32_t nValues) + { + q31_t y; /* output */ + q31_t y0, y1; /* Nearest output values */ + q31_t fract; /* fractional part */ + int32_t index; /* Index to read nearest output values */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + index = ((x & (q31_t)0xFFF00000) >> 20); + + if(index >= (int32_t)(nValues - 1)) + { + return (pYData[nValues - 1]); + } + else if(index < 0) + { + return (pYData[0]); + } + else + { + /* 20 bits for the fractional part */ + /* shift left by 11 to keep fract in 1.31 format */ + fract = (x & 0x000FFFFF) << 11; + + /* Read two nearest output values from the index in 1.31(q31) format */ + y0 = pYData[index]; + y1 = pYData[index + 1]; + + /* Calculation of y0 * (1-fract) and y is in 2.30 format */ + y = ((q31_t) ((q63_t) y0 * (0x7FFFFFFF - fract) >> 32)); + + /* Calculation of y0 * (1-fract) + y1 *fract and y is in 2.30 format */ + y += ((q31_t) (((q63_t) y1 * fract) >> 32)); + + /* Convert y to 1.31 format */ + return (y << 1u); + } + } + + + /** + * + * @brief Process function for the Q15 Linear Interpolation Function. + * @param[in] pYData pointer to Q15 Linear Interpolation table + * @param[in] x input sample to process + * @param[in] nValues number of table values + * @return y processed output sample. + * + * \par + * Input sample x is in 12.20 format which contains 12 bits for table index and 20 bits for fractional part. + * This function can support maximum of table size 2^12. + * + */ + static __INLINE q15_t arm_linear_interp_q15( + q15_t * pYData, + q31_t x, + uint32_t nValues) + { + q63_t y; /* output */ + q15_t y0, y1; /* Nearest output values */ + q31_t fract; /* fractional part */ + int32_t index; /* Index to read nearest output values */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + index = ((x & (int32_t)0xFFF00000) >> 20); + + if(index >= (int32_t)(nValues - 1)) + { + return (pYData[nValues - 1]); + } + else if(index < 0) + { + return (pYData[0]); + } + else + { + /* 20 bits for the fractional part */ + /* fract is in 12.20 format */ + fract = (x & 0x000FFFFF); + + /* Read two nearest output values from the index */ + y0 = pYData[index]; + y1 = pYData[index + 1]; + + /* Calculation of y0 * (1-fract) and y is in 13.35 format */ + y = ((q63_t) y0 * (0xFFFFF - fract)); + + /* Calculation of (y0 * (1-fract) + y1 * fract) and y is in 13.35 format */ + y += ((q63_t) y1 * (fract)); + + /* convert y to 1.15 format */ + return (q15_t) (y >> 20); + } + } + + + /** + * + * @brief Process function for the Q7 Linear Interpolation Function. + * @param[in] pYData pointer to Q7 Linear Interpolation table + * @param[in] x input sample to process + * @param[in] nValues number of table values + * @return y processed output sample. + * + * \par + * Input sample x is in 12.20 format which contains 12 bits for table index and 20 bits for fractional part. + * This function can support maximum of table size 2^12. + */ + static __INLINE q7_t arm_linear_interp_q7( + q7_t * pYData, + q31_t x, + uint32_t nValues) + { + q31_t y; /* output */ + q7_t y0, y1; /* Nearest output values */ + q31_t fract; /* fractional part */ + uint32_t index; /* Index to read nearest output values */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + if (x < 0) + { + return (pYData[0]); + } + index = (x >> 20) & 0xfff; + + if(index >= (nValues - 1)) + { + return (pYData[nValues - 1]); + } + else + { + /* 20 bits for the fractional part */ + /* fract is in 12.20 format */ + fract = (x & 0x000FFFFF); + + /* Read two nearest output values from the index and are in 1.7(q7) format */ + y0 = pYData[index]; + y1 = pYData[index + 1]; + + /* Calculation of y0 * (1-fract ) and y is in 13.27(q27) format */ + y = ((y0 * (0xFFFFF - fract))); + + /* Calculation of y1 * fract + y0 * (1-fract) and y is in 13.27(q27) format */ + y += (y1 * fract); + + /* convert y to 1.7(q7) format */ + return (q7_t) (y >> 20); + } + } + + /** + * @} end of LinearInterpolate group + */ + + /** + * @brief Fast approximation to the trigonometric sine function for floating-point data. + * @param[in] x input value in radians. + * @return sin(x). + */ + float32_t arm_sin_f32( + float32_t x); + + + /** + * @brief Fast approximation to the trigonometric sine function for Q31 data. + * @param[in] x Scaled input value in radians. + * @return sin(x). + */ + q31_t arm_sin_q31( + q31_t x); + + + /** + * @brief Fast approximation to the trigonometric sine function for Q15 data. + * @param[in] x Scaled input value in radians. + * @return sin(x). + */ + q15_t arm_sin_q15( + q15_t x); + + + /** + * @brief Fast approximation to the trigonometric cosine function for floating-point data. + * @param[in] x input value in radians. + * @return cos(x). + */ + float32_t arm_cos_f32( + float32_t x); + + + /** + * @brief Fast approximation to the trigonometric cosine function for Q31 data. + * @param[in] x Scaled input value in radians. + * @return cos(x). + */ + q31_t arm_cos_q31( + q31_t x); + + + /** + * @brief Fast approximation to the trigonometric cosine function for Q15 data. + * @param[in] x Scaled input value in radians. + * @return cos(x). + */ + q15_t arm_cos_q15( + q15_t x); + + + /** + * @ingroup groupFastMath + */ + + + /** + * @defgroup SQRT Square Root + * + * Computes the square root of a number. + * There are separate functions for Q15, Q31, and floating-point data types. + * The square root function is computed using the Newton-Raphson algorithm. + * This is an iterative algorithm of the form: + *
+   *      x1 = x0 - f(x0)/f'(x0)
+   * 
+ * where x1 is the current estimate, + * x0 is the previous estimate, and + * f'(x0) is the derivative of f() evaluated at x0. + * For the square root function, the algorithm reduces to: + *
+   *     x0 = in/2                         [initial guess]
+   *     x1 = 1/2 * ( x0 + in / x0)        [each iteration]
+   * 
+ */ + + + /** + * @addtogroup SQRT + * @{ + */ + + /** + * @brief Floating-point square root function. + * @param[in] in input value. + * @param[out] pOut square root of input value. + * @return The function returns ARM_MATH_SUCCESS if input value is positive value or ARM_MATH_ARGUMENT_ERROR if + * in is negative value and returns zero output for negative values. + */ + static __INLINE arm_status arm_sqrt_f32( + float32_t in, + float32_t * pOut) + { + if(in >= 0.0f) + { + +#if (__FPU_USED == 1) && defined ( __CC_ARM ) + *pOut = __sqrtf(in); +#elif (__FPU_USED == 1) && (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)) + *pOut = __builtin_sqrtf(in); +#elif (__FPU_USED == 1) && defined(__GNUC__) + *pOut = __builtin_sqrtf(in); +#elif (__FPU_USED == 1) && defined ( __ICCARM__ ) && (__VER__ >= 6040000) + __ASM("VSQRT.F32 %0,%1" : "=t"(*pOut) : "t"(in)); +#else + *pOut = sqrtf(in); +#endif + + return (ARM_MATH_SUCCESS); + } + else + { + *pOut = 0.0f; + return (ARM_MATH_ARGUMENT_ERROR); + } + } + + + /** + * @brief Q31 square root function. + * @param[in] in input value. The range of the input value is [0 +1) or 0x00000000 to 0x7FFFFFFF. + * @param[out] pOut square root of input value. + * @return The function returns ARM_MATH_SUCCESS if input value is positive value or ARM_MATH_ARGUMENT_ERROR if + * in is negative value and returns zero output for negative values. + */ + arm_status arm_sqrt_q31( + q31_t in, + q31_t * pOut); + + + /** + * @brief Q15 square root function. + * @param[in] in input value. The range of the input value is [0 +1) or 0x0000 to 0x7FFF. + * @param[out] pOut square root of input value. + * @return The function returns ARM_MATH_SUCCESS if input value is positive value or ARM_MATH_ARGUMENT_ERROR if + * in is negative value and returns zero output for negative values. + */ + arm_status arm_sqrt_q15( + q15_t in, + q15_t * pOut); + + /** + * @} end of SQRT group + */ + + + /** + * @brief floating-point Circular write function. + */ + static __INLINE void arm_circularWrite_f32( + int32_t * circBuffer, + int32_t L, + uint16_t * writeOffset, + int32_t bufferInc, + const int32_t * src, + int32_t srcInc, + uint32_t blockSize) + { + uint32_t i = 0u; + int32_t wOffset; + + /* Copy the value of Index pointer that points + * to the current location where the input samples to be copied */ + wOffset = *writeOffset; + + /* Loop over the blockSize */ + i = blockSize; + + while(i > 0u) + { + /* copy the input sample to the circular buffer */ + circBuffer[wOffset] = *src; + + /* Update the input pointer */ + src += srcInc; + + /* Circularly update wOffset. Watch out for positive and negative value */ + wOffset += bufferInc; + if(wOffset >= L) + wOffset -= L; + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *writeOffset = (uint16_t)wOffset; + } + + + + /** + * @brief floating-point Circular Read function. + */ + static __INLINE void arm_circularRead_f32( + int32_t * circBuffer, + int32_t L, + int32_t * readOffset, + int32_t bufferInc, + int32_t * dst, + int32_t * dst_base, + int32_t dst_length, + int32_t dstInc, + uint32_t blockSize) + { + uint32_t i = 0u; + int32_t rOffset, dst_end; + + /* Copy the value of Index pointer that points + * to the current location from where the input samples to be read */ + rOffset = *readOffset; + dst_end = (int32_t) (dst_base + dst_length); + + /* Loop over the blockSize */ + i = blockSize; + + while(i > 0u) + { + /* copy the sample from the circular buffer to the destination buffer */ + *dst = circBuffer[rOffset]; + + /* Update the input pointer */ + dst += dstInc; + + if(dst == (int32_t *) dst_end) + { + dst = dst_base; + } + + /* Circularly update rOffset. Watch out for positive and negative value */ + rOffset += bufferInc; + + if(rOffset >= L) + { + rOffset -= L; + } + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *readOffset = rOffset; + } + + + /** + * @brief Q15 Circular write function. + */ + static __INLINE void arm_circularWrite_q15( + q15_t * circBuffer, + int32_t L, + uint16_t * writeOffset, + int32_t bufferInc, + const q15_t * src, + int32_t srcInc, + uint32_t blockSize) + { + uint32_t i = 0u; + int32_t wOffset; + + /* Copy the value of Index pointer that points + * to the current location where the input samples to be copied */ + wOffset = *writeOffset; + + /* Loop over the blockSize */ + i = blockSize; + + while(i > 0u) + { + /* copy the input sample to the circular buffer */ + circBuffer[wOffset] = *src; + + /* Update the input pointer */ + src += srcInc; + + /* Circularly update wOffset. Watch out for positive and negative value */ + wOffset += bufferInc; + if(wOffset >= L) + wOffset -= L; + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *writeOffset = (uint16_t)wOffset; + } + + + /** + * @brief Q15 Circular Read function. + */ + static __INLINE void arm_circularRead_q15( + q15_t * circBuffer, + int32_t L, + int32_t * readOffset, + int32_t bufferInc, + q15_t * dst, + q15_t * dst_base, + int32_t dst_length, + int32_t dstInc, + uint32_t blockSize) + { + uint32_t i = 0; + int32_t rOffset, dst_end; + + /* Copy the value of Index pointer that points + * to the current location from where the input samples to be read */ + rOffset = *readOffset; + + dst_end = (int32_t) (dst_base + dst_length); + + /* Loop over the blockSize */ + i = blockSize; + + while(i > 0u) + { + /* copy the sample from the circular buffer to the destination buffer */ + *dst = circBuffer[rOffset]; + + /* Update the input pointer */ + dst += dstInc; + + if(dst == (q15_t *) dst_end) + { + dst = dst_base; + } + + /* Circularly update wOffset. Watch out for positive and negative value */ + rOffset += bufferInc; + + if(rOffset >= L) + { + rOffset -= L; + } + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *readOffset = rOffset; + } + + + /** + * @brief Q7 Circular write function. + */ + static __INLINE void arm_circularWrite_q7( + q7_t * circBuffer, + int32_t L, + uint16_t * writeOffset, + int32_t bufferInc, + const q7_t * src, + int32_t srcInc, + uint32_t blockSize) + { + uint32_t i = 0u; + int32_t wOffset; + + /* Copy the value of Index pointer that points + * to the current location where the input samples to be copied */ + wOffset = *writeOffset; + + /* Loop over the blockSize */ + i = blockSize; + + while(i > 0u) + { + /* copy the input sample to the circular buffer */ + circBuffer[wOffset] = *src; + + /* Update the input pointer */ + src += srcInc; + + /* Circularly update wOffset. Watch out for positive and negative value */ + wOffset += bufferInc; + if(wOffset >= L) + wOffset -= L; + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *writeOffset = (uint16_t)wOffset; + } + + + /** + * @brief Q7 Circular Read function. + */ + static __INLINE void arm_circularRead_q7( + q7_t * circBuffer, + int32_t L, + int32_t * readOffset, + int32_t bufferInc, + q7_t * dst, + q7_t * dst_base, + int32_t dst_length, + int32_t dstInc, + uint32_t blockSize) + { + uint32_t i = 0; + int32_t rOffset, dst_end; + + /* Copy the value of Index pointer that points + * to the current location from where the input samples to be read */ + rOffset = *readOffset; + + dst_end = (int32_t) (dst_base + dst_length); + + /* Loop over the blockSize */ + i = blockSize; + + while(i > 0u) + { + /* copy the sample from the circular buffer to the destination buffer */ + *dst = circBuffer[rOffset]; + + /* Update the input pointer */ + dst += dstInc; + + if(dst == (q7_t *) dst_end) + { + dst = dst_base; + } + + /* Circularly update rOffset. Watch out for positive and negative value */ + rOffset += bufferInc; + + if(rOffset >= L) + { + rOffset -= L; + } + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *readOffset = rOffset; + } + + + /** + * @brief Sum of the squares of the elements of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_power_q31( + q31_t * pSrc, + uint32_t blockSize, + q63_t * pResult); + + + /** + * @brief Sum of the squares of the elements of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_power_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult); + + + /** + * @brief Sum of the squares of the elements of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_power_q15( + q15_t * pSrc, + uint32_t blockSize, + q63_t * pResult); + + + /** + * @brief Sum of the squares of the elements of a Q7 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_power_q7( + q7_t * pSrc, + uint32_t blockSize, + q31_t * pResult); + + + /** + * @brief Mean value of a Q7 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_mean_q7( + q7_t * pSrc, + uint32_t blockSize, + q7_t * pResult); + + + /** + * @brief Mean value of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_mean_q15( + q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult); + + + /** + * @brief Mean value of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_mean_q31( + q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult); + + + /** + * @brief Mean value of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_mean_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult); + + + /** + * @brief Variance of the elements of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_var_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult); + + + /** + * @brief Variance of the elements of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_var_q31( + q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult); + + + /** + * @brief Variance of the elements of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_var_q15( + q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult); + + + /** + * @brief Root Mean Square of the elements of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_rms_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult); + + + /** + * @brief Root Mean Square of the elements of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_rms_q31( + q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult); + + + /** + * @brief Root Mean Square of the elements of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_rms_q15( + q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult); + + + /** + * @brief Standard deviation of the elements of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_std_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult); + + + /** + * @brief Standard deviation of the elements of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_std_q31( + q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult); + + + /** + * @brief Standard deviation of the elements of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_std_q15( + q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult); + + + /** + * @brief Floating-point complex magnitude + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_f32( + float32_t * pSrc, + float32_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q31 complex magnitude + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_q31( + q31_t * pSrc, + q31_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q15 complex magnitude + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_q15( + q15_t * pSrc, + q15_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q15 complex dot product + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] numSamples number of complex samples in each vector + * @param[out] realResult real part of the result returned here + * @param[out] imagResult imaginary part of the result returned here + */ + void arm_cmplx_dot_prod_q15( + q15_t * pSrcA, + q15_t * pSrcB, + uint32_t numSamples, + q31_t * realResult, + q31_t * imagResult); + + + /** + * @brief Q31 complex dot product + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] numSamples number of complex samples in each vector + * @param[out] realResult real part of the result returned here + * @param[out] imagResult imaginary part of the result returned here + */ + void arm_cmplx_dot_prod_q31( + q31_t * pSrcA, + q31_t * pSrcB, + uint32_t numSamples, + q63_t * realResult, + q63_t * imagResult); + + + /** + * @brief Floating-point complex dot product + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] numSamples number of complex samples in each vector + * @param[out] realResult real part of the result returned here + * @param[out] imagResult imaginary part of the result returned here + */ + void arm_cmplx_dot_prod_f32( + float32_t * pSrcA, + float32_t * pSrcB, + uint32_t numSamples, + float32_t * realResult, + float32_t * imagResult); + + + /** + * @brief Q15 complex-by-real multiplication + * @param[in] pSrcCmplx points to the complex input vector + * @param[in] pSrcReal points to the real input vector + * @param[out] pCmplxDst points to the complex output vector + * @param[in] numSamples number of samples in each vector + */ + void arm_cmplx_mult_real_q15( + q15_t * pSrcCmplx, + q15_t * pSrcReal, + q15_t * pCmplxDst, + uint32_t numSamples); + + + /** + * @brief Q31 complex-by-real multiplication + * @param[in] pSrcCmplx points to the complex input vector + * @param[in] pSrcReal points to the real input vector + * @param[out] pCmplxDst points to the complex output vector + * @param[in] numSamples number of samples in each vector + */ + void arm_cmplx_mult_real_q31( + q31_t * pSrcCmplx, + q31_t * pSrcReal, + q31_t * pCmplxDst, + uint32_t numSamples); + + + /** + * @brief Floating-point complex-by-real multiplication + * @param[in] pSrcCmplx points to the complex input vector + * @param[in] pSrcReal points to the real input vector + * @param[out] pCmplxDst points to the complex output vector + * @param[in] numSamples number of samples in each vector + */ + void arm_cmplx_mult_real_f32( + float32_t * pSrcCmplx, + float32_t * pSrcReal, + float32_t * pCmplxDst, + uint32_t numSamples); + + + /** + * @brief Minimum value of a Q7 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] result is output pointer + * @param[in] index is the array index of the minimum value in the input buffer. + */ + void arm_min_q7( + q7_t * pSrc, + uint32_t blockSize, + q7_t * result, + uint32_t * index); + + + /** + * @brief Minimum value of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output pointer + * @param[in] pIndex is the array index of the minimum value in the input buffer. + */ + void arm_min_q15( + q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult, + uint32_t * pIndex); + + + /** + * @brief Minimum value of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output pointer + * @param[out] pIndex is the array index of the minimum value in the input buffer. + */ + void arm_min_q31( + q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult, + uint32_t * pIndex); + + + /** + * @brief Minimum value of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output pointer + * @param[out] pIndex is the array index of the minimum value in the input buffer. + */ + void arm_min_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult, + uint32_t * pIndex); + + +/** + * @brief Maximum value of a Q7 vector. + * @param[in] pSrc points to the input buffer + * @param[in] blockSize length of the input vector + * @param[out] pResult maximum value returned here + * @param[out] pIndex index of maximum value returned here + */ + void arm_max_q7( + q7_t * pSrc, + uint32_t blockSize, + q7_t * pResult, + uint32_t * pIndex); + + +/** + * @brief Maximum value of a Q15 vector. + * @param[in] pSrc points to the input buffer + * @param[in] blockSize length of the input vector + * @param[out] pResult maximum value returned here + * @param[out] pIndex index of maximum value returned here + */ + void arm_max_q15( + q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult, + uint32_t * pIndex); + + +/** + * @brief Maximum value of a Q31 vector. + * @param[in] pSrc points to the input buffer + * @param[in] blockSize length of the input vector + * @param[out] pResult maximum value returned here + * @param[out] pIndex index of maximum value returned here + */ + void arm_max_q31( + q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult, + uint32_t * pIndex); + + +/** + * @brief Maximum value of a floating-point vector. + * @param[in] pSrc points to the input buffer + * @param[in] blockSize length of the input vector + * @param[out] pResult maximum value returned here + * @param[out] pIndex index of maximum value returned here + */ + void arm_max_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult, + uint32_t * pIndex); + + + /** + * @brief Q15 complex-by-complex multiplication + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_mult_cmplx_q15( + q15_t * pSrcA, + q15_t * pSrcB, + q15_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q31 complex-by-complex multiplication + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_mult_cmplx_q31( + q31_t * pSrcA, + q31_t * pSrcB, + q31_t * pDst, + uint32_t numSamples); + + + /** + * @brief Floating-point complex-by-complex multiplication + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_mult_cmplx_f32( + float32_t * pSrcA, + float32_t * pSrcB, + float32_t * pDst, + uint32_t numSamples); + + + /** + * @brief Converts the elements of the floating-point vector to Q31 vector. + * @param[in] pSrc points to the floating-point input vector + * @param[out] pDst points to the Q31 output vector + * @param[in] blockSize length of the input vector + */ + void arm_float_to_q31( + float32_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the floating-point vector to Q15 vector. + * @param[in] pSrc points to the floating-point input vector + * @param[out] pDst points to the Q15 output vector + * @param[in] blockSize length of the input vector + */ + void arm_float_to_q15( + float32_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the floating-point vector to Q7 vector. + * @param[in] pSrc points to the floating-point input vector + * @param[out] pDst points to the Q7 output vector + * @param[in] blockSize length of the input vector + */ + void arm_float_to_q7( + float32_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the Q31 vector to Q15 vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q31_to_q15( + q31_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the Q31 vector to Q7 vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q31_to_q7( + q31_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the Q15 vector to floating-point vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q15_to_float( + q15_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the Q15 vector to Q31 vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q15_to_q31( + q15_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the Q15 vector to Q7 vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q15_to_q7( + q15_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @ingroup groupInterpolation + */ + + /** + * @defgroup BilinearInterpolate Bilinear Interpolation + * + * Bilinear interpolation is an extension of linear interpolation applied to a two dimensional grid. + * The underlying function f(x, y) is sampled on a regular grid and the interpolation process + * determines values between the grid points. + * Bilinear interpolation is equivalent to two step linear interpolation, first in the x-dimension and then in the y-dimension. + * Bilinear interpolation is often used in image processing to rescale images. + * The CMSIS DSP library provides bilinear interpolation functions for Q7, Q15, Q31, and floating-point data types. + * + * Algorithm + * \par + * The instance structure used by the bilinear interpolation functions describes a two dimensional data table. + * For floating-point, the instance structure is defined as: + *
+   *   typedef struct
+   *   {
+   *     uint16_t numRows;
+   *     uint16_t numCols;
+   *     float32_t *pData;
+   * } arm_bilinear_interp_instance_f32;
+   * 
+ * + * \par + * where numRows specifies the number of rows in the table; + * numCols specifies the number of columns in the table; + * and pData points to an array of size numRows*numCols values. + * The data table pTable is organized in row order and the supplied data values fall on integer indexes. + * That is, table element (x,y) is located at pTable[x + y*numCols] where x and y are integers. + * + * \par + * Let (x, y) specify the desired interpolation point. Then define: + *
+   *     XF = floor(x)
+   *     YF = floor(y)
+   * 
+ * \par + * The interpolated output point is computed as: + *
+   *  f(x, y) = f(XF, YF) * (1-(x-XF)) * (1-(y-YF))
+   *           + f(XF+1, YF) * (x-XF)*(1-(y-YF))
+   *           + f(XF, YF+1) * (1-(x-XF))*(y-YF)
+   *           + f(XF+1, YF+1) * (x-XF)*(y-YF)
+   * 
+ * Note that the coordinates (x, y) contain integer and fractional components. + * The integer components specify which portion of the table to use while the + * fractional components control the interpolation processor. + * + * \par + * if (x,y) are outside of the table boundary, Bilinear interpolation returns zero output. + */ + + /** + * @addtogroup BilinearInterpolate + * @{ + */ + + + /** + * + * @brief Floating-point bilinear interpolation. + * @param[in,out] S points to an instance of the interpolation structure. + * @param[in] X interpolation coordinate. + * @param[in] Y interpolation coordinate. + * @return out interpolated value. + */ + static __INLINE float32_t arm_bilinear_interp_f32( + const arm_bilinear_interp_instance_f32 * S, + float32_t X, + float32_t Y) + { + float32_t out; + float32_t f00, f01, f10, f11; + float32_t *pData = S->pData; + int32_t xIndex, yIndex, index; + float32_t xdiff, ydiff; + float32_t b1, b2, b3, b4; + + xIndex = (int32_t) X; + yIndex = (int32_t) Y; + + /* Care taken for table outside boundary */ + /* Returns zero output when values are outside table boundary */ + if(xIndex < 0 || xIndex > (S->numRows - 1) || yIndex < 0 || yIndex > (S->numCols - 1)) + { + return (0); + } + + /* Calculation of index for two nearest points in X-direction */ + index = (xIndex - 1) + (yIndex - 1) * S->numCols; + + + /* Read two nearest points in X-direction */ + f00 = pData[index]; + f01 = pData[index + 1]; + + /* Calculation of index for two nearest points in Y-direction */ + index = (xIndex - 1) + (yIndex) * S->numCols; + + + /* Read two nearest points in Y-direction */ + f10 = pData[index]; + f11 = pData[index + 1]; + + /* Calculation of intermediate values */ + b1 = f00; + b2 = f01 - f00; + b3 = f10 - f00; + b4 = f00 - f01 - f10 + f11; + + /* Calculation of fractional part in X */ + xdiff = X - xIndex; + + /* Calculation of fractional part in Y */ + ydiff = Y - yIndex; + + /* Calculation of bi-linear interpolated output */ + out = b1 + b2 * xdiff + b3 * ydiff + b4 * xdiff * ydiff; + + /* return to application */ + return (out); + } + + + /** + * + * @brief Q31 bilinear interpolation. + * @param[in,out] S points to an instance of the interpolation structure. + * @param[in] X interpolation coordinate in 12.20 format. + * @param[in] Y interpolation coordinate in 12.20 format. + * @return out interpolated value. + */ + static __INLINE q31_t arm_bilinear_interp_q31( + arm_bilinear_interp_instance_q31 * S, + q31_t X, + q31_t Y) + { + q31_t out; /* Temporary output */ + q31_t acc = 0; /* output */ + q31_t xfract, yfract; /* X, Y fractional parts */ + q31_t x1, x2, y1, y2; /* Nearest output values */ + int32_t rI, cI; /* Row and column indices */ + q31_t *pYData = S->pData; /* pointer to output table values */ + uint32_t nCols = S->numCols; /* num of rows */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + rI = ((X & (q31_t)0xFFF00000) >> 20); + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + cI = ((Y & (q31_t)0xFFF00000) >> 20); + + /* Care taken for table outside boundary */ + /* Returns zero output when values are outside table boundary */ + if(rI < 0 || rI > (S->numRows - 1) || cI < 0 || cI > (S->numCols - 1)) + { + return (0); + } + + /* 20 bits for the fractional part */ + /* shift left xfract by 11 to keep 1.31 format */ + xfract = (X & 0x000FFFFF) << 11u; + + /* Read two nearest output values from the index */ + x1 = pYData[(rI) + (int32_t)nCols * (cI) ]; + x2 = pYData[(rI) + (int32_t)nCols * (cI) + 1]; + + /* 20 bits for the fractional part */ + /* shift left yfract by 11 to keep 1.31 format */ + yfract = (Y & 0x000FFFFF) << 11u; + + /* Read two nearest output values from the index */ + y1 = pYData[(rI) + (int32_t)nCols * (cI + 1) ]; + y2 = pYData[(rI) + (int32_t)nCols * (cI + 1) + 1]; + + /* Calculation of x1 * (1-xfract ) * (1-yfract) and acc is in 3.29(q29) format */ + out = ((q31_t) (((q63_t) x1 * (0x7FFFFFFF - xfract)) >> 32)); + acc = ((q31_t) (((q63_t) out * (0x7FFFFFFF - yfract)) >> 32)); + + /* x2 * (xfract) * (1-yfract) in 3.29(q29) and adding to acc */ + out = ((q31_t) ((q63_t) x2 * (0x7FFFFFFF - yfract) >> 32)); + acc += ((q31_t) ((q63_t) out * (xfract) >> 32)); + + /* y1 * (1 - xfract) * (yfract) in 3.29(q29) and adding to acc */ + out = ((q31_t) ((q63_t) y1 * (0x7FFFFFFF - xfract) >> 32)); + acc += ((q31_t) ((q63_t) out * (yfract) >> 32)); + + /* y2 * (xfract) * (yfract) in 3.29(q29) and adding to acc */ + out = ((q31_t) ((q63_t) y2 * (xfract) >> 32)); + acc += ((q31_t) ((q63_t) out * (yfract) >> 32)); + + /* Convert acc to 1.31(q31) format */ + return ((q31_t)(acc << 2)); + } + + + /** + * @brief Q15 bilinear interpolation. + * @param[in,out] S points to an instance of the interpolation structure. + * @param[in] X interpolation coordinate in 12.20 format. + * @param[in] Y interpolation coordinate in 12.20 format. + * @return out interpolated value. + */ + static __INLINE q15_t arm_bilinear_interp_q15( + arm_bilinear_interp_instance_q15 * S, + q31_t X, + q31_t Y) + { + q63_t acc = 0; /* output */ + q31_t out; /* Temporary output */ + q15_t x1, x2, y1, y2; /* Nearest output values */ + q31_t xfract, yfract; /* X, Y fractional parts */ + int32_t rI, cI; /* Row and column indices */ + q15_t *pYData = S->pData; /* pointer to output table values */ + uint32_t nCols = S->numCols; /* num of rows */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + rI = ((X & (q31_t)0xFFF00000) >> 20); + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + cI = ((Y & (q31_t)0xFFF00000) >> 20); + + /* Care taken for table outside boundary */ + /* Returns zero output when values are outside table boundary */ + if(rI < 0 || rI > (S->numRows - 1) || cI < 0 || cI > (S->numCols - 1)) + { + return (0); + } + + /* 20 bits for the fractional part */ + /* xfract should be in 12.20 format */ + xfract = (X & 0x000FFFFF); + + /* Read two nearest output values from the index */ + x1 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI) ]; + x2 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI) + 1]; + + /* 20 bits for the fractional part */ + /* yfract should be in 12.20 format */ + yfract = (Y & 0x000FFFFF); + + /* Read two nearest output values from the index */ + y1 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI + 1) ]; + y2 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI + 1) + 1]; + + /* Calculation of x1 * (1-xfract ) * (1-yfract) and acc is in 13.51 format */ + + /* x1 is in 1.15(q15), xfract in 12.20 format and out is in 13.35 format */ + /* convert 13.35 to 13.31 by right shifting and out is in 1.31 */ + out = (q31_t) (((q63_t) x1 * (0xFFFFF - xfract)) >> 4u); + acc = ((q63_t) out * (0xFFFFF - yfract)); + + /* x2 * (xfract) * (1-yfract) in 1.51 and adding to acc */ + out = (q31_t) (((q63_t) x2 * (0xFFFFF - yfract)) >> 4u); + acc += ((q63_t) out * (xfract)); + + /* y1 * (1 - xfract) * (yfract) in 1.51 and adding to acc */ + out = (q31_t) (((q63_t) y1 * (0xFFFFF - xfract)) >> 4u); + acc += ((q63_t) out * (yfract)); + + /* y2 * (xfract) * (yfract) in 1.51 and adding to acc */ + out = (q31_t) (((q63_t) y2 * (xfract)) >> 4u); + acc += ((q63_t) out * (yfract)); + + /* acc is in 13.51 format and down shift acc by 36 times */ + /* Convert out to 1.15 format */ + return ((q15_t)(acc >> 36)); + } + + + /** + * @brief Q7 bilinear interpolation. + * @param[in,out] S points to an instance of the interpolation structure. + * @param[in] X interpolation coordinate in 12.20 format. + * @param[in] Y interpolation coordinate in 12.20 format. + * @return out interpolated value. + */ + static __INLINE q7_t arm_bilinear_interp_q7( + arm_bilinear_interp_instance_q7 * S, + q31_t X, + q31_t Y) + { + q63_t acc = 0; /* output */ + q31_t out; /* Temporary output */ + q31_t xfract, yfract; /* X, Y fractional parts */ + q7_t x1, x2, y1, y2; /* Nearest output values */ + int32_t rI, cI; /* Row and column indices */ + q7_t *pYData = S->pData; /* pointer to output table values */ + uint32_t nCols = S->numCols; /* num of rows */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + rI = ((X & (q31_t)0xFFF00000) >> 20); + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + cI = ((Y & (q31_t)0xFFF00000) >> 20); + + /* Care taken for table outside boundary */ + /* Returns zero output when values are outside table boundary */ + if(rI < 0 || rI > (S->numRows - 1) || cI < 0 || cI > (S->numCols - 1)) + { + return (0); + } + + /* 20 bits for the fractional part */ + /* xfract should be in 12.20 format */ + xfract = (X & (q31_t)0x000FFFFF); + + /* Read two nearest output values from the index */ + x1 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI) ]; + x2 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI) + 1]; + + /* 20 bits for the fractional part */ + /* yfract should be in 12.20 format */ + yfract = (Y & (q31_t)0x000FFFFF); + + /* Read two nearest output values from the index */ + y1 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI + 1) ]; + y2 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI + 1) + 1]; + + /* Calculation of x1 * (1-xfract ) * (1-yfract) and acc is in 16.47 format */ + out = ((x1 * (0xFFFFF - xfract))); + acc = (((q63_t) out * (0xFFFFF - yfract))); + + /* x2 * (xfract) * (1-yfract) in 2.22 and adding to acc */ + out = ((x2 * (0xFFFFF - yfract))); + acc += (((q63_t) out * (xfract))); + + /* y1 * (1 - xfract) * (yfract) in 2.22 and adding to acc */ + out = ((y1 * (0xFFFFF - xfract))); + acc += (((q63_t) out * (yfract))); + + /* y2 * (xfract) * (yfract) in 2.22 and adding to acc */ + out = ((y2 * (yfract))); + acc += (((q63_t) out * (xfract))); + + /* acc in 16.47 format and down shift by 40 to convert to 1.7 format */ + return ((q7_t)(acc >> 40)); + } + + /** + * @} end of BilinearInterpolate group + */ + + +/* SMMLAR */ +#define multAcc_32x32_keep32_R(a, x, y) \ + a = (q31_t) (((((q63_t) a) << 32) + ((q63_t) x * y) + 0x80000000LL ) >> 32) + +/* SMMLSR */ +#define multSub_32x32_keep32_R(a, x, y) \ + a = (q31_t) (((((q63_t) a) << 32) - ((q63_t) x * y) + 0x80000000LL ) >> 32) + +/* SMMULR */ +#define mult_32x32_keep32_R(a, x, y) \ + a = (q31_t) (((q63_t) x * y + 0x80000000LL ) >> 32) + +/* SMMLA */ +#define multAcc_32x32_keep32(a, x, y) \ + a += (q31_t) (((q63_t) x * y) >> 32) + +/* SMMLS */ +#define multSub_32x32_keep32(a, x, y) \ + a -= (q31_t) (((q63_t) x * y) >> 32) + +/* SMMUL */ +#define mult_32x32_keep32(a, x, y) \ + a = (q31_t) (((q63_t) x * y ) >> 32) + + +#if defined ( __CC_ARM ) + /* Enter low optimization region - place directly above function definition */ + #if defined( ARM_MATH_CM4 ) || defined( ARM_MATH_CM7) + #define LOW_OPTIMIZATION_ENTER \ + _Pragma ("push") \ + _Pragma ("O1") + #else + #define LOW_OPTIMIZATION_ENTER + #endif + + /* Exit low optimization region - place directly after end of function definition */ + #if defined( ARM_MATH_CM4 ) || defined( ARM_MATH_CM7) + #define LOW_OPTIMIZATION_EXIT \ + _Pragma ("pop") + #else + #define LOW_OPTIMIZATION_EXIT + #endif + + /* Enter low optimization region - place directly above function definition */ + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + + /* Exit low optimization region - place directly after end of function definition */ + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #define LOW_OPTIMIZATION_ENTER + #define LOW_OPTIMIZATION_EXIT + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined(__GNUC__) + #define LOW_OPTIMIZATION_ENTER __attribute__(( optimize("-O1") )) + #define LOW_OPTIMIZATION_EXIT + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined(__ICCARM__) + /* Enter low optimization region - place directly above function definition */ + #if defined( ARM_MATH_CM4 ) || defined( ARM_MATH_CM7) + #define LOW_OPTIMIZATION_ENTER \ + _Pragma ("optimize=low") + #else + #define LOW_OPTIMIZATION_ENTER + #endif + + /* Exit low optimization region - place directly after end of function definition */ + #define LOW_OPTIMIZATION_EXIT + + /* Enter low optimization region - place directly above function definition */ + #if defined( ARM_MATH_CM4 ) || defined( ARM_MATH_CM7) + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER \ + _Pragma ("optimize=low") + #else + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + #endif + + /* Exit low optimization region - place directly after end of function definition */ + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined(__CSMC__) + #define LOW_OPTIMIZATION_ENTER + #define LOW_OPTIMIZATION_EXIT + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined(__TASKING__) + #define LOW_OPTIMIZATION_ENTER + #define LOW_OPTIMIZATION_EXIT + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#endif + + +#ifdef __cplusplus +} +#endif + + +#if defined ( __GNUC__ ) +#pragma GCC diagnostic pop +#endif + +#endif /* _ARM_MATH_H */ + +/** + * + * End of file. + */ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/cmsis_armcc.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/cmsis_armcc.h new file mode 100644 index 0000000..74c49c6 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/cmsis_armcc.h @@ -0,0 +1,734 @@ +/**************************************************************************//** + * @file cmsis_armcc.h + * @brief CMSIS Cortex-M Core Function/Instruction Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM 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: + - 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 COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (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 __CMSIS_ARMCC_H +#define __CMSIS_ARMCC_H + + +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 400677) + #error "Please use ARM Compiler Toolchain V4.0.677 or later!" +#endif + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +/* intrinsic void __enable_irq(); */ +/* intrinsic void __disable_irq(); */ + +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__STATIC_INLINE uint32_t __get_CONTROL(void) +{ + register uint32_t __regControl __ASM("control"); + return(__regControl); +} + + +/** + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set + */ +__STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + register uint32_t __regControl __ASM("control"); + __regControl = control; +} + + +/** + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value + */ +__STATIC_INLINE uint32_t __get_IPSR(void) +{ + register uint32_t __regIPSR __ASM("ipsr"); + return(__regIPSR); +} + + +/** + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value + */ +__STATIC_INLINE uint32_t __get_APSR(void) +{ + register uint32_t __regAPSR __ASM("apsr"); + return(__regAPSR); +} + + +/** + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + \return xPSR Register value + */ +__STATIC_INLINE uint32_t __get_xPSR(void) +{ + register uint32_t __regXPSR __ASM("xpsr"); + return(__regXPSR); +} + + +/** + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value + */ +__STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + return(__regProcessStackPointer); +} + + +/** + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + __regProcessStackPointer = topOfProcStack; +} + + +/** + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value + */ +__STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + return(__regMainStackPointer); +} + + +/** + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + __regMainStackPointer = topOfMainStack; +} + + +/** + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value + */ +__STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + register uint32_t __regPriMask __ASM("primask"); + return(__regPriMask); +} + + +/** + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask + */ +__STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + register uint32_t __regPriMask __ASM("primask"); + __regPriMask = (priMask); +} + + +#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) + +/** + \brief Enable FIQ + \details Enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __enable_fault_irq __enable_fiq + + +/** + \brief Disable FIQ + \details Disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __disable_fault_irq __disable_fiq + + +/** + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value + */ +__STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + register uint32_t __regBasePri __ASM("basepri"); + return(__regBasePri); +} + + +/** + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set + */ +__STATIC_INLINE void __set_BASEPRI(uint32_t basePri) +{ + register uint32_t __regBasePri __ASM("basepri"); + __regBasePri = (basePri & 0xFFU); +} + + +/** + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__STATIC_INLINE void __set_BASEPRI_MAX(uint32_t basePri) +{ + register uint32_t __regBasePriMax __ASM("basepri_max"); + __regBasePriMax = (basePri & 0xFFU); +} + + +/** + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value + */ +__STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + return(__regFaultMask); +} + + +/** + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + __regFaultMask = (faultMask & (uint32_t)1); +} + +#endif /* (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) */ + + +#if (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U) + +/** + \brief Get FPSCR + \details Returns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value + */ +__STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + register uint32_t __regfpscr __ASM("fpscr"); + return(__regfpscr); +#else + return(0U); +#endif +} + + +/** + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set + */ +__STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + register uint32_t __regfpscr __ASM("fpscr"); + __regfpscr = (fpscr); +#endif +} + +#endif /* (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U) */ + + + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP __nop + + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +#define __WFI __wfi + + +/** + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE __wfe + + +/** + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV __sev + + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +#define __ISB() do {\ + __schedule_barrier();\ + __isb(0xF);\ + __schedule_barrier();\ + } while (0U) + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +#define __DSB() do {\ + __schedule_barrier();\ + __dsb(0xF);\ + __schedule_barrier();\ + } while (0U) + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +#define __DMB() do {\ + __schedule_barrier();\ + __dmb(0xF);\ + __schedule_barrier();\ + } while (0U) + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in integer value. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV __rev + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in two unsigned short values. + \param [in] value Value to reverse + \return Reversed value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value) +{ + rev16 r0, r0 + bx lr +} +#endif + +/** + \brief Reverse byte order in signed short value + \details Reverses the byte order in a signed short value with sign extension to integer. + \param [in] value Value to reverse + \return Reversed value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value) +{ + revsh r0, r0 + bx lr +} +#endif + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] value Value to rotate + \param [in] value Number of Bits to rotate + \return Rotated value + */ +#define __ROR __ror + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __breakpoint(value) + + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) + #define __RBIT __rbit +#else +__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + int32_t s = 4 /*sizeof(v)*/ * 8 - 1; /* extra shift needed at end */ + + result = value; /* r will be reversed bits of v; first get LSB of v */ + for (value >>= 1U; value; value >>= 1U) + { + result <<= 1U; + result |= value & 1U; + s--; + } + result <<= s; /* shift when v's highest bits are zero */ + return(result); +} +#endif + + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +#define __CLZ __clz + + +#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) + +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr)) +#else + #define __LDREXB(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint8_t ) __ldrex(ptr)) _Pragma("pop") +#endif + + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __LDREXH(ptr) ((uint16_t) __ldrex(ptr)) +#else + #define __LDREXH(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint16_t) __ldrex(ptr)) _Pragma("pop") +#endif + + +/** + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr)) +#else + #define __LDREXW(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint32_t ) __ldrex(ptr)) _Pragma("pop") +#endif + + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __STREXB(value, ptr) __strex(value, ptr) +#else + #define __STREXB(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") +#endif + + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __STREXH(value, ptr) __strex(value, ptr) +#else + #define __STREXH(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") +#endif + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __STREXW(value, ptr) __strex(value, ptr) +#else + #define __STREXW(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") +#endif + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +#define __CLREX __clrex + + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT __ssat + + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT __usat + + +/** + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".rrx_text"))) __STATIC_INLINE __ASM uint32_t __RRX(uint32_t value) +{ + rrx r0, r0 + bx lr +} +#endif + + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDRBT(ptr) ((uint8_t ) __ldrt(ptr)) + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDRHT(ptr) ((uint16_t) __ldrt(ptr)) + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDRT(ptr) ((uint32_t ) __ldrt(ptr)) + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +#define __STRBT(value, ptr) __strt(value, ptr) + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +#define __STRHT(value, ptr) __strt(value, ptr) + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +#define __STRT(value, ptr) __strt(value, ptr) + +#endif /* (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) */ + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if (__CORTEX_M >= 0x04U) /* only for Cortex-M4 and above */ + +#define __SADD8 __sadd8 +#define __QADD8 __qadd8 +#define __SHADD8 __shadd8 +#define __UADD8 __uadd8 +#define __UQADD8 __uqadd8 +#define __UHADD8 __uhadd8 +#define __SSUB8 __ssub8 +#define __QSUB8 __qsub8 +#define __SHSUB8 __shsub8 +#define __USUB8 __usub8 +#define __UQSUB8 __uqsub8 +#define __UHSUB8 __uhsub8 +#define __SADD16 __sadd16 +#define __QADD16 __qadd16 +#define __SHADD16 __shadd16 +#define __UADD16 __uadd16 +#define __UQADD16 __uqadd16 +#define __UHADD16 __uhadd16 +#define __SSUB16 __ssub16 +#define __QSUB16 __qsub16 +#define __SHSUB16 __shsub16 +#define __USUB16 __usub16 +#define __UQSUB16 __uqsub16 +#define __UHSUB16 __uhsub16 +#define __SASX __sasx +#define __QASX __qasx +#define __SHASX __shasx +#define __UASX __uasx +#define __UQASX __uqasx +#define __UHASX __uhasx +#define __SSAX __ssax +#define __QSAX __qsax +#define __SHSAX __shsax +#define __USAX __usax +#define __UQSAX __uqsax +#define __UHSAX __uhsax +#define __USAD8 __usad8 +#define __USADA8 __usada8 +#define __SSAT16 __ssat16 +#define __USAT16 __usat16 +#define __UXTB16 __uxtb16 +#define __UXTAB16 __uxtab16 +#define __SXTB16 __sxtb16 +#define __SXTAB16 __sxtab16 +#define __SMUAD __smuad +#define __SMUADX __smuadx +#define __SMLAD __smlad +#define __SMLADX __smladx +#define __SMLALD __smlald +#define __SMLALDX __smlaldx +#define __SMUSD __smusd +#define __SMUSDX __smusdx +#define __SMLSD __smlsd +#define __SMLSDX __smlsdx +#define __SMLSLD __smlsld +#define __SMLSLDX __smlsldx +#define __SEL __sel +#define __QADD __qadd +#define __QSUB __qsub + +#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ + ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) + +#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ + ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) + +#define __SMMLA(ARG1,ARG2,ARG3) ( (int32_t)((((int64_t)(ARG1) * (ARG2)) + \ + ((int64_t)(ARG3) << 32U) ) >> 32U)) + +#endif /* (__CORTEX_M >= 0x04) */ +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#endif /* __CMSIS_ARMCC_H */ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/cmsis_armcc_V6.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/cmsis_armcc_V6.h new file mode 100644 index 0000000..cd13240 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/cmsis_armcc_V6.h @@ -0,0 +1,1800 @@ +/**************************************************************************//** + * @file cmsis_armcc_V6.h + * @brief CMSIS Cortex-M Core Function/Instruction Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM 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: + - 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 COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (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 __CMSIS_ARMCC_V6_H +#define __CMSIS_ARMCC_V6_H + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by clearing the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__((always_inline)) __STATIC_INLINE void __enable_irq(void) +{ + __ASM volatile ("cpsie i" : : : "memory"); +} + + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by setting the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__((always_inline)) __STATIC_INLINE void __disable_irq(void) +{ + __ASM volatile ("cpsid i" : : : "memory"); +} + + +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Control Register (non-secure) + \details Returns the content of the non-secure Control Register when in secure mode. + \return non-secure Control Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_CONTROL_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Control Register (non-secure) + \details Writes the given value to the non-secure Control Register when in secure state. + \param [in] control Control Register value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_CONTROL_NS(uint32_t control) +{ + __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory"); +} +#endif + + +/** + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get IPSR Register (non-secure) + \details Returns the content of the non-secure IPSR Register when in secure state. + \return IPSR Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_IPSR_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get APSR Register (non-secure) + \details Returns the content of the non-secure APSR Register when in secure state. + \return APSR Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_APSR_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + \return xPSR Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get xPSR Register (non-secure) + \details Returns the content of the non-secure xPSR Register when in secure state. + \return xPSR Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_xPSR_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, psp" : "=r" (result) ); + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Process Stack Pointer (non-secure) + \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state. + \return PSP Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_PSP_NS(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, psp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : "sp"); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Process Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state. + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : "sp"); +} +#endif + + +/** + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, msp" : "=r" (result) ); + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Main Stack Pointer (non-secure) + \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state. + \return MSP Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_MSP_NS(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, msp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : "sp"); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Main Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state. + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : "sp"); +} +#endif + + +/** + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) ); + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Priority Mask (non-secure) + \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state. + \return Priority Mask value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_PRIMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Priority Mask (non-secure) + \details Assigns the given value to the non-secure Priority Mask Register when in secure state. + \param [in] priMask Priority Mask + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) +{ + __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory"); +} +#endif + + +#if ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) /* ToDo: ARMCC_V6: check if this is ok for cortex >=3 */ + +/** + \brief Enable FIQ + \details Enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__((always_inline)) __STATIC_INLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f" : : : "memory"); +} + + +/** + \brief Disable FIQ + \details Disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__((always_inline)) __STATIC_INLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f" : : : "memory"); +} + + +/** + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri" : "=r" (result) ); + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Base Priority (non-secure) + \details Returns the current value of the non-secure Base Priority register when in secure state. + \return Base Priority register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_BASEPRI_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_BASEPRI(uint32_t value) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (value) : "memory"); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Base Priority (non-secure) + \details Assigns the given value to the non-secure Base Priority register when in secure state. + \param [in] basePri Base Priority value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_BASEPRI_NS(uint32_t value) +{ + __ASM volatile ("MSR basepri_ns, %0" : : "r" (value) : "memory"); +} +#endif + + +/** + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_BASEPRI_MAX(uint32_t value) +{ + __ASM volatile ("MSR basepri_max, %0" : : "r" (value) : "memory"); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Base Priority with condition (non_secure) + \details Assigns the given value to the non-secure Base Priority register when in secure state only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_BASEPRI_MAX_NS(uint32_t value) +{ + __ASM volatile ("MSR basepri_max_ns, %0" : : "r" (value) : "memory"); +} +#endif + + +/** + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Fault Mask (non-secure) + \details Returns the current value of the non-secure Fault Mask register when in secure state. + \return Fault Mask register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_FAULTMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Fault Mask (non-secure) + \details Assigns the given value to the non-secure Fault Mask register when in secure state. + \param [in] faultMask Fault Mask value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory"); +} +#endif + + +#endif /* ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_8M__ == 1U)) */ + + +#if (__ARM_ARCH_8M__ == 1U) + +/** + \brief Get Process Stack Pointer Limit + \details Returns the current value of the Process Stack Pointer Limit (PSPLIM). + \return PSPLIM Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_PSPLIM(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, psplim" : "=r" (result) ); + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) && (__ARM_ARCH_PROFILE == 'M') /* ToDo: ARMCC_V6: check predefined macro for mainline */ +/** + \brief Get Process Stack Pointer Limit (non-secure) + \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \return PSPLIM Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_PSPLIM_NS(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Process Stack Pointer Limit + \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM). + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) +{ + __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit)); +} + + +#if (__ARM_FEATURE_CMSE == 3U) && (__ARM_ARCH_PROFILE == 'M') /* ToDo: ARMCC_V6: check predefined macro for mainline */ +/** + \brief Set Process Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) +{ + __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit)); +} +#endif + + +/** + \brief Get Main Stack Pointer Limit + \details Returns the current value of the Main Stack Pointer Limit (MSPLIM). + \return MSPLIM Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_MSPLIM(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, msplim" : "=r" (result) ); + + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) && (__ARM_ARCH_PROFILE == 'M') /* ToDo: ARMCC_V6: check predefined macro for mainline */ +/** + \brief Get Main Stack Pointer Limit (non-secure) + \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state. + \return MSPLIM Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_MSPLIM_NS(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Main Stack Pointer Limit + \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM). + \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) +{ + __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit)); +} + + +#if (__ARM_FEATURE_CMSE == 3U) && (__ARM_ARCH_PROFILE == 'M') /* ToDo: ARMCC_V6: check predefined macro for mainline */ +/** + \brief Set Main Stack Pointer Limit (non-secure) + \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state. + \param [in] MainStackPtrLimit Main Stack Pointer value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) +{ + __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit)); +} +#endif + +#endif /* (__ARM_ARCH_8M__ == 1U) */ + + +#if ((__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) /* ToDo: ARMCC_V6: check if this is ok for cortex >=4 */ + +/** + \brief Get FPSCR + \details eturns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value + */ +#define __get_FPSCR __builtin_arm_get_fpscr +#if 0 +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + uint32_t result; + + __ASM volatile (""); /* Empty asm statement works as a scheduling barrier */ + __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); + __ASM volatile (""); + return(result); +#else + return(0); +#endif +} +#endif + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get FPSCR (non-secure) + \details Returns the current value of the non-secure Floating Point Status/Control register when in secure state. + \return Floating Point Status/Control register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_FPSCR_NS(void) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + uint32_t result; + + __ASM volatile (""); /* Empty asm statement works as a scheduling barrier */ + __ASM volatile ("VMRS %0, fpscr_ns" : "=r" (result) ); + __ASM volatile (""); + return(result); +#else + return(0); +#endif +} +#endif + + +/** + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set + */ +#define __set_FPSCR __builtin_arm_set_fpscr +#if 0 +__attribute__((always_inline)) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + __ASM volatile (""); /* Empty asm statement works as a scheduling barrier */ + __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc"); + __ASM volatile (""); +#endif +} +#endif + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set FPSCR (non-secure) + \details Assigns the given value to the non-secure Floating Point Status/Control register when in secure state. + \param [in] fpscr Floating Point Status/Control value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_FPSCR_NS(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + __ASM volatile (""); /* Empty asm statement works as a scheduling barrier */ + __ASM volatile ("VMSR fpscr_ns, %0" : : "r" (fpscr) : "vfpcc"); + __ASM volatile (""); +#endif +} +#endif + +#endif /* ((__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) */ + + + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/* Define macros for porting to both thumb1 and thumb2. + * For thumb1, use low register (r0-r7), specified by constraint "l" + * Otherwise, use general registers, specified by constraint "r" */ +#if defined (__thumb__) && !defined (__thumb2__) +#define __CMSIS_GCC_OUT_REG(r) "=l" (r) +#define __CMSIS_GCC_USE_REG(r) "l" (r) +#else +#define __CMSIS_GCC_OUT_REG(r) "=r" (r) +#define __CMSIS_GCC_USE_REG(r) "r" (r) +#endif + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP __builtin_arm_nop + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +#define __WFI __builtin_arm_wfi + + +/** + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE __builtin_arm_wfe + + +/** + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV __builtin_arm_sev + + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +#define __ISB() __builtin_arm_isb(0xF); + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +#define __DSB() __builtin_arm_dsb(0xF); + + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +#define __DMB() __builtin_arm_dmb(0xF); + + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in integer value. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV __builtin_bswap32 + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in two unsigned short values. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV16 __builtin_bswap16 /* ToDo: ARMCC_V6: check if __builtin_bswap16 could be used */ +#if 0 +__attribute__((always_inline)) __STATIC_INLINE uint32_t __REV16(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} +#endif + + +/** + \brief Reverse byte order in signed short value + \details Reverses the byte order in a signed short value with sign extension to integer. + \param [in] value Value to reverse + \return Reversed value + */ + /* ToDo: ARMCC_V6: check if __builtin_bswap16 could be used */ +__attribute__((always_inline)) __STATIC_INLINE int32_t __REVSH(int32_t value) +{ + int32_t result; + + __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] op1 Value to rotate + \param [in] op2 Number of Bits to rotate + \return Rotated value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + return (op1 >> op2) | (op1 << (32U - op2)); +} + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __ASM volatile ("bkpt "#value) + + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ + /* ToDo: ARMCC_V6: check if __builtin_arm_rbit is supported */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + +#if ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) /* ToDo: ARMCC_V6: check if this is ok for cortex >=3 */ + __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); +#else + int32_t s = 4 /*sizeof(v)*/ * 8 - 1; /* extra shift needed at end */ + + result = value; /* r will be reversed bits of v; first get LSB of v */ + for (value >>= 1U; value; value >>= 1U) + { + result <<= 1U; + result |= value & 1U; + s--; + } + result <<= s; /* shift when v's highest bits are zero */ +#endif + return(result); +} + + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +#define __CLZ __builtin_clz + + +#if ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) /* ToDo: ARMCC_V6: check if this is ok for cortex >=3 */ + +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDREXB (uint8_t)__builtin_arm_ldrex + + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDREXH (uint16_t)__builtin_arm_ldrex + + +/** + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDREXW (uint32_t)__builtin_arm_ldrex + + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXB (uint32_t)__builtin_arm_strex + + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXH (uint32_t)__builtin_arm_strex + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXW (uint32_t)__builtin_arm_strex + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +#define __CLREX __builtin_arm_clrex + + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +/*#define __SSAT __builtin_arm_ssat*/ +#define __SSAT(ARG1,ARG2) \ +({ \ + int32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT __builtin_arm_usat +#if 0 +#define __USAT(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) +#endif + + +/** + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __RRX(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint8_t __LDRBT(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint16_t __LDRHT(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __LDRT(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); +} + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__attribute__((always_inline)) __STATIC_INLINE void __STRBT(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__attribute__((always_inline)) __STATIC_INLINE void __STRHT(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__attribute__((always_inline)) __STATIC_INLINE void __STRT(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) ); +} + +#endif /* ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) */ + + +#if (__ARM_ARCH_8M__ == 1U) + +/** + \brief Load-Acquire (8 bit) + \details Executes a LDAB instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint8_t __LDAB(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint8_t) result); +} + + +/** + \brief Load-Acquire (16 bit) + \details Executes a LDAH instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint16_t __LDAH(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint16_t) result); +} + + +/** + \brief Load-Acquire (32 bit) + \details Executes a LDA instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __LDA(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); +} + + +/** + \brief Store-Release (8 bit) + \details Executes a STLB instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__attribute__((always_inline)) __STATIC_INLINE void __STLB(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief Store-Release (16 bit) + \details Executes a STLH instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__attribute__((always_inline)) __STATIC_INLINE void __STLH(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief Store-Release (32 bit) + \details Executes a STL instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__attribute__((always_inline)) __STATIC_INLINE void __STL(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief Load-Acquire Exclusive (8 bit) + \details Executes a LDAB exclusive instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDAEXB (uint8_t)__builtin_arm_ldaex + + +/** + \brief Load-Acquire Exclusive (16 bit) + \details Executes a LDAH exclusive instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDAEXH (uint16_t)__builtin_arm_ldaex + + +/** + \brief Load-Acquire Exclusive (32 bit) + \details Executes a LDA exclusive instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDAEX (uint32_t)__builtin_arm_ldaex + + +/** + \brief Store-Release Exclusive (8 bit) + \details Executes a STLB exclusive instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEXB (uint32_t)__builtin_arm_stlex + + +/** + \brief Store-Release Exclusive (16 bit) + \details Executes a STLH exclusive instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEXH (uint32_t)__builtin_arm_stlex + + +/** + \brief Store-Release Exclusive (32 bit) + \details Executes a STL exclusive instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEX (uint32_t)__builtin_arm_stlex + +#endif /* (__ARM_ARCH_8M__ == 1U) */ + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if (__ARM_FEATURE_DSP == 1U) /* ToDo: ARMCC_V6: This should be ARCH >= ARMv7-M + SIMD */ + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __QASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __USAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#define __SSAT16(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +#define __USAT16(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SEL (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE int32_t __QADD( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE int32_t __QSUB( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +#define __PKHBT(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + __ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) + +#define __PKHTB(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + if (ARG3 == 0) \ + __ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \ + else \ + __ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) +{ + int32_t result; + + __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#endif /* (__ARM_FEATURE_DSP == 1U) */ +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#endif /* __CMSIS_ARMCC_V6_H */ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/cmsis_gcc.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/cmsis_gcc.h new file mode 100644 index 0000000..bb89fbb --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/cmsis_gcc.h @@ -0,0 +1,1373 @@ +/**************************************************************************//** + * @file cmsis_gcc.h + * @brief CMSIS Cortex-M Core Function/Instruction Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM 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: + - 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 COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (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 __CMSIS_GCC_H +#define __CMSIS_GCC_H + +/* ignore some GCC warnings */ +#if defined ( __GNUC__ ) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-conversion" +#pragma GCC diagnostic ignored "-Wconversion" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by clearing the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void) +{ + __ASM volatile ("cpsie i" : : : "memory"); +} + + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by setting the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void) +{ + __ASM volatile ("cpsid i" : : : "memory"); +} + + +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); +} + + +/** + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + + \return xPSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, psp\n" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0\n" : : "r" (topOfProcStack) : "sp"); +} + + +/** + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, msp\n" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) : "sp"); +} + + +/** + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); +} + + +#if (__CORTEX_M >= 0x03U) + +/** + \brief Enable FIQ + \details Enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f" : : : "memory"); +} + + +/** + \brief Disable FIQ + \details Disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f" : : : "memory"); +} + + +/** + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI(uint32_t value) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (value) : "memory"); +} + + +/** + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI_MAX(uint32_t value) +{ + __ASM volatile ("MSR basepri_max, %0" : : "r" (value) : "memory"); +} + + +/** + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); +} + +#endif /* (__CORTEX_M >= 0x03U) */ + + +#if (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U) + +/** + \brief Get FPSCR + \details Returns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + uint32_t result; + + /* Empty asm statement works as a scheduling barrier */ + __ASM volatile (""); + __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); + __ASM volatile (""); + return(result); +#else + return(0); +#endif +} + + +/** + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + /* Empty asm statement works as a scheduling barrier */ + __ASM volatile (""); + __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc"); + __ASM volatile (""); +#endif +} + +#endif /* (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U) */ + + + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/* Define macros for porting to both thumb1 and thumb2. + * For thumb1, use low register (r0-r7), specified by constraint "l" + * Otherwise, use general registers, specified by constraint "r" */ +#if defined (__thumb__) && !defined (__thumb2__) +#define __CMSIS_GCC_OUT_REG(r) "=l" (r) +#define __CMSIS_GCC_USE_REG(r) "l" (r) +#else +#define __CMSIS_GCC_OUT_REG(r) "=r" (r) +#define __CMSIS_GCC_USE_REG(r) "r" (r) +#endif + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +__attribute__((always_inline)) __STATIC_INLINE void __NOP(void) +{ + __ASM volatile ("nop"); +} + + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +__attribute__((always_inline)) __STATIC_INLINE void __WFI(void) +{ + __ASM volatile ("wfi"); +} + + +/** + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +__attribute__((always_inline)) __STATIC_INLINE void __WFE(void) +{ + __ASM volatile ("wfe"); +} + + +/** + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +__attribute__((always_inline)) __STATIC_INLINE void __SEV(void) +{ + __ASM volatile ("sev"); +} + + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +__attribute__((always_inline)) __STATIC_INLINE void __ISB(void) +{ + __ASM volatile ("isb 0xF":::"memory"); +} + + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +__attribute__((always_inline)) __STATIC_INLINE void __DSB(void) +{ + __ASM volatile ("dsb 0xF":::"memory"); +} + + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +__attribute__((always_inline)) __STATIC_INLINE void __DMB(void) +{ + __ASM volatile ("dmb 0xF":::"memory"); +} + + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in integer value. + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __REV(uint32_t value) +{ +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) + return __builtin_bswap32(value); +#else + uint32_t result; + + __ASM volatile ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +#endif +} + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in two unsigned short values. + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __REV16(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** + \brief Reverse byte order in signed short value + \details Reverses the byte order in a signed short value with sign extension to integer. + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__((always_inline)) __STATIC_INLINE int32_t __REVSH(int32_t value) +{ +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + return (short)__builtin_bswap16(value); +#else + int32_t result; + + __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +#endif +} + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] value Value to rotate + \param [in] value Number of Bits to rotate + \return Rotated value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + return (op1 >> op2) | (op1 << (32U - op2)); +} + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __ASM volatile ("bkpt "#value) + + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + +#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) + __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); +#else + int32_t s = 4 /*sizeof(v)*/ * 8 - 1; /* extra shift needed at end */ + + result = value; /* r will be reversed bits of v; first get LSB of v */ + for (value >>= 1U; value; value >>= 1U) + { + result <<= 1U; + result |= value & 1U; + s--; + } + result <<= s; /* shift when v's highest bits are zero */ +#endif + return(result); +} + + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +#define __CLZ __builtin_clz + + +#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) + +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint8_t __LDREXB(volatile uint8_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint16_t __LDREXH(volatile uint16_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __LDREXW(volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) ); + return(result); +} + + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); + return(result); +} + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +__attribute__((always_inline)) __STATIC_INLINE void __CLREX(void) +{ + __ASM volatile ("clrex" ::: "memory"); +} + + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __RRX(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint8_t __LDRBT(volatile uint8_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrbt %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint16_t __LDRHT(volatile uint16_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrht %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __LDRT(volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*addr) ); + return(result); +} + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__attribute__((always_inline)) __STATIC_INLINE void __STRBT(uint8_t value, volatile uint8_t *addr) +{ + __ASM volatile ("strbt %1, %0" : "=Q" (*addr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__attribute__((always_inline)) __STATIC_INLINE void __STRHT(uint16_t value, volatile uint16_t *addr) +{ + __ASM volatile ("strht %1, %0" : "=Q" (*addr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__attribute__((always_inline)) __STATIC_INLINE void __STRT(uint32_t value, volatile uint32_t *addr) +{ + __ASM volatile ("strt %1, %0" : "=Q" (*addr) : "r" (value) ); +} + +#endif /* (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) */ + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if (__CORTEX_M >= 0x04U) /* only for Cortex-M4 and above */ + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#define __SSAT16(ARG1,ARG2) \ +({ \ + int32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +#define __USAT16(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SEL (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __QADD( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __QSUB( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +#define __PKHBT(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + __ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) + +#define __PKHTB(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + if (ARG3 == 0) \ + __ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \ + else \ + __ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) +{ + int32_t result; + + __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#endif /* (__CORTEX_M >= 0x04) */ +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#if defined ( __GNUC__ ) +#pragma GCC diagnostic pop +#endif + +#endif /* __CMSIS_GCC_H */ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cm0.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cm0.h new file mode 100644 index 0000000..711dad5 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cm0.h @@ -0,0 +1,798 @@ +/**************************************************************************//** + * @file core_cm0.h + * @brief CMSIS Cortex-M0 Core Peripheral Access Layer Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM 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: + - 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 COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (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 ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CM0_H_GENERIC +#define __CORE_CM0_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_M0 + @{ + */ + +/* CMSIS CM0 definitions */ +#define __CM0_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */ +#define __CM0_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */ +#define __CM0_CMSIS_VERSION ((__CM0_CMSIS_VERSION_MAIN << 16U) | \ + __CM0_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + +#define __CORTEX_M (0x00U) /*!< Cortex-M Core */ + + +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ + #define __STATIC_INLINE static inline + +#elif defined ( __TMS470__ ) + #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __CSMC__ ) + #define __packed + #define __ASM _asm /*!< asm keyword for COSMIC Compiler */ + #define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */ + #define __STATIC_INLINE static inline + +#else + #error Unknown compiler +#endif + +/** __FPU_USED indicates whether an FPU is used or not. + This core does not support an FPU at all +*/ +#define __FPU_USED 0U + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_PCS_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TMS470__ ) + #if defined __TI_VFP_SUPPORT__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#endif + +#include "core_cmInstr.h" /* Core Instruction Access */ +#include "core_cmFunc.h" /* Core Function Access */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM0_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM0_H_DEPENDANT +#define __CORE_CM0_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM0_REV + #define __CM0_REV 0x0000U + #warning "__CM0_REV not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 2U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex_M0 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t _reserved0:1; /*!< bit: 0 Reserved */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[31U]; + __IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[31U]; + __IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[31U]; + __IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[31U]; + uint32_t RESERVED4[64U]; + __IOM uint32_t IP[8U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */ +} NVIC_Type; + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + uint32_t RESERVED0; + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + uint32_t RESERVED1; + __IOM uint32_t SHP[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Cortex-M0 Core Debug Registers (DCB registers, SHCSR, and DFSR) are only accessible over DAP and not via processor. + Therefore they are not covered by the Cortex-M0 header file. + @{ + */ +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Cortex-M0 Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ + + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +/* Interrupt Priorities are WORD accessible only under ARMv6M */ +/* The following MACROS handle generation of the register offset and byte masks */ +#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL) +#define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) ) +#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) ) + + +/** + \brief Enable External Interrupt + \details Enables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Disable External Interrupt + \details Disables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Get Pending Interrupt + \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of an external interrupt. + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of an external interrupt. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of an interrupt. + \note The priority cannot be set for every core interrupt. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) < 0) + { + SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } + else + { + NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of an interrupt. + The interrupt number can be positive to specify an external (device specific) interrupt, + or negative to specify an internal (core) interrupt. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) < 0) + { + return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__STATIC_INLINE void NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + SCB_AIRCR_SYSRESETREQ_Msk); + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM0_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cm0plus.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cm0plus.h new file mode 100644 index 0000000..b04aa39 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cm0plus.h @@ -0,0 +1,914 @@ +/**************************************************************************//** + * @file core_cm0plus.h + * @brief CMSIS Cortex-M0+ Core Peripheral Access Layer Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM 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: + - 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 COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (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 ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CM0PLUS_H_GENERIC +#define __CORE_CM0PLUS_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex-M0+ + @{ + */ + +/* CMSIS CM0+ definitions */ +#define __CM0PLUS_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */ +#define __CM0PLUS_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */ +#define __CM0PLUS_CMSIS_VERSION ((__CM0PLUS_CMSIS_VERSION_MAIN << 16U) | \ + __CM0PLUS_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + +#define __CORTEX_M (0x00U) /*!< Cortex-M Core */ + + +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ + #define __STATIC_INLINE static inline + +#elif defined ( __TMS470__ ) + #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __CSMC__ ) + #define __packed + #define __ASM _asm /*!< asm keyword for COSMIC Compiler */ + #define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */ + #define __STATIC_INLINE static inline + +#else + #error Unknown compiler +#endif + +/** __FPU_USED indicates whether an FPU is used or not. + This core does not support an FPU at all +*/ +#define __FPU_USED 0U + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_PCS_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TMS470__ ) + #if defined __TI_VFP_SUPPORT__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#endif + +#include "core_cmInstr.h" /* Core Instruction Access */ +#include "core_cmFunc.h" /* Core Function Access */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM0PLUS_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM0PLUS_H_DEPENDANT +#define __CORE_CM0PLUS_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM0PLUS_REV + #define __CM0PLUS_REV 0x0000U + #warning "__CM0PLUS_REV not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __VTOR_PRESENT + #define __VTOR_PRESENT 0U + #warning "__VTOR_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 2U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex-M0+ */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core MPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[31U]; + __IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[31U]; + __IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[31U]; + __IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[31U]; + uint32_t RESERVED4[64U]; + __IOM uint32_t IP[8U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */ +} NVIC_Type; + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ +#if (__VTOR_PRESENT == 1U) + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ +#else + uint32_t RESERVED0; +#endif + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + uint32_t RESERVED1; + __IOM uint32_t SHP[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +#if (__VTOR_PRESENT == 1U) +/* SCB Interrupt Control State Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 8U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0xFFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ +#endif + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + +#if (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ +} MPU_Type; + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_ADDR_Pos 8U /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0xFFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register Definitions */ +#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Cortex-M0+ Core Debug Registers (DCB registers, SHCSR, and DFSR) are only accessible over DAP and not via processor. + Therefore they are not covered by the Cortex-M0+ header file. + @{ + */ +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Cortex-M0+ Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ + +#if (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +/* Interrupt Priorities are WORD accessible only under ARMv6M */ +/* The following MACROS handle generation of the register offset and byte masks */ +#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL) +#define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) ) +#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) ) + + +/** + \brief Enable External Interrupt + \details Enables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Disable External Interrupt + \details Disables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Get Pending Interrupt + \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of an external interrupt. + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of an external interrupt. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of an interrupt. + \note The priority cannot be set for every core interrupt. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) < 0) + { + SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } + else + { + NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of an interrupt. + The interrupt number can be positive to specify an external (device specific) interrupt, + or negative to specify an internal (core) interrupt. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) < 0) + { + return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__STATIC_INLINE void NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + SCB_AIRCR_SYSRESETREQ_Msk); + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM0PLUS_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cm3.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cm3.h new file mode 100644 index 0000000..b4ac4c7 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cm3.h @@ -0,0 +1,1763 @@ +/**************************************************************************//** + * @file core_cm3.h + * @brief CMSIS Cortex-M3 Core Peripheral Access Layer Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM 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: + - 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 COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (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 ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CM3_H_GENERIC +#define __CORE_CM3_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_M3 + @{ + */ + +/* CMSIS CM3 definitions */ +#define __CM3_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */ +#define __CM3_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */ +#define __CM3_CMSIS_VERSION ((__CM3_CMSIS_VERSION_MAIN << 16U) | \ + __CM3_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + +#define __CORTEX_M (0x03U) /*!< Cortex-M Core */ + + +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ + #define __STATIC_INLINE static inline + +#elif defined ( __TMS470__ ) + #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __CSMC__ ) + #define __packed + #define __ASM _asm /*!< asm keyword for COSMIC Compiler */ + #define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */ + #define __STATIC_INLINE static inline + +#else + #error Unknown compiler +#endif + +/** __FPU_USED indicates whether an FPU is used or not. + This core does not support an FPU at all +*/ +#define __FPU_USED 0U + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_PCS_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TMS470__ ) + #if defined __TI_VFP_SUPPORT__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#endif + +#include "core_cmInstr.h" /* Core Instruction Access */ +#include "core_cmFunc.h" /* Core Function Access */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM3_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM3_H_DEPENDANT +#define __CORE_CM3_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM3_REV + #define __CM3_REV 0x0200U + #warning "__CM3_REV not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 4U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex_M3 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + +#define APSR_Q_Pos 27U /*!< APSR: Q Position */ +#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ +#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ + +#define xPSR_IT_Pos 25U /*!< xPSR: IT Position */ +#define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24U]; + __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[24U]; + __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24U]; + __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24U]; + __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56U]; + __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHP[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[5U]; + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#if (__CM3_REV < 0x0201U) /* core r2p1 */ +#define SCB_VTOR_TBLBASE_Pos 29U /*!< SCB VTOR: TBLBASE Position */ +#define SCB_VTOR_TBLBASE_Msk (1UL << SCB_VTOR_TBLBASE_Pos) /*!< SCB VTOR: TBLBASE Mask */ + +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x3FFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ +#else +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ +#endif + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +#define SCB_AIRCR_VECTRESET_Pos 0U /*!< SCB AIRCR: VECTRESET Position */ +#define SCB_AIRCR_VECTRESET_Msk (1UL /*<< SCB_AIRCR_VECTRESET_Pos*/) /*!< SCB AIRCR: VECTRESET Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +#define SCB_CCR_NONBASETHRDENA_Pos 0U /*!< SCB CCR: NONBASETHRDENA Position */ +#define SCB_CCR_NONBASETHRDENA_Msk (1UL /*<< SCB_CCR_NONBASETHRDENA_Pos*/) /*!< SCB CCR: NONBASETHRDENA Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Register Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* SCB Hard Fault Status Register Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ +#if ((defined __CM3_REV) && (__CM3_REV >= 0x200U)) + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +#else + uint32_t RESERVED1[1U]; +#endif +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ + +/* Auxiliary Control Register Definitions */ + +#define SCnSCB_ACTLR_DISFOLD_Pos 2U /*!< ACTLR: DISFOLD Position */ +#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ + +#define SCnSCB_ACTLR_DISDEFWBUF_Pos 1U /*!< ACTLR: DISDEFWBUF Position */ +#define SCnSCB_ACTLR_DISDEFWBUF_Msk (1UL << SCnSCB_ACTLR_DISDEFWBUF_Pos) /*!< ACTLR: DISDEFWBUF Mask */ + +#define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */ +#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** + \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[29U]; + __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ + __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ + __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TraceBusID_Pos 16U /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPrescale_Pos 8U /*!< ITM TCR: TSPrescale Position */ +#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ + +#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Integration Write Register Definitions */ +#define ITM_IWR_ATVALIDM_Pos 0U /*!< ITM IWR: ATVALIDM Position */ +#define ITM_IWR_ATVALIDM_Msk (1UL /*<< ITM_IWR_ATVALIDM_Pos*/) /*!< ITM IWR: ATVALIDM Mask */ + +/* ITM Integration Read Register Definitions */ +#define ITM_IRR_ATREADYM_Pos 0U /*!< ITM IRR: ATREADYM Position */ +#define ITM_IRR_ATREADYM_Msk (1UL /*<< ITM_IRR_ATREADYM_Pos*/) /*!< ITM IRR: ATREADYM Mask */ + +/* ITM Integration Mode Control Register Definitions */ +#define ITM_IMCR_INTEGRATION_Pos 0U /*!< ITM IMCR: INTEGRATION Position */ +#define ITM_IMCR_INTEGRATION_Msk (1UL /*<< ITM_IMCR_INTEGRATION_Pos*/) /*!< ITM IMCR: INTEGRATION Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Mask Register Definitions */ +#define DWT_MASK_MASK_Pos 0U /*!< DWT MASK: MASK Position */ +#define DWT_MASK_MASK_Msk (0x1FUL /*<< DWT_MASK_MASK_Pos*/) /*!< DWT MASK: MASK Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVADDR1_Pos 16U /*!< DWT FUNCTION: DATAVADDR1 Position */ +#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ + +#define DWT_FUNCTION_DATAVADDR0_Pos 12U /*!< DWT FUNCTION: DATAVADDR0 Position */ +#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_LNK1ENA_Pos 9U /*!< DWT FUNCTION: LNK1ENA Position */ +#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ + +#define DWT_FUNCTION_DATAVMATCH_Pos 8U /*!< DWT FUNCTION: DATAVMATCH Position */ +#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ + +#define DWT_FUNCTION_CYCMATCH_Pos 7U /*!< DWT FUNCTION: CYCMATCH Position */ +#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ + +#define DWT_FUNCTION_EMITRANGE_Pos 5U /*!< DWT FUNCTION: EMITRANGE Position */ +#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ + +#define DWT_FUNCTION_FUNCTION_Pos 0U /*!< DWT FUNCTION: FUNCTION Position */ +#define DWT_FUNCTION_FUNCTION_Msk (0xFUL /*<< DWT_FUNCTION_FUNCTION_Pos*/) /*!< DWT FUNCTION: FUNCTION Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IOM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ + __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY_Pos 0U /*!< TPI ITATBCTR2: ATREADY Position */ +#define TPI_ITATBCTR2_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY_Pos*/) /*!< TPI ITATBCTR2: ATREADY Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY_Pos 0U /*!< TPI ITATBCTR0: ATREADY Position */ +#define TPI_ITATBCTR0_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY_Pos*/) /*!< TPI ITATBCTR0: ATREADY Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x1UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_MajorType_Pos 4U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +#define TPI_DEVTYPE_SubType_Pos 0U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ +} MPU_Type; + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register Definitions */ +#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register Definitions */ +#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Cortex-M3 Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +/** + \brief Set Priority Grouping + \details Sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */ + SCB->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping + \details Reads the priority grouping field from the NVIC Interrupt Controller. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t NVIC_GetPriorityGrouping(void) +{ + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable External Interrupt + \details Enables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Disable External Interrupt + \details Disables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Get Pending Interrupt + \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t)(((NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of an external interrupt. + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of an external interrupt. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in NVIC and returns the active bit. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + */ +__STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) +{ + return((uint32_t)(((NVIC->IABR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of an interrupt. + \note The priority cannot be set for every core interrupt. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) < 0) + { + SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + NVIC->IP[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of an interrupt. + The interrupt number can be positive to specify an external (device specific) interrupt, + or negative to specify an internal (core) interrupt. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) < 0) + { + return(((uint32_t)SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)NVIC->IP[((uint32_t)(int32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__STATIC_INLINE void NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY 0x5AA55AA5U /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** + \brief ITM Send Character + \details Transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + \param [in] ch Character to transmit. + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; + } + return (ch); +} + + +/** + \brief ITM Receive Character + \details Inputs a character via the external variable \ref ITM_RxBuffer. + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) +{ + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** + \brief ITM Check Character + \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) +{ + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM3_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cm4.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cm4.h new file mode 100644 index 0000000..dc840eb --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cm4.h @@ -0,0 +1,1937 @@ +/**************************************************************************//** + * @file core_cm4.h + * @brief CMSIS Cortex-M4 Core Peripheral Access Layer Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM 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: + - 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 COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (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 ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CM4_H_GENERIC +#define __CORE_CM4_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_M4 + @{ + */ + +/* CMSIS CM4 definitions */ +#define __CM4_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */ +#define __CM4_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */ +#define __CM4_CMSIS_VERSION ((__CM4_CMSIS_VERSION_MAIN << 16U) | \ + __CM4_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + +#define __CORTEX_M (0x04U) /*!< Cortex-M Core */ + + +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ + #define __STATIC_INLINE static inline + +#elif defined ( __TMS470__ ) + #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __CSMC__ ) + #define __packed + #define __ASM _asm /*!< asm keyword for COSMIC Compiler */ + #define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */ + #define __STATIC_INLINE static inline + +#else + #error Unknown compiler +#endif + +/** __FPU_USED indicates whether an FPU is used or not. + For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. +*/ +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_PCS_VFP + #if (__FPU_PRESENT == 1) + #define __FPU_USED 1U + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TMS470__ ) + #if defined __TI_VFP_SUPPORT__ + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#endif + +#include "core_cmInstr.h" /* Core Instruction Access */ +#include "core_cmFunc.h" /* Core Function Access */ +#include "core_cmSimd.h" /* Compiler specific SIMD Intrinsics */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM4_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM4_H_DEPENDANT +#define __CORE_CM4_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM4_REV + #define __CM4_REV 0x0000U + #warning "__CM4_REV not defined in device header file; using default!" + #endif + + #ifndef __FPU_PRESENT + #define __FPU_PRESENT 0U + #warning "__FPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 4U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex_M4 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + - Core FPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + +#define APSR_Q_Pos 27U /*!< APSR: Q Position */ +#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ + +#define APSR_GE_Pos 16U /*!< APSR: GE Position */ +#define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ +#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ + +#define xPSR_IT_Pos 25U /*!< xPSR: IT Position */ +#define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_GE_Pos 16U /*!< xPSR: GE Position */ +#define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */ + uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */ +#define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */ + +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24U]; + __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[24U]; + __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24U]; + __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24U]; + __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56U]; + __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHP[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[5U]; + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +#define SCB_AIRCR_VECTRESET_Pos 0U /*!< SCB AIRCR: VECTRESET Position */ +#define SCB_AIRCR_VECTRESET_Msk (1UL /*<< SCB_AIRCR_VECTRESET_Pos*/) /*!< SCB AIRCR: VECTRESET Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +#define SCB_CCR_NONBASETHRDENA_Pos 0U /*!< SCB CCR: NONBASETHRDENA Position */ +#define SCB_CCR_NONBASETHRDENA_Msk (1UL /*<< SCB_CCR_NONBASETHRDENA_Pos*/) /*!< SCB CCR: NONBASETHRDENA Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Register Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* SCB Hard Fault Status Register Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ + +/* Auxiliary Control Register Definitions */ +#define SCnSCB_ACTLR_DISOOFP_Pos 9U /*!< ACTLR: DISOOFP Position */ +#define SCnSCB_ACTLR_DISOOFP_Msk (1UL << SCnSCB_ACTLR_DISOOFP_Pos) /*!< ACTLR: DISOOFP Mask */ + +#define SCnSCB_ACTLR_DISFPCA_Pos 8U /*!< ACTLR: DISFPCA Position */ +#define SCnSCB_ACTLR_DISFPCA_Msk (1UL << SCnSCB_ACTLR_DISFPCA_Pos) /*!< ACTLR: DISFPCA Mask */ + +#define SCnSCB_ACTLR_DISFOLD_Pos 2U /*!< ACTLR: DISFOLD Position */ +#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ + +#define SCnSCB_ACTLR_DISDEFWBUF_Pos 1U /*!< ACTLR: DISDEFWBUF Position */ +#define SCnSCB_ACTLR_DISDEFWBUF_Msk (1UL << SCnSCB_ACTLR_DISDEFWBUF_Pos) /*!< ACTLR: DISDEFWBUF Mask */ + +#define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */ +#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** + \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[29U]; + __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ + __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ + __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TraceBusID_Pos 16U /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPrescale_Pos 8U /*!< ITM TCR: TSPrescale Position */ +#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ + +#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Integration Write Register Definitions */ +#define ITM_IWR_ATVALIDM_Pos 0U /*!< ITM IWR: ATVALIDM Position */ +#define ITM_IWR_ATVALIDM_Msk (1UL /*<< ITM_IWR_ATVALIDM_Pos*/) /*!< ITM IWR: ATVALIDM Mask */ + +/* ITM Integration Read Register Definitions */ +#define ITM_IRR_ATREADYM_Pos 0U /*!< ITM IRR: ATREADYM Position */ +#define ITM_IRR_ATREADYM_Msk (1UL /*<< ITM_IRR_ATREADYM_Pos*/) /*!< ITM IRR: ATREADYM Mask */ + +/* ITM Integration Mode Control Register Definitions */ +#define ITM_IMCR_INTEGRATION_Pos 0U /*!< ITM IMCR: INTEGRATION Position */ +#define ITM_IMCR_INTEGRATION_Msk (1UL /*<< ITM_IMCR_INTEGRATION_Pos*/) /*!< ITM IMCR: INTEGRATION Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Mask Register Definitions */ +#define DWT_MASK_MASK_Pos 0U /*!< DWT MASK: MASK Position */ +#define DWT_MASK_MASK_Msk (0x1FUL /*<< DWT_MASK_MASK_Pos*/) /*!< DWT MASK: MASK Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVADDR1_Pos 16U /*!< DWT FUNCTION: DATAVADDR1 Position */ +#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ + +#define DWT_FUNCTION_DATAVADDR0_Pos 12U /*!< DWT FUNCTION: DATAVADDR0 Position */ +#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_LNK1ENA_Pos 9U /*!< DWT FUNCTION: LNK1ENA Position */ +#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ + +#define DWT_FUNCTION_DATAVMATCH_Pos 8U /*!< DWT FUNCTION: DATAVMATCH Position */ +#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ + +#define DWT_FUNCTION_CYCMATCH_Pos 7U /*!< DWT FUNCTION: CYCMATCH Position */ +#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ + +#define DWT_FUNCTION_EMITRANGE_Pos 5U /*!< DWT FUNCTION: EMITRANGE Position */ +#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ + +#define DWT_FUNCTION_FUNCTION_Pos 0U /*!< DWT FUNCTION: FUNCTION Position */ +#define DWT_FUNCTION_FUNCTION_Msk (0xFUL /*<< DWT_FUNCTION_FUNCTION_Pos*/) /*!< DWT FUNCTION: FUNCTION Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IOM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ + __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY_Pos 0U /*!< TPI ITATBCTR2: ATREADY Position */ +#define TPI_ITATBCTR2_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY_Pos*/) /*!< TPI ITATBCTR2: ATREADY Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY_Pos 0U /*!< TPI ITATBCTR0: ATREADY Position */ +#define TPI_ITATBCTR0_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY_Pos*/) /*!< TPI ITATBCTR0: ATREADY Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x1UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_MajorType_Pos 4U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +#define TPI_DEVTYPE_SubType_Pos 0U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ +} MPU_Type; + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register Definitions */ +#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +#if (__FPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_FPU Floating Point Unit (FPU) + \brief Type definitions for the Floating Point Unit (FPU) + @{ + */ + +/** + \brief Structure type to access the Floating Point Unit (FPU). + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ + __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ + __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ + __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ +} FPU_Type; + +/* Floating-Point Context Control Register Definitions */ +#define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */ +#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */ + +#define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */ +#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */ + +#define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */ +#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */ + +#define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */ +#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */ + +#define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */ +#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */ + +#define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */ +#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */ + +#define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */ +#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */ + +#define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */ +#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */ + +#define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */ +#define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */ + +/* Floating-Point Context Address Register Definitions */ +#define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */ +#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */ + +/* Floating-Point Default Status Control Register Definitions */ +#define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */ +#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */ + +#define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */ +#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */ + +#define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */ +#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */ + +#define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */ +#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */ + +/* Media and FP Feature Register 0 Definitions */ +#define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */ +#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */ + +#define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */ +#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */ + +#define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */ +#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */ + +#define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */ +#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */ + +#define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */ +#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */ + +#define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */ +#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */ + +#define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */ +#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */ + +#define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */ +#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */ + +/* Media and FP Feature Register 1 Definitions */ +#define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */ +#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */ + +#define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */ +#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */ + +#define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */ +#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */ + +#define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */ +#define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */ + +/*@} end of group CMSIS_FPU */ +#endif + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register Definitions */ +#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Cortex-M4 Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +#if (__FPU_PRESENT == 1U) + #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ + #define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +/** + \brief Set Priority Grouping + \details Sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */ + SCB->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping + \details Reads the priority grouping field from the NVIC Interrupt Controller. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t NVIC_GetPriorityGrouping(void) +{ + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable External Interrupt + \details Enables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Disable External Interrupt + \details Disables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Get Pending Interrupt + \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t)(((NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of an external interrupt. + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of an external interrupt. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in NVIC and returns the active bit. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + */ +__STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) +{ + return((uint32_t)(((NVIC->IABR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of an interrupt. + \note The priority cannot be set for every core interrupt. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) < 0) + { + SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + NVIC->IP[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of an interrupt. + The interrupt number can be positive to specify an external (device specific) interrupt, + or negative to specify an internal (core) interrupt. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) < 0) + { + return(((uint32_t)SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)NVIC->IP[((uint32_t)(int32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__STATIC_INLINE void NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY 0x5AA55AA5U /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** + \brief ITM Send Character + \details Transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + \param [in] ch Character to transmit. + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; + } + return (ch); +} + + +/** + \brief ITM Receive Character + \details Inputs a character via the external variable \ref ITM_RxBuffer. + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) +{ + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** + \brief ITM Check Character + \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) +{ + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM4_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cm7.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cm7.h new file mode 100644 index 0000000..3b7530a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cm7.h @@ -0,0 +1,2512 @@ +/**************************************************************************//** + * @file core_cm7.h + * @brief CMSIS Cortex-M7 Core Peripheral Access Layer Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM 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: + - 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 COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (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 ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CM7_H_GENERIC +#define __CORE_CM7_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_M7 + @{ + */ + +/* CMSIS CM7 definitions */ +#define __CM7_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */ +#define __CM7_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */ +#define __CM7_CMSIS_VERSION ((__CM7_CMSIS_VERSION_MAIN << 16U) | \ + __CM7_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + +#define __CORTEX_M (0x07U) /*!< Cortex-M Core */ + + +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ + #define __STATIC_INLINE static inline + +#elif defined ( __TMS470__ ) + #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __CSMC__ ) + #define __packed + #define __ASM _asm /*!< asm keyword for COSMIC Compiler */ + #define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */ + #define __STATIC_INLINE static inline + +#else + #error Unknown compiler +#endif + +/** __FPU_USED indicates whether an FPU is used or not. + For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. +*/ +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_PCS_VFP + #if (__FPU_PRESENT == 1) + #define __FPU_USED 1U + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TMS470__ ) + #if defined __TI_VFP_SUPPORT__ + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#endif + +#include "core_cmInstr.h" /* Core Instruction Access */ +#include "core_cmFunc.h" /* Core Function Access */ +#include "core_cmSimd.h" /* Compiler specific SIMD Intrinsics */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM7_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM7_H_DEPENDANT +#define __CORE_CM7_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM7_REV + #define __CM7_REV 0x0000U + #warning "__CM7_REV not defined in device header file; using default!" + #endif + + #ifndef __FPU_PRESENT + #define __FPU_PRESENT 0U + #warning "__FPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __ICACHE_PRESENT + #define __ICACHE_PRESENT 0U + #warning "__ICACHE_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __DCACHE_PRESENT + #define __DCACHE_PRESENT 0U + #warning "__DCACHE_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __DTCM_PRESENT + #define __DTCM_PRESENT 0U + #warning "__DTCM_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 3U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex_M7 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + - Core FPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + +#define APSR_Q_Pos 27U /*!< APSR: Q Position */ +#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ + +#define APSR_GE_Pos 16U /*!< APSR: GE Position */ +#define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ +#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ + +#define xPSR_IT_Pos 25U /*!< xPSR: IT Position */ +#define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_GE_Pos 16U /*!< xPSR: GE Position */ +#define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */ + uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */ +#define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */ + +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24U]; + __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[24U]; + __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24U]; + __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24U]; + __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56U]; + __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHPR[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t ID_PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t ID_DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ID_AFR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t ID_MFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ID_ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[1U]; + __IM uint32_t CLIDR; /*!< Offset: 0x078 (R/ ) Cache Level ID register */ + __IM uint32_t CTR; /*!< Offset: 0x07C (R/ ) Cache Type register */ + __IM uint32_t CCSIDR; /*!< Offset: 0x080 (R/ ) Cache Size ID Register */ + __IOM uint32_t CSSELR; /*!< Offset: 0x084 (R/W) Cache Size Selection Register */ + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ + uint32_t RESERVED3[93U]; + __OM uint32_t STIR; /*!< Offset: 0x200 ( /W) Software Triggered Interrupt Register */ + uint32_t RESERVED4[15U]; + __IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */ + __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 1 */ + uint32_t RESERVED5[1U]; + __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */ + uint32_t RESERVED6[1U]; + __OM uint32_t ICIMVAU; /*!< Offset: 0x258 ( /W) I-Cache Invalidate by MVA to PoU */ + __OM uint32_t DCIMVAC; /*!< Offset: 0x25C ( /W) D-Cache Invalidate by MVA to PoC */ + __OM uint32_t DCISW; /*!< Offset: 0x260 ( /W) D-Cache Invalidate by Set-way */ + __OM uint32_t DCCMVAU; /*!< Offset: 0x264 ( /W) D-Cache Clean by MVA to PoU */ + __OM uint32_t DCCMVAC; /*!< Offset: 0x268 ( /W) D-Cache Clean by MVA to PoC */ + __OM uint32_t DCCSW; /*!< Offset: 0x26C ( /W) D-Cache Clean by Set-way */ + __OM uint32_t DCCIMVAC; /*!< Offset: 0x270 ( /W) D-Cache Clean and Invalidate by MVA to PoC */ + __OM uint32_t DCCISW; /*!< Offset: 0x274 ( /W) D-Cache Clean and Invalidate by Set-way */ + uint32_t RESERVED7[6U]; + __IOM uint32_t ITCMCR; /*!< Offset: 0x290 (R/W) Instruction Tightly-Coupled Memory Control Register */ + __IOM uint32_t DTCMCR; /*!< Offset: 0x294 (R/W) Data Tightly-Coupled Memory Control Registers */ + __IOM uint32_t AHBPCR; /*!< Offset: 0x298 (R/W) AHBP Control Register */ + __IOM uint32_t CACR; /*!< Offset: 0x29C (R/W) L1 Cache Control Register */ + __IOM uint32_t AHBSCR; /*!< Offset: 0x2A0 (R/W) AHB Slave Control Register */ + uint32_t RESERVED8[1U]; + __IOM uint32_t ABFSR; /*!< Offset: 0x2A8 (R/W) Auxiliary Bus Fault Status Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +#define SCB_AIRCR_VECTRESET_Pos 0U /*!< SCB AIRCR: VECTRESET Position */ +#define SCB_AIRCR_VECTRESET_Msk (1UL /*<< SCB_AIRCR_VECTRESET_Pos*/) /*!< SCB AIRCR: VECTRESET Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_BP_Pos 18U /*!< SCB CCR: Branch prediction enable bit Position */ +#define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: Branch prediction enable bit Mask */ + +#define SCB_CCR_IC_Pos 17U /*!< SCB CCR: Instruction cache enable bit Position */ +#define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: Instruction cache enable bit Mask */ + +#define SCB_CCR_DC_Pos 16U /*!< SCB CCR: Cache enable bit Position */ +#define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: Cache enable bit Mask */ + +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +#define SCB_CCR_NONBASETHRDENA_Pos 0U /*!< SCB CCR: NONBASETHRDENA Position */ +#define SCB_CCR_NONBASETHRDENA_Msk (1UL /*<< SCB_CCR_NONBASETHRDENA_Pos*/) /*!< SCB CCR: NONBASETHRDENA Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Register Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* SCB Hard Fault Status Register Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ + +/* SCB Cache Level ID Register Definitions */ +#define SCB_CLIDR_LOUU_Pos 27U /*!< SCB CLIDR: LoUU Position */ +#define SCB_CLIDR_LOUU_Msk (7UL << SCB_CLIDR_LOUU_Pos) /*!< SCB CLIDR: LoUU Mask */ + +#define SCB_CLIDR_LOC_Pos 24U /*!< SCB CLIDR: LoC Position */ +#define SCB_CLIDR_LOC_Msk (7UL << SCB_CLIDR_LOC_Pos) /*!< SCB CLIDR: LoC Mask */ + +/* SCB Cache Type Register Definitions */ +#define SCB_CTR_FORMAT_Pos 29U /*!< SCB CTR: Format Position */ +#define SCB_CTR_FORMAT_Msk (7UL << SCB_CTR_FORMAT_Pos) /*!< SCB CTR: Format Mask */ + +#define SCB_CTR_CWG_Pos 24U /*!< SCB CTR: CWG Position */ +#define SCB_CTR_CWG_Msk (0xFUL << SCB_CTR_CWG_Pos) /*!< SCB CTR: CWG Mask */ + +#define SCB_CTR_ERG_Pos 20U /*!< SCB CTR: ERG Position */ +#define SCB_CTR_ERG_Msk (0xFUL << SCB_CTR_ERG_Pos) /*!< SCB CTR: ERG Mask */ + +#define SCB_CTR_DMINLINE_Pos 16U /*!< SCB CTR: DminLine Position */ +#define SCB_CTR_DMINLINE_Msk (0xFUL << SCB_CTR_DMINLINE_Pos) /*!< SCB CTR: DminLine Mask */ + +#define SCB_CTR_IMINLINE_Pos 0U /*!< SCB CTR: ImInLine Position */ +#define SCB_CTR_IMINLINE_Msk (0xFUL /*<< SCB_CTR_IMINLINE_Pos*/) /*!< SCB CTR: ImInLine Mask */ + +/* SCB Cache Size ID Register Definitions */ +#define SCB_CCSIDR_WT_Pos 31U /*!< SCB CCSIDR: WT Position */ +#define SCB_CCSIDR_WT_Msk (1UL << SCB_CCSIDR_WT_Pos) /*!< SCB CCSIDR: WT Mask */ + +#define SCB_CCSIDR_WB_Pos 30U /*!< SCB CCSIDR: WB Position */ +#define SCB_CCSIDR_WB_Msk (1UL << SCB_CCSIDR_WB_Pos) /*!< SCB CCSIDR: WB Mask */ + +#define SCB_CCSIDR_RA_Pos 29U /*!< SCB CCSIDR: RA Position */ +#define SCB_CCSIDR_RA_Msk (1UL << SCB_CCSIDR_RA_Pos) /*!< SCB CCSIDR: RA Mask */ + +#define SCB_CCSIDR_WA_Pos 28U /*!< SCB CCSIDR: WA Position */ +#define SCB_CCSIDR_WA_Msk (1UL << SCB_CCSIDR_WA_Pos) /*!< SCB CCSIDR: WA Mask */ + +#define SCB_CCSIDR_NUMSETS_Pos 13U /*!< SCB CCSIDR: NumSets Position */ +#define SCB_CCSIDR_NUMSETS_Msk (0x7FFFUL << SCB_CCSIDR_NUMSETS_Pos) /*!< SCB CCSIDR: NumSets Mask */ + +#define SCB_CCSIDR_ASSOCIATIVITY_Pos 3U /*!< SCB CCSIDR: Associativity Position */ +#define SCB_CCSIDR_ASSOCIATIVITY_Msk (0x3FFUL << SCB_CCSIDR_ASSOCIATIVITY_Pos) /*!< SCB CCSIDR: Associativity Mask */ + +#define SCB_CCSIDR_LINESIZE_Pos 0U /*!< SCB CCSIDR: LineSize Position */ +#define SCB_CCSIDR_LINESIZE_Msk (7UL /*<< SCB_CCSIDR_LINESIZE_Pos*/) /*!< SCB CCSIDR: LineSize Mask */ + +/* SCB Cache Size Selection Register Definitions */ +#define SCB_CSSELR_LEVEL_Pos 1U /*!< SCB CSSELR: Level Position */ +#define SCB_CSSELR_LEVEL_Msk (7UL << SCB_CSSELR_LEVEL_Pos) /*!< SCB CSSELR: Level Mask */ + +#define SCB_CSSELR_IND_Pos 0U /*!< SCB CSSELR: InD Position */ +#define SCB_CSSELR_IND_Msk (1UL /*<< SCB_CSSELR_IND_Pos*/) /*!< SCB CSSELR: InD Mask */ + +/* SCB Software Triggered Interrupt Register Definitions */ +#define SCB_STIR_INTID_Pos 0U /*!< SCB STIR: INTID Position */ +#define SCB_STIR_INTID_Msk (0x1FFUL /*<< SCB_STIR_INTID_Pos*/) /*!< SCB STIR: INTID Mask */ + +/* SCB D-Cache Invalidate by Set-way Register Definitions */ +#define SCB_DCISW_WAY_Pos 30U /*!< SCB DCISW: Way Position */ +#define SCB_DCISW_WAY_Msk (3UL << SCB_DCISW_WAY_Pos) /*!< SCB DCISW: Way Mask */ + +#define SCB_DCISW_SET_Pos 5U /*!< SCB DCISW: Set Position */ +#define SCB_DCISW_SET_Msk (0x1FFUL << SCB_DCISW_SET_Pos) /*!< SCB DCISW: Set Mask */ + +/* SCB D-Cache Clean by Set-way Register Definitions */ +#define SCB_DCCSW_WAY_Pos 30U /*!< SCB DCCSW: Way Position */ +#define SCB_DCCSW_WAY_Msk (3UL << SCB_DCCSW_WAY_Pos) /*!< SCB DCCSW: Way Mask */ + +#define SCB_DCCSW_SET_Pos 5U /*!< SCB DCCSW: Set Position */ +#define SCB_DCCSW_SET_Msk (0x1FFUL << SCB_DCCSW_SET_Pos) /*!< SCB DCCSW: Set Mask */ + +/* SCB D-Cache Clean and Invalidate by Set-way Register Definitions */ +#define SCB_DCCISW_WAY_Pos 30U /*!< SCB DCCISW: Way Position */ +#define SCB_DCCISW_WAY_Msk (3UL << SCB_DCCISW_WAY_Pos) /*!< SCB DCCISW: Way Mask */ + +#define SCB_DCCISW_SET_Pos 5U /*!< SCB DCCISW: Set Position */ +#define SCB_DCCISW_SET_Msk (0x1FFUL << SCB_DCCISW_SET_Pos) /*!< SCB DCCISW: Set Mask */ + +/* Instruction Tightly-Coupled Memory Control Register Definitions */ +#define SCB_ITCMCR_SZ_Pos 3U /*!< SCB ITCMCR: SZ Position */ +#define SCB_ITCMCR_SZ_Msk (0xFUL << SCB_ITCMCR_SZ_Pos) /*!< SCB ITCMCR: SZ Mask */ + +#define SCB_ITCMCR_RETEN_Pos 2U /*!< SCB ITCMCR: RETEN Position */ +#define SCB_ITCMCR_RETEN_Msk (1UL << SCB_ITCMCR_RETEN_Pos) /*!< SCB ITCMCR: RETEN Mask */ + +#define SCB_ITCMCR_RMW_Pos 1U /*!< SCB ITCMCR: RMW Position */ +#define SCB_ITCMCR_RMW_Msk (1UL << SCB_ITCMCR_RMW_Pos) /*!< SCB ITCMCR: RMW Mask */ + +#define SCB_ITCMCR_EN_Pos 0U /*!< SCB ITCMCR: EN Position */ +#define SCB_ITCMCR_EN_Msk (1UL /*<< SCB_ITCMCR_EN_Pos*/) /*!< SCB ITCMCR: EN Mask */ + +/* Data Tightly-Coupled Memory Control Register Definitions */ +#define SCB_DTCMCR_SZ_Pos 3U /*!< SCB DTCMCR: SZ Position */ +#define SCB_DTCMCR_SZ_Msk (0xFUL << SCB_DTCMCR_SZ_Pos) /*!< SCB DTCMCR: SZ Mask */ + +#define SCB_DTCMCR_RETEN_Pos 2U /*!< SCB DTCMCR: RETEN Position */ +#define SCB_DTCMCR_RETEN_Msk (1UL << SCB_DTCMCR_RETEN_Pos) /*!< SCB DTCMCR: RETEN Mask */ + +#define SCB_DTCMCR_RMW_Pos 1U /*!< SCB DTCMCR: RMW Position */ +#define SCB_DTCMCR_RMW_Msk (1UL << SCB_DTCMCR_RMW_Pos) /*!< SCB DTCMCR: RMW Mask */ + +#define SCB_DTCMCR_EN_Pos 0U /*!< SCB DTCMCR: EN Position */ +#define SCB_DTCMCR_EN_Msk (1UL /*<< SCB_DTCMCR_EN_Pos*/) /*!< SCB DTCMCR: EN Mask */ + +/* AHBP Control Register Definitions */ +#define SCB_AHBPCR_SZ_Pos 1U /*!< SCB AHBPCR: SZ Position */ +#define SCB_AHBPCR_SZ_Msk (7UL << SCB_AHBPCR_SZ_Pos) /*!< SCB AHBPCR: SZ Mask */ + +#define SCB_AHBPCR_EN_Pos 0U /*!< SCB AHBPCR: EN Position */ +#define SCB_AHBPCR_EN_Msk (1UL /*<< SCB_AHBPCR_EN_Pos*/) /*!< SCB AHBPCR: EN Mask */ + +/* L1 Cache Control Register Definitions */ +#define SCB_CACR_FORCEWT_Pos 2U /*!< SCB CACR: FORCEWT Position */ +#define SCB_CACR_FORCEWT_Msk (1UL << SCB_CACR_FORCEWT_Pos) /*!< SCB CACR: FORCEWT Mask */ + +#define SCB_CACR_ECCEN_Pos 1U /*!< SCB CACR: ECCEN Position */ +#define SCB_CACR_ECCEN_Msk (1UL << SCB_CACR_ECCEN_Pos) /*!< SCB CACR: ECCEN Mask */ + +#define SCB_CACR_SIWT_Pos 0U /*!< SCB CACR: SIWT Position */ +#define SCB_CACR_SIWT_Msk (1UL /*<< SCB_CACR_SIWT_Pos*/) /*!< SCB CACR: SIWT Mask */ + +/* AHBS Control Register Definitions */ +#define SCB_AHBSCR_INITCOUNT_Pos 11U /*!< SCB AHBSCR: INITCOUNT Position */ +#define SCB_AHBSCR_INITCOUNT_Msk (0x1FUL << SCB_AHBPCR_INITCOUNT_Pos) /*!< SCB AHBSCR: INITCOUNT Mask */ + +#define SCB_AHBSCR_TPRI_Pos 2U /*!< SCB AHBSCR: TPRI Position */ +#define SCB_AHBSCR_TPRI_Msk (0x1FFUL << SCB_AHBPCR_TPRI_Pos) /*!< SCB AHBSCR: TPRI Mask */ + +#define SCB_AHBSCR_CTL_Pos 0U /*!< SCB AHBSCR: CTL Position*/ +#define SCB_AHBSCR_CTL_Msk (3UL /*<< SCB_AHBPCR_CTL_Pos*/) /*!< SCB AHBSCR: CTL Mask */ + +/* Auxiliary Bus Fault Status Register Definitions */ +#define SCB_ABFSR_AXIMTYPE_Pos 8U /*!< SCB ABFSR: AXIMTYPE Position*/ +#define SCB_ABFSR_AXIMTYPE_Msk (3UL << SCB_ABFSR_AXIMTYPE_Pos) /*!< SCB ABFSR: AXIMTYPE Mask */ + +#define SCB_ABFSR_EPPB_Pos 4U /*!< SCB ABFSR: EPPB Position*/ +#define SCB_ABFSR_EPPB_Msk (1UL << SCB_ABFSR_EPPB_Pos) /*!< SCB ABFSR: EPPB Mask */ + +#define SCB_ABFSR_AXIM_Pos 3U /*!< SCB ABFSR: AXIM Position*/ +#define SCB_ABFSR_AXIM_Msk (1UL << SCB_ABFSR_AXIM_Pos) /*!< SCB ABFSR: AXIM Mask */ + +#define SCB_ABFSR_AHBP_Pos 2U /*!< SCB ABFSR: AHBP Position*/ +#define SCB_ABFSR_AHBP_Msk (1UL << SCB_ABFSR_AHBP_Pos) /*!< SCB ABFSR: AHBP Mask */ + +#define SCB_ABFSR_DTCM_Pos 1U /*!< SCB ABFSR: DTCM Position*/ +#define SCB_ABFSR_DTCM_Msk (1UL << SCB_ABFSR_DTCM_Pos) /*!< SCB ABFSR: DTCM Mask */ + +#define SCB_ABFSR_ITCM_Pos 0U /*!< SCB ABFSR: ITCM Position*/ +#define SCB_ABFSR_ITCM_Msk (1UL /*<< SCB_ABFSR_ITCM_Pos*/) /*!< SCB ABFSR: ITCM Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ + +/* Auxiliary Control Register Definitions */ +#define SCnSCB_ACTLR_DISITMATBFLUSH_Pos 12U /*!< ACTLR: DISITMATBFLUSH Position */ +#define SCnSCB_ACTLR_DISITMATBFLUSH_Msk (1UL << SCnSCB_ACTLR_DISITMATBFLUSH_Pos) /*!< ACTLR: DISITMATBFLUSH Mask */ + +#define SCnSCB_ACTLR_DISRAMODE_Pos 11U /*!< ACTLR: DISRAMODE Position */ +#define SCnSCB_ACTLR_DISRAMODE_Msk (1UL << SCnSCB_ACTLR_DISRAMODE_Pos) /*!< ACTLR: DISRAMODE Mask */ + +#define SCnSCB_ACTLR_FPEXCODIS_Pos 10U /*!< ACTLR: FPEXCODIS Position */ +#define SCnSCB_ACTLR_FPEXCODIS_Msk (1UL << SCnSCB_ACTLR_FPEXCODIS_Pos) /*!< ACTLR: FPEXCODIS Mask */ + +#define SCnSCB_ACTLR_DISFOLD_Pos 2U /*!< ACTLR: DISFOLD Position */ +#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ + +#define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */ +#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** + \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[29U]; + __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ + __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ + __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TraceBusID_Pos 16U /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPrescale_Pos 8U /*!< ITM TCR: TSPrescale Position */ +#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ + +#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Integration Write Register Definitions */ +#define ITM_IWR_ATVALIDM_Pos 0U /*!< ITM IWR: ATVALIDM Position */ +#define ITM_IWR_ATVALIDM_Msk (1UL /*<< ITM_IWR_ATVALIDM_Pos*/) /*!< ITM IWR: ATVALIDM Mask */ + +/* ITM Integration Read Register Definitions */ +#define ITM_IRR_ATREADYM_Pos 0U /*!< ITM IRR: ATREADYM Position */ +#define ITM_IRR_ATREADYM_Msk (1UL /*<< ITM_IRR_ATREADYM_Pos*/) /*!< ITM IRR: ATREADYM Mask */ + +/* ITM Integration Mode Control Register Definitions */ +#define ITM_IMCR_INTEGRATION_Pos 0U /*!< ITM IMCR: INTEGRATION Position */ +#define ITM_IMCR_INTEGRATION_Msk (1UL /*<< ITM_IMCR_INTEGRATION_Pos*/) /*!< ITM IMCR: INTEGRATION Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ + uint32_t RESERVED3[981U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( W) Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R ) Lock Status Register */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Mask Register Definitions */ +#define DWT_MASK_MASK_Pos 0U /*!< DWT MASK: MASK Position */ +#define DWT_MASK_MASK_Msk (0x1FUL /*<< DWT_MASK_MASK_Pos*/) /*!< DWT MASK: MASK Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVADDR1_Pos 16U /*!< DWT FUNCTION: DATAVADDR1 Position */ +#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ + +#define DWT_FUNCTION_DATAVADDR0_Pos 12U /*!< DWT FUNCTION: DATAVADDR0 Position */ +#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_LNK1ENA_Pos 9U /*!< DWT FUNCTION: LNK1ENA Position */ +#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ + +#define DWT_FUNCTION_DATAVMATCH_Pos 8U /*!< DWT FUNCTION: DATAVMATCH Position */ +#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ + +#define DWT_FUNCTION_CYCMATCH_Pos 7U /*!< DWT FUNCTION: CYCMATCH Position */ +#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ + +#define DWT_FUNCTION_EMITRANGE_Pos 5U /*!< DWT FUNCTION: EMITRANGE Position */ +#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ + +#define DWT_FUNCTION_FUNCTION_Pos 0U /*!< DWT FUNCTION: FUNCTION Position */ +#define DWT_FUNCTION_FUNCTION_Msk (0xFUL /*<< DWT_FUNCTION_FUNCTION_Pos*/) /*!< DWT FUNCTION: FUNCTION Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IOM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ + __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY_Pos 0U /*!< TPI ITATBCTR2: ATREADY Position */ +#define TPI_ITATBCTR2_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY_Pos*/) /*!< TPI ITATBCTR2: ATREADY Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY_Pos 0U /*!< TPI ITATBCTR0: ATREADY Position */ +#define TPI_ITATBCTR0_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY_Pos*/) /*!< TPI ITATBCTR0: ATREADY Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x1UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_MajorType_Pos 4U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +#define TPI_DEVTYPE_SubType_Pos 0U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ +} MPU_Type; + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register Definitions */ +#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +#if (__FPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_FPU Floating Point Unit (FPU) + \brief Type definitions for the Floating Point Unit (FPU) + @{ + */ + +/** + \brief Structure type to access the Floating Point Unit (FPU). + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ + __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ + __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ + __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ + __IM uint32_t MVFR2; /*!< Offset: 0x018 (R/ ) Media and FP Feature Register 2 */ +} FPU_Type; + +/* Floating-Point Context Control Register Definitions */ +#define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */ +#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */ + +#define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */ +#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */ + +#define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */ +#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */ + +#define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */ +#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */ + +#define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */ +#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */ + +#define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */ +#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */ + +#define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */ +#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */ + +#define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */ +#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */ + +#define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */ +#define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */ + +/* Floating-Point Context Address Register Definitions */ +#define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */ +#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */ + +/* Floating-Point Default Status Control Register Definitions */ +#define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */ +#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */ + +#define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */ +#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */ + +#define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */ +#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */ + +#define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */ +#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */ + +/* Media and FP Feature Register 0 Definitions */ +#define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */ +#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */ + +#define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */ +#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */ + +#define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */ +#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */ + +#define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */ +#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */ + +#define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */ +#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */ + +#define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */ +#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */ + +#define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */ +#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */ + +#define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */ +#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */ + +/* Media and FP Feature Register 1 Definitions */ +#define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */ +#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */ + +#define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */ +#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */ + +#define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */ +#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */ + +#define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */ +#define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */ + +/* Media and FP Feature Register 2 Definitions */ + +/*@} end of group CMSIS_FPU */ +#endif + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register Definitions */ +#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Cortex-M4 Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +#if (__FPU_PRESENT == 1U) + #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ + #define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +/** + \brief Set Priority Grouping + \details Sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */ + SCB->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping + \details Reads the priority grouping field from the NVIC Interrupt Controller. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t NVIC_GetPriorityGrouping(void) +{ + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable External Interrupt + \details Enables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Disable External Interrupt + \details Disables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Get Pending Interrupt + \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t)(((NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of an external interrupt. + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of an external interrupt. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in NVIC and returns the active bit. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + */ +__STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) +{ + return((uint32_t)(((NVIC->IABR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of an interrupt. + \note The priority cannot be set for every core interrupt. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) < 0) + { + SCB->SHPR[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + NVIC->IP[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of an interrupt. + The interrupt number can be positive to specify an external (device specific) interrupt, + or negative to specify an internal (core) interrupt. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) < 0) + { + return(((uint32_t)SCB->SHPR[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)NVIC->IP[((uint32_t)(int32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__STATIC_INLINE void NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + uint32_t mvfr0; + + mvfr0 = SCB->MVFR0; + if ((mvfr0 & 0x00000FF0UL) == 0x220UL) + { + return 2UL; /* Double + Single precision FPU */ + } + else if ((mvfr0 & 0x00000FF0UL) == 0x020UL) + { + return 1UL; /* Single precision FPU */ + } + else + { + return 0UL; /* No FPU */ + } +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + + + +/* ########################## Cache functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_CacheFunctions Cache Functions + \brief Functions that configure Instruction and Data cache. + @{ + */ + +/* Cache Size ID Register Macros */ +#define CCSIDR_WAYS(x) (((x) & SCB_CCSIDR_ASSOCIATIVITY_Msk) >> SCB_CCSIDR_ASSOCIATIVITY_Pos) +#define CCSIDR_SETS(x) (((x) & SCB_CCSIDR_NUMSETS_Msk ) >> SCB_CCSIDR_NUMSETS_Pos ) + + +/** + \brief Enable I-Cache + \details Turns on I-Cache + */ +__STATIC_INLINE void SCB_EnableICache (void) +{ + #if (__ICACHE_PRESENT == 1U) + __DSB(); + __ISB(); + SCB->ICIALLU = 0UL; /* invalidate I-Cache */ + SCB->CCR |= (uint32_t)SCB_CCR_IC_Msk; /* enable I-Cache */ + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Disable I-Cache + \details Turns off I-Cache + */ +__STATIC_INLINE void SCB_DisableICache (void) +{ + #if (__ICACHE_PRESENT == 1U) + __DSB(); + __ISB(); + SCB->CCR &= ~(uint32_t)SCB_CCR_IC_Msk; /* disable I-Cache */ + SCB->ICIALLU = 0UL; /* invalidate I-Cache */ + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Invalidate I-Cache + \details Invalidates I-Cache + */ +__STATIC_INLINE void SCB_InvalidateICache (void) +{ + #if (__ICACHE_PRESENT == 1U) + __DSB(); + __ISB(); + SCB->ICIALLU = 0UL; + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Enable D-Cache + \details Turns on D-Cache + */ +__STATIC_INLINE void SCB_EnableDCache (void) +{ + #if (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + SCB->CSSELR = (0U << 1U) | 0U; /* Level 1 data cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + /* invalidate D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCISW = (((sets << SCB_DCISW_SET_Pos) & SCB_DCISW_SET_Msk) | + ((ways << SCB_DCISW_WAY_Pos) & SCB_DCISW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways--); + } while(sets--); + __DSB(); + + SCB->CCR |= (uint32_t)SCB_CCR_DC_Msk; /* enable D-Cache */ + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Disable D-Cache + \details Turns off D-Cache + */ +__STATIC_INLINE void SCB_DisableDCache (void) +{ + #if (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + SCB->CSSELR = (0U << 1U) | 0U; /* Level 1 data cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + SCB->CCR &= ~(uint32_t)SCB_CCR_DC_Msk; /* disable D-Cache */ + + /* clean & invalidate D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCCISW = (((sets << SCB_DCCISW_SET_Pos) & SCB_DCCISW_SET_Msk) | + ((ways << SCB_DCCISW_WAY_Pos) & SCB_DCCISW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways--); + } while(sets--); + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Invalidate D-Cache + \details Invalidates D-Cache + */ +__STATIC_INLINE void SCB_InvalidateDCache (void) +{ + #if (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + SCB->CSSELR = (0U << 1U) | 0U; /* Level 1 data cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + /* invalidate D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCISW = (((sets << SCB_DCISW_SET_Pos) & SCB_DCISW_SET_Msk) | + ((ways << SCB_DCISW_WAY_Pos) & SCB_DCISW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways--); + } while(sets--); + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Clean D-Cache + \details Cleans D-Cache + */ +__STATIC_INLINE void SCB_CleanDCache (void) +{ + #if (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + SCB->CSSELR = (0U << 1U) | 0U; /* Level 1 data cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + /* clean D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCCSW = (((sets << SCB_DCCSW_SET_Pos) & SCB_DCCSW_SET_Msk) | + ((ways << SCB_DCCSW_WAY_Pos) & SCB_DCCSW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways--); + } while(sets--); + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Clean & Invalidate D-Cache + \details Cleans and Invalidates D-Cache + */ +__STATIC_INLINE void SCB_CleanInvalidateDCache (void) +{ + #if (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + SCB->CSSELR = (0U << 1U) | 0U; /* Level 1 data cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + /* clean & invalidate D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCCISW = (((sets << SCB_DCCISW_SET_Pos) & SCB_DCCISW_SET_Msk) | + ((ways << SCB_DCCISW_WAY_Pos) & SCB_DCCISW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways--); + } while(sets--); + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief D-Cache Invalidate by address + \details Invalidates D-Cache for the given address + \param[in] addr address (aligned to 32-byte boundary) + \param[in] dsize size of memory block (in number of bytes) +*/ +__STATIC_INLINE void SCB_InvalidateDCache_by_Addr (uint32_t *addr, int32_t dsize) +{ + #if (__DCACHE_PRESENT == 1U) + int32_t op_size = dsize; + uint32_t op_addr = (uint32_t)addr; + int32_t linesize = 32U; /* in Cortex-M7 size of cache line is fixed to 8 words (32 bytes) */ + + __DSB(); + + while (op_size > 0) { + SCB->DCIMVAC = op_addr; + op_addr += linesize; + op_size -= linesize; + } + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief D-Cache Clean by address + \details Cleans D-Cache for the given address + \param[in] addr address (aligned to 32-byte boundary) + \param[in] dsize size of memory block (in number of bytes) +*/ +__STATIC_INLINE void SCB_CleanDCache_by_Addr (uint32_t *addr, int32_t dsize) +{ + #if (__DCACHE_PRESENT == 1) + int32_t op_size = dsize; + uint32_t op_addr = (uint32_t) addr; + int32_t linesize = 32U; /* in Cortex-M7 size of cache line is fixed to 8 words (32 bytes) */ + + __DSB(); + + while (op_size > 0) { + SCB->DCCMVAC = op_addr; + op_addr += linesize; + op_size -= linesize; + } + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief D-Cache Clean and Invalidate by address + \details Cleans and invalidates D_Cache for the given address + \param[in] addr address (aligned to 32-byte boundary) + \param[in] dsize size of memory block (in number of bytes) +*/ +__STATIC_INLINE void SCB_CleanInvalidateDCache_by_Addr (uint32_t *addr, int32_t dsize) +{ + #if (__DCACHE_PRESENT == 1U) + int32_t op_size = dsize; + uint32_t op_addr = (uint32_t) addr; + int32_t linesize = 32U; /* in Cortex-M7 size of cache line is fixed to 8 words (32 bytes) */ + + __DSB(); + + while (op_size > 0) { + SCB->DCCIMVAC = op_addr; + op_addr += linesize; + op_size -= linesize; + } + + __DSB(); + __ISB(); + #endif +} + + +/*@} end of CMSIS_Core_CacheFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY 0x5AA55AA5U /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** + \brief ITM Send Character + \details Transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + \param [in] ch Character to transmit. + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; + } + return (ch); +} + + +/** + \brief ITM Receive Character + \details Inputs a character via the external variable \ref ITM_RxBuffer. + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) +{ + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** + \brief ITM Check Character + \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) +{ + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM7_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cmFunc.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cmFunc.h new file mode 100644 index 0000000..652a48a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cmFunc.h @@ -0,0 +1,87 @@ +/**************************************************************************//** + * @file core_cmFunc.h + * @brief CMSIS Cortex-M Core Function Access Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM 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: + - 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 COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (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 ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CMFUNC_H +#define __CORE_CMFUNC_H + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ +*/ + +/*------------------ RealView Compiler -----------------*/ +#if defined ( __CC_ARM ) + #include "cmsis_armcc.h" + +/*------------------ ARM Compiler V6 -------------------*/ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #include "cmsis_armcc_V6.h" + +/*------------------ GNU Compiler ----------------------*/ +#elif defined ( __GNUC__ ) + #include "cmsis_gcc.h" + +/*------------------ ICC Compiler ----------------------*/ +#elif defined ( __ICCARM__ ) + #include + +/*------------------ TI CCS Compiler -------------------*/ +#elif defined ( __TMS470__ ) + #include + +/*------------------ TASKING Compiler ------------------*/ +#elif defined ( __TASKING__ ) + /* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all intrinsics, + * Including the CMSIS ones. + */ + +/*------------------ COSMIC Compiler -------------------*/ +#elif defined ( __CSMC__ ) + #include + +#endif + +/*@} end of CMSIS_Core_RegAccFunctions */ + +#endif /* __CORE_CMFUNC_H */ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cmInstr.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cmInstr.h new file mode 100644 index 0000000..f474b0e --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cmInstr.h @@ -0,0 +1,87 @@ +/**************************************************************************//** + * @file core_cmInstr.h + * @brief CMSIS Cortex-M Core Instruction Access Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM 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: + - 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 COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (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 ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CMINSTR_H +#define __CORE_CMINSTR_H + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/*------------------ RealView Compiler -----------------*/ +#if defined ( __CC_ARM ) + #include "cmsis_armcc.h" + +/*------------------ ARM Compiler V6 -------------------*/ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #include "cmsis_armcc_V6.h" + +/*------------------ GNU Compiler ----------------------*/ +#elif defined ( __GNUC__ ) + #include "cmsis_gcc.h" + +/*------------------ ICC Compiler ----------------------*/ +#elif defined ( __ICCARM__ ) + #include + +/*------------------ TI CCS Compiler -------------------*/ +#elif defined ( __TMS470__ ) + #include + +/*------------------ TASKING Compiler ------------------*/ +#elif defined ( __TASKING__ ) + /* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all intrinsics, + * Including the CMSIS ones. + */ + +/*------------------ COSMIC Compiler -------------------*/ +#elif defined ( __CSMC__ ) + #include + +#endif + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + +#endif /* __CORE_CMINSTR_H */ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cmSimd.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cmSimd.h new file mode 100644 index 0000000..66bf5c2 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_cmSimd.h @@ -0,0 +1,96 @@ +/**************************************************************************//** + * @file core_cmSimd.h + * @brief CMSIS Cortex-M SIMD Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM 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: + - 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 COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (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 ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CMSIMD_H +#define __CORE_CMSIMD_H + +#ifdef __cplusplus + extern "C" { +#endif + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +/*------------------ RealView Compiler -----------------*/ +#if defined ( __CC_ARM ) + #include "cmsis_armcc.h" + +/*------------------ ARM Compiler V6 -------------------*/ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #include "cmsis_armcc_V6.h" + +/*------------------ GNU Compiler ----------------------*/ +#elif defined ( __GNUC__ ) + #include "cmsis_gcc.h" + +/*------------------ ICC Compiler ----------------------*/ +#elif defined ( __ICCARM__ ) + #include + +/*------------------ TI CCS Compiler -------------------*/ +#elif defined ( __TMS470__ ) + #include + +/*------------------ TASKING Compiler ------------------*/ +#elif defined ( __TASKING__ ) + /* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all intrinsics, + * Including the CMSIS ones. + */ + +/*------------------ COSMIC Compiler -------------------*/ +#elif defined ( __CSMC__ ) + #include + +#endif + +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CMSIMD_H */ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_sc000.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_sc000.h new file mode 100644 index 0000000..514dbd8 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_sc000.h @@ -0,0 +1,926 @@ +/**************************************************************************//** + * @file core_sc000.h + * @brief CMSIS SC000 Core Peripheral Access Layer Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM 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: + - 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 COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (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 ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_SC000_H_GENERIC +#define __CORE_SC000_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup SC000 + @{ + */ + +/* CMSIS SC000 definitions */ +#define __SC000_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */ +#define __SC000_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */ +#define __SC000_CMSIS_VERSION ((__SC000_CMSIS_VERSION_MAIN << 16U) | \ + __SC000_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + +#define __CORTEX_SC (000U) /*!< Cortex secure core */ + + +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ + #define __STATIC_INLINE static inline + +#elif defined ( __TMS470__ ) + #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __CSMC__ ) + #define __packed + #define __ASM _asm /*!< asm keyword for COSMIC Compiler */ + #define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */ + #define __STATIC_INLINE static inline + +#else + #error Unknown compiler +#endif + +/** __FPU_USED indicates whether an FPU is used or not. + This core does not support an FPU at all +*/ +#define __FPU_USED 0U + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_PCS_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TMS470__ ) + #if defined __TI_VFP_SUPPORT__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#endif + +#include "core_cmInstr.h" /* Core Instruction Access */ +#include "core_cmFunc.h" /* Core Function Access */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_SC000_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_SC000_H_DEPENDANT +#define __CORE_SC000_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __SC000_REV + #define __SC000_REV 0x0000U + #warning "__SC000_REV not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 2U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group SC000 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core MPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t _reserved0:1; /*!< bit: 0 Reserved */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[31U]; + __IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[31U]; + __IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[31U]; + __IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[31U]; + uint32_t RESERVED4[64U]; + __IOM uint32_t IP[8U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */ +} NVIC_Type; + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + uint32_t RESERVED0[1U]; + __IOM uint32_t SHP[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + uint32_t RESERVED1[154U]; + __IOM uint32_t SFCR; /*!< Offset: 0x290 (R/W) Security Features Control Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +} SCnSCB_Type; + +/* Auxiliary Control Register Definitions */ +#define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */ +#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + +#if (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ +} MPU_Type; + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_ADDR_Pos 8U /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0xFFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register Definitions */ +#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief SC000 Core Debug Registers (DCB registers, SHCSR, and DFSR) are only accessible over DAP and not via processor. + Therefore they are not covered by the SC000 header file. + @{ + */ +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of SC000 Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ + +#if (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +/* Interrupt Priorities are WORD accessible only under ARMv6M */ +/* The following MACROS handle generation of the register offset and byte masks */ +#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL) +#define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) ) +#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) ) + + +/** + \brief Enable External Interrupt + \details Enables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Disable External Interrupt + \details Disables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Get Pending Interrupt + \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of an external interrupt. + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of an external interrupt. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of an interrupt. + \note The priority cannot be set for every core interrupt. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) < 0) + { + SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } + else + { + NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of an interrupt. + The interrupt number can be positive to specify an external (device specific) interrupt, + or negative to specify an internal (core) interrupt. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) < 0) + { + return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__STATIC_INLINE void NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + SCB_AIRCR_SYSRESETREQ_Msk); + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_SC000_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_sc300.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_sc300.h new file mode 100644 index 0000000..8bd18aa --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/CMSIS/Include/core_sc300.h @@ -0,0 +1,1745 @@ +/**************************************************************************//** + * @file core_sc300.h + * @brief CMSIS SC300 Core Peripheral Access Layer Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM 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: + - 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 COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (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 ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_SC300_H_GENERIC +#define __CORE_SC300_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup SC3000 + @{ + */ + +/* CMSIS SC300 definitions */ +#define __SC300_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */ +#define __SC300_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */ +#define __SC300_CMSIS_VERSION ((__SC300_CMSIS_VERSION_MAIN << 16U) | \ + __SC300_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + +#define __CORTEX_SC (300U) /*!< Cortex secure core */ + + +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ + #define __STATIC_INLINE static inline + +#elif defined ( __TMS470__ ) + #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __CSMC__ ) + #define __packed + #define __ASM _asm /*!< asm keyword for COSMIC Compiler */ + #define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */ + #define __STATIC_INLINE static inline + +#else + #error Unknown compiler +#endif + +/** __FPU_USED indicates whether an FPU is used or not. + This core does not support an FPU at all +*/ +#define __FPU_USED 0U + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_PCS_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TMS470__ ) + #if defined __TI_VFP_SUPPORT__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#endif + +#include "core_cmInstr.h" /* Core Instruction Access */ +#include "core_cmFunc.h" /* Core Function Access */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_SC300_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_SC300_H_DEPENDANT +#define __CORE_SC300_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __SC300_REV + #define __SC300_REV 0x0000U + #warning "__SC300_REV not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 4U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group SC300 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + +#define APSR_Q_Pos 27U /*!< APSR: Q Position */ +#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ +#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ + +#define xPSR_IT_Pos 25U /*!< xPSR: IT Position */ +#define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24U]; + __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[24U]; + __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24U]; + __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24U]; + __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56U]; + __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHP[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[5U]; + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ + uint32_t RESERVED1[129U]; + __IOM uint32_t SFCR; /*!< Offset: 0x290 (R/W) Security Features Control Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLBASE_Pos 29U /*!< SCB VTOR: TBLBASE Position */ +#define SCB_VTOR_TBLBASE_Msk (1UL << SCB_VTOR_TBLBASE_Pos) /*!< SCB VTOR: TBLBASE Mask */ + +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x3FFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +#define SCB_AIRCR_VECTRESET_Pos 0U /*!< SCB AIRCR: VECTRESET Position */ +#define SCB_AIRCR_VECTRESET_Msk (1UL /*<< SCB_AIRCR_VECTRESET_Pos*/) /*!< SCB AIRCR: VECTRESET Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +#define SCB_CCR_NONBASETHRDENA_Pos 0U /*!< SCB CCR: NONBASETHRDENA Position */ +#define SCB_CCR_NONBASETHRDENA_Msk (1UL /*<< SCB_CCR_NONBASETHRDENA_Pos*/) /*!< SCB CCR: NONBASETHRDENA Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Register Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* SCB Hard Fault Status Register Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ + uint32_t RESERVED1[1U]; +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** + \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[29U]; + __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ + __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ + __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TraceBusID_Pos 16U /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPrescale_Pos 8U /*!< ITM TCR: TSPrescale Position */ +#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ + +#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Integration Write Register Definitions */ +#define ITM_IWR_ATVALIDM_Pos 0U /*!< ITM IWR: ATVALIDM Position */ +#define ITM_IWR_ATVALIDM_Msk (1UL /*<< ITM_IWR_ATVALIDM_Pos*/) /*!< ITM IWR: ATVALIDM Mask */ + +/* ITM Integration Read Register Definitions */ +#define ITM_IRR_ATREADYM_Pos 0U /*!< ITM IRR: ATREADYM Position */ +#define ITM_IRR_ATREADYM_Msk (1UL /*<< ITM_IRR_ATREADYM_Pos*/) /*!< ITM IRR: ATREADYM Mask */ + +/* ITM Integration Mode Control Register Definitions */ +#define ITM_IMCR_INTEGRATION_Pos 0U /*!< ITM IMCR: INTEGRATION Position */ +#define ITM_IMCR_INTEGRATION_Msk (1UL /*<< ITM_IMCR_INTEGRATION_Pos*/) /*!< ITM IMCR: INTEGRATION Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Mask Register Definitions */ +#define DWT_MASK_MASK_Pos 0U /*!< DWT MASK: MASK Position */ +#define DWT_MASK_MASK_Msk (0x1FUL /*<< DWT_MASK_MASK_Pos*/) /*!< DWT MASK: MASK Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVADDR1_Pos 16U /*!< DWT FUNCTION: DATAVADDR1 Position */ +#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ + +#define DWT_FUNCTION_DATAVADDR0_Pos 12U /*!< DWT FUNCTION: DATAVADDR0 Position */ +#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_LNK1ENA_Pos 9U /*!< DWT FUNCTION: LNK1ENA Position */ +#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ + +#define DWT_FUNCTION_DATAVMATCH_Pos 8U /*!< DWT FUNCTION: DATAVMATCH Position */ +#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ + +#define DWT_FUNCTION_CYCMATCH_Pos 7U /*!< DWT FUNCTION: CYCMATCH Position */ +#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ + +#define DWT_FUNCTION_EMITRANGE_Pos 5U /*!< DWT FUNCTION: EMITRANGE Position */ +#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ + +#define DWT_FUNCTION_FUNCTION_Pos 0U /*!< DWT FUNCTION: FUNCTION Position */ +#define DWT_FUNCTION_FUNCTION_Msk (0xFUL /*<< DWT_FUNCTION_FUNCTION_Pos*/) /*!< DWT FUNCTION: FUNCTION Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IOM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ + __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY_Pos 0U /*!< TPI ITATBCTR2: ATREADY Position */ +#define TPI_ITATBCTR2_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY_Pos*/) /*!< TPI ITATBCTR2: ATREADY Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY_Pos 0U /*!< TPI ITATBCTR0: ATREADY Position */ +#define TPI_ITATBCTR0_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY_Pos*/) /*!< TPI ITATBCTR0: ATREADY Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x1UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_MajorType_Pos 4U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +#define TPI_DEVTYPE_SubType_Pos 0U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ +} MPU_Type; + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register Definitions */ +#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register Definitions */ +#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Cortex-M3 Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +/** + \brief Set Priority Grouping + \details Sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */ + SCB->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping + \details Reads the priority grouping field from the NVIC Interrupt Controller. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t NVIC_GetPriorityGrouping(void) +{ + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable External Interrupt + \details Enables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Disable External Interrupt + \details Disables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Get Pending Interrupt + \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t)(((NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of an external interrupt. + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of an external interrupt. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in NVIC and returns the active bit. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + */ +__STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) +{ + return((uint32_t)(((NVIC->IABR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of an interrupt. + \note The priority cannot be set for every core interrupt. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) < 0) + { + SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + NVIC->IP[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of an interrupt. + The interrupt number can be positive to specify an external (device specific) interrupt, + or negative to specify an internal (core) interrupt. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) < 0) + { + return(((uint32_t)SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)NVIC->IP[((uint32_t)(int32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__STATIC_INLINE void NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY 0x5AA55AA5U /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** + \brief ITM Send Character + \details Transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + \param [in] ch Character to transmit. + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; + } + return (ch); +} + + +/** + \brief ITM Receive Character + \details Inputs a character via the external variable \ref ITM_RxBuffer. + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) +{ + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** + \brief ITM Check Character + \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) +{ + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_SC300_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h new file mode 100644 index 0000000..0ae9d0b --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h @@ -0,0 +1,3309 @@ +/** + ****************************************************************************** + * @file stm32_hal_legacy.h + * @author MCD Application Team + * @brief This file contains aliases definition for the STM32Cube HAL constants + * macros and functions maintained for legacy purpose. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32_HAL_LEGACY +#define __STM32_HAL_LEGACY + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/** @defgroup HAL_AES_Aliased_Defines HAL CRYP Aliased Defines maintained for legacy purpose + * @{ + */ +#define AES_FLAG_RDERR CRYP_FLAG_RDERR +#define AES_FLAG_WRERR CRYP_FLAG_WRERR +#define AES_CLEARFLAG_CCF CRYP_CLEARFLAG_CCF +#define AES_CLEARFLAG_RDERR CRYP_CLEARFLAG_RDERR +#define AES_CLEARFLAG_WRERR CRYP_CLEARFLAG_WRERR + +/** + * @} + */ + +/** @defgroup HAL_ADC_Aliased_Defines HAL ADC Aliased Defines maintained for legacy purpose + * @{ + */ +#define ADC_RESOLUTION12b ADC_RESOLUTION_12B +#define ADC_RESOLUTION10b ADC_RESOLUTION_10B +#define ADC_RESOLUTION8b ADC_RESOLUTION_8B +#define ADC_RESOLUTION6b ADC_RESOLUTION_6B +#define OVR_DATA_OVERWRITTEN ADC_OVR_DATA_OVERWRITTEN +#define OVR_DATA_PRESERVED ADC_OVR_DATA_PRESERVED +#define EOC_SINGLE_CONV ADC_EOC_SINGLE_CONV +#define EOC_SEQ_CONV ADC_EOC_SEQ_CONV +#define EOC_SINGLE_SEQ_CONV ADC_EOC_SINGLE_SEQ_CONV +#define REGULAR_GROUP ADC_REGULAR_GROUP +#define INJECTED_GROUP ADC_INJECTED_GROUP +#define REGULAR_INJECTED_GROUP ADC_REGULAR_INJECTED_GROUP +#define AWD_EVENT ADC_AWD_EVENT +#define AWD1_EVENT ADC_AWD1_EVENT +#define AWD2_EVENT ADC_AWD2_EVENT +#define AWD3_EVENT ADC_AWD3_EVENT +#define OVR_EVENT ADC_OVR_EVENT +#define JQOVF_EVENT ADC_JQOVF_EVENT +#define ALL_CHANNELS ADC_ALL_CHANNELS +#define REGULAR_CHANNELS ADC_REGULAR_CHANNELS +#define INJECTED_CHANNELS ADC_INJECTED_CHANNELS +#define SYSCFG_FLAG_SENSOR_ADC ADC_FLAG_SENSOR +#define SYSCFG_FLAG_VREF_ADC ADC_FLAG_VREFINT +#define ADC_CLOCKPRESCALER_PCLK_DIV1 ADC_CLOCK_SYNC_PCLK_DIV1 +#define ADC_CLOCKPRESCALER_PCLK_DIV2 ADC_CLOCK_SYNC_PCLK_DIV2 +#define ADC_CLOCKPRESCALER_PCLK_DIV4 ADC_CLOCK_SYNC_PCLK_DIV4 +#define ADC_CLOCKPRESCALER_PCLK_DIV6 ADC_CLOCK_SYNC_PCLK_DIV6 +#define ADC_CLOCKPRESCALER_PCLK_DIV8 ADC_CLOCK_SYNC_PCLK_DIV8 +#define ADC_EXTERNALTRIG0_T6_TRGO ADC_EXTERNALTRIGCONV_T6_TRGO +#define ADC_EXTERNALTRIG1_T21_CC2 ADC_EXTERNALTRIGCONV_T21_CC2 +#define ADC_EXTERNALTRIG2_T2_TRGO ADC_EXTERNALTRIGCONV_T2_TRGO +#define ADC_EXTERNALTRIG3_T2_CC4 ADC_EXTERNALTRIGCONV_T2_CC4 +#define ADC_EXTERNALTRIG4_T22_TRGO ADC_EXTERNALTRIGCONV_T22_TRGO +#define ADC_EXTERNALTRIG7_EXT_IT11 ADC_EXTERNALTRIGCONV_EXT_IT11 +#define ADC_CLOCK_ASYNC ADC_CLOCK_ASYNC_DIV1 +#define ADC_EXTERNALTRIG_EDGE_NONE ADC_EXTERNALTRIGCONVEDGE_NONE +#define ADC_EXTERNALTRIG_EDGE_RISING ADC_EXTERNALTRIGCONVEDGE_RISING +#define ADC_EXTERNALTRIG_EDGE_FALLING ADC_EXTERNALTRIGCONVEDGE_FALLING +#define ADC_EXTERNALTRIG_EDGE_RISINGFALLING ADC_EXTERNALTRIGCONVEDGE_RISINGFALLING +#define ADC_SAMPLETIME_2CYCLE_5 ADC_SAMPLETIME_2CYCLES_5 + +#define HAL_ADC_STATE_BUSY_REG HAL_ADC_STATE_REG_BUSY +#define HAL_ADC_STATE_BUSY_INJ HAL_ADC_STATE_INJ_BUSY +#define HAL_ADC_STATE_EOC_REG HAL_ADC_STATE_REG_EOC +#define HAL_ADC_STATE_EOC_INJ HAL_ADC_STATE_INJ_EOC +#define HAL_ADC_STATE_ERROR HAL_ADC_STATE_ERROR_INTERNAL +#define HAL_ADC_STATE_BUSY HAL_ADC_STATE_BUSY_INTERNAL +#define HAL_ADC_STATE_AWD HAL_ADC_STATE_AWD1 +/** + * @} + */ + +/** @defgroup HAL_CEC_Aliased_Defines HAL CEC Aliased Defines maintained for legacy purpose + * @{ + */ + +#define __HAL_CEC_GET_IT __HAL_CEC_GET_FLAG + +/** + * @} + */ + +/** @defgroup HAL_COMP_Aliased_Defines HAL COMP Aliased Defines maintained for legacy purpose + * @{ + */ +#define COMP_WINDOWMODE_DISABLED COMP_WINDOWMODE_DISABLE +#define COMP_WINDOWMODE_ENABLED COMP_WINDOWMODE_ENABLE +#define COMP_EXTI_LINE_COMP1_EVENT COMP_EXTI_LINE_COMP1 +#define COMP_EXTI_LINE_COMP2_EVENT COMP_EXTI_LINE_COMP2 +#define COMP_EXTI_LINE_COMP3_EVENT COMP_EXTI_LINE_COMP3 +#define COMP_EXTI_LINE_COMP4_EVENT COMP_EXTI_LINE_COMP4 +#define COMP_EXTI_LINE_COMP5_EVENT COMP_EXTI_LINE_COMP5 +#define COMP_EXTI_LINE_COMP6_EVENT COMP_EXTI_LINE_COMP6 +#define COMP_EXTI_LINE_COMP7_EVENT COMP_EXTI_LINE_COMP7 +#if defined(STM32L0) +#define COMP_LPTIMCONNECTION_ENABLED ((uint32_t)0x00000003U) /*!< COMPX output generic naming: connected to LPTIM input 1 for COMP1, LPTIM input 2 for COMP2 */ +#endif +#define COMP_OUTPUT_COMP6TIM2OCREFCLR COMP_OUTPUT_COMP6_TIM2OCREFCLR +#if defined(STM32F373xC) || defined(STM32F378xx) +#define COMP_OUTPUT_TIM3IC1 COMP_OUTPUT_COMP1_TIM3IC1 +#define COMP_OUTPUT_TIM3OCREFCLR COMP_OUTPUT_COMP1_TIM3OCREFCLR +#endif /* STM32F373xC || STM32F378xx */ + +#if defined(STM32L0) || defined(STM32L4) +#define COMP_WINDOWMODE_ENABLE COMP_WINDOWMODE_COMP1_INPUT_PLUS_COMMON + +#define COMP_NONINVERTINGINPUT_IO1 COMP_INPUT_PLUS_IO1 +#define COMP_NONINVERTINGINPUT_IO2 COMP_INPUT_PLUS_IO2 +#define COMP_NONINVERTINGINPUT_IO3 COMP_INPUT_PLUS_IO3 +#define COMP_NONINVERTINGINPUT_IO4 COMP_INPUT_PLUS_IO4 +#define COMP_NONINVERTINGINPUT_IO5 COMP_INPUT_PLUS_IO5 +#define COMP_NONINVERTINGINPUT_IO6 COMP_INPUT_PLUS_IO6 + +#define COMP_INVERTINGINPUT_1_4VREFINT COMP_INPUT_MINUS_1_4VREFINT +#define COMP_INVERTINGINPUT_1_2VREFINT COMP_INPUT_MINUS_1_2VREFINT +#define COMP_INVERTINGINPUT_3_4VREFINT COMP_INPUT_MINUS_3_4VREFINT +#define COMP_INVERTINGINPUT_VREFINT COMP_INPUT_MINUS_VREFINT +#define COMP_INVERTINGINPUT_DAC1_CH1 COMP_INPUT_MINUS_DAC1_CH1 +#define COMP_INVERTINGINPUT_DAC1_CH2 COMP_INPUT_MINUS_DAC1_CH2 +#define COMP_INVERTINGINPUT_DAC1 COMP_INPUT_MINUS_DAC1_CH1 +#define COMP_INVERTINGINPUT_DAC2 COMP_INPUT_MINUS_DAC1_CH2 +#define COMP_INVERTINGINPUT_IO1 COMP_INPUT_MINUS_IO1 +#if defined(STM32L0) +/* Issue fixed on STM32L0 COMP driver: only 2 dedicated IO (IO1 and IO2), */ +/* IO2 was wrongly assigned to IO shared with DAC and IO3 was corresponding */ +/* to the second dedicated IO (only for COMP2). */ +#define COMP_INVERTINGINPUT_IO2 COMP_INPUT_MINUS_DAC1_CH2 +#define COMP_INVERTINGINPUT_IO3 COMP_INPUT_MINUS_IO2 +#else +#define COMP_INVERTINGINPUT_IO2 COMP_INPUT_MINUS_IO2 +#define COMP_INVERTINGINPUT_IO3 COMP_INPUT_MINUS_IO3 +#endif +#define COMP_INVERTINGINPUT_IO4 COMP_INPUT_MINUS_IO4 +#define COMP_INVERTINGINPUT_IO5 COMP_INPUT_MINUS_IO5 + +#define COMP_OUTPUTLEVEL_LOW COMP_OUTPUT_LEVEL_LOW +#define COMP_OUTPUTLEVEL_HIGH COMP_OUTPUT_LEVEL_HIGH + +/* Note: Literal "COMP_FLAG_LOCK" kept for legacy purpose. */ +/* To check COMP lock state, use macro "__HAL_COMP_IS_LOCKED()". */ +#if defined(COMP_CSR_LOCK) +#define COMP_FLAG_LOCK COMP_CSR_LOCK +#elif defined(COMP_CSR_COMP1LOCK) +#define COMP_FLAG_LOCK COMP_CSR_COMP1LOCK +#elif defined(COMP_CSR_COMPxLOCK) +#define COMP_FLAG_LOCK COMP_CSR_COMPxLOCK +#endif + +#if defined(STM32L4) +#define COMP_BLANKINGSRCE_TIM1OC5 COMP_BLANKINGSRC_TIM1_OC5_COMP1 +#define COMP_BLANKINGSRCE_TIM2OC3 COMP_BLANKINGSRC_TIM2_OC3_COMP1 +#define COMP_BLANKINGSRCE_TIM3OC3 COMP_BLANKINGSRC_TIM3_OC3_COMP1 +#define COMP_BLANKINGSRCE_TIM3OC4 COMP_BLANKINGSRC_TIM3_OC4_COMP2 +#define COMP_BLANKINGSRCE_TIM8OC5 COMP_BLANKINGSRC_TIM8_OC5_COMP2 +#define COMP_BLANKINGSRCE_TIM15OC1 COMP_BLANKINGSRC_TIM15_OC1_COMP2 +#define COMP_BLANKINGSRCE_NONE COMP_BLANKINGSRC_NONE +#endif + +#if defined(STM32L0) +#define COMP_MODE_HIGHSPEED COMP_POWERMODE_MEDIUMSPEED +#define COMP_MODE_LOWSPEED COMP_POWERMODE_ULTRALOWPOWER +#else +#define COMP_MODE_HIGHSPEED COMP_POWERMODE_HIGHSPEED +#define COMP_MODE_MEDIUMSPEED COMP_POWERMODE_MEDIUMSPEED +#define COMP_MODE_LOWPOWER COMP_POWERMODE_LOWPOWER +#define COMP_MODE_ULTRALOWPOWER COMP_POWERMODE_ULTRALOWPOWER +#endif + +#endif +/** + * @} + */ + +/** @defgroup HAL_CORTEX_Aliased_Defines HAL CORTEX Aliased Defines maintained for legacy purpose + * @{ + */ +#define __HAL_CORTEX_SYSTICKCLK_CONFIG HAL_SYSTICK_CLKSourceConfig +/** + * @} + */ + +/** @defgroup HAL_CRC_Aliased_Defines HAL CRC Aliased Defines maintained for legacy purpose + * @{ + */ + +#define CRC_OUTPUTDATA_INVERSION_DISABLED CRC_OUTPUTDATA_INVERSION_DISABLE +#define CRC_OUTPUTDATA_INVERSION_ENABLED CRC_OUTPUTDATA_INVERSION_ENABLE + +/** + * @} + */ + +/** @defgroup HAL_DAC_Aliased_Defines HAL DAC Aliased Defines maintained for legacy purpose + * @{ + */ + +#define DAC1_CHANNEL_1 DAC_CHANNEL_1 +#define DAC1_CHANNEL_2 DAC_CHANNEL_2 +#define DAC2_CHANNEL_1 DAC_CHANNEL_1 +#define DAC_WAVE_NONE 0x00000000U +#define DAC_WAVE_NOISE DAC_CR_WAVE1_0 +#define DAC_WAVE_TRIANGLE DAC_CR_WAVE1_1 +#define DAC_WAVEGENERATION_NONE DAC_WAVE_NONE +#define DAC_WAVEGENERATION_NOISE DAC_WAVE_NOISE +#define DAC_WAVEGENERATION_TRIANGLE DAC_WAVE_TRIANGLE + +/** + * @} + */ + +/** @defgroup HAL_DMA_Aliased_Defines HAL DMA Aliased Defines maintained for legacy purpose + * @{ + */ +#define HAL_REMAPDMA_ADC_DMA_CH2 DMA_REMAP_ADC_DMA_CH2 +#define HAL_REMAPDMA_USART1_TX_DMA_CH4 DMA_REMAP_USART1_TX_DMA_CH4 +#define HAL_REMAPDMA_USART1_RX_DMA_CH5 DMA_REMAP_USART1_RX_DMA_CH5 +#define HAL_REMAPDMA_TIM16_DMA_CH4 DMA_REMAP_TIM16_DMA_CH4 +#define HAL_REMAPDMA_TIM17_DMA_CH2 DMA_REMAP_TIM17_DMA_CH2 +#define HAL_REMAPDMA_USART3_DMA_CH32 DMA_REMAP_USART3_DMA_CH32 +#define HAL_REMAPDMA_TIM16_DMA_CH6 DMA_REMAP_TIM16_DMA_CH6 +#define HAL_REMAPDMA_TIM17_DMA_CH7 DMA_REMAP_TIM17_DMA_CH7 +#define HAL_REMAPDMA_SPI2_DMA_CH67 DMA_REMAP_SPI2_DMA_CH67 +#define HAL_REMAPDMA_USART2_DMA_CH67 DMA_REMAP_USART2_DMA_CH67 +#define HAL_REMAPDMA_I2C1_DMA_CH76 DMA_REMAP_I2C1_DMA_CH76 +#define HAL_REMAPDMA_TIM1_DMA_CH6 DMA_REMAP_TIM1_DMA_CH6 +#define HAL_REMAPDMA_TIM2_DMA_CH7 DMA_REMAP_TIM2_DMA_CH7 +#define HAL_REMAPDMA_TIM3_DMA_CH6 DMA_REMAP_TIM3_DMA_CH6 + +#define IS_HAL_REMAPDMA IS_DMA_REMAP +#define __HAL_REMAPDMA_CHANNEL_ENABLE __HAL_DMA_REMAP_CHANNEL_ENABLE +#define __HAL_REMAPDMA_CHANNEL_DISABLE __HAL_DMA_REMAP_CHANNEL_DISABLE + + + +/** + * @} + */ + +/** @defgroup HAL_FLASH_Aliased_Defines HAL FLASH Aliased Defines maintained for legacy purpose + * @{ + */ + +#define TYPEPROGRAM_BYTE FLASH_TYPEPROGRAM_BYTE +#define TYPEPROGRAM_HALFWORD FLASH_TYPEPROGRAM_HALFWORD +#define TYPEPROGRAM_WORD FLASH_TYPEPROGRAM_WORD +#define TYPEPROGRAM_DOUBLEWORD FLASH_TYPEPROGRAM_DOUBLEWORD +#define TYPEERASE_SECTORS FLASH_TYPEERASE_SECTORS +#define TYPEERASE_PAGES FLASH_TYPEERASE_PAGES +#define TYPEERASE_PAGEERASE FLASH_TYPEERASE_PAGES +#define TYPEERASE_MASSERASE FLASH_TYPEERASE_MASSERASE +#define WRPSTATE_DISABLE OB_WRPSTATE_DISABLE +#define WRPSTATE_ENABLE OB_WRPSTATE_ENABLE +#define HAL_FLASH_TIMEOUT_VALUE FLASH_TIMEOUT_VALUE +#define OBEX_PCROP OPTIONBYTE_PCROP +#define OBEX_BOOTCONFIG OPTIONBYTE_BOOTCONFIG +#define PCROPSTATE_DISABLE OB_PCROP_STATE_DISABLE +#define PCROPSTATE_ENABLE OB_PCROP_STATE_ENABLE +#define TYPEERASEDATA_BYTE FLASH_TYPEERASEDATA_BYTE +#define TYPEERASEDATA_HALFWORD FLASH_TYPEERASEDATA_HALFWORD +#define TYPEERASEDATA_WORD FLASH_TYPEERASEDATA_WORD +#define TYPEPROGRAMDATA_BYTE FLASH_TYPEPROGRAMDATA_BYTE +#define TYPEPROGRAMDATA_HALFWORD FLASH_TYPEPROGRAMDATA_HALFWORD +#define TYPEPROGRAMDATA_WORD FLASH_TYPEPROGRAMDATA_WORD +#define TYPEPROGRAMDATA_FASTBYTE FLASH_TYPEPROGRAMDATA_FASTBYTE +#define TYPEPROGRAMDATA_FASTHALFWORD FLASH_TYPEPROGRAMDATA_FASTHALFWORD +#define TYPEPROGRAMDATA_FASTWORD FLASH_TYPEPROGRAMDATA_FASTWORD +#define PAGESIZE FLASH_PAGE_SIZE +#define TYPEPROGRAM_FASTBYTE FLASH_TYPEPROGRAM_BYTE +#define TYPEPROGRAM_FASTHALFWORD FLASH_TYPEPROGRAM_HALFWORD +#define TYPEPROGRAM_FASTWORD FLASH_TYPEPROGRAM_WORD +#define VOLTAGE_RANGE_1 FLASH_VOLTAGE_RANGE_1 +#define VOLTAGE_RANGE_2 FLASH_VOLTAGE_RANGE_2 +#define VOLTAGE_RANGE_3 FLASH_VOLTAGE_RANGE_3 +#define VOLTAGE_RANGE_4 FLASH_VOLTAGE_RANGE_4 +#define TYPEPROGRAM_FAST FLASH_TYPEPROGRAM_FAST +#define TYPEPROGRAM_FAST_AND_LAST FLASH_TYPEPROGRAM_FAST_AND_LAST +#define WRPAREA_BANK1_AREAA OB_WRPAREA_BANK1_AREAA +#define WRPAREA_BANK1_AREAB OB_WRPAREA_BANK1_AREAB +#define WRPAREA_BANK2_AREAA OB_WRPAREA_BANK2_AREAA +#define WRPAREA_BANK2_AREAB OB_WRPAREA_BANK2_AREAB +#define IWDG_STDBY_FREEZE OB_IWDG_STDBY_FREEZE +#define IWDG_STDBY_ACTIVE OB_IWDG_STDBY_RUN +#define IWDG_STOP_FREEZE OB_IWDG_STOP_FREEZE +#define IWDG_STOP_ACTIVE OB_IWDG_STOP_RUN +#define FLASH_ERROR_NONE HAL_FLASH_ERROR_NONE +#define FLASH_ERROR_RD HAL_FLASH_ERROR_RD +#define FLASH_ERROR_PG HAL_FLASH_ERROR_PROG +#define FLASH_ERROR_PGP HAL_FLASH_ERROR_PGS +#define FLASH_ERROR_WRP HAL_FLASH_ERROR_WRP +#define FLASH_ERROR_OPTV HAL_FLASH_ERROR_OPTV +#define FLASH_ERROR_OPTVUSR HAL_FLASH_ERROR_OPTVUSR +#define FLASH_ERROR_PROG HAL_FLASH_ERROR_PROG +#define FLASH_ERROR_OP HAL_FLASH_ERROR_OPERATION +#define FLASH_ERROR_PGA HAL_FLASH_ERROR_PGA +#define FLASH_ERROR_SIZE HAL_FLASH_ERROR_SIZE +#define FLASH_ERROR_SIZ HAL_FLASH_ERROR_SIZE +#define FLASH_ERROR_PGS HAL_FLASH_ERROR_PGS +#define FLASH_ERROR_MIS HAL_FLASH_ERROR_MIS +#define FLASH_ERROR_FAST HAL_FLASH_ERROR_FAST +#define FLASH_ERROR_FWWERR HAL_FLASH_ERROR_FWWERR +#define FLASH_ERROR_NOTZERO HAL_FLASH_ERROR_NOTZERO +#define FLASH_ERROR_OPERATION HAL_FLASH_ERROR_OPERATION +#define FLASH_ERROR_ERS HAL_FLASH_ERROR_ERS +#define OB_WDG_SW OB_IWDG_SW +#define OB_WDG_HW OB_IWDG_HW +#define OB_SDADC12_VDD_MONITOR_SET OB_SDACD_VDD_MONITOR_SET +#define OB_SDADC12_VDD_MONITOR_RESET OB_SDACD_VDD_MONITOR_RESET +#define OB_RAM_PARITY_CHECK_SET OB_SRAM_PARITY_SET +#define OB_RAM_PARITY_CHECK_RESET OB_SRAM_PARITY_RESET +#define IS_OB_SDADC12_VDD_MONITOR IS_OB_SDACD_VDD_MONITOR +#define OB_RDP_LEVEL0 OB_RDP_LEVEL_0 +#define OB_RDP_LEVEL1 OB_RDP_LEVEL_1 +#define OB_RDP_LEVEL2 OB_RDP_LEVEL_2 + +/** + * @} + */ + +/** @defgroup HAL_SYSCFG_Aliased_Defines HAL SYSCFG Aliased Defines maintained for legacy purpose + * @{ + */ + +#define HAL_SYSCFG_FASTMODEPLUS_I2C_PA9 I2C_FASTMODEPLUS_PA9 +#define HAL_SYSCFG_FASTMODEPLUS_I2C_PA10 I2C_FASTMODEPLUS_PA10 +#define HAL_SYSCFG_FASTMODEPLUS_I2C_PB6 I2C_FASTMODEPLUS_PB6 +#define HAL_SYSCFG_FASTMODEPLUS_I2C_PB7 I2C_FASTMODEPLUS_PB7 +#define HAL_SYSCFG_FASTMODEPLUS_I2C_PB8 I2C_FASTMODEPLUS_PB8 +#define HAL_SYSCFG_FASTMODEPLUS_I2C_PB9 I2C_FASTMODEPLUS_PB9 +#define HAL_SYSCFG_FASTMODEPLUS_I2C1 I2C_FASTMODEPLUS_I2C1 +#define HAL_SYSCFG_FASTMODEPLUS_I2C2 I2C_FASTMODEPLUS_I2C2 +#define HAL_SYSCFG_FASTMODEPLUS_I2C3 I2C_FASTMODEPLUS_I2C3 +/** + * @} + */ + + +/** @defgroup LL_FMC_Aliased_Defines LL FMC Aliased Defines maintained for compatibility purpose + * @{ + */ +#if defined(STM32L4) || defined(STM32F7) || defined(STM32H7) || defined(STM32G4) +#define FMC_NAND_PCC_WAIT_FEATURE_DISABLE FMC_NAND_WAIT_FEATURE_DISABLE +#define FMC_NAND_PCC_WAIT_FEATURE_ENABLE FMC_NAND_WAIT_FEATURE_ENABLE +#define FMC_NAND_PCC_MEM_BUS_WIDTH_8 FMC_NAND_MEM_BUS_WIDTH_8 +#define FMC_NAND_PCC_MEM_BUS_WIDTH_16 FMC_NAND_MEM_BUS_WIDTH_16 +#else +#define FMC_NAND_WAIT_FEATURE_DISABLE FMC_NAND_PCC_WAIT_FEATURE_DISABLE +#define FMC_NAND_WAIT_FEATURE_ENABLE FMC_NAND_PCC_WAIT_FEATURE_ENABLE +#define FMC_NAND_MEM_BUS_WIDTH_8 FMC_NAND_PCC_MEM_BUS_WIDTH_8 +#define FMC_NAND_MEM_BUS_WIDTH_16 FMC_NAND_PCC_MEM_BUS_WIDTH_16 +#endif +/** + * @} + */ + +/** @defgroup LL_FSMC_Aliased_Defines LL FSMC Aliased Defines maintained for legacy purpose + * @{ + */ + +#define FSMC_NORSRAM_TYPEDEF FSMC_NORSRAM_TypeDef +#define FSMC_NORSRAM_EXTENDED_TYPEDEF FSMC_NORSRAM_EXTENDED_TypeDef +/** + * @} + */ + +/** @defgroup HAL_GPIO_Aliased_Macros HAL GPIO Aliased Macros maintained for legacy purpose + * @{ + */ +#define GET_GPIO_SOURCE GPIO_GET_INDEX +#define GET_GPIO_INDEX GPIO_GET_INDEX + +#if defined(STM32F4) +#define GPIO_AF12_SDMMC GPIO_AF12_SDIO +#define GPIO_AF12_SDMMC1 GPIO_AF12_SDIO +#endif + +#if defined(STM32F7) +#define GPIO_AF12_SDIO GPIO_AF12_SDMMC1 +#define GPIO_AF12_SDMMC GPIO_AF12_SDMMC1 +#endif + +#if defined(STM32L4) +#define GPIO_AF12_SDIO GPIO_AF12_SDMMC1 +#define GPIO_AF12_SDMMC GPIO_AF12_SDMMC1 +#endif + +#define GPIO_AF0_LPTIM GPIO_AF0_LPTIM1 +#define GPIO_AF1_LPTIM GPIO_AF1_LPTIM1 +#define GPIO_AF2_LPTIM GPIO_AF2_LPTIM1 + +#if defined(STM32L0) || defined(STM32L4) || defined(STM32F4) || defined(STM32F2) || defined(STM32F7) || defined(STM32G4) +#define GPIO_SPEED_LOW GPIO_SPEED_FREQ_LOW +#define GPIO_SPEED_MEDIUM GPIO_SPEED_FREQ_MEDIUM +#define GPIO_SPEED_FAST GPIO_SPEED_FREQ_HIGH +#define GPIO_SPEED_HIGH GPIO_SPEED_FREQ_VERY_HIGH +#endif /* STM32L0 || STM32L4 || STM32F4 || STM32F2 || STM32F7 || STM32G4 */ + +#if defined(STM32L1) + #define GPIO_SPEED_VERY_LOW GPIO_SPEED_FREQ_LOW + #define GPIO_SPEED_LOW GPIO_SPEED_FREQ_MEDIUM + #define GPIO_SPEED_MEDIUM GPIO_SPEED_FREQ_HIGH + #define GPIO_SPEED_HIGH GPIO_SPEED_FREQ_VERY_HIGH +#endif /* STM32L1 */ + +#if defined(STM32F0) || defined(STM32F3) || defined(STM32F1) + #define GPIO_SPEED_LOW GPIO_SPEED_FREQ_LOW + #define GPIO_SPEED_MEDIUM GPIO_SPEED_FREQ_MEDIUM + #define GPIO_SPEED_HIGH GPIO_SPEED_FREQ_HIGH +#endif /* STM32F0 || STM32F3 || STM32F1 */ + +#define GPIO_AF6_DFSDM GPIO_AF6_DFSDM1 +/** + * @} + */ + +/** @defgroup HAL_JPEG_Aliased_Macros HAL JPEG Aliased Macros maintained for legacy purpose + * @{ + */ + +#if defined(STM32H7) + #define __HAL_RCC_JPEG_CLK_ENABLE __HAL_RCC_JPGDECEN_CLK_ENABLE + #define __HAL_RCC_JPEG_CLK_DISABLE __HAL_RCC_JPGDECEN_CLK_DISABLE + #define __HAL_RCC_JPEG_FORCE_RESET __HAL_RCC_JPGDECRST_FORCE_RESET + #define __HAL_RCC_JPEG_RELEASE_RESET __HAL_RCC_JPGDECRST_RELEASE_RESET + #define __HAL_RCC_JPEG_CLK_SLEEP_ENABLE __HAL_RCC_JPGDEC_CLK_SLEEP_ENABLE + #define __HAL_RCC_JPEG_CLK_SLEEP_DISABLE __HAL_RCC_JPGDEC_CLK_SLEEP_DISABLE + + #define DMA_REQUEST_DAC1 DMA_REQUEST_DAC1_CH1 + #define DMA_REQUEST_DAC2 DMA_REQUEST_DAC1_CH2 + + #define BDMA_REQUEST_LP_UART1_RX BDMA_REQUEST_LPUART1_RX + #define BDMA_REQUEST_LP_UART1_TX BDMA_REQUEST_LPUART1_TX + + #define HAL_DMAMUX1_REQUEST_GEN_DMAMUX1_CH0_EVT HAL_DMAMUX1_REQ_GEN_DMAMUX1_CH0_EVT + #define HAL_DMAMUX1_REQUEST_GEN_DMAMUX1_CH1_EVT HAL_DMAMUX1_REQ_GEN_DMAMUX1_CH1_EVT + #define HAL_DMAMUX1_REQUEST_GEN_DMAMUX1_CH2_EVT HAL_DMAMUX1_REQ_GEN_DMAMUX1_CH2_EVT + #define HAL_DMAMUX1_REQUEST_GEN_LPTIM1_OUT HAL_DMAMUX1_REQ_GEN_LPTIM1_OUT + #define HAL_DMAMUX1_REQUEST_GEN_LPTIM2_OUT HAL_DMAMUX1_REQ_GEN_LPTIM2_OUT + #define HAL_DMAMUX1_REQUEST_GEN_LPTIM3_OUT HAL_DMAMUX1_REQ_GEN_LPTIM3_OUT + #define HAL_DMAMUX1_REQUEST_GEN_EXTI0 HAL_DMAMUX1_REQ_GEN_EXTI0 + #define HAL_DMAMUX1_REQUEST_GEN_TIM12_TRGO HAL_DMAMUX1_REQ_GEN_TIM12_TRGO + + #define HAL_DMAMUX2_REQUEST_GEN_DMAMUX2_CH0_EVT HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH0_EVT + #define HAL_DMAMUX2_REQUEST_GEN_DMAMUX2_CH1_EVT HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH1_EVT + #define HAL_DMAMUX2_REQUEST_GEN_DMAMUX2_CH2_EVT HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH2_EVT + #define HAL_DMAMUX2_REQUEST_GEN_DMAMUX2_CH3_EVT HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH3_EVT + #define HAL_DMAMUX2_REQUEST_GEN_DMAMUX2_CH4_EVT HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH4_EVT + #define HAL_DMAMUX2_REQUEST_GEN_DMAMUX2_CH5_EVT HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH5_EVT + #define HAL_DMAMUX2_REQUEST_GEN_DMAMUX2_CH6_EVT HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH6_EVT + #define HAL_DMAMUX2_REQUEST_GEN_LPUART1_RX_WKUP HAL_DMAMUX2_REQ_GEN_LPUART1_RX_WKUP + #define HAL_DMAMUX2_REQUEST_GEN_LPUART1_TX_WKUP HAL_DMAMUX2_REQ_GEN_LPUART1_TX_WKUP + #define HAL_DMAMUX2_REQUEST_GEN_LPTIM2_WKUP HAL_DMAMUX2_REQ_GEN_LPTIM2_WKUP + #define HAL_DMAMUX2_REQUEST_GEN_LPTIM2_OUT HAL_DMAMUX2_REQ_GEN_LPTIM2_OUT + #define HAL_DMAMUX2_REQUEST_GEN_LPTIM3_WKUP HAL_DMAMUX2_REQ_GEN_LPTIM3_WKUP + #define HAL_DMAMUX2_REQUEST_GEN_LPTIM3_OUT HAL_DMAMUX2_REQ_GEN_LPTIM3_OUT + #define HAL_DMAMUX2_REQUEST_GEN_LPTIM4_WKUP HAL_DMAMUX2_REQ_GEN_LPTIM4_WKUP + #define HAL_DMAMUX2_REQUEST_GEN_LPTIM5_WKUP HAL_DMAMUX2_REQ_GEN_LPTIM5_WKUP + #define HAL_DMAMUX2_REQUEST_GEN_I2C4_WKUP HAL_DMAMUX2_REQ_GEN_I2C4_WKUP + #define HAL_DMAMUX2_REQUEST_GEN_SPI6_WKUP HAL_DMAMUX2_REQ_GEN_SPI6_WKUP + #define HAL_DMAMUX2_REQUEST_GEN_COMP1_OUT HAL_DMAMUX2_REQ_GEN_COMP1_OUT + #define HAL_DMAMUX2_REQUEST_GEN_COMP2_OUT HAL_DMAMUX2_REQ_GEN_COMP2_OUT + #define HAL_DMAMUX2_REQUEST_GEN_RTC_WKUP HAL_DMAMUX2_REQ_GEN_RTC_WKUP + #define HAL_DMAMUX2_REQUEST_GEN_EXTI0 HAL_DMAMUX2_REQ_GEN_EXTI0 + #define HAL_DMAMUX2_REQUEST_GEN_EXTI2 HAL_DMAMUX2_REQ_GEN_EXTI2 + #define HAL_DMAMUX2_REQUEST_GEN_I2C4_IT_EVT HAL_DMAMUX2_REQ_GEN_I2C4_IT_EVT + #define HAL_DMAMUX2_REQUEST_GEN_SPI6_IT HAL_DMAMUX2_REQ_GEN_SPI6_IT + #define HAL_DMAMUX2_REQUEST_GEN_LPUART1_TX_IT HAL_DMAMUX2_REQ_GEN_LPUART1_TX_IT + #define HAL_DMAMUX2_REQUEST_GEN_LPUART1_RX_IT HAL_DMAMUX2_REQ_GEN_LPUART1_RX_IT + #define HAL_DMAMUX2_REQUEST_GEN_ADC3_IT HAL_DMAMUX2_REQ_GEN_ADC3_IT + #define HAL_DMAMUX2_REQUEST_GEN_ADC3_AWD1_OUT HAL_DMAMUX2_REQ_GEN_ADC3_AWD1_OUT + #define HAL_DMAMUX2_REQUEST_GEN_BDMA_CH0_IT HAL_DMAMUX2_REQ_GEN_BDMA_CH0_IT + #define HAL_DMAMUX2_REQUEST_GEN_BDMA_CH1_IT HAL_DMAMUX2_REQ_GEN_BDMA_CH1_IT + + #define HAL_DMAMUX_REQUEST_GEN_NO_EVENT HAL_DMAMUX_REQ_GEN_NO_EVENT + #define HAL_DMAMUX_REQUEST_GEN_RISING HAL_DMAMUX_REQ_GEN_RISING + #define HAL_DMAMUX_REQUEST_GEN_FALLING HAL_DMAMUX_REQ_GEN_FALLING + #define HAL_DMAMUX_REQUEST_GEN_RISING_FALLING HAL_DMAMUX_REQ_GEN_RISING_FALLING + + +#endif /* STM32H7 */ + + +/** + * @} + */ + + +/** @defgroup HAL_HRTIM_Aliased_Macros HAL HRTIM Aliased Macros maintained for legacy purpose + * @{ + */ +#define HRTIM_TIMDELAYEDPROTECTION_DISABLED HRTIM_TIMER_A_B_C_DELAYEDPROTECTION_DISABLED +#define HRTIM_TIMDELAYEDPROTECTION_DELAYEDOUT1_EEV68 HRTIM_TIMER_A_B_C_DELAYEDPROTECTION_DELAYEDOUT1_EEV6 +#define HRTIM_TIMDELAYEDPROTECTION_DELAYEDOUT2_EEV68 HRTIM_TIMER_A_B_C_DELAYEDPROTECTION_DELAYEDOUT2_EEV6 +#define HRTIM_TIMDELAYEDPROTECTION_DELAYEDBOTH_EEV68 HRTIM_TIMER_A_B_C_DELAYEDPROTECTION_DELAYEDBOTH_EEV6 +#define HRTIM_TIMDELAYEDPROTECTION_BALANCED_EEV68 HRTIM_TIMER_A_B_C_DELAYEDPROTECTION_BALANCED_EEV6 +#define HRTIM_TIMDELAYEDPROTECTION_DELAYEDOUT1_DEEV79 HRTIM_TIMER_A_B_C_DELAYEDPROTECTION_DELAYEDOUT1_DEEV7 +#define HRTIM_TIMDELAYEDPROTECTION_DELAYEDOUT2_DEEV79 HRTIM_TIMER_A_B_C_DELAYEDPROTECTION_DELAYEDOUT2_DEEV7 +#define HRTIM_TIMDELAYEDPROTECTION_DELAYEDBOTH_EEV79 HRTIM_TIMER_A_B_C_DELAYEDPROTECTION_DELAYEDBOTH_EEV7 +#define HRTIM_TIMDELAYEDPROTECTION_BALANCED_EEV79 HRTIM_TIMER_A_B_C_DELAYEDPROTECTION_BALANCED_EEV7 + +#define __HAL_HRTIM_SetCounter __HAL_HRTIM_SETCOUNTER +#define __HAL_HRTIM_GetCounter __HAL_HRTIM_GETCOUNTER +#define __HAL_HRTIM_SetPeriod __HAL_HRTIM_SETPERIOD +#define __HAL_HRTIM_GetPeriod __HAL_HRTIM_GETPERIOD +#define __HAL_HRTIM_SetClockPrescaler __HAL_HRTIM_SETCLOCKPRESCALER +#define __HAL_HRTIM_GetClockPrescaler __HAL_HRTIM_GETCLOCKPRESCALER +#define __HAL_HRTIM_SetCompare __HAL_HRTIM_SETCOMPARE +#define __HAL_HRTIM_GetCompare __HAL_HRTIM_GETCOMPARE +/** + * @} + */ + +/** @defgroup HAL_I2C_Aliased_Defines HAL I2C Aliased Defines maintained for legacy purpose + * @{ + */ +#define I2C_DUALADDRESS_DISABLED I2C_DUALADDRESS_DISABLE +#define I2C_DUALADDRESS_ENABLED I2C_DUALADDRESS_ENABLE +#define I2C_GENERALCALL_DISABLED I2C_GENERALCALL_DISABLE +#define I2C_GENERALCALL_ENABLED I2C_GENERALCALL_ENABLE +#define I2C_NOSTRETCH_DISABLED I2C_NOSTRETCH_DISABLE +#define I2C_NOSTRETCH_ENABLED I2C_NOSTRETCH_ENABLE +#define I2C_ANALOGFILTER_ENABLED I2C_ANALOGFILTER_ENABLE +#define I2C_ANALOGFILTER_DISABLED I2C_ANALOGFILTER_DISABLE +#if defined(STM32F0) || defined(STM32F1) || defined(STM32F3) || defined(STM32G0) || defined(STM32L4) || defined(STM32L1) || defined(STM32F7) +#define HAL_I2C_STATE_MEM_BUSY_TX HAL_I2C_STATE_BUSY_TX +#define HAL_I2C_STATE_MEM_BUSY_RX HAL_I2C_STATE_BUSY_RX +#define HAL_I2C_STATE_MASTER_BUSY_TX HAL_I2C_STATE_BUSY_TX +#define HAL_I2C_STATE_MASTER_BUSY_RX HAL_I2C_STATE_BUSY_RX +#define HAL_I2C_STATE_SLAVE_BUSY_TX HAL_I2C_STATE_BUSY_TX +#define HAL_I2C_STATE_SLAVE_BUSY_RX HAL_I2C_STATE_BUSY_RX +#endif +/** + * @} + */ + +/** @defgroup HAL_IRDA_Aliased_Defines HAL IRDA Aliased Defines maintained for legacy purpose + * @{ + */ +#define IRDA_ONE_BIT_SAMPLE_DISABLED IRDA_ONE_BIT_SAMPLE_DISABLE +#define IRDA_ONE_BIT_SAMPLE_ENABLED IRDA_ONE_BIT_SAMPLE_ENABLE + +/** + * @} + */ + +/** @defgroup HAL_IWDG_Aliased_Defines HAL IWDG Aliased Defines maintained for legacy purpose + * @{ + */ +#define KR_KEY_RELOAD IWDG_KEY_RELOAD +#define KR_KEY_ENABLE IWDG_KEY_ENABLE +#define KR_KEY_EWA IWDG_KEY_WRITE_ACCESS_ENABLE +#define KR_KEY_DWA IWDG_KEY_WRITE_ACCESS_DISABLE +/** + * @} + */ + +/** @defgroup HAL_LPTIM_Aliased_Defines HAL LPTIM Aliased Defines maintained for legacy purpose + * @{ + */ + +#define LPTIM_CLOCKSAMPLETIME_DIRECTTRANSISTION LPTIM_CLOCKSAMPLETIME_DIRECTTRANSITION +#define LPTIM_CLOCKSAMPLETIME_2TRANSISTIONS LPTIM_CLOCKSAMPLETIME_2TRANSITIONS +#define LPTIM_CLOCKSAMPLETIME_4TRANSISTIONS LPTIM_CLOCKSAMPLETIME_4TRANSITIONS +#define LPTIM_CLOCKSAMPLETIME_8TRANSISTIONS LPTIM_CLOCKSAMPLETIME_8TRANSITIONS + +#define LPTIM_CLOCKPOLARITY_RISINGEDGE LPTIM_CLOCKPOLARITY_RISING +#define LPTIM_CLOCKPOLARITY_FALLINGEDGE LPTIM_CLOCKPOLARITY_FALLING +#define LPTIM_CLOCKPOLARITY_BOTHEDGES LPTIM_CLOCKPOLARITY_RISING_FALLING + +#define LPTIM_TRIGSAMPLETIME_DIRECTTRANSISTION LPTIM_TRIGSAMPLETIME_DIRECTTRANSITION +#define LPTIM_TRIGSAMPLETIME_2TRANSISTIONS LPTIM_TRIGSAMPLETIME_2TRANSITIONS +#define LPTIM_TRIGSAMPLETIME_4TRANSISTIONS LPTIM_TRIGSAMPLETIME_4TRANSITIONS +#define LPTIM_TRIGSAMPLETIME_8TRANSISTIONS LPTIM_TRIGSAMPLETIME_8TRANSITIONS + +/* The following 3 definition have also been present in a temporary version of lptim.h */ +/* They need to be renamed also to the right name, just in case */ +#define LPTIM_TRIGSAMPLETIME_2TRANSITION LPTIM_TRIGSAMPLETIME_2TRANSITIONS +#define LPTIM_TRIGSAMPLETIME_4TRANSITION LPTIM_TRIGSAMPLETIME_4TRANSITIONS +#define LPTIM_TRIGSAMPLETIME_8TRANSITION LPTIM_TRIGSAMPLETIME_8TRANSITIONS + +/** + * @} + */ + +/** @defgroup HAL_NAND_Aliased_Defines HAL NAND Aliased Defines maintained for legacy purpose + * @{ + */ +#define HAL_NAND_Read_Page HAL_NAND_Read_Page_8b +#define HAL_NAND_Write_Page HAL_NAND_Write_Page_8b +#define HAL_NAND_Read_SpareArea HAL_NAND_Read_SpareArea_8b +#define HAL_NAND_Write_SpareArea HAL_NAND_Write_SpareArea_8b + +#define NAND_AddressTypedef NAND_AddressTypeDef + +#define __ARRAY_ADDRESS ARRAY_ADDRESS +#define __ADDR_1st_CYCLE ADDR_1ST_CYCLE +#define __ADDR_2nd_CYCLE ADDR_2ND_CYCLE +#define __ADDR_3rd_CYCLE ADDR_3RD_CYCLE +#define __ADDR_4th_CYCLE ADDR_4TH_CYCLE +/** + * @} + */ + +/** @defgroup HAL_NOR_Aliased_Defines HAL NOR Aliased Defines maintained for legacy purpose + * @{ + */ +#define NOR_StatusTypedef HAL_NOR_StatusTypeDef +#define NOR_SUCCESS HAL_NOR_STATUS_SUCCESS +#define NOR_ONGOING HAL_NOR_STATUS_ONGOING +#define NOR_ERROR HAL_NOR_STATUS_ERROR +#define NOR_TIMEOUT HAL_NOR_STATUS_TIMEOUT + +#define __NOR_WRITE NOR_WRITE +#define __NOR_ADDR_SHIFT NOR_ADDR_SHIFT +/** + * @} + */ + +/** @defgroup HAL_OPAMP_Aliased_Defines HAL OPAMP Aliased Defines maintained for legacy purpose + * @{ + */ + +#define OPAMP_NONINVERTINGINPUT_VP0 OPAMP_NONINVERTINGINPUT_IO0 +#define OPAMP_NONINVERTINGINPUT_VP1 OPAMP_NONINVERTINGINPUT_IO1 +#define OPAMP_NONINVERTINGINPUT_VP2 OPAMP_NONINVERTINGINPUT_IO2 +#define OPAMP_NONINVERTINGINPUT_VP3 OPAMP_NONINVERTINGINPUT_IO3 + +#define OPAMP_SEC_NONINVERTINGINPUT_VP0 OPAMP_SEC_NONINVERTINGINPUT_IO0 +#define OPAMP_SEC_NONINVERTINGINPUT_VP1 OPAMP_SEC_NONINVERTINGINPUT_IO1 +#define OPAMP_SEC_NONINVERTINGINPUT_VP2 OPAMP_SEC_NONINVERTINGINPUT_IO2 +#define OPAMP_SEC_NONINVERTINGINPUT_VP3 OPAMP_SEC_NONINVERTINGINPUT_IO3 + +#define OPAMP_INVERTINGINPUT_VM0 OPAMP_INVERTINGINPUT_IO0 +#define OPAMP_INVERTINGINPUT_VM1 OPAMP_INVERTINGINPUT_IO1 + +#define IOPAMP_INVERTINGINPUT_VM0 OPAMP_INVERTINGINPUT_IO0 +#define IOPAMP_INVERTINGINPUT_VM1 OPAMP_INVERTINGINPUT_IO1 + +#define OPAMP_SEC_INVERTINGINPUT_VM0 OPAMP_SEC_INVERTINGINPUT_IO0 +#define OPAMP_SEC_INVERTINGINPUT_VM1 OPAMP_SEC_INVERTINGINPUT_IO1 + +#define OPAMP_INVERTINGINPUT_VINM OPAMP_SEC_INVERTINGINPUT_IO1 + +#define OPAMP_PGACONNECT_NO OPAMP_PGA_CONNECT_INVERTINGINPUT_NO +#define OPAMP_PGACONNECT_VM0 OPAMP_PGA_CONNECT_INVERTINGINPUT_IO0 +#define OPAMP_PGACONNECT_VM1 OPAMP_PGA_CONNECT_INVERTINGINPUT_IO1 + +/** + * @} + */ + +/** @defgroup HAL_I2S_Aliased_Defines HAL I2S Aliased Defines maintained for legacy purpose + * @{ + */ +#define I2S_STANDARD_PHILLIPS I2S_STANDARD_PHILIPS +#if defined(STM32F7) + #define I2S_CLOCK_SYSCLK I2S_CLOCK_PLL +#endif +/** + * @} + */ + +/** @defgroup HAL_PCCARD_Aliased_Defines HAL PCCARD Aliased Defines maintained for legacy purpose + * @{ + */ + +/* Compact Flash-ATA registers description */ +#define CF_DATA ATA_DATA +#define CF_SECTOR_COUNT ATA_SECTOR_COUNT +#define CF_SECTOR_NUMBER ATA_SECTOR_NUMBER +#define CF_CYLINDER_LOW ATA_CYLINDER_LOW +#define CF_CYLINDER_HIGH ATA_CYLINDER_HIGH +#define CF_CARD_HEAD ATA_CARD_HEAD +#define CF_STATUS_CMD ATA_STATUS_CMD +#define CF_STATUS_CMD_ALTERNATE ATA_STATUS_CMD_ALTERNATE +#define CF_COMMON_DATA_AREA ATA_COMMON_DATA_AREA + +/* Compact Flash-ATA commands */ +#define CF_READ_SECTOR_CMD ATA_READ_SECTOR_CMD +#define CF_WRITE_SECTOR_CMD ATA_WRITE_SECTOR_CMD +#define CF_ERASE_SECTOR_CMD ATA_ERASE_SECTOR_CMD +#define CF_IDENTIFY_CMD ATA_IDENTIFY_CMD + +#define PCCARD_StatusTypedef HAL_PCCARD_StatusTypeDef +#define PCCARD_SUCCESS HAL_PCCARD_STATUS_SUCCESS +#define PCCARD_ONGOING HAL_PCCARD_STATUS_ONGOING +#define PCCARD_ERROR HAL_PCCARD_STATUS_ERROR +#define PCCARD_TIMEOUT HAL_PCCARD_STATUS_TIMEOUT +/** + * @} + */ + +/** @defgroup HAL_RTC_Aliased_Defines HAL RTC Aliased Defines maintained for legacy purpose + * @{ + */ + +#define FORMAT_BIN RTC_FORMAT_BIN +#define FORMAT_BCD RTC_FORMAT_BCD + +#define RTC_ALARMSUBSECONDMASK_None RTC_ALARMSUBSECONDMASK_NONE +#define RTC_TAMPERERASEBACKUP_DISABLED RTC_TAMPER_ERASE_BACKUP_DISABLE +#define RTC_TAMPERMASK_FLAG_DISABLED RTC_TAMPERMASK_FLAG_DISABLE +#define RTC_TAMPERMASK_FLAG_ENABLED RTC_TAMPERMASK_FLAG_ENABLE + +#define RTC_MASKTAMPERFLAG_DISABLED RTC_TAMPERMASK_FLAG_DISABLE +#define RTC_MASKTAMPERFLAG_ENABLED RTC_TAMPERMASK_FLAG_ENABLE +#define RTC_TAMPERERASEBACKUP_ENABLED RTC_TAMPER_ERASE_BACKUP_ENABLE +#define RTC_TAMPER1_2_INTERRUPT RTC_ALL_TAMPER_INTERRUPT +#define RTC_TAMPER1_2_3_INTERRUPT RTC_ALL_TAMPER_INTERRUPT + +#define RTC_TIMESTAMPPIN_PC13 RTC_TIMESTAMPPIN_DEFAULT +#define RTC_TIMESTAMPPIN_PA0 RTC_TIMESTAMPPIN_POS1 +#define RTC_TIMESTAMPPIN_PI8 RTC_TIMESTAMPPIN_POS1 +#define RTC_TIMESTAMPPIN_PC1 RTC_TIMESTAMPPIN_POS2 + +#define RTC_OUTPUT_REMAP_PC13 RTC_OUTPUT_REMAP_NONE +#define RTC_OUTPUT_REMAP_PB14 RTC_OUTPUT_REMAP_POS1 +#define RTC_OUTPUT_REMAP_PB2 RTC_OUTPUT_REMAP_POS1 + +#define RTC_TAMPERPIN_PC13 RTC_TAMPERPIN_DEFAULT +#define RTC_TAMPERPIN_PA0 RTC_TAMPERPIN_POS1 +#define RTC_TAMPERPIN_PI8 RTC_TAMPERPIN_POS1 + +/** + * @} + */ + + +/** @defgroup HAL_SMARTCARD_Aliased_Defines HAL SMARTCARD Aliased Defines maintained for legacy purpose + * @{ + */ +#define SMARTCARD_NACK_ENABLED SMARTCARD_NACK_ENABLE +#define SMARTCARD_NACK_DISABLED SMARTCARD_NACK_DISABLE + +#define SMARTCARD_ONEBIT_SAMPLING_DISABLED SMARTCARD_ONE_BIT_SAMPLE_DISABLE +#define SMARTCARD_ONEBIT_SAMPLING_ENABLED SMARTCARD_ONE_BIT_SAMPLE_ENABLE +#define SMARTCARD_ONEBIT_SAMPLING_DISABLE SMARTCARD_ONE_BIT_SAMPLE_DISABLE +#define SMARTCARD_ONEBIT_SAMPLING_ENABLE SMARTCARD_ONE_BIT_SAMPLE_ENABLE + +#define SMARTCARD_TIMEOUT_DISABLED SMARTCARD_TIMEOUT_DISABLE +#define SMARTCARD_TIMEOUT_ENABLED SMARTCARD_TIMEOUT_ENABLE + +#define SMARTCARD_LASTBIT_DISABLED SMARTCARD_LASTBIT_DISABLE +#define SMARTCARD_LASTBIT_ENABLED SMARTCARD_LASTBIT_ENABLE +/** + * @} + */ + + +/** @defgroup HAL_SMBUS_Aliased_Defines HAL SMBUS Aliased Defines maintained for legacy purpose + * @{ + */ +#define SMBUS_DUALADDRESS_DISABLED SMBUS_DUALADDRESS_DISABLE +#define SMBUS_DUALADDRESS_ENABLED SMBUS_DUALADDRESS_ENABLE +#define SMBUS_GENERALCALL_DISABLED SMBUS_GENERALCALL_DISABLE +#define SMBUS_GENERALCALL_ENABLED SMBUS_GENERALCALL_ENABLE +#define SMBUS_NOSTRETCH_DISABLED SMBUS_NOSTRETCH_DISABLE +#define SMBUS_NOSTRETCH_ENABLED SMBUS_NOSTRETCH_ENABLE +#define SMBUS_ANALOGFILTER_ENABLED SMBUS_ANALOGFILTER_ENABLE +#define SMBUS_ANALOGFILTER_DISABLED SMBUS_ANALOGFILTER_DISABLE +#define SMBUS_PEC_DISABLED SMBUS_PEC_DISABLE +#define SMBUS_PEC_ENABLED SMBUS_PEC_ENABLE +#define HAL_SMBUS_STATE_SLAVE_LISTEN HAL_SMBUS_STATE_LISTEN +/** + * @} + */ + +/** @defgroup HAL_SPI_Aliased_Defines HAL SPI Aliased Defines maintained for legacy purpose + * @{ + */ +#define SPI_TIMODE_DISABLED SPI_TIMODE_DISABLE +#define SPI_TIMODE_ENABLED SPI_TIMODE_ENABLE + +#define SPI_CRCCALCULATION_DISABLED SPI_CRCCALCULATION_DISABLE +#define SPI_CRCCALCULATION_ENABLED SPI_CRCCALCULATION_ENABLE + +#define SPI_NSS_PULSE_DISABLED SPI_NSS_PULSE_DISABLE +#define SPI_NSS_PULSE_ENABLED SPI_NSS_PULSE_ENABLE + +/** + * @} + */ + +/** @defgroup HAL_TIM_Aliased_Defines HAL TIM Aliased Defines maintained for legacy purpose + * @{ + */ +#define CCER_CCxE_MASK TIM_CCER_CCxE_MASK +#define CCER_CCxNE_MASK TIM_CCER_CCxNE_MASK + +#define TIM_DMABase_CR1 TIM_DMABASE_CR1 +#define TIM_DMABase_CR2 TIM_DMABASE_CR2 +#define TIM_DMABase_SMCR TIM_DMABASE_SMCR +#define TIM_DMABase_DIER TIM_DMABASE_DIER +#define TIM_DMABase_SR TIM_DMABASE_SR +#define TIM_DMABase_EGR TIM_DMABASE_EGR +#define TIM_DMABase_CCMR1 TIM_DMABASE_CCMR1 +#define TIM_DMABase_CCMR2 TIM_DMABASE_CCMR2 +#define TIM_DMABase_CCER TIM_DMABASE_CCER +#define TIM_DMABase_CNT TIM_DMABASE_CNT +#define TIM_DMABase_PSC TIM_DMABASE_PSC +#define TIM_DMABase_ARR TIM_DMABASE_ARR +#define TIM_DMABase_RCR TIM_DMABASE_RCR +#define TIM_DMABase_CCR1 TIM_DMABASE_CCR1 +#define TIM_DMABase_CCR2 TIM_DMABASE_CCR2 +#define TIM_DMABase_CCR3 TIM_DMABASE_CCR3 +#define TIM_DMABase_CCR4 TIM_DMABASE_CCR4 +#define TIM_DMABase_BDTR TIM_DMABASE_BDTR +#define TIM_DMABase_DCR TIM_DMABASE_DCR +#define TIM_DMABase_DMAR TIM_DMABASE_DMAR +#define TIM_DMABase_OR1 TIM_DMABASE_OR1 +#define TIM_DMABase_CCMR3 TIM_DMABASE_CCMR3 +#define TIM_DMABase_CCR5 TIM_DMABASE_CCR5 +#define TIM_DMABase_CCR6 TIM_DMABASE_CCR6 +#define TIM_DMABase_OR2 TIM_DMABASE_OR2 +#define TIM_DMABase_OR3 TIM_DMABASE_OR3 +#define TIM_DMABase_OR TIM_DMABASE_OR + +#define TIM_EventSource_Update TIM_EVENTSOURCE_UPDATE +#define TIM_EventSource_CC1 TIM_EVENTSOURCE_CC1 +#define TIM_EventSource_CC2 TIM_EVENTSOURCE_CC2 +#define TIM_EventSource_CC3 TIM_EVENTSOURCE_CC3 +#define TIM_EventSource_CC4 TIM_EVENTSOURCE_CC4 +#define TIM_EventSource_COM TIM_EVENTSOURCE_COM +#define TIM_EventSource_Trigger TIM_EVENTSOURCE_TRIGGER +#define TIM_EventSource_Break TIM_EVENTSOURCE_BREAK +#define TIM_EventSource_Break2 TIM_EVENTSOURCE_BREAK2 + +#define TIM_DMABurstLength_1Transfer TIM_DMABURSTLENGTH_1TRANSFER +#define TIM_DMABurstLength_2Transfers TIM_DMABURSTLENGTH_2TRANSFERS +#define TIM_DMABurstLength_3Transfers TIM_DMABURSTLENGTH_3TRANSFERS +#define TIM_DMABurstLength_4Transfers TIM_DMABURSTLENGTH_4TRANSFERS +#define TIM_DMABurstLength_5Transfers TIM_DMABURSTLENGTH_5TRANSFERS +#define TIM_DMABurstLength_6Transfers TIM_DMABURSTLENGTH_6TRANSFERS +#define TIM_DMABurstLength_7Transfers TIM_DMABURSTLENGTH_7TRANSFERS +#define TIM_DMABurstLength_8Transfers TIM_DMABURSTLENGTH_8TRANSFERS +#define TIM_DMABurstLength_9Transfers TIM_DMABURSTLENGTH_9TRANSFERS +#define TIM_DMABurstLength_10Transfers TIM_DMABURSTLENGTH_10TRANSFERS +#define TIM_DMABurstLength_11Transfers TIM_DMABURSTLENGTH_11TRANSFERS +#define TIM_DMABurstLength_12Transfers TIM_DMABURSTLENGTH_12TRANSFERS +#define TIM_DMABurstLength_13Transfers TIM_DMABURSTLENGTH_13TRANSFERS +#define TIM_DMABurstLength_14Transfers TIM_DMABURSTLENGTH_14TRANSFERS +#define TIM_DMABurstLength_15Transfers TIM_DMABURSTLENGTH_15TRANSFERS +#define TIM_DMABurstLength_16Transfers TIM_DMABURSTLENGTH_16TRANSFERS +#define TIM_DMABurstLength_17Transfers TIM_DMABURSTLENGTH_17TRANSFERS +#define TIM_DMABurstLength_18Transfers TIM_DMABURSTLENGTH_18TRANSFERS + +/** + * @} + */ + +/** @defgroup HAL_TSC_Aliased_Defines HAL TSC Aliased Defines maintained for legacy purpose + * @{ + */ +#define TSC_SYNC_POL_FALL TSC_SYNC_POLARITY_FALLING +#define TSC_SYNC_POL_RISE_HIGH TSC_SYNC_POLARITY_RISING +/** + * @} + */ + +/** @defgroup HAL_UART_Aliased_Defines HAL UART Aliased Defines maintained for legacy purpose + * @{ + */ +#define UART_ONEBIT_SAMPLING_DISABLED UART_ONE_BIT_SAMPLE_DISABLE +#define UART_ONEBIT_SAMPLING_ENABLED UART_ONE_BIT_SAMPLE_ENABLE +#define UART_ONE_BIT_SAMPLE_DISABLED UART_ONE_BIT_SAMPLE_DISABLE +#define UART_ONE_BIT_SAMPLE_ENABLED UART_ONE_BIT_SAMPLE_ENABLE + +#define __HAL_UART_ONEBIT_ENABLE __HAL_UART_ONE_BIT_SAMPLE_ENABLE +#define __HAL_UART_ONEBIT_DISABLE __HAL_UART_ONE_BIT_SAMPLE_DISABLE + +#define __DIV_SAMPLING16 UART_DIV_SAMPLING16 +#define __DIVMANT_SAMPLING16 UART_DIVMANT_SAMPLING16 +#define __DIVFRAQ_SAMPLING16 UART_DIVFRAQ_SAMPLING16 +#define __UART_BRR_SAMPLING16 UART_BRR_SAMPLING16 + +#define __DIV_SAMPLING8 UART_DIV_SAMPLING8 +#define __DIVMANT_SAMPLING8 UART_DIVMANT_SAMPLING8 +#define __DIVFRAQ_SAMPLING8 UART_DIVFRAQ_SAMPLING8 +#define __UART_BRR_SAMPLING8 UART_BRR_SAMPLING8 + +#define __DIV_LPUART UART_DIV_LPUART + +#define UART_WAKEUPMETHODE_IDLELINE UART_WAKEUPMETHOD_IDLELINE +#define UART_WAKEUPMETHODE_ADDRESSMARK UART_WAKEUPMETHOD_ADDRESSMARK + +/** + * @} + */ + + +/** @defgroup HAL_USART_Aliased_Defines HAL USART Aliased Defines maintained for legacy purpose + * @{ + */ + +#define USART_CLOCK_DISABLED USART_CLOCK_DISABLE +#define USART_CLOCK_ENABLED USART_CLOCK_ENABLE + +#define USARTNACK_ENABLED USART_NACK_ENABLE +#define USARTNACK_DISABLED USART_NACK_DISABLE +/** + * @} + */ + +/** @defgroup HAL_WWDG_Aliased_Defines HAL WWDG Aliased Defines maintained for legacy purpose + * @{ + */ +#define CFR_BASE WWDG_CFR_BASE + +/** + * @} + */ + +/** @defgroup HAL_CAN_Aliased_Defines HAL CAN Aliased Defines maintained for legacy purpose + * @{ + */ +#define CAN_FilterFIFO0 CAN_FILTER_FIFO0 +#define CAN_FilterFIFO1 CAN_FILTER_FIFO1 +#define CAN_IT_RQCP0 CAN_IT_TME +#define CAN_IT_RQCP1 CAN_IT_TME +#define CAN_IT_RQCP2 CAN_IT_TME +#define INAK_TIMEOUT CAN_TIMEOUT_VALUE +#define SLAK_TIMEOUT CAN_TIMEOUT_VALUE +#define CAN_TXSTATUS_FAILED ((uint8_t)0x00U) +#define CAN_TXSTATUS_OK ((uint8_t)0x01U) +#define CAN_TXSTATUS_PENDING ((uint8_t)0x02U) + +/** + * @} + */ + +/** @defgroup HAL_ETH_Aliased_Defines HAL ETH Aliased Defines maintained for legacy purpose + * @{ + */ + +#define VLAN_TAG ETH_VLAN_TAG +#define MIN_ETH_PAYLOAD ETH_MIN_ETH_PAYLOAD +#define MAX_ETH_PAYLOAD ETH_MAX_ETH_PAYLOAD +#define JUMBO_FRAME_PAYLOAD ETH_JUMBO_FRAME_PAYLOAD +#define MACMIIAR_CR_MASK ETH_MACMIIAR_CR_MASK +#define MACCR_CLEAR_MASK ETH_MACCR_CLEAR_MASK +#define MACFCR_CLEAR_MASK ETH_MACFCR_CLEAR_MASK +#define DMAOMR_CLEAR_MASK ETH_DMAOMR_CLEAR_MASK + +#define ETH_MMCCR 0x00000100U +#define ETH_MMCRIR 0x00000104U +#define ETH_MMCTIR 0x00000108U +#define ETH_MMCRIMR 0x0000010CU +#define ETH_MMCTIMR 0x00000110U +#define ETH_MMCTGFSCCR 0x0000014CU +#define ETH_MMCTGFMSCCR 0x00000150U +#define ETH_MMCTGFCR 0x00000168U +#define ETH_MMCRFCECR 0x00000194U +#define ETH_MMCRFAECR 0x00000198U +#define ETH_MMCRGUFCR 0x000001C4U + +#define ETH_MAC_TXFIFO_FULL 0x02000000U /* Tx FIFO full */ +#define ETH_MAC_TXFIFONOT_EMPTY 0x01000000U /* Tx FIFO not empty */ +#define ETH_MAC_TXFIFO_WRITE_ACTIVE 0x00400000U /* Tx FIFO write active */ +#define ETH_MAC_TXFIFO_IDLE 0x00000000U /* Tx FIFO read status: Idle */ +#define ETH_MAC_TXFIFO_READ 0x00100000U /* Tx FIFO read status: Read (transferring data to the MAC transmitter) */ +#define ETH_MAC_TXFIFO_WAITING 0x00200000U /* Tx FIFO read status: Waiting for TxStatus from MAC transmitter */ +#define ETH_MAC_TXFIFO_WRITING 0x00300000U /* Tx FIFO read status: Writing the received TxStatus or flushing the TxFIFO */ +#define ETH_MAC_TRANSMISSION_PAUSE 0x00080000U /* MAC transmitter in pause */ +#define ETH_MAC_TRANSMITFRAMECONTROLLER_IDLE 0x00000000U /* MAC transmit frame controller: Idle */ +#define ETH_MAC_TRANSMITFRAMECONTROLLER_WAITING 0x00020000U /* MAC transmit frame controller: Waiting for Status of previous frame or IFG/backoff period to be over */ +#define ETH_MAC_TRANSMITFRAMECONTROLLER_GENRATING_PCF 0x00040000U /* MAC transmit frame controller: Generating and transmitting a Pause control frame (in full duplex mode) */ +#define ETH_MAC_TRANSMITFRAMECONTROLLER_TRANSFERRING 0x00060000U /* MAC transmit frame controller: Transferring input frame for transmission */ +#define ETH_MAC_MII_TRANSMIT_ACTIVE 0x00010000U /* MAC MII transmit engine active */ +#define ETH_MAC_RXFIFO_EMPTY 0x00000000U /* Rx FIFO fill level: empty */ +#define ETH_MAC_RXFIFO_BELOW_THRESHOLD 0x00000100U /* Rx FIFO fill level: fill-level below flow-control de-activate threshold */ +#define ETH_MAC_RXFIFO_ABOVE_THRESHOLD 0x00000200U /* Rx FIFO fill level: fill-level above flow-control activate threshold */ +#define ETH_MAC_RXFIFO_FULL 0x00000300U /* Rx FIFO fill level: full */ +#if defined(STM32F1) +#else +#define ETH_MAC_READCONTROLLER_IDLE 0x00000000U /* Rx FIFO read controller IDLE state */ +#define ETH_MAC_READCONTROLLER_READING_DATA 0x00000020U /* Rx FIFO read controller Reading frame data */ +#define ETH_MAC_READCONTROLLER_READING_STATUS 0x00000040U /* Rx FIFO read controller Reading frame status (or time-stamp) */ +#endif +#define ETH_MAC_READCONTROLLER_FLUSHING 0x00000060U /* Rx FIFO read controller Flushing the frame data and status */ +#define ETH_MAC_RXFIFO_WRITE_ACTIVE 0x00000010U /* Rx FIFO write controller active */ +#define ETH_MAC_SMALL_FIFO_NOTACTIVE 0x00000000U /* MAC small FIFO read / write controllers not active */ +#define ETH_MAC_SMALL_FIFO_READ_ACTIVE 0x00000002U /* MAC small FIFO read controller active */ +#define ETH_MAC_SMALL_FIFO_WRITE_ACTIVE 0x00000004U /* MAC small FIFO write controller active */ +#define ETH_MAC_SMALL_FIFO_RW_ACTIVE 0x00000006U /* MAC small FIFO read / write controllers active */ +#define ETH_MAC_MII_RECEIVE_PROTOCOL_ACTIVE 0x00000001U /* MAC MII receive protocol engine active */ + +/** + * @} + */ + +/** @defgroup HAL_DCMI_Aliased_Defines HAL DCMI Aliased Defines maintained for legacy purpose + * @{ + */ +#define HAL_DCMI_ERROR_OVF HAL_DCMI_ERROR_OVR +#define DCMI_IT_OVF DCMI_IT_OVR +#define DCMI_FLAG_OVFRI DCMI_FLAG_OVRRI +#define DCMI_FLAG_OVFMI DCMI_FLAG_OVRMI + +#define HAL_DCMI_ConfigCROP HAL_DCMI_ConfigCrop +#define HAL_DCMI_EnableCROP HAL_DCMI_EnableCrop +#define HAL_DCMI_DisableCROP HAL_DCMI_DisableCrop + +/** + * @} + */ + +#if defined(STM32L4) || defined(STM32F7) || defined(STM32F427xx) || defined(STM32F437xx) ||\ + defined(STM32F429xx) || defined(STM32F439xx) || defined(STM32F469xx) || defined(STM32F479xx) +/** @defgroup HAL_DMA2D_Aliased_Defines HAL DMA2D Aliased Defines maintained for legacy purpose + * @{ + */ +#define DMA2D_ARGB8888 DMA2D_OUTPUT_ARGB8888 +#define DMA2D_RGB888 DMA2D_OUTPUT_RGB888 +#define DMA2D_RGB565 DMA2D_OUTPUT_RGB565 +#define DMA2D_ARGB1555 DMA2D_OUTPUT_ARGB1555 +#define DMA2D_ARGB4444 DMA2D_OUTPUT_ARGB4444 + +#define CM_ARGB8888 DMA2D_INPUT_ARGB8888 +#define CM_RGB888 DMA2D_INPUT_RGB888 +#define CM_RGB565 DMA2D_INPUT_RGB565 +#define CM_ARGB1555 DMA2D_INPUT_ARGB1555 +#define CM_ARGB4444 DMA2D_INPUT_ARGB4444 +#define CM_L8 DMA2D_INPUT_L8 +#define CM_AL44 DMA2D_INPUT_AL44 +#define CM_AL88 DMA2D_INPUT_AL88 +#define CM_L4 DMA2D_INPUT_L4 +#define CM_A8 DMA2D_INPUT_A8 +#define CM_A4 DMA2D_INPUT_A4 +/** + * @} + */ +#endif /* STM32L4 || STM32F7*/ + +/** @defgroup HAL_PPP_Aliased_Defines HAL PPP Aliased Defines maintained for legacy purpose + * @{ + */ + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup HAL_CRYP_Aliased_Functions HAL CRYP Aliased Functions maintained for legacy purpose + * @{ + */ +#define HAL_CRYP_ComputationCpltCallback HAL_CRYPEx_ComputationCpltCallback +/** + * @} + */ + +/** @defgroup HAL_HASH_Aliased_Functions HAL HASH Aliased Functions maintained for legacy purpose + * @{ + */ +#define HAL_HASH_STATETypeDef HAL_HASH_StateTypeDef +#define HAL_HASHPhaseTypeDef HAL_HASH_PhaseTypeDef +#define HAL_HMAC_MD5_Finish HAL_HASH_MD5_Finish +#define HAL_HMAC_SHA1_Finish HAL_HASH_SHA1_Finish +#define HAL_HMAC_SHA224_Finish HAL_HASH_SHA224_Finish +#define HAL_HMAC_SHA256_Finish HAL_HASH_SHA256_Finish + +/*HASH Algorithm Selection*/ + +#define HASH_AlgoSelection_SHA1 HASH_ALGOSELECTION_SHA1 +#define HASH_AlgoSelection_SHA224 HASH_ALGOSELECTION_SHA224 +#define HASH_AlgoSelection_SHA256 HASH_ALGOSELECTION_SHA256 +#define HASH_AlgoSelection_MD5 HASH_ALGOSELECTION_MD5 + +#define HASH_AlgoMode_HASH HASH_ALGOMODE_HASH +#define HASH_AlgoMode_HMAC HASH_ALGOMODE_HMAC + +#define HASH_HMACKeyType_ShortKey HASH_HMAC_KEYTYPE_SHORTKEY +#define HASH_HMACKeyType_LongKey HASH_HMAC_KEYTYPE_LONGKEY +/** + * @} + */ + +/** @defgroup HAL_Aliased_Functions HAL Generic Aliased Functions maintained for legacy purpose + * @{ + */ +#define HAL_EnableDBGSleepMode HAL_DBGMCU_EnableDBGSleepMode +#define HAL_DisableDBGSleepMode HAL_DBGMCU_DisableDBGSleepMode +#define HAL_EnableDBGStopMode HAL_DBGMCU_EnableDBGStopMode +#define HAL_DisableDBGStopMode HAL_DBGMCU_DisableDBGStopMode +#define HAL_EnableDBGStandbyMode HAL_DBGMCU_EnableDBGStandbyMode +#define HAL_DisableDBGStandbyMode HAL_DBGMCU_DisableDBGStandbyMode +#define HAL_DBG_LowPowerConfig(Periph, cmd) (((cmd)==ENABLE)? HAL_DBGMCU_DBG_EnableLowPowerConfig(Periph) : HAL_DBGMCU_DBG_DisableLowPowerConfig(Periph)) +#define HAL_VREFINT_OutputSelect HAL_SYSCFG_VREFINT_OutputSelect +#define HAL_Lock_Cmd(cmd) (((cmd)==ENABLE) ? HAL_SYSCFG_Enable_Lock_VREFINT() : HAL_SYSCFG_Disable_Lock_VREFINT()) +#if defined(STM32L0) +#else +#define HAL_VREFINT_Cmd(cmd) (((cmd)==ENABLE)? HAL_SYSCFG_EnableVREFINT() : HAL_SYSCFG_DisableVREFINT()) +#endif +#define HAL_ADC_EnableBuffer_Cmd(cmd) (((cmd)==ENABLE) ? HAL_ADCEx_EnableVREFINT() : HAL_ADCEx_DisableVREFINT()) +#define HAL_ADC_EnableBufferSensor_Cmd(cmd) (((cmd)==ENABLE) ? HAL_ADCEx_EnableVREFINTTempSensor() : HAL_ADCEx_DisableVREFINTTempSensor()) +/** + * @} + */ + +/** @defgroup HAL_FLASH_Aliased_Functions HAL FLASH Aliased Functions maintained for legacy purpose + * @{ + */ +#define FLASH_HalfPageProgram HAL_FLASHEx_HalfPageProgram +#define FLASH_EnableRunPowerDown HAL_FLASHEx_EnableRunPowerDown +#define FLASH_DisableRunPowerDown HAL_FLASHEx_DisableRunPowerDown +#define HAL_DATA_EEPROMEx_Unlock HAL_FLASHEx_DATAEEPROM_Unlock +#define HAL_DATA_EEPROMEx_Lock HAL_FLASHEx_DATAEEPROM_Lock +#define HAL_DATA_EEPROMEx_Erase HAL_FLASHEx_DATAEEPROM_Erase +#define HAL_DATA_EEPROMEx_Program HAL_FLASHEx_DATAEEPROM_Program + + /** + * @} + */ + +/** @defgroup HAL_I2C_Aliased_Functions HAL I2C Aliased Functions maintained for legacy purpose + * @{ + */ +#define HAL_I2CEx_AnalogFilter_Config HAL_I2CEx_ConfigAnalogFilter +#define HAL_I2CEx_DigitalFilter_Config HAL_I2CEx_ConfigDigitalFilter +#define HAL_FMPI2CEx_AnalogFilter_Config HAL_FMPI2CEx_ConfigAnalogFilter +#define HAL_FMPI2CEx_DigitalFilter_Config HAL_FMPI2CEx_ConfigDigitalFilter + +#define HAL_I2CFastModePlusConfig(SYSCFG_I2CFastModePlus, cmd) (((cmd)==ENABLE)? HAL_I2CEx_EnableFastModePlus(SYSCFG_I2CFastModePlus): HAL_I2CEx_DisableFastModePlus(SYSCFG_I2CFastModePlus)) + /** + * @} + */ + +/** @defgroup HAL_PWR_Aliased HAL PWR Aliased maintained for legacy purpose + * @{ + */ +#define HAL_PWR_PVDConfig HAL_PWR_ConfigPVD +#define HAL_PWR_DisableBkUpReg HAL_PWREx_DisableBkUpReg +#define HAL_PWR_DisableFlashPowerDown HAL_PWREx_DisableFlashPowerDown +#define HAL_PWR_DisableVddio2Monitor HAL_PWREx_DisableVddio2Monitor +#define HAL_PWR_EnableBkUpReg HAL_PWREx_EnableBkUpReg +#define HAL_PWR_EnableFlashPowerDown HAL_PWREx_EnableFlashPowerDown +#define HAL_PWR_EnableVddio2Monitor HAL_PWREx_EnableVddio2Monitor +#define HAL_PWR_PVD_PVM_IRQHandler HAL_PWREx_PVD_PVM_IRQHandler +#define HAL_PWR_PVDLevelConfig HAL_PWR_ConfigPVD +#define HAL_PWR_Vddio2Monitor_IRQHandler HAL_PWREx_Vddio2Monitor_IRQHandler +#define HAL_PWR_Vddio2MonitorCallback HAL_PWREx_Vddio2MonitorCallback +#define HAL_PWREx_ActivateOverDrive HAL_PWREx_EnableOverDrive +#define HAL_PWREx_DeactivateOverDrive HAL_PWREx_DisableOverDrive +#define HAL_PWREx_DisableSDADCAnalog HAL_PWREx_DisableSDADC +#define HAL_PWREx_EnableSDADCAnalog HAL_PWREx_EnableSDADC +#define HAL_PWREx_PVMConfig HAL_PWREx_ConfigPVM + +#define PWR_MODE_NORMAL PWR_PVD_MODE_NORMAL +#define PWR_MODE_IT_RISING PWR_PVD_MODE_IT_RISING +#define PWR_MODE_IT_FALLING PWR_PVD_MODE_IT_FALLING +#define PWR_MODE_IT_RISING_FALLING PWR_PVD_MODE_IT_RISING_FALLING +#define PWR_MODE_EVENT_RISING PWR_PVD_MODE_EVENT_RISING +#define PWR_MODE_EVENT_FALLING PWR_PVD_MODE_EVENT_FALLING +#define PWR_MODE_EVENT_RISING_FALLING PWR_PVD_MODE_EVENT_RISING_FALLING + +#define CR_OFFSET_BB PWR_CR_OFFSET_BB +#define CSR_OFFSET_BB PWR_CSR_OFFSET_BB +#define PMODE_BIT_NUMBER VOS_BIT_NUMBER +#define CR_PMODE_BB CR_VOS_BB + +#define DBP_BitNumber DBP_BIT_NUMBER +#define PVDE_BitNumber PVDE_BIT_NUMBER +#define PMODE_BitNumber PMODE_BIT_NUMBER +#define EWUP_BitNumber EWUP_BIT_NUMBER +#define FPDS_BitNumber FPDS_BIT_NUMBER +#define ODEN_BitNumber ODEN_BIT_NUMBER +#define ODSWEN_BitNumber ODSWEN_BIT_NUMBER +#define MRLVDS_BitNumber MRLVDS_BIT_NUMBER +#define LPLVDS_BitNumber LPLVDS_BIT_NUMBER +#define BRE_BitNumber BRE_BIT_NUMBER + +#define PWR_MODE_EVT PWR_PVD_MODE_NORMAL + + /** + * @} + */ + +/** @defgroup HAL_SMBUS_Aliased_Functions HAL SMBUS Aliased Functions maintained for legacy purpose + * @{ + */ +#define HAL_SMBUS_Slave_Listen_IT HAL_SMBUS_EnableListen_IT +#define HAL_SMBUS_SlaveAddrCallback HAL_SMBUS_AddrCallback +#define HAL_SMBUS_SlaveListenCpltCallback HAL_SMBUS_ListenCpltCallback +/** + * @} + */ + +/** @defgroup HAL_SPI_Aliased_Functions HAL SPI Aliased Functions maintained for legacy purpose + * @{ + */ +#define HAL_SPI_FlushRxFifo HAL_SPIEx_FlushRxFifo +/** + * @} + */ + +/** @defgroup HAL_TIM_Aliased_Functions HAL TIM Aliased Functions maintained for legacy purpose + * @{ + */ +#define HAL_TIM_DMADelayPulseCplt TIM_DMADelayPulseCplt +#define HAL_TIM_DMAError TIM_DMAError +#define HAL_TIM_DMACaptureCplt TIM_DMACaptureCplt +#define HAL_TIMEx_DMACommutationCplt TIMEx_DMACommutationCplt +/** + * @} + */ + +/** @defgroup HAL_UART_Aliased_Functions HAL UART Aliased Functions maintained for legacy purpose + * @{ + */ +#define HAL_UART_WakeupCallback HAL_UARTEx_WakeupCallback +/** + * @} + */ + +/** @defgroup HAL_LTDC_Aliased_Functions HAL LTDC Aliased Functions maintained for legacy purpose + * @{ + */ +#define HAL_LTDC_LineEvenCallback HAL_LTDC_LineEventCallback +#define HAL_LTDC_Relaod HAL_LTDC_Reload +#define HAL_LTDC_StructInitFromVideoConfig HAL_LTDCEx_StructInitFromVideoConfig +#define HAL_LTDC_StructInitFromAdaptedCommandConfig HAL_LTDCEx_StructInitFromAdaptedCommandConfig +/** + * @} + */ + + +/** @defgroup HAL_PPP_Aliased_Functions HAL PPP Aliased Functions maintained for legacy purpose + * @{ + */ + +/** + * @} + */ + +/* Exported macros ------------------------------------------------------------*/ + +/** @defgroup HAL_AES_Aliased_Macros HAL CRYP Aliased Macros maintained for legacy purpose + * @{ + */ +#define AES_IT_CC CRYP_IT_CC +#define AES_IT_ERR CRYP_IT_ERR +#define AES_FLAG_CCF CRYP_FLAG_CCF +/** + * @} + */ + +/** @defgroup HAL_Aliased_Macros HAL Generic Aliased Macros maintained for legacy purpose + * @{ + */ +#define __HAL_GET_BOOT_MODE __HAL_SYSCFG_GET_BOOT_MODE +#define __HAL_REMAPMEMORY_FLASH __HAL_SYSCFG_REMAPMEMORY_FLASH +#define __HAL_REMAPMEMORY_SYSTEMFLASH __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH +#define __HAL_REMAPMEMORY_SRAM __HAL_SYSCFG_REMAPMEMORY_SRAM +#define __HAL_REMAPMEMORY_FMC __HAL_SYSCFG_REMAPMEMORY_FMC +#define __HAL_REMAPMEMORY_FMC_SDRAM __HAL_SYSCFG_REMAPMEMORY_FMC_SDRAM +#define __HAL_REMAPMEMORY_FSMC __HAL_SYSCFG_REMAPMEMORY_FSMC +#define __HAL_REMAPMEMORY_QUADSPI __HAL_SYSCFG_REMAPMEMORY_QUADSPI +#define __HAL_FMC_BANK __HAL_SYSCFG_FMC_BANK +#define __HAL_GET_FLAG __HAL_SYSCFG_GET_FLAG +#define __HAL_CLEAR_FLAG __HAL_SYSCFG_CLEAR_FLAG +#define __HAL_VREFINT_OUT_ENABLE __HAL_SYSCFG_VREFINT_OUT_ENABLE +#define __HAL_VREFINT_OUT_DISABLE __HAL_SYSCFG_VREFINT_OUT_DISABLE +#define __HAL_SYSCFG_SRAM2_WRP_ENABLE __HAL_SYSCFG_SRAM2_WRP_0_31_ENABLE + +#define SYSCFG_FLAG_VREF_READY SYSCFG_FLAG_VREFINT_READY +#define SYSCFG_FLAG_RC48 RCC_FLAG_HSI48 +#define IS_SYSCFG_FASTMODEPLUS_CONFIG IS_I2C_FASTMODEPLUS +#define UFB_MODE_BitNumber UFB_MODE_BIT_NUMBER +#define CMP_PD_BitNumber CMP_PD_BIT_NUMBER + +/** + * @} + */ + + +/** @defgroup HAL_ADC_Aliased_Macros HAL ADC Aliased Macros maintained for legacy purpose + * @{ + */ +#define __ADC_ENABLE __HAL_ADC_ENABLE +#define __ADC_DISABLE __HAL_ADC_DISABLE +#define __HAL_ADC_ENABLING_CONDITIONS ADC_ENABLING_CONDITIONS +#define __HAL_ADC_DISABLING_CONDITIONS ADC_DISABLING_CONDITIONS +#define __HAL_ADC_IS_ENABLED ADC_IS_ENABLE +#define __ADC_IS_ENABLED ADC_IS_ENABLE +#define __HAL_ADC_IS_SOFTWARE_START_REGULAR ADC_IS_SOFTWARE_START_REGULAR +#define __HAL_ADC_IS_SOFTWARE_START_INJECTED ADC_IS_SOFTWARE_START_INJECTED +#define __HAL_ADC_IS_CONVERSION_ONGOING_REGULAR_INJECTED ADC_IS_CONVERSION_ONGOING_REGULAR_INJECTED +#define __HAL_ADC_IS_CONVERSION_ONGOING_REGULAR ADC_IS_CONVERSION_ONGOING_REGULAR +#define __HAL_ADC_IS_CONVERSION_ONGOING_INJECTED ADC_IS_CONVERSION_ONGOING_INJECTED +#define __HAL_ADC_IS_CONVERSION_ONGOING ADC_IS_CONVERSION_ONGOING +#define __HAL_ADC_CLEAR_ERRORCODE ADC_CLEAR_ERRORCODE + +#define __HAL_ADC_GET_RESOLUTION ADC_GET_RESOLUTION +#define __HAL_ADC_JSQR_RK ADC_JSQR_RK +#define __HAL_ADC_CFGR_AWD1CH ADC_CFGR_AWD1CH_SHIFT +#define __HAL_ADC_CFGR_AWD23CR ADC_CFGR_AWD23CR +#define __HAL_ADC_CFGR_INJECT_AUTO_CONVERSION ADC_CFGR_INJECT_AUTO_CONVERSION +#define __HAL_ADC_CFGR_INJECT_CONTEXT_QUEUE ADC_CFGR_INJECT_CONTEXT_QUEUE +#define __HAL_ADC_CFGR_INJECT_DISCCONTINUOUS ADC_CFGR_INJECT_DISCCONTINUOUS +#define __HAL_ADC_CFGR_REG_DISCCONTINUOUS ADC_CFGR_REG_DISCCONTINUOUS +#define __HAL_ADC_CFGR_DISCONTINUOUS_NUM ADC_CFGR_DISCONTINUOUS_NUM +#define __HAL_ADC_CFGR_AUTOWAIT ADC_CFGR_AUTOWAIT +#define __HAL_ADC_CFGR_CONTINUOUS ADC_CFGR_CONTINUOUS +#define __HAL_ADC_CFGR_OVERRUN ADC_CFGR_OVERRUN +#define __HAL_ADC_CFGR_DMACONTREQ ADC_CFGR_DMACONTREQ +#define __HAL_ADC_CFGR_EXTSEL ADC_CFGR_EXTSEL_SET +#define __HAL_ADC_JSQR_JEXTSEL ADC_JSQR_JEXTSEL_SET +#define __HAL_ADC_OFR_CHANNEL ADC_OFR_CHANNEL +#define __HAL_ADC_DIFSEL_CHANNEL ADC_DIFSEL_CHANNEL +#define __HAL_ADC_CALFACT_DIFF_SET ADC_CALFACT_DIFF_SET +#define __HAL_ADC_CALFACT_DIFF_GET ADC_CALFACT_DIFF_GET +#define __HAL_ADC_TRX_HIGHTHRESHOLD ADC_TRX_HIGHTHRESHOLD + +#define __HAL_ADC_OFFSET_SHIFT_RESOLUTION ADC_OFFSET_SHIFT_RESOLUTION +#define __HAL_ADC_AWD1THRESHOLD_SHIFT_RESOLUTION ADC_AWD1THRESHOLD_SHIFT_RESOLUTION +#define __HAL_ADC_AWD23THRESHOLD_SHIFT_RESOLUTION ADC_AWD23THRESHOLD_SHIFT_RESOLUTION +#define __HAL_ADC_COMMON_REGISTER ADC_COMMON_REGISTER +#define __HAL_ADC_COMMON_CCR_MULTI ADC_COMMON_CCR_MULTI +#define __HAL_ADC_MULTIMODE_IS_ENABLED ADC_MULTIMODE_IS_ENABLE +#define __ADC_MULTIMODE_IS_ENABLED ADC_MULTIMODE_IS_ENABLE +#define __HAL_ADC_NONMULTIMODE_OR_MULTIMODEMASTER ADC_NONMULTIMODE_OR_MULTIMODEMASTER +#define __HAL_ADC_COMMON_ADC_OTHER ADC_COMMON_ADC_OTHER +#define __HAL_ADC_MULTI_SLAVE ADC_MULTI_SLAVE + +#define __HAL_ADC_SQR1_L ADC_SQR1_L_SHIFT +#define __HAL_ADC_JSQR_JL ADC_JSQR_JL_SHIFT +#define __HAL_ADC_JSQR_RK_JL ADC_JSQR_RK_JL +#define __HAL_ADC_CR1_DISCONTINUOUS_NUM ADC_CR1_DISCONTINUOUS_NUM +#define __HAL_ADC_CR1_SCAN ADC_CR1_SCAN_SET +#define __HAL_ADC_CONVCYCLES_MAX_RANGE ADC_CONVCYCLES_MAX_RANGE +#define __HAL_ADC_CLOCK_PRESCALER_RANGE ADC_CLOCK_PRESCALER_RANGE +#define __HAL_ADC_GET_CLOCK_PRESCALER ADC_GET_CLOCK_PRESCALER + +#define __HAL_ADC_SQR1 ADC_SQR1 +#define __HAL_ADC_SMPR1 ADC_SMPR1 +#define __HAL_ADC_SMPR2 ADC_SMPR2 +#define __HAL_ADC_SQR3_RK ADC_SQR3_RK +#define __HAL_ADC_SQR2_RK ADC_SQR2_RK +#define __HAL_ADC_SQR1_RK ADC_SQR1_RK +#define __HAL_ADC_CR2_CONTINUOUS ADC_CR2_CONTINUOUS +#define __HAL_ADC_CR1_DISCONTINUOUS ADC_CR1_DISCONTINUOUS +#define __HAL_ADC_CR1_SCANCONV ADC_CR1_SCANCONV +#define __HAL_ADC_CR2_EOCSelection ADC_CR2_EOCSelection +#define __HAL_ADC_CR2_DMAContReq ADC_CR2_DMAContReq +#define __HAL_ADC_JSQR ADC_JSQR + +#define __HAL_ADC_CHSELR_CHANNEL ADC_CHSELR_CHANNEL +#define __HAL_ADC_CFGR1_REG_DISCCONTINUOUS ADC_CFGR1_REG_DISCCONTINUOUS +#define __HAL_ADC_CFGR1_AUTOOFF ADC_CFGR1_AUTOOFF +#define __HAL_ADC_CFGR1_AUTOWAIT ADC_CFGR1_AUTOWAIT +#define __HAL_ADC_CFGR1_CONTINUOUS ADC_CFGR1_CONTINUOUS +#define __HAL_ADC_CFGR1_OVERRUN ADC_CFGR1_OVERRUN +#define __HAL_ADC_CFGR1_SCANDIR ADC_CFGR1_SCANDIR +#define __HAL_ADC_CFGR1_DMACONTREQ ADC_CFGR1_DMACONTREQ + +/** + * @} + */ + +/** @defgroup HAL_DAC_Aliased_Macros HAL DAC Aliased Macros maintained for legacy purpose + * @{ + */ +#define __HAL_DHR12R1_ALIGNEMENT DAC_DHR12R1_ALIGNMENT +#define __HAL_DHR12R2_ALIGNEMENT DAC_DHR12R2_ALIGNMENT +#define __HAL_DHR12RD_ALIGNEMENT DAC_DHR12RD_ALIGNMENT +#define IS_DAC_GENERATE_WAVE IS_DAC_WAVE + +/** + * @} + */ + +/** @defgroup HAL_DBGMCU_Aliased_Macros HAL DBGMCU Aliased Macros maintained for legacy purpose + * @{ + */ +#define __HAL_FREEZE_TIM1_DBGMCU __HAL_DBGMCU_FREEZE_TIM1 +#define __HAL_UNFREEZE_TIM1_DBGMCU __HAL_DBGMCU_UNFREEZE_TIM1 +#define __HAL_FREEZE_TIM2_DBGMCU __HAL_DBGMCU_FREEZE_TIM2 +#define __HAL_UNFREEZE_TIM2_DBGMCU __HAL_DBGMCU_UNFREEZE_TIM2 +#define __HAL_FREEZE_TIM3_DBGMCU __HAL_DBGMCU_FREEZE_TIM3 +#define __HAL_UNFREEZE_TIM3_DBGMCU __HAL_DBGMCU_UNFREEZE_TIM3 +#define __HAL_FREEZE_TIM4_DBGMCU __HAL_DBGMCU_FREEZE_TIM4 +#define __HAL_UNFREEZE_TIM4_DBGMCU __HAL_DBGMCU_UNFREEZE_TIM4 +#define __HAL_FREEZE_TIM5_DBGMCU __HAL_DBGMCU_FREEZE_TIM5 +#define __HAL_UNFREEZE_TIM5_DBGMCU __HAL_DBGMCU_UNFREEZE_TIM5 +#define __HAL_FREEZE_TIM6_DBGMCU __HAL_DBGMCU_FREEZE_TIM6 +#define __HAL_UNFREEZE_TIM6_DBGMCU __HAL_DBGMCU_UNFREEZE_TIM6 +#define __HAL_FREEZE_TIM7_DBGMCU __HAL_DBGMCU_FREEZE_TIM7 +#define __HAL_UNFREEZE_TIM7_DBGMCU __HAL_DBGMCU_UNFREEZE_TIM7 +#define __HAL_FREEZE_TIM8_DBGMCU __HAL_DBGMCU_FREEZE_TIM8 +#define __HAL_UNFREEZE_TIM8_DBGMCU __HAL_DBGMCU_UNFREEZE_TIM8 + +#define __HAL_FREEZE_TIM9_DBGMCU __HAL_DBGMCU_FREEZE_TIM9 +#define __HAL_UNFREEZE_TIM9_DBGMCU __HAL_DBGMCU_UNFREEZE_TIM9 +#define __HAL_FREEZE_TIM10_DBGMCU __HAL_DBGMCU_FREEZE_TIM10 +#define __HAL_UNFREEZE_TIM10_DBGMCU __HAL_DBGMCU_UNFREEZE_TIM10 +#define __HAL_FREEZE_TIM11_DBGMCU __HAL_DBGMCU_FREEZE_TIM11 +#define __HAL_UNFREEZE_TIM11_DBGMCU __HAL_DBGMCU_UNFREEZE_TIM11 +#define __HAL_FREEZE_TIM12_DBGMCU __HAL_DBGMCU_FREEZE_TIM12 +#define __HAL_UNFREEZE_TIM12_DBGMCU __HAL_DBGMCU_UNFREEZE_TIM12 +#define __HAL_FREEZE_TIM13_DBGMCU __HAL_DBGMCU_FREEZE_TIM13 +#define __HAL_UNFREEZE_TIM13_DBGMCU __HAL_DBGMCU_UNFREEZE_TIM13 +#define __HAL_FREEZE_TIM14_DBGMCU __HAL_DBGMCU_FREEZE_TIM14 +#define __HAL_UNFREEZE_TIM14_DBGMCU __HAL_DBGMCU_UNFREEZE_TIM14 +#define __HAL_FREEZE_CAN2_DBGMCU __HAL_DBGMCU_FREEZE_CAN2 +#define __HAL_UNFREEZE_CAN2_DBGMCU __HAL_DBGMCU_UNFREEZE_CAN2 + + +#define __HAL_FREEZE_TIM15_DBGMCU __HAL_DBGMCU_FREEZE_TIM15 +#define __HAL_UNFREEZE_TIM15_DBGMCU __HAL_DBGMCU_UNFREEZE_TIM15 +#define __HAL_FREEZE_TIM16_DBGMCU __HAL_DBGMCU_FREEZE_TIM16 +#define __HAL_UNFREEZE_TIM16_DBGMCU __HAL_DBGMCU_UNFREEZE_TIM16 +#define __HAL_FREEZE_TIM17_DBGMCU __HAL_DBGMCU_FREEZE_TIM17 +#define __HAL_UNFREEZE_TIM17_DBGMCU __HAL_DBGMCU_UNFREEZE_TIM17 +#define __HAL_FREEZE_RTC_DBGMCU __HAL_DBGMCU_FREEZE_RTC +#define __HAL_UNFREEZE_RTC_DBGMCU __HAL_DBGMCU_UNFREEZE_RTC +#define __HAL_FREEZE_WWDG_DBGMCU __HAL_DBGMCU_FREEZE_WWDG +#define __HAL_UNFREEZE_WWDG_DBGMCU __HAL_DBGMCU_UNFREEZE_WWDG +#define __HAL_FREEZE_IWDG_DBGMCU __HAL_DBGMCU_FREEZE_IWDG +#define __HAL_UNFREEZE_IWDG_DBGMCU __HAL_DBGMCU_UNFREEZE_IWDG +#define __HAL_FREEZE_I2C1_TIMEOUT_DBGMCU __HAL_DBGMCU_FREEZE_I2C1_TIMEOUT +#define __HAL_UNFREEZE_I2C1_TIMEOUT_DBGMCU __HAL_DBGMCU_UNFREEZE_I2C1_TIMEOUT +#define __HAL_FREEZE_I2C2_TIMEOUT_DBGMCU __HAL_DBGMCU_FREEZE_I2C2_TIMEOUT +#define __HAL_UNFREEZE_I2C2_TIMEOUT_DBGMCU __HAL_DBGMCU_UNFREEZE_I2C2_TIMEOUT +#define __HAL_FREEZE_I2C3_TIMEOUT_DBGMCU __HAL_DBGMCU_FREEZE_I2C3_TIMEOUT +#define __HAL_UNFREEZE_I2C3_TIMEOUT_DBGMCU __HAL_DBGMCU_UNFREEZE_I2C3_TIMEOUT +#define __HAL_FREEZE_CAN1_DBGMCU __HAL_DBGMCU_FREEZE_CAN1 +#define __HAL_UNFREEZE_CAN1_DBGMCU __HAL_DBGMCU_UNFREEZE_CAN1 +#define __HAL_FREEZE_LPTIM1_DBGMCU __HAL_DBGMCU_FREEZE_LPTIM1 +#define __HAL_UNFREEZE_LPTIM1_DBGMCU __HAL_DBGMCU_UNFREEZE_LPTIM1 +#define __HAL_FREEZE_LPTIM2_DBGMCU __HAL_DBGMCU_FREEZE_LPTIM2 +#define __HAL_UNFREEZE_LPTIM2_DBGMCU __HAL_DBGMCU_UNFREEZE_LPTIM2 + +/** + * @} + */ + +/** @defgroup HAL_COMP_Aliased_Macros HAL COMP Aliased Macros maintained for legacy purpose + * @{ + */ +#if defined(STM32F3) +#define COMP_START __HAL_COMP_ENABLE +#define COMP_STOP __HAL_COMP_DISABLE +#define COMP_LOCK __HAL_COMP_LOCK + +#if defined(STM32F301x8) || defined(STM32F302x8) || defined(STM32F318xx) || defined(STM32F303x8) || defined(STM32F334x8) || defined(STM32F328xx) +#define __HAL_COMP_EXTI_RISING_IT_ENABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_ENABLE_RISING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_ENABLE_RISING_EDGE() : \ + __HAL_COMP_COMP6_EXTI_ENABLE_RISING_EDGE()) +#define __HAL_COMP_EXTI_RISING_IT_DISABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_DISABLE_RISING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_DISABLE_RISING_EDGE() : \ + __HAL_COMP_COMP6_EXTI_DISABLE_RISING_EDGE()) +#define __HAL_COMP_EXTI_FALLING_IT_ENABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_ENABLE_FALLING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_ENABLE_FALLING_EDGE() : \ + __HAL_COMP_COMP6_EXTI_ENABLE_FALLING_EDGE()) +#define __HAL_COMP_EXTI_FALLING_IT_DISABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_DISABLE_FALLING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_DISABLE_FALLING_EDGE() : \ + __HAL_COMP_COMP6_EXTI_DISABLE_FALLING_EDGE()) +#define __HAL_COMP_EXTI_ENABLE_IT(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_ENABLE_IT() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_ENABLE_IT() : \ + __HAL_COMP_COMP6_EXTI_ENABLE_IT()) +#define __HAL_COMP_EXTI_DISABLE_IT(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_DISABLE_IT() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_DISABLE_IT() : \ + __HAL_COMP_COMP6_EXTI_DISABLE_IT()) +#define __HAL_COMP_EXTI_GET_FLAG(__FLAG__) (((__FLAG__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_GET_FLAG() : \ + ((__FLAG__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_GET_FLAG() : \ + __HAL_COMP_COMP6_EXTI_GET_FLAG()) +#define __HAL_COMP_EXTI_CLEAR_FLAG(__FLAG__) (((__FLAG__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_CLEAR_FLAG() : \ + ((__FLAG__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_CLEAR_FLAG() : \ + __HAL_COMP_COMP6_EXTI_CLEAR_FLAG()) +# endif +# if defined(STM32F302xE) || defined(STM32F302xC) +#define __HAL_COMP_EXTI_RISING_IT_ENABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_ENABLE_RISING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_ENABLE_RISING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_ENABLE_RISING_EDGE() : \ + __HAL_COMP_COMP6_EXTI_ENABLE_RISING_EDGE()) +#define __HAL_COMP_EXTI_RISING_IT_DISABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_DISABLE_RISING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_DISABLE_RISING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_DISABLE_RISING_EDGE() : \ + __HAL_COMP_COMP6_EXTI_DISABLE_RISING_EDGE()) +#define __HAL_COMP_EXTI_FALLING_IT_ENABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_ENABLE_FALLING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_ENABLE_FALLING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_ENABLE_FALLING_EDGE() : \ + __HAL_COMP_COMP6_EXTI_ENABLE_FALLING_EDGE()) +#define __HAL_COMP_EXTI_FALLING_IT_DISABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_DISABLE_FALLING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_DISABLE_FALLING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_DISABLE_FALLING_EDGE() : \ + __HAL_COMP_COMP6_EXTI_DISABLE_FALLING_EDGE()) +#define __HAL_COMP_EXTI_ENABLE_IT(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_ENABLE_IT() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_ENABLE_IT() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_ENABLE_IT() : \ + __HAL_COMP_COMP6_EXTI_ENABLE_IT()) +#define __HAL_COMP_EXTI_DISABLE_IT(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_DISABLE_IT() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_DISABLE_IT() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_DISABLE_IT() : \ + __HAL_COMP_COMP6_EXTI_DISABLE_IT()) +#define __HAL_COMP_EXTI_GET_FLAG(__FLAG__) (((__FLAG__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_GET_FLAG() : \ + ((__FLAG__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_GET_FLAG() : \ + ((__FLAG__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_GET_FLAG() : \ + __HAL_COMP_COMP6_EXTI_GET_FLAG()) +#define __HAL_COMP_EXTI_CLEAR_FLAG(__FLAG__) (((__FLAG__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_CLEAR_FLAG() : \ + ((__FLAG__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_CLEAR_FLAG() : \ + ((__FLAG__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_CLEAR_FLAG() : \ + __HAL_COMP_COMP6_EXTI_CLEAR_FLAG()) +# endif +# if defined(STM32F303xE) || defined(STM32F398xx) || defined(STM32F303xC) || defined(STM32F358xx) +#define __HAL_COMP_EXTI_RISING_IT_ENABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_ENABLE_RISING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_ENABLE_RISING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP3) ? __HAL_COMP_COMP3_EXTI_ENABLE_RISING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_ENABLE_RISING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP5) ? __HAL_COMP_COMP5_EXTI_ENABLE_RISING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP6) ? __HAL_COMP_COMP6_EXTI_ENABLE_RISING_EDGE() : \ + __HAL_COMP_COMP7_EXTI_ENABLE_RISING_EDGE()) +#define __HAL_COMP_EXTI_RISING_IT_DISABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_DISABLE_RISING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_DISABLE_RISING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP3) ? __HAL_COMP_COMP3_EXTI_DISABLE_RISING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_DISABLE_RISING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP5) ? __HAL_COMP_COMP5_EXTI_DISABLE_RISING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP6) ? __HAL_COMP_COMP6_EXTI_DISABLE_RISING_EDGE() : \ + __HAL_COMP_COMP7_EXTI_DISABLE_RISING_EDGE()) +#define __HAL_COMP_EXTI_FALLING_IT_ENABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_ENABLE_FALLING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_ENABLE_FALLING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP3) ? __HAL_COMP_COMP3_EXTI_ENABLE_FALLING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_ENABLE_FALLING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP5) ? __HAL_COMP_COMP5_EXTI_ENABLE_FALLING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP6) ? __HAL_COMP_COMP6_EXTI_ENABLE_FALLING_EDGE() : \ + __HAL_COMP_COMP7_EXTI_ENABLE_FALLING_EDGE()) +#define __HAL_COMP_EXTI_FALLING_IT_DISABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_DISABLE_FALLING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_DISABLE_FALLING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP3) ? __HAL_COMP_COMP3_EXTI_DISABLE_FALLING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_DISABLE_FALLING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP5) ? __HAL_COMP_COMP5_EXTI_DISABLE_FALLING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP6) ? __HAL_COMP_COMP6_EXTI_DISABLE_FALLING_EDGE() : \ + __HAL_COMP_COMP7_EXTI_DISABLE_FALLING_EDGE()) +#define __HAL_COMP_EXTI_ENABLE_IT(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_ENABLE_IT() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_ENABLE_IT() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP3) ? __HAL_COMP_COMP3_EXTI_ENABLE_IT() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_ENABLE_IT() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP5) ? __HAL_COMP_COMP5_EXTI_ENABLE_IT() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP6) ? __HAL_COMP_COMP6_EXTI_ENABLE_IT() : \ + __HAL_COMP_COMP7_EXTI_ENABLE_IT()) +#define __HAL_COMP_EXTI_DISABLE_IT(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_DISABLE_IT() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_DISABLE_IT() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP3) ? __HAL_COMP_COMP3_EXTI_DISABLE_IT() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_DISABLE_IT() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP5) ? __HAL_COMP_COMP5_EXTI_DISABLE_IT() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP6) ? __HAL_COMP_COMP6_EXTI_DISABLE_IT() : \ + __HAL_COMP_COMP7_EXTI_DISABLE_IT()) +#define __HAL_COMP_EXTI_GET_FLAG(__FLAG__) (((__FLAG__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_GET_FLAG() : \ + ((__FLAG__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_GET_FLAG() : \ + ((__FLAG__) == COMP_EXTI_LINE_COMP3) ? __HAL_COMP_COMP3_EXTI_GET_FLAG() : \ + ((__FLAG__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_GET_FLAG() : \ + ((__FLAG__) == COMP_EXTI_LINE_COMP5) ? __HAL_COMP_COMP5_EXTI_GET_FLAG() : \ + ((__FLAG__) == COMP_EXTI_LINE_COMP6) ? __HAL_COMP_COMP6_EXTI_GET_FLAG() : \ + __HAL_COMP_COMP7_EXTI_GET_FLAG()) +#define __HAL_COMP_EXTI_CLEAR_FLAG(__FLAG__) (((__FLAG__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_CLEAR_FLAG() : \ + ((__FLAG__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_CLEAR_FLAG() : \ + ((__FLAG__) == COMP_EXTI_LINE_COMP3) ? __HAL_COMP_COMP3_EXTI_CLEAR_FLAG() : \ + ((__FLAG__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_CLEAR_FLAG() : \ + ((__FLAG__) == COMP_EXTI_LINE_COMP5) ? __HAL_COMP_COMP5_EXTI_CLEAR_FLAG() : \ + ((__FLAG__) == COMP_EXTI_LINE_COMP6) ? __HAL_COMP_COMP6_EXTI_CLEAR_FLAG() : \ + __HAL_COMP_COMP7_EXTI_CLEAR_FLAG()) +# endif +# if defined(STM32F373xC) ||defined(STM32F378xx) +#define __HAL_COMP_EXTI_RISING_IT_ENABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_ENABLE_RISING_EDGE() : \ + __HAL_COMP_COMP2_EXTI_ENABLE_RISING_EDGE()) +#define __HAL_COMP_EXTI_RISING_IT_DISABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_DISABLE_RISING_EDGE() : \ + __HAL_COMP_COMP2_EXTI_DISABLE_RISING_EDGE()) +#define __HAL_COMP_EXTI_FALLING_IT_ENABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_ENABLE_FALLING_EDGE() : \ + __HAL_COMP_COMP2_EXTI_ENABLE_FALLING_EDGE()) +#define __HAL_COMP_EXTI_FALLING_IT_DISABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_DISABLE_FALLING_EDGE() : \ + __HAL_COMP_COMP2_EXTI_DISABLE_FALLING_EDGE()) +#define __HAL_COMP_EXTI_ENABLE_IT(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_ENABLE_IT() : \ + __HAL_COMP_COMP2_EXTI_ENABLE_IT()) +#define __HAL_COMP_EXTI_DISABLE_IT(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_DISABLE_IT() : \ + __HAL_COMP_COMP2_EXTI_DISABLE_IT()) +#define __HAL_COMP_EXTI_GET_FLAG(__FLAG__) (((__FLAG__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_GET_FLAG() : \ + __HAL_COMP_COMP2_EXTI_GET_FLAG()) +#define __HAL_COMP_EXTI_CLEAR_FLAG(__FLAG__) (((__FLAG__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_CLEAR_FLAG() : \ + __HAL_COMP_COMP2_EXTI_CLEAR_FLAG()) +# endif +#else +#define __HAL_COMP_EXTI_RISING_IT_ENABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_ENABLE_RISING_EDGE() : \ + __HAL_COMP_COMP2_EXTI_ENABLE_RISING_EDGE()) +#define __HAL_COMP_EXTI_RISING_IT_DISABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_DISABLE_RISING_EDGE() : \ + __HAL_COMP_COMP2_EXTI_DISABLE_RISING_EDGE()) +#define __HAL_COMP_EXTI_FALLING_IT_ENABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_ENABLE_FALLING_EDGE() : \ + __HAL_COMP_COMP2_EXTI_ENABLE_FALLING_EDGE()) +#define __HAL_COMP_EXTI_FALLING_IT_DISABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_DISABLE_FALLING_EDGE() : \ + __HAL_COMP_COMP2_EXTI_DISABLE_FALLING_EDGE()) +#define __HAL_COMP_EXTI_ENABLE_IT(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_ENABLE_IT() : \ + __HAL_COMP_COMP2_EXTI_ENABLE_IT()) +#define __HAL_COMP_EXTI_DISABLE_IT(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_DISABLE_IT() : \ + __HAL_COMP_COMP2_EXTI_DISABLE_IT()) +#define __HAL_COMP_EXTI_GET_FLAG(__FLAG__) (((__FLAG__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_GET_FLAG() : \ + __HAL_COMP_COMP2_EXTI_GET_FLAG()) +#define __HAL_COMP_EXTI_CLEAR_FLAG(__FLAG__) (((__FLAG__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_CLEAR_FLAG() : \ + __HAL_COMP_COMP2_EXTI_CLEAR_FLAG()) +#endif + +#define __HAL_COMP_GET_EXTI_LINE COMP_GET_EXTI_LINE + +#if defined(STM32L0) || defined(STM32L4) +/* Note: On these STM32 families, the only argument of this macro */ +/* is COMP_FLAG_LOCK. */ +/* This macro is replaced by __HAL_COMP_IS_LOCKED with only HAL handle */ +/* argument. */ +#define __HAL_COMP_GET_FLAG(__HANDLE__, __FLAG__) (__HAL_COMP_IS_LOCKED(__HANDLE__)) +#endif +/** + * @} + */ + +#if defined(STM32L0) || defined(STM32L4) +/** @defgroup HAL_COMP_Aliased_Functions HAL COMP Aliased Functions maintained for legacy purpose + * @{ + */ +#define HAL_COMP_Start_IT HAL_COMP_Start /* Function considered as legacy as EXTI event or IT configuration is done into HAL_COMP_Init() */ +#define HAL_COMP_Stop_IT HAL_COMP_Stop /* Function considered as legacy as EXTI event or IT configuration is done into HAL_COMP_Init() */ +/** + * @} + */ +#endif + +/** @defgroup HAL_DAC_Aliased_Macros HAL DAC Aliased Macros maintained for legacy purpose + * @{ + */ + +#define IS_DAC_WAVE(WAVE) (((WAVE) == DAC_WAVE_NONE) || \ + ((WAVE) == DAC_WAVE_NOISE)|| \ + ((WAVE) == DAC_WAVE_TRIANGLE)) + +/** + * @} + */ + +/** @defgroup HAL_FLASH_Aliased_Macros HAL FLASH Aliased Macros maintained for legacy purpose + * @{ + */ + +#define IS_WRPAREA IS_OB_WRPAREA +#define IS_TYPEPROGRAM IS_FLASH_TYPEPROGRAM +#define IS_TYPEPROGRAMFLASH IS_FLASH_TYPEPROGRAM +#define IS_TYPEERASE IS_FLASH_TYPEERASE +#define IS_NBSECTORS IS_FLASH_NBSECTORS +#define IS_OB_WDG_SOURCE IS_OB_IWDG_SOURCE + +/** + * @} + */ + +/** @defgroup HAL_I2C_Aliased_Macros HAL I2C Aliased Macros maintained for legacy purpose + * @{ + */ + +#define __HAL_I2C_RESET_CR2 I2C_RESET_CR2 +#define __HAL_I2C_GENERATE_START I2C_GENERATE_START +#if defined(STM32F1) +#define __HAL_I2C_FREQ_RANGE I2C_FREQRANGE +#else +#define __HAL_I2C_FREQ_RANGE I2C_FREQ_RANGE +#endif /* STM32F1 */ +#define __HAL_I2C_RISE_TIME I2C_RISE_TIME +#define __HAL_I2C_SPEED_STANDARD I2C_SPEED_STANDARD +#define __HAL_I2C_SPEED_FAST I2C_SPEED_FAST +#define __HAL_I2C_SPEED I2C_SPEED +#define __HAL_I2C_7BIT_ADD_WRITE I2C_7BIT_ADD_WRITE +#define __HAL_I2C_7BIT_ADD_READ I2C_7BIT_ADD_READ +#define __HAL_I2C_10BIT_ADDRESS I2C_10BIT_ADDRESS +#define __HAL_I2C_10BIT_HEADER_WRITE I2C_10BIT_HEADER_WRITE +#define __HAL_I2C_10BIT_HEADER_READ I2C_10BIT_HEADER_READ +#define __HAL_I2C_MEM_ADD_MSB I2C_MEM_ADD_MSB +#define __HAL_I2C_MEM_ADD_LSB I2C_MEM_ADD_LSB +#define __HAL_I2C_FREQRANGE I2C_FREQRANGE +/** + * @} + */ + +/** @defgroup HAL_I2S_Aliased_Macros HAL I2S Aliased Macros maintained for legacy purpose + * @{ + */ + +#define IS_I2S_INSTANCE IS_I2S_ALL_INSTANCE +#define IS_I2S_INSTANCE_EXT IS_I2S_ALL_INSTANCE_EXT + +/** + * @} + */ + +/** @defgroup HAL_IRDA_Aliased_Macros HAL IRDA Aliased Macros maintained for legacy purpose + * @{ + */ + +#define __IRDA_DISABLE __HAL_IRDA_DISABLE +#define __IRDA_ENABLE __HAL_IRDA_ENABLE + +#define __HAL_IRDA_GETCLOCKSOURCE IRDA_GETCLOCKSOURCE +#define __HAL_IRDA_MASK_COMPUTATION IRDA_MASK_COMPUTATION +#define __IRDA_GETCLOCKSOURCE IRDA_GETCLOCKSOURCE +#define __IRDA_MASK_COMPUTATION IRDA_MASK_COMPUTATION + +#define IS_IRDA_ONEBIT_SAMPLE IS_IRDA_ONE_BIT_SAMPLE + + +/** + * @} + */ + + +/** @defgroup HAL_IWDG_Aliased_Macros HAL IWDG Aliased Macros maintained for legacy purpose + * @{ + */ +#define __HAL_IWDG_ENABLE_WRITE_ACCESS IWDG_ENABLE_WRITE_ACCESS +#define __HAL_IWDG_DISABLE_WRITE_ACCESS IWDG_DISABLE_WRITE_ACCESS +/** + * @} + */ + + +/** @defgroup HAL_LPTIM_Aliased_Macros HAL LPTIM Aliased Macros maintained for legacy purpose + * @{ + */ + +#define __HAL_LPTIM_ENABLE_INTERRUPT __HAL_LPTIM_ENABLE_IT +#define __HAL_LPTIM_DISABLE_INTERRUPT __HAL_LPTIM_DISABLE_IT +#define __HAL_LPTIM_GET_ITSTATUS __HAL_LPTIM_GET_IT_SOURCE + +/** + * @} + */ + + +/** @defgroup HAL_OPAMP_Aliased_Macros HAL OPAMP Aliased Macros maintained for legacy purpose + * @{ + */ +#define __OPAMP_CSR_OPAXPD OPAMP_CSR_OPAXPD +#define __OPAMP_CSR_S3SELX OPAMP_CSR_S3SELX +#define __OPAMP_CSR_S4SELX OPAMP_CSR_S4SELX +#define __OPAMP_CSR_S5SELX OPAMP_CSR_S5SELX +#define __OPAMP_CSR_S6SELX OPAMP_CSR_S6SELX +#define __OPAMP_CSR_OPAXCAL_L OPAMP_CSR_OPAXCAL_L +#define __OPAMP_CSR_OPAXCAL_H OPAMP_CSR_OPAXCAL_H +#define __OPAMP_CSR_OPAXLPM OPAMP_CSR_OPAXLPM +#define __OPAMP_CSR_ALL_SWITCHES OPAMP_CSR_ALL_SWITCHES +#define __OPAMP_CSR_ANAWSELX OPAMP_CSR_ANAWSELX +#define __OPAMP_CSR_OPAXCALOUT OPAMP_CSR_OPAXCALOUT +#define __OPAMP_OFFSET_TRIM_BITSPOSITION OPAMP_OFFSET_TRIM_BITSPOSITION +#define __OPAMP_OFFSET_TRIM_SET OPAMP_OFFSET_TRIM_SET + +/** + * @} + */ + + +/** @defgroup HAL_PWR_Aliased_Macros HAL PWR Aliased Macros maintained for legacy purpose + * @{ + */ +#define __HAL_PVD_EVENT_DISABLE __HAL_PWR_PVD_EXTI_DISABLE_EVENT +#define __HAL_PVD_EVENT_ENABLE __HAL_PWR_PVD_EXTI_ENABLE_EVENT +#define __HAL_PVD_EXTI_FALLINGTRIGGER_DISABLE __HAL_PWR_PVD_EXTI_DISABLE_FALLING_EDGE +#define __HAL_PVD_EXTI_FALLINGTRIGGER_ENABLE __HAL_PWR_PVD_EXTI_ENABLE_FALLING_EDGE +#define __HAL_PVD_EXTI_RISINGTRIGGER_DISABLE __HAL_PWR_PVD_EXTI_DISABLE_RISING_EDGE +#define __HAL_PVD_EXTI_RISINGTRIGGER_ENABLE __HAL_PWR_PVD_EXTI_ENABLE_RISING_EDGE +#define __HAL_PVM_EVENT_DISABLE __HAL_PWR_PVM_EVENT_DISABLE +#define __HAL_PVM_EVENT_ENABLE __HAL_PWR_PVM_EVENT_ENABLE +#define __HAL_PVM_EXTI_FALLINGTRIGGER_DISABLE __HAL_PWR_PVM_EXTI_FALLINGTRIGGER_DISABLE +#define __HAL_PVM_EXTI_FALLINGTRIGGER_ENABLE __HAL_PWR_PVM_EXTI_FALLINGTRIGGER_ENABLE +#define __HAL_PVM_EXTI_RISINGTRIGGER_DISABLE __HAL_PWR_PVM_EXTI_RISINGTRIGGER_DISABLE +#define __HAL_PVM_EXTI_RISINGTRIGGER_ENABLE __HAL_PWR_PVM_EXTI_RISINGTRIGGER_ENABLE +#define __HAL_PWR_INTERNALWAKEUP_DISABLE HAL_PWREx_DisableInternalWakeUpLine +#define __HAL_PWR_INTERNALWAKEUP_ENABLE HAL_PWREx_EnableInternalWakeUpLine +#define __HAL_PWR_PULL_UP_DOWN_CONFIG_DISABLE HAL_PWREx_DisablePullUpPullDownConfig +#define __HAL_PWR_PULL_UP_DOWN_CONFIG_ENABLE HAL_PWREx_EnablePullUpPullDownConfig +#define __HAL_PWR_PVD_EXTI_CLEAR_EGDE_TRIGGER() do { __HAL_PWR_PVD_EXTI_DISABLE_RISING_EDGE();__HAL_PWR_PVD_EXTI_DISABLE_FALLING_EDGE(); } while(0) +#define __HAL_PWR_PVD_EXTI_EVENT_DISABLE __HAL_PWR_PVD_EXTI_DISABLE_EVENT +#define __HAL_PWR_PVD_EXTI_EVENT_ENABLE __HAL_PWR_PVD_EXTI_ENABLE_EVENT +#define __HAL_PWR_PVD_EXTI_FALLINGTRIGGER_DISABLE __HAL_PWR_PVD_EXTI_DISABLE_FALLING_EDGE +#define __HAL_PWR_PVD_EXTI_FALLINGTRIGGER_ENABLE __HAL_PWR_PVD_EXTI_ENABLE_FALLING_EDGE +#define __HAL_PWR_PVD_EXTI_RISINGTRIGGER_DISABLE __HAL_PWR_PVD_EXTI_DISABLE_RISING_EDGE +#define __HAL_PWR_PVD_EXTI_RISINGTRIGGER_ENABLE __HAL_PWR_PVD_EXTI_ENABLE_RISING_EDGE +#define __HAL_PWR_PVD_EXTI_SET_FALLING_EGDE_TRIGGER __HAL_PWR_PVD_EXTI_ENABLE_FALLING_EDGE +#define __HAL_PWR_PVD_EXTI_SET_RISING_EDGE_TRIGGER __HAL_PWR_PVD_EXTI_ENABLE_RISING_EDGE +#define __HAL_PWR_PVM_DISABLE() do { HAL_PWREx_DisablePVM1();HAL_PWREx_DisablePVM2();HAL_PWREx_DisablePVM3();HAL_PWREx_DisablePVM4(); } while(0) +#define __HAL_PWR_PVM_ENABLE() do { HAL_PWREx_EnablePVM1();HAL_PWREx_EnablePVM2();HAL_PWREx_EnablePVM3();HAL_PWREx_EnablePVM4(); } while(0) +#define __HAL_PWR_SRAM2CONTENT_PRESERVE_DISABLE HAL_PWREx_DisableSRAM2ContentRetention +#define __HAL_PWR_SRAM2CONTENT_PRESERVE_ENABLE HAL_PWREx_EnableSRAM2ContentRetention +#define __HAL_PWR_VDDIO2_DISABLE HAL_PWREx_DisableVddIO2 +#define __HAL_PWR_VDDIO2_ENABLE HAL_PWREx_EnableVddIO2 +#define __HAL_PWR_VDDIO2_EXTI_CLEAR_EGDE_TRIGGER __HAL_PWR_VDDIO2_EXTI_DISABLE_FALLING_EDGE +#define __HAL_PWR_VDDIO2_EXTI_SET_FALLING_EGDE_TRIGGER __HAL_PWR_VDDIO2_EXTI_ENABLE_FALLING_EDGE +#define __HAL_PWR_VDDUSB_DISABLE HAL_PWREx_DisableVddUSB +#define __HAL_PWR_VDDUSB_ENABLE HAL_PWREx_EnableVddUSB + +#if defined (STM32F4) +#define __HAL_PVD_EXTI_ENABLE_IT(PWR_EXTI_LINE_PVD) __HAL_PWR_PVD_EXTI_ENABLE_IT() +#define __HAL_PVD_EXTI_DISABLE_IT(PWR_EXTI_LINE_PVD) __HAL_PWR_PVD_EXTI_DISABLE_IT() +#define __HAL_PVD_EXTI_GET_FLAG(PWR_EXTI_LINE_PVD) __HAL_PWR_PVD_EXTI_GET_FLAG() +#define __HAL_PVD_EXTI_CLEAR_FLAG(PWR_EXTI_LINE_PVD) __HAL_PWR_PVD_EXTI_CLEAR_FLAG() +#define __HAL_PVD_EXTI_GENERATE_SWIT(PWR_EXTI_LINE_PVD) __HAL_PWR_PVD_EXTI_GENERATE_SWIT() +#else +#define __HAL_PVD_EXTI_CLEAR_FLAG __HAL_PWR_PVD_EXTI_CLEAR_FLAG +#define __HAL_PVD_EXTI_DISABLE_IT __HAL_PWR_PVD_EXTI_DISABLE_IT +#define __HAL_PVD_EXTI_ENABLE_IT __HAL_PWR_PVD_EXTI_ENABLE_IT +#define __HAL_PVD_EXTI_GENERATE_SWIT __HAL_PWR_PVD_EXTI_GENERATE_SWIT +#define __HAL_PVD_EXTI_GET_FLAG __HAL_PWR_PVD_EXTI_GET_FLAG +#endif /* STM32F4 */ +/** + * @} + */ + + +/** @defgroup HAL_RCC_Aliased HAL RCC Aliased maintained for legacy purpose + * @{ + */ + +#define RCC_StopWakeUpClock_MSI RCC_STOP_WAKEUPCLOCK_MSI +#define RCC_StopWakeUpClock_HSI RCC_STOP_WAKEUPCLOCK_HSI + +#define HAL_RCC_CCSCallback HAL_RCC_CSSCallback +#define HAL_RC48_EnableBuffer_Cmd(cmd) (((cmd)==ENABLE) ? HAL_RCCEx_EnableHSI48_VREFINT() : HAL_RCCEx_DisableHSI48_VREFINT()) + +#define __ADC_CLK_DISABLE __HAL_RCC_ADC_CLK_DISABLE +#define __ADC_CLK_ENABLE __HAL_RCC_ADC_CLK_ENABLE +#define __ADC_CLK_SLEEP_DISABLE __HAL_RCC_ADC_CLK_SLEEP_DISABLE +#define __ADC_CLK_SLEEP_ENABLE __HAL_RCC_ADC_CLK_SLEEP_ENABLE +#define __ADC_FORCE_RESET __HAL_RCC_ADC_FORCE_RESET +#define __ADC_RELEASE_RESET __HAL_RCC_ADC_RELEASE_RESET +#define __ADC1_CLK_DISABLE __HAL_RCC_ADC1_CLK_DISABLE +#define __ADC1_CLK_ENABLE __HAL_RCC_ADC1_CLK_ENABLE +#define __ADC1_FORCE_RESET __HAL_RCC_ADC1_FORCE_RESET +#define __ADC1_RELEASE_RESET __HAL_RCC_ADC1_RELEASE_RESET +#define __ADC1_CLK_SLEEP_ENABLE __HAL_RCC_ADC1_CLK_SLEEP_ENABLE +#define __ADC1_CLK_SLEEP_DISABLE __HAL_RCC_ADC1_CLK_SLEEP_DISABLE +#define __ADC2_CLK_DISABLE __HAL_RCC_ADC2_CLK_DISABLE +#define __ADC2_CLK_ENABLE __HAL_RCC_ADC2_CLK_ENABLE +#define __ADC2_FORCE_RESET __HAL_RCC_ADC2_FORCE_RESET +#define __ADC2_RELEASE_RESET __HAL_RCC_ADC2_RELEASE_RESET +#define __ADC3_CLK_DISABLE __HAL_RCC_ADC3_CLK_DISABLE +#define __ADC3_CLK_ENABLE __HAL_RCC_ADC3_CLK_ENABLE +#define __ADC3_FORCE_RESET __HAL_RCC_ADC3_FORCE_RESET +#define __ADC3_RELEASE_RESET __HAL_RCC_ADC3_RELEASE_RESET +#define __AES_CLK_DISABLE __HAL_RCC_AES_CLK_DISABLE +#define __AES_CLK_ENABLE __HAL_RCC_AES_CLK_ENABLE +#define __AES_CLK_SLEEP_DISABLE __HAL_RCC_AES_CLK_SLEEP_DISABLE +#define __AES_CLK_SLEEP_ENABLE __HAL_RCC_AES_CLK_SLEEP_ENABLE +#define __AES_FORCE_RESET __HAL_RCC_AES_FORCE_RESET +#define __AES_RELEASE_RESET __HAL_RCC_AES_RELEASE_RESET +#define __CRYP_CLK_SLEEP_ENABLE __HAL_RCC_CRYP_CLK_SLEEP_ENABLE +#define __CRYP_CLK_SLEEP_DISABLE __HAL_RCC_CRYP_CLK_SLEEP_DISABLE +#define __CRYP_CLK_ENABLE __HAL_RCC_CRYP_CLK_ENABLE +#define __CRYP_CLK_DISABLE __HAL_RCC_CRYP_CLK_DISABLE +#define __CRYP_FORCE_RESET __HAL_RCC_CRYP_FORCE_RESET +#define __CRYP_RELEASE_RESET __HAL_RCC_CRYP_RELEASE_RESET +#define __AFIO_CLK_DISABLE __HAL_RCC_AFIO_CLK_DISABLE +#define __AFIO_CLK_ENABLE __HAL_RCC_AFIO_CLK_ENABLE +#define __AFIO_FORCE_RESET __HAL_RCC_AFIO_FORCE_RESET +#define __AFIO_RELEASE_RESET __HAL_RCC_AFIO_RELEASE_RESET +#define __AHB_FORCE_RESET __HAL_RCC_AHB_FORCE_RESET +#define __AHB_RELEASE_RESET __HAL_RCC_AHB_RELEASE_RESET +#define __AHB1_FORCE_RESET __HAL_RCC_AHB1_FORCE_RESET +#define __AHB1_RELEASE_RESET __HAL_RCC_AHB1_RELEASE_RESET +#define __AHB2_FORCE_RESET __HAL_RCC_AHB2_FORCE_RESET +#define __AHB2_RELEASE_RESET __HAL_RCC_AHB2_RELEASE_RESET +#define __AHB3_FORCE_RESET __HAL_RCC_AHB3_FORCE_RESET +#define __AHB3_RELEASE_RESET __HAL_RCC_AHB3_RELEASE_RESET +#define __APB1_FORCE_RESET __HAL_RCC_APB1_FORCE_RESET +#define __APB1_RELEASE_RESET __HAL_RCC_APB1_RELEASE_RESET +#define __APB2_FORCE_RESET __HAL_RCC_APB2_FORCE_RESET +#define __APB2_RELEASE_RESET __HAL_RCC_APB2_RELEASE_RESET +#define __BKP_CLK_DISABLE __HAL_RCC_BKP_CLK_DISABLE +#define __BKP_CLK_ENABLE __HAL_RCC_BKP_CLK_ENABLE +#define __BKP_FORCE_RESET __HAL_RCC_BKP_FORCE_RESET +#define __BKP_RELEASE_RESET __HAL_RCC_BKP_RELEASE_RESET +#define __CAN1_CLK_DISABLE __HAL_RCC_CAN1_CLK_DISABLE +#define __CAN1_CLK_ENABLE __HAL_RCC_CAN1_CLK_ENABLE +#define __CAN1_CLK_SLEEP_DISABLE __HAL_RCC_CAN1_CLK_SLEEP_DISABLE +#define __CAN1_CLK_SLEEP_ENABLE __HAL_RCC_CAN1_CLK_SLEEP_ENABLE +#define __CAN1_FORCE_RESET __HAL_RCC_CAN1_FORCE_RESET +#define __CAN1_RELEASE_RESET __HAL_RCC_CAN1_RELEASE_RESET +#define __CAN_CLK_DISABLE __HAL_RCC_CAN1_CLK_DISABLE +#define __CAN_CLK_ENABLE __HAL_RCC_CAN1_CLK_ENABLE +#define __CAN_FORCE_RESET __HAL_RCC_CAN1_FORCE_RESET +#define __CAN_RELEASE_RESET __HAL_RCC_CAN1_RELEASE_RESET +#define __CAN2_CLK_DISABLE __HAL_RCC_CAN2_CLK_DISABLE +#define __CAN2_CLK_ENABLE __HAL_RCC_CAN2_CLK_ENABLE +#define __CAN2_FORCE_RESET __HAL_RCC_CAN2_FORCE_RESET +#define __CAN2_RELEASE_RESET __HAL_RCC_CAN2_RELEASE_RESET +#define __CEC_CLK_DISABLE __HAL_RCC_CEC_CLK_DISABLE +#define __CEC_CLK_ENABLE __HAL_RCC_CEC_CLK_ENABLE +#define __COMP_CLK_DISABLE __HAL_RCC_COMP_CLK_DISABLE +#define __COMP_CLK_ENABLE __HAL_RCC_COMP_CLK_ENABLE +#define __COMP_FORCE_RESET __HAL_RCC_COMP_FORCE_RESET +#define __COMP_RELEASE_RESET __HAL_RCC_COMP_RELEASE_RESET +#define __COMP_CLK_SLEEP_ENABLE __HAL_RCC_COMP_CLK_SLEEP_ENABLE +#define __COMP_CLK_SLEEP_DISABLE __HAL_RCC_COMP_CLK_SLEEP_DISABLE +#define __CEC_FORCE_RESET __HAL_RCC_CEC_FORCE_RESET +#define __CEC_RELEASE_RESET __HAL_RCC_CEC_RELEASE_RESET +#define __CRC_CLK_DISABLE __HAL_RCC_CRC_CLK_DISABLE +#define __CRC_CLK_ENABLE __HAL_RCC_CRC_CLK_ENABLE +#define __CRC_CLK_SLEEP_DISABLE __HAL_RCC_CRC_CLK_SLEEP_DISABLE +#define __CRC_CLK_SLEEP_ENABLE __HAL_RCC_CRC_CLK_SLEEP_ENABLE +#define __CRC_FORCE_RESET __HAL_RCC_CRC_FORCE_RESET +#define __CRC_RELEASE_RESET __HAL_RCC_CRC_RELEASE_RESET +#define __DAC_CLK_DISABLE __HAL_RCC_DAC_CLK_DISABLE +#define __DAC_CLK_ENABLE __HAL_RCC_DAC_CLK_ENABLE +#define __DAC_FORCE_RESET __HAL_RCC_DAC_FORCE_RESET +#define __DAC_RELEASE_RESET __HAL_RCC_DAC_RELEASE_RESET +#define __DAC1_CLK_DISABLE __HAL_RCC_DAC1_CLK_DISABLE +#define __DAC1_CLK_ENABLE __HAL_RCC_DAC1_CLK_ENABLE +#define __DAC1_CLK_SLEEP_DISABLE __HAL_RCC_DAC1_CLK_SLEEP_DISABLE +#define __DAC1_CLK_SLEEP_ENABLE __HAL_RCC_DAC1_CLK_SLEEP_ENABLE +#define __DAC1_FORCE_RESET __HAL_RCC_DAC1_FORCE_RESET +#define __DAC1_RELEASE_RESET __HAL_RCC_DAC1_RELEASE_RESET +#define __DBGMCU_CLK_ENABLE __HAL_RCC_DBGMCU_CLK_ENABLE +#define __DBGMCU_CLK_DISABLE __HAL_RCC_DBGMCU_CLK_DISABLE +#define __DBGMCU_FORCE_RESET __HAL_RCC_DBGMCU_FORCE_RESET +#define __DBGMCU_RELEASE_RESET __HAL_RCC_DBGMCU_RELEASE_RESET +#define __DFSDM_CLK_DISABLE __HAL_RCC_DFSDM_CLK_DISABLE +#define __DFSDM_CLK_ENABLE __HAL_RCC_DFSDM_CLK_ENABLE +#define __DFSDM_CLK_SLEEP_DISABLE __HAL_RCC_DFSDM_CLK_SLEEP_DISABLE +#define __DFSDM_CLK_SLEEP_ENABLE __HAL_RCC_DFSDM_CLK_SLEEP_ENABLE +#define __DFSDM_FORCE_RESET __HAL_RCC_DFSDM_FORCE_RESET +#define __DFSDM_RELEASE_RESET __HAL_RCC_DFSDM_RELEASE_RESET +#define __DMA1_CLK_DISABLE __HAL_RCC_DMA1_CLK_DISABLE +#define __DMA1_CLK_ENABLE __HAL_RCC_DMA1_CLK_ENABLE +#define __DMA1_CLK_SLEEP_DISABLE __HAL_RCC_DMA1_CLK_SLEEP_DISABLE +#define __DMA1_CLK_SLEEP_ENABLE __HAL_RCC_DMA1_CLK_SLEEP_ENABLE +#define __DMA1_FORCE_RESET __HAL_RCC_DMA1_FORCE_RESET +#define __DMA1_RELEASE_RESET __HAL_RCC_DMA1_RELEASE_RESET +#define __DMA2_CLK_DISABLE __HAL_RCC_DMA2_CLK_DISABLE +#define __DMA2_CLK_ENABLE __HAL_RCC_DMA2_CLK_ENABLE +#define __DMA2_CLK_SLEEP_DISABLE __HAL_RCC_DMA2_CLK_SLEEP_DISABLE +#define __DMA2_CLK_SLEEP_ENABLE __HAL_RCC_DMA2_CLK_SLEEP_ENABLE +#define __DMA2_FORCE_RESET __HAL_RCC_DMA2_FORCE_RESET +#define __DMA2_RELEASE_RESET __HAL_RCC_DMA2_RELEASE_RESET +#define __ETHMAC_CLK_DISABLE __HAL_RCC_ETHMAC_CLK_DISABLE +#define __ETHMAC_CLK_ENABLE __HAL_RCC_ETHMAC_CLK_ENABLE +#define __ETHMAC_FORCE_RESET __HAL_RCC_ETHMAC_FORCE_RESET +#define __ETHMAC_RELEASE_RESET __HAL_RCC_ETHMAC_RELEASE_RESET +#define __ETHMACRX_CLK_DISABLE __HAL_RCC_ETHMACRX_CLK_DISABLE +#define __ETHMACRX_CLK_ENABLE __HAL_RCC_ETHMACRX_CLK_ENABLE +#define __ETHMACTX_CLK_DISABLE __HAL_RCC_ETHMACTX_CLK_DISABLE +#define __ETHMACTX_CLK_ENABLE __HAL_RCC_ETHMACTX_CLK_ENABLE +#define __FIREWALL_CLK_DISABLE __HAL_RCC_FIREWALL_CLK_DISABLE +#define __FIREWALL_CLK_ENABLE __HAL_RCC_FIREWALL_CLK_ENABLE +#define __FLASH_CLK_DISABLE __HAL_RCC_FLASH_CLK_DISABLE +#define __FLASH_CLK_ENABLE __HAL_RCC_FLASH_CLK_ENABLE +#define __FLASH_CLK_SLEEP_DISABLE __HAL_RCC_FLASH_CLK_SLEEP_DISABLE +#define __FLASH_CLK_SLEEP_ENABLE __HAL_RCC_FLASH_CLK_SLEEP_ENABLE +#define __FLASH_FORCE_RESET __HAL_RCC_FLASH_FORCE_RESET +#define __FLASH_RELEASE_RESET __HAL_RCC_FLASH_RELEASE_RESET +#define __FLITF_CLK_DISABLE __HAL_RCC_FLITF_CLK_DISABLE +#define __FLITF_CLK_ENABLE __HAL_RCC_FLITF_CLK_ENABLE +#define __FLITF_FORCE_RESET __HAL_RCC_FLITF_FORCE_RESET +#define __FLITF_RELEASE_RESET __HAL_RCC_FLITF_RELEASE_RESET +#define __FLITF_CLK_SLEEP_ENABLE __HAL_RCC_FLITF_CLK_SLEEP_ENABLE +#define __FLITF_CLK_SLEEP_DISABLE __HAL_RCC_FLITF_CLK_SLEEP_DISABLE +#define __FMC_CLK_DISABLE __HAL_RCC_FMC_CLK_DISABLE +#define __FMC_CLK_ENABLE __HAL_RCC_FMC_CLK_ENABLE +#define __FMC_CLK_SLEEP_DISABLE __HAL_RCC_FMC_CLK_SLEEP_DISABLE +#define __FMC_CLK_SLEEP_ENABLE __HAL_RCC_FMC_CLK_SLEEP_ENABLE +#define __FMC_FORCE_RESET __HAL_RCC_FMC_FORCE_RESET +#define __FMC_RELEASE_RESET __HAL_RCC_FMC_RELEASE_RESET +#define __FSMC_CLK_DISABLE __HAL_RCC_FSMC_CLK_DISABLE +#define __FSMC_CLK_ENABLE __HAL_RCC_FSMC_CLK_ENABLE +#define __GPIOA_CLK_DISABLE __HAL_RCC_GPIOA_CLK_DISABLE +#define __GPIOA_CLK_ENABLE __HAL_RCC_GPIOA_CLK_ENABLE +#define __GPIOA_CLK_SLEEP_DISABLE __HAL_RCC_GPIOA_CLK_SLEEP_DISABLE +#define __GPIOA_CLK_SLEEP_ENABLE __HAL_RCC_GPIOA_CLK_SLEEP_ENABLE +#define __GPIOA_FORCE_RESET __HAL_RCC_GPIOA_FORCE_RESET +#define __GPIOA_RELEASE_RESET __HAL_RCC_GPIOA_RELEASE_RESET +#define __GPIOB_CLK_DISABLE __HAL_RCC_GPIOB_CLK_DISABLE +#define __GPIOB_CLK_ENABLE __HAL_RCC_GPIOB_CLK_ENABLE +#define __GPIOB_CLK_SLEEP_DISABLE __HAL_RCC_GPIOB_CLK_SLEEP_DISABLE +#define __GPIOB_CLK_SLEEP_ENABLE __HAL_RCC_GPIOB_CLK_SLEEP_ENABLE +#define __GPIOB_FORCE_RESET __HAL_RCC_GPIOB_FORCE_RESET +#define __GPIOB_RELEASE_RESET __HAL_RCC_GPIOB_RELEASE_RESET +#define __GPIOC_CLK_DISABLE __HAL_RCC_GPIOC_CLK_DISABLE +#define __GPIOC_CLK_ENABLE __HAL_RCC_GPIOC_CLK_ENABLE +#define __GPIOC_CLK_SLEEP_DISABLE __HAL_RCC_GPIOC_CLK_SLEEP_DISABLE +#define __GPIOC_CLK_SLEEP_ENABLE __HAL_RCC_GPIOC_CLK_SLEEP_ENABLE +#define __GPIOC_FORCE_RESET __HAL_RCC_GPIOC_FORCE_RESET +#define __GPIOC_RELEASE_RESET __HAL_RCC_GPIOC_RELEASE_RESET +#define __GPIOD_CLK_DISABLE __HAL_RCC_GPIOD_CLK_DISABLE +#define __GPIOD_CLK_ENABLE __HAL_RCC_GPIOD_CLK_ENABLE +#define __GPIOD_CLK_SLEEP_DISABLE __HAL_RCC_GPIOD_CLK_SLEEP_DISABLE +#define __GPIOD_CLK_SLEEP_ENABLE __HAL_RCC_GPIOD_CLK_SLEEP_ENABLE +#define __GPIOD_FORCE_RESET __HAL_RCC_GPIOD_FORCE_RESET +#define __GPIOD_RELEASE_RESET __HAL_RCC_GPIOD_RELEASE_RESET +#define __GPIOE_CLK_DISABLE __HAL_RCC_GPIOE_CLK_DISABLE +#define __GPIOE_CLK_ENABLE __HAL_RCC_GPIOE_CLK_ENABLE +#define __GPIOE_CLK_SLEEP_DISABLE __HAL_RCC_GPIOE_CLK_SLEEP_DISABLE +#define __GPIOE_CLK_SLEEP_ENABLE __HAL_RCC_GPIOE_CLK_SLEEP_ENABLE +#define __GPIOE_FORCE_RESET __HAL_RCC_GPIOE_FORCE_RESET +#define __GPIOE_RELEASE_RESET __HAL_RCC_GPIOE_RELEASE_RESET +#define __GPIOF_CLK_DISABLE __HAL_RCC_GPIOF_CLK_DISABLE +#define __GPIOF_CLK_ENABLE __HAL_RCC_GPIOF_CLK_ENABLE +#define __GPIOF_CLK_SLEEP_DISABLE __HAL_RCC_GPIOF_CLK_SLEEP_DISABLE +#define __GPIOF_CLK_SLEEP_ENABLE __HAL_RCC_GPIOF_CLK_SLEEP_ENABLE +#define __GPIOF_FORCE_RESET __HAL_RCC_GPIOF_FORCE_RESET +#define __GPIOF_RELEASE_RESET __HAL_RCC_GPIOF_RELEASE_RESET +#define __GPIOG_CLK_DISABLE __HAL_RCC_GPIOG_CLK_DISABLE +#define __GPIOG_CLK_ENABLE __HAL_RCC_GPIOG_CLK_ENABLE +#define __GPIOG_CLK_SLEEP_DISABLE __HAL_RCC_GPIOG_CLK_SLEEP_DISABLE +#define __GPIOG_CLK_SLEEP_ENABLE __HAL_RCC_GPIOG_CLK_SLEEP_ENABLE +#define __GPIOG_FORCE_RESET __HAL_RCC_GPIOG_FORCE_RESET +#define __GPIOG_RELEASE_RESET __HAL_RCC_GPIOG_RELEASE_RESET +#define __GPIOH_CLK_DISABLE __HAL_RCC_GPIOH_CLK_DISABLE +#define __GPIOH_CLK_ENABLE __HAL_RCC_GPIOH_CLK_ENABLE +#define __GPIOH_CLK_SLEEP_DISABLE __HAL_RCC_GPIOH_CLK_SLEEP_DISABLE +#define __GPIOH_CLK_SLEEP_ENABLE __HAL_RCC_GPIOH_CLK_SLEEP_ENABLE +#define __GPIOH_FORCE_RESET __HAL_RCC_GPIOH_FORCE_RESET +#define __GPIOH_RELEASE_RESET __HAL_RCC_GPIOH_RELEASE_RESET +#define __I2C1_CLK_DISABLE __HAL_RCC_I2C1_CLK_DISABLE +#define __I2C1_CLK_ENABLE __HAL_RCC_I2C1_CLK_ENABLE +#define __I2C1_CLK_SLEEP_DISABLE __HAL_RCC_I2C1_CLK_SLEEP_DISABLE +#define __I2C1_CLK_SLEEP_ENABLE __HAL_RCC_I2C1_CLK_SLEEP_ENABLE +#define __I2C1_FORCE_RESET __HAL_RCC_I2C1_FORCE_RESET +#define __I2C1_RELEASE_RESET __HAL_RCC_I2C1_RELEASE_RESET +#define __I2C2_CLK_DISABLE __HAL_RCC_I2C2_CLK_DISABLE +#define __I2C2_CLK_ENABLE __HAL_RCC_I2C2_CLK_ENABLE +#define __I2C2_CLK_SLEEP_DISABLE __HAL_RCC_I2C2_CLK_SLEEP_DISABLE +#define __I2C2_CLK_SLEEP_ENABLE __HAL_RCC_I2C2_CLK_SLEEP_ENABLE +#define __I2C2_FORCE_RESET __HAL_RCC_I2C2_FORCE_RESET +#define __I2C2_RELEASE_RESET __HAL_RCC_I2C2_RELEASE_RESET +#define __I2C3_CLK_DISABLE __HAL_RCC_I2C3_CLK_DISABLE +#define __I2C3_CLK_ENABLE __HAL_RCC_I2C3_CLK_ENABLE +#define __I2C3_CLK_SLEEP_DISABLE __HAL_RCC_I2C3_CLK_SLEEP_DISABLE +#define __I2C3_CLK_SLEEP_ENABLE __HAL_RCC_I2C3_CLK_SLEEP_ENABLE +#define __I2C3_FORCE_RESET __HAL_RCC_I2C3_FORCE_RESET +#define __I2C3_RELEASE_RESET __HAL_RCC_I2C3_RELEASE_RESET +#define __LCD_CLK_DISABLE __HAL_RCC_LCD_CLK_DISABLE +#define __LCD_CLK_ENABLE __HAL_RCC_LCD_CLK_ENABLE +#define __LCD_CLK_SLEEP_DISABLE __HAL_RCC_LCD_CLK_SLEEP_DISABLE +#define __LCD_CLK_SLEEP_ENABLE __HAL_RCC_LCD_CLK_SLEEP_ENABLE +#define __LCD_FORCE_RESET __HAL_RCC_LCD_FORCE_RESET +#define __LCD_RELEASE_RESET __HAL_RCC_LCD_RELEASE_RESET +#define __LPTIM1_CLK_DISABLE __HAL_RCC_LPTIM1_CLK_DISABLE +#define __LPTIM1_CLK_ENABLE __HAL_RCC_LPTIM1_CLK_ENABLE +#define __LPTIM1_CLK_SLEEP_DISABLE __HAL_RCC_LPTIM1_CLK_SLEEP_DISABLE +#define __LPTIM1_CLK_SLEEP_ENABLE __HAL_RCC_LPTIM1_CLK_SLEEP_ENABLE +#define __LPTIM1_FORCE_RESET __HAL_RCC_LPTIM1_FORCE_RESET +#define __LPTIM1_RELEASE_RESET __HAL_RCC_LPTIM1_RELEASE_RESET +#define __LPTIM2_CLK_DISABLE __HAL_RCC_LPTIM2_CLK_DISABLE +#define __LPTIM2_CLK_ENABLE __HAL_RCC_LPTIM2_CLK_ENABLE +#define __LPTIM2_CLK_SLEEP_DISABLE __HAL_RCC_LPTIM2_CLK_SLEEP_DISABLE +#define __LPTIM2_CLK_SLEEP_ENABLE __HAL_RCC_LPTIM2_CLK_SLEEP_ENABLE +#define __LPTIM2_FORCE_RESET __HAL_RCC_LPTIM2_FORCE_RESET +#define __LPTIM2_RELEASE_RESET __HAL_RCC_LPTIM2_RELEASE_RESET +#define __LPUART1_CLK_DISABLE __HAL_RCC_LPUART1_CLK_DISABLE +#define __LPUART1_CLK_ENABLE __HAL_RCC_LPUART1_CLK_ENABLE +#define __LPUART1_CLK_SLEEP_DISABLE __HAL_RCC_LPUART1_CLK_SLEEP_DISABLE +#define __LPUART1_CLK_SLEEP_ENABLE __HAL_RCC_LPUART1_CLK_SLEEP_ENABLE +#define __LPUART1_FORCE_RESET __HAL_RCC_LPUART1_FORCE_RESET +#define __LPUART1_RELEASE_RESET __HAL_RCC_LPUART1_RELEASE_RESET +#define __OPAMP_CLK_DISABLE __HAL_RCC_OPAMP_CLK_DISABLE +#define __OPAMP_CLK_ENABLE __HAL_RCC_OPAMP_CLK_ENABLE +#define __OPAMP_CLK_SLEEP_DISABLE __HAL_RCC_OPAMP_CLK_SLEEP_DISABLE +#define __OPAMP_CLK_SLEEP_ENABLE __HAL_RCC_OPAMP_CLK_SLEEP_ENABLE +#define __OPAMP_FORCE_RESET __HAL_RCC_OPAMP_FORCE_RESET +#define __OPAMP_RELEASE_RESET __HAL_RCC_OPAMP_RELEASE_RESET +#define __OTGFS_CLK_DISABLE __HAL_RCC_OTGFS_CLK_DISABLE +#define __OTGFS_CLK_ENABLE __HAL_RCC_OTGFS_CLK_ENABLE +#define __OTGFS_CLK_SLEEP_DISABLE __HAL_RCC_OTGFS_CLK_SLEEP_DISABLE +#define __OTGFS_CLK_SLEEP_ENABLE __HAL_RCC_OTGFS_CLK_SLEEP_ENABLE +#define __OTGFS_FORCE_RESET __HAL_RCC_OTGFS_FORCE_RESET +#define __OTGFS_RELEASE_RESET __HAL_RCC_OTGFS_RELEASE_RESET +#define __PWR_CLK_DISABLE __HAL_RCC_PWR_CLK_DISABLE +#define __PWR_CLK_ENABLE __HAL_RCC_PWR_CLK_ENABLE +#define __PWR_CLK_SLEEP_DISABLE __HAL_RCC_PWR_CLK_SLEEP_DISABLE +#define __PWR_CLK_SLEEP_ENABLE __HAL_RCC_PWR_CLK_SLEEP_ENABLE +#define __PWR_FORCE_RESET __HAL_RCC_PWR_FORCE_RESET +#define __PWR_RELEASE_RESET __HAL_RCC_PWR_RELEASE_RESET +#define __QSPI_CLK_DISABLE __HAL_RCC_QSPI_CLK_DISABLE +#define __QSPI_CLK_ENABLE __HAL_RCC_QSPI_CLK_ENABLE +#define __QSPI_CLK_SLEEP_DISABLE __HAL_RCC_QSPI_CLK_SLEEP_DISABLE +#define __QSPI_CLK_SLEEP_ENABLE __HAL_RCC_QSPI_CLK_SLEEP_ENABLE +#define __QSPI_FORCE_RESET __HAL_RCC_QSPI_FORCE_RESET +#define __QSPI_RELEASE_RESET __HAL_RCC_QSPI_RELEASE_RESET + +#if defined(STM32WB) +#define __HAL_RCC_QSPI_CLK_DISABLE __HAL_RCC_QUADSPI_CLK_DISABLE +#define __HAL_RCC_QSPI_CLK_ENABLE __HAL_RCC_QUADSPI_CLK_ENABLE +#define __HAL_RCC_QSPI_CLK_SLEEP_DISABLE __HAL_RCC_QUADSPI_CLK_SLEEP_DISABLE +#define __HAL_RCC_QSPI_CLK_SLEEP_ENABLE __HAL_RCC_QUADSPI_CLK_SLEEP_ENABLE +#define __HAL_RCC_QSPI_FORCE_RESET __HAL_RCC_QUADSPI_FORCE_RESET +#define __HAL_RCC_QSPI_RELEASE_RESET __HAL_RCC_QUADSPI_RELEASE_RESET +#define __HAL_RCC_QSPI_IS_CLK_ENABLED __HAL_RCC_QUADSPI_IS_CLK_ENABLED +#define __HAL_RCC_QSPI_IS_CLK_DISABLED __HAL_RCC_QUADSPI_IS_CLK_DISABLED +#define __HAL_RCC_QSPI_IS_CLK_SLEEP_ENABLED __HAL_RCC_QUADSPI_IS_CLK_SLEEP_ENABLED +#define __HAL_RCC_QSPI_IS_CLK_SLEEP_DISABLED __HAL_RCC_QUADSPI_IS_CLK_SLEEP_DISABLED +#define QSPI_IRQHandler QUADSPI_IRQHandler +#endif /* __HAL_RCC_QUADSPI_CLK_ENABLE */ + +#define __RNG_CLK_DISABLE __HAL_RCC_RNG_CLK_DISABLE +#define __RNG_CLK_ENABLE __HAL_RCC_RNG_CLK_ENABLE +#define __RNG_CLK_SLEEP_DISABLE __HAL_RCC_RNG_CLK_SLEEP_DISABLE +#define __RNG_CLK_SLEEP_ENABLE __HAL_RCC_RNG_CLK_SLEEP_ENABLE +#define __RNG_FORCE_RESET __HAL_RCC_RNG_FORCE_RESET +#define __RNG_RELEASE_RESET __HAL_RCC_RNG_RELEASE_RESET +#define __SAI1_CLK_DISABLE __HAL_RCC_SAI1_CLK_DISABLE +#define __SAI1_CLK_ENABLE __HAL_RCC_SAI1_CLK_ENABLE +#define __SAI1_CLK_SLEEP_DISABLE __HAL_RCC_SAI1_CLK_SLEEP_DISABLE +#define __SAI1_CLK_SLEEP_ENABLE __HAL_RCC_SAI1_CLK_SLEEP_ENABLE +#define __SAI1_FORCE_RESET __HAL_RCC_SAI1_FORCE_RESET +#define __SAI1_RELEASE_RESET __HAL_RCC_SAI1_RELEASE_RESET +#define __SAI2_CLK_DISABLE __HAL_RCC_SAI2_CLK_DISABLE +#define __SAI2_CLK_ENABLE __HAL_RCC_SAI2_CLK_ENABLE +#define __SAI2_CLK_SLEEP_DISABLE __HAL_RCC_SAI2_CLK_SLEEP_DISABLE +#define __SAI2_CLK_SLEEP_ENABLE __HAL_RCC_SAI2_CLK_SLEEP_ENABLE +#define __SAI2_FORCE_RESET __HAL_RCC_SAI2_FORCE_RESET +#define __SAI2_RELEASE_RESET __HAL_RCC_SAI2_RELEASE_RESET +#define __SDIO_CLK_DISABLE __HAL_RCC_SDIO_CLK_DISABLE +#define __SDIO_CLK_ENABLE __HAL_RCC_SDIO_CLK_ENABLE +#define __SDMMC_CLK_DISABLE __HAL_RCC_SDMMC_CLK_DISABLE +#define __SDMMC_CLK_ENABLE __HAL_RCC_SDMMC_CLK_ENABLE +#define __SDMMC_CLK_SLEEP_DISABLE __HAL_RCC_SDMMC_CLK_SLEEP_DISABLE +#define __SDMMC_CLK_SLEEP_ENABLE __HAL_RCC_SDMMC_CLK_SLEEP_ENABLE +#define __SDMMC_FORCE_RESET __HAL_RCC_SDMMC_FORCE_RESET +#define __SDMMC_RELEASE_RESET __HAL_RCC_SDMMC_RELEASE_RESET +#define __SPI1_CLK_DISABLE __HAL_RCC_SPI1_CLK_DISABLE +#define __SPI1_CLK_ENABLE __HAL_RCC_SPI1_CLK_ENABLE +#define __SPI1_CLK_SLEEP_DISABLE __HAL_RCC_SPI1_CLK_SLEEP_DISABLE +#define __SPI1_CLK_SLEEP_ENABLE __HAL_RCC_SPI1_CLK_SLEEP_ENABLE +#define __SPI1_FORCE_RESET __HAL_RCC_SPI1_FORCE_RESET +#define __SPI1_RELEASE_RESET __HAL_RCC_SPI1_RELEASE_RESET +#define __SPI2_CLK_DISABLE __HAL_RCC_SPI2_CLK_DISABLE +#define __SPI2_CLK_ENABLE __HAL_RCC_SPI2_CLK_ENABLE +#define __SPI2_CLK_SLEEP_DISABLE __HAL_RCC_SPI2_CLK_SLEEP_DISABLE +#define __SPI2_CLK_SLEEP_ENABLE __HAL_RCC_SPI2_CLK_SLEEP_ENABLE +#define __SPI2_FORCE_RESET __HAL_RCC_SPI2_FORCE_RESET +#define __SPI2_RELEASE_RESET __HAL_RCC_SPI2_RELEASE_RESET +#define __SPI3_CLK_DISABLE __HAL_RCC_SPI3_CLK_DISABLE +#define __SPI3_CLK_ENABLE __HAL_RCC_SPI3_CLK_ENABLE +#define __SPI3_CLK_SLEEP_DISABLE __HAL_RCC_SPI3_CLK_SLEEP_DISABLE +#define __SPI3_CLK_SLEEP_ENABLE __HAL_RCC_SPI3_CLK_SLEEP_ENABLE +#define __SPI3_FORCE_RESET __HAL_RCC_SPI3_FORCE_RESET +#define __SPI3_RELEASE_RESET __HAL_RCC_SPI3_RELEASE_RESET +#define __SRAM_CLK_DISABLE __HAL_RCC_SRAM_CLK_DISABLE +#define __SRAM_CLK_ENABLE __HAL_RCC_SRAM_CLK_ENABLE +#define __SRAM1_CLK_SLEEP_DISABLE __HAL_RCC_SRAM1_CLK_SLEEP_DISABLE +#define __SRAM1_CLK_SLEEP_ENABLE __HAL_RCC_SRAM1_CLK_SLEEP_ENABLE +#define __SRAM2_CLK_SLEEP_DISABLE __HAL_RCC_SRAM2_CLK_SLEEP_DISABLE +#define __SRAM2_CLK_SLEEP_ENABLE __HAL_RCC_SRAM2_CLK_SLEEP_ENABLE +#define __SWPMI1_CLK_DISABLE __HAL_RCC_SWPMI1_CLK_DISABLE +#define __SWPMI1_CLK_ENABLE __HAL_RCC_SWPMI1_CLK_ENABLE +#define __SWPMI1_CLK_SLEEP_DISABLE __HAL_RCC_SWPMI1_CLK_SLEEP_DISABLE +#define __SWPMI1_CLK_SLEEP_ENABLE __HAL_RCC_SWPMI1_CLK_SLEEP_ENABLE +#define __SWPMI1_FORCE_RESET __HAL_RCC_SWPMI1_FORCE_RESET +#define __SWPMI1_RELEASE_RESET __HAL_RCC_SWPMI1_RELEASE_RESET +#define __SYSCFG_CLK_DISABLE __HAL_RCC_SYSCFG_CLK_DISABLE +#define __SYSCFG_CLK_ENABLE __HAL_RCC_SYSCFG_CLK_ENABLE +#define __SYSCFG_CLK_SLEEP_DISABLE __HAL_RCC_SYSCFG_CLK_SLEEP_DISABLE +#define __SYSCFG_CLK_SLEEP_ENABLE __HAL_RCC_SYSCFG_CLK_SLEEP_ENABLE +#define __SYSCFG_FORCE_RESET __HAL_RCC_SYSCFG_FORCE_RESET +#define __SYSCFG_RELEASE_RESET __HAL_RCC_SYSCFG_RELEASE_RESET +#define __TIM1_CLK_DISABLE __HAL_RCC_TIM1_CLK_DISABLE +#define __TIM1_CLK_ENABLE __HAL_RCC_TIM1_CLK_ENABLE +#define __TIM1_CLK_SLEEP_DISABLE __HAL_RCC_TIM1_CLK_SLEEP_DISABLE +#define __TIM1_CLK_SLEEP_ENABLE __HAL_RCC_TIM1_CLK_SLEEP_ENABLE +#define __TIM1_FORCE_RESET __HAL_RCC_TIM1_FORCE_RESET +#define __TIM1_RELEASE_RESET __HAL_RCC_TIM1_RELEASE_RESET +#define __TIM10_CLK_DISABLE __HAL_RCC_TIM10_CLK_DISABLE +#define __TIM10_CLK_ENABLE __HAL_RCC_TIM10_CLK_ENABLE +#define __TIM10_FORCE_RESET __HAL_RCC_TIM10_FORCE_RESET +#define __TIM10_RELEASE_RESET __HAL_RCC_TIM10_RELEASE_RESET +#define __TIM11_CLK_DISABLE __HAL_RCC_TIM11_CLK_DISABLE +#define __TIM11_CLK_ENABLE __HAL_RCC_TIM11_CLK_ENABLE +#define __TIM11_FORCE_RESET __HAL_RCC_TIM11_FORCE_RESET +#define __TIM11_RELEASE_RESET __HAL_RCC_TIM11_RELEASE_RESET +#define __TIM12_CLK_DISABLE __HAL_RCC_TIM12_CLK_DISABLE +#define __TIM12_CLK_ENABLE __HAL_RCC_TIM12_CLK_ENABLE +#define __TIM12_FORCE_RESET __HAL_RCC_TIM12_FORCE_RESET +#define __TIM12_RELEASE_RESET __HAL_RCC_TIM12_RELEASE_RESET +#define __TIM13_CLK_DISABLE __HAL_RCC_TIM13_CLK_DISABLE +#define __TIM13_CLK_ENABLE __HAL_RCC_TIM13_CLK_ENABLE +#define __TIM13_FORCE_RESET __HAL_RCC_TIM13_FORCE_RESET +#define __TIM13_RELEASE_RESET __HAL_RCC_TIM13_RELEASE_RESET +#define __TIM14_CLK_DISABLE __HAL_RCC_TIM14_CLK_DISABLE +#define __TIM14_CLK_ENABLE __HAL_RCC_TIM14_CLK_ENABLE +#define __TIM14_FORCE_RESET __HAL_RCC_TIM14_FORCE_RESET +#define __TIM14_RELEASE_RESET __HAL_RCC_TIM14_RELEASE_RESET +#define __TIM15_CLK_DISABLE __HAL_RCC_TIM15_CLK_DISABLE +#define __TIM15_CLK_ENABLE __HAL_RCC_TIM15_CLK_ENABLE +#define __TIM15_CLK_SLEEP_DISABLE __HAL_RCC_TIM15_CLK_SLEEP_DISABLE +#define __TIM15_CLK_SLEEP_ENABLE __HAL_RCC_TIM15_CLK_SLEEP_ENABLE +#define __TIM15_FORCE_RESET __HAL_RCC_TIM15_FORCE_RESET +#define __TIM15_RELEASE_RESET __HAL_RCC_TIM15_RELEASE_RESET +#define __TIM16_CLK_DISABLE __HAL_RCC_TIM16_CLK_DISABLE +#define __TIM16_CLK_ENABLE __HAL_RCC_TIM16_CLK_ENABLE +#define __TIM16_CLK_SLEEP_DISABLE __HAL_RCC_TIM16_CLK_SLEEP_DISABLE +#define __TIM16_CLK_SLEEP_ENABLE __HAL_RCC_TIM16_CLK_SLEEP_ENABLE +#define __TIM16_FORCE_RESET __HAL_RCC_TIM16_FORCE_RESET +#define __TIM16_RELEASE_RESET __HAL_RCC_TIM16_RELEASE_RESET +#define __TIM17_CLK_DISABLE __HAL_RCC_TIM17_CLK_DISABLE +#define __TIM17_CLK_ENABLE __HAL_RCC_TIM17_CLK_ENABLE +#define __TIM17_CLK_SLEEP_DISABLE __HAL_RCC_TIM17_CLK_SLEEP_DISABLE +#define __TIM17_CLK_SLEEP_ENABLE __HAL_RCC_TIM17_CLK_SLEEP_ENABLE +#define __TIM17_FORCE_RESET __HAL_RCC_TIM17_FORCE_RESET +#define __TIM17_RELEASE_RESET __HAL_RCC_TIM17_RELEASE_RESET +#define __TIM2_CLK_DISABLE __HAL_RCC_TIM2_CLK_DISABLE +#define __TIM2_CLK_ENABLE __HAL_RCC_TIM2_CLK_ENABLE +#define __TIM2_CLK_SLEEP_DISABLE __HAL_RCC_TIM2_CLK_SLEEP_DISABLE +#define __TIM2_CLK_SLEEP_ENABLE __HAL_RCC_TIM2_CLK_SLEEP_ENABLE +#define __TIM2_FORCE_RESET __HAL_RCC_TIM2_FORCE_RESET +#define __TIM2_RELEASE_RESET __HAL_RCC_TIM2_RELEASE_RESET +#define __TIM3_CLK_DISABLE __HAL_RCC_TIM3_CLK_DISABLE +#define __TIM3_CLK_ENABLE __HAL_RCC_TIM3_CLK_ENABLE +#define __TIM3_CLK_SLEEP_DISABLE __HAL_RCC_TIM3_CLK_SLEEP_DISABLE +#define __TIM3_CLK_SLEEP_ENABLE __HAL_RCC_TIM3_CLK_SLEEP_ENABLE +#define __TIM3_FORCE_RESET __HAL_RCC_TIM3_FORCE_RESET +#define __TIM3_RELEASE_RESET __HAL_RCC_TIM3_RELEASE_RESET +#define __TIM4_CLK_DISABLE __HAL_RCC_TIM4_CLK_DISABLE +#define __TIM4_CLK_ENABLE __HAL_RCC_TIM4_CLK_ENABLE +#define __TIM4_CLK_SLEEP_DISABLE __HAL_RCC_TIM4_CLK_SLEEP_DISABLE +#define __TIM4_CLK_SLEEP_ENABLE __HAL_RCC_TIM4_CLK_SLEEP_ENABLE +#define __TIM4_FORCE_RESET __HAL_RCC_TIM4_FORCE_RESET +#define __TIM4_RELEASE_RESET __HAL_RCC_TIM4_RELEASE_RESET +#define __TIM5_CLK_DISABLE __HAL_RCC_TIM5_CLK_DISABLE +#define __TIM5_CLK_ENABLE __HAL_RCC_TIM5_CLK_ENABLE +#define __TIM5_CLK_SLEEP_DISABLE __HAL_RCC_TIM5_CLK_SLEEP_DISABLE +#define __TIM5_CLK_SLEEP_ENABLE __HAL_RCC_TIM5_CLK_SLEEP_ENABLE +#define __TIM5_FORCE_RESET __HAL_RCC_TIM5_FORCE_RESET +#define __TIM5_RELEASE_RESET __HAL_RCC_TIM5_RELEASE_RESET +#define __TIM6_CLK_DISABLE __HAL_RCC_TIM6_CLK_DISABLE +#define __TIM6_CLK_ENABLE __HAL_RCC_TIM6_CLK_ENABLE +#define __TIM6_CLK_SLEEP_DISABLE __HAL_RCC_TIM6_CLK_SLEEP_DISABLE +#define __TIM6_CLK_SLEEP_ENABLE __HAL_RCC_TIM6_CLK_SLEEP_ENABLE +#define __TIM6_FORCE_RESET __HAL_RCC_TIM6_FORCE_RESET +#define __TIM6_RELEASE_RESET __HAL_RCC_TIM6_RELEASE_RESET +#define __TIM7_CLK_DISABLE __HAL_RCC_TIM7_CLK_DISABLE +#define __TIM7_CLK_ENABLE __HAL_RCC_TIM7_CLK_ENABLE +#define __TIM7_CLK_SLEEP_DISABLE __HAL_RCC_TIM7_CLK_SLEEP_DISABLE +#define __TIM7_CLK_SLEEP_ENABLE __HAL_RCC_TIM7_CLK_SLEEP_ENABLE +#define __TIM7_FORCE_RESET __HAL_RCC_TIM7_FORCE_RESET +#define __TIM7_RELEASE_RESET __HAL_RCC_TIM7_RELEASE_RESET +#define __TIM8_CLK_DISABLE __HAL_RCC_TIM8_CLK_DISABLE +#define __TIM8_CLK_ENABLE __HAL_RCC_TIM8_CLK_ENABLE +#define __TIM8_CLK_SLEEP_DISABLE __HAL_RCC_TIM8_CLK_SLEEP_DISABLE +#define __TIM8_CLK_SLEEP_ENABLE __HAL_RCC_TIM8_CLK_SLEEP_ENABLE +#define __TIM8_FORCE_RESET __HAL_RCC_TIM8_FORCE_RESET +#define __TIM8_RELEASE_RESET __HAL_RCC_TIM8_RELEASE_RESET +#define __TIM9_CLK_DISABLE __HAL_RCC_TIM9_CLK_DISABLE +#define __TIM9_CLK_ENABLE __HAL_RCC_TIM9_CLK_ENABLE +#define __TIM9_FORCE_RESET __HAL_RCC_TIM9_FORCE_RESET +#define __TIM9_RELEASE_RESET __HAL_RCC_TIM9_RELEASE_RESET +#define __TSC_CLK_DISABLE __HAL_RCC_TSC_CLK_DISABLE +#define __TSC_CLK_ENABLE __HAL_RCC_TSC_CLK_ENABLE +#define __TSC_CLK_SLEEP_DISABLE __HAL_RCC_TSC_CLK_SLEEP_DISABLE +#define __TSC_CLK_SLEEP_ENABLE __HAL_RCC_TSC_CLK_SLEEP_ENABLE +#define __TSC_FORCE_RESET __HAL_RCC_TSC_FORCE_RESET +#define __TSC_RELEASE_RESET __HAL_RCC_TSC_RELEASE_RESET +#define __UART4_CLK_DISABLE __HAL_RCC_UART4_CLK_DISABLE +#define __UART4_CLK_ENABLE __HAL_RCC_UART4_CLK_ENABLE +#define __UART4_CLK_SLEEP_DISABLE __HAL_RCC_UART4_CLK_SLEEP_DISABLE +#define __UART4_CLK_SLEEP_ENABLE __HAL_RCC_UART4_CLK_SLEEP_ENABLE +#define __UART4_FORCE_RESET __HAL_RCC_UART4_FORCE_RESET +#define __UART4_RELEASE_RESET __HAL_RCC_UART4_RELEASE_RESET +#define __UART5_CLK_DISABLE __HAL_RCC_UART5_CLK_DISABLE +#define __UART5_CLK_ENABLE __HAL_RCC_UART5_CLK_ENABLE +#define __UART5_CLK_SLEEP_DISABLE __HAL_RCC_UART5_CLK_SLEEP_DISABLE +#define __UART5_CLK_SLEEP_ENABLE __HAL_RCC_UART5_CLK_SLEEP_ENABLE +#define __UART5_FORCE_RESET __HAL_RCC_UART5_FORCE_RESET +#define __UART5_RELEASE_RESET __HAL_RCC_UART5_RELEASE_RESET +#define __USART1_CLK_DISABLE __HAL_RCC_USART1_CLK_DISABLE +#define __USART1_CLK_ENABLE __HAL_RCC_USART1_CLK_ENABLE +#define __USART1_CLK_SLEEP_DISABLE __HAL_RCC_USART1_CLK_SLEEP_DISABLE +#define __USART1_CLK_SLEEP_ENABLE __HAL_RCC_USART1_CLK_SLEEP_ENABLE +#define __USART1_FORCE_RESET __HAL_RCC_USART1_FORCE_RESET +#define __USART1_RELEASE_RESET __HAL_RCC_USART1_RELEASE_RESET +#define __USART2_CLK_DISABLE __HAL_RCC_USART2_CLK_DISABLE +#define __USART2_CLK_ENABLE __HAL_RCC_USART2_CLK_ENABLE +#define __USART2_CLK_SLEEP_DISABLE __HAL_RCC_USART2_CLK_SLEEP_DISABLE +#define __USART2_CLK_SLEEP_ENABLE __HAL_RCC_USART2_CLK_SLEEP_ENABLE +#define __USART2_FORCE_RESET __HAL_RCC_USART2_FORCE_RESET +#define __USART2_RELEASE_RESET __HAL_RCC_USART2_RELEASE_RESET +#define __USART3_CLK_DISABLE __HAL_RCC_USART3_CLK_DISABLE +#define __USART3_CLK_ENABLE __HAL_RCC_USART3_CLK_ENABLE +#define __USART3_CLK_SLEEP_DISABLE __HAL_RCC_USART3_CLK_SLEEP_DISABLE +#define __USART3_CLK_SLEEP_ENABLE __HAL_RCC_USART3_CLK_SLEEP_ENABLE +#define __USART3_FORCE_RESET __HAL_RCC_USART3_FORCE_RESET +#define __USART3_RELEASE_RESET __HAL_RCC_USART3_RELEASE_RESET +#define __USART4_CLK_DISABLE __HAL_RCC_UART4_CLK_DISABLE +#define __USART4_CLK_ENABLE __HAL_RCC_UART4_CLK_ENABLE +#define __USART4_CLK_SLEEP_ENABLE __HAL_RCC_UART4_CLK_SLEEP_ENABLE +#define __USART4_CLK_SLEEP_DISABLE __HAL_RCC_UART4_CLK_SLEEP_DISABLE +#define __USART4_FORCE_RESET __HAL_RCC_UART4_FORCE_RESET +#define __USART4_RELEASE_RESET __HAL_RCC_UART4_RELEASE_RESET +#define __USART5_CLK_DISABLE __HAL_RCC_UART5_CLK_DISABLE +#define __USART5_CLK_ENABLE __HAL_RCC_UART5_CLK_ENABLE +#define __USART5_CLK_SLEEP_ENABLE __HAL_RCC_UART5_CLK_SLEEP_ENABLE +#define __USART5_CLK_SLEEP_DISABLE __HAL_RCC_UART5_CLK_SLEEP_DISABLE +#define __USART5_FORCE_RESET __HAL_RCC_UART5_FORCE_RESET +#define __USART5_RELEASE_RESET __HAL_RCC_UART5_RELEASE_RESET +#define __USART7_CLK_DISABLE __HAL_RCC_UART7_CLK_DISABLE +#define __USART7_CLK_ENABLE __HAL_RCC_UART7_CLK_ENABLE +#define __USART7_FORCE_RESET __HAL_RCC_UART7_FORCE_RESET +#define __USART7_RELEASE_RESET __HAL_RCC_UART7_RELEASE_RESET +#define __USART8_CLK_DISABLE __HAL_RCC_UART8_CLK_DISABLE +#define __USART8_CLK_ENABLE __HAL_RCC_UART8_CLK_ENABLE +#define __USART8_FORCE_RESET __HAL_RCC_UART8_FORCE_RESET +#define __USART8_RELEASE_RESET __HAL_RCC_UART8_RELEASE_RESET +#define __USB_CLK_DISABLE __HAL_RCC_USB_CLK_DISABLE +#define __USB_CLK_ENABLE __HAL_RCC_USB_CLK_ENABLE +#define __USB_FORCE_RESET __HAL_RCC_USB_FORCE_RESET +#define __USB_CLK_SLEEP_ENABLE __HAL_RCC_USB_CLK_SLEEP_ENABLE +#define __USB_CLK_SLEEP_DISABLE __HAL_RCC_USB_CLK_SLEEP_DISABLE +#define __USB_OTG_FS_CLK_DISABLE __HAL_RCC_USB_OTG_FS_CLK_DISABLE +#define __USB_OTG_FS_CLK_ENABLE __HAL_RCC_USB_OTG_FS_CLK_ENABLE +#define __USB_RELEASE_RESET __HAL_RCC_USB_RELEASE_RESET +#define __WWDG_CLK_DISABLE __HAL_RCC_WWDG_CLK_DISABLE +#define __WWDG_CLK_ENABLE __HAL_RCC_WWDG_CLK_ENABLE +#define __WWDG_CLK_SLEEP_DISABLE __HAL_RCC_WWDG_CLK_SLEEP_DISABLE +#define __WWDG_CLK_SLEEP_ENABLE __HAL_RCC_WWDG_CLK_SLEEP_ENABLE +#define __WWDG_FORCE_RESET __HAL_RCC_WWDG_FORCE_RESET +#define __WWDG_RELEASE_RESET __HAL_RCC_WWDG_RELEASE_RESET +#define __TIM21_CLK_ENABLE __HAL_RCC_TIM21_CLK_ENABLE +#define __TIM21_CLK_DISABLE __HAL_RCC_TIM21_CLK_DISABLE +#define __TIM21_FORCE_RESET __HAL_RCC_TIM21_FORCE_RESET +#define __TIM21_RELEASE_RESET __HAL_RCC_TIM21_RELEASE_RESET +#define __TIM21_CLK_SLEEP_ENABLE __HAL_RCC_TIM21_CLK_SLEEP_ENABLE +#define __TIM21_CLK_SLEEP_DISABLE __HAL_RCC_TIM21_CLK_SLEEP_DISABLE +#define __TIM22_CLK_ENABLE __HAL_RCC_TIM22_CLK_ENABLE +#define __TIM22_CLK_DISABLE __HAL_RCC_TIM22_CLK_DISABLE +#define __TIM22_FORCE_RESET __HAL_RCC_TIM22_FORCE_RESET +#define __TIM22_RELEASE_RESET __HAL_RCC_TIM22_RELEASE_RESET +#define __TIM22_CLK_SLEEP_ENABLE __HAL_RCC_TIM22_CLK_SLEEP_ENABLE +#define __TIM22_CLK_SLEEP_DISABLE __HAL_RCC_TIM22_CLK_SLEEP_DISABLE +#define __CRS_CLK_DISABLE __HAL_RCC_CRS_CLK_DISABLE +#define __CRS_CLK_ENABLE __HAL_RCC_CRS_CLK_ENABLE +#define __CRS_CLK_SLEEP_DISABLE __HAL_RCC_CRS_CLK_SLEEP_DISABLE +#define __CRS_CLK_SLEEP_ENABLE __HAL_RCC_CRS_CLK_SLEEP_ENABLE +#define __CRS_FORCE_RESET __HAL_RCC_CRS_FORCE_RESET +#define __CRS_RELEASE_RESET __HAL_RCC_CRS_RELEASE_RESET +#define __RCC_BACKUPRESET_FORCE __HAL_RCC_BACKUPRESET_FORCE +#define __RCC_BACKUPRESET_RELEASE __HAL_RCC_BACKUPRESET_RELEASE + +#define __USB_OTG_FS_FORCE_RESET __HAL_RCC_USB_OTG_FS_FORCE_RESET +#define __USB_OTG_FS_RELEASE_RESET __HAL_RCC_USB_OTG_FS_RELEASE_RESET +#define __USB_OTG_FS_CLK_SLEEP_ENABLE __HAL_RCC_USB_OTG_FS_CLK_SLEEP_ENABLE +#define __USB_OTG_FS_CLK_SLEEP_DISABLE __HAL_RCC_USB_OTG_FS_CLK_SLEEP_DISABLE +#define __USB_OTG_HS_CLK_DISABLE __HAL_RCC_USB_OTG_HS_CLK_DISABLE +#define __USB_OTG_HS_CLK_ENABLE __HAL_RCC_USB_OTG_HS_CLK_ENABLE +#define __USB_OTG_HS_ULPI_CLK_ENABLE __HAL_RCC_USB_OTG_HS_ULPI_CLK_ENABLE +#define __USB_OTG_HS_ULPI_CLK_DISABLE __HAL_RCC_USB_OTG_HS_ULPI_CLK_DISABLE +#define __TIM9_CLK_SLEEP_ENABLE __HAL_RCC_TIM9_CLK_SLEEP_ENABLE +#define __TIM9_CLK_SLEEP_DISABLE __HAL_RCC_TIM9_CLK_SLEEP_DISABLE +#define __TIM10_CLK_SLEEP_ENABLE __HAL_RCC_TIM10_CLK_SLEEP_ENABLE +#define __TIM10_CLK_SLEEP_DISABLE __HAL_RCC_TIM10_CLK_SLEEP_DISABLE +#define __TIM11_CLK_SLEEP_ENABLE __HAL_RCC_TIM11_CLK_SLEEP_ENABLE +#define __TIM11_CLK_SLEEP_DISABLE __HAL_RCC_TIM11_CLK_SLEEP_DISABLE +#define __ETHMACPTP_CLK_SLEEP_ENABLE __HAL_RCC_ETHMACPTP_CLK_SLEEP_ENABLE +#define __ETHMACPTP_CLK_SLEEP_DISABLE __HAL_RCC_ETHMACPTP_CLK_SLEEP_DISABLE +#define __ETHMACPTP_CLK_ENABLE __HAL_RCC_ETHMACPTP_CLK_ENABLE +#define __ETHMACPTP_CLK_DISABLE __HAL_RCC_ETHMACPTP_CLK_DISABLE +#define __HASH_CLK_ENABLE __HAL_RCC_HASH_CLK_ENABLE +#define __HASH_FORCE_RESET __HAL_RCC_HASH_FORCE_RESET +#define __HASH_RELEASE_RESET __HAL_RCC_HASH_RELEASE_RESET +#define __HASH_CLK_SLEEP_ENABLE __HAL_RCC_HASH_CLK_SLEEP_ENABLE +#define __HASH_CLK_SLEEP_DISABLE __HAL_RCC_HASH_CLK_SLEEP_DISABLE +#define __HASH_CLK_DISABLE __HAL_RCC_HASH_CLK_DISABLE +#define __SPI5_CLK_ENABLE __HAL_RCC_SPI5_CLK_ENABLE +#define __SPI5_CLK_DISABLE __HAL_RCC_SPI5_CLK_DISABLE +#define __SPI5_FORCE_RESET __HAL_RCC_SPI5_FORCE_RESET +#define __SPI5_RELEASE_RESET __HAL_RCC_SPI5_RELEASE_RESET +#define __SPI5_CLK_SLEEP_ENABLE __HAL_RCC_SPI5_CLK_SLEEP_ENABLE +#define __SPI5_CLK_SLEEP_DISABLE __HAL_RCC_SPI5_CLK_SLEEP_DISABLE +#define __SPI6_CLK_ENABLE __HAL_RCC_SPI6_CLK_ENABLE +#define __SPI6_CLK_DISABLE __HAL_RCC_SPI6_CLK_DISABLE +#define __SPI6_FORCE_RESET __HAL_RCC_SPI6_FORCE_RESET +#define __SPI6_RELEASE_RESET __HAL_RCC_SPI6_RELEASE_RESET +#define __SPI6_CLK_SLEEP_ENABLE __HAL_RCC_SPI6_CLK_SLEEP_ENABLE +#define __SPI6_CLK_SLEEP_DISABLE __HAL_RCC_SPI6_CLK_SLEEP_DISABLE +#define __LTDC_CLK_ENABLE __HAL_RCC_LTDC_CLK_ENABLE +#define __LTDC_CLK_DISABLE __HAL_RCC_LTDC_CLK_DISABLE +#define __LTDC_FORCE_RESET __HAL_RCC_LTDC_FORCE_RESET +#define __LTDC_RELEASE_RESET __HAL_RCC_LTDC_RELEASE_RESET +#define __LTDC_CLK_SLEEP_ENABLE __HAL_RCC_LTDC_CLK_SLEEP_ENABLE +#define __ETHMAC_CLK_SLEEP_ENABLE __HAL_RCC_ETHMAC_CLK_SLEEP_ENABLE +#define __ETHMAC_CLK_SLEEP_DISABLE __HAL_RCC_ETHMAC_CLK_SLEEP_DISABLE +#define __ETHMACTX_CLK_SLEEP_ENABLE __HAL_RCC_ETHMACTX_CLK_SLEEP_ENABLE +#define __ETHMACTX_CLK_SLEEP_DISABLE __HAL_RCC_ETHMACTX_CLK_SLEEP_DISABLE +#define __ETHMACRX_CLK_SLEEP_ENABLE __HAL_RCC_ETHMACRX_CLK_SLEEP_ENABLE +#define __ETHMACRX_CLK_SLEEP_DISABLE __HAL_RCC_ETHMACRX_CLK_SLEEP_DISABLE +#define __TIM12_CLK_SLEEP_ENABLE __HAL_RCC_TIM12_CLK_SLEEP_ENABLE +#define __TIM12_CLK_SLEEP_DISABLE __HAL_RCC_TIM12_CLK_SLEEP_DISABLE +#define __TIM13_CLK_SLEEP_ENABLE __HAL_RCC_TIM13_CLK_SLEEP_ENABLE +#define __TIM13_CLK_SLEEP_DISABLE __HAL_RCC_TIM13_CLK_SLEEP_DISABLE +#define __TIM14_CLK_SLEEP_ENABLE __HAL_RCC_TIM14_CLK_SLEEP_ENABLE +#define __TIM14_CLK_SLEEP_DISABLE __HAL_RCC_TIM14_CLK_SLEEP_DISABLE +#define __BKPSRAM_CLK_ENABLE __HAL_RCC_BKPSRAM_CLK_ENABLE +#define __BKPSRAM_CLK_DISABLE __HAL_RCC_BKPSRAM_CLK_DISABLE +#define __BKPSRAM_CLK_SLEEP_ENABLE __HAL_RCC_BKPSRAM_CLK_SLEEP_ENABLE +#define __BKPSRAM_CLK_SLEEP_DISABLE __HAL_RCC_BKPSRAM_CLK_SLEEP_DISABLE +#define __CCMDATARAMEN_CLK_ENABLE __HAL_RCC_CCMDATARAMEN_CLK_ENABLE +#define __CCMDATARAMEN_CLK_DISABLE __HAL_RCC_CCMDATARAMEN_CLK_DISABLE +#define __USART6_CLK_ENABLE __HAL_RCC_USART6_CLK_ENABLE +#define __USART6_CLK_DISABLE __HAL_RCC_USART6_CLK_DISABLE +#define __USART6_FORCE_RESET __HAL_RCC_USART6_FORCE_RESET +#define __USART6_RELEASE_RESET __HAL_RCC_USART6_RELEASE_RESET +#define __USART6_CLK_SLEEP_ENABLE __HAL_RCC_USART6_CLK_SLEEP_ENABLE +#define __USART6_CLK_SLEEP_DISABLE __HAL_RCC_USART6_CLK_SLEEP_DISABLE +#define __SPI4_CLK_ENABLE __HAL_RCC_SPI4_CLK_ENABLE +#define __SPI4_CLK_DISABLE __HAL_RCC_SPI4_CLK_DISABLE +#define __SPI4_FORCE_RESET __HAL_RCC_SPI4_FORCE_RESET +#define __SPI4_RELEASE_RESET __HAL_RCC_SPI4_RELEASE_RESET +#define __SPI4_CLK_SLEEP_ENABLE __HAL_RCC_SPI4_CLK_SLEEP_ENABLE +#define __SPI4_CLK_SLEEP_DISABLE __HAL_RCC_SPI4_CLK_SLEEP_DISABLE +#define __GPIOI_CLK_ENABLE __HAL_RCC_GPIOI_CLK_ENABLE +#define __GPIOI_CLK_DISABLE __HAL_RCC_GPIOI_CLK_DISABLE +#define __GPIOI_FORCE_RESET __HAL_RCC_GPIOI_FORCE_RESET +#define __GPIOI_RELEASE_RESET __HAL_RCC_GPIOI_RELEASE_RESET +#define __GPIOI_CLK_SLEEP_ENABLE __HAL_RCC_GPIOI_CLK_SLEEP_ENABLE +#define __GPIOI_CLK_SLEEP_DISABLE __HAL_RCC_GPIOI_CLK_SLEEP_DISABLE +#define __GPIOJ_CLK_ENABLE __HAL_RCC_GPIOJ_CLK_ENABLE +#define __GPIOJ_CLK_DISABLE __HAL_RCC_GPIOJ_CLK_DISABLE +#define __GPIOJ_FORCE_RESET __HAL_RCC_GPIOJ_FORCE_RESET +#define __GPIOJ_RELEASE_RESET __HAL_RCC_GPIOJ_RELEASE_RESET +#define __GPIOJ_CLK_SLEEP_ENABLE __HAL_RCC_GPIOJ_CLK_SLEEP_ENABLE +#define __GPIOJ_CLK_SLEEP_DISABLE __HAL_RCC_GPIOJ_CLK_SLEEP_DISABLE +#define __GPIOK_CLK_ENABLE __HAL_RCC_GPIOK_CLK_ENABLE +#define __GPIOK_CLK_DISABLE __HAL_RCC_GPIOK_CLK_DISABLE +#define __GPIOK_RELEASE_RESET __HAL_RCC_GPIOK_RELEASE_RESET +#define __GPIOK_CLK_SLEEP_ENABLE __HAL_RCC_GPIOK_CLK_SLEEP_ENABLE +#define __GPIOK_CLK_SLEEP_DISABLE __HAL_RCC_GPIOK_CLK_SLEEP_DISABLE +#define __ETH_CLK_ENABLE __HAL_RCC_ETH_CLK_ENABLE +#define __ETH_CLK_DISABLE __HAL_RCC_ETH_CLK_DISABLE +#define __DCMI_CLK_ENABLE __HAL_RCC_DCMI_CLK_ENABLE +#define __DCMI_CLK_DISABLE __HAL_RCC_DCMI_CLK_DISABLE +#define __DCMI_FORCE_RESET __HAL_RCC_DCMI_FORCE_RESET +#define __DCMI_RELEASE_RESET __HAL_RCC_DCMI_RELEASE_RESET +#define __DCMI_CLK_SLEEP_ENABLE __HAL_RCC_DCMI_CLK_SLEEP_ENABLE +#define __DCMI_CLK_SLEEP_DISABLE __HAL_RCC_DCMI_CLK_SLEEP_DISABLE +#define __UART7_CLK_ENABLE __HAL_RCC_UART7_CLK_ENABLE +#define __UART7_CLK_DISABLE __HAL_RCC_UART7_CLK_DISABLE +#define __UART7_RELEASE_RESET __HAL_RCC_UART7_RELEASE_RESET +#define __UART7_FORCE_RESET __HAL_RCC_UART7_FORCE_RESET +#define __UART7_CLK_SLEEP_ENABLE __HAL_RCC_UART7_CLK_SLEEP_ENABLE +#define __UART7_CLK_SLEEP_DISABLE __HAL_RCC_UART7_CLK_SLEEP_DISABLE +#define __UART8_CLK_ENABLE __HAL_RCC_UART8_CLK_ENABLE +#define __UART8_CLK_DISABLE __HAL_RCC_UART8_CLK_DISABLE +#define __UART8_FORCE_RESET __HAL_RCC_UART8_FORCE_RESET +#define __UART8_RELEASE_RESET __HAL_RCC_UART8_RELEASE_RESET +#define __UART8_CLK_SLEEP_ENABLE __HAL_RCC_UART8_CLK_SLEEP_ENABLE +#define __UART8_CLK_SLEEP_DISABLE __HAL_RCC_UART8_CLK_SLEEP_DISABLE +#define __OTGHS_CLK_SLEEP_ENABLE __HAL_RCC_USB_OTG_HS_CLK_SLEEP_ENABLE +#define __OTGHS_CLK_SLEEP_DISABLE __HAL_RCC_USB_OTG_HS_CLK_SLEEP_DISABLE +#define __OTGHS_FORCE_RESET __HAL_RCC_USB_OTG_HS_FORCE_RESET +#define __OTGHS_RELEASE_RESET __HAL_RCC_USB_OTG_HS_RELEASE_RESET +#define __OTGHSULPI_CLK_SLEEP_ENABLE __HAL_RCC_USB_OTG_HS_ULPI_CLK_SLEEP_ENABLE +#define __OTGHSULPI_CLK_SLEEP_DISABLE __HAL_RCC_USB_OTG_HS_ULPI_CLK_SLEEP_DISABLE +#define __HAL_RCC_OTGHS_CLK_SLEEP_ENABLE __HAL_RCC_USB_OTG_HS_CLK_SLEEP_ENABLE +#define __HAL_RCC_OTGHS_CLK_SLEEP_DISABLE __HAL_RCC_USB_OTG_HS_CLK_SLEEP_DISABLE +#define __HAL_RCC_OTGHS_IS_CLK_SLEEP_ENABLED __HAL_RCC_USB_OTG_HS_IS_CLK_SLEEP_ENABLED +#define __HAL_RCC_OTGHS_IS_CLK_SLEEP_DISABLED __HAL_RCC_USB_OTG_HS_IS_CLK_SLEEP_DISABLED +#define __HAL_RCC_OTGHS_FORCE_RESET __HAL_RCC_USB_OTG_HS_FORCE_RESET +#define __HAL_RCC_OTGHS_RELEASE_RESET __HAL_RCC_USB_OTG_HS_RELEASE_RESET +#define __HAL_RCC_OTGHSULPI_CLK_SLEEP_ENABLE __HAL_RCC_USB_OTG_HS_ULPI_CLK_SLEEP_ENABLE +#define __HAL_RCC_OTGHSULPI_CLK_SLEEP_DISABLE __HAL_RCC_USB_OTG_HS_ULPI_CLK_SLEEP_DISABLE +#define __HAL_RCC_OTGHSULPI_IS_CLK_SLEEP_ENABLED __HAL_RCC_USB_OTG_HS_ULPI_IS_CLK_SLEEP_ENABLED +#define __HAL_RCC_OTGHSULPI_IS_CLK_SLEEP_DISABLED __HAL_RCC_USB_OTG_HS_ULPI_IS_CLK_SLEEP_DISABLED +#define __SRAM3_CLK_SLEEP_ENABLE __HAL_RCC_SRAM3_CLK_SLEEP_ENABLE +#define __CAN2_CLK_SLEEP_ENABLE __HAL_RCC_CAN2_CLK_SLEEP_ENABLE +#define __CAN2_CLK_SLEEP_DISABLE __HAL_RCC_CAN2_CLK_SLEEP_DISABLE +#define __DAC_CLK_SLEEP_ENABLE __HAL_RCC_DAC_CLK_SLEEP_ENABLE +#define __DAC_CLK_SLEEP_DISABLE __HAL_RCC_DAC_CLK_SLEEP_DISABLE +#define __ADC2_CLK_SLEEP_ENABLE __HAL_RCC_ADC2_CLK_SLEEP_ENABLE +#define __ADC2_CLK_SLEEP_DISABLE __HAL_RCC_ADC2_CLK_SLEEP_DISABLE +#define __ADC3_CLK_SLEEP_ENABLE __HAL_RCC_ADC3_CLK_SLEEP_ENABLE +#define __ADC3_CLK_SLEEP_DISABLE __HAL_RCC_ADC3_CLK_SLEEP_DISABLE +#define __FSMC_FORCE_RESET __HAL_RCC_FSMC_FORCE_RESET +#define __FSMC_RELEASE_RESET __HAL_RCC_FSMC_RELEASE_RESET +#define __FSMC_CLK_SLEEP_ENABLE __HAL_RCC_FSMC_CLK_SLEEP_ENABLE +#define __FSMC_CLK_SLEEP_DISABLE __HAL_RCC_FSMC_CLK_SLEEP_DISABLE +#define __SDIO_FORCE_RESET __HAL_RCC_SDIO_FORCE_RESET +#define __SDIO_RELEASE_RESET __HAL_RCC_SDIO_RELEASE_RESET +#define __SDIO_CLK_SLEEP_DISABLE __HAL_RCC_SDIO_CLK_SLEEP_DISABLE +#define __SDIO_CLK_SLEEP_ENABLE __HAL_RCC_SDIO_CLK_SLEEP_ENABLE +#define __DMA2D_CLK_ENABLE __HAL_RCC_DMA2D_CLK_ENABLE +#define __DMA2D_CLK_DISABLE __HAL_RCC_DMA2D_CLK_DISABLE +#define __DMA2D_FORCE_RESET __HAL_RCC_DMA2D_FORCE_RESET +#define __DMA2D_RELEASE_RESET __HAL_RCC_DMA2D_RELEASE_RESET +#define __DMA2D_CLK_SLEEP_ENABLE __HAL_RCC_DMA2D_CLK_SLEEP_ENABLE +#define __DMA2D_CLK_SLEEP_DISABLE __HAL_RCC_DMA2D_CLK_SLEEP_DISABLE + +/* alias define maintained for legacy */ +#define __HAL_RCC_OTGFS_FORCE_RESET __HAL_RCC_USB_OTG_FS_FORCE_RESET +#define __HAL_RCC_OTGFS_RELEASE_RESET __HAL_RCC_USB_OTG_FS_RELEASE_RESET + +#define __ADC12_CLK_ENABLE __HAL_RCC_ADC12_CLK_ENABLE +#define __ADC12_CLK_DISABLE __HAL_RCC_ADC12_CLK_DISABLE +#define __ADC34_CLK_ENABLE __HAL_RCC_ADC34_CLK_ENABLE +#define __ADC34_CLK_DISABLE __HAL_RCC_ADC34_CLK_DISABLE +#define __DAC2_CLK_ENABLE __HAL_RCC_DAC2_CLK_ENABLE +#define __DAC2_CLK_DISABLE __HAL_RCC_DAC2_CLK_DISABLE +#define __TIM18_CLK_ENABLE __HAL_RCC_TIM18_CLK_ENABLE +#define __TIM18_CLK_DISABLE __HAL_RCC_TIM18_CLK_DISABLE +#define __TIM19_CLK_ENABLE __HAL_RCC_TIM19_CLK_ENABLE +#define __TIM19_CLK_DISABLE __HAL_RCC_TIM19_CLK_DISABLE +#define __TIM20_CLK_ENABLE __HAL_RCC_TIM20_CLK_ENABLE +#define __TIM20_CLK_DISABLE __HAL_RCC_TIM20_CLK_DISABLE +#define __HRTIM1_CLK_ENABLE __HAL_RCC_HRTIM1_CLK_ENABLE +#define __HRTIM1_CLK_DISABLE __HAL_RCC_HRTIM1_CLK_DISABLE +#define __SDADC1_CLK_ENABLE __HAL_RCC_SDADC1_CLK_ENABLE +#define __SDADC2_CLK_ENABLE __HAL_RCC_SDADC2_CLK_ENABLE +#define __SDADC3_CLK_ENABLE __HAL_RCC_SDADC3_CLK_ENABLE +#define __SDADC1_CLK_DISABLE __HAL_RCC_SDADC1_CLK_DISABLE +#define __SDADC2_CLK_DISABLE __HAL_RCC_SDADC2_CLK_DISABLE +#define __SDADC3_CLK_DISABLE __HAL_RCC_SDADC3_CLK_DISABLE + +#define __ADC12_FORCE_RESET __HAL_RCC_ADC12_FORCE_RESET +#define __ADC12_RELEASE_RESET __HAL_RCC_ADC12_RELEASE_RESET +#define __ADC34_FORCE_RESET __HAL_RCC_ADC34_FORCE_RESET +#define __ADC34_RELEASE_RESET __HAL_RCC_ADC34_RELEASE_RESET +#define __DAC2_FORCE_RESET __HAL_RCC_DAC2_FORCE_RESET +#define __DAC2_RELEASE_RESET __HAL_RCC_DAC2_RELEASE_RESET +#define __TIM18_FORCE_RESET __HAL_RCC_TIM18_FORCE_RESET +#define __TIM18_RELEASE_RESET __HAL_RCC_TIM18_RELEASE_RESET +#define __TIM19_FORCE_RESET __HAL_RCC_TIM19_FORCE_RESET +#define __TIM19_RELEASE_RESET __HAL_RCC_TIM19_RELEASE_RESET +#define __TIM20_FORCE_RESET __HAL_RCC_TIM20_FORCE_RESET +#define __TIM20_RELEASE_RESET __HAL_RCC_TIM20_RELEASE_RESET +#define __HRTIM1_FORCE_RESET __HAL_RCC_HRTIM1_FORCE_RESET +#define __HRTIM1_RELEASE_RESET __HAL_RCC_HRTIM1_RELEASE_RESET +#define __SDADC1_FORCE_RESET __HAL_RCC_SDADC1_FORCE_RESET +#define __SDADC2_FORCE_RESET __HAL_RCC_SDADC2_FORCE_RESET +#define __SDADC3_FORCE_RESET __HAL_RCC_SDADC3_FORCE_RESET +#define __SDADC1_RELEASE_RESET __HAL_RCC_SDADC1_RELEASE_RESET +#define __SDADC2_RELEASE_RESET __HAL_RCC_SDADC2_RELEASE_RESET +#define __SDADC3_RELEASE_RESET __HAL_RCC_SDADC3_RELEASE_RESET + +#define __ADC1_IS_CLK_ENABLED __HAL_RCC_ADC1_IS_CLK_ENABLED +#define __ADC1_IS_CLK_DISABLED __HAL_RCC_ADC1_IS_CLK_DISABLED +#define __ADC12_IS_CLK_ENABLED __HAL_RCC_ADC12_IS_CLK_ENABLED +#define __ADC12_IS_CLK_DISABLED __HAL_RCC_ADC12_IS_CLK_DISABLED +#define __ADC34_IS_CLK_ENABLED __HAL_RCC_ADC34_IS_CLK_ENABLED +#define __ADC34_IS_CLK_DISABLED __HAL_RCC_ADC34_IS_CLK_DISABLED +#define __CEC_IS_CLK_ENABLED __HAL_RCC_CEC_IS_CLK_ENABLED +#define __CEC_IS_CLK_DISABLED __HAL_RCC_CEC_IS_CLK_DISABLED +#define __CRC_IS_CLK_ENABLED __HAL_RCC_CRC_IS_CLK_ENABLED +#define __CRC_IS_CLK_DISABLED __HAL_RCC_CRC_IS_CLK_DISABLED +#define __DAC1_IS_CLK_ENABLED __HAL_RCC_DAC1_IS_CLK_ENABLED +#define __DAC1_IS_CLK_DISABLED __HAL_RCC_DAC1_IS_CLK_DISABLED +#define __DAC2_IS_CLK_ENABLED __HAL_RCC_DAC2_IS_CLK_ENABLED +#define __DAC2_IS_CLK_DISABLED __HAL_RCC_DAC2_IS_CLK_DISABLED +#define __DMA1_IS_CLK_ENABLED __HAL_RCC_DMA1_IS_CLK_ENABLED +#define __DMA1_IS_CLK_DISABLED __HAL_RCC_DMA1_IS_CLK_DISABLED +#define __DMA2_IS_CLK_ENABLED __HAL_RCC_DMA2_IS_CLK_ENABLED +#define __DMA2_IS_CLK_DISABLED __HAL_RCC_DMA2_IS_CLK_DISABLED +#define __FLITF_IS_CLK_ENABLED __HAL_RCC_FLITF_IS_CLK_ENABLED +#define __FLITF_IS_CLK_DISABLED __HAL_RCC_FLITF_IS_CLK_DISABLED +#define __FMC_IS_CLK_ENABLED __HAL_RCC_FMC_IS_CLK_ENABLED +#define __FMC_IS_CLK_DISABLED __HAL_RCC_FMC_IS_CLK_DISABLED +#define __GPIOA_IS_CLK_ENABLED __HAL_RCC_GPIOA_IS_CLK_ENABLED +#define __GPIOA_IS_CLK_DISABLED __HAL_RCC_GPIOA_IS_CLK_DISABLED +#define __GPIOB_IS_CLK_ENABLED __HAL_RCC_GPIOB_IS_CLK_ENABLED +#define __GPIOB_IS_CLK_DISABLED __HAL_RCC_GPIOB_IS_CLK_DISABLED +#define __GPIOC_IS_CLK_ENABLED __HAL_RCC_GPIOC_IS_CLK_ENABLED +#define __GPIOC_IS_CLK_DISABLED __HAL_RCC_GPIOC_IS_CLK_DISABLED +#define __GPIOD_IS_CLK_ENABLED __HAL_RCC_GPIOD_IS_CLK_ENABLED +#define __GPIOD_IS_CLK_DISABLED __HAL_RCC_GPIOD_IS_CLK_DISABLED +#define __GPIOE_IS_CLK_ENABLED __HAL_RCC_GPIOE_IS_CLK_ENABLED +#define __GPIOE_IS_CLK_DISABLED __HAL_RCC_GPIOE_IS_CLK_DISABLED +#define __GPIOF_IS_CLK_ENABLED __HAL_RCC_GPIOF_IS_CLK_ENABLED +#define __GPIOF_IS_CLK_DISABLED __HAL_RCC_GPIOF_IS_CLK_DISABLED +#define __GPIOG_IS_CLK_ENABLED __HAL_RCC_GPIOG_IS_CLK_ENABLED +#define __GPIOG_IS_CLK_DISABLED __HAL_RCC_GPIOG_IS_CLK_DISABLED +#define __GPIOH_IS_CLK_ENABLED __HAL_RCC_GPIOH_IS_CLK_ENABLED +#define __GPIOH_IS_CLK_DISABLED __HAL_RCC_GPIOH_IS_CLK_DISABLED +#define __HRTIM1_IS_CLK_ENABLED __HAL_RCC_HRTIM1_IS_CLK_ENABLED +#define __HRTIM1_IS_CLK_DISABLED __HAL_RCC_HRTIM1_IS_CLK_DISABLED +#define __I2C1_IS_CLK_ENABLED __HAL_RCC_I2C1_IS_CLK_ENABLED +#define __I2C1_IS_CLK_DISABLED __HAL_RCC_I2C1_IS_CLK_DISABLED +#define __I2C2_IS_CLK_ENABLED __HAL_RCC_I2C2_IS_CLK_ENABLED +#define __I2C2_IS_CLK_DISABLED __HAL_RCC_I2C2_IS_CLK_DISABLED +#define __I2C3_IS_CLK_ENABLED __HAL_RCC_I2C3_IS_CLK_ENABLED +#define __I2C3_IS_CLK_DISABLED __HAL_RCC_I2C3_IS_CLK_DISABLED +#define __PWR_IS_CLK_ENABLED __HAL_RCC_PWR_IS_CLK_ENABLED +#define __PWR_IS_CLK_DISABLED __HAL_RCC_PWR_IS_CLK_DISABLED +#define __SYSCFG_IS_CLK_ENABLED __HAL_RCC_SYSCFG_IS_CLK_ENABLED +#define __SYSCFG_IS_CLK_DISABLED __HAL_RCC_SYSCFG_IS_CLK_DISABLED +#define __SPI1_IS_CLK_ENABLED __HAL_RCC_SPI1_IS_CLK_ENABLED +#define __SPI1_IS_CLK_DISABLED __HAL_RCC_SPI1_IS_CLK_DISABLED +#define __SPI2_IS_CLK_ENABLED __HAL_RCC_SPI2_IS_CLK_ENABLED +#define __SPI2_IS_CLK_DISABLED __HAL_RCC_SPI2_IS_CLK_DISABLED +#define __SPI3_IS_CLK_ENABLED __HAL_RCC_SPI3_IS_CLK_ENABLED +#define __SPI3_IS_CLK_DISABLED __HAL_RCC_SPI3_IS_CLK_DISABLED +#define __SPI4_IS_CLK_ENABLED __HAL_RCC_SPI4_IS_CLK_ENABLED +#define __SPI4_IS_CLK_DISABLED __HAL_RCC_SPI4_IS_CLK_DISABLED +#define __SDADC1_IS_CLK_ENABLED __HAL_RCC_SDADC1_IS_CLK_ENABLED +#define __SDADC1_IS_CLK_DISABLED __HAL_RCC_SDADC1_IS_CLK_DISABLED +#define __SDADC2_IS_CLK_ENABLED __HAL_RCC_SDADC2_IS_CLK_ENABLED +#define __SDADC2_IS_CLK_DISABLED __HAL_RCC_SDADC2_IS_CLK_DISABLED +#define __SDADC3_IS_CLK_ENABLED __HAL_RCC_SDADC3_IS_CLK_ENABLED +#define __SDADC3_IS_CLK_DISABLED __HAL_RCC_SDADC3_IS_CLK_DISABLED +#define __SRAM_IS_CLK_ENABLED __HAL_RCC_SRAM_IS_CLK_ENABLED +#define __SRAM_IS_CLK_DISABLED __HAL_RCC_SRAM_IS_CLK_DISABLED +#define __TIM1_IS_CLK_ENABLED __HAL_RCC_TIM1_IS_CLK_ENABLED +#define __TIM1_IS_CLK_DISABLED __HAL_RCC_TIM1_IS_CLK_DISABLED +#define __TIM2_IS_CLK_ENABLED __HAL_RCC_TIM2_IS_CLK_ENABLED +#define __TIM2_IS_CLK_DISABLED __HAL_RCC_TIM2_IS_CLK_DISABLED +#define __TIM3_IS_CLK_ENABLED __HAL_RCC_TIM3_IS_CLK_ENABLED +#define __TIM3_IS_CLK_DISABLED __HAL_RCC_TIM3_IS_CLK_DISABLED +#define __TIM4_IS_CLK_ENABLED __HAL_RCC_TIM4_IS_CLK_ENABLED +#define __TIM4_IS_CLK_DISABLED __HAL_RCC_TIM4_IS_CLK_DISABLED +#define __TIM5_IS_CLK_ENABLED __HAL_RCC_TIM5_IS_CLK_ENABLED +#define __TIM5_IS_CLK_DISABLED __HAL_RCC_TIM5_IS_CLK_DISABLED +#define __TIM6_IS_CLK_ENABLED __HAL_RCC_TIM6_IS_CLK_ENABLED +#define __TIM6_IS_CLK_DISABLED __HAL_RCC_TIM6_IS_CLK_DISABLED +#define __TIM7_IS_CLK_ENABLED __HAL_RCC_TIM7_IS_CLK_ENABLED +#define __TIM7_IS_CLK_DISABLED __HAL_RCC_TIM7_IS_CLK_DISABLED +#define __TIM8_IS_CLK_ENABLED __HAL_RCC_TIM8_IS_CLK_ENABLED +#define __TIM8_IS_CLK_DISABLED __HAL_RCC_TIM8_IS_CLK_DISABLED +#define __TIM12_IS_CLK_ENABLED __HAL_RCC_TIM12_IS_CLK_ENABLED +#define __TIM12_IS_CLK_DISABLED __HAL_RCC_TIM12_IS_CLK_DISABLED +#define __TIM13_IS_CLK_ENABLED __HAL_RCC_TIM13_IS_CLK_ENABLED +#define __TIM13_IS_CLK_DISABLED __HAL_RCC_TIM13_IS_CLK_DISABLED +#define __TIM14_IS_CLK_ENABLED __HAL_RCC_TIM14_IS_CLK_ENABLED +#define __TIM14_IS_CLK_DISABLED __HAL_RCC_TIM14_IS_CLK_DISABLED +#define __TIM15_IS_CLK_ENABLED __HAL_RCC_TIM15_IS_CLK_ENABLED +#define __TIM15_IS_CLK_DISABLED __HAL_RCC_TIM15_IS_CLK_DISABLED +#define __TIM16_IS_CLK_ENABLED __HAL_RCC_TIM16_IS_CLK_ENABLED +#define __TIM16_IS_CLK_DISABLED __HAL_RCC_TIM16_IS_CLK_DISABLED +#define __TIM17_IS_CLK_ENABLED __HAL_RCC_TIM17_IS_CLK_ENABLED +#define __TIM17_IS_CLK_DISABLED __HAL_RCC_TIM17_IS_CLK_DISABLED +#define __TIM18_IS_CLK_ENABLED __HAL_RCC_TIM18_IS_CLK_ENABLED +#define __TIM18_IS_CLK_DISABLED __HAL_RCC_TIM18_IS_CLK_DISABLED +#define __TIM19_IS_CLK_ENABLED __HAL_RCC_TIM19_IS_CLK_ENABLED +#define __TIM19_IS_CLK_DISABLED __HAL_RCC_TIM19_IS_CLK_DISABLED +#define __TIM20_IS_CLK_ENABLED __HAL_RCC_TIM20_IS_CLK_ENABLED +#define __TIM20_IS_CLK_DISABLED __HAL_RCC_TIM20_IS_CLK_DISABLED +#define __TSC_IS_CLK_ENABLED __HAL_RCC_TSC_IS_CLK_ENABLED +#define __TSC_IS_CLK_DISABLED __HAL_RCC_TSC_IS_CLK_DISABLED +#define __UART4_IS_CLK_ENABLED __HAL_RCC_UART4_IS_CLK_ENABLED +#define __UART4_IS_CLK_DISABLED __HAL_RCC_UART4_IS_CLK_DISABLED +#define __UART5_IS_CLK_ENABLED __HAL_RCC_UART5_IS_CLK_ENABLED +#define __UART5_IS_CLK_DISABLED __HAL_RCC_UART5_IS_CLK_DISABLED +#define __USART1_IS_CLK_ENABLED __HAL_RCC_USART1_IS_CLK_ENABLED +#define __USART1_IS_CLK_DISABLED __HAL_RCC_USART1_IS_CLK_DISABLED +#define __USART2_IS_CLK_ENABLED __HAL_RCC_USART2_IS_CLK_ENABLED +#define __USART2_IS_CLK_DISABLED __HAL_RCC_USART2_IS_CLK_DISABLED +#define __USART3_IS_CLK_ENABLED __HAL_RCC_USART3_IS_CLK_ENABLED +#define __USART3_IS_CLK_DISABLED __HAL_RCC_USART3_IS_CLK_DISABLED +#define __USB_IS_CLK_ENABLED __HAL_RCC_USB_IS_CLK_ENABLED +#define __USB_IS_CLK_DISABLED __HAL_RCC_USB_IS_CLK_DISABLED +#define __WWDG_IS_CLK_ENABLED __HAL_RCC_WWDG_IS_CLK_ENABLED +#define __WWDG_IS_CLK_DISABLED __HAL_RCC_WWDG_IS_CLK_DISABLED + +#if defined(STM32F4) +#define __HAL_RCC_SDMMC1_FORCE_RESET __HAL_RCC_SDIO_FORCE_RESET +#define __HAL_RCC_SDMMC1_RELEASE_RESET __HAL_RCC_SDIO_RELEASE_RESET +#define __HAL_RCC_SDMMC1_CLK_SLEEP_ENABLE __HAL_RCC_SDIO_CLK_SLEEP_ENABLE +#define __HAL_RCC_SDMMC1_CLK_SLEEP_DISABLE __HAL_RCC_SDIO_CLK_SLEEP_DISABLE +#define __HAL_RCC_SDMMC1_CLK_ENABLE __HAL_RCC_SDIO_CLK_ENABLE +#define __HAL_RCC_SDMMC1_CLK_DISABLE __HAL_RCC_SDIO_CLK_DISABLE +#define __HAL_RCC_SDMMC1_IS_CLK_ENABLED __HAL_RCC_SDIO_IS_CLK_ENABLED +#define __HAL_RCC_SDMMC1_IS_CLK_DISABLED __HAL_RCC_SDIO_IS_CLK_DISABLED +#define Sdmmc1ClockSelection SdioClockSelection +#define RCC_PERIPHCLK_SDMMC1 RCC_PERIPHCLK_SDIO +#define RCC_SDMMC1CLKSOURCE_CLK48 RCC_SDIOCLKSOURCE_CK48 +#define RCC_SDMMC1CLKSOURCE_SYSCLK RCC_SDIOCLKSOURCE_SYSCLK +#define __HAL_RCC_SDMMC1_CONFIG __HAL_RCC_SDIO_CONFIG +#define __HAL_RCC_GET_SDMMC1_SOURCE __HAL_RCC_GET_SDIO_SOURCE +#endif + +#if defined(STM32F7) || defined(STM32L4) +#define __HAL_RCC_SDIO_FORCE_RESET __HAL_RCC_SDMMC1_FORCE_RESET +#define __HAL_RCC_SDIO_RELEASE_RESET __HAL_RCC_SDMMC1_RELEASE_RESET +#define __HAL_RCC_SDIO_CLK_SLEEP_ENABLE __HAL_RCC_SDMMC1_CLK_SLEEP_ENABLE +#define __HAL_RCC_SDIO_CLK_SLEEP_DISABLE __HAL_RCC_SDMMC1_CLK_SLEEP_DISABLE +#define __HAL_RCC_SDIO_CLK_ENABLE __HAL_RCC_SDMMC1_CLK_ENABLE +#define __HAL_RCC_SDIO_CLK_DISABLE __HAL_RCC_SDMMC1_CLK_DISABLE +#define __HAL_RCC_SDIO_IS_CLK_ENABLED __HAL_RCC_SDMMC1_IS_CLK_ENABLED +#define __HAL_RCC_SDIO_IS_CLK_DISABLED __HAL_RCC_SDMMC1_IS_CLK_DISABLED +#define SdioClockSelection Sdmmc1ClockSelection +#define RCC_PERIPHCLK_SDIO RCC_PERIPHCLK_SDMMC1 +#define __HAL_RCC_SDIO_CONFIG __HAL_RCC_SDMMC1_CONFIG +#define __HAL_RCC_GET_SDIO_SOURCE __HAL_RCC_GET_SDMMC1_SOURCE +#endif + +#if defined(STM32F7) +#define RCC_SDIOCLKSOURCE_CLK48 RCC_SDMMC1CLKSOURCE_CLK48 +#define RCC_SDIOCLKSOURCE_SYSCLK RCC_SDMMC1CLKSOURCE_SYSCLK +#endif + +#if defined(STM32H7) +#define __HAL_RCC_USB_OTG_HS_CLK_ENABLE() __HAL_RCC_USB1_OTG_HS_CLK_ENABLE() +#define __HAL_RCC_USB_OTG_HS_ULPI_CLK_ENABLE() __HAL_RCC_USB1_OTG_HS_ULPI_CLK_ENABLE() +#define __HAL_RCC_USB_OTG_HS_CLK_DISABLE() __HAL_RCC_USB1_OTG_HS_CLK_DISABLE() +#define __HAL_RCC_USB_OTG_HS_ULPI_CLK_DISABLE() __HAL_RCC_USB1_OTG_HS_ULPI_CLK_DISABLE() +#define __HAL_RCC_USB_OTG_HS_FORCE_RESET() __HAL_RCC_USB1_OTG_HS_FORCE_RESET() +#define __HAL_RCC_USB_OTG_HS_RELEASE_RESET() __HAL_RCC_USB1_OTG_HS_RELEASE_RESET() +#define __HAL_RCC_USB_OTG_HS_CLK_SLEEP_ENABLE() __HAL_RCC_USB1_OTG_HS_CLK_SLEEP_ENABLE() +#define __HAL_RCC_USB_OTG_HS_ULPI_CLK_SLEEP_ENABLE() __HAL_RCC_USB1_OTG_HS_ULPI_CLK_SLEEP_ENABLE() +#define __HAL_RCC_USB_OTG_HS_CLK_SLEEP_DISABLE() __HAL_RCC_USB1_OTG_HS_CLK_SLEEP_DISABLE() +#define __HAL_RCC_USB_OTG_HS_ULPI_CLK_SLEEP_DISABLE() __HAL_RCC_USB1_OTG_HS_ULPI_CLK_SLEEP_DISABLE() + +#define __HAL_RCC_USB_OTG_FS_CLK_ENABLE() __HAL_RCC_USB2_OTG_FS_CLK_ENABLE() +#define __HAL_RCC_USB_OTG_FS_ULPI_CLK_ENABLE() __HAL_RCC_USB2_OTG_FS_ULPI_CLK_ENABLE() +#define __HAL_RCC_USB_OTG_FS_CLK_DISABLE() __HAL_RCC_USB2_OTG_FS_CLK_DISABLE() +#define __HAL_RCC_USB_OTG_FS_ULPI_CLK_DISABLE() __HAL_RCC_USB2_OTG_FS_ULPI_CLK_DISABLE() +#define __HAL_RCC_USB_OTG_FS_FORCE_RESET() __HAL_RCC_USB2_OTG_FS_FORCE_RESET() +#define __HAL_RCC_USB_OTG_FS_RELEASE_RESET() __HAL_RCC_USB2_OTG_FS_RELEASE_RESET() +#define __HAL_RCC_USB_OTG_FS_CLK_SLEEP_ENABLE() __HAL_RCC_USB2_OTG_FS_CLK_SLEEP_ENABLE() +#define __HAL_RCC_USB_OTG_FS_ULPI_CLK_SLEEP_ENABLE() __HAL_RCC_USB2_OTG_FS_ULPI_CLK_SLEEP_ENABLE() +#define __HAL_RCC_USB_OTG_FS_CLK_SLEEP_DISABLE() __HAL_RCC_USB2_OTG_FS_CLK_SLEEP_DISABLE() +#define __HAL_RCC_USB_OTG_FS_ULPI_CLK_SLEEP_DISABLE() __HAL_RCC_USB2_OTG_FS_ULPI_CLK_SLEEP_DISABLE() +#endif + +#define __HAL_RCC_I2SCLK __HAL_RCC_I2S_CONFIG +#define __HAL_RCC_I2SCLK_CONFIG __HAL_RCC_I2S_CONFIG + +#define __RCC_PLLSRC RCC_GET_PLL_OSCSOURCE + +#define IS_RCC_MSIRANGE IS_RCC_MSI_CLOCK_RANGE +#define IS_RCC_RTCCLK_SOURCE IS_RCC_RTCCLKSOURCE +#define IS_RCC_SYSCLK_DIV IS_RCC_HCLK +#define IS_RCC_HCLK_DIV IS_RCC_PCLK +#define IS_RCC_PERIPHCLK IS_RCC_PERIPHCLOCK + +#define RCC_IT_HSI14 RCC_IT_HSI14RDY + +#define RCC_IT_CSSLSE RCC_IT_LSECSS +#define RCC_IT_CSSHSE RCC_IT_CSS + +#define RCC_PLLMUL_3 RCC_PLL_MUL3 +#define RCC_PLLMUL_4 RCC_PLL_MUL4 +#define RCC_PLLMUL_6 RCC_PLL_MUL6 +#define RCC_PLLMUL_8 RCC_PLL_MUL8 +#define RCC_PLLMUL_12 RCC_PLL_MUL12 +#define RCC_PLLMUL_16 RCC_PLL_MUL16 +#define RCC_PLLMUL_24 RCC_PLL_MUL24 +#define RCC_PLLMUL_32 RCC_PLL_MUL32 +#define RCC_PLLMUL_48 RCC_PLL_MUL48 + +#define RCC_PLLDIV_2 RCC_PLL_DIV2 +#define RCC_PLLDIV_3 RCC_PLL_DIV3 +#define RCC_PLLDIV_4 RCC_PLL_DIV4 + +#define IS_RCC_MCOSOURCE IS_RCC_MCO1SOURCE +#define __HAL_RCC_MCO_CONFIG __HAL_RCC_MCO1_CONFIG +#define RCC_MCO_NODIV RCC_MCODIV_1 +#define RCC_MCO_DIV1 RCC_MCODIV_1 +#define RCC_MCO_DIV2 RCC_MCODIV_2 +#define RCC_MCO_DIV4 RCC_MCODIV_4 +#define RCC_MCO_DIV8 RCC_MCODIV_8 +#define RCC_MCO_DIV16 RCC_MCODIV_16 +#define RCC_MCO_DIV32 RCC_MCODIV_32 +#define RCC_MCO_DIV64 RCC_MCODIV_64 +#define RCC_MCO_DIV128 RCC_MCODIV_128 +#define RCC_MCOSOURCE_NONE RCC_MCO1SOURCE_NOCLOCK +#define RCC_MCOSOURCE_LSI RCC_MCO1SOURCE_LSI +#define RCC_MCOSOURCE_LSE RCC_MCO1SOURCE_LSE +#define RCC_MCOSOURCE_SYSCLK RCC_MCO1SOURCE_SYSCLK +#define RCC_MCOSOURCE_HSI RCC_MCO1SOURCE_HSI +#define RCC_MCOSOURCE_HSI14 RCC_MCO1SOURCE_HSI14 +#define RCC_MCOSOURCE_HSI48 RCC_MCO1SOURCE_HSI48 +#define RCC_MCOSOURCE_HSE RCC_MCO1SOURCE_HSE +#define RCC_MCOSOURCE_PLLCLK_DIV1 RCC_MCO1SOURCE_PLLCLK +#define RCC_MCOSOURCE_PLLCLK_NODIV RCC_MCO1SOURCE_PLLCLK +#define RCC_MCOSOURCE_PLLCLK_DIV2 RCC_MCO1SOURCE_PLLCLK_DIV2 + +#if defined(STM32L4) +#define RCC_RTCCLKSOURCE_NO_CLK RCC_RTCCLKSOURCE_NONE +#elif defined(STM32WB) || defined(STM32G0) +#else +#define RCC_RTCCLKSOURCE_NONE RCC_RTCCLKSOURCE_NO_CLK +#endif + +#define RCC_USBCLK_PLLSAI1 RCC_USBCLKSOURCE_PLLSAI1 +#define RCC_USBCLK_PLL RCC_USBCLKSOURCE_PLL +#define RCC_USBCLK_MSI RCC_USBCLKSOURCE_MSI +#define RCC_USBCLKSOURCE_PLLCLK RCC_USBCLKSOURCE_PLL +#define RCC_USBPLLCLK_DIV1 RCC_USBCLKSOURCE_PLL +#define RCC_USBPLLCLK_DIV1_5 RCC_USBCLKSOURCE_PLL_DIV1_5 +#define RCC_USBPLLCLK_DIV2 RCC_USBCLKSOURCE_PLL_DIV2 +#define RCC_USBPLLCLK_DIV3 RCC_USBCLKSOURCE_PLL_DIV3 + +#define HSION_BitNumber RCC_HSION_BIT_NUMBER +#define HSION_BITNUMBER RCC_HSION_BIT_NUMBER +#define HSEON_BitNumber RCC_HSEON_BIT_NUMBER +#define HSEON_BITNUMBER RCC_HSEON_BIT_NUMBER +#define MSION_BITNUMBER RCC_MSION_BIT_NUMBER +#define CSSON_BitNumber RCC_CSSON_BIT_NUMBER +#define CSSON_BITNUMBER RCC_CSSON_BIT_NUMBER +#define PLLON_BitNumber RCC_PLLON_BIT_NUMBER +#define PLLON_BITNUMBER RCC_PLLON_BIT_NUMBER +#define PLLI2SON_BitNumber RCC_PLLI2SON_BIT_NUMBER +#define I2SSRC_BitNumber RCC_I2SSRC_BIT_NUMBER +#define RTCEN_BitNumber RCC_RTCEN_BIT_NUMBER +#define RTCEN_BITNUMBER RCC_RTCEN_BIT_NUMBER +#define BDRST_BitNumber RCC_BDRST_BIT_NUMBER +#define BDRST_BITNUMBER RCC_BDRST_BIT_NUMBER +#define RTCRST_BITNUMBER RCC_RTCRST_BIT_NUMBER +#define LSION_BitNumber RCC_LSION_BIT_NUMBER +#define LSION_BITNUMBER RCC_LSION_BIT_NUMBER +#define LSEON_BitNumber RCC_LSEON_BIT_NUMBER +#define LSEON_BITNUMBER RCC_LSEON_BIT_NUMBER +#define LSEBYP_BITNUMBER RCC_LSEBYP_BIT_NUMBER +#define PLLSAION_BitNumber RCC_PLLSAION_BIT_NUMBER +#define TIMPRE_BitNumber RCC_TIMPRE_BIT_NUMBER +#define RMVF_BitNumber RCC_RMVF_BIT_NUMBER +#define RMVF_BITNUMBER RCC_RMVF_BIT_NUMBER +#define RCC_CR2_HSI14TRIM_BitNumber RCC_HSI14TRIM_BIT_NUMBER +#define CR_BYTE2_ADDRESS RCC_CR_BYTE2_ADDRESS +#define CIR_BYTE1_ADDRESS RCC_CIR_BYTE1_ADDRESS +#define CIR_BYTE2_ADDRESS RCC_CIR_BYTE2_ADDRESS +#define BDCR_BYTE0_ADDRESS RCC_BDCR_BYTE0_ADDRESS +#define DBP_TIMEOUT_VALUE RCC_DBP_TIMEOUT_VALUE +#define LSE_TIMEOUT_VALUE RCC_LSE_TIMEOUT_VALUE + +#define CR_HSION_BB RCC_CR_HSION_BB +#define CR_CSSON_BB RCC_CR_CSSON_BB +#define CR_PLLON_BB RCC_CR_PLLON_BB +#define CR_PLLI2SON_BB RCC_CR_PLLI2SON_BB +#define CR_MSION_BB RCC_CR_MSION_BB +#define CSR_LSION_BB RCC_CSR_LSION_BB +#define CSR_LSEON_BB RCC_CSR_LSEON_BB +#define CSR_LSEBYP_BB RCC_CSR_LSEBYP_BB +#define CSR_RTCEN_BB RCC_CSR_RTCEN_BB +#define CSR_RTCRST_BB RCC_CSR_RTCRST_BB +#define CFGR_I2SSRC_BB RCC_CFGR_I2SSRC_BB +#define BDCR_RTCEN_BB RCC_BDCR_RTCEN_BB +#define BDCR_BDRST_BB RCC_BDCR_BDRST_BB +#define CR_HSEON_BB RCC_CR_HSEON_BB +#define CSR_RMVF_BB RCC_CSR_RMVF_BB +#define CR_PLLSAION_BB RCC_CR_PLLSAION_BB +#define DCKCFGR_TIMPRE_BB RCC_DCKCFGR_TIMPRE_BB + +#define __HAL_RCC_CRS_ENABLE_FREQ_ERROR_COUNTER __HAL_RCC_CRS_FREQ_ERROR_COUNTER_ENABLE +#define __HAL_RCC_CRS_DISABLE_FREQ_ERROR_COUNTER __HAL_RCC_CRS_FREQ_ERROR_COUNTER_DISABLE +#define __HAL_RCC_CRS_ENABLE_AUTOMATIC_CALIB __HAL_RCC_CRS_AUTOMATIC_CALIB_ENABLE +#define __HAL_RCC_CRS_DISABLE_AUTOMATIC_CALIB __HAL_RCC_CRS_AUTOMATIC_CALIB_DISABLE +#define __HAL_RCC_CRS_CALCULATE_RELOADVALUE __HAL_RCC_CRS_RELOADVALUE_CALCULATE + +#define __HAL_RCC_GET_IT_SOURCE __HAL_RCC_GET_IT + +#define RCC_CRS_SYNCWARM RCC_CRS_SYNCWARN +#define RCC_CRS_TRIMOV RCC_CRS_TRIMOVF + +#define RCC_PERIPHCLK_CK48 RCC_PERIPHCLK_CLK48 +#define RCC_CK48CLKSOURCE_PLLQ RCC_CLK48CLKSOURCE_PLLQ +#define RCC_CK48CLKSOURCE_PLLSAIP RCC_CLK48CLKSOURCE_PLLSAIP +#define RCC_CK48CLKSOURCE_PLLI2SQ RCC_CLK48CLKSOURCE_PLLI2SQ +#define IS_RCC_CK48CLKSOURCE IS_RCC_CLK48CLKSOURCE +#define RCC_SDIOCLKSOURCE_CK48 RCC_SDIOCLKSOURCE_CLK48 + +#define __HAL_RCC_DFSDM_CLK_ENABLE __HAL_RCC_DFSDM1_CLK_ENABLE +#define __HAL_RCC_DFSDM_CLK_DISABLE __HAL_RCC_DFSDM1_CLK_DISABLE +#define __HAL_RCC_DFSDM_IS_CLK_ENABLED __HAL_RCC_DFSDM1_IS_CLK_ENABLED +#define __HAL_RCC_DFSDM_IS_CLK_DISABLED __HAL_RCC_DFSDM1_IS_CLK_DISABLED +#define __HAL_RCC_DFSDM_FORCE_RESET __HAL_RCC_DFSDM1_FORCE_RESET +#define __HAL_RCC_DFSDM_RELEASE_RESET __HAL_RCC_DFSDM1_RELEASE_RESET +#define __HAL_RCC_DFSDM_CLK_SLEEP_ENABLE __HAL_RCC_DFSDM1_CLK_SLEEP_ENABLE +#define __HAL_RCC_DFSDM_CLK_SLEEP_DISABLE __HAL_RCC_DFSDM1_CLK_SLEEP_DISABLE +#define __HAL_RCC_DFSDM_IS_CLK_SLEEP_ENABLED __HAL_RCC_DFSDM1_IS_CLK_SLEEP_ENABLED +#define __HAL_RCC_DFSDM_IS_CLK_SLEEP_DISABLED __HAL_RCC_DFSDM1_IS_CLK_SLEEP_DISABLED +#define DfsdmClockSelection Dfsdm1ClockSelection +#define RCC_PERIPHCLK_DFSDM RCC_PERIPHCLK_DFSDM1 +#define RCC_DFSDMCLKSOURCE_PCLK RCC_DFSDM1CLKSOURCE_PCLK2 +#define RCC_DFSDMCLKSOURCE_SYSCLK RCC_DFSDM1CLKSOURCE_SYSCLK +#define __HAL_RCC_DFSDM_CONFIG __HAL_RCC_DFSDM1_CONFIG +#define __HAL_RCC_GET_DFSDM_SOURCE __HAL_RCC_GET_DFSDM1_SOURCE +#define RCC_DFSDM1CLKSOURCE_PCLK RCC_DFSDM1CLKSOURCE_PCLK2 +#define RCC_SWPMI1CLKSOURCE_PCLK RCC_SWPMI1CLKSOURCE_PCLK1 +#define RCC_LPTIM1CLKSOURCE_PCLK RCC_LPTIM1CLKSOURCE_PCLK1 +#define RCC_LPTIM2CLKSOURCE_PCLK RCC_LPTIM2CLKSOURCE_PCLK1 + +#define RCC_DFSDM1AUDIOCLKSOURCE_I2SAPB1 RCC_DFSDM1AUDIOCLKSOURCE_I2S1 +#define RCC_DFSDM1AUDIOCLKSOURCE_I2SAPB2 RCC_DFSDM1AUDIOCLKSOURCE_I2S2 +#define RCC_DFSDM2AUDIOCLKSOURCE_I2SAPB1 RCC_DFSDM2AUDIOCLKSOURCE_I2S1 +#define RCC_DFSDM2AUDIOCLKSOURCE_I2SAPB2 RCC_DFSDM2AUDIOCLKSOURCE_I2S2 +#define RCC_DFSDM1CLKSOURCE_APB2 RCC_DFSDM1CLKSOURCE_PCLK2 +#define RCC_DFSDM2CLKSOURCE_APB2 RCC_DFSDM2CLKSOURCE_PCLK2 +#define RCC_FMPI2C1CLKSOURCE_APB RCC_FMPI2C1CLKSOURCE_PCLK1 + +/** + * @} + */ + +/** @defgroup HAL_RNG_Aliased_Macros HAL RNG Aliased Macros maintained for legacy purpose + * @{ + */ +#define HAL_RNG_ReadyCallback(__HANDLE__) HAL_RNG_ReadyDataCallback((__HANDLE__), uint32_t random32bit) + +/** + * @} + */ + +/** @defgroup HAL_RTC_Aliased_Macros HAL RTC Aliased Macros maintained for legacy purpose + * @{ + */ +#if defined (STM32G0) +#else +#define __HAL_RTC_CLEAR_FLAG __HAL_RTC_EXTI_CLEAR_FLAG +#endif +#define __HAL_RTC_DISABLE_IT __HAL_RTC_EXTI_DISABLE_IT +#define __HAL_RTC_ENABLE_IT __HAL_RTC_EXTI_ENABLE_IT + +#if defined (STM32F1) +#define __HAL_RTC_EXTI_CLEAR_FLAG(RTC_EXTI_LINE_ALARM_EVENT) __HAL_RTC_ALARM_EXTI_CLEAR_FLAG() + +#define __HAL_RTC_EXTI_ENABLE_IT(RTC_EXTI_LINE_ALARM_EVENT) __HAL_RTC_ALARM_EXTI_ENABLE_IT() + +#define __HAL_RTC_EXTI_DISABLE_IT(RTC_EXTI_LINE_ALARM_EVENT) __HAL_RTC_ALARM_EXTI_DISABLE_IT() + +#define __HAL_RTC_EXTI_GET_FLAG(RTC_EXTI_LINE_ALARM_EVENT) __HAL_RTC_ALARM_EXTI_GET_FLAG() + +#define __HAL_RTC_EXTI_GENERATE_SWIT(RTC_EXTI_LINE_ALARM_EVENT) __HAL_RTC_ALARM_EXTI_GENERATE_SWIT() +#else +#define __HAL_RTC_EXTI_CLEAR_FLAG(__EXTI_LINE__) (((__EXTI_LINE__) == RTC_EXTI_LINE_ALARM_EVENT) ? __HAL_RTC_ALARM_EXTI_CLEAR_FLAG() : \ + (((__EXTI_LINE__) == RTC_EXTI_LINE_WAKEUPTIMER_EVENT) ? __HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG() : \ + __HAL_RTC_TAMPER_TIMESTAMP_EXTI_CLEAR_FLAG())) +#define __HAL_RTC_EXTI_ENABLE_IT(__EXTI_LINE__) (((__EXTI_LINE__) == RTC_EXTI_LINE_ALARM_EVENT) ? __HAL_RTC_ALARM_EXTI_ENABLE_IT() : \ + (((__EXTI_LINE__) == RTC_EXTI_LINE_WAKEUPTIMER_EVENT) ? __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_IT() : \ + __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_IT())) +#define __HAL_RTC_EXTI_DISABLE_IT(__EXTI_LINE__) (((__EXTI_LINE__) == RTC_EXTI_LINE_ALARM_EVENT) ? __HAL_RTC_ALARM_EXTI_DISABLE_IT() : \ + (((__EXTI_LINE__) == RTC_EXTI_LINE_WAKEUPTIMER_EVENT) ? __HAL_RTC_WAKEUPTIMER_EXTI_DISABLE_IT() : \ + __HAL_RTC_TAMPER_TIMESTAMP_EXTI_DISABLE_IT())) +#define __HAL_RTC_EXTI_GET_FLAG(__EXTI_LINE__) (((__EXTI_LINE__) == RTC_EXTI_LINE_ALARM_EVENT) ? __HAL_RTC_ALARM_EXTI_GET_FLAG() : \ + (((__EXTI_LINE__) == RTC_EXTI_LINE_WAKEUPTIMER_EVENT) ? __HAL_RTC_WAKEUPTIMER_EXTI_GET_FLAG() : \ + __HAL_RTC_TAMPER_TIMESTAMP_EXTI_GET_FLAG())) +#define __HAL_RTC_EXTI_GENERATE_SWIT(__EXTI_LINE__) (((__EXTI_LINE__) == RTC_EXTI_LINE_ALARM_EVENT) ? __HAL_RTC_ALARM_EXTI_GENERATE_SWIT() : \ + (((__EXTI_LINE__) == RTC_EXTI_LINE_WAKEUPTIMER_EVENT) ? __HAL_RTC_WAKEUPTIMER_EXTI_GENERATE_SWIT() : \ + __HAL_RTC_TAMPER_TIMESTAMP_EXTI_GENERATE_SWIT())) +#endif /* STM32F1 */ + +#define IS_ALARM IS_RTC_ALARM +#define IS_ALARM_MASK IS_RTC_ALARM_MASK +#define IS_TAMPER IS_RTC_TAMPER +#define IS_TAMPER_ERASE_MODE IS_RTC_TAMPER_ERASE_MODE +#define IS_TAMPER_FILTER IS_RTC_TAMPER_FILTER +#define IS_TAMPER_INTERRUPT IS_RTC_TAMPER_INTERRUPT +#define IS_TAMPER_MASKFLAG_STATE IS_RTC_TAMPER_MASKFLAG_STATE +#define IS_TAMPER_PRECHARGE_DURATION IS_RTC_TAMPER_PRECHARGE_DURATION +#define IS_TAMPER_PULLUP_STATE IS_RTC_TAMPER_PULLUP_STATE +#define IS_TAMPER_SAMPLING_FREQ IS_RTC_TAMPER_SAMPLING_FREQ +#define IS_TAMPER_TIMESTAMPONTAMPER_DETECTION IS_RTC_TAMPER_TIMESTAMPONTAMPER_DETECTION +#define IS_TAMPER_TRIGGER IS_RTC_TAMPER_TRIGGER +#define IS_WAKEUP_CLOCK IS_RTC_WAKEUP_CLOCK +#define IS_WAKEUP_COUNTER IS_RTC_WAKEUP_COUNTER + +#define __RTC_WRITEPROTECTION_ENABLE __HAL_RTC_WRITEPROTECTION_ENABLE +#define __RTC_WRITEPROTECTION_DISABLE __HAL_RTC_WRITEPROTECTION_DISABLE + +/** + * @} + */ + +/** @defgroup HAL_SD_Aliased_Macros HAL SD Aliased Macros maintained for legacy purpose + * @{ + */ + +#define SD_OCR_CID_CSD_OVERWRIETE SD_OCR_CID_CSD_OVERWRITE +#define SD_CMD_SD_APP_STAUS SD_CMD_SD_APP_STATUS + +#if defined(STM32F4) || defined(STM32F2) +#define SD_SDMMC_DISABLED SD_SDIO_DISABLED +#define SD_SDMMC_FUNCTION_BUSY SD_SDIO_FUNCTION_BUSY +#define SD_SDMMC_FUNCTION_FAILED SD_SDIO_FUNCTION_FAILED +#define SD_SDMMC_UNKNOWN_FUNCTION SD_SDIO_UNKNOWN_FUNCTION +#define SD_CMD_SDMMC_SEN_OP_COND SD_CMD_SDIO_SEN_OP_COND +#define SD_CMD_SDMMC_RW_DIRECT SD_CMD_SDIO_RW_DIRECT +#define SD_CMD_SDMMC_RW_EXTENDED SD_CMD_SDIO_RW_EXTENDED +#define __HAL_SD_SDMMC_ENABLE __HAL_SD_SDIO_ENABLE +#define __HAL_SD_SDMMC_DISABLE __HAL_SD_SDIO_DISABLE +#define __HAL_SD_SDMMC_DMA_ENABLE __HAL_SD_SDIO_DMA_ENABLE +#define __HAL_SD_SDMMC_DMA_DISABLE __HAL_SD_SDIO_DMA_DISABL +#define __HAL_SD_SDMMC_ENABLE_IT __HAL_SD_SDIO_ENABLE_IT +#define __HAL_SD_SDMMC_DISABLE_IT __HAL_SD_SDIO_DISABLE_IT +#define __HAL_SD_SDMMC_GET_FLAG __HAL_SD_SDIO_GET_FLAG +#define __HAL_SD_SDMMC_CLEAR_FLAG __HAL_SD_SDIO_CLEAR_FLAG +#define __HAL_SD_SDMMC_GET_IT __HAL_SD_SDIO_GET_IT +#define __HAL_SD_SDMMC_CLEAR_IT __HAL_SD_SDIO_CLEAR_IT +#define SDMMC_STATIC_FLAGS SDIO_STATIC_FLAGS +#define SDMMC_CMD0TIMEOUT SDIO_CMD0TIMEOUT +#define SD_SDMMC_SEND_IF_COND SD_SDIO_SEND_IF_COND +/* alias CMSIS */ +#define SDMMC1_IRQn SDIO_IRQn +#define SDMMC1_IRQHandler SDIO_IRQHandler +#endif + +#if defined(STM32F7) || defined(STM32L4) +#define SD_SDIO_DISABLED SD_SDMMC_DISABLED +#define SD_SDIO_FUNCTION_BUSY SD_SDMMC_FUNCTION_BUSY +#define SD_SDIO_FUNCTION_FAILED SD_SDMMC_FUNCTION_FAILED +#define SD_SDIO_UNKNOWN_FUNCTION SD_SDMMC_UNKNOWN_FUNCTION +#define SD_CMD_SDIO_SEN_OP_COND SD_CMD_SDMMC_SEN_OP_COND +#define SD_CMD_SDIO_RW_DIRECT SD_CMD_SDMMC_RW_DIRECT +#define SD_CMD_SDIO_RW_EXTENDED SD_CMD_SDMMC_RW_EXTENDED +#define __HAL_SD_SDIO_ENABLE __HAL_SD_SDMMC_ENABLE +#define __HAL_SD_SDIO_DISABLE __HAL_SD_SDMMC_DISABLE +#define __HAL_SD_SDIO_DMA_ENABLE __HAL_SD_SDMMC_DMA_ENABLE +#define __HAL_SD_SDIO_DMA_DISABL __HAL_SD_SDMMC_DMA_DISABLE +#define __HAL_SD_SDIO_ENABLE_IT __HAL_SD_SDMMC_ENABLE_IT +#define __HAL_SD_SDIO_DISABLE_IT __HAL_SD_SDMMC_DISABLE_IT +#define __HAL_SD_SDIO_GET_FLAG __HAL_SD_SDMMC_GET_FLAG +#define __HAL_SD_SDIO_CLEAR_FLAG __HAL_SD_SDMMC_CLEAR_FLAG +#define __HAL_SD_SDIO_GET_IT __HAL_SD_SDMMC_GET_IT +#define __HAL_SD_SDIO_CLEAR_IT __HAL_SD_SDMMC_CLEAR_IT +#define SDIO_STATIC_FLAGS SDMMC_STATIC_FLAGS +#define SDIO_CMD0TIMEOUT SDMMC_CMD0TIMEOUT +#define SD_SDIO_SEND_IF_COND SD_SDMMC_SEND_IF_COND +/* alias CMSIS for compatibilities */ +#define SDIO_IRQn SDMMC1_IRQn +#define SDIO_IRQHandler SDMMC1_IRQHandler +#endif + +#if defined(STM32F7) || defined(STM32F4) || defined(STM32F2) +#define HAL_SD_CardCIDTypedef HAL_SD_CardCIDTypeDef +#define HAL_SD_CardCSDTypedef HAL_SD_CardCSDTypeDef +#define HAL_SD_CardStatusTypedef HAL_SD_CardStatusTypeDef +#define HAL_SD_CardStateTypedef HAL_SD_CardStateTypeDef +#endif + +#if defined(STM32H7) +#define HAL_MMCEx_Read_DMADoubleBuffer0CpltCallback HAL_MMCEx_Read_DMADoubleBuf0CpltCallback +#define HAL_MMCEx_Read_DMADoubleBuffer1CpltCallback HAL_MMCEx_Read_DMADoubleBuf1CpltCallback +#define HAL_MMCEx_Write_DMADoubleBuffer0CpltCallback HAL_MMCEx_Write_DMADoubleBuf0CpltCallback +#define HAL_MMCEx_Write_DMADoubleBuffer1CpltCallback HAL_MMCEx_Write_DMADoubleBuf1CpltCallback +#define HAL_SDEx_Read_DMADoubleBuffer0CpltCallback HAL_SDEx_Read_DMADoubleBuf0CpltCallback +#define HAL_SDEx_Read_DMADoubleBuffer1CpltCallback HAL_SDEx_Read_DMADoubleBuf1CpltCallback +#define HAL_SDEx_Write_DMADoubleBuffer0CpltCallback HAL_SDEx_Write_DMADoubleBuf0CpltCallback +#define HAL_SDEx_Write_DMADoubleBuffer1CpltCallback HAL_SDEx_Write_DMADoubleBuf1CpltCallback +#endif +/** + * @} + */ + +/** @defgroup HAL_SMARTCARD_Aliased_Macros HAL SMARTCARD Aliased Macros maintained for legacy purpose + * @{ + */ + +#define __SMARTCARD_ENABLE_IT __HAL_SMARTCARD_ENABLE_IT +#define __SMARTCARD_DISABLE_IT __HAL_SMARTCARD_DISABLE_IT +#define __SMARTCARD_ENABLE __HAL_SMARTCARD_ENABLE +#define __SMARTCARD_DISABLE __HAL_SMARTCARD_DISABLE +#define __SMARTCARD_DMA_REQUEST_ENABLE __HAL_SMARTCARD_DMA_REQUEST_ENABLE +#define __SMARTCARD_DMA_REQUEST_DISABLE __HAL_SMARTCARD_DMA_REQUEST_DISABLE + +#define __HAL_SMARTCARD_GETCLOCKSOURCE SMARTCARD_GETCLOCKSOURCE +#define __SMARTCARD_GETCLOCKSOURCE SMARTCARD_GETCLOCKSOURCE + +#define IS_SMARTCARD_ONEBIT_SAMPLING IS_SMARTCARD_ONE_BIT_SAMPLE + +/** + * @} + */ + +/** @defgroup HAL_SMBUS_Aliased_Macros HAL SMBUS Aliased Macros maintained for legacy purpose + * @{ + */ +#define __HAL_SMBUS_RESET_CR1 SMBUS_RESET_CR1 +#define __HAL_SMBUS_RESET_CR2 SMBUS_RESET_CR2 +#define __HAL_SMBUS_GENERATE_START SMBUS_GENERATE_START +#define __HAL_SMBUS_GET_ADDR_MATCH SMBUS_GET_ADDR_MATCH +#define __HAL_SMBUS_GET_DIR SMBUS_GET_DIR +#define __HAL_SMBUS_GET_STOP_MODE SMBUS_GET_STOP_MODE +#define __HAL_SMBUS_GET_PEC_MODE SMBUS_GET_PEC_MODE +#define __HAL_SMBUS_GET_ALERT_ENABLED SMBUS_GET_ALERT_ENABLED +/** + * @} + */ + +/** @defgroup HAL_SPI_Aliased_Macros HAL SPI Aliased Macros maintained for legacy purpose + * @{ + */ + +#define __HAL_SPI_1LINE_TX SPI_1LINE_TX +#define __HAL_SPI_1LINE_RX SPI_1LINE_RX +#define __HAL_SPI_RESET_CRC SPI_RESET_CRC + +/** + * @} + */ + +/** @defgroup HAL_UART_Aliased_Macros HAL UART Aliased Macros maintained for legacy purpose + * @{ + */ + +#define __HAL_UART_GETCLOCKSOURCE UART_GETCLOCKSOURCE +#define __HAL_UART_MASK_COMPUTATION UART_MASK_COMPUTATION +#define __UART_GETCLOCKSOURCE UART_GETCLOCKSOURCE +#define __UART_MASK_COMPUTATION UART_MASK_COMPUTATION + +#define IS_UART_WAKEUPMETHODE IS_UART_WAKEUPMETHOD + +#define IS_UART_ONEBIT_SAMPLE IS_UART_ONE_BIT_SAMPLE +#define IS_UART_ONEBIT_SAMPLING IS_UART_ONE_BIT_SAMPLE + +/** + * @} + */ + + +/** @defgroup HAL_USART_Aliased_Macros HAL USART Aliased Macros maintained for legacy purpose + * @{ + */ + +#define __USART_ENABLE_IT __HAL_USART_ENABLE_IT +#define __USART_DISABLE_IT __HAL_USART_DISABLE_IT +#define __USART_ENABLE __HAL_USART_ENABLE +#define __USART_DISABLE __HAL_USART_DISABLE + +#define __HAL_USART_GETCLOCKSOURCE USART_GETCLOCKSOURCE +#define __USART_GETCLOCKSOURCE USART_GETCLOCKSOURCE + +/** + * @} + */ + +/** @defgroup HAL_USB_Aliased_Macros HAL USB Aliased Macros maintained for legacy purpose + * @{ + */ +#define USB_EXTI_LINE_WAKEUP USB_WAKEUP_EXTI_LINE + +#define USB_FS_EXTI_TRIGGER_RISING_EDGE USB_OTG_FS_WAKEUP_EXTI_RISING_EDGE +#define USB_FS_EXTI_TRIGGER_FALLING_EDGE USB_OTG_FS_WAKEUP_EXTI_FALLING_EDGE +#define USB_FS_EXTI_TRIGGER_BOTH_EDGE USB_OTG_FS_WAKEUP_EXTI_RISING_FALLING_EDGE +#define USB_FS_EXTI_LINE_WAKEUP USB_OTG_FS_WAKEUP_EXTI_LINE + +#define USB_HS_EXTI_TRIGGER_RISING_EDGE USB_OTG_HS_WAKEUP_EXTI_RISING_EDGE +#define USB_HS_EXTI_TRIGGER_FALLING_EDGE USB_OTG_HS_WAKEUP_EXTI_FALLING_EDGE +#define USB_HS_EXTI_TRIGGER_BOTH_EDGE USB_OTG_HS_WAKEUP_EXTI_RISING_FALLING_EDGE +#define USB_HS_EXTI_LINE_WAKEUP USB_OTG_HS_WAKEUP_EXTI_LINE + +#define __HAL_USB_EXTI_ENABLE_IT __HAL_USB_WAKEUP_EXTI_ENABLE_IT +#define __HAL_USB_EXTI_DISABLE_IT __HAL_USB_WAKEUP_EXTI_DISABLE_IT +#define __HAL_USB_EXTI_GET_FLAG __HAL_USB_WAKEUP_EXTI_GET_FLAG +#define __HAL_USB_EXTI_CLEAR_FLAG __HAL_USB_WAKEUP_EXTI_CLEAR_FLAG +#define __HAL_USB_EXTI_SET_RISING_EDGE_TRIGGER __HAL_USB_WAKEUP_EXTI_ENABLE_RISING_EDGE +#define __HAL_USB_EXTI_SET_FALLING_EDGE_TRIGGER __HAL_USB_WAKEUP_EXTI_ENABLE_FALLING_EDGE +#define __HAL_USB_EXTI_SET_FALLINGRISING_TRIGGER __HAL_USB_WAKEUP_EXTI_ENABLE_RISING_FALLING_EDGE + +#define __HAL_USB_FS_EXTI_ENABLE_IT __HAL_USB_OTG_FS_WAKEUP_EXTI_ENABLE_IT +#define __HAL_USB_FS_EXTI_DISABLE_IT __HAL_USB_OTG_FS_WAKEUP_EXTI_DISABLE_IT +#define __HAL_USB_FS_EXTI_GET_FLAG __HAL_USB_OTG_FS_WAKEUP_EXTI_GET_FLAG +#define __HAL_USB_FS_EXTI_CLEAR_FLAG __HAL_USB_OTG_FS_WAKEUP_EXTI_CLEAR_FLAG +#define __HAL_USB_FS_EXTI_SET_RISING_EGDE_TRIGGER __HAL_USB_OTG_FS_WAKEUP_EXTI_ENABLE_RISING_EDGE +#define __HAL_USB_FS_EXTI_SET_FALLING_EGDE_TRIGGER __HAL_USB_OTG_FS_WAKEUP_EXTI_ENABLE_FALLING_EDGE +#define __HAL_USB_FS_EXTI_SET_FALLINGRISING_TRIGGER __HAL_USB_OTG_FS_WAKEUP_EXTI_ENABLE_RISING_FALLING_EDGE +#define __HAL_USB_FS_EXTI_GENERATE_SWIT __HAL_USB_OTG_FS_WAKEUP_EXTI_GENERATE_SWIT + +#define __HAL_USB_HS_EXTI_ENABLE_IT __HAL_USB_OTG_HS_WAKEUP_EXTI_ENABLE_IT +#define __HAL_USB_HS_EXTI_DISABLE_IT __HAL_USB_OTG_HS_WAKEUP_EXTI_DISABLE_IT +#define __HAL_USB_HS_EXTI_GET_FLAG __HAL_USB_OTG_HS_WAKEUP_EXTI_GET_FLAG +#define __HAL_USB_HS_EXTI_CLEAR_FLAG __HAL_USB_OTG_HS_WAKEUP_EXTI_CLEAR_FLAG +#define __HAL_USB_HS_EXTI_SET_RISING_EGDE_TRIGGER __HAL_USB_OTG_HS_WAKEUP_EXTI_ENABLE_RISING_EDGE +#define __HAL_USB_HS_EXTI_SET_FALLING_EGDE_TRIGGER __HAL_USB_OTG_HS_WAKEUP_EXTI_ENABLE_FALLING_EDGE +#define __HAL_USB_HS_EXTI_SET_FALLINGRISING_TRIGGER __HAL_USB_OTG_HS_WAKEUP_EXTI_ENABLE_RISING_FALLING_EDGE +#define __HAL_USB_HS_EXTI_GENERATE_SWIT __HAL_USB_OTG_HS_WAKEUP_EXTI_GENERATE_SWIT + +#define HAL_PCD_ActiveRemoteWakeup HAL_PCD_ActivateRemoteWakeup +#define HAL_PCD_DeActiveRemoteWakeup HAL_PCD_DeActivateRemoteWakeup + +#define HAL_PCD_SetTxFiFo HAL_PCDEx_SetTxFiFo +#define HAL_PCD_SetRxFiFo HAL_PCDEx_SetRxFiFo +/** + * @} + */ + +/** @defgroup HAL_TIM_Aliased_Macros HAL TIM Aliased Macros maintained for legacy purpose + * @{ + */ +#define __HAL_TIM_SetICPrescalerValue TIM_SET_ICPRESCALERVALUE +#define __HAL_TIM_ResetICPrescalerValue TIM_RESET_ICPRESCALERVALUE + +#define TIM_GET_ITSTATUS __HAL_TIM_GET_IT_SOURCE +#define TIM_GET_CLEAR_IT __HAL_TIM_CLEAR_IT + +#define __HAL_TIM_GET_ITSTATUS __HAL_TIM_GET_IT_SOURCE + +#define __HAL_TIM_DIRECTION_STATUS __HAL_TIM_IS_TIM_COUNTING_DOWN +#define __HAL_TIM_PRESCALER __HAL_TIM_SET_PRESCALER +#define __HAL_TIM_SetCounter __HAL_TIM_SET_COUNTER +#define __HAL_TIM_GetCounter __HAL_TIM_GET_COUNTER +#define __HAL_TIM_SetAutoreload __HAL_TIM_SET_AUTORELOAD +#define __HAL_TIM_GetAutoreload __HAL_TIM_GET_AUTORELOAD +#define __HAL_TIM_SetClockDivision __HAL_TIM_SET_CLOCKDIVISION +#define __HAL_TIM_GetClockDivision __HAL_TIM_GET_CLOCKDIVISION +#define __HAL_TIM_SetICPrescaler __HAL_TIM_SET_ICPRESCALER +#define __HAL_TIM_GetICPrescaler __HAL_TIM_GET_ICPRESCALER +#define __HAL_TIM_SetCompare __HAL_TIM_SET_COMPARE +#define __HAL_TIM_GetCompare __HAL_TIM_GET_COMPARE + +#define TIM_BREAKINPUTSOURCE_DFSDM TIM_BREAKINPUTSOURCE_DFSDM1 +/** + * @} + */ + +/** @defgroup HAL_ETH_Aliased_Macros HAL ETH Aliased Macros maintained for legacy purpose + * @{ + */ + +#define __HAL_ETH_EXTI_ENABLE_IT __HAL_ETH_WAKEUP_EXTI_ENABLE_IT +#define __HAL_ETH_EXTI_DISABLE_IT __HAL_ETH_WAKEUP_EXTI_DISABLE_IT +#define __HAL_ETH_EXTI_GET_FLAG __HAL_ETH_WAKEUP_EXTI_GET_FLAG +#define __HAL_ETH_EXTI_CLEAR_FLAG __HAL_ETH_WAKEUP_EXTI_CLEAR_FLAG +#define __HAL_ETH_EXTI_SET_RISING_EGDE_TRIGGER __HAL_ETH_WAKEUP_EXTI_ENABLE_RISING_EDGE_TRIGGER +#define __HAL_ETH_EXTI_SET_FALLING_EGDE_TRIGGER __HAL_ETH_WAKEUP_EXTI_ENABLE_FALLING_EDGE_TRIGGER +#define __HAL_ETH_EXTI_SET_FALLINGRISING_TRIGGER __HAL_ETH_WAKEUP_EXTI_ENABLE_FALLINGRISING_TRIGGER + +#define ETH_PROMISCIOUSMODE_ENABLE ETH_PROMISCUOUS_MODE_ENABLE +#define ETH_PROMISCIOUSMODE_DISABLE ETH_PROMISCUOUS_MODE_DISABLE +#define IS_ETH_PROMISCIOUS_MODE IS_ETH_PROMISCUOUS_MODE +/** + * @} + */ + +/** @defgroup HAL_LTDC_Aliased_Macros HAL LTDC Aliased Macros maintained for legacy purpose + * @{ + */ +#define __HAL_LTDC_LAYER LTDC_LAYER +#define __HAL_LTDC_RELOAD_CONFIG __HAL_LTDC_RELOAD_IMMEDIATE_CONFIG +/** + * @} + */ + +/** @defgroup HAL_SAI_Aliased_Macros HAL SAI Aliased Macros maintained for legacy purpose + * @{ + */ +#define SAI_OUTPUTDRIVE_DISABLED SAI_OUTPUTDRIVE_DISABLE +#define SAI_OUTPUTDRIVE_ENABLED SAI_OUTPUTDRIVE_ENABLE +#define SAI_MASTERDIVIDER_ENABLED SAI_MASTERDIVIDER_ENABLE +#define SAI_MASTERDIVIDER_DISABLED SAI_MASTERDIVIDER_DISABLE +#define SAI_STREOMODE SAI_STEREOMODE +#define SAI_FIFOStatus_Empty SAI_FIFOSTATUS_EMPTY +#define SAI_FIFOStatus_Less1QuarterFull SAI_FIFOSTATUS_LESS1QUARTERFULL +#define SAI_FIFOStatus_1QuarterFull SAI_FIFOSTATUS_1QUARTERFULL +#define SAI_FIFOStatus_HalfFull SAI_FIFOSTATUS_HALFFULL +#define SAI_FIFOStatus_3QuartersFull SAI_FIFOSTATUS_3QUARTERFULL +#define SAI_FIFOStatus_Full SAI_FIFOSTATUS_FULL +#define IS_SAI_BLOCK_MONO_STREO_MODE IS_SAI_BLOCK_MONO_STEREO_MODE +#define SAI_SYNCHRONOUS_EXT SAI_SYNCHRONOUS_EXT_SAI1 +#define SAI_SYNCEXT_IN_ENABLE SAI_SYNCEXT_OUTBLOCKA_ENABLE +/** + * @} + */ + +/** @defgroup HAL_SPDIFRX_Aliased_Macros HAL SPDIFRX Aliased Macros maintained for legacy purpose + * @{ + */ +#if defined(STM32H7) +#define HAL_SPDIFRX_ReceiveControlFlow HAL_SPDIFRX_ReceiveCtrlFlow +#define HAL_SPDIFRX_ReceiveControlFlow_IT HAL_SPDIFRX_ReceiveCtrlFlow_IT +#define HAL_SPDIFRX_ReceiveControlFlow_DMA HAL_SPDIFRX_ReceiveCtrlFlow_DMA +#endif +/** + * @} + */ + +/** @defgroup HAL_PPP_Aliased_Macros HAL PPP Aliased Macros maintained for legacy purpose + * @{ + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* ___STM32_HAL_LEGACY */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal.h new file mode 100644 index 0000000..3b3c147 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal.h @@ -0,0 +1,669 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal.h + * @author MCD Application Team + * @brief This file contains all the functions prototypes for the HAL + * module driver. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_H +#define __STM32L4xx_HAL_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_conf.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup HAL + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/** @defgroup SYSCFG_Exported_Constants SYSCFG Exported Constants + * @{ + */ + +/** @defgroup SYSCFG_BootMode Boot Mode + * @{ + */ +#define SYSCFG_BOOT_MAINFLASH ((uint32_t)0x00000000) +#define SYSCFG_BOOT_SYSTEMFLASH SYSCFG_MEMRMP_MEM_MODE_0 + +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define SYSCFG_BOOT_FMC SYSCFG_MEMRMP_MEM_MODE_1 +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx || */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#define SYSCFG_BOOT_SRAM (SYSCFG_MEMRMP_MEM_MODE_1 | SYSCFG_MEMRMP_MEM_MODE_0) + +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define SYSCFG_BOOT_OCTOPSPI1 (SYSCFG_MEMRMP_MEM_MODE_2) +#define SYSCFG_BOOT_OCTOPSPI2 (SYSCFG_MEMRMP_MEM_MODE_2 | SYSCFG_MEMRMP_MEM_MODE_0) +#else +#define SYSCFG_BOOT_QUADSPI (SYSCFG_MEMRMP_MEM_MODE_2 | SYSCFG_MEMRMP_MEM_MODE_1) +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +/** + * @} + */ + +/** @defgroup SYSCFG_FPU_Interrupts FPU Interrupts + * @{ + */ +#define SYSCFG_IT_FPU_IOC SYSCFG_CFGR1_FPU_IE_0 /*!< Floating Point Unit Invalid operation Interrupt */ +#define SYSCFG_IT_FPU_DZC SYSCFG_CFGR1_FPU_IE_1 /*!< Floating Point Unit Divide-by-zero Interrupt */ +#define SYSCFG_IT_FPU_UFC SYSCFG_CFGR1_FPU_IE_2 /*!< Floating Point Unit Underflow Interrupt */ +#define SYSCFG_IT_FPU_OFC SYSCFG_CFGR1_FPU_IE_3 /*!< Floating Point Unit Overflow Interrupt */ +#define SYSCFG_IT_FPU_IDC SYSCFG_CFGR1_FPU_IE_4 /*!< Floating Point Unit Input denormal Interrupt */ +#define SYSCFG_IT_FPU_IXC SYSCFG_CFGR1_FPU_IE_5 /*!< Floating Point Unit Inexact Interrupt */ + +/** + * @} + */ + +/** @defgroup SYSCFG_SRAM2WRP SRAM2 Page Write protection (0 to 31) + * @{ + */ +#define SYSCFG_SRAM2WRP_PAGE0 SYSCFG_SWPR_PAGE0 /*!< SRAM2 Write protection page 0 */ +#define SYSCFG_SRAM2WRP_PAGE1 SYSCFG_SWPR_PAGE1 /*!< SRAM2 Write protection page 1 */ +#define SYSCFG_SRAM2WRP_PAGE2 SYSCFG_SWPR_PAGE2 /*!< SRAM2 Write protection page 2 */ +#define SYSCFG_SRAM2WRP_PAGE3 SYSCFG_SWPR_PAGE3 /*!< SRAM2 Write protection page 3 */ +#define SYSCFG_SRAM2WRP_PAGE4 SYSCFG_SWPR_PAGE4 /*!< SRAM2 Write protection page 4 */ +#define SYSCFG_SRAM2WRP_PAGE5 SYSCFG_SWPR_PAGE5 /*!< SRAM2 Write protection page 5 */ +#define SYSCFG_SRAM2WRP_PAGE6 SYSCFG_SWPR_PAGE6 /*!< SRAM2 Write protection page 6 */ +#define SYSCFG_SRAM2WRP_PAGE7 SYSCFG_SWPR_PAGE7 /*!< SRAM2 Write protection page 7 */ +#define SYSCFG_SRAM2WRP_PAGE8 SYSCFG_SWPR_PAGE8 /*!< SRAM2 Write protection page 8 */ +#define SYSCFG_SRAM2WRP_PAGE9 SYSCFG_SWPR_PAGE9 /*!< SRAM2 Write protection page 9 */ +#define SYSCFG_SRAM2WRP_PAGE10 SYSCFG_SWPR_PAGE10 /*!< SRAM2 Write protection page 10 */ +#define SYSCFG_SRAM2WRP_PAGE11 SYSCFG_SWPR_PAGE11 /*!< SRAM2 Write protection page 11 */ +#define SYSCFG_SRAM2WRP_PAGE12 SYSCFG_SWPR_PAGE12 /*!< SRAM2 Write protection page 12 */ +#define SYSCFG_SRAM2WRP_PAGE13 SYSCFG_SWPR_PAGE13 /*!< SRAM2 Write protection page 13 */ +#define SYSCFG_SRAM2WRP_PAGE14 SYSCFG_SWPR_PAGE14 /*!< SRAM2 Write protection page 14 */ +#define SYSCFG_SRAM2WRP_PAGE15 SYSCFG_SWPR_PAGE15 /*!< SRAM2 Write protection page 15 */ +#if defined(SYSCFG_SWPR_PAGE31) +#define SYSCFG_SRAM2WRP_PAGE16 SYSCFG_SWPR_PAGE16 /*!< SRAM2 Write protection page 16 */ +#define SYSCFG_SRAM2WRP_PAGE17 SYSCFG_SWPR_PAGE17 /*!< SRAM2 Write protection page 17 */ +#define SYSCFG_SRAM2WRP_PAGE18 SYSCFG_SWPR_PAGE18 /*!< SRAM2 Write protection page 18 */ +#define SYSCFG_SRAM2WRP_PAGE19 SYSCFG_SWPR_PAGE19 /*!< SRAM2 Write protection page 19 */ +#define SYSCFG_SRAM2WRP_PAGE20 SYSCFG_SWPR_PAGE20 /*!< SRAM2 Write protection page 20 */ +#define SYSCFG_SRAM2WRP_PAGE21 SYSCFG_SWPR_PAGE21 /*!< SRAM2 Write protection page 21 */ +#define SYSCFG_SRAM2WRP_PAGE22 SYSCFG_SWPR_PAGE22 /*!< SRAM2 Write protection page 22 */ +#define SYSCFG_SRAM2WRP_PAGE23 SYSCFG_SWPR_PAGE23 /*!< SRAM2 Write protection page 23 */ +#define SYSCFG_SRAM2WRP_PAGE24 SYSCFG_SWPR_PAGE24 /*!< SRAM2 Write protection page 24 */ +#define SYSCFG_SRAM2WRP_PAGE25 SYSCFG_SWPR_PAGE25 /*!< SRAM2 Write protection page 25 */ +#define SYSCFG_SRAM2WRP_PAGE26 SYSCFG_SWPR_PAGE26 /*!< SRAM2 Write protection page 26 */ +#define SYSCFG_SRAM2WRP_PAGE27 SYSCFG_SWPR_PAGE27 /*!< SRAM2 Write protection page 27 */ +#define SYSCFG_SRAM2WRP_PAGE28 SYSCFG_SWPR_PAGE28 /*!< SRAM2 Write protection page 28 */ +#define SYSCFG_SRAM2WRP_PAGE29 SYSCFG_SWPR_PAGE29 /*!< SRAM2 Write protection page 29 */ +#define SYSCFG_SRAM2WRP_PAGE30 SYSCFG_SWPR_PAGE30 /*!< SRAM2 Write protection page 30 */ +#define SYSCFG_SRAM2WRP_PAGE31 SYSCFG_SWPR_PAGE31 /*!< SRAM2 Write protection page 31 */ +#endif /* SYSCFG_SWPR_PAGE31 */ + +/** + * @} + */ + +#if defined(SYSCFG_SWPR2_PAGE63) +/** @defgroup SYSCFG_SRAM2WRP_32_63 SRAM2 Page Write protection (32 to 63) + * @{ + */ +#define SYSCFG_SRAM2WRP_PAGE32 SYSCFG_SWPR2_PAGE32 /*!< SRAM2 Write protection page 32 */ +#define SYSCFG_SRAM2WRP_PAGE33 SYSCFG_SWPR2_PAGE33 /*!< SRAM2 Write protection page 33 */ +#define SYSCFG_SRAM2WRP_PAGE34 SYSCFG_SWPR2_PAGE34 /*!< SRAM2 Write protection page 34 */ +#define SYSCFG_SRAM2WRP_PAGE35 SYSCFG_SWPR2_PAGE35 /*!< SRAM2 Write protection page 35 */ +#define SYSCFG_SRAM2WRP_PAGE36 SYSCFG_SWPR2_PAGE36 /*!< SRAM2 Write protection page 36 */ +#define SYSCFG_SRAM2WRP_PAGE37 SYSCFG_SWPR2_PAGE37 /*!< SRAM2 Write protection page 37 */ +#define SYSCFG_SRAM2WRP_PAGE38 SYSCFG_SWPR2_PAGE38 /*!< SRAM2 Write protection page 38 */ +#define SYSCFG_SRAM2WRP_PAGE39 SYSCFG_SWPR2_PAGE39 /*!< SRAM2 Write protection page 39 */ +#define SYSCFG_SRAM2WRP_PAGE40 SYSCFG_SWPR2_PAGE40 /*!< SRAM2 Write protection page 40 */ +#define SYSCFG_SRAM2WRP_PAGE41 SYSCFG_SWPR2_PAGE41 /*!< SRAM2 Write protection page 41 */ +#define SYSCFG_SRAM2WRP_PAGE42 SYSCFG_SWPR2_PAGE42 /*!< SRAM2 Write protection page 42 */ +#define SYSCFG_SRAM2WRP_PAGE43 SYSCFG_SWPR2_PAGE43 /*!< SRAM2 Write protection page 43 */ +#define SYSCFG_SRAM2WRP_PAGE44 SYSCFG_SWPR2_PAGE44 /*!< SRAM2 Write protection page 44 */ +#define SYSCFG_SRAM2WRP_PAGE45 SYSCFG_SWPR2_PAGE45 /*!< SRAM2 Write protection page 45 */ +#define SYSCFG_SRAM2WRP_PAGE46 SYSCFG_SWPR2_PAGE46 /*!< SRAM2 Write protection page 46 */ +#define SYSCFG_SRAM2WRP_PAGE47 SYSCFG_SWPR2_PAGE47 /*!< SRAM2 Write protection page 47 */ +#define SYSCFG_SRAM2WRP_PAGE48 SYSCFG_SWPR2_PAGE48 /*!< SRAM2 Write protection page 48 */ +#define SYSCFG_SRAM2WRP_PAGE49 SYSCFG_SWPR2_PAGE49 /*!< SRAM2 Write protection page 49 */ +#define SYSCFG_SRAM2WRP_PAGE50 SYSCFG_SWPR2_PAGE50 /*!< SRAM2 Write protection page 50 */ +#define SYSCFG_SRAM2WRP_PAGE51 SYSCFG_SWPR2_PAGE51 /*!< SRAM2 Write protection page 51 */ +#define SYSCFG_SRAM2WRP_PAGE52 SYSCFG_SWPR2_PAGE52 /*!< SRAM2 Write protection page 52 */ +#define SYSCFG_SRAM2WRP_PAGE53 SYSCFG_SWPR2_PAGE53 /*!< SRAM2 Write protection page 53 */ +#define SYSCFG_SRAM2WRP_PAGE54 SYSCFG_SWPR2_PAGE54 /*!< SRAM2 Write protection page 54 */ +#define SYSCFG_SRAM2WRP_PAGE55 SYSCFG_SWPR2_PAGE55 /*!< SRAM2 Write protection page 55 */ +#define SYSCFG_SRAM2WRP_PAGE56 SYSCFG_SWPR2_PAGE56 /*!< SRAM2 Write protection page 56 */ +#define SYSCFG_SRAM2WRP_PAGE57 SYSCFG_SWPR2_PAGE57 /*!< SRAM2 Write protection page 57 */ +#define SYSCFG_SRAM2WRP_PAGE58 SYSCFG_SWPR2_PAGE58 /*!< SRAM2 Write protection page 58 */ +#define SYSCFG_SRAM2WRP_PAGE59 SYSCFG_SWPR2_PAGE59 /*!< SRAM2 Write protection page 59 */ +#define SYSCFG_SRAM2WRP_PAGE60 SYSCFG_SWPR2_PAGE60 /*!< SRAM2 Write protection page 60 */ +#define SYSCFG_SRAM2WRP_PAGE61 SYSCFG_SWPR2_PAGE61 /*!< SRAM2 Write protection page 61 */ +#define SYSCFG_SRAM2WRP_PAGE62 SYSCFG_SWPR2_PAGE62 /*!< SRAM2 Write protection page 62 */ +#define SYSCFG_SRAM2WRP_PAGE63 SYSCFG_SWPR2_PAGE63 /*!< SRAM2 Write protection page 63 */ + +/** + * @} + */ +#endif /* SYSCFG_SWPR2_PAGE63 */ + +#if defined(VREFBUF) +/** @defgroup SYSCFG_VREFBUF_VoltageScale VREFBUF Voltage Scale + * @{ + */ +#define SYSCFG_VREFBUF_VOLTAGE_SCALE0 ((uint32_t)0x00000000) /*!< Voltage reference scale 0 (VREF_OUT1) */ +#define SYSCFG_VREFBUF_VOLTAGE_SCALE1 VREFBUF_CSR_VRS /*!< Voltage reference scale 1 (VREF_OUT2) */ + +/** + * @} + */ + +/** @defgroup SYSCFG_VREFBUF_HighImpedance VREFBUF High Impedance + * @{ + */ +#define SYSCFG_VREFBUF_HIGH_IMPEDANCE_DISABLE ((uint32_t)0x00000000) /*!< VREF_plus pin is internally connected to Voltage reference buffer output */ +#define SYSCFG_VREFBUF_HIGH_IMPEDANCE_ENABLE VREFBUF_CSR_HIZ /*!< VREF_plus pin is high impedance */ + +/** + * @} + */ +#endif /* VREFBUF */ + +/** @defgroup SYSCFG_flags_definition Flags + * @{ + */ + +#define SYSCFG_FLAG_SRAM2_PE SYSCFG_CFGR2_SPF /*!< SRAM2 parity error */ +#define SYSCFG_FLAG_SRAM2_BUSY SYSCFG_SCSR_SRAM2BSY /*!< SRAM2 busy by erase operation */ + +/** + * @} + */ + +/** @defgroup SYSCFG_FastModePlus_GPIO Fast-mode Plus on GPIO + * @{ + */ + +/** @brief Fast-mode Plus driving capability on a specific GPIO + */ +#define SYSCFG_FASTMODEPLUS_PB6 SYSCFG_CFGR1_I2C_PB6_FMP /*!< Enable Fast-mode Plus on PB6 */ +#define SYSCFG_FASTMODEPLUS_PB7 SYSCFG_CFGR1_I2C_PB7_FMP /*!< Enable Fast-mode Plus on PB7 */ +#if defined(SYSCFG_CFGR1_I2C_PB8_FMP) +#define SYSCFG_FASTMODEPLUS_PB8 SYSCFG_CFGR1_I2C_PB8_FMP /*!< Enable Fast-mode Plus on PB8 */ +#endif /* SYSCFG_CFGR1_I2C_PB8_FMP */ +#if defined(SYSCFG_CFGR1_I2C_PB9_FMP) +#define SYSCFG_FASTMODEPLUS_PB9 SYSCFG_CFGR1_I2C_PB9_FMP /*!< Enable Fast-mode Plus on PB9 */ +#endif /* SYSCFG_CFGR1_I2C_PB9_FMP */ + +/** + * @} + */ + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ + +/** @defgroup DBGMCU_Exported_Macros DBGMCU Exported Macros + * @{ + */ + +/** @brief Freeze/Unfreeze Peripherals in Debug mode + */ +#if defined(DBGMCU_APB1FZR1_DBG_TIM2_STOP) +#define __HAL_DBGMCU_FREEZE_TIM2() SET_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_TIM2_STOP) +#define __HAL_DBGMCU_UNFREEZE_TIM2() CLEAR_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_TIM2_STOP) +#endif + +#if defined(DBGMCU_APB1FZR1_DBG_TIM3_STOP) +#define __HAL_DBGMCU_FREEZE_TIM3() SET_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_TIM3_STOP) +#define __HAL_DBGMCU_UNFREEZE_TIM3() CLEAR_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_TIM3_STOP) +#endif + +#if defined(DBGMCU_APB1FZR1_DBG_TIM4_STOP) +#define __HAL_DBGMCU_FREEZE_TIM4() SET_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_TIM4_STOP) +#define __HAL_DBGMCU_UNFREEZE_TIM4() CLEAR_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_TIM4_STOP) +#endif + +#if defined(DBGMCU_APB1FZR1_DBG_TIM5_STOP) +#define __HAL_DBGMCU_FREEZE_TIM5() SET_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_TIM5_STOP) +#define __HAL_DBGMCU_UNFREEZE_TIM5() CLEAR_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_TIM5_STOP) +#endif + +#if defined(DBGMCU_APB1FZR1_DBG_TIM6_STOP) +#define __HAL_DBGMCU_FREEZE_TIM6() SET_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_TIM6_STOP) +#define __HAL_DBGMCU_UNFREEZE_TIM6() CLEAR_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_TIM6_STOP) +#endif + +#if defined(DBGMCU_APB1FZR1_DBG_TIM7_STOP) +#define __HAL_DBGMCU_FREEZE_TIM7() SET_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_TIM7_STOP) +#define __HAL_DBGMCU_UNFREEZE_TIM7() CLEAR_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_TIM7_STOP) +#endif + +#if defined(DBGMCU_APB1FZR1_DBG_RTC_STOP) +#define __HAL_DBGMCU_FREEZE_RTC() SET_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_RTC_STOP) +#define __HAL_DBGMCU_UNFREEZE_RTC() CLEAR_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_RTC_STOP) +#endif + +#if defined(DBGMCU_APB1FZR1_DBG_WWDG_STOP) +#define __HAL_DBGMCU_FREEZE_WWDG() SET_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_WWDG_STOP) +#define __HAL_DBGMCU_UNFREEZE_WWDG() CLEAR_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_WWDG_STOP) +#endif + +#if defined(DBGMCU_APB1FZR1_DBG_IWDG_STOP) +#define __HAL_DBGMCU_FREEZE_IWDG() SET_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_IWDG_STOP) +#define __HAL_DBGMCU_UNFREEZE_IWDG() CLEAR_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_IWDG_STOP) +#endif + +#if defined(DBGMCU_APB1FZR1_DBG_I2C1_STOP) +#define __HAL_DBGMCU_FREEZE_I2C1_TIMEOUT() SET_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_I2C1_STOP) +#define __HAL_DBGMCU_UNFREEZE_I2C1_TIMEOUT() CLEAR_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_I2C1_STOP) +#endif + +#if defined(DBGMCU_APB1FZR1_DBG_I2C2_STOP) +#define __HAL_DBGMCU_FREEZE_I2C2_TIMEOUT() SET_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_I2C2_STOP) +#define __HAL_DBGMCU_UNFREEZE_I2C2_TIMEOUT() CLEAR_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_I2C2_STOP) +#endif + +#if defined(DBGMCU_APB1FZR1_DBG_I2C3_STOP) +#define __HAL_DBGMCU_FREEZE_I2C3_TIMEOUT() SET_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_I2C3_STOP) +#define __HAL_DBGMCU_UNFREEZE_I2C3_TIMEOUT() CLEAR_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_I2C3_STOP) +#endif + +#if defined(DBGMCU_APB1FZR2_DBG_I2C4_STOP) +#define __HAL_DBGMCU_FREEZE_I2C4_TIMEOUT() SET_BIT(DBGMCU->APB1FZR2, DBGMCU_APB1FZR2_DBG_I2C4_STOP) +#define __HAL_DBGMCU_UNFREEZE_I2C4_TIMEOUT() CLEAR_BIT(DBGMCU->APB1FZR2, DBGMCU_APB1FZR2_DBG_I2C4_STOP) +#endif + +#if defined(DBGMCU_APB1FZR1_DBG_CAN_STOP) +#define __HAL_DBGMCU_FREEZE_CAN1() SET_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_CAN_STOP) +#define __HAL_DBGMCU_UNFREEZE_CAN1() CLEAR_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_CAN_STOP) +#endif + +#if defined(DBGMCU_APB1FZR1_DBG_CAN2_STOP) +#define __HAL_DBGMCU_FREEZE_CAN2() SET_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_CAN2_STOP) +#define __HAL_DBGMCU_UNFREEZE_CAN2() CLEAR_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_CAN2_STOP) +#endif + +#if defined(DBGMCU_APB1FZR1_DBG_LPTIM1_STOP) +#define __HAL_DBGMCU_FREEZE_LPTIM1() SET_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_LPTIM1_STOP) +#define __HAL_DBGMCU_UNFREEZE_LPTIM1() CLEAR_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_LPTIM1_STOP) +#endif + +#if defined(DBGMCU_APB1FZR2_DBG_LPTIM2_STOP) +#define __HAL_DBGMCU_FREEZE_LPTIM2() SET_BIT(DBGMCU->APB1FZR2, DBGMCU_APB1FZR2_DBG_LPTIM2_STOP) +#define __HAL_DBGMCU_UNFREEZE_LPTIM2() CLEAR_BIT(DBGMCU->APB1FZR2, DBGMCU_APB1FZR2_DBG_LPTIM2_STOP) +#endif + +#if defined(DBGMCU_APB2FZ_DBG_TIM1_STOP) +#define __HAL_DBGMCU_FREEZE_TIM1() SET_BIT(DBGMCU->APB2FZ, DBGMCU_APB2FZ_DBG_TIM1_STOP) +#define __HAL_DBGMCU_UNFREEZE_TIM1() CLEAR_BIT(DBGMCU->APB2FZ, DBGMCU_APB2FZ_DBG_TIM1_STOP) +#endif + +#if defined(DBGMCU_APB2FZ_DBG_TIM8_STOP) +#define __HAL_DBGMCU_FREEZE_TIM8() SET_BIT(DBGMCU->APB2FZ, DBGMCU_APB2FZ_DBG_TIM8_STOP) +#define __HAL_DBGMCU_UNFREEZE_TIM8() CLEAR_BIT(DBGMCU->APB2FZ, DBGMCU_APB2FZ_DBG_TIM8_STOP) +#endif + +#if defined(DBGMCU_APB2FZ_DBG_TIM15_STOP) +#define __HAL_DBGMCU_FREEZE_TIM15() SET_BIT(DBGMCU->APB2FZ, DBGMCU_APB2FZ_DBG_TIM15_STOP) +#define __HAL_DBGMCU_UNFREEZE_TIM15() CLEAR_BIT(DBGMCU->APB2FZ, DBGMCU_APB2FZ_DBG_TIM15_STOP) +#endif + +#if defined(DBGMCU_APB2FZ_DBG_TIM16_STOP) +#define __HAL_DBGMCU_FREEZE_TIM16() SET_BIT(DBGMCU->APB2FZ, DBGMCU_APB2FZ_DBG_TIM16_STOP) +#define __HAL_DBGMCU_UNFREEZE_TIM16() CLEAR_BIT(DBGMCU->APB2FZ, DBGMCU_APB2FZ_DBG_TIM16_STOP) +#endif + +#if defined(DBGMCU_APB2FZ_DBG_TIM17_STOP) +#define __HAL_DBGMCU_FREEZE_TIM17() SET_BIT(DBGMCU->APB2FZ, DBGMCU_APB2FZ_DBG_TIM17_STOP) +#define __HAL_DBGMCU_UNFREEZE_TIM17() CLEAR_BIT(DBGMCU->APB2FZ, DBGMCU_APB2FZ_DBG_TIM17_STOP) +#endif + +/** + * @} + */ + +/** @defgroup SYSCFG_Exported_Macros SYSCFG Exported Macros + * @{ + */ + +/** @brief Main Flash memory mapped at 0x00000000. + */ +#define __HAL_SYSCFG_REMAPMEMORY_FLASH() CLEAR_BIT(SYSCFG->MEMRMP, SYSCFG_MEMRMP_MEM_MODE) + +/** @brief System Flash memory mapped at 0x00000000. + */ +#define __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH() MODIFY_REG(SYSCFG->MEMRMP, SYSCFG_MEMRMP_MEM_MODE, SYSCFG_MEMRMP_MEM_MODE_0) + +/** @brief Embedded SRAM mapped at 0x00000000. + */ +#define __HAL_SYSCFG_REMAPMEMORY_SRAM() MODIFY_REG(SYSCFG->MEMRMP, SYSCFG_MEMRMP_MEM_MODE, (SYSCFG_MEMRMP_MEM_MODE_1|SYSCFG_MEMRMP_MEM_MODE_0)) + +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + +/** @brief FMC Bank1 (NOR/PSRAM 1 and 2) mapped at 0x00000000. + */ +#define __HAL_SYSCFG_REMAPMEMORY_FMC() MODIFY_REG(SYSCFG->MEMRMP, SYSCFG_MEMRMP_MEM_MODE, SYSCFG_MEMRMP_MEM_MODE_1) + +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx || */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + +/** @brief OCTOSPI mapped at 0x00000000. + */ +#define __HAL_SYSCFG_REMAPMEMORY_OCTOSPI1() MODIFY_REG(SYSCFG->MEMRMP, SYSCFG_MEMRMP_MEM_MODE, (SYSCFG_MEMRMP_MEM_MODE_2)) +#define __HAL_SYSCFG_REMAPMEMORY_OCTOSPI2() MODIFY_REG(SYSCFG->MEMRMP, SYSCFG_MEMRMP_MEM_MODE, (SYSCFG_MEMRMP_MEM_MODE_2|SYSCFG_MEMRMP_MEM_MODE_0)) + +#else + +/** @brief QUADSPI mapped at 0x00000000. + */ +#define __HAL_SYSCFG_REMAPMEMORY_QUADSPI() MODIFY_REG(SYSCFG->MEMRMP, SYSCFG_MEMRMP_MEM_MODE, (SYSCFG_MEMRMP_MEM_MODE_2|SYSCFG_MEMRMP_MEM_MODE_1)) + +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +/** + * @brief Return the boot mode as configured by user. + * @retval The boot mode as configured by user. The returned value can be one + * of the following values: + * @arg @ref SYSCFG_BOOT_MAINFLASH + * @arg @ref SYSCFG_BOOT_SYSTEMFLASH + @if STM32L486xx + * @arg @ref SYSCFG_BOOT_FMC + @endif + * @arg @ref SYSCFG_BOOT_SRAM + * @arg @ref SYSCFG_BOOT_QUADSPI + */ +#define __HAL_SYSCFG_GET_BOOT_MODE() READ_BIT(SYSCFG->MEMRMP, SYSCFG_MEMRMP_MEM_MODE) + +/** @brief SRAM2 page 0 to 31 write protection enable macro + * @param __SRAM2WRP__ This parameter can be a combination of values of @ref SYSCFG_SRAM2WRP + * @note Write protection can only be disabled by a system reset + */ +#define __HAL_SYSCFG_SRAM2_WRP_1_31_ENABLE(__SRAM2WRP__) do {assert_param(IS_SYSCFG_SRAM2WRP_PAGE((__SRAM2WRP__)));\ + SET_BIT(SYSCFG->SWPR, (__SRAM2WRP__));\ + }while(0) + +#if defined(SYSCFG_SWPR2_PAGE63) +/** @brief SRAM2 page 32 to 63 write protection enable macro + * @param __SRAM2WRP__ This parameter can be a combination of values of @ref SYSCFG_SRAM2WRP_32_63 + * @note Write protection can only be disabled by a system reset + */ +#define __HAL_SYSCFG_SRAM2_WRP_32_63_ENABLE(__SRAM2WRP__) do {assert_param(IS_SYSCFG_SRAM2WRP_PAGE((__SRAM2WRP__)));\ + SET_BIT(SYSCFG->SWPR2, (__SRAM2WRP__));\ + }while(0) +#endif /* SYSCFG_SWPR2_PAGE63 */ + +/** @brief SRAM2 page write protection unlock prior to erase + * @note Writing a wrong key reactivates the write protection + */ +#define __HAL_SYSCFG_SRAM2_WRP_UNLOCK() do {SYSCFG->SKR = 0xCA;\ + SYSCFG->SKR = 0x53;\ + }while(0) + +/** @brief SRAM2 erase + * @note __SYSCFG_GET_FLAG(SYSCFG_FLAG_SRAM2_BUSY) may be used to check end of erase + */ +#define __HAL_SYSCFG_SRAM2_ERASE() SET_BIT(SYSCFG->SCSR, SYSCFG_SCSR_SRAM2ER) + +/** @brief Floating Point Unit interrupt enable/disable macros + * @param __INTERRUPT__ This parameter can be a value of @ref SYSCFG_FPU_Interrupts + */ +#define __HAL_SYSCFG_FPU_INTERRUPT_ENABLE(__INTERRUPT__) do {assert_param(IS_SYSCFG_FPU_INTERRUPT((__INTERRUPT__)));\ + SET_BIT(SYSCFG->CFGR1, (__INTERRUPT__));\ + }while(0) + +#define __HAL_SYSCFG_FPU_INTERRUPT_DISABLE(__INTERRUPT__) do {assert_param(IS_SYSCFG_FPU_INTERRUPT((__INTERRUPT__)));\ + CLEAR_BIT(SYSCFG->CFGR1, (__INTERRUPT__));\ + }while(0) + +/** @brief SYSCFG Break ECC lock. + * Enable and lock the connection of Flash ECC error connection to TIM1/8/15/16/17 Break input. + * @note The selected configuration is locked and can be unlocked only by system reset. + */ +#define __HAL_SYSCFG_BREAK_ECC_LOCK() SET_BIT(SYSCFG->CFGR2, SYSCFG_CFGR2_ECCL) + +/** @brief SYSCFG Break Cortex-M4 Lockup lock. + * Enable and lock the connection of Cortex-M4 LOCKUP (Hardfault) output to TIM1/8/15/16/17 Break input. + * @note The selected configuration is locked and can be unlocked only by system reset. + */ +#define __HAL_SYSCFG_BREAK_LOCKUP_LOCK() SET_BIT(SYSCFG->CFGR2, SYSCFG_CFGR2_CLL) + +/** @brief SYSCFG Break PVD lock. + * Enable and lock the PVD connection to Timer1/8/15/16/17 Break input, as well as the PVDE and PLS[2:0] in the PWR_CR2 register. + * @note The selected configuration is locked and can be unlocked only by system reset. + */ +#define __HAL_SYSCFG_BREAK_PVD_LOCK() SET_BIT(SYSCFG->CFGR2, SYSCFG_CFGR2_PVDL) + +/** @brief SYSCFG Break SRAM2 parity lock. + * Enable and lock the SRAM2 parity error signal connection to TIM1/8/15/16/17 Break input. + * @note The selected configuration is locked and can be unlocked by system reset. + */ +#define __HAL_SYSCFG_BREAK_SRAM2PARITY_LOCK() SET_BIT(SYSCFG->CFGR2, SYSCFG_CFGR2_SPL) + +/** @brief Check SYSCFG flag is set or not. + * @param __FLAG__ specifies the flag to check. + * This parameter can be one of the following values: + * @arg @ref SYSCFG_FLAG_SRAM2_PE SRAM2 Parity Error Flag + * @arg @ref SYSCFG_FLAG_SRAM2_BUSY SRAM2 Erase Ongoing + * @retval The new state of __FLAG__ (TRUE or FALSE). + */ +#define __HAL_SYSCFG_GET_FLAG(__FLAG__) ((((((__FLAG__) == SYSCFG_SCSR_SRAM2BSY)? SYSCFG->SCSR : SYSCFG->CFGR2) & (__FLAG__))!= 0) ? 1 : 0) + +/** @brief Set the SPF bit to clear the SRAM Parity Error Flag. + */ +#define __HAL_SYSCFG_CLEAR_FLAG() SET_BIT(SYSCFG->CFGR2, SYSCFG_CFGR2_SPF) + +/** @brief Fast-mode Plus driving capability enable/disable macros + * @param __FASTMODEPLUS__ This parameter can be a value of : + * @arg @ref SYSCFG_FASTMODEPLUS_PB6 Fast-mode Plus driving capability activation on PB6 + * @arg @ref SYSCFG_FASTMODEPLUS_PB7 Fast-mode Plus driving capability activation on PB7 + * @arg @ref SYSCFG_FASTMODEPLUS_PB8 Fast-mode Plus driving capability activation on PB8 + * @arg @ref SYSCFG_FASTMODEPLUS_PB9 Fast-mode Plus driving capability activation on PB9 + */ +#define __HAL_SYSCFG_FASTMODEPLUS_ENABLE(__FASTMODEPLUS__) do {assert_param(IS_SYSCFG_FASTMODEPLUS((__FASTMODEPLUS__)));\ + SET_BIT(SYSCFG->CFGR1, (__FASTMODEPLUS__));\ + }while(0) + +#define __HAL_SYSCFG_FASTMODEPLUS_DISABLE(__FASTMODEPLUS__) do {assert_param(IS_SYSCFG_FASTMODEPLUS((__FASTMODEPLUS__)));\ + CLEAR_BIT(SYSCFG->CFGR1, (__FASTMODEPLUS__));\ + }while(0) + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup SYSCFG_Private_Macros SYSCFG Private Macros + * @{ + */ + +#define IS_SYSCFG_FPU_INTERRUPT(__INTERRUPT__) ((((__INTERRUPT__) & SYSCFG_IT_FPU_IOC) == SYSCFG_IT_FPU_IOC) || \ + (((__INTERRUPT__) & SYSCFG_IT_FPU_DZC) == SYSCFG_IT_FPU_DZC) || \ + (((__INTERRUPT__) & SYSCFG_IT_FPU_UFC) == SYSCFG_IT_FPU_UFC) || \ + (((__INTERRUPT__) & SYSCFG_IT_FPU_OFC) == SYSCFG_IT_FPU_OFC) || \ + (((__INTERRUPT__) & SYSCFG_IT_FPU_IDC) == SYSCFG_IT_FPU_IDC) || \ + (((__INTERRUPT__) & SYSCFG_IT_FPU_IXC) == SYSCFG_IT_FPU_IXC)) + +#define IS_SYSCFG_BREAK_CONFIG(__CONFIG__) (((__CONFIG__) == SYSCFG_BREAK_ECC) || \ + ((__CONFIG__) == SYSCFG_BREAK_PVD) || \ + ((__CONFIG__) == SYSCFG_BREAK_SRAM2_PARITY) || \ + ((__CONFIG__) == SYSCFG_BREAK_LOCKUP)) + +#define IS_SYSCFG_SRAM2WRP_PAGE(__PAGE__) (((__PAGE__) > 0) && ((__PAGE__) <= 0xFFFFFFFF)) + +#if defined(VREFBUF) +#define IS_SYSCFG_VREFBUF_VOLTAGE_SCALE(__SCALE__) (((__SCALE__) == SYSCFG_VREFBUF_VOLTAGE_SCALE0) || \ + ((__SCALE__) == SYSCFG_VREFBUF_VOLTAGE_SCALE1)) + +#define IS_SYSCFG_VREFBUF_HIGH_IMPEDANCE(__VALUE__) (((__VALUE__) == SYSCFG_VREFBUF_HIGH_IMPEDANCE_DISABLE) || \ + ((__VALUE__) == SYSCFG_VREFBUF_HIGH_IMPEDANCE_ENABLE)) + +#define IS_SYSCFG_VREFBUF_TRIMMING(__VALUE__) (((__VALUE__) > 0) && ((__VALUE__) <= VREFBUF_CCR_TRIM)) +#endif /* VREFBUF */ + +#if defined(SYSCFG_FASTMODEPLUS_PB8) && defined(SYSCFG_FASTMODEPLUS_PB9) +#define IS_SYSCFG_FASTMODEPLUS(__PIN__) ((((__PIN__) & SYSCFG_FASTMODEPLUS_PB6) == SYSCFG_FASTMODEPLUS_PB6) || \ + (((__PIN__) & SYSCFG_FASTMODEPLUS_PB7) == SYSCFG_FASTMODEPLUS_PB7) || \ + (((__PIN__) & SYSCFG_FASTMODEPLUS_PB8) == SYSCFG_FASTMODEPLUS_PB8) || \ + (((__PIN__) & SYSCFG_FASTMODEPLUS_PB9) == SYSCFG_FASTMODEPLUS_PB9)) +#elif defined(SYSCFG_FASTMODEPLUS_PB8) +#define IS_SYSCFG_FASTMODEPLUS(__PIN__) ((((__PIN__) & SYSCFG_FASTMODEPLUS_PB6) == SYSCFG_FASTMODEPLUS_PB6) || \ + (((__PIN__) & SYSCFG_FASTMODEPLUS_PB7) == SYSCFG_FASTMODEPLUS_PB7) || \ + (((__PIN__) & SYSCFG_FASTMODEPLUS_PB8) == SYSCFG_FASTMODEPLUS_PB8)) +#elif defined(SYSCFG_FASTMODEPLUS_PB9) +#define IS_SYSCFG_FASTMODEPLUS(__PIN__) ((((__PIN__) & SYSCFG_FASTMODEPLUS_PB6) == SYSCFG_FASTMODEPLUS_PB6) || \ + (((__PIN__) & SYSCFG_FASTMODEPLUS_PB7) == SYSCFG_FASTMODEPLUS_PB7) || \ + (((__PIN__) & SYSCFG_FASTMODEPLUS_PB9) == SYSCFG_FASTMODEPLUS_PB9)) +#else +#define IS_SYSCFG_FASTMODEPLUS(__PIN__) ((((__PIN__) & SYSCFG_FASTMODEPLUS_PB6) == SYSCFG_FASTMODEPLUS_PB6) || \ + (((__PIN__) & SYSCFG_FASTMODEPLUS_PB7) == SYSCFG_FASTMODEPLUS_PB7)) +#endif +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ + +/** @addtogroup HAL_Exported_Functions + * @{ + */ + +/** @addtogroup HAL_Exported_Functions_Group1 + * @{ + */ + +/* Initialization and de-initialization functions ******************************/ +HAL_StatusTypeDef HAL_Init(void); +HAL_StatusTypeDef HAL_DeInit(void); +void HAL_MspInit(void); +void HAL_MspDeInit(void); +HAL_StatusTypeDef HAL_InitTick (uint32_t TickPriority); + +/** + * @} + */ + +/** @addtogroup HAL_Exported_Functions_Group2 + * @{ + */ + +/* Peripheral Control functions ************************************************/ +void HAL_IncTick(void); +void HAL_Delay(uint32_t Delay); +uint32_t HAL_GetTick(void); +void HAL_SuspendTick(void); +void HAL_ResumeTick(void); +uint32_t HAL_GetHalVersion(void); +uint32_t HAL_GetREVID(void); +uint32_t HAL_GetDEVID(void); +uint32_t HAL_GetUIDw0(void); +uint32_t HAL_GetUIDw1(void); +uint32_t HAL_GetUIDw2(void); + +/** + * @} + */ + +/** @addtogroup HAL_Exported_Functions_Group3 + * @{ + */ + +/* DBGMCU Peripheral Control functions *****************************************/ +void HAL_DBGMCU_EnableDBGSleepMode(void); +void HAL_DBGMCU_DisableDBGSleepMode(void); +void HAL_DBGMCU_EnableDBGStopMode(void); +void HAL_DBGMCU_DisableDBGStopMode(void); +void HAL_DBGMCU_EnableDBGStandbyMode(void); +void HAL_DBGMCU_DisableDBGStandbyMode(void); + +/** + * @} + */ + +/** @addtogroup HAL_Exported_Functions_Group4 + * @{ + */ + +/* SYSCFG Control functions ****************************************************/ +void HAL_SYSCFG_SRAM2Erase(void); +void HAL_SYSCFG_EnableMemorySwappingBank(void); +void HAL_SYSCFG_DisableMemorySwappingBank(void); + +#if defined(VREFBUF) +void HAL_SYSCFG_VREFBUF_VoltageScalingConfig(uint32_t VoltageScaling); +void HAL_SYSCFG_VREFBUF_HighImpedanceConfig(uint32_t Mode); +void HAL_SYSCFG_VREFBUF_TrimmingConfig(uint32_t TrimmingValue); +HAL_StatusTypeDef HAL_SYSCFG_EnableVREFBUF(void); +void HAL_SYSCFG_DisableVREFBUF(void); +#endif /* VREFBUF */ + +void HAL_SYSCFG_EnableIOAnalogSwitchBooster(void); +void HAL_SYSCFG_DisableIOAnalogSwitchBooster(void); + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_HAL_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_cortex.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_cortex.h new file mode 100644 index 0000000..b6e2e9f --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_cortex.h @@ -0,0 +1,433 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_cortex.h + * @author MCD Application Team + * @brief Header file of CORTEX HAL module. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_CORTEX_H +#define __STM32L4xx_HAL_CORTEX_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup CORTEX CORTEX + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup CORTEX_Exported_Types CORTEX Exported Types + * @{ + */ + +#if (__MPU_PRESENT == 1) +/** @defgroup CORTEX_MPU_Region_Initialization_Structure_definition MPU Region Initialization Structure Definition + * @{ + */ +typedef struct +{ + uint8_t Enable; /*!< Specifies the status of the region. + This parameter can be a value of @ref CORTEX_MPU_Region_Enable */ + uint8_t Number; /*!< Specifies the number of the region to protect. + This parameter can be a value of @ref CORTEX_MPU_Region_Number */ + uint32_t BaseAddress; /*!< Specifies the base address of the region to protect. */ + uint8_t Size; /*!< Specifies the size of the region to protect. + This parameter can be a value of @ref CORTEX_MPU_Region_Size */ + uint8_t SubRegionDisable; /*!< Specifies the number of the subregion protection to disable. + This parameter must be a number between Min_Data = 0x00 and Max_Data = 0xFF */ + uint8_t TypeExtField; /*!< Specifies the TEX field level. + This parameter can be a value of @ref CORTEX_MPU_TEX_Levels */ + uint8_t AccessPermission; /*!< Specifies the region access permission type. + This parameter can be a value of @ref CORTEX_MPU_Region_Permission_Attributes */ + uint8_t DisableExec; /*!< Specifies the instruction access status. + This parameter can be a value of @ref CORTEX_MPU_Instruction_Access */ + uint8_t IsShareable; /*!< Specifies the shareability status of the protected region. + This parameter can be a value of @ref CORTEX_MPU_Access_Shareable */ + uint8_t IsCacheable; /*!< Specifies the cacheable status of the region protected. + This parameter can be a value of @ref CORTEX_MPU_Access_Cacheable */ + uint8_t IsBufferable; /*!< Specifies the bufferable status of the protected region. + This parameter can be a value of @ref CORTEX_MPU_Access_Bufferable */ +}MPU_Region_InitTypeDef; +/** + * @} + */ +#endif /* __MPU_PRESENT */ + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ + +/** @defgroup CORTEX_Exported_Constants CORTEX Exported Constants + * @{ + */ + +/** @defgroup CORTEX_Preemption_Priority_Group CORTEX Preemption Priority Group + * @{ + */ +#define NVIC_PRIORITYGROUP_0 ((uint32_t)0x00000007) /*!< 0 bit for pre-emption priority, + 4 bits for subpriority */ +#define NVIC_PRIORITYGROUP_1 ((uint32_t)0x00000006) /*!< 1 bit for pre-emption priority, + 3 bits for subpriority */ +#define NVIC_PRIORITYGROUP_2 ((uint32_t)0x00000005) /*!< 2 bits for pre-emption priority, + 2 bits for subpriority */ +#define NVIC_PRIORITYGROUP_3 ((uint32_t)0x00000004) /*!< 3 bits for pre-emption priority, + 1 bit for subpriority */ +#define NVIC_PRIORITYGROUP_4 ((uint32_t)0x00000003) /*!< 4 bits for pre-emption priority, + 0 bit for subpriority */ +/** + * @} + */ + +/** @defgroup CORTEX_SysTick_clock_source CORTEX SysTick clock source + * @{ + */ +#define SYSTICK_CLKSOURCE_HCLK_DIV8 ((uint32_t)0x00000000) +#define SYSTICK_CLKSOURCE_HCLK ((uint32_t)0x00000004) +/** + * @} + */ + +#if (__MPU_PRESENT == 1) +/** @defgroup CORTEX_MPU_HFNMI_PRIVDEF_Control CORTEX MPU HFNMI and PRIVILEGED Access control + * @{ + */ +#define MPU_HFNMI_PRIVDEF_NONE ((uint32_t)0x00000000) +#define MPU_HARDFAULT_NMI ((uint32_t)0x00000002) +#define MPU_PRIVILEGED_DEFAULT ((uint32_t)0x00000004) +#define MPU_HFNMI_PRIVDEF ((uint32_t)0x00000006) +/** + * @} + */ + +/** @defgroup CORTEX_MPU_Region_Enable CORTEX MPU Region Enable + * @{ + */ +#define MPU_REGION_ENABLE ((uint8_t)0x01) +#define MPU_REGION_DISABLE ((uint8_t)0x00) +/** + * @} + */ + +/** @defgroup CORTEX_MPU_Instruction_Access CORTEX MPU Instruction Access + * @{ + */ +#define MPU_INSTRUCTION_ACCESS_ENABLE ((uint8_t)0x00) +#define MPU_INSTRUCTION_ACCESS_DISABLE ((uint8_t)0x01) +/** + * @} + */ + +/** @defgroup CORTEX_MPU_Access_Shareable CORTEX MPU Instruction Access Shareable + * @{ + */ +#define MPU_ACCESS_SHAREABLE ((uint8_t)0x01) +#define MPU_ACCESS_NOT_SHAREABLE ((uint8_t)0x00) +/** + * @} + */ + +/** @defgroup CORTEX_MPU_Access_Cacheable CORTEX MPU Instruction Access Cacheable + * @{ + */ +#define MPU_ACCESS_CACHEABLE ((uint8_t)0x01) +#define MPU_ACCESS_NOT_CACHEABLE ((uint8_t)0x00) +/** + * @} + */ + +/** @defgroup CORTEX_MPU_Access_Bufferable CORTEX MPU Instruction Access Bufferable + * @{ + */ +#define MPU_ACCESS_BUFFERABLE ((uint8_t)0x01) +#define MPU_ACCESS_NOT_BUFFERABLE ((uint8_t)0x00) +/** + * @} + */ + +/** @defgroup CORTEX_MPU_TEX_Levels CORTEX MPU TEX Levels + * @{ + */ +#define MPU_TEX_LEVEL0 ((uint8_t)0x00) +#define MPU_TEX_LEVEL1 ((uint8_t)0x01) +#define MPU_TEX_LEVEL2 ((uint8_t)0x02) +/** + * @} + */ + +/** @defgroup CORTEX_MPU_Region_Size CORTEX MPU Region Size + * @{ + */ +#define MPU_REGION_SIZE_32B ((uint8_t)0x04) +#define MPU_REGION_SIZE_64B ((uint8_t)0x05) +#define MPU_REGION_SIZE_128B ((uint8_t)0x06) +#define MPU_REGION_SIZE_256B ((uint8_t)0x07) +#define MPU_REGION_SIZE_512B ((uint8_t)0x08) +#define MPU_REGION_SIZE_1KB ((uint8_t)0x09) +#define MPU_REGION_SIZE_2KB ((uint8_t)0x0A) +#define MPU_REGION_SIZE_4KB ((uint8_t)0x0B) +#define MPU_REGION_SIZE_8KB ((uint8_t)0x0C) +#define MPU_REGION_SIZE_16KB ((uint8_t)0x0D) +#define MPU_REGION_SIZE_32KB ((uint8_t)0x0E) +#define MPU_REGION_SIZE_64KB ((uint8_t)0x0F) +#define MPU_REGION_SIZE_128KB ((uint8_t)0x10) +#define MPU_REGION_SIZE_256KB ((uint8_t)0x11) +#define MPU_REGION_SIZE_512KB ((uint8_t)0x12) +#define MPU_REGION_SIZE_1MB ((uint8_t)0x13) +#define MPU_REGION_SIZE_2MB ((uint8_t)0x14) +#define MPU_REGION_SIZE_4MB ((uint8_t)0x15) +#define MPU_REGION_SIZE_8MB ((uint8_t)0x16) +#define MPU_REGION_SIZE_16MB ((uint8_t)0x17) +#define MPU_REGION_SIZE_32MB ((uint8_t)0x18) +#define MPU_REGION_SIZE_64MB ((uint8_t)0x19) +#define MPU_REGION_SIZE_128MB ((uint8_t)0x1A) +#define MPU_REGION_SIZE_256MB ((uint8_t)0x1B) +#define MPU_REGION_SIZE_512MB ((uint8_t)0x1C) +#define MPU_REGION_SIZE_1GB ((uint8_t)0x1D) +#define MPU_REGION_SIZE_2GB ((uint8_t)0x1E) +#define MPU_REGION_SIZE_4GB ((uint8_t)0x1F) +/** + * @} + */ + +/** @defgroup CORTEX_MPU_Region_Permission_Attributes CORTEX MPU Region Permission Attributes + * @{ + */ +#define MPU_REGION_NO_ACCESS ((uint8_t)0x00) +#define MPU_REGION_PRIV_RW ((uint8_t)0x01) +#define MPU_REGION_PRIV_RW_URO ((uint8_t)0x02) +#define MPU_REGION_FULL_ACCESS ((uint8_t)0x03) +#define MPU_REGION_PRIV_RO ((uint8_t)0x05) +#define MPU_REGION_PRIV_RO_URO ((uint8_t)0x06) +/** + * @} + */ + +/** @defgroup CORTEX_MPU_Region_Number CORTEX MPU Region Number + * @{ + */ +#define MPU_REGION_NUMBER0 ((uint8_t)0x00) +#define MPU_REGION_NUMBER1 ((uint8_t)0x01) +#define MPU_REGION_NUMBER2 ((uint8_t)0x02) +#define MPU_REGION_NUMBER3 ((uint8_t)0x03) +#define MPU_REGION_NUMBER4 ((uint8_t)0x04) +#define MPU_REGION_NUMBER5 ((uint8_t)0x05) +#define MPU_REGION_NUMBER6 ((uint8_t)0x06) +#define MPU_REGION_NUMBER7 ((uint8_t)0x07) +/** + * @} + */ +#endif /* __MPU_PRESENT */ + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ +/** @defgroup CORTEX_Exported_Macros CORTEX Exported Macros + * @{ + */ + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup CORTEX_Exported_Functions CORTEX Exported Functions + * @{ + */ + +/** @defgroup CORTEX_Exported_Functions_Group1 Initialization and Configuration functions + * @brief Initialization and Configuration functions + * @{ + */ +/* Initialization and Configuration functions *****************************/ +void HAL_NVIC_SetPriorityGrouping(uint32_t PriorityGroup); +void HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority); +void HAL_NVIC_EnableIRQ(IRQn_Type IRQn); +void HAL_NVIC_DisableIRQ(IRQn_Type IRQn); +void HAL_NVIC_SystemReset(void); +uint32_t HAL_SYSTICK_Config(uint32_t TicksNumb); + +/** + * @} + */ + +/** @defgroup CORTEX_Exported_Functions_Group2 Peripheral Control functions + * @brief Cortex control functions + * @{ + */ +/* Peripheral Control functions ***********************************************/ +uint32_t HAL_NVIC_GetPriorityGrouping(void); +void HAL_NVIC_GetPriority(IRQn_Type IRQn, uint32_t PriorityGroup, uint32_t* pPreemptPriority, uint32_t* pSubPriority); +uint32_t HAL_NVIC_GetPendingIRQ(IRQn_Type IRQn); +void HAL_NVIC_SetPendingIRQ(IRQn_Type IRQn); +void HAL_NVIC_ClearPendingIRQ(IRQn_Type IRQn); +uint32_t HAL_NVIC_GetActive(IRQn_Type IRQn); +void HAL_SYSTICK_CLKSourceConfig(uint32_t CLKSource); +void HAL_SYSTICK_IRQHandler(void); +void HAL_SYSTICK_Callback(void); + +#if (__MPU_PRESENT == 1) +void HAL_MPU_Enable(uint32_t MPU_Control); +void HAL_MPU_Disable(void); +void HAL_MPU_ConfigRegion(MPU_Region_InitTypeDef *MPU_Init); +#endif /* __MPU_PRESENT */ +/** + * @} + */ + +/** + * @} + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ +/** @defgroup CORTEX_Private_Macros CORTEX Private Macros + * @{ + */ +#define IS_NVIC_PRIORITY_GROUP(GROUP) (((GROUP) == NVIC_PRIORITYGROUP_0) || \ + ((GROUP) == NVIC_PRIORITYGROUP_1) || \ + ((GROUP) == NVIC_PRIORITYGROUP_2) || \ + ((GROUP) == NVIC_PRIORITYGROUP_3) || \ + ((GROUP) == NVIC_PRIORITYGROUP_4)) + +#define IS_NVIC_PREEMPTION_PRIORITY(PRIORITY) ((PRIORITY) < 0x10) + +#define IS_NVIC_SUB_PRIORITY(PRIORITY) ((PRIORITY) < 0x10) + +#define IS_NVIC_DEVICE_IRQ(IRQ) ((IRQ) >= 0x00) + +#define IS_SYSTICK_CLK_SOURCE(SOURCE) (((SOURCE) == SYSTICK_CLKSOURCE_HCLK) || \ + ((SOURCE) == SYSTICK_CLKSOURCE_HCLK_DIV8)) + +#if (__MPU_PRESENT == 1) +#define IS_MPU_REGION_ENABLE(STATE) (((STATE) == MPU_REGION_ENABLE) || \ + ((STATE) == MPU_REGION_DISABLE)) + +#define IS_MPU_INSTRUCTION_ACCESS(STATE) (((STATE) == MPU_INSTRUCTION_ACCESS_ENABLE) || \ + ((STATE) == MPU_INSTRUCTION_ACCESS_DISABLE)) + +#define IS_MPU_ACCESS_SHAREABLE(STATE) (((STATE) == MPU_ACCESS_SHAREABLE) || \ + ((STATE) == MPU_ACCESS_NOT_SHAREABLE)) + +#define IS_MPU_ACCESS_CACHEABLE(STATE) (((STATE) == MPU_ACCESS_CACHEABLE) || \ + ((STATE) == MPU_ACCESS_NOT_CACHEABLE)) + +#define IS_MPU_ACCESS_BUFFERABLE(STATE) (((STATE) == MPU_ACCESS_BUFFERABLE) || \ + ((STATE) == MPU_ACCESS_NOT_BUFFERABLE)) + +#define IS_MPU_TEX_LEVEL(TYPE) (((TYPE) == MPU_TEX_LEVEL0) || \ + ((TYPE) == MPU_TEX_LEVEL1) || \ + ((TYPE) == MPU_TEX_LEVEL2)) + +#define IS_MPU_REGION_PERMISSION_ATTRIBUTE(TYPE) (((TYPE) == MPU_REGION_NO_ACCESS) || \ + ((TYPE) == MPU_REGION_PRIV_RW) || \ + ((TYPE) == MPU_REGION_PRIV_RW_URO) || \ + ((TYPE) == MPU_REGION_FULL_ACCESS) || \ + ((TYPE) == MPU_REGION_PRIV_RO) || \ + ((TYPE) == MPU_REGION_PRIV_RO_URO)) + +#define IS_MPU_REGION_NUMBER(NUMBER) (((NUMBER) == MPU_REGION_NUMBER0) || \ + ((NUMBER) == MPU_REGION_NUMBER1) || \ + ((NUMBER) == MPU_REGION_NUMBER2) || \ + ((NUMBER) == MPU_REGION_NUMBER3) || \ + ((NUMBER) == MPU_REGION_NUMBER4) || \ + ((NUMBER) == MPU_REGION_NUMBER5) || \ + ((NUMBER) == MPU_REGION_NUMBER6) || \ + ((NUMBER) == MPU_REGION_NUMBER7)) + +#define IS_MPU_REGION_SIZE(SIZE) (((SIZE) == MPU_REGION_SIZE_32B) || \ + ((SIZE) == MPU_REGION_SIZE_64B) || \ + ((SIZE) == MPU_REGION_SIZE_128B) || \ + ((SIZE) == MPU_REGION_SIZE_256B) || \ + ((SIZE) == MPU_REGION_SIZE_512B) || \ + ((SIZE) == MPU_REGION_SIZE_1KB) || \ + ((SIZE) == MPU_REGION_SIZE_2KB) || \ + ((SIZE) == MPU_REGION_SIZE_4KB) || \ + ((SIZE) == MPU_REGION_SIZE_8KB) || \ + ((SIZE) == MPU_REGION_SIZE_16KB) || \ + ((SIZE) == MPU_REGION_SIZE_32KB) || \ + ((SIZE) == MPU_REGION_SIZE_64KB) || \ + ((SIZE) == MPU_REGION_SIZE_128KB) || \ + ((SIZE) == MPU_REGION_SIZE_256KB) || \ + ((SIZE) == MPU_REGION_SIZE_512KB) || \ + ((SIZE) == MPU_REGION_SIZE_1MB) || \ + ((SIZE) == MPU_REGION_SIZE_2MB) || \ + ((SIZE) == MPU_REGION_SIZE_4MB) || \ + ((SIZE) == MPU_REGION_SIZE_8MB) || \ + ((SIZE) == MPU_REGION_SIZE_16MB) || \ + ((SIZE) == MPU_REGION_SIZE_32MB) || \ + ((SIZE) == MPU_REGION_SIZE_64MB) || \ + ((SIZE) == MPU_REGION_SIZE_128MB) || \ + ((SIZE) == MPU_REGION_SIZE_256MB) || \ + ((SIZE) == MPU_REGION_SIZE_512MB) || \ + ((SIZE) == MPU_REGION_SIZE_1GB) || \ + ((SIZE) == MPU_REGION_SIZE_2GB) || \ + ((SIZE) == MPU_REGION_SIZE_4GB)) + +#define IS_MPU_SUB_REGION_DISABLE(SUBREGION) ((SUBREGION) < (uint16_t)0x00FF) +#endif /* __MPU_PRESENT */ + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_HAL_CORTEX_H */ + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_def.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_def.h new file mode 100644 index 0000000..bb9816b --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_def.h @@ -0,0 +1,213 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_def.h + * @author MCD Application Team + * @brief This file contains HAL common defines, enumeration, macros and + * structures definitions. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_DEF +#define __STM32L4xx_HAL_DEF + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx.h" +#include "Legacy/stm32_hal_legacy.h" /* Aliases file for old names compatibility */ +#include + +/* Exported types ------------------------------------------------------------*/ + +/** + * @brief HAL Status structures definition + */ +typedef enum +{ + HAL_OK = 0x00, + HAL_ERROR = 0x01, + HAL_BUSY = 0x02, + HAL_TIMEOUT = 0x03 +} HAL_StatusTypeDef; + +/** + * @brief HAL Lock structures definition + */ +typedef enum +{ + HAL_UNLOCKED = 0x00, + HAL_LOCKED = 0x01 +} HAL_LockTypeDef; + +/* Exported macros -----------------------------------------------------------*/ + +#define HAL_MAX_DELAY 0xFFFFFFFFU + +#define HAL_IS_BIT_SET(REG, BIT) (((REG) & (BIT)) == (BIT)) +#define HAL_IS_BIT_CLR(REG, BIT) (((REG) & (BIT)) == RESET) + +#define __HAL_LINKDMA(__HANDLE__, __PPP_DMA_FIELD__, __DMA_HANDLE__) \ + do{ \ + (__HANDLE__)->__PPP_DMA_FIELD__ = &(__DMA_HANDLE__); \ + (__DMA_HANDLE__).Parent = (__HANDLE__); \ + } while(0) + +#define UNUSED(x) ((void)(x)) + +/** @brief Reset the Handle's State field. + * @param __HANDLE__: specifies the Peripheral Handle. + * @note This macro can be used for the following purpose: + * - When the Handle is declared as local variable; before passing it as parameter + * to HAL_PPP_Init() for the first time, it is mandatory to use this macro + * to set to 0 the Handle's "State" field. + * Otherwise, "State" field may have any random value and the first time the function + * HAL_PPP_Init() is called, the low level hardware initialization will be missed + * (i.e. HAL_PPP_MspInit() will not be executed). + * - When there is a need to reconfigure the low level hardware: instead of calling + * HAL_PPP_DeInit() then HAL_PPP_Init(), user can make a call to this macro then HAL_PPP_Init(). + * In this later function, when the Handle's "State" field is set to 0, it will execute the function + * HAL_PPP_MspInit() which will reconfigure the low level hardware. + * @retval None + */ +#define __HAL_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = 0) + +#if (USE_RTOS == 1) + /* Reserved for future use */ + #error " USE_RTOS should be 0 in the current HAL release " +#else + #define __HAL_LOCK(__HANDLE__) \ + do{ \ + if((__HANDLE__)->Lock == HAL_LOCKED) \ + { \ + return HAL_BUSY; \ + } \ + else \ + { \ + (__HANDLE__)->Lock = HAL_LOCKED; \ + } \ + }while (0) + + #define __HAL_UNLOCK(__HANDLE__) \ + do{ \ + (__HANDLE__)->Lock = HAL_UNLOCKED; \ + }while (0) +#endif /* USE_RTOS */ + +#if defined ( __GNUC__ ) && !defined (__CC_ARM) /* GNU Compiler */ + #ifndef __weak + #define __weak __attribute__((weak)) + #endif /* __weak */ + #ifndef __packed + #define __packed __attribute__((__packed__)) + #endif /* __packed */ +#endif /* __GNUC__ */ + + +/* Macro to get variable aligned on 4-bytes, for __ICCARM__ the directive "#pragma data_alignment=4" must be used instead */ +#if defined ( __GNUC__ ) && !defined (__CC_ARM) /* GNU Compiler */ + #ifndef __ALIGN_END + #define __ALIGN_END __attribute__ ((aligned (4))) + #endif /* __ALIGN_END */ + #ifndef __ALIGN_BEGIN + #define __ALIGN_BEGIN + #endif /* __ALIGN_BEGIN */ +#else + #ifndef __ALIGN_END + #define __ALIGN_END + #endif /* __ALIGN_END */ + #ifndef __ALIGN_BEGIN + #if defined (__CC_ARM) /* ARM Compiler */ + #define __ALIGN_BEGIN __align(4) + #elif defined (__ICCARM__) /* IAR Compiler */ + #define __ALIGN_BEGIN + #endif /* __CC_ARM */ + #endif /* __ALIGN_BEGIN */ +#endif /* __GNUC__ */ + +/** + * @brief __RAM_FUNC definition + */ +#if defined ( __CC_ARM ) +/* ARM Compiler + ------------ + RAM functions are defined using the toolchain options. + Functions that are executed in RAM should reside in a separate source module. + Using the 'Options for File' dialog you can simply change the 'Code / Const' + area of a module to a memory space in physical RAM. + Available memory areas are declared in the 'Target' tab of the 'Options for Target' + dialog. +*/ +#define __RAM_FUNC HAL_StatusTypeDef + +#elif defined ( __ICCARM__ ) +/* ICCARM Compiler + --------------- + RAM functions are defined using a specific toolchain keyword "__ramfunc". +*/ +#define __RAM_FUNC __ramfunc HAL_StatusTypeDef + +#elif defined ( __GNUC__ ) +/* GNU Compiler + ------------ + RAM functions are defined using a specific toolchain attribute + "__attribute__((section(".RamFunc")))". +*/ +#define __RAM_FUNC HAL_StatusTypeDef __attribute__((section(".RamFunc"))) + +#endif + +/** + * @brief __NOINLINE definition + */ +#if defined ( __CC_ARM ) || defined ( __GNUC__ ) +/* ARM & GNUCompiler + ---------------- +*/ +#define __NOINLINE __attribute__ ( (noinline) ) + +#elif defined ( __ICCARM__ ) +/* ICCARM Compiler + --------------- +*/ +#define __NOINLINE _Pragma("optimize = no_inline") + +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* ___STM32L4xx_HAL_DEF */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_dma.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_dma.h new file mode 100644 index 0000000..c11a47c --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_dma.h @@ -0,0 +1,766 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_dma.h + * @author MCD Application Team + * @brief Header file of DMA HAL module. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_DMA_H +#define __STM32L4xx_HAL_DMA_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup DMA + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup DMA_Exported_Types DMA Exported Types + * @{ + */ + +/** + * @brief DMA Configuration Structure definition + */ +typedef struct +{ + uint32_t Request; /*!< Specifies the request selected for the specified channel. + This parameter can be a value of @ref DMA_request */ + + uint32_t Direction; /*!< Specifies if the data will be transferred from memory to peripheral, + from memory to memory or from peripheral to memory. + This parameter can be a value of @ref DMA_Data_transfer_direction */ + + uint32_t PeriphInc; /*!< Specifies whether the Peripheral address register should be incremented or not. + This parameter can be a value of @ref DMA_Peripheral_incremented_mode */ + + uint32_t MemInc; /*!< Specifies whether the memory address register should be incremented or not. + This parameter can be a value of @ref DMA_Memory_incremented_mode */ + + uint32_t PeriphDataAlignment; /*!< Specifies the Peripheral data width. + This parameter can be a value of @ref DMA_Peripheral_data_size */ + + uint32_t MemDataAlignment; /*!< Specifies the Memory data width. + This parameter can be a value of @ref DMA_Memory_data_size */ + + uint32_t Mode; /*!< Specifies the operation mode of the DMAy Channelx. + This parameter can be a value of @ref DMA_mode + @note The circular buffer mode cannot be used if the memory-to-memory + data transfer is configured on the selected Channel */ + + uint32_t Priority; /*!< Specifies the software priority for the DMAy Channelx. + This parameter can be a value of @ref DMA_Priority_level */ +} DMA_InitTypeDef; + +/** + * @brief HAL DMA State structures definition + */ +typedef enum +{ + HAL_DMA_STATE_RESET = 0x00, /*!< DMA not yet initialized or disabled */ + HAL_DMA_STATE_READY = 0x01, /*!< DMA initialized and ready for use */ + HAL_DMA_STATE_BUSY = 0x02, /*!< DMA process is ongoing */ + HAL_DMA_STATE_TIMEOUT = 0x03, /*!< DMA timeout state */ +}HAL_DMA_StateTypeDef; + +/** + * @brief HAL DMA Error Code structure definition + */ +typedef enum +{ + HAL_DMA_FULL_TRANSFER = 0x00, /*!< Full transfer */ + HAL_DMA_HALF_TRANSFER = 0x01 /*!< Half Transfer */ +}HAL_DMA_LevelCompleteTypeDef; + + +/** + * @brief HAL DMA Callback ID structure definition + */ +typedef enum +{ + HAL_DMA_XFER_CPLT_CB_ID = 0x00, /*!< Full transfer */ + HAL_DMA_XFER_HALFCPLT_CB_ID = 0x01, /*!< Half transfer */ + HAL_DMA_XFER_ERROR_CB_ID = 0x02, /*!< Error */ + HAL_DMA_XFER_ABORT_CB_ID = 0x03, /*!< Abort */ + HAL_DMA_XFER_ALL_CB_ID = 0x04 /*!< All */ + +}HAL_DMA_CallbackIDTypeDef; + +/** + * @brief DMA handle Structure definition + */ +typedef struct __DMA_HandleTypeDef +{ + DMA_Channel_TypeDef *Instance; /*!< Register base address */ + + DMA_InitTypeDef Init; /*!< DMA communication parameters */ + + HAL_LockTypeDef Lock; /*!< DMA locking object */ + + __IO HAL_DMA_StateTypeDef State; /*!< DMA transfer state */ + + void *Parent; /*!< Parent object state */ + + void (* XferCpltCallback)(struct __DMA_HandleTypeDef * hdma); /*!< DMA transfer complete callback */ + + void (* XferHalfCpltCallback)(struct __DMA_HandleTypeDef * hdma); /*!< DMA Half transfer complete callback */ + + void (* XferErrorCallback)(struct __DMA_HandleTypeDef * hdma); /*!< DMA transfer error callback */ + + void (* XferAbortCallback)( struct __DMA_HandleTypeDef * hdma); /*!< DMA transfer abort callback */ + + __IO uint32_t ErrorCode; /*!< DMA Error code */ + + DMA_TypeDef *DmaBaseAddress; /*!< DMA Channel Base Address */ + + uint32_t ChannelIndex; /*!< DMA Channel Index */ + +#if defined(DMAMUX1) + DMAMUX_Channel_TypeDef *DMAmuxChannel; /*!< Register base address */ + + DMAMUX_ChannelStatus_TypeDef *DMAmuxChannelStatus; /*!< DMAMUX Channels Status Base Address */ + + uint32_t DMAmuxChannelStatusMask; /*!< DMAMUX Channel Status Mask */ + + DMAMUX_RequestGen_TypeDef *DMAmuxRequestGen; /*!< DMAMUX request generator Base Address */ + + DMAMUX_RequestGenStatus_TypeDef *DMAmuxRequestGenStatus; /*!< DMAMUX request generator Address */ + + uint32_t DMAmuxRequestGenStatusMask; /*!< DMAMUX request generator Status mask */ + +#endif /* DMAMUX1 */ + +}DMA_HandleTypeDef; +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ + +/** @defgroup DMA_Exported_Constants DMA Exported Constants + * @{ + */ + +/** @defgroup DMA_Error_Code DMA Error Code + * @{ + */ +#define HAL_DMA_ERROR_NONE ((uint32_t)0x00000000U) /*!< No error */ +#define HAL_DMA_ERROR_TE ((uint32_t)0x00000001U) /*!< Transfer error */ +#define HAL_DMA_ERROR_NO_XFER ((uint32_t)0x00000004U) /*!< Abort requested with no Xfer ongoing */ +#define HAL_DMA_ERROR_TIMEOUT ((uint32_t)0x00000020U) /*!< Timeout error */ +#define HAL_DMA_ERROR_NOT_SUPPORTED ((uint32_t)0x00000100U) /*!< Not supported mode */ +#define HAL_DMA_ERROR_SYNC ((uint32_t)0x00000200U) /*!< DMAMUX sync overrun error */ +#define HAL_DMA_ERROR_REQGEN ((uint32_t)0x00000400U) /*!< DMAMUX request generator overrun error */ + +/** + * @} + */ + +/** @defgroup DMA_request DMA request + * @{ + */ +#if !defined (DMAMUX1) + +#define DMA_REQUEST_0 ((uint32_t)0x00000000) +#define DMA_REQUEST_1 ((uint32_t)0x00000001) +#define DMA_REQUEST_2 ((uint32_t)0x00000002) +#define DMA_REQUEST_3 ((uint32_t)0x00000003) +#define DMA_REQUEST_4 ((uint32_t)0x00000004) +#define DMA_REQUEST_5 ((uint32_t)0x00000005) +#define DMA_REQUEST_6 ((uint32_t)0x00000006) +#define DMA_REQUEST_7 ((uint32_t)0x00000007) + +#endif + +#if defined(DMAMUX1) + +#define DMA_REQUEST_MEM2MEM 0U /*!< memory to memory transfer */ + +#define DMA_REQUEST_GENERATOR0 1U /*!< DMAMUX1 request generator 0 */ +#define DMA_REQUEST_GENERATOR1 2U /*!< DMAMUX1 request generator 1 */ +#define DMA_REQUEST_GENERATOR2 3U /*!< DMAMUX1 request generator 2 */ +#define DMA_REQUEST_GENERATOR3 4U /*!< DMAMUX1 request generator 3 */ + +#define DMA_REQUEST_ADC1 5U /*!< DMAMUX1 ADC1 request */ + +#define DMA_REQUEST_DAC1_CH1 6U /*!< DMAMUX1 DAC1 CH1 request */ +#define DMA_REQUEST_DAC1_CH2 7U /*!< DMAMUX1 DAC1 CH2 request */ + +#define DMA_REQUEST_TIM6_UP 8U /*!< DMAMUX1 TIM6 UP request */ +#define DMA_REQUEST_TIM7_UP 9U /*!< DMAMUX1 TIM7 UP request */ + +#define DMA_REQUEST_SPI1_RX 10U /*!< DMAMUX1 SPI1 RX request */ +#define DMA_REQUEST_SPI1_TX 11U /*!< DMAMUX1 SPI1 TX request */ +#define DMA_REQUEST_SPI2_RX 12U /*!< DMAMUX1 SPI2 RX request */ +#define DMA_REQUEST_SPI2_TX 13U /*!< DMAMUX1 SPI2 TX request */ +#define DMA_REQUEST_SPI3_RX 14U /*!< DMAMUX1 SPI3 RX request */ +#define DMA_REQUEST_SPI3_TX 15U /*!< DMAMUX1 SPI3 TX request */ + +#define DMA_REQUEST_I2C1_RX 16U /*!< DMAMUX1 I2C1 RX request */ +#define DMA_REQUEST_I2C1_TX 17U /*!< DMAMUX1 I2C1 TX request */ +#define DMA_REQUEST_I2C2_RX 18U /*!< DMAMUX1 I2C2 RX request */ +#define DMA_REQUEST_I2C2_TX 19U /*!< DMAMUX1 I2C2 TX request */ +#define DMA_REQUEST_I2C3_RX 20U /*!< DMAMUX1 I2C3 RX request */ +#define DMA_REQUEST_I2C3_TX 21U /*!< DMAMUX1 I2C3 TX request */ +#define DMA_REQUEST_I2C4_RX 22U /*!< DMAMUX1 I2C4 RX request */ +#define DMA_REQUEST_I2C4_TX 23U /*!< DMAMUX1 I2C4 TX request */ + +#define DMA_REQUEST_USART1_RX 24U /*!< DMAMUX1 USART1 RX request */ +#define DMA_REQUEST_USART1_TX 25U /*!< DMAMUX1 USART1 TX request */ +#define DMA_REQUEST_USART2_RX 26U /*!< DMAMUX1 USART2 RX request */ +#define DMA_REQUEST_USART2_TX 27U /*!< DMAMUX1 USART2 TX request */ +#define DMA_REQUEST_USART3_RX 28U /*!< DMAMUX1 USART3 RX request */ +#define DMA_REQUEST_USART3_TX 29U /*!< DMAMUX1 USART3 TX request */ + +#define DMA_REQUEST_UART4_RX 30U /*!< DMAMUX1 UART4 RX request */ +#define DMA_REQUEST_UART4_TX 31U /*!< DMAMUX1 UART4 TX request */ +#define DMA_REQUEST_UART5_RX 32U /*!< DMAMUX1 UART5 RX request */ +#define DMA_REQUEST_UART5_TX 33U /*!< DMAMUX1 UART5 TX request */ + +#define DMA_REQUEST_LPUART1_RX 34U /*!< DMAMUX1 LP_UART1_RX request */ +#define DMA_REQUEST_LPUART1_TX 35U /*!< DMAMUX1 LP_UART1_RX request */ + +#define DMA_REQUEST_SAI1_A 36U /*!< DMAMUX1 SAI1 A request */ +#define DMA_REQUEST_SAI1_B 37U /*!< DMAMUX1 SAI1 B request */ +#define DMA_REQUEST_SAI2_A 38U /*!< DMAMUX1 SAI2 A request */ +#define DMA_REQUEST_SAI2_B 39U /*!< DMAMUX1 SAI2 B request */ + +#define DMA_REQUEST_OCTOSPI1 40U /*!< DMAMUX1 OCTOSPI1 request */ +#define DMA_REQUEST_OCTOSPI2 41U /*!< DMAMUX1 OCTOSPI2 request */ + +#define DMA_REQUEST_TIM1_CH1 42U /*!< DMAMUX1 TIM1 CH1 request */ +#define DMA_REQUEST_TIM1_CH2 43U /*!< DMAMUX1 TIM1 CH2 request */ +#define DMA_REQUEST_TIM1_CH3 44U /*!< DMAMUX1 TIM1 CH3 request */ +#define DMA_REQUEST_TIM1_CH4 45U /*!< DMAMUX1 TIM1 CH4 request */ +#define DMA_REQUEST_TIM1_UP 46U /*!< DMAMUX1 TIM1 UP request */ +#define DMA_REQUEST_TIM1_TRIG 47U /*!< DMAMUX1 TIM1 TRIG request */ +#define DMA_REQUEST_TIM1_COM 48U /*!< DMAMUX1 TIM1 COM request */ + +#define DMA_REQUEST_TIM8_CH1 49U /*!< DMAMUX1 TIM8 CH1 request */ +#define DMA_REQUEST_TIM8_CH2 50U /*!< DMAMUX1 TIM8 CH2 request */ +#define DMA_REQUEST_TIM8_CH3 51U /*!< DMAMUX1 TIM8 CH3 request */ +#define DMA_REQUEST_TIM8_CH4 52U /*!< DMAMUX1 TIM8 CH4 request */ +#define DMA_REQUEST_TIM8_UP 53U /*!< DMAMUX1 TIM8 UP request */ +#define DMA_REQUEST_TIM8_TRIG 54U /*!< DMAMUX1 TIM8 TRIG request */ +#define DMA_REQUEST_TIM8_COM 55U /*!< DMAMUX1 TIM8 COM request */ + +#define DMA_REQUEST_TIM2_CH1 56U /*!< DMAMUX1 TIM2 CH1 request */ +#define DMA_REQUEST_TIM2_CH2 57U /*!< DMAMUX1 TIM2 CH2 request */ +#define DMA_REQUEST_TIM2_CH3 58U /*!< DMAMUX1 TIM2 CH3 request */ +#define DMA_REQUEST_TIM2_CH4 59U /*!< DMAMUX1 TIM2 CH4 request */ +#define DMA_REQUEST_TIM2_UP 60U /*!< DMAMUX1 TIM2 UP request */ + +#define DMA_REQUEST_TIM3_CH1 61U /*!< DMAMUX1 TIM3 CH1 request */ +#define DMA_REQUEST_TIM3_CH2 62U /*!< DMAMUX1 TIM3 CH2 request */ +#define DMA_REQUEST_TIM3_CH3 63U /*!< DMAMUX1 TIM3 CH3 request */ +#define DMA_REQUEST_TIM3_CH4 64U /*!< DMAMUX1 TIM3 CH4 request */ +#define DMA_REQUEST_TIM3_UP 65U /*!< DMAMUX1 TIM3 UP request */ +#define DMA_REQUEST_TIM3_TRIG 66U /*!< DMAMUX1 TIM3 TRIG request */ + +#define DMA_REQUEST_TIM4_CH1 67U /*!< DMAMUX1 TIM4 CH1 request */ +#define DMA_REQUEST_TIM4_CH2 68U /*!< DMAMUX1 TIM4 CH2 request */ +#define DMA_REQUEST_TIM4_CH3 69U /*!< DMAMUX1 TIM4 CH3 request */ +#define DMA_REQUEST_TIM4_CH4 70U /*!< DMAMUX1 TIM4 CH4 request */ +#define DMA_REQUEST_TIM4_UP 71U /*!< DMAMUX1 TIM4 UP request */ + +#define DMA_REQUEST_TIM5_CH1 72U /*!< DMAMUX1 TIM5 CH1 request */ +#define DMA_REQUEST_TIM5_CH2 73U /*!< DMAMUX1 TIM5 CH2 request */ +#define DMA_REQUEST_TIM5_CH3 74U /*!< DMAMUX1 TIM5 CH3 request */ +#define DMA_REQUEST_TIM5_CH4 75U /*!< DMAMUX1 TIM5 CH4 request */ +#define DMA_REQUEST_TIM5_UP 76U /*!< DMAMUX1 TIM5 UP request */ +#define DMA_REQUEST_TIM5_TRIG 77U /*!< DMAMUX1 TIM5 TRIG request */ + +#define DMA_REQUEST_TIM15_CH1 78U /*!< DMAMUX1 TIM15 CH1 request */ +#define DMA_REQUEST_TIM15_UP 79U /*!< DMAMUX1 TIM15 UP request */ +#define DMA_REQUEST_TIM15_TRIG 80U /*!< DMAMUX1 TIM15 TRIG request */ +#define DMA_REQUEST_TIM15_COM 81U /*!< DMAMUX1 TIM15 COM request */ + +#define DMA_REQUEST_TIM16_CH1 82U /*!< DMAMUX1 TIM16 CH1 request */ +#define DMA_REQUEST_TIM16_UP 83U /*!< DMAMUX1 TIM16 UP request */ +#define DMA_REQUEST_TIM17_CH1 84U /*!< DMAMUX1 TIM17 CH1 request */ +#define DMA_REQUEST_TIM17_UP 85U /*!< DMAMUX1 TIM17 UP request */ + +#define DMA_REQUEST_DFSDM1_FLT0 86U /*!< DMAMUX1 DFSDM1 Filter0 request */ +#define DMA_REQUEST_DFSDM1_FLT1 87U /*!< DMAMUX1 DFSDM1 Filter1 request */ +#define DMA_REQUEST_DFSDM1_FLT2 88U /*!< DMAMUX1 DFSDM1 Filter2 request */ +#define DMA_REQUEST_DFSDM1_FLT3 89U /*!< DMAMUX1 DFSDM1 Filter3 request */ + +#define DMA_REQUEST_DCMI 90U /*!< DMAMUX1 DCMI request */ + +#define DMA_REQUEST_AES_IN 91U /*!< DMAMUX1 AES IN request */ +#define DMA_REQUEST_AES_OUT 92U /*!< DMAMUX1 AES OUT request */ + +#define DMA_REQUEST_HASH_IN 93U /*!< DMAMUX1 HASH IN request */ + +#endif /* DMAMUX1 */ + +/** + * @} + */ + +/** @defgroup DMA_Data_transfer_direction DMA Data transfer direction + * @{ + */ +#define DMA_PERIPH_TO_MEMORY ((uint32_t)0x00000000) /*!< Peripheral to memory direction */ +#define DMA_MEMORY_TO_PERIPH ((uint32_t)DMA_CCR_DIR) /*!< Memory to peripheral direction */ +#define DMA_MEMORY_TO_MEMORY ((uint32_t)DMA_CCR_MEM2MEM) /*!< Memory to memory direction */ +/** + * @} + */ + +/** @defgroup DMA_Peripheral_incremented_mode DMA Peripheral incremented mode + * @{ + */ +#define DMA_PINC_ENABLE ((uint32_t)DMA_CCR_PINC) /*!< Peripheral increment mode Enable */ +#define DMA_PINC_DISABLE ((uint32_t)0x00000000) /*!< Peripheral increment mode Disable */ +/** + * @} + */ + +/** @defgroup DMA_Memory_incremented_mode DMA Memory incremented mode + * @{ + */ +#define DMA_MINC_ENABLE ((uint32_t)DMA_CCR_MINC) /*!< Memory increment mode Enable */ +#define DMA_MINC_DISABLE ((uint32_t)0x00000000) /*!< Memory increment mode Disable */ +/** + * @} + */ + +/** @defgroup DMA_Peripheral_data_size DMA Peripheral data size + * @{ + */ +#define DMA_PDATAALIGN_BYTE ((uint32_t)0x00000000) /*!< Peripheral data alignment : Byte */ +#define DMA_PDATAALIGN_HALFWORD ((uint32_t)DMA_CCR_PSIZE_0) /*!< Peripheral data alignment : HalfWord */ +#define DMA_PDATAALIGN_WORD ((uint32_t)DMA_CCR_PSIZE_1) /*!< Peripheral data alignment : Word */ +/** + * @} + */ + +/** @defgroup DMA_Memory_data_size DMA Memory data size + * @{ + */ +#define DMA_MDATAALIGN_BYTE ((uint32_t)0x00000000) /*!< Memory data alignment : Byte */ +#define DMA_MDATAALIGN_HALFWORD ((uint32_t)DMA_CCR_MSIZE_0) /*!< Memory data alignment : HalfWord */ +#define DMA_MDATAALIGN_WORD ((uint32_t)DMA_CCR_MSIZE_1) /*!< Memory data alignment : Word */ +/** + * @} + */ + +/** @defgroup DMA_mode DMA mode + * @{ + */ +#define DMA_NORMAL ((uint32_t)0x00000000) /*!< Normal mode */ +#define DMA_CIRCULAR ((uint32_t)DMA_CCR_CIRC) /*!< Circular mode */ +/** + * @} + */ + +/** @defgroup DMA_Priority_level DMA Priority level + * @{ + */ +#define DMA_PRIORITY_LOW ((uint32_t)0x00000000) /*!< Priority level : Low */ +#define DMA_PRIORITY_MEDIUM ((uint32_t)DMA_CCR_PL_0) /*!< Priority level : Medium */ +#define DMA_PRIORITY_HIGH ((uint32_t)DMA_CCR_PL_1) /*!< Priority level : High */ +#define DMA_PRIORITY_VERY_HIGH ((uint32_t)DMA_CCR_PL) /*!< Priority level : Very_High */ +/** + * @} + */ + + +/** @defgroup DMA_interrupt_enable_definitions DMA interrupt enable definitions + * @{ + */ +#define DMA_IT_TC ((uint32_t)DMA_CCR_TCIE) +#define DMA_IT_HT ((uint32_t)DMA_CCR_HTIE) +#define DMA_IT_TE ((uint32_t)DMA_CCR_TEIE) +/** + * @} + */ + +/** @defgroup DMA_flag_definitions DMA flag definitions + * @{ + */ +#define DMA_FLAG_GL1 ((uint32_t)0x00000001) +#define DMA_FLAG_TC1 ((uint32_t)0x00000002) +#define DMA_FLAG_HT1 ((uint32_t)0x00000004) +#define DMA_FLAG_TE1 ((uint32_t)0x00000008) +#define DMA_FLAG_GL2 ((uint32_t)0x00000010) +#define DMA_FLAG_TC2 ((uint32_t)0x00000020) +#define DMA_FLAG_HT2 ((uint32_t)0x00000040) +#define DMA_FLAG_TE2 ((uint32_t)0x00000080) +#define DMA_FLAG_GL3 ((uint32_t)0x00000100) +#define DMA_FLAG_TC3 ((uint32_t)0x00000200) +#define DMA_FLAG_HT3 ((uint32_t)0x00000400) +#define DMA_FLAG_TE3 ((uint32_t)0x00000800) +#define DMA_FLAG_GL4 ((uint32_t)0x00001000) +#define DMA_FLAG_TC4 ((uint32_t)0x00002000) +#define DMA_FLAG_HT4 ((uint32_t)0x00004000) +#define DMA_FLAG_TE4 ((uint32_t)0x00008000) +#define DMA_FLAG_GL5 ((uint32_t)0x00010000) +#define DMA_FLAG_TC5 ((uint32_t)0x00020000) +#define DMA_FLAG_HT5 ((uint32_t)0x00040000) +#define DMA_FLAG_TE5 ((uint32_t)0x00080000) +#define DMA_FLAG_GL6 ((uint32_t)0x00100000) +#define DMA_FLAG_TC6 ((uint32_t)0x00200000) +#define DMA_FLAG_HT6 ((uint32_t)0x00400000) +#define DMA_FLAG_TE6 ((uint32_t)0x00800000) +#define DMA_FLAG_GL7 ((uint32_t)0x01000000) +#define DMA_FLAG_TC7 ((uint32_t)0x02000000) +#define DMA_FLAG_HT7 ((uint32_t)0x04000000) +#define DMA_FLAG_TE7 ((uint32_t)0x08000000) +/** + * @} + */ + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ +/** @defgroup DMA_Exported_Macros DMA Exported Macros + * @{ + */ + +/** @brief Reset DMA handle state. + * @param __HANDLE__: DMA handle + * @retval None + */ +#define __HAL_DMA_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_DMA_STATE_RESET) + +/** + * @brief Enable the specified DMA Channel. + * @param __HANDLE__: DMA handle + * @retval None + */ +#define __HAL_DMA_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CCR |= DMA_CCR_EN) + +/** + * @brief Disable the specified DMA Channel. + * @param __HANDLE__: DMA handle + * @retval None + */ +#define __HAL_DMA_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CCR &= ~DMA_CCR_EN) + + +/* Interrupt & Flag management */ + +/** + * @brief Return the current DMA Channel transfer complete flag. + * @param __HANDLE__: DMA handle + * @retval The specified transfer complete flag index. + */ + +#define __HAL_DMA_GET_TC_FLAG_INDEX(__HANDLE__) \ +(((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel1))? DMA_FLAG_TC1 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel1))? DMA_FLAG_TC1 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel2))? DMA_FLAG_TC2 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel2))? DMA_FLAG_TC2 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel3))? DMA_FLAG_TC3 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel3))? DMA_FLAG_TC3 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel4))? DMA_FLAG_TC4 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel4))? DMA_FLAG_TC4 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel5))? DMA_FLAG_TC5 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel5))? DMA_FLAG_TC5 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel6))? DMA_FLAG_TC6 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel6))? DMA_FLAG_TC6 :\ + DMA_FLAG_TC7) + +/** + * @brief Return the current DMA Channel half transfer complete flag. + * @param __HANDLE__: DMA handle + * @retval The specified half transfer complete flag index. + */ +#define __HAL_DMA_GET_HT_FLAG_INDEX(__HANDLE__)\ +(((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel1))? DMA_FLAG_HT1 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel1))? DMA_FLAG_HT1 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel2))? DMA_FLAG_HT2 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel2))? DMA_FLAG_HT2 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel3))? DMA_FLAG_HT3 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel3))? DMA_FLAG_HT3 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel4))? DMA_FLAG_HT4 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel4))? DMA_FLAG_HT4 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel5))? DMA_FLAG_HT5 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel5))? DMA_FLAG_HT5 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel6))? DMA_FLAG_HT6 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel6))? DMA_FLAG_HT6 :\ + DMA_FLAG_HT7) + +/** + * @brief Return the current DMA Channel transfer error flag. + * @param __HANDLE__: DMA handle + * @retval The specified transfer error flag index. + */ +#define __HAL_DMA_GET_TE_FLAG_INDEX(__HANDLE__)\ +(((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel1))? DMA_FLAG_TE1 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel1))? DMA_FLAG_TE1 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel2))? DMA_FLAG_TE2 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel2))? DMA_FLAG_TE2 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel3))? DMA_FLAG_TE3 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel3))? DMA_FLAG_TE3 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel4))? DMA_FLAG_TE4 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel4))? DMA_FLAG_TE4 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel5))? DMA_FLAG_TE5 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel5))? DMA_FLAG_TE5 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel6))? DMA_FLAG_TE6 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel6))? DMA_FLAG_TE6 :\ + DMA_FLAG_TE7) + +/** + * @brief Return the current DMA Channel Global interrupt flag. + * @param __HANDLE__: DMA handle + * @retval The specified transfer error flag index. + */ +#define __HAL_DMA_GET_GI_FLAG_INDEX(__HANDLE__)\ +(((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel1))? DMA_ISR_GIF1 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel1))? DMA_ISR_GIF1 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel2))? DMA_ISR_GIF2 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel2))? DMA_ISR_GIF2 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel3))? DMA_ISR_GIF3 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel3))? DMA_ISR_GIF3 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel4))? DMA_ISR_GIF4 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel4))? DMA_ISR_GIF4 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel5))? DMA_ISR_GIF5 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel5))? DMA_ISR_GIF5 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel6))? DMA_ISR_GIF6 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel6))? DMA_ISR_GIF6 :\ + DMA_ISR_GIF7) + +/** + * @brief Get the DMA Channel pending flags. + * @param __HANDLE__: DMA handle + * @param __FLAG__: Get the specified flag. + * This parameter can be any combination of the following values: + * @arg DMA_FLAG_TCx: Transfer complete flag + * @arg DMA_FLAG_HTx: Half transfer complete flag + * @arg DMA_FLAG_TEx: Transfer error flag + * @arg DMA_FLAG_GLx: Global interrupt flag + * Where x can be from 1 to 7 to select the DMA Channel x flag. + * @retval The state of FLAG (SET or RESET). + */ +#define __HAL_DMA_GET_FLAG(__HANDLE__, __FLAG__) (((uint32_t)((__HANDLE__)->Instance) > ((uint32_t)DMA1_Channel7))? \ + (DMA2->ISR & (__FLAG__)) : (DMA1->ISR & (__FLAG__))) + +/** + * @brief Clear the DMA Channel pending flags. + * @param __HANDLE__: DMA handle + * @param __FLAG__: specifies the flag to clear. + * This parameter can be any combination of the following values: + * @arg DMA_FLAG_TCx: Transfer complete flag + * @arg DMA_FLAG_HTx: Half transfer complete flag + * @arg DMA_FLAG_TEx: Transfer error flag + * @arg DMA_FLAG_GLx: Global interrupt flag + * Where x can be from 1 to 7 to select the DMA Channel x flag. + * @retval None + */ +#define __HAL_DMA_CLEAR_FLAG(__HANDLE__, __FLAG__) (((uint32_t)((__HANDLE__)->Instance) > ((uint32_t)DMA1_Channel7))? \ + (DMA2->IFCR = (__FLAG__)) : (DMA1->IFCR = (__FLAG__))) + +/** + * @brief Enable the specified DMA Channel interrupts. + * @param __HANDLE__: DMA handle + * @param __INTERRUPT__: specifies the DMA interrupt sources to be enabled or disabled. + * This parameter can be any combination of the following values: + * @arg DMA_IT_TC: Transfer complete interrupt mask + * @arg DMA_IT_HT: Half transfer complete interrupt mask + * @arg DMA_IT_TE: Transfer error interrupt mask + * @retval None + */ +#define __HAL_DMA_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CCR |= (__INTERRUPT__)) + +/** + * @brief Disable the specified DMA Channel interrupts. + * @param __HANDLE__: DMA handle + * @param __INTERRUPT__: specifies the DMA interrupt sources to be enabled or disabled. + * This parameter can be any combination of the following values: + * @arg DMA_IT_TC: Transfer complete interrupt mask + * @arg DMA_IT_HT: Half transfer complete interrupt mask + * @arg DMA_IT_TE: Transfer error interrupt mask + * @retval None + */ +#define __HAL_DMA_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CCR &= ~(__INTERRUPT__)) + +/** + * @brief Check whether the specified DMA Channel interrupt is enabled or not. + * @param __HANDLE__: DMA handle + * @param __INTERRUPT__: specifies the DMA interrupt source to check. + * This parameter can be one of the following values: + * @arg DMA_IT_TC: Transfer complete interrupt mask + * @arg DMA_IT_HT: Half transfer complete interrupt mask + * @arg DMA_IT_TE: Transfer error interrupt mask + * @retval The state of DMA_IT (SET or RESET). + */ +#define __HAL_DMA_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->CCR & (__INTERRUPT__))) + +/** + * @brief Return the number of remaining data units in the current DMA Channel transfer. + * @param __HANDLE__: DMA handle + * @retval The number of remaining data units in the current DMA Channel transfer. + */ +#define __HAL_DMA_GET_COUNTER(__HANDLE__) ((__HANDLE__)->Instance->CNDTR) + +/** + * @} + */ + +#if defined(DMAMUX1) +/* Include DMA HAL Extension module */ +#include "stm32l4xx_hal_dma_ex.h" +#endif /* DMAMUX1 */ + +/* Exported functions --------------------------------------------------------*/ + +/** @addtogroup DMA_Exported_Functions + * @{ + */ + +/** @addtogroup DMA_Exported_Functions_Group1 + * @{ + */ +/* Initialization and de-initialization functions *****************************/ +HAL_StatusTypeDef HAL_DMA_Init(DMA_HandleTypeDef *hdma); +HAL_StatusTypeDef HAL_DMA_DeInit (DMA_HandleTypeDef *hdma); +/** + * @} + */ + +/** @addtogroup DMA_Exported_Functions_Group2 + * @{ + */ +/* IO operation functions *****************************************************/ +HAL_StatusTypeDef HAL_DMA_Start (DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength); +HAL_StatusTypeDef HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength); +HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *hdma); +HAL_StatusTypeDef HAL_DMA_Abort_IT(DMA_HandleTypeDef *hdma); +HAL_StatusTypeDef HAL_DMA_PollForTransfer(DMA_HandleTypeDef *hdma, HAL_DMA_LevelCompleteTypeDef CompleteLevel, uint32_t Timeout); +void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma); +HAL_StatusTypeDef HAL_DMA_RegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID, void (* pCallback)( DMA_HandleTypeDef * _hdma)); +HAL_StatusTypeDef HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID); + +/** + * @} + */ + +/** @addtogroup DMA_Exported_Functions_Group3 + * @{ + */ +/* Peripheral State and Error functions ***************************************/ +HAL_DMA_StateTypeDef HAL_DMA_GetState(DMA_HandleTypeDef *hdma); +uint32_t HAL_DMA_GetError(DMA_HandleTypeDef *hdma); +/** + * @} + */ + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup DMA_Private_Macros DMA Private Macros + * @{ + */ + +#define IS_DMA_DIRECTION(DIRECTION) (((DIRECTION) == DMA_PERIPH_TO_MEMORY ) || \ + ((DIRECTION) == DMA_MEMORY_TO_PERIPH) || \ + ((DIRECTION) == DMA_MEMORY_TO_MEMORY)) + +#define IS_DMA_BUFFER_SIZE(SIZE) (((SIZE) >= 0x1) && ((SIZE) < 0x10000)) + +#define IS_DMA_PERIPHERAL_INC_STATE(STATE) (((STATE) == DMA_PINC_ENABLE) || \ + ((STATE) == DMA_PINC_DISABLE)) + +#define IS_DMA_MEMORY_INC_STATE(STATE) (((STATE) == DMA_MINC_ENABLE) || \ + ((STATE) == DMA_MINC_DISABLE)) + +#if !defined (DMAMUX1) + +#define IS_DMA_ALL_REQUEST(REQUEST) (((REQUEST) == DMA_REQUEST_0) || \ + ((REQUEST) == DMA_REQUEST_1) || \ + ((REQUEST) == DMA_REQUEST_2) || \ + ((REQUEST) == DMA_REQUEST_3) || \ + ((REQUEST) == DMA_REQUEST_4) || \ + ((REQUEST) == DMA_REQUEST_5) || \ + ((REQUEST) == DMA_REQUEST_6) || \ + ((REQUEST) == DMA_REQUEST_7)) +#endif + +#if defined(DMAMUX1) + +#define IS_DMA_ALL_REQUEST(REQUEST)((REQUEST) <= DMA_REQUEST_HASH_IN) + +#endif /* DMAMUX1 */ + +#define IS_DMA_PERIPHERAL_DATA_SIZE(SIZE) (((SIZE) == DMA_PDATAALIGN_BYTE) || \ + ((SIZE) == DMA_PDATAALIGN_HALFWORD) || \ + ((SIZE) == DMA_PDATAALIGN_WORD)) + +#define IS_DMA_MEMORY_DATA_SIZE(SIZE) (((SIZE) == DMA_MDATAALIGN_BYTE) || \ + ((SIZE) == DMA_MDATAALIGN_HALFWORD) || \ + ((SIZE) == DMA_MDATAALIGN_WORD )) + +#define IS_DMA_MODE(MODE) (((MODE) == DMA_NORMAL ) || \ + ((MODE) == DMA_CIRCULAR)) + +#define IS_DMA_PRIORITY(PRIORITY) (((PRIORITY) == DMA_PRIORITY_LOW ) || \ + ((PRIORITY) == DMA_PRIORITY_MEDIUM) || \ + ((PRIORITY) == DMA_PRIORITY_HIGH) || \ + ((PRIORITY) == DMA_PRIORITY_VERY_HIGH)) + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_HAL_DMA_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_dma_ex.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_dma_ex.h new file mode 100644 index 0000000..0ce4b2a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_dma_ex.h @@ -0,0 +1,298 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_dma_ex.h + * @author MCD Application Team + * @brief Header file of DMA HAL extension module. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_DMA_EX_H +#define __STM32L4xx_HAL_DMA_EX_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(DMAMUX1) + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup DMAEx + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup DMAEx_Exported_Types DMAEx Exported Types + * @{ + */ + +/** + * @brief HAL DMA Synchro definition + */ + + +/** + * @brief HAL DMAMUX Synchronization configuration structure definition + */ +typedef struct +{ + uint32_t SyncSignalID; /*!< Specifies the synchronization signal gating the DMA request in periodic mode. + This parameter can be a value of @ref DMAEx_DMAMUX_SyncSignalID_selection */ + + uint32_t SyncPolarity; /*!< Specifies the polarity of the signal on which the DMA request is synchronized. + This parameter can be a value of @ref DMAEx_DMAMUX_SyncPolarity_selection */ + + FunctionalState SyncEnable; /*!< Specifies if the synchronization shall be enabled or disabled + This parameter can take the value ENABLE or DISABLE*/ + + + FunctionalState EventEnable; /*!< Specifies if an event shall be generated once the RequestNumber is reached. + This parameter can take the value ENABLE or DISABLE */ + + uint32_t RequestNumber; /*!< Specifies the number of DMA request that will be authorized after a sync event + This parameter must be a number between Min_Data = 1 and Max_Data = 32 */ + + +}HAL_DMA_MuxSyncConfigTypeDef; + + +/** + * @brief HAL DMAMUX request generator parameters structure definition + */ +typedef struct +{ + uint32_t SignalID; /*!< Specifies the ID of the signal used for DMAMUX request generator + This parameter can be a value of @ref DMAEx_DMAMUX_SignalGeneratorID_selection */ + + uint32_t Polarity; /*!< Specifies the polarity of the signal on which the request is generated. + This parameter can be a value of @ref DMAEx_DMAMUX_RequestGeneneratorPolarity_selection */ + + uint32_t RequestNumber; /*!< Specifies the number of DMA request that will be generated after a signal event + This parameter must be a number between Min_Data = 1 and Max_Data = 32 */ + +}HAL_DMA_MuxRequestGeneratorConfigTypeDef; + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup DMAEx_Exported_Constants DMAEx Exported Constants + * @{ + */ + +/** @defgroup DMAEx_DMAMUX_SyncSignalID_selection DMAMUX SyncSignalID selection + * @{ + */ +#define HAL_DMAMUX1_SYNC_EXTI0 0U /*!< Synchronization Signal is EXTI0 IT */ +#define HAL_DMAMUX1_SYNC_EXTI1 1U /*!< Synchronization Signal is EXTI1 IT */ +#define HAL_DMAMUX1_SYNC_EXTI2 2U /*!< Synchronization Signal is EXTI2 IT */ +#define HAL_DMAMUX1_SYNC_EXTI3 3U /*!< Synchronization Signal is EXTI3 IT */ +#define HAL_DMAMUX1_SYNC_EXTI4 4U /*!< Synchronization Signal is EXTI4 IT */ +#define HAL_DMAMUX1_SYNC_EXTI5 5U /*!< Synchronization Signal is EXTI5 IT */ +#define HAL_DMAMUX1_SYNC_EXTI6 6U /*!< Synchronization Signal is EXTI6 IT */ +#define HAL_DMAMUX1_SYNC_EXTI7 7U /*!< Synchronization Signal is EXTI7 IT */ +#define HAL_DMAMUX1_SYNC_EXTI8 8U /*!< Synchronization Signal is EXTI8 IT */ +#define HAL_DMAMUX1_SYNC_EXTI9 9U /*!< Synchronization Signal is EXTI9 IT */ +#define HAL_DMAMUX1_SYNC_EXTI10 10U /*!< Synchronization Signal is EXTI10 IT */ +#define HAL_DMAMUX1_SYNC_EXTI11 11U /*!< Synchronization Signal is EXTI11 IT */ +#define HAL_DMAMUX1_SYNC_EXTI12 12U /*!< Synchronization Signal is EXTI12 IT */ +#define HAL_DMAMUX1_SYNC_EXTI13 13U /*!< Synchronization Signal is EXTI13 IT */ +#define HAL_DMAMUX1_SYNC_EXTI14 14U /*!< Synchronization Signal is EXTI14 IT */ +#define HAL_DMAMUX1_SYNC_EXTI15 15U /*!< Synchronization Signal is EXTI15 IT */ +#define HAL_DMAMUX1_SYNC_DMAMUX1_CH0_EVT 16U /*!< Synchronization Signal is DMAMUX1 Channel0 Event */ +#define HAL_DMAMUX1_SYNC_DMAMUX1_CH1_EVT 17U /*!< Synchronization Signal is DMAMUX1 Channel1 Event */ +#define HAL_DMAMUX1_SYNC_DMAMUX1_CH2_EVT 18U /*!< Synchronization Signal is DMAMUX1 Channel2 Event */ +#define HAL_DMAMUX1_SYNC_DMAMUX1_CH3_EVT 19U /*!< Synchronization Signal is DMAMUX1 Channel3 Event */ +#define HAL_DMAMUX1_SYNC_LPTIM1_OUT 20U /*!< Synchronization Signal is LPTIM1 OUT */ +#define HAL_DMAMUX1_SYNC_LPTIM2_OUT 21U /*!< Synchronization Signal is LPTIM2 OUT */ +#define HAL_DMAMUX1_SYNC_DSI_TE 22U /*!< Synchronization Signal is DSI Tearing Effect */ +#define HAL_DMAMUX1_SYNC_DSI_EOT 23U /*!< Synchronization Signal is DSI End of refresh */ +#define HAL_DMAMUX1_SYNC_DMA2D_EOT 24U /*!< Synchronization Signal is DMA2D End of Transfer */ +#define HAL_DMAMUX1_SYNC_LDTC_IT 25U /*!< Synchronization Signal is LDTC IT */ + +/** + * @} + */ + +/** @defgroup DMAEx_DMAMUX_SyncPolarity_selection DMAMUX SyncPolarity selection + * @{ + */ +#define HAL_DMAMUX_SYNC_NO_EVENT 0U /*!< block synchronization events */ +#define HAL_DMAMUX_SYNC_RISING ((uint32_t)DMAMUX_CxCR_SPOL_0) /*!< synchronize with rising edge events */ +#define HAL_DMAMUX_SYNC_FALLING ((uint32_t)DMAMUX_CxCR_SPOL_1) /*!< synchronize with falling edge events */ +#define HAL_DMAMUX_SYNC_RISING_FALLING ((uint32_t)DMAMUX_CxCR_SPOL) /*!< synchronize with rising and falling edge events */ + +/** + * @} + */ + +/** @defgroup DMAEx_DMAMUX_SignalGeneratorID_selection DMAMUX SignalGeneratorID selection + * @{ + */ + +#define HAL_DMAMUX1_REQUEST_GEN_EXTI0 0U /*!< Request generator Signal is EXTI0 IT */ +#define HAL_DMAMUX1_REQUEST_GEN_EXTI1 1U /*!< Request generator Signal is EXTI1 IT */ +#define HAL_DMAMUX1_REQUEST_GEN_EXTI2 2U /*!< Request generator Signal is EXTI2 IT */ +#define HAL_DMAMUX1_REQUEST_GEN_EXTI3 3U /*!< Request generator Signal is EXTI3 IT */ +#define HAL_DMAMUX1_REQUEST_GEN_EXTI4 4U /*!< Request generator Signal is EXTI4 IT */ +#define HAL_DMAMUX1_REQUEST_GEN_EXTI5 5U /*!< Request generator Signal is EXTI5 IT */ +#define HAL_DMAMUX1_REQUEST_GEN_EXTI6 6U /*!< Request generator Signal is EXTI6 IT */ +#define HAL_DMAMUX1_REQUEST_GEN_EXTI7 7U /*!< Request generator Signal is EXTI7 IT */ +#define HAL_DMAMUX1_REQUEST_GEN_EXTI8 8U /*!< Request generator Signal is EXTI8 IT */ +#define HAL_DMAMUX1_REQUEST_GEN_EXTI9 9U /*!< Request generator Signal is EXTI9 IT */ +#define HAL_DMAMUX1_REQUEST_GEN_EXTI10 10U /*!< Request generator Signal is EXTI10 IT */ +#define HAL_DMAMUX1_REQUEST_GEN_EXTI11 11U /*!< Request generator Signal is EXTI11 IT */ +#define HAL_DMAMUX1_REQUEST_GEN_EXTI12 12U /*!< Request generator Signal is EXTI12 IT */ +#define HAL_DMAMUX1_REQUEST_GEN_EXTI13 13U /*!< Request generator Signal is EXTI13 IT */ +#define HAL_DMAMUX1_REQUEST_GEN_EXTI14 14U /*!< Request generator Signal is EXTI14 IT */ +#define HAL_DMAMUX1_REQUEST_GEN_EXTI15 15U /*!< Request generator Signal is EXTI15 IT */ +#define HAL_DMAMUX1_REQUEST_GEN_DMAMUX1_CH0_EVT 16U /*!< Request generator Signal is DMAMUX1 Channel0 Event */ +#define HAL_DMAMUX1_REQUEST_GEN_DMAMUX1_CH1_EVT 17U /*!< Request generator Signal is DMAMUX1 Channel1 Event */ +#define HAL_DMAMUX1_REQUEST_GEN_DMAMUX1_CH2_EVT 18U /*!< Request generator Signal is DMAMUX1 Channel2 Event */ +#define HAL_DMAMUX1_REQUEST_GEN_DMAMUX1_CH3_EVT 19U /*!< Request generator Signal is DMAMUX1 Channel3 Event */ +#define HAL_DMAMUX1_REQUEST_GEN_LPTIM1_OUT 20U /*!< Request generator Signal is LPTIM1 OUT */ +#define HAL_DMAMUX1_REQUEST_GEN_LPTIM2_OUT 21U /*!< Request generator Signal is LPTIM2 OUT */ +#define HAL_DMAMUX1_REQUEST_GEN_DSI_TE 22U /*!< Request generator Signal is DSI Tearing Effect */ +#define HAL_DMAMUX1_REQUEST_GEN_DSI_EOT 23U /*!< Request generator Signal is DSI End of refresh */ +#define HAL_DMAMUX1_REQUEST_GEN_DMA2D_EOT 24U /*!< Request generator Signal is DMA2D End of Transfer */ +#define HAL_DMAMUX1_REQUEST_GEN_LTDC_IT 25U /*!< Request generator Signal is LTDC IT */ + +/** + * @} + */ + +/** @defgroup DMAEx_DMAMUX_RequestGeneneratorPolarity_selection DMAMUX RequestGeneneratorPolarity selection + * @{ + */ +#define HAL_DMAMUX_REQUEST_GEN_NO_EVENT 0U /*!< block request generator events */ +#define HAL_DMAMUX_REQUEST_GEN_RISING DMAMUX_RGxCR_GPOL_0 /*!< generate request on rising edge events */ +#define HAL_DMAMUX_REQUEST_GEN_FALLING DMAMUX_RGxCR_GPOL_1 /*!< generate request on falling edge events */ +#define HAL_DMAMUX_REQUEST_GEN_RISING_FALLING DMAMUX_RGxCR_GPOL /*!< generate request on rising and falling edge events */ + +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup DMAEx_Exported_Functions + * @{ + */ + +/* IO operation functions *****************************************************/ +/** @addtogroup DMAEx_Exported_Functions_Group1 + * @{ + */ + +/* ------------------------- REQUEST -----------------------------------------*/ +HAL_StatusTypeDef HAL_DMAEx_ConfigMuxRequestGenerator (DMA_HandleTypeDef *hdma, + HAL_DMA_MuxRequestGeneratorConfigTypeDef *pRequestGeneratorConfig); +HAL_StatusTypeDef HAL_DMAEx_EnableMuxRequestGenerator (DMA_HandleTypeDef *hdma); +HAL_StatusTypeDef HAL_DMAEx_DisableMuxRequestGenerator (DMA_HandleTypeDef *hdma); +/* -------------------------------------------------------------------------- */ + +/* ------------------------- SYNCHRO -----------------------------------------*/ +HAL_StatusTypeDef HAL_DMAEx_ConfigMuxSync(DMA_HandleTypeDef *hdma, HAL_DMA_MuxSyncConfigTypeDef *pSyncConfig); +/* -------------------------------------------------------------------------- */ + +void HAL_DMAEx_MUX_IRQHandler(DMA_HandleTypeDef *hdma); + +/** + * @} + */ + +/** + * @} + */ + + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup DMAEx_Private_Macros DMAEx Private Macros + * @brief DMAEx private macros + * @{ + */ + +#define IS_DMAMUX_SYNC_SIGNAL_ID(SIGNAL_ID) ((SIGNAL_ID) <= HAL_DMAMUX1_SYNC_LDTC_IT) + +#define IS_DMAMUX_SYNC_REQUEST_NUMBER(REQUEST_NUMBER) (((REQUEST_NUMBER) > 0) && ((REQUEST_NUMBER) <= 32)) + +#define IS_DMAMUX_SYNC_POLARITY(POLARITY) (((POLARITY) == HAL_DMAMUX_SYNC_NO_EVENT) || \ + ((POLARITY) == HAL_DMAMUX_SYNC_RISING) || \ + ((POLARITY) == HAL_DMAMUX_SYNC_FALLING) || \ + ((POLARITY) == HAL_DMAMUX_SYNC_RISING_FALLING)) + +#define IS_DMAMUX_SYNC_STATE(SYNC) (((SYNC) == DISABLE) || ((SYNC) == ENABLE)) + +#define IS_DMAMUX_SYNC_EVENT(EVENT) (((EVENT) == DISABLE) || \ + ((EVENT) == ENABLE)) + +#define IS_DMAMUX_REQUEST_GEN_SIGNAL_ID(SIGNAL_ID) ((SIGNAL_ID) <= HAL_DMAMUX1_REQUEST_GEN_LTDC_IT) + +#define IS_DMAMUX_REQUEST_GEN_REQUEST_NUMBER(REQUEST_NUMBER) (((REQUEST_NUMBER) > 0) && ((REQUEST_NUMBER) <= 32)) + +#define IS_DMAMUX_REQUEST_GEN_POLARITY(POLARITY) (((POLARITY) == HAL_DMAMUX_REQUEST_GEN_NO_EVENT) || \ + ((POLARITY) == HAL_DMAMUX_REQUEST_GEN_RISING) || \ + ((POLARITY) == HAL_DMAMUX_REQUEST_GEN_FALLING) || \ + ((POLARITY) == HAL_DMAMUX_REQUEST_GEN_RISING_FALLING)) + +/** + * @} + */ + + +/** + * @} + */ + +/** + * @} + */ + +#endif /* DMAMUX1 */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_HAL_DMA_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash.h new file mode 100644 index 0000000..ef4ea30 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash.h @@ -0,0 +1,1022 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_flash.h + * @author MCD Application Team + * @brief Header file of FLASH HAL module. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_FLASH_H +#define __STM32L4xx_HAL_FLASH_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup FLASH + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup FLASH_Exported_Types FLASH Exported Types + * @{ + */ + +/** + * @brief FLASH Erase structure definition + */ +typedef struct +{ + uint32_t TypeErase; /*!< Mass erase or page erase. + This parameter can be a value of @ref FLASH_Type_Erase */ + uint32_t Banks; /*!< Select bank to erase. + This parameter must be a value of @ref FLASH_Banks + (FLASH_BANK_BOTH should be used only for mass erase) */ + uint32_t Page; /*!< Initial Flash page to erase when page erase is disabled + This parameter must be a value between 0 and (max number of pages in the bank - 1) + (eg : 255 for 1MB dual bank) */ + uint32_t NbPages; /*!< Number of pages to be erased. + This parameter must be a value between 1 and (max number of pages in the bank - value of initial page)*/ +} FLASH_EraseInitTypeDef; + +/** + * @brief FLASH Option Bytes Program structure definition + */ +typedef struct +{ + uint32_t OptionType; /*!< Option byte to be configured. + This parameter can be a combination of the values of @ref FLASH_OB_Type */ + uint32_t WRPArea; /*!< Write protection area to be programmed (used for OPTIONBYTE_WRP). + Only one WRP area could be programmed at the same time. + This parameter can be value of @ref FLASH_OB_WRP_Area */ + uint32_t WRPStartOffset; /*!< Write protection start offset (used for OPTIONBYTE_WRP). + This parameter must be a value between 0 and (max number of pages in the bank - 1) + (eg : 25 for 1MB dual bank) */ + uint32_t WRPEndOffset; /*!< Write protection end offset (used for OPTIONBYTE_WRP). + This parameter must be a value between WRPStartOffset and (max number of pages in the bank - 1) */ + uint32_t RDPLevel; /*!< Set the read protection level.. (used for OPTIONBYTE_RDP). + This parameter can be a value of @ref FLASH_OB_Read_Protection */ + uint32_t USERType; /*!< User option byte(s) to be configured (used for OPTIONBYTE_USER). + This parameter can be a combination of @ref FLASH_OB_USER_Type */ + uint32_t USERConfig; /*!< Value of the user option byte (used for OPTIONBYTE_USER). + This parameter can be a combination of @ref FLASH_OB_USER_BOR_LEVEL, + @ref FLASH_OB_USER_nRST_STOP, @ref FLASH_OB_USER_nRST_STANDBY, + @ref FLASH_OB_USER_nRST_SHUTDOWN, @ref FLASH_OB_USER_IWDG_SW, + @ref FLASH_OB_USER_IWDG_STOP, @ref FLASH_OB_USER_IWDG_STANDBY, + @ref FLASH_OB_USER_WWDG_SW, @ref FLASH_OB_USER_BFB2, + @ref FLASH_OB_USER_DUALBANK, @ref FLASH_OB_USER_nBOOT1, + @ref FLASH_OB_USER_SRAM2_PE and @ref FLASH_OB_USER_SRAM2_RST */ + uint32_t PCROPConfig; /*!< Configuration of the PCROP (used for OPTIONBYTE_PCROP). + This parameter must be a combination of @ref FLASH_Banks (except FLASH_BANK_BOTH) + and @ref FLASH_OB_PCROP_RDP */ + uint32_t PCROPStartAddr; /*!< PCROP Start address (used for OPTIONBYTE_PCROP). + This parameter must be a value between begin and end of bank + => Be careful of the bank swapping for the address */ + uint32_t PCROPEndAddr; /*!< PCROP End address (used for OPTIONBYTE_PCROP). + This parameter must be a value between PCROP Start address and end of bank */ +} FLASH_OBProgramInitTypeDef; + +/** + * @brief FLASH Procedure structure definition + */ +typedef enum +{ + FLASH_PROC_NONE = 0, + FLASH_PROC_PAGE_ERASE, + FLASH_PROC_MASS_ERASE, + FLASH_PROC_PROGRAM, + FLASH_PROC_PROGRAM_LAST +} FLASH_ProcedureTypeDef; + +/** + * @brief FLASH Cache structure definition + */ +typedef enum +{ + FLASH_CACHE_DISABLED = 0, + FLASH_CACHE_ICACHE_ENABLED, + FLASH_CACHE_DCACHE_ENABLED, + FLASH_CACHE_ICACHE_DCACHE_ENABLED +} FLASH_CacheTypeDef; + +/** + * @brief FLASH handle Structure definition + */ +typedef struct +{ + HAL_LockTypeDef Lock; /* FLASH locking object */ + __IO uint32_t ErrorCode; /* FLASH error code */ + __IO FLASH_ProcedureTypeDef ProcedureOnGoing; /* Internal variable to indicate which procedure is ongoing or not in IT context */ + __IO uint32_t Address; /* Internal variable to save address selected for program in IT context */ + __IO uint32_t Bank; /* Internal variable to save current bank selected during erase in IT context */ + __IO uint32_t Page; /* Internal variable to define the current page which is erasing in IT context */ + __IO uint32_t NbPagesToErase; /* Internal variable to save the remaining pages to erase in IT context */ + __IO FLASH_CacheTypeDef CacheToReactivate; /* Internal variable to indicate which caches should be reactivated */ +}FLASH_ProcessTypeDef; + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup FLASH_Exported_Constants FLASH Exported Constants + * @{ + */ + +/** @defgroup FLASH_Error FLASH Error + * @{ + */ +#define HAL_FLASH_ERROR_NONE ((uint32_t)0x00000000) +#define HAL_FLASH_ERROR_OP ((uint32_t)0x00000001) +#define HAL_FLASH_ERROR_PROG ((uint32_t)0x00000002) +#define HAL_FLASH_ERROR_WRP ((uint32_t)0x00000004) +#define HAL_FLASH_ERROR_PGA ((uint32_t)0x00000008) +#define HAL_FLASH_ERROR_SIZ ((uint32_t)0x00000010) +#define HAL_FLASH_ERROR_PGS ((uint32_t)0x00000020) +#define HAL_FLASH_ERROR_MIS ((uint32_t)0x00000040) +#define HAL_FLASH_ERROR_FAST ((uint32_t)0x00000080) +#define HAL_FLASH_ERROR_RD ((uint32_t)0x00000100) +#define HAL_FLASH_ERROR_OPTV ((uint32_t)0x00000200) +#define HAL_FLASH_ERROR_ECCD ((uint32_t)0x00000400) +#if defined (STM32L431xx) || defined (STM32L432xx) || defined (STM32L433xx) || defined (STM32L442xx) || defined (STM32L443xx) || \ + defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define HAL_FLASH_ERROR_PEMPTY ((uint32_t)0x00000800) +#endif +/** + * @} + */ + +/** @defgroup FLASH_Type_Erase FLASH Erase Type + * @{ + */ +#define FLASH_TYPEERASE_PAGES ((uint32_t)0x00) /*!> 24) /*!< ECC Correction Interrupt source */ +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ +/** @defgroup FLASH_Exported_Macros FLASH Exported Macros + * @brief macros to control FLASH features + * @{ + */ + +/** + * @brief Set the FLASH Latency. + * @param __LATENCY__: FLASH Latency + * This parameter can be one of the following values : + * @arg FLASH_LATENCY_0: FLASH Zero wait state + * @arg FLASH_LATENCY_1: FLASH One wait state + * @arg FLASH_LATENCY_2: FLASH Two wait states + * @arg FLASH_LATENCY_3: FLASH Three wait states + * @arg FLASH_LATENCY_4: FLASH Four wait states + * @retval None + */ +#define __HAL_FLASH_SET_LATENCY(__LATENCY__) (MODIFY_REG(FLASH->ACR, FLASH_ACR_LATENCY, (__LATENCY__))) + +/** + * @brief Get the FLASH Latency. + * @retval FLASH Latency + * This parameter can be one of the following values : + * @arg FLASH_LATENCY_0: FLASH Zero wait state + * @arg FLASH_LATENCY_1: FLASH One wait state + * @arg FLASH_LATENCY_2: FLASH Two wait states + * @arg FLASH_LATENCY_3: FLASH Three wait states + * @arg FLASH_LATENCY_4: FLASH Four wait states + */ +#define __HAL_FLASH_GET_LATENCY() READ_BIT(FLASH->ACR, FLASH_ACR_LATENCY) + +/** + * @brief Enable the FLASH prefetch buffer. + * @retval None + */ +#define __HAL_FLASH_PREFETCH_BUFFER_ENABLE() SET_BIT(FLASH->ACR, FLASH_ACR_PRFTEN) + +/** + * @brief Disable the FLASH prefetch buffer. + * @retval None + */ +#define __HAL_FLASH_PREFETCH_BUFFER_DISABLE() CLEAR_BIT(FLASH->ACR, FLASH_ACR_PRFTEN) + +/** + * @brief Enable the FLASH instruction cache. + * @retval none + */ +#define __HAL_FLASH_INSTRUCTION_CACHE_ENABLE() SET_BIT(FLASH->ACR, FLASH_ACR_ICEN) + +/** + * @brief Disable the FLASH instruction cache. + * @retval none + */ +#define __HAL_FLASH_INSTRUCTION_CACHE_DISABLE() CLEAR_BIT(FLASH->ACR, FLASH_ACR_ICEN) + +/** + * @brief Enable the FLASH data cache. + * @retval none + */ +#define __HAL_FLASH_DATA_CACHE_ENABLE() SET_BIT(FLASH->ACR, FLASH_ACR_DCEN) + +/** + * @brief Disable the FLASH data cache. + * @retval none + */ +#define __HAL_FLASH_DATA_CACHE_DISABLE() CLEAR_BIT(FLASH->ACR, FLASH_ACR_DCEN) + +/** + * @brief Reset the FLASH instruction Cache. + * @note This function must be used only when the Instruction Cache is disabled. + * @retval None + */ +#define __HAL_FLASH_INSTRUCTION_CACHE_RESET() do { SET_BIT(FLASH->ACR, FLASH_ACR_ICRST); \ + CLEAR_BIT(FLASH->ACR, FLASH_ACR_ICRST); \ + } while (0) + +/** + * @brief Reset the FLASH data Cache. + * @note This function must be used only when the data Cache is disabled. + * @retval None + */ +#define __HAL_FLASH_DATA_CACHE_RESET() do { SET_BIT(FLASH->ACR, FLASH_ACR_DCRST); \ + CLEAR_BIT(FLASH->ACR, FLASH_ACR_DCRST); \ + } while (0) + +/** + * @brief Enable the FLASH power down during Low-power run mode. + * @note Writing this bit to 0 this bit, automatically the keys are + * loss and a new unlock sequence is necessary to re-write it to 1. + */ +#define __HAL_FLASH_POWER_DOWN_ENABLE() do { WRITE_REG(FLASH->PDKEYR, FLASH_PDKEY1); \ + WRITE_REG(FLASH->PDKEYR, FLASH_PDKEY2); \ + SET_BIT(FLASH->ACR, FLASH_ACR_RUN_PD); \ + } while (0) + +/** + * @brief Disable the FLASH power down during Low-power run mode. + * @note Writing this bit to 0 this bit, automatically the keys are + * loss and a new unlock sequence is necessary to re-write it to 1. + */ +#define __HAL_FLASH_POWER_DOWN_DISABLE() do { WRITE_REG(FLASH->PDKEYR, FLASH_PDKEY1); \ + WRITE_REG(FLASH->PDKEYR, FLASH_PDKEY2); \ + CLEAR_BIT(FLASH->ACR, FLASH_ACR_RUN_PD); \ + } while (0) + +/** + * @brief Enable the FLASH power down during Low-Power sleep mode + * @retval none + */ +#define __HAL_FLASH_SLEEP_POWERDOWN_ENABLE() SET_BIT(FLASH->ACR, FLASH_ACR_SLEEP_PD) + +/** + * @brief Disable the FLASH power down during Low-Power sleep mode + * @retval none + */ +#define __HAL_FLASH_SLEEP_POWERDOWN_DISABLE() CLEAR_BIT(FLASH->ACR, FLASH_ACR_SLEEP_PD) + +/** + * @} + */ + +/** @defgroup FLASH_Interrupt FLASH Interrupts Macros + * @brief macros to handle FLASH interrupts + * @{ + */ + +/** + * @brief Enable the specified FLASH interrupt. + * @param __INTERRUPT__: FLASH interrupt + * This parameter can be any combination of the following values: + * @arg FLASH_IT_EOP: End of FLASH Operation Interrupt + * @arg FLASH_IT_OPERR: Error Interrupt + * @arg FLASH_IT_RDERR: PCROP Read Error Interrupt + * @arg FLASH_IT_ECCC: ECC Correction Interrupt + * @retval none + */ +#define __HAL_FLASH_ENABLE_IT(__INTERRUPT__) do { if((__INTERRUPT__) & FLASH_IT_ECCC) { SET_BIT(FLASH->ECCR, FLASH_ECCR_ECCIE); }\ + if((__INTERRUPT__) & (~FLASH_IT_ECCC)) { SET_BIT(FLASH->CR, ((__INTERRUPT__) & (~FLASH_IT_ECCC))); }\ + } while(0) + +/** + * @brief Disable the specified FLASH interrupt. + * @param __INTERRUPT__: FLASH interrupt + * This parameter can be any combination of the following values: + * @arg FLASH_IT_EOP: End of FLASH Operation Interrupt + * @arg FLASH_IT_OPERR: Error Interrupt + * @arg FLASH_IT_RDERR: PCROP Read Error Interrupt + * @arg FLASH_IT_ECCC: ECC Correction Interrupt + * @retval none + */ +#define __HAL_FLASH_DISABLE_IT(__INTERRUPT__) do { if((__INTERRUPT__) & FLASH_IT_ECCC) { CLEAR_BIT(FLASH->ECCR, FLASH_ECCR_ECCIE); }\ + if((__INTERRUPT__) & (~FLASH_IT_ECCC)) { CLEAR_BIT(FLASH->CR, ((__INTERRUPT__) & (~FLASH_IT_ECCC))); }\ + } while(0) + +/** + * @brief Check whether the specified FLASH flag is set or not. + * @param __FLAG__: specifies the FLASH flag to check. + * This parameter can be one of the following values: + * @arg FLASH_FLAG_EOP: FLASH End of Operation flag + * @arg FLASH_FLAG_OPERR: FLASH Operation error flag + * @arg FLASH_FLAG_PROGERR: FLASH Programming error flag + * @arg FLASH_FLAG_WRPERR: FLASH Write protection error flag + * @arg FLASH_FLAG_PGAERR: FLASH Programming alignment error flag + * @arg FLASH_FLAG_SIZERR: FLASH Size error flag + * @arg FLASH_FLAG_PGSERR: FLASH Programming sequence error flag + * @arg FLASH_FLAG_MISERR: FLASH Fast programming data miss error flag + * @arg FLASH_FLAG_FASTERR: FLASH Fast programming error flag + * @arg FLASH_FLAG_RDERR: FLASH PCROP read error flag + * @arg FLASH_FLAG_OPTVERR: FLASH Option validity error flag + * @arg FLASH_FLAG_BSY: FLASH write/erase operations in progress flag + * @arg FLASH_FLAG_PEMPTY : FLASH Boot from not programmed flash (apply only for STM32L43x/STM32L44x devices) + * @arg FLASH_FLAG_ECCC: FLASH one ECC error has been detected and corrected + * @arg FLASH_FLAG_ECCD: FLASH two ECC errors have been detected + * @retval The new state of FLASH_FLAG (SET or RESET). + */ +#define __HAL_FLASH_GET_FLAG(__FLAG__) (((__FLAG__) & (FLASH_FLAG_ECCC | FLASH_FLAG_ECCD)) ? \ + (READ_BIT(FLASH->ECCR, (__FLAG__)) == (__FLAG__)) : \ + (READ_BIT(FLASH->SR, (__FLAG__)) == (__FLAG__))) + +/** + * @brief Clear the FLASH's pending flags. + * @param __FLAG__: specifies the FLASH flags to clear. + * This parameter can be any combination of the following values: + * @arg FLASH_FLAG_EOP: FLASH End of Operation flag + * @arg FLASH_FLAG_OPERR: FLASH Operation error flag + * @arg FLASH_FLAG_PROGERR: FLASH Programming error flag + * @arg FLASH_FLAG_WRPERR: FLASH Write protection error flag + * @arg FLASH_FLAG_PGAERR: FLASH Programming alignment error flag + * @arg FLASH_FLAG_SIZERR: FLASH Size error flag + * @arg FLASH_FLAG_PGSERR: FLASH Programming sequence error flag + * @arg FLASH_FLAG_MISERR: FLASH Fast programming data miss error flag + * @arg FLASH_FLAG_FASTERR: FLASH Fast programming error flag + * @arg FLASH_FLAG_RDERR: FLASH PCROP read error flag + * @arg FLASH_FLAG_OPTVERR: FLASH Option validity error flag + * @arg FLASH_FLAG_ECCC: FLASH one ECC error has been detected and corrected + * @arg FLASH_FLAG_ECCD: FLASH two ECC errors have been detected + * @arg FLASH_FLAG_ALL_ERRORS: FLASH All errors flags + * @retval None + */ +#define __HAL_FLASH_CLEAR_FLAG(__FLAG__) do { if((__FLAG__) & (FLASH_FLAG_ECCC | FLASH_FLAG_ECCD)) { SET_BIT(FLASH->ECCR, ((__FLAG__) & (FLASH_FLAG_ECCC | FLASH_FLAG_ECCD))); }\ + if((__FLAG__) & ~(FLASH_FLAG_ECCC | FLASH_FLAG_ECCD)) { WRITE_REG(FLASH->SR, ((__FLAG__) & ~(FLASH_FLAG_ECCC | FLASH_FLAG_ECCD))); }\ + } while(0) +/** + * @} + */ + +/* Include FLASH HAL Extended module */ +#include "stm32l4xx_hal_flash_ex.h" +#include "stm32l4xx_hal_flash_ramfunc.h" + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup FLASH_Exported_Functions + * @{ + */ + +/* Program operation functions ***********************************************/ +/** @addtogroup FLASH_Exported_Functions_Group1 + * @{ + */ +HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data); +HAL_StatusTypeDef HAL_FLASH_Program_IT(uint32_t TypeProgram, uint32_t Address, uint64_t Data); +/* FLASH IRQ handler method */ +void HAL_FLASH_IRQHandler(void); +/* Callbacks in non blocking modes */ +void HAL_FLASH_EndOfOperationCallback(uint32_t ReturnValue); +void HAL_FLASH_OperationErrorCallback(uint32_t ReturnValue); +/** + * @} + */ + +/* Peripheral Control functions **********************************************/ +/** @addtogroup FLASH_Exported_Functions_Group2 + * @{ + */ +HAL_StatusTypeDef HAL_FLASH_Unlock(void); +HAL_StatusTypeDef HAL_FLASH_Lock(void); +/* Option bytes control */ +HAL_StatusTypeDef HAL_FLASH_OB_Unlock(void); +HAL_StatusTypeDef HAL_FLASH_OB_Lock(void); +HAL_StatusTypeDef HAL_FLASH_OB_Launch(void); +/** + * @} + */ + +/* Peripheral State functions ************************************************/ +/** @addtogroup FLASH_Exported_Functions_Group3 + * @{ + */ +uint32_t HAL_FLASH_GetError(void); +/** + * @} + */ + +/** + * @} + */ + +/* Private constants --------------------------------------------------------*/ +/** @defgroup FLASH_Private_Constants FLASH Private Constants + * @{ + */ +#define FLASH_SIZE_DATA_REGISTER ((uint32_t)0x1FFF75E0) + +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define FLASH_SIZE ((((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) == 0xFFFF)) ? (0x800 << 10) : \ + (((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) & (0x0FFF)) << 10)) +#elif defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) +#define FLASH_SIZE ((((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) == 0xFFFF)) ? (0x200 << 10) : \ + (((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) & (0x0FFF)) << 10)) +#else +#define FLASH_SIZE ((((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) == 0xFFFF)) ? (0x400 << 10) : \ + (((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) & (0x0FFF)) << 10)) +#endif + +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define FLASH_BANK_SIZE (FLASH_SIZE >> 1) +#else +#define FLASH_BANK_SIZE (FLASH_SIZE) +#endif + +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define FLASH_PAGE_SIZE ((uint32_t)0x1000) +#define FLASH_PAGE_SIZE_128_BITS ((uint32_t)0x2000) +#else +#define FLASH_PAGE_SIZE ((uint32_t)0x800) +#endif + +#define FLASH_TIMEOUT_VALUE ((uint32_t)50000)/* 50 s */ +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup FLASH_Private_Macros FLASH Private Macros + * @{ + */ + +#define IS_FLASH_TYPEERASE(VALUE) (((VALUE) == FLASH_TYPEERASE_PAGES) || \ + ((VALUE) == FLASH_TYPEERASE_MASSERASE)) + +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define IS_FLASH_BANK(BANK) (((BANK) == FLASH_BANK_1) || \ + ((BANK) == FLASH_BANK_2) || \ + ((BANK) == FLASH_BANK_BOTH)) + +#define IS_FLASH_BANK_EXCLUSIVE(BANK) (((BANK) == FLASH_BANK_1) || \ + ((BANK) == FLASH_BANK_2)) +#else +#define IS_FLASH_BANK(BANK) ((BANK) == FLASH_BANK_1) + +#define IS_FLASH_BANK_EXCLUSIVE(BANK) ((BANK) == FLASH_BANK_1) +#endif + +#define IS_FLASH_TYPEPROGRAM(VALUE) (((VALUE) == FLASH_TYPEPROGRAM_DOUBLEWORD) || \ + ((VALUE) == FLASH_TYPEPROGRAM_FAST) || \ + ((VALUE) == FLASH_TYPEPROGRAM_FAST_AND_LAST)) + +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define IS_FLASH_MAIN_MEM_ADDRESS(ADDRESS) (((ADDRESS) >= FLASH_BASE) && ((ADDRESS) <= FLASH_BASE+0x1FFFFF)) +#else +#define IS_FLASH_MAIN_MEM_ADDRESS(ADDRESS) (((ADDRESS) >= FLASH_BASE) && ((((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) & (0x0FFF)) == 0x400) ? \ + ((ADDRESS) <= FLASH_BASE+0xFFFFF) : ((((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) & (0x0FFF)) == 0x200) ? \ + ((ADDRESS) <= FLASH_BASE+0x7FFFF) : ((((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) & (0x0FFF)) == 0x100) ? \ + ((ADDRESS) <= FLASH_BASE+0x3FFFF) : ((((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) & (0x0FFF)) == 0x80) ? \ + ((ADDRESS) <= FLASH_BASE+0x1FFFF) : ((ADDRESS) <= FLASH_BASE+0xFFFFF)))))) +#endif + +#define IS_FLASH_OTP_ADDRESS(ADDRESS) (((ADDRESS) >= 0x1FFF7000) && ((ADDRESS) <= 0x1FFF73FF)) + +#define IS_FLASH_PROGRAM_ADDRESS(ADDRESS) (IS_FLASH_MAIN_MEM_ADDRESS(ADDRESS) || IS_FLASH_OTP_ADDRESS(ADDRESS)) + +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define IS_FLASH_PAGE(PAGE) ((PAGE) < 256) +#elif defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || defined(STM32L496xx) || defined(STM32L4A6xx) +#define IS_FLASH_PAGE(PAGE) (((((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) & (0x0FFF)) == 0x400) ? ((PAGE) < 256) : \ + ((((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) & (0x0FFF)) == 0x200) ? ((PAGE) < 128) : \ + ((((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) & (0x0FFF)) == 0x100) ? ((PAGE) < 64) : \ + ((PAGE) < 256))))) +#elif defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) +#define IS_FLASH_PAGE(PAGE) (((((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) & (0x0FFF)) == 0x200) ? ((PAGE) < 256) : \ + ((((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) & (0x0FFF)) == 0x100) ? ((PAGE) < 128) : \ + ((PAGE) < 256)))) +#else +#define IS_FLASH_PAGE(PAGE) (((((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) & (0x0FFF)) == 0x100) ? ((PAGE) < 128) : \ + ((((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) & (0x0FFF)) == 0x80) ? ((PAGE) < 64) : \ + ((PAGE) < 128)))) +#endif + +#define IS_OPTIONBYTE(VALUE) (((VALUE) <= (OPTIONBYTE_WRP | OPTIONBYTE_RDP | OPTIONBYTE_USER | OPTIONBYTE_PCROP))) + +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define IS_OB_WRPAREA(VALUE) (((VALUE) == OB_WRPAREA_BANK1_AREAA) || ((VALUE) == OB_WRPAREA_BANK1_AREAB) || \ + ((VALUE) == OB_WRPAREA_BANK2_AREAA) || ((VALUE) == OB_WRPAREA_BANK2_AREAB)) +#else +#define IS_OB_WRPAREA(VALUE) (((VALUE) == OB_WRPAREA_BANK1_AREAA) || ((VALUE) == OB_WRPAREA_BANK1_AREAB)) +#endif + +#define IS_OB_RDP_LEVEL(LEVEL) (((LEVEL) == OB_RDP_LEVEL_0) ||\ + ((LEVEL) == OB_RDP_LEVEL_1)/* ||\ + ((LEVEL) == OB_RDP_LEVEL_2)*/) + +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define IS_OB_USER_TYPE(TYPE) (((TYPE) <= (uint32_t)0xFFFF) && ((TYPE) != 0)) +#elif defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || defined(STM32L496xx) || defined(STM32L4A6xx) +#define IS_OB_USER_TYPE(TYPE) (((TYPE) <= (uint32_t)0x1FFF) && ((TYPE) != 0)) +#else +#define IS_OB_USER_TYPE(TYPE) (((TYPE) <= (uint32_t)0x7E7F) && ((TYPE) != 0) && (((TYPE)&0x0180) == 0)) +#endif + +#define IS_OB_USER_BOR_LEVEL(LEVEL) (((LEVEL) == OB_BOR_LEVEL_0) || ((LEVEL) == OB_BOR_LEVEL_1) || \ + ((LEVEL) == OB_BOR_LEVEL_2) || ((LEVEL) == OB_BOR_LEVEL_3) || \ + ((LEVEL) == OB_BOR_LEVEL_4)) + +#define IS_OB_USER_STOP(VALUE) (((VALUE) == OB_STOP_RST) || ((VALUE) == OB_STOP_NORST)) + +#define IS_OB_USER_STANDBY(VALUE) (((VALUE) == OB_STANDBY_RST) || ((VALUE) == OB_STANDBY_NORST)) + +#define IS_OB_USER_SHUTDOWN(VALUE) (((VALUE) == OB_SHUTDOWN_RST) || ((VALUE) == OB_SHUTDOWN_NORST)) + +#define IS_OB_USER_IWDG(VALUE) (((VALUE) == OB_IWDG_HW) || ((VALUE) == OB_IWDG_SW)) + +#define IS_OB_USER_IWDG_STOP(VALUE) (((VALUE) == OB_IWDG_STOP_FREEZE) || ((VALUE) == OB_IWDG_STOP_RUN)) + +#define IS_OB_USER_IWDG_STDBY(VALUE) (((VALUE) == OB_IWDG_STDBY_FREEZE) || ((VALUE) == OB_IWDG_STDBY_RUN)) + +#define IS_OB_USER_WWDG(VALUE) (((VALUE) == OB_WWDG_HW) || ((VALUE) == OB_WWDG_SW)) + +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define IS_OB_USER_BFB2(VALUE) (((VALUE) == OB_BFB2_DISABLE) || ((VALUE) == OB_BFB2_ENABLE)) + +#define IS_OB_USER_DUALBANK(VALUE) (((VALUE) == OB_DUALBANK_SINGLE) || ((VALUE) == OB_DUALBANK_DUAL)) +#endif + +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define IS_OB_USER_DBANK(VALUE) (((VALUE) == OB_DBANK_128_BITS) || ((VALUE) == OB_DBANK_64_BITS)) +#endif + +#define IS_OB_USER_BOOT1(VALUE) (((VALUE) == OB_BOOT1_SRAM) || ((VALUE) == OB_BOOT1_SYSTEM)) + +#define IS_OB_USER_SRAM2_PARITY(VALUE) (((VALUE) == OB_SRAM2_PARITY_ENABLE) || ((VALUE) == OB_SRAM2_PARITY_DISABLE)) + +#define IS_OB_USER_SRAM2_RST(VALUE) (((VALUE) == OB_SRAM2_RST_ERASE) || ((VALUE) == OB_SRAM2_RST_NOT_ERASE)) + +#if defined (STM32L431xx) || defined (STM32L432xx) || defined (STM32L433xx) || defined (STM32L442xx) || \ + defined (STM32L443xx) || defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define IS_OB_USER_SWBOOT0(VALUE) (((VALUE) == OB_BOOT0_FROM_OB) || ((VALUE) == OB_BOOT0_FROM_PIN)) + +#define IS_OB_USER_BOOT0(VALUE) (((VALUE) == OB_BOOT0_RESET) || ((VALUE) == OB_BOOT0_SET)) +#endif + +#define IS_OB_PCROP_RDP(VALUE) (((VALUE) == OB_PCROP_RDP_NOT_ERASE) || ((VALUE) == OB_PCROP_RDP_ERASE)) + +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define IS_FLASH_LATENCY(LATENCY) (((LATENCY) == FLASH_LATENCY_0) || ((LATENCY) == FLASH_LATENCY_1) || \ + ((LATENCY) == FLASH_LATENCY_2) || ((LATENCY) == FLASH_LATENCY_3) || \ + ((LATENCY) == FLASH_LATENCY_4) || ((LATENCY) == FLASH_LATENCY_5) || \ + ((LATENCY) == FLASH_LATENCY_6) || ((LATENCY) == FLASH_LATENCY_7) || \ + ((LATENCY) == FLASH_LATENCY_8) || ((LATENCY) == FLASH_LATENCY_9) || \ + ((LATENCY) == FLASH_LATENCY_10) || ((LATENCY) == FLASH_LATENCY_11) || \ + ((LATENCY) == FLASH_LATENCY_12) || ((LATENCY) == FLASH_LATENCY_13) || \ + ((LATENCY) == FLASH_LATENCY_14) || ((LATENCY) == FLASH_LATENCY_15)) +#else +#define IS_FLASH_LATENCY(LATENCY) (((LATENCY) == FLASH_LATENCY_0) || \ + ((LATENCY) == FLASH_LATENCY_1) || \ + ((LATENCY) == FLASH_LATENCY_2) || \ + ((LATENCY) == FLASH_LATENCY_3) || \ + ((LATENCY) == FLASH_LATENCY_4)) +#endif +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_HAL_FLASH_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash_ex.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash_ex.h new file mode 100644 index 0000000..63d5c9f --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash_ex.h @@ -0,0 +1,134 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_flash_ex.h + * @author MCD Application Team + * @brief Header file of FLASH HAL Extended module. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_FLASH_EX_H +#define __STM32L4xx_HAL_FLASH_EX_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup FLASHEx + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ + +/* Exported constants --------------------------------------------------------*/ +#if defined (FLASH_CFGR_LVEN) +/** @addtogroup FLASHEx_Exported_Constants + * @{ + */ +/** @defgroup FLASHEx_LVE_PIN_CFG FLASHEx LVE pin configuration + * @{ + */ +#define FLASH_LVE_PIN_CTRL 0x00000000U /*!< LVE FLASH pin controlled by power controller */ +#define FLASH_LVE_PIN_FORCED FLASH_CFGR_LVEN /*!< LVE FLASH pin enforced to low (external SMPS used) */ +/** + * @} + */ + +/** + * @} + */ +#endif /* FLASH_CFGR_LVEN */ + +/* Exported macro ------------------------------------------------------------*/ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup FLASHEx_Exported_Functions + * @{ + */ + +/* Extended Program operation functions *************************************/ +/** @addtogroup FLASHEx_Exported_Functions_Group1 + * @{ + */ +HAL_StatusTypeDef HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *PageError); +HAL_StatusTypeDef HAL_FLASHEx_Erase_IT(FLASH_EraseInitTypeDef *pEraseInit); +HAL_StatusTypeDef HAL_FLASHEx_OBProgram(FLASH_OBProgramInitTypeDef *pOBInit); +void HAL_FLASHEx_OBGetConfig(FLASH_OBProgramInitTypeDef *pOBInit); +/** + * @} + */ + +#if defined (FLASH_CFGR_LVEN) +/** @addtogroup FLASHEx_Exported_Functions_Group2 + * @{ + */ +HAL_StatusTypeDef HAL_FLASHEx_ConfigLVEPin(uint32_t ConfigLVE); +/** + * @} + */ +#endif /* FLASH_CFGR_LVEN */ + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** + @cond 0 + */ +#if defined (FLASH_CFGR_LVEN) +#define IS_FLASH_LVE_PIN(CFG) (((CFG) == FLASH_LVE_PIN_CTRL) || ((CFG) == FLASH_LVE_PIN_FORCED)) +#endif /* FLASH_CFGR_LVEN */ +/** + @endcond + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_HAL_FLASH_EX_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash_ramfunc.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash_ramfunc.h new file mode 100644 index 0000000..723157f --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash_ramfunc.h @@ -0,0 +1,126 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_flash_ramfunc.h + * @author MCD Application Team + * @brief Header file of FLASH RAMFUNC driver. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_FLASH_RAMFUNC_H +#define __STM32L4xx_FLASH_RAMFUNC_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup FLASH_RAMFUNC + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ +/** + * @brief __RAM_FUNC definition + */ +#if defined ( __CC_ARM ) +/* ARM Compiler + ------------ + RAM functions are defined using the toolchain options. + Functions that are executed in RAM should reside in a separate source module. + Using the 'Options for File' dialog you can simply change the 'Code / Const' + area of a module to a memory space in physical RAM. + Available memory areas are declared in the 'Target' tab of the 'Options for Target' + dialog. +*/ +#define __RAM_FUNC HAL_StatusTypeDef + +#elif defined ( __ICCARM__ ) +/* ICCARM Compiler + --------------- + RAM functions are defined using a specific toolchain keyword "__ramfunc". +*/ +#define __RAM_FUNC __ramfunc HAL_StatusTypeDef + +#elif defined ( __GNUC__ ) +/* GNU Compiler + ------------ + RAM functions are defined using a specific toolchain attribute + "__attribute__((section(".RamFunc")))". +*/ +#define __RAM_FUNC HAL_StatusTypeDef __attribute__((section(".RamFunc"))) + +#endif + + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup FLASH_RAMFUNC_Exported_Functions + * @{ + */ + +/** @addtogroup FLASH_RAMFUNC_Exported_Functions_Group1 + * @{ + */ +/* Peripheral Control functions ************************************************/ +__RAM_FUNC HAL_FLASHEx_EnableRunPowerDown(void); +__RAM_FUNC HAL_FLASHEx_DisableRunPowerDown(void); +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +__RAM_FUNC HAL_FLASHEx_OB_DBankConfig(uint32_t DBankConfig); +#endif +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_FLASH_RAMFUNC_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_gpio.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_gpio.h new file mode 100644 index 0000000..bfae10d --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_gpio.h @@ -0,0 +1,316 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_gpio.h + * @author MCD Application Team + * @brief Header file of GPIO HAL module. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_GPIO_H +#define __STM32L4xx_HAL_GPIO_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup GPIO + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ + +/** @defgroup GPIO_Exported_Types GPIO Exported Types + * @{ + */ +/** + * @brief GPIO Init structure definition + */ +typedef struct +{ + uint32_t Pin; /*!< Specifies the GPIO pins to be configured. + This parameter can be any value of @ref GPIO_pins */ + + uint32_t Mode; /*!< Specifies the operating mode for the selected pins. + This parameter can be a value of @ref GPIO_mode */ + + uint32_t Pull; /*!< Specifies the Pull-up or Pull-Down activation for the selected pins. + This parameter can be a value of @ref GPIO_pull */ + + uint32_t Speed; /*!< Specifies the speed for the selected pins. + This parameter can be a value of @ref GPIO_speed */ + + uint32_t Alternate; /*!< Peripheral to be connected to the selected pins + This parameter can be a value of @ref GPIOEx_Alternate_function_selection */ +}GPIO_InitTypeDef; + +/** + * @brief GPIO Bit SET and Bit RESET enumeration + */ +typedef enum +{ + GPIO_PIN_RESET = 0, + GPIO_PIN_SET +}GPIO_PinState; +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup GPIO_Exported_Constants GPIO Exported Constants + * @{ + */ +/** @defgroup GPIO_pins GPIO pins + * @{ + */ +#define GPIO_PIN_0 ((uint16_t)0x0001) /* Pin 0 selected */ +#define GPIO_PIN_1 ((uint16_t)0x0002) /* Pin 1 selected */ +#define GPIO_PIN_2 ((uint16_t)0x0004) /* Pin 2 selected */ +#define GPIO_PIN_3 ((uint16_t)0x0008) /* Pin 3 selected */ +#define GPIO_PIN_4 ((uint16_t)0x0010) /* Pin 4 selected */ +#define GPIO_PIN_5 ((uint16_t)0x0020) /* Pin 5 selected */ +#define GPIO_PIN_6 ((uint16_t)0x0040) /* Pin 6 selected */ +#define GPIO_PIN_7 ((uint16_t)0x0080) /* Pin 7 selected */ +#define GPIO_PIN_8 ((uint16_t)0x0100) /* Pin 8 selected */ +#define GPIO_PIN_9 ((uint16_t)0x0200) /* Pin 9 selected */ +#define GPIO_PIN_10 ((uint16_t)0x0400) /* Pin 10 selected */ +#define GPIO_PIN_11 ((uint16_t)0x0800) /* Pin 11 selected */ +#define GPIO_PIN_12 ((uint16_t)0x1000) /* Pin 12 selected */ +#define GPIO_PIN_13 ((uint16_t)0x2000) /* Pin 13 selected */ +#define GPIO_PIN_14 ((uint16_t)0x4000) /* Pin 14 selected */ +#define GPIO_PIN_15 ((uint16_t)0x8000) /* Pin 15 selected */ +#define GPIO_PIN_All ((uint16_t)0xFFFF) /* All pins selected */ + +#define GPIO_PIN_MASK ((uint32_t)0x0000FFFF) /* PIN mask for assert test */ +/** + * @} + */ + +/** @defgroup GPIO_mode GPIO mode + * @brief GPIO Configuration Mode + * Elements values convention: 0xX0yz00YZ + * - X : GPIO mode or EXTI Mode + * - y : External IT or Event trigger detection + * - z : IO configuration on External IT or Event + * - Y : Output type (Push Pull or Open Drain) + * - Z : IO Direction mode (Input, Output, Alternate or Analog) + * @{ + */ +#define GPIO_MODE_INPUT ((uint32_t)0x00000000) /*!< Input Floating Mode */ +#define GPIO_MODE_OUTPUT_PP ((uint32_t)0x00000001) /*!< Output Push Pull Mode */ +#define GPIO_MODE_OUTPUT_OD ((uint32_t)0x00000011) /*!< Output Open Drain Mode */ +#define GPIO_MODE_AF_PP ((uint32_t)0x00000002) /*!< Alternate Function Push Pull Mode */ +#define GPIO_MODE_AF_OD ((uint32_t)0x00000012) /*!< Alternate Function Open Drain Mode */ +#define GPIO_MODE_ANALOG ((uint32_t)0x00000003) /*!< Analog Mode */ +#define GPIO_MODE_ANALOG_ADC_CONTROL ((uint32_t)0x0000000B) /*!< Analog Mode for ADC conversion */ +#define GPIO_MODE_IT_RISING ((uint32_t)0x10110000) /*!< External Interrupt Mode with Rising edge trigger detection */ +#define GPIO_MODE_IT_FALLING ((uint32_t)0x10210000) /*!< External Interrupt Mode with Falling edge trigger detection */ +#define GPIO_MODE_IT_RISING_FALLING ((uint32_t)0x10310000) /*!< External Interrupt Mode with Rising/Falling edge trigger detection */ +#define GPIO_MODE_EVT_RISING ((uint32_t)0x10120000) /*!< External Event Mode with Rising edge trigger detection */ +#define GPIO_MODE_EVT_FALLING ((uint32_t)0x10220000) /*!< External Event Mode with Falling edge trigger detection */ +#define GPIO_MODE_EVT_RISING_FALLING ((uint32_t)0x10320000) /*!< External Event Mode with Rising/Falling edge trigger detection */ +/** + * @} + */ + +/** @defgroup GPIO_speed GPIO speed + * @brief GPIO Output Maximum frequency + * @{ + */ +#define GPIO_SPEED_FREQ_LOW ((uint32_t)0x00000000) /*!< range up to 5 MHz, please refer to the product datasheet */ +#define GPIO_SPEED_FREQ_MEDIUM ((uint32_t)0x00000001) /*!< range 5 MHz to 25 MHz, please refer to the product datasheet */ +#define GPIO_SPEED_FREQ_HIGH ((uint32_t)0x00000002) /*!< range 25 MHz to 50 MHz, please refer to the product datasheet */ +#define GPIO_SPEED_FREQ_VERY_HIGH ((uint32_t)0x00000003) /*!< range 50 MHz to 80 MHz, please refer to the product datasheet */ +/** + * @} + */ + + /** @defgroup GPIO_pull GPIO pull + * @brief GPIO Pull-Up or Pull-Down Activation + * @{ + */ +#define GPIO_NOPULL ((uint32_t)0x00000000) /*!< No Pull-up or Pull-down activation */ +#define GPIO_PULLUP ((uint32_t)0x00000001) /*!< Pull-up activation */ +#define GPIO_PULLDOWN ((uint32_t)0x00000002) /*!< Pull-down activation */ +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup GPIO_Exported_Macros GPIO Exported Macros + * @{ + */ + +/** + * @brief Check whether the specified EXTI line flag is set or not. + * @param __EXTI_LINE__: specifies the EXTI line flag to check. + * This parameter can be GPIO_PIN_x where x can be(0..15) + * @retval The new state of __EXTI_LINE__ (SET or RESET). + */ +#define __HAL_GPIO_EXTI_GET_FLAG(__EXTI_LINE__) (EXTI->PR1 & (__EXTI_LINE__)) + +/** + * @brief Clear the EXTI's line pending flags. + * @param __EXTI_LINE__: specifies the EXTI lines flags to clear. + * This parameter can be any combination of GPIO_PIN_x where x can be (0..15) + * @retval None + */ +#define __HAL_GPIO_EXTI_CLEAR_FLAG(__EXTI_LINE__) (EXTI->PR1 = (__EXTI_LINE__)) + +/** + * @brief Check whether the specified EXTI line is asserted or not. + * @param __EXTI_LINE__: specifies the EXTI line to check. + * This parameter can be GPIO_PIN_x where x can be(0..15) + * @retval The new state of __EXTI_LINE__ (SET or RESET). + */ +#define __HAL_GPIO_EXTI_GET_IT(__EXTI_LINE__) (EXTI->PR1 & (__EXTI_LINE__)) + +/** + * @brief Clear the EXTI's line pending bits. + * @param __EXTI_LINE__: specifies the EXTI lines to clear. + * This parameter can be any combination of GPIO_PIN_x where x can be (0..15) + * @retval None + */ +#define __HAL_GPIO_EXTI_CLEAR_IT(__EXTI_LINE__) (EXTI->PR1 = (__EXTI_LINE__)) + +/** + * @brief Generate a Software interrupt on selected EXTI line. + * @param __EXTI_LINE__: specifies the EXTI line to check. + * This parameter can be GPIO_PIN_x where x can be(0..15) + * @retval None + */ +#define __HAL_GPIO_EXTI_GENERATE_SWIT(__EXTI_LINE__) (EXTI->SWIER1 |= (__EXTI_LINE__)) + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @addtogroup GPIO_Private_Macros GPIO Private Macros + * @{ + */ +#define IS_GPIO_PIN_ACTION(ACTION) (((ACTION) == GPIO_PIN_RESET) || ((ACTION) == GPIO_PIN_SET)) + +#define IS_GPIO_PIN(__PIN__) ((((__PIN__) & GPIO_PIN_MASK) != (uint32_t)0x00) &&\ + (((__PIN__) & ~GPIO_PIN_MASK) == (uint32_t)0x00)) + +#define IS_GPIO_MODE(__MODE__) (((__MODE__) == GPIO_MODE_INPUT) ||\ + ((__MODE__) == GPIO_MODE_OUTPUT_PP) ||\ + ((__MODE__) == GPIO_MODE_OUTPUT_OD) ||\ + ((__MODE__) == GPIO_MODE_AF_PP) ||\ + ((__MODE__) == GPIO_MODE_AF_OD) ||\ + ((__MODE__) == GPIO_MODE_IT_RISING) ||\ + ((__MODE__) == GPIO_MODE_IT_FALLING) ||\ + ((__MODE__) == GPIO_MODE_IT_RISING_FALLING) ||\ + ((__MODE__) == GPIO_MODE_EVT_RISING) ||\ + ((__MODE__) == GPIO_MODE_EVT_FALLING) ||\ + ((__MODE__) == GPIO_MODE_EVT_RISING_FALLING) ||\ + ((__MODE__) == GPIO_MODE_ANALOG) ||\ + ((__MODE__) == GPIO_MODE_ANALOG_ADC_CONTROL)) + +#define IS_GPIO_SPEED(__SPEED__) (((__SPEED__) == GPIO_SPEED_FREQ_LOW) ||\ + ((__SPEED__) == GPIO_SPEED_FREQ_MEDIUM) ||\ + ((__SPEED__) == GPIO_SPEED_FREQ_HIGH) ||\ + ((__SPEED__) == GPIO_SPEED_FREQ_VERY_HIGH)) + +#define IS_GPIO_PULL(__PULL__) (((__PULL__) == GPIO_NOPULL) ||\ + ((__PULL__) == GPIO_PULLUP) || \ + ((__PULL__) == GPIO_PULLDOWN)) +/** + * @} + */ + +/* Include GPIO HAL Extended module */ +#include "stm32l4xx_hal_gpio_ex.h" + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup GPIO_Exported_Functions GPIO Exported Functions + * @{ + */ + +/** @addtogroup GPIO_Exported_Functions_Group1 Initialization/de-initialization functions + * @brief Initialization and Configuration functions + * @{ + */ + +/* Initialization and de-initialization functions *****************************/ +void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init); +void HAL_GPIO_DeInit(GPIO_TypeDef *GPIOx, uint32_t GPIO_Pin); + +/** + * @} + */ + +/** @addtogroup GPIO_Exported_Functions_Group2 IO operation functions + * @{ + */ + +/* IO operation functions *****************************************************/ +GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); +void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState); +void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); +HAL_StatusTypeDef HAL_GPIO_LockPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); +void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin); +void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin); + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_HAL_GPIO_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_gpio_ex.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_gpio_ex.h new file mode 100644 index 0000000..db5d8d7 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_gpio_ex.h @@ -0,0 +1,822 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_gpio_ex.h + * @author MCD Application Team + * @brief Header file of GPIO HAL Extended module. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_GPIO_EX_H +#define __STM32L4xx_HAL_GPIO_EX_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup GPIOEx GPIOEx + * @brief GPIO Extended HAL module driver + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/** @defgroup GPIOEx_Exported_Constants GPIOEx Exported Constants + * @{ + */ + +/** @defgroup GPIOEx_Alternate_function_selection GPIOEx Alternate function selection + * @{ + */ + +#if defined(STM32L431xx) || defined(STM32L432xx) || defined(STM32L433xx) || defined(STM32L442xx) || defined(STM32L443xx) +/*--------------STM32L431xx/STM32L432xx/STM32L433xx/STM32L442xx/STM32L443xx---*/ +/** + * @brief AF 0 selection + */ +#define GPIO_AF0_RTC_50Hz ((uint8_t)0x00) /* RTC_50Hz Alternate Function mapping */ +#define GPIO_AF0_MCO ((uint8_t)0x00) /* MCO (MCO1 and MCO2) Alternate Function mapping */ +#define GPIO_AF0_SWJ ((uint8_t)0x00) /* SWJ (SWD and JTAG) Alternate Function mapping */ +#if defined(STM32L433xx) || defined(STM32L443xx) +#define GPIO_AF0_LCDBIAS ((uint8_t)0x00) /* LCDBIAS Alternate Function mapping */ +#endif /* STM32L433xx || STM32L443xx */ +#define GPIO_AF0_TRACE ((uint8_t)0x00) /* TRACE Alternate Function mapping */ + +/** + * @brief AF 1 selection + */ +#define GPIO_AF1_TIM1 ((uint8_t)0x01) /* TIM1 Alternate Function mapping */ +#define GPIO_AF1_TIM2 ((uint8_t)0x01) /* TIM2 Alternate Function mapping */ +#define GPIO_AF1_LPTIM1 ((uint8_t)0x01) /* LPTIM1 Alternate Function mapping */ +#define GPIO_AF1_IR ((uint8_t)0x01) /* IR Alternate Function mapping */ + +/** + * @brief AF 2 selection + */ +#define GPIO_AF2_TIM1 ((uint8_t)0x02) /* TIM1 Alternate Function mapping */ +#define GPIO_AF2_TIM2 ((uint8_t)0x02) /* TIM2 Alternate Function mapping */ + +/** + * @brief AF 3 selection + */ +#define GPIO_AF3_USART2 ((uint8_t)0x03) /* USART1 Alternate Function mapping */ +#define GPIO_AF3_TIM1_COMP2 ((uint8_t)0x03) /* TIM1/COMP2 Break in Alternate Function mapping */ +#define GPIO_AF3_TIM1_COMP1 ((uint8_t)0x03) /* TIM1/COMP1 Break in Alternate Function mapping */ + +/** + * @brief AF 4 selection + */ +#define GPIO_AF4_I2C1 ((uint8_t)0x04) /* I2C1 Alternate Function mapping */ +#define GPIO_AF4_I2C2 ((uint8_t)0x04) /* I2C2 Alternate Function mapping */ +#define GPIO_AF4_I2C3 ((uint8_t)0x04) /* I2C3 Alternate Function mapping */ + +/** + * @brief AF 5 selection + */ +#define GPIO_AF5_SPI1 ((uint8_t)0x05) /* SPI1 Alternate Function mapping */ +#define GPIO_AF5_SPI2 ((uint8_t)0x05) /* SPI2 Alternate Function mapping */ + +/** + * @brief AF 6 selection + */ +#define GPIO_AF6_SPI3 ((uint8_t)0x06) /* SPI3 Alternate Function mapping */ +#define GPIO_AF6_COMP1 ((uint8_t)0x06) /* COMP1 Alternate Function mapping */ + +/** + * @brief AF 7 selection + */ +#define GPIO_AF7_USART1 ((uint8_t)0x07) /* USART1 Alternate Function mapping */ +#define GPIO_AF7_USART2 ((uint8_t)0x07) /* USART2 Alternate Function mapping */ +#define GPIO_AF7_USART3 ((uint8_t)0x07) /* USART3 Alternate Function mapping */ + +/** + * @brief AF 8 selection + */ +#define GPIO_AF8_LPUART1 ((uint8_t)0x08) /* LPUART1 Alternate Function mapping */ + +/** + * @brief AF 9 selection + */ +#define GPIO_AF9_CAN1 ((uint8_t)0x09) /* CAN1 Alternate Function mapping */ +#define GPIO_AF9_TSC ((uint8_t)0x09) /* TSC Alternate Function mapping */ + +/** + * @brief AF 10 selection + */ +#if defined(STM32L432xx) || defined(STM32L433xx) || defined(STM32L442xx) || defined(STM32L443xx) +#define GPIO_AF10_USB_FS ((uint8_t)0x0A) /* USB_FS Alternate Function mapping */ +#endif /* STM32L432xx || STM32L433xx || STM32L442xx || STM32L443xx */ +#define GPIO_AF10_QUADSPI ((uint8_t)0x0A) /* QUADSPI Alternate Function mapping */ + +#if defined(STM32L433xx) || defined(STM32L443xx) +/** + * @brief AF 11 selection + */ +#define GPIO_AF11_LCD ((uint8_t)0x0B) /* LCD Alternate Function mapping */ +#endif /* STM32L433xx || STM32L443xx */ + +/** + * @brief AF 12 selection + */ +#define GPIO_AF12_SWPMI1 ((uint8_t)0x0C) /* SWPMI1 Alternate Function mapping */ +#define GPIO_AF12_COMP1 ((uint8_t)0x0C) /* COMP1 Alternate Function mapping */ +#define GPIO_AF12_COMP2 ((uint8_t)0x0C) /* COMP2 Alternate Function mapping */ +#define GPIO_AF12_SDMMC1 ((uint8_t)0x0C) /* SDMMC1 Alternate Function mapping */ + +/** + * @brief AF 13 selection + */ +#define GPIO_AF13_SAI1 ((uint8_t)0x0D) /* SAI1 Alternate Function mapping */ + +/** + * @brief AF 14 selection + */ +#define GPIO_AF14_TIM2 ((uint8_t)0x0E) /* TIM2 Alternate Function mapping */ +#define GPIO_AF14_TIM15 ((uint8_t)0x0E) /* TIM15 Alternate Function mapping */ +#define GPIO_AF14_TIM16 ((uint8_t)0x0E) /* TIM16 Alternate Function mapping */ +#define GPIO_AF14_LPTIM2 ((uint8_t)0x0E) /* LPTIM2 Alternate Function mapping */ + +/** + * @brief AF 15 selection + */ +#define GPIO_AF15_EVENTOUT ((uint8_t)0x0F) /* EVENTOUT Alternate Function mapping */ + +#define IS_GPIO_AF(AF) ((AF) <= (uint8_t)0x0F) + +#endif /* STM32L431xx || STM32L432xx || STM32L433xx || STM32L442xx || STM32L443xx */ + +#if defined(STM32L451xx) || defined(STM32L452xx) || defined(STM32L462xx) +/*--------------STM32L451xx/STM32L452xx/STM32L462xx---------------------------*/ +/** + * @brief AF 0 selection + */ +#define GPIO_AF0_RTC_50Hz ((uint8_t)0x00) /* RTC_50Hz Alternate Function mapping */ +#define GPIO_AF0_MCO ((uint8_t)0x00) /* MCO (MCO1 and MCO2) Alternate Function mapping */ +#define GPIO_AF0_SWJ ((uint8_t)0x00) /* SWJ (SWD and JTAG) Alternate Function mapping */ +#define GPIO_AF0_TRACE ((uint8_t)0x00) /* TRACE Alternate Function mapping */ + +/** + * @brief AF 1 selection + */ +#define GPIO_AF1_TIM1 ((uint8_t)0x01) /* TIM1 Alternate Function mapping */ +#define GPIO_AF1_TIM2 ((uint8_t)0x01) /* TIM2 Alternate Function mapping */ +#define GPIO_AF1_LPTIM1 ((uint8_t)0x01) /* LPTIM1 Alternate Function mapping */ +#define GPIO_AF1_IR ((uint8_t)0x01) /* IR Alternate Function mapping */ + +/** + * @brief AF 2 selection + */ +#define GPIO_AF2_TIM1 ((uint8_t)0x02) /* TIM1 Alternate Function mapping */ +#define GPIO_AF2_TIM2 ((uint8_t)0x02) /* TIM2 Alternate Function mapping */ +#define GPIO_AF2_TIM3 ((uint8_t)0x02) /* TIM3 Alternate Function mapping */ +#define GPIO_AF2_I2C4 ((uint8_t)0x02) /* I2C4 Alternate Function mapping */ + +/** + * @brief AF 3 selection + */ +#define GPIO_AF3_TIM1_COMP2 ((uint8_t)0x03) /* TIM1/COMP2 Break in Alternate Function mapping */ +#define GPIO_AF3_TIM1_COMP1 ((uint8_t)0x03) /* TIM1/COMP1 Break in Alternate Function mapping */ +#define GPIO_AF3_USART2 ((uint8_t)0x03) /* USART2 Alternate Function mapping */ +#define GPIO_AF3_CAN1 ((uint8_t)0x03) /* CAN1 Alternate Function mapping */ +#define GPIO_AF3_I2C4 ((uint8_t)0x03) /* I2C4 Alternate Function mapping */ + +/** + * @brief AF 4 selection + */ +#define GPIO_AF4_I2C1 ((uint8_t)0x04) /* I2C1 Alternate Function mapping */ +#define GPIO_AF4_I2C2 ((uint8_t)0x04) /* I2C2 Alternate Function mapping */ +#define GPIO_AF4_I2C3 ((uint8_t)0x04) /* I2C3 Alternate Function mapping */ +#define GPIO_AF4_I2C4 ((uint8_t)0x04) /* I2C4 Alternate Function mapping */ + +/** + * @brief AF 5 selection + */ +#define GPIO_AF5_SPI1 ((uint8_t)0x05) /* SPI1 Alternate Function mapping */ +#define GPIO_AF5_SPI2 ((uint8_t)0x05) /* SPI2 Alternate Function mapping */ +#define GPIO_AF5_I2C4 ((uint8_t)0x05) /* I2C4 Alternate Function mapping */ + +/** + * @brief AF 6 selection + */ +#define GPIO_AF6_SPI3 ((uint8_t)0x06) /* SPI3 Alternate Function mapping */ +#define GPIO_AF6_DFSDM1 ((uint8_t)0x06) /* DFSDM1 Alternate Function mapping */ +#define GPIO_AF6_COMP1 ((uint8_t)0x06) /* COMP1 Alternate Function mapping */ + +/** + * @brief AF 7 selection + */ +#define GPIO_AF7_USART1 ((uint8_t)0x07) /* USART1 Alternate Function mapping */ +#define GPIO_AF7_USART2 ((uint8_t)0x07) /* USART2 Alternate Function mapping */ +#define GPIO_AF7_USART3 ((uint8_t)0x07) /* USART3 Alternate Function mapping */ + +/** + * @brief AF 8 selection + */ +#define GPIO_AF8_UART4 ((uint8_t)0x08) /* UART4 Alternate Function mapping */ +#define GPIO_AF8_LPUART1 ((uint8_t)0x08) /* LPUART1 Alternate Function mapping */ +#define GPIO_AF8_CAN1 ((uint8_t)0x08) /* CAN1 Alternate Function mapping */ + + +/** + * @brief AF 9 selection + */ +#define GPIO_AF9_CAN1 ((uint8_t)0x09) /* CAN1 Alternate Function mapping */ +#define GPIO_AF9_TSC ((uint8_t)0x09) /* TSC Alternate Function mapping */ + +/** + * @brief AF 10 selection + */ +#if defined(STM32L452xx) || defined(STM32L462xx) +#define GPIO_AF10_USB_FS ((uint8_t)0x0A) /* USB_FS Alternate Function mapping */ +#endif /* STM32L452xx || STM32L462xx */ +#define GPIO_AF10_QUADSPI ((uint8_t)0x0A) /* QUADSPI Alternate Function mapping */ +#define GPIO_AF10_CAN1 ((uint8_t)0x0A) /* CAN1 Alternate Function mapping */ + +/** + * @brief AF 11 selection + */ + +/** + * @brief AF 12 selection + */ +#define GPIO_AF12_COMP1 ((uint8_t)0x0C) /* COMP1 Alternate Function mapping */ +#define GPIO_AF12_COMP2 ((uint8_t)0x0C) /* COMP2 Alternate Function mapping */ +#define GPIO_AF12_SDMMC1 ((uint8_t)0x0C) /* SDMMC1 Alternate Function mapping */ + +/** + * @brief AF 13 selection + */ +#define GPIO_AF13_SAI1 ((uint8_t)0x0D) /* SAI1 Alternate Function mapping */ + +/** + * @brief AF 14 selection + */ +#define GPIO_AF14_TIM2 ((uint8_t)0x0E) /* TIM2 Alternate Function mapping */ +#define GPIO_AF14_TIM15 ((uint8_t)0x0E) /* TIM15 Alternate Function mapping */ +#define GPIO_AF14_TIM16 ((uint8_t)0x0E) /* TIM16 Alternate Function mapping */ +#define GPIO_AF14_TIM17 ((uint8_t)0x0E) /* TIM17 Alternate Function mapping */ +#define GPIO_AF14_LPTIM2 ((uint8_t)0x0E) /* LPTIM2 Alternate Function mapping */ + +/** + * @brief AF 15 selection + */ +#define GPIO_AF15_EVENTOUT ((uint8_t)0x0F) /* EVENTOUT Alternate Function mapping */ + +#define IS_GPIO_AF(AF) ((AF) <= (uint8_t)0x0F) + +#endif /* STM32L451xx || STM32L452xx || STM32L462xx */ + +#if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) +/*--------------STM32L471xx/STM32L475xx/STM32L476xx/STM32L485xx/STM32L486xx---*/ +/** + * @brief AF 0 selection + */ +#define GPIO_AF0_RTC_50Hz ((uint8_t)0x00) /* RTC_50Hz Alternate Function mapping */ +#define GPIO_AF0_MCO ((uint8_t)0x00) /* MCO (MCO1 and MCO2) Alternate Function mapping */ +#define GPIO_AF0_SWJ ((uint8_t)0x00) /* SWJ (SWD and JTAG) Alternate Function mapping */ +#if defined(STM32L476xx) || defined(STM32L486xx) +#define GPIO_AF0_LCDBIAS ((uint8_t)0x00) /* LCDBIAS Alternate Function mapping */ +#endif /* STM32L476xx || STM32L486xx */ +#define GPIO_AF0_TRACE ((uint8_t)0x00) /* TRACE Alternate Function mapping */ + +/** + * @brief AF 1 selection + */ +#define GPIO_AF1_TIM1 ((uint8_t)0x01) /* TIM1 Alternate Function mapping */ +#define GPIO_AF1_TIM2 ((uint8_t)0x01) /* TIM2 Alternate Function mapping */ +#define GPIO_AF1_TIM5 ((uint8_t)0x01) /* TIM5 Alternate Function mapping */ +#define GPIO_AF1_TIM8 ((uint8_t)0x01) /* TIM8 Alternate Function mapping */ +#define GPIO_AF1_LPTIM1 ((uint8_t)0x01) /* LPTIM1 Alternate Function mapping */ +#define GPIO_AF1_IR ((uint8_t)0x01) /* IR Alternate Function mapping */ + +/** + * @brief AF 2 selection + */ +#define GPIO_AF2_TIM1 ((uint8_t)0x02) /* TIM1 Alternate Function mapping */ +#define GPIO_AF2_TIM2 ((uint8_t)0x02) /* TIM2 Alternate Function mapping */ +#define GPIO_AF2_TIM3 ((uint8_t)0x02) /* TIM3 Alternate Function mapping */ +#define GPIO_AF2_TIM4 ((uint8_t)0x02) /* TIM4 Alternate Function mapping */ +#define GPIO_AF2_TIM5 ((uint8_t)0x02) /* TIM5 Alternate Function mapping */ + +/** + * @brief AF 3 selection + */ +#define GPIO_AF3_TIM8 ((uint8_t)0x03) /* TIM8 Alternate Function mapping */ +#define GPIO_AF3_TIM1_COMP2 ((uint8_t)0x03) /* TIM1/COMP2 Break in Alternate Function mapping */ +#define GPIO_AF3_TIM1_COMP1 ((uint8_t)0x03) /* TIM1/COMP1 Break in Alternate Function mapping */ + +/** + * @brief AF 4 selection + */ +#define GPIO_AF4_I2C1 ((uint8_t)0x04) /* I2C1 Alternate Function mapping */ +#define GPIO_AF4_I2C2 ((uint8_t)0x04) /* I2C2 Alternate Function mapping */ +#define GPIO_AF4_I2C3 ((uint8_t)0x04) /* I2C3 Alternate Function mapping */ + +/** + * @brief AF 5 selection + */ +#define GPIO_AF5_SPI1 ((uint8_t)0x05) /* SPI1 Alternate Function mapping */ +#define GPIO_AF5_SPI2 ((uint8_t)0x05) /* SPI2 Alternate Function mapping */ + +/** + * @brief AF 6 selection + */ +#define GPIO_AF6_SPI3 ((uint8_t)0x06) /* SPI3 Alternate Function mapping */ +#define GPIO_AF6_DFSDM1 ((uint8_t)0x06) /* DFSDM1 Alternate Function mapping */ + +/** + * @brief AF 7 selection + */ +#define GPIO_AF7_USART1 ((uint8_t)0x07) /* USART1 Alternate Function mapping */ +#define GPIO_AF7_USART2 ((uint8_t)0x07) /* USART2 Alternate Function mapping */ +#define GPIO_AF7_USART3 ((uint8_t)0x07) /* USART3 Alternate Function mapping */ + +/** + * @brief AF 8 selection + */ +#define GPIO_AF8_UART4 ((uint8_t)0x08) /* UART4 Alternate Function mapping */ +#define GPIO_AF8_UART5 ((uint8_t)0x08) /* UART5 Alternate Function mapping */ +#define GPIO_AF8_LPUART1 ((uint8_t)0x08) /* LPUART1 Alternate Function mapping */ + + +/** + * @brief AF 9 selection + */ +#define GPIO_AF9_CAN1 ((uint8_t)0x09) /* CAN1 Alternate Function mapping */ +#define GPIO_AF9_TSC ((uint8_t)0x09) /* TSC Alternate Function mapping */ + +/** + * @brief AF 10 selection + */ +#if defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) +#define GPIO_AF10_OTG_FS ((uint8_t)0x0A) /* OTG_FS Alternate Function mapping */ +#endif /* STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx */ +#define GPIO_AF10_QUADSPI ((uint8_t)0x0A) /* QUADSPI Alternate Function mapping */ + +#if defined(STM32L476xx) || defined(STM32L486xx) +/** + * @brief AF 11 selection + */ +#define GPIO_AF11_LCD ((uint8_t)0x0B) /* LCD Alternate Function mapping */ +#endif /* STM32L476xx || STM32L486xx */ + +/** + * @brief AF 12 selection + */ +#define GPIO_AF12_FMC ((uint8_t)0x0C) /* FMC Alternate Function mapping */ +#define GPIO_AF12_SWPMI1 ((uint8_t)0x0C) /* SWPMI1 Alternate Function mapping */ +#define GPIO_AF12_COMP1 ((uint8_t)0x0C) /* COMP1 Alternate Function mapping */ +#define GPIO_AF12_COMP2 ((uint8_t)0x0C) /* COMP2 Alternate Function mapping */ +#define GPIO_AF12_SDMMC1 ((uint8_t)0x0C) /* SDMMC1 Alternate Function mapping */ + +/** + * @brief AF 13 selection + */ +#define GPIO_AF13_SAI1 ((uint8_t)0x0D) /* SAI1 Alternate Function mapping */ +#define GPIO_AF13_SAI2 ((uint8_t)0x0D) /* SAI2 Alternate Function mapping */ +#define GPIO_AF13_TIM8_COMP2 ((uint8_t)0x0D) /* TIM8/COMP2 Break in Alternate Function mapping */ +#define GPIO_AF13_TIM8_COMP1 ((uint8_t)0x0D) /* TIM8/COMP1 Break in Alternate Function mapping */ + +/** + * @brief AF 14 selection + */ +#define GPIO_AF14_TIM2 ((uint8_t)0x0E) /* TIM2 Alternate Function mapping */ +#define GPIO_AF14_TIM15 ((uint8_t)0x0E) /* TIM15 Alternate Function mapping */ +#define GPIO_AF14_TIM16 ((uint8_t)0x0E) /* TIM16 Alternate Function mapping */ +#define GPIO_AF14_TIM17 ((uint8_t)0x0E) /* TIM17 Alternate Function mapping */ +#define GPIO_AF14_LPTIM2 ((uint8_t)0x0E) /* LPTIM2 Alternate Function mapping */ +#define GPIO_AF14_TIM8_COMP1 ((uint8_t)0x0E) /* TIM8/COMP1 Break in Alternate Function mapping */ + +/** + * @brief AF 15 selection + */ +#define GPIO_AF15_EVENTOUT ((uint8_t)0x0F) /* EVENTOUT Alternate Function mapping */ + +#define IS_GPIO_AF(AF) ((AF) <= (uint8_t)0x0F) + +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx */ + +#if defined(STM32L496xx) || defined(STM32L4A6xx) +/*--------------------------------STM32L496xx/STM32L4A6xx---------------------*/ +/** + * @brief AF 0 selection + */ +#define GPIO_AF0_RTC_50Hz ((uint8_t)0x00) /* RTC_50Hz Alternate Function mapping */ +#define GPIO_AF0_MCO ((uint8_t)0x00) /* MCO (MCO1 and MCO2) Alternate Function mapping */ +#define GPIO_AF0_SWJ ((uint8_t)0x00) /* SWJ (SWD and JTAG) Alternate Function mapping */ +#define GPIO_AF0_TRACE ((uint8_t)0x00) /* TRACE Alternate Function mapping */ + +/** + * @brief AF 1 selection + */ +#define GPIO_AF1_TIM1 ((uint8_t)0x01) /* TIM1 Alternate Function mapping */ +#define GPIO_AF1_TIM2 ((uint8_t)0x01) /* TIM2 Alternate Function mapping */ +#define GPIO_AF1_TIM5 ((uint8_t)0x01) /* TIM5 Alternate Function mapping */ +#define GPIO_AF1_TIM8 ((uint8_t)0x01) /* TIM8 Alternate Function mapping */ +#define GPIO_AF1_LPTIM1 ((uint8_t)0x01) /* LPTIM1 Alternate Function mapping */ +#define GPIO_AF1_IR ((uint8_t)0x01) /* IR Alternate Function mapping */ + +/** + * @brief AF 2 selection + */ +#define GPIO_AF2_TIM1 ((uint8_t)0x02) /* TIM1 Alternate Function mapping */ +#define GPIO_AF2_TIM2 ((uint8_t)0x02) /* TIM2 Alternate Function mapping */ +#define GPIO_AF2_TIM3 ((uint8_t)0x02) /* TIM3 Alternate Function mapping */ +#define GPIO_AF2_TIM4 ((uint8_t)0x02) /* TIM4 Alternate Function mapping */ +#define GPIO_AF2_TIM5 ((uint8_t)0x02) /* TIM5 Alternate Function mapping */ +#define GPIO_AF2_I2C4 ((uint8_t)0x02) /* I2C4 Alternate Function mapping */ + +/** + * @brief AF 3 selection + */ +#define GPIO_AF3_TIM8 ((uint8_t)0x03) /* TIM8 Alternate Function mapping */ +#define GPIO_AF3_TIM1_COMP2 ((uint8_t)0x03) /* TIM1/COMP2 Break in Alternate Function mapping */ +#define GPIO_AF3_TIM1_COMP1 ((uint8_t)0x03) /* TIM1/COMP1 Break in Alternate Function mapping */ +#define GPIO_AF3_CAN2 ((uint8_t)0x03) /* CAN2 Alternate Function mapping */ +#define GPIO_AF3_I2C4 ((uint8_t)0x03) /* I2C4 Alternate Function mapping */ +#define GPIO_AF3_QUADSPI ((uint8_t)0x03) /* QUADSPI Alternate Function mapping */ +#define GPIO_AF3_SPI2 ((uint8_t)0x03) /* SPI2 Alternate Function mapping */ +#define GPIO_AF3_USART2 ((uint8_t)0x03) /* USART2 Alternate Function mapping */ + +/** + * @brief AF 4 selection + */ +#define GPIO_AF4_I2C1 ((uint8_t)0x04) /* I2C1 Alternate Function mapping */ +#define GPIO_AF4_I2C2 ((uint8_t)0x04) /* I2C2 Alternate Function mapping */ +#define GPIO_AF4_I2C3 ((uint8_t)0x04) /* I2C3 Alternate Function mapping */ +#define GPIO_AF4_I2C4 ((uint8_t)0x04) /* I2C4 Alternate Function mapping */ +#define GPIO_AF4_DCMI ((uint8_t)0x04) /* DCMI Alternate Function mapping */ + +/** + * @brief AF 5 selection + */ +#define GPIO_AF5_SPI1 ((uint8_t)0x05) /* SPI1 Alternate Function mapping */ +#define GPIO_AF5_SPI2 ((uint8_t)0x05) /* SPI2 Alternate Function mapping */ +#define GPIO_AF5_DCMI ((uint8_t)0x05) /* DCMI Alternate Function mapping */ +#define GPIO_AF5_I2C4 ((uint8_t)0x05) /* I2C4 Alternate Function mapping */ +#define GPIO_AF5_QUADSPI ((uint8_t)0x05) /* QUADSPI Alternate Function mapping */ + +/** + * @brief AF 6 selection + */ +#define GPIO_AF6_SPI3 ((uint8_t)0x06) /* SPI3 Alternate Function mapping */ +#define GPIO_AF6_DFSDM1 ((uint8_t)0x06) /* DFSDM1 Alternate Function mapping */ +#define GPIO_AF6_I2C3 ((uint8_t)0x06) /* I2C3 Alternate Function mapping */ + +/** + * @brief AF 7 selection + */ +#define GPIO_AF7_USART1 ((uint8_t)0x07) /* USART1 Alternate Function mapping */ +#define GPIO_AF7_USART2 ((uint8_t)0x07) /* USART2 Alternate Function mapping */ +#define GPIO_AF7_USART3 ((uint8_t)0x07) /* USART3 Alternate Function mapping */ + +/** + * @brief AF 8 selection + */ +#define GPIO_AF8_UART4 ((uint8_t)0x08) /* UART4 Alternate Function mapping */ +#define GPIO_AF8_UART5 ((uint8_t)0x08) /* UART5 Alternate Function mapping */ +#define GPIO_AF8_LPUART1 ((uint8_t)0x08) /* LPUART1 Alternate Function mapping */ +#define GPIO_AF8_CAN2 ((uint8_t)0x08) /* CAN2 Alternate Function mapping */ + +/** + * @brief AF 9 selection + */ +#define GPIO_AF9_CAN1 ((uint8_t)0x09) /* CAN1 Alternate Function mapping */ +#define GPIO_AF9_TSC ((uint8_t)0x09) /* TSC Alternate Function mapping */ + +/** + * @brief AF 10 selection + */ +#define GPIO_AF10_OTG_FS ((uint8_t)0x0A) /* OTG_FS Alternate Function mapping */ +#define GPIO_AF10_QUADSPI ((uint8_t)0x0A) /* QUADSPI Alternate Function mapping */ +#define GPIO_AF10_CAN2 ((uint8_t)0x0A) /* CAN2 Alternate Function mapping */ +#define GPIO_AF10_DCMI ((uint8_t)0x0A) /* DCMI Alternate Function mapping */ + +/** + * @brief AF 11 selection + */ +#define GPIO_AF11_LCD ((uint8_t)0x0B) /* LCD Alternate Function mapping */ + +/** + * @brief AF 12 selection + */ +#define GPIO_AF12_FMC ((uint8_t)0x0C) /* FMC Alternate Function mapping */ +#define GPIO_AF12_SWPMI1 ((uint8_t)0x0C) /* SWPMI1 Alternate Function mapping */ +#define GPIO_AF12_COMP1 ((uint8_t)0x0C) /* COMP1 Alternate Function mapping */ +#define GPIO_AF12_COMP2 ((uint8_t)0x0C) /* COMP2 Alternate Function mapping */ +#define GPIO_AF12_SDMMC1 ((uint8_t)0x0C) /* SDMMC1 Alternate Function mapping */ +#define GPIO_AF12_TIM1_COMP2 ((uint8_t)0x0C) /* TIM1/COMP2 Break in Alternate Function mapping */ +#define GPIO_AF12_TIM1_COMP1 ((uint8_t)0x0C) /* TIM1/COMP1 Break in Alternate Function mapping */ +#define GPIO_AF12_TIM8_COMP2 ((uint8_t)0x0C) /* TIM8/COMP2 Break in Alternate Function mapping */ + +/** + * @brief AF 13 selection + */ +#define GPIO_AF13_SAI1 ((uint8_t)0x0D) /* SAI1 Alternate Function mapping */ +#define GPIO_AF13_SAI2 ((uint8_t)0x0D) /* SAI2 Alternate Function mapping */ +#define GPIO_AF13_TIM8_COMP2 ((uint8_t)0x0D) /* TIM8/COMP2 Break in Alternate Function mapping */ +#define GPIO_AF13_TIM8_COMP1 ((uint8_t)0x0D) /* TIM8/COMP1 Break in Alternate Function mapping */ + +/** + * @brief AF 14 selection + */ +#define GPIO_AF14_TIM2 ((uint8_t)0x0E) /* TIM2 Alternate Function mapping */ +#define GPIO_AF14_TIM15 ((uint8_t)0x0E) /* TIM15 Alternate Function mapping */ +#define GPIO_AF14_TIM16 ((uint8_t)0x0E) /* TIM16 Alternate Function mapping */ +#define GPIO_AF14_TIM17 ((uint8_t)0x0E) /* TIM17 Alternate Function mapping */ +#define GPIO_AF14_LPTIM2 ((uint8_t)0x0E) /* LPTIM2 Alternate Function mapping */ +#define GPIO_AF14_TIM8_COMP1 ((uint8_t)0x0E) /* TIM8/COMP1 Break in Alternate Function mapping */ + +/** + * @brief AF 15 selection + */ +#define GPIO_AF15_EVENTOUT ((uint8_t)0x0F) /* EVENTOUT Alternate Function mapping */ + +#define IS_GPIO_AF(AF) ((AF) <= (uint8_t)0x0F) + +#endif /* STM32L496xx || STM32L4A6xx */ + +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +/*---STM32L4R5xx/STM32L4R7xx/STM32L4R9xx/STM32L4S5xx/STM32L4S7xx/STM32L4S9xx--*/ +/** + * @brief AF 0 selection + */ +#define GPIO_AF0_RTC_50Hz ((uint8_t)0x00) /* RTC_50Hz Alternate Function mapping */ +#define GPIO_AF0_MCO ((uint8_t)0x00) /* MCO (MCO1 and MCO2) Alternate Function mapping */ +#define GPIO_AF0_SWJ ((uint8_t)0x00) /* SWJ (SWD and JTAG) Alternate Function mapping */ +#define GPIO_AF0_TRACE ((uint8_t)0x00) /* TRACE Alternate Function mapping */ + +/** + * @brief AF 1 selection + */ +#define GPIO_AF1_TIM1 ((uint8_t)0x01) /* TIM1 Alternate Function mapping */ +#define GPIO_AF1_TIM2 ((uint8_t)0x01) /* TIM2 Alternate Function mapping */ +#define GPIO_AF1_TIM5 ((uint8_t)0x01) /* TIM5 Alternate Function mapping */ +#define GPIO_AF1_TIM8 ((uint8_t)0x01) /* TIM8 Alternate Function mapping */ +#define GPIO_AF1_LPTIM1 ((uint8_t)0x01) /* LPTIM1 Alternate Function mapping */ +#define GPIO_AF1_IR ((uint8_t)0x01) /* IR Alternate Function mapping */ + +/** + * @brief AF 2 selection + */ +#define GPIO_AF2_TIM1 ((uint8_t)0x02) /* TIM1 Alternate Function mapping */ +#define GPIO_AF2_TIM2 ((uint8_t)0x02) /* TIM2 Alternate Function mapping */ +#define GPIO_AF2_TIM3 ((uint8_t)0x02) /* TIM3 Alternate Function mapping */ +#define GPIO_AF2_TIM4 ((uint8_t)0x02) /* TIM4 Alternate Function mapping */ +#define GPIO_AF2_TIM5 ((uint8_t)0x02) /* TIM5 Alternate Function mapping */ + +/** + * @brief AF 3 selection + */ +#define GPIO_AF3_I2C4 ((uint8_t)0x03) /* I2C4 Alternate Function mapping */ +#define GPIO_AF3_OCTOSPIM_P1 ((uint8_t)0x03) /* OctoSPI Manager Port 1 Alternate Function mapping */ +#define GPIO_AF3_SAI1 ((uint8_t)0x03) /* SAI1 Alternate Function mapping */ +#define GPIO_AF3_SPI2 ((uint8_t)0x03) /* SPI2 Alternate Function mapping */ +#define GPIO_AF3_TIM1_COMP1 ((uint8_t)0x03) /* TIM1/COMP1 Break in Alternate Function mapping */ +#define GPIO_AF3_TIM1_COMP2 ((uint8_t)0x03) /* TIM1/COMP2 Break in Alternate Function mapping */ +#define GPIO_AF3_TIM8 ((uint8_t)0x03) /* TIM8 Alternate Function mapping */ +#define GPIO_AF3_TIM8_COMP1 ((uint8_t)0x03) /* TIM8/COMP1 Break in Alternate Function mapping */ +#define GPIO_AF3_TIM8_COMP2 ((uint8_t)0x03) /* TIM8/COMP2 Break in Alternate Function mapping */ +#define GPIO_AF3_USART2 ((uint8_t)0x03) /* USART2 Alternate Function mapping */ + +/** + * @brief AF 4 selection + */ +#define GPIO_AF4_I2C1 ((uint8_t)0x04) /* I2C1 Alternate Function mapping */ +#define GPIO_AF4_I2C2 ((uint8_t)0x04) /* I2C2 Alternate Function mapping */ +#define GPIO_AF4_I2C3 ((uint8_t)0x04) /* I2C3 Alternate Function mapping */ +#define GPIO_AF4_I2C4 ((uint8_t)0x04) /* I2C4 Alternate Function mapping */ +#define GPIO_AF4_DCMI ((uint8_t)0x04) /* DCMI Alternate Function mapping */ + +/** + * @brief AF 5 selection + */ +#define GPIO_AF5_DCMI ((uint8_t)0x05) /* DCMI Alternate Function mapping */ +#define GPIO_AF5_DFSDM1 ((uint8_t)0x05) /* DFSDM1 Alternate Function mapping */ +#define GPIO_AF5_I2C4 ((uint8_t)0x05) /* I2C4 Alternate Function mapping */ +#define GPIO_AF5_OCTOSPIM_P1 ((uint8_t)0x05) /* OctoSPI Manager Port 1 Alternate Function mapping */ +#define GPIO_AF5_OCTOSPIM_P2 ((uint8_t)0x05) /* OctoSPI Manager Port 2 Alternate Function mapping */ +#define GPIO_AF5_SPI1 ((uint8_t)0x05) /* SPI1 Alternate Function mapping */ +#define GPIO_AF5_SPI2 ((uint8_t)0x05) /* SPI2 Alternate Function mapping */ +#define GPIO_AF5_SPI3 ((uint8_t)0x05) /* SPI2 Alternate Function mapping */ + +/** + * @brief AF 6 selection + */ +#define GPIO_AF6_DFSDM1 ((uint8_t)0x06) /* DFSDM1 Alternate Function mapping */ +#define GPIO_AF6_I2C3 ((uint8_t)0x06) /* I2C3 Alternate Function mapping */ +#define GPIO_AF6_SPI3 ((uint8_t)0x06) /* SPI3 Alternate Function mapping */ + +/** + * @brief AF 7 selection + */ +#define GPIO_AF7_USART1 ((uint8_t)0x07) /* USART1 Alternate Function mapping */ +#define GPIO_AF7_USART2 ((uint8_t)0x07) /* USART2 Alternate Function mapping */ +#define GPIO_AF7_USART3 ((uint8_t)0x07) /* USART3 Alternate Function mapping */ + +/** + * @brief AF 8 selection + */ +#define GPIO_AF8_LPUART1 ((uint8_t)0x08) /* LPUART1 Alternate Function mapping */ +#define GPIO_AF8_SDMMC1 ((uint8_t)0x08) /* SDMMC1 Alternate Function mapping */ +#define GPIO_AF8_UART4 ((uint8_t)0x08) /* UART4 Alternate Function mapping */ +#define GPIO_AF8_UART5 ((uint8_t)0x08) /* UART5 Alternate Function mapping */ + +/** + * @brief AF 9 selection + */ +#define GPIO_AF9_CAN1 ((uint8_t)0x09) /* CAN1 Alternate Function mapping */ +#define GPIO_AF9_LTDC ((uint8_t)0x09) /* LTDC Alternate Function mapping */ +#define GPIO_AF9_TSC ((uint8_t)0x09) /* TSC Alternate Function mapping */ + +/** + * @brief AF 10 selection + */ +#define GPIO_AF10_DCMI ((uint8_t)0x0A) /* DCMI Alternate Function mapping */ +#define GPIO_AF10_OCTOSPIM_P1 ((uint8_t)0x0A) /* OctoSPI Manager Port 1 Alternate Function mapping */ +#define GPIO_AF10_OCTOSPIM_P2 ((uint8_t)0x0A) /* OctoSPI Manager Port 2 Alternate Function mapping */ +#define GPIO_AF10_OTG_FS ((uint8_t)0x0A) /* OTG_FS Alternate Function mapping */ + +/** + * @brief AF 11 selection + */ +#define GPIO_AF11_DSI ((uint8_t)0x0B) /* DSI Alternate Function mapping */ +#define GPIO_AF11_LTDC ((uint8_t)0x0B) /* LTDC Alternate Function mapping */ + +/** + * @brief AF 12 selection + */ +#define GPIO_AF12_COMP1 ((uint8_t)0x0C) /* COMP1 Alternate Function mapping */ +#define GPIO_AF12_COMP2 ((uint8_t)0x0C) /* COMP2 Alternate Function mapping */ +#define GPIO_AF12_DSI ((uint8_t)0x0C) /* FMC Alternate Function mapping */ +#define GPIO_AF12_FMC ((uint8_t)0x0C) /* FMC Alternate Function mapping */ +#define GPIO_AF12_SDMMC1 ((uint8_t)0x0C) /* SDMMC1 Alternate Function mapping */ +#define GPIO_AF12_TIM1_COMP1 ((uint8_t)0x0C) /* TIM1/COMP1 Break in Alternate Function mapping */ +#define GPIO_AF12_TIM1_COMP2 ((uint8_t)0x0C) /* TIM1/COMP2 Break in Alternate Function mapping */ +#define GPIO_AF12_TIM8_COMP2 ((uint8_t)0x0C) /* TIM8/COMP2 Break in Alternate Function mapping */ + +/** + * @brief AF 13 selection + */ +#define GPIO_AF13_SAI1 ((uint8_t)0x0D) /* SAI1 Alternate Function mapping */ +#define GPIO_AF13_SAI2 ((uint8_t)0x0D) /* SAI2 Alternate Function mapping */ +#define GPIO_AF13_TIM8_COMP1 ((uint8_t)0x0D) /* TIM8/COMP1 Break in Alternate Function mapping */ + +/** + * @brief AF 14 selection + */ +#define GPIO_AF14_TIM15 ((uint8_t)0x0E) /* TIM15 Alternate Function mapping */ +#define GPIO_AF14_TIM16 ((uint8_t)0x0E) /* TIM16 Alternate Function mapping */ +#define GPIO_AF14_TIM17 ((uint8_t)0x0E) /* TIM17 Alternate Function mapping */ +#define GPIO_AF14_LPTIM2 ((uint8_t)0x0E) /* LPTIM2 Alternate Function mapping */ +#define GPIO_AF14_TIM8_COMP2 ((uint8_t)0x0E) /* TIM8/COMP2 Break in Alternate Function mapping */ + +/** + * @brief AF 15 selection + */ +#define GPIO_AF15_EVENTOUT ((uint8_t)0x0F) /* EVENTOUT Alternate Function mapping */ + +#define IS_GPIO_AF(AF) ((AF) <= (uint8_t)0x0F) + +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup GPIOEx_Exported_Macros GPIOEx Exported Macros + * @{ + */ + +/** @defgroup GPIOEx_Get_Port_Index GPIOEx_Get Port Index +* @{ + */ +#if defined(STM32L431xx) || defined(STM32L433xx) || defined(STM32L443xx) + +#define GPIO_GET_INDEX(__GPIOx__) (((__GPIOx__) == (GPIOA))? 0U :\ + ((__GPIOx__) == (GPIOB))? 1U :\ + ((__GPIOx__) == (GPIOC))? 2U :\ + ((__GPIOx__) == (GPIOD))? 3U :\ + ((__GPIOx__) == (GPIOE))? 4U : 7U) + +#endif /* STM32L431xx || STM32L433xx || STM32L443xx */ + +#if defined(STM32L432xx) || defined(STM32L442xx) + +#define GPIO_GET_INDEX(__GPIOx__) (((__GPIOx__) == (GPIOA))? 0U :\ + ((__GPIOx__) == (GPIOB))? 1U :\ + ((__GPIOx__) == (GPIOC))? 2U : 7U) + +#endif /* STM32L432xx || STM32L442xx */ + +#if defined(STM32L451xx) || defined(STM32L452xx) || defined(STM32L462xx) + +#define GPIO_GET_INDEX(__GPIOx__) (((__GPIOx__) == (GPIOA))? 0U :\ + ((__GPIOx__) == (GPIOB))? 1U :\ + ((__GPIOx__) == (GPIOC))? 2U :\ + ((__GPIOx__) == (GPIOD))? 3U :\ + ((__GPIOx__) == (GPIOE))? 4U : 7U) + +#endif /* STM32L451xx || STM32L452xx || STM32L462xx */ + +#if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) + +#define GPIO_GET_INDEX(__GPIOx__) (((__GPIOx__) == (GPIOA))? 0U :\ + ((__GPIOx__) == (GPIOB))? 1U :\ + ((__GPIOx__) == (GPIOC))? 2U :\ + ((__GPIOx__) == (GPIOD))? 3U :\ + ((__GPIOx__) == (GPIOE))? 4U :\ + ((__GPIOx__) == (GPIOF))? 5U :\ + ((__GPIOx__) == (GPIOG))? 6U : 7U) + +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx */ + +#if defined(STM32L496xx) || defined(STM32L4A6xx) + +#define GPIO_GET_INDEX(__GPIOx__) (((__GPIOx__) == (GPIOA))? 0U :\ + ((__GPIOx__) == (GPIOB))? 1U :\ + ((__GPIOx__) == (GPIOC))? 2U :\ + ((__GPIOx__) == (GPIOD))? 3U :\ + ((__GPIOx__) == (GPIOE))? 4U :\ + ((__GPIOx__) == (GPIOF))? 5U :\ + ((__GPIOx__) == (GPIOG))? 6U :\ + ((__GPIOx__) == (GPIOH))? 7U : 8U) + +#endif /* STM32L496xx || STM32L4A6xx */ + +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + +#define GPIO_GET_INDEX(__GPIOx__) (((__GPIOx__) == (GPIOA))? 0U :\ + ((__GPIOx__) == (GPIOB))? 1U :\ + ((__GPIOx__) == (GPIOC))? 2U :\ + ((__GPIOx__) == (GPIOD))? 3U :\ + ((__GPIOx__) == (GPIOE))? 4U :\ + ((__GPIOx__) == (GPIOF))? 5U :\ + ((__GPIOx__) == (GPIOG))? 6U :\ + ((__GPIOx__) == (GPIOH))? 7U : 8U) + +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +/** + * @} + */ + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_HAL_GPIO_EX_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_i2c.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_i2c.h new file mode 100644 index 0000000..7a8f85f --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_i2c.h @@ -0,0 +1,708 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_i2c.h + * @author MCD Application Team + * @brief Header file of I2C HAL module. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_I2C_H +#define __STM32L4xx_HAL_I2C_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup I2C + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup I2C_Exported_Types I2C Exported Types + * @{ + */ + +/** @defgroup I2C_Configuration_Structure_definition I2C Configuration Structure definition + * @brief I2C Configuration Structure definition + * @{ + */ +typedef struct +{ + uint32_t Timing; /*!< Specifies the I2C_TIMINGR_register value. + This parameter calculated by referring to I2C initialization + section in Reference manual */ + + uint32_t OwnAddress1; /*!< Specifies the first device own address. + This parameter can be a 7-bit or 10-bit address. */ + + uint32_t AddressingMode; /*!< Specifies if 7-bit or 10-bit addressing mode is selected. + This parameter can be a value of @ref I2C_ADDRESSING_MODE */ + + uint32_t DualAddressMode; /*!< Specifies if dual addressing mode is selected. + This parameter can be a value of @ref I2C_DUAL_ADDRESSING_MODE */ + + uint32_t OwnAddress2; /*!< Specifies the second device own address if dual addressing mode is selected + This parameter can be a 7-bit address. */ + + uint32_t OwnAddress2Masks; /*!< Specifies the acknowledge mask address second device own address if dual addressing mode is selected + This parameter can be a value of @ref I2C_OWN_ADDRESS2_MASKS */ + + uint32_t GeneralCallMode; /*!< Specifies if general call mode is selected. + This parameter can be a value of @ref I2C_GENERAL_CALL_ADDRESSING_MODE */ + + uint32_t NoStretchMode; /*!< Specifies if nostretch mode is selected. + This parameter can be a value of @ref I2C_NOSTRETCH_MODE */ + +} I2C_InitTypeDef; + +/** + * @} + */ + +/** @defgroup HAL_state_structure_definition HAL state structure definition + * @brief HAL State structure definition + * @note HAL I2C State value coding follow below described bitmap :\n + * b7-b6 Error information\n + * 00 : No Error\n + * 01 : Abort (Abort user request on going)\n + * 10 : Timeout\n + * 11 : Error\n + * b5 IP initilisation status\n + * 0 : Reset (IP not initialized)\n + * 1 : Init done (IP initialized and ready to use. HAL I2C Init function called)\n + * b4 (not used)\n + * x : Should be set to 0\n + * b3\n + * 0 : Ready or Busy (No Listen mode ongoing)\n + * 1 : Listen (IP in Address Listen Mode)\n + * b2 Intrinsic process state\n + * 0 : Ready\n + * 1 : Busy (IP busy with some configuration or internal operations)\n + * b1 Rx state\n + * 0 : Ready (no Rx operation ongoing)\n + * 1 : Busy (Rx operation ongoing)\n + * b0 Tx state\n + * 0 : Ready (no Tx operation ongoing)\n + * 1 : Busy (Tx operation ongoing) + * @{ + */ +typedef enum +{ + HAL_I2C_STATE_RESET = 0x00U, /*!< Peripheral is not yet Initialized */ + HAL_I2C_STATE_READY = 0x20U, /*!< Peripheral Initialized and ready for use */ + HAL_I2C_STATE_BUSY = 0x24U, /*!< An internal process is ongoing */ + HAL_I2C_STATE_BUSY_TX = 0x21U, /*!< Data Transmission process is ongoing */ + HAL_I2C_STATE_BUSY_RX = 0x22U, /*!< Data Reception process is ongoing */ + HAL_I2C_STATE_LISTEN = 0x28U, /*!< Address Listen Mode is ongoing */ + HAL_I2C_STATE_BUSY_TX_LISTEN = 0x29U, /*!< Address Listen Mode and Data Transmission + process is ongoing */ + HAL_I2C_STATE_BUSY_RX_LISTEN = 0x2AU, /*!< Address Listen Mode and Data Reception + process is ongoing */ + HAL_I2C_STATE_ABORT = 0x60U, /*!< Abort user request ongoing */ + HAL_I2C_STATE_TIMEOUT = 0xA0U, /*!< Timeout state */ + HAL_I2C_STATE_ERROR = 0xE0U /*!< Error */ + +} HAL_I2C_StateTypeDef; + +/** + * @} + */ + +/** @defgroup HAL_mode_structure_definition HAL mode structure definition + * @brief HAL Mode structure definition + * @note HAL I2C Mode value coding follow below described bitmap :\n + * b7 (not used)\n + * x : Should be set to 0\n + * b6\n + * 0 : None\n + * 1 : Memory (HAL I2C communication is in Memory Mode)\n + * b5\n + * 0 : None\n + * 1 : Slave (HAL I2C communication is in Slave Mode)\n + * b4\n + * 0 : None\n + * 1 : Master (HAL I2C communication is in Master Mode)\n + * b3-b2-b1-b0 (not used)\n + * xxxx : Should be set to 0000 + * @{ + */ +typedef enum +{ + HAL_I2C_MODE_NONE = 0x00U, /*!< No I2C communication on going */ + HAL_I2C_MODE_MASTER = 0x10U, /*!< I2C communication is in Master Mode */ + HAL_I2C_MODE_SLAVE = 0x20U, /*!< I2C communication is in Slave Mode */ + HAL_I2C_MODE_MEM = 0x40U /*!< I2C communication is in Memory Mode */ + +} HAL_I2C_ModeTypeDef; + +/** + * @} + */ + +/** @defgroup I2C_Error_Code_definition I2C Error Code definition + * @brief I2C Error Code definition + * @{ + */ +#define HAL_I2C_ERROR_NONE (0x00000000U) /*!< No error */ +#define HAL_I2C_ERROR_BERR (0x00000001U) /*!< BERR error */ +#define HAL_I2C_ERROR_ARLO (0x00000002U) /*!< ARLO error */ +#define HAL_I2C_ERROR_AF (0x00000004U) /*!< ACKF error */ +#define HAL_I2C_ERROR_OVR (0x00000008U) /*!< OVR error */ +#define HAL_I2C_ERROR_DMA (0x00000010U) /*!< DMA transfer error */ +#define HAL_I2C_ERROR_TIMEOUT (0x00000020U) /*!< Timeout error */ +#define HAL_I2C_ERROR_SIZE (0x00000040U) /*!< Size Management error */ +/** + * @} + */ + +/** @defgroup I2C_handle_Structure_definition I2C handle Structure definition + * @brief I2C handle Structure definition + * @{ + */ +typedef struct __I2C_HandleTypeDef +{ + I2C_TypeDef *Instance; /*!< I2C registers base address */ + + I2C_InitTypeDef Init; /*!< I2C communication parameters */ + + uint8_t *pBuffPtr; /*!< Pointer to I2C transfer buffer */ + + uint16_t XferSize; /*!< I2C transfer size */ + + __IO uint16_t XferCount; /*!< I2C transfer counter */ + + __IO uint32_t XferOptions; /*!< I2C sequantial transfer options, this parameter can + be a value of @ref I2C_XFEROPTIONS */ + + __IO uint32_t PreviousState; /*!< I2C communication Previous state */ + + HAL_StatusTypeDef(*XferISR)(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags, uint32_t ITSources); /*!< I2C transfer IRQ handler function pointer */ + + DMA_HandleTypeDef *hdmatx; /*!< I2C Tx DMA handle parameters */ + + DMA_HandleTypeDef *hdmarx; /*!< I2C Rx DMA handle parameters */ + + HAL_LockTypeDef Lock; /*!< I2C locking object */ + + __IO HAL_I2C_StateTypeDef State; /*!< I2C communication state */ + + __IO HAL_I2C_ModeTypeDef Mode; /*!< I2C communication mode */ + + __IO uint32_t ErrorCode; /*!< I2C Error code */ + + __IO uint32_t AddrEventCount; /*!< I2C Address Event counter */ +} I2C_HandleTypeDef; +/** + * @} + */ + +/** + * @} + */ +/* Exported constants --------------------------------------------------------*/ + +/** @defgroup I2C_Exported_Constants I2C Exported Constants + * @{ + */ + +/** @defgroup I2C_XFEROPTIONS I2C Sequential Transfer Options + * @{ + */ +#define I2C_FIRST_FRAME ((uint32_t)I2C_SOFTEND_MODE) +#define I2C_FIRST_AND_NEXT_FRAME ((uint32_t)(I2C_RELOAD_MODE | I2C_SOFTEND_MODE)) +#define I2C_NEXT_FRAME ((uint32_t)(I2C_RELOAD_MODE | I2C_SOFTEND_MODE)) +#define I2C_FIRST_AND_LAST_FRAME ((uint32_t)I2C_AUTOEND_MODE) +#define I2C_LAST_FRAME ((uint32_t)I2C_AUTOEND_MODE) +/** + * @} + */ + +/** @defgroup I2C_ADDRESSING_MODE I2C Addressing Mode + * @{ + */ +#define I2C_ADDRESSINGMODE_7BIT (0x00000001U) +#define I2C_ADDRESSINGMODE_10BIT (0x00000002U) +/** + * @} + */ + +/** @defgroup I2C_DUAL_ADDRESSING_MODE I2C Dual Addressing Mode + * @{ + */ +#define I2C_DUALADDRESS_DISABLE (0x00000000U) +#define I2C_DUALADDRESS_ENABLE I2C_OAR2_OA2EN +/** + * @} + */ + +/** @defgroup I2C_OWN_ADDRESS2_MASKS I2C Own Address2 Masks + * @{ + */ +#define I2C_OA2_NOMASK ((uint8_t)0x00U) +#define I2C_OA2_MASK01 ((uint8_t)0x01U) +#define I2C_OA2_MASK02 ((uint8_t)0x02U) +#define I2C_OA2_MASK03 ((uint8_t)0x03U) +#define I2C_OA2_MASK04 ((uint8_t)0x04U) +#define I2C_OA2_MASK05 ((uint8_t)0x05U) +#define I2C_OA2_MASK06 ((uint8_t)0x06U) +#define I2C_OA2_MASK07 ((uint8_t)0x07U) +/** + * @} + */ + +/** @defgroup I2C_GENERAL_CALL_ADDRESSING_MODE I2C General Call Addressing Mode + * @{ + */ +#define I2C_GENERALCALL_DISABLE (0x00000000U) +#define I2C_GENERALCALL_ENABLE I2C_CR1_GCEN +/** + * @} + */ + +/** @defgroup I2C_NOSTRETCH_MODE I2C No-Stretch Mode + * @{ + */ +#define I2C_NOSTRETCH_DISABLE (0x00000000U) +#define I2C_NOSTRETCH_ENABLE I2C_CR1_NOSTRETCH +/** + * @} + */ + +/** @defgroup I2C_MEMORY_ADDRESS_SIZE I2C Memory Address Size + * @{ + */ +#define I2C_MEMADD_SIZE_8BIT (0x00000001U) +#define I2C_MEMADD_SIZE_16BIT (0x00000002U) +/** + * @} + */ + +/** @defgroup I2C_XFERDIRECTION I2C Transfer Direction Master Point of View + * @{ + */ +#define I2C_DIRECTION_TRANSMIT (0x00000000U) +#define I2C_DIRECTION_RECEIVE (0x00000001U) +/** + * @} + */ + +/** @defgroup I2C_RELOAD_END_MODE I2C Reload End Mode + * @{ + */ +#define I2C_RELOAD_MODE I2C_CR2_RELOAD +#define I2C_AUTOEND_MODE I2C_CR2_AUTOEND +#define I2C_SOFTEND_MODE (0x00000000U) +/** + * @} + */ + +/** @defgroup I2C_START_STOP_MODE I2C Start or Stop Mode + * @{ + */ +#define I2C_NO_STARTSTOP (0x00000000U) +#define I2C_GENERATE_STOP (uint32_t)(0x80000000U | I2C_CR2_STOP) +#define I2C_GENERATE_START_READ (uint32_t)(0x80000000U | I2C_CR2_START | I2C_CR2_RD_WRN) +#define I2C_GENERATE_START_WRITE (uint32_t)(0x80000000U | I2C_CR2_START) +/** + * @} + */ + +/** @defgroup I2C_Interrupt_configuration_definition I2C Interrupt configuration definition + * @brief I2C Interrupt definition + * Elements values convention: 0xXXXXXXXX + * - XXXXXXXX : Interrupt control mask + * @{ + */ +#define I2C_IT_ERRI I2C_CR1_ERRIE +#define I2C_IT_TCI I2C_CR1_TCIE +#define I2C_IT_STOPI I2C_CR1_STOPIE +#define I2C_IT_NACKI I2C_CR1_NACKIE +#define I2C_IT_ADDRI I2C_CR1_ADDRIE +#define I2C_IT_RXI I2C_CR1_RXIE +#define I2C_IT_TXI I2C_CR1_TXIE +/** + * @} + */ + +/** @defgroup I2C_Flag_definition I2C Flag definition + * @{ + */ +#define I2C_FLAG_TXE I2C_ISR_TXE +#define I2C_FLAG_TXIS I2C_ISR_TXIS +#define I2C_FLAG_RXNE I2C_ISR_RXNE +#define I2C_FLAG_ADDR I2C_ISR_ADDR +#define I2C_FLAG_AF I2C_ISR_NACKF +#define I2C_FLAG_STOPF I2C_ISR_STOPF +#define I2C_FLAG_TC I2C_ISR_TC +#define I2C_FLAG_TCR I2C_ISR_TCR +#define I2C_FLAG_BERR I2C_ISR_BERR +#define I2C_FLAG_ARLO I2C_ISR_ARLO +#define I2C_FLAG_OVR I2C_ISR_OVR +#define I2C_FLAG_PECERR I2C_ISR_PECERR +#define I2C_FLAG_TIMEOUT I2C_ISR_TIMEOUT +#define I2C_FLAG_ALERT I2C_ISR_ALERT +#define I2C_FLAG_BUSY I2C_ISR_BUSY +#define I2C_FLAG_DIR I2C_ISR_DIR +/** + * @} + */ + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ + +/** @defgroup I2C_Exported_Macros I2C Exported Macros + * @{ + */ + +/** @brief Reset I2C handle state. + * @param __HANDLE__ specifies the I2C Handle. + * @retval None + */ +#define __HAL_I2C_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_I2C_STATE_RESET) + +/** @brief Enable the specified I2C interrupt. + * @param __HANDLE__ specifies the I2C Handle. + * @param __INTERRUPT__ specifies the interrupt source to enable. + * This parameter can be one of the following values: + * @arg @ref I2C_IT_ERRI Errors interrupt enable + * @arg @ref I2C_IT_TCI Transfer complete interrupt enable + * @arg @ref I2C_IT_STOPI STOP detection interrupt enable + * @arg @ref I2C_IT_NACKI NACK received interrupt enable + * @arg @ref I2C_IT_ADDRI Address match interrupt enable + * @arg @ref I2C_IT_RXI RX interrupt enable + * @arg @ref I2C_IT_TXI TX interrupt enable + * + * @retval None + */ +#define __HAL_I2C_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CR1 |= (__INTERRUPT__)) + +/** @brief Disable the specified I2C interrupt. + * @param __HANDLE__ specifies the I2C Handle. + * @param __INTERRUPT__ specifies the interrupt source to disable. + * This parameter can be one of the following values: + * @arg @ref I2C_IT_ERRI Errors interrupt enable + * @arg @ref I2C_IT_TCI Transfer complete interrupt enable + * @arg @ref I2C_IT_STOPI STOP detection interrupt enable + * @arg @ref I2C_IT_NACKI NACK received interrupt enable + * @arg @ref I2C_IT_ADDRI Address match interrupt enable + * @arg @ref I2C_IT_RXI RX interrupt enable + * @arg @ref I2C_IT_TXI TX interrupt enable + * + * @retval None + */ +#define __HAL_I2C_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CR1 &= (~(__INTERRUPT__))) + +/** @brief Check whether the specified I2C interrupt source is enabled or not. + * @param __HANDLE__ specifies the I2C Handle. + * @param __INTERRUPT__ specifies the I2C interrupt source to check. + * This parameter can be one of the following values: + * @arg @ref I2C_IT_ERRI Errors interrupt enable + * @arg @ref I2C_IT_TCI Transfer complete interrupt enable + * @arg @ref I2C_IT_STOPI STOP detection interrupt enable + * @arg @ref I2C_IT_NACKI NACK received interrupt enable + * @arg @ref I2C_IT_ADDRI Address match interrupt enable + * @arg @ref I2C_IT_RXI RX interrupt enable + * @arg @ref I2C_IT_TXI TX interrupt enable + * + * @retval The new state of __INTERRUPT__ (SET or RESET). + */ +#define __HAL_I2C_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) ((((__HANDLE__)->Instance->CR1 & (__INTERRUPT__)) == (__INTERRUPT__)) ? SET : RESET) + +/** @brief Check whether the specified I2C flag is set or not. + * @param __HANDLE__ specifies the I2C Handle. + * @param __FLAG__ specifies the flag to check. + * This parameter can be one of the following values: + * @arg @ref I2C_FLAG_TXE Transmit data register empty + * @arg @ref I2C_FLAG_TXIS Transmit interrupt status + * @arg @ref I2C_FLAG_RXNE Receive data register not empty + * @arg @ref I2C_FLAG_ADDR Address matched (slave mode) + * @arg @ref I2C_FLAG_AF Acknowledge failure received flag + * @arg @ref I2C_FLAG_STOPF STOP detection flag + * @arg @ref I2C_FLAG_TC Transfer complete (master mode) + * @arg @ref I2C_FLAG_TCR Transfer complete reload + * @arg @ref I2C_FLAG_BERR Bus error + * @arg @ref I2C_FLAG_ARLO Arbitration lost + * @arg @ref I2C_FLAG_OVR Overrun/Underrun + * @arg @ref I2C_FLAG_PECERR PEC error in reception + * @arg @ref I2C_FLAG_TIMEOUT Timeout or Tlow detection flag + * @arg @ref I2C_FLAG_ALERT SMBus alert + * @arg @ref I2C_FLAG_BUSY Bus busy + * @arg @ref I2C_FLAG_DIR Transfer direction (slave mode) + * + * @retval The new state of __FLAG__ (SET or RESET). + */ +#define __HAL_I2C_GET_FLAG(__HANDLE__, __FLAG__) (((((__HANDLE__)->Instance->ISR) & (__FLAG__)) == (__FLAG__)) ? SET : RESET) + +/** @brief Clear the I2C pending flags which are cleared by writing 1 in a specific bit. + * @param __HANDLE__ specifies the I2C Handle. + * @param __FLAG__ specifies the flag to clear. + * This parameter can be any combination of the following values: + * @arg @ref I2C_FLAG_TXE Transmit data register empty + * @arg @ref I2C_FLAG_ADDR Address matched (slave mode) + * @arg @ref I2C_FLAG_AF Acknowledge failure received flag + * @arg @ref I2C_FLAG_STOPF STOP detection flag + * @arg @ref I2C_FLAG_BERR Bus error + * @arg @ref I2C_FLAG_ARLO Arbitration lost + * @arg @ref I2C_FLAG_OVR Overrun/Underrun + * @arg @ref I2C_FLAG_PECERR PEC error in reception + * @arg @ref I2C_FLAG_TIMEOUT Timeout or Tlow detection flag + * @arg @ref I2C_FLAG_ALERT SMBus alert + * + * @retval None + */ +#define __HAL_I2C_CLEAR_FLAG(__HANDLE__, __FLAG__) (((__FLAG__) == I2C_FLAG_TXE) ? ((__HANDLE__)->Instance->ISR |= (__FLAG__)) \ + : ((__HANDLE__)->Instance->ICR = (__FLAG__))) + +/** @brief Enable the specified I2C peripheral. + * @param __HANDLE__ specifies the I2C Handle. + * @retval None + */ +#define __HAL_I2C_ENABLE(__HANDLE__) (SET_BIT((__HANDLE__)->Instance->CR1, I2C_CR1_PE)) + +/** @brief Disable the specified I2C peripheral. + * @param __HANDLE__ specifies the I2C Handle. + * @retval None + */ +#define __HAL_I2C_DISABLE(__HANDLE__) (CLEAR_BIT((__HANDLE__)->Instance->CR1, I2C_CR1_PE)) + +/** @brief Generate a Non-Acknowledge I2C peripheral in Slave mode. + * @param __HANDLE__ specifies the I2C Handle. + * @retval None + */ +#define __HAL_I2C_GENERATE_NACK(__HANDLE__) (SET_BIT((__HANDLE__)->Instance->CR2, I2C_CR2_NACK)) +/** + * @} + */ + +/* Include I2C HAL Extended module */ +#include "stm32l4xx_hal_i2c_ex.h" + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup I2C_Exported_Functions + * @{ + */ + +/** @addtogroup I2C_Exported_Functions_Group1 Initialization and de-initialization functions + * @{ + */ +/* Initialization and de-initialization functions******************************/ +HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c); +HAL_StatusTypeDef HAL_I2C_DeInit(I2C_HandleTypeDef *hi2c); +void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c); +void HAL_I2C_MspDeInit(I2C_HandleTypeDef *hi2c); +/** + * @} + */ + +/** @addtogroup I2C_Exported_Functions_Group2 Input and Output operation functions + * @{ + */ +/* IO operation functions ****************************************************/ +/******* Blocking mode: Polling */ +HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_I2C_Slave_Transmit(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_I2C_Slave_Receive(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_I2C_IsDeviceReady(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Trials, uint32_t Timeout); + +/******* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_I2C_Master_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Master_Receive_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Slave_Transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Slave_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Mem_Write_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Mem_Read_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size); + +HAL_StatusTypeDef HAL_I2C_Master_Sequential_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions); +HAL_StatusTypeDef HAL_I2C_Master_Sequential_Receive_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions); +HAL_StatusTypeDef HAL_I2C_Slave_Sequential_Transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions); +HAL_StatusTypeDef HAL_I2C_Slave_Sequential_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions); +HAL_StatusTypeDef HAL_I2C_EnableListen_IT(I2C_HandleTypeDef *hi2c); +HAL_StatusTypeDef HAL_I2C_DisableListen_IT(I2C_HandleTypeDef *hi2c); +HAL_StatusTypeDef HAL_I2C_Master_Abort_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress); + +/******* Non-Blocking mode: DMA */ +HAL_StatusTypeDef HAL_I2C_Master_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Master_Receive_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Slave_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Slave_Receive_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Mem_Write_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Mem_Read_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size); +/** + * @} + */ + +/** @addtogroup I2C_IRQ_Handler_and_Callbacks IRQ Handler and Callbacks + * @{ + */ +/******* I2C IRQHandler and Callbacks used in non blocking modes (Interrupt and DMA) */ +void HAL_I2C_EV_IRQHandler(I2C_HandleTypeDef *hi2c); +void HAL_I2C_ER_IRQHandler(I2C_HandleTypeDef *hi2c); +void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c); +void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c); +void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c); +void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c); +void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode); +void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c); +void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c); +void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c); +void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c); +void HAL_I2C_AbortCpltCallback(I2C_HandleTypeDef *hi2c); +/** + * @} + */ + +/** @addtogroup I2C_Exported_Functions_Group3 Peripheral State, Mode and Error functions + * @{ + */ +/* Peripheral State, Mode and Error functions *********************************/ +HAL_I2C_StateTypeDef HAL_I2C_GetState(I2C_HandleTypeDef *hi2c); +HAL_I2C_ModeTypeDef HAL_I2C_GetMode(I2C_HandleTypeDef *hi2c); +uint32_t HAL_I2C_GetError(I2C_HandleTypeDef *hi2c); + +/** + * @} + */ + +/** + * @} + */ + +/* Private constants ---------------------------------------------------------*/ +/** @defgroup I2C_Private_Constants I2C Private Constants + * @{ + */ + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup I2C_Private_Macro I2C Private Macros + * @{ + */ + +#define IS_I2C_ADDRESSING_MODE(MODE) (((MODE) == I2C_ADDRESSINGMODE_7BIT) || \ + ((MODE) == I2C_ADDRESSINGMODE_10BIT)) + +#define IS_I2C_DUAL_ADDRESS(ADDRESS) (((ADDRESS) == I2C_DUALADDRESS_DISABLE) || \ + ((ADDRESS) == I2C_DUALADDRESS_ENABLE)) + +#define IS_I2C_OWN_ADDRESS2_MASK(MASK) (((MASK) == I2C_OA2_NOMASK) || \ + ((MASK) == I2C_OA2_MASK01) || \ + ((MASK) == I2C_OA2_MASK02) || \ + ((MASK) == I2C_OA2_MASK03) || \ + ((MASK) == I2C_OA2_MASK04) || \ + ((MASK) == I2C_OA2_MASK05) || \ + ((MASK) == I2C_OA2_MASK06) || \ + ((MASK) == I2C_OA2_MASK07)) + +#define IS_I2C_GENERAL_CALL(CALL) (((CALL) == I2C_GENERALCALL_DISABLE) || \ + ((CALL) == I2C_GENERALCALL_ENABLE)) + +#define IS_I2C_NO_STRETCH(STRETCH) (((STRETCH) == I2C_NOSTRETCH_DISABLE) || \ + ((STRETCH) == I2C_NOSTRETCH_ENABLE)) + +#define IS_I2C_MEMADD_SIZE(SIZE) (((SIZE) == I2C_MEMADD_SIZE_8BIT) || \ + ((SIZE) == I2C_MEMADD_SIZE_16BIT)) + +#define IS_TRANSFER_MODE(MODE) (((MODE) == I2C_RELOAD_MODE) || \ + ((MODE) == I2C_AUTOEND_MODE) || \ + ((MODE) == I2C_SOFTEND_MODE)) + +#define IS_TRANSFER_REQUEST(REQUEST) (((REQUEST) == I2C_GENERATE_STOP) || \ + ((REQUEST) == I2C_GENERATE_START_READ) || \ + ((REQUEST) == I2C_GENERATE_START_WRITE) || \ + ((REQUEST) == I2C_NO_STARTSTOP)) + +#define IS_I2C_TRANSFER_OPTIONS_REQUEST(REQUEST) (((REQUEST) == I2C_FIRST_FRAME) || \ + ((REQUEST) == I2C_FIRST_AND_NEXT_FRAME) || \ + ((REQUEST) == I2C_NEXT_FRAME) || \ + ((REQUEST) == I2C_FIRST_AND_LAST_FRAME) || \ + ((REQUEST) == I2C_LAST_FRAME)) + +#define I2C_RESET_CR2(__HANDLE__) ((__HANDLE__)->Instance->CR2 &= (uint32_t)~((uint32_t)(I2C_CR2_SADD | I2C_CR2_HEAD10R | I2C_CR2_NBYTES | I2C_CR2_RELOAD | I2C_CR2_RD_WRN))) + +#define I2C_GET_ADDR_MATCH(__HANDLE__) (((__HANDLE__)->Instance->ISR & I2C_ISR_ADDCODE) >> 16U) +#define I2C_GET_DIR(__HANDLE__) (((__HANDLE__)->Instance->ISR & I2C_ISR_DIR) >> 16U) +#define I2C_GET_STOP_MODE(__HANDLE__) ((__HANDLE__)->Instance->CR2 & I2C_CR2_AUTOEND) +#define I2C_GET_OWN_ADDRESS1(__HANDLE__) ((__HANDLE__)->Instance->OAR1 & I2C_OAR1_OA1) +#define I2C_GET_OWN_ADDRESS2(__HANDLE__) ((__HANDLE__)->Instance->OAR2 & I2C_OAR2_OA2) + +#define IS_I2C_OWN_ADDRESS1(ADDRESS1) ((ADDRESS1) <= 0x000003FFU) +#define IS_I2C_OWN_ADDRESS2(ADDRESS2) ((ADDRESS2) <= (uint16_t)0x00FFU) + +#define I2C_MEM_ADD_MSB(__ADDRESS__) ((uint8_t)((uint16_t)(((uint16_t)((__ADDRESS__) & (uint16_t)(0xFF00U))) >> 8U))) +#define I2C_MEM_ADD_LSB(__ADDRESS__) ((uint8_t)((uint16_t)((__ADDRESS__) & (uint16_t)(0x00FFU)))) + +#define I2C_GENERATE_START(__ADDMODE__,__ADDRESS__) (((__ADDMODE__) == I2C_ADDRESSINGMODE_7BIT) ? (uint32_t)((((uint32_t)(__ADDRESS__) & (I2C_CR2_SADD)) | (I2C_CR2_START) | (I2C_CR2_AUTOEND)) & (~I2C_CR2_RD_WRN)) : \ + (uint32_t)((((uint32_t)(__ADDRESS__) & (I2C_CR2_SADD)) | (I2C_CR2_ADD10) | (I2C_CR2_START)) & (~I2C_CR2_RD_WRN))) +/** + * @} + */ + +/* Private Functions ---------------------------------------------------------*/ +/** @defgroup I2C_Private_Functions I2C Private Functions + * @{ + */ +/* Private functions are defined in stm32l4xx_hal_i2c.c file */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + + +#endif /* __STM32L4xx_HAL_I2C_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_i2c_ex.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_i2c_ex.h new file mode 100644 index 0000000..726a83f --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_i2c_ex.h @@ -0,0 +1,186 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_i2c_ex.h + * @author MCD Application Team + * @brief Header file of I2C HAL Extended module. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_I2C_EX_H +#define __STM32L4xx_HAL_I2C_EX_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup I2CEx + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/** @defgroup I2CEx_Exported_Constants I2C Extended Exported Constants + * @{ + */ + +/** @defgroup I2CEx_Analog_Filter I2C Extended Analog Filter + * @{ + */ +#define I2C_ANALOGFILTER_ENABLE 0x00000000U +#define I2C_ANALOGFILTER_DISABLE I2C_CR1_ANFOFF +/** + * @} + */ + +/** @defgroup I2CEx_FastModePlus I2C Extended Fast Mode Plus + * @{ + */ +#define I2C_FMP_NOT_SUPPORTED 0xAAAA0000U /*!< Fast Mode Plus not supported */ +#define I2C_FASTMODEPLUS_PB6 SYSCFG_CFGR1_I2C_PB6_FMP /*!< Enable Fast Mode Plus on PB6 */ +#define I2C_FASTMODEPLUS_PB7 SYSCFG_CFGR1_I2C_PB7_FMP /*!< Enable Fast Mode Plus on PB7 */ +#if defined(SYSCFG_CFGR1_I2C_PB8_FMP) +#define I2C_FASTMODEPLUS_PB8 SYSCFG_CFGR1_I2C_PB8_FMP /*!< Enable Fast Mode Plus on PB8 */ +#define I2C_FASTMODEPLUS_PB9 SYSCFG_CFGR1_I2C_PB9_FMP /*!< Enable Fast Mode Plus on PB9 */ +#else +#define I2C_FASTMODEPLUS_PB8 (uint32_t)(0x00000010U | I2C_FMP_NOT_SUPPORTED) /*!< Fast Mode Plus PB8 not supported */ +#define I2C_FASTMODEPLUS_PB9 (uint32_t)(0x00000012U | I2C_FMP_NOT_SUPPORTED) /*!< Fast Mode Plus PB9 not supported */ +#endif +#define I2C_FASTMODEPLUS_I2C1 SYSCFG_CFGR1_I2C1_FMP /*!< Enable Fast Mode Plus on I2C1 pins */ +#if defined(SYSCFG_CFGR1_I2C2_FMP) +#define I2C_FASTMODEPLUS_I2C2 SYSCFG_CFGR1_I2C2_FMP /*!< Enable Fast Mode Plus on I2C2 pins */ +#else +#define I2C_FASTMODEPLUS_I2C2 (uint32_t)(0x00000200U | I2C_FMP_NOT_SUPPORTED) /*!< Fast Mode Plus I2C2 not supported */ +#endif +#define I2C_FASTMODEPLUS_I2C3 SYSCFG_CFGR1_I2C3_FMP /*!< Enable Fast Mode Plus on I2C3 pins */ +#if defined(SYSCFG_CFGR1_I2C4_FMP) +#define I2C_FASTMODEPLUS_I2C4 SYSCFG_CFGR1_I2C4_FMP /*!< Enable Fast Mode Plus on I2C4 pins */ +#else +#define I2C_FASTMODEPLUS_I2C4 (uint32_t)(0x00000800U | I2C_FMP_NOT_SUPPORTED) /*!< Fast Mode Plus I2C4 not supported */ +#endif +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/** @addtogroup I2CEx_Exported_Functions I2C Extended Exported Functions + * @{ + */ + +/** @addtogroup I2CEx_Exported_Functions_Group1 Extended features functions + * @brief Extended features functions + * @{ + */ + +/* Peripheral Control functions ************************************************/ +HAL_StatusTypeDef HAL_I2CEx_ConfigAnalogFilter(I2C_HandleTypeDef *hi2c, uint32_t AnalogFilter); +HAL_StatusTypeDef HAL_I2CEx_ConfigDigitalFilter(I2C_HandleTypeDef *hi2c, uint32_t DigitalFilter); +HAL_StatusTypeDef HAL_I2CEx_EnableWakeUp(I2C_HandleTypeDef *hi2c); +HAL_StatusTypeDef HAL_I2CEx_DisableWakeUp(I2C_HandleTypeDef *hi2c); +void HAL_I2CEx_EnableFastModePlus(uint32_t ConfigFastModePlus); +void HAL_I2CEx_DisableFastModePlus(uint32_t ConfigFastModePlus); + +/* Private constants ---------------------------------------------------------*/ +/** @defgroup I2CEx_Private_Constants I2C Extended Private Constants + * @{ + */ + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup I2CEx_Private_Macro I2C Extended Private Macros + * @{ + */ +#define IS_I2C_ANALOG_FILTER(FILTER) (((FILTER) == I2C_ANALOGFILTER_ENABLE) || \ + ((FILTER) == I2C_ANALOGFILTER_DISABLE)) + +#define IS_I2C_DIGITAL_FILTER(FILTER) ((FILTER) <= 0x0000000FU) + +#define IS_I2C_FASTMODEPLUS(__CONFIG__) ((((__CONFIG__) & I2C_FMP_NOT_SUPPORTED) != I2C_FMP_NOT_SUPPORTED) && \ + ((((__CONFIG__) & (I2C_FASTMODEPLUS_PB6)) == I2C_FASTMODEPLUS_PB6) || \ + (((__CONFIG__) & (I2C_FASTMODEPLUS_PB7)) == I2C_FASTMODEPLUS_PB7) || \ + (((__CONFIG__) & (I2C_FASTMODEPLUS_PB8)) == I2C_FASTMODEPLUS_PB8) || \ + (((__CONFIG__) & (I2C_FASTMODEPLUS_PB9)) == I2C_FASTMODEPLUS_PB9) || \ + (((__CONFIG__) & (I2C_FASTMODEPLUS_I2C1)) == I2C_FASTMODEPLUS_I2C1) || \ + (((__CONFIG__) & (I2C_FASTMODEPLUS_I2C2)) == I2C_FASTMODEPLUS_I2C2) || \ + (((__CONFIG__) & (I2C_FASTMODEPLUS_I2C3)) == I2C_FASTMODEPLUS_I2C3) || \ + (((__CONFIG__) & (I2C_FASTMODEPLUS_I2C4)) == I2C_FASTMODEPLUS_I2C4))) +/** + * @} + */ + +/* Private Functions ---------------------------------------------------------*/ +/** @defgroup I2CEx_Private_Functions I2C Extended Private Functions + * @{ + */ +/* Private functions are defined in stm32l4xx_hal_i2c_ex.c file */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_HAL_I2C_EX_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pcd.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pcd.h new file mode 100644 index 0000000..0fa4476 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pcd.h @@ -0,0 +1,874 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_pcd.h + * @author MCD Application Team + * @brief Header file of PCD HAL module. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_PCD_H +#define __STM32L4xx_HAL_PCD_H + +#ifdef __cplusplus + extern "C" { +#endif + +#if defined(STM32L432xx) || defined(STM32L433xx) || defined(STM32L442xx) || defined(STM32L443xx) || \ + defined(STM32L452xx) || defined(STM32L462xx) || \ + defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || \ + defined(STM32L496xx) || defined(STM32L4A6xx) || \ + defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_ll_usb.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup PCD + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup PCD_Exported_Types PCD Exported Types + * @{ + */ + + /** + * @brief PCD State structure definition + */ +typedef enum +{ + HAL_PCD_STATE_RESET = 0x00, + HAL_PCD_STATE_READY = 0x01, + HAL_PCD_STATE_ERROR = 0x02, + HAL_PCD_STATE_BUSY = 0x03, + HAL_PCD_STATE_TIMEOUT = 0x04 +} PCD_StateTypeDef; + +/* Device LPM suspend state */ +typedef enum +{ + LPM_L0 = 0x00, /* on */ + LPM_L1 = 0x01, /* LPM L1 sleep */ + LPM_L2 = 0x02, /* suspend */ + LPM_L3 = 0x03, /* off */ +}PCD_LPM_StateTypeDef; + +#if defined (USB) +/** + * @brief PCD double buffered endpoint direction + */ +typedef enum +{ + PCD_EP_DBUF_OUT, + PCD_EP_DBUF_IN, + PCD_EP_DBUF_ERR, +}PCD_EP_DBUF_DIR; + +/** + * @brief PCD endpoint buffer number + */ +typedef enum +{ + PCD_EP_NOBUF, + PCD_EP_BUF0, + PCD_EP_BUF1 +}PCD_EP_BUF_NUM; +#endif /* USB */ + +#if defined (USB_OTG_FS) +typedef USB_OTG_GlobalTypeDef PCD_TypeDef; +typedef USB_OTG_CfgTypeDef PCD_InitTypeDef; +typedef USB_OTG_EPTypeDef PCD_EPTypeDef; +#endif /* USB_OTG_FS */ + +#if defined (USB) +typedef USB_TypeDef PCD_TypeDef; +typedef USB_CfgTypeDef PCD_InitTypeDef; +typedef USB_EPTypeDef PCD_EPTypeDef; +#endif /* USB */ + +/** + * @brief PCD Handle Structure definition + */ +typedef struct +{ + PCD_TypeDef *Instance; /*!< Register base address */ + PCD_InitTypeDef Init; /*!< PCD required parameters */ + __IO uint8_t USB_Address; /*!< USB Address: not used by USB OTG FS */ + PCD_EPTypeDef IN_ep[15]; /*!< IN endpoint parameters */ + PCD_EPTypeDef OUT_ep[15]; /*!< OUT endpoint parameters */ + HAL_LockTypeDef Lock; /*!< PCD peripheral status */ + __IO PCD_StateTypeDef State; /*!< PCD communication state */ + uint32_t Setup[12]; /*!< Setup packet buffer */ + PCD_LPM_StateTypeDef LPM_State; /*!< LPM State */ + uint32_t BESL; + + + uint32_t lpm_active; /*!< Enable or disable the Link Power Management . + This parameter can be set to ENABLE or DISABLE */ + + uint32_t battery_charging_active; /*!< Enable or disable Battery charging. + This parameter can be set to ENABLE or DISABLE */ + void *pData; /*!< Pointer to upper stack Handler */ + +} PCD_HandleTypeDef; + +/** + * @} + */ + +/* Include PCD HAL Extended module */ +#include "stm32l4xx_hal_pcd_ex.h" + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup PCD_Exported_Constants PCD Exported Constants + * @{ + */ + +/** @defgroup PCD_Speed PCD Speed + * @{ + */ +#define PCD_SPEED_FULL 1 +/** + * @} + */ + +/** @defgroup PCD_PHY_Module PCD PHY Module + * @{ + */ +#define PCD_PHY_EMBEDDED 1 +/** + * @} + */ + +/** @defgroup PCD_Turnaround_Timeout Turnaround Timeout Value + * @{ + */ +#ifndef USBD_FS_TRDT_VALUE + #define USBD_FS_TRDT_VALUE 5 +#endif /* USBD_FS_TRDT_VALUE */ +/** + * @} + */ + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ +/** @defgroup PCD_Exported_Macros PCD Exported Macros + * @brief macros to handle interrupts and specific clock configurations + * @{ + */ +#if defined (USB_OTG_FS) +#define __HAL_PCD_ENABLE(__HANDLE__) USB_EnableGlobalInt ((__HANDLE__)->Instance) +#define __HAL_PCD_DISABLE(__HANDLE__) USB_DisableGlobalInt ((__HANDLE__)->Instance) + +#define __HAL_PCD_GET_FLAG(__HANDLE__, __INTERRUPT__) ((USB_ReadInterrupts((__HANDLE__)->Instance) & (__INTERRUPT__)) == (__INTERRUPT__)) +#define __HAL_PCD_CLEAR_FLAG(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->GINTSTS) &= (__INTERRUPT__)) +#define __HAL_PCD_IS_INVALID_INTERRUPT(__HANDLE__) (USB_ReadInterrupts((__HANDLE__)->Instance) == 0) + + +#define __HAL_PCD_UNGATE_PHYCLOCK(__HANDLE__) *(__IO uint32_t *)((uint32_t)((__HANDLE__)->Instance) + USB_OTG_PCGCCTL_BASE) &= \ + ~(USB_OTG_PCGCCTL_STOPCLK) + +#define __HAL_PCD_GATE_PHYCLOCK(__HANDLE__) *(__IO uint32_t *)((uint32_t)((__HANDLE__)->Instance) + USB_OTG_PCGCCTL_BASE) |= USB_OTG_PCGCCTL_STOPCLK + +#define __HAL_PCD_IS_PHY_SUSPENDED(__HANDLE__) ((*(__IO uint32_t *)((uint32_t)((__HANDLE__)->Instance) + USB_OTG_PCGCCTL_BASE))&0x10) + +#define __HAL_USB_OTG_FS_WAKEUP_EXTI_ENABLE_IT() EXTI->IMR1 |= USB_OTG_FS_WAKEUP_EXTI_LINE +#define __HAL_USB_OTG_FS_WAKEUP_EXTI_DISABLE_IT() EXTI->IMR1 &= ~(USB_OTG_FS_WAKEUP_EXTI_LINE) +#define __HAL_USB_OTG_FS_WAKEUP_EXTI_GET_FLAG() EXTI->PR1 & (USB_OTG_FS_WAKEUP_EXTI_LINE) +#define __HAL_USB_OTG_FS_WAKEUP_EXTI_CLEAR_FLAG() EXTI->PR1 = USB_OTG_FS_WAKEUP_EXTI_LINE + +#define __HAL_USB_OTG_FS_WAKEUP_EXTI_ENABLE_RISING_EDGE() do {\ + EXTI->FTSR1 &= ~(USB_OTG_FS_WAKEUP_EXTI_LINE);\ + EXTI->RTSR1 |= USB_OTG_FS_WAKEUP_EXTI_LINE;\ + } while(0) + +#define __HAL_USB_OTG_FS_WAKEUP_EXTI_ENABLE_FALLING_EDGE() do {\ + EXTI->FTSR1 |= (USB_OTG_FS_WAKEUP_EXTI_LINE);\ + EXTI->RTSR1 &= ~(USB_OTG_FS_WAKEUP_EXTI_LINE);\ + } while(0) + +#define __HAL_USB_OTG_FS_WAKEUP_EXTI_ENABLE_RISING_FALLING_EDGE() do {\ + EXTI->RTSR1 &= ~(USB_OTG_FS_WAKEUP_EXTI_LINE);\ + EXTI->FTSR1 &= ~(USB_OTG_FS_WAKEUP_EXTI_LINE);\ + EXTI->RTSR1 |= USB_OTG_FS_WAKEUP_EXTI_LINE;\ + EXTI->FTSR1 |= USB_OTG_FS_WAKEUP_EXTI_LINE;\ + } while(0) + +#define __HAL_USB_OTG_FS_WAKEUP_EXTI_GENERATE_SWIT() (EXTI->SWIER1 |= USB_OTG_FS_WAKEUP_EXTI_LINE) + +#endif /* USB_OTG_FS */ + +#if defined (USB) +#define __HAL_PCD_ENABLE(__HANDLE__) USB_EnableGlobalInt ((__HANDLE__)->Instance) +#define __HAL_PCD_DISABLE(__HANDLE__) USB_DisableGlobalInt ((__HANDLE__)->Instance) +#define __HAL_PCD_GET_FLAG(__HANDLE__, __INTERRUPT__) ((USB_ReadInterrupts((__HANDLE__)->Instance) & (__INTERRUPT__)) == (__INTERRUPT__)) +#define __HAL_PCD_CLEAR_FLAG(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->ISTR) &= ~(__INTERRUPT__)) + +#define __HAL_USB_WAKEUP_EXTI_ENABLE_IT() EXTI->IMR1 |= USB_WAKEUP_EXTI_LINE +#define __HAL_USB_WAKEUP_EXTI_DISABLE_IT() EXTI->IMR1 &= ~(USB_WAKEUP_EXTI_LINE) +#define __HAL_USB_WAKEUP_EXTI_GET_FLAG() EXTI->PR1 & (USB_WAKEUP_EXTI_LINE) +#define __HAL_USB_WAKEUP_EXTI_CLEAR_FLAG() EXTI->PR1 = USB_WAKEUP_EXTI_LINE + +#define __HAL_USB_WAKEUP_EXTI_ENABLE_RISING_EDGE() do {\ + EXTI->FTSR1 &= ~(USB_WAKEUP_EXTI_LINE);\ + EXTI->RTSR1 |= USB_WAKEUP_EXTI_LINE;\ + } while(0) + +#define __HAL_USB_WAKEUP_EXTI_ENABLE_FALLING_EDGE() do {\ + EXTI->FTSR1 |= (USB_WAKEUP_EXTI_LINE);\ + EXTI->RTSR1 &= ~(USB_WAKEUP_EXTI_LINE);\ + } while(0) + +#define __HAL_USB_WAKEUP_EXTI_ENABLE_RISING_FALLING_EDGE() do {\ + EXTI->RTSR1 &= ~(USB_WAKEUP_EXTI_LINE);\ + EXTI->FTSR1 &= ~(USB_WAKEUP_EXTI_LINE);\ + EXTI->RTSR1 |= USB_WAKEUP_EXTI_LINE;\ + EXTI->FTSR1 |= USB_WAKEUP_EXTI_LINE;\ + } while(0) + +#define __HAL_USB_WAKEUP_EXTI_GENERATE_SWIT() (EXTI->SWIER1 |= USB_WAKEUP_EXTI_LINE) + +#endif /* USB */ + +/** + * @} + */ + +/** @addtogroup PCD_Exported_Functions PCD Exported Functions + * @{ + */ + +/* Initialization/de-initialization functions ********************************/ +/** @addtogroup PCD_Exported_Functions_Group1 Initialization and de-initialization functions + * @{ + */ +HAL_StatusTypeDef HAL_PCD_Init(PCD_HandleTypeDef *hpcd); +HAL_StatusTypeDef HAL_PCD_DeInit (PCD_HandleTypeDef *hpcd); +void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd); +void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd); +/** + * @} + */ + +/* I/O operation functions ***************************************************/ +/* Non-Blocking mode: Interrupt */ +/** @addtogroup PCD_Exported_Functions_Group2 Input and Output operation functions + * @{ + */ + /* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_PCD_Start(PCD_HandleTypeDef *hpcd); +HAL_StatusTypeDef HAL_PCD_Stop(PCD_HandleTypeDef *hpcd); +void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd); + +void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum); +void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum); +void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd); +void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd); +void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd); +void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd); +void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd); +void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum); +void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum); +void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd); +void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd); +/** + * @} + */ + +/* Peripheral Control functions **********************************************/ +/** @addtogroup PCD_Exported_Functions_Group3 Peripheral Control functions + * @{ + */ +HAL_StatusTypeDef HAL_PCD_DevConnect(PCD_HandleTypeDef *hpcd); +HAL_StatusTypeDef HAL_PCD_DevDisconnect(PCD_HandleTypeDef *hpcd); +HAL_StatusTypeDef HAL_PCD_SetAddress(PCD_HandleTypeDef *hpcd, uint8_t address); +HAL_StatusTypeDef HAL_PCD_EP_Open(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint16_t ep_mps, uint8_t ep_type); +HAL_StatusTypeDef HAL_PCD_EP_Close(PCD_HandleTypeDef *hpcd, uint8_t ep_addr); +HAL_StatusTypeDef HAL_PCD_EP_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len); +HAL_StatusTypeDef HAL_PCD_EP_Transmit(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len); +uint16_t HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef *hpcd, uint8_t ep_addr); +HAL_StatusTypeDef HAL_PCD_EP_SetStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr); +HAL_StatusTypeDef HAL_PCD_EP_ClrStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr); +HAL_StatusTypeDef HAL_PCD_EP_Flush(PCD_HandleTypeDef *hpcd, uint8_t ep_addr); +HAL_StatusTypeDef HAL_PCD_ActivateRemoteWakeup(PCD_HandleTypeDef *hpcd); +HAL_StatusTypeDef HAL_PCD_DeActivateRemoteWakeup(PCD_HandleTypeDef *hpcd); +/** + * @} + */ + +/* Peripheral State functions ************************************************/ +/** @addtogroup PCD_Exported_Functions_Group4 Peripheral State functions + * @{ + */ +PCD_StateTypeDef HAL_PCD_GetState(PCD_HandleTypeDef *hpcd); +/** + * @} + */ + +/** + * @} + */ + +/* Private constants ---------------------------------------------------------*/ +/** @defgroup PCD_Private_Constants PCD Private Constants + * @{ + */ +/** @defgroup USB_EXTI_Line_Interrupt USB EXTI line interrupt + * @{ + */ +#if defined (USB_OTG_FS) +#define USB_OTG_FS_WAKEUP_EXTI_RISING_EDGE ((uint32_t)0x08) +#define USB_OTG_FS_WAKEUP_EXTI_FALLING_EDGE ((uint32_t)0x0C) +#define USB_OTG_FS_WAKEUP_EXTI_RISING_FALLING_EDGE ((uint32_t)0x10) + +#define USB_OTG_FS_WAKEUP_EXTI_LINE ((uint32_t)0x00020000) /*!< External interrupt line 17 Connected to the USB EXTI Line */ +#endif /* USB_OTG_FS */ + +#if defined (USB) +#define USB_WAKEUP_EXTI_LINE ((uint32_t)0x00020000) /*!< External interrupt line 17Connected to the USB EXTI Line */ +#endif /* USB */ + +/** + * @} + */ + +#if defined (USB) +/** @defgroup PCD_EP0_MPS PCD EP0 MPS + * @{ + */ +#define PCD_EP0MPS_64 DEP0CTL_MPS_64 +#define PCD_EP0MPS_32 DEP0CTL_MPS_32 +#define PCD_EP0MPS_16 DEP0CTL_MPS_16 +#define PCD_EP0MPS_08 DEP0CTL_MPS_8 +/** + * @} + */ + +/** @defgroup PCD_ENDP PCD ENDP + * @{ + */ +#define PCD_ENDP0 ((uint8_t)0) +#define PCD_ENDP1 ((uint8_t)1) +#define PCD_ENDP2 ((uint8_t)2) +#define PCD_ENDP3 ((uint8_t)3) +#define PCD_ENDP4 ((uint8_t)4) +#define PCD_ENDP5 ((uint8_t)5) +#define PCD_ENDP6 ((uint8_t)6) +#define PCD_ENDP7 ((uint8_t)7) +/** + * @} + */ + +/** @defgroup PCD_ENDP_Kind PCD Endpoint Kind + * @{ + */ +#define PCD_SNG_BUF 0 +#define PCD_DBL_BUF 1 +/** + * @} + */ +#endif /* USB */ +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @addtogroup PCD_Private_Macros PCD Private Macros + * @{ + */ +#if defined (USB) +/* SetENDPOINT */ +#define PCD_SET_ENDPOINT(USBx, bEpNum,wRegValue) (*(&(USBx)->EP0R + (bEpNum) * 2)= (uint16_t)(wRegValue)) + +/* GetENDPOINT */ +#define PCD_GET_ENDPOINT(USBx, bEpNum) (*(&(USBx)->EP0R + (bEpNum) * 2)) + +/* ENDPOINT transfer */ +#define USB_EP0StartXfer USB_EPStartXfer + +/** + * @brief sets the type in the endpoint register(bits EP_TYPE[1:0]) + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @param wType: Endpoint Type. + * @retval None + */ +#define PCD_SET_EPTYPE(USBx, bEpNum,wType) (PCD_SET_ENDPOINT((USBx), (bEpNum),\ + ((PCD_GET_ENDPOINT((USBx), (bEpNum)) & USB_EP_T_MASK) | (wType) ))) + +/** + * @brief gets the type in the endpoint register(bits EP_TYPE[1:0]) + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @retval Endpoint Type + */ +#define PCD_GET_EPTYPE(USBx, bEpNum) (PCD_GET_ENDPOINT((USBx), (bEpNum)) & USB_EP_T_FIELD) + +/** + * @brief free buffer used from the application realizing it to the line + toggles bit SW_BUF in the double buffered endpoint register + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @param bDir: Direction + * @retval None + */ +#define PCD_FreeUserBuffer(USBx, bEpNum, bDir)\ +{\ + if ((bDir) == PCD_EP_DBUF_OUT)\ + { /* OUT double buffered endpoint */\ + PCD_TX_DTOG((USBx), (bEpNum));\ + }\ + else if ((bDir) == PCD_EP_DBUF_IN)\ + { /* IN double buffered endpoint */\ + PCD_RX_DTOG((USBx), (bEpNum));\ + }\ +} + +/** + * @brief gets direction of the double buffered endpoint + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @retval EP_DBUF_OUT, EP_DBUF_IN, + * EP_DBUF_ERR if the endpoint counter not yet programmed. + */ +#define PCD_GET_DB_DIR(USBx, bEpNum)\ +{\ + if ((uint16_t)(*PCD_EP_RX_CNT((USBx), (bEpNum)) & 0xFC00) != 0)\ + return(PCD_EP_DBUF_OUT);\ + else if (((uint16_t)(*PCD_EP_TX_CNT((USBx), (bEpNum))) & 0x03FF) != 0)\ + return(PCD_EP_DBUF_IN);\ + else\ + return(PCD_EP_DBUF_ERR);\ +} + +/** + * @brief sets the status for tx transfer (bits STAT_TX[1:0]). + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @param wState: new state + * @retval None + */ +#define PCD_SET_EP_TX_STATUS(USBx, bEpNum, wState) { register uint16_t _wRegVal;\ + \ + _wRegVal = PCD_GET_ENDPOINT((USBx), (bEpNum)) & USB_EPTX_DTOGMASK;\ + /* toggle first bit ? */ \ + if((USB_EPTX_DTOG1 & (wState))!= 0)\ + { \ + _wRegVal ^= USB_EPTX_DTOG1; \ + } \ + /* toggle second bit ? */ \ + if((USB_EPTX_DTOG2 & (wState))!= 0) \ + { \ + _wRegVal ^= USB_EPTX_DTOG2; \ + } \ + PCD_SET_ENDPOINT((USBx), (bEpNum), (_wRegVal | USB_EP_CTR_RX|USB_EP_CTR_TX));\ + } /* PCD_SET_EP_TX_STATUS */ + +/** + * @brief sets the status for rx transfer (bits STAT_TX[1:0]) + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @param wState: new state + * @retval None + */ +#define PCD_SET_EP_RX_STATUS(USBx, bEpNum,wState) {\ + register uint16_t _wRegVal; \ + \ + _wRegVal = PCD_GET_ENDPOINT((USBx), (bEpNum)) & USB_EPRX_DTOGMASK;\ + /* toggle first bit ? */ \ + if((USB_EPRX_DTOG1 & (wState))!= 0) \ + { \ + _wRegVal ^= USB_EPRX_DTOG1; \ + } \ + /* toggle second bit ? */ \ + if((USB_EPRX_DTOG2 & (wState))!= 0) \ + { \ + _wRegVal ^= USB_EPRX_DTOG2; \ + } \ + PCD_SET_ENDPOINT((USBx), (bEpNum), (_wRegVal | USB_EP_CTR_RX|USB_EP_CTR_TX)); \ + } /* PCD_SET_EP_RX_STATUS */ + +/** + * @brief sets the status for rx & tx (bits STAT_TX[1:0] & STAT_RX[1:0]) + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @param wStaterx: new state. + * @param wStatetx: new state. + * @retval None + */ +#define PCD_SET_EP_TXRX_STATUS(USBx,bEpNum,wStaterx,wStatetx) {\ + register uint32_t _wRegVal; \ + \ + _wRegVal = PCD_GET_ENDPOINT((USBx), (bEpNum)) & (USB_EPRX_DTOGMASK |USB_EPTX_STAT) ;\ + /* toggle first bit ? */ \ + if((USB_EPRX_DTOG1 & ((wStaterx)))!= 0) \ + { \ + _wRegVal ^= USB_EPRX_DTOG1; \ + } \ + /* toggle second bit ? */ \ + if((USB_EPRX_DTOG2 & (wStaterx))!= 0) \ + { \ + _wRegVal ^= USB_EPRX_DTOG2; \ + } \ + /* toggle first bit ? */ \ + if((USB_EPTX_DTOG1 & (wStatetx))!= 0) \ + { \ + _wRegVal ^= USB_EPTX_DTOG1; \ + } \ + /* toggle second bit ? */ \ + if((USB_EPTX_DTOG2 & (wStatetx))!= 0) \ + { \ + _wRegVal ^= USB_EPTX_DTOG2; \ + } \ + PCD_SET_ENDPOINT((USBx), (bEpNum), _wRegVal | USB_EP_CTR_RX|USB_EP_CTR_TX); \ + } /* PCD_SET_EP_TXRX_STATUS */ + +/** + * @brief gets the status for tx/rx transfer (bits STAT_TX[1:0] + * /STAT_RX[1:0]) + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @retval status + */ +#define PCD_GET_EP_TX_STATUS(USBx, bEpNum) ((uint16_t)PCD_GET_ENDPOINT((USBx), (bEpNum)) & USB_EPTX_STAT) +#define PCD_GET_EP_RX_STATUS(USBx, bEpNum) ((uint16_t)PCD_GET_ENDPOINT((USBx), (bEpNum)) & USB_EPRX_STAT) + +/** + * @brief sets directly the VALID tx/rx-status into the endpoint register + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @retval None + */ +#define PCD_SET_EP_TX_VALID(USBx, bEpNum) (PCD_SET_EP_TX_STATUS((USBx), (bEpNum), USB_EP_TX_VALID)) +#define PCD_SET_EP_RX_VALID(USBx, bEpNum) (PCD_SET_EP_RX_STATUS((USBx), (bEpNum), USB_EP_RX_VALID)) + +/** + * @brief checks stall condition in an endpoint. + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @retval TRUE = endpoint in stall condition. + */ +#define PCD_GET_EP_TX_STALL_STATUS(USBx, bEpNum) (PCD_GET_EP_TX_STATUS((USBx), (bEpNum)) \ + == USB_EP_TX_STALL) +#define PCD_GET_EP_RX_STALL_STATUS(USBx, bEpNum) (PCD_GET_EP_RX_STATUS((USBx), (bEpNum)) \ + == USB_EP_RX_STALL) + +/** + * @brief set & clear EP_KIND bit. + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @retval None + */ +#define PCD_SET_EP_KIND(USBx, bEpNum) (PCD_SET_ENDPOINT((USBx), (bEpNum), \ + (USB_EP_CTR_RX|USB_EP_CTR_TX|((PCD_GET_ENDPOINT((USBx), (bEpNum)) | USB_EP_KIND) & USB_EPREG_MASK)))) +#define PCD_CLEAR_EP_KIND(USBx, bEpNum) (PCD_SET_ENDPOINT((USBx), (bEpNum), \ + (USB_EP_CTR_RX|USB_EP_CTR_TX|(PCD_GET_ENDPOINT((USBx), (bEpNum)) & USB_EPKIND_MASK)))) + +/** + * @brief Sets/clears directly STATUS_OUT bit in the endpoint register. + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @retval None + */ +#define PCD_SET_OUT_STATUS(USBx, bEpNum) PCD_SET_EP_KIND((USBx), (bEpNum)) +#define PCD_CLEAR_OUT_STATUS(USBx, bEpNum) PCD_CLEAR_EP_KIND((USBx), (bEpNum)) + +/** + * @brief Sets/clears directly EP_KIND bit in the endpoint register. + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @retval None + */ +#define PCD_SET_EP_DBUF(USBx, bEpNum) PCD_SET_EP_KIND((USBx), (bEpNum)) +#define PCD_CLEAR_EP_DBUF(USBx, bEpNum) PCD_CLEAR_EP_KIND((USBx), (bEpNum)) + +/** + * @brief Clears bit CTR_RX / CTR_TX in the endpoint register. + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @retval None + */ +#define PCD_CLEAR_RX_EP_CTR(USBx, bEpNum) (PCD_SET_ENDPOINT((USBx), (bEpNum),\ + PCD_GET_ENDPOINT((USBx), (bEpNum)) & 0x7FFF & USB_EPREG_MASK)) +#define PCD_CLEAR_TX_EP_CTR(USBx, bEpNum) (PCD_SET_ENDPOINT((USBx), (bEpNum),\ + PCD_GET_ENDPOINT((USBx), (bEpNum)) & 0xFF7F & USB_EPREG_MASK)) + +/** + * @brief Toggles DTOG_RX / DTOG_TX bit in the endpoint register. + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @retval None + */ +#define PCD_RX_DTOG(USBx, bEpNum) (PCD_SET_ENDPOINT((USBx), (bEpNum), \ + USB_EP_CTR_RX|USB_EP_CTR_TX|USB_EP_DTOG_RX | (PCD_GET_ENDPOINT((USBx), (bEpNum)) & USB_EPREG_MASK))) +#define PCD_TX_DTOG(USBx, bEpNum) (PCD_SET_ENDPOINT((USBx), (bEpNum), \ + USB_EP_CTR_RX|USB_EP_CTR_TX|USB_EP_DTOG_TX | (PCD_GET_ENDPOINT((USBx), (bEpNum)) & USB_EPREG_MASK))) + +/** + * @brief Clears DTOG_RX / DTOG_TX bit in the endpoint register. + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @retval None + */ +#define PCD_CLEAR_RX_DTOG(USBx, bEpNum) if((PCD_GET_ENDPOINT((USBx), (bEpNum)) & USB_EP_DTOG_RX) != 0)\ + { \ + PCD_RX_DTOG((USBx), (bEpNum)); \ + } +#define PCD_CLEAR_TX_DTOG(USBx, bEpNum) if((PCD_GET_ENDPOINT((USBx), (bEpNum)) & USB_EP_DTOG_TX) != 0)\ + { \ + PCD_TX_DTOG((USBx), (bEpNum)); \ + } + +/** + * @brief Sets address in an endpoint register. + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @param bAddr: Address. + * @retval None + */ +#define PCD_SET_EP_ADDRESS(USBx, bEpNum,bAddr) PCD_SET_ENDPOINT((USBx), (bEpNum),\ + USB_EP_CTR_RX|USB_EP_CTR_TX|(PCD_GET_ENDPOINT((USBx), (bEpNum)) & USB_EPREG_MASK) | (bAddr)) + +#define PCD_GET_EP_ADDRESS(USBx, bEpNum) ((uint8_t)(PCD_GET_ENDPOINT((USBx), (bEpNum)) & USB_EPADDR_FIELD)) + +#define PCD_EP_TX_ADDRESS(USBx, bEpNum) ((uint16_t *)(((USBx)->BTABLE+(bEpNum)*8)+ ((uint32_t)(USBx) + 0x400))) +#define PCD_EP_TX_CNT(USBx, bEpNum) ((uint16_t *)(((USBx)->BTABLE+(bEpNum)*8+2)+ ((uint32_t)(USBx) + 0x400))) +#define PCD_EP_RX_ADDRESS(USBx, bEpNum) ((uint16_t *)(((USBx)->BTABLE+(bEpNum)*8+4)+ ((uint32_t)(USBx) + 0x400))) +#define PCD_EP_RX_CNT(USBx, bEpNum) ((uint16_t *)(((USBx)->BTABLE+(bEpNum)*8+6)+ ((uint32_t)(USBx) + 0x400))) + +#define PCD_SET_EP_RX_CNT(USBx, bEpNum,wCount) {\ + uint16_t *pdwReg = PCD_EP_RX_CNT((USBx), (bEpNum)); \ + PCD_SET_EP_CNT_RX_REG(pdwReg, (wCount));\ + } + +/** + * @brief sets address of the tx/rx buffer. + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @param wAddr: address to be set (must be word aligned). + * @retval None + */ +#define PCD_SET_EP_TX_ADDRESS(USBx, bEpNum,wAddr) (*PCD_EP_TX_ADDRESS((USBx), (bEpNum)) = (((wAddr) >> 1) << 1)) +#define PCD_SET_EP_RX_ADDRESS(USBx, bEpNum,wAddr) (*PCD_EP_RX_ADDRESS((USBx), (bEpNum)) = (((wAddr) >> 1) << 1)) + +/** + * @brief Gets address of the tx/rx buffer. + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @retval address of the buffer. + */ +#define PCD_GET_EP_TX_ADDRESS(USBx, bEpNum) ((uint16_t)*PCD_EP_TX_ADDRESS((USBx), (bEpNum))) +#define PCD_GET_EP_RX_ADDRESS(USBx, bEpNum) ((uint16_t)*PCD_EP_RX_ADDRESS((USBx), (bEpNum))) + +/** + * @brief Sets counter of rx buffer with no. of blocks. + * @param dwReg: Register + * @param wCount: Counter. + * @param wNBlocks: no. of Blocks. + * @retval None + */ +#define PCD_CALC_BLK32(dwReg,wCount,wNBlocks) {\ + (wNBlocks) = (wCount) >> 5;\ + if(((wCount) & 0x1f) == 0)\ + { \ + (wNBlocks)--;\ + } \ + *pdwReg = (uint16_t)((uint16_t)((wNBlocks) << 10) | 0x8000); \ + }/* PCD_CALC_BLK32 */ + +#define PCD_CALC_BLK2(dwReg,wCount,wNBlocks) {\ + (wNBlocks) = (wCount) >> 1;\ + if(((wCount) & 0x1) != 0)\ + { \ + (wNBlocks)++;\ + } \ + *pdwReg = (uint16_t)((wNBlocks) << 10);\ + }/* PCD_CALC_BLK2 */ + +#define PCD_SET_EP_CNT_RX_REG(dwReg,wCount) {\ + uint16_t wNBlocks;\ + if((wCount) > 62) \ + { \ + PCD_CALC_BLK32((dwReg),(wCount),wNBlocks); \ + } \ + else \ + { \ + PCD_CALC_BLK2((dwReg),(wCount),wNBlocks); \ + } \ + }/* PCD_SET_EP_CNT_RX_REG */ + +#define PCD_SET_EP_RX_DBUF0_CNT(USBx, bEpNum,wCount) {\ + uint16_t *pdwReg = PCD_EP_TX_CNT((USBx), (bEpNum)); \ + PCD_SET_EP_CNT_RX_REG(pdwReg, (wCount));\ + } + +/** + * @brief sets counter for the tx/rx buffer. + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @param wCount: Counter value. + * @retval None + */ +#define PCD_SET_EP_TX_CNT(USBx, bEpNum,wCount) (*PCD_EP_TX_CNT((USBx), (bEpNum)) = (wCount)) + + +/** + * @brief gets counter of the tx buffer. + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @retval Counter value + */ +#define PCD_GET_EP_TX_CNT(USBx, bEpNum) ((uint16_t)(*PCD_EP_TX_CNT((USBx), (bEpNum))) & 0x3ff) +#define PCD_GET_EP_RX_CNT(USBx, bEpNum) ((uint16_t)(*PCD_EP_RX_CNT((USBx), (bEpNum))) & 0x3ff) + +/** + * @brief Sets buffer 0/1 address in a double buffer endpoint. + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @param wBuf0Addr: buffer 0 address. + * @retval Counter value + */ +#define PCD_SET_EP_DBUF0_ADDR(USBx, bEpNum,wBuf0Addr) {PCD_SET_EP_TX_ADDRESS((USBx), (bEpNum), (wBuf0Addr));} +#define PCD_SET_EP_DBUF1_ADDR(USBx, bEpNum,wBuf1Addr) {PCD_SET_EP_RX_ADDRESS((USBx), (bEpNum), (wBuf1Addr));} + +/** + * @brief Sets addresses in a double buffer endpoint. + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @param wBuf0Addr: buffer 0 address. + * @param wBuf1Addr = buffer 1 address. + * @retval None + */ +#define PCD_SET_EP_DBUF_ADDR(USBx, bEpNum,wBuf0Addr,wBuf1Addr) { \ + PCD_SET_EP_DBUF0_ADDR((USBx), (bEpNum), (wBuf0Addr));\ + PCD_SET_EP_DBUF1_ADDR((USBx), (bEpNum), (wBuf1Addr));\ + } /* PCD_SET_EP_DBUF_ADDR */ + +/** + * @brief Gets buffer 0/1 address of a double buffer endpoint. + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @retval None + */ +#define PCD_GET_EP_DBUF0_ADDR(USBx, bEpNum) (PCD_GET_EP_TX_ADDRESS((USBx), (bEpNum))) +#define PCD_GET_EP_DBUF1_ADDR(USBx, bEpNum) (PCD_GET_EP_RX_ADDRESS((USBx), (bEpNum))) + +/** + * @brief Gets buffer 0/1 address of a double buffer endpoint. + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @param bDir: endpoint dir EP_DBUF_OUT = OUT + * EP_DBUF_IN = IN + * @param wCount: Counter value + * @retval None + */ +#define PCD_SET_EP_DBUF0_CNT(USBx, bEpNum, bDir, wCount) { \ + if((bDir) == PCD_EP_DBUF_OUT)\ + /* OUT endpoint */ \ + {PCD_SET_EP_RX_DBUF0_CNT((USBx), (bEpNum),(wCount));} \ + else if((bDir) == PCD_EP_DBUF_IN)\ + /* IN endpoint */ \ + *PCD_EP_TX_CNT((USBx), (bEpNum)) = (uint32_t)(wCount); \ + } /* SetEPDblBuf0Count*/ + +#define PCD_SET_EP_DBUF1_CNT(USBx, bEpNum, bDir, wCount) { \ + if((bDir) == PCD_EP_DBUF_OUT)\ + {/* OUT endpoint */ \ + PCD_SET_EP_RX_CNT((USBx), (bEpNum),(wCount)); \ + } \ + else if((bDir) == PCD_EP_DBUF_IN)\ + {/* IN endpoint */ \ + *PCD_EP_TX_CNT((USBx), (bEpNum)) = (uint32_t)(wCount); \ + } \ + } /* SetEPDblBuf1Count */ + +#define PCD_SET_EP_DBUF_CNT(USBx, bEpNum, bDir, wCount) {\ + PCD_SET_EP_DBUF0_CNT((USBx), (bEpNum), (bDir), (wCount)); \ + PCD_SET_EP_DBUF1_CNT((USBx), (bEpNum), (bDir), (wCount)); \ + } /* PCD_SET_EP_DBUF_CNT */ + +/** + * @brief Gets buffer 0/1 rx/tx counter for double buffering. + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @retval None + */ +#define PCD_GET_EP_DBUF0_CNT(USBx, bEpNum) (PCD_GET_EP_TX_CNT((USBx), (bEpNum))) +#define PCD_GET_EP_DBUF1_CNT(USBx, bEpNum) (PCD_GET_EP_RX_CNT((USBx), (bEpNum))) + +#endif /* USB */ + +#if defined(STM32L432xx) || defined(STM32L433xx) || defined(STM32L442xx) || defined(STM32L443xx) || \ + defined(STM32L452xx) || defined(STM32L462xx) + +/** @defgroup PCD_Instance_definition PCD Instance definition + * @{ + */ +#define IS_PCD_ALL_INSTANCE IS_USB_ALL_INSTANCE +/** + * @} + */ +#endif /* STM32L432xx || STM32L433xx || STM32L442xx || STM32L443xx || */ + /* STM32L452xx || STM32L462xx */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* STM32L432xx || STM32L433xx || STM32L442xx || STM32L443xx || */ + /* STM32L452xx || STM32L462xx || */ + /* STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx || */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#ifdef __cplusplus +} +#endif + + +#endif /* __STM32L4xx_HAL_PCD_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pcd_ex.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pcd_ex.h new file mode 100644 index 0000000..5fce957 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pcd_ex.h @@ -0,0 +1,136 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_pcd_ex.h + * @author MCD Application Team + * @brief Header file of PCD HAL module. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_PCD_EX_H +#define __STM32L4xx_HAL_PCD_EX_H + +#ifdef __cplusplus + extern "C" { +#endif + +#if defined(STM32L432xx) || defined(STM32L433xx) || defined(STM32L442xx) || defined(STM32L443xx) || \ + defined(STM32L452xx) || defined(STM32L462xx) || \ + defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || \ + defined(STM32L496xx) || defined(STM32L4A6xx) || \ + defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup PCDEx + * @{ + */ +/* Exported types ------------------------------------------------------------*/ +typedef enum +{ + PCD_LPM_L0_ACTIVE = 0x00, /* on */ + PCD_LPM_L1_ACTIVE = 0x01, /* LPM L1 sleep */ +}PCD_LPM_MsgTypeDef; + +typedef enum +{ + PCD_BCD_ERROR = 0xFF, + PCD_BCD_CONTACT_DETECTION = 0xFE, + PCD_BCD_STD_DOWNSTREAM_PORT = 0xFD, + PCD_BCD_CHARGING_DOWNSTREAM_PORT = 0xFC, + PCD_BCD_DEDICATED_CHARGING_PORT = 0xFB, + PCD_BCD_DISCOVERY_COMPLETED = 0x00, + +}PCD_BCD_MsgTypeDef; + +/* Exported constants --------------------------------------------------------*/ +/* Exported macros -----------------------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup PCDEx_Exported_Functions PCDEx Exported Functions + * @{ + */ +/** @addtogroup PCDEx_Exported_Functions_Group1 Peripheral Control functions + * @{ + */ + +#if defined(USB_OTG_FS) +HAL_StatusTypeDef HAL_PCDEx_SetTxFiFo(PCD_HandleTypeDef *hpcd, uint8_t fifo, uint16_t size); +HAL_StatusTypeDef HAL_PCDEx_SetRxFiFo(PCD_HandleTypeDef *hpcd, uint16_t size); +#endif /* USB_OTG_FS */ + +#if defined (USB) +HAL_StatusTypeDef HAL_PCDEx_PMAConfig(PCD_HandleTypeDef *hpcd, + uint16_t ep_addr, + uint16_t ep_kind, + uint32_t pmaadress); +#endif /* USB */ +HAL_StatusTypeDef HAL_PCDEx_ActivateLPM(PCD_HandleTypeDef *hpcd); +HAL_StatusTypeDef HAL_PCDEx_DeActivateLPM(PCD_HandleTypeDef *hpcd); +HAL_StatusTypeDef HAL_PCDEx_ActivateBCD(PCD_HandleTypeDef *hpcd); +HAL_StatusTypeDef HAL_PCDEx_DeActivateBCD(PCD_HandleTypeDef *hpcd); +void HAL_PCDEx_BCD_VBUSDetect(PCD_HandleTypeDef *hpcd); +void HAL_PCDEx_LPM_Callback(PCD_HandleTypeDef *hpcd, PCD_LPM_MsgTypeDef msg); +void HAL_PCDEx_BCD_Callback(PCD_HandleTypeDef *hpcd, PCD_BCD_MsgTypeDef msg); + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* STM32L432xx || STM32L433xx || STM32L442xx || STM32L443xx || */ + /* STM32L452xx || STM32L462xx || */ + /* STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx || */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#ifdef __cplusplus +} +#endif + + +#endif /* __STM32L4xx_HAL_PCD_EX_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pwr.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pwr.h new file mode 100644 index 0000000..75d18b1 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pwr.h @@ -0,0 +1,427 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_pwr.h + * @author MCD Application Team + * @brief Header file of PWR HAL module. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_PWR_H +#define __STM32L4xx_HAL_PWR_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup PWR + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ + +/** @defgroup PWR_Exported_Types PWR Exported Types + * @{ + */ + +/** + * @brief PWR PVD configuration structure definition + */ +typedef struct +{ + uint32_t PVDLevel; /*!< PVDLevel: Specifies the PVD detection level. + This parameter can be a value of @ref PWR_PVD_detection_level. */ + + uint32_t Mode; /*!< Mode: Specifies the operating mode for the selected pins. + This parameter can be a value of @ref PWR_PVD_Mode. */ +}PWR_PVDTypeDef; + + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ + +/** @defgroup PWR_Exported_Constants PWR Exported Constants + * @{ + */ + + +/** @defgroup PWR_PVD_detection_level Programmable Voltage Detection levels + * @{ + */ +#define PWR_PVDLEVEL_0 PWR_CR2_PLS_LEV0 /*!< PVD threshold around 2.0 V */ +#define PWR_PVDLEVEL_1 PWR_CR2_PLS_LEV1 /*!< PVD threshold around 2.2 V */ +#define PWR_PVDLEVEL_2 PWR_CR2_PLS_LEV2 /*!< PVD threshold around 2.4 V */ +#define PWR_PVDLEVEL_3 PWR_CR2_PLS_LEV3 /*!< PVD threshold around 2.5 V */ +#define PWR_PVDLEVEL_4 PWR_CR2_PLS_LEV4 /*!< PVD threshold around 2.6 V */ +#define PWR_PVDLEVEL_5 PWR_CR2_PLS_LEV5 /*!< PVD threshold around 2.8 V */ +#define PWR_PVDLEVEL_6 PWR_CR2_PLS_LEV6 /*!< PVD threshold around 2.9 V */ +#define PWR_PVDLEVEL_7 PWR_CR2_PLS_LEV7 /*!< External input analog voltage (compared internally to VREFINT) */ +/** + * @} + */ + +/** @defgroup PWR_PVD_Mode PWR PVD interrupt and event mode + * @{ + */ +#define PWR_PVD_MODE_NORMAL ((uint32_t)0x00000000) /*!< Basic mode is used */ +#define PWR_PVD_MODE_IT_RISING ((uint32_t)0x00010001) /*!< External Interrupt Mode with Rising edge trigger detection */ +#define PWR_PVD_MODE_IT_FALLING ((uint32_t)0x00010002) /*!< External Interrupt Mode with Falling edge trigger detection */ +#define PWR_PVD_MODE_IT_RISING_FALLING ((uint32_t)0x00010003) /*!< External Interrupt Mode with Rising/Falling edge trigger detection */ +#define PWR_PVD_MODE_EVENT_RISING ((uint32_t)0x00020001) /*!< Event Mode with Rising edge trigger detection */ +#define PWR_PVD_MODE_EVENT_FALLING ((uint32_t)0x00020002) /*!< Event Mode with Falling edge trigger detection */ +#define PWR_PVD_MODE_EVENT_RISING_FALLING ((uint32_t)0x00020003) /*!< Event Mode with Rising/Falling edge trigger detection */ +/** + * @} + */ + + + + +/** @defgroup PWR_Regulator_state_in_SLEEP_STOP_mode PWR regulator mode + * @{ + */ +#define PWR_MAINREGULATOR_ON ((uint32_t)0x00000000) /*!< Regulator in main mode */ +#define PWR_LOWPOWERREGULATOR_ON PWR_CR1_LPR /*!< Regulator in low-power mode */ +/** + * @} + */ + +/** @defgroup PWR_SLEEP_mode_entry PWR SLEEP mode entry + * @{ + */ +#define PWR_SLEEPENTRY_WFI ((uint8_t)0x01) /*!< Wait For Interruption instruction to enter Sleep mode */ +#define PWR_SLEEPENTRY_WFE ((uint8_t)0x02) /*!< Wait For Event instruction to enter Sleep mode */ +/** + * @} + */ + +/** @defgroup PWR_STOP_mode_entry PWR STOP mode entry + * @{ + */ +#define PWR_STOPENTRY_WFI ((uint8_t)0x01) /*!< Wait For Interruption instruction to enter Stop mode */ +#define PWR_STOPENTRY_WFE ((uint8_t)0x02) /*!< Wait For Event instruction to enter Stop mode */ +/** + * @} + */ + + +/** @defgroup PWR_PVD_EXTI_LINE PWR PVD external interrupt line + * @{ + */ +#define PWR_EXTI_LINE_PVD ((uint32_t)0x00010000) /*!< External interrupt line 16 Connected to the PVD EXTI Line */ +/** + * @} + */ + +/** @defgroup PWR_PVD_EVENT_LINE PWR PVD event line + * @{ + */ +#define PWR_EVENT_LINE_PVD ((uint32_t)0x00010000) /*!< Event line 16 Connected to the PVD Event Line */ +/** + * @} + */ + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ +/** @defgroup PWR_Exported_Macros PWR Exported Macros + * @{ + */ + +/** @brief Check whether or not a specific PWR flag is set. + * @param __FLAG__: specifies the flag to check. + * This parameter can be one of the following values: + * @arg @ref PWR_FLAG_WUF1 Wake Up Flag 1. Indicates that a wakeup event + * was received from the WKUP pin 1. + * @arg @ref PWR_FLAG_WUF2 Wake Up Flag 2. Indicates that a wakeup event + * was received from the WKUP pin 2. + * @arg @ref PWR_FLAG_WUF3 Wake Up Flag 3. Indicates that a wakeup event + * was received from the WKUP pin 3. + * @arg @ref PWR_FLAG_WUF4 Wake Up Flag 4. Indicates that a wakeup event + * was received from the WKUP pin 4. + * @arg @ref PWR_FLAG_WUF5 Wake Up Flag 5. Indicates that a wakeup event + * was received from the WKUP pin 5. + * @arg @ref PWR_FLAG_SB StandBy Flag. Indicates that the system + * entered StandBy mode. + * @arg @ref PWR_FLAG_WUFI Wake-Up Flag Internal. Set when a wakeup is detected on + * the internal wakeup line. + * @arg @ref PWR_FLAG_REGLPS Low Power Regulator Started. Indicates whether or not the + * low-power regulator is ready. + * @arg @ref PWR_FLAG_REGLPF Low Power Regulator Flag. Indicates whether the + * regulator is ready in main mode or is in low-power mode. + * @arg @ref PWR_FLAG_VOSF Voltage Scaling Flag. Indicates whether the regulator is ready + * in the selected voltage range or is still changing to the required voltage level. + * @arg @ref PWR_FLAG_PVDO Power Voltage Detector Output. Indicates whether VDD voltage is + * below or above the selected PVD threshold. + * @arg @ref PWR_FLAG_PVMO1 Peripheral Voltage Monitoring Output 1. Indicates whether VDDUSB voltage is + * is below or above PVM1 threshold (applicable when USB feature is supported). + @if STM32L486xx + * @arg @ref PWR_FLAG_PVMO2 Peripheral Voltage Monitoring Output 2. Indicates whether VDDIO2 voltage is + * is below or above PVM2 threshold (applicable when VDDIO2 is present on device). + @endif + * @arg @ref PWR_FLAG_PVMO3 Peripheral Voltage Monitoring Output 3. Indicates whether VDDA voltage is + * is below or above PVM3 threshold. + * @arg @ref PWR_FLAG_PVMO4 Peripheral Voltage Monitoring Output 4. Indicates whether VDDA voltage is + * is below or above PVM4 threshold. + * + * @retval The new state of __FLAG__ (TRUE or FALSE). + */ +#define __HAL_PWR_GET_FLAG(__FLAG__) ( ((((uint8_t)(__FLAG__)) >> 5U) == 1) ?\ + (PWR->SR1 & (1U << ((__FLAG__) & 31U))) :\ + (PWR->SR2 & (1U << ((__FLAG__) & 31U))) ) + +/** @brief Clear a specific PWR flag. + * @param __FLAG__: specifies the flag to clear. + * This parameter can be one of the following values: + * @arg @ref PWR_FLAG_WUF1 Wake Up Flag 1. Indicates that a wakeup event + * was received from the WKUP pin 1. + * @arg @ref PWR_FLAG_WUF2 Wake Up Flag 2. Indicates that a wakeup event + * was received from the WKUP pin 2. + * @arg @ref PWR_FLAG_WUF3 Wake Up Flag 3. Indicates that a wakeup event + * was received from the WKUP pin 3. + * @arg @ref PWR_FLAG_WUF4 Wake Up Flag 4. Indicates that a wakeup event + * was received from the WKUP pin 4. + * @arg @ref PWR_FLAG_WUF5 Wake Up Flag 5. Indicates that a wakeup event + * was received from the WKUP pin 5. + * @arg @ref PWR_FLAG_WU Encompasses all five Wake Up Flags. + * @arg @ref PWR_FLAG_SB Standby Flag. Indicates that the system + * entered Standby mode. + * @retval None + */ +#define __HAL_PWR_CLEAR_FLAG(__FLAG__) ( (((uint8_t)(__FLAG__)) == PWR_FLAG_WU) ?\ + (PWR->SCR = (__FLAG__)) :\ + (PWR->SCR = (1U << ((__FLAG__) & 31U))) ) +/** + * @brief Enable the PVD Extended Interrupt Line. + * @retval None + */ +#define __HAL_PWR_PVD_EXTI_ENABLE_IT() SET_BIT(EXTI->IMR1, PWR_EXTI_LINE_PVD) + +/** + * @brief Disable the PVD Extended Interrupt Line. + * @retval None + */ +#define __HAL_PWR_PVD_EXTI_DISABLE_IT() CLEAR_BIT(EXTI->IMR1, PWR_EXTI_LINE_PVD) + +/** + * @brief Enable the PVD Event Line. + * @retval None + */ +#define __HAL_PWR_PVD_EXTI_ENABLE_EVENT() SET_BIT(EXTI->EMR1, PWR_EVENT_LINE_PVD) + +/** + * @brief Disable the PVD Event Line. + * @retval None + */ +#define __HAL_PWR_PVD_EXTI_DISABLE_EVENT() CLEAR_BIT(EXTI->EMR1, PWR_EVENT_LINE_PVD) + +/** + * @brief Enable the PVD Extended Interrupt Rising Trigger. + * @retval None + */ +#define __HAL_PWR_PVD_EXTI_ENABLE_RISING_EDGE() SET_BIT(EXTI->RTSR1, PWR_EXTI_LINE_PVD) + +/** + * @brief Disable the PVD Extended Interrupt Rising Trigger. + * @retval None + */ +#define __HAL_PWR_PVD_EXTI_DISABLE_RISING_EDGE() CLEAR_BIT(EXTI->RTSR1, PWR_EXTI_LINE_PVD) + +/** + * @brief Enable the PVD Extended Interrupt Falling Trigger. + * @retval None + */ +#define __HAL_PWR_PVD_EXTI_ENABLE_FALLING_EDGE() SET_BIT(EXTI->FTSR1, PWR_EXTI_LINE_PVD) + + +/** + * @brief Disable the PVD Extended Interrupt Falling Trigger. + * @retval None + */ +#define __HAL_PWR_PVD_EXTI_DISABLE_FALLING_EDGE() CLEAR_BIT(EXTI->FTSR1, PWR_EXTI_LINE_PVD) + + +/** + * @brief Enable the PVD Extended Interrupt Rising & Falling Trigger. + * @retval None + */ +#define __HAL_PWR_PVD_EXTI_ENABLE_RISING_FALLING_EDGE() \ + do { \ + __HAL_PWR_PVD_EXTI_ENABLE_RISING_EDGE(); \ + __HAL_PWR_PVD_EXTI_ENABLE_FALLING_EDGE(); \ + } while(0) + +/** + * @brief Disable the PVD Extended Interrupt Rising & Falling Trigger. + * @retval None + */ +#define __HAL_PWR_PVD_EXTI_DISABLE_RISING_FALLING_EDGE() \ + do { \ + __HAL_PWR_PVD_EXTI_DISABLE_RISING_EDGE(); \ + __HAL_PWR_PVD_EXTI_DISABLE_FALLING_EDGE(); \ + } while(0) + +/** + * @brief Generate a Software interrupt on selected EXTI line. + * @retval None + */ +#define __HAL_PWR_PVD_EXTI_GENERATE_SWIT() SET_BIT(EXTI->SWIER1, PWR_EXTI_LINE_PVD) + +/** + * @brief Check whether or not the PVD EXTI interrupt flag is set. + * @retval EXTI PVD Line Status. + */ +#define __HAL_PWR_PVD_EXTI_GET_FLAG() (EXTI->PR1 & PWR_EXTI_LINE_PVD) + +/** + * @brief Clear the PVD EXTI interrupt flag. + * @retval None + */ +#define __HAL_PWR_PVD_EXTI_CLEAR_FLAG() WRITE_REG(EXTI->PR1, PWR_EXTI_LINE_PVD) + +/** + * @} + */ + + +/* Private macros --------------------------------------------------------*/ +/** @addtogroup PWR_Private_Macros PWR Private Macros + * @{ + */ + +#define IS_PWR_PVD_LEVEL(LEVEL) (((LEVEL) == PWR_PVDLEVEL_0) || ((LEVEL) == PWR_PVDLEVEL_1)|| \ + ((LEVEL) == PWR_PVDLEVEL_2) || ((LEVEL) == PWR_PVDLEVEL_3)|| \ + ((LEVEL) == PWR_PVDLEVEL_4) || ((LEVEL) == PWR_PVDLEVEL_5)|| \ + ((LEVEL) == PWR_PVDLEVEL_6) || ((LEVEL) == PWR_PVDLEVEL_7)) + +#define IS_PWR_PVD_MODE(MODE) (((MODE) == PWR_PVD_MODE_NORMAL) ||\ + ((MODE) == PWR_PVD_MODE_IT_RISING) ||\ + ((MODE) == PWR_PVD_MODE_IT_FALLING) ||\ + ((MODE) == PWR_PVD_MODE_IT_RISING_FALLING) ||\ + ((MODE) == PWR_PVD_MODE_EVENT_RISING) ||\ + ((MODE) == PWR_PVD_MODE_EVENT_FALLING) ||\ + ((MODE) == PWR_PVD_MODE_EVENT_RISING_FALLING)) + +#define IS_PWR_REGULATOR(REGULATOR) (((REGULATOR) == PWR_MAINREGULATOR_ON) || \ + ((REGULATOR) == PWR_LOWPOWERREGULATOR_ON)) + +#define IS_PWR_SLEEP_ENTRY(ENTRY) (((ENTRY) == PWR_SLEEPENTRY_WFI) || ((ENTRY) == PWR_SLEEPENTRY_WFE)) + +#define IS_PWR_STOP_ENTRY(ENTRY) (((ENTRY) == PWR_STOPENTRY_WFI) || ((ENTRY) == PWR_STOPENTRY_WFE) ) + +/** + * @} + */ + +/* Include PWR HAL Extended module */ +#include "stm32l4xx_hal_pwr_ex.h" + +/* Exported functions --------------------------------------------------------*/ + +/** @addtogroup PWR_Exported_Functions PWR Exported Functions + * @{ + */ + +/** @addtogroup PWR_Exported_Functions_Group1 Initialization and de-initialization functions + * @{ + */ + +/* Initialization and de-initialization functions *******************************/ +void HAL_PWR_DeInit(void); +void HAL_PWR_EnableBkUpAccess(void); +void HAL_PWR_DisableBkUpAccess(void); + +/** + * @} + */ + +/** @addtogroup PWR_Exported_Functions_Group2 Peripheral Control functions + * @{ + */ + +/* Peripheral Control functions ************************************************/ +HAL_StatusTypeDef HAL_PWR_ConfigPVD(PWR_PVDTypeDef *sConfigPVD); +void HAL_PWR_EnablePVD(void); +void HAL_PWR_DisablePVD(void); + + +/* WakeUp pins configuration functions ****************************************/ +void HAL_PWR_EnableWakeUpPin(uint32_t WakeUpPinPolarity); +void HAL_PWR_DisableWakeUpPin(uint32_t WakeUpPinx); + +/* Low Power modes configuration functions ************************************/ +void HAL_PWR_EnterSLEEPMode(uint32_t Regulator, uint8_t SLEEPEntry); +void HAL_PWR_EnterSTOPMode(uint32_t Regulator, uint8_t STOPEntry); +void HAL_PWR_EnterSTANDBYMode(void); + +void HAL_PWR_EnableSleepOnExit(void); +void HAL_PWR_DisableSleepOnExit(void); +void HAL_PWR_EnableSEVOnPend(void); +void HAL_PWR_DisableSEVOnPend(void); + +void HAL_PWR_PVDCallback(void); + + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + + +#endif /* __STM32L4xx_HAL_PWR_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pwr_ex.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pwr_ex.h new file mode 100644 index 0000000..b9b9fa5 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pwr_ex.h @@ -0,0 +1,906 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_pwr_ex.h + * @author MCD Application Team + * @brief Header file of PWR HAL Extended module. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_PWR_EX_H +#define __STM32L4xx_HAL_PWR_EX_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup PWREx + * @{ + */ + + +/* Exported types ------------------------------------------------------------*/ + +/** @defgroup PWREx_Exported_Types PWR Extended Exported Types + * @{ + */ + + +/** + * @brief PWR PVM configuration structure definition + */ +typedef struct +{ + uint32_t PVMType; /*!< PVMType: Specifies which voltage is monitored and against which threshold. + This parameter can be a value of @ref PWREx_PVM_Type. + @arg @ref PWR_PVM_1 Peripheral Voltage Monitoring 1 enable: VDDUSB versus 1.2 V (applicable when USB feature is supported). +@if STM32L486xx + @arg @ref PWR_PVM_2 Peripheral Voltage Monitoring 2 enable: VDDIO2 versus 0.9 V (applicable when VDDIO2 is present on device). +@endif + @arg @ref PWR_PVM_3 Peripheral Voltage Monitoring 3 enable: VDDA versus 1.62 V. + @arg @ref PWR_PVM_4 Peripheral Voltage Monitoring 4 enable: VDDA versus 2.2 V. */ + + uint32_t Mode; /*!< Mode: Specifies the operating mode for the selected pins. + This parameter can be a value of @ref PWREx_PVM_Mode. */ +}PWR_PVMTypeDef; + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ + +/** @defgroup PWREx_Exported_Constants PWR Extended Exported Constants + * @{ + */ + +/** @defgroup PWREx_WUP_Polarity Shift to apply to retrieve polarity information from PWR_WAKEUP_PINy_xxx constants + * @{ + */ +#define PWR_WUP_POLARITY_SHIFT 0x05 /*!< Internal constant used to retrieve wakeup pin polariry */ +/** + * @} + */ + + +/** @defgroup PWREx_WakeUp_Pins PWR wake-up pins + * @{ + */ +#define PWR_WAKEUP_PIN1 PWR_CR3_EWUP1 /*!< Wakeup pin 1 (with high level polarity) */ +#define PWR_WAKEUP_PIN2 PWR_CR3_EWUP2 /*!< Wakeup pin 2 (with high level polarity) */ +#define PWR_WAKEUP_PIN3 PWR_CR3_EWUP3 /*!< Wakeup pin 3 (with high level polarity) */ +#define PWR_WAKEUP_PIN4 PWR_CR3_EWUP4 /*!< Wakeup pin 4 (with high level polarity) */ +#define PWR_WAKEUP_PIN5 PWR_CR3_EWUP5 /*!< Wakeup pin 5 (with high level polarity) */ +#define PWR_WAKEUP_PIN1_HIGH PWR_CR3_EWUP1 /*!< Wakeup pin 1 (with high level polarity) */ +#define PWR_WAKEUP_PIN2_HIGH PWR_CR3_EWUP2 /*!< Wakeup pin 2 (with high level polarity) */ +#define PWR_WAKEUP_PIN3_HIGH PWR_CR3_EWUP3 /*!< Wakeup pin 3 (with high level polarity) */ +#define PWR_WAKEUP_PIN4_HIGH PWR_CR3_EWUP4 /*!< Wakeup pin 4 (with high level polarity) */ +#define PWR_WAKEUP_PIN5_HIGH PWR_CR3_EWUP5 /*!< Wakeup pin 5 (with high level polarity) */ +#define PWR_WAKEUP_PIN1_LOW (uint32_t)((PWR_CR4_WP1<IMR2, PWR_EXTI_LINE_PVM1) + +/** + * @brief Disable the PVM1 Extended Interrupt Line. + * @retval None + */ +#define __HAL_PWR_PVM1_EXTI_DISABLE_IT() CLEAR_BIT(EXTI->IMR2, PWR_EXTI_LINE_PVM1) + +/** + * @brief Enable the PVM1 Event Line. + * @retval None + */ +#define __HAL_PWR_PVM1_EXTI_ENABLE_EVENT() SET_BIT(EXTI->EMR2, PWR_EVENT_LINE_PVM1) + +/** + * @brief Disable the PVM1 Event Line. + * @retval None + */ +#define __HAL_PWR_PVM1_EXTI_DISABLE_EVENT() CLEAR_BIT(EXTI->EMR2, PWR_EVENT_LINE_PVM1) + +/** + * @brief Enable the PVM1 Extended Interrupt Rising Trigger. + * @retval None + */ +#define __HAL_PWR_PVM1_EXTI_ENABLE_RISING_EDGE() SET_BIT(EXTI->RTSR2, PWR_EXTI_LINE_PVM1) + +/** + * @brief Disable the PVM1 Extended Interrupt Rising Trigger. + * @retval None + */ +#define __HAL_PWR_PVM1_EXTI_DISABLE_RISING_EDGE() CLEAR_BIT(EXTI->RTSR2, PWR_EXTI_LINE_PVM1) + +/** + * @brief Enable the PVM1 Extended Interrupt Falling Trigger. + * @retval None + */ +#define __HAL_PWR_PVM1_EXTI_ENABLE_FALLING_EDGE() SET_BIT(EXTI->FTSR2, PWR_EXTI_LINE_PVM1) + + +/** + * @brief Disable the PVM1 Extended Interrupt Falling Trigger. + * @retval None + */ +#define __HAL_PWR_PVM1_EXTI_DISABLE_FALLING_EDGE() CLEAR_BIT(EXTI->FTSR2, PWR_EXTI_LINE_PVM1) + + +/** + * @brief PVM1 EXTI line configuration: set rising & falling edge trigger. + * @retval None + */ +#define __HAL_PWR_PVM1_EXTI_ENABLE_RISING_FALLING_EDGE() \ + do { \ + __HAL_PWR_PVM1_EXTI_ENABLE_RISING_EDGE(); \ + __HAL_PWR_PVM1_EXTI_ENABLE_FALLING_EDGE(); \ + } while(0) + +/** + * @brief Disable the PVM1 Extended Interrupt Rising & Falling Trigger. + * @retval None + */ +#define __HAL_PWR_PVM1_EXTI_DISABLE_RISING_FALLING_EDGE() \ + do { \ + __HAL_PWR_PVM1_EXTI_DISABLE_RISING_EDGE(); \ + __HAL_PWR_PVM1_EXTI_DISABLE_FALLING_EDGE(); \ + } while(0) + +/** + * @brief Generate a Software interrupt on selected EXTI line. + * @retval None + */ +#define __HAL_PWR_PVM1_EXTI_GENERATE_SWIT() SET_BIT(EXTI->SWIER2, PWR_EXTI_LINE_PVM1) + +/** + * @brief Check whether the specified PVM1 EXTI interrupt flag is set or not. + * @retval EXTI PVM1 Line Status. + */ +#define __HAL_PWR_PVM1_EXTI_GET_FLAG() (EXTI->PR2 & PWR_EXTI_LINE_PVM1) + +/** + * @brief Clear the PVM1 EXTI flag. + * @retval None + */ +#define __HAL_PWR_PVM1_EXTI_CLEAR_FLAG() WRITE_REG(EXTI->PR2, PWR_EXTI_LINE_PVM1) + +#endif /* PWR_CR2_PVME1 */ + + +#if defined(PWR_CR2_PVME2) +/** + * @brief Enable the PVM2 Extended Interrupt Line. + * @retval None + */ +#define __HAL_PWR_PVM2_EXTI_ENABLE_IT() SET_BIT(EXTI->IMR2, PWR_EXTI_LINE_PVM2) + +/** + * @brief Disable the PVM2 Extended Interrupt Line. + * @retval None + */ +#define __HAL_PWR_PVM2_EXTI_DISABLE_IT() CLEAR_BIT(EXTI->IMR2, PWR_EXTI_LINE_PVM2) + +/** + * @brief Enable the PVM2 Event Line. + * @retval None + */ +#define __HAL_PWR_PVM2_EXTI_ENABLE_EVENT() SET_BIT(EXTI->EMR2, PWR_EVENT_LINE_PVM2) + +/** + * @brief Disable the PVM2 Event Line. + * @retval None + */ +#define __HAL_PWR_PVM2_EXTI_DISABLE_EVENT() CLEAR_BIT(EXTI->EMR2, PWR_EVENT_LINE_PVM2) + +/** + * @brief Enable the PVM2 Extended Interrupt Rising Trigger. + * @retval None + */ +#define __HAL_PWR_PVM2_EXTI_ENABLE_RISING_EDGE() SET_BIT(EXTI->RTSR2, PWR_EXTI_LINE_PVM2) + +/** + * @brief Disable the PVM2 Extended Interrupt Rising Trigger. + * @retval None + */ +#define __HAL_PWR_PVM2_EXTI_DISABLE_RISING_EDGE() CLEAR_BIT(EXTI->RTSR2, PWR_EXTI_LINE_PVM2) + +/** + * @brief Enable the PVM2 Extended Interrupt Falling Trigger. + * @retval None + */ +#define __HAL_PWR_PVM2_EXTI_ENABLE_FALLING_EDGE() SET_BIT(EXTI->FTSR2, PWR_EXTI_LINE_PVM2) + + +/** + * @brief Disable the PVM2 Extended Interrupt Falling Trigger. + * @retval None + */ +#define __HAL_PWR_PVM2_EXTI_DISABLE_FALLING_EDGE() CLEAR_BIT(EXTI->FTSR2, PWR_EXTI_LINE_PVM2) + + +/** + * @brief PVM2 EXTI line configuration: set rising & falling edge trigger. + * @retval None + */ +#define __HAL_PWR_PVM2_EXTI_ENABLE_RISING_FALLING_EDGE() \ + do { \ + __HAL_PWR_PVM2_EXTI_ENABLE_RISING_EDGE(); \ + __HAL_PWR_PVM2_EXTI_ENABLE_FALLING_EDGE(); \ + } while(0) + +/** + * @brief Disable the PVM2 Extended Interrupt Rising & Falling Trigger. + * @retval None + */ +#define __HAL_PWR_PVM2_EXTI_DISABLE_RISING_FALLING_EDGE() \ + do { \ + __HAL_PWR_PVM2_EXTI_DISABLE_RISING_EDGE(); \ + __HAL_PWR_PVM2_EXTI_DISABLE_FALLING_EDGE(); \ + } while(0) + +/** + * @brief Generate a Software interrupt on selected EXTI line. + * @retval None + */ +#define __HAL_PWR_PVM2_EXTI_GENERATE_SWIT() SET_BIT(EXTI->SWIER2, PWR_EXTI_LINE_PVM2) + +/** + * @brief Check whether the specified PVM2 EXTI interrupt flag is set or not. + * @retval EXTI PVM2 Line Status. + */ +#define __HAL_PWR_PVM2_EXTI_GET_FLAG() (EXTI->PR2 & PWR_EXTI_LINE_PVM2) + +/** + * @brief Clear the PVM2 EXTI flag. + * @retval None + */ +#define __HAL_PWR_PVM2_EXTI_CLEAR_FLAG() WRITE_REG(EXTI->PR2, PWR_EXTI_LINE_PVM2) + +#endif /* PWR_CR2_PVME2 */ + + +/** + * @brief Enable the PVM3 Extended Interrupt Line. + * @retval None + */ +#define __HAL_PWR_PVM3_EXTI_ENABLE_IT() SET_BIT(EXTI->IMR2, PWR_EXTI_LINE_PVM3) + +/** + * @brief Disable the PVM3 Extended Interrupt Line. + * @retval None + */ +#define __HAL_PWR_PVM3_EXTI_DISABLE_IT() CLEAR_BIT(EXTI->IMR2, PWR_EXTI_LINE_PVM3) + +/** + * @brief Enable the PVM3 Event Line. + * @retval None + */ +#define __HAL_PWR_PVM3_EXTI_ENABLE_EVENT() SET_BIT(EXTI->EMR2, PWR_EVENT_LINE_PVM3) + +/** + * @brief Disable the PVM3 Event Line. + * @retval None + */ +#define __HAL_PWR_PVM3_EXTI_DISABLE_EVENT() CLEAR_BIT(EXTI->EMR2, PWR_EVENT_LINE_PVM3) + +/** + * @brief Enable the PVM3 Extended Interrupt Rising Trigger. + * @retval None + */ +#define __HAL_PWR_PVM3_EXTI_ENABLE_RISING_EDGE() SET_BIT(EXTI->RTSR2, PWR_EXTI_LINE_PVM3) + +/** + * @brief Disable the PVM3 Extended Interrupt Rising Trigger. + * @retval None + */ +#define __HAL_PWR_PVM3_EXTI_DISABLE_RISING_EDGE() CLEAR_BIT(EXTI->RTSR2, PWR_EXTI_LINE_PVM3) + +/** + * @brief Enable the PVM3 Extended Interrupt Falling Trigger. + * @retval None + */ +#define __HAL_PWR_PVM3_EXTI_ENABLE_FALLING_EDGE() SET_BIT(EXTI->FTSR2, PWR_EXTI_LINE_PVM3) + + +/** + * @brief Disable the PVM3 Extended Interrupt Falling Trigger. + * @retval None + */ +#define __HAL_PWR_PVM3_EXTI_DISABLE_FALLING_EDGE() CLEAR_BIT(EXTI->FTSR2, PWR_EXTI_LINE_PVM3) + + +/** + * @brief PVM3 EXTI line configuration: set rising & falling edge trigger. + * @retval None + */ +#define __HAL_PWR_PVM3_EXTI_ENABLE_RISING_FALLING_EDGE() \ + do { \ + __HAL_PWR_PVM3_EXTI_ENABLE_RISING_EDGE(); \ + __HAL_PWR_PVM3_EXTI_ENABLE_FALLING_EDGE(); \ + } while(0) + +/** + * @brief Disable the PVM3 Extended Interrupt Rising & Falling Trigger. + * @retval None + */ +#define __HAL_PWR_PVM3_EXTI_DISABLE_RISING_FALLING_EDGE() \ + do { \ + __HAL_PWR_PVM3_EXTI_DISABLE_RISING_EDGE(); \ + __HAL_PWR_PVM3_EXTI_DISABLE_FALLING_EDGE(); \ + } while(0) + +/** + * @brief Generate a Software interrupt on selected EXTI line. + * @retval None + */ +#define __HAL_PWR_PVM3_EXTI_GENERATE_SWIT() SET_BIT(EXTI->SWIER2, PWR_EXTI_LINE_PVM3) + +/** + * @brief Check whether the specified PVM3 EXTI interrupt flag is set or not. + * @retval EXTI PVM3 Line Status. + */ +#define __HAL_PWR_PVM3_EXTI_GET_FLAG() (EXTI->PR2 & PWR_EXTI_LINE_PVM3) + +/** + * @brief Clear the PVM3 EXTI flag. + * @retval None + */ +#define __HAL_PWR_PVM3_EXTI_CLEAR_FLAG() WRITE_REG(EXTI->PR2, PWR_EXTI_LINE_PVM3) + + + + +/** + * @brief Enable the PVM4 Extended Interrupt Line. + * @retval None + */ +#define __HAL_PWR_PVM4_EXTI_ENABLE_IT() SET_BIT(EXTI->IMR2, PWR_EXTI_LINE_PVM4) + +/** + * @brief Disable the PVM4 Extended Interrupt Line. + * @retval None + */ +#define __HAL_PWR_PVM4_EXTI_DISABLE_IT() CLEAR_BIT(EXTI->IMR2, PWR_EXTI_LINE_PVM4) + +/** + * @brief Enable the PVM4 Event Line. + * @retval None + */ +#define __HAL_PWR_PVM4_EXTI_ENABLE_EVENT() SET_BIT(EXTI->EMR2, PWR_EVENT_LINE_PVM4) + +/** + * @brief Disable the PVM4 Event Line. + * @retval None + */ +#define __HAL_PWR_PVM4_EXTI_DISABLE_EVENT() CLEAR_BIT(EXTI->EMR2, PWR_EVENT_LINE_PVM4) + +/** + * @brief Enable the PVM4 Extended Interrupt Rising Trigger. + * @retval None + */ +#define __HAL_PWR_PVM4_EXTI_ENABLE_RISING_EDGE() SET_BIT(EXTI->RTSR2, PWR_EXTI_LINE_PVM4) + +/** + * @brief Disable the PVM4 Extended Interrupt Rising Trigger. + * @retval None + */ +#define __HAL_PWR_PVM4_EXTI_DISABLE_RISING_EDGE() CLEAR_BIT(EXTI->RTSR2, PWR_EXTI_LINE_PVM4) + +/** + * @brief Enable the PVM4 Extended Interrupt Falling Trigger. + * @retval None + */ +#define __HAL_PWR_PVM4_EXTI_ENABLE_FALLING_EDGE() SET_BIT(EXTI->FTSR2, PWR_EXTI_LINE_PVM4) + + +/** + * @brief Disable the PVM4 Extended Interrupt Falling Trigger. + * @retval None + */ +#define __HAL_PWR_PVM4_EXTI_DISABLE_FALLING_EDGE() CLEAR_BIT(EXTI->FTSR2, PWR_EXTI_LINE_PVM4) + + +/** + * @brief PVM4 EXTI line configuration: set rising & falling edge trigger. + * @retval None + */ +#define __HAL_PWR_PVM4_EXTI_ENABLE_RISING_FALLING_EDGE() \ + do { \ + __HAL_PWR_PVM4_EXTI_ENABLE_RISING_EDGE(); \ + __HAL_PWR_PVM4_EXTI_ENABLE_FALLING_EDGE(); \ + } while(0) + +/** + * @brief Disable the PVM4 Extended Interrupt Rising & Falling Trigger. + * @retval None + */ +#define __HAL_PWR_PVM4_EXTI_DISABLE_RISING_FALLING_EDGE() \ + do { \ + __HAL_PWR_PVM4_EXTI_DISABLE_RISING_EDGE(); \ + __HAL_PWR_PVM4_EXTI_DISABLE_FALLING_EDGE(); \ + } while(0) + +/** + * @brief Generate a Software interrupt on selected EXTI line. + * @retval None + */ +#define __HAL_PWR_PVM4_EXTI_GENERATE_SWIT() SET_BIT(EXTI->SWIER2, PWR_EXTI_LINE_PVM4) + +/** + * @brief Check whether or not the specified PVM4 EXTI interrupt flag is set. + * @retval EXTI PVM4 Line Status. + */ +#define __HAL_PWR_PVM4_EXTI_GET_FLAG() (EXTI->PR2 & PWR_EXTI_LINE_PVM4) + +/** + * @brief Clear the PVM4 EXTI flag. + * @retval None + */ +#define __HAL_PWR_PVM4_EXTI_CLEAR_FLAG() WRITE_REG(EXTI->PR2, PWR_EXTI_LINE_PVM4) + + +/** + * @brief Configure the main internal regulator output voltage. + * @param __REGULATOR__: specifies the regulator output voltage to achieve + * a tradeoff between performance and power consumption. + * This parameter can be one of the following values: + * @arg @ref PWR_REGULATOR_VOLTAGE_SCALE1 Regulator voltage output range 1 mode, + * typical output voltage at 1.2 V, + * system frequency up to 80 MHz. + * @arg @ref PWR_REGULATOR_VOLTAGE_SCALE2 Regulator voltage output range 2 mode, + * typical output voltage at 1.0 V, + * system frequency up to 26 MHz. + * @note This macro is similar to HAL_PWREx_ControlVoltageScaling() API but doesn't check + * whether or not VOSF flag is cleared when moving from range 2 to range 1. User + * may resort to __HAL_PWR_GET_FLAG() macro to check VOSF bit resetting. + * @retval None + */ +#define __HAL_PWR_VOLTAGESCALING_CONFIG(__REGULATOR__) do { \ + __IO uint32_t tmpreg; \ + MODIFY_REG(PWR->CR1, PWR_CR1_VOS, (__REGULATOR__)); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(PWR->CR1, PWR_CR1_VOS); \ + UNUSED(tmpreg); \ + } while(0) + +/** + * @} + */ + +/* Private macros --------------------------------------------------------*/ +/** @addtogroup PWREx_Private_Macros PWR Extended Private Macros + * @{ + */ + +#define IS_PWR_WAKEUP_PIN(PIN) (((PIN) == PWR_WAKEUP_PIN1) || \ + ((PIN) == PWR_WAKEUP_PIN2) || \ + ((PIN) == PWR_WAKEUP_PIN3) || \ + ((PIN) == PWR_WAKEUP_PIN4) || \ + ((PIN) == PWR_WAKEUP_PIN5) || \ + ((PIN) == PWR_WAKEUP_PIN1_HIGH) || \ + ((PIN) == PWR_WAKEUP_PIN2_HIGH) || \ + ((PIN) == PWR_WAKEUP_PIN3_HIGH) || \ + ((PIN) == PWR_WAKEUP_PIN4_HIGH) || \ + ((PIN) == PWR_WAKEUP_PIN5_HIGH) || \ + ((PIN) == PWR_WAKEUP_PIN1_LOW) || \ + ((PIN) == PWR_WAKEUP_PIN2_LOW) || \ + ((PIN) == PWR_WAKEUP_PIN3_LOW) || \ + ((PIN) == PWR_WAKEUP_PIN4_LOW) || \ + ((PIN) == PWR_WAKEUP_PIN5_LOW)) + +#if defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define IS_PWR_PVM_TYPE(TYPE) (((TYPE) == PWR_PVM_1) ||\ + ((TYPE) == PWR_PVM_2) ||\ + ((TYPE) == PWR_PVM_3) ||\ + ((TYPE) == PWR_PVM_4)) +#elif defined (STM32L471xx) +#define IS_PWR_PVM_TYPE(TYPE) (((TYPE) == PWR_PVM_2) ||\ + ((TYPE) == PWR_PVM_3) ||\ + ((TYPE) == PWR_PVM_4)) +#endif + +#if defined (STM32L433xx) || defined (STM32L443xx) || defined (STM32L452xx) || defined (STM32L462xx) +#define IS_PWR_PVM_TYPE(TYPE) (((TYPE) == PWR_PVM_1) ||\ + ((TYPE) == PWR_PVM_3) ||\ + ((TYPE) == PWR_PVM_4)) +#elif defined (STM32L431xx) || defined (STM32L432xx) || defined (STM32L442xx) || defined (STM32L451xx) +#define IS_PWR_PVM_TYPE(TYPE) (((TYPE) == PWR_PVM_3) ||\ + ((TYPE) == PWR_PVM_4)) +#endif + +#define IS_PWR_PVM_MODE(MODE) (((MODE) == PWR_PVM_MODE_NORMAL) ||\ + ((MODE) == PWR_PVM_MODE_IT_RISING) ||\ + ((MODE) == PWR_PVM_MODE_IT_FALLING) ||\ + ((MODE) == PWR_PVM_MODE_IT_RISING_FALLING) ||\ + ((MODE) == PWR_PVM_MODE_EVENT_RISING) ||\ + ((MODE) == PWR_PVM_MODE_EVENT_FALLING) ||\ + ((MODE) == PWR_PVM_MODE_EVENT_RISING_FALLING)) + +#if defined(PWR_CR5_R1MODE) +#define IS_PWR_VOLTAGE_SCALING_RANGE(RANGE) (((RANGE) == PWR_REGULATOR_VOLTAGE_SCALE1_BOOST) || \ + ((RANGE) == PWR_REGULATOR_VOLTAGE_SCALE1) || \ + ((RANGE) == PWR_REGULATOR_VOLTAGE_SCALE2)) +#else +#define IS_PWR_VOLTAGE_SCALING_RANGE(RANGE) (((RANGE) == PWR_REGULATOR_VOLTAGE_SCALE1) || \ + ((RANGE) == PWR_REGULATOR_VOLTAGE_SCALE2)) +#endif + + +#define IS_PWR_BATTERY_RESISTOR_SELECT(RESISTOR) (((RESISTOR) == PWR_BATTERY_CHARGING_RESISTOR_5) ||\ + ((RESISTOR) == PWR_BATTERY_CHARGING_RESISTOR_1_5)) + +#define IS_PWR_BATTERY_CHARGING(CHARGING) (((CHARGING) == PWR_BATTERY_CHARGING_DISABLE) ||\ + ((CHARGING) == PWR_BATTERY_CHARGING_ENABLE)) + +#define IS_PWR_GPIO_BIT_NUMBER(BIT_NUMBER) (((BIT_NUMBER) & GPIO_PIN_MASK) != (uint32_t)0x00) + + +#if defined (STM32L431xx) || defined (STM32L433xx) || defined (STM32L443xx) || \ + defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) +#define IS_PWR_GPIO(GPIO) (((GPIO) == PWR_GPIO_A) ||\ + ((GPIO) == PWR_GPIO_B) ||\ + ((GPIO) == PWR_GPIO_C) ||\ + ((GPIO) == PWR_GPIO_D) ||\ + ((GPIO) == PWR_GPIO_E) ||\ + ((GPIO) == PWR_GPIO_H)) +#elif defined (STM32L432xx) || defined (STM32L442xx) +#define IS_PWR_GPIO(GPIO) (((GPIO) == PWR_GPIO_A) ||\ + ((GPIO) == PWR_GPIO_B) ||\ + ((GPIO) == PWR_GPIO_C) ||\ + ((GPIO) == PWR_GPIO_H)) +#elif defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) +#define IS_PWR_GPIO(GPIO) (((GPIO) == PWR_GPIO_A) ||\ + ((GPIO) == PWR_GPIO_B) ||\ + ((GPIO) == PWR_GPIO_C) ||\ + ((GPIO) == PWR_GPIO_D) ||\ + ((GPIO) == PWR_GPIO_E) ||\ + ((GPIO) == PWR_GPIO_F) ||\ + ((GPIO) == PWR_GPIO_G) ||\ + ((GPIO) == PWR_GPIO_H)) +#elif defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define IS_PWR_GPIO(GPIO) (((GPIO) == PWR_GPIO_A) ||\ + ((GPIO) == PWR_GPIO_B) ||\ + ((GPIO) == PWR_GPIO_C) ||\ + ((GPIO) == PWR_GPIO_D) ||\ + ((GPIO) == PWR_GPIO_E) ||\ + ((GPIO) == PWR_GPIO_F) ||\ + ((GPIO) == PWR_GPIO_G) ||\ + ((GPIO) == PWR_GPIO_H) ||\ + ((GPIO) == PWR_GPIO_I)) +#endif + + +/** + * @} + */ + + +/** @addtogroup PWREx_Exported_Functions PWR Extended Exported Functions + * @{ + */ + +/** @addtogroup PWREx_Exported_Functions_Group1 Extended Peripheral Control functions + * @{ + */ + + +/* Peripheral Control functions **********************************************/ +uint32_t HAL_PWREx_GetVoltageRange(void); +HAL_StatusTypeDef HAL_PWREx_ControlVoltageScaling(uint32_t VoltageScaling); +void HAL_PWREx_EnableBatteryCharging(uint32_t ResistorSelection); +void HAL_PWREx_DisableBatteryCharging(void); +#if defined(PWR_CR2_USV) +void HAL_PWREx_EnableVddUSB(void); +void HAL_PWREx_DisableVddUSB(void); +#endif /* PWR_CR2_USV */ +#if defined(PWR_CR2_IOSV) +void HAL_PWREx_EnableVddIO2(void); +void HAL_PWREx_DisableVddIO2(void); +#endif /* PWR_CR2_IOSV */ +void HAL_PWREx_EnableInternalWakeUpLine(void); +void HAL_PWREx_DisableInternalWakeUpLine(void); +HAL_StatusTypeDef HAL_PWREx_EnableGPIOPullUp(uint32_t GPIO, uint32_t GPIONumber); +HAL_StatusTypeDef HAL_PWREx_DisableGPIOPullUp(uint32_t GPIO, uint32_t GPIONumber); +HAL_StatusTypeDef HAL_PWREx_EnableGPIOPullDown(uint32_t GPIO, uint32_t GPIONumber); +HAL_StatusTypeDef HAL_PWREx_DisableGPIOPullDown(uint32_t GPIO, uint32_t GPIONumber); +void HAL_PWREx_EnablePullUpPullDownConfig(void); +void HAL_PWREx_DisablePullUpPullDownConfig(void); +void HAL_PWREx_EnableSRAM2ContentRetention(void); +void HAL_PWREx_DisableSRAM2ContentRetention(void); +#if defined(PWR_CR1_RRSTP) +void HAL_PWREx_EnableSRAM3ContentRetention(void); +void HAL_PWREx_DisableSRAM3ContentRetention(void); +#endif /* PWR_CR1_RRSTP */ +#if defined(PWR_CR3_DSIPDEN) +void HAL_PWREx_EnableDSIPinsPDActivation(void); +void HAL_PWREx_DisableDSIPinsPDActivation(void); +#endif /* PWR_CR3_DSIPDEN */ +#if defined(PWR_CR2_PVME1) +void HAL_PWREx_EnablePVM1(void); +void HAL_PWREx_DisablePVM1(void); +#endif /* PWR_CR2_PVME1 */ +#if defined(PWR_CR2_PVME2) +void HAL_PWREx_EnablePVM2(void); +void HAL_PWREx_DisablePVM2(void); +#endif /* PWR_CR2_PVME2 */ +void HAL_PWREx_EnablePVM3(void); +void HAL_PWREx_DisablePVM3(void); +void HAL_PWREx_EnablePVM4(void); +void HAL_PWREx_DisablePVM4(void); +HAL_StatusTypeDef HAL_PWREx_ConfigPVM(PWR_PVMTypeDef *sConfigPVM); + + +/* Low Power modes configuration functions ************************************/ +void HAL_PWREx_EnableLowPowerRunMode(void); +HAL_StatusTypeDef HAL_PWREx_DisableLowPowerRunMode(void); +void HAL_PWREx_EnterSTOP0Mode(uint8_t STOPEntry); +void HAL_PWREx_EnterSTOP1Mode(uint8_t STOPEntry); +void HAL_PWREx_EnterSTOP2Mode(uint8_t STOPEntry); +void HAL_PWREx_EnterSHUTDOWNMode(void); + +void HAL_PWREx_PVD_PVM_IRQHandler(void); +#if defined(PWR_CR2_PVME1) +void HAL_PWREx_PVM1Callback(void); +#endif /* PWR_CR2_PVME1 */ +#if defined(PWR_CR2_PVME2) +void HAL_PWREx_PVM2Callback(void); +#endif /* PWR_CR2_PVME2 */ +void HAL_PWREx_PVM3Callback(void); +void HAL_PWREx_PVM4Callback(void); + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + + +#endif /* __STM32L4xx_HAL_PWR_EX_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rcc.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rcc.h new file mode 100644 index 0000000..9c8014c --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rcc.h @@ -0,0 +1,4594 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_rcc.h + * @author MCD Application Team + * @brief Header file of RCC HAL module. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_RCC_H +#define __STM32L4xx_HAL_RCC_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup RCC + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup RCC_Exported_Types RCC Exported Types + * @{ + */ + +/** + * @brief RCC PLL configuration structure definition + */ +typedef struct +{ + uint32_t PLLState; /*!< The new state of the PLL. + This parameter can be a value of @ref RCC_PLL_Config */ + + uint32_t PLLSource; /*!< RCC_PLLSource: PLL entry clock source. + This parameter must be a value of @ref RCC_PLL_Clock_Source */ + + uint32_t PLLM; /*!< PLLM: Division factor for PLL VCO input clock. + This parameter must be a number between Min_Data = 1 and Max_Data = 16 on STM32L4Rx/STM32L4Sx devices. + This parameter must be a number between Min_Data = 1 and Max_Data = 8 on the other devices */ + + uint32_t PLLN; /*!< PLLN: Multiplication factor for PLL VCO output clock. + This parameter must be a number between Min_Data = 8 and Max_Data = 86 */ + + uint32_t PLLP; /*!< PLLP: Division factor for SAI clock. + This parameter must be a value of @ref RCC_PLLP_Clock_Divider */ + + uint32_t PLLQ; /*!< PLLQ: Division factor for SDMMC1, RNG and USB clocks. + This parameter must be a value of @ref RCC_PLLQ_Clock_Divider */ + + uint32_t PLLR; /*!< PLLR: Division for the main system clock. + User have to set the PLLR parameter correctly to not exceed max frequency 80MHZ. + This parameter must be a value of @ref RCC_PLLR_Clock_Divider */ + +}RCC_PLLInitTypeDef; + +/** + * @brief RCC Internal/External Oscillator (HSE, HSI, MSI, LSE and LSI) configuration structure definition + */ +typedef struct +{ + uint32_t OscillatorType; /*!< The oscillators to be configured. + This parameter can be a value of @ref RCC_Oscillator_Type */ + + uint32_t HSEState; /*!< The new state of the HSE. + This parameter can be a value of @ref RCC_HSE_Config */ + + uint32_t LSEState; /*!< The new state of the LSE. + This parameter can be a value of @ref RCC_LSE_Config */ + + uint32_t HSIState; /*!< The new state of the HSI. + This parameter can be a value of @ref RCC_HSI_Config */ + + uint32_t HSICalibrationValue; /*!< The calibration trimming value (default is RCC_HSICALIBRATION_DEFAULT). + This parameter must be a number between Min_Data = 0x00 and Max_Data = 0x1F on STM32L43x/STM32L44x/STM32L47x/STM32L48x devices. + This parameter must be a number between Min_Data = 0x00 and Max_Data = 0x7F on the other devices */ + + uint32_t LSIState; /*!< The new state of the LSI. + This parameter can be a value of @ref RCC_LSI_Config */ + + uint32_t MSIState; /*!< The new state of the MSI. + This parameter can be a value of @ref RCC_MSI_Config */ + + uint32_t MSICalibrationValue; /*!< The calibration trimming value (default is RCC_MSICALIBRATION_DEFAULT). + This parameter must be a number between Min_Data = 0x00 and Max_Data = 0xFF */ + + uint32_t MSIClockRange; /*!< The MSI frequency range. + This parameter can be a value of @ref RCC_MSI_Clock_Range */ + + uint32_t HSI48State; /*!< The new state of the HSI48 (only applicable to STM32L43x/STM32L44x/STM32L49x/STM32L4Ax devices). + This parameter can be a value of @ref RCC_HSI48_Config */ + + RCC_PLLInitTypeDef PLL; /*!< Main PLL structure parameters */ + +}RCC_OscInitTypeDef; + +/** + * @brief RCC System, AHB and APB busses clock configuration structure definition + */ +typedef struct +{ + uint32_t ClockType; /*!< The clock to be configured. + This parameter can be a value of @ref RCC_System_Clock_Type */ + + uint32_t SYSCLKSource; /*!< The clock source used as system clock (SYSCLK). + This parameter can be a value of @ref RCC_System_Clock_Source */ + + uint32_t AHBCLKDivider; /*!< The AHB clock (HCLK) divider. This clock is derived from the system clock (SYSCLK). + This parameter can be a value of @ref RCC_AHB_Clock_Source */ + + uint32_t APB1CLKDivider; /*!< The APB1 clock (PCLK1) divider. This clock is derived from the AHB clock (HCLK). + This parameter can be a value of @ref RCC_APB1_APB2_Clock_Source */ + + uint32_t APB2CLKDivider; /*!< The APB2 clock (PCLK2) divider. This clock is derived from the AHB clock (HCLK). + This parameter can be a value of @ref RCC_APB1_APB2_Clock_Source */ + +}RCC_ClkInitTypeDef; + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup RCC_Exported_Constants RCC Exported Constants + * @{ + */ + +/** @defgroup RCC_Timeout_Value Timeout Values + * @{ + */ +#define RCC_DBP_TIMEOUT_VALUE 2U /* 2 ms (minimum Tick + 1) */ +#define RCC_LSE_TIMEOUT_VALUE LSE_STARTUP_TIMEOUT +/** + * @} + */ + +/** @defgroup RCC_Oscillator_Type Oscillator Type + * @{ + */ +#define RCC_OSCILLATORTYPE_NONE 0x00000000U /*!< Oscillator configuration unchanged */ +#define RCC_OSCILLATORTYPE_HSE 0x00000001U /*!< HSE to configure */ +#define RCC_OSCILLATORTYPE_HSI 0x00000002U /*!< HSI to configure */ +#define RCC_OSCILLATORTYPE_LSE 0x00000004U /*!< LSE to configure */ +#define RCC_OSCILLATORTYPE_LSI 0x00000008U /*!< LSI to configure */ +#define RCC_OSCILLATORTYPE_MSI 0x00000010U /*!< MSI to configure */ +#if defined(RCC_HSI48_SUPPORT) +#define RCC_OSCILLATORTYPE_HSI48 0x00000020U /*!< HSI48 to configure */ +#endif /* RCC_HSI48_SUPPORT */ +/** + * @} + */ + +/** @defgroup RCC_HSE_Config HSE Config + * @{ + */ +#define RCC_HSE_OFF 0x00000000U /*!< HSE clock deactivation */ +#define RCC_HSE_ON RCC_CR_HSEON /*!< HSE clock activation */ +#define RCC_HSE_BYPASS (RCC_CR_HSEBYP | RCC_CR_HSEON) /*!< External clock source for HSE clock */ +/** + * @} + */ + +/** @defgroup RCC_LSE_Config LSE Config + * @{ + */ +#define RCC_LSE_OFF 0x00000000U /*!< LSE clock deactivation */ +#define RCC_LSE_ON RCC_BDCR_LSEON /*!< LSE clock activation */ +#define RCC_LSE_BYPASS (RCC_BDCR_LSEBYP | RCC_BDCR_LSEON) /*!< External clock source for LSE clock */ +/** + * @} + */ + +/** @defgroup RCC_HSI_Config HSI Config + * @{ + */ +#define RCC_HSI_OFF 0x00000000U /*!< HSI clock deactivation */ +#define RCC_HSI_ON RCC_CR_HSION /*!< HSI clock activation */ + +#if defined(STM32L431xx) || defined(STM32L432xx) || defined(STM32L433xx) || defined(STM32L442xx) || defined(STM32L443xx) || \ + defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) +#define RCC_HSICALIBRATION_DEFAULT 0x10U /* Default HSI calibration trimming value */ +#else +#define RCC_HSICALIBRATION_DEFAULT 0x40U /* Default HSI calibration trimming value */ +#endif /* STM32L431xx || STM32L432xx || STM32L433xx || STM32L442xx || STM32L443xx || */ + /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx */ +/** + * @} + */ + +/** @defgroup RCC_LSI_Config LSI Config + * @{ + */ +#define RCC_LSI_OFF 0x00000000U /*!< LSI clock deactivation */ +#define RCC_LSI_ON RCC_CSR_LSION /*!< LSI clock activation */ +/** + * @} + */ + +/** @defgroup RCC_MSI_Config MSI Config + * @{ + */ +#define RCC_MSI_OFF 0x00000000U /*!< MSI clock deactivation */ +#define RCC_MSI_ON RCC_CR_MSION /*!< MSI clock activation */ + +#define RCC_MSICALIBRATION_DEFAULT 0U /*!< Default MSI calibration trimming value */ +/** + * @} + */ + +#if defined(RCC_HSI48_SUPPORT) +/** @defgroup RCC_HSI48_Config HSI48 Config + * @{ + */ +#define RCC_HSI48_OFF 0x00000000U /*!< HSI48 clock deactivation */ +#define RCC_HSI48_ON RCC_CRRCR_HSI48ON /*!< HSI48 clock activation */ +/** + * @} + */ +#else +/** @defgroup RCC_HSI48_Config HSI48 Config + * @{ + */ +#define RCC_HSI48_OFF 0x00000000U /*!< HSI48 clock deactivation */ +/** + * @} + */ +#endif /* RCC_HSI48_SUPPORT */ + +/** @defgroup RCC_PLL_Config PLL Config + * @{ + */ +#define RCC_PLL_NONE 0x00000000U /*!< PLL configuration unchanged */ +#define RCC_PLL_OFF 0x00000001U /*!< PLL deactivation */ +#define RCC_PLL_ON 0x00000002U /*!< PLL activation */ +/** + * @} + */ + +/** @defgroup RCC_PLLP_Clock_Divider PLLP Clock Divider + * @{ + */ +#if defined(RCC_PLLP_DIV_2_31_SUPPORT) +#define RCC_PLLP_DIV2 0x00000002U /*!< PLLP division factor = 2 */ +#define RCC_PLLP_DIV3 0x00000003U /*!< PLLP division factor = 3 */ +#define RCC_PLLP_DIV4 0x00000004U /*!< PLLP division factor = 4 */ +#define RCC_PLLP_DIV5 0x00000005U /*!< PLLP division factor = 5 */ +#define RCC_PLLP_DIV6 0x00000006U /*!< PLLP division factor = 6 */ +#define RCC_PLLP_DIV7 0x00000007U /*!< PLLP division factor = 7 */ +#define RCC_PLLP_DIV8 0x00000008U /*!< PLLP division factor = 8 */ +#define RCC_PLLP_DIV9 0x00000009U /*!< PLLP division factor = 9 */ +#define RCC_PLLP_DIV10 0x0000000AU /*!< PLLP division factor = 10 */ +#define RCC_PLLP_DIV11 0x0000000BU /*!< PLLP division factor = 11 */ +#define RCC_PLLP_DIV12 0x0000000CU /*!< PLLP division factor = 12 */ +#define RCC_PLLP_DIV13 0x0000000DU /*!< PLLP division factor = 13 */ +#define RCC_PLLP_DIV14 0x0000000EU /*!< PLLP division factor = 14 */ +#define RCC_PLLP_DIV15 0x0000000FU /*!< PLLP division factor = 15 */ +#define RCC_PLLP_DIV16 0x00000010U /*!< PLLP division factor = 16 */ +#define RCC_PLLP_DIV17 0x00000011U /*!< PLLP division factor = 17 */ +#define RCC_PLLP_DIV18 0x00000012U /*!< PLLP division factor = 18 */ +#define RCC_PLLP_DIV19 0x00000013U /*!< PLLP division factor = 19 */ +#define RCC_PLLP_DIV20 0x00000014U /*!< PLLP division factor = 20 */ +#define RCC_PLLP_DIV21 0x00000015U /*!< PLLP division factor = 21 */ +#define RCC_PLLP_DIV22 0x00000016U /*!< PLLP division factor = 22 */ +#define RCC_PLLP_DIV23 0x00000017U /*!< PLLP division factor = 23 */ +#define RCC_PLLP_DIV24 0x00000018U /*!< PLLP division factor = 24 */ +#define RCC_PLLP_DIV25 0x00000019U /*!< PLLP division factor = 25 */ +#define RCC_PLLP_DIV26 0x0000001AU /*!< PLLP division factor = 26 */ +#define RCC_PLLP_DIV27 0x0000001BU /*!< PLLP division factor = 27 */ +#define RCC_PLLP_DIV28 0x0000001CU /*!< PLLP division factor = 28 */ +#define RCC_PLLP_DIV29 0x0000001DU /*!< PLLP division factor = 29 */ +#define RCC_PLLP_DIV30 0x0000001EU /*!< PLLP division factor = 30 */ +#define RCC_PLLP_DIV31 0x0000001FU /*!< PLLP division factor = 31 */ +#else +#define RCC_PLLP_DIV7 0x00000007U /*!< PLLP division factor = 7 */ +#define RCC_PLLP_DIV17 0x00000011U /*!< PLLP division factor = 17 */ +#endif /* RCC_PLLP_DIV_2_31_SUPPORT */ +/** + * @} + */ + +/** @defgroup RCC_PLLQ_Clock_Divider PLLQ Clock Divider + * @{ + */ +#define RCC_PLLQ_DIV2 0x00000002U /*!< PLLQ division factor = 2 */ +#define RCC_PLLQ_DIV4 0x00000004U /*!< PLLQ division factor = 4 */ +#define RCC_PLLQ_DIV6 0x00000006U /*!< PLLQ division factor = 6 */ +#define RCC_PLLQ_DIV8 0x00000008U /*!< PLLQ division factor = 8 */ +/** + * @} + */ + +/** @defgroup RCC_PLLR_Clock_Divider PLLR Clock Divider + * @{ + */ +#define RCC_PLLR_DIV2 0x00000002U /*!< PLLR division factor = 2 */ +#define RCC_PLLR_DIV4 0x00000004U /*!< PLLR division factor = 4 */ +#define RCC_PLLR_DIV6 0x00000006U /*!< PLLR division factor = 6 */ +#define RCC_PLLR_DIV8 0x00000008U /*!< PLLR division factor = 8 */ +/** + * @} + */ + +/** @defgroup RCC_PLL_Clock_Source PLL Clock Source + * @{ + */ +#define RCC_PLLSOURCE_NONE 0x00000000U /*!< No clock selected as PLL entry clock source */ +#define RCC_PLLSOURCE_MSI RCC_PLLCFGR_PLLSRC_MSI /*!< MSI clock selected as PLL entry clock source */ +#define RCC_PLLSOURCE_HSI RCC_PLLCFGR_PLLSRC_HSI /*!< HSI clock selected as PLL entry clock source */ +#define RCC_PLLSOURCE_HSE RCC_PLLCFGR_PLLSRC_HSE /*!< HSE clock selected as PLL entry clock source */ +/** + * @} + */ + +/** @defgroup RCC_PLL_Clock_Output PLL Clock Output + * @{ + */ +#if defined(RCC_PLLSAI2_SUPPORT) +#define RCC_PLL_SAI3CLK RCC_PLLCFGR_PLLPEN /*!< PLLSAI3CLK selection from main PLL (for devices with PLLSAI2) */ +#else +#define RCC_PLL_SAI2CLK RCC_PLLCFGR_PLLPEN /*!< PLLSAI2CLK selection from main PLL (for devices without PLLSAI2) */ +#endif /* RCC_PLLSAI2_SUPPORT */ +#define RCC_PLL_48M1CLK RCC_PLLCFGR_PLLQEN /*!< PLL48M1CLK selection from main PLL */ +#define RCC_PLL_SYSCLK RCC_PLLCFGR_PLLREN /*!< PLLCLK selection from main PLL */ +/** + * @} + */ + +/** @defgroup RCC_PLLSAI1_Clock_Output PLLSAI1 Clock Output + * @{ + */ +#define RCC_PLLSAI1_SAI1CLK RCC_PLLSAI1CFGR_PLLSAI1PEN /*!< PLLSAI1CLK selection from PLLSAI1 */ +#define RCC_PLLSAI1_48M2CLK RCC_PLLSAI1CFGR_PLLSAI1QEN /*!< PLL48M2CLK selection from PLLSAI1 */ +#define RCC_PLLSAI1_ADC1CLK RCC_PLLSAI1CFGR_PLLSAI1REN /*!< PLLADC1CLK selection from PLLSAI1 */ +/** + * @} + */ + +#if defined(RCC_PLLSAI2_SUPPORT) + +/** @defgroup RCC_PLLSAI2_Clock_Output PLLSAI2 Clock Output + * @{ + */ +#define RCC_PLLSAI2_SAI2CLK RCC_PLLSAI2CFGR_PLLSAI2PEN /*!< PLLSAI2CLK selection from PLLSAI2 */ +#if defined(RCC_PLLSAI2Q_DIV_SUPPORT) +#define RCC_PLLSAI2_DSICLK RCC_PLLSAI2CFGR_PLLSAI2QEN /*!< PLLDSICLK selection from PLLSAI2 */ +#endif /* RCC_PLLSAI2Q_DIV_SUPPORT */ +#if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || defined(STM32L496xx) || defined(STM32L4A6xx) +#define RCC_PLLSAI2_ADC2CLK RCC_PLLSAI2CFGR_PLLSAI2REN /*!< PLLADC2CLK selection from PLLSAI2 */ +#else +#define RCC_PLLSAI2_LTDCCLK RCC_PLLSAI2CFGR_PLLSAI2REN /*!< PLLLTDCCLK selection from PLLSAI2 */ +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || STM32L496xx || STM32L4A6xx */ +/** + * @} + */ + +#endif /* RCC_PLLSAI2_SUPPORT */ + +/** @defgroup RCC_MSI_Clock_Range MSI Clock Range + * @{ + */ +#define RCC_MSIRANGE_0 RCC_CR_MSIRANGE_0 /*!< MSI = 100 KHz */ +#define RCC_MSIRANGE_1 RCC_CR_MSIRANGE_1 /*!< MSI = 200 KHz */ +#define RCC_MSIRANGE_2 RCC_CR_MSIRANGE_2 /*!< MSI = 400 KHz */ +#define RCC_MSIRANGE_3 RCC_CR_MSIRANGE_3 /*!< MSI = 800 KHz */ +#define RCC_MSIRANGE_4 RCC_CR_MSIRANGE_4 /*!< MSI = 1 MHz */ +#define RCC_MSIRANGE_5 RCC_CR_MSIRANGE_5 /*!< MSI = 2 MHz */ +#define RCC_MSIRANGE_6 RCC_CR_MSIRANGE_6 /*!< MSI = 4 MHz */ +#define RCC_MSIRANGE_7 RCC_CR_MSIRANGE_7 /*!< MSI = 8 MHz */ +#define RCC_MSIRANGE_8 RCC_CR_MSIRANGE_8 /*!< MSI = 16 MHz */ +#define RCC_MSIRANGE_9 RCC_CR_MSIRANGE_9 /*!< MSI = 24 MHz */ +#define RCC_MSIRANGE_10 RCC_CR_MSIRANGE_10 /*!< MSI = 32 MHz */ +#define RCC_MSIRANGE_11 RCC_CR_MSIRANGE_11 /*!< MSI = 48 MHz */ +/** + * @} + */ + +/** @defgroup RCC_System_Clock_Type System Clock Type + * @{ + */ +#define RCC_CLOCKTYPE_SYSCLK 0x00000001U /*!< SYSCLK to configure */ +#define RCC_CLOCKTYPE_HCLK 0x00000002U /*!< HCLK to configure */ +#define RCC_CLOCKTYPE_PCLK1 0x00000004U /*!< PCLK1 to configure */ +#define RCC_CLOCKTYPE_PCLK2 0x00000008U /*!< PCLK2 to configure */ +/** + * @} + */ + +/** @defgroup RCC_System_Clock_Source System Clock Source + * @{ + */ +#define RCC_SYSCLKSOURCE_MSI RCC_CFGR_SW_MSI /*!< MSI selection as system clock */ +#define RCC_SYSCLKSOURCE_HSI RCC_CFGR_SW_HSI /*!< HSI selection as system clock */ +#define RCC_SYSCLKSOURCE_HSE RCC_CFGR_SW_HSE /*!< HSE selection as system clock */ +#define RCC_SYSCLKSOURCE_PLLCLK RCC_CFGR_SW_PLL /*!< PLL selection as system clock */ +/** + * @} + */ + +/** @defgroup RCC_System_Clock_Source_Status System Clock Source Status + * @{ + */ +#define RCC_SYSCLKSOURCE_STATUS_MSI RCC_CFGR_SWS_MSI /*!< MSI used as system clock */ +#define RCC_SYSCLKSOURCE_STATUS_HSI RCC_CFGR_SWS_HSI /*!< HSI used as system clock */ +#define RCC_SYSCLKSOURCE_STATUS_HSE RCC_CFGR_SWS_HSE /*!< HSE used as system clock */ +#define RCC_SYSCLKSOURCE_STATUS_PLLCLK RCC_CFGR_SWS_PLL /*!< PLL used as system clock */ +/** + * @} + */ + +/** @defgroup RCC_AHB_Clock_Source AHB Clock Source + * @{ + */ +#define RCC_SYSCLK_DIV1 RCC_CFGR_HPRE_DIV1 /*!< SYSCLK not divided */ +#define RCC_SYSCLK_DIV2 RCC_CFGR_HPRE_DIV2 /*!< SYSCLK divided by 2 */ +#define RCC_SYSCLK_DIV4 RCC_CFGR_HPRE_DIV4 /*!< SYSCLK divided by 4 */ +#define RCC_SYSCLK_DIV8 RCC_CFGR_HPRE_DIV8 /*!< SYSCLK divided by 8 */ +#define RCC_SYSCLK_DIV16 RCC_CFGR_HPRE_DIV16 /*!< SYSCLK divided by 16 */ +#define RCC_SYSCLK_DIV64 RCC_CFGR_HPRE_DIV64 /*!< SYSCLK divided by 64 */ +#define RCC_SYSCLK_DIV128 RCC_CFGR_HPRE_DIV128 /*!< SYSCLK divided by 128 */ +#define RCC_SYSCLK_DIV256 RCC_CFGR_HPRE_DIV256 /*!< SYSCLK divided by 256 */ +#define RCC_SYSCLK_DIV512 RCC_CFGR_HPRE_DIV512 /*!< SYSCLK divided by 512 */ +/** + * @} + */ + +/** @defgroup RCC_APB1_APB2_Clock_Source APB1 APB2 Clock Source + * @{ + */ +#define RCC_HCLK_DIV1 RCC_CFGR_PPRE1_DIV1 /*!< HCLK not divided */ +#define RCC_HCLK_DIV2 RCC_CFGR_PPRE1_DIV2 /*!< HCLK divided by 2 */ +#define RCC_HCLK_DIV4 RCC_CFGR_PPRE1_DIV4 /*!< HCLK divided by 4 */ +#define RCC_HCLK_DIV8 RCC_CFGR_PPRE1_DIV8 /*!< HCLK divided by 8 */ +#define RCC_HCLK_DIV16 RCC_CFGR_PPRE1_DIV16 /*!< HCLK divided by 16 */ +/** + * @} + */ + +/** @defgroup RCC_RTC_Clock_Source RTC Clock Source + * @{ + */ +#define RCC_RTCCLKSOURCE_NONE 0x00000000U /*!< No clock used as RTC clock */ +#define RCC_RTCCLKSOURCE_LSE RCC_BDCR_RTCSEL_0 /*!< LSE oscillator clock used as RTC clock */ +#define RCC_RTCCLKSOURCE_LSI RCC_BDCR_RTCSEL_1 /*!< LSI oscillator clock used as RTC clock */ +#define RCC_RTCCLKSOURCE_HSE_DIV32 RCC_BDCR_RTCSEL /*!< HSE oscillator clock divided by 32 used as RTC clock */ +/** + * @} + */ + +/** @defgroup RCC_MCO_Index MCO Index + * @{ + */ +#define RCC_MCO1 0x00000000U +#define RCC_MCO RCC_MCO1 /*!< MCO1 to be compliant with other families with 2 MCOs*/ +/** + * @} + */ + +/** @defgroup RCC_MCO1_Clock_Source MCO1 Clock Source + * @{ + */ +#define RCC_MCO1SOURCE_NOCLOCK 0x00000000U /*!< MCO1 output disabled, no clock on MCO1 */ +#define RCC_MCO1SOURCE_SYSCLK RCC_CFGR_MCOSEL_0 /*!< SYSCLK selection as MCO1 source */ +#define RCC_MCO1SOURCE_MSI RCC_CFGR_MCOSEL_1 /*!< MSI selection as MCO1 source */ +#define RCC_MCO1SOURCE_HSI (RCC_CFGR_MCOSEL_0| RCC_CFGR_MCOSEL_1) /*!< HSI selection as MCO1 source */ +#define RCC_MCO1SOURCE_HSE RCC_CFGR_MCOSEL_2 /*!< HSE selection as MCO1 source */ +#define RCC_MCO1SOURCE_PLLCLK (RCC_CFGR_MCOSEL_0|RCC_CFGR_MCOSEL_2) /*!< PLLCLK selection as MCO1 source */ +#define RCC_MCO1SOURCE_LSI (RCC_CFGR_MCOSEL_1|RCC_CFGR_MCOSEL_2) /*!< LSI selection as MCO1 source */ +#define RCC_MCO1SOURCE_LSE (RCC_CFGR_MCOSEL_0|RCC_CFGR_MCOSEL_1|RCC_CFGR_MCOSEL_2) /*!< LSE selection as MCO1 source */ +#if defined(RCC_HSI48_SUPPORT) +#define RCC_MCO1SOURCE_HSI48 RCC_CFGR_MCOSEL_3 /*!< HSI48 selection as MCO1 source (STM32L43x/STM32L44x devices) */ +#endif /* RCC_HSI48_SUPPORT */ +/** + * @} + */ + +/** @defgroup RCC_MCOx_Clock_Prescaler MCO1 Clock Prescaler + * @{ + */ +#define RCC_MCODIV_1 RCC_CFGR_MCOPRE_DIV1 /*!< MCO not divided */ +#define RCC_MCODIV_2 RCC_CFGR_MCOPRE_DIV2 /*!< MCO divided by 2 */ +#define RCC_MCODIV_4 RCC_CFGR_MCOPRE_DIV4 /*!< MCO divided by 4 */ +#define RCC_MCODIV_8 RCC_CFGR_MCOPRE_DIV8 /*!< MCO divided by 8 */ +#define RCC_MCODIV_16 RCC_CFGR_MCOPRE_DIV16 /*!< MCO divided by 16 */ +/** + * @} + */ + +/** @defgroup RCC_Interrupt Interrupts + * @{ + */ +#define RCC_IT_LSIRDY RCC_CIFR_LSIRDYF /*!< LSI Ready Interrupt flag */ +#define RCC_IT_LSERDY RCC_CIFR_LSERDYF /*!< LSE Ready Interrupt flag */ +#define RCC_IT_MSIRDY RCC_CIFR_MSIRDYF /*!< MSI Ready Interrupt flag */ +#define RCC_IT_HSIRDY RCC_CIFR_HSIRDYF /*!< HSI16 Ready Interrupt flag */ +#define RCC_IT_HSERDY RCC_CIFR_HSERDYF /*!< HSE Ready Interrupt flag */ +#define RCC_IT_PLLRDY RCC_CIFR_PLLRDYF /*!< PLL Ready Interrupt flag */ +#define RCC_IT_PLLSAI1RDY RCC_CIFR_PLLSAI1RDYF /*!< PLLSAI1 Ready Interrupt flag */ +#if defined(RCC_PLLSAI2_SUPPORT) +#define RCC_IT_PLLSAI2RDY RCC_CIFR_PLLSAI2RDYF /*!< PLLSAI2 Ready Interrupt flag */ +#endif /* RCC_PLLSAI2_SUPPORT */ +#define RCC_IT_CSS RCC_CIFR_CSSF /*!< Clock Security System Interrupt flag */ +#define RCC_IT_LSECSS RCC_CIFR_LSECSSF /*!< LSE Clock Security System Interrupt flag */ +#if defined(RCC_HSI48_SUPPORT) +#define RCC_IT_HSI48RDY RCC_CIFR_HSI48RDYF /*!< HSI48 Ready Interrupt flag */ +#endif /* RCC_HSI48_SUPPORT */ +/** + * @} + */ + +/** @defgroup RCC_Flag Flags + * Elements values convention: XXXYYYYYb + * - YYYYY : Flag position in the register + * - XXX : Register index + * - 001: CR register + * - 010: BDCR register + * - 011: CSR register + * - 100: CRRCR register + * @{ + */ +/* Flags in the CR register */ +#define RCC_FLAG_MSIRDY ((CR_REG_INDEX << 5U) | RCC_CR_MSIRDY_Pos) /*!< MSI Ready flag */ +#define RCC_FLAG_HSIRDY ((CR_REG_INDEX << 5U) | RCC_CR_HSIRDY_Pos) /*!< HSI Ready flag */ +#define RCC_FLAG_HSERDY ((CR_REG_INDEX << 5U) | RCC_CR_HSERDY_Pos) /*!< HSE Ready flag */ +#define RCC_FLAG_PLLRDY ((CR_REG_INDEX << 5U) | RCC_CR_PLLRDY_Pos) /*!< PLL Ready flag */ +#define RCC_FLAG_PLLSAI1RDY ((CR_REG_INDEX << 5U) | RCC_CR_PLLSAI1RDY_Pos) /*!< PLLSAI1 Ready flag */ +#if defined(RCC_PLLSAI2_SUPPORT) +#define RCC_FLAG_PLLSAI2RDY ((CR_REG_INDEX << 5U) | RCC_CR_PLLSAI2RDY_Pos) /*!< PLLSAI2 Ready flag */ +#endif /* RCC_PLLSAI2_SUPPORT */ + +/* Flags in the BDCR register */ +#define RCC_FLAG_LSERDY ((BDCR_REG_INDEX << 5U) | RCC_BDCR_LSERDY_Pos) /*!< LSE Ready flag */ +#define RCC_FLAG_LSECSSD ((BDCR_REG_INDEX << 5U) | RCC_BDCR_LSECSSD_Pos) /*!< LSE Clock Security System Interrupt flag */ + +/* Flags in the CSR register */ +#define RCC_FLAG_LSIRDY ((CSR_REG_INDEX << 5U) | RCC_CSR_LSIRDY_Pos) /*!< LSI Ready flag */ +#define RCC_FLAG_RMVF ((CSR_REG_INDEX << 5U) | RCC_CSR_RMVF_Pos) /*!< Remove reset flag */ +#define RCC_FLAG_FWRST ((CSR_REG_INDEX << 5U) | RCC_CSR_FWRSTF_Pos) /*!< Firewall reset flag */ +#define RCC_FLAG_OBLRST ((CSR_REG_INDEX << 5U) | RCC_CSR_OBLRSTF_Pos) /*!< Option Byte Loader reset flag */ +#define RCC_FLAG_PINRST ((CSR_REG_INDEX << 5U) | RCC_CSR_PINRSTF_Pos) /*!< PIN reset flag */ +#define RCC_FLAG_BORRST ((CSR_REG_INDEX << 5U) | RCC_CSR_BORRSTF_Pos) /*!< BOR reset flag */ +#define RCC_FLAG_SFTRST ((CSR_REG_INDEX << 5U) | RCC_CSR_SFTRSTF_Pos) /*!< Software Reset flag */ +#define RCC_FLAG_IWDGRST ((CSR_REG_INDEX << 5U) | RCC_CSR_IWDGRSTF_Pos) /*!< Independent Watchdog reset flag */ +#define RCC_FLAG_WWDGRST ((CSR_REG_INDEX << 5U) | RCC_CSR_WWDGRSTF_Pos) /*!< Window watchdog reset flag */ +#define RCC_FLAG_LPWRRST ((CSR_REG_INDEX << 5U) | RCC_CSR_LPWRRSTF_Pos) /*!< Low-Power reset flag */ + +#if defined(RCC_HSI48_SUPPORT) +/* Flags in the CRRCR register */ +#define RCC_FLAG_HSI48RDY ((CRRCR_REG_INDEX << 5U) | RCC_CRRCR_HSI48RDY_Pos) /*!< HSI48 Ready flag */ +#endif /* RCC_HSI48_SUPPORT */ +/** + * @} + */ + +/** @defgroup RCC_LSEDrive_Config LSE Drive Config + * @{ + */ +#define RCC_LSEDRIVE_LOW 0x00000000U /*!< LSE low drive capability */ +#define RCC_LSEDRIVE_MEDIUMLOW RCC_BDCR_LSEDRV_0 /*!< LSE medium low drive capability */ +#define RCC_LSEDRIVE_MEDIUMHIGH RCC_BDCR_LSEDRV_1 /*!< LSE medium high drive capability */ +#define RCC_LSEDRIVE_HIGH RCC_BDCR_LSEDRV /*!< LSE high drive capability */ +/** + * @} + */ + +/** @defgroup RCC_Stop_WakeUpClock Wake-Up from STOP Clock + * @{ + */ +#define RCC_STOP_WAKEUPCLOCK_MSI 0x00000000U /*!< MSI selection after wake-up from STOP */ +#define RCC_STOP_WAKEUPCLOCK_HSI RCC_CFGR_STOPWUCK /*!< HSI selection after wake-up from STOP */ +/** + * @} + */ + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ + +/** @defgroup RCC_Exported_Macros RCC Exported Macros + * @{ + */ + +/** @defgroup RCC_AHB1_Peripheral_Clock_Enable_Disable AHB1 Peripheral Clock Enable Disable + * @brief Enable or disable the AHB1 peripheral clock. + * @note After reset, the peripheral clock (used for registers read/write access) + * is disabled and the application software has to enable this clock before + * using it. + * @{ + */ + +#define __HAL_RCC_DMA1_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMA1EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMA1EN); \ + UNUSED(tmpreg); \ + } while(0) + +#define __HAL_RCC_DMA2_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMA2EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMA2EN); \ + UNUSED(tmpreg); \ + } while(0) + +#if defined(DMAMUX1) +#define __HAL_RCC_DMAMUX1_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMAMUX1EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMAMUX1EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* DMAMUX1 */ + +#define __HAL_RCC_FLASH_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_FLASHEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_FLASHEN); \ + UNUSED(tmpreg); \ + } while(0) + +#define __HAL_RCC_CRC_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_CRCEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_CRCEN); \ + UNUSED(tmpreg); \ + } while(0) + +#define __HAL_RCC_TSC_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_TSCEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_TSCEN); \ + UNUSED(tmpreg); \ + } while(0) + +#if defined(DMA2D) +#define __HAL_RCC_DMA2D_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMA2DEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMA2DEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* DMA2D */ + +#if defined(GFXMMU) +#define __HAL_RCC_GFXMMU_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GFXMMUEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GFXMMUEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* GFXMMU */ + + +#define __HAL_RCC_DMA1_CLK_DISABLE() CLEAR_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMA1EN) + +#define __HAL_RCC_DMA2_CLK_DISABLE() CLEAR_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMA2EN) + +#if defined(DMAMUX1) +#define __HAL_RCC_DMAMUX1_CLK_DISABLE() CLEAR_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMAMUX1EN) +#endif /* DMAMUX1 */ + +#define __HAL_RCC_FLASH_CLK_DISABLE() CLEAR_BIT(RCC->AHB1ENR, RCC_AHB1ENR_FLASHEN) + +#define __HAL_RCC_CRC_CLK_DISABLE() CLEAR_BIT(RCC->AHB1ENR, RCC_AHB1ENR_CRCEN) + +#define __HAL_RCC_TSC_CLK_DISABLE() CLEAR_BIT(RCC->AHB1ENR, RCC_AHB1ENR_TSCEN) + +#if defined(DMA2D) +#define __HAL_RCC_DMA2D_CLK_DISABLE() CLEAR_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMA2DEN) +#endif /* DMA2D */ + +#if defined(GFXMMU) +#define __HAL_RCC_GFXMMU_CLK_DISABLE() CLEAR_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GFXMMUEN) +#endif /* GFXMMU */ + +/** + * @} + */ + +/** @defgroup RCC_AHB2_Peripheral_Clock_Enable_Disable AHB2 Peripheral Clock Enable Disable + * @brief Enable or disable the AHB2 peripheral clock. + * @note After reset, the peripheral clock (used for registers read/write access) + * is disabled and the application software has to enable this clock before + * using it. + * @{ + */ + +#define __HAL_RCC_GPIOA_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOAEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOAEN); \ + UNUSED(tmpreg); \ + } while(0) + +#define __HAL_RCC_GPIOB_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOBEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOBEN); \ + UNUSED(tmpreg); \ + } while(0) + +#define __HAL_RCC_GPIOC_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOCEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOCEN); \ + UNUSED(tmpreg); \ + } while(0) + +#if defined(GPIOD) +#define __HAL_RCC_GPIOD_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIODEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIODEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* GPIOD */ + +#if defined(GPIOE) +#define __HAL_RCC_GPIOE_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOEEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOEEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* GPIOE */ + +#if defined(GPIOF) +#define __HAL_RCC_GPIOF_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOFEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOFEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* GPIOF */ + +#if defined(GPIOG) +#define __HAL_RCC_GPIOG_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOGEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOGEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* GPIOG */ + +#define __HAL_RCC_GPIOH_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOHEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOHEN); \ + UNUSED(tmpreg); \ + } while(0) + +#if defined(GPIOI) +#define __HAL_RCC_GPIOI_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOIEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOIEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* GPIOI */ + +#if defined(USB_OTG_FS) +#define __HAL_RCC_USB_OTG_FS_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_OTGFSEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_OTGFSEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* USB_OTG_FS */ + +#define __HAL_RCC_ADC_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_ADCEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_ADCEN); \ + UNUSED(tmpreg); \ + } while(0) + +#if defined(DCMI) +#define __HAL_RCC_DCMI_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_DCMIEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_DCMIEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* DCMI */ + +#if defined(AES) +#define __HAL_RCC_AES_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_AESEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_AESEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* AES */ + +#if defined(HASH) +#define __HAL_RCC_HASH_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_HASHEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_HASHEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* HASH */ + +#define __HAL_RCC_RNG_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_RNGEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_RNGEN); \ + UNUSED(tmpreg); \ + } while(0) + +#if defined(OCTOSPIM) +#define __HAL_RCC_OSPIM_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_OSPIMEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_OSPIMEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* OCTOSPIM */ + +#if defined(SDMMC1) && defined(RCC_AHB2ENR_SDMMC1EN) +#define __HAL_RCC_SDMMC1_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_SDMMC1EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_SDMMC1EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* SDMMC1 && RCC_AHB2ENR_SDMMC1EN */ + + +#define __HAL_RCC_GPIOA_CLK_DISABLE() CLEAR_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOAEN) + +#define __HAL_RCC_GPIOB_CLK_DISABLE() CLEAR_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOBEN) + +#define __HAL_RCC_GPIOC_CLK_DISABLE() CLEAR_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOCEN) + +#if defined(GPIOD) +#define __HAL_RCC_GPIOD_CLK_DISABLE() CLEAR_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIODEN) +#endif /* GPIOD */ + +#if defined(GPIOE) +#define __HAL_RCC_GPIOE_CLK_DISABLE() CLEAR_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOEEN) +#endif /* GPIOE */ + +#if defined(GPIOF) +#define __HAL_RCC_GPIOF_CLK_DISABLE() CLEAR_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOFEN) +#endif /* GPIOF */ + +#if defined(GPIOG) +#define __HAL_RCC_GPIOG_CLK_DISABLE() CLEAR_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOGEN) +#endif /* GPIOG */ + +#define __HAL_RCC_GPIOH_CLK_DISABLE() CLEAR_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOHEN) + +#if defined(GPIOI) +#define __HAL_RCC_GPIOI_CLK_DISABLE() CLEAR_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOIEN) +#endif /* GPIOI */ + +#if defined(USB_OTG_FS) +#define __HAL_RCC_USB_OTG_FS_CLK_DISABLE() CLEAR_BIT(RCC->AHB2ENR, RCC_AHB2ENR_OTGFSEN); +#endif /* USB_OTG_FS */ + +#define __HAL_RCC_ADC_CLK_DISABLE() CLEAR_BIT(RCC->AHB2ENR, RCC_AHB2ENR_ADCEN) + +#if defined(DCMI) +#define __HAL_RCC_DCMI_CLK_DISABLE() CLEAR_BIT(RCC->AHB2ENR, RCC_AHB2ENR_DCMIEN) +#endif /* DCMI */ + +#if defined(AES) +#define __HAL_RCC_AES_CLK_DISABLE() CLEAR_BIT(RCC->AHB2ENR, RCC_AHB2ENR_AESEN); +#endif /* AES */ + +#if defined(HASH) +#define __HAL_RCC_HASH_CLK_DISABLE() CLEAR_BIT(RCC->AHB2ENR, RCC_AHB2ENR_HASHEN) +#endif /* HASH */ + +#define __HAL_RCC_RNG_CLK_DISABLE() CLEAR_BIT(RCC->AHB2ENR, RCC_AHB2ENR_RNGEN) + +#if defined(OCTOSPIM) +#define __HAL_RCC_OSPIM_CLK_DISABLE() CLEAR_BIT(RCC->AHB2ENR, RCC_AHB2ENR_OSPIMEN) +#endif /* OCTOSPIM */ + +#if defined(SDMMC1) && defined(RCC_AHB2ENR_SDMMC1EN) +#define __HAL_RCC_SDMMC1_CLK_DISABLE() CLEAR_BIT(RCC->AHB2ENR, RCC_AHB2ENR_SDMMC1EN) +#endif /* SDMMC1 && RCC_AHB2ENR_SDMMC1EN */ + +/** + * @} + */ + +/** @defgroup RCC_AHB3_Clock_Enable_Disable AHB3 Peripheral Clock Enable Disable + * @brief Enable or disable the AHB3 peripheral clock. + * @note After reset, the peripheral clock (used for registers read/write access) + * is disabled and the application software has to enable this clock before + * using it. + * @{ + */ + +#if defined(FMC_BANK1) +#define __HAL_RCC_FMC_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* FMC_BANK1 */ + +#if defined(QUADSPI) +#define __HAL_RCC_QSPI_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB3ENR, RCC_AHB3ENR_QSPIEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_QSPIEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* QUADSPI */ + +#if defined(OCTOSPI1) +#define __HAL_RCC_OSPI1_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB3ENR, RCC_AHB3ENR_OSPI1EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_OSPI1EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* OCTOSPI1 */ + +#if defined(OCTOSPI2) +#define __HAL_RCC_OSPI2_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB3ENR, RCC_AHB3ENR_OSPI2EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_OSPI2EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* OCTOSPI2 */ + +#if defined(FMC_BANK1) +#define __HAL_RCC_FMC_CLK_DISABLE() CLEAR_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN) +#endif /* FMC_BANK1 */ + +#if defined(QUADSPI) +#define __HAL_RCC_QSPI_CLK_DISABLE() CLEAR_BIT(RCC->AHB3ENR, RCC_AHB3ENR_QSPIEN) +#endif /* QUADSPI */ + +#if defined(OCTOSPI1) +#define __HAL_RCC_OSPI1_CLK_DISABLE() CLEAR_BIT(RCC->AHB3ENR, RCC_AHB3ENR_OSPI1EN) +#endif /* OCTOSPI1 */ + +#if defined(OCTOSPI2) +#define __HAL_RCC_OSPI2_CLK_DISABLE() CLEAR_BIT(RCC->AHB3ENR, RCC_AHB3ENR_OSPI2EN) +#endif /* OCTOSPI2 */ + +/** + * @} + */ + +/** @defgroup RCC_APB1_Clock_Enable_Disable APB1 Peripheral Clock Enable Disable + * @brief Enable or disable the APB1 peripheral clock. + * @note After reset, the peripheral clock (used for registers read/write access) + * is disabled and the application software has to enable this clock before + * using it. + * @{ + */ + +#define __HAL_RCC_TIM2_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM2EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM2EN); \ + UNUSED(tmpreg); \ + } while(0) + +#if defined(TIM3) +#define __HAL_RCC_TIM3_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM3EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM3EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* TIM3 */ + +#if defined(TIM4) +#define __HAL_RCC_TIM4_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM4EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM4EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* TIM4 */ + +#if defined(TIM5) +#define __HAL_RCC_TIM5_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM5EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM5EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* TIM5 */ + +#define __HAL_RCC_TIM6_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM6EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM6EN); \ + UNUSED(tmpreg); \ + } while(0) + +#define __HAL_RCC_TIM7_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM7EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM7EN); \ + UNUSED(tmpreg); \ + } while(0) + +#if defined(LCD) +#define __HAL_RCC_LCD_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_LCDEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_LCDEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* LCD */ + +#if defined(RCC_APB1ENR1_RTCAPBEN) +#define __HAL_RCC_RTCAPB_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_RTCAPBEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_RTCAPBEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* RCC_APB1ENR1_RTCAPBEN */ + +#define __HAL_RCC_WWDG_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_WWDGEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_WWDGEN); \ + UNUSED(tmpreg); \ + } while(0) + +#if defined(SPI2) +#define __HAL_RCC_SPI2_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_SPI2EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_SPI2EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* SPI2 */ + +#define __HAL_RCC_SPI3_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_SPI3EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_SPI3EN); \ + UNUSED(tmpreg); \ + } while(0) + +#define __HAL_RCC_USART2_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USART2EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USART2EN); \ + UNUSED(tmpreg); \ + } while(0) + +#if defined(USART3) +#define __HAL_RCC_USART3_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USART3EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USART3EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* USART3 */ + +#if defined(UART4) +#define __HAL_RCC_UART4_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_UART4EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_UART4EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* UART4 */ + +#if defined(UART5) +#define __HAL_RCC_UART5_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_UART5EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_UART5EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* UART5 */ + +#define __HAL_RCC_I2C1_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_I2C1EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_I2C1EN); \ + UNUSED(tmpreg); \ + } while(0) + +#if defined(I2C2) +#define __HAL_RCC_I2C2_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_I2C2EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_I2C2EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* I2C2 */ + +#define __HAL_RCC_I2C3_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_I2C3EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_I2C3EN); \ + UNUSED(tmpreg); \ + } while(0) + +#if defined(I2C4) +#define __HAL_RCC_I2C4_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR2, RCC_APB1ENR2_I2C4EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR2, RCC_APB1ENR2_I2C4EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* I2C4 */ + +#if defined(CRS) +#define __HAL_RCC_CRS_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_CRSEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_CRSEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* CRS */ + +#define __HAL_RCC_CAN1_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_CAN1EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_CAN1EN); \ + UNUSED(tmpreg); \ + } while(0) + +#if defined(CAN2) +#define __HAL_RCC_CAN2_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_CAN2EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_CAN2EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* CAN2 */ + +#if defined(USB) +#define __HAL_RCC_USB_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USBFSEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USBFSEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* USB */ + +#define __HAL_RCC_PWR_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_PWREN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_PWREN); \ + UNUSED(tmpreg); \ + } while(0) + +#define __HAL_RCC_DAC1_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_DAC1EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_DAC1EN); \ + UNUSED(tmpreg); \ + } while(0) + +#define __HAL_RCC_OPAMP_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_OPAMPEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_OPAMPEN); \ + UNUSED(tmpreg); \ + } while(0) + +#define __HAL_RCC_LPTIM1_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_LPTIM1EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_LPTIM1EN); \ + UNUSED(tmpreg); \ + } while(0) + +#define __HAL_RCC_LPUART1_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR2, RCC_APB1ENR2_LPUART1EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR2, RCC_APB1ENR2_LPUART1EN); \ + UNUSED(tmpreg); \ + } while(0) + +#if defined(SWPMI1) +#define __HAL_RCC_SWPMI1_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR2, RCC_APB1ENR2_SWPMI1EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR2, RCC_APB1ENR2_SWPMI1EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* SWPMI1 */ + +#define __HAL_RCC_LPTIM2_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR2, RCC_APB1ENR2_LPTIM2EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR2, RCC_APB1ENR2_LPTIM2EN); \ + UNUSED(tmpreg); \ + } while(0) + + +#define __HAL_RCC_TIM2_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM2EN) + +#if defined(TIM3) +#define __HAL_RCC_TIM3_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM3EN) +#endif /* TIM3 */ + +#if defined(TIM4) +#define __HAL_RCC_TIM4_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM4EN) +#endif /* TIM4 */ + +#if defined(TIM5) +#define __HAL_RCC_TIM5_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM5EN) +#endif /* TIM5 */ + +#define __HAL_RCC_TIM6_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM6EN) + +#define __HAL_RCC_TIM7_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM7EN) + +#if defined(LCD) +#define __HAL_RCC_LCD_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_LCDEN); +#endif /* LCD */ + +#if defined(RCC_APB1ENR1_RTCAPBEN) +#define __HAL_RCC_RTCAPB_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_RTCAPBEN); +#endif /* RCC_APB1ENR1_RTCAPBEN */ + +#if defined(SPI2) +#define __HAL_RCC_SPI2_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_SPI2EN) +#endif /* SPI2 */ + +#define __HAL_RCC_SPI3_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_SPI3EN) + +#define __HAL_RCC_USART2_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USART2EN) + +#if defined(USART3) +#define __HAL_RCC_USART3_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USART3EN) +#endif /* USART3 */ + +#if defined(UART4) +#define __HAL_RCC_UART4_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_UART4EN) +#endif /* UART4 */ + +#if defined(UART5) +#define __HAL_RCC_UART5_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_UART5EN) +#endif /* UART5 */ + +#define __HAL_RCC_I2C1_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_I2C1EN) + +#if defined(I2C2) +#define __HAL_RCC_I2C2_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_I2C2EN) +#endif /* I2C2 */ + +#define __HAL_RCC_I2C3_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_I2C3EN) + +#if defined(I2C4) +#define __HAL_RCC_I2C4_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR2, RCC_APB1ENR2_I2C4EN) +#endif /* I2C4 */ + +#if defined(CRS) +#define __HAL_RCC_CRS_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_CRSEN); +#endif /* CRS */ + +#define __HAL_RCC_CAN1_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_CAN1EN) + +#if defined(CAN2) +#define __HAL_RCC_CAN2_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_CAN2EN) +#endif /* CAN2 */ + +#if defined(USB) +#define __HAL_RCC_USB_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USBFSEN); +#endif /* USB */ + +#define __HAL_RCC_PWR_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_PWREN) + +#define __HAL_RCC_DAC1_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_DAC1EN) + +#define __HAL_RCC_OPAMP_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_OPAMPEN) + +#define __HAL_RCC_LPTIM1_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_LPTIM1EN) + +#define __HAL_RCC_LPUART1_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR2, RCC_APB1ENR2_LPUART1EN) + +#if defined(SWPMI1) +#define __HAL_RCC_SWPMI1_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR2, RCC_APB1ENR2_SWPMI1EN) +#endif /* SWPMI1 */ + +#define __HAL_RCC_LPTIM2_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR2, RCC_APB1ENR2_LPTIM2EN) + +/** + * @} + */ + +/** @defgroup RCC_APB2_Clock_Enable_Disable APB2 Peripheral Clock Enable Disable + * @brief Enable or disable the APB2 peripheral clock. + * @note After reset, the peripheral clock (used for registers read/write access) + * is disabled and the application software has to enable this clock before + * using it. + * @{ + */ + +#define __HAL_RCC_SYSCFG_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_SYSCFGEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_SYSCFGEN); \ + UNUSED(tmpreg); \ + } while(0) + +#define __HAL_RCC_FIREWALL_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_FWEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_FWEN); \ + UNUSED(tmpreg); \ + } while(0) + +#if defined(SDMMC1) && defined(RCC_APB2ENR_SDMMC1EN) +#define __HAL_RCC_SDMMC1_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_SDMMC1EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_SDMMC1EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* SDMMC1 && RCC_APB2ENR_SDMMC1EN */ + +#define __HAL_RCC_TIM1_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM1EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM1EN); \ + UNUSED(tmpreg); \ + } while(0) + +#define __HAL_RCC_SPI1_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_SPI1EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_SPI1EN); \ + UNUSED(tmpreg); \ + } while(0) + +#if defined(TIM8) +#define __HAL_RCC_TIM8_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM8EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM8EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* TIM8 */ + +#define __HAL_RCC_USART1_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_USART1EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_USART1EN); \ + UNUSED(tmpreg); \ + } while(0) + + +#define __HAL_RCC_TIM15_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM15EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM15EN); \ + UNUSED(tmpreg); \ + } while(0) + +#define __HAL_RCC_TIM16_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM16EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM16EN); \ + UNUSED(tmpreg); \ + } while(0) + +#if defined(TIM17) +#define __HAL_RCC_TIM17_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM17EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM17EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* TIM17 */ + +#define __HAL_RCC_SAI1_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_SAI1EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_SAI1EN); \ + UNUSED(tmpreg); \ + } while(0) + +#if defined(SAI2) +#define __HAL_RCC_SAI2_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_SAI2EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_SAI2EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* SAI2 */ + +#if defined(DFSDM1_Filter0) +#define __HAL_RCC_DFSDM1_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_DFSDM1EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_DFSDM1EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* DFSDM1_Filter0 */ + +#if defined(LTDC) +#define __HAL_RCC_LTDC_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_LTDCEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_LTDCEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* LTDC */ + +#if defined(DSI) +#define __HAL_RCC_DSI_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_DSIEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_DSIEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* DSI */ + + +#define __HAL_RCC_SYSCFG_CLK_DISABLE() CLEAR_BIT(RCC->APB2ENR, RCC_APB2ENR_SYSCFGEN) + +#if defined(SDMMC1) && defined(RCC_APB2ENR_SDMMC1EN) +#define __HAL_RCC_SDMMC1_CLK_DISABLE() CLEAR_BIT(RCC->APB2ENR, RCC_APB2ENR_SDMMC1EN) +#endif /* SDMMC1 && RCC_APB2ENR_SDMMC1EN */ + +#define __HAL_RCC_TIM1_CLK_DISABLE() CLEAR_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM1EN) + +#define __HAL_RCC_SPI1_CLK_DISABLE() CLEAR_BIT(RCC->APB2ENR, RCC_APB2ENR_SPI1EN) + +#if defined(TIM8) +#define __HAL_RCC_TIM8_CLK_DISABLE() CLEAR_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM8EN) +#endif /* TIM8 */ + +#define __HAL_RCC_USART1_CLK_DISABLE() CLEAR_BIT(RCC->APB2ENR, RCC_APB2ENR_USART1EN) + +#define __HAL_RCC_TIM15_CLK_DISABLE() CLEAR_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM15EN) + +#define __HAL_RCC_TIM16_CLK_DISABLE() CLEAR_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM16EN) + +#if defined(TIM17) +#define __HAL_RCC_TIM17_CLK_DISABLE() CLEAR_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM17EN) +#endif /* TIM17 */ + +#define __HAL_RCC_SAI1_CLK_DISABLE() CLEAR_BIT(RCC->APB2ENR, RCC_APB2ENR_SAI1EN) + +#if defined(SAI2) +#define __HAL_RCC_SAI2_CLK_DISABLE() CLEAR_BIT(RCC->APB2ENR, RCC_APB2ENR_SAI2EN) +#endif /* SAI2 */ + +#if defined(DFSDM1_Filter0) +#define __HAL_RCC_DFSDM1_CLK_DISABLE() CLEAR_BIT(RCC->APB2ENR, RCC_APB2ENR_DFSDM1EN) +#endif /* DFSDM1_Filter0 */ + +#if defined(LTDC) +#define __HAL_RCC_LTDC_CLK_DISABLE() CLEAR_BIT(RCC->APB2ENR, RCC_APB2ENR_LTDCEN) +#endif /* LTDC */ + +#if defined(DSI) +#define __HAL_RCC_DSI_CLK_DISABLE() CLEAR_BIT(RCC->APB2ENR, RCC_APB2ENR_DSIEN) +#endif /* DSI */ + +/** + * @} + */ + +/** @defgroup RCC_AHB1_Peripheral_Clock_Enable_Disable_Status AHB1 Peripheral Clock Enabled or Disabled Status + * @brief Check whether the AHB1 peripheral clock is enabled or not. + * @note After reset, the peripheral clock (used for registers read/write access) + * is disabled and the application software has to enable this clock before + * using it. + * @{ + */ + +#define __HAL_RCC_DMA1_IS_CLK_ENABLED() (READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMA1EN) != RESET) + +#define __HAL_RCC_DMA2_IS_CLK_ENABLED() (READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMA2EN) != RESET) + +#if defined(DMAMUX1) +#define __HAL_RCC_DMAMUX1_IS_CLK_ENABLED() (READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMAMUX1EN) != RESET) +#endif /* DMAMUX1 */ + +#define __HAL_RCC_FLASH_IS_CLK_ENABLED() (READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_FLASHEN) != RESET) + +#define __HAL_RCC_CRC_IS_CLK_ENABLED() (READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_CRCEN) != RESET) + +#define __HAL_RCC_TSC_IS_CLK_ENABLED() (READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_TSCEN) != RESET) + +#if defined(DMA2D) +#define __HAL_RCC_DMA2D_IS_CLK_ENABLED() (READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMA2DEN) != RESET) +#endif /* DMA2D */ + +#if defined(GFXMMU) +#define __HAL_RCC_GFXMMU_IS_CLK_ENABLED() (READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GFXMMUEN) != RESET) +#endif /* GFXMMU */ + + +#define __HAL_RCC_DMA1_IS_CLK_DISABLED() (READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMA1EN) == RESET) + +#define __HAL_RCC_DMA2_IS_CLK_DISABLED() (READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMA2EN) == RESET) + +#if defined(DMAMUX1) +#define __HAL_RCC_DMAMUX1_IS_CLK_DISABLED() (READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMAMUX1EN) == RESET) +#endif /* DMAMUX1 */ + +#define __HAL_RCC_FLASH_IS_CLK_DISABLED() (READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_FLASHEN) == RESET) + +#define __HAL_RCC_CRC_IS_CLK_DISABLED() (READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_CRCEN) == RESET) + +#define __HAL_RCC_TSC_IS_CLK_DISABLED() (READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_TSCEN) == RESET) + +#if defined(DMA2D) +#define __HAL_RCC_DMA2D_IS_CLK_DISABLED() (READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMA2DEN) == RESET) +#endif /* DMA2D */ + +#if defined(GFXMMU) +#define __HAL_RCC_GFXMMU_IS_CLK_DISABLED() (READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GFXMMUEN) == RESET) +#endif /* GFXMMU */ + +/** + * @} + */ + +/** @defgroup RCC_AHB2_Clock_Enable_Disable_Status AHB2 Peripheral Clock Enabled or Disabled Status + * @brief Check whether the AHB2 peripheral clock is enabled or not. + * @note After reset, the peripheral clock (used for registers read/write access) + * is disabled and the application software has to enable this clock before + * using it. + * @{ + */ + +#define __HAL_RCC_GPIOA_IS_CLK_ENABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOAEN) != RESET) + +#define __HAL_RCC_GPIOB_IS_CLK_ENABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOBEN) != RESET) + +#define __HAL_RCC_GPIOC_IS_CLK_ENABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOCEN) != RESET) + +#if defined(GPIOD) +#define __HAL_RCC_GPIOD_IS_CLK_ENABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIODEN) != RESET) +#endif /* GPIOD */ + +#if defined(GPIOE) +#define __HAL_RCC_GPIOE_IS_CLK_ENABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOEEN) != RESET) +#endif /* GPIOE */ + +#if defined(GPIOF) +#define __HAL_RCC_GPIOF_IS_CLK_ENABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOFEN) != RESET) +#endif /* GPIOF */ + +#if defined(GPIOG) +#define __HAL_RCC_GPIOG_IS_CLK_ENABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOGEN) != RESET) +#endif /* GPIOG */ + +#define __HAL_RCC_GPIOH_IS_CLK_ENABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOHEN) != RESET) + +#if defined(GPIOI) +#define __HAL_RCC_GPIOI_IS_CLK_ENABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOIEN) != RESET) +#endif /* GPIOI */ + +#if defined(USB_OTG_FS) +#define __HAL_RCC_USB_OTG_FS_IS_CLK_ENABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_OTGFSEN) != RESET) +#endif /* USB_OTG_FS */ + +#define __HAL_RCC_ADC_IS_CLK_ENABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_ADCEN) != RESET) + +#if defined(DCMI) +#define __HAL_RCC_DCMI_IS_CLK_ENABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_DCMIEN) != RESET) +#endif /* DCMI */ + +#if defined(AES) +#define __HAL_RCC_AES_IS_CLK_ENABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_AESEN) != RESET) +#endif /* AES */ + +#if defined(HASH) +#define __HAL_RCC_HASH_IS_CLK_ENABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_HASHEN) != RESET) +#endif /* HASH */ + +#define __HAL_RCC_RNG_IS_CLK_ENABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_RNGEN) != RESET) + + +#define __HAL_RCC_GPIOA_IS_CLK_DISABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOAEN) == RESET) + +#define __HAL_RCC_GPIOB_IS_CLK_DISABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOBEN) == RESET) + +#define __HAL_RCC_GPIOC_IS_CLK_DISABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOCEN) == RESET) + +#if defined(GPIOD) +#define __HAL_RCC_GPIOD_IS_CLK_DISABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIODEN) == RESET) +#endif /* GPIOD */ + +#if defined(GPIOE) +#define __HAL_RCC_GPIOE_IS_CLK_DISABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOEEN) == RESET) +#endif /* GPIOE */ + +#if defined(GPIOF) +#define __HAL_RCC_GPIOF_IS_CLK_DISABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOFEN) == RESET) +#endif /* GPIOF */ + +#if defined(GPIOG) +#define __HAL_RCC_GPIOG_IS_CLK_DISABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOGEN) == RESET) +#endif /* GPIOG */ + +#define __HAL_RCC_GPIOH_IS_CLK_DISABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOHEN) == RESET) + +#if defined(GPIOI) +#define __HAL_RCC_GPIOI_IS_CLK_DISABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOIEN) == RESET) +#endif /* GPIOI */ + +#if defined(USB_OTG_FS) +#define __HAL_RCC_USB_OTG_FS_IS_CLK_DISABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_OTGFSEN) == RESET) +#endif /* USB_OTG_FS */ + +#define __HAL_RCC_ADC_IS_CLK_DISABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_ADCEN) == RESET) + +#if defined(DCMI) +#define __HAL_RCC_DCMI_IS_CLK_DISABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_DCMIEN) == RESET) +#endif /* DCMI */ + +#if defined(AES) +#define __HAL_RCC_AES_IS_CLK_DISABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_AESEN) == RESET) +#endif /* AES */ + +#if defined(HASH) +#define __HAL_RCC_HASH_IS_CLK_DISABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_HASHEN) == RESET) +#endif /* HASH */ + +#define __HAL_RCC_RNG_IS_CLK_DISABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_RNGEN) == RESET) + +/** + * @} + */ + +/** @defgroup RCC_AHB3_Clock_Enable_Disable_Status AHB3 Peripheral Clock Enabled or Disabled Status + * @brief Check whether the AHB3 peripheral clock is enabled or not. + * @note After reset, the peripheral clock (used for registers read/write access) + * is disabled and the application software has to enable this clock before + * using it. + * @{ + */ + +#if defined(FMC_BANK1) +#define __HAL_RCC_FMC_IS_CLK_ENABLED() (READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN) != RESET) +#endif /* FMC_BANK1 */ + +#if defined(QUADSPI) +#define __HAL_RCC_QSPI_IS_CLK_ENABLED() (READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_QSPIEN) != RESET) +#endif /* QUADSPI */ + +#if defined(FMC_BANK1) +#define __HAL_RCC_FMC_IS_CLK_DISABLED() (READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN) == RESET) +#endif /* FMC_BANK1 */ + +#if defined(QUADSPI) +#define __HAL_RCC_QSPI_IS_CLK_DISABLED() (READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_QSPIEN) == RESET) +#endif /* QUADSPI */ + +/** + * @} + */ + +/** @defgroup RCC_APB1_Clock_Enable_Disable_Status APB1 Peripheral Clock Enabled or Disabled Status + * @brief Check whether the APB1 peripheral clock is enabled or not. + * @note After reset, the peripheral clock (used for registers read/write access) + * is disabled and the application software has to enable this clock before + * using it. + * @{ + */ + +#define __HAL_RCC_TIM2_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM2EN) != RESET) + +#if defined(TIM3) +#define __HAL_RCC_TIM3_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM3EN) != RESET) +#endif /* TIM3 */ + +#if defined(TIM4) +#define __HAL_RCC_TIM4_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM4EN) != RESET) +#endif /* TIM4 */ + +#if defined(TIM5) +#define __HAL_RCC_TIM5_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM5EN) != RESET) +#endif /* TIM5 */ + +#define __HAL_RCC_TIM6_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM6EN) != RESET) + +#define __HAL_RCC_TIM7_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM7EN) != RESET) + +#if defined(LCD) +#define __HAL_RCC_LCD_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_LCDEN) != RESET) +#endif /* LCD */ + +#if defined(RCC_APB1ENR1_RTCAPBEN) +#define __HAL_RCC_RTCAPB_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_RTCAPBEN) != RESET) +#endif /* RCC_APB1ENR1_RTCAPBEN */ + +#define __HAL_RCC_WWDG_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_WWDGEN) != RESET) + +#if defined(SPI2) +#define __HAL_RCC_SPI2_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_SPI2EN) != RESET) +#endif /* SPI2 */ + +#define __HAL_RCC_SPI3_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_SPI3EN) != RESET) + +#define __HAL_RCC_USART2_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USART2EN) != RESET) + +#if defined(USART3) +#define __HAL_RCC_USART3_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USART3EN) != RESET) +#endif /* USART3 */ + +#if defined(UART4) +#define __HAL_RCC_UART4_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_UART4EN) != RESET) +#endif /* UART4 */ + +#if defined(UART5) +#define __HAL_RCC_UART5_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_UART5EN) != RESET) +#endif /* UART5 */ + +#define __HAL_RCC_I2C1_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_I2C1EN) != RESET) + +#if defined(I2C2) +#define __HAL_RCC_I2C2_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_I2C2EN) != RESET) +#endif /* I2C2 */ + +#define __HAL_RCC_I2C3_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_I2C3EN) != RESET) + +#if defined(I2C4) +#define __HAL_RCC_I2C4_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR2, RCC_APB1ENR2_I2C4EN) != RESET) +#endif /* I2C4 */ + +#if defined(CRS) +#define __HAL_RCC_CRS_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_CRSEN) != RESET) +#endif /* CRS */ + +#define __HAL_RCC_CAN1_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_CAN1EN) != RESET) + +#if defined(CAN2) +#define __HAL_RCC_CAN2_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_CAN2EN) != RESET) +#endif /* CAN2 */ + +#if defined(USB) +#define __HAL_RCC_USB_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USBFSEN) != RESET) +#endif /* USB */ + +#define __HAL_RCC_PWR_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_PWREN) != RESET) + +#define __HAL_RCC_DAC1_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_DAC1EN) != RESET) + +#define __HAL_RCC_OPAMP_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_OPAMPEN) != RESET) + +#define __HAL_RCC_LPTIM1_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_LPTIM1EN) != RESET) + +#define __HAL_RCC_LPUART1_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR2, RCC_APB1ENR2_LPUART1EN) != RESET) + +#if defined(SWPMI1) +#define __HAL_RCC_SWPMI1_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR2, RCC_APB1ENR2_SWPMI1EN) != RESET) +#endif /* SWPMI1 */ + +#define __HAL_RCC_LPTIM2_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR2, RCC_APB1ENR2_LPTIM2EN) != RESET) + + +#define __HAL_RCC_TIM2_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM2EN) == RESET) + +#if defined(TIM3) +#define __HAL_RCC_TIM3_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM3EN) == RESET) +#endif /* TIM3 */ + +#if defined(TIM4) +#define __HAL_RCC_TIM4_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM4EN) == RESET) +#endif /* TIM4 */ + +#if defined(TIM5) +#define __HAL_RCC_TIM5_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM5EN) == RESET) +#endif /* TIM5 */ + +#define __HAL_RCC_TIM6_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM6EN) == RESET) + +#define __HAL_RCC_TIM7_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM7EN) == RESET) + +#if defined(LCD) +#define __HAL_RCC_LCD_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_LCDEN) == RESET) +#endif /* LCD */ + +#if defined(RCC_APB1ENR1_RTCAPBEN) +#define __HAL_RCC_RTCAPB_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_RTCAPBEN) == RESET) +#endif /* RCC_APB1ENR1_RTCAPBEN */ + +#define __HAL_RCC_WWDG_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_WWDGEN) == RESET) + +#if defined(SPI2) +#define __HAL_RCC_SPI2_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_SPI2EN) == RESET) +#endif /* SPI2 */ + +#define __HAL_RCC_SPI3_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_SPI3EN) == RESET) + +#define __HAL_RCC_USART2_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USART2EN) == RESET) + +#if defined(USART3) +#define __HAL_RCC_USART3_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USART3EN) == RESET) +#endif /* USART3 */ + +#if defined(UART4) +#define __HAL_RCC_UART4_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_UART4EN) == RESET) +#endif /* UART4 */ + +#if defined(UART5) +#define __HAL_RCC_UART5_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_UART5EN) == RESET) +#endif /* UART5 */ + +#define __HAL_RCC_I2C1_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_I2C1EN) == RESET) + +#if defined(I2C2) +#define __HAL_RCC_I2C2_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_I2C2EN) == RESET) +#endif /* I2C2 */ + +#define __HAL_RCC_I2C3_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_I2C3EN) == RESET) + +#if defined(I2C4) +#define __HAL_RCC_I2C4_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR2, RCC_APB1ENR2_I2C4EN) == RESET) +#endif /* I2C4 */ + +#if defined(CRS) +#define __HAL_RCC_CRS_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_CRSEN) == RESET) +#endif /* CRS */ + +#define __HAL_RCC_CAN1_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_CAN1EN) == RESET) + +#if defined(CAN2) +#define __HAL_RCC_CAN2_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_CAN2EN) == RESET) +#endif /* CAN2 */ + +#if defined(USB) +#define __HAL_RCC_USB_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USBFSEN) == RESET) +#endif /* USB */ + +#define __HAL_RCC_PWR_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_PWREN) == RESET) + +#define __HAL_RCC_DAC1_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_DAC1EN) == RESET) + +#define __HAL_RCC_OPAMP_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_OPAMPEN) == RESET) + +#define __HAL_RCC_LPTIM1_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_LPTIM1EN) == RESET) + +#define __HAL_RCC_LPUART1_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR2, RCC_APB1ENR2_LPUART1EN) == RESET) + +#if defined(SWPMI1) +#define __HAL_RCC_SWPMI1_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR2, RCC_APB1ENR2_SWPMI1EN) == RESET) +#endif /* SWPMI1 */ + +#define __HAL_RCC_LPTIM2_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR2, RCC_APB1ENR2_LPTIM2EN) == RESET) + +/** + * @} + */ + +/** @defgroup RCC_APB2_Clock_Enable_Disable_Status APB2 Peripheral Clock Enabled or Disabled Status + * @brief Check whether the APB2 peripheral clock is enabled or not. + * @note After reset, the peripheral clock (used for registers read/write access) + * is disabled and the application software has to enable this clock before + * using it. + * @{ + */ + +#define __HAL_RCC_SYSCFG_IS_CLK_ENABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_SYSCFGEN) != RESET) + +#define __HAL_RCC_FIREWALL_IS_CLK_ENABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_FWEN) != RESET) + +#if defined(SDMMC1) && defined(RCC_APB2ENR_SDMMC1EN) +#define __HAL_RCC_SDMMC1_IS_CLK_ENABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_SDMMC1EN) != RESET) +#endif /* SDMMC1 && RCC_APB2ENR_SDMMC1EN */ + +#define __HAL_RCC_TIM1_IS_CLK_ENABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM1EN) != RESET) + +#define __HAL_RCC_SPI1_IS_CLK_ENABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_SPI1EN) != RESET) + +#if defined(TIM8) +#define __HAL_RCC_TIM8_IS_CLK_ENABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM8EN) != RESET) +#endif /* TIM8 */ + +#define __HAL_RCC_USART1_IS_CLK_ENABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_USART1EN) != RESET) + +#define __HAL_RCC_TIM15_IS_CLK_ENABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM15EN) != RESET) + +#define __HAL_RCC_TIM16_IS_CLK_ENABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM16EN) != RESET) + +#if defined(TIM17) +#define __HAL_RCC_TIM17_IS_CLK_ENABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM17EN) != RESET) +#endif /* TIM17 */ + +#define __HAL_RCC_SAI1_IS_CLK_ENABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_SAI1EN) != RESET) + +#if defined(SAI2) +#define __HAL_RCC_SAI2_IS_CLK_ENABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_SAI2EN) != RESET) +#endif /* SAI2 */ + +#if defined(DFSDM1_Filter0) +#define __HAL_RCC_DFSDM1_IS_CLK_ENABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_DFSDM1EN) != RESET) +#endif /* DFSDM1_Filter0 */ + +#if defined(LTDC) +#define __HAL_RCC_LTDC_IS_CLK_ENABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_LTDCEN) != RESET) +#endif /* LTDC */ + +#if defined(DSI) +#define __HAL_RCC_DSI_IS_CLK_ENABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_DSIEN) != RESET) +#endif /* DSI */ + + +#define __HAL_RCC_SYSCFG_IS_CLK_DISABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_SYSCFGEN) == RESET) + +#if defined(SDMMC1) && defined(RCC_APB2ENR_SDMMC1EN) +#define __HAL_RCC_SDMMC1_IS_CLK_DISABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_SDMMC1EN) == RESET) +#endif /* SDMMC1 && RCC_APB2ENR_SDMMC1EN */ + +#define __HAL_RCC_TIM1_IS_CLK_DISABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM1EN) == RESET) + +#define __HAL_RCC_SPI1_IS_CLK_DISABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_SPI1EN) == RESET) + +#if defined(TIM8) +#define __HAL_RCC_TIM8_IS_CLK_DISABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM8EN) == RESET) +#endif /* TIM8 */ + +#define __HAL_RCC_USART1_IS_CLK_DISABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_USART1EN) == RESET) + +#define __HAL_RCC_TIM15_IS_CLK_DISABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM15EN) == RESET) + +#define __HAL_RCC_TIM16_IS_CLK_DISABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM16EN) == RESET) + +#if defined(TIM17) +#define __HAL_RCC_TIM17_IS_CLK_DISABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM17EN) == RESET) +#endif /* TIM17 */ + +#define __HAL_RCC_SAI1_IS_CLK_DISABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_SAI1EN) == RESET) + +#if defined(SAI2) +#define __HAL_RCC_SAI2_IS_CLK_DISABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_SAI2EN) == RESET) +#endif /* SAI2 */ + +#if defined(DFSDM1_Filter0) +#define __HAL_RCC_DFSDM1_IS_CLK_DISABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_DFSDM1EN) == RESET) +#endif /* DFSDM1_Filter0 */ + +#if defined(LTDC) +#define __HAL_RCC_LTDC_IS_CLK_DISABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_LTDCEN) == RESET) +#endif /* LTDC */ + +#if defined(DSI) +#define __HAL_RCC_DSI_IS_CLK_DISABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_DSIEN) == RESET) +#endif /* DSI */ + +/** + * @} + */ + +/** @defgroup RCC_AHB1_Force_Release_Reset AHB1 Peripheral Force Release Reset + * @brief Force or release AHB1 peripheral reset. + * @{ + */ +#define __HAL_RCC_AHB1_FORCE_RESET() WRITE_REG(RCC->AHB1RSTR, 0xFFFFFFFFU) + +#define __HAL_RCC_DMA1_FORCE_RESET() SET_BIT(RCC->AHB1RSTR, RCC_AHB1RSTR_DMA1RST) + +#define __HAL_RCC_DMA2_FORCE_RESET() SET_BIT(RCC->AHB1RSTR, RCC_AHB1RSTR_DMA2RST) + +#if defined(DMAMUX1) +#define __HAL_RCC_DMAMUX1_FORCE_RESET() SET_BIT(RCC->AHB1RSTR, RCC_AHB1RSTR_DMAMUX1RST) +#endif /* DMAMUX1 */ + +#define __HAL_RCC_FLASH_FORCE_RESET() SET_BIT(RCC->AHB1RSTR, RCC_AHB1RSTR_FLASHRST) + +#define __HAL_RCC_CRC_FORCE_RESET() SET_BIT(RCC->AHB1RSTR, RCC_AHB1RSTR_CRCRST) + +#define __HAL_RCC_TSC_FORCE_RESET() SET_BIT(RCC->AHB1RSTR, RCC_AHB1RSTR_TSCRST) + +#if defined(DMA2D) +#define __HAL_RCC_DMA2D_FORCE_RESET() SET_BIT(RCC->AHB1RSTR, RCC_AHB1RSTR_DMA2DRST) +#endif /* DMA2D */ + +#if defined(GFXMMU) +#define __HAL_RCC_GFXMMU_FORCE_RESET() SET_BIT(RCC->AHB1RSTR, RCC_AHB1RSTR_GFXMMURST) +#endif /* GFXMMU */ + + +#define __HAL_RCC_AHB1_RELEASE_RESET() WRITE_REG(RCC->AHB1RSTR, 0x00000000U) + +#define __HAL_RCC_DMA1_RELEASE_RESET() CLEAR_BIT(RCC->AHB1RSTR, RCC_AHB1RSTR_DMA1RST) + +#define __HAL_RCC_DMA2_RELEASE_RESET() CLEAR_BIT(RCC->AHB1RSTR, RCC_AHB1RSTR_DMA2RST) + +#if defined(DMAMUX1) +#define __HAL_RCC_DMAMUX1_RELEASE_RESET() CLEAR_BIT(RCC->AHB1RSTR, RCC_AHB1RSTR_DMAMUX1RST) +#endif /* DMAMUX1 */ + +#define __HAL_RCC_FLASH_RELEASE_RESET() CLEAR_BIT(RCC->AHB1RSTR, RCC_AHB1RSTR_FLASHRST) + +#define __HAL_RCC_CRC_RELEASE_RESET() CLEAR_BIT(RCC->AHB1RSTR, RCC_AHB1RSTR_CRCRST) + +#define __HAL_RCC_TSC_RELEASE_RESET() CLEAR_BIT(RCC->AHB1RSTR, RCC_AHB1RSTR_TSCRST) + +#if defined(DMA2D) +#define __HAL_RCC_DMA2D_RELEASE_RESET() CLEAR_BIT(RCC->AHB1RSTR, RCC_AHB1RSTR_DMA2DRST) +#endif /* DMA2D */ + +#if defined(GFXMMU) +#define __HAL_RCC_GFXMMU_RELEASE_RESET() CLEAR_BIT(RCC->AHB1RSTR, RCC_AHB1RSTR_GFXMMURST) +#endif /* GFXMMU */ + +/** + * @} + */ + +/** @defgroup RCC_AHB2_Force_Release_Reset AHB2 Peripheral Force Release Reset + * @brief Force or release AHB2 peripheral reset. + * @{ + */ +#define __HAL_RCC_AHB2_FORCE_RESET() WRITE_REG(RCC->AHB2RSTR, 0xFFFFFFFFU) + +#define __HAL_RCC_GPIOA_FORCE_RESET() SET_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_GPIOARST) + +#define __HAL_RCC_GPIOB_FORCE_RESET() SET_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_GPIOBRST) + +#define __HAL_RCC_GPIOC_FORCE_RESET() SET_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_GPIOCRST) + +#if defined(GPIOD) +#define __HAL_RCC_GPIOD_FORCE_RESET() SET_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_GPIODRST) +#endif /* GPIOD */ + +#if defined(GPIOE) +#define __HAL_RCC_GPIOE_FORCE_RESET() SET_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_GPIOERST) +#endif /* GPIOE */ + +#if defined(GPIOF) +#define __HAL_RCC_GPIOF_FORCE_RESET() SET_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_GPIOFRST) +#endif /* GPIOF */ + +#if defined(GPIOG) +#define __HAL_RCC_GPIOG_FORCE_RESET() SET_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_GPIOGRST) +#endif /* GPIOG */ + +#define __HAL_RCC_GPIOH_FORCE_RESET() SET_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_GPIOHRST) + +#if defined(GPIOI) +#define __HAL_RCC_GPIOI_FORCE_RESET() SET_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_GPIOIRST) +#endif /* GPIOI */ + +#if defined(USB_OTG_FS) +#define __HAL_RCC_USB_OTG_FS_FORCE_RESET() SET_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_OTGFSRST) +#endif /* USB_OTG_FS */ + +#define __HAL_RCC_ADC_FORCE_RESET() SET_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_ADCRST) + +#if defined(DCMI) +#define __HAL_RCC_DCMI_FORCE_RESET() SET_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_DCMIRST) +#endif /* DCMI */ + +#if defined(AES) +#define __HAL_RCC_AES_FORCE_RESET() SET_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_AESRST) +#endif /* AES */ + +#if defined(HASH) +#define __HAL_RCC_HASH_FORCE_RESET() SET_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_HASHRST) +#endif /* HASH */ + +#define __HAL_RCC_RNG_FORCE_RESET() SET_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_RNGRST) + +#if defined(OCTOSPIM) +#define __HAL_RCC_OSPIM_FORCE_RESET() SET_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_OSPIMRST) +#endif /* OCTOSPIM */ + +#if defined(SDMMC1) && defined(RCC_AHB2RSTR_SDMMC1RST) +#define __HAL_RCC_SDMMC1_FORCE_RESET() SET_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_SDMMC1RST) +#endif /* SDMMC1 && RCC_AHB2RSTR_SDMMC1RST */ + + +#define __HAL_RCC_AHB2_RELEASE_RESET() WRITE_REG(RCC->AHB2RSTR, 0x00000000U) + +#define __HAL_RCC_GPIOA_RELEASE_RESET() CLEAR_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_GPIOARST) + +#define __HAL_RCC_GPIOB_RELEASE_RESET() CLEAR_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_GPIOBRST) + +#define __HAL_RCC_GPIOC_RELEASE_RESET() CLEAR_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_GPIOCRST) + +#if defined(GPIOD) +#define __HAL_RCC_GPIOD_RELEASE_RESET() CLEAR_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_GPIODRST) +#endif /* GPIOD */ + +#if defined(GPIOE) +#define __HAL_RCC_GPIOE_RELEASE_RESET() CLEAR_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_GPIOERST) +#endif /* GPIOE */ + +#if defined(GPIOF) +#define __HAL_RCC_GPIOF_RELEASE_RESET() CLEAR_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_GPIOFRST) +#endif /* GPIOF */ + +#if defined(GPIOG) +#define __HAL_RCC_GPIOG_RELEASE_RESET() CLEAR_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_GPIOGRST) +#endif /* GPIOG */ + +#define __HAL_RCC_GPIOH_RELEASE_RESET() CLEAR_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_GPIOHRST) + +#if defined(GPIOI) +#define __HAL_RCC_GPIOI_RELEASE_RESET() CLEAR_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_GPIOIRST) +#endif /* GPIOI */ + +#if defined(USB_OTG_FS) +#define __HAL_RCC_USB_OTG_FS_RELEASE_RESET() CLEAR_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_OTGFSRST) +#endif /* USB_OTG_FS */ + +#define __HAL_RCC_ADC_RELEASE_RESET() CLEAR_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_ADCRST) + +#if defined(DCMI) +#define __HAL_RCC_DCMI_RELEASE_RESET() CLEAR_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_DCMIRST) +#endif /* DCMI */ + +#if defined(AES) +#define __HAL_RCC_AES_RELEASE_RESET() CLEAR_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_AESRST) +#endif /* AES */ + +#if defined(HASH) +#define __HAL_RCC_HASH_RELEASE_RESET() CLEAR_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_HASHRST) +#endif /* HASH */ + +#define __HAL_RCC_RNG_RELEASE_RESET() CLEAR_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_RNGRST) + +#if defined(OCTOSPIM) +#define __HAL_RCC_OSPIM_RELEASE_RESET() CLEAR_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_OSPIMRST) +#endif /* OCTOSPIM */ + +#if defined(SDMMC1) && defined(RCC_AHB2RSTR_SDMMC1RST) +#define __HAL_RCC_SDMMC1_RELEASE_RESET() CLEAR_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_SDMMC1RST) +#endif /* SDMMC1 && RCC_AHB2RSTR_SDMMC1RST */ + +/** + * @} + */ + +/** @defgroup RCC_AHB3_Force_Release_Reset AHB3 Peripheral Force Release Reset + * @brief Force or release AHB3 peripheral reset. + * @{ + */ +#define __HAL_RCC_AHB3_FORCE_RESET() WRITE_REG(RCC->AHB3RSTR, 0xFFFFFFFFU) + +#if defined(FMC_BANK1) +#define __HAL_RCC_FMC_FORCE_RESET() SET_BIT(RCC->AHB3RSTR, RCC_AHB3RSTR_FMCRST) +#endif /* FMC_BANK1 */ + +#if defined(QUADSPI) +#define __HAL_RCC_QSPI_FORCE_RESET() SET_BIT(RCC->AHB3RSTR, RCC_AHB3RSTR_QSPIRST) +#endif /* QUADSPI */ + +#if defined(OCTOSPI1) +#define __HAL_RCC_OSPI1_FORCE_RESET() SET_BIT(RCC->AHB3RSTR, RCC_AHB3RSTR_OSPI1RST) +#endif /* OCTOSPI1 */ + +#if defined(OCTOSPI2) +#define __HAL_RCC_OSPI2_FORCE_RESET() SET_BIT(RCC->AHB3RSTR, RCC_AHB3RSTR_OSPI2RST) +#endif /* OCTOSPI2 */ + +#define __HAL_RCC_AHB3_RELEASE_RESET() WRITE_REG(RCC->AHB3RSTR, 0x00000000U) + +#if defined(FMC_BANK1) +#define __HAL_RCC_FMC_RELEASE_RESET() CLEAR_BIT(RCC->AHB3RSTR, RCC_AHB3RSTR_FMCRST) +#endif /* FMC_BANK1 */ + +#if defined(QUADSPI) +#define __HAL_RCC_QSPI_RELEASE_RESET() CLEAR_BIT(RCC->AHB3RSTR, RCC_AHB3RSTR_QSPIRST) +#endif /* QUADSPI */ + +#if defined(OCTOSPI1) +#define __HAL_RCC_OSPI1_RELEASE_RESET() CLEAR_BIT(RCC->AHB3RSTR, RCC_AHB3RSTR_OSPI1RST) +#endif /* OCTOSPI1 */ + +#if defined(OCTOSPI2) +#define __HAL_RCC_OSPI2_RELEASE_RESET() CLEAR_BIT(RCC->AHB3RSTR, RCC_AHB3RSTR_OSPI2RST) +#endif /* OCTOSPI2 */ + +/** + * @} + */ + +/** @defgroup RCC_APB1_Force_Release_Reset APB1 Peripheral Force Release Reset + * @brief Force or release APB1 peripheral reset. + * @{ + */ +#define __HAL_RCC_APB1_FORCE_RESET() WRITE_REG(RCC->APB1RSTR1, 0xFFFFFFFFU) + +#define __HAL_RCC_TIM2_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_TIM2RST) + +#if defined(TIM3) +#define __HAL_RCC_TIM3_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_TIM3RST) +#endif /* TIM3 */ + +#if defined(TIM4) +#define __HAL_RCC_TIM4_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_TIM4RST) +#endif /* TIM4 */ + +#if defined(TIM5) +#define __HAL_RCC_TIM5_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_TIM5RST) +#endif /* TIM5 */ + +#define __HAL_RCC_TIM6_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_TIM6RST) + +#define __HAL_RCC_TIM7_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_TIM7RST) + +#if defined(LCD) +#define __HAL_RCC_LCD_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_LCDRST) +#endif /* LCD */ + +#if defined(SPI2) +#define __HAL_RCC_SPI2_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_SPI2RST) +#endif /* SPI2 */ + +#define __HAL_RCC_SPI3_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_SPI3RST) + +#define __HAL_RCC_USART2_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_USART2RST) + +#if defined(USART3) +#define __HAL_RCC_USART3_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_USART3RST) +#endif /* USART3 */ + +#if defined(UART4) +#define __HAL_RCC_UART4_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_UART4RST) +#endif /* UART4 */ + +#if defined(UART5) +#define __HAL_RCC_UART5_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_UART5RST) +#endif /* UART5 */ + +#define __HAL_RCC_I2C1_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_I2C1RST) + +#if defined(I2C2) +#define __HAL_RCC_I2C2_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_I2C2RST) +#endif /* I2C2 */ + +#define __HAL_RCC_I2C3_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_I2C3RST) + +#if defined(I2C4) +#define __HAL_RCC_I2C4_FORCE_RESET() SET_BIT(RCC->APB1RSTR2, RCC_APB1RSTR2_I2C4RST) +#endif /* I2C4 */ + +#if defined(CRS) +#define __HAL_RCC_CRS_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_CRSRST) +#endif /* CRS */ + +#define __HAL_RCC_CAN1_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_CAN1RST) + +#if defined(CAN2) +#define __HAL_RCC_CAN2_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_CAN2RST) +#endif /* CAN2 */ + +#if defined(USB) +#define __HAL_RCC_USB_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_USBFSRST) +#endif /* USB */ + +#define __HAL_RCC_PWR_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_PWRRST) + +#define __HAL_RCC_DAC1_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_DAC1RST) + +#define __HAL_RCC_OPAMP_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_OPAMPRST) + +#define __HAL_RCC_LPTIM1_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_LPTIM1RST) + +#define __HAL_RCC_LPUART1_FORCE_RESET() SET_BIT(RCC->APB1RSTR2, RCC_APB1RSTR2_LPUART1RST) + +#if defined(SWPMI1) +#define __HAL_RCC_SWPMI1_FORCE_RESET() SET_BIT(RCC->APB1RSTR2, RCC_APB1RSTR2_SWPMI1RST) +#endif /* SWPMI1 */ + +#define __HAL_RCC_LPTIM2_FORCE_RESET() SET_BIT(RCC->APB1RSTR2, RCC_APB1RSTR2_LPTIM2RST) + + +#define __HAL_RCC_APB1_RELEASE_RESET() WRITE_REG(RCC->APB1RSTR1, 0x00000000U) + +#define __HAL_RCC_TIM2_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_TIM2RST) + +#if defined(TIM3) +#define __HAL_RCC_TIM3_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_TIM3RST) +#endif /* TIM3 */ + +#if defined(TIM4) +#define __HAL_RCC_TIM4_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_TIM4RST) +#endif /* TIM4 */ + +#if defined(TIM5) +#define __HAL_RCC_TIM5_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_TIM5RST) +#endif /* TIM5 */ + +#define __HAL_RCC_TIM6_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_TIM6RST) + +#define __HAL_RCC_TIM7_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_TIM7RST) + +#if defined(LCD) +#define __HAL_RCC_LCD_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_LCDRST) +#endif /* LCD */ + +#if defined(SPI2) +#define __HAL_RCC_SPI2_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_SPI2RST) +#endif /* SPI2 */ + +#define __HAL_RCC_SPI3_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_SPI3RST) + +#define __HAL_RCC_USART2_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_USART2RST) + +#if defined(USART3) +#define __HAL_RCC_USART3_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_USART3RST) +#endif /* USART3 */ + +#if defined(UART4) +#define __HAL_RCC_UART4_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_UART4RST) +#endif /* UART4 */ + +#if defined(UART5) +#define __HAL_RCC_UART5_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_UART5RST) +#endif /* UART5 */ + +#define __HAL_RCC_I2C1_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_I2C1RST) + +#if defined(I2C2) +#define __HAL_RCC_I2C2_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_I2C2RST) +#endif /* I2C2 */ + +#define __HAL_RCC_I2C3_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_I2C3RST) + +#if defined(I2C4) +#define __HAL_RCC_I2C4_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR2, RCC_APB1RSTR2_I2C4RST) +#endif /* I2C4 */ + +#if defined(CRS) +#define __HAL_RCC_CRS_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_CRSRST) +#endif /* CRS */ + +#define __HAL_RCC_CAN1_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_CAN1RST) + +#if defined(CAN2) +#define __HAL_RCC_CAN2_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_CAN2RST) +#endif /* CAN2 */ + +#if defined(USB) +#define __HAL_RCC_USB_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_USBFSRST) +#endif /* USB */ + +#define __HAL_RCC_PWR_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_PWRRST) + +#define __HAL_RCC_DAC1_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_DAC1RST) + +#define __HAL_RCC_OPAMP_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_OPAMPRST) + +#define __HAL_RCC_LPTIM1_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_LPTIM1RST) + +#define __HAL_RCC_LPUART1_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR2, RCC_APB1RSTR2_LPUART1RST) + +#if defined(SWPMI1) +#define __HAL_RCC_SWPMI1_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR2, RCC_APB1RSTR2_SWPMI1RST) +#endif /* SWPMI1 */ + +#define __HAL_RCC_LPTIM2_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR2, RCC_APB1RSTR2_LPTIM2RST) + +/** + * @} + */ + +/** @defgroup RCC_APB2_Force_Release_Reset APB2 Peripheral Force Release Reset + * @brief Force or release APB2 peripheral reset. + * @{ + */ +#define __HAL_RCC_APB2_FORCE_RESET() WRITE_REG(RCC->APB2RSTR, 0xFFFFFFFFU) + +#define __HAL_RCC_SYSCFG_FORCE_RESET() SET_BIT(RCC->APB2RSTR, RCC_APB2RSTR_SYSCFGRST) + +#if defined(SDMMC1) && defined(RCC_APB2RSTR_SDMMC1RST) +#define __HAL_RCC_SDMMC1_FORCE_RESET() SET_BIT(RCC->APB2RSTR, RCC_APB2RSTR_SDMMC1RST) +#endif /* SDMMC1 && RCC_APB2RSTR_SDMMC1RST */ + +#define __HAL_RCC_TIM1_FORCE_RESET() SET_BIT(RCC->APB2RSTR, RCC_APB2RSTR_TIM1RST) + +#define __HAL_RCC_SPI1_FORCE_RESET() SET_BIT(RCC->APB2RSTR, RCC_APB2RSTR_SPI1RST) + +#if defined(TIM8) +#define __HAL_RCC_TIM8_FORCE_RESET() SET_BIT(RCC->APB2RSTR, RCC_APB2RSTR_TIM8RST) +#endif /* TIM8 */ + +#define __HAL_RCC_USART1_FORCE_RESET() SET_BIT(RCC->APB2RSTR, RCC_APB2RSTR_USART1RST) + +#define __HAL_RCC_TIM15_FORCE_RESET() SET_BIT(RCC->APB2RSTR, RCC_APB2RSTR_TIM15RST) + +#define __HAL_RCC_TIM16_FORCE_RESET() SET_BIT(RCC->APB2RSTR, RCC_APB2RSTR_TIM16RST) + +#if defined(TIM17) +#define __HAL_RCC_TIM17_FORCE_RESET() SET_BIT(RCC->APB2RSTR, RCC_APB2RSTR_TIM17RST) +#endif /* TIM17 */ + +#define __HAL_RCC_SAI1_FORCE_RESET() SET_BIT(RCC->APB2RSTR, RCC_APB2RSTR_SAI1RST) + +#if defined(SAI2) +#define __HAL_RCC_SAI2_FORCE_RESET() SET_BIT(RCC->APB2RSTR, RCC_APB2RSTR_SAI2RST) +#endif /* SAI2 */ + +#if defined(DFSDM1_Filter0) +#define __HAL_RCC_DFSDM1_FORCE_RESET() SET_BIT(RCC->APB2RSTR, RCC_APB2RSTR_DFSDM1RST) +#endif /* DFSDM1_Filter0 */ + +#if defined(LTDC) +#define __HAL_RCC_LTDC_FORCE_RESET() SET_BIT(RCC->APB2RSTR, RCC_APB2RSTR_LTDCRST) +#endif /* LTDC */ + +#if defined(DSI) +#define __HAL_RCC_DSI_FORCE_RESET() SET_BIT(RCC->APB2RSTR, RCC_APB2RSTR_DSIRST) +#endif /* DSI */ + + +#define __HAL_RCC_APB2_RELEASE_RESET() WRITE_REG(RCC->APB2RSTR, 0x00000000U) + +#define __HAL_RCC_SYSCFG_RELEASE_RESET() CLEAR_BIT(RCC->APB2RSTR, RCC_APB2RSTR_SYSCFGRST) + +#if defined(SDMMC1) && defined(RCC_APB2RSTR_SDMMC1RST) +#define __HAL_RCC_SDMMC1_RELEASE_RESET() CLEAR_BIT(RCC->APB2RSTR, RCC_APB2RSTR_SDMMC1RST) +#endif /* SDMMC1 && RCC_APB2RSTR_SDMMC1RST */ + +#define __HAL_RCC_TIM1_RELEASE_RESET() CLEAR_BIT(RCC->APB2RSTR, RCC_APB2RSTR_TIM1RST) + +#define __HAL_RCC_SPI1_RELEASE_RESET() CLEAR_BIT(RCC->APB2RSTR, RCC_APB2RSTR_SPI1RST) + +#if defined(TIM8) +#define __HAL_RCC_TIM8_RELEASE_RESET() CLEAR_BIT(RCC->APB2RSTR, RCC_APB2RSTR_TIM8RST) +#endif /* TIM8 */ + +#define __HAL_RCC_USART1_RELEASE_RESET() CLEAR_BIT(RCC->APB2RSTR, RCC_APB2RSTR_USART1RST) + +#define __HAL_RCC_TIM15_RELEASE_RESET() CLEAR_BIT(RCC->APB2RSTR, RCC_APB2RSTR_TIM15RST) + +#define __HAL_RCC_TIM16_RELEASE_RESET() CLEAR_BIT(RCC->APB2RSTR, RCC_APB2RSTR_TIM16RST) + +#if defined(TIM17) +#define __HAL_RCC_TIM17_RELEASE_RESET() CLEAR_BIT(RCC->APB2RSTR, RCC_APB2RSTR_TIM17RST) +#endif /* TIM17 */ + +#define __HAL_RCC_SAI1_RELEASE_RESET() CLEAR_BIT(RCC->APB2RSTR, RCC_APB2RSTR_SAI1RST) + +#if defined(SAI2) +#define __HAL_RCC_SAI2_RELEASE_RESET() CLEAR_BIT(RCC->APB2RSTR, RCC_APB2RSTR_SAI2RST) +#endif /* SAI2 */ + +#if defined(DFSDM1_Filter0) +#define __HAL_RCC_DFSDM1_RELEASE_RESET() CLEAR_BIT(RCC->APB2RSTR, RCC_APB2RSTR_DFSDM1RST) +#endif /* DFSDM1_Filter0 */ + +#if defined(LTDC) +#define __HAL_RCC_LTDC_RELEASE_RESET() CLEAR_BIT(RCC->APB2RSTR, RCC_APB2RSTR_LTDCRST) +#endif /* LTDC */ + +#if defined(DSI) +#define __HAL_RCC_DSI_RELEASE_RESET() CLEAR_BIT(RCC->APB2RSTR, RCC_APB2RSTR_DSIRST) +#endif /* DSI */ + +/** + * @} + */ + +/** @defgroup RCC_AHB1_Clock_Sleep_Enable_Disable AHB1 Peripheral Clock Sleep Enable Disable + * @brief Enable or disable the AHB1 peripheral clock during Low Power (Sleep) mode. + * @note Peripheral clock gating in SLEEP mode can be used to further reduce + * power consumption. + * @note After wakeup from SLEEP mode, the peripheral clock is enabled again. + * @note By default, all peripheral clocks are enabled during SLEEP mode. + * @{ + */ + +#define __HAL_RCC_DMA1_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_DMA1SMEN) + +#define __HAL_RCC_DMA2_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_DMA2SMEN) + +#if defined(DMAMUX1) +#define __HAL_RCC_DMAMUX1_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_DMAMUX1SMEN) +#endif /* DMAMUX1 */ + +#define __HAL_RCC_FLASH_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_FLASHSMEN) + +#define __HAL_RCC_SRAM1_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_SRAM1SMEN) + +#define __HAL_RCC_CRC_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_CRCSMEN) + +#define __HAL_RCC_TSC_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_TSCSMEN) + +#if defined(DMA2D) +#define __HAL_RCC_DMA2D_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_DMA2DSMEN) +#endif /* DMA2D */ + +#if defined(GFXMMU) +#define __HAL_RCC_GFXMMU_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_GFXMMUSMEN) +#endif /* GFXMMU */ + + +#define __HAL_RCC_DMA1_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_DMA1SMEN) + +#define __HAL_RCC_DMA2_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_DMA2SMEN) + +#if defined(DMAMUX1) +#define __HAL_RCC_DMAMUX1_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_DMAMUX1SMEN) +#endif /* DMAMUX1 */ + +#define __HAL_RCC_FLASH_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_FLASHSMEN) + +#define __HAL_RCC_SRAM1_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_SRAM1SMEN) + +#define __HAL_RCC_CRC_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_CRCSMEN) + +#define __HAL_RCC_TSC_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_TSCSMEN) + +#if defined(DMA2D) +#define __HAL_RCC_DMA2D_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_DMA2DSMEN) +#endif /* DMA2D */ + +#if defined(GFXMMU) +#define __HAL_RCC_GFXMMU_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_GFXMMUSMEN) +#endif /* GFXMMU */ + +/** + * @} + */ + +/** @defgroup RCC_AHB2_Clock_Sleep_Enable_Disable AHB2 Peripheral Clock Sleep Enable Disable + * @brief Enable or disable the AHB2 peripheral clock during Low Power (Sleep) mode. + * @note Peripheral clock gating in SLEEP mode can be used to further reduce + * power consumption. + * @note After wakeup from SLEEP mode, the peripheral clock is enabled again. + * @note By default, all peripheral clocks are enabled during SLEEP mode. + * @{ + */ + +#define __HAL_RCC_GPIOA_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOASMEN) + +#define __HAL_RCC_GPIOB_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOBSMEN) + +#define __HAL_RCC_GPIOC_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOCSMEN) + +#if defined(GPIOD) +#define __HAL_RCC_GPIOD_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIODSMEN) +#endif /* GPIOD */ + +#if defined(GPIOE) +#define __HAL_RCC_GPIOE_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOESMEN) +#endif /* GPIOE */ + +#if defined(GPIOF) +#define __HAL_RCC_GPIOF_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOFSMEN) +#endif /* GPIOF */ + +#if defined(GPIOG) +#define __HAL_RCC_GPIOG_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOGSMEN) +#endif /* GPIOG */ + +#define __HAL_RCC_GPIOH_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOHSMEN) + +#if defined(GPIOI) +#define __HAL_RCC_GPIOI_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOISMEN) +#endif /* GPIOI */ + +#define __HAL_RCC_SRAM2_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_SRAM2SMEN) + +#if defined(SRAM3) +#define __HAL_RCC_SRAM3_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_SRAM3SMEN) +#endif /* SRAM3 */ + +#if defined(USB_OTG_FS) +#define __HAL_RCC_USB_OTG_FS_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_OTGFSSMEN) +#endif /* USB_OTG_FS */ + +#define __HAL_RCC_ADC_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_ADCSMEN) + +#if defined(DCMI) +#define __HAL_RCC_DCMI_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_DCMISMEN) +#endif /* DCMI */ + +#if defined(AES) +#define __HAL_RCC_AES_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_AESSMEN) +#endif /* AES */ + +#if defined(HASH) +#define __HAL_RCC_HASH_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_HASHSMEN) +#endif /* HASH */ + +#define __HAL_RCC_RNG_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_RNGSMEN) + +#if defined(OCTOSPIM) +#define __HAL_RCC_OSPIM_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_OSPIMSMEN) +#endif /* OCTOSPIM */ + +#if defined(SDMMC1) && defined(RCC_AHB2SMENR_SDMMC1SMEN) +#define __HAL_RCC_SDMMC1_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_SDMMC1SMEN) +#endif /* SDMMC1 && RCC_AHB2SMENR_SDMMC1SMEN */ + + +#define __HAL_RCC_GPIOA_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOASMEN) + +#define __HAL_RCC_GPIOB_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOBSMEN) + +#define __HAL_RCC_GPIOC_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOCSMEN) + +#if defined(GPIOD) +#define __HAL_RCC_GPIOD_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIODSMEN) +#endif /* GPIOD */ + +#if defined(GPIOE) +#define __HAL_RCC_GPIOE_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOESMEN) +#endif /* GPIOE */ + +#if defined(GPIOF) +#define __HAL_RCC_GPIOF_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOFSMEN) +#endif /* GPIOF */ + +#if defined(GPIOG) +#define __HAL_RCC_GPIOG_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOGSMEN) +#endif /* GPIOG */ + +#define __HAL_RCC_GPIOH_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOHSMEN) + +#if defined(GPIOI) +#define __HAL_RCC_GPIOI_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOISMEN) +#endif /* GPIOI */ + +#define __HAL_RCC_SRAM2_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_SRAM2SMEN) + +#if defined(SRAM3) +#define __HAL_RCC_SRAM3_IS_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_SRAM3SMEN) +#endif /* SRAM3 */ + +#if defined(USB_OTG_FS) +#define __HAL_RCC_USB_OTG_FS_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_OTGFSSMEN) +#endif /* USB_OTG_FS */ + +#define __HAL_RCC_ADC_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_ADCSMEN) + +#if defined(DCMI) +#define __HAL_RCC_DCMI_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_DCMISMEN) +#endif /* DCMI */ + +#if defined(AES) +#define __HAL_RCC_AES_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_AESSMEN) +#endif /* AES */ + +#if defined(HASH) +#define __HAL_RCC_HASH_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_HASHSMEN) +#endif /* HASH */ + +#define __HAL_RCC_RNG_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_RNGSMEN) + +#if defined(OCTOSPIM) +#define __HAL_RCC_OSPIM_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_OSPIMSMEN) +#endif /* OCTOSPIM */ + +#if defined(SDMMC1) && defined(RCC_AHB2SMENR_SDMMC1SMEN) +#define __HAL_RCC_SDMMC1_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_SDMMC1SMEN) +#endif /* SDMMC1 && RCC_AHB2SMENR_SDMMC1SMEN */ + +/** + * @} + */ + +/** @defgroup RCC_AHB3_Clock_Sleep_Enable_Disable AHB3 Peripheral Clock Sleep Enable Disable + * @brief Enable or disable the AHB3 peripheral clock during Low Power (Sleep) mode. + * @note Peripheral clock gating in SLEEP mode can be used to further reduce + * power consumption. + * @note After wakeup from SLEEP mode, the peripheral clock is enabled again. + * @note By default, all peripheral clocks are enabled during SLEEP mode. + * @{ + */ + +#if defined(QUADSPI) +#define __HAL_RCC_QSPI_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB3SMENR, RCC_AHB3SMENR_QSPISMEN) +#endif /* QUADSPI */ + +#if defined(OCTOSPI1) +#define __HAL_RCC_OSPI1_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB3SMENR, RCC_AHB3SMENR_OSPI1SMEN) +#endif /* OCTOSPI1 */ + +#if defined(OCTOSPI2) +#define __HAL_RCC_OSPI2_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB3SMENR, RCC_AHB3SMENR_OSPI2SMEN) +#endif /* OCTOSPI2 */ + +#if defined(FMC_BANK1) +#define __HAL_RCC_FMC_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB3SMENR, RCC_AHB3SMENR_FMCSMEN) +#endif /* FMC_BANK1 */ + +#if defined(QUADSPI) +#define __HAL_RCC_QSPI_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB3SMENR, RCC_AHB3SMENR_QSPISMEN) +#endif /* QUADSPI */ + +#if defined(OCTOSPI1) +#define __HAL_RCC_OSPI1_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB3SMENR, RCC_AHB3SMENR_OSPI1SMEN) +#endif /* OCTOSPI1 */ + +#if defined(OCTOSPI2) +#define __HAL_RCC_OSPI2_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB3SMENR, RCC_AHB3SMENR_OSPI2SMEN) +#endif /* OCTOSPI2 */ + +#if defined(FMC_BANK1) +#define __HAL_RCC_FMC_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB3SMENR, RCC_AHB3SMENR_FMCSMEN) +#endif /* FMC_BANK1 */ + +/** + * @} + */ + +/** @defgroup RCC_APB1_Clock_Sleep_Enable_Disable APB1 Peripheral Clock Sleep Enable Disable + * @brief Enable or disable the APB1 peripheral clock during Low Power (Sleep) mode. + * @note Peripheral clock gating in SLEEP mode can be used to further reduce + * power consumption. + * @note After wakeup from SLEEP mode, the peripheral clock is enabled again. + * @note By default, all peripheral clocks are enabled during SLEEP mode. + * @{ + */ + +#define __HAL_RCC_TIM2_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM2SMEN) + +#if defined(TIM3) +#define __HAL_RCC_TIM3_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM3SMEN) +#endif /* TIM3 */ + +#if defined(TIM4) +#define __HAL_RCC_TIM4_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM4SMEN) +#endif /* TIM4 */ + +#if defined(TIM5) +#define __HAL_RCC_TIM5_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM5SMEN) +#endif /* TIM5 */ + +#define __HAL_RCC_TIM6_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM6SMEN) + +#define __HAL_RCC_TIM7_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM7SMEN) + +#if defined(LCD) +#define __HAL_RCC_LCD_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_LCDSMEN) +#endif /* LCD */ + +#if defined(RCC_APB1SMENR1_RTCAPBSMEN) +#define __HAL_RCC_RTCAPB_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_RTCAPBSMEN) +#endif /* RCC_APB1SMENR1_RTCAPBSMEN */ + +#define __HAL_RCC_WWDG_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_WWDGSMEN) + +#if defined(SPI2) +#define __HAL_RCC_SPI2_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_SPI2SMEN) +#endif /* SPI2 */ + +#define __HAL_RCC_SPI3_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_SPI3SMEN) + +#define __HAL_RCC_USART2_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_USART2SMEN) + +#if defined(USART3) +#define __HAL_RCC_USART3_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_USART3SMEN) +#endif /* USART3 */ + +#if defined(UART4) +#define __HAL_RCC_UART4_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_UART4SMEN) +#endif /* UART4 */ + +#if defined(UART5) +#define __HAL_RCC_UART5_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_UART5SMEN) +#endif /* UART5 */ + +#define __HAL_RCC_I2C1_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_I2C1SMEN) + +#if defined(I2C2) +#define __HAL_RCC_I2C2_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_I2C2SMEN) +#endif /* I2C2 */ + +#define __HAL_RCC_I2C3_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_I2C3SMEN) + +#if defined(I2C4) +#define __HAL_RCC_I2C4_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR2, RCC_APB1SMENR2_I2C4SMEN) +#endif /* I2C4 */ + +#if defined(CRS) +#define __HAL_RCC_CRS_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_CRSSMEN) +#endif /* CRS */ + +#define __HAL_RCC_CAN1_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_CAN1SMEN) + +#if defined(CAN2) +#define __HAL_RCC_CAN2_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_CAN2SMEN) +#endif /* CAN2 */ + +#if defined(USB) +#define __HAL_RCC_USB_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_USBFSSMEN) +#endif /* USB */ + +#define __HAL_RCC_PWR_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_PWRSMEN) + +#define __HAL_RCC_DAC1_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_DAC1SMEN) + +#define __HAL_RCC_OPAMP_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_OPAMPSMEN) + +#define __HAL_RCC_LPTIM1_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_LPTIM1SMEN) + +#define __HAL_RCC_LPUART1_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR2, RCC_APB1SMENR2_LPUART1SMEN) + +#if defined(SWPMI1) +#define __HAL_RCC_SWPMI1_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR2, RCC_APB1SMENR2_SWPMI1SMEN) +#endif /* SWPMI1 */ + +#define __HAL_RCC_LPTIM2_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR2, RCC_APB1SMENR2_LPTIM2SMEN) + + +#define __HAL_RCC_TIM2_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM2SMEN) + +#if defined(TIM3) +#define __HAL_RCC_TIM3_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM3SMEN) +#endif /* TIM3 */ + +#if defined(TIM4) +#define __HAL_RCC_TIM4_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM4SMEN) +#endif /* TIM4 */ + +#if defined(TIM5) +#define __HAL_RCC_TIM5_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM5SMEN) +#endif /* TIM5 */ + +#define __HAL_RCC_TIM6_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM6SMEN) + +#define __HAL_RCC_TIM7_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM7SMEN) + +#if defined(LCD) +#define __HAL_RCC_LCD_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_LCDSMEN) +#endif /* LCD */ + +#if defined(RCC_APB1SMENR1_RTCAPBSMEN) +#define __HAL_RCC_RTCAPB_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_RTCAPBSMEN) +#endif /* RCC_APB1SMENR1_RTCAPBSMEN */ + +#define __HAL_RCC_WWDG_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_WWDGSMEN) + +#if defined(SPI2) +#define __HAL_RCC_SPI2_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_SPI2SMEN) +#endif /* SPI2 */ + +#define __HAL_RCC_SPI3_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_SPI3SMEN) + +#define __HAL_RCC_USART2_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_USART2SMEN) + +#if defined(USART3) +#define __HAL_RCC_USART3_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_USART3SMEN) +#endif /* USART3 */ + +#if defined(UART4) +#define __HAL_RCC_UART4_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_UART4SMEN) +#endif /* UART4 */ + +#if defined(UART5) +#define __HAL_RCC_UART5_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_UART5SMEN) +#endif /* UART5 */ + +#define __HAL_RCC_I2C1_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_I2C1SMEN) + +#if defined(I2C2) +#define __HAL_RCC_I2C2_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_I2C2SMEN) +#endif /* I2C2 */ + +#define __HAL_RCC_I2C3_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_I2C3SMEN) + +#if defined(I2C4) +#define __HAL_RCC_I2C4_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR2, RCC_APB1SMENR2_I2C4SMEN) +#endif /* I2C4 */ + +#if defined(CRS) +#define __HAL_RCC_CRS_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_CRSSMEN) +#endif /* CRS */ + +#define __HAL_RCC_CAN1_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_CAN1SMEN) + +#if defined(CAN2) +#define __HAL_RCC_CAN2_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_CAN2SMEN) +#endif /* CAN2 */ + +#if defined(USB) +#define __HAL_RCC_USB_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_USBFSSMEN) +#endif /* USB */ + +#define __HAL_RCC_PWR_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_PWRSMEN) + +#define __HAL_RCC_DAC1_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_DAC1SMEN) + +#define __HAL_RCC_OPAMP_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_OPAMPSMEN) + +#define __HAL_RCC_LPTIM1_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_LPTIM1SMEN) + +#define __HAL_RCC_LPUART1_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR2, RCC_APB1SMENR2_LPUART1SMEN) + +#if defined(SWPMI1) +#define __HAL_RCC_SWPMI1_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR2, RCC_APB1SMENR2_SWPMI1SMEN) +#endif /* SWPMI1 */ + +#define __HAL_RCC_LPTIM2_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR2, RCC_APB1SMENR2_LPTIM2SMEN) + +/** + * @} + */ + +/** @defgroup RCC_APB2_Clock_Sleep_Enable_Disable APB2 Peripheral Clock Sleep Enable Disable + * @brief Enable or disable the APB2 peripheral clock during Low Power (Sleep) mode. + * @note Peripheral clock gating in SLEEP mode can be used to further reduce + * power consumption. + * @note After wakeup from SLEEP mode, the peripheral clock is enabled again. + * @note By default, all peripheral clocks are enabled during SLEEP mode. + * @{ + */ + +#define __HAL_RCC_SYSCFG_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SYSCFGSMEN) + +#if defined(SDMMC1) && defined(RCC_APB2SMENR_SDMMC1SMEN) +#define __HAL_RCC_SDMMC1_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SDMMC1SMEN) +#endif /* SDMMC1 && RCC_APB2SMENR_SDMMC1SMEN */ + +#define __HAL_RCC_TIM1_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM1SMEN) + +#define __HAL_RCC_SPI1_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SPI1SMEN) + +#if defined(TIM8) +#define __HAL_RCC_TIM8_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM8SMEN) +#endif /* TIM8 */ + +#define __HAL_RCC_USART1_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB2SMENR, RCC_APB2SMENR_USART1SMEN) + +#define __HAL_RCC_TIM15_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM15SMEN) + +#define __HAL_RCC_TIM16_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM16SMEN) + +#if defined(TIM17) +#define __HAL_RCC_TIM17_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM17SMEN) +#endif /* TIM17 */ + +#define __HAL_RCC_SAI1_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SAI1SMEN) + +#if defined(SAI2) +#define __HAL_RCC_SAI2_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SAI2SMEN) +#endif /* SAI2 */ + +#if defined(DFSDM1_Filter0) +#define __HAL_RCC_DFSDM1_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB2SMENR, RCC_APB2SMENR_DFSDM1SMEN) +#endif /* DFSDM1_Filter0 */ + +#if defined(LTDC) +#define __HAL_RCC_LTDC_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB2SMENR, RCC_APB2SMENR_LTDCSMEN) +#endif /* LTDC */ + +#if defined(DSI) +#define __HAL_RCC_DSI_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB2SMENR, RCC_APB2SMENR_DSISMEN) +#endif /* DSI */ + + +#define __HAL_RCC_SYSCFG_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SYSCFGSMEN) + +#if defined(SDMMC1) && defined(RCC_APB2SMENR_SDMMC1SMEN) +#define __HAL_RCC_SDMMC1_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SDMMC1SMEN) +#endif /* SDMMC1 && RCC_APB2SMENR_SDMMC1SMEN */ + +#define __HAL_RCC_TIM1_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM1SMEN) + +#define __HAL_RCC_SPI1_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SPI1SMEN) + +#if defined(TIM8) +#define __HAL_RCC_TIM8_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM8SMEN) +#endif /* TIM8 */ + +#define __HAL_RCC_USART1_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB2SMENR, RCC_APB2SMENR_USART1SMEN) + +#define __HAL_RCC_TIM15_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM15SMEN) + +#define __HAL_RCC_TIM16_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM16SMEN) + +#if defined(TIM17) +#define __HAL_RCC_TIM17_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM17SMEN) +#endif /* TIM17 */ + +#define __HAL_RCC_SAI1_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SAI1SMEN) + +#if defined(SAI2) +#define __HAL_RCC_SAI2_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SAI2SMEN) +#endif /* SAI2 */ + +#if defined(DFSDM1_Filter0) +#define __HAL_RCC_DFSDM1_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB2SMENR, RCC_APB2SMENR_DFSDM1SMEN) +#endif /* DFSDM1_Filter0 */ + +#if defined(LTDC) +#define __HAL_RCC_LTDC_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB2SMENR, RCC_APB2SMENR_LTDCSMEN) +#endif /* LTDC */ + +#if defined(DSI) +#define __HAL_RCC_DSI_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB2SMENR, RCC_APB2SMENR_DSISMEN) +#endif /* DSI */ + +/** + * @} + */ + +/** @defgroup RCC_AHB1_Clock_Sleep_Enable_Disable_Status AHB1 Peripheral Clock Sleep Enabled or Disabled Status + * @brief Check whether the AHB1 peripheral clock during Low Power (Sleep) mode is enabled or not. + * @note Peripheral clock gating in SLEEP mode can be used to further reduce + * power consumption. + * @note After wakeup from SLEEP mode, the peripheral clock is enabled again. + * @note By default, all peripheral clocks are enabled during SLEEP mode. + * @{ + */ + +#define __HAL_RCC_DMA1_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_DMA1SMEN) != RESET) + +#define __HAL_RCC_DMA2_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_DMA2SMEN) != RESET) + +#if defined(DMAMUX1) +#define __HAL_RCC_DMAMUX1_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_DMAMUX1SMEN) != RESET) +#endif /* DMAMUX1 */ + +#define __HAL_RCC_FLASH_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_FLASHSMEN) != RESET) + +#define __HAL_RCC_SRAM1_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_SRAM1SMEN) != RESET) + +#define __HAL_RCC_CRC_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_CRCSMEN) != RESET) + +#define __HAL_RCC_TSC_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_TSCSMEN) != RESET) + +#if defined(DMA2D) +#define __HAL_RCC_DMA2D_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_DMA2DSMEN) != RESET) +#endif /* DMA2D */ + +#if defined(GFXMMU) +#define __HAL_RCC_GFXMMU_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_GFXMMUSMEN) != RESET) +#endif /* GFXMMU */ + + +#define __HAL_RCC_DMA1_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_DMA1SMEN) == RESET) + +#define __HAL_RCC_DMA2_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_DMA2SMEN) == RESET) + +#if defined(DMAMUX1) +#define __HAL_RCC_DMAMUX1_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_DMAMUX1SMEN) == RESET) +#endif /* DMAMUX1 */ + +#define __HAL_RCC_FLASH_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_FLASHSMEN) == RESET) + +#define __HAL_RCC_SRAM1_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_SRAM1SMEN) == RESET) + +#define __HAL_RCC_CRC_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_CRCSMEN) == RESET) + +#define __HAL_RCC_TSC_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_TSCSMEN) == RESET) + +#if defined(DMA2D) +#define __HAL_RCC_DMA2D_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_DMA2DSMEN) == RESET) +#endif /* DMA2D */ + +#if defined(GFXMMU) +#define __HAL_RCC_GFXMMU_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_GFXMMUSMEN) == RESET) +#endif /* GFXMMU */ + +/** + * @} + */ + +/** @defgroup RCC_AHB2_Clock_Sleep_Enable_Disable_Status AHB2 Peripheral Clock Sleep Enabled or Disabled Status + * @brief Check whether the AHB2 peripheral clock during Low Power (Sleep) mode is enabled or not. + * @note Peripheral clock gating in SLEEP mode can be used to further reduce + * power consumption. + * @note After wakeup from SLEEP mode, the peripheral clock is enabled again. + * @note By default, all peripheral clocks are enabled during SLEEP mode. + * @{ + */ + +#define __HAL_RCC_GPIOA_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOASMEN) != RESET) + +#define __HAL_RCC_GPIOB_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOBSMEN) != RESET) + +#define __HAL_RCC_GPIOC_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOCSMEN) != RESET) + +#if defined(GPIOD) +#define __HAL_RCC_GPIOD_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIODSMEN) != RESET) +#endif /* GPIOD */ + +#if defined(GPIOE) +#define __HAL_RCC_GPIOE_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOESMEN) != RESET) +#endif /* GPIOE */ + +#if defined(GPIOF) +#define __HAL_RCC_GPIOF_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOFSMEN) != RESET) +#endif /* GPIOF */ + +#if defined(GPIOG) +#define __HAL_RCC_GPIOG_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOGSMEN) != RESET) +#endif /* GPIOG */ + +#define __HAL_RCC_GPIOH_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOHSMEN) != RESET) + +#if defined(GPIOI) +#define __HAL_RCC_GPIOI_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOISMEN) != RESET) +#endif /* GPIOI */ + +#define __HAL_RCC_SRAM2_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_SRAM2SMEN) != RESET) + +#if defined(SRAM3) +#define __HAL_RCC_SRAM3_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_SRAM3SMEN) != RESET) +#endif /* SRAM3 */ + +#if defined(USB_OTG_FS) +#define __HAL_RCC_USB_OTG_FS_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_OTGFSSMEN) != RESET) +#endif /* USB_OTG_FS */ + +#define __HAL_RCC_ADC_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_ADCSMEN) != RESET) + +#if defined(DCMI) +#define __HAL_RCC_DCMI_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_DCMISMEN) != RESET) +#endif /* DCMI */ + +#if defined(AES) +#define __HAL_RCC_AES_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_AESSMEN) != RESET) +#endif /* AES */ + +#if defined(HASH) +#define __HAL_RCC_HASH_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_HASHSMEN) != RESET) +#endif /* HASH */ + +#define __HAL_RCC_RNG_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_RNGSMEN) != RESET) + +#if defined(OCTOSPIM) +#define __HAL_RCC_OSPIM_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_OSPIMSMEN) != RESET) +#endif /* OCTOSPIM */ + +#if defined(SDMMC1) && defined(RCC_AHB2SMENR_SDMMC1SMEN) +#define __HAL_RCC_SDMMC1_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_SDMMC1SMEN) != RESET) +#endif /* SDMMC1 && RCC_AHB2SMENR_SDMMC1SMEN */ + + +#define __HAL_RCC_GPIOA_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOASMEN) == RESET) + +#define __HAL_RCC_GPIOB_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOBSMEN) == RESET) + +#define __HAL_RCC_GPIOC_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOCSMEN) == RESET) + +#if defined(GPIOD) +#define __HAL_RCC_GPIOD_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIODSMEN) == RESET) +#endif /* GPIOD */ + +#if defined(GPIOE) +#define __HAL_RCC_GPIOE_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOESMEN) == RESET) +#endif /* GPIOE */ + +#if defined(GPIOF) +#define __HAL_RCC_GPIOF_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOFSMEN) == RESET) +#endif /* GPIOF */ + +#if defined(GPIOG) +#define __HAL_RCC_GPIOG_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOGSMEN) == RESET) +#endif /* GPIOG */ + +#define __HAL_RCC_GPIOH_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOHSMEN) == RESET) + +#if defined(GPIOI) +#define __HAL_RCC_GPIOI_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOISMEN) == RESET) +#endif /* GPIOI */ + +#define __HAL_RCC_SRAM2_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_SRAM2SMEN) == RESET) + +#if defined(SRAM3) +#define __HAL_RCC_SRAM3_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_SRAM3SMEN) == RESET) +#endif /* SRAM3 */ + +#if defined(USB_OTG_FS) +#define __HAL_RCC_USB_OTG_FS_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_OTGFSSMEN) == RESET) +#endif /* USB_OTG_FS */ + +#define __HAL_RCC_ADC_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_ADCSMEN) == RESET) + +#if defined(DCMI) +#define __HAL_RCC_DCMI_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_DCMISMEN) == RESET) +#endif /* DCMI */ + +#if defined(AES) +#define __HAL_RCC_AES_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_AESSMEN) == RESET) +#endif /* AES */ + +#if defined(HASH) +#define __HAL_RCC_HASH_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_HASHSMEN) == RESET) +#endif /* HASH */ + +#define __HAL_RCC_RNG_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_RNGSMEN) == RESET) + +#if defined(OCTOSPIM) +#define __HAL_RCC_OSPIM_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_OSPIMSMEN) == RESET) +#endif /* OCTOSPIM */ + +#if defined(SDMMC1) && defined(RCC_AHB2SMENR_SDMMC1SMEN) +#define __HAL_RCC_SDMMC1_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_SDMMC1SMEN) == RESET) +#endif /* SDMMC1 && RCC_AHB2SMENR_SDMMC1SMEN */ + +/** + * @} + */ + +/** @defgroup RCC_AHB3_Clock_Sleep_Enable_Disable_Status AHB3 Peripheral Clock Sleep Enabled or Disabled Status + * @brief Check whether the AHB3 peripheral clock during Low Power (Sleep) mode is enabled or not. + * @note Peripheral clock gating in SLEEP mode can be used to further reduce + * power consumption. + * @note After wakeup from SLEEP mode, the peripheral clock is enabled again. + * @note By default, all peripheral clocks are enabled during SLEEP mode. + * @{ + */ + +#if defined(QUADSPI) +#define __HAL_RCC_QSPI_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB3SMENR, RCC_AHB3SMENR_QSPISMEN) != RESET) +#endif /* QUADSPI */ + +#if defined(OCTOSPI1) +#define __HAL_RCC_OSPI1_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB3SMENR, RCC_AHB3SMENR_OSPI1SMEN) != RESET) +#endif /* OCTOSPI1 */ + +#if defined(OCTOSPI2) +#define __HAL_RCC_OSPI2_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB3SMENR, RCC_AHB3SMENR_OSPI2SMEN) != RESET) +#endif /* OCTOSPI2 */ + +#if defined(FMC_BANK1) +#define __HAL_RCC_FMC_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB3SMENR, RCC_AHB3SMENR_FMCSMEN) != RESET) +#endif /* FMC_BANK1 */ + + +#if defined(QUADSPI) +#define __HAL_RCC_QSPI_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB3SMENR, RCC_AHB3SMENR_QSPISMEN) == RESET) +#endif /* QUADSPI */ + +#if defined(OCTOSPI1) +#define __HAL_RCC_OSPI1_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB3SMENR, RCC_AHB3SMENR_OSPI1SMEN) == RESET) +#endif /* OCTOSPI1 */ + +#if defined(OCTOSPI2) +#define __HAL_RCC_OSPI2_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB3SMENR, RCC_AHB3SMENR_OSPI2SMEN) == RESET) +#endif /* OCTOSPI2 */ + +#if defined(FMC_BANK1) +#define __HAL_RCC_FMC_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB3SMENR, RCC_AHB3SMENR_FMCSMEN) == RESET) +#endif /* FMC_BANK1 */ + +/** + * @} + */ + +/** @defgroup RCC_APB1_Clock_Sleep_Enable_Disable_Status APB1 Peripheral Clock Sleep Enabled or Disabled Status + * @brief Check whether the APB1 peripheral clock during Low Power (Sleep) mode is enabled or not. + * @note Peripheral clock gating in SLEEP mode can be used to further reduce + * power consumption. + * @note After wakeup from SLEEP mode, the peripheral clock is enabled again. + * @note By default, all peripheral clocks are enabled during SLEEP mode. + * @{ + */ + +#define __HAL_RCC_TIM2_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM2SMEN) != RESET) + +#if defined(TIM3) +#define __HAL_RCC_TIM3_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM3SMEN) != RESET) +#endif /* TIM3 */ + +#if defined(TIM4) +#define __HAL_RCC_TIM4_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM4SMEN) != RESET) +#endif /* TIM4 */ + +#if defined(TIM5) +#define __HAL_RCC_TIM5_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM5SMEN) != RESET) +#endif /* TIM5 */ + +#define __HAL_RCC_TIM6_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM6SMEN) != RESET) + +#define __HAL_RCC_TIM7_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM7SMEN) != RESET) + +#if defined(LCD) +#define __HAL_RCC_LCD_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_LCDSMEN) != RESET) +#endif /* LCD */ + +#if defined(RCC_APB1SMENR1_RTCAPBSMEN) +#define __HAL_RCC_RTCAPB_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_RTCAPBSMEN) != RESET) +#endif /* RCC_APB1SMENR1_RTCAPBSMEN */ + +#define __HAL_RCC_WWDG_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_WWDGSMEN) != RESET) + +#if defined(SPI2) +#define __HAL_RCC_SPI2_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_SPI2SMEN) != RESET) +#endif /* SPI2 */ + +#define __HAL_RCC_SPI3_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_SPI3SMEN) != RESET) + +#define __HAL_RCC_USART2_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_USART2SMEN) != RESET) + +#if defined(USART3) +#define __HAL_RCC_USART3_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_USART3SMEN) != RESET) +#endif /* USART3 */ + +#if defined(UART4) +#define __HAL_RCC_UART4_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_UART4SMEN) != RESET) +#endif /* UART4 */ + +#if defined(UART5) +#define __HAL_RCC_UART5_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_UART5SMEN) != RESET) +#endif /* UART5 */ + +#define __HAL_RCC_I2C1_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_I2C1SMEN) != RESET) + +#if defined(I2C2) +#define __HAL_RCC_I2C2_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_I2C2SMEN) != RESET) +#endif /* I2C2 */ + +#define __HAL_RCC_I2C3_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_I2C3SMEN) != RESET) + +#if defined(I2C4) +#define __HAL_RCC_I2C4_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR2, RCC_APB1SMENR2_I2C4SMEN) != RESET) +#endif /* I2C4 */ + +#if defined(CRS) +#define __HAL_RCC_CRS_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_CRSSMEN) != RESET) +#endif /* CRS */ + +#define __HAL_RCC_CAN1_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_CAN1SMEN) != RESET) + +#if defined(CAN2) +#define __HAL_RCC_CAN2_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_CAN2SMEN) != RESET) +#endif /* CAN2 */ + +#if defined(USB) +#define __HAL_RCC_USB_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_USBFSSMEN) != RESET) +#endif /* USB */ + +#define __HAL_RCC_PWR_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_PWRSMEN) != RESET) + +#define __HAL_RCC_DAC1_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_DAC1SMEN) != RESET) + +#define __HAL_RCC_OPAMP_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_OPAMPSMEN) != RESET) + +#define __HAL_RCC_LPTIM1_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_LPTIM1SMEN) != RESET) + +#define __HAL_RCC_LPUART1_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR2, RCC_APB1SMENR2_LPUART1SMEN) != RESET) + +#if defined(SWPMI1) +#define __HAL_RCC_SWPMI1_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR2, RCC_APB1SMENR2_SWPMI1SMEN) != RESET) +#endif /* SWPMI1 */ + +#define __HAL_RCC_LPTIM2_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR2, RCC_APB1SMENR2_LPTIM2SMEN) != RESET) + + +#define __HAL_RCC_TIM2_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM2SMEN) == RESET) + +#if defined(TIM3) +#define __HAL_RCC_TIM3_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM3SMEN) == RESET) +#endif /* TIM3 */ + +#if defined(TIM4) +#define __HAL_RCC_TIM4_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM4SMEN) == RESET) +#endif /* TIM4 */ + +#if defined(TIM5) +#define __HAL_RCC_TIM5_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM5SMEN) == RESET) +#endif /* TIM5 */ + +#define __HAL_RCC_TIM6_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM6SMEN) == RESET) + +#define __HAL_RCC_TIM7_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM7SMEN) == RESET) + +#if defined(LCD) +#define __HAL_RCC_LCD_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_LCDSMEN) == RESET) +#endif /* LCD */ + +#if defined(RCC_APB1SMENR1_RTCAPBSMEN) +#define __HAL_RCC_RTCAPB_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_RTCAPBSMEN) == RESET) +#endif /* RCC_APB1SMENR1_RTCAPBSMEN */ + +#define __HAL_RCC_WWDG_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_WWDGSMEN) == RESET) + +#if defined(SPI2) +#define __HAL_RCC_SPI2_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_SPI2SMEN) == RESET) +#endif /* SPI2 */ + +#define __HAL_RCC_SPI3_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_SPI3SMEN) == RESET) + +#define __HAL_RCC_USART2_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_USART2SMEN) == RESET) + +#if defined(USART3) +#define __HAL_RCC_USART3_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_USART3SMEN) == RESET) +#endif /* USART3 */ + +#if defined(UART4) +#define __HAL_RCC_UART4_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_UART4SMEN) == RESET) +#endif /* UART4 */ + +#if defined(UART5) +#define __HAL_RCC_UART5_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_UART5SMEN) == RESET) +#endif /* UART5 */ + +#define __HAL_RCC_I2C1_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_I2C1SMEN) == RESET) + +#if defined(I2C2) +#define __HAL_RCC_I2C2_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_I2C2SMEN) == RESET) +#endif /* I2C2 */ + +#define __HAL_RCC_I2C3_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_I2C3SMEN) == RESET) + +#if defined(I2C4) +#define __HAL_RCC_I2C4_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR2, RCC_APB1SMENR2_I2C4SMEN) == RESET) +#endif /* I2C4 */ + +#if defined(CRS) +#define __HAL_RCC_CRS_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_CRSSMEN) == RESET) +#endif /* CRS */ + +#define __HAL_RCC_CAN1_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_CAN1SMEN) == RESET) + +#if defined(CAN2) +#define __HAL_RCC_CAN2_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_CAN2SMEN) == RESET) +#endif /* CAN2 */ + +#if defined(USB) +#define __HAL_RCC_USB_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_USBFSSMEN) == RESET) +#endif /* USB */ + +#define __HAL_RCC_PWR_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_PWRSMEN) == RESET) + +#define __HAL_RCC_DAC1_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_DAC1SMEN) == RESET) + +#define __HAL_RCC_OPAMP_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_OPAMPSMEN) == RESET) + +#define __HAL_RCC_LPTIM1_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_LPTIM1SMEN) == RESET) + +#define __HAL_RCC_LPUART1_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR2, RCC_APB1SMENR2_LPUART1SMEN) == RESET) + +#if defined(SWPMI1) +#define __HAL_RCC_SWPMI1_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR2, RCC_APB1SMENR2_SWPMI1SMEN) == RESET) +#endif /* SWPMI1 */ + +#define __HAL_RCC_LPTIM2_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR2, RCC_APB1SMENR2_LPTIM2SMEN) == RESET) + +/** + * @} + */ + +/** @defgroup RCC_APB2_Clock_Sleep_Enable_Disable_Status APB2 Peripheral Clock Sleep Enabled or Disabled Status + * @brief Check whether the APB2 peripheral clock during Low Power (Sleep) mode is enabled or not. + * @note Peripheral clock gating in SLEEP mode can be used to further reduce + * power consumption. + * @note After wakeup from SLEEP mode, the peripheral clock is enabled again. + * @note By default, all peripheral clocks are enabled during SLEEP mode. + * @{ + */ + +#define __HAL_RCC_SYSCFG_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SYSCFGSMEN) != RESET) + +#if defined(SDMMC1) && defined(RCC_APB2SMENR_SDMMC1SMEN) +#define __HAL_RCC_SDMMC1_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SDMMC1SMEN) != RESET) +#endif /* SDMMC1 && RCC_APB2SMENR_SDMMC1SMEN */ + +#define __HAL_RCC_TIM1_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM1SMEN) != RESET) + +#define __HAL_RCC_SPI1_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SPI1SMEN) != RESET) + +#if defined(TIM8) +#define __HAL_RCC_TIM8_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM8SMEN) != RESET) +#endif /* TIM8 */ + +#define __HAL_RCC_USART1_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_USART1SMEN) != RESET) + +#define __HAL_RCC_TIM15_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM15SMEN) != RESET) + +#define __HAL_RCC_TIM16_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM16SMEN) != RESET) + +#if defined(TIM17) +#define __HAL_RCC_TIM17_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM17SMEN) != RESET) +#endif /* TIM17 */ + +#define __HAL_RCC_SAI1_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SAI1SMEN) != RESET) + +#if defined(SAI2) +#define __HAL_RCC_SAI2_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SAI2SMEN) != RESET) +#endif /* SAI2 */ + +#if defined(DFSDM1_Filter0) +#define __HAL_RCC_DFSDM1_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_DFSDM1SMEN) != RESET) +#endif /* DFSDM1_Filter0 */ + +#if defined(LTDC) +#define __HAL_RCC_LTDC_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_LTDCSMEN) != RESET) +#endif /* LTDC */ + +#if defined(DSI) +#define __HAL_RCC_DSI_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_DSISMEN) != RESET) +#endif /* DSI */ + + +#define __HAL_RCC_SYSCFG_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SYSCFGSMEN) == RESET) + +#if defined(SDMMC1) && defined(RCC_APB2SMENR_SDMMC1SMEN) +#define __HAL_RCC_SDMMC1_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SDMMC1SMEN) == RESET) +#endif /* SDMMC1 && RCC_APB2SMENR_SDMMC1SMEN */ + +#define __HAL_RCC_TIM1_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM1SMEN) == RESET) + +#define __HAL_RCC_SPI1_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SPI1SMEN) == RESET) + +#if defined(TIM8) +#define __HAL_RCC_TIM8_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM8SMEN) == RESET) +#endif /* TIM8 */ + +#define __HAL_RCC_USART1_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_USART1SMEN) == RESET) + +#define __HAL_RCC_TIM15_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM15SMEN) == RESET) + +#define __HAL_RCC_TIM16_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM16SMEN) == RESET) + +#if defined(TIM17) +#define __HAL_RCC_TIM17_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM17SMEN) == RESET) +#endif /* TIM17 */ + +#define __HAL_RCC_SAI1_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SAI1SMEN) == RESET) + +#if defined(SAI2) +#define __HAL_RCC_SAI2_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SAI2SMEN) == RESET) +#endif /* SAI2 */ + +#if defined(DFSDM1_Filter0) +#define __HAL_RCC_DFSDM1_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_DFSDM1SMEN) == RESET) +#endif /* DFSDM1_Filter0 */ + +#if defined(LTDC) +#define __HAL_RCC_LTDC_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_LTDCSMEN) == RESET) +#endif /* LTDC */ + +#if defined(DSI) +#define __HAL_RCC_DSI_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_DSISMEN) == RESET) +#endif /* DSI */ + +/** + * @} + */ + +/** @defgroup RCC_Backup_Domain_Reset RCC Backup Domain Reset + * @{ + */ + +/** @brief Macros to force or release the Backup domain reset. + * @note This function resets the RTC peripheral (including the backup registers) + * and the RTC clock source selection in RCC_CSR register. + * @note The BKPSRAM is not affected by this reset. + * @retval None + */ +#define __HAL_RCC_BACKUPRESET_FORCE() SET_BIT(RCC->BDCR, RCC_BDCR_BDRST) + +#define __HAL_RCC_BACKUPRESET_RELEASE() CLEAR_BIT(RCC->BDCR, RCC_BDCR_BDRST) + +/** + * @} + */ + +/** @defgroup RCC_RTC_Clock_Configuration RCC RTC Clock Configuration + * @{ + */ + +/** @brief Macros to enable or disable the RTC clock. + * @note As the RTC is in the Backup domain and write access is denied to + * this domain after reset, you have to enable write access using + * HAL_PWR_EnableBkUpAccess() function before to configure the RTC + * (to be done once after reset). + * @note These macros must be used after the RTC clock source was selected. + * @retval None + */ +#define __HAL_RCC_RTC_ENABLE() SET_BIT(RCC->BDCR, RCC_BDCR_RTCEN) + +#define __HAL_RCC_RTC_DISABLE() CLEAR_BIT(RCC->BDCR, RCC_BDCR_RTCEN) + +/** + * @} + */ + +/** @brief Macros to enable or disable the Internal High Speed 16MHz oscillator (HSI). + * @note The HSI is stopped by hardware when entering STOP and STANDBY modes. + * It is used (enabled by hardware) as system clock source after startup + * from Reset, wakeup from STOP and STANDBY mode, or in case of failure + * of the HSE used directly or indirectly as system clock (if the Clock + * Security System CSS is enabled). + * @note HSI can not be stopped if it is used as system clock source. In this case, + * you have to select another source of the system clock then stop the HSI. + * @note After enabling the HSI, the application software should wait on HSIRDY + * flag to be set indicating that HSI clock is stable and can be used as + * system clock source. + * This parameter can be: ENABLE or DISABLE. + * @note When the HSI is stopped, HSIRDY flag goes low after 6 HSI oscillator + * clock cycles. + * @retval None + */ +#define __HAL_RCC_HSI_ENABLE() SET_BIT(RCC->CR, RCC_CR_HSION) + +#define __HAL_RCC_HSI_DISABLE() CLEAR_BIT(RCC->CR, RCC_CR_HSION) + +/** @brief Macro to adjust the Internal High Speed 16MHz oscillator (HSI) calibration value. + * @note The calibration is used to compensate for the variations in voltage + * and temperature that influence the frequency of the internal HSI RC. + * @param __HSICALIBRATIONVALUE__ specifies the calibration trimming value + * (default is RCC_HSICALIBRATION_DEFAULT). + * This parameter must be a number between 0 and 0x1F (STM32L43x/STM32L44x/STM32L47x/STM32L48x) or 0x7F (for other devices). + * @retval None + */ +#define __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(__HSICALIBRATIONVALUE__) \ + MODIFY_REG(RCC->ICSCR, RCC_ICSCR_HSITRIM, (__HSICALIBRATIONVALUE__) << RCC_ICSCR_HSITRIM_Pos) + +/** + * @brief Macros to enable or disable the wakeup the Internal High Speed oscillator (HSI) + * in parallel to the Internal Multi Speed oscillator (MSI) used at system wakeup. + * @note The enable of this function has not effect on the HSION bit. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +#define __HAL_RCC_HSIAUTOMATIC_START_ENABLE() SET_BIT(RCC->CR, RCC_CR_HSIASFS) + +#define __HAL_RCC_HSIAUTOMATIC_START_DISABLE() CLEAR_BIT(RCC->CR, RCC_CR_HSIASFS) + +/** + * @brief Macros to enable or disable the force of the Internal High Speed oscillator (HSI) + * in STOP mode to be quickly available as kernel clock for USARTs and I2Cs. + * @note Keeping the HSI ON in STOP mode allows to avoid slowing down the communication + * speed because of the HSI startup time. + * @note The enable of this function has not effect on the HSION bit. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +#define __HAL_RCC_HSISTOP_ENABLE() SET_BIT(RCC->CR, RCC_CR_HSIKERON) + +#define __HAL_RCC_HSISTOP_DISABLE() CLEAR_BIT(RCC->CR, RCC_CR_HSIKERON) + +/** + * @brief Macros to enable or disable the Internal Multi Speed oscillator (MSI). + * @note The MSI is stopped by hardware when entering STOP and STANDBY modes. + * It is used (enabled by hardware) as system clock source after + * startup from Reset, wakeup from STOP and STANDBY mode, or in case + * of failure of the HSE used directly or indirectly as system clock + * (if the Clock Security System CSS is enabled). + * @note MSI can not be stopped if it is used as system clock source. + * In this case, you have to select another source of the system + * clock then stop the MSI. + * @note After enabling the MSI, the application software should wait on + * MSIRDY flag to be set indicating that MSI clock is stable and can + * be used as system clock source. + * @note When the MSI is stopped, MSIRDY flag goes low after 6 MSI oscillator + * clock cycles. + * @retval None + */ +#define __HAL_RCC_MSI_ENABLE() SET_BIT(RCC->CR, RCC_CR_MSION) + +#define __HAL_RCC_MSI_DISABLE() CLEAR_BIT(RCC->CR, RCC_CR_MSION) + +/** @brief Macro Adjusts the Internal Multi Speed oscillator (MSI) calibration value. + * @note The calibration is used to compensate for the variations in voltage + * and temperature that influence the frequency of the internal MSI RC. + * Refer to the Application Note AN3300 for more details on how to + * calibrate the MSI. + * @param __MSICALIBRATIONVALUE__ specifies the calibration trimming value + * (default is RCC_MSICALIBRATION_DEFAULT). + * This parameter must be a number between 0 and 255. + * @retval None + */ +#define __HAL_RCC_MSI_CALIBRATIONVALUE_ADJUST(__MSICALIBRATIONVALUE__) \ + MODIFY_REG(RCC->ICSCR, RCC_ICSCR_MSITRIM, (__MSICALIBRATIONVALUE__) << RCC_ICSCR_MSITRIM_Pos) + +/** + * @brief Macro configures the Internal Multi Speed oscillator (MSI) clock range in run mode + * @note After restart from Reset , the MSI clock is around 4 MHz. + * After stop the startup clock can be MSI (at any of its possible + * frequencies, the one that was used before entering stop mode) or HSI. + * After Standby its frequency can be selected between 4 possible values + * (1, 2, 4 or 8 MHz). + * @note MSIRANGE can be modified when MSI is OFF (MSION=0) or when MSI is ready + * (MSIRDY=1). + * @note The MSI clock range after reset can be modified on the fly. + * @param __MSIRANGEVALUE__ specifies the MSI clock range. + * This parameter must be one of the following values: + * @arg @ref RCC_MSIRANGE_0 MSI clock is around 100 KHz + * @arg @ref RCC_MSIRANGE_1 MSI clock is around 200 KHz + * @arg @ref RCC_MSIRANGE_2 MSI clock is around 400 KHz + * @arg @ref RCC_MSIRANGE_3 MSI clock is around 800 KHz + * @arg @ref RCC_MSIRANGE_4 MSI clock is around 1 MHz + * @arg @ref RCC_MSIRANGE_5 MSI clock is around 2 MHz + * @arg @ref RCC_MSIRANGE_6 MSI clock is around 4 MHz (default after Reset) + * @arg @ref RCC_MSIRANGE_7 MSI clock is around 8 MHz + * @arg @ref RCC_MSIRANGE_8 MSI clock is around 16 MHz + * @arg @ref RCC_MSIRANGE_9 MSI clock is around 24 MHz + * @arg @ref RCC_MSIRANGE_10 MSI clock is around 32 MHz + * @arg @ref RCC_MSIRANGE_11 MSI clock is around 48 MHz + * @retval None + */ +#define __HAL_RCC_MSI_RANGE_CONFIG(__MSIRANGEVALUE__) \ + do { \ + SET_BIT(RCC->CR, RCC_CR_MSIRGSEL); \ + MODIFY_REG(RCC->CR, RCC_CR_MSIRANGE, (__MSIRANGEVALUE__)); \ + } while(0) + +/** + * @brief Macro configures the Internal Multi Speed oscillator (MSI) clock range after Standby mode + * After Standby its frequency can be selected between 4 possible values (1, 2, 4 or 8 MHz). + * @param __MSIRANGEVALUE__ specifies the MSI clock range. + * This parameter must be one of the following values: + * @arg @ref RCC_MSIRANGE_4 MSI clock is around 1 MHz + * @arg @ref RCC_MSIRANGE_5 MSI clock is around 2 MHz + * @arg @ref RCC_MSIRANGE_6 MSI clock is around 4 MHz (default after Reset) + * @arg @ref RCC_MSIRANGE_7 MSI clock is around 8 MHz + * @retval None + */ +#define __HAL_RCC_MSI_STANDBY_RANGE_CONFIG(__MSIRANGEVALUE__) \ + MODIFY_REG(RCC->CSR, RCC_CSR_MSISRANGE, (__MSIRANGEVALUE__) << 4U) + +/** @brief Macro to get the Internal Multi Speed oscillator (MSI) clock range in run mode + * @retval MSI clock range. + * This parameter must be one of the following values: + * @arg @ref RCC_MSIRANGE_0 MSI clock is around 100 KHz + * @arg @ref RCC_MSIRANGE_1 MSI clock is around 200 KHz + * @arg @ref RCC_MSIRANGE_2 MSI clock is around 400 KHz + * @arg @ref RCC_MSIRANGE_3 MSI clock is around 800 KHz + * @arg @ref RCC_MSIRANGE_4 MSI clock is around 1 MHz + * @arg @ref RCC_MSIRANGE_5 MSI clock is around 2 MHz + * @arg @ref RCC_MSIRANGE_6 MSI clock is around 4 MHz (default after Reset) + * @arg @ref RCC_MSIRANGE_7 MSI clock is around 8 MHz + * @arg @ref RCC_MSIRANGE_8 MSI clock is around 16 MHz + * @arg @ref RCC_MSIRANGE_9 MSI clock is around 24 MHz + * @arg @ref RCC_MSIRANGE_10 MSI clock is around 32 MHz + * @arg @ref RCC_MSIRANGE_11 MSI clock is around 48 MHz + */ +#define __HAL_RCC_GET_MSI_RANGE() \ + ((READ_BIT(RCC->CR, RCC_CR_MSIRGSEL) != RESET) ? \ + READ_BIT(RCC->CR, RCC_CR_MSIRANGE) : \ + READ_BIT(RCC->CSR, RCC_CSR_MSISRANGE) >> 4U) + +/** @brief Macros to enable or disable the Internal Low Speed oscillator (LSI). + * @note After enabling the LSI, the application software should wait on + * LSIRDY flag to be set indicating that LSI clock is stable and can + * be used to clock the IWDG and/or the RTC. + * @note LSI can not be disabled if the IWDG is running. + * @note When the LSI is stopped, LSIRDY flag goes low after 6 LSI oscillator + * clock cycles. + * @retval None + */ +#define __HAL_RCC_LSI_ENABLE() SET_BIT(RCC->CSR, RCC_CSR_LSION) + +#define __HAL_RCC_LSI_DISABLE() CLEAR_BIT(RCC->CSR, RCC_CSR_LSION) + +/** + * @brief Macro to configure the External High Speed oscillator (HSE). + * @note Transition HSE Bypass to HSE On and HSE On to HSE Bypass are not + * supported by this macro. User should request a transition to HSE Off + * first and then HSE On or HSE Bypass. + * @note After enabling the HSE (RCC_HSE_ON or RCC_HSE_Bypass), the application + * software should wait on HSERDY flag to be set indicating that HSE clock + * is stable and can be used to clock the PLL and/or system clock. + * @note HSE state can not be changed if it is used directly or through the + * PLL as system clock. In this case, you have to select another source + * of the system clock then change the HSE state (ex. disable it). + * @note The HSE is stopped by hardware when entering STOP and STANDBY modes. + * @note This function reset the CSSON bit, so if the clock security system(CSS) + * was previously enabled you have to enable it again after calling this + * function. + * @param __STATE__ specifies the new state of the HSE. + * This parameter can be one of the following values: + * @arg @ref RCC_HSE_OFF Turn OFF the HSE oscillator, HSERDY flag goes low after + * 6 HSE oscillator clock cycles. + * @arg @ref RCC_HSE_ON Turn ON the HSE oscillator. + * @arg @ref RCC_HSE_BYPASS HSE oscillator bypassed with external clock. + * @retval None + */ +#define __HAL_RCC_HSE_CONFIG(__STATE__) \ + do { \ + if((__STATE__) == RCC_HSE_ON) \ + { \ + SET_BIT(RCC->CR, RCC_CR_HSEON); \ + } \ + else if((__STATE__) == RCC_HSE_BYPASS) \ + { \ + SET_BIT(RCC->CR, RCC_CR_HSEBYP); \ + SET_BIT(RCC->CR, RCC_CR_HSEON); \ + } \ + else \ + { \ + CLEAR_BIT(RCC->CR, RCC_CR_HSEON); \ + CLEAR_BIT(RCC->CR, RCC_CR_HSEBYP); \ + } \ + } while(0) + +/** + * @brief Macro to configure the External Low Speed oscillator (LSE). + * @note Transitions LSE Bypass to LSE On and LSE On to LSE Bypass are not + * supported by this macro. User should request a transition to LSE Off + * first and then LSE On or LSE Bypass. + * @note As the LSE is in the Backup domain and write access is denied to + * this domain after reset, you have to enable write access using + * HAL_PWR_EnableBkUpAccess() function before to configure the LSE + * (to be done once after reset). + * @note After enabling the LSE (RCC_LSE_ON or RCC_LSE_BYPASS), the application + * software should wait on LSERDY flag to be set indicating that LSE clock + * is stable and can be used to clock the RTC. + * @param __STATE__ specifies the new state of the LSE. + * This parameter can be one of the following values: + * @arg @ref RCC_LSE_OFF Turn OFF the LSE oscillator, LSERDY flag goes low after + * 6 LSE oscillator clock cycles. + * @arg @ref RCC_LSE_ON Turn ON the LSE oscillator. + * @arg @ref RCC_LSE_BYPASS LSE oscillator bypassed with external clock. + * @retval None + */ +#define __HAL_RCC_LSE_CONFIG(__STATE__) \ + do { \ + if((__STATE__) == RCC_LSE_ON) \ + { \ + SET_BIT(RCC->BDCR, RCC_BDCR_LSEON); \ + } \ + else if((__STATE__) == RCC_LSE_BYPASS) \ + { \ + SET_BIT(RCC->BDCR, RCC_BDCR_LSEBYP); \ + SET_BIT(RCC->BDCR, RCC_BDCR_LSEON); \ + } \ + else \ + { \ + CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSEON); \ + CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSEBYP); \ + } \ + } while(0) + +#if defined(RCC_HSI48_SUPPORT) + +/** @brief Macros to enable or disable the Internal High Speed 48MHz oscillator (HSI48). + * @note The HSI48 is stopped by hardware when entering STOP and STANDBY modes. + * @note After enabling the HSI48, the application software should wait on HSI48RDY + * flag to be set indicating that HSI48 clock is stable. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +#define __HAL_RCC_HSI48_ENABLE() SET_BIT(RCC->CRRCR, RCC_CRRCR_HSI48ON) + +#define __HAL_RCC_HSI48_DISABLE() CLEAR_BIT(RCC->CRRCR, RCC_CRRCR_HSI48ON) + +#endif /* RCC_HSI48_SUPPORT */ + +/** @brief Macros to configure the RTC clock (RTCCLK). + * @note As the RTC clock configuration bits are in the Backup domain and write + * access is denied to this domain after reset, you have to enable write + * access using the Power Backup Access macro before to configure + * the RTC clock source (to be done once after reset). + * @note Once the RTC clock is configured it cannot be changed unless the + * Backup domain is reset using __HAL_RCC_BACKUPRESET_FORCE() macro, or by + * a Power On Reset (POR). + * + * @param __RTC_CLKSOURCE__ specifies the RTC clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_RTCCLKSOURCE_NONE No clock selected as RTC clock. + * @arg @ref RCC_RTCCLKSOURCE_LSE LSE selected as RTC clock. + * @arg @ref RCC_RTCCLKSOURCE_LSI LSI selected as RTC clock. + * @arg @ref RCC_RTCCLKSOURCE_HSE_DIV32 HSE clock divided by 32 selected + * + * @note If the LSE or LSI is used as RTC clock source, the RTC continues to + * work in STOP and STANDBY modes, and can be used as wakeup source. + * However, when the HSE clock is used as RTC clock source, the RTC + * cannot be used in STOP and STANDBY modes. + * @note The maximum input clock frequency for RTC is 1MHz (when using HSE as + * RTC clock source). + * @retval None + */ +#define __HAL_RCC_RTC_CONFIG(__RTC_CLKSOURCE__) \ + MODIFY_REG( RCC->BDCR, RCC_BDCR_RTCSEL, (__RTC_CLKSOURCE__)) + + +/** @brief Macro to get the RTC clock source. + * @retval The returned value can be one of the following: + * @arg @ref RCC_RTCCLKSOURCE_NONE No clock selected as RTC clock. + * @arg @ref RCC_RTCCLKSOURCE_LSE LSE selected as RTC clock. + * @arg @ref RCC_RTCCLKSOURCE_LSI LSI selected as RTC clock. + * @arg @ref RCC_RTCCLKSOURCE_HSE_DIV32 HSE clock divided by 32 selected + */ +#define __HAL_RCC_GET_RTC_SOURCE() (READ_BIT(RCC->BDCR, RCC_BDCR_RTCSEL)) + +/** @brief Macros to enable or disable the main PLL. + * @note After enabling the main PLL, the application software should wait on + * PLLRDY flag to be set indicating that PLL clock is stable and can + * be used as system clock source. + * @note The main PLL can not be disabled if it is used as system clock source + * @note The main PLL is disabled by hardware when entering STOP and STANDBY modes. + * @retval None + */ +#define __HAL_RCC_PLL_ENABLE() SET_BIT(RCC->CR, RCC_CR_PLLON) + +#define __HAL_RCC_PLL_DISABLE() CLEAR_BIT(RCC->CR, RCC_CR_PLLON) + +/** @brief Macro to configure the PLL clock source. + * @note This function must be used only when the main PLL is disabled. + * @param __PLLSOURCE__ specifies the PLL entry clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_PLLSOURCE_NONE No clock selected as PLL clock entry + * @arg @ref RCC_PLLSOURCE_MSI MSI oscillator clock selected as PLL clock entry + * @arg @ref RCC_PLLSOURCE_HSI HSI oscillator clock selected as PLL clock entry + * @arg @ref RCC_PLLSOURCE_HSE HSE oscillator clock selected as PLL clock entry + * @note This clock source is common for the main PLL and audio PLL (PLLSAI1 and PLLSAI2). + * @retval None + * + */ +#define __HAL_RCC_PLL_PLLSOURCE_CONFIG(__PLLSOURCE__) \ + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, (__PLLSOURCE__)) + +/** @brief Macro to configure the PLL source division factor M. + * @note This function must be used only when the main PLL is disabled. + * @param __PLLM__ specifies the division factor for PLL VCO input clock + * This parameter must be a number between Min_Data = 1 and Max_Data = 16 on STM32L4Rx/STM32L4Sx devices. + * This parameter must be a number between Min_Data = 1 and Max_Data = 8 on other devices. + * @note You have to set the PLLM parameter correctly to ensure that the VCO input + * frequency ranges from 4 to 16 MHz. It is recommended to select a frequency + * of 16 MHz to limit PLL jitter. + * @retval None + * + */ +#define __HAL_RCC_PLL_PLLM_CONFIG(__PLLM__) \ + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLM, ((__PLLM__) - 1) << 4U) + +/** + * @brief Macro to configure the main PLL clock source, multiplication and division factors. + * @note This function must be used only when the main PLL is disabled. + * + * @param __PLLSOURCE__ specifies the PLL entry clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_PLLSOURCE_NONE No clock selected as PLL clock entry + * @arg @ref RCC_PLLSOURCE_MSI MSI oscillator clock selected as PLL clock entry + * @arg @ref RCC_PLLSOURCE_HSI HSI oscillator clock selected as PLL clock entry + * @arg @ref RCC_PLLSOURCE_HSE HSE oscillator clock selected as PLL clock entry + * @note This clock source is common for the main PLL and audio PLL (PLLSAI1 and PLLSAI2). + * + * @param __PLLM__ specifies the division factor for PLL VCO input clock. + * This parameter must be a number between Min_Data = 1 and Max_Data = 16 on STM32L4Rx/STM32L4Sx devices. + * This parameter must be a number between Min_Data = 1 and Max_Data = 8 on other devices. + * @note You have to set the PLLM parameter correctly to ensure that the VCO input + * frequency ranges from 4 to 16 MHz. It is recommended to select a frequency + * of 16 MHz to limit PLL jitter. + * + * @param __PLLN__ specifies the multiplication factor for PLL VCO output clock. + * This parameter must be a number between 8 and 86. + * @note You have to set the PLLN parameter correctly to ensure that the VCO + * output frequency is between 64 and 344 MHz. + * + * @param __PLLP__ specifies the division factor for SAI clock. + * This parameter must be a number in the range (7 or 17) for STM32L47x/STM32L48x + * else (2 to 31). + * + * @param __PLLQ__ specifies the division factor for OTG FS, SDMMC1 and RNG clocks. + * This parameter must be in the range (2, 4, 6 or 8). + * @note If the USB OTG FS is used in your application, you have to set the + * PLLQ parameter correctly to have 48 MHz clock for the USB. However, + * the SDMMC1 and RNG need a frequency lower than or equal to 48 MHz to work + * correctly. + * @param __PLLR__ specifies the division factor for the main system clock. + * @note You have to set the PLLR parameter correctly to not exceed 80MHZ. + * This parameter must be in the range (2, 4, 6 or 8). + * @retval None + */ +#if defined(RCC_PLLP_DIV_2_31_SUPPORT) + +#define __HAL_RCC_PLL_CONFIG(__PLLSOURCE__, __PLLM__, __PLLN__, __PLLP__, __PLLQ__,__PLLR__ ) \ + (RCC->PLLCFGR = (uint32_t)(((__PLLM__) - 1U) << 4U) | (uint32_t)((__PLLN__) << 8U) | \ + (__PLLSOURCE__) | (uint32_t)((((__PLLQ__) >> 1U) - 1U) << 21U) | (uint32_t)((((__PLLR__) >> 1U) - 1U) << 25U) | \ + ((uint32_t)(__PLLP__) << 27U)) +#else + +#define __HAL_RCC_PLL_CONFIG(__PLLSOURCE__, __PLLM__, __PLLN__, __PLLP__, __PLLQ__,__PLLR__ ) \ + (RCC->PLLCFGR = (uint32_t)(((__PLLM__) - 1U) << 4U) | (uint32_t)((__PLLN__) << 8U) | \ + (uint32_t)(((__PLLP__) >> 4U ) << 17U) | \ + (__PLLSOURCE__) | (uint32_t)((((__PLLQ__) >> 1U) - 1U) << 21U) | (uint32_t)((((__PLLR__) >> 1U) - 1U) << 25U)) + +#endif /* RCC_PLLP_DIV_2_31_SUPPORT */ + +/** @brief Macro to get the oscillator used as PLL clock source. + * @retval The oscillator used as PLL clock source. The returned value can be one + * of the following: + * - RCC_PLLSOURCE_NONE: No oscillator is used as PLL clock source. + * - RCC_PLLSOURCE_MSI: MSI oscillator is used as PLL clock source. + * - RCC_PLLSOURCE_HSI: HSI oscillator is used as PLL clock source. + * - RCC_PLLSOURCE_HSE: HSE oscillator is used as PLL clock source. + */ +#define __HAL_RCC_GET_PLL_OSCSOURCE() (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC)) + +/** + * @brief Enable or disable each clock output (RCC_PLL_SYSCLK, RCC_PLL_48M1CLK, RCC_PLL_SAI3CLK) + * @note Enabling/disabling clock outputs RCC_PLL_SAI3CLK and RCC_PLL_48M1CLK can be done at anytime + * without the need to stop the PLL in order to save power. But RCC_PLL_SYSCLK cannot + * be stopped if used as System Clock. + * @param __PLLCLOCKOUT__ specifies the PLL clock to be output. + * This parameter can be one or a combination of the following values: + * @arg @ref RCC_PLL_SAI3CLK This clock is used to generate an accurate clock to achieve + * high-quality audio performance on SAI interface in case. + * @arg @ref RCC_PLL_48M1CLK This Clock is used to generate the clock for the USB OTG FS (48 MHz), + * the random analog generator (<=48 MHz) and the SDMMC1 (<= 48 MHz). + * @arg @ref RCC_PLL_SYSCLK This Clock is used to generate the high speed system clock (up to 80MHz) + * @retval None + */ +#define __HAL_RCC_PLLCLKOUT_ENABLE(__PLLCLOCKOUT__) SET_BIT(RCC->PLLCFGR, (__PLLCLOCKOUT__)) + +#define __HAL_RCC_PLLCLKOUT_DISABLE(__PLLCLOCKOUT__) CLEAR_BIT(RCC->PLLCFGR, (__PLLCLOCKOUT__)) + +/** + * @brief Get clock output enable status (RCC_PLL_SYSCLK, RCC_PLL_48M1CLK, RCC_PLL_SAI3CLK) + * @param __PLLCLOCKOUT__ specifies the output PLL clock to be checked. + * This parameter can be one of the following values: + * @arg @ref RCC_PLL_SAI3CLK This clock is used to generate an accurate clock to achieve + * high-quality audio performance on SAI interface in case. + * @arg @ref RCC_PLL_48M1CLK This Clock is used to generate the clock for the USB OTG FS (48 MHz), + * the random analog generator (<=48 MHz) and the SDMMC1 (<= 48 MHz). + * @arg @ref RCC_PLL_SYSCLK This Clock is used to generate the high speed system clock (up to 80MHz) + * @retval SET / RESET + */ +#define __HAL_RCC_GET_PLLCLKOUT_CONFIG(__PLLCLOCKOUT__) READ_BIT(RCC->PLLCFGR, (__PLLCLOCKOUT__)) + +/** + * @brief Macro to configure the system clock source. + * @param __SYSCLKSOURCE__ specifies the system clock source. + * This parameter can be one of the following values: + * - RCC_SYSCLKSOURCE_MSI: MSI oscillator is used as system clock source. + * - RCC_SYSCLKSOURCE_HSI: HSI oscillator is used as system clock source. + * - RCC_SYSCLKSOURCE_HSE: HSE oscillator is used as system clock source. + * - RCC_SYSCLKSOURCE_PLLCLK: PLL output is used as system clock source. + * @retval None + */ +#define __HAL_RCC_SYSCLK_CONFIG(__SYSCLKSOURCE__) \ + MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, (__SYSCLKSOURCE__)) + +/** @brief Macro to get the clock source used as system clock. + * @retval The clock source used as system clock. The returned value can be one + * of the following: + * - RCC_SYSCLKSOURCE_STATUS_MSI: MSI used as system clock. + * - RCC_SYSCLKSOURCE_STATUS_HSI: HSI used as system clock. + * - RCC_SYSCLKSOURCE_STATUS_HSE: HSE used as system clock. + * - RCC_SYSCLKSOURCE_STATUS_PLLCLK: PLL used as system clock. + */ +#define __HAL_RCC_GET_SYSCLK_SOURCE() (READ_BIT(RCC->CFGR, RCC_CFGR_SWS)) + +/** + * @brief Macro to configure the External Low Speed oscillator (LSE) drive capability. + * @note As the LSE is in the Backup domain and write access is denied to + * this domain after reset, you have to enable write access using + * HAL_PWR_EnableBkUpAccess() function before to configure the LSE + * (to be done once after reset). + * @param __LSEDRIVE__ specifies the new state of the LSE drive capability. + * This parameter can be one of the following values: + * @arg @ref RCC_LSEDRIVE_LOW LSE oscillator low drive capability. + * @arg @ref RCC_LSEDRIVE_MEDIUMLOW LSE oscillator medium low drive capability. + * @arg @ref RCC_LSEDRIVE_MEDIUMHIGH LSE oscillator medium high drive capability. + * @arg @ref RCC_LSEDRIVE_HIGH LSE oscillator high drive capability. + * @retval None + */ +#define __HAL_RCC_LSEDRIVE_CONFIG(__LSEDRIVE__) \ + MODIFY_REG(RCC->BDCR, RCC_BDCR_LSEDRV, (__LSEDRIVE__)) + +/** + * @brief Macro to configure the wake up from stop clock. + * @param __STOPWUCLK__ specifies the clock source used after wake up from stop. + * This parameter can be one of the following values: + * @arg @ref RCC_STOP_WAKEUPCLOCK_MSI MSI selected as system clock source + * @arg @ref RCC_STOP_WAKEUPCLOCK_HSI HSI selected as system clock source + * @retval None + */ +#define __HAL_RCC_WAKEUPSTOP_CLK_CONFIG(__STOPWUCLK__) \ + MODIFY_REG(RCC->CFGR, RCC_CFGR_STOPWUCK, (__STOPWUCLK__)) + + +/** @brief Macro to configure the MCO clock. + * @param __MCOCLKSOURCE__ specifies the MCO clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_MCO1SOURCE_NOCLOCK MCO output disabled + * @arg @ref RCC_MCO1SOURCE_SYSCLK System clock selected as MCO source + * @arg @ref RCC_MCO1SOURCE_MSI MSI clock selected as MCO source + * @arg @ref RCC_MCO1SOURCE_HSI HSI clock selected as MCO source + * @arg @ref RCC_MCO1SOURCE_HSE HSE clock selected as MCO sourcee + * @arg @ref RCC_MCO1SOURCE_PLLCLK Main PLL clock selected as MCO source + * @arg @ref RCC_MCO1SOURCE_LSI LSI clock selected as MCO source + * @arg @ref RCC_MCO1SOURCE_LSE LSE clock selected as MCO source + @if STM32L443xx + * @arg @ref RCC_MCO1SOURCE_HSI48 HSI48 clock selected as MCO source for devices with HSI48 + @endif + @if STM32L4A6xx + * @arg @ref RCC_MCO1SOURCE_HSI48 HSI48 clock selected as MCO source for devices with HSI48 + @endif + * @param __MCODIV__ specifies the MCO clock prescaler. + * This parameter can be one of the following values: + * @arg @ref RCC_MCODIV_1 MCO clock source is divided by 1 + * @arg @ref RCC_MCODIV_2 MCO clock source is divided by 2 + * @arg @ref RCC_MCODIV_4 MCO clock source is divided by 4 + * @arg @ref RCC_MCODIV_8 MCO clock source is divided by 8 + * @arg @ref RCC_MCODIV_16 MCO clock source is divided by 16 + */ +#define __HAL_RCC_MCO1_CONFIG(__MCOCLKSOURCE__, __MCODIV__) \ + MODIFY_REG(RCC->CFGR, (RCC_CFGR_MCOSEL | RCC_CFGR_MCOPRE), ((__MCOCLKSOURCE__) | (__MCODIV__))) + +/** @defgroup RCC_Flags_Interrupts_Management Flags Interrupts Management + * @brief macros to manage the specified RCC Flags and interrupts. + * @{ + */ + +/** @brief Enable RCC interrupt(s). + * @param __INTERRUPT__ specifies the RCC interrupt source(s) to be enabled. + * This parameter can be any combination of the following values: + * @arg @ref RCC_IT_LSIRDY LSI ready interrupt + * @arg @ref RCC_IT_LSERDY LSE ready interrupt + * @arg @ref RCC_IT_MSIRDY HSI ready interrupt + * @arg @ref RCC_IT_HSIRDY HSI ready interrupt + * @arg @ref RCC_IT_HSERDY HSE ready interrupt + * @arg @ref RCC_IT_PLLRDY Main PLL ready interrupt + * @arg @ref RCC_IT_PLLSAI1RDY PLLSAI1 ready interrupt + * @arg @ref RCC_IT_PLLSAI2RDY PLLSAI2 ready interrupt for devices with PLLSAI2 + * @arg @ref RCC_IT_LSECSS LSE Clock security system interrupt + @if STM32L443xx + * @arg @ref RCC_IT_HSI48RDY HSI48 ready interrupt for devices with HSI48 + @endif + @if STM32L4A6xx + * @arg @ref RCC_IT_HSI48RDY HSI48 ready interrupt for devices with HSI48 + @endif + * @retval None + */ +#define __HAL_RCC_ENABLE_IT(__INTERRUPT__) SET_BIT(RCC->CIER, (__INTERRUPT__)) + +/** @brief Disable RCC interrupt(s). + * @param __INTERRUPT__ specifies the RCC interrupt source(s) to be disabled. + * This parameter can be any combination of the following values: + * @arg @ref RCC_IT_LSIRDY LSI ready interrupt + * @arg @ref RCC_IT_LSERDY LSE ready interrupt + * @arg @ref RCC_IT_MSIRDY HSI ready interrupt + * @arg @ref RCC_IT_HSIRDY HSI ready interrupt + * @arg @ref RCC_IT_HSERDY HSE ready interrupt + * @arg @ref RCC_IT_PLLRDY Main PLL ready interrupt + * @arg @ref RCC_IT_PLLSAI1RDY PLLSAI1 ready interrupt + * @arg @ref RCC_IT_PLLSAI2RDY PLLSAI2 ready interrupt for devices with PLLSAI2 + * @arg @ref RCC_IT_LSECSS LSE Clock security system interrupt + @if STM32L443xx + * @arg @ref RCC_IT_HSI48RDY HSI48 ready interrupt for devices with HSI48 + @endif + @if STM32L4A6xx + * @arg @ref RCC_IT_HSI48RDY HSI48 ready interrupt for devices with HSI48 + @endif + * @retval None + */ +#define __HAL_RCC_DISABLE_IT(__INTERRUPT__) CLEAR_BIT(RCC->CIER, (__INTERRUPT__)) + +/** @brief Clear the RCC's interrupt pending bits. + * @param __INTERRUPT__ specifies the interrupt pending bit to clear. + * This parameter can be any combination of the following values: + * @arg @ref RCC_IT_LSIRDY LSI ready interrupt + * @arg @ref RCC_IT_LSERDY LSE ready interrupt + * @arg @ref RCC_IT_MSIRDY MSI ready interrupt + * @arg @ref RCC_IT_HSIRDY HSI ready interrupt + * @arg @ref RCC_IT_HSERDY HSE ready interrupt + * @arg @ref RCC_IT_PLLRDY Main PLL ready interrupt + * @arg @ref RCC_IT_PLLSAI1RDY PLLSAI1 ready interrupt + * @arg @ref RCC_IT_PLLSAI2RDY PLLSAI2 ready interrupt for devices with PLLSAI2 + * @arg @ref RCC_IT_CSS HSE Clock security system interrupt + * @arg @ref RCC_IT_LSECSS LSE Clock security system interrupt + @if STM32L443xx + * @arg @ref RCC_IT_HSI48RDY HSI48 ready interrupt for devices with HSI48 + @endif + @if STM32L4A6xx + * @arg @ref RCC_IT_HSI48RDY HSI48 ready interrupt for devices with HSI48 + @endif + * @retval None + */ +#define __HAL_RCC_CLEAR_IT(__INTERRUPT__) WRITE_REG(RCC->CICR, (__INTERRUPT__)) + +/** @brief Check whether the RCC interrupt has occurred or not. + * @param __INTERRUPT__ specifies the RCC interrupt source to check. + * This parameter can be one of the following values: + * @arg @ref RCC_IT_LSIRDY LSI ready interrupt + * @arg @ref RCC_IT_LSERDY LSE ready interrupt + * @arg @ref RCC_IT_MSIRDY MSI ready interrupt + * @arg @ref RCC_IT_HSIRDY HSI ready interrupt + * @arg @ref RCC_IT_HSERDY HSE ready interrupt + * @arg @ref RCC_IT_PLLRDY Main PLL ready interrupt + * @arg @ref RCC_IT_PLLSAI1RDY PLLSAI1 ready interrupt + * @arg @ref RCC_IT_PLLSAI2RDY PLLSAI2 ready interrupt for devices with PLLSAI2 + * @arg @ref RCC_IT_CSS HSE Clock security system interrupt + * @arg @ref RCC_IT_LSECSS LSE Clock security system interrupt + @if STM32L443xx + * @arg @ref RCC_IT_HSI48RDY HSI48 ready interrupt for devices with HSI48 + @endif + @if STM32L4A6xx + * @arg @ref RCC_IT_HSI48RDY HSI48 ready interrupt for devices with HSI48 + @endif + * @retval The new state of __INTERRUPT__ (TRUE or FALSE). + */ +#define __HAL_RCC_GET_IT(__INTERRUPT__) (READ_BIT(RCC->CIFR, (__INTERRUPT__)) == (__INTERRUPT__)) + +/** @brief Set RMVF bit to clear the reset flags. + * The reset flags are: RCC_FLAG_FWRRST, RCC_FLAG_OBLRST, RCC_FLAG_PINRST, RCC_FLAG_BORRST, + * RCC_FLAG_SFTRST, RCC_FLAG_IWDGRST, RCC_FLAG_WWDGRST and RCC_FLAG_LPWRRST. + * @retval None + */ +#define __HAL_RCC_CLEAR_RESET_FLAGS() SET_BIT(RCC->CSR, RCC_CSR_RMVF) + +/** @brief Check whether the selected RCC flag is set or not. + * @param __FLAG__ specifies the flag to check. + * This parameter can be one of the following values: + * @arg @ref RCC_FLAG_MSIRDY MSI oscillator clock ready + * @arg @ref RCC_FLAG_HSIRDY HSI oscillator clock ready + * @arg @ref RCC_FLAG_HSERDY HSE oscillator clock ready + * @arg @ref RCC_FLAG_PLLRDY Main PLL clock ready + * @arg @ref RCC_FLAG_PLLSAI1RDY PLLSAI1 clock ready + * @arg @ref RCC_FLAG_PLLSAI2RDY PLLSAI2 clock ready for devices with PLLSAI2 + @if STM32L443xx + * @arg @ref RCC_FLAG_HSI48RDY HSI48 clock ready for devices with HSI48 + @endif + @if STM32L4A6xx + * @arg @ref RCC_FLAG_HSI48RDY HSI48 clock ready for devices with HSI48 + @endif + * @arg @ref RCC_FLAG_LSERDY LSE oscillator clock ready + * @arg @ref RCC_FLAG_LSECSSD Clock security system failure on LSE oscillator detection + * @arg @ref RCC_FLAG_LSIRDY LSI oscillator clock ready + * @arg @ref RCC_FLAG_BORRST BOR reset + * @arg @ref RCC_FLAG_OBLRST OBLRST reset + * @arg @ref RCC_FLAG_PINRST Pin reset + * @arg @ref RCC_FLAG_FWRST FIREWALL reset + * @arg @ref RCC_FLAG_RMVF Remove reset Flag + * @arg @ref RCC_FLAG_SFTRST Software reset + * @arg @ref RCC_FLAG_IWDGRST Independent Watchdog reset + * @arg @ref RCC_FLAG_WWDGRST Window Watchdog reset + * @arg @ref RCC_FLAG_LPWRRST Low Power reset + * @retval The new state of __FLAG__ (TRUE or FALSE). + */ +#if defined(RCC_HSI48_SUPPORT) +#define __HAL_RCC_GET_FLAG(__FLAG__) (((((((__FLAG__) >> 5U) == 1U) ? RCC->CR : \ + ((((__FLAG__) >> 5U) == 4U) ? RCC->CRRCR : \ + ((((__FLAG__) >> 5U) == 2U) ? RCC->BDCR : \ + ((((__FLAG__) >> 5U) == 3U) ? RCC->CSR : RCC->CIFR)))) & \ + (1U << ((__FLAG__) & RCC_FLAG_MASK))) != RESET) ? 1U : 0U) +#else +#define __HAL_RCC_GET_FLAG(__FLAG__) (((((((__FLAG__) >> 5U) == 1U) ? RCC->CR : \ + ((((__FLAG__) >> 5U) == 2U) ? RCC->BDCR : \ + ((((__FLAG__) >> 5U) == 3U) ? RCC->CSR : RCC->CIFR))) & \ + (1U << ((__FLAG__) & RCC_FLAG_MASK))) != RESET) ? 1U : 0U) +#endif /* RCC_HSI48_SUPPORT */ + +/** + * @} + */ + +/** + * @} + */ + +/* Private constants ---------------------------------------------------------*/ +/** @defgroup RCC_Private_Constants RCC Private Constants + * @{ + */ +/* Defines used for Flags */ +#define CR_REG_INDEX 1U +#define BDCR_REG_INDEX 2U +#define CSR_REG_INDEX 3U +#if defined(RCC_HSI48_SUPPORT) +#define CRRCR_REG_INDEX 4U +#endif /* RCC_HSI48_SUPPORT */ + +#define RCC_FLAG_MASK 0x1FU +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @addtogroup RCC_Private_Macros + * @{ + */ + +#if defined(RCC_HSI48_SUPPORT) +#define IS_RCC_OSCILLATORTYPE(__OSCILLATOR__) (((__OSCILLATOR__) == RCC_OSCILLATORTYPE_NONE) || \ + (((__OSCILLATOR__) & RCC_OSCILLATORTYPE_HSE) == RCC_OSCILLATORTYPE_HSE) || \ + (((__OSCILLATOR__) & RCC_OSCILLATORTYPE_HSI) == RCC_OSCILLATORTYPE_HSI) || \ + (((__OSCILLATOR__) & RCC_OSCILLATORTYPE_HSI48) == RCC_OSCILLATORTYPE_HSI48) || \ + (((__OSCILLATOR__) & RCC_OSCILLATORTYPE_MSI) == RCC_OSCILLATORTYPE_MSI) || \ + (((__OSCILLATOR__) & RCC_OSCILLATORTYPE_LSI) == RCC_OSCILLATORTYPE_LSI) || \ + (((__OSCILLATOR__) & RCC_OSCILLATORTYPE_LSE) == RCC_OSCILLATORTYPE_LSE)) +#else +#define IS_RCC_OSCILLATORTYPE(__OSCILLATOR__) (((__OSCILLATOR__) == RCC_OSCILLATORTYPE_NONE) || \ + (((__OSCILLATOR__) & RCC_OSCILLATORTYPE_HSE) == RCC_OSCILLATORTYPE_HSE) || \ + (((__OSCILLATOR__) & RCC_OSCILLATORTYPE_HSI) == RCC_OSCILLATORTYPE_HSI) || \ + (((__OSCILLATOR__) & RCC_OSCILLATORTYPE_MSI) == RCC_OSCILLATORTYPE_MSI) || \ + (((__OSCILLATOR__) & RCC_OSCILLATORTYPE_LSI) == RCC_OSCILLATORTYPE_LSI) || \ + (((__OSCILLATOR__) & RCC_OSCILLATORTYPE_LSE) == RCC_OSCILLATORTYPE_LSE)) +#endif /* RCC_HSI48_SUPPORT */ + +#define IS_RCC_HSE(__HSE__) (((__HSE__) == RCC_HSE_OFF) || ((__HSE__) == RCC_HSE_ON) || \ + ((__HSE__) == RCC_HSE_BYPASS)) + +#define IS_RCC_LSE(__LSE__) (((__LSE__) == RCC_LSE_OFF) || ((__LSE__) == RCC_LSE_ON) || \ + ((__LSE__) == RCC_LSE_BYPASS)) + +#define IS_RCC_HSI(__HSI__) (((__HSI__) == RCC_HSI_OFF) || ((__HSI__) == RCC_HSI_ON)) + +#define IS_RCC_HSI_CALIBRATION_VALUE(__VALUE__) ((__VALUE__) <= (RCC_ICSCR_HSITRIM >> RCC_ICSCR_HSITRIM_Pos)) + +#define IS_RCC_LSI(__LSI__) (((__LSI__) == RCC_LSI_OFF) || ((__LSI__) == RCC_LSI_ON)) + +#define IS_RCC_MSI(__MSI__) (((__MSI__) == RCC_MSI_OFF) || ((__MSI__) == RCC_MSI_ON)) + +#define IS_RCC_MSICALIBRATION_VALUE(__VALUE__) ((__VALUE__) <= 255U) + +#if defined(RCC_HSI48_SUPPORT) +#define IS_RCC_HSI48(__HSI48__) (((__HSI48__) == RCC_HSI48_OFF) || ((__HSI48__) == RCC_HSI48_ON)) +#endif /* RCC_HSI48_SUPPORT */ + +#define IS_RCC_PLL(__PLL__) (((__PLL__) == RCC_PLL_NONE) ||((__PLL__) == RCC_PLL_OFF) || \ + ((__PLL__) == RCC_PLL_ON)) + +#define IS_RCC_PLLSOURCE(__SOURCE__) (((__SOURCE__) == RCC_PLLSOURCE_NONE) || \ + ((__SOURCE__) == RCC_PLLSOURCE_MSI) || \ + ((__SOURCE__) == RCC_PLLSOURCE_HSI) || \ + ((__SOURCE__) == RCC_PLLSOURCE_HSE)) + +#if defined(RCC_PLLM_DIV_1_16_SUPPORT) +#define IS_RCC_PLLM_VALUE(__VALUE__) ((1U <= (__VALUE__)) && ((__VALUE__) <= 16U)) +#else +#define IS_RCC_PLLM_VALUE(__VALUE__) ((1U <= (__VALUE__)) && ((__VALUE__) <= 8U)) +#endif /*RCC_PLLM_DIV_1_16_SUPPORT */ + +#define IS_RCC_PLLN_VALUE(__VALUE__) ((8U <= (__VALUE__)) && ((__VALUE__) <= 86U)) + +#if defined(RCC_PLLP_DIV_2_31_SUPPORT) +#define IS_RCC_PLLP_VALUE(__VALUE__) (((__VALUE__) >= 2U) && ((__VALUE__) <= 31U)) +#else +#define IS_RCC_PLLP_VALUE(__VALUE__) (((__VALUE__) == 7U) || ((__VALUE__) == 17U)) +#endif /*RCC_PLLP_DIV_2_31_SUPPORT */ + +#define IS_RCC_PLLQ_VALUE(__VALUE__) (((__VALUE__) == 2U) || ((__VALUE__) == 4U) || \ + ((__VALUE__) == 6U) || ((__VALUE__) == 8U)) + +#define IS_RCC_PLLR_VALUE(__VALUE__) (((__VALUE__) == 2U) || ((__VALUE__) == 4U) || \ + ((__VALUE__) == 6U) || ((__VALUE__) == 8U)) + +#define IS_RCC_PLLSAI1CLOCKOUT_VALUE(__VALUE__) (((((__VALUE__) & RCC_PLLSAI1_SAI1CLK) == RCC_PLLSAI1_SAI1CLK) || \ + (((__VALUE__) & RCC_PLLSAI1_48M2CLK) == RCC_PLLSAI1_48M2CLK) || \ + (((__VALUE__) & RCC_PLLSAI1_ADC1CLK) == RCC_PLLSAI1_ADC1CLK)) && \ + (((__VALUE__) & ~(RCC_PLLSAI1_SAI1CLK|RCC_PLLSAI1_48M2CLK|RCC_PLLSAI1_ADC1CLK)) == 0U)) + +#if defined(RCC_PLLSAI2_SUPPORT) +#if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || defined(STM32L496xx) || defined(STM32L4A6xx) +#define IS_RCC_PLLSAI2CLOCKOUT_VALUE(__VALUE__) (((((__VALUE__) & RCC_PLLSAI2_SAI2CLK) == RCC_PLLSAI2_SAI2CLK) || \ + (((__VALUE__) & RCC_PLLSAI2_ADC2CLK) == RCC_PLLSAI2_ADC2CLK)) && \ + (((__VALUE__) & ~(RCC_PLLSAI2_SAI2CLK|RCC_PLLSAI2_ADC2CLK)) == 0U)) +#elif defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +#define IS_RCC_PLLSAI2CLOCKOUT_VALUE(__VALUE__) (((((__VALUE__) & RCC_PLLSAI2_SAI2CLK) == RCC_PLLSAI2_SAI2CLK) || \ + (((__VALUE__) & RCC_PLLSAI2_DSICLK) == RCC_PLLSAI2_DSICLK) || \ + (((__VALUE__) & RCC_PLLSAI2_LTDCCLK) == RCC_PLLSAI2_LTDCCLK)) && \ + (((__VALUE__) & ~(RCC_PLLSAI2_SAI2CLK|RCC_PLLSAI2_DSICLK|RCC_PLLSAI2_LTDCCLK)) == 0U)) +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || STM32L496xx || STM32L4A6xx */ +#endif /* RCC_PLLSAI2_SUPPORT */ + +#define IS_RCC_MSI_CLOCK_RANGE(__RANGE__) (((__RANGE__) == RCC_MSIRANGE_0) || \ + ((__RANGE__) == RCC_MSIRANGE_1) || \ + ((__RANGE__) == RCC_MSIRANGE_2) || \ + ((__RANGE__) == RCC_MSIRANGE_3) || \ + ((__RANGE__) == RCC_MSIRANGE_4) || \ + ((__RANGE__) == RCC_MSIRANGE_5) || \ + ((__RANGE__) == RCC_MSIRANGE_6) || \ + ((__RANGE__) == RCC_MSIRANGE_7) || \ + ((__RANGE__) == RCC_MSIRANGE_8) || \ + ((__RANGE__) == RCC_MSIRANGE_9) || \ + ((__RANGE__) == RCC_MSIRANGE_10) || \ + ((__RANGE__) == RCC_MSIRANGE_11)) + +#define IS_RCC_MSI_STANDBY_CLOCK_RANGE(__RANGE__) (((__RANGE__) == RCC_MSIRANGE_4) || \ + ((__RANGE__) == RCC_MSIRANGE_5) || \ + ((__RANGE__) == RCC_MSIRANGE_6) || \ + ((__RANGE__) == RCC_MSIRANGE_7)) + +#define IS_RCC_CLOCKTYPE(__CLK__) ((1U <= (__CLK__)) && ((__CLK__) <= 15U)) + +#define IS_RCC_SYSCLKSOURCE(__SOURCE__) (((__SOURCE__) == RCC_SYSCLKSOURCE_MSI) || \ + ((__SOURCE__) == RCC_SYSCLKSOURCE_HSI) || \ + ((__SOURCE__) == RCC_SYSCLKSOURCE_HSE) || \ + ((__SOURCE__) == RCC_SYSCLKSOURCE_PLLCLK)) + +#define IS_RCC_HCLK(__HCLK__) (((__HCLK__) == RCC_SYSCLK_DIV1) || ((__HCLK__) == RCC_SYSCLK_DIV2) || \ + ((__HCLK__) == RCC_SYSCLK_DIV4) || ((__HCLK__) == RCC_SYSCLK_DIV8) || \ + ((__HCLK__) == RCC_SYSCLK_DIV16) || ((__HCLK__) == RCC_SYSCLK_DIV64) || \ + ((__HCLK__) == RCC_SYSCLK_DIV128) || ((__HCLK__) == RCC_SYSCLK_DIV256) || \ + ((__HCLK__) == RCC_SYSCLK_DIV512)) + +#define IS_RCC_PCLK(__PCLK__) (((__PCLK__) == RCC_HCLK_DIV1) || ((__PCLK__) == RCC_HCLK_DIV2) || \ + ((__PCLK__) == RCC_HCLK_DIV4) || ((__PCLK__) == RCC_HCLK_DIV8) || \ + ((__PCLK__) == RCC_HCLK_DIV16)) + +#define IS_RCC_RTCCLKSOURCE(__SOURCE__) (((__SOURCE__) == RCC_RTCCLKSOURCE_NONE) || \ + ((__SOURCE__) == RCC_RTCCLKSOURCE_LSE) || \ + ((__SOURCE__) == RCC_RTCCLKSOURCE_LSI) || \ + ((__SOURCE__) == RCC_RTCCLKSOURCE_HSE_DIV32)) + +#define IS_RCC_MCO(__MCOX__) ((__MCOX__) == RCC_MCO1) + +#if defined(RCC_HSI48_SUPPORT) +#define IS_RCC_MCO1SOURCE(__SOURCE__) (((__SOURCE__) == RCC_MCO1SOURCE_NOCLOCK) || \ + ((__SOURCE__) == RCC_MCO1SOURCE_SYSCLK) || \ + ((__SOURCE__) == RCC_MCO1SOURCE_MSI) || \ + ((__SOURCE__) == RCC_MCO1SOURCE_HSI) || \ + ((__SOURCE__) == RCC_MCO1SOURCE_HSE) || \ + ((__SOURCE__) == RCC_MCO1SOURCE_PLLCLK) || \ + ((__SOURCE__) == RCC_MCO1SOURCE_LSI) || \ + ((__SOURCE__) == RCC_MCO1SOURCE_LSE) || \ + ((__SOURCE__) == RCC_MCO1SOURCE_HSI48)) +#else +#define IS_RCC_MCO1SOURCE(__SOURCE__) (((__SOURCE__) == RCC_MCO1SOURCE_NOCLOCK) || \ + ((__SOURCE__) == RCC_MCO1SOURCE_SYSCLK) || \ + ((__SOURCE__) == RCC_MCO1SOURCE_MSI) || \ + ((__SOURCE__) == RCC_MCO1SOURCE_HSI) || \ + ((__SOURCE__) == RCC_MCO1SOURCE_HSE) || \ + ((__SOURCE__) == RCC_MCO1SOURCE_PLLCLK) || \ + ((__SOURCE__) == RCC_MCO1SOURCE_LSI) || \ + ((__SOURCE__) == RCC_MCO1SOURCE_LSE)) +#endif /* RCC_HSI48_SUPPORT */ + +#define IS_RCC_MCODIV(__DIV__) (((__DIV__) == RCC_MCODIV_1) || ((__DIV__) == RCC_MCODIV_2) || \ + ((__DIV__) == RCC_MCODIV_4) || ((__DIV__) == RCC_MCODIV_8) || \ + ((__DIV__) == RCC_MCODIV_16)) + +#define IS_RCC_LSE_DRIVE(__DRIVE__) (((__DRIVE__) == RCC_LSEDRIVE_LOW) || \ + ((__DRIVE__) == RCC_LSEDRIVE_MEDIUMLOW) || \ + ((__DRIVE__) == RCC_LSEDRIVE_MEDIUMHIGH) || \ + ((__DRIVE__) == RCC_LSEDRIVE_HIGH)) + +#define IS_RCC_STOP_WAKEUPCLOCK(__SOURCE__) (((__SOURCE__) == RCC_STOP_WAKEUPCLOCK_MSI) || \ + ((__SOURCE__) == RCC_STOP_WAKEUPCLOCK_HSI)) +/** + * @} + */ + +/* Include RCC HAL Extended module */ +#include "stm32l4xx_hal_rcc_ex.h" + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup RCC_Exported_Functions + * @{ + */ + + +/** @addtogroup RCC_Exported_Functions_Group1 + * @{ + */ + +/* Initialization and de-initialization functions ******************************/ +HAL_StatusTypeDef HAL_RCC_DeInit(void); +HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct); +HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, uint32_t FLatency); + +/** + * @} + */ + +/** @addtogroup RCC_Exported_Functions_Group2 + * @{ + */ + +/* Peripheral Control functions ************************************************/ +void HAL_RCC_MCOConfig(uint32_t RCC_MCOx, uint32_t RCC_MCOSource, uint32_t RCC_MCODiv); +void HAL_RCC_EnableCSS(void); +uint32_t HAL_RCC_GetSysClockFreq(void); +uint32_t HAL_RCC_GetHCLKFreq(void); +uint32_t HAL_RCC_GetPCLK1Freq(void); +uint32_t HAL_RCC_GetPCLK2Freq(void); +void HAL_RCC_GetOscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct); +void HAL_RCC_GetClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, uint32_t *pFLatency); +/* CSS NMI IRQ handler */ +void HAL_RCC_NMI_IRQHandler(void); +/* User Callbacks in non blocking mode (IT mode) */ +void HAL_RCC_CSSCallback(void); + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_HAL_RCC_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rcc_ex.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rcc_ex.h new file mode 100644 index 0000000..b0000a7 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rcc_ex.h @@ -0,0 +1,3018 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_rcc_ex.h + * @author MCD Application Team + * @brief Header file of RCC HAL Extended module. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_RCC_EX_H +#define __STM32L4xx_HAL_RCC_EX_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup RCCEx + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ + +/** @defgroup RCCEx_Exported_Types RCCEx Exported Types + * @{ + */ + +/** + * @brief PLLSAI1 Clock structure definition + */ +typedef struct +{ + + uint32_t PLLSAI1Source; /*!< PLLSAI1Source: PLLSAI1 entry clock source. + This parameter must be a value of @ref RCC_PLL_Clock_Source */ + +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + uint32_t PLLSAI1M; /*!< PLLSAI1M: specifies the division factor for PLLSAI1 input clock. + This parameter must be a number between Min_Data = 1 and Max_Data = 16 */ +#else + uint32_t PLLSAI1M; /*!< PLLSAI1M: specifies the division factor for PLLSAI1 input clock. + This parameter must be a number between Min_Data = 1 and Max_Data = 8 */ +#endif + + uint32_t PLLSAI1N; /*!< PLLSAI1N: specifies the multiplication factor for PLLSAI1 VCO output clock. + This parameter must be a number between 8 and 86 or 127 depending on devices. */ + + uint32_t PLLSAI1P; /*!< PLLSAI1P: specifies the division factor for SAI clock. + This parameter must be a value of @ref RCC_PLLP_Clock_Divider */ + + uint32_t PLLSAI1Q; /*!< PLLSAI1Q: specifies the division factor for USB/RNG/SDMMC1 clock. + This parameter must be a value of @ref RCC_PLLQ_Clock_Divider */ + + uint32_t PLLSAI1R; /*!< PLLSAI1R: specifies the division factor for ADC clock. + This parameter must be a value of @ref RCC_PLLR_Clock_Divider */ + + uint32_t PLLSAI1ClockOut; /*!< PLLSAIClockOut: specifies PLLSAI1 output clock to be enabled. + This parameter must be a value of @ref RCC_PLLSAI1_Clock_Output */ +}RCC_PLLSAI1InitTypeDef; + +#if defined(RCC_PLLSAI2_SUPPORT) + +/** + * @brief PLLSAI2 Clock structure definition + */ +typedef struct +{ + + uint32_t PLLSAI2Source; /*!< PLLSAI2Source: PLLSAI2 entry clock source. + This parameter must be a value of @ref RCC_PLL_Clock_Source */ + +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + uint32_t PLLSAI2M; /*!< PLLSAI2M: specifies the division factor for PLLSAI2 input clock. + This parameter must be a number between Min_Data = 1 and Max_Data = 16 */ +#else + uint32_t PLLSAI2M; /*!< PLLSAI2M: specifies the division factor for PLLSAI2 input clock. + This parameter must be a number between Min_Data = 1 and Max_Data = 8 */ +#endif + + uint32_t PLLSAI2N; /*!< PLLSAI2N: specifies the multiplication factor for PLLSAI2 VCO output clock. + This parameter must be a number between 8 and 86 or 127 depending on devices. */ + + uint32_t PLLSAI2P; /*!< PLLSAI2P: specifies the division factor for SAI clock. + This parameter must be a value of @ref RCC_PLLP_Clock_Divider */ + +#if defined(RCC_PLLSAI2Q_DIV_SUPPORT) + uint32_t PLLSAI2Q; /*!< PLLSAI2Q: specifies the division factor for DSI clock. + This parameter must be a value of @ref RCC_PLLQ_Clock_Divider */ +#endif + + uint32_t PLLSAI2R; /*!< PLLSAI2R: specifies the division factor for ADC clock. + This parameter must be a value of @ref RCC_PLLR_Clock_Divider */ + + uint32_t PLLSAI2ClockOut; /*!< PLLSAIClockOut: specifies PLLSAI2 output clock to be enabled. + This parameter must be a value of @ref RCC_PLLSAI2_Clock_Output */ +}RCC_PLLSAI2InitTypeDef; + +#endif /* RCC_PLLSAI2_SUPPORT */ + +/** + * @brief RCC extended clocks structure definition + */ +typedef struct +{ + uint32_t PeriphClockSelection; /*!< The Extended Clock to be configured. + This parameter can be a value of @ref RCCEx_Periph_Clock_Selection */ + + RCC_PLLSAI1InitTypeDef PLLSAI1; /*!< PLLSAI1 structure parameters. + This parameter will be used only when PLLSAI1 is selected as Clock Source for SAI1, USB/RNG/SDMMC1 or ADC */ + +#if defined(RCC_PLLSAI2_SUPPORT) + + RCC_PLLSAI2InitTypeDef PLLSAI2; /*!< PLLSAI2 structure parameters. + This parameter will be used only when PLLSAI2 is selected as Clock Source for SAI2 or ADC */ + +#endif /* RCC_PLLSAI2_SUPPORT */ + + uint32_t Usart1ClockSelection; /*!< Specifies USART1 clock source. + This parameter can be a value of @ref RCCEx_USART1_Clock_Source */ + + uint32_t Usart2ClockSelection; /*!< Specifies USART2 clock source. + This parameter can be a value of @ref RCCEx_USART2_Clock_Source */ + +#if defined(USART3) + + uint32_t Usart3ClockSelection; /*!< Specifies USART3 clock source. + This parameter can be a value of @ref RCCEx_USART3_Clock_Source */ + +#endif /* USART3 */ + +#if defined(UART4) + + uint32_t Uart4ClockSelection; /*!< Specifies UART4 clock source. + This parameter can be a value of @ref RCCEx_UART4_Clock_Source */ + +#endif /* UART4 */ + +#if defined(UART5) + + uint32_t Uart5ClockSelection; /*!< Specifies UART5 clock source. + This parameter can be a value of @ref RCCEx_UART5_Clock_Source */ + +#endif /* UART5 */ + + uint32_t Lpuart1ClockSelection; /*!< Specifies LPUART1 clock source. + This parameter can be a value of @ref RCCEx_LPUART1_Clock_Source */ + + uint32_t I2c1ClockSelection; /*!< Specifies I2C1 clock source. + This parameter can be a value of @ref RCCEx_I2C1_Clock_Source */ + +#if defined(I2C2) + + uint32_t I2c2ClockSelection; /*!< Specifies I2C2 clock source. + This parameter can be a value of @ref RCCEx_I2C2_Clock_Source */ + +#endif /* I2C2 */ + + uint32_t I2c3ClockSelection; /*!< Specifies I2C3 clock source. + This parameter can be a value of @ref RCCEx_I2C3_Clock_Source */ + +#if defined(I2C4) + + uint32_t I2c4ClockSelection; /*!< Specifies I2C4 clock source. + This parameter can be a value of @ref RCCEx_I2C4_Clock_Source */ + +#endif /* I2C4 */ + + uint32_t Lptim1ClockSelection; /*!< Specifies LPTIM1 clock source. + This parameter can be a value of @ref RCCEx_LPTIM1_Clock_Source */ + + uint32_t Lptim2ClockSelection; /*!< Specifies LPTIM2 clock source. + This parameter can be a value of @ref RCCEx_LPTIM2_Clock_Source */ + + uint32_t Sai1ClockSelection; /*!< Specifies SAI1 clock source. + This parameter can be a value of @ref RCCEx_SAI1_Clock_Source */ + +#if defined(SAI2) + + uint32_t Sai2ClockSelection; /*!< Specifies SAI2 clock source. + This parameter can be a value of @ref RCCEx_SAI2_Clock_Source */ + +#endif /* SAI2 */ + +#if defined(USB_OTG_FS) || defined(USB) + + uint32_t UsbClockSelection; /*!< Specifies USB clock source (warning: same source for SDMMC1 and RNG). + This parameter can be a value of @ref RCCEx_USB_Clock_Source */ + +#endif /* USB_OTG_FS || USB */ + +#if defined(SDMMC1) + + uint32_t Sdmmc1ClockSelection; /*!< Specifies SDMMC1 clock source (warning: same source for USB and RNG). + This parameter can be a value of @ref RCCEx_SDMMC1_Clock_Source */ + +#endif /* SDMMC1 */ + + uint32_t RngClockSelection; /*!< Specifies RNG clock source (warning: same source for USB and SDMMC1). + This parameter can be a value of @ref RCCEx_RNG_Clock_Source */ + + uint32_t AdcClockSelection; /*!< Specifies ADC interface clock source. + This parameter can be a value of @ref RCCEx_ADC_Clock_Source */ + +#if defined(SWPMI1) + + uint32_t Swpmi1ClockSelection; /*!< Specifies SWPMI1 clock source. + This parameter can be a value of @ref RCCEx_SWPMI1_Clock_Source */ + +#endif /* SWPMI1 */ + +#if defined(DFSDM1_Filter0) + + uint32_t Dfsdm1ClockSelection; /*!< Specifies DFSDM1 clock source. + This parameter can be a value of @ref RCCEx_DFSDM1_Clock_Source */ + +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + uint32_t Dfsdm1AudioClockSelection; /*!< Specifies DFSDM1 audio clock source. + This parameter can be a value of @ref RCCEx_DFSDM1_Audio_Clock_Source */ + +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#endif /* DFSDM1_Filter0 */ + +#if defined(LTDC) + + uint32_t LtdcClockSelection; /*!< Specifies LTDC clock source. + This parameter can be a value of @ref RCCEx_LTDC_Clock_Source */ + +#endif /* LTDC */ + +#if defined(DSI) + + uint32_t DsiClockSelection; /*!< Specifies DSI clock source. + This parameter can be a value of @ref RCCEx_DSI_Clock_Source */ + +#endif /* DSI */ + +#if defined(OCTOSPI1) || defined(OCTOSPI2) + + uint32_t OspiClockSelection; /*!< Specifies OctoSPI clock source. + This parameter can be a value of @ref RCCEx_OSPI_Clock_Source */ + +#endif + + uint32_t RTCClockSelection; /*!< Specifies RTC clock source. + This parameter can be a value of @ref RCC_RTC_Clock_Source */ +}RCC_PeriphCLKInitTypeDef; + +#if defined(CRS) + +/** + * @brief RCC_CRS Init structure definition + */ +typedef struct +{ + uint32_t Prescaler; /*!< Specifies the division factor of the SYNC signal. + This parameter can be a value of @ref RCCEx_CRS_SynchroDivider */ + + uint32_t Source; /*!< Specifies the SYNC signal source. + This parameter can be a value of @ref RCCEx_CRS_SynchroSource */ + + uint32_t Polarity; /*!< Specifies the input polarity for the SYNC signal source. + This parameter can be a value of @ref RCCEx_CRS_SynchroPolarity */ + + uint32_t ReloadValue; /*!< Specifies the value to be loaded in the frequency error counter with each SYNC event. + It can be calculated in using macro __HAL_RCC_CRS_RELOADVALUE_CALCULATE(__FTARGET__, __FSYNC__) + This parameter must be a number between 0 and 0xFFFF or a value of @ref RCCEx_CRS_ReloadValueDefault .*/ + + uint32_t ErrorLimitValue; /*!< Specifies the value to be used to evaluate the captured frequency error value. + This parameter must be a number between 0 and 0xFF or a value of @ref RCCEx_CRS_ErrorLimitDefault */ + + uint32_t HSI48CalibrationValue; /*!< Specifies a user-programmable trimming value to the HSI48 oscillator. + This parameter must be a number between 0 and 0x3F or a value of @ref RCCEx_CRS_HSI48CalibrationDefault */ + +}RCC_CRSInitTypeDef; + +/** + * @brief RCC_CRS Synchronization structure definition + */ +typedef struct +{ + uint32_t ReloadValue; /*!< Specifies the value loaded in the Counter reload value. + This parameter must be a number between 0 and 0xFFFF */ + + uint32_t HSI48CalibrationValue; /*!< Specifies value loaded in HSI48 oscillator smooth trimming. + This parameter must be a number between 0 and 0x3F */ + + uint32_t FreqErrorCapture; /*!< Specifies the value loaded in the .FECAP, the frequency error counter + value latched in the time of the last SYNC event. + This parameter must be a number between 0 and 0xFFFF */ + + uint32_t FreqErrorDirection; /*!< Specifies the value loaded in the .FEDIR, the counting direction of the + frequency error counter latched in the time of the last SYNC event. + It shows whether the actual frequency is below or above the target. + This parameter must be a value of @ref RCCEx_CRS_FreqErrorDirection*/ + +}RCC_CRSSynchroInfoTypeDef; + +#endif /* CRS */ +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup RCCEx_Exported_Constants RCCEx Exported Constants + * @{ + */ + +/** @defgroup RCCEx_LSCO_Clock_Source Low Speed Clock Source + * @{ + */ +#define RCC_LSCOSOURCE_LSI 0x00000000U /*!< LSI selection for low speed clock output */ +#define RCC_LSCOSOURCE_LSE RCC_BDCR_LSCOSEL /*!< LSE selection for low speed clock output */ +/** + * @} + */ + +/** @defgroup RCCEx_Periph_Clock_Selection Periph Clock Selection + * @{ + */ +#define RCC_PERIPHCLK_USART1 0x00000001U +#define RCC_PERIPHCLK_USART2 0x00000002U +#if defined(USART3) +#define RCC_PERIPHCLK_USART3 0x00000004U +#endif +#if defined(UART4) +#define RCC_PERIPHCLK_UART4 0x00000008U +#endif +#if defined(UART5) +#define RCC_PERIPHCLK_UART5 0x00000010U +#endif +#define RCC_PERIPHCLK_LPUART1 0x00000020U +#define RCC_PERIPHCLK_I2C1 0x00000040U +#if defined(I2C2) +#define RCC_PERIPHCLK_I2C2 0x00000080U +#endif +#define RCC_PERIPHCLK_I2C3 0x00000100U +#define RCC_PERIPHCLK_LPTIM1 0x00000200U +#define RCC_PERIPHCLK_LPTIM2 0x00000400U +#define RCC_PERIPHCLK_SAI1 0x00000800U +#if defined(SAI2) +#define RCC_PERIPHCLK_SAI2 0x00001000U +#endif +#if defined(USB_OTG_FS) || defined(USB) +#define RCC_PERIPHCLK_USB 0x00002000U +#endif +#define RCC_PERIPHCLK_ADC 0x00004000U +#if defined(SWPMI1) +#define RCC_PERIPHCLK_SWPMI1 0x00008000U +#endif +#if defined(DFSDM1_Filter0) +#define RCC_PERIPHCLK_DFSDM1 0x00010000U +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +#define RCC_PERIPHCLK_DFSDM1AUDIO 0x00200000U +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ +#endif +#define RCC_PERIPHCLK_RTC 0x00020000U +#define RCC_PERIPHCLK_RNG 0x00040000U +#if defined(SDMMC1) +#define RCC_PERIPHCLK_SDMMC1 0x00080000U +#endif +#if defined(I2C4) +#define RCC_PERIPHCLK_I2C4 0x00100000U +#endif +#if defined(LTDC) +#define RCC_PERIPHCLK_LTDC 0x00400000U +#endif +#if defined(DSI) +#define RCC_PERIPHCLK_DSI 0x00800000U +#endif +#if defined(OCTOSPI1) || defined(OCTOSPI2) +#define RCC_PERIPHCLK_OSPI 0x01000000U +#endif +/** + * @} + */ + + +/** @defgroup RCCEx_USART1_Clock_Source USART1 Clock Source + * @{ + */ +#define RCC_USART1CLKSOURCE_PCLK2 0x00000000U +#define RCC_USART1CLKSOURCE_SYSCLK RCC_CCIPR_USART1SEL_0 +#define RCC_USART1CLKSOURCE_HSI RCC_CCIPR_USART1SEL_1 +#define RCC_USART1CLKSOURCE_LSE (RCC_CCIPR_USART1SEL_0 | RCC_CCIPR_USART1SEL_1) +/** + * @} + */ + +/** @defgroup RCCEx_USART2_Clock_Source USART2 Clock Source + * @{ + */ +#define RCC_USART2CLKSOURCE_PCLK1 0x00000000U +#define RCC_USART2CLKSOURCE_SYSCLK RCC_CCIPR_USART2SEL_0 +#define RCC_USART2CLKSOURCE_HSI RCC_CCIPR_USART2SEL_1 +#define RCC_USART2CLKSOURCE_LSE (RCC_CCIPR_USART2SEL_0 | RCC_CCIPR_USART2SEL_1) +/** + * @} + */ + +#if defined(USART3) +/** @defgroup RCCEx_USART3_Clock_Source USART3 Clock Source + * @{ + */ +#define RCC_USART3CLKSOURCE_PCLK1 0x00000000U +#define RCC_USART3CLKSOURCE_SYSCLK RCC_CCIPR_USART3SEL_0 +#define RCC_USART3CLKSOURCE_HSI RCC_CCIPR_USART3SEL_1 +#define RCC_USART3CLKSOURCE_LSE (RCC_CCIPR_USART3SEL_0 | RCC_CCIPR_USART3SEL_1) +/** + * @} + */ +#endif /* USART3 */ + +#if defined(UART4) +/** @defgroup RCCEx_UART4_Clock_Source UART4 Clock Source + * @{ + */ +#define RCC_UART4CLKSOURCE_PCLK1 0x00000000U +#define RCC_UART4CLKSOURCE_SYSCLK RCC_CCIPR_UART4SEL_0 +#define RCC_UART4CLKSOURCE_HSI RCC_CCIPR_UART4SEL_1 +#define RCC_UART4CLKSOURCE_LSE (RCC_CCIPR_UART4SEL_0 | RCC_CCIPR_UART4SEL_1) +/** + * @} + */ +#endif /* UART4 */ + +#if defined(UART5) +/** @defgroup RCCEx_UART5_Clock_Source UART5 Clock Source + * @{ + */ +#define RCC_UART5CLKSOURCE_PCLK1 0x00000000U +#define RCC_UART5CLKSOURCE_SYSCLK RCC_CCIPR_UART5SEL_0 +#define RCC_UART5CLKSOURCE_HSI RCC_CCIPR_UART5SEL_1 +#define RCC_UART5CLKSOURCE_LSE (RCC_CCIPR_UART5SEL_0 | RCC_CCIPR_UART5SEL_1) +/** + * @} + */ +#endif /* UART5 */ + +/** @defgroup RCCEx_LPUART1_Clock_Source LPUART1 Clock Source + * @{ + */ +#define RCC_LPUART1CLKSOURCE_PCLK1 0x00000000U +#define RCC_LPUART1CLKSOURCE_SYSCLK RCC_CCIPR_LPUART1SEL_0 +#define RCC_LPUART1CLKSOURCE_HSI RCC_CCIPR_LPUART1SEL_1 +#define RCC_LPUART1CLKSOURCE_LSE (RCC_CCIPR_LPUART1SEL_0 | RCC_CCIPR_LPUART1SEL_1) +/** + * @} + */ + +/** @defgroup RCCEx_I2C1_Clock_Source I2C1 Clock Source + * @{ + */ +#define RCC_I2C1CLKSOURCE_PCLK1 0x00000000U +#define RCC_I2C1CLKSOURCE_SYSCLK RCC_CCIPR_I2C1SEL_0 +#define RCC_I2C1CLKSOURCE_HSI RCC_CCIPR_I2C1SEL_1 +/** + * @} + */ + +#if defined(I2C2) +/** @defgroup RCCEx_I2C2_Clock_Source I2C2 Clock Source + * @{ + */ +#define RCC_I2C2CLKSOURCE_PCLK1 0x00000000U +#define RCC_I2C2CLKSOURCE_SYSCLK RCC_CCIPR_I2C2SEL_0 +#define RCC_I2C2CLKSOURCE_HSI RCC_CCIPR_I2C2SEL_1 +/** + * @} + */ +#endif /* I2C2 */ + +/** @defgroup RCCEx_I2C3_Clock_Source I2C3 Clock Source + * @{ + */ +#define RCC_I2C3CLKSOURCE_PCLK1 0x00000000U +#define RCC_I2C3CLKSOURCE_SYSCLK RCC_CCIPR_I2C3SEL_0 +#define RCC_I2C3CLKSOURCE_HSI RCC_CCIPR_I2C3SEL_1 +/** + * @} + */ + +#if defined(I2C4) +/** @defgroup RCCEx_I2C4_Clock_Source I2C4 Clock Source + * @{ + */ +#define RCC_I2C4CLKSOURCE_PCLK1 0x00000000U +#define RCC_I2C4CLKSOURCE_SYSCLK RCC_CCIPR2_I2C4SEL_0 +#define RCC_I2C4CLKSOURCE_HSI RCC_CCIPR2_I2C4SEL_1 +/** + * @} + */ +#endif /* I2C4 */ + +/** @defgroup RCCEx_SAI1_Clock_Source SAI1 Clock Source + * @{ + */ +#define RCC_SAI1CLKSOURCE_PLLSAI1 0x00000000U +#if defined(RCC_PLLSAI2_SUPPORT) +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +#define RCC_SAI1CLKSOURCE_PLLSAI2 RCC_CCIPR2_SAI1SEL_0 +#else +#define RCC_SAI1CLKSOURCE_PLLSAI2 RCC_CCIPR_SAI1SEL_0 +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ +#endif /* RCC_PLLSAI2_SUPPORT */ +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +#define RCC_SAI1CLKSOURCE_PLL RCC_CCIPR2_SAI1SEL_1 +#define RCC_SAI1CLKSOURCE_PIN (RCC_CCIPR2_SAI1SEL_1 | RCC_CCIPR2_SAI1SEL_0) +#define RCC_SAI1CLKSOURCE_HSI RCC_CCIPR2_SAI1SEL_2 +#else +#define RCC_SAI1CLKSOURCE_PLL RCC_CCIPR_SAI1SEL_1 +#define RCC_SAI1CLKSOURCE_PIN RCC_CCIPR_SAI1SEL +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ +/** + * @} + */ + +#if defined(SAI2) +/** @defgroup RCCEx_SAI2_Clock_Source SAI2 Clock Source + * @{ + */ +#define RCC_SAI2CLKSOURCE_PLLSAI1 0x00000000U +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +#define RCC_SAI2CLKSOURCE_PLLSAI2 RCC_CCIPR2_SAI2SEL_0 +#define RCC_SAI2CLKSOURCE_PLL RCC_CCIPR2_SAI2SEL_1 +#define RCC_SAI2CLKSOURCE_PIN (RCC_CCIPR2_SAI2SEL_1 | RCC_CCIPR2_SAI2SEL_0) +#define RCC_SAI2CLKSOURCE_HSI RCC_CCIPR2_SAI2SEL_2 +#else +#define RCC_SAI2CLKSOURCE_PLLSAI2 RCC_CCIPR_SAI2SEL_0 +#define RCC_SAI2CLKSOURCE_PLL RCC_CCIPR_SAI2SEL_1 +#define RCC_SAI2CLKSOURCE_PIN RCC_CCIPR_SAI2SEL +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ +/** + * @} + */ +#endif /* SAI2 */ + +/** @defgroup RCCEx_LPTIM1_Clock_Source LPTIM1 Clock Source + * @{ + */ +#define RCC_LPTIM1CLKSOURCE_PCLK1 0x00000000U +#define RCC_LPTIM1CLKSOURCE_LSI RCC_CCIPR_LPTIM1SEL_0 +#define RCC_LPTIM1CLKSOURCE_HSI RCC_CCIPR_LPTIM1SEL_1 +#define RCC_LPTIM1CLKSOURCE_LSE RCC_CCIPR_LPTIM1SEL +/** + * @} + */ + +/** @defgroup RCCEx_LPTIM2_Clock_Source LPTIM2 Clock Source + * @{ + */ +#define RCC_LPTIM2CLKSOURCE_PCLK1 0x00000000U +#define RCC_LPTIM2CLKSOURCE_LSI RCC_CCIPR_LPTIM2SEL_0 +#define RCC_LPTIM2CLKSOURCE_HSI RCC_CCIPR_LPTIM2SEL_1 +#define RCC_LPTIM2CLKSOURCE_LSE RCC_CCIPR_LPTIM2SEL +/** + * @} + */ + +#if defined(SDMMC1) +/** @defgroup RCCEx_SDMMC1_Clock_Source SDMMC1 Clock Source + * @{ + */ +#if defined(RCC_HSI48_SUPPORT) +#define RCC_SDMMC1CLKSOURCE_HSI48 0x00000000U /*!< HSI48 clock selected as SDMMC1 clock */ +#else +#define RCC_SDMMC1CLKSOURCE_NONE 0x00000000U /*!< No clock selected as SDMMC1 clock */ +#endif /* RCC_HSI48_SUPPORT */ +#define RCC_SDMMC1CLKSOURCE_PLLSAI1 RCC_CCIPR_CLK48SEL_0 /*!< PLLSAI1 "Q" clock selected as SDMMC1 clock */ +#define RCC_SDMMC1CLKSOURCE_PLL RCC_CCIPR_CLK48SEL_1 /*!< PLL "Q" clock selected as SDMMC1 clock */ +#define RCC_SDMMC1CLKSOURCE_MSI RCC_CCIPR_CLK48SEL /*!< MSI clock selected as SDMMC1 clock */ +#if defined(RCC_CCIPR2_SDMMCSEL) +#define RCC_SDMMC1CLKSOURCE_PLLP RCC_CCIPR2_SDMMCSEL /*!< PLL "P" clock selected as SDMMC1 kernel clock */ +#endif /* RCC_CCIPR2_SDMMCSEL */ +/** + * @} + */ +#endif /* SDMMC1 */ + +/** @defgroup RCCEx_RNG_Clock_Source RNG Clock Source + * @{ + */ +#if defined(RCC_HSI48_SUPPORT) +#define RCC_RNGCLKSOURCE_HSI48 0x00000000U +#else +#define RCC_RNGCLKSOURCE_NONE 0x00000000U +#endif /* RCC_HSI48_SUPPORT */ +#define RCC_RNGCLKSOURCE_PLLSAI1 RCC_CCIPR_CLK48SEL_0 +#define RCC_RNGCLKSOURCE_PLL RCC_CCIPR_CLK48SEL_1 +#define RCC_RNGCLKSOURCE_MSI RCC_CCIPR_CLK48SEL +/** + * @} + */ + +#if defined(USB_OTG_FS) || defined(USB) +/** @defgroup RCCEx_USB_Clock_Source USB Clock Source + * @{ + */ +#if defined(RCC_HSI48_SUPPORT) +#define RCC_USBCLKSOURCE_HSI48 0x00000000U +#else +#define RCC_USBCLKSOURCE_NONE 0x00000000U +#endif /* RCC_HSI48_SUPPORT */ +#define RCC_USBCLKSOURCE_PLLSAI1 RCC_CCIPR_CLK48SEL_0 +#define RCC_USBCLKSOURCE_PLL RCC_CCIPR_CLK48SEL_1 +#define RCC_USBCLKSOURCE_MSI RCC_CCIPR_CLK48SEL +/** + * @} + */ +#endif /* USB_OTG_FS || USB */ + +/** @defgroup RCCEx_ADC_Clock_Source ADC Clock Source + * @{ + */ +#define RCC_ADCCLKSOURCE_NONE 0x00000000U +#define RCC_ADCCLKSOURCE_PLLSAI1 RCC_CCIPR_ADCSEL_0 +#if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || defined(STM32L496xx) || defined(STM32L4A6xx) +#define RCC_ADCCLKSOURCE_PLLSAI2 RCC_CCIPR_ADCSEL_1 +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || STM32L496xx || STM32L4A6xx */ +#define RCC_ADCCLKSOURCE_SYSCLK RCC_CCIPR_ADCSEL +/** + * @} + */ + +#if defined(SWPMI1) +/** @defgroup RCCEx_SWPMI1_Clock_Source SWPMI1 Clock Source + * @{ + */ +#define RCC_SWPMI1CLKSOURCE_PCLK1 0x00000000U +#define RCC_SWPMI1CLKSOURCE_HSI RCC_CCIPR_SWPMI1SEL +/** + * @} + */ +#endif /* SWPMI1 */ + +#if defined(DFSDM1_Filter0) +/** @defgroup RCCEx_DFSDM1_Clock_Source DFSDM1 Clock Source + * @{ + */ +#define RCC_DFSDM1CLKSOURCE_PCLK2 0x00000000U +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +#define RCC_DFSDM1CLKSOURCE_SYSCLK RCC_CCIPR2_DFSDM1SEL +#else +#define RCC_DFSDM1CLKSOURCE_SYSCLK RCC_CCIPR_DFSDM1SEL +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ +/** + * @} + */ + +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +/** @defgroup RCCEx_DFSDM1_Audio_Clock_Source DFSDM1 Audio Clock Source + * @{ + */ +#define RCC_DFSDM1AUDIOCLKSOURCE_SAI1 0x00000000U +#define RCC_DFSDM1AUDIOCLKSOURCE_HSI RCC_CCIPR2_ADFSDM1SEL_0 +#define RCC_DFSDM1AUDIOCLKSOURCE_MSI RCC_CCIPR2_ADFSDM1SEL_1 +/** + * @} + */ +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ +#endif /* DFSDM1_Filter0 */ + +#if defined(LTDC) +/** @defgroup RCCEx_LTDC_Clock_Source LTDC Clock Source + * @{ + */ +#define RCC_LTDCCLKSOURCE_PLLSAI2_DIV2 0x00000000U +#define RCC_LTDCCLKSOURCE_PLLSAI2_DIV4 RCC_CCIPR2_PLLSAI2DIVR_0 +#define RCC_LTDCCLKSOURCE_PLLSAI2_DIV8 RCC_CCIPR2_PLLSAI2DIVR_1 +#define RCC_LTDCCLKSOURCE_PLLSAI2_DIV16 RCC_CCIPR2_PLLSAI2DIVR +/** + * @} + */ +#endif /* LTDC */ + +#if defined(DSI) +/** @defgroup RCCEx_DSI_Clock_Source DSI Clock Source + * @{ + */ +#define RCC_DSICLKSOURCE_DSIPHY 0x00000000U +#define RCC_DSICLKSOURCE_PLLSAI2 RCC_CCIPR2_DSISEL +/** + * @} + */ +#endif /* DSI */ + +#if defined(OCTOSPI1) || defined(OCTOSPI2) +/** @defgroup RCCEx_OSPI_Clock_Source OctoSPI Clock Source + * @{ + */ +#define RCC_OSPICLKSOURCE_SYSCLK 0x00000000U +#define RCC_OSPICLKSOURCE_MSI RCC_CCIPR2_OSPISEL_0 +#define RCC_OSPICLKSOURCE_PLL RCC_CCIPR2_OSPISEL_1 +/** + * @} + */ +#endif /* OCTOSPI1 || OCTOSPI2 */ + +/** @defgroup RCCEx_EXTI_LINE_LSECSS RCC LSE CSS external interrupt line + * @{ + */ +#define RCC_EXTI_LINE_LSECSS EXTI_IMR1_IM19 /*!< External interrupt line 19 connected to the LSE CSS EXTI Line */ +/** + * @} + */ + +#if defined(CRS) + +/** @defgroup RCCEx_CRS_Status RCCEx CRS Status + * @{ + */ +#define RCC_CRS_NONE 0x00000000U +#define RCC_CRS_TIMEOUT 0x00000001U +#define RCC_CRS_SYNCOK 0x00000002U +#define RCC_CRS_SYNCWARN 0x00000004U +#define RCC_CRS_SYNCERR 0x00000008U +#define RCC_CRS_SYNCMISS 0x00000010U +#define RCC_CRS_TRIMOVF 0x00000020U +/** + * @} + */ + +/** @defgroup RCCEx_CRS_SynchroSource RCCEx CRS SynchroSource + * @{ + */ +#define RCC_CRS_SYNC_SOURCE_GPIO 0x00000000U /*!< Synchro Signal source GPIO */ +#define RCC_CRS_SYNC_SOURCE_LSE CRS_CFGR_SYNCSRC_0 /*!< Synchro Signal source LSE */ +#define RCC_CRS_SYNC_SOURCE_USB CRS_CFGR_SYNCSRC_1 /*!< Synchro Signal source USB SOF (default)*/ +/** + * @} + */ + +/** @defgroup RCCEx_CRS_SynchroDivider RCCEx CRS SynchroDivider + * @{ + */ +#define RCC_CRS_SYNC_DIV1 0x00000000U /*!< Synchro Signal not divided (default) */ +#define RCC_CRS_SYNC_DIV2 CRS_CFGR_SYNCDIV_0 /*!< Synchro Signal divided by 2 */ +#define RCC_CRS_SYNC_DIV4 CRS_CFGR_SYNCDIV_1 /*!< Synchro Signal divided by 4 */ +#define RCC_CRS_SYNC_DIV8 (CRS_CFGR_SYNCDIV_1 | CRS_CFGR_SYNCDIV_0) /*!< Synchro Signal divided by 8 */ +#define RCC_CRS_SYNC_DIV16 CRS_CFGR_SYNCDIV_2 /*!< Synchro Signal divided by 16 */ +#define RCC_CRS_SYNC_DIV32 (CRS_CFGR_SYNCDIV_2 | CRS_CFGR_SYNCDIV_0) /*!< Synchro Signal divided by 32 */ +#define RCC_CRS_SYNC_DIV64 (CRS_CFGR_SYNCDIV_2 | CRS_CFGR_SYNCDIV_1) /*!< Synchro Signal divided by 64 */ +#define RCC_CRS_SYNC_DIV128 CRS_CFGR_SYNCDIV /*!< Synchro Signal divided by 128 */ +/** + * @} + */ + +/** @defgroup RCCEx_CRS_SynchroPolarity RCCEx CRS SynchroPolarity + * @{ + */ +#define RCC_CRS_SYNC_POLARITY_RISING 0x00000000U /*!< Synchro Active on rising edge (default) */ +#define RCC_CRS_SYNC_POLARITY_FALLING CRS_CFGR_SYNCPOL /*!< Synchro Active on falling edge */ +/** + * @} + */ + +/** @defgroup RCCEx_CRS_ReloadValueDefault RCCEx CRS ReloadValueDefault + * @{ + */ +#define RCC_CRS_RELOADVALUE_DEFAULT 0x0000BB7FU /*!< The reset value of the RELOAD field corresponds + to a target frequency of 48 MHz and a synchronization signal frequency of 1 kHz (SOF signal from USB). */ +/** + * @} + */ + +/** @defgroup RCCEx_CRS_ErrorLimitDefault RCCEx CRS ErrorLimitDefault + * @{ + */ +#define RCC_CRS_ERRORLIMIT_DEFAULT 0x00000022U /*!< Default Frequency error limit */ +/** + * @} + */ + +/** @defgroup RCCEx_CRS_HSI48CalibrationDefault RCCEx CRS HSI48CalibrationDefault + * @{ + */ +#define RCC_CRS_HSI48CALIBRATION_DEFAULT 0x00000020U /*!< The default value is 32, which corresponds to the middle of the trimming interval. + The trimming step is around 67 kHz between two consecutive TRIM steps. A higher TRIM value + corresponds to a higher output frequency */ +/** + * @} + */ + +/** @defgroup RCCEx_CRS_FreqErrorDirection RCCEx CRS FreqErrorDirection + * @{ + */ +#define RCC_CRS_FREQERRORDIR_UP 0x00000000U /*!< Upcounting direction, the actual frequency is above the target */ +#define RCC_CRS_FREQERRORDIR_DOWN CRS_ISR_FEDIR /*!< Downcounting direction, the actual frequency is below the target */ +/** + * @} + */ + +/** @defgroup RCCEx_CRS_Interrupt_Sources RCCEx CRS Interrupt Sources + * @{ + */ +#define RCC_CRS_IT_SYNCOK CRS_CR_SYNCOKIE /*!< SYNC event OK */ +#define RCC_CRS_IT_SYNCWARN CRS_CR_SYNCWARNIE /*!< SYNC warning */ +#define RCC_CRS_IT_ERR CRS_CR_ERRIE /*!< Error */ +#define RCC_CRS_IT_ESYNC CRS_CR_ESYNCIE /*!< Expected SYNC */ +#define RCC_CRS_IT_SYNCERR CRS_CR_ERRIE /*!< SYNC error */ +#define RCC_CRS_IT_SYNCMISS CRS_CR_ERRIE /*!< SYNC missed */ +#define RCC_CRS_IT_TRIMOVF CRS_CR_ERRIE /*!< Trimming overflow or underflow */ + +/** + * @} + */ + +/** @defgroup RCCEx_CRS_Flags RCCEx CRS Flags + * @{ + */ +#define RCC_CRS_FLAG_SYNCOK CRS_ISR_SYNCOKF /*!< SYNC event OK flag */ +#define RCC_CRS_FLAG_SYNCWARN CRS_ISR_SYNCWARNF /*!< SYNC warning flag */ +#define RCC_CRS_FLAG_ERR CRS_ISR_ERRF /*!< Error flag */ +#define RCC_CRS_FLAG_ESYNC CRS_ISR_ESYNCF /*!< Expected SYNC flag */ +#define RCC_CRS_FLAG_SYNCERR CRS_ISR_SYNCERR /*!< SYNC error */ +#define RCC_CRS_FLAG_SYNCMISS CRS_ISR_SYNCMISS /*!< SYNC missed*/ +#define RCC_CRS_FLAG_TRIMOVF CRS_ISR_TRIMOVF /*!< Trimming overflow or underflow */ + +/** + * @} + */ + +#endif /* CRS */ + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ +/** @defgroup RCCEx_Exported_Macros RCCEx Exported Macros + * @{ + */ + + +/** + * @brief Macro to configure the PLLSAI1 clock multiplication and division factors. + * + * @note This function must be used only when the PLLSAI1 is disabled. + * @note PLLSAI1 clock source is common with the main PLL (configured through + * __HAL_RCC_PLL_CONFIG() macro) + * + @if STM32L4S9xx + * @param __PLLSAI1M__ specifies the division factor of PLLSAI1 input clock. + * This parameter must be a number between Min_Data = 1 and Max_Data = 16. + * + @endif + * @param __PLLSAI1N__ specifies the multiplication factor for PLLSAI1 VCO output clock. + * This parameter must be a number between 8 and 86. + * @note You have to set the PLLSAI1N parameter correctly to ensure that the VCO + * output frequency is between 64 and 344 MHz. + * PLLSAI1 clock frequency = f(PLLSAI1) multiplied by PLLSAI1N + * + * @param __PLLSAI1P__ specifies the division factor for SAI clock. + * This parameter must be a number in the range (7 or 17) for STM32L47xxx/L48xxx + * else (2 to 31). + * SAI1 clock frequency = f(PLLSAI1) / PLLSAI1P + * + * @param __PLLSAI1Q__ specifies the division factor for USB/RNG/SDMMC1 clock. + * This parameter must be in the range (2, 4, 6 or 8). + * USB/RNG/SDMMC1 clock frequency = f(PLLSAI1) / PLLSAI1Q + * + * @param __PLLSAI1R__ specifies the division factor for SAR ADC clock. + * This parameter must be in the range (2, 4, 6 or 8). + * ADC clock frequency = f(PLLSAI1) / PLLSAI1R + * + * @retval None + */ +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + +#if defined(RCC_PLLSAI1P_DIV_2_31_SUPPORT) + +#define __HAL_RCC_PLLSAI1_CONFIG(__PLLSAI1M__, __PLLSAI1N__, __PLLSAI1P__, __PLLSAI1Q__, __PLLSAI1R__) \ + WRITE_REG(RCC->PLLSAI1CFGR, ((__PLLSAI1N__) << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) | \ + ((((__PLLSAI1Q__) >> 1U) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1Q_Pos) | \ + ((((__PLLSAI1R__) >> 1U) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1R_Pos) | \ + ((__PLLSAI1P__) << RCC_PLLSAI1CFGR_PLLSAI1PDIV_Pos) | \ + (((__PLLSAI1M__) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1M_Pos)) + +#else + +#define __HAL_RCC_PLLSAI1_CONFIG(__PLLSAI1M__, __PLLSAI1N__, __PLLSAI1P__, __PLLSAI1Q__, __PLLSAI1R__) \ + WRITE_REG(RCC->PLLSAI1CFGR, ((__PLLSAI1N__) << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) | \ + (((__PLLSAI1P__) >> 4U) << RCC_PLLSAI1CFGR_PLLSAI1P_Pos) | \ + ((((__PLLSAI1Q__) >> 1U) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1Q_Pos) | \ + ((((__PLLSAI1R__) >> 1U) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1R_Pos) | \ + (((__PLLSAI1M__) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1M_Pos)) + +#endif /* RCC_PLLSAI1P_DIV_2_31_SUPPORT */ + +#else + +#if defined(RCC_PLLSAI1P_DIV_2_31_SUPPORT) + +#define __HAL_RCC_PLLSAI1_CONFIG(__PLLSAI1N__, __PLLSAI1P__, __PLLSAI1Q__, __PLLSAI1R__) \ + WRITE_REG(RCC->PLLSAI1CFGR, ((__PLLSAI1N__) << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) | \ + ((((__PLLSAI1Q__) >> 1U) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1Q_Pos) | \ + ((((__PLLSAI1R__) >> 1U) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1R_Pos) | \ + ((__PLLSAI1P__) << RCC_PLLSAI1CFGR_PLLSAI1PDIV_Pos)) + +#else + +#define __HAL_RCC_PLLSAI1_CONFIG(__PLLSAI1N__, __PLLSAI1P__, __PLLSAI1Q__, __PLLSAI1R__) \ + WRITE_REG(RCC->PLLSAI1CFGR, ((__PLLSAI1N__) << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) | \ + (((__PLLSAI1P__) >> 4U) << RCC_PLLSAI1CFGR_PLLSAI1P_Pos) | \ + ((((__PLLSAI1Q__) >> 1U) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1Q_Pos) | \ + ((((__PLLSAI1R__) >> 1U) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1R_Pos)) + +#endif /* RCC_PLLSAI1P_DIV_2_31_SUPPORT */ + +#endif /* RCC_PLLSAI1M_DIV_1_16_SUPPORT */ + +/** + * @brief Macro to configure the PLLSAI1 clock multiplication factor N. + * + * @note This function must be used only when the PLLSAI1 is disabled. + * @note PLLSAI1 clock source is common with the main PLL (configured through + * __HAL_RCC_PLL_CONFIG() macro) + * + * @param __PLLSAI1N__ specifies the multiplication factor for PLLSAI1 VCO output clock. + * This parameter must be a number between 8 and 86. + * @note You have to set the PLLSAI1N parameter correctly to ensure that the VCO + * output frequency is between 64 and 344 MHz. + * Use to set PLLSAI1 clock frequency = f(PLLSAI1) multiplied by PLLSAI1N + * + * @retval None + */ +#define __HAL_RCC_PLLSAI1_MULN_CONFIG(__PLLSAI1N__) \ + MODIFY_REG(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N, (__PLLSAI1N__) << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) + +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + +/** @brief Macro to configure the PLLSAI1 input clock division factor M. + * + * @note This function must be used only when the PLLSAI1 is disabled. + * @note PLLSAI1 clock source is common with the main PLL (configured through + * __HAL_RCC_PLL_CONFIG() macro) + * + * @param __PLLSAI1M__ specifies the division factor for PLLSAI1 clock. + * This parameter must be a number between Min_Data = 1 and Max_Data = 16. + * + * @retval None + */ + +#define __HAL_RCC_PLLSAI1_DIVM_CONFIG(__PLLSAI1M__) \ + MODIFY_REG(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1M, ((__PLLSAI1M__) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1M_Pos) + +#endif /* RCC_PLLSAI1M_DIV_1_16_SUPPORT */ + +/** @brief Macro to configure the PLLSAI1 clock division factor P. + * + * @note This function must be used only when the PLLSAI1 is disabled. + * @note PLLSAI1 clock source is common with the main PLL (configured through + * __HAL_RCC_PLL_CONFIG() macro) + * + * @param __PLLSAI1P__ specifies the division factor for SAI clock. + * This parameter must be a number in the range (7 or 17) for STM32L47xxx/L48xxx + * else (2 to 31). + * Use to set SAI1 clock frequency = f(PLLSAI1) / PLLSAI1P + * + * @retval None + */ +#if defined(RCC_PLLSAI1P_DIV_2_31_SUPPORT) + +#define __HAL_RCC_PLLSAI1_DIVP_CONFIG(__PLLSAI1P__) \ + MODIFY_REG(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1PDIV, (__PLLSAI1P__) << RCC_PLLSAI1CFGR_PLLSAI1PDIV_Pos) + +#else + +#define __HAL_RCC_PLLSAI1_DIVP_CONFIG(__PLLSAI1P__) \ + MODIFY_REG(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1P, ((__PLLSAI1P__) >> 4U) << RCC_PLLSAI1CFGR_PLLSAI1P_Pos) + +#endif /* RCC_PLLSAI1P_DIV_2_31_SUPPORT */ + +/** @brief Macro to configure the PLLSAI1 clock division factor Q. + * + * @note This function must be used only when the PLLSAI1 is disabled. + * @note PLLSAI1 clock source is common with the main PLL (configured through + * __HAL_RCC_PLL_CONFIG() macro) + * + * @param __PLLSAI1Q__ specifies the division factor for USB/RNG/SDMMC1 clock. + * This parameter must be in the range (2, 4, 6 or 8). + * Use to set USB/RNG/SDMMC1 clock frequency = f(PLLSAI1) / PLLSAI1Q + * + * @retval None + */ +#define __HAL_RCC_PLLSAI1_DIVQ_CONFIG(__PLLSAI1Q__) \ + MODIFY_REG(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1Q, (((__PLLSAI1Q__) >> 1U) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1Q_Pos) + +/** @brief Macro to configure the PLLSAI1 clock division factor R. + * + * @note This function must be used only when the PLLSAI1 is disabled. + * @note PLLSAI1 clock source is common with the main PLL (configured through + * __HAL_RCC_PLL_CONFIG() macro) + * + * @param __PLLSAI1R__ specifies the division factor for ADC clock. + * This parameter must be in the range (2, 4, 6 or 8) + * Use to set ADC clock frequency = f(PLLSAI1) / PLLSAI1R + * + * @retval None + */ +#define __HAL_RCC_PLLSAI1_DIVR_CONFIG(__PLLSAI1R__) \ + MODIFY_REG(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1R, (((__PLLSAI1R__) >> 1U) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1R_Pos) + +/** + * @brief Macros to enable or disable the PLLSAI1. + * @note The PLLSAI1 is disabled by hardware when entering STOP and STANDBY modes. + * @retval None + */ + +#define __HAL_RCC_PLLSAI1_ENABLE() SET_BIT(RCC->CR, RCC_CR_PLLSAI1ON) + +#define __HAL_RCC_PLLSAI1_DISABLE() CLEAR_BIT(RCC->CR, RCC_CR_PLLSAI1ON) + +/** + * @brief Macros to enable or disable each clock output (PLLSAI1_SAI1, PLLSAI1_USB2 and PLLSAI1_ADC1). + * @note Enabling and disabling those clocks can be done without the need to stop the PLL. + * This is mainly used to save Power. + * @param __PLLSAI1_CLOCKOUT__ specifies the PLLSAI1 clock to be output. + * This parameter can be one or a combination of the following values: + * @arg @ref RCC_PLLSAI1_SAI1CLK This clock is used to generate an accurate clock to achieve + * high-quality audio performance on SAI interface in case. + * @arg @ref RCC_PLLSAI1_48M2CLK This clock is used to generate the clock for the USB OTG FS (48 MHz), + * the random number generator (<=48 MHz) and the SDIO (<= 48 MHz). + * @arg @ref RCC_PLLSAI1_ADC1CLK Clock used to clock ADC peripheral. + * @retval None + */ + +#define __HAL_RCC_PLLSAI1CLKOUT_ENABLE(__PLLSAI1_CLOCKOUT__) SET_BIT(RCC->PLLSAI1CFGR, (__PLLSAI1_CLOCKOUT__)) + +#define __HAL_RCC_PLLSAI1CLKOUT_DISABLE(__PLLSAI1_CLOCKOUT__) CLEAR_BIT(RCC->PLLSAI1CFGR, (__PLLSAI1_CLOCKOUT__)) + +/** + * @brief Macro to get clock output enable status (PLLSAI1_SAI1, PLLSAI1_USB2 and PLLSAI1_ADC1). + * @param __PLLSAI1_CLOCKOUT__ specifies the PLLSAI1 clock to be output. + * This parameter can be one of the following values: + * @arg @ref RCC_PLLSAI1_SAI1CLK This clock is used to generate an accurate clock to achieve + * high-quality audio performance on SAI interface in case. + * @arg @ref RCC_PLLSAI1_48M2CLK This clock is used to generate the clock for the USB OTG FS (48 MHz), + * the random number generator (<=48 MHz) and the SDIO (<= 48 MHz). + * @arg @ref RCC_PLLSAI1_ADC1CLK Clock used to clock ADC peripheral. + * @retval SET / RESET + */ +#define __HAL_RCC_GET_PLLSAI1CLKOUT_CONFIG(__PLLSAI1_CLOCKOUT__) READ_BIT(RCC->PLLSAI1CFGR, (__PLLSAI1_CLOCKOUT__)) + +#if defined(RCC_PLLSAI2_SUPPORT) + +/** + * @brief Macro to configure the PLLSAI2 clock multiplication and division factors. + * + * @note This function must be used only when the PLLSAI2 is disabled. + * @note PLLSAI2 clock source is common with the main PLL (configured through + * __HAL_RCC_PLL_CONFIG() macro) + * + @if STM32L4S9xx + * @param __PLLSAI2M__ specifies the division factor of PLLSAI2 input clock. + * This parameter must be a number between Min_Data = 1 and Max_Data = 16. + * + @endif + * @param __PLLSAI2N__ specifies the multiplication factor for PLLSAI2 VCO output clock. + * This parameter must be a number between 8 and 86. + * @note You have to set the PLLSAI2N parameter correctly to ensure that the VCO + * output frequency is between 64 and 344 MHz. + * + * @param __PLLSAI2P__ specifies the division factor for SAI clock. + * This parameter must be a number in the range (7 or 17) for STM32L47xxx/L48xxx + * else (2 to 31). + * SAI2 clock frequency = f(PLLSAI2) / PLLSAI2P + * + @if STM32L4S9xx + * @param __PLLSAI2Q__ specifies the division factor for DSI clock. + * This parameter must be in the range (2, 4, 6 or 8). + * DSI clock frequency = f(PLLSAI2) / PLLSAI2Q + * + @endif + * @param __PLLSAI2R__ specifies the division factor for SAR ADC clock. + * This parameter must be in the range (2, 4, 6 or 8). + * + * @retval None + */ + +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + +# if defined(RCC_PLLSAI2P_DIV_2_31_SUPPORT) && defined(RCC_PLLSAI2Q_DIV_SUPPORT) + +#define __HAL_RCC_PLLSAI2_CONFIG(__PLLSAI2M__, __PLLSAI2N__, __PLLSAI2P__, __PLLSAI2Q__, __PLLSAI2R__) \ + WRITE_REG(RCC->PLLSAI2CFGR, ((__PLLSAI2N__) << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | \ + ((((__PLLSAI2Q__) >> 1U) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2Q_Pos) | \ + ((((__PLLSAI2R__) >> 1U) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2R_Pos) | \ + ((__PLLSAI2P__) << RCC_PLLSAI2CFGR_PLLSAI2PDIV_Pos) | \ + (((__PLLSAI2M__) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2M_Pos)) + +# elif defined(RCC_PLLSAI2P_DIV_2_31_SUPPORT) + +#define __HAL_RCC_PLLSAI2_CONFIG(__PLLSAI2M__, __PLLSAI2N__, __PLLSAI2P__, __PLLSAI2R__) \ + WRITE_REG(RCC->PLLSAI2CFGR, ((__PLLSAI2N__) << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | \ + ((((__PLLSAI2R__) >> 1U) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2R_Pos) | \ + ((__PLLSAI2P__) << RCC_PLLSAI2CFGR_PLLSAI2PDIV_Pos) | \ + (((__PLLSAI2M__) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2M_Pos)) + +# else + +#define __HAL_RCC_PLLSAI2_CONFIG(__PLLSAI2M__, __PLLSAI2N__, __PLLSAI2P__, __PLLSAI2R__) \ + WRITE_REG(RCC->PLLSAI2CFGR, ((__PLLSAI2N__) << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | \ + (((__PLLSAI2P__) >> 4U) << RCC_PLLSAI2CFGR_PLLSAI2P_Pos) | \ + ((((__PLLSAI2R__) >> 1U) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2R_Pos) | \ + (((__PLLSAI2M__) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2M_Pos)) + +# endif /* RCC_PLLSAI2P_DIV_2_31_SUPPORT && RCC_PLLSAI2Q_DIV_SUPPORT */ + +#else + +# if defined(RCC_PLLSAI2P_DIV_2_31_SUPPORT) && defined(RCC_PLLSAI2Q_DIV_SUPPORT) + +#define __HAL_RCC_PLLSAI2_CONFIG(__PLLSAI2N__, __PLLSAI2P__, __PLLSAI2Q__, __PLLSAI2R__) \ + WRITE_REG(RCC->PLLSAI2CFGR, ((__PLLSAI2N__) << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | \ + ((((__PLLSAI2Q__) >> 1U) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2Q_Pos) | \ + ((((__PLLSAI2R__) >> 1U) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2R_Pos) | \ + ((__PLLSAI2P__) << RCC_PLLSAI2CFGR_PLLSAI2PDIV_Pos)) + +# elif defined(RCC_PLLSAI2P_DIV_2_31_SUPPORT) + +#define __HAL_RCC_PLLSAI2_CONFIG(__PLLSAI2N__, __PLLSAI2P__, __PLLSAI2R__) \ + WRITE_REG(RCC->PLLSAI2CFGR, ((__PLLSAI2N__) << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | \ + ((((__PLLSAI2R__) >> 1U) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2R_Pos) | \ + ((__PLLSAI2P__) << RCC_PLLSAI2CFGR_PLLSAI2PDIV_Pos)) + +# else + +#define __HAL_RCC_PLLSAI2_CONFIG(__PLLSAI2N__, __PLLSAI2P__, __PLLSAI2R__) \ + WRITE_REG(RCC->PLLSAI2CFGR, ((__PLLSAI2N__) << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | \ + (((__PLLSAI2P__) >> 4U) << RCC_PLLSAI2CFGR_PLLSAI2P_Pos) | \ + ((((__PLLSAI2R__) >> 1U) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2R_Pos)) + +# endif /* RCC_PLLSAI2P_DIV_2_31_SUPPORT && RCC_PLLSAI2Q_DIV_SUPPORT */ + +#endif /* RCC_PLLSAI2M_DIV_1_16_SUPPORT */ + + +/** + * @brief Macro to configure the PLLSAI2 clock multiplication factor N. + * + * @note This function must be used only when the PLLSAI2 is disabled. + * @note PLLSAI2 clock source is common with the main PLL (configured through + * __HAL_RCC_PLL_CONFIG() macro) + * + * @param __PLLSAI2N__ specifies the multiplication factor for PLLSAI2 VCO output clock. + * This parameter must be a number between 8 and 86. + * @note You have to set the PLLSAI2N parameter correctly to ensure that the VCO + * output frequency is between 64 and 344 MHz. + * PLLSAI1 clock frequency = f(PLLSAI1) multiplied by PLLSAI2N + * + * @retval None + */ +#define __HAL_RCC_PLLSAI2_MULN_CONFIG(__PLLSAI2N__) \ + MODIFY_REG(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2N, (__PLLSAI2N__) << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) + +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + +/** @brief Macro to configure the PLLSAI2 input clock division factor M. + * + * @note This function must be used only when the PLLSAI2 is disabled. + * @note PLLSAI2 clock source is common with the main PLL (configured through + * __HAL_RCC_PLL_CONFIG() macro) + * + * @param __PLLSAI2M__ specifies the division factor for PLLSAI2 clock. + * This parameter must be a number between Min_Data = 1 and Max_Data = 16. + * + * @retval None + */ + +#define __HAL_RCC_PLLSAI2_DIVM_CONFIG(__PLLSAI2M__) \ + MODIFY_REG(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2M, ((__PLLSAI2M__) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2M_Pos) + +#endif /* RCC_PLLSAI2M_DIV_1_16_SUPPORT */ + +/** @brief Macro to configure the PLLSAI2 clock division factor P. + * + * @note This function must be used only when the PLLSAI2 is disabled. + * @note PLLSAI2 clock source is common with the main PLL (configured through + * __HAL_RCC_PLL_CONFIG() macro) + * + * @param __PLLSAI2P__ specifies the division factor. + * This parameter must be a number in the range (7 or 17). + * Use to set SAI2 clock frequency = f(PLLSAI2) / __PLLSAI2P__ + * + * @retval None + */ +#define __HAL_RCC_PLLSAI2_DIVP_CONFIG(__PLLSAI2P__) \ + MODIFY_REG(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2P, ((__PLLSAI2P__) >> 4U) << RCC_PLLSAI2CFGR_PLLSAI2P_Pos) + +#if defined(RCC_PLLSAI2Q_DIV_SUPPORT) + +/** @brief Macro to configure the PLLSAI2 clock division factor Q. + * + * @note This function must be used only when the PLLSAI2 is disabled. + * @note PLLSAI2 clock source is common with the main PLL (configured through + * __HAL_RCC_PLL_CONFIG() macro) + * + * @param __PLLSAI2Q__ specifies the division factor for USB/RNG/SDMMC1 clock. + * This parameter must be in the range (2, 4, 6 or 8). + * Use to set USB/RNG/SDMMC1 clock frequency = f(PLLSAI2) / PLLSAI2Q + * + * @retval None + */ +#define __HAL_RCC_PLLSAI2_DIVQ_CONFIG(__PLLSAI2Q__) \ + MODIFY_REG(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2Q, (((__PLLSAI2Q__) >> 1U) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2Q_Pos) + +#endif /* RCC_PLLSAI2Q_DIV_SUPPORT */ + +/** @brief Macro to configure the PLLSAI2 clock division factor R. + * + * @note This function must be used only when the PLLSAI2 is disabled. + * @note PLLSAI2 clock source is common with the main PLL (configured through + * __HAL_RCC_PLL_CONFIG() macro) + * + * @param __PLLSAI2R__ specifies the division factor. + * This parameter must be in the range (2, 4, 6 or 8). + * Use to set ADC clock frequency = f(PLLSAI2) / __PLLSAI2R__ + * + * @retval None + */ +#define __HAL_RCC_PLLSAI2_DIVR_CONFIG(__PLLSAI2R__) \ + MODIFY_REG(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2R, (((__PLLSAI2R__) >> 1U) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2R_Pos) + +/** + * @brief Macros to enable or disable the PLLSAI2. + * @note The PLLSAI2 is disabled by hardware when entering STOP and STANDBY modes. + * @retval None + */ + +#define __HAL_RCC_PLLSAI2_ENABLE() SET_BIT(RCC->CR, RCC_CR_PLLSAI2ON) + +#define __HAL_RCC_PLLSAI2_DISABLE() CLEAR_BIT(RCC->CR, RCC_CR_PLLSAI2ON) + +/** + * @brief Macros to enable or disable each clock output (PLLSAI2_SAI2, PLLSAI2_ADC2 and RCC_PLLSAI2_DSICLK). + * @note Enabling and disabling those clocks can be done without the need to stop the PLL. + * This is mainly used to save Power. + * @param __PLLSAI2_CLOCKOUT__ specifies the PLLSAI2 clock to be output. + * This parameter can be one or a combination of the following values: + @if STM32L486xx + * @arg @ref RCC_PLLSAI2_SAI2CLK This clock is used to generate an accurate clock to achieve + * high-quality audio performance on SAI interface in case. + * @arg @ref RCC_PLLSAI2_ADC2CLK Clock used to clock ADC peripheral. + @endif + @if STM32L4A6xx + * @arg @ref RCC_PLLSAI2_SAI2CLK This clock is used to generate an accurate clock to achieve + * high-quality audio performance on SAI interface in case. + * @arg @ref RCC_PLLSAI2_ADC2CLK Clock used to clock ADC peripheral. + @endif + @if STM32L4S9xx + * @arg @ref RCC_PLLSAI2_SAI2CLK This clock is used to generate an accurate clock to achieve + * high-quality audio performance on SAI interface in case. + * @arg @ref RCC_PLLSAI2_DSICLK Clock used to clock DSI peripheral. + @endif + * @retval None + */ + +#define __HAL_RCC_PLLSAI2CLKOUT_ENABLE(__PLLSAI2_CLOCKOUT__) SET_BIT(RCC->PLLSAI2CFGR, (__PLLSAI2_CLOCKOUT__)) + +#define __HAL_RCC_PLLSAI2CLKOUT_DISABLE(__PLLSAI2_CLOCKOUT__) CLEAR_BIT(RCC->PLLSAI2CFGR, (__PLLSAI2_CLOCKOUT__)) + +/** + * @brief Macro to get clock output enable status (PLLSAI2_SAI2, PLLSAI2_ADC2 and RCC_PLLSAI2_DSICLK). + * @param __PLLSAI2_CLOCKOUT__ specifies the PLLSAI2 clock to be output. + * This parameter can be one of the following values: + @if STM32L486xx + * @arg @ref RCC_PLLSAI2_SAI2CLK This clock is used to generate an accurate clock to achieve + * high-quality audio performance on SAI interface in case. + * @arg @ref RCC_PLLSAI2_ADC2CLK Clock used to clock ADC peripheral. + @endif + @if STM32L4A6xx + * @arg @ref RCC_PLLSAI2_SAI2CLK This clock is used to generate an accurate clock to achieve + * high-quality audio performance on SAI interface in case. + * @arg @ref RCC_PLLSAI2_ADC2CLK Clock used to clock ADC peripheral. + @endif + @if STM32L4S9xx + * @arg @ref RCC_PLLSAI2_SAI2CLK This clock is used to generate an accurate clock to achieve + * high-quality audio performance on SAI interface in case. + * @arg @ref RCC_PLLSAI2_DSICLK Clock used to clock DSI peripheral. + @endif + * @retval SET / RESET + */ +#define __HAL_RCC_GET_PLLSAI2CLKOUT_CONFIG(__PLLSAI2_CLOCKOUT__) READ_BIT(RCC->PLLSAI2CFGR, (__PLLSAI2_CLOCKOUT__)) + +#endif /* RCC_PLLSAI2_SUPPORT */ + +/** + * @brief Macro to configure the SAI1 clock source. + * @param __SAI1_CLKSOURCE__ defines the SAI1 clock source. This clock is derived + * from the PLLSAI1, system PLL or external clock (through a dedicated pin). + * This parameter can be one of the following values: + * @arg @ref RCC_SAI1CLKSOURCE_PLLSAI1 SAI1 clock = PLLSAI1 "P" clock (PLLSAI1CLK) + @if STM32L486xx + * @arg @ref RCC_SAI1CLKSOURCE_PLLSAI2 SAI1 clock = PLLSAI2 "P" clock (PLLSAI2CLK) for devices with PLLSAI2 + @endif + * @arg @ref RCC_SAI1CLKSOURCE_PLL SAI1 clock = PLL "P" clock (PLLSAI3CLK if PLLSAI2 exists, else PLLSAI2CLK) + * @arg @ref RCC_SAI1CLKSOURCE_PIN SAI1 clock = External Clock (SAI1_EXTCLK) + @if STM32L4S9xx + * @arg @ref RCC_SAI1CLKSOURCE_HSI SAI1 clock = HSI16 + @endif + * + @if STM32L443xx + * @note HSI16 is automatically set as SAI1 clock source when PLL are disabled for devices without PLLSAI2. + @endif + * + * @retval None + */ +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +#define __HAL_RCC_SAI1_CONFIG(__SAI1_CLKSOURCE__)\ + MODIFY_REG(RCC->CCIPR2, RCC_CCIPR2_SAI1SEL, (__SAI1_CLKSOURCE__)) +#else +#define __HAL_RCC_SAI1_CONFIG(__SAI1_CLKSOURCE__)\ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_SAI1SEL, (__SAI1_CLKSOURCE__)) +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +/** @brief Macro to get the SAI1 clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_SAI1CLKSOURCE_PLLSAI1 SAI1 clock = PLLSAI1 "P" clock (PLLSAI1CLK) + @if STM32L486xx + * @arg @ref RCC_SAI1CLKSOURCE_PLLSAI2 SAI1 clock = PLLSAI2 "P" clock (PLLSAI2CLK) for devices with PLLSAI2 + @endif + * @arg @ref RCC_SAI1CLKSOURCE_PLL SAI1 clock = PLL "P" clock (PLLSAI3CLK if PLLSAI2 exists, else PLLSAI2CLK) + * @arg @ref RCC_SAI1CLKSOURCE_PIN SAI1 clock = External Clock (SAI1_EXTCLK) + * + * @note Despite returned values RCC_SAI1CLKSOURCE_PLLSAI1 or RCC_SAI1CLKSOURCE_PLL, HSI16 is automatically set as SAI1 + * clock source when PLLs are disabled for devices without PLLSAI2. + * + */ +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +#define __HAL_RCC_GET_SAI1_SOURCE() (READ_BIT(RCC->CCIPR2, RCC_CCIPR2_SAI1SEL)) +#else +#define __HAL_RCC_GET_SAI1_SOURCE() (READ_BIT(RCC->CCIPR, RCC_CCIPR_SAI1SEL)) +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#if defined(SAI2) + +/** + * @brief Macro to configure the SAI2 clock source. + * @param __SAI2_CLKSOURCE__ defines the SAI2 clock source. This clock is derived + * from the PLLSAI2, system PLL or external clock (through a dedicated pin). + * This parameter can be one of the following values: + * @arg @ref RCC_SAI2CLKSOURCE_PLLSAI1 SAI2 clock = PLLSAI1 "P" clock (PLLSAI1CLK) + * @arg @ref RCC_SAI2CLKSOURCE_PLLSAI2 SAI2 clock = PLLSAI2 "P" clock (PLLSAI2CLK) + * @arg @ref RCC_SAI2CLKSOURCE_PLL SAI2 clock = PLL "P" clock (PLLSAI3CLK) + * @arg @ref RCC_SAI2CLKSOURCE_PIN SAI2 clock = External Clock (SAI2_EXTCLK) + @if STM32L4S9xx + * @arg @ref RCC_SAI2CLKSOURCE_HSI SAI2 clock = HSI16 + @endif + * + * @retval None + */ +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +#define __HAL_RCC_SAI2_CONFIG(__SAI2_CLKSOURCE__ )\ + MODIFY_REG(RCC->CCIPR2, RCC_CCIPR2_SAI2SEL, (__SAI2_CLKSOURCE__)) +#else +#define __HAL_RCC_SAI2_CONFIG(__SAI2_CLKSOURCE__ )\ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_SAI2SEL, (__SAI2_CLKSOURCE__)) +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +/** @brief Macro to get the SAI2 clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_SAI2CLKSOURCE_PLLSAI1 SAI2 clock = PLLSAI1 "P" clock (PLLSAI1CLK) + * @arg @ref RCC_SAI2CLKSOURCE_PLLSAI2 SAI2 clock = PLLSAI2 "P" clock (PLLSAI2CLK) + * @arg @ref RCC_SAI2CLKSOURCE_PLL SAI2 clock = PLL "P" clock (PLLSAI3CLK) + * @arg @ref RCC_SAI2CLKSOURCE_PIN SAI2 clock = External Clock (SAI2_EXTCLK) + */ +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +#define __HAL_RCC_GET_SAI2_SOURCE() (READ_BIT(RCC->CCIPR2, RCC_CCIPR2_SAI2SEL)) +#else +#define __HAL_RCC_GET_SAI2_SOURCE() (READ_BIT(RCC->CCIPR, RCC_CCIPR_SAI2SEL)) +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#endif /* SAI2 */ + +/** @brief Macro to configure the I2C1 clock (I2C1CLK). + * + * @param __I2C1_CLKSOURCE__ specifies the I2C1 clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_I2C1CLKSOURCE_PCLK1 PCLK1 selected as I2C1 clock + * @arg @ref RCC_I2C1CLKSOURCE_HSI HSI selected as I2C1 clock + * @arg @ref RCC_I2C1CLKSOURCE_SYSCLK System Clock selected as I2C1 clock + * @retval None + */ +#define __HAL_RCC_I2C1_CONFIG(__I2C1_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_I2C1SEL, (__I2C1_CLKSOURCE__)) + +/** @brief Macro to get the I2C1 clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_I2C1CLKSOURCE_PCLK1 PCLK1 selected as I2C1 clock + * @arg @ref RCC_I2C1CLKSOURCE_HSI HSI selected as I2C1 clock + * @arg @ref RCC_I2C1CLKSOURCE_SYSCLK System Clock selected as I2C1 clock + */ +#define __HAL_RCC_GET_I2C1_SOURCE() (READ_BIT(RCC->CCIPR, RCC_CCIPR_I2C1SEL)) + +#if defined(I2C2) + +/** @brief Macro to configure the I2C2 clock (I2C2CLK). + * + * @param __I2C2_CLKSOURCE__ specifies the I2C2 clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_I2C2CLKSOURCE_PCLK1 PCLK1 selected as I2C2 clock + * @arg @ref RCC_I2C2CLKSOURCE_HSI HSI selected as I2C2 clock + * @arg @ref RCC_I2C2CLKSOURCE_SYSCLK System Clock selected as I2C2 clock + * @retval None + */ +#define __HAL_RCC_I2C2_CONFIG(__I2C2_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_I2C2SEL, (__I2C2_CLKSOURCE__)) + +/** @brief Macro to get the I2C2 clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_I2C2CLKSOURCE_PCLK1 PCLK1 selected as I2C2 clock + * @arg @ref RCC_I2C2CLKSOURCE_HSI HSI selected as I2C2 clock + * @arg @ref RCC_I2C2CLKSOURCE_SYSCLK System Clock selected as I2C2 clock + */ +#define __HAL_RCC_GET_I2C2_SOURCE() (READ_BIT(RCC->CCIPR, RCC_CCIPR_I2C2SEL)) + +#endif /* I2C2 */ + +/** @brief Macro to configure the I2C3 clock (I2C3CLK). + * + * @param __I2C3_CLKSOURCE__ specifies the I2C3 clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_I2C3CLKSOURCE_PCLK1 PCLK1 selected as I2C3 clock + * @arg @ref RCC_I2C3CLKSOURCE_HSI HSI selected as I2C3 clock + * @arg @ref RCC_I2C3CLKSOURCE_SYSCLK System Clock selected as I2C3 clock + * @retval None + */ +#define __HAL_RCC_I2C3_CONFIG(__I2C3_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_I2C3SEL, (__I2C3_CLKSOURCE__)) + +/** @brief Macro to get the I2C3 clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_I2C3CLKSOURCE_PCLK1 PCLK1 selected as I2C3 clock + * @arg @ref RCC_I2C3CLKSOURCE_HSI HSI selected as I2C3 clock + * @arg @ref RCC_I2C3CLKSOURCE_SYSCLK System Clock selected as I2C3 clock + */ +#define __HAL_RCC_GET_I2C3_SOURCE() (READ_BIT(RCC->CCIPR, RCC_CCIPR_I2C3SEL)) + +#if defined(I2C4) + +/** @brief Macro to configure the I2C4 clock (I2C4CLK). + * + * @param __I2C4_CLKSOURCE__ specifies the I2C4 clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_I2C4CLKSOURCE_PCLK1 PCLK1 selected as I2C4 clock + * @arg @ref RCC_I2C4CLKSOURCE_HSI HSI selected as I2C4 clock + * @arg @ref RCC_I2C4CLKSOURCE_SYSCLK System Clock selected as I2C4 clock + * @retval None + */ +#define __HAL_RCC_I2C4_CONFIG(__I2C4_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR2, RCC_CCIPR2_I2C4SEL, (__I2C4_CLKSOURCE__)) + +/** @brief Macro to get the I2C4 clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_I2C4CLKSOURCE_PCLK1 PCLK1 selected as I2C4 clock + * @arg @ref RCC_I2C4CLKSOURCE_HSI HSI selected as I2C4 clock + * @arg @ref RCC_I2C4CLKSOURCE_SYSCLK System Clock selected as I2C4 clock + */ +#define __HAL_RCC_GET_I2C4_SOURCE() (READ_BIT(RCC->CCIPR2, RCC_CCIPR2_I2C4SEL)) + +#endif /* I2C4 */ + + +/** @brief Macro to configure the USART1 clock (USART1CLK). + * + * @param __USART1_CLKSOURCE__ specifies the USART1 clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_USART1CLKSOURCE_PCLK2 PCLK2 selected as USART1 clock + * @arg @ref RCC_USART1CLKSOURCE_HSI HSI selected as USART1 clock + * @arg @ref RCC_USART1CLKSOURCE_SYSCLK System Clock selected as USART1 clock + * @arg @ref RCC_USART1CLKSOURCE_LSE SE selected as USART1 clock + * @retval None + */ +#define __HAL_RCC_USART1_CONFIG(__USART1_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_USART1SEL, (__USART1_CLKSOURCE__)) + +/** @brief Macro to get the USART1 clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_USART1CLKSOURCE_PCLK2 PCLK2 selected as USART1 clock + * @arg @ref RCC_USART1CLKSOURCE_HSI HSI selected as USART1 clock + * @arg @ref RCC_USART1CLKSOURCE_SYSCLK System Clock selected as USART1 clock + * @arg @ref RCC_USART1CLKSOURCE_LSE LSE selected as USART1 clock + */ +#define __HAL_RCC_GET_USART1_SOURCE() (READ_BIT(RCC->CCIPR, RCC_CCIPR_USART1SEL)) + +/** @brief Macro to configure the USART2 clock (USART2CLK). + * + * @param __USART2_CLKSOURCE__ specifies the USART2 clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_USART2CLKSOURCE_PCLK1 PCLK1 selected as USART2 clock + * @arg @ref RCC_USART2CLKSOURCE_HSI HSI selected as USART2 clock + * @arg @ref RCC_USART2CLKSOURCE_SYSCLK System Clock selected as USART2 clock + * @arg @ref RCC_USART2CLKSOURCE_LSE LSE selected as USART2 clock + * @retval None + */ +#define __HAL_RCC_USART2_CONFIG(__USART2_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_USART2SEL, (__USART2_CLKSOURCE__)) + +/** @brief Macro to get the USART2 clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_USART2CLKSOURCE_PCLK1 PCLK1 selected as USART2 clock + * @arg @ref RCC_USART2CLKSOURCE_HSI HSI selected as USART2 clock + * @arg @ref RCC_USART2CLKSOURCE_SYSCLK System Clock selected as USART2 clock + * @arg @ref RCC_USART2CLKSOURCE_LSE LSE selected as USART2 clock + */ +#define __HAL_RCC_GET_USART2_SOURCE() (READ_BIT(RCC->CCIPR, RCC_CCIPR_USART2SEL)) + +#if defined(USART3) + +/** @brief Macro to configure the USART3 clock (USART3CLK). + * + * @param __USART3_CLKSOURCE__ specifies the USART3 clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_USART3CLKSOURCE_PCLK1 PCLK1 selected as USART3 clock + * @arg @ref RCC_USART3CLKSOURCE_HSI HSI selected as USART3 clock + * @arg @ref RCC_USART3CLKSOURCE_SYSCLK System Clock selected as USART3 clock + * @arg @ref RCC_USART3CLKSOURCE_LSE LSE selected as USART3 clock + * @retval None + */ +#define __HAL_RCC_USART3_CONFIG(__USART3_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_USART3SEL, (__USART3_CLKSOURCE__)) + +/** @brief Macro to get the USART3 clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_USART3CLKSOURCE_PCLK1 PCLK1 selected as USART3 clock + * @arg @ref RCC_USART3CLKSOURCE_HSI HSI selected as USART3 clock + * @arg @ref RCC_USART3CLKSOURCE_SYSCLK System Clock selected as USART3 clock + * @arg @ref RCC_USART3CLKSOURCE_LSE LSE selected as USART3 clock + */ +#define __HAL_RCC_GET_USART3_SOURCE() (READ_BIT(RCC->CCIPR, RCC_CCIPR_USART3SEL)) + +#endif /* USART3 */ + +#if defined(UART4) + +/** @brief Macro to configure the UART4 clock (UART4CLK). + * + * @param __UART4_CLKSOURCE__ specifies the UART4 clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_UART4CLKSOURCE_PCLK1 PCLK1 selected as UART4 clock + * @arg @ref RCC_UART4CLKSOURCE_HSI HSI selected as UART4 clock + * @arg @ref RCC_UART4CLKSOURCE_SYSCLK System Clock selected as UART4 clock + * @arg @ref RCC_UART4CLKSOURCE_LSE LSE selected as UART4 clock + * @retval None + */ +#define __HAL_RCC_UART4_CONFIG(__UART4_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_UART4SEL, (__UART4_CLKSOURCE__)) + +/** @brief Macro to get the UART4 clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_UART4CLKSOURCE_PCLK1 PCLK1 selected as UART4 clock + * @arg @ref RCC_UART4CLKSOURCE_HSI HSI selected as UART4 clock + * @arg @ref RCC_UART4CLKSOURCE_SYSCLK System Clock selected as UART4 clock + * @arg @ref RCC_UART4CLKSOURCE_LSE LSE selected as UART4 clock + */ +#define __HAL_RCC_GET_UART4_SOURCE() (READ_BIT(RCC->CCIPR, RCC_CCIPR_UART4SEL)) + +#endif /* UART4 */ + +#if defined(UART5) + +/** @brief Macro to configure the UART5 clock (UART5CLK). + * + * @param __UART5_CLKSOURCE__ specifies the UART5 clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_UART5CLKSOURCE_PCLK1 PCLK1 selected as UART5 clock + * @arg @ref RCC_UART5CLKSOURCE_HSI HSI selected as UART5 clock + * @arg @ref RCC_UART5CLKSOURCE_SYSCLK System Clock selected as UART5 clock + * @arg @ref RCC_UART5CLKSOURCE_LSE LSE selected as UART5 clock + * @retval None + */ +#define __HAL_RCC_UART5_CONFIG(__UART5_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_UART5SEL, (__UART5_CLKSOURCE__)) + +/** @brief Macro to get the UART5 clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_UART5CLKSOURCE_PCLK1 PCLK1 selected as UART5 clock + * @arg @ref RCC_UART5CLKSOURCE_HSI HSI selected as UART5 clock + * @arg @ref RCC_UART5CLKSOURCE_SYSCLK System Clock selected as UART5 clock + * @arg @ref RCC_UART5CLKSOURCE_LSE LSE selected as UART5 clock + */ +#define __HAL_RCC_GET_UART5_SOURCE() (READ_BIT(RCC->CCIPR, RCC_CCIPR_UART5SEL)) + +#endif /* UART5 */ + +/** @brief Macro to configure the LPUART1 clock (LPUART1CLK). + * + * @param __LPUART1_CLKSOURCE__ specifies the LPUART1 clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_LPUART1CLKSOURCE_PCLK1 PCLK1 selected as LPUART1 clock + * @arg @ref RCC_LPUART1CLKSOURCE_HSI HSI selected as LPUART1 clock + * @arg @ref RCC_LPUART1CLKSOURCE_SYSCLK System Clock selected as LPUART1 clock + * @arg @ref RCC_LPUART1CLKSOURCE_LSE LSE selected as LPUART1 clock + * @retval None + */ +#define __HAL_RCC_LPUART1_CONFIG(__LPUART1_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_LPUART1SEL, (__LPUART1_CLKSOURCE__)) + +/** @brief Macro to get the LPUART1 clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_LPUART1CLKSOURCE_PCLK1 PCLK1 selected as LPUART1 clock + * @arg @ref RCC_LPUART1CLKSOURCE_HSI HSI selected as LPUART1 clock + * @arg @ref RCC_LPUART1CLKSOURCE_SYSCLK System Clock selected as LPUART1 clock + * @arg @ref RCC_LPUART1CLKSOURCE_LSE LSE selected as LPUART1 clock + */ +#define __HAL_RCC_GET_LPUART1_SOURCE() (READ_BIT(RCC->CCIPR, RCC_CCIPR_LPUART1SEL)) + +/** @brief Macro to configure the LPTIM1 clock (LPTIM1CLK). + * + * @param __LPTIM1_CLKSOURCE__ specifies the LPTIM1 clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_LPTIM1CLKSOURCE_PCLK1 PCLK1 selected as LPTIM1 clock + * @arg @ref RCC_LPTIM1CLKSOURCE_LSI HSI selected as LPTIM1 clock + * @arg @ref RCC_LPTIM1CLKSOURCE_HSI LSI selected as LPTIM1 clock + * @arg @ref RCC_LPTIM1CLKSOURCE_LSE LSE selected as LPTIM1 clock + * @retval None + */ +#define __HAL_RCC_LPTIM1_CONFIG(__LPTIM1_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_LPTIM1SEL, (__LPTIM1_CLKSOURCE__)) + +/** @brief Macro to get the LPTIM1 clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_LPTIM1CLKSOURCE_PCLK1 PCLK1 selected as LPUART1 clock + * @arg @ref RCC_LPTIM1CLKSOURCE_LSI HSI selected as LPUART1 clock + * @arg @ref RCC_LPTIM1CLKSOURCE_HSI System Clock selected as LPUART1 clock + * @arg @ref RCC_LPTIM1CLKSOURCE_LSE LSE selected as LPUART1 clock + */ +#define __HAL_RCC_GET_LPTIM1_SOURCE() (READ_BIT(RCC->CCIPR, RCC_CCIPR_LPTIM1SEL)) + +/** @brief Macro to configure the LPTIM2 clock (LPTIM2CLK). + * + * @param __LPTIM2_CLKSOURCE__ specifies the LPTIM2 clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_LPTIM2CLKSOURCE_PCLK1 PCLK1 selected as LPTIM2 clock + * @arg @ref RCC_LPTIM2CLKSOURCE_LSI HSI selected as LPTIM2 clock + * @arg @ref RCC_LPTIM2CLKSOURCE_HSI LSI selected as LPTIM2 clock + * @arg @ref RCC_LPTIM2CLKSOURCE_LSE LSE selected as LPTIM2 clock + * @retval None + */ +#define __HAL_RCC_LPTIM2_CONFIG(__LPTIM2_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_LPTIM2SEL, (__LPTIM2_CLKSOURCE__)) + +/** @brief Macro to get the LPTIM2 clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_LPTIM2CLKSOURCE_PCLK1 PCLK1 selected as LPUART1 clock + * @arg @ref RCC_LPTIM2CLKSOURCE_LSI HSI selected as LPUART1 clock + * @arg @ref RCC_LPTIM2CLKSOURCE_HSI System Clock selected as LPUART1 clock + * @arg @ref RCC_LPTIM2CLKSOURCE_LSE LSE selected as LPUART1 clock + */ +#define __HAL_RCC_GET_LPTIM2_SOURCE() (READ_BIT(RCC->CCIPR, RCC_CCIPR_LPTIM2SEL)) + +#if defined(SDMMC1) + +/** @brief Macro to configure the SDMMC1 clock. + * + @if STM32L486xx + * @note USB, RNG and SDMMC1 peripherals share the same 48MHz clock source. + @endif + * + @if STM32L443xx + * @note USB, RNG and SDMMC1 peripherals share the same 48MHz clock source. + @endif + * + * @param __SDMMC1_CLKSOURCE__ specifies the SDMMC1 clock source. + * This parameter can be one of the following values: + @if STM32L486xx + * @arg @ref RCC_SDMMC1CLKSOURCE_NONE No clock selected as SDMMC1 clock for devices without HSI48 + * @arg @ref RCC_SDMMC1CLKSOURCE_MSI MSI selected as SDMMC1 clock + * @arg @ref RCC_SDMMC1CLKSOURCE_PLLSAI1 PLLSAI1 "Q" Clock selected as SDMMC1 clock + @endif + @if STM32L443xx + * @arg @ref RCC_SDMMC1CLKSOURCE_HSI48 HSI48 selected as SDMMC1 clock for devices with HSI48 + * @arg @ref RCC_SDMMC1CLKSOURCE_MSI MSI selected as SDMMC1 clock + * @arg @ref RCC_SDMMC1CLKSOURCE_PLLSAI1 PLLSAI1 "Q" Clock selected as SDMMC1 clock + @endif + @if STM32L4S9xx + * @arg @ref RCC_SDMMC1CLKSOURCE_HSI48 HSI48 selected as SDMMC1 clock for devices with HSI48 + * @arg @ref RCC_SDMMC1CLKSOURCE_MSI MSI selected as SDMMC1 clock + * @arg @ref RCC_SDMMC1CLKSOURCE_PLLSAI1 PLLSAI1 "Q" Clock selected as SDMMC1 clock + * @arg @ref RCC_SDMMC1CLKSOURCE_PLLP PLL "P" Clock selected as SDMMC1 clock + @endif + * @arg @ref RCC_SDMMC1CLKSOURCE_PLL PLL "Q" Clock selected as SDMMC1 clock + * @retval None + */ +#if defined(RCC_CCIPR2_SDMMCSEL) +#define __HAL_RCC_SDMMC1_CONFIG(__SDMMC1_CLKSOURCE__) \ + do \ + { \ + if((__SDMMC1_CLKSOURCE__) == RCC_SDMMC1CLKSOURCE_PLLP) \ + { \ + SET_BIT(RCC->CCIPR2, RCC_CCIPR2_SDMMCSEL); \ + } \ + else \ + { \ + CLEAR_BIT(RCC->CCIPR2, RCC_CCIPR2_SDMMCSEL); \ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_CLK48SEL, (__SDMMC1_CLKSOURCE__)); \ + } \ + } while(0) +#else +#define __HAL_RCC_SDMMC1_CONFIG(__SDMMC1_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_CLK48SEL, (__SDMMC1_CLKSOURCE__)) +#endif /* RCC_CCIPR2_SDMMCSEL */ + +/** @brief Macro to get the SDMMC1 clock. + * @retval The clock source can be one of the following values: + @if STM32L486xx + * @arg @ref RCC_SDMMC1CLKSOURCE_NONE No clock selected as SDMMC1 clock for devices without HSI48 + * @arg @ref RCC_SDMMC1CLKSOURCE_MSI MSI selected as SDMMC1 clock + * @arg @ref RCC_SDMMC1CLKSOURCE_PLLSAI1 PLLSAI1 "Q" clock (PLL48M2CLK) selected as SDMMC1 clock + @endif + @if STM32L443xx + * @arg @ref RCC_SDMMC1CLKSOURCE_HSI48 HSI48 selected as SDMMC1 clock for devices with HSI48 + * @arg @ref RCC_SDMMC1CLKSOURCE_MSI MSI selected as SDMMC1 clock + * @arg @ref RCC_SDMMC1CLKSOURCE_PLLSAI1 PLLSAI1 "Q" clock (PLL48M2CLK) selected as SDMMC1 clock + @endif + @if STM32L4S9xx + * @arg @ref RCC_SDMMC1CLKSOURCE_HSI48 HSI48 selected as SDMMC1 clock for devices with HSI48 + * @arg @ref RCC_SDMMC1CLKSOURCE_MSI MSI selected as SDMMC1 clock + * @arg @ref RCC_SDMMC1CLKSOURCE_PLLSAI1 PLLSAI1 "Q" clock (PLL48M2CLK) selected as SDMMC1 clock + * @arg @ref RCC_SDMMC1CLKSOURCE_PLLP PLL "P" clock (PLLSAI3CLK) selected as SDMMC1 kernel clock + @endif + * @arg @ref RCC_SDMMC1CLKSOURCE_PLL PLL "Q" clock (PLL48M1CLK) selected as SDMMC1 clock + */ +#if defined(RCC_CCIPR2_SDMMCSEL) +#define __HAL_RCC_GET_SDMMC1_SOURCE() \ + ((READ_BIT(RCC->CCIPR2, RCC_CCIPR2_SDMMCSEL) != RESET) ? RCC_SDMMC1CLKSOURCE_PLLP : (READ_BIT(RCC->CCIPR, RCC_CCIPR_CLK48SEL))) +#else +#define __HAL_RCC_GET_SDMMC1_SOURCE() \ + (READ_BIT(RCC->CCIPR, RCC_CCIPR_CLK48SEL)) +#endif /* RCC_CCIPR2_SDMMCSEL */ + +#endif /* SDMMC1 */ + +/** @brief Macro to configure the RNG clock. + * + * @note USB, RNG and SDMMC1 peripherals share the same 48MHz clock source. + * + * @param __RNG_CLKSOURCE__ specifies the RNG clock source. + * This parameter can be one of the following values: + @if STM32L486xx + * @arg @ref RCC_RNGCLKSOURCE_NONE No clock selected as RNG clock for devices without HSI48 + @endif + @if STM32L443xx + * @arg @ref RCC_RNGCLKSOURCE_HSI48 HSI48 selected as RNG clock clock for devices with HSI48 + @endif + * @arg @ref RCC_RNGCLKSOURCE_MSI MSI selected as RNG clock + * @arg @ref RCC_RNGCLKSOURCE_PLLSAI1 PLLSAI1 Clock selected as RNG clock + * @arg @ref RCC_RNGCLKSOURCE_PLL PLL Clock selected as RNG clock + * @retval None + */ +#define __HAL_RCC_RNG_CONFIG(__RNG_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_CLK48SEL, (__RNG_CLKSOURCE__)) + +/** @brief Macro to get the RNG clock. + * @retval The clock source can be one of the following values: + @if STM32L486xx + * @arg @ref RCC_RNGCLKSOURCE_NONE No clock selected as RNG clock for devices without HSI48 + @endif + @if STM32L443xx + * @arg @ref RCC_RNGCLKSOURCE_HSI48 HSI48 selected as RNG clock clock for devices with HSI48 + @endif + * @arg @ref RCC_RNGCLKSOURCE_MSI MSI selected as RNG clock + * @arg @ref RCC_RNGCLKSOURCE_PLLSAI1 PLLSAI1 "Q" clock (PLL48M2CLK) selected as RNG clock + * @arg @ref RCC_RNGCLKSOURCE_PLL PLL "Q" clock (PLL48M1CLK) selected as RNG clock + */ +#define __HAL_RCC_GET_RNG_SOURCE() (READ_BIT(RCC->CCIPR, RCC_CCIPR_CLK48SEL)) + +#if defined(USB_OTG_FS) || defined(USB) + +/** @brief Macro to configure the USB clock (USBCLK). + * + * @note USB, RNG and SDMMC1 peripherals share the same 48MHz clock source. + * + * @param __USB_CLKSOURCE__ specifies the USB clock source. + * This parameter can be one of the following values: + @if STM32L486xx + * @arg @ref RCC_USBCLKSOURCE_NONE No clock selected as 48MHz clock for devices without HSI48 + @endif + @if STM32L443xx + * @arg @ref RCC_USBCLKSOURCE_HSI48 HSI48 selected as 48MHz clock for devices with HSI48 + @endif + * @arg @ref RCC_USBCLKSOURCE_MSI MSI selected as USB clock + * @arg @ref RCC_USBCLKSOURCE_PLLSAI1 PLLSAI1 "Q" clock (PLL48M2CLK) selected as USB clock + * @arg @ref RCC_USBCLKSOURCE_PLL PLL "Q" clock (PLL48M1CLK) selected as USB clock + * @retval None + */ +#define __HAL_RCC_USB_CONFIG(__USB_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_CLK48SEL, (__USB_CLKSOURCE__)) + +/** @brief Macro to get the USB clock source. + * @retval The clock source can be one of the following values: + @if STM32L486xx + * @arg @ref RCC_USBCLKSOURCE_NONE No clock selected as 48MHz clock for devices without HSI48 + @endif + @if STM32L443xx + * @arg @ref RCC_USBCLKSOURCE_HSI48 HSI48 selected as 48MHz clock for devices with HSI48 + @endif + * @arg @ref RCC_USBCLKSOURCE_MSI MSI selected as USB clock + * @arg @ref RCC_USBCLKSOURCE_PLLSAI1 PLLSAI1 "Q" clock (PLL48M2CLK) selected as USB clock + * @arg @ref RCC_USBCLKSOURCE_PLL PLL "Q" clock (PLL48M1CLK) selected as USB clock + */ +#define __HAL_RCC_GET_USB_SOURCE() (READ_BIT(RCC->CCIPR, RCC_CCIPR_CLK48SEL)) + +#endif /* USB_OTG_FS || USB */ + +/** @brief Macro to configure the ADC interface clock. + * @param __ADC_CLKSOURCE__ specifies the ADC digital interface clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_ADCCLKSOURCE_NONE No clock selected as ADC clock + * @arg @ref RCC_ADCCLKSOURCE_PLLSAI1 PLLSAI1 Clock selected as ADC clock + @if STM32L486xx + * @arg @ref RCC_ADCCLKSOURCE_PLLSAI2 PLLSAI2 Clock selected as ADC clock for STM32L47x/STM32L48x/STM32L49x/STM32L4Ax devices + @endif + * @arg @ref RCC_ADCCLKSOURCE_SYSCLK System Clock selected as ADC clock + * @retval None + */ +#define __HAL_RCC_ADC_CONFIG(__ADC_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_ADCSEL, (__ADC_CLKSOURCE__)) + +/** @brief Macro to get the ADC clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_ADCCLKSOURCE_NONE No clock selected as ADC clock + * @arg @ref RCC_ADCCLKSOURCE_PLLSAI1 PLLSAI1 Clock selected as ADC clock + @if STM32L486xx + * @arg @ref RCC_ADCCLKSOURCE_PLLSAI2 PLLSAI2 Clock selected as ADC clock for STM32L47x/STM32L48x/STM32L49x/STM32L4Ax devices + @endif + * @arg @ref RCC_ADCCLKSOURCE_SYSCLK System Clock selected as ADC clock + */ +#define __HAL_RCC_GET_ADC_SOURCE() (READ_BIT(RCC->CCIPR, RCC_CCIPR_ADCSEL)) + +#if defined(SWPMI1) + +/** @brief Macro to configure the SWPMI1 clock. + * @param __SWPMI1_CLKSOURCE__ specifies the SWPMI1 clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_SWPMI1CLKSOURCE_PCLK1 PCLK1 Clock selected as SWPMI1 clock + * @arg @ref RCC_SWPMI1CLKSOURCE_HSI HSI Clock selected as SWPMI1 clock + * @retval None + */ +#define __HAL_RCC_SWPMI1_CONFIG(__SWPMI1_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_SWPMI1SEL, (__SWPMI1_CLKSOURCE__)) + +/** @brief Macro to get the SWPMI1 clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_SWPMI1CLKSOURCE_PCLK1 PCLK1 Clock selected as SWPMI1 clock + * @arg @ref RCC_SWPMI1CLKSOURCE_HSI HSI Clock selected as SWPMI1 clock + */ +#define __HAL_RCC_GET_SWPMI1_SOURCE() (READ_BIT(RCC->CCIPR, RCC_CCIPR_SWPMI1SEL)) + +#endif /* SWPMI1 */ + +#if defined(DFSDM1_Filter0) +/** @brief Macro to configure the DFSDM1 clock. + * @param __DFSDM1_CLKSOURCE__ specifies the DFSDM1 clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_DFSDM1CLKSOURCE_PCLK2 PCLK2 Clock selected as DFSDM1 clock + * @arg @ref RCC_DFSDM1CLKSOURCE_SYSCLK System Clock selected as DFSDM1 clock + * @retval None + */ +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +#define __HAL_RCC_DFSDM1_CONFIG(__DFSDM1_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR2, RCC_CCIPR2_DFSDM1SEL, (__DFSDM1_CLKSOURCE__)) +#else +#define __HAL_RCC_DFSDM1_CONFIG(__DFSDM1_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_DFSDM1SEL, (__DFSDM1_CLKSOURCE__)) +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +/** @brief Macro to get the DFSDM1 clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_DFSDM1CLKSOURCE_PCLK2 PCLK2 Clock selected as DFSDM1 clock + * @arg @ref RCC_DFSDM1CLKSOURCE_SYSCLK System Clock selected as DFSDM1 clock + */ +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +#define __HAL_RCC_GET_DFSDM1_SOURCE() (READ_BIT(RCC->CCIPR2, RCC_CCIPR2_DFSDM1SEL)) +#else +#define __HAL_RCC_GET_DFSDM1_SOURCE() (READ_BIT(RCC->CCIPR, RCC_CCIPR_DFSDM1SEL)) +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + +/** @brief Macro to configure the DFSDM1 audio clock. + * @param __DFSDM1AUDIO_CLKSOURCE__ specifies the DFSDM1 audio clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_DFSDM1AUDIOCLKSOURCE_SAI1 SAI1 clock selected as DFSDM1 audio clock + * @arg @ref RCC_DFSDM1AUDIOCLKSOURCE_HSI HSI clock selected as DFSDM1 audio clock + * @arg @ref RCC_DFSDM1AUDIOCLKSOURCE_MSI MSI clock selected as DFSDM1 audio clock + * @retval None + */ +#define __HAL_RCC_DFSDM1AUDIO_CONFIG(__DFSDM1AUDIO_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR2, RCC_CCIPR2_ADFSDM1SEL, (__DFSDM1AUDIO_CLKSOURCE__)) + +/** @brief Macro to get the DFSDM1 audio clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_DFSDM1AUDIOCLKSOURCE_SAI1 SAI1 clock selected as DFSDM1 audio clock + * @arg @ref RCC_DFSDM1AUDIOCLKSOURCE_HSI HSI clock selected as DFSDM1 audio clock + * @arg @ref RCC_DFSDM1AUDIOCLKSOURCE_MSI MSI clock selected as DFSDM1 audio clock + */ +#define __HAL_RCC_GET_DFSDM1AUDIO_SOURCE() (READ_BIT(RCC->CCIPR2, RCC_CCIPR2_ADFSDM1SEL)) + +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#endif /* DFSDM1_Filter0 */ + +#if defined(LTDC) + +/** @brief Macro to configure the LTDC clock. + * @param __LTDC_CLKSOURCE__ specifies the DSI clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_LTDCCLKSOURCE_PLLSAI2_DIV2 PLLSAI2 divider R divided by 2 clock selected as LTDC clock + * @arg @ref RCC_LTDCCLKSOURCE_PLLSAI2_DIV4 PLLSAI2 divider R divided by 4 clock selected as LTDC clock + * @arg @ref RCC_LTDCCLKSOURCE_PLLSAI2_DIV8 PLLSAI2 divider R divided by 8 clock selected as LTDC clock + * @arg @ref RCC_LTDCCLKSOURCE_PLLSAI2_DIV16 PLLSAI2 divider R divided by 16 clock selected as LTDC clock + * @retval None + */ +#define __HAL_RCC_LTDC_CONFIG(__LTDC_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR2, RCC_CCIPR2_PLLSAI2DIVR, (__LTDC_CLKSOURCE__)) + +/** @brief Macro to get the LTDC clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_LTDCCLKSOURCE_PLLSAI2_DIV2 PLLSAI2 divider R divided by 2 clock selected as LTDC clock + * @arg @ref RCC_LTDCCLKSOURCE_PLLSAI2_DIV4 PLLSAI2 divider R divided by 4 clock selected as LTDC clock + * @arg @ref RCC_LTDCCLKSOURCE_PLLSAI2_DIV8 PLLSAI2 divider R divided by 8 clock selected as LTDC clock + * @arg @ref RCC_LTDCCLKSOURCE_PLLSAI2_DIV16 PLLSAI2 divider R divided by 16 clock selected as LTDC clock + */ +#define __HAL_RCC_GET_LTDC_SOURCE() (READ_BIT(RCC->CCIPR2, RCC_CCIPR2_PLLSAI2DIVR)) + +#endif /* LTDC */ + +#if defined(DSI) + +/** @brief Macro to configure the DSI clock. + * @param __DSI_CLKSOURCE__ specifies the DSI clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_DSICLKSOURCE_DSIPHY DSI-PHY clock selected as DSI clock + * @arg @ref RCC_DSICLKSOURCE_PLLSAI2 PLLSAI2 R divider clock selected as DSI clock + * @retval None + */ +#define __HAL_RCC_DSI_CONFIG(__DSI_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR2, RCC_CCIPR2_DSISEL, (__DSI_CLKSOURCE__)) + +/** @brief Macro to get the DSI clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_DSICLKSOURCE_DSIPHY DSI-PHY clock selected as DSI clock + * @arg @ref RCC_DSICLKSOURCE_PLLSAI2 PLLSAI2 R divider clock selected as DSI clock + */ +#define __HAL_RCC_GET_DSI_SOURCE() (READ_BIT(RCC->CCIPR2, RCC_CCIPR2_DSISEL)) + +#endif /* DSI */ + +#if defined(OCTOSPI1) || defined(OCTOSPI2) + +/** @brief Macro to configure the OctoSPI clock. + * @param __OSPI_CLKSOURCE__ specifies the OctoSPI clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_OSPICLKSOURCE_SYSCLK System Clock selected as OctoSPI clock + * @arg @ref RCC_OSPICLKSOURCE_MSI MSI clock selected as OctoSPI clock + * @arg @ref RCC_OSPICLKSOURCE_PLL PLL Q divider clock selected as OctoSPI clock + * @retval None + */ +#define __HAL_RCC_OSPI_CONFIG(__OSPI_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR2, RCC_CCIPR2_OSPISEL, (__OSPI_CLKSOURCE__)) + +/** @brief Macro to get the OctoSPI clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_OSPICLKSOURCE_SYSCLK System Clock selected as OctoSPI clock + * @arg @ref RCC_OSPICLKSOURCE_MSI MSI clock selected as OctoSPI clock + * @arg @ref RCC_OSPICLKSOURCE_PLL PLL Q divider clock selected as OctoSPI clock + */ +#define __HAL_RCC_GET_OSPI_SOURCE() (READ_BIT(RCC->CCIPR2, RCC_CCIPR2_OSPISEL)) + +#endif /* OCTOSPI1 || OCTOSPI2 */ + +/** @defgroup RCCEx_Flags_Interrupts_Management Flags Interrupts Management + * @brief macros to manage the specified RCC Flags and interrupts. + * @{ + */ + +/** @brief Enable PLLSAI1RDY interrupt. + * @retval None + */ +#define __HAL_RCC_PLLSAI1_ENABLE_IT() SET_BIT(RCC->CIER, RCC_CIER_PLLSAI1RDYIE) + +/** @brief Disable PLLSAI1RDY interrupt. + * @retval None + */ +#define __HAL_RCC_PLLSAI1_DISABLE_IT() CLEAR_BIT(RCC->CIER, RCC_CIER_PLLSAI1RDYIE) + +/** @brief Clear the PLLSAI1RDY interrupt pending bit. + * @retval None + */ +#define __HAL_RCC_PLLSAI1_CLEAR_IT() WRITE_REG(RCC->CICR, RCC_CICR_PLLSAI1RDYC) + +/** @brief Check whether PLLSAI1RDY interrupt has occurred or not. + * @retval TRUE or FALSE. + */ +#define __HAL_RCC_PLLSAI1_GET_IT_SOURCE() (READ_BIT(RCC->CIFR, RCC_CIFR_PLLSAI1RDYF) == RCC_CIFR_PLLSAI1RDYF) + +/** @brief Check whether the PLLSAI1RDY flag is set or not. + * @retval TRUE or FALSE. + */ +#define __HAL_RCC_PLLSAI1_GET_FLAG() (READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) == (RCC_CR_PLLSAI1RDY)) + +#if defined(RCC_PLLSAI2_SUPPORT) + +/** @brief Enable PLLSAI2RDY interrupt. + * @retval None + */ +#define __HAL_RCC_PLLSAI2_ENABLE_IT() SET_BIT(RCC->CIER, RCC_CIER_PLLSAI2RDYIE) + +/** @brief Disable PLLSAI2RDY interrupt. + * @retval None + */ +#define __HAL_RCC_PLLSAI2_DISABLE_IT() CLEAR_BIT(RCC->CIER, RCC_CIER_PLLSAI2RDYIE) + +/** @brief Clear the PLLSAI2RDY interrupt pending bit. + * @retval None + */ +#define __HAL_RCC_PLLSAI2_CLEAR_IT() WRITE_REG(RCC->CICR, RCC_CICR_PLLSAI2RDYC) + +/** @brief Check whether the PLLSAI2RDY interrupt has occurred or not. + * @retval TRUE or FALSE. + */ +#define __HAL_RCC_PLLSAI2_GET_IT_SOURCE() (READ_BIT(RCC->CIFR, RCC_CIFR_PLLSAI2RDYF) == RCC_CIFR_PLLSAI2RDYF) + +/** @brief Check whether the PLLSAI2RDY flag is set or not. + * @retval TRUE or FALSE. + */ +#define __HAL_RCC_PLLSAI2_GET_FLAG() (READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) == (RCC_CR_PLLSAI2RDY)) + +#endif /* RCC_PLLSAI2_SUPPORT */ + + +/** + * @brief Enable the RCC LSE CSS Extended Interrupt Line. + * @retval None + */ +#define __HAL_RCC_LSECSS_EXTI_ENABLE_IT() SET_BIT(EXTI->IMR1, RCC_EXTI_LINE_LSECSS) + +/** + * @brief Disable the RCC LSE CSS Extended Interrupt Line. + * @retval None + */ +#define __HAL_RCC_LSECSS_EXTI_DISABLE_IT() CLEAR_BIT(EXTI->IMR1, RCC_EXTI_LINE_LSECSS) + +/** + * @brief Enable the RCC LSE CSS Event Line. + * @retval None. + */ +#define __HAL_RCC_LSECSS_EXTI_ENABLE_EVENT() SET_BIT(EXTI->EMR1, RCC_EXTI_LINE_LSECSS) + +/** + * @brief Disable the RCC LSE CSS Event Line. + * @retval None. + */ +#define __HAL_RCC_LSECSS_EXTI_DISABLE_EVENT() CLEAR_BIT(EXTI->EMR1, RCC_EXTI_LINE_LSECSS) + + +/** + * @brief Enable the RCC LSE CSS Extended Interrupt Falling Trigger. + * @retval None. + */ +#define __HAL_RCC_LSECSS_EXTI_ENABLE_FALLING_EDGE() SET_BIT(EXTI->FTSR1, RCC_EXTI_LINE_LSECSS) + + +/** + * @brief Disable the RCC LSE CSS Extended Interrupt Falling Trigger. + * @retval None. + */ +#define __HAL_RCC_LSECSS_EXTI_DISABLE_FALLING_EDGE() CLEAR_BIT(EXTI->FTSR1, RCC_EXTI_LINE_LSECSS) + + +/** + * @brief Enable the RCC LSE CSS Extended Interrupt Rising Trigger. + * @retval None. + */ +#define __HAL_RCC_LSECSS_EXTI_ENABLE_RISING_EDGE() SET_BIT(EXTI->RTSR1, RCC_EXTI_LINE_LSECSS) + +/** + * @brief Disable the RCC LSE CSS Extended Interrupt Rising Trigger. + * @retval None. + */ +#define __HAL_RCC_LSECSS_EXTI_DISABLE_RISING_EDGE() CLEAR_BIT(EXTI->RTSR1, RCC_EXTI_LINE_LSECSS) + +/** + * @brief Enable the RCC LSE CSS Extended Interrupt Rising & Falling Trigger. + * @retval None. + */ +#define __HAL_RCC_LSECSS_EXTI_ENABLE_RISING_FALLING_EDGE() \ + do { \ + __HAL_RCC_LSECSS_EXTI_ENABLE_RISING_EDGE(); \ + __HAL_RCC_LSECSS_EXTI_ENABLE_FALLING_EDGE(); \ + } while(0) + +/** + * @brief Disable the RCC LSE CSS Extended Interrupt Rising & Falling Trigger. + * @retval None. + */ +#define __HAL_RCC_LSECSS_EXTI_DISABLE_RISING_FALLING_EDGE() \ + do { \ + __HAL_RCC_LSECSS_EXTI_DISABLE_RISING_EDGE(); \ + __HAL_RCC_LSECSS_EXTI_DISABLE_FALLING_EDGE(); \ + } while(0) + +/** + * @brief Check whether the specified RCC LSE CSS EXTI interrupt flag is set or not. + * @retval EXTI RCC LSE CSS Line Status. + */ +#define __HAL_RCC_LSECSS_EXTI_GET_FLAG() (READ_BIT(EXTI->PR1, RCC_EXTI_LINE_LSECSS) == RCC_EXTI_LINE_LSECSS) + +/** + * @brief Clear the RCC LSE CSS EXTI flag. + * @retval None. + */ +#define __HAL_RCC_LSECSS_EXTI_CLEAR_FLAG() WRITE_REG(EXTI->PR1, RCC_EXTI_LINE_LSECSS) + +/** + * @brief Generate a Software interrupt on the RCC LSE CSS EXTI line. + * @retval None. + */ +#define __HAL_RCC_LSECSS_EXTI_GENERATE_SWIT() SET_BIT(EXTI->SWIER1, RCC_EXTI_LINE_LSECSS) + + +#if defined(CRS) + +/** + * @brief Enable the specified CRS interrupts. + * @param __INTERRUPT__ specifies the CRS interrupt sources to be enabled. + * This parameter can be any combination of the following values: + * @arg @ref RCC_CRS_IT_SYNCOK SYNC event OK interrupt + * @arg @ref RCC_CRS_IT_SYNCWARN SYNC warning interrupt + * @arg @ref RCC_CRS_IT_ERR Synchronization or trimming error interrupt + * @arg @ref RCC_CRS_IT_ESYNC Expected SYNC interrupt + * @retval None + */ +#define __HAL_RCC_CRS_ENABLE_IT(__INTERRUPT__) SET_BIT(CRS->CR, (__INTERRUPT__)) + +/** + * @brief Disable the specified CRS interrupts. + * @param __INTERRUPT__ specifies the CRS interrupt sources to be disabled. + * This parameter can be any combination of the following values: + * @arg @ref RCC_CRS_IT_SYNCOK SYNC event OK interrupt + * @arg @ref RCC_CRS_IT_SYNCWARN SYNC warning interrupt + * @arg @ref RCC_CRS_IT_ERR Synchronization or trimming error interrupt + * @arg @ref RCC_CRS_IT_ESYNC Expected SYNC interrupt + * @retval None + */ +#define __HAL_RCC_CRS_DISABLE_IT(__INTERRUPT__) CLEAR_BIT(CRS->CR, (__INTERRUPT__)) + +/** @brief Check whether the CRS interrupt has occurred or not. + * @param __INTERRUPT__ specifies the CRS interrupt source to check. + * This parameter can be one of the following values: + * @arg @ref RCC_CRS_IT_SYNCOK SYNC event OK interrupt + * @arg @ref RCC_CRS_IT_SYNCWARN SYNC warning interrupt + * @arg @ref RCC_CRS_IT_ERR Synchronization or trimming error interrupt + * @arg @ref RCC_CRS_IT_ESYNC Expected SYNC interrupt + * @retval The new state of __INTERRUPT__ (SET or RESET). + */ +#define __HAL_RCC_CRS_GET_IT_SOURCE(__INTERRUPT__) ((READ_BIT(CRS->CR, (__INTERRUPT__)) != RESET) ? SET : RESET) + +/** @brief Clear the CRS interrupt pending bits + * @param __INTERRUPT__ specifies the interrupt pending bit to clear. + * This parameter can be any combination of the following values: + * @arg @ref RCC_CRS_IT_SYNCOK SYNC event OK interrupt + * @arg @ref RCC_CRS_IT_SYNCWARN SYNC warning interrupt + * @arg @ref RCC_CRS_IT_ERR Synchronization or trimming error interrupt + * @arg @ref RCC_CRS_IT_ESYNC Expected SYNC interrupt + * @arg @ref RCC_CRS_IT_TRIMOVF Trimming overflow or underflow interrupt + * @arg @ref RCC_CRS_IT_SYNCERR SYNC error interrupt + * @arg @ref RCC_CRS_IT_SYNCMISS SYNC missed interrupt + */ +/* CRS IT Error Mask */ +#define RCC_CRS_IT_ERROR_MASK (RCC_CRS_IT_TRIMOVF | RCC_CRS_IT_SYNCERR | RCC_CRS_IT_SYNCMISS) + +#define __HAL_RCC_CRS_CLEAR_IT(__INTERRUPT__) do { \ + if(((__INTERRUPT__) & RCC_CRS_IT_ERROR_MASK) != RESET) \ + { \ + WRITE_REG(CRS->ICR, CRS_ICR_ERRC | ((__INTERRUPT__) & ~RCC_CRS_IT_ERROR_MASK)); \ + } \ + else \ + { \ + WRITE_REG(CRS->ICR, (__INTERRUPT__)); \ + } \ + } while(0) + +/** + * @brief Check whether the specified CRS flag is set or not. + * @param __FLAG__ specifies the flag to check. + * This parameter can be one of the following values: + * @arg @ref RCC_CRS_FLAG_SYNCOK SYNC event OK + * @arg @ref RCC_CRS_FLAG_SYNCWARN SYNC warning + * @arg @ref RCC_CRS_FLAG_ERR Error + * @arg @ref RCC_CRS_FLAG_ESYNC Expected SYNC + * @arg @ref RCC_CRS_FLAG_TRIMOVF Trimming overflow or underflow + * @arg @ref RCC_CRS_FLAG_SYNCERR SYNC error + * @arg @ref RCC_CRS_FLAG_SYNCMISS SYNC missed + * @retval The new state of _FLAG_ (TRUE or FALSE). + */ +#define __HAL_RCC_CRS_GET_FLAG(__FLAG__) (READ_BIT(CRS->ISR, (__FLAG__)) == (__FLAG__)) + +/** + * @brief Clear the CRS specified FLAG. + * @param __FLAG__ specifies the flag to clear. + * This parameter can be one of the following values: + * @arg @ref RCC_CRS_FLAG_SYNCOK SYNC event OK + * @arg @ref RCC_CRS_FLAG_SYNCWARN SYNC warning + * @arg @ref RCC_CRS_FLAG_ERR Error + * @arg @ref RCC_CRS_FLAG_ESYNC Expected SYNC + * @arg @ref RCC_CRS_FLAG_TRIMOVF Trimming overflow or underflow + * @arg @ref RCC_CRS_FLAG_SYNCERR SYNC error + * @arg @ref RCC_CRS_FLAG_SYNCMISS SYNC missed + * @note RCC_CRS_FLAG_ERR clears RCC_CRS_FLAG_TRIMOVF, RCC_CRS_FLAG_SYNCERR, RCC_CRS_FLAG_SYNCMISS and consequently RCC_CRS_FLAG_ERR + * @retval None + */ + +/* CRS Flag Error Mask */ +#define RCC_CRS_FLAG_ERROR_MASK (RCC_CRS_FLAG_TRIMOVF | RCC_CRS_FLAG_SYNCERR | RCC_CRS_FLAG_SYNCMISS) + +#define __HAL_RCC_CRS_CLEAR_FLAG(__FLAG__) do { \ + if(((__FLAG__) & RCC_CRS_FLAG_ERROR_MASK) != RESET) \ + { \ + WRITE_REG(CRS->ICR, CRS_ICR_ERRC | ((__FLAG__) & ~RCC_CRS_FLAG_ERROR_MASK)); \ + } \ + else \ + { \ + WRITE_REG(CRS->ICR, (__FLAG__)); \ + } \ + } while(0) + +#endif /* CRS */ + +/** + * @} + */ + +#if defined(CRS) + +/** @defgroup RCCEx_CRS_Extended_Features RCCEx CRS Extended Features + * @{ + */ +/** + * @brief Enable the oscillator clock for frequency error counter. + * @note when the CEN bit is set the CRS_CFGR register becomes write-protected. + * @retval None + */ +#define __HAL_RCC_CRS_FREQ_ERROR_COUNTER_ENABLE() SET_BIT(CRS->CR, CRS_CR_CEN) + +/** + * @brief Disable the oscillator clock for frequency error counter. + * @retval None + */ +#define __HAL_RCC_CRS_FREQ_ERROR_COUNTER_DISABLE() CLEAR_BIT(CRS->CR, CRS_CR_CEN) + +/** + * @brief Enable the automatic hardware adjustement of TRIM bits. + * @note When the AUTOTRIMEN bit is set the CRS_CFGR register becomes write-protected. + * @retval None + */ +#define __HAL_RCC_CRS_AUTOMATIC_CALIB_ENABLE() SET_BIT(CRS->CR, CRS_CR_AUTOTRIMEN) + +/** + * @brief Enable or disable the automatic hardware adjustement of TRIM bits. + * @retval None + */ +#define __HAL_RCC_CRS_AUTOMATIC_CALIB_DISABLE() CLEAR_BIT(CRS->CR, CRS_CR_AUTOTRIMEN) + +/** + * @brief Macro to calculate reload value to be set in CRS register according to target and sync frequencies + * @note The RELOAD value should be selected according to the ratio between the target frequency and the frequency + * of the synchronization source after prescaling. It is then decreased by one in order to + * reach the expected synchronization on the zero value. The formula is the following: + * RELOAD = (fTARGET / fSYNC) -1 + * @param __FTARGET__ Target frequency (value in Hz) + * @param __FSYNC__ Synchronization signal frequency (value in Hz) + * @retval None + */ +#define __HAL_RCC_CRS_RELOADVALUE_CALCULATE(__FTARGET__, __FSYNC__) (((__FTARGET__) / (__FSYNC__)) - 1U) + +/** + * @} + */ + +#endif /* CRS */ + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup RCCEx_Exported_Functions + * @{ + */ + +/** @addtogroup RCCEx_Exported_Functions_Group1 + * @{ + */ + +HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit); +void HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit); +uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk); + +/** + * @} + */ + +/** @addtogroup RCCEx_Exported_Functions_Group2 + * @{ + */ + +HAL_StatusTypeDef HAL_RCCEx_EnablePLLSAI1(RCC_PLLSAI1InitTypeDef *PLLSAI1Init); +HAL_StatusTypeDef HAL_RCCEx_DisablePLLSAI1(void); + +#if defined(RCC_PLLSAI2_SUPPORT) + +HAL_StatusTypeDef HAL_RCCEx_EnablePLLSAI2(RCC_PLLSAI2InitTypeDef *PLLSAI2Init); +HAL_StatusTypeDef HAL_RCCEx_DisablePLLSAI2(void); + +#endif /* RCC_PLLSAI2_SUPPORT */ + +void HAL_RCCEx_WakeUpStopCLKConfig(uint32_t WakeUpClk); +void HAL_RCCEx_StandbyMSIRangeConfig(uint32_t MSIRange); +void HAL_RCCEx_EnableLSECSS(void); +void HAL_RCCEx_DisableLSECSS(void); +void HAL_RCCEx_EnableLSECSS_IT(void); +void HAL_RCCEx_LSECSS_IRQHandler(void); +void HAL_RCCEx_LSECSS_Callback(void); +void HAL_RCCEx_EnableLSCO(uint32_t LSCOSource); +void HAL_RCCEx_DisableLSCO(void); +void HAL_RCCEx_EnableMSIPLLMode(void); +void HAL_RCCEx_DisableMSIPLLMode(void); + +/** + * @} + */ + +#if defined(CRS) + +/** @addtogroup RCCEx_Exported_Functions_Group3 + * @{ + */ + +void HAL_RCCEx_CRSConfig(RCC_CRSInitTypeDef *pInit); +void HAL_RCCEx_CRSSoftwareSynchronizationGenerate(void); +void HAL_RCCEx_CRSGetSynchronizationInfo(RCC_CRSSynchroInfoTypeDef *pSynchroInfo); +uint32_t HAL_RCCEx_CRSWaitSynchronization(uint32_t Timeout); +void HAL_RCCEx_CRS_IRQHandler(void); +void HAL_RCCEx_CRS_SyncOkCallback(void); +void HAL_RCCEx_CRS_SyncWarnCallback(void); +void HAL_RCCEx_CRS_ExpectedSyncCallback(void); +void HAL_RCCEx_CRS_ErrorCallback(uint32_t Error); + +/** + * @} + */ + +#endif /* CRS */ + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @addtogroup RCCEx_Private_Macros + * @{ + */ + +#define IS_RCC_LSCOSOURCE(__SOURCE__) (((__SOURCE__) == RCC_LSCOSOURCE_LSI) || \ + ((__SOURCE__) == RCC_LSCOSOURCE_LSE)) + +#if defined(STM32L431xx) + +#define IS_RCC_PERIPHCLOCK(__SELECTION__) \ + ((((__SELECTION__) & RCC_PERIPHCLK_USART1) == RCC_PERIPHCLK_USART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART2) == RCC_PERIPHCLK_USART2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART3) == RCC_PERIPHCLK_USART3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPUART1) == RCC_PERIPHCLK_LPUART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C1) == RCC_PERIPHCLK_I2C1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C2) == RCC_PERIPHCLK_I2C2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C3) == RCC_PERIPHCLK_I2C3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM1) == RCC_PERIPHCLK_LPTIM1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM2) == RCC_PERIPHCLK_LPTIM2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_ADC) == RCC_PERIPHCLK_ADC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SWPMI1) == RCC_PERIPHCLK_SWPMI1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RNG) == RCC_PERIPHCLK_RNG) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SDMMC1) == RCC_PERIPHCLK_SDMMC1)) + +#elif defined(STM32L432xx) || defined(STM32L442xx) + +#define IS_RCC_PERIPHCLOCK(__SELECTION__) \ + ((((__SELECTION__) & RCC_PERIPHCLK_USART1) == RCC_PERIPHCLK_USART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART2) == RCC_PERIPHCLK_USART2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPUART1) == RCC_PERIPHCLK_LPUART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C1) == RCC_PERIPHCLK_I2C1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C3) == RCC_PERIPHCLK_I2C3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM1) == RCC_PERIPHCLK_LPTIM1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM2) == RCC_PERIPHCLK_LPTIM2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USB) == RCC_PERIPHCLK_USB) || \ + (((__SELECTION__) & RCC_PERIPHCLK_ADC) == RCC_PERIPHCLK_ADC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SWPMI1) == RCC_PERIPHCLK_SWPMI1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RNG) == RCC_PERIPHCLK_RNG)) + +#elif defined(STM32L433xx) || defined(STM32L443xx) + +#define IS_RCC_PERIPHCLOCK(__SELECTION__) \ + ((((__SELECTION__) & RCC_PERIPHCLK_USART1) == RCC_PERIPHCLK_USART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART2) == RCC_PERIPHCLK_USART2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART3) == RCC_PERIPHCLK_USART3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPUART1) == RCC_PERIPHCLK_LPUART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C1) == RCC_PERIPHCLK_I2C1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C2) == RCC_PERIPHCLK_I2C2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C3) == RCC_PERIPHCLK_I2C3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM1) == RCC_PERIPHCLK_LPTIM1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM2) == RCC_PERIPHCLK_LPTIM2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USB) == RCC_PERIPHCLK_USB) || \ + (((__SELECTION__) & RCC_PERIPHCLK_ADC) == RCC_PERIPHCLK_ADC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SWPMI1) == RCC_PERIPHCLK_SWPMI1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RNG) == RCC_PERIPHCLK_RNG) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SDMMC1) == RCC_PERIPHCLK_SDMMC1)) + +#elif defined(STM32L451xx) + +#define IS_RCC_PERIPHCLOCK(__SELECTION__) \ + ((((__SELECTION__) & RCC_PERIPHCLK_USART1) == RCC_PERIPHCLK_USART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART2) == RCC_PERIPHCLK_USART2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART3) == RCC_PERIPHCLK_USART3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_UART4) == RCC_PERIPHCLK_UART4) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPUART1) == RCC_PERIPHCLK_LPUART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C1) == RCC_PERIPHCLK_I2C1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C2) == RCC_PERIPHCLK_I2C2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C3) == RCC_PERIPHCLK_I2C3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C4) == RCC_PERIPHCLK_I2C4) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM1) == RCC_PERIPHCLK_LPTIM1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM2) == RCC_PERIPHCLK_LPTIM2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_ADC) == RCC_PERIPHCLK_ADC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_DFSDM1) == RCC_PERIPHCLK_DFSDM1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RNG) == RCC_PERIPHCLK_RNG) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SDMMC1) == RCC_PERIPHCLK_SDMMC1)) + +#elif defined(STM32L452xx) || defined(STM32L462xx) + +#define IS_RCC_PERIPHCLOCK(__SELECTION__) \ + ((((__SELECTION__) & RCC_PERIPHCLK_USART1) == RCC_PERIPHCLK_USART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART2) == RCC_PERIPHCLK_USART2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART3) == RCC_PERIPHCLK_USART3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_UART4) == RCC_PERIPHCLK_UART4) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPUART1) == RCC_PERIPHCLK_LPUART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C1) == RCC_PERIPHCLK_I2C1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C2) == RCC_PERIPHCLK_I2C2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C3) == RCC_PERIPHCLK_I2C3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C4) == RCC_PERIPHCLK_I2C4) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM1) == RCC_PERIPHCLK_LPTIM1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM2) == RCC_PERIPHCLK_LPTIM2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USB) == RCC_PERIPHCLK_USB) || \ + (((__SELECTION__) & RCC_PERIPHCLK_ADC) == RCC_PERIPHCLK_ADC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_DFSDM1) == RCC_PERIPHCLK_DFSDM1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RNG) == RCC_PERIPHCLK_RNG) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SDMMC1) == RCC_PERIPHCLK_SDMMC1)) + +#elif defined(STM32L471xx) + +#define IS_RCC_PERIPHCLOCK(__SELECTION__) \ + ((((__SELECTION__) & RCC_PERIPHCLK_USART1) == RCC_PERIPHCLK_USART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART2) == RCC_PERIPHCLK_USART2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART3) == RCC_PERIPHCLK_USART3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_UART4) == RCC_PERIPHCLK_UART4) || \ + (((__SELECTION__) & RCC_PERIPHCLK_UART5) == RCC_PERIPHCLK_UART5) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPUART1) == RCC_PERIPHCLK_LPUART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C1) == RCC_PERIPHCLK_I2C1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C2) == RCC_PERIPHCLK_I2C2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C3) == RCC_PERIPHCLK_I2C3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM1) == RCC_PERIPHCLK_LPTIM1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM2) == RCC_PERIPHCLK_LPTIM2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SAI2) == RCC_PERIPHCLK_SAI2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_ADC) == RCC_PERIPHCLK_ADC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SWPMI1) == RCC_PERIPHCLK_SWPMI1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_DFSDM1) == RCC_PERIPHCLK_DFSDM1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RNG) == RCC_PERIPHCLK_RNG) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SDMMC1) == RCC_PERIPHCLK_SDMMC1)) + +#elif defined(STM32L496xx) || defined(STM32L4A6xx) + +#define IS_RCC_PERIPHCLOCK(__SELECTION__) \ + ((((__SELECTION__) & RCC_PERIPHCLK_USART1) == RCC_PERIPHCLK_USART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART2) == RCC_PERIPHCLK_USART2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART3) == RCC_PERIPHCLK_USART3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_UART4) == RCC_PERIPHCLK_UART4) || \ + (((__SELECTION__) & RCC_PERIPHCLK_UART5) == RCC_PERIPHCLK_UART5) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPUART1) == RCC_PERIPHCLK_LPUART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C1) == RCC_PERIPHCLK_I2C1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C2) == RCC_PERIPHCLK_I2C2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C3) == RCC_PERIPHCLK_I2C3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C4) == RCC_PERIPHCLK_I2C4) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM1) == RCC_PERIPHCLK_LPTIM1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM2) == RCC_PERIPHCLK_LPTIM2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SAI2) == RCC_PERIPHCLK_SAI2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USB) == RCC_PERIPHCLK_USB) || \ + (((__SELECTION__) & RCC_PERIPHCLK_ADC) == RCC_PERIPHCLK_ADC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SWPMI1) == RCC_PERIPHCLK_SWPMI1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_DFSDM1) == RCC_PERIPHCLK_DFSDM1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RNG) == RCC_PERIPHCLK_RNG) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SDMMC1) == RCC_PERIPHCLK_SDMMC1)) + +#elif defined(STM32L4R5xx) || defined(STM32L4S5xx) + +#define IS_RCC_PERIPHCLOCK(__SELECTION__) \ + ((((__SELECTION__) & RCC_PERIPHCLK_USART1) == RCC_PERIPHCLK_USART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART2) == RCC_PERIPHCLK_USART2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART3) == RCC_PERIPHCLK_USART3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_UART4) == RCC_PERIPHCLK_UART4) || \ + (((__SELECTION__) & RCC_PERIPHCLK_UART5) == RCC_PERIPHCLK_UART5) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPUART1) == RCC_PERIPHCLK_LPUART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C1) == RCC_PERIPHCLK_I2C1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C2) == RCC_PERIPHCLK_I2C2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C3) == RCC_PERIPHCLK_I2C3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C4) == RCC_PERIPHCLK_I2C4) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM1) == RCC_PERIPHCLK_LPTIM1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM2) == RCC_PERIPHCLK_LPTIM2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SAI2) == RCC_PERIPHCLK_SAI2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USB) == RCC_PERIPHCLK_USB) || \ + (((__SELECTION__) & RCC_PERIPHCLK_ADC) == RCC_PERIPHCLK_ADC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_DFSDM1) == RCC_PERIPHCLK_DFSDM1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_DFSDM1AUDIO) == RCC_PERIPHCLK_DFSDM1AUDIO) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RNG) == RCC_PERIPHCLK_RNG) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SDMMC1) == RCC_PERIPHCLK_SDMMC1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_OSPI) == RCC_PERIPHCLK_OSPI)) + +#elif defined(STM32L4R7xx) || defined(STM32L4S7xx) + +#define IS_RCC_PERIPHCLOCK(__SELECTION__) \ + ((((__SELECTION__) & RCC_PERIPHCLK_USART1) == RCC_PERIPHCLK_USART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART2) == RCC_PERIPHCLK_USART2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART3) == RCC_PERIPHCLK_USART3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_UART4) == RCC_PERIPHCLK_UART4) || \ + (((__SELECTION__) & RCC_PERIPHCLK_UART5) == RCC_PERIPHCLK_UART5) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPUART1) == RCC_PERIPHCLK_LPUART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C1) == RCC_PERIPHCLK_I2C1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C2) == RCC_PERIPHCLK_I2C2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C3) == RCC_PERIPHCLK_I2C3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C4) == RCC_PERIPHCLK_I2C4) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM1) == RCC_PERIPHCLK_LPTIM1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM2) == RCC_PERIPHCLK_LPTIM2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SAI2) == RCC_PERIPHCLK_SAI2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USB) == RCC_PERIPHCLK_USB) || \ + (((__SELECTION__) & RCC_PERIPHCLK_ADC) == RCC_PERIPHCLK_ADC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_DFSDM1) == RCC_PERIPHCLK_DFSDM1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_DFSDM1AUDIO) == RCC_PERIPHCLK_DFSDM1AUDIO) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RNG) == RCC_PERIPHCLK_RNG) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SDMMC1) == RCC_PERIPHCLK_SDMMC1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_OSPI) == RCC_PERIPHCLK_OSPI) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LTDC) == RCC_PERIPHCLK_LTDC)) + +#elif defined(STM32L4R9xx) || defined(STM32L4S9xx) + +#define IS_RCC_PERIPHCLOCK(__SELECTION__) \ + ((((__SELECTION__) & RCC_PERIPHCLK_USART1) == RCC_PERIPHCLK_USART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART2) == RCC_PERIPHCLK_USART2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART3) == RCC_PERIPHCLK_USART3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_UART4) == RCC_PERIPHCLK_UART4) || \ + (((__SELECTION__) & RCC_PERIPHCLK_UART5) == RCC_PERIPHCLK_UART5) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPUART1) == RCC_PERIPHCLK_LPUART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C1) == RCC_PERIPHCLK_I2C1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C2) == RCC_PERIPHCLK_I2C2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C3) == RCC_PERIPHCLK_I2C3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C4) == RCC_PERIPHCLK_I2C4) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM1) == RCC_PERIPHCLK_LPTIM1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM2) == RCC_PERIPHCLK_LPTIM2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SAI2) == RCC_PERIPHCLK_SAI2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USB) == RCC_PERIPHCLK_USB) || \ + (((__SELECTION__) & RCC_PERIPHCLK_ADC) == RCC_PERIPHCLK_ADC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_DFSDM1) == RCC_PERIPHCLK_DFSDM1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_DFSDM1AUDIO) == RCC_PERIPHCLK_DFSDM1AUDIO) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RNG) == RCC_PERIPHCLK_RNG) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SDMMC1) == RCC_PERIPHCLK_SDMMC1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_OSPI) == RCC_PERIPHCLK_OSPI) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LTDC) == RCC_PERIPHCLK_LTDC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_DSI) == RCC_PERIPHCLK_DSI)) + +#else + +#define IS_RCC_PERIPHCLOCK(__SELECTION__) \ + ((((__SELECTION__) & RCC_PERIPHCLK_USART1) == RCC_PERIPHCLK_USART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART2) == RCC_PERIPHCLK_USART2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART3) == RCC_PERIPHCLK_USART3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_UART4) == RCC_PERIPHCLK_UART4) || \ + (((__SELECTION__) & RCC_PERIPHCLK_UART5) == RCC_PERIPHCLK_UART5) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPUART1) == RCC_PERIPHCLK_LPUART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C1) == RCC_PERIPHCLK_I2C1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C2) == RCC_PERIPHCLK_I2C2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C3) == RCC_PERIPHCLK_I2C3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM1) == RCC_PERIPHCLK_LPTIM1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM2) == RCC_PERIPHCLK_LPTIM2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SAI2) == RCC_PERIPHCLK_SAI2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USB) == RCC_PERIPHCLK_USB) || \ + (((__SELECTION__) & RCC_PERIPHCLK_ADC) == RCC_PERIPHCLK_ADC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SWPMI1) == RCC_PERIPHCLK_SWPMI1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_DFSDM1) == RCC_PERIPHCLK_DFSDM1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RNG) == RCC_PERIPHCLK_RNG) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SDMMC1) == RCC_PERIPHCLK_SDMMC1)) + +#endif /* STM32L431xx */ + +#define IS_RCC_USART1CLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_USART1CLKSOURCE_PCLK2) || \ + ((__SOURCE__) == RCC_USART1CLKSOURCE_SYSCLK) || \ + ((__SOURCE__) == RCC_USART1CLKSOURCE_LSE) || \ + ((__SOURCE__) == RCC_USART1CLKSOURCE_HSI)) + +#define IS_RCC_USART2CLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_USART2CLKSOURCE_PCLK1) || \ + ((__SOURCE__) == RCC_USART2CLKSOURCE_SYSCLK) || \ + ((__SOURCE__) == RCC_USART2CLKSOURCE_LSE) || \ + ((__SOURCE__) == RCC_USART2CLKSOURCE_HSI)) + +#if defined(USART3) + +#define IS_RCC_USART3CLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_USART3CLKSOURCE_PCLK1) || \ + ((__SOURCE__) == RCC_USART3CLKSOURCE_SYSCLK) || \ + ((__SOURCE__) == RCC_USART3CLKSOURCE_LSE) || \ + ((__SOURCE__) == RCC_USART3CLKSOURCE_HSI)) + +#endif /* USART3 */ + +#if defined(UART4) + +#define IS_RCC_UART4CLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_UART4CLKSOURCE_PCLK1) || \ + ((__SOURCE__) == RCC_UART4CLKSOURCE_SYSCLK) || \ + ((__SOURCE__) == RCC_UART4CLKSOURCE_LSE) || \ + ((__SOURCE__) == RCC_UART4CLKSOURCE_HSI)) + +#endif /* UART4 */ + +#if defined(UART5) + +#define IS_RCC_UART5CLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_UART5CLKSOURCE_PCLK1) || \ + ((__SOURCE__) == RCC_UART5CLKSOURCE_SYSCLK) || \ + ((__SOURCE__) == RCC_UART5CLKSOURCE_LSE) || \ + ((__SOURCE__) == RCC_UART5CLKSOURCE_HSI)) + +#endif /* UART5 */ + +#define IS_RCC_LPUART1CLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_LPUART1CLKSOURCE_PCLK1) || \ + ((__SOURCE__) == RCC_LPUART1CLKSOURCE_SYSCLK) || \ + ((__SOURCE__) == RCC_LPUART1CLKSOURCE_LSE) || \ + ((__SOURCE__) == RCC_LPUART1CLKSOURCE_HSI)) + +#define IS_RCC_I2C1CLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_I2C1CLKSOURCE_PCLK1) || \ + ((__SOURCE__) == RCC_I2C1CLKSOURCE_SYSCLK)|| \ + ((__SOURCE__) == RCC_I2C1CLKSOURCE_HSI)) + +#if defined(I2C2) + +#define IS_RCC_I2C2CLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_I2C2CLKSOURCE_PCLK1) || \ + ((__SOURCE__) == RCC_I2C2CLKSOURCE_SYSCLK)|| \ + ((__SOURCE__) == RCC_I2C2CLKSOURCE_HSI)) + +#endif /* I2C2 */ + +#define IS_RCC_I2C3CLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_I2C3CLKSOURCE_PCLK1) || \ + ((__SOURCE__) == RCC_I2C3CLKSOURCE_SYSCLK)|| \ + ((__SOURCE__) == RCC_I2C3CLKSOURCE_HSI)) + +#if defined(I2C4) + +#define IS_RCC_I2C4CLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_I2C4CLKSOURCE_PCLK1) || \ + ((__SOURCE__) == RCC_I2C4CLKSOURCE_SYSCLK)|| \ + ((__SOURCE__) == RCC_I2C4CLKSOURCE_HSI)) + +#endif /* I2C4 */ + +#if defined(RCC_PLLSAI2_SUPPORT) + +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +#define IS_RCC_SAI1CLK(__SOURCE__) \ + (((__SOURCE__) == RCC_SAI1CLKSOURCE_PLLSAI1) || \ + ((__SOURCE__) == RCC_SAI1CLKSOURCE_PLLSAI2) || \ + ((__SOURCE__) == RCC_SAI1CLKSOURCE_PLL) || \ + ((__SOURCE__) == RCC_SAI1CLKSOURCE_PIN) || \ + ((__SOURCE__) == RCC_SAI1CLKSOURCE_HSI)) +#else +#define IS_RCC_SAI1CLK(__SOURCE__) \ + (((__SOURCE__) == RCC_SAI1CLKSOURCE_PLLSAI1) || \ + ((__SOURCE__) == RCC_SAI1CLKSOURCE_PLLSAI2) || \ + ((__SOURCE__) == RCC_SAI1CLKSOURCE_PLL) || \ + ((__SOURCE__) == RCC_SAI1CLKSOURCE_PIN)) +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#else + +#define IS_RCC_SAI1CLK(__SOURCE__) \ + (((__SOURCE__) == RCC_SAI1CLKSOURCE_PLLSAI1) || \ + ((__SOURCE__) == RCC_SAI1CLKSOURCE_PLL) || \ + ((__SOURCE__) == RCC_SAI1CLKSOURCE_PIN)) + +#endif /* RCC_PLLSAI2_SUPPORT */ + +#if defined(RCC_PLLSAI2_SUPPORT) + +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +#define IS_RCC_SAI2CLK(__SOURCE__) \ + (((__SOURCE__) == RCC_SAI2CLKSOURCE_PLLSAI1) || \ + ((__SOURCE__) == RCC_SAI2CLKSOURCE_PLLSAI2) || \ + ((__SOURCE__) == RCC_SAI2CLKSOURCE_PLL) || \ + ((__SOURCE__) == RCC_SAI2CLKSOURCE_PIN) || \ + ((__SOURCE__) == RCC_SAI2CLKSOURCE_HSI)) +#else +#define IS_RCC_SAI2CLK(__SOURCE__) \ + (((__SOURCE__) == RCC_SAI2CLKSOURCE_PLLSAI1) || \ + ((__SOURCE__) == RCC_SAI2CLKSOURCE_PLLSAI2) || \ + ((__SOURCE__) == RCC_SAI2CLKSOURCE_PLL) || \ + ((__SOURCE__) == RCC_SAI2CLKSOURCE_PIN)) +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#endif /* RCC_PLLSAI2_SUPPORT */ + +#define IS_RCC_LPTIM1CLK(__SOURCE__) \ + (((__SOURCE__) == RCC_LPTIM1CLKSOURCE_PCLK1) || \ + ((__SOURCE__) == RCC_LPTIM1CLKSOURCE_LSI) || \ + ((__SOURCE__) == RCC_LPTIM1CLKSOURCE_HSI) || \ + ((__SOURCE__) == RCC_LPTIM1CLKSOURCE_LSE)) + +#define IS_RCC_LPTIM2CLK(__SOURCE__) \ + (((__SOURCE__) == RCC_LPTIM2CLKSOURCE_PCLK1) || \ + ((__SOURCE__) == RCC_LPTIM2CLKSOURCE_LSI) || \ + ((__SOURCE__) == RCC_LPTIM2CLKSOURCE_HSI) || \ + ((__SOURCE__) == RCC_LPTIM2CLKSOURCE_LSE)) + +#if defined(SDMMC1) +#if defined(RCC_HSI48_SUPPORT) && defined(RCC_CCIPR2_SDMMCSEL) + +#define IS_RCC_SDMMC1CLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_SDMMC1CLKSOURCE_PLLP) || \ + ((__SOURCE__) == RCC_SDMMC1CLKSOURCE_HSI48) || \ + ((__SOURCE__) == RCC_SDMMC1CLKSOURCE_PLLSAI1) || \ + ((__SOURCE__) == RCC_SDMMC1CLKSOURCE_PLL) || \ + ((__SOURCE__) == RCC_SDMMC1CLKSOURCE_MSI)) + +#elif defined(RCC_HSI48_SUPPORT) + +#define IS_RCC_SDMMC1CLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_SDMMC1CLKSOURCE_HSI48) || \ + ((__SOURCE__) == RCC_SDMMC1CLKSOURCE_PLLSAI1) || \ + ((__SOURCE__) == RCC_SDMMC1CLKSOURCE_PLL) || \ + ((__SOURCE__) == RCC_SDMMC1CLKSOURCE_MSI)) +#else + +#define IS_RCC_SDMMC1CLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_SDMMC1CLKSOURCE_NONE) || \ + ((__SOURCE__) == RCC_SDMMC1CLKSOURCE_PLLSAI1) || \ + ((__SOURCE__) == RCC_SDMMC1CLKSOURCE_PLL) || \ + ((__SOURCE__) == RCC_SDMMC1CLKSOURCE_MSI)) + +#endif /* RCC_HSI48_SUPPORT */ +#endif /* SDMMC1 */ + +#if defined(RCC_HSI48_SUPPORT) + +#define IS_RCC_RNGCLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_RNGCLKSOURCE_HSI48) || \ + ((__SOURCE__) == RCC_RNGCLKSOURCE_PLLSAI1) || \ + ((__SOURCE__) == RCC_RNGCLKSOURCE_PLL) || \ + ((__SOURCE__) == RCC_RNGCLKSOURCE_MSI)) + +#else + +#define IS_RCC_RNGCLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_RNGCLKSOURCE_NONE) || \ + ((__SOURCE__) == RCC_RNGCLKSOURCE_PLLSAI1) || \ + ((__SOURCE__) == RCC_RNGCLKSOURCE_PLL) || \ + ((__SOURCE__) == RCC_RNGCLKSOURCE_MSI)) + +#endif /* RCC_HSI48_SUPPORT */ + +#if defined(USB_OTG_FS) || defined(USB) +#if defined(RCC_HSI48_SUPPORT) + +#define IS_RCC_USBCLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_USBCLKSOURCE_HSI48) || \ + ((__SOURCE__) == RCC_USBCLKSOURCE_PLLSAI1) || \ + ((__SOURCE__) == RCC_USBCLKSOURCE_PLL) || \ + ((__SOURCE__) == RCC_USBCLKSOURCE_MSI)) + +#else + +#define IS_RCC_USBCLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_USBCLKSOURCE_NONE) || \ + ((__SOURCE__) == RCC_USBCLKSOURCE_PLLSAI1) || \ + ((__SOURCE__) == RCC_USBCLKSOURCE_PLL) || \ + ((__SOURCE__) == RCC_USBCLKSOURCE_MSI)) + +#endif /* RCC_HSI48_SUPPORT */ +#endif /* USB_OTG_FS || USB */ + +#if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || defined(STM32L496xx) || defined(STM32L4A6xx) + +#define IS_RCC_ADCCLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_ADCCLKSOURCE_NONE) || \ + ((__SOURCE__) == RCC_ADCCLKSOURCE_PLLSAI1) || \ + ((__SOURCE__) == RCC_ADCCLKSOURCE_PLLSAI2) || \ + ((__SOURCE__) == RCC_ADCCLKSOURCE_SYSCLK)) + +#else + +#define IS_RCC_ADCCLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_ADCCLKSOURCE_NONE) || \ + ((__SOURCE__) == RCC_ADCCLKSOURCE_PLLSAI1) || \ + ((__SOURCE__) == RCC_ADCCLKSOURCE_SYSCLK)) + +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || STM32L496xx || STM32L4A6xx */ + +#if defined(SWPMI1) + +#define IS_RCC_SWPMI1CLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_SWPMI1CLKSOURCE_PCLK1) || \ + ((__SOURCE__) == RCC_SWPMI1CLKSOURCE_HSI)) + +#endif /* SWPMI1 */ + +#if defined(DFSDM1_Filter0) + +#define IS_RCC_DFSDM1CLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_DFSDM1CLKSOURCE_PCLK2) || \ + ((__SOURCE__) == RCC_DFSDM1CLKSOURCE_SYSCLK)) + +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + +#define IS_RCC_DFSDM1AUDIOCLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_DFSDM1AUDIOCLKSOURCE_SAI1) || \ + ((__SOURCE__) == RCC_DFSDM1AUDIOCLKSOURCE_HSI) || \ + ((__SOURCE__) == RCC_DFSDM1AUDIOCLKSOURCE_MSI)) + +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#endif /* DFSDM1_Filter0 */ + +#if defined(LTDC) + +#define IS_RCC_LTDCCLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_LTDCCLKSOURCE_PLLSAI2_DIV2) || \ + ((__SOURCE__) == RCC_LTDCCLKSOURCE_PLLSAI2_DIV4) || \ + ((__SOURCE__) == RCC_LTDCCLKSOURCE_PLLSAI2_DIV8) || \ + ((__SOURCE__) == RCC_LTDCCLKSOURCE_PLLSAI2_DIV16)) + +#endif /* LTDC */ + +#if defined(DSI) + +#define IS_RCC_DSICLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_DSICLKSOURCE_DSIPHY) || \ + ((__SOURCE__) == RCC_DSICLKSOURCE_PLLSAI2)) + +#endif /* DSI */ + +#if defined(OCTOSPI1) || defined(OCTOSPI2) + +#define IS_RCC_OSPICLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_OSPICLKSOURCE_SYSCLK) || \ + ((__SOURCE__) == RCC_OSPICLKSOURCE_MSI) || \ + ((__SOURCE__) == RCC_OSPICLKSOURCE_PLL)) + +#endif /* OCTOSPI1 || OCTOSPI2 */ + +#define IS_RCC_PLLSAI1SOURCE(__VALUE__) IS_RCC_PLLSOURCE(__VALUE__) + +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) +#define IS_RCC_PLLSAI1M_VALUE(__VALUE__) ((1U <= (__VALUE__)) && ((__VALUE__) <= 16U)) +#else +#define IS_RCC_PLLSAI1M_VALUE(__VALUE__) ((1U <= (__VALUE__)) && ((__VALUE__) <= 8U)) +#endif /* RCC_PLLSAI1M_DIV_1_16_SUPPORT */ + +#define IS_RCC_PLLSAI1N_VALUE(__VALUE__) ((8U <= (__VALUE__)) && ((__VALUE__) <= 86U)) + +#if defined(RCC_PLLSAI1P_DIV_2_31_SUPPORT) +#define IS_RCC_PLLSAI1P_VALUE(__VALUE__) (((__VALUE__) >= 2U) && ((__VALUE__) <= 31U)) +#else +#define IS_RCC_PLLSAI1P_VALUE(__VALUE__) (((__VALUE__) == 7U) || ((__VALUE__) == 17U)) +#endif /* RCC_PLLSAI1P_DIV_2_31_SUPPORT */ + +#define IS_RCC_PLLSAI1Q_VALUE(__VALUE__) (((__VALUE__) == 2U) || ((__VALUE__) == 4U) || \ + ((__VALUE__) == 6U) || ((__VALUE__) == 8U)) + +#define IS_RCC_PLLSAI1R_VALUE(__VALUE__) (((__VALUE__) == 2U) || ((__VALUE__) == 4U) || \ + ((__VALUE__) == 6U) || ((__VALUE__) == 8U)) + +#if defined(RCC_PLLSAI2_SUPPORT) + +#define IS_RCC_PLLSAI2SOURCE(__VALUE__) IS_RCC_PLLSOURCE(__VALUE__) + +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) +#define IS_RCC_PLLSAI2M_VALUE(__VALUE__) ((1U <= (__VALUE__)) && ((__VALUE__) <= 16U)) +#else +#define IS_RCC_PLLSAI2M_VALUE(__VALUE__) ((1U <= (__VALUE__)) && ((__VALUE__) <= 8U)) +#endif /* RCC_PLLSAI2M_DIV_1_16_SUPPORT */ + +#define IS_RCC_PLLSAI2N_VALUE(__VALUE__) ((8U <= (__VALUE__)) && ((__VALUE__) <= 86U)) + +#if defined(RCC_PLLSAI2P_DIV_2_31_SUPPORT) +#define IS_RCC_PLLSAI2P_VALUE(__VALUE__) (((__VALUE__) >= 2U) && ((__VALUE__) <= 31U)) +#else +#define IS_RCC_PLLSAI2P_VALUE(__VALUE__) (((__VALUE__) == 7U) || ((__VALUE__) == 17U)) +#endif /* RCC_PLLSAI2P_DIV_2_31_SUPPORT */ + +#if defined(RCC_PLLSAI2Q_DIV_SUPPORT) +#define IS_RCC_PLLSAI2Q_VALUE(__VALUE__) (((__VALUE__) == 2U) || ((__VALUE__) == 4U) || \ + ((__VALUE__) == 6U) || ((__VALUE__) == 8U)) +#endif /* RCC_PLLSAI2Q_DIV_SUPPORT */ + +#define IS_RCC_PLLSAI2R_VALUE(__VALUE__) (((__VALUE__) == 2U) || ((__VALUE__) == 4U) || \ + ((__VALUE__) == 6U) || ((__VALUE__) == 8U)) + +#endif /* RCC_PLLSAI2_SUPPORT */ + +#if defined(CRS) + +#define IS_RCC_CRS_SYNC_SOURCE(__SOURCE__) (((__SOURCE__) == RCC_CRS_SYNC_SOURCE_GPIO) || \ + ((__SOURCE__) == RCC_CRS_SYNC_SOURCE_LSE) || \ + ((__SOURCE__) == RCC_CRS_SYNC_SOURCE_USB)) + +#define IS_RCC_CRS_SYNC_DIV(__DIV__) (((__DIV__) == RCC_CRS_SYNC_DIV1) || ((__DIV__) == RCC_CRS_SYNC_DIV2) || \ + ((__DIV__) == RCC_CRS_SYNC_DIV4) || ((__DIV__) == RCC_CRS_SYNC_DIV8) || \ + ((__DIV__) == RCC_CRS_SYNC_DIV16) || ((__DIV__) == RCC_CRS_SYNC_DIV32) || \ + ((__DIV__) == RCC_CRS_SYNC_DIV64) || ((__DIV__) == RCC_CRS_SYNC_DIV128)) + +#define IS_RCC_CRS_SYNC_POLARITY(__POLARITY__) (((__POLARITY__) == RCC_CRS_SYNC_POLARITY_RISING) || \ + ((__POLARITY__) == RCC_CRS_SYNC_POLARITY_FALLING)) + +#define IS_RCC_CRS_RELOADVALUE(__VALUE__) (((__VALUE__) <= 0xFFFFU)) + +#define IS_RCC_CRS_ERRORLIMIT(__VALUE__) (((__VALUE__) <= 0xFFU)) + +#define IS_RCC_CRS_HSI48CALIBRATION(__VALUE__) (((__VALUE__) <= 0x3FU)) + +#define IS_RCC_CRS_FREQERRORDIR(__DIR__) (((__DIR__) == RCC_CRS_FREQERRORDIR_UP) || \ + ((__DIR__) == RCC_CRS_FREQERRORDIR_DOWN)) + +#endif /* CRS */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_HAL_RCC_EX_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rng.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rng.h new file mode 100644 index 0000000..6939084 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rng.h @@ -0,0 +1,325 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_rng.h + * @author MCD Application Team + * @brief Header file of RNG HAL module. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_RNG_H +#define __STM32L4xx_HAL_RNG_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup RNG + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup RNG_Exported_Types RNG Exported Types + * @{ + */ + +#if defined(RNG_CR_CED) +/** + * @brief RNG Configuration Structure definition + */ +typedef struct +{ + uint32_t ClockErrorDetection; /*!< Clock error detection */ +}RNG_InitTypeDef; +#endif /* defined(RNG_CR_CED) */ + +/** + * @brief RNG HAL State Structure definition + */ +typedef enum +{ + HAL_RNG_STATE_RESET = 0x00, /*!< RNG not yet initialized or disabled */ + HAL_RNG_STATE_READY = 0x01, /*!< RNG initialized and ready for use */ + HAL_RNG_STATE_BUSY = 0x02, /*!< RNG internal process is ongoing */ + HAL_RNG_STATE_TIMEOUT = 0x03, /*!< RNG timeout state */ + HAL_RNG_STATE_ERROR = 0x04 /*!< RNG error state */ + +}HAL_RNG_StateTypeDef; + +/** + * @brief RNG Handle Structure definition + */ +typedef struct +{ + RNG_TypeDef *Instance; /*!< Register base address */ + +#if defined(RNG_CR_CED) + RNG_InitTypeDef Init; /*!< RNG configuration parameters */ +#endif /* defined(RNG_CR_CED) */ + + HAL_LockTypeDef Lock; /*!< RNG locking object */ + + __IO HAL_RNG_StateTypeDef State; /*!< RNG communication state */ + + uint32_t RandomNumber; /*!< Last Generated RNG Data */ + +}RNG_HandleTypeDef; + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup RNG_Exported_Constants RNG Exported Constants + * @{ + */ + +/** @defgroup RNG_Interrupt_definition RNG Interrupts Definition + * @{ + */ +#define RNG_IT_DRDY RNG_SR_DRDY /*!< Data Ready interrupt */ +#define RNG_IT_CEI RNG_SR_CEIS /*!< Clock error interrupt */ +#define RNG_IT_SEI RNG_SR_SEIS /*!< Seed error interrupt */ +/** + * @} + */ + +/** @defgroup RNG_Flag_definition RNG Flags Definition + * @{ + */ +#define RNG_FLAG_DRDY RNG_SR_DRDY /*!< Data ready */ +#define RNG_FLAG_CECS RNG_SR_CECS /*!< Clock error current status */ +#define RNG_FLAG_SECS RNG_SR_SECS /*!< Seed error current status */ +/** + * @} + */ + +#if defined(RNG_CR_CED) +/** @defgroup RNG_Clock_Error_Detection RNG Clock Error Detection + * @{ + */ +#define RNG_CED_ENABLE ((uint32_t)0x00000000) /*!< Clock error detection enabled */ +#define RNG_CED_DISABLE RNG_CR_CED /*!< Clock error detection disabled */ +/** + * @} + */ +#endif /* defined(RNG_CR_CED) */ + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ +/** @defgroup RNG_Exported_Macros RNG Exported Macros + * @{ + */ + +/** @brief Reset RNG handle state. + * @param __HANDLE__: RNG Handle + * @retval None + */ +#define __HAL_RNG_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_RNG_STATE_RESET) + +/** + * @brief Enable the RNG peripheral. + * @param __HANDLE__: RNG Handle + * @retval None + */ +#define __HAL_RNG_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR |= RNG_CR_RNGEN) + +/** + * @brief Disable the RNG peripheral. + * @param __HANDLE__: RNG Handle + * @retval None + */ +#define __HAL_RNG_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR &= ~RNG_CR_RNGEN) + +/** + * @brief Check whether the specified RNG flag is set or not. + * @param __HANDLE__: RNG Handle + * @param __FLAG__: RNG flag + * This parameter can be one of the following values: + * @arg RNG_FLAG_DRDY: Data ready + * @arg RNG_FLAG_CECS: Clock error current status + * @arg RNG_FLAG_SECS: Seed error current status + * @retval The new state of __FLAG__ (SET or RESET). + */ +#define __HAL_RNG_GET_FLAG(__HANDLE__, __FLAG__) (((__HANDLE__)->Instance->SR & (__FLAG__)) == (__FLAG__)) + + +/** + * @brief Clear the selected RNG flag status. + * @param __HANDLE__: RNG handle + * @param __FLAG__: RNG flag to clear + * @note WARNING: This is a dummy macro for HAL code alignment, + * flags RNG_FLAG_DRDY, RNG_FLAG_CECS and RNG_FLAG_SECS are read-only. + * @retval None + */ +#define __HAL_RNG_CLEAR_FLAG(__HANDLE__, __FLAG__) /* dummy macro */ + + + +/** + * @brief Enable the RNG interrupt. + * @param __HANDLE__: RNG Handle + * @retval None + */ +#define __HAL_RNG_ENABLE_IT(__HANDLE__) ((__HANDLE__)->Instance->CR |= RNG_CR_IE) + +/** + * @brief Disable the RNG interrupt. + * @param __HANDLE__: RNG Handle + * @retval None + */ +#define __HAL_RNG_DISABLE_IT(__HANDLE__) ((__HANDLE__)->Instance->CR &= ~RNG_CR_IE) + +/** + * @brief Check whether the specified RNG interrupt has occurred or not. + * @param __HANDLE__: RNG Handle + * @param __INTERRUPT__: specifies the RNG interrupt status flag to check. + * This parameter can be one of the following values: + * @arg RNG_IT_DRDY: Data ready interrupt + * @arg RNG_IT_CEI: Clock error interrupt + * @arg RNG_IT_SEI: Seed error interrupt + * @retval The new state of __INTERRUPT__ (SET or RESET). + */ +#define __HAL_RNG_GET_IT(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->SR & (__INTERRUPT__)) == (__INTERRUPT__)) + +/** + * @brief Clear the RNG interrupt status flags. + * @param __HANDLE__: RNG Handle + * @param __INTERRUPT__: specifies the RNG interrupt status flag to clear. + * This parameter can be one of the following values: + * @arg RNG_IT_CEI: Clock error interrupt + * @arg RNG_IT_SEI: Seed error interrupt + * @note RNG_IT_DRDY flag is read-only, reading RNG_DR register automatically clears RNG_IT_DRDY. + * @retval None + */ +#define __HAL_RNG_CLEAR_IT(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->SR) = ~(__INTERRUPT__)) + +/** + * @} + */ + + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup RNG_Exported_Functions RNG Exported Functions + * @{ + */ + +/* Initialization and de-initialization functions ******************************/ +/** @defgroup RNG_Exported_Functions_Group1 Initialization and de-initialization functions + * @{ + */ +HAL_StatusTypeDef HAL_RNG_Init(RNG_HandleTypeDef *hrng); +HAL_StatusTypeDef HAL_RNG_DeInit (RNG_HandleTypeDef *hrng); +void HAL_RNG_MspInit(RNG_HandleTypeDef *hrng); +void HAL_RNG_MspDeInit(RNG_HandleTypeDef *hrng); +/** + * @} + */ + +/* Peripheral Control functions ************************************************/ +/** @defgroup RNG_Exported_Functions_Group2 Peripheral Control functions + * @{ + */ +uint32_t HAL_RNG_GetRandomNumber(RNG_HandleTypeDef *hrng); /* Obsolete, use HAL_RNG_GenerateRandomNumber() instead */ +uint32_t HAL_RNG_GetRandomNumber_IT(RNG_HandleTypeDef *hrng); /* Obsolete, use HAL_RNG_GenerateRandomNumber_IT() instead */ + +HAL_StatusTypeDef HAL_RNG_GenerateRandomNumber(RNG_HandleTypeDef *hrng, uint32_t *random32bit); +HAL_StatusTypeDef HAL_RNG_GenerateRandomNumber_IT(RNG_HandleTypeDef *hrng); +uint32_t HAL_RNG_ReadLastRandomNumber(RNG_HandleTypeDef *hrng); + +void HAL_RNG_IRQHandler(RNG_HandleTypeDef *hrng); +void HAL_RNG_ErrorCallback(RNG_HandleTypeDef *hrng); +void HAL_RNG_ReadyDataCallback(RNG_HandleTypeDef* hrng, uint32_t random32bit); +/** + * @} + */ + +/* Peripheral State functions **************************************************/ +/** @defgroup RNG_Exported_Functions_Group3 Peripheral State functions + * @{ + */ +HAL_RNG_StateTypeDef HAL_RNG_GetState(RNG_HandleTypeDef *hrng); +/** + * @} + */ + +/** + * @} + */ + +/* Private types -------------------------------------------------------------*/ +/* Private defines -----------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ +/** @addtogroup RNG_Private_Macros RNG Private Macros + * @{ + */ + +#if defined(RNG_CR_CED) +/** + * @brief Verify the RNG Clock Error Detection mode. + * @param __MODE__: RNG Clock Error Detection mode + * @retval SET (__MODE__ is valid) or RESET (__MODE__ is invalid) + */ +#define IS_RNG_CED(__MODE__) (((__MODE__) == RNG_CED_ENABLE) || \ + ((__MODE__) == RNG_CED_DISABLE)) +#endif /* defined(RNG_CR_CED) */ + +/** + * @} + */ +/* Private functions prototypes ----------------------------------------------*/ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_HAL_RNG_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rtc.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rtc.h new file mode 100644 index 0000000..5d6ce90 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rtc.h @@ -0,0 +1,861 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_rtc.h + * @author MCD Application Team + * @brief Header file of RTC HAL module. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_RTC_H +#define __STM32L4xx_HAL_RTC_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup RTC + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup RTC_Exported_Types RTC Exported Types + * @{ + */ +/** + * @brief HAL State structures definition + */ +typedef enum +{ + HAL_RTC_STATE_RESET = 0x00, /*!< RTC not yet initialized or disabled */ + HAL_RTC_STATE_READY = 0x01, /*!< RTC initialized and ready for use */ + HAL_RTC_STATE_BUSY = 0x02, /*!< RTC process is ongoing */ + HAL_RTC_STATE_TIMEOUT = 0x03, /*!< RTC timeout state */ + HAL_RTC_STATE_ERROR = 0x04 /*!< RTC error state */ + +}HAL_RTCStateTypeDef; + +/** + * @brief RTC Configuration Structure definition + */ +typedef struct +{ + uint32_t HourFormat; /*!< Specifies the RTC Hour Format. + This parameter can be a value of @ref RTC_Hour_Formats */ + + uint32_t AsynchPrediv; /*!< Specifies the RTC Asynchronous Predivider value. + This parameter must be a number between Min_Data = 0x00 and Max_Data = 0x7F */ + + uint32_t SynchPrediv; /*!< Specifies the RTC Synchronous Predivider value. + This parameter must be a number between Min_Data = 0x00 and Max_Data = 0x7FFF */ + + uint32_t OutPut; /*!< Specifies which signal will be routed to the RTC output. + This parameter can be a value of @ref RTCEx_Output_selection_Definitions */ + + uint32_t OutPutRemap; /*!< Specifies the remap for RTC output. + This parameter can be a value of @ref RTC_Output_ALARM_OUT_Remap */ + + uint32_t OutPutPolarity; /*!< Specifies the polarity of the output signal. + This parameter can be a value of @ref RTC_Output_Polarity_Definitions */ + + uint32_t OutPutType; /*!< Specifies the RTC Output Pin mode. + This parameter can be a value of @ref RTC_Output_Type_ALARM_OUT */ +}RTC_InitTypeDef; + +/** + * @brief RTC Time structure definition + */ +typedef struct +{ + uint8_t Hours; /*!< Specifies the RTC Time Hour. + This parameter must be a number between Min_Data = 0 and Max_Data = 12 if the RTC_HourFormat_12 is selected. + This parameter must be a number between Min_Data = 0 and Max_Data = 23 if the RTC_HourFormat_24 is selected */ + + uint8_t Minutes; /*!< Specifies the RTC Time Minutes. + This parameter must be a number between Min_Data = 0 and Max_Data = 59 */ + + uint8_t Seconds; /*!< Specifies the RTC Time Seconds. + This parameter must be a number between Min_Data = 0 and Max_Data = 59 */ + + uint8_t TimeFormat; /*!< Specifies the RTC AM/PM Time. + This parameter can be a value of @ref RTC_AM_PM_Definitions */ + + uint32_t SubSeconds; /*!< Specifies the RTC_SSR RTC Sub Second register content. + This parameter corresponds to a time unit range between [0-1] Second + with [1 Sec / SecondFraction +1] granularity */ + + uint32_t SecondFraction; /*!< Specifies the range or granularity of Sub Second register content + corresponding to Synchronous pre-scaler factor value (PREDIV_S) + This parameter corresponds to a time unit range between [0-1] Second + with [1 Sec / SecondFraction +1] granularity. + This field will be used only by HAL_RTC_GetTime function */ + + uint32_t DayLightSaving; /*!< Specifies RTC_DayLightSaveOperation: the value of hour adjustment. + This parameter can be a value of @ref RTC_DayLightSaving_Definitions */ + + uint32_t StoreOperation; /*!< Specifies RTC_StoreOperation value to be written in the BCK bit + in CR register to store the operation. + This parameter can be a value of @ref RTC_StoreOperation_Definitions */ +}RTC_TimeTypeDef; + +/** + * @brief RTC Date structure definition + */ +typedef struct +{ + uint8_t WeekDay; /*!< Specifies the RTC Date WeekDay. + This parameter can be a value of @ref RTC_WeekDay_Definitions */ + + uint8_t Month; /*!< Specifies the RTC Date Month (in BCD format). + This parameter can be a value of @ref RTC_Month_Date_Definitions */ + + uint8_t Date; /*!< Specifies the RTC Date. + This parameter must be a number between Min_Data = 1 and Max_Data = 31 */ + + uint8_t Year; /*!< Specifies the RTC Date Year. + This parameter must be a number between Min_Data = 0 and Max_Data = 99 */ + +}RTC_DateTypeDef; + +/** + * @brief RTC Alarm structure definition + */ +typedef struct +{ + RTC_TimeTypeDef AlarmTime; /*!< Specifies the RTC Alarm Time members */ + + uint32_t AlarmMask; /*!< Specifies the RTC Alarm Masks. + This parameter can be a value of @ref RTC_AlarmMask_Definitions */ + + uint32_t AlarmSubSecondMask; /*!< Specifies the RTC Alarm SubSeconds Masks. + This parameter can be a value of @ref RTC_Alarm_Sub_Seconds_Masks_Definitions */ + + uint32_t AlarmDateWeekDaySel; /*!< Specifies the RTC Alarm is on Date or WeekDay. + This parameter can be a value of @ref RTC_AlarmDateWeekDay_Definitions */ + + uint8_t AlarmDateWeekDay; /*!< Specifies the RTC Alarm Date/WeekDay. + If the Alarm Date is selected, this parameter must be set to a value in the 1-31 range. + If the Alarm WeekDay is selected, this parameter can be a value of @ref RTC_WeekDay_Definitions */ + + uint32_t Alarm; /*!< Specifies the alarm . + This parameter can be a value of @ref RTC_Alarms_Definitions */ +}RTC_AlarmTypeDef; + +/** + * @brief Time Handle Structure definition + */ +typedef struct +{ + RTC_TypeDef *Instance; /*!< Register base address */ + + RTC_InitTypeDef Init; /*!< RTC required parameters */ + + HAL_LockTypeDef Lock; /*!< RTC locking object */ + + __IO HAL_RTCStateTypeDef State; /*!< Time communication state */ + +}RTC_HandleTypeDef; + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup RTC_Exported_Constants RTC Exported Constants + * @{ + */ + +/** @defgroup RTC_Hour_Formats RTC Hour Formats + * @{ + */ +#define RTC_HOURFORMAT_24 ((uint32_t)0x00000000) +#define RTC_HOURFORMAT_12 ((uint32_t)0x00000040) +/** + * @} + */ + +/** @defgroup RTC_Output_Polarity_Definitions RTC Output Polarity Definitions + * @{ + */ +#define RTC_OUTPUT_POLARITY_HIGH ((uint32_t)0x00000000) +#define RTC_OUTPUT_POLARITY_LOW ((uint32_t)0x00100000) +/** + * @} + */ + +/** @defgroup RTC_Output_Type_ALARM_OUT RTC Output Type ALARM OUT + * @{ + */ +#define RTC_OUTPUT_TYPE_OPENDRAIN ((uint32_t)0x00000000) +#define RTC_OUTPUT_TYPE_PUSHPULL ((uint32_t)RTC_OR_ALARMOUTTYPE) +/** + * @} + */ + +/** @defgroup RTC_Output_ALARM_OUT_Remap RTC Output ALARM OUT Remap + * @{ + */ +#define RTC_OUTPUT_REMAP_NONE ((uint32_t)0x00000000) +#define RTC_OUTPUT_REMAP_POS1 ((uint32_t)RTC_OR_OUT_RMP) +/** + * @} + */ + +/** @defgroup RTC_AM_PM_Definitions RTC AM PM Definitions + * @{ + */ +#define RTC_HOURFORMAT12_AM ((uint8_t)0x00) +#define RTC_HOURFORMAT12_PM ((uint8_t)0x40) +/** + * @} + */ + +/** @defgroup RTC_DayLightSaving_Definitions RTC DayLight Saving Definitions + * @{ + */ +#define RTC_DAYLIGHTSAVING_SUB1H ((uint32_t)0x00020000) +#define RTC_DAYLIGHTSAVING_ADD1H ((uint32_t)0x00010000) +#define RTC_DAYLIGHTSAVING_NONE ((uint32_t)0x00000000) +/** + * @} + */ + +/** @defgroup RTC_StoreOperation_Definitions RTC Store Operation Definitions + * @{ + */ +#define RTC_STOREOPERATION_RESET ((uint32_t)0x00000000) +#define RTC_STOREOPERATION_SET ((uint32_t)0x00040000) +/** + * @} + */ + +/** @defgroup RTC_Input_parameter_format_definitions RTC Input Parameter Format Definitions + * @{ + */ +#define RTC_FORMAT_BIN ((uint32_t)0x00000000) +#define RTC_FORMAT_BCD ((uint32_t)0x00000001) +/** + * @} + */ + +/** @defgroup RTC_Month_Date_Definitions RTC Month Date Definitions + * @{ + */ + +/* Coded in BCD format */ +#define RTC_MONTH_JANUARY ((uint8_t)0x01) +#define RTC_MONTH_FEBRUARY ((uint8_t)0x02) +#define RTC_MONTH_MARCH ((uint8_t)0x03) +#define RTC_MONTH_APRIL ((uint8_t)0x04) +#define RTC_MONTH_MAY ((uint8_t)0x05) +#define RTC_MONTH_JUNE ((uint8_t)0x06) +#define RTC_MONTH_JULY ((uint8_t)0x07) +#define RTC_MONTH_AUGUST ((uint8_t)0x08) +#define RTC_MONTH_SEPTEMBER ((uint8_t)0x09) +#define RTC_MONTH_OCTOBER ((uint8_t)0x10) +#define RTC_MONTH_NOVEMBER ((uint8_t)0x11) +#define RTC_MONTH_DECEMBER ((uint8_t)0x12) +/** + * @} + */ + +/** @defgroup RTC_WeekDay_Definitions RTC WeekDay Definitions + * @{ + */ +#define RTC_WEEKDAY_MONDAY ((uint8_t)0x01) +#define RTC_WEEKDAY_TUESDAY ((uint8_t)0x02) +#define RTC_WEEKDAY_WEDNESDAY ((uint8_t)0x03) +#define RTC_WEEKDAY_THURSDAY ((uint8_t)0x04) +#define RTC_WEEKDAY_FRIDAY ((uint8_t)0x05) +#define RTC_WEEKDAY_SATURDAY ((uint8_t)0x06) +#define RTC_WEEKDAY_SUNDAY ((uint8_t)0x07) +/** + * @} + */ + +/** @defgroup RTC_AlarmDateWeekDay_Definitions RTC Alarm Date WeekDay Definitions + * @{ + */ +#define RTC_ALARMDATEWEEKDAYSEL_DATE ((uint32_t)0x00000000) +#define RTC_ALARMDATEWEEKDAYSEL_WEEKDAY ((uint32_t)0x40000000) +/** + * @} + */ + + +/** @defgroup RTC_AlarmMask_Definitions RTC Alarm Mask Definitions + * @{ + */ +#define RTC_ALARMMASK_NONE ((uint32_t)0x00000000) +#define RTC_ALARMMASK_DATEWEEKDAY RTC_ALRMAR_MSK4 +#define RTC_ALARMMASK_HOURS RTC_ALRMAR_MSK3 +#define RTC_ALARMMASK_MINUTES RTC_ALRMAR_MSK2 +#define RTC_ALARMMASK_SECONDS RTC_ALRMAR_MSK1 +#define RTC_ALARMMASK_ALL ((uint32_t)0x80808080) +/** + * @} + */ + +/** @defgroup RTC_Alarms_Definitions RTC Alarms Definitions + * @{ + */ +#define RTC_ALARM_A RTC_CR_ALRAE +#define RTC_ALARM_B RTC_CR_ALRBE +/** + * @} + */ + +/** @defgroup RTC_Alarm_Sub_Seconds_Masks_Definitions RTC Alarm Sub Seconds Masks Definitions + * @{ + */ +#define RTC_ALARMSUBSECONDMASK_ALL ((uint32_t)0x00000000) /*!< All Alarm SS fields are masked. + There is no comparison on sub seconds + for Alarm */ +#define RTC_ALARMSUBSECONDMASK_SS14_1 ((uint32_t)0x01000000) /*!< SS[14:1] are don't care in Alarm + comparison. Only SS[0] is compared. */ +#define RTC_ALARMSUBSECONDMASK_SS14_2 ((uint32_t)0x02000000) /*!< SS[14:2] are don't care in Alarm + comparison. Only SS[1:0] are compared */ +#define RTC_ALARMSUBSECONDMASK_SS14_3 ((uint32_t)0x03000000) /*!< SS[14:3] are don't care in Alarm + comparison. Only SS[2:0] are compared */ +#define RTC_ALARMSUBSECONDMASK_SS14_4 ((uint32_t)0x04000000) /*!< SS[14:4] are don't care in Alarm + comparison. Only SS[3:0] are compared */ +#define RTC_ALARMSUBSECONDMASK_SS14_5 ((uint32_t)0x05000000) /*!< SS[14:5] are don't care in Alarm + comparison. Only SS[4:0] are compared */ +#define RTC_ALARMSUBSECONDMASK_SS14_6 ((uint32_t)0x06000000) /*!< SS[14:6] are don't care in Alarm + comparison. Only SS[5:0] are compared */ +#define RTC_ALARMSUBSECONDMASK_SS14_7 ((uint32_t)0x07000000) /*!< SS[14:7] are don't care in Alarm + comparison. Only SS[6:0] are compared */ +#define RTC_ALARMSUBSECONDMASK_SS14_8 ((uint32_t)0x08000000) /*!< SS[14:8] are don't care in Alarm + comparison. Only SS[7:0] are compared */ +#define RTC_ALARMSUBSECONDMASK_SS14_9 ((uint32_t)0x09000000) /*!< SS[14:9] are don't care in Alarm + comparison. Only SS[8:0] are compared */ +#define RTC_ALARMSUBSECONDMASK_SS14_10 ((uint32_t)0x0A000000) /*!< SS[14:10] are don't care in Alarm + comparison. Only SS[9:0] are compared */ +#define RTC_ALARMSUBSECONDMASK_SS14_11 ((uint32_t)0x0B000000) /*!< SS[14:11] are don't care in Alarm + comparison. Only SS[10:0] are compared */ +#define RTC_ALARMSUBSECONDMASK_SS14_12 ((uint32_t)0x0C000000) /*!< SS[14:12] are don't care in Alarm + comparison. Only SS[11:0] are compared */ +#define RTC_ALARMSUBSECONDMASK_SS14_13 ((uint32_t)0x0D000000) /*!< SS[14:13] are don't care in Alarm + comparison. Only SS[12:0] are compared */ +#define RTC_ALARMSUBSECONDMASK_SS14 ((uint32_t)0x0E000000) /*!< SS[14] is don't care in Alarm + comparison. Only SS[13:0] are compared */ +#define RTC_ALARMSUBSECONDMASK_NONE ((uint32_t)0x0F000000) /*!< SS[14:0] are compared and must match + to activate alarm. */ +/** + * @} + */ + +/** @defgroup RTC_Interrupts_Definitions RTC Interrupts Definitions + * @{ + */ +#define RTC_IT_TS ((uint32_t)RTC_CR_TSIE) /*!< Enable Timestamp Interrupt */ +#define RTC_IT_WUT ((uint32_t)RTC_CR_WUTIE) /*!< Enable Wakeup timer Interrupt */ +#define RTC_IT_ALRA ((uint32_t)RTC_CR_ALRAIE) /*!< Enable Alarm A Interrupt */ +#define RTC_IT_ALRB ((uint32_t)RTC_CR_ALRBIE) /*!< Enable Alarm B Interrupt */ +#define RTC_IT_TAMP ((uint32_t)RTC_TAMPCR_TAMPIE) /*!< Enable all Tamper Interrupt */ +#define RTC_IT_TAMP1 ((uint32_t)RTC_TAMPCR_TAMP1IE) /*!< Enable Tamper 1 Interrupt */ +#define RTC_IT_TAMP2 ((uint32_t)RTC_TAMPCR_TAMP2IE) /*!< Enable Tamper 2 Interrupt */ +#define RTC_IT_TAMP3 ((uint32_t)RTC_TAMPCR_TAMP3IE) /*!< Enable Tamper 3 Interrupt */ +/** + * @} + */ + +/** @defgroup RTC_Flags_Definitions RTC Flags Definitions + * @{ + */ +#define RTC_FLAG_RECALPF ((uint32_t)RTC_ISR_RECALPF) +#define RTC_FLAG_TAMP3F ((uint32_t)RTC_ISR_TAMP3F) +#define RTC_FLAG_TAMP2F ((uint32_t)RTC_ISR_TAMP2F) +#define RTC_FLAG_TAMP1F ((uint32_t)RTC_ISR_TAMP1F) +#define RTC_FLAG_TSOVF ((uint32_t)RTC_ISR_TSOVF) +#define RTC_FLAG_TSF ((uint32_t)RTC_ISR_TSF) +#define RTC_FLAG_ITSF ((uint32_t)RTC_ISR_ITSF) +#define RTC_FLAG_WUTF ((uint32_t)RTC_ISR_WUTF) +#define RTC_FLAG_ALRBF ((uint32_t)RTC_ISR_ALRBF) +#define RTC_FLAG_ALRAF ((uint32_t)RTC_ISR_ALRAF) +#define RTC_FLAG_INITF ((uint32_t)RTC_ISR_INITF) +#define RTC_FLAG_RSF ((uint32_t)RTC_ISR_RSF) +#define RTC_FLAG_INITS ((uint32_t)RTC_ISR_INITS) +#define RTC_FLAG_SHPF ((uint32_t)RTC_ISR_SHPF) +#define RTC_FLAG_WUTWF ((uint32_t)RTC_ISR_WUTWF) +#define RTC_FLAG_ALRBWF ((uint32_t)RTC_ISR_ALRBWF) +#define RTC_FLAG_ALRAWF ((uint32_t)RTC_ISR_ALRAWF) +/** + * @} + */ + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ +/** @defgroup RTC_Exported_Macros RTC Exported Macros + * @{ + */ + +/** @brief Reset RTC handle state. + * @param __HANDLE__: RTC handle. + * @retval None + */ +#define __HAL_RTC_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_RTC_STATE_RESET) + +/** + * @brief Disable the write protection for RTC registers. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_WRITEPROTECTION_DISABLE(__HANDLE__) \ + do{ \ + (__HANDLE__)->Instance->WPR = 0xCA; \ + (__HANDLE__)->Instance->WPR = 0x53; \ + } while(0) + +/** + * @brief Enable the write protection for RTC registers. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_WRITEPROTECTION_ENABLE(__HANDLE__) \ + do{ \ + (__HANDLE__)->Instance->WPR = 0xFF; \ + } while(0) + + +/** + * @brief Enable the RTC ALARMA peripheral. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_ALARMA_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR |= (RTC_CR_ALRAE)) + +/** + * @brief Disable the RTC ALARMA peripheral. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_ALARMA_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR &= ~(RTC_CR_ALRAE)) + +/** + * @brief Enable the RTC ALARMB peripheral. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_ALARMB_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR |= (RTC_CR_ALRBE)) + +/** + * @brief Disable the RTC ALARMB peripheral. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_ALARMB_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR &= ~(RTC_CR_ALRBE)) + +/** + * @brief Enable the RTC Alarm interrupt. + * @param __HANDLE__: specifies the RTC handle. + * @param __INTERRUPT__: specifies the RTC Alarm interrupt sources to be enabled or disabled. + * This parameter can be any combination of the following values: + * @arg RTC_IT_ALRA: Alarm A interrupt + * @arg RTC_IT_ALRB: Alarm B interrupt + * @retval None + */ +#define __HAL_RTC_ALARM_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CR |= (__INTERRUPT__)) + +/** + * @brief Disable the RTC Alarm interrupt. + * @param __HANDLE__: specifies the RTC handle. + * @param __INTERRUPT__: specifies the RTC Alarm interrupt sources to be enabled or disabled. + * This parameter can be any combination of the following values: + * @arg RTC_IT_ALRA: Alarm A interrupt + * @arg RTC_IT_ALRB: Alarm B interrupt + * @retval None + */ +#define __HAL_RTC_ALARM_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CR &= ~(__INTERRUPT__)) + +/** + * @brief Check whether the specified RTC Alarm interrupt has occurred or not. + * @param __HANDLE__: specifies the RTC handle. + * @param __INTERRUPT__: specifies the RTC Alarm interrupt sources to check. + * This parameter can be: + * @arg RTC_IT_ALRA: Alarm A interrupt + * @arg RTC_IT_ALRB: Alarm B interrupt + * @retval None + */ +#define __HAL_RTC_ALARM_GET_IT(__HANDLE__, __INTERRUPT__) (((((__HANDLE__)->Instance->ISR)& ((__INTERRUPT__)>> 4)) != RESET) ? SET : RESET) + +/** + * @brief Get the selected RTC Alarm's flag status. + * @param __HANDLE__: specifies the RTC handle. + * @param __FLAG__: specifies the RTC Alarm Flag sources to check. + * This parameter can be: + * @arg RTC_FLAG_ALRAF + * @arg RTC_FLAG_ALRBF + * @arg RTC_FLAG_ALRAWF + * @arg RTC_FLAG_ALRBWF + * @retval None + */ +#define __HAL_RTC_ALARM_GET_FLAG(__HANDLE__, __FLAG__) (((((__HANDLE__)->Instance->ISR) & (__FLAG__)) != RESET) ? SET : RESET) + +/** + * @brief Clear the RTC Alarm's pending flags. + * @param __HANDLE__: specifies the RTC handle. + * @param __FLAG__: specifies the RTC Alarm Flag sources to clear. + * This parameter can be: + * @arg RTC_FLAG_ALRAF + * @arg RTC_FLAG_ALRBF + * @retval None + */ +#define __HAL_RTC_ALARM_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->ISR) = (~((__FLAG__) | RTC_ISR_INIT)|((__HANDLE__)->Instance->ISR & RTC_ISR_INIT)) + +/** + * @brief Check whether the specified RTC Alarm interrupt is enabled or not. + * @param __HANDLE__: specifies the RTC handle. + * @param __INTERRUPT__: specifies the RTC Alarm interrupt sources to check. + * This parameter can be: + * @arg RTC_IT_ALRA: Alarm A interrupt + * @arg RTC_IT_ALRB: Alarm B interrupt + * @retval None + */ +#define __HAL_RTC_ALARM_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) (((((__HANDLE__)->Instance->CR) & (__INTERRUPT__)) != RESET) ? SET : RESET) + +/** + * @brief Enable interrupt on the RTC Alarm associated Exti line. + * @retval None + */ +#define __HAL_RTC_ALARM_EXTI_ENABLE_IT() (EXTI->IMR1 |= RTC_EXTI_LINE_ALARM_EVENT) + +/** + * @brief Disable interrupt on the RTC Alarm associated Exti line. + * @retval None + */ +#define __HAL_RTC_ALARM_EXTI_DISABLE_IT() (EXTI->IMR1 &= ~(RTC_EXTI_LINE_ALARM_EVENT)) + +/** + * @brief Enable event on the RTC Alarm associated Exti line. + * @retval None + */ +#define __HAL_RTC_ALARM_EXTI_ENABLE_EVENT() (EXTI->EMR1 |= RTC_EXTI_LINE_ALARM_EVENT) + +/** + * @brief Disable event on the RTC Alarm associated Exti line. + * @retval None + */ +#define __HAL_RTC_ALARM_EXTI_DISABLE_EVENT() (EXTI->EMR1 &= ~(RTC_EXTI_LINE_ALARM_EVENT)) + +/** + * @brief Enable falling edge trigger on the RTC Alarm associated Exti line. + * @retval None + */ +#define __HAL_RTC_ALARM_EXTI_ENABLE_FALLING_EDGE() (EXTI->FTSR1 |= RTC_EXTI_LINE_ALARM_EVENT) + +/** + * @brief Disable falling edge trigger on the RTC Alarm associated Exti line. + * @retval None + */ +#define __HAL_RTC_ALARM_EXTI_DISABLE_FALLING_EDGE() (EXTI->FTSR1 &= ~(RTC_EXTI_LINE_ALARM_EVENT)) + +/** + * @brief Enable rising edge trigger on the RTC Alarm associated Exti line. + * @retval None + */ +#define __HAL_RTC_ALARM_EXTI_ENABLE_RISING_EDGE() (EXTI->RTSR1 |= RTC_EXTI_LINE_ALARM_EVENT) + +/** + * @brief Disable rising edge trigger on the RTC Alarm associated Exti line. + * @retval None + */ +#define __HAL_RTC_ALARM_EXTI_DISABLE_RISING_EDGE() (EXTI->RTSR1 &= ~(RTC_EXTI_LINE_ALARM_EVENT)) + +/** + * @brief Enable rising & falling edge trigger on the RTC Alarm associated Exti line. + * @retval None + */ +#define __HAL_RTC_ALARM_EXTI_ENABLE_RISING_FALLING_EDGE() do { \ + __HAL_RTC_ALARM_EXTI_ENABLE_RISING_EDGE(); \ + __HAL_RTC_ALARM_EXTI_ENABLE_FALLING_EDGE(); \ + } while(0) + +/** + * @brief Disable rising & falling edge trigger on the RTC Alarm associated Exti line. + * @retval None + */ +#define __HAL_RTC_ALARM_EXTI_DISABLE_RISING_FALLING_EDGE() do { \ + __HAL_RTC_ALARM_EXTI_DISABLE_RISING_EDGE(); \ + __HAL_RTC_ALARM_EXTI_DISABLE_FALLING_EDGE(); \ + } while(0) + +/** + * @brief Check whether the RTC Alarm associated Exti line interrupt flag is set or not. + * @retval Line Status. + */ +#define __HAL_RTC_ALARM_EXTI_GET_FLAG() (EXTI->PR1 & RTC_EXTI_LINE_ALARM_EVENT) + +/** + * @brief Clear the RTC Alarm associated Exti line flag. + * @retval None + */ +#define __HAL_RTC_ALARM_EXTI_CLEAR_FLAG() (EXTI->PR1 = RTC_EXTI_LINE_ALARM_EVENT) + +/** + * @brief Generate a Software interrupt on RTC Alarm associated Exti line. + * @retval None + */ +#define __HAL_RTC_ALARM_EXTI_GENERATE_SWIT() (EXTI->SWIER1 |= RTC_EXTI_LINE_ALARM_EVENT) + +/** + * @} + */ + +/* Include RTC HAL Extended module */ +#include "stm32l4xx_hal_rtc_ex.h" + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup RTC_Exported_Functions + * @{ + */ + +/** @addtogroup RTC_Exported_Functions_Group1 + * @{ + */ +/* Initialization and de-initialization functions ****************************/ +HAL_StatusTypeDef HAL_RTC_Init(RTC_HandleTypeDef *hrtc); +HAL_StatusTypeDef HAL_RTC_DeInit(RTC_HandleTypeDef *hrtc); +void HAL_RTC_MspInit(RTC_HandleTypeDef *hrtc); +void HAL_RTC_MspDeInit(RTC_HandleTypeDef *hrtc); +/** + * @} + */ + +/** @addtogroup RTC_Exported_Functions_Group2 + * @{ + */ +/* RTC Time and Date functions ************************************************/ +HAL_StatusTypeDef HAL_RTC_SetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format); +HAL_StatusTypeDef HAL_RTC_GetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format); +HAL_StatusTypeDef HAL_RTC_SetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format); +HAL_StatusTypeDef HAL_RTC_GetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format); +/** + * @} + */ + +/** @addtogroup RTC_Exported_Functions_Group3 + * @{ + */ +/* RTC Alarm functions ********************************************************/ +HAL_StatusTypeDef HAL_RTC_SetAlarm(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Format); +HAL_StatusTypeDef HAL_RTC_SetAlarm_IT(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Format); +HAL_StatusTypeDef HAL_RTC_DeactivateAlarm(RTC_HandleTypeDef *hrtc, uint32_t Alarm); +HAL_StatusTypeDef HAL_RTC_GetAlarm(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Alarm, uint32_t Format); +void HAL_RTC_AlarmIRQHandler(RTC_HandleTypeDef *hrtc); +HAL_StatusTypeDef HAL_RTC_PollForAlarmAEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout); +void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc); +/** + * @} + */ + +/** @addtogroup RTC_Exported_Functions_Group4 + * @{ + */ +/* Peripheral Control functions ***********************************************/ +HAL_StatusTypeDef HAL_RTC_WaitForSynchro(RTC_HandleTypeDef* hrtc); +/** + * @} + */ + +/** @addtogroup RTC_Exported_Functions_Group5 + * @{ + */ +/* Peripheral State functions *************************************************/ +HAL_RTCStateTypeDef HAL_RTC_GetState(RTC_HandleTypeDef *hrtc); + +/** + * @} + */ + +/** + * @} + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** @defgroup RTC_Private_Constants RTC Private Constants + * @{ + */ +/* Masks Definition */ +#define RTC_TR_RESERVED_MASK 0x007F7F7FU +#define RTC_DR_RESERVED_MASK 0x00FFFF3FU +#define RTC_INIT_MASK 0xFFFFFFFFU +#define RTC_RSF_MASK 0xFFFFFF5FU + +#define RTC_TIMEOUT_VALUE 1000 + +#define RTC_EXTI_LINE_ALARM_EVENT ((uint32_t)0x00040000) /*!< External interrupt line 18 Connected to the RTC Alarm event */ + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup RTC_Private_Macros RTC Private Macros + * @{ + */ + +/** @defgroup RTC_IS_RTC_Definitions RTC Private macros to check input parameters + * @{ + */ + +#define IS_RTC_HOUR_FORMAT(FORMAT) (((FORMAT) == RTC_HOURFORMAT_12) || \ + ((FORMAT) == RTC_HOURFORMAT_24)) + +#define IS_RTC_OUTPUT_POL(POL) (((POL) == RTC_OUTPUT_POLARITY_HIGH) || \ + ((POL) == RTC_OUTPUT_POLARITY_LOW)) + +#define IS_RTC_OUTPUT_TYPE(TYPE) (((TYPE) == RTC_OUTPUT_TYPE_OPENDRAIN) || \ + ((TYPE) == RTC_OUTPUT_TYPE_PUSHPULL)) + +#define IS_RTC_OUTPUT_REMAP(REMAP) (((REMAP) == RTC_OUTPUT_REMAP_NONE) || \ + ((REMAP) == RTC_OUTPUT_REMAP_POS1)) + +#define IS_RTC_HOURFORMAT12(PM) (((PM) == RTC_HOURFORMAT12_AM) || ((PM) == RTC_HOURFORMAT12_PM)) + +#define IS_RTC_DAYLIGHT_SAVING(SAVE) (((SAVE) == RTC_DAYLIGHTSAVING_SUB1H) || \ + ((SAVE) == RTC_DAYLIGHTSAVING_ADD1H) || \ + ((SAVE) == RTC_DAYLIGHTSAVING_NONE)) + +#define IS_RTC_STORE_OPERATION(OPERATION) (((OPERATION) == RTC_STOREOPERATION_RESET) || \ + ((OPERATION) == RTC_STOREOPERATION_SET)) + +#define IS_RTC_FORMAT(FORMAT) (((FORMAT) == RTC_FORMAT_BIN) || ((FORMAT) == RTC_FORMAT_BCD)) + +#define IS_RTC_YEAR(YEAR) ((YEAR) <= (uint32_t)99) + +#define IS_RTC_MONTH(MONTH) (((MONTH) >= (uint32_t)1) && ((MONTH) <= (uint32_t)12)) + +#define IS_RTC_DATE(DATE) (((DATE) >= (uint32_t)1) && ((DATE) <= (uint32_t)31)) + +#define IS_RTC_WEEKDAY(WEEKDAY) (((WEEKDAY) == RTC_WEEKDAY_MONDAY) || \ + ((WEEKDAY) == RTC_WEEKDAY_TUESDAY) || \ + ((WEEKDAY) == RTC_WEEKDAY_WEDNESDAY) || \ + ((WEEKDAY) == RTC_WEEKDAY_THURSDAY) || \ + ((WEEKDAY) == RTC_WEEKDAY_FRIDAY) || \ + ((WEEKDAY) == RTC_WEEKDAY_SATURDAY) || \ + ((WEEKDAY) == RTC_WEEKDAY_SUNDAY)) + +#define IS_RTC_ALARM_DATE_WEEKDAY_DATE(DATE) (((DATE) >(uint32_t) 0) && ((DATE) <= (uint32_t)31)) + +#define IS_RTC_ALARM_DATE_WEEKDAY_WEEKDAY(WEEKDAY) (((WEEKDAY) == RTC_WEEKDAY_MONDAY) || \ + ((WEEKDAY) == RTC_WEEKDAY_TUESDAY) || \ + ((WEEKDAY) == RTC_WEEKDAY_WEDNESDAY) || \ + ((WEEKDAY) == RTC_WEEKDAY_THURSDAY) || \ + ((WEEKDAY) == RTC_WEEKDAY_FRIDAY) || \ + ((WEEKDAY) == RTC_WEEKDAY_SATURDAY) || \ + ((WEEKDAY) == RTC_WEEKDAY_SUNDAY)) + +#define IS_RTC_ALARM_DATE_WEEKDAY_SEL(SEL) (((SEL) == RTC_ALARMDATEWEEKDAYSEL_DATE) || \ + ((SEL) == RTC_ALARMDATEWEEKDAYSEL_WEEKDAY)) + +#define IS_RTC_ALARM_MASK(MASK) (((MASK) & 0x7F7F7F7F) == (uint32_t)RESET) + +#define IS_RTC_ALARM(ALARM) (((ALARM) == RTC_ALARM_A) || ((ALARM) == RTC_ALARM_B)) + +#define IS_RTC_ALARM_SUB_SECOND_VALUE(VALUE) ((VALUE) <= (uint32_t)0x00007FFF) + +#define IS_RTC_ALARM_SUB_SECOND_MASK(MASK) (((MASK) == RTC_ALARMSUBSECONDMASK_ALL) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14_1) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14_2) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14_3) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14_4) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14_5) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14_6) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14_7) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14_8) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14_9) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14_10) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14_11) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14_12) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14_13) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_NONE)) + +#define IS_RTC_ASYNCH_PREDIV(PREDIV) ((PREDIV) <= (uint32_t)0x7F) + +#define IS_RTC_SYNCH_PREDIV(PREDIV) ((PREDIV) <= (uint32_t)0x7FFF) + +#define IS_RTC_HOUR12(HOUR) (((HOUR) > (uint32_t)0) && ((HOUR) <= (uint32_t)12)) + +#define IS_RTC_HOUR24(HOUR) ((HOUR) <= (uint32_t)23) + +#define IS_RTC_MINUTES(MINUTES) ((MINUTES) <= (uint32_t)59) + +#define IS_RTC_SECONDS(SECONDS) ((SECONDS) <= (uint32_t)59) + +/** + * @} + */ + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ +/** @addtogroup RTC_Private_Functions + * @{ + */ + +HAL_StatusTypeDef RTC_EnterInitMode(RTC_HandleTypeDef* hrtc); +uint8_t RTC_ByteToBcd2(uint8_t Value); +uint8_t RTC_Bcd2ToByte(uint8_t Value); + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_HAL_RTC_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rtc_ex.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rtc_ex.h new file mode 100644 index 0000000..8ba89b0 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rtc_ex.h @@ -0,0 +1,1100 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_rtc_ex.h + * @author MCD Application Team + * @brief Header file of RTC HAL Extended module. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_RTC_EX_H +#define __STM32L4xx_HAL_RTC_EX_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup RTCEx + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup RTCEx_Exported_Types RTCEx Exported Types + * @{ + */ +/** + * @brief RTC Tamper structure definition + */ +typedef struct +{ + uint32_t Tamper; /*!< Specifies the Tamper Pin. + This parameter can be a value of @ref RTCEx_Tamper_Pins_Definitions */ + + uint32_t Interrupt; /*!< Specifies the Tamper Interrupt. + This parameter can be a value of @ref RTCEx_Tamper_Interrupt_Definitions */ + + uint32_t Trigger; /*!< Specifies the Tamper Trigger. + This parameter can be a value of @ref RTCEx_Tamper_Trigger_Definitions */ + + uint32_t NoErase; /*!< Specifies the Tamper no erase mode. + This parameter can be a value of @ref RTCEx_Tamper_EraseBackUp_Definitions */ + + uint32_t MaskFlag; /*!< Specifies the Tamper Flag masking. + This parameter can be a value of @ref RTCEx_Tamper_MaskFlag_Definitions */ + + uint32_t Filter; /*!< Specifies the RTC Filter Tamper. + This parameter can be a value of @ref RTCEx_Tamper_Filter_Definitions */ + + uint32_t SamplingFrequency; /*!< Specifies the sampling frequency. + This parameter can be a value of @ref RTCEx_Tamper_Sampling_Frequencies_Definitions */ + + uint32_t PrechargeDuration; /*!< Specifies the Precharge Duration . + This parameter can be a value of @ref RTCEx_Tamper_Pin_Precharge_Duration_Definitions */ + + uint32_t TamperPullUp; /*!< Specifies the Tamper PullUp . + This parameter can be a value of @ref RTCEx_Tamper_Pull_UP_Definitions */ + + uint32_t TimeStampOnTamperDetection; /*!< Specifies the TimeStampOnTamperDetection. + This parameter can be a value of @ref RTCEx_Tamper_TimeStampOnTamperDetection_Definitions */ +}RTC_TamperTypeDef; + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup RTCEx_Exported_Constants RTCEx Exported Constants + * @{ + */ + +/** @defgroup RTCEx_Output_selection_Definitions RTC Output Selection Definitions + * @{ + */ +#define RTC_OUTPUT_DISABLE ((uint32_t)0x00000000) +#define RTC_OUTPUT_ALARMA ((uint32_t)0x00200000) +#define RTC_OUTPUT_ALARMB ((uint32_t)0x00400000) +#define RTC_OUTPUT_WAKEUP ((uint32_t)0x00600000) +/** + * @} + */ + +/** @defgroup RTCEx_Backup_Registers_Definitions RTC Backup Registers Definitions + * @{ + */ +#define RTC_BKP_DR0 ((uint32_t)0x00000000) +#define RTC_BKP_DR1 ((uint32_t)0x00000001) +#define RTC_BKP_DR2 ((uint32_t)0x00000002) +#define RTC_BKP_DR3 ((uint32_t)0x00000003) +#define RTC_BKP_DR4 ((uint32_t)0x00000004) +#define RTC_BKP_DR5 ((uint32_t)0x00000005) +#define RTC_BKP_DR6 ((uint32_t)0x00000006) +#define RTC_BKP_DR7 ((uint32_t)0x00000007) +#define RTC_BKP_DR8 ((uint32_t)0x00000008) +#define RTC_BKP_DR9 ((uint32_t)0x00000009) +#define RTC_BKP_DR10 ((uint32_t)0x0000000A) +#define RTC_BKP_DR11 ((uint32_t)0x0000000B) +#define RTC_BKP_DR12 ((uint32_t)0x0000000C) +#define RTC_BKP_DR13 ((uint32_t)0x0000000D) +#define RTC_BKP_DR14 ((uint32_t)0x0000000E) +#define RTC_BKP_DR15 ((uint32_t)0x0000000F) +#define RTC_BKP_DR16 ((uint32_t)0x00000010) +#define RTC_BKP_DR17 ((uint32_t)0x00000011) +#define RTC_BKP_DR18 ((uint32_t)0x00000012) +#define RTC_BKP_DR19 ((uint32_t)0x00000013) +#define RTC_BKP_DR20 ((uint32_t)0x00000014) +#define RTC_BKP_DR21 ((uint32_t)0x00000015) +#define RTC_BKP_DR22 ((uint32_t)0x00000016) +#define RTC_BKP_DR23 ((uint32_t)0x00000017) +#define RTC_BKP_DR24 ((uint32_t)0x00000018) +#define RTC_BKP_DR25 ((uint32_t)0x00000019) +#define RTC_BKP_DR26 ((uint32_t)0x0000001A) +#define RTC_BKP_DR27 ((uint32_t)0x0000001B) +#define RTC_BKP_DR28 ((uint32_t)0x0000001C) +#define RTC_BKP_DR29 ((uint32_t)0x0000001D) +#define RTC_BKP_DR30 ((uint32_t)0x0000001E) +#define RTC_BKP_DR31 ((uint32_t)0x0000001F) +/** + * @} + */ + +/** @defgroup RTCEx_TimeStamp_Edges_definitions RTC TimeStamp Edges Definitions + * @{ + */ +#define RTC_TIMESTAMPEDGE_RISING ((uint32_t)0x00000000) +#define RTC_TIMESTAMPEDGE_FALLING ((uint32_t)0x00000008) +/** + * @} + */ + +/** @defgroup RTCEx_TimeStamp_Pin_Selection RTC TimeStamp Pins Selection + * @{ + */ +#define RTC_TIMESTAMPPIN_DEFAULT ((uint32_t)0x00000000) +/** + * @} + */ + +/** @defgroup RTCEx_Tamper_Pins_Definitions RTC Tamper Pins Definitions + * @{ + */ +#if defined(RTC_TAMPER1_SUPPORT) +#define RTC_TAMPER_1 RTC_TAMPCR_TAMP1E +#endif /* RTC_TAMPER1_SUPPORT */ +#define RTC_TAMPER_2 RTC_TAMPCR_TAMP2E +#if defined(RTC_TAMPER3_SUPPORT) +#define RTC_TAMPER_3 RTC_TAMPCR_TAMP3E +#endif /* RTC_TAMPER3_SUPPORT */ +/** + * @} + */ + +/** @defgroup RTCEx_Tamper_Interrupt_Definitions RTC Tamper Interrupts Definitions + * @{ + */ +#if defined(RTC_TAMPER1_SUPPORT) +#define RTC_TAMPER1_INTERRUPT RTC_TAMPCR_TAMP1IE +#endif /* RTC_TAMPER1_SUPPORT */ +#define RTC_TAMPER2_INTERRUPT RTC_TAMPCR_TAMP2IE +#if defined(RTC_TAMPER3_SUPPORT) +#define RTC_TAMPER3_INTERRUPT RTC_TAMPCR_TAMP3IE +#endif /* RTC_TAMPER3_SUPPORT */ +#define RTC_ALL_TAMPER_INTERRUPT RTC_TAMPCR_TAMPIE +/** + * @} + */ + +/** @defgroup RTCEx_Tamper_Trigger_Definitions RTC Tamper Triggers Definitions + * @{ + */ +#define RTC_TAMPERTRIGGER_RISINGEDGE ((uint32_t)0x00000000) +#define RTC_TAMPERTRIGGER_FALLINGEDGE ((uint32_t)0x00000002) +#define RTC_TAMPERTRIGGER_LOWLEVEL RTC_TAMPERTRIGGER_RISINGEDGE +#define RTC_TAMPERTRIGGER_HIGHLEVEL RTC_TAMPERTRIGGER_FALLINGEDGE +/** + * @} + */ + +/** @defgroup RTCEx_Tamper_EraseBackUp_Definitions RTC Tamper EraseBackUp Definitions +* @{ +*/ +#define RTC_TAMPER_ERASE_BACKUP_ENABLE ((uint32_t)0x00000000) +#define RTC_TAMPER_ERASE_BACKUP_DISABLE ((uint32_t)0x00020000) +/** + * @} + */ + +/** @defgroup RTCEx_Tamper_MaskFlag_Definitions RTC Tamper Mask Flag Definitions +* @{ +*/ +#define RTC_TAMPERMASK_FLAG_DISABLE ((uint32_t)0x00000000) +#define RTC_TAMPERMASK_FLAG_ENABLE ((uint32_t)0x00040000) +/** + * @} + */ + +/** @defgroup RTCEx_Tamper_Filter_Definitions RTC Tamper Filter Definitions + * @{ + */ +#define RTC_TAMPERFILTER_DISABLE ((uint32_t)0x00000000) /*!< Tamper filter is disabled */ + +#define RTC_TAMPERFILTER_2SAMPLE ((uint32_t)0x00000800) /*!< Tamper is activated after 2 + consecutive samples at the active level */ +#define RTC_TAMPERFILTER_4SAMPLE ((uint32_t)0x00001000) /*!< Tamper is activated after 4 + consecutive samples at the active level */ +#define RTC_TAMPERFILTER_8SAMPLE ((uint32_t)0x00001800) /*!< Tamper is activated after 8 + consecutive samples at the active level. */ +/** + * @} + */ + +/** @defgroup RTCEx_Tamper_Sampling_Frequencies_Definitions RTC Tamper Sampling Frequencies Definitions + * @{ + */ +#define RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV32768 ((uint32_t)0x00000000) /*!< Each of the tamper inputs are sampled + with a frequency = RTCCLK / 32768 */ +#define RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV16384 ((uint32_t)0x00000100) /*!< Each of the tamper inputs are sampled + with a frequency = RTCCLK / 16384 */ +#define RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV8192 ((uint32_t)0x00000200) /*!< Each of the tamper inputs are sampled + with a frequency = RTCCLK / 8192 */ +#define RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV4096 ((uint32_t)0x00000300) /*!< Each of the tamper inputs are sampled + with a frequency = RTCCLK / 4096 */ +#define RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV2048 ((uint32_t)0x00000400) /*!< Each of the tamper inputs are sampled + with a frequency = RTCCLK / 2048 */ +#define RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV1024 ((uint32_t)0x00000500) /*!< Each of the tamper inputs are sampled + with a frequency = RTCCLK / 1024 */ +#define RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV512 ((uint32_t)0x00000600) /*!< Each of the tamper inputs are sampled + with a frequency = RTCCLK / 512 */ +#define RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV256 ((uint32_t)0x00000700) /*!< Each of the tamper inputs are sampled + with a frequency = RTCCLK / 256 */ +/** + * @} + */ + +/** @defgroup RTCEx_Tamper_Pin_Precharge_Duration_Definitions RTC Tamper Pin Precharge Duration Definitions + * @{ + */ +#define RTC_TAMPERPRECHARGEDURATION_1RTCCLK ((uint32_t)0x00000000) /*!< Tamper pins are pre-charged before + sampling during 1 RTCCLK cycle */ +#define RTC_TAMPERPRECHARGEDURATION_2RTCCLK ((uint32_t)0x00002000) /*!< Tamper pins are pre-charged before + sampling during 2 RTCCLK cycles */ +#define RTC_TAMPERPRECHARGEDURATION_4RTCCLK ((uint32_t)0x00004000) /*!< Tamper pins are pre-charged before + sampling during 4 RTCCLK cycles */ +#define RTC_TAMPERPRECHARGEDURATION_8RTCCLK ((uint32_t)0x00006000) /*!< Tamper pins are pre-charged before + sampling during 8 RTCCLK cycles */ +/** + * @} + */ + +/** @defgroup RTCEx_Tamper_TimeStampOnTamperDetection_Definitions RTC Tamper TimeStamp On Tamper Detection Definitions + * @{ + */ +#define RTC_TIMESTAMPONTAMPERDETECTION_ENABLE ((uint32_t)RTC_TAMPCR_TAMPTS) /*!< TimeStamp on Tamper Detection event saved */ +#define RTC_TIMESTAMPONTAMPERDETECTION_DISABLE ((uint32_t)0x00000000) /*!< TimeStamp on Tamper Detection event is not saved */ +/** + * @} + */ + +/** @defgroup RTCEx_Tamper_Pull_UP_Definitions RTC Tamper Pull Up Definitions + * @{ + */ +#define RTC_TAMPER_PULLUP_ENABLE ((uint32_t)0x00000000) /*!< TimeStamp on Tamper Detection event saved */ +#define RTC_TAMPER_PULLUP_DISABLE ((uint32_t)RTC_TAMPCR_TAMPPUDIS) /*!< TimeStamp on Tamper Detection event is not saved */ +/** + * @} + */ + +/** @defgroup RTCEx_Wakeup_Timer_Definitions RTC Wakeup Timer Definitions + * @{ + */ +#define RTC_WAKEUPCLOCK_RTCCLK_DIV16 ((uint32_t)0x00000000) +#define RTC_WAKEUPCLOCK_RTCCLK_DIV8 ((uint32_t)0x00000001) +#define RTC_WAKEUPCLOCK_RTCCLK_DIV4 ((uint32_t)0x00000002) +#define RTC_WAKEUPCLOCK_RTCCLK_DIV2 ((uint32_t)0x00000003) +#define RTC_WAKEUPCLOCK_CK_SPRE_16BITS ((uint32_t)0x00000004) +#define RTC_WAKEUPCLOCK_CK_SPRE_17BITS ((uint32_t)0x00000006) +/** + * @} + */ + +/** @defgroup RTCEx_Smooth_calib_period_Definitions RTC Smooth Calib Period Definitions + * @{ + */ +#define RTC_SMOOTHCALIB_PERIOD_32SEC ((uint32_t)0x00000000) /*!< If RTCCLK = 32768 Hz, Smooth calibration + period is 32s, else 2exp20 RTCCLK seconds */ +#define RTC_SMOOTHCALIB_PERIOD_16SEC ((uint32_t)0x00002000) /*!< If RTCCLK = 32768 Hz, Smooth calibration + period is 16s, else 2exp19 RTCCLK seconds */ +#define RTC_SMOOTHCALIB_PERIOD_8SEC ((uint32_t)0x00004000) /*!< If RTCCLK = 32768 Hz, Smooth calibration + period is 8s, else 2exp18 RTCCLK seconds */ +/** + * @} + */ + +/** @defgroup RTCEx_Smooth_calib_Plus_pulses_Definitions RTC Smooth Calib Plus Pulses Definitions + * @{ + */ +#define RTC_SMOOTHCALIB_PLUSPULSES_SET ((uint32_t)0x00008000) /*!< The number of RTCCLK pulses added + during a X -second window = Y - CALM[8:0] + with Y = 512, 256, 128 when X = 32, 16, 8 */ +#define RTC_SMOOTHCALIB_PLUSPULSES_RESET ((uint32_t)0x00000000) /*!< The number of RTCCLK pulses subbstited + during a 32-second window = CALM[8:0] */ +/** + * @} + */ + +/** @defgroup RTCEx_Calib_Output_selection_Definitions RTC Calib Output Selection Definitions + * @{ + */ +#define RTC_CALIBOUTPUT_512HZ ((uint32_t)0x00000000) +#define RTC_CALIBOUTPUT_1HZ ((uint32_t)0x00080000) +/** + * @} + */ + +/** @defgroup RTCEx_Add_1_Second_Parameter_Definitions RTC Add 1 Second Parameter Definitions + * @{ + */ +#define RTC_SHIFTADD1S_RESET ((uint32_t)0x00000000) +#define RTC_SHIFTADD1S_SET ((uint32_t)0x80000000) +/** + * @} + */ + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ +/** @defgroup RTCEx_Exported_Macros RTCEx Exported Macros + * @{ + */ + +/** + * @brief Enable the RTC WakeUp Timer peripheral. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR |= (RTC_CR_WUTE)) + +/** + * @brief Disable the RTC WakeUp Timer peripheral. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR &= ~(RTC_CR_WUTE)) + +/** + * @brief Enable the RTC WakeUpTimer interrupt. + * @param __HANDLE__: specifies the RTC handle. + * @param __INTERRUPT__: specifies the RTC WakeUpTimer interrupt sources to be enabled. + * This parameter can be: + * @arg RTC_IT_WUT: WakeUpTimer interrupt + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CR |= (__INTERRUPT__)) + +/** + * @brief Disable the RTC WakeUpTimer interrupt. + * @param __HANDLE__: specifies the RTC handle. + * @param __INTERRUPT__: specifies the RTC WakeUpTimer interrupt sources to be disabled. + * This parameter can be: + * @arg RTC_IT_WUT: WakeUpTimer interrupt + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CR &= ~(__INTERRUPT__)) + +/** + * @brief Check whether the specified RTC WakeUpTimer interrupt has occurred or not. + * @param __HANDLE__: specifies the RTC handle. + * @param __INTERRUPT__: specifies the RTC WakeUpTimer interrupt sources to check. + * This parameter can be: + * @arg RTC_IT_WUT: WakeUpTimer interrupt + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_GET_IT(__HANDLE__, __INTERRUPT__) (((((__HANDLE__)->Instance->ISR) & ((__INTERRUPT__)>> 4)) != RESET) ? SET : RESET) + +/** + * @brief Check whether the specified RTC Wake Up timer interrupt is enabled or not. + * @param __HANDLE__: specifies the RTC handle. + * @param __INTERRUPT__: specifies the RTC Wake Up timer interrupt sources to check. + * This parameter can be: + * @arg RTC_IT_WUT: WakeUpTimer interrupt + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) (((((__HANDLE__)->Instance->CR) & (__INTERRUPT__)) != RESET) ? SET : RESET) + +/** + * @brief Get the selected RTC WakeUpTimer's flag status. + * @param __HANDLE__: specifies the RTC handle. + * @param __FLAG__: specifies the RTC WakeUpTimer Flag is pending or not. + * This parameter can be: + * @arg RTC_FLAG_WUTF + * @arg RTC_FLAG_WUTWF + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_GET_FLAG(__HANDLE__, __FLAG__) (((((__HANDLE__)->Instance->ISR) & (__FLAG__)) != RESET) ? SET : RESET) + +/** + * @brief Clear the RTC Wake Up timer's pending flags. + * @param __HANDLE__: specifies the RTC handle. + * @param __FLAG__: specifies the RTC WakeUpTimer Flag to clear. + * This parameter can be: + * @arg RTC_FLAG_WUTF + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->ISR) = (~((__FLAG__) | RTC_ISR_INIT)|((__HANDLE__)->Instance->ISR & RTC_ISR_INIT)) + +#if defined(RTC_TAMPER1_SUPPORT) +/** + * @brief Enable the RTC Tamper1 input detection. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_TAMPER1_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->TAMPCR |= (RTC_TAMPCR_TAMP1E)) + +/** + * @brief Disable the RTC Tamper1 input detection. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_TAMPER1_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->TAMPCR &= ~(RTC_TAMPCR_TAMP1E)) +#endif /* RTC_TAMPER1_SUPPORT */ + +/** + * @brief Enable the RTC Tamper2 input detection. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_TAMPER2_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->TAMPCR |= (RTC_TAMPCR_TAMP2E)) + +/** + * @brief Disable the RTC Tamper2 input detection. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_TAMPER2_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->TAMPCR &= ~(RTC_TAMPCR_TAMP2E)) + +#if defined(RTC_TAMPER3_SUPPORT) +/** + * @brief Enable the RTC Tamper3 input detection. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_TAMPER3_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->TAMPCR |= (RTC_TAMPCR_TAMP3E)) + +/** + * @brief Disable the RTC Tamper3 input detection. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_TAMPER3_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->TAMPCR &= ~(RTC_TAMPCR_TAMP3E)) +#endif /* RTC_TAMPER3_SUPPORT */ + +/** + * @brief Enable the RTC Tamper interrupt. + * @param __HANDLE__: specifies the RTC handle. + * @param __INTERRUPT__: specifies the RTC Tamper interrupt sources to be enabled. + * This parameter can be any combination of the following values: + * @arg RTC_IT_TAMP: All tampers interrupts + * @arg RTC_IT_TAMP1: Tamper1 interrupt + * @arg RTC_IT_TAMP2: Tamper2 interrupt + * @arg RTC_IT_TAMP3: Tamper3 interrupt + * @retval None + */ +#define __HAL_RTC_TAMPER_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->TAMPCR |= (__INTERRUPT__)) + +/** + * @brief Disable the RTC Tamper interrupt. + * @param __HANDLE__: specifies the RTC handle. + * @param __INTERRUPT__: specifies the RTC Tamper interrupt sources to be disabled. + * This parameter can be any combination of the following values: + * @arg RTC_IT_TAMP: All tampers interrupts + * @arg RTC_IT_TAMP1: Tamper1 interrupt + * @arg RTC_IT_TAMP2: Tamper2 interrupt + * @arg RTC_IT_TAMP3: Tamper3 interrupt + * @retval None + */ +#define __HAL_RTC_TAMPER_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->TAMPCR &= ~(__INTERRUPT__)) + +/** + * @brief Check whether the specified RTC Tamper interrupt has occurred or not. + * @param __HANDLE__: specifies the RTC handle. + * @param __INTERRUPT__: specifies the RTC Tamper interrupt to check. + * This parameter can be: + * @arg RTC_IT_TAMP1: Tamper1 interrupt + * @arg RTC_IT_TAMP2: Tamper2 interrupt + * @arg RTC_IT_TAMP3: Tamper3 interrupt + * @retval None + */ +#if defined(RTC_TAMPER1_SUPPORT) && defined(RTC_TAMPER3_SUPPORT) +#define __HAL_RTC_TAMPER_GET_IT(__HANDLE__, __INTERRUPT__) (((__INTERRUPT__) == RTC_IT_TAMP1) ? (((((__HANDLE__)->Instance->ISR) & ((__INTERRUPT__)>> 3)) != RESET) ? SET : RESET) : \ + ((__INTERRUPT__) == RTC_IT_TAMP2) ? (((((__HANDLE__)->Instance->ISR) & ((__INTERRUPT__)>> 5)) != RESET) ? SET : RESET) : \ + (((((__HANDLE__)->Instance->ISR) & ((__INTERRUPT__)>> 7)) != RESET) ? SET : RESET)) +#else +#define __HAL_RTC_TAMPER_GET_IT(__HANDLE__, __INTERRUPT__) (((((__HANDLE__)->Instance->ISR) & ((__INTERRUPT__)>> 5)) != RESET) ? SET : RESET) +#endif /* RTC_TAMPER1_SUPPORT && RTC_TAMPER3_SUPPORT */ + +/** + * @brief Check whether the specified RTC Tamper interrupt is enabled or not. + * @param __HANDLE__: specifies the RTC handle. + * @param __INTERRUPT__: specifies the RTC Tamper interrupt source to check. + * This parameter can be: + * @arg RTC_IT_TAMP: All tampers interrupts + * @arg RTC_IT_TAMP1: Tamper1 interrupt + * @arg RTC_IT_TAMP2: Tamper2 interrupt + * @arg RTC_IT_TAMP3: Tamper3 interrupt + * @retval None + */ +#define __HAL_RTC_TAMPER_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) (((((__HANDLE__)->Instance->TAMPCR) & (__INTERRUPT__)) != RESET) ? SET : RESET) + +/** + * @brief Get the selected RTC Tamper's flag status. + * @param __HANDLE__: specifies the RTC handle. + * @param __FLAG__: specifies the RTC Tamper Flag is pending or not. + * This parameter can be: + * @arg RTC_FLAG_TAMP1F: Tamper1 flag + * @arg RTC_FLAG_TAMP2F: Tamper2 flag + * @arg RTC_FLAG_TAMP3F: Tamper3 flag + * @retval None + */ +#define __HAL_RTC_TAMPER_GET_FLAG(__HANDLE__, __FLAG__) (((((__HANDLE__)->Instance->ISR) & (__FLAG__)) != RESET) ? SET : RESET) + +/** + * @brief Clear the RTC Tamper's pending flags. + * @param __HANDLE__: specifies the RTC handle. + * @param __FLAG__: specifies the RTC Tamper Flag sources to clear. + * This parameter can be: + * @arg RTC_FLAG_TAMP1F: Tamper1 flag + * @arg RTC_FLAG_TAMP2F: Tamper2 flag + * @arg RTC_FLAG_TAMP3F: Tamper3 flag + * @retval None + */ +#define __HAL_RTC_TAMPER_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->ISR) = (~((__FLAG__) | RTC_ISR_INIT)|((__HANDLE__)->Instance->ISR & RTC_ISR_INIT)) + +/** + * @brief Enable the RTC TimeStamp peripheral. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_TIMESTAMP_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR |= (RTC_CR_TSE)) + +/** + * @brief Disable the RTC TimeStamp peripheral. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_TIMESTAMP_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR &= ~(RTC_CR_TSE)) + +/** + * @brief Enable the RTC TimeStamp interrupt. + * @param __HANDLE__: specifies the RTC handle. + * @param __INTERRUPT__: specifies the RTC TimeStamp interrupt source to be enabled. + * This parameter can be: + * @arg RTC_IT_TS: TimeStamp interrupt + * @retval None + */ +#define __HAL_RTC_TIMESTAMP_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CR |= (__INTERRUPT__)) + +/** + * @brief Disable the RTC TimeStamp interrupt. + * @param __HANDLE__: specifies the RTC handle. + * @param __INTERRUPT__: specifies the RTC TimeStamp interrupt source to be disabled. + * This parameter can be: + * @arg RTC_IT_TS: TimeStamp interrupt + * @retval None + */ +#define __HAL_RTC_TIMESTAMP_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CR &= ~(__INTERRUPT__)) + +/** + * @brief Check whether the specified RTC TimeStamp interrupt has occurred or not. + * @param __HANDLE__: specifies the RTC handle. + * @param __INTERRUPT__: specifies the RTC TimeStamp interrupt source to check. + * This parameter can be: + * @arg RTC_IT_TS: TimeStamp interrupt + * @retval None + */ +#define __HAL_RTC_TIMESTAMP_GET_IT(__HANDLE__, __INTERRUPT__) (((((__HANDLE__)->Instance->ISR) & ((__INTERRUPT__)>> 4)) != RESET) ? SET : RESET) + +/** + * @brief Check whether the specified RTC Time Stamp interrupt is enabled or not. + * @param __HANDLE__: specifies the RTC handle. + * @param __INTERRUPT__: specifies the RTC Time Stamp interrupt source to check. + * This parameter can be: + * @arg RTC_IT_TS: TimeStamp interrupt + * @retval None + */ +#define __HAL_RTC_TIMESTAMP_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) (((((__HANDLE__)->Instance->CR) & (__INTERRUPT__)) != RESET) ? SET : RESET) + +/** + * @brief Get the selected RTC TimeStamp's flag status. + * @param __HANDLE__: specifies the RTC handle. + * @param __FLAG__: specifies the RTC TimeStamp Flag is pending or not. + * This parameter can be: + * @arg RTC_FLAG_TSF + * @arg RTC_FLAG_TSOVF + * @retval None + */ +#define __HAL_RTC_TIMESTAMP_GET_FLAG(__HANDLE__, __FLAG__) (((((__HANDLE__)->Instance->ISR) & (__FLAG__)) != RESET) ? SET : RESET) + +/** + * @brief Clear the RTC Time Stamp's pending flags. + * @param __HANDLE__: specifies the RTC handle. + * @param __FLAG__: specifies the RTC Alarm Flag sources to clear. + * This parameter can be: + * @arg RTC_FLAG_TSF + * @arg RTC_FLAG_TSOVF + * @retval None + */ +#define __HAL_RTC_TIMESTAMP_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->ISR) = (~((__FLAG__) | RTC_ISR_INIT)|((__HANDLE__)->Instance->ISR & RTC_ISR_INIT)) + +/** + * @brief Enable the RTC internal TimeStamp peripheral. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_INTERNAL_TIMESTAMP_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR |= (RTC_CR_ITSE)) + +/** + * @brief Disable the RTC internal TimeStamp peripheral. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_INTERNAL_TIMESTAMP_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR &= ~(RTC_CR_ITSE)) + +/** + * @brief Get the selected RTC Internal Time Stamp's flag status. + * @param __HANDLE__: specifies the RTC handle. + * @param __FLAG__: specifies the RTC Internal Time Stamp Flag is pending or not. + * This parameter can be: + * @arg RTC_FLAG_ITSF + * @retval None + */ +#define __HAL_RTC_INTERNAL_TIMESTAMP_GET_FLAG(__HANDLE__, __FLAG__) (((((__HANDLE__)->Instance->ISR) & (__FLAG__)) != RESET) ? SET : RESET) + +/** + * @brief Clear the RTC Internal Time Stamp's pending flags. + * @param __HANDLE__: specifies the RTC handle. + * @param __FLAG__: specifies the RTC Internal Time Stamp Flag source to clear. + * This parameter can be: + * @arg RTC_FLAG_ITSF + * @retval None + */ +#define __HAL_RTC_INTERNAL_TIMESTAMP_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->ISR) = (~((__FLAG__) | RTC_ISR_INIT)|((__HANDLE__)->Instance->ISR & RTC_ISR_INIT)) + +/** + * @brief Enable the RTC calibration output. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_CALIBRATION_OUTPUT_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR |= (RTC_CR_COE)) + +/** + * @brief Disable the calibration output. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_CALIBRATION_OUTPUT_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR &= ~(RTC_CR_COE)) + +/** + * @brief Enable the clock reference detection. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_CLOCKREF_DETECTION_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR |= (RTC_CR_REFCKON)) + +/** + * @brief Disable the clock reference detection. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_CLOCKREF_DETECTION_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR &= ~(RTC_CR_REFCKON)) + +/** + * @brief Get the selected RTC shift operation's flag status. + * @param __HANDLE__: specifies the RTC handle. + * @param __FLAG__: specifies the RTC shift operation Flag is pending or not. + * This parameter can be: + * @arg RTC_FLAG_SHPF + * @retval None + */ +#define __HAL_RTC_SHIFT_GET_FLAG(__HANDLE__, __FLAG__) (((((__HANDLE__)->Instance->ISR) & (__FLAG__)) != RESET) ? SET : RESET) + +/** + * @brief Enable interrupt on the RTC WakeUp Timer associated Exti line. + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_IT() (EXTI->IMR1 |= RTC_EXTI_LINE_WAKEUPTIMER_EVENT) + +/** + * @brief Disable interrupt on the RTC WakeUp Timer associated Exti line. + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_EXTI_DISABLE_IT() (EXTI->IMR1 &= ~(RTC_EXTI_LINE_WAKEUPTIMER_EVENT)) + +/** + * @brief Enable event on the RTC WakeUp Timer associated Exti line. + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_EVENT() (EXTI->EMR1 |= RTC_EXTI_LINE_WAKEUPTIMER_EVENT) + +/** + * @brief Disable event on the RTC WakeUp Timer associated Exti line. + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_EXTI_DISABLE_EVENT() (EXTI->EMR1 &= ~(RTC_EXTI_LINE_WAKEUPTIMER_EVENT)) + +/** + * @brief Enable falling edge trigger on the RTC WakeUp Timer associated Exti line. + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_FALLING_EDGE() (EXTI->FTSR1 |= RTC_EXTI_LINE_WAKEUPTIMER_EVENT) + +/** + * @brief Disable falling edge trigger on the RTC WakeUp Timer associated Exti line. + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_EXTI_DISABLE_FALLING_EDGE() (EXTI->FTSR1 &= ~(RTC_EXTI_LINE_WAKEUPTIMER_EVENT)) + +/** + * @brief Enable rising edge trigger on the RTC WakeUp Timer associated Exti line. + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_RISING_EDGE() (EXTI->RTSR1 |= RTC_EXTI_LINE_WAKEUPTIMER_EVENT) + +/** + * @brief Disable rising edge trigger on the RTC WakeUp Timer associated Exti line. + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_EXTI_DISABLE_RISING_EDGE() (EXTI->RTSR1 &= ~(RTC_EXTI_LINE_WAKEUPTIMER_EVENT)) + +/** + * @brief Enable rising & falling edge trigger on the RTC WakeUp Timer associated Exti line. + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_RISING_FALLING_EDGE() do { \ + __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_RISING_EDGE(); \ + __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_FALLING_EDGE(); \ + } while(0) + +/** + * @brief Disable rising & falling edge trigger on the RTC WakeUp Timer associated Exti line. + * This parameter can be: + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_EXTI_DISABLE_RISING_FALLING_EDGE() do { \ + __HAL_RTC_WAKEUPTIMER_EXTI_DISABLE_RISING_EDGE(); \ + __HAL_RTC_WAKEUPTIMER_EXTI_DISABLE_FALLING_EDGE(); \ + } while(0) + +/** + * @brief Check whether the RTC WakeUp Timer associated Exti line interrupt flag is set or not. + * @retval Line Status. + */ +#define __HAL_RTC_WAKEUPTIMER_EXTI_GET_FLAG() (EXTI->PR1 & RTC_EXTI_LINE_WAKEUPTIMER_EVENT) + +/** + * @brief Clear the RTC WakeUp Timer associated Exti line flag. + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG() (EXTI->PR1 = RTC_EXTI_LINE_WAKEUPTIMER_EVENT) + +/** + * @brief Generate a Software interrupt on the RTC WakeUp Timer associated Exti line. + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_EXTI_GENERATE_SWIT() (EXTI->SWIER1 |= RTC_EXTI_LINE_WAKEUPTIMER_EVENT) + +/** + * @brief Enable interrupt on the RTC Tamper and Timestamp associated Exti line. + * @retval None + */ +#define __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_IT() (EXTI->IMR1 |= RTC_EXTI_LINE_TAMPER_TIMESTAMP_EVENT) + +/** + * @brief Disable interrupt on the RTC Tamper and Timestamp associated Exti line. + * @retval None + */ +#define __HAL_RTC_TAMPER_TIMESTAMP_EXTI_DISABLE_IT() (EXTI->IMR1 &= ~(RTC_EXTI_LINE_TAMPER_TIMESTAMP_EVENT)) + +/** + * @brief Enable event on the RTC Tamper and Timestamp associated Exti line. + * @retval None + */ +#define __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_EVENT() (EXTI->EMR1 |= RTC_EXTI_LINE_TAMPER_TIMESTAMP_EVENT) + +/** + * @brief Disable event on the RTC Tamper and Timestamp associated Exti line. + * @retval None + */ +#define __HAL_RTC_TAMPER_TIMESTAMP_EXTI_DISABLE_EVENT() (EXTI->EMR1 &= ~(RTC_EXTI_LINE_TAMPER_TIMESTAMP_EVENT)) + +/** + * @brief Enable falling edge trigger on the RTC Tamper and Timestamp associated Exti line. + * @retval None + */ +#define __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_FALLING_EDGE() (EXTI->FTSR1 |= RTC_EXTI_LINE_TAMPER_TIMESTAMP_EVENT) + +/** + * @brief Disable falling edge trigger on the RTC Tamper and Timestamp associated Exti line. + * @retval None + */ +#define __HAL_RTC_TAMPER_TIMESTAMP_EXTI_DISABLE_FALLING_EDGE() (EXTI->FTSR1 &= ~(RTC_EXTI_LINE_TAMPER_TIMESTAMP_EVENT)) + +/** + * @brief Enable rising edge trigger on the RTC Tamper and Timestamp associated Exti line. + * @retval None + */ +#define __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_RISING_EDGE() (EXTI->RTSR1 |= RTC_EXTI_LINE_TAMPER_TIMESTAMP_EVENT) + +/** + * @brief Disable rising edge trigger on the RTC Tamper and Timestamp associated Exti line. + * @retval None + */ +#define __HAL_RTC_TAMPER_TIMESTAMP_EXTI_DISABLE_RISING_EDGE() (EXTI->RTSR1 &= ~(RTC_EXTI_LINE_TAMPER_TIMESTAMP_EVENT)) + +/** + * @brief Enable rising & falling edge trigger on the RTC Tamper and Timestamp associated Exti line. + * @retval None + */ +#define __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_RISING_FALLING_EDGE() do { \ + __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_RISING_EDGE(); \ + __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_FALLING_EDGE(); \ + } while(0) + +/** + * @brief Disable rising & falling edge trigger on the RTC Tamper and Timestamp associated Exti line. + * This parameter can be: + * @retval None + */ +#define __HAL_RTC_TAMPER_TIMESTAMP_EXTI_DISABLE_RISING_FALLING_EDGE() do { \ + __HAL_RTC_TAMPER_TIMESTAMP_EXTI_DISABLE_RISING_EDGE(); \ + __HAL_RTC_TAMPER_TIMESTAMP_EXTI_DISABLE_FALLING_EDGE(); \ + } while(0) + +/** + * @brief Check whether the RTC Tamper and Timestamp associated Exti line interrupt flag is set or not. + * @retval Line Status. + */ +#define __HAL_RTC_TAMPER_TIMESTAMP_EXTI_GET_FLAG() (EXTI->PR1 & RTC_EXTI_LINE_TAMPER_TIMESTAMP_EVENT) + +/** + * @brief Clear the RTC Tamper and Timestamp associated Exti line flag. + * @retval None + */ +#define __HAL_RTC_TAMPER_TIMESTAMP_EXTI_CLEAR_FLAG() (EXTI->PR1 = RTC_EXTI_LINE_TAMPER_TIMESTAMP_EVENT) + +/** + * @brief Generate a Software interrupt on the RTC Tamper and Timestamp associated Exti line + * @retval None + */ +#define __HAL_RTC_TAMPER_TIMESTAMP_EXTI_GENERATE_SWIT() (EXTI->SWIER1 |= RTC_EXTI_LINE_TAMPER_TIMESTAMP_EVENT) + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup RTCEx_Exported_Functions + * @{ + */ + +/* RTC TimeStamp and Tamper functions *****************************************/ +/** @addtogroup RTCEx_Exported_Functions_Group1 + * @{ + */ +HAL_StatusTypeDef HAL_RTCEx_SetTimeStamp(RTC_HandleTypeDef *hrtc, uint32_t TimeStampEdge, uint32_t RTC_TimeStampPin); +HAL_StatusTypeDef HAL_RTCEx_SetTimeStamp_IT(RTC_HandleTypeDef *hrtc, uint32_t TimeStampEdge, uint32_t RTC_TimeStampPin); +HAL_StatusTypeDef HAL_RTCEx_DeactivateTimeStamp(RTC_HandleTypeDef *hrtc); +HAL_StatusTypeDef HAL_RTCEx_SetInternalTimeStamp(RTC_HandleTypeDef *hrtc); +HAL_StatusTypeDef HAL_RTCEx_DeactivateInternalTimeStamp(RTC_HandleTypeDef *hrtc); +HAL_StatusTypeDef HAL_RTCEx_GetTimeStamp(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTimeStamp, RTC_DateTypeDef *sTimeStampDate, uint32_t Format); + +HAL_StatusTypeDef HAL_RTCEx_SetTamper(RTC_HandleTypeDef *hrtc, RTC_TamperTypeDef* sTamper); +HAL_StatusTypeDef HAL_RTCEx_SetTamper_IT(RTC_HandleTypeDef *hrtc, RTC_TamperTypeDef* sTamper); +HAL_StatusTypeDef HAL_RTCEx_DeactivateTamper(RTC_HandleTypeDef *hrtc, uint32_t Tamper); +void HAL_RTCEx_TamperTimeStampIRQHandler(RTC_HandleTypeDef *hrtc); + +#if defined(RTC_TAMPER1_SUPPORT) +void HAL_RTCEx_Tamper1EventCallback(RTC_HandleTypeDef *hrtc); +#endif /* RTC_TAMPER1_SUPPORT */ +void HAL_RTCEx_Tamper2EventCallback(RTC_HandleTypeDef *hrtc); +#if defined(RTC_TAMPER3_SUPPORT) +void HAL_RTCEx_Tamper3EventCallback(RTC_HandleTypeDef *hrtc); +#endif /* RTC_TAMPER3_SUPPORT */ +void HAL_RTCEx_TimeStampEventCallback(RTC_HandleTypeDef *hrtc); +HAL_StatusTypeDef HAL_RTCEx_PollForTimeStampEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout); +#if defined(RTC_TAMPER1_SUPPORT) +HAL_StatusTypeDef HAL_RTCEx_PollForTamper1Event(RTC_HandleTypeDef *hrtc, uint32_t Timeout); +#endif /* RTC_TAMPER1_SUPPORT */ +HAL_StatusTypeDef HAL_RTCEx_PollForTamper2Event(RTC_HandleTypeDef *hrtc, uint32_t Timeout); +#if defined(RTC_TAMPER3_SUPPORT) +HAL_StatusTypeDef HAL_RTCEx_PollForTamper3Event(RTC_HandleTypeDef *hrtc, uint32_t Timeout); +#endif /* RTC_TAMPER3_SUPPORT */ +/** + * @} + */ + +/* RTC Wake-up functions ******************************************************/ +/** @addtogroup RTCEx_Exported_Functions_Group2 + * @{ + */ +HAL_StatusTypeDef HAL_RTCEx_SetWakeUpTimer(RTC_HandleTypeDef *hrtc, uint32_t WakeUpCounter, uint32_t WakeUpClock); +HAL_StatusTypeDef HAL_RTCEx_SetWakeUpTimer_IT(RTC_HandleTypeDef *hrtc, uint32_t WakeUpCounter, uint32_t WakeUpClock); +uint32_t HAL_RTCEx_DeactivateWakeUpTimer(RTC_HandleTypeDef *hrtc); +uint32_t HAL_RTCEx_GetWakeUpTimer(RTC_HandleTypeDef *hrtc); +void HAL_RTCEx_WakeUpTimerIRQHandler(RTC_HandleTypeDef *hrtc); +void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc); +HAL_StatusTypeDef HAL_RTCEx_PollForWakeUpTimerEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout); +/** + * @} + */ + +/* Extended Control functions ************************************************/ +/** @addtogroup RTCEx_Exported_Functions_Group3 + * @{ + */ +void HAL_RTCEx_BKUPWrite(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister, uint32_t Data); +uint32_t HAL_RTCEx_BKUPRead(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister); + +HAL_StatusTypeDef HAL_RTCEx_SetSmoothCalib(RTC_HandleTypeDef *hrtc, uint32_t SmoothCalibPeriod, uint32_t SmoothCalibPlusPulses, uint32_t SmoothCalibMinusPulsesValue); +HAL_StatusTypeDef HAL_RTCEx_SetSynchroShift(RTC_HandleTypeDef *hrtc, uint32_t ShiftAdd1S, uint32_t ShiftSubFS); +HAL_StatusTypeDef HAL_RTCEx_SetCalibrationOutPut(RTC_HandleTypeDef *hrtc, uint32_t CalibOutput); +HAL_StatusTypeDef HAL_RTCEx_DeactivateCalibrationOutPut(RTC_HandleTypeDef *hrtc); +HAL_StatusTypeDef HAL_RTCEx_SetRefClock(RTC_HandleTypeDef *hrtc); +HAL_StatusTypeDef HAL_RTCEx_DeactivateRefClock(RTC_HandleTypeDef *hrtc); +HAL_StatusTypeDef HAL_RTCEx_EnableBypassShadow(RTC_HandleTypeDef *hrtc); +HAL_StatusTypeDef HAL_RTCEx_DisableBypassShadow(RTC_HandleTypeDef *hrtc); +/** + * @} + */ + +/* Extended RTC features functions *******************************************/ +/** @addtogroup RTCEx_Exported_Functions_Group4 + * @{ + */ +void HAL_RTCEx_AlarmBEventCallback(RTC_HandleTypeDef *hrtc); +HAL_StatusTypeDef HAL_RTCEx_PollForAlarmBEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout); +/** + * @} + */ + +/** + * @} + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** @defgroup RTCEx_Private_Constants RTCEx Private Constants + * @{ + */ +#define RTC_EXTI_LINE_TAMPER_TIMESTAMP_EVENT ((uint32_t)0x00080000) /*!< External interrupt line 19 Connected to the RTC Tamper and Time Stamp events */ +#define RTC_EXTI_LINE_WAKEUPTIMER_EVENT ((uint32_t)0x00100000) /*!< External interrupt line 20 Connected to the RTC Wakeup event */ + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup RTCEx_Private_Macros RTCEx Private Macros + * @{ + */ + +/** @defgroup RTCEx_IS_RTC_Definitions Private macros to check input parameters + * @{ + */ + +#define IS_RTC_OUTPUT(OUTPUT) (((OUTPUT) == RTC_OUTPUT_DISABLE) || \ + ((OUTPUT) == RTC_OUTPUT_ALARMA) || \ + ((OUTPUT) == RTC_OUTPUT_ALARMB) || \ + ((OUTPUT) == RTC_OUTPUT_WAKEUP)) + +#define IS_RTC_BKP(BKP) ((BKP) < (uint32_t) RTC_BKP_NUMBER) + +#define IS_TIMESTAMP_EDGE(EDGE) (((EDGE) == RTC_TIMESTAMPEDGE_RISING) || \ + ((EDGE) == RTC_TIMESTAMPEDGE_FALLING)) + +#define IS_RTC_TAMPER(TAMPER) ((((TAMPER) & (uint32_t)0xFFFFFFD6) == 0x00) && ((TAMPER) != (uint32_t)RESET)) + +#define IS_RTC_TAMPER_INTERRUPT(INTERRUPT) ((((INTERRUPT) & (uint32_t)0xFFB6FFFB) == 0x00) && ((INTERRUPT) != (uint32_t)RESET)) + +#define IS_RTC_TIMESTAMP_PIN(PIN) (((PIN) == RTC_TIMESTAMPPIN_DEFAULT)) + +#define IS_RTC_TAMPER_TRIGGER(TRIGGER) (((TRIGGER) == RTC_TAMPERTRIGGER_RISINGEDGE) || \ + ((TRIGGER) == RTC_TAMPERTRIGGER_FALLINGEDGE) || \ + ((TRIGGER) == RTC_TAMPERTRIGGER_LOWLEVEL) || \ + ((TRIGGER) == RTC_TAMPERTRIGGER_HIGHLEVEL)) + +#define IS_RTC_TAMPER_ERASE_MODE(MODE) (((MODE) == RTC_TAMPER_ERASE_BACKUP_ENABLE) || \ + ((MODE) == RTC_TAMPER_ERASE_BACKUP_DISABLE)) + +#define IS_RTC_TAMPER_MASKFLAG_STATE(STATE) (((STATE) == RTC_TAMPERMASK_FLAG_ENABLE) || \ + ((STATE) == RTC_TAMPERMASK_FLAG_DISABLE)) + +#define IS_RTC_TAMPER_FILTER(FILTER) (((FILTER) == RTC_TAMPERFILTER_DISABLE) || \ + ((FILTER) == RTC_TAMPERFILTER_2SAMPLE) || \ + ((FILTER) == RTC_TAMPERFILTER_4SAMPLE) || \ + ((FILTER) == RTC_TAMPERFILTER_8SAMPLE)) + +#define IS_RTC_TAMPER_SAMPLING_FREQ(FREQ) (((FREQ) == RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV32768)|| \ + ((FREQ) == RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV16384)|| \ + ((FREQ) == RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV8192) || \ + ((FREQ) == RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV4096) || \ + ((FREQ) == RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV2048) || \ + ((FREQ) == RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV1024) || \ + ((FREQ) == RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV512) || \ + ((FREQ) == RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV256)) + +#define IS_RTC_TAMPER_PRECHARGE_DURATION(DURATION) (((DURATION) == RTC_TAMPERPRECHARGEDURATION_1RTCCLK) || \ + ((DURATION) == RTC_TAMPERPRECHARGEDURATION_2RTCCLK) || \ + ((DURATION) == RTC_TAMPERPRECHARGEDURATION_4RTCCLK) || \ + ((DURATION) == RTC_TAMPERPRECHARGEDURATION_8RTCCLK)) + +#define IS_RTC_TAMPER_TIMESTAMPONTAMPER_DETECTION(DETECTION) (((DETECTION) == RTC_TIMESTAMPONTAMPERDETECTION_ENABLE) || \ + ((DETECTION) == RTC_TIMESTAMPONTAMPERDETECTION_DISABLE)) + +#define IS_RTC_TAMPER_PULLUP_STATE(STATE) (((STATE) == RTC_TAMPER_PULLUP_ENABLE) || \ + ((STATE) == RTC_TAMPER_PULLUP_DISABLE)) + +#define IS_RTC_WAKEUP_CLOCK(CLOCK) (((CLOCK) == RTC_WAKEUPCLOCK_RTCCLK_DIV16) || \ + ((CLOCK) == RTC_WAKEUPCLOCK_RTCCLK_DIV8) || \ + ((CLOCK) == RTC_WAKEUPCLOCK_RTCCLK_DIV4) || \ + ((CLOCK) == RTC_WAKEUPCLOCK_RTCCLK_DIV2) || \ + ((CLOCK) == RTC_WAKEUPCLOCK_CK_SPRE_16BITS) || \ + ((CLOCK) == RTC_WAKEUPCLOCK_CK_SPRE_17BITS)) + +#define IS_RTC_WAKEUP_COUNTER(COUNTER) ((COUNTER) <= 0xFFFF) + +#define IS_RTC_SMOOTH_CALIB_PERIOD(PERIOD) (((PERIOD) == RTC_SMOOTHCALIB_PERIOD_32SEC) || \ + ((PERIOD) == RTC_SMOOTHCALIB_PERIOD_16SEC) || \ + ((PERIOD) == RTC_SMOOTHCALIB_PERIOD_8SEC)) + +#define IS_RTC_SMOOTH_CALIB_PLUS(PLUS) (((PLUS) == RTC_SMOOTHCALIB_PLUSPULSES_SET) || \ + ((PLUS) == RTC_SMOOTHCALIB_PLUSPULSES_RESET)) + +#define IS_RTC_SMOOTH_CALIB_MINUS(VALUE) ((VALUE) <= 0x000001FF) + +#define IS_RTC_SHIFT_ADD1S(SEL) (((SEL) == RTC_SHIFTADD1S_RESET) || \ + ((SEL) == RTC_SHIFTADD1S_SET)) + +#define IS_RTC_SHIFT_SUBFS(FS) ((FS) <= 0x00007FFF) + +#define IS_RTC_CALIB_OUTPUT(OUTPUT) (((OUTPUT) == RTC_CALIBOUTPUT_512HZ) || \ + ((OUTPUT) == RTC_CALIBOUTPUT_1HZ)) + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_HAL_RTC_EX_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_tim.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_tim.h new file mode 100644 index 0000000..bfc0194 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_tim.h @@ -0,0 +1,2043 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_tim.h + * @author MCD Application Team + * @brief Header file of TIM HAL module. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_TIM_H +#define __STM32L4xx_HAL_TIM_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup TIM + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup TIM_Exported_Types TIM Exported Types + * @{ + */ + +/** + * @brief TIM Time base Configuration Structure definition + */ +typedef struct +{ + uint32_t Prescaler; /*!< Specifies the prescaler value used to divide the TIM clock. + This parameter can be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF */ + + uint32_t CounterMode; /*!< Specifies the counter mode. + This parameter can be a value of @ref TIM_Counter_Mode */ + + uint32_t Period; /*!< Specifies the period value to be loaded into the active + Auto-Reload Register at the next update event. + This parameter can be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */ + + uint32_t ClockDivision; /*!< Specifies the clock division. + This parameter can be a value of @ref TIM_ClockDivision */ + + uint32_t RepetitionCounter; /*!< Specifies the repetition counter value. Each time the RCR downcounter + reaches zero, an update event is generated and counting restarts + from the RCR value (N). + This means in PWM mode that (N+1) corresponds to: + - the number of PWM periods in edge-aligned mode + - the number of half PWM period in center-aligned mode + This parameter must be a number between Min_Data = 0x00 and Max_Data = 0xFF. + @note This parameter is valid only for TIM1 and TIM8. */ + + uint32_t AutoReloadPreload; /*!< Specifies the auto-reload preload. + This parameter can be a value of @ref TIM_AutoReloadPreload */ +} TIM_Base_InitTypeDef; + +/** + * @brief TIM Output Compare Configuration Structure definition + */ +typedef struct +{ + uint32_t OCMode; /*!< Specifies the TIM mode. + This parameter can be a value of @ref TIM_Output_Compare_and_PWM_modes */ + + uint32_t Pulse; /*!< Specifies the pulse value to be loaded into the Capture Compare Register. + This parameter can be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF */ + + uint32_t OCPolarity; /*!< Specifies the output polarity. + This parameter can be a value of @ref TIM_Output_Compare_Polarity */ + + uint32_t OCNPolarity; /*!< Specifies the complementary output polarity. + This parameter can be a value of @ref TIM_Output_Compare_N_Polarity + @note This parameter is valid only for TIM1 and TIM8. */ + + uint32_t OCFastMode; /*!< Specifies the Fast mode state. + This parameter can be a value of @ref TIM_Output_Fast_State + @note This parameter is valid only in PWM1 and PWM2 mode. */ + + + uint32_t OCIdleState; /*!< Specifies the TIM Output Compare pin state during Idle state. + This parameter can be a value of @ref TIM_Output_Compare_Idle_State + @note This parameter is valid only for TIM1 and TIM8. */ + + uint32_t OCNIdleState; /*!< Specifies the TIM Output Compare pin state during Idle state. + This parameter can be a value of @ref TIM_Output_Compare_N_Idle_State + @note This parameter is valid only for TIM1 and TIM8. */ +} TIM_OC_InitTypeDef; + +/** + * @brief TIM One Pulse Mode Configuration Structure definition + */ +typedef struct +{ + uint32_t OCMode; /*!< Specifies the TIM mode. + This parameter can be a value of @ref TIM_Output_Compare_and_PWM_modes */ + + uint32_t Pulse; /*!< Specifies the pulse value to be loaded into the Capture Compare Register. + This parameter can be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF */ + + uint32_t OCPolarity; /*!< Specifies the output polarity. + This parameter can be a value of @ref TIM_Output_Compare_Polarity */ + + uint32_t OCNPolarity; /*!< Specifies the complementary output polarity. + This parameter can be a value of @ref TIM_Output_Compare_N_Polarity + @note This parameter is valid only for TIM1 and TIM8. */ + + uint32_t OCIdleState; /*!< Specifies the TIM Output Compare pin state during Idle state. + This parameter can be a value of @ref TIM_Output_Compare_Idle_State + @note This parameter is valid only for TIM1 and TIM8. */ + + uint32_t OCNIdleState; /*!< Specifies the TIM Output Compare pin state during Idle state. + This parameter can be a value of @ref TIM_Output_Compare_N_Idle_State + @note This parameter is valid only for TIM1 and TIM8. */ + + uint32_t ICPolarity; /*!< Specifies the active edge of the input signal. + This parameter can be a value of @ref TIM_Input_Capture_Polarity */ + + uint32_t ICSelection; /*!< Specifies the input. + This parameter can be a value of @ref TIM_Input_Capture_Selection */ + + uint32_t ICFilter; /*!< Specifies the input capture filter. + This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */ +} TIM_OnePulse_InitTypeDef; + + +/** + * @brief TIM Input Capture Configuration Structure definition + */ +typedef struct +{ + uint32_t ICPolarity; /*!< Specifies the active edge of the input signal. + This parameter can be a value of @ref TIM_Input_Capture_Polarity */ + + uint32_t ICSelection; /*!< Specifies the input. + This parameter can be a value of @ref TIM_Input_Capture_Selection */ + + uint32_t ICPrescaler; /*!< Specifies the Input Capture Prescaler. + This parameter can be a value of @ref TIM_Input_Capture_Prescaler */ + + uint32_t ICFilter; /*!< Specifies the input capture filter. + This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */ +} TIM_IC_InitTypeDef; + +/** + * @brief TIM Encoder Configuration Structure definition + */ +typedef struct +{ + uint32_t EncoderMode; /*!< Specifies the active edge of the input signal. + This parameter can be a value of @ref TIM_Encoder_Mode */ + + uint32_t IC1Polarity; /*!< Specifies the active edge of the input signal. + This parameter can be a value of @ref TIM_Input_Capture_Polarity */ + + uint32_t IC1Selection; /*!< Specifies the input. + This parameter can be a value of @ref TIM_Input_Capture_Selection */ + + uint32_t IC1Prescaler; /*!< Specifies the Input Capture Prescaler. + This parameter can be a value of @ref TIM_Input_Capture_Prescaler */ + + uint32_t IC1Filter; /*!< Specifies the input capture filter. + This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */ + + uint32_t IC2Polarity; /*!< Specifies the active edge of the input signal. + This parameter can be a value of @ref TIM_Input_Capture_Polarity */ + + uint32_t IC2Selection; /*!< Specifies the input. + This parameter can be a value of @ref TIM_Input_Capture_Selection */ + + uint32_t IC2Prescaler; /*!< Specifies the Input Capture Prescaler. + This parameter can be a value of @ref TIM_Input_Capture_Prescaler */ + + uint32_t IC2Filter; /*!< Specifies the input capture filter. + This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */ +} TIM_Encoder_InitTypeDef; + + +/** + * @brief Clock Configuration Handle Structure definition + */ +typedef struct +{ + uint32_t ClockSource; /*!< TIM clock sources + This parameter can be a value of @ref TIM_Clock_Source */ + uint32_t ClockPolarity; /*!< TIM clock polarity + This parameter can be a value of @ref TIM_Clock_Polarity */ + uint32_t ClockPrescaler; /*!< TIM clock prescaler + This parameter can be a value of @ref TIM_Clock_Prescaler */ + uint32_t ClockFilter; /*!< TIM clock filter + This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */ +}TIM_ClockConfigTypeDef; + +/** + * @brief Clear Input Configuration Handle Structure definition + */ +typedef struct +{ + uint32_t ClearInputState; /*!< TIM clear Input state + This parameter can be ENABLE or DISABLE */ + uint32_t ClearInputSource; /*!< TIM clear Input sources + This parameter can be a value of @ref TIM_ClearInput_Source */ + uint32_t ClearInputPolarity; /*!< TIM Clear Input polarity + This parameter can be a value of @ref TIM_ClearInput_Polarity */ + uint32_t ClearInputPrescaler; /*!< TIM Clear Input prescaler + This parameter can be a value of @ref TIM_ClearInput_Prescaler */ + uint32_t ClearInputFilter; /*!< TIM Clear Input filter + This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */ +}TIM_ClearInputConfigTypeDef; + +/** + * @brief TIM Master configuration Structure definition + * @note Advanced timers provide TRGO2 internal line which is redirected + * to the ADC + */ +typedef struct { + uint32_t MasterOutputTrigger; /*!< Trigger output (TRGO) selection + This parameter can be a value of @ref TIM_Master_Mode_Selection */ + uint32_t MasterOutputTrigger2; /*!< Trigger output2 (TRGO2) selection + This parameter can be a value of @ref TIM_Master_Mode_Selection_2 */ + uint32_t MasterSlaveMode; /*!< Master/slave mode selection + This parameter can be a value of @ref TIM_Master_Slave_Mode */ +}TIM_MasterConfigTypeDef; + +/** + * @brief TIM Slave configuration Structure definition + */ +typedef struct { + uint32_t SlaveMode; /*!< Slave mode selection + This parameter can be a value of @ref TIM_Slave_Mode */ + uint32_t InputTrigger; /*!< Input Trigger source + This parameter can be a value of @ref TIM_Trigger_Selection */ + uint32_t TriggerPolarity; /*!< Input Trigger polarity + This parameter can be a value of @ref TIM_Trigger_Polarity */ + uint32_t TriggerPrescaler; /*!< Input trigger prescaler + This parameter can be a value of @ref TIM_Trigger_Prescaler */ + uint32_t TriggerFilter; /*!< Input trigger filter + This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */ + +}TIM_SlaveConfigTypeDef; + +/** + * @brief TIM Break input(s) and Dead time configuration Structure definition + * @note 2 break inputs can be configured (BKIN and BKIN2) with configurable + * filter and polarity. + */ +typedef struct +{ + uint32_t OffStateRunMode; /*!< TIM off state in run mode + This parameter can be a value of @ref TIM_OSSR_Off_State_Selection_for_Run_mode_state */ + uint32_t OffStateIDLEMode; /*!< TIM off state in IDLE mode + This parameter can be a value of @ref TIM_OSSI_Off_State_Selection_for_Idle_mode_state */ + uint32_t LockLevel; /*!< TIM Lock level + This parameter can be a value of @ref TIM_Lock_level */ + uint32_t DeadTime; /*!< TIM dead Time + This parameter can be a number between Min_Data = 0x00 and Max_Data = 0xFF */ + uint32_t BreakState; /*!< TIM Break State + This parameter can be a value of @ref TIM_Break_Input_enable_disable */ + uint32_t BreakPolarity; /*!< TIM Break input polarity + This parameter can be a value of @ref TIM_Break_Polarity */ + uint32_t BreakFilter; /*!< Specifies the break input filter. + This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */ + uint32_t Break2State; /*!< TIM Break2 State + This parameter can be a value of @ref TIM_Break2_Input_enable_disable */ + uint32_t Break2Polarity; /*!< TIM Break2 input polarity + This parameter can be a value of @ref TIM_Break2_Polarity */ + uint32_t Break2Filter; /*!< TIM break2 input filter. + This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */ + uint32_t AutomaticOutput; /*!< TIM Automatic Output Enable state + This parameter can be a value of @ref TIM_AOE_Bit_Set_Reset */ +} TIM_BreakDeadTimeConfigTypeDef; + +/** + * @brief HAL State structures definition + */ +typedef enum +{ + HAL_TIM_STATE_RESET = 0x00, /*!< Peripheral not yet initialized or disabled */ + HAL_TIM_STATE_READY = 0x01, /*!< Peripheral Initialized and ready for use */ + HAL_TIM_STATE_BUSY = 0x02, /*!< An internal process is ongoing */ + HAL_TIM_STATE_TIMEOUT = 0x03, /*!< Timeout state */ + HAL_TIM_STATE_ERROR = 0x04 /*!< Reception process is ongoing */ +}HAL_TIM_StateTypeDef; + +/** + * @brief HAL Active channel structures definition + */ +typedef enum +{ + HAL_TIM_ACTIVE_CHANNEL_1 = 0x01, /*!< The active channel is 1 */ + HAL_TIM_ACTIVE_CHANNEL_2 = 0x02, /*!< The active channel is 2 */ + HAL_TIM_ACTIVE_CHANNEL_3 = 0x04, /*!< The active channel is 3 */ + HAL_TIM_ACTIVE_CHANNEL_4 = 0x08, /*!< The active channel is 4 */ + HAL_TIM_ACTIVE_CHANNEL_5 = 0x10, /*!< The active channel is 5 */ + HAL_TIM_ACTIVE_CHANNEL_6 = 0x20, /*!< The active channel is 6 */ + HAL_TIM_ACTIVE_CHANNEL_CLEARED = 0x00 /*!< All active channels cleared */ +}HAL_TIM_ActiveChannel; + +/** + * @brief TIM Time Base Handle Structure definition + */ +typedef struct +{ + TIM_TypeDef *Instance; /*!< Register base address */ + TIM_Base_InitTypeDef Init; /*!< TIM Time Base required parameters */ + HAL_TIM_ActiveChannel Channel; /*!< Active channel */ + DMA_HandleTypeDef *hdma[7]; /*!< DMA Handlers array + This array is accessed by a @ref DMA_Handle_index */ + HAL_LockTypeDef Lock; /*!< Locking object */ + __IO HAL_TIM_StateTypeDef State; /*!< TIM operation state */ +}TIM_HandleTypeDef; + +/** + * @} + */ +/* End of exported types -----------------------------------------------------*/ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup TIM_Exported_Constants TIM Exported Constants + * @{ + */ + +/** @defgroup TIM_ClearInput_Source TIM Clear Input Source + * @{ + */ +#define TIM_CLEARINPUTSOURCE_ETR ((uint32_t)0x0001) +#define TIM_CLEARINPUTSOURCE_OCREFCLR ((uint32_t)0x0002) +#define TIM_CLEARINPUTSOURCE_NONE ((uint32_t)0x0000) +/** + * @} + */ + +/** @defgroup TIM_DMA_Base_address TIM DMA Base Address + * @{ + */ +#define TIM_DMABASE_CR1 (0x00000000) +#define TIM_DMABASE_CR2 (0x00000001) +#define TIM_DMABASE_SMCR (0x00000002) +#define TIM_DMABASE_DIER (0x00000003) +#define TIM_DMABASE_SR (0x00000004) +#define TIM_DMABASE_EGR (0x00000005) +#define TIM_DMABASE_CCMR1 (0x00000006) +#define TIM_DMABASE_CCMR2 (0x00000007) +#define TIM_DMABASE_CCER (0x00000008) +#define TIM_DMABASE_CNT (0x00000009) +#define TIM_DMABASE_PSC (0x0000000A) +#define TIM_DMABASE_ARR (0x0000000B) +#define TIM_DMABASE_RCR (0x0000000C) +#define TIM_DMABASE_CCR1 (0x0000000D) +#define TIM_DMABASE_CCR2 (0x0000000E) +#define TIM_DMABASE_CCR3 (0x0000000F) +#define TIM_DMABASE_CCR4 (0x00000010) +#define TIM_DMABASE_BDTR (0x00000011) +#define TIM_DMABASE_DCR (0x00000012) +#define TIM_DMABASE_DMAR (0x00000013) +#define TIM_DMABASE_OR1 (0x00000014) +#define TIM_DMABASE_CCMR3 (0x00000015) +#define TIM_DMABASE_CCR5 (0x00000016) +#define TIM_DMABASE_CCR6 (0x00000017) +#define TIM_DMABASE_OR2 (0x00000018) +#define TIM_DMABASE_OR3 (0x00000019) +/** + * @} + */ + +/** @defgroup TIM_Event_Source TIM Extended Event Source + * @{ + */ +#define TIM_EVENTSOURCE_UPDATE TIM_EGR_UG /*!< Reinitialize the counter and generates an update of the registers */ +#define TIM_EVENTSOURCE_CC1 TIM_EGR_CC1G /*!< A capture/compare event is generated on channel 1 */ +#define TIM_EVENTSOURCE_CC2 TIM_EGR_CC2G /*!< A capture/compare event is generated on channel 2 */ +#define TIM_EVENTSOURCE_CC3 TIM_EGR_CC3G /*!< A capture/compare event is generated on channel 3 */ +#define TIM_EVENTSOURCE_CC4 TIM_EGR_CC4G /*!< A capture/compare event is generated on channel 4 */ +#define TIM_EVENTSOURCE_COM TIM_EGR_COMG /*!< A commutation event is generated */ +#define TIM_EVENTSOURCE_TRIGGER TIM_EGR_TG /*!< A trigger event is generated */ +#define TIM_EVENTSOURCE_BREAK TIM_EGR_BG /*!< A break event is generated */ +#define TIM_EVENTSOURCE_BREAK2 TIM_EGR_B2G /*!< A break 2 event is generated */ +/** + * @} + */ + +/** @defgroup TIM_Input_Channel_Polarity TIM Input Channel polarity + * @{ + */ +#define TIM_INPUTCHANNELPOLARITY_RISING ((uint32_t)0x00000000) /*!< Polarity for TIx source */ +#define TIM_INPUTCHANNELPOLARITY_FALLING (TIM_CCER_CC1P) /*!< Polarity for TIx source */ +#define TIM_INPUTCHANNELPOLARITY_BOTHEDGE (TIM_CCER_CC1P | TIM_CCER_CC1NP) /*!< Polarity for TIx source */ +/** + * @} + */ + +/** @defgroup TIM_ETR_Polarity TIM ETR Polarity + * @{ + */ +#define TIM_ETRPOLARITY_INVERTED (TIM_SMCR_ETP) /*!< Polarity for ETR source */ +#define TIM_ETRPOLARITY_NONINVERTED ((uint32_t)0x0000) /*!< Polarity for ETR source */ +/** + * @} + */ + +/** @defgroup TIM_ETR_Prescaler TIM ETR Prescaler + * @{ + */ +#define TIM_ETRPRESCALER_DIV1 ((uint32_t)0x0000) /*!< No prescaler is used */ +#define TIM_ETRPRESCALER_DIV2 (TIM_SMCR_ETPS_0) /*!< ETR input source is divided by 2 */ +#define TIM_ETRPRESCALER_DIV4 (TIM_SMCR_ETPS_1) /*!< ETR input source is divided by 4 */ +#define TIM_ETRPRESCALER_DIV8 (TIM_SMCR_ETPS) /*!< ETR input source is divided by 8 */ +/** + * @} + */ + +/** @defgroup TIM_Counter_Mode TIM Counter Mode + * @{ + */ +#define TIM_COUNTERMODE_UP ((uint32_t)0x0000) +#define TIM_COUNTERMODE_DOWN TIM_CR1_DIR +#define TIM_COUNTERMODE_CENTERALIGNED1 TIM_CR1_CMS_0 +#define TIM_COUNTERMODE_CENTERALIGNED2 TIM_CR1_CMS_1 +#define TIM_COUNTERMODE_CENTERALIGNED3 TIM_CR1_CMS +/** + * @} + */ + +/** @defgroup TIM_ClockDivision TIM Clock Division + * @{ + */ +#define TIM_CLOCKDIVISION_DIV1 ((uint32_t)0x0000) +#define TIM_CLOCKDIVISION_DIV2 (TIM_CR1_CKD_0) +#define TIM_CLOCKDIVISION_DIV4 (TIM_CR1_CKD_1) +/** + * @} + */ + +/** @defgroup TIM_AutoReloadPreload TIM Auto-Reload Preload + * @{ + */ +#define TIM_AUTORELOAD_PRELOAD_DISABLE ((uint32_t)0x0000) /*!< TIMx_ARR register is not buffered */ +#define TIM_AUTORELOAD_PRELOAD_ENABLE (TIM_CR1_ARPE) /*!< TIMx_ARR register is buffered */ +/** + * @} + */ + +/** @defgroup TIM_Output_Compare_State TIM Output Compare State + * @{ + */ +#define TIM_OUTPUTSTATE_DISABLE ((uint32_t)0x0000) +#define TIM_OUTPUTSTATE_ENABLE (TIM_CCER_CC1E) +/** + * @} + */ + +/** @defgroup TIM_Output_Compare_N_State TIM Complementary Output Compare State + * @{ + */ +#define TIM_OUTPUTNSTATE_DISABLE ((uint32_t)0x0000) +#define TIM_OUTPUTNSTATE_ENABLE (TIM_CCER_CC1NE) +/** + * @} + */ + +/** @defgroup TIM_Output_Fast_State TIM Output Fast State + * @{ + */ +#define TIM_OCFAST_DISABLE ((uint32_t)0x0000) +#define TIM_OCFAST_ENABLE (TIM_CCMR1_OC1FE) +/** + * @} + */ + +/** @defgroup TIM_Output_Compare_Polarity TIM Output Compare Polarity + * @{ + */ +#define TIM_OCPOLARITY_HIGH ((uint32_t)0x0000) +#define TIM_OCPOLARITY_LOW (TIM_CCER_CC1P) +/** + * @} + */ + +/** @defgroup TIM_Output_Compare_N_Polarity TIM Complementary Output Compare Polarity + * @{ + */ +#define TIM_OCNPOLARITY_HIGH ((uint32_t)0x0000) +#define TIM_OCNPOLARITY_LOW (TIM_CCER_CC1NP) +/** + * @} + */ + +/** @defgroup TIM_Output_Compare_Idle_State TIM Output Compare Idle State + * @{ + */ +#define TIM_OCIDLESTATE_SET (TIM_CR2_OIS1) +#define TIM_OCIDLESTATE_RESET ((uint32_t)0x0000) +/** + * @} + */ + +/** @defgroup TIM_Output_Compare_N_Idle_State TIM Complementary Output Compare Idle State + * @{ + */ +#define TIM_OCNIDLESTATE_SET (TIM_CR2_OIS1N) +#define TIM_OCNIDLESTATE_RESET ((uint32_t)0x0000) +/** + * @} + */ + +/** @defgroup TIM_Input_Capture_Polarity TIM Input Capture Polarity + * @{ + */ +#define TIM_ICPOLARITY_RISING TIM_INPUTCHANNELPOLARITY_RISING +#define TIM_ICPOLARITY_FALLING TIM_INPUTCHANNELPOLARITY_FALLING +#define TIM_ICPOLARITY_BOTHEDGE TIM_INPUTCHANNELPOLARITY_BOTHEDGE +/** + * @} + */ + +/** @defgroup TIM_Input_Capture_Selection TIM Input Capture Selection + * @{ + */ +#define TIM_ICSELECTION_DIRECTTI (TIM_CCMR1_CC1S_0) /*!< TIM Input 1, 2, 3 or 4 is selected to be + connected to IC1, IC2, IC3 or IC4, respectively */ +#define TIM_ICSELECTION_INDIRECTTI (TIM_CCMR1_CC1S_1) /*!< TIM Input 1, 2, 3 or 4 is selected to be + connected to IC2, IC1, IC4 or IC3, respectively */ +#define TIM_ICSELECTION_TRC (TIM_CCMR1_CC1S) /*!< TIM Input 1, 2, 3 or 4 is selected to be connected to TRC */ +/** + * @} + */ + +/** @defgroup TIM_Input_Capture_Prescaler TIM Input Capture Prescaler + * @{ + */ +#define TIM_ICPSC_DIV1 ((uint32_t)0x0000) /*!< Capture performed each time an edge is detected on the capture input */ +#define TIM_ICPSC_DIV2 (TIM_CCMR1_IC1PSC_0) /*!< Capture performed once every 2 events */ +#define TIM_ICPSC_DIV4 (TIM_CCMR1_IC1PSC_1) /*!< Capture performed once every 4 events */ +#define TIM_ICPSC_DIV8 (TIM_CCMR1_IC1PSC) /*!< Capture performed once every 8 events */ +/** + * @} + */ + +/** @defgroup TIM_One_Pulse_Mode TIM One Pulse Mode + * @{ + */ +#define TIM_OPMODE_SINGLE (TIM_CR1_OPM) +#define TIM_OPMODE_REPETITIVE ((uint32_t)0x0000) +/** + * @} + */ + +/** @defgroup TIM_Encoder_Mode TIM Encoder Mode + * @{ + */ +#define TIM_ENCODERMODE_TI1 (TIM_SMCR_SMS_0) +#define TIM_ENCODERMODE_TI2 (TIM_SMCR_SMS_1) +#define TIM_ENCODERMODE_TI12 (TIM_SMCR_SMS_1 | TIM_SMCR_SMS_0) +/** + * @} + */ + +/** @defgroup TIM_Interrupt_definition TIM interrupt Definition + * @{ + */ +#define TIM_IT_UPDATE (TIM_DIER_UIE) +#define TIM_IT_CC1 (TIM_DIER_CC1IE) +#define TIM_IT_CC2 (TIM_DIER_CC2IE) +#define TIM_IT_CC3 (TIM_DIER_CC3IE) +#define TIM_IT_CC4 (TIM_DIER_CC4IE) +#define TIM_IT_COM (TIM_DIER_COMIE) +#define TIM_IT_TRIGGER (TIM_DIER_TIE) +#define TIM_IT_BREAK (TIM_DIER_BIE) +/** + * @} + */ + +/** @defgroup TIM_Commutation_Source TIM Commutation Source + * @{ + */ +#define TIM_COMMUTATION_TRGI (TIM_CR2_CCUS) +#define TIM_COMMUTATION_SOFTWARE ((uint32_t)0x0000) +/** + * @} + */ + +/** @defgroup TIM_DMA_sources TIM DMA Sources + * @{ + */ +#define TIM_DMA_UPDATE (TIM_DIER_UDE) +#define TIM_DMA_CC1 (TIM_DIER_CC1DE) +#define TIM_DMA_CC2 (TIM_DIER_CC2DE) +#define TIM_DMA_CC3 (TIM_DIER_CC3DE) +#define TIM_DMA_CC4 (TIM_DIER_CC4DE) +#define TIM_DMA_COM (TIM_DIER_COMDE) +#define TIM_DMA_TRIGGER (TIM_DIER_TDE) +/** + * @} + */ + +/** @defgroup TIM_Flag_definition TIM Flag Definition + * @{ + */ +#define TIM_FLAG_UPDATE (TIM_SR_UIF) +#define TIM_FLAG_CC1 (TIM_SR_CC1IF) +#define TIM_FLAG_CC2 (TIM_SR_CC2IF) +#define TIM_FLAG_CC3 (TIM_SR_CC3IF) +#define TIM_FLAG_CC4 (TIM_SR_CC4IF) +#define TIM_FLAG_CC5 (TIM_SR_CC5IF) +#define TIM_FLAG_CC6 (TIM_SR_CC6IF) +#define TIM_FLAG_COM (TIM_SR_COMIF) +#define TIM_FLAG_TRIGGER (TIM_SR_TIF) +#define TIM_FLAG_BREAK (TIM_SR_BIF) +#define TIM_FLAG_BREAK2 (TIM_SR_B2IF) +#define TIM_FLAG_SYSTEM_BREAK (TIM_SR_SBIF) +#define TIM_FLAG_CC1OF (TIM_SR_CC1OF) +#define TIM_FLAG_CC2OF (TIM_SR_CC2OF) +#define TIM_FLAG_CC3OF (TIM_SR_CC3OF) +#define TIM_FLAG_CC4OF (TIM_SR_CC4OF) +/** + * @} + */ + +/** @defgroup TIM_Channel TIM Channel + * @{ + */ +#define TIM_CHANNEL_1 ((uint32_t)0x0000) +#define TIM_CHANNEL_2 ((uint32_t)0x0004) +#define TIM_CHANNEL_3 ((uint32_t)0x0008) +#define TIM_CHANNEL_4 ((uint32_t)0x000C) +#define TIM_CHANNEL_5 ((uint32_t)0x0010) +#define TIM_CHANNEL_6 ((uint32_t)0x0014) +#define TIM_CHANNEL_ALL ((uint32_t)0x003C) +/** + * @} + */ + +/** @defgroup TIM_Clock_Source TIM Clock Source + * @{ + */ +#define TIM_CLOCKSOURCE_ETRMODE2 (TIM_SMCR_ETPS_1) +#define TIM_CLOCKSOURCE_INTERNAL (TIM_SMCR_ETPS_0) +#define TIM_CLOCKSOURCE_ITR0 ((uint32_t)0x0000) +#define TIM_CLOCKSOURCE_ITR1 (TIM_SMCR_TS_0) +#define TIM_CLOCKSOURCE_ITR2 (TIM_SMCR_TS_1) +#define TIM_CLOCKSOURCE_ITR3 (TIM_SMCR_TS_0 | TIM_SMCR_TS_1) +#define TIM_CLOCKSOURCE_TI1ED (TIM_SMCR_TS_2) +#define TIM_CLOCKSOURCE_TI1 (TIM_SMCR_TS_0 | TIM_SMCR_TS_2) +#define TIM_CLOCKSOURCE_TI2 (TIM_SMCR_TS_1 | TIM_SMCR_TS_2) +#define TIM_CLOCKSOURCE_ETRMODE1 (TIM_SMCR_TS) +/** + * @} + */ + +/** @defgroup TIM_Clock_Polarity TIM Clock Polarity + * @{ + */ +#define TIM_CLOCKPOLARITY_INVERTED TIM_ETRPOLARITY_INVERTED /*!< Polarity for ETRx clock sources */ +#define TIM_CLOCKPOLARITY_NONINVERTED TIM_ETRPOLARITY_NONINVERTED /*!< Polarity for ETRx clock sources */ +#define TIM_CLOCKPOLARITY_RISING TIM_INPUTCHANNELPOLARITY_RISING /*!< Polarity for TIx clock sources */ +#define TIM_CLOCKPOLARITY_FALLING TIM_INPUTCHANNELPOLARITY_FALLING /*!< Polarity for TIx clock sources */ +#define TIM_CLOCKPOLARITY_BOTHEDGE TIM_INPUTCHANNELPOLARITY_BOTHEDGE /*!< Polarity for TIx clock sources */ +/** + * @} + */ + +/** @defgroup TIM_Clock_Prescaler TIM Clock Prescaler + * @{ + */ +#define TIM_CLOCKPRESCALER_DIV1 TIM_ETRPRESCALER_DIV1 /*!< No prescaler is used */ +#define TIM_CLOCKPRESCALER_DIV2 TIM_ETRPRESCALER_DIV2 /*!< Prescaler for External ETR Clock: Capture performed once every 2 events. */ +#define TIM_CLOCKPRESCALER_DIV4 TIM_ETRPRESCALER_DIV4 /*!< Prescaler for External ETR Clock: Capture performed once every 4 events. */ +#define TIM_CLOCKPRESCALER_DIV8 TIM_ETRPRESCALER_DIV8 /*!< Prescaler for External ETR Clock: Capture performed once every 8 events. */ +/** + * @} + */ + +/** @defgroup TIM_ClearInput_Polarity TIM Clear Input Polarity + * @{ + */ +#define TIM_CLEARINPUTPOLARITY_INVERTED TIM_ETRPOLARITY_INVERTED /*!< Polarity for ETRx pin */ +#define TIM_CLEARINPUTPOLARITY_NONINVERTED TIM_ETRPOLARITY_NONINVERTED /*!< Polarity for ETRx pin */ +/** + * @} + */ + +/** @defgroup TIM_ClearInput_Prescaler TIM Clear Input Prescaler + * @{ + */ +#define TIM_CLEARINPUTPRESCALER_DIV1 TIM_ETRPRESCALER_DIV1 /*!< No prescaler is used */ +#define TIM_CLEARINPUTPRESCALER_DIV2 TIM_ETRPRESCALER_DIV2 /*!< Prescaler for External ETR pin: Capture performed once every 2 events. */ +#define TIM_CLEARINPUTPRESCALER_DIV4 TIM_ETRPRESCALER_DIV4 /*!< Prescaler for External ETR pin: Capture performed once every 4 events. */ +#define TIM_CLEARINPUTPRESCALER_DIV8 TIM_ETRPRESCALER_DIV8 /*!< Prescaler for External ETR pin: Capture performed once every 8 events. */ +/** + * @} + */ + +/** @defgroup TIM_OSSR_Off_State_Selection_for_Run_mode_state TIM OSSR OffState Selection for Run mode state + * @{ + */ +#define TIM_OSSR_ENABLE (TIM_BDTR_OSSR) +#define TIM_OSSR_DISABLE ((uint32_t)0x0000) +/** + * @} + */ + +/** @defgroup TIM_OSSI_Off_State_Selection_for_Idle_mode_state TIM OSSI OffState Selection for Idle mode state + * @{ + */ +#define TIM_OSSI_ENABLE (TIM_BDTR_OSSI) +#define TIM_OSSI_DISABLE ((uint32_t)0x0000) +/** + * @} + */ +/** @defgroup TIM_Lock_level TIM Lock level + * @{ + */ +#define TIM_LOCKLEVEL_OFF ((uint32_t)0x0000) +#define TIM_LOCKLEVEL_1 (TIM_BDTR_LOCK_0) +#define TIM_LOCKLEVEL_2 (TIM_BDTR_LOCK_1) +#define TIM_LOCKLEVEL_3 (TIM_BDTR_LOCK) +/** + * @} + */ + +/** @defgroup TIM_Break_Input_enable_disable TIM Break Input Enable + * @{ + */ +#define TIM_BREAK_ENABLE (TIM_BDTR_BKE) +#define TIM_BREAK_DISABLE ((uint32_t)0x0000) +/** + * @} + */ + +/** @defgroup TIM_Break_Polarity TIM Break Input Polarity + * @{ + */ +#define TIM_BREAKPOLARITY_LOW ((uint32_t)0x0000) +#define TIM_BREAKPOLARITY_HIGH (TIM_BDTR_BKP) +/** + * @} + */ + +/** @defgroup TIM_Break2_Input_enable_disable TIM Break input 2 Enable + * @{ + */ +#define TIM_BREAK2_DISABLE ((uint32_t)0x00000000) +#define TIM_BREAK2_ENABLE ((uint32_t)TIM_BDTR_BK2E) +/** + * @} + */ + +/** @defgroup TIM_Break2_Polarity TIM Break Input 2 Polarity + * @{ + */ +#define TIM_BREAK2POLARITY_LOW ((uint32_t)0x00000000) +#define TIM_BREAK2POLARITY_HIGH ((uint32_t)TIM_BDTR_BK2P) +/** + * @} + */ + +/** @defgroup TIM_AOE_Bit_Set_Reset TIM Automatic Output Enable + * @{ + */ +#define TIM_AUTOMATICOUTPUT_ENABLE (TIM_BDTR_AOE) +#define TIM_AUTOMATICOUTPUT_DISABLE ((uint32_t)0x0000) +/** + * @} + */ + +/** @defgroup TIM_Group_Channel5 Group Channel 5 and Channel 1, 2 or 3 + * @{ + */ +#define TIM_GROUPCH5_NONE (uint32_t)0x00000000 /* !< No effect of OC5REF on OC1REFC, OC2REFC and OC3REFC */ +#define TIM_GROUPCH5_OC1REFC (TIM_CCR5_GC5C1) /* !< OC1REFC is the logical AND of OC1REFC and OC5REF */ +#define TIM_GROUPCH5_OC2REFC (TIM_CCR5_GC5C2) /* !< OC2REFC is the logical AND of OC2REFC and OC5REF */ +#define TIM_GROUPCH5_OC3REFC (TIM_CCR5_GC5C3) /* !< OC3REFC is the logical AND of OC3REFC and OC5REF */ +/** + * @} + */ + +/** @defgroup TIM_Master_Mode_Selection TIM Master Mode Selection + * @{ + */ +#define TIM_TRGO_RESET ((uint32_t)0x0000) +#define TIM_TRGO_ENABLE (TIM_CR2_MMS_0) +#define TIM_TRGO_UPDATE (TIM_CR2_MMS_1) +#define TIM_TRGO_OC1 ((TIM_CR2_MMS_1 | TIM_CR2_MMS_0)) +#define TIM_TRGO_OC1REF (TIM_CR2_MMS_2) +#define TIM_TRGO_OC2REF ((TIM_CR2_MMS_2 | TIM_CR2_MMS_0)) +#define TIM_TRGO_OC3REF ((TIM_CR2_MMS_2 | TIM_CR2_MMS_1)) +#define TIM_TRGO_OC4REF ((TIM_CR2_MMS_2 | TIM_CR2_MMS_1 | TIM_CR2_MMS_0)) +/** + * @} + */ + +/** @defgroup TIM_Master_Mode_Selection_2 TIM Master Mode Selection 2 (TRGO2) + * @{ + */ +#define TIM_TRGO2_RESET ((uint32_t)0x00000000) +#define TIM_TRGO2_ENABLE ((uint32_t)(TIM_CR2_MMS2_0)) +#define TIM_TRGO2_UPDATE ((uint32_t)(TIM_CR2_MMS2_1)) +#define TIM_TRGO2_OC1 ((uint32_t)(TIM_CR2_MMS2_1 | TIM_CR2_MMS2_0)) +#define TIM_TRGO2_OC1REF ((uint32_t)(TIM_CR2_MMS2_2)) +#define TIM_TRGO2_OC2REF ((uint32_t)(TIM_CR2_MMS2_2 | TIM_CR2_MMS2_0)) +#define TIM_TRGO2_OC3REF ((uint32_t)(TIM_CR2_MMS2_2 | TIM_CR2_MMS2_1)) +#define TIM_TRGO2_OC4REF ((uint32_t)(TIM_CR2_MMS2_2 | TIM_CR2_MMS2_1 | TIM_CR2_MMS2_0)) +#define TIM_TRGO2_OC5REF ((uint32_t)(TIM_CR2_MMS2_3)) +#define TIM_TRGO2_OC6REF ((uint32_t)(TIM_CR2_MMS2_3 | TIM_CR2_MMS2_0)) +#define TIM_TRGO2_OC4REF_RISINGFALLING ((uint32_t)(TIM_CR2_MMS2_3 | TIM_CR2_MMS2_1)) +#define TIM_TRGO2_OC6REF_RISINGFALLING ((uint32_t)(TIM_CR2_MMS2_3 | TIM_CR2_MMS2_1 | TIM_CR2_MMS2_0)) +#define TIM_TRGO2_OC4REF_RISING_OC6REF_RISING ((uint32_t)(TIM_CR2_MMS2_3 | TIM_CR2_MMS2_2)) +#define TIM_TRGO2_OC4REF_RISING_OC6REF_FALLING ((uint32_t)(TIM_CR2_MMS2_3 | TIM_CR2_MMS2_2 | TIM_CR2_MMS2_0)) +#define TIM_TRGO2_OC5REF_RISING_OC6REF_RISING ((uint32_t)(TIM_CR2_MMS2_3 | TIM_CR2_MMS2_2 |TIM_CR2_MMS2_1)) +#define TIM_TRGO2_OC5REF_RISING_OC6REF_FALLING ((uint32_t)(TIM_CR2_MMS2_3 | TIM_CR2_MMS2_2 | TIM_CR2_MMS2_1 | TIM_CR2_MMS2_0)) +/** + * @} + */ + +/** @defgroup TIM_Master_Slave_Mode TIM Master/Slave Mode + * @{ + */ +#define TIM_MASTERSLAVEMODE_ENABLE ((uint32_t)0x0080) +#define TIM_MASTERSLAVEMODE_DISABLE ((uint32_t)0x0000) +/** + * @} + */ + +/** @defgroup TIM_Slave_Mode TIM Slave mode + * @{ + */ +#define TIM_SLAVEMODE_DISABLE ((uint32_t)0x0000) +#define TIM_SLAVEMODE_RESET ((uint32_t)(TIM_SMCR_SMS_2)) +#define TIM_SLAVEMODE_GATED ((uint32_t)(TIM_SMCR_SMS_2 | TIM_SMCR_SMS_0)) +#define TIM_SLAVEMODE_TRIGGER ((uint32_t)(TIM_SMCR_SMS_2 | TIM_SMCR_SMS_1)) +#define TIM_SLAVEMODE_EXTERNAL1 ((uint32_t)(TIM_SMCR_SMS_2 | TIM_SMCR_SMS_1 | TIM_SMCR_SMS_0)) +#define TIM_SLAVEMODE_COMBINED_RESETTRIGGER ((uint32_t)(TIM_SMCR_SMS_3)) +/** + * @} + */ + +/** @defgroup TIM_Output_Compare_and_PWM_modes TIM Output Compare and PWM Modes + * @{ + */ +#define TIM_OCMODE_TIMING ((uint32_t)0x0000) +#define TIM_OCMODE_ACTIVE ((uint32_t)TIM_CCMR1_OC1M_0) +#define TIM_OCMODE_INACTIVE ((uint32_t)TIM_CCMR1_OC1M_1) +#define TIM_OCMODE_TOGGLE ((uint32_t)TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_0) +#define TIM_OCMODE_PWM1 ((uint32_t)TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1) +#define TIM_OCMODE_PWM2 ((uint32_t)TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_0) +#define TIM_OCMODE_FORCED_ACTIVE ((uint32_t)TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_0) +#define TIM_OCMODE_FORCED_INACTIVE ((uint32_t)TIM_CCMR1_OC1M_2) + +#define TIM_OCMODE_RETRIGERRABLE_OPM1 ((uint32_t)TIM_CCMR1_OC1M_3) +#define TIM_OCMODE_RETRIGERRABLE_OPM2 ((uint32_t)TIM_CCMR1_OC1M_3 | TIM_CCMR1_OC1M_0) +#define TIM_OCMODE_COMBINED_PWM1 ((uint32_t)TIM_CCMR1_OC1M_3 | TIM_CCMR1_OC1M_2) +#define TIM_OCMODE_COMBINED_PWM2 ((uint32_t)TIM_CCMR1_OC1M_3 | TIM_CCMR1_OC1M_0 | TIM_CCMR1_OC1M_2) +#define TIM_OCMODE_ASSYMETRIC_PWM1 ((uint32_t)TIM_CCMR1_OC1M_3 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2) +#define TIM_OCMODE_ASSYMETRIC_PWM2 ((uint32_t)TIM_CCMR1_OC1M_3 | TIM_CCMR1_OC1M) +/** + * @} + */ + +/** @defgroup TIM_Trigger_Selection TIM Trigger Selection + * @{ + */ +#define TIM_TS_ITR0 ((uint32_t)0x0000) +#define TIM_TS_ITR1 ((uint32_t)0x0010) +#define TIM_TS_ITR2 ((uint32_t)0x0020) +#define TIM_TS_ITR3 ((uint32_t)0x0030) +#define TIM_TS_TI1F_ED ((uint32_t)0x0040) +#define TIM_TS_TI1FP1 ((uint32_t)0x0050) +#define TIM_TS_TI2FP2 ((uint32_t)0x0060) +#define TIM_TS_ETRF ((uint32_t)0x0070) +#define TIM_TS_NONE ((uint32_t)0xFFFF) +/** + * @} + */ + +/** @defgroup TIM_Trigger_Polarity TIM Trigger Polarity + * @{ + */ +#define TIM_TRIGGERPOLARITY_INVERTED TIM_ETRPOLARITY_INVERTED /*!< Polarity for ETRx trigger sources */ +#define TIM_TRIGGERPOLARITY_NONINVERTED TIM_ETRPOLARITY_NONINVERTED /*!< Polarity for ETRx trigger sources */ +#define TIM_TRIGGERPOLARITY_RISING TIM_INPUTCHANNELPOLARITY_RISING /*!< Polarity for TIxFPx or TI1_ED trigger sources */ +#define TIM_TRIGGERPOLARITY_FALLING TIM_INPUTCHANNELPOLARITY_FALLING /*!< Polarity for TIxFPx or TI1_ED trigger sources */ +#define TIM_TRIGGERPOLARITY_BOTHEDGE TIM_INPUTCHANNELPOLARITY_BOTHEDGE /*!< Polarity for TIxFPx or TI1_ED trigger sources */ +/** + * @} + */ + +/** @defgroup TIM_Trigger_Prescaler TIM Trigger Prescaler + * @{ + */ +#define TIM_TRIGGERPRESCALER_DIV1 TIM_ETRPRESCALER_DIV1 /*!< No prescaler is used */ +#define TIM_TRIGGERPRESCALER_DIV2 TIM_ETRPRESCALER_DIV2 /*!< Prescaler for External ETR Trigger: Capture performed once every 2 events. */ +#define TIM_TRIGGERPRESCALER_DIV4 TIM_ETRPRESCALER_DIV4 /*!< Prescaler for External ETR Trigger: Capture performed once every 4 events. */ +#define TIM_TRIGGERPRESCALER_DIV8 TIM_ETRPRESCALER_DIV8 /*!< Prescaler for External ETR Trigger: Capture performed once every 8 events. */ +/** + * @} + */ + +/** @defgroup TIM_TI1_Selection TIM TI1 Input Selection + * @{ + */ +#define TIM_TI1SELECTION_CH1 ((uint32_t)0x0000) +#define TIM_TI1SELECTION_XORCOMBINATION (TIM_CR2_TI1S) +/** + * @} + */ + +/** @defgroup TIM_DMA_Burst_Length TIM DMA Burst Length + * @{ + */ +#define TIM_DMABURSTLENGTH_1TRANSFER (0x00000000) +#define TIM_DMABURSTLENGTH_2TRANSFERS (0x00000100) +#define TIM_DMABURSTLENGTH_3TRANSFERS (0x00000200) +#define TIM_DMABURSTLENGTH_4TRANSFERS (0x00000300) +#define TIM_DMABURSTLENGTH_5TRANSFERS (0x00000400) +#define TIM_DMABURSTLENGTH_6TRANSFERS (0x00000500) +#define TIM_DMABURSTLENGTH_7TRANSFERS (0x00000600) +#define TIM_DMABURSTLENGTH_8TRANSFERS (0x00000700) +#define TIM_DMABURSTLENGTH_9TRANSFERS (0x00000800) +#define TIM_DMABURSTLENGTH_10TRANSFERS (0x00000900) +#define TIM_DMABURSTLENGTH_11TRANSFERS (0x00000A00) +#define TIM_DMABURSTLENGTH_12TRANSFERS (0x00000B00) +#define TIM_DMABURSTLENGTH_13TRANSFERS (0x00000C00) +#define TIM_DMABURSTLENGTH_14TRANSFERS (0x00000D00) +#define TIM_DMABURSTLENGTH_15TRANSFERS (0x00000E00) +#define TIM_DMABURSTLENGTH_16TRANSFERS (0x00000F00) +#define TIM_DMABURSTLENGTH_17TRANSFERS (0x00001000) +#define TIM_DMABURSTLENGTH_18TRANSFERS (0x00001100) +/** + * @} + */ + +/** @defgroup DMA_Handle_index TIM DMA Handle Index + * @{ + */ +#define TIM_DMA_ID_UPDATE ((uint16_t) 0x0) /*!< Index of the DMA handle used for Update DMA requests */ +#define TIM_DMA_ID_CC1 ((uint16_t) 0x1) /*!< Index of the DMA handle used for Capture/Compare 1 DMA requests */ +#define TIM_DMA_ID_CC2 ((uint16_t) 0x2) /*!< Index of the DMA handle used for Capture/Compare 2 DMA requests */ +#define TIM_DMA_ID_CC3 ((uint16_t) 0x3) /*!< Index of the DMA handle used for Capture/Compare 3 DMA requests */ +#define TIM_DMA_ID_CC4 ((uint16_t) 0x4) /*!< Index of the DMA handle used for Capture/Compare 4 DMA requests */ +#define TIM_DMA_ID_COMMUTATION ((uint16_t) 0x5) /*!< Index of the DMA handle used for Commutation DMA requests */ +#define TIM_DMA_ID_TRIGGER ((uint16_t) 0x6) /*!< Index of the DMA handle used for Trigger DMA requests */ +/** + * @} + */ + +/** @defgroup Channel_CC_State TIM Capture/Compare Channel State + * @{ + */ +#define TIM_CCx_ENABLE ((uint32_t)0x0001) +#define TIM_CCx_DISABLE ((uint32_t)0x0000) +#define TIM_CCxN_ENABLE ((uint32_t)0x0004) +#define TIM_CCxN_DISABLE ((uint32_t)0x0000) +/** + * @} + */ + +/** @defgroup TIM_Break_System TIM Break System + * @{ + */ +#define TIM_BREAK_SYSTEM_ECC SYSCFG_CFGR2_ECCL /*!< Enables and locks the ECC error signal with Break Input of TIM1/8/15/16/17 */ +#define TIM_BREAK_SYSTEM_PVD SYSCFG_CFGR2_PVDL /*!< Enables and locks the PVD connection with TIM1/8/15/16/17 Break Input and also the PVDE and PLS bits of the Power Control Interface */ +#define TIM_BREAK_SYSTEM_SRAM2_PARITY_ERROR SYSCFG_CFGR2_SPL /*!< Enables and locks the SRAM2_PARITY error signal with Break Input of TIM1/8/15/16/17 */ +#define TIM_BREAK_SYSTEM_LOCKUP SYSCFG_CFGR2_CLL /*!< Enables and locks the LOCKUP output of CortexM4 with Break Input of TIM1/15/16/17 */ +/** + * @} + */ + +/** + * @} + */ +/* End of exported constants -------------------------------------------------*/ + +/* Exported macros -----------------------------------------------------------*/ +/** @defgroup TIM_Exported_Macros TIM Exported Macros + * @{ + */ + +/** @brief Reset TIM handle state. + * @param __HANDLE__ TIM handle. + * @retval None + */ +#define __HAL_TIM_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_TIM_STATE_RESET) + +/** + * @brief Enable the TIM peripheral. + * @param __HANDLE__ TIM handle + * @retval None + */ +#define __HAL_TIM_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR1|=(TIM_CR1_CEN)) + +/** + * @brief Enable the TIM main Output. + * @param __HANDLE__ TIM handle + * @retval None + */ +#define __HAL_TIM_MOE_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->BDTR|=(TIM_BDTR_MOE)) + +/** + * @brief Disable the TIM peripheral. + * @param __HANDLE__ TIM handle + * @retval None + */ +#define __HAL_TIM_DISABLE(__HANDLE__) \ + do { \ + if (((__HANDLE__)->Instance->CCER & TIM_CCER_CCxE_MASK) == 0) \ + { \ + if(((__HANDLE__)->Instance->CCER & TIM_CCER_CCxNE_MASK) == 0) \ + { \ + (__HANDLE__)->Instance->CR1 &= ~(TIM_CR1_CEN); \ + } \ + } \ + } while(0) + +/** + * @brief Disable the TIM main Output. + * @param __HANDLE__ TIM handle + * @retval None + * @note The Main Output Enable of a timer instance is disabled only if all the CCx and CCxN channels have been disabled + */ +#define __HAL_TIM_MOE_DISABLE(__HANDLE__) \ + do { \ + if (((__HANDLE__)->Instance->CCER & TIM_CCER_CCxE_MASK) == 0) \ + { \ + if(((__HANDLE__)->Instance->CCER & TIM_CCER_CCxNE_MASK) == 0) \ + { \ + (__HANDLE__)->Instance->BDTR &= ~(TIM_BDTR_MOE); \ + } \ + } \ + } while(0) + +/** + * @brief Disable the TIM main Output. + * @param __HANDLE__ TIM handle + * @retval None + * @note The Main Output Enable of a timer instance is disabled unconditionally + */ +#define __HAL_TIM_MOE_DISABLE_UNCONDITIONALLY(__HANDLE__) (__HANDLE__)->Instance->BDTR &= ~(TIM_BDTR_MOE) + +/** @brief Enable the specified TIM interrupt. + * @param __HANDLE__ specifies the TIM Handle. + * @param __INTERRUPT__ specifies the TIM interrupt source to enable. + * This parameter can be one of the following values: + * @arg TIM_IT_UPDATE: Update interrupt + * @arg TIM_IT_CC1: Capture/Compare 1 interrupt + * @arg TIM_IT_CC2: Capture/Compare 2 interrupt + * @arg TIM_IT_CC3: Capture/Compare 3 interrupt + * @arg TIM_IT_CC4: Capture/Compare 4 interrupt + * @arg TIM_IT_COM: Commutation interrupt + * @arg TIM_IT_TRIGGER: Trigger interrupt + * @arg TIM_IT_BREAK: Break interrupt + * @retval None + */ +#define __HAL_TIM_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->DIER |= (__INTERRUPT__)) + + +/** @brief Disable the specified TIM interrupt. + * @param __HANDLE__ specifies the TIM Handle. + * @param __INTERRUPT__ specifies the TIM interrupt source to disable. + * This parameter can be one of the following values: + * @arg TIM_IT_UPDATE: Update interrupt + * @arg TIM_IT_CC1: Capture/Compare 1 interrupt + * @arg TIM_IT_CC2: Capture/Compare 2 interrupt + * @arg TIM_IT_CC3: Capture/Compare 3 interrupt + * @arg TIM_IT_CC4: Capture/Compare 4 interrupt + * @arg TIM_IT_COM: Commutation interrupt + * @arg TIM_IT_TRIGGER: Trigger interrupt + * @arg TIM_IT_BREAK: Break interrupt + * @retval None + */ +#define __HAL_TIM_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->DIER &= ~(__INTERRUPT__)) + +/** @brief Enable the specified DMA request. + * @param __HANDLE__ specifies the TIM Handle. + * @param __DMA__ specifies the TIM DMA request to enable. + * This parameter can be one of the following values: + * @arg TIM_DMA_UPDATE: Update DMA request + * @arg TIM_DMA_CC1: Capture/Compare 1 DMA request + * @arg TIM_DMA_CC2: Capture/Compare 2 DMA request + * @arg TIM_DMA_CC3: Capture/Compare 3 DMA request + * @arg TIM_DMA_CC4: Capture/Compare 4 DMA request + * @arg TIM_DMA_COM: Commutation DMA request + * @arg TIM_DMA_TRIGGER: Trigger DMA request + * @retval None + */ +#define __HAL_TIM_ENABLE_DMA(__HANDLE__, __DMA__) ((__HANDLE__)->Instance->DIER |= (__DMA__)) + +/** @brief Disable the specified DMA request. + * @param __HANDLE__ specifies the TIM Handle. + * @param __DMA__ specifies the TIM DMA request to disable. + * This parameter can be one of the following values: + * @arg TIM_DMA_UPDATE: Update DMA request + * @arg TIM_DMA_CC1: Capture/Compare 1 DMA request + * @arg TIM_DMA_CC2: Capture/Compare 2 DMA request + * @arg TIM_DMA_CC3: Capture/Compare 3 DMA request + * @arg TIM_DMA_CC4: Capture/Compare 4 DMA request + * @arg TIM_DMA_COM: Commutation DMA request + * @arg TIM_DMA_TRIGGER: Trigger DMA request + * @retval None + */ +#define __HAL_TIM_DISABLE_DMA(__HANDLE__, __DMA__) ((__HANDLE__)->Instance->DIER &= ~(__DMA__)) + +/** @brief Check whether the specified TIM interrupt flag is set or not. + * @param __HANDLE__ specifies the TIM Handle. + * @param __FLAG__ specifies the TIM interrupt flag to check. + * This parameter can be one of the following values: + * @arg TIM_FLAG_UPDATE: Update interrupt flag + * @arg TIM_FLAG_CC1: Capture/Compare 1 interrupt flag + * @arg TIM_FLAG_CC2: Capture/Compare 2 interrupt flag + * @arg TIM_FLAG_CC3: Capture/Compare 3 interrupt flag + * @arg TIM_FLAG_CC4: Capture/Compare 4 interrupt flag + * @arg TIM_FLAG_CC5: Compare 5 interrupt flag + * @arg TIM_FLAG_CC6: Compare 6 interrupt flag + * @arg TIM_FLAG_COM: Commutation interrupt flag + * @arg TIM_FLAG_TRIGGER: Trigger interrupt flag + * @arg TIM_FLAG_BREAK: Break interrupt flag + * @arg TIM_FLAG_BREAK2: Break 2 interrupt flag + * @arg TIM_FLAG_SYSTEM_BREAK: System Break interrupt flag + * @arg TIM_FLAG_CC1OF: Capture/Compare 1 overcapture flag + * @arg TIM_FLAG_CC2OF: Capture/Compare 2 overcapture flag + * @arg TIM_FLAG_CC3OF: Capture/Compare 3 overcapture flag + * @arg TIM_FLAG_CC4OF: Capture/Compare 4 overcapture flag + * @retval The new state of __FLAG__ (TRUE or FALSE). + */ +#define __HAL_TIM_GET_FLAG(__HANDLE__, __FLAG__) (((__HANDLE__)->Instance->SR &(__FLAG__)) == (__FLAG__)) + +/** @brief Clear the specified TIM interrupt flag. + * @param __HANDLE__ specifies the TIM Handle. + * @param __FLAG__ specifies the TIM interrupt flag to clear. + * This parameter can be one of the following values: + * @arg TIM_FLAG_UPDATE: Update interrupt flag + * @arg TIM_FLAG_CC1: Capture/Compare 1 interrupt flag + * @arg TIM_FLAG_CC2: Capture/Compare 2 interrupt flag + * @arg TIM_FLAG_CC3: Capture/Compare 3 interrupt flag + * @arg TIM_FLAG_CC4: Capture/Compare 4 interrupt flag + * @arg TIM_FLAG_CC5: Compare 5 interrupt flag + * @arg TIM_FLAG_CC6: Compare 6 interrupt flag + * @arg TIM_FLAG_COM: Commutation interrupt flag + * @arg TIM_FLAG_TRIGGER: Trigger interrupt flag + * @arg TIM_FLAG_BREAK: Break interrupt flag + * @arg TIM_FLAG_BREAK2: Break 2 interrupt flag + * @arg TIM_FLAG_SYSTEM_BREAK: System Break interrupt flag + * @arg TIM_FLAG_CC1OF: Capture/Compare 1 overcapture flag + * @arg TIM_FLAG_CC2OF: Capture/Compare 2 overcapture flag + * @arg TIM_FLAG_CC3OF: Capture/Compare 3 overcapture flag + * @arg TIM_FLAG_CC4OF: Capture/Compare 4 overcapture flag + * @retval The new state of __FLAG__ (TRUE or FALSE). + */ +#define __HAL_TIM_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->SR = ~(__FLAG__)) + +/** + * @brief Check whether the specified TIM interrupt source is enabled or not. + * @param __HANDLE__ TIM handle + * @param __INTERRUPT__ specifies the TIM interrupt source to check. + * This parameter can be one of the following values: + * @arg TIM_IT_UPDATE: Update interrupt + * @arg TIM_IT_CC1: Capture/Compare 1 interrupt + * @arg TIM_IT_CC2: Capture/Compare 2 interrupt + * @arg TIM_IT_CC3: Capture/Compare 3 interrupt + * @arg TIM_IT_CC4: Capture/Compare 4 interrupt + * @arg TIM_IT_COM: Commutation interrupt + * @arg TIM_IT_TRIGGER: Trigger interrupt + * @arg TIM_IT_BREAK: Break interrupt + * @retval The state of TIM_IT (SET or RESET). + */ +#define __HAL_TIM_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) ((((__HANDLE__)->Instance->DIER & (__INTERRUPT__)) == (__INTERRUPT__)) ? SET : RESET) + +/** @brief Clear the TIM interrupt pending bits. + * @param __HANDLE__ TIM handle + * @param __INTERRUPT__ specifies the interrupt pending bit to clear. + * This parameter can be one of the following values: + * @arg TIM_IT_UPDATE: Update interrupt + * @arg TIM_IT_CC1: Capture/Compare 1 interrupt + * @arg TIM_IT_CC2: Capture/Compare 2 interrupt + * @arg TIM_IT_CC3: Capture/Compare 3 interrupt + * @arg TIM_IT_CC4: Capture/Compare 4 interrupt + * @arg TIM_IT_COM: Commutation interrupt + * @arg TIM_IT_TRIGGER: Trigger interrupt + * @arg TIM_IT_BREAK: Break interrupt + * @retval None + */ +#define __HAL_TIM_CLEAR_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->SR = ~(__INTERRUPT__)) + +/** + * @brief Indicates whether or not the TIM Counter is used as downcounter. + * @param __HANDLE__ TIM handle. + * @retval False (Counter used as upcounter) or True (Counter used as downcounter) + * @note This macro is particularly useful to get the counting mode when the timer operates in Center-aligned mode or Encoder +mode. + */ +#define __HAL_TIM_IS_TIM_COUNTING_DOWN(__HANDLE__) (((__HANDLE__)->Instance->CR1 &(TIM_CR1_DIR)) == (TIM_CR1_DIR)) + + +/** + * @brief Set the TIM Prescaler on runtime. + * @param __HANDLE__ TIM handle. + * @param __PRESC__ specifies the Prescaler new value. + * @retval None + */ +#define __HAL_TIM_SET_PRESCALER(__HANDLE__, __PRESC__) ((__HANDLE__)->Instance->PSC = (__PRESC__)) + +/** + * @brief Set the TIM Counter Register value on runtime. + * @param __HANDLE__ TIM handle. + * @param __COUNTER__ specifies the Counter register new value. + * @retval None + */ +#define __HAL_TIM_SET_COUNTER(__HANDLE__, __COUNTER__) ((__HANDLE__)->Instance->CNT = (__COUNTER__)) + +/** + * @brief Get the TIM Counter Register value on runtime. + * @param __HANDLE__ TIM handle. + * @retval 16-bit or 32-bit value of the timer counter register (TIMx_CNT) + */ +#define __HAL_TIM_GET_COUNTER(__HANDLE__) \ + ((__HANDLE__)->Instance->CNT) + +/** + * @brief Set the TIM Autoreload Register value on runtime without calling another time any Init function. + * @param __HANDLE__ TIM handle. + * @param __AUTORELOAD__ specifies the Counter register new value. + * @retval None + */ +#define __HAL_TIM_SET_AUTORELOAD(__HANDLE__, __AUTORELOAD__) \ + do{ \ + (__HANDLE__)->Instance->ARR = (__AUTORELOAD__); \ + (__HANDLE__)->Init.Period = (__AUTORELOAD__); \ + } while(0) + +/** + * @brief Get the TIM Autoreload Register value on runtime. + * @param __HANDLE__ TIM handle. + * @retval 16-bit or 32-bit value of the timer auto-reload register(TIMx_ARR) + */ +#define __HAL_TIM_GET_AUTORELOAD(__HANDLE__) \ + ((__HANDLE__)->Instance->ARR) + +/** + * @brief Set the TIM Clock Division value on runtime without calling another time any Init function. + * @param __HANDLE__ TIM handle. + * @param __CKD__ specifies the clock division value. + * This parameter can be one of the following value: + * @arg TIM_CLOCKDIVISION_DIV1: tDTS=tCK_INT + * @arg TIM_CLOCKDIVISION_DIV2: tDTS=2*tCK_INT + * @arg TIM_CLOCKDIVISION_DIV4: tDTS=4*tCK_INT + * @retval None + */ +#define __HAL_TIM_SET_CLOCKDIVISION(__HANDLE__, __CKD__) \ + do{ \ + (__HANDLE__)->Instance->CR1 &= (uint16_t)(~TIM_CR1_CKD); \ + (__HANDLE__)->Instance->CR1 |= (__CKD__); \ + (__HANDLE__)->Init.ClockDivision = (__CKD__); \ + } while(0) + +/** + * @brief Get the TIM Clock Division value on runtime. + * @param __HANDLE__ TIM handle. + * @retval The clock division can be one of the following values: + * @arg TIM_CLOCKDIVISION_DIV1: tDTS=tCK_INT + * @arg TIM_CLOCKDIVISION_DIV2: tDTS=2*tCK_INT + * @arg TIM_CLOCKDIVISION_DIV4: tDTS=4*tCK_INT + */ +#define __HAL_TIM_GET_CLOCKDIVISION(__HANDLE__) \ + ((__HANDLE__)->Instance->CR1 & TIM_CR1_CKD) + +/** + * @brief Set the TIM Input Capture prescaler on runtime without calling another time HAL_TIM_IC_ConfigChannel() function. + * @param __HANDLE__ TIM handle. + * @param __CHANNEL__ TIM Channels to be configured. + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @param __ICPSC__ specifies the Input Capture4 prescaler new value. + * This parameter can be one of the following values: + * @arg TIM_ICPSC_DIV1: no prescaler + * @arg TIM_ICPSC_DIV2: capture is done once every 2 events + * @arg TIM_ICPSC_DIV4: capture is done once every 4 events + * @arg TIM_ICPSC_DIV8: capture is done once every 8 events + * @retval None + */ +#define __HAL_TIM_SET_ICPRESCALER(__HANDLE__, __CHANNEL__, __ICPSC__) \ + do{ \ + TIM_RESET_ICPRESCALERVALUE((__HANDLE__), (__CHANNEL__)); \ + TIM_SET_ICPRESCALERVALUE((__HANDLE__), (__CHANNEL__), (__ICPSC__)); \ + } while(0) + +/** + * @brief Get the TIM Input Capture prescaler on runtime. + * @param __HANDLE__ TIM handle. + * @param __CHANNEL__ TIM Channels to be configured. + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: get input capture 1 prescaler value + * @arg TIM_CHANNEL_2: get input capture 2 prescaler value + * @arg TIM_CHANNEL_3: get input capture 3 prescaler value + * @arg TIM_CHANNEL_4: get input capture 4 prescaler value + * @retval The input capture prescaler can be one of the following values: + * @arg TIM_ICPSC_DIV1: no prescaler + * @arg TIM_ICPSC_DIV2: capture is done once every 2 events + * @arg TIM_ICPSC_DIV4: capture is done once every 4 events + * @arg TIM_ICPSC_DIV8: capture is done once every 8 events + */ +#define __HAL_TIM_GET_ICPRESCALER(__HANDLE__, __CHANNEL__) \ + (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCMR1 & TIM_CCMR1_IC1PSC) :\ + ((__CHANNEL__) == TIM_CHANNEL_2) ? (((__HANDLE__)->Instance->CCMR1 & TIM_CCMR1_IC2PSC) >> 8) :\ + ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCMR2 & TIM_CCMR2_IC3PSC) :\ + (((__HANDLE__)->Instance->CCMR2 & TIM_CCMR2_IC4PSC)) >> 8) + +/** + * @brief Set the TIM Capture Compare Register value on runtime without calling another time ConfigChannel function. + * @param __HANDLE__ TIM handle. + * @param __CHANNEL__ TIM Channels to be configured. + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @arg TIM_CHANNEL_5: TIM Channel 5 selected + * @arg TIM_CHANNEL_6: TIM Channel 6 selected + * @param __COMPARE__ specifies the Capture Compare register new value. + * @retval None + */ +#define __HAL_TIM_SET_COMPARE(__HANDLE__, __CHANNEL__, __COMPARE__) \ +(((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCR1 = (__COMPARE__)) :\ + ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCR2 = (__COMPARE__)) :\ + ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCR3 = (__COMPARE__)) :\ + ((__CHANNEL__) == TIM_CHANNEL_4) ? ((__HANDLE__)->Instance->CCR4 = (__COMPARE__)) :\ + ((__CHANNEL__) == TIM_CHANNEL_5) ? ((__HANDLE__)->Instance->CCR5 = (__COMPARE__)) :\ + ((__HANDLE__)->Instance->CCR6 = (__COMPARE__))) + +/** + * @brief Get the TIM Capture Compare Register value on runtime. + * @param __HANDLE__ TIM handle. + * @param __CHANNEL__ TIM Channel associated with the capture compare register + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: get capture/compare 1 register value + * @arg TIM_CHANNEL_2: get capture/compare 2 register value + * @arg TIM_CHANNEL_3: get capture/compare 3 register value + * @arg TIM_CHANNEL_4: get capture/compare 4 register value + * @arg TIM_CHANNEL_5: get capture/compare 5 register value + * @arg TIM_CHANNEL_6: get capture/compare 6 register value + * @retval 16-bit or 32-bit value of the capture/compare register (TIMx_CCRy) + */ +#define __HAL_TIM_GET_COMPARE(__HANDLE__, __CHANNEL__) \ +(((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCR1) :\ + ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCR2) :\ + ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCR3) :\ + ((__CHANNEL__) == TIM_CHANNEL_4) ? ((__HANDLE__)->Instance->CCR4) :\ + ((__CHANNEL__) == TIM_CHANNEL_5) ? ((__HANDLE__)->Instance->CCR5) :\ + ((__HANDLE__)->Instance->CCR6)) + +/** + * @brief Set the TIM Output compare preload. + * @param __HANDLE__ TIM handle. + * @param __CHANNEL__ TIM Channels to be configured. + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @arg TIM_CHANNEL_5: TIM Channel 5 selected + * @arg TIM_CHANNEL_6: TIM Channel 6 selected + * @retval None + */ +#define __HAL_TIM_ENABLE_OCxPRELOAD(__HANDLE__, __CHANNEL__) \ + (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCMR1 |= TIM_CCMR1_OC1PE) :\ + ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCMR1 |= TIM_CCMR1_OC2PE) :\ + ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCMR2 |= TIM_CCMR2_OC3PE) :\ + ((__CHANNEL__) == TIM_CHANNEL_4) ? ((__HANDLE__)->Instance->CCMR2 |= TIM_CCMR2_OC4PE) :\ + ((__CHANNEL__) == TIM_CHANNEL_5) ? ((__HANDLE__)->Instance->CCMR3 |= TIM_CCMR3_OC5PE) :\ + ((__HANDLE__)->Instance->CCMR3 |= TIM_CCMR3_OC6PE)) + +/** + * @brief Reset the TIM Output compare preload. + * @param __HANDLE__ TIM handle. + * @param __CHANNEL__ TIM Channels to be configured. + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @arg TIM_CHANNEL_5: TIM Channel 5 selected + * @arg TIM_CHANNEL_6: TIM Channel 6 selected + * @retval None + */ +#define __HAL_TIM_DISABLE_OCxPRELOAD(__HANDLE__, __CHANNEL__) \ + (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCMR1 &= (uint16_t)~TIM_CCMR1_OC1PE) :\ + ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCMR1 &= (uint16_t)~TIM_CCMR1_OC2PE) :\ + ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCMR2 &= (uint16_t)~TIM_CCMR2_OC3PE) :\ + ((__CHANNEL__) == TIM_CHANNEL_4) ? ((__HANDLE__)->Instance->CCMR2 &= (uint16_t)~TIM_CCMR2_OC4PE) :\ + ((__CHANNEL__) == TIM_CHANNEL_5) ? ((__HANDLE__)->Instance->CCMR3 &= (uint16_t)~TIM_CCMR3_OC5PE) :\ + ((__HANDLE__)->Instance->CCMR3 &= (uint16_t)~TIM_CCMR3_OC6PE)) + +/** + * @brief Set the Update Request Source (URS) bit of the TIMx_CR1 register. + * @param __HANDLE__ TIM handle. + * @note When the USR bit of the TIMx_CR1 register is set, only counter + * overflow/underflow generates an update interrupt or DMA request (if + * enabled) + * @retval None + */ +#define __HAL_TIM_URS_ENABLE(__HANDLE__) \ + ((__HANDLE__)->Instance->CR1|= (TIM_CR1_URS)) + +/** + * @brief Reset the Update Request Source (URS) bit of the TIMx_CR1 register. + * @param __HANDLE__ TIM handle. + * @note When the USR bit of the TIMx_CR1 register is reset, any of the + * following events generate an update interrupt or DMA request (if + * enabled): + * _ Counter overflow underflow + * _ Setting the UG bit + * _ Update generation through the slave mode controller + * @retval None + */ +#define __HAL_TIM_URS_DISABLE(__HANDLE__) \ + ((__HANDLE__)->Instance->CR1&=~(TIM_CR1_URS)) + +/** + * @brief Set the TIM Capture x input polarity on runtime. + * @param __HANDLE__ TIM handle. + * @param __CHANNEL__ TIM Channels to be configured. + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @param __POLARITY__ Polarity for TIx source + * @arg TIM_INPUTCHANNELPOLARITY_RISING: Rising Edge + * @arg TIM_INPUTCHANNELPOLARITY_FALLING: Falling Edge + * @arg TIM_INPUTCHANNELPOLARITY_BOTHEDGE: Rising and Falling Edge + * @retval None + */ +#define __HAL_TIM_SET_CAPTUREPOLARITY(__HANDLE__, __CHANNEL__, __POLARITY__) \ + do{ \ + TIM_RESET_CAPTUREPOLARITY((__HANDLE__), (__CHANNEL__)); \ + TIM_SET_CAPTUREPOLARITY((__HANDLE__), (__CHANNEL__), (__POLARITY__)); \ + }while(0) + +/** + * @} + */ +/* End of exported macros ----------------------------------------------------*/ + +/* Private constants ---------------------------------------------------------*/ +/** @defgroup TIM_Private_Constants TIM Private Constants + * @{ + */ +/* The counter of a timer instance is disabled only if all the CCx and CCxN + channels have been disabled */ +#define TIM_CCER_CCxE_MASK ((uint32_t)(TIM_CCER_CC1E | TIM_CCER_CC2E | TIM_CCER_CC3E | TIM_CCER_CC4E)) +#define TIM_CCER_CCxNE_MASK ((uint32_t)(TIM_CCER_CC1NE | TIM_CCER_CC2NE | TIM_CCER_CC3NE)) +/** + * @} + */ +/* End of private constants --------------------------------------------------*/ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup TIM_Private_Macros TIM Private Macros + * @{ + */ + +#define IS_TIM_CLEARINPUT_SOURCE(__MODE__) (((__MODE__) == TIM_CLEARINPUTSOURCE_ETR) || \ + ((__MODE__) == TIM_CLEARINPUTSOURCE_OCREFCLR) || \ + ((__MODE__) == TIM_CLEARINPUTSOURCE_NONE)) + +#define IS_TIM_DMA_BASE(__BASE__) (((__BASE__) == TIM_DMABASE_CR1) || \ + ((__BASE__) == TIM_DMABASE_CR2) || \ + ((__BASE__) == TIM_DMABASE_SMCR) || \ + ((__BASE__) == TIM_DMABASE_DIER) || \ + ((__BASE__) == TIM_DMABASE_SR) || \ + ((__BASE__) == TIM_DMABASE_EGR) || \ + ((__BASE__) == TIM_DMABASE_CCMR1) || \ + ((__BASE__) == TIM_DMABASE_CCMR2) || \ + ((__BASE__) == TIM_DMABASE_CCER) || \ + ((__BASE__) == TIM_DMABASE_CNT) || \ + ((__BASE__) == TIM_DMABASE_PSC) || \ + ((__BASE__) == TIM_DMABASE_ARR) || \ + ((__BASE__) == TIM_DMABASE_RCR) || \ + ((__BASE__) == TIM_DMABASE_CCR1) || \ + ((__BASE__) == TIM_DMABASE_CCR2) || \ + ((__BASE__) == TIM_DMABASE_CCR3) || \ + ((__BASE__) == TIM_DMABASE_CCR4) || \ + ((__BASE__) == TIM_DMABASE_BDTR) || \ + ((__BASE__) == TIM_DMABASE_CCMR3) || \ + ((__BASE__) == TIM_DMABASE_CCR5) || \ + ((__BASE__) == TIM_DMABASE_CCR6) || \ + ((__BASE__) == TIM_DMABASE_OR1) || \ + ((__BASE__) == TIM_DMABASE_OR2) || \ + ((__BASE__) == TIM_DMABASE_OR3)) + + +#define IS_TIM_EVENT_SOURCE(__SOURCE__) ((((__SOURCE__) & 0xFFFFFE00U) == 0x00000000U) && ((__SOURCE__) != 0x00000000U)) + + +#define IS_TIM_COUNTER_MODE(__MODE__) (((__MODE__) == TIM_COUNTERMODE_UP) || \ + ((__MODE__) == TIM_COUNTERMODE_DOWN) || \ + ((__MODE__) == TIM_COUNTERMODE_CENTERALIGNED1) || \ + ((__MODE__) == TIM_COUNTERMODE_CENTERALIGNED2) || \ + ((__MODE__) == TIM_COUNTERMODE_CENTERALIGNED3)) + +#define IS_TIM_CLOCKDIVISION_DIV(__DIV__) (((__DIV__) == TIM_CLOCKDIVISION_DIV1) || \ + ((__DIV__) == TIM_CLOCKDIVISION_DIV2) || \ + ((__DIV__) == TIM_CLOCKDIVISION_DIV4)) + +#define IS_TIM_AUTORELOAD_PRELOAD(PRELOAD) (((PRELOAD) == TIM_AUTORELOAD_PRELOAD_DISABLE) || \ + ((PRELOAD) == TIM_AUTORELOAD_PRELOAD_ENABLE)) + +#define IS_TIM_FAST_STATE(__STATE__) (((__STATE__) == TIM_OCFAST_DISABLE) || \ + ((__STATE__) == TIM_OCFAST_ENABLE)) + +#define IS_TIM_OC_POLARITY(__POLARITY__) (((__POLARITY__) == TIM_OCPOLARITY_HIGH) || \ + ((__POLARITY__) == TIM_OCPOLARITY_LOW)) + +#define IS_TIM_OCN_POLARITY(__POLARITY__) (((__POLARITY__) == TIM_OCNPOLARITY_HIGH) || \ + ((__POLARITY__) == TIM_OCNPOLARITY_LOW)) + +#define IS_TIM_OCIDLE_STATE(__STATE__) (((__STATE__) == TIM_OCIDLESTATE_SET) || \ + ((__STATE__) == TIM_OCIDLESTATE_RESET)) + +#define IS_TIM_OCNIDLE_STATE(__STATE__) (((__STATE__) == TIM_OCNIDLESTATE_SET) || \ + ((__STATE__) == TIM_OCNIDLESTATE_RESET)) + +#define IS_TIM_IC_POLARITY(__POLARITY__) (((__POLARITY__) == TIM_ICPOLARITY_RISING) || \ + ((__POLARITY__) == TIM_ICPOLARITY_FALLING) || \ + ((__POLARITY__) == TIM_ICPOLARITY_BOTHEDGE)) + +#define IS_TIM_IC_SELECTION(__SELECTION__) (((__SELECTION__) == TIM_ICSELECTION_DIRECTTI) || \ + ((__SELECTION__) == TIM_ICSELECTION_INDIRECTTI) || \ + ((__SELECTION__) == TIM_ICSELECTION_TRC)) + +#define IS_TIM_IC_PRESCALER(__PRESCALER__) (((__PRESCALER__) == TIM_ICPSC_DIV1) || \ + ((__PRESCALER__) == TIM_ICPSC_DIV2) || \ + ((__PRESCALER__) == TIM_ICPSC_DIV4) || \ + ((__PRESCALER__) == TIM_ICPSC_DIV8)) + +#define IS_TIM_OPM_MODE(__MODE__) (((__MODE__) == TIM_OPMODE_SINGLE) || \ + ((__MODE__) == TIM_OPMODE_REPETITIVE)) + +#define IS_TIM_ENCODER_MODE(__MODE__) (((__MODE__) == TIM_ENCODERMODE_TI1) || \ + ((__MODE__) == TIM_ENCODERMODE_TI2) || \ + ((__MODE__) == TIM_ENCODERMODE_TI12)) + +#define IS_TIM_DMA_SOURCE(__SOURCE__) ((((__SOURCE__) & 0xFFFF80FFU) == 0x00000000U) && ((__SOURCE__) != 0x00000000U)) + +#define IS_TIM_CHANNELS(__CHANNEL__) (((__CHANNEL__) == TIM_CHANNEL_1) || \ + ((__CHANNEL__) == TIM_CHANNEL_2) || \ + ((__CHANNEL__) == TIM_CHANNEL_3) || \ + ((__CHANNEL__) == TIM_CHANNEL_4) || \ + ((__CHANNEL__) == TIM_CHANNEL_5) || \ + ((__CHANNEL__) == TIM_CHANNEL_6) || \ + ((__CHANNEL__) == TIM_CHANNEL_ALL)) + +#define IS_TIM_OPM_CHANNELS(__CHANNEL__) (((__CHANNEL__) == TIM_CHANNEL_1) || \ + ((__CHANNEL__) == TIM_CHANNEL_2)) + +#define IS_TIM_COMPLEMENTARY_CHANNELS(__CHANNEL__) (((__CHANNEL__) == TIM_CHANNEL_1) || \ + ((__CHANNEL__) == TIM_CHANNEL_2) || \ + ((__CHANNEL__) == TIM_CHANNEL_3)) + +#define IS_TIM_CLOCKSOURCE(__CLOCK__) (((__CLOCK__) == TIM_CLOCKSOURCE_INTERNAL) || \ + ((__CLOCK__) == TIM_CLOCKSOURCE_ETRMODE2) || \ + ((__CLOCK__) == TIM_CLOCKSOURCE_ITR0) || \ + ((__CLOCK__) == TIM_CLOCKSOURCE_ITR1) || \ + ((__CLOCK__) == TIM_CLOCKSOURCE_ITR2) || \ + ((__CLOCK__) == TIM_CLOCKSOURCE_ITR3) || \ + ((__CLOCK__) == TIM_CLOCKSOURCE_TI1ED) || \ + ((__CLOCK__) == TIM_CLOCKSOURCE_TI1) || \ + ((__CLOCK__) == TIM_CLOCKSOURCE_TI2) || \ + ((__CLOCK__) == TIM_CLOCKSOURCE_ETRMODE1)) + +#define IS_TIM_CLOCKPOLARITY(__POLARITY__) (((__POLARITY__) == TIM_CLOCKPOLARITY_INVERTED) || \ + ((__POLARITY__) == TIM_CLOCKPOLARITY_NONINVERTED) || \ + ((__POLARITY__) == TIM_CLOCKPOLARITY_RISING) || \ + ((__POLARITY__) == TIM_CLOCKPOLARITY_FALLING) || \ + ((__POLARITY__) == TIM_CLOCKPOLARITY_BOTHEDGE)) + +#define IS_TIM_CLOCKPRESCALER(__PRESCALER__) (((__PRESCALER__) == TIM_CLOCKPRESCALER_DIV1) || \ + ((__PRESCALER__) == TIM_CLOCKPRESCALER_DIV2) || \ + ((__PRESCALER__) == TIM_CLOCKPRESCALER_DIV4) || \ + ((__PRESCALER__) == TIM_CLOCKPRESCALER_DIV8)) + +#define IS_TIM_CLOCKFILTER(ICFILTER) ((ICFILTER) <= 0xF) + +#define IS_TIM_CLEARINPUT_POLARITY(__POLARITY__) (((__POLARITY__) == TIM_CLEARINPUTPOLARITY_INVERTED) || \ + ((__POLARITY__) == TIM_CLEARINPUTPOLARITY_NONINVERTED)) + +#define IS_TIM_CLEARINPUT_PRESCALER(__PRESCALER__) (((__PRESCALER__) == TIM_CLEARINPUTPRESCALER_DIV1) || \ + ((__PRESCALER__) == TIM_CLEARINPUTPRESCALER_DIV2) || \ + ((__PRESCALER__) == TIM_CLEARINPUTPRESCALER_DIV4) || \ + ((__PRESCALER__) == TIM_CLEARINPUTPRESCALER_DIV8)) + +#define IS_TIM_CLEARINPUT_FILTER(__ICFILTER__) ((__ICFILTER__) <= 0xF) + + +#define IS_TIM_OSSR_STATE(__STATE__) (((__STATE__) == TIM_OSSR_ENABLE) || \ + ((__STATE__) == TIM_OSSR_DISABLE)) + +#define IS_TIM_OSSI_STATE(__STATE__) (((__STATE__) == TIM_OSSI_ENABLE) || \ + ((__STATE__) == TIM_OSSI_DISABLE)) + +#define IS_TIM_LOCK_LEVEL(__LEVEL__) (((__LEVEL__) == TIM_LOCKLEVEL_OFF) || \ + ((__LEVEL__) == TIM_LOCKLEVEL_1) || \ + ((__LEVEL__) == TIM_LOCKLEVEL_2) || \ + ((__LEVEL__) == TIM_LOCKLEVEL_3)) + +#define IS_TIM_BREAK_FILTER(__BRKFILTER__) ((__BRKFILTER__) <= 0xF) + + +#define IS_TIM_BREAK_STATE(__STATE__) (((__STATE__) == TIM_BREAK_ENABLE) || \ + ((__STATE__) == TIM_BREAK_DISABLE)) + +#define IS_TIM_BREAK_POLARITY(__POLARITY__) (((__POLARITY__) == TIM_BREAKPOLARITY_LOW) || \ + ((__POLARITY__) == TIM_BREAKPOLARITY_HIGH)) + +#define IS_TIM_BREAK2_STATE(__STATE__) (((__STATE__) == TIM_BREAK2_ENABLE) || \ + ((__STATE__) == TIM_BREAK2_DISABLE)) + +#define IS_TIM_BREAK2_POLARITY(__POLARITY__) (((__POLARITY__) == TIM_BREAK2POLARITY_LOW) || \ + ((__POLARITY__) == TIM_BREAK2POLARITY_HIGH)) + +#define IS_TIM_AUTOMATIC_OUTPUT_STATE(__STATE__) (((__STATE__) == TIM_AUTOMATICOUTPUT_ENABLE) || \ + ((__STATE__) == TIM_AUTOMATICOUTPUT_DISABLE)) + +#define IS_TIM_GROUPCH5(__OCREF__) ((((__OCREF__) & 0x1FFFFFFF) == 0x00000000)) + +#define IS_TIM_TRGO_SOURCE(__SOURCE__) (((__SOURCE__) == TIM_TRGO_RESET) || \ + ((__SOURCE__) == TIM_TRGO_ENABLE) || \ + ((__SOURCE__) == TIM_TRGO_UPDATE) || \ + ((__SOURCE__) == TIM_TRGO_OC1) || \ + ((__SOURCE__) == TIM_TRGO_OC1REF) || \ + ((__SOURCE__) == TIM_TRGO_OC2REF) || \ + ((__SOURCE__) == TIM_TRGO_OC3REF) || \ + ((__SOURCE__) == TIM_TRGO_OC4REF)) + +#define IS_TIM_TRGO2_SOURCE(__SOURCE__) (((__SOURCE__) == TIM_TRGO2_RESET) || \ + ((__SOURCE__) == TIM_TRGO2_ENABLE) || \ + ((__SOURCE__) == TIM_TRGO2_UPDATE) || \ + ((__SOURCE__) == TIM_TRGO2_OC1) || \ + ((__SOURCE__) == TIM_TRGO2_OC1REF) || \ + ((__SOURCE__) == TIM_TRGO2_OC2REF) || \ + ((__SOURCE__) == TIM_TRGO2_OC3REF) || \ + ((__SOURCE__) == TIM_TRGO2_OC3REF) || \ + ((__SOURCE__) == TIM_TRGO2_OC4REF) || \ + ((__SOURCE__) == TIM_TRGO2_OC5REF) || \ + ((__SOURCE__) == TIM_TRGO2_OC6REF) || \ + ((__SOURCE__) == TIM_TRGO2_OC4REF_RISINGFALLING) || \ + ((__SOURCE__) == TIM_TRGO2_OC6REF_RISINGFALLING) || \ + ((__SOURCE__) == TIM_TRGO2_OC4REF_RISING_OC6REF_RISING) || \ + ((__SOURCE__) == TIM_TRGO2_OC4REF_RISING_OC6REF_FALLING) || \ + ((__SOURCE__) == TIM_TRGO2_OC5REF_RISING_OC6REF_RISING) || \ + ((__SOURCE__) == TIM_TRGO2_OC5REF_RISING_OC6REF_FALLING)) + +#define IS_TIM_MSM_STATE(__STATE__) (((__STATE__) == TIM_MASTERSLAVEMODE_ENABLE) || \ + ((__STATE__) == TIM_MASTERSLAVEMODE_DISABLE)) + +#define IS_TIM_SLAVE_MODE(__MODE__) (((__MODE__) == TIM_SLAVEMODE_DISABLE) || \ + ((__MODE__) == TIM_SLAVEMODE_RESET) || \ + ((__MODE__) == TIM_SLAVEMODE_GATED) || \ + ((__MODE__) == TIM_SLAVEMODE_TRIGGER) || \ + ((__MODE__) == TIM_SLAVEMODE_EXTERNAL1) || \ + ((__MODE__) == TIM_SLAVEMODE_COMBINED_RESETTRIGGER)) + +#define IS_TIM_PWM_MODE(__MODE__) (((__MODE__) == TIM_OCMODE_PWM1) || \ + ((__MODE__) == TIM_OCMODE_PWM2) || \ + ((__MODE__) == TIM_OCMODE_COMBINED_PWM1) || \ + ((__MODE__) == TIM_OCMODE_COMBINED_PWM2) || \ + ((__MODE__) == TIM_OCMODE_ASSYMETRIC_PWM1) || \ + ((__MODE__) == TIM_OCMODE_ASSYMETRIC_PWM2)) + +#define IS_TIM_OC_MODE(__MODE__) (((__MODE__) == TIM_OCMODE_TIMING) || \ + ((__MODE__) == TIM_OCMODE_ACTIVE) || \ + ((__MODE__) == TIM_OCMODE_INACTIVE) || \ + ((__MODE__) == TIM_OCMODE_TOGGLE) || \ + ((__MODE__) == TIM_OCMODE_FORCED_ACTIVE) || \ + ((__MODE__) == TIM_OCMODE_FORCED_INACTIVE) || \ + ((__MODE__) == TIM_OCMODE_RETRIGERRABLE_OPM1) || \ + ((__MODE__) == TIM_OCMODE_RETRIGERRABLE_OPM2)) + +#define IS_TIM_TRIGGER_SELECTION(__SELECTION__) (((__SELECTION__) == TIM_TS_ITR0) || \ + ((__SELECTION__) == TIM_TS_ITR1) || \ + ((__SELECTION__) == TIM_TS_ITR2) || \ + ((__SELECTION__) == TIM_TS_ITR3) || \ + ((__SELECTION__) == TIM_TS_TI1F_ED) || \ + ((__SELECTION__) == TIM_TS_TI1FP1) || \ + ((__SELECTION__) == TIM_TS_TI2FP2) || \ + ((__SELECTION__) == TIM_TS_ETRF)) + +#define IS_TIM_INTERNAL_TRIGGEREVENT_SELECTION(__SELECTION__) (((__SELECTION__) == TIM_TS_ITR0) || \ + ((__SELECTION__) == TIM_TS_ITR1) || \ + ((__SELECTION__) == TIM_TS_ITR2) || \ + ((__SELECTION__) == TIM_TS_ITR3) || \ + ((__SELECTION__) == TIM_TS_NONE)) + + +#define IS_TIM_TRIGGERPOLARITY(__POLARITY__) (((__POLARITY__) == TIM_TRIGGERPOLARITY_INVERTED ) || \ + ((__POLARITY__) == TIM_TRIGGERPOLARITY_NONINVERTED) || \ + ((__POLARITY__) == TIM_TRIGGERPOLARITY_RISING ) || \ + ((__POLARITY__) == TIM_TRIGGERPOLARITY_FALLING ) || \ + ((__POLARITY__) == TIM_TRIGGERPOLARITY_BOTHEDGE )) + +#define IS_TIM_TRIGGERPRESCALER(__PRESCALER__) (((__PRESCALER__) == TIM_TRIGGERPRESCALER_DIV1) || \ + ((__PRESCALER__) == TIM_TRIGGERPRESCALER_DIV2) || \ + ((__PRESCALER__) == TIM_TRIGGERPRESCALER_DIV4) || \ + ((__PRESCALER__) == TIM_TRIGGERPRESCALER_DIV8)) + +#define IS_TIM_TRIGGERFILTER(__ICFILTER__) ((__ICFILTER__) <= 0xF) + +#define IS_TIM_TI1SELECTION(__TI1SELECTION__) (((__TI1SELECTION__) == TIM_TI1SELECTION_CH1) || \ + ((__TI1SELECTION__) == TIM_TI1SELECTION_XORCOMBINATION)) + +#define IS_TIM_DMA_LENGTH(__LENGTH__) (((__LENGTH__) == TIM_DMABURSTLENGTH_1TRANSFER) || \ + ((__LENGTH__) == TIM_DMABURSTLENGTH_2TRANSFERS) || \ + ((__LENGTH__) == TIM_DMABURSTLENGTH_3TRANSFERS) || \ + ((__LENGTH__) == TIM_DMABURSTLENGTH_4TRANSFERS) || \ + ((__LENGTH__) == TIM_DMABURSTLENGTH_5TRANSFERS) || \ + ((__LENGTH__) == TIM_DMABURSTLENGTH_6TRANSFERS) || \ + ((__LENGTH__) == TIM_DMABURSTLENGTH_7TRANSFERS) || \ + ((__LENGTH__) == TIM_DMABURSTLENGTH_8TRANSFERS) || \ + ((__LENGTH__) == TIM_DMABURSTLENGTH_9TRANSFERS) || \ + ((__LENGTH__) == TIM_DMABURSTLENGTH_10TRANSFERS) || \ + ((__LENGTH__) == TIM_DMABURSTLENGTH_11TRANSFERS) || \ + ((__LENGTH__) == TIM_DMABURSTLENGTH_12TRANSFERS) || \ + ((__LENGTH__) == TIM_DMABURSTLENGTH_13TRANSFERS) || \ + ((__LENGTH__) == TIM_DMABURSTLENGTH_14TRANSFERS) || \ + ((__LENGTH__) == TIM_DMABURSTLENGTH_15TRANSFERS) || \ + ((__LENGTH__) == TIM_DMABURSTLENGTH_16TRANSFERS) || \ + ((__LENGTH__) == TIM_DMABURSTLENGTH_17TRANSFERS) || \ + ((__LENGTH__) == TIM_DMABURSTLENGTH_18TRANSFERS)) + +#define IS_TIM_IC_FILTER(__ICFILTER__) ((__ICFILTER__) <= 0xF) + +#define IS_TIM_DEADTIME(__DEADTIME__) ((__DEADTIME__) <= 0xFF) + +#define IS_TIM_BREAK_SYSTEM(__CONFIG__) (((__CONFIG__) == TIM_BREAK_SYSTEM_ECC) || \ + ((__CONFIG__) == TIM_BREAK_SYSTEM_PVD) || \ + ((__CONFIG__) == TIM_BREAK_SYSTEM_SRAM2_PARITY_ERROR) || \ + ((__CONFIG__) == TIM_BREAK_SYSTEM_LOCKUP)) + +#define TIM_SET_ICPRESCALERVALUE(__HANDLE__, __CHANNEL__, __ICPSC__) \ +(((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCMR1 |= (__ICPSC__)) :\ + ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCMR1 |= ((__ICPSC__) << 8)) :\ + ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCMR2 |= (__ICPSC__)) :\ + ((__HANDLE__)->Instance->CCMR2 |= ((__ICPSC__) << 8))) + +#define TIM_RESET_ICPRESCALERVALUE(__HANDLE__, __CHANNEL__) \ +(((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCMR1 &= (uint16_t)~TIM_CCMR1_IC1PSC) :\ + ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCMR1 &= (uint16_t)~TIM_CCMR1_IC2PSC) :\ + ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCMR2 &= (uint16_t)~TIM_CCMR2_IC3PSC) :\ + ((__HANDLE__)->Instance->CCMR2 &= (uint16_t)~TIM_CCMR2_IC4PSC)) + +#define TIM_SET_CAPTUREPOLARITY(__HANDLE__, __CHANNEL__, __POLARITY__) \ +(((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCER |= (__POLARITY__)) :\ + ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCER |= ((__POLARITY__) << 4)) :\ + ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCER |= ((__POLARITY__) << 8)) :\ + ((__HANDLE__)->Instance->CCER |= (((__POLARITY__) << 12)))) + +#define TIM_RESET_CAPTUREPOLARITY(__HANDLE__, __CHANNEL__) \ +(((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCER &= (uint16_t)~(TIM_CCER_CC1P | TIM_CCER_CC1NP)) :\ + ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCER &= (uint16_t)~(TIM_CCER_CC2P | TIM_CCER_CC2NP)) :\ + ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCER &= (uint16_t)~(TIM_CCER_CC3P | TIM_CCER_CC3NP)) :\ + ((__HANDLE__)->Instance->CCER &= (uint16_t)~(TIM_CCER_CC4P | TIM_CCER_CC4NP))) + +/** + * @} + */ +/* End of private macros -----------------------------------------------------*/ + +/* Include TIM HAL Extended module */ +#include "stm32l4xx_hal_tim_ex.h" + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup TIM_Exported_Functions TIM Exported Functions + * @{ + */ + +/** @addtogroup TIM_Exported_Functions_Group1 Time Base functions + * @brief Time Base functions + * @{ + */ +/* Time Base functions ********************************************************/ +HAL_StatusTypeDef HAL_TIM_Base_Init(TIM_HandleTypeDef *htim); +HAL_StatusTypeDef HAL_TIM_Base_DeInit(TIM_HandleTypeDef *htim); +void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim); +void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef *htim); +/* Blocking mode: Polling */ +HAL_StatusTypeDef HAL_TIM_Base_Start(TIM_HandleTypeDef *htim); +HAL_StatusTypeDef HAL_TIM_Base_Stop(TIM_HandleTypeDef *htim); +/* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim); +HAL_StatusTypeDef HAL_TIM_Base_Stop_IT(TIM_HandleTypeDef *htim); +/* Non-Blocking mode: DMA */ +HAL_StatusTypeDef HAL_TIM_Base_Start_DMA(TIM_HandleTypeDef *htim, uint32_t *pData, uint16_t Length); +HAL_StatusTypeDef HAL_TIM_Base_Stop_DMA(TIM_HandleTypeDef *htim); +/** + * @} + */ + +/** @addtogroup TIM_Exported_Functions_Group2 Time Output Compare functions + * @brief Time Output Compare functions + * @{ + */ +/* Timer Output Compare functions *********************************************/ +HAL_StatusTypeDef HAL_TIM_OC_Init(TIM_HandleTypeDef *htim); +HAL_StatusTypeDef HAL_TIM_OC_DeInit(TIM_HandleTypeDef *htim); +void HAL_TIM_OC_MspInit(TIM_HandleTypeDef *htim); +void HAL_TIM_OC_MspDeInit(TIM_HandleTypeDef *htim); +/* Blocking mode: Polling */ +HAL_StatusTypeDef HAL_TIM_OC_Start(TIM_HandleTypeDef *htim, uint32_t Channel); +HAL_StatusTypeDef HAL_TIM_OC_Stop(TIM_HandleTypeDef *htim, uint32_t Channel); +/* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_TIM_OC_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel); +HAL_StatusTypeDef HAL_TIM_OC_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel); +/* Non-Blocking mode: DMA */ +HAL_StatusTypeDef HAL_TIM_OC_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length); +HAL_StatusTypeDef HAL_TIM_OC_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel); +/** + * @} + */ + +/** @addtogroup TIM_Exported_Functions_Group3 Time PWM functions + * @brief Time PWM functions + * @{ + */ +/* Timer PWM functions ********************************************************/ +HAL_StatusTypeDef HAL_TIM_PWM_Init(TIM_HandleTypeDef *htim); +HAL_StatusTypeDef HAL_TIM_PWM_DeInit(TIM_HandleTypeDef *htim); +void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim); +void HAL_TIM_PWM_MspDeInit(TIM_HandleTypeDef *htim); +/* Blocking mode: Polling */ +HAL_StatusTypeDef HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim, uint32_t Channel); +HAL_StatusTypeDef HAL_TIM_PWM_Stop(TIM_HandleTypeDef *htim, uint32_t Channel); +/* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_TIM_PWM_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel); +HAL_StatusTypeDef HAL_TIM_PWM_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel); +/* Non-Blocking mode: DMA */ +HAL_StatusTypeDef HAL_TIM_PWM_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length); +HAL_StatusTypeDef HAL_TIM_PWM_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel); +/** + * @} + */ + +/** @addtogroup TIM_Exported_Functions_Group4 Time Input Capture functions + * @brief Time Input Capture functions + * @{ + */ +/* Timer Input Capture functions **********************************************/ +HAL_StatusTypeDef HAL_TIM_IC_Init(TIM_HandleTypeDef *htim); +HAL_StatusTypeDef HAL_TIM_IC_DeInit(TIM_HandleTypeDef *htim); +void HAL_TIM_IC_MspInit(TIM_HandleTypeDef *htim); +void HAL_TIM_IC_MspDeInit(TIM_HandleTypeDef *htim); +/* Blocking mode: Polling */ +HAL_StatusTypeDef HAL_TIM_IC_Start(TIM_HandleTypeDef *htim, uint32_t Channel); +HAL_StatusTypeDef HAL_TIM_IC_Stop(TIM_HandleTypeDef *htim, uint32_t Channel); +/* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_TIM_IC_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel); +HAL_StatusTypeDef HAL_TIM_IC_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel); +/* Non-Blocking mode: DMA */ +HAL_StatusTypeDef HAL_TIM_IC_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length); +HAL_StatusTypeDef HAL_TIM_IC_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel); +/** + * @} + */ + +/** @addtogroup TIM_Exported_Functions_Group5 Time One Pulse functions + * @brief Time One Pulse functions + * @{ + */ +/* Timer One Pulse functions **************************************************/ +HAL_StatusTypeDef HAL_TIM_OnePulse_Init(TIM_HandleTypeDef *htim, uint32_t OnePulseMode); +HAL_StatusTypeDef HAL_TIM_OnePulse_DeInit(TIM_HandleTypeDef *htim); +void HAL_TIM_OnePulse_MspInit(TIM_HandleTypeDef *htim); +void HAL_TIM_OnePulse_MspDeInit(TIM_HandleTypeDef *htim); +/* Blocking mode: Polling */ +HAL_StatusTypeDef HAL_TIM_OnePulse_Start(TIM_HandleTypeDef *htim, uint32_t OutputChannel); +HAL_StatusTypeDef HAL_TIM_OnePulse_Stop(TIM_HandleTypeDef *htim, uint32_t OutputChannel); +/* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_TIM_OnePulse_Start_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel); +HAL_StatusTypeDef HAL_TIM_OnePulse_Stop_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel); +/** + * @} + */ + +/** @addtogroup TIM_Exported_Functions_Group6 Time Encoder functions + * @brief Time Encoder functions + * @{ + */ +/* Timer Encoder functions ****************************************************/ +HAL_StatusTypeDef HAL_TIM_Encoder_Init(TIM_HandleTypeDef *htim, TIM_Encoder_InitTypeDef* sConfig); +HAL_StatusTypeDef HAL_TIM_Encoder_DeInit(TIM_HandleTypeDef *htim); +void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef *htim); +void HAL_TIM_Encoder_MspDeInit(TIM_HandleTypeDef *htim); + /* Blocking mode: Polling */ +HAL_StatusTypeDef HAL_TIM_Encoder_Start(TIM_HandleTypeDef *htim, uint32_t Channel); +HAL_StatusTypeDef HAL_TIM_Encoder_Stop(TIM_HandleTypeDef *htim, uint32_t Channel); +/* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_TIM_Encoder_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel); +HAL_StatusTypeDef HAL_TIM_Encoder_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel); +/* Non-Blocking mode: DMA */ +HAL_StatusTypeDef HAL_TIM_Encoder_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData1, uint32_t *pData2, uint16_t Length); +HAL_StatusTypeDef HAL_TIM_Encoder_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel); +/** + * @} + */ + +/** @addtogroup TIM_Exported_Functions_Group7 TIM IRQ handler management + * @brief IRQ handler management + * @{ + */ +/* Interrupt Handler functions ***********************************************/ +void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim); +/** + * @} + */ + +/** @defgroup TIM_Exported_Functions_Group8 Peripheral Control functions + * @brief Peripheral Control functions + * @{ + */ +/* Control functions *********************************************************/ +HAL_StatusTypeDef HAL_TIM_OC_ConfigChannel(TIM_HandleTypeDef *htim, TIM_OC_InitTypeDef* sConfig, uint32_t Channel); +HAL_StatusTypeDef HAL_TIM_PWM_ConfigChannel(TIM_HandleTypeDef *htim, TIM_OC_InitTypeDef* sConfig, uint32_t Channel); +HAL_StatusTypeDef HAL_TIM_IC_ConfigChannel(TIM_HandleTypeDef *htim, TIM_IC_InitTypeDef* sConfig, uint32_t Channel); +HAL_StatusTypeDef HAL_TIM_OnePulse_ConfigChannel(TIM_HandleTypeDef *htim, TIM_OnePulse_InitTypeDef* sConfig, uint32_t OutputChannel, uint32_t InputChannel); +HAL_StatusTypeDef HAL_TIM_ConfigOCrefClear(TIM_HandleTypeDef *htim, TIM_ClearInputConfigTypeDef * sClearInputConfig, uint32_t Channel); +HAL_StatusTypeDef HAL_TIM_ConfigClockSource(TIM_HandleTypeDef *htim, TIM_ClockConfigTypeDef * sClockSourceConfig); +HAL_StatusTypeDef HAL_TIM_ConfigTI1Input(TIM_HandleTypeDef *htim, uint32_t TI1_Selection); +HAL_StatusTypeDef HAL_TIM_SlaveConfigSynchronization(TIM_HandleTypeDef *htim, TIM_SlaveConfigTypeDef * sSlaveConfig); +HAL_StatusTypeDef HAL_TIM_SlaveConfigSynchronization_IT(TIM_HandleTypeDef *htim, TIM_SlaveConfigTypeDef * sSlaveConfig); +HAL_StatusTypeDef HAL_TIM_DMABurst_WriteStart(TIM_HandleTypeDef *htim, uint32_t BurstBaseAddress, uint32_t BurstRequestSrc, \ + uint32_t *BurstBuffer, uint32_t BurstLength); +HAL_StatusTypeDef HAL_TIM_DMABurst_WriteStop(TIM_HandleTypeDef *htim, uint32_t BurstRequestSrc); +HAL_StatusTypeDef HAL_TIM_DMABurst_ReadStart(TIM_HandleTypeDef *htim, uint32_t BurstBaseAddress, uint32_t BurstRequestSrc, \ + uint32_t *BurstBuffer, uint32_t BurstLength); +HAL_StatusTypeDef HAL_TIM_DMABurst_ReadStop(TIM_HandleTypeDef *htim, uint32_t BurstRequestSrc); +HAL_StatusTypeDef HAL_TIM_GenerateEvent(TIM_HandleTypeDef *htim, uint32_t EventSource); +uint32_t HAL_TIM_ReadCapturedValue(TIM_HandleTypeDef *htim, uint32_t Channel); +/** + * @} + */ + +/** @defgroup TIM_Exported_Functions_Group9 TIM Callbacks functions + * @brief TIM Callbacks functions + * @{ + */ +/* Callback in non blocking modes (Interrupt and DMA) *************************/ +void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim); +void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim); +void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim); +void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim); +void HAL_TIM_TriggerCallback(TIM_HandleTypeDef *htim); +void HAL_TIM_ErrorCallback(TIM_HandleTypeDef *htim); +/** + * @} + */ + +/** @defgroup TIM_Exported_Functions_Group10 Peripheral State functions + * @brief Peripheral State functions + * @{ + */ +/* Peripheral State functions ************************************************/ +HAL_TIM_StateTypeDef HAL_TIM_Base_GetState(TIM_HandleTypeDef *htim); +HAL_TIM_StateTypeDef HAL_TIM_OC_GetState(TIM_HandleTypeDef *htim); +HAL_TIM_StateTypeDef HAL_TIM_PWM_GetState(TIM_HandleTypeDef *htim); +HAL_TIM_StateTypeDef HAL_TIM_IC_GetState(TIM_HandleTypeDef *htim); +HAL_TIM_StateTypeDef HAL_TIM_OnePulse_GetState(TIM_HandleTypeDef *htim); +HAL_TIM_StateTypeDef HAL_TIM_Encoder_GetState(TIM_HandleTypeDef *htim); +/** + * @} + */ + +/** + * @} + */ +/* End of exported functions -------------------------------------------------*/ + +/* Private functions----------------------------------------------------------*/ +/** @defgroup TIM_Private_Functions TIM Private Functions +* @{ +*/ +void TIM_Base_SetConfig(TIM_TypeDef *TIMx, TIM_Base_InitTypeDef *Structure); +void TIM_TI1_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection, uint32_t TIM_ICFilter); +void TIM_OC2_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config); +void TIM_ETR_SetConfig(TIM_TypeDef* TIMx, uint32_t TIM_ExtTRGPrescaler, + uint32_t TIM_ExtTRGPolarity, uint32_t ExtTRGFilter); + +void TIM_DMADelayPulseCplt(DMA_HandleTypeDef *hdma); +void TIM_DMAError(DMA_HandleTypeDef *hdma); +void TIM_DMACaptureCplt(DMA_HandleTypeDef *hdma); +void TIM_CCxChannelCmd(TIM_TypeDef* TIMx, uint32_t Channel, uint32_t ChannelState); +/** +* @} +*/ +/* End of private functions --------------------------------------------------*/ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_HAL_TIM_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_tim_ex.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_tim_ex.h new file mode 100644 index 0000000..eae1c9a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_tim_ex.h @@ -0,0 +1,484 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_tim_ex.h + * @author MCD Application Team + * @brief Header file of TIM HAL Extended module. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_TIM_EX_H +#define __STM32L4xx_HAL_TIM_EX_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup TIMEx + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup TIMEx_Exported_Types TIM Extended Exported Types + * @{ + */ + +/** + * @brief TIM Hall sensor Configuration Structure definition + */ + +typedef struct +{ + + uint32_t IC1Polarity; /*!< Specifies the active edge of the input signal. + This parameter can be a value of @ref TIM_Input_Capture_Polarity */ + + uint32_t IC1Prescaler; /*!< Specifies the Input Capture Prescaler. + This parameter can be a value of @ref TIM_Input_Capture_Prescaler */ + + uint32_t IC1Filter; /*!< Specifies the input capture filter. + This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */ + + uint32_t Commutation_Delay; /*!< Specifies the pulse value to be loaded into the Capture Compare Register. + This parameter can be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF */ +} TIM_HallSensor_InitTypeDef; + +/** + * @brief TIM Break/Break2 input configuration + */ +typedef struct { + uint32_t Source; /*!< Specifies the source of the timer break input. + This parameter can be a value of @ref TIMEx_Break_Input_Source */ + uint32_t Enable; /*!< Specifies whether or not the break input source is enabled. + This parameter can be a value of @ref TIMEx_Break_Input_Source_Enable */ + uint32_t Polarity; /*!< Specifies the break input source polarity. + This parameter can be a value of @ref TIMEx_Break_Input_Source_Polarity + Not relevant when analog watchdog output of the DFSDM1 used as break input source */ +} TIMEx_BreakInputConfigTypeDef; + +/** + * @} + */ +/* End of exported types -----------------------------------------------------*/ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup TIMEx_Exported_Constants TIM Extended Exported Constants + * @{ + */ + +/** @defgroup TIMEx_Remap TIM Extended Remapping + * @{ + */ +#define TIM_TIM1_ETR_ADC1_NONE ((uint32_t)(0x00000000)) /* !< TIM1_ETR is not connected to any AWD (analog watchdog)*/ +#define TIM_TIM1_ETR_ADC1_AWD1 (TIM1_OR1_ETR_ADC1_RMP_0) /* !< TIM1_ETR is connected to ADC1 AWD1 */ +#define TIM_TIM1_ETR_ADC1_AWD2 (TIM1_OR1_ETR_ADC1_RMP_1) /* !< TIM1_ETR is connected to ADC1 AWD2 */ +#define TIM_TIM1_ETR_ADC1_AWD3 (TIM1_OR1_ETR_ADC1_RMP_1 | TIM1_OR1_ETR_ADC1_RMP_0) /* !< TIM1_ETR is connected to ADC1 AWD3 */ +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) +#define TIM_TIM1_ETR_ADC3_NONE ((uint32_t)(0x00000000)) /* !< TIM1_ETR is not connected to any AWD (analog watchdog)*/ +#define TIM_TIM1_ETR_ADC3_AWD1 (TIM1_OR1_ETR_ADC3_RMP_0) /* !< TIM1_ETR is connected to ADC3 AWD1 */ +#define TIM_TIM1_ETR_ADC3_AWD2 (TIM1_OR1_ETR_ADC3_RMP_1) /* !< TIM1_ETR is connected to ADC3 AWD2 */ +#define TIM_TIM1_ETR_ADC3_AWD3 (TIM1_OR1_ETR_ADC3_RMP_1 | TIM1_OR1_ETR_ADC3_RMP_0) /* !< TIM1_ETR is connected to ADC3 AWD3 */ +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx */ +#define TIM_TIM1_TI1_GPIO ((uint32_t)(0x00000000)) /* !< TIM1 TI1 is connected to GPIO */ +#define TIM_TIM1_TI1_COMP1 (TIM1_OR1_TI1_RMP) /* !< TIM1 TI1 is connected to COMP1 */ +#define TIM_TIM1_ETR_GPIO ((uint32_t)(0x00000000)) /* !< TIM1_ETR is connected to GPIO */ +#define TIM_TIM1_ETR_COMP1 (TIM1_OR2_ETRSEL_0) /* !< TIM1_ETR is connected to COMP1 output */ +#define TIM_TIM1_ETR_COMP2 (TIM1_OR2_ETRSEL_1) /* !< TIM1_ETR is connected to COMP2 output */ + +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define TIM_TIM2_ITR1_TIM8_TRGO ((uint32_t)(0x00000000)) /* !< TIM2_ITR1 is connected to TIM8_TRGO */ +#define TIM_TIM2_ITR1_OTG_FS_SOF (TIM2_OR1_ITR1_RMP) /* !< TIM2_ITR1 is connected to OTG_FS SOF */ +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx || */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ +#if defined (STM32L431xx) || defined (STM32L432xx) || defined (STM32L433xx) || defined (STM32L442xx) || defined (STM32L443xx) || \ + defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) +#define TIM_TIM2_ITR1_NONE ((uint32_t)(0x00000000)) /* !< No internal trigger on TIM2_ITR1 */ +#define TIM_TIM2_ITR1_USB_SOF (TIM2_OR1_ITR1_RMP) /* !< TIM2_ITR1 is connected to USB SOF */ +#endif /* STM32L431xx || STM32L432xx || STM32L442xx || STM32L433xx || STM32L443xx || */ + /* STM32L451xx || STM32L452xx || STM32L462xx */ +#define TIM_TIM2_ETR_GPIO ((uint32_t)(0x00000000)) /* !< TIM2_ETR is connected to GPIO */ +#define TIM_TIM2_ETR_LSE (TIM2_OR1_ETR1_RMP) /* !< TIM2_ETR is connected to LSE */ +#define TIM_TIM2_ETR_COMP1 (TIM2_OR2_ETRSEL_0) /* !< TIM2_ETR is connected to COMP1 output */ +#define TIM_TIM2_ETR_COMP2 (TIM2_OR2_ETRSEL_1) /* !< TIM2_ETR is connected to COMP2 output */ +#define TIM_TIM2_TI4_GPIO ((uint32_t)(0x00000000)) /* !< TIM2 TI4 is connected to GPIO */ +#define TIM_TIM2_TI4_COMP1 (TIM2_OR1_TI4_RMP_0) /* !< TIM2 TI4 is connected to COMP1 output */ +#define TIM_TIM2_TI4_COMP2 (TIM2_OR1_TI4_RMP_1) /* !< TIM2 TI4 is connected to COMP2 output */ +#define TIM_TIM2_TI4_COMP1_COMP2 (TIM2_OR1_TI4_RMP_1| TIM2_OR1_TI4_RMP_0) /* !< TIM2 TI4 is connected to logical OR between COMP1 and COMP2 output2 */ + +#if defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || \ + defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define TIM_TIM3_TI1_GPIO ((uint32_t)(0x00000000)) /* !< TIM3 TI1 is connected to GPIO */ +#define TIM_TIM3_TI1_COMP1 (TIM3_OR1_TI1_RMP_0) /* !< TIM3 TI1 is connected to COMP1 output */ +#define TIM_TIM3_TI1_COMP2 (TIM3_OR1_TI1_RMP_1) /* !< TIM3 TI1 is connected to COMP2 output */ +#define TIM_TIM3_TI1_COMP1_COMP2 (TIM3_OR1_TI1_RMP_1 | TIM3_OR1_TI1_RMP_0) /* !< TIM3 TI1 is connected to logical OR between COMP1 and COMP2 output2 */ +#define TIM_TIM3_ETR_GPIO ((uint32_t)(0x00000000)) /* !< TIM3_ETR is connected to GPIO */ +#define TIM_TIM3_ETR_COMP1 (TIM3_OR2_ETRSEL_0) /* !< TIM3_ETR is connected to COMP1 output */ +#endif /* STM32L451xx || STM32L452xx || STM32L462xx || */ + /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx || */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) +#define TIM_TIM8_ETR_ADC2_NONE ((uint32_t)(0x00000000)) /* !< TIM8_ETR is not connected to any AWD (analog watchdog)*/ +#define TIM_TIM8_ETR_ADC2_AWD1 (TIM8_OR1_ETR_ADC2_RMP_0) /* !< TIM8_ETR is connected to ADC2 AWD1 */ +#define TIM_TIM8_ETR_ADC2_AWD2 (TIM8_OR1_ETR_ADC2_RMP_1) /* !< TIM8_ETR is connected to ADC2 AWD2 */ +#define TIM_TIM8_ETR_ADC2_AWD3 (TIM8_OR1_ETR_ADC2_RMP_1 | TIM8_OR1_ETR_ADC2_RMP_0) /* !< TIM8_ETR is connected to ADC2 AWD3 */ +#define TIM_TIM8_ETR_ADC3_NONE ((uint32_t)(0x00000000)) /* !< TIM8_ETR is not connected to any AWD (analog watchdog)*/ +#define TIM_TIM8_ETR_ADC3_AWD1 (TIM8_OR1_ETR_ADC3_RMP_0) /* !< TIM8_ETR is connected to ADC3 AWD1 */ +#define TIM_TIM8_ETR_ADC3_AWD2 (TIM8_OR1_ETR_ADC3_RMP_1) /* !< TIM8_ETR is connected to ADC3 AWD2 */ +#define TIM_TIM8_ETR_ADC3_AWD3 (TIM8_OR1_ETR_ADC3_RMP_1 | TIM8_OR1_ETR_ADC3_RMP_0) /* !< TIM8_ETR is connected to ADC3 AWD3 */ +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx */ +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define TIM_TIM8_TI1_GPIO ((uint32_t)(0x00000000)) /* !< TIM8 TI1 is connected to GPIO */ +#define TIM_TIM8_TI1_COMP2 (TIM8_OR1_TI1_RMP) /* !< TIM8 TI1 is connected to COMP1 */ +#define TIM_TIM8_ETR_GPIO ((uint32_t)(0x00000000)) /* !< TIM8_ETR is connected to GPIO */ +#define TIM_TIM8_ETR_COMP1 (TIM8_OR2_ETRSEL_0) /* !< TIM8_ETR is connected to COMP1 output */ +#define TIM_TIM8_ETR_COMP2 (TIM8_OR2_ETRSEL_1) /* !< TIM8_ETR is connected to COMP2 output */ +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx || */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#define TIM_TIM15_TI1_GPIO ((uint32_t)(0x00000000)) /* !< TIM15 TI1 is connected to GPIO */ +#define TIM_TIM15_TI1_LSE (TIM15_OR1_TI1_RMP) /* !< TIM15 TI1 is connected to LSE */ +#define TIM_TIM15_ENCODERMODE_NONE ((uint32_t)(0x00000000)) /* !< No redirection */ +#define TIM_TIM15_ENCODERMODE_TIM2 (TIM15_OR1_ENCODER_MODE_0) /* !< TIM2 IC1 and TIM2 IC2 are connected to TIM15 IC1 and TIM15 IC2 respectively */ +#if defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || \ + defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define TIM_TIM15_ENCODERMODE_TIM3 (TIM15_OR1_ENCODER_MODE_1) /* !< TIM3 IC1 and TIM3 IC2 are connected to TIM15 IC1 and TIM15 IC2 respectively */ +#endif /* STM32L451xx || STM32L452xx || STM32L462xx */ + /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx || */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define TIM_TIM15_ENCODERMODE_TIM4 (TIM15_OR1_ENCODER_MODE_1 | TIM15_OR1_ENCODER_MODE_0) /* !< TIM4 IC1 and TIM4 IC2 are connected to TIM15 IC1 and TIM15 IC2 respectively */ +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx || */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#define TIM_TIM16_TI1_GPIO ((uint32_t)(0x00000000)) /* !< TIM16 TI1 is connected to GPIO */ +#define TIM_TIM16_TI1_LSI (TIM16_OR1_TI1_RMP_0) /* !< TIM16 TI1 is connected to LSI */ +#define TIM_TIM16_TI1_LSE (TIM16_OR1_TI1_RMP_1) /* !< TIM16 TI1 is connected to LSE */ +#define TIM_TIM16_TI1_RTC (TIM16_OR1_TI1_RMP_1 | TIM16_OR1_TI1_RMP_0) /* !< TIM16 TI1 is connected to RTC wakeup interrupt */ +#if defined (STM32L431xx) || defined (STM32L432xx) || defined (STM32L433xx) || defined (STM32L442xx) || defined (STM32L443xx) || \ + defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) +#define TIM_TIM16_TI1_MSI (TIM16_OR1_TI1_RMP_2) /* !< TIM16 TI1 is connected to MSI */ +#define TIM_TIM16_TI1_HSE_32 (TIM16_OR1_TI1_RMP_2 | TIM16_OR1_TI1_RMP_0) /* !< TIM16 TI1 is connected to HSE div 32 */ +#define TIM_TIM16_TI1_MCO (TIM16_OR1_TI1_RMP_2 | TIM16_OR1_TI1_RMP_1) /* !< TIM16 TI1 is connected to MCO */ +#endif /* STM32L431xx || STM32L432xx || STM32L442xx || STM32L433xx || STM32L443xx || */ + /* STM32L451xx || STM32L452xx || STM32L462xx || */ + /* STM32L496xx || STM32L4A6xx */ + +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define TIM_TIM17_TI1_GPIO ((uint32_t)(0x00000000)) /* !< TIM17 TI1 is connected to GPIO */ +#define TIM_TIM17_TI1_MSI (TIM17_OR1_TI1_RMP_0) /* !< TIM17 TI1 is connected to MSI */ +#define TIM_TIM17_TI1_HSE_32 (TIM17_OR1_TI1_RMP_1) /* !< TIM17 TI1 is connected to HSE div 32 */ +#define TIM_TIM17_TI1_MCO (TIM17_OR1_TI1_RMP_1 | TIM17_OR1_TI1_RMP_0) /* !< TIM17 TI1 is connected to MCO */ +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx || */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ +/** + * @} + */ + +/** @defgroup TIMEx_Break_Input TIM Extended Break input + * @{ + */ +#define TIM_BREAKINPUT_BRK ((uint32_t)(0x00000001)) /* !< Timer break input */ +#define TIM_BREAKINPUT_BRK2 ((uint32_t)(0x00000002)) /* !< Timer break2 input */ +/** + * @} + */ + +/** @defgroup TIMEx_Break_Input_Source TIM Extended Break input source + * @{ + */ +#define TIM_BREAKINPUTSOURCE_BKIN ((uint32_t)(0x00000001)) /* !< An external source (GPIO) is connected to the BKIN pin */ +#define TIM_BREAKINPUTSOURCE_COMP1 ((uint32_t)(0x00000002)) /* !< The COMP1 output is connected to the break input */ +#define TIM_BREAKINPUTSOURCE_COMP2 ((uint32_t)(0x00000004)) /* !< The COMP2 output is connected to the break input */ +#if defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || \ + defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define TIM_BREAKINPUTSOURCE_DFSDM1 ((uint32_t)(0x00000008)) /* !< The analog watchdog output of the DFSDM1 peripheral is connected to the break input */ +#endif /* STM32L451xx || STM32L452xx || STM32L462xx || */ + /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx || */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ +/** + * @} + */ + +/** @defgroup TIMEx_Break_Input_Source_Enable TIM Extended Break input source enabling + * @{ + */ +#define TIM_BREAKINPUTSOURCE_DISABLE ((uint32_t)(0x00000000)) /* !< Break input source is disabled */ +#define TIM_BREAKINPUTSOURCE_ENABLE ((uint32_t)(0x00000001)) /* !< Break input source is enabled */ +/** + * @} + */ + +/** @defgroup TIMEx_Break_Input_Source_Polarity TIM Extended Break input polarity + * @{ + */ +#define TIM_BREAKINPUTSOURCE_POLARITY_LOW ((uint32_t)(0x00000001)) /* !< Break input source is active low */ +#define TIM_BREAKINPUTSOURCE_POLARITY_HIGH ((uint32_t)(0x00000000)) /* !< Break input source is active_high */ +/** + * @} + */ + +/** + * @} + */ +/* End of exported constants -------------------------------------------------*/ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup TIMEx_Exported_Macros TIM Extended Exported Macros + * @{ + */ + +/** + * @} + */ +/* End of exported macro -----------------------------------------------------*/ + +/* Private macro -------------------------------------------------------------*/ +/** @defgroup TIMEx_Private_Macros TIM Extended Private Macros + * @{ + */ +#define IS_TIM_REMAP(__REMAP__) (((__REMAP__) <= (uint32_t)0x0001C01F)) + +#define IS_TIM_BREAKINPUT(__BREAKINPUT__) (((__BREAKINPUT__) == TIM_BREAKINPUT_BRK) || \ + ((__BREAKINPUT__) == TIM_BREAKINPUT_BRK2)) + +#if defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || \ + defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define IS_TIM_BREAKINPUTSOURCE(__SOURCE__) (((__SOURCE__) == TIM_BREAKINPUTSOURCE_BKIN) || \ + ((__SOURCE__) == TIM_BREAKINPUTSOURCE_COMP1) || \ + ((__SOURCE__) == TIM_BREAKINPUTSOURCE_COMP2) || \ + ((__SOURCE__) == TIM_BREAKINPUTSOURCE_DFSDM1)) +#else +#define IS_TIM_BREAKINPUTSOURCE(__SOURCE__) (((__SOURCE__) == TIM_BREAKINPUTSOURCE_BKIN) || \ + ((__SOURCE__) == TIM_BREAKINPUTSOURCE_COMP1) || \ + ((__SOURCE__) == TIM_BREAKINPUTSOURCE_COMP2)) +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx || */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#define IS_TIM_BREAKINPUTSOURCE_STATE(__STATE__) (((__STATE__) == TIM_BREAKINPUTSOURCE_DISABLE) || \ + ((__STATE__) == TIM_BREAKINPUTSOURCE_ENABLE)) + +#define IS_TIM_BREAKINPUTSOURCE_POLARITY(__POLARITY__) (((__POLARITY__) == TIM_BREAKINPUTSOURCE_POLARITY_LOW) || \ + ((__POLARITY__) == TIM_BREAKINPUTSOURCE_POLARITY_HIGH)) +/** + * @} + */ +/* End of private macro ------------------------------------------------------*/ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup TIMEx_Exported_Functions TIM Extended Exported Functions + * @{ + */ + +/** @addtogroup TIMEx_Exported_Functions_Group1 Extended Timer Hall Sensor functions + * @brief Timer Hall Sensor functions + * @{ + */ +/* Timer Hall Sensor functions **********************************************/ +HAL_StatusTypeDef HAL_TIMEx_HallSensor_Init(TIM_HandleTypeDef *htim, TIM_HallSensor_InitTypeDef* sConfig); +HAL_StatusTypeDef HAL_TIMEx_HallSensor_DeInit(TIM_HandleTypeDef *htim); + +void HAL_TIMEx_HallSensor_MspInit(TIM_HandleTypeDef *htim); +void HAL_TIMEx_HallSensor_MspDeInit(TIM_HandleTypeDef *htim); + + /* Blocking mode: Polling */ +HAL_StatusTypeDef HAL_TIMEx_HallSensor_Start(TIM_HandleTypeDef *htim); +HAL_StatusTypeDef HAL_TIMEx_HallSensor_Stop(TIM_HandleTypeDef *htim); +/* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_TIMEx_HallSensor_Start_IT(TIM_HandleTypeDef *htim); +HAL_StatusTypeDef HAL_TIMEx_HallSensor_Stop_IT(TIM_HandleTypeDef *htim); +/* Non-Blocking mode: DMA */ +HAL_StatusTypeDef HAL_TIMEx_HallSensor_Start_DMA(TIM_HandleTypeDef *htim, uint32_t *pData, uint16_t Length); +HAL_StatusTypeDef HAL_TIMEx_HallSensor_Stop_DMA(TIM_HandleTypeDef *htim); +/** + * @} + */ + +/** @addtogroup TIMEx_Exported_Functions_Group2 Extended Timer Complementary Output Compare functions + * @brief Timer Complementary Output Compare functions + * @{ + */ +/* Timer Complementary Output Compare functions *****************************/ +/* Blocking mode: Polling */ +HAL_StatusTypeDef HAL_TIMEx_OCN_Start(TIM_HandleTypeDef *htim, uint32_t Channel); +HAL_StatusTypeDef HAL_TIMEx_OCN_Stop(TIM_HandleTypeDef *htim, uint32_t Channel); + +/* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_TIMEx_OCN_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel); +HAL_StatusTypeDef HAL_TIMEx_OCN_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel); + +/* Non-Blocking mode: DMA */ +HAL_StatusTypeDef HAL_TIMEx_OCN_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length); +HAL_StatusTypeDef HAL_TIMEx_OCN_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel); +/** + * @} + */ + +/** @addtogroup TIMEx_Exported_Functions_Group3 Extended Timer Complementary PWM functions + * @brief Timer Complementary PWM functions + * @{ + */ +/* Timer Complementary PWM functions ****************************************/ +/* Blocking mode: Polling */ +HAL_StatusTypeDef HAL_TIMEx_PWMN_Start(TIM_HandleTypeDef *htim, uint32_t Channel); +HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop(TIM_HandleTypeDef *htim, uint32_t Channel); + +/* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_TIMEx_PWMN_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel); +HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel); +/* Non-Blocking mode: DMA */ +HAL_StatusTypeDef HAL_TIMEx_PWMN_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length); +HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel); +/** + * @} + */ + +/** @addtogroup TIMEx_Exported_Functions_Group4 Extended Timer Complementary One Pulse functions + * @brief Timer Complementary One Pulse functions + * @{ + */ +/* Timer Complementary One Pulse functions **********************************/ +/* Blocking mode: Polling */ +HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Start(TIM_HandleTypeDef *htim, uint32_t OutputChannel); +HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Stop(TIM_HandleTypeDef *htim, uint32_t OutputChannel); + +/* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Start_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel); +HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Stop_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel); +/** + * @} + */ + +/** @addtogroup TIMEx_Exported_Functions_Group5 Extended Peripheral Control functions + * @brief Peripheral Control functions + * @{ + */ +/* Extended Control functions ************************************************/ +HAL_StatusTypeDef HAL_TIMEx_ConfigCommutationEvent(TIM_HandleTypeDef *htim, uint32_t InputTrigger, uint32_t CommutationSource); +HAL_StatusTypeDef HAL_TIMEx_ConfigCommutationEvent_IT(TIM_HandleTypeDef *htim, uint32_t InputTrigger, uint32_t CommutationSource); +HAL_StatusTypeDef HAL_TIMEx_ConfigCommutationEvent_DMA(TIM_HandleTypeDef *htim, uint32_t InputTrigger, uint32_t CommutationSource); +HAL_StatusTypeDef HAL_TIMEx_MasterConfigSynchronization(TIM_HandleTypeDef *htim, TIM_MasterConfigTypeDef * sMasterConfig); +HAL_StatusTypeDef HAL_TIMEx_ConfigBreakDeadTime(TIM_HandleTypeDef *htim, TIM_BreakDeadTimeConfigTypeDef *sBreakDeadTimeConfig); +HAL_StatusTypeDef HAL_TIMEx_ConfigBreakInput(TIM_HandleTypeDef *htim, uint32_t BreakInput, TIMEx_BreakInputConfigTypeDef *sBreakInputConfig); +HAL_StatusTypeDef HAL_TIMEx_GroupChannel5(TIM_HandleTypeDef *htim, uint32_t Channels); +HAL_StatusTypeDef HAL_TIMEx_RemapConfig(TIM_HandleTypeDef *htim, uint32_t Remap); + +/** + * @} + */ + +/** @addtogroup TIMEx_Exported_Functions_Group6 Extended Callbacks functions + * @brief Extended Callbacks functions + * @{ + */ +/* Extended Callback **********************************************************/ +void HAL_TIMEx_CommutationCallback(TIM_HandleTypeDef *htim); +void HAL_TIMEx_BreakCallback(TIM_HandleTypeDef *htim); +/** + * @} + */ + +/** @addtogroup TIMEx_Exported_Functions_Group7 Extended Peripheral State functions + * @brief Extended Peripheral State functions + * @{ + */ +/* Extended Peripheral State functions ***************************************/ +HAL_TIM_StateTypeDef HAL_TIMEx_HallSensor_GetState(TIM_HandleTypeDef *htim); +/** + * @} + */ + +/** + * @} + */ +/* End of exported functions -------------------------------------------------*/ + +/* Private functions----------------------------------------------------------*/ +/** @defgroup TIMEx_Private_Functions TIMEx Private Functions +* @{ +*/ +void TIMEx_DMACommutationCplt(DMA_HandleTypeDef *hdma); +/** +* @} +*/ +/* End of private functions --------------------------------------------------*/ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + + +#endif /* __STM32L4xx_HAL_TIM_EX_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_uart.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_uart.h new file mode 100644 index 0000000..c1b0489 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_uart.h @@ -0,0 +1,1638 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_uart.h + * @author MCD Application Team + * @brief Header file of UART HAL module. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_UART_H +#define __STM32L4xx_HAL_UART_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup UART + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup UART_Exported_Types UART Exported Types + * @{ + */ + +/** + * @brief UART Init Structure definition + */ +typedef struct +{ + uint32_t BaudRate; /*!< This member configures the UART communication baud rate. + The baud rate register is computed using the following formula: + UART: + ===== + - If oversampling is 16 or in LIN mode, + Baud Rate Register = ((uart_ker_ckpres) / ((huart->Init.BaudRate))) + - If oversampling is 8, + Baud Rate Register[15:4] = ((2 * uart_ker_ckpres) / ((huart->Init.BaudRate)))[15:4] + Baud Rate Register[3] = 0 + Baud Rate Register[2:0] = (((2 * uart_ker_ckpres) / ((huart->Init.BaudRate)))[3:0]) >> 1 + LPUART: + ======= + Baud Rate Register = ((256 * lpuart_ker_ckpres) / ((huart->Init.BaudRate))) + + where (uart/lpuart)_ker_ck_pres is the UART input clock divided by a prescaler */ + + uint32_t WordLength; /*!< Specifies the number of data bits transmitted or received in a frame. + This parameter can be a value of @ref UARTEx_Word_Length. */ + + uint32_t StopBits; /*!< Specifies the number of stop bits transmitted. + This parameter can be a value of @ref UART_Stop_Bits. */ + + uint32_t Parity; /*!< Specifies the parity mode. + This parameter can be a value of @ref UART_Parity + @note When parity is enabled, the computed parity is inserted + at the MSB position of the transmitted data (9th bit when + the word length is set to 9 data bits; 8th bit when the + word length is set to 8 data bits). */ + + uint32_t Mode; /*!< Specifies whether the Receive or Transmit mode is enabled or disabled. + This parameter can be a value of @ref UART_Mode. */ + + uint32_t HwFlowCtl; /*!< Specifies whether the hardware flow control mode is enabled + or disabled. + This parameter can be a value of @ref UART_Hardware_Flow_Control. */ + + uint32_t OverSampling; /*!< Specifies whether the Over sampling 8 is enabled or disabled, to achieve higher speed (up to f_PCLK/8). + This parameter can be a value of @ref UART_Over_Sampling. */ + + uint32_t OneBitSampling; /*!< Specifies whether a single sample or three samples' majority vote is selected. + Selecting the single sample method increases the receiver tolerance to clock + deviations. This parameter can be a value of @ref UART_OneBit_Sampling. */ + +#if defined(USART_PRESC_PRESCALER) + uint32_t ClockPrescaler; /*!< Specifies the prescaler value used to divide the UART clock source. + This parameter can be a value of @ref UART_ClockPrescaler. */ +#endif + +}UART_InitTypeDef; + +/** + * @brief UART Advanced Features initalization structure definition + */ +typedef struct +{ + uint32_t AdvFeatureInit; /*!< Specifies which advanced UART features is initialized. Several + Advanced Features may be initialized at the same time . + This parameter can be a value of @ref UART_Advanced_Features_Initialization_Type. */ + + uint32_t TxPinLevelInvert; /*!< Specifies whether the TX pin active level is inverted. + This parameter can be a value of @ref UART_Tx_Inv. */ + + uint32_t RxPinLevelInvert; /*!< Specifies whether the RX pin active level is inverted. + This parameter can be a value of @ref UART_Rx_Inv. */ + + uint32_t DataInvert; /*!< Specifies whether data are inverted (positive/direct logic + vs negative/inverted logic). + This parameter can be a value of @ref UART_Data_Inv. */ + + uint32_t Swap; /*!< Specifies whether TX and RX pins are swapped. + This parameter can be a value of @ref UART_Rx_Tx_Swap. */ + + uint32_t OverrunDisable; /*!< Specifies whether the reception overrun detection is disabled. + This parameter can be a value of @ref UART_Overrun_Disable. */ + + uint32_t DMADisableonRxError; /*!< Specifies whether the DMA is disabled in case of reception error. + This parameter can be a value of @ref UART_DMA_Disable_on_Rx_Error. */ + + uint32_t AutoBaudRateEnable; /*!< Specifies whether auto Baud rate detection is enabled. + This parameter can be a value of @ref UART_AutoBaudRate_Enable */ + + uint32_t AutoBaudRateMode; /*!< If auto Baud rate detection is enabled, specifies how the rate + detection is carried out. + This parameter can be a value of @ref UART_AutoBaud_Rate_Mode. */ + + uint32_t MSBFirst; /*!< Specifies whether MSB is sent first on UART line. + This parameter can be a value of @ref UART_MSB_First. */ +} UART_AdvFeatureInitTypeDef; + + + +/** + * @brief HAL UART State structures definition + * @note HAL UART State value is a combination of 2 different substates: gState and RxState. + * - gState contains UART state information related to global Handle management + * and also information related to Tx operations. + * gState value coding follow below described bitmap : + * b7-b6 Error information + * 00 : No Error + * 01 : (Not Used) + * 10 : Timeout + * 11 : Error + * b5 IP initilisation status + * 0 : Reset (IP not initialized) + * 1 : Init done (IP not initialized. HAL UART Init function already called) + * b4-b3 (not used) + * xx : Should be set to 00 + * b2 Intrinsic process state + * 0 : Ready + * 1 : Busy (IP busy with some configuration or internal operations) + * b1 (not used) + * x : Should be set to 0 + * b0 Tx state + * 0 : Ready (no Tx operation ongoing) + * 1 : Busy (Tx operation ongoing) + * - RxState contains information related to Rx operations. + * RxState value coding follow below described bitmap : + * b7-b6 (not used) + * xx : Should be set to 00 + * b5 IP initilisation status + * 0 : Reset (IP not initialized) + * 1 : Init done (IP not initialized) + * b4-b2 (not used) + * xxx : Should be set to 000 + * b1 Rx state + * 0 : Ready (no Rx operation ongoing) + * 1 : Busy (Rx operation ongoing) + * b0 (not used) + * x : Should be set to 0. + */ +typedef enum +{ + HAL_UART_STATE_RESET = 0x00U, /*!< Peripheral is not initialized + Value is allowed for gState and RxState */ + HAL_UART_STATE_READY = 0x20U, /*!< Peripheral Initialized and ready for use + Value is allowed for gState and RxState */ + HAL_UART_STATE_BUSY = 0x24U, /*!< an internal process is ongoing + Value is allowed for gState only */ + HAL_UART_STATE_BUSY_TX = 0x21U, /*!< Data Transmission process is ongoing + Value is allowed for gState only */ + HAL_UART_STATE_BUSY_RX = 0x22U, /*!< Data Reception process is ongoing + Value is allowed for RxState only */ + HAL_UART_STATE_BUSY_TX_RX = 0x23U, /*!< Data Transmission and Reception process is ongoing + Not to be used for neither gState nor RxState. + Value is result of combination (Or) between gState and RxState values */ + HAL_UART_STATE_TIMEOUT = 0xA0U, /*!< Timeout state + Value is allowed for gState only */ + HAL_UART_STATE_ERROR = 0xE0U /*!< Error + Value is allowed for gState only */ +}HAL_UART_StateTypeDef; + +/** + * @brief HAL UART Error Code structure definition + */ +typedef enum +{ + HAL_UART_ERROR_NONE = 0x00U, /*!< No error */ + HAL_UART_ERROR_PE = 0x01U, /*!< Parity error */ + HAL_UART_ERROR_NE = 0x02U, /*!< Noise error */ + HAL_UART_ERROR_FE = 0x04U, /*!< frame error */ + HAL_UART_ERROR_ORE = 0x08U, /*!< Overrun error */ + HAL_UART_ERROR_DMA = 0x10U /*!< DMA transfer error */ +}HAL_UART_ErrorTypeDef; + +/** + * @brief UART clock sources definition + */ +typedef enum +{ + UART_CLOCKSOURCE_PCLK1 = 0x00U, /*!< PCLK1 clock source */ + UART_CLOCKSOURCE_PCLK2 = 0x01U, /*!< PCLK2 clock source */ + UART_CLOCKSOURCE_HSI = 0x02U, /*!< HSI clock source */ + UART_CLOCKSOURCE_SYSCLK = 0x04U, /*!< SYSCLK clock source */ + UART_CLOCKSOURCE_LSE = 0x08U, /*!< LSE clock source */ + UART_CLOCKSOURCE_UNDEFINED = 0x10U /*!< Undefined clock source */ +}UART_ClockSourceTypeDef; + +/** + * @brief UART handle Structure definition + */ +typedef struct __UART_HandleTypeDef +{ + USART_TypeDef *Instance; /*!< UART registers base address */ + + UART_InitTypeDef Init; /*!< UART communication parameters */ + + UART_AdvFeatureInitTypeDef AdvancedInit; /*!< UART Advanced Features initialization parameters */ + + uint8_t *pTxBuffPtr; /*!< Pointer to UART Tx transfer Buffer */ + + uint16_t TxXferSize; /*!< UART Tx Transfer size */ + + __IO uint16_t TxXferCount; /*!< UART Tx Transfer Counter */ + + uint8_t *pRxBuffPtr; /*!< Pointer to UART Rx transfer Buffer */ + + uint16_t RxXferSize; /*!< UART Rx Transfer size */ + + __IO uint16_t RxXferCount; /*!< UART Rx Transfer Counter */ + + uint16_t Mask; /*!< UART Rx RDR register mask */ + +#if defined(USART_CR1_FIFOEN) + uint16_t NbRxDataToProcess; /*!< Number of data to process during RX ISR execution */ + + uint16_t NbTxDataToProcess; /*!< Number of data to process during TX ISR execution */ + + uint32_t FifoMode; /*!< Specifies if the FIFO mode is being used. + This parameter can be a value of @ref UARTEx_FIFO_mode. */ +#endif + +#if defined(USART_CR2_SLVEN) + uint32_t SlaveMode; /*!< Specifies if the UART SPI Slave mode is being used. + This parameter can be a value of @ref UARTEx_Slave_Mode. */ +#endif + + void (*RxISR)(struct __UART_HandleTypeDef *huart); /*!< Function pointer on Rx IRQ handler */ + + void (*TxISR)(struct __UART_HandleTypeDef *huart); /*!< Function pointer on Tx IRQ handler */ + + DMA_HandleTypeDef *hdmatx; /*!< UART Tx DMA Handle parameters */ + + DMA_HandleTypeDef *hdmarx; /*!< UART Rx DMA Handle parameters */ + + HAL_LockTypeDef Lock; /*!< Locking object */ + + __IO HAL_UART_StateTypeDef gState; /*!< UART state information related to global Handle management + and also related to Tx operations. + This parameter can be a value of @ref HAL_UART_StateTypeDef */ + + __IO HAL_UART_StateTypeDef RxState; /*!< UART state information related to Rx operations. + This parameter can be a value of @ref HAL_UART_StateTypeDef */ + + __IO uint32_t ErrorCode; /*!< UART Error code */ + +}UART_HandleTypeDef; + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup UART_Exported_Constants UART Exported Constants + * @{ + */ + +/** @defgroup UART_Stop_Bits UART Number of Stop Bits + * @{ + */ +#define UART_STOPBITS_0_5 USART_CR2_STOP_0 /*!< UART frame with 0.5 stop bit */ +#define UART_STOPBITS_1 0x00000000U /*!< UART frame with 1 stop bit */ +#define UART_STOPBITS_1_5 (USART_CR2_STOP_0 | USART_CR2_STOP_1) /*!< UART frame with 1.5 stop bits */ +#define UART_STOPBITS_2 USART_CR2_STOP_1 /*!< UART frame with 2 stop bits */ +/** + * @} + */ + +/** @defgroup UART_Parity UART Parity + * @{ + */ +#define UART_PARITY_NONE 0x00000000U /*!< No parity */ +#define UART_PARITY_EVEN USART_CR1_PCE /*!< Even parity */ +#define UART_PARITY_ODD (USART_CR1_PCE | USART_CR1_PS) /*!< Odd parity */ +/** + * @} + */ + +/** @defgroup UART_Hardware_Flow_Control UART Hardware Flow Control + * @{ + */ +#define UART_HWCONTROL_NONE 0x00000000U /*!< No hardware control */ +#define UART_HWCONTROL_RTS USART_CR3_RTSE /*!< Request To Send */ +#define UART_HWCONTROL_CTS USART_CR3_CTSE /*!< Clear To Send */ +#define UART_HWCONTROL_RTS_CTS (USART_CR3_RTSE | USART_CR3_CTSE) /*!< Request and Clear To Send */ +/** + * @} + */ + +/** @defgroup UART_Mode UART Transfer Mode + * @{ + */ +#define UART_MODE_RX USART_CR1_RE /*!< RX mode */ +#define UART_MODE_TX USART_CR1_TE /*!< TX mode */ +#define UART_MODE_TX_RX (USART_CR1_TE |USART_CR1_RE) /*!< RX and TX mode */ +/** + * @} + */ + +/** @defgroup UART_State UART State + * @{ + */ +#define UART_STATE_DISABLE 0x00000000U /*!< UART disabled */ +#define UART_STATE_ENABLE USART_CR1_UE /*!< UART enabled */ +/** + * @} + */ + +/** @defgroup UART_Over_Sampling UART Over Sampling + * @{ + */ +#define UART_OVERSAMPLING_16 0x00000000U /*!< Oversampling by 16 */ +#define UART_OVERSAMPLING_8 USART_CR1_OVER8 /*!< Oversampling by 8 */ +/** + * @} + */ + +/** @defgroup UART_OneBit_Sampling UART One Bit Sampling Method + * @{ + */ +#define UART_ONE_BIT_SAMPLE_DISABLE 0x00000000U /*!< One-bit sampling disable */ +#define UART_ONE_BIT_SAMPLE_ENABLE USART_CR3_ONEBIT /*!< One-bit sampling enable */ +/** + * @} + */ + +#if defined(USART_PRESC_PRESCALER) +/** @defgroup UART_ClockPrescaler UART Clock Prescaler + * @{ + */ +#define UART_PRESCALER_DIV1 0x00000000U /*!< fclk_pres = fclk */ +#define UART_PRESCALER_DIV2 0x00000001U /*!< fclk_pres = fclk/2 */ +#define UART_PRESCALER_DIV4 0x00000002U /*!< fclk_pres = fclk/4 */ +#define UART_PRESCALER_DIV6 0x00000003U /*!< fclk_pres = fclk/6 */ +#define UART_PRESCALER_DIV8 0x00000004U /*!< fclk_pres = fclk/8 */ +#define UART_PRESCALER_DIV10 0x00000005U /*!< fclk_pres = fclk/10 */ +#define UART_PRESCALER_DIV12 0x00000006U /*!< fclk_pres = fclk/12 */ +#define UART_PRESCALER_DIV16 0x00000007U /*!< fclk_pres = fclk/16 */ +#define UART_PRESCALER_DIV32 0x00000008U /*!< fclk_pres = fclk/32 */ +#define UART_PRESCALER_DIV64 0x00000009U /*!< fclk_pres = fclk/64 */ +#define UART_PRESCALER_DIV128 0x0000000AU /*!< fclk_pres = fclk/128 */ +#define UART_PRESCALER_DIV256 0x0000000BU /*!< fclk_pres = fclk/256 */ +/** + * @} + */ +#endif + +/** @defgroup UART_AutoBaud_Rate_Mode UART Advanced Feature AutoBaud Rate Mode + * @{ + */ +#define UART_ADVFEATURE_AUTOBAUDRATE_ONSTARTBIT 0x00000000U /*!< Auto Baud rate detection on start bit */ +#define UART_ADVFEATURE_AUTOBAUDRATE_ONFALLINGEDGE USART_CR2_ABRMODE_0 /*!< Auto Baud rate detection on falling edge */ +#define UART_ADVFEATURE_AUTOBAUDRATE_ON0X7FFRAME USART_CR2_ABRMODE_1 /*!< Auto Baud rate detection on 0x7F frame detection */ +#define UART_ADVFEATURE_AUTOBAUDRATE_ON0X55FRAME USART_CR2_ABRMODE /*!< Auto Baud rate detection on 0x55 frame detection */ +/** + * @} + */ + +/** @defgroup UART_Receiver_TimeOut UART Receiver TimeOut + * @{ + */ +#define UART_RECEIVER_TIMEOUT_DISABLE 0x00000000U /*!< UART receiver timeout disable */ +#define UART_RECEIVER_TIMEOUT_ENABLE USART_CR2_RTOEN /*!< UART receiver timeout enable */ +/** + * @} + */ + +/** @defgroup UART_LIN UART Local Interconnection Network mode + * @{ + */ +#define UART_LIN_DISABLE 0x00000000U /*!< Local Interconnect Network disable */ +#define UART_LIN_ENABLE USART_CR2_LINEN /*!< Local Interconnect Network enable */ +/** + * @} + */ + +/** @defgroup UART_LIN_Break_Detection UART LIN Break Detection + * @{ + */ +#define UART_LINBREAKDETECTLENGTH_10B 0x00000000U /*!< LIN 10-bit break detection length */ +#define UART_LINBREAKDETECTLENGTH_11B USART_CR2_LBDL /*!< LIN 11-bit break detection length */ +/** + * @} + */ + +/** @defgroup UART_DMA_Tx UART DMA Tx + * @{ + */ +#define UART_DMA_TX_DISABLE 0x00000000U /*!< UART DMA TX disabled */ +#define UART_DMA_TX_ENABLE USART_CR3_DMAT /*!< UART DMA TX enabled */ +/** + * @} + */ + +/** @defgroup UART_DMA_Rx UART DMA Rx + * @{ + */ +#define UART_DMA_RX_DISABLE 0x00000000U /*!< UART DMA RX disabled */ +#define UART_DMA_RX_ENABLE USART_CR3_DMAR /*!< UART DMA RX enabled */ +/** + * @} + */ + +/** @defgroup UART_Half_Duplex_Selection UART Half Duplex Selection + * @{ + */ +#define UART_HALF_DUPLEX_DISABLE 0x00000000U /*!< UART half-duplex disabled */ +#define UART_HALF_DUPLEX_ENABLE USART_CR3_HDSEL /*!< UART half-duplex enabled */ +/** + * @} + */ + +/** @defgroup UART_WakeUp_Methods UART WakeUp Methods + * @{ + */ +#define UART_WAKEUPMETHOD_IDLELINE 0x00000000U /*!< UART wake-up on idle line */ +#define UART_WAKEUPMETHOD_ADDRESSMARK USART_CR1_WAKE /*!< UART wake-up on address mark */ +/** + * @} + */ + +/** @defgroup UART_Request_Parameters UART Request Parameters + * @{ + */ +#define UART_AUTOBAUD_REQUEST USART_RQR_ABRRQ /*!< Auto-Baud Rate Request */ +#define UART_SENDBREAK_REQUEST USART_RQR_SBKRQ /*!< Send Break Request */ +#define UART_MUTE_MODE_REQUEST USART_RQR_MMRQ /*!< Mute Mode Request */ +#define UART_RXDATA_FLUSH_REQUEST USART_RQR_RXFRQ /*!< Receive Data flush Request */ +#define UART_TXDATA_FLUSH_REQUEST USART_RQR_TXFRQ /*!< Transmit data flush Request */ +/** + * @} + */ + +/** @defgroup UART_Advanced_Features_Initialization_Type UART Advanced Feature Initialization Type + * @{ + */ +#define UART_ADVFEATURE_NO_INIT 0x00000000U /*!< No advanced feature initialization */ +#define UART_ADVFEATURE_TXINVERT_INIT 0x00000001U /*!< TX pin active level inversion */ +#define UART_ADVFEATURE_RXINVERT_INIT 0x00000002U /*!< RX pin active level inversion */ +#define UART_ADVFEATURE_DATAINVERT_INIT 0x00000004U /*!< Binary data inversion */ +#define UART_ADVFEATURE_SWAP_INIT 0x00000008U /*!< TX/RX pins swap */ +#define UART_ADVFEATURE_RXOVERRUNDISABLE_INIT 0x00000010U /*!< RX overrun disable */ +#define UART_ADVFEATURE_DMADISABLEONERROR_INIT 0x00000020U /*!< DMA disable on Reception Error */ +#define UART_ADVFEATURE_AUTOBAUDRATE_INIT 0x00000040U /*!< Auto Baud rate detection initialization */ +#define UART_ADVFEATURE_MSBFIRST_INIT 0x00000080U /*!< Most significant bit sent/received first */ +/** + * @} + */ + +/** @defgroup UART_Tx_Inv UART Advanced Feature TX Pin Active Level Inversion + * @{ + */ +#define UART_ADVFEATURE_TXINV_DISABLE 0x00000000U /*!< TX pin active level inversion disable */ +#define UART_ADVFEATURE_TXINV_ENABLE USART_CR2_TXINV /*!< TX pin active level inversion enable */ +/** + * @} + */ + +/** @defgroup UART_Rx_Inv UART Advanced Feature RX Pin Active Level Inversion + * @{ + */ +#define UART_ADVFEATURE_RXINV_DISABLE 0x00000000U /*!< RX pin active level inversion disable */ +#define UART_ADVFEATURE_RXINV_ENABLE USART_CR2_RXINV /*!< RX pin active level inversion enable */ +/** + * @} + */ + +/** @defgroup UART_Data_Inv UART Advanced Feature Binary Data Inversion + * @{ + */ +#define UART_ADVFEATURE_DATAINV_DISABLE 0x00000000U /*!< Binary data inversion disable */ +#define UART_ADVFEATURE_DATAINV_ENABLE USART_CR2_DATAINV /*!< Binary data inversion enable */ +/** + * @} + */ + +/** @defgroup UART_Rx_Tx_Swap UART Advanced Feature RX TX Pins Swap + * @{ + */ +#define UART_ADVFEATURE_SWAP_DISABLE 0x00000000U /*!< TX/RX pins swap disable */ +#define UART_ADVFEATURE_SWAP_ENABLE USART_CR2_SWAP /*!< TX/RX pins swap enable */ +/** + * @} + */ + +/** @defgroup UART_Overrun_Disable UART Advanced Feature Overrun Disable + * @{ + */ +#define UART_ADVFEATURE_OVERRUN_ENABLE 0x00000000U /*!< RX overrun enable */ +#define UART_ADVFEATURE_OVERRUN_DISABLE USART_CR3_OVRDIS /*!< RX overrun disable */ +/** + * @} + */ + +/** @defgroup UART_AutoBaudRate_Enable UART Advanced Feature Auto BaudRate Enable + * @{ + */ +#define UART_ADVFEATURE_AUTOBAUDRATE_DISABLE 0x00000000U /*!< RX Auto Baud rate detection enable */ +#define UART_ADVFEATURE_AUTOBAUDRATE_ENABLE USART_CR2_ABREN /*!< RX Auto Baud rate detection disable */ +/** + * @} + */ + +/** @defgroup UART_DMA_Disable_on_Rx_Error UART Advanced Feature DMA Disable On Rx Error + * @{ + */ +#define UART_ADVFEATURE_DMA_ENABLEONRXERROR 0x00000000U /*!< DMA enable on Reception Error */ +#define UART_ADVFEATURE_DMA_DISABLEONRXERROR USART_CR3_DDRE /*!< DMA disable on Reception Error */ +/** + * @} + */ + +/** @defgroup UART_MSB_First UART Advanced Feature MSB First + * @{ + */ +#define UART_ADVFEATURE_MSBFIRST_DISABLE 0x00000000U /*!< Most significant bit sent/received first disable */ +#define UART_ADVFEATURE_MSBFIRST_ENABLE USART_CR2_MSBFIRST /*!< Most significant bit sent/received first enable */ +/** + * @} + */ + +/** @defgroup UART_Stop_Mode_Enable UART Advanced Feature Stop Mode Enable + * @{ + */ +#define UART_ADVFEATURE_STOPMODE_DISABLE 0x00000000U /*!< UART stop mode disable */ +#define UART_ADVFEATURE_STOPMODE_ENABLE USART_CR1_UESM /*!< UART stop mode enable */ +/** + * @} + */ + +/** @defgroup UART_Mute_Mode UART Advanced Feature Mute Mode Enable + * @{ + */ +#define UART_ADVFEATURE_MUTEMODE_DISABLE 0x00000000U /*!< UART mute mode disable */ +#define UART_ADVFEATURE_MUTEMODE_ENABLE USART_CR1_MME /*!< UART mute mode enable */ +/** + * @} + */ + +/** @defgroup UART_CR2_ADDRESS_LSB_POS UART Address-matching LSB Position In CR2 Register + * @{ + */ +#define UART_CR2_ADDRESS_LSB_POS 24U /*!< UART address-matching LSB position in CR2 register */ +/** + * @} + */ + +/** @defgroup UART_WakeUp_from_Stop_Selection UART WakeUp From Stop Selection + * @{ + */ +#define UART_WAKEUP_ON_ADDRESS 0x00000000U /*!< UART wake-up on address */ +#define UART_WAKEUP_ON_STARTBIT USART_CR3_WUS_1 /*!< UART wake-up on start bit */ +#define UART_WAKEUP_ON_READDATA_NONEMPTY USART_CR3_WUS /*!< UART wake-up on receive data register not empty or RXFIFO is not empty */ +/** + * @} + */ + +/** @defgroup UART_DriverEnable_Polarity UART DriverEnable Polarity + * @{ + */ +#define UART_DE_POLARITY_HIGH 0x00000000U /*!< Driver enable signal is active high */ +#define UART_DE_POLARITY_LOW USART_CR3_DEP /*!< Driver enable signal is active low */ +/** + * @} + */ + +/** @defgroup UART_CR1_DEAT_ADDRESS_LSB_POS UART Driver Enable Assertion Time LSB Position In CR1 Register + * @{ + */ +#define UART_CR1_DEAT_ADDRESS_LSB_POS 21U /*!< UART Driver Enable assertion time LSB position in CR1 register */ +/** + * @} + */ + +/** @defgroup UART_CR1_DEDT_ADDRESS_LSB_POS UART Driver Enable DeAssertion Time LSB Position In CR1 Register + * @{ + */ +#define UART_CR1_DEDT_ADDRESS_LSB_POS 16U /*!< UART Driver Enable de-assertion time LSB position in CR1 register */ +/** + * @} + */ + +/** @defgroup UART_Interruption_Mask UART Interruptions Flag Mask + * @{ + */ +#define UART_IT_MASK 0x001FU /*!< UART interruptions flags mask */ +/** + * @} + */ + +/** @defgroup UART_TimeOut_Value UART polling-based communications time-out value + * @{ + */ +#define HAL_UART_TIMEOUT_VALUE 0x1FFFFFFU /*!< UART polling-based communications time-out value */ +/** + * @} + */ + +/** @defgroup UART_Flags UART Status Flags + * Elements values convention: 0xXXXX + * - 0xXXXX : Flag mask in the ISR register + * @{ + */ +#define UART_FLAG_TXFT USART_ISR_TXFT /*!< UART TXFIFO threshold flag */ +#define UART_FLAG_RXFT USART_ISR_RXFT /*!< UART RXFIFO threshold flag */ +#define UART_FLAG_RXFF USART_ISR_RXFF /*!< UART RXFIFO Full flag */ +#define UART_FLAG_TXFE USART_ISR_TXFE /*!< UART TXFIFO Empty flag */ +#define UART_FLAG_REACK USART_ISR_REACK /*!< UART receive enable acknowledge flag */ +#define UART_FLAG_TEACK USART_ISR_TEACK /*!< UART transmit enable acknowledge flag */ +#define UART_FLAG_WUF USART_ISR_WUF /*!< UART wake-up from stop mode flag */ +#define UART_FLAG_RWU USART_ISR_RWU /*!< UART receiver wake-up from mute mode flag */ +#define UART_FLAG_SBKF USART_ISR_SBKF /*!< UART send break flag */ +#define UART_FLAG_CMF USART_ISR_CMF /*!< UART character match flag */ +#define UART_FLAG_BUSY USART_ISR_BUSY /*!< UART busy flag */ +#define UART_FLAG_ABRF USART_ISR_ABRF /*!< UART auto Baud rate flag */ +#define UART_FLAG_ABRE USART_ISR_ABRE /*!< UART auto Baud rate error */ +#define UART_FLAG_CTS USART_ISR_CTS /*!< UART clear to send flag */ +#define UART_FLAG_CTSIF USART_ISR_CTSIF /*!< UART clear to send interrupt flag */ +#define UART_FLAG_LBDF USART_ISR_LBDF /*!< UART LIN break detection flag */ +#if defined(USART_CR1_FIFOEN) +#define UART_FLAG_TXE USART_ISR_TXE_TXFNF /*!< UART transmit data register empty */ +#define UART_FLAG_TXFNF USART_ISR_TXE_TXFNF /*!< UART TXFIFO not full */ +#else +#define UART_FLAG_TXE USART_ISR_TXE /*!< UART transmit data register empty */ +#endif +#define UART_FLAG_TC USART_ISR_TC /*!< UART transmission complete */ +#if defined(USART_CR1_FIFOEN) +#define UART_FLAG_RXNE USART_ISR_RXNE_RXFNE /*!< UART read data register not empty */ +#define UART_FLAG_RXFNE USART_ISR_RXNE_RXFNE /*!< UART RXFIFO not empty */ +#else +#define UART_FLAG_RXNE USART_ISR_RXNE /*!< UART read data register not empty */ +#endif +#define UART_FLAG_IDLE USART_ISR_IDLE /*!< UART idle flag */ +#define UART_FLAG_ORE USART_ISR_ORE /*!< UART overrun error */ +#define UART_FLAG_NE USART_ISR_NE /*!< UART noise error */ +#define UART_FLAG_FE USART_ISR_FE /*!< UART frame error */ +#define UART_FLAG_PE USART_ISR_PE /*!< UART parity error */ +/** + * @} + */ + +/** @defgroup UART_Interrupt_definition UART Interrupts Definition + * Elements values convention: 000ZZZZZ0XXYYYYYb + * - YYYYY : Interrupt source position in the XX register (5bits) + * - XX : Interrupt source register (2bits) + * - 01: CR1 register + * - 10: CR2 register + * - 11: CR3 register + * - ZZZZZ : Flag position in the ISR register(5bits) + * @{ + */ +#define UART_IT_PE 0x0028U /*!< UART parity error interruption */ +#define UART_IT_TXE 0x0727U /*!< UART transmit data register empty interruption */ +#if defined(USART_CR1_FIFOEN) +#define UART_IT_TXFNF 0x0727U /*!< UART TX FIFO not full interruption */ +#endif +#define UART_IT_TC 0x0626U /*!< UART transmission complete interruption */ +#define UART_IT_RXNE 0x0525U /*!< UART read data register not empty interruption */ +#if defined(USART_CR1_FIFOEN) +#define UART_IT_RXFNE 0x0525U /*!< UART RXFIFO not empty interruption */ +#endif +#define UART_IT_IDLE 0x0424U /*!< UART idle interruption */ +#define UART_IT_LBD 0x0846U /*!< UART LIN break detection interruption */ +#define UART_IT_CTS 0x096AU /*!< UART CTS interruption */ +#define UART_IT_CM 0x112EU /*!< UART character match interruption */ +#define UART_IT_WUF 0x1476U /*!< UART wake-up from stop mode interruption */ +#if defined(USART_CR1_FIFOEN) +#define UART_IT_RXFF 0x183FU /*!< UART RXFIFO full interruption */ +#define UART_IT_TXFE 0x173EU /*!< UART TXFIFO empty interruption */ +#define UART_IT_RXFT 0x1A7CU /*!< UART RXFIFO threshold reached interruption */ +#define UART_IT_TXFT 0x1B77U /*!< UART TXFIFO threshold reached interruption */ +#endif + +/* Elements values convention: 000000000XXYYYYYb + - YYYYY : Interrupt source position in the XX register (5bits) + - XX : Interrupt source register (2bits) + - 01: CR1 register + - 10: CR2 register + - 11: CR3 register */ +#define UART_IT_ERR 0x0060U /*!< UART error interruption */ + +/* Elements values convention: 0000ZZZZ00000000b + - ZZZZ : Flag position in the ISR register(4bits) */ +#define UART_IT_ORE 0x0300U /*!< UART overrun error interruption */ +#define UART_IT_NE 0x0200U /*!< UART noise error interruption */ +#define UART_IT_FE 0x0100U /*!< UART frame error interruption */ +/** + * @} + */ + +/** @defgroup UART_IT_CLEAR_Flags UART Interruption Clear Flags + * @{ + */ +#define UART_CLEAR_PEF USART_ICR_PECF /*!< Parity Error Clear Flag */ +#define UART_CLEAR_FEF USART_ICR_FECF /*!< Framing Error Clear Flag */ +#define UART_CLEAR_NEF USART_ICR_NCF /*!< Noise detected Clear Flag */ +#define UART_CLEAR_OREF USART_ICR_ORECF /*!< Overrun Error Clear Flag */ +#define UART_CLEAR_IDLEF USART_ICR_IDLECF /*!< IDLE line detected Clear Flag */ +#if defined(USART_CR1_FIFOEN) +#define UART_CLEAR_TXFECF USART_ICR_TXFECF /*!< TXFIFO empty clear flag */ +#endif +#define UART_CLEAR_TCF USART_ICR_TCCF /*!< Transmission Complete Clear Flag */ +#define UART_CLEAR_LBDF USART_ICR_LBDCF /*!< LIN Break Detection Clear Flag */ +#define UART_CLEAR_CTSF USART_ICR_CTSCF /*!< CTS Interrupt Clear Flag */ +#define UART_CLEAR_CMF USART_ICR_CMCF /*!< Character Match Clear Flag */ +#define UART_CLEAR_WUF USART_ICR_WUCF /*!< Wake Up from stop mode Clear Flag */ +/** + * @} + */ + + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ +/** @defgroup UART_Exported_Macros UART Exported Macros + * @{ + */ + +/** @brief Reset UART handle states. + * @param __HANDLE__ UART handle. + * @retval None + */ +#define __HAL_UART_RESET_HANDLE_STATE(__HANDLE__) do{ \ + (__HANDLE__)->gState = HAL_UART_STATE_RESET; \ + (__HANDLE__)->RxState = HAL_UART_STATE_RESET; \ + } while(0) +/** @brief Flush the UART Data registers. + * @param __HANDLE__ specifies the UART Handle. + * @retval None + */ +#define __HAL_UART_FLUSH_DRREGISTER(__HANDLE__) \ + do{ \ + SET_BIT((__HANDLE__)->Instance->RQR, UART_RXDATA_FLUSH_REQUEST); \ + SET_BIT((__HANDLE__)->Instance->RQR, UART_TXDATA_FLUSH_REQUEST); \ + } while(0) + +/** @brief Clear the specified UART pending flag. + * @param __HANDLE__ specifies the UART Handle. + * @param __FLAG__ specifies the flag to check. + * This parameter can be any combination of the following values: + * @arg @ref UART_CLEAR_PEF Parity Error Clear Flag + * @arg @ref UART_CLEAR_FEF Framing Error Clear Flag + * @arg @ref UART_CLEAR_NEF Noise detected Clear Flag + * @arg @ref UART_CLEAR_OREF Overrun Error Clear Flag + * @arg @ref UART_CLEAR_IDLEF IDLE line detected Clear Flag + * @arg @ref UART_CLEAR_TXFECF TXFIFO empty clear Flag + * @arg @ref UART_CLEAR_TCF Transmission Complete Clear Flag + * @arg @ref UART_CLEAR_LBDF LIN Break Detection Clear Flag + * @arg @ref UART_CLEAR_CTSF CTS Interrupt Clear Flag + * @arg @ref UART_CLEAR_CMF Character Match Clear Flag + * @arg @ref UART_CLEAR_WUF Wake Up from stop mode Clear Flag + * @retval None + */ +#define __HAL_UART_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->ICR = (__FLAG__)) + +/** @brief Clear the UART PE pending flag. + * @param __HANDLE__ specifies the UART Handle. + * @retval None + */ +#define __HAL_UART_CLEAR_PEFLAG(__HANDLE__) __HAL_UART_CLEAR_FLAG((__HANDLE__), UART_CLEAR_PEF) + +/** @brief Clear the UART FE pending flag. + * @param __HANDLE__ specifies the UART Handle. + * @retval None + */ +#define __HAL_UART_CLEAR_FEFLAG(__HANDLE__) __HAL_UART_CLEAR_FLAG((__HANDLE__), UART_CLEAR_FEF) + +/** @brief Clear the UART NE pending flag. + * @param __HANDLE__ specifies the UART Handle. + * @retval None + */ +#define __HAL_UART_CLEAR_NEFLAG(__HANDLE__) __HAL_UART_CLEAR_FLAG((__HANDLE__), UART_CLEAR_NEF) + +/** @brief Clear the UART ORE pending flag. + * @param __HANDLE__ specifies the UART Handle. + * @retval None + */ +#define __HAL_UART_CLEAR_OREFLAG(__HANDLE__) __HAL_UART_CLEAR_FLAG((__HANDLE__), UART_CLEAR_OREF) + +/** @brief Clear the UART IDLE pending flag. + * @param __HANDLE__ specifies the UART Handle. + * @retval None + */ +#define __HAL_UART_CLEAR_IDLEFLAG(__HANDLE__) __HAL_UART_CLEAR_FLAG((__HANDLE__), UART_CLEAR_IDLEF) + +#if defined(USART_CR1_FIFOEN) +/** @brief Clear the UART TX FIFO empty clear flag. + * @param __HANDLE__ specifies the UART Handle. + * @retval None + */ +#define __HAL_UART_CLEAR_TXFECF(__HANDLE__) __HAL_UART_CLEAR_FLAG((__HANDLE__), UART_CLEAR_TXFECF) +#endif + +/** @brief Check whether the specified UART flag is set or not. + * @param __HANDLE__ specifies the UART Handle. + * @param __FLAG__ specifies the flag to check. + * This parameter can be one of the following values: + * @arg @ref UART_FLAG_TXFT TXFIFO threshold flag + * @arg @ref UART_FLAG_RXFT RXFIFO threshold flag + * @arg @ref UART_FLAG_RXFF RXFIFO Full flag + * @arg @ref UART_FLAG_TXFE TXFIFO Empty flag + * @arg @ref UART_FLAG_REACK Receive enable acknowledge flag + * @arg @ref UART_FLAG_TEACK Transmit enable acknowledge flag + * @arg @ref UART_FLAG_WUF Wake up from stop mode flag + * @arg @ref UART_FLAG_RWU Receiver wake up flag (if the UART in mute mode) + * @arg @ref UART_FLAG_SBKF Send Break flag + * @arg @ref UART_FLAG_CMF Character match flag + * @arg @ref UART_FLAG_BUSY Busy flag + * @arg @ref UART_FLAG_ABRF Auto Baud rate detection flag + * @arg @ref UART_FLAG_ABRE Auto Baud rate detection error flag + * @arg @ref UART_FLAG_CTS CTS Change flag + * @arg @ref UART_FLAG_LBDF LIN Break detection flag + * @arg @ref UART_FLAG_TXE Transmit data register empty flag + * @arg @ref UART_FLAG_TXFNF UART TXFIFO not full flag + * @arg @ref UART_FLAG_TC Transmission Complete flag + * @arg @ref UART_FLAG_RXNE Receive data register not empty flag + * @arg @ref UART_FLAG_RXFNE UART RXFIFO not empty flag + * @arg @ref UART_FLAG_IDLE Idle Line detection flag + * @arg @ref UART_FLAG_ORE Overrun Error flag + * @arg @ref UART_FLAG_NE Noise Error flag + * @arg @ref UART_FLAG_FE Framing Error flag + * @arg @ref UART_FLAG_PE Parity Error flag + * @retval The new state of __FLAG__ (TRUE or FALSE). + */ +#define __HAL_UART_GET_FLAG(__HANDLE__, __FLAG__) (((__HANDLE__)->Instance->ISR & (__FLAG__)) == (__FLAG__)) + +/** @brief Enable the specified UART interrupt. + * @param __HANDLE__ specifies the UART Handle. + * @param __INTERRUPT__ specifies the UART interrupt source to enable. + * This parameter can be one of the following values: + * @arg @ref UART_IT_RXFF RXFIFO Full interrupt + * @arg @ref UART_IT_TXFE TXFIFO Empty interrupt + * @arg @ref UART_IT_RXFT RXFIFO threshold interrupt + * @arg @ref UART_IT_TXFT TXFIFO threshold interrupt + * @arg @ref UART_IT_WUF Wakeup from stop mode interrupt + * @arg @ref UART_IT_CM Character match interrupt + * @arg @ref UART_IT_CTS CTS change interrupt + * @arg @ref UART_IT_LBD LIN Break detection interrupt + * @arg @ref UART_IT_TXE Transmit Data Register empty interrupt + * @arg @ref UART_IT_TXFNF TX FIFO not full interrupt + * @arg @ref UART_IT_TC Transmission complete interrupt + * @arg @ref UART_IT_RXNE Receive Data register not empty interrupt + * @arg @ref UART_IT_RXFNE RXFIFO not empty interrupt + * @arg @ref UART_IT_IDLE Idle line detection interrupt + * @arg @ref UART_IT_PE Parity Error interrupt + * @arg @ref UART_IT_ERR Error interrupt (Frame error, noise error, overrun error) + * @retval None + */ +#define __HAL_UART_ENABLE_IT(__HANDLE__, __INTERRUPT__) (((((uint8_t)(__INTERRUPT__)) >> 5U) == 1U)? ((__HANDLE__)->Instance->CR1 |= (1U << ((__INTERRUPT__) & UART_IT_MASK))): \ + ((((uint8_t)(__INTERRUPT__)) >> 5U) == 2U)? ((__HANDLE__)->Instance->CR2 |= (1U << ((__INTERRUPT__) & UART_IT_MASK))): \ + ((__HANDLE__)->Instance->CR3 |= (1U << ((__INTERRUPT__) & UART_IT_MASK)))) + + +/** @brief Disable the specified UART interrupt. + * @param __HANDLE__ specifies the UART Handle. + * @param __INTERRUPT__ specifies the UART interrupt source to disable. + * This parameter can be one of the following values: + * @arg @ref UART_IT_RXFF RXFIFO Full interrupt + * @arg @ref UART_IT_TXFE TXFIFO Empty interrupt + * @arg @ref UART_IT_RXFT RXFIFO threshold interrupt + * @arg @ref UART_IT_TXFT TXFIFO threshold interrupt + * @arg @ref UART_IT_WUF Wakeup from stop mode interrupt + * @arg @ref UART_IT_CM Character match interrupt + * @arg @ref UART_IT_CTS CTS change interrupt + * @arg @ref UART_IT_LBD LIN Break detection interrupt + * @arg @ref UART_IT_TXE Transmit Data Register empty interrupt + * @arg @ref UART_IT_TXFNF TX FIFO not full interrupt + * @arg @ref UART_IT_TC Transmission complete interrupt + * @arg @ref UART_IT_RXNE Receive Data register not empty interrupt + * @arg @ref UART_IT_RXFNE RXFIFO not empty interrupt + * @arg @ref UART_IT_IDLE Idle line detection interrupt + * @arg @ref UART_IT_PE Parity Error interrupt + * @arg @ref UART_IT_ERR Error interrupt (Frame error, noise error, overrun error) + * @retval None + */ +#define __HAL_UART_DISABLE_IT(__HANDLE__, __INTERRUPT__) (((((uint8_t)(__INTERRUPT__)) >> 5U) == 1U)? ((__HANDLE__)->Instance->CR1 &= ~ (1U << ((__INTERRUPT__) & UART_IT_MASK))): \ + ((((uint8_t)(__INTERRUPT__)) >> 5U) == 2U)? ((__HANDLE__)->Instance->CR2 &= ~ (1U << ((__INTERRUPT__) & UART_IT_MASK))): \ + ((__HANDLE__)->Instance->CR3 &= ~ (1U << ((__INTERRUPT__) & UART_IT_MASK)))) + +/** @brief Check whether the specified UART interrupt has occurred or not. + * @param __HANDLE__ specifies the UART Handle. + * @param __INTERRUPT__ specifies the UART interrupt to check. + * This parameter can be one of the following values: + * @arg @ref UART_IT_RXFF RXFIFO Full interrupt + * @arg @ref UART_IT_TXFE TXFIFO Empty interrupt + * @arg @ref UART_IT_RXFT RXFIFO threshold interrupt + * @arg @ref UART_IT_TXFT TXFIFO threshold interrupt + * @arg @ref UART_IT_WUF Wakeup from stop mode interrupt + * @arg @ref UART_IT_CM Character match interrupt + * @arg @ref UART_IT_CTS CTS change interrupt + * @arg @ref UART_IT_LBD LIN Break detection interrupt + * @arg @ref UART_IT_TXE Transmit Data Register empty interrupt + * @arg @ref UART_IT_TXFNF TX FIFO not full interrupt + * @arg @ref UART_IT_TC Transmission complete interrupt + * @arg @ref UART_IT_RXNE Receive Data register not empty interrupt + * @arg @ref UART_IT_RXFNE RXFIFO not empty interrupt + * @arg @ref UART_IT_IDLE Idle line detection interrupt + * @arg @ref UART_IT_PE Parity Error interrupt + * @arg @ref UART_IT_ERR Error interrupt (Frame error, noise error, overrun error) + * @retval The new state of __INTERRUPT__ (SET or RESET). + */ +#define __HAL_UART_GET_IT(__HANDLE__, __INTERRUPT__) ((((__HANDLE__)->Instance->ISR & (1U << ((__INTERRUPT__)>> 8U))) != RESET) ? SET : RESET) + +/** @brief Check whether the specified UART interrupt source is enabled or not. + * @param __HANDLE__ specifies the UART Handle. + * @param __INTERRUPT__ specifies the UART interrupt source to check. + * This parameter can be one of the following values: + * @arg @ref UART_IT_RXFF RXFIFO Full interrupt + * @arg @ref UART_IT_TXFE TXFIFO Empty interrupt + * @arg @ref UART_IT_RXFT RXFIFO threshold interrupt + * @arg @ref UART_IT_TXFT TXFIFO threshold interrupt + * @arg @ref UART_IT_WUF Wakeup from stop mode interrupt + * @arg @ref UART_IT_CM Character match interrupt + * @arg @ref UART_IT_CTS CTS change interrupt + * @arg @ref UART_IT_LBD LIN Break detection interrupt + * @arg @ref UART_IT_TXE Transmit Data Register empty interrupt + * @arg @ref UART_IT_TXFNF TX FIFO not full interrupt + * @arg @ref UART_IT_TC Transmission complete interrupt + * @arg @ref UART_IT_RXNE Receive Data register not empty interrupt + * @arg @ref UART_IT_RXFNE RXFIFO not empty interrupt + * @arg @ref UART_IT_IDLE Idle line detection interrupt + * @arg @ref UART_IT_PE Parity Error interrupt + * @arg @ref UART_IT_ERR Error interrupt (Frame error, noise error, overrun error) + * @retval The new state of __INTERRUPT__ (SET or RESET). + */ +#define __HAL_UART_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) ((((((((uint8_t)(__INTERRUPT__)) >> 5U) == 1U) ? (__HANDLE__)->Instance->CR1 : \ + (((((uint8_t)(__INTERRUPT__)) >> 5U) == 2U) ? (__HANDLE__)->Instance->CR2 : \ + (__HANDLE__)->Instance->CR3)) & (1U << (((uint16_t)(__INTERRUPT__)) & UART_IT_MASK))) != RESET) ? SET : RESET) + +/** @brief Clear the specified UART ISR flag, in setting the proper ICR register flag. + * @param __HANDLE__ specifies the UART Handle. + * @param __IT_CLEAR__ specifies the interrupt clear register flag that needs to be set + * to clear the corresponding interrupt + * This parameter can be one of the following values: + * @arg @ref UART_CLEAR_PEF Parity Error Clear Flag + * @arg @ref UART_CLEAR_FEF Framing Error Clear Flag + * @arg @ref UART_CLEAR_NEF Noise detected Clear Flag + * @arg @ref UART_CLEAR_OREF Overrun Error Clear Flag + * @arg @ref UART_CLEAR_IDLEF IDLE line detected Clear Flag + * @arg @ref UART_CLEAR_TXFECF TXFIFO empty Clear Flag + * @arg @ref UART_CLEAR_TCF Transmission Complete Clear Flag + * @arg @ref UART_CLEAR_LBDF LIN Break Detection Clear Flag + * @arg @ref UART_CLEAR_CTSF CTS Interrupt Clear Flag + * @arg @ref UART_CLEAR_CMF Character Match Clear Flag + * @arg @ref UART_CLEAR_WUF Wake Up from stop mode Clear Flag + * @retval None + */ +#define __HAL_UART_CLEAR_IT(__HANDLE__, __IT_CLEAR__) ((__HANDLE__)->Instance->ICR = (uint32_t)(__IT_CLEAR__)) + +/** @brief Set a specific UART request flag. + * @param __HANDLE__ specifies the UART Handle. + * @param __REQ__ specifies the request flag to set + * This parameter can be one of the following values: + * @arg @ref UART_AUTOBAUD_REQUEST Auto-Baud Rate Request + * @arg @ref UART_SENDBREAK_REQUEST Send Break Request + * @arg @ref UART_MUTE_MODE_REQUEST Mute Mode Request + * @arg @ref UART_RXDATA_FLUSH_REQUEST Receive Data flush Request + * @arg @ref UART_TXDATA_FLUSH_REQUEST Transmit data flush Request + * @retval None + */ +#define __HAL_UART_SEND_REQ(__HANDLE__, __REQ__) ((__HANDLE__)->Instance->RQR |= (__REQ__)) + +/** @brief Enable the UART one bit sample method. + * @param __HANDLE__ specifies the UART Handle. + * @retval None + */ +#define __HAL_UART_ONE_BIT_SAMPLE_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR3|= USART_CR3_ONEBIT) + +/** @brief Disable the UART one bit sample method. + * @param __HANDLE__ specifies the UART Handle. + * @retval None + */ +#define __HAL_UART_ONE_BIT_SAMPLE_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR3 &= ~USART_CR3_ONEBIT) + +/** @brief Enable UART. + * @param __HANDLE__ specifies the UART Handle. + * @retval None + */ +#define __HAL_UART_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR1 |= USART_CR1_UE) + +/** @brief Disable UART. + * @param __HANDLE__ specifies the UART Handle. + * @retval None + */ +#define __HAL_UART_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR1 &= ~USART_CR1_UE) + +/** @brief Enable CTS flow control. + * @note This macro allows to enable CTS hardware flow control for a given UART instance, + * without need to call HAL_UART_Init() function. + * As involving direct access to UART registers, usage of this macro should be fully endorsed by user. + * @note As macro is expected to be used for modifying CTS Hw flow control feature activation, without need + * for USART instance Deinit/Init, following conditions for macro call should be fulfilled : + * - UART instance should have already been initialised (through call of HAL_UART_Init() ) + * - macro could only be called when corresponding UART instance is disabled (i.e. __HAL_UART_DISABLE(__HANDLE__)) + * and should be followed by an Enable macro (i.e. __HAL_UART_ENABLE(__HANDLE__)). + * @param __HANDLE__ specifies the UART Handle. + * @retval None + */ +#define __HAL_UART_HWCONTROL_CTS_ENABLE(__HANDLE__) \ + do{ \ + SET_BIT((__HANDLE__)->Instance->CR3, USART_CR3_CTSE); \ + (__HANDLE__)->Init.HwFlowCtl |= USART_CR3_CTSE; \ + } while(0) + +/** @brief Disable CTS flow control. + * @note This macro allows to disable CTS hardware flow control for a given UART instance, + * without need to call HAL_UART_Init() function. + * As involving direct access to UART registers, usage of this macro should be fully endorsed by user. + * @note As macro is expected to be used for modifying CTS Hw flow control feature activation, without need + * for USART instance Deinit/Init, following conditions for macro call should be fulfilled : + * - UART instance should have already been initialised (through call of HAL_UART_Init() ) + * - macro could only be called when corresponding UART instance is disabled (i.e. __HAL_UART_DISABLE(__HANDLE__)) + * and should be followed by an Enable macro (i.e. __HAL_UART_ENABLE(__HANDLE__)). + * @param __HANDLE__ specifies the UART Handle. + * @retval None + */ +#define __HAL_UART_HWCONTROL_CTS_DISABLE(__HANDLE__) \ + do{ \ + CLEAR_BIT((__HANDLE__)->Instance->CR3, USART_CR3_CTSE); \ + (__HANDLE__)->Init.HwFlowCtl &= ~(USART_CR3_CTSE); \ + } while(0) + +/** @brief Enable RTS flow control. + * @note This macro allows to enable RTS hardware flow control for a given UART instance, + * without need to call HAL_UART_Init() function. + * As involving direct access to UART registers, usage of this macro should be fully endorsed by user. + * @note As macro is expected to be used for modifying RTS Hw flow control feature activation, without need + * for USART instance Deinit/Init, following conditions for macro call should be fulfilled : + * - UART instance should have already been initialised (through call of HAL_UART_Init() ) + * - macro could only be called when corresponding UART instance is disabled (i.e. __HAL_UART_DISABLE(__HANDLE__)) + * and should be followed by an Enable macro (i.e. __HAL_UART_ENABLE(__HANDLE__)). + * @param __HANDLE__ specifies the UART Handle. + * @retval None + */ +#define __HAL_UART_HWCONTROL_RTS_ENABLE(__HANDLE__) \ + do{ \ + SET_BIT((__HANDLE__)->Instance->CR3, USART_CR3_RTSE); \ + (__HANDLE__)->Init.HwFlowCtl |= USART_CR3_RTSE; \ + } while(0) + +/** @brief Disable RTS flow control. + * @note This macro allows to disable RTS hardware flow control for a given UART instance, + * without need to call HAL_UART_Init() function. + * As involving direct access to UART registers, usage of this macro should be fully endorsed by user. + * @note As macro is expected to be used for modifying RTS Hw flow control feature activation, without need + * for USART instance Deinit/Init, following conditions for macro call should be fulfilled : + * - UART instance should have already been initialised (through call of HAL_UART_Init() ) + * - macro could only be called when corresponding UART instance is disabled (i.e. __HAL_UART_DISABLE(__HANDLE__)) + * and should be followed by an Enable macro (i.e. __HAL_UART_ENABLE(__HANDLE__)). + * @param __HANDLE__ specifies the UART Handle. + * @retval None + */ +#define __HAL_UART_HWCONTROL_RTS_DISABLE(__HANDLE__) \ + do{ \ + CLEAR_BIT((__HANDLE__)->Instance->CR3, USART_CR3_RTSE);\ + (__HANDLE__)->Init.HwFlowCtl &= ~(USART_CR3_RTSE); \ + } while(0) +/** + * @} + */ + +/* Private variables -----------------------------------------------------*/ +#if defined(USART_PRESC_PRESCALER) +/** @defgroup UART_Private_Variables UART Private Variables + * @{ + */ +static const uint16_t UARTPrescTable[12] = {1, 2, 4, 6, 8, 10, 12, 16, 32, 64, 128, 256}; +/** + * @} + */ +#endif + +/* Private macros --------------------------------------------------------*/ +/** @defgroup UART_Private_Macros UART Private Macros + * @{ + */ +#if defined(USART_PRESC_PRESCALER) + +/** @brief BRR division operation to set BRR register with LPUART. + * @param __PCLK__ LPUART clock. + * @param __BAUD__ Baud rate set by the user. + * @param __CLOCKPRESCALER__ UART prescaler value. + * @retval Division result + */ +#define UART_DIV_LPUART(__PCLK__, __BAUD__, __CLOCKPRESCALER__) ((((((uint64_t)(__PCLK__)/UARTPrescTable[(__CLOCKPRESCALER__)])*256)) + ((__BAUD__)/2)) / (__BAUD__)) + +/** @brief BRR division operation to set BRR register in 8-bit oversampling mode. + * @param __PCLK__ UART clock. + * @param __BAUD__ Baud rate set by the user. + * @param __CLOCKPRESCALER__ UART prescaler value. + * @retval Division result + */ +#define UART_DIV_SAMPLING8(__PCLK__, __BAUD__, __CLOCKPRESCALER__) (((((__PCLK__)/UARTPrescTable[(__CLOCKPRESCALER__)])*2) + ((__BAUD__)/2)) / (__BAUD__)) + +/** @brief BRR division operation to set BRR register in 16-bit oversampling mode. + * @param __PCLK__ UART clock. + * @param __BAUD__ Baud rate set by the user. + * @param __CLOCKPRESCALER__ UART prescaler value. + * @retval Division result + */ +#define UART_DIV_SAMPLING16(__PCLK__, __BAUD__, __CLOCKPRESCALER__) ((((__PCLK__)/UARTPrescTable[(__CLOCKPRESCALER__)]) + ((__BAUD__)/2)) / (__BAUD__)) + +#else + +/** @brief BRR division operation to set BRR register with LPUART. + * @param __PCLK__ LPUART clock. + * @param __BAUD__ Baud rate set by the user. + * @retval Division result + */ +#define UART_DIV_LPUART(__PCLK__, __BAUD__) (((((uint64_t)(__PCLK__)*256)) + ((__BAUD__)/2)) / (__BAUD__)) + +/** @brief BRR division operation to set BRR register in 8-bit oversampling mode. + * @param __PCLK__ UART clock. + * @param __BAUD__ Baud rate set by the user. + * @retval Division result + */ +#define UART_DIV_SAMPLING8(__PCLK__, __BAUD__) ((((__PCLK__)*2) + ((__BAUD__)/2)) / (__BAUD__)) + +/** @brief BRR division operation to set BRR register in 16-bit oversampling mode. + * @param __PCLK__ UART clock. + * @param __BAUD__ Baud rate set by the user. + * @retval Division result + */ +#define UART_DIV_SAMPLING16(__PCLK__, __BAUD__) (((__PCLK__) + ((__BAUD__)/2)) / (__BAUD__)) + +#endif /* USART_PRESC_PRESCALER */ + +/** @brief Check whether or not UART instance is Low Power UART. + * @param __HANDLE__ specifies the UART Handle. + * @retval SET (instance is LPUART) or RESET (instance isn't LPUART) + */ +#define UART_INSTANCE_LOWPOWER(__HANDLE__) (IS_LPUART_INSTANCE(__HANDLE__->Instance)) + +/** @brief Check UART Baud rate. + * @param __BAUDRATE__ Baudrate specified by the user. + * The maximum Baud Rate is derived from the maximum clock on G0 (i.e. 52 MHz) + * divided by the smallest oversampling used on the USART (i.e. 8) + * @retval SET (__BAUDRATE__ is valid) or RESET (__BAUDRATE__ is invalid) + */ +#define IS_UART_BAUDRATE(__BAUDRATE__) ((__BAUDRATE__) < 6500001U) + +/** @brief Check UART assertion time. + * @param __TIME__ 5-bit value assertion time. + * @retval Test result (TRUE or FALSE). + */ +#define IS_UART_ASSERTIONTIME(__TIME__) ((__TIME__) <= 0x1FU) + +/** @brief Check UART deassertion time. + * @param __TIME__ 5-bit value deassertion time. + * @retval Test result (TRUE or FALSE). + */ +#define IS_UART_DEASSERTIONTIME(__TIME__) ((__TIME__) <= 0x1FU) + +/** + * @brief Ensure that UART frame number of stop bits is valid. + * @param __STOPBITS__ UART frame number of stop bits. + * @retval SET (__STOPBITS__ is valid) or RESET (__STOPBITS__ is invalid) + */ +#define IS_UART_STOPBITS(__STOPBITS__) (((__STOPBITS__) == UART_STOPBITS_0_5) || \ + ((__STOPBITS__) == UART_STOPBITS_1) || \ + ((__STOPBITS__) == UART_STOPBITS_1_5) || \ + ((__STOPBITS__) == UART_STOPBITS_2)) + +/** + * @brief Ensure that LPUART frame number of stop bits is valid. + * @param __STOPBITS__ LPUART frame number of stop bits. + * @retval SET (__STOPBITS__ is valid) or RESET (__STOPBITS__ is invalid) + */ +#define IS_LPUART_STOPBITS(__STOPBITS__) (((__STOPBITS__) == UART_STOPBITS_1) || \ + ((__STOPBITS__) == UART_STOPBITS_2)) + +/** + * @brief Ensure that UART frame parity is valid. + * @param __PARITY__ UART frame parity. + * @retval SET (__PARITY__ is valid) or RESET (__PARITY__ is invalid) + */ +#define IS_UART_PARITY(__PARITY__) (((__PARITY__) == UART_PARITY_NONE) || \ + ((__PARITY__) == UART_PARITY_EVEN) || \ + ((__PARITY__) == UART_PARITY_ODD)) + +/** + * @brief Ensure that UART hardware flow control is valid. + * @param __CONTROL__ UART hardware flow control. + * @retval SET (__CONTROL__ is valid) or RESET (__CONTROL__ is invalid) + */ +#define IS_UART_HARDWARE_FLOW_CONTROL(__CONTROL__)\ + (((__CONTROL__) == UART_HWCONTROL_NONE) || \ + ((__CONTROL__) == UART_HWCONTROL_RTS) || \ + ((__CONTROL__) == UART_HWCONTROL_CTS) || \ + ((__CONTROL__) == UART_HWCONTROL_RTS_CTS)) + +/** + * @brief Ensure that UART communication mode is valid. + * @param __MODE__ UART communication mode. + * @retval SET (__MODE__ is valid) or RESET (__MODE__ is invalid) + */ +#define IS_UART_MODE(__MODE__) ((((__MODE__) & (~((uint32_t)(UART_MODE_TX_RX)))) == 0x00U) && ((__MODE__) != 0x00U)) + +/** + * @brief Ensure that UART state is valid. + * @param __STATE__ UART state. + * @retval SET (__STATE__ is valid) or RESET (__STATE__ is invalid) + */ +#define IS_UART_STATE(__STATE__) (((__STATE__) == UART_STATE_DISABLE) || \ + ((__STATE__) == UART_STATE_ENABLE)) + +/** + * @brief Ensure that UART oversampling is valid. + * @param __SAMPLING__ UART oversampling. + * @retval SET (__SAMPLING__ is valid) or RESET (__SAMPLING__ is invalid) + */ +#define IS_UART_OVERSAMPLING(__SAMPLING__) (((__SAMPLING__) == UART_OVERSAMPLING_16) || \ + ((__SAMPLING__) == UART_OVERSAMPLING_8)) + +/** + * @brief Ensure that UART frame sampling is valid. + * @param __ONEBIT__ UART frame sampling. + * @retval SET (__ONEBIT__ is valid) or RESET (__ONEBIT__ is invalid) + */ +#define IS_UART_ONE_BIT_SAMPLE(__ONEBIT__) (((__ONEBIT__) == UART_ONE_BIT_SAMPLE_DISABLE) || \ + ((__ONEBIT__) == UART_ONE_BIT_SAMPLE_ENABLE)) + +/** + * @brief Ensure that UART auto Baud rate detection mode is valid. + * @param __MODE__ UART auto Baud rate detection mode. + * @retval SET (__MODE__ is valid) or RESET (__MODE__ is invalid) + */ +#define IS_UART_ADVFEATURE_AUTOBAUDRATEMODE(__MODE__) (((__MODE__) == UART_ADVFEATURE_AUTOBAUDRATE_ONSTARTBIT) || \ + ((__MODE__) == UART_ADVFEATURE_AUTOBAUDRATE_ONFALLINGEDGE) || \ + ((__MODE__) == UART_ADVFEATURE_AUTOBAUDRATE_ON0X7FFRAME) || \ + ((__MODE__) == UART_ADVFEATURE_AUTOBAUDRATE_ON0X55FRAME)) + +/** + * @brief Ensure that UART receiver timeout setting is valid. + * @param __TIMEOUT__ UART receiver timeout setting. + * @retval SET (__TIMEOUT__ is valid) or RESET (__TIMEOUT__ is invalid) + */ +#define IS_UART_RECEIVER_TIMEOUT(__TIMEOUT__) (((__TIMEOUT__) == UART_RECEIVER_TIMEOUT_DISABLE) || \ + ((__TIMEOUT__) == UART_RECEIVER_TIMEOUT_ENABLE)) + +/** + * @brief Ensure that UART LIN state is valid. + * @param __LIN__ UART LIN state. + * @retval SET (__LIN__ is valid) or RESET (__LIN__ is invalid) + */ +#define IS_UART_LIN(__LIN__) (((__LIN__) == UART_LIN_DISABLE) || \ + ((__LIN__) == UART_LIN_ENABLE)) + +/** + * @brief Ensure that UART LIN break detection length is valid. + * @param __LENGTH__ UART LIN break detection length. + * @retval SET (__LENGTH__ is valid) or RESET (__LENGTH__ is invalid) + */ +#define IS_UART_LIN_BREAK_DETECT_LENGTH(__LENGTH__) (((__LENGTH__) == UART_LINBREAKDETECTLENGTH_10B) || \ + ((__LENGTH__) == UART_LINBREAKDETECTLENGTH_11B)) + +/** + * @brief Ensure that UART DMA TX state is valid. + * @param __DMATX__ UART DMA TX state. + * @retval SET (__DMATX__ is valid) or RESET (__DMATX__ is invalid) + */ +#define IS_UART_DMA_TX(__DMATX__) (((__DMATX__) == UART_DMA_TX_DISABLE) || \ + ((__DMATX__) == UART_DMA_TX_ENABLE)) + +/** + * @brief Ensure that UART DMA RX state is valid. + * @param __DMARX__ UART DMA RX state. + * @retval SET (__DMARX__ is valid) or RESET (__DMARX__ is invalid) + */ +#define IS_UART_DMA_RX(__DMARX__) (((__DMARX__) == UART_DMA_RX_DISABLE) || \ + ((__DMARX__) == UART_DMA_RX_ENABLE)) + +/** + * @brief Ensure that UART half-duplex state is valid. + * @param __HDSEL__ UART half-duplex state. + * @retval SET (__HDSEL__ is valid) or RESET (__HDSEL__ is invalid) + */ +#define IS_UART_HALF_DUPLEX(__HDSEL__) (((__HDSEL__) == UART_HALF_DUPLEX_DISABLE) || \ + ((__HDSEL__) == UART_HALF_DUPLEX_ENABLE)) + +/** + * @brief Ensure that UART wake-up method is valid. + * @param __WAKEUP__ UART wake-up method . + * @retval SET (__WAKEUP__ is valid) or RESET (__WAKEUP__ is invalid) + */ +#define IS_UART_WAKEUPMETHOD(__WAKEUP__) (((__WAKEUP__) == UART_WAKEUPMETHOD_IDLELINE) || \ + ((__WAKEUP__) == UART_WAKEUPMETHOD_ADDRESSMARK)) + +/** + * @brief Ensure that UART request parameter is valid. + * @param __PARAM__ UART request parameter. + * @retval SET (__PARAM__ is valid) or RESET (__PARAM__ is invalid) + */ +#define IS_UART_REQUEST_PARAMETER(__PARAM__) (((__PARAM__) == UART_AUTOBAUD_REQUEST) || \ + ((__PARAM__) == UART_SENDBREAK_REQUEST) || \ + ((__PARAM__) == UART_MUTE_MODE_REQUEST) || \ + ((__PARAM__) == UART_RXDATA_FLUSH_REQUEST) || \ + ((__PARAM__) == UART_TXDATA_FLUSH_REQUEST)) + +/** + * @brief Ensure that UART advanced features initialization is valid. + * @param __INIT__ UART advanced features initialization. + * @retval SET (__INIT__ is valid) or RESET (__INIT__ is invalid) + */ +#define IS_UART_ADVFEATURE_INIT(__INIT__) ((__INIT__) <= (UART_ADVFEATURE_NO_INIT | \ + UART_ADVFEATURE_TXINVERT_INIT | \ + UART_ADVFEATURE_RXINVERT_INIT | \ + UART_ADVFEATURE_DATAINVERT_INIT | \ + UART_ADVFEATURE_SWAP_INIT | \ + UART_ADVFEATURE_RXOVERRUNDISABLE_INIT | \ + UART_ADVFEATURE_DMADISABLEONERROR_INIT | \ + UART_ADVFEATURE_AUTOBAUDRATE_INIT | \ + UART_ADVFEATURE_MSBFIRST_INIT)) + +/** + * @brief Ensure that UART frame TX inversion setting is valid. + * @param __TXINV__ UART frame TX inversion setting. + * @retval SET (__TXINV__ is valid) or RESET (__TXINV__ is invalid) + */ +#define IS_UART_ADVFEATURE_TXINV(__TXINV__) (((__TXINV__) == UART_ADVFEATURE_TXINV_DISABLE) || \ + ((__TXINV__) == UART_ADVFEATURE_TXINV_ENABLE)) + +/** + * @brief Ensure that UART frame RX inversion setting is valid. + * @param __RXINV__ UART frame RX inversion setting. + * @retval SET (__RXINV__ is valid) or RESET (__RXINV__ is invalid) + */ +#define IS_UART_ADVFEATURE_RXINV(__RXINV__) (((__RXINV__) == UART_ADVFEATURE_RXINV_DISABLE) || \ + ((__RXINV__) == UART_ADVFEATURE_RXINV_ENABLE)) + +/** + * @brief Ensure that UART frame data inversion setting is valid. + * @param __DATAINV__ UART frame data inversion setting. + * @retval SET (__DATAINV__ is valid) or RESET (__DATAINV__ is invalid) + */ +#define IS_UART_ADVFEATURE_DATAINV(__DATAINV__) (((__DATAINV__) == UART_ADVFEATURE_DATAINV_DISABLE) || \ + ((__DATAINV__) == UART_ADVFEATURE_DATAINV_ENABLE)) + +/** + * @brief Ensure that UART frame RX/TX pins swap setting is valid. + * @param __SWAP__ UART frame RX/TX pins swap setting. + * @retval SET (__SWAP__ is valid) or RESET (__SWAP__ is invalid) + */ +#define IS_UART_ADVFEATURE_SWAP(__SWAP__) (((__SWAP__) == UART_ADVFEATURE_SWAP_DISABLE) || \ + ((__SWAP__) == UART_ADVFEATURE_SWAP_ENABLE)) + +/** + * @brief Ensure that UART frame overrun setting is valid. + * @param __OVERRUN__ UART frame overrun setting. + * @retval SET (__OVERRUN__ is valid) or RESET (__OVERRUN__ is invalid) + */ +#define IS_UART_OVERRUN(__OVERRUN__) (((__OVERRUN__) == UART_ADVFEATURE_OVERRUN_ENABLE) || \ + ((__OVERRUN__) == UART_ADVFEATURE_OVERRUN_DISABLE)) + +/** + * @brief Ensure that UART auto Baud rate state is valid. + * @param __AUTOBAUDRATE__ UART auto Baud rate state. + * @retval SET (__AUTOBAUDRATE__ is valid) or RESET (__AUTOBAUDRATE__ is invalid) + */ +#define IS_UART_ADVFEATURE_AUTOBAUDRATE(__AUTOBAUDRATE__) (((__AUTOBAUDRATE__) == UART_ADVFEATURE_AUTOBAUDRATE_DISABLE) || \ + ((__AUTOBAUDRATE__) == UART_ADVFEATURE_AUTOBAUDRATE_ENABLE)) + +/** + * @brief Ensure that UART DMA enabling or disabling on error setting is valid. + * @param __DMA__ UART DMA enabling or disabling on error setting. + * @retval SET (__DMA__ is valid) or RESET (__DMA__ is invalid) + */ +#define IS_UART_ADVFEATURE_DMAONRXERROR(__DMA__) (((__DMA__) == UART_ADVFEATURE_DMA_ENABLEONRXERROR) || \ + ((__DMA__) == UART_ADVFEATURE_DMA_DISABLEONRXERROR)) + +/** + * @brief Ensure that UART frame MSB first setting is valid. + * @param __MSBFIRST__ UART frame MSB first setting. + * @retval SET (__MSBFIRST__ is valid) or RESET (__MSBFIRST__ is invalid) + */ +#define IS_UART_ADVFEATURE_MSBFIRST(__MSBFIRST__) (((__MSBFIRST__) == UART_ADVFEATURE_MSBFIRST_DISABLE) || \ + ((__MSBFIRST__) == UART_ADVFEATURE_MSBFIRST_ENABLE)) + +/** + * @brief Ensure that UART stop mode state is valid. + * @param __STOPMODE__ UART stop mode state. + * @retval SET (__STOPMODE__ is valid) or RESET (__STOPMODE__ is invalid) + */ +#define IS_UART_ADVFEATURE_STOPMODE(__STOPMODE__) (((__STOPMODE__) == UART_ADVFEATURE_STOPMODE_DISABLE) || \ + ((__STOPMODE__) == UART_ADVFEATURE_STOPMODE_ENABLE)) + +/** + * @brief Ensure that UART mute mode state is valid. + * @param __MUTE__ UART mute mode state. + * @retval SET (__MUTE__ is valid) or RESET (__MUTE__ is invalid) + */ +#define IS_UART_MUTE_MODE(__MUTE__) (((__MUTE__) == UART_ADVFEATURE_MUTEMODE_DISABLE) || \ + ((__MUTE__) == UART_ADVFEATURE_MUTEMODE_ENABLE)) + +/** + * @brief Ensure that UART wake-up selection is valid. + * @param __WAKE__ UART wake-up selection. + * @retval SET (__WAKE__ is valid) or RESET (__WAKE__ is invalid) + */ +#define IS_UART_WAKEUP_SELECTION(__WAKE__) (((__WAKE__) == UART_WAKEUP_ON_ADDRESS) || \ + ((__WAKE__) == UART_WAKEUP_ON_STARTBIT) || \ + ((__WAKE__) == UART_WAKEUP_ON_READDATA_NONEMPTY)) + +/** + * @brief Ensure that UART driver enable polarity is valid. + * @param __POLARITY__ UART driver enable polarity. + * @retval SET (__POLARITY__ is valid) or RESET (__POLARITY__ is invalid) + */ +#define IS_UART_DE_POLARITY(__POLARITY__) (((__POLARITY__) == UART_DE_POLARITY_HIGH) || \ + ((__POLARITY__) == UART_DE_POLARITY_LOW)) + +#if defined(USART_PRESC_PRESCALER) +/** + * @brief Ensure that UART Prescaler is valid. + * @param __CLOCKPRESCALER__ UART Prescaler value. + * @retval SET (__CLOCKPRESCALER__ is valid) or RESET (__CLOCKPRESCALER__ is invalid) + */ +#define IS_UART_PRESCALER(__CLOCKPRESCALER__) (((__CLOCKPRESCALER__) == UART_PRESCALER_DIV1) || \ + ((__CLOCKPRESCALER__) == UART_PRESCALER_DIV2) || \ + ((__CLOCKPRESCALER__) == UART_PRESCALER_DIV4) || \ + ((__CLOCKPRESCALER__) == UART_PRESCALER_DIV6) || \ + ((__CLOCKPRESCALER__) == UART_PRESCALER_DIV8) || \ + ((__CLOCKPRESCALER__) == UART_PRESCALER_DIV10) || \ + ((__CLOCKPRESCALER__) == UART_PRESCALER_DIV12) || \ + ((__CLOCKPRESCALER__) == UART_PRESCALER_DIV16) || \ + ((__CLOCKPRESCALER__) == UART_PRESCALER_DIV32) || \ + ((__CLOCKPRESCALER__) == UART_PRESCALER_DIV64) || \ + ((__CLOCKPRESCALER__) == UART_PRESCALER_DIV128) || \ + ((__CLOCKPRESCALER__) == UART_PRESCALER_DIV256)) +#endif + +#if defined(USART_CR1_FIFOEN) +/** + * @brief Ensure that UART TXFIFO threshold level is valid. + * @param __THRESHOLD__ UART TXFIFO threshold level. + * @retval SET (__THRESHOLD__ is valid) or RESET (__THRESHOLD__ is invalid) + */ +#define IS_UART_TXFIFO_THRESHOLD(__THRESHOLD__) (((__THRESHOLD__) == UART_TXFIFO_THRESHOLD_1_8) || \ + ((__THRESHOLD__) == UART_TXFIFO_THRESHOLD_1_4) || \ + ((__THRESHOLD__) == UART_TXFIFO_THRESHOLD_1_2) || \ + ((__THRESHOLD__) == UART_TXFIFO_THRESHOLD_3_4) || \ + ((__THRESHOLD__) == UART_TXFIFO_THRESHOLD_7_8) || \ + ((__THRESHOLD__) == UART_TXFIFO_THRESHOLD_8_8)) + +/** + * @brief Ensure that UART RXFIFO threshold level is valid. + * @param __THRESHOLD__ UART RXFIFO threshold level. + * @retval SET (__THRESHOLD__ is valid) or RESET (__THRESHOLD__ is invalid) + */ +#define IS_UART_RXFIFO_THRESHOLD(__THRESHOLD__) (((__THRESHOLD__) == UART_RXFIFO_THRESHOLD_1_8) || \ + ((__THRESHOLD__) == UART_RXFIFO_THRESHOLD_1_4) || \ + ((__THRESHOLD__) == UART_RXFIFO_THRESHOLD_1_2) || \ + ((__THRESHOLD__) == UART_RXFIFO_THRESHOLD_3_4) || \ + ((__THRESHOLD__) == UART_RXFIFO_THRESHOLD_7_8) || \ + ((__THRESHOLD__) == UART_RXFIFO_THRESHOLD_8_8)) +#endif + +/** + * @} + */ + +/* Include UART HAL Extended module */ +#include "stm32l4xx_hal_uart_ex.h" + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup UART_Exported_Functions UART Exported Functions + * @{ + */ + +/** @addtogroup UART_Exported_Functions_Group1 Initialization and de-initialization functions + * @{ + */ + +/* Initialization and de-initialization functions ****************************/ +HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_HalfDuplex_Init(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_LIN_Init(UART_HandleTypeDef *huart, uint32_t BreakDetectLength); +HAL_StatusTypeDef HAL_MultiProcessor_Init(UART_HandleTypeDef *huart, uint8_t Address, uint32_t WakeUpMethod); +HAL_StatusTypeDef HAL_UART_DeInit (UART_HandleTypeDef *huart); +void HAL_UART_MspInit(UART_HandleTypeDef *huart); +void HAL_UART_MspDeInit(UART_HandleTypeDef *huart); + +/** + * @} + */ + +/** @addtogroup UART_Exported_Functions_Group2 IO operation functions + * @{ + */ + +/* IO operation functions *****************************************************/ +HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_UART_DMAPause(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_UART_DMAResume(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_UART_DMAStop(UART_HandleTypeDef *huart); +/* Transfer Abort functions */ +HAL_StatusTypeDef HAL_UART_Abort(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_UART_AbortTransmit(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_UART_AbortReceive(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_UART_Abort_IT(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_UART_AbortTransmit_IT(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_UART_AbortReceive_IT(UART_HandleTypeDef *huart); + +void HAL_UART_IRQHandler(UART_HandleTypeDef *huart); +void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart); +void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart); +void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart); +void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart); +void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart); +void HAL_UART_AbortCpltCallback (UART_HandleTypeDef *huart); +void HAL_UART_AbortTransmitCpltCallback (UART_HandleTypeDef *huart); +void HAL_UART_AbortReceiveCpltCallback (UART_HandleTypeDef *huart); + +/** + * @} + */ + +/** @addtogroup UART_Exported_Functions_Group3 Peripheral Control functions + * @{ + */ + +/* Peripheral Control functions ************************************************/ +HAL_StatusTypeDef HAL_LIN_SendBreak(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_MultiProcessor_EnableMuteMode(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_MultiProcessor_DisableMuteMode(UART_HandleTypeDef *huart); +void HAL_MultiProcessor_EnterMuteMode(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_HalfDuplex_EnableTransmitter(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_HalfDuplex_EnableReceiver(UART_HandleTypeDef *huart); + +/** + * @} + */ + +/** @addtogroup UART_Exported_Functions_Group4 Peripheral State and Error functions + * @{ + */ + +/* Peripheral State and Errors functions **************************************************/ +HAL_UART_StateTypeDef HAL_UART_GetState(UART_HandleTypeDef *huart); +uint32_t HAL_UART_GetError(UART_HandleTypeDef *huart); + +/** + * @} + */ + +/** + * @} + */ + +/* Private functions -----------------------------------------------------------*/ +/** @addtogroup UART_Private_Functions UART Private Functions + * @{ + */ + +HAL_StatusTypeDef UART_SetConfig(UART_HandleTypeDef *huart); +HAL_StatusTypeDef UART_CheckIdleState(UART_HandleTypeDef *huart); +HAL_StatusTypeDef UART_WaitOnFlagUntilTimeout(UART_HandleTypeDef *huart, uint32_t Flag, FlagStatus Status, uint32_t Tickstart, uint32_t Timeout); +void UART_AdvFeatureConfig(UART_HandleTypeDef *huart); + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_HAL_UART_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_uart_ex.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_uart_ex.h new file mode 100644 index 0000000..06d6c92 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_uart_ex.h @@ -0,0 +1,771 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_uart_ex.h + * @author MCD Application Team + * @brief Header file of UART HAL Extended module. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_UART_EX_H +#define __STM32L4xx_HAL_UART_EX_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup UARTEx + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup UARTEx_Exported_Types UARTEx Exported Types + * @{ + */ + +/** + * @brief UART wake up from stop mode parameters + */ +typedef struct +{ + uint32_t WakeUpEvent; /*!< Specifies which event will activat the Wakeup from Stop mode flag (WUF). + This parameter can be a value of @ref UART_WakeUp_from_Stop_Selection. + If set to UART_WAKEUP_ON_ADDRESS, the two other fields below must + be filled up. */ + + uint16_t AddressLength; /*!< Specifies whether the address is 4 or 7-bit long. + This parameter can be a value of @ref UARTEx_WakeUp_Address_Length. */ + + uint8_t Address; /*!< UART/USART node address (7-bit long max). */ +} UART_WakeUpTypeDef; + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup UARTEx_Exported_Constants UARTEx Exported Constants + * @{ + */ + +/** @defgroup UARTEx_Word_Length UARTEx Word Length + * @{ + */ +#define UART_WORDLENGTH_7B USART_CR1_M1 /*!< 7-bit long UART frame */ +#define UART_WORDLENGTH_8B 0x00000000U /*!< 8-bit long UART frame */ +#define UART_WORDLENGTH_9B USART_CR1_M0 /*!< 9-bit long UART frame */ +/** + * @} + */ + +/** @defgroup UARTEx_WakeUp_Address_Length UARTEx WakeUp Address Length + * @{ + */ +#define UART_ADDRESS_DETECT_4B 0x00000000U /*!< 4-bit long wake-up address */ +#define UART_ADDRESS_DETECT_7B USART_CR2_ADDM7 /*!< 7-bit long wake-up address */ +/** + * @} + */ + +#if defined(USART_CR2_SLVEN) +/** @defgroup UARTEx_Slave_Select_management UARTEx Slave Select Management + * @{ + */ +#define UART_NSS_HARD 0x00000000U /*!< SPI slave selection depends on NSS input pin */ +#define UART_NSS_SOFT USART_CR2_DIS_NSS /*!< SPI slave is always selected and NSS input pin is ignored */ +/** + * @} + */ +#endif + +#if defined(USART_CR1_FIFOEN) +/** @defgroup UARTEx_TXFIFO_threshold_level UARTEx TXFIFO threshold level + * @brief UART TXFIFO level + * @{ + */ +#define UART_TXFIFO_THRESHOLD_1_8 0x00000000U /*!< TXFIFO reaches 1/8 of its depth */ +#define UART_TXFIFO_THRESHOLD_1_4 USART_CR3_TXFTCFG_0 /*!< TXFIFO reaches 1/4 of its depth */ +#define UART_TXFIFO_THRESHOLD_1_2 USART_CR3_TXFTCFG_1 /*!< TXFIFO reaches 1/2 of its depth */ +#define UART_TXFIFO_THRESHOLD_3_4 (USART_CR3_TXFTCFG_0|USART_CR3_TXFTCFG_1) /*!< TXFIFO reaches 3/4 of its depth */ +#define UART_TXFIFO_THRESHOLD_7_8 USART_CR3_TXFTCFG_2 /*!< TXFIFO reaches 7/8 of its depth */ +#define UART_TXFIFO_THRESHOLD_8_8 (USART_CR3_TXFTCFG_2|USART_CR3_TXFTCFG_0) /*!< TXFIFO becomes empty */ +/** + * @} + */ + +/** @defgroup UARTEx_RXFIFO_threshold_level UARTEx RXFIFO threshold level + * @brief UART RXFIFO level + * @{ + */ +#define UART_RXFIFO_THRESHOLD_1_8 0x00000000U /*!< RXFIFO FIFO reaches 1/8 of its depth */ +#define UART_RXFIFO_THRESHOLD_1_4 USART_CR3_RXFTCFG_0 /*!< RXFIFO FIFO reaches 1/4 of its depth */ +#define UART_RXFIFO_THRESHOLD_1_2 USART_CR3_RXFTCFG_1 /*!< RXFIFO FIFO reaches 1/2 of its depth */ +#define UART_RXFIFO_THRESHOLD_3_4 (USART_CR3_RXFTCFG_0|USART_CR3_RXFTCFG_1) /*!< RXFIFO FIFO reaches 3/4 of its depth */ +#define UART_RXFIFO_THRESHOLD_7_8 USART_CR3_RXFTCFG_2 /*!< RXFIFO FIFO reaches 7/8 of its depth */ +#define UART_RXFIFO_THRESHOLD_8_8 (USART_CR3_RXFTCFG_2|USART_CR3_RXFTCFG_0) /*!< RXFIFO FIFO becomes full */ +/** + * @} + */ +#endif + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup UARTEx_Exported_Functions + * @{ + */ + +/** @addtogroup UARTEx_Exported_Functions_Group1 + * @{ + */ + +/* Initialization and de-initialization functions ****************************/ +HAL_StatusTypeDef HAL_RS485Ex_Init(UART_HandleTypeDef *huart, uint32_t Polarity, uint32_t AssertionTime, uint32_t DeassertionTime); + +/** + * @} + */ + +/** @addtogroup UARTEx_Exported_Functions_Group2 + * @{ + */ + +/* IO operation functions *****************************************************/ +void HAL_UARTEx_WakeupCallback(UART_HandleTypeDef *huart); + +#if defined(USART_CR1_FIFOEN) +void HAL_UARTEx_RxFifoFullCallback(UART_HandleTypeDef *huart); +void HAL_UARTEx_TxFifoEmptyCallback(UART_HandleTypeDef *huart); +#endif + +/** + * @} + */ + +/** @addtogroup UARTEx_Exported_Functions_Group3 + * @{ + */ + +/* Peripheral Control functions **********************************************/ +HAL_StatusTypeDef HAL_UARTEx_StopModeWakeUpSourceConfig(UART_HandleTypeDef *huart, UART_WakeUpTypeDef WakeUpSelection); +HAL_StatusTypeDef HAL_UARTEx_EnableStopMode(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_UARTEx_DisableStopMode(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_MultiProcessorEx_AddressLength_Set(UART_HandleTypeDef *huart, uint32_t AddressLength); + +#if defined(USART_CR2_SLVEN) +HAL_StatusTypeDef HAL_UARTEx_EnableSlaveMode(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_UARTEx_DisableSlaveMode(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_UARTEx_ConfigNSS(UART_HandleTypeDef *huart, uint32_t NSSConfig); +#endif + +#if defined(USART_CR1_FIFOEN) +HAL_StatusTypeDef HAL_UARTEx_EnableFifoMode(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_UARTEx_DisableFifoMode(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_UARTEx_SetTxFifoThreshold(UART_HandleTypeDef *huart, uint32_t Threshold); +HAL_StatusTypeDef HAL_UARTEx_SetRxFifoThreshold(UART_HandleTypeDef *huart, uint32_t Threshold); +#endif + + +/** + * @} + */ + +/** + * @} + */ + +/* Private constants ---------------------------------------------------------*/ +/** @defgroup UARTEx_Private_Constants UARTEx Private Constants + * @{ + */ +#if defined(USART_CR2_SLVEN) +/** @defgroup UARTEx_Slave_Mode UARTEx Synchronous Slave mode + * @{ + */ +#define UART_SLAVEMODE_DISABLE 0x00000000U /*!< USART SPI Slave Mode Enable */ +#define UART_SLAVEMODE_ENABLE USART_CR2_SLVEN /*!< USART SPI Slave Mode Disable */ +/** + * @} + */ +#endif + +#if defined(USART_CR1_FIFOEN) +/** @defgroup UARTEx_FIFO_mode UARTEx FIFO mode + * @{ + */ +#define UART_FIFOMODE_DISABLE 0x00000000U /*!< FIFO mode disable */ +#define UART_FIFOMODE_ENABLE USART_CR1_FIFOEN /*!< FIFO mode enable */ +/** + * @} + */ +#endif +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup UARTEx_Private_Macros UARTEx Private Macros + * @{ + */ + +/** @brief Report the UART clock source. + * @param __HANDLE__ specifies the UART Handle. + * @param __CLOCKSOURCE__ output variable. + * @retval UART clocking source, written in __CLOCKSOURCE__. + */ +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define UART_GETCLOCKSOURCE(__HANDLE__,__CLOCKSOURCE__) \ + do { \ + if((__HANDLE__)->Instance == USART1) \ + { \ + switch(__HAL_RCC_GET_USART1_SOURCE()) \ + { \ + case RCC_USART1CLKSOURCE_PCLK2: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK2; \ + break; \ + case RCC_USART1CLKSOURCE_HSI: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \ + break; \ + case RCC_USART1CLKSOURCE_SYSCLK: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \ + break; \ + case RCC_USART1CLKSOURCE_LSE: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \ + break; \ + default: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \ + break; \ + } \ + } \ + else if((__HANDLE__)->Instance == USART2) \ + { \ + switch(__HAL_RCC_GET_USART2_SOURCE()) \ + { \ + case RCC_USART2CLKSOURCE_PCLK1: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \ + break; \ + case RCC_USART2CLKSOURCE_HSI: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \ + break; \ + case RCC_USART2CLKSOURCE_SYSCLK: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \ + break; \ + case RCC_USART2CLKSOURCE_LSE: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \ + break; \ + default: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \ + break; \ + } \ + } \ + else if((__HANDLE__)->Instance == USART3) \ + { \ + switch(__HAL_RCC_GET_USART3_SOURCE()) \ + { \ + case RCC_USART3CLKSOURCE_PCLK1: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \ + break; \ + case RCC_USART3CLKSOURCE_HSI: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \ + break; \ + case RCC_USART3CLKSOURCE_SYSCLK: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \ + break; \ + case RCC_USART3CLKSOURCE_LSE: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \ + break; \ + default: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \ + break; \ + } \ + } \ + else if((__HANDLE__)->Instance == UART4) \ + { \ + switch(__HAL_RCC_GET_UART4_SOURCE()) \ + { \ + case RCC_UART4CLKSOURCE_PCLK1: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \ + break; \ + case RCC_UART4CLKSOURCE_HSI: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \ + break; \ + case RCC_UART4CLKSOURCE_SYSCLK: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \ + break; \ + case RCC_UART4CLKSOURCE_LSE: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \ + break; \ + default: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \ + break; \ + } \ + } \ + else if((__HANDLE__)->Instance == UART5) \ + { \ + switch(__HAL_RCC_GET_UART5_SOURCE()) \ + { \ + case RCC_UART5CLKSOURCE_PCLK1: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \ + break; \ + case RCC_UART5CLKSOURCE_HSI: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \ + break; \ + case RCC_UART5CLKSOURCE_SYSCLK: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \ + break; \ + case RCC_UART5CLKSOURCE_LSE: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \ + break; \ + default: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \ + break; \ + } \ + } \ + else if((__HANDLE__)->Instance == LPUART1) \ + { \ + switch(__HAL_RCC_GET_LPUART1_SOURCE()) \ + { \ + case RCC_LPUART1CLKSOURCE_PCLK1: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \ + break; \ + case RCC_LPUART1CLKSOURCE_HSI: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \ + break; \ + case RCC_LPUART1CLKSOURCE_SYSCLK: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \ + break; \ + case RCC_LPUART1CLKSOURCE_LSE: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \ + break; \ + default: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \ + break; \ + } \ + } \ + } while(0) +#elif defined (STM32L431xx) || defined (STM32L433xx) || defined (STM32L443xx) +#define UART_GETCLOCKSOURCE(__HANDLE__,__CLOCKSOURCE__) \ + do { \ + if((__HANDLE__)->Instance == USART1) \ + { \ + switch(__HAL_RCC_GET_USART1_SOURCE()) \ + { \ + case RCC_USART1CLKSOURCE_PCLK2: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK2; \ + break; \ + case RCC_USART1CLKSOURCE_HSI: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \ + break; \ + case RCC_USART1CLKSOURCE_SYSCLK: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \ + break; \ + case RCC_USART1CLKSOURCE_LSE: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \ + break; \ + default: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \ + break; \ + } \ + } \ + else if((__HANDLE__)->Instance == USART2) \ + { \ + switch(__HAL_RCC_GET_USART2_SOURCE()) \ + { \ + case RCC_USART2CLKSOURCE_PCLK1: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \ + break; \ + case RCC_USART2CLKSOURCE_HSI: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \ + break; \ + case RCC_USART2CLKSOURCE_SYSCLK: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \ + break; \ + case RCC_USART2CLKSOURCE_LSE: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \ + break; \ + default: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \ + break; \ + } \ + } \ + else if((__HANDLE__)->Instance == USART3) \ + { \ + switch(__HAL_RCC_GET_USART3_SOURCE()) \ + { \ + case RCC_USART3CLKSOURCE_PCLK1: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \ + break; \ + case RCC_USART3CLKSOURCE_HSI: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \ + break; \ + case RCC_USART3CLKSOURCE_SYSCLK: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \ + break; \ + case RCC_USART3CLKSOURCE_LSE: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \ + break; \ + default: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \ + break; \ + } \ + } \ + else if((__HANDLE__)->Instance == LPUART1) \ + { \ + switch(__HAL_RCC_GET_LPUART1_SOURCE()) \ + { \ + case RCC_LPUART1CLKSOURCE_PCLK1: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \ + break; \ + case RCC_LPUART1CLKSOURCE_HSI: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \ + break; \ + case RCC_LPUART1CLKSOURCE_SYSCLK: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \ + break; \ + case RCC_LPUART1CLKSOURCE_LSE: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \ + break; \ + default: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \ + break; \ + } \ + } \ + } while(0) +#elif defined (STM32L432xx) || defined (STM32L442xx) +#define UART_GETCLOCKSOURCE(__HANDLE__,__CLOCKSOURCE__) \ + do { \ + if((__HANDLE__)->Instance == USART1) \ + { \ + switch(__HAL_RCC_GET_USART1_SOURCE()) \ + { \ + case RCC_USART1CLKSOURCE_PCLK2: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK2; \ + break; \ + case RCC_USART1CLKSOURCE_HSI: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \ + break; \ + case RCC_USART1CLKSOURCE_SYSCLK: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \ + break; \ + case RCC_USART1CLKSOURCE_LSE: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \ + break; \ + default: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \ + break; \ + } \ + } \ + else if((__HANDLE__)->Instance == USART2) \ + { \ + switch(__HAL_RCC_GET_USART2_SOURCE()) \ + { \ + case RCC_USART2CLKSOURCE_PCLK1: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \ + break; \ + case RCC_USART2CLKSOURCE_HSI: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \ + break; \ + case RCC_USART2CLKSOURCE_SYSCLK: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \ + break; \ + case RCC_USART2CLKSOURCE_LSE: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \ + break; \ + default: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \ + break; \ + } \ + } \ + else if((__HANDLE__)->Instance == LPUART1) \ + { \ + switch(__HAL_RCC_GET_LPUART1_SOURCE()) \ + { \ + case RCC_LPUART1CLKSOURCE_PCLK1: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \ + break; \ + case RCC_LPUART1CLKSOURCE_HSI: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \ + break; \ + case RCC_LPUART1CLKSOURCE_SYSCLK: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \ + break; \ + case RCC_LPUART1CLKSOURCE_LSE: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \ + break; \ + default: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \ + break; \ + } \ + } \ + } while(0) +#elif defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) +#define UART_GETCLOCKSOURCE(__HANDLE__,__CLOCKSOURCE__) \ + do { \ + if((__HANDLE__)->Instance == USART1) \ + { \ + switch(__HAL_RCC_GET_USART1_SOURCE()) \ + { \ + case RCC_USART1CLKSOURCE_PCLK2: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK2; \ + break; \ + case RCC_USART1CLKSOURCE_HSI: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \ + break; \ + case RCC_USART1CLKSOURCE_SYSCLK: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \ + break; \ + case RCC_USART1CLKSOURCE_LSE: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \ + break; \ + default: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \ + break; \ + } \ + } \ + else if((__HANDLE__)->Instance == USART2) \ + { \ + switch(__HAL_RCC_GET_USART2_SOURCE()) \ + { \ + case RCC_USART2CLKSOURCE_PCLK1: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \ + break; \ + case RCC_USART2CLKSOURCE_HSI: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \ + break; \ + case RCC_USART2CLKSOURCE_SYSCLK: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \ + break; \ + case RCC_USART2CLKSOURCE_LSE: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \ + break; \ + default: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \ + break; \ + } \ + } \ + else if((__HANDLE__)->Instance == USART3) \ + { \ + switch(__HAL_RCC_GET_USART3_SOURCE()) \ + { \ + case RCC_USART3CLKSOURCE_PCLK1: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \ + break; \ + case RCC_USART3CLKSOURCE_HSI: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \ + break; \ + case RCC_USART3CLKSOURCE_SYSCLK: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \ + break; \ + case RCC_USART3CLKSOURCE_LSE: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \ + break; \ + default: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \ + break; \ + } \ + } \ + else if((__HANDLE__)->Instance == UART4) \ + { \ + switch(__HAL_RCC_GET_UART4_SOURCE()) \ + { \ + case RCC_UART4CLKSOURCE_PCLK1: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \ + break; \ + case RCC_UART4CLKSOURCE_HSI: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \ + break; \ + case RCC_UART4CLKSOURCE_SYSCLK: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \ + break; \ + case RCC_UART4CLKSOURCE_LSE: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \ + break; \ + default: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \ + break; \ + } \ + } \ + else if((__HANDLE__)->Instance == LPUART1) \ + { \ + switch(__HAL_RCC_GET_LPUART1_SOURCE()) \ + { \ + case RCC_LPUART1CLKSOURCE_PCLK1: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \ + break; \ + case RCC_LPUART1CLKSOURCE_HSI: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \ + break; \ + case RCC_LPUART1CLKSOURCE_SYSCLK: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \ + break; \ + case RCC_LPUART1CLKSOURCE_LSE: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \ + break; \ + default: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \ + break; \ + } \ + } \ + } while(0) +#endif + +/** @brief Report the UART mask to apply to retrieve the received data + * according to the word length and to the parity bits activation. + * @note If PCE = 1, the parity bit is not included in the data extracted + * by the reception API(). + * This masking operation is not carried out in the case of + * DMA transfers. + * @param __HANDLE__: specifies the UART Handle. + * @retval None, the mask to apply to UART RDR register is stored in (__HANDLE__)->Mask field. + */ +#define UART_MASK_COMPUTATION(__HANDLE__) \ + do { \ + if ((__HANDLE__)->Init.WordLength == UART_WORDLENGTH_9B) \ + { \ + if ((__HANDLE__)->Init.Parity == UART_PARITY_NONE) \ + { \ + (__HANDLE__)->Mask = 0x01FF ; \ + } \ + else \ + { \ + (__HANDLE__)->Mask = 0x00FF ; \ + } \ + } \ + else if ((__HANDLE__)->Init.WordLength == UART_WORDLENGTH_8B) \ + { \ + if ((__HANDLE__)->Init.Parity == UART_PARITY_NONE) \ + { \ + (__HANDLE__)->Mask = 0x00FF ; \ + } \ + else \ + { \ + (__HANDLE__)->Mask = 0x007F ; \ + } \ + } \ + else if ((__HANDLE__)->Init.WordLength == UART_WORDLENGTH_7B) \ + { \ + if ((__HANDLE__)->Init.Parity == UART_PARITY_NONE) \ + { \ + (__HANDLE__)->Mask = 0x007F ; \ + } \ + else \ + { \ + (__HANDLE__)->Mask = 0x003F ; \ + } \ + } \ +} while(0) + + +/** + * @brief Ensure that UART frame length is valid. + * @param __LENGTH__ UART frame length. + * @retval SET (__LENGTH__ is valid) or RESET (__LENGTH__ is invalid) + */ +#define IS_UART_WORD_LENGTH(__LENGTH__) (((__LENGTH__) == UART_WORDLENGTH_7B) || \ + ((__LENGTH__) == UART_WORDLENGTH_8B) || \ + ((__LENGTH__) == UART_WORDLENGTH_9B)) + +/** + * @brief Ensure that UART wake-up address length is valid. + * @param __ADDRESS__ UART wake-up address length. + * @retval SET (__ADDRESS__ is valid) or RESET (__ADDRESS__ is invalid) + */ +#define IS_UART_ADDRESSLENGTH_DETECT(__ADDRESS__) (((__ADDRESS__) == UART_ADDRESS_DETECT_4B) || \ + ((__ADDRESS__) == UART_ADDRESS_DETECT_7B)) + +#if defined(USART_CR2_SLVEN) +/** + * @brief Ensure that UART Negative Slave Select (NSS) pin management is valid. + * @param __NSS__ UART Negative Slave Select pin management. + * @retval SET (__NSS__ is valid) or RESET (__NSS__ is invalid) + */ +#define IS_UART_NSS(__NSS__) (((__NSS__) == UART_NSS_HARD) || \ + ((__NSS__) == UART_NSS_SOFT)) +#endif + +#if defined(USART_CR1_FIFOEN) +/** + * @brief Ensure that UART TXFIFO threshold level is valid. + * @param __THRESHOLD__ UART TXFIFO threshold level. + * @retval SET (__THRESHOLD__ is valid) or RESET (__THRESHOLD__ is invalid) + */ +#define IS_UART_TXFIFO_THRESHOLD(__THRESHOLD__) (((__THRESHOLD__) == UART_TXFIFO_THRESHOLD_1_8) || \ + ((__THRESHOLD__) == UART_TXFIFO_THRESHOLD_1_4) || \ + ((__THRESHOLD__) == UART_TXFIFO_THRESHOLD_1_2) || \ + ((__THRESHOLD__) == UART_TXFIFO_THRESHOLD_3_4) || \ + ((__THRESHOLD__) == UART_TXFIFO_THRESHOLD_7_8) || \ + ((__THRESHOLD__) == UART_TXFIFO_THRESHOLD_8_8)) + +/** + * @brief Ensure that USART RXFIFO threshold level is valid. + * @param __THRESHOLD__ USART RXFIFO threshold level. + * @retval SET (__THRESHOLD__ is valid) or RESET (__THRESHOLD__ is invalid) + */ +#define IS_UART_RXFIFO_THRESHOLD(__THRESHOLD__) (((__THRESHOLD__) == UART_RXFIFO_THRESHOLD_1_8) || \ + ((__THRESHOLD__) == UART_RXFIFO_THRESHOLD_1_4) || \ + ((__THRESHOLD__) == UART_RXFIFO_THRESHOLD_1_2) || \ + ((__THRESHOLD__) == UART_RXFIFO_THRESHOLD_3_4) || \ + ((__THRESHOLD__) == UART_RXFIFO_THRESHOLD_7_8) || \ + ((__THRESHOLD__) == UART_RXFIFO_THRESHOLD_8_8)) +#endif + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_HAL_UART_EX_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_usb.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_usb.h new file mode 100644 index 0000000..d4a19ed --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_usb.h @@ -0,0 +1,617 @@ +/** + ****************************************************************************** + * @file stm32l4xx_ll_usb.h + * @author MCD Application Team + * @brief Header file of USB Core HAL module. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_LL_USB_H +#define __STM32L4xx_LL_USB_H + +#ifdef __cplusplus + extern "C" { +#endif + +#if defined(STM32L432xx) || defined(STM32L433xx) || defined(STM32L442xx) || defined(STM32L443xx) || \ + defined(STM32L452xx) || defined(STM32L462xx) || \ + defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || \ + defined(STM32L496xx) || defined(STM32L4A6xx) || \ + defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL + * @{ + */ + +/** @addtogroup USB_Core + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ + +/** + * @brief USB Mode definition + */ +typedef enum +{ + USB_DEVICE_MODE = 0, + USB_HOST_MODE = 1, + USB_DRD_MODE = 2 + +}USB_ModeTypeDef; + +#if defined (USB_OTG_FS) +/** + * @brief URB States definition + */ +typedef enum { + URB_IDLE = 0, + URB_DONE, + URB_NOTREADY, + URB_NYET, + URB_ERROR, + URB_STALL + +}USB_OTG_URBStateTypeDef; + +/** + * @brief Host channel States definition + */ +typedef enum { + HC_IDLE = 0, + HC_XFRC, + HC_HALTED, + HC_NAK, + HC_NYET, + HC_STALL, + HC_XACTERR, + HC_BBLERR, + HC_DATATGLERR + +}USB_OTG_HCStateTypeDef; + +/** + * @brief PCD Initialization Structure definition + */ +typedef struct +{ + uint32_t dev_endpoints; /*!< Device Endpoints number. + This parameter depends on the used USB core. + This parameter must be a number between Min_Data = 1 and Max_Data = 15 */ + + uint32_t Host_channels; /*!< Host Channels number. + This parameter Depends on the used USB core. + This parameter must be a number between Min_Data = 1 and Max_Data = 15 */ + + uint32_t speed; /*!< USB Core speed. + This parameter can be any value of @ref USB_Core_Speed_ */ + + uint32_t dma_enable; /*!< Enable or disable of the USB embedded DMA. */ + + uint32_t ep0_mps; /*!< Set the Endpoint 0 Max Packet size. + This parameter can be any value of @ref USB_EP0_MPS_ */ + + uint32_t phy_itface; /*!< Select the used PHY interface. + This parameter can be any value of @ref USB_Core_PHY_ */ + + uint32_t Sof_enable; /*!< Enable or disable the output of the SOF signal. */ + + uint32_t low_power_enable; /*!< Enable or disable the low power mode. */ + + uint32_t lpm_enable; /*!< Enable or disable Battery charging. */ + + uint32_t battery_charging_enable; /*!< Enable or disable Battery charging. */ + + uint32_t vbus_sensing_enable; /*!< Enable or disable the VBUS Sensing feature. */ + + uint32_t use_dedicated_ep1; /*!< Enable or disable the use of the dedicated EP1 interrupt. */ + + uint32_t use_external_vbus; /*!< Enable or disable the use of the external VBUS. */ + +}USB_OTG_CfgTypeDef; + +typedef struct +{ + uint8_t num; /*!< Endpoint number + This parameter must be a number between Min_Data = 1 and Max_Data = 15 */ + + uint8_t is_in; /*!< Endpoint direction + This parameter must be a number between Min_Data = 0 and Max_Data = 1 */ + + uint8_t is_stall; /*!< Endpoint stall condition + This parameter must be a number between Min_Data = 0 and Max_Data = 1 */ + + uint8_t type; /*!< Endpoint type + This parameter can be any value of @ref USB_EP_Type_ */ + + uint8_t data_pid_start; /*!< Initial data PID + This parameter must be a number between Min_Data = 0 and Max_Data = 1 */ + + uint8_t even_odd_frame; /*!< IFrame parity + This parameter must be a number between Min_Data = 0 and Max_Data = 1 */ + + uint16_t tx_fifo_num; /*!< Transmission FIFO number + This parameter must be a number between Min_Data = 1 and Max_Data = 15 */ + + uint32_t maxpacket; /*!< Endpoint Max packet size + This parameter must be a number between Min_Data = 0 and Max_Data = 64KB */ + + uint8_t *xfer_buff; /*!< Pointer to transfer buffer */ + + uint32_t dma_addr; /*!< 32 bits aligned transfer buffer address */ + + uint32_t xfer_len; /*!< Current transfer length */ + + uint32_t xfer_count; /*!< Partial transfer length in case of multi packet transfer */ + +}USB_OTG_EPTypeDef; + +typedef struct +{ + uint8_t dev_addr ; /*!< USB device address. + This parameter must be a number between Min_Data = 1 and Max_Data = 255 */ + + uint8_t ch_num; /*!< Host channel number. + This parameter must be a number between Min_Data = 1 and Max_Data = 15 */ + + uint8_t ep_num; /*!< Endpoint number. + This parameter must be a number between Min_Data = 1 and Max_Data = 15 */ + + uint8_t ep_is_in; /*!< Endpoint direction + This parameter must be a number between Min_Data = 0 and Max_Data = 1 */ + + uint8_t speed; /*!< USB Host speed. + This parameter can be any value of @ref USB_Core_Speed_ */ + + uint8_t do_ping; /*!< Enable or disable the use of the PING protocol for HS mode. */ + + uint8_t process_ping; /*!< Execute the PING protocol for HS mode. */ + + uint8_t ep_type; /*!< Endpoint Type. + This parameter can be any value of @ref USB_EP_Type_ */ + + uint16_t max_packet; /*!< Endpoint Max packet size. + This parameter must be a number between Min_Data = 0 and Max_Data = 64KB */ + + uint8_t data_pid; /*!< Initial data PID. + This parameter must be a number between Min_Data = 0 and Max_Data = 1 */ + + uint8_t *xfer_buff; /*!< Pointer to transfer buffer. */ + + uint32_t xfer_len; /*!< Current transfer length. */ + + uint32_t xfer_count; /*!< Partial transfer length in case of multi packet transfer. */ + + uint8_t toggle_in; /*!< IN transfer current toggle flag. + This parameter must be a number between Min_Data = 0 and Max_Data = 1 */ + + uint8_t toggle_out; /*!< OUT transfer current toggle flag + This parameter must be a number between Min_Data = 0 and Max_Data = 1 */ + + uint32_t dma_addr; /*!< 32 bits aligned transfer buffer address. */ + + uint32_t ErrCnt; /*!< Host channel error count.*/ + + USB_OTG_URBStateTypeDef urb_state; /*!< URB state. + This parameter can be any value of @ref USB_OTG_URBStateTypeDef */ + + USB_OTG_HCStateTypeDef state; /*!< Host Channel state. + This parameter can be any value of @ref USB_OTG_HCStateTypeDef */ + +}USB_OTG_HCTypeDef; +#endif /* USB_OTG_FS */ + +#if defined (USB) +/** + * @brief USB Initialization Structure definition + */ +typedef struct +{ + uint32_t dev_endpoints; /*!< Device Endpoints number. + This parameter depends on the used USB core. + This parameter must be a number between Min_Data = 1 and Max_Data = 15 */ + + uint32_t speed; /*!< USB Core speed. + This parameter can be any value of @ref USB_Core_Speed */ + + uint32_t dma_enable; /*!< Enable or disable of the USB embedded DMA. */ + + uint32_t ep0_mps; /*!< Set the Endpoint 0 Max Packet size. + This parameter can be any value of @ref USB_EP0_MPS */ + + uint32_t phy_itface; /*!< Select the used PHY interface. + This parameter can be any value of @ref USB_Core_PHY */ + + uint32_t Sof_enable; /*!< Enable or disable the output of the SOF signal. */ + + uint32_t low_power_enable; /*!< Enable or disable Low Power mode */ + + uint32_t lpm_enable; /*!< Enable or disable Battery charging. */ + + uint32_t battery_charging_enable; /*!< Enable or disable Battery charging. */ +} USB_CfgTypeDef; + +typedef struct +{ + uint8_t num; /*!< Endpoint number + This parameter must be a number between Min_Data = 1 and Max_Data = 15 */ + + uint8_t is_in; /*!< Endpoint direction + This parameter must be a number between Min_Data = 0 and Max_Data = 1 */ + + uint8_t is_stall; /*!< Endpoint stall condition + This parameter must be a number between Min_Data = 0 and Max_Data = 1 */ + + uint8_t type; /*!< Endpoint type + This parameter can be any value of @ref USB_EP_Type */ + + uint16_t pmaadress; /*!< PMA Address + This parameter can be any value between Min_addr = 0 and Max_addr = 1K */ + + uint16_t pmaaddr0; /*!< PMA Address0 + This parameter can be any value between Min_addr = 0 and Max_addr = 1K */ + + uint16_t pmaaddr1; /*!< PMA Address1 + This parameter can be any value between Min_addr = 0 and Max_addr = 1K */ + + uint8_t doublebuffer; /*!< Double buffer enable + This parameter can be 0 or 1 */ + + uint16_t tx_fifo_num; /*!< This parameter is not required by USB Device FS peripheral, it is used + only by USB OTG FS peripheral + This parameter is added to ensure compatibility across USB peripherals */ + + uint32_t maxpacket; /*!< Endpoint Max packet size + This parameter must be a number between Min_Data = 0 and Max_Data = 64KB */ + + uint8_t *xfer_buff; /*!< Pointer to transfer buffer */ + + uint32_t xfer_len; /*!< Current transfer length */ + + uint32_t xfer_count; /*!< Partial transfer length in case of multi packet transfer */ + +} USB_EPTypeDef; +#endif /* USB */ + +/* Exported constants --------------------------------------------------------*/ + +/** @defgroup PCD_Exported_Constants PCD Exported Constants + * @{ + */ +#if defined (USB_OTG_FS) +/** @defgroup USB_Core_Mode_ USB Core Mode + * @{ + */ +#define USB_OTG_MODE_DEVICE 0 +#define USB_OTG_MODE_HOST 1 +#define USB_OTG_MODE_DRD 2 +/** + * @} + */ + +/** @defgroup USB_Core_Speed_ USB Core Speed + * @{ + */ +#define USB_OTG_SPEED_HIGH 0 +#define USB_OTG_SPEED_HIGH_IN_FULL 1 +#define USB_OTG_SPEED_LOW 2 +#define USB_OTG_SPEED_FULL 3 +/** + * @} + */ + +/** @defgroup USB_Core_PHY_ USB Core PHY + * @{ + */ +#define USB_OTG_EMBEDDED_PHY 1 +/** + * @} + */ + +/** @defgroup USB_Core_MPS_ USB Core MPS + * @{ + */ +#define USB_OTG_FS_MAX_PACKET_SIZE 64 +#define USB_OTG_MAX_EP0_SIZE 64 +/** + * @} + */ + +/** @defgroup USB_Core_Phy_Frequency_ USB Core Phy Frequency + * @{ + */ +#define DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ (0 << 1) +#define DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ (1 << 1) +#define DSTS_ENUMSPD_LS_PHY_6MHZ (2 << 1) +#define DSTS_ENUMSPD_FS_PHY_48MHZ (3 << 1) +/** + * @} + */ + +/** @defgroup USB_CORE_Frame_Interval_ USB CORE Frame Interval + * @{ + */ +#define DCFG_FRAME_INTERVAL_80 0 +#define DCFG_FRAME_INTERVAL_85 1 +#define DCFG_FRAME_INTERVAL_90 2 +#define DCFG_FRAME_INTERVAL_95 3 +/** + * @} + */ + +/** @defgroup USB_EP0_MPS_ USB EP0 MPS + * @{ + */ +#define DEP0CTL_MPS_64 0 +#define DEP0CTL_MPS_32 1 +#define DEP0CTL_MPS_16 2 +#define DEP0CTL_MPS_8 3 +/** + * @} + */ + +/** @defgroup USB_EP_Speed_ USB EP Speed + * @{ + */ +#define EP_SPEED_LOW 0 +#define EP_SPEED_FULL 1 +#define EP_SPEED_HIGH 2 +/** + * @} + */ + +/** @defgroup USB_EP_Type_ USB EP Type + * @{ + */ +#define EP_TYPE_CTRL 0 +#define EP_TYPE_ISOC 1 +#define EP_TYPE_BULK 2 +#define EP_TYPE_INTR 3 +#define EP_TYPE_MSK 3 +/** + * @} + */ + +/** @defgroup USB_STS_Defines_ USB STS Defines + * @{ + */ +#define STS_GOUT_NAK 1 +#define STS_DATA_UPDT 2 +#define STS_XFER_COMP 3 +#define STS_SETUP_COMP 4 +#define STS_SETUP_UPDT 6 +/** + * @} + */ + +/** @defgroup HCFG_SPEED_Defines_ HCFG SPEED Defines + * @{ + */ +#define HCFG_30_60_MHZ 0 +#define HCFG_48_MHZ 1 +#define HCFG_6_MHZ 2 +/** + * @} + */ + +/** @defgroup HPRT0_PRTSPD_SPEED_Defines_ HPRT0 PRTSPD SPEED Defines + * @{ + */ +#define HPRT0_PRTSPD_HIGH_SPEED 0 +#define HPRT0_PRTSPD_FULL_SPEED 1 +#define HPRT0_PRTSPD_LOW_SPEED 2 +/** + * @} + */ + +#define HCCHAR_CTRL 0 +#define HCCHAR_ISOC 1 +#define HCCHAR_BULK 2 +#define HCCHAR_INTR 3 + +#define HC_PID_DATA0 0 +#define HC_PID_DATA2 1 +#define HC_PID_DATA1 2 +#define HC_PID_SETUP 3 + +#define GRXSTS_PKTSTS_IN 2 +#define GRXSTS_PKTSTS_IN_XFER_COMP 3 +#define GRXSTS_PKTSTS_DATA_TOGGLE_ERR 5 +#define GRXSTS_PKTSTS_CH_HALTED 7 + +#define USBx_PCGCCTL *(__IO uint32_t *)((uint32_t)USBx + USB_OTG_PCGCCTL_BASE) +#define USBx_HPRT0 *(__IO uint32_t *)((uint32_t)USBx + USB_OTG_HOST_PORT_BASE) + +#define USBx_DEVICE ((USB_OTG_DeviceTypeDef *)((uint32_t )USBx + USB_OTG_DEVICE_BASE)) +#define USBx_INEP(i) ((USB_OTG_INEndpointTypeDef *)((uint32_t)USBx + USB_OTG_IN_ENDPOINT_BASE + (i)*USB_OTG_EP_REG_SIZE)) +#define USBx_OUTEP(i) ((USB_OTG_OUTEndpointTypeDef *)((uint32_t)USBx + USB_OTG_OUT_ENDPOINT_BASE + (i)*USB_OTG_EP_REG_SIZE)) +#define USBx_DFIFO(i) *(__IO uint32_t *)((uint32_t)USBx + USB_OTG_FIFO_BASE + (i) * USB_OTG_FIFO_SIZE) + +#define USBx_HOST ((USB_OTG_HostTypeDef *)((uint32_t )USBx + USB_OTG_HOST_BASE)) +#define USBx_HC(i) ((USB_OTG_HostChannelTypeDef *)((uint32_t)USBx + USB_OTG_HOST_CHANNEL_BASE + (i)*USB_OTG_HOST_CHANNEL_SIZE)) + +#endif /* USB_OTG_FS */ + +#if defined (USB) +/** @defgroup USB_LL_EP0_MPS USB Low Layer EP0 MPS + * @{ + */ +#define DEP0CTL_MPS_64 0 +#define DEP0CTL_MPS_32 1 +#define DEP0CTL_MPS_16 2 +#define DEP0CTL_MPS_8 3 +/** + * @} + */ + +/** @defgroup USB_LL_EP_Type USB Low Layer EP Type + * @{ + */ +#define EP_TYPE_CTRL 0 +#define EP_TYPE_ISOC 1 +#define EP_TYPE_BULK 2 +#define EP_TYPE_INTR 3 +#define EP_TYPE_MSK 3 +/** + * @} + */ + +#define BTABLE_ADDRESS (0x000) +#endif /* USB */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +#if defined (USB_OTG_FS) +#define USB_MASK_INTERRUPT(__INSTANCE__, __INTERRUPT__) ((__INSTANCE__)->GINTMSK &= ~(__INTERRUPT__)) +#define USB_UNMASK_INTERRUPT(__INSTANCE__, __INTERRUPT__) ((__INSTANCE__)->GINTMSK |= (__INTERRUPT__)) + +#define CLEAR_IN_EP_INTR(__EPNUM__, __INTERRUPT__) (USBx_INEP(__EPNUM__)->DIEPINT = (__INTERRUPT__)) +#define CLEAR_OUT_EP_INTR(__EPNUM__, __INTERRUPT__) (USBx_OUTEP(__EPNUM__)->DOEPINT = (__INTERRUPT__)) +#endif /* USB_OTG_FS */ + +/* Exported functions --------------------------------------------------------*/ +#if defined (USB_OTG_FS) +HAL_StatusTypeDef USB_CoreInit(USB_OTG_GlobalTypeDef *USBx, USB_OTG_CfgTypeDef Init); +HAL_StatusTypeDef USB_DevInit(USB_OTG_GlobalTypeDef *USBx, USB_OTG_CfgTypeDef Init); +HAL_StatusTypeDef USB_EnableGlobalInt(USB_OTG_GlobalTypeDef *USBx); +HAL_StatusTypeDef USB_DisableGlobalInt(USB_OTG_GlobalTypeDef *USBx); +HAL_StatusTypeDef USB_SetCurrentMode(USB_OTG_GlobalTypeDef *USBx , USB_ModeTypeDef mode); +HAL_StatusTypeDef USB_SetDevSpeed(USB_OTG_GlobalTypeDef *USBx , uint8_t speed); +HAL_StatusTypeDef USB_FlushRxFifo (USB_OTG_GlobalTypeDef *USBx); +HAL_StatusTypeDef USB_FlushTxFifo (USB_OTG_GlobalTypeDef *USBx, uint32_t num ); +HAL_StatusTypeDef USB_ActivateEndpoint(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep); +HAL_StatusTypeDef USB_DeactivateEndpoint(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep); +HAL_StatusTypeDef USB_ActivateDedicatedEndpoint(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep); +HAL_StatusTypeDef USB_DeactivateDedicatedEndpoint(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep); +HAL_StatusTypeDef USB_EPStartXfer(USB_OTG_GlobalTypeDef *USBx , USB_OTG_EPTypeDef *ep, uint8_t dma); +HAL_StatusTypeDef USB_EP0StartXfer(USB_OTG_GlobalTypeDef *USBx , USB_OTG_EPTypeDef *ep, uint8_t dma); +HAL_StatusTypeDef USB_WritePacket(USB_OTG_GlobalTypeDef *USBx, uint8_t *src, uint8_t ch_ep_num, uint16_t len, uint8_t dma); +void * USB_ReadPacket(USB_OTG_GlobalTypeDef *USBx, uint8_t *dest, uint16_t len); +HAL_StatusTypeDef USB_EPSetStall(USB_OTG_GlobalTypeDef *USBx , USB_OTG_EPTypeDef *ep); +HAL_StatusTypeDef USB_EPClearStall(USB_OTG_GlobalTypeDef *USBx , USB_OTG_EPTypeDef *ep); +HAL_StatusTypeDef USB_SetDevAddress (USB_OTG_GlobalTypeDef *USBx, uint8_t address); +HAL_StatusTypeDef USB_DevConnect (USB_OTG_GlobalTypeDef *USBx); +HAL_StatusTypeDef USB_DevDisconnect (USB_OTG_GlobalTypeDef *USBx); +HAL_StatusTypeDef USB_StopDevice(USB_OTG_GlobalTypeDef *USBx); +HAL_StatusTypeDef USB_ActivateSetup (USB_OTG_GlobalTypeDef *USBx); +HAL_StatusTypeDef USB_EP0_OutStart(USB_OTG_GlobalTypeDef *USBx, uint8_t dma, uint8_t *psetup); +uint8_t USB_GetDevSpeed(USB_OTG_GlobalTypeDef *USBx); +uint32_t USB_GetMode(USB_OTG_GlobalTypeDef *USBx); +uint32_t USB_ReadInterrupts (USB_OTG_GlobalTypeDef *USBx); +uint32_t USB_ReadDevAllOutEpInterrupt (USB_OTG_GlobalTypeDef *USBx); +uint32_t USB_ReadDevOutEPInterrupt (USB_OTG_GlobalTypeDef *USBx , uint8_t epnum); +uint32_t USB_ReadDevAllInEpInterrupt (USB_OTG_GlobalTypeDef *USBx); +uint32_t USB_ReadDevInEPInterrupt (USB_OTG_GlobalTypeDef *USBx , uint8_t epnum); +void USB_ClearInterrupts (USB_OTG_GlobalTypeDef *USBx, uint32_t interrupt); + +HAL_StatusTypeDef USB_HostInit (USB_OTG_GlobalTypeDef *USBx, USB_OTG_CfgTypeDef cfg); +HAL_StatusTypeDef USB_InitFSLSPClkSel(USB_OTG_GlobalTypeDef *USBx , uint8_t freq); +HAL_StatusTypeDef USB_ResetPort(USB_OTG_GlobalTypeDef *USBx); +HAL_StatusTypeDef USB_DriveVbus (USB_OTG_GlobalTypeDef *USBx, uint8_t state); +uint32_t USB_GetHostSpeed (USB_OTG_GlobalTypeDef *USBx); +uint32_t USB_GetCurrentFrame (USB_OTG_GlobalTypeDef *USBx); +HAL_StatusTypeDef USB_HC_Init(USB_OTG_GlobalTypeDef *USBx, + uint8_t ch_num, + uint8_t epnum, + uint8_t dev_address, + uint8_t speed, + uint8_t ep_type, + uint16_t mps); +HAL_StatusTypeDef USB_HC_StartXfer(USB_OTG_GlobalTypeDef *USBx, USB_OTG_HCTypeDef *hc, uint8_t dma); +uint32_t USB_HC_ReadInterrupt (USB_OTG_GlobalTypeDef *USBx); +HAL_StatusTypeDef USB_HC_Halt(USB_OTG_GlobalTypeDef *USBx , uint8_t hc_num); +HAL_StatusTypeDef USB_DoPing(USB_OTG_GlobalTypeDef *USBx , uint8_t ch_num); +HAL_StatusTypeDef USB_StopHost(USB_OTG_GlobalTypeDef *USBx); +HAL_StatusTypeDef USB_ActivateRemoteWakeup(USB_OTG_GlobalTypeDef *USBx); +HAL_StatusTypeDef USB_DeActivateRemoteWakeup(USB_OTG_GlobalTypeDef *USBx); +#endif /* USB_OTG_FS */ + +#if defined (USB) +HAL_StatusTypeDef USB_CoreInit(USB_TypeDef *USBx, USB_CfgTypeDef Init); +HAL_StatusTypeDef USB_DevInit(USB_TypeDef *USBx, USB_CfgTypeDef Init); +HAL_StatusTypeDef USB_EnableGlobalInt(USB_TypeDef *USBx); +HAL_StatusTypeDef USB_DisableGlobalInt(USB_TypeDef *USBx); +HAL_StatusTypeDef USB_SetCurrentMode(USB_TypeDef *USBx , USB_ModeTypeDef mode); +HAL_StatusTypeDef USB_SetDevSpeed(USB_TypeDef *USBx , uint8_t speed); +HAL_StatusTypeDef USB_FlushRxFifo (USB_TypeDef *USBx); +HAL_StatusTypeDef USB_FlushTxFifo (USB_TypeDef *USBx, uint32_t num ); +HAL_StatusTypeDef USB_ActivateEndpoint(USB_TypeDef *USBx, USB_EPTypeDef *ep); +HAL_StatusTypeDef USB_DeactivateEndpoint(USB_TypeDef *USBx, USB_EPTypeDef *ep); +HAL_StatusTypeDef USB_EPStartXfer(USB_TypeDef *USBx , USB_EPTypeDef *ep ,uint8_t dma); +HAL_StatusTypeDef USB_WritePacket(USB_TypeDef *USBx, uint8_t *src, uint8_t ch_ep_num, uint16_t len); +void * USB_ReadPacket(USB_TypeDef *USBx, uint8_t *dest, uint16_t len); +HAL_StatusTypeDef USB_EPSetStall(USB_TypeDef *USBx , USB_EPTypeDef *ep); +HAL_StatusTypeDef USB_EPClearStall(USB_TypeDef *USBx , USB_EPTypeDef *ep); +HAL_StatusTypeDef USB_SetDevAddress (USB_TypeDef *USBx, uint8_t address); +HAL_StatusTypeDef USB_DevConnect (USB_TypeDef *USBx); +HAL_StatusTypeDef USB_DevDisconnect (USB_TypeDef *USBx); +HAL_StatusTypeDef USB_StopDevice(USB_TypeDef *USBx); +HAL_StatusTypeDef USB_EP0_OutStart(USB_TypeDef *USBx, uint8_t dma, uint8_t *psetup); +uint32_t USB_ReadInterrupts (USB_TypeDef *USBx); +uint32_t USB_ReadDevAllOutEpInterrupt (USB_TypeDef *USBx); +uint32_t USB_ReadDevOutEPInterrupt (USB_TypeDef *USBx , uint8_t epnum); +uint32_t USB_ReadDevAllInEpInterrupt (USB_TypeDef *USBx); +uint32_t USB_ReadDevInEPInterrupt (USB_TypeDef *USBx , uint8_t epnum); +void USB_ClearInterrupts (USB_TypeDef *USBx, uint32_t interrupt); + +HAL_StatusTypeDef USB_ActivateRemoteWakeup(USB_TypeDef *USBx); +HAL_StatusTypeDef USB_DeActivateRemoteWakeup(USB_TypeDef *USBx); +void USB_WritePMA(USB_TypeDef *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes); +void USB_ReadPMA(USB_TypeDef *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes); +#endif /* USB */ +/** + * @} + */ + +/** + * @} + */ + +#endif /* STM32L432xx || STM32L433xx || STM32L442xx || STM32L443xx || */ + /* STM32L452xx || STM32L462xx || */ + /* STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx || */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#ifdef __cplusplus +} +#endif + + +#endif /* __STM32L4xx_LL_USB_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal.c new file mode 100644 index 0000000..1870606 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal.c @@ -0,0 +1,693 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal.c + * @author MCD Application Team + * @brief HAL module driver. + * This is the common part of the HAL initialization + * + @verbatim + ============================================================================== + ##### How to use this driver ##### + ============================================================================== + [..] + The common HAL driver contains a set of generic and common APIs that can be + used by the PPP peripheral drivers and the user to start using the HAL. + [..] + The HAL contains two APIs' categories: + (+) Common HAL APIs + (+) Services HAL APIs + + @endverbatim + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup HAL HAL + * @brief HAL module driver + * @{ + */ + +#ifdef HAL_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/** + * @brief STM32L4xx HAL Driver version number + */ +#define __STM32L4xx_HAL_VERSION_MAIN (0x01) /*!< [31:24] main version */ +#define __STM32L4xx_HAL_VERSION_SUB1 (0x08) /*!< [23:16] sub1 version */ +#define __STM32L4xx_HAL_VERSION_SUB2 (0x02) /*!< [15:8] sub2 version */ +#define __STM32L4xx_HAL_VERSION_RC (0x00) /*!< [7:0] release candidate */ +#define __STM32L4xx_HAL_VERSION ((__STM32L4xx_HAL_VERSION_MAIN << 24)\ + |(__STM32L4xx_HAL_VERSION_SUB1 << 16)\ + |(__STM32L4xx_HAL_VERSION_SUB2 << 8 )\ + |(__STM32L4xx_HAL_VERSION_RC)) + +#if defined(VREFBUF) +#define VREFBUF_TIMEOUT_VALUE (uint32_t)10 /* 10 ms (to be confirmed) */ +#endif /* VREFBUF */ + +/* ------------ SYSCFG registers bit address in the alias region ------------ */ +#define SYSCFG_OFFSET (SYSCFG_BASE - PERIPH_BASE) +/* --- MEMRMP Register ---*/ +/* Alias word address of FB_MODE bit */ +#define MEMRMP_OFFSET SYSCFG_OFFSET +#define FB_MODE_BitNumber ((uint8_t)0x8) +#define FB_MODE_BB (PERIPH_BB_BASE + (MEMRMP_OFFSET * 32) + (FB_MODE_BitNumber * 4)) + +/* --- SCSR Register ---*/ +/* Alias word address of SRAM2ER bit */ +#define SCSR_OFFSET (SYSCFG_OFFSET + 0x18) +#define BRER_BitNumber ((uint8_t)0x0) +#define SCSR_SRAM2ER_BB (PERIPH_BB_BASE + (SCSR_OFFSET * 32) + (BRER_BitNumber * 4)) + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +__IO uint32_t uwTick; + +/* Private function prototypes -----------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup HAL_Exported_Functions HAL Exported Functions + * @{ + */ + +/** @defgroup HAL_Exported_Functions_Group1 Initialization and de-initialization Functions + * @brief Initialization and de-initialization functions + * +@verbatim + =============================================================================== + ##### Initialization and de-initialization functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Initialize the Flash interface the NVIC allocation and initial time base + clock configuration. + (+) De-initialize common part of the HAL. + (+) Configure the time base source to have 1ms time base with a dedicated + Tick interrupt priority. + (++) SysTick timer is used by default as source of time base, but user + can eventually implement his proper time base source (a general purpose + timer for example or other time source), keeping in mind that Time base + duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and + handled in milliseconds basis. + (++) Time base configuration function (HAL_InitTick ()) is called automatically + at the beginning of the program after reset by HAL_Init() or at any time + when clock is configured, by HAL_RCC_ClockConfig(). + (++) Source of time base is configured to generate interrupts at regular + time intervals. Care must be taken if HAL_Delay() is called from a + peripheral ISR process, the Tick interrupt line must have higher priority + (numerically lower) than the peripheral interrupt. Otherwise the caller + ISR process will be blocked. + (++) functions affecting time base configurations are declared as __weak + to make override possible in case of other implementations in user file. +@endverbatim + * @{ + */ + +/** + * @brief Configure the Flash prefetch, the Instruction and Data caches, + * the time base source, NVIC and any required global low level hardware + * by calling the HAL_MspInit() callback function to be optionally defined in user file + * stm32l4xx_hal_msp.c. + * + * @note HAL_Init() function is called at the beginning of program after reset and before + * the clock configuration. + * + * @note In the default implementation the System Timer (Systick) is used as source of time base. + * The Systick configuration is based on MSI clock, as MSI is the clock + * used after a system Reset and the NVIC configuration is set to Priority group 4. + * Once done, time base tick starts incrementing: the tick variable counter is incremented + * each 1ms in the SysTick_Handler() interrupt handler. + * + * @retval HAL status + */ +HAL_StatusTypeDef HAL_Init(void) +{ + /* Configure Flash prefetch, Instruction cache, Data cache */ + /* Default configuration at reset is: */ + /* - Prefetch disabled */ + /* - Instruction cache enabled */ + /* - Data cache enabled */ +#if (INSTRUCTION_CACHE_ENABLE == 0) + __HAL_FLASH_INSTRUCTION_CACHE_DISABLE(); +#endif /* INSTRUCTION_CACHE_ENABLE */ + +#if (DATA_CACHE_ENABLE == 0) + __HAL_FLASH_DATA_CACHE_DISABLE(); +#endif /* DATA_CACHE_ENABLE */ + +#if (PREFETCH_ENABLE != 0) + __HAL_FLASH_PREFETCH_BUFFER_ENABLE(); +#endif /* PREFETCH_ENABLE */ + + /* Set Interrupt Group Priority */ + HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4); + + /* Use SysTick as time base source and configure 1ms tick (default clock after Reset is MSI) */ + HAL_InitTick(TICK_INT_PRIORITY); + + /* Init the low level hardware */ + HAL_MspInit(); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief De-initialize common part of the HAL and stop the source of time base. + * @note This function is optional. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DeInit(void) +{ + /* Reset of all peripherals */ + __HAL_RCC_APB1_FORCE_RESET(); + __HAL_RCC_APB1_RELEASE_RESET(); + + __HAL_RCC_APB2_FORCE_RESET(); + __HAL_RCC_APB2_RELEASE_RESET(); + + __HAL_RCC_AHB1_FORCE_RESET(); + __HAL_RCC_AHB1_RELEASE_RESET(); + + __HAL_RCC_AHB2_FORCE_RESET(); + __HAL_RCC_AHB2_RELEASE_RESET(); + + __HAL_RCC_AHB3_FORCE_RESET(); + __HAL_RCC_AHB3_RELEASE_RESET(); + + /* De-Init the low level hardware */ + HAL_MspDeInit(); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Initialize the MSP. + * @retval None + */ +__weak void HAL_MspInit(void) +{ + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitialize the MSP. + * @retval None + */ +__weak void HAL_MspDeInit(void) +{ + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_MspDeInit could be implemented in the user file + */ +} + +/** + * @brief This function configures the source of the time base: + * The time source is configured to have 1ms time base with a dedicated + * Tick interrupt priority. + * @note This function is called automatically at the beginning of program after + * reset by HAL_Init() or at any time when clock is reconfigured by HAL_RCC_ClockConfig(). + * @note In the default implementation, SysTick timer is the source of time base. + * It is used to generate interrupts at regular time intervals. + * Care must be taken if HAL_Delay() is called from a peripheral ISR process, + * The SysTick interrupt must have higher priority (numerically lower) + * than the peripheral interrupt. Otherwise the caller ISR process will be blocked. + * The function is declared as __weak to be overwritten in case of other + * implementation in user file. + * @param TickPriority Tick interrupt priority. + * @retval HAL status + */ +__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority) +{ + /*Configure the SysTick to have interrupt in 1ms time basis*/ + HAL_SYSTICK_Config(SystemCoreClock/1000); + + /*Configure the SysTick IRQ priority */ + HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority ,0); + + /* Return function status */ + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup HAL_Exported_Functions_Group2 HAL Control functions + * @brief HAL Control functions + * +@verbatim + =============================================================================== + ##### HAL Control functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Provide a tick value in millisecond + (+) Provide a blocking delay in millisecond + (+) Suspend the time base source interrupt + (+) Resume the time base source interrupt + (+) Get the HAL API driver version + (+) Get the device identifier + (+) Get the device revision identifier + +@endverbatim + * @{ + */ + +/** + * @brief This function is called to increment a global variable "uwTick" + * used as application time base. + * @note In the default implementation, this variable is incremented each 1ms + * in SysTick ISR. + * @note This function is declared as __weak to be overwritten in case of other + * implementations in user file. + * @retval None + */ +__weak void HAL_IncTick(void) +{ + uwTick++; +} + +/** + * @brief Provide a tick value in millisecond. + * @note This function is declared as __weak to be overwritten in case of other + * implementations in user file. + * @retval tick value + */ +__weak uint32_t HAL_GetTick(void) +{ + return uwTick; +} + +/** + * @brief This function provides minimum delay (in milliseconds) based + * on variable incremented. + * @note In the default implementation , SysTick timer is the source of time base. + * It is used to generate interrupts at regular time intervals where uwTick + * is incremented. + * @note This function is declared as __weak to be overwritten in case of other + * implementations in user file. + * @param Delay specifies the delay time length, in milliseconds. + * @retval None + */ +__weak void HAL_Delay(uint32_t Delay) +{ + uint32_t tickstart = HAL_GetTick(); + uint32_t wait = Delay; + + /* Add a period to guaranty minimum wait */ + if (wait < HAL_MAX_DELAY) + { + wait++; + } + + while((HAL_GetTick() - tickstart) < wait) + { + } +} + +/** + * @brief Suspend Tick increment. + * @note In the default implementation , SysTick timer is the source of time base. It is + * used to generate interrupts at regular time intervals. Once HAL_SuspendTick() + * is called, the SysTick interrupt will be disabled and so Tick increment + * is suspended. + * @note This function is declared as __weak to be overwritten in case of other + * implementations in user file. + * @retval None + */ +__weak void HAL_SuspendTick(void) +{ + /* Disable SysTick Interrupt */ + SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk; +} + +/** + * @brief Resume Tick increment. + * @note In the default implementation , SysTick timer is the source of time base. It is + * used to generate interrupts at regular time intervals. Once HAL_ResumeTick() + * is called, the SysTick interrupt will be enabled and so Tick increment + * is resumed. + * @note This function is declared as __weak to be overwritten in case of other + * implementations in user file. + * @retval None + */ +__weak void HAL_ResumeTick(void) +{ + /* Enable SysTick Interrupt */ + SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk; +} + +/** + * @brief Return the HAL revision. + * @retval version : 0xXYZR (8bits for each decimal, R for RC) + */ +uint32_t HAL_GetHalVersion(void) +{ + return __STM32L4xx_HAL_VERSION; +} + +/** + * @brief Return the device revision identifier. + * @retval Device revision identifier + */ +uint32_t HAL_GetREVID(void) +{ + return((DBGMCU->IDCODE & DBGMCU_IDCODE_REV_ID) >> 16); +} + +/** + * @brief Return the device identifier. + * @retval Device identifier + */ +uint32_t HAL_GetDEVID(void) +{ + return(DBGMCU->IDCODE & DBGMCU_IDCODE_DEV_ID); +} + +/** + * @brief Return the first word of the unique device identifier (UID based on 96 bits) + * @retval Device identifier + */ +uint32_t HAL_GetUIDw0(void) +{ + return(READ_REG(*((uint32_t *)UID_BASE))); +} + +/** + * @brief Return the second word of the unique device identifier (UID based on 96 bits) + * @retval Device identifier + */ +uint32_t HAL_GetUIDw1(void) +{ + return(READ_REG(*((uint32_t *)(UID_BASE + 4U)))); +} + +/** + * @brief Return the third word of the unique device identifier (UID based on 96 bits) + * @retval Device identifier + */ +uint32_t HAL_GetUIDw2(void) +{ + return(READ_REG(*((uint32_t *)(UID_BASE + 8U)))); +} + +/** + * @} + */ + +/** @defgroup HAL_Exported_Functions_Group3 HAL Debug functions + * @brief HAL Debug functions + * +@verbatim + =============================================================================== + ##### HAL Debug functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Enable/Disable Debug module during SLEEP mode + (+) Enable/Disable Debug module during STOP0/STOP1/STOP2 modes + (+) Enable/Disable Debug module during STANDBY mode + +@endverbatim + * @{ + */ + +/** + * @brief Enable the Debug Module during SLEEP mode. + * @retval None + */ +void HAL_DBGMCU_EnableDBGSleepMode(void) +{ + SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_SLEEP); +} + +/** + * @brief Disable the Debug Module during SLEEP mode. + * @retval None + */ +void HAL_DBGMCU_DisableDBGSleepMode(void) +{ + CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_SLEEP); +} + +/** + * @brief Enable the Debug Module during STOP0/STOP1/STOP2 modes. + * @retval None + */ +void HAL_DBGMCU_EnableDBGStopMode(void) +{ + SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STOP); +} + +/** + * @brief Disable the Debug Module during STOP0/STOP1/STOP2 modes. + * @retval None + */ +void HAL_DBGMCU_DisableDBGStopMode(void) +{ + CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STOP); +} + +/** + * @brief Enable the Debug Module during STANDBY mode. + * @retval None + */ +void HAL_DBGMCU_EnableDBGStandbyMode(void) +{ + SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STANDBY); +} + +/** + * @brief Disable the Debug Module during STANDBY mode. + * @retval None + */ +void HAL_DBGMCU_DisableDBGStandbyMode(void) +{ + CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STANDBY); +} + +/** + * @} + */ + +/** @defgroup HAL_Exported_Functions_Group4 HAL SYSCFG configuration functions + * @brief HAL SYSCFG configuration functions + * +@verbatim + =============================================================================== + ##### HAL SYSCFG configuration functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Start a hardware SRAM2 erase operation + (+) Enable/Disable the Internal FLASH Bank Swapping + (+) Configure the Voltage reference buffer + (+) Enable/Disable the Voltage reference buffer + (+) Enable/Disable the I/O analog switch voltage booster + +@endverbatim + * @{ + */ + +/** + * @brief Start a hardware SRAM2 erase operation. + * @note As long as SRAM2 is not erased the SRAM2ER bit will be set. + * This bit is automatically reset at the end of the SRAM2 erase operation. + * @retval None + */ +void HAL_SYSCFG_SRAM2Erase(void) +{ + /* unlock the write protection of the SRAM2ER bit */ + SYSCFG->SKR = 0xCA; + SYSCFG->SKR = 0x53; + /* Starts a hardware SRAM2 erase operation*/ + *(__IO uint32_t *) SCSR_SRAM2ER_BB = (uint8_t)0x00000001; +} + +/** + * @brief Enable the Internal FLASH Bank Swapping. + * + * @note This function can be used only for STM32L4xx devices. + * + * @note Flash Bank2 mapped at 0x08000000 (and aliased @0x00000000) + * and Flash Bank1 mapped at 0x08100000 (and aliased at 0x00100000) + * + * @retval None + */ +void HAL_SYSCFG_EnableMemorySwappingBank(void) +{ + *(__IO uint32_t *)FB_MODE_BB = (uint32_t)ENABLE; +} + +/** + * @brief Disable the Internal FLASH Bank Swapping. + * + * @note This function can be used only for STM32L4xx devices. + * + * @note The default state : Flash Bank1 mapped at 0x08000000 (and aliased @0x0000 0000) + * and Flash Bank2 mapped at 0x08100000 (and aliased at 0x00100000) + * + * @retval None + */ +void HAL_SYSCFG_DisableMemorySwappingBank(void) +{ + + *(__IO uint32_t *)FB_MODE_BB = (uint32_t)DISABLE; +} + +#if defined(VREFBUF) +/** + * @brief Configure the internal voltage reference buffer voltage scale. + * @param VoltageScaling specifies the output voltage to achieve + * This parameter can be one of the following values: + * @arg SYSCFG_VREFBUF_VOLTAGE_SCALE0: VREF_OUT1 around 2.048 V. + * This requires VDDA equal to or higher than 2.4 V. + * @arg SYSCFG_VREFBUF_VOLTAGE_SCALE1: VREF_OUT2 around 2.5 V. + * This requires VDDA equal to or higher than 2.8 V. + * @retval None + */ +void HAL_SYSCFG_VREFBUF_VoltageScalingConfig(uint32_t VoltageScaling) +{ + /* Check the parameters */ + assert_param(IS_SYSCFG_VREFBUF_VOLTAGE_SCALE(VoltageScaling)); + + MODIFY_REG(VREFBUF->CSR, VREFBUF_CSR_VRS, VoltageScaling); +} + +/** + * @brief Configure the internal voltage reference buffer high impedance mode. + * @param Mode specifies the high impedance mode + * This parameter can be one of the following values: + * @arg SYSCFG_VREFBUF_HIGH_IMPEDANCE_DISABLE: VREF+ pin is internally connect to VREFINT output. + * @arg SYSCFG_VREFBUF_HIGH_IMPEDANCE_ENABLE: VREF+ pin is high impedance. + * @retval None + */ +void HAL_SYSCFG_VREFBUF_HighImpedanceConfig(uint32_t Mode) +{ + /* Check the parameters */ + assert_param(IS_SYSCFG_VREFBUF_HIGH_IMPEDANCE(Mode)); + + MODIFY_REG(VREFBUF->CSR, VREFBUF_CSR_HIZ, Mode); +} + +/** + * @brief Tune the Internal Voltage Reference buffer (VREFBUF). + * @retval None + */ +void HAL_SYSCFG_VREFBUF_TrimmingConfig(uint32_t TrimmingValue) +{ + /* Check the parameters */ + assert_param(IS_SYSCFG_VREFBUF_TRIMMING(TrimmingValue)); + + MODIFY_REG(VREFBUF->CCR, VREFBUF_CCR_TRIM, TrimmingValue); +} + +/** + * @brief Enable the Internal Voltage Reference buffer (VREFBUF). + * @retval HAL_OK/HAL_TIMEOUT + */ +HAL_StatusTypeDef HAL_SYSCFG_EnableVREFBUF(void) +{ + uint32_t tickstart = 0; + + SET_BIT(VREFBUF->CSR, VREFBUF_CSR_ENVR); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait for VRR bit */ + while(READ_BIT(VREFBUF->CSR, VREFBUF_CSR_VRR) == RESET) + { + if((HAL_GetTick() - tickstart) > VREFBUF_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + + return HAL_OK; +} + +/** + * @brief Disable the Internal Voltage Reference buffer (VREFBUF). + * + * @retval None + */ +void HAL_SYSCFG_DisableVREFBUF(void) +{ + CLEAR_BIT(VREFBUF->CSR, VREFBUF_CSR_ENVR); +} +#endif /* VREFBUF */ + +/** + * @brief Enable the I/O analog switch voltage booster + * + * @retval None + */ +void HAL_SYSCFG_EnableIOAnalogSwitchBooster(void) +{ + SET_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_BOOSTEN); +} + +/** + * @brief Disable the I/O analog switch voltage booster + * + * @retval None + */ +void HAL_SYSCFG_DisableIOAnalogSwitchBooster(void) +{ + CLEAR_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_BOOSTEN); +} + +/** + * @} + */ + +/** + * @} + */ + +#endif /* HAL_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_cortex.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_cortex.c new file mode 100644 index 0000000..4c99c72 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_cortex.c @@ -0,0 +1,539 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_cortex.c + * @author MCD Application Team + * @brief CORTEX HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the CORTEX: + * + Initialization and Configuration functions + * + Peripheral Control functions + * + @verbatim + ============================================================================== + ##### How to use this driver ##### + ============================================================================== + + [..] + *** How to configure Interrupts using CORTEX HAL driver *** + =========================================================== + [..] + This section provides functions allowing to configure the NVIC interrupts (IRQ). + The Cortex-M4 exceptions are managed by CMSIS functions. + + (#) Configure the NVIC Priority Grouping using HAL_NVIC_SetPriorityGrouping() function. + (#) Configure the priority of the selected IRQ Channels using HAL_NVIC_SetPriority(). + (#) Enable the selected IRQ Channels using HAL_NVIC_EnableIRQ(). + + -@- When the NVIC_PRIORITYGROUP_0 is selected, IRQ pre-emption is no more possible. + The pending IRQ priority will be managed only by the sub priority. + + -@- IRQ priority order (sorted by highest to lowest priority): + (+@) Lowest pre-emption priority + (+@) Lowest sub priority + (+@) Lowest hardware priority (IRQ number) + + [..] + *** How to configure SysTick using CORTEX HAL driver *** + ======================================================== + [..] + Setup SysTick Timer for time base. + + (+) The HAL_SYSTICK_Config() function calls the SysTick_Config() function which + is a CMSIS function that: + (++) Configures the SysTick Reload register with value passed as function parameter. + (++) Configures the SysTick IRQ priority to the lowest value (0x0F). + (++) Resets the SysTick Counter register. + (++) Configures the SysTick Counter clock source to be Core Clock Source (HCLK). + (++) Enables the SysTick Interrupt. + (++) Starts the SysTick Counter. + + (+) You can change the SysTick Clock source to be HCLK_Div8 by calling the macro + __HAL_CORTEX_SYSTICKCLK_CONFIG(SYSTICK_CLKSOURCE_HCLK_DIV8) just after the + HAL_SYSTICK_Config() function call. The __HAL_CORTEX_SYSTICKCLK_CONFIG() macro is defined + inside the stm32l4xx_hal_cortex.h file. + + (+) You can change the SysTick IRQ priority by calling the + HAL_NVIC_SetPriority(SysTick_IRQn,...) function just after the HAL_SYSTICK_Config() function + call. The HAL_NVIC_SetPriority() call the NVIC_SetPriority() function which is a CMSIS function. + + (+) To adjust the SysTick time base, use the following formula: + + Reload Value = SysTick Counter Clock (Hz) x Desired Time base (s) + (++) Reload Value is the parameter to be passed for HAL_SYSTICK_Config() function + (++) Reload Value should not exceed 0xFFFFFF + + @endverbatim + ****************************************************************************** + + The table below gives the allowed values of the pre-emption priority and subpriority according + to the Priority Grouping configuration performed by HAL_NVIC_SetPriorityGrouping() function. + + ========================================================================================================================== + NVIC_PriorityGroup | NVIC_IRQChannelPreemptionPriority | NVIC_IRQChannelSubPriority | Description + ========================================================================================================================== + NVIC_PRIORITYGROUP_0 | 0 | 0-15 | 0 bit for pre-emption priority + | | | 4 bits for subpriority + -------------------------------------------------------------------------------------------------------------------------- + NVIC_PRIORITYGROUP_1 | 0-1 | 0-7 | 1 bit for pre-emption priority + | | | 3 bits for subpriority + -------------------------------------------------------------------------------------------------------------------------- + NVIC_PRIORITYGROUP_2 | 0-3 | 0-3 | 2 bits for pre-emption priority + | | | 2 bits for subpriority + -------------------------------------------------------------------------------------------------------------------------- + NVIC_PRIORITYGROUP_3 | 0-7 | 0-1 | 3 bits for pre-emption priority + | | | 1 bit for subpriority + -------------------------------------------------------------------------------------------------------------------------- + NVIC_PRIORITYGROUP_4 | 0-15 | 0 | 4 bits for pre-emption priority + | | | 0 bit for subpriority + ========================================================================================================================== + + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup CORTEX + * @{ + */ + +#ifdef HAL_CORTEX_MODULE_ENABLED + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/** @addtogroup CORTEX_Exported_Functions + * @{ + */ + + +/** @addtogroup CORTEX_Exported_Functions_Group1 + * @brief Initialization and Configuration functions + * +@verbatim + ============================================================================== + ##### Initialization and Configuration functions ##### + ============================================================================== + [..] + This section provides the CORTEX HAL driver functions allowing to configure Interrupts + SysTick functionalities + +@endverbatim + * @{ + */ + + +/** + * @brief Set the priority grouping field (pre-emption priority and subpriority) + * using the required unlock sequence. + * @param PriorityGroup: The priority grouping bits length. + * This parameter can be one of the following values: + * @arg NVIC_PRIORITYGROUP_0: 0 bit for pre-emption priority, + * 4 bits for subpriority + * @arg NVIC_PRIORITYGROUP_1: 1 bit for pre-emption priority, + * 3 bits for subpriority + * @arg NVIC_PRIORITYGROUP_2: 2 bits for pre-emption priority, + * 2 bits for subpriority + * @arg NVIC_PRIORITYGROUP_3: 3 bits for pre-emption priority, + * 1 bit for subpriority + * @arg NVIC_PRIORITYGROUP_4: 4 bits for pre-emption priority, + * 0 bit for subpriority + * @note When the NVIC_PriorityGroup_0 is selected, IRQ pre-emption is no more possible. + * The pending IRQ priority will be managed only by the subpriority. + * @retval None + */ +void HAL_NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + /* Check the parameters */ + assert_param(IS_NVIC_PRIORITY_GROUP(PriorityGroup)); + + /* Set the PRIGROUP[10:8] bits according to the PriorityGroup parameter value */ + NVIC_SetPriorityGrouping(PriorityGroup); +} + +/** + * @brief Set the priority of an interrupt. + * @param IRQn: External interrupt number. + * This parameter can be an enumerator of IRQn_Type enumeration + * (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32l4xxxx.h)) + * @param PreemptPriority: The pre-emption priority for the IRQn channel. + * This parameter can be a value between 0 and 15 + * A lower priority value indicates a higher priority + * @param SubPriority: the subpriority level for the IRQ channel. + * This parameter can be a value between 0 and 15 + * A lower priority value indicates a higher priority. + * @retval None + */ +void HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t prioritygroup = 0x00; + + /* Check the parameters */ + assert_param(IS_NVIC_SUB_PRIORITY(SubPriority)); + assert_param(IS_NVIC_PREEMPTION_PRIORITY(PreemptPriority)); + + prioritygroup = NVIC_GetPriorityGrouping(); + + NVIC_SetPriority(IRQn, NVIC_EncodePriority(prioritygroup, PreemptPriority, SubPriority)); +} + +/** + * @brief Enable a device specific interrupt in the NVIC interrupt controller. + * @note To configure interrupts priority correctly, the NVIC_PriorityGroupConfig() + * function should be called before. + * @param IRQn External interrupt number. + * This parameter can be an enumerator of IRQn_Type enumeration + * (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32l4xxxx.h)) + * @retval None + */ +void HAL_NVIC_EnableIRQ(IRQn_Type IRQn) +{ + /* Check the parameters */ + assert_param(IS_NVIC_DEVICE_IRQ(IRQn)); + + /* Enable interrupt */ + NVIC_EnableIRQ(IRQn); +} + +/** + * @brief Disable a device specific interrupt in the NVIC interrupt controller. + * @param IRQn External interrupt number. + * This parameter can be an enumerator of IRQn_Type enumeration + * (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32l4xxxx.h)) + * @retval None + */ +void HAL_NVIC_DisableIRQ(IRQn_Type IRQn) +{ + /* Check the parameters */ + assert_param(IS_NVIC_DEVICE_IRQ(IRQn)); + + /* Disable interrupt */ + NVIC_DisableIRQ(IRQn); +} + +/** + * @brief Initiate a system reset request to reset the MCU. + * @retval None + */ +void HAL_NVIC_SystemReset(void) +{ + /* System Reset */ + NVIC_SystemReset(); +} + +/** + * @brief Initialize the System Timer with interrupt enabled and start the System Tick Timer (SysTick): + * Counter is in free running mode to generate periodic interrupts. + * @param TicksNumb: Specifies the ticks Number of ticks between two interrupts. + * @retval status: - 0 Function succeeded. + * - 1 Function failed. + */ +uint32_t HAL_SYSTICK_Config(uint32_t TicksNumb) +{ + return SysTick_Config(TicksNumb); +} +/** + * @} + */ + +/** @addtogroup CORTEX_Exported_Functions_Group2 + * @brief Cortex control functions + * +@verbatim + ============================================================================== + ##### Peripheral Control functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to control the CORTEX + (NVIC, SYSTICK, MPU) functionalities. + + +@endverbatim + * @{ + */ + +/** + * @brief Get the priority grouping field from the NVIC Interrupt Controller. + * @retval Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field) + */ +uint32_t HAL_NVIC_GetPriorityGrouping(void) +{ + /* Get the PRIGROUP[10:8] field value */ + return NVIC_GetPriorityGrouping(); +} + +/** + * @brief Get the priority of an interrupt. + * @param IRQn: External interrupt number. + * This parameter can be an enumerator of IRQn_Type enumeration + * (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32l4xxxx.h)) + * @param PriorityGroup: the priority grouping bits length. + * This parameter can be one of the following values: + * @arg NVIC_PRIORITYGROUP_0: 0 bit for pre-emption priority, + * 4 bits for subpriority + * @arg NVIC_PRIORITYGROUP_1: 1 bit for pre-emption priority, + * 3 bits for subpriority + * @arg NVIC_PRIORITYGROUP_2: 2 bits for pre-emption priority, + * 2 bits for subpriority + * @arg NVIC_PRIORITYGROUP_3: 3 bits for pre-emption priority, + * 1 bit for subpriority + * @arg NVIC_PRIORITYGROUP_4: 4 bits for pre-emption priority, + * 0 bit for subpriority + * @param pPreemptPriority: Pointer on the Preemptive priority value (starting from 0). + * @param pSubPriority: Pointer on the Subpriority value (starting from 0). + * @retval None + */ +void HAL_NVIC_GetPriority(IRQn_Type IRQn, uint32_t PriorityGroup, uint32_t *pPreemptPriority, uint32_t *pSubPriority) +{ + /* Check the parameters */ + assert_param(IS_NVIC_PRIORITY_GROUP(PriorityGroup)); + /* Get priority for Cortex-M system or device specific interrupts */ + NVIC_DecodePriority(NVIC_GetPriority(IRQn), PriorityGroup, pPreemptPriority, pSubPriority); +} + +/** + * @brief Set Pending bit of an external interrupt. + * @param IRQn External interrupt number + * This parameter can be an enumerator of IRQn_Type enumeration + * (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32l4xxxx.h)) + * @retval None + */ +void HAL_NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + /* Check the parameters */ + assert_param(IS_NVIC_DEVICE_IRQ(IRQn)); + + /* Set interrupt pending */ + NVIC_SetPendingIRQ(IRQn); +} + +/** + * @brief Get Pending Interrupt (read the pending register in the NVIC + * and return the pending bit for the specified interrupt). + * @param IRQn External interrupt number. + * This parameter can be an enumerator of IRQn_Type enumeration + * (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32l4xxxx.h)) + * @retval status: - 0 Interrupt status is not pending. + * - 1 Interrupt status is pending. + */ +uint32_t HAL_NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + /* Check the parameters */ + assert_param(IS_NVIC_DEVICE_IRQ(IRQn)); + + /* Return 1 if pending else 0 */ + return NVIC_GetPendingIRQ(IRQn); +} + +/** + * @brief Clear the pending bit of an external interrupt. + * @param IRQn External interrupt number. + * This parameter can be an enumerator of IRQn_Type enumeration + * (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32l4xxxx.h)) + * @retval None + */ +void HAL_NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + /* Check the parameters */ + assert_param(IS_NVIC_DEVICE_IRQ(IRQn)); + + /* Clear pending interrupt */ + NVIC_ClearPendingIRQ(IRQn); +} + +/** + * @brief Get active interrupt (read the active register in NVIC and return the active bit). + * @param IRQn External interrupt number + * This parameter can be an enumerator of IRQn_Type enumeration + * (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32l4xxxx.h)) + * @retval status: - 0 Interrupt status is not pending. + * - 1 Interrupt status is pending. + */ +uint32_t HAL_NVIC_GetActive(IRQn_Type IRQn) +{ + /* Return 1 if active else 0 */ + return NVIC_GetActive(IRQn); +} + +/** + * @brief Configure the SysTick clock source. + * @param CLKSource: specifies the SysTick clock source. + * This parameter can be one of the following values: + * @arg SYSTICK_CLKSOURCE_HCLK_DIV8: AHB clock divided by 8 selected as SysTick clock source. + * @arg SYSTICK_CLKSOURCE_HCLK: AHB clock selected as SysTick clock source. + * @retval None + */ +void HAL_SYSTICK_CLKSourceConfig(uint32_t CLKSource) +{ + /* Check the parameters */ + assert_param(IS_SYSTICK_CLK_SOURCE(CLKSource)); + if (CLKSource == SYSTICK_CLKSOURCE_HCLK) + { + SysTick->CTRL |= SYSTICK_CLKSOURCE_HCLK; + } + else + { + SysTick->CTRL &= ~SYSTICK_CLKSOURCE_HCLK; + } +} + +/** + * @brief Handle SYSTICK interrupt request. + * @retval None + */ +void HAL_SYSTICK_IRQHandler(void) +{ + HAL_SYSTICK_Callback(); +} + +/** + * @brief SYSTICK callback. + * @retval None + */ +__weak void HAL_SYSTICK_Callback(void) +{ + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SYSTICK_Callback could be implemented in the user file + */ +} + +#if (__MPU_PRESENT == 1) +/** + * @brief Disable the MPU. + * @retval None + */ +void HAL_MPU_Disable(void) +{ + /* Make sure outstanding transfers are done */ + __DMB(); + + /* Disable fault exceptions */ + SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk; + + /* Disable the MPU and clear the control register*/ + MPU->CTRL = 0U; +} + +/** + * @brief Enable the MPU. + * @param MPU_Control: Specifies the control mode of the MPU during hard fault, + * NMI, FAULTMASK and privileged accessto the default memory + * This parameter can be one of the following values: + * @arg MPU_HFNMI_PRIVDEF_NONE + * @arg MPU_HARDFAULT_NMI + * @arg MPU_PRIVILEGED_DEFAULT + * @arg MPU_HFNMI_PRIVDEF + * @retval None + */ +void HAL_MPU_Enable(uint32_t MPU_Control) +{ + /* Enable the MPU */ + MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk; + + /* Enable fault exceptions */ + SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; + + /* Ensure MPU settings take effects */ + __DSB(); + __ISB(); +} + +/** + * @brief Initialize and configure the Region and the memory to be protected. + * @param MPU_Init: Pointer to a MPU_Region_InitTypeDef structure that contains + * the initialization and configuration information. + * @retval None + */ +void HAL_MPU_ConfigRegion(MPU_Region_InitTypeDef *MPU_Init) +{ + /* Check the parameters */ + assert_param(IS_MPU_REGION_NUMBER(MPU_Init->Number)); + assert_param(IS_MPU_REGION_ENABLE(MPU_Init->Enable)); + + /* Set the Region number */ + MPU->RNR = MPU_Init->Number; + + if ((MPU_Init->Enable) != RESET) + { + /* Check the parameters */ + assert_param(IS_MPU_INSTRUCTION_ACCESS(MPU_Init->DisableExec)); + assert_param(IS_MPU_REGION_PERMISSION_ATTRIBUTE(MPU_Init->AccessPermission)); + assert_param(IS_MPU_TEX_LEVEL(MPU_Init->TypeExtField)); + assert_param(IS_MPU_ACCESS_SHAREABLE(MPU_Init->IsShareable)); + assert_param(IS_MPU_ACCESS_CACHEABLE(MPU_Init->IsCacheable)); + assert_param(IS_MPU_ACCESS_BUFFERABLE(MPU_Init->IsBufferable)); + assert_param(IS_MPU_SUB_REGION_DISABLE(MPU_Init->SubRegionDisable)); + assert_param(IS_MPU_REGION_SIZE(MPU_Init->Size)); + + MPU->RBAR = MPU_Init->BaseAddress; + MPU->RASR = ((uint32_t)MPU_Init->DisableExec << MPU_RASR_XN_Pos) | + ((uint32_t)MPU_Init->AccessPermission << MPU_RASR_AP_Pos) | + ((uint32_t)MPU_Init->TypeExtField << MPU_RASR_TEX_Pos) | + ((uint32_t)MPU_Init->IsShareable << MPU_RASR_S_Pos) | + ((uint32_t)MPU_Init->IsCacheable << MPU_RASR_C_Pos) | + ((uint32_t)MPU_Init->IsBufferable << MPU_RASR_B_Pos) | + ((uint32_t)MPU_Init->SubRegionDisable << MPU_RASR_SRD_Pos) | + ((uint32_t)MPU_Init->Size << MPU_RASR_SIZE_Pos) | + ((uint32_t)MPU_Init->Enable << MPU_RASR_ENABLE_Pos); + } + else + { + MPU->RBAR = 0x00; + MPU->RASR = 0x00; + } +} +#endif /* __MPU_PRESENT */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* HAL_CORTEX_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_dma.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_dma.c new file mode 100644 index 0000000..8d30b49 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_dma.c @@ -0,0 +1,1179 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_dma.c + * @author MCD Application Team + * @brief DMA HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Direct Memory Access (DMA) peripheral: + * + Initialization and de-initialization functions + * + IO operation functions + * + Peripheral State and errors functions + @verbatim + ============================================================================== + ##### How to use this driver ##### + ============================================================================== + [..] + (#) Enable and configure the peripheral to be connected to the DMA Channel + (except for internal SRAM / FLASH memories: no initialization is + necessary). Please refer to the Reference manual for connection between peripherals + and DMA requests. + + (#) For a given Channel, program the required configuration through the following parameters: + Channel request, Transfer Direction, Source and Destination data formats, + Circular or Normal mode, Channel Priority level, Source and Destination Increment mode + using HAL_DMA_Init() function. + + Prior to HAL_DMA_Init the peripheral clock shall be enabled for both DMA & DMAMUX + thanks to: + (##) DMA1 or DMA2: __HAL_RCC_DMA1_CLK_ENABLE() or __HAL_RCC_DMA2_CLK_ENABLE() ; + (##) DMAMUX1: __HAL_RCC_DMAMUX1_CLK_ENABLE(); + + (#) Use HAL_DMA_GetState() function to return the DMA state and HAL_DMA_GetError() in case of error + detection. + + (#) Use HAL_DMA_Abort() function to abort the current transfer + + -@- In Memory-to-Memory transfer mode, Circular mode is not allowed. + + *** Polling mode IO operation *** + ================================= + [..] + (+) Use HAL_DMA_Start() to start DMA transfer after the configuration of Source + address and destination address and the Length of data to be transferred + (+) Use HAL_DMA_PollForTransfer() to poll for the end of current transfer, in this + case a fixed Timeout can be configured by User depending from his application. + + *** Interrupt mode IO operation *** + =================================== + [..] + (+) Configure the DMA interrupt priority using HAL_NVIC_SetPriority() + (+) Enable the DMA IRQ handler using HAL_NVIC_EnableIRQ() + (+) Use HAL_DMA_Start_IT() to start DMA transfer after the configuration of + Source address and destination address and the Length of data to be transferred. + In this case the DMA interrupt is configured + (+) Use HAL_DMA_IRQHandler() called under DMA_IRQHandler() Interrupt subroutine + (+) At the end of data transfer HAL_DMA_IRQHandler() function is executed and user can + add his own function to register callbacks with HAL_DMA_RegisterCallback(). + + *** DMA HAL driver macros list *** + ============================================= + [..] + Below the list of macros in DMA HAL driver. + + (+) __HAL_DMA_ENABLE: Enable the specified DMA Channel. + (+) __HAL_DMA_DISABLE: Disable the specified DMA Channel. + (+) __HAL_DMA_GET_FLAG: Get the DMA Channel pending flags. + (+) __HAL_DMA_CLEAR_FLAG: Clear the DMA Channel pending flags. + (+) __HAL_DMA_ENABLE_IT: Enable the specified DMA Channel interrupts. + (+) __HAL_DMA_DISABLE_IT: Disable the specified DMA Channel interrupts. + (+) __HAL_DMA_GET_IT_SOURCE: Check whether the specified DMA Channel interrupt is enabled or not. + + [..] + (@) You can refer to the DMA HAL driver header file for more useful macros + + @endverbatim + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup DMA DMA + * @brief DMA HAL module driver + * @{ + */ + +#ifdef HAL_DMA_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/** @defgroup DMA_Private_Functions DMA Private Functions + * @{ + */ +static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength); +#if defined(DMAMUX1) +static void DMA_CalcDMAMUXChannelBaseAndMask(DMA_HandleTypeDef *hdma); +static void DMA_CalcDMAMUXRequestGenBaseAndMask(DMA_HandleTypeDef *hdma); +#endif /* DMAMUX1 */ + +/** + * @} + */ + +/* Exported functions ---------------------------------------------------------*/ + +/** @defgroup DMA_Exported_Functions DMA Exported Functions + * @{ + */ + +/** @defgroup DMA_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and de-initialization functions + * +@verbatim + =============================================================================== + ##### Initialization and de-initialization functions ##### + =============================================================================== + [..] + This section provides functions allowing to initialize the DMA Channel source + and destination addresses, incrementation and data sizes, transfer direction, + circular/normal mode selection, memory-to-memory mode selection and Channel priority value. + [..] + The HAL_DMA_Init() function follows the DMA configuration procedures as described in + reference manual. + +@endverbatim + * @{ + */ + +/** + * @brief Initialize the DMA according to the specified + * parameters in the DMA_InitTypeDef and initialize the associated handle. + * @param hdma: Pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA Channel. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA_Init(DMA_HandleTypeDef *hdma) +{ + uint32_t tmp = 0; + + /* Check the DMA handle allocation */ + if(hdma == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance)); + assert_param(IS_DMA_DIRECTION(hdma->Init.Direction)); + assert_param(IS_DMA_PERIPHERAL_INC_STATE(hdma->Init.PeriphInc)); + assert_param(IS_DMA_MEMORY_INC_STATE(hdma->Init.MemInc)); + assert_param(IS_DMA_PERIPHERAL_DATA_SIZE(hdma->Init.PeriphDataAlignment)); + assert_param(IS_DMA_MEMORY_DATA_SIZE(hdma->Init.MemDataAlignment)); + assert_param(IS_DMA_MODE(hdma->Init.Mode)); + assert_param(IS_DMA_PRIORITY(hdma->Init.Priority)); + + assert_param(IS_DMA_ALL_REQUEST(hdma->Init.Request)); + + /* Compute the channel index */ + if ((uint32_t)(hdma->Instance) < (uint32_t)(DMA2_Channel1)) + { + /* DMA1 */ + hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2; + hdma->DmaBaseAddress = DMA1; + } + else + { + /* DMA2 */ + hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA2_Channel1) / ((uint32_t)DMA2_Channel2 - (uint32_t)DMA2_Channel1)) << 2; + hdma->DmaBaseAddress = DMA2; + } + + /* Change DMA peripheral state */ + hdma->State = HAL_DMA_STATE_BUSY; + + /* Get the CR register value */ + tmp = hdma->Instance->CCR; + + /* Clear PL, MSIZE, PSIZE, MINC, PINC, CIRC, DIR and MEM2MEM bits */ + tmp &= ((uint32_t)~(DMA_CCR_PL | DMA_CCR_MSIZE | DMA_CCR_PSIZE | + DMA_CCR_MINC | DMA_CCR_PINC | DMA_CCR_CIRC | + DMA_CCR_DIR | DMA_CCR_MEM2MEM)); + + /* Prepare the DMA Channel configuration */ + tmp |= hdma->Init.Direction | + hdma->Init.PeriphInc | hdma->Init.MemInc | + hdma->Init.PeriphDataAlignment | hdma->Init.MemDataAlignment | + hdma->Init.Mode | hdma->Init.Priority; + + /* Write to DMA Channel CR register */ + hdma->Instance->CCR = tmp; + + +#if defined(DMAMUX1) + /* Initialize parameters for DMAMUX channel : + DMAmuxChannel, DMAmuxChannelStatus and DMAmuxChannelStatusMask + */ + DMA_CalcDMAMUXChannelBaseAndMask(hdma); + + if(hdma->Init.Direction == DMA_MEMORY_TO_MEMORY) + { + /* if memory to memory force the request to 0*/ + hdma->Init.Request = DMA_REQUEST_MEM2MEM; + } + + /* Set peripheral request to DMAMUX channel */ + hdma->DMAmuxChannel->CCR = (hdma->Init.Request & DMAMUX_CxCR_DMAREQ_ID); + + /* Clear the DMAMUX synchro overrun flag */ + hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask; + + if(((hdma->Init.Request > 0) && (hdma->Init.Request <= DMA_REQUEST_GENERATOR3))) + { + /* Initialize parameters for DMAMUX request generator : + DMAmuxRequestGen, DMAmuxRequestGenStatus and DMAmuxRequestGenStatusMask + */ + DMA_CalcDMAMUXRequestGenBaseAndMask(hdma); + + /* Reset the DMAMUX request generator register*/ + hdma->DMAmuxRequestGen->RGCR = 0U; + + /* Clear the DMAMUX request generator overrun flag */ + hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask; + } + else + { + hdma->DMAmuxRequestGen = 0U; + hdma->DMAmuxRequestGenStatus = 0U; + hdma->DMAmuxRequestGenStatusMask = 0U; + } +#endif /* DMAMUX1 */ + +#if !defined (DMAMUX1) + + /* Set request selection */ + if(hdma->Init.Direction != DMA_MEMORY_TO_MEMORY) + { + /* Write to DMA channel selection register */ + if (DMA1 == hdma->DmaBaseAddress) + { + /* Reset request selection for DMA1 Channelx */ + DMA1_CSELR->CSELR &= ~(DMA_CSELR_C1S << hdma->ChannelIndex); + + /* Configure request selection for DMA1 Channelx */ + DMA1_CSELR->CSELR |= (uint32_t) (hdma->Init.Request << (hdma->ChannelIndex)); + } + else /* DMA2 */ + { + /* Reset request selection for DMA2 Channelx */ + DMA2_CSELR->CSELR &= ~(DMA_CSELR_C1S << hdma->ChannelIndex); + + /* Configure request selection for DMA2 Channelx */ + DMA2_CSELR->CSELR |= (uint32_t) (hdma->Init.Request << (hdma->ChannelIndex)); + } + } + +#endif /* STM32L431xx || STM32L432xx || STM32L433xx || STM32L442xx || STM32L443xx */ + /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L442xx || STM32L486xx */ + /* STM32L496xx || STM32L4A6xx */ + + /* Clean callbacks */ + hdma->XferCpltCallback = NULL; + hdma->XferHalfCpltCallback = NULL; + hdma->XferErrorCallback = NULL; + hdma->XferAbortCallback = NULL; + + /* Initialise the error code */ + hdma->ErrorCode = HAL_DMA_ERROR_NONE; + + /* Initialize the DMA state*/ + hdma->State = HAL_DMA_STATE_READY; + + /* Allocate lock resource and initialize it */ + hdma->Lock = HAL_UNLOCKED; + + return HAL_OK; +} + +/** + * @brief DeInitialize the DMA peripheral. + * @param hdma: pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA Channel. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA_DeInit(DMA_HandleTypeDef *hdma) +{ + + /* Check the DMA handle allocation */ + if (NULL == hdma ) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance)); + + /* Disable the selected DMA Channelx */ + __HAL_DMA_DISABLE(hdma); + + /* Compute the channel index */ + if ((uint32_t)(hdma->Instance) < (uint32_t)(DMA2_Channel1)) + { + /* DMA1 */ + hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2; + hdma->DmaBaseAddress = DMA1; + } + else + { + /* DMA2 */ + hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA2_Channel1) / ((uint32_t)DMA2_Channel2 - (uint32_t)DMA2_Channel1)) << 2; + hdma->DmaBaseAddress = DMA2; + } + + /* Reset DMA Channel control register */ + hdma->Instance->CCR = 0; + + /* Clear all flags */ + hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex)); + +#if !defined (DMAMUX1) + + /* Reset DMA channel selection register */ + if (DMA1 == hdma->DmaBaseAddress) + { + /* DMA1 */ + DMA1_CSELR->CSELR &= ~(DMA_CSELR_C1S << (hdma->ChannelIndex)); + } + else + { + /* DMA2 */ + DMA2_CSELR->CSELR &= ~(DMA_CSELR_C1S << (hdma->ChannelIndex)); + } +#endif /* STM32L431xx || STM32L432xx || STM32L433xx || STM32L442xx || STM32L443xx */ + /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L442xx || STM32L486xx */ + /* STM32L496xx || STM32L4A6xx */ + +#if defined(DMAMUX1) + + /* Initialize parameters for DMAMUX channel : + DMAmuxChannel, DMAmuxChannelStatus and DMAmuxChannelStatusMask */ + + DMA_CalcDMAMUXChannelBaseAndMask(hdma); + + /* Reset the DMAMUX channel that corresponds to the DMA channel */ + hdma->DMAmuxChannel->CCR = 0; + + /* Clear the DMAMUX synchro overrun flag */ + hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask; + + /* Reset Request generator parameters if any */ + if(((hdma->Init.Request > 0) && (hdma->Init.Request <= DMA_REQUEST_GENERATOR3))) + { + /* Initialize parameters for DMAMUX request generator : + DMAmuxRequestGen, DMAmuxRequestGenStatus and DMAmuxRequestGenStatusMask + */ + DMA_CalcDMAMUXRequestGenBaseAndMask(hdma); + + /* Reset the DMAMUX request generator register*/ + hdma->DMAmuxRequestGen->RGCR = 0U; + + /* Clear the DMAMUX request generator overrun flag */ + hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask; + } + + hdma->DMAmuxRequestGen = 0U; + hdma->DMAmuxRequestGenStatus = 0U; + hdma->DMAmuxRequestGenStatusMask = 0U; + +#endif /* DMAMUX1 */ + + /* Initialise the error code */ + hdma->ErrorCode = HAL_DMA_ERROR_NONE; + + /* Initialize the DMA state */ + hdma->State = HAL_DMA_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(hdma); + + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup DMA_Exported_Functions_Group2 Input and Output operation functions + * @brief Input and Output operation functions + * +@verbatim + =============================================================================== + ##### IO operation functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Configure the source, destination address and data length and Start DMA transfer + (+) Configure the source, destination address and data length and + Start DMA transfer with interrupt + (+) Abort DMA transfer + (+) Poll for transfer complete + (+) Handle DMA interrupt request + +@endverbatim + * @{ + */ + +/** + * @brief Start the DMA Transfer. + * @param hdma: pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA Channel. + * @param SrcAddress: The source memory Buffer address + * @param DstAddress: The destination memory Buffer address + * @param DataLength: The length of data to be transferred from source to destination + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA_Start(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check the parameters */ + assert_param(IS_DMA_BUFFER_SIZE(DataLength)); + + /* Process locked */ + __HAL_LOCK(hdma); + + if(HAL_DMA_STATE_READY == hdma->State) + { + /* Change DMA peripheral state */ + hdma->State = HAL_DMA_STATE_BUSY; + hdma->ErrorCode = HAL_DMA_ERROR_NONE; + + /* Disable the peripheral */ + __HAL_DMA_DISABLE(hdma); + + /* Configure the source, destination address and the data length & clear flags*/ + DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength); + + /* Enable the Peripheral */ + __HAL_DMA_ENABLE(hdma); + } + else + { + /* Process Unlocked */ + __HAL_UNLOCK(hdma); + status = HAL_BUSY; + } + return status; +} + +/** + * @brief Start the DMA Transfer with interrupt enabled. + * @param hdma: pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA Channel. + * @param SrcAddress: The source memory Buffer address + * @param DstAddress: The destination memory Buffer address + * @param DataLength: The length of data to be transferred from source to destination + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check the parameters */ + assert_param(IS_DMA_BUFFER_SIZE(DataLength)); + + /* Process locked */ + __HAL_LOCK(hdma); + + if(HAL_DMA_STATE_READY == hdma->State) + { + /* Change DMA peripheral state */ + hdma->State = HAL_DMA_STATE_BUSY; + hdma->ErrorCode = HAL_DMA_ERROR_NONE; + + /* Disable the peripheral */ + __HAL_DMA_DISABLE(hdma); + + /* Configure the source, destination address and the data length & clear flags*/ + DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength); + + /* Enable the transfer complete interrupt */ + /* Enable the transfer Error interrupt */ + if(NULL != hdma->XferHalfCpltCallback ) + { + /* Enable the Half transfer complete interrupt as well */ + __HAL_DMA_ENABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE)); + } + else + { + __HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT); + __HAL_DMA_ENABLE_IT(hdma, (DMA_IT_TC | DMA_IT_TE)); + } + +#ifdef DMAMUX1 + + /* Check if DMAMUX Synchronization is enabled*/ + if((hdma->DMAmuxChannel->CCR & DMAMUX_CxCR_SE) != 0U) + { + /* Enable DMAMUX sync overrun IT*/ + hdma->DMAmuxChannel->CCR |= DMAMUX_CxCR_SOIE; + } + + if(hdma->DMAmuxRequestGen != 0U) + { + /* if using DMAMUX request generator, enable the DMAMUX request generator overrun IT*/ + /* enable the request gen overrun IT*/ + hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_OIE; + } + +#endif /* DMAMUX1 */ + + /* Enable the Peripheral */ + __HAL_DMA_ENABLE(hdma); + } + else + { + /* Process Unlocked */ + __HAL_UNLOCK(hdma); + + /* Remain BUSY */ + status = HAL_BUSY; + } + return status; +} + +/** + * @brief Abort the DMA Transfer. + * @param hdma: pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA Channel. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *hdma) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check the DMA peripheral handle */ + if(NULL == hdma) + { + return HAL_ERROR; + } + + /* Disable DMA IT */ + __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE)); + +#if defined(DMAMUX1) + /* disable the DMAMUX sync overrun IT*/ + hdma->DMAmuxChannel->CCR &= ~DMAMUX_CxCR_SOIE; +#endif /* DMAMUX1 */ + + /* Disable the channel */ + __HAL_DMA_DISABLE(hdma); + + /* Clear all flags */ + hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << hdma->ChannelIndex); + +#if defined(DMAMUX1) + /* Clear the DMAMUX synchro overrun flag */ + hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask; + + if(hdma->DMAmuxRequestGen != 0U) + { + /* if using DMAMUX request generator, disable the DMAMUX request generator overrun IT*/ + /* disable the request gen overrun IT*/ + hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_OIE; + + /* Clear the DMAMUX request generator overrun flag */ + hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask; + } + +#endif /* DMAMUX1 */ + + /* Change the DMA state */ + hdma->State = HAL_DMA_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hdma); + + return status; +} + +/** + * @brief Aborts the DMA Transfer in Interrupt mode. + * @param hdma : pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA Channel. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA_Abort_IT(DMA_HandleTypeDef *hdma) +{ + HAL_StatusTypeDef status = HAL_OK; + + if(HAL_DMA_STATE_BUSY != hdma->State) + { + /* no transfer ongoing */ + hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER; + + status = HAL_ERROR; + } + else + { + /* Disable DMA IT */ + __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE)); + + /* Disable the channel */ + __HAL_DMA_DISABLE(hdma); + +#if defined(DMAMUX1) + /* disable the DMAMUX sync overrun IT*/ + hdma->DMAmuxChannel->CCR &= ~DMAMUX_CxCR_SOIE; + + /* Clear all flags */ + hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << hdma->ChannelIndex); + + /* Clear the DMAMUX synchro overrun flag */ + hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask; + + if(hdma->DMAmuxRequestGen != 0U) + { + /* if using DMAMUX request generator, disable the DMAMUX request generator overrun IT*/ + /* disable the request gen overrun IT*/ + hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_OIE; + + /* Clear the DMAMUX request generator overrun flag */ + hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask; + } + +#else + /* Clear all flags */ + hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << hdma->ChannelIndex); +#endif /* DMAMUX1 */ + + /* Change the DMA state */ + hdma->State = HAL_DMA_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hdma); + + /* Call User Abort callback */ + if(hdma->XferAbortCallback != NULL) + { + hdma->XferAbortCallback(hdma); + } + } + return status; +} + +/** + * @brief Polling for transfer complete. + * @param hdma: pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA Channel. + * @param CompleteLevel: Specifies the DMA level complete. + * @param Timeout: Timeout duration. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA_PollForTransfer(DMA_HandleTypeDef *hdma, HAL_DMA_LevelCompleteTypeDef CompleteLevel, uint32_t Timeout) +{ + uint32_t temp; + uint32_t tickstart = 0; + + if(HAL_DMA_STATE_BUSY != hdma->State) + { + /* no transfer ongoing */ + hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER; + __HAL_UNLOCK(hdma); + return HAL_ERROR; + } + + /* Polling mode not supported in circular mode */ + if (RESET != (hdma->Instance->CCR & DMA_CCR_CIRC)) + { + hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED; + return HAL_ERROR; + } + + /* Get the level transfer complete flag */ + if (HAL_DMA_FULL_TRANSFER == CompleteLevel) + { + /* Transfer Complete flag */ + temp = DMA_FLAG_TC1 << hdma->ChannelIndex; + } + else + { + /* Half Transfer Complete flag */ + temp = DMA_FLAG_HT1 << hdma->ChannelIndex; + } + + /* Get tick */ + tickstart = HAL_GetTick(); + + while(RESET == (hdma->DmaBaseAddress->ISR & temp)) + { + if((RESET != (hdma->DmaBaseAddress->ISR & (DMA_FLAG_TE1 << hdma->ChannelIndex)))) + { + /* When a DMA transfer error occurs */ + /* A hardware clear of its EN bits is performed */ + /* Clear all flags */ + hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << hdma->ChannelIndex); + + /* Update error code */ + hdma->ErrorCode = HAL_DMA_ERROR_TE; + + /* Change the DMA state */ + hdma->State= HAL_DMA_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hdma); + + return HAL_ERROR; + } + /* Check for the Timeout */ + if(Timeout != HAL_MAX_DELAY) + { + if((Timeout == 0) || ((HAL_GetTick() - tickstart) > Timeout)) + { + /* Update error code */ + hdma->ErrorCode = HAL_DMA_ERROR_TIMEOUT; + + /* Change the DMA state */ + hdma->State = HAL_DMA_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hdma); + + return HAL_ERROR; + } + } + } + +#if defined(DMAMUX1) + /*Check for DMAMUX Request generator (if used) overrun status */ + if(hdma->DMAmuxRequestGen != 0U) + { + /* if using DMAMUX request generator Check for DMAMUX request generator overrun */ + if((hdma->DMAmuxRequestGenStatus->RGSR & hdma->DMAmuxRequestGenStatusMask) != 0U) + { + /* Disable the request gen overrun interrupt */ + hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_OIE; + + /* Clear the DMAMUX request generator overrun flag */ + hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask; + + /* Update error code */ + hdma->ErrorCode |= HAL_DMA_ERROR_REQGEN; + } + } + + /* Check for DMAMUX Synchronization overrun */ + if((hdma->DMAmuxChannelStatus->CSR & hdma->DMAmuxChannelStatusMask) != 0U) + { + /* Clear the DMAMUX synchro overrun flag */ + hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask; + + /* Update error code */ + hdma->ErrorCode |= HAL_DMA_ERROR_SYNC; + } +#endif /* DMAMUX1 */ + + if(HAL_DMA_FULL_TRANSFER == CompleteLevel) + { + /* Clear the transfer complete flag */ + hdma->DmaBaseAddress->IFCR = (DMA_FLAG_TC1 << hdma->ChannelIndex); + + /* The selected Channelx EN bit is cleared (DMA is disabled and + all transfers are complete) */ + hdma->State = HAL_DMA_STATE_READY; + } + else + { + /* Clear the half transfer complete flag */ + hdma->DmaBaseAddress->IFCR = (DMA_FLAG_HT1 << hdma->ChannelIndex); + } + + /* Process unlocked */ + __HAL_UNLOCK(hdma); + + return HAL_OK; +} + +/** + * @brief Handle DMA interrupt request. + * @param hdma: pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA Channel. + * @retval None + */ +void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma) +{ + uint32_t flag_it = hdma->DmaBaseAddress->ISR; + uint32_t source_it = hdma->Instance->CCR; + + /* Half Transfer Complete Interrupt management ******************************/ + if ((RESET != (flag_it & (DMA_FLAG_HT1 << hdma->ChannelIndex))) && (RESET != (source_it & DMA_IT_HT))) + { + /* Disable the half transfer interrupt if the DMA mode is not CIRCULAR */ + if((hdma->Instance->CCR & DMA_CCR_CIRC) == 0) + { + /* Disable the half transfer interrupt */ + __HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT); + } + /* Clear the half transfer complete flag */ + hdma->DmaBaseAddress->IFCR = (DMA_ISR_HTIF1 << hdma->ChannelIndex); + + /* DMA peripheral state is not updated in Half Transfer */ + /* but in Transfer Complete case */ + + if(hdma->XferHalfCpltCallback != NULL) + { + /* Half transfer callback */ + hdma->XferHalfCpltCallback(hdma); + } + } + + /* Transfer Complete Interrupt management ***********************************/ + else if ((RESET != (flag_it & (DMA_FLAG_TC1 << hdma->ChannelIndex))) && (RESET != (source_it & DMA_IT_TC))) + { + if((hdma->Instance->CCR & DMA_CCR_CIRC) == 0) + { + /* Disable the transfer complete and error interrupt */ + __HAL_DMA_DISABLE_IT(hdma, DMA_IT_TE | DMA_IT_TC); + + /* Change the DMA state */ + hdma->State = HAL_DMA_STATE_READY; + } + /* Clear the transfer complete flag */ + hdma->DmaBaseAddress->IFCR = (DMA_ISR_TCIF1 << hdma->ChannelIndex); + + /* Process Unlocked */ + __HAL_UNLOCK(hdma); + + if(hdma->XferCpltCallback != NULL) + { + /* Transfer complete callback */ + hdma->XferCpltCallback(hdma); + } + } + + /* Transfer Error Interrupt management **************************************/ + else if (( RESET != (flag_it & (DMA_FLAG_TE1 << hdma->ChannelIndex))) && (RESET != (source_it & DMA_IT_TE))) + { + /* When a DMA transfer error occurs */ + /* A hardware clear of its EN bits is performed */ + /* Disable ALL DMA IT */ + __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE)); + + /* Clear all flags */ + hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << hdma->ChannelIndex); + + /* Update error code */ + hdma->ErrorCode = HAL_DMA_ERROR_TE; + + /* Change the DMA state */ + hdma->State = HAL_DMA_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hdma); + + if (hdma->XferErrorCallback != NULL) + { + /* Transfer error callback */ + hdma->XferErrorCallback(hdma); + } + } + return; +} + +/** + * @brief Register callbacks + * @param hdma: pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA Channel. + * @param CallbackID: User Callback identifer + * a HAL_DMA_CallbackIDTypeDef ENUM as parameter. + * @param pCallback: pointer to private callbacsk function which has pointer to + * a DMA_HandleTypeDef structure as parameter. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA_RegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID, void (* pCallback)( DMA_HandleTypeDef * _hdma)) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(hdma); + + if(HAL_DMA_STATE_READY == hdma->State) + { + switch (CallbackID) + { + case HAL_DMA_XFER_CPLT_CB_ID: + hdma->XferCpltCallback = pCallback; + break; + + case HAL_DMA_XFER_HALFCPLT_CB_ID: + hdma->XferHalfCpltCallback = pCallback; + break; + + case HAL_DMA_XFER_ERROR_CB_ID: + hdma->XferErrorCallback = pCallback; + break; + + case HAL_DMA_XFER_ABORT_CB_ID: + hdma->XferAbortCallback = pCallback; + break; + + default: + status = HAL_ERROR; + break; + } + } + else + { + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hdma); + + return status; +} + +/** + * @brief UnRegister callbacks + * @param hdma: pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA Channel. + * @param CallbackID: User Callback identifer + * a HAL_DMA_CallbackIDTypeDef ENUM as parameter. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(hdma); + + if(HAL_DMA_STATE_READY == hdma->State) + { + switch (CallbackID) + { + case HAL_DMA_XFER_CPLT_CB_ID: + hdma->XferCpltCallback = NULL; + break; + + case HAL_DMA_XFER_HALFCPLT_CB_ID: + hdma->XferHalfCpltCallback = NULL; + break; + + case HAL_DMA_XFER_ERROR_CB_ID: + hdma->XferErrorCallback = NULL; + break; + + case HAL_DMA_XFER_ABORT_CB_ID: + hdma->XferAbortCallback = NULL; + break; + + case HAL_DMA_XFER_ALL_CB_ID: + hdma->XferCpltCallback = NULL; + hdma->XferHalfCpltCallback = NULL; + hdma->XferErrorCallback = NULL; + hdma->XferAbortCallback = NULL; + break; + + default: + status = HAL_ERROR; + break; + } + } + else + { + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hdma); + + return status; +} + +/** + * @} + */ + + + +/** @defgroup DMA_Exported_Functions_Group3 Peripheral State and Errors functions + * @brief Peripheral State and Errors functions + * +@verbatim + =============================================================================== + ##### Peripheral State and Errors functions ##### + =============================================================================== + [..] + This subsection provides functions allowing to + (+) Check the DMA state + (+) Get error code + +@endverbatim + * @{ + */ + +/** + * @brief Return the DMA hande state. + * @param hdma: pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA Channel. + * @retval HAL state + */ +HAL_DMA_StateTypeDef HAL_DMA_GetState(DMA_HandleTypeDef *hdma) +{ + /* Return DMA handle state */ + return hdma->State; +} + +/** + * @brief Return the DMA error code. + * @param hdma : pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA Channel. + * @retval DMA Error Code + */ +uint32_t HAL_DMA_GetError(DMA_HandleTypeDef *hdma) +{ + return hdma->ErrorCode; +} + +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup DMA_Private_Functions + * @{ + */ + +/** + * @brief Sets the DMA Transfer parameter. + * @param hdma: pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA Channel. + * @param SrcAddress: The source memory Buffer address + * @param DstAddress: The destination memory Buffer address + * @param DataLength: The length of data to be transferred from source to destination + * @retval HAL status + */ +static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength) +{ +#if defined(DMAMUX1) + /* Clear the DMAMUX synchro overrun flag */ + hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask; + + if(hdma->DMAmuxRequestGen != 0U) + { + /* Clear the DMAMUX request generator overrun flag */ + hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask; + } +#endif + + /* Clear all flags */ + hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << hdma->ChannelIndex); + + /* Configure DMA Channel data length */ + hdma->Instance->CNDTR = DataLength; + + /* Peripheral to Memory */ + if((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH) + { + /* Configure DMA Channel destination address */ + hdma->Instance->CPAR = DstAddress; + + /* Configure DMA Channel source address */ + hdma->Instance->CMAR = SrcAddress; + } + /* Memory to Peripheral */ + else + { + /* Configure DMA Channel source address */ + hdma->Instance->CPAR = SrcAddress; + + /* Configure DMA Channel destination address */ + hdma->Instance->CMAR = DstAddress; + } +} + +#if defined(DMAMUX1) + +/** + * @brief Updates the DMA handle with the DMAMUX channel and status mask depending on stream number + * @param hdma: pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA Stream. + * @retval None + */ +static void DMA_CalcDMAMUXChannelBaseAndMask(DMA_HandleTypeDef *hdma) +{ + uint32_t channel_number = 0; + DMAMUX_Channel_TypeDef *DMAMUX1_ChannelBase; + + /* check if instance is not outside the DMA channel range */ + if ((uint32_t)hdma->Instance < (uint32_t)DMA2_Channel1) + { + /* DMA1 */ + DMAMUX1_ChannelBase = DMAMUX1_Channel0; + } + else + { + /* DMA2 */ + DMAMUX1_ChannelBase = DMAMUX1_Channel7; + } + channel_number = (((uint32_t)hdma->Instance & 0xFF) - 8) / 20; + hdma->DMAmuxChannel = (DMAMUX_Channel_TypeDef *)(uint32_t)((uint32_t)DMAMUX1_ChannelBase + (hdma->ChannelIndex >> 2) * ((uint32_t)DMAMUX1_Channel1 - (uint32_t)DMAMUX1_Channel0)); + hdma->DMAmuxChannelStatus = DMAMUX1_ChannelStatus; + hdma->DMAmuxChannelStatusMask = 1U << channel_number; +} + +/** + * @brief Updates the DMA handle with the DMAMUX request generator params + * @param hdma: pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA Stream. + * @retval None + */ + +static void DMA_CalcDMAMUXRequestGenBaseAndMask(DMA_HandleTypeDef *hdma) +{ + uint32_t request = hdma->Init.Request & DMAMUX_CxCR_DMAREQ_ID; + + /* DMA Channels are connected to DMAMUX1 request generator blocks*/ + hdma->DMAmuxRequestGen = (DMAMUX_RequestGen_TypeDef *)((uint32_t)(((uint32_t)DMAMUX1_RequestGenerator0) + ((request - 1U) * 4U))); + + hdma->DMAmuxRequestGenStatus = DMAMUX1_RequestGenStatus; + + hdma->DMAmuxRequestGenStatusMask = 1U << (request - 1U); +} + +#endif /* DMAMUX1 */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* HAL_DMA_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_dma_ex.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_dma_ex.c new file mode 100644 index 0000000..50b09d5 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_dma_ex.c @@ -0,0 +1,319 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_dma_ex.c + * @author MCD Application Team + * @brief DMA Extension HAL module driver + * This file provides firmware functions to manage the following + * functionalities of the DMA Extension peripheral: + * + Extended features functions + * + @verbatim + ============================================================================== + ##### How to use this driver ##### + ============================================================================== + [..] + The DMA Extension HAL driver can be used as follows: + + (+) Configure the DMA_MUX Synchronization Block using HAL_DMAEx_ConfigMuxSync function. + (+) Configure the DMA_MUX Request Generator Block using HAL_DMAEx_ConfigMuxRequestGenerator function. + Functions HAL_DMAEx_EnableMuxRequestGenerator and HAL_DMAEx_DisableMuxRequestGenerator can then be used + to respectively enable/disable the request generator. + + (+) To handle the DMAMUX Interrupts, the function HAL_DMAEx_MUX_IRQHandler should be called from + the DMAMUX IRQ handler i.e DMAMUX1_OVR_IRQHandler. + As only one interrupt line is available for all DMAMUX channels and request generators , HAL_DMAEx_MUX_IRQHandler should be + called with, as parameter, the appropriate DMA handle as many as used DMAs in the user project + (exception done if a given DMA is not using the DMAMUX SYNC block neither a request generator) + + @endverbatim + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +#if defined(DMAMUX1) + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup DMAEx DMAEx + * @brief DMA Extended HAL module driver + * @{ + */ + +#ifdef HAL_DMA_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private Constants ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + + +/** @defgroup DMAEx_Exported_Functions DMAEx Exported Functions + * @{ + */ + +/** @defgroup DMAEx_Exported_Functions_Group1 DMAEx Extended features functions + * @brief Extended features functions + * +@verbatim + =============================================================================== + ##### Extended features functions ##### + =============================================================================== + [..] This section provides functions allowing to: + + (+) Configure the DMAMUX Synchronization Block using HAL_DMAEx_ConfigMuxSync function. + (+) Configure the DMAMUX Request Generator Block using HAL_DMAEx_ConfigMuxRequestGenerator function. + Functions HAL_DMAEx_EnableMuxRequestGenerator and HAL_DMAEx_DisableMuxRequestGenerator can then be used + to respectively enable/disable the request generator. + +@endverbatim + * @{ + */ + + +/** + * @brief Configure the DMAMUX synchronization parameters for a given DMA channel (instance). + * @param hdma: pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA channel. + * @param pSyncConfig : pointer to HAL_DMA_MuxSyncConfigTypeDef : contains the DMAMUX synchronization parameters + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMAEx_ConfigMuxSync(DMA_HandleTypeDef *hdma, HAL_DMA_MuxSyncConfigTypeDef *pSyncConfig) +{ + /* Check the parameters */ + assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance)); + + assert_param(IS_DMAMUX_SYNC_SIGNAL_ID(pSyncConfig->SyncSignalID)); + + assert_param(IS_DMAMUX_SYNC_POLARITY(pSyncConfig-> SyncPolarity)); + assert_param(IS_DMAMUX_SYNC_STATE(pSyncConfig->SyncEnable)); + assert_param(IS_DMAMUX_SYNC_EVENT(pSyncConfig->EventEnable)); + assert_param(IS_DMAMUX_SYNC_REQUEST_NUMBER(pSyncConfig->RequestNumber)); + + /*Check if the DMA state is ready */ + if(hdma->State == HAL_DMA_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hdma); + + /* Set the new synchronization parameters (and keep the request ID filled during the Init)*/ + MODIFY_REG( hdma->DMAmuxChannel->CCR, \ + (~DMAMUX_CxCR_DMAREQ_ID) , \ + ((pSyncConfig->SyncSignalID) << DMAMUX_CxCR_SYNC_ID_Pos) | ((pSyncConfig->RequestNumber - 1U) << DMAMUX_CxCR_NBREQ_Pos) | \ + pSyncConfig->SyncPolarity | (pSyncConfig->SyncEnable << DMAMUX_CxCR_SE_Pos) | \ + (pSyncConfig->EventEnable << DMAMUX_CxCR_EGE_Pos)); + + /* Process UnLocked */ + __HAL_UNLOCK(hdma); + + return HAL_OK; + } + else + { + /*DMA State not Ready*/ + return HAL_ERROR; + } +} + +/** + * @brief Configure the DMAMUX request generator block used by the given DMA channel (instance). + * @param hdma: pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA channel. + * @param pRequestGeneratorConfig : pointer to HAL_DMA_MuxRequestGeneratorConfigTypeDef : + * contains the request generator parameters. + * + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMAEx_ConfigMuxRequestGenerator (DMA_HandleTypeDef *hdma, HAL_DMA_MuxRequestGeneratorConfigTypeDef *pRequestGeneratorConfig) +{ + /* Check the parameters */ + assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance)); + + assert_param(IS_DMAMUX_REQUEST_GEN_SIGNAL_ID(pRequestGeneratorConfig->SignalID)); + + assert_param(IS_DMAMUX_REQUEST_GEN_POLARITY(pRequestGeneratorConfig->Polarity)); + assert_param(IS_DMAMUX_REQUEST_GEN_REQUEST_NUMBER(pRequestGeneratorConfig->RequestNumber)); + + /* check if the DMA state is ready + and DMA is using a DMAMUX request generator block + */ + if((hdma->State == HAL_DMA_STATE_READY) && (hdma->DMAmuxRequestGen != 0U)) + { + /* Process Locked */ + __HAL_LOCK(hdma); + + /* Set the request generator new parameters*/ + hdma->DMAmuxRequestGen->RGCR = pRequestGeneratorConfig->SignalID | \ + ((pRequestGeneratorConfig->RequestNumber - 1U) << POSITION_VAL(DMAMUX_RGxCR_GNBREQ))| \ + pRequestGeneratorConfig->Polarity; + /* Process UnLocked */ + __HAL_UNLOCK(hdma); + + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Enable the DMAMUX request generator block used by the given DMA channel (instance). + * @param hdma: pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA channel. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMAEx_EnableMuxRequestGenerator (DMA_HandleTypeDef *hdma) +{ + /* Check the parameters */ + assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance)); + + /* check if the DMA state is ready + and DMA is using a DMAMUX request generator block + */ + if((hdma->State != HAL_DMA_STATE_RESET) && (hdma->DMAmuxRequestGen != 0)) + { + + /* Enable the request generator*/ + hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_GE; + + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Disable the DMAMUX request generator block used by the given DMA channel (instance). + * @param hdma: pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA channel. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMAEx_DisableMuxRequestGenerator (DMA_HandleTypeDef *hdma) +{ + /* Check the parameters */ + assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance)); + + /* check if the DMA state is ready + and DMA is using a DMAMUX request generator block + */ + if((hdma->State != HAL_DMA_STATE_RESET) && (hdma->DMAmuxRequestGen != 0)) + { + + /* Disable the request generator*/ + hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_GE; + + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Handles DMAMUX interrupt request. + * @param hdma: pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA channel. + * @retval None + */ +void HAL_DMAEx_MUX_IRQHandler(DMA_HandleTypeDef *hdma) +{ + /* Check for DMAMUX Synchronization overrun */ + if((hdma->DMAmuxChannelStatus->CSR & hdma->DMAmuxChannelStatusMask) != 0U) + { + /* Disable the synchro overrun interrupt */ + hdma->DMAmuxChannel->CCR &= ~DMAMUX_CxCR_SOIE; + + /* Clear the DMAMUX synchro overrun flag */ + hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask; + + /* Update error code */ + hdma->ErrorCode |= HAL_DMA_ERROR_SYNC; + + if(hdma->XferErrorCallback != NULL) + { + /* Transfer error callback */ + hdma->XferErrorCallback(hdma); + } + } + + if(hdma->DMAmuxRequestGen != 0) + { + /* if using a DMAMUX request generator block Check for DMAMUX request generator overrun */ + if((hdma->DMAmuxRequestGenStatus->RGSR & hdma->DMAmuxRequestGenStatusMask) != 0U) + { + /* Disable the request gen overrun interrupt */ + hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_OIE; + + /* Clear the DMAMUX request generator overrun flag */ + hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask; + + /* Update error code */ + hdma->ErrorCode |= HAL_DMA_ERROR_REQGEN; + + if(hdma->XferErrorCallback != NULL) + { + /* Transfer error callback */ + hdma->XferErrorCallback(hdma); + } + } + } +} + +/** + * @} + */ + +/** + * @} + */ + +#endif /* HAL_DMA_MODULE_ENABLED */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* DMAMUX1 */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash.c new file mode 100644 index 0000000..0c035a6 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash.c @@ -0,0 +1,835 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_flash.c + * @author MCD Application Team + * @brief FLASH HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the internal FLASH memory: + * + Program operations functions + * + Memory Control functions + * + Peripheral Errors functions + * + @verbatim + ============================================================================== + ##### FLASH peripheral features ##### + ============================================================================== + + [..] The Flash memory interface manages CPU AHB I-Code and D-Code accesses + to the Flash memory. It implements the erase and program Flash memory operations + and the read and write protection mechanisms. + + [..] The Flash memory interface accelerates code execution with a system of instruction + prefetch and cache lines. + + [..] The FLASH main features are: + (+) Flash memory read operations + (+) Flash memory program/erase operations + (+) Read / write protections + (+) Option bytes programming + (+) Prefetch on I-Code + (+) 32 cache lines of 4*64 bits on I-Code + (+) 8 cache lines of 4*64 bits on D-Code + (+) Error code correction (ECC) : Data in flash are 72-bits word + (8 bits added per double word) + + + ##### How to use this driver ##### + ============================================================================== + [..] + This driver provides functions and macros to configure and program the FLASH + memory of all STM32L4xx devices. + + (#) Flash Memory IO Programming functions: + (++) Lock and Unlock the FLASH interface using HAL_FLASH_Unlock() and + HAL_FLASH_Lock() functions + (++) Program functions: double word and fast program (full row programming) + (++) There Two modes of programming : + (+++) Polling mode using HAL_FLASH_Program() function + (+++) Interrupt mode using HAL_FLASH_Program_IT() function + + (#) Interrupts and flags management functions : + (++) Handle FLASH interrupts by calling HAL_FLASH_IRQHandler() + (++) Callback functions are called when the flash operations are finished : + HAL_FLASH_EndOfOperationCallback() when everything is ok, otherwise + HAL_FLASH_OperationErrorCallback() + (++) Get error flag status by calling HAL_GetError() + + (#) Option bytes management functions : + (++) Lock and Unlock the option bytes using HAL_FLASH_OB_Unlock() and + HAL_FLASH_OB_Lock() functions + (++) Launch the reload of the option bytes using HAL_FLASH_Launch() function. + In this case, a reset is generated + + [..] + In addition to these functions, this driver includes a set of macros allowing + to handle the following operations: + (+) Set the latency + (+) Enable/Disable the prefetch buffer + (+) Enable/Disable the Instruction cache and the Data cache + (+) Reset the Instruction cache and the Data cache + (+) Enable/Disable the Flash power-down during low-power run and sleep modes + (+) Enable/Disable the Flash interrupts + (+) Monitor the Flash flags status + + @endverbatim + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup FLASH FLASH + * @brief FLASH HAL module driver + * @{ + */ + +#ifdef HAL_FLASH_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private defines -----------------------------------------------------------*/ +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define FLASH_NB_DOUBLE_WORDS_IN_ROW 64 +#else +#define FLASH_NB_DOUBLE_WORDS_IN_ROW 32 +#endif +/* Private macros ------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/** @defgroup FLASH_Private_Variables FLASH Private Variables + * @{ + */ +/** + * @brief Variable used for Program/Erase sectors under interruption + */ +FLASH_ProcessTypeDef pFlash; +/** + * @} + */ + +/* Private function prototypes -----------------------------------------------*/ +/** @defgroup FLASH_Private_Functions FLASH Private Functions + * @{ + */ +HAL_StatusTypeDef FLASH_WaitForLastOperation(uint32_t Timeout); +extern void FLASH_PageErase(uint32_t Page, uint32_t Banks); +extern void FLASH_FlushCaches(void); +static void FLASH_SetErrorCode(void); +static void FLASH_Program_DoubleWord(uint32_t Address, uint64_t Data); +static void FLASH_Program_Fast(uint32_t Address, uint32_t DataAddress); +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup FLASH_Exported_Functions FLASH Exported Functions + * @{ + */ + +/** @defgroup FLASH_Exported_Functions_Group1 Programming operation functions + * @brief Programming operation functions + * +@verbatim + =============================================================================== + ##### Programming operation functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to manage the FLASH + program operations. + +@endverbatim + * @{ + */ + +/** + * @brief Program double word or fast program of a row at a specified address. + * @param TypeProgram: Indicate the way to program at a specified address. + * This parameter can be a value of @ref FLASH_Type_Program + * @param Address: specifies the address to be programmed. + * @param Data: specifies the data to be programmed + * This parameter is the data for the double word program and the address where + * are stored the data for the row fast program + * + * @retval HAL_StatusTypeDef HAL Status + */ +HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data) +{ + HAL_StatusTypeDef status = HAL_ERROR; + uint32_t prog_bit = 0; + + /* Process Locked */ + __HAL_LOCK(&pFlash); + + /* Check the parameters */ + assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram)); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); + + if(status == HAL_OK) + { + pFlash.ErrorCode = HAL_FLASH_ERROR_NONE; + + /* Deactivate the data cache if they are activated to avoid data misbehavior */ + if(READ_BIT(FLASH->ACR, FLASH_ACR_DCEN) != RESET) + { + /* Disable data cache */ + __HAL_FLASH_DATA_CACHE_DISABLE(); + pFlash.CacheToReactivate = FLASH_CACHE_DCACHE_ENABLED; + } + else + { + pFlash.CacheToReactivate = FLASH_CACHE_DISABLED; + } + + if(TypeProgram == FLASH_TYPEPROGRAM_DOUBLEWORD) + { + /* Program double-word (64-bit) at a specified address */ + FLASH_Program_DoubleWord(Address, Data); + prog_bit = FLASH_CR_PG; + } + else if((TypeProgram == FLASH_TYPEPROGRAM_FAST) || (TypeProgram == FLASH_TYPEPROGRAM_FAST_AND_LAST)) + { + /* Fast program a 32 row double-word (64-bit) at a specified address */ + FLASH_Program_Fast(Address, (uint32_t)Data); + + /* If it is the last row, the bit will be cleared at the end of the operation */ + if(TypeProgram == FLASH_TYPEPROGRAM_FAST_AND_LAST) + { + prog_bit = FLASH_CR_FSTPG; + } + } + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); + + /* If the program operation is completed, disable the PG or FSTPG Bit */ + if (prog_bit != 0) + { + CLEAR_BIT(FLASH->CR, prog_bit); + } + + /* Flush the caches to be sure of the data consistency */ + FLASH_FlushCaches(); + } + + /* Process Unlocked */ + __HAL_UNLOCK(&pFlash); + + return status; +} + +/** + * @brief Program double word or fast program of a row at a specified address with interrupt enabled. + * @param TypeProgram: Indicate the way to program at a specified address. + * This parameter can be a value of @ref FLASH_Type_Program + * @param Address: specifies the address to be programmed. + * @param Data: specifies the data to be programmed + * This parameter is the data for the double word program and the address where + * are stored the data for the row fast program + * + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_FLASH_Program_IT(uint32_t TypeProgram, uint32_t Address, uint64_t Data) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check the parameters */ + assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram)); + + /* Process Locked */ + __HAL_LOCK(&pFlash); + + pFlash.ErrorCode = HAL_FLASH_ERROR_NONE; + + /* Deactivate the data cache if they are activated to avoid data misbehavior */ + if(READ_BIT(FLASH->ACR, FLASH_ACR_DCEN) != RESET) + { + /* Disable data cache */ + __HAL_FLASH_DATA_CACHE_DISABLE(); + pFlash.CacheToReactivate = FLASH_CACHE_DCACHE_ENABLED; + } + else + { + pFlash.CacheToReactivate = FLASH_CACHE_DISABLED; + } + + /* Set internal variables used by the IRQ handler */ + if(TypeProgram == FLASH_TYPEPROGRAM_FAST_AND_LAST) + { + pFlash.ProcedureOnGoing = FLASH_PROC_PROGRAM_LAST; + } + else + { + pFlash.ProcedureOnGoing = FLASH_PROC_PROGRAM; + } + pFlash.Address = Address; + + /* Enable End of Operation and Error interrupts */ + __HAL_FLASH_ENABLE_IT(FLASH_IT_EOP | FLASH_IT_OPERR); + + if(TypeProgram == FLASH_TYPEPROGRAM_DOUBLEWORD) + { + /* Program double-word (64-bit) at a specified address */ + FLASH_Program_DoubleWord(Address, Data); + } + else if((TypeProgram == FLASH_TYPEPROGRAM_FAST) || (TypeProgram == FLASH_TYPEPROGRAM_FAST_AND_LAST)) + { + /* Fast program a 32 row double-word (64-bit) at a specified address */ + FLASH_Program_Fast(Address, (uint32_t)Data); + } + + return status; +} + +/** + * @brief Handle FLASH interrupt request. + * @retval None + */ +void HAL_FLASH_IRQHandler(void) +{ + uint32_t tmp_page; + + /* If the operation is completed, disable the PG, PNB, MER1, MER2 and PER Bit */ + CLEAR_BIT(FLASH->CR, (FLASH_CR_PG | FLASH_CR_MER1 | FLASH_CR_PER | FLASH_CR_PNB)); +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + CLEAR_BIT(FLASH->CR, FLASH_CR_MER2); +#endif + + /* Disable the FSTPG Bit only if it is the last row programmed */ + if(pFlash.ProcedureOnGoing == FLASH_PROC_PROGRAM_LAST) + { + CLEAR_BIT(FLASH->CR, FLASH_CR_FSTPG); + } + + /* Check FLASH operation error flags */ + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) || +#if defined (STM32L431xx) || defined (STM32L432xx) || defined (STM32L433xx) || defined (STM32L442xx) || defined (STM32L443xx) || \ + defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PEMPTY))) +#else + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD))) +#endif + { + /*Save the error code*/ + FLASH_SetErrorCode(); + + /* Flush the caches to be sure of the data consistency */ + FLASH_FlushCaches() ; + + /* FLASH error interrupt user callback */ + if(pFlash.ProcedureOnGoing == FLASH_PROC_PAGE_ERASE) + { + HAL_FLASH_OperationErrorCallback(pFlash.Page); + } + else if(pFlash.ProcedureOnGoing == FLASH_PROC_MASS_ERASE) + { + HAL_FLASH_OperationErrorCallback(pFlash.Bank); + } + else if((pFlash.ProcedureOnGoing == FLASH_PROC_PROGRAM) || + (pFlash.ProcedureOnGoing == FLASH_PROC_PROGRAM_LAST)) + { + HAL_FLASH_OperationErrorCallback(pFlash.Address); + } + + /*Stop the procedure ongoing*/ + pFlash.ProcedureOnGoing = FLASH_PROC_NONE; + } + + /* Check FLASH End of Operation flag */ + if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP)) + { + /* Clear FLASH End of Operation pending bit */ + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP); + + if(pFlash.ProcedureOnGoing == FLASH_PROC_PAGE_ERASE) + { + /* Nb of pages to erased can be decreased */ + pFlash.NbPagesToErase--; + + /* Check if there are still pages to erase*/ + if(pFlash.NbPagesToErase != 0) + { + /* Indicate user which page has been erased*/ + HAL_FLASH_EndOfOperationCallback(pFlash.Page); + + /* Increment page number */ + pFlash.Page++; + tmp_page = pFlash.Page; + FLASH_PageErase(tmp_page, pFlash.Bank); + } + else + { + /* No more pages to Erase */ + /* Reset Address and stop Erase pages procedure */ + pFlash.Page = 0xFFFFFFFF; + pFlash.ProcedureOnGoing = FLASH_PROC_NONE; + + /* Flush the caches to be sure of the data consistency */ + FLASH_FlushCaches() ; + + /* FLASH EOP interrupt user callback */ + HAL_FLASH_EndOfOperationCallback(pFlash.Page); + } + } + else + { + /* Flush the caches to be sure of the data consistency */ + FLASH_FlushCaches() ; + + if(pFlash.ProcedureOnGoing == FLASH_PROC_MASS_ERASE) + { + /* MassErase ended. Return the selected bank */ + /* FLASH EOP interrupt user callback */ + HAL_FLASH_EndOfOperationCallback(pFlash.Bank); + } + else if((pFlash.ProcedureOnGoing == FLASH_PROC_PROGRAM) || + (pFlash.ProcedureOnGoing == FLASH_PROC_PROGRAM_LAST)) + { + /* Program ended. Return the selected address */ + /* FLASH EOP interrupt user callback */ + HAL_FLASH_EndOfOperationCallback(pFlash.Address); + } + + /*Clear the procedure ongoing*/ + pFlash.ProcedureOnGoing = FLASH_PROC_NONE; + } + } + + if(pFlash.ProcedureOnGoing == FLASH_PROC_NONE) + { + /* Disable End of Operation and Error interrupts */ + __HAL_FLASH_DISABLE_IT(FLASH_IT_EOP | FLASH_IT_OPERR); + + /* Process Unlocked */ + __HAL_UNLOCK(&pFlash); + } +} + +/** + * @brief FLASH end of operation interrupt callback. + * @param ReturnValue: The value saved in this parameter depends on the ongoing procedure + * Mass Erase: Bank number which has been requested to erase + * Page Erase: Page which has been erased + * (if 0xFFFFFFFF, it means that all the selected pages have been erased) + * Program: Address which was selected for data program + * @retval None + */ +__weak void HAL_FLASH_EndOfOperationCallback(uint32_t ReturnValue) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(ReturnValue); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_FLASH_EndOfOperationCallback could be implemented in the user file + */ +} + +/** + * @brief FLASH operation error interrupt callback. + * @param ReturnValue: The value saved in this parameter depends on the ongoing procedure + * Mass Erase: Bank number which has been requested to erase + * Page Erase: Page number which returned an error + * Program: Address which was selected for data program + * @retval None + */ +__weak void HAL_FLASH_OperationErrorCallback(uint32_t ReturnValue) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(ReturnValue); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_FLASH_OperationErrorCallback could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup FLASH_Exported_Functions_Group2 Peripheral Control functions + * @brief Management functions + * +@verbatim + =============================================================================== + ##### Peripheral Control functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to control the FLASH + memory operations. + +@endverbatim + * @{ + */ + +/** + * @brief Unlock the FLASH control register access. + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_FLASH_Unlock(void) +{ + HAL_StatusTypeDef status = HAL_OK; + + if(READ_BIT(FLASH->CR, FLASH_CR_LOCK) != RESET) + { + /* Authorize the FLASH Registers access */ + WRITE_REG(FLASH->KEYR, FLASH_KEY1); + WRITE_REG(FLASH->KEYR, FLASH_KEY2); + + /* Verify Flash is unlocked */ + if(READ_BIT(FLASH->CR, FLASH_CR_LOCK) != RESET) + { + status = HAL_ERROR; + } + } + + return status; +} + +/** + * @brief Lock the FLASH control register access. + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_FLASH_Lock(void) +{ + /* Set the LOCK Bit to lock the FLASH Registers access */ + SET_BIT(FLASH->CR, FLASH_CR_LOCK); + + return HAL_OK; +} + +/** + * @brief Unlock the FLASH Option Bytes Registers access. + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_FLASH_OB_Unlock(void) +{ + if(READ_BIT(FLASH->CR, FLASH_CR_OPTLOCK) != RESET) + { + /* Authorizes the Option Byte register programming */ + WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY1); + WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY2); + } + else + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief Lock the FLASH Option Bytes Registers access. + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_FLASH_OB_Lock(void) +{ + /* Set the OPTLOCK Bit to lock the FLASH Option Byte Registers access */ + SET_BIT(FLASH->CR, FLASH_CR_OPTLOCK); + + return HAL_OK; +} + +/** + * @brief Launch the option byte loading. + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_FLASH_OB_Launch(void) +{ + /* Set the bit to force the option byte reloading */ + SET_BIT(FLASH->CR, FLASH_CR_OBL_LAUNCH); + + /* Wait for last operation to be completed */ + return(FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE)); +} + +/** + * @} + */ + +/** @defgroup FLASH_Exported_Functions_Group3 Peripheral State and Errors functions + * @brief Peripheral Errors functions + * +@verbatim + =============================================================================== + ##### Peripheral Errors functions ##### + =============================================================================== + [..] + This subsection permits to get in run-time Errors of the FLASH peripheral. + +@endverbatim + * @{ + */ + +/** + * @brief Get the specific FLASH error flag. + * @retval FLASH_ErrorCode: The returned value can be: + * @arg HAL_FLASH_ERROR_RD: FLASH Read Protection error flag (PCROP) + * @arg HAL_FLASH_ERROR_PGS: FLASH Programming Sequence error flag + * @arg HAL_FLASH_ERROR_PGP: FLASH Programming Parallelism error flag + * @arg HAL_FLASH_ERROR_PGA: FLASH Programming Alignment error flag + * @arg HAL_FLASH_ERROR_WRP: FLASH Write protected error flag + * @arg HAL_FLASH_ERROR_OPERATION: FLASH operation Error flag + * @arg HAL_FLASH_ERROR_NONE: No error set + * @arg HAL_FLASH_ERROR_OP: FLASH Operation error + * @arg HAL_FLASH_ERROR_PROG: FLASH Programming error + * @arg HAL_FLASH_ERROR_WRP: FLASH Write protection error + * @arg HAL_FLASH_ERROR_PGA: FLASH Programming alignment error + * @arg HAL_FLASH_ERROR_SIZ: FLASH Size error + * @arg HAL_FLASH_ERROR_PGS: FLASH Programming sequence error + * @arg HAL_FLASH_ERROR_MIS: FLASH Fast programming data miss error + * @arg HAL_FLASH_ERROR_FAST: FLASH Fast programming error + * @arg HAL_FLASH_ERROR_RD: FLASH PCROP read error + * @arg HAL_FLASH_ERROR_OPTV: FLASH Option validity error + * @arg FLASH_FLAG_PEMPTY : FLASH Boot from not programmed flash (apply only for STM32L43x/STM32L44x devices) + * @arg HAL_FLASH_ERROR_ECCD: FLASH two ECC errors have been detected + */ +uint32_t HAL_FLASH_GetError(void) +{ + return pFlash.ErrorCode; +} + +/** + * @} + */ + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ + +/** @addtogroup FLASH_Private_Functions + * @{ + */ + +/** + * @brief Wait for a FLASH operation to complete. + * @param Timeout: maximum flash operation timeout + * @retval HAL_StatusTypeDef HAL Status + */ +HAL_StatusTypeDef FLASH_WaitForLastOperation(uint32_t Timeout) +{ + /* Wait for the FLASH operation to complete by polling on BUSY flag to be reset. + Even if the FLASH operation fails, the BUSY flag will be reset and an error + flag will be set */ + + uint32_t tickstart = HAL_GetTick(); + + while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) + { + if(Timeout != HAL_MAX_DELAY) + { + if((HAL_GetTick() - tickstart) >= Timeout) + { + return HAL_TIMEOUT; + } + } + } + + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) || +#if defined (STM32L431xx) || defined (STM32L432xx) || defined (STM32L433xx) || defined (STM32L442xx) || defined (STM32L443xx) || \ + defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PEMPTY))) +#else + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD))) +#endif + { + /*Save the error code*/ + FLASH_SetErrorCode(); + + return HAL_ERROR; + } + + /* Check FLASH End of Operation flag */ + if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP)) + { + /* Clear FLASH End of Operation pending bit */ + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP); + } + + /* If there is an error flag set */ + return HAL_OK; +} + +/** + * @brief Set the specific FLASH error flag. + * @retval None + */ +static void FLASH_SetErrorCode(void) +{ + if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) + { + pFlash.ErrorCode |= HAL_FLASH_ERROR_OP; + } + + if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) + { + pFlash.ErrorCode |= HAL_FLASH_ERROR_PROG; + } + + if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) + { + pFlash.ErrorCode |= HAL_FLASH_ERROR_WRP; + } + + if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) + { + pFlash.ErrorCode |= HAL_FLASH_ERROR_PGA; + } + + if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) + { + pFlash.ErrorCode |= HAL_FLASH_ERROR_SIZ; + } + + if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR)) + { + pFlash.ErrorCode |= HAL_FLASH_ERROR_PGS; + } + + if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) + { + pFlash.ErrorCode |= HAL_FLASH_ERROR_MIS; + } + + if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) + { + pFlash.ErrorCode |= HAL_FLASH_ERROR_FAST; + } + + if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR)) + { + pFlash.ErrorCode |= HAL_FLASH_ERROR_RD; + } + + if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) + { + pFlash.ErrorCode |= HAL_FLASH_ERROR_OPTV; + } + + if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD)) + { + pFlash.ErrorCode |= HAL_FLASH_ERROR_ECCD; + } + +#if defined (STM32L431xx) || defined (STM32L432xx) || defined (STM32L433xx) || defined (STM32L442xx) || defined (STM32L443xx) || \ + defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_PEMPTY)) + { + pFlash.ErrorCode |= HAL_FLASH_ERROR_PEMPTY; + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_PEMPTY); + } +#endif + + /* Clear error programming flags */ + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS); +} + +/** + * @brief Program double-word (64-bit) at a specified address. + * @param Address: specifies the address to be programmed. + * @param Data: specifies the data to be programmed. + * @retval None + */ +static void FLASH_Program_DoubleWord(uint32_t Address, uint64_t Data) +{ + /* Check the parameters */ + assert_param(IS_FLASH_PROGRAM_ADDRESS(Address)); + + /* Set PG bit */ + SET_BIT(FLASH->CR, FLASH_CR_PG); + + /* Program the double word */ + *(__IO uint32_t*)Address = (uint32_t)Data; + *(__IO uint32_t*)(Address+4) = (uint32_t)(Data >> 32); +} + +/** + * @brief Fast program a row double-word (64-bit) at a specified address. + * @param Address: specifies the address to be programmed. + * @param DataAddress: specifies the address where the data are stored. + * @retval None + */ +static void FLASH_Program_Fast(uint32_t Address, uint32_t DataAddress) +{ + uint8_t row_index = (2*FLASH_NB_DOUBLE_WORDS_IN_ROW); + __IO uint32_t *dest_addr = (__IO uint32_t*)Address; + __IO uint32_t *src_addr = (__IO uint32_t*)DataAddress; + + /* Check the parameters */ + assert_param(IS_FLASH_MAIN_MEM_ADDRESS(Address)); + + /* Set FSTPG bit */ + SET_BIT(FLASH->CR, FLASH_CR_FSTPG); + + /* Disable interrupts to avoid any interruption during the loop */ + __disable_irq(); + + /* Program the double word of the row */ + do + { + *dest_addr++ = *src_addr++; + } while (--row_index != 0); + + /* Re-enable the interrupts */ + __enable_irq(); +} + +/** + * @} + */ + +#endif /* HAL_FLASH_MODULE_ENABLED */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash_ex.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash_ex.c new file mode 100644 index 0000000..8f09359 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash_ex.c @@ -0,0 +1,1305 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_flash_ex.c + * @author MCD Application Team + * @brief Extended FLASH HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the FLASH extended peripheral: + * + Extended programming operations functions + * + @verbatim + ============================================================================== + ##### Flash Extended features ##### + ============================================================================== + + [..] Comparing to other previous devices, the FLASH interface for STM32L4xx + devices contains the following additional features + + (+) Capacity up to 2 Mbyte with dual bank architecture supporting read-while-write + capability (RWW) + (+) Dual bank memory organization + (+) PCROP protection for all banks + + ##### How to use this driver ##### + ============================================================================== + [..] This driver provides functions to configure and program the FLASH memory + of all STM32L4xx devices. It includes + (#) Flash Memory Erase functions: + (++) Lock and Unlock the FLASH interface using HAL_FLASH_Unlock() and + HAL_FLASH_Lock() functions + (++) Erase function: Erase page, erase all sectors + (++) There are two modes of erase : + (+++) Polling Mode using HAL_FLASHEx_Erase() + (+++) Interrupt Mode using HAL_FLASHEx_Erase_IT() + + (#) Option Bytes Programming function: Use HAL_FLASHEx_OBProgram() to : + (++) Set/Reset the write protection + (++) Set the Read protection Level + (++) Program the user Option Bytes + (++) Configure the PCROP protection + + (#) Get Option Bytes Configuration function: Use HAL_FLASHEx_OBGetConfig() to : + (++) Get the value of a write protection area + (++) Know if the read protection is activated + (++) Get the value of the user Option Bytes + (++) Get the value of a PCROP area + + @endverbatim + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup FLASHEx FLASHEx + * @brief FLASH Extended HAL module driver + * @{ + */ + +#ifdef HAL_FLASH_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/** @defgroup FLASHEx_Private_Variables FLASHEx Private Variables + * @{ + */ +extern FLASH_ProcessTypeDef pFlash; +/** + * @} + */ + +/* Private function prototypes -----------------------------------------------*/ +/** @defgroup FLASHEx_Private_Functions FLASHEx Private Functions + * @{ + */ +extern HAL_StatusTypeDef FLASH_WaitForLastOperation(uint32_t Timeout); +void FLASH_PageErase(uint32_t Page, uint32_t Banks); +static void FLASH_MassErase(uint32_t Banks); +void FLASH_FlushCaches(void); +static HAL_StatusTypeDef FLASH_OB_WRPConfig(uint32_t WRPArea, uint32_t WRPStartOffset, uint32_t WRDPEndOffset); +static HAL_StatusTypeDef FLASH_OB_RDPConfig(uint32_t RDPLevel); +static HAL_StatusTypeDef FLASH_OB_UserConfig(uint32_t UserType, uint32_t UserConfig); +static HAL_StatusTypeDef FLASH_OB_PCROPConfig(uint32_t PCROPConfig, uint32_t PCROPStartAddr, uint32_t PCROPEndAddr); +static void FLASH_OB_GetWRP(uint32_t WRPArea, uint32_t * WRPStartOffset, uint32_t * WRDPEndOffset); +static uint32_t FLASH_OB_GetRDP(void); +static uint32_t FLASH_OB_GetUser(void); +static void FLASH_OB_GetPCROP(uint32_t * PCROPConfig, uint32_t * PCROPStartAddr, uint32_t * PCROPEndAddr); +/** + * @} + */ + +/* Exported functions -------------------------------------------------------*/ +/** @defgroup FLASHEx_Exported_Functions FLASHEx Exported Functions + * @{ + */ + +/** @defgroup FLASHEx_Exported_Functions_Group1 Extended IO operation functions + * @brief Extended IO operation functions + * +@verbatim + =============================================================================== + ##### Extended programming operation functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to manage the Extended FLASH + programming operations Operations. + +@endverbatim + * @{ + */ +/** + * @brief Perform a mass erase or erase the specified FLASH memory pages. + * @param[in] pEraseInit: pointer to an FLASH_EraseInitTypeDef structure that + * contains the configuration information for the erasing. + * + * @param[out] PageError : pointer to variable that contains the configuration + * information on faulty page in case of error (0xFFFFFFFF means that all + * the pages have been correctly erased) + * + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *PageError) +{ + HAL_StatusTypeDef status = HAL_ERROR; + uint32_t page_index = 0; + + /* Process Locked */ + __HAL_LOCK(&pFlash); + + /* Check the parameters */ + assert_param(IS_FLASH_TYPEERASE(pEraseInit->TypeErase)); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); + + if (status == HAL_OK) + { + pFlash.ErrorCode = HAL_FLASH_ERROR_NONE; + + /* Deactivate the cache if they are activated to avoid data misbehavior */ + if(READ_BIT(FLASH->ACR, FLASH_ACR_ICEN) != RESET) + { + /* Disable instruction cache */ + __HAL_FLASH_INSTRUCTION_CACHE_DISABLE(); + + if(READ_BIT(FLASH->ACR, FLASH_ACR_DCEN) != RESET) + { + /* Disable data cache */ + __HAL_FLASH_DATA_CACHE_DISABLE(); + pFlash.CacheToReactivate = FLASH_CACHE_ICACHE_DCACHE_ENABLED; + } + else + { + pFlash.CacheToReactivate = FLASH_CACHE_ICACHE_ENABLED; + } + } + else if(READ_BIT(FLASH->ACR, FLASH_ACR_DCEN) != RESET) + { + /* Disable data cache */ + __HAL_FLASH_DATA_CACHE_DISABLE(); + pFlash.CacheToReactivate = FLASH_CACHE_DCACHE_ENABLED; + } + else + { + pFlash.CacheToReactivate = FLASH_CACHE_DISABLED; + } + + if (pEraseInit->TypeErase == FLASH_TYPEERASE_MASSERASE) + { + /* Mass erase to be done */ + FLASH_MassErase(pEraseInit->Banks); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); + +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + /* If the erase operation is completed, disable the MER1 and MER2 Bits */ + CLEAR_BIT(FLASH->CR, (FLASH_CR_MER1 | FLASH_CR_MER2)); +#else + /* If the erase operation is completed, disable the MER1 Bit */ + CLEAR_BIT(FLASH->CR, (FLASH_CR_MER1)); +#endif + } + else + { + /*Initialization of PageError variable*/ + *PageError = 0xFFFFFFFF; + + for(page_index = pEraseInit->Page; page_index < (pEraseInit->Page + pEraseInit->NbPages); page_index++) + { + FLASH_PageErase(page_index, pEraseInit->Banks); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); + + /* If the erase operation is completed, disable the PER Bit */ + CLEAR_BIT(FLASH->CR, (FLASH_CR_PER | FLASH_CR_PNB)); + + if (status != HAL_OK) + { + /* In case of error, stop erase procedure and return the faulty address */ + *PageError = page_index; + break; + } + } + } + + /* Flush the caches to be sure of the data consistency */ + FLASH_FlushCaches(); + } + + /* Process Unlocked */ + __HAL_UNLOCK(&pFlash); + + return status; +} + +/** + * @brief Perform a mass erase or erase the specified FLASH memory pages with interrupt enabled. + * @param pEraseInit: pointer to an FLASH_EraseInitTypeDef structure that + * contains the configuration information for the erasing. + * + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_FLASHEx_Erase_IT(FLASH_EraseInitTypeDef *pEraseInit) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process Locked */ + __HAL_LOCK(&pFlash); + + /* Check the parameters */ + assert_param(IS_FLASH_TYPEERASE(pEraseInit->TypeErase)); + + pFlash.ErrorCode = HAL_FLASH_ERROR_NONE; + + /* Deactivate the cache if they are activated to avoid data misbehavior */ + if(READ_BIT(FLASH->ACR, FLASH_ACR_ICEN) != RESET) + { + /* Disable instruction cache */ + __HAL_FLASH_INSTRUCTION_CACHE_DISABLE(); + + if(READ_BIT(FLASH->ACR, FLASH_ACR_DCEN) != RESET) + { + /* Disable data cache */ + __HAL_FLASH_DATA_CACHE_DISABLE(); + pFlash.CacheToReactivate = FLASH_CACHE_ICACHE_DCACHE_ENABLED; + } + else + { + pFlash.CacheToReactivate = FLASH_CACHE_ICACHE_ENABLED; + } + } + else if(READ_BIT(FLASH->ACR, FLASH_ACR_DCEN) != RESET) + { + /* Disable data cache */ + __HAL_FLASH_DATA_CACHE_DISABLE(); + pFlash.CacheToReactivate = FLASH_CACHE_DCACHE_ENABLED; + } + else + { + pFlash.CacheToReactivate = FLASH_CACHE_DISABLED; + } + + /* Enable End of Operation and Error interrupts */ + __HAL_FLASH_ENABLE_IT(FLASH_IT_EOP | FLASH_IT_OPERR); + + pFlash.Bank = pEraseInit->Banks; + + if (pEraseInit->TypeErase == FLASH_TYPEERASE_MASSERASE) + { + /* Mass erase to be done */ + pFlash.ProcedureOnGoing = FLASH_PROC_MASS_ERASE; + FLASH_MassErase(pEraseInit->Banks); + } + else + { + /* Erase by page to be done */ + pFlash.ProcedureOnGoing = FLASH_PROC_PAGE_ERASE; + pFlash.NbPagesToErase = pEraseInit->NbPages; + pFlash.Page = pEraseInit->Page; + + /*Erase 1st page and wait for IT */ + FLASH_PageErase(pEraseInit->Page, pEraseInit->Banks); + } + + return status; +} + +/** + * @brief Program Option bytes. + * @param pOBInit: pointer to an FLASH_OBInitStruct structure that + * contains the configuration information for the programming. + * + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_FLASHEx_OBProgram(FLASH_OBProgramInitTypeDef *pOBInit) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process Locked */ + __HAL_LOCK(&pFlash); + + /* Check the parameters */ + assert_param(IS_OPTIONBYTE(pOBInit->OptionType)); + + pFlash.ErrorCode = HAL_FLASH_ERROR_NONE; + + /* Write protection configuration */ + if((pOBInit->OptionType & OPTIONBYTE_WRP) != RESET) + { + /* Configure of Write protection on the selected area */ + if(FLASH_OB_WRPConfig(pOBInit->WRPArea, pOBInit->WRPStartOffset, pOBInit->WRPEndOffset) != HAL_OK) + { + status = HAL_ERROR; + } + + } + + /* Read protection configuration */ + if((pOBInit->OptionType & OPTIONBYTE_RDP) != RESET) + { + /* Configure the Read protection level */ + if(FLASH_OB_RDPConfig(pOBInit->RDPLevel) != HAL_OK) + { + status = HAL_ERROR; + } + } + + /* User Configuration */ + if((pOBInit->OptionType & OPTIONBYTE_USER) != RESET) + { + /* Configure the user option bytes */ + if(FLASH_OB_UserConfig(pOBInit->USERType, pOBInit->USERConfig) != HAL_OK) + { + status = HAL_ERROR; + } + } + + /* PCROP Configuration */ + if((pOBInit->OptionType & OPTIONBYTE_PCROP) != RESET) + { + if (pOBInit->PCROPStartAddr != pOBInit->PCROPEndAddr) + { + /* Configure the Proprietary code readout protection */ + if(FLASH_OB_PCROPConfig(pOBInit->PCROPConfig, pOBInit->PCROPStartAddr, pOBInit->PCROPEndAddr) != HAL_OK) + { + status = HAL_ERROR; + } + } + } + + /* Process Unlocked */ + __HAL_UNLOCK(&pFlash); + + return status; +} + +/** + * @brief Get the Option bytes configuration. + * @param pOBInit: pointer to an FLASH_OBInitStruct structure that contains the + * configuration information. + * @note The fields pOBInit->WRPArea and pOBInit->PCROPConfig should indicate + * which area is requested for the WRP and PCROP, else no information will be returned + * + * @retval None + */ +void HAL_FLASHEx_OBGetConfig(FLASH_OBProgramInitTypeDef *pOBInit) +{ + pOBInit->OptionType = (OPTIONBYTE_RDP | OPTIONBYTE_USER); + +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + if((pOBInit->WRPArea == OB_WRPAREA_BANK1_AREAA) || (pOBInit->WRPArea == OB_WRPAREA_BANK1_AREAB) || + (pOBInit->WRPArea == OB_WRPAREA_BANK2_AREAA) || (pOBInit->WRPArea == OB_WRPAREA_BANK2_AREAB)) +#else + if((pOBInit->WRPArea == OB_WRPAREA_BANK1_AREAA) || (pOBInit->WRPArea == OB_WRPAREA_BANK1_AREAB)) +#endif + { + pOBInit->OptionType |= OPTIONBYTE_WRP; + /* Get write protection on the selected area */ + FLASH_OB_GetWRP(pOBInit->WRPArea, &(pOBInit->WRPStartOffset), &(pOBInit->WRPEndOffset)); + } + + /* Get Read protection level */ + pOBInit->RDPLevel = FLASH_OB_GetRDP(); + + /* Get the user option bytes */ + pOBInit->USERConfig = FLASH_OB_GetUser(); + +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + if((pOBInit->PCROPConfig == FLASH_BANK_1) || (pOBInit->PCROPConfig == FLASH_BANK_2)) +#else + if(pOBInit->PCROPConfig == FLASH_BANK_1) +#endif + { + pOBInit->OptionType |= OPTIONBYTE_PCROP; + /* Get the Proprietary code readout protection */ + FLASH_OB_GetPCROP(&(pOBInit->PCROPConfig), &(pOBInit->PCROPStartAddr), &(pOBInit->PCROPEndAddr)); + } +} + +/** + * @} + */ + +#if defined (FLASH_CFGR_LVEN) +/** @defgroup FLASHEx_Exported_Functions_Group2 Extended specific configuration functions + * @brief Extended specific configuration functions + * +@verbatim + =============================================================================== + ##### Extended specific configuration functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to manage the Extended FLASH + specific configurations. + +@endverbatim + * @{ + */ + +/** + * @brief Configuration of the LVE pin of the Flash (managed by power controller + * or forced to low in order to use an external SMPS) + * @param ConfigLVE: Configuration of the LVE pin, + * This parameter can be one of the following values: + * @arg FLASH_LVE_PIN_CTRL: LVE FLASH pin controlled by power controller + * @arg FLASH_LVE_PIN_FORCED: LVE FLASH pin enforced to low (external SMPS used) + * + * @note Before enforcing the LVE pin to low, the SOC should be in low voltage + * range 2 and the voltage VDD12 should be higher than 1.08V and SMPS is ON. + * + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_FLASHEx_ConfigLVEPin(uint32_t ConfigLVE) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process Locked */ + __HAL_LOCK(&pFlash); + + /* Check the parameters */ + assert_param(IS_FLASH_LVE_PIN(ConfigLVE)); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); + + if (status == HAL_OK) + { + /* Check that the voltage scaling is range 2 */ + if (HAL_PWREx_GetVoltageRange() == PWR_REGULATOR_VOLTAGE_SCALE2) + { + /* Configure the LVEN bit */ + MODIFY_REG(FLASH->CFGR, FLASH_CFGR_LVEN, ConfigLVE); + + /* Check that the bit has been correctly configured */ + if (READ_BIT(FLASH->CFGR, FLASH_CFGR_LVEN) != ConfigLVE) + { + status = HAL_ERROR; + } + } + else + { + /* Not allow to force Flash LVE pin if not in voltage range 2 */ + status = HAL_ERROR; + } + } + + /* Process Unlocked */ + __HAL_UNLOCK(&pFlash); + + return status; +} + +/** + * @} + */ +#endif /* FLASH_CFGR_LVEN */ + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ + +/** @addtogroup FLASHEx_Private_Functions + * @{ + */ +/** + * @brief Mass erase of FLASH memory. + * @param Banks: Banks to be erased + * This parameter can be one of the following values: + * @arg FLASH_BANK_1: Bank1 to be erased + * @arg FLASH_BANK_2: Bank2 to be erased + * @arg FLASH_BANK_BOTH: Bank1 and Bank2 to be erased + * @retval None + */ +static void FLASH_MassErase(uint32_t Banks) +{ +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + if (READ_BIT(FLASH->OPTR, FLASH_OPTR_DBANK) != RESET) +#endif + { + /* Check the parameters */ + assert_param(IS_FLASH_BANK(Banks)); + + /* Set the Mass Erase Bit for the bank 1 if requested */ + if((Banks & FLASH_BANK_1) != RESET) + { + SET_BIT(FLASH->CR, FLASH_CR_MER1); + } + +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + /* Set the Mass Erase Bit for the bank 2 if requested */ + if((Banks & FLASH_BANK_2) != RESET) + { + SET_BIT(FLASH->CR, FLASH_CR_MER2); + } +#endif + } +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + else + { + SET_BIT(FLASH->CR, (FLASH_CR_MER1 | FLASH_CR_MER2)); + } +#endif + + /* Proceed to erase all sectors */ + SET_BIT(FLASH->CR, FLASH_CR_STRT); +} + +/** + * @brief Erase the specified FLASH memory page. + * @param Page: FLASH page to erase + * This parameter must be a value between 0 and (max number of pages in the bank - 1) + * @param Banks: Bank(s) where the page will be erased + * This parameter can be one of the following values: + * @arg FLASH_BANK_1: Page in bank 1 to be erased + * @arg FLASH_BANK_2: Page in bank 2 to be erased + * @retval None + */ +void FLASH_PageErase(uint32_t Page, uint32_t Banks) +{ + /* Check the parameters */ + assert_param(IS_FLASH_PAGE(Page)); + +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + if(READ_BIT(FLASH->OPTR, FLASH_OPTR_DBANK) == RESET) + { + CLEAR_BIT(FLASH->CR, FLASH_CR_BKER); + } + else +#endif + { + assert_param(IS_FLASH_BANK_EXCLUSIVE(Banks)); + + if((Banks & FLASH_BANK_1) != RESET) + { + CLEAR_BIT(FLASH->CR, FLASH_CR_BKER); + } + else + { + SET_BIT(FLASH->CR, FLASH_CR_BKER); + } + } +#endif + + /* Proceed to erase the page */ + MODIFY_REG(FLASH->CR, FLASH_CR_PNB, (Page << POSITION_VAL(FLASH_CR_PNB))); + SET_BIT(FLASH->CR, FLASH_CR_PER); + SET_BIT(FLASH->CR, FLASH_CR_STRT); +} + +/** + * @brief Flush the instruction and data caches. + * @retval None + */ +void FLASH_FlushCaches(void) +{ + /* Flush instruction cache */ + if((pFlash.CacheToReactivate == FLASH_CACHE_ICACHE_ENABLED) || + (pFlash.CacheToReactivate == FLASH_CACHE_ICACHE_DCACHE_ENABLED)) + { + /* Reset instruction cache */ + __HAL_FLASH_INSTRUCTION_CACHE_RESET(); + /* Enable instruction cache */ + __HAL_FLASH_INSTRUCTION_CACHE_ENABLE(); + } + + /* Flush data cache */ + if((pFlash.CacheToReactivate == FLASH_CACHE_DCACHE_ENABLED) || + (pFlash.CacheToReactivate == FLASH_CACHE_ICACHE_DCACHE_ENABLED)) + { + /* Reset data cache */ + __HAL_FLASH_DATA_CACHE_RESET(); + /* Enable data cache */ + __HAL_FLASH_DATA_CACHE_ENABLE(); + } + + /* Reset internal variable */ + pFlash.CacheToReactivate = FLASH_CACHE_DISABLED; +} + +/** + * @brief Configure the write protection of the desired pages. + * + * @note When the memory read protection level is selected (RDP level = 1), + * it is not possible to program or erase Flash memory if the CPU debug + * features are connected (JTAG or single wire) or boot code is being + * executed from RAM or System flash, even if WRP is not activated. + * @note To configure the WRP options, the option lock bit OPTLOCK must be + * cleared with the call of the HAL_FLASH_OB_Unlock() function. + * @note To validate the WRP options, the option bytes must be reloaded + * through the call of the HAL_FLASH_OB_Launch() function. + * + * @param WRPArea: specifies the area to be configured. + * This parameter can be one of the following values: + * @arg OB_WRPAREA_BANK1_AREAA: Flash Bank 1 Area A + * @arg OB_WRPAREA_BANK1_AREAB: Flash Bank 1 Area B + * @arg OB_WRPAREA_BANK2_AREAA: Flash Bank 2 Area A (don't apply for STM32L43x/STM32L44x devices) + * @arg OB_WRPAREA_BANK2_AREAB: Flash Bank 2 Area B (don't apply for STM32L43x/STM32L44x devices) + * + * @param WRPStartOffset: specifies the start page of the write protected area + * This parameter can be page number between 0 and (max number of pages in the bank - 1) + * + * @param WRDPEndOffset: specifies the end page of the write protected area + * This parameter can be page number between WRPStartOffset and (max number of pages in the bank - 1) + * + * @retval HAL Status + */ +static HAL_StatusTypeDef FLASH_OB_WRPConfig(uint32_t WRPArea, uint32_t WRPStartOffset, uint32_t WRDPEndOffset) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check the parameters */ + assert_param(IS_OB_WRPAREA(WRPArea)); + assert_param(IS_FLASH_PAGE(WRPStartOffset)); + assert_param(IS_FLASH_PAGE(WRDPEndOffset)); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); + + if(status == HAL_OK) + { + /* Configure the write protected area */ + if(WRPArea == OB_WRPAREA_BANK1_AREAA) + { + MODIFY_REG(FLASH->WRP1AR, (FLASH_WRP1AR_WRP1A_STRT | FLASH_WRP1AR_WRP1A_END), + (WRPStartOffset | (WRDPEndOffset << 16))); + } + else if(WRPArea == OB_WRPAREA_BANK1_AREAB) + { + MODIFY_REG(FLASH->WRP1BR, (FLASH_WRP1BR_WRP1B_STRT | FLASH_WRP1BR_WRP1B_END), + (WRPStartOffset | (WRDPEndOffset << 16))); + } +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + else if(WRPArea == OB_WRPAREA_BANK2_AREAA) + { + MODIFY_REG(FLASH->WRP2AR, (FLASH_WRP2AR_WRP2A_STRT | FLASH_WRP2AR_WRP2A_END), + (WRPStartOffset | (WRDPEndOffset << 16))); + } + else if(WRPArea == OB_WRPAREA_BANK2_AREAB) + { + MODIFY_REG(FLASH->WRP2BR, (FLASH_WRP2BR_WRP2B_STRT | FLASH_WRP2BR_WRP2B_END), + (WRPStartOffset | (WRDPEndOffset << 16))); + } +#endif + + /* Set OPTSTRT Bit */ + SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); + + /* If the option byte program operation is completed, disable the OPTSTRT Bit */ + CLEAR_BIT(FLASH->CR, FLASH_CR_OPTSTRT); + } + + return status; +} + +/** + * @brief Set the read protection level. + * + * @note To configure the RDP level, the option lock bit OPTLOCK must be + * cleared with the call of the HAL_FLASH_OB_Unlock() function. + * @note To validate the RDP level, the option bytes must be reloaded + * through the call of the HAL_FLASH_OB_Launch() function. + * @note !!! Warning : When enabling OB_RDP level 2 it's no more possible + * to go back to level 1 or 0 !!! + * + * @param RDPLevel: specifies the read protection level. + * This parameter can be one of the following values: + * @arg OB_RDP_LEVEL_0: No protection + * @arg OB_RDP_LEVEL_1: Read protection of the memory + * @arg OB_RDP_LEVEL_2: Full chip protection + * + * @retval HAL status + */ +static HAL_StatusTypeDef FLASH_OB_RDPConfig(uint32_t RDPLevel) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check the parameters */ + assert_param(IS_OB_RDP_LEVEL(RDPLevel)); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); + + if(status == HAL_OK) + { + /* Configure the RDP level in the option bytes register */ + MODIFY_REG(FLASH->OPTR, FLASH_OPTR_RDP, RDPLevel); + + /* Set OPTSTRT Bit */ + SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); + + /* If the option byte program operation is completed, disable the OPTSTRT Bit */ + CLEAR_BIT(FLASH->CR, FLASH_CR_OPTSTRT); + } + + return status; +} + +/** + * @brief Program the FLASH User Option Byte. + * + * @note To configure the user option bytes, the option lock bit OPTLOCK must + * be cleared with the call of the HAL_FLASH_OB_Unlock() function. + * @note To validate the user option bytes, the option bytes must be reloaded + * through the call of the HAL_FLASH_OB_Launch() function. + * + * @param UserType: The FLASH User Option Bytes to be modified + * @param UserConfig: The FLASH User Option Bytes values: + * BOR_LEV(Bit8-10), nRST_STOP(Bit12), nRST_STDBY(Bit13), IWDG_SW(Bit16), + * IWDG_STOP(Bit17), IWDG_STDBY(Bit18), WWDG_SW(Bit19), BFB2(Bit20), + * DUALBANK(Bit21), nBOOT1(Bit23), SRAM2_PE(Bit24) and SRAM2_RST(Bit25). + * + * @retval HAL status + */ +static HAL_StatusTypeDef FLASH_OB_UserConfig(uint32_t UserType, uint32_t UserConfig) +{ + uint32_t optr_reg_val = 0; + uint32_t optr_reg_mask = 0; + HAL_StatusTypeDef status = HAL_OK; + + /* Check the parameters */ + assert_param(IS_OB_USER_TYPE(UserType)); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); + + if(status == HAL_OK) + { + if((UserType & OB_USER_BOR_LEV) != RESET) + { + /* BOR level option byte should be modified */ + assert_param(IS_OB_USER_BOR_LEVEL(UserConfig & FLASH_OPTR_BOR_LEV)); + + /* Set value and mask for BOR level option byte */ + optr_reg_val |= (UserConfig & FLASH_OPTR_BOR_LEV); + optr_reg_mask |= FLASH_OPTR_BOR_LEV; + } + + if((UserType & OB_USER_nRST_STOP) != RESET) + { + /* nRST_STOP option byte should be modified */ + assert_param(IS_OB_USER_STOP(UserConfig & FLASH_OPTR_nRST_STOP)); + + /* Set value and mask for nRST_STOP option byte */ + optr_reg_val |= (UserConfig & FLASH_OPTR_nRST_STOP); + optr_reg_mask |= FLASH_OPTR_nRST_STOP; + } + + if((UserType & OB_USER_nRST_STDBY) != RESET) + { + /* nRST_STDBY option byte should be modified */ + assert_param(IS_OB_USER_STANDBY(UserConfig & FLASH_OPTR_nRST_STDBY)); + + /* Set value and mask for nRST_STDBY option byte */ + optr_reg_val |= (UserConfig & FLASH_OPTR_nRST_STDBY); + optr_reg_mask |= FLASH_OPTR_nRST_STDBY; + } + + if((UserType & OB_USER_nRST_SHDW) != RESET) + { + /* nRST_SHDW option byte should be modified */ + assert_param(IS_OB_USER_SHUTDOWN(UserConfig & FLASH_OPTR_nRST_SHDW)); + + /* Set value and mask for nRST_SHDW option byte */ + optr_reg_val |= (UserConfig & FLASH_OPTR_nRST_SHDW); + optr_reg_mask |= FLASH_OPTR_nRST_SHDW; + } + + if((UserType & OB_USER_IWDG_SW) != RESET) + { + /* IWDG_SW option byte should be modified */ + assert_param(IS_OB_USER_IWDG(UserConfig & FLASH_OPTR_IWDG_SW)); + + /* Set value and mask for IWDG_SW option byte */ + optr_reg_val |= (UserConfig & FLASH_OPTR_IWDG_SW); + optr_reg_mask |= FLASH_OPTR_IWDG_SW; + } + + if((UserType & OB_USER_IWDG_STOP) != RESET) + { + /* IWDG_STOP option byte should be modified */ + assert_param(IS_OB_USER_IWDG_STOP(UserConfig & FLASH_OPTR_IWDG_STOP)); + + /* Set value and mask for IWDG_STOP option byte */ + optr_reg_val |= (UserConfig & FLASH_OPTR_IWDG_STOP); + optr_reg_mask |= FLASH_OPTR_IWDG_STOP; + } + + if((UserType & OB_USER_IWDG_STDBY) != RESET) + { + /* IWDG_STDBY option byte should be modified */ + assert_param(IS_OB_USER_IWDG_STDBY(UserConfig & FLASH_OPTR_IWDG_STDBY)); + + /* Set value and mask for IWDG_STDBY option byte */ + optr_reg_val |= (UserConfig & FLASH_OPTR_IWDG_STDBY); + optr_reg_mask |= FLASH_OPTR_IWDG_STDBY; + } + + if((UserType & OB_USER_WWDG_SW) != RESET) + { + /* WWDG_SW option byte should be modified */ + assert_param(IS_OB_USER_WWDG(UserConfig & FLASH_OPTR_WWDG_SW)); + + /* Set value and mask for WWDG_SW option byte */ + optr_reg_val |= (UserConfig & FLASH_OPTR_WWDG_SW); + optr_reg_mask |= FLASH_OPTR_WWDG_SW; + } + +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + if((UserType & OB_USER_BFB2) != RESET) + { + /* BFB2 option byte should be modified */ + assert_param(IS_OB_USER_BFB2(UserConfig & FLASH_OPTR_BFB2)); + + /* Set value and mask for BFB2 option byte */ + optr_reg_val |= (UserConfig & FLASH_OPTR_BFB2); + optr_reg_mask |= FLASH_OPTR_BFB2; + } + + if((UserType & OB_USER_DUALBANK) != RESET) + { +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + /* DUALBANK option byte should be modified */ + assert_param(IS_OB_USER_DUALBANK(UserConfig & FLASH_OPTR_DB1M)); + + /* Set value and mask for DUALBANK option byte */ + optr_reg_val |= (UserConfig & FLASH_OPTR_DB1M); + optr_reg_mask |= FLASH_OPTR_DB1M; +#else + /* DUALBANK option byte should be modified */ + assert_param(IS_OB_USER_DUALBANK(UserConfig & FLASH_OPTR_DUALBANK)); + + /* Set value and mask for DUALBANK option byte */ + optr_reg_val |= (UserConfig & FLASH_OPTR_DUALBANK); + optr_reg_mask |= FLASH_OPTR_DUALBANK; +#endif + } +#endif + + if((UserType & OB_USER_nBOOT1) != RESET) + { + /* nBOOT1 option byte should be modified */ + assert_param(IS_OB_USER_BOOT1(UserConfig & FLASH_OPTR_nBOOT1)); + + /* Set value and mask for nBOOT1 option byte */ + optr_reg_val |= (UserConfig & FLASH_OPTR_nBOOT1); + optr_reg_mask |= FLASH_OPTR_nBOOT1; + } + + if((UserType & OB_USER_SRAM2_PE) != RESET) + { + /* SRAM2_PE option byte should be modified */ + assert_param(IS_OB_USER_SRAM2_PARITY(UserConfig & FLASH_OPTR_SRAM2_PE)); + + /* Set value and mask for SRAM2_PE option byte */ + optr_reg_val |= (UserConfig & FLASH_OPTR_SRAM2_PE); + optr_reg_mask |= FLASH_OPTR_SRAM2_PE; + } + + if((UserType & OB_USER_SRAM2_RST) != RESET) + { + /* SRAM2_RST option byte should be modified */ + assert_param(IS_OB_USER_SRAM2_RST(UserConfig & FLASH_OPTR_SRAM2_RST)); + + /* Set value and mask for SRAM2_RST option byte */ + optr_reg_val |= (UserConfig & FLASH_OPTR_SRAM2_RST); + optr_reg_mask |= FLASH_OPTR_SRAM2_RST; + } + +#if defined (STM32L431xx) || defined (STM32L432xx) || defined (STM32L433xx) || defined (STM32L442xx) || \ + defined (STM32L443xx) || defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + if((UserType & OB_USER_nSWBOOT0) != RESET) + { + /* nSWBOOT0 option byte should be modified */ + assert_param(IS_OB_USER_SWBOOT0(UserConfig & FLASH_OPTR_nSWBOOT0)); + + /* Set value and mask for nSWBOOT0 option byte */ + optr_reg_val |= (UserConfig & FLASH_OPTR_nSWBOOT0); + optr_reg_mask |= FLASH_OPTR_nSWBOOT0; + } + + if((UserType & OB_USER_nBOOT0) != RESET) + { + /* nBOOT0 option byte should be modified */ + assert_param(IS_OB_USER_BOOT0(UserConfig & FLASH_OPTR_nBOOT0)); + + /* Set value and mask for nBOOT0 option byte */ + optr_reg_val |= (UserConfig & FLASH_OPTR_nBOOT0); + optr_reg_mask |= FLASH_OPTR_nBOOT0; + } +#endif + + /* Configure the option bytes register */ + MODIFY_REG(FLASH->OPTR, optr_reg_mask, optr_reg_val); + + /* Set OPTSTRT Bit */ + SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); + + /* If the option byte program operation is completed, disable the OPTSTRT Bit */ + CLEAR_BIT(FLASH->CR, FLASH_CR_OPTSTRT); + } + + return status; +} + +/** + * @brief Configure the Proprietary code readout protection of the desired addresses. + * + * @note To configure the PCROP options, the option lock bit OPTLOCK must be + * cleared with the call of the HAL_FLASH_OB_Unlock() function. + * @note To validate the PCROP options, the option bytes must be reloaded + * through the call of the HAL_FLASH_OB_Launch() function. + * + * @param PCROPConfig: specifies the configuration (Bank to be configured and PCROP_RDP option). + * This parameter must be a combination of FLASH_BANK_1 or FLASH_BANK_2 + * with OB_PCROP_RDP_NOT_ERASE or OB_PCROP_RDP_ERASE + * + * @param PCROPStartAddr: specifies the start address of the Proprietary code readout protection + * This parameter can be an address between begin and end of the bank + * + * @param PCROPEndAddr: specifies the end address of the Proprietary code readout protection + * This parameter can be an address between PCROPStartAddr and end of the bank + * + * @retval HAL Status + */ +static HAL_StatusTypeDef FLASH_OB_PCROPConfig(uint32_t PCROPConfig, uint32_t PCROPStartAddr, uint32_t PCROPEndAddr) +{ + HAL_StatusTypeDef status = HAL_OK; + uint32_t reg_value = 0; + uint32_t bank1_addr; +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + uint32_t bank2_addr; +#endif + + /* Check the parameters */ + assert_param(IS_FLASH_BANK_EXCLUSIVE(PCROPConfig & FLASH_BANK_BOTH)); + assert_param(IS_OB_PCROP_RDP(PCROPConfig & FLASH_PCROP1ER_PCROP_RDP)); + assert_param(IS_FLASH_MAIN_MEM_ADDRESS(PCROPStartAddr)); + assert_param(IS_FLASH_MAIN_MEM_ADDRESS(PCROPEndAddr)); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); + + if(status == HAL_OK) + { +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + /* Get the information about the bank swapping */ + if (READ_BIT(SYSCFG->MEMRMP, SYSCFG_MEMRMP_FB_MODE) == 0) + { + bank1_addr = FLASH_BASE; + bank2_addr = FLASH_BASE + FLASH_BANK_SIZE; + } + else + { + bank1_addr = FLASH_BASE + FLASH_BANK_SIZE; + bank2_addr = FLASH_BASE; + } +#else + bank1_addr = FLASH_BASE; +#endif + +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + if (READ_BIT(FLASH->OPTR, FLASH_OPTR_DBANK) == RESET) + { + /* Configure the Proprietary code readout protection */ + if((PCROPConfig & FLASH_BANK_BOTH) == FLASH_BANK_1) + { + reg_value = ((PCROPStartAddr - FLASH_BASE) >> 4); + MODIFY_REG(FLASH->PCROP1SR, FLASH_PCROP1SR_PCROP1_STRT, reg_value); + + reg_value = ((PCROPEndAddr - FLASH_BASE) >> 4); + MODIFY_REG(FLASH->PCROP1ER, FLASH_PCROP1ER_PCROP1_END, reg_value); + } + else if((PCROPConfig & FLASH_BANK_BOTH) == FLASH_BANK_2) + { + reg_value = ((PCROPStartAddr - FLASH_BASE) >> 4); + MODIFY_REG(FLASH->PCROP2SR, FLASH_PCROP2SR_PCROP2_STRT, reg_value); + + reg_value = ((PCROPEndAddr - FLASH_BASE) >> 4); + MODIFY_REG(FLASH->PCROP2ER, FLASH_PCROP2ER_PCROP2_END, reg_value); + } + } + else +#endif + { + /* Configure the Proprietary code readout protection */ + if((PCROPConfig & FLASH_BANK_BOTH) == FLASH_BANK_1) + { + reg_value = ((PCROPStartAddr - bank1_addr) >> 3); + MODIFY_REG(FLASH->PCROP1SR, FLASH_PCROP1SR_PCROP1_STRT, reg_value); + + reg_value = ((PCROPEndAddr - bank1_addr) >> 3); + MODIFY_REG(FLASH->PCROP1ER, FLASH_PCROP1ER_PCROP1_END, reg_value); + } +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + else if((PCROPConfig & FLASH_BANK_BOTH) == FLASH_BANK_2) + { + reg_value = ((PCROPStartAddr - bank2_addr) >> 3); + MODIFY_REG(FLASH->PCROP2SR, FLASH_PCROP2SR_PCROP2_STRT, reg_value); + + reg_value = ((PCROPEndAddr - bank2_addr) >> 3); + MODIFY_REG(FLASH->PCROP2ER, FLASH_PCROP2ER_PCROP2_END, reg_value); + } +#endif + } + + MODIFY_REG(FLASH->PCROP1ER, FLASH_PCROP1ER_PCROP_RDP, (PCROPConfig & FLASH_PCROP1ER_PCROP_RDP)); + + /* Set OPTSTRT Bit */ + SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); + + /* If the option byte program operation is completed, disable the OPTSTRT Bit */ + CLEAR_BIT(FLASH->CR, FLASH_CR_OPTSTRT); + } + + return status; +} + +/** + * @brief Return the FLASH Write Protection Option Bytes value. + * + * @param[in] WRPArea: specifies the area to be returned. + * This parameter can be one of the following values: + * @arg OB_WRPAREA_BANK1_AREAA: Flash Bank 1 Area A + * @arg OB_WRPAREA_BANK1_AREAB: Flash Bank 1 Area B + * @arg OB_WRPAREA_BANK2_AREAA: Flash Bank 2 Area A (don't apply to STM32L43x/STM32L44x devices) + * @arg OB_WRPAREA_BANK2_AREAB: Flash Bank 2 Area B (don't apply to STM32L43x/STM32L44x devices) + * + * @param[out] WRPStartOffset: specifies the address where to copied the start page + * of the write protected area + * + * @param[out] WRDPEndOffset: specifies the address where to copied the end page of + * the write protected area + * + * @retval None + */ +static void FLASH_OB_GetWRP(uint32_t WRPArea, uint32_t * WRPStartOffset, uint32_t * WRDPEndOffset) +{ + /* Get the configuration of the write protected area */ + if(WRPArea == OB_WRPAREA_BANK1_AREAA) + { + *WRPStartOffset = READ_BIT(FLASH->WRP1AR, FLASH_WRP1AR_WRP1A_STRT); + *WRDPEndOffset = (READ_BIT(FLASH->WRP1AR, FLASH_WRP1AR_WRP1A_END) >> 16); + } + else if(WRPArea == OB_WRPAREA_BANK1_AREAB) + { + *WRPStartOffset = READ_BIT(FLASH->WRP1BR, FLASH_WRP1BR_WRP1B_STRT); + *WRDPEndOffset = (READ_BIT(FLASH->WRP1BR, FLASH_WRP1BR_WRP1B_END) >> 16); + } +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + else if(WRPArea == OB_WRPAREA_BANK2_AREAA) + { + *WRPStartOffset = READ_BIT(FLASH->WRP2AR, FLASH_WRP2AR_WRP2A_STRT); + *WRDPEndOffset = (READ_BIT(FLASH->WRP2AR, FLASH_WRP2AR_WRP2A_END) >> 16); + } + else if(WRPArea == OB_WRPAREA_BANK2_AREAB) + { + *WRPStartOffset = READ_BIT(FLASH->WRP2BR, FLASH_WRP2BR_WRP2B_STRT); + *WRDPEndOffset = (READ_BIT(FLASH->WRP2BR, FLASH_WRP2BR_WRP2B_END) >> 16); + } +#endif +} + +/** + * @brief Return the FLASH Read Protection level. + * @retval FLASH ReadOut Protection Status: + * This return value can be one of the following values: + * @arg OB_RDP_LEVEL_0: No protection + * @arg OB_RDP_LEVEL_1: Read protection of the memory + * @arg OB_RDP_LEVEL_2: Full chip protection + */ +static uint32_t FLASH_OB_GetRDP(void) +{ + if ((READ_BIT(FLASH->OPTR, FLASH_OPTR_RDP) != OB_RDP_LEVEL_0) && + (READ_BIT(FLASH->OPTR, FLASH_OPTR_RDP) != OB_RDP_LEVEL_2)) + { + return (OB_RDP_LEVEL_1); + } + else + { + return (READ_BIT(FLASH->OPTR, FLASH_OPTR_RDP)); + } +} + +/** + * @brief Return the FLASH User Option Byte value. + * @retval The FLASH User Option Bytes values: + * For STM32L47x/STM32L48x devices : + * BOR_LEV(Bit8-10), nRST_STOP(Bit12), nRST_STDBY(Bit13), nRST_SHDW(Bit14), + * IWDG_SW(Bit16), IWDG_STOP(Bit17), IWDG_STDBY(Bit18), WWDG_SW(Bit19), + * BFB2(Bit20), DUALBANK(Bit21), nBOOT1(Bit23), SRAM2_PE(Bit24) and SRAM2_RST(Bit25). + * For STM32L43x/STM32L44x devices : + * BOR_LEV(Bit8-10), nRST_STOP(Bit12), nRST_STDBY(Bit13), nRST_SHDW(Bit14), + * IWDG_SW(Bit16), IWDG_STOP(Bit17), IWDG_STDBY(Bit18), WWDG_SW(Bit19), + * nBOOT1(Bit23), SRAM2_PE(Bit24), SRAM2_RST(Bit25), nSWBOOT0(Bit26) and nBOOT0(Bit27). + */ +static uint32_t FLASH_OB_GetUser(void) +{ + uint32_t user_config = READ_REG(FLASH->OPTR); + CLEAR_BIT(user_config, FLASH_OPTR_RDP); + + return user_config; +} + +/** + * @brief Return the FLASH Write Protection Option Bytes value. + * + * @param PCROPConfig [inout]: specifies the configuration (Bank to be configured and PCROP_RDP option). + * This parameter must be a combination of FLASH_BANK_1 or FLASH_BANK_2 + * with OB_PCROP_RDP_NOT_ERASE or OB_PCROP_RDP_ERASE + * + * @param PCROPStartAddr [out]: specifies the address where to copied the start address + * of the Proprietary code readout protection + * + * @param PCROPEndAddr [out]: specifies the address where to copied the end address of + * the Proprietary code readout protection + * + * @retval None + */ +static void FLASH_OB_GetPCROP(uint32_t * PCROPConfig, uint32_t * PCROPStartAddr, uint32_t * PCROPEndAddr) +{ + uint32_t reg_value = 0; + uint32_t bank1_addr; +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + uint32_t bank2_addr; +#endif + +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + /* Get the information about the bank swapping */ + if (READ_BIT(SYSCFG->MEMRMP, SYSCFG_MEMRMP_FB_MODE) == 0) + { + bank1_addr = FLASH_BASE; + bank2_addr = FLASH_BASE + FLASH_BANK_SIZE; + } + else + { + bank1_addr = FLASH_BASE + FLASH_BANK_SIZE; + bank2_addr = FLASH_BASE; + } +#else + bank1_addr = FLASH_BASE; +#endif + +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + if (READ_BIT(FLASH->OPTR, FLASH_OPTR_DBANK) == RESET) + { + if(((*PCROPConfig) & FLASH_BANK_BOTH) == FLASH_BANK_1) + { + reg_value = (READ_REG(FLASH->PCROP1SR) & FLASH_PCROP1SR_PCROP1_STRT); + *PCROPStartAddr = (reg_value << 4) + FLASH_BASE; + + reg_value = (READ_REG(FLASH->PCROP1ER) & FLASH_PCROP1ER_PCROP1_END); + *PCROPEndAddr = (reg_value << 4) + FLASH_BASE; + } + else if(((*PCROPConfig) & FLASH_BANK_BOTH) == FLASH_BANK_2) + { + reg_value = (READ_REG(FLASH->PCROP2SR) & FLASH_PCROP2SR_PCROP2_STRT); + *PCROPStartAddr = (reg_value << 4) + FLASH_BASE; + + reg_value = (READ_REG(FLASH->PCROP2ER) & FLASH_PCROP2ER_PCROP2_END); + *PCROPEndAddr = (reg_value << 4) + FLASH_BASE; + } + } + else +#endif + { + if(((*PCROPConfig) & FLASH_BANK_BOTH) == FLASH_BANK_1) + { + reg_value = (READ_REG(FLASH->PCROP1SR) & FLASH_PCROP1SR_PCROP1_STRT); + *PCROPStartAddr = (reg_value << 3) + bank1_addr; + + reg_value = (READ_REG(FLASH->PCROP1ER) & FLASH_PCROP1ER_PCROP1_END); + *PCROPEndAddr = (reg_value << 3) + bank1_addr; + } +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + else if(((*PCROPConfig) & FLASH_BANK_BOTH) == FLASH_BANK_2) + { + reg_value = (READ_REG(FLASH->PCROP2SR) & FLASH_PCROP2SR_PCROP2_STRT); + *PCROPStartAddr = (reg_value << 3) + bank2_addr; + + reg_value = (READ_REG(FLASH->PCROP2ER) & FLASH_PCROP2ER_PCROP2_END); + *PCROPEndAddr = (reg_value << 3) + bank2_addr; + } +#endif + } + + *PCROPConfig |= (READ_REG(FLASH->PCROP1ER) & FLASH_PCROP1ER_PCROP_RDP); +} +/** + * @} + */ + +/** + * @} + */ + +#endif /* HAL_FLASH_MODULE_ENABLED */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash_ramfunc.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash_ramfunc.c new file mode 100644 index 0000000..537560f --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash_ramfunc.c @@ -0,0 +1,271 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_flash_ramfunc.c + * @author MCD Application Team + * @brief FLASH RAMFUNC driver. + * This file provides a Flash firmware functions which should be + * executed from internal SRAM + * + FLASH HalfPage Programming + * + FLASH Power Down in Run mode + * + * @verbatim + ============================================================================== + ##### Flash RAM functions ##### + ============================================================================== + + *** ARM Compiler *** + -------------------- + [..] RAM functions are defined using the toolchain options. + Functions that are executed in RAM should reside in a separate + source module. Using the 'Options for File' dialog you can simply change + the 'Code / Const' area of a module to a memory space in physical RAM. + Available memory areas are declared in the 'Target' tab of the + Options for Target' dialog. + + *** ICCARM Compiler *** + ----------------------- + [..] RAM functions are defined using a specific toolchain keyword "__ramfunc". + + *** GNU Compiler *** + -------------------- + [..] RAM functions are defined using a specific toolchain attribute + "__attribute__((section(".RamFunc")))". + + @endverbatim + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup FLASH_RAMFUNC FLASH_RAMFUNC + * @brief FLASH functions executed from RAM + * @{ + */ + +#ifdef HAL_FLASH_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +extern FLASH_ProcessTypeDef pFlash; + +/* Private function prototypes -----------------------------------------------*/ +/* Exported functions -------------------------------------------------------*/ + +/** @defgroup FLASH_RAMFUNC_Exported_Functions FLASH in RAM function Exported Functions + * @{ + */ + +/** @defgroup FLASH_RAMFUNC_Exported_Functions_Group1 Peripheral features functions + * @brief Data transfers functions + * +@verbatim + =============================================================================== + ##### ramfunc functions ##### + =============================================================================== + [..] + This subsection provides a set of functions that should be executed from RAM. + +@endverbatim + * @{ + */ + +/** + * @brief Enable the Power down in Run Mode + * @note This function should be called and executed from SRAM memory + * @retval None + */ +__RAM_FUNC HAL_FLASHEx_EnableRunPowerDown(void) +{ + /* Enable the Power Down in Run mode*/ + __HAL_FLASH_POWER_DOWN_ENABLE(); + + return HAL_OK; + +} + +/** + * @brief Disable the Power down in Run Mode + * @note This function should be called and executed from SRAM memory + * @retval None + */ +__RAM_FUNC HAL_FLASHEx_DisableRunPowerDown(void) +{ + /* Disable the Power Down in Run mode*/ + __HAL_FLASH_POWER_DOWN_DISABLE(); + + return HAL_OK; +} + +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +/** + * @brief Program the FLASH DBANK User Option Byte. + * + * @note To configure the user option bytes, the option lock bit OPTLOCK must + * be cleared with the call of the HAL_FLASH_OB_Unlock() function. + * @note To modify the DBANK option byte, no PCROP region should be defined. + * To deactivate PCROP, user should perform RDP changing + * + * @param DBankConfig: The FLASH DBANK User Option Byte value. + * This parameter can be one of the following values: + * @arg OB_DBANK_128_BITS: Single-bank with 128-bits data + * @arg OB_DBANK_64_BITS: Dual-bank with 64-bits data + * + * @retval HAL status + */ +__RAM_FUNC HAL_FLASHEx_OB_DBankConfig(uint32_t DBankConfig) +{ + register uint32_t count, reg; + HAL_StatusTypeDef status = HAL_ERROR; + + /* Process Locked */ + __HAL_LOCK(&pFlash); + + /* Check if the PCROP is disabled */ + reg = FLASH->PCROP1SR; + if (reg > FLASH->PCROP1ER) + { + reg = FLASH->PCROP2SR; + if (reg > FLASH->PCROP2ER) + { + /* Disable Flash prefetch */ + __HAL_FLASH_PREFETCH_BUFFER_DISABLE(); + + if (READ_BIT(FLASH->ACR, FLASH_ACR_ICEN) != RESET) + { + /* Disable Flash instruction cache */ + __HAL_FLASH_INSTRUCTION_CACHE_DISABLE(); + + /* Flush Flash instruction cache */ + __HAL_FLASH_INSTRUCTION_CACHE_RESET(); + } + + if (READ_BIT(FLASH->ACR, FLASH_ACR_DCEN) != RESET) + { + /* Disable Flash data cache */ + __HAL_FLASH_DATA_CACHE_DISABLE(); + + /* Flush Flash data cache */ + __HAL_FLASH_DATA_CACHE_RESET(); + } + + /* Disable WRP zone 1 of 1st bank if needed */ + reg = FLASH->WRP1AR; + if (((reg & FLASH_WRP1AR_WRP1A_STRT) >> POSITION_VAL(FLASH_WRP1AR_WRP1A_STRT)) <= + ((reg & FLASH_WRP1AR_WRP1A_END) >> POSITION_VAL(FLASH_WRP1AR_WRP1A_END))) + { + MODIFY_REG(FLASH->WRP1AR, (FLASH_WRP1AR_WRP1A_STRT | FLASH_WRP1AR_WRP1A_END), FLASH_WRP1AR_WRP1A_STRT); + } + + /* Disable WRP zone 2 of 1st bank if needed */ + reg = FLASH->WRP1BR; + if (((reg & FLASH_WRP1BR_WRP1B_STRT) >> POSITION_VAL(FLASH_WRP1BR_WRP1B_STRT)) <= + ((reg & FLASH_WRP1BR_WRP1B_END) >> POSITION_VAL(FLASH_WRP1BR_WRP1B_END))) + { + MODIFY_REG(FLASH->WRP1BR, (FLASH_WRP1BR_WRP1B_STRT | FLASH_WRP1BR_WRP1B_END), FLASH_WRP1BR_WRP1B_STRT); + } + + /* Disable WRP zone 1 of 2nd bank if needed */ + reg = FLASH->WRP2AR; + if (((reg & FLASH_WRP2AR_WRP2A_STRT) >> POSITION_VAL(FLASH_WRP2AR_WRP2A_STRT)) <= + ((reg & FLASH_WRP2AR_WRP2A_END) >> POSITION_VAL(FLASH_WRP2AR_WRP2A_END))) + { + MODIFY_REG(FLASH->WRP2AR, (FLASH_WRP2AR_WRP2A_STRT | FLASH_WRP2AR_WRP2A_END), FLASH_WRP2AR_WRP2A_STRT); + } + + /* Disable WRP zone 2 of 2nd bank if needed */ + reg = FLASH->WRP2BR; + if (((reg & FLASH_WRP2BR_WRP2B_STRT) >> POSITION_VAL(FLASH_WRP2BR_WRP2B_STRT)) <= + ((reg & FLASH_WRP2BR_WRP2B_END) >> POSITION_VAL(FLASH_WRP2BR_WRP2B_END))) + { + MODIFY_REG(FLASH->WRP2BR, (FLASH_WRP2BR_WRP2B_STRT | FLASH_WRP2BR_WRP2B_END), FLASH_WRP2BR_WRP2B_STRT); + } + + /* Modify the DBANK user option byte */ + MODIFY_REG(FLASH->OPTR, FLASH_OPTR_DBANK, DBankConfig); + + /* Set OPTSTRT Bit */ + SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT); + + /* Wait for last operation to be completed */ + /* 8 is the number of required instruction cycles for the below loop statement (timeout expressed in ms) */ + count = FLASH_TIMEOUT_VALUE * (SystemCoreClock / 8 / 1000); + do + { + if (count-- == 0) + { + break; + } + } while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY) != RESET); + + /* If the option byte program operation is completed, disable the OPTSTRT Bit */ + CLEAR_BIT(FLASH->CR, FLASH_CR_OPTSTRT); + + /* Set the bit to force the option byte reloading */ + SET_BIT(FLASH->CR, FLASH_CR_OBL_LAUNCH); + } + } + + /* Process Unlocked */ + __HAL_UNLOCK(&pFlash); + + return status; +} +#endif + +/** + * @} + */ + +/** + * @} + */ +#endif /* HAL_FLASH_MODULE_ENABLED */ + + + +/** + * @} + */ + +/** + * @} + */ + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + + diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_gpio.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_gpio.c new file mode 100644 index 0000000..a2cf329 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_gpio.c @@ -0,0 +1,568 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_gpio.c + * @author MCD Application Team + * @brief GPIO HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the General Purpose Input/Output (GPIO) peripheral: + * + Initialization and de-initialization functions + * + IO operation functions + * + @verbatim + ============================================================================== + ##### GPIO Peripheral features ##### + ============================================================================== + [..] + (+) Each port bit of the general-purpose I/O (GPIO) ports can be individually + configured by software in several modes: + (++) Input mode + (++) Analog mode + (++) Output mode + (++) Alternate function mode + (++) External interrupt/event lines + + (+) During and just after reset, the alternate functions and external interrupt + lines are not active and the I/O ports are configured in input floating mode. + + (+) All GPIO pins have weak internal pull-up and pull-down resistors, which can be + activated or not. + + (+) In Output or Alternate mode, each IO can be configured on open-drain or push-pull + type and the IO speed can be selected depending on the VDD value. + + (+) The microcontroller IO pins are connected to onboard peripherals/modules through a + multiplexer that allows only one peripheral alternate function (AF) connected + to an IO pin at a time. In this way, there can be no conflict between peripherals + sharing the same IO pin. + + (+) All ports have external interrupt/event capability. To use external interrupt + lines, the port must be configured in input mode. All available GPIO pins are + connected to the 16 external interrupt/event lines from EXTI0 to EXTI15. + + (+) The external interrupt/event controller consists of up to 39 edge detectors + (16 lines are connected to GPIO) for generating event/interrupt requests (each + input line can be independently configured to select the type (interrupt or event) + and the corresponding trigger event (rising or falling or both). Each line can + also be masked independently. + + ##### How to use this driver ##### + ============================================================================== + [..] + (#) Enable the GPIO AHB clock using the following function: __HAL_RCC_GPIOx_CLK_ENABLE(). + + (#) Configure the GPIO pin(s) using HAL_GPIO_Init(). + (++) Configure the IO mode using "Mode" member from GPIO_InitTypeDef structure + (++) Activate Pull-up, Pull-down resistor using "Pull" member from GPIO_InitTypeDef + structure. + (++) In case of Output or alternate function mode selection: the speed is + configured through "Speed" member from GPIO_InitTypeDef structure. + (++) In alternate mode is selection, the alternate function connected to the IO + is configured through "Alternate" member from GPIO_InitTypeDef structure. + (++) Analog mode is required when a pin is to be used as ADC channel + or DAC output. + (++) In case of external interrupt/event selection the "Mode" member from + GPIO_InitTypeDef structure select the type (interrupt or event) and + the corresponding trigger event (rising or falling or both). + + (#) In case of external interrupt/event mode selection, configure NVIC IRQ priority + mapped to the EXTI line using HAL_NVIC_SetPriority() and enable it using + HAL_NVIC_EnableIRQ(). + + (#) To get the level of a pin configured in input mode use HAL_GPIO_ReadPin(). + + (#) To set/reset the level of a pin configured in output mode use + HAL_GPIO_WritePin()/HAL_GPIO_TogglePin(). + + (#) To lock pin configuration until next reset use HAL_GPIO_LockPin(). + + (#) During and just after reset, the alternate functions are not + active and the GPIO pins are configured in input floating mode (except JTAG + pins). + + (#) The LSE oscillator pins OSC32_IN and OSC32_OUT can be used as general purpose + (PC14 and PC15, respectively) when the LSE oscillator is off. The LSE has + priority over the GPIO function. + + (#) The HSE oscillator pins OSC_IN/OSC_OUT can be used as + general purpose PH0 and PH1, respectively, when the HSE oscillator is off. + The HSE has priority over the GPIO function. + + @endverbatim + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup GPIO GPIO + * @brief GPIO HAL module driver + * @{ + */ + +#ifdef HAL_GPIO_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private defines -----------------------------------------------------------*/ +/** @defgroup GPIO_Private_Defines GPIO Private Defines + * @{ + */ +#define GPIO_MODE ((uint32_t)0x00000003) +#define ANALOG_MODE ((uint32_t)0x00000008) +#define EXTI_MODE ((uint32_t)0x10000000) +#define GPIO_MODE_IT ((uint32_t)0x00010000) +#define GPIO_MODE_EVT ((uint32_t)0x00020000) +#define RISING_EDGE ((uint32_t)0x00100000) +#define FALLING_EDGE ((uint32_t)0x00200000) +#define GPIO_OUTPUT_TYPE ((uint32_t)0x00000010) + +#define GPIO_NUMBER ((uint32_t)16) +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ +/** @defgroup GPIO_Private_Macros GPIO Private Macros + * @{ + */ +/** + * @} + */ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup GPIO_Exported_Functions GPIO Exported Functions + * @{ + */ + +/** @defgroup GPIO_Exported_Functions_Group1 Initialization/de-initialization functions + * @brief Initialization and Configuration functions + * +@verbatim + =============================================================================== + ##### Initialization and de-initialization functions ##### + =============================================================================== + +@endverbatim + * @{ + */ + +/** + * @brief Initialize the GPIOx peripheral according to the specified parameters in the GPIO_Init. + * @param GPIOx: where x can be (A..H) to select the GPIO peripheral for STM32L4 family + * @param GPIO_Init: pointer to a GPIO_InitTypeDef structure that contains + * the configuration information for the specified GPIO peripheral. + * @retval None + */ +void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init) +{ + uint32_t position = 0x00; + uint32_t iocurrent = 0x00; + uint32_t temp = 0x00; + + /* Check the parameters */ + assert_param(IS_GPIO_ALL_INSTANCE(GPIOx)); + assert_param(IS_GPIO_PIN(GPIO_Init->Pin)); + assert_param(IS_GPIO_MODE(GPIO_Init->Mode)); + assert_param(IS_GPIO_PULL(GPIO_Init->Pull)); + + /* Configure the port pins */ + while (((GPIO_Init->Pin) >> position) != RESET) + { + /* Get current io position */ + iocurrent = (GPIO_Init->Pin) & (1U << position); + + if(iocurrent) + { + /*--------------------- GPIO Mode Configuration ------------------------*/ + /* In case of Alternate function mode selection */ + if((GPIO_Init->Mode == GPIO_MODE_AF_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_OD)) + { + /* Check the Alternate function parameters */ + assert_param(IS_GPIO_AF_INSTANCE(GPIOx)); + assert_param(IS_GPIO_AF(GPIO_Init->Alternate)); + + /* Configure Alternate function mapped with the current IO */ + temp = GPIOx->AFR[position >> 3]; + temp &= ~((uint32_t)0xF << ((uint32_t)(position & (uint32_t)0x07) * 4)) ; + temp |= ((uint32_t)(GPIO_Init->Alternate) << (((uint32_t)position & (uint32_t)0x07) * 4)); + GPIOx->AFR[position >> 3] = temp; + } + + /* Configure IO Direction mode (Input, Output, Alternate or Analog) */ + temp = GPIOx->MODER; + temp &= ~(GPIO_MODER_MODE0 << (position * 2)); + temp |= ((GPIO_Init->Mode & GPIO_MODE) << (position * 2)); + GPIOx->MODER = temp; + + /* In case of Output or Alternate function mode selection */ + if((GPIO_Init->Mode == GPIO_MODE_OUTPUT_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_PP) || + (GPIO_Init->Mode == GPIO_MODE_OUTPUT_OD) || (GPIO_Init->Mode == GPIO_MODE_AF_OD)) + { + /* Check the Speed parameter */ + assert_param(IS_GPIO_SPEED(GPIO_Init->Speed)); + /* Configure the IO Speed */ + temp = GPIOx->OSPEEDR; + temp &= ~(GPIO_OSPEEDR_OSPEED0 << (position * 2)); + temp |= (GPIO_Init->Speed << (position * 2)); + GPIOx->OSPEEDR = temp; + + /* Configure the IO Output Type */ + temp = GPIOx->OTYPER; + temp &= ~(GPIO_OTYPER_OT0 << position) ; + temp |= (((GPIO_Init->Mode & GPIO_OUTPUT_TYPE) >> 4) << position); + GPIOx->OTYPER = temp; + } + +#if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) + + /* In case of Analog mode, check if ADC control mode is selected */ + if((GPIO_Init->Mode & GPIO_MODE_ANALOG) == GPIO_MODE_ANALOG) + { + /* Configure the IO Output Type */ + temp = GPIOx->ASCR; + temp &= ~(GPIO_ASCR_ASC0 << position) ; + temp |= (((GPIO_Init->Mode & ANALOG_MODE) >> 3) << position); + GPIOx->ASCR = temp; + } + +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx */ + + /* Activate the Pull-up or Pull down resistor for the current IO */ + temp = GPIOx->PUPDR; + temp &= ~(GPIO_PUPDR_PUPD0 << (position * 2)); + temp |= ((GPIO_Init->Pull) << (position * 2)); + GPIOx->PUPDR = temp; + + /*--------------------- EXTI Mode Configuration ------------------------*/ + /* Configure the External Interrupt or event for the current IO */ + if((GPIO_Init->Mode & EXTI_MODE) == EXTI_MODE) + { + /* Enable SYSCFG Clock */ + __HAL_RCC_SYSCFG_CLK_ENABLE(); + + temp = SYSCFG->EXTICR[position >> 2]; + temp &= ~(((uint32_t)0x0F) << (4 * (position & 0x03))); + temp |= (GPIO_GET_INDEX(GPIOx) << (4 * (position & 0x03))); + SYSCFG->EXTICR[position >> 2] = temp; + + /* Clear EXTI line configuration */ + temp = EXTI->IMR1; + temp &= ~((uint32_t)iocurrent); + if((GPIO_Init->Mode & GPIO_MODE_IT) == GPIO_MODE_IT) + { + temp |= iocurrent; + } + EXTI->IMR1 = temp; + + temp = EXTI->EMR1; + temp &= ~((uint32_t)iocurrent); + if((GPIO_Init->Mode & GPIO_MODE_EVT) == GPIO_MODE_EVT) + { + temp |= iocurrent; + } + EXTI->EMR1 = temp; + + /* Clear Rising Falling edge configuration */ + temp = EXTI->RTSR1; + temp &= ~((uint32_t)iocurrent); + if((GPIO_Init->Mode & RISING_EDGE) == RISING_EDGE) + { + temp |= iocurrent; + } + EXTI->RTSR1 = temp; + + temp = EXTI->FTSR1; + temp &= ~((uint32_t)iocurrent); + if((GPIO_Init->Mode & FALLING_EDGE) == FALLING_EDGE) + { + temp |= iocurrent; + } + EXTI->FTSR1 = temp; + } + } + + position++; + } +} + +/** + * @brief De-initialize the GPIOx peripheral registers to their default reset values. + * @param GPIOx: where x can be (A..H) to select the GPIO peripheral for STM32L4 family + * @param GPIO_Pin: specifies the port bit to be written. + * This parameter can be one of GPIO_PIN_x where x can be (0..15). + * @retval None + */ +void HAL_GPIO_DeInit(GPIO_TypeDef *GPIOx, uint32_t GPIO_Pin) +{ + uint32_t position = 0x00; + uint32_t iocurrent = 0x00; + uint32_t tmp = 0x00; + + /* Check the parameters */ + assert_param(IS_GPIO_ALL_INSTANCE(GPIOx)); + assert_param(IS_GPIO_PIN(GPIO_Pin)); + + /* Configure the port pins */ + while ((GPIO_Pin >> position) != RESET) + { + /* Get current io position */ + iocurrent = (GPIO_Pin) & (1U << position); + + if (iocurrent) + { + /*------------------------- GPIO Mode Configuration --------------------*/ + /* Configure IO in Analog Mode */ + GPIOx->MODER |= (GPIO_MODER_MODE0 << (position * 2)); + + /* Configure the default Alternate Function in current IO */ + GPIOx->AFR[position >> 3] &= ~((uint32_t)0xF << ((uint32_t)(position & (uint32_t)0x07) * 4)) ; + + /* Configure the default value for IO Speed */ + GPIOx->OSPEEDR &= ~(GPIO_OSPEEDR_OSPEED0 << (position * 2)); + + /* Configure the default value IO Output Type */ + GPIOx->OTYPER &= ~(GPIO_OTYPER_OT0 << position) ; + + /* Deactivate the Pull-up and Pull-down resistor for the current IO */ + GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPD0 << (position * 2)); + +#if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) + + /* Deactivate the Control bit of Analog mode for the current IO */ + GPIOx->ASCR &= ~(GPIO_ASCR_ASC0<< position); + +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx */ + + /*------------------------- EXTI Mode Configuration --------------------*/ + /* Clear the External Interrupt or Event for the current IO */ + + tmp = SYSCFG->EXTICR[position >> 2]; + tmp &= (((uint32_t)0x0F) << (4 * (position & 0x03))); + if(tmp == (GPIO_GET_INDEX(GPIOx) << (4 * (position & 0x03)))) + { + tmp = ((uint32_t)0x0F) << (4 * (position & 0x03)); + SYSCFG->EXTICR[position >> 2] &= ~tmp; + + /* Clear EXTI line configuration */ + EXTI->IMR1 &= ~((uint32_t)iocurrent); + EXTI->EMR1 &= ~((uint32_t)iocurrent); + + /* Clear Rising Falling edge configuration */ + EXTI->RTSR1 &= ~((uint32_t)iocurrent); + EXTI->FTSR1 &= ~((uint32_t)iocurrent); + } + } + + position++; + } +} + +/** + * @} + */ + +/** @defgroup GPIO_Exported_Functions_Group2 IO operation functions + * @brief GPIO Read, Write, Toggle, Lock and EXTI management functions. + * +@verbatim + =============================================================================== + ##### IO operation functions ##### + =============================================================================== + +@endverbatim + * @{ + */ + +/** + * @brief Read the specified input port pin. + * @param GPIOx: where x can be (A..H) to select the GPIO peripheral for STM32L4 family + * @param GPIO_Pin: specifies the port bit to read. + * This parameter can be GPIO_PIN_x where x can be (0..15). + * @retval The input port pin value. + */ +GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) +{ + GPIO_PinState bitstatus; + + /* Check the parameters */ + assert_param(IS_GPIO_PIN(GPIO_Pin)); + + if((GPIOx->IDR & GPIO_Pin) != (uint32_t)GPIO_PIN_RESET) + { + bitstatus = GPIO_PIN_SET; + } + else + { + bitstatus = GPIO_PIN_RESET; + } + return bitstatus; +} + +/** + * @brief Set or clear the selected data port bit. + * + * @note This function uses GPIOx_BSRR and GPIOx_BRR registers to allow atomic read/modify + * accesses. In this way, there is no risk of an IRQ occurring between + * the read and the modify access. + * + * @param GPIOx: where x can be (A..H) to select the GPIO peripheral for STM32L4 family + * @param GPIO_Pin: specifies the port bit to be written. + * This parameter can be one of GPIO_PIN_x where x can be (0..15). + * @param PinState: specifies the value to be written to the selected bit. + * This parameter can be one of the GPIO_PinState enum values: + * @arg GPIO_PIN_RESET: to clear the port pin + * @arg GPIO_PIN_SET: to set the port pin + * @retval None + */ +void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState) +{ + /* Check the parameters */ + assert_param(IS_GPIO_PIN(GPIO_Pin)); + assert_param(IS_GPIO_PIN_ACTION(PinState)); + + if(PinState != GPIO_PIN_RESET) + { + GPIOx->BSRR = (uint32_t)GPIO_Pin; + } + else + { + GPIOx->BRR = (uint32_t)GPIO_Pin; + } +} + +/** + * @brief Toggle the specified GPIO pin. + * @param GPIOx: where x can be (A..H) to select the GPIO peripheral for STM32L4 family + * @param GPIO_Pin: specifies the pin to be toggled. + * @retval None + */ +void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) +{ + /* Check the parameters */ + assert_param(IS_GPIO_PIN(GPIO_Pin)); + + GPIOx->ODR ^= GPIO_Pin; +} + +/** +* @brief Lock GPIO Pins configuration registers. + * @note The locked registers are GPIOx_MODER, GPIOx_OTYPER, GPIOx_OSPEEDR, + * GPIOx_PUPDR, GPIOx_AFRL and GPIOx_AFRH. + * @note The configuration of the locked GPIO pins can no longer be modified + * until the next reset. + * @param GPIOx: where x can be (A..H) to select the GPIO peripheral for STM32L4 family + * @param GPIO_Pin: specifies the port bits to be locked. + * This parameter can be any combination of GPIO_Pin_x where x can be (0..15). + * @retval None + */ +HAL_StatusTypeDef HAL_GPIO_LockPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) +{ + __IO uint32_t tmp = GPIO_LCKR_LCKK; + + /* Check the parameters */ + assert_param(IS_GPIO_LOCK_INSTANCE(GPIOx)); + assert_param(IS_GPIO_PIN(GPIO_Pin)); + + /* Apply lock key write sequence */ + tmp |= GPIO_Pin; + /* Set LCKx bit(s): LCKK='1' + LCK[15-0] */ + GPIOx->LCKR = tmp; + /* Reset LCKx bit(s): LCKK='0' + LCK[15-0] */ + GPIOx->LCKR = GPIO_Pin; + /* Set LCKx bit(s): LCKK='1' + LCK[15-0] */ + GPIOx->LCKR = tmp; + /* Read LCKK bit*/ + tmp = GPIOx->LCKR; + + if((GPIOx->LCKR & GPIO_LCKR_LCKK) != RESET) + { + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Handle EXTI interrupt request. + * @param GPIO_Pin: Specifies the port pin connected to corresponding EXTI line. + * @retval None + */ +void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin) +{ + /* EXTI line interrupt detected */ + if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != RESET) + { + __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin); + HAL_GPIO_EXTI_Callback(GPIO_Pin); + } +} + +/** + * @brief EXTI line detection callback. + * @param GPIO_Pin: Specifies the port pin connected to corresponding EXTI line. + * @retval None + */ +__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(GPIO_Pin); + + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_GPIO_EXTI_Callback could be implemented in the user file + */ +} + +/** + * @} + */ + + +/** + * @} + */ + +#endif /* HAL_GPIO_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_i2c.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_i2c.c new file mode 100644 index 0000000..63d38c3 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_i2c.c @@ -0,0 +1,4868 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_i2c.c + * @author MCD Application Team + * @brief I2C HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Inter Integrated Circuit (I2C) peripheral: + * + Initialization and de-initialization functions + * + IO operation functions + * + Peripheral State and Errors functions + * + @verbatim + ============================================================================== + ##### How to use this driver ##### + ============================================================================== + [..] + The I2C HAL driver can be used as follows: + + (#) Declare a I2C_HandleTypeDef handle structure, for example: + I2C_HandleTypeDef hi2c; + + (#)Initialize the I2C low level resources by implementing the HAL_I2C_MspInit() API: + (##) Enable the I2Cx interface clock + (##) I2C pins configuration + (+++) Enable the clock for the I2C GPIOs + (+++) Configure I2C pins as alternate function open-drain + (##) NVIC configuration if you need to use interrupt process + (+++) Configure the I2Cx interrupt priority + (+++) Enable the NVIC I2C IRQ Channel + (##) DMA Configuration if you need to use DMA process + (+++) Declare a DMA_HandleTypeDef handle structure for the transmit or receive channel + (+++) Enable the DMAx interface clock using + (+++) Configure the DMA handle parameters + (+++) Configure the DMA Tx or Rx channel + (+++) Associate the initialized DMA handle to the hi2c DMA Tx or Rx handle + (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on + the DMA Tx or Rx channel + + (#) Configure the Communication Clock Timing, Own Address1, Master Addressing mode, Dual Addressing mode, + Own Address2, Own Address2 Mask, General call and Nostretch mode in the hi2c Init structure. + + (#) Initialize the I2C registers by calling the HAL_I2C_Init(), configures also the low level Hardware + (GPIO, CLOCK, NVIC...etc) by calling the customized HAL_I2C_MspInit(&hi2c) API. + + (#) To check if target device is ready for communication, use the function HAL_I2C_IsDeviceReady() + + (#) For I2C IO and IO MEM operations, three operation modes are available within this driver : + + *** Polling mode IO operation *** + ================================= + [..] + (+) Transmit in master mode an amount of data in blocking mode using HAL_I2C_Master_Transmit() + (+) Receive in master mode an amount of data in blocking mode using HAL_I2C_Master_Receive() + (+) Transmit in slave mode an amount of data in blocking mode using HAL_I2C_Slave_Transmit() + (+) Receive in slave mode an amount of data in blocking mode using HAL_I2C_Slave_Receive() + + *** Polling mode IO MEM operation *** + ===================================== + [..] + (+) Write an amount of data in blocking mode to a specific memory address using HAL_I2C_Mem_Write() + (+) Read an amount of data in blocking mode from a specific memory address using HAL_I2C_Mem_Read() + + + *** Interrupt mode IO operation *** + =================================== + [..] + (+) Transmit in master mode an amount of data in non-blocking mode using HAL_I2C_Master_Transmit_IT() + (+) At transmission end of transfer, HAL_I2C_MasterTxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_MasterTxCpltCallback() + (+) Receive in master mode an amount of data in non-blocking mode using HAL_I2C_Master_Receive_IT() + (+) At reception end of transfer, HAL_I2C_MasterRxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_MasterRxCpltCallback() + (+) Transmit in slave mode an amount of data in non-blocking mode using HAL_I2C_Slave_Transmit_IT() + (+) At transmission end of transfer, HAL_I2C_SlaveTxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_SlaveTxCpltCallback() + (+) Receive in slave mode an amount of data in non-blocking mode using HAL_I2C_Slave_Receive_IT() + (+) At reception end of transfer, HAL_I2C_SlaveRxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_SlaveRxCpltCallback() + (+) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_I2C_ErrorCallback() + (+) Abort a master I2C process communication with Interrupt using HAL_I2C_Master_Abort_IT() + (+) End of abort process, HAL_I2C_AbortCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_AbortCpltCallback() + (+) Discard a slave I2C process communication using __HAL_I2C_GENERATE_NACK() macro. + This action will inform Master to generate a Stop condition to discard the communication. + + + *** Interrupt mode IO sequential operation *** + ============================================== + [..] + (@) These interfaces allow to manage a sequential transfer with a repeated start condition + when a direction change during transfer + [..] + (+) A specific option field manage the different steps of a sequential transfer + (+) Option field values are defined through @ref I2C_XFEROPTIONS and are listed below: + (++) I2C_FIRST_AND_LAST_FRAME: No sequential usage, functionnal is same as associated interfaces in no sequential mode + (++) I2C_FIRST_FRAME: Sequential usage, this option allow to manage a sequence with start condition, address + and data to transfer without a final stop condition + (++) I2C_FIRST_AND_NEXT_FRAME: Sequential usage (Master only), this option allow to manage a sequence with start condition, address + and data to transfer without a final stop condition, an then permit a call the same master sequential interface + several times (like HAL_I2C_Master_Sequential_Transmit_IT() then HAL_I2C_Master_Sequential_Transmit_IT()) + (++) I2C_NEXT_FRAME: Sequential usage, this option allow to manage a sequence with a restart condition, address + and with new data to transfer if the direction change or manage only the new data to transfer + if no direction change and without a final stop condition in both cases + (++) I2C_LAST_FRAME: Sequential usage, this option allow to manage a sequance with a restart condition, address + and with new data to transfer if the direction change or manage only the new data to transfer + if no direction change and with a final stop condition in both cases + + (+) Differents sequential I2C interfaces are listed below: + (++) Sequential transmit in master I2C mode an amount of data in non-blocking mode using HAL_I2C_Master_Sequential_Transmit_IT() + (+++) At transmission end of current frame transfer, HAL_I2C_MasterTxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_MasterTxCpltCallback() + (++) Sequential receive in master I2C mode an amount of data in non-blocking mode using HAL_I2C_Master_Sequential_Receive_IT() + (+++) At reception end of current frame transfer, HAL_I2C_MasterRxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_MasterRxCpltCallback() + (++) Abort a master I2C process communication with Interrupt using HAL_I2C_Master_Abort_IT() + (+++) End of abort process, HAL_I2C_AbortCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_AbortCpltCallback() + (++) Enable/disable the Address listen mode in slave I2C mode using HAL_I2C_EnableListen_IT() HAL_I2C_DisableListen_IT() + (+++) When address slave I2C match, HAL_I2C_AddrCallback() is executed and user can + add his own code to check the Address Match Code and the transmission direction request by master (Write/Read). + (+++) At Listen mode end HAL_I2C_ListenCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_ListenCpltCallback() + (++) Sequential transmit in slave I2C mode an amount of data in non-blocking mode using HAL_I2C_Slave_Sequential_Transmit_IT() + (+++) At transmission end of current frame transfer, HAL_I2C_SlaveTxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_SlaveTxCpltCallback() + (++) Sequential receive in slave I2C mode an amount of data in non-blocking mode using HAL_I2C_Slave_Sequential_Receive_IT() + (+++) At reception end of current frame transfer, HAL_I2C_SlaveRxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_SlaveRxCpltCallback() + (++) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_I2C_ErrorCallback() + (++) Abort a master I2C process communication with Interrupt using HAL_I2C_Master_Abort_IT() + (++) End of abort process, HAL_I2C_AbortCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_AbortCpltCallback() + (++) Discard a slave I2C process communication using __HAL_I2C_GENERATE_NACK() macro. + This action will inform Master to generate a Stop condition to discard the communication. + + *** Interrupt mode IO MEM operation *** + ======================================= + [..] + (+) Write an amount of data in non-blocking mode with Interrupt to a specific memory address using + HAL_I2C_Mem_Write_IT() + (+) At Memory end of write transfer, HAL_I2C_MemTxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_MemTxCpltCallback() + (+) Read an amount of data in non-blocking mode with Interrupt from a specific memory address using + HAL_I2C_Mem_Read_IT() + (+) At Memory end of read transfer, HAL_I2C_MemRxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_MemRxCpltCallback() + (+) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_I2C_ErrorCallback() + + *** DMA mode IO operation *** + ============================== + [..] + (+) Transmit in master mode an amount of data in non-blocking mode (DMA) using + HAL_I2C_Master_Transmit_DMA() + (+) At transmission end of transfer, HAL_I2C_MasterTxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_MasterTxCpltCallback() + (+) Receive in master mode an amount of data in non-blocking mode (DMA) using + HAL_I2C_Master_Receive_DMA() + (+) At reception end of transfer, HAL_I2C_MasterRxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_MasterRxCpltCallback() + (+) Transmit in slave mode an amount of data in non-blocking mode (DMA) using + HAL_I2C_Slave_Transmit_DMA() + (+) At transmission end of transfer, HAL_I2C_SlaveTxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_SlaveTxCpltCallback() + (+) Receive in slave mode an amount of data in non-blocking mode (DMA) using + HAL_I2C_Slave_Receive_DMA() + (+) At reception end of transfer, HAL_I2C_SlaveRxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_SlaveRxCpltCallback() + (+) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_I2C_ErrorCallback() + (+) Abort a master I2C process communication with Interrupt using HAL_I2C_Master_Abort_IT() + (+) End of abort process, HAL_I2C_AbortCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_AbortCpltCallback() + (+) Discard a slave I2C process communication using __HAL_I2C_GENERATE_NACK() macro. + This action will inform Master to generate a Stop condition to discard the communication. + + *** DMA mode IO MEM operation *** + ================================= + [..] + (+) Write an amount of data in non-blocking mode with DMA to a specific memory address using + HAL_I2C_Mem_Write_DMA() + (+) At Memory end of write transfer, HAL_I2C_MemTxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_MemTxCpltCallback() + (+) Read an amount of data in non-blocking mode with DMA from a specific memory address using + HAL_I2C_Mem_Read_DMA() + (+) At Memory end of read transfer, HAL_I2C_MemRxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_MemRxCpltCallback() + (+) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_I2C_ErrorCallback() + + + *** I2C HAL driver macros list *** + ================================== + [..] + Below the list of most used macros in I2C HAL driver. + + (+) __HAL_I2C_ENABLE: Enable the I2C peripheral + (+) __HAL_I2C_DISABLE: Disable the I2C peripheral + (+) __HAL_I2C_GENERATE_NACK: Generate a Non-Acknowledge I2C peripheral in Slave mode + (+) __HAL_I2C_GET_FLAG: Check whether the specified I2C flag is set or not + (+) __HAL_I2C_CLEAR_FLAG: Clear the specified I2C pending flag + (+) __HAL_I2C_ENABLE_IT: Enable the specified I2C interrupt + (+) __HAL_I2C_DISABLE_IT: Disable the specified I2C interrupt + + [..] + (@) You can refer to the I2C HAL driver header file for more useful macros + + @endverbatim + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup I2C I2C + * @brief I2C HAL module driver + * @{ + */ + +#ifdef HAL_I2C_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ + +/** @defgroup I2C_Private_Define I2C Private Define + * @{ + */ +#define TIMING_CLEAR_MASK (0xF0FFFFFFU) /*!< I2C TIMING clear register Mask */ +#define I2C_TIMEOUT_ADDR (10000U) /*!< 10 s */ +#define I2C_TIMEOUT_BUSY (25U) /*!< 25 ms */ +#define I2C_TIMEOUT_DIR (25U) /*!< 25 ms */ +#define I2C_TIMEOUT_RXNE (25U) /*!< 25 ms */ +#define I2C_TIMEOUT_STOPF (25U) /*!< 25 ms */ +#define I2C_TIMEOUT_TC (25U) /*!< 25 ms */ +#define I2C_TIMEOUT_TCR (25U) /*!< 25 ms */ +#define I2C_TIMEOUT_TXIS (25U) /*!< 25 ms */ +#define I2C_TIMEOUT_FLAG (25U) /*!< 25 ms */ + +#define MAX_NBYTE_SIZE 255U +#define SlaveAddr_SHIFT 7U +#define SlaveAddr_MSK 0x06U + +/* Private define for @ref PreviousState usage */ +#define I2C_STATE_MSK ((uint32_t)((HAL_I2C_STATE_BUSY_TX | HAL_I2C_STATE_BUSY_RX) & (~((uint32_t)HAL_I2C_STATE_READY)))) /*!< Mask State define, keep only RX and TX bits */ +#define I2C_STATE_NONE ((uint32_t)(HAL_I2C_MODE_NONE)) /*!< Default Value */ +#define I2C_STATE_MASTER_BUSY_TX ((uint32_t)((HAL_I2C_STATE_BUSY_TX & I2C_STATE_MSK) | HAL_I2C_MODE_MASTER)) /*!< Master Busy TX, combinaison of State LSB and Mode enum */ +#define I2C_STATE_MASTER_BUSY_RX ((uint32_t)((HAL_I2C_STATE_BUSY_RX & I2C_STATE_MSK) | HAL_I2C_MODE_MASTER)) /*!< Master Busy RX, combinaison of State LSB and Mode enum */ +#define I2C_STATE_SLAVE_BUSY_TX ((uint32_t)((HAL_I2C_STATE_BUSY_TX & I2C_STATE_MSK) | HAL_I2C_MODE_SLAVE)) /*!< Slave Busy TX, combinaison of State LSB and Mode enum */ +#define I2C_STATE_SLAVE_BUSY_RX ((uint32_t)((HAL_I2C_STATE_BUSY_RX & I2C_STATE_MSK) | HAL_I2C_MODE_SLAVE)) /*!< Slave Busy RX, combinaison of State LSB and Mode enum */ +#define I2C_STATE_MEM_BUSY_TX ((uint32_t)((HAL_I2C_STATE_BUSY_TX & I2C_STATE_MSK) | HAL_I2C_MODE_MEM)) /*!< Memory Busy TX, combinaison of State LSB and Mode enum */ +#define I2C_STATE_MEM_BUSY_RX ((uint32_t)((HAL_I2C_STATE_BUSY_RX & I2C_STATE_MSK) | HAL_I2C_MODE_MEM)) /*!< Memory Busy RX, combinaison of State LSB and Mode enum */ + + +/* Private define to centralize the enable/disable of Interrupts */ +#define I2C_XFER_TX_IT (0x00000001U) +#define I2C_XFER_RX_IT (0x00000002U) +#define I2C_XFER_LISTEN_IT (0x00000004U) + +#define I2C_XFER_ERROR_IT (0x00000011U) +#define I2C_XFER_CPLT_IT (0x00000012U) +#define I2C_XFER_RELOAD_IT (0x00000012U) + +/* Private define Sequential Transfer Options default/reset value */ +#define I2C_NO_OPTION_FRAME (0xFFFF0000U) +/** + * @} + */ + +/* Private macro -------------------------------------------------------------*/ +#define I2C_GET_DMA_REMAIN_DATA(__HANDLE__) ((((__HANDLE__)->State) == HAL_I2C_STATE_BUSY_TX) ? \ + ((uint32_t)(((DMA_Channel_TypeDef *)(__HANDLE__)->hdmatx->Instance)->CNDTR)) : \ + ((uint32_t)(((DMA_Channel_TypeDef *)(__HANDLE__)->hdmarx->Instance)->CNDTR))) + +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ + +/** @defgroup I2C_Private_Functions I2C Private Functions + * @{ + */ +/* Private functions to handle DMA transfer */ +static void I2C_DMAMasterTransmitCplt(DMA_HandleTypeDef *hdma); +static void I2C_DMAMasterReceiveCplt(DMA_HandleTypeDef *hdma); +static void I2C_DMASlaveTransmitCplt(DMA_HandleTypeDef *hdma); +static void I2C_DMASlaveReceiveCplt(DMA_HandleTypeDef *hdma); +static void I2C_DMAError(DMA_HandleTypeDef *hdma); +static void I2C_DMAAbort(DMA_HandleTypeDef *hdma); + +/* Private functions to handle IT transfer */ +static void I2C_ITAddrCplt(I2C_HandleTypeDef *hi2c, uint32_t ITFlags); +static void I2C_ITMasterSequentialCplt(I2C_HandleTypeDef *hi2c); +static void I2C_ITSlaveSequentialCplt(I2C_HandleTypeDef *hi2c); +static void I2C_ITMasterCplt(I2C_HandleTypeDef *hi2c, uint32_t ITFlags); +static void I2C_ITSlaveCplt(I2C_HandleTypeDef *hi2c, uint32_t ITFlags); +static void I2C_ITListenCplt(I2C_HandleTypeDef *hi2c, uint32_t ITFlags); +static void I2C_ITError(I2C_HandleTypeDef *hi2c, uint32_t ErrorCode); + +/* Private functions to handle IT transfer */ +static HAL_StatusTypeDef I2C_RequestMemoryWrite(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout, uint32_t Tickstart); +static HAL_StatusTypeDef I2C_RequestMemoryRead(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout, uint32_t Tickstart); + +/* Private functions for I2C transfer IRQ handler */ +static HAL_StatusTypeDef I2C_Master_ISR_IT(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags, uint32_t ITSources); +static HAL_StatusTypeDef I2C_Slave_ISR_IT(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags, uint32_t ITSources); +static HAL_StatusTypeDef I2C_Master_ISR_DMA(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags, uint32_t ITSources); +static HAL_StatusTypeDef I2C_Slave_ISR_DMA(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags, uint32_t ITSources); + +/* Private functions to handle flags during polling transfer */ +static HAL_StatusTypeDef I2C_WaitOnFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, FlagStatus Status, uint32_t Timeout, uint32_t Tickstart); +static HAL_StatusTypeDef I2C_WaitOnTXISFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart); +static HAL_StatusTypeDef I2C_WaitOnRXNEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart); +static HAL_StatusTypeDef I2C_WaitOnSTOPFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart); +static HAL_StatusTypeDef I2C_IsAcknowledgeFailed(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart); + +/* Private functions to centralize the enable/disable of Interrupts */ +static HAL_StatusTypeDef I2C_Enable_IRQ(I2C_HandleTypeDef *hi2c, uint16_t InterruptRequest); +static HAL_StatusTypeDef I2C_Disable_IRQ(I2C_HandleTypeDef *hi2c, uint16_t InterruptRequest); + +/* Private functions to flush TXDR register */ +static void I2C_Flush_TXDR(I2C_HandleTypeDef *hi2c); + +/* Private functions to handle start, restart or stop a transfer */ +static void I2C_TransferConfig(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t Size, uint32_t Mode, uint32_t Request); +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup I2C_Exported_Functions I2C Exported Functions + * @{ + */ + +/** @defgroup I2C_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions + * +@verbatim + =============================================================================== + ##### Initialization and de-initialization functions ##### + =============================================================================== + [..] This subsection provides a set of functions allowing to initialize and + deinitialize the I2Cx peripheral: + + (+) User must Implement HAL_I2C_MspInit() function in which he configures + all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ). + + (+) Call the function HAL_I2C_Init() to configure the selected device with + the selected configuration: + (++) Clock Timing + (++) Own Address 1 + (++) Addressing mode (Master, Slave) + (++) Dual Addressing mode + (++) Own Address 2 + (++) Own Address 2 Mask + (++) General call mode + (++) Nostretch mode + + (+) Call the function HAL_I2C_DeInit() to restore the default configuration + of the selected I2Cx peripheral. + +@endverbatim + * @{ + */ + +/** + * @brief Initializes the I2C according to the specified parameters + * in the I2C_InitTypeDef and initialize the associated handle. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c) +{ + /* Check the I2C handle allocation */ + if (hi2c == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance)); + assert_param(IS_I2C_OWN_ADDRESS1(hi2c->Init.OwnAddress1)); + assert_param(IS_I2C_ADDRESSING_MODE(hi2c->Init.AddressingMode)); + assert_param(IS_I2C_DUAL_ADDRESS(hi2c->Init.DualAddressMode)); + assert_param(IS_I2C_OWN_ADDRESS2(hi2c->Init.OwnAddress2)); + assert_param(IS_I2C_OWN_ADDRESS2_MASK(hi2c->Init.OwnAddress2Masks)); + assert_param(IS_I2C_GENERAL_CALL(hi2c->Init.GeneralCallMode)); + assert_param(IS_I2C_NO_STRETCH(hi2c->Init.NoStretchMode)); + + if (hi2c->State == HAL_I2C_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hi2c->Lock = HAL_UNLOCKED; + + /* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */ + HAL_I2C_MspInit(hi2c); + } + + hi2c->State = HAL_I2C_STATE_BUSY; + + /* Disable the selected I2C peripheral */ + __HAL_I2C_DISABLE(hi2c); + + /*---------------------------- I2Cx TIMINGR Configuration ------------------*/ + /* Configure I2Cx: Frequency range */ + hi2c->Instance->TIMINGR = hi2c->Init.Timing & TIMING_CLEAR_MASK; + + /*---------------------------- I2Cx OAR1 Configuration ---------------------*/ + /* Disable Own Address1 before set the Own Address1 configuration */ + hi2c->Instance->OAR1 &= ~I2C_OAR1_OA1EN; + + /* Configure I2Cx: Own Address1 and ack own address1 mode */ + if (hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_7BIT) + { + hi2c->Instance->OAR1 = (I2C_OAR1_OA1EN | hi2c->Init.OwnAddress1); + } + else /* I2C_ADDRESSINGMODE_10BIT */ + { + hi2c->Instance->OAR1 = (I2C_OAR1_OA1EN | I2C_OAR1_OA1MODE | hi2c->Init.OwnAddress1); + } + + /*---------------------------- I2Cx CR2 Configuration ----------------------*/ + /* Configure I2Cx: Addressing Master mode */ + if (hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_10BIT) + { + hi2c->Instance->CR2 = (I2C_CR2_ADD10); + } + /* Enable the AUTOEND by default, and enable NACK (should be disable only during Slave process */ + hi2c->Instance->CR2 |= (I2C_CR2_AUTOEND | I2C_CR2_NACK); + + /*---------------------------- I2Cx OAR2 Configuration ---------------------*/ + /* Disable Own Address2 before set the Own Address2 configuration */ + hi2c->Instance->OAR2 &= ~I2C_DUALADDRESS_ENABLE; + + /* Configure I2Cx: Dual mode and Own Address2 */ + hi2c->Instance->OAR2 = (hi2c->Init.DualAddressMode | hi2c->Init.OwnAddress2 | (hi2c->Init.OwnAddress2Masks << 8)); + + /*---------------------------- I2Cx CR1 Configuration ----------------------*/ + /* Configure I2Cx: Generalcall and NoStretch mode */ + hi2c->Instance->CR1 = (hi2c->Init.GeneralCallMode | hi2c->Init.NoStretchMode); + + /* Enable the selected I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->Mode = HAL_I2C_MODE_NONE; + + return HAL_OK; +} + +/** + * @brief DeInitialize the I2C peripheral. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_DeInit(I2C_HandleTypeDef *hi2c) +{ + /* Check the I2C handle allocation */ + if (hi2c == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance)); + + hi2c->State = HAL_I2C_STATE_BUSY; + + /* Disable the I2C Peripheral Clock */ + __HAL_I2C_DISABLE(hi2c); + + /* DeInit the low level hardware: GPIO, CLOCK, NVIC */ + HAL_I2C_MspDeInit(hi2c); + + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + hi2c->State = HAL_I2C_STATE_RESET; + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Release Lock */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; +} + +/** + * @brief Initialize the I2C MSP. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitialize the I2C MSP. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_MspDeInit(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_MspDeInit could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup I2C_Exported_Functions_Group2 Input and Output operation functions + * @brief Data transfers functions + * +@verbatim + =============================================================================== + ##### IO operation functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to manage the I2C data + transfers. + + (#) There are two modes of transfer: + (++) Blocking mode : The communication is performed in the polling mode. + The status of all data processing is returned by the same function + after finishing transfer. + (++) No-Blocking mode : The communication is performed using Interrupts + or DMA. These functions return the status of the transfer startup. + The end of the data processing will be indicated through the + dedicated I2C IRQ when using Interrupt mode or the DMA IRQ when + using DMA mode. + + (#) Blocking mode functions are : + (++) HAL_I2C_Master_Transmit() + (++) HAL_I2C_Master_Receive() + (++) HAL_I2C_Slave_Transmit() + (++) HAL_I2C_Slave_Receive() + (++) HAL_I2C_Mem_Write() + (++) HAL_I2C_Mem_Read() + (++) HAL_I2C_IsDeviceReady() + + (#) No-Blocking mode functions with Interrupt are : + (++) HAL_I2C_Master_Transmit_IT() + (++) HAL_I2C_Master_Receive_IT() + (++) HAL_I2C_Slave_Transmit_IT() + (++) HAL_I2C_Slave_Receive_IT() + (++) HAL_I2C_Mem_Write_IT() + (++) HAL_I2C_Mem_Read_IT() + + (#) No-Blocking mode functions with DMA are : + (++) HAL_I2C_Master_Transmit_DMA() + (++) HAL_I2C_Master_Receive_DMA() + (++) HAL_I2C_Slave_Transmit_DMA() + (++) HAL_I2C_Slave_Receive_DMA() + (++) HAL_I2C_Mem_Write_DMA() + (++) HAL_I2C_Mem_Read_DMA() + + (#) A set of Transfer Complete Callbacks are provided in non Blocking mode: + (++) HAL_I2C_MemTxCpltCallback() + (++) HAL_I2C_MemRxCpltCallback() + (++) HAL_I2C_MasterTxCpltCallback() + (++) HAL_I2C_MasterRxCpltCallback() + (++) HAL_I2C_SlaveTxCpltCallback() + (++) HAL_I2C_SlaveRxCpltCallback() + (++) HAL_I2C_ErrorCallback() + +@endverbatim + * @{ + */ + +/** + * @brief Transmits in master mode an amount of data in blocking mode. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shift at right before call interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + uint32_t tickstart = 0U; + + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_MASTER; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferISR = NULL; + + /* Send Slave Address */ + /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */ + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_RELOAD_MODE, I2C_GENERATE_START_WRITE); + } + else + { + hi2c->XferSize = hi2c->XferCount; + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_GENERATE_START_WRITE); + } + + while (hi2c->XferCount > 0U) + { + /* Wait until TXIS flag is set */ + if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + /* Write data to TXDR */ + hi2c->Instance->TXDR = (*hi2c->pBuffPtr++); + hi2c->XferCount--; + hi2c->XferSize--; + + if ((hi2c->XferSize == 0U) && (hi2c->XferCount != 0U)) + { + /* Wait until TCR flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_RELOAD_MODE, I2C_NO_STARTSTOP); + } + else + { + hi2c->XferSize = hi2c->XferCount; + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP); + } + } + } + + /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */ + /* Wait until STOPF flag is set */ + if (I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + /* Clear STOP Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); + + /* Clear Configuration Register 2 */ + I2C_RESET_CR2(hi2c); + + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receives in master mode an amount of data in blocking mode. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shift at right before call interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + uint32_t tickstart = 0U; + + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_MASTER; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferISR = NULL; + + /* Send Slave Address */ + /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */ + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_RELOAD_MODE, I2C_GENERATE_START_READ); + } + else + { + hi2c->XferSize = hi2c->XferCount; + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_GENERATE_START_READ); + } + + while (hi2c->XferCount > 0U) + { + /* Wait until RXNE flag is set */ + if (I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + /* Read data from RXDR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->RXDR; + hi2c->XferSize--; + hi2c->XferCount--; + + if ((hi2c->XferSize == 0U) && (hi2c->XferCount != 0U)) + { + /* Wait until TCR flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_RELOAD_MODE, I2C_NO_STARTSTOP); + } + else + { + hi2c->XferSize = hi2c->XferCount; + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP); + } + } + } + + /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */ + /* Wait until STOPF flag is set */ + if (I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + /* Clear STOP Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); + + /* Clear Configuration Register 2 */ + I2C_RESET_CR2(hi2c); + + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Transmits in slave mode an amount of data in blocking mode. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Slave_Transmit(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + uint32_t tickstart = 0U; + + if (hi2c->State == HAL_I2C_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_SLAVE; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferISR = NULL; + + /* Enable Address Acknowledge */ + hi2c->Instance->CR2 &= ~I2C_CR2_NACK; + + /* Wait until ADDR flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, RESET, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + hi2c->Instance->CR2 |= I2C_CR2_NACK; + return HAL_TIMEOUT; + } + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR); + + /* If 10bit addressing mode is selected */ + if (hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_10BIT) + { + /* Wait until ADDR flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, RESET, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + hi2c->Instance->CR2 |= I2C_CR2_NACK; + return HAL_TIMEOUT; + } + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR); + } + + /* Wait until DIR flag is set Transmitter mode */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_DIR, RESET, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + hi2c->Instance->CR2 |= I2C_CR2_NACK; + return HAL_TIMEOUT; + } + + while (hi2c->XferCount > 0U) + { + /* Wait until TXIS flag is set */ + if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + hi2c->Instance->CR2 |= I2C_CR2_NACK; + + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + /* Write data to TXDR */ + hi2c->Instance->TXDR = (*hi2c->pBuffPtr++); + hi2c->XferCount--; + } + + /* Wait until STOP flag is set */ + if (I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + hi2c->Instance->CR2 |= I2C_CR2_NACK; + + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Normal use case for Transmitter mode */ + /* A NACK is generated to confirm the end of transfer */ + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + } + else + { + return HAL_TIMEOUT; + } + } + + /* Clear STOP flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); + + /* Wait until BUSY flag is reset */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + hi2c->Instance->CR2 |= I2C_CR2_NACK; + return HAL_TIMEOUT; + } + + /* Disable Address Acknowledge */ + hi2c->Instance->CR2 |= I2C_CR2_NACK; + + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive in slave mode an amount of data in blocking mode + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Slave_Receive(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + uint32_t tickstart = 0U; + + if (hi2c->State == HAL_I2C_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_SLAVE; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferISR = NULL; + + /* Enable Address Acknowledge */ + hi2c->Instance->CR2 &= ~I2C_CR2_NACK; + + /* Wait until ADDR flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, RESET, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + hi2c->Instance->CR2 |= I2C_CR2_NACK; + return HAL_TIMEOUT; + } + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR); + + /* Wait until DIR flag is reset Receiver mode */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_DIR, SET, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + hi2c->Instance->CR2 |= I2C_CR2_NACK; + return HAL_TIMEOUT; + } + + while (hi2c->XferCount > 0U) + { + /* Wait until RXNE flag is set */ + if (I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + hi2c->Instance->CR2 |= I2C_CR2_NACK; + + /* Store Last receive data if any */ + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == SET) + { + /* Read data from RXDR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->RXDR; + hi2c->XferCount--; + } + + if (hi2c->ErrorCode == HAL_I2C_ERROR_TIMEOUT) + { + return HAL_TIMEOUT; + } + else + { + return HAL_ERROR; + } + } + + /* Read data from RXDR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->RXDR; + hi2c->XferCount--; + } + + /* Wait until STOP flag is set */ + if (I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + hi2c->Instance->CR2 |= I2C_CR2_NACK; + + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + /* Clear STOP flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); + + /* Wait until BUSY flag is reset */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + hi2c->Instance->CR2 |= I2C_CR2_NACK; + return HAL_TIMEOUT; + } + + /* Disable Address Acknowledge */ + hi2c->Instance->CR2 |= I2C_CR2_NACK; + + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Transmit in master mode an amount of data in non-blocking mode with Interrupt + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shift at right before call interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size) +{ + uint32_t xfermode = 0U; + + if (hi2c->State == HAL_I2C_STATE_READY) + { + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_MASTER; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferISR = I2C_Master_ISR_IT; + + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + xfermode = I2C_RELOAD_MODE; + } + else + { + hi2c->XferSize = hi2c->XferCount; + xfermode = I2C_AUTOEND_MODE; + } + + /* Send Slave Address */ + /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE */ + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, xfermode, I2C_GENERATE_START_WRITE); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable ERR, TC, STOP, NACK, TXI interrupt */ + /* possible to enable all of these */ + /* I2C_IT_ERRI | I2C_IT_TCI| I2C_IT_STOPI| I2C_IT_NACKI | I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */ + I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive in master mode an amount of data in non-blocking mode with Interrupt + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shift at right before call interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Receive_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size) +{ + uint32_t xfermode = 0U; + + if (hi2c->State == HAL_I2C_STATE_READY) + { + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_MASTER; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferISR = I2C_Master_ISR_IT; + + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + xfermode = I2C_RELOAD_MODE; + } + else + { + hi2c->XferSize = hi2c->XferCount; + xfermode = I2C_AUTOEND_MODE; + } + + /* Send Slave Address */ + /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE */ + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, xfermode, I2C_GENERATE_START_READ); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable ERR, TC, STOP, NACK, RXI interrupt */ + /* possible to enable all of these */ + /* I2C_IT_ERRI | I2C_IT_TCI| I2C_IT_STOPI| I2C_IT_NACKI | I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */ + I2C_Enable_IRQ(hi2c, I2C_XFER_RX_IT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Transmit in slave mode an amount of data in non-blocking mode with Interrupt + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Slave_Transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size) +{ + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hi2c); + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_SLAVE; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Enable Address Acknowledge */ + hi2c->Instance->CR2 &= ~I2C_CR2_NACK; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferISR = I2C_Slave_ISR_IT; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable ERR, TC, STOP, NACK, TXI interrupt */ + /* possible to enable all of these */ + /* I2C_IT_ERRI | I2C_IT_TCI| I2C_IT_STOPI| I2C_IT_NACKI | I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */ + I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT | I2C_XFER_LISTEN_IT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive in slave mode an amount of data in non-blocking mode with Interrupt + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Slave_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size) +{ + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hi2c); + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_SLAVE; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Enable Address Acknowledge */ + hi2c->Instance->CR2 &= ~I2C_CR2_NACK; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferISR = I2C_Slave_ISR_IT; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable ERR, TC, STOP, NACK, RXI interrupt */ + /* possible to enable all of these */ + /* I2C_IT_ERRI | I2C_IT_TCI| I2C_IT_STOPI| I2C_IT_NACKI | I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */ + I2C_Enable_IRQ(hi2c, I2C_XFER_RX_IT | I2C_XFER_LISTEN_IT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Transmit in master mode an amount of data in non-blocking mode with DMA + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shift at right before call interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size) +{ + uint32_t xfermode = 0U; + + if (hi2c->State == HAL_I2C_STATE_READY) + { + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_MASTER; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferISR = I2C_Master_ISR_DMA; + + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + xfermode = I2C_RELOAD_MODE; + } + else + { + hi2c->XferSize = hi2c->XferCount; + xfermode = I2C_AUTOEND_MODE; + } + + if (hi2c->XferSize > 0U) + { + /* Set the I2C DMA transfer complete callback */ + hi2c->hdmatx->XferCpltCallback = I2C_DMAMasterTransmitCplt; + + /* Set the DMA error callback */ + hi2c->hdmatx->XferErrorCallback = I2C_DMAError; + + /* Set the unused DMA callbacks to NULL */ + hi2c->hdmatx->XferHalfCpltCallback = NULL; + hi2c->hdmatx->XferAbortCallback = NULL; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)pData, (uint32_t)&hi2c->Instance->TXDR, hi2c->XferSize); + + /* Send Slave Address */ + /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */ + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, xfermode, I2C_GENERATE_START_WRITE); + + /* Update XferCount value */ + hi2c->XferCount -= hi2c->XferSize; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + /* Enable ERR and NACK interrupts */ + I2C_Enable_IRQ(hi2c, I2C_XFER_ERROR_IT); + + /* Enable DMA Request */ + hi2c->Instance->CR1 |= I2C_CR1_TXDMAEN; + } + else + { + /* Update Transfer ISR function pointer */ + hi2c->XferISR = I2C_Master_ISR_IT; + + /* Send Slave Address */ + /* Set NBYTES to write and generate START condition */ + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_GENERATE_START_WRITE); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + /* Enable ERR, TC, STOP, NACK, TXI interrupt */ + /* possible to enable all of these */ + /* I2C_IT_ERRI | I2C_IT_TCI| I2C_IT_STOPI| I2C_IT_NACKI | I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */ + I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT); + } + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive in master mode an amount of data in non-blocking mode with DMA + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shift at right before call interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Receive_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size) +{ + uint32_t xfermode = 0U; + + if (hi2c->State == HAL_I2C_STATE_READY) + { + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_MASTER; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferISR = I2C_Master_ISR_DMA; + + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + xfermode = I2C_RELOAD_MODE; + } + else + { + hi2c->XferSize = hi2c->XferCount; + xfermode = I2C_AUTOEND_MODE; + } + + if (hi2c->XferSize > 0U) + { + /* Set the I2C DMA transfer complete callback */ + hi2c->hdmarx->XferCpltCallback = I2C_DMAMasterReceiveCplt; + + /* Set the DMA error callback */ + hi2c->hdmarx->XferErrorCallback = I2C_DMAError; + + /* Set the unused DMA callbacks to NULL */ + hi2c->hdmarx->XferHalfCpltCallback = NULL; + hi2c->hdmarx->XferAbortCallback = NULL; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->RXDR, (uint32_t)pData, hi2c->XferSize); + + /* Send Slave Address */ + /* Set NBYTES to read and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */ + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, xfermode, I2C_GENERATE_START_READ); + + /* Update XferCount value */ + hi2c->XferCount -= hi2c->XferSize; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + /* Enable ERR and NACK interrupts */ + I2C_Enable_IRQ(hi2c, I2C_XFER_ERROR_IT); + + /* Enable DMA Request */ + hi2c->Instance->CR1 |= I2C_CR1_RXDMAEN; + } + else + { + /* Update Transfer ISR function pointer */ + hi2c->XferISR = I2C_Master_ISR_IT; + + /* Send Slave Address */ + /* Set NBYTES to read and generate START condition */ + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_GENERATE_START_READ); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + /* Enable ERR, TC, STOP, NACK, TXI interrupt */ + /* possible to enable all of these */ + /* I2C_IT_ERRI | I2C_IT_TCI| I2C_IT_STOPI| I2C_IT_NACKI | I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */ + I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT); + } + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Transmit in slave mode an amount of data in non-blocking mode with DMA + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Slave_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size) +{ + if (hi2c->State == HAL_I2C_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + /* Process Locked */ + __HAL_LOCK(hi2c); + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_SLAVE; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferISR = I2C_Slave_ISR_DMA; + + /* Set the I2C DMA transfer complete callback */ + hi2c->hdmatx->XferCpltCallback = I2C_DMASlaveTransmitCplt; + + /* Set the DMA error callback */ + hi2c->hdmatx->XferErrorCallback = I2C_DMAError; + + /* Set the unused DMA callbacks to NULL */ + hi2c->hdmatx->XferHalfCpltCallback = NULL; + hi2c->hdmatx->XferAbortCallback = NULL; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)pData, (uint32_t)&hi2c->Instance->TXDR, hi2c->XferSize); + + /* Enable Address Acknowledge */ + hi2c->Instance->CR2 &= ~I2C_CR2_NACK; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + /* Enable ERR, STOP, NACK, ADDR interrupts */ + I2C_Enable_IRQ(hi2c, I2C_XFER_LISTEN_IT); + + /* Enable DMA Request */ + hi2c->Instance->CR1 |= I2C_CR1_TXDMAEN; + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive in slave mode an amount of data in non-blocking mode with DMA + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Slave_Receive_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size) +{ + if (hi2c->State == HAL_I2C_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + /* Process Locked */ + __HAL_LOCK(hi2c); + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_SLAVE; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferISR = I2C_Slave_ISR_DMA; + + /* Set the I2C DMA transfer complete callback */ + hi2c->hdmarx->XferCpltCallback = I2C_DMASlaveReceiveCplt; + + /* Set the DMA error callback */ + hi2c->hdmarx->XferErrorCallback = I2C_DMAError; + + /* Set the unused DMA callbacks to NULL */ + hi2c->hdmarx->XferHalfCpltCallback = NULL; + hi2c->hdmarx->XferAbortCallback = NULL; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->RXDR, (uint32_t)pData, hi2c->XferSize); + + /* Enable Address Acknowledge */ + hi2c->Instance->CR2 &= ~I2C_CR2_NACK; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + /* Enable ERR, STOP, NACK, ADDR interrupts */ + I2C_Enable_IRQ(hi2c, I2C_XFER_LISTEN_IT); + + /* Enable DMA Request */ + hi2c->Instance->CR1 |= I2C_CR1_RXDMAEN; + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} +/** + * @brief Write an amount of data in blocking mode to a specific memory address + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shift at right before call interface + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + uint32_t tickstart = 0U; + + /* Check the parameters */ + assert_param(IS_I2C_MEMADD_SIZE(MemAddSize)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_MEM; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferISR = NULL; + + /* Send Slave Address and Memory Address */ + if (I2C_RequestMemoryWrite(hi2c, DevAddress, MemAddress, MemAddSize, Timeout, tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_ERROR; + } + else + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_TIMEOUT; + } + } + + /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE */ + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_RELOAD_MODE, I2C_NO_STARTSTOP); + } + else + { + hi2c->XferSize = hi2c->XferCount; + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP); + } + + do + { + /* Wait until TXIS flag is set */ + if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + /* Write data to TXDR */ + hi2c->Instance->TXDR = (*hi2c->pBuffPtr++); + hi2c->XferCount--; + hi2c->XferSize--; + + if ((hi2c->XferSize == 0U) && (hi2c->XferCount != 0U)) + { + /* Wait until TCR flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_RELOAD_MODE, I2C_NO_STARTSTOP); + } + else + { + hi2c->XferSize = hi2c->XferCount; + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP); + } + } + + } + while (hi2c->XferCount > 0U); + + /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */ + /* Wait until STOPF flag is reset */ + if (I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + /* Clear STOP Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); + + /* Clear Configuration Register 2 */ + I2C_RESET_CR2(hi2c); + + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Read an amount of data in blocking mode from a specific memory address + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shift at right before call interface + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + uint32_t tickstart = 0U; + + /* Check the parameters */ + assert_param(IS_I2C_MEMADD_SIZE(MemAddSize)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_MEM; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferISR = NULL; + + /* Send Slave Address and Memory Address */ + if (I2C_RequestMemoryRead(hi2c, DevAddress, MemAddress, MemAddSize, Timeout, tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_ERROR; + } + else + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_TIMEOUT; + } + } + + /* Send Slave Address */ + /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */ + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_RELOAD_MODE, I2C_GENERATE_START_READ); + } + else + { + hi2c->XferSize = hi2c->XferCount; + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_GENERATE_START_READ); + } + + do + { + /* Wait until RXNE flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_RXNE, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + /* Read data from RXDR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->RXDR; + hi2c->XferSize--; + hi2c->XferCount--; + + if ((hi2c->XferSize == 0U) && (hi2c->XferCount != 0U)) + { + /* Wait until TCR flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_RELOAD_MODE, I2C_NO_STARTSTOP); + } + else + { + hi2c->XferSize = hi2c->XferCount; + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP); + } + } + } + while (hi2c->XferCount > 0U); + + /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */ + /* Wait until STOPF flag is reset */ + if (I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + /* Clear STOP Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); + + /* Clear Configuration Register 2 */ + I2C_RESET_CR2(hi2c); + + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} +/** + * @brief Write an amount of data in non-blocking mode with Interrupt to a specific memory address + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shift at right before call interface + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Mem_Write_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size) +{ + uint32_t tickstart = 0U; + uint32_t xfermode = 0U; + + /* Check the parameters */ + assert_param(IS_I2C_MEMADD_SIZE(MemAddSize)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_MEM; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferISR = I2C_Master_ISR_IT; + + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + xfermode = I2C_RELOAD_MODE; + } + else + { + hi2c->XferSize = hi2c->XferCount; + xfermode = I2C_AUTOEND_MODE; + } + + /* Send Slave Address and Memory Address */ + if (I2C_RequestMemoryWrite(hi2c, DevAddress, MemAddress, MemAddSize, I2C_TIMEOUT_FLAG, tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_ERROR; + } + else + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_TIMEOUT; + } + } + + /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */ + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, xfermode, I2C_NO_STARTSTOP); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable ERR, TC, STOP, NACK, TXI interrupt */ + /* possible to enable all of these */ + /* I2C_IT_ERRI | I2C_IT_TCI| I2C_IT_STOPI| I2C_IT_NACKI | I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */ + I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Read an amount of data in non-blocking mode with Interrupt from a specific memory address + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shift at right before call interface + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Mem_Read_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size) +{ + uint32_t tickstart = 0U; + uint32_t xfermode = 0U; + + /* Check the parameters */ + assert_param(IS_I2C_MEMADD_SIZE(MemAddSize)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_MEM; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferISR = I2C_Master_ISR_IT; + + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + xfermode = I2C_RELOAD_MODE; + } + else + { + hi2c->XferSize = hi2c->XferCount; + xfermode = I2C_AUTOEND_MODE; + } + + /* Send Slave Address and Memory Address */ + if (I2C_RequestMemoryRead(hi2c, DevAddress, MemAddress, MemAddSize, I2C_TIMEOUT_FLAG, tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_ERROR; + } + else + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_TIMEOUT; + } + } + + /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */ + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, xfermode, I2C_GENERATE_START_READ); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable ERR, TC, STOP, NACK, RXI interrupt */ + /* possible to enable all of these */ + /* I2C_IT_ERRI | I2C_IT_TCI| I2C_IT_STOPI| I2C_IT_NACKI | I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */ + I2C_Enable_IRQ(hi2c, I2C_XFER_RX_IT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} +/** + * @brief Write an amount of data in non-blocking mode with DMA to a specific memory address + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shift at right before call interface + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Mem_Write_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size) +{ + uint32_t tickstart = 0U; + uint32_t xfermode = 0U; + + /* Check the parameters */ + assert_param(IS_I2C_MEMADD_SIZE(MemAddSize)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_MEM; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferISR = I2C_Master_ISR_DMA; + + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + xfermode = I2C_RELOAD_MODE; + } + else + { + hi2c->XferSize = hi2c->XferCount; + xfermode = I2C_AUTOEND_MODE; + } + + /* Send Slave Address and Memory Address */ + if (I2C_RequestMemoryWrite(hi2c, DevAddress, MemAddress, MemAddSize, I2C_TIMEOUT_FLAG, tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_ERROR; + } + else + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_TIMEOUT; + } + } + + /* Set the I2C DMA transfer complete callback */ + hi2c->hdmatx->XferCpltCallback = I2C_DMAMasterTransmitCplt; + + /* Set the DMA error callback */ + hi2c->hdmatx->XferErrorCallback = I2C_DMAError; + + /* Set the unused DMA callbacks to NULL */ + hi2c->hdmatx->XferHalfCpltCallback = NULL; + hi2c->hdmatx->XferAbortCallback = NULL; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)pData, (uint32_t)&hi2c->Instance->TXDR, hi2c->XferSize); + + /* Send Slave Address */ + /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */ + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, xfermode, I2C_NO_STARTSTOP); + + /* Update XferCount value */ + hi2c->XferCount -= hi2c->XferSize; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + /* Enable ERR and NACK interrupts */ + I2C_Enable_IRQ(hi2c, I2C_XFER_ERROR_IT); + + /* Enable DMA Request */ + hi2c->Instance->CR1 |= I2C_CR1_TXDMAEN; + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Reads an amount of data in non-blocking mode with DMA from a specific memory address. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shift at right before call interface + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param pData Pointer to data buffer + * @param Size Amount of data to be read + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Mem_Read_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size) +{ + uint32_t tickstart = 0U; + uint32_t xfermode = 0U; + + /* Check the parameters */ + assert_param(IS_I2C_MEMADD_SIZE(MemAddSize)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_MEM; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferISR = I2C_Master_ISR_DMA; + + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + xfermode = I2C_RELOAD_MODE; + } + else + { + hi2c->XferSize = hi2c->XferCount; + xfermode = I2C_AUTOEND_MODE; + } + + /* Send Slave Address and Memory Address */ + if (I2C_RequestMemoryRead(hi2c, DevAddress, MemAddress, MemAddSize, I2C_TIMEOUT_FLAG, tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_ERROR; + } + else + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_TIMEOUT; + } + } + + /* Set the I2C DMA transfer complete callback */ + hi2c->hdmarx->XferCpltCallback = I2C_DMAMasterReceiveCplt; + + /* Set the DMA error callback */ + hi2c->hdmarx->XferErrorCallback = I2C_DMAError; + + /* Set the unused DMA callbacks to NULL */ + hi2c->hdmarx->XferHalfCpltCallback = NULL; + hi2c->hdmarx->XferAbortCallback = NULL; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->RXDR, (uint32_t)pData, hi2c->XferSize); + + /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */ + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, xfermode, I2C_GENERATE_START_READ); + + /* Update XferCount value */ + hi2c->XferCount -= hi2c->XferSize; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Enable DMA Request */ + hi2c->Instance->CR1 |= I2C_CR1_RXDMAEN; + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + /* Enable ERR and NACK interrupts */ + I2C_Enable_IRQ(hi2c, I2C_XFER_ERROR_IT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Checks if target device is ready for communication. + * @note This function is used with Memory devices + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shift at right before call interface + * @param Trials Number of trials + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_IsDeviceReady(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Trials, uint32_t Timeout) +{ + uint32_t tickstart = 0U; + + __IO uint32_t I2C_Trials = 0U; + + if (hi2c->State == HAL_I2C_STATE_READY) + { + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + hi2c->State = HAL_I2C_STATE_BUSY; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + do + { + /* Generate Start */ + hi2c->Instance->CR2 = I2C_GENERATE_START(hi2c->Init.AddressingMode, DevAddress); + + /* 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*/ + tickstart = HAL_GetTick(); + while ((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == RESET) && (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == RESET) && (hi2c->State != HAL_I2C_STATE_TIMEOUT)) + { + if (Timeout != HAL_MAX_DELAY) + { + if ((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout)) + { + /* Device is ready */ + hi2c->State = HAL_I2C_STATE_READY; + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_TIMEOUT; + } + } + } + + /* Check if the NACKF flag has not been set */ + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == RESET) + { + /* Wait until STOPF flag is reset */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_STOPF, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + /* Clear STOP Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); + + /* Device is ready */ + hi2c->State = HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + /* Wait until STOPF flag is reset */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_STOPF, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + /* Clear NACK Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + + /* Clear STOP Flag, auto generated with autoend*/ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); + } + + /* Check if the maximum allowed number of trials has been reached */ + if (I2C_Trials++ == Trials) + { + /* Generate Stop */ + hi2c->Instance->CR2 |= I2C_CR2_STOP; + + /* Wait until STOPF flag is reset */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_STOPF, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + /* Clear STOP Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); + } + } + while (I2C_Trials < Trials); + + hi2c->State = HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_TIMEOUT; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Sequential transmit in master I2C mode an amount of data in non-blocking mode with Interrupt. + * @note This interface allow to manage repeated start condition when a direction change during transfer + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shift at right before call interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param XferOptions Options of Transfer, value of @ref I2C_XFEROPTIONS + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Sequential_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions) +{ + uint32_t xfermode = 0U; + uint32_t xferrequest = I2C_GENERATE_START_WRITE; + + /* Check the parameters */ + assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hi2c); + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_MASTER; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferOptions = XferOptions; + hi2c->XferISR = I2C_Master_ISR_IT; + + /* If size > MAX_NBYTE_SIZE, use reload mode */ + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + xfermode = I2C_RELOAD_MODE; + } + else + { + hi2c->XferSize = hi2c->XferCount; + xfermode = hi2c->XferOptions; + } + + /* If transfer direction not change, do not generate Restart Condition */ + /* Mean Previous state is same as current state */ + if (hi2c->PreviousState == I2C_STATE_MASTER_BUSY_TX) + { + xferrequest = I2C_NO_STARTSTOP; + } + + /* Send Slave Address and set NBYTES to write */ + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, xfermode, xferrequest); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Sequential receive in master I2C mode an amount of data in non-blocking mode with Interrupt + * @note This interface allow to manage repeated start condition when a direction change during transfer + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shift at right before call interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param XferOptions Options of Transfer, value of @ref I2C_XFEROPTIONS + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Sequential_Receive_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions) +{ + uint32_t xfermode = 0U; + uint32_t xferrequest = I2C_GENERATE_START_READ; + + /* Check the parameters */ + assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hi2c); + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_MASTER; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferOptions = XferOptions; + hi2c->XferISR = I2C_Master_ISR_IT; + + /* If hi2c->XferCount > MAX_NBYTE_SIZE, use reload mode */ + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + xfermode = I2C_RELOAD_MODE; + } + else + { + hi2c->XferSize = hi2c->XferCount; + xfermode = hi2c->XferOptions; + } + + /* If transfer direction not change, do not generate Restart Condition */ + /* Mean Previous state is same as current state */ + if (hi2c->PreviousState == I2C_STATE_MASTER_BUSY_RX) + { + xferrequest = I2C_NO_STARTSTOP; + } + + /* Send Slave Address and set NBYTES to read */ + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, xfermode, xferrequest); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + I2C_Enable_IRQ(hi2c, I2C_XFER_RX_IT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Sequential transmit in slave/device I2C mode an amount of data in non-blocking mode with Interrupt + * @note This interface allow to manage repeated start condition when a direction change during transfer + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param XferOptions Options of Transfer, value of @ref I2C_XFEROPTIONS + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Slave_Sequential_Transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions) +{ + /* Check the parameters */ + assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions)); + + if ((hi2c->State & HAL_I2C_STATE_LISTEN) == HAL_I2C_STATE_LISTEN) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Disable Interrupts, to prevent preemption during treatment in case of multicall */ + I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT | I2C_XFER_TX_IT); + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* I2C cannot manage full duplex exchange so disable previous IT enabled if any */ + /* and then toggle the HAL slave RX state to TX state */ + if (hi2c->State == HAL_I2C_STATE_BUSY_RX_LISTEN) + { + /* Disable associated Interrupts */ + I2C_Disable_IRQ(hi2c, I2C_XFER_RX_IT); + } + + hi2c->State = HAL_I2C_STATE_BUSY_TX_LISTEN; + hi2c->Mode = HAL_I2C_MODE_SLAVE; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Enable Address Acknowledge */ + hi2c->Instance->CR2 &= ~I2C_CR2_NACK; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = XferOptions; + hi2c->XferISR = I2C_Slave_ISR_IT; + + if (I2C_GET_DIR(hi2c) == I2C_DIRECTION_RECEIVE) + { + /* Clear ADDR flag after prepare the transfer parameters */ + /* This action will generate an acknowledge to the Master */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + /* REnable ADDR interrupt */ + I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT | I2C_XFER_LISTEN_IT); + + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Sequential receive in slave/device I2C mode an amount of data in non-blocking mode with Interrupt + * @note This interface allow to manage repeated start condition when a direction change during transfer + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param XferOptions Options of Transfer, value of @ref I2C_XFEROPTIONS + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Slave_Sequential_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions) +{ + /* Check the parameters */ + assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions)); + + if ((hi2c->State & HAL_I2C_STATE_LISTEN) == HAL_I2C_STATE_LISTEN) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Disable Interrupts, to prevent preemption during treatment in case of multicall */ + I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT | I2C_XFER_RX_IT); + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* I2C cannot manage full duplex exchange so disable previous IT enabled if any */ + /* and then toggle the HAL slave TX state to RX state */ + if (hi2c->State == HAL_I2C_STATE_BUSY_TX_LISTEN) + { + /* Disable associated Interrupts */ + I2C_Disable_IRQ(hi2c, I2C_XFER_TX_IT); + } + + hi2c->State = HAL_I2C_STATE_BUSY_RX_LISTEN; + hi2c->Mode = HAL_I2C_MODE_SLAVE; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Enable Address Acknowledge */ + hi2c->Instance->CR2 &= ~I2C_CR2_NACK; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = XferOptions; + hi2c->XferISR = I2C_Slave_ISR_IT; + + if (I2C_GET_DIR(hi2c) == I2C_DIRECTION_TRANSMIT) + { + /* Clear ADDR flag after prepare the transfer parameters */ + /* This action will generate an acknowledge to the Master */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + /* REnable ADDR interrupt */ + I2C_Enable_IRQ(hi2c, I2C_XFER_RX_IT | I2C_XFER_LISTEN_IT); + + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Enable the Address listen mode with Interrupt. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_EnableListen_IT(I2C_HandleTypeDef *hi2c) +{ + if (hi2c->State == HAL_I2C_STATE_READY) + { + hi2c->State = HAL_I2C_STATE_LISTEN; + hi2c->XferISR = I2C_Slave_ISR_IT; + + /* Enable the Address Match interrupt */ + I2C_Enable_IRQ(hi2c, I2C_XFER_LISTEN_IT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Disable the Address listen mode with Interrupt. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_DisableListen_IT(I2C_HandleTypeDef *hi2c) +{ + /* Declaration of tmp to prevent undefined behavior of volatile usage */ + uint32_t tmp; + + /* Disable Address listen mode only if a transfer is not ongoing */ + if (hi2c->State == HAL_I2C_STATE_LISTEN) + { + tmp = (uint32_t)(hi2c->State) & I2C_STATE_MSK; + hi2c->PreviousState = tmp | (uint32_t)(hi2c->Mode); + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->XferISR = NULL; + + /* Disable the Address Match interrupt */ + I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Abort a master I2C IT or DMA process communication with Interrupt. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shift at right before call interface + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Abort_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress) +{ + if (hi2c->Mode == HAL_I2C_MODE_MASTER) + { + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Disable Interrupts */ + I2C_Disable_IRQ(hi2c, I2C_XFER_RX_IT); + I2C_Disable_IRQ(hi2c, I2C_XFER_TX_IT); + + /* Set State at HAL_I2C_STATE_ABORT */ + hi2c->State = HAL_I2C_STATE_ABORT; + + /* Set NBYTES to 1 to generate a dummy read on I2C peripheral */ + /* Set AUTOEND mode, this will generate a NACK then STOP condition to abort the current transfer */ + I2C_TransferConfig(hi2c, DevAddress, 1, I2C_AUTOEND_MODE, I2C_GENERATE_STOP); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + I2C_Enable_IRQ(hi2c, I2C_XFER_CPLT_IT); + + return HAL_OK; + } + else + { + /* Wrong usage of abort function */ + /* This function should be used only in case of abort monitored by master device */ + return HAL_ERROR; + } +} + +/** + * @} + */ + +/** @defgroup I2C_IRQ_Handler_and_Callbacks IRQ Handler and Callbacks + * @{ + */ + +/** + * @brief This function handles I2C event interrupt request. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +void HAL_I2C_EV_IRQHandler(I2C_HandleTypeDef *hi2c) +{ + /* Get current IT Flags and IT sources value */ + uint32_t itflags = READ_REG(hi2c->Instance->ISR); + uint32_t itsources = READ_REG(hi2c->Instance->CR1); + + /* I2C events treatment -------------------------------------*/ + if (hi2c->XferISR != NULL) + { + hi2c->XferISR(hi2c, itflags, itsources); + } +} + +/** + * @brief This function handles I2C error interrupt request. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +void HAL_I2C_ER_IRQHandler(I2C_HandleTypeDef *hi2c) +{ + uint32_t itflags = READ_REG(hi2c->Instance->ISR); + uint32_t itsources = READ_REG(hi2c->Instance->CR1); + + /* I2C Bus error interrupt occurred ------------------------------------*/ + if (((itflags & I2C_FLAG_BERR) != RESET) && ((itsources & I2C_IT_ERRI) != RESET)) + { + hi2c->ErrorCode |= HAL_I2C_ERROR_BERR; + + /* Clear BERR flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_BERR); + } + + /* I2C Over-Run/Under-Run interrupt occurred ----------------------------------------*/ + if (((itflags & I2C_FLAG_OVR) != RESET) && ((itsources & I2C_IT_ERRI) != RESET)) + { + hi2c->ErrorCode |= HAL_I2C_ERROR_OVR; + + /* Clear OVR flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_OVR); + } + + /* I2C Arbitration Loss error interrupt occurred -------------------------------------*/ + if (((itflags & I2C_FLAG_ARLO) != RESET) && ((itsources & I2C_IT_ERRI) != RESET)) + { + hi2c->ErrorCode |= HAL_I2C_ERROR_ARLO; + + /* Clear ARLO flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ARLO); + } + + /* Call the Error Callback in case of Error detected */ + if ((hi2c->ErrorCode & (HAL_I2C_ERROR_BERR | HAL_I2C_ERROR_OVR | HAL_I2C_ERROR_ARLO)) != HAL_I2C_ERROR_NONE) + { + I2C_ITError(hi2c, hi2c->ErrorCode); + } +} + +/** + * @brief Master Tx Transfer completed callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_MasterTxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Master Rx Transfer completed callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_MasterRxCpltCallback could be implemented in the user file + */ +} + +/** @brief Slave Tx Transfer completed callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_SlaveTxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Slave Rx Transfer completed callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_SlaveRxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Slave Address Match callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param TransferDirection Master request Transfer Direction (Write/Read), value of @ref I2C_XFERDIRECTION + * @param AddrMatchCode Address Match Code + * @retval None + */ +__weak void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + UNUSED(TransferDirection); + UNUSED(AddrMatchCode); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_AddrCallback() could be implemented in the user file + */ +} + +/** + * @brief Listen Complete callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_ListenCpltCallback() could be implemented in the user file + */ +} + +/** + * @brief Memory Tx Transfer completed callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_MemTxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Memory Rx Transfer completed callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_MemRxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief I2C error callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_ErrorCallback could be implemented in the user file + */ +} + +/** + * @brief I2C abort callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_AbortCpltCallback(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_AbortCpltCallback could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup I2C_Exported_Functions_Group3 Peripheral State, Mode and Error functions + * @brief Peripheral State, Mode and Error functions + * +@verbatim + =============================================================================== + ##### Peripheral State, Mode and Error functions ##### + =============================================================================== + [..] + This subsection permit to get in run-time the status of the peripheral + and the data flow. + +@endverbatim + * @{ + */ + +/** + * @brief Return the I2C handle state. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval HAL state + */ +HAL_I2C_StateTypeDef HAL_I2C_GetState(I2C_HandleTypeDef *hi2c) +{ + /* Return I2C handle state */ + return hi2c->State; +} + +/** + * @brief Returns the I2C Master, Slave, Memory or no mode. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @retval HAL mode + */ +HAL_I2C_ModeTypeDef HAL_I2C_GetMode(I2C_HandleTypeDef *hi2c) +{ + return hi2c->Mode; +} + +/** +* @brief Return the I2C error code. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. +* @retval I2C Error Code +*/ +uint32_t HAL_I2C_GetError(I2C_HandleTypeDef *hi2c) +{ + return hi2c->ErrorCode; +} + +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup I2C_Private_Functions + * @{ + */ + +/** + * @brief Interrupt Sub-Routine which handle the Interrupt Flags Master Mode with Interrupt. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param ITFlags Interrupt flags to handle. + * @param ITSources Interrupt sources enabled. + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_Master_ISR_IT(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags, uint32_t ITSources) +{ + uint16_t devaddress = 0U; + + /* Process Locked */ + __HAL_LOCK(hi2c); + + if (((ITFlags & I2C_FLAG_AF) != RESET) && ((ITSources & I2C_IT_NACKI) != RESET)) + { + /* Clear NACK Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + + /* Set corresponding Error Code */ + /* No need to generate STOP, it is automatically done */ + /* Error callback will be send during stop flag treatment */ + hi2c->ErrorCode |= HAL_I2C_ERROR_AF; + + /* Flush TX register */ + I2C_Flush_TXDR(hi2c); + } + else if (((ITFlags & I2C_FLAG_RXNE) != RESET) && ((ITSources & I2C_IT_RXI) != RESET)) + { + /* Read data from RXDR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->RXDR; + hi2c->XferSize--; + hi2c->XferCount--; + } + else if (((ITFlags & I2C_FLAG_TXIS) != RESET) && ((ITSources & I2C_IT_TXI) != RESET)) + { + /* Write data to TXDR */ + hi2c->Instance->TXDR = (*hi2c->pBuffPtr++); + hi2c->XferSize--; + hi2c->XferCount--; + } + else if (((ITFlags & I2C_FLAG_TCR) != RESET) && ((ITSources & I2C_IT_TCI) != RESET)) + { + if ((hi2c->XferSize == 0U) && (hi2c->XferCount != 0U)) + { + devaddress = (hi2c->Instance->CR2 & I2C_CR2_SADD); + + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + I2C_TransferConfig(hi2c, devaddress, hi2c->XferSize, I2C_RELOAD_MODE, I2C_NO_STARTSTOP); + } + else + { + hi2c->XferSize = hi2c->XferCount; + if (hi2c->XferOptions != I2C_NO_OPTION_FRAME) + { + I2C_TransferConfig(hi2c, devaddress, hi2c->XferSize, hi2c->XferOptions, I2C_NO_STARTSTOP); + } + else + { + I2C_TransferConfig(hi2c, devaddress, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP); + } + } + } + else + { + /* Call TxCpltCallback() if no stop mode is set */ + if (I2C_GET_STOP_MODE(hi2c) != I2C_AUTOEND_MODE) + { + /* Call I2C Master Sequential complete process */ + I2C_ITMasterSequentialCplt(hi2c); + } + else + { + /* Wrong size Status regarding TCR flag event */ + /* Call the corresponding callback to inform upper layer of End of Transfer */ + I2C_ITError(hi2c, HAL_I2C_ERROR_SIZE); + } + } + } + else if (((ITFlags & I2C_FLAG_TC) != RESET) && ((ITSources & I2C_IT_TCI) != RESET)) + { + if (hi2c->XferCount == 0U) + { + if (I2C_GET_STOP_MODE(hi2c) != I2C_AUTOEND_MODE) + { + /* Generate a stop condition in case of no transfer option */ + if (hi2c->XferOptions == I2C_NO_OPTION_FRAME) + { + /* Generate Stop */ + hi2c->Instance->CR2 |= I2C_CR2_STOP; + } + else + { + /* Call I2C Master Sequential complete process */ + I2C_ITMasterSequentialCplt(hi2c); + } + } + } + else + { + /* Wrong size Status regarding TC flag event */ + /* Call the corresponding callback to inform upper layer of End of Transfer */ + I2C_ITError(hi2c, HAL_I2C_ERROR_SIZE); + } + } + + if (((ITFlags & I2C_FLAG_STOPF) != RESET) && ((ITSources & I2C_IT_STOPI) != RESET)) + { + /* Call I2C Master complete process */ + I2C_ITMasterCplt(hi2c, ITFlags); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; +} + +/** + * @brief Interrupt Sub-Routine which handle the Interrupt Flags Slave Mode with Interrupt. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param ITFlags Interrupt flags to handle. + * @param ITSources Interrupt sources enabled. + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_Slave_ISR_IT(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags, uint32_t ITSources) +{ + /* Process locked */ + __HAL_LOCK(hi2c); + + if (((ITFlags & I2C_FLAG_AF) != RESET) && ((ITSources & I2C_IT_NACKI) != RESET)) + { + /* Check that I2C transfer finished */ + /* if yes, normal use case, a NACK is sent by the MASTER when Transfer is finished */ + /* Mean XferCount == 0*/ + /* So clear Flag NACKF only */ + if (hi2c->XferCount == 0U) + { + if (((hi2c->XferOptions == I2C_FIRST_AND_LAST_FRAME) || (hi2c->XferOptions == I2C_LAST_FRAME)) && \ + (hi2c->State == HAL_I2C_STATE_LISTEN)) + { + /* Call I2C Listen complete process */ + I2C_ITListenCplt(hi2c, ITFlags); + } + else if ((hi2c->XferOptions != I2C_NO_OPTION_FRAME) && (hi2c->State == HAL_I2C_STATE_BUSY_TX_LISTEN)) + { + /* Clear NACK Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + + /* Flush TX register */ + I2C_Flush_TXDR(hi2c); + + /* Last Byte is Transmitted */ + /* Call I2C Slave Sequential complete process */ + I2C_ITSlaveSequentialCplt(hi2c); + } + else + { + /* Clear NACK Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + } + } + else + { + /* if no, error use case, a Non-Acknowledge of last Data is generated by the MASTER*/ + /* Clear NACK Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + + /* Set ErrorCode corresponding to a Non-Acknowledge */ + hi2c->ErrorCode |= HAL_I2C_ERROR_AF; + } + } + else if (((ITFlags & I2C_FLAG_RXNE) != RESET) && ((ITSources & I2C_IT_RXI) != RESET)) + { + if (hi2c->XferCount > 0U) + { + /* Read data from RXDR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->RXDR; + hi2c->XferSize--; + hi2c->XferCount--; + } + + if ((hi2c->XferCount == 0U) && \ + (hi2c->XferOptions != I2C_NO_OPTION_FRAME)) + { + /* Call I2C Slave Sequential complete process */ + I2C_ITSlaveSequentialCplt(hi2c); + } + } + else if (((ITFlags & I2C_FLAG_ADDR) != RESET) && ((ITSources & I2C_IT_ADDRI) != RESET)) + { + I2C_ITAddrCplt(hi2c, ITFlags); + } + else if (((ITFlags & I2C_FLAG_TXIS) != RESET) && ((ITSources & I2C_IT_TXI) != RESET)) + { + /* Write data to TXDR only if XferCount not reach "0" */ + /* A TXIS flag can be set, during STOP treatment */ + /* Check if all Datas have already been sent */ + /* If it is the case, this last write in TXDR is not sent, correspond to a dummy TXIS event */ + if (hi2c->XferCount > 0U) + { + /* Write data to TXDR */ + hi2c->Instance->TXDR = (*hi2c->pBuffPtr++); + hi2c->XferCount--; + hi2c->XferSize--; + } + else + { + if ((hi2c->XferOptions == I2C_NEXT_FRAME) || (hi2c->XferOptions == I2C_FIRST_FRAME)) + { + /* Last Byte is Transmitted */ + /* Call I2C Slave Sequential complete process */ + I2C_ITSlaveSequentialCplt(hi2c); + } + } + } + + /* Check if STOPF is set */ + if (((ITFlags & I2C_FLAG_STOPF) != RESET) && ((ITSources & I2C_IT_STOPI) != RESET)) + { + /* Call I2C Slave complete process */ + I2C_ITSlaveCplt(hi2c, ITFlags); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; +} + +/** + * @brief Interrupt Sub-Routine which handle the Interrupt Flags Master Mode with DMA. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param ITFlags Interrupt flags to handle. + * @param ITSources Interrupt sources enabled. + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_Master_ISR_DMA(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags, uint32_t ITSources) +{ + uint16_t devaddress = 0U; + uint32_t xfermode = 0U; + + /* Process Locked */ + __HAL_LOCK(hi2c); + + if (((ITFlags & I2C_FLAG_AF) != RESET) && ((ITSources & I2C_IT_NACKI) != RESET)) + { + /* Clear NACK Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + + /* Set corresponding Error Code */ + hi2c->ErrorCode |= HAL_I2C_ERROR_AF; + + /* No need to generate STOP, it is automatically done */ + /* But enable STOP interrupt, to treat it */ + /* Error callback will be send during stop flag treatment */ + I2C_Enable_IRQ(hi2c, I2C_XFER_CPLT_IT); + + /* Flush TX register */ + I2C_Flush_TXDR(hi2c); + } + else if (((ITFlags & I2C_FLAG_TCR) != RESET) && ((ITSources & I2C_IT_TCI) != RESET)) + { + /* Disable TC interrupt */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_TCI); + + if (hi2c->XferCount != 0U) + { + /* Recover Slave address */ + devaddress = (hi2c->Instance->CR2 & I2C_CR2_SADD); + + /* Prepare the new XferSize to transfer */ + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + xfermode = I2C_RELOAD_MODE; + } + else + { + hi2c->XferSize = hi2c->XferCount; + xfermode = I2C_AUTOEND_MODE; + } + + /* Set the new XferSize in Nbytes register */ + I2C_TransferConfig(hi2c, devaddress, hi2c->XferSize, xfermode, I2C_NO_STARTSTOP); + + /* Update XferCount value */ + hi2c->XferCount -= hi2c->XferSize; + + /* Enable DMA Request */ + if (hi2c->State == HAL_I2C_STATE_BUSY_RX) + { + hi2c->Instance->CR1 |= I2C_CR1_RXDMAEN; + } + else + { + hi2c->Instance->CR1 |= I2C_CR1_TXDMAEN; + } + } + else + { + /* Wrong size Status regarding TCR flag event */ + /* Call the corresponding callback to inform upper layer of End of Transfer */ + I2C_ITError(hi2c, HAL_I2C_ERROR_SIZE); + } + } + else if (((ITFlags & I2C_FLAG_STOPF) != RESET) && ((ITSources & I2C_IT_STOPI) != RESET)) + { + /* Call I2C Master complete process */ + I2C_ITMasterCplt(hi2c, ITFlags); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; +} + +/** + * @brief Interrupt Sub-Routine which handle the Interrupt Flags Slave Mode with DMA. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param ITFlags Interrupt flags to handle. + * @param ITSources Interrupt sources enabled. + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_Slave_ISR_DMA(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags, uint32_t ITSources) +{ + /* Process locked */ + __HAL_LOCK(hi2c); + + if (((ITFlags & I2C_FLAG_AF) != RESET) && ((ITSources & I2C_IT_NACKI) != RESET)) + { + /* Check that I2C transfer finished */ + /* if yes, normal use case, a NACK is sent by the MASTER when Transfer is finished */ + /* Mean XferCount == 0 */ + /* So clear Flag NACKF only */ + if (I2C_GET_DMA_REMAIN_DATA(hi2c) == 0U) + { + /* Clear NACK Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + } + else + { + /* if no, error use case, a Non-Acknowledge of last Data is generated by the MASTER*/ + /* Clear NACK Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + + /* Set ErrorCode corresponding to a Non-Acknowledge */ + hi2c->ErrorCode |= HAL_I2C_ERROR_AF; + } + } + else if (((ITFlags & I2C_FLAG_ADDR) != RESET) && ((ITSources & I2C_IT_ADDRI) != RESET)) + { + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR); + } + else if (((ITFlags & I2C_FLAG_STOPF) != RESET) && ((ITSources & I2C_IT_STOPI) != RESET)) + { + /* Call I2C Slave complete process */ + I2C_ITSlaveCplt(hi2c, ITFlags); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; +} + +/** + * @brief Master sends target device address followed by internal memory address for write request. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shift at right before call interface + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_RequestMemoryWrite(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout, uint32_t Tickstart) +{ + I2C_TransferConfig(hi2c, DevAddress, MemAddSize, I2C_RELOAD_MODE, I2C_GENERATE_START_WRITE); + + /* Wait until TXIS flag is set */ + if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + /* If Memory address size is 8Bit */ + if (MemAddSize == I2C_MEMADD_SIZE_8BIT) + { + /* Send Memory Address */ + hi2c->Instance->TXDR = I2C_MEM_ADD_LSB(MemAddress); + } + /* If Memory address size is 16Bit */ + else + { + /* Send MSB of Memory Address */ + hi2c->Instance->TXDR = I2C_MEM_ADD_MSB(MemAddress); + + /* Wait until TXIS flag is set */ + if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + /* Send LSB of Memory Address */ + hi2c->Instance->TXDR = I2C_MEM_ADD_LSB(MemAddress); + } + + /* Wait until TCR flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout, Tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + return HAL_OK; +} + +/** + * @brief Master sends target device address followed by internal memory address for read request. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shift at right before call interface + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_RequestMemoryRead(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout, uint32_t Tickstart) +{ + I2C_TransferConfig(hi2c, DevAddress, MemAddSize, I2C_SOFTEND_MODE, I2C_GENERATE_START_WRITE); + + /* Wait until TXIS flag is set */ + if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + /* If Memory address size is 8Bit */ + if (MemAddSize == I2C_MEMADD_SIZE_8BIT) + { + /* Send Memory Address */ + hi2c->Instance->TXDR = I2C_MEM_ADD_LSB(MemAddress); + } + /* If Memory address size is 16Bit */ + else + { + /* Send MSB of Memory Address */ + hi2c->Instance->TXDR = I2C_MEM_ADD_MSB(MemAddress); + + /* Wait until TXIS flag is set */ + if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + /* Send LSB of Memory Address */ + hi2c->Instance->TXDR = I2C_MEM_ADD_LSB(MemAddress); + } + + /* Wait until TC flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TC, RESET, Timeout, Tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + return HAL_OK; +} + +/** + * @brief I2C Address complete process callback. + * @param hi2c I2C handle. + * @param ITFlags Interrupt flags to handle. + * @retval None + */ +static void I2C_ITAddrCplt(I2C_HandleTypeDef *hi2c, uint32_t ITFlags) +{ + uint8_t transferdirection = 0U; + uint16_t slaveaddrcode = 0U; + uint16_t ownadd1code = 0U; + uint16_t ownadd2code = 0U; + + /* Prevent unused argument(s) compilation warning */ + UNUSED(ITFlags); + + /* In case of Listen state, need to inform upper layer of address match code event */ + if ((hi2c->State & HAL_I2C_STATE_LISTEN) == HAL_I2C_STATE_LISTEN) + { + transferdirection = I2C_GET_DIR(hi2c); + slaveaddrcode = I2C_GET_ADDR_MATCH(hi2c); + ownadd1code = I2C_GET_OWN_ADDRESS1(hi2c); + ownadd2code = I2C_GET_OWN_ADDRESS2(hi2c); + + /* If 10bits addressing mode is selected */ + if (hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_10BIT) + { + if ((slaveaddrcode & SlaveAddr_MSK) == ((ownadd1code >> SlaveAddr_SHIFT) & SlaveAddr_MSK)) + { + slaveaddrcode = ownadd1code; + hi2c->AddrEventCount++; + if (hi2c->AddrEventCount == 2U) + { + /* Reset Address Event counter */ + hi2c->AddrEventCount = 0U; + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Call Slave Addr callback */ + HAL_I2C_AddrCallback(hi2c, transferdirection, slaveaddrcode); + } + } + else + { + slaveaddrcode = ownadd2code; + + /* Disable ADDR Interrupts */ + I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Call Slave Addr callback */ + HAL_I2C_AddrCallback(hi2c, transferdirection, slaveaddrcode); + } + } + /* else 7 bits addressing mode is selected */ + else + { + /* Disable ADDR Interrupts */ + I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Call Slave Addr callback */ + HAL_I2C_AddrCallback(hi2c, transferdirection, slaveaddrcode); + } + } + /* Else clear address flag only */ + else + { + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + } +} + +/** + * @brief I2C Master sequential complete process. + * @param hi2c I2C handle. + * @retval None + */ +static void I2C_ITMasterSequentialCplt(I2C_HandleTypeDef *hi2c) +{ + /* Reset I2C handle mode */ + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* No Generate Stop, to permit restart mode */ + /* The stop will be done at the end of transfer, when I2C_AUTOEND_MODE enable */ + if (hi2c->State == HAL_I2C_STATE_BUSY_TX) + { + hi2c->State = HAL_I2C_STATE_READY; + hi2c->PreviousState = I2C_STATE_MASTER_BUSY_TX; + hi2c->XferISR = NULL; + + /* Disable Interrupts */ + I2C_Disable_IRQ(hi2c, I2C_XFER_TX_IT); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ + HAL_I2C_MasterTxCpltCallback(hi2c); + } + /* hi2c->State == HAL_I2C_STATE_BUSY_RX */ + else + { + hi2c->State = HAL_I2C_STATE_READY; + hi2c->PreviousState = I2C_STATE_MASTER_BUSY_RX; + hi2c->XferISR = NULL; + + /* Disable Interrupts */ + I2C_Disable_IRQ(hi2c, I2C_XFER_RX_IT); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ + HAL_I2C_MasterRxCpltCallback(hi2c); + } +} + +/** + * @brief I2C Slave sequential complete process. + * @param hi2c I2C handle. + * @retval None + */ +static void I2C_ITSlaveSequentialCplt(I2C_HandleTypeDef *hi2c) +{ + /* Reset I2C handle mode */ + hi2c->Mode = HAL_I2C_MODE_NONE; + + if (hi2c->State == HAL_I2C_STATE_BUSY_TX_LISTEN) + { + /* Remove HAL_I2C_STATE_SLAVE_BUSY_TX, keep only HAL_I2C_STATE_LISTEN */ + hi2c->State = HAL_I2C_STATE_LISTEN; + hi2c->PreviousState = I2C_STATE_SLAVE_BUSY_TX; + + /* Disable Interrupts */ + I2C_Disable_IRQ(hi2c, I2C_XFER_TX_IT); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Call the Tx complete callback to inform upper layer of the end of transmit process */ + HAL_I2C_SlaveTxCpltCallback(hi2c); + } + + else if (hi2c->State == HAL_I2C_STATE_BUSY_RX_LISTEN) + { + /* Remove HAL_I2C_STATE_SLAVE_BUSY_RX, keep only HAL_I2C_STATE_LISTEN */ + hi2c->State = HAL_I2C_STATE_LISTEN; + hi2c->PreviousState = I2C_STATE_SLAVE_BUSY_RX; + + /* Disable Interrupts */ + I2C_Disable_IRQ(hi2c, I2C_XFER_RX_IT); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Call the Rx complete callback to inform upper layer of the end of receive process */ + HAL_I2C_SlaveRxCpltCallback(hi2c); + } +} + +/** + * @brief I2C Master complete process. + * @param hi2c I2C handle. + * @param ITFlags Interrupt flags to handle. + * @retval None + */ +static void I2C_ITMasterCplt(I2C_HandleTypeDef *hi2c, uint32_t ITFlags) +{ + /* Clear STOP Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); + + /* Clear Configuration Register 2 */ + I2C_RESET_CR2(hi2c); + + /* Reset handle parameters */ + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->XferISR = NULL; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + + if ((ITFlags & I2C_FLAG_AF) != RESET) + { + /* Clear NACK Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + + /* Set acknowledge error code */ + hi2c->ErrorCode |= HAL_I2C_ERROR_AF; + } + + /* Flush TX register */ + I2C_Flush_TXDR(hi2c); + + /* Disable Interrupts */ + I2C_Disable_IRQ(hi2c, I2C_XFER_TX_IT | I2C_XFER_RX_IT); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ + if ((hi2c->ErrorCode != HAL_I2C_ERROR_NONE) || (hi2c->State == HAL_I2C_STATE_ABORT)) + { + /* Call the corresponding callback to inform upper layer of End of Transfer */ + I2C_ITError(hi2c, hi2c->ErrorCode); + } + /* hi2c->State == HAL_I2C_STATE_BUSY_TX */ + else if (hi2c->State == HAL_I2C_STATE_BUSY_TX) + { + hi2c->State = HAL_I2C_STATE_READY; + + if (hi2c->Mode == HAL_I2C_MODE_MEM) + { + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ + HAL_I2C_MemTxCpltCallback(hi2c); + } + else + { + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ + HAL_I2C_MasterTxCpltCallback(hi2c); + } + } + /* hi2c->State == HAL_I2C_STATE_BUSY_RX */ + else if (hi2c->State == HAL_I2C_STATE_BUSY_RX) + { + hi2c->State = HAL_I2C_STATE_READY; + + if (hi2c->Mode == HAL_I2C_MODE_MEM) + { + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + HAL_I2C_MemRxCpltCallback(hi2c); + } + else + { + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + HAL_I2C_MasterRxCpltCallback(hi2c); + } + } +} + +/** + * @brief I2C Slave complete process. + * @param hi2c I2C handle. + * @param ITFlags Interrupt flags to handle. + * @retval None + */ +static void I2C_ITSlaveCplt(I2C_HandleTypeDef *hi2c, uint32_t ITFlags) +{ + /* Clear STOP Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR); + + /* Disable all interrupts */ + I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT | I2C_XFER_TX_IT | I2C_XFER_RX_IT); + + /* Disable Address Acknowledge */ + hi2c->Instance->CR2 |= I2C_CR2_NACK; + + /* Clear Configuration Register 2 */ + I2C_RESET_CR2(hi2c); + + /* Flush TX register */ + I2C_Flush_TXDR(hi2c); + + /* If a DMA is ongoing, Update handle size context */ + if (((hi2c->Instance->CR1 & I2C_CR1_TXDMAEN) == I2C_CR1_TXDMAEN) || + ((hi2c->Instance->CR1 & I2C_CR1_RXDMAEN) == I2C_CR1_RXDMAEN)) + { + hi2c->XferCount = I2C_GET_DMA_REMAIN_DATA(hi2c); + } + + /* All data are not transferred, so set error code accordingly */ + if (hi2c->XferCount != 0U) + { + /* Set ErrorCode corresponding to a Non-Acknowledge */ + hi2c->ErrorCode |= HAL_I2C_ERROR_AF; + } + + /* Store Last receive data if any */ + if (((ITFlags & I2C_FLAG_RXNE) != RESET)) + { + /* Read data from RXDR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->RXDR; + + if ((hi2c->XferSize > 0U)) + { + hi2c->XferSize--; + hi2c->XferCount--; + + /* Set ErrorCode corresponding to a Non-Acknowledge */ + hi2c->ErrorCode |= HAL_I2C_ERROR_AF; + } + } + + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->XferISR = NULL; + + if (hi2c->ErrorCode != HAL_I2C_ERROR_NONE) + { + /* Call the corresponding callback to inform upper layer of End of Transfer */ + I2C_ITError(hi2c, hi2c->ErrorCode); + + /* Call the Listen Complete callback, to inform upper layer of the end of Listen usecase */ + if (hi2c->State == HAL_I2C_STATE_LISTEN) + { + /* Call I2C Listen complete process */ + I2C_ITListenCplt(hi2c, ITFlags); + } + } + else if (hi2c->XferOptions != I2C_NO_OPTION_FRAME) + { + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->State = HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Call the Listen Complete callback, to inform upper layer of the end of Listen usecase */ + HAL_I2C_ListenCpltCallback(hi2c); + } + /* Call the corresponding callback to inform upper layer of End of Transfer */ + else if (hi2c->State == HAL_I2C_STATE_BUSY_RX) + { + hi2c->State = HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Call the Slave Rx Complete callback */ + HAL_I2C_SlaveRxCpltCallback(hi2c); + } + else + { + hi2c->State = HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Call the Slave Tx Complete callback */ + HAL_I2C_SlaveTxCpltCallback(hi2c); + } +} + +/** + * @brief I2C Listen complete process. + * @param hi2c I2C handle. + * @param ITFlags Interrupt flags to handle. + * @retval None + */ +static void I2C_ITListenCplt(I2C_HandleTypeDef *hi2c, uint32_t ITFlags) +{ + /* Reset handle parameters */ + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->XferISR = NULL; + + /* Store Last receive data if any */ + if (((ITFlags & I2C_FLAG_RXNE) != RESET)) + { + /* Read data from RXDR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->RXDR; + + if ((hi2c->XferSize > 0U)) + { + hi2c->XferSize--; + hi2c->XferCount--; + + /* Set ErrorCode corresponding to a Non-Acknowledge */ + hi2c->ErrorCode |= HAL_I2C_ERROR_AF; + } + } + + /* Disable all Interrupts*/ + I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT | I2C_XFER_RX_IT | I2C_XFER_TX_IT); + + /* Clear NACK Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Call the Listen Complete callback, to inform upper layer of the end of Listen usecase */ + HAL_I2C_ListenCpltCallback(hi2c); +} + +/** + * @brief I2C interrupts error process. + * @param hi2c I2C handle. + * @param ErrorCode Error code to handle. + * @retval None + */ +static void I2C_ITError(I2C_HandleTypeDef *hi2c, uint32_t ErrorCode) +{ + /* Reset handle parameters */ + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferCount = 0U; + + /* Set new error code */ + hi2c->ErrorCode |= ErrorCode; + + /* Disable Interrupts */ + if ((hi2c->State == HAL_I2C_STATE_LISTEN) || + (hi2c->State == HAL_I2C_STATE_BUSY_TX_LISTEN) || + (hi2c->State == HAL_I2C_STATE_BUSY_RX_LISTEN)) + { + /* Disable all interrupts, except interrupts related to LISTEN state */ + I2C_Disable_IRQ(hi2c, I2C_XFER_RX_IT | I2C_XFER_TX_IT); + + /* keep HAL_I2C_STATE_LISTEN if set */ + hi2c->State = HAL_I2C_STATE_LISTEN; + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->XferISR = I2C_Slave_ISR_IT; + } + else + { + /* Disable all interrupts */ + I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT | I2C_XFER_RX_IT | I2C_XFER_TX_IT); + + /* If state is an abort treatment on goind, don't change state */ + /* This change will be do later */ + if (hi2c->State != HAL_I2C_STATE_ABORT) + { + /* Set HAL_I2C_STATE_READY */ + hi2c->State = HAL_I2C_STATE_READY; + } + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->XferISR = NULL; + } + + /* Abort DMA TX transfer if any */ + if ((hi2c->Instance->CR1 & I2C_CR1_TXDMAEN) == I2C_CR1_TXDMAEN) + { + hi2c->Instance->CR1 &= ~I2C_CR1_TXDMAEN; + + /* Set the I2C DMA Abort callback : + will lead to call HAL_I2C_ErrorCallback() at end of DMA abort procedure */ + hi2c->hdmatx->XferAbortCallback = I2C_DMAAbort; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Abort DMA TX */ + if (HAL_DMA_Abort_IT(hi2c->hdmatx) != HAL_OK) + { + /* Call Directly XferAbortCallback function in case of error */ + hi2c->hdmatx->XferAbortCallback(hi2c->hdmatx); + } + } + /* Abort DMA RX transfer if any */ + else if ((hi2c->Instance->CR1 & I2C_CR1_RXDMAEN) == I2C_CR1_RXDMAEN) + { + hi2c->Instance->CR1 &= ~I2C_CR1_RXDMAEN; + + /* Set the I2C DMA Abort callback : + will lead to call HAL_I2C_ErrorCallback() at end of DMA abort procedure */ + hi2c->hdmarx->XferAbortCallback = I2C_DMAAbort; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Abort DMA RX */ + if (HAL_DMA_Abort_IT(hi2c->hdmarx) != HAL_OK) + { + /* Call Directly hi2c->hdmarx->XferAbortCallback function in case of error */ + hi2c->hdmarx->XferAbortCallback(hi2c->hdmarx); + } + } + else if (hi2c->State == HAL_I2C_STATE_ABORT) + { + hi2c->State = HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ + HAL_I2C_AbortCpltCallback(hi2c); + } + else + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ + HAL_I2C_ErrorCallback(hi2c); + } +} + +/** + * @brief I2C Tx data register flush process. + * @param hi2c I2C handle. + * @retval None + */ +static void I2C_Flush_TXDR(I2C_HandleTypeDef *hi2c) +{ + /* If a pending TXIS flag is set */ + /* Write a dummy data in TXDR to clear it */ + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXIS) != RESET) + { + hi2c->Instance->TXDR = 0x00U; + } + + /* Flush TX register if not empty */ + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXE) == RESET) + { + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_TXE); + } +} + +/** + * @brief DMA I2C master transmit process complete callback. + * @param hdma DMA handle + * @retval None + */ +static void I2C_DMAMasterTransmitCplt(DMA_HandleTypeDef *hdma) +{ + I2C_HandleTypeDef *hi2c = (I2C_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + /* Disable DMA Request */ + hi2c->Instance->CR1 &= ~I2C_CR1_TXDMAEN; + + /* If last transfer, enable STOP interrupt */ + if (hi2c->XferCount == 0U) + { + /* Enable STOP interrupt */ + I2C_Enable_IRQ(hi2c, I2C_XFER_CPLT_IT); + } + /* else prepare a new DMA transfer and enable TCReload interrupt */ + else + { + /* Update Buffer pointer */ + hi2c->pBuffPtr += hi2c->XferSize; + + /* Set the XferSize to transfer */ + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + } + else + { + hi2c->XferSize = hi2c->XferCount; + } + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)hi2c->pBuffPtr, (uint32_t)&hi2c->Instance->TXDR, hi2c->XferSize); + + /* Enable TC interrupts */ + I2C_Enable_IRQ(hi2c, I2C_XFER_RELOAD_IT); + } +} + +/** + * @brief DMA I2C slave transmit process complete callback. + * @param hdma DMA handle + * @retval None + */ +static void I2C_DMASlaveTransmitCplt(DMA_HandleTypeDef *hdma) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hdma); + + /* No specific action, Master fully manage the generation of STOP condition */ + /* Mean that this generation can arrive at any time, at the end or during DMA process */ + /* So STOP condition should be manage through Interrupt treatment */ +} + +/** + * @brief DMA I2C master receive process complete callback. + * @param hdma DMA handle + * @retval None + */ +static void I2C_DMAMasterReceiveCplt(DMA_HandleTypeDef *hdma) +{ + I2C_HandleTypeDef *hi2c = (I2C_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + /* Disable DMA Request */ + hi2c->Instance->CR1 &= ~I2C_CR1_RXDMAEN; + + /* If last transfer, enable STOP interrupt */ + if (hi2c->XferCount == 0U) + { + /* Enable STOP interrupt */ + I2C_Enable_IRQ(hi2c, I2C_XFER_CPLT_IT); + } + /* else prepare a new DMA transfer and enable TCReload interrupt */ + else + { + /* Update Buffer pointer */ + hi2c->pBuffPtr += hi2c->XferSize; + + /* Set the XferSize to transfer */ + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + } + else + { + hi2c->XferSize = hi2c->XferCount; + } + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->RXDR, (uint32_t)hi2c->pBuffPtr, hi2c->XferSize); + + /* Enable TC interrupts */ + I2C_Enable_IRQ(hi2c, I2C_XFER_RELOAD_IT); + } +} + +/** + * @brief DMA I2C slave receive process complete callback. + * @param hdma DMA handle + * @retval None + */ +static void I2C_DMASlaveReceiveCplt(DMA_HandleTypeDef *hdma) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hdma); + + /* No specific action, Master fully manage the generation of STOP condition */ + /* Mean that this generation can arrive at any time, at the end or during DMA process */ + /* So STOP condition should be manage through Interrupt treatment */ +} + +/** + * @brief DMA I2C communication error callback. + * @param hdma DMA handle + * @retval None + */ +static void I2C_DMAError(DMA_HandleTypeDef *hdma) +{ + I2C_HandleTypeDef *hi2c = (I2C_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + /* Disable Acknowledge */ + hi2c->Instance->CR2 |= I2C_CR2_NACK; + + /* Call the corresponding callback to inform upper layer of End of Transfer */ + I2C_ITError(hi2c, HAL_I2C_ERROR_DMA); +} + +/** + * @brief DMA I2C communication abort callback + * (To be called at end of DMA Abort procedure). + * @param hdma DMA handle. + * @retval None + */ +static void I2C_DMAAbort(DMA_HandleTypeDef *hdma) +{ + I2C_HandleTypeDef *hi2c = (I2C_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + /* Disable Acknowledge */ + hi2c->Instance->CR2 |= I2C_CR2_NACK; + + /* Reset AbortCpltCallback */ + hi2c->hdmatx->XferAbortCallback = NULL; + hi2c->hdmarx->XferAbortCallback = NULL; + + /* Check if come from abort from user */ + if (hi2c->State == HAL_I2C_STATE_ABORT) + { + hi2c->State = HAL_I2C_STATE_READY; + + /* Call the corresponding callback to inform upper layer of End of Transfer */ + HAL_I2C_AbortCpltCallback(hi2c); + } + else + { + /* Call the corresponding callback to inform upper layer of End of Transfer */ + HAL_I2C_ErrorCallback(hi2c); + } +} + +/** + * @brief This function handles I2C Communication Timeout. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param Flag Specifies the I2C flag to check. + * @param Status The new Flag status (SET or RESET). + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_WaitOnFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, FlagStatus Status, uint32_t Timeout, uint32_t Tickstart) +{ + while (__HAL_I2C_GET_FLAG(hi2c, Flag) == Status) + { + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if ((Timeout == 0U) || ((HAL_GetTick() - Tickstart) > Timeout)) + { + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_TIMEOUT; + } + } + } + return HAL_OK; +} + +/** + * @brief This function handles I2C Communication Timeout for specific usage of TXIS flag. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_WaitOnTXISFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart) +{ + while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXIS) == RESET) + { + /* Check if a NACK is detected */ + if (I2C_IsAcknowledgeFailed(hi2c, Timeout, Tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if ((Timeout == 0U) || ((HAL_GetTick() - Tickstart) > Timeout)) + { + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_TIMEOUT; + } + } + } + return HAL_OK; +} + +/** + * @brief This function handles I2C Communication Timeout for specific usage of STOP flag. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_WaitOnSTOPFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart) +{ + while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == RESET) + { + /* Check if a NACK is detected */ + if (I2C_IsAcknowledgeFailed(hi2c, Timeout, Tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Check for the Timeout */ + if ((Timeout == 0U) || ((HAL_GetTick() - Tickstart) > Timeout)) + { + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_TIMEOUT; + } + } + return HAL_OK; +} + +/** + * @brief This function handles I2C Communication Timeout for specific usage of RXNE flag. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_WaitOnRXNEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart) +{ + while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == RESET) + { + /* Check if a NACK is detected */ + if (I2C_IsAcknowledgeFailed(hi2c, Timeout, Tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Check if a STOPF is detected */ + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == SET) + { + /* Check if an RXNE is pending */ + /* Store Last receive data if any */ + if ((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == SET) && (hi2c->XferSize > 0U)) + { + /* Return HAL_OK */ + /* The Reading of data from RXDR will be done in caller function */ + return HAL_OK; + } + else + { + /* Clear STOP Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); + + /* Clear Configuration Register 2 */ + I2C_RESET_CR2(hi2c); + + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + } + + /* Check for the Timeout */ + if ((Timeout == 0U) || ((HAL_GetTick() - Tickstart) > Timeout)) + { + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + hi2c->State = HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_TIMEOUT; + } + } + return HAL_OK; +} + +/** + * @brief This function handles Acknowledge failed detection during an I2C Communication. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_IsAcknowledgeFailed(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart) +{ + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET) + { + /* Wait until STOP Flag is reset */ + /* AutoEnd should be initiate after AF */ + while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == RESET) + { + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if ((Timeout == 0U) || ((HAL_GetTick() - Tickstart) > Timeout)) + { + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_TIMEOUT; + } + } + } + + /* Clear NACKF Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + + /* Clear STOP Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); + + /* Flush TX register */ + I2C_Flush_TXDR(hi2c); + + /* Clear Configuration Register 2 */ + I2C_RESET_CR2(hi2c); + + hi2c->ErrorCode = HAL_I2C_ERROR_AF; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + return HAL_OK; +} + +/** + * @brief Handles I2Cx communication when starting transfer or during transfer (TC or TCR flag are set). + * @param hi2c I2C handle. + * @param DevAddress Specifies the slave address to be programmed. + * @param Size Specifies the number of bytes to be programmed. + * This parameter must be a value between 0 and 255. + * @param Mode New state of the I2C START condition generation. + * This parameter can be one of the following values: + * @arg @ref I2C_RELOAD_MODE Enable Reload mode . + * @arg @ref I2C_AUTOEND_MODE Enable Automatic end mode. + * @arg @ref I2C_SOFTEND_MODE Enable Software end mode. + * @param Request New state of the I2C START condition generation. + * This parameter can be one of the following values: + * @arg @ref I2C_NO_STARTSTOP Don't Generate stop and start condition. + * @arg @ref I2C_GENERATE_STOP Generate stop condition (Size should be set to 0). + * @arg @ref I2C_GENERATE_START_READ Generate Restart for read request. + * @arg @ref I2C_GENERATE_START_WRITE Generate Restart for write request. + * @retval None + */ +static void I2C_TransferConfig(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t Size, uint32_t Mode, uint32_t Request) +{ + /* Check the parameters */ + assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance)); + assert_param(IS_TRANSFER_MODE(Mode)); + assert_param(IS_TRANSFER_REQUEST(Request)); + + /* update CR2 register */ + MODIFY_REG(hi2c->Instance->CR2, ((I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD | I2C_CR2_AUTOEND | (I2C_CR2_RD_WRN & (uint32_t)(Request >> (31U - I2C_CR2_RD_WRN_Pos))) | I2C_CR2_START | I2C_CR2_STOP)), \ + (uint32_t)(((uint32_t)DevAddress & I2C_CR2_SADD) | (((uint32_t)Size << I2C_CR2_NBYTES_Pos) & I2C_CR2_NBYTES) | (uint32_t)Mode | (uint32_t)Request)); +} + +/** + * @brief Manage the enabling of Interrupts. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param InterruptRequest Value of @ref I2C_Interrupt_configuration_definition. + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_Enable_IRQ(I2C_HandleTypeDef *hi2c, uint16_t InterruptRequest) +{ + uint32_t tmpisr = 0U; + + if ((hi2c->XferISR == I2C_Master_ISR_DMA) || \ + (hi2c->XferISR == I2C_Slave_ISR_DMA)) + { + if ((InterruptRequest & I2C_XFER_LISTEN_IT) == I2C_XFER_LISTEN_IT) + { + /* Enable ERR, STOP, NACK and ADDR interrupts */ + tmpisr |= I2C_IT_ADDRI | I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_ERRI; + } + + if ((InterruptRequest & I2C_XFER_ERROR_IT) == I2C_XFER_ERROR_IT) + { + /* Enable ERR and NACK interrupts */ + tmpisr |= I2C_IT_ERRI | I2C_IT_NACKI; + } + + if ((InterruptRequest & I2C_XFER_CPLT_IT) == I2C_XFER_CPLT_IT) + { + /* Enable STOP interrupts */ + tmpisr |= I2C_IT_STOPI; + } + + if ((InterruptRequest & I2C_XFER_RELOAD_IT) == I2C_XFER_RELOAD_IT) + { + /* Enable TC interrupts */ + tmpisr |= I2C_IT_TCI; + } + } + else + { + if ((InterruptRequest & I2C_XFER_LISTEN_IT) == I2C_XFER_LISTEN_IT) + { + /* Enable ERR, STOP, NACK, and ADDR interrupts */ + tmpisr |= I2C_IT_ADDRI | I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_ERRI; + } + + if ((InterruptRequest & I2C_XFER_TX_IT) == I2C_XFER_TX_IT) + { + /* Enable ERR, TC, STOP, NACK and RXI interrupts */ + tmpisr |= I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_TXI; + } + + if ((InterruptRequest & I2C_XFER_RX_IT) == I2C_XFER_RX_IT) + { + /* Enable ERR, TC, STOP, NACK and TXI interrupts */ + tmpisr |= I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_RXI; + } + + if ((InterruptRequest & I2C_XFER_CPLT_IT) == I2C_XFER_CPLT_IT) + { + /* Enable STOP interrupts */ + tmpisr |= I2C_IT_STOPI; + } + } + + /* Enable interrupts only at the end */ + /* to avoid the risk of I2C interrupt handle execution before */ + /* all interrupts requested done */ + __HAL_I2C_ENABLE_IT(hi2c, tmpisr); + + return HAL_OK; +} + +/** + * @brief Manage the disabling of Interrupts. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param InterruptRequest Value of @ref I2C_Interrupt_configuration_definition. + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_Disable_IRQ(I2C_HandleTypeDef *hi2c, uint16_t InterruptRequest) +{ + uint32_t tmpisr = 0U; + + if ((InterruptRequest & I2C_XFER_TX_IT) == I2C_XFER_TX_IT) + { + /* Disable TC and TXI interrupts */ + tmpisr |= I2C_IT_TCI | I2C_IT_TXI; + + if ((hi2c->State & HAL_I2C_STATE_LISTEN) != HAL_I2C_STATE_LISTEN) + { + /* Disable NACK and STOP interrupts */ + tmpisr |= I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_ERRI; + } + } + + if ((InterruptRequest & I2C_XFER_RX_IT) == I2C_XFER_RX_IT) + { + /* Disable TC and RXI interrupts */ + tmpisr |= I2C_IT_TCI | I2C_IT_RXI; + + if ((hi2c->State & HAL_I2C_STATE_LISTEN) != HAL_I2C_STATE_LISTEN) + { + /* Disable NACK and STOP interrupts */ + tmpisr |= I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_ERRI; + } + } + + if ((InterruptRequest & I2C_XFER_LISTEN_IT) == I2C_XFER_LISTEN_IT) + { + /* Disable ADDR, NACK and STOP interrupts */ + tmpisr |= I2C_IT_ADDRI | I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_ERRI; + } + + if ((InterruptRequest & I2C_XFER_ERROR_IT) == I2C_XFER_ERROR_IT) + { + /* Enable ERR and NACK interrupts */ + tmpisr |= I2C_IT_ERRI | I2C_IT_NACKI; + } + + if ((InterruptRequest & I2C_XFER_CPLT_IT) == I2C_XFER_CPLT_IT) + { + /* Enable STOP interrupts */ + tmpisr |= I2C_IT_STOPI; + } + + if ((InterruptRequest & I2C_XFER_RELOAD_IT) == I2C_XFER_RELOAD_IT) + { + /* Enable TC interrupts */ + tmpisr |= I2C_IT_TCI; + } + + /* Disable interrupts only at the end */ + /* to avoid a breaking situation like at "t" time */ + /* all disable interrupts request are not done */ + __HAL_I2C_DISABLE_IT(hi2c, tmpisr); + + return HAL_OK; +} + +/** + * @} + */ + +#endif /* HAL_I2C_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_i2c_ex.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_i2c_ex.c new file mode 100644 index 0000000..bd4e329 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_i2c_ex.c @@ -0,0 +1,355 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_i2c_ex.c + * @author MCD Application Team + * @brief I2C Extended HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of I2C Extended peripheral: + * + Extended features functions + * + @verbatim + ============================================================================== + ##### I2C peripheral Extended features ##### + ============================================================================== + + [..] Comparing to other previous devices, the I2C interface for STM32L4xx + devices contains the following additional features + + (+) Possibility to disable or enable Analog Noise Filter + (+) Use of a configured Digital Noise Filter + (+) Disable or enable wakeup from Stop mode(s) + (+) Disable or enable Fast Mode Plus + + ##### How to use this driver ##### + ============================================================================== + [..] This driver provides functions to configure Noise Filter and Wake Up Feature + (#) Configure I2C Analog noise filter using the function HAL_I2CEx_ConfigAnalogFilter() + (#) Configure I2C Digital noise filter using the function HAL_I2CEx_ConfigDigitalFilter() + (#) Configure the enable or disable of I2C Wake Up Mode using the functions : + (++) HAL_I2CEx_EnableWakeUp() + (++) HAL_I2CEx_DisableWakeUp() + (#) Configure the enable or disable of fast mode plus driving capability using the functions : + (++) HAL_I2CEx_EnableFastModePlus() + (++) HAL_I2CEx_DisableFastModePlus() + @endverbatim + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup I2CEx I2CEx + * @brief I2C Extended HAL module driver + * @{ + */ + +#ifdef HAL_I2C_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + +/** @defgroup I2CEx_Exported_Functions I2C Extended Exported Functions + * @{ + */ + +/** @defgroup I2CEx_Exported_Functions_Group1 Extended features functions + * @brief Extended features functions + * +@verbatim + =============================================================================== + ##### Extended features functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Configure Noise Filters + (+) Configure Wake Up Feature + (+) Configure Fast Mode Plus + +@endverbatim + * @{ + */ + +/** + * @brief Configure I2C Analog noise filter. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2Cx peripheral. + * @param AnalogFilter New state of the Analog filter. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2CEx_ConfigAnalogFilter(I2C_HandleTypeDef *hi2c, uint32_t AnalogFilter) +{ + /* Check the parameters */ + assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance)); + assert_param(IS_I2C_ANALOG_FILTER(AnalogFilter)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hi2c); + + hi2c->State = HAL_I2C_STATE_BUSY; + + /* Disable the selected I2C peripheral */ + __HAL_I2C_DISABLE(hi2c); + + /* Reset I2Cx ANOFF bit */ + hi2c->Instance->CR1 &= ~(I2C_CR1_ANFOFF); + + /* Set analog filter bit*/ + hi2c->Instance->CR1 |= AnalogFilter; + + __HAL_I2C_ENABLE(hi2c); + + hi2c->State = HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Configure I2C Digital noise filter. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2Cx peripheral. + * @param DigitalFilter Coefficient of digital noise filter between Min_Data=0x00 and Max_Data=0x0F. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2CEx_ConfigDigitalFilter(I2C_HandleTypeDef *hi2c, uint32_t DigitalFilter) +{ + uint32_t tmpreg = 0U; + + /* Check the parameters */ + assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance)); + assert_param(IS_I2C_DIGITAL_FILTER(DigitalFilter)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hi2c); + + hi2c->State = HAL_I2C_STATE_BUSY; + + /* Disable the selected I2C peripheral */ + __HAL_I2C_DISABLE(hi2c); + + /* Get the old register value */ + tmpreg = hi2c->Instance->CR1; + + /* Reset I2Cx DNF bits [11:8] */ + tmpreg &= ~(I2C_CR1_DNF); + + /* Set I2Cx DNF coefficient */ + tmpreg |= DigitalFilter << 8U; + + /* Store the new register value */ + hi2c->Instance->CR1 = tmpreg; + + __HAL_I2C_ENABLE(hi2c); + + hi2c->State = HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Enable I2C wakeup from Stop mode(s). + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2Cx peripheral. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2CEx_EnableWakeUp(I2C_HandleTypeDef *hi2c) +{ + /* Check the parameters */ + assert_param(IS_I2C_WAKEUP_FROMSTOP_INSTANCE(hi2c->Instance)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hi2c); + + hi2c->State = HAL_I2C_STATE_BUSY; + + /* Disable the selected I2C peripheral */ + __HAL_I2C_DISABLE(hi2c); + + /* Enable wakeup from stop mode */ + hi2c->Instance->CR1 |= I2C_CR1_WUPEN; + + __HAL_I2C_ENABLE(hi2c); + + hi2c->State = HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Disable I2C wakeup from Stop mode(s). + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2Cx peripheral. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2CEx_DisableWakeUp(I2C_HandleTypeDef *hi2c) +{ + /* Check the parameters */ + assert_param(IS_I2C_WAKEUP_FROMSTOP_INSTANCE(hi2c->Instance)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hi2c); + + hi2c->State = HAL_I2C_STATE_BUSY; + + /* Disable the selected I2C peripheral */ + __HAL_I2C_DISABLE(hi2c); + + /* Enable wakeup from stop mode */ + hi2c->Instance->CR1 &= ~(I2C_CR1_WUPEN); + + __HAL_I2C_ENABLE(hi2c); + + hi2c->State = HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Enable the I2C fast mode plus driving capability. + * @param ConfigFastModePlus Selects the pin. + * This parameter can be one of the @ref I2CEx_FastModePlus values + * @note For I2C1, fast mode plus driving capability can be enabled on all selected + * I2C1 pins using I2C_FASTMODEPLUS_I2C1 parameter or independently + * on each one of the following pins PB6, PB7, PB8 and PB9. + * @note For remaining I2C1 pins (PA14, PA15...) fast mode plus driving capability + * can be enabled only by using I2C_FASTMODEPLUS_I2C1 parameter. + * @note For all I2C2 pins fast mode plus driving capability can be enabled + * only by using I2C_FASTMODEPLUS_I2C2 parameter. + * @note For all I2C3 pins fast mode plus driving capability can be enabled + * only by using I2C_FASTMODEPLUS_I2C3 parameter. + * @note For all I2C4 pins fast mode plus driving capability can be enabled + * only by using I2C_FASTMODEPLUS_I2C4 parameter. + * @retval None + */ +void HAL_I2CEx_EnableFastModePlus(uint32_t ConfigFastModePlus) +{ + /* Check the parameter */ + assert_param(IS_I2C_FASTMODEPLUS(ConfigFastModePlus)); + + /* Enable SYSCFG clock */ + __HAL_RCC_SYSCFG_CLK_ENABLE(); + + /* Enable fast mode plus driving capability for selected pin */ + SET_BIT(SYSCFG->CFGR1, (uint32_t)ConfigFastModePlus); +} + +/** + * @brief Disable the I2C fast mode plus driving capability. + * @param ConfigFastModePlus Selects the pin. + * This parameter can be one of the @ref I2CEx_FastModePlus values + * @note For I2C1, fast mode plus driving capability can be disabled on all selected + * I2C1 pins using I2C_FASTMODEPLUS_I2C1 parameter or independently + * on each one of the following pins PB6, PB7, PB8 and PB9. + * @note For remaining I2C1 pins (PA14, PA15...) fast mode plus driving capability + * can be disabled only by using I2C_FASTMODEPLUS_I2C1 parameter. + * @note For all I2C2 pins fast mode plus driving capability can be disabled + * only by using I2C_FASTMODEPLUS_I2C2 parameter. + * @note For all I2C3 pins fast mode plus driving capability can be disabled + * only by using I2C_FASTMODEPLUS_I2C3 parameter. + * @note For all I2C4 pins fast mode plus driving capability can be disabled + * only by using I2C_FASTMODEPLUS_I2C4 parameter. + * @retval None + */ +void HAL_I2CEx_DisableFastModePlus(uint32_t ConfigFastModePlus) +{ + /* Check the parameter */ + assert_param(IS_I2C_FASTMODEPLUS(ConfigFastModePlus)); + + /* Enable SYSCFG clock */ + __HAL_RCC_SYSCFG_CLK_ENABLE(); + + /* Disable fast mode plus driving capability for selected pin */ + CLEAR_BIT(SYSCFG->CFGR1, (uint32_t)ConfigFastModePlus); +} + +/** + * @} + */ + +/** + * @} + */ + +#endif /* HAL_I2C_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pcd.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pcd.c new file mode 100644 index 0000000..de415ad --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pcd.c @@ -0,0 +1,1675 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_pcd.c + * @author MCD Application Team + * @brief PCD HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the USB Peripheral Controller: + * + Initialization and de-initialization functions + * + IO operation functions + * + Peripheral Control functions + * + Peripheral State functions + * + @verbatim + ============================================================================== + ##### How to use this driver ##### + ============================================================================== + [..] + The PCD HAL driver can be used as follows: + + (#) Declare a PCD_HandleTypeDef handle structure, for example: + PCD_HandleTypeDef hpcd; + + (#) Fill parameters of Init structure in HCD handle + + (#) Call HAL_PCD_Init() API to initialize the PCD peripheral (Core, Device core, ...) + + (#) Initialize the PCD low level resources through the HAL_PCD_MspInit() API: + (##) Enable the PCD/USB Low Level interface clock using + (+++) __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); + (##) Initialize the related GPIO clocks + (##) Configure PCD pin-out + (##) Configure PCD NVIC interrupt + + (#)Associate the Upper USB device stack to the HAL PCD Driver: + (##) hpcd.pData = pdev; + + (#)Enable PCD transmission and reception: + (##) HAL_PCD_Start(); + + @endverbatim + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup PCD PCD + * @brief PCD HAL module driver + * @{ + */ + +#ifdef HAL_PCD_MODULE_ENABLED + +#if defined(STM32L432xx) || defined(STM32L433xx) || defined(STM32L442xx) || defined(STM32L443xx) || \ + defined(STM32L452xx) || defined(STM32L462xx) || \ + defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || \ + defined(STM32L496xx) || defined(STM32L4A6xx) || \ + defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** + * USB_OTG_CORE VERSION ID + */ +#define USB_OTG_CORE_ID_310A 0x4F54310A +#define USB_OTG_CORE_ID_320A 0x4F54320A + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup PCD_Private_Macros PCD Private Macros + * @{ + */ +#define PCD_MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define PCD_MAX(a, b) (((a) > (b)) ? (a) : (b)) +/** + * @} + */ + +/* Private functions prototypes ----------------------------------------------*/ +/** @defgroup PCD_Private_Functions PCD Private Functions + * @{ + */ +#if defined (USB_OTG_FS) +static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum); +#endif /* USB_OTG_FS */ +#if defined (USB) +static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd); +#endif /* USB */ +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup PCD_Exported_Functions PCD Exported Functions + * @{ + */ + +/** @defgroup PCD_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions + * +@verbatim + =============================================================================== + ##### Initialization and de-initialization functions ##### + =============================================================================== + [..] This section provides functions allowing to: + +@endverbatim + * @{ + */ + +/** + * @brief Initializes the PCD according to the specified + * parameters in the PCD_InitTypeDef and initialize the associated handle. + * @param hpcd: PCD handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCD_Init(PCD_HandleTypeDef *hpcd) +{ + uint32_t index = 0U; + + /* Check the PCD handle allocation */ + if(hpcd == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_PCD_ALL_INSTANCE(hpcd->Instance)); + + if(hpcd->State == HAL_PCD_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hpcd->Lock = HAL_UNLOCKED; + + /* Init the low level hardware : GPIO, CLOCK, NVIC... */ + HAL_PCD_MspInit(hpcd); + } + + hpcd->State = HAL_PCD_STATE_BUSY; + + /* Disable the Interrupts */ + __HAL_PCD_DISABLE(hpcd); + + /*Init the Core (common init.) */ + USB_CoreInit(hpcd->Instance, hpcd->Init); + + /* Force Device Mode*/ + USB_SetCurrentMode(hpcd->Instance , USB_DEVICE_MODE); + + /* Init endpoints structures */ + for (index = 0; index < hpcd->Init.dev_endpoints ; index++) + { + /* Init ep structure */ + hpcd->IN_ep[index].is_in = 1; + hpcd->IN_ep[index].num = index; + hpcd->IN_ep[index].tx_fifo_num = index; + /* Control until ep is activated */ + hpcd->IN_ep[index].type = EP_TYPE_CTRL; + hpcd->IN_ep[index].maxpacket = 0; + hpcd->IN_ep[index].xfer_buff = 0; + hpcd->IN_ep[index].xfer_len = 0; + } + + for (index = 0; index < 15 ; index++) + { + hpcd->OUT_ep[index].is_in = 0; + hpcd->OUT_ep[index].num = index; + hpcd->IN_ep[index].tx_fifo_num = index; + /* Control until ep is activated */ + hpcd->OUT_ep[index].type = EP_TYPE_CTRL; + hpcd->OUT_ep[index].maxpacket = 0; + hpcd->OUT_ep[index].xfer_buff = 0; + hpcd->OUT_ep[index].xfer_len = 0; + } + + /* Init Device */ + USB_DevInit(hpcd->Instance, hpcd->Init); + + hpcd->USB_Address = 0; + + hpcd->State= HAL_PCD_STATE_READY; + + /* Activate LPM */ + if (hpcd->Init.lpm_enable ==1) + { + HAL_PCDEx_ActivateLPM(hpcd); + } + /* Activate Battery charging */ + if (hpcd->Init.battery_charging_enable ==1) + { + HAL_PCDEx_ActivateBCD(hpcd); + } + USB_DevDisconnect (hpcd->Instance); + return HAL_OK; +} + +/** + * @brief DeInitializes the PCD peripheral. + * @param hpcd: PCD handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCD_DeInit(PCD_HandleTypeDef *hpcd) +{ + /* Check the PCD handle allocation */ + if(hpcd == NULL) + { + return HAL_ERROR; + } + + hpcd->State = HAL_PCD_STATE_BUSY; + + /* Stop Device */ + HAL_PCD_Stop(hpcd); + + /* DeInit the low level hardware */ + HAL_PCD_MspDeInit(hpcd); + + hpcd->State = HAL_PCD_STATE_RESET; + + return HAL_OK; +} + +/** + * @brief Initializes the PCD MSP. + * @param hpcd: PCD handle + * @retval None + */ +__weak void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hpcd); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_PCD_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitializes PCD MSP. + * @param hpcd: PCD handle + * @retval None + */ +__weak void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hpcd); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_PCD_MspDeInit could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup PCD_Exported_Functions_Group2 Input and Output operation functions + * @brief Data transfers functions + * +@verbatim + =============================================================================== + ##### IO operation functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to manage the PCD data + transfers. + +@endverbatim + * @{ + */ + +/** + * @brief Start The USB OTG Device. + * @param hpcd: PCD handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCD_Start(PCD_HandleTypeDef *hpcd) +{ + __HAL_LOCK(hpcd); + USB_DevConnect (hpcd->Instance); + __HAL_PCD_ENABLE(hpcd); + __HAL_UNLOCK(hpcd); + return HAL_OK; +} + +/** + * @brief Stop The USB OTG Device. + * @param hpcd: PCD handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCD_Stop(PCD_HandleTypeDef *hpcd) +{ + __HAL_LOCK(hpcd); + __HAL_PCD_DISABLE(hpcd); + USB_StopDevice(hpcd->Instance); + USB_DevDisconnect (hpcd->Instance); + __HAL_UNLOCK(hpcd); + return HAL_OK; +} +#if defined (USB_OTG_FS) +/** + * @brief Handles PCD interrupt request. + * @param hpcd: PCD handle + * @retval HAL status + */ +void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd) +{ + USB_OTG_GlobalTypeDef *USBx = hpcd->Instance; + uint32_t index = 0U, ep_intr = 0U, epint = 0U, epnum = 0U; + uint32_t fifoemptymsk = 0U, temp = 0U; + USB_OTG_EPTypeDef *ep = NULL; + uint32_t hclk = 80000000; + + /* ensure that we are in device mode */ + if (USB_GetMode(hpcd->Instance) == USB_OTG_MODE_DEVICE) + { + /* avoid spurious interrupt */ + if(__HAL_PCD_IS_INVALID_INTERRUPT(hpcd)) + { + return; + } + + if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_MMIS)) + { + /* incorrect mode, acknowledge the interrupt */ + __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_MMIS); + } + + if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OEPINT)) + { + epnum = 0; + + /* Read in the device interrupt bits */ + ep_intr = USB_ReadDevAllOutEpInterrupt(hpcd->Instance); + + while (ep_intr) + { + if (ep_intr & 0x1) + { + epint = USB_ReadDevOutEPInterrupt(hpcd->Instance, epnum); + + if (( epint & USB_OTG_DOEPINT_XFRC) == USB_OTG_DOEPINT_XFRC) + { + CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_XFRC); + + /* setup/out transaction management for Core ID 310A */ + if (USBx->GSNPSID == USB_OTG_CORE_ID_310A) + { + if (!(USBx_OUTEP(0)->DOEPINT & (0x1 << 15))) + { + if (hpcd->Init.dma_enable == 1) + { + hpcd->OUT_ep[epnum].xfer_count = + hpcd->OUT_ep[epnum].maxpacket - + (USBx_OUTEP(epnum)->DOEPTSIZ & USB_OTG_DOEPTSIZ_XFRSIZ); + + hpcd->OUT_ep[epnum].xfer_buff += + hpcd->OUT_ep[epnum].maxpacket; + } + + HAL_PCD_DataOutStageCallback(hpcd, epnum); + + if (hpcd->Init.dma_enable == 1) + { + if (!epnum && !hpcd->OUT_ep[epnum].xfer_len) + { + /* this is ZLP, so prepare EP0 for next setup */ + USB_EP0_OutStart(hpcd->Instance, 1, (uint8_t *)hpcd->Setup); + } + } + } + + /* Clear the SetPktRcvd flag*/ + USBx_OUTEP(0)->DOEPINT |= (0x1 << 15) | (0x1 << 5); + } + else + { + if (hpcd->Init.dma_enable == 1) + { + hpcd->OUT_ep[epnum].xfer_count = + hpcd->OUT_ep[epnum].maxpacket - + (USBx_OUTEP(epnum)->DOEPTSIZ & USB_OTG_DOEPTSIZ_XFRSIZ); + hpcd->OUT_ep[epnum].xfer_buff += hpcd->OUT_ep[epnum].maxpacket; + } + + HAL_PCD_DataOutStageCallback(hpcd, epnum); + + if (hpcd->Init.dma_enable == 1) + { + if (!epnum && !hpcd->OUT_ep[epnum].xfer_len) + { + /* this is ZLP, so prepare EP0 for next setup */ + USB_EP0_OutStart(hpcd->Instance, 1, (uint8_t *)hpcd->Setup); + } + } + } + } + + if(( epint & USB_OTG_DOEPINT_STUP) == USB_OTG_DOEPINT_STUP) + { + /* Inform the upper layer that a setup packet is available */ + HAL_PCD_SetupStageCallback(hpcd); + CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STUP); + } + + if(( epint & USB_OTG_DOEPINT_OTEPDIS) == USB_OTG_DOEPINT_OTEPDIS) + { + CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPDIS); + } + +#ifdef USB_OTG_DOEPINT_OTEPSPR + /* Clear Status Phase Received interrupt */ + if(( epint & USB_OTG_DOEPINT_OTEPSPR) == USB_OTG_DOEPINT_OTEPSPR) + { + CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPSPR); + } +#endif /* USB_OTG_DOEPINT_OTEPSPR */ + } + epnum++; + ep_intr >>= 1; + } + } + + if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IEPINT)) + { + /* Read in the device interrupt bits */ + ep_intr = USB_ReadDevAllInEpInterrupt(hpcd->Instance); + + epnum = 0; + + while ( ep_intr ) + { + if (ep_intr & 0x1) /* In ITR */ + { + epint = USB_ReadDevInEPInterrupt(hpcd->Instance, epnum); + + if(( epint & USB_OTG_DIEPINT_XFRC) == USB_OTG_DIEPINT_XFRC) + { + fifoemptymsk = 0x1 << epnum; + USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk; + + CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_XFRC); + + if (hpcd->Init.dma_enable == 1) + { + hpcd->IN_ep[epnum].xfer_buff += hpcd->IN_ep[epnum].maxpacket; + } + + HAL_PCD_DataInStageCallback(hpcd, epnum); + + if (hpcd->Init.dma_enable == 1) + { + /* this is ZLP, so prepare EP0 for next setup */ + if((epnum == 0) && (hpcd->IN_ep[epnum].xfer_len == 0)) + { + /* prepare to rx more setup packets */ + USB_EP0_OutStart(hpcd->Instance, 1, (uint8_t *)hpcd->Setup); + } + } + } + if(( epint & USB_OTG_DIEPINT_TOC) == USB_OTG_DIEPINT_TOC) + { + CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_TOC); + } + if(( epint & USB_OTG_DIEPINT_ITTXFE) == USB_OTG_DIEPINT_ITTXFE) + { + CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_ITTXFE); + } + if(( epint & USB_OTG_DIEPINT_INEPNE) == USB_OTG_DIEPINT_INEPNE) + { + CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_INEPNE); + } + if(( epint & USB_OTG_DIEPINT_EPDISD) == USB_OTG_DIEPINT_EPDISD) + { + CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_EPDISD); + } + if(( epint & USB_OTG_DIEPINT_TXFE) == USB_OTG_DIEPINT_TXFE) + { + PCD_WriteEmptyTxFifo(hpcd , epnum); + } + } + epnum++; + ep_intr >>= 1; + } + } + + /* Handle Resume Interrupt */ + if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT)) + { + /* Clear the Remote Wake-up Signaling */ + USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG; + + if(hpcd->LPM_State == LPM_L1) + { + hpcd->LPM_State = LPM_L0; + HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L0_ACTIVE); + } + else + { + HAL_PCD_ResumeCallback(hpcd); + } + + __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT); + } + + /* Handle Suspend Interrupt */ + if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP)) + { + if((USBx_DEVICE->DSTS & USB_OTG_DSTS_SUSPSTS) == USB_OTG_DSTS_SUSPSTS) + { + + HAL_PCD_SuspendCallback(hpcd); + } + __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP); + } + + /* Handle LPM Interrupt */ + if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_LPMINT)) + { + __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_LPMINT); + if( hpcd->LPM_State == LPM_L0) + { + hpcd->LPM_State = LPM_L1; + hpcd->BESL = (hpcd->Instance->GLPMCFG & USB_OTG_GLPMCFG_BESL) >>2 ; + HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L1_ACTIVE); + } + else + { + HAL_PCD_SuspendCallback(hpcd); + } + } + + /* Handle Reset Interrupt */ + if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBRST)) + { + USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG; + USB_FlushTxFifo(hpcd->Instance , 0x10); + + for (index = 0; index < hpcd->Init.dev_endpoints ; index++) + { + USBx_INEP(index)->DIEPINT = 0xFF; + USBx_OUTEP(index)->DOEPINT = 0xFF; + } + USBx_DEVICE->DAINT = 0xFFFFFFFF; + USBx_DEVICE->DAINTMSK |= 0x10001; + + if(hpcd->Init.use_dedicated_ep1) + { + USBx_DEVICE->DOUTEP1MSK |= (USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM | USB_OTG_DOEPMSK_EPDM); + USBx_DEVICE->DINEP1MSK |= (USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM | USB_OTG_DIEPMSK_EPDM); + } + else + { +#ifdef USB_OTG_DOEPINT_OTEPSPR + USBx_DEVICE->DOEPMSK |= (USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM | USB_OTG_DOEPMSK_EPDM | USB_OTG_DOEPMSK_OTEPSPRM); +#else + USBx_DEVICE->DOEPMSK |= (USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM | USB_OTG_DOEPMSK_EPDM); +#endif /* USB_OTG_DOEPINT_OTEPSPR */ + USBx_DEVICE->DIEPMSK |= (USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM | USB_OTG_DIEPMSK_EPDM); + } + + /* Set Default Address to 0 */ + USBx_DEVICE->DCFG &= ~USB_OTG_DCFG_DAD; + + /* setup EP0 to receive SETUP packets */ + USB_EP0_OutStart(hpcd->Instance, hpcd->Init.dma_enable, (uint8_t *)hpcd->Setup); + + __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBRST); + } + + /* Handle Enumeration done Interrupt */ + if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE)) + { + USB_ActivateSetup(hpcd->Instance); + hpcd->Instance->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT; + + hpcd->Init.speed = USB_OTG_SPEED_FULL; + hpcd->Init.ep0_mps = USB_OTG_FS_MAX_PACKET_SIZE ; + + /* The USBTRD is configured according to the tables below, depending on AHB frequency + used by application. In the low AHB frequency range it is used to stretch enough the USB response + time to IN tokens, the USB turnaround time, so to compensate for the longer AHB read access + latency to the Data FIFO */ + + /* Get hclk frequency value */ + hclk = HAL_RCC_GetHCLKFreq(); + + if((hclk >= 14200000)&&(hclk < 15000000)) + { + /* hclk Clock Range between 14.2-15 MHz */ + hpcd->Instance->GUSBCFG |= (uint32_t)((0xF << 10) & USB_OTG_GUSBCFG_TRDT); + } + + else if((hclk >= 15000000)&&(hclk < 16000000)) + { + /* hclk Clock Range between 15-16 MHz */ + hpcd->Instance->GUSBCFG |= (uint32_t)((0xE << 10) & USB_OTG_GUSBCFG_TRDT); + } + + else if((hclk >= 16000000)&&(hclk < 17200000)) + { + /* hclk Clock Range between 16-17.2 MHz */ + hpcd->Instance->GUSBCFG |= (uint32_t)((0xD << 10) & USB_OTG_GUSBCFG_TRDT); + } + + else if((hclk >= 17200000)&&(hclk < 18500000)) + { + /* hclk Clock Range between 17.2-18.5 MHz */ + hpcd->Instance->GUSBCFG |= (uint32_t)((0xC << 10) & USB_OTG_GUSBCFG_TRDT); + } + + else if((hclk >= 18500000)&&(hclk < 20000000)) + { + /* hclk Clock Range between 18.5-20 MHz */ + hpcd->Instance->GUSBCFG |= (uint32_t)((0xB << 10) & USB_OTG_GUSBCFG_TRDT); + } + + else if((hclk >= 20000000)&&(hclk < 21800000)) + { + /* hclk Clock Range between 20-21.8 MHz */ + hpcd->Instance->GUSBCFG |= (uint32_t)((0xA << 10) & USB_OTG_GUSBCFG_TRDT); + } + + else if((hclk >= 21800000)&&(hclk < 24000000)) + { + /* hclk Clock Range between 21.8-24 MHz */ + hpcd->Instance->GUSBCFG |= (uint32_t)((0x9 << 10) & USB_OTG_GUSBCFG_TRDT); + } + + else if((hclk >= 24000000)&&(hclk < 27700000)) + { + /* hclk Clock Range between 24-27.7 MHz */ + hpcd->Instance->GUSBCFG |= (uint32_t)((0x8 << 10) & USB_OTG_GUSBCFG_TRDT); + } + + else if((hclk >= 27700000)&&(hclk < 32000000)) + { + /* hclk Clock Range between 27.7-32 MHz */ + hpcd->Instance->GUSBCFG |= (uint32_t)((0x7 << 10) & USB_OTG_GUSBCFG_TRDT); + } + + else /* if(hclk >= 32000000) */ + { + /* hclk Clock Range between 32-80 MHz */ + hpcd->Instance->GUSBCFG |= (uint32_t)((0x6 << 10) & USB_OTG_GUSBCFG_TRDT); + } + + HAL_PCD_ResetCallback(hpcd); + + __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE); + } + + /* Handle RxQLevel Interrupt */ + if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_RXFLVL)) + { + USB_MASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL); + + temp = USBx->GRXSTSP; + + ep = &hpcd->OUT_ep[temp & USB_OTG_GRXSTSP_EPNUM]; + + if(((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17) == STS_DATA_UPDT) + { + if((temp & USB_OTG_GRXSTSP_BCNT) != 0) + { + USB_ReadPacket(USBx, ep->xfer_buff, (temp & USB_OTG_GRXSTSP_BCNT) >> 4); + ep->xfer_buff += (temp & USB_OTG_GRXSTSP_BCNT) >> 4; + ep->xfer_count += (temp & USB_OTG_GRXSTSP_BCNT) >> 4; + } + } + else if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17) == STS_SETUP_UPDT) + { + USB_ReadPacket(USBx, (uint8_t *)hpcd->Setup, 8); + ep->xfer_count += (temp & USB_OTG_GRXSTSP_BCNT) >> 4; + } + USB_UNMASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL); + } + + /* Handle SOF Interrupt */ + if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SOF)) + { + HAL_PCD_SOFCallback(hpcd); + __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SOF); + } + + /* Handle Incomplete ISO IN Interrupt */ + if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR)) + { + HAL_PCD_ISOINIncompleteCallback(hpcd, epnum); + __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR); + } + + /* Handle Incomplete ISO OUT Interrupt */ + if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT)) + { + HAL_PCD_ISOOUTIncompleteCallback(hpcd, epnum); + __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT); + } + + /* Handle Connection event Interrupt */ + if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT)) + { + HAL_PCD_ConnectCallback(hpcd); + __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT); + } + + /* Handle Disconnection event Interrupt */ + if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OTGINT)) + { + temp = hpcd->Instance->GOTGINT; + + if((temp & USB_OTG_GOTGINT_SEDET) == USB_OTG_GOTGINT_SEDET) + { + HAL_PCD_DisconnectCallback(hpcd); + } + hpcd->Instance->GOTGINT |= temp; + } + } +} + +#endif /* USB_OTG_FS */ + +#if defined (USB) +/** + * @brief This function handles PCD interrupt request. + * @param hpcd: PCD handle + * @retval HAL status + */ +void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd) +{ + uint32_t wInterrupt_Mask = 0; + + if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_CTR)) + { + /* servicing of the endpoint correct transfer interrupt */ + /* clear of the CTR flag into the sub */ + PCD_EP_ISR_Handler(hpcd); + } + + if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_RESET)) + { + __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_RESET); + HAL_PCD_ResetCallback(hpcd); + HAL_PCD_SetAddress(hpcd, 0); + } + + if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_PMAOVR)) + { + __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_PMAOVR); + } + + if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_ERR)) + { + __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_ERR); + } + + if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_WKUP)) + { + + hpcd->Instance->CNTR &= ~(USB_CNTR_LPMODE); + + /*set wInterrupt_Mask global variable*/ + wInterrupt_Mask = USB_CNTR_CTRM | USB_CNTR_WKUPM | USB_CNTR_SUSPM | USB_CNTR_ERRM \ + | USB_CNTR_SOFM | USB_CNTR_ESOFM | USB_CNTR_RESETM; + + /*Set interrupt mask*/ + hpcd->Instance->CNTR = wInterrupt_Mask; + + /* enable L1REQ interrupt */ + if (hpcd->Init.lpm_enable ==1) + { + wInterrupt_Mask |= USB_CNTR_L1REQM; + + /* Enable LPM support and enable ACK answer to LPM request*/ + USB_TypeDef *USBx = hpcd->Instance; + hpcd->lpm_active = ENABLE; + hpcd->LPM_State = LPM_L0; + + USBx->LPMCSR |= (USB_LPMCSR_LMPEN); + USBx->LPMCSR |= (USB_LPMCSR_LPMACK); + } + + if(hpcd->LPM_State == LPM_L1) + { + hpcd->LPM_State = LPM_L0; + HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L0_ACTIVE); + } + + HAL_PCD_ResumeCallback(hpcd); + + __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_WKUP); + } + + if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_SUSP)) + { + /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */ + __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_SUSP); + + /* Force low-power mode in the macrocell */ + hpcd->Instance->CNTR |= USB_CNTR_FSUSP; + hpcd->Instance->CNTR |= USB_CNTR_LPMODE; + + if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_WKUP) == 0) + { + HAL_PCD_SuspendCallback(hpcd); + } + } + + /* Handle LPM Interrupt */ + if(__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_L1REQ)) + { + __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_L1REQ); + if( hpcd->LPM_State == LPM_L0) + { + /* Force suspend and low-power mode before going to L1 state*/ + hpcd->Instance->CNTR |= USB_CNTR_LPMODE; + hpcd->Instance->CNTR |= USB_CNTR_FSUSP; + + hpcd->LPM_State = LPM_L1; + hpcd->BESL = (hpcd->Instance->LPMCSR & USB_LPMCSR_BESL) >>2 ; + HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L1_ACTIVE); + } + else + { + HAL_PCD_SuspendCallback(hpcd); + } + } + + if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_SOF)) + { + __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_SOF); + HAL_PCD_SOFCallback(hpcd); + } + + if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_ESOF)) + { + /* clear ESOF flag in ISTR */ + __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_ESOF); + } +} +#endif /* USB */ + +/** + * @brief Data OUT stage callback. + * @param hpcd: PCD handle + * @param epnum: endpoint number + * @retval None + */ +__weak void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hpcd); + UNUSED(epnum); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_PCD_DataOutStageCallback could be implemented in the user file + */ +} + +/** + * @brief Data IN stage callback. + * @param hpcd: PCD handle + * @param epnum: endpoint number + * @retval None + */ +__weak void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hpcd); + UNUSED(epnum); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_PCD_DataInStageCallback could be implemented in the user file + */ +} +/** + * @brief Setup stage callback. + * @param hpcd: PCD handle + * @retval None + */ +__weak void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hpcd); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_PCD_SetupStageCallback could be implemented in the user file + */ +} + +/** + * @brief USB Start Of Frame callback. + * @param hpcd: PCD handle + * @retval None + */ +__weak void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hpcd); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_PCD_SOFCallback could be implemented in the user file + */ +} + +/** + * @brief USB Reset callback. + * @param hpcd: PCD handle + * @retval None + */ +__weak void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hpcd); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_PCD_ResetCallback could be implemented in the user file + */ +} + +/** + * @brief Suspend event callback. + * @param hpcd: PCD handle + * @retval None + */ +__weak void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hpcd); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_PCD_SuspendCallback could be implemented in the user file + */ +} + +/** + * @brief Resume event callback. + * @param hpcd: PCD handle + * @retval None + */ +__weak void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hpcd); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_PCD_ResumeCallback could be implemented in the user file + */ +} + +/** + * @brief Incomplete ISO OUT callback. + * @param hpcd: PCD handle + * @param epnum: endpoint number + * @retval None + */ +__weak void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hpcd); + UNUSED(epnum); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_PCD_ISOOUTIncompleteCallback could be implemented in the user file + */ +} + +/** + * @brief Incomplete ISO IN callback. + * @param hpcd: PCD handle + * @param epnum: endpoint number + * @retval None + */ +__weak void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hpcd); + UNUSED(epnum); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_PCD_ISOINIncompleteCallback could be implemented in the user file + */ +} + +/** + * @brief Connection event callback. + * @param hpcd: PCD handle + * @retval None + */ +__weak void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hpcd); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_PCD_ConnectCallback could be implemented in the user file + */ +} + +/** + * @brief Disconnection event callback. + * @param hpcd: PCD handle + * @retval None + */ +__weak void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hpcd); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_PCD_DisconnectCallback could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup PCD_Exported_Functions_Group3 Peripheral Control functions + * @brief management functions + * +@verbatim + =============================================================================== + ##### Peripheral Control functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to control the PCD data + transfers. + +@endverbatim + * @{ + */ + +/** + * @brief Connect the USB device. + * @param hpcd: PCD handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCD_DevConnect(PCD_HandleTypeDef *hpcd) +{ + __HAL_LOCK(hpcd); + USB_DevConnect(hpcd->Instance); + __HAL_UNLOCK(hpcd); + return HAL_OK; +} + +/** + * @brief Disconnect the USB device. + * @param hpcd: PCD handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCD_DevDisconnect(PCD_HandleTypeDef *hpcd) +{ + __HAL_LOCK(hpcd); + USB_DevDisconnect(hpcd->Instance); + __HAL_UNLOCK(hpcd); + return HAL_OK; +} + +/** + * @brief Set the USB Device address. + * @param hpcd: PCD handle + * @param address: new device address + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCD_SetAddress(PCD_HandleTypeDef *hpcd, uint8_t address) +{ + __HAL_LOCK(hpcd); + hpcd->USB_Address = address; + USB_SetDevAddress(hpcd->Instance, address); + __HAL_UNLOCK(hpcd); + return HAL_OK; +} +/** + * @brief Open and configure an endpoint. + * @param hpcd: PCD handle + * @param ep_addr: endpoint address + * @param ep_mps: endpoint max packet size + * @param ep_type: endpoint type + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCD_EP_Open(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint16_t ep_mps, uint8_t ep_type) +{ + HAL_StatusTypeDef ret = HAL_OK; + PCD_EPTypeDef *ep = NULL; + + if ((ep_addr & 0x80) == 0x80) + { + ep = &hpcd->IN_ep[ep_addr & 0x7F]; + } + else + { + ep = &hpcd->OUT_ep[ep_addr & 0x7F]; + } + ep->num = ep_addr & 0x7F; + + ep->is_in = (0x80 & ep_addr) != 0; + ep->maxpacket = ep_mps; + ep->type = ep_type; + + __HAL_LOCK(hpcd); + USB_ActivateEndpoint(hpcd->Instance , ep); + __HAL_UNLOCK(hpcd); + return ret; + +} + + +/** + * @brief Deactivate an endpoint. + * @param hpcd: PCD handle + * @param ep_addr: endpoint address + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCD_EP_Close(PCD_HandleTypeDef *hpcd, uint8_t ep_addr) +{ + PCD_EPTypeDef *ep = NULL; + + if ((ep_addr & 0x80) == 0x80) + { + ep = &hpcd->IN_ep[ep_addr & 0x7F]; + } + else + { + ep = &hpcd->OUT_ep[ep_addr & 0x7F]; + } + ep->num = ep_addr & 0x7F; + + ep->is_in = (0x80 & ep_addr) != 0; + + __HAL_LOCK(hpcd); + USB_DeactivateEndpoint(hpcd->Instance , ep); + __HAL_UNLOCK(hpcd); + return HAL_OK; +} + + +/** + * @brief Receive an amount of data. + * @param hpcd: PCD handle + * @param ep_addr: endpoint address + * @param pBuf: pointer to the reception buffer + * @param len: amount of data to be received + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCD_EP_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len) +{ + PCD_EPTypeDef *ep = NULL; + + ep = &hpcd->OUT_ep[ep_addr & 0x7F]; + + /*setup and start the Xfer */ + ep->xfer_buff = pBuf; + ep->xfer_len = len; + ep->xfer_count = 0; + ep->is_in = 0; + ep->num = ep_addr & 0x7F; + + if ((ep_addr & 0x7F) == 0 ) + { + USB_EP0StartXfer(hpcd->Instance, ep, hpcd->Init.dma_enable); + } + else + { + USB_EPStartXfer(hpcd->Instance, ep, hpcd->Init.dma_enable); + } + + return HAL_OK; +} + +/** + * @brief Get Received Data Size. + * @param hpcd: PCD handle + * @param ep_addr: endpoint address + * @retval Data Size + */ +uint16_t HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef *hpcd, uint8_t ep_addr) +{ + return hpcd->OUT_ep[ep_addr & 0x7F].xfer_count; +} +/** + * @brief Send an amount of data. + * @param hpcd: PCD handle + * @param ep_addr: endpoint address + * @param pBuf: pointer to the transmission buffer + * @param len: amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCD_EP_Transmit(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len) +{ + PCD_EPTypeDef *ep = NULL; + + ep = &hpcd->IN_ep[ep_addr & 0x7F]; + + /*setup and start the Xfer */ + ep->xfer_buff = pBuf; + ep->xfer_len = len; + ep->xfer_count = 0; + ep->is_in = 1; + ep->num = ep_addr & 0x7F; + + if ((ep_addr & 0x7F) == 0 ) + { + USB_EP0StartXfer(hpcd->Instance,ep, hpcd->Init.dma_enable); + } + else + { + USB_EPStartXfer(hpcd->Instance, ep, hpcd->Init.dma_enable); + } + + return HAL_OK; +} + +/** + * @brief Set a STALL condition over an endpoint. + * @param hpcd: PCD handle + * @param ep_addr: endpoint address + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCD_EP_SetStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr) +{ + PCD_EPTypeDef *ep = NULL; + + if ((0x80 & ep_addr) == 0x80) + { + ep = &hpcd->IN_ep[ep_addr & 0x7F]; + } + else + { + ep = &hpcd->OUT_ep[ep_addr]; + } + + ep->is_stall = 1; + ep->num = ep_addr & 0x7F; + ep->is_in = ((ep_addr & 0x80) == 0x80); + + __HAL_LOCK(hpcd); + USB_EPSetStall(hpcd->Instance , ep); + if((ep_addr & 0x7F) == 0) + { + USB_EP0_OutStart(hpcd->Instance, hpcd->Init.dma_enable, (uint8_t *)hpcd->Setup); + } + __HAL_UNLOCK(hpcd); + + return HAL_OK; +} + +/** + * @brief Clear a STALL condition over in an endpoint. + * @param hpcd: PCD handle + * @param ep_addr: endpoint address + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCD_EP_ClrStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr) +{ + PCD_EPTypeDef *ep = NULL; + + if ((0x80 & ep_addr) == 0x80) + { + ep = &hpcd->IN_ep[ep_addr & 0x7F]; + } + else + { + ep = &hpcd->OUT_ep[ep_addr]; + } + + ep->is_stall = 0; + ep->num = ep_addr & 0x7F; + ep->is_in = ((ep_addr & 0x80) == 0x80); + + __HAL_LOCK(hpcd); + USB_EPClearStall(hpcd->Instance , ep); + __HAL_UNLOCK(hpcd); + + return HAL_OK; +} + +/** + * @brief Flush an endpoint. + * @param hpcd: PCD handle + * @param ep_addr: endpoint address + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCD_EP_Flush(PCD_HandleTypeDef *hpcd, uint8_t ep_addr) +{ + __HAL_LOCK(hpcd); + + if ((ep_addr & 0x80) == 0x80) + { + USB_FlushTxFifo(hpcd->Instance, ep_addr & 0x7F); + } + else + { + USB_FlushRxFifo(hpcd->Instance); + } + + __HAL_UNLOCK(hpcd); + + return HAL_OK; +} + +/** + * @brief Activate remote wakeup signalling. + * @param hpcd: PCD handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCD_ActivateRemoteWakeup(PCD_HandleTypeDef *hpcd) +{ + return(USB_ActivateRemoteWakeup(hpcd->Instance)); +} + +/** + * @brief De-activate remote wakeup signalling. + * @param hpcd: PCD handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCD_DeActivateRemoteWakeup(PCD_HandleTypeDef *hpcd) +{ + return(USB_DeActivateRemoteWakeup(hpcd->Instance)); +} +/** + * @} + */ + +/** @defgroup PCD_Exported_Functions_Group4 Peripheral State functions + * @brief Peripheral State functions + * +@verbatim + =============================================================================== + ##### Peripheral State functions ##### + =============================================================================== + [..] + This subsection permits to get in run-time the status of the peripheral + and the data flow. + +@endverbatim + * @{ + */ + +/** + * @brief Return the PCD handle state. + * @param hpcd: PCD handle + * @retval HAL state + */ +PCD_StateTypeDef HAL_PCD_GetState(PCD_HandleTypeDef *hpcd) +{ + return hpcd->State; +} +/** + * @} + */ + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ +/** @addtogroup PCD_Private_Functions + * @{ + */ +#if defined (USB_OTG_FS) +/** + * @brief Check FIFO for the next packet to be loaded. + * @param hpcd: PCD handle + * @param epnum: endpoint number + * @retval HAL status + */ +static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum) +{ + USB_OTG_GlobalTypeDef *USBx = hpcd->Instance; + USB_OTG_EPTypeDef *ep = NULL; + int32_t len = 0U; + uint32_t len32b = 0; + uint32_t fifoemptymsk = 0; + + ep = &hpcd->IN_ep[epnum]; + len = ep->xfer_len - ep->xfer_count; + + if (len > ep->maxpacket) + { + len = ep->maxpacket; + } + + + len32b = (len + 3) / 4; + + while ( (USBx_INEP(epnum)->DTXFSTS & USB_OTG_DTXFSTS_INEPTFSAV) > len32b && + ep->xfer_count < ep->xfer_len && + ep->xfer_len != 0) + { + /* Write the FIFO */ + len = ep->xfer_len - ep->xfer_count; + + if (len > ep->maxpacket) + { + len = ep->maxpacket; + } + len32b = (len + 3) / 4; + + USB_WritePacket(USBx, ep->xfer_buff, epnum, len, hpcd->Init.dma_enable); + + ep->xfer_buff += len; + ep->xfer_count += len; + } + + if(len <= 0) + { + fifoemptymsk = 0x1 << epnum; + USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk; + + } + + return HAL_OK; +} +#endif /* USB_OTG_FS */ + +#if defined (USB) +/** + * @brief This function handles PCD Endpoint interrupt request. + * @param hpcd: PCD handle + * @retval HAL status + */ +static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd) +{ + PCD_EPTypeDef *ep = NULL; + uint16_t count = 0; + uint8_t epindex = 0; + __IO uint16_t wIstr = 0; + __IO uint16_t wEPVal = 0; + + /* stay in loop while pending interrupts */ + while (((wIstr = hpcd->Instance->ISTR) & USB_ISTR_CTR) != 0) + { + /* extract highest priority endpoint number */ + epindex = (uint8_t)(wIstr & USB_ISTR_EP_ID); + + if (epindex == 0) + { + /* Decode and service control endpoint interrupt */ + + /* DIR bit = origin of the interrupt */ + if ((wIstr & USB_ISTR_DIR) == 0) + { + /* DIR = 0 */ + + /* DIR = 0 => IN int */ + /* DIR = 0 implies that (EP_CTR_TX = 1) always */ + PCD_CLEAR_TX_EP_CTR(hpcd->Instance, PCD_ENDP0); + ep = &hpcd->IN_ep[0]; + + ep->xfer_count = PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num); + ep->xfer_buff += ep->xfer_count; + + /* TX COMPLETE */ + HAL_PCD_DataInStageCallback(hpcd, 0); + + + if((hpcd->USB_Address > 0)&& ( ep->xfer_len == 0)) + { + hpcd->Instance->DADDR = (hpcd->USB_Address | USB_DADDR_EF); + hpcd->USB_Address = 0; + } + + } + else + { + /* DIR = 1 */ + + /* DIR = 1 & CTR_RX => SETUP or OUT int */ + /* DIR = 1 & (CTR_TX | CTR_RX) => 2 int pending */ + ep = &hpcd->OUT_ep[0]; + wEPVal = PCD_GET_ENDPOINT(hpcd->Instance, PCD_ENDP0); + + if ((wEPVal & USB_EP_SETUP) != 0) + { + /* Get SETUP Packet*/ + ep->xfer_count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num); + USB_ReadPMA(hpcd->Instance, (uint8_t*)hpcd->Setup ,ep->pmaadress , ep->xfer_count); + /* SETUP bit kept frozen while CTR_RX = 1*/ + PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0); + + /* Process SETUP Packet*/ + HAL_PCD_SetupStageCallback(hpcd); + } + + else if ((wEPVal & USB_EP_CTR_RX) != 0) + { + PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0); + /* Get Control Data OUT Packet*/ + ep->xfer_count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num); + + if (ep->xfer_count != 0) + { + USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, ep->xfer_count); + ep->xfer_buff+=ep->xfer_count; + } + + /* Process Control Data OUT Packet*/ + HAL_PCD_DataOutStageCallback(hpcd, 0); + + PCD_SET_EP_RX_CNT(hpcd->Instance, PCD_ENDP0, ep->maxpacket); + PCD_SET_EP_RX_STATUS(hpcd->Instance, PCD_ENDP0, USB_EP_RX_VALID); + } + } + } + else + { + /* Decode and service non control endpoints interrupt */ + + /* process related endpoint register */ + wEPVal = PCD_GET_ENDPOINT(hpcd->Instance, epindex); + if ((wEPVal & USB_EP_CTR_RX) != 0) + { + /* clear int flag */ + PCD_CLEAR_RX_EP_CTR(hpcd->Instance, epindex); + ep = &hpcd->OUT_ep[epindex]; + + /* OUT double Buffering*/ + if (ep->doublebuffer == 0) + { + count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num); + if (count != 0) + { + USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, count); + } + } + else + { + if (PCD_GET_ENDPOINT(hpcd->Instance, ep->num) & USB_EP_DTOG_RX) + { + /*read from endpoint BUF0Addr buffer*/ + count = PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num); + if (count != 0) + { + USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr0, count); + } + } + else + { + /*read from endpoint BUF1Addr buffer*/ + count = PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num); + if (count != 0) + { + USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr1, count); + } + } + PCD_FreeUserBuffer(hpcd->Instance, ep->num, PCD_EP_DBUF_OUT); + } + /*multi-packet on the NON control OUT endpoint*/ + ep->xfer_count+=count; + ep->xfer_buff+=count; + + if ((ep->xfer_len == 0) || (count < ep->maxpacket)) + { + /* RX COMPLETE */ + HAL_PCD_DataOutStageCallback(hpcd, ep->num); + } + else + { + HAL_PCD_EP_Receive(hpcd, ep->num, ep->xfer_buff, ep->xfer_len); + } + + } /* if((wEPVal & EP_CTR_RX) */ + + if ((wEPVal & USB_EP_CTR_TX) != 0) + { + ep = &hpcd->IN_ep[epindex]; + + /* clear int flag */ + PCD_CLEAR_TX_EP_CTR(hpcd->Instance, epindex); + + /* IN double Buffering*/ + if (ep->doublebuffer == 0) + { + ep->xfer_count = PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num); + if (ep->xfer_count != 0) + { + USB_WritePMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, ep->xfer_count); + } + } + else + { + if (PCD_GET_ENDPOINT(hpcd->Instance, ep->num) & USB_EP_DTOG_TX) + { + /*read from endpoint BUF0Addr buffer*/ + ep->xfer_count = PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num); + if (ep->xfer_count != 0) + { + USB_WritePMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr0, ep->xfer_count); + } + } + else + { + /*read from endpoint BUF1Addr buffer*/ + ep->xfer_count = PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num); + if (ep->xfer_count != 0) + { + USB_WritePMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr1, ep->xfer_count); + } + } + PCD_FreeUserBuffer(hpcd->Instance, ep->num, PCD_EP_DBUF_IN); + } + /*multi-packet on the NON control IN endpoint*/ + ep->xfer_count = PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num); + ep->xfer_buff+=ep->xfer_count; + + /* Zero Length Packet? */ + if (ep->xfer_len == 0) + { + /* TX COMPLETE */ + HAL_PCD_DataInStageCallback(hpcd, ep->num); + } + else + { + HAL_PCD_EP_Transmit(hpcd, ep->num, ep->xfer_buff, ep->xfer_len); + } + } + } + } + return HAL_OK; +} +#endif /* USB */ + +/** + * @} + */ + +#endif /* STM32L432xx || STM32L433xx || STM32L442xx || STM32L443xx || */ + /* STM32L452xx || STM32L462xx || */ + /* STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx || */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#endif /* HAL_PCD_MODULE_ENABLED */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pcd_ex.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pcd_ex.c new file mode 100644 index 0000000..80fc7f9 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pcd_ex.c @@ -0,0 +1,523 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_pcd_ex.c + * @author MCD Application Team + * @brief PCD Extended HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the USB Peripheral Controller: + * + Extended features functions + * + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup PCDEx PCDEx + * @brief PCD Extended HAL module driver + * @{ + */ + +#ifdef HAL_PCD_MODULE_ENABLED + +#if defined(STM32L432xx) || defined(STM32L433xx) || defined(STM32L442xx) || defined(STM32L443xx) || \ + defined(STM32L452xx) || defined(STM32L462xx) || \ + defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || \ + defined(STM32L496xx) || defined(STM32L4A6xx) || \ + defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup PCDEx_Exported_Functions PCDEx Exported Functions + * @{ + */ + +/** @defgroup PCDEx_Exported_Functions_Group1 Peripheral Control functions + * @brief PCDEx control functions + * +@verbatim + =============================================================================== + ##### Extended features functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Update FIFO configuration + +@endverbatim + * @{ + */ +#if defined (USB_OTG_FS) +/** + * @brief Set Tx FIFO + * @param hpcd: PCD handle + * @param fifo: The number of Tx fifo + * @param size: Fifo size + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCDEx_SetTxFiFo(PCD_HandleTypeDef *hpcd, uint8_t fifo, uint16_t size) +{ + uint8_t index = 0; + uint32_t Tx_Offset = 0; + + /* TXn min size = 16 words. (n : Transmit FIFO index) + When a TxFIFO is not used, the Configuration should be as follows: + case 1 : n > m and Txn is not used (n,m : Transmit FIFO indexes) + --> Txm can use the space allocated for Txn. + case2 : n < m and Txn is not used (n,m : Transmit FIFO indexes) + --> Txn should be configured with the minimum space of 16 words + The FIFO is used optimally when used TxFIFOs are allocated in the top + of the FIFO.Ex: use EP1 and EP2 as IN instead of EP1 and EP3 as IN ones. + When DMA is used 3n * FIFO locations should be reserved for internal DMA registers */ + + Tx_Offset = hpcd->Instance->GRXFSIZ; + + if(fifo == 0) + { + hpcd->Instance->DIEPTXF0_HNPTXFSIZ = (size << 16) | Tx_Offset; + } + else + { + Tx_Offset += (hpcd->Instance->DIEPTXF0_HNPTXFSIZ) >> 16; + for (index = 0; index < (fifo - 1); index++) + { + Tx_Offset += (hpcd->Instance->DIEPTXF[index] >> 16); + } + + /* Multiply Tx_Size by 2 to get higher performance */ + hpcd->Instance->DIEPTXF[fifo - 1] = (size << 16) | Tx_Offset; + } + + return HAL_OK; +} + +/** + * @brief Set Rx FIFO + * @param hpcd: PCD handle + * @param size: Size of Rx fifo + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCDEx_SetRxFiFo(PCD_HandleTypeDef *hpcd, uint16_t size) +{ + hpcd->Instance->GRXFSIZ = size; + + return HAL_OK; +} + +/** + * @brief Activate LPM feature. + * @param hpcd: PCD handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCDEx_ActivateLPM(PCD_HandleTypeDef *hpcd) +{ + USB_OTG_GlobalTypeDef *USBx = hpcd->Instance; + + hpcd->lpm_active = ENABLE; + hpcd->LPM_State = LPM_L0; + USBx->GINTMSK |= USB_OTG_GINTMSK_LPMINTM; + USBx->GLPMCFG |= (USB_OTG_GLPMCFG_LPMEN | USB_OTG_GLPMCFG_LPMACK | USB_OTG_GLPMCFG_ENBESL); + + return HAL_OK; +} + +/** + * @brief Deactivate LPM feature. + * @param hpcd: PCD handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCDEx_DeActivateLPM(PCD_HandleTypeDef *hpcd) +{ + USB_OTG_GlobalTypeDef *USBx = hpcd->Instance; + + hpcd->lpm_active = DISABLE; + USBx->GINTMSK &= ~USB_OTG_GINTMSK_LPMINTM; + USBx->GLPMCFG &= ~(USB_OTG_GLPMCFG_LPMEN | USB_OTG_GLPMCFG_LPMACK | USB_OTG_GLPMCFG_ENBESL); + + return HAL_OK; +} + +/** + * @brief Handle BatteryCharging Process. + * @param hpcd: PCD handle + * @retval HAL status + */ +void HAL_PCDEx_BCD_VBUSDetect(PCD_HandleTypeDef *hpcd) +{ + USB_OTG_GlobalTypeDef *USBx = hpcd->Instance; + uint32_t tickstart = HAL_GetTick(); + + /* Start BCD When device is connected */ + if (USBx_DEVICE->DCTL & USB_OTG_DCTL_SDIS) + { + /* Enable DCD : Data Contact Detect */ + USBx->GCCFG |= USB_OTG_GCCFG_DCDEN; + + /* Wait Detect flag or a timeout is happen*/ + while ((USBx->GCCFG & USB_OTG_GCCFG_DCDET) == 0) + { + /* Check for the Timeout */ + if((HAL_GetTick() - tickstart ) > 1000) + { + HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_ERROR); + return; + } + } + + /* Right response got */ + HAL_Delay(100); + + /* Check Detect flag*/ + if (USBx->GCCFG & USB_OTG_GCCFG_DCDET) + { + HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_CONTACT_DETECTION); + } + + /*Primary detection: checks if connected to Standard Downstream Port + (without charging capability) */ + USBx->GCCFG &=~ USB_OTG_GCCFG_DCDEN; + USBx->GCCFG |= USB_OTG_GCCFG_PDEN; + HAL_Delay(100); + + if (!(USBx->GCCFG & USB_OTG_GCCFG_PDET)) + { + /* Case of Standard Downstream Port */ + HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_STD_DOWNSTREAM_PORT); + } + else + { + /* start secondary detection to check connection to Charging Downstream + Port or Dedicated Charging Port */ + USBx->GCCFG &=~ USB_OTG_GCCFG_PDEN; + USBx->GCCFG |= USB_OTG_GCCFG_SDEN; + HAL_Delay(100); + + if ((USBx->GCCFG) & USB_OTG_GCCFG_SDET) + { + /* case Dedicated Charging Port */ + HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_DEDICATED_CHARGING_PORT); + } + else + { + /* case Charging Downstream Port */ + HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_CHARGING_DOWNSTREAM_PORT); + } + } + /* Battery Charging capability discovery finished */ + HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_DISCOVERY_COMPLETED); + } +} + +/** + * @brief Activate BatteryCharging feature. + * @param hpcd: PCD handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCDEx_ActivateBCD(PCD_HandleTypeDef *hpcd) +{ + USB_OTG_GlobalTypeDef *USBx = hpcd->Instance; + + hpcd->battery_charging_active = ENABLE; + USBx->GCCFG |= (USB_OTG_GCCFG_BCDEN); + + return HAL_OK; +} + +/** + * @brief Deactivate BatteryCharging feature. + * @param hpcd: PCD handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCDEx_DeActivateBCD(PCD_HandleTypeDef *hpcd) +{ + USB_OTG_GlobalTypeDef *USBx = hpcd->Instance; + hpcd->battery_charging_active = DISABLE; + USBx->GCCFG &= ~(USB_OTG_GCCFG_BCDEN); + return HAL_OK; +} +#endif /* USB_OTG_FS */ + +#if defined (USB) +/** + * @brief Configure PMA for EP + * @param hpcd : Device instance + * @param ep_addr: endpoint address + * @param ep_kind: endpoint Kind + * USB_SNG_BUF: Single Buffer used + * USB_DBL_BUF: Double Buffer used + * @param pmaadress: EP address in The PMA: In case of single buffer endpoint + * this parameter is 16-bit value providing the address + * in PMA allocated to endpoint. + * In case of double buffer endpoint this parameter + * is a 32-bit value providing the endpoint buffer 0 address + * in the LSB part of 32-bit value and endpoint buffer 1 address + * in the MSB part of 32-bit value. + * @retval HAL status + */ + +HAL_StatusTypeDef HAL_PCDEx_PMAConfig(PCD_HandleTypeDef *hpcd, + uint16_t ep_addr, + uint16_t ep_kind, + uint32_t pmaadress) + +{ + PCD_EPTypeDef *ep = NULL; + + /* initialize ep structure*/ + if ((0x80 & ep_addr) == 0x80) + { + ep = &hpcd->IN_ep[ep_addr & 0x7F]; + } + else + { + ep = &hpcd->OUT_ep[ep_addr]; + } + + /* Here we check if the endpoint is single or double Buffer*/ + if (ep_kind == PCD_SNG_BUF) + { + /*Single Buffer*/ + ep->doublebuffer = 0; + /*Configure te PMA*/ + ep->pmaadress = (uint16_t)pmaadress; + } + else /*USB_DBL_BUF*/ + { + /*Double Buffer Endpoint*/ + ep->doublebuffer = 1; + /*Configure the PMA*/ + ep->pmaaddr0 = pmaadress & 0xFFFF; + ep->pmaaddr1 = (pmaadress & 0xFFFF0000) >> 16; + } + + return HAL_OK; +} + +/** + * @brief Activate BatteryCharging feature. + * @param hpcd: PCD handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCDEx_ActivateBCD(PCD_HandleTypeDef *hpcd) +{ + USB_TypeDef *USBx = hpcd->Instance; + hpcd->battery_charging_active = ENABLE; + + USBx->BCDR |= (USB_BCDR_BCDEN); + /* Enable DCD : Data Contact Detect */ + USBx->BCDR |= (USB_BCDR_DCDEN); + + return HAL_OK; +} + +/** + * @brief Deactivate BatteryCharging feature. + * @param hpcd: PCD handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCDEx_DeActivateBCD(PCD_HandleTypeDef *hpcd) +{ + USB_TypeDef *USBx = hpcd->Instance; + hpcd->battery_charging_active = DISABLE; + + USBx->BCDR &= ~(USB_BCDR_BCDEN); + return HAL_OK; +} + +/** + * @brief Handle BatteryCharging Process. + * @param hpcd: PCD handle + * @retval HAL status + */ +void HAL_PCDEx_BCD_VBUSDetect(PCD_HandleTypeDef *hpcd) +{ + USB_TypeDef *USBx = hpcd->Instance; + uint32_t tickstart = HAL_GetTick(); + + /* Wait Detect flag or a timeout is happen*/ + while ((USBx->BCDR & USB_BCDR_DCDET) == 0) + { + /* Check for the Timeout */ + if((HAL_GetTick() - tickstart ) > 1000) + { + HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_ERROR); + return; + } + } + + HAL_Delay(300); + + /* Data Pin Contact ? Check Detect flag */ + if (USBx->BCDR & USB_BCDR_DCDET) + { + HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_CONTACT_DETECTION); + } + /* Primary detection: checks if connected to Standard Downstream Port + (without charging capability) */ + USBx->BCDR &= ~(USB_BCDR_DCDEN); + USBx->BCDR |= (USB_BCDR_PDEN); + HAL_Delay(300); + + /* If Charger detect ? */ + if (USBx->BCDR & USB_BCDR_PDET) + { + /* Start secondary detection to check connection to Charging Downstream + Port or Dedicated Charging Port */ + USBx->BCDR &= ~(USB_BCDR_PDEN); + USBx->BCDR |= (USB_BCDR_SDEN); + HAL_Delay(300); + + /* If CDP ? */ + if (USBx->BCDR & USB_BCDR_SDET) + { + /* Dedicated Downstream Port DCP */ + HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_DEDICATED_CHARGING_PORT); + } + else + { + /* Charging Downstream Port CDP */ + HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_CHARGING_DOWNSTREAM_PORT); + + /* Battery Charging capability discovery finished + Start Enumeration*/ + HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_DISCOVERY_COMPLETED); + } + } + else /* NO */ + { + /* Standard Downstream Port */ + HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_STD_DOWNSTREAM_PORT); + } +} + +/** + * @brief Activate LPM feature. + * @param hpcd: PCD handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCDEx_ActivateLPM(PCD_HandleTypeDef *hpcd) +{ + + USB_TypeDef *USBx = hpcd->Instance; + hpcd->lpm_active = ENABLE; + hpcd->LPM_State = LPM_L0; + + USBx->LPMCSR |= (USB_LPMCSR_LMPEN); + USBx->LPMCSR |= (USB_LPMCSR_LPMACK); + + + return HAL_OK; +} + +/** + * @brief Deactivate LPM feature. + * @param hpcd: PCD handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCDEx_DeActivateLPM(PCD_HandleTypeDef *hpcd) +{ + USB_TypeDef *USBx = hpcd->Instance; + + hpcd->lpm_active = DISABLE; + + USBx->LPMCSR &= ~ (USB_LPMCSR_LMPEN); + USBx->LPMCSR &= ~ (USB_LPMCSR_LPMACK); + + return HAL_OK; +} + +#endif /* USB */ + +/** + * @brief Send LPM message to user layer callback. + * @param hpcd: PCD handle + * @param msg: LPM message + * @retval HAL status + */ +__weak void HAL_PCDEx_LPM_Callback(PCD_HandleTypeDef *hpcd, PCD_LPM_MsgTypeDef msg) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hpcd); + UNUSED(msg); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_PCDEx_LPM_Callback could be implemented in the user file + */ +} + +/** + * @brief Send BatteryCharging message to user layer callback. + * @param hpcd: PCD handle + * @param msg: LPM message + * @retval HAL status + */ +__weak void HAL_PCDEx_BCD_Callback(PCD_HandleTypeDef *hpcd, PCD_BCD_MsgTypeDef msg) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hpcd); + UNUSED(msg); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_PCDEx_BCD_Callback could be implemented in the user file + */ +} + +/** + * @} + */ + +/** + * @} + */ + +#endif /* STM32L432xx || STM32L433xx || STM32L442xx || STM32L443xx || */ + /* STM32L452xx || STM32L462xx || */ + /* STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx || */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#endif /* HAL_PCD_MODULE_ENABLED */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pwr.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pwr.c new file mode 100644 index 0000000..919b992 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pwr.c @@ -0,0 +1,674 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_pwr.c + * @author MCD Application Team + * @brief PWR HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Power Controller (PWR) peripheral: + * + Initialization/de-initialization functions + * + Peripheral Control functions + * + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup PWR PWR + * @brief PWR HAL module driver + * @{ + */ + +#ifdef HAL_PWR_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ + +/** @defgroup PWR_Private_Defines PWR Private Defines + * @{ + */ + +/** @defgroup PWR_PVD_Mode_Mask PWR PVD Mode Mask + * @{ + */ +#define PVD_MODE_IT ((uint32_t)0x00010000) /*!< Mask for interruption yielded by PVD threshold crossing */ +#define PVD_MODE_EVT ((uint32_t)0x00020000) /*!< Mask for event yielded by PVD threshold crossing */ +#define PVD_RISING_EDGE ((uint32_t)0x00000001) /*!< Mask for rising edge set as PVD trigger */ +#define PVD_FALLING_EDGE ((uint32_t)0x00000002) /*!< Mask for falling edge set as PVD trigger */ +/** + * @} + */ + +/** + * @} + */ + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup PWR_Exported_Functions PWR Exported Functions + * @{ + */ + +/** @defgroup PWR_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and de-initialization functions + * +@verbatim + =============================================================================== + ##### Initialization and de-initialization functions ##### + =============================================================================== + [..] + +@endverbatim + * @{ + */ + +/** + * @brief Deinitialize the HAL PWR peripheral registers to their default reset values. + * @retval None + */ +void HAL_PWR_DeInit(void) +{ + __HAL_RCC_PWR_FORCE_RESET(); + __HAL_RCC_PWR_RELEASE_RESET(); +} + +/** + * @brief Enable access to the backup domain + * (RTC registers, RTC backup data registers). + * @note After reset, the backup domain is protected against + * possible unwanted write accesses. + * @note RTCSEL that sets the RTC clock source selection is in the RTC back-up domain. + * In order to set or modify the RTC clock, the backup domain access must be + * disabled. + * @note LSEON bit that switches on and off the LSE crystal belongs as well to the + * back-up domain. + * @retval None + */ +void HAL_PWR_EnableBkUpAccess(void) +{ + SET_BIT(PWR->CR1, PWR_CR1_DBP); +} + +/** + * @brief Disable access to the backup domain + * (RTC registers, RTC backup data registers). + * @retval None + */ +void HAL_PWR_DisableBkUpAccess(void) +{ + CLEAR_BIT(PWR->CR1, PWR_CR1_DBP); +} + + + + +/** + * @} + */ + + + +/** @defgroup PWR_Exported_Functions_Group2 Peripheral Control functions + * @brief Low Power modes configuration functions + * +@verbatim + + =============================================================================== + ##### Peripheral Control functions ##### + =============================================================================== + + [..] + *** PVD configuration *** + ========================= + [..] + (+) The PVD is used to monitor the VDD power supply by comparing it to a + threshold selected by the PVD Level (PLS[2:0] bits in PWR_CR2 register). + + (+) PVDO flag is available to indicate if VDD/VDDA is higher or lower + than the PVD threshold. This event is internally connected to the EXTI + line16 and can generate an interrupt if enabled. This is done through + __HAL_PVD_EXTI_ENABLE_IT() macro. + (+) The PVD is stopped in Standby mode. + + + *** WakeUp pin configuration *** + ================================ + [..] + (+) WakeUp pins are used to wakeup the system from Standby mode or Shutdown mode. + The polarity of these pins can be set to configure event detection on high + level (rising edge) or low level (falling edge). + + + + *** Low Power modes configuration *** + ===================================== + [..] + The devices feature 8 low-power modes: + (+) Low-power Run mode: core and peripherals are running, main regulator off, low power regulator on. + (+) Sleep mode: Cortex-M4 core stopped, peripherals kept running, main and low power regulators on. + (+) Low-power Sleep mode: Cortex-M4 core stopped, peripherals kept running, main regulator off, low power regulator on. + (+) Stop 0 mode: all clocks are stopped except LSI and LSE, main and low power regulators on. + (+) Stop 1 mode: all clocks are stopped except LSI and LSE, main regulator off, low power regulator on. + (+) Stop 2 mode: all clocks are stopped except LSI and LSE, main regulator off, low power regulator on, reduced set of waking up IPs compared to Stop 1 mode. + (+) Standby mode with SRAM2: all clocks are stopped except LSI and LSE, SRAM2 content preserved, main regulator off, low power regulator on. + (+) Standby mode without SRAM2: all clocks are stopped except LSI and LSE, main and low power regulators off. + (+) Shutdown mode: all clocks are stopped except LSE, main and low power regulators off. + + + *** Low-power run mode *** + ========================== + [..] + (+) Entry: (from main run mode) + (++) set LPR bit with HAL_PWREx_EnableLowPowerRunMode() API after having decreased the system clock below 2 MHz. + + (+) Exit: + (++) clear LPR bit then wait for REGLP bit to be reset with HAL_PWREx_DisableLowPowerRunMode() API. Only + then can the system clock frequency be increased above 2 MHz. + + + *** Sleep mode / Low-power sleep mode *** + ========================================= + [..] + (+) Entry: + The Sleep mode / Low-power Sleep mode is entered thru HAL_PWR_EnterSLEEPMode() API + in specifying whether or not the regulator is forced to low-power mode and if exit is interrupt or event-triggered. + (++) PWR_MAINREGULATOR_ON: Sleep mode (regulator in main mode). + (++) PWR_LOWPOWERREGULATOR_ON: Low-power sleep (regulator in low power mode). + In the latter case, the system clock frequency must have been decreased below 2 MHz beforehand. + (++) PWR_SLEEPENTRY_WFI: enter SLEEP mode with WFI instruction + (++) PWR_SLEEPENTRY_WFE: enter SLEEP mode with WFE instruction + + (+) WFI Exit: + (++) Any peripheral interrupt acknowledged by the nested vectored interrupt + controller (NVIC) or any wake-up event. + + (+) WFE Exit: + (++) Any wake-up event such as an EXTI line configured in event mode. + + [..] When exiting the Low-power sleep mode by issuing an interrupt or a wakeup event, + the MCU is in Low-power Run mode. + + *** Stop 0, Stop 1 and Stop 2 modes *** + =============================== + [..] + (+) Entry: + The Stop 0, Stop 1 or Stop 2 modes are entered thru the following API's: + (++) HAL_PWREx_EnterSTOP0Mode() for mode 0 or HAL_PWREx_EnterSTOP1Mode() for mode 1 or for porting reasons HAL_PWR_EnterSTOPMode(). + (++) HAL_PWREx_EnterSTOP2Mode() for mode 2. + (+) Regulator setting (applicable to HAL_PWR_EnterSTOPMode() only): + (++) PWR_MAINREGULATOR_ON + (++) PWR_LOWPOWERREGULATOR_ON + (+) Exit (interrupt or event-triggered, specified when entering STOP mode): + (++) PWR_STOPENTRY_WFI: enter Stop mode with WFI instruction + (++) PWR_STOPENTRY_WFE: enter Stop mode with WFE instruction + + (+) WFI Exit: + (++) Any EXTI Line (Internal or External) configured in Interrupt mode. + (++) Some specific communication peripherals (USART, LPUART, I2C) interrupts + when programmed in wakeup mode. + (+) WFE Exit: + (++) Any EXTI Line (Internal or External) configured in Event mode. + + [..] + When exiting Stop 0 and Stop 1 modes, the MCU is either in Run mode or in Low-power Run mode + depending on the LPR bit setting. + When exiting Stop 2 mode, the MCU is in Run mode. + + *** Standby mode *** + ==================== + [..] + The Standby mode offers two options: + (+) option a) all clocks off except LSI and LSE, RRS bit set (keeps voltage regulator in low power mode). + SRAM and registers contents are lost except for the SRAM2 content, the RTC registers, RTC backup registers + and Standby circuitry. + (+) option b) all clocks off except LSI and LSE, RRS bit cleared (voltage regulator then disabled). + SRAM and register contents are lost except for the RTC registers, RTC backup registers + and Standby circuitry. + + (++) Entry: + (+++) The Standby mode is entered thru HAL_PWR_EnterSTANDBYMode() API. + SRAM1 and register contents are lost except for registers in the Backup domain and + Standby circuitry. SRAM2 content can be preserved if the bit RRS is set in PWR_CR3 register. + To enable this feature, the user can resort to HAL_PWREx_EnableSRAM2ContentRetention() API + to set RRS bit. + + (++) Exit: + (+++) WKUP pin rising edge, RTC alarm or wakeup, tamper event, time-stamp event, + external reset in NRST pin, IWDG reset. + + [..] After waking up from Standby mode, program execution restarts in the same way as after a Reset. + + + *** Shutdown mode *** + ====================== + [..] + In Shutdown mode, + voltage regulator is disabled, all clocks are off except LSE, RRS bit is cleared. + SRAM and registers contents are lost except for backup domain registers. + + (+) Entry: + The Shutdown mode is entered thru HAL_PWREx_EnterSHUTDOWNMode() API. + + (+) Exit: + (++) WKUP pin rising edge, RTC alarm or wakeup, tamper event, time-stamp event, + external reset in NRST pin. + + [..] After waking up from Shutdown mode, program execution restarts in the same way as after a Reset. + + + *** Auto-wakeup (AWU) from low-power mode *** + ============================================= + [..] + The MCU can be woken up from low-power mode by an RTC Alarm event, an RTC + Wakeup event, a tamper event or a time-stamp event, without depending on + an external interrupt (Auto-wakeup mode). + + (+) RTC auto-wakeup (AWU) from the Stop, Standby and Shutdown modes + + + (++) To wake up from the Stop mode with an RTC alarm event, it is necessary to + configure the RTC to generate the RTC alarm using the HAL_RTC_SetAlarm_IT() function. + + (++) To wake up from the Stop mode with an RTC Tamper or time stamp event, it + is necessary to configure the RTC to detect the tamper or time stamp event using the + HAL_RTCEx_SetTimeStamp_IT() or HAL_RTCEx_SetTamper_IT() functions. + + (++) To wake up from the Stop mode with an RTC WakeUp event, it is necessary to + configure the RTC to generate the RTC WakeUp event using the HAL_RTCEx_SetWakeUpTimer_IT() function. + +@endverbatim + * @{ + */ + + + +/** + * @brief Configure the voltage threshold detected by the Power Voltage Detector (PVD). + * @param sConfigPVD: pointer to a PWR_PVDTypeDef structure that contains the PVD + * configuration information. + * @note Refer to the electrical characteristics of your device datasheet for + * more details about the voltage thresholds corresponding to each + * detection level. + * @retval None + */ +HAL_StatusTypeDef HAL_PWR_ConfigPVD(PWR_PVDTypeDef *sConfigPVD) +{ + /* Check the parameters */ + assert_param(IS_PWR_PVD_LEVEL(sConfigPVD->PVDLevel)); + assert_param(IS_PWR_PVD_MODE(sConfigPVD->Mode)); + + /* Set PLS bits according to PVDLevel value */ + MODIFY_REG(PWR->CR2, PWR_CR2_PLS, sConfigPVD->PVDLevel); + + /* Clear any previous config. Keep it clear if no event or IT mode is selected */ + __HAL_PWR_PVD_EXTI_DISABLE_EVENT(); + __HAL_PWR_PVD_EXTI_DISABLE_IT(); + __HAL_PWR_PVD_EXTI_DISABLE_FALLING_EDGE(); + __HAL_PWR_PVD_EXTI_DISABLE_RISING_EDGE(); + + /* Configure interrupt mode */ + if((sConfigPVD->Mode & PVD_MODE_IT) == PVD_MODE_IT) + { + __HAL_PWR_PVD_EXTI_ENABLE_IT(); + } + + /* Configure event mode */ + if((sConfigPVD->Mode & PVD_MODE_EVT) == PVD_MODE_EVT) + { + __HAL_PWR_PVD_EXTI_ENABLE_EVENT(); + } + + /* Configure the edge */ + if((sConfigPVD->Mode & PVD_RISING_EDGE) == PVD_RISING_EDGE) + { + __HAL_PWR_PVD_EXTI_ENABLE_RISING_EDGE(); + } + + if((sConfigPVD->Mode & PVD_FALLING_EDGE) == PVD_FALLING_EDGE) + { + __HAL_PWR_PVD_EXTI_ENABLE_FALLING_EDGE(); + } + + return HAL_OK; +} + + +/** + * @brief Enable the Power Voltage Detector (PVD). + * @retval None + */ +void HAL_PWR_EnablePVD(void) +{ + SET_BIT(PWR->CR2, PWR_CR2_PVDE); +} + +/** + * @brief Disable the Power Voltage Detector (PVD). + * @retval None + */ +void HAL_PWR_DisablePVD(void) +{ + CLEAR_BIT(PWR->CR2, PWR_CR2_PVDE); +} + + + + +/** + * @brief Enable the WakeUp PINx functionality. + * @param WakeUpPinPolarity: Specifies which Wake-Up pin to enable. + * This parameter can be one of the following legacy values which set the default polarity + * i.e. detection on high level (rising edge): + * @arg @ref PWR_WAKEUP_PIN1, PWR_WAKEUP_PIN2, PWR_WAKEUP_PIN3, PWR_WAKEUP_PIN4, PWR_WAKEUP_PIN5 + * + * or one of the following value where the user can explicitly specify the enabled pin and + * the chosen polarity: + * @arg @ref PWR_WAKEUP_PIN1_HIGH or PWR_WAKEUP_PIN1_LOW + * @arg @ref PWR_WAKEUP_PIN2_HIGH or PWR_WAKEUP_PIN2_LOW + * @arg @ref PWR_WAKEUP_PIN3_HIGH or PWR_WAKEUP_PIN3_LOW + * @arg @ref PWR_WAKEUP_PIN4_HIGH or PWR_WAKEUP_PIN4_LOW + * @arg @ref PWR_WAKEUP_PIN5_HIGH or PWR_WAKEUP_PIN5_LOW + * @note PWR_WAKEUP_PINx and PWR_WAKEUP_PINx_HIGH are equivalent. + * @retval None + */ +void HAL_PWR_EnableWakeUpPin(uint32_t WakeUpPinPolarity) +{ + assert_param(IS_PWR_WAKEUP_PIN(WakeUpPinPolarity)); + + /* Specifies the Wake-Up pin polarity for the event detection + (rising or falling edge) */ + MODIFY_REG(PWR->CR4, (PWR_CR3_EWUP & WakeUpPinPolarity), (WakeUpPinPolarity >> PWR_WUP_POLARITY_SHIFT)); + + /* Enable wake-up pin */ + SET_BIT(PWR->CR3, (PWR_CR3_EWUP & WakeUpPinPolarity)); + + +} + +/** + * @brief Disable the WakeUp PINx functionality. + * @param WakeUpPinx: Specifies the Power Wake-Up pin to disable. + * This parameter can be one of the following values: + * @arg @ref PWR_WAKEUP_PIN1, PWR_WAKEUP_PIN2, PWR_WAKEUP_PIN3, PWR_WAKEUP_PIN4, PWR_WAKEUP_PIN5 + * @retval None + */ +void HAL_PWR_DisableWakeUpPin(uint32_t WakeUpPinx) +{ + assert_param(IS_PWR_WAKEUP_PIN(WakeUpPinx)); + + CLEAR_BIT(PWR->CR3, (PWR_CR3_EWUP & WakeUpPinx)); +} + + +/** + * @brief Enter Sleep or Low-power Sleep mode. + * @note In Sleep/Low-power Sleep mode, all I/O pins keep the same state as in Run mode. + * @param Regulator: Specifies the regulator state in Sleep/Low-power Sleep mode. + * This parameter can be one of the following values: + * @arg @ref PWR_MAINREGULATOR_ON Sleep mode (regulator in main mode) + * @arg @ref PWR_LOWPOWERREGULATOR_ON Low-power Sleep mode (regulator in low-power mode) + * @note Low-power Sleep mode is entered from Low-power Run mode. Therefore, if not yet + * in Low-power Run mode before calling HAL_PWR_EnterSLEEPMode() with Regulator set + * to PWR_LOWPOWERREGULATOR_ON, the user can optionally configure the + * Flash in power-down monde in setting the SLEEP_PD bit in FLASH_ACR register. + * Additionally, the clock frequency must be reduced below 2 MHz. + * Setting SLEEP_PD in FLASH_ACR then appropriately reducing the clock frequency must + * be done before calling HAL_PWR_EnterSLEEPMode() API. + * @note When exiting Low-power Sleep mode, the MCU is in Low-power Run mode. To move in + * Run mode, the user must resort to HAL_PWREx_DisableLowPowerRunMode() API. + * @param SLEEPEntry: Specifies if Sleep mode is entered with WFI or WFE instruction. + * This parameter can be one of the following values: + * @arg @ref PWR_SLEEPENTRY_WFI enter Sleep or Low-power Sleep mode with WFI instruction + * @arg @ref PWR_SLEEPENTRY_WFE enter Sleep or Low-power Sleep mode with WFE instruction + * @note When WFI entry is used, tick interrupt have to be disabled if not desired as + * the interrupt wake up source. + * @retval None + */ +void HAL_PWR_EnterSLEEPMode(uint32_t Regulator, uint8_t SLEEPEntry) +{ + /* Check the parameters */ + assert_param(IS_PWR_REGULATOR(Regulator)); + assert_param(IS_PWR_SLEEP_ENTRY(SLEEPEntry)); + + /* Set Regulator parameter */ + if (Regulator == PWR_MAINREGULATOR_ON) + { + /* If in low-power run mode at this point, exit it */ + if (HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_REGLPF)) + { + HAL_PWREx_DisableLowPowerRunMode(); + } + /* Regulator now in main mode. */ + } + else + { + /* If in run mode, first move to low-power run mode. + The system clock frequency must be below 2 MHz at this point. */ + if (HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_REGLPF) == RESET) + { + HAL_PWREx_EnableLowPowerRunMode(); + } + } + + /* Clear SLEEPDEEP bit of Cortex System Control Register */ + CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk)); + + /* Select SLEEP mode entry -------------------------------------------------*/ + if(SLEEPEntry == PWR_SLEEPENTRY_WFI) + { + /* Request Wait For Interrupt */ + __WFI(); + } + else + { + /* Request Wait For Event */ + __SEV(); + __WFE(); + __WFE(); + } + +} + + +/** + * @brief Enter Stop mode + * @note This API is named HAL_PWR_EnterSTOPMode to ensure compatibility with legacy code running + * on devices where only "Stop mode" is mentioned with main or low power regulator ON. + * @note In Stop mode, all I/O pins keep the same state as in Run mode. + * @note All clocks in the VCORE domain are stopped; the PLL, the MSI, + * the HSI and the HSE oscillators are disabled. Some peripherals with the wakeup capability + * (I2Cx, USARTx and LPUART) can switch on the HSI to receive a frame, and switch off the HSI + * after receiving the frame if it is not a wakeup frame. In this case, the HSI clock is propagated + * only to the peripheral requesting it. + * SRAM1, SRAM2 and register contents are preserved. + * The BOR is available. + * The voltage regulator can be configured either in normal (Stop 0) or low-power mode (Stop 1). + * @note When exiting Stop 0 or Stop 1 mode by issuing an interrupt or a wakeup event, + * the HSI RC oscillator is selected as system clock if STOPWUCK bit in RCC_CFGR register + * is set; the MSI oscillator is selected if STOPWUCK is cleared. + * @note When the voltage regulator operates in low power mode (Stop 1), an additional + * startup delay is incurred when waking up. + * By keeping the internal regulator ON during Stop mode (Stop 0), the consumption + * is higher although the startup time is reduced. + * @param Regulator: Specifies the regulator state in Stop mode. + * This parameter can be one of the following values: + * @arg @ref PWR_MAINREGULATOR_ON Stop 0 mode (main regulator ON) + * @arg @ref PWR_LOWPOWERREGULATOR_ON Stop 1 mode (low power regulator ON) + * @param STOPEntry: Specifies Stop 0 or Stop 1 mode is entered with WFI or WFE instruction. + * This parameter can be one of the following values: + * @arg @ref PWR_STOPENTRY_WFI Enter Stop 0 or Stop 1 mode with WFI instruction. + * @arg @ref PWR_STOPENTRY_WFE Enter Stop 0 or Stop 1 mode with WFE instruction. + * @retval None + */ +void HAL_PWR_EnterSTOPMode(uint32_t Regulator, uint8_t STOPEntry) +{ + /* Check the parameters */ + assert_param(IS_PWR_REGULATOR(Regulator)); + + if(Regulator == PWR_LOWPOWERREGULATOR_ON) + { + HAL_PWREx_EnterSTOP1Mode(STOPEntry); + } + else + { + HAL_PWREx_EnterSTOP0Mode(STOPEntry); + } +} + +/** + * @brief Enter Standby mode. + * @note In Standby mode, the PLL, the HSI, the MSI and the HSE oscillators are switched + * off. The voltage regulator is disabled, except when SRAM2 content is preserved + * in which case the regulator is in low-power mode. + * SRAM1 and register contents are lost except for registers in the Backup domain and + * Standby circuitry. SRAM2 content can be preserved if the bit RRS is set in PWR_CR3 register. + * To enable this feature, the user can resort to HAL_PWREx_EnableSRAM2ContentRetention() API + * to set RRS bit. + * The BOR is available. + * @note The I/Os can be configured either with a pull-up or pull-down or can be kept in analog state. + * HAL_PWREx_EnableGPIOPullUp() and HAL_PWREx_EnableGPIOPullDown() respectively enable Pull Up and + * Pull Down state, HAL_PWREx_DisableGPIOPullUp() and HAL_PWREx_DisableGPIOPullDown() disable the + * same. + * These states are effective in Standby mode only if APC bit is set through + * HAL_PWREx_EnablePullUpPullDownConfig() API. + * @retval None + */ +void HAL_PWR_EnterSTANDBYMode(void) +{ + /* Set Stand-by mode */ + MODIFY_REG(PWR->CR1, PWR_CR1_LPMS, PWR_CR1_LPMS_STANDBY); + + /* Set SLEEPDEEP bit of Cortex System Control Register */ + SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk)); + +/* This option is used to ensure that store operations are completed */ +#if defined ( __CC_ARM) + __force_stores(); +#endif + /* Request Wait For Interrupt */ + __WFI(); +} + + + +/** + * @brief Indicate Sleep-On-Exit when returning from Handler mode to Thread mode. + * @note Set SLEEPONEXIT bit of SCR register. When this bit is set, the processor + * re-enters SLEEP mode when an interruption handling is over. + * Setting this bit is useful when the processor is expected to run only on + * interruptions handling. + * @retval None + */ +void HAL_PWR_EnableSleepOnExit(void) +{ + /* Set SLEEPONEXIT bit of Cortex System Control Register */ + SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPONEXIT_Msk)); +} + + +/** + * @brief Disable Sleep-On-Exit feature when returning from Handler mode to Thread mode. + * @note Clear SLEEPONEXIT bit of SCR register. When this bit is set, the processor + * re-enters SLEEP mode when an interruption handling is over. + * @retval None + */ +void HAL_PWR_DisableSleepOnExit(void) +{ + /* Clear SLEEPONEXIT bit of Cortex System Control Register */ + CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPONEXIT_Msk)); +} + + + +/** + * @brief Enable CORTEX M4 SEVONPEND bit. + * @note Set SEVONPEND bit of SCR register. When this bit is set, this causes + * WFE to wake up when an interrupt moves from inactive to pended. + * @retval None + */ +void HAL_PWR_EnableSEVOnPend(void) +{ + /* Set SEVONPEND bit of Cortex System Control Register */ + SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SEVONPEND_Msk)); +} + + +/** + * @brief Disable CORTEX M4 SEVONPEND bit. + * @note Clear SEVONPEND bit of SCR register. When this bit is set, this causes + * WFE to wake up when an interrupt moves from inactive to pended. + * @retval None + */ +void HAL_PWR_DisableSEVOnPend(void) +{ + /* Clear SEVONPEND bit of Cortex System Control Register */ + CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SEVONPEND_Msk)); +} + + + + + +/** + * @brief PWR PVD interrupt callback + * @retval None + */ +__weak void HAL_PWR_PVDCallback(void) +{ + /* NOTE : This function should not be modified; when the callback is needed, + the HAL_PWR_PVDCallback can be implemented in the user file + */ +} + +/** + * @} + */ + +/** + * @} + */ + +#endif /* HAL_PWR_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pwr_ex.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pwr_ex.c new file mode 100644 index 0000000..bdd8960 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pwr_ex.c @@ -0,0 +1,1399 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_pwr_ex.c + * @author MCD Application Team + * @brief Extended PWR HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Power Controller (PWR) peripheral: + * + Extended Initialization and de-initialization functions + * + Extended Peripheral Control functions + * + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup PWREx PWREx + * @brief PWR Extended HAL module driver + * @{ + */ + +#ifdef HAL_PWR_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ + +#if defined (STM32L431xx) || defined (STM32L432xx) || defined (STM32L433xx) || defined (STM32L442xx) || defined (STM32L443xx) +#define PWR_PORTH_AVAILABLE_PINS ((uint32_t)0x0000000B) /* PH0/PH1/PH3 */ +#elif defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) +#define PWR_PORTH_AVAILABLE_PINS ((uint32_t)0x0000000B) /* PH0/PH1/PH3 */ +#elif defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) +#define PWR_PORTH_AVAILABLE_PINS ((uint32_t)0x00000003) /* PH0/PH1 */ +#elif defined (STM32L496xx) || defined (STM32L4A6xx) || defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define PWR_PORTH_AVAILABLE_PINS ((uint32_t)0x0000FFFF) /* PH0..PH15 */ +#endif + +#if defined (STM32L496xx) || defined (STM32L4A6xx) || defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define PWR_PORTI_AVAILABLE_PINS ((uint32_t)0x00000FFF) /* PI0..PI11 */ +#endif + +/** @defgroup PWR_Extended_Private_Defines PWR Extended Private Defines + * @{ + */ + +/** @defgroup PWREx_PVM_Mode_Mask PWR PVM Mode Mask + * @{ + */ +#define PVM_MODE_IT ((uint32_t)0x00010000) /*!< Mask for interruption yielded by PVM threshold crossing */ +#define PVM_MODE_EVT ((uint32_t)0x00020000) /*!< Mask for event yielded by PVM threshold crossing */ +#define PVM_RISING_EDGE ((uint32_t)0x00000001) /*!< Mask for rising edge set as PVM trigger */ +#define PVM_FALLING_EDGE ((uint32_t)0x00000002) /*!< Mask for falling edge set as PVM trigger */ +/** + * @} + */ + +/** @defgroup PWREx_TimeOut_Value PWR Extended Flag Setting Time Out Value + * @{ + */ +#define PWR_FLAG_SETTING_DELAY_US 50 /*!< Time out value for REGLPF and VOSF flags setting */ +/** + * @} + */ + + + +/** + * @} + */ + + + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup PWREx_Exported_Functions PWR Extended Exported Functions + * @{ + */ + +/** @defgroup PWREx_Exported_Functions_Group1 Extended Peripheral Control functions + * @brief Extended Peripheral Control functions + * +@verbatim + =============================================================================== + ##### Extended Peripheral Initialization and de-initialization functions ##### + =============================================================================== + [..] + +@endverbatim + * @{ + */ + + +/** + * @brief Return Voltage Scaling Range. + * @retval VOS bit field (PWR_REGULATOR_VOLTAGE_RANGE1 or PWR_REGULATOR_VOLTAGE_RANGE2 + * or PWR_REGULATOR_VOLTAGE_SCALE1_BOOST when applicable) + */ +uint32_t HAL_PWREx_GetVoltageRange(void) +{ +#if defined(PWR_CR5_R1MODE) + if (READ_BIT(PWR->CR1, PWR_CR1_VOS) == PWR_REGULATOR_VOLTAGE_SCALE2) + { + return PWR_REGULATOR_VOLTAGE_SCALE2; + } + else if (READ_BIT(PWR->CR5, PWR_CR5_R1MODE) == PWR_CR5_R1MODE) + { + /* PWR_CR5_R1MODE bit set means that Range 1 Boost is disabled */ + return PWR_REGULATOR_VOLTAGE_SCALE1; + } + else + { + return PWR_REGULATOR_VOLTAGE_SCALE1_BOOST; + } +#else + return (PWR->CR1 & PWR_CR1_VOS); +#endif +} + + + +/** + * @brief Configure the main internal regulator output voltage. + * @param VoltageScaling: specifies the regulator output voltage to achieve + * a tradeoff between performance and power consumption. + * This parameter can be one of the following values: + @if STM32L4S9xx + * @arg @ref PWR_REGULATOR_VOLTAGE_SCALE1_BOOST when available, Regulator voltage output range 1 boost mode, + * typical output voltage at 1.2 V, + * system frequency up to 120 MHz. + @endif + * @arg @ref PWR_REGULATOR_VOLTAGE_SCALE1 Regulator voltage output range 1 mode, + * typical output voltage at 1.2 V, + * system frequency up to 80 MHz. + * @arg @ref PWR_REGULATOR_VOLTAGE_SCALE2 Regulator voltage output range 2 mode, + * typical output voltage at 1.0 V, + * system frequency up to 26 MHz. + * @note When moving from Range 1 to Range 2, the system frequency must be decreased to + * a value below 26 MHz before calling HAL_PWREx_ControlVoltageScaling() API. + * When moving from Range 2 to Range 1, the system frequency can be increased to + * a value up to 80 MHz after calling HAL_PWREx_ControlVoltageScaling() API. For + * some devices, the system frequency can be increased up to 120 MHz. + * @note When moving from Range 2 to Range 1, the API waits for VOSF flag to be + * cleared before returning the status. If the flag is not cleared within + * 50 microseconds, HAL_TIMEOUT status is reported. + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_PWREx_ControlVoltageScaling(uint32_t VoltageScaling) +{ + uint32_t wait_loop_index = 0; + + assert_param(IS_PWR_VOLTAGE_SCALING_RANGE(VoltageScaling)); + +#if defined(PWR_CR5_R1MODE) + if (VoltageScaling == PWR_REGULATOR_VOLTAGE_SCALE1_BOOST) + { + /* If current range is range 2 */ + if (READ_BIT(PWR->CR1, PWR_CR1_VOS) == PWR_REGULATOR_VOLTAGE_SCALE2) + { + /* Make sure Range 1 Boost is enabled */ + CLEAR_BIT(PWR->CR5, PWR_CR5_R1MODE); + + /* Set Range 1 */ + MODIFY_REG(PWR->CR1, PWR_CR1_VOS, PWR_REGULATOR_VOLTAGE_SCALE1); + + /* Wait until VOSF is cleared */ + wait_loop_index = (PWR_FLAG_SETTING_DELAY_US * (SystemCoreClock / 1000000)); + while ((wait_loop_index != 0) && (HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_VOSF))) + { + wait_loop_index--; + } + if (HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_VOSF)) + { + return HAL_TIMEOUT; + } + } + /* If current range is range 1 normal or boost mode */ + else + { + /* Enable Range 1 Boost (no issue if bit already reset) */ + CLEAR_BIT(PWR->CR5, PWR_CR5_R1MODE); + } + } + else if (VoltageScaling == PWR_REGULATOR_VOLTAGE_SCALE1) + { + /* If current range is range 2 */ + if (READ_BIT(PWR->CR1, PWR_CR1_VOS) == PWR_REGULATOR_VOLTAGE_SCALE2) + { + /* Make sure Range 1 Boost is disabled */ + SET_BIT(PWR->CR5, PWR_CR5_R1MODE); + + /* Set Range 1 */ + MODIFY_REG(PWR->CR1, PWR_CR1_VOS, PWR_REGULATOR_VOLTAGE_SCALE1); + + /* Wait until VOSF is cleared */ + wait_loop_index = (PWR_FLAG_SETTING_DELAY_US * (SystemCoreClock / 1000000)); + while ((wait_loop_index != 0) && (HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_VOSF))) + { + wait_loop_index--; + } + if (HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_VOSF)) + { + return HAL_TIMEOUT; + } + } + /* If current range is range 1 normal or boost mode */ + else + { + /* Disable Range 1 Boost (no issue if bit already set) */ + SET_BIT(PWR->CR5, PWR_CR5_R1MODE); + } + } + else + { + /* Set Range 2 */ + MODIFY_REG(PWR->CR1, PWR_CR1_VOS, PWR_REGULATOR_VOLTAGE_SCALE2); + /* No need to wait for VOSF to be cleared for this transition */ + /* PWR_CR5_R1MODE bit setting has no effect in Range 2 */ + } + +#else + + /* If Set Range 1 */ + if (VoltageScaling == PWR_REGULATOR_VOLTAGE_SCALE1) + { + if (READ_BIT(PWR->CR1, PWR_CR1_VOS) != PWR_REGULATOR_VOLTAGE_SCALE1) + { + /* Set Range 1 */ + MODIFY_REG(PWR->CR1, PWR_CR1_VOS, PWR_REGULATOR_VOLTAGE_SCALE1); + + /* Wait until VOSF is cleared */ + wait_loop_index = (PWR_FLAG_SETTING_DELAY_US * (SystemCoreClock / 1000000)); + while ((wait_loop_index != 0) && (HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_VOSF))) + { + wait_loop_index--; + } + if (HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_VOSF)) + { + return HAL_TIMEOUT; + } + } + } + else + { + if (READ_BIT(PWR->CR1, PWR_CR1_VOS) != PWR_REGULATOR_VOLTAGE_SCALE2) + { + /* Set Range 2 */ + MODIFY_REG(PWR->CR1, PWR_CR1_VOS, PWR_REGULATOR_VOLTAGE_SCALE2); + /* No need to wait for VOSF to be cleared for this transition */ + } + } +#endif + + return HAL_OK; +} + + +/** + * @brief Enable battery charging. + * When VDD is present, charge the external battery on VBAT thru an internal resistor. + * @param ResistorSelection: specifies the resistor impedance. + * This parameter can be one of the following values: + * @arg @ref PWR_BATTERY_CHARGING_RESISTOR_5 5 kOhms resistor + * @arg @ref PWR_BATTERY_CHARGING_RESISTOR_1_5 1.5 kOhms resistor + * @retval None + */ +void HAL_PWREx_EnableBatteryCharging(uint32_t ResistorSelection) +{ + assert_param(IS_PWR_BATTERY_RESISTOR_SELECT(ResistorSelection)); + + /* Specify resistor selection */ + MODIFY_REG(PWR->CR4, PWR_CR4_VBRS, ResistorSelection); + + /* Enable battery charging */ + SET_BIT(PWR->CR4, PWR_CR4_VBE); +} + + +/** + * @brief Disable battery charging. + * @retval None + */ +void HAL_PWREx_DisableBatteryCharging(void) +{ + CLEAR_BIT(PWR->CR4, PWR_CR4_VBE); +} + + +#if defined(PWR_CR2_USV) +/** + * @brief Enable VDDUSB supply. + * @note Remove VDDUSB electrical and logical isolation, once VDDUSB supply is present. + * @retval None + */ +void HAL_PWREx_EnableVddUSB(void) +{ + SET_BIT(PWR->CR2, PWR_CR2_USV); +} + + +/** + * @brief Disable VDDUSB supply. + * @retval None + */ +void HAL_PWREx_DisableVddUSB(void) +{ + CLEAR_BIT(PWR->CR2, PWR_CR2_USV); +} +#endif /* PWR_CR2_USV */ + +#if defined(PWR_CR2_IOSV) +/** + * @brief Enable VDDIO2 supply. + * @note Remove VDDIO2 electrical and logical isolation, once VDDIO2 supply is present. + * @retval None + */ +void HAL_PWREx_EnableVddIO2(void) +{ + SET_BIT(PWR->CR2, PWR_CR2_IOSV); +} + + +/** + * @brief Disable VDDIO2 supply. + * @retval None + */ +void HAL_PWREx_DisableVddIO2(void) +{ + CLEAR_BIT(PWR->CR2, PWR_CR2_IOSV); +} +#endif /* PWR_CR2_IOSV */ + + +/** + * @brief Enable Internal Wake-up Line. + * @retval None + */ +void HAL_PWREx_EnableInternalWakeUpLine(void) +{ + SET_BIT(PWR->CR3, PWR_CR3_EIWF); +} + + +/** + * @brief Disable Internal Wake-up Line. + * @retval None + */ +void HAL_PWREx_DisableInternalWakeUpLine(void) +{ + CLEAR_BIT(PWR->CR3, PWR_CR3_EIWF); +} + + + +/** + * @brief Enable GPIO pull-up state in Standby and Shutdown modes. + * @note Set the relevant PUy bits of PWR_PUCRx register to configure the I/O in + * pull-up state in Standby and Shutdown modes. + * @note This state is effective in Standby and Shutdown modes only if APC bit + * is set through HAL_PWREx_EnablePullUpPullDownConfig() API. + * @note The configuration is lost when exiting the Shutdown mode due to the + * power-on reset, maintained when exiting the Standby mode. + * @note To avoid any conflict at Standby and Shutdown modes exits, the corresponding + * PDy bit of PWR_PDCRx register is cleared unless it is reserved. + * @note Even if a PUy bit to set is reserved, the other PUy bits entered as input + * parameter at the same time are set. + * @param GPIO: Specify the IO port. This parameter can be PWR_GPIO_A, ..., PWR_GPIO_H + * (or PWR_GPIO_I depending on the devices) to select the GPIO peripheral. + * @param GPIONumber: Specify the I/O pins numbers. + * This parameter can be one of the following values: + * PWR_GPIO_BIT_0, ..., PWR_GPIO_BIT_15 (except for the port where less + * I/O pins are available) or the logical OR of several of them to set + * several bits for a given port in a single API call. + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_PWREx_EnableGPIOPullUp(uint32_t GPIO, uint32_t GPIONumber) +{ + assert_param(IS_PWR_GPIO(GPIO)); + assert_param(IS_PWR_GPIO_BIT_NUMBER(GPIONumber)); + + switch (GPIO) + { + case PWR_GPIO_A: + SET_BIT(PWR->PUCRA, (GPIONumber & (~(PWR_GPIO_BIT_14)))); + CLEAR_BIT(PWR->PDCRA, (GPIONumber & (~(PWR_GPIO_BIT_13|PWR_GPIO_BIT_15)))); + break; + case PWR_GPIO_B: + SET_BIT(PWR->PUCRB, GPIONumber); + CLEAR_BIT(PWR->PDCRB, (GPIONumber & (~(PWR_GPIO_BIT_4)))); + break; + case PWR_GPIO_C: + SET_BIT(PWR->PUCRC, GPIONumber); + CLEAR_BIT(PWR->PDCRC, GPIONumber); + break; +#if defined(GPIOD) + case PWR_GPIO_D: + SET_BIT(PWR->PUCRD, GPIONumber); + CLEAR_BIT(PWR->PDCRD, GPIONumber); + break; +#endif +#if defined(GPIOE) + case PWR_GPIO_E: + SET_BIT(PWR->PUCRE, GPIONumber); + CLEAR_BIT(PWR->PDCRE, GPIONumber); + break; +#endif +#if defined(GPIOF) + case PWR_GPIO_F: + SET_BIT(PWR->PUCRF, GPIONumber); + CLEAR_BIT(PWR->PDCRF, GPIONumber); + break; +#endif +#if defined(GPIOG) + case PWR_GPIO_G: + SET_BIT(PWR->PUCRG, GPIONumber); + CLEAR_BIT(PWR->PDCRG, GPIONumber); + break; +#endif + case PWR_GPIO_H: + SET_BIT(PWR->PUCRH, (GPIONumber & PWR_PORTH_AVAILABLE_PINS)); +#if defined (STM32L496xx) || defined (STM32L4A6xx) + CLEAR_BIT(PWR->PDCRH, ((GPIONumber & PWR_PORTH_AVAILABLE_PINS) & (~(PWR_GPIO_BIT_3)))); +#else + CLEAR_BIT(PWR->PDCRH, (GPIONumber & PWR_PORTH_AVAILABLE_PINS)); +#endif + break; +#if defined(GPIOI) + case PWR_GPIO_I: + SET_BIT(PWR->PUCRI, (GPIONumber & PWR_PORTI_AVAILABLE_PINS)); + CLEAR_BIT(PWR->PDCRI, (GPIONumber & PWR_PORTI_AVAILABLE_PINS)); + break; +#endif + default: + return HAL_ERROR; + } + + return HAL_OK; +} + + +/** + * @brief Disable GPIO pull-up state in Standby mode and Shutdown modes. + * @note Reset the relevant PUy bits of PWR_PUCRx register used to configure the I/O + * in pull-up state in Standby and Shutdown modes. + * @note Even if a PUy bit to reset is reserved, the other PUy bits entered as input + * parameter at the same time are reset. + * @param GPIO: Specifies the IO port. This parameter can be PWR_GPIO_A, ..., PWR_GPIO_H + * (or PWR_GPIO_I depending on the devices) to select the GPIO peripheral. + * @param GPIONumber: Specify the I/O pins numbers. + * This parameter can be one of the following values: + * PWR_GPIO_BIT_0, ..., PWR_GPIO_BIT_15 (except for the port where less + * I/O pins are available) or the logical OR of several of them to reset + * several bits for a given port in a single API call. + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_PWREx_DisableGPIOPullUp(uint32_t GPIO, uint32_t GPIONumber) +{ + assert_param(IS_PWR_GPIO(GPIO)); + assert_param(IS_PWR_GPIO_BIT_NUMBER(GPIONumber)); + + switch (GPIO) + { + case PWR_GPIO_A: + CLEAR_BIT(PWR->PUCRA, (GPIONumber & (~(PWR_GPIO_BIT_14)))); + break; + case PWR_GPIO_B: + CLEAR_BIT(PWR->PUCRB, GPIONumber); + break; + case PWR_GPIO_C: + CLEAR_BIT(PWR->PUCRC, GPIONumber); + break; +#if defined(GPIOD) + case PWR_GPIO_D: + CLEAR_BIT(PWR->PUCRD, GPIONumber); + break; +#endif +#if defined(GPIOE) + case PWR_GPIO_E: + CLEAR_BIT(PWR->PUCRE, GPIONumber); + break; +#endif +#if defined(GPIOF) + case PWR_GPIO_F: + CLEAR_BIT(PWR->PUCRF, GPIONumber); + break; +#endif +#if defined(GPIOG) + case PWR_GPIO_G: + CLEAR_BIT(PWR->PUCRG, GPIONumber); + break; +#endif + case PWR_GPIO_H: + CLEAR_BIT(PWR->PUCRH, (GPIONumber & PWR_PORTH_AVAILABLE_PINS)); + break; +#if defined(GPIOI) + case PWR_GPIO_I: + CLEAR_BIT(PWR->PUCRI, (GPIONumber & PWR_PORTI_AVAILABLE_PINS)); + break; +#endif + default: + return HAL_ERROR; + } + + return HAL_OK; +} + + + +/** + * @brief Enable GPIO pull-down state in Standby and Shutdown modes. + * @note Set the relevant PDy bits of PWR_PDCRx register to configure the I/O in + * pull-down state in Standby and Shutdown modes. + * @note This state is effective in Standby and Shutdown modes only if APC bit + * is set through HAL_PWREx_EnablePullUpPullDownConfig() API. + * @note The configuration is lost when exiting the Shutdown mode due to the + * power-on reset, maintained when exiting the Standby mode. + * @note To avoid any conflict at Standby and Shutdown modes exits, the corresponding + * PUy bit of PWR_PUCRx register is cleared unless it is reserved. + * @note Even if a PDy bit to set is reserved, the other PDy bits entered as input + * parameter at the same time are set. + * @param GPIO: Specify the IO port. This parameter can be PWR_GPIO_A..PWR_GPIO_H + * (or PWR_GPIO_I depending on the devices) to select the GPIO peripheral. + * @param GPIONumber: Specify the I/O pins numbers. + * This parameter can be one of the following values: + * PWR_GPIO_BIT_0, ..., PWR_GPIO_BIT_15 (except for the port where less + * I/O pins are available) or the logical OR of several of them to set + * several bits for a given port in a single API call. + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_PWREx_EnableGPIOPullDown(uint32_t GPIO, uint32_t GPIONumber) +{ + assert_param(IS_PWR_GPIO(GPIO)); + assert_param(IS_PWR_GPIO_BIT_NUMBER(GPIONumber)); + + switch (GPIO) + { + case PWR_GPIO_A: + SET_BIT(PWR->PDCRA, (GPIONumber & (~(PWR_GPIO_BIT_13|PWR_GPIO_BIT_15)))); + CLEAR_BIT(PWR->PUCRA, (GPIONumber & (~(PWR_GPIO_BIT_14)))); + break; + case PWR_GPIO_B: + SET_BIT(PWR->PDCRB, (GPIONumber & (~(PWR_GPIO_BIT_4)))); + CLEAR_BIT(PWR->PUCRB, GPIONumber); + break; + case PWR_GPIO_C: + SET_BIT(PWR->PDCRC, GPIONumber); + CLEAR_BIT(PWR->PUCRC, GPIONumber); + break; +#if defined(GPIOD) + case PWR_GPIO_D: + SET_BIT(PWR->PDCRD, GPIONumber); + CLEAR_BIT(PWR->PUCRD, GPIONumber); + break; +#endif +#if defined(GPIOE) + case PWR_GPIO_E: + SET_BIT(PWR->PDCRE, GPIONumber); + CLEAR_BIT(PWR->PUCRE, GPIONumber); + break; +#endif +#if defined(GPIOF) + case PWR_GPIO_F: + SET_BIT(PWR->PDCRF, GPIONumber); + CLEAR_BIT(PWR->PUCRF, GPIONumber); + break; +#endif +#if defined(GPIOG) + case PWR_GPIO_G: + SET_BIT(PWR->PDCRG, GPIONumber); + CLEAR_BIT(PWR->PUCRG, GPIONumber); + break; +#endif + case PWR_GPIO_H: +#if defined (STM32L496xx) || defined (STM32L4A6xx) + SET_BIT(PWR->PDCRH, ((GPIONumber & PWR_PORTH_AVAILABLE_PINS) & (~(PWR_GPIO_BIT_3)))); +#else + SET_BIT(PWR->PDCRH, (GPIONumber & PWR_PORTH_AVAILABLE_PINS)); +#endif + CLEAR_BIT(PWR->PUCRH, (GPIONumber & PWR_PORTH_AVAILABLE_PINS)); + break; +#if defined(GPIOI) + case PWR_GPIO_I: + SET_BIT(PWR->PDCRI, (GPIONumber & PWR_PORTI_AVAILABLE_PINS)); + CLEAR_BIT(PWR->PUCRI, (GPIONumber & PWR_PORTI_AVAILABLE_PINS)); + break; +#endif + default: + return HAL_ERROR; + } + + return HAL_OK; +} + + +/** + * @brief Disable GPIO pull-down state in Standby and Shutdown modes. + * @note Reset the relevant PDy bits of PWR_PDCRx register used to configure the I/O + * in pull-down state in Standby and Shutdown modes. + * @note Even if a PDy bit to reset is reserved, the other PDy bits entered as input + * parameter at the same time are reset. + * @param GPIO: Specifies the IO port. This parameter can be PWR_GPIO_A..PWR_GPIO_H + * (or PWR_GPIO_I depending on the devices) to select the GPIO peripheral. + * @param GPIONumber: Specify the I/O pins numbers. + * This parameter can be one of the following values: + * PWR_GPIO_BIT_0, ..., PWR_GPIO_BIT_15 (except for the port where less + * I/O pins are available) or the logical OR of several of them to reset + * several bits for a given port in a single API call. + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_PWREx_DisableGPIOPullDown(uint32_t GPIO, uint32_t GPIONumber) +{ + assert_param(IS_PWR_GPIO(GPIO)); + assert_param(IS_PWR_GPIO_BIT_NUMBER(GPIONumber)); + + switch (GPIO) + { + case PWR_GPIO_A: + CLEAR_BIT(PWR->PDCRA, (GPIONumber & (~(PWR_GPIO_BIT_13|PWR_GPIO_BIT_15)))); + break; + case PWR_GPIO_B: + CLEAR_BIT(PWR->PDCRB, (GPIONumber & (~(PWR_GPIO_BIT_4)))); + break; + case PWR_GPIO_C: + CLEAR_BIT(PWR->PDCRC, GPIONumber); + break; +#if defined(GPIOD) + case PWR_GPIO_D: + CLEAR_BIT(PWR->PDCRD, GPIONumber); + break; +#endif +#if defined(GPIOE) + case PWR_GPIO_E: + CLEAR_BIT(PWR->PDCRE, GPIONumber); + break; +#endif +#if defined(GPIOF) + case PWR_GPIO_F: + CLEAR_BIT(PWR->PDCRF, GPIONumber); + break; +#endif +#if defined(GPIOG) + case PWR_GPIO_G: + CLEAR_BIT(PWR->PDCRG, GPIONumber); + break; +#endif + case PWR_GPIO_H: +#if defined (STM32L496xx) || defined (STM32L4A6xx) + CLEAR_BIT(PWR->PDCRH, ((GPIONumber & PWR_PORTH_AVAILABLE_PINS) & (~(PWR_GPIO_BIT_3)))); +#else + CLEAR_BIT(PWR->PDCRH, (GPIONumber & PWR_PORTH_AVAILABLE_PINS)); +#endif + break; +#if defined(GPIOI) + case PWR_GPIO_I: + CLEAR_BIT(PWR->PDCRI, (GPIONumber & PWR_PORTI_AVAILABLE_PINS)); + break; +#endif + default: + return HAL_ERROR; + } + + return HAL_OK; +} + + + +/** + * @brief Enable pull-up and pull-down configuration. + * @note When APC bit is set, the I/O pull-up and pull-down configurations defined in + * PWR_PUCRx and PWR_PDCRx registers are applied in Standby and Shutdown modes. + * @note Pull-up set by PUy bit of PWR_PUCRx register is not activated if the corresponding + * PDy bit of PWR_PDCRx register is also set (pull-down configuration priority is higher). + * HAL_PWREx_EnableGPIOPullUp() and HAL_PWREx_EnableGPIOPullDown() API's ensure there + * is no conflict when setting PUy or PDy bit. + * @retval None + */ +void HAL_PWREx_EnablePullUpPullDownConfig(void) +{ + SET_BIT(PWR->CR3, PWR_CR3_APC); +} + + +/** + * @brief Disable pull-up and pull-down configuration. + * @note When APC bit is cleared, the I/O pull-up and pull-down configurations defined in + * PWR_PUCRx and PWR_PDCRx registers are not applied in Standby and Shutdown modes. + * @retval None + */ +void HAL_PWREx_DisablePullUpPullDownConfig(void) +{ + CLEAR_BIT(PWR->CR3, PWR_CR3_APC); +} + + + +/** + * @brief Enable SRAM2 content retention in Standby mode. + * @note When RRS bit is set, SRAM2 is powered by the low-power regulator in + * Standby mode and its content is kept. + * @retval None + */ +void HAL_PWREx_EnableSRAM2ContentRetention(void) +{ + SET_BIT(PWR->CR3, PWR_CR3_RRS); +} + + +/** + * @brief Disable SRAM2 content retention in Standby mode. + * @note When RRS bit is reset, SRAM2 is powered off in Standby mode + * and its content is lost. + * @retval None + */ +void HAL_PWREx_DisableSRAM2ContentRetention(void) +{ + CLEAR_BIT(PWR->CR3, PWR_CR3_RRS); +} + + +#if defined(PWR_CR1_RRSTP) +/** + * @brief Enable SRAM3 content retention in Stop 2 mode. + * @note When RRSTP bit is set, SRAM3 is powered by the low-power regulator in + * Stop 2 mode and its content is kept. + * @retval None + */ +void HAL_PWREx_EnableSRAM3ContentRetention(void) +{ + SET_BIT(PWR->CR1, PWR_CR1_RRSTP); +} + + +/** + * @brief Disable SRAM3 content retention in Stop 2 mode. + * @note When RRSTP bit is reset, SRAM3 is powered off in Stop 2 mode + * and its content is lost. + * @retval None + */ +void HAL_PWREx_DisableSRAM3ContentRetention(void) +{ + CLEAR_BIT(PWR->CR1, PWR_CR1_RRSTP); +} +#endif /* PWR_CR1_RRSTP */ + +#if defined(PWR_CR3_DSIPDEN) +/** + * @brief Enable pull-down activation on DSI pins. + * @retval None + */ +void HAL_PWREx_EnableDSIPinsPDActivation(void) +{ + SET_BIT(PWR->CR3, PWR_CR3_DSIPDEN); +} + + +/** + * @brief Disable pull-down activation on DSI pins. + * @retval None + */ +void HAL_PWREx_DisableDSIPinsPDActivation(void) +{ + CLEAR_BIT(PWR->CR3, PWR_CR3_DSIPDEN); +} +#endif /* PWR_CR3_DSIPDEN */ + +#if defined(PWR_CR2_PVME1) +/** + * @brief Enable the Power Voltage Monitoring 1: VDDUSB versus 1.2V. + * @retval None + */ +void HAL_PWREx_EnablePVM1(void) +{ + SET_BIT(PWR->CR2, PWR_PVM_1); +} + +/** + * @brief Disable the Power Voltage Monitoring 1: VDDUSB versus 1.2V. + * @retval None + */ +void HAL_PWREx_DisablePVM1(void) +{ + CLEAR_BIT(PWR->CR2, PWR_PVM_1); +} +#endif /* PWR_CR2_PVME1 */ + + +#if defined(PWR_CR2_PVME2) +/** + * @brief Enable the Power Voltage Monitoring 2: VDDIO2 versus 0.9V. + * @retval None + */ +void HAL_PWREx_EnablePVM2(void) +{ + SET_BIT(PWR->CR2, PWR_PVM_2); +} + +/** + * @brief Disable the Power Voltage Monitoring 2: VDDIO2 versus 0.9V. + * @retval None + */ +void HAL_PWREx_DisablePVM2(void) +{ + CLEAR_BIT(PWR->CR2, PWR_PVM_2); +} +#endif /* PWR_CR2_PVME2 */ + + +/** + * @brief Enable the Power Voltage Monitoring 3: VDDA versus 1.62V. + * @retval None + */ +void HAL_PWREx_EnablePVM3(void) +{ + SET_BIT(PWR->CR2, PWR_PVM_3); +} + +/** + * @brief Disable the Power Voltage Monitoring 3: VDDA versus 1.62V. + * @retval None + */ +void HAL_PWREx_DisablePVM3(void) +{ + CLEAR_BIT(PWR->CR2, PWR_PVM_3); +} + + +/** + * @brief Enable the Power Voltage Monitoring 4: VDDA versus 2.2V. + * @retval None + */ +void HAL_PWREx_EnablePVM4(void) +{ + SET_BIT(PWR->CR2, PWR_PVM_4); +} + +/** + * @brief Disable the Power Voltage Monitoring 4: VDDA versus 2.2V. + * @retval None + */ +void HAL_PWREx_DisablePVM4(void) +{ + CLEAR_BIT(PWR->CR2, PWR_PVM_4); +} + + + + +/** + * @brief Configure the Peripheral Voltage Monitoring (PVM). + * @param sConfigPVM: pointer to a PWR_PVMTypeDef structure that contains the + * PVM configuration information. + * @note The API configures a single PVM according to the information contained + * in the input structure. To configure several PVMs, the API must be singly + * called for each PVM used. + * @note Refer to the electrical characteristics of your device datasheet for + * more details about the voltage thresholds corresponding to each + * detection level and to each monitored supply. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PWREx_ConfigPVM(PWR_PVMTypeDef *sConfigPVM) +{ + /* Check the parameters */ + assert_param(IS_PWR_PVM_TYPE(sConfigPVM->PVMType)); + assert_param(IS_PWR_PVM_MODE(sConfigPVM->Mode)); + + + /* Configure EXTI 35 to 38 interrupts if so required: + scan thru PVMType to detect which PVMx is set and + configure the corresponding EXTI line accordingly. */ + switch (sConfigPVM->PVMType) + { +#if defined(PWR_CR2_PVME1) + case PWR_PVM_1: + /* Clear any previous config. Keep it clear if no event or IT mode is selected */ + __HAL_PWR_PVM1_EXTI_DISABLE_EVENT(); + __HAL_PWR_PVM1_EXTI_DISABLE_IT(); + __HAL_PWR_PVM1_EXTI_DISABLE_FALLING_EDGE(); + __HAL_PWR_PVM1_EXTI_DISABLE_RISING_EDGE(); + + /* Configure interrupt mode */ + if((sConfigPVM->Mode & PVM_MODE_IT) == PVM_MODE_IT) + { + __HAL_PWR_PVM1_EXTI_ENABLE_IT(); + } + + /* Configure event mode */ + if((sConfigPVM->Mode & PVM_MODE_EVT) == PVM_MODE_EVT) + { + __HAL_PWR_PVM1_EXTI_ENABLE_EVENT(); + } + + /* Configure the edge */ + if((sConfigPVM->Mode & PVM_RISING_EDGE) == PVM_RISING_EDGE) + { + __HAL_PWR_PVM1_EXTI_ENABLE_RISING_EDGE(); + } + + if((sConfigPVM->Mode & PVM_FALLING_EDGE) == PVM_FALLING_EDGE) + { + __HAL_PWR_PVM1_EXTI_ENABLE_FALLING_EDGE(); + } + break; +#endif /* PWR_CR2_PVME1 */ + +#if defined(PWR_CR2_PVME2) + case PWR_PVM_2: + /* Clear any previous config. Keep it clear if no event or IT mode is selected */ + __HAL_PWR_PVM2_EXTI_DISABLE_EVENT(); + __HAL_PWR_PVM2_EXTI_DISABLE_IT(); + __HAL_PWR_PVM2_EXTI_DISABLE_FALLING_EDGE(); + __HAL_PWR_PVM2_EXTI_DISABLE_RISING_EDGE(); + + /* Configure interrupt mode */ + if((sConfigPVM->Mode & PVM_MODE_IT) == PVM_MODE_IT) + { + __HAL_PWR_PVM2_EXTI_ENABLE_IT(); + } + + /* Configure event mode */ + if((sConfigPVM->Mode & PVM_MODE_EVT) == PVM_MODE_EVT) + { + __HAL_PWR_PVM2_EXTI_ENABLE_EVENT(); + } + + /* Configure the edge */ + if((sConfigPVM->Mode & PVM_RISING_EDGE) == PVM_RISING_EDGE) + { + __HAL_PWR_PVM2_EXTI_ENABLE_RISING_EDGE(); + } + + if((sConfigPVM->Mode & PVM_FALLING_EDGE) == PVM_FALLING_EDGE) + { + __HAL_PWR_PVM2_EXTI_ENABLE_FALLING_EDGE(); + } + break; +#endif /* PWR_CR2_PVME2 */ + + case PWR_PVM_3: + /* Clear any previous config. Keep it clear if no event or IT mode is selected */ + __HAL_PWR_PVM3_EXTI_DISABLE_EVENT(); + __HAL_PWR_PVM3_EXTI_DISABLE_IT(); + __HAL_PWR_PVM3_EXTI_DISABLE_FALLING_EDGE(); + __HAL_PWR_PVM3_EXTI_DISABLE_RISING_EDGE(); + + /* Configure interrupt mode */ + if((sConfigPVM->Mode & PVM_MODE_IT) == PVM_MODE_IT) + { + __HAL_PWR_PVM3_EXTI_ENABLE_IT(); + } + + /* Configure event mode */ + if((sConfigPVM->Mode & PVM_MODE_EVT) == PVM_MODE_EVT) + { + __HAL_PWR_PVM3_EXTI_ENABLE_EVENT(); + } + + /* Configure the edge */ + if((sConfigPVM->Mode & PVM_RISING_EDGE) == PVM_RISING_EDGE) + { + __HAL_PWR_PVM3_EXTI_ENABLE_RISING_EDGE(); + } + + if((sConfigPVM->Mode & PVM_FALLING_EDGE) == PVM_FALLING_EDGE) + { + __HAL_PWR_PVM3_EXTI_ENABLE_FALLING_EDGE(); + } + break; + + case PWR_PVM_4: + /* Clear any previous config. Keep it clear if no event or IT mode is selected */ + __HAL_PWR_PVM4_EXTI_DISABLE_EVENT(); + __HAL_PWR_PVM4_EXTI_DISABLE_IT(); + __HAL_PWR_PVM4_EXTI_DISABLE_FALLING_EDGE(); + __HAL_PWR_PVM4_EXTI_DISABLE_RISING_EDGE(); + + /* Configure interrupt mode */ + if((sConfigPVM->Mode & PVM_MODE_IT) == PVM_MODE_IT) + { + __HAL_PWR_PVM4_EXTI_ENABLE_IT(); + } + + /* Configure event mode */ + if((sConfigPVM->Mode & PVM_MODE_EVT) == PVM_MODE_EVT) + { + __HAL_PWR_PVM4_EXTI_ENABLE_EVENT(); + } + + /* Configure the edge */ + if((sConfigPVM->Mode & PVM_RISING_EDGE) == PVM_RISING_EDGE) + { + __HAL_PWR_PVM4_EXTI_ENABLE_RISING_EDGE(); + } + + if((sConfigPVM->Mode & PVM_FALLING_EDGE) == PVM_FALLING_EDGE) + { + __HAL_PWR_PVM4_EXTI_ENABLE_FALLING_EDGE(); + } + break; + + default: + return HAL_ERROR; + + } + + + return HAL_OK; +} + + + +/** + * @brief Enter Low-power Run mode + * @note In Low-power Run mode, all I/O pins keep the same state as in Run mode. + * @note When Regulator is set to PWR_LOWPOWERREGULATOR_ON, the user can optionally configure the + * Flash in power-down monde in setting the RUN_PD bit in FLASH_ACR register. + * Additionally, the clock frequency must be reduced below 2 MHz. + * Setting RUN_PD in FLASH_ACR then appropriately reducing the clock frequency must + * be done before calling HAL_PWREx_EnableLowPowerRunMode() API. + * @retval None + */ +void HAL_PWREx_EnableLowPowerRunMode(void) +{ + /* Set Regulator parameter */ + SET_BIT(PWR->CR1, PWR_CR1_LPR); +} + + +/** + * @brief Exit Low-power Run mode. + * @note Before HAL_PWREx_DisableLowPowerRunMode() completion, the function checks that + * REGLPF has been properly reset (otherwise, HAL_PWREx_DisableLowPowerRunMode + * returns HAL_TIMEOUT status). The system clock frequency can then be + * increased above 2 MHz. + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_PWREx_DisableLowPowerRunMode(void) +{ + uint32_t wait_loop_index = 0; + + /* Clear LPR bit */ + CLEAR_BIT(PWR->CR1, PWR_CR1_LPR); + + /* Wait until REGLPF is reset */ + wait_loop_index = (PWR_FLAG_SETTING_DELAY_US * (SystemCoreClock / 1000000)); + while ((wait_loop_index != 0) && (HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_REGLPF))) + { + wait_loop_index--; + } + if (HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_REGLPF)) + { + return HAL_TIMEOUT; + } + + return HAL_OK; +} + + +/** + * @brief Enter Stop 0 mode. + * @note In Stop 0 mode, main and low voltage regulators are ON. + * @note In Stop 0 mode, all I/O pins keep the same state as in Run mode. + * @note All clocks in the VCORE domain are stopped; the PLL, the MSI, + * the HSI and the HSE oscillators are disabled. Some peripherals with the wakeup capability + * (I2Cx, USARTx and LPUART) can switch on the HSI to receive a frame, and switch off the HSI + * after receiving the frame if it is not a wakeup frame. In this case, the HSI clock is propagated + * only to the peripheral requesting it. + * SRAM1, SRAM2 and register contents are preserved. + * The BOR is available. + * @note When exiting Stop 0 mode by issuing an interrupt or a wakeup event, + * the HSI RC oscillator is selected as system clock if STOPWUCK bit in RCC_CFGR register + * is set; the MSI oscillator is selected if STOPWUCK is cleared. + * @note By keeping the internal regulator ON during Stop 0 mode, the consumption + * is higher although the startup time is reduced. + * @param STOPEntry specifies if Stop mode in entered with WFI or WFE instruction. + * This parameter can be one of the following values: + * @arg @ref PWR_STOPENTRY_WFI Enter Stop mode with WFI instruction + * @arg @ref PWR_STOPENTRY_WFE Enter Stop mode with WFE instruction + * @retval None + */ +void HAL_PWREx_EnterSTOP0Mode(uint8_t STOPEntry) +{ + /* Check the parameters */ + assert_param(IS_PWR_STOP_ENTRY(STOPEntry)); + + /* Stop 0 mode with Main Regulator */ + MODIFY_REG(PWR->CR1, PWR_CR1_LPMS, PWR_CR1_LPMS_STOP0); + + /* Set SLEEPDEEP bit of Cortex System Control Register */ + SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk)); + + /* Select Stop mode entry --------------------------------------------------*/ + if(STOPEntry == PWR_STOPENTRY_WFI) + { + /* Request Wait For Interrupt */ + __WFI(); + } + else + { + /* Request Wait For Event */ + __SEV(); + __WFE(); + __WFE(); + } + + /* Reset SLEEPDEEP bit of Cortex System Control Register */ + CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk)); +} + + +/** + * @brief Enter Stop 1 mode. + * @note In Stop 1 mode, only low power voltage regulator is ON. + * @note In Stop 1 mode, all I/O pins keep the same state as in Run mode. + * @note All clocks in the VCORE domain are stopped; the PLL, the MSI, + * the HSI and the HSE oscillators are disabled. Some peripherals with the wakeup capability + * (I2Cx, USARTx and LPUART) can switch on the HSI to receive a frame, and switch off the HSI + * after receiving the frame if it is not a wakeup frame. In this case, the HSI clock is propagated + * only to the peripheral requesting it. + * SRAM1, SRAM2 and register contents are preserved. + * The BOR is available. + * @note When exiting Stop 1 mode by issuing an interrupt or a wakeup event, + * the HSI RC oscillator is selected as system clock if STOPWUCK bit in RCC_CFGR register + * is set; the MSI oscillator is selected if STOPWUCK is cleared. + * @note Due to low power mode, an additional startup delay is incurred when waking up from Stop 1 mode. + * @param STOPEntry specifies if Stop mode in entered with WFI or WFE instruction. + * This parameter can be one of the following values: + * @arg @ref PWR_STOPENTRY_WFI Enter Stop mode with WFI instruction + * @arg @ref PWR_STOPENTRY_WFE Enter Stop mode with WFE instruction + * @retval None + */ +void HAL_PWREx_EnterSTOP1Mode(uint8_t STOPEntry) +{ + /* Check the parameters */ + assert_param(IS_PWR_STOP_ENTRY(STOPEntry)); + + /* Stop 1 mode with Low-Power Regulator */ + MODIFY_REG(PWR->CR1, PWR_CR1_LPMS, PWR_CR1_LPMS_STOP1); + + /* Set SLEEPDEEP bit of Cortex System Control Register */ + SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk)); + + /* Select Stop mode entry --------------------------------------------------*/ + if(STOPEntry == PWR_STOPENTRY_WFI) + { + /* Request Wait For Interrupt */ + __WFI(); + } + else + { + /* Request Wait For Event */ + __SEV(); + __WFE(); + __WFE(); + } + + /* Reset SLEEPDEEP bit of Cortex System Control Register */ + CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk)); +} + + +/** + * @brief Enter Stop 2 mode. + * @note In Stop 2 mode, only low power voltage regulator is ON. + * @note In Stop 2 mode, all I/O pins keep the same state as in Run mode. + * @note All clocks in the VCORE domain are stopped, the PLL, the MSI, + * the HSI and the HSE oscillators are disabled. Some peripherals with wakeup capability + * (LCD, LPTIM1, I2C3 and LPUART) can switch on the HSI to receive a frame, and switch off the HSI after + * receiving the frame if it is not a wakeup frame. In this case the HSI clock is propagated only + * to the peripheral requesting it. + * SRAM1, SRAM2 and register contents are preserved. + * The BOR is available. + * The voltage regulator is set in low-power mode but LPR bit must be cleared to enter stop 2 mode. + * Otherwise, Stop 1 mode is entered. + * @note When exiting Stop 2 mode by issuing an interrupt or a wakeup event, + * the HSI RC oscillator is selected as system clock if STOPWUCK bit in RCC_CFGR register + * is set; the MSI oscillator is selected if STOPWUCK is cleared. + * @param STOPEntry specifies if Stop mode in entered with WFI or WFE instruction. + * This parameter can be one of the following values: + * @arg @ref PWR_STOPENTRY_WFI Enter Stop mode with WFI instruction + * @arg @ref PWR_STOPENTRY_WFE Enter Stop mode with WFE instruction + * @retval None + */ +void HAL_PWREx_EnterSTOP2Mode(uint8_t STOPEntry) +{ + /* Check the parameter */ + assert_param(IS_PWR_STOP_ENTRY(STOPEntry)); + + /* Set Stop mode 2 */ + MODIFY_REG(PWR->CR1, PWR_CR1_LPMS, PWR_CR1_LPMS_STOP2); + + /* Set SLEEPDEEP bit of Cortex System Control Register */ + SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk)); + + /* Select Stop mode entry --------------------------------------------------*/ + if(STOPEntry == PWR_STOPENTRY_WFI) + { + /* Request Wait For Interrupt */ + __WFI(); + } + else + { + /* Request Wait For Event */ + __SEV(); + __WFE(); + __WFE(); + } + + /* Reset SLEEPDEEP bit of Cortex System Control Register */ + CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk)); +} + + + + + +/** + * @brief Enter Shutdown mode. + * @note In Shutdown mode, the PLL, the HSI, the MSI, the LSI and the HSE oscillators are switched + * off. The voltage regulator is disabled and Vcore domain is powered off. + * SRAM1, SRAM2 and registers contents are lost except for registers in the Backup domain. + * The BOR is not available. + * @note The I/Os can be configured either with a pull-up or pull-down or can be kept in analog state. + * @retval None + */ +void HAL_PWREx_EnterSHUTDOWNMode(void) +{ + + /* Set Shutdown mode */ + MODIFY_REG(PWR->CR1, PWR_CR1_LPMS, PWR_CR1_LPMS_SHUTDOWN); + + /* Set SLEEPDEEP bit of Cortex System Control Register */ + SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk)); + +/* This option is used to ensure that store operations are completed */ +#if defined ( __CC_ARM) + __force_stores(); +#endif + /* Request Wait For Interrupt */ + __WFI(); +} + + + + +/** + * @brief This function handles the PWR PVD/PVMx interrupt request. + * @note This API should be called under the PVD_PVM_IRQHandler(). + * @retval None + */ +void HAL_PWREx_PVD_PVM_IRQHandler(void) +{ + /* Check PWR exti flag */ + if(__HAL_PWR_PVD_EXTI_GET_FLAG() != RESET) + { + /* PWR PVD interrupt user callback */ + HAL_PWR_PVDCallback(); + + /* Clear PVD exti pending bit */ + __HAL_PWR_PVD_EXTI_CLEAR_FLAG(); + } + /* Next, successively check PVMx exti flags */ +#if defined(PWR_CR2_PVME1) + if(__HAL_PWR_PVM1_EXTI_GET_FLAG() != RESET) + { + /* PWR PVM1 interrupt user callback */ + HAL_PWREx_PVM1Callback(); + + /* Clear PVM1 exti pending bit */ + __HAL_PWR_PVM1_EXTI_CLEAR_FLAG(); + } +#endif /* PWR_CR2_PVME1 */ +#if defined(PWR_CR2_PVME2) + if(__HAL_PWR_PVM2_EXTI_GET_FLAG() != RESET) + { + /* PWR PVM2 interrupt user callback */ + HAL_PWREx_PVM2Callback(); + + /* Clear PVM2 exti pending bit */ + __HAL_PWR_PVM2_EXTI_CLEAR_FLAG(); + } +#endif /* PWR_CR2_PVME2 */ + if(__HAL_PWR_PVM3_EXTI_GET_FLAG() != RESET) + { + /* PWR PVM3 interrupt user callback */ + HAL_PWREx_PVM3Callback(); + + /* Clear PVM3 exti pending bit */ + __HAL_PWR_PVM3_EXTI_CLEAR_FLAG(); + } + if(__HAL_PWR_PVM4_EXTI_GET_FLAG() != RESET) + { + /* PWR PVM4 interrupt user callback */ + HAL_PWREx_PVM4Callback(); + + /* Clear PVM4 exti pending bit */ + __HAL_PWR_PVM4_EXTI_CLEAR_FLAG(); + } +} + + +#if defined(PWR_CR2_PVME1) +/** + * @brief PWR PVM1 interrupt callback + * @retval None + */ +__weak void HAL_PWREx_PVM1Callback(void) +{ + /* NOTE : This function should not be modified; when the callback is needed, + HAL_PWREx_PVM1Callback() API can be implemented in the user file + */ +} +#endif /* PWR_CR2_PVME1 */ + +#if defined(PWR_CR2_PVME2) +/** + * @brief PWR PVM2 interrupt callback + * @retval None + */ +__weak void HAL_PWREx_PVM2Callback(void) +{ + /* NOTE : This function should not be modified; when the callback is needed, + HAL_PWREx_PVM2Callback() API can be implemented in the user file + */ +} +#endif /* PWR_CR2_PVME2 */ + +/** + * @brief PWR PVM3 interrupt callback + * @retval None + */ +__weak void HAL_PWREx_PVM3Callback(void) +{ + /* NOTE : This function should not be modified; when the callback is needed, + HAL_PWREx_PVM3Callback() API can be implemented in the user file + */ +} + +/** + * @brief PWR PVM4 interrupt callback + * @retval None + */ +__weak void HAL_PWREx_PVM4Callback(void) +{ + /* NOTE : This function should not be modified; when the callback is needed, + HAL_PWREx_PVM4Callback() API can be implemented in the user file + */ +} + + +/** + * @} + */ + +/** + * @} + */ + +#endif /* HAL_PWR_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rcc.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rcc.c new file mode 100644 index 0000000..06a9b26 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rcc.c @@ -0,0 +1,1730 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_rcc.c + * @author MCD Application Team + * @brief RCC HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Reset and Clock Control (RCC) peripheral: + * + Initialization and de-initialization functions + * + Peripheral Control functions + * + @verbatim + ============================================================================== + ##### RCC specific features ##### + ============================================================================== + [..] + After reset the device is running from Multiple Speed Internal oscillator + (4 MHz) with Flash 0 wait state. Flash prefetch buffer, D-Cache + and I-Cache are disabled, and all peripherals are off except internal + SRAM, Flash and JTAG. + + (+) There is no prescaler on High speed (AHBs) and Low speed (APBs) busses: + all peripherals mapped on these busses are running at MSI speed. + (+) The clock for all peripherals is switched off, except the SRAM and FLASH. + (+) All GPIOs are in analog mode, except the JTAG pins which + are assigned to be used for debug purpose. + + [..] + Once the device started from reset, the user application has to: + (+) Configure the clock source to be used to drive the System clock + (if the application needs higher frequency/performance) + (+) Configure the System clock frequency and Flash settings + (+) Configure the AHB and APB busses prescalers + (+) Enable the clock for the peripheral(s) to be used + (+) Configure the clock source(s) for peripherals which clocks are not + derived from the System clock (SAIx, RTC, ADC, USB OTG FS/SDMMC1/RNG) + + @endverbatim + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup RCC RCC + * @brief RCC HAL module driver + * @{ + */ + +#ifdef HAL_RCC_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/** @defgroup RCC_Private_Constants RCC Private Constants + * @{ + */ +#define HSE_TIMEOUT_VALUE HSE_STARTUP_TIMEOUT +#define HSI_TIMEOUT_VALUE 2U /* 2 ms (minimum Tick + 1) */ +#define MSI_TIMEOUT_VALUE 2U /* 2 ms (minimum Tick + 1) */ +#define LSI_TIMEOUT_VALUE 2U /* 2 ms (minimum Tick + 1) */ +#define HSI48_TIMEOUT_VALUE 2U /* 2 ms (minimum Tick + 1) */ +#define PLL_TIMEOUT_VALUE 2U /* 2 ms (minimum Tick + 1) */ +#define CLOCKSWITCH_TIMEOUT_VALUE 5000U /* 5 s */ +/** + * @} + */ + +/* Private macro -------------------------------------------------------------*/ +/** @defgroup RCC_Private_Macros RCC Private Macros + * @{ + */ +#define __MCO1_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE() +#define MCO1_GPIO_PORT GPIOA +#define MCO1_PIN GPIO_PIN_8 + +#define RCC_PLL_OSCSOURCE_CONFIG(__HAL_RCC_PLLSOURCE__) \ + (MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, (__HAL_RCC_PLLSOURCE__))) +/** + * @} + */ + +/* Private variables ---------------------------------------------------------*/ + +/* Private function prototypes -----------------------------------------------*/ +/** @defgroup RCC_Private_Functions RCC Private Functions + * @{ + */ +static HAL_StatusTypeDef RCC_SetFlashLatencyFromMSIRange(uint32_t msirange); +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +static uint32_t RCC_GetSysClockFreqFromPLLSource(void); +#endif +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup RCC_Exported_Functions RCC Exported Functions + * @{ + */ + +/** @defgroup RCC_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions + * + @verbatim + =============================================================================== + ##### Initialization and de-initialization functions ##### + =============================================================================== + [..] + This section provides functions allowing to configure the internal and external oscillators + (HSE, HSI, LSE, MSI, LSI, PLL, CSS and MCO) and the System busses clocks (SYSCLK, AHB, APB1 + and APB2). + + [..] Internal/external clock and PLL configuration + (+) HSI (high-speed internal): 16 MHz factory-trimmed RC used directly or through + the PLL as System clock source. + + (+) MSI (Mutiple Speed Internal): Its frequency is software trimmable from 100KHZ to 48MHZ. + It can be used to generate the clock for the USB OTG FS (48 MHz). + The number of flash wait states is automatically adjusted when MSI range is updated with + HAL_RCC_OscConfig() and the MSI is used as System clock source. + + (+) LSI (low-speed internal): 32 KHz low consumption RC used as IWDG and/or RTC + clock source. + + (+) HSE (high-speed external): 4 to 48 MHz crystal oscillator used directly or + through the PLL as System clock source. Can be used also optionally as RTC clock source. + + (+) LSE (low-speed external): 32.768 KHz oscillator used optionally as RTC clock source. + + (+) PLL (clocked by HSI, HSE or MSI) providing up to three independent output clocks: + (++) The first output is used to generate the high speed system clock (up to 80MHz). + (++) The second output is used to generate the clock for the USB OTG FS (48 MHz), + the random analog generator (<=48 MHz) and the SDMMC1 (<= 48 MHz). + (++) The third output is used to generate an accurate clock to achieve + high-quality audio performance on SAI interface. + + (+) PLLSAI1 (clocked by HSI, HSE or MSI) providing up to three independent output clocks: + (++) The first output is used to generate SAR ADC1 clock. + (++) The second output is used to generate the clock for the USB OTG FS (48 MHz), + the random analog generator (<=48 MHz) and the SDMMC1 (<= 48 MHz). + (++) The Third output is used to generate an accurate clock to achieve + high-quality audio performance on SAI interface. + + (+) PLLSAI2 (clocked by HSI , HSE or MSI) providing up to two independent output clocks: + (++) The first output is used to generate SAR ADC2 clock. + (++) The second output is used to generate an accurate clock to achieve + high-quality audio performance on SAI interface. + + (+) CSS (Clock security system): once enabled, if a HSE clock failure occurs + (HSE used directly or through PLL as System clock source), the System clock + is automatically switched to HSI and an interrupt is generated if enabled. + The interrupt is linked to the Cortex-M4 NMI (Non-Maskable Interrupt) + exception vector. + + (+) MCO (microcontroller clock output): used to output MSI, LSI, HSI, LSE, HSE or + main PLL clock (through a configurable prescaler) on PA8 pin. + + [..] System, AHB and APB busses clocks configuration + (+) Several clock sources can be used to drive the System clock (SYSCLK): MSI, HSI, + HSE and main PLL. + The AHB clock (HCLK) is derived from System clock through configurable + prescaler and used to clock the CPU, memory and peripherals mapped + on AHB bus (DMA, GPIO...). APB1 (PCLK1) and APB2 (PCLK2) clocks are derived + from AHB clock through configurable prescalers and used to clock + the peripherals mapped on these busses. You can use + "HAL_RCC_GetSysClockFreq()" function to retrieve the frequencies of these clocks. + + -@- All the peripheral clocks are derived from the System clock (SYSCLK) except: + + (+@) SAI: the SAI clock can be derived either from a specific PLL (PLLSAI1) or (PLLSAI2) or + from an external clock mapped on the SAI_CKIN pin. + You have to use HAL_RCCEx_PeriphCLKConfig() function to configure this clock. + (+@) RTC: the RTC clock can be derived either from the LSI, LSE or HSE clock + divided by 2 to 31. + You have to use __HAL_RCC_RTC_ENABLE() and HAL_RCCEx_PeriphCLKConfig() function + to configure this clock. + (+@) USB OTG FS, SDMMC1 and RNG: USB OTG FS requires a frequency equal to 48 MHz + to work correctly, while the SDMMC1 and RNG peripherals require a frequency + equal or lower than to 48 MHz. This clock is derived of the main PLL or PLLSAI1 + through PLLQ divider. You have to enable the peripheral clock and use + HAL_RCCEx_PeriphCLKConfig() function to configure this clock. + (+@) IWDG clock which is always the LSI clock. + + + (+) The maximum frequency of the SYSCLK, HCLK, PCLK1 and PCLK2 is 80 MHz. + The clock source frequency should be adapted depending on the device voltage range + as listed in the Reference Manual "Clock source frequency versus voltage scaling" chapter. + + @endverbatim + + Table 1. HCLK clock frequency for STM32L4Rx/STM32L4Sx devices + +--------------------------------------------------------+ + | Latency | HCLK clock frequency (MHz) | + | |--------------------------------------| + | | voltage range 1 | voltage range 2 | + | | 1.2 V | 1.0 V | + |-----------------|-------------------|------------------| + |0WS(1 CPU cycles)| 0 < HCLK <= 20 | 0 < HCLK <= 8 | + |-----------------|-------------------|------------------| + |1WS(2 CPU cycles)| 20 < HCLK <= 40 | 8 < HCLK <= 16 | + |-----------------|-------------------|------------------| + |2WS(3 CPU cycles)| 40 < HCLK <= 60 | 16 < HCLK <= 26 | + |-----------------|-------------------|------------------| + |3WS(4 CPU cycles)| 60 < HCLK <= 80 | 16 < HCLK <= 26 | + |-----------------|-------------------|------------------| + |4WS(5 CPU cycles)| 80 < HCLK <= 100 | 16 < HCLK <= 26 | + |-----------------|-------------------|------------------| + |5WS(6 CPU cycles)| 100 < HCLK <= 120 | 16 < HCLK <= 26 | + +--------------------------------------------------------+ + + Table 2. HCLK clock frequency for other STM32L4 devices + +-------------------------------------------------------+ + | Latency | HCLK clock frequency (MHz) | + | |-------------------------------------| + | | voltage range 1 | voltage range 2 | + | | 1.2 V | 1.0 V | + |-----------------|------------------|------------------| + |0WS(1 CPU cycles)| 0 < HCLK <= 16 | 0 < HCLK <= 6 | + |-----------------|------------------|------------------| + |1WS(2 CPU cycles)| 16 < HCLK <= 32 | 6 < HCLK <= 12 | + |-----------------|------------------|------------------| + |2WS(3 CPU cycles)| 32 < HCLK <= 48 | 12 < HCLK <= 18 | + |-----------------|------------------|------------------| + |3WS(4 CPU cycles)| 48 < HCLK <= 64 | 18 < HCLK <= 26 | + |-----------------|------------------|------------------| + |4WS(5 CPU cycles)| 64 < HCLK <= 80 | 18 < HCLK <= 26 | + +-------------------------------------------------------+ + * @{ + */ + +/** + * @brief Reset the RCC clock configuration to the default reset state. + * @note The default reset state of the clock configuration is given below: + * - MSI ON and used as system clock source + * - HSE, HSI, PLL, PLLSAI1 and PLLISAI2 OFF + * - AHB, APB1 and APB2 prescaler set to 1. + * - CSS, MCO1 OFF + * - All interrupts disabled + * - All interrupt and reset flags cleared + * @note This function doesn't modify the configuration of the + * - Peripheral clocks + * - LSI, LSE and RTC clocks + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RCC_DeInit(void) +{ + uint32_t tickstart = 0; + + /* Set MSION bit */ + SET_BIT(RCC->CR, RCC_CR_MSION); + + /* Insure MSIRDY bit is set before writing default MSIRANGE value */ + /* Get start tick */ + tickstart = HAL_GetTick(); + + /* Wait till MSI is ready */ + while(READ_BIT(RCC->CR, RCC_CR_MSIRDY) == RESET) + { + if((HAL_GetTick() - tickstart) > MSI_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + + /* Set MSIRANGE default value */ + MODIFY_REG(RCC->CR, RCC_CR_MSIRANGE, RCC_MSIRANGE_6); + + /* Reset CFGR register (MSI is selected as system clock source) */ + CLEAR_REG(RCC->CFGR); + + /* Update the SystemCoreClock global variable for MSI as system clock source */ + SystemCoreClock = MSI_VALUE; + + /* Configure the source of time base considering new system clock settings */ + if(HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK) + { + return HAL_ERROR; + } + + /* Insure MSI selected as system clock source */ + /* Get start tick */ + tickstart = HAL_GetTick(); + + /* Wait till system clock source is ready */ + while(READ_BIT(RCC->CFGR, RCC_CFGR_SWS) != RCC_CFGR_SWS_MSI) + { + if((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + + /* Reset HSION, HSIKERON, HSIASFS, HSEON, HSECSSON, PLLON, PLLSAIxON bits */ +#if defined(RCC_PLLSAI2_SUPPORT) + + CLEAR_BIT(RCC->CR, RCC_CR_HSEON | RCC_CR_HSION | RCC_CR_HSIKERON| RCC_CR_HSIASFS | RCC_CR_PLLON | RCC_CR_PLLSAI1ON | RCC_CR_PLLSAI2ON); + +#else + + CLEAR_BIT(RCC->CR, RCC_CR_HSEON | RCC_CR_HSION | RCC_CR_HSIKERON| RCC_CR_HSIASFS | RCC_CR_PLLON | RCC_CR_PLLSAI1ON); + +#endif /* RCC_PLLSAI2_SUPPORT */ + + /* Insure PLLRDY, PLLSAI1RDY and PLLSAI2RDY (if present) are reset */ + /* Get start tick */ + tickstart = HAL_GetTick(); + +#if defined(RCC_PLLSAI2_SUPPORT) + + while(READ_BIT(RCC->CR, RCC_CR_PLLRDY | RCC_CR_PLLSAI1RDY | RCC_CR_PLLSAI2RDY) != 0U) + +#else + + while(READ_BIT(RCC->CR, RCC_CR_PLLRDY | RCC_CR_PLLSAI1RDY) != 0U) + +#endif + { + if((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + + /* Reset PLLCFGR register */ + CLEAR_REG(RCC->PLLCFGR); + SET_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN_4 ); + + /* Reset PLLSAI1CFGR register */ + CLEAR_REG(RCC->PLLSAI1CFGR); + SET_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N_4 ); + +#if defined(RCC_PLLSAI2_SUPPORT) + + /* Reset PLLSAI2CFGR register */ + CLEAR_REG(RCC->PLLSAI2CFGR); + SET_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2N_4 ); + +#endif /* RCC_PLLSAI2_SUPPORT */ + + /* Reset HSEBYP bit */ + CLEAR_BIT(RCC->CR, RCC_CR_HSEBYP); + + /* Disable all interrupts */ + CLEAR_REG(RCC->CIER); + + /* Clear all interrupt flags */ + WRITE_REG(RCC->CICR, 0xFFFFFFFFU); + + /* Clear all reset flags */ + SET_BIT(RCC->CSR, RCC_CSR_RMVF); + + return HAL_OK; +} + +/** + * @brief Initialize the RCC Oscillators according to the specified parameters in the + * RCC_OscInitTypeDef. + * @param RCC_OscInitStruct pointer to an RCC_OscInitTypeDef structure that + * contains the configuration information for the RCC Oscillators. + * @note The PLL is not disabled when used as system clock. + * @note Transitions LSE Bypass to LSE On and LSE On to LSE Bypass are not + * supported by this macro. User should request a transition to LSE Off + * first and then LSE On or LSE Bypass. + * @note Transition HSE Bypass to HSE On and HSE On to HSE Bypass are not + * supported by this macro. User should request a transition to HSE Off + * first and then HSE On or HSE Bypass. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) +{ + uint32_t tickstart = 0; + + /* Check the parameters */ + assert_param(RCC_OscInitStruct != NULL); + assert_param(IS_RCC_OSCILLATORTYPE(RCC_OscInitStruct->OscillatorType)); + + /*----------------------------- MSI Configuration --------------------------*/ + if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_MSI) == RCC_OSCILLATORTYPE_MSI) + { + /* Check the parameters */ + assert_param(IS_RCC_MSI(RCC_OscInitStruct->MSIState)); + assert_param(IS_RCC_MSICALIBRATION_VALUE(RCC_OscInitStruct->MSICalibrationValue)); + assert_param(IS_RCC_MSI_CLOCK_RANGE(RCC_OscInitStruct->MSIClockRange)); + + /* When the MSI is used as system clock it will not be disabled */ + if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_MSI) ) + { + if((READ_BIT(RCC->CR, RCC_CR_MSIRDY) != RESET) && (RCC_OscInitStruct->MSIState == RCC_MSI_OFF)) + { + return HAL_ERROR; + } + + /* Otherwise, just the calibration and MSI range change are allowed */ + else + { + /* To correctly read data from FLASH memory, the number of wait states (LATENCY) + must be correctly programmed according to the frequency of the CPU clock + (HCLK) and the supply voltage of the device. */ + if(RCC_OscInitStruct->MSIClockRange > __HAL_RCC_GET_MSI_RANGE()) + { + /* First increase number of wait states update if necessary */ + if(RCC_SetFlashLatencyFromMSIRange(RCC_OscInitStruct->MSIClockRange) != HAL_OK) + { + return HAL_ERROR; + } + + /* Selects the Multiple Speed oscillator (MSI) clock range .*/ + __HAL_RCC_MSI_RANGE_CONFIG(RCC_OscInitStruct->MSIClockRange); + /* Adjusts the Multiple Speed oscillator (MSI) calibration value.*/ + __HAL_RCC_MSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->MSICalibrationValue); + } + else + { + /* Else, keep current flash latency while decreasing applies */ + /* Selects the Multiple Speed oscillator (MSI) clock range .*/ + __HAL_RCC_MSI_RANGE_CONFIG(RCC_OscInitStruct->MSIClockRange); + /* Adjusts the Multiple Speed oscillator (MSI) calibration value.*/ + __HAL_RCC_MSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->MSICalibrationValue); + + /* Decrease number of wait states update if necessary */ + if(RCC_SetFlashLatencyFromMSIRange(RCC_OscInitStruct->MSIClockRange) != HAL_OK) + { + return HAL_ERROR; + } + } + + /* Update the SystemCoreClock global variable */ + SystemCoreClock = HAL_RCC_GetSysClockFreq() >> AHBPrescTable[READ_BIT(RCC->CFGR, RCC_CFGR_HPRE) >> RCC_CFGR_HPRE_Pos]; + + /* Configure the source of time base considering new system clocks settings*/ + HAL_InitTick (TICK_INT_PRIORITY); + } + } + else + { + /* Check the MSI State */ + if(RCC_OscInitStruct->MSIState != RCC_MSI_OFF) + { + /* Enable the Internal High Speed oscillator (MSI). */ + __HAL_RCC_MSI_ENABLE(); + + /* Get timeout */ + tickstart = HAL_GetTick(); + + /* Wait till MSI is ready */ + while(READ_BIT(RCC->CR, RCC_CR_MSIRDY) == RESET) + { + if((HAL_GetTick() - tickstart) > MSI_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + /* Selects the Multiple Speed oscillator (MSI) clock range .*/ + __HAL_RCC_MSI_RANGE_CONFIG(RCC_OscInitStruct->MSIClockRange); + /* Adjusts the Multiple Speed oscillator (MSI) calibration value.*/ + __HAL_RCC_MSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->MSICalibrationValue); + + } + else + { + /* Disable the Internal High Speed oscillator (MSI). */ + __HAL_RCC_MSI_DISABLE(); + + /* Get timeout */ + tickstart = HAL_GetTick(); + + /* Wait till MSI is ready */ + while(READ_BIT(RCC->CR, RCC_CR_MSIRDY) != RESET) + { + if((HAL_GetTick() - tickstart) > MSI_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + } + } + /*------------------------------- HSE Configuration ------------------------*/ + if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSE) == RCC_OSCILLATORTYPE_HSE) + { + /* Check the parameters */ + assert_param(IS_RCC_HSE(RCC_OscInitStruct->HSEState)); + + /* When the HSE is used as system clock or clock source for PLL in these cases it is not allowed to be disabled */ + if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSE) || + ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && (__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSE))) + { + if((READ_BIT(RCC->CR, RCC_CR_HSERDY) != RESET) && (RCC_OscInitStruct->HSEState == RCC_HSE_OFF)) + { + return HAL_ERROR; + } + } + else + { + /* Set the new HSE configuration ---------------------------------------*/ + __HAL_RCC_HSE_CONFIG(RCC_OscInitStruct->HSEState); + + /* Check the HSE State */ + if(RCC_OscInitStruct->HSEState != RCC_HSE_OFF) + { + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till HSE is ready */ + while(READ_BIT(RCC->CR, RCC_CR_HSERDY) == RESET) + { + if((HAL_GetTick() - tickstart) > HSE_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + else + { + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till HSE is disabled */ + while(READ_BIT(RCC->CR, RCC_CR_HSERDY) != RESET) + { + if((HAL_GetTick() - tickstart) > HSE_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + } + } + /*----------------------------- HSI Configuration --------------------------*/ + if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSI) == RCC_OSCILLATORTYPE_HSI) + { + /* Check the parameters */ + assert_param(IS_RCC_HSI(RCC_OscInitStruct->HSIState)); + assert_param(IS_RCC_HSI_CALIBRATION_VALUE(RCC_OscInitStruct->HSICalibrationValue)); + + /* Check if HSI is used as system clock or as PLL source when PLL is selected as system clock */ + if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSI) || + ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && (__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSI))) + { + /* When HSI is used as system clock it will not be disabled */ + if((READ_BIT(RCC->CR, RCC_CR_HSIRDY) != RESET) && (RCC_OscInitStruct->HSIState == RCC_HSI_OFF)) + { + return HAL_ERROR; + } + /* Otherwise, just the calibration is allowed */ + else + { + /* Adjusts the Internal High Speed oscillator (HSI) calibration value.*/ + __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->HSICalibrationValue); + } + } + else + { + /* Check the HSI State */ + if(RCC_OscInitStruct->HSIState != RCC_HSI_OFF) + { + /* Enable the Internal High Speed oscillator (HSI). */ + __HAL_RCC_HSI_ENABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till HSI is ready */ + while(READ_BIT(RCC->CR, RCC_CR_HSIRDY) == RESET) + { + if((HAL_GetTick() - tickstart) > HSI_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + + /* Adjusts the Internal High Speed oscillator (HSI) calibration value.*/ + __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->HSICalibrationValue); + } + else + { + /* Disable the Internal High Speed oscillator (HSI). */ + __HAL_RCC_HSI_DISABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till HSI is disabled */ + while(READ_BIT(RCC->CR, RCC_CR_HSIRDY) != RESET) + { + if((HAL_GetTick() - tickstart) > HSI_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + } + } + /*------------------------------ LSI Configuration -------------------------*/ + if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSI) == RCC_OSCILLATORTYPE_LSI) + { + /* Check the parameters */ + assert_param(IS_RCC_LSI(RCC_OscInitStruct->LSIState)); + + /* Check the LSI State */ + if(RCC_OscInitStruct->LSIState != RCC_LSI_OFF) + { + /* Enable the Internal Low Speed oscillator (LSI). */ + __HAL_RCC_LSI_ENABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till LSI is ready */ + while(READ_BIT(RCC->CSR, RCC_CSR_LSIRDY) == RESET) + { + if((HAL_GetTick() - tickstart) > LSI_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + else + { + /* Disable the Internal Low Speed oscillator (LSI). */ + __HAL_RCC_LSI_DISABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till LSI is disabled */ + while(READ_BIT(RCC->CSR, RCC_CSR_LSIRDY) != RESET) + { + if((HAL_GetTick() - tickstart) > LSI_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + } + /*------------------------------ LSE Configuration -------------------------*/ + if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSE) == RCC_OSCILLATORTYPE_LSE) + { + FlagStatus pwrclkchanged = RESET; + + /* Check the parameters */ + assert_param(IS_RCC_LSE(RCC_OscInitStruct->LSEState)); + + /* Update LSE configuration in Backup Domain control register */ + /* Requires to enable write access to Backup Domain of necessary */ + if(HAL_IS_BIT_CLR(RCC->APB1ENR1, RCC_APB1ENR1_PWREN)) + { + __HAL_RCC_PWR_CLK_ENABLE(); + pwrclkchanged = SET; + } + + if(HAL_IS_BIT_CLR(PWR->CR1, PWR_CR1_DBP)) + { + /* Enable write access to Backup domain */ + SET_BIT(PWR->CR1, PWR_CR1_DBP); + + /* Wait for Backup domain Write protection disable */ + tickstart = HAL_GetTick(); + + while(HAL_IS_BIT_CLR(PWR->CR1, PWR_CR1_DBP)) + { + if((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + + /* Set the new LSE configuration -----------------------------------------*/ + __HAL_RCC_LSE_CONFIG(RCC_OscInitStruct->LSEState); + + /* Check the LSE State */ + if(RCC_OscInitStruct->LSEState != RCC_LSE_OFF) + { + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till LSE is ready */ + while(READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) == RESET) + { + if((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + else + { + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till LSE is disabled */ + while(READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) != RESET) + { + if((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + + /* Restore clock configuration if changed */ + if(pwrclkchanged == SET) + { + __HAL_RCC_PWR_CLK_DISABLE(); + } + } +#if defined(RCC_HSI48_SUPPORT) + /*------------------------------ HSI48 Configuration -----------------------*/ + if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSI48) == RCC_OSCILLATORTYPE_HSI48) + { + /* Check the parameters */ + assert_param(IS_RCC_HSI48(RCC_OscInitStruct->HSI48State)); + + /* Check the LSI State */ + if(RCC_OscInitStruct->HSI48State != RCC_HSI48_OFF) + { + /* Enable the Internal Low Speed oscillator (HSI48). */ + __HAL_RCC_HSI48_ENABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till HSI48 is ready */ + while(READ_BIT(RCC->CRRCR, RCC_CRRCR_HSI48RDY) == RESET) + { + if((HAL_GetTick() - tickstart) > HSI48_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + else + { + /* Disable the Internal Low Speed oscillator (HSI48). */ + __HAL_RCC_HSI48_DISABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till HSI48 is disabled */ + while(READ_BIT(RCC->CRRCR, RCC_CRRCR_HSI48RDY) != RESET) + { + if((HAL_GetTick() - tickstart) > HSI48_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + } +#endif /* RCC_HSI48_SUPPORT */ + /*-------------------------------- PLL Configuration -----------------------*/ + /* Check the parameters */ + assert_param(IS_RCC_PLL(RCC_OscInitStruct->PLL.PLLState)); + + if(RCC_OscInitStruct->PLL.PLLState != RCC_PLL_NONE) + { + /* Check if the PLL is used as system clock or not */ + if(__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL) + { + if(RCC_OscInitStruct->PLL.PLLState == RCC_PLL_ON) + { + /* Check the parameters */ + assert_param(IS_RCC_PLLSOURCE(RCC_OscInitStruct->PLL.PLLSource)); + assert_param(IS_RCC_PLLM_VALUE(RCC_OscInitStruct->PLL.PLLM)); + assert_param(IS_RCC_PLLN_VALUE(RCC_OscInitStruct->PLL.PLLN)); + assert_param(IS_RCC_PLLP_VALUE(RCC_OscInitStruct->PLL.PLLP)); + assert_param(IS_RCC_PLLQ_VALUE(RCC_OscInitStruct->PLL.PLLQ)); + assert_param(IS_RCC_PLLR_VALUE(RCC_OscInitStruct->PLL.PLLR)); + + /* Disable the main PLL. */ + __HAL_RCC_PLL_DISABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till PLL is ready */ + while(READ_BIT(RCC->CR, RCC_CR_PLLRDY) != RESET) + { + if((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + + /* Configure the main PLL clock source, multiplication and division factors. */ + __HAL_RCC_PLL_CONFIG(RCC_OscInitStruct->PLL.PLLSource, + RCC_OscInitStruct->PLL.PLLM, + RCC_OscInitStruct->PLL.PLLN, + RCC_OscInitStruct->PLL.PLLP, + RCC_OscInitStruct->PLL.PLLQ, + RCC_OscInitStruct->PLL.PLLR); + + /* Enable the main PLL. */ + __HAL_RCC_PLL_ENABLE(); + + /* Enable PLL System Clock output. */ + __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_SYSCLK); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till PLL is ready */ + while(READ_BIT(RCC->CR, RCC_CR_PLLRDY) == RESET) + { + if((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + else + { + /* Disable the main PLL. */ + __HAL_RCC_PLL_DISABLE(); + + /* Disable all PLL outputs to save power if no PLLs on */ + if((READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) == RESET) +#if defined(RCC_PLLSAI2_SUPPORT) + && + (READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) == RESET) +#endif /* RCC_PLLSAI2_SUPPORT */ + ) + { + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, RCC_PLLSOURCE_NONE); + } + +#if defined(RCC_PLLSAI2_SUPPORT) + __HAL_RCC_PLLCLKOUT_DISABLE(RCC_PLL_SYSCLK | RCC_PLL_48M1CLK | RCC_PLL_SAI3CLK); +#else + __HAL_RCC_PLLCLKOUT_DISABLE(RCC_PLL_SYSCLK | RCC_PLL_48M1CLK | RCC_PLL_SAI2CLK); +#endif /* RCC_PLLSAI2_SUPPORT */ + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till PLL is disabled */ + while(READ_BIT(RCC->CR, RCC_CR_PLLRDY) != RESET) + { + if((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + } + else + { + return HAL_ERROR; + } + } + return HAL_OK; +} + +/** + * @brief Initialize the CPU, AHB and APB busses clocks according to the specified + * parameters in the RCC_ClkInitStruct. + * @param RCC_ClkInitStruct pointer to an RCC_OscInitTypeDef structure that + * contains the configuration information for the RCC peripheral. + * @param FLatency FLASH Latency + * This parameter can be one of the following values: + * @arg FLASH_LATENCY_0 FLASH 0 Latency cycle + * @arg FLASH_LATENCY_1 FLASH 1 Latency cycle + * @arg FLASH_LATENCY_2 FLASH 2 Latency cycles + * @arg FLASH_LATENCY_3 FLASH 3 Latency cycles + * @arg FLASH_LATENCY_4 FLASH 4 Latency cycles + @if STM32L4S9xx + * @arg FLASH_LATENCY_5 FLASH 5 Latency cycles + * @arg FLASH_LATENCY_6 FLASH 6 Latency cycles + * @arg FLASH_LATENCY_7 FLASH 7 Latency cycles + * @arg FLASH_LATENCY_8 FLASH 8 Latency cycles + * @arg FLASH_LATENCY_9 FLASH 9 Latency cycles + * @arg FLASH_LATENCY_10 FLASH 10 Latency cycles + * @arg FLASH_LATENCY_11 FLASH 11 Latency cycles + * @arg FLASH_LATENCY_12 FLASH 12 Latency cycles + * @arg FLASH_LATENCY_13 FLASH 13 Latency cycles + * @arg FLASH_LATENCY_14 FLASH 14 Latency cycles + * @arg FLASH_LATENCY_15 FLASH 15 Latency cycles + @endif + * + * @note The SystemCoreClock CMSIS variable is used to store System Clock Frequency + * and updated by HAL_RCC_GetHCLKFreq() function called within this function + * + * @note The MSI is used by default as system clock source after + * startup from Reset, wake-up from STANDBY mode. After restart from Reset, + * the MSI frequency is set to its default value 4 MHz. + * + * @note The HSI can be selected as system clock source after + * from STOP modes or in case of failure of the HSE used directly or indirectly + * as system clock (if the Clock Security System CSS is enabled). + * + * @note A switch from one clock source to another occurs only if the target + * clock source is ready (clock stable after startup delay or PLL locked). + * If a clock source which is not yet ready is selected, the switch will + * occur when the clock source is ready. + * + * @note You can use HAL_RCC_GetClockConfig() function to know which clock is + * currently used as system clock source. + * + * @note Depending on the device voltage range, the software has to set correctly + * HPRE[3:0] bits to ensure that HCLK not exceed the maximum allowed frequency + * (for more details refer to section above "Initialization/de-initialization functions") + * @retval None + */ +HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, uint32_t FLatency) +{ + uint32_t tickstart = 0; +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + uint32_t pllfreq = 0; + uint32_t hpre = RCC_SYSCLK_DIV1; +#endif + + /* Check the parameters */ + assert_param(RCC_ClkInitStruct != NULL); + assert_param(IS_RCC_CLOCKTYPE(RCC_ClkInitStruct->ClockType)); + assert_param(IS_FLASH_LATENCY(FLatency)); + + /* To correctly read data from FLASH memory, the number of wait states (LATENCY) + must be correctly programmed according to the frequency of the CPU clock + (HCLK) and the supply voltage of the device. */ + + /* Increasing the number of wait states because of higher CPU frequency */ + if(FLatency > READ_BIT(FLASH->ACR, FLASH_ACR_LATENCY)) + { + /* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */ + __HAL_FLASH_SET_LATENCY(FLatency); + + /* Check that the new number of wait states is taken into account to access the Flash + memory by reading the FLASH_ACR register */ + if(READ_BIT(FLASH->ACR, FLASH_ACR_LATENCY) != FLatency) + { + return HAL_ERROR; + } + } + + /*------------------------- SYSCLK Configuration ---------------------------*/ + if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_SYSCLK) == RCC_CLOCKTYPE_SYSCLK) + { + assert_param(IS_RCC_SYSCLKSOURCE(RCC_ClkInitStruct->SYSCLKSource)); + + /* PLL is selected as System Clock Source */ + if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_PLLCLK) + { + /* Check the PLL ready flag */ + if(READ_BIT(RCC->CR, RCC_CR_PLLRDY) == RESET) + { + return HAL_ERROR; + } +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + /* Undershoot management when selection PLL as SYSCLK source and frequency above 80Mhz */ + /* Compute target PLL output frequency */ + pllfreq = RCC_GetSysClockFreqFromPLLSource(); + + /* Intermediate step with HCLK prescaler 2 necessary before to go over 80Mhz */ + if((pllfreq > 80000000U) && + (((((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_HCLK) == RCC_CLOCKTYPE_HCLK) && (RCC_ClkInitStruct->AHBCLKDivider == RCC_SYSCLK_DIV1)) + || + ((READ_BIT(RCC->CFGR, RCC_CFGR_HPRE) == RCC_SYSCLK_DIV1)))) + { + MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_SYSCLK_DIV2); + hpre = RCC_SYSCLK_DIV2; + } +#endif + } + else + { + /* HSE is selected as System Clock Source */ + if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_HSE) + { + /* Check the HSE ready flag */ + if(READ_BIT(RCC->CR, RCC_CR_HSERDY) == RESET) + { + return HAL_ERROR; + } + } + /* MSI is selected as System Clock Source */ + else if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_MSI) + { + /* Check the MSI ready flag */ + if(READ_BIT(RCC->CR, RCC_CR_MSIRDY) == RESET) + { + return HAL_ERROR; + } + } + /* HSI is selected as System Clock Source */ + else + { + /* Check the HSI ready flag */ + if(READ_BIT(RCC->CR, RCC_CR_HSIRDY) == RESET) + { + return HAL_ERROR; + } + } +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + /* Overshoot management when going down from PLL as SYSCLK source and frequency above 80Mhz */ + pllfreq = HAL_RCC_GetSysClockFreq(); + + /* Intermediate step with HCLK prescaler 2 necessary before to go under 80Mhz */ + if(pllfreq > 80000000U) + { + MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_SYSCLK_DIV2); + hpre = RCC_SYSCLK_DIV2; + } +#endif + + } + + MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_ClkInitStruct->SYSCLKSource); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_PLLCLK) + { + while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL) + { + if((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + else + { + if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_HSE) + { + while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_HSE) + { + if((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + else if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_MSI) + { + while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_MSI) + { + if((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + else + { + while(__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_HSI) + { + if((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + } + } + + /*-------------------------- HCLK Configuration --------------------------*/ + if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_HCLK) == RCC_CLOCKTYPE_HCLK) + { + assert_param(IS_RCC_HCLK(RCC_ClkInitStruct->AHBCLKDivider)); + MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_ClkInitStruct->AHBCLKDivider); + } +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + else + { + /* Is intermediate HCLK prescaler 2 applied internally, complete with HCLK prescaler 1 */ + if(hpre == RCC_SYSCLK_DIV2) + { + MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_SYSCLK_DIV1); + } + } +#endif + + /* Decreasing the number of wait states because of lower CPU frequency */ + if(FLatency < READ_BIT(FLASH->ACR, FLASH_ACR_LATENCY)) + { + /* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */ + __HAL_FLASH_SET_LATENCY(FLatency); + + /* Check that the new number of wait states is taken into account to access the Flash + memory by reading the FLASH_ACR register */ + if(READ_BIT(FLASH->ACR, FLASH_ACR_LATENCY) != FLatency) + { + return HAL_ERROR; + } + } + + /*-------------------------- PCLK1 Configuration ---------------------------*/ + if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK1) == RCC_CLOCKTYPE_PCLK1) + { + assert_param(IS_RCC_PCLK(RCC_ClkInitStruct->APB1CLKDivider)); + MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE1, RCC_ClkInitStruct->APB1CLKDivider); + } + + /*-------------------------- PCLK2 Configuration ---------------------------*/ + if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK2) == RCC_CLOCKTYPE_PCLK2) + { + assert_param(IS_RCC_PCLK(RCC_ClkInitStruct->APB2CLKDivider)); + MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE2, ((RCC_ClkInitStruct->APB2CLKDivider) << 3U)); + } + + /* Update the SystemCoreClock global variable */ + SystemCoreClock = HAL_RCC_GetSysClockFreq() >> AHBPrescTable[READ_BIT(RCC->CFGR, RCC_CFGR_HPRE) >> RCC_CFGR_HPRE_Pos]; + + /* Configure the source of time base considering new system clocks settings*/ + HAL_InitTick (TICK_INT_PRIORITY); + + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup RCC_Exported_Functions_Group2 Peripheral Control functions + * @brief RCC clocks control functions + * +@verbatim + =============================================================================== + ##### Peripheral Control functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to: + + (+) Ouput clock to MCO pin. + (+) Retrieve current clock frequencies. + (+) Enable the Clock Security System. + +@endverbatim + * @{ + */ + +/** + * @brief Select the clock source to output on MCO pin(PA8). + * @note PA8 should be configured in alternate function mode. + * @param RCC_MCOx specifies the output direction for the clock source. + * For STM32L4xx family this parameter can have only one value: + * @arg @ref RCC_MCO1 Clock source to output on MCO1 pin(PA8). + * @param RCC_MCOSource specifies the clock source to output. + * This parameter can be one of the following values: + * @arg @ref RCC_MCO1SOURCE_NOCLOCK MCO output disabled, no clock on MCO + * @arg @ref RCC_MCO1SOURCE_SYSCLK system clock selected as MCO source + * @arg @ref RCC_MCO1SOURCE_MSI MSI clock selected as MCO source + * @arg @ref RCC_MCO1SOURCE_HSI HSI clock selected as MCO source + * @arg @ref RCC_MCO1SOURCE_HSE HSE clock selected as MCO sourcee + * @arg @ref RCC_MCO1SOURCE_PLLCLK main PLL clock selected as MCO source + * @arg @ref RCC_MCO1SOURCE_LSI LSI clock selected as MCO source + * @arg @ref RCC_MCO1SOURCE_LSE LSE clock selected as MCO source + @if STM32L443xx + * @arg @ref RCC_MCO1SOURCE_HSI48 HSI48 clock selected as MCO source for devices with HSI48 + @endif + * @param RCC_MCODiv specifies the MCO prescaler. + * This parameter can be one of the following values: + * @arg @ref RCC_MCODIV_1 no division applied to MCO clock + * @arg @ref RCC_MCODIV_2 division by 2 applied to MCO clock + * @arg @ref RCC_MCODIV_4 division by 4 applied to MCO clock + * @arg @ref RCC_MCODIV_8 division by 8 applied to MCO clock + * @arg @ref RCC_MCODIV_16 division by 16 applied to MCO clock + * @retval None + */ +void HAL_RCC_MCOConfig( uint32_t RCC_MCOx, uint32_t RCC_MCOSource, uint32_t RCC_MCODiv) +{ + GPIO_InitTypeDef GPIO_InitStruct; + /* Check the parameters */ + assert_param(IS_RCC_MCO(RCC_MCOx)); + assert_param(IS_RCC_MCODIV(RCC_MCODiv)); + assert_param(IS_RCC_MCO1SOURCE(RCC_MCOSource)); + + /* MCO Clock Enable */ + __MCO1_CLK_ENABLE(); + + /* Configue the MCO1 pin in alternate function mode */ + GPIO_InitStruct.Pin = MCO1_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Alternate = GPIO_AF0_MCO; + HAL_GPIO_Init(MCO1_GPIO_PORT, &GPIO_InitStruct); + + /* Mask MCOSEL[] and MCOPRE[] bits then set MCO1 clock source and prescaler */ + MODIFY_REG(RCC->CFGR, (RCC_CFGR_MCOSEL | RCC_CFGR_MCOPRE), (RCC_MCOSource | RCC_MCODiv )); +} + +/** + * @brief Return the SYSCLK frequency. + * + * @note The system frequency computed by this function is not the real + * frequency in the chip. It is calculated based on the predefined + * constant and the selected clock source: + * @note If SYSCLK source is MSI, function returns values based on MSI + * Value as defined by the MSI range. + * @note If SYSCLK source is HSI, function returns values based on HSI_VALUE(*) + * @note If SYSCLK source is HSE, function returns values based on HSE_VALUE(**) + * @note If SYSCLK source is PLL, function returns values based on HSE_VALUE(**), + * HSI_VALUE(*) or MSI Value multiplied/divided by the PLL factors. + * @note (*) HSI_VALUE is a constant defined in stm32l4xx_hal_conf.h file (default value + * 16 MHz) but the real value may vary depending on the variations + * in voltage and temperature. + * @note (**) HSE_VALUE is a constant defined in stm32l4xx_hal_conf.h file (default value + * 8 MHz), user has to ensure that HSE_VALUE is same as the real + * frequency of the crystal used. Otherwise, this function may + * have wrong result. + * + * @note The result of this function could be not correct when using fractional + * value for HSE crystal. + * + * @note This function can be used by the user application to compute the + * baudrate for the communication peripherals or configure other parameters. + * + * @note Each time SYSCLK changes, this function must be called to update the + * right SYSCLK value. Otherwise, any configuration based on this function will be incorrect. + * + * + * @retval SYSCLK frequency + */ +uint32_t HAL_RCC_GetSysClockFreq(void) +{ + uint32_t msirange = 0U, pllvco = 0U, pllsource = 0U, pllr = 2U, pllm = 2U; + uint32_t sysclockfreq = 0U; + + if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_MSI) || + ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && (__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_MSI))) + { + /* MSI or PLL with MSI source used as system clock source */ + + /* Get SYSCLK source */ + if(READ_BIT(RCC->CR, RCC_CR_MSIRGSEL) == RESET) + { /* MSISRANGE from RCC_CSR applies */ + msirange = READ_BIT(RCC->CSR, RCC_CSR_MSISRANGE) >> RCC_CSR_MSISRANGE_Pos; + } + else + { /* MSIRANGE from RCC_CR applies */ + msirange = READ_BIT(RCC->CR, RCC_CR_MSIRANGE) >> RCC_CR_MSIRANGE_Pos; + } + /*MSI frequency range in HZ*/ + msirange = MSIRangeTable[msirange]; + + if(__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_MSI) + { + /* MSI used as system clock source */ + sysclockfreq = msirange; + } + } + else if(__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSI) + { + /* HSI used as system clock source */ + sysclockfreq = HSI_VALUE; + } + else if(__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSE) + { + /* HSE used as system clock source */ + sysclockfreq = HSE_VALUE; + } + + if(__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) + { + /* PLL used as system clock source */ + + /* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLN + SYSCLK = PLL_VCO / PLLR + */ + pllsource = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC); + pllm = (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U ; + + switch (pllsource) + { + case RCC_PLLSOURCE_HSI: /* HSI used as PLL clock source */ + pllvco = (HSI_VALUE / pllm) * (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos); + break; + + case RCC_PLLSOURCE_HSE: /* HSE used as PLL clock source */ + pllvco = (HSE_VALUE / pllm) * (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos); + break; + + case RCC_PLLSOURCE_MSI: /* MSI used as PLL clock source */ + default: + pllvco = (msirange / pllm) * (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos); + break; + } + pllr = ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLR) >> RCC_PLLCFGR_PLLR_Pos) + 1U ) * 2U; + sysclockfreq = pllvco/pllr; + } + + return sysclockfreq; +} + +/** + * @brief Return the HCLK frequency. + * @note Each time HCLK changes, this function must be called to update the + * right HCLK value. Otherwise, any configuration based on this function will be incorrect. + * + * @note The SystemCoreClock CMSIS variable is used to store System Clock Frequency. + * @retval HCLK frequency in Hz + */ +uint32_t HAL_RCC_GetHCLKFreq(void) +{ + return SystemCoreClock; +} + +/** + * @brief Return the PCLK1 frequency. + * @note Each time PCLK1 changes, this function must be called to update the + * right PCLK1 value. Otherwise, any configuration based on this function will be incorrect. + * @retval PCLK1 frequency in Hz + */ +uint32_t HAL_RCC_GetPCLK1Freq(void) +{ + /* Get HCLK source and Compute PCLK1 frequency ---------------------------*/ + return (HAL_RCC_GetHCLKFreq() >> APBPrescTable[READ_BIT(RCC->CFGR, RCC_CFGR_PPRE1) >> RCC_CFGR_PPRE1_Pos]); +} + +/** + * @brief Return the PCLK2 frequency. + * @note Each time PCLK2 changes, this function must be called to update the + * right PCLK2 value. Otherwise, any configuration based on this function will be incorrect. + * @retval PCLK2 frequency in Hz + */ +uint32_t HAL_RCC_GetPCLK2Freq(void) +{ + /* Get HCLK source and Compute PCLK2 frequency ---------------------------*/ + return (HAL_RCC_GetHCLKFreq()>> APBPrescTable[READ_BIT(RCC->CFGR, RCC_CFGR_PPRE2) >> RCC_CFGR_PPRE2_Pos]); +} + +/** + * @brief Configure the RCC_OscInitStruct according to the internal + * RCC configuration registers. + * @param RCC_OscInitStruct pointer to an RCC_OscInitTypeDef structure that + * will be configured. + * @retval None + */ +void HAL_RCC_GetOscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) +{ + /* Check the parameters */ + assert_param(RCC_OscInitStruct != NULL); + + /* Set all possible values for the Oscillator type parameter ---------------*/ +#if defined(RCC_HSI48_SUPPORT) + RCC_OscInitStruct->OscillatorType = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_MSI | \ + RCC_OSCILLATORTYPE_LSE | RCC_OSCILLATORTYPE_LSI | RCC_OSCILLATORTYPE_HSI48; +#else + RCC_OscInitStruct->OscillatorType = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_MSI | \ + RCC_OSCILLATORTYPE_LSE | RCC_OSCILLATORTYPE_LSI; +#endif /* RCC_HSI48_SUPPORT */ + + /* Get the HSE configuration -----------------------------------------------*/ + if(READ_BIT(RCC->CR, RCC_CR_HSEBYP) == RCC_CR_HSEBYP) + { + RCC_OscInitStruct->HSEState = RCC_HSE_BYPASS; + } + else if(READ_BIT(RCC->CR, RCC_CR_HSEON) == RCC_CR_HSEON) + { + RCC_OscInitStruct->HSEState = RCC_HSE_ON; + } + else + { + RCC_OscInitStruct->HSEState = RCC_HSE_OFF; + } + + /* Get the MSI configuration -----------------------------------------------*/ + if(READ_BIT(RCC->CR, RCC_CR_MSION) == RCC_CR_MSION) + { + RCC_OscInitStruct->MSIState = RCC_MSI_ON; + } + else + { + RCC_OscInitStruct->MSIState = RCC_MSI_OFF; + } + + RCC_OscInitStruct->MSICalibrationValue = READ_BIT(RCC->ICSCR, RCC_ICSCR_MSITRIM) >> RCC_ICSCR_MSITRIM_Pos; + RCC_OscInitStruct->MSIClockRange = READ_BIT(RCC->CR, RCC_CR_MSIRANGE); + + /* Get the HSI configuration -----------------------------------------------*/ + if(READ_BIT(RCC->CR, RCC_CR_HSION) == RCC_CR_HSION) + { + RCC_OscInitStruct->HSIState = RCC_HSI_ON; + } + else + { + RCC_OscInitStruct->HSIState = RCC_HSI_OFF; + } + + RCC_OscInitStruct->HSICalibrationValue = READ_BIT(RCC->ICSCR, RCC_ICSCR_HSITRIM) >> RCC_ICSCR_HSITRIM_Pos; + + /* Get the LSE configuration -----------------------------------------------*/ + if(READ_BIT(RCC->BDCR, RCC_BDCR_LSEBYP) == RCC_BDCR_LSEBYP) + { + RCC_OscInitStruct->LSEState = RCC_LSE_BYPASS; + } + else if(READ_BIT(RCC->BDCR, RCC_BDCR_LSEON) == RCC_BDCR_LSEON) + { + RCC_OscInitStruct->LSEState = RCC_LSE_ON; + } + else + { + RCC_OscInitStruct->LSEState = RCC_LSE_OFF; + } + + /* Get the LSI configuration -----------------------------------------------*/ + if(READ_BIT(RCC->CSR, RCC_CSR_LSION) == RCC_CSR_LSION) + { + RCC_OscInitStruct->LSIState = RCC_LSI_ON; + } + else + { + RCC_OscInitStruct->LSIState = RCC_LSI_OFF; + } + +#if defined(RCC_HSI48_SUPPORT) + /* Get the HSI48 configuration ---------------------------------------------*/ + if(READ_BIT(RCC->CRRCR, RCC_CRRCR_HSI48ON) == RCC_CRRCR_HSI48ON) + { + RCC_OscInitStruct->HSI48State = RCC_HSI48_ON; + } + else + { + RCC_OscInitStruct->HSI48State = RCC_HSI48_OFF; + } +#else + RCC_OscInitStruct->HSI48State = RCC_HSI48_OFF; +#endif /* RCC_HSI48_SUPPORT */ + + /* Get the PLL configuration -----------------------------------------------*/ + if(READ_BIT(RCC->CR, RCC_CR_PLLON) == RCC_CR_PLLON) + { + RCC_OscInitStruct->PLL.PLLState = RCC_PLL_ON; + } + else + { + RCC_OscInitStruct->PLL.PLLState = RCC_PLL_OFF; + } + RCC_OscInitStruct->PLL.PLLSource = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC); + RCC_OscInitStruct->PLL.PLLM = (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U; + RCC_OscInitStruct->PLL.PLLN = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos; + RCC_OscInitStruct->PLL.PLLQ = (((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLQ) >> RCC_PLLCFGR_PLLQ_Pos) + 1U) << 1U); + RCC_OscInitStruct->PLL.PLLR = (((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLR) >> RCC_PLLCFGR_PLLR_Pos) + 1U) << 1U); +#if defined(RCC_PLLP_DIV_2_31_SUPPORT) + RCC_OscInitStruct->PLL.PLLP = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLPDIV) >> RCC_PLLCFGR_PLLPDIV_Pos; +#else + if(READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLP) != RESET) + { + RCC_OscInitStruct->PLL.PLLP = RCC_PLLP_DIV17; + } + else + { + RCC_OscInitStruct->PLL.PLLP = RCC_PLLP_DIV7; + } +#endif /* RCC_PLLP_DIV_2_31_SUPPORT */ +} + +/** + * @brief Configure the RCC_ClkInitStruct according to the internal + * RCC configuration registers. + * @param RCC_ClkInitStruct pointer to an RCC_ClkInitTypeDef structure that + * will be configured. + * @param pFLatency Pointer on the Flash Latency. + * @retval None + */ +void HAL_RCC_GetClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, uint32_t *pFLatency) +{ + /* Check the parameters */ + assert_param(RCC_ClkInitStruct != NULL); + assert_param(pFLatency != NULL); + + /* Set all possible values for the Clock type parameter --------------------*/ + RCC_ClkInitStruct->ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; + + /* Get the SYSCLK configuration --------------------------------------------*/ + RCC_ClkInitStruct->SYSCLKSource = READ_BIT(RCC->CFGR, RCC_CFGR_SW); + + /* Get the HCLK configuration ----------------------------------------------*/ + RCC_ClkInitStruct->AHBCLKDivider = READ_BIT(RCC->CFGR, RCC_CFGR_HPRE); + + /* Get the APB1 configuration ----------------------------------------------*/ + RCC_ClkInitStruct->APB1CLKDivider = READ_BIT(RCC->CFGR, RCC_CFGR_PPRE1); + + /* Get the APB2 configuration ----------------------------------------------*/ + RCC_ClkInitStruct->APB2CLKDivider = (READ_BIT(RCC->CFGR, RCC_CFGR_PPRE2) >> 3U); + + /* Get the Flash Wait State (Latency) configuration ------------------------*/ + *pFLatency = READ_BIT(FLASH->ACR, FLASH_ACR_LATENCY); +} + +/** + * @brief Enable the Clock Security System. + * @note If a failure is detected on the HSE oscillator clock, this oscillator + * is automatically disabled and an interrupt is generated to inform the + * software about the failure (Clock Security System Interrupt, CSSI), + * allowing the MCU to perform rescue operations. The CSSI is linked to + * the Cortex-M4 NMI (Non-Maskable Interrupt) exception vector. + * @note The Clock Security System can only be cleared by reset. + * @retval None + */ +void HAL_RCC_EnableCSS(void) +{ + SET_BIT(RCC->CR, RCC_CR_CSSON) ; +} + +/** + * @brief Handle the RCC Clock Security System interrupt request. + * @note This API should be called under the NMI_Handler(). + * @retval None + */ +void HAL_RCC_NMI_IRQHandler(void) +{ + /* Check RCC CSSF interrupt flag */ + if(__HAL_RCC_GET_IT(RCC_IT_CSS)) + { + /* RCC Clock Security System interrupt user callback */ + HAL_RCC_CSSCallback(); + + /* Clear RCC CSS pending bit */ + __HAL_RCC_CLEAR_IT(RCC_IT_CSS); + } +} + +/** + * @brief RCC Clock Security System interrupt callback. + * @retval none + */ +__weak void HAL_RCC_CSSCallback(void) +{ + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_RCC_CSSCallback should be implemented in the user file + */ +} + +/** + * @} + */ + +/** + * @} + */ + +/* Private function prototypes -----------------------------------------------*/ +/** @addtogroup RCC_Private_Functions + * @{ + */ +/** + * @brief Update number of Flash wait states in line with MSI range and current + voltage range. + * @param msirange MSI range value from RCC_MSIRANGE_0 to RCC_MSIRANGE_11 + * @retval HAL status + */ +static HAL_StatusTypeDef RCC_SetFlashLatencyFromMSIRange(uint32_t msirange) +{ + uint32_t vos = 0; + uint32_t latency = FLASH_LATENCY_0; /* default value 0WS */ + + if(__HAL_RCC_PWR_IS_CLK_ENABLED()) + { + vos = HAL_PWREx_GetVoltageRange(); + } + else + { + __HAL_RCC_PWR_CLK_ENABLE(); + vos = HAL_PWREx_GetVoltageRange(); + __HAL_RCC_PWR_CLK_DISABLE(); + } + + if(vos == PWR_REGULATOR_VOLTAGE_SCALE1) + { + if(msirange > RCC_MSIRANGE_8) + { + /* MSI > 16Mhz */ + if(msirange > RCC_MSIRANGE_10) + { + /* MSI 48Mhz */ + latency = FLASH_LATENCY_2; /* 2WS */ + } + else + { + /* MSI 24Mhz or 32Mhz */ + latency = FLASH_LATENCY_1; /* 1WS */ + } + } + /* else MSI <= 16Mhz default FLASH_LATENCY_0 0WS */ + } + else + { +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + if(msirange >= RCC_MSIRANGE_8) + { + /* MSI >= 16Mhz */ + latency = FLASH_LATENCY_2; /* 2WS */ + } + else + { + if(msirange == RCC_MSIRANGE_7) + { + /* MSI 8Mhz */ + latency = FLASH_LATENCY_1; /* 1WS */ + } + /* else MSI < 8Mhz default FLASH_LATENCY_0 0WS */ + } +#else + if(msirange > RCC_MSIRANGE_8) + { + /* MSI > 16Mhz */ + latency = FLASH_LATENCY_3; /* 3WS */ + } + else + { + if(msirange == RCC_MSIRANGE_8) + { + /* MSI 16Mhz */ + latency = FLASH_LATENCY_2; /* 2WS */ + } + else if(msirange == RCC_MSIRANGE_7) + { + /* MSI 8Mhz */ + latency = FLASH_LATENCY_1; /* 1WS */ + } + /* else MSI < 8Mhz default FLASH_LATENCY_0 0WS */ + } +#endif + } + + __HAL_FLASH_SET_LATENCY(latency); + + /* Check that the new number of wait states is taken into account to access the Flash + memory by reading the FLASH_ACR register */ + if(READ_BIT(FLASH->ACR, FLASH_ACR_LATENCY) != latency) + { + return HAL_ERROR; + } + + return HAL_OK; +} + +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +/** + * @brief Compute SYSCLK frequency based on PLL SYSCLK source. + * @retval SYSCLK frequency + */ +static uint32_t RCC_GetSysClockFreqFromPLLSource(void) +{ + uint32_t msirange = 0U, pllvco = 0U, pllsource = 0U, pllr = 2U, pllm = 2U; + uint32_t sysclockfreq = 0U; + + if(__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_MSI) + { + /* Get MSI range source */ + if(READ_BIT(RCC->CR, RCC_CR_MSIRGSEL) == RESET) + { /* MSISRANGE from RCC_CSR applies */ + msirange = READ_BIT(RCC->CSR, RCC_CSR_MSISRANGE) >> RCC_CSR_MSISRANGE_Pos; + } + else + { /* MSIRANGE from RCC_CR applies */ + msirange = READ_BIT(RCC->CR, RCC_CR_MSIRANGE) >> RCC_CR_MSIRANGE_Pos; + } + /*MSI frequency range in HZ*/ + msirange = MSIRangeTable[msirange]; + } + + /* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLN + SYSCLK = PLL_VCO / PLLR + */ + pllsource = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC); + pllm = (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U ; + + switch (pllsource) + { + case RCC_PLLSOURCE_HSI: /* HSI used as PLL clock source */ + pllvco = (HSI_VALUE / pllm) * (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos); + break; + + case RCC_PLLSOURCE_HSE: /* HSE used as PLL clock source */ + pllvco = (HSE_VALUE / pllm) * (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos); + break; + + case RCC_PLLSOURCE_MSI: /* MSI used as PLL clock source */ + default: + pllvco = (msirange / pllm) * (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos); + break; + } + + pllr = ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLR) >> RCC_PLLCFGR_PLLR_Pos) + 1U ) * 2U; + sysclockfreq = pllvco/pllr; + + return sysclockfreq; +} +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +/** + * @} + */ + +#endif /* HAL_RCC_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rcc_ex.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rcc_ex.c new file mode 100644 index 0000000..7c31e73 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rcc_ex.c @@ -0,0 +1,3358 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_rcc_ex.c + * @author MCD Application Team + * @brief Extended RCC HAL module driver. + * This file provides firmware functions to manage the following + * functionalities RCC extended peripheral: + * + Extended Peripheral Control functions + * + Extended Clock management functions + * + Extended Clock Recovery System Control functions + * + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup RCCEx RCCEx + * @brief RCC Extended HAL module driver + * @{ + */ + +#ifdef HAL_RCC_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private defines -----------------------------------------------------------*/ +/** @defgroup RCCEx_Private_Constants RCCEx Private Constants + * @{ + */ +#define PLLSAI1_TIMEOUT_VALUE 2U /* 2 ms (minimum Tick + 1) */ +#define PLLSAI2_TIMEOUT_VALUE 2U /* 2 ms (minimum Tick + 1) */ +#define PLL_TIMEOUT_VALUE 2U /* 2 ms (minimum Tick + 1) */ + +#define DIVIDER_P_UPDATE 0U +#define DIVIDER_Q_UPDATE 1U +#define DIVIDER_R_UPDATE 2U + +#define __LSCO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE() +#define LSCO_GPIO_PORT GPIOA +#define LSCO_PIN GPIO_PIN_2 +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/** @defgroup RCCEx_Private_Functions RCCEx Private Functions + * @{ + */ +static HAL_StatusTypeDef RCCEx_PLLSAI1_Config(RCC_PLLSAI1InitTypeDef *PllSai1, uint32_t Divider); + +#if defined(RCC_PLLSAI2_SUPPORT) + +static HAL_StatusTypeDef RCCEx_PLLSAI2_Config(RCC_PLLSAI2InitTypeDef *PllSai2, uint32_t Divider); + +#endif /* RCC_PLLSAI2_SUPPORT */ + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup RCCEx_Exported_Functions RCCEx Exported Functions + * @{ + */ + +/** @defgroup RCCEx_Exported_Functions_Group1 Extended Peripheral Control functions + * @brief Extended Peripheral Control functions + * +@verbatim + =============================================================================== + ##### Extended Peripheral Control functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to control the RCC Clocks + frequencies. + [..] + (@) Important note: Care must be taken when HAL_RCCEx_PeriphCLKConfig() is used to + select the RTC clock source; in this case the Backup domain will be reset in + order to modify the RTC Clock source, as consequence RTC registers (including + the backup registers) are set to their reset values. + +@endverbatim + * @{ + */ +/** + * @brief Initialize the RCC extended peripherals clocks according to the specified + * parameters in the RCC_PeriphCLKInitTypeDef. + * @param PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that + * contains a field PeriphClockSelection which can be a combination of the following values: + * @arg @ref RCC_PERIPHCLK_RTC RTC peripheral clock + * @arg @ref RCC_PERIPHCLK_ADC ADC peripheral clock + @if STM32L462xx + * @arg @ref RCC_PERIPHCLK_DFSDM1 DFSDM1 peripheral clock (only for devices with DFSDM1) + @endif + @if STM32L486xx + * @arg @ref RCC_PERIPHCLK_DFSDM1 DFSDM1 peripheral clock (only for devices with DFSDM1) + @endif + @if STM32L4A6xx + * @arg @ref RCC_PERIPHCLK_DFSDM1 DFSDM1 peripheral clock (only for devices with DFSDM1) + @endif + * @arg @ref RCC_PERIPHCLK_I2C1 I2C1 peripheral clock + * @arg @ref RCC_PERIPHCLK_I2C2 I2C2 peripheral clock + * @arg @ref RCC_PERIPHCLK_I2C3 I2C3 peripheral clock + @if STM32L462xx + * @arg @ref RCC_PERIPHCLK_I2C4 I2C4 peripheral clock (only for devices with I2C4) + @endif + @if STM32L4A6xx + * @arg @ref RCC_PERIPHCLK_I2C4 I2C4 peripheral clock (only for devices with I2C4) + @endif + @if STM32L4S9xx + * @arg @ref RCC_PERIPHCLK_I2C4 I2C4 peripheral clock (only for devices with I2C4) + @endif + * @arg @ref RCC_PERIPHCLK_LPTIM1 LPTIM1 peripheral clock + * @arg @ref RCC_PERIPHCLK_LPTIM2 LPTIM2 peripheral clock + * @arg @ref RCC_PERIPHCLK_LPUART1 LPUART1 peripheral clock + * @arg @ref RCC_PERIPHCLK_RNG RNG peripheral clock + * @arg @ref RCC_PERIPHCLK_SAI1 SAI1 peripheral clock + @if STM32L486xx + * @arg @ref RCC_PERIPHCLK_SAI2 SAI2 peripheral clock (only for devices with SAI2) + @endif + @if STM32L4A6xx + * @arg @ref RCC_PERIPHCLK_SAI2 SAI2 peripheral clock (only for devices with SAI2) + @endif + @if STM32L4S9xx + * @arg @ref RCC_PERIPHCLK_SAI2 SAI2 peripheral clock (only for devices with SAI2) + @endif + * @arg @ref RCC_PERIPHCLK_SDMMC1 SDMMC1 peripheral clock + @if STM32L443xx + * @arg @ref RCC_PERIPHCLK_SWPMI1 SWPMI1 peripheral clock (only for devices with SWPMI1) + @endif + @if STM32L486xx + * @arg @ref RCC_PERIPHCLK_SWPMI1 SWPMI1 peripheral clock (only for devices with SWPMI1) + @endif + @if STM32L4A6xx + * @arg @ref RCC_PERIPHCLK_SWPMI1 SWPMI1 peripheral clock (only for devices with SWPMI1) + @endif + * @arg @ref RCC_PERIPHCLK_USART1 USART1 peripheral clock + * @arg @ref RCC_PERIPHCLK_USART2 USART1 peripheral clock + * @arg @ref RCC_PERIPHCLK_USART3 USART1 peripheral clock + @if STM32L462xx + * @arg @ref RCC_PERIPHCLK_UART4 USART1 peripheral clock (only for devices with UART4) + @endif + @if STM32L486xx + * @arg @ref RCC_PERIPHCLK_UART4 USART1 peripheral clock (only for devices with UART4) + * @arg @ref RCC_PERIPHCLK_UART5 USART1 peripheral clock (only for devices with UART5) + * @arg @ref RCC_PERIPHCLK_USB USB peripheral clock (only for devices with USB) + @endif + @if STM32L4A6xx + * @arg @ref RCC_PERIPHCLK_UART4 USART1 peripheral clock (only for devices with UART4) + * @arg @ref RCC_PERIPHCLK_UART5 USART1 peripheral clock (only for devices with UART5) + * @arg @ref RCC_PERIPHCLK_USB USB peripheral clock (only for devices with USB) + @endif + @if STM32L4S9xx + * @arg @ref RCC_PERIPHCLK_UART4 USART1 peripheral clock (only for devices with UART4) + * @arg @ref RCC_PERIPHCLK_UART5 USART1 peripheral clock (only for devices with UART5) + * @arg @ref RCC_PERIPHCLK_USB USB peripheral clock (only for devices with USB) + * @arg @ref RCC_PERIPHCLK_DFSDM1 DFSDM1 peripheral kernel clock (only for devices with DFSDM1) + * @arg @ref RCC_PERIPHCLK_DFSDM1AUDIO DFSDM1 peripheral audio clock (only for devices with DFSDM1) + * @arg @ref RCC_PERIPHCLK_LTDC LTDC peripheral clock (only for devices with LTDC) + * @arg @ref RCC_PERIPHCLK_DSI DSI peripheral clock (only for devices with DSI) + * @arg @ref RCC_PERIPHCLK_OSPI OctoSPI peripheral clock (only for devices with OctoSPI) + @endif + * + * @note Care must be taken when HAL_RCCEx_PeriphCLKConfig() is used to select + * the RTC clock source: in this case the access to Backup domain is enabled. + * + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit) +{ + uint32_t tmpregister = 0; + uint32_t tickstart = 0U; + HAL_StatusTypeDef ret = HAL_OK; /* Intermediate status */ + HAL_StatusTypeDef status = HAL_OK; /* Final status */ + + /* Check the parameters */ + assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection)); + + /*-------------------------- SAI1 clock source configuration ---------------------*/ + if((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1)) + { + /* Check the parameters */ + assert_param(IS_RCC_SAI1CLK(PeriphClkInit->Sai1ClockSelection)); + + switch(PeriphClkInit->Sai1ClockSelection) + { + case RCC_SAI1CLKSOURCE_PLL: /* PLL is used as clock source for SAI1*/ + /* Enable SAI Clock output generated form System PLL . */ +#if defined(RCC_PLLSAI2_SUPPORT) + __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_SAI3CLK); +#else + __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_SAI2CLK); +#endif /* RCC_PLLSAI2_SUPPORT */ + /* SAI1 clock source config set later after clock selection check */ + break; + + case RCC_SAI1CLKSOURCE_PLLSAI1: /* PLLSAI1 is used as clock source for SAI1*/ + /* PLLSAI1 input clock, parameters M, N & P configuration and clock output (PLLSAI1ClockOut) */ + ret = RCCEx_PLLSAI1_Config(&(PeriphClkInit->PLLSAI1), DIVIDER_P_UPDATE); + /* SAI1 clock source config set later after clock selection check */ + break; + +#if defined(RCC_PLLSAI2_SUPPORT) + + case RCC_SAI1CLKSOURCE_PLLSAI2: /* PLLSAI2 is used as clock source for SAI1*/ + /* PLLSAI2 input clock, parameters M, N & P configuration clock output (PLLSAI2ClockOut) */ + ret = RCCEx_PLLSAI2_Config(&(PeriphClkInit->PLLSAI2), DIVIDER_P_UPDATE); + /* SAI1 clock source config set later after clock selection check */ + break; + +#endif /* RCC_PLLSAI2_SUPPORT */ + + case RCC_SAI1CLKSOURCE_PIN: /* External clock is used as source of SAI1 clock*/ +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + case RCC_SAI1CLKSOURCE_HSI: /* HSI is used as source of SAI1 clock*/ +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + /* SAI1 clock source config set later after clock selection check */ + break; + + default: + ret = HAL_ERROR; + break; + } + + if(ret == HAL_OK) + { + /* Set the source of SAI1 clock*/ + __HAL_RCC_SAI1_CONFIG(PeriphClkInit->Sai1ClockSelection); + } + else + { + /* set overall return value */ + status = ret; + } + } + +#if defined(SAI2) + + /*-------------------------- SAI2 clock source configuration ---------------------*/ + if((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI2) == RCC_PERIPHCLK_SAI2)) + { + /* Check the parameters */ + assert_param(IS_RCC_SAI2CLK(PeriphClkInit->Sai2ClockSelection)); + + switch(PeriphClkInit->Sai2ClockSelection) + { + case RCC_SAI2CLKSOURCE_PLL: /* PLL is used as clock source for SAI2*/ + /* Enable SAI Clock output generated form System PLL . */ + __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_SAI3CLK); + /* SAI2 clock source config set later after clock selection check */ + break; + + case RCC_SAI2CLKSOURCE_PLLSAI1: /* PLLSAI1 is used as clock source for SAI2*/ + /* PLLSAI1 input clock, parameters M, N & P configuration and clock output (PLLSAI1ClockOut) */ + ret = RCCEx_PLLSAI1_Config(&(PeriphClkInit->PLLSAI1), DIVIDER_P_UPDATE); + /* SAI2 clock source config set later after clock selection check */ + break; + + case RCC_SAI2CLKSOURCE_PLLSAI2: /* PLLSAI2 is used as clock source for SAI2*/ + /* PLLSAI2 input clock, parameters M, N & P configuration and clock output (PLLSAI2ClockOut) */ + ret = RCCEx_PLLSAI2_Config(&(PeriphClkInit->PLLSAI2), DIVIDER_P_UPDATE); + /* SAI2 clock source config set later after clock selection check */ + break; + + case RCC_SAI2CLKSOURCE_PIN: /* External clock is used as source of SAI2 clock*/ +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + case RCC_SAI2CLKSOURCE_HSI: /* HSI is used as source of SAI2 clock*/ +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + /* SAI2 clock source config set later after clock selection check */ + break; + + default: + ret = HAL_ERROR; + break; + } + + if(ret == HAL_OK) + { + /* Set the source of SAI2 clock*/ + __HAL_RCC_SAI2_CONFIG(PeriphClkInit->Sai2ClockSelection); + } + else + { + /* set overall return value */ + status = ret; + } + } +#endif /* SAI2 */ + + /*-------------------------- RTC clock source configuration ----------------------*/ + if((PeriphClkInit->PeriphClockSelection & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC) + { + FlagStatus pwrclkchanged = RESET; + + /* Check for RTC Parameters used to output RTCCLK */ + assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection)); + + /* Enable Power Clock */ + if(__HAL_RCC_PWR_IS_CLK_DISABLED()) + { + __HAL_RCC_PWR_CLK_ENABLE(); + pwrclkchanged = SET; + } + + /* Enable write access to Backup domain */ + SET_BIT(PWR->CR1, PWR_CR1_DBP); + + /* Wait for Backup domain Write protection disable */ + tickstart = HAL_GetTick(); + + while(READ_BIT(PWR->CR1, PWR_CR1_DBP) == RESET) + { + if((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE) + { + ret = HAL_TIMEOUT; + break; + } + } + + if(ret == HAL_OK) + { + /* Reset the Backup domain only if the RTC Clock source selection is modified from default */ + tmpregister = READ_BIT(RCC->BDCR, RCC_BDCR_RTCSEL); + + if((tmpregister != RCC_RTCCLKSOURCE_NONE) && (tmpregister != PeriphClkInit->RTCClockSelection)) + { + /* Store the content of BDCR register before the reset of Backup Domain */ + tmpregister = READ_BIT(RCC->BDCR, ~(RCC_BDCR_RTCSEL)); + /* RTC Clock selection can be changed only if the Backup Domain is reset */ + __HAL_RCC_BACKUPRESET_FORCE(); + __HAL_RCC_BACKUPRESET_RELEASE(); + /* Restore the Content of BDCR register */ + RCC->BDCR = tmpregister; + } + + /* Wait for LSE reactivation if LSE was enable prior to Backup Domain reset */ + if (HAL_IS_BIT_SET(tmpregister, RCC_BDCR_LSEON)) + { + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till LSE is ready */ + while(READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) == RESET) + { + if((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE) + { + ret = HAL_TIMEOUT; + break; + } + } + } + + if(ret == HAL_OK) + { + /* Apply new RTC clock source selection */ + __HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection); + } + else + { + /* set overall return value */ + status = ret; + } + } + else + { + /* set overall return value */ + status = ret; + } + + /* Restore clock configuration if changed */ + if(pwrclkchanged == SET) + { + __HAL_RCC_PWR_CLK_DISABLE(); + } + } + + /*-------------------------- USART1 clock source configuration -------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_USART1) == RCC_PERIPHCLK_USART1) + { + /* Check the parameters */ + assert_param(IS_RCC_USART1CLKSOURCE(PeriphClkInit->Usart1ClockSelection)); + + /* Configure the USART1 clock source */ + __HAL_RCC_USART1_CONFIG(PeriphClkInit->Usart1ClockSelection); + } + + /*-------------------------- USART2 clock source configuration -------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_USART2) == RCC_PERIPHCLK_USART2) + { + /* Check the parameters */ + assert_param(IS_RCC_USART2CLKSOURCE(PeriphClkInit->Usart2ClockSelection)); + + /* Configure the USART2 clock source */ + __HAL_RCC_USART2_CONFIG(PeriphClkInit->Usart2ClockSelection); + } + +#if defined(USART3) + + /*-------------------------- USART3 clock source configuration -------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_USART3) == RCC_PERIPHCLK_USART3) + { + /* Check the parameters */ + assert_param(IS_RCC_USART3CLKSOURCE(PeriphClkInit->Usart3ClockSelection)); + + /* Configure the USART3 clock source */ + __HAL_RCC_USART3_CONFIG(PeriphClkInit->Usart3ClockSelection); + } + +#endif /* USART3 */ + +#if defined(UART4) + + /*-------------------------- UART4 clock source configuration --------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_UART4) == RCC_PERIPHCLK_UART4) + { + /* Check the parameters */ + assert_param(IS_RCC_UART4CLKSOURCE(PeriphClkInit->Uart4ClockSelection)); + + /* Configure the UART4 clock source */ + __HAL_RCC_UART4_CONFIG(PeriphClkInit->Uart4ClockSelection); + } + +#endif /* UART4 */ + +#if defined(UART5) + + /*-------------------------- UART5 clock source configuration --------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_UART5) == RCC_PERIPHCLK_UART5) + { + /* Check the parameters */ + assert_param(IS_RCC_UART5CLKSOURCE(PeriphClkInit->Uart5ClockSelection)); + + /* Configure the UART5 clock source */ + __HAL_RCC_UART5_CONFIG(PeriphClkInit->Uart5ClockSelection); + } + +#endif /* UART5 */ + + /*-------------------------- LPUART1 clock source configuration ------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LPUART1) == RCC_PERIPHCLK_LPUART1) + { + /* Check the parameters */ + assert_param(IS_RCC_LPUART1CLKSOURCE(PeriphClkInit->Lpuart1ClockSelection)); + + /* Configure the LPUAR1 clock source */ + __HAL_RCC_LPUART1_CONFIG(PeriphClkInit->Lpuart1ClockSelection); + } + + /*-------------------------- LPTIM1 clock source configuration -------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LPTIM1) == (RCC_PERIPHCLK_LPTIM1)) + { + assert_param(IS_RCC_LPTIM1CLK(PeriphClkInit->Lptim1ClockSelection)); + __HAL_RCC_LPTIM1_CONFIG(PeriphClkInit->Lptim1ClockSelection); + } + + /*-------------------------- LPTIM2 clock source configuration -------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LPTIM2) == (RCC_PERIPHCLK_LPTIM2)) + { + assert_param(IS_RCC_LPTIM2CLK(PeriphClkInit->Lptim2ClockSelection)); + __HAL_RCC_LPTIM2_CONFIG(PeriphClkInit->Lptim2ClockSelection); + } + + /*-------------------------- I2C1 clock source configuration ---------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2C1) == RCC_PERIPHCLK_I2C1) + { + /* Check the parameters */ + assert_param(IS_RCC_I2C1CLKSOURCE(PeriphClkInit->I2c1ClockSelection)); + + /* Configure the I2C1 clock source */ + __HAL_RCC_I2C1_CONFIG(PeriphClkInit->I2c1ClockSelection); + } + +#if defined(I2C2) + + /*-------------------------- I2C2 clock source configuration ---------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2C2) == RCC_PERIPHCLK_I2C2) + { + /* Check the parameters */ + assert_param(IS_RCC_I2C2CLKSOURCE(PeriphClkInit->I2c2ClockSelection)); + + /* Configure the I2C2 clock source */ + __HAL_RCC_I2C2_CONFIG(PeriphClkInit->I2c2ClockSelection); + } + +#endif /* I2C2 */ + + /*-------------------------- I2C3 clock source configuration ---------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2C3) == RCC_PERIPHCLK_I2C3) + { + /* Check the parameters */ + assert_param(IS_RCC_I2C3CLKSOURCE(PeriphClkInit->I2c3ClockSelection)); + + /* Configure the I2C3 clock source */ + __HAL_RCC_I2C3_CONFIG(PeriphClkInit->I2c3ClockSelection); + } + +#if defined(I2C4) + + /*-------------------------- I2C4 clock source configuration ---------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2C4) == RCC_PERIPHCLK_I2C4) + { + /* Check the parameters */ + assert_param(IS_RCC_I2C4CLKSOURCE(PeriphClkInit->I2c4ClockSelection)); + + /* Configure the I2C4 clock source */ + __HAL_RCC_I2C4_CONFIG(PeriphClkInit->I2c4ClockSelection); + } + +#endif /* I2C4 */ + +#if defined(USB_OTG_FS) || defined(USB) + + /*-------------------------- USB clock source configuration ----------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_USB) == (RCC_PERIPHCLK_USB)) + { + assert_param(IS_RCC_USBCLKSOURCE(PeriphClkInit->UsbClockSelection)); + __HAL_RCC_USB_CONFIG(PeriphClkInit->UsbClockSelection); + + if(PeriphClkInit->UsbClockSelection == RCC_USBCLKSOURCE_PLL) + { + /* Enable PLL48M1CLK output */ + __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_48M1CLK); + } + else + { + if(PeriphClkInit->UsbClockSelection == RCC_USBCLKSOURCE_PLLSAI1) + { + /* PLLSAI1 input clock, parameters M, N & Q configuration and clock output (PLLSAI1ClockOut) */ + ret = RCCEx_PLLSAI1_Config(&(PeriphClkInit->PLLSAI1), DIVIDER_Q_UPDATE); + + if(ret != HAL_OK) + { + /* set overall return value */ + status = ret; + } + } + } + } + +#endif /* USB_OTG_FS || USB */ + +#if defined(SDMMC1) + + /*-------------------------- SDMMC1 clock source configuration -------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SDMMC1) == (RCC_PERIPHCLK_SDMMC1)) + { + assert_param(IS_RCC_SDMMC1CLKSOURCE(PeriphClkInit->Sdmmc1ClockSelection)); + __HAL_RCC_SDMMC1_CONFIG(PeriphClkInit->Sdmmc1ClockSelection); + + if(PeriphClkInit->Sdmmc1ClockSelection == RCC_SDMMC1CLKSOURCE_PLL) /* PLL "Q" ? */ + { + /* Enable PLL48M1CLK output */ + __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_48M1CLK); + } +#if defined(RCC_CCIPR2_SDMMCSEL) + else if(PeriphClkInit->Sdmmc1ClockSelection == RCC_SDMMC1CLKSOURCE_PLLP) /* PLL "P" ? */ + { + /* Enable PLLSAI3CLK output */ + __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_SAI3CLK); + } +#endif + else if(PeriphClkInit->Sdmmc1ClockSelection == RCC_SDMMC1CLKSOURCE_PLLSAI1) + { + /* PLLSAI1 input clock, parameters M, N & Q configuration and clock output (PLLSAI1ClockOut) */ + ret = RCCEx_PLLSAI1_Config(&(PeriphClkInit->PLLSAI1), DIVIDER_Q_UPDATE); + + if(ret != HAL_OK) + { + /* set overall return value */ + status = ret; + } + } + } + +#endif /* SDMMC1 */ + + /*-------------------------- RNG clock source configuration ----------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RNG) == (RCC_PERIPHCLK_RNG)) + { + assert_param(IS_RCC_RNGCLKSOURCE(PeriphClkInit->RngClockSelection)); + __HAL_RCC_RNG_CONFIG(PeriphClkInit->RngClockSelection); + + if(PeriphClkInit->RngClockSelection == RCC_RNGCLKSOURCE_PLL) + { + /* Enable PLL48M1CLK output */ + __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_48M1CLK); + } + else if(PeriphClkInit->RngClockSelection == RCC_RNGCLKSOURCE_PLLSAI1) + { + /* PLLSAI1 input clock, parameters M, N & Q configuration and clock output (PLLSAI1ClockOut) */ + ret = RCCEx_PLLSAI1_Config(&(PeriphClkInit->PLLSAI1), DIVIDER_Q_UPDATE); + + if(ret != HAL_OK) + { + /* set overall return value */ + status = ret; + } + } + } + + /*-------------------------- ADC clock source configuration ----------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_ADC) == RCC_PERIPHCLK_ADC) + { + /* Check the parameters */ + assert_param(IS_RCC_ADCCLKSOURCE(PeriphClkInit->AdcClockSelection)); + + /* Configure the ADC interface clock source */ + __HAL_RCC_ADC_CONFIG(PeriphClkInit->AdcClockSelection); + + if(PeriphClkInit->AdcClockSelection == RCC_ADCCLKSOURCE_PLLSAI1) + { + /* PLLSAI1 input clock, parameters M, N & R configuration and clock output (PLLSAI1ClockOut) */ + ret = RCCEx_PLLSAI1_Config(&(PeriphClkInit->PLLSAI1), DIVIDER_R_UPDATE); + + if(ret != HAL_OK) + { + /* set overall return value */ + status = ret; + } + } + +#if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || defined(STM32L496xx) || defined(STM32L4A6xx) + + else if(PeriphClkInit->AdcClockSelection == RCC_ADCCLKSOURCE_PLLSAI2) + { + /* PLLSAI2 input clock, parameters M, N & R configuration and clock output (PLLSAI2ClockOut) */ + ret = RCCEx_PLLSAI2_Config(&(PeriphClkInit->PLLSAI2), DIVIDER_R_UPDATE); + + if(ret != HAL_OK) + { + /* set overall return value */ + status = ret; + } + } + +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || STM32L496xx || STM32L4A6xx */ + + } + +#if defined(SWPMI1) + + /*-------------------------- SWPMI1 clock source configuration -------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SWPMI1) == RCC_PERIPHCLK_SWPMI1) + { + /* Check the parameters */ + assert_param(IS_RCC_SWPMI1CLKSOURCE(PeriphClkInit->Swpmi1ClockSelection)); + + /* Configure the SWPMI1 clock source */ + __HAL_RCC_SWPMI1_CONFIG(PeriphClkInit->Swpmi1ClockSelection); + } + +#endif /* SWPMI1 */ + +#if defined(DFSDM1_Filter0) + + /*-------------------------- DFSDM1 clock source configuration -------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_DFSDM1) == RCC_PERIPHCLK_DFSDM1) + { + /* Check the parameters */ + assert_param(IS_RCC_DFSDM1CLKSOURCE(PeriphClkInit->Dfsdm1ClockSelection)); + + /* Configure the DFSDM1 interface clock source */ + __HAL_RCC_DFSDM1_CONFIG(PeriphClkInit->Dfsdm1ClockSelection); + } + +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + /*-------------------------- DFSDM1 audio clock source configuration -------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_DFSDM1AUDIO) == RCC_PERIPHCLK_DFSDM1AUDIO) + { + /* Check the parameters */ + assert_param(IS_RCC_DFSDM1AUDIOCLKSOURCE(PeriphClkInit->Dfsdm1AudioClockSelection)); + + /* Configure the DFSDM1 interface audio clock source */ + __HAL_RCC_DFSDM1AUDIO_CONFIG(PeriphClkInit->Dfsdm1AudioClockSelection); + } + +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#endif /* DFSDM1_Filter0 */ + +#if defined(LTDC) + + /*-------------------------- LTDC clock source configuration --------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LTDC) == RCC_PERIPHCLK_LTDC) + { + /* Check the parameters */ + assert_param(IS_RCC_LTDCCLKSOURCE(PeriphClkInit->LtdcClockSelection)); + + /* Disable the PLLSAI2 */ + __HAL_RCC_PLLSAI2_DISABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till PLLSAI2 is ready */ + while(READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) != RESET) + { + if((HAL_GetTick() - tickstart) > PLLSAI2_TIMEOUT_VALUE) + { + ret = HAL_TIMEOUT; + break; + } + } + + if(ret == HAL_OK) + { + /* Configure the LTDC clock source */ + __HAL_RCC_LTDC_CONFIG(PeriphClkInit->LtdcClockSelection); + + /* PLLSAI2 input clock, parameters M, N & R configuration and clock output (PLLSAI2ClockOut) */ + ret = RCCEx_PLLSAI2_Config(&(PeriphClkInit->PLLSAI2), DIVIDER_R_UPDATE); + } + + if(ret != HAL_OK) + { + /* set overall return value */ + status = ret; + } + } + +#endif /* LTDC */ + +#if defined(DSI) + + /*-------------------------- DSI clock source configuration ---------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_DSI) == RCC_PERIPHCLK_DSI) + { + /* Check the parameters */ + assert_param(IS_RCC_DSICLKSOURCE(PeriphClkInit->DsiClockSelection)); + + /* Configure the DSI clock source */ + __HAL_RCC_DSI_CONFIG(PeriphClkInit->DsiClockSelection); + + if(PeriphClkInit->DsiClockSelection == RCC_DSICLKSOURCE_PLLSAI2) + { + /* PLLSAI2 input clock, parameters M, N & Q configuration and clock output (PLLSAI2ClockOut) */ + ret = RCCEx_PLLSAI2_Config(&(PeriphClkInit->PLLSAI2), DIVIDER_Q_UPDATE); + + if(ret != HAL_OK) + { + /* set overall return value */ + status = ret; + } + } + } + +#endif /* DSI */ + +#if defined(OCTOSPI1) || defined(OCTOSPI2) + + /*-------------------------- OctoSPIx clock source configuration ----------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_OSPI) == RCC_PERIPHCLK_OSPI) + { + /* Check the parameters */ + assert_param(IS_RCC_OSPICLKSOURCE(PeriphClkInit->OspiClockSelection)); + + /* Configure the OctoSPI clock source */ + __HAL_RCC_OSPI_CONFIG(PeriphClkInit->OspiClockSelection); + + if(PeriphClkInit->OspiClockSelection == RCC_OSPICLKSOURCE_PLL) + { + /* Enable PLL48M1CLK output */ + __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_48M1CLK); + } + } + +#endif /* OCTOSPI1 || OCTOSPI2 */ + + return status; +} + +/** + * @brief Get the RCC_ClkInitStruct according to the internal RCC configuration registers. + * @param PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that + * returns the configuration information for the Extended Peripherals + * clocks(SAI1, SAI2, LPTIM1, LPTIM2, I2C1, I2C2, I2C3, I2C4, LPUART, + * USART1, USART2, USART3, UART4, UART5, RTC, ADCx, DFSDMx, SWPMI1, USB, SDMMC1 and RNG). + * @retval None + */ +void HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit) +{ + /* Set all possible values for the extended clock type parameter------------*/ + +#if defined(STM32L431xx) + + PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | \ + RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 | RCC_PERIPHCLK_I2C3 | \ + RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_SAI1 | \ + RCC_PERIPHCLK_SDMMC1 | RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_SWPMI1 | \ + RCC_PERIPHCLK_RTC ; + +#elif defined(STM32L432xx) || defined(STM32L442xx) + + PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | \ + RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C3 | \ + RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_SAI1 | RCC_PERIPHCLK_USB | \ + RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_SWPMI1 | \ + RCC_PERIPHCLK_RTC ; + +#elif defined(STM32L433xx) || defined(STM32L443xx) + + PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | \ + RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 | RCC_PERIPHCLK_I2C3 | \ + RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_SAI1 | RCC_PERIPHCLK_USB | \ + RCC_PERIPHCLK_SDMMC1 | RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_SWPMI1 | \ + RCC_PERIPHCLK_RTC ; + +#elif defined(STM32L451xx) + + PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | RCC_PERIPHCLK_UART4 | \ + RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 | RCC_PERIPHCLK_I2C3 | RCC_PERIPHCLK_I2C4 | \ + RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_SAI1 | \ + RCC_PERIPHCLK_SDMMC1 | RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_DFSDM1 | \ + RCC_PERIPHCLK_RTC ; + +#elif defined(STM32L452xx) || defined(STM32L462xx) + + PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | RCC_PERIPHCLK_UART4 | \ + RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 | RCC_PERIPHCLK_I2C3 | RCC_PERIPHCLK_I2C4 | \ + RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_SAI1 | RCC_PERIPHCLK_USB | \ + RCC_PERIPHCLK_SDMMC1 | RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_DFSDM1 | \ + RCC_PERIPHCLK_RTC ; + +#elif defined(STM32L471xx) + + PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | RCC_PERIPHCLK_UART4 | RCC_PERIPHCLK_UART5 | \ + RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 | RCC_PERIPHCLK_I2C3 | \ + RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_SAI1 | RCC_PERIPHCLK_SAI2 | \ + RCC_PERIPHCLK_SDMMC1 | RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_SWPMI1 | RCC_PERIPHCLK_DFSDM1 | \ + RCC_PERIPHCLK_RTC ; + +#elif defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) + + PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | RCC_PERIPHCLK_UART4 | RCC_PERIPHCLK_UART5 | \ + RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 | RCC_PERIPHCLK_I2C3 | \ + RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_SAI1 | RCC_PERIPHCLK_SAI2 | RCC_PERIPHCLK_USB | \ + RCC_PERIPHCLK_SDMMC1 | RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_SWPMI1 | RCC_PERIPHCLK_DFSDM1 | \ + RCC_PERIPHCLK_RTC ; + +#elif defined(STM32L496xx) || defined(STM32L4A6xx) + + PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | RCC_PERIPHCLK_UART4 | RCC_PERIPHCLK_UART5 | \ + RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 | RCC_PERIPHCLK_I2C3 | RCC_PERIPHCLK_I2C4 | \ + RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_SAI1 | RCC_PERIPHCLK_SAI2 | RCC_PERIPHCLK_USB | \ + RCC_PERIPHCLK_SDMMC1 | RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_SWPMI1 | RCC_PERIPHCLK_DFSDM1 | \ + RCC_PERIPHCLK_RTC ; + +#elif defined(STM32L4R5xx) || defined(STM32L4S5xx) + + PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | RCC_PERIPHCLK_UART4 | RCC_PERIPHCLK_UART5 | \ + RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 | RCC_PERIPHCLK_I2C3 | RCC_PERIPHCLK_I2C4 | \ + RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_SAI1 | RCC_PERIPHCLK_SAI2 | RCC_PERIPHCLK_USB | \ + RCC_PERIPHCLK_SDMMC1 | RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_DFSDM1 | \ + RCC_PERIPHCLK_DFSDM1AUDIO | RCC_PERIPHCLK_RTC | RCC_PERIPHCLK_OSPI; + +#elif defined(STM32L4R7xx) || defined(STM32L4S7xx) + + PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | RCC_PERIPHCLK_UART4 | RCC_PERIPHCLK_UART5 | \ + RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 | RCC_PERIPHCLK_I2C3 | RCC_PERIPHCLK_I2C4 | \ + RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_SAI1 | RCC_PERIPHCLK_SAI2 | RCC_PERIPHCLK_USB | \ + RCC_PERIPHCLK_SDMMC1 | RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_DFSDM1 | \ + RCC_PERIPHCLK_DFSDM1AUDIO | RCC_PERIPHCLK_RTC | RCC_PERIPHCLK_OSPI | RCC_PERIPHCLK_LTDC; + +#elif defined(STM32L4R9xx) || defined(STM32L4S9xx) + + PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | RCC_PERIPHCLK_UART4 | RCC_PERIPHCLK_UART5 | \ + RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 | RCC_PERIPHCLK_I2C3 | RCC_PERIPHCLK_I2C4 | \ + RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_SAI1 | RCC_PERIPHCLK_SAI2 | RCC_PERIPHCLK_USB | \ + RCC_PERIPHCLK_SDMMC1 | RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_DFSDM1 | \ + RCC_PERIPHCLK_DFSDM1AUDIO | RCC_PERIPHCLK_RTC | RCC_PERIPHCLK_OSPI | RCC_PERIPHCLK_LTDC | RCC_PERIPHCLK_DSI; + +#endif /* STM32L431xx */ + + /* Get the PLLSAI1 Clock configuration -----------------------------------------------*/ + + PeriphClkInit->PLLSAI1.PLLSAI1Source = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC) >> RCC_PLLCFGR_PLLSRC_Pos; +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + PeriphClkInit->PLLSAI1.PLLSAI1M = (READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1M) >> RCC_PLLSAI1CFGR_PLLSAI1M_Pos) + 1U; +#else + PeriphClkInit->PLLSAI1.PLLSAI1M = (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U; +#endif /* RCC_PLLSAI1M_DIV_1_16_SUPPORT */ + PeriphClkInit->PLLSAI1.PLLSAI1N = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos; + PeriphClkInit->PLLSAI1.PLLSAI1P = ((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1P) >> RCC_PLLSAI1CFGR_PLLSAI1P_Pos) << 4U) + 7U; + PeriphClkInit->PLLSAI1.PLLSAI1Q = ((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1Q) >> RCC_PLLSAI1CFGR_PLLSAI1Q_Pos) + 1U) * 2U; + PeriphClkInit->PLLSAI1.PLLSAI1R = ((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1R) >> RCC_PLLSAI1CFGR_PLLSAI1R_Pos) + 1U) * 2U; + +#if defined(RCC_PLLSAI2_SUPPORT) + + /* Get the PLLSAI2 Clock configuration -----------------------------------------------*/ + + PeriphClkInit->PLLSAI2.PLLSAI2Source = PeriphClkInit->PLLSAI1.PLLSAI1Source; +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + PeriphClkInit->PLLSAI2.PLLSAI2M = (READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2M) >> RCC_PLLSAI2CFGR_PLLSAI2M_Pos) + 1U; +#else + PeriphClkInit->PLLSAI2.PLLSAI2M = PeriphClkInit->PLLSAI1.PLLSAI1M; +#endif /* RCC_PLLSAI2M_DIV_1_16_SUPPORT */ + PeriphClkInit->PLLSAI2.PLLSAI2N = READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2N) >> RCC_PLLSAI2CFGR_PLLSAI2N_Pos; + PeriphClkInit->PLLSAI2.PLLSAI2P = ((READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2P) >> RCC_PLLSAI2CFGR_PLLSAI2P_Pos) << 4U) + 7U; +#if defined(RCC_PLLSAI2Q_DIV_SUPPORT) + PeriphClkInit->PLLSAI2.PLLSAI2Q = ((READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2Q) >> RCC_PLLSAI2CFGR_PLLSAI2Q_Pos) + 1U) * 2U; +#endif /* RCC_PLLSAI2Q_DIV_SUPPORT */ + PeriphClkInit->PLLSAI2.PLLSAI2R = ((READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2R)>> RCC_PLLSAI2CFGR_PLLSAI2R_Pos) + 1U) * 2U; + +#endif /* RCC_PLLSAI2_SUPPORT */ + + /* Get the USART1 clock source ---------------------------------------------*/ + PeriphClkInit->Usart1ClockSelection = __HAL_RCC_GET_USART1_SOURCE(); + /* Get the USART2 clock source ---------------------------------------------*/ + PeriphClkInit->Usart2ClockSelection = __HAL_RCC_GET_USART2_SOURCE(); + +#if defined(USART3) + /* Get the USART3 clock source ---------------------------------------------*/ + PeriphClkInit->Usart3ClockSelection = __HAL_RCC_GET_USART3_SOURCE(); +#endif /* USART3 */ + +#if defined(UART4) + /* Get the UART4 clock source ----------------------------------------------*/ + PeriphClkInit->Uart4ClockSelection = __HAL_RCC_GET_UART4_SOURCE(); +#endif /* UART4 */ + +#if defined(UART5) + /* Get the UART5 clock source ----------------------------------------------*/ + PeriphClkInit->Uart5ClockSelection = __HAL_RCC_GET_UART5_SOURCE(); +#endif /* UART5 */ + + /* Get the LPUART1 clock source --------------------------------------------*/ + PeriphClkInit->Lpuart1ClockSelection = __HAL_RCC_GET_LPUART1_SOURCE(); + + /* Get the I2C1 clock source -----------------------------------------------*/ + PeriphClkInit->I2c1ClockSelection = __HAL_RCC_GET_I2C1_SOURCE(); + +#if defined(I2C2) + /* Get the I2C2 clock source ----------------------------------------------*/ + PeriphClkInit->I2c2ClockSelection = __HAL_RCC_GET_I2C2_SOURCE(); +#endif /* I2C2 */ + + /* Get the I2C3 clock source -----------------------------------------------*/ + PeriphClkInit->I2c3ClockSelection = __HAL_RCC_GET_I2C3_SOURCE(); + +#if defined(I2C4) + /* Get the I2C4 clock source -----------------------------------------------*/ + PeriphClkInit->I2c4ClockSelection = __HAL_RCC_GET_I2C4_SOURCE(); +#endif /* I2C4 */ + + /* Get the LPTIM1 clock source ---------------------------------------------*/ + PeriphClkInit->Lptim1ClockSelection = __HAL_RCC_GET_LPTIM1_SOURCE(); + + /* Get the LPTIM2 clock source ---------------------------------------------*/ + PeriphClkInit->Lptim2ClockSelection = __HAL_RCC_GET_LPTIM2_SOURCE(); + + /* Get the SAI1 clock source -----------------------------------------------*/ + PeriphClkInit->Sai1ClockSelection = __HAL_RCC_GET_SAI1_SOURCE(); + +#if defined(SAI2) + /* Get the SAI2 clock source -----------------------------------------------*/ + PeriphClkInit->Sai2ClockSelection = __HAL_RCC_GET_SAI2_SOURCE(); +#endif /* SAI2 */ + + /* Get the RTC clock source ------------------------------------------------*/ + PeriphClkInit->RTCClockSelection = __HAL_RCC_GET_RTC_SOURCE(); + +#if defined(USB_OTG_FS) || defined(USB) + /* Get the USB clock source ------------------------------------------------*/ + PeriphClkInit->UsbClockSelection = __HAL_RCC_GET_USB_SOURCE(); +#endif /* USB_OTG_FS || USB */ + +#if defined(SDMMC1) + /* Get the SDMMC1 clock source ---------------------------------------------*/ + PeriphClkInit->Sdmmc1ClockSelection = __HAL_RCC_GET_SDMMC1_SOURCE(); +#endif /* SDMMC1 */ + + /* Get the RNG clock source ------------------------------------------------*/ + PeriphClkInit->RngClockSelection = __HAL_RCC_GET_RNG_SOURCE(); + + /* Get the ADC clock source ------------------------------------------------*/ + PeriphClkInit->AdcClockSelection = __HAL_RCC_GET_ADC_SOURCE(); + +#if defined(SWPMI1) + /* Get the SWPMI1 clock source ---------------------------------------------*/ + PeriphClkInit->Swpmi1ClockSelection = __HAL_RCC_GET_SWPMI1_SOURCE(); +#endif /* SWPMI1 */ + +#if defined(DFSDM1_Filter0) + /* Get the DFSDM1 clock source ---------------------------------------------*/ + PeriphClkInit->Dfsdm1ClockSelection = __HAL_RCC_GET_DFSDM1_SOURCE(); + +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + /* Get the DFSDM1 audio clock source ---------------------------------------*/ + PeriphClkInit->Dfsdm1AudioClockSelection = __HAL_RCC_GET_DFSDM1AUDIO_SOURCE(); +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ +#endif /* DFSDM1_Filter0 */ + +#if defined(LTDC) + /* Get the LTDC clock source -----------------------------------------------*/ + PeriphClkInit->LtdcClockSelection = __HAL_RCC_GET_LTDC_SOURCE(); +#endif /* LTDC */ + +#if defined(DSI) + /* Get the DSI clock source ------------------------------------------------*/ + PeriphClkInit->DsiClockSelection = __HAL_RCC_GET_DSI_SOURCE(); +#endif /* DSI */ + +#if defined(OCTOSPI1) || defined(OCTOSPI2) + /* Get the OctoSPIclock source --------------------------------------------*/ + PeriphClkInit->OspiClockSelection = __HAL_RCC_GET_OSPI_SOURCE(); +#endif /* OCTOSPI1 || OCTOSPI2 */ +} + +/** + * @brief Return the peripheral clock frequency for peripherals with clock source from PLLSAIs + * @note Return 0 if peripheral clock identifier not managed by this API + * @param PeriphClk Peripheral clock identifier + * This parameter can be one of the following values: + * @arg @ref RCC_PERIPHCLK_RTC RTC peripheral clock + * @arg @ref RCC_PERIPHCLK_ADC ADC peripheral clock + @if STM32L462xx + * @arg @ref RCC_PERIPHCLK_DFSDM1 DFSDM1 peripheral clock (only for devices with DFSDM) + @endif + @if STM32L486xx + * @arg @ref RCC_PERIPHCLK_DFSDM1 DFSDM1 peripheral clock (only for devices with DFSDM) + @endif + @if STM32L4A6xx + * @arg @ref RCC_PERIPHCLK_DFSDM1 DFSDM1 peripheral clock (only for devices with DFSDM) + @endif + * @arg @ref RCC_PERIPHCLK_I2C1 I2C1 peripheral clock + * @arg @ref RCC_PERIPHCLK_I2C2 I2C2 peripheral clock + * @arg @ref RCC_PERIPHCLK_I2C3 I2C3 peripheral clock + @if STM32L462xx + * @arg @ref RCC_PERIPHCLK_I2C4 I2C4 peripheral clock (only for devices with I2C4) + @endif + @if STM32L4A6xx + * @arg @ref RCC_PERIPHCLK_I2C4 I2C4 peripheral clock (only for devices with I2C4) + @endif + @if STM32L4S9xx + * @arg @ref RCC_PERIPHCLK_I2C4 I2C4 peripheral clock (only for devices with I2C4) + @endif + * @arg @ref RCC_PERIPHCLK_LPTIM1 LPTIM1 peripheral clock + * @arg @ref RCC_PERIPHCLK_LPTIM2 LPTIM2 peripheral clock + * @arg @ref RCC_PERIPHCLK_LPUART1 LPUART1 peripheral clock + * @arg @ref RCC_PERIPHCLK_RNG RNG peripheral clock + * @arg @ref RCC_PERIPHCLK_SAI1 SAI1 peripheral clock + @if STM32L486xx + * @arg @ref RCC_PERIPHCLK_SAI2 SAI2 peripheral clock (only for devices with SAI2) + @endif + @if STM32L4A6xx + * @arg @ref RCC_PERIPHCLK_SAI2 SAI2 peripheral clock (only for devices with SAI2) + @endif + @if STM32L4S9xx + * @arg @ref RCC_PERIPHCLK_SAI2 SAI2 peripheral clock (only for devices with SAI2) + @endif + * @arg @ref RCC_PERIPHCLK_SDMMC1 SDMMC1 peripheral clock + @if STM32L443xx + * @arg @ref RCC_PERIPHCLK_SWPMI1 SWPMI1 peripheral clock (only for devices with SWPMI1) + @endif + @if STM32L486xx + * @arg @ref RCC_PERIPHCLK_SWPMI1 SWPMI1 peripheral clock (only for devices with SWPMI1) + @endif + @if STM32L4A6xx + * @arg @ref RCC_PERIPHCLK_SWPMI1 SWPMI1 peripheral clock (only for devices with SWPMI1) + @endif + * @arg @ref RCC_PERIPHCLK_USART1 USART1 peripheral clock + * @arg @ref RCC_PERIPHCLK_USART2 USART1 peripheral clock + * @arg @ref RCC_PERIPHCLK_USART3 USART1 peripheral clock + @if STM32L462xx + * @arg @ref RCC_PERIPHCLK_UART4 UART4 peripheral clock (only for devices with UART4) + * @arg @ref RCC_PERIPHCLK_USB USB peripheral clock (only for devices with USB) + @endif + @if STM32L486xx + * @arg @ref RCC_PERIPHCLK_UART4 UART4 peripheral clock (only for devices with UART4) + * @arg @ref RCC_PERIPHCLK_UART5 UART5 peripheral clock (only for devices with UART5) + * @arg @ref RCC_PERIPHCLK_USB USB peripheral clock (only for devices with USB) + @endif + @if STM32L4A6xx + * @arg @ref RCC_PERIPHCLK_UART4 UART4 peripheral clock (only for devices with UART4) + * @arg @ref RCC_PERIPHCLK_UART5 UART5 peripheral clock (only for devices with UART5) + * @arg @ref RCC_PERIPHCLK_USB USB peripheral clock (only for devices with USB) + @endif + @if STM32L4S9xx + * @arg @ref RCC_PERIPHCLK_UART4 USART1 peripheral clock (only for devices with UART4) + * @arg @ref RCC_PERIPHCLK_UART5 USART1 peripheral clock (only for devices with UART5) + * @arg @ref RCC_PERIPHCLK_USB USB peripheral clock (only for devices with USB) + * @arg @ref RCC_PERIPHCLK_DFSDM1 DFSDM1 peripheral kernel clock (only for devices with DFSDM1) + * @arg @ref RCC_PERIPHCLK_DFSDM1AUDIO DFSDM1 peripheral audio clock (only for devices with DFSDM1) + * @arg @ref RCC_PERIPHCLK_LTDC LTDC peripheral clock (only for devices with LTDC) + * @arg @ref RCC_PERIPHCLK_DSI DSI peripheral clock (only for devices with DSI) + * @arg @ref RCC_PERIPHCLK_OSPI OctoSPI peripheral clock (only for devices with OctoSPI) + @endif + * @retval Frequency in Hz + */ +uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk) +{ + uint32_t frequency = 0U; + uint32_t srcclk = 0U; + uint32_t pllvco = 0U, plln = 0U, pllp = 0U; + + /* Check the parameters */ + assert_param(IS_RCC_PERIPHCLOCK(PeriphClk)); + + if(PeriphClk == RCC_PERIPHCLK_RTC) + { + /* Get the current RTC source */ + srcclk = __HAL_RCC_GET_RTC_SOURCE(); + + /* Check if LSE is ready and if RTC clock selection is LSE */ + if ((srcclk == RCC_RTCCLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))) + { + frequency = LSE_VALUE; + } + /* Check if LSI is ready and if RTC clock selection is LSI */ + else if ((srcclk == RCC_RTCCLKSOURCE_LSI) && (HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIRDY))) + { + frequency = LSI_VALUE; + } + /* Check if HSE is ready and if RTC clock selection is HSI_DIV32*/ + else if ((srcclk == RCC_RTCCLKSOURCE_HSE_DIV32) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY))) + { + frequency = HSE_VALUE / 32U; + } + /* Clock not enabled for RTC*/ + else + { + frequency = 0U; + } + } + else + { + /* Other external peripheral clock source than RTC */ + + /* Compute PLL clock input */ + if(__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_MSI) /* MSI ? */ + { + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_MSIRDY)) + { + /*MSI frequency range in HZ*/ + pllvco = MSIRangeTable[(__HAL_RCC_GET_MSI_RANGE() >> 4U)]; + } + else + { + pllvco = 0U; + } + } + else if(__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSI) /* HSI ? */ + { + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) + { + pllvco = HSI_VALUE; + } + else + { + pllvco = 0U; + } + } + else if(__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSE) /* HSE ? */ + { + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY)) + { + pllvco = HSE_VALUE; + } + else + { + pllvco = 0U; + } + } + else /* No source */ + { + pllvco = 0U; + } + +#if !defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) && !defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + /* f(PLL Source) / PLLM */ + pllvco = (pllvco / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U)); +#endif + + switch(PeriphClk) + { +#if defined(SAI2) + + case RCC_PERIPHCLK_SAI1: + case RCC_PERIPHCLK_SAI2: + + if(PeriphClk == RCC_PERIPHCLK_SAI1) + { + srcclk = __HAL_RCC_GET_SAI1_SOURCE(); + + if(srcclk == RCC_SAI1CLKSOURCE_PIN) + { + frequency = EXTERNAL_SAI1_CLOCK_VALUE; + } + /* Else, PLL clock output to check below */ + } + else /* RCC_PERIPHCLK_SAI2 */ + { + srcclk = __HAL_RCC_GET_SAI2_SOURCE(); + + if(srcclk == RCC_SAI2CLKSOURCE_PIN) + { + frequency = EXTERNAL_SAI2_CLOCK_VALUE; + } + /* Else, PLL clock output to check below */ + } + +#else + + case RCC_PERIPHCLK_SAI1: + + if(PeriphClk == RCC_PERIPHCLK_SAI1) + { + srcclk = READ_BIT(RCC->CCIPR, RCC_CCIPR_SAI1SEL); + + if(srcclk == RCC_SAI1CLKSOURCE_PIN) + { + frequency = EXTERNAL_SAI1_CLOCK_VALUE; + } + /* Else, PLL clock output to check below */ + } + +#endif /* SAI2 */ + + if(frequency == 0U) + { +#if defined(SAI2) + if((srcclk == RCC_SAI1CLKSOURCE_PLL) || (srcclk == RCC_SAI2CLKSOURCE_PLL)) + { + if(__HAL_RCC_GET_PLLCLKOUT_CONFIG(RCC_PLL_SAI3CLK) != RESET) + { + /* f(PLLSAI3CLK) = f(VCO input) * PLLN / PLLP */ + plln = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos; +#if defined(RCC_PLLP_DIV_2_31_SUPPORT) + pllp = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLPDIV) >> RCC_PLLCFGR_PLLPDIV_Pos; +#endif + if(pllp == 0U) + { + if(READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLP) != RESET) + { + pllp = 17U; + } + else + { + pllp = 7U; + } + } + frequency = (pllvco * plln) / pllp; + } + } + else if(srcclk == 0U) /* RCC_SAI1CLKSOURCE_PLLSAI1 || RCC_SAI2CLKSOURCE_PLLSAI1 */ + { + if(__HAL_RCC_GET_PLLSAI1CLKOUT_CONFIG(RCC_PLLSAI1_SAI1CLK) != RESET) + { +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + /* f(PLLSAI1 Source) / PLLSAI1M */ + pllvco = (pllvco / ((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1M) >> RCC_PLLSAI1CFGR_PLLSAI1M_Pos) + 1U)); +#endif + /* f(PLLSAI1CLK) = f(VCOSAI1 input) * PLLSAI1N / PLLSAI1P */ + plln = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos; +#if defined(RCC_PLLSAI1P_DIV_2_31_SUPPORT) + pllp = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1PDIV) >> RCC_PLLSAI1CFGR_PLLSAI1PDIV_Pos; +#endif + if(pllp == 0U) + { + if(READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1P) != RESET) + { + pllp = 17U; + } + else + { + pllp = 7U; + } + } + frequency = (pllvco * plln) / pllp; + } + } +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + else if((srcclk == RCC_SAI1CLKSOURCE_HSI) || (srcclk == RCC_SAI2CLKSOURCE_HSI)) + { + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) + { + frequency = HSI_VALUE; + } + } +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#else + if(srcclk == RCC_SAI1CLKSOURCE_PLL) + { + if(__HAL_RCC_GET_PLLCLKOUT_CONFIG(RCC_PLL_SAI2CLK) != RESET) + { + /* f(PLLSAI2CLK) = f(VCO input) * PLLN / PLLP */ + plln = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos; +#if defined(RCC_PLLP_DIV_2_31_SUPPORT) + pllp = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLPDIV) >> RCC_PLLCFGR_PLLPDIV_Pos; +#endif + if(pllp == 0U) + { + if(READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLP) != RESET) + { + pllp = 17U; + } + else + { + pllp = 7U; + } + } + + frequency = (pllvco * plln) / pllp; + } + else if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) + { + /* HSI automatically selected as clock source if PLLs not enabled */ + frequency = HSI_VALUE; + } + else + { + /* No clock source */ + frequency = 0U; + } + } + else if(srcclk == RCC_SAI1CLKSOURCE_PLLSAI1) + { + if(__HAL_RCC_GET_PLLSAI1CLKOUT_CONFIG(RCC_PLLSAI1_SAI1CLK) != RESET) + { +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + /* f(PLLSAI1 Source) / PLLSAI1M */ + pllvco = (pllvco / ((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1M) >> RCC_PLLSAI1CFGR_PLLSAI1M_Pos) + 1U)); +#endif + /* f(PLLSAI1CLK) = f(VCOSAI1 input) * PLLSAI1N / PLLSAI1P */ + plln = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos; +#if defined(RCC_PLLSAI1P_DIV_2_31_SUPPORT) + pllp = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1PDIV) >> RCC_PLLSAI1CFGR_PLLSAI1PDIV_Pos; +#endif + if(pllp == 0U) + { + if(READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1P) != RESET) + { + pllp = 17U; + } + else + { + pllp = 7U; + } + } + + frequency = (pllvco * plln) / pllp; + } + else if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) + { + /* HSI automatically selected as clock source if PLLs not enabled */ + frequency = HSI_VALUE; + } + else + { + /* No clock source */ + frequency = 0U; + } + } +#endif /* SAI2 */ + +#if defined(RCC_PLLSAI2_SUPPORT) + + else if((srcclk == RCC_SAI1CLKSOURCE_PLLSAI2) || (srcclk == RCC_SAI2CLKSOURCE_PLLSAI2)) + { + if(__HAL_RCC_GET_PLLSAI2CLKOUT_CONFIG(RCC_PLLSAI2_SAI2CLK) != RESET) + { +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + /* f(PLLSAI2 Source) / PLLSAI2M */ + pllvco = (pllvco / ((READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2M) >> RCC_PLLSAI2CFGR_PLLSAI2M_Pos) + 1U)); +#endif + /* f(PLLSAI2CLK) = f(VCOSAI2 input) * PLLSAI2N / PLLSAI2P */ + plln = READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2N) >> RCC_PLLSAI2CFGR_PLLSAI2N_Pos; +#if defined(RCC_PLLSAI2P_DIV_2_31_SUPPORT) + pllp = READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2PDIV) >> RCC_PLLSAI2CFGR_PLLSAI2PDIV_Pos; +#endif + if(pllp == 0U) + { + if(READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2P) != RESET) + { + pllp = 17U; + } + else + { + pllp = 7U; + } + } + frequency = (pllvco * plln) / pllp; + } + } + +#endif /* RCC_PLLSAI2_SUPPORT */ + + else + { + /* No clock source */ + frequency = 0U; + } + } + break; + +#if defined(USB_OTG_FS) || defined(USB) + + case RCC_PERIPHCLK_USB: + +#endif /* USB_OTG_FS || USB */ + + case RCC_PERIPHCLK_RNG: + +#if defined(SDMMC1) && !defined(RCC_CCIPR2_SDMMCSEL) + + case RCC_PERIPHCLK_SDMMC1: + +#endif /* SDMMC1 && !RCC_CCIPR2_SDMMCSEL */ + + srcclk = READ_BIT(RCC->CCIPR, RCC_CCIPR_CLK48SEL); + + if(srcclk == RCC_CCIPR_CLK48SEL) /* MSI ? */ + { + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_MSIRDY)) + { + /*MSI frequency range in HZ*/ + frequency = MSIRangeTable[(__HAL_RCC_GET_MSI_RANGE() >> 4U)]; + } + else + { + frequency = 0U; + } + } + else if(srcclk == RCC_CCIPR_CLK48SEL_1) /* PLL ? */ + { + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLRDY) && HAL_IS_BIT_SET(RCC->PLLCFGR, RCC_PLLCFGR_PLLQEN)) + { +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) || defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + /* f(PLL Source) / PLLM */ + pllvco = (pllvco / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U)); +#endif + /* f(PLL48M1CLK) = f(VCO input) * PLLN / PLLQ */ + plln = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos; + frequency = (pllvco * plln) / (((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLQ) >> RCC_PLLCFGR_PLLQ_Pos) + 1U) << 1U); + } + else + { + frequency = 0U; + } + } + else if(srcclk == RCC_CCIPR_CLK48SEL_0) /* PLLSAI1 ? */ + { + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLSAI1RDY) && HAL_IS_BIT_SET(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1QEN)) + { +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + /* f(PLLSAI1 Source) / PLLSAI1M */ + pllvco = (pllvco / ((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1M) >> RCC_PLLSAI1CFGR_PLLSAI1M_Pos) + 1U)); +#endif + /* f(PLL48M2CLK) = f(VCOSAI1 input) * PLLSAI1N / PLLSAI1Q */ + plln = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos; + frequency = (pllvco * plln) / (((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1Q) >> RCC_PLLSAI1CFGR_PLLSAI1Q_Pos) + 1U) << 1U); + } + else + { + frequency = 0U; + } + } +#if defined(RCC_HSI48_SUPPORT) + else if((srcclk == 0U) && (HAL_IS_BIT_SET(RCC->CRRCR, RCC_CRRCR_HSI48RDY))) /* HSI48 ? */ + { + frequency = HSI48_VALUE; + } + else /* No clock source */ + { + frequency = 0U; + } +#else + else /* No clock source */ + { + frequency = 0U; + } +#endif /* RCC_HSI48_SUPPORT */ + break; + +#if defined(SDMMC1) && defined(RCC_CCIPR2_SDMMCSEL) + + case RCC_PERIPHCLK_SDMMC1: + + if(HAL_IS_BIT_SET(RCC->CCIPR2, RCC_CCIPR2_SDMMCSEL)) /* PLL "P" ? */ + { + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLRDY) && HAL_IS_BIT_SET(RCC->PLLCFGR, RCC_PLLCFGR_PLLPEN)) + { +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) || defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + /* f(PLL Source) / PLLM */ + pllvco = (pllvco / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U)); +#endif + /* f(PLLSAI3CLK) = f(VCO input) * PLLN / PLLP */ + plln = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos; +#if defined(RCC_PLLP_DIV_2_31_SUPPORT) + pllp = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLPDIV) >> RCC_PLLCFGR_PLLPDIV_Pos; +#endif + if(pllp == 0U) + { + if(READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLP) != RESET) + { + pllp = 17U; + } + else + { + pllp = 7U; + } + } + frequency = (pllvco * plln) / pllp; + } + else + { + frequency = 0U; + } + } + else /* 48MHz from PLL "Q" or MSI or PLLSAI1Q or HSI48 */ + { + srcclk = READ_BIT(RCC->CCIPR, RCC_CCIPR_CLK48SEL); + + if(srcclk == RCC_CCIPR_CLK48SEL) /* MSI ? */ + { + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_MSIRDY)) + { + /*MSI frequency range in HZ*/ + frequency = MSIRangeTable[(__HAL_RCC_GET_MSI_RANGE() >> 4U)]; + } + else + { + frequency = 0U; + } + } + else if(srcclk == RCC_CCIPR_CLK48SEL_1) /* PLL "Q" ? */ + { + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLRDY) && HAL_IS_BIT_SET(RCC->PLLCFGR, RCC_PLLCFGR_PLLQEN)) + { +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) || defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + /* f(PLL Source) / PLLM */ + pllvco = (pllvco / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U)); +#endif + /* f(PLL48M1CLK) = f(VCO input) * PLLN / PLLQ */ + plln = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos; + frequency = (pllvco * plln) / (((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLQ) >> RCC_PLLCFGR_PLLQ_Pos) + 1U) << 1U); + } + else + { + frequency = 0U; + } + } + else if(srcclk == RCC_CCIPR_CLK48SEL_0) /* PLLSAI1 ? */ + { + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLSAI1RDY) && HAL_IS_BIT_SET(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1QEN)) + { +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + /* f(PLLSAI1 Source) / PLLSAI1M */ + pllvco = (pllvco / ((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1M) >> RCC_PLLSAI1CFGR_PLLSAI1M_Pos) + 1U)); +#endif + /* f(PLL48M2CLK) = f(VCOSAI1 input) * PLLSAI1N / PLLSAI1Q */ + plln = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos; + frequency = (pllvco * plln) / (((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1Q) >> RCC_PLLSAI1CFGR_PLLSAI1Q_Pos) + 1U) << 1U); + } + else + { + frequency = 0U; + } + } + else if((srcclk == 0U) && (HAL_IS_BIT_SET(RCC->CRRCR, RCC_CRRCR_HSI48RDY))) /* HSI48 ? */ + { + frequency = HSI48_VALUE; + } + else /* No clock source */ + { + frequency = 0U; + } + } + break; + +#endif /* SDMMC1 && RCC_CCIPR2_SDMMCSEL */ + + case RCC_PERIPHCLK_USART1: + /* Get the current USART1 source */ + srcclk = __HAL_RCC_GET_USART1_SOURCE(); + + if(srcclk == RCC_USART1CLKSOURCE_PCLK2) + { + frequency = HAL_RCC_GetPCLK2Freq(); + } + else if(srcclk == RCC_USART1CLKSOURCE_SYSCLK) + { + frequency = HAL_RCC_GetSysClockFreq(); + } + else if((srcclk == RCC_USART1CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + { + frequency = HSI_VALUE; + } + else if((srcclk == RCC_USART1CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))) + { + frequency = LSE_VALUE; + } + /* Clock not enabled for USART1 */ + else + { + frequency = 0U; + } + break; + + case RCC_PERIPHCLK_USART2: + /* Get the current USART2 source */ + srcclk = __HAL_RCC_GET_USART2_SOURCE(); + + if(srcclk == RCC_USART2CLKSOURCE_PCLK1) + { + frequency = HAL_RCC_GetPCLK1Freq(); + } + else if(srcclk == RCC_USART2CLKSOURCE_SYSCLK) + { + frequency = HAL_RCC_GetSysClockFreq(); + } + else if((srcclk == RCC_USART2CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + { + frequency = HSI_VALUE; + } + else if((srcclk == RCC_USART2CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))) + { + frequency = LSE_VALUE; + } + /* Clock not enabled for USART2 */ + else + { + frequency = 0U; + } + break; + +#if defined(USART3) + + case RCC_PERIPHCLK_USART3: + /* Get the current USART3 source */ + srcclk = __HAL_RCC_GET_USART3_SOURCE(); + + if(srcclk == RCC_USART3CLKSOURCE_PCLK1) + { + frequency = HAL_RCC_GetPCLK1Freq(); + } + else if(srcclk == RCC_USART3CLKSOURCE_SYSCLK) + { + frequency = HAL_RCC_GetSysClockFreq(); + } + else if((srcclk == RCC_USART3CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + { + frequency = HSI_VALUE; + } + else if((srcclk == RCC_USART3CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))) + { + frequency = LSE_VALUE; + } + /* Clock not enabled for USART3 */ + else + { + frequency = 0U; + } + break; + +#endif /* USART3 */ + +#if defined(UART4) + + case RCC_PERIPHCLK_UART4: + /* Get the current UART4 source */ + srcclk = __HAL_RCC_GET_UART4_SOURCE(); + + if(srcclk == RCC_UART4CLKSOURCE_PCLK1) + { + frequency = HAL_RCC_GetPCLK1Freq(); + } + else if(srcclk == RCC_UART4CLKSOURCE_SYSCLK) + { + frequency = HAL_RCC_GetSysClockFreq(); + } + else if((srcclk == RCC_UART4CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + { + frequency = HSI_VALUE; + } + else if((srcclk == RCC_UART4CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))) + { + frequency = LSE_VALUE; + } + /* Clock not enabled for UART4 */ + else + { + frequency = 0U; + } + break; + +#endif /* UART4 */ + +#if defined(UART5) + + case RCC_PERIPHCLK_UART5: + /* Get the current UART5 source */ + srcclk = __HAL_RCC_GET_UART5_SOURCE(); + + if(srcclk == RCC_UART5CLKSOURCE_PCLK1) + { + frequency = HAL_RCC_GetPCLK1Freq(); + } + else if(srcclk == RCC_UART5CLKSOURCE_SYSCLK) + { + frequency = HAL_RCC_GetSysClockFreq(); + } + else if((srcclk == RCC_UART5CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + { + frequency = HSI_VALUE; + } + else if((srcclk == RCC_UART5CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))) + { + frequency = LSE_VALUE; + } + /* Clock not enabled for UART5 */ + else + { + frequency = 0U; + } + break; + +#endif /* UART5 */ + + case RCC_PERIPHCLK_LPUART1: + /* Get the current LPUART1 source */ + srcclk = __HAL_RCC_GET_LPUART1_SOURCE(); + + if(srcclk == RCC_LPUART1CLKSOURCE_PCLK1) + { + frequency = HAL_RCC_GetPCLK1Freq(); + } + else if(srcclk == RCC_LPUART1CLKSOURCE_SYSCLK) + { + frequency = HAL_RCC_GetSysClockFreq(); + } + else if((srcclk == RCC_LPUART1CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + { + frequency = HSI_VALUE; + } + else if((srcclk == RCC_LPUART1CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))) + { + frequency = LSE_VALUE; + } + /* Clock not enabled for LPUART1 */ + else + { + frequency = 0U; + } + break; + + case RCC_PERIPHCLK_ADC: + + srcclk = __HAL_RCC_GET_ADC_SOURCE(); + + if(srcclk == RCC_ADCCLKSOURCE_SYSCLK) + { + frequency = HAL_RCC_GetSysClockFreq(); + } + else if(srcclk == RCC_ADCCLKSOURCE_PLLSAI1) + { + if(__HAL_RCC_GET_PLLSAI1CLKOUT_CONFIG(RCC_PLLSAI1_ADC1CLK) != RESET) + { +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + /* f(PLLSAI1 Source) / PLLSAI1M */ + pllvco = (pllvco / ((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1M) >> RCC_PLLSAI1CFGR_PLLSAI1M_Pos) + 1U)); +#endif + /* f(PLLADC1CLK) = f(VCOSAI1 input) * PLLSAI1N / PLLSAI1R */ + plln = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos; + frequency = (pllvco * plln) / (((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1R) >> RCC_PLLSAI1CFGR_PLLSAI1R_Pos) + 1U) << 1U); + } + } +#if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || defined(STM32L496xx) || defined(STM32L4A6xx) + else if(srcclk == RCC_ADCCLKSOURCE_PLLSAI2) + { + if(__HAL_RCC_GET_PLLSAI2CLKOUT_CONFIG(RCC_PLLSAI2_ADC2CLK) != RESET) + { +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + /* f(PLLSAI2 Source) / PLLSAI2M */ + pllvco = (pllvco / ((READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2M) >> RCC_PLLSAI2CFGR_PLLSAI2M_Pos) + 1U)); +#endif + /* f(PLLADC2CLK) = f(VCOSAI2 input) * PLLSAI2N / PLLSAI2R */ + plln = READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2N) >> RCC_PLLSAI2CFGR_PLLSAI2N_Pos; + frequency = (pllvco * plln) / (((READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2R) >> RCC_PLLSAI2CFGR_PLLSAI2R_Pos) + 1U) << 1U); + } + } +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || STM32L496xx || STM32L4A6xx */ + /* Clock not enabled for ADC */ + else + { + frequency = 0U; + } + break; + +#if defined(DFSDM1_Filter0) + + case RCC_PERIPHCLK_DFSDM1: + /* Get the current DFSDM1 source */ + srcclk = __HAL_RCC_GET_DFSDM1_SOURCE(); + + if(srcclk == RCC_DFSDM1CLKSOURCE_PCLK2) + { + frequency = HAL_RCC_GetPCLK2Freq(); + } + else + { + frequency = HAL_RCC_GetSysClockFreq(); + } + break; + +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + + case RCC_PERIPHCLK_DFSDM1AUDIO: + /* Get the current DFSDM1 audio source */ + srcclk = __HAL_RCC_GET_DFSDM1AUDIO_SOURCE(); + + if(srcclk == RCC_DFSDM1AUDIOCLKSOURCE_SAI1) + { + frequency = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI1); + } + else if((srcclk == RCC_DFSDM1AUDIOCLKSOURCE_MSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_MSIRDY))) + { + /*MSI frequency range in HZ*/ + frequency = MSIRangeTable[(__HAL_RCC_GET_MSI_RANGE() >> 4U)]; + } + else if((srcclk == RCC_DFSDM1AUDIOCLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + { + frequency = HSI_VALUE; + } + /* Clock not enabled for DFSDM1 audio source */ + else + { + frequency = 0U; + } + break; + +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#endif /* DFSDM1_Filter0 */ + + case RCC_PERIPHCLK_I2C1: + /* Get the current I2C1 source */ + srcclk = __HAL_RCC_GET_I2C1_SOURCE(); + + if(srcclk == RCC_I2C1CLKSOURCE_PCLK1) + { + frequency = HAL_RCC_GetPCLK1Freq(); + } + else if(srcclk == RCC_I2C1CLKSOURCE_SYSCLK) + { + frequency = HAL_RCC_GetSysClockFreq(); + } + else if((srcclk == RCC_I2C1CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + { + frequency = HSI_VALUE; + } + /* Clock not enabled for I2C1 */ + else + { + frequency = 0U; + } + break; + +#if defined(I2C2) + + case RCC_PERIPHCLK_I2C2: + /* Get the current I2C2 source */ + srcclk = __HAL_RCC_GET_I2C2_SOURCE(); + + if(srcclk == RCC_I2C2CLKSOURCE_PCLK1) + { + frequency = HAL_RCC_GetPCLK1Freq(); + } + else if(srcclk == RCC_I2C2CLKSOURCE_SYSCLK) + { + frequency = HAL_RCC_GetSysClockFreq(); + } + else if((srcclk == RCC_I2C2CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + { + frequency = HSI_VALUE; + } + /* Clock not enabled for I2C2 */ + else + { + frequency = 0U; + } + break; + +#endif /* I2C2 */ + + case RCC_PERIPHCLK_I2C3: + /* Get the current I2C3 source */ + srcclk = __HAL_RCC_GET_I2C3_SOURCE(); + + if(srcclk == RCC_I2C3CLKSOURCE_PCLK1) + { + frequency = HAL_RCC_GetPCLK1Freq(); + } + else if(srcclk == RCC_I2C3CLKSOURCE_SYSCLK) + { + frequency = HAL_RCC_GetSysClockFreq(); + } + else if((srcclk == RCC_I2C3CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + { + frequency = HSI_VALUE; + } + /* Clock not enabled for I2C3 */ + else + { + frequency = 0U; + } + break; + +#if defined(I2C4) + + case RCC_PERIPHCLK_I2C4: + /* Get the current I2C4 source */ + srcclk = __HAL_RCC_GET_I2C4_SOURCE(); + + if(srcclk == RCC_I2C4CLKSOURCE_PCLK1) + { + frequency = HAL_RCC_GetPCLK1Freq(); + } + else if(srcclk == RCC_I2C4CLKSOURCE_SYSCLK) + { + frequency = HAL_RCC_GetSysClockFreq(); + } + else if((srcclk == RCC_I2C4CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + { + frequency = HSI_VALUE; + } + /* Clock not enabled for I2C4 */ + else + { + frequency = 0U; + } + break; + +#endif /* I2C4 */ + + case RCC_PERIPHCLK_LPTIM1: + /* Get the current LPTIM1 source */ + srcclk = __HAL_RCC_GET_LPTIM1_SOURCE(); + + if(srcclk == RCC_LPTIM1CLKSOURCE_PCLK1) + { + frequency = HAL_RCC_GetPCLK1Freq(); + } + else if((srcclk == RCC_LPTIM1CLKSOURCE_LSI) && (HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIRDY))) + { + frequency = LSI_VALUE; + } + else if((srcclk == RCC_LPTIM1CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + { + frequency = HSI_VALUE; + } + else if ((srcclk == RCC_LPTIM1CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))) + { + frequency = LSE_VALUE; + } + /* Clock not enabled for LPTIM1 */ + else + { + frequency = 0U; + } + break; + + case RCC_PERIPHCLK_LPTIM2: + /* Get the current LPTIM2 source */ + srcclk = __HAL_RCC_GET_LPTIM2_SOURCE(); + + if(srcclk == RCC_LPTIM2CLKSOURCE_PCLK1) + { + frequency = HAL_RCC_GetPCLK1Freq(); + } + else if((srcclk == RCC_LPTIM2CLKSOURCE_LSI) && (HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIRDY))) + { + frequency = LSI_VALUE; + } + else if((srcclk == RCC_LPTIM2CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + { + frequency = HSI_VALUE; + } + else if ((srcclk == RCC_LPTIM2CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))) + { + frequency = LSE_VALUE; + } + /* Clock not enabled for LPTIM2 */ + else + { + frequency = 0U; + } + break; + +#if defined(SWPMI1) + + case RCC_PERIPHCLK_SWPMI1: + /* Get the current SWPMI1 source */ + srcclk = __HAL_RCC_GET_SWPMI1_SOURCE(); + + if(srcclk == RCC_SWPMI1CLKSOURCE_PCLK1) + { + frequency = HAL_RCC_GetPCLK1Freq(); + } + else if((srcclk == RCC_SWPMI1CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + { + frequency = HSI_VALUE; + } + /* Clock not enabled for SWPMI1 */ + else + { + frequency = 0U; + } + break; + +#endif /* SWPMI1 */ + +#if defined(OCTOSPI1) || defined(OCTOSPI2) + + case RCC_PERIPHCLK_OSPI: + /* Get the current OctoSPI clock source */ + srcclk = __HAL_RCC_GET_OSPI_SOURCE(); + + if(srcclk == RCC_OSPICLKSOURCE_SYSCLK) + { + frequency = HAL_RCC_GetSysClockFreq(); + } + else if((srcclk == RCC_OSPICLKSOURCE_MSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_MSIRDY))) + { + /*MSI frequency range in HZ*/ + frequency = MSIRangeTable[(__HAL_RCC_GET_MSI_RANGE() >> 4U)]; + } + else if(srcclk == RCC_OSPICLKSOURCE_PLL) + { + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLRDY) && HAL_IS_BIT_SET(RCC->PLLCFGR, RCC_PLLCFGR_PLLQEN)) + { + /* f(PLL Source) / PLLM */ + pllvco = (pllvco / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U)); + /* f(PLL48M1CLK) = f(VCO input) * PLLN / PLLQ */ + plln = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos; + frequency = (pllvco * plln) / (((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLQ) >> RCC_PLLCFGR_PLLQ_Pos) + 1U) << 1U); + } + else + { + frequency = 0U; + } + } + /* Clock not enabled for OctoSPI */ + else + { + frequency = 0U; + } + break; + +#endif /* OCTOSPI1 || OCTOSPI2 */ + + default: + break; + } + } + + return(frequency); +} + +/** + * @} + */ + +/** @defgroup RCCEx_Exported_Functions_Group2 Extended Clock management functions + * @brief Extended Clock management functions + * +@verbatim + =============================================================================== + ##### Extended clock management functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to control the + activation or deactivation of MSI PLL-mode, PLLSAI1, PLLSAI2, LSE CSS, + Low speed clock output and clock after wake-up from STOP mode. +@endverbatim + * @{ + */ + +/** + * @brief Enable PLLSAI1. + * @param PLLSAI1Init pointer to an RCC_PLLSAI1InitTypeDef structure that + * contains the configuration information for the PLLSAI1 + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RCCEx_EnablePLLSAI1(RCC_PLLSAI1InitTypeDef *PLLSAI1Init) +{ + uint32_t tickstart = 0U; + HAL_StatusTypeDef status = HAL_OK; + + /* check for PLLSAI1 Parameters used to output PLLSAI1CLK */ + assert_param(IS_RCC_PLLSAI1SOURCE(PLLSAI1Init->PLLSAI1Source)); + assert_param(IS_RCC_PLLSAI1M_VALUE(PLLSAI1Init->PLLSAI1M)); + assert_param(IS_RCC_PLLSAI1N_VALUE(PLLSAI1Init->PLLSAI1N)); + assert_param(IS_RCC_PLLSAI1P_VALUE(PLLSAI1Init->PLLSAI1P)); + assert_param(IS_RCC_PLLSAI1Q_VALUE(PLLSAI1Init->PLLSAI1Q)); + assert_param(IS_RCC_PLLSAI1R_VALUE(PLLSAI1Init->PLLSAI1R)); + assert_param(IS_RCC_PLLSAI1CLOCKOUT_VALUE(PLLSAI1Init->PLLSAI1ClockOut)); + + /* Disable the PLLSAI1 */ + __HAL_RCC_PLLSAI1_DISABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till PLLSAI1 is ready to be updated */ + while(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) != RESET) + { + if((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE) + { + status = HAL_TIMEOUT; + break; + } + } + + if(status == HAL_OK) + { +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + /* Configure the PLLSAI1 Multiplication factor N */ + /* Configure the PLLSAI1 Division factors M, P, Q and R */ + __HAL_RCC_PLLSAI1_CONFIG(PLLSAI1Init->PLLSAI1M, PLLSAI1Init->PLLSAI1N, PLLSAI1Init->PLLSAI1P, PLLSAI1Init->PLLSAI1Q, PLLSAI1Init->PLLSAI1R); +#else + /* Configure the PLLSAI1 Multiplication factor N */ + /* Configure the PLLSAI1 Division factors P, Q and R */ + __HAL_RCC_PLLSAI1_CONFIG(PLLSAI1Init->PLLSAI1N, PLLSAI1Init->PLLSAI1P, PLLSAI1Init->PLLSAI1Q, PLLSAI1Init->PLLSAI1R); +#endif /* RCC_PLLSAI1M_DIV_1_16_SUPPORT */ + /* Configure the PLLSAI1 Clock output(s) */ + __HAL_RCC_PLLSAI1CLKOUT_ENABLE(PLLSAI1Init->PLLSAI1ClockOut); + + /* Enable the PLLSAI1 again by setting PLLSAI1ON to 1*/ + __HAL_RCC_PLLSAI1_ENABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till PLLSAI1 is ready */ + while(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) == RESET) + { + if((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE) + { + status = HAL_TIMEOUT; + break; + } + } + } + + return status; +} + +/** + * @brief Disable PLLSAI1. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RCCEx_DisablePLLSAI1(void) +{ + uint32_t tickstart = 0U; + HAL_StatusTypeDef status = HAL_OK; + + /* Disable the PLLSAI1 */ + __HAL_RCC_PLLSAI1_DISABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till PLLSAI1 is ready */ + while(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) != RESET) + { + if((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE) + { + status = HAL_TIMEOUT; + break; + } + } + + /* Disable the PLLSAI1 Clock outputs */ + __HAL_RCC_PLLSAI1CLKOUT_DISABLE(RCC_PLLSAI1CFGR_PLLSAI1PEN|RCC_PLLSAI1CFGR_PLLSAI1QEN|RCC_PLLSAI1CFGR_PLLSAI1REN); + + /* Reset PLL source to save power if no PLLs on */ + if((READ_BIT(RCC->CR, RCC_CR_PLLRDY) == RESET) +#if defined(RCC_PLLSAI2_SUPPORT) + && + (READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) == RESET) +#endif /* RCC_PLLSAI2_SUPPORT */ + ) + { + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, RCC_PLLSOURCE_NONE); + } + + return status; +} + +#if defined(RCC_PLLSAI2_SUPPORT) + +/** + * @brief Enable PLLSAI2. + * @param PLLSAI2Init pointer to an RCC_PLLSAI2InitTypeDef structure that + * contains the configuration information for the PLLSAI2 + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RCCEx_EnablePLLSAI2(RCC_PLLSAI2InitTypeDef *PLLSAI2Init) +{ + uint32_t tickstart = 0U; + HAL_StatusTypeDef status = HAL_OK; + + /* check for PLLSAI2 Parameters used to output PLLSAI2CLK */ + assert_param(IS_RCC_PLLSAI2SOURCE(PLLSAI2Init->PLLSAI2Source)); + assert_param(IS_RCC_PLLSAI2M_VALUE(PLLSAI2Init->PLLSAI2M)); + assert_param(IS_RCC_PLLSAI2N_VALUE(PLLSAI2Init->PLLSAI2N)); + assert_param(IS_RCC_PLLSAI2P_VALUE(PLLSAI2Init->PLLSAI2P)); +#if defined(RCC_PLLSAI2Q_DIV_SUPPORT) + assert_param(IS_RCC_PLLSAI2Q_VALUE(PLLSAI2Init->PLLSAI2Q)); +#endif /* RCC_PLLSAI2Q_DIV_SUPPORT */ + assert_param(IS_RCC_PLLSAI2R_VALUE(PLLSAI2Init->PLLSAI2R)); + assert_param(IS_RCC_PLLSAI2CLOCKOUT_VALUE(PLLSAI2Init->PLLSAI2ClockOut)); + + /* Disable the PLLSAI2 */ + __HAL_RCC_PLLSAI2_DISABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till PLLSAI2 is ready to be updated */ + while(READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) != RESET) + { + if((HAL_GetTick() - tickstart) > PLLSAI2_TIMEOUT_VALUE) + { + status = HAL_TIMEOUT; + break; + } + } + + if(status == HAL_OK) + { +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) && defined(RCC_PLLSAI2Q_DIV_SUPPORT) + /* Configure the PLLSAI2 Multiplication factor N */ + /* Configure the PLLSAI2 Division factors M, P, Q and R */ + __HAL_RCC_PLLSAI2_CONFIG(PLLSAI2Init->PLLSAI2M, PLLSAI2Init->PLLSAI2N, PLLSAI2Init->PLLSAI2P, PLLSAI2Init->PLLSAI2Q, PLLSAI2Init->PLLSAI2R); +#elif defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + /* Configure the PLLSAI2 Multiplication factor N */ + /* Configure the PLLSAI2 Division factors M, P and R */ + __HAL_RCC_PLLSAI2_CONFIG(PLLSAI2Init->PLLSAI2M, PLLSAI2Init->PLLSAI2N, PLLSAI2Init->PLLSAI2P, PLLSAI2Init->PLLSAI2R); +#elif defined(RCC_PLLSAI2Q_DIV_SUPPORT) + /* Configure the PLLSAI2 Multiplication factor N */ + /* Configure the PLLSAI2 Division factors P, Q and R */ + __HAL_RCC_PLLSAI2_CONFIG(PLLSAI2Init->PLLSAI2N, PLLSAI2Init->PLLSAI2P, PLLSAI2Init->PLLSAI2Q, PLLSAI2Init->PLLSAI2R); +#else + /* Configure the PLLSAI2 Multiplication factor N */ + /* Configure the PLLSAI2 Division factors P and R */ + __HAL_RCC_PLLSAI2_CONFIG(PLLSAI2Init->PLLSAI2N, PLLSAI2Init->PLLSAI2P, PLLSAI2Init->PLLSAI2R); +#endif /* RCC_PLLSAI2M_DIV_1_16_SUPPORT && RCC_PLLSAI2Q_DIV_SUPPORT */ + /* Configure the PLLSAI2 Clock output(s) */ + __HAL_RCC_PLLSAI2CLKOUT_ENABLE(PLLSAI2Init->PLLSAI2ClockOut); + + /* Enable the PLLSAI2 again by setting PLLSAI2ON to 1*/ + __HAL_RCC_PLLSAI2_ENABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till PLLSAI2 is ready */ + while(READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) == RESET) + { + if((HAL_GetTick() - tickstart) > PLLSAI2_TIMEOUT_VALUE) + { + status = HAL_TIMEOUT; + break; + } + } + } + + return status; +} + +/** + * @brief Disable PLLISAI2. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RCCEx_DisablePLLSAI2(void) +{ + uint32_t tickstart = 0U; + HAL_StatusTypeDef status = HAL_OK; + + /* Disable the PLLSAI2 */ + __HAL_RCC_PLLSAI2_DISABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till PLLSAI2 is ready */ + while(READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) != RESET) + { + if((HAL_GetTick() - tickstart) > PLLSAI2_TIMEOUT_VALUE) + { + status = HAL_TIMEOUT; + break; + } + } + + /* Disable the PLLSAI2 Clock outputs */ +#if defined(RCC_PLLSAI2Q_DIV_SUPPORT) + __HAL_RCC_PLLSAI2CLKOUT_DISABLE(RCC_PLLSAI2CFGR_PLLSAI2PEN|RCC_PLLSAI2CFGR_PLLSAI2QEN|RCC_PLLSAI2CFGR_PLLSAI2REN); +#else + __HAL_RCC_PLLSAI2CLKOUT_DISABLE(RCC_PLLSAI2CFGR_PLLSAI2PEN|RCC_PLLSAI2CFGR_PLLSAI2REN); +#endif /* RCC_PLLSAI2M_DIV_1_16_SUPPORT && RCC_PLLSAI2Q_DIV_SUPPORT */ + + /* Reset PLL source to save power if no PLLs on */ + if((READ_BIT(RCC->CR, RCC_CR_PLLRDY) == RESET) + && + (READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) == RESET) + ) + { + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, RCC_PLLSOURCE_NONE); + } + + return status; +} + +#endif /* RCC_PLLSAI2_SUPPORT */ + +/** + * @brief Configure the oscillator clock source for wakeup from Stop and CSS backup clock. + * @param WakeUpClk Wakeup clock + * This parameter can be one of the following values: + * @arg @ref RCC_STOP_WAKEUPCLOCK_MSI MSI oscillator selection + * @arg @ref RCC_STOP_WAKEUPCLOCK_HSI HSI oscillator selection + * @note This function shall not be called after the Clock Security System on HSE has been + * enabled. + * @retval None + */ +void HAL_RCCEx_WakeUpStopCLKConfig(uint32_t WakeUpClk) +{ + assert_param(IS_RCC_STOP_WAKEUPCLOCK(WakeUpClk)); + + __HAL_RCC_WAKEUPSTOP_CLK_CONFIG(WakeUpClk); +} + +/** + * @brief Configure the MSI range after standby mode. + * @note After Standby its frequency can be selected between 4 possible values (1, 2, 4 or 8 MHz). + * @param MSIRange MSI range + * This parameter can be one of the following values: + * @arg @ref RCC_MSIRANGE_4 Range 4 around 1 MHz + * @arg @ref RCC_MSIRANGE_5 Range 5 around 2 MHz + * @arg @ref RCC_MSIRANGE_6 Range 6 around 4 MHz (reset value) + * @arg @ref RCC_MSIRANGE_7 Range 7 around 8 MHz + * @retval None + */ +void HAL_RCCEx_StandbyMSIRangeConfig(uint32_t MSIRange) +{ + assert_param(IS_RCC_MSI_STANDBY_CLOCK_RANGE(MSIRange)); + + __HAL_RCC_MSI_STANDBY_RANGE_CONFIG(MSIRange); +} + +/** + * @brief Enable the LSE Clock Security System. + * @note Prior to enable the LSE Clock Security System, LSE oscillator is to be enabled + * with HAL_RCC_OscConfig() and the LSE oscillator clock is to be selected as RTC + * clock with HAL_RCCEx_PeriphCLKConfig(). + * @retval None + */ +void HAL_RCCEx_EnableLSECSS(void) +{ + SET_BIT(RCC->BDCR, RCC_BDCR_LSECSSON) ; +} + +/** + * @brief Disable the LSE Clock Security System. + * @note LSE Clock Security System can only be disabled after a LSE failure detection. + * @retval None + */ +void HAL_RCCEx_DisableLSECSS(void) +{ + CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSECSSON) ; + + /* Disable LSE CSS IT if any */ + __HAL_RCC_DISABLE_IT(RCC_IT_LSECSS); +} + +/** + * @brief Enable the LSE Clock Security System Interrupt & corresponding EXTI line. + * @note LSE Clock Security System Interrupt is mapped on RTC EXTI line 19 + * @retval None + */ +void HAL_RCCEx_EnableLSECSS_IT(void) +{ + /* Enable LSE CSS */ + SET_BIT(RCC->BDCR, RCC_BDCR_LSECSSON) ; + + /* Enable LSE CSS IT */ + __HAL_RCC_ENABLE_IT(RCC_IT_LSECSS); + + /* Enable IT on EXTI Line 19 */ + __HAL_RCC_LSECSS_EXTI_ENABLE_IT(); + __HAL_RCC_LSECSS_EXTI_ENABLE_RISING_EDGE(); +} + +/** + * @brief Handle the RCC LSE Clock Security System interrupt request. + * @retval None + */ +void HAL_RCCEx_LSECSS_IRQHandler(void) +{ + /* Check RCC LSE CSSF flag */ + if(__HAL_RCC_GET_IT(RCC_IT_LSECSS)) + { + /* RCC LSE Clock Security System interrupt user callback */ + HAL_RCCEx_LSECSS_Callback(); + + /* Clear RCC LSE CSS pending bit */ + __HAL_RCC_CLEAR_IT(RCC_IT_LSECSS); + } +} + +/** + * @brief RCCEx LSE Clock Security System interrupt callback. + * @retval none + */ +__weak void HAL_RCCEx_LSECSS_Callback(void) +{ + /* NOTE : This function should not be modified, when the callback is needed, + the @ref HAL_RCCEx_LSECSS_Callback should be implemented in the user file + */ +} + +/** + * @brief Select the Low Speed clock source to output on LSCO pin (PA2). + * @param LSCOSource specifies the Low Speed clock source to output. + * This parameter can be one of the following values: + * @arg @ref RCC_LSCOSOURCE_LSI LSI clock selected as LSCO source + * @arg @ref RCC_LSCOSOURCE_LSE LSE clock selected as LSCO source + * @retval None + */ +void HAL_RCCEx_EnableLSCO(uint32_t LSCOSource) +{ + GPIO_InitTypeDef GPIO_InitStruct; + FlagStatus pwrclkchanged = RESET; + FlagStatus backupchanged = RESET; + + /* Check the parameters */ + assert_param(IS_RCC_LSCOSOURCE(LSCOSource)); + + /* LSCO Pin Clock Enable */ + __LSCO_CLK_ENABLE(); + + /* Configue the LSCO pin in analog mode */ + GPIO_InitStruct.Pin = LSCO_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(LSCO_GPIO_PORT, &GPIO_InitStruct); + + /* Update LSCOSEL clock source in Backup Domain control register */ + if(__HAL_RCC_PWR_IS_CLK_DISABLED()) + { + __HAL_RCC_PWR_CLK_ENABLE(); + pwrclkchanged = SET; + } + if(HAL_IS_BIT_CLR(PWR->CR1, PWR_CR1_DBP)) + { + HAL_PWR_EnableBkUpAccess(); + backupchanged = SET; + } + + MODIFY_REG(RCC->BDCR, RCC_BDCR_LSCOSEL | RCC_BDCR_LSCOEN, LSCOSource | RCC_BDCR_LSCOEN); + + if(backupchanged == SET) + { + HAL_PWR_DisableBkUpAccess(); + } + if(pwrclkchanged == SET) + { + __HAL_RCC_PWR_CLK_DISABLE(); + } +} + +/** + * @brief Disable the Low Speed clock output. + * @retval None + */ +void HAL_RCCEx_DisableLSCO(void) +{ + FlagStatus pwrclkchanged = RESET; + FlagStatus backupchanged = RESET; + + /* Update LSCOEN bit in Backup Domain control register */ + if(__HAL_RCC_PWR_IS_CLK_DISABLED()) + { + __HAL_RCC_PWR_CLK_ENABLE(); + pwrclkchanged = SET; + } + if(HAL_IS_BIT_CLR(PWR->CR1, PWR_CR1_DBP)) + { + /* Enable access to the backup domain */ + HAL_PWR_EnableBkUpAccess(); + backupchanged = SET; + } + + CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSCOEN); + + /* Restore previous configuration */ + if(backupchanged == SET) + { + /* Disable access to the backup domain */ + HAL_PWR_DisableBkUpAccess(); + } + if(pwrclkchanged == SET) + { + __HAL_RCC_PWR_CLK_DISABLE(); + } +} + +/** + * @brief Enable the PLL-mode of the MSI. + * @note Prior to enable the PLL-mode of the MSI for automatic hardware + * calibration LSE oscillator is to be enabled with HAL_RCC_OscConfig(). + * @retval None + */ +void HAL_RCCEx_EnableMSIPLLMode(void) +{ + SET_BIT(RCC->CR, RCC_CR_MSIPLLEN) ; +} + +/** + * @brief Disable the PLL-mode of the MSI. + * @note PLL-mode of the MSI is automatically reset when LSE oscillator is disabled. + * @retval None + */ +void HAL_RCCEx_DisableMSIPLLMode(void) +{ + CLEAR_BIT(RCC->CR, RCC_CR_MSIPLLEN) ; +} + +/** + * @} + */ + +#if defined(CRS) + +/** @defgroup RCCEx_Exported_Functions_Group3 Extended Clock Recovery System Control functions + * @brief Extended Clock Recovery System Control functions + * +@verbatim + =============================================================================== + ##### Extended Clock Recovery System Control functions ##### + =============================================================================== + [..] + For devices with Clock Recovery System feature (CRS), RCC Extention HAL driver can be used as follows: + + (#) In System clock config, HSI48 needs to be enabled + + (#) Enable CRS clock in IP MSP init which will use CRS functions + + (#) Call CRS functions as follows: + (##) Prepare synchronization configuration necessary for HSI48 calibration + (+++) Default values can be set for frequency Error Measurement (reload and error limit) + and also HSI48 oscillator smooth trimming. + (+++) Macro __HAL_RCC_CRS_RELOADVALUE_CALCULATE can be also used to calculate + directly reload value with target and sychronization frequencies values + (##) Call function HAL_RCCEx_CRSConfig which + (+++) Resets CRS registers to their default values. + (+++) Configures CRS registers with synchronization configuration + (+++) Enables automatic calibration and frequency error counter feature + Note: When using USB LPM (Link Power Management) and the device is in Sleep mode, the + periodic USB SOF will not be generated by the host. No SYNC signal will therefore be + provided to the CRS to calibrate the HSI48 on the run. To guarantee the required clock + precision after waking up from Sleep mode, the LSE or reference clock on the GPIOs + should be used as SYNC signal. + + (##) A polling function is provided to wait for complete synchronization + (+++) Call function HAL_RCCEx_CRSWaitSynchronization() + (+++) According to CRS status, user can decide to adjust again the calibration or continue + application if synchronization is OK + + (#) User can retrieve information related to synchronization in calling function + HAL_RCCEx_CRSGetSynchronizationInfo() + + (#) Regarding synchronization status and synchronization information, user can try a new calibration + in changing synchronization configuration and call again HAL_RCCEx_CRSConfig. + Note: When the SYNC event is detected during the downcounting phase (before reaching the zero value), + it means that the actual frequency is lower than the target (and so, that the TRIM value should be + incremented), while when it is detected during the upcounting phase it means that the actual frequency + is higher (and that the TRIM value should be decremented). + + (#) In interrupt mode, user can resort to the available macros (__HAL_RCC_CRS_XXX_IT). Interrupts will go + through CRS Handler (CRS_IRQn/CRS_IRQHandler) + (++) Call function HAL_RCCEx_CRSConfig() + (++) Enable CRS_IRQn (thanks to NVIC functions) + (++) Enable CRS interrupt (__HAL_RCC_CRS_ENABLE_IT) + (++) Implement CRS status management in the following user callbacks called from + HAL_RCCEx_CRS_IRQHandler(): + (+++) HAL_RCCEx_CRS_SyncOkCallback() + (+++) HAL_RCCEx_CRS_SyncWarnCallback() + (+++) HAL_RCCEx_CRS_ExpectedSyncCallback() + (+++) HAL_RCCEx_CRS_ErrorCallback() + + (#) To force a SYNC EVENT, user can use the function HAL_RCCEx_CRSSoftwareSynchronizationGenerate(). + This function can be called before calling HAL_RCCEx_CRSConfig (for instance in Systick handler) + +@endverbatim + * @{ + */ + +/** + * @brief Start automatic synchronization for polling mode + * @param pInit Pointer on RCC_CRSInitTypeDef structure + * @retval None + */ +void HAL_RCCEx_CRSConfig(RCC_CRSInitTypeDef *pInit) +{ + uint32_t value = 0; + + /* Check the parameters */ + assert_param(IS_RCC_CRS_SYNC_DIV(pInit->Prescaler)); + assert_param(IS_RCC_CRS_SYNC_SOURCE(pInit->Source)); + assert_param(IS_RCC_CRS_SYNC_POLARITY(pInit->Polarity)); + assert_param(IS_RCC_CRS_RELOADVALUE(pInit->ReloadValue)); + assert_param(IS_RCC_CRS_ERRORLIMIT(pInit->ErrorLimitValue)); + assert_param(IS_RCC_CRS_HSI48CALIBRATION(pInit->HSI48CalibrationValue)); + + /* CONFIGURATION */ + + /* Before configuration, reset CRS registers to their default values*/ + __HAL_RCC_CRS_FORCE_RESET(); + __HAL_RCC_CRS_RELEASE_RESET(); + + /* Set the SYNCDIV[2:0] bits according to Prescaler value */ + /* Set the SYNCSRC[1:0] bits according to Source value */ + /* Set the SYNCSPOL bit according to Polarity value */ + value = (pInit->Prescaler | pInit->Source | pInit->Polarity); + /* Set the RELOAD[15:0] bits according to ReloadValue value */ + value |= pInit->ReloadValue; + /* Set the FELIM[7:0] bits according to ErrorLimitValue value */ + value |= (pInit->ErrorLimitValue << CRS_CFGR_FELIM_Pos); + WRITE_REG(CRS->CFGR, value); + + /* Adjust HSI48 oscillator smooth trimming */ + /* Set the TRIM[5:0] bits according to RCC_CRS_HSI48CalibrationValue value */ + MODIFY_REG(CRS->CR, CRS_CR_TRIM, (pInit->HSI48CalibrationValue << CRS_CR_TRIM_Pos)); + + /* START AUTOMATIC SYNCHRONIZATION*/ + + /* Enable Automatic trimming & Frequency error counter */ + SET_BIT(CRS->CR, CRS_CR_AUTOTRIMEN | CRS_CR_CEN); +} + +/** + * @brief Generate the software synchronization event + * @retval None + */ +void HAL_RCCEx_CRSSoftwareSynchronizationGenerate(void) +{ + SET_BIT(CRS->CR, CRS_CR_SWSYNC); +} + +/** + * @brief Return synchronization info + * @param pSynchroInfo Pointer on RCC_CRSSynchroInfoTypeDef structure + * @retval None + */ +void HAL_RCCEx_CRSGetSynchronizationInfo(RCC_CRSSynchroInfoTypeDef *pSynchroInfo) +{ + /* Check the parameter */ + assert_param(pSynchroInfo != NULL); + + /* Get the reload value */ + pSynchroInfo->ReloadValue = (READ_BIT(CRS->CFGR, CRS_CFGR_RELOAD)); + + /* Get HSI48 oscillator smooth trimming */ + pSynchroInfo->HSI48CalibrationValue = (READ_BIT(CRS->CR, CRS_CR_TRIM) >> CRS_CR_TRIM_Pos); + + /* Get Frequency error capture */ + pSynchroInfo->FreqErrorCapture = (READ_BIT(CRS->ISR, CRS_ISR_FECAP) >> CRS_ISR_FECAP_Pos); + + /* Get Frequency error direction */ + pSynchroInfo->FreqErrorDirection = (READ_BIT(CRS->ISR, CRS_ISR_FEDIR)); +} + +/** +* @brief Wait for CRS Synchronization status. +* @param Timeout Duration of the timeout +* @note Timeout is based on the maximum time to receive a SYNC event based on synchronization +* frequency. +* @note If Timeout set to HAL_MAX_DELAY, HAL_TIMEOUT will be never returned. +* @retval Combination of Synchronization status +* This parameter can be a combination of the following values: +* @arg @ref RCC_CRS_TIMEOUT +* @arg @ref RCC_CRS_SYNCOK +* @arg @ref RCC_CRS_SYNCWARN +* @arg @ref RCC_CRS_SYNCERR +* @arg @ref RCC_CRS_SYNCMISS +* @arg @ref RCC_CRS_TRIMOVF +*/ +uint32_t HAL_RCCEx_CRSWaitSynchronization(uint32_t Timeout) +{ + uint32_t crsstatus = RCC_CRS_NONE; + uint32_t tickstart = 0U; + + /* Get timeout */ + tickstart = HAL_GetTick(); + + /* Wait for CRS flag or timeout detection */ + do + { + if(Timeout != HAL_MAX_DELAY) + { + if((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout)) + { + crsstatus = RCC_CRS_TIMEOUT; + } + } + /* Check CRS SYNCOK flag */ + if(__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_SYNCOK)) + { + /* CRS SYNC event OK */ + crsstatus |= RCC_CRS_SYNCOK; + + /* Clear CRS SYNC event OK bit */ + __HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_SYNCOK); + } + + /* Check CRS SYNCWARN flag */ + if(__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_SYNCWARN)) + { + /* CRS SYNC warning */ + crsstatus |= RCC_CRS_SYNCWARN; + + /* Clear CRS SYNCWARN bit */ + __HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_SYNCWARN); + } + + /* Check CRS TRIM overflow flag */ + if(__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_TRIMOVF)) + { + /* CRS SYNC Error */ + crsstatus |= RCC_CRS_TRIMOVF; + + /* Clear CRS Error bit */ + __HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_TRIMOVF); + } + + /* Check CRS Error flag */ + if(__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_SYNCERR)) + { + /* CRS SYNC Error */ + crsstatus |= RCC_CRS_SYNCERR; + + /* Clear CRS Error bit */ + __HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_SYNCERR); + } + + /* Check CRS SYNC Missed flag */ + if(__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_SYNCMISS)) + { + /* CRS SYNC Missed */ + crsstatus |= RCC_CRS_SYNCMISS; + + /* Clear CRS SYNC Missed bit */ + __HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_SYNCMISS); + } + + /* Check CRS Expected SYNC flag */ + if(__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_ESYNC)) + { + /* frequency error counter reached a zero value */ + __HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_ESYNC); + } + } while(RCC_CRS_NONE == crsstatus); + + return crsstatus; +} + +/** + * @brief Handle the Clock Recovery System interrupt request. + * @retval None + */ +void HAL_RCCEx_CRS_IRQHandler(void) +{ + uint32_t crserror = RCC_CRS_NONE; + /* Get current IT flags and IT sources values */ + uint32_t itflags = READ_REG(CRS->ISR); + uint32_t itsources = READ_REG(CRS->CR); + + /* Check CRS SYNCOK flag */ + if(((itflags & RCC_CRS_FLAG_SYNCOK) != RESET) && ((itsources & RCC_CRS_IT_SYNCOK) != RESET)) + { + /* Clear CRS SYNC event OK flag */ + WRITE_REG(CRS->ICR, CRS_ICR_SYNCOKC); + + /* user callback */ + HAL_RCCEx_CRS_SyncOkCallback(); + } + /* Check CRS SYNCWARN flag */ + else if(((itflags & RCC_CRS_FLAG_SYNCWARN) != RESET) && ((itsources & RCC_CRS_IT_SYNCWARN) != RESET)) + { + /* Clear CRS SYNCWARN flag */ + WRITE_REG(CRS->ICR, CRS_ICR_SYNCWARNC); + + /* user callback */ + HAL_RCCEx_CRS_SyncWarnCallback(); + } + /* Check CRS Expected SYNC flag */ + else if(((itflags & RCC_CRS_FLAG_ESYNC) != RESET) && ((itsources & RCC_CRS_IT_ESYNC) != RESET)) + { + /* frequency error counter reached a zero value */ + WRITE_REG(CRS->ICR, CRS_ICR_ESYNCC); + + /* user callback */ + HAL_RCCEx_CRS_ExpectedSyncCallback(); + } + /* Check CRS Error flags */ + else + { + if(((itflags & RCC_CRS_FLAG_ERR) != RESET) && ((itsources & RCC_CRS_IT_ERR) != RESET)) + { + if((itflags & RCC_CRS_FLAG_SYNCERR) != RESET) + { + crserror |= RCC_CRS_SYNCERR; + } + if((itflags & RCC_CRS_FLAG_SYNCMISS) != RESET) + { + crserror |= RCC_CRS_SYNCMISS; + } + if((itflags & RCC_CRS_FLAG_TRIMOVF) != RESET) + { + crserror |= RCC_CRS_TRIMOVF; + } + + /* Clear CRS Error flags */ + WRITE_REG(CRS->ICR, CRS_ICR_ERRC); + + /* user error callback */ + HAL_RCCEx_CRS_ErrorCallback(crserror); + } + } +} + +/** + * @brief RCCEx Clock Recovery System SYNCOK interrupt callback. + * @retval none + */ +__weak void HAL_RCCEx_CRS_SyncOkCallback(void) +{ + /* NOTE : This function should not be modified, when the callback is needed, + the @ref HAL_RCCEx_CRS_SyncOkCallback should be implemented in the user file + */ +} + +/** + * @brief RCCEx Clock Recovery System SYNCWARN interrupt callback. + * @retval none + */ +__weak void HAL_RCCEx_CRS_SyncWarnCallback(void) +{ + /* NOTE : This function should not be modified, when the callback is needed, + the @ref HAL_RCCEx_CRS_SyncWarnCallback should be implemented in the user file + */ +} + +/** + * @brief RCCEx Clock Recovery System Expected SYNC interrupt callback. + * @retval none + */ +__weak void HAL_RCCEx_CRS_ExpectedSyncCallback(void) +{ + /* NOTE : This function should not be modified, when the callback is needed, + the @ref HAL_RCCEx_CRS_ExpectedSyncCallback should be implemented in the user file + */ +} + +/** + * @brief RCCEx Clock Recovery System Error interrupt callback. + * @param Error Combination of Error status. + * This parameter can be a combination of the following values: + * @arg @ref RCC_CRS_SYNCERR + * @arg @ref RCC_CRS_SYNCMISS + * @arg @ref RCC_CRS_TRIMOVF + * @retval none + */ +__weak void HAL_RCCEx_CRS_ErrorCallback(uint32_t Error) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(Error); + + /* NOTE : This function should not be modified, when the callback is needed, + the @ref HAL_RCCEx_CRS_ErrorCallback should be implemented in the user file + */ +} + +/** + * @} + */ + +#endif /* CRS */ + +/** + * @} + */ + +/** @addtogroup RCCEx_Private_Functions + * @{ + */ + +/** + * @brief Configure the parameters N & P & optionally M of PLLSAI1 and enable PLLSAI1 output clock(s). + * @param PllSai1 pointer to an RCC_PLLSAI1InitTypeDef structure that + * contains the configuration parameters N & P & optionally M as well as PLLSAI1 output clock(s) + * @param Divider divider parameter to be updated + * + * @note PLLSAI1 is temporary disable to apply new parameters + * + * @retval HAL status + */ +static HAL_StatusTypeDef RCCEx_PLLSAI1_Config(RCC_PLLSAI1InitTypeDef *PllSai1, uint32_t Divider) +{ + uint32_t tickstart = 0U; + HAL_StatusTypeDef status = HAL_OK; + + /* check for PLLSAI1 Parameters used to output PLLSAI1CLK */ + /* P, Q and R dividers are verified in each specific divider case below */ + assert_param(IS_RCC_PLLSAI1SOURCE(PllSai1->PLLSAI1Source)); + assert_param(IS_RCC_PLLSAI1M_VALUE(PllSai1->PLLSAI1M)); + assert_param(IS_RCC_PLLSAI1N_VALUE(PllSai1->PLLSAI1N)); + assert_param(IS_RCC_PLLSAI1CLOCKOUT_VALUE(PllSai1->PLLSAI1ClockOut)); + + /* Check that PLLSAI1 clock source and divider M can be applied */ + if(__HAL_RCC_GET_PLL_OSCSOURCE() != RCC_PLLSOURCE_NONE) + { + /* PLL clock source and divider M already set, check that no request for change */ + if((__HAL_RCC_GET_PLL_OSCSOURCE() != PllSai1->PLLSAI1Source) + || + (PllSai1->PLLSAI1Source == RCC_PLLSOURCE_NONE) +#if !defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + || + (((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U) != PllSai1->PLLSAI1M) +#endif + ) + { + status = HAL_ERROR; + } + } + else + { + /* Check PLLSAI1 clock source availability */ + switch(PllSai1->PLLSAI1Source) + { + case RCC_PLLSOURCE_MSI: + if(HAL_IS_BIT_CLR(RCC->CR, RCC_CR_MSIRDY)) + { + status = HAL_ERROR; + } + break; + case RCC_PLLSOURCE_HSI: + if(HAL_IS_BIT_CLR(RCC->CR, RCC_CR_HSIRDY)) + { + status = HAL_ERROR; + } + break; + case RCC_PLLSOURCE_HSE: + if(HAL_IS_BIT_CLR(RCC->CR, RCC_CR_HSERDY) && HAL_IS_BIT_CLR(RCC->CR, RCC_CR_HSEBYP)) + { + status = HAL_ERROR; + } + break; + default: + status = HAL_ERROR; + break; + } + + if(status == HAL_OK) + { +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + /* Set PLLSAI1 clock source */ + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, PllSai1->PLLSAI1Source); +#else + /* Set PLLSAI1 clock source and divider M */ + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC | RCC_PLLCFGR_PLLM, PllSai1->PLLSAI1Source | (PllSai1->PLLSAI1M - 1U) << RCC_PLLCFGR_PLLM_Pos); +#endif + } + } + + if(status == HAL_OK) + { + /* Disable the PLLSAI1 */ + __HAL_RCC_PLLSAI1_DISABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till PLLSAI1 is ready to be updated */ + while(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) != RESET) + { + if((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE) + { + status = HAL_TIMEOUT; + break; + } + } + + if(status == HAL_OK) + { + if(Divider == DIVIDER_P_UPDATE) + { + assert_param(IS_RCC_PLLSAI1P_VALUE(PllSai1->PLLSAI1P)); +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + + /* Configure the PLLSAI1 Division factor M, P and Multiplication factor N*/ +#if defined(RCC_PLLSAI1P_DIV_2_31_SUPPORT) + MODIFY_REG(RCC->PLLSAI1CFGR, + RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1PDIV | RCC_PLLSAI1CFGR_PLLSAI1M, + (PllSai1->PLLSAI1N << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) | + (PllSai1->PLLSAI1P << RCC_PLLSAI1CFGR_PLLSAI1PDIV_Pos) | + ((PllSai1->PLLSAI1M - 1U) << RCC_PLLSAI1CFGR_PLLSAI1M_Pos)); +#else + MODIFY_REG(RCC->PLLSAI1CFGR, + RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1P | RCC_PLLSAI1CFGR_PLLSAI1M, + (PllSai1->PLLSAI1N << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) | + ((PllSai1->PLLSAI1P >> 4U) << RCC_PLLSAI1CFGR_PLLSAI1P_Pos) | + ((PllSai1->PLLSAI1M - 1U) << RCC_PLLSAI1CFGR_PLLSAI1M_Pos)); +#endif /* RCC_PLLSAI1P_DIV_2_31_SUPPORT */ + +#else + /* Configure the PLLSAI1 Division factor P and Multiplication factor N*/ +#if defined(RCC_PLLSAI1P_DIV_2_31_SUPPORT) + MODIFY_REG(RCC->PLLSAI1CFGR, + RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1PDIV, + (PllSai1->PLLSAI1N << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) | + (PllSai1->PLLSAI1P << RCC_PLLSAI1CFGR_PLLSAI1PDIV_Pos)); +#else + MODIFY_REG(RCC->PLLSAI1CFGR, + RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1P, + (PllSai1->PLLSAI1N << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) | + ((PllSai1->PLLSAI1P >> 4U) << RCC_PLLSAI1CFGR_PLLSAI1P_Pos)); +#endif /* RCC_PLLSAI1P_DIV_2_31_SUPPORT */ + +#endif /* RCC_PLLSAI1M_DIV_1_16_SUPPORT */ + } + else if(Divider == DIVIDER_Q_UPDATE) + { + assert_param(IS_RCC_PLLSAI1Q_VALUE(PllSai1->PLLSAI1Q)); +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + /* Configure the PLLSAI1 Division factor M, Q and Multiplication factor N*/ + MODIFY_REG(RCC->PLLSAI1CFGR, + RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1Q | RCC_PLLSAI1CFGR_PLLSAI1M, + (PllSai1->PLLSAI1N << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) | + (((PllSai1->PLLSAI1Q >> 1U) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1Q_Pos) | + ((PllSai1->PLLSAI1M - 1U) << RCC_PLLSAI1CFGR_PLLSAI1M_Pos)); +#else + /* Configure the PLLSAI1 Division factor Q and Multiplication factor N*/ + MODIFY_REG(RCC->PLLSAI1CFGR, + RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1Q, + (PllSai1->PLLSAI1N << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) | + (((PllSai1->PLLSAI1Q >> 1U) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1Q_Pos)); +#endif /* RCC_PLLSAI1M_DIV_1_16_SUPPORT */ + } + else + { + assert_param(IS_RCC_PLLSAI1R_VALUE(PllSai1->PLLSAI1R)); +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + /* Configure the PLLSAI1 Division factor M, R and Multiplication factor N*/ + MODIFY_REG(RCC->PLLSAI1CFGR, + RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1R | RCC_PLLSAI1CFGR_PLLSAI1M, + (PllSai1->PLLSAI1N << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) | + (((PllSai1->PLLSAI1R >> 1U) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1R_Pos) | + ((PllSai1->PLLSAI1M - 1U) << RCC_PLLSAI1CFGR_PLLSAI1M_Pos)); +#else + /* Configure the PLLSAI1 Division factor R and Multiplication factor N*/ + MODIFY_REG(RCC->PLLSAI1CFGR, + RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1R, + (PllSai1->PLLSAI1N << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) | + (((PllSai1->PLLSAI1R >> 1U) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1R_Pos)); +#endif /* RCC_PLLSAI1M_DIV_1_16_SUPPORT */ + } + + /* Enable the PLLSAI1 again by setting PLLSAI1ON to 1*/ + __HAL_RCC_PLLSAI1_ENABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till PLLSAI1 is ready */ + while(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) == RESET) + { + if((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE) + { + status = HAL_TIMEOUT; + break; + } + } + + if(status == HAL_OK) + { + /* Configure the PLLSAI1 Clock output(s) */ + __HAL_RCC_PLLSAI1CLKOUT_ENABLE(PllSai1->PLLSAI1ClockOut); + } + } + } + + return status; +} + +#if defined(RCC_PLLSAI2_SUPPORT) + +/** + * @brief Configure the parameters N & P & optionally M of PLLSAI2 and enable PLLSAI2 output clock(s). + * @param PllSai2 pointer to an RCC_PLLSAI2InitTypeDef structure that + * contains the configuration parameters N & P & optionally M as well as PLLSAI2 output clock(s) + * @param Divider divider parameter to be updated + * + * @note PLLSAI2 is temporary disable to apply new parameters + * + * @retval HAL status + */ +static HAL_StatusTypeDef RCCEx_PLLSAI2_Config(RCC_PLLSAI2InitTypeDef *PllSai2, uint32_t Divider) +{ + uint32_t tickstart = 0U; + HAL_StatusTypeDef status = HAL_OK; + + /* check for PLLSAI2 Parameters used to output PLLSAI2CLK */ + /* P, Q and R dividers are verified in each specific divider case below */ + assert_param(IS_RCC_PLLSAI2SOURCE(PllSai2->PLLSAI2Source)); + assert_param(IS_RCC_PLLSAI2M_VALUE(PllSai2->PLLSAI2M)); + assert_param(IS_RCC_PLLSAI2N_VALUE(PllSai2->PLLSAI2N)); + assert_param(IS_RCC_PLLSAI2CLOCKOUT_VALUE(PllSai2->PLLSAI2ClockOut)); + + /* Check that PLLSAI2 clock source and divider M can be applied */ + if(__HAL_RCC_GET_PLL_OSCSOURCE() != RCC_PLLSOURCE_NONE) + { + /* PLL clock source and divider M already set, check that no request for change */ + if((__HAL_RCC_GET_PLL_OSCSOURCE() != PllSai2->PLLSAI2Source) + || + (PllSai2->PLLSAI2Source == RCC_PLLSOURCE_NONE) +#if !defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + || + (((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U) != PllSai2->PLLSAI2M) +#endif + ) + { + status = HAL_ERROR; + } + } + else + { + /* Check PLLSAI2 clock source availability */ + switch(PllSai2->PLLSAI2Source) + { + case RCC_PLLSOURCE_MSI: + if(HAL_IS_BIT_CLR(RCC->CR, RCC_CR_MSIRDY)) + { + status = HAL_ERROR; + } + break; + case RCC_PLLSOURCE_HSI: + if(HAL_IS_BIT_CLR(RCC->CR, RCC_CR_HSIRDY)) + { + status = HAL_ERROR; + } + break; + case RCC_PLLSOURCE_HSE: + if(HAL_IS_BIT_CLR(RCC->CR, RCC_CR_HSERDY) && HAL_IS_BIT_CLR(RCC->CR, RCC_CR_HSEBYP)) + { + status = HAL_ERROR; + } + break; + default: + status = HAL_ERROR; + break; + } + + if(status == HAL_OK) + { +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + /* Set PLLSAI2 clock source */ + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, PllSai2->PLLSAI2Source); +#else + /* Set PLLSAI2 clock source and divider M */ + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC | RCC_PLLCFGR_PLLM, PllSai2->PLLSAI2Source | (PllSai2->PLLSAI2M - 1U) << RCC_PLLCFGR_PLLM_Pos); +#endif + } + } + + if(status == HAL_OK) + { + /* Disable the PLLSAI2 */ + __HAL_RCC_PLLSAI2_DISABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till PLLSAI2 is ready to be updated */ + while(READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) != RESET) + { + if((HAL_GetTick() - tickstart) > PLLSAI2_TIMEOUT_VALUE) + { + status = HAL_TIMEOUT; + break; + } + } + + if(status == HAL_OK) + { + if(Divider == DIVIDER_P_UPDATE) + { + assert_param(IS_RCC_PLLSAI2P_VALUE(PllSai2->PLLSAI2P)); +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + + /* Configure the PLLSAI2 Division factor M, P and Multiplication factor N*/ +#if defined(RCC_PLLSAI2P_DIV_2_31_SUPPORT) + MODIFY_REG(RCC->PLLSAI2CFGR, + RCC_PLLSAI2CFGR_PLLSAI2N | RCC_PLLSAI2CFGR_PLLSAI2PDIV | RCC_PLLSAI2CFGR_PLLSAI2M, + (PllSai2->PLLSAI2N << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | + (PllSai2->PLLSAI2P << RCC_PLLSAI2CFGR_PLLSAI2PDIV_Pos) | + ((PllSai2->PLLSAI2M - 1U) << RCC_PLLSAI2CFGR_PLLSAI2M_Pos)); +#else + MODIFY_REG(RCC->PLLSAI2CFGR, + RCC_PLLSAI2CFGR_PLLSAI2N | RCC_PLLSAI2CFGR_PLLSAI2P | RCC_PLLSAI2CFGR_PLLSAI2M, + (PllSai2->PLLSAI2N << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | + ((PllSai2->PLLSAI2P >> 4U) << RCC_PLLSAI2CFGR_PLLSAI2P_Pos) | + ((PllSai2->PLLSAI2M - 1U) << RCC_PLLSAI2CFGR_PLLSAI2M_Pos)); +#endif /* RCC_PLLSAI2P_DIV_2_31_SUPPORT */ + +#else + /* Configure the PLLSAI2 Division factor P and Multiplication factor N*/ +#if defined(RCC_PLLSAI2P_DIV_2_31_SUPPORT) + MODIFY_REG(RCC->PLLSAI2CFGR, + RCC_PLLSAI2CFGR_PLLSAI2N | RCC_PLLSAI2CFGR_PLLSAI2PDIV, + (PllSai2->PLLSAI2N << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | + (PllSai2->PLLSAI2P << RCC_PLLSAI2CFGR_PLLSAI2PDIV_Pos)); +#else + MODIFY_REG(RCC->PLLSAI2CFGR, + RCC_PLLSAI2CFGR_PLLSAI2N | RCC_PLLSAI2CFGR_PLLSAI2P, + (PllSai2->PLLSAI2N << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | + ((PllSai2->PLLSAI2P >> 4U) << RCC_PLLSAI2CFGR_PLLSAI2P_Pos)); +#endif /* RCC_PLLSAI2P_DIV_2_31_SUPPORT */ + +#endif /* RCC_PLLSAI2M_DIV_1_16_SUPPORT */ + } +#if defined(RCC_PLLSAI2Q_DIV_SUPPORT) + else if(Divider == DIVIDER_Q_UPDATE) + { + assert_param(IS_RCC_PLLSAI2Q_VALUE(PllSai2->PLLSAI2Q)); +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + /* Configure the PLLSAI2 Division factor M, Q and Multiplication factor N*/ + MODIFY_REG(RCC->PLLSAI2CFGR, + RCC_PLLSAI2CFGR_PLLSAI2N | RCC_PLLSAI2CFGR_PLLSAI2Q | RCC_PLLSAI2CFGR_PLLSAI2M, + (PllSai2->PLLSAI2N << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | + (((PllSai2->PLLSAI2Q >> 1U) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2Q_Pos) | + ((PllSai2->PLLSAI2M - 1U) << RCC_PLLSAI2CFGR_PLLSAI2M_Pos)); +#else + /* Configure the PLLSAI2 Division factor Q and Multiplication factor N*/ + MODIFY_REG(RCC->PLLSAI2CFGR, + RCC_PLLSAI2CFGR_PLLSAI2N | RCC_PLLSAI2CFGR_PLLSAI2Q, + (PllSai2->PLLSAI2N << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | + (((PllSai2->PLLSAI2Q >> 1U) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2Q_Pos)); +#endif /* RCC_PLLSAI2M_DIV_1_16_SUPPORT */ + } +#endif /* RCC_PLLSAI2Q_DIV_SUPPORT */ + else + { + assert_param(IS_RCC_PLLSAI2R_VALUE(PllSai2->PLLSAI2R)); +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + /* Configure the PLLSAI2 Division factor M, R and Multiplication factor N*/ + MODIFY_REG(RCC->PLLSAI2CFGR, + RCC_PLLSAI2CFGR_PLLSAI2N | RCC_PLLSAI2CFGR_PLLSAI2R | RCC_PLLSAI2CFGR_PLLSAI2M, + (PllSai2->PLLSAI2N << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | + (((PllSai2->PLLSAI2R >> 1U) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2R_Pos) | + ((PllSai2->PLLSAI2M - 1U) << RCC_PLLSAI2CFGR_PLLSAI2M_Pos)); +#else + /* Configure the PLLSAI2 Division factor R and Multiplication factor N*/ + MODIFY_REG(RCC->PLLSAI2CFGR, + RCC_PLLSAI2CFGR_PLLSAI2N | RCC_PLLSAI2CFGR_PLLSAI2R, + (PllSai2->PLLSAI2N << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | + (((PllSai2->PLLSAI2R >> 1U) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2R_Pos)); +#endif /* RCC_PLLSAI2M_DIV_1_16_SUPPORT */ + } + + /* Enable the PLLSAI2 again by setting PLLSAI2ON to 1*/ + __HAL_RCC_PLLSAI2_ENABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till PLLSAI2 is ready */ + while(READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) == RESET) + { + if((HAL_GetTick() - tickstart) > PLLSAI2_TIMEOUT_VALUE) + { + status = HAL_TIMEOUT; + break; + } + } + + if(status == HAL_OK) + { + /* Configure the PLLSAI2 Clock output(s) */ + __HAL_RCC_PLLSAI2CLKOUT_ENABLE(PllSai2->PLLSAI2ClockOut); + } + } + } + + return status; +} + +#endif /* RCC_PLLSAI2_SUPPORT */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* HAL_RCC_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rng.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rng.c new file mode 100644 index 0000000..b5df280 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rng.c @@ -0,0 +1,527 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_rng.c + * @author MCD Application Team + * @brief RNG HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Random Number Generator (RNG) peripheral: + * + Initialization/de-initialization functions + * + Peripheral Control functions + * + Peripheral State functions + * + @verbatim + ============================================================================== + ##### How to use this driver ##### + ============================================================================== + [..] + The RNG HAL driver can be used as follows: + + (#) Enable the RNG controller clock using __HAL_RCC_RNG_CLK_ENABLE() macro + in HAL_RNG_MspInit(). + (#) Activate the RNG peripheral using HAL_RNG_Init() function. + (#) Wait until the 32-bit Random Number Generator contains a valid + random data using (polling/interrupt) mode. + (#) Get the 32 bit random number using HAL_RNG_GenerateRandomNumber() function. + + @endverbatim + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup RNG RNG + * @brief RNG HAL module driver. + * @{ + */ + +#ifdef HAL_RNG_MODULE_ENABLED + + + +/* Private types -------------------------------------------------------------*/ +/* Private defines -----------------------------------------------------------*/ +/** @defgroup RNG_Private_Constants RNG_Private_Constants + * @{ + */ +#define RNG_TIMEOUT_VALUE 2 +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/** @addtogroup RNG_Exported_Functions + * @{ + */ + +/** @addtogroup RNG_Exported_Functions_Group1 + * @brief Initialization and de-initialization functions + * +@verbatim + =============================================================================== + ##### Initialization and de-initialization functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Initialize the RNG according to the specified parameters + in the RNG_InitTypeDef and create the associated handle + (+) DeInitialize the RNG peripheral + (+) Initialize the RNG MSP (MCU Specific Package) + (+) DeInitialize the RNG MSP + +@endverbatim + * @{ + */ + +/** + * @brief Initialize the RNG peripheral and initialize the associated handle. + * @param hrng: pointer to a RNG_HandleTypeDef structure. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RNG_Init(RNG_HandleTypeDef *hrng) +{ + /* Check the RNG handle allocation */ + if(hrng == NULL) + { + return HAL_ERROR; + } + + assert_param(IS_RNG_ALL_INSTANCE(hrng->Instance)); +#if defined(RNG_CR_CED) + assert_param(IS_RNG_CED(hrng->Init.ClockErrorDetection)); +#endif /* defined(RNG_CR_CED) */ + + if(hrng->State == HAL_RNG_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hrng->Lock = HAL_UNLOCKED; + + /* Init the low level hardware */ + HAL_RNG_MspInit(hrng); + } + + /* Change RNG peripheral state */ + hrng->State = HAL_RNG_STATE_BUSY; + +#if defined(RNG_CR_CED) + /* Clock Error Detection configuration */ + MODIFY_REG(hrng->Instance->CR, RNG_CR_CED, hrng->Init.ClockErrorDetection); +#endif /* defined(RNG_CR_CED) */ + + /* Enable the RNG Peripheral */ + __HAL_RNG_ENABLE(hrng); + + /* Initialize the RNG state */ + hrng->State = HAL_RNG_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief DeInitialize the RNG peripheral. + * @param hrng: pointer to a RNG_HandleTypeDef structure. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RNG_DeInit(RNG_HandleTypeDef *hrng) +{ + /* Check the RNG handle allocation */ + if(hrng == NULL) + { + return HAL_ERROR; + } + +#if defined(RNG_CR_CED) + /* Clear Clock Error Detection bit */ + CLEAR_BIT(hrng->Instance->CR, RNG_CR_CED); +#endif /* defined(RNG_CR_CED) */ + + /* Disable the RNG Peripheral */ + CLEAR_BIT(hrng->Instance->CR, RNG_CR_IE | RNG_CR_RNGEN); + + /* Clear RNG interrupt status flags */ + CLEAR_BIT(hrng->Instance->SR, RNG_SR_CEIS | RNG_SR_SEIS); + + /* DeInit the low level hardware */ + HAL_RNG_MspDeInit(hrng); + + /* Update the RNG state */ + hrng->State = HAL_RNG_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(hrng); + + /* Return the function status */ + return HAL_OK; +} + +/** + * @brief Initialize the RNG MSP. + * @param hrng: pointer to a RNG_HandleTypeDef structure. + * @retval None + */ +__weak void HAL_RNG_MspInit(RNG_HandleTypeDef *hrng) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hrng); + + /* NOTE : This function should not be modified. When the callback is needed, + function HAL_RNG_MspInit must be implemented in the user file. + */ +} + +/** + * @brief DeInitialize the RNG MSP. + * @param hrng: pointer to a RNG_HandleTypeDef structure. + * @retval None + */ +__weak void HAL_RNG_MspDeInit(RNG_HandleTypeDef *hrng) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hrng); + + /* NOTE : This function should not be modified. When the callback is needed, + function HAL_RNG_MspDeInit must be implemented in the user file. + */ +} + +/** + * @} + */ + +/** @addtogroup RNG_Exported_Functions_Group2 + * @brief Management functions. + * +@verbatim + =============================================================================== + ##### Peripheral Control functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Get the 32 bit Random number + (+) Get the 32 bit Random number with interrupt enabled + (+) Handle RNG interrupt request + +@endverbatim + * @{ + */ + +/** + * @brief Generate a 32-bit random number. + * @note Each time the random number data is read the RNG_FLAG_DRDY flag + * is automatically cleared. + * @param hrng: pointer to a RNG_HandleTypeDef structure. + * @param random32bit: pointer to generated random number variable if successful. + * @retval HAL status + */ + +HAL_StatusTypeDef HAL_RNG_GenerateRandomNumber(RNG_HandleTypeDef *hrng, uint32_t *random32bit) +{ + uint32_t tickstart = 0; + HAL_StatusTypeDef status = HAL_OK; + + /* Process Locked */ + __HAL_LOCK(hrng); + + /* Check RNS peripheral state */ + if(hrng->State == HAL_RNG_STATE_READY) + { + /* Change RNG peripheral state */ + hrng->State = HAL_RNG_STATE_BUSY; + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Check if data register contains valid random data */ + while(__HAL_RNG_GET_FLAG(hrng, RNG_FLAG_DRDY) == RESET) + { + if((HAL_GetTick() - tickstart ) > RNG_TIMEOUT_VALUE) + { + hrng->State = HAL_RNG_STATE_ERROR; + + /* Process Unlocked */ + __HAL_UNLOCK(hrng); + + return HAL_TIMEOUT; + } + } + + /* Get a 32bit Random number */ + hrng->RandomNumber = hrng->Instance->DR; + *random32bit = hrng->RandomNumber; + + hrng->State = HAL_RNG_STATE_READY; + } + else + { + status = HAL_ERROR; + } + + /* Process Unlocked */ + __HAL_UNLOCK(hrng); + + return status; +} + +/** + * @brief Generate a 32-bit random number in interrupt mode. + * @param hrng: pointer to a RNG_HandleTypeDef structure. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RNG_GenerateRandomNumber_IT(RNG_HandleTypeDef *hrng) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process Locked */ + __HAL_LOCK(hrng); + + /* Check RNG peripheral state */ + if(hrng->State == HAL_RNG_STATE_READY) + { + /* Change RNG peripheral state */ + hrng->State = HAL_RNG_STATE_BUSY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrng); + + /* Enable the RNG Interrupts: Data Ready, Clock error, Seed error */ + __HAL_RNG_ENABLE_IT(hrng); + } + else + { + /* Process Unlocked */ + __HAL_UNLOCK(hrng); + + status = HAL_ERROR; + } + + return status; +} + +/** + * @brief Handle RNG interrupt request. + * @note In the case of a clock error, the RNG is no more able to generate + * random numbers because the PLL48CLK clock is not correct. User has + * to check that the clock controller is correctly configured to provide + * the RNG clock and clear the CEIS bit using __HAL_RNG_CLEAR_IT(). + * The clock error has no impact on the previously generated + * random numbers, and the RNG_DR register contents can be used. + * @note In the case of a seed error, the generation of random numbers is + * interrupted as long as the SECS bit is '1'. If a number is + * available in the RNG_DR register, it must not be used because it may + * not have enough entropy. In this case, it is recommended to clear the + * SEIS bit using __HAL_RNG_CLEAR_IT(), then disable and enable + * the RNG peripheral to reinitialize and restart the RNG. + * @note User-written HAL_RNG_ErrorCallback() API is called once whether SEIS + * or CEIS are set. + * @param hrng: pointer to a RNG_HandleTypeDef structure. + * @retval None + + */ +void HAL_RNG_IRQHandler(RNG_HandleTypeDef *hrng) +{ + /* RNG clock error interrupt occurred */ + if((__HAL_RNG_GET_IT(hrng, RNG_IT_CEI) != RESET) || (__HAL_RNG_GET_IT(hrng, RNG_IT_SEI) != RESET)) + { + /* Change RNG peripheral state */ + hrng->State = HAL_RNG_STATE_ERROR; + + HAL_RNG_ErrorCallback(hrng); + + /* Clear the clock error flag */ + __HAL_RNG_CLEAR_IT(hrng, RNG_IT_CEI|RNG_IT_SEI); + + } + + /* Check RNG data ready interrupt occurred */ + if(__HAL_RNG_GET_IT(hrng, RNG_IT_DRDY) != RESET) + { + /* Generate random number once, so disable the IT */ + __HAL_RNG_DISABLE_IT(hrng); + + /* Get the 32bit Random number (DRDY flag automatically cleared) */ + hrng->RandomNumber = hrng->Instance->DR; + + if(hrng->State != HAL_RNG_STATE_ERROR) + { + /* Change RNG peripheral state */ + hrng->State = HAL_RNG_STATE_READY; + + /* Data Ready callback */ + HAL_RNG_ReadyDataCallback(hrng, hrng->RandomNumber); + } + } +} + +/** + * @brief Return generated random number in polling mode (Obsolete). + * @note Use HAL_RNG_GenerateRandomNumber() API instead. + * @param hrng: pointer to a RNG_HandleTypeDef structure that contains + * the configuration information for RNG. + * @retval random value + */ +uint32_t HAL_RNG_GetRandomNumber(RNG_HandleTypeDef *hrng) +{ + if(HAL_RNG_GenerateRandomNumber(hrng, &(hrng->RandomNumber)) == HAL_OK) + { + return hrng->RandomNumber; + } + else + { + return 0; + } +} + + +/** + * @brief Return a 32-bit random number with interrupt enabled (Obsolete). + * @note Use HAL_RNG_GenerateRandomNumber_IT() API instead. + * @param hrng: RNG handle + * @retval 32-bit random number + */ +uint32_t HAL_RNG_GetRandomNumber_IT(RNG_HandleTypeDef *hrng) +{ + uint32_t random32bit = 0; + + /* Process locked */ + __HAL_LOCK(hrng); + + /* Change RNG peripheral state */ + hrng->State = HAL_RNG_STATE_BUSY; + + /* Get a 32bit Random number */ + random32bit = hrng->Instance->DR; + + /* Enable the RNG Interrupts: Data Ready, Clock error, Seed error */ + __HAL_RNG_ENABLE_IT(hrng); + + /* Return the 32 bit random number */ + return random32bit; +} + + + +/** + * @brief Read latest generated random number. + * @param hrng: pointer to a RNG_HandleTypeDef structure. + * @retval random value + */ +uint32_t HAL_RNG_ReadLastRandomNumber(RNG_HandleTypeDef *hrng) +{ + return(hrng->RandomNumber); +} + +/** + * @brief Data Ready callback in non-blocking mode. + * @param hrng: pointer to a RNG_HandleTypeDef structure. + * @param random32bit: generated random value + * @retval None + */ +__weak void HAL_RNG_ReadyDataCallback(RNG_HandleTypeDef *hrng, uint32_t random32bit) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hrng); + UNUSED(random32bit); + + /* NOTE : This function should not be modified. When the callback is needed, + function HAL_RNG_ReadyDataCallback must be implemented in the user file. + */ +} + +/** + * @brief RNG error callback. + * @param hrng: pointer to a RNG_HandleTypeDef structure. + * @retval None + */ +__weak void HAL_RNG_ErrorCallback(RNG_HandleTypeDef *hrng) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hrng); + + /* NOTE : This function should not be modified. When the callback is needed, + function HAL_RNG_ErrorCallback must be implemented in the user file. + */ +} + +/** + * @} + */ + +/** @addtogroup RNG_Exported_Functions_Group3 + * @brief Peripheral State functions. + * +@verbatim + =============================================================================== + ##### Peripheral State functions ##### + =============================================================================== + [..] + This subsection permits to get in run-time the status of the peripheral. + +@endverbatim + * @{ + */ + +/** + * @brief Return the RNG handle state. + * @param hrng: pointer to a RNG_HandleTypeDef structure. + * @retval HAL state + */ +HAL_RNG_StateTypeDef HAL_RNG_GetState(RNG_HandleTypeDef *hrng) +{ + /* Return RNG handle state */ + return hrng->State; +} + +/** + * @} + */ + +/** + * @} + */ + + +#endif /* HAL_RNG_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rtc.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rtc.c new file mode 100644 index 0000000..eb08d77 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rtc.c @@ -0,0 +1,1539 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_rtc.c + * @author MCD Application Team + * @brief RTC HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Real-Time Clock (RTC) peripheral: + * + Initialization + * + Calendar (Time and Date) configuration + * + Alarms (Alarm A and Alarm B) configuration + * + WakeUp Timer configuration + * + TimeStamp configuration + * + Tampers configuration + * + Backup Data Registers configuration + * + RTC Tamper and TimeStamp Pins Selection + * + Interrupts and flags management + * + @verbatim + =============================================================================== + ##### RTC Operating Condition ##### + =============================================================================== + [..] The real-time clock (RTC) and the RTC backup registers can be powered + from the VBAT voltage when the main VDD supply is powered off. + To retain the content of the RTC backup registers and supply the RTC + when VDD is turned off, VBAT pin can be connected to an optional + standby voltage supplied by a battery or by another source. + + ##### Backup Domain Reset ##### + =============================================================================== + [..] The backup domain reset sets all RTC registers and the RCC_BDCR register + to their reset values. + A backup domain reset is generated when one of the following events occurs: + (#) Software reset, triggered by setting the BDRST bit in the + RCC Backup domain control register (RCC_BDCR). + (#) VDD or VBAT power on, if both supplies have previously been powered off. + (#) Tamper detection event resets all data backup registers. + + ##### Backup Domain Access ##### + =================================================================== + [..] After reset, the backup domain (RTC registers, RTC backup data + registers and backup SRAM) is protected against possible unwanted write + accesses. + + [..] To enable access to the RTC Domain and RTC registers, proceed as follows: + (#) Call the function HAL_RCCEx_PeriphCLKConfig with RCC_PERIPHCLK_RTC for + PeriphClockSelection and select RTCClockSelection (LSE, LSI or HSEdiv32) + (#) Enable RTC Clock using the __HAL_RCC_RTC_ENABLE() macro. + + ##### How to use RTC Driver ##### + =================================================================== + [..] + (#) Enable the RTC domain access (see description in the section above). + (#) Configure the RTC Prescaler (Asynchronous and Synchronous) and RTC hour + format using the HAL_RTC_Init() function. + + *** Time and Date configuration *** + =================================== + [..] + (#) To configure the RTC Calendar (Time and Date) use the HAL_RTC_SetTime() + and HAL_RTC_SetDate() functions. + (#) To read the RTC Calendar, use the HAL_RTC_GetTime() and HAL_RTC_GetDate() functions. + + *** Alarm configuration *** + =========================== + [..] + (#) To configure the RTC Alarm use the HAL_RTC_SetAlarm() function. + You can also configure the RTC Alarm with interrupt mode using the + HAL_RTC_SetAlarm_IT() function. + (#) To read the RTC Alarm, use the HAL_RTC_GetAlarm() function. + + ##### RTC and low power modes ##### + =================================================================== + [..] The MCU can be woken up from a low power mode by an RTC alternate + function. + [..] The RTC alternate functions are the RTC alarms (Alarm A and Alarm B), + RTC wakeup, RTC tamper event detection and RTC time stamp event detection. + These RTC alternate functions can wake up the system from the Stop and + Standby low power modes. + [..] The system can also wake up from low power modes without depending + on an external interrupt (Auto-wakeup mode), by using the RTC alarm + or the RTC wakeup events. + [..] The RTC provides a programmable time base for waking up from the + Stop or Standby mode at regular intervals. + Wakeup from STOP and Standby modes is possible only when the RTC clock source + is LSE or LSI. + + @endverbatim + + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup RTC RTC + * @brief RTC HAL module driver + * @{ + */ + +#ifdef HAL_RTC_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup RTC_Exported_Functions RTC Exported Functions + * @{ + */ + +/** @defgroup RTC_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions + * +@verbatim + =============================================================================== + ##### Initialization and de-initialization functions ##### + =============================================================================== + [..] This section provide functions allowing to initialize and configure the + RTC Prescaler (Synchronous and Asynchronous), RTC Hour format, disable + RTC registers Write protection, enter and exit the RTC initialization mode, + RTC registers synchronization check and reference clock detection enable. + (#) The RTC Prescaler is programmed to generate the RTC 1Hz time base. + It is split into 2 programmable prescalers to minimize power consumption. + (++) A 7-bit asynchronous prescaler and a 15-bit synchronous prescaler. + (++) When both prescalers are used, it is recommended to configure the + asynchronous prescaler to a high value to minimize power consumption. + (#) All RTC registers are Write protected. Writing to the RTC registers + is enabled by writing a key into the Write Protection register, RTC_WPR. + (#) To configure the RTC Calendar, user application should enter + initialization mode. In this mode, the calendar counter is stopped + and its value can be updated. When the initialization sequence is + complete, the calendar restarts counting after 4 RTCCLK cycles. + (#) To read the calendar through the shadow registers after Calendar + initialization, calendar update or after wakeup from low power modes + the software must first clear the RSF flag. The software must then + wait until it is set again before reading the calendar, which means + that the calendar registers have been correctly copied into the + RTC_TR and RTC_DR shadow registers. The HAL_RTC_WaitForSynchro() function + implements the above software sequence (RSF clear and RSF check). + +@endverbatim + * @{ + */ + +/** + * @brief Initialize the RTC according to the specified parameters + * in the RTC_InitTypeDef structure and initialize the associated handle. + * @param hrtc: RTC handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTC_Init(RTC_HandleTypeDef *hrtc) +{ + /* Check the RTC peripheral state */ + if(hrtc == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_RTC_ALL_INSTANCE(hrtc->Instance)); + assert_param(IS_RTC_HOUR_FORMAT(hrtc->Init.HourFormat)); + assert_param(IS_RTC_ASYNCH_PREDIV(hrtc->Init.AsynchPrediv)); + assert_param(IS_RTC_SYNCH_PREDIV(hrtc->Init.SynchPrediv)); + assert_param(IS_RTC_OUTPUT(hrtc->Init.OutPut)); + assert_param(IS_RTC_OUTPUT_REMAP(hrtc->Init.OutPutRemap)); + assert_param(IS_RTC_OUTPUT_POL(hrtc->Init.OutPutPolarity)); + assert_param(IS_RTC_OUTPUT_TYPE(hrtc->Init.OutPutType)); + + if(hrtc->State == HAL_RTC_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hrtc->Lock = HAL_UNLOCKED; + + /* Initialize RTC MSP */ + HAL_RTC_MspInit(hrtc); + } + + /* Set RTC state */ + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Set Initialization mode */ + if(RTC_EnterInitMode(hrtc) != HAL_OK) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Set RTC state */ + hrtc->State = HAL_RTC_STATE_ERROR; + + return HAL_ERROR; + } + else + { + /* Clear RTC_CR FMT, OSEL and POL Bits */ + hrtc->Instance->CR &= ((uint32_t)~(RTC_CR_FMT | RTC_CR_OSEL | RTC_CR_POL)); + /* Set RTC_CR register */ + hrtc->Instance->CR |= (uint32_t)(hrtc->Init.HourFormat | hrtc->Init.OutPut | hrtc->Init.OutPutPolarity); + + /* Configure the RTC PRER */ + hrtc->Instance->PRER = (uint32_t)(hrtc->Init.SynchPrediv); + hrtc->Instance->PRER |= (uint32_t)(hrtc->Init.AsynchPrediv << 16); + + /* Exit Initialization mode */ + hrtc->Instance->ISR &= ((uint32_t)~RTC_ISR_INIT); + + /* If CR_BYPSHAD bit = 0, wait for synchro else this check is not needed */ + if((hrtc->Instance->CR & RTC_CR_BYPSHAD) == RESET) + { + if(HAL_RTC_WaitForSynchro(hrtc) != HAL_OK) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_ERROR; + + return HAL_ERROR; + } + } + + hrtc->Instance->OR &= (uint32_t)~(RTC_OR_ALARMOUTTYPE | RTC_OR_OUT_RMP); + hrtc->Instance->OR |= (uint32_t)(hrtc->Init.OutPutType | hrtc->Init.OutPutRemap); + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Set RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + return HAL_OK; + } +} + +/** + * @brief DeInitialize the RTC peripheral. + * @param hrtc: RTC handle + * @note This function doesn't reset the RTC Backup Data registers. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTC_DeInit(RTC_HandleTypeDef *hrtc) +{ + uint32_t tickstart = 0; + + /* Check the parameters */ + assert_param(IS_RTC_ALL_INSTANCE(hrtc->Instance)); + + /* Set RTC state */ + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Set Initialization mode */ + if(RTC_EnterInitMode(hrtc) != HAL_OK) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Set RTC state */ + hrtc->State = HAL_RTC_STATE_ERROR; + + return HAL_ERROR; + } + else + { + /* Reset TR, DR and CR registers */ + hrtc->Instance->TR = (uint32_t)0x00000000; + hrtc->Instance->DR = ((uint32_t)(RTC_DR_WDU_0 | RTC_DR_MU_0 | RTC_DR_DU_0)); + /* Reset All CR bits except CR[2:0] */ + hrtc->Instance->CR &= RTC_CR_WUCKSEL; + + tickstart = HAL_GetTick(); + + /* Wait till WUTWF flag is set and if Time out is reached exit */ + while(((hrtc->Instance->ISR) & RTC_ISR_WUTWF) == (uint32_t)RESET) + { + if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Set RTC state */ + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + return HAL_TIMEOUT; + } + } + + /* Reset all RTC CR register bits */ + hrtc->Instance->CR &= (uint32_t)0x00000000; + hrtc->Instance->WUTR = RTC_WUTR_WUT; + hrtc->Instance->PRER = ((uint32_t)(RTC_PRER_PREDIV_A | 0x000000FF)); + hrtc->Instance->ALRMAR = (uint32_t)0x00000000; + hrtc->Instance->ALRMBR = (uint32_t)0x00000000; + hrtc->Instance->SHIFTR = (uint32_t)0x00000000; + hrtc->Instance->CALR = (uint32_t)0x00000000; + hrtc->Instance->ALRMASSR = (uint32_t)0x00000000; + hrtc->Instance->ALRMBSSR = (uint32_t)0x00000000; + + /* Reset ISR register and exit initialization mode */ + hrtc->Instance->ISR = (uint32_t)0x00000000; + + /* Reset Tamper configuration register */ + hrtc->Instance->TAMPCR = 0x00000000; + + /* Reset Option register */ + hrtc->Instance->OR = 0x00000000; + + /* If RTC_CR_BYPSHAD bit = 0, wait for synchro else this check is not needed */ + if((hrtc->Instance->CR & RTC_CR_BYPSHAD) == RESET) + { + if(HAL_RTC_WaitForSynchro(hrtc) != HAL_OK) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_ERROR; + + return HAL_ERROR; + } + } + } + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* De-Initialize RTC MSP */ + HAL_RTC_MspDeInit(hrtc); + + hrtc->State = HAL_RTC_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Initialize the RTC MSP. + * @param hrtc: RTC handle + * @retval None + */ +__weak void HAL_RTC_MspInit(RTC_HandleTypeDef* hrtc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hrtc); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_RTC_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitialize the RTC MSP. + * @param hrtc: RTC handle + * @retval None + */ +__weak void HAL_RTC_MspDeInit(RTC_HandleTypeDef* hrtc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hrtc); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_RTC_MspDeInit could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup RTC_Exported_Functions_Group2 RTC Time and Date functions + * @brief RTC Time and Date functions + * +@verbatim + =============================================================================== + ##### RTC Time and Date functions ##### + =============================================================================== + + [..] This section provides functions allowing to configure Time and Date features + +@endverbatim + * @{ + */ + +/** + * @brief Set RTC current time. + * @param hrtc: RTC handle + * @param sTime: Pointer to Time structure + * @param Format: Specifies the format of the entered parameters. + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN: Binary data format + * @arg RTC_FORMAT_BCD: BCD data format + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTC_SetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_RTC_FORMAT(Format)); + assert_param(IS_RTC_DAYLIGHT_SAVING(sTime->DayLightSaving)); + assert_param(IS_RTC_STORE_OPERATION(sTime->StoreOperation)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + if(Format == RTC_FORMAT_BIN) + { + if((hrtc->Instance->CR & RTC_CR_FMT) != (uint32_t)RESET) + { + assert_param(IS_RTC_HOUR12(sTime->Hours)); + assert_param(IS_RTC_HOURFORMAT12(sTime->TimeFormat)); + } + else + { + sTime->TimeFormat = 0x00; + assert_param(IS_RTC_HOUR24(sTime->Hours)); + } + assert_param(IS_RTC_MINUTES(sTime->Minutes)); + assert_param(IS_RTC_SECONDS(sTime->Seconds)); + + tmpreg = (uint32_t)(((uint32_t)RTC_ByteToBcd2(sTime->Hours) << 16) | \ + ((uint32_t)RTC_ByteToBcd2(sTime->Minutes) << 8) | \ + ((uint32_t)RTC_ByteToBcd2(sTime->Seconds)) | \ + (((uint32_t)sTime->TimeFormat) << 16)); + } + else + { + if((hrtc->Instance->CR & RTC_CR_FMT) != (uint32_t)RESET) + { + tmpreg = RTC_Bcd2ToByte(sTime->Hours); + assert_param(IS_RTC_HOUR12(tmpreg)); + assert_param(IS_RTC_HOURFORMAT12(sTime->TimeFormat)); + } + else + { + sTime->TimeFormat = 0x00; + assert_param(IS_RTC_HOUR24(RTC_Bcd2ToByte(sTime->Hours))); + } + assert_param(IS_RTC_MINUTES(RTC_Bcd2ToByte(sTime->Minutes))); + assert_param(IS_RTC_SECONDS(RTC_Bcd2ToByte(sTime->Seconds))); + tmpreg = (((uint32_t)(sTime->Hours) << 16) | \ + ((uint32_t)(sTime->Minutes) << 8) | \ + ((uint32_t)sTime->Seconds) | \ + ((uint32_t)(sTime->TimeFormat) << 16)); + } + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Set Initialization mode */ + if(RTC_EnterInitMode(hrtc) != HAL_OK) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Set RTC state */ + hrtc->State = HAL_RTC_STATE_ERROR; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_ERROR; + } + else + { + /* Set the RTC_TR register */ + hrtc->Instance->TR = (uint32_t)(tmpreg & RTC_TR_RESERVED_MASK); + + /* Clear the bits to be configured */ + hrtc->Instance->CR &= ((uint32_t)~RTC_CR_BCK); + + /* Configure the RTC_CR register */ + hrtc->Instance->CR |= (uint32_t)(sTime->DayLightSaving | sTime->StoreOperation); + + /* Exit Initialization mode */ + hrtc->Instance->ISR &= ((uint32_t)~RTC_ISR_INIT); + + /* If CR_BYPSHAD bit = 0, wait for synchro else this check is not needed */ + if((hrtc->Instance->CR & RTC_CR_BYPSHAD) == RESET) + { + if(HAL_RTC_WaitForSynchro(hrtc) != HAL_OK) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_ERROR; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_ERROR; + } + } + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_READY; + + __HAL_UNLOCK(hrtc); + + return HAL_OK; + } +} + +/** + * @brief Get RTC current time. + * @param hrtc: RTC handle + * @param sTime: Pointer to Time structure with Hours, Minutes and Seconds fields returned + * with input format (BIN or BCD), also SubSeconds field returning the + * RTC_SSR register content and SecondFraction field the Synchronous pre-scaler + * factor to be used for second fraction ratio computation. + * @param Format: Specifies the format of the entered parameters. + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN: Binary data format + * @arg RTC_FORMAT_BCD: BCD data format + * @note You can use SubSeconds and SecondFraction (sTime structure fields returned) to convert SubSeconds + * value in second fraction ratio with time unit following generic formula: + * Second fraction ratio * time_unit= [(SecondFraction-SubSeconds)/(SecondFraction+1)] * time_unit + * This conversion can be performed only if no shift operation is pending (ie. SHFP=0) when PREDIV_S >= SS + * @note You must call HAL_RTC_GetDate() after HAL_RTC_GetTime() to unlock the values + * in the higher-order calendar shadow registers to ensure consistency between the time and date values. + * Reading RTC current time locks the values in calendar shadow registers until Current date is read + * to ensure consistency between the time and date values. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTC_GetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_RTC_FORMAT(Format)); + + /* Get subseconds structure field from the corresponding register*/ + sTime->SubSeconds = (uint32_t)(hrtc->Instance->SSR); + + /* Get SecondFraction structure field from the corresponding register field*/ + sTime->SecondFraction = (uint32_t)(hrtc->Instance->PRER & RTC_PRER_PREDIV_S); + + /* Get the TR register */ + tmpreg = (uint32_t)(hrtc->Instance->TR & RTC_TR_RESERVED_MASK); + + /* Fill the structure fields with the read parameters */ + sTime->Hours = (uint8_t)((tmpreg & (RTC_TR_HT | RTC_TR_HU)) >> 16); + sTime->Minutes = (uint8_t)((tmpreg & (RTC_TR_MNT | RTC_TR_MNU)) >>8); + sTime->Seconds = (uint8_t)(tmpreg & (RTC_TR_ST | RTC_TR_SU)); + sTime->TimeFormat = (uint8_t)((tmpreg & (RTC_TR_PM)) >> 16); + + /* Check the input parameters format */ + if(Format == RTC_FORMAT_BIN) + { + /* Convert the time structure parameters to Binary format */ + sTime->Hours = (uint8_t)RTC_Bcd2ToByte(sTime->Hours); + sTime->Minutes = (uint8_t)RTC_Bcd2ToByte(sTime->Minutes); + sTime->Seconds = (uint8_t)RTC_Bcd2ToByte(sTime->Seconds); + } + + return HAL_OK; +} + +/** + * @brief Set RTC current date. + * @param hrtc: RTC handle + * @param sDate: Pointer to date structure + * @param Format: specifies the format of the entered parameters. + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN: Binary data format + * @arg RTC_FORMAT_BCD: BCD data format + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTC_SetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format) +{ + uint32_t datetmpreg = 0; + + /* Check the parameters */ + assert_param(IS_RTC_FORMAT(Format)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + if((Format == RTC_FORMAT_BIN) && ((sDate->Month & 0x10U) == 0x10U)) + { + sDate->Month = (uint8_t)((sDate->Month & (uint8_t)~(0x10U)) + (uint8_t)0x0AU); + } + + assert_param(IS_RTC_WEEKDAY(sDate->WeekDay)); + + if(Format == RTC_FORMAT_BIN) + { + assert_param(IS_RTC_YEAR(sDate->Year)); + assert_param(IS_RTC_MONTH(sDate->Month)); + assert_param(IS_RTC_DATE(sDate->Date)); + + datetmpreg = (((uint32_t)RTC_ByteToBcd2(sDate->Year) << 16) | \ + ((uint32_t)RTC_ByteToBcd2(sDate->Month) << 8) | \ + ((uint32_t)RTC_ByteToBcd2(sDate->Date)) | \ + ((uint32_t)sDate->WeekDay << 13)); + } + else + { + assert_param(IS_RTC_YEAR(RTC_Bcd2ToByte(sDate->Year))); + datetmpreg = RTC_Bcd2ToByte(sDate->Month); + assert_param(IS_RTC_MONTH(datetmpreg)); + datetmpreg = RTC_Bcd2ToByte(sDate->Date); + assert_param(IS_RTC_DATE(datetmpreg)); + + datetmpreg = ((((uint32_t)sDate->Year) << 16) | \ + (((uint32_t)sDate->Month) << 8) | \ + ((uint32_t)sDate->Date) | \ + (((uint32_t)sDate->WeekDay) << 13)); + } + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Set Initialization mode */ + if(RTC_EnterInitMode(hrtc) != HAL_OK) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Set RTC state*/ + hrtc->State = HAL_RTC_STATE_ERROR; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_ERROR; + } + else + { + /* Set the RTC_DR register */ + hrtc->Instance->DR = (uint32_t)(datetmpreg & RTC_DR_RESERVED_MASK); + + /* Exit Initialization mode */ + hrtc->Instance->ISR &= ((uint32_t)~RTC_ISR_INIT); + + /* If CR_BYPSHAD bit = 0, wait for synchro else this check is not needed */ + if((hrtc->Instance->CR & RTC_CR_BYPSHAD) == RESET) + { + if(HAL_RTC_WaitForSynchro(hrtc) != HAL_OK) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_ERROR; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_ERROR; + } + } + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_READY ; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; + } +} + +/** + * @brief Get RTC current date. + * @param hrtc: RTC handle + * @param sDate: Pointer to Date structure + * @param Format: Specifies the format of the entered parameters. + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN: Binary data format + * @arg RTC_FORMAT_BCD: BCD data format + * @note You must call HAL_RTC_GetDate() after HAL_RTC_GetTime() to unlock the values + * in the higher-order calendar shadow registers to ensure consistency between the time and date values. + * Reading RTC current time locks the values in calendar shadow registers until Current date is read. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTC_GetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format) +{ + uint32_t datetmpreg = 0; + + /* Check the parameters */ + assert_param(IS_RTC_FORMAT(Format)); + + /* Get the DR register */ + datetmpreg = (uint32_t)(hrtc->Instance->DR & RTC_DR_RESERVED_MASK); + + /* Fill the structure fields with the read parameters */ + sDate->Year = (uint8_t)((datetmpreg & (RTC_DR_YT | RTC_DR_YU)) >> 16); + sDate->Month = (uint8_t)((datetmpreg & (RTC_DR_MT | RTC_DR_MU)) >> 8); + sDate->Date = (uint8_t)(datetmpreg & (RTC_DR_DT | RTC_DR_DU)); + sDate->WeekDay = (uint8_t)((datetmpreg & (RTC_DR_WDU)) >> 13); + + /* Check the input parameters format */ + if(Format == RTC_FORMAT_BIN) + { + /* Convert the date structure parameters to Binary format */ + sDate->Year = (uint8_t)RTC_Bcd2ToByte(sDate->Year); + sDate->Month = (uint8_t)RTC_Bcd2ToByte(sDate->Month); + sDate->Date = (uint8_t)RTC_Bcd2ToByte(sDate->Date); + } + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup RTC_Exported_Functions_Group3 RTC Alarm functions + * @brief RTC Alarm functions + * +@verbatim + =============================================================================== + ##### RTC Alarm functions ##### + =============================================================================== + + [..] This section provides functions allowing to configure Alarm feature + +@endverbatim + * @{ + */ +/** + * @brief Set the specified RTC Alarm. + * @param hrtc: RTC handle + * @param sAlarm: Pointer to Alarm structure + * @param Format: Specifies the format of the entered parameters. + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN: Binary data format + * @arg RTC_FORMAT_BCD: BCD data format + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTC_SetAlarm(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Format) +{ + uint32_t tickstart = 0; + uint32_t tmpreg = 0, subsecondtmpreg = 0; + + /* Check the parameters */ + assert_param(IS_RTC_FORMAT(Format)); + assert_param(IS_RTC_ALARM(sAlarm->Alarm)); + assert_param(IS_RTC_ALARM_MASK(sAlarm->AlarmMask)); + assert_param(IS_RTC_ALARM_DATE_WEEKDAY_SEL(sAlarm->AlarmDateWeekDaySel)); + assert_param(IS_RTC_ALARM_SUB_SECOND_VALUE(sAlarm->AlarmTime.SubSeconds)); + assert_param(IS_RTC_ALARM_SUB_SECOND_MASK(sAlarm->AlarmSubSecondMask)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + if(Format == RTC_FORMAT_BIN) + { + if((hrtc->Instance->CR & RTC_CR_FMT) != (uint32_t)RESET) + { + assert_param(IS_RTC_HOUR12(sAlarm->AlarmTime.Hours)); + assert_param(IS_RTC_HOURFORMAT12(sAlarm->AlarmTime.TimeFormat)); + } + else + { + sAlarm->AlarmTime.TimeFormat = 0x00; + assert_param(IS_RTC_HOUR24(sAlarm->AlarmTime.Hours)); + } + assert_param(IS_RTC_MINUTES(sAlarm->AlarmTime.Minutes)); + assert_param(IS_RTC_SECONDS(sAlarm->AlarmTime.Seconds)); + + if(sAlarm->AlarmDateWeekDaySel == RTC_ALARMDATEWEEKDAYSEL_DATE) + { + assert_param(IS_RTC_ALARM_DATE_WEEKDAY_DATE(sAlarm->AlarmDateWeekDay)); + } + else + { + assert_param(IS_RTC_ALARM_DATE_WEEKDAY_WEEKDAY(sAlarm->AlarmDateWeekDay)); + } + + tmpreg = (((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmTime.Hours) << 16) | \ + ((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmTime.Minutes) << 8) | \ + ((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmTime.Seconds)) | \ + ((uint32_t)(sAlarm->AlarmTime.TimeFormat) << 16) | \ + ((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmDateWeekDay) << 24) | \ + ((uint32_t)sAlarm->AlarmDateWeekDaySel) | \ + ((uint32_t)sAlarm->AlarmMask)); + } + else + { + if((hrtc->Instance->CR & RTC_CR_FMT) != (uint32_t)RESET) + { + tmpreg = RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours); + assert_param(IS_RTC_HOUR12(tmpreg)); + assert_param(IS_RTC_HOURFORMAT12(sAlarm->AlarmTime.TimeFormat)); + } + else + { + sAlarm->AlarmTime.TimeFormat = 0x00; + assert_param(IS_RTC_HOUR24(RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours))); + } + + assert_param(IS_RTC_MINUTES(RTC_Bcd2ToByte(sAlarm->AlarmTime.Minutes))); + assert_param(IS_RTC_SECONDS(RTC_Bcd2ToByte(sAlarm->AlarmTime.Seconds))); + + if(sAlarm->AlarmDateWeekDaySel == RTC_ALARMDATEWEEKDAYSEL_DATE) + { + tmpreg = RTC_Bcd2ToByte(sAlarm->AlarmDateWeekDay); + assert_param(IS_RTC_ALARM_DATE_WEEKDAY_DATE(tmpreg)); + } + else + { + tmpreg = RTC_Bcd2ToByte(sAlarm->AlarmDateWeekDay); + assert_param(IS_RTC_ALARM_DATE_WEEKDAY_WEEKDAY(tmpreg)); + } + + tmpreg = (((uint32_t)(sAlarm->AlarmTime.Hours) << 16) | \ + ((uint32_t)(sAlarm->AlarmTime.Minutes) << 8) | \ + ((uint32_t) sAlarm->AlarmTime.Seconds) | \ + ((uint32_t)(sAlarm->AlarmTime.TimeFormat) << 16) | \ + ((uint32_t)(sAlarm->AlarmDateWeekDay) << 24) | \ + ((uint32_t)sAlarm->AlarmDateWeekDaySel) | \ + ((uint32_t)sAlarm->AlarmMask)); + } + + /* Configure the Alarm A or Alarm B Sub Second registers */ + subsecondtmpreg = (uint32_t)((uint32_t)(sAlarm->AlarmTime.SubSeconds) | (uint32_t)(sAlarm->AlarmSubSecondMask)); + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Configure the Alarm register */ + if(sAlarm->Alarm == RTC_ALARM_A) + { + /* Disable the Alarm A interrupt */ + __HAL_RTC_ALARMA_DISABLE(hrtc); + + /* In case of interrupt mode is used, the interrupt source must disabled */ + __HAL_RTC_ALARM_DISABLE_IT(hrtc, RTC_IT_ALRA); + + tickstart = HAL_GetTick(); + /* Wait till RTC ALRAWF flag is set and if Time out is reached exit */ + while(__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAWF) == RESET) + { + if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_TIMEOUT; + } + } + + hrtc->Instance->ALRMAR = (uint32_t)tmpreg; + /* Configure the Alarm A Sub Second register */ + hrtc->Instance->ALRMASSR = subsecondtmpreg; + /* Configure the Alarm state: Enable Alarm */ + __HAL_RTC_ALARMA_ENABLE(hrtc); + } + else + { + /* Disable the Alarm B interrupt */ + __HAL_RTC_ALARMB_DISABLE(hrtc); + + /* In case of interrupt mode is used, the interrupt source must disabled */ + __HAL_RTC_ALARM_DISABLE_IT(hrtc, RTC_IT_ALRB); + + tickstart = HAL_GetTick(); + /* Wait till RTC ALRBWF flag is set and if Time out is reached exit */ + while(__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRBWF) == RESET) + { + if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_TIMEOUT; + } + } + + hrtc->Instance->ALRMBR = (uint32_t)tmpreg; + /* Configure the Alarm B Sub Second register */ + hrtc->Instance->ALRMBSSR = subsecondtmpreg; + /* Configure the Alarm state: Enable Alarm */ + __HAL_RTC_ALARMB_ENABLE(hrtc); + } + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Set the specified RTC Alarm with Interrupt. + * @param hrtc: RTC handle + * @param sAlarm: Pointer to Alarm structure + * @param Format: Specifies the format of the entered parameters. + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN: Binary data format + * @arg RTC_FORMAT_BCD: BCD data format + * @note The Alarm register can only be written when the corresponding Alarm + * is disabled (Use the HAL_RTC_DeactivateAlarm()). + * @note The HAL_RTC_SetTime() must be called before enabling the Alarm feature. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTC_SetAlarm_IT(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Format) +{ + uint32_t tickstart = 0; + uint32_t tmpreg = 0, subsecondtmpreg = 0; + + /* Check the parameters */ + assert_param(IS_RTC_FORMAT(Format)); + assert_param(IS_RTC_ALARM(sAlarm->Alarm)); + assert_param(IS_RTC_ALARM_MASK(sAlarm->AlarmMask)); + assert_param(IS_RTC_ALARM_DATE_WEEKDAY_SEL(sAlarm->AlarmDateWeekDaySel)); + assert_param(IS_RTC_ALARM_SUB_SECOND_VALUE(sAlarm->AlarmTime.SubSeconds)); + assert_param(IS_RTC_ALARM_SUB_SECOND_MASK(sAlarm->AlarmSubSecondMask)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + if(Format == RTC_FORMAT_BIN) + { + if((hrtc->Instance->CR & RTC_CR_FMT) != (uint32_t)RESET) + { + assert_param(IS_RTC_HOUR12(sAlarm->AlarmTime.Hours)); + assert_param(IS_RTC_HOURFORMAT12(sAlarm->AlarmTime.TimeFormat)); + } + else + { + sAlarm->AlarmTime.TimeFormat = 0x00; + assert_param(IS_RTC_HOUR24(sAlarm->AlarmTime.Hours)); + } + assert_param(IS_RTC_MINUTES(sAlarm->AlarmTime.Minutes)); + assert_param(IS_RTC_SECONDS(sAlarm->AlarmTime.Seconds)); + + if(sAlarm->AlarmDateWeekDaySel == RTC_ALARMDATEWEEKDAYSEL_DATE) + { + assert_param(IS_RTC_ALARM_DATE_WEEKDAY_DATE(sAlarm->AlarmDateWeekDay)); + } + else + { + assert_param(IS_RTC_ALARM_DATE_WEEKDAY_WEEKDAY(sAlarm->AlarmDateWeekDay)); + } + tmpreg = (((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmTime.Hours) << 16) | \ + ((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmTime.Minutes) << 8) | \ + ((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmTime.Seconds)) | \ + ((uint32_t)(sAlarm->AlarmTime.TimeFormat) << 16) | \ + ((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmDateWeekDay) << 24) | \ + ((uint32_t)sAlarm->AlarmDateWeekDaySel) | \ + ((uint32_t)sAlarm->AlarmMask)); + } + else + { + if((hrtc->Instance->CR & RTC_CR_FMT) != (uint32_t)RESET) + { + tmpreg = RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours); + assert_param(IS_RTC_HOUR12(tmpreg)); + assert_param(IS_RTC_HOURFORMAT12(sAlarm->AlarmTime.TimeFormat)); + } + else + { + sAlarm->AlarmTime.TimeFormat = 0x00; + assert_param(IS_RTC_HOUR24(RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours))); + } + + assert_param(IS_RTC_MINUTES(RTC_Bcd2ToByte(sAlarm->AlarmTime.Minutes))); + assert_param(IS_RTC_SECONDS(RTC_Bcd2ToByte(sAlarm->AlarmTime.Seconds))); + + if(sAlarm->AlarmDateWeekDaySel == RTC_ALARMDATEWEEKDAYSEL_DATE) + { + tmpreg = RTC_Bcd2ToByte(sAlarm->AlarmDateWeekDay); + assert_param(IS_RTC_ALARM_DATE_WEEKDAY_DATE(tmpreg)); + } + else + { + tmpreg = RTC_Bcd2ToByte(sAlarm->AlarmDateWeekDay); + assert_param(IS_RTC_ALARM_DATE_WEEKDAY_WEEKDAY(tmpreg)); + } + tmpreg = (((uint32_t)(sAlarm->AlarmTime.Hours) << 16) | \ + ((uint32_t)(sAlarm->AlarmTime.Minutes) << 8) | \ + ((uint32_t) sAlarm->AlarmTime.Seconds) | \ + ((uint32_t)(sAlarm->AlarmTime.TimeFormat) << 16) | \ + ((uint32_t)(sAlarm->AlarmDateWeekDay) << 24) | \ + ((uint32_t)sAlarm->AlarmDateWeekDaySel) | \ + ((uint32_t)sAlarm->AlarmMask)); + } + /* Configure the Alarm A or Alarm B Sub Second registers */ + subsecondtmpreg = (uint32_t)((uint32_t)(sAlarm->AlarmTime.SubSeconds) | (uint32_t)(sAlarm->AlarmSubSecondMask)); + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Configure the Alarm register */ + if(sAlarm->Alarm == RTC_ALARM_A) + { + /* Disable the Alarm A interrupt */ + __HAL_RTC_ALARMA_DISABLE(hrtc); + + /* Clear flag alarm A */ + __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF); + + tickstart = HAL_GetTick(); + /* Wait till RTC ALRAWF flag is set and if Time out is reached exit */ + while(__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAWF) == RESET) + { + if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_TIMEOUT; + } + } + + hrtc->Instance->ALRMAR = (uint32_t)tmpreg; + /* Configure the Alarm A Sub Second register */ + hrtc->Instance->ALRMASSR = subsecondtmpreg; + /* Configure the Alarm state: Enable Alarm */ + __HAL_RTC_ALARMA_ENABLE(hrtc); + /* Configure the Alarm interrupt */ + __HAL_RTC_ALARM_ENABLE_IT(hrtc,RTC_IT_ALRA); + } + else + { + /* Disable the Alarm B interrupt */ + __HAL_RTC_ALARMB_DISABLE(hrtc); + + /* Clear flag alarm B */ + __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRBF); + + tickstart = HAL_GetTick(); + /* Wait till RTC ALRBWF flag is set and if Time out is reached exit */ + while(__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRBWF) == RESET) + { + if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_TIMEOUT; + } + } + + hrtc->Instance->ALRMBR = (uint32_t)tmpreg; + /* Configure the Alarm B Sub Second register */ + hrtc->Instance->ALRMBSSR = subsecondtmpreg; + /* Configure the Alarm state: Enable Alarm */ + __HAL_RTC_ALARMB_ENABLE(hrtc); + /* Configure the Alarm interrupt */ + __HAL_RTC_ALARM_ENABLE_IT(hrtc, RTC_IT_ALRB); + } + + /* RTC Alarm Interrupt Configuration: EXTI configuration */ + __HAL_RTC_ALARM_EXTI_ENABLE_IT(); + + __HAL_RTC_ALARM_EXTI_ENABLE_RISING_EDGE(); + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Deactivate the specified RTC Alarm. + * @param hrtc: RTC handle + * @param Alarm: Specifies the Alarm. + * This parameter can be one of the following values: + * @arg RTC_ALARM_A: AlarmA + * @arg RTC_ALARM_B: AlarmB + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTC_DeactivateAlarm(RTC_HandleTypeDef *hrtc, uint32_t Alarm) +{ + uint32_t tickstart = 0; + + /* Check the parameters */ + assert_param(IS_RTC_ALARM(Alarm)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + if(Alarm == RTC_ALARM_A) + { + /* AlarmA */ + __HAL_RTC_ALARMA_DISABLE(hrtc); + + /* In case of interrupt mode is used, the interrupt source must disabled */ + __HAL_RTC_ALARM_DISABLE_IT(hrtc, RTC_IT_ALRA); + + tickstart = HAL_GetTick(); + + /* Wait till RTC ALRxWF flag is set and if Time out is reached exit */ + while(__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAWF) == RESET) + { + if( (HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_TIMEOUT; + } + } + } + else + { + /* AlarmB */ + __HAL_RTC_ALARMB_DISABLE(hrtc); + + /* In case of interrupt mode is used, the interrupt source must disabled */ + __HAL_RTC_ALARM_DISABLE_IT(hrtc,RTC_IT_ALRB); + + tickstart = HAL_GetTick(); + + /* Wait till RTC ALRxWF flag is set and if Time out is reached exit */ + while(__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRBWF) == RESET) + { + if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_TIMEOUT; + } + } + } + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Get the RTC Alarm value and masks. + * @param hrtc: RTC handle + * @param sAlarm: Pointer to Date structure + * @param Alarm: Specifies the Alarm. + * This parameter can be one of the following values: + * @arg RTC_ALARM_A: AlarmA + * @arg RTC_ALARM_B: AlarmB + * @param Format: Specifies the format of the entered parameters. + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN: Binary data format + * @arg RTC_FORMAT_BCD: BCD data format + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTC_GetAlarm(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Alarm, uint32_t Format) +{ + uint32_t tmpreg = 0, subsecondtmpreg = 0; + + /* Check the parameters */ + assert_param(IS_RTC_FORMAT(Format)); + assert_param(IS_RTC_ALARM(Alarm)); + + if(Alarm == RTC_ALARM_A) + { + /* AlarmA */ + sAlarm->Alarm = RTC_ALARM_A; + + tmpreg = (uint32_t)(hrtc->Instance->ALRMAR); + subsecondtmpreg = (uint32_t)((hrtc->Instance->ALRMASSR ) & RTC_ALRMASSR_SS); + } + else + { + sAlarm->Alarm = RTC_ALARM_B; + + tmpreg = (uint32_t)(hrtc->Instance->ALRMBR); + subsecondtmpreg = (uint32_t)((hrtc->Instance->ALRMBSSR) & RTC_ALRMBSSR_SS); + } + + /* Fill the structure with the read parameters */ + /* ALRMAR/ALRMBR registers have same mapping) */ + sAlarm->AlarmTime.Hours = (uint32_t)((tmpreg & (RTC_ALRMAR_HT | RTC_ALRMAR_HU)) >> 16); + sAlarm->AlarmTime.Minutes = (uint32_t)((tmpreg & (RTC_ALRMAR_MNT | RTC_ALRMAR_MNU)) >> 8); + sAlarm->AlarmTime.Seconds = (uint32_t)(tmpreg & (RTC_ALRMAR_ST | RTC_ALRMAR_SU)); + sAlarm->AlarmTime.TimeFormat = (uint32_t)((tmpreg & RTC_ALRMAR_PM) >> 16); + sAlarm->AlarmTime.SubSeconds = (uint32_t) subsecondtmpreg; + sAlarm->AlarmDateWeekDay = (uint32_t)((tmpreg & (RTC_ALRMAR_DT | RTC_ALRMAR_DU)) >> 24); + sAlarm->AlarmDateWeekDaySel = (uint32_t)(tmpreg & RTC_ALRMAR_WDSEL); + sAlarm->AlarmMask = (uint32_t)(tmpreg & RTC_ALARMMASK_ALL); + + if(Format == RTC_FORMAT_BIN) + { + sAlarm->AlarmTime.Hours = RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours); + sAlarm->AlarmTime.Minutes = RTC_Bcd2ToByte(sAlarm->AlarmTime.Minutes); + sAlarm->AlarmTime.Seconds = RTC_Bcd2ToByte(sAlarm->AlarmTime.Seconds); + sAlarm->AlarmDateWeekDay = RTC_Bcd2ToByte(sAlarm->AlarmDateWeekDay); + } + + return HAL_OK; +} + +/** + * @brief Handle Alarm interrupt request. + * @param hrtc: RTC handle + * @retval None + */ +void HAL_RTC_AlarmIRQHandler(RTC_HandleTypeDef* hrtc) +{ + /* Clear the EXTI's line Flag for RTC Alarm */ + __HAL_RTC_ALARM_EXTI_CLEAR_FLAG(); + + /* As alarms are sharing the same EXTI line, exit when no more pending Alarm event */ + while(((__HAL_RTC_ALARM_GET_IT_SOURCE(hrtc, RTC_IT_ALRA) != RESET) && (__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAF) != RESET)) || + ((__HAL_RTC_ALARM_GET_IT_SOURCE(hrtc, RTC_IT_ALRB) != RESET) && (__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRBF) != RESET))) + { + /* Get the AlarmA interrupt source enable status and pending flag status*/ + if((__HAL_RTC_ALARM_GET_IT_SOURCE(hrtc, RTC_IT_ALRA) != RESET) && (__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAF) != RESET)) + { + /* Clear the AlarmA interrupt pending bit */ + __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF); + + /* AlarmA callback */ + HAL_RTC_AlarmAEventCallback(hrtc); + } + + /* Get the AlarmB interrupt source enable status and pending flag status*/ + if((__HAL_RTC_ALARM_GET_IT_SOURCE(hrtc, RTC_IT_ALRB) != RESET) && (__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRBF) != RESET)) + { + /* Clear the AlarmB interrupt pending bit */ + __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRBF); + + /* AlarmB callback */ + HAL_RTCEx_AlarmBEventCallback(hrtc); + } + } + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; +} + +/** + * @brief Alarm A callback. + * @param hrtc: RTC handle + * @retval None + */ +__weak void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hrtc); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_RTC_AlarmAEventCallback could be implemented in the user file + */ +} + +/** + * @brief Handle AlarmA Polling request. + * @param hrtc: RTC handle + * @param Timeout: Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTC_PollForAlarmAEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout) +{ + + uint32_t tickstart = HAL_GetTick(); + + while(__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAF) == RESET) + { + if(Timeout != HAL_MAX_DELAY) + { + if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)) + { + hrtc->State = HAL_RTC_STATE_TIMEOUT; + return HAL_TIMEOUT; + } + } + } + + /* Clear the Alarm interrupt pending bit */ + __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup RTC_Exported_Functions_Group4 Peripheral Control functions + * @brief Peripheral Control functions + * +@verbatim + =============================================================================== + ##### Peripheral Control functions ##### + =============================================================================== + [..] + This subsection provides functions allowing to + (+) Wait for RTC Time and Date Synchronization + +@endverbatim + * @{ + */ + +/** + * @brief Wait until the RTC Time and Date registers (RTC_TR and RTC_DR) are + * synchronized with RTC APB clock. + * @note The RTC Resynchronization mode is write protected, use the + * __HAL_RTC_WRITEPROTECTION_DISABLE() before calling this function. + * @note To read the calendar through the shadow registers after Calendar + * initialization, calendar update or after wakeup from low power modes + * the software must first clear the RSF flag. + * The software must then wait until it is set again before reading + * the calendar, which means that the calendar registers have been + * correctly copied into the RTC_TR and RTC_DR shadow registers. + * @param hrtc: RTC handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTC_WaitForSynchro(RTC_HandleTypeDef* hrtc) +{ + uint32_t tickstart = 0; + + /* Clear RSF flag */ + hrtc->Instance->ISR &= (uint32_t)RTC_RSF_MASK; + + tickstart = HAL_GetTick(); + + /* Wait the registers to be synchronised */ + while((hrtc->Instance->ISR & RTC_ISR_RSF) == (uint32_t)RESET) + { + if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup RTC_Exported_Functions_Group5 Peripheral State functions + * @brief Peripheral State functions + * +@verbatim + =============================================================================== + ##### Peripheral State functions ##### + =============================================================================== + [..] + This subsection provides functions allowing to + (+) Get RTC state + +@endverbatim + * @{ + */ +/** + * @brief Return the RTC handle state. + * @param hrtc: RTC handle + * @retval HAL state + */ +HAL_RTCStateTypeDef HAL_RTC_GetState(RTC_HandleTypeDef* hrtc) +{ + /* Return RTC handle state */ + return hrtc->State; +} + +/** + * @} + */ + +/** + * @} + */ + +/** @defgroup RTC_Private_Functions RTC Private functions + * @{ + */ +/** + * @brief Enter the RTC Initialization mode. + * @note The RTC Initialization mode is write protected, use the + * __HAL_RTC_WRITEPROTECTION_DISABLE() before calling this function. + * @param hrtc: RTC handle + * @retval HAL status + */ +HAL_StatusTypeDef RTC_EnterInitMode(RTC_HandleTypeDef* hrtc) +{ + uint32_t tickstart = 0; + + /* Check if the Initialization mode is set */ + if((hrtc->Instance->ISR & RTC_ISR_INITF) == (uint32_t)RESET) + { + /* Set the Initialization mode */ + hrtc->Instance->ISR = (uint32_t)RTC_INIT_MASK; + + tickstart = HAL_GetTick(); + /* Wait till RTC is in INIT state and if Time out is reached exit */ + while((hrtc->Instance->ISR & RTC_ISR_INITF) == (uint32_t)RESET) + { + if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + + return HAL_OK; +} + + +/** + * @brief Convert a 2 digit decimal to BCD format. + * @param Value: Byte to be converted + * @retval Converted byte + */ +uint8_t RTC_ByteToBcd2(uint8_t Value) +{ + uint32_t bcdhigh = 0; + + while(Value >= 10) + { + bcdhigh++; + Value -= 10; + } + + return ((uint8_t)(bcdhigh << 4) | Value); +} + +/** + * @brief Convert from 2 digit BCD to Binary. + * @param Value: BCD value to be converted + * @retval Converted word + */ +uint8_t RTC_Bcd2ToByte(uint8_t Value) +{ + uint32_t tmp = 0; + tmp = ((uint8_t)(Value & (uint8_t)0xF0) >> (uint8_t)0x4) * 10; + return (tmp + (Value & (uint8_t)0x0F)); +} + +/** + * @} + */ + +#endif /* HAL_RTC_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rtc_ex.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rtc_ex.c new file mode 100644 index 0000000..35be397 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rtc_ex.c @@ -0,0 +1,1875 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_rtc_ex.c + * @author MCD Application Team + * @brief Extended RTC HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Real Time Clock (RTC) Extended peripheral: + * + RTC Time Stamp functions + * + RTC Tamper functions + * + RTC Wake-up functions + * + Extended Control functions + * + Extended RTC features functions + * + @verbatim + ============================================================================== + ##### How to use this driver ##### + ============================================================================== + [..] + (+) Enable the RTC domain access. + (+) Configure the RTC Prescaler (Asynchronous and Synchronous) and RTC hour + format using the HAL_RTC_Init() function. + + *** RTC Wakeup configuration *** + ================================ + [..] + (+) To configure the RTC Wakeup Clock source and Counter use the HAL_RTCEx_SetWakeUpTimer() + function. You can also configure the RTC Wakeup timer with interrupt mode + using the HAL_RTCEx_SetWakeUpTimer_IT() function. + (+) To read the RTC WakeUp Counter register, use the HAL_RTCEx_GetWakeUpTimer() + function. + + *** Outputs configuration *** + ============================= + [..] The RTC has 2 different outputs: + (+) RTC_ALARM: this output is used to manage the RTC Alarm A, Alarm B + and WaKeUp signals. + To output the selected RTC signal, use the HAL_RTC_Init() function. + (+) RTC_CALIB: this output is 512Hz signal or 1Hz. + To enable the RTC_CALIB, use the HAL_RTCEx_SetCalibrationOutPut() function. + (+) Two pins can be used as RTC_ALARM or RTC_CALIB (PC13, PB2) managed on + the RTC_OR register. + (+) When the RTC_CALIB or RTC_ALARM output is selected, the RTC_OUT pin is + automatically configured in output alternate function. + + *** Smooth digital Calibration configuration *** + ================================================ + [..] + (+) Configure the RTC Original Digital Calibration Value and the corresponding + calibration cycle period (32s,16s and 8s) using the HAL_RTCEx_SetSmoothCalib() + function. + + *** TimeStamp configuration *** + =============================== + [..] + (+) Enable the RTC TimeStamp using the HAL_RTCEx_SetTimeStamp() function. + You can also configure the RTC TimeStamp with interrupt mode using the + HAL_RTCEx_SetTimeStamp_IT() function. + (+) To read the RTC TimeStamp Time and Date register, use the HAL_RTCEx_GetTimeStamp() + function. + + *** Internal TimeStamp configuration *** + =============================== + [..] + (+) Enable the RTC internal TimeStamp using the HAL_RTCEx_SetInternalTimeStamp() function. + User has to check internal timestamp occurrence using __HAL_RTC_INTERNAL_TIMESTAMP_GET_FLAG. + (+) To read the RTC TimeStamp Time and Date register, use the HAL_RTCEx_GetTimeStamp() + function. + + *** Tamper configuration *** + ============================ + [..] + (+) Enable the RTC Tamper and configure the Tamper filter count, trigger Edge + or Level according to the Tamper filter (if equal to 0 Edge else Level) + value, sampling frequency, NoErase, MaskFlag, precharge or discharge and + Pull-UP using the HAL_RTCEx_SetTamper() function. You can configure RTC Tamper + with interrupt mode using HAL_RTCEx_SetTamper_IT() function. + (+) The default configuration of the Tamper erases the backup registers. To avoid + erase, enable the NoErase field on the RTC_TAMPCR register. + + *** Backup Data Registers configuration *** + =========================================== + [..] + (+) To write to the RTC Backup Data registers, use the HAL_RTCEx_BKUPWrite() + function. + (+) To read the RTC Backup Data registers, use the HAL_RTCEx_BKUPRead() + function. + + @endverbatim + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup RTCEx RTCEx + * @brief RTC Extended HAL module driver + * @{ + */ + +#ifdef HAL_RTC_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +#if defined(RTC_TAMPER1_SUPPORT) && defined(RTC_TAMPER3_SUPPORT) +#define RTC_TAMPCR_MASK ((uint32_t)RTC_TAMPCR_TAMPTS |\ + (uint32_t)RTC_TAMPCR_TAMPFREQ | (uint32_t)RTC_TAMPCR_TAMPFLT | (uint32_t)RTC_TAMPCR_TAMPPRCH |\ + (uint32_t)RTC_TAMPCR_TAMPPUDIS | (uint32_t)RTC_TAMPCR_TAMPIE |\ + (uint32_t)RTC_TAMPCR_TAMP1IE | (uint32_t)RTC_TAMPCR_TAMP1NOERASE | (uint32_t)RTC_TAMPCR_TAMP1MF |\ + (uint32_t)RTC_TAMPCR_TAMP2IE | (uint32_t)RTC_TAMPCR_TAMP2NOERASE | (uint32_t)RTC_TAMPCR_TAMP2MF |\ + (uint32_t)RTC_TAMPCR_TAMP3IE | (uint32_t)RTC_TAMPCR_TAMP3NOERASE | (uint32_t)RTC_TAMPCR_TAMP3MF) +#elif defined(RTC_TAMPER1_SUPPORT) +#define RTC_TAMPCR_MASK ((uint32_t)RTC_TAMPCR_TAMPTS |\ + (uint32_t)RTC_TAMPCR_TAMPFREQ | (uint32_t)RTC_TAMPCR_TAMPFLT | (uint32_t)RTC_TAMPCR_TAMPPRCH |\ + (uint32_t)RTC_TAMPCR_TAMPPUDIS | (uint32_t)RTC_TAMPCR_TAMPIE |\ + (uint32_t)RTC_TAMPCR_TAMP1IE | (uint32_t)RTC_TAMPCR_TAMP1NOERASE | (uint32_t)RTC_TAMPCR_TAMP1MF |\ + (uint32_t)RTC_TAMPCR_TAMP2IE | (uint32_t)RTC_TAMPCR_TAMP2NOERASE | (uint32_t)RTC_TAMPCR_TAMP2MF) +#elif defined(RTC_TAMPER3_SUPPORT) +#define RTC_TAMPCR_MASK ((uint32_t)RTC_TAMPCR_TAMPTS |\ + (uint32_t)RTC_TAMPCR_TAMPFREQ | (uint32_t)RTC_TAMPCR_TAMPFLT | (uint32_t)RTC_TAMPCR_TAMPPRCH |\ + (uint32_t)RTC_TAMPCR_TAMPPUDIS | (uint32_t)RTC_TAMPCR_TAMPIE |\ + (uint32_t)RTC_TAMPCR_TAMP2IE | (uint32_t)RTC_TAMPCR_TAMP2NOERASE | (uint32_t)RTC_TAMPCR_TAMP2MF |\ + (uint32_t)RTC_TAMPCR_TAMP3IE | (uint32_t)RTC_TAMPCR_TAMP3NOERASE | (uint32_t)RTC_TAMPCR_TAMP3MF) +#else +#define RTC_TAMPCR_MASK ((uint32_t)RTC_TAMPCR_TAMPTS |\ + (uint32_t)RTC_TAMPCR_TAMPFREQ | (uint32_t)RTC_TAMPCR_TAMPFLT | (uint32_t)RTC_TAMPCR_TAMPPRCH |\ + (uint32_t)RTC_TAMPCR_TAMPPUDIS | (uint32_t)RTC_TAMPCR_TAMPIE |\ + (uint32_t)RTC_TAMPCR_TAMP2IE | (uint32_t)RTC_TAMPCR_TAMP2NOERASE | (uint32_t)RTC_TAMPCR_TAMP2MF) +#endif /* RTC_TAMPER1_SUPPORT && RTC_TAMPER3_SUPPORT */ + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup RTCEx_Exported_Functions RTCEx Exported Functions + * @{ + */ + + +/** @defgroup RTCEx_Exported_Functions_Group1 RTC TimeStamp and Tamper functions + * @brief RTC TimeStamp and Tamper functions + * +@verbatim + =============================================================================== + ##### RTC TimeStamp and Tamper functions ##### + =============================================================================== + + [..] This section provide functions allowing to configure TimeStamp feature + +@endverbatim + * @{ + */ + +/** + * @brief Set TimeStamp. + * @note This API must be called before enabling the TimeStamp feature. + * @param hrtc: RTC handle + * @param TimeStampEdge: Specifies the pin edge on which the TimeStamp is + * activated. + * This parameter can be one of the following values: + * @arg RTC_TIMESTAMPEDGE_RISING: the Time stamp event occurs on the + * rising edge of the related pin. + * @arg RTC_TIMESTAMPEDGE_FALLING: the Time stamp event occurs on the + * falling edge of the related pin. + * @param RTC_TimeStampPin: specifies the RTC TimeStamp Pin. + * This parameter can be one of the following values: + * @arg RTC_TIMESTAMPPIN_DEFAULT: PC13 is selected as RTC TimeStamp Pin. + * The RTC TimeStamp Pin is per default PC13, but for reasons of + * compatibility, this parameter is required. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_SetTimeStamp(RTC_HandleTypeDef *hrtc, uint32_t TimeStampEdge, uint32_t RTC_TimeStampPin) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_TIMESTAMP_EDGE(TimeStampEdge)); + assert_param(IS_RTC_TIMESTAMP_PIN(RTC_TimeStampPin)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Get the RTC_CR register and clear the bits to be configured */ + tmpreg = (uint32_t)(hrtc->Instance->CR & (uint32_t)~(RTC_CR_TSEDGE | RTC_CR_TSE)); + + tmpreg|= TimeStampEdge; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Configure the Time Stamp TSEDGE and Enable bits */ + hrtc->Instance->CR = (uint32_t)tmpreg; + + __HAL_RTC_TIMESTAMP_ENABLE(hrtc); + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Set TimeStamp with Interrupt. + * @param hrtc: RTC handle + * @note This API must be called before enabling the TimeStamp feature. + * @param TimeStampEdge: Specifies the pin edge on which the TimeStamp is + * activated. + * This parameter can be one of the following values: + * @arg RTC_TIMESTAMPEDGE_RISING: the Time stamp event occurs on the + * rising edge of the related pin. + * @arg RTC_TIMESTAMPEDGE_FALLING: the Time stamp event occurs on the + * falling edge of the related pin. + * @param RTC_TimeStampPin: Specifies the RTC TimeStamp Pin. + * This parameter can be one of the following values: + * @arg RTC_TIMESTAMPPIN_DEFAULT: PC13 is selected as RTC TimeStamp Pin. + * The RTC TimeStamp Pin is per default PC13, but for reasons of + * compatibility, this parameter is required. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_SetTimeStamp_IT(RTC_HandleTypeDef *hrtc, uint32_t TimeStampEdge, uint32_t RTC_TimeStampPin) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_TIMESTAMP_EDGE(TimeStampEdge)); + assert_param(IS_RTC_TIMESTAMP_PIN(RTC_TimeStampPin)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Get the RTC_CR register and clear the bits to be configured */ + tmpreg = (uint32_t)(hrtc->Instance->CR & (uint32_t)~(RTC_CR_TSEDGE | RTC_CR_TSE)); + + tmpreg |= TimeStampEdge; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Configure the Time Stamp TSEDGE and Enable bits */ + hrtc->Instance->CR = (uint32_t)tmpreg; + + __HAL_RTC_TIMESTAMP_ENABLE(hrtc); + + /* Enable IT timestamp */ + __HAL_RTC_TIMESTAMP_ENABLE_IT(hrtc,RTC_IT_TS); + + /* RTC timestamp Interrupt Configuration: EXTI configuration */ + __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_IT(); + + __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_RISING_EDGE(); + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Deactivate TimeStamp. + * @param hrtc: RTC handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_DeactivateTimeStamp(RTC_HandleTypeDef *hrtc) +{ + uint32_t tmpreg = 0; + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* In case of interrupt mode is used, the interrupt source must disabled */ + __HAL_RTC_TIMESTAMP_DISABLE_IT(hrtc, RTC_IT_TS); + + /* Get the RTC_CR register and clear the bits to be configured */ + tmpreg = (uint32_t)(hrtc->Instance->CR & (uint32_t)~(RTC_CR_TSEDGE | RTC_CR_TSE)); + + /* Configure the Time Stamp TSEDGE and Enable bits */ + hrtc->Instance->CR = (uint32_t)tmpreg; + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Set Internal TimeStamp. + * @note This API must be called before enabling the internal TimeStamp feature. + * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_SetInternalTimeStamp(RTC_HandleTypeDef *hrtc) +{ + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Configure the internal Time Stamp Enable bits */ + __HAL_RTC_INTERNAL_TIMESTAMP_ENABLE(hrtc); + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Deactivate Internal TimeStamp. + * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_DeactivateInternalTimeStamp(RTC_HandleTypeDef *hrtc) +{ + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Configure the internal Time Stamp Enable bits */ + __HAL_RTC_INTERNAL_TIMESTAMP_DISABLE(hrtc); + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Get the RTC TimeStamp value. + * @param hrtc: RTC handle + * @param sTimeStamp: Pointer to Time structure + * @param sTimeStampDate: Pointer to Date structure + * @param Format: specifies the format of the entered parameters. + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN: Binary data format + * @arg RTC_FORMAT_BCD: BCD data format + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_GetTimeStamp(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef* sTimeStamp, RTC_DateTypeDef* sTimeStampDate, uint32_t Format) +{ + uint32_t tmptime = 0, tmpdate = 0; + + /* Check the parameters */ + assert_param(IS_RTC_FORMAT(Format)); + + /* Get the TimeStamp time and date registers values */ + tmptime = (uint32_t)(hrtc->Instance->TSTR & RTC_TR_RESERVED_MASK); + tmpdate = (uint32_t)(hrtc->Instance->TSDR & RTC_DR_RESERVED_MASK); + + /* Fill the Time structure fields with the read parameters */ + sTimeStamp->Hours = (uint8_t)((tmptime & (RTC_TR_HT | RTC_TR_HU)) >> 16); + sTimeStamp->Minutes = (uint8_t)((tmptime & (RTC_TR_MNT | RTC_TR_MNU)) >> 8); + sTimeStamp->Seconds = (uint8_t)(tmptime & (RTC_TR_ST | RTC_TR_SU)); + sTimeStamp->TimeFormat = (uint8_t)((tmptime & (RTC_TR_PM)) >> 16); + sTimeStamp->SubSeconds = (uint32_t) hrtc->Instance->TSSSR; + + /* Fill the Date structure fields with the read parameters */ + sTimeStampDate->Year = 0; + sTimeStampDate->Month = (uint8_t)((tmpdate & (RTC_DR_MT | RTC_DR_MU)) >> 8); + sTimeStampDate->Date = (uint8_t)(tmpdate & (RTC_DR_DT | RTC_DR_DU)); + sTimeStampDate->WeekDay = (uint8_t)((tmpdate & (RTC_DR_WDU)) >> 13); + + /* Check the input parameters format */ + if(Format == RTC_FORMAT_BIN) + { + /* Convert the TimeStamp structure parameters to Binary format */ + sTimeStamp->Hours = (uint8_t)RTC_Bcd2ToByte(sTimeStamp->Hours); + sTimeStamp->Minutes = (uint8_t)RTC_Bcd2ToByte(sTimeStamp->Minutes); + sTimeStamp->Seconds = (uint8_t)RTC_Bcd2ToByte(sTimeStamp->Seconds); + + /* Convert the DateTimeStamp structure parameters to Binary format */ + sTimeStampDate->Month = (uint8_t)RTC_Bcd2ToByte(sTimeStampDate->Month); + sTimeStampDate->Date = (uint8_t)RTC_Bcd2ToByte(sTimeStampDate->Date); + sTimeStampDate->WeekDay = (uint8_t)RTC_Bcd2ToByte(sTimeStampDate->WeekDay); + } + + /* Clear the TIMESTAMP Flags */ + __HAL_RTC_INTERNAL_TIMESTAMP_CLEAR_FLAG(hrtc, RTC_FLAG_ITSF); + __HAL_RTC_TIMESTAMP_CLEAR_FLAG(hrtc, RTC_FLAG_TSF); + + return HAL_OK; +} + +/** + * @brief Set Tamper. + * @note By calling this API we disable the tamper interrupt for all tampers. + * @param hrtc: RTC handle + * @param sTamper: Pointer to Tamper Structure. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_SetTamper(RTC_HandleTypeDef *hrtc, RTC_TamperTypeDef* sTamper) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_RTC_TAMPER(sTamper->Tamper)); + assert_param(IS_RTC_TAMPER_TRIGGER(sTamper->Trigger)); + assert_param(IS_RTC_TAMPER_ERASE_MODE(sTamper->NoErase)); + assert_param(IS_RTC_TAMPER_MASKFLAG_STATE(sTamper->MaskFlag)); + assert_param(IS_RTC_TAMPER_FILTER(sTamper->Filter)); + assert_param(IS_RTC_TAMPER_SAMPLING_FREQ(sTamper->SamplingFrequency)); + assert_param(IS_RTC_TAMPER_PRECHARGE_DURATION(sTamper->PrechargeDuration)); + assert_param(IS_RTC_TAMPER_PULLUP_STATE(sTamper->TamperPullUp)); + assert_param(IS_RTC_TAMPER_TIMESTAMPONTAMPER_DETECTION(sTamper->TimeStampOnTamperDetection)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Configure the tamper trigger */ + if(sTamper->Trigger != RTC_TAMPERTRIGGER_RISINGEDGE) + { + sTamper->Trigger = (uint32_t)(sTamper->Tamper << 1); + } + + if(sTamper->NoErase != RTC_TAMPER_ERASE_BACKUP_ENABLE) + { + sTamper->NoErase = 0; +#if defined(RTC_TAMPER1_SUPPORT) + if((sTamper->Tamper & RTC_TAMPER_1) != 0) + { + sTamper->NoErase |= RTC_TAMPCR_TAMP1NOERASE; + } +#endif /* RTC_TAMPER1_SUPPORT */ + if((sTamper->Tamper & RTC_TAMPER_2) != 0) + { + sTamper->NoErase |= RTC_TAMPCR_TAMP2NOERASE; + } +#if defined(RTC_TAMPER3_SUPPORT) + if((sTamper->Tamper & RTC_TAMPER_3) != 0) + { + sTamper->NoErase |= RTC_TAMPCR_TAMP3NOERASE; + } +#endif /* RTC_TAMPER3_SUPPORT */ + } + + if(sTamper->MaskFlag != RTC_TAMPERMASK_FLAG_DISABLE) + { + sTamper->MaskFlag = 0; +#if defined(RTC_TAMPER1_SUPPORT) + if((sTamper->Tamper & RTC_TAMPER_1) != 0) + { + sTamper->MaskFlag |= RTC_TAMPCR_TAMP1MF; + } +#endif /* RTC_TAMPER1_SUPPORT */ + if((sTamper->Tamper & RTC_TAMPER_2) != 0) + { + sTamper->MaskFlag |= RTC_TAMPCR_TAMP2MF; + } +#if defined(RTC_TAMPER3_SUPPORT) + if((sTamper->Tamper & RTC_TAMPER_3) != 0) + { + sTamper->MaskFlag |= RTC_TAMPCR_TAMP3MF; + } +#endif /* RTC_TAMPER3_SUPPORT */ + } + + tmpreg = ((uint32_t)sTamper->Tamper | (uint32_t)sTamper->Trigger | (uint32_t)sTamper->NoErase |\ + (uint32_t)sTamper->MaskFlag | (uint32_t)sTamper->Filter | (uint32_t)sTamper->SamplingFrequency |\ + (uint32_t)sTamper->PrechargeDuration | (uint32_t)sTamper->TamperPullUp | sTamper->TimeStampOnTamperDetection); + + hrtc->Instance->TAMPCR &= (uint32_t)~((uint32_t)sTamper->Tamper | (uint32_t)(sTamper->Tamper << 1) | RTC_TAMPCR_MASK); + + hrtc->Instance->TAMPCR |= tmpreg; + + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Set Tamper with interrupt. + * @note By calling this API we force the tamper interrupt for all tampers. + * @param hrtc: RTC handle + * @param sTamper: Pointer to RTC Tamper. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_SetTamper_IT(RTC_HandleTypeDef *hrtc, RTC_TamperTypeDef* sTamper) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_RTC_TAMPER(sTamper->Tamper)); + assert_param(IS_RTC_TAMPER_INTERRUPT(sTamper->Interrupt)); + assert_param(IS_RTC_TAMPER_TRIGGER(sTamper->Trigger)); + assert_param(IS_RTC_TAMPER_ERASE_MODE(sTamper->NoErase)); + assert_param(IS_RTC_TAMPER_MASKFLAG_STATE(sTamper->MaskFlag)); + assert_param(IS_RTC_TAMPER_FILTER(sTamper->Filter)); + assert_param(IS_RTC_TAMPER_SAMPLING_FREQ(sTamper->SamplingFrequency)); + assert_param(IS_RTC_TAMPER_PRECHARGE_DURATION(sTamper->PrechargeDuration)); + assert_param(IS_RTC_TAMPER_PULLUP_STATE(sTamper->TamperPullUp)); + assert_param(IS_RTC_TAMPER_TIMESTAMPONTAMPER_DETECTION(sTamper->TimeStampOnTamperDetection)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Configure the tamper trigger */ + if(sTamper->Trigger != RTC_TAMPERTRIGGER_RISINGEDGE) + { + sTamper->Trigger = (uint32_t)(sTamper->Tamper << 1); + } + + if(sTamper->NoErase != RTC_TAMPER_ERASE_BACKUP_ENABLE) + { + sTamper->NoErase = 0; +#if defined(RTC_TAMPER1_SUPPORT) + if((sTamper->Tamper & RTC_TAMPER_1) != 0) + { + sTamper->NoErase |= RTC_TAMPCR_TAMP1NOERASE; + } +#endif /* RTC_TAMPER1_SUPPORT */ + if((sTamper->Tamper & RTC_TAMPER_2) != 0) + { + sTamper->NoErase |= RTC_TAMPCR_TAMP2NOERASE; + } +#if defined(RTC_TAMPER3_SUPPORT) + if((sTamper->Tamper & RTC_TAMPER_3) != 0) + { + sTamper->NoErase |= RTC_TAMPCR_TAMP3NOERASE; + } +#endif /* RTC_TAMPER3_SUPPORT */ + } + + if(sTamper->MaskFlag != RTC_TAMPERMASK_FLAG_DISABLE) + { + sTamper->MaskFlag = 0; +#if defined(RTC_TAMPER1_SUPPORT) + if((sTamper->Tamper & RTC_TAMPER_1) != 0) + { + sTamper->MaskFlag |= RTC_TAMPCR_TAMP1MF; + } +#endif /* RTC_TAMPER1_SUPPORT */ + if((sTamper->Tamper & RTC_TAMPER_2) != 0) + { + sTamper->MaskFlag |= RTC_TAMPCR_TAMP2MF; + } +#if defined(RTC_TAMPER3_SUPPORT) + if((sTamper->Tamper & RTC_TAMPER_3) != 0) + { + sTamper->MaskFlag |= RTC_TAMPCR_TAMP3MF; + } +#endif /* RTC_TAMPER3_SUPPORT */ + } + + tmpreg = ((uint32_t)sTamper->Tamper | (uint32_t)sTamper->Interrupt | (uint32_t)sTamper->Trigger | (uint32_t)sTamper->NoErase |\ + (uint32_t)sTamper->MaskFlag | (uint32_t)sTamper->Filter | (uint32_t)sTamper->SamplingFrequency |\ + (uint32_t)sTamper->PrechargeDuration | (uint32_t)sTamper->TamperPullUp | sTamper->TimeStampOnTamperDetection); + + hrtc->Instance->TAMPCR &= (uint32_t)~((uint32_t)sTamper->Tamper | (uint32_t)(sTamper->Tamper << 1) | RTC_TAMPCR_MASK); + + hrtc->Instance->TAMPCR |= tmpreg; + + /* RTC Tamper Interrupt Configuration: EXTI configuration */ + __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_IT(); + + __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_RISING_EDGE(); + + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Deactivate Tamper. + * @param hrtc: RTC handle + * @param Tamper: Selected tamper pin. + * This parameter can be any combination of RTC_TAMPER_1, RTC_TAMPER_2 and RTC_TAMPER_3. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_DeactivateTamper(RTC_HandleTypeDef *hrtc, uint32_t Tamper) +{ + assert_param(IS_RTC_TAMPER(Tamper)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the selected Tamper pin */ + hrtc->Instance->TAMPCR &= ((uint32_t)~Tamper); + +#if defined(RTC_TAMPER1_SUPPORT) + if ((Tamper & RTC_TAMPER_1) != 0) + { + /* Disable the Tamper1 interrupt */ + hrtc->Instance->TAMPCR &= ((uint32_t)~(RTC_IT_TAMP | RTC_IT_TAMP1)); + } +#endif /* RTC_TAMPER1_SUPPORT */ + if ((Tamper & RTC_TAMPER_2) != 0) + { + /* Disable the Tamper2 interrupt */ + hrtc->Instance->TAMPCR &= ((uint32_t)~(RTC_IT_TAMP | RTC_IT_TAMP2)); + } +#if defined(RTC_TAMPER3_SUPPORT) + if ((Tamper & RTC_TAMPER_3) != 0) + { + /* Disable the Tamper3 interrupt */ + hrtc->Instance->TAMPCR &= ((uint32_t)~(RTC_IT_TAMP | RTC_IT_TAMP3)); + } +#endif /* RTC_TAMPER3_SUPPORT */ + + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Handle TimeStamp interrupt request. + * @param hrtc: RTC handle + * @retval None + */ +void HAL_RTCEx_TamperTimeStampIRQHandler(RTC_HandleTypeDef *hrtc) +{ + /* Clear the EXTI's Flag for RTC TimeStamp and Tamper */ + __HAL_RTC_TAMPER_TIMESTAMP_EXTI_CLEAR_FLAG(); + + /* As Tampers and TimeStamp are sharing the same EXTI line, exit when no more pending event */ + while( + ((__HAL_RTC_TIMESTAMP_GET_IT_SOURCE(hrtc, RTC_IT_TS) != RESET) && (__HAL_RTC_TIMESTAMP_GET_FLAG(hrtc, RTC_FLAG_TSF) != RESET)) +#if defined(RTC_TAMPER1_SUPPORT) + || ((__HAL_RTC_TAMPER_GET_IT_SOURCE(hrtc, RTC_IT_TAMP | RTC_IT_TAMP1) != RESET) && (__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP1F) != RESET)) +#endif /* RTC_TAMPER1_SUPPORT */ + || ((__HAL_RTC_TAMPER_GET_IT_SOURCE(hrtc, RTC_IT_TAMP | RTC_IT_TAMP2) != RESET) && (__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP2F) != RESET)) +#if defined(RTC_TAMPER3_SUPPORT) + || ((__HAL_RTC_TAMPER_GET_IT_SOURCE(hrtc, RTC_IT_TAMP | RTC_IT_TAMP3) != RESET) && (__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP3F) != RESET)) +#endif /* RTC_TAMPER3_SUPPORT */ + ) + { + + /* Get the TimeStamp interrupt source enable status and pending flag status */ + if((__HAL_RTC_TIMESTAMP_GET_IT_SOURCE(hrtc, RTC_IT_TS) != RESET) && (__HAL_RTC_TIMESTAMP_GET_FLAG(hrtc, RTC_FLAG_TSF) != RESET)) + { + /* TIMESTAMP callback */ + HAL_RTCEx_TimeStampEventCallback(hrtc); + + /* Clear the TIMESTAMP interrupt pending bit (this will clear timestamp time and date registers) */ + __HAL_RTC_TIMESTAMP_CLEAR_FLAG(hrtc, RTC_FLAG_TSF); + } + +#if defined(RTC_TAMPER1_SUPPORT) + /* Get the Tamper1 interrupt source enable status and pending flag status */ + if((__HAL_RTC_TAMPER_GET_IT_SOURCE(hrtc, RTC_IT_TAMP | RTC_IT_TAMP1) != RESET) && (__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP1F) != RESET)) + { + /* Clear the Tamper1 interrupt pending bit */ + __HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP1F); + + /* Tamper1 callback */ + HAL_RTCEx_Tamper1EventCallback(hrtc); + } +#endif /* RTC_TAMPER1_SUPPORT */ + + /* Get the Tamper2 interrupt source enable status and pending flag status */ + if((__HAL_RTC_TAMPER_GET_IT_SOURCE(hrtc, RTC_IT_TAMP | RTC_IT_TAMP2) != RESET) && (__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP2F) != RESET)) + { + /* Clear the Tamper2 interrupt pending bit */ + __HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP2F); + + /* Tamper2 callback */ + HAL_RTCEx_Tamper2EventCallback(hrtc); + } + +#if defined(RTC_TAMPER3_SUPPORT) + /* Get the Tamper3 interrupts source enable status and pending flag status */ + if((__HAL_RTC_TAMPER_GET_IT_SOURCE(hrtc, RTC_IT_TAMP | RTC_IT_TAMP3) != RESET) && (__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP3F) != RESET)) + { + /* Clear the Tamper3 interrupt pending bit */ + __HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP3F); + + /* Tamper3 callback */ + HAL_RTCEx_Tamper3EventCallback(hrtc); + } +#endif /* RTC_TAMPER3_SUPPORT */ + + } + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; +} + +/** + * @brief TimeStamp callback. + * @param hrtc: RTC handle + * @retval None + */ +__weak void HAL_RTCEx_TimeStampEventCallback(RTC_HandleTypeDef *hrtc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hrtc); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_RTCEx_TimeStampEventCallback could be implemented in the user file + */ +} + +#if defined(RTC_TAMPER1_SUPPORT) +/** + * @brief Tamper 1 callback. + * @param hrtc: RTC handle + * @retval None + */ +__weak void HAL_RTCEx_Tamper1EventCallback(RTC_HandleTypeDef *hrtc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hrtc); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_RTCEx_Tamper1EventCallback could be implemented in the user file + */ +} +#endif /* RTC_TAMPER1_SUPPORT */ + +/** + * @brief Tamper 2 callback. + * @param hrtc: RTC handle + * @retval None + */ +__weak void HAL_RTCEx_Tamper2EventCallback(RTC_HandleTypeDef *hrtc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hrtc); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_RTCEx_Tamper2EventCallback could be implemented in the user file + */ +} + +#if defined(RTC_TAMPER3_SUPPORT) +/** + * @brief Tamper 3 callback. + * @param hrtc: RTC handle + * @retval None + */ +__weak void HAL_RTCEx_Tamper3EventCallback(RTC_HandleTypeDef *hrtc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hrtc); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_RTCEx_Tamper3EventCallback could be implemented in the user file + */ +} +#endif /* RTC_TAMPER3_SUPPORT */ + +/** + * @brief Handle TimeStamp polling request. + * @param hrtc: RTC handle + * @param Timeout: Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_PollForTimeStampEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout) +{ + uint32_t tickstart = HAL_GetTick(); + + while(__HAL_RTC_TIMESTAMP_GET_FLAG(hrtc, RTC_FLAG_TSF) == RESET) + { + if(__HAL_RTC_TIMESTAMP_GET_FLAG(hrtc, RTC_FLAG_TSOVF) != RESET) + { + /* Clear the TIMESTAMP OverRun Flag */ + __HAL_RTC_TIMESTAMP_CLEAR_FLAG(hrtc, RTC_FLAG_TSOVF); + + /* Change TIMESTAMP state */ + hrtc->State = HAL_RTC_STATE_ERROR; + + return HAL_ERROR; + } + + if(Timeout != HAL_MAX_DELAY) + { + if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)) + { + hrtc->State = HAL_RTC_STATE_TIMEOUT; + return HAL_TIMEOUT; + } + } + } + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + return HAL_OK; +} + +#if defined(RTC_TAMPER1_SUPPORT) +/** + * @brief Handle Tamper 1 Polling. + * @param hrtc: RTC handle + * @param Timeout: Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_PollForTamper1Event(RTC_HandleTypeDef *hrtc, uint32_t Timeout) +{ + uint32_t tickstart = HAL_GetTick(); + + /* Get the status of the Interrupt */ + while(__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP1F)== RESET) + { + if(Timeout != HAL_MAX_DELAY) + { + if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)) + { + hrtc->State = HAL_RTC_STATE_TIMEOUT; + return HAL_TIMEOUT; + } + } + } + + /* Clear the Tamper Flag */ + __HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP1F); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + return HAL_OK; +} +#endif /* RTC_TAMPER1_SUPPORT */ + +/** + * @brief Handle Tamper 2 Polling. + * @param hrtc: RTC handle + * @param Timeout: Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_PollForTamper2Event(RTC_HandleTypeDef *hrtc, uint32_t Timeout) +{ + uint32_t tickstart = HAL_GetTick(); + + /* Get the status of the Interrupt */ + while(__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP2F) == RESET) + { + if(Timeout != HAL_MAX_DELAY) + { + if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)) + { + hrtc->State = HAL_RTC_STATE_TIMEOUT; + return HAL_TIMEOUT; + } + } + } + + /* Clear the Tamper Flag */ + __HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP2F); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + return HAL_OK; +} + +#if defined(RTC_TAMPER3_SUPPORT) +/** + * @brief Handle Tamper 3 Polling. + * @param hrtc: RTC handle + * @param Timeout: Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_PollForTamper3Event(RTC_HandleTypeDef *hrtc, uint32_t Timeout) +{ + uint32_t tickstart = HAL_GetTick(); + + /* Get the status of the Interrupt */ + while(__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP3F) == RESET) + { + if(Timeout != HAL_MAX_DELAY) + { + if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)) + { + hrtc->State = HAL_RTC_STATE_TIMEOUT; + return HAL_TIMEOUT; + } + } + } + + /* Clear the Tamper Flag */ + __HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP3F); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + return HAL_OK; +} +#endif /* RTC_TAMPER3_SUPPORT */ + +/** + * @} + */ + +/** @defgroup RTCEx_Exported_Functions_Group2 RTC Wake-up functions + * @brief RTC Wake-up functions + * +@verbatim + =============================================================================== + ##### RTC Wake-up functions ##### + =============================================================================== + + [..] This section provide functions allowing to configure Wake-up feature + +@endverbatim + * @{ + */ + +/** + * @brief Set wake up timer. + * @param hrtc: RTC handle + * @param WakeUpCounter: Wake up counter + * @param WakeUpClock: Wake up clock + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_SetWakeUpTimer(RTC_HandleTypeDef *hrtc, uint32_t WakeUpCounter, uint32_t WakeUpClock) +{ + uint32_t tickstart = 0; + + /* Check the parameters */ + assert_param(IS_RTC_WAKEUP_CLOCK(WakeUpClock)); + assert_param(IS_RTC_WAKEUP_COUNTER(WakeUpCounter)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /*Check RTC WUTWF flag is reset only when wake up timer enabled*/ + if((hrtc->Instance->CR & RTC_CR_WUTE) != RESET) + { + tickstart = HAL_GetTick(); + + /* Wait till RTC WUTWF flag is reset and if Time out is reached exit */ + while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTWF) == SET) + { + if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_TIMEOUT; + } + } + } + + __HAL_RTC_WAKEUPTIMER_DISABLE(hrtc); + + tickstart = HAL_GetTick(); + + /* Wait till RTC WUTWF flag is set and if Time out is reached exit */ + while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTWF) == RESET) + { + if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_TIMEOUT; + } + } + + /* Clear the Wakeup Timer clock source bits in CR register */ + hrtc->Instance->CR &= (uint32_t)~RTC_CR_WUCKSEL; + + /* Configure the clock source */ + hrtc->Instance->CR |= (uint32_t)WakeUpClock; + + /* Configure the Wakeup Timer counter */ + hrtc->Instance->WUTR = (uint32_t)WakeUpCounter; + + /* Enable the Wakeup Timer */ + __HAL_RTC_WAKEUPTIMER_ENABLE(hrtc); + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Set wake up timer with interrupt. + * @param hrtc: RTC handle + * @param WakeUpCounter: Wake up counter + * @param WakeUpClock: Wake up clock + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_SetWakeUpTimer_IT(RTC_HandleTypeDef *hrtc, uint32_t WakeUpCounter, uint32_t WakeUpClock) +{ + uint32_t tickstart = 0; + + /* Check the parameters */ + assert_param(IS_RTC_WAKEUP_CLOCK(WakeUpClock)); + assert_param(IS_RTC_WAKEUP_COUNTER(WakeUpCounter)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /*Check RTC WUTWF flag is reset only when wake up timer enabled*/ + if((hrtc->Instance->CR & RTC_CR_WUTE) != RESET) + { + tickstart = HAL_GetTick(); + + /* Wait till RTC WUTWF flag is reset and if Time out is reached exit */ + while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTWF) == SET) + { + if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_TIMEOUT; + } + } + } + /* Disable the Wake-Up timer */ + __HAL_RTC_WAKEUPTIMER_DISABLE(hrtc); + + /* Clear flag Wake-Up */ + __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(hrtc, RTC_FLAG_WUTF); + + tickstart = HAL_GetTick(); + + /* Wait till RTC WUTWF flag is set and if Time out is reached exit */ + while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTWF) == RESET) + { + if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_TIMEOUT; + } + } + + /* Configure the Wakeup Timer counter */ + hrtc->Instance->WUTR = (uint32_t)WakeUpCounter; + + /* Clear the Wakeup Timer clock source bits in CR register */ + hrtc->Instance->CR &= (uint32_t)~RTC_CR_WUCKSEL; + + /* Configure the clock source */ + hrtc->Instance->CR |= (uint32_t)WakeUpClock; + + /* RTC WakeUpTimer Interrupt Configuration: EXTI configuration */ + __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_IT(); + + __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_RISING_EDGE(); + + /* Configure the Interrupt in the RTC_CR register */ + __HAL_RTC_WAKEUPTIMER_ENABLE_IT(hrtc,RTC_IT_WUT); + + /* Enable the Wakeup Timer */ + __HAL_RTC_WAKEUPTIMER_ENABLE(hrtc); + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Deactivate wake up timer counter. + * @param hrtc: RTC handle + * @retval HAL status + */ +uint32_t HAL_RTCEx_DeactivateWakeUpTimer(RTC_HandleTypeDef *hrtc) +{ + uint32_t tickstart = 0; + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Disable the Wakeup Timer */ + __HAL_RTC_WAKEUPTIMER_DISABLE(hrtc); + + /* In case of interrupt mode is used, the interrupt source must disabled */ + __HAL_RTC_WAKEUPTIMER_DISABLE_IT(hrtc,RTC_IT_WUT); + + tickstart = HAL_GetTick(); + /* Wait till RTC WUTWF flag is set and if Time out is reached exit */ + while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTWF) == RESET) + { + if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_TIMEOUT; + } + } + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Get wake up timer counter. + * @param hrtc: RTC handle + * @retval Counter value + */ +uint32_t HAL_RTCEx_GetWakeUpTimer(RTC_HandleTypeDef *hrtc) +{ + /* Get the counter value */ + return ((uint32_t)(hrtc->Instance->WUTR & RTC_WUTR_WUT)); +} + +/** + * @brief Handle Wake Up Timer interrupt request. + * @param hrtc: RTC handle + * @retval None + */ +void HAL_RTCEx_WakeUpTimerIRQHandler(RTC_HandleTypeDef *hrtc) +{ + /* Clear the EXTI's line Flag for RTC WakeUpTimer */ + __HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG(); + + /* Get the pending status of the WAKEUPTIMER Interrupt */ + if(__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTF) != RESET) + { + /* Clear the WAKEUPTIMER interrupt pending bit */ + __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(hrtc, RTC_FLAG_WUTF); + + /* WAKEUPTIMER callback */ + HAL_RTCEx_WakeUpTimerEventCallback(hrtc); + } + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; +} + +/** + * @brief Wake Up Timer callback. + * @param hrtc: RTC handle + * @retval None + */ +__weak void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hrtc); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_RTCEx_WakeUpTimerEventCallback could be implemented in the user file + */ +} + +/** + * @brief Handle Wake Up Timer Polling. + * @param hrtc: RTC handle + * @param Timeout: Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_PollForWakeUpTimerEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout) +{ + uint32_t tickstart = HAL_GetTick(); + + while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTF) == RESET) + { + if(Timeout != HAL_MAX_DELAY) + { + if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)) + { + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + return HAL_TIMEOUT; + } + } + } + + /* Clear the WAKEUPTIMER Flag */ + __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(hrtc, RTC_FLAG_WUTF); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + return HAL_OK; +} + +/** + * @} + */ + + +/** @defgroup RTCEx_Exported_Functions_Group3 Extended Peripheral Control functions + * @brief Extended Peripheral Control functions + * +@verbatim + =============================================================================== + ##### Extended Peripheral Control functions ##### + =============================================================================== + [..] + This subsection provides functions allowing to + (+) Write a data in a specified RTC Backup data register + (+) Read a data in a specified RTC Backup data register + (+) Set the Coarse calibration parameters. + (+) Deactivate the Coarse calibration parameters + (+) Set the Smooth calibration parameters. + (+) Configure the Synchronization Shift Control Settings. + (+) Configure the Calibration Pinout (RTC_CALIB) Selection (1Hz or 512Hz). + (+) Deactivate the Calibration Pinout (RTC_CALIB) Selection (1Hz or 512Hz). + (+) Enable the RTC reference clock detection. + (+) Disable the RTC reference clock detection. + (+) Enable the Bypass Shadow feature. + (+) Disable the Bypass Shadow feature. + +@endverbatim + * @{ + */ + +/** + * @brief Write a data in a specified RTC Backup data register. + * @param hrtc: RTC handle + * @param BackupRegister: RTC Backup data Register number. + * This parameter can be: RTC_BKP_DRx where x can be from 0 to 19 to + * specify the register. + * @param Data: Data to be written in the specified RTC Backup data register. + * @retval None + */ +void HAL_RTCEx_BKUPWrite(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister, uint32_t Data) +{ + uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_RTC_BKP(BackupRegister)); + + tmp = (uint32_t)&(hrtc->Instance->BKP0R); + tmp += (BackupRegister * 4); + + /* Write the specified register */ + *(__IO uint32_t *)tmp = (uint32_t)Data; +} + +/** + * @brief Read data from the specified RTC Backup data Register. + * @param hrtc: RTC handle + * @param BackupRegister: RTC Backup data Register number. + * This parameter can be: RTC_BKP_DRx where x can be from 0 to 19 to + * specify the register. + * @retval Read value + */ +uint32_t HAL_RTCEx_BKUPRead(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister) +{ + uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_RTC_BKP(BackupRegister)); + + tmp = (uint32_t)&(hrtc->Instance->BKP0R); + tmp += (BackupRegister * 4); + + /* Read the specified register */ + return (*(__IO uint32_t *)tmp); +} + +/** + * @brief Set the Smooth calibration parameters. + * @param hrtc: RTC handle + * @param SmoothCalibPeriod: Select the Smooth Calibration Period. + * This parameter can be can be one of the following values : + * @arg RTC_SMOOTHCALIB_PERIOD_32SEC: The smooth calibration period is 32s. + * @arg RTC_SMOOTHCALIB_PERIOD_16SEC: The smooth calibration period is 16s. + * @arg RTC_SMOOTHCALIB_PERIOD_8SEC: The smooth calibration period is 8s. + * @param SmoothCalibPlusPulses: Select to Set or reset the CALP bit. + * This parameter can be one of the following values: + * @arg RTC_SMOOTHCALIB_PLUSPULSES_SET: Add one RTCCLK pulse every 2*11 pulses. + * @arg RTC_SMOOTHCALIB_PLUSPULSES_RESET: No RTCCLK pulses are added. + * @param SmoothCalibMinusPulsesValue: Select the value of CALM[8:0] bits. + * This parameter can be one any value from 0 to 0x000001FF. + * @note To deactivate the smooth calibration, the field SmoothCalibPlusPulses + * must be equal to SMOOTHCALIB_PLUSPULSES_RESET and the field + * SmoothCalibMinusPulsesValue must be equal to 0. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_SetSmoothCalib(RTC_HandleTypeDef* hrtc, uint32_t SmoothCalibPeriod, uint32_t SmoothCalibPlusPulses, uint32_t SmoothCalibMinusPulsesValue) +{ + uint32_t tickstart = 0; + + /* Check the parameters */ + assert_param(IS_RTC_SMOOTH_CALIB_PERIOD(SmoothCalibPeriod)); + assert_param(IS_RTC_SMOOTH_CALIB_PLUS(SmoothCalibPlusPulses)); + assert_param(IS_RTC_SMOOTH_CALIB_MINUS(SmoothCalibMinusPulsesValue)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* check if a calibration is pending*/ + if((hrtc->Instance->ISR & RTC_ISR_RECALPF) != RESET) + { + tickstart = HAL_GetTick(); + + /* check if a calibration is pending*/ + while((hrtc->Instance->ISR & RTC_ISR_RECALPF) != RESET) + { + if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_TIMEOUT; + } + } + } + + /* Configure the Smooth calibration settings */ + hrtc->Instance->CALR = (uint32_t)((uint32_t)SmoothCalibPeriod | (uint32_t)SmoothCalibPlusPulses | (uint32_t)SmoothCalibMinusPulsesValue); + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Configure the Synchronization Shift Control Settings. + * @note When REFCKON is set, firmware must not write to Shift control register. + * @param hrtc: RTC handle + * @param ShiftAdd1S: Select to add or not 1 second to the time calendar. + * This parameter can be one of the following values : + * @arg RTC_SHIFTADD1S_SET: Add one second to the clock calendar. + * @arg RTC_SHIFTADD1S_RESET: No effect. + * @param ShiftSubFS: Select the number of Second Fractions to substitute. + * This parameter can be one any value from 0 to 0x7FFF. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_SetSynchroShift(RTC_HandleTypeDef* hrtc, uint32_t ShiftAdd1S, uint32_t ShiftSubFS) +{ + uint32_t tickstart = 0; + + /* Check the parameters */ + assert_param(IS_RTC_SHIFT_ADD1S(ShiftAdd1S)); + assert_param(IS_RTC_SHIFT_SUBFS(ShiftSubFS)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + tickstart = HAL_GetTick(); + + /* Wait until the shift is completed*/ + while((hrtc->Instance->ISR & RTC_ISR_SHPF) != RESET) + { + if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_TIMEOUT; + } + } + + /* Check if the reference clock detection is disabled */ + if((hrtc->Instance->CR & RTC_CR_REFCKON) == RESET) + { + /* Configure the Shift settings */ + hrtc->Instance->SHIFTR = (uint32_t)(uint32_t)(ShiftSubFS) | (uint32_t)(ShiftAdd1S); + + /* If RTC_CR_BYPSHAD bit = 0, wait for synchro else this check is not needed */ + if((hrtc->Instance->CR & RTC_CR_BYPSHAD) == RESET) + { + if(HAL_RTC_WaitForSynchro(hrtc) != HAL_OK) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_ERROR; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_ERROR; + } + } + } + else + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_ERROR; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_ERROR; + } + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Configure the Calibration Pinout (RTC_CALIB) Selection (1Hz or 512Hz). + * @param hrtc: RTC handle + * @param CalibOutput : Select the Calibration output Selection . + * This parameter can be one of the following values: + * @arg RTC_CALIBOUTPUT_512HZ: A signal has a regular waveform at 512Hz. + * @arg RTC_CALIBOUTPUT_1HZ: A signal has a regular waveform at 1Hz. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_SetCalibrationOutPut(RTC_HandleTypeDef* hrtc, uint32_t CalibOutput) +{ + /* Check the parameters */ + assert_param(IS_RTC_CALIB_OUTPUT(CalibOutput)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Clear flags before config */ + hrtc->Instance->CR &= (uint32_t)~RTC_CR_COSEL; + + /* Configure the RTC_CR register */ + hrtc->Instance->CR |= (uint32_t)CalibOutput; + + __HAL_RTC_CALIBRATION_OUTPUT_ENABLE(hrtc); + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Deactivate the Calibration Pinout (RTC_CALIB) Selection (1Hz or 512Hz). + * @param hrtc: RTC handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_DeactivateCalibrationOutPut(RTC_HandleTypeDef* hrtc) +{ + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + __HAL_RTC_CALIBRATION_OUTPUT_DISABLE(hrtc); + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Enable the RTC reference clock detection. + * @param hrtc: RTC handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_SetRefClock(RTC_HandleTypeDef* hrtc) +{ + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Set Initialization mode */ + if(RTC_EnterInitMode(hrtc) != HAL_OK) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Set RTC state*/ + hrtc->State = HAL_RTC_STATE_ERROR; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_ERROR; + } + else + { + __HAL_RTC_CLOCKREF_DETECTION_ENABLE(hrtc); + + /* Exit Initialization mode */ + hrtc->Instance->ISR &= (uint32_t)~RTC_ISR_INIT; + } + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Disable the RTC reference clock detection. + * @param hrtc: RTC handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_DeactivateRefClock(RTC_HandleTypeDef* hrtc) +{ + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Set Initialization mode */ + if(RTC_EnterInitMode(hrtc) != HAL_OK) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Set RTC state*/ + hrtc->State = HAL_RTC_STATE_ERROR; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_ERROR; + } + else + { + __HAL_RTC_CLOCKREF_DETECTION_DISABLE(hrtc); + + /* Exit Initialization mode */ + hrtc->Instance->ISR &= (uint32_t)~RTC_ISR_INIT; + } + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Enable the Bypass Shadow feature. + * @param hrtc: RTC handle + * @note When the Bypass Shadow is enabled the calendar value are taken + * directly from the Calendar counter. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_EnableBypassShadow(RTC_HandleTypeDef* hrtc) +{ + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Set the BYPSHAD bit */ + hrtc->Instance->CR |= (uint8_t)RTC_CR_BYPSHAD; + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Disable the Bypass Shadow feature. + * @param hrtc: RTC handle + * @note When the Bypass Shadow is enabled the calendar value are taken + * directly from the Calendar counter. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_DisableBypassShadow(RTC_HandleTypeDef* hrtc) +{ + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Reset the BYPSHAD bit */ + hrtc->Instance->CR &= ((uint8_t)~RTC_CR_BYPSHAD); + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup RTCEx_Exported_Functions_Group4 Extended features functions + * @brief Extended features functions + * +@verbatim + =============================================================================== + ##### Extended features functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) RTC Alarm B callback + (+) RTC Poll for Alarm B request + +@endverbatim + * @{ + */ + +/** + * @brief Alarm B callback. + * @param hrtc: RTC handle + * @retval None + */ +__weak void HAL_RTCEx_AlarmBEventCallback(RTC_HandleTypeDef *hrtc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hrtc); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_RTCEx_AlarmBEventCallback could be implemented in the user file + */ +} + +/** + * @brief Handle Alarm B Polling request. + * @param hrtc: RTC handle + * @param Timeout: Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_PollForAlarmBEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout) +{ + uint32_t tickstart = HAL_GetTick(); + + while(__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRBF) == RESET) + { + if(Timeout != HAL_MAX_DELAY) + { + if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)) + { + hrtc->State = HAL_RTC_STATE_TIMEOUT; + return HAL_TIMEOUT; + } + } + } + + /* Clear the Alarm Flag */ + __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRBF); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + return HAL_OK; +} + +/** + * @} + */ + +/** + * @} + */ + +#endif /* HAL_RTC_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_tim.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_tim.c new file mode 100644 index 0000000..41d343d --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_tim.c @@ -0,0 +1,5675 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_tim.c + * @author MCD Application Team + * @brief TIM HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Timer (TIM) peripheral: + * + Time Base Initialization + * + Time Base Start + * + Time Base Start Interruption + * + Time Base Start DMA + * + Time Output Compare/PWM Initialization + * + Time Output Compare/PWM Channel Configuration + * + Time Output Compare/PWM Start + * + Time Output Compare/PWM Start Interruption + * + Time Output Compare/PWM Start DMA + * + Time Input Capture Initialization + * + Time Input Capture Channel Configuration + * + Time Input Capture Start + * + Time Input Capture Start Interruption + * + Time Input Capture Start DMA + * + Time One Pulse Initialization + * + Time One Pulse Channel Configuration + * + Time One Pulse Start + * + Time Encoder Interface Initialization + * + Time Encoder Interface Start + * + Time Encoder Interface Start Interruption + * + Time Encoder Interface Start DMA + * + Commutation Event configuration with Interruption and DMA + * + Time OCRef clear configuration + * + Time External Clock configuration + @verbatim + ============================================================================== + ##### TIMER Generic features ##### + ============================================================================== + [..] The Timer features include: + (#) 16-bit up, down, up/down auto-reload counter. + (#) 16-bit programmable prescaler allowing dividing (also on the fly) the + counter clock frequency either by any factor between 1 and 65536. + (#) Up to 4 independent channels for: + (++) Input Capture + (++) Output Compare + (++) PWM generation (Edge and Center-aligned Mode) + (++) One-pulse mode output + + ##### How to use this driver ##### + ============================================================================== + [..] + (#) Initialize the TIM low level resources by implementing the following functions + depending on the selected feature: + (++) Time Base : HAL_TIM_Base_MspInit() + (++) Input Capture : HAL_TIM_IC_MspInit() + (++) Output Compare : HAL_TIM_OC_MspInit() + (++) PWM generation : HAL_TIM_PWM_MspInit() + (++) One-pulse mode output : HAL_TIM_OnePulse_MspInit() + (++) Encoder mode output : HAL_TIM_Encoder_MspInit() + + (#) Initialize the TIM low level resources : + (##) Enable the TIM interface clock using __HAL_RCC_TIMx_CLK_ENABLE(); + (##) TIM pins configuration + (+++) Enable the clock for the TIM GPIOs using the following function: + __HAL_RCC_GPIOx_CLK_ENABLE(); + (+++) Configure these TIM pins in Alternate function mode using HAL_GPIO_Init(); + + (#) The external Clock can be configured, if needed (the default clock is the + internal clock from the APBx), using the following function: + HAL_TIM_ConfigClockSource, the clock configuration should be done before + any start function. + + (#) Configure the TIM in the desired functioning mode using one of the + Initialization function of this driver: + (++) HAL_TIM_Base_Init: to use the Timer to generate a simple time base + (++) HAL_TIM_OC_Init and HAL_TIM_OC_ConfigChannel: to use the Timer to generate an + Output Compare signal. + (++) HAL_TIM_PWM_Init and HAL_TIM_PWM_ConfigChannel: to use the Timer to generate a + PWM signal. + (++) HAL_TIM_IC_Init and HAL_TIM_IC_ConfigChannel: to use the Timer to measure an + external signal. + (++) HAL_TIM_OnePulse_Init and HAL_TIM_OnePulse_ConfigChannel: to use the Timer + in One Pulse Mode. + (++) HAL_TIM_Encoder_Init: to use the Timer Encoder Interface. + + (#) Activate the TIM peripheral using one of the start functions depending from the feature used: + (++) Time Base : HAL_TIM_Base_Start(), HAL_TIM_Base_Start_DMA(), HAL_TIM_Base_Start_IT() + (++) Input Capture : HAL_TIM_IC_Start(), HAL_TIM_IC_Start_DMA(), HAL_TIM_IC_Start_IT() + (++) Output Compare : HAL_TIM_OC_Start(), HAL_TIM_OC_Start_DMA(), HAL_TIM_OC_Start_IT() + (++) PWM generation : HAL_TIM_PWM_Start(), HAL_TIM_PWM_Start_DMA(), HAL_TIM_PWM_Start_IT() + (++) One-pulse mode output : HAL_TIM_OnePulse_Start(), HAL_TIM_OnePulse_Start_IT() + (++) Encoder mode output : HAL_TIM_Encoder_Start(), HAL_TIM_Encoder_Start_DMA(), HAL_TIM_Encoder_Start_IT(). + + (#) The DMA Burst is managed with the two following functions: + HAL_TIM_DMABurst_WriteStart() + HAL_TIM_DMABurst_ReadStart() + + @endverbatim + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup TIM TIM + * @brief TIM HAL module driver + * @{ + */ + +#ifdef HAL_TIM_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +static void TIM_OC1_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config); +static void TIM_OC3_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config); +static void TIM_OC4_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config); +static void TIM_OC5_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config); +static void TIM_OC6_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config); +static void TIM_TI1_ConfigInputStage(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICFilter); +static void TIM_TI2_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection, + uint32_t TIM_ICFilter); +static void TIM_TI2_ConfigInputStage(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICFilter); +static void TIM_TI3_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection, + uint32_t TIM_ICFilter); +static void TIM_TI4_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection, + uint32_t TIM_ICFilter); +static void TIM_ITRx_SetConfig(TIM_TypeDef* TIMx, uint16_t InputTriggerSource); +static void TIM_DMAPeriodElapsedCplt(DMA_HandleTypeDef *hdma); +static void TIM_DMATriggerCplt(DMA_HandleTypeDef *hdma); +static void TIM_SlaveTimer_SetConfig(TIM_HandleTypeDef *htim, + TIM_SlaveConfigTypeDef * sSlaveConfig); +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup TIM_Exported_Functions TIM Exported Functions + * @{ + */ + +/** @defgroup TIM_Exported_Functions_Group1 Time Base functions + * @brief Time Base functions + * +@verbatim + ============================================================================== + ##### Time Base functions ##### + ============================================================================== + [..] + This section provides functions allowing to: + (+) Initialize and configure the TIM base. + (+) De-initialize the TIM base. + (+) Start the Time Base. + (+) Stop the Time Base. + (+) Start the Time Base and enable interrupt. + (+) Stop the Time Base and disable interrupt. + (+) Start the Time Base and enable DMA transfer. + (+) Stop the Time Base and disable DMA transfer. + +@endverbatim + * @{ + */ +/** + * @brief Initializes the TIM Time base Unit according to the specified + * parameters in the TIM_HandleTypeDef and initialize the associated handle. + * @note Switching from Center Aligned counter mode to Edge counter mode (or reverse) + * requires a timer reset to avoid unexpected direction + * due to DIR bit readonly in center aligned mode. + * Ex: call @ref HAL_TIM_Base_DeInit() before HAL_TIM_Base_Init() + * @param htim TIM Base handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_Base_Init(TIM_HandleTypeDef *htim) +{ + /* Check the TIM handle allocation */ + if(htim == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_TIM_INSTANCE(htim->Instance)); + assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode)); + assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision)); + assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload)); + + if(htim->State == HAL_TIM_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + htim->Lock = HAL_UNLOCKED; + + /* Init the low level hardware : GPIO, CLOCK, NVIC */ + HAL_TIM_Base_MspInit(htim); + } + + /* Set the TIM state */ + htim->State= HAL_TIM_STATE_BUSY; + + /* Set the Time Base configuration */ + TIM_Base_SetConfig(htim->Instance, &htim->Init); + + /* Initialize the TIM state*/ + htim->State= HAL_TIM_STATE_READY; + + return HAL_OK; +} + +/** + * @brief DeInitialize the TIM Base peripheral + * @param htim TIM Base handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_Base_DeInit(TIM_HandleTypeDef *htim) +{ + /* Check the parameters */ + assert_param(IS_TIM_INSTANCE(htim->Instance)); + + htim->State = HAL_TIM_STATE_BUSY; + + /* Disable the TIM Peripheral Clock */ + __HAL_TIM_DISABLE(htim); + + /* DeInit the low level hardware: GPIO, CLOCK, NVIC */ + HAL_TIM_Base_MspDeInit(htim); + + /* Change TIM state */ + htim->State = HAL_TIM_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @brief Initializes the TIM Base MSP. + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_TIM_Base_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitialize TIM Base MSP. + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_TIM_Base_MspDeInit could be implemented in the user file + */ +} + + +/** + * @brief Starts the TIM Base generation. + * @param htim TIM handle + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_Base_Start(TIM_HandleTypeDef *htim) +{ + /* Check the parameters */ + assert_param(IS_TIM_INSTANCE(htim->Instance)); + + /* Set the TIM state */ + htim->State= HAL_TIM_STATE_BUSY; + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Change the TIM state*/ + htim->State= HAL_TIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM Base generation. + * @param htim TIM handle + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_Base_Stop(TIM_HandleTypeDef *htim) +{ + /* Check the parameters */ + assert_param(IS_TIM_INSTANCE(htim->Instance)); + + /* Set the TIM state */ + htim->State= HAL_TIM_STATE_BUSY; + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Change the TIM state*/ + htim->State= HAL_TIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Starts the TIM Base generation in interrupt mode. + * @param htim TIM handle + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim) +{ + /* Check the parameters */ + assert_param(IS_TIM_INSTANCE(htim->Instance)); + + /* Enable the TIM Update interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_UPDATE); + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM Base generation in interrupt mode. + * @param htim TIM handle + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_Base_Stop_IT(TIM_HandleTypeDef *htim) +{ + /* Check the parameters */ + assert_param(IS_TIM_INSTANCE(htim->Instance)); + /* Disable the TIM Update interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_UPDATE); + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Starts the TIM Base generation in DMA mode. + * @param htim TIM handle + * @param pData The source Buffer address. + * @param Length The length of data to be transferred from memory to peripheral. + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_Base_Start_DMA(TIM_HandleTypeDef *htim, uint32_t *pData, uint16_t Length) +{ + /* Check the parameters */ + assert_param(IS_TIM_DMA_INSTANCE(htim->Instance)); + + if((htim->State == HAL_TIM_STATE_BUSY)) + { + return HAL_BUSY; + } + else if((htim->State == HAL_TIM_STATE_READY)) + { + if((pData == 0 ) && (Length > 0)) + { + return HAL_ERROR; + } + else + { + htim->State = HAL_TIM_STATE_BUSY; + } + } + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_UPDATE]->XferCpltCallback = TIM_DMAPeriodElapsedCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_UPDATE]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_UPDATE], (uint32_t)pData, (uint32_t)&htim->Instance->ARR, Length); + + /* Enable the TIM Update DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_UPDATE); + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM Base generation in DMA mode. + * @param htim TIM handle + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_Base_Stop_DMA(TIM_HandleTypeDef *htim) +{ + /* Check the parameters */ + assert_param(IS_TIM_DMA_INSTANCE(htim->Instance)); + + /* Disable the TIM Update DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_UPDATE); + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Change the htim state */ + htim->State = HAL_TIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup TIM_Exported_Functions_Group2 Time Output Compare functions + * @brief Time Output Compare functions + * +@verbatim + ============================================================================== + ##### Time Output Compare functions ##### + ============================================================================== + [..] + This section provides functions allowing to: + (+) Initialize and configure the TIM Output Compare. + (+) De-initialize the TIM Output Compare. + (+) Start the Time Output Compare. + (+) Stop the Time Output Compare. + (+) Start the Time Output Compare and enable interrupt. + (+) Stop the Time Output Compare and disable interrupt. + (+) Start the Time Output Compare and enable DMA transfer. + (+) Stop the Time Output Compare and disable DMA transfer. + +@endverbatim + * @{ + */ +/** + * @brief Initializes the TIM Output Compare according to the specified + * parameters in the TIM_HandleTypeDef and initialize the associated handle. + * @note Switching from Center Aligned counter mode to Edge counter mode (or reverse) + * requires a timer reset to avoid unexpected direction + * due to DIR bit readonly in center aligned mode. + * Ex: call @ref HAL_TIM_OC_DeInit() before HAL_TIM_OC_Init() + * @param htim TIM Output Compare handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_OC_Init(TIM_HandleTypeDef* htim) +{ + /* Check the TIM handle allocation */ + if(htim == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_TIM_INSTANCE(htim->Instance)); + assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode)); + assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision)); + assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload)); + + if(htim->State == HAL_TIM_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + htim->Lock = HAL_UNLOCKED; + + /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */ + HAL_TIM_OC_MspInit(htim); + } + + /* Set the TIM state */ + htim->State= HAL_TIM_STATE_BUSY; + + /* Init the base time for the Output Compare */ + TIM_Base_SetConfig(htim->Instance, &htim->Init); + + /* Initialize the TIM state*/ + htim->State= HAL_TIM_STATE_READY; + + return HAL_OK; +} + +/** + * @brief DeInitialize the TIM peripheral + * @param htim TIM Output Compare handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_OC_DeInit(TIM_HandleTypeDef *htim) +{ + /* Check the parameters */ + assert_param(IS_TIM_INSTANCE(htim->Instance)); + + htim->State = HAL_TIM_STATE_BUSY; + + /* Disable the TIM Peripheral Clock */ + __HAL_TIM_DISABLE(htim); + + /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */ + HAL_TIM_OC_MspDeInit(htim); + + /* Change TIM state */ + htim->State = HAL_TIM_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @brief Initializes the TIM Output Compare MSP. + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIM_OC_MspInit(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_TIM_OC_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitialize TIM Output Compare MSP. + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIM_OC_MspDeInit(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_TIM_OC_MspDeInit could be implemented in the user file + */ +} + +/** + * @brief Starts the TIM Output Compare signal generation. + * @param htim TIM Output Compare handle + * @param Channel TIM Channel to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @arg TIM_CHANNEL_5: TIM Channel 5 selected + * @arg TIM_CHANNEL_6: TIM Channel 6 selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_OC_Start(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel)); + + /* Enable the Output compare channel */ + TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE); + + if(IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET) + { + /* Enable the main output */ + __HAL_TIM_MOE_ENABLE(htim); + } + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM Output Compare signal generation. + * @param htim TIM handle + * @param Channel TIM Channel to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @arg TIM_CHANNEL_5: TIM Channel 5 selected + * @arg TIM_CHANNEL_6: TIM Channel 6 selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_OC_Stop(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel)); + + /* Disable the Output compare channel */ + TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE); + + if(IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET) + { + /* Disable the Main Ouput */ + __HAL_TIM_MOE_DISABLE(htim); + } + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Starts the TIM Output Compare signal generation in interrupt mode. + * @param htim TIM OC handle + * @param Channel TIM Channel to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @arg TIM_CHANNEL_5: TIM Channel 5 selected + * @arg TIM_CHANNEL_6: TIM Channel 6 selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_OC_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel)); + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Enable the TIM Capture/Compare 1 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Enable the TIM Capture/Compare 2 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2); + } + break; + + case TIM_CHANNEL_3: + { + /* Enable the TIM Capture/Compare 3 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Enable the TIM Capture/Compare 4 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC4); + } + break; + + default: + break; + } + + /* Enable the Output compare channel */ + TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE); + + if(IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET) + { + /* Enable the main output */ + __HAL_TIM_MOE_ENABLE(htim); + } + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM Output Compare signal generation in interrupt mode. + * @param htim TIM Output Compare handle + * @param Channel TIM Channel to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @arg TIM_CHANNEL_5: TIM Channel 5 selected + * @arg TIM_CHANNEL_6: TIM Channel 6 selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_OC_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel)); + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Disable the TIM Capture/Compare 1 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Disable the TIM Capture/Compare 2 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2); + } + break; + + case TIM_CHANNEL_3: + { + /* Disable the TIM Capture/Compare 3 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Disable the TIM Capture/Compare 4 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC4); + } + break; + + default: + break; + } + + /* Disable the Output compare channel */ + TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE); + + if(IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET) + { + /* Disable the Main Ouput */ + __HAL_TIM_MOE_DISABLE(htim); + } + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Starts the TIM Output Compare signal generation in DMA mode. + * @param htim TIM Output Compare handle + * @param Channel TIM Channel to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @arg TIM_CHANNEL_5: TIM Channel 5 selected + * @arg TIM_CHANNEL_6: TIM Channel 6 selected + * @param pData The source Buffer address. + * @param Length The length of data to be transferred from memory to TIM peripheral + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_OC_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel)); + + if((htim->State == HAL_TIM_STATE_BUSY)) + { + return HAL_BUSY; + } + else if((htim->State == HAL_TIM_STATE_READY)) + { + if(((uint32_t)pData == 0 ) && (Length > 0)) + { + return HAL_ERROR; + } + else + { + htim->State = HAL_TIM_STATE_BUSY; + } + } + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)pData, (uint32_t)&htim->Instance->CCR1, Length); + + /* Enable the TIM Capture/Compare 1 DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)pData, (uint32_t)&htim->Instance->CCR2, Length); + + /* Enable the TIM Capture/Compare 2 DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2); + } + break; + + case TIM_CHANNEL_3: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)pData, (uint32_t)&htim->Instance->CCR3,Length); + + /* Enable the TIM Capture/Compare 3 DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC4]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC4], (uint32_t)pData, (uint32_t)&htim->Instance->CCR4, Length); + + /* Enable the TIM Capture/Compare 4 DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC4); + } + break; + + default: + break; + } + + /* Enable the Output compare channel */ + TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE); + + if(IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET) + { + /* Enable the main output */ + __HAL_TIM_MOE_ENABLE(htim); + } + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM Output Compare signal generation in DMA mode. + * @param htim TIM Output Compare handle + * @param Channel TIM Channel to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @arg TIM_CHANNEL_5: TIM Channel 5 selected + * @arg TIM_CHANNEL_6: TIM Channel 6 selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_OC_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel)); + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Disable the TIM Capture/Compare 1 DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Disable the TIM Capture/Compare 2 DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2); + } + break; + + case TIM_CHANNEL_3: + { + /* Disable the TIM Capture/Compare 3 DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Disable the TIM Capture/Compare 4 interrupt */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC4); + } + break; + + default: + break; + } + + /* Disable the Output compare channel */ + TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE); + + if(IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET) + { + /* Disable the Main Ouput */ + __HAL_TIM_MOE_DISABLE(htim); + } + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Change the htim state */ + htim->State = HAL_TIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup TIM_Exported_Functions_Group3 Time PWM functions + * @brief Time PWM functions + * +@verbatim + ============================================================================== + ##### Time PWM functions ##### + ============================================================================== + [..] + This section provides functions allowing to: + (+) Initialize and configure the TIM OPWM. + (+) De-initialize the TIM PWM. + (+) Start the Time PWM. + (+) Stop the Time PWM. + (+) Start the Time PWM and enable interrupt. + (+) Stop the Time PWM and disable interrupt. + (+) Start the Time PWM and enable DMA transfer. + (+) Stop the Time PWM and disable DMA transfer. + +@endverbatim + * @{ + */ +/** + * @brief Initializes the TIM PWM Time Base according to the specified + * parameters in the TIM_HandleTypeDef and initialize the associated handle. + * @note Switching from Center Aligned counter mode to Edge counter mode (or reverse) + * requires a timer reset to avoid unexpected direction + * due to DIR bit readonly in center aligned mode. + * Ex: call @ref HAL_TIM_PWM_DeInit() before HAL_TIM_PWM_Init() + * @param htim TIM handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_PWM_Init(TIM_HandleTypeDef *htim) +{ + /* Check the TIM handle allocation */ + if(htim == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_TIM_INSTANCE(htim->Instance)); + assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode)); + assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision)); + assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload)); + + if(htim->State == HAL_TIM_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + htim->Lock = HAL_UNLOCKED; + + /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */ + HAL_TIM_PWM_MspInit(htim); + } + + /* Set the TIM state */ + htim->State= HAL_TIM_STATE_BUSY; + + /* Init the base time for the PWM */ + TIM_Base_SetConfig(htim->Instance, &htim->Init); + + /* Initialize the TIM state*/ + htim->State= HAL_TIM_STATE_READY; + + return HAL_OK; +} + +/** + * @brief DeInitialize the TIM peripheral + * @param htim TIM handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_PWM_DeInit(TIM_HandleTypeDef *htim) +{ + /* Check the parameters */ + assert_param(IS_TIM_INSTANCE(htim->Instance)); + + htim->State = HAL_TIM_STATE_BUSY; + + /* Disable the TIM Peripheral Clock */ + __HAL_TIM_DISABLE(htim); + + /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */ + HAL_TIM_PWM_MspDeInit(htim); + + /* Change TIM state */ + htim->State = HAL_TIM_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @brief Initializes the TIM PWM MSP. + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_TIM_PWM_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitialize TIM PWM MSP. + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIM_PWM_MspDeInit(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_TIM_PWM_MspDeInit could be implemented in the user file + */ +} + +/** + * @brief Starts the PWM signal generation. + * @param htim TIM handle + * @param Channel TIM Channels to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @arg TIM_CHANNEL_5: TIM Channel 5 selected + * @arg TIM_CHANNEL_6: TIM Channel 6 selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel)); + + /* Enable the Capture compare channel */ + TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE); + + if(IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET) + { + /* Enable the main output */ + __HAL_TIM_MOE_ENABLE(htim); + } + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the PWM signal generation. + * @param htim TIM handle + * @param Channel TIM Channels to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @arg TIM_CHANNEL_5: TIM Channel 5 selected + * @arg TIM_CHANNEL_6: TIM Channel 6 selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_PWM_Stop(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel)); + + /* Disable the Capture compare channel */ + TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE); + + if(IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET) + { + /* Disable the Main Ouput */ + __HAL_TIM_MOE_DISABLE(htim); + } + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Change the htim state */ + htim->State = HAL_TIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Starts the PWM signal generation in interrupt mode. + * @param htim TIM handle + * @param Channel TIM Channel to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_PWM_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel)); + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Enable the TIM Capture/Compare 1 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Enable the TIM Capture/Compare 2 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2); + } + break; + + case TIM_CHANNEL_3: + { + /* Enable the TIM Capture/Compare 3 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Enable the TIM Capture/Compare 4 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC4); + } + break; + + default: + break; + } + + /* Enable the Capture compare channel */ + TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE); + + if(IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET) + { + /* Enable the main output */ + __HAL_TIM_MOE_ENABLE(htim); + } + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the PWM signal generation in interrupt mode. + * @param htim TIM handle + * @param Channel TIM Channels to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_PWM_Stop_IT (TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel)); + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Disable the TIM Capture/Compare 1 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Disable the TIM Capture/Compare 2 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2); + } + break; + + case TIM_CHANNEL_3: + { + /* Disable the TIM Capture/Compare 3 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Disable the TIM Capture/Compare 4 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC4); + } + break; + + default: + break; + } + + /* Disable the Capture compare channel */ + TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE); + + if(IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET) + { + /* Disable the Main Ouput */ + __HAL_TIM_MOE_DISABLE(htim); + } + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Starts the TIM PWM signal generation in DMA mode. + * @param htim TIM handle + * @param Channel TIM Channels to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @param pData The source Buffer address. + * @param Length The length of data to be transferred from memory to TIM peripheral + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_PWM_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel)); + + if((htim->State == HAL_TIM_STATE_BUSY)) + { + return HAL_BUSY; + } + else if((htim->State == HAL_TIM_STATE_READY)) + { + if(((uint32_t)pData == 0 ) && (Length > 0)) + { + return HAL_ERROR; + } + else + { + htim->State = HAL_TIM_STATE_BUSY; + } + } + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)pData, (uint32_t)&htim->Instance->CCR1, Length); + + /* Enable the TIM Capture/Compare 1 DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)pData, (uint32_t)&htim->Instance->CCR2, Length); + + /* Enable the TIM Capture/Compare 2 DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2); + } + break; + + case TIM_CHANNEL_3: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)pData, (uint32_t)&htim->Instance->CCR3,Length); + + /* Enable the TIM Output Capture/Compare 3 request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC4]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC4], (uint32_t)pData, (uint32_t)&htim->Instance->CCR4, Length); + + /* Enable the TIM Capture/Compare 4 DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC4); + } + break; + + default: + break; + } + + /* Enable the Capture compare channel */ + TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE); + + if(IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET) + { + /* Enable the main output */ + __HAL_TIM_MOE_ENABLE(htim); + } + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM PWM signal generation in DMA mode. + * @param htim TIM handle + * @param Channel TIM Channels to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_PWM_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel)); + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Disable the TIM Capture/Compare 1 DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Disable the TIM Capture/Compare 2 DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2); + } + break; + + case TIM_CHANNEL_3: + { + /* Disable the TIM Capture/Compare 3 DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Disable the TIM Capture/Compare 4 interrupt */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC4); + } + break; + + default: + break; + } + + /* Disable the Capture compare channel */ + TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE); + + if(IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET) + { + /* Disable the Main Ouput */ + __HAL_TIM_MOE_DISABLE(htim); + } + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Change the htim state */ + htim->State = HAL_TIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup TIM_Exported_Functions_Group4 Time Input Capture functions + * @brief Time Input Capture functions + * +@verbatim + ============================================================================== + ##### Time Input Capture functions ##### + ============================================================================== + [..] + This section provides functions allowing to: + (+) Initialize and configure the TIM Input Capture. + (+) De-initialize the TIM Input Capture. + (+) Start the Time Input Capture. + (+) Stop the Time Input Capture. + (+) Start the Time Input Capture and enable interrupt. + (+) Stop the Time Input Capture and disable interrupt. + (+) Start the Time Input Capture and enable DMA transfer. + (+) Stop the Time Input Capture and disable DMA transfer. + +@endverbatim + * @{ + */ +/** + * @brief Initializes the TIM Input Capture Time base according to the specified + * parameters in the TIM_HandleTypeDef and initialize the associated handle. + * @note Switching from Center Aligned counter mode to Edge counter mode (or reverse) + * requires a timer reset to avoid unexpected direction + * due to DIR bit readonly in center aligned mode. + * Ex: call @ref HAL_TIM_IC_DeInit() before HAL_TIM_IC_Init() + * @param htim TIM Input Capture handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_IC_Init(TIM_HandleTypeDef *htim) +{ + /* Check the TIM handle allocation */ + if(htim == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_TIM_INSTANCE(htim->Instance)); + assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode)); + assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision)); + assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload)); + + if(htim->State == HAL_TIM_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + htim->Lock = HAL_UNLOCKED; + + /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */ + HAL_TIM_IC_MspInit(htim); + } + + /* Set the TIM state */ + htim->State= HAL_TIM_STATE_BUSY; + + /* Init the base time for the input capture */ + TIM_Base_SetConfig(htim->Instance, &htim->Init); + + /* Initialize the TIM state*/ + htim->State= HAL_TIM_STATE_READY; + + return HAL_OK; +} + +/** + * @brief DeInitialize the TIM peripheral + * @param htim TIM Input Capture handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_IC_DeInit(TIM_HandleTypeDef *htim) +{ + /* Check the parameters */ + assert_param(IS_TIM_INSTANCE(htim->Instance)); + + htim->State = HAL_TIM_STATE_BUSY; + + /* Disable the TIM Peripheral Clock */ + __HAL_TIM_DISABLE(htim); + + /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */ + HAL_TIM_IC_MspDeInit(htim); + + /* Change TIM state */ + htim->State = HAL_TIM_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @brief Initializes the TIM INput Capture MSP. + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIM_IC_MspInit(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_TIM_IC_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitialize TIM Input Capture MSP. + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIM_IC_MspDeInit(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_TIM_IC_MspDeInit could be implemented in the user file + */ +} + +/** + * @brief Starts the TIM Input Capture measurement. + * @param htim TIM Input Capture handle + * @param Channel TIM Channels to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_IC_Start (TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel)); + + /* Enable the Input Capture channel */ + TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE); + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM Input Capture measurement. + * @param htim TIM handle + * @param Channel TIM Channels to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_IC_Stop(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel)); + + /* Disable the Input Capture channel */ + TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE); + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Starts the TIM Input Capture measurement in interrupt mode. + * @param htim TIM Input Capture handle + * @param Channel TIM Channels to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_IC_Start_IT (TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel)); + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Enable the TIM Capture/Compare 1 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Enable the TIM Capture/Compare 2 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2); + } + break; + + case TIM_CHANNEL_3: + { + /* Enable the TIM Capture/Compare 3 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Enable the TIM Capture/Compare 4 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC4); + } + break; + + default: + break; + } + /* Enable the Input Capture channel */ + TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE); + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM Input Capture measurement in interrupt mode. + * @param htim TIM handle + * @param Channel TIM Channels to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_IC_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel)); + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Disable the TIM Capture/Compare 1 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Disable the TIM Capture/Compare 2 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2); + } + break; + + case TIM_CHANNEL_3: + { + /* Disable the TIM Capture/Compare 3 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Disable the TIM Capture/Compare 4 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC4); + } + break; + + default: + break; + } + + /* Disable the Input Capture channel */ + TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE); + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Starts the TIM Input Capture measurement on in DMA mode. + * @param htim TIM Input Capture handle + * @param Channel TIM Channels to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @param pData The destination Buffer address. + * @param Length The length of data to be transferred from TIM peripheral to memory. + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_IC_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel)); + assert_param(IS_TIM_DMA_CC_INSTANCE(htim->Instance)); + + if((htim->State == HAL_TIM_STATE_BUSY)) + { + return HAL_BUSY; + } + else if((htim->State == HAL_TIM_STATE_READY)) + { + if((pData == 0 ) && (Length > 0)) + { + return HAL_ERROR; + } + else + { + htim->State = HAL_TIM_STATE_BUSY; + } + } + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMACaptureCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)&htim->Instance->CCR1, (uint32_t)pData, Length); + + /* Enable the TIM Capture/Compare 1 DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMACaptureCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)&htim->Instance->CCR2, (uint32_t)pData, Length); + + /* Enable the TIM Capture/Compare 2 DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2); + } + break; + + case TIM_CHANNEL_3: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMACaptureCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)&htim->Instance->CCR3, (uint32_t)pData, Length); + + /* Enable the TIM Capture/Compare 3 DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC4]->XferCpltCallback = TIM_DMACaptureCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC4], (uint32_t)&htim->Instance->CCR4, (uint32_t)pData, Length); + + /* Enable the TIM Capture/Compare 4 DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC4); + } + break; + + default: + break; + } + + /* Enable the Input Capture channel */ + TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE); + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM Input Capture measurement in DMA mode. + * @param htim TIM Input Capture handle + * @param Channel TIM Channels to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_IC_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel)); + assert_param(IS_TIM_DMA_CC_INSTANCE(htim->Instance)); + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Disable the TIM Capture/Compare 1 DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Disable the TIM Capture/Compare 2 DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2); + } + break; + + case TIM_CHANNEL_3: + { + /* Disable the TIM Capture/Compare 3 DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Disable the TIM Capture/Compare 4 DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC4); + } + break; + + default: + break; + } + + /* Disable the Input Capture channel */ + TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE); + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Change the htim state */ + htim->State = HAL_TIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} +/** + * @} + */ + +/** @defgroup TIM_Exported_Functions_Group5 Time One Pulse functions + * @brief Time One Pulse functions + * +@verbatim + ============================================================================== + ##### Time One Pulse functions ##### + ============================================================================== + [..] + This section provides functions allowing to: + (+) Initialize and configure the TIM One Pulse. + (+) De-initialize the TIM One Pulse. + (+) Start the Time One Pulse. + (+) Stop the Time One Pulse. + (+) Start the Time One Pulse and enable interrupt. + (+) Stop the Time One Pulse and disable interrupt. + (+) Start the Time One Pulse and enable DMA transfer. + (+) Stop the Time One Pulse and disable DMA transfer. + +@endverbatim + * @{ + */ +/** + * @brief Initializes the TIM One Pulse Time Base according to the specified + * parameters in the TIM_HandleTypeDef and initialize the associated handle. + * @note Switching from Center Aligned counter mode to Edge counter mode (or reverse) + * requires a timer reset to avoid unexpected direction + * due to DIR bit readonly in center aligned mode. + * Ex: call @ref HAL_TIM_OnePulse_DeInit() before HAL_TIM_OnePulse_Init() + * @param htim TIM OnePulse handle + * @param OnePulseMode Select the One pulse mode. + * This parameter can be one of the following values: + * @arg TIM_OPMODE_SINGLE: Only one pulse will be generated. + * @arg TIM_OPMODE_REPETITIVE: Repetitive pulses will be generated. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_OnePulse_Init(TIM_HandleTypeDef *htim, uint32_t OnePulseMode) +{ + /* Check the TIM handle allocation */ + if(htim == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_TIM_INSTANCE(htim->Instance)); + assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode)); + assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision)); + assert_param(IS_TIM_OPM_MODE(OnePulseMode)); + assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload)); + + if(htim->State == HAL_TIM_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + htim->Lock = HAL_UNLOCKED; + + /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */ + HAL_TIM_OnePulse_MspInit(htim); + } + + /* Set the TIM state */ + htim->State= HAL_TIM_STATE_BUSY; + + /* Configure the Time base in the One Pulse Mode */ + TIM_Base_SetConfig(htim->Instance, &htim->Init); + + /* Reset the OPM Bit */ + htim->Instance->CR1 &= ~TIM_CR1_OPM; + + /* Configure the OPM Mode */ + htim->Instance->CR1 |= OnePulseMode; + + /* Initialize the TIM state*/ + htim->State= HAL_TIM_STATE_READY; + + return HAL_OK; +} + +/** + * @brief DeInitialize the TIM One Pulse + * @param htim TIM One Pulse handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_OnePulse_DeInit(TIM_HandleTypeDef *htim) +{ + /* Check the parameters */ + assert_param(IS_TIM_INSTANCE(htim->Instance)); + + htim->State = HAL_TIM_STATE_BUSY; + + /* Disable the TIM Peripheral Clock */ + __HAL_TIM_DISABLE(htim); + + /* DeInit the low level hardware: GPIO, CLOCK, NVIC */ + HAL_TIM_OnePulse_MspDeInit(htim); + + /* Change TIM state */ + htim->State = HAL_TIM_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @brief Initializes the TIM One Pulse MSP. + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIM_OnePulse_MspInit(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_TIM_OnePulse_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitialize TIM One Pulse MSP. + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIM_OnePulse_MspDeInit(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_TIM_OnePulse_MspDeInit could be implemented in the user file + */ +} + +/** + * @brief Starts the TIM One Pulse signal generation. + * @param htim TIM One Pulse handle + * @param OutputChannel TIM Channels to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_OnePulse_Start(TIM_HandleTypeDef *htim, uint32_t OutputChannel) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(OutputChannel); + + /* Enable the Capture compare and the Input Capture channels + (in the OPM Mode the two possible channels that can be used are TIM_CHANNEL_1 and TIM_CHANNEL_2) + if TIM_CHANNEL_1 is used as output, the TIM_CHANNEL_2 will be used as input and + if TIM_CHANNEL_1 is used as input, the TIM_CHANNEL_2 will be used as output + in all combinations, the TIM_CHANNEL_1 and TIM_CHANNEL_2 should be enabled together + + No need to enable the counter, it's enabled automatically by hardware + (the counter starts in response to a stimulus and generate a pulse */ + + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE); + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE); + + if(IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET) + { + /* Enable the main output */ + __HAL_TIM_MOE_ENABLE(htim); + } + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM One Pulse signal generation. + * @param htim TIM One Pulse handle + * @param OutputChannel TIM Channels to be disable + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_OnePulse_Stop(TIM_HandleTypeDef *htim, uint32_t OutputChannel) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(OutputChannel); + + /* Disable the Capture compare and the Input Capture channels + (in the OPM Mode the two possible channels that can be used are TIM_CHANNEL_1 and TIM_CHANNEL_2) + if TIM_CHANNEL_1 is used as output, the TIM_CHANNEL_2 will be used as input and + if TIM_CHANNEL_1 is used as input, the TIM_CHANNEL_2 will be used as output + in all combinations, the TIM_CHANNEL_1 and TIM_CHANNEL_2 should be disabled together */ + + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE); + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE); + + if(IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET) + { + /* Disable the Main Ouput */ + __HAL_TIM_MOE_DISABLE(htim); + } + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Starts the TIM One Pulse signal generation in interrupt mode. + * @param htim TIM One Pulse handle + * @param OutputChannel TIM Channels to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_OnePulse_Start_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(OutputChannel); + + /* Enable the Capture compare and the Input Capture channels + (in the OPM Mode the two possible channels that can be used are TIM_CHANNEL_1 and TIM_CHANNEL_2) + if TIM_CHANNEL_1 is used as output, the TIM_CHANNEL_2 will be used as input and + if TIM_CHANNEL_1 is used as input, the TIM_CHANNEL_2 will be used as output + in all combinations, the TIM_CHANNEL_1 and TIM_CHANNEL_2 should be enabled together + + No need to enable the counter, it's enabled automatically by hardware + (the counter starts in response to a stimulus and generate a pulse */ + + /* Enable the TIM Capture/Compare 1 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1); + + /* Enable the TIM Capture/Compare 2 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2); + + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE); + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE); + + if(IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET) + { + /* Enable the main output */ + __HAL_TIM_MOE_ENABLE(htim); + } + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM One Pulse signal generation in interrupt mode. + * @param htim TIM One Pulse handle + * @param OutputChannel TIM Channels to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_OnePulse_Stop_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(OutputChannel); + + /* Disable the TIM Capture/Compare 1 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1); + + /* Disable the TIM Capture/Compare 2 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2); + + /* Disable the Capture compare and the Input Capture channels + (in the OPM Mode the two possible channels that can be used are TIM_CHANNEL_1 and TIM_CHANNEL_2) + if TIM_CHANNEL_1 is used as output, the TIM_CHANNEL_2 will be used as input and + if TIM_CHANNEL_1 is used as input, the TIM_CHANNEL_2 will be used as output + in all combinations, the TIM_CHANNEL_1 and TIM_CHANNEL_2 should be disabled together */ + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE); + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE); + + if(IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET) + { + /* Disable the Main Ouput */ + __HAL_TIM_MOE_DISABLE(htim); + } + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup TIM_Exported_Functions_Group6 Time Encoder functions + * @brief Time Encoder functions + * +@verbatim + ============================================================================== + ##### Time Encoder functions ##### + ============================================================================== + [..] + This section provides functions allowing to: + (+) Initialize and configure the TIM Encoder. + (+) De-initialize the TIM Encoder. + (+) Start the Time Encoder. + (+) Stop the Time Encoder. + (+) Start the Time Encoder and enable interrupt. + (+) Stop the Time Encoder and disable interrupt. + (+) Start the Time Encoder and enable DMA transfer. + (+) Stop the Time Encoder and disable DMA transfer. + +@endverbatim + * @{ + */ +/** + * @brief Initializes the TIM Encoder Interface and initialize the associated handle. + * @note Switching from Center Aligned counter mode to Edge counter mode (or reverse) + * requires a timer reset to avoid unexpected direction + * due to DIR bit readonly in center aligned mode. + * Ex: call @ref HAL_TIM_Encoder_DeInit() before HAL_TIM_Encoder_Init() + * @param htim TIM Encoder Interface handle + * @param sConfig TIM Encoder Interface configuration structure + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_Encoder_Init(TIM_HandleTypeDef *htim, TIM_Encoder_InitTypeDef* sConfig) +{ + uint32_t tmpsmcr = 0; + uint32_t tmpccmr1 = 0; + uint32_t tmpccer = 0; + + /* Check the TIM handle allocation */ + if(htim == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_TIM_CC2_INSTANCE(htim->Instance)); + assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode)); + assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision)); + assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload)); + assert_param(IS_TIM_ENCODER_MODE(sConfig->EncoderMode)); + assert_param(IS_TIM_IC_SELECTION(sConfig->IC1Selection)); + assert_param(IS_TIM_IC_SELECTION(sConfig->IC2Selection)); + assert_param(IS_TIM_IC_POLARITY(sConfig->IC1Polarity)); + assert_param(IS_TIM_IC_POLARITY(sConfig->IC2Polarity)); + assert_param(IS_TIM_IC_PRESCALER(sConfig->IC1Prescaler)); + assert_param(IS_TIM_IC_PRESCALER(sConfig->IC2Prescaler)); + assert_param(IS_TIM_IC_FILTER(sConfig->IC1Filter)); + assert_param(IS_TIM_IC_FILTER(sConfig->IC2Filter)); + + if(htim->State == HAL_TIM_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + htim->Lock = HAL_UNLOCKED; + + /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */ + HAL_TIM_Encoder_MspInit(htim); + } + + /* Set the TIM state */ + htim->State= HAL_TIM_STATE_BUSY; + + /* Reset the SMS bits */ + htim->Instance->SMCR &= ~TIM_SMCR_SMS; + + /* Configure the Time base in the Encoder Mode */ + TIM_Base_SetConfig(htim->Instance, &htim->Init); + + /* Get the TIMx SMCR register value */ + tmpsmcr = htim->Instance->SMCR; + + /* Get the TIMx CCMR1 register value */ + tmpccmr1 = htim->Instance->CCMR1; + + /* Get the TIMx CCER register value */ + tmpccer = htim->Instance->CCER; + + /* Set the encoder Mode */ + tmpsmcr |= sConfig->EncoderMode; + + /* Select the Capture Compare 1 and the Capture Compare 2 as input */ + tmpccmr1 &= ~(TIM_CCMR1_CC1S | TIM_CCMR1_CC2S); + tmpccmr1 |= (sConfig->IC1Selection | (sConfig->IC2Selection << 8)); + + /* Set the Capture Compare 1 and the Capture Compare 2 prescalers and filters */ + tmpccmr1 &= ~(TIM_CCMR1_IC1PSC | TIM_CCMR1_IC2PSC); + tmpccmr1 &= ~(TIM_CCMR1_IC1F | TIM_CCMR1_IC2F); + tmpccmr1 |= sConfig->IC1Prescaler | (sConfig->IC2Prescaler << 8); + tmpccmr1 |= (sConfig->IC1Filter << 4) | (sConfig->IC2Filter << 12); + + /* Set the TI1 and the TI2 Polarities */ + tmpccer &= ~(TIM_CCER_CC1P | TIM_CCER_CC2P); + tmpccer &= ~(TIM_CCER_CC1NP | TIM_CCER_CC2NP); + tmpccer |= sConfig->IC1Polarity | (sConfig->IC2Polarity << 4); + + /* Write to TIMx SMCR */ + htim->Instance->SMCR = tmpsmcr; + + /* Write to TIMx CCMR1 */ + htim->Instance->CCMR1 = tmpccmr1; + + /* Write to TIMx CCER */ + htim->Instance->CCER = tmpccer; + + /* Initialize the TIM state*/ + htim->State= HAL_TIM_STATE_READY; + + return HAL_OK; +} + + +/** + * @brief DeInitialize the TIM Encoder interface + * @param htim TIM Encoder handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_Encoder_DeInit(TIM_HandleTypeDef *htim) +{ + /* Check the parameters */ + assert_param(IS_TIM_INSTANCE(htim->Instance)); + + htim->State = HAL_TIM_STATE_BUSY; + + /* Disable the TIM Peripheral Clock */ + __HAL_TIM_DISABLE(htim); + + /* DeInit the low level hardware: GPIO, CLOCK, NVIC */ + HAL_TIM_Encoder_MspDeInit(htim); + + /* Change TIM state */ + htim->State = HAL_TIM_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @brief Initializes the TIM Encoder Interface MSP. + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_TIM_Encoder_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitialize TIM Encoder Interface MSP. + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIM_Encoder_MspDeInit(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_TIM_Encoder_MspDeInit could be implemented in the user file + */ +} + +/** + * @brief Starts the TIM Encoder Interface. + * @param htim TIM Encoder Interface handle + * @param Channel TIM Channels to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_ALL: TIM Channel 1 and TIM Channel 2 are selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_Encoder_Start(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CC2_INSTANCE(htim->Instance)); + + /* Enable the encoder interface channels */ + switch (Channel) + { + case TIM_CHANNEL_1: + { + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE); + } + break; + + case TIM_CHANNEL_2: + { + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE); + } + break; + + default : + { + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE); + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE); + } + break; + } + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM Encoder Interface. + * @param htim TIM Encoder Interface handle + * @param Channel TIM Channels to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_ALL: TIM Channel 1 and TIM Channel 2 are selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_Encoder_Stop(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CC2_INSTANCE(htim->Instance)); + + /* Disable the Input Capture channels 1 and 2 + (in the EncoderInterface the two possible channels that can be used are TIM_CHANNEL_1 and TIM_CHANNEL_2) */ + switch (Channel) + { + case TIM_CHANNEL_1: + { + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE); + } + break; + + case TIM_CHANNEL_2: + { + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE); + } + break; + + default : + { + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE); + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE); + } + break; + } + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Starts the TIM Encoder Interface in interrupt mode. + * @param htim TIM Encoder Interface handle + * @param Channel TIM Channels to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_ALL: TIM Channel 1 and TIM Channel 2 are selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_Encoder_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CC2_INSTANCE(htim->Instance)); + + /* Enable the encoder interface channels */ + /* Enable the capture compare Interrupts 1 and/or 2 */ + switch (Channel) + { + case TIM_CHANNEL_1: + { + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE); + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1); + } + break; + + case TIM_CHANNEL_2: + { + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE); + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2); + } + break; + + default : + { + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE); + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE); + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1); + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2); + } + break; + } + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM Encoder Interface in interrupt mode. + * @param htim TIM Encoder Interface handle + * @param Channel TIM Channels to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_ALL: TIM Channel 1 and TIM Channel 2 are selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_Encoder_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CC2_INSTANCE(htim->Instance)); + + /* Disable the Input Capture channels 1 and 2 + (in the EncoderInterface the two possible channels that can be used are TIM_CHANNEL_1 and TIM_CHANNEL_2) */ + if(Channel == TIM_CHANNEL_1) + { + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE); + + /* Disable the capture compare Interrupts 1 */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1); + } + else if(Channel == TIM_CHANNEL_2) + { + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE); + + /* Disable the capture compare Interrupts 2 */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2); + } + else + { + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE); + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE); + + /* Disable the capture compare Interrupts 1 and 2 */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1); + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2); + } + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Change the htim state */ + htim->State = HAL_TIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Starts the TIM Encoder Interface in DMA mode. + * @param htim TIM Encoder Interface handle + * @param Channel TIM Channels to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_ALL: TIM Channel 1 and TIM Channel 2 are selected + * @param pData1 The destination Buffer address for IC1. + * @param pData2 The destination Buffer address for IC2. + * @param Length The length of data to be transferred from TIM peripheral to memory. + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_Encoder_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData1, uint32_t *pData2, uint16_t Length) +{ + /* Check the parameters */ + assert_param(IS_TIM_DMA_CC_INSTANCE(htim->Instance)); + + if((htim->State == HAL_TIM_STATE_BUSY)) + { + return HAL_BUSY; + } + else if((htim->State == HAL_TIM_STATE_READY)) + { + if((((pData1 == 0) || (pData2 == 0) )) && (Length > 0)) + { + return HAL_ERROR; + } + else + { + htim->State = HAL_TIM_STATE_BUSY; + } + } + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMACaptureCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)&htim->Instance->CCR1, (uint32_t )pData1, Length); + + /* Enable the TIM Input Capture DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1); + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Enable the Capture compare channel */ + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE); + } + break; + + case TIM_CHANNEL_2: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMACaptureCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError; + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)&htim->Instance->CCR2, (uint32_t)pData2, Length); + + /* Enable the TIM Input Capture DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2); + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Enable the Capture compare channel */ + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE); + } + break; + + case TIM_CHANNEL_ALL: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMACaptureCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)&htim->Instance->CCR1, (uint32_t)pData1, Length); + + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMACaptureCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)&htim->Instance->CCR2, (uint32_t)pData2, Length); + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Enable the Capture compare channel */ + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE); + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE); + + /* Enable the TIM Input Capture DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1); + /* Enable the TIM Input Capture DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2); + } + break; + + default: + break; + } + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM Encoder Interface in DMA mode. + * @param htim TIM Encoder Interface handle + * @param Channel TIM Channels to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_ALL: TIM Channel 1 and TIM Channel 2 are selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_Encoder_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_DMA_CC_INSTANCE(htim->Instance)); + + /* Disable the Input Capture channels 1 and 2 + (in the EncoderInterface the two possible channels that can be used are TIM_CHANNEL_1 and TIM_CHANNEL_2) */ + if(Channel == TIM_CHANNEL_1) + { + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE); + + /* Disable the capture compare DMA Request 1 */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1); + } + else if(Channel == TIM_CHANNEL_2) + { + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE); + + /* Disable the capture compare DMA Request 2 */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2); + } + else + { + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE); + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE); + + /* Disable the capture compare DMA Request 1 and 2 */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1); + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2); + } + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Change the htim state */ + htim->State = HAL_TIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @} + */ +/** @defgroup TIM_Exported_Functions_Group7 TIM IRQ handler management + * @brief IRQ handler management + * +@verbatim + ============================================================================== + ##### IRQ handler management ##### + ============================================================================== + [..] + This section provides Timer IRQ handler function. + +@endverbatim + * @{ + */ +/** + * @brief This function handles TIM interrupts requests. + * @param htim TIM handle + * @retval None + */ +void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim) +{ + /* Capture compare 1 event */ + if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC1) != RESET) + { + if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC1) !=RESET) + { + { + __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC1); + htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1; + + /* Input capture event */ + if((htim->Instance->CCMR1 & TIM_CCMR1_CC1S) != 0x00) + { + HAL_TIM_IC_CaptureCallback(htim); + } + /* Output compare event */ + else + { + HAL_TIM_OC_DelayElapsedCallback(htim); + HAL_TIM_PWM_PulseFinishedCallback(htim); + } + htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED; + } + } + } + /* Capture compare 2 event */ + if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC2) != RESET) + { + if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC2) !=RESET) + { + __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC2); + htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2; + /* Input capture event */ + if((htim->Instance->CCMR1 & TIM_CCMR1_CC2S) != 0x00) + { + HAL_TIM_IC_CaptureCallback(htim); + } + /* Output compare event */ + else + { + HAL_TIM_OC_DelayElapsedCallback(htim); + HAL_TIM_PWM_PulseFinishedCallback(htim); + } + htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED; + } + } + /* Capture compare 3 event */ + if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC3) != RESET) + { + if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC3) !=RESET) + { + __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC3); + htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3; + /* Input capture event */ + if((htim->Instance->CCMR2 & TIM_CCMR2_CC3S) != 0x00) + { + HAL_TIM_IC_CaptureCallback(htim); + } + /* Output compare event */ + else + { + HAL_TIM_OC_DelayElapsedCallback(htim); + HAL_TIM_PWM_PulseFinishedCallback(htim); + } + htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED; + } + } + /* Capture compare 4 event */ + if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC4) != RESET) + { + if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC4) !=RESET) + { + __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC4); + htim->Channel = HAL_TIM_ACTIVE_CHANNEL_4; + /* Input capture event */ + if((htim->Instance->CCMR2 & TIM_CCMR2_CC4S) != 0x00) + { + HAL_TIM_IC_CaptureCallback(htim); + } + /* Output compare event */ + else + { + HAL_TIM_OC_DelayElapsedCallback(htim); + HAL_TIM_PWM_PulseFinishedCallback(htim); + } + htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED; + } + } + /* TIM Update event */ + if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_UPDATE) != RESET) + { + if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_UPDATE) !=RESET) + { + __HAL_TIM_CLEAR_IT(htim, TIM_IT_UPDATE); + HAL_TIM_PeriodElapsedCallback(htim); + } + } + /* TIM Break input event */ + if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_BREAK) != RESET) + { + if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_BREAK) !=RESET) + { + __HAL_TIM_CLEAR_IT(htim, TIM_IT_BREAK); + HAL_TIMEx_BreakCallback(htim); + } + } + /* TIM Trigger detection event */ + if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_TRIGGER) != RESET) + { + if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_TRIGGER) !=RESET) + { + __HAL_TIM_CLEAR_IT(htim, TIM_IT_TRIGGER); + HAL_TIM_TriggerCallback(htim); + } + } + /* TIM commutation event */ + if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_COM) != RESET) + { + if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_COM) !=RESET) + { + __HAL_TIM_CLEAR_IT(htim, TIM_FLAG_COM); + HAL_TIMEx_CommutationCallback(htim); + } + } +} + +/** + * @} + */ + +/** @defgroup TIM_Exported_Functions_Group8 Peripheral Control functions + * @brief Peripheral Control functions + * +@verbatim + ============================================================================== + ##### Peripheral Control functions ##### + ============================================================================== + [..] + This section provides functions allowing to: + (+) Configure The Input Output channels for OC, PWM, IC or One Pulse mode. + (+) Configure External Clock source. + (+) Configure Complementary channels, break features and dead time. + (+) Configure Master and the Slave synchronization. + (+) Configure the DMA Burst Mode. + +@endverbatim + * @{ + */ + +/** + * @brief Initializes the TIM Output Compare Channels according to the specified + * parameters in the TIM_OC_InitTypeDef. + * @param htim TIM Output Compare handle + * @param sConfig TIM Output Compare configuration structure + * @param Channel TIM Channels to configure + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @arg TIM_CHANNEL_5: TIM Channel 5 selected + * @arg TIM_CHANNEL_6: TIM Channel 6 selected + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_OC_ConfigChannel(TIM_HandleTypeDef *htim, + TIM_OC_InitTypeDef* sConfig, + uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CHANNELS(Channel)); + assert_param(IS_TIM_OC_MODE(sConfig->OCMode)); + assert_param(IS_TIM_OC_POLARITY(sConfig->OCPolarity)); + + /* Process Locked */ + __HAL_LOCK(htim); + + htim->State = HAL_TIM_STATE_BUSY; + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Check the parameters */ + assert_param(IS_TIM_CC1_INSTANCE(htim->Instance)); + + /* Configure the TIM Channel 1 in Output Compare */ + TIM_OC1_SetConfig(htim->Instance, sConfig); + } + break; + + case TIM_CHANNEL_2: + { + /* Check the parameters */ + assert_param(IS_TIM_CC2_INSTANCE(htim->Instance)); + + /* Configure the TIM Channel 2 in Output Compare */ + TIM_OC2_SetConfig(htim->Instance, sConfig); + } + break; + + case TIM_CHANNEL_3: + { + /* Check the parameters */ + assert_param(IS_TIM_CC3_INSTANCE(htim->Instance)); + + /* Configure the TIM Channel 3 in Output Compare */ + TIM_OC3_SetConfig(htim->Instance, sConfig); + } + break; + + case TIM_CHANNEL_4: + { + /* Check the parameters */ + assert_param(IS_TIM_CC4_INSTANCE(htim->Instance)); + + /* Configure the TIM Channel 4 in Output Compare */ + TIM_OC4_SetConfig(htim->Instance, sConfig); + } + break; + + case TIM_CHANNEL_5: + { + /* Check the parameters */ + assert_param(IS_TIM_CC5_INSTANCE(htim->Instance)); + + /* Configure the TIM Channel 5 in Output Compare */ + TIM_OC5_SetConfig(htim->Instance, sConfig); + } + break; + + case TIM_CHANNEL_6: + { + /* Check the parameters */ + assert_param(IS_TIM_CC6_INSTANCE(htim->Instance)); + + /* Configure the TIM Channel 6 in Output Compare */ + TIM_OC6_SetConfig(htim->Instance, sConfig); + } + break; + + default: + break; + } + + htim->State = HAL_TIM_STATE_READY; + + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @brief Initializes the TIM Input Capture Channels according to the specified + * parameters in the TIM_IC_InitTypeDef. + * @param htim TIM IC handle + * @param sConfig TIM Input Capture configuration structure + * @param Channel TIM Channels to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_IC_ConfigChannel(TIM_HandleTypeDef *htim, TIM_IC_InitTypeDef* sConfig, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CC1_INSTANCE(htim->Instance)); + assert_param(IS_TIM_IC_POLARITY(sConfig->ICPolarity)); + assert_param(IS_TIM_IC_SELECTION(sConfig->ICSelection)); + assert_param(IS_TIM_IC_PRESCALER(sConfig->ICPrescaler)); + assert_param(IS_TIM_IC_FILTER(sConfig->ICFilter)); + + /* Process Locked */ + __HAL_LOCK(htim); + + htim->State = HAL_TIM_STATE_BUSY; + + if (Channel == TIM_CHANNEL_1) + { + /* TI1 Configuration */ + TIM_TI1_SetConfig(htim->Instance, + sConfig->ICPolarity, + sConfig->ICSelection, + sConfig->ICFilter); + + /* Reset the IC1PSC Bits */ + htim->Instance->CCMR1 &= ~TIM_CCMR1_IC1PSC; + + /* Set the IC1PSC value */ + htim->Instance->CCMR1 |= sConfig->ICPrescaler; + } + else if (Channel == TIM_CHANNEL_2) + { + /* TI2 Configuration */ + assert_param(IS_TIM_CC2_INSTANCE(htim->Instance)); + + TIM_TI2_SetConfig(htim->Instance, + sConfig->ICPolarity, + sConfig->ICSelection, + sConfig->ICFilter); + + /* Reset the IC2PSC Bits */ + htim->Instance->CCMR1 &= ~TIM_CCMR1_IC2PSC; + + /* Set the IC2PSC value */ + htim->Instance->CCMR1 |= (sConfig->ICPrescaler << 8); + } + else if (Channel == TIM_CHANNEL_3) + { + /* TI3 Configuration */ + assert_param(IS_TIM_CC3_INSTANCE(htim->Instance)); + + TIM_TI3_SetConfig(htim->Instance, + sConfig->ICPolarity, + sConfig->ICSelection, + sConfig->ICFilter); + + /* Reset the IC3PSC Bits */ + htim->Instance->CCMR2 &= ~TIM_CCMR2_IC3PSC; + + /* Set the IC3PSC value */ + htim->Instance->CCMR2 |= sConfig->ICPrescaler; + } + else + { + /* TI4 Configuration */ + assert_param(IS_TIM_CC4_INSTANCE(htim->Instance)); + + TIM_TI4_SetConfig(htim->Instance, + sConfig->ICPolarity, + sConfig->ICSelection, + sConfig->ICFilter); + + /* Reset the IC4PSC Bits */ + htim->Instance->CCMR2 &= ~TIM_CCMR2_IC4PSC; + + /* Set the IC4PSC value */ + htim->Instance->CCMR2 |= (sConfig->ICPrescaler << 8); + } + + htim->State = HAL_TIM_STATE_READY; + + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @brief Initializes the TIM PWM channels according to the specified + * parameters in the TIM_OC_InitTypeDef. + * @param htim TIM PWM handle + * @param sConfig TIM PWM configuration structure + * @param Channel TIM Channels to be configured + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @arg TIM_CHANNEL_5: TIM Channel 5 selected + * @arg TIM_CHANNEL_6: TIM Channel 6 selected + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_PWM_ConfigChannel(TIM_HandleTypeDef *htim, + TIM_OC_InitTypeDef* sConfig, + uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CHANNELS(Channel)); + assert_param(IS_TIM_PWM_MODE(sConfig->OCMode)); + assert_param(IS_TIM_OC_POLARITY(sConfig->OCPolarity)); + assert_param(IS_TIM_FAST_STATE(sConfig->OCFastMode)); + + /* Process Locked */ + __HAL_LOCK(htim); + + htim->State = HAL_TIM_STATE_BUSY; + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Check the parameters */ + assert_param(IS_TIM_CC1_INSTANCE(htim->Instance)); + + /* Configure the Channel 1 in PWM mode */ + TIM_OC1_SetConfig(htim->Instance, sConfig); + + /* Set the Preload enable bit for channel1 */ + htim->Instance->CCMR1 |= TIM_CCMR1_OC1PE; + + /* Configure the Output Fast mode */ + htim->Instance->CCMR1 &= ~TIM_CCMR1_OC1FE; + htim->Instance->CCMR1 |= sConfig->OCFastMode; + } + break; + + case TIM_CHANNEL_2: + { + /* Check the parameters */ + assert_param(IS_TIM_CC2_INSTANCE(htim->Instance)); + + /* Configure the Channel 2 in PWM mode */ + TIM_OC2_SetConfig(htim->Instance, sConfig); + + /* Set the Preload enable bit for channel2 */ + htim->Instance->CCMR1 |= TIM_CCMR1_OC2PE; + + /* Configure the Output Fast mode */ + htim->Instance->CCMR1 &= ~TIM_CCMR1_OC2FE; + htim->Instance->CCMR1 |= sConfig->OCFastMode << 8; + } + break; + + case TIM_CHANNEL_3: + { + /* Check the parameters */ + assert_param(IS_TIM_CC3_INSTANCE(htim->Instance)); + + /* Configure the Channel 3 in PWM mode */ + TIM_OC3_SetConfig(htim->Instance, sConfig); + + /* Set the Preload enable bit for channel3 */ + htim->Instance->CCMR2 |= TIM_CCMR2_OC3PE; + + /* Configure the Output Fast mode */ + htim->Instance->CCMR2 &= ~TIM_CCMR2_OC3FE; + htim->Instance->CCMR2 |= sConfig->OCFastMode; + } + break; + + case TIM_CHANNEL_4: + { + /* Check the parameters */ + assert_param(IS_TIM_CC4_INSTANCE(htim->Instance)); + + /* Configure the Channel 4 in PWM mode */ + TIM_OC4_SetConfig(htim->Instance, sConfig); + + /* Set the Preload enable bit for channel4 */ + htim->Instance->CCMR2 |= TIM_CCMR2_OC4PE; + + /* Configure the Output Fast mode */ + htim->Instance->CCMR2 &= ~TIM_CCMR2_OC4FE; + htim->Instance->CCMR2 |= sConfig->OCFastMode << 8; + } + break; + + case TIM_CHANNEL_5: + { + /* Check the parameters */ + assert_param(IS_TIM_CC5_INSTANCE(htim->Instance)); + + /* Configure the Channel 5 in PWM mode */ + TIM_OC5_SetConfig(htim->Instance, sConfig); + + /* Set the Preload enable bit for channel5*/ + htim->Instance->CCMR3 |= TIM_CCMR3_OC5PE; + + /* Configure the Output Fast mode */ + htim->Instance->CCMR3 &= ~TIM_CCMR3_OC5FE; + htim->Instance->CCMR3 |= sConfig->OCFastMode; + } + break; + + case TIM_CHANNEL_6: + { + /* Check the parameters */ + assert_param(IS_TIM_CC6_INSTANCE(htim->Instance)); + + /* Configure the Channel 5 in PWM mode */ + TIM_OC6_SetConfig(htim->Instance, sConfig); + + /* Set the Preload enable bit for channel6 */ + htim->Instance->CCMR3 |= TIM_CCMR3_OC6PE; + + /* Configure the Output Fast mode */ + htim->Instance->CCMR3 &= ~TIM_CCMR3_OC6FE; + htim->Instance->CCMR3 |= sConfig->OCFastMode << 8; + } + break; + + default: + break; + } + + htim->State = HAL_TIM_STATE_READY; + + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @brief Initializes the TIM One Pulse Channels according to the specified + * parameters in the TIM_OnePulse_InitTypeDef. + * @param htim TIM One Pulse handle + * @param sConfig TIM One Pulse configuration structure + * @param OutputChannel TIM Channels to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @param InputChannel TIM Channels to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_OnePulse_ConfigChannel(TIM_HandleTypeDef *htim, TIM_OnePulse_InitTypeDef* sConfig, uint32_t OutputChannel, uint32_t InputChannel) +{ + TIM_OC_InitTypeDef temp1; + + /* Check the parameters */ + assert_param(IS_TIM_OPM_CHANNELS(OutputChannel)); + assert_param(IS_TIM_OPM_CHANNELS(InputChannel)); + + if(OutputChannel != InputChannel) + { + /* Process Locked */ + __HAL_LOCK(htim); + + htim->State = HAL_TIM_STATE_BUSY; + + /* Extract the Ouput compare configuration from sConfig structure */ + temp1.OCMode = sConfig->OCMode; + temp1.Pulse = sConfig->Pulse; + temp1.OCPolarity = sConfig->OCPolarity; + temp1.OCNPolarity = sConfig->OCNPolarity; + temp1.OCIdleState = sConfig->OCIdleState; + temp1.OCNIdleState = sConfig->OCNIdleState; + + switch (OutputChannel) + { + case TIM_CHANNEL_1: + { + assert_param(IS_TIM_CC1_INSTANCE(htim->Instance)); + + TIM_OC1_SetConfig(htim->Instance, &temp1); + } + break; + case TIM_CHANNEL_2: + { + assert_param(IS_TIM_CC2_INSTANCE(htim->Instance)); + + TIM_OC2_SetConfig(htim->Instance, &temp1); + } + break; + default: + break; + } + + switch (InputChannel) + { + case TIM_CHANNEL_1: + { + assert_param(IS_TIM_CC1_INSTANCE(htim->Instance)); + + TIM_TI1_SetConfig(htim->Instance, sConfig->ICPolarity, + sConfig->ICSelection, sConfig->ICFilter); + + /* Reset the IC1PSC Bits */ + htim->Instance->CCMR1 &= ~TIM_CCMR1_IC1PSC; + + /* Select the Trigger source */ + htim->Instance->SMCR &= ~TIM_SMCR_TS; + htim->Instance->SMCR |= TIM_TS_TI1FP1; + + /* Select the Slave Mode */ + htim->Instance->SMCR &= ~TIM_SMCR_SMS; + htim->Instance->SMCR |= TIM_SLAVEMODE_TRIGGER; + } + break; + case TIM_CHANNEL_2: + { + assert_param(IS_TIM_CC2_INSTANCE(htim->Instance)); + + TIM_TI2_SetConfig(htim->Instance, sConfig->ICPolarity, + sConfig->ICSelection, sConfig->ICFilter); + + /* Reset the IC2PSC Bits */ + htim->Instance->CCMR1 &= ~TIM_CCMR1_IC2PSC; + + /* Select the Trigger source */ + htim->Instance->SMCR &= ~TIM_SMCR_TS; + htim->Instance->SMCR |= TIM_TS_TI2FP2; + + /* Select the Slave Mode */ + htim->Instance->SMCR &= ~TIM_SMCR_SMS; + htim->Instance->SMCR |= TIM_SLAVEMODE_TRIGGER; + } + break; + + default: + break; + } + + htim->State = HAL_TIM_STATE_READY; + + __HAL_UNLOCK(htim); + + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Configure the DMA Burst to transfer Data from the memory to the TIM peripheral + * @param htim TIM handle + * @param BurstBaseAddress TIM Base address from when the DMA will starts the Data write + * This parameters can be on of the following values: + * @arg TIM_DMABASE_CR1 + * @arg TIM_DMABASE_CR2 + * @arg TIM_DMABASE_SMCR + * @arg TIM_DMABASE_DIER + * @arg TIM_DMABASE_SR + * @arg TIM_DMABASE_EGR + * @arg TIM_DMABASE_CCMR1 + * @arg TIM_DMABASE_CCMR2 + * @arg TIM_DMABASE_CCER + * @arg TIM_DMABASE_CNT + * @arg TIM_DMABASE_PSC + * @arg TIM_DMABASE_ARR + * @arg TIM_DMABASE_RCR + * @arg TIM_DMABASE_CCR1 + * @arg TIM_DMABASE_CCR2 + * @arg TIM_DMABASE_CCR3 + * @arg TIM_DMABASE_CCR4 + * @arg TIM_DMABASE_BDTR + * @arg TIM_DMABASE_DCR + * @param BurstRequestSrc TIM DMA Request sources + * This parameters can be on of the following values: + * @arg TIM_DMA_UPDATE: TIM update Interrupt source + * @arg TIM_DMA_CC1: TIM Capture Compare 1 DMA source + * @arg TIM_DMA_CC2: TIM Capture Compare 2 DMA source + * @arg TIM_DMA_CC3: TIM Capture Compare 3 DMA source + * @arg TIM_DMA_CC4: TIM Capture Compare 4 DMA source + * @arg TIM_DMA_COM: TIM Commutation DMA source + * @arg TIM_DMA_TRIGGER: TIM Trigger DMA source + * @param BurstBuffer The Buffer address. + * @param BurstLength DMA Burst length. This parameter can be one value + * between: TIM_DMABurstLength_1Transfer and TIM_DMABurstLength_18Transfers. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_DMABurst_WriteStart(TIM_HandleTypeDef *htim, uint32_t BurstBaseAddress, uint32_t BurstRequestSrc, + uint32_t* BurstBuffer, uint32_t BurstLength) +{ + /* Check the parameters */ + assert_param(IS_TIM_DMABURST_INSTANCE(htim->Instance)); + assert_param(IS_TIM_DMA_BASE(BurstBaseAddress)); + assert_param(IS_TIM_DMA_SOURCE(BurstRequestSrc)); + assert_param(IS_TIM_DMA_LENGTH(BurstLength)); + + if((htim->State == HAL_TIM_STATE_BUSY)) + { + return HAL_BUSY; + } + else if((htim->State == HAL_TIM_STATE_READY)) + { + if((BurstBuffer == 0 ) && (BurstLength > 0)) + { + return HAL_ERROR; + } + else + { + htim->State = HAL_TIM_STATE_BUSY; + } + } + switch(BurstRequestSrc) + { + case TIM_DMA_UPDATE: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_UPDATE]->XferCpltCallback = TIM_DMAPeriodElapsedCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_UPDATE]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_UPDATE], (uint32_t)BurstBuffer, (uint32_t)&htim->Instance->DMAR, ((BurstLength) >> 8) + 1); + } + break; + case TIM_DMA_CC1: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)BurstBuffer, (uint32_t)&htim->Instance->DMAR, ((BurstLength) >> 8) + 1); + } + break; + case TIM_DMA_CC2: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)BurstBuffer, (uint32_t)&htim->Instance->DMAR, ((BurstLength) >> 8) + 1); + } + break; + case TIM_DMA_CC3: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)BurstBuffer, (uint32_t)&htim->Instance->DMAR, ((BurstLength) >> 8) + 1); + } + break; + case TIM_DMA_CC4: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC4]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC4], (uint32_t)BurstBuffer, (uint32_t)&htim->Instance->DMAR, ((BurstLength) >> 8) + 1); + } + break; + case TIM_DMA_COM: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_COMMUTATION]->XferCpltCallback = TIMEx_DMACommutationCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_COMMUTATION]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_COMMUTATION], (uint32_t)BurstBuffer, (uint32_t)&htim->Instance->DMAR, ((BurstLength) >> 8) + 1); + } + break; + case TIM_DMA_TRIGGER: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_TRIGGER]->XferCpltCallback = TIM_DMATriggerCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_TRIGGER]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_TRIGGER], (uint32_t)BurstBuffer, (uint32_t)&htim->Instance->DMAR, ((BurstLength) >> 8) + 1); + } + break; + default: + break; + } + /* configure the DMA Burst Mode */ + htim->Instance->DCR = BurstBaseAddress | BurstLength; + + /* Enable the TIM DMA Request */ + __HAL_TIM_ENABLE_DMA(htim, BurstRequestSrc); + + htim->State = HAL_TIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM DMA Burst mode + * @param htim TIM handle + * @param BurstRequestSrc TIM DMA Request sources to disable + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_DMABurst_WriteStop(TIM_HandleTypeDef *htim, uint32_t BurstRequestSrc) +{ + /* Check the parameters */ + assert_param(IS_TIM_DMA_SOURCE(BurstRequestSrc)); + + /* Abort the DMA transfer (at least disable the DMA channel) */ + switch(BurstRequestSrc) + { + case TIM_DMA_UPDATE: + { + HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_UPDATE]); + } + break; + case TIM_DMA_CC1: + { + HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_CC1]); + } + break; + case TIM_DMA_CC2: + { + HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_CC2]); + } + break; + case TIM_DMA_CC3: + { + HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_CC3]); + } + break; + case TIM_DMA_CC4: + { + HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_CC4]); + } + break; + case TIM_DMA_COM: + { + HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_COMMUTATION]); + } + break; + case TIM_DMA_TRIGGER: + { + HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_TRIGGER]); + } + break; + default: + break; + } + + /* Disable the TIM Update DMA request */ + __HAL_TIM_DISABLE_DMA(htim, BurstRequestSrc); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Configure the DMA Burst to transfer Data from the TIM peripheral to the memory + * @param htim TIM handle + * @param BurstBaseAddress TIM Base address from when the DMA will starts the Data read + * This parameters can be on of the following values: + * @arg TIM_DMABASE_CR1 + * @arg TIM_DMABASE_CR2 + * @arg TIM_DMABASE_SMCR + * @arg TIM_DMABASE_DIER + * @arg TIM_DMABASE_SR + * @arg TIM_DMABASE_EGR + * @arg TIM_DMABASE_CCMR1 + * @arg TIM_DMABASE_CCMR2 + * @arg TIM_DMABASE_CCER + * @arg TIM_DMABASE_CNT + * @arg TIM_DMABASE_PSC + * @arg TIM_DMABASE_ARR + * @arg TIM_DMABASE_RCR + * @arg TIM_DMABASE_CCR1 + * @arg TIM_DMABASE_CCR2 + * @arg TIM_DMABASE_CCR3 + * @arg TIM_DMABASE_CCR4 + * @arg TIM_DMABASE_BDTR + * @arg TIM_DMABASE_DCR + * @param BurstRequestSrc TIM DMA Request sources + * This parameters can be on of the following values: + * @arg TIM_DMA_UPDATE: TIM update Interrupt source + * @arg TIM_DMA_CC1: TIM Capture Compare 1 DMA source + * @arg TIM_DMA_CC2: TIM Capture Compare 2 DMA source + * @arg TIM_DMA_CC3: TIM Capture Compare 3 DMA source + * @arg TIM_DMA_CC4: TIM Capture Compare 4 DMA source + * @arg TIM_DMA_COM: TIM Commutation DMA source + * @arg TIM_DMA_TRIGGER: TIM Trigger DMA source + * @param BurstBuffer The Buffer address. + * @param BurstLength DMA Burst length. This parameter can be one value + * between: TIM_DMABurstLength_1Transfer and TIM_DMABurstLength_18Transfers. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_DMABurst_ReadStart(TIM_HandleTypeDef *htim, uint32_t BurstBaseAddress, uint32_t BurstRequestSrc, + uint32_t *BurstBuffer, uint32_t BurstLength) +{ + /* Check the parameters */ + assert_param(IS_TIM_DMABURST_INSTANCE(htim->Instance)); + assert_param(IS_TIM_DMA_BASE(BurstBaseAddress)); + assert_param(IS_TIM_DMA_SOURCE(BurstRequestSrc)); + assert_param(IS_TIM_DMA_LENGTH(BurstLength)); + + if((htim->State == HAL_TIM_STATE_BUSY)) + { + return HAL_BUSY; + } + else if((htim->State == HAL_TIM_STATE_READY)) + { + if((BurstBuffer == 0 ) && (BurstLength > 0)) + { + return HAL_ERROR; + } + else + { + htim->State = HAL_TIM_STATE_BUSY; + } + } + switch(BurstRequestSrc) + { + case TIM_DMA_UPDATE: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_UPDATE]->XferCpltCallback = TIM_DMAPeriodElapsedCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_UPDATE]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_UPDATE], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer, ((BurstLength) >> 8) + 1); + } + break; + case TIM_DMA_CC1: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMACaptureCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer, ((BurstLength) >> 8) + 1); + } + break; + case TIM_DMA_CC2: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMACaptureCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer, ((BurstLength) >> 8) + 1); + } + break; + case TIM_DMA_CC3: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMACaptureCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer, ((BurstLength) >> 8) + 1); + } + break; + case TIM_DMA_CC4: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC4]->XferCpltCallback = TIM_DMACaptureCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC4], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer, ((BurstLength) >> 8) + 1); + } + break; + case TIM_DMA_COM: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_COMMUTATION]->XferCpltCallback = TIMEx_DMACommutationCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_COMMUTATION]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_COMMUTATION], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer, ((BurstLength) >> 8) + 1); + } + break; + case TIM_DMA_TRIGGER: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_TRIGGER]->XferCpltCallback = TIM_DMATriggerCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_TRIGGER]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_TRIGGER], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer, ((BurstLength) >> 8) + 1); + } + break; + default: + break; + } + + /* configure the DMA Burst Mode */ + htim->Instance->DCR = BurstBaseAddress | BurstLength; + + /* Enable the TIM DMA Request */ + __HAL_TIM_ENABLE_DMA(htim, BurstRequestSrc); + + htim->State = HAL_TIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stop the DMA burst reading + * @param htim TIM handle + * @param BurstRequestSrc TIM DMA Request sources to disable. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_DMABurst_ReadStop(TIM_HandleTypeDef *htim, uint32_t BurstRequestSrc) +{ + /* Check the parameters */ + assert_param(IS_TIM_DMA_SOURCE(BurstRequestSrc)); + + /* Abort the DMA transfer (at least disable the DMA channel) */ + switch(BurstRequestSrc) + { + case TIM_DMA_UPDATE: + { + HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_UPDATE]); + } + break; + case TIM_DMA_CC1: + { + HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_CC1]); + } + break; + case TIM_DMA_CC2: + { + HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_CC2]); + } + break; + case TIM_DMA_CC3: + { + HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_CC3]); + } + break; + case TIM_DMA_CC4: + { + HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_CC4]); + } + break; + case TIM_DMA_COM: + { + HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_COMMUTATION]); + } + break; + case TIM_DMA_TRIGGER: + { + HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_TRIGGER]); + } + break; + default: + break; + } + + /* Disable the TIM Update DMA request */ + __HAL_TIM_DISABLE_DMA(htim, BurstRequestSrc); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Generate a software event + * @param htim TIM handle + * @param EventSource specifies the event source. + * This parameter can be one of the following values: + * @arg TIM_EVENTSOURCE_UPDATE: Timer update Event source + * @arg TIM_EVENTSOURCE_CC1: Timer Capture Compare 1 Event source + * @arg TIM_EVENTSOURCE_CC2: Timer Capture Compare 2 Event source + * @arg TIM_EVENTSOURCE_CC3: Timer Capture Compare 3 Event source + * @arg TIM_EVENTSOURCE_CC4: Timer Capture Compare 4 Event source + * @arg TIM_EVENTSOURCE_COM: Timer COM event source + * @arg TIM_EVENTSOURCE_TRIGGER: Timer Trigger Event source + * @arg TIM_EVENTSOURCE_BREAK: Timer Break event source + * @arg TIM_EVENTSOURCE_BREAK2: Timer Break2 event source + * @retval HAL status + */ + +HAL_StatusTypeDef HAL_TIM_GenerateEvent(TIM_HandleTypeDef *htim, uint32_t EventSource) +{ + /* Check the parameters */ + assert_param(IS_TIM_INSTANCE(htim->Instance)); + assert_param(IS_TIM_EVENT_SOURCE(EventSource)); + + /* Process Locked */ + __HAL_LOCK(htim); + + /* Change the TIM state */ + htim->State = HAL_TIM_STATE_BUSY; + + /* Set the event sources */ + htim->Instance->EGR = EventSource; + + /* Change the TIM state */ + htim->State = HAL_TIM_STATE_READY; + + __HAL_UNLOCK(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Configures the OCRef clear feature + * @param htim TIM handle + * @param sClearInputConfig pointer to a TIM_ClearInputConfigTypeDef structure that + * contains the OCREF clear feature and parameters for the TIM peripheral. + * @param Channel specifies the TIM Channel + * This parameter can be one of the following values: + * @arg TIM_Channel_1: TIM Channel 1 + * @arg TIM_Channel_2: TIM Channel 2 + * @arg TIM_Channel_3: TIM Channel 3 + * @arg TIM_Channel_4: TIM Channel 4 + * @arg TIM_Channel_5: TIM Channel 5 + * @arg TIM_Channel_6: TIM Channel 6 + * @retval None + */ +HAL_StatusTypeDef HAL_TIM_ConfigOCrefClear(TIM_HandleTypeDef *htim, + TIM_ClearInputConfigTypeDef *sClearInputConfig, + uint32_t Channel) +{ + uint32_t tmpsmcr = 0; + + /* Check the parameters */ + assert_param(IS_TIM_OCXREF_CLEAR_INSTANCE(htim->Instance)); + assert_param(IS_TIM_CLEARINPUT_SOURCE(sClearInputConfig->ClearInputSource)); + + /* Process Locked */ + __HAL_LOCK(htim); + + switch (sClearInputConfig->ClearInputSource) + { + case TIM_CLEARINPUTSOURCE_NONE: + { + /* Get the TIMx SMCR register value */ + tmpsmcr = htim->Instance->SMCR; + + /* Clear the OCREF clear selection bit */ + tmpsmcr &= ~TIM_SMCR_OCCS; + + /* Clear the ETR Bits */ + tmpsmcr &= ~(TIM_SMCR_ETF | TIM_SMCR_ETPS | TIM_SMCR_ECE | TIM_SMCR_ETP); + + /* Set TIMx_SMCR */ + htim->Instance->SMCR = tmpsmcr; + } + break; + + case TIM_CLEARINPUTSOURCE_OCREFCLR: + { + /* Clear the OCREF clear selection bit */ + htim->Instance->SMCR &= ~TIM_SMCR_OCCS; + } + break; + + case TIM_CLEARINPUTSOURCE_ETR: + { + /* Check the parameters */ + assert_param(IS_TIM_CLEARINPUT_POLARITY(sClearInputConfig->ClearInputPolarity)); + assert_param(IS_TIM_CLEARINPUT_PRESCALER(sClearInputConfig->ClearInputPrescaler)); + assert_param(IS_TIM_CLEARINPUT_FILTER(sClearInputConfig->ClearInputFilter)); + + TIM_ETR_SetConfig(htim->Instance, + sClearInputConfig->ClearInputPrescaler, + sClearInputConfig->ClearInputPolarity, + sClearInputConfig->ClearInputFilter); + + /* Set the OCREF clear selection bit */ + htim->Instance->SMCR |= TIM_SMCR_OCCS; + } + break; + + default: + break; + } + + switch (Channel) + { + case TIM_CHANNEL_1: + { + if(sClearInputConfig->ClearInputState != RESET) + { + /* Enable the OCREF clear feature for Channel 1 */ + htim->Instance->CCMR1 |= TIM_CCMR1_OC1CE; + } + else + { + /* Disable the OCREF clear feature for Channel 1 */ + htim->Instance->CCMR1 &= ~TIM_CCMR1_OC1CE; + } + } + break; + case TIM_CHANNEL_2: + { + if(sClearInputConfig->ClearInputState != RESET) + { + /* Enable the OCREF clear feature for Channel 2 */ + htim->Instance->CCMR1 |= TIM_CCMR1_OC2CE; + } + else + { + /* Disable the OCREF clear feature for Channel 2 */ + htim->Instance->CCMR1 &= ~TIM_CCMR1_OC2CE; + } + } + break; + case TIM_CHANNEL_3: + { + if(sClearInputConfig->ClearInputState != RESET) + { + /* Enable the OCREF clear feature for Channel 3 */ + htim->Instance->CCMR2 |= TIM_CCMR2_OC3CE; + } + else + { + /* Disable the OCREF clear feature for Channel 3 */ + htim->Instance->CCMR2 &= ~TIM_CCMR2_OC3CE; + } + } + break; + case TIM_CHANNEL_4: + { + if(sClearInputConfig->ClearInputState != RESET) + { + /* Enable the OCREF clear feature for Channel 4 */ + htim->Instance->CCMR2 |= TIM_CCMR2_OC4CE; + } + else + { + /* Disable the OCREF clear feature for Channel 4 */ + htim->Instance->CCMR2 &= ~TIM_CCMR2_OC4CE; + } + } + break; + case TIM_CHANNEL_5: + { + if(sClearInputConfig->ClearInputState != RESET) + { + /* Enable the OCREF clear feature for Channel 1 */ + htim->Instance->CCMR3 |= TIM_CCMR3_OC5CE; + } + else + { + /* Disable the OCREF clear feature for Channel 1 */ + htim->Instance->CCMR3 &= ~TIM_CCMR3_OC5CE; + } + } + break; + case TIM_CHANNEL_6: + { + if(sClearInputConfig->ClearInputState != RESET) + { + /* Enable the OCREF clear feature for Channel 1 */ + htim->Instance->CCMR3 |= TIM_CCMR3_OC6CE; + } + else + { + /* Disable the OCREF clear feature for Channel 1 */ + htim->Instance->CCMR3 &= ~TIM_CCMR3_OC6CE; + } + } + break; + default: + break; + } + + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @brief Configures the clock source to be used + * @param htim TIM handle + * @param sClockSourceConfig pointer to a TIM_ClockConfigTypeDef structure that + * contains the clock source information for the TIM peripheral. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_ConfigClockSource(TIM_HandleTypeDef *htim, TIM_ClockConfigTypeDef * sClockSourceConfig) +{ + uint32_t tmpsmcr = 0; + + /* Process Locked */ + __HAL_LOCK(htim); + + htim->State = HAL_TIM_STATE_BUSY; + + /* Check the parameters */ + assert_param(IS_TIM_CLOCKSOURCE(sClockSourceConfig->ClockSource)); + + /* Reset the SMS, TS, ECE, ETPS and ETRF bits */ + tmpsmcr = htim->Instance->SMCR; + tmpsmcr &= ~(TIM_SMCR_SMS | TIM_SMCR_TS); + tmpsmcr &= ~(TIM_SMCR_ETF | TIM_SMCR_ETPS | TIM_SMCR_ECE | TIM_SMCR_ETP); + htim->Instance->SMCR = tmpsmcr; + + switch (sClockSourceConfig->ClockSource) + { + case TIM_CLOCKSOURCE_INTERNAL: + { + assert_param(IS_TIM_INSTANCE(htim->Instance)); + /* Disable slave mode to clock the prescaler directly with the internal clock */ + htim->Instance->SMCR &= ~TIM_SMCR_SMS; + } + break; + + case TIM_CLOCKSOURCE_ETRMODE1: + { + /* Check whether or not the timer instance supports external trigger input mode 1 (ETRF)*/ + assert_param(IS_TIM_CLOCKSOURCE_ETRMODE1_INSTANCE(htim->Instance)); + + /* Check ETR input conditioning related parameters */ + assert_param(IS_TIM_CLOCKPRESCALER(sClockSourceConfig->ClockPrescaler)); + assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity)); + assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter)); + + /* Configure the ETR Clock source */ + TIM_ETR_SetConfig(htim->Instance, + sClockSourceConfig->ClockPrescaler, + sClockSourceConfig->ClockPolarity, + sClockSourceConfig->ClockFilter); + /* Get the TIMx SMCR register value */ + tmpsmcr = htim->Instance->SMCR; + /* Reset the SMS and TS Bits */ + tmpsmcr &= ~(TIM_SMCR_SMS | TIM_SMCR_TS); + /* Select the External clock mode1 and the ETRF trigger */ + tmpsmcr |= (TIM_SLAVEMODE_EXTERNAL1 | TIM_CLOCKSOURCE_ETRMODE1); + /* Write to TIMx SMCR */ + htim->Instance->SMCR = tmpsmcr; + } + break; + + case TIM_CLOCKSOURCE_ETRMODE2: + { + /* Check whether or not the timer instance supports external trigger input mode 2 (ETRF)*/ + assert_param(IS_TIM_CLOCKSOURCE_ETRMODE2_INSTANCE(htim->Instance)); + + /* Check ETR input conditioning related parameters */ + assert_param(IS_TIM_CLOCKPRESCALER(sClockSourceConfig->ClockPrescaler)); + assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity)); + assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter)); + + /* Configure the ETR Clock source */ + TIM_ETR_SetConfig(htim->Instance, + sClockSourceConfig->ClockPrescaler, + sClockSourceConfig->ClockPolarity, + sClockSourceConfig->ClockFilter); + /* Enable the External clock mode2 */ + htim->Instance->SMCR |= TIM_SMCR_ECE; + } + break; + + case TIM_CLOCKSOURCE_TI1: + { + /* Check whether or not the timer instance supports external clock mode 1 */ + assert_param(IS_TIM_CLOCKSOURCE_TIX_INSTANCE(htim->Instance)); + + /* Check TI1 input conditioning related parameters */ + assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity)); + assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter)); + + TIM_TI1_ConfigInputStage(htim->Instance, + sClockSourceConfig->ClockPolarity, + sClockSourceConfig->ClockFilter); + TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_TI1); + } + break; + + case TIM_CLOCKSOURCE_TI2: + { + /* Check whether or not the timer instance supports external clock mode 1 (ETRF)*/ + assert_param(IS_TIM_CLOCKSOURCE_TIX_INSTANCE(htim->Instance)); + + /* Check TI2 input conditioning related parameters */ + assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity)); + assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter)); + + TIM_TI2_ConfigInputStage(htim->Instance, + sClockSourceConfig->ClockPolarity, + sClockSourceConfig->ClockFilter); + TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_TI2); + } + break; + + case TIM_CLOCKSOURCE_TI1ED: + { + /* Check whether or not the timer instance supports external clock mode 1 */ + assert_param(IS_TIM_CLOCKSOURCE_TIX_INSTANCE(htim->Instance)); + + /* Check TI1 input conditioning related parameters */ + assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity)); + assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter)); + + TIM_TI1_ConfigInputStage(htim->Instance, + sClockSourceConfig->ClockPolarity, + sClockSourceConfig->ClockFilter); + TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_TI1ED); + } + break; + + case TIM_CLOCKSOURCE_ITR0: + { + /* Check whether or not the timer instance supports internal trigger input */ + assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance)); + + TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_ITR0); + } + break; + + case TIM_CLOCKSOURCE_ITR1: + { + /* Check whether or not the timer instance supports internal trigger input */ + assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance)); + + TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_ITR1); + } + break; + + case TIM_CLOCKSOURCE_ITR2: + { + /* Check whether or not the timer instance supports internal trigger input */ + assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance)); + + TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_ITR2); + } + break; + + case TIM_CLOCKSOURCE_ITR3: + { + /* Check whether or not the timer instance supports internal trigger input */ + assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance)); + + TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_ITR3); + } + break; + + default: + break; + } + htim->State = HAL_TIM_STATE_READY; + + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @brief Selects the signal connected to the TI1 input: direct from CH1_input + * or a XOR combination between CH1_input, CH2_input & CH3_input + * @param htim TIM handle. + * @param TI1_Selection Indicate whether or not channel 1 is connected to the + * output of a XOR gate. + * This parameter can be one of the following values: + * @arg TIM_TI1SELECTION_CH1: The TIMx_CH1 pin is connected to TI1 input + * @arg TIM_TI1SELECTION_XORCOMBINATION: The TIMx_CH1, CH2 and CH3 + * pins are connected to the TI1 input (XOR combination) + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_ConfigTI1Input(TIM_HandleTypeDef *htim, uint32_t TI1_Selection) +{ + uint32_t tmpcr2 = 0; + + /* Check the parameters */ + assert_param(IS_TIM_XOR_INSTANCE(htim->Instance)); + assert_param(IS_TIM_TI1SELECTION(TI1_Selection)); + + /* Get the TIMx CR2 register value */ + tmpcr2 = htim->Instance->CR2; + + /* Reset the TI1 selection */ + tmpcr2 &= ~TIM_CR2_TI1S; + + /* Set the TI1 selection */ + tmpcr2 |= TI1_Selection; + + /* Write to TIMxCR2 */ + htim->Instance->CR2 = tmpcr2; + + return HAL_OK; +} + +/** + * @brief Configures the TIM in Slave mode + * @param htim TIM handle. + * @param sSlaveConfig pointer to a TIM_SlaveConfigTypeDef structure that + * contains the selected trigger (internal trigger input, filtered + * timer input or external trigger input) and the ) and the Slave + * mode (Disable, Reset, Gated, Trigger, External clock mode 1). + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_SlaveConfigSynchronization(TIM_HandleTypeDef *htim, TIM_SlaveConfigTypeDef * sSlaveConfig) +{ + /* Check the parameters */ + assert_param(IS_TIM_SLAVE_INSTANCE(htim->Instance)); + assert_param(IS_TIM_SLAVE_MODE(sSlaveConfig->SlaveMode)); + assert_param(IS_TIM_TRIGGER_SELECTION(sSlaveConfig->InputTrigger)); + + __HAL_LOCK(htim); + + htim->State = HAL_TIM_STATE_BUSY; + + TIM_SlaveTimer_SetConfig(htim, sSlaveConfig); + + /* Disable Trigger Interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_TRIGGER); + + /* Disable Trigger DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_TRIGGER); + + htim->State = HAL_TIM_STATE_READY; + + __HAL_UNLOCK(htim); + + return HAL_OK; + } + +/** + * @brief Configures the TIM in Slave mode in interrupt mode + * @param htim TIM handle. + * @param sSlaveConfig pointer to a TIM_SlaveConfigTypeDef structure that + * contains the selected trigger (internal trigger input, filtered + * timer input or external trigger input) and the ) and the Slave + * mode (Disable, Reset, Gated, Trigger, External clock mode 1). + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_SlaveConfigSynchronization_IT(TIM_HandleTypeDef *htim, + TIM_SlaveConfigTypeDef * sSlaveConfig) + { + /* Check the parameters */ + assert_param(IS_TIM_SLAVE_INSTANCE(htim->Instance)); + assert_param(IS_TIM_SLAVE_MODE(sSlaveConfig->SlaveMode)); + assert_param(IS_TIM_TRIGGER_SELECTION(sSlaveConfig->InputTrigger)); + + __HAL_LOCK(htim); + + htim->State = HAL_TIM_STATE_BUSY; + + TIM_SlaveTimer_SetConfig(htim, sSlaveConfig); + + /* Enable Trigger Interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_TRIGGER); + + /* Disable Trigger DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_TRIGGER); + + htim->State = HAL_TIM_STATE_READY; + + __HAL_UNLOCK(htim); + + return HAL_OK; + } + +/** + * @brief Read the captured value from Capture Compare unit + * @param htim TIM handle. + * @param Channel TIM Channels to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @retval Captured value + */ +uint32_t HAL_TIM_ReadCapturedValue(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + uint32_t tmpreg = 0; + + __HAL_LOCK(htim); + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Check the parameters */ + assert_param(IS_TIM_CC1_INSTANCE(htim->Instance)); + + /* Return the capture 1 value */ + tmpreg = htim->Instance->CCR1; + + break; + } + case TIM_CHANNEL_2: + { + /* Check the parameters */ + assert_param(IS_TIM_CC2_INSTANCE(htim->Instance)); + + /* Return the capture 2 value */ + tmpreg = htim->Instance->CCR2; + + break; + } + + case TIM_CHANNEL_3: + { + /* Check the parameters */ + assert_param(IS_TIM_CC3_INSTANCE(htim->Instance)); + + /* Return the capture 3 value */ + tmpreg = htim->Instance->CCR3; + + break; + } + + case TIM_CHANNEL_4: + { + /* Check the parameters */ + assert_param(IS_TIM_CC4_INSTANCE(htim->Instance)); + + /* Return the capture 4 value */ + tmpreg = htim->Instance->CCR4; + + break; + } + + default: + break; + } + + __HAL_UNLOCK(htim); + return tmpreg; +} + +/** + * @} + */ + +/** @defgroup TIM_Exported_Functions_Group9 TIM Callbacks functions + * @brief TIM Callbacks functions + * +@verbatim + ============================================================================== + ##### TIM Callbacks functions ##### + ============================================================================== + [..] + This section provides TIM callback functions: + (+) Timer Period elapsed callback + (+) Timer Output Compare callback + (+) Timer Input capture callback + (+) Timer Trigger callback + (+) Timer Error callback + +@endverbatim + * @{ + */ + +/** + * @brief Period elapsed callback in non-blocking mode + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the __HAL_TIM_PeriodElapsedCallback could be implemented in the user file + */ + +} +/** + * @brief Output Compare callback in non-blocking mode + * @param htim TIM OC handle + * @retval None + */ +__weak void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the __HAL_TIM_OC_DelayElapsedCallback could be implemented in the user file + */ +} +/** + * @brief Input Capture callback in non-blocking mode + * @param htim TIM IC handle + * @retval None + */ +__weak void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the __HAL_TIM_IC_CaptureCallback could be implemented in the user file + */ +} + +/** + * @brief PWM Pulse finished callback in non-blocking mode + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the __HAL_TIM_PWM_PulseFinishedCallback could be implemented in the user file + */ +} + +/** + * @brief Hall Trigger detection callback in non-blocking mode + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIM_TriggerCallback(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_TIM_TriggerCallback could be implemented in the user file + */ +} + +/** + * @brief Timer error callback in non-blocking mode + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIM_ErrorCallback(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_TIM_ErrorCallback could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup TIM_Exported_Functions_Group10 Peripheral State functions + * @brief Peripheral State functions + * +@verbatim + ============================================================================== + ##### Peripheral State functions ##### + ============================================================================== + [..] + This subsection permits to get in run-time the status of the peripheral + and the data flow. + +@endverbatim + * @{ + */ + +/** + * @brief Return the TIM Base handle state. + * @param htim TIM Base handle + * @retval HAL state + */ +HAL_TIM_StateTypeDef HAL_TIM_Base_GetState(TIM_HandleTypeDef *htim) +{ + return htim->State; +} + +/** + * @brief Return the TIM OC handle state. + * @param htim TIM Ouput Compare handle + * @retval HAL state + */ +HAL_TIM_StateTypeDef HAL_TIM_OC_GetState(TIM_HandleTypeDef *htim) +{ + return htim->State; +} + +/** + * @brief Return the TIM PWM handle state. + * @param htim TIM handle + * @retval HAL state + */ +HAL_TIM_StateTypeDef HAL_TIM_PWM_GetState(TIM_HandleTypeDef *htim) +{ + return htim->State; +} + +/** + * @brief Return the TIM Input Capture handle state. + * @param htim TIM IC handle + * @retval HAL state + */ +HAL_TIM_StateTypeDef HAL_TIM_IC_GetState(TIM_HandleTypeDef *htim) +{ + return htim->State; +} + +/** + * @brief Return the TIM One Pulse Mode handle state. + * @param htim TIM OPM handle + * @retval HAL state + */ +HAL_TIM_StateTypeDef HAL_TIM_OnePulse_GetState(TIM_HandleTypeDef *htim) +{ + return htim->State; +} + +/** + * @brief Return the TIM Encoder Mode handle state. + * @param htim TIM Encoder handle + * @retval HAL state + */ +HAL_TIM_StateTypeDef HAL_TIM_Encoder_GetState(TIM_HandleTypeDef *htim) +{ + return htim->State; +} + +/** + * @} + */ + +/** + * @brief TIM DMA error callback + * @param hdma pointer to DMA handle. + * @retval None + */ +void TIM_DMAError(DMA_HandleTypeDef *hdma) +{ + TIM_HandleTypeDef* htim = ( TIM_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; + + htim->State= HAL_TIM_STATE_READY; + + HAL_TIM_ErrorCallback(htim); +} + +/** + * @brief TIM DMA Delay Pulse complete callback. + * @param hdma pointer to DMA handle. + * @retval None + */ +void TIM_DMADelayPulseCplt(DMA_HandleTypeDef *hdma) +{ + TIM_HandleTypeDef* htim = ( TIM_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; + + htim->State= HAL_TIM_STATE_READY; + + if (hdma == htim->hdma[TIM_DMA_ID_CC1]) + { + htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1; + } + else if (hdma == htim->hdma[TIM_DMA_ID_CC2]) + { + htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2; + } + else if (hdma == htim->hdma[TIM_DMA_ID_CC3]) + { + htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3; + } + else if (hdma == htim->hdma[TIM_DMA_ID_CC4]) + { + htim->Channel = HAL_TIM_ACTIVE_CHANNEL_4; + } + + HAL_TIM_PWM_PulseFinishedCallback(htim); + + htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED; +} +/** + * @brief TIM DMA Capture complete callback. + * @param hdma pointer to DMA handle. + * @retval None + */ +void TIM_DMACaptureCplt(DMA_HandleTypeDef *hdma) +{ + TIM_HandleTypeDef* htim = ( TIM_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; + + htim->State= HAL_TIM_STATE_READY; + + if (hdma == htim->hdma[TIM_DMA_ID_CC1]) + { + htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1; + } + else if (hdma == htim->hdma[TIM_DMA_ID_CC2]) + { + htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2; + } + else if (hdma == htim->hdma[TIM_DMA_ID_CC3]) + { + htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3; + } + else if (hdma == htim->hdma[TIM_DMA_ID_CC4]) + { + htim->Channel = HAL_TIM_ACTIVE_CHANNEL_4; + } + + HAL_TIM_IC_CaptureCallback(htim); + + htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED; +} + +/** + * @brief TIM DMA Period Elapse complete callback. + * @param hdma pointer to DMA handle. + * @retval None + */ +static void TIM_DMAPeriodElapsedCplt(DMA_HandleTypeDef *hdma) +{ + TIM_HandleTypeDef* htim = ( TIM_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; + + htim->State= HAL_TIM_STATE_READY; + + HAL_TIM_PeriodElapsedCallback(htim); +} + +/** + * @brief TIM DMA Trigger callback. + * @param hdma pointer to DMA handle. + * @retval None + */ +static void TIM_DMATriggerCplt(DMA_HandleTypeDef *hdma) +{ + TIM_HandleTypeDef* htim = ( TIM_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; + + htim->State= HAL_TIM_STATE_READY; + + HAL_TIM_TriggerCallback(htim); +} + +/** + * @brief Time Base configuration + * @param TIMx TIM peripheral + * @param Structure TIM Base configuration structure + * @retval None + */ +void TIM_Base_SetConfig(TIM_TypeDef *TIMx, TIM_Base_InitTypeDef *Structure) +{ + uint32_t tmpcr1 = 0; + tmpcr1 = TIMx->CR1; + + /* Set TIM Time Base Unit parameters ---------------------------------------*/ + if (IS_TIM_COUNTER_MODE_SELECT_INSTANCE(TIMx)) + { + /* Select the Counter Mode */ + tmpcr1 &= ~(TIM_CR1_DIR | TIM_CR1_CMS); + tmpcr1 |= Structure->CounterMode; + } + + if(IS_TIM_CLOCK_DIVISION_INSTANCE(TIMx)) + { + /* Set the clock division */ + tmpcr1 &= ~TIM_CR1_CKD; + tmpcr1 |= (uint32_t)Structure->ClockDivision; + } + + /* Set the auto-reload preload */ + tmpcr1 &= ~TIM_CR1_ARPE; + tmpcr1 |= (uint32_t)Structure->AutoReloadPreload; + + TIMx->CR1 = tmpcr1; + + /* Set the Autoreload value */ + TIMx->ARR = (uint32_t)Structure->Period ; + + /* Set the Prescaler value */ + TIMx->PSC = (uint32_t)Structure->Prescaler; + + if (IS_TIM_REPETITION_COUNTER_INSTANCE(TIMx)) + { + /* Set the Repetition Counter value */ + TIMx->RCR = Structure->RepetitionCounter; + } + + /* Generate an update event to reload the Prescaler + and the repetition counter(only for TIM1 and TIM8) value immediately */ + TIMx->EGR = TIM_EGR_UG; +} + +/** + * @brief Time Ouput Compare 1 configuration + * @param TIMx to select the TIM peripheral + * @param OC_Config The ouput configuration structure + * @retval None + */ +static void TIM_OC1_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config) +{ + uint32_t tmpccmrx = 0; + uint32_t tmpccer = 0; + uint32_t tmpcr2 = 0; + + /* Disable the Channel 1: Reset the CC1E Bit */ + TIMx->CCER &= ~TIM_CCER_CC1E; + + /* Get the TIMx CCER register value */ + tmpccer = TIMx->CCER; + /* Get the TIMx CR2 register value */ + tmpcr2 = TIMx->CR2; + + /* Get the TIMx CCMR1 register value */ + tmpccmrx = TIMx->CCMR1; + + /* Reset the Output Compare Mode Bits */ + tmpccmrx &= ~TIM_CCMR1_OC1M; + tmpccmrx &= ~TIM_CCMR1_CC1S; + /* Select the Output Compare Mode */ + tmpccmrx |= OC_Config->OCMode; + + /* Reset the Output Polarity level */ + tmpccer &= ~TIM_CCER_CC1P; + /* Set the Output Compare Polarity */ + tmpccer |= OC_Config->OCPolarity; + + if(IS_TIM_CCXN_INSTANCE(TIMx, TIM_CHANNEL_1)) + { + /* Check parameters */ + assert_param(IS_TIM_OCN_POLARITY(OC_Config->OCNPolarity)); + + /* Reset the Output N Polarity level */ + tmpccer &= ~TIM_CCER_CC1NP; + /* Set the Output N Polarity */ + tmpccer |= OC_Config->OCNPolarity; + /* Reset the Output N State */ + tmpccer &= ~TIM_CCER_CC1NE; + } + + if(IS_TIM_BREAK_INSTANCE(TIMx)) + { + /* Check parameters */ + assert_param(IS_TIM_OCNIDLE_STATE(OC_Config->OCNIdleState)); + assert_param(IS_TIM_OCIDLE_STATE(OC_Config->OCIdleState)); + + /* Reset the Output Compare and Output Compare N IDLE State */ + tmpcr2 &= ~TIM_CR2_OIS1; + tmpcr2 &= ~TIM_CR2_OIS1N; + /* Set the Output Idle state */ + tmpcr2 |= OC_Config->OCIdleState; + /* Set the Output N Idle state */ + tmpcr2 |= OC_Config->OCNIdleState; + } + /* Write to TIMx CR2 */ + TIMx->CR2 = tmpcr2; + + /* Write to TIMx CCMR1 */ + TIMx->CCMR1 = tmpccmrx; + + /* Set the Capture Compare Register value */ + TIMx->CCR1 = OC_Config->Pulse; + + /* Write to TIMx CCER */ + TIMx->CCER = tmpccer; +} + +/** + * @brief Time Ouput Compare 2 configuration + * @param TIMx to select the TIM peripheral + * @param OC_Config The ouput configuration structure + * @retval None + */ +void TIM_OC2_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config) +{ + uint32_t tmpccmrx = 0; + uint32_t tmpccer = 0; + uint32_t tmpcr2 = 0; + + /* Disable the Channel 2: Reset the CC2E Bit */ + TIMx->CCER &= ~TIM_CCER_CC2E; + + /* Get the TIMx CCER register value */ + tmpccer = TIMx->CCER; + /* Get the TIMx CR2 register value */ + tmpcr2 = TIMx->CR2; + + /* Get the TIMx CCMR1 register value */ + tmpccmrx = TIMx->CCMR1; + + /* Reset the Output Compare mode and Capture/Compare selection Bits */ + tmpccmrx &= ~TIM_CCMR1_OC2M; + tmpccmrx &= ~TIM_CCMR1_CC2S; + + /* Select the Output Compare Mode */ + tmpccmrx |= (OC_Config->OCMode << 8); + + /* Reset the Output Polarity level */ + tmpccer &= ~TIM_CCER_CC2P; + /* Set the Output Compare Polarity */ + tmpccer |= (OC_Config->OCPolarity << 4); + + if(IS_TIM_CCXN_INSTANCE(TIMx, TIM_CHANNEL_2)) + { + assert_param(IS_TIM_OCN_POLARITY(OC_Config->OCNPolarity)); + + /* Reset the Output N Polarity level */ + tmpccer &= ~TIM_CCER_CC2NP; + /* Set the Output N Polarity */ + tmpccer |= (OC_Config->OCNPolarity << 4); + /* Reset the Output N State */ + tmpccer &= ~TIM_CCER_CC2NE; + + } + + if(IS_TIM_BREAK_INSTANCE(TIMx)) + { + /* Check parameters */ + assert_param(IS_TIM_OCNIDLE_STATE(OC_Config->OCNIdleState)); + assert_param(IS_TIM_OCIDLE_STATE(OC_Config->OCIdleState)); + + /* Reset the Output Compare and Output Compare N IDLE State */ + tmpcr2 &= ~TIM_CR2_OIS2; + tmpcr2 &= ~TIM_CR2_OIS2N; + /* Set the Output Idle state */ + tmpcr2 |= (OC_Config->OCIdleState << 2); + /* Set the Output N Idle state */ + tmpcr2 |= (OC_Config->OCNIdleState << 2); + } + + /* Write to TIMx CR2 */ + TIMx->CR2 = tmpcr2; + + /* Write to TIMx CCMR1 */ + TIMx->CCMR1 = tmpccmrx; + + /* Set the Capture Compare Register value */ + TIMx->CCR2 = OC_Config->Pulse; + + /* Write to TIMx CCER */ + TIMx->CCER = tmpccer; +} + +/** + * @brief Time Ouput Compare 3 configuration + * @param TIMx to select the TIM peripheral + * @param OC_Config The ouput configuration structure + * @retval None + */ +static void TIM_OC3_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config) +{ + uint32_t tmpccmrx = 0; + uint32_t tmpccer = 0; + uint32_t tmpcr2 = 0; + + /* Disable the Channel 3: Reset the CC2E Bit */ + TIMx->CCER &= ~TIM_CCER_CC3E; + + /* Get the TIMx CCER register value */ + tmpccer = TIMx->CCER; + /* Get the TIMx CR2 register value */ + tmpcr2 = TIMx->CR2; + + /* Get the TIMx CCMR2 register value */ + tmpccmrx = TIMx->CCMR2; + + /* Reset the Output Compare mode and Capture/Compare selection Bits */ + tmpccmrx &= ~TIM_CCMR2_OC3M; + tmpccmrx &= ~TIM_CCMR2_CC3S; + /* Select the Output Compare Mode */ + tmpccmrx |= OC_Config->OCMode; + + /* Reset the Output Polarity level */ + tmpccer &= ~TIM_CCER_CC3P; + /* Set the Output Compare Polarity */ + tmpccer |= (OC_Config->OCPolarity << 8); + + if(IS_TIM_CCXN_INSTANCE(TIMx, TIM_CHANNEL_3)) + { + assert_param(IS_TIM_OCN_POLARITY(OC_Config->OCNPolarity)); + + /* Reset the Output N Polarity level */ + tmpccer &= ~TIM_CCER_CC3NP; + /* Set the Output N Polarity */ + tmpccer |= (OC_Config->OCNPolarity << 8); + /* Reset the Output N State */ + tmpccer &= ~TIM_CCER_CC3NE; + } + + if(IS_TIM_BREAK_INSTANCE(TIMx)) + { + /* Check parameters */ + assert_param(IS_TIM_OCNIDLE_STATE(OC_Config->OCNIdleState)); + assert_param(IS_TIM_OCIDLE_STATE(OC_Config->OCIdleState)); + + /* Reset the Output Compare and Output Compare N IDLE State */ + tmpcr2 &= ~TIM_CR2_OIS3; + tmpcr2 &= ~TIM_CR2_OIS3N; + /* Set the Output Idle state */ + tmpcr2 |= (OC_Config->OCIdleState << 4); + /* Set the Output N Idle state */ + tmpcr2 |= (OC_Config->OCNIdleState << 4); + } + + /* Write to TIMx CR2 */ + TIMx->CR2 = tmpcr2; + + /* Write to TIMx CCMR2 */ + TIMx->CCMR2 = tmpccmrx; + + /* Set the Capture Compare Register value */ + TIMx->CCR3 = OC_Config->Pulse; + + /* Write to TIMx CCER */ + TIMx->CCER = tmpccer; +} + +/** + * @brief Time Ouput Compare 4 configuration + * @param TIMx to select the TIM peripheral + * @param OC_Config The ouput configuration structure + * @retval None + */ +static void TIM_OC4_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config) +{ + uint32_t tmpccmrx = 0; + uint32_t tmpccer = 0; + uint32_t tmpcr2 = 0; + + /* Disable the Channel 4: Reset the CC4E Bit */ + TIMx->CCER &= ~TIM_CCER_CC4E; + + /* Get the TIMx CCER register value */ + tmpccer = TIMx->CCER; + /* Get the TIMx CR2 register value */ + tmpcr2 = TIMx->CR2; + + /* Get the TIMx CCMR2 register value */ + tmpccmrx = TIMx->CCMR2; + + /* Reset the Output Compare mode and Capture/Compare selection Bits */ + tmpccmrx &= ~TIM_CCMR2_OC4M; + tmpccmrx &= ~TIM_CCMR2_CC4S; + + /* Select the Output Compare Mode */ + tmpccmrx |= (OC_Config->OCMode << 8); + + /* Reset the Output Polarity level */ + tmpccer &= ~TIM_CCER_CC4P; + /* Set the Output Compare Polarity */ + tmpccer |= (OC_Config->OCPolarity << 12); + + if(IS_TIM_BREAK_INSTANCE(TIMx)) + { + assert_param(IS_TIM_OCIDLE_STATE(OC_Config->OCIdleState)); + + /* Reset the Output Compare IDLE State */ + tmpcr2 &= ~TIM_CR2_OIS4; + /* Set the Output Idle state */ + tmpcr2 |= (OC_Config->OCIdleState << 6); + } + + /* Write to TIMx CR2 */ + TIMx->CR2 = tmpcr2; + + /* Write to TIMx CCMR2 */ + TIMx->CCMR2 = tmpccmrx; + + /* Set the Capture Compare Register value */ + TIMx->CCR4 = OC_Config->Pulse; + + /* Write to TIMx CCER */ + TIMx->CCER = tmpccer; +} + +/** + * @brief Timer Ouput Compare 5 configuration + * @param TIMx to select the TIM peripheral + * @param OC_Config The ouput configuration structure + * @retval None + */ +static void TIM_OC5_SetConfig(TIM_TypeDef *TIMx, + TIM_OC_InitTypeDef *OC_Config) +{ + uint32_t tmpccmrx = 0; + uint32_t tmpccer = 0; + uint32_t tmpcr2 = 0; + + /* Disable the output: Reset the CCxE Bit */ + TIMx->CCER &= ~TIM_CCER_CC5E; + + /* Get the TIMx CCER register value */ + tmpccer = TIMx->CCER; + /* Get the TIMx CR2 register value */ + tmpcr2 = TIMx->CR2; + /* Get the TIMx CCMR1 register value */ + tmpccmrx = TIMx->CCMR3; + + /* Reset the Output Compare Mode Bits */ + tmpccmrx &= ~(TIM_CCMR3_OC5M); + /* Select the Output Compare Mode */ + tmpccmrx |= OC_Config->OCMode; + + /* Reset the Output Polarity level */ + tmpccer &= ~TIM_CCER_CC5P; + /* Set the Output Compare Polarity */ + tmpccer |= (OC_Config->OCPolarity << 16); + + if(IS_TIM_BREAK_INSTANCE(TIMx)) + { + /* Reset the Output Compare IDLE State */ + tmpcr2 &= ~TIM_CR2_OIS5; + /* Set the Output Idle state */ + tmpcr2 |= (OC_Config->OCIdleState << 8); + } + /* Write to TIMx CR2 */ + TIMx->CR2 = tmpcr2; + + /* Write to TIMx CCMR3 */ + TIMx->CCMR3 = tmpccmrx; + + /* Set the Capture Compare Register value */ + TIMx->CCR5 = OC_Config->Pulse; + + /* Write to TIMx CCER */ + TIMx->CCER = tmpccer; +} + +/** + * @brief Timer Ouput Compare 6 configuration + * @param TIMx to select the TIM peripheral + * @param OC_Config The ouput configuration structure + * @retval None + */ +static void TIM_OC6_SetConfig(TIM_TypeDef *TIMx, + TIM_OC_InitTypeDef *OC_Config) +{ + uint32_t tmpccmrx = 0; + uint32_t tmpccer = 0; + uint32_t tmpcr2 = 0; + + /* Disable the output: Reset the CCxE Bit */ + TIMx->CCER &= ~TIM_CCER_CC6E; + + /* Get the TIMx CCER register value */ + tmpccer = TIMx->CCER; + /* Get the TIMx CR2 register value */ + tmpcr2 = TIMx->CR2; + /* Get the TIMx CCMR1 register value */ + tmpccmrx = TIMx->CCMR3; + + /* Reset the Output Compare Mode Bits */ + tmpccmrx &= ~(TIM_CCMR3_OC6M); + /* Select the Output Compare Mode */ + tmpccmrx |= (OC_Config->OCMode << 8); + + /* Reset the Output Polarity level */ + tmpccer &= (uint32_t)~TIM_CCER_CC6P; + /* Set the Output Compare Polarity */ + tmpccer |= (OC_Config->OCPolarity << 20); + + if(IS_TIM_BREAK_INSTANCE(TIMx)) + { + /* Reset the Output Compare IDLE State */ + tmpcr2 &= ~TIM_CR2_OIS6; + /* Set the Output Idle state */ + tmpcr2 |= (OC_Config->OCIdleState << 10); + } + + /* Write to TIMx CR2 */ + TIMx->CR2 = tmpcr2; + + /* Write to TIMx CCMR3 */ + TIMx->CCMR3 = tmpccmrx; + + /* Set the Capture Compare Register value */ + TIMx->CCR6 = OC_Config->Pulse; + + /* Write to TIMx CCER */ + TIMx->CCER = tmpccer; +} + +static void TIM_SlaveTimer_SetConfig(TIM_HandleTypeDef *htim, + TIM_SlaveConfigTypeDef * sSlaveConfig) +{ + uint32_t tmpsmcr = 0; + uint32_t tmpccmr1 = 0; + uint32_t tmpccer = 0; + + /* Get the TIMx SMCR register value */ + tmpsmcr = htim->Instance->SMCR; + + /* Reset the Trigger Selection Bits */ + tmpsmcr &= ~TIM_SMCR_TS; + /* Set the Input Trigger source */ + tmpsmcr |= sSlaveConfig->InputTrigger; + + /* Reset the slave mode Bits */ + tmpsmcr &= ~TIM_SMCR_SMS; + /* Set the slave mode */ + tmpsmcr |= sSlaveConfig->SlaveMode; + + /* Write to TIMx SMCR */ + htim->Instance->SMCR = tmpsmcr; + + /* Configure the trigger prescaler, filter, and polarity */ + switch (sSlaveConfig->InputTrigger) + { + case TIM_TS_ETRF: + { + /* Check the parameters */ + assert_param(IS_TIM_CLOCKSOURCE_ETRMODE1_INSTANCE(htim->Instance)); + assert_param(IS_TIM_TRIGGERPRESCALER(sSlaveConfig->TriggerPrescaler)); + assert_param(IS_TIM_TRIGGERPOLARITY(sSlaveConfig->TriggerPolarity)); + assert_param(IS_TIM_TRIGGERFILTER(sSlaveConfig->TriggerFilter)); + /* Configure the ETR Trigger source */ + TIM_ETR_SetConfig(htim->Instance, + sSlaveConfig->TriggerPrescaler, + sSlaveConfig->TriggerPolarity, + sSlaveConfig->TriggerFilter); + } + break; + + case TIM_TS_TI1F_ED: + { + /* Check the parameters */ + assert_param(IS_TIM_CC1_INSTANCE(htim->Instance)); + assert_param(IS_TIM_TRIGGERFILTER(sSlaveConfig->TriggerFilter)); + + /* Disable the Channel 1: Reset the CC1E Bit */ + tmpccer = htim->Instance->CCER; + htim->Instance->CCER &= ~TIM_CCER_CC1E; + tmpccmr1 = htim->Instance->CCMR1; + + /* Set the filter */ + tmpccmr1 &= ~TIM_CCMR1_IC1F; + tmpccmr1 |= ((sSlaveConfig->TriggerFilter) << 4); + + /* Write to TIMx CCMR1 and CCER registers */ + htim->Instance->CCMR1 = tmpccmr1; + htim->Instance->CCER = tmpccer; + + } + break; + + case TIM_TS_TI1FP1: + { + /* Check the parameters */ + assert_param(IS_TIM_CC1_INSTANCE(htim->Instance)); + assert_param(IS_TIM_TRIGGERPOLARITY(sSlaveConfig->TriggerPolarity)); + assert_param(IS_TIM_TRIGGERFILTER(sSlaveConfig->TriggerFilter)); + + /* Configure TI1 Filter and Polarity */ + TIM_TI1_ConfigInputStage(htim->Instance, + sSlaveConfig->TriggerPolarity, + sSlaveConfig->TriggerFilter); + } + break; + + case TIM_TS_TI2FP2: + { + /* Check the parameters */ + assert_param(IS_TIM_CC2_INSTANCE(htim->Instance)); + assert_param(IS_TIM_TRIGGERPOLARITY(sSlaveConfig->TriggerPolarity)); + assert_param(IS_TIM_TRIGGERFILTER(sSlaveConfig->TriggerFilter)); + + /* Configure TI2 Filter and Polarity */ + TIM_TI2_ConfigInputStage(htim->Instance, + sSlaveConfig->TriggerPolarity, + sSlaveConfig->TriggerFilter); + } + break; + + case TIM_TS_ITR0: + { + /* Check the parameter */ + assert_param(IS_TIM_CC2_INSTANCE(htim->Instance)); + } + break; + + case TIM_TS_ITR1: + { + /* Check the parameter */ + assert_param(IS_TIM_CC2_INSTANCE(htim->Instance)); + } + break; + + case TIM_TS_ITR2: + { + /* Check the parameter */ + assert_param(IS_TIM_CC2_INSTANCE(htim->Instance)); + } + break; + + case TIM_TS_ITR3: + { + /* Check the parameter */ + assert_param(IS_TIM_CC2_INSTANCE(htim->Instance)); + } + break; + + default: + break; + } +} + +/** + * @brief Configure the TI1 as Input. + * @param TIMx to select the TIM peripheral. + * @param TIM_ICPolarity The Input Polarity. + * This parameter can be one of the following values: + * @arg TIM_ICPolarity_Rising + * @arg TIM_ICPolarity_Falling + * @arg TIM_ICPolarity_BothEdge + * @param TIM_ICSelection specifies the input to be used. + * This parameter can be one of the following values: + * @arg TIM_ICSelection_DirectTI: TIM Input 1 is selected to be connected to IC1. + * @arg TIM_ICSelection_IndirectTI: TIM Input 1 is selected to be connected to IC2. + * @arg TIM_ICSelection_TRC: TIM Input 1 is selected to be connected to TRC. + * @param TIM_ICFilter Specifies the Input Capture Filter. + * This parameter must be a value between 0x00 and 0x0F. + * @retval None + * @note TIM_ICFilter and TIM_ICPolarity are not used in INDIRECT mode as TI2FP1 + * (on channel2 path) is used as the input signal. Therefore CCMR1 must be + * protected against un-initialized filter and polarity values. + */ +void TIM_TI1_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection, + uint32_t TIM_ICFilter) +{ + uint32_t tmpccmr1 = 0; + uint32_t tmpccer = 0; + + /* Disable the Channel 1: Reset the CC1E Bit */ + TIMx->CCER &= ~TIM_CCER_CC1E; + tmpccmr1 = TIMx->CCMR1; + tmpccer = TIMx->CCER; + + /* Select the Input */ + if(IS_TIM_CC2_INSTANCE(TIMx) != RESET) + { + tmpccmr1 &= ~TIM_CCMR1_CC1S; + tmpccmr1 |= TIM_ICSelection; + } + else + { + tmpccmr1 |= TIM_CCMR1_CC1S_0; + } + + /* Set the filter */ + tmpccmr1 &= ~TIM_CCMR1_IC1F; + tmpccmr1 |= ((TIM_ICFilter << 4) & TIM_CCMR1_IC1F); + + /* Select the Polarity and set the CC1E Bit */ + tmpccer &= ~(TIM_CCER_CC1P | TIM_CCER_CC1NP); + tmpccer |= (TIM_ICPolarity & (TIM_CCER_CC1P | TIM_CCER_CC1NP)); + + /* Write to TIMx CCMR1 and CCER registers */ + TIMx->CCMR1 = tmpccmr1; + TIMx->CCER = tmpccer; +} + +/** + * @brief Configure the Polarity and Filter for TI1. + * @param TIMx to select the TIM peripheral. + * @param TIM_ICPolarity The Input Polarity. + * This parameter can be one of the following values: + * @arg TIM_ICPolarity_Rising + * @arg TIM_ICPolarity_Falling + * @arg TIM_ICPolarity_BothEdge + * @param TIM_ICFilter Specifies the Input Capture Filter. + * This parameter must be a value between 0x00 and 0x0F. + * @retval None + */ +static void TIM_TI1_ConfigInputStage(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICFilter) +{ + uint32_t tmpccmr1 = 0; + uint32_t tmpccer = 0; + + /* Disable the Channel 1: Reset the CC1E Bit */ + tmpccer = TIMx->CCER; + TIMx->CCER &= ~TIM_CCER_CC1E; + tmpccmr1 = TIMx->CCMR1; + + /* Set the filter */ + tmpccmr1 &= ~TIM_CCMR1_IC1F; + tmpccmr1 |= (TIM_ICFilter << 4); + + /* Select the Polarity and set the CC1E Bit */ + tmpccer &= ~(TIM_CCER_CC1P | TIM_CCER_CC1NP); + tmpccer |= TIM_ICPolarity; + + /* Write to TIMx CCMR1 and CCER registers */ + TIMx->CCMR1 = tmpccmr1; + TIMx->CCER = tmpccer; +} + +/** + * @brief Configure the TI2 as Input. + * @param TIMx to select the TIM peripheral + * @param TIM_ICPolarity The Input Polarity. + * This parameter can be one of the following values: + * @arg TIM_ICPolarity_Rising + * @arg TIM_ICPolarity_Falling + * @arg TIM_ICPolarity_BothEdge + * @param TIM_ICSelection specifies the input to be used. + * This parameter can be one of the following values: + * @arg TIM_ICSelection_DirectTI: TIM Input 2 is selected to be connected to IC2. + * @arg TIM_ICSelection_IndirectTI: TIM Input 2 is selected to be connected to IC1. + * @arg TIM_ICSelection_TRC: TIM Input 2 is selected to be connected to TRC. + * @param TIM_ICFilter Specifies the Input Capture Filter. + * This parameter must be a value between 0x00 and 0x0F. + * @retval None + * @note TIM_ICFilter and TIM_ICPolarity are not used in INDIRECT mode as TI1FP2 + * (on channel1 path) is used as the input signal. Therefore CCMR1 must be + * protected against un-initialized filter and polarity values. + */ +static void TIM_TI2_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection, + uint32_t TIM_ICFilter) +{ + uint32_t tmpccmr1 = 0; + uint32_t tmpccer = 0; + + /* Disable the Channel 2: Reset the CC2E Bit */ + TIMx->CCER &= ~TIM_CCER_CC2E; + tmpccmr1 = TIMx->CCMR1; + tmpccer = TIMx->CCER; + + /* Select the Input */ + tmpccmr1 &= ~TIM_CCMR1_CC2S; + tmpccmr1 |= (TIM_ICSelection << 8); + + /* Set the filter */ + tmpccmr1 &= ~TIM_CCMR1_IC2F; + tmpccmr1 |= ((TIM_ICFilter << 12) & TIM_CCMR1_IC2F); + + /* Select the Polarity and set the CC2E Bit */ + tmpccer &= ~(TIM_CCER_CC2P | TIM_CCER_CC2NP); + tmpccer |= ((TIM_ICPolarity << 4) & (TIM_CCER_CC2P | TIM_CCER_CC2NP)); + + /* Write to TIMx CCMR1 and CCER registers */ + TIMx->CCMR1 = tmpccmr1 ; + TIMx->CCER = tmpccer; +} + +/** + * @brief Configure the Polarity and Filter for TI2. + * @param TIMx to select the TIM peripheral. + * @param TIM_ICPolarity The Input Polarity. + * This parameter can be one of the following values: + * @arg TIM_ICPolarity_Rising + * @arg TIM_ICPolarity_Falling + * @arg TIM_ICPolarity_BothEdge + * @param TIM_ICFilter Specifies the Input Capture Filter. + * This parameter must be a value between 0x00 and 0x0F. + * @retval None + */ +static void TIM_TI2_ConfigInputStage(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICFilter) +{ + uint32_t tmpccmr1 = 0; + uint32_t tmpccer = 0; + + /* Disable the Channel 2: Reset the CC2E Bit */ + TIMx->CCER &= ~TIM_CCER_CC2E; + tmpccmr1 = TIMx->CCMR1; + tmpccer = TIMx->CCER; + + /* Set the filter */ + tmpccmr1 &= ~TIM_CCMR1_IC2F; + tmpccmr1 |= (TIM_ICFilter << 12); + + /* Select the Polarity and set the CC2E Bit */ + tmpccer &= ~(TIM_CCER_CC2P | TIM_CCER_CC2NP); + tmpccer |= (TIM_ICPolarity << 4); + + /* Write to TIMx CCMR1 and CCER registers */ + TIMx->CCMR1 = tmpccmr1 ; + TIMx->CCER = tmpccer; +} + +/** + * @brief Configure the TI3 as Input. + * @param TIMx to select the TIM peripheral + * @param TIM_ICPolarity The Input Polarity. + * This parameter can be one of the following values: + * @arg TIM_ICPolarity_Rising + * @arg TIM_ICPolarity_Falling + * @arg TIM_ICPolarity_BothEdge + * @param TIM_ICSelection specifies the input to be used. + * This parameter can be one of the following values: + * @arg TIM_ICSelection_DirectTI: TIM Input 3 is selected to be connected to IC3. + * @arg TIM_ICSelection_IndirectTI: TIM Input 3 is selected to be connected to IC4. + * @arg TIM_ICSelection_TRC: TIM Input 3 is selected to be connected to TRC. + * @param TIM_ICFilter Specifies the Input Capture Filter. + * This parameter must be a value between 0x00 and 0x0F. + * @retval None + * @note TIM_ICFilter and TIM_ICPolarity are not used in INDIRECT mode as TI3FP4 + * (on channel1 path) is used as the input signal. Therefore CCMR2 must be + * protected against un-initialized filter and polarity values. + */ +static void TIM_TI3_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection, + uint32_t TIM_ICFilter) +{ + uint32_t tmpccmr2 = 0; + uint32_t tmpccer = 0; + + /* Disable the Channel 3: Reset the CC3E Bit */ + TIMx->CCER &= ~TIM_CCER_CC3E; + tmpccmr2 = TIMx->CCMR2; + tmpccer = TIMx->CCER; + + /* Select the Input */ + tmpccmr2 &= ~TIM_CCMR2_CC3S; + tmpccmr2 |= TIM_ICSelection; + + /* Set the filter */ + tmpccmr2 &= ~TIM_CCMR2_IC3F; + tmpccmr2 |= ((TIM_ICFilter << 4) & TIM_CCMR2_IC3F); + + /* Select the Polarity and set the CC3E Bit */ + tmpccer &= ~(TIM_CCER_CC3P | TIM_CCER_CC3NP); + tmpccer |= ((TIM_ICPolarity << 8) & (TIM_CCER_CC3P | TIM_CCER_CC3NP)); + + /* Write to TIMx CCMR2 and CCER registers */ + TIMx->CCMR2 = tmpccmr2; + TIMx->CCER = tmpccer; +} + +/** + * @brief Configure the TI4 as Input. + * @param TIMx to select the TIM peripheral + * @param TIM_ICPolarity The Input Polarity. + * This parameter can be one of the following values: + * @arg TIM_ICPolarity_Rising + * @arg TIM_ICPolarity_Falling + * @arg TIM_ICPolarity_BothEdge + * @param TIM_ICSelection specifies the input to be used. + * This parameter can be one of the following values: + * @arg TIM_ICSelection_DirectTI: TIM Input 4 is selected to be connected to IC4. + * @arg TIM_ICSelection_IndirectTI: TIM Input 4 is selected to be connected to IC3. + * @arg TIM_ICSelection_TRC: TIM Input 4 is selected to be connected to TRC. + * @param TIM_ICFilter Specifies the Input Capture Filter. + * This parameter must be a value between 0x00 and 0x0F. + * @note TIM_ICFilter and TIM_ICPolarity are not used in INDIRECT mode as TI4FP3 + * (on channel1 path) is used as the input signal. Therefore CCMR2 must be + * protected against un-initialized filter and polarity values. + * @retval None + */ +static void TIM_TI4_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection, + uint32_t TIM_ICFilter) +{ + uint32_t tmpccmr2 = 0; + uint32_t tmpccer = 0; + + /* Disable the Channel 4: Reset the CC4E Bit */ + TIMx->CCER &= ~TIM_CCER_CC4E; + tmpccmr2 = TIMx->CCMR2; + tmpccer = TIMx->CCER; + + /* Select the Input */ + tmpccmr2 &= ~TIM_CCMR2_CC4S; + tmpccmr2 |= (TIM_ICSelection << 8); + + /* Set the filter */ + tmpccmr2 &= ~TIM_CCMR2_IC4F; + tmpccmr2 |= ((TIM_ICFilter << 12) & TIM_CCMR2_IC4F); + + /* Select the Polarity and set the CC4E Bit */ + tmpccer &= ~(TIM_CCER_CC4P | TIM_CCER_CC4NP); + tmpccer |= ((TIM_ICPolarity << 12) & (TIM_CCER_CC4P | TIM_CCER_CC4NP)); + + /* Write to TIMx CCMR2 and CCER registers */ + TIMx->CCMR2 = tmpccmr2; + TIMx->CCER = tmpccer ; +} + +/** + * @brief Selects the Input Trigger source + * @param TIMx to select the TIM peripheral + * @param InputTriggerSource The Input Trigger source. + * This parameter can be one of the following values: + * @arg TIM_TS_ITR0: Internal Trigger 0 + * @arg TIM_TS_ITR1: Internal Trigger 1 + * @arg TIM_TS_ITR2: Internal Trigger 2 + * @arg TIM_TS_ITR3: Internal Trigger 3 + * @arg TIM_TS_TI1F_ED: TI1 Edge Detector + * @arg TIM_TS_TI1FP1: Filtered Timer Input 1 + * @arg TIM_TS_TI2FP2: Filtered Timer Input 2 + * @arg TIM_TS_ETRF: External Trigger input + * @retval None + */ +static void TIM_ITRx_SetConfig(TIM_TypeDef *TIMx, uint16_t InputTriggerSource) +{ + uint32_t tmpsmcr = 0; + + /* Get the TIMx SMCR register value */ + tmpsmcr = TIMx->SMCR; + /* Reset the TS Bits */ + tmpsmcr &= ~TIM_SMCR_TS; + /* Set the Input Trigger source and the slave mode*/ + tmpsmcr |= InputTriggerSource | TIM_SLAVEMODE_EXTERNAL1; + /* Write to TIMx SMCR */ + TIMx->SMCR = tmpsmcr; +} +/** + * @brief Configures the TIMx External Trigger (ETR). + * @param TIMx to select the TIM peripheral + * @param TIM_ExtTRGPrescaler The external Trigger Prescaler. + * This parameter can be one of the following values: + * @arg TIM_ETRPRESCALER_DIV1 : ETRP Prescaler OFF. + * @arg TIM_ETRPRESCALER_DIV2 : ETRP frequency divided by 2. + * @arg TIM_ETRPRESCALER_DIV4 : ETRP frequency divided by 4. + * @arg TIM_ETRPRESCALER_DIV8 : ETRP frequency divided by 8. + * @param TIM_ExtTRGPolarity The external Trigger Polarity. + * This parameter can be one of the following values: + * @arg TIM_ETRPOLARITY_INVERTED : active low or falling edge active. + * @arg TIM_ETRPOLARITY_NONINVERTED : active high or rising edge active. + * @param ExtTRGFilter External Trigger Filter. + * This parameter must be a value between 0x00 and 0x0F + * @retval None + */ +void TIM_ETR_SetConfig(TIM_TypeDef* TIMx, uint32_t TIM_ExtTRGPrescaler, + uint32_t TIM_ExtTRGPolarity, uint32_t ExtTRGFilter) +{ + uint32_t tmpsmcr = 0; + + tmpsmcr = TIMx->SMCR; + + /* Reset the ETR Bits */ + tmpsmcr &= ~(TIM_SMCR_ETF | TIM_SMCR_ETPS | TIM_SMCR_ECE | TIM_SMCR_ETP); + + /* Set the Prescaler, the Filter value and the Polarity */ + tmpsmcr |= (uint32_t)(TIM_ExtTRGPrescaler | (TIM_ExtTRGPolarity | (ExtTRGFilter << 8))); + + /* Write to TIMx SMCR */ + TIMx->SMCR = tmpsmcr; +} + +/** + * @brief Enables or disables the TIM Capture Compare Channel x. + * @param TIMx to select the TIM peripheral + * @param Channel specifies the TIM Channel + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 + * @arg TIM_CHANNEL_2: TIM Channel 2 + * @arg TIM_CHANNEL_3: TIM Channel 3 + * @arg TIM_CHANNEL_4: TIM Channel 4 + * @param ChannelState: specifies the TIM Channel CCxE bit new state. + * This parameter can be: TIM_CCx_ENABLE or TIM_CCx_Disable. + * @retval None + */ +void TIM_CCxChannelCmd(TIM_TypeDef* TIMx, uint32_t Channel, uint32_t ChannelState) +{ + uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_TIM_CC1_INSTANCE(TIMx)); + assert_param(IS_TIM_CHANNELS(Channel)); + + tmp = TIM_CCER_CC1E << Channel; + + /* Reset the CCxE Bit */ + TIMx->CCER &= ~tmp; + + /* Set or reset the CCxE Bit */ + TIMx->CCER |= (uint32_t)(ChannelState << Channel); +} + + +/** + * @} + */ + +#endif /* HAL_TIM_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_tim_ex.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_tim_ex.c new file mode 100644 index 0000000..754c1a7 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_tim_ex.c @@ -0,0 +1,2243 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_tim_ex.c + * @author MCD Application Team + * @brief TIM HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Timer Extended peripheral: + * + Time Hall Sensor Interface Initialization + * + Time Hall Sensor Interface Start + * + Time Complementary signal break and dead time configuration + * + Time Master and Slave synchronization configuration + * + Time Output Compare/PWM Channel Configuration (for channels 5 and 6) + * + Time OCRef clear configuration + * + Timer remapping capabilities configuration + @verbatim + ============================================================================== + ##### TIMER Extended features ##### + ============================================================================== + [..] + The Timer Extended features include: + (#) Complementary outputs with programmable dead-time for : + (++) Output Compare + (++) PWM generation (Edge and Center-aligned Mode) + (++) One-pulse mode output + (#) Synchronization circuit to control the timer with external signals and to + interconnect several timers together. + (#) Break input to put the timer output signals in reset state or in a known state. + (#) Supports incremental (quadrature) encoder and hall-sensor circuitry for + positioning purposes + + ##### How to use this driver ##### + ============================================================================== + [..] + (#) Initialize the TIM low level resources by implementing the following functions + depending on the selected feature: + (++) Hall Sensor output : HAL_TIMEx_HallSensor_MspInit() + + (#) Initialize the TIM low level resources : + (##) Enable the TIM interface clock using __HAL_RCC_TIMx_CLK_ENABLE(); + (##) TIM pins configuration + (+++) Enable the clock for the TIM GPIOs using the following function: + __HAL_RCC_GPIOx_CLK_ENABLE(); + (+++) Configure these TIM pins in Alternate function mode using HAL_GPIO_Init(); + + (#) The external Clock can be configured, if needed (the default clock is the + internal clock from the APBx), using the following function: + HAL_TIM_ConfigClockSource, the clock configuration should be done before + any start function. + + (#) Configure the TIM in the desired functioning mode using one of the + initialization function of this driver: + (++) HAL_TIMEx_HallSensor_Init() and HAL_TIMEx_ConfigCommutationEvent(): to use the + Timer Hall Sensor Interface and the commutation event with the corresponding + Interrupt and DMA request if needed (Note that One Timer is used to interface + with the Hall sensor Interface and another Timer should be used to use + the commutation event). + + (#) Activate the TIM peripheral using one of the start functions: + (++) Complementary Output Compare : HAL_TIMEx_OCN_Start(), HAL_TIMEx_OCN_Start_DMA(), HAL_TIMEx_OC_Start_IT() + (++) Complementary PWM generation : HAL_TIMEx_PWMN_Start(), HAL_TIMEx_PWMN_Start_DMA(), HAL_TIMEx_PWMN_Start_IT() + (++) Complementary One-pulse mode output : HAL_TIMEx_OnePulseN_Start(), HAL_TIMEx_OnePulseN_Start_IT() + (++) Hall Sensor output : HAL_TIMEx_HallSensor_Start(), HAL_TIMEx_HallSensor_Start_DMA(), HAL_TIMEx_HallSensor_Start_IT(). + + + @endverbatim + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** +*/ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup TIMEx TIMEx + * @brief TIM Extended HAL module driver + * @{ + */ + +#ifdef HAL_TIM_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +#define BDTR_BKF_SHIFT (16) +#define BDTR_BK2F_SHIFT (20) +#define TIMx_ETRSEL_MASK ((uint32_t)0x0003C000) + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +static void TIM_CCxNChannelCmd(TIM_TypeDef* TIMx, uint32_t Channel, uint32_t ChannelNState); + +/* Private functions ---------------------------------------------------------*/ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup TIMEx_Exported_Functions TIM Extended Exported Functions + * @{ + */ + +/** @defgroup TIMEx_Exported_Functions_Group1 Extended Timer Hall Sensor functions + * @brief Timer Hall Sensor functions + * +@verbatim + ============================================================================== + ##### Timer Hall Sensor functions ##### + ============================================================================== + [..] + This section provides functions allowing to: + (+) Initialize and configure TIM HAL Sensor. + (+) De-initialize TIM HAL Sensor. + (+) Start the Hall Sensor Interface. + (+) Stop the Hall Sensor Interface. + (+) Start the Hall Sensor Interface and enable interrupts. + (+) Stop the Hall Sensor Interface and disable interrupts. + (+) Start the Hall Sensor Interface and enable DMA transfers. + (+) Stop the Hall Sensor Interface and disable DMA transfers. + +@endverbatim + * @{ + */ +/** + * @brief Initializes the TIM Hall Sensor Interface and initialize the associated handle. + * @param htim TIM Encoder Interface handle + * @param sConfig TIM Hall Sensor configuration structure + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_HallSensor_Init(TIM_HandleTypeDef *htim, TIM_HallSensor_InitTypeDef* sConfig) +{ + TIM_OC_InitTypeDef OC_Config; + + /* Check the TIM handle allocation */ + if(htim == NULL) + { + return HAL_ERROR; + } + + assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance)); + assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode)); + assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision)); + assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload)); + assert_param(IS_TIM_IC_POLARITY(sConfig->IC1Polarity)); + assert_param(IS_TIM_IC_PRESCALER(sConfig->IC1Prescaler)); + assert_param(IS_TIM_IC_FILTER(sConfig->IC1Filter)); + + if(htim->State == HAL_TIM_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + htim->Lock = HAL_UNLOCKED; + + /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */ + HAL_TIMEx_HallSensor_MspInit(htim); + } + + /* Set the TIM state */ + htim->State = HAL_TIM_STATE_BUSY; + + /* Configure the Time base in the Encoder Mode */ + TIM_Base_SetConfig(htim->Instance, &htim->Init); + + /* Configure the Channel 1 as Input Channel to interface with the three Outputs of the Hall sensor */ + TIM_TI1_SetConfig(htim->Instance, sConfig->IC1Polarity, TIM_ICSELECTION_TRC, sConfig->IC1Filter); + + /* Reset the IC1PSC Bits */ + htim->Instance->CCMR1 &= ~TIM_CCMR1_IC1PSC; + /* Set the IC1PSC value */ + htim->Instance->CCMR1 |= sConfig->IC1Prescaler; + + /* Enable the Hall sensor interface (XOR function of the three inputs) */ + htim->Instance->CR2 |= TIM_CR2_TI1S; + + /* Select the TIM_TS_TI1F_ED signal as Input trigger for the TIM */ + htim->Instance->SMCR &= ~TIM_SMCR_TS; + htim->Instance->SMCR |= TIM_TS_TI1F_ED; + + /* Use the TIM_TS_TI1F_ED signal to reset the TIM counter each edge detection */ + htim->Instance->SMCR &= ~TIM_SMCR_SMS; + htim->Instance->SMCR |= TIM_SLAVEMODE_RESET; + + /* Program channel 2 in PWM 2 mode with the desired Commutation_Delay*/ + OC_Config.OCFastMode = TIM_OCFAST_DISABLE; + OC_Config.OCIdleState = TIM_OCIDLESTATE_RESET; + OC_Config.OCMode = TIM_OCMODE_PWM2; + OC_Config.OCNIdleState = TIM_OCNIDLESTATE_RESET; + OC_Config.OCNPolarity = TIM_OCNPOLARITY_HIGH; + OC_Config.OCPolarity = TIM_OCPOLARITY_HIGH; + OC_Config.Pulse = sConfig->Commutation_Delay; + + TIM_OC2_SetConfig(htim->Instance, &OC_Config); + + /* Select OC2REF as trigger output on TRGO: write the MMS bits in the TIMx_CR2 + register to 101 */ + htim->Instance->CR2 &= ~TIM_CR2_MMS; + htim->Instance->CR2 |= TIM_TRGO_OC2REF; + + /* Initialize the TIM state*/ + htim->State= HAL_TIM_STATE_READY; + + return HAL_OK; +} + +/** + * @brief DeInitialize the TIM Hall Sensor interface + * @param htim TIM Hall Sensor handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_HallSensor_DeInit(TIM_HandleTypeDef *htim) +{ + /* Check the parameters */ + assert_param(IS_TIM_INSTANCE(htim->Instance)); + + htim->State = HAL_TIM_STATE_BUSY; + + /* Disable the TIM Peripheral Clock */ + __HAL_TIM_DISABLE(htim); + + /* DeInit the low level hardware: GPIO, CLOCK, NVIC */ + HAL_TIMEx_HallSensor_MspDeInit(htim); + + /* Change TIM state */ + htim->State = HAL_TIM_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @brief Initializes the TIM Hall Sensor MSP. + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIMEx_HallSensor_MspInit(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_TIMEx_HallSensor_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitialize TIM Hall Sensor MSP. + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIMEx_HallSensor_MspDeInit(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_TIMEx_HallSensor_MspDeInit could be implemented in the user file + */ +} + +/** + * @brief Starts the TIM Hall Sensor Interface. + * @param htim TIM Hall Sensor handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_HallSensor_Start(TIM_HandleTypeDef *htim) +{ + /* Check the parameters */ + assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance)); + + /* Enable the Input Capture channel 1 + (in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1, TIM_CHANNEL_2 and TIM_CHANNEL_3) */ + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE); + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM Hall sensor Interface. + * @param htim TIM Hall Sensor handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_HallSensor_Stop(TIM_HandleTypeDef *htim) +{ + /* Check the parameters */ + assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance)); + + /* Disable the Input Capture channels 1, 2 and 3 + (in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1, TIM_CHANNEL_2 and TIM_CHANNEL_3) */ + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE); + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Starts the TIM Hall Sensor Interface in interrupt mode. + * @param htim TIM Hall Sensor handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_HallSensor_Start_IT(TIM_HandleTypeDef *htim) +{ + /* Check the parameters */ + assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance)); + + /* Enable the capture compare Interrupts 1 event */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1); + + /* Enable the Input Capture channel 1 + (in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1, TIM_CHANNEL_2 and TIM_CHANNEL_3) */ + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE); + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM Hall Sensor Interface in interrupt mode. + * @param htim TIM handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_HallSensor_Stop_IT(TIM_HandleTypeDef *htim) +{ + /* Check the parameters */ + assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance)); + + /* Disable the Input Capture channel 1 + (in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1, TIM_CHANNEL_2 and TIM_CHANNEL_3) */ + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE); + + /* Disable the capture compare Interrupts event */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1); + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Starts the TIM Hall Sensor Interface in DMA mode. + * @param htim TIM Hall Sensor handle + * @param pData The destination Buffer address. + * @param Length The length of data to be transferred from TIM peripheral to memory. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_HallSensor_Start_DMA(TIM_HandleTypeDef *htim, uint32_t *pData, uint16_t Length) +{ + /* Check the parameters */ + assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance)); + + if((htim->State == HAL_TIM_STATE_BUSY)) + { + return HAL_BUSY; + } + else if((htim->State == HAL_TIM_STATE_READY)) + { + if(((uint32_t)pData == 0 ) && (Length > 0)) + { + return HAL_ERROR; + } + else + { + htim->State = HAL_TIM_STATE_BUSY; + } + } + /* Enable the Input Capture channel 1 + (in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1, TIM_CHANNEL_2 and TIM_CHANNEL_3) */ + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE); + + /* Set the DMA Input Capture 1 Callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMACaptureCplt; + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel for Capture 1*/ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)&htim->Instance->CCR1, (uint32_t)pData, Length); + + /* Enable the capture compare 1 Interrupt */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1); + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM Hall Sensor Interface in DMA mode. + * @param htim TIM handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_HallSensor_Stop_DMA(TIM_HandleTypeDef *htim) +{ + /* Check the parameters */ + assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance)); + + /* Disable the Input Capture channel 1 + (in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1, TIM_CHANNEL_2 and TIM_CHANNEL_3) */ + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE); + + + /* Disable the capture compare Interrupts 1 event */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1); + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup TIMEx_Exported_Functions_Group2 Extended Timer Complementary Output Compare functions + * @brief Timer Complementary Output Compare functions + * +@verbatim + ============================================================================== + ##### Timer Complementary Output Compare functions ##### + ============================================================================== + [..] + This section provides functions allowing to: + (+) Start the Complementary Output Compare/PWM. + (+) Stop the Complementary Output Compare/PWM. + (+) Start the Complementary Output Compare/PWM and enable interrupts. + (+) Stop the Complementary Output Compare/PWM and disable interrupts. + (+) Start the Complementary Output Compare/PWM and enable DMA transfers. + (+) Stop the Complementary Output Compare/PWM and disable DMA transfers. + +@endverbatim + * @{ + */ + +/** + * @brief Starts the TIM Output Compare signal generation on the complementary + * output. + * @param htim TIM Output Compare handle + * @param Channel TIM Channel to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_OCN_Start(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel)); + + /* Enable the Capture compare channel N */ + TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE); + + /* Enable the Main Ouput */ + __HAL_TIM_MOE_ENABLE(htim); + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM Output Compare signal generation on the complementary + * output. + * @param htim TIM handle + * @param Channel TIM Channel to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_OCN_Stop(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel)); + + /* Disable the Capture compare channel N */ + TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE); + + /* Disable the Main Ouput */ + __HAL_TIM_MOE_DISABLE(htim); + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Starts the TIM Output Compare signal generation in interrupt mode + * on the complementary output. + * @param htim TIM OC handle + * @param Channel TIM Channel to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_OCN_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel)); + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Enable the TIM Output Compare interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Enable the TIM Output Compare interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2); + } + break; + + case TIM_CHANNEL_3: + { + /* Enable the TIM Output Compare interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Enable the TIM Output Compare interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC4); + } + break; + + default: + break; + } + + /* Enable the TIM Break interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_BREAK); + + /* Enable the Capture compare channel N */ + TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE); + + /* Enable the Main Ouput */ + __HAL_TIM_MOE_ENABLE(htim); + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM Output Compare signal generation in interrupt mode + * on the complementary output. + * @param htim TIM Output Compare handle + * @param Channel TIM Channel to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_OCN_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + uint32_t tmpccer = 0; + + /* Check the parameters */ + assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel)); + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Disable the TIM Output Compare interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Disable the TIM Output Compare interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2); + } + break; + + case TIM_CHANNEL_3: + { + /* Disable the TIM Output Compare interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Disable the TIM Output Compare interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC4); + } + break; + + default: + break; + } + + /* Disable the Capture compare channel N */ + TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE); + + /* Disable the TIM Break interrupt (only if no more channel is active) */ + tmpccer = htim->Instance->CCER; + if ((tmpccer & (TIM_CCER_CC1NE | TIM_CCER_CC2NE | TIM_CCER_CC3NE)) == RESET) + { + __HAL_TIM_DISABLE_IT(htim, TIM_IT_BREAK); + } + + /* Disable the Main Ouput */ + __HAL_TIM_MOE_DISABLE(htim); + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Starts the TIM Output Compare signal generation in DMA mode + * on the complementary output. + * @param htim TIM Output Compare handle + * @param Channel TIM Channel to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @param pData The source Buffer address. + * @param Length The length of data to be transferred from memory to TIM peripheral + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_OCN_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel)); + + if((htim->State == HAL_TIM_STATE_BUSY)) + { + return HAL_BUSY; + } + else if((htim->State == HAL_TIM_STATE_READY)) + { + if(((uint32_t)pData == 0 ) && (Length > 0)) + { + return HAL_ERROR; + } + else + { + htim->State = HAL_TIM_STATE_BUSY; + } + } + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)pData, (uint32_t)&htim->Instance->CCR1, Length); + + /* Enable the TIM Output Compare DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)pData, (uint32_t)&htim->Instance->CCR2, Length); + + /* Enable the TIM Output Compare DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2); + } + break; + + case TIM_CHANNEL_3: +{ + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)pData, (uint32_t)&htim->Instance->CCR3,Length); + + /* Enable the TIM Output Compare DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC4]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC4], (uint32_t)pData, (uint32_t)&htim->Instance->CCR4, Length); + + /* Enable the TIM Output Compare DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC4); + } + break; + + default: + break; + } + + /* Enable the Capture compare channel N */ + TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE); + + /* Enable the Main Ouput */ + __HAL_TIM_MOE_ENABLE(htim); + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM Output Compare signal generation in DMA mode + * on the complementary output. + * @param htim TIM Output Compare handle + * @param Channel TIM Channel to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_OCN_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel)); + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Disable the TIM Output Compare DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Disable the TIM Output Compare DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2); + } + break; + + case TIM_CHANNEL_3: + { + /* Disable the TIM Output Compare DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Disable the TIM Output Compare interrupt */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC4); + } + break; + + default: + break; + } + + /* Disable the Capture compare channel N */ + TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE); + + /* Disable the Main Ouput */ + __HAL_TIM_MOE_DISABLE(htim); + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Change the htim state */ + htim->State = HAL_TIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup TIMEx_Exported_Functions_Group3 Extended Timer Complementary PWM functions + * @brief Timer Complementary PWM functions + * +@verbatim + ============================================================================== + ##### Timer Complementary PWM functions ##### + ============================================================================== + [..] + This section provides functions allowing to: + (+) Start the Complementary PWM. + (+) Stop the Complementary PWM. + (+) Start the Complementary PWM and enable interrupts. + (+) Stop the Complementary PWM and disable interrupts. + (+) Start the Complementary PWM and enable DMA transfers. + (+) Stop the Complementary PWM and disable DMA transfers. + (+) Start the Complementary Input Capture measurement. + (+) Stop the Complementary Input Capture. + (+) Start the Complementary Input Capture and enable interrupts. + (+) Stop the Complementary Input Capture and disable interrupts. + (+) Start the Complementary Input Capture and enable DMA transfers. + (+) Stop the Complementary Input Capture and disable DMA transfers. + (+) Start the Complementary One Pulse generation. + (+) Stop the Complementary One Pulse. + (+) Start the Complementary One Pulse and enable interrupts. + (+) Stop the Complementary One Pulse and disable interrupts. + +@endverbatim + * @{ + */ + +/** + * @brief Starts the PWM signal generation on the complementary output. + * @param htim TIM handle + * @param Channel TIM Channel to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_PWMN_Start(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel)); + + /* Enable the complementary PWM output */ + TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE); + + /* Enable the Main Ouput */ + __HAL_TIM_MOE_ENABLE(htim); + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the PWM signal generation on the complementary output. + * @param htim TIM handle + * @param Channel TIM Channel to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel)); + + /* Disable the complementary PWM output */ + TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE); + + /* Disable the Main Ouput */ + __HAL_TIM_MOE_DISABLE(htim); + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Starts the PWM signal generation in interrupt mode on the + * complementary output. + * @param htim TIM handle + * @param Channel TIM Channel to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_PWMN_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel)); + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Enable the TIM Capture/Compare 1 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Enable the TIM Capture/Compare 2 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2); + } + break; + + case TIM_CHANNEL_3: + { + /* Enable the TIM Capture/Compare 3 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Enable the TIM Capture/Compare 4 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC4); + } + break; + + default: + break; + } + + /* Enable the TIM Break interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_BREAK); + + /* Enable the complementary PWM output */ + TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE); + + /* Enable the Main Ouput */ + __HAL_TIM_MOE_ENABLE(htim); + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the PWM signal generation in interrupt mode on the + * complementary output. + * @param htim TIM handle + * @param Channel TIM Channel to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop_IT (TIM_HandleTypeDef *htim, uint32_t Channel) +{ + uint32_t tmpccer = 0; + + /* Check the parameters */ + assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel)); + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Disable the TIM Capture/Compare 1 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Disable the TIM Capture/Compare 2 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2); + } + break; + + case TIM_CHANNEL_3: + { + /* Disable the TIM Capture/Compare 3 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Disable the TIM Capture/Compare 3 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC4); + } + break; + + default: + break; + } + + /* Disable the complementary PWM output */ + TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE); + + + /* Disable the TIM Break interrupt (only if no more channel is active) */ + tmpccer = htim->Instance->CCER; + if ((tmpccer & (TIM_CCER_CC1NE | TIM_CCER_CC2NE | TIM_CCER_CC3NE)) == RESET) + { + __HAL_TIM_DISABLE_IT(htim, TIM_IT_BREAK); + } + + /* Disable the Main Ouput */ + __HAL_TIM_MOE_DISABLE(htim); + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Starts the TIM PWM signal generation in DMA mode on the + * complementary output + * @param htim TIM handle + * @param Channel TIM Channel to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @param pData The source Buffer address. + * @param Length The length of data to be transferred from memory to TIM peripheral + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_PWMN_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel)); + + if((htim->State == HAL_TIM_STATE_BUSY)) + { + return HAL_BUSY; + } + else if((htim->State == HAL_TIM_STATE_READY)) + { + if(((uint32_t)pData == 0 ) && (Length > 0)) + { + return HAL_ERROR; + } + else + { + htim->State = HAL_TIM_STATE_BUSY; + } + } + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)pData, (uint32_t)&htim->Instance->CCR1, Length); + + /* Enable the TIM Capture/Compare 1 DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)pData, (uint32_t)&htim->Instance->CCR2, Length); + + /* Enable the TIM Capture/Compare 2 DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2); + } + break; + + case TIM_CHANNEL_3: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)pData, (uint32_t)&htim->Instance->CCR3,Length); + + /* Enable the TIM Capture/Compare 3 DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC4]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC4], (uint32_t)pData, (uint32_t)&htim->Instance->CCR4, Length); + + /* Enable the TIM Capture/Compare 4 DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC4); + } + break; + + default: + break; + } + + /* Enable the complementary PWM output */ + TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE); + + /* Enable the Main Ouput */ + __HAL_TIM_MOE_ENABLE(htim); + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM PWM signal generation in DMA mode on the complementary + * output + * @param htim TIM handle + * @param Channel TIM Channel to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel)); + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Disable the TIM Capture/Compare 1 DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Disable the TIM Capture/Compare 2 DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2); + } + break; + + case TIM_CHANNEL_3: + { + /* Disable the TIM Capture/Compare 3 DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Disable the TIM Capture/Compare 4 DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC4); + } + break; + + default: + break; + } + + /* Disable the complementary PWM output */ + TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE); + + /* Disable the Main Ouput */ + __HAL_TIM_MOE_DISABLE(htim); + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Change the htim state */ + htim->State = HAL_TIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup TIMEx_Exported_Functions_Group4 Extended Timer Complementary One Pulse functions + * @brief Timer Complementary One Pulse functions + * +@verbatim + ============================================================================== + ##### Timer Complementary One Pulse functions ##### + ============================================================================== + [..] + This section provides functions allowing to: + (+) Start the Complementary One Pulse generation. + (+) Stop the Complementary One Pulse. + (+) Start the Complementary One Pulse and enable interrupts. + (+) Stop the Complementary One Pulse and disable interrupts. + +@endverbatim + * @{ + */ + +/** + * @brief Starts the TIM One Pulse signal generation on the complementary + * output. + * @param htim TIM One Pulse handle + * @param OutputChannel TIM Channel to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Start(TIM_HandleTypeDef *htim, uint32_t OutputChannel) + { + /* Check the parameters */ + assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, OutputChannel)); + + /* Enable the complementary One Pulse output */ + TIM_CCxNChannelCmd(htim->Instance, OutputChannel, TIM_CCxN_ENABLE); + + /* Enable the Main Ouput */ + __HAL_TIM_MOE_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM One Pulse signal generation on the complementary + * output. + * @param htim TIM One Pulse handle + * @param OutputChannel TIM Channel to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Stop(TIM_HandleTypeDef *htim, uint32_t OutputChannel) +{ + + /* Check the parameters */ + assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, OutputChannel)); + + /* Disable the complementary One Pulse output */ + TIM_CCxNChannelCmd(htim->Instance, OutputChannel, TIM_CCxN_DISABLE); + + /* Disable the Main Ouput */ + __HAL_TIM_MOE_DISABLE(htim); + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Starts the TIM One Pulse signal generation in interrupt mode on the + * complementary channel. + * @param htim TIM One Pulse handle + * @param OutputChannel TIM Channel to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Start_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, OutputChannel)); + + /* Enable the TIM Capture/Compare 1 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1); + + /* Enable the TIM Capture/Compare 2 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2); + + /* Enable the complementary One Pulse output */ + TIM_CCxNChannelCmd(htim->Instance, OutputChannel, TIM_CCxN_ENABLE); + + /* Enable the Main Ouput */ + __HAL_TIM_MOE_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM One Pulse signal generation in interrupt mode on the + * complementary channel. + * @param htim TIM One Pulse handle + * @param OutputChannel TIM Channel to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Stop_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, OutputChannel)); + + /* Disable the TIM Capture/Compare 1 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1); + + /* Disable the TIM Capture/Compare 2 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2); + + /* Disable the complementary One Pulse output */ + TIM_CCxNChannelCmd(htim->Instance, OutputChannel, TIM_CCxN_DISABLE); + + /* Disable the Main Ouput */ + __HAL_TIM_MOE_DISABLE(htim); + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup TIMEx_Exported_Functions_Group5 Extended Peripheral Control functions + * @brief Peripheral Control functions + * +@verbatim + ============================================================================== + ##### Peripheral Control functions ##### + ============================================================================== + [..] + This section provides functions allowing to: + (+) Configure the commutation event in case of use of the Hall sensor interface. + (+) Configure Output channels for OC and PWM mode. + + (+) Configure Complementary channels, break features and dead time. + (+) Configure Master synchronization. + (+) Configure timer remapping capabilities. + (+) Enable or disable channel grouping + +@endverbatim + * @{ + */ + +/** + * @brief Configure the TIM commutation event sequence. + * @note This function is mandatory to use the commutation event in order to + * update the configuration at each commutation detection on the TRGI input of the Timer, + * the typical use of this feature is with the use of another Timer(interface Timer) + * configured in Hall sensor interface, this interface Timer will generate the + * commutation at its TRGO output (connected to Timer used in this function) each time + * the TI1 of the Interface Timer detect a commutation at its input TI1. + * @param htim TIM handle + * @param InputTrigger the Internal trigger corresponding to the Timer Interfacing with the Hall sensor + * This parameter can be one of the following values: + * @arg TIM_TS_ITR0: Internal trigger 0 selected + * @arg TIM_TS_ITR1: Internal trigger 1 selected + * @arg TIM_TS_ITR2: Internal trigger 2 selected + * @arg TIM_TS_ITR3: Internal trigger 3 selected + * @arg TIM_TS_NONE: No trigger is needed + * @param CommutationSource the Commutation Event source + * This parameter can be one of the following values: + * @arg TIM_COMMUTATION_TRGI: Commutation source is the TRGI of the Interface Timer + * @arg TIM_COMMUTATION_SOFTWARE: Commutation source is set by software using the COMG bit + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_ConfigCommutationEvent(TIM_HandleTypeDef *htim, uint32_t InputTrigger, uint32_t CommutationSource) +{ + /* Check the parameters */ + assert_param(IS_TIM_COMMUTATION_EVENT_INSTANCE(htim->Instance)); + assert_param(IS_TIM_INTERNAL_TRIGGEREVENT_SELECTION(InputTrigger)); + + __HAL_LOCK(htim); + + if ((InputTrigger == TIM_TS_ITR0) || (InputTrigger == TIM_TS_ITR1) || + (InputTrigger == TIM_TS_ITR2) || (InputTrigger == TIM_TS_ITR3)) + { + /* Select the Input trigger */ + htim->Instance->SMCR &= ~TIM_SMCR_TS; + htim->Instance->SMCR |= InputTrigger; + } + + /* Select the Capture Compare preload feature */ + htim->Instance->CR2 |= TIM_CR2_CCPC; + /* Select the Commutation event source */ + htim->Instance->CR2 &= ~TIM_CR2_CCUS; + htim->Instance->CR2 |= CommutationSource; + + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @brief Configure the TIM commutation event sequence with interrupt. + * @note This function is mandatory to use the commutation event in order to + * update the configuration at each commutation detection on the TRGI input of the Timer, + * the typical use of this feature is with the use of another Timer(interface Timer) + * configured in Hall sensor interface, this interface Timer will generate the + * commutation at its TRGO output (connected to Timer used in this function) each time + * the TI1 of the Interface Timer detect a commutation at its input TI1. + * @param htim TIM handle + * @param InputTrigger the Internal trigger corresponding to the Timer Interfacing with the Hall sensor + * This parameter can be one of the following values: + * @arg TIM_TS_ITR0: Internal trigger 0 selected + * @arg TIM_TS_ITR1: Internal trigger 1 selected + * @arg TIM_TS_ITR2: Internal trigger 2 selected + * @arg TIM_TS_ITR3: Internal trigger 3 selected + * @arg TIM_TS_NONE: No trigger is needed + * @param CommutationSource the Commutation Event source + * This parameter can be one of the following values: + * @arg TIM_COMMUTATION_TRGI: Commutation source is the TRGI of the Interface Timer + * @arg TIM_COMMUTATION_SOFTWARE: Commutation source is set by software using the COMG bit + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_ConfigCommutationEvent_IT(TIM_HandleTypeDef *htim, uint32_t InputTrigger, uint32_t CommutationSource) +{ + /* Check the parameters */ + assert_param(IS_TIM_COMMUTATION_EVENT_INSTANCE(htim->Instance)); + assert_param(IS_TIM_INTERNAL_TRIGGEREVENT_SELECTION(InputTrigger)); + + __HAL_LOCK(htim); + + if ((InputTrigger == TIM_TS_ITR0) || (InputTrigger == TIM_TS_ITR1) || + (InputTrigger == TIM_TS_ITR2) || (InputTrigger == TIM_TS_ITR3)) + { + /* Select the Input trigger */ + htim->Instance->SMCR &= ~TIM_SMCR_TS; + htim->Instance->SMCR |= InputTrigger; + } + + /* Select the Capture Compare preload feature */ + htim->Instance->CR2 |= TIM_CR2_CCPC; + /* Select the Commutation event source */ + htim->Instance->CR2 &= ~TIM_CR2_CCUS; + htim->Instance->CR2 |= CommutationSource; + + /* Enable the Commutation Interrupt Request */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_COM); + + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @brief Configure the TIM commutation event sequence with DMA. + * @note This function is mandatory to use the commutation event in order to + * update the configuration at each commutation detection on the TRGI input of the Timer, + * the typical use of this feature is with the use of another Timer(interface Timer) + * configured in Hall sensor interface, this interface Timer will generate the + * commutation at its TRGO output (connected to Timer used in this function) each time + * the TI1 of the Interface Timer detect a commutation at its input TI1. + * @note The user should configure the DMA in his own software, in This function only the COMDE bit is set + * @param htim TIM handle + * @param InputTrigger the Internal trigger corresponding to the Timer Interfacing with the Hall sensor + * This parameter can be one of the following values: + * @arg TIM_TS_ITR0: Internal trigger 0 selected + * @arg TIM_TS_ITR1: Internal trigger 1 selected + * @arg TIM_TS_ITR2: Internal trigger 2 selected + * @arg TIM_TS_ITR3: Internal trigger 3 selected + * @arg TIM_TS_NONE: No trigger is needed + * @param CommutationSource the Commutation Event source + * This parameter can be one of the following values: + * @arg TIM_COMMUTATION_TRGI: Commutation source is the TRGI of the Interface Timer + * @arg TIM_COMMUTATION_SOFTWARE: Commutation source is set by software using the COMG bit + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_ConfigCommutationEvent_DMA(TIM_HandleTypeDef *htim, uint32_t InputTrigger, uint32_t CommutationSource) +{ + /* Check the parameters */ + assert_param(IS_TIM_COMMUTATION_EVENT_INSTANCE(htim->Instance)); + assert_param(IS_TIM_INTERNAL_TRIGGEREVENT_SELECTION(InputTrigger)); + + __HAL_LOCK(htim); + + if ((InputTrigger == TIM_TS_ITR0) || (InputTrigger == TIM_TS_ITR1) || + (InputTrigger == TIM_TS_ITR2) || (InputTrigger == TIM_TS_ITR3)) + { + /* Select the Input trigger */ + htim->Instance->SMCR &= ~TIM_SMCR_TS; + htim->Instance->SMCR |= InputTrigger; + } + + /* Select the Capture Compare preload feature */ + htim->Instance->CR2 |= TIM_CR2_CCPC; + /* Select the Commutation event source */ + htim->Instance->CR2 &= ~TIM_CR2_CCUS; + htim->Instance->CR2 |= CommutationSource; + + /* Enable the Commutation DMA Request */ + /* Set the DMA Commutation Callback */ + htim->hdma[TIM_DMA_ID_COMMUTATION]->XferCpltCallback = TIMEx_DMACommutationCplt; + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_COMMUTATION]->XferErrorCallback = TIM_DMAError; + + /* Enable the Commutation DMA Request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_COM); + + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @brief Configures the TIM in master mode. + * @param htim TIM handle. + * @param sMasterConfig pointer to a TIM_MasterConfigTypeDef structure that + * contains the selected trigger output (TRGO) and the Master/Slave + * mode. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_MasterConfigSynchronization(TIM_HandleTypeDef *htim, + TIM_MasterConfigTypeDef * sMasterConfig) +{ + uint32_t tmpcr2; + uint32_t tmpsmcr; + + /* Check the parameters */ + assert_param(IS_TIM_SYNCHRO_INSTANCE(htim->Instance)); + assert_param(IS_TIM_TRGO_SOURCE(sMasterConfig->MasterOutputTrigger)); + assert_param(IS_TIM_MSM_STATE(sMasterConfig->MasterSlaveMode)); + + /* Check input state */ + __HAL_LOCK(htim); + + /* Get the TIMx CR2 register value */ + tmpcr2 = htim->Instance->CR2; + + /* Get the TIMx SMCR register value */ + tmpsmcr = htim->Instance->SMCR; + + /* If the timer supports ADC synchronization through TRGO2, set the master mode selection 2 */ + if (IS_TIM_TRGO2_INSTANCE(htim->Instance)) + { + /* Check the parameters */ + assert_param(IS_TIM_TRGO2_SOURCE(sMasterConfig->MasterOutputTrigger2)); + + /* Clear the MMS2 bits */ + tmpcr2 &= ~TIM_CR2_MMS2; + /* Select the TRGO2 source*/ + tmpcr2 |= sMasterConfig->MasterOutputTrigger2; + } + + /* Reset the MMS Bits */ + tmpcr2 &= ~TIM_CR2_MMS; + /* Select the TRGO source */ + tmpcr2 |= sMasterConfig->MasterOutputTrigger; + + /* Reset the MSM Bit */ + tmpsmcr &= ~TIM_SMCR_MSM; + /* Set master mode */ + tmpsmcr |= sMasterConfig->MasterSlaveMode; + + /* Update TIMx CR2 */ + htim->Instance->CR2 = tmpcr2; + + /* Update TIMx SMCR */ + htim->Instance->SMCR = tmpsmcr; + + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @brief Configures the Break feature, dead time, Lock level, OSSI/OSSR State + * and the AOE(automatic output enable). + * @param htim TIM handle + * @param sBreakDeadTimeConfig pointer to a TIM_ConfigBreakDeadConfigTypeDef structure that + * contains the BDTR Register configuration information for the TIM peripheral. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_ConfigBreakDeadTime(TIM_HandleTypeDef *htim, + TIM_BreakDeadTimeConfigTypeDef * sBreakDeadTimeConfig) +{ + uint32_t tmpbdtr = 0; + + /* Check the parameters */ + assert_param(IS_TIM_BREAK_INSTANCE(htim->Instance)); + assert_param(IS_TIM_OSSR_STATE(sBreakDeadTimeConfig->OffStateRunMode)); + assert_param(IS_TIM_OSSI_STATE(sBreakDeadTimeConfig->OffStateIDLEMode)); + assert_param(IS_TIM_LOCK_LEVEL(sBreakDeadTimeConfig->LockLevel)); + assert_param(IS_TIM_DEADTIME(sBreakDeadTimeConfig->DeadTime)); + assert_param(IS_TIM_BREAK_STATE(sBreakDeadTimeConfig->BreakState)); + assert_param(IS_TIM_BREAK_POLARITY(sBreakDeadTimeConfig->BreakPolarity)); + assert_param(IS_TIM_BREAK_FILTER(sBreakDeadTimeConfig->BreakFilter)); + assert_param(IS_TIM_AUTOMATIC_OUTPUT_STATE(sBreakDeadTimeConfig->AutomaticOutput)); + + /* Check input state */ + __HAL_LOCK(htim); + + /* Set the Lock level, the Break enable Bit and the Polarity, the OSSR State, + the OSSI State, the dead time value and the Automatic Output Enable Bit */ + + /* Set the BDTR bits */ + MODIFY_REG(tmpbdtr, TIM_BDTR_DTG, sBreakDeadTimeConfig->DeadTime); + MODIFY_REG(tmpbdtr, TIM_BDTR_LOCK, sBreakDeadTimeConfig->LockLevel); + MODIFY_REG(tmpbdtr, TIM_BDTR_OSSI, sBreakDeadTimeConfig->OffStateIDLEMode); + MODIFY_REG(tmpbdtr, TIM_BDTR_OSSR, sBreakDeadTimeConfig->OffStateRunMode); + MODIFY_REG(tmpbdtr, TIM_BDTR_BKE, sBreakDeadTimeConfig->BreakState); + MODIFY_REG(tmpbdtr, TIM_BDTR_BKP, sBreakDeadTimeConfig->BreakPolarity); + MODIFY_REG(tmpbdtr, TIM_BDTR_AOE, sBreakDeadTimeConfig->AutomaticOutput); + MODIFY_REG(tmpbdtr, TIM_BDTR_MOE, sBreakDeadTimeConfig->AutomaticOutput); + MODIFY_REG(tmpbdtr, TIM_BDTR_BKF, (sBreakDeadTimeConfig->BreakFilter << BDTR_BKF_SHIFT)); + + if (IS_TIM_BKIN2_INSTANCE(htim->Instance)) + { + /* Check the parameters */ + assert_param(IS_TIM_BREAK2_STATE(sBreakDeadTimeConfig->Break2State)); + assert_param(IS_TIM_BREAK2_POLARITY(sBreakDeadTimeConfig->Break2Polarity)); + assert_param(IS_TIM_BREAK_FILTER(sBreakDeadTimeConfig->Break2Filter)); + + /* Set the BREAK2 input related BDTR bits */ + MODIFY_REG(tmpbdtr, TIM_BDTR_BK2F, (sBreakDeadTimeConfig->Break2Filter << BDTR_BK2F_SHIFT)); + MODIFY_REG(tmpbdtr, TIM_BDTR_BK2E, sBreakDeadTimeConfig->Break2State); + MODIFY_REG(tmpbdtr, TIM_BDTR_BK2P, sBreakDeadTimeConfig->Break2Polarity); + } + + /* Set TIMx_BDTR */ + htim->Instance->BDTR = tmpbdtr; + + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @brief Configures the break input source. + * @param htim TIM handle. + * @param BreakInput Break input to configure + * This parameter can be one of the following values: + * @arg TIM_BREAKINPUT_BRK: Timer break input + * @arg TIM_BREAKINPUT_BRK2: Timer break 2 input + * @param sBreakInputConfig Break input source configuration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_ConfigBreakInput(TIM_HandleTypeDef *htim, + uint32_t BreakInput, + TIMEx_BreakInputConfigTypeDef *sBreakInputConfig) + +{ + uint32_t tmporx = 0; + uint32_t bkin_enable_mask = 0; + uint32_t bkin_polarity_mask = 0; + uint32_t bkin_enable_bitpos = 0; + uint32_t bkin_polarity_bitpos = 0; + + /* Check the parameters */ + assert_param(IS_TIM_BREAK_INSTANCE(htim->Instance)); + assert_param(IS_TIM_BREAKINPUT(BreakInput)); + assert_param(IS_TIM_BREAKINPUTSOURCE(sBreakInputConfig->Source)); + assert_param(IS_TIM_BREAKINPUTSOURCE_STATE(sBreakInputConfig->Enable)); + +#if defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || \ + defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + if (sBreakInputConfig->Source != TIM_BREAKINPUTSOURCE_DFSDM1) + { + assert_param(IS_TIM_BREAKINPUTSOURCE_POLARITY(sBreakInputConfig->Polarity)); + } +#else + assert_param(IS_TIM_BREAKINPUTSOURCE_POLARITY(sBreakInputConfig->Polarity)); +#endif /* STM32L451xx || STM32L452xx || STM32L462xx || */ + /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx || */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + + /* Check input state */ + __HAL_LOCK(htim); + + switch(sBreakInputConfig->Source) + { + case TIM_BREAKINPUTSOURCE_BKIN: + { + bkin_enable_mask = TIM1_OR2_BKINE; + bkin_enable_bitpos = 0; + bkin_polarity_mask = TIM1_OR2_BKINP; + bkin_polarity_bitpos = 9; + } + break; + case TIM_BREAKINPUTSOURCE_COMP1: + { + bkin_enable_mask = TIM1_OR2_BKCMP1E; + bkin_enable_bitpos = 1; + bkin_polarity_mask = TIM1_OR2_BKCMP1P; + bkin_polarity_bitpos = 10; + } + break; + case TIM_BREAKINPUTSOURCE_COMP2: + { + bkin_enable_mask = TIM1_OR2_BKCMP2E; + bkin_enable_bitpos = 2; + bkin_polarity_mask = TIM1_OR2_BKCMP2P; + bkin_polarity_bitpos = 11; + } + break; + +#if defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || \ + defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + case TIM_BREAKINPUTSOURCE_DFSDM1: + { + bkin_enable_mask = TIM1_OR2_BKDF1BK0E; + bkin_enable_bitpos = 8; + } + break; +#endif /* STM32L451xx || STM32L452xx || STM32L462xx || */ + /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx || */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + + default: + break; + } + + switch(BreakInput) + { + case TIM_BREAKINPUT_BRK: + { + /* Get the TIMx_OR2 register value */ + tmporx = htim->Instance->OR2; + + /* Enable the break input */ + tmporx &= ~bkin_enable_mask; + tmporx |= (sBreakInputConfig->Enable << bkin_enable_bitpos) & bkin_enable_mask; + + /* Set the break input polarity */ +#if defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || \ + defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + if (sBreakInputConfig->Source != TIM_BREAKINPUTSOURCE_DFSDM1) +#endif /* STM32L451xx || STM32L452xx || STM32L462xx || */ + /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx || */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + { + tmporx &= ~bkin_polarity_mask; + tmporx |= (sBreakInputConfig->Polarity << bkin_polarity_bitpos) & bkin_polarity_mask; + } + + /* Set TIMx_OR2 */ + htim->Instance->OR2 = tmporx; + } + break; + case TIM_BREAKINPUT_BRK2: + { + /* Get the TIMx_OR3 register value */ + tmporx = htim->Instance->OR3; + + /* Enable the break input */ + tmporx &= ~bkin_enable_mask; + tmporx |= (sBreakInputConfig->Enable << bkin_enable_bitpos) & bkin_enable_mask; + + /* Set the break input polarity */ +#if defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || \ + defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + if (sBreakInputConfig->Source != TIM_BREAKINPUTSOURCE_DFSDM1) +#endif /* STM32L451xx || STM32L452xx || STM32L462xx */ + /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + { + tmporx &= ~bkin_polarity_mask; + tmporx |= (sBreakInputConfig->Polarity << bkin_polarity_bitpos) & bkin_polarity_mask; + } + + /* Set TIMx_OR3 */ + htim->Instance->OR3 = tmporx; + } + break; + default: + break; + } + + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @brief Configures the TIMx Remapping input capabilities. + * @param htim TIM handle. + * @param Remap: specifies the TIM remapping source. + * + @if STM32L486xx + * For TIM1, the parameter is a combination of 4 fields (field1 | field2 | field3 | field4): + * + * field1 can have the following values: + * @arg TIM_TIM1_ETR_ADC1_NONE: TIM1_ETR is not connected to any ADC1 AWD (analog watchdog) + * @arg TIM_TIM1_ETR_ADC1_AWD1: TIM1_ETR is connected to ADC1 AWD1 + * @arg TIM_TIM1_ETR_ADC1_AWD2: TIM1_ETR is connected to ADC1 AWD2 + * @arg TIM_TIM1_ETR_ADC1_AWD3: TIM1_ETR is connected to ADC1 AWD3 + * + * field2 can have the following values: + * @arg TIM_TIM1_ETR_ADC3_NONE: TIM1_ETR is not connected to any ADC3 AWD (analog watchdog) + * @arg TIM_TIM1_ETR_ADC3_AWD1: TIM1_ETR is connected to ADC3 AWD1 + * @arg TIM_TIM1_ETR_ADC3_AWD2: TIM1_ETR is connected to ADC3 AWD2 + * @arg TIM_TIM1_ETR_ADC3_AWD3: TIM1_ETR is connected to ADC3 AWD3 + * + * field3 can have the following values: + * @arg TIM_TIM1_TI1_GPIO: TIM1 TI1 is connected to GPIO + * @arg TIM_TIM1_TI1_COMP1: TIM1 TI1 is connected to COMP1 output + * + * field4 can have the following values: + * @arg TIM_TIM1_ETR_COMP1: TIM1_ETR is connected to COMP1 output + * @arg TIM_TIM1_ETR_COMP2: TIM1_ETR is connected to COMP2 output + * @note When field4 is set to TIM_TIM1_ETR_COMP1 or TIM_TIM1_ETR_COMP2 field1 and field2 values are not significant + @endif + @if STM32L443xx + * For TIM1, the parameter is a combination of 3 fields (field1 | field2 | field3): + * + * field1 can have the following values: + * @arg TIM_TIM1_ETR_ADC1_NONE: TIM1_ETR is not connected to any ADC1 AWD (analog watchdog) + * @arg TIM_TIM1_ETR_ADC1_AWD1: TIM1_ETR is connected to ADC1 AWD1 + * @arg TIM_TIM1_ETR_ADC1_AWD2: TIM1_ETR is connected to ADC1 AWD2 + * @arg TIM_TIM1_ETR_ADC1_AWD3: TIM1_ETR is connected to ADC1 AWD3 + * + * field2 can have the following values: + * @arg TIM_TIM1_TI1_GPIO: TIM1 TI1 is connected to GPIO + * @arg TIM_TIM1_TI1_COMP1: TIM1 TI1 is connected to COMP1 output + * + * field3 can have the following values: + * @arg TIM_TIM1_ETR_COMP1: TIM1_ETR is connected to COMP1 output + * @arg TIM_TIM1_ETR_COMP2: TIM1_ETR is connected to COMP2 output + * + * @note When field3 is set to TIM_TIM1_ETR_COMP1 or TIM_TIM1_ETR_COMP2 field1 values is not significant + * + @endif + @if STM32L486xx + * For TIM2, the parameter is a combination of 3 fields (field1 | field2 | field3): + * + * field1 can have the following values: + * @arg TIM_TIM2_ITR1_TIM8_TRGO: TIM2_ITR1 is connected to TIM8_TRGO + * @arg TIM_TIM2_ITR1_OTG_FS_SOF: TIM2_ITR1 is connected to OTG_FS SOF + * + * field2 can have the following values: + * @arg TIM_TIM2_ETR_GPIO: TIM2_ETR is connected to GPIO + * @arg TIM_TIM2_ETR_LSE: TIM2_ETR is connected to LSE + * @arg TIM_TIM2_ETR_COMP1: TIM2_ETR is connected to COMP1 output + * @arg TIM_TIM2_ETR_COMP2: TIM2_ETR is connected to COMP2 output + * + * field3 can have the following values: + * @arg TIM_TIM2_TI4_GPIO: TIM2 TI4 is connected to GPIO + * @arg TIM_TIM2_TI4_COMP1: TIM2 TI4 is connected to COMP1 output + * @arg TIM_TIM2_TI4_COMP2: TIM2 TI4 is connected to COMP2 output + * @arg TIM_TIM2_TI4_COMP1_COMP2: TIM2 TI4 is connected to logical OR between COMP1 and COMP2 output + @endif + @if STM32L443xx + * For TIM2, the parameter is a combination of 3 fields (field1 | field2 | field3): + * + * field1 can have the following values: + * @arg TIM_TIM2_ITR1_NONE: No internal trigger on TIM2_ITR1 + * @arg TIM_TIM2_ITR1_USB_SOF: TIM2_ITR1 is connected to USB SOF + * + * field2 can have the following values: + * @arg TIM_TIM2_ETR_GPIO: TIM2_ETR is connected to GPIO + * @arg TIM_TIM2_ETR_LSE: TIM2_ETR is connected to LSE + * @arg TIM_TIM2_ETR_COMP1: TIM2_ETR is connected to COMP1 output + * @arg TIM_TIM2_ETR_COMP2: TIM2_ETR is connected to COMP2 output + * + * field3 can have the following values: + * @arg TIM_TIM2_TI4_GPIO: TIM2 TI4 is connected to GPIO + * @arg TIM_TIM2_TI4_COMP1: TIM2 TI4 is connected to COMP1 output + * @arg TIM_TIM2_TI4_COMP2: TIM2 TI4 is connected to COMP2 output + * @arg TIM_TIM2_TI4_COMP1_COMP2: TIM2 TI4 is connected to logical OR between COMP1 and COMP2 output + * + @endif + @if STM32L486xx + * For TIM3, the parameter is a combination 2 fields(field1 | field2): + * + * field1 can have the following values: + * @arg TIM_TIM3_TI1_GPIO: TIM3 TI1 is connected to GPIO + * @arg TIM_TIM3_TI1_COMP1: TIM3 TI1 is connected to COMP1 output + * @arg TIM_TIM3_TI1_COMP2: TIM3 TI1 is connected to COMP2 output + * @arg TIM_TIM3_TI1_COMP1_COMP2: TIM3 TI1 is connected to logical OR between COMP1 and COMP2 output + * + * field2 can have the following values: + * @arg TIM_TIM3_ETR_GPIO: TIM3_ETR is connected to GPIO + * @arg TIM_TIM3_ETR_COMP1: TIM3_ETR is connected to COMP1 output + * + @endif + @if STM32L486xx + * For TIM8, the parameter is a combination of 3 fields (field1 | field2 | field3): + * + * field1 can have the following values: + * @arg TIM_TIM8_ETR_ADC2_NONE: TIM8_ETR is not connected to any ADC2 AWD (analog watchdog) + * @arg TIM_TIM8_ETR_ADC2_AWD1: TIM8_ETR is connected to ADC2 AWD1 + * @arg TIM_TIM8_ETR_ADC2_AWD2: TIM8_ETR is connected to ADC2 AWD2 + * @arg TIM_TIM8_ETR_ADC2_AWD3: TIM8_ETR is connected to ADC2 AWD3 + * + * field2 can have the following values: + * @arg TIM_TIM8_ETR_ADC3_NONE: TIM8_ETR is not connected to any ADC3 AWD (analog watchdog) + * @arg TIM_TIM8_ETR_ADC3_AWD1: TIM8_ETR is connected to ADC3 AWD1 + * @arg TIM_TIM8_ETR_ADC3_AWD2: TIM8_ETR is connected to ADC3 AWD2 + * @arg TIM_TIM8_ETR_ADC3_AWD3: TIM8_ETR is connected to ADC3 AWD3 + * + * field3 can have the following values: + * @arg TIM_TIM8_TI1_GPIO: TIM8 TI1 is connected to GPIO + * @arg TIM_TIM8_TI1_COMP2: TIM8 TI1 is connected to COMP2 output + * + * field4 can have the following values: + * @arg TIM_TIM8_ETR_COMP1: TIM8_ETR is connected to COMP1 output + * @arg TIM_TIM8_ETR_COMP2: TIM8_ETR is connected to COMP2 output + * @note When field4 is set to TIM_TIM8_ETR_COMP1 or TIM_TIM8_ETR_COMP2 field1 and field2 values are not significant + * + @endif + * For TIM15, the parameter is a combination of 3 fields (field1 | field2): + * + * field1 can have the following values: + * @arg TIM_TIM15_TI1_GPIO: TIM15 TI1 is connected to GPIO + * @arg TIM_TIM15_TI1_LSE: TIM15 TI1 is connected to LSE + * + * field2 can have the following values: + * @arg TIM_TIM15_ENCODERMODE_NONE: No redirection + * @arg TIM_TIM15_ENCODERMODE_TIM2: TIM2 IC1 and TIM2 IC2 are connected to TIM15 IC1 and TIM15 IC2 respectively + * @arg TIM_TIM15_ENCODERMODE_TIM3: TIM3 IC1 and TIM3 IC2 are connected to TIM15 IC1 and TIM15 IC2 respectively + * @arg TIM_TIM15_ENCODERMODE_TIM4: TIM4 IC1 and TIM4 IC2 are connected to TIM15 IC1 and TIM15 IC2 respectively + * + @if STM32L486xx + * @arg TIM_TIM16_TI1_GPIO: TIM16 TI1 is connected to GPIO + * @arg TIM_TIM16_TI1_LSI: TIM16 TI1 is connected to LSI + * @arg TIM_TIM16_TI1_LSE: TIM16 TI1 is connected to LSE + * @arg TIM_TIM16_TI1_RTC: TIM16 TI1 is connected to RTC wakeup interrupt + * + @endif + @if STM32L443xx + * For TIM16, the parameter can have the following values: + * @arg TIM_TIM16_TI1_GPIO: TIM16 TI1 is connected to GPIO + * @arg TIM_TIM16_TI1_LSI: TIM16 TI1 is connected to LSI + * @arg TIM_TIM16_TI1_LSE: TIM16 TI1 is connected to LSE + * @arg TIM_TIM16_TI1_RTC: TIM16 TI1 is connected to RTC wakeup interrupt + * @arg TIM_TIM16_TI1_MSI: TIM16 TI1 is connected to MSI (contraints: MSI clock < 1/4 TIM APB clock) + * @arg TIM_TIM16_TI1_HSE_32: TIM16 TI1 is connected to HSE div 32 (note that HSE div 32 must be selected as RTC clock source) + * @arg TIM_TIM16_TI1_MCO: TIM16 TI1 is connected to MCO + * + @endif + @if STM32L486xx + * For TIM17, the parameter can have the following values: + * @arg TIM_TIM17_TI1_GPIO: TIM17 TI1 is connected to GPIO + * @arg TIM_TIM17_TI1_MSI: TIM17 TI1 is connected to MSI (contraints: MSI clock < 1/4 TIM APB clock) + * @arg TIM_TIM17_TI1_HSE_32: TIM17 TI1 is connected to HSE div 32 + * @arg TIM_TIM17_TI1_MCO: TIM17 TI1 is connected to MCO + @endif + * + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_RemapConfig(TIM_HandleTypeDef *htim, uint32_t Remap) +{ + uint32_t tmpor1 = 0; + uint32_t tmpor2 = 0; + + __HAL_LOCK(htim); + + /* Check parameters */ + assert_param(IS_TIM_REMAP_INSTANCE(htim->Instance)); + assert_param(IS_TIM_REMAP(Remap)); + + /* Set ETR_SEL bit field (if required) */ + if (IS_TIM_ETRSEL_INSTANCE(htim->Instance)) + { + tmpor2 = htim->Instance->OR2; + tmpor2 &= ~TIMx_ETRSEL_MASK; + tmpor2 |= (Remap & TIMx_ETRSEL_MASK); + + /* Set TIMx_OR2 */ + htim->Instance->OR2 = tmpor2; + } + + /* Set other remapping capabilities */ + tmpor1 = Remap; + tmpor1 &= ~TIMx_ETRSEL_MASK; + + /* Set TIMx_OR1 */ + htim->Instance->OR1 = tmpor1; + + htim->State = HAL_TIM_STATE_READY; + + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @brief Group channel 5 and channel 1, 2 or 3 + * @param htim TIM handle. + * @param Channels specifies the reference signal(s) the OC5REF is combined with. + * This parameter can be any combination of the following values: + * TIM_GROUPCH5_NONE: No effect of OC5REF on OC1REFC, OC2REFC and OC3REFC + * TIM_GROUPCH5_OC1REFC: OC1REFC is the logical AND of OC1REFC and OC5REF + * TIM_GROUPCH5_OC2REFC: OC2REFC is the logical AND of OC2REFC and OC5REF + * TIM_GROUPCH5_OC3REFC: OC3REFC is the logical AND of OC3REFC and OC5REF + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_GroupChannel5(TIM_HandleTypeDef *htim, uint32_t Channels) +{ + /* Check parameters */ + assert_param(IS_TIM_COMBINED3PHASEPWM_INSTANCE(htim->Instance)); + assert_param(IS_TIM_GROUPCH5(Channels)); + + /* Process Locked */ + __HAL_LOCK(htim); + + htim->State = HAL_TIM_STATE_BUSY; + + /* Clear GC5Cx bit fields */ + htim->Instance->CCR5 &= ~(TIM_CCR5_GC5C3|TIM_CCR5_GC5C2|TIM_CCR5_GC5C1); + + /* Set GC5Cx bit fields */ + htim->Instance->CCR5 |= Channels; + + htim->State = HAL_TIM_STATE_READY; + + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup TIMEx_Exported_Functions_Group6 Extended Callbacks functions + * @brief Extended Callbacks functions + * +@verbatim + ============================================================================== + ##### Extended Callbacks functions ##### + ============================================================================== + [..] + This section provides Extended TIM callback functions: + (+) Timer Commutation callback + (+) Timer Break callback + +@endverbatim + * @{ + */ + +/** + * @brief Hall commutation changed callback in non-blocking mode + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIMEx_CommutationCallback(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_TIMEx_CommutationCallback could be implemented in the user file + */ +} + +/** + * @brief Hall Break detection callback in non-blocking mode + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIMEx_BreakCallback(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_TIMEx_BreakCallback could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup TIMEx_Exported_Functions_Group7 Extended Peripheral State functions + * @brief Extended Peripheral State functions + * +@verbatim + ============================================================================== + ##### Extended Peripheral State functions ##### + ============================================================================== + [..] + This subsection permits to get in run-time the status of the peripheral + and the data flow. + +@endverbatim + * @{ + */ + +/** + * @brief Return the TIM Hall Sensor interface handle state. + * @param htim TIM Hall Sensor handle + * @retval HAL state + */ +HAL_TIM_StateTypeDef HAL_TIMEx_HallSensor_GetState(TIM_HandleTypeDef *htim) +{ + return htim->State; +} + +/** + * @} + */ + +/** + * @brief TIM DMA Commutation callback. + * @param hdma pointer to DMA handle. + * @retval None + */ +void TIMEx_DMACommutationCplt(DMA_HandleTypeDef *hdma) +{ + TIM_HandleTypeDef* htim = ( TIM_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; + + htim->State= HAL_TIM_STATE_READY; + + HAL_TIMEx_CommutationCallback(htim); +} + +/** + * @brief Enables or disables the TIM Capture Compare Channel xN. + * @param TIMx to select the TIM peripheral + * @param Channel specifies the TIM Channel + * This parameter can be one of the following values: + * @arg TIM_Channel_1: TIM Channel 1 + * @arg TIM_Channel_2: TIM Channel 2 + * @arg TIM_Channel_3: TIM Channel 3 + * @param ChannelNState specifies the TIM Channel CCxNE bit new state. + * This parameter can be: TIM_CCxN_ENABLE or TIM_CCxN_Disable. + * @retval None + */ +static void TIM_CCxNChannelCmd(TIM_TypeDef* TIMx, uint32_t Channel, uint32_t ChannelNState) +{ + uint32_t tmp = 0; + + tmp = TIM_CCER_CC1NE << Channel; + + /* Reset the CCxNE Bit */ + TIMx->CCER &= ~tmp; + + /* Set or reset the CCxNE Bit */ + TIMx->CCER |= (uint32_t)(ChannelNState << Channel); +} + +/** + * @} + */ + +#endif /* HAL_TIM_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_uart.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_uart.c new file mode 100644 index 0000000..7cbb858 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_uart.c @@ -0,0 +1,3448 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_uart.c + * @author MCD Application Team + * @brief UART HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Universal Asynchronous Receiver Transmitter Peripheral (UART). + * + Initialization and de-initialization functions + * + IO operation functions + * + Peripheral Control functions + * + * + @verbatim + =============================================================================== + ##### How to use this driver ##### + =============================================================================== + [..] + The UART HAL driver can be used as follows: + + (#) Declare a UART_HandleTypeDef handle structure (eg. UART_HandleTypeDef huart). + (#) Initialize the UART low level resources by implementing the HAL_UART_MspInit() API: + (++) Enable the USARTx interface clock. + (++) UART pins configuration: + (+++) Enable the clock for the UART GPIOs. + (+++) Configure these UART pins as alternate function pull-up. + (++) NVIC configuration if you need to use interrupt process (HAL_UART_Transmit_IT() + and HAL_UART_Receive_IT() APIs): + (+++) Configure the USARTx interrupt priority. + (+++) Enable the NVIC USART IRQ handle. + (++) UART interrupts handling: + -@@- The specific UART interrupts (Transmission complete interrupt, + RXNE interrupt, RX/TX FIFOs related interrupts and Error Interrupts) + are managed using the macros __HAL_UART_ENABLE_IT() and __HAL_UART_DISABLE_IT() + inside the transmit and receive processes. + (++) DMA Configuration if you need to use DMA process (HAL_UART_Transmit_DMA() + and HAL_UART_Receive_DMA() APIs): + (+++) Declare a DMA handle structure for the Tx/Rx channel. + (+++) Enable the DMAx interface clock. + (+++) Configure the declared DMA handle structure with the required Tx/Rx parameters. + (+++) Configure the DMA Tx/Rx channel. + (+++) Associate the initialized DMA handle to the UART DMA Tx/Rx handle. + (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the DMA Tx/Rx channel. + + (#) Program the Baud Rate, Word Length, Stop Bit, Parity, Prescaler value , Hardware + flow control and Mode (Receiver/Transmitter) in the huart handle Init structure. + + (#) If required, program UART advanced features (TX/RX pins swap, auto Baud rate detection,...) + in the huart handle AdvancedInit structure. + + (#) For the UART asynchronous mode, initialize the UART registers by calling + the HAL_UART_Init() API. + + (#) For the UART Half duplex mode, initialize the UART registers by calling + the HAL_HalfDuplex_Init() API. + + (#) For the UART LIN (Local Interconnection Network) mode, initialize the UART registers + by calling the HAL_LIN_Init() API. + + (#) For the UART Multiprocessor mode, initialize the UART registers + by calling the HAL_MultiProcessor_Init() API. + + (#) For the UART RS485 Driver Enabled mode, initialize the UART registers + by calling the HAL_RS485Ex_Init() API. + + [..] + (@) These API's (HAL_UART_Init(), HAL_HalfDuplex_Init(), HAL_LIN_Init(), HAL_MultiProcessor_Init(), + also configure the low level Hardware GPIO, CLOCK, CORTEX...etc) by + calling the customized HAL_UART_MspInit() API. + + @endverbatim + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup UART UART + * @brief HAL UART module driver + * @{ + */ + +#ifdef HAL_UART_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/** @defgroup UART_Private_Constants UART Private Constants + * @{ + */ +#if defined(USART_CR1_FIFOEN) +#define USART_CR1_FIELDS ((uint32_t)(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | \ + USART_CR1_TE | USART_CR1_RE | USART_CR1_OVER8| \ + USART_CR1_FIFOEN )) /*!< UART or USART CR1 fields of parameters set by UART_SetConfig API */ +#else +#define USART_CR1_FIELDS ((uint32_t)(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | \ + USART_CR1_TE | USART_CR1_RE | USART_CR1_OVER8 )) /*!< UART or USART CR1 fields of parameters set by UART_SetConfig API */ +#endif + +#if defined(USART_CR1_FIFOEN) +#define USART_CR3_FIELDS ((uint32_t)(USART_CR3_RTSE | USART_CR3_CTSE | USART_CR3_ONEBIT| \ + USART_CR3_TXFTCFG | USART_CR3_RXFTCFG )) /*!< UART or USART CR3 fields of parameters set by UART_SetConfig API */ +#else +#define USART_CR3_FIELDS ((uint32_t)(USART_CR3_RTSE | USART_CR3_CTSE | USART_CR3_ONEBIT)) /*!< UART or USART CR3 fields of parameters set by UART_SetConfig API */ +#endif + +#define LPUART_BRR_MIN 0x00000300U /* LPUART BRR minimum authorized value */ +#define LPUART_BRR_MAX 0x000FFFFFU /* LPUART BRR maximum authorized value */ + +#define UART_BRR_MIN 0x10U /* UART BRR minimum authorized value */ +#define UART_BRR_MAX 0x0000FFFFU /* UART BRR maximum authorized value */ + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/** @addtogroup UART_Private_Functions + * @{ + */ +static void UART_EndTxTransfer(UART_HandleTypeDef *huart); +static void UART_EndRxTransfer(UART_HandleTypeDef *huart); +static void UART_DMATransmitCplt(DMA_HandleTypeDef *hdma); +static void UART_DMAReceiveCplt(DMA_HandleTypeDef *hdma); +static void UART_DMARxHalfCplt(DMA_HandleTypeDef *hdma); +static void UART_DMATxHalfCplt(DMA_HandleTypeDef *hdma); +static void UART_DMAError(DMA_HandleTypeDef *hdma); +static void UART_DMAAbortOnError(DMA_HandleTypeDef *hdma); +static void UART_DMATxAbortCallback(DMA_HandleTypeDef *hdma); +static void UART_DMARxAbortCallback(DMA_HandleTypeDef *hdma); +static void UART_DMATxOnlyAbortCallback(DMA_HandleTypeDef *hdma); +static void UART_DMARxOnlyAbortCallback(DMA_HandleTypeDef *hdma); +static void UART_TxISR_8BIT(UART_HandleTypeDef *huart); +static void UART_TxISR_16BIT(UART_HandleTypeDef *huart); +#if defined(USART_CR1_FIFOEN) +static void UART_TxISR_8BIT_FIFOEN(UART_HandleTypeDef *huart); +static void UART_TxISR_16BIT_FIFOEN(UART_HandleTypeDef *huart); +#endif +static void UART_EndTransmit_IT(UART_HandleTypeDef *huart); +static void UART_RxISR_8BIT(UART_HandleTypeDef *huart); +static void UART_RxISR_16BIT(UART_HandleTypeDef *huart); +#if defined(USART_CR1_FIFOEN) +static void UART_RxISR_8BIT_FIFOEN(UART_HandleTypeDef *huart); +static void UART_RxISR_16BIT_FIFOEN(UART_HandleTypeDef *huart); +#endif + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup UART_Exported_Functions UART Exported Functions + * @{ + */ + +/** @defgroup UART_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions + * +@verbatim +=============================================================================== + ##### Initialization and Configuration functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to initialize the USARTx or the UARTy + in asynchronous mode. + (+) For the asynchronous mode the parameters below can be configured: + (++) Baud Rate + (++) Word Length + (++) Stop Bit + (++) Parity: If the parity is enabled, then the MSB bit of the data written + in the data register is transmitted but is changed by the parity bit. + (++) Hardware flow control + (++) Receiver/transmitter modes + (++) Over Sampling Method + (++) One-Bit Sampling Method + (+) For the asynchronous mode, the following advanced features can be configured as well: + (++) TX and/or RX pin level inversion + (++) data logical level inversion + (++) RX and TX pins swap + (++) RX overrun detection disabling + (++) DMA disabling on RX error + (++) MSB first on communication line + (++) auto Baud rate detection + [..] + The HAL_UART_Init(), HAL_HalfDuplex_Init(), HAL_LIN_Init()and HAL_MultiProcessor_Init()API + follow respectively the UART asynchronous, UART Half duplex, UART LIN mode + and UART multiprocessor mode configuration procedures (details for the procedures + are available in reference manual). + +@endverbatim + + Depending on the frame length defined by the M1 and M0 bits (7-bit, + 8-bit or 9-bit), the possible UART formats are listed in the + following table. + + Table 1. UART frame format. + +-----------------------------------------------------------------------+ + | M1 bit | M0 bit | PCE bit | UART frame | + |---------|---------|-----------|---------------------------------------| + | 0 | 0 | 0 | | SB | 8 bit data | STB | | + |---------|---------|-----------|---------------------------------------| + | 0 | 0 | 1 | | SB | 7 bit data | PB | STB | | + |---------|---------|-----------|---------------------------------------| + | 0 | 1 | 0 | | SB | 9 bit data | STB | | + |---------|---------|-----------|---------------------------------------| + | 0 | 1 | 1 | | SB | 8 bit data | PB | STB | | + |---------|---------|-----------|---------------------------------------| + | 1 | 0 | 0 | | SB | 7 bit data | STB | | + |---------|---------|-----------|---------------------------------------| + | 1 | 0 | 1 | | SB | 6 bit data | PB | STB | | + +-----------------------------------------------------------------------+ + + * @{ + */ + +/** + * @brief Initialize the UART mode according to the specified + * parameters in the UART_InitTypeDef and initialize the associated handle. + * @param huart UART handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart) +{ + /* Check the UART handle allocation */ + if(huart == NULL) + { + return HAL_ERROR; + } + + if(huart->Init.HwFlowCtl != UART_HWCONTROL_NONE) + { + /* Check the parameters */ + assert_param(IS_UART_HWFLOW_INSTANCE(huart->Instance)); + } + else + { + /* Check the parameters */ + assert_param((IS_UART_INSTANCE(huart->Instance)) || (IS_LPUART_INSTANCE(huart->Instance))); + } + + if(huart->gState == HAL_UART_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + huart->Lock = HAL_UNLOCKED; + + /* Init the low level hardware : GPIO, CLOCK */ + HAL_UART_MspInit(huart); + } + + huart->gState = HAL_UART_STATE_BUSY; + + /* Disable the Peripheral */ + __HAL_UART_DISABLE(huart); + + /* Set the UART Communication parameters */ + if (UART_SetConfig(huart) == HAL_ERROR) + { + return HAL_ERROR; + } + + if (huart->AdvancedInit.AdvFeatureInit != UART_ADVFEATURE_NO_INIT) + { + UART_AdvFeatureConfig(huart); + } + + /* In asynchronous mode, the following bits must be kept cleared: + - LINEN and CLKEN bits in the USART_CR2 register, + - SCEN, HDSEL and IREN bits in the USART_CR3 register.*/ + CLEAR_BIT(huart->Instance->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN)); + CLEAR_BIT(huart->Instance->CR3, (USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN)); + + /* Enable the Peripheral */ + __HAL_UART_ENABLE(huart); + + /* TEACK and/or REACK to check before moving huart->gState and huart->RxState to Ready */ + return (UART_CheckIdleState(huart)); +} + +/** + * @brief Initialize the half-duplex mode according to the specified + * parameters in the UART_InitTypeDef and creates the associated handle. + * @param huart UART handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HalfDuplex_Init(UART_HandleTypeDef *huart) +{ + /* Check the UART handle allocation */ + if(huart == NULL) + { + return HAL_ERROR; + } + + /* Check UART instance */ + assert_param(IS_UART_HALFDUPLEX_INSTANCE(huart->Instance)); + + if(huart->gState == HAL_UART_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + huart->Lock = HAL_UNLOCKED; + + /* Init the low level hardware : GPIO, CLOCK */ + HAL_UART_MspInit(huart); + } + + huart->gState = HAL_UART_STATE_BUSY; + + /* Disable the Peripheral */ + __HAL_UART_DISABLE(huart); + + /* Set the UART Communication parameters */ + if (UART_SetConfig(huart) == HAL_ERROR) + { + return HAL_ERROR; + } + + if (huart->AdvancedInit.AdvFeatureInit != UART_ADVFEATURE_NO_INIT) + { + UART_AdvFeatureConfig(huart); + } + + /* In half-duplex mode, the following bits must be kept cleared: + - LINEN and CLKEN bits in the USART_CR2 register, + - SCEN and IREN bits in the USART_CR3 register.*/ + CLEAR_BIT(huart->Instance->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN)); + CLEAR_BIT(huart->Instance->CR3, (USART_CR3_IREN | USART_CR3_SCEN)); + + /* Enable the Half-Duplex mode by setting the HDSEL bit in the CR3 register */ + SET_BIT(huart->Instance->CR3, USART_CR3_HDSEL); + + /* Enable the Peripheral */ + __HAL_UART_ENABLE(huart); + + /* TEACK and/or REACK to check before moving huart->gState and huart->RxState to Ready */ + return (UART_CheckIdleState(huart)); +} + + +/** + * @brief Initialize the LIN mode according to the specified + * parameters in the UART_InitTypeDef and creates the associated handle . + * @param huart UART handle. + * @param BreakDetectLength Specifies the LIN break detection length. + * This parameter can be one of the following values: + * @arg @ref UART_LINBREAKDETECTLENGTH_10B 10-bit break detection + * @arg @ref UART_LINBREAKDETECTLENGTH_11B 11-bit break detection + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LIN_Init(UART_HandleTypeDef *huart, uint32_t BreakDetectLength) +{ + /* Check the UART handle allocation */ + if(huart == NULL) + { + return HAL_ERROR; + } + + /* Check the LIN UART instance */ + assert_param(IS_UART_LIN_INSTANCE(huart->Instance)); + /* Check the Break detection length parameter */ + assert_param(IS_UART_LIN_BREAK_DETECT_LENGTH(BreakDetectLength)); + + /* LIN mode limited to 16-bit oversampling only */ + if(huart->Init.OverSampling == UART_OVERSAMPLING_8) + { + return HAL_ERROR; + } + /* LIN mode limited to 8-bit data length */ + if(huart->Init.WordLength != UART_WORDLENGTH_8B) + { + return HAL_ERROR; + } + + if(huart->gState == HAL_UART_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + huart->Lock = HAL_UNLOCKED; + + /* Init the low level hardware : GPIO, CLOCK */ + HAL_UART_MspInit(huart); + } + + huart->gState = HAL_UART_STATE_BUSY; + + /* Disable the Peripheral */ + __HAL_UART_DISABLE(huart); + + /* Set the UART Communication parameters */ + if (UART_SetConfig(huart) == HAL_ERROR) + { + return HAL_ERROR; + } + + if (huart->AdvancedInit.AdvFeatureInit != UART_ADVFEATURE_NO_INIT) + { + UART_AdvFeatureConfig(huart); + } + + /* In LIN mode, the following bits must be kept cleared: + - LINEN and CLKEN bits in the USART_CR2 register, + - SCEN and IREN bits in the USART_CR3 register.*/ + CLEAR_BIT(huart->Instance->CR2, USART_CR2_CLKEN); + CLEAR_BIT(huart->Instance->CR3, (USART_CR3_HDSEL | USART_CR3_IREN | USART_CR3_SCEN)); + + /* Enable the LIN mode by setting the LINEN bit in the CR2 register */ + SET_BIT(huart->Instance->CR2, USART_CR2_LINEN); + + /* Set the USART LIN Break detection length. */ + MODIFY_REG(huart->Instance->CR2, USART_CR2_LBDL, BreakDetectLength); + + /* Enable the Peripheral */ + __HAL_UART_ENABLE(huart); + + /* TEACK and/or REACK to check before moving huart->gState and huart->RxState to Ready */ + return (UART_CheckIdleState(huart)); +} + + +/** + * @brief Initialize the multiprocessor mode according to the specified + * parameters in the UART_InitTypeDef and initialize the associated handle. + * @param huart UART handle. + * @param Address UART node address (4-, 6-, 7- or 8-bit long). + * @param WakeUpMethod Specifies the UART wakeup method. + * This parameter can be one of the following values: + * @arg @ref UART_WAKEUPMETHOD_IDLELINE WakeUp by an idle line detection + * @arg @ref UART_WAKEUPMETHOD_ADDRESSMARK WakeUp by an address mark + * @note If the user resorts to idle line detection wake up, the Address parameter + * is useless and ignored by the initialization function. + * @note If the user resorts to address mark wake up, the address length detection + * is configured by default to 4 bits only. For the UART to be able to + * manage 6-, 7- or 8-bit long addresses detection, the API + * HAL_MultiProcessorEx_AddressLength_Set() must be called after + * HAL_MultiProcessor_Init(). + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MultiProcessor_Init(UART_HandleTypeDef *huart, uint8_t Address, uint32_t WakeUpMethod) +{ + /* Check the UART handle allocation */ + if(huart == NULL) + { + return HAL_ERROR; + } + + /* Check the wake up method parameter */ + assert_param(IS_UART_WAKEUPMETHOD(WakeUpMethod)); + + if(huart->gState == HAL_UART_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + huart->Lock = HAL_UNLOCKED; + + /* Init the low level hardware : GPIO, CLOCK */ + HAL_UART_MspInit(huart); + } + + huart->gState = HAL_UART_STATE_BUSY; + + /* Disable the Peripheral */ + __HAL_UART_DISABLE(huart); + + /* Set the UART Communication parameters */ + if (UART_SetConfig(huart) == HAL_ERROR) + { + return HAL_ERROR; + } + + if (huart->AdvancedInit.AdvFeatureInit != UART_ADVFEATURE_NO_INIT) + { + UART_AdvFeatureConfig(huart); + } + + /* In multiprocessor mode, the following bits must be kept cleared: + - LINEN and CLKEN bits in the USART_CR2 register, + - SCEN, HDSEL and IREN bits in the USART_CR3 register. */ + CLEAR_BIT(huart->Instance->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN)); + CLEAR_BIT(huart->Instance->CR3, (USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN)); + + if (WakeUpMethod == UART_WAKEUPMETHOD_ADDRESSMARK) + { + /* If address mark wake up method is chosen, set the USART address node */ + MODIFY_REG(huart->Instance->CR2, USART_CR2_ADD, ((uint32_t)Address << UART_CR2_ADDRESS_LSB_POS)); + } + + /* Set the wake up method by setting the WAKE bit in the CR1 register */ + MODIFY_REG(huart->Instance->CR1, USART_CR1_WAKE, WakeUpMethod); + + /* Enable the Peripheral */ + __HAL_UART_ENABLE(huart); + + /* TEACK and/or REACK to check before moving huart->gState and huart->RxState to Ready */ + return (UART_CheckIdleState(huart)); +} + + +/** + * @brief DeInitialize the UART peripheral. + * @param huart UART handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_DeInit(UART_HandleTypeDef *huart) +{ + /* Check the UART handle allocation */ + if(huart == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param((IS_UART_INSTANCE(huart->Instance)) || (IS_LPUART_INSTANCE(huart->Instance))); + + huart->gState = HAL_UART_STATE_BUSY; + + /* Disable the Peripheral */ + __HAL_UART_DISABLE(huart); + + huart->Instance->CR1 = 0x0U; + huart->Instance->CR2 = 0x0U; + huart->Instance->CR3 = 0x0U; + + /* DeInit the low level hardware */ + HAL_UART_MspDeInit(huart); + + huart->ErrorCode = HAL_UART_ERROR_NONE; + huart->gState = HAL_UART_STATE_RESET; + huart->RxState = HAL_UART_STATE_RESET; + + /* Process Unlock */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +/** + * @brief Initialize the UART MSP. + * @param huart UART handle. + * @retval None + */ +__weak void HAL_UART_MspInit(UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_UART_MspInit can be implemented in the user file + */ +} + +/** + * @brief DeInitialize the UART MSP. + * @param huart UART handle. + * @retval None + */ +__weak void HAL_UART_MspDeInit(UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_UART_MspDeInit can be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup UART_Exported_Functions_Group2 IO operation functions + * @brief UART Transmit/Receive functions + * +@verbatim + =============================================================================== + ##### IO operation functions ##### + =============================================================================== + This subsection provides a set of functions allowing to manage the UART asynchronous + and Half duplex data transfers. + + (#) There are two mode of transfer: + (+) Blocking mode: The communication is performed in polling mode. + The HAL status of all data processing is returned by the same function + after finishing transfer. + (+) Non-Blocking mode: The communication is performed using Interrupts + or DMA, These API's return the HAL status. + The end of the data processing will be indicated through the + dedicated UART IRQ when using Interrupt mode or the DMA IRQ when + using DMA mode. + The HAL_UART_TxCpltCallback(), HAL_UART_RxCpltCallback() user callbacks + will be executed respectively at the end of the transmit or Receive process + The HAL_UART_ErrorCallback()user callback will be executed when a communication error is detected + + (#) Blocking mode API's are : + (+) HAL_UART_Transmit() + (+) HAL_UART_Receive() + + (#) Non-Blocking mode API's with Interrupt are : + (+) HAL_UART_Transmit_IT() + (+) HAL_UART_Receive_IT() + (+) HAL_UART_IRQHandler() + + (#) Non-Blocking mode API's with DMA are : + (+) HAL_UART_Transmit_DMA() + (+) HAL_UART_Receive_DMA() + (+) HAL_UART_DMAPause() + (+) HAL_UART_DMAResume() + (+) HAL_UART_DMAStop() + + (#) A set of Transfer Complete Callbacks are provided in Non_Blocking mode: + (+) HAL_UART_TxHalfCpltCallback() + (+) HAL_UART_TxCpltCallback() + (+) HAL_UART_RxHalfCpltCallback() + (+) HAL_UART_RxCpltCallback() + (+) HAL_UART_ErrorCallback() + + (#) Non-Blocking mode transfers could be aborted using Abort API's : + (+) HAL_UART_Abort() + (+) HAL_UART_AbortTransmit() + (+) HAL_UART_AbortReceive() + (+) HAL_UART_Abort_IT() + (+) HAL_UART_AbortTransmit_IT() + (+) HAL_UART_AbortReceive_IT() + + (#) For Abort services based on interrupts (HAL_UART_Abortxxx_IT), a set of Abort Complete Callbacks are provided: + (+) HAL_UART_AbortCpltCallback() + (+) HAL_UART_AbortTransmitCpltCallback() + (+) HAL_UART_AbortReceiveCpltCallback() + + (#) In Non-Blocking mode transfers, possible errors are split into 2 categories. + Errors are handled as follows : + (+) Error is considered as Recoverable and non blocking : Transfer could go till end, but error severity is + to be evaluated by user : this concerns Frame Error, Parity Error or Noise Error in Interrupt mode reception . + Received character is then retrieved and stored in Rx buffer, Error code is set to allow user to identify error type, + and HAL_UART_ErrorCallback() user callback is executed. Transfer is kept ongoing on UART side. + If user wants to abort it, Abort services should be called by user. + (+) Error is considered as Blocking : Transfer could not be completed properly and is aborted. + This concerns Overrun Error In Interrupt mode reception and all errors in DMA mode. + Error code is set to allow user to identify error type, and HAL_UART_ErrorCallback() user callback is executed. + + -@- In the Half duplex communication, it is forbidden to run the transmit + and receive process in parallel, the UART state HAL_UART_STATE_BUSY_TX_RX can't be useful. + +@endverbatim + * @{ + */ + +/** + * @brief Send an amount of data in blocking mode. + * @note When FIFO mode is enabled, writing a data in the TDR register adds one + * data to the TXFIFO. Write operations to the TDR register are performed + * when TXFNF flag is set. From hardware perspective, TXFNF flag and + * TXE are mapped on the same bit-field. + * @param huart UART handle. + * @param pData Pointer to data buffer. + * @param Size Amount of data to be sent. + * @param Timeout Timeout duration. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + uint16_t* tmp; + uint32_t tickstart = 0U; + + /* Check that a Tx process is not already ongoing */ + if(huart->gState == HAL_UART_STATE_READY) + { + if((pData == NULL ) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->ErrorCode = HAL_UART_ERROR_NONE; + huart->gState = HAL_UART_STATE_BUSY_TX; + + /* Init tickstart for timeout managment*/ + tickstart = HAL_GetTick(); + + huart->TxXferSize = Size; + huart->TxXferCount = Size; + + while(huart->TxXferCount > 0U) + { + if(UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } + if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE)) + { + tmp = (uint16_t*) pData; + huart->Instance->TDR = (*tmp & (uint16_t)0x01FFU); + pData += 2U; + } + else + { + huart->Instance->TDR = (*pData++ & (uint8_t)0xFFU); + } + huart->TxXferCount--; + } + + if(UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TC, RESET, tickstart, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } + + /* At end of Tx process, restore huart->gState to Ready */ + huart->gState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive an amount of data in blocking mode. + * @note When FIFO mode is enabled, the RXFNE flag is set as long as the RXFIFO + * is not empty. Read operations from the RDR register are performed when + * RXFNE flag is set. From hardware perspective, RXFNE flag and + * RXNE are mapped on the same bit-field. + * @param huart UART handle. + * @param pData Pointer to data buffer. + * @param Size Amount of data to be received. + * @param Timeout Timeout duration. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + uint16_t* tmp; + uint16_t uhMask; + uint32_t tickstart = 0; + + /* Check that a Rx process is not already ongoing */ + if(huart->RxState == HAL_UART_STATE_READY) + { + if((pData == NULL ) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->ErrorCode = HAL_UART_ERROR_NONE; + huart->RxState = HAL_UART_STATE_BUSY_RX; + + /* Init tickstart for timeout managment*/ + tickstart = HAL_GetTick(); + + huart->RxXferSize = Size; + huart->RxXferCount = Size; + + /* Computation of UART mask to apply to RDR register */ + UART_MASK_COMPUTATION(huart); + uhMask = huart->Mask; + + /* as long as data have to be received */ + while(huart->RxXferCount > 0U) + { + if(UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } + if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE)) + { + tmp = (uint16_t*) pData ; + *tmp = (uint16_t)(huart->Instance->RDR & uhMask); + pData +=2U; + } + else + { + *pData++ = (uint8_t)(huart->Instance->RDR & (uint8_t)uhMask); + } + huart->RxXferCount--; + } + + /* At end of Rx process, restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Send an amount of data in interrupt mode. + * @param huart UART handle. + * @param pData Pointer to data buffer. + * @param Size Amount of data to be sent. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) +{ + /* Check that a Tx process is not already ongoing */ + if(huart->gState == HAL_UART_STATE_READY) + { + if((pData == NULL ) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->pTxBuffPtr = pData; + huart->TxXferSize = Size; + huart->TxXferCount = Size; + huart->TxISR = NULL; + + huart->ErrorCode = HAL_UART_ERROR_NONE; + huart->gState = HAL_UART_STATE_BUSY_TX; + +#if defined(USART_CR1_FIFOEN) + /* Configure Tx interrupt processing */ + if (huart->FifoMode == UART_FIFOMODE_ENABLE) + { + /* Set the Tx ISR function pointer according to the data word length */ + if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE)) + { + huart->TxISR = UART_TxISR_16BIT_FIFOEN; + } + else + { + huart->TxISR = UART_TxISR_8BIT_FIFOEN; + } + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + /* Enable the TX FIFO threshold interrupt */ + SET_BIT(huart->Instance->CR3, USART_CR3_TXFTIE); + } + else +#endif + { + /* Set the Tx ISR function pointer according to the data word length */ + if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE)) + { + huart->TxISR = UART_TxISR_16BIT; + } + else + { + huart->TxISR = UART_TxISR_8BIT; + } + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + /* Enable the Transmit Data Register Empty interrupt */ +#if defined(USART_CR1_FIFOEN) + SET_BIT(huart->Instance->CR1, USART_CR1_TXEIE_TXFNFIE); +#else + SET_BIT(huart->Instance->CR1, USART_CR1_TXEIE); +#endif + } + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive an amount of data in interrupt mode. + * @param huart UART handle. + * @param pData Pointer to data buffer. + * @param Size Amount of data to be received. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) +{ + /* Check that a Rx process is not already ongoing */ + if(huart->RxState == HAL_UART_STATE_READY) + { + if((pData == NULL ) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->pRxBuffPtr = pData; + huart->RxXferSize = Size; + huart->RxXferCount = Size; + huart->RxISR = NULL; + + /* Computation of UART mask to apply to RDR register */ + UART_MASK_COMPUTATION(huart); + + huart->ErrorCode = HAL_UART_ERROR_NONE; + huart->RxState = HAL_UART_STATE_BUSY_RX; + + /* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */ + SET_BIT(huart->Instance->CR3, USART_CR3_EIE); + +#if defined(USART_CR1_FIFOEN) + /* Configure Rx interrupt processing*/ + if ((huart->FifoMode == UART_FIFOMODE_ENABLE) && (Size >= huart->NbRxDataToProcess)) + { + /* Set the Rx ISR function pointer according to the data word length */ + if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE)) + { + huart->RxISR = UART_RxISR_16BIT_FIFOEN; + } + else + { + huart->RxISR = UART_RxISR_8BIT_FIFOEN; + } + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + /* Enable the UART Parity Error interrupt and RX FIFO Threshold interrupt */ + SET_BIT(huart->Instance->CR1, USART_CR1_PEIE); + SET_BIT(huart->Instance->CR3, USART_CR3_RXFTIE); + } + else +#endif + { + /* Set the Rx ISR function pointer according to the data word length */ + if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE)) + { + huart->RxISR = UART_RxISR_16BIT; + } + else + { + huart->RxISR = UART_RxISR_8BIT; + } + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + /* Enable the UART Parity Error interrupt and Data Register Not Empty interrupt */ +#if defined(USART_CR1_FIFOEN) + SET_BIT(huart->Instance->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE_RXFNEIE); +#else + SET_BIT(huart->Instance->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE); +#endif + } + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Send an amount of data in DMA mode. + * @param huart UART handle. + * @param pData Pointer to data buffer. + * @param Size Amount of data to be sent. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) +{ + /* Check that a Tx process is not already ongoing */ + if(huart->gState == HAL_UART_STATE_READY) + { + if((pData == NULL ) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->pTxBuffPtr = pData; + huart->TxXferSize = Size; + huart->TxXferCount = Size; + + huart->ErrorCode = HAL_UART_ERROR_NONE; + huart->gState = HAL_UART_STATE_BUSY_TX; + + /* Set the UART DMA transfer complete callback */ + huart->hdmatx->XferCpltCallback = UART_DMATransmitCplt; + + /* Set the UART DMA Half transfer complete callback */ + huart->hdmatx->XferHalfCpltCallback = UART_DMATxHalfCplt; + + /* Set the DMA error callback */ + huart->hdmatx->XferErrorCallback = UART_DMAError; + + /* Set the DMA abort callback */ + huart->hdmatx->XferAbortCallback = NULL; + + /* Enable the UART transmit DMA channel */ + HAL_DMA_Start_IT(huart->hdmatx, (uint32_t)huart->pTxBuffPtr, (uint32_t)&huart->Instance->TDR, Size); + + /* Clear the TC flag in the ICR register */ + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_TCF); + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + /* Enable the DMA transfer for transmit request by setting the DMAT bit + in the UART CR3 register */ + SET_BIT(huart->Instance->CR3, USART_CR3_DMAT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive an amount of data in DMA mode. + * @param huart UART handle. + * @param pData Pointer to data buffer. + * @param Size Amount of data to be received. + * @note When the UART parity is enabled (PCE = 1), the received data contain + * the parity bit (MSB position). + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) +{ + /* Check that a Rx process is not already ongoing */ + if(huart->RxState == HAL_UART_STATE_READY) + { + if((pData == NULL ) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->pRxBuffPtr = pData; + huart->RxXferSize = Size; + + huart->ErrorCode = HAL_UART_ERROR_NONE; + huart->RxState = HAL_UART_STATE_BUSY_RX; + + /* Set the UART DMA transfer complete callback */ + huart->hdmarx->XferCpltCallback = UART_DMAReceiveCplt; + + /* Set the UART DMA Half transfer complete callback */ + huart->hdmarx->XferHalfCpltCallback = UART_DMARxHalfCplt; + + /* Set the DMA error callback */ + huart->hdmarx->XferErrorCallback = UART_DMAError; + + /* Set the DMA abort callback */ + huart->hdmarx->XferAbortCallback = NULL; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(huart->hdmarx, (uint32_t)&huart->Instance->RDR, (uint32_t)huart->pRxBuffPtr, Size); + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + /* Enable the UART Parity Error Interrupt */ + SET_BIT(huart->Instance->CR1, USART_CR1_PEIE); + + /* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */ + SET_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Enable the DMA transfer for the receiver request by setting the DMAR bit + in the UART CR3 register */ + SET_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Pause the DMA Transfer. + * @param huart UART handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_DMAPause(UART_HandleTypeDef *huart) +{ + /* Process Locked */ + __HAL_LOCK(huart); + + if ((huart->gState == HAL_UART_STATE_BUSY_TX) && + (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT))) + { + /* Disable the UART DMA Tx request */ + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT); + } + if ((huart->RxState == HAL_UART_STATE_BUSY_RX) && + (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))) + { + /* Disable PE and ERR (Frame error, noise error, overrun error) interrupts */ + CLEAR_BIT(huart->Instance->CR1, USART_CR1_PEIE); + CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Disable the UART DMA Rx request */ + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + } + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +/** + * @brief Resume the DMA Transfer. + * @param huart UART handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_DMAResume(UART_HandleTypeDef *huart) +{ + /* Process Locked */ + __HAL_LOCK(huart); + + if(huart->gState == HAL_UART_STATE_BUSY_TX) + { + /* Enable the UART DMA Tx request */ + SET_BIT(huart->Instance->CR3, USART_CR3_DMAT); + } + if(huart->RxState == HAL_UART_STATE_BUSY_RX) + { + /* Clear the Overrun flag before resuming the Rx transfer */ + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF); + + /* Reenable PE and ERR (Frame error, noise error, overrun error) interrupts */ + SET_BIT(huart->Instance->CR1, USART_CR1_PEIE); + SET_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Enable the UART DMA Rx request */ + SET_BIT(huart->Instance->CR3, USART_CR3_DMAR); + } + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +/** + * @brief Stop the DMA Transfer. + * @param huart UART handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_DMAStop(UART_HandleTypeDef *huart) +{ + /* The Lock is not implemented on this API to allow the user application + to call the HAL UART API under callbacks HAL_UART_TxCpltCallback() / HAL_UART_RxCpltCallback() / + HAL_UART_TxHalfCpltCallback / HAL_UART_RxHalfCpltCallback: + indeed, when HAL_DMA_Abort() API is called, the DMA TX/RX Transfer or Half Transfer complete + interrupt is generated if the DMA transfer interruption occurs at the middle or at the end of + the stream and the corresponding call back is executed. */ + + /* Stop UART DMA Tx request if ongoing */ + if ((huart->gState == HAL_UART_STATE_BUSY_TX) && + (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT))) + { + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT); + + /* Abort the UART DMA Tx channel */ + if(huart->hdmatx != NULL) + { + HAL_DMA_Abort(huart->hdmatx); + } + + UART_EndTxTransfer(huart); + } + + /* Stop UART DMA Rx request if ongoing */ + if ((huart->RxState == HAL_UART_STATE_BUSY_RX) && + (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))) + { + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + /* Abort the UART DMA Rx channel */ + if(huart->hdmarx != NULL) + { + HAL_DMA_Abort(huart->hdmarx); + } + + UART_EndRxTransfer(huart); + } + + return HAL_OK; +} + +/** + * @brief Abort ongoing transfers (blocking mode). + * @param huart UART handle. + * @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable UART Interrupts (Tx and Rx) + * - Disable the DMA transfer in the peripheral register (if enabled) + * - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode) + * - Set handle State to READY + * @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed. + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_UART_Abort(UART_HandleTypeDef *huart) +{ + /* Disable TXEIE, TCIE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ +#if defined(USART_CR1_FIFOEN) + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE | USART_CR1_TXEIE_TXFNFIE | USART_CR1_TCIE)); +#else + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE)); +#endif + CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Disable the UART DMA Tx request if enabled */ + if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT)) + { + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT); + + /* Abort the UART DMA Tx channel : use blocking DMA Abort API (no callback) */ + if(huart->hdmatx != NULL) + { + /* Set the UART DMA Abort callback to Null. + No call back execution at end of DMA abort procedure */ + huart->hdmatx->XferAbortCallback = NULL; + + HAL_DMA_Abort(huart->hdmatx); + } + } + + /* Disable the UART DMA Rx request if enabled */ + if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) + { + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + /* Abort the UART DMA Rx channel : use blocking DMA Abort API (no callback) */ + if(huart->hdmarx != NULL) + { + /* Set the UART DMA Abort callback to Null. + No call back execution at end of DMA abort procedure */ + huart->hdmarx->XferAbortCallback = NULL; + + HAL_DMA_Abort(huart->hdmarx); + } + } + + /* Reset Tx and Rx transfer counters */ + huart->TxXferCount = 0U; + huart->RxXferCount = 0U; + + /* Clear the Error flags in the ICR register */ + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_PEF | UART_CLEAR_FEF); + +#if defined(USART_CR1_FIFOEN) + /* Flush the whole TX FIFO (if needed) */ + if (huart->FifoMode == UART_FIFOMODE_ENABLE) + { + __HAL_UART_SEND_REQ(huart, UART_TXDATA_FLUSH_REQUEST); + } +#endif + + /* Discard the received data */ + __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST); + + /* Restore huart->gState and huart->RxState to Ready */ + huart->gState = HAL_UART_STATE_READY; + huart->RxState = HAL_UART_STATE_READY; + + /* Reset Handle ErrorCode to No Error */ + huart->ErrorCode = HAL_UART_ERROR_NONE; + + return HAL_OK; +} + +/** + * @brief Abort ongoing Transmit transfer (blocking mode). + * @param huart UART handle. + * @note This procedure could be used for aborting any ongoing Tx transfer started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable UART Interrupts (Tx) + * - Disable the DMA transfer in the peripheral register (if enabled) + * - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode) + * - Set handle State to READY + * @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed. + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_UART_AbortTransmit(UART_HandleTypeDef *huart) +{ + /* Disable TXEIE and TCIE interrupts */ +#if defined(USART_CR1_FIFOEN) + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_TXEIE_TXFNFIE | USART_CR1_TCIE)); +#else + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE)); +#endif + + /* Disable the UART DMA Tx request if enabled */ + if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT)) + { + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT); + + /* Abort the UART DMA Tx channel : use blocking DMA Abort API (no callback) */ + if(huart->hdmatx != NULL) + { + /* Set the UART DMA Abort callback to Null. + No call back execution at end of DMA abort procedure */ + huart->hdmatx->XferAbortCallback = NULL; + + HAL_DMA_Abort(huart->hdmatx); + } + } + + /* Reset Tx transfer counter */ + huart->TxXferCount = 0U; + +#if defined(USART_CR1_FIFOEN) + /* Flush the whole TX FIFO (if needed) */ + if (huart->FifoMode == UART_FIFOMODE_ENABLE) + { + __HAL_UART_SEND_REQ(huart, UART_TXDATA_FLUSH_REQUEST); + } +#endif + + /* Restore huart->gState to Ready */ + huart->gState = HAL_UART_STATE_READY; + + return HAL_OK; +} + +/** + * @brief Abort ongoing Receive transfer (blocking mode). + * @param huart UART handle. + * @note This procedure could be used for aborting any ongoing Rx transfer started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable UART Interrupts (Rx) + * - Disable the DMA transfer in the peripheral register (if enabled) + * - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode) + * - Set handle State to READY + * @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed. + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_UART_AbortReceive(UART_HandleTypeDef *huart) +{ + /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ +#if defined(USART_CR1_FIFOEN) + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE)); +#else + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE)); +#endif + CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Disable the UART DMA Rx request if enabled */ + if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) + { + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + /* Abort the UART DMA Rx channel : use blocking DMA Abort API (no callback) */ + if(huart->hdmarx != NULL) + { + /* Set the UART DMA Abort callback to Null. + No call back execution at end of DMA abort procedure */ + huart->hdmarx->XferAbortCallback = NULL; + + HAL_DMA_Abort(huart->hdmarx); + } + } + + /* Reset Rx transfer counter */ + huart->RxXferCount = 0U; + + /* Clear the Error flags in the ICR register */ + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_PEF | UART_CLEAR_FEF); + + /* Discard the received data */ + __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST); + + /* Restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + + return HAL_OK; +} + +/** + * @brief Abort ongoing transfers (Interrupt mode). + * @param huart UART handle. + * @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable UART Interrupts (Tx and Rx) + * - Disable the DMA transfer in the peripheral register (if enabled) + * - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode) + * - Set handle State to READY + * - At abort completion, call user abort complete callback + * @note This procedure is executed in Interrupt mode, meaning that abort procedure could be + * considered as completed only when user abort complete callback is executed (not when exiting function). + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_UART_Abort_IT(UART_HandleTypeDef *huart) +{ + uint32_t abortcplt = 1U; + + /* Disable TXEIE, TCIE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ +#if defined(USART_CR1_FIFOEN) + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE | USART_CR1_TXEIE_TXFNFIE | USART_CR1_TCIE)); +#else + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE)); +#endif + CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* If DMA Tx and/or DMA Rx Handles are associated to UART Handle, DMA Abort complete callbacks should be initialised + before any call to DMA Abort functions */ + /* DMA Tx Handle is valid */ + if(huart->hdmatx != NULL) + { + /* Set DMA Abort Complete callback if UART DMA Tx request if enabled. + Otherwise, set it to NULL */ + if(HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT)) + { + huart->hdmatx->XferAbortCallback = UART_DMATxAbortCallback; + } + else + { + huart->hdmatx->XferAbortCallback = NULL; + } + } + /* DMA Rx Handle is valid */ + if(huart->hdmarx != NULL) + { + /* Set DMA Abort Complete callback if UART DMA Rx request if enabled. + Otherwise, set it to NULL */ + if(HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) + { + huart->hdmarx->XferAbortCallback = UART_DMARxAbortCallback; + } + else + { + huart->hdmarx->XferAbortCallback = NULL; + } + } + + /* Disable the UART DMA Tx request if enabled */ + if(HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT)) + { + /* Disable DMA Tx at UART level */ + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT); + + /* Abort the UART DMA Tx channel : use non blocking DMA Abort API (callback) */ + if(huart->hdmatx != NULL) + { + /* UART Tx DMA Abort callback has already been initialised : + will lead to call HAL_UART_AbortCpltCallback() at end of DMA abort procedure */ + + /* Abort DMA TX */ + if(HAL_DMA_Abort_IT(huart->hdmatx) != HAL_OK) + { + huart->hdmatx->XferAbortCallback = NULL; + } + else + { + abortcplt = 0U; + } + } + } + + /* Disable the UART DMA Rx request if enabled */ + if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) + { + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + /* Abort the UART DMA Rx channel : use non blocking DMA Abort API (callback) */ + if(huart->hdmarx != NULL) + { + /* UART Rx DMA Abort callback has already been initialised : + will lead to call HAL_UART_AbortCpltCallback() at end of DMA abort procedure */ + + /* Abort DMA RX */ + if(HAL_DMA_Abort_IT(huart->hdmarx) != HAL_OK) + { + huart->hdmarx->XferAbortCallback = NULL; + abortcplt = 1U; + } + else + { + abortcplt = 0U; + } + } + } + + /* if no DMA abort complete callback execution is required => call user Abort Complete callback */ + if (abortcplt == 1U) + { + /* Reset Tx and Rx transfer counters */ + huart->TxXferCount = 0U; + huart->RxXferCount = 0U; + + /* Clear ISR function pointers */ + huart->RxISR = NULL; + huart->TxISR = NULL; + + /* Reset errorCode */ + huart->ErrorCode = HAL_UART_ERROR_NONE; + + /* Clear the Error flags in the ICR register */ + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_PEF | UART_CLEAR_FEF); + +#if defined(USART_CR1_FIFOEN) + /* Flush the whole TX FIFO (if needed) */ + if (huart->FifoMode == UART_FIFOMODE_ENABLE) + { + __HAL_UART_SEND_REQ(huart, UART_TXDATA_FLUSH_REQUEST); + } +#endif + + /* Discard the received data */ + __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST); + + /* Restore huart->gState and huart->RxState to Ready */ + huart->gState = HAL_UART_STATE_READY; + huart->RxState = HAL_UART_STATE_READY; + + /* As no DMA to be aborted, call directly user Abort complete callback */ + HAL_UART_AbortCpltCallback(huart); + } + + return HAL_OK; +} + +/** + * @brief Abort ongoing Transmit transfer (Interrupt mode). + * @param huart UART handle. + * @note This procedure could be used for aborting any ongoing Tx transfer started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable UART Interrupts (Tx) + * - Disable the DMA transfer in the peripheral register (if enabled) + * - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode) + * - Set handle State to READY + * - At abort completion, call user abort complete callback + * @note This procedure is executed in Interrupt mode, meaning that abort procedure could be + * considered as completed only when user abort complete callback is executed (not when exiting function). + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_UART_AbortTransmit_IT(UART_HandleTypeDef *huart) +{ + /* Disable TXEIE and TCIE interrupts */ +#if defined(USART_CR1_FIFOEN) + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_TXEIE_TXFNFIE | USART_CR1_TCIE)); +#else + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE)); +#endif + + /* Disable the UART DMA Tx request if enabled */ + if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT)) + { + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT); + + /* Abort the UART DMA Tx channel : use non blocking DMA Abort API (callback) */ + if(huart->hdmatx != NULL) + { + /* Set the UART DMA Abort callback : + will lead to call HAL_UART_AbortCpltCallback() at end of DMA abort procedure */ + huart->hdmatx->XferAbortCallback = UART_DMATxOnlyAbortCallback; + + /* Abort DMA TX */ + if(HAL_DMA_Abort_IT(huart->hdmatx) != HAL_OK) + { + /* Call Directly huart->hdmatx->XferAbortCallback function in case of error */ + huart->hdmatx->XferAbortCallback(huart->hdmatx); + } + } + else + { + /* Reset Tx transfer counter */ + huart->TxXferCount = 0U; + + /* Clear TxISR function pointers */ + huart->TxISR = NULL; + + /* Restore huart->gState to Ready */ + huart->gState = HAL_UART_STATE_READY; + + /* As no DMA to be aborted, call directly user Abort complete callback */ + HAL_UART_AbortTransmitCpltCallback(huart); + } + } + else + { + /* Reset Tx transfer counter */ + huart->TxXferCount = 0U; + + /* Clear TxISR function pointers */ + huart->TxISR = NULL; + +#if defined(USART_CR1_FIFOEN) + /* Flush the whole TX FIFO (if needed) */ + if (huart->FifoMode == UART_FIFOMODE_ENABLE) + { + __HAL_UART_SEND_REQ(huart, UART_TXDATA_FLUSH_REQUEST); + } +#endif + + /* Restore huart->gState to Ready */ + huart->gState = HAL_UART_STATE_READY; + + /* As no DMA to be aborted, call directly user Abort complete callback */ + HAL_UART_AbortTransmitCpltCallback(huart); + } + + return HAL_OK; +} + +/** + * @brief Abort ongoing Receive transfer (Interrupt mode). + * @param huart UART handle. + * @note This procedure could be used for aborting any ongoing Rx transfer started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable UART Interrupts (Rx) + * - Disable the DMA transfer in the peripheral register (if enabled) + * - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode) + * - Set handle State to READY + * - At abort completion, call user abort complete callback + * @note This procedure is executed in Interrupt mode, meaning that abort procedure could be + * considered as completed only when user abort complete callback is executed (not when exiting function). + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_UART_AbortReceive_IT(UART_HandleTypeDef *huart) +{ + /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ +#if defined(USART_CR1_FIFOEN) + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE)); +#else + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE)); +#endif + CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Disable the UART DMA Rx request if enabled */ + if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) + { + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + /* Abort the UART DMA Rx channel : use non blocking DMA Abort API (callback) */ + if(huart->hdmarx != NULL) + { + /* Set the UART DMA Abort callback : + will lead to call HAL_UART_AbortCpltCallback() at end of DMA abort procedure */ + huart->hdmarx->XferAbortCallback = UART_DMARxOnlyAbortCallback; + + /* Abort DMA RX */ + if(HAL_DMA_Abort_IT(huart->hdmarx) != HAL_OK) + { + /* Call Directly huart->hdmarx->XferAbortCallback function in case of error */ + huart->hdmarx->XferAbortCallback(huart->hdmarx); + } + } + else + { + /* Reset Rx transfer counter */ + huart->RxXferCount = 0U; + + /* Clear RxISR function pointer */ + huart->pRxBuffPtr = NULL; + + /* Clear the Error flags in the ICR register */ + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_PEF | UART_CLEAR_FEF); + + /* Discard the received data */ + __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST); + + /* Restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + + /* As no DMA to be aborted, call directly user Abort complete callback */ + HAL_UART_AbortReceiveCpltCallback(huart); + } + } + else + { + /* Reset Rx transfer counter */ + huart->RxXferCount = 0U; + + /* Clear RxISR function pointer */ + huart->pRxBuffPtr = NULL; + + /* Clear the Error flags in the ICR register */ + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_PEF | UART_CLEAR_FEF); + + /* Restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + + /* As no DMA to be aborted, call directly user Abort complete callback */ + HAL_UART_AbortReceiveCpltCallback(huart); + } + + return HAL_OK; +} + +/** + * @brief Handle UART interrupt request. + * @param huart UART handle. + * @retval None + */ +void HAL_UART_IRQHandler(UART_HandleTypeDef *huart) +{ + uint32_t isrflags = READ_REG(huart->Instance->ISR); + uint32_t cr1its = READ_REG(huart->Instance->CR1); + uint32_t cr3its = READ_REG(huart->Instance->CR3); + uint32_t errorflags; + + /* If no error occurs */ + errorflags = (isrflags & (uint32_t)(USART_ISR_PE | USART_ISR_FE | USART_ISR_ORE | USART_ISR_NE)); + if (errorflags == RESET) + { + /* UART in mode Receiver ---------------------------------------------------*/ +#if defined(USART_CR1_FIFOEN) + if(((isrflags & USART_ISR_RXNE_RXFNE) != RESET) + && ( ((cr1its & USART_CR1_RXNEIE_RXFNEIE) != RESET) + || ((cr3its & USART_CR3_RXFTIE) != RESET)) ) +#else + if(((isrflags & USART_ISR_RXNE) != RESET) + && ((cr1its & USART_CR1_RXNEIE) != RESET)) +#endif + { + if (huart->RxISR != NULL) {huart->RxISR(huart);} + return; + } + } + + /* If some errors occur */ +#if defined(USART_CR1_FIFOEN) + if( (errorflags != RESET) + && ( (((cr3its & (USART_CR3_RXFTIE | USART_CR3_EIE)) != RESET) + || ((cr1its & (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE)) != RESET))) ) +#else + if( (errorflags != RESET) + && ( ((cr3its & USART_CR3_EIE) != RESET) + || ((cr1its & (USART_CR1_RXNEIE | USART_CR1_PEIE)) != RESET)) ) +#endif + { + /* UART parity error interrupt occurred -------------------------------------*/ + if(((isrflags & USART_ISR_PE) != RESET) && ((cr1its & USART_CR1_PEIE) != RESET)) + { + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_PEF); + + huart->ErrorCode |= HAL_UART_ERROR_PE; + } + + /* UART frame error interrupt occurred --------------------------------------*/ + if(((isrflags & USART_ISR_FE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET)) + { + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_FEF); + + huart->ErrorCode |= HAL_UART_ERROR_FE; + } + + /* UART noise error interrupt occurred --------------------------------------*/ + if(((isrflags & USART_ISR_NE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET)) + { + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_NEF); + + huart->ErrorCode |= HAL_UART_ERROR_NE; + } + + /* UART Over-Run interrupt occurred -----------------------------------------*/ +#if defined(USART_CR1_FIFOEN) + if( ((isrflags & USART_ISR_ORE) != RESET) + &&( ((cr1its & USART_CR1_RXNEIE_RXFNEIE) != RESET) || + ((cr3its & (USART_CR3_RXFTIE | USART_CR3_EIE)) != RESET))) +#else + if( ((isrflags & USART_ISR_ORE) != RESET) + &&( ((cr1its & USART_CR1_RXNEIE) != RESET) || + ((cr3its & USART_CR3_EIE) != RESET))) +#endif + { + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF); + + huart->ErrorCode |= HAL_UART_ERROR_ORE; + } + + /* Call UART Error Call back function if need be --------------------------*/ + if(huart->ErrorCode != HAL_UART_ERROR_NONE) + { + /* UART in mode Receiver ---------------------------------------------------*/ +#if defined(USART_CR1_FIFOEN) + if(((isrflags & USART_ISR_RXNE_RXFNE) != RESET) + && ( ((cr1its & USART_CR1_RXNEIE_RXFNEIE) != RESET) + || ((cr3its & USART_CR3_RXFTIE) != RESET)) ) +#else + if(((isrflags & USART_ISR_RXNE) != RESET) + && ((cr1its & USART_CR1_RXNEIE) != RESET)) +#endif + { + if (huart->RxISR != NULL) {huart->RxISR(huart);} + } + + /* If Overrun error occurs, or if any error occurs in DMA mode reception, + consider error as blocking */ + if (((huart->ErrorCode & HAL_UART_ERROR_ORE) != RESET) || + (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))) + { + /* Blocking error : transfer is aborted + Set the UART state ready to be able to start again the process, + Disable Rx Interrupts, and disable Rx DMA request, if ongoing */ + UART_EndRxTransfer(huart); + + /* Disable the UART DMA Rx request if enabled */ + if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) + { + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + /* Abort the UART DMA Rx channel */ + if(huart->hdmarx != NULL) + { + /* Set the UART DMA Abort callback : + will lead to call HAL_UART_ErrorCallback() at end of DMA abort procedure */ + huart->hdmarx->XferAbortCallback = UART_DMAAbortOnError; + + /* Abort DMA RX */ + if(HAL_DMA_Abort_IT(huart->hdmarx) != HAL_OK) + { + /* Call Directly huart->hdmarx->XferAbortCallback function in case of error */ + huart->hdmarx->XferAbortCallback(huart->hdmarx); + } + } + else + { + /* Call user error callback */ + HAL_UART_ErrorCallback(huart); + } + } + else + { + /* Call user error callback */ + HAL_UART_ErrorCallback(huart); + } + } + else + { + /* Non Blocking error : transfer could go on. + Error is notified to user through user error callback */ + HAL_UART_ErrorCallback(huart); + huart->ErrorCode = HAL_UART_ERROR_NONE; + } + } + return; + + } /* End if some error occurs */ + + /* UART wakeup from Stop mode interrupt occurred ---------------------------*/ + if(((isrflags & USART_ISR_WUF) != RESET) && ((cr3its & USART_CR3_WUFIE) != RESET)) + { + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_WUF); + /* Set the UART state ready to be able to start again the process */ + huart->gState = HAL_UART_STATE_READY; + huart->RxState = HAL_UART_STATE_READY; + HAL_UARTEx_WakeupCallback(huart); + return; + } + + /* UART in mode Transmitter ------------------------------------------------*/ +#if defined(USART_CR1_FIFOEN) + if(((isrflags & USART_ISR_TXE_TXFNF) != RESET) + && ( ((cr1its & USART_CR1_TXEIE_TXFNFIE) != RESET) + || ((cr3its & USART_CR3_TXFTIE) != RESET)) ) +#else + if(((isrflags & USART_ISR_TXE) != RESET) + && ((cr1its & USART_CR1_TXEIE) != RESET)) +#endif + { + if (huart->TxISR != NULL) {huart->TxISR(huart);} + return; + } + + /* UART in mode Transmitter (transmission end) -----------------------------*/ + if(((isrflags & USART_ISR_TC) != RESET) && ((cr1its & USART_CR1_TCIE) != RESET)) + { + UART_EndTransmit_IT(huart); + return; + } + +#if defined(USART_CR1_FIFOEN) + /* UART TX Fifo Empty occurred ----------------------------------------------*/ + if(((isrflags & USART_ISR_TXFE) != RESET) && ((cr1its & USART_CR1_TXFEIE) != RESET)) + { + HAL_UARTEx_TxFifoEmptyCallback(huart); + return; + } + + /* UART RX Fifo Full occurred ----------------------------------------------*/ + if(((isrflags & USART_ISR_RXFF) != RESET) && ((cr1its & USART_CR1_RXFFIE) != RESET)) + { + HAL_UARTEx_RxFifoFullCallback(huart); + return; + } +#endif +} + +/** + * @brief Tx Transfer completed callback. + * @param huart UART handle. + * @retval None + */ +__weak void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_UART_TxCpltCallback can be implemented in the user file. + */ +} + +/** + * @brief Tx Half Transfer completed callback. + * @param huart UART handle. + * @retval None + */ +__weak void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_UART_TxHalfCpltCallback can be implemented in the user file. + */ +} + +/** + * @brief Rx Transfer completed callback. + * @param huart UART handle. + * @retval None + */ +__weak void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_UART_RxCpltCallback can be implemented in the user file. + */ +} + +/** + * @brief Rx Half Transfer completed callback. + * @param huart UART handle. + * @retval None + */ +__weak void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_UART_RxHalfCpltCallback can be implemented in the user file. + */ +} + +/** + * @brief UART error callback. + * @param huart UART handle. + * @retval None + */ +__weak void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_UART_ErrorCallback can be implemented in the user file. + */ +} + +/** + * @brief UART Abort Complete callback. + * @param huart UART handle. + * @retval None + */ +__weak void HAL_UART_AbortCpltCallback (UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_UART_AbortCpltCallback can be implemented in the user file. + */ +} + +/** + * @brief UART Abort Complete callback. + * @param huart UART handle. + * @retval None + */ +__weak void HAL_UART_AbortTransmitCpltCallback (UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_UART_AbortTransmitCpltCallback can be implemented in the user file. + */ +} + +/** + * @brief UART Abort Receive Complete callback. + * @param huart UART handle. + * @retval None + */ +__weak void HAL_UART_AbortReceiveCpltCallback (UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_UART_AbortReceiveCpltCallback can be implemented in the user file. + */ +} + +/** + * @} + */ + +/** @defgroup UART_Exported_Functions_Group3 Peripheral Control functions + * @brief UART control functions + * +@verbatim + =============================================================================== + ##### Peripheral Control functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to control the UART. + (+) HAL_MultiProcessor_EnableMuteMode() API enables mute mode + (+) HAL_MultiProcessor_DisableMuteMode() API disables mute mode + (+) HAL_MultiProcessor_EnterMuteMode() API enters mute mode + (+) HAL_MultiProcessor_EnableMuteMode() API enables mute mode + (+) UART_SetConfig() API configures the UART peripheral + (+) UART_AdvFeatureConfig() API optionally configures the UART advanced features + (+) UART_CheckIdleState() API ensures that TEACK and/or REACK are set after initialization + (+) UART_Wakeup_AddressConfig() API configures the wake-up from stop mode parameters + (+) HAL_HalfDuplex_EnableTransmitter() API disables receiver and enables transmitter + (+) HAL_HalfDuplex_EnableReceiver() API disables transmitter and enables receiver + (+) HAL_LIN_SendBreak() API transmits the break characters +@endverbatim + * @{ + */ + +/** + * @brief Enable UART in mute mode (does not mean UART enters mute mode; + * to enter mute mode, HAL_MultiProcessor_EnterMuteMode() API must be called). + * @param huart UART handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MultiProcessor_EnableMuteMode(UART_HandleTypeDef *huart) +{ + /* Process Locked */ + __HAL_LOCK(huart); + + huart->gState = HAL_UART_STATE_BUSY; + + /* Enable USART mute mode by setting the MME bit in the CR1 register */ + SET_BIT(huart->Instance->CR1, USART_CR1_MME); + + huart->gState = HAL_UART_STATE_READY; + + return (UART_CheckIdleState(huart)); +} + +/** + * @brief Disable UART mute mode (does not mean the UART actually exits mute mode + * as it may not have been in mute mode at this very moment). + * @param huart UART handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MultiProcessor_DisableMuteMode(UART_HandleTypeDef *huart) +{ + /* Process Locked */ + __HAL_LOCK(huart); + + huart->gState = HAL_UART_STATE_BUSY; + + /* Disable USART mute mode by clearing the MME bit in the CR1 register */ + CLEAR_BIT(huart->Instance->CR1, USART_CR1_MME); + + huart->gState = HAL_UART_STATE_READY; + + return (UART_CheckIdleState(huart)); +} + +/** + * @brief Enter UART mute mode (means UART actually enters mute mode). + * @note To exit from mute mode, HAL_MultiProcessor_DisableMuteMode() API must be called. + * @param huart UART handle. + * @retval None + */ +void HAL_MultiProcessor_EnterMuteMode(UART_HandleTypeDef *huart) +{ + __HAL_UART_SEND_REQ(huart, UART_MUTE_MODE_REQUEST); +} + +/** + * @brief Enable the UART transmitter and disable the UART receiver. + * @param huart UART handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HalfDuplex_EnableTransmitter(UART_HandleTypeDef *huart) +{ + /* Process Locked */ + __HAL_LOCK(huart); + huart->gState = HAL_UART_STATE_BUSY; + + /* Clear TE and RE bits */ + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_TE | USART_CR1_RE)); + + /* Enable the USART's transmit interface by setting the TE bit in the USART CR1 register */ + SET_BIT(huart->Instance->CR1, USART_CR1_TE); + + huart->gState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +/** + * @brief Enable the UART receiver and disable the UART transmitter. + * @param huart UART handle. + * @retval HAL status. + */ +HAL_StatusTypeDef HAL_HalfDuplex_EnableReceiver(UART_HandleTypeDef *huart) +{ + /* Process Locked */ + __HAL_LOCK(huart); + huart->gState = HAL_UART_STATE_BUSY; + + /* Clear TE and RE bits */ + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_TE | USART_CR1_RE)); + + /* Enable the USART's receive interface by setting the RE bit in the USART CR1 register */ + SET_BIT(huart->Instance->CR1, USART_CR1_RE); + + huart->gState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + + +/** + * @brief Transmit break characters. + * @param huart UART handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LIN_SendBreak(UART_HandleTypeDef *huart) +{ + /* Check the parameters */ + assert_param(IS_UART_LIN_INSTANCE(huart->Instance)); + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->gState = HAL_UART_STATE_BUSY; + + /* Send break characters */ + SET_BIT(huart->Instance->RQR, UART_SENDBREAK_REQUEST); + + huart->gState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup UART_Exported_Functions_Group4 Peripheral State and Error functions + * @brief UART Peripheral State functions + * +@verbatim + ============================================================================== + ##### Peripheral State and Error functions ##### + ============================================================================== + [..] + This subsection provides functions allowing to : + (+) Return the UART handle state. + (+) Return the UART handle error code + +@endverbatim + * @{ + */ + +/** + * @brief Return the UART handle state. + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART. + * @retval HAL state + */ +HAL_UART_StateTypeDef HAL_UART_GetState(UART_HandleTypeDef *huart) +{ + uint32_t temp1= 0x00U, temp2 = 0x00U; + temp1 = huart->gState; + temp2 = huart->RxState; + + return (HAL_UART_StateTypeDef)(temp1 | temp2); +} + +/** +* @brief Return the UART handle error code. + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART. +* @retval UART Error Code +*/ +uint32_t HAL_UART_GetError(UART_HandleTypeDef *huart) +{ + return huart->ErrorCode; +} +/** + * @} + */ + +/** + * @} + */ + +/** @defgroup UART_Private_Functions UART Private Functions + * @{ + */ + +/** + * @brief Configure the UART peripheral. + * @param huart UART handle. + * @retval HAL status + */ +HAL_StatusTypeDef UART_SetConfig(UART_HandleTypeDef *huart) +{ + uint32_t tmpreg = 0x00000000U; + UART_ClockSourceTypeDef clocksource = UART_CLOCKSOURCE_UNDEFINED; + uint16_t brrtemp = 0x0000U; + uint32_t usartdiv = 0x00000000U; + HAL_StatusTypeDef ret = HAL_OK; + uint32_t lpuart_ker_ck_pres = 0x00000000U; + + /* Check the parameters */ + assert_param(IS_UART_BAUDRATE(huart->Init.BaudRate)); + assert_param(IS_UART_WORD_LENGTH(huart->Init.WordLength)); + if(UART_INSTANCE_LOWPOWER(huart)) + { + assert_param(IS_LPUART_STOPBITS(huart->Init.StopBits)); + } + else + { + assert_param(IS_UART_STOPBITS(huart->Init.StopBits)); + assert_param(IS_UART_ONE_BIT_SAMPLE(huart->Init.OneBitSampling)); + } + + assert_param(IS_UART_PARITY(huart->Init.Parity)); + assert_param(IS_UART_MODE(huart->Init.Mode)); + assert_param(IS_UART_HARDWARE_FLOW_CONTROL(huart->Init.HwFlowCtl)); + assert_param(IS_UART_OVERSAMPLING(huart->Init.OverSampling)); +#if defined(USART_PRESC_PRESCALER) + assert_param(IS_UART_PRESCALER(huart->Init.ClockPrescaler)); +#endif + + /*-------------------------- USART CR1 Configuration -----------------------*/ + /* Clear M, PCE, PS, TE, RE and OVER8 bits and configure + * the UART Word Length, Parity, Mode and oversampling: + * set the M bits according to huart->Init.WordLength value + * set PCE and PS bits according to huart->Init.Parity value + * set TE and RE bits according to huart->Init.Mode value + * set OVER8 bit according to huart->Init.OverSampling value */ + tmpreg = (uint32_t)huart->Init.WordLength | huart->Init.Parity | huart->Init.Mode | huart->Init.OverSampling ; + MODIFY_REG(huart->Instance->CR1, USART_CR1_FIELDS, tmpreg); + + /*-------------------------- USART CR2 Configuration -----------------------*/ + /* Configure the UART Stop Bits: Set STOP[13:12] bits according + * to huart->Init.StopBits value */ + MODIFY_REG(huart->Instance->CR2, USART_CR2_STOP, huart->Init.StopBits); + + /*-------------------------- USART CR3 Configuration -----------------------*/ + /* Configure + * - UART HardWare Flow Control: set CTSE and RTSE bits according + * to huart->Init.HwFlowCtl value + * - one-bit sampling method versus three samples' majority rule according + * to huart->Init.OneBitSampling (not applicable to LPUART) + * - set TXFTCFG bit according to huart->Init.TxFifoThreshold value + * - set RXFTCFG bit according to huart->Init.RxFifoThreshold value */ + tmpreg = (uint32_t)huart->Init.HwFlowCtl; + + if (!(UART_INSTANCE_LOWPOWER(huart))) + { + tmpreg |= huart->Init.OneBitSampling; + } + MODIFY_REG(huart->Instance->CR3, USART_CR3_FIELDS, tmpreg); + +#if defined(USART_PRESC_PRESCALER) + /*-------------------------- USART PRESC Configuration -----------------------*/ + /* Configure + * - UART Clock Prescaler : set PRESCALER according to huart->Init.ClockPrescaler value */ + MODIFY_REG(huart->Instance->PRESC, USART_PRESC_PRESCALER, huart->Init.ClockPrescaler); +#endif + + /*-------------------------- USART BRR Configuration -----------------------*/ + UART_GETCLOCKSOURCE(huart, clocksource); + + /* Check LPUART instance */ + if(UART_INSTANCE_LOWPOWER(huart)) + { + /* Retrieve frequency clock */ + switch (clocksource) + { + case UART_CLOCKSOURCE_PCLK1: +#if defined(USART_PRESC_PRESCALER) + lpuart_ker_ck_pres = (HAL_RCC_GetPCLK1Freq()/UARTPrescTable[huart->Init.ClockPrescaler]); +#else + lpuart_ker_ck_pres = HAL_RCC_GetPCLK1Freq(); +#endif + break; + case UART_CLOCKSOURCE_HSI: +#if defined(USART_PRESC_PRESCALER) + lpuart_ker_ck_pres = ((uint32_t)HSI_VALUE/UARTPrescTable[huart->Init.ClockPrescaler]); +#else + lpuart_ker_ck_pres = (uint32_t)HSI_VALUE; +#endif + break; + case UART_CLOCKSOURCE_SYSCLK: +#if defined(USART_PRESC_PRESCALER) + lpuart_ker_ck_pres = (HAL_RCC_GetSysClockFreq()/UARTPrescTable[huart->Init.ClockPrescaler]); +#else + lpuart_ker_ck_pres = HAL_RCC_GetSysClockFreq(); +#endif + break; + case UART_CLOCKSOURCE_LSE: +#if defined(USART_PRESC_PRESCALER) + lpuart_ker_ck_pres = ((uint32_t)LSE_VALUE/UARTPrescTable[huart->Init.ClockPrescaler]); +#else + lpuart_ker_ck_pres = (uint32_t)LSE_VALUE; +#endif + break; + case UART_CLOCKSOURCE_UNDEFINED: + default: + ret = HAL_ERROR; + break; + } + + /* if proper clock source reported */ + if (lpuart_ker_ck_pres != 0U) + { + /* ensure that Frequency clock is in the range [3 * baudrate, 4096 * baudrate] */ + if ( (lpuart_ker_ck_pres < (3 * huart->Init.BaudRate) ) || + (lpuart_ker_ck_pres > (4096 * huart->Init.BaudRate) )) + { + ret = HAL_ERROR; + } + else + { + switch (clocksource) + { + case UART_CLOCKSOURCE_PCLK1: +#if defined(USART_PRESC_PRESCALER) + usartdiv = (uint32_t)(UART_DIV_LPUART(HAL_RCC_GetPCLK1Freq(), huart->Init.BaudRate, huart->Init.ClockPrescaler)); +#else + usartdiv = (uint32_t)(UART_DIV_LPUART(HAL_RCC_GetPCLK1Freq(), huart->Init.BaudRate)); +#endif + break; + case UART_CLOCKSOURCE_HSI: +#if defined(USART_PRESC_PRESCALER) + usartdiv = (uint32_t)(UART_DIV_LPUART(HSI_VALUE, huart->Init.BaudRate, huart->Init.ClockPrescaler)); +#else + usartdiv = (uint32_t)(UART_DIV_LPUART(HSI_VALUE, huart->Init.BaudRate)); +#endif + break; + case UART_CLOCKSOURCE_SYSCLK: +#if defined(USART_PRESC_PRESCALER) + usartdiv = (uint32_t)(UART_DIV_LPUART(HAL_RCC_GetSysClockFreq(), huart->Init.BaudRate, huart->Init.ClockPrescaler)); +#else + usartdiv = (uint32_t)(UART_DIV_LPUART(HAL_RCC_GetSysClockFreq(), huart->Init.BaudRate)); +#endif + break; + case UART_CLOCKSOURCE_LSE: +#if defined(USART_PRESC_PRESCALER) + usartdiv = (uint32_t)(UART_DIV_LPUART(LSE_VALUE, huart->Init.BaudRate, huart->Init.ClockPrescaler)); +#else + usartdiv = (uint32_t)(UART_DIV_LPUART(LSE_VALUE, huart->Init.BaudRate)); +#endif + break; + case UART_CLOCKSOURCE_UNDEFINED: + default: + ret = HAL_ERROR; + break; + } + + /* It is forbidden to write values lower than 0x300 in the LPUART_BRR register */ + if ((usartdiv >= LPUART_BRR_MIN) && (usartdiv <= LPUART_BRR_MAX)) + { + huart->Instance->BRR = usartdiv; + } + else + { + ret = HAL_ERROR; + } + } /* if ( (tmpreg < (3 * huart->Init.BaudRate) ) || (tmpreg > (4096 * huart->Init.BaudRate) )) */ + } /* if (tmpreg != 0) */ + } + /* Check UART Over Sampling to set Baud Rate Register */ + else if (huart->Init.OverSampling == UART_OVERSAMPLING_8) + { + switch (clocksource) + { + case UART_CLOCKSOURCE_PCLK1: +#if defined(USART_PRESC_PRESCALER) + usartdiv = (uint16_t)(UART_DIV_SAMPLING8(HAL_RCC_GetPCLK1Freq(), huart->Init.BaudRate, huart->Init.ClockPrescaler)); +#else + usartdiv = (uint16_t)(UART_DIV_SAMPLING8(HAL_RCC_GetPCLK1Freq(), huart->Init.BaudRate)); +#endif + break; + case UART_CLOCKSOURCE_PCLK2: +#if defined(USART_PRESC_PRESCALER) + usartdiv = (uint16_t)(UART_DIV_SAMPLING8(HAL_RCC_GetPCLK2Freq(), huart->Init.BaudRate, huart->Init.ClockPrescaler)); +#else + usartdiv = (uint16_t)(UART_DIV_SAMPLING8(HAL_RCC_GetPCLK2Freq(), huart->Init.BaudRate)); +#endif + break; + case UART_CLOCKSOURCE_HSI: +#if defined(USART_PRESC_PRESCALER) + usartdiv = (uint16_t)(UART_DIV_SAMPLING8(HSI_VALUE, huart->Init.BaudRate, huart->Init.ClockPrescaler)); +#else + usartdiv = (uint16_t)(UART_DIV_SAMPLING8(HSI_VALUE, huart->Init.BaudRate)); +#endif + break; + case UART_CLOCKSOURCE_SYSCLK: +#if defined(USART_PRESC_PRESCALER) + usartdiv = (uint16_t)(UART_DIV_SAMPLING8(HAL_RCC_GetSysClockFreq(), huart->Init.BaudRate, huart->Init.ClockPrescaler)); +#else + usartdiv = (uint16_t)(UART_DIV_SAMPLING8(HAL_RCC_GetSysClockFreq(), huart->Init.BaudRate)); +#endif + break; + case UART_CLOCKSOURCE_LSE: +#if defined(USART_PRESC_PRESCALER) + usartdiv = (uint16_t)(UART_DIV_SAMPLING8(LSE_VALUE, huart->Init.BaudRate, huart->Init.ClockPrescaler)); +#else + usartdiv = (uint16_t)(UART_DIV_SAMPLING8(LSE_VALUE, huart->Init.BaudRate)); +#endif + break; + case UART_CLOCKSOURCE_UNDEFINED: + default: + ret = HAL_ERROR; + break; + } + + /* USARTDIV must be greater than or equal to 0d16 */ + if ((usartdiv >= UART_BRR_MIN) && (usartdiv <= UART_BRR_MAX)) + { + brrtemp = usartdiv & 0xFFF0U; + brrtemp |= (uint16_t)((usartdiv & (uint16_t)0x000FU) >> 1U); + huart->Instance->BRR = brrtemp; + } + else + { + ret = HAL_ERROR; + } + } + else + { + switch (clocksource) + { + case UART_CLOCKSOURCE_PCLK1: +#if defined(USART_PRESC_PRESCALER) + usartdiv = (uint16_t)(UART_DIV_SAMPLING16(HAL_RCC_GetPCLK1Freq(), huart->Init.BaudRate, huart->Init.ClockPrescaler)); +#else + usartdiv = (uint16_t)(UART_DIV_SAMPLING16(HAL_RCC_GetPCLK1Freq(), huart->Init.BaudRate)); +#endif + break; + case UART_CLOCKSOURCE_PCLK2: +#if defined(USART_PRESC_PRESCALER) + usartdiv = (uint16_t)(UART_DIV_SAMPLING16(HAL_RCC_GetPCLK2Freq(), huart->Init.BaudRate, huart->Init.ClockPrescaler)); +#else + usartdiv = (uint16_t)(UART_DIV_SAMPLING16(HAL_RCC_GetPCLK2Freq(), huart->Init.BaudRate)); +#endif + break; + case UART_CLOCKSOURCE_HSI: +#if defined(USART_PRESC_PRESCALER) + usartdiv = (uint16_t)(UART_DIV_SAMPLING16(HSI_VALUE, huart->Init.BaudRate, huart->Init.ClockPrescaler)); +#else + usartdiv = (uint16_t)(UART_DIV_SAMPLING16(HSI_VALUE, huart->Init.BaudRate)); +#endif + break; + case UART_CLOCKSOURCE_SYSCLK: +#if defined(USART_PRESC_PRESCALER) + usartdiv = (uint16_t)(UART_DIV_SAMPLING16(HAL_RCC_GetSysClockFreq(), huart->Init.BaudRate, huart->Init.ClockPrescaler)); +#else + usartdiv = (uint16_t)(UART_DIV_SAMPLING16(HAL_RCC_GetSysClockFreq(), huart->Init.BaudRate)); +#endif + break; + case UART_CLOCKSOURCE_LSE: +#if defined(USART_PRESC_PRESCALER) + usartdiv = (uint16_t)(UART_DIV_SAMPLING16(LSE_VALUE, huart->Init.BaudRate, huart->Init.ClockPrescaler)); +#else + usartdiv = (uint16_t)(UART_DIV_SAMPLING16(LSE_VALUE, huart->Init.BaudRate)); +#endif + break; + case UART_CLOCKSOURCE_UNDEFINED: + default: + ret = HAL_ERROR; + break; + } + + /* USARTDIV must be greater than or equal to 0d16 */ + if ((usartdiv >= UART_BRR_MIN) && (usartdiv <= UART_BRR_MAX)) + { + huart->Instance->BRR = usartdiv; + } + else + { + ret = HAL_ERROR; + } + } + +#if defined(USART_CR1_FIFOEN) + /* Initialize the number of data to process during RX/TX ISR execution */ + huart->NbTxDataToProcess = 1; + huart->NbRxDataToProcess = 1; +#endif + + /* Clear ISR function pointers */ + huart->RxISR = NULL; + huart->TxISR = NULL; + + return ret; +} + +/** + * @brief Configure the UART peripheral advanced features. + * @param huart UART handle. + * @retval None + */ +void UART_AdvFeatureConfig(UART_HandleTypeDef *huart) +{ + /* Check whether the set of advanced features to configure is properly set */ + assert_param(IS_UART_ADVFEATURE_INIT(huart->AdvancedInit.AdvFeatureInit)); + + /* if required, configure TX pin active level inversion */ + if(HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_TXINVERT_INIT)) + { + assert_param(IS_UART_ADVFEATURE_TXINV(huart->AdvancedInit.TxPinLevelInvert)); + MODIFY_REG(huart->Instance->CR2, USART_CR2_TXINV, huart->AdvancedInit.TxPinLevelInvert); + } + + /* if required, configure RX pin active level inversion */ + if(HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_RXINVERT_INIT)) + { + assert_param(IS_UART_ADVFEATURE_RXINV(huart->AdvancedInit.RxPinLevelInvert)); + MODIFY_REG(huart->Instance->CR2, USART_CR2_RXINV, huart->AdvancedInit.RxPinLevelInvert); + } + + /* if required, configure data inversion */ + if(HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_DATAINVERT_INIT)) + { + assert_param(IS_UART_ADVFEATURE_DATAINV(huart->AdvancedInit.DataInvert)); + MODIFY_REG(huart->Instance->CR2, USART_CR2_DATAINV, huart->AdvancedInit.DataInvert); + } + + /* if required, configure RX/TX pins swap */ + if(HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_SWAP_INIT)) + { + assert_param(IS_UART_ADVFEATURE_SWAP(huart->AdvancedInit.Swap)); + MODIFY_REG(huart->Instance->CR2, USART_CR2_SWAP, huart->AdvancedInit.Swap); + } + + /* if required, configure RX overrun detection disabling */ + if(HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_RXOVERRUNDISABLE_INIT)) + { + assert_param(IS_UART_OVERRUN(huart->AdvancedInit.OverrunDisable)); + MODIFY_REG(huart->Instance->CR3, USART_CR3_OVRDIS, huart->AdvancedInit.OverrunDisable); + } + + /* if required, configure DMA disabling on reception error */ + if(HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_DMADISABLEONERROR_INIT)) + { + assert_param(IS_UART_ADVFEATURE_DMAONRXERROR(huart->AdvancedInit.DMADisableonRxError)); + MODIFY_REG(huart->Instance->CR3, USART_CR3_DDRE, huart->AdvancedInit.DMADisableonRxError); + } + + /* if required, configure auto Baud rate detection scheme */ + if(HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_AUTOBAUDRATE_INIT)) + { + assert_param(IS_USART_AUTOBAUDRATE_DETECTION_INSTANCE(huart->Instance)); + assert_param(IS_UART_ADVFEATURE_AUTOBAUDRATE(huart->AdvancedInit.AutoBaudRateEnable)); + MODIFY_REG(huart->Instance->CR2, USART_CR2_ABREN, huart->AdvancedInit.AutoBaudRateEnable); + /* set auto Baudrate detection parameters if detection is enabled */ + if(huart->AdvancedInit.AutoBaudRateEnable == UART_ADVFEATURE_AUTOBAUDRATE_ENABLE) + { + assert_param(IS_UART_ADVFEATURE_AUTOBAUDRATEMODE(huart->AdvancedInit.AutoBaudRateMode)); + MODIFY_REG(huart->Instance->CR2, USART_CR2_ABRMODE, huart->AdvancedInit.AutoBaudRateMode); + } + } + + /* if required, configure MSB first on communication line */ + if(HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_MSBFIRST_INIT)) + { + assert_param(IS_UART_ADVFEATURE_MSBFIRST(huart->AdvancedInit.MSBFirst)); + MODIFY_REG(huart->Instance->CR2, USART_CR2_MSBFIRST, huart->AdvancedInit.MSBFirst); + } +} + +/** + * @brief Check the UART Idle State. + * @param huart UART handle. + * @retval HAL status + */ +HAL_StatusTypeDef UART_CheckIdleState(UART_HandleTypeDef *huart) +{ + uint32_t tickstart = 0U; + + /* Initialize the UART ErrorCode */ + huart->ErrorCode = HAL_UART_ERROR_NONE; + + /* Init tickstart for timeout managment*/ + tickstart = HAL_GetTick(); + + /* Check if the Transmitter is enabled */ + if((huart->Instance->CR1 & USART_CR1_TE) == USART_CR1_TE) + { + /* Wait until TEACK flag is set */ + if(UART_WaitOnFlagUntilTimeout(huart, USART_ISR_TEACK, RESET, tickstart, HAL_UART_TIMEOUT_VALUE) != HAL_OK) + { + /* Timeout occurred */ + return HAL_TIMEOUT; + } + } + /* Check if the Receiver is enabled */ + if((huart->Instance->CR1 & USART_CR1_RE) == USART_CR1_RE) + { + /* Wait until REACK flag is set */ + if(UART_WaitOnFlagUntilTimeout(huart, USART_ISR_REACK, RESET, tickstart, HAL_UART_TIMEOUT_VALUE) != HAL_OK) + { + /* Timeout occurred */ + return HAL_TIMEOUT; + } + } + + /* Initialize the UART State */ + huart->gState= HAL_UART_STATE_READY; + huart->RxState= HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +/** + * @brief Handle UART Communication Timeout. + * @param huart UART handle. + * @param Flag Specifies the UART flag to check + * @param Status Flag status (SET or RESET) + * @param Tickstart Tick start value + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef UART_WaitOnFlagUntilTimeout(UART_HandleTypeDef *huart, uint32_t Flag, FlagStatus Status, uint32_t Tickstart, uint32_t Timeout) +{ + /* Wait until flag is set */ + while((__HAL_UART_GET_FLAG(huart, Flag) ? SET : RESET) == Status) + { + /* Check for the Timeout */ + if(Timeout != HAL_MAX_DELAY) + { + if((Timeout == 0U) || ((HAL_GetTick()-Tickstart) > Timeout)) + { + /* Disable TXE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts for the interrupt process */ +#if defined(USART_CR1_FIFOEN) + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE | USART_CR1_TXEIE_TXFNFIE)); +#else + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE)); +#endif + CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + huart->gState = HAL_UART_STATE_READY; + huart->RxState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_TIMEOUT; + } + } + } + return HAL_OK; +} + + +/** + * @brief End ongoing Tx transfer on UART peripheral (following error detection or Transmit completion). + * @param huart UART handle. + * @retval None + */ +static void UART_EndTxTransfer(UART_HandleTypeDef *huart) +{ + /* Disable TXEIE and TCIE interrupts */ +#if defined(USART_CR1_FIFOEN) + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_TXEIE_TXFNFIE | USART_CR1_TCIE)); +#else + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE)); +#endif + + /* At end of Tx process, restore huart->gState to Ready */ + huart->gState = HAL_UART_STATE_READY; +} + + +/** + * @brief End ongoing Rx transfer on UART peripheral (following error detection or Reception completion). + * @param huart UART handle. + * @retval None + */ +static void UART_EndRxTransfer(UART_HandleTypeDef *huart) +{ + /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ +#if defined(USART_CR1_FIFOEN) + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE)); +#else + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE)); +#endif + CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* At end of Rx process, restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + + /* Reset RxIsr function pointer */ + huart->RxISR = NULL; +} + + +/** + * @brief DMA UART transmit process complete callback. + * @param hdma DMA handle. + * @retval None + */ +static void UART_DMATransmitCplt(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef* huart = (UART_HandleTypeDef*)(hdma->Parent); + + /* DMA Normal mode */ + if ( HAL_IS_BIT_CLR(hdma->Instance->CCR, DMA_CCR_CIRC) ) + { + huart->TxXferCount = 0U; + + /* Disable the DMA transfer for transmit request by resetting the DMAT bit + in the UART CR3 register */ + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT); + + /* Enable the UART Transmit Complete Interrupt */ + SET_BIT(huart->Instance->CR1, USART_CR1_TCIE); + } + /* DMA Circular mode */ + else + { + HAL_UART_TxCpltCallback(huart); + } +} + +/** + * @brief DMA UART transmit process half complete callback. + * @param hdma DMA handle. + * @retval None + */ +static void UART_DMATxHalfCplt(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef* huart = (UART_HandleTypeDef*)(hdma->Parent); + + HAL_UART_TxHalfCpltCallback(huart); +} + +/** + * @brief DMA UART receive process complete callback. + * @param hdma DMA handle. + * @retval None + */ +static void UART_DMAReceiveCplt(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef* huart = (UART_HandleTypeDef*)(hdma->Parent); + + /* DMA Normal mode */ + if ( HAL_IS_BIT_CLR(hdma->Instance->CCR, DMA_CCR_CIRC) ) + { + huart->RxXferCount = 0U; + + /* Disable PE and ERR (Frame error, noise error, overrun error) interrupts */ + CLEAR_BIT(huart->Instance->CR1, USART_CR1_PEIE); + CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Disable the DMA transfer for the receiver request by resetting the DMAR bit + in the UART CR3 register */ + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + /* At end of Rx process, restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + } + + HAL_UART_RxCpltCallback(huart); +} + +/** + * @brief DMA UART receive process half complete callback. + * @param hdma DMA handle. + * @retval None + */ +static void UART_DMARxHalfCplt(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef* huart = (UART_HandleTypeDef*)(hdma->Parent); + + HAL_UART_RxHalfCpltCallback(huart); +} + +/** + * @brief DMA UART communication error callback. + * @param hdma DMA handle. + * @retval None + */ +static void UART_DMAError(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef* huart = (UART_HandleTypeDef*)(hdma->Parent); + + /* Stop UART DMA Tx request if ongoing */ + if ( (huart->gState == HAL_UART_STATE_BUSY_TX) + &&(HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT)) ) + { + huart->TxXferCount = 0U; + UART_EndTxTransfer(huart); + } + + /* Stop UART DMA Rx request if ongoing */ + if ( (huart->RxState == HAL_UART_STATE_BUSY_RX) + &&(HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) ) + { + huart->RxXferCount = 0U; + UART_EndRxTransfer(huart); + } + + huart->ErrorCode |= HAL_UART_ERROR_DMA; + HAL_UART_ErrorCallback(huart); +} + +/** + * @brief DMA UART communication abort callback, when initiated by HAL services on Error + * (To be called at end of DMA Abort procedure following error occurrence). + * @param hdma DMA handle. + * @retval None + */ +static void UART_DMAAbortOnError(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef* huart = (UART_HandleTypeDef*)(hdma->Parent); + huart->RxXferCount = 0U; + huart->TxXferCount = 0U; + + HAL_UART_ErrorCallback(huart); +} + +/** + * @brief DMA UART Tx communication abort callback, when initiated by user + * (To be called at end of DMA Tx Abort procedure following user abort request). + * @note When this callback is executed, User Abort complete call back is called only if no + * Abort still ongoing for Rx DMA Handle. + * @param hdma DMA handle. + * @retval None + */ +static void UART_DMATxAbortCallback(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef* huart = (UART_HandleTypeDef* )(hdma->Parent); + + huart->hdmatx->XferAbortCallback = NULL; + + /* Check if an Abort process is still ongoing */ + if(huart->hdmarx != NULL) + { + if(huart->hdmarx->XferAbortCallback != NULL) + { + return; + } + } + + /* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */ + huart->TxXferCount = 0U; + huart->RxXferCount = 0U; + + /* Reset errorCode */ + huart->ErrorCode = HAL_UART_ERROR_NONE; + + /* Clear the Error flags in the ICR register */ + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_PEF | UART_CLEAR_FEF); + +#if defined(USART_CR1_FIFOEN) + /* Flush the whole TX FIFO (if needed) */ + if (huart->FifoMode == UART_FIFOMODE_ENABLE) + { + __HAL_UART_SEND_REQ(huart, UART_TXDATA_FLUSH_REQUEST); + } +#endif + + /* Restore huart->gState and huart->RxState to Ready */ + huart->gState = HAL_UART_STATE_READY; + huart->RxState = HAL_UART_STATE_READY; + + /* Call user Abort complete callback */ + HAL_UART_AbortCpltCallback(huart); +} + + +/** + * @brief DMA UART Rx communication abort callback, when initiated by user + * (To be called at end of DMA Rx Abort procedure following user abort request). + * @note When this callback is executed, User Abort complete call back is called only if no + * Abort still ongoing for Tx DMA Handle. + * @param hdma DMA handle. + * @retval None + */ +static void UART_DMARxAbortCallback(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef* huart = (UART_HandleTypeDef* )(hdma->Parent); + + huart->hdmarx->XferAbortCallback = NULL; + + /* Check if an Abort process is still ongoing */ + if(huart->hdmatx != NULL) + { + if(huart->hdmatx->XferAbortCallback != NULL) + { + return; + } + } + + /* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */ + huart->TxXferCount = 0U; + huart->RxXferCount = 0U; + + /* Reset errorCode */ + huart->ErrorCode = HAL_UART_ERROR_NONE; + + /* Clear the Error flags in the ICR register */ + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_PEF | UART_CLEAR_FEF); + + /* Discard the received data */ + __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST); + + /* Restore huart->gState and huart->RxState to Ready */ + huart->gState = HAL_UART_STATE_READY; + huart->RxState = HAL_UART_STATE_READY; + + /* Call user Abort complete callback */ + HAL_UART_AbortCpltCallback(huart); +} + + +/** + * @brief DMA UART Tx communication abort callback, when initiated by user by a call to + * HAL_UART_AbortTransmit_IT API (Abort only Tx transfer) + * (This callback is executed at end of DMA Tx Abort procedure following user abort request, + * and leads to user Tx Abort Complete callback execution). + * @param hdma DMA handle. + * @retval None + */ +static void UART_DMATxOnlyAbortCallback(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef* huart = (UART_HandleTypeDef*)(hdma->Parent); + + huart->TxXferCount = 0U; + +#if defined(USART_CR1_FIFOEN) + /* Flush the whole TX FIFO (if needed) */ + if (huart->FifoMode == UART_FIFOMODE_ENABLE) + { + __HAL_UART_SEND_REQ(huart, UART_TXDATA_FLUSH_REQUEST); + } +#endif + + /* Restore huart->gState to Ready */ + huart->gState = HAL_UART_STATE_READY; + + /* Call user Abort complete callback */ + HAL_UART_AbortTransmitCpltCallback(huart); +} + +/** + * @brief DMA UART Rx communication abort callback, when initiated by user by a call to + * HAL_UART_AbortReceive_IT API (Abort only Rx transfer) + * (This callback is executed at end of DMA Rx Abort procedure following user abort request, + * and leads to user Rx Abort Complete callback execution). + * @param hdma DMA handle. + * @retval None + */ +static void UART_DMARxOnlyAbortCallback(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef* huart = ( UART_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; + + huart->RxXferCount = 0U; + + /* Clear the Error flags in the ICR register */ + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_PEF | UART_CLEAR_FEF); + + /* Discard the received data */ + __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST); + + /* Restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + + /* Call user Abort complete callback */ + HAL_UART_AbortReceiveCpltCallback(huart); +} + +/** + * @brief TX interrrupt handler for 7 or 8 bits data word length . + * @note Function is called under interruption only, once + * interruptions have been enabled by HAL_UART_Transmit_IT(). + * @param huart UART handle. + * @retval None + */ +static void UART_TxISR_8BIT(UART_HandleTypeDef *huart) +{ + /* Check that a Tx process is ongoing */ + if (huart->gState == HAL_UART_STATE_BUSY_TX) + { + if(huart->TxXferCount == 0) + { + /* Disable the UART Transmit Data Register Empty Interrupt */ +#if defined(USART_CR1_FIFOEN) + CLEAR_BIT(huart->Instance->CR1, USART_CR1_TXEIE_TXFNFIE); +#else + CLEAR_BIT(huart->Instance->CR1, USART_CR1_TXEIE); +#endif + + /* Enable the UART Transmit Complete Interrupt */ + SET_BIT(huart->Instance->CR1, USART_CR1_TCIE); + } + else + { + huart->Instance->TDR = (uint8_t)(*huart->pTxBuffPtr++ & (uint8_t)0xFF); + huart->TxXferCount--; + } + } +} + +/** + * @brief TX interrrupt handler for 9 bits data word length. + * @note Function is called under interruption only, once + * interruptions have been enabled by HAL_UART_Transmit_IT(). + * @param huart UART handle. + * @retval None + */ +static void UART_TxISR_16BIT(UART_HandleTypeDef *huart) +{ + uint16_t* tmp; + + /* Check that a Tx process is ongoing */ + if (huart->gState == HAL_UART_STATE_BUSY_TX) + { + if(huart->TxXferCount == 0) + { + /* Disable the UART Transmit Data Register Empty Interrupt */ +#if defined(USART_CR1_FIFOEN) + CLEAR_BIT(huart->Instance->CR1, USART_CR1_TXEIE_TXFNFIE); +#else + CLEAR_BIT(huart->Instance->CR1, USART_CR1_TXEIE); +#endif + + /* Enable the UART Transmit Complete Interrupt */ + SET_BIT(huart->Instance->CR1, USART_CR1_TCIE); + } + else + { + tmp = (uint16_t*) huart->pTxBuffPtr; + huart->Instance->TDR = (*tmp & (uint16_t)0x01FF); + huart->pTxBuffPtr += 2; + huart->TxXferCount--; + } + } +} + +#if defined(USART_CR1_FIFOEN) +/** + * @brief TX interrrupt handler for 7 or 8 bits data word length and FIFO mode is enabled. + * @note Function is called under interruption only, once + * interruptions have been enabled by HAL_UART_Transmit_IT(). + * @param huart UART handle. + * @retval None + */ +static void UART_TxISR_8BIT_FIFOEN(UART_HandleTypeDef *huart) +{ + uint8_t nb_tx_data; + + /* Check that a Tx process is ongoing */ + if (huart->gState == HAL_UART_STATE_BUSY_TX) + { + for(nb_tx_data = huart->NbTxDataToProcess ; nb_tx_data > 0 ; nb_tx_data--) + { + if(huart->TxXferCount == 0U) + { + /* Disable the TX FIFO threshold interrupt */ + CLEAR_BIT(huart->Instance->CR3, USART_CR3_TXFTIE); + + /* Enable the UART Transmit Complete Interrupt */ + SET_BIT(huart->Instance->CR1, USART_CR1_TCIE); + + break; /* force exit loop */ + } + else if (READ_BIT(huart->Instance->ISR, USART_ISR_TXE_TXFNF) != RESET) + { + huart->Instance->TDR = (uint8_t)(*huart->pTxBuffPtr++ & (uint8_t)0xFF); + huart->TxXferCount--; + } + } + } +} + +/** + * @brief TX interrrupt handler for 9 bits data word length and FIFO mode is enabled. + * @note Function is called under interruption only, once + * interruptions have been enabled by HAL_UART_Transmit_IT(). + * @param huart UART handle. + * @retval None + */ +static void UART_TxISR_16BIT_FIFOEN(UART_HandleTypeDef *huart) +{ + uint16_t* tmp; + uint8_t nb_tx_data; + + /* Check that a Tx process is ongoing */ + if (huart->gState == HAL_UART_STATE_BUSY_TX) + { + for(nb_tx_data = huart->NbTxDataToProcess ; nb_tx_data > 0 ; nb_tx_data--) + { + if(huart->TxXferCount == 0U) + { + /* Disable the TX FIFO threshold interrupt */ + CLEAR_BIT(huart->Instance->CR3, USART_CR3_TXFTIE); + + /* Enable the UART Transmit Complete Interrupt */ + SET_BIT(huart->Instance->CR1, USART_CR1_TCIE); + + break; /* force exit loop */ + } + else if (READ_BIT(huart->Instance->ISR, USART_ISR_TXE_TXFNF) != RESET) + { + tmp = (uint16_t*) huart->pTxBuffPtr; + huart->Instance->TDR = (*tmp & (uint16_t)0x01FFU); + huart->pTxBuffPtr += 2U; + huart->TxXferCount--; + } + } + } +} +#endif + +/** + * @brief Wrap up transmission in non-blocking mode. + * @param huart pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval None + */ +static void UART_EndTransmit_IT(UART_HandleTypeDef *huart) +{ + /* Disable the UART Transmit Complete Interrupt */ + CLEAR_BIT(huart->Instance->CR1, USART_CR1_TCIE); + + /* Tx process is ended, restore huart->gState to Ready */ + huart->gState = HAL_UART_STATE_READY; + + /* Cleat TxISR function pointer */ + huart->TxISR = NULL; + + HAL_UART_TxCpltCallback(huart); +} + +/** + * @brief RX interrrupt handler for 7 or 8 bits data word length . + * @param huart UART handle. + * @retval None + */ +static void UART_RxISR_8BIT(UART_HandleTypeDef *huart) +{ + uint16_t uhMask = huart->Mask; + uint16_t uhdata; + + /* Check that a Rx process is ongoing */ + if(huart->RxState == HAL_UART_STATE_BUSY_RX) + { + uhdata = (uint16_t) READ_REG(huart->Instance->RDR); + *huart->pRxBuffPtr++ = (uint8_t)(uhdata & (uint8_t)uhMask); + + if(--huart->RxXferCount == 0) + { + /* Disable the UART Parity Error Interrupt and RXNE interrupt*/ +#if defined(USART_CR1_FIFOEN) + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE)); +#else + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE)); +#endif + + /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */ + CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Rx process is completed, restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + + /* Clear RxISR function pointer */ + huart->RxISR = NULL; + + HAL_UART_RxCpltCallback(huart); + } + } + else + { + /* Clear RXNE interrupt flag */ + __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST); + } +} + +/** + * @brief RX interrrupt handler for 9 bits data word length . + * @note Function is called under interruption only, once + * interruptions have been enabled by HAL_UART_Receive_IT() + * @param huart UART handle. + * @retval None + */ +static void UART_RxISR_16BIT(UART_HandleTypeDef *huart) +{ + uint16_t* tmp; + uint16_t uhMask = huart->Mask; + uint16_t uhdata; + + /* Check that a Rx process is ongoing */ + if(huart->RxState == HAL_UART_STATE_BUSY_RX) + { + uhdata = (uint16_t) READ_REG(huart->Instance->RDR); + tmp = (uint16_t*) huart->pRxBuffPtr ; + *tmp = (uint16_t)(uhdata & uhMask); + huart->pRxBuffPtr +=2; + + if(--huart->RxXferCount == 0) + { + /* Disable the UART Parity Error Interrupt and RXNE interrupt*/ +#if defined(USART_CR1_FIFOEN) + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE)); +#else + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE)); +#endif + + /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */ + CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Rx process is completed, restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + + /* Clear RxISR function pointer */ + huart->RxISR = NULL; + + HAL_UART_RxCpltCallback(huart); + } + } + else + { + /* Clear RXNE interrupt flag */ + __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST); + } +} + +#if defined(USART_CR1_FIFOEN) +/** + * @brief RX interrrupt handler for 7 or 8 bits data word length and FIFO mode is enabled. + * @note Function is called under interruption only, once + * interruptions have been enabled by HAL_UART_Receive_IT() + * @param huart UART handle. + * @retval None + */ +static void UART_RxISR_8BIT_FIFOEN(UART_HandleTypeDef *huart) +{ + uint16_t uhMask = huart->Mask; + uint16_t uhdata; + uint8_t nb_rx_data; + + /* Check that a Rx process is ongoing */ + if(huart->RxState == HAL_UART_STATE_BUSY_RX) + { + for(nb_rx_data = huart->NbRxDataToProcess ; nb_rx_data > 0 ; nb_rx_data--) + { + uhdata = (uint16_t) READ_REG(huart->Instance->RDR); + *huart->pRxBuffPtr++ = (uint8_t)(uhdata & (uint8_t)uhMask); + huart->RxXferCount--; + + if(huart->RxXferCount == 0U) + { + /* Disable the UART Parity Error Interrupt and RXFT interrupt*/ + CLEAR_BIT(huart->Instance->CR1, USART_CR1_PEIE); + + /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) and RX FIFO Threshold interrupt */ + CLEAR_BIT(huart->Instance->CR3, (USART_CR3_EIE | USART_CR3_RXFTIE)); + + /* Rx process is completed, restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + + /* Clear RxISR function pointer */ + huart->RxISR = NULL; + + HAL_UART_RxCpltCallback(huart); + } + } + + /* When remaining number of bytes to receive is less than the RX FIFO + threshold, next incoming frames are processed as if FIFO mode was + disabled (i.e. one interrupt per received frame). + */ + if (((huart->RxXferCount != 0U)) && (huart->RxXferCount < huart->NbRxDataToProcess)) + { + /* Disable the UART RXFT interrupt*/ + CLEAR_BIT(huart->Instance->CR3, USART_CR3_RXFTIE); + + /* Update the RxISR function pointer */ + huart->RxISR = UART_RxISR_8BIT; + + /* Enable the UART Data Register Not Empty interrupt */ + SET_BIT(huart->Instance->CR1, USART_CR1_RXNEIE_RXFNEIE); + } + } + else + { + /* Clear RXNE interrupt flag */ + __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST); + } +} + +/** + * @brief RX interrrupt handler for 9 bits data word length and FIFO mode is enabled. + * @note Function is called under interruption only, once + * interruptions have been enabled by HAL_UART_Receive_IT() + * @param huart UART handle. + * @retval None + */ +static void UART_RxISR_16BIT_FIFOEN(UART_HandleTypeDef *huart) +{ + uint16_t* tmp; + uint16_t uhMask = huart->Mask; + uint16_t uhdata; + uint8_t nb_rx_data; + + /* Check that a Rx process is ongoing */ + if(huart->RxState == HAL_UART_STATE_BUSY_RX) + { + for(nb_rx_data = huart->NbRxDataToProcess ; nb_rx_data > 0 ; nb_rx_data--) + { + uhdata = (uint16_t) READ_REG(huart->Instance->RDR); + tmp = (uint16_t*) huart->pRxBuffPtr ; + *tmp = (uint16_t)(uhdata & uhMask); + huart->pRxBuffPtr +=2; + huart->RxXferCount--; + + if(huart->RxXferCount == 0U) + { + /* Disable the UART Parity Error Interrupt and RXFT interrupt*/ + CLEAR_BIT(huart->Instance->CR1, USART_CR1_PEIE); + + /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) and RX FIFO Threshold interrupt */ + CLEAR_BIT(huart->Instance->CR3, (USART_CR3_EIE | USART_CR3_RXFTIE)); + + /* Rx process is completed, restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + + /* Clear RxISR function pointer */ + huart->RxISR = NULL; + + HAL_UART_RxCpltCallback(huart); + } + } + + /* When remaining number of bytes to receive is less than the RX FIFO + threshold, next incoming frames are processed as if FIFO mode was + disabled (i.e. one interrupt per received frame). + */ + if (((huart->RxXferCount != 0U)) && (huart->RxXferCount < huart->NbRxDataToProcess)) + { + /* Disable the UART RXFT interrupt*/ + CLEAR_BIT(huart->Instance->CR3, USART_CR3_RXFTIE); + + /* Update the RxISR function pointer */ + huart->RxISR = UART_RxISR_16BIT; + + /* Enable the UART Data Register Not Empty interrupt */ + SET_BIT(huart->Instance->CR1, USART_CR1_RXNEIE_RXFNEIE); + } + } + else + { + /* Clear RXNE interrupt flag */ + __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST); + } +} +#endif + +/** + * @} + */ + +#endif /* HAL_UART_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_uart_ex.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_uart_ex.c new file mode 100644 index 0000000..c8c80f5 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_uart_ex.c @@ -0,0 +1,900 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_uart_ex.c + * @author MCD Application Team + * @brief Extended UART HAL module driver. + * This file provides firmware functions to manage the following extended + * functionalities of the Universal Asynchronous Receiver Transmitter Peripheral (UART). + * + Initialization and de-initialization functions + * + Peripheral Control functions + * + * + @verbatim + ============================================================================== + ##### UART peripheral extended features ##### + ============================================================================== + + (#) Declare a UART_HandleTypeDef handle structure. + + (#) For the UART RS485 Driver Enable mode, initialize the UART registers + by calling the HAL_RS485Ex_Init() API. + + (#) FIFO mode enabling/disabling and RX/TX FIFO threshold programming. + + -@- When USART operates in FIFO mode, FIFO mode must be enabled prior + starting RX/TX transfers. Also RX/TX FIFO thresholds must be + configured prior starting RX/TX transfers. + + (#) Slave mode enabling/disabling and NSS pin configuration. + + -@- When USART operates in Slave mode, Slave mode must be enabled prior + starting RX/TX transfers. + + @endverbatim + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup UARTEx UARTEx + * @brief UART Extended HAL module driver + * @{ + */ + +#ifdef HAL_UART_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/** @defgroup UARTEx_Private_Functions UARTEx Private Functions + * @{ + */ +static void UARTEx_Wakeup_AddressConfig(UART_HandleTypeDef *huart, UART_WakeUpTypeDef WakeUpSelection); +#if defined(USART_CR1_FIFOEN) +static void UARTEx_SetNbDataToProcess(UART_HandleTypeDef *huart); +#endif +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup UARTEx_Exported_Functions UARTEx Exported Functions + * @{ + */ + +/** @defgroup UARTEx_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Extended Initialization and Configuration Functions + * +@verbatim +=============================================================================== + ##### Initialization and Configuration functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to initialize the USARTx or the UARTy + in asynchronous mode. + (+) For the asynchronous mode the parameters below can be configured: + (++) Baud Rate + (++) Word Length + (++) Stop Bit + (++) Parity: If the parity is enabled, then the MSB bit of the data written + in the data register is transmitted but is changed by the parity bit. + (++) Hardware flow control + (++) Receiver/transmitter modes + (++) Over Sampling Method + (++) One-Bit Sampling Method + (+) For the asynchronous mode, the following advanced features can be configured as well: + (++) TX and/or RX pin level inversion + (++) data logical level inversion + (++) RX and TX pins swap + (++) RX overrun detection disabling + (++) DMA disabling on RX error + (++) MSB first on communication line + (++) auto Baud rate detection + [..] + The HAL_RS485Ex_Init() API follows the UART RS485 mode configuration + procedures (details for the procedures are available in reference manual). + +@endverbatim + + Depending on the frame length defined by the M1 and M0 bits (7-bit, + 8-bit or 9-bit), the possible UART formats are listed in the + following table. + + Table 1. UART frame format. + +-----------------------------------------------------------------------+ + | M1 bit | M0 bit | PCE bit | UART frame | + |---------|---------|-----------|---------------------------------------| + | 0 | 0 | 0 | | SB | 8 bit data | STB | | + |---------|---------|-----------|---------------------------------------| + | 0 | 0 | 1 | | SB | 7 bit data | PB | STB | | + |---------|---------|-----------|---------------------------------------| + | 0 | 1 | 0 | | SB | 9 bit data | STB | | + |---------|---------|-----------|---------------------------------------| + | 0 | 1 | 1 | | SB | 8 bit data | PB | STB | | + |---------|---------|-----------|---------------------------------------| + | 1 | 0 | 0 | | SB | 7 bit data | STB | | + |---------|---------|-----------|---------------------------------------| + | 1 | 0 | 1 | | SB | 6 bit data | PB | STB | | + +-----------------------------------------------------------------------+ + + * @{ + */ + +/** + * @brief Initialize the RS485 Driver enable feature according to the specified + * parameters in the UART_InitTypeDef and creates the associated handle. + * @param huart UART handle. + * @param Polarity Select the driver enable polarity. + * This parameter can be one of the following values: + * @arg @ref UART_DE_POLARITY_HIGH DE signal is active high + * @arg @ref UART_DE_POLARITY_LOW DE signal is active low + * @param AssertionTime Driver Enable assertion time: + * 5-bit value defining the time between the activation of the DE (Driver Enable) + * signal and the beginning of the start bit. It is expressed in sample time + * units (1/8 or 1/16 bit time, depending on the oversampling rate) + * @param DeassertionTime Driver Enable deassertion time: + * 5-bit value defining the time between the end of the last stop bit, in a + * transmitted message, and the de-activation of the DE (Driver Enable) signal. + * It is expressed in sample time units (1/8 or 1/16 bit time, depending on the + * oversampling rate). + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RS485Ex_Init(UART_HandleTypeDef *huart, uint32_t Polarity, uint32_t AssertionTime, uint32_t DeassertionTime) +{ + uint32_t temp = 0x0; + + /* Check the UART handle allocation */ + if(huart == NULL) + { + return HAL_ERROR; + } + /* Check the Driver Enable UART instance */ + assert_param(IS_UART_DRIVER_ENABLE_INSTANCE(huart->Instance)); + + /* Check the Driver Enable polarity */ + assert_param(IS_UART_DE_POLARITY(Polarity)); + + /* Check the Driver Enable assertion time */ + assert_param(IS_UART_ASSERTIONTIME(AssertionTime)); + + /* Check the Driver Enable deassertion time */ + assert_param(IS_UART_DEASSERTIONTIME(DeassertionTime)); + + if(huart->gState == HAL_UART_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + huart->Lock = HAL_UNLOCKED; + + /* Init the low level hardware : GPIO, CLOCK, CORTEX */ + HAL_UART_MspInit(huart); + } + + huart->gState = HAL_UART_STATE_BUSY; + + /* Disable the Peripheral */ + __HAL_UART_DISABLE(huart); + + /* Set the UART Communication parameters */ + if (UART_SetConfig(huart) == HAL_ERROR) + { + return HAL_ERROR; + } + + if(huart->AdvancedInit.AdvFeatureInit != UART_ADVFEATURE_NO_INIT) + { + UART_AdvFeatureConfig(huart); + } + + /* Enable the Driver Enable mode by setting the DEM bit in the CR3 register */ + SET_BIT(huart->Instance->CR3, USART_CR3_DEM); + + /* Set the Driver Enable polarity */ + MODIFY_REG(huart->Instance->CR3, USART_CR3_DEP, Polarity); + + /* Set the Driver Enable assertion and deassertion times */ + temp = (AssertionTime << UART_CR1_DEAT_ADDRESS_LSB_POS); + temp |= (DeassertionTime << UART_CR1_DEDT_ADDRESS_LSB_POS); + MODIFY_REG(huart->Instance->CR1, (USART_CR1_DEDT|USART_CR1_DEAT), temp); + + /* Enable the Peripheral */ + __HAL_UART_ENABLE(huart); + + /* TEACK and/or REACK to check before moving huart->gState and huart->RxState to Ready */ + return (UART_CheckIdleState(huart)); +} + + +/** + * @} + */ + +/** @defgroup UARTEx_Exported_Functions_Group2 IO operation functions + * @brief Extended functions + * +@verbatim + =============================================================================== + ##### IO operation functions ##### + =============================================================================== + This subsection provides a set of Wakeup and FIFO mode related callback functions. + + (#) Wakeup from Stop mode Callback: + (+) HAL_UARTEx_WakeupCallback() + + (#) TX/RX Fifos Callbacks: + (+) HAL_UARTEx_RxFifoFullCallback() + (+) HAL_UARTEx_TxFifoEmptyCallback() + +@endverbatim + * @{ + */ + +/** + * @brief UART wakeup from Stop mode callback. + * @param huart UART handle. + * @retval None + */ + __weak void HAL_UARTEx_WakeupCallback(UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_UARTEx_WakeupCallback can be implemented in the user file. + */ +} + +#if defined(USART_CR1_FIFOEN) +/** + * @brief UART RX Fifo full callback. + * @param huart UART handle. + * @retval None + */ +__weak void HAL_UARTEx_RxFifoFullCallback (UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_UARTEx_RxFifoFullCallback can be implemented in the user file. + */ +} + +/** + * @brief UART TX Fifo empty callback. + * @param huart UART handle. + * @retval None + */ +__weak void HAL_UARTEx_TxFifoEmptyCallback (UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_UARTEx_TxFifoEmptyCallback can be implemented in the user file. + */ +} +#endif + +/** + * @} + */ + +/** @defgroup UARTEx_Exported_Functions_Group3 Peripheral Control functions + * @brief Extended Peripheral Control functions + * +@verbatim + =============================================================================== + ##### Peripheral Control functions ##### + =============================================================================== + [..] This section provides the following functions: + (+) HAL_UARTEx_EnableClockStopMode() API enables the UART clock (HSI or LSE only) during stop mode + (+) HAL_UARTEx_DisableClockStopMode() API disables the above functionality + (+) HAL_MultiProcessorEx_AddressLength_Set() API optionally sets the UART node address + detection length to more than 4 bits for multiprocessor address mark wake up. + (+) HAL_UARTEx_StopModeWakeUpSourceConfig() API defines the wake-up from stop mode + trigger: address match, Start Bit detection or RXNE bit status. + (+) HAL_UARTEx_EnableStopMode() API enables the UART to wake up the MCU from stop mode + (+) HAL_UARTEx_DisableStopMode() API disables the above functionality + (+) HAL_UARTEx_WakeupCallback() called upon UART wakeup interrupt + (+) HAL_UARTEx_EnableSPISlaveMode() API enables the SPI slave mode + (+) HAL_UARTEx_DisableSPISlaveMode() API disables the SPI slave mode + (+) HAL_UARTEx_ConfigNSS API configures the Slave Select input pin (NSS) + (+) HAL_UARTEx_EnableFifoMode() API enables the FIFO mode + (+) HAL_UARTEx_DisableFifoMode() API disables the FIFO mode + (+) HAL_UARTEx_SetTxFifoThreshold() API sets the TX FIFO threshold + (+) HAL_UARTEx_SetRxFifoThreshold() API sets the RX FIFO threshold + +@endverbatim + * @{ + */ + + + + +/** + * @brief By default in multiprocessor mode, when the wake up method is set + * to address mark, the UART handles only 4-bit long addresses detection; + * this API allows to enable longer addresses detection (6-, 7- or 8-bit + * long). + * @note Addresses detection lengths are: 6-bit address detection in 7-bit data mode, + * 7-bit address detection in 8-bit data mode, 8-bit address detection in 9-bit data mode. + * @param huart UART handle. + * @param AddressLength This parameter can be one of the following values: + * @arg @ref UART_ADDRESS_DETECT_4B 4-bit long address + * @arg @ref UART_ADDRESS_DETECT_7B 6-, 7- or 8-bit long address + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MultiProcessorEx_AddressLength_Set(UART_HandleTypeDef *huart, uint32_t AddressLength) +{ + /* Check the UART handle allocation */ + if(huart == NULL) + { + return HAL_ERROR; + } + + /* Check the address length parameter */ + assert_param(IS_UART_ADDRESSLENGTH_DETECT(AddressLength)); + + huart->gState = HAL_UART_STATE_BUSY; + + /* Disable the Peripheral */ + __HAL_UART_DISABLE(huart); + + /* Set the address length */ + MODIFY_REG(huart->Instance->CR2, USART_CR2_ADDM7, AddressLength); + + /* Enable the Peripheral */ + __HAL_UART_ENABLE(huart); + + /* TEACK and/or REACK to check before moving huart->gState to Ready */ + return (UART_CheckIdleState(huart)); +} + + +/** + * @brief Set Wakeup from Stop mode interrupt flag selection. + * @note It is the application responsibility to enable the interrupt used as + * usart_wkup interrupt source before entering low-power mode. + * @param huart UART handle. + * @param WakeUpSelection Address match, Start Bit detection or RXNE/RXFNE bit status. + * This parameter can be one of the following values: + * @arg @ref UART_WAKEUP_ON_ADDRESS + * @arg @ref UART_WAKEUP_ON_STARTBIT + * @arg @ref UART_WAKEUP_ON_READDATA_NONEMPTY + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UARTEx_StopModeWakeUpSourceConfig(UART_HandleTypeDef *huart, UART_WakeUpTypeDef WakeUpSelection) +{ + HAL_StatusTypeDef status = HAL_OK; + uint32_t tickstart = 0; + + /* check the wake-up from stop mode UART instance */ + assert_param(IS_UART_WAKEUP_FROMSTOP_INSTANCE(huart->Instance)); + /* check the wake-up selection parameter */ + assert_param(IS_UART_WAKEUP_SELECTION(WakeUpSelection.WakeUpEvent)); + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->gState = HAL_UART_STATE_BUSY; + + /* Disable the Peripheral */ + __HAL_UART_DISABLE(huart); + + /* Set the wake-up selection scheme */ + MODIFY_REG(huart->Instance->CR3, USART_CR3_WUS, WakeUpSelection.WakeUpEvent); + + if (WakeUpSelection.WakeUpEvent == UART_WAKEUP_ON_ADDRESS) + { + UARTEx_Wakeup_AddressConfig(huart, WakeUpSelection); + } + + /* Enable the Peripheral */ + __HAL_UART_ENABLE(huart); + + /* Init tickstart for timeout managment*/ + tickstart = HAL_GetTick(); + + /* Wait until REACK flag is set */ + if(UART_WaitOnFlagUntilTimeout(huart, USART_ISR_REACK, RESET, tickstart, HAL_UART_TIMEOUT_VALUE) != HAL_OK) + { + status = HAL_TIMEOUT; + } + else + { + /* Initialize the UART State */ + huart->gState = HAL_UART_STATE_READY; + } + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return status; +} + + +/** + * @brief Enable UART Stop Mode. + * @note The UART is able to wake up the MCU from Stop 1 mode as long as UART clock is HSI or LSE. + * @param huart UART handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UARTEx_EnableStopMode(UART_HandleTypeDef *huart) +{ + /* Process Locked */ + __HAL_LOCK(huart); + + huart->gState = HAL_UART_STATE_BUSY; + + /* Set UESM bit */ + SET_BIT(huart->Instance->CR1, USART_CR1_UESM); + + huart->gState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +/** + * @brief Disable UART Stop Mode. + * @param huart UART handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UARTEx_DisableStopMode(UART_HandleTypeDef *huart) +{ + /* Process Locked */ + __HAL_LOCK(huart); + + huart->gState = HAL_UART_STATE_BUSY; + + /* Clear UESM bit */ + CLEAR_BIT(huart->Instance->CR1, USART_CR1_UESM); + + huart->gState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +#if defined(USART_CR2_SLVEN) +/** + * @brief Enable the SPI slave mode. + * @note When the UART operates in SPI slave mode, it handles data flow using + * the serial interface clock derived from the external SCLK signal + * provided by the external master SPI device. + * @note In SPI slave mode, the UART must be enabled before starting the master + * communications (or between frames while the clock is stable). Otherwise, + * if the UART slave is enabled while the master is in the middle of a + * frame, it will become desynchronized with the master. + * @note The data register of the slave needs to be ready before the first edge + * of the communication clock or before the end of the ongoing communication, + * otherwise the SPI slave will transmit zeros. + * @param huart UART handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UARTEx_EnableSlaveMode(UART_HandleTypeDef *huart) +{ + uint32_t tmpcr1 = 0; + + /* Check parameters */ + assert_param(IS_UART_SPI_SLAVE_INSTANCE(huart->Instance)); + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->gState = HAL_UART_STATE_BUSY; + + /* Save actual UART configuration */ + tmpcr1 = READ_REG(huart->Instance->CR1); + + /* Disable UART */ + __HAL_UART_DISABLE(huart); + + /* In SPI slave mode mode, the following bits must be kept cleared: + - LINEN and CLKEN bit in the USART_CR2 register + - HDSEL, SCEN and IREN bits in the USART_CR3 register.*/ + CLEAR_BIT(huart->Instance->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN)); + CLEAR_BIT(huart->Instance->CR3, (USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN)); + + /* Enable SPI slave mode */ + SET_BIT(huart->Instance->CR2, USART_CR2_SLVEN); + + /* Restore UART configuration */ + WRITE_REG(huart->Instance->CR1, tmpcr1); + + huart->SlaveMode = UART_SLAVEMODE_ENABLE; + + huart->gState = HAL_UART_STATE_READY; + + /* Enable UART */ + __HAL_UART_ENABLE(huart); + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +/** + * @brief Disable the SPI slave mode. + * @param huart UART handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UARTEx_DisableSlaveMode(UART_HandleTypeDef *huart) +{ + uint32_t tmpcr1 = 0; + + /* Check parameters */ + assert_param(IS_UART_SPI_SLAVE_INSTANCE(huart->Instance)); + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->gState = HAL_UART_STATE_BUSY; + + /* Save actual UART configuration */ + tmpcr1 = READ_REG(huart->Instance->CR1); + + /* Disable UART */ + __HAL_UART_DISABLE(huart); + + /* Disable SPI slave mode */ + CLEAR_BIT(huart->Instance->CR2, USART_CR2_SLVEN); + + /* Restore UART configuration */ + WRITE_REG(huart->Instance->CR1, tmpcr1); + + huart->SlaveMode = UART_SLAVEMODE_ENABLE; + + huart->gState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +/** + * @brief Configure the Slave Select input pin (NSS). + * @note Software NSS management: SPI slave will always be selected and NSS + * input pin will be ignored. + * @note Hardware NSS management: the SPI slave selection depends on NSS + * input pin. The slave is selected when NSS is low and deselected when + * NSS is high. + * @param huart UART handle. + * @param NSSConfig NSS configuration. + * This parameter can be one of the following values: + * @arg @ref UART_NSS_HARD + * @arg @ref UART_NSS_SOFT + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UARTEx_ConfigNSS(UART_HandleTypeDef *huart, uint32_t NSSConfig) +{ + uint32_t tmpcr1 = 0; + + /* Check parameters */ + assert_param(IS_UART_SPI_SLAVE_INSTANCE(huart->Instance)); + assert_param(IS_UART_NSS(NSSConfig)); + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->gState = HAL_UART_STATE_BUSY; + + /* Save actual UART configuration */ + tmpcr1 = READ_REG(huart->Instance->CR1); + + /* Disable UART */ + __HAL_UART_DISABLE(huart); + + /* Program DIS_NSS bit in the USART_CR2 register */ + MODIFY_REG(huart->Instance->CR2, USART_CR2_DIS_NSS, NSSConfig); + + /* Restore UART configuration */ + WRITE_REG(huart->Instance->CR1, tmpcr1); + + huart->gState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} +#endif + +#if defined(USART_CR1_FIFOEN) +/** + * @brief Enable the FIFO mode. + * @param huart UART handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UARTEx_EnableFifoMode(UART_HandleTypeDef *huart) +{ + uint32_t tmpcr1 = 0; + + /* Check parameters */ + assert_param(IS_UART_FIFO_INSTANCE(huart->Instance)); + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->gState = HAL_UART_STATE_BUSY; + + /* Save actual UART configuration */ + tmpcr1 = READ_REG(huart->Instance->CR1); + + /* Disable UART */ + __HAL_UART_DISABLE(huart); + + /* Enable FIFO mode */ + SET_BIT(tmpcr1, USART_CR1_FIFOEN); + huart->FifoMode = UART_FIFOMODE_ENABLE; + + /* Restore UART configuration */ + WRITE_REG(huart->Instance->CR1, tmpcr1); + + /* Determine the number of data to process during RX/TX ISR execution */ + UARTEx_SetNbDataToProcess(huart); + + huart->gState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +/** + * @brief Disable the FIFO mode. + * @param huart UART handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UARTEx_DisableFifoMode(UART_HandleTypeDef *huart) +{ + uint32_t tmpcr1 = 0; + + /* Check parameters */ + assert_param(IS_UART_FIFO_INSTANCE(huart->Instance)); + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->gState = HAL_UART_STATE_BUSY; + + /* Save actual UART configuration */ + tmpcr1 = READ_REG(huart->Instance->CR1); + + /* Disable UART */ + __HAL_UART_DISABLE(huart); + + /* Enable FIFO mode */ + CLEAR_BIT(tmpcr1, USART_CR1_FIFOEN); + huart->FifoMode = UART_FIFOMODE_DISABLE; + + /* Restore UART configuration */ + WRITE_REG(huart->Instance->CR1, tmpcr1); + + huart->gState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +/** + * @brief Set the TXFIFO threshold. + * @param huart UART handle. + * @param Threshold TX FIFO threshold value + * This parameter can be one of the following values: + * @arg @ref UART_TXFIFO_THRESHOLD_1_8 + * @arg @ref UART_TXFIFO_THRESHOLD_1_4 + * @arg @ref UART_TXFIFO_THRESHOLD_1_2 + * @arg @ref UART_TXFIFO_THRESHOLD_3_4 + * @arg @ref UART_TXFIFO_THRESHOLD_7_8 + * @arg @ref UART_TXFIFO_THRESHOLD_8_8 + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UARTEx_SetTxFifoThreshold(UART_HandleTypeDef *huart, uint32_t Threshold) +{ + uint32_t tmpcr1 = 0; + + /* Check parameters */ + assert_param(IS_UART_FIFO_INSTANCE(huart->Instance)); + assert_param(IS_UART_TXFIFO_THRESHOLD(Threshold)); + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->gState = HAL_UART_STATE_BUSY; + + /* Save actual UART configuration */ + tmpcr1 = READ_REG(huart->Instance->CR1); + + /* Disable UART */ + __HAL_UART_DISABLE(huart); + + /* Update TX threshold configuration */ + MODIFY_REG(huart->Instance->CR3, USART_CR3_TXFTCFG, Threshold); + + /* Determine the number of data to process during RX/TX ISR execution */ + UARTEx_SetNbDataToProcess(huart); + + /* Restore UART configuration */ + WRITE_REG(huart->Instance->CR1, tmpcr1); + + huart->gState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +/** + * @brief Set the RXFIFO threshold. + * @param huart UART handle. + * @param Threshold RX FIFO threshold value + * This parameter can be one of the following values: + * @arg @ref UART_RXFIFO_THRESHOLD_1_8 + * @arg @ref UART_RXFIFO_THRESHOLD_1_4 + * @arg @ref UART_RXFIFO_THRESHOLD_1_2 + * @arg @ref UART_RXFIFO_THRESHOLD_3_4 + * @arg @ref UART_RXFIFO_THRESHOLD_7_8 + * @arg @ref UART_RXFIFO_THRESHOLD_8_8 + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UARTEx_SetRxFifoThreshold(UART_HandleTypeDef *huart, uint32_t Threshold) +{ + uint32_t tmpcr1 = 0; + + /* Check the parameters */ + assert_param(IS_UART_FIFO_INSTANCE(huart->Instance)); + assert_param(IS_UART_RXFIFO_THRESHOLD(Threshold)); + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->gState = HAL_UART_STATE_BUSY; + + /* Save actual UART configuration */ + tmpcr1 = READ_REG(huart->Instance->CR1); + + /* Disable UART */ + __HAL_UART_DISABLE(huart); + + /* Update RX threshold configuration */ + MODIFY_REG(huart->Instance->CR3, USART_CR3_RXFTCFG, Threshold); + + /* Determine the number of data to process during RX/TX ISR execution */ + UARTEx_SetNbDataToProcess(huart); + + /* Restore UART configuration */ + WRITE_REG(huart->Instance->CR1, tmpcr1); + + huart->gState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} +#endif + +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup UARTEx_Private_Functions + * @{ + */ + +/** + * @brief Initialize the UART wake-up from stop mode parameters when triggered by address detection. + * @param huart UART handle. + * @param WakeUpSelection UART wake up from stop mode parameters. + * @retval None + */ +static void UARTEx_Wakeup_AddressConfig(UART_HandleTypeDef *huart, UART_WakeUpTypeDef WakeUpSelection) +{ + assert_param(IS_UART_ADDRESSLENGTH_DETECT(WakeUpSelection.AddressLength)); + + /* Set the USART address length */ + MODIFY_REG(huart->Instance->CR2, USART_CR2_ADDM7, WakeUpSelection.AddressLength); + + /* Set the USART address node */ + MODIFY_REG(huart->Instance->CR2, USART_CR2_ADD, ((uint32_t)WakeUpSelection.Address << UART_CR2_ADDRESS_LSB_POS)); +} + +#if defined(USART_CR1_FIFOEN) +/** + * @brief Calculate the number of data to process in RX/TX ISR. + * @note The RX FIFO depth and the TX FIFO depth is extracted from + * the UART configuration registers. + * @param huart UART handle. + * @retval None + */ +void UARTEx_SetNbDataToProcess(UART_HandleTypeDef *huart) +{ + uint8_t rx_fifo_depth; + uint8_t tx_fifo_depth; + uint8_t rx_fifo_threshold; + uint8_t tx_fifo_threshold; + uint8_t numerator[] = {1, 1, 1, 3, 7, 1}; + uint8_t denominator[] = {8, 4, 2, 4, 8, 1}; + + if (huart->FifoMode == UART_FIFOMODE_DISABLE) + { + huart->NbTxDataToProcess = 1; + huart->NbRxDataToProcess = 1; + } + else + { + rx_fifo_depth = 8; /* RX Fifo size */ + tx_fifo_depth = 8; /* TX Fifo size */ + rx_fifo_threshold = (uint8_t)(READ_BIT(huart->Instance->CR3, USART_CR3_RXFTCFG) >> USART_CR3_RXFTCFG_Pos); + tx_fifo_threshold = (uint8_t)(READ_BIT(huart->Instance->CR3, USART_CR3_TXFTCFG) >> USART_CR3_TXFTCFG_Pos); + huart->NbTxDataToProcess = (uint8_t)(tx_fifo_depth * numerator[tx_fifo_threshold])/denominator[tx_fifo_threshold]; + huart->NbRxDataToProcess = (uint8_t)(rx_fifo_depth * numerator[rx_fifo_threshold])/denominator[rx_fifo_threshold]; + } +} +#endif + +/** + * @} + */ + +#endif /* HAL_UART_MODULE_ENABLED */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_usb.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_usb.c new file mode 100644 index 0000000..875c0c5 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_usb.c @@ -0,0 +1,2397 @@ +/** + ****************************************************************************** + * @file stm32l4xx_ll_usb.c + * @author MCD Application Team + * @brief USB Low Layer HAL module driver. + * + * This file provides firmware functions to manage the following + * functionalities of the USB Peripheral Controller: + * + Initialization/de-initialization functions + * + I/O operation functions + * + Peripheral Control functions + * + Peripheral State functions + * + @verbatim + ============================================================================== + ##### How to use this driver ##### + ============================================================================== + [..] + (#) Fill parameters of Init structure in USB_OTG_CfgTypeDef structure. + + (#) Call USB_CoreInit() API to initialize the USB Core peripheral. + + (#) The upper HAL HCD/PCD driver will call the right routines for its internal processes. + + @endverbatim + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @defgroup USB_LL USB Low Layer + * @brief Low layer module for USB_FS and USB_OTG_FS drivers + * @{ + */ +#if defined (HAL_PCD_MODULE_ENABLED) || defined (HAL_HCD_MODULE_ENABLED) + +#if defined(STM32L432xx) || defined(STM32L433xx) || defined(STM32L442xx) || defined(STM32L443xx) || \ + defined(STM32L452xx) || defined(STM32L462xx) || \ + defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || \ + defined(STM32L496xx) || defined(STM32L4A6xx) || \ + defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + +/** @addtogroup STM32L4xx_LL_USB_DRIVER + * @{ + */ + + + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ +#if defined (USB_OTG_FS) +/** @defgroup USB_LL_Private_Functions USB Low Layer Private Functions + * @{ + */ +static HAL_StatusTypeDef USB_CoreReset(USB_OTG_GlobalTypeDef *USBx); +/** + * @} + */ +#endif /* USB_OTG_FS */ +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup LL_USB_Exported_Functions USB Low Layer Exported Functions + * @{ + */ + +/** @defgroup LL_USB_Group1 Initialization/de-initialization functions + * @brief Initialization and Configuration functions + * +@verbatim + =============================================================================== + ##### Initialization/de-initialization functions ##### + =============================================================================== + [..] This section provides functions allowing to: + +@endverbatim + * @{ + */ +/*============================================================================== + USB OTG FS peripheral available on STM32L475xx, STM32L476xx, STM32L485xx and + STM32L486xx devices +==============================================================================*/ +#if defined (USB_OTG_FS) +/** + * @brief Initializes the USB Core + * @param USBx: USB Instance + * @param cfg: pointer to a USB_OTG_CfgTypeDef structure that contains + * the configuration information for the specified USBx peripheral. + * @retval HAL status + */ +HAL_StatusTypeDef USB_CoreInit(USB_OTG_GlobalTypeDef *USBx, USB_OTG_CfgTypeDef cfg) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(cfg); + + /* Select FS Embedded PHY */ + USBx->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL; + + /* Reset after a PHY select and set Host mode */ + USB_CoreReset(USBx); + + /* Deactivate the power down*/ + USBx->GCCFG = USB_OTG_GCCFG_PWRDWN; + + return HAL_OK; +} + +/** + * @brief USB_EnableGlobalInt + * Enables the controller's Global Int in the AHB Config reg + * @param USBx: Selected device + * @retval HAL status + */ +HAL_StatusTypeDef USB_EnableGlobalInt(USB_OTG_GlobalTypeDef *USBx) +{ + USBx->GAHBCFG |= USB_OTG_GAHBCFG_GINT; + return HAL_OK; +} + + +/** + * @brief USB_DisableGlobalInt + * Disable the controller's Global Int in the AHB Config reg + * @param USBx: Selected device + * @retval HAL status +*/ +HAL_StatusTypeDef USB_DisableGlobalInt(USB_OTG_GlobalTypeDef *USBx) +{ + USBx->GAHBCFG &= ~USB_OTG_GAHBCFG_GINT; + return HAL_OK; +} + +/** + * @brief USB_SetCurrentMode : Set functional mode + * @param USBx: Selected device + * @param mode: current core mode + * This parameter can be one of these values: + * @arg USB_OTG_DEVICE_MODE: Peripheral mode + * @arg USB_OTG_HOST_MODE: Host mode + * @arg USB_OTG_DRD_MODE: Dual Role Device mode + * @retval HAL status + */ +HAL_StatusTypeDef USB_SetCurrentMode(USB_OTG_GlobalTypeDef *USBx , USB_ModeTypeDef mode) +{ + USBx->GUSBCFG &= ~(USB_OTG_GUSBCFG_FHMOD | USB_OTG_GUSBCFG_FDMOD); + + if ( mode == USB_HOST_MODE) + { + USBx->GUSBCFG |= USB_OTG_GUSBCFG_FHMOD; + } + else if ( mode == USB_DEVICE_MODE) + { + USBx->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD; + } + HAL_Delay(50); + + return HAL_OK; +} + +/** + * @brief USB_DevInit : Initializes the USB_OTG controller registers + * for device mode + * @param USBx: Selected device + * @param cfg: pointer to a USB_OTG_CfgTypeDef structure that contains + * the configuration information for the specified USBx peripheral. + * @retval HAL status + */ +HAL_StatusTypeDef USB_DevInit (USB_OTG_GlobalTypeDef *USBx, USB_OTG_CfgTypeDef cfg) +{ + uint32_t index = 0; + + /*Activate VBUS Sensing B */ + USBx->GCCFG |= USB_OTG_GCCFG_VBDEN; + + if (cfg.vbus_sensing_enable == 0) + { + /* Deactivate VBUS Sensing B */ + USBx->GCCFG &= ~ USB_OTG_GCCFG_VBDEN; + + /* B-peripheral session valid override enable*/ + USBx->GOTGCTL |= USB_OTG_GOTGCTL_BVALOEN; + USBx->GOTGCTL |= USB_OTG_GOTGCTL_BVALOVAL; + } + + /* Restart the Phy Clock */ + USBx_PCGCCTL = 0; + + /* Device mode configuration */ + USBx_DEVICE->DCFG |= DCFG_FRAME_INTERVAL_80; + + /* Set Full speed phy */ + USB_SetDevSpeed (USBx , USB_OTG_SPEED_FULL); + + /* Flush the FIFOs */ + USB_FlushTxFifo(USBx , 0x10); /* all Tx FIFOs */ + USB_FlushRxFifo(USBx); + + /* Clear all pending Device Interrupts */ + USBx_DEVICE->DIEPMSK = 0; + USBx_DEVICE->DOEPMSK = 0; + USBx_DEVICE->DAINT = 0xFFFFFFFF; + USBx_DEVICE->DAINTMSK = 0; + + for (index = 0; index < cfg.dev_endpoints; index++) + { + if ((USBx_INEP(index)->DIEPCTL & USB_OTG_DIEPCTL_EPENA) == USB_OTG_DIEPCTL_EPENA) + { + USBx_INEP(index)->DIEPCTL = (USB_OTG_DIEPCTL_EPDIS | USB_OTG_DIEPCTL_SNAK); + } + else + { + USBx_INEP(index)->DIEPCTL = 0; + } + + USBx_INEP(index)->DIEPTSIZ = 0; + USBx_INEP(index)->DIEPINT = 0xFF; + } + + for (index = 0; index < cfg.dev_endpoints; index++) + { + if ((USBx_OUTEP(index)->DOEPCTL & USB_OTG_DOEPCTL_EPENA) == USB_OTG_DOEPCTL_EPENA) + { + USBx_OUTEP(index)->DOEPCTL = (USB_OTG_DOEPCTL_EPDIS | USB_OTG_DOEPCTL_SNAK); + } + else + { + USBx_OUTEP(index)->DOEPCTL = 0; + } + + USBx_OUTEP(index)->DOEPTSIZ = 0; + USBx_OUTEP(index)->DOEPINT = 0xFF; + } + + USBx_DEVICE->DIEPMSK &= ~(USB_OTG_DIEPMSK_TXFURM); + + if (cfg.dma_enable == 1) + { + /*Set threshold parameters */ + USBx_DEVICE->DTHRCTL = (USB_OTG_DTHRCTL_TXTHRLEN_6 | USB_OTG_DTHRCTL_RXTHRLEN_6); + USBx_DEVICE->DTHRCTL |= (USB_OTG_DTHRCTL_RXTHREN | USB_OTG_DTHRCTL_ISOTHREN | USB_OTG_DTHRCTL_NONISOTHREN); + + index= USBx_DEVICE->DTHRCTL; + } + + /* Disable all interrupts. */ + USBx->GINTMSK = 0; + + /* Clear any pending interrupts */ + USBx->GINTSTS = 0xBFFFFFFF; + + /* Enable the common interrupts */ + if (cfg.dma_enable == DISABLE) + { + USBx->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM; + } + + /* Enable interrupts matching to the Device mode ONLY */ + USBx->GINTMSK |= (USB_OTG_GINTMSK_USBSUSPM | USB_OTG_GINTMSK_USBRST |\ + USB_OTG_GINTMSK_ENUMDNEM | USB_OTG_GINTMSK_IEPINT |\ + USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IISOIXFRM|\ + USB_OTG_GINTMSK_PXFRM_IISOOXFRM | USB_OTG_GINTMSK_WUIM); + + if(cfg.Sof_enable) + { + USBx->GINTMSK |= USB_OTG_GINTMSK_SOFM; + } + + if (cfg.vbus_sensing_enable == ENABLE) + { + USBx->GINTMSK |= (USB_OTG_GINTMSK_SRQIM | USB_OTG_GINTMSK_OTGINT); + } + + return HAL_OK; +} + + +/** + * @brief USB_OTG_FlushTxFifo : Flush a Tx FIFO + * @param USBx: Selected device + * @param num: FIFO number + * This parameter can be a value from 1 to 15 + 15 means Flush all Tx FIFOs + * @retval HAL status + */ +HAL_StatusTypeDef USB_FlushTxFifo (USB_OTG_GlobalTypeDef *USBx, uint32_t num) +{ + uint32_t count = 0; + + USBx->GRSTCTL = ( USB_OTG_GRSTCTL_TXFFLSH |(uint32_t)( num << 6)); + + do + { + if (++count > 200000) + { + return HAL_TIMEOUT; + } + } + while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_TXFFLSH) == USB_OTG_GRSTCTL_TXFFLSH); + + return HAL_OK; +} + + +/** + * @brief USB_FlushRxFifo : Flush Rx FIFO + * @param USBx: Selected device + * @retval HAL status + */ +HAL_StatusTypeDef USB_FlushRxFifo(USB_OTG_GlobalTypeDef *USBx) +{ + uint32_t count = 0; + + USBx->GRSTCTL = USB_OTG_GRSTCTL_RXFFLSH; + + do + { + if (++count > 200000) + { + return HAL_TIMEOUT; + } + } + while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_RXFFLSH) == USB_OTG_GRSTCTL_RXFFLSH); + + return HAL_OK; +} + +/** + * @brief USB_SetDevSpeed :Initializes the DevSpd field of DCFG register + * depending the PHY type and the enumeration speed of the device. + * @param USBx: Selected device + * @param speed: device speed + * This parameter can be one of these values: + * @arg USB_OTG_SPEED_HIGH: High speed mode + * @arg USB_OTG_SPEED_HIGH_IN_FULL: High speed core in Full Speed mode + * @arg USB_OTG_SPEED_FULL: Full speed mode + * @arg USB_OTG_SPEED_LOW: Low speed mode + * @retval Hal status + */ +HAL_StatusTypeDef USB_SetDevSpeed(USB_OTG_GlobalTypeDef *USBx , uint8_t speed) +{ + USBx_DEVICE->DCFG |= speed; + return HAL_OK; +} + +/** + * @brief USB_GetDevSpeed :Return the Dev Speed + * @param USBx: Selected device + * @retval speed : device speed + * This parameter can be one of these values: + * @arg USB_OTG_SPEED_HIGH: High speed mode + * @arg USB_OTG_SPEED_FULL: Full speed mode + * @arg USB_OTG_SPEED_LOW: Low speed mode + */ +uint8_t USB_GetDevSpeed(USB_OTG_GlobalTypeDef *USBx) +{ + uint8_t speed = 0; + + if((USBx_DEVICE->DSTS & USB_OTG_DSTS_ENUMSPD) == DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ) + { + speed = USB_OTG_SPEED_HIGH; + } + else if (((USBx_DEVICE->DSTS & USB_OTG_DSTS_ENUMSPD) == DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ)|| + ((USBx_DEVICE->DSTS & USB_OTG_DSTS_ENUMSPD) == DSTS_ENUMSPD_FS_PHY_48MHZ)) + { + speed = USB_OTG_SPEED_FULL; + } + else if((USBx_DEVICE->DSTS & USB_OTG_DSTS_ENUMSPD) == DSTS_ENUMSPD_LS_PHY_6MHZ) + { + speed = USB_OTG_SPEED_LOW; + } + + return speed; +} + +/** + * @brief Activate and configure an endpoint + * @param USBx: Selected device + * @param ep: pointer to endpoint structure + * @retval HAL status + */ +HAL_StatusTypeDef USB_ActivateEndpoint(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep) +{ + if (ep->is_in == 1) + { + USBx_DEVICE->DAINTMSK |= USB_OTG_DAINTMSK_IEPM & ((1 << (ep->num))); + + if (((USBx_INEP(ep->num)->DIEPCTL) & USB_OTG_DIEPCTL_USBAEP) == 0) + { + USBx_INEP(ep->num)->DIEPCTL |= ((ep->maxpacket & USB_OTG_DIEPCTL_MPSIZ ) | (ep->type << 18 ) |\ + ((ep->num) << 22 ) | (USB_OTG_DIEPCTL_SD0PID_SEVNFRM) | (USB_OTG_DIEPCTL_USBAEP)); + } + + } + else + { + USBx_DEVICE->DAINTMSK |= USB_OTG_DAINTMSK_OEPM & ((1 << (ep->num)) << 16); + + if (((USBx_OUTEP(ep->num)->DOEPCTL) & USB_OTG_DOEPCTL_USBAEP) == 0) + { + USBx_OUTEP(ep->num)->DOEPCTL |= ((ep->maxpacket & USB_OTG_DOEPCTL_MPSIZ ) | (ep->type << 18 ) |\ + (USB_OTG_DIEPCTL_SD0PID_SEVNFRM)| (USB_OTG_DOEPCTL_USBAEP)); + } + } + return HAL_OK; +} +/** + * @brief Activate and configure a dedicated endpoint + * @param USBx: Selected device + * @param ep: pointer to endpoint structure + * @retval HAL status + */ +HAL_StatusTypeDef USB_ActivateDedicatedEndpoint(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep) +{ + static __IO uint32_t debug = 0; + + /* Read DEPCTLn register */ + if (ep->is_in == 1) + { + if (((USBx_INEP(ep->num)->DIEPCTL) & USB_OTG_DIEPCTL_USBAEP) == 0) + { + USBx_INEP(ep->num)->DIEPCTL |= ((ep->maxpacket & USB_OTG_DIEPCTL_MPSIZ ) | (ep->type << 18 ) |\ + ((ep->num) << 22 ) | (USB_OTG_DIEPCTL_SD0PID_SEVNFRM) | (USB_OTG_DIEPCTL_USBAEP)); + } + + + debug |= ((ep->maxpacket & USB_OTG_DIEPCTL_MPSIZ ) | (ep->type << 18 ) |\ + ((ep->num) << 22 ) | (USB_OTG_DIEPCTL_SD0PID_SEVNFRM) | (USB_OTG_DIEPCTL_USBAEP)); + + USBx_DEVICE->DEACHMSK |= USB_OTG_DAINTMSK_IEPM & ((1 << (ep->num))); + } + else + { + if (((USBx_OUTEP(ep->num)->DOEPCTL) & USB_OTG_DOEPCTL_USBAEP) == 0) + { + USBx_OUTEP(ep->num)->DOEPCTL |= ((ep->maxpacket & USB_OTG_DOEPCTL_MPSIZ ) | (ep->type << 18 ) |\ + ((ep->num) << 22 ) | (USB_OTG_DOEPCTL_USBAEP)); + + debug = (uint32_t)(((uint32_t )USBx) + USB_OTG_OUT_ENDPOINT_BASE + (0)*USB_OTG_EP_REG_SIZE); + debug = (uint32_t )&USBx_OUTEP(ep->num)->DOEPCTL; + debug |= ((ep->maxpacket & USB_OTG_DOEPCTL_MPSIZ ) | (ep->type << 18 ) |\ + ((ep->num) << 22 ) | (USB_OTG_DOEPCTL_USBAEP)); + } + + USBx_DEVICE->DEACHMSK |= USB_OTG_DAINTMSK_OEPM & ((1 << (ep->num)) << 16); + } + + return HAL_OK; +} +/** + * @brief De-activate and de-initialize an endpoint + * @param USBx: Selected device + * @param ep: pointer to endpoint structure + * @retval HAL status + */ +HAL_StatusTypeDef USB_DeactivateEndpoint(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep) +{ + /* Read DEPCTLn register */ + if (ep->is_in == 1) + { + USBx_DEVICE->DEACHMSK &= ~(USB_OTG_DAINTMSK_IEPM & ((1 << (ep->num)))); + USBx_DEVICE->DAINTMSK &= ~(USB_OTG_DAINTMSK_IEPM & ((1 << (ep->num)))); + USBx_INEP(ep->num)->DIEPCTL &= ~ USB_OTG_DIEPCTL_USBAEP; + } + else + { + USBx_DEVICE->DEACHMSK &= ~(USB_OTG_DAINTMSK_OEPM & ((1 << (ep->num)) << 16)); + USBx_DEVICE->DAINTMSK &= ~(USB_OTG_DAINTMSK_OEPM & ((1 << (ep->num)) << 16)); + USBx_OUTEP(ep->num)->DOEPCTL &= ~USB_OTG_DOEPCTL_USBAEP; + } + return HAL_OK; +} + +/** + * @brief De-activate and de-initialize a dedicated endpoint + * @param USBx: Selected device + * @param ep: pointer to endpoint structure + * @retval HAL status + */ +HAL_StatusTypeDef USB_DeactivateDedicatedEndpoint(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep) +{ + /* Read DEPCTLn register */ + if (ep->is_in == 1) + { + USBx_INEP(ep->num)->DIEPCTL &= ~ USB_OTG_DIEPCTL_USBAEP; + USBx_DEVICE->DAINTMSK &= ~(USB_OTG_DAINTMSK_IEPM & ((1 << (ep->num)))); + } + else + { + USBx_OUTEP(ep->num)->DOEPCTL &= ~USB_OTG_DOEPCTL_USBAEP; + USBx_DEVICE->DAINTMSK &= ~(USB_OTG_DAINTMSK_OEPM & ((1 << (ep->num)) << 16)); + } + return HAL_OK; +} + +/** + * @brief USB_EPStartXfer : setup and starts a transfer over an EP + * @param USBx: Selected device + * @param ep: pointer to endpoint structure + * @param dma: USB dma enabled or disabled + * This parameter can be one of these values: + * 0 : DMA feature not used + * 1 : DMA feature used + * @retval HAL status + */ +HAL_StatusTypeDef USB_EPStartXfer(USB_OTG_GlobalTypeDef *USBx , USB_OTG_EPTypeDef *ep, uint8_t dma) +{ + uint16_t pktcnt = 0; + + /* IN endpoint */ + if (ep->is_in == 1) + { + /* Zero Length Packet? */ + if (ep->xfer_len == 0) + { + USBx_INEP(ep->num)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_PKTCNT); + USBx_INEP(ep->num)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_PKTCNT & (1 << 19)) ; + USBx_INEP(ep->num)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_XFRSIZ); + } + else + { + /* Program the transfer size and packet count + * as follows: xfersize = N * maxpacket + + * short_packet pktcnt = N + (short_packet + * exist ? 1 : 0) + */ + USBx_INEP(ep->num)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_XFRSIZ); + USBx_INEP(ep->num)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_PKTCNT); + USBx_INEP(ep->num)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_PKTCNT & (((ep->xfer_len + ep->maxpacket -1)/ ep->maxpacket) << 19)) ; + USBx_INEP(ep->num)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_XFRSIZ & ep->xfer_len); + + if (ep->type == EP_TYPE_ISOC) + { + USBx_INEP(ep->num)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_MULCNT); + USBx_INEP(ep->num)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_MULCNT & (1 << 29)); + } + } + if (ep->type != EP_TYPE_ISOC) + { + /* Enable the Tx FIFO Empty Interrupt for this EP */ + if (ep->xfer_len > 0) + { + USBx_DEVICE->DIEPEMPMSK |= 1 << ep->num; + } + } + + if (ep->type == EP_TYPE_ISOC) + { + if ((USBx_DEVICE->DSTS & ( 1 << 8 )) == 0) + { + USBx_INEP(ep->num)->DIEPCTL |= USB_OTG_DIEPCTL_SODDFRM; + } + else + { + USBx_INEP(ep->num)->DIEPCTL |= USB_OTG_DIEPCTL_SD0PID_SEVNFRM; + } + } + + /* EP enable, IN data in FIFO */ + USBx_INEP(ep->num)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA); + + if (ep->type == EP_TYPE_ISOC) + { + USB_WritePacket(USBx, ep->xfer_buff, ep->num, ep->xfer_len, dma); + } + } + else /* OUT endpoint */ + { + /* Program the transfer size and packet count as follows: + * pktcnt = N + * xfersize = N * maxpacket + */ + USBx_OUTEP(ep->num)->DOEPTSIZ &= ~(USB_OTG_DOEPTSIZ_XFRSIZ); + USBx_OUTEP(ep->num)->DOEPTSIZ &= ~(USB_OTG_DOEPTSIZ_PKTCNT); + + if (ep->xfer_len == 0) + { + USBx_OUTEP(ep->num)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_XFRSIZ & ep->maxpacket); + USBx_OUTEP(ep->num)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_PKTCNT & (1 << 19)) ; + } + else + { + pktcnt = (ep->xfer_len + ep->maxpacket -1)/ ep->maxpacket; + USBx_OUTEP(ep->num)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_PKTCNT & (pktcnt << 19)); ; + USBx_OUTEP(ep->num)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_XFRSIZ & (ep->maxpacket * pktcnt)); + } + + if (ep->type == EP_TYPE_ISOC) + { + if ((USBx_DEVICE->DSTS & ( 1 << 8 )) == 0) + { + USBx_OUTEP(ep->num)->DOEPCTL |= USB_OTG_DOEPCTL_SODDFRM; + } + else + { + USBx_OUTEP(ep->num)->DOEPCTL |= USB_OTG_DOEPCTL_SD0PID_SEVNFRM; + } + } + /* EP enable */ + USBx_OUTEP(ep->num)->DOEPCTL |= (USB_OTG_DOEPCTL_CNAK | USB_OTG_DOEPCTL_EPENA); + } + return HAL_OK; +} + +/** + * @brief USB_EP0StartXfer : setup and starts a transfer over the EP 0 + * @param USBx: Selected device + * @param ep: pointer to endpoint structure + * @param dma: USB dma enabled or disabled + * This parameter can be one of these values: + * 0 : DMA feature not used + * 1 : DMA feature used + * @retval HAL status + */ +HAL_StatusTypeDef USB_EP0StartXfer(USB_OTG_GlobalTypeDef *USBx , USB_OTG_EPTypeDef *ep, uint8_t dma) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(USBx); + UNUSED(dma); + + /* IN endpoint */ + if (ep->is_in == 1) + { + /* Zero Length Packet? */ + if (ep->xfer_len == 0) + { + USBx_INEP(ep->num)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_PKTCNT); + USBx_INEP(ep->num)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_PKTCNT & (1 << 19)) ; + USBx_INEP(ep->num)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_XFRSIZ); + } + else + { + /* Program the transfer size and packet count + * as follows: xfersize = N * maxpacket + + * short_packet pktcnt = N + (short_packet + * exist ? 1 : 0) + */ + USBx_INEP(ep->num)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_XFRSIZ); + USBx_INEP(ep->num)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_PKTCNT); + + if(ep->xfer_len > ep->maxpacket) + { + ep->xfer_len = ep->maxpacket; + } + USBx_INEP(ep->num)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_PKTCNT & (1 << 19)) ; + USBx_INEP(ep->num)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_XFRSIZ & ep->xfer_len); + + } + + /* Enable the Tx FIFO Empty Interrupt for this EP */ + if (ep->xfer_len > 0) + { + USBx_DEVICE->DIEPEMPMSK |= 1 << (ep->num); + } + + /* EP enable, IN data in FIFO */ + USBx_INEP(ep->num)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA); + } + else /* OUT endpoint */ + { + /* Program the transfer size and packet count as follows: + * pktcnt = N + * xfersize = N * maxpacket + */ + USBx_OUTEP(ep->num)->DOEPTSIZ &= ~(USB_OTG_DOEPTSIZ_XFRSIZ); + USBx_OUTEP(ep->num)->DOEPTSIZ &= ~(USB_OTG_DOEPTSIZ_PKTCNT); + + if (ep->xfer_len > 0) + { + ep->xfer_len = ep->maxpacket; + } + + USBx_OUTEP(ep->num)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_PKTCNT & (1 << 19)); + USBx_OUTEP(ep->num)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_XFRSIZ & (ep->maxpacket)); + + /* EP enable */ + USBx_OUTEP(ep->num)->DOEPCTL |= (USB_OTG_DOEPCTL_CNAK | USB_OTG_DOEPCTL_EPENA); + } + return HAL_OK; +} + +/** + * @brief USB_WritePacket : Writes a packet into the Tx FIFO associated + * with the EP/channel + * @param USBx: Selected device + * @param src: pointer to source buffer + * @param ch_ep_num: endpoint or host channel number + * @param len: Number of bytes to write + * @param dma: USB dma enabled or disabled + * This parameter can be one of these values: + * 0 : DMA feature not used + * 1 : DMA feature used + * @retval HAL status + */ +HAL_StatusTypeDef USB_WritePacket(USB_OTG_GlobalTypeDef *USBx, uint8_t *src, uint8_t ch_ep_num, uint16_t len, uint8_t dma) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(USBx); + UNUSED(dma); + + uint32_t count32b= 0 , index= 0; + count32b = (len + 3) / 4; + for (index = 0; index < count32b; index++, src += 4) + { + USBx_DFIFO(ch_ep_num) = *((__packed uint32_t *)src); + } + return HAL_OK; +} + +/** + * @brief USB_ReadPacket : read a packet from the Tx FIFO associated + * with the EP/channel + * @param USBx: Selected device + * @param src: source pointer + * @param ch_ep_num: endpoint or host channel number + * @param len: Number of bytes to read + * @param dma: USB dma enabled or disabled + * This parameter can be one of these values: + * 0 : DMA feature not used + * 1 : DMA feature used + * @retval pointer to destination buffer + */ +void *USB_ReadPacket(USB_OTG_GlobalTypeDef *USBx, uint8_t *dest, uint16_t len) +{ + uint32_t index=0; + uint32_t count32b = (len + 3) / 4; + + for ( index = 0; index < count32b; index++, dest += 4 ) + { + *(__packed uint32_t *)dest = USBx_DFIFO(0); + + } + return ((void *)dest); +} + +/** + * @brief USB_EPSetStall : set a stall condition over an EP + * @param USBx: Selected device + * @param ep: pointer to endpoint structure + * @retval HAL status + */ +HAL_StatusTypeDef USB_EPSetStall(USB_OTG_GlobalTypeDef *USBx , USB_OTG_EPTypeDef *ep) +{ + if (ep->is_in == 1) + { + if (((USBx_INEP(ep->num)->DIEPCTL) & USB_OTG_DIEPCTL_EPENA) == 0) + { + USBx_INEP(ep->num)->DIEPCTL &= ~(USB_OTG_DIEPCTL_EPDIS); + } + USBx_INEP(ep->num)->DIEPCTL |= USB_OTG_DIEPCTL_STALL; + } + else + { + if (((USBx_OUTEP(ep->num)->DOEPCTL) & USB_OTG_DOEPCTL_EPENA) == 0) + { + USBx_OUTEP(ep->num)->DOEPCTL &= ~(USB_OTG_DOEPCTL_EPDIS); + } + USBx_OUTEP(ep->num)->DOEPCTL |= USB_OTG_DOEPCTL_STALL; + } + return HAL_OK; +} + + +/** + * @brief USB_EPClearStall : Clear a stall condition over an EP + * @param USBx: Selected device + * @param ep: pointer to endpoint structure + * @retval HAL status + */ +HAL_StatusTypeDef USB_EPClearStall(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep) +{ + if (ep->is_in == 1) + { + USBx_INEP(ep->num)->DIEPCTL &= ~USB_OTG_DIEPCTL_STALL; + if (ep->type == EP_TYPE_INTR || ep->type == EP_TYPE_BULK) + { + USBx_INEP(ep->num)->DIEPCTL |= USB_OTG_DIEPCTL_SD0PID_SEVNFRM; /* DATA0 */ + } + } + else + { + USBx_OUTEP(ep->num)->DOEPCTL &= ~USB_OTG_DOEPCTL_STALL; + if (ep->type == EP_TYPE_INTR || ep->type == EP_TYPE_BULK) + { + USBx_OUTEP(ep->num)->DOEPCTL |= USB_OTG_DOEPCTL_SD0PID_SEVNFRM; /* DATA0 */ + } + } + return HAL_OK; +} + +/** + * @brief USB_StopDevice : Stop the USB device mode + * @param USBx: Selected device + * @retval HAL status + */ +HAL_StatusTypeDef USB_StopDevice(USB_OTG_GlobalTypeDef *USBx) +{ + uint32_t index; + + /* Clear Pending interrupt */ + for (index = 0; index < 15 ; index++) + { + USBx_INEP(index)->DIEPINT = 0xFF; + USBx_OUTEP(index)->DOEPINT = 0xFF; + } + USBx_DEVICE->DAINT = 0xFFFFFFFF; + + /* Clear interrupt masks */ + USBx_DEVICE->DIEPMSK = 0; + USBx_DEVICE->DOEPMSK = 0; + USBx_DEVICE->DAINTMSK = 0; + + /* Flush the FIFO */ + USB_FlushRxFifo(USBx); + USB_FlushTxFifo(USBx , 0x10 ); + + return HAL_OK; +} + +/** + * @brief USB_SetDevAddress : Stop the USB device mode + * @param USBx: Selected device + * @param address: new device address to be assigned + * This parameter can be a value from 0 to 255 + * @retval HAL status + */ +HAL_StatusTypeDef USB_SetDevAddress (USB_OTG_GlobalTypeDef *USBx, uint8_t address) +{ + USBx_DEVICE->DCFG &= ~ (USB_OTG_DCFG_DAD); + USBx_DEVICE->DCFG |= (address << 4) & USB_OTG_DCFG_DAD ; + + return HAL_OK; +} + +/** + * @brief USB_DevConnect : Connect the USB device by enabling the pull-up/pull-down + * @param USBx: Selected device + * @retval HAL status + */ +HAL_StatusTypeDef USB_DevConnect (USB_OTG_GlobalTypeDef *USBx) +{ + USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_SDIS ; + HAL_Delay(3); + + return HAL_OK; +} + +/** + * @brief USB_DevDisconnect : Disconnect the USB device by disabling the pull-up/pull-down + * @param USBx: Selected device + * @retval HAL status + */ +HAL_StatusTypeDef USB_DevDisconnect (USB_OTG_GlobalTypeDef *USBx) +{ + USBx_DEVICE->DCTL |= USB_OTG_DCTL_SDIS ; + HAL_Delay(3); + + return HAL_OK; +} + +/** + * @brief USB_ReadInterrupts: return the global USB interrupt status + * @param USBx: Selected device + * @retval HAL status + */ +uint32_t USB_ReadInterrupts (USB_OTG_GlobalTypeDef *USBx) +{ + uint32_t tmpreg = 0; + + tmpreg = USBx->GINTSTS; + tmpreg &= USBx->GINTMSK; + return tmpreg; +} + +/** + * @brief USB_ReadDevAllOutEpInterrupt: return the USB device OUT endpoints interrupt status + * @param USBx: Selected device + * @retval HAL status + */ +uint32_t USB_ReadDevAllOutEpInterrupt (USB_OTG_GlobalTypeDef *USBx) +{ + uint32_t tmpreg; + tmpreg = USBx_DEVICE->DAINT; + tmpreg &= USBx_DEVICE->DAINTMSK; + return ((tmpreg & 0xffff0000) >> 16); +} + +/** + * @brief USB_ReadDevAllInEpInterrupt: return the USB device IN endpoints interrupt status + * @param USBx: Selected device + * @retval HAL status + */ +uint32_t USB_ReadDevAllInEpInterrupt (USB_OTG_GlobalTypeDef *USBx) +{ + uint32_t tmpreg; + tmpreg = USBx_DEVICE->DAINT; + tmpreg &= USBx_DEVICE->DAINTMSK; + return ((tmpreg & 0xFFFF)); +} + +/** + * @brief Returns Device OUT EP Interrupt register + * @param USBx: Selected device + * @param epnum: endpoint number + * This parameter can be a value from 0 to 15 + * @retval Device OUT EP Interrupt register + */ +uint32_t USB_ReadDevOutEPInterrupt (USB_OTG_GlobalTypeDef *USBx , uint8_t epnum) +{ + uint32_t tmpreg; + tmpreg = USBx_OUTEP(epnum)->DOEPINT; + tmpreg &= USBx_DEVICE->DOEPMSK; + return tmpreg; +} + +/** + * @brief Returns Device IN EP Interrupt register + * @param USBx: Selected device + * @param epnum: endpoint number + * This parameter can be a value from 0 to 15 + * @retval Device IN EP Interrupt register + */ +uint32_t USB_ReadDevInEPInterrupt (USB_OTG_GlobalTypeDef *USBx , uint8_t epnum) +{ + uint32_t tmpreg = 0, msk = 0, emp = 0; + + msk = USBx_DEVICE->DIEPMSK; + emp = USBx_DEVICE->DIEPEMPMSK; + msk |= ((emp >> epnum) & 0x1) << 7; + tmpreg = USBx_INEP(epnum)->DIEPINT & msk; + return tmpreg; +} + +/** + * @brief USB_ClearInterrupts: clear a USB interrupt + * @param USBx: Selected device + * @param interrupt: interrupt flag + * @retval None + */ +void USB_ClearInterrupts (USB_OTG_GlobalTypeDef *USBx, uint32_t interrupt) +{ + USBx->GINTSTS |= interrupt; +} + +/** + * @brief Returns USB core mode + * @param USBx: Selected device + * @retval return core mode : Host or Device + * This parameter can be one of these values: + * 0 : Host + * 1 : Device + */ +uint32_t USB_GetMode(USB_OTG_GlobalTypeDef *USBx) +{ + return ((USBx->GINTSTS ) & 0x1); +} + + +/** + * @brief Activate EP0 for Setup transactions + * @param USBx: Selected device + * @retval HAL status + */ +HAL_StatusTypeDef USB_ActivateSetup (USB_OTG_GlobalTypeDef *USBx) +{ + /* Set the MPS of the IN EP based on the enumeration speed */ + USBx_INEP(0)->DIEPCTL &= ~USB_OTG_DIEPCTL_MPSIZ; + + if((USBx_DEVICE->DSTS & USB_OTG_DSTS_ENUMSPD) == DSTS_ENUMSPD_LS_PHY_6MHZ) + { + USBx_INEP(0)->DIEPCTL |= 3; + } + USBx_DEVICE->DCTL |= USB_OTG_DCTL_CGINAK; + + return HAL_OK; +} + + +/** + * @brief Prepare the EP0 to start the first control setup + * @param USBx: Selected device + * @param dma: USB dma enabled or disabled + * This parameter can be one of these values: + * 0 : DMA feature not used + * 1 : DMA feature used + * @param psetup: pointer to setup packet + * @retval HAL status + */ +HAL_StatusTypeDef USB_EP0_OutStart(USB_OTG_GlobalTypeDef *USBx, uint8_t dma, uint8_t *psetup) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(psetup); + + USBx_OUTEP(0)->DOEPTSIZ = 0; + USBx_OUTEP(0)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_PKTCNT & (1 << 19)) ; + USBx_OUTEP(0)->DOEPTSIZ |= (3 * 8); + USBx_OUTEP(0)->DOEPTSIZ |= USB_OTG_DOEPTSIZ_STUPCNT; + + return HAL_OK; +} + +/** + * @brief USB_HostInit : Initializes the USB OTG controller registers + * for Host mode + * @param USBx: Selected device + * @param cfg: pointer to a USB_OTG_CfgTypeDef structure that contains + * the configuration information for the specified USBx peripheral. + * @retval HAL status + */ +HAL_StatusTypeDef USB_HostInit (USB_OTG_GlobalTypeDef *USBx, USB_OTG_CfgTypeDef cfg) +{ + uint32_t index = 0; + + /* Restart the Phy Clock */ + USBx_PCGCCTL = 0; + + /* Disable the FS/LS support mode only */ + if((cfg.speed == USB_OTG_SPEED_FULL)&& + (USBx != USB_OTG_FS)) + { + USBx_HOST->HCFG |= USB_OTG_HCFG_FSLSS; + } + else + { + USBx_HOST->HCFG &= ~(USB_OTG_HCFG_FSLSS); + } + + /* Make sure the FIFOs are flushed. */ + USB_FlushTxFifo(USBx, 0x10 ); /* all Tx FIFOs */ + USB_FlushRxFifo(USBx); + + /* Clear all pending HC Interrupts */ + for (index = 0; index < cfg.Host_channels; index++) + { + USBx_HC(index)->HCINT = 0xFFFFFFFF; + USBx_HC(index)->HCINTMSK = 0; + } + + /* Enable VBUS driving */ + USB_DriveVbus(USBx, 1); + + HAL_Delay(200); + + /* Disable all interrupts. */ + USBx->GINTMSK = 0; + + /* Clear any pending interrupts */ + USBx->GINTSTS = 0xFFFFFFFF; + + /* set Rx FIFO size */ + USBx->GRXFSIZ = (uint32_t )0x80; + USBx->DIEPTXF0_HNPTXFSIZ = (uint32_t )(((0x60 << 16)& USB_OTG_NPTXFD) | 0x80); + USBx->HPTXFSIZ = (uint32_t )(((0x40 << 16)& USB_OTG_HPTXFSIZ_PTXFD) | 0xE0); + + /* Enable the common interrupts */ + if (cfg.dma_enable == DISABLE) + { + USBx->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM; + } + + /* Enable interrupts matching to the Host mode ONLY */ + USBx->GINTMSK |= (USB_OTG_GINTMSK_PRTIM | USB_OTG_GINTMSK_HCIM |\ + USB_OTG_GINTMSK_SOFM |USB_OTG_GINTSTS_DISCINT|\ + USB_OTG_GINTMSK_PXFRM_IISOOXFRM | USB_OTG_GINTMSK_WUIM); + + return HAL_OK; +} + +/** + * @brief USB_InitFSLSPClkSel : Initializes the FSLSPClkSel field of the + * HCFG register on the PHY type and set the right frame interval + * @param USBx: Selected device + * @param freq: clock frequency + * This parameter can be one of these values: + * HCFG_48_MHZ : Full Speed 48 MHz Clock + * HCFG_6_MHZ : Low Speed 6 MHz Clock + * @retval HAL status + */ +HAL_StatusTypeDef USB_InitFSLSPClkSel(USB_OTG_GlobalTypeDef *USBx , uint8_t freq) +{ + USBx_HOST->HCFG &= ~(USB_OTG_HCFG_FSLSPCS); + USBx_HOST->HCFG |= (freq & USB_OTG_HCFG_FSLSPCS); + + if (freq == HCFG_48_MHZ) + { + USBx_HOST->HFIR = (uint32_t)48000; + } + else if (freq == HCFG_6_MHZ) + { + USBx_HOST->HFIR = (uint32_t)6000; + } + return HAL_OK; +} + +/** +* @brief USB_OTG_ResetPort : Reset Host Port + * @param USBx: Selected device + * @retval HAL status + * @note (1)The application must wait at least 10 ms + * before clearing the reset bit. + */ +HAL_StatusTypeDef USB_ResetPort(USB_OTG_GlobalTypeDef *USBx) +{ + __IO uint32_t hprt0 = 0; + + hprt0 = USBx_HPRT0; + + hprt0 &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |\ + USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG ); + + USBx_HPRT0 = (USB_OTG_HPRT_PRST | hprt0); + HAL_Delay (10); /* See Note #1 */ + USBx_HPRT0 = ((~USB_OTG_HPRT_PRST) & hprt0); + return HAL_OK; +} + +/** + * @brief USB_DriveVbus : activate or de-activate vbus + * @param state: VBUS state + * This parameter can be one of these values: + * 0 : VBUS Active + * 1 : VBUS Inactive + * @retval HAL status +*/ +HAL_StatusTypeDef USB_DriveVbus (USB_OTG_GlobalTypeDef *USBx, uint8_t state) +{ + __IO uint32_t hprt0 = 0; + + hprt0 = USBx_HPRT0; + hprt0 &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |\ + USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG ); + + if (((hprt0 & USB_OTG_HPRT_PPWR) == 0 ) && (state == 1 )) + { + USBx_HPRT0 = (USB_OTG_HPRT_PPWR | hprt0); + } + if (((hprt0 & USB_OTG_HPRT_PPWR) == USB_OTG_HPRT_PPWR) && (state == 0 )) + { + USBx_HPRT0 = ((~USB_OTG_HPRT_PPWR) & hprt0); + } + return HAL_OK; +} + +/** + * @brief Return Host Core speed + * @param USBx: Selected device + * @retval speed : Host speed + * This parameter can be one of these values: + * @arg USB_OTG_SPEED_HIGH: High speed mode + * @arg USB_OTG_SPEED_FULL: Full speed mode + * @arg USB_OTG_SPEED_LOW: Low speed mode + */ +uint32_t USB_GetHostSpeed (USB_OTG_GlobalTypeDef *USBx) +{ + __IO uint32_t hprt0 = 0; + + hprt0 = USBx_HPRT0; + return ((hprt0 & USB_OTG_HPRT_PSPD) >> 17); +} + +/** + * @brief Return Host Current Frame number + * @param USBx: Selected device + * @retval current frame number +*/ +uint32_t USB_GetCurrentFrame (USB_OTG_GlobalTypeDef *USBx) +{ + return (USBx_HOST->HFNUM & USB_OTG_HFNUM_FRNUM); +} + +/** + * @brief Initialize a host channel + * @param USBx: Selected device + * @param ch_num : Channel number + * This parameter can be a value from 1 to 15 + * @param epnum: Endpoint number + * This parameter can be a value from 1 to 15 + * @param dev_address: Current device address + * This parameter can be a value from 0 to 255 + * @param speed: Current device speed + * This parameter can be one of these values: + * @arg USB_OTG_SPEED_HIGH: High speed mode + * @arg USB_OTG_SPEED_FULL: Full speed mode + * @arg USB_OTG_SPEED_LOW: Low speed mode + * @param ep_type: Endpoint Type + * This parameter can be one of these values: + * @arg EP_TYPE_CTRL: Control type + * @arg EP_TYPE_ISOC: Isochronous type + * @arg EP_TYPE_BULK: Bulk type + * @arg EP_TYPE_INTR: Interrupt type + * @param mps: Max Packet Size + * This parameter can be a value from 0 to32K + * @retval HAL state + */ +HAL_StatusTypeDef USB_HC_Init(USB_OTG_GlobalTypeDef *USBx, + uint8_t ch_num, + uint8_t epnum, + uint8_t dev_address, + uint8_t speed, + uint8_t ep_type, + uint16_t mps) +{ + + /* Clear old interrupt conditions for this host channel. */ + USBx_HC(ch_num)->HCINT = 0xFFFFFFFF; + + /* Enable channel interrupts required for this transfer. */ + switch (ep_type) + { + case EP_TYPE_CTRL: + case EP_TYPE_BULK: + + USBx_HC(ch_num)->HCINTMSK = USB_OTG_HCINTMSK_XFRCM |\ + USB_OTG_HCINTMSK_STALLM |\ + USB_OTG_HCINTMSK_TXERRM |\ + USB_OTG_HCINTMSK_DTERRM |\ + USB_OTG_HCINTMSK_AHBERR |\ + USB_OTG_HCINTMSK_NAKM ; + + if (epnum & 0x80) + { + USBx_HC(ch_num)->HCINTMSK |= USB_OTG_HCINTMSK_BBERRM; + } + break; + + case EP_TYPE_INTR: + + USBx_HC(ch_num)->HCINTMSK = USB_OTG_HCINTMSK_XFRCM |\ + USB_OTG_HCINTMSK_STALLM |\ + USB_OTG_HCINTMSK_TXERRM |\ + USB_OTG_HCINTMSK_DTERRM |\ + USB_OTG_HCINTMSK_NAKM |\ + USB_OTG_HCINTMSK_AHBERR |\ + USB_OTG_HCINTMSK_FRMORM ; + + if (epnum & 0x80) + { + USBx_HC(ch_num)->HCINTMSK |= USB_OTG_HCINTMSK_BBERRM; + } + + break; + case EP_TYPE_ISOC: + + USBx_HC(ch_num)->HCINTMSK = USB_OTG_HCINTMSK_XFRCM |\ + USB_OTG_HCINTMSK_ACKM |\ + USB_OTG_HCINTMSK_AHBERR |\ + USB_OTG_HCINTMSK_FRMORM ; + + if (epnum & 0x80) + { + USBx_HC(ch_num)->HCINTMSK |= (USB_OTG_HCINTMSK_TXERRM | USB_OTG_HCINTMSK_BBERRM); + } + break; + } + + /* Enable the top level host channel interrupt. */ + USBx_HOST->HAINTMSK |= (1 << ch_num); + + /* Make sure host channel interrupts are enabled. */ + USBx->GINTMSK |= USB_OTG_GINTMSK_HCIM; + + /* Program the HCCHAR register */ + USBx_HC(ch_num)->HCCHAR = (((dev_address << 22) & USB_OTG_HCCHAR_DAD) |\ + (((epnum & 0x7F)<< 11) & USB_OTG_HCCHAR_EPNUM)|\ + ((((epnum & 0x80) == 0x80)<< 15) & USB_OTG_HCCHAR_EPDIR)|\ + (((speed == HPRT0_PRTSPD_LOW_SPEED)<< 17) & USB_OTG_HCCHAR_LSDEV)|\ + ((ep_type << 18) & USB_OTG_HCCHAR_EPTYP)|\ + (mps & USB_OTG_HCCHAR_MPSIZ)); + + if (ep_type == EP_TYPE_INTR) + { + USBx_HC(ch_num)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM ; + } + + return HAL_OK; +} + +/** + * @brief Start a transfer over a host channel + * @param USBx: Selected device + * @param hc: pointer to host channel structure + * @param dma: USB dma enabled or disabled + * This parameter can be one of these values: + * 0 : DMA feature not used + * 1 : DMA feature used + * @retval HAL state + */ +#if defined (__CC_ARM) /*!< ARM Compiler */ +#pragma O0 +#elif defined (__GNUC__) /*!< GNU Compiler */ +#pragma GCC optimize ("O0") +#endif /* __CC_ARM */ +HAL_StatusTypeDef USB_HC_StartXfer(USB_OTG_GlobalTypeDef *USBx, USB_OTG_HCTypeDef *hc, uint8_t dma) +{ + uint8_t is_oddframe = 0; + uint16_t len_words = 0; + uint16_t num_packets = 0; + uint16_t max_hc_pkt_count = 256; + uint32_t tmpreg = 0; + + /* Compute the expected number of packets associated to the transfer */ + if (hc->xfer_len > 0) + { + num_packets = (hc->xfer_len + hc->max_packet - 1) / hc->max_packet; + + if (num_packets > max_hc_pkt_count) + { + num_packets = max_hc_pkt_count; + hc->xfer_len = num_packets * hc->max_packet; + } + } + else + { + num_packets = 1; + } + if (hc->ep_is_in) + { + hc->xfer_len = num_packets * hc->max_packet; + } + + /* Initialize the HCTSIZn register */ + USBx_HC(hc->ch_num)->HCTSIZ = (((hc->xfer_len) & USB_OTG_HCTSIZ_XFRSIZ)) |\ + ((num_packets << 19) & USB_OTG_HCTSIZ_PKTCNT) |\ + (((hc->data_pid) << 29) & USB_OTG_HCTSIZ_DPID); + + if (dma) + { + /* xfer_buff MUST be 32-bits aligned */ + USBx_HC(hc->ch_num)->HCDMA = (uint32_t)hc->xfer_buff; + } + + is_oddframe = (USBx_HOST->HFNUM & 0x01) ? 0 : 1; + USBx_HC(hc->ch_num)->HCCHAR &= ~USB_OTG_HCCHAR_ODDFRM; + USBx_HC(hc->ch_num)->HCCHAR |= (is_oddframe << 29); + + /* Set host channel enable */ + tmpreg = USBx_HC(hc->ch_num)->HCCHAR; + tmpreg &= ~USB_OTG_HCCHAR_CHDIS; + tmpreg |= USB_OTG_HCCHAR_CHENA; + USBx_HC(hc->ch_num)->HCCHAR = tmpreg; + + if (dma == 0) /* Slave mode */ + { + if((hc->ep_is_in == 0) && (hc->xfer_len > 0)) + { + switch(hc->ep_type) + { + /* Non periodic transfer */ + case EP_TYPE_CTRL: + case EP_TYPE_BULK: + + len_words = (hc->xfer_len + 3) / 4; + + /* check if there is enough space in FIFO space */ + if(len_words > (USBx->HNPTXSTS & 0xFFFF)) + { + /* need to process data in nptxfempty interrupt */ + USBx->GINTMSK |= USB_OTG_GINTMSK_NPTXFEM; + } + break; + /* Periodic transfer */ + case EP_TYPE_INTR: + case EP_TYPE_ISOC: + len_words = (hc->xfer_len + 3) / 4; + /* check if there is enough space in FIFO space */ + if(len_words > (USBx_HOST->HPTXSTS & 0xFFFF)) /* split the transfer */ + { + /* need to process data in ptxfempty interrupt */ + USBx->GINTMSK |= USB_OTG_GINTMSK_PTXFEM; + } + break; + + default: + break; + } + + /* Write packet into the Tx FIFO. */ + USB_WritePacket(USBx, hc->xfer_buff, hc->ch_num, hc->xfer_len, 0); + } + } + + return HAL_OK; +} + +/** + * @brief Read all host channel interrupts status + * @param USBx: Selected device + * @retval HAL state + */ +uint32_t USB_HC_ReadInterrupt (USB_OTG_GlobalTypeDef *USBx) +{ + return ((USBx_HOST->HAINT) & 0xFFFF); +} + +/** + * @brief Halt a host channel + * @param USBx: Selected device + * @param hc_num: Host Channel number + * This parameter can be a value from 1 to 15 + * @retval HAL state + */ +HAL_StatusTypeDef USB_HC_Halt(USB_OTG_GlobalTypeDef *USBx , uint8_t hc_num) +{ + uint32_t count = 0; + + /* Check for space in the request queue to issue the halt. */ + if (((USBx_HC(hc_num)->HCCHAR) & (HCCHAR_CTRL << 18)) || ((USBx_HC(hc_num)->HCCHAR) & (HCCHAR_BULK << 18))) + { + USBx_HC(hc_num)->HCCHAR |= USB_OTG_HCCHAR_CHDIS; + + if ((USBx->HNPTXSTS & 0xFFFF) == 0) + { + USBx_HC(hc_num)->HCCHAR &= ~USB_OTG_HCCHAR_CHENA; + USBx_HC(hc_num)->HCCHAR |= USB_OTG_HCCHAR_CHENA; + USBx_HC(hc_num)->HCCHAR &= ~USB_OTG_HCCHAR_EPDIR; + do + { + if (++count > 1000) + { + break; + } + } + while ((USBx_HC(hc_num)->HCCHAR & USB_OTG_HCCHAR_CHENA) == USB_OTG_HCCHAR_CHENA); + } + else + { + USBx_HC(hc_num)->HCCHAR |= USB_OTG_HCCHAR_CHENA; + } + } + else + { + USBx_HC(hc_num)->HCCHAR |= USB_OTG_HCCHAR_CHDIS; + + if ((USBx_HOST->HPTXSTS & 0xFFFF) == 0) + { + USBx_HC(hc_num)->HCCHAR &= ~USB_OTG_HCCHAR_CHENA; + USBx_HC(hc_num)->HCCHAR |= USB_OTG_HCCHAR_CHENA; + USBx_HC(hc_num)->HCCHAR &= ~USB_OTG_HCCHAR_EPDIR; + do + { + if (++count > 1000) + { + break; + } + } + while ((USBx_HC(hc_num)->HCCHAR & USB_OTG_HCCHAR_CHENA) == USB_OTG_HCCHAR_CHENA); + } + else + { + USBx_HC(hc_num)->HCCHAR |= USB_OTG_HCCHAR_CHENA; + } + } + + return HAL_OK; +} + +/** + * @brief Initiate Do Ping protocol + * @param USBx: Selected device + * @param hc_num: Host Channel number + * This parameter can be a value from 1 to 15 + * @retval HAL state + */ +HAL_StatusTypeDef USB_DoPing(USB_OTG_GlobalTypeDef *USBx , uint8_t ch_num) +{ + uint8_t num_packets = 1; + uint32_t tmpreg = 0; + + USBx_HC(ch_num)->HCTSIZ = ((num_packets << 19) & USB_OTG_HCTSIZ_PKTCNT) |\ + USB_OTG_HCTSIZ_DOPING; + + /* Set host channel enable */ + tmpreg = USBx_HC(ch_num)->HCCHAR; + tmpreg &= ~USB_OTG_HCCHAR_CHDIS; + tmpreg |= USB_OTG_HCCHAR_CHENA; + USBx_HC(ch_num)->HCCHAR = tmpreg; + + return HAL_OK; +} + +/** + * @brief Stop Host Core + * @param USBx: Selected device + * @retval HAL state + */ +HAL_StatusTypeDef USB_StopHost(USB_OTG_GlobalTypeDef *USBx) +{ + uint8_t index; + uint32_t count = 0; + uint32_t value = 0; + + USB_DisableGlobalInt(USBx); + + /* Flush FIFO */ + USB_FlushTxFifo(USBx, 0x10); + USB_FlushRxFifo(USBx); + + /* Flush out any leftover queued requests. */ + for (index = 0; index <= 15; index++) + { + value = USBx_HC(index)->HCCHAR; + value |= USB_OTG_HCCHAR_CHDIS; + value &= ~USB_OTG_HCCHAR_CHENA; + value &= ~USB_OTG_HCCHAR_EPDIR; + USBx_HC(index)->HCCHAR = value; + } + + /* Halt all channels to put them into a known state. */ + for (index = 0; index <= 15; index++) + { + value = USBx_HC(index)->HCCHAR ; + value |= USB_OTG_HCCHAR_CHDIS; + value |= USB_OTG_HCCHAR_CHENA; + value &= ~USB_OTG_HCCHAR_EPDIR; + USBx_HC(index)->HCCHAR = value; + + USBx_HC(index)->HCCHAR = value; + do + { + if (++count > 1000) + { + break; + } + } + while ((USBx_HC(index)->HCCHAR & USB_OTG_HCCHAR_CHENA) == USB_OTG_HCCHAR_CHENA); + } + + /* Clear any pending Host interrupts */ + USBx_HOST->HAINT = 0xFFFFFFFF; + USBx->GINTSTS = 0xFFFFFFFF; + USB_EnableGlobalInt(USBx); + return HAL_OK; +} + +/** + * @brief USB_ActivateRemoteWakeup : active remote wakeup signalling + * @param USBx : Selected device + * @retval HAL status + */ +HAL_StatusTypeDef USB_ActivateRemoteWakeup(USB_OTG_GlobalTypeDef *USBx) +{ + if((USBx_DEVICE->DSTS & USB_OTG_DSTS_SUSPSTS) == USB_OTG_DSTS_SUSPSTS) + { + /* active Remote wakeup signalling */ + USBx_DEVICE->DCTL |= USB_OTG_DCTL_RWUSIG; + } + return HAL_OK; +} + +/** + * @brief USB_DeActivateRemoteWakeup : de-active remote wakeup signalling + * @param USBx : Selected device + * @retval HAL status + */ +HAL_StatusTypeDef USB_DeActivateRemoteWakeup(USB_OTG_GlobalTypeDef *USBx) +{ + /* active Remote wakeup signalling */ + USBx_DEVICE->DCTL &= ~(USB_OTG_DCTL_RWUSIG); + return HAL_OK; +} + +#endif /* USB_OTG_FS */ + +/*============================================================================== + USB Device FS peripheral available on STM32L432xx, STM32L433xx, STM32L442xx) + and STM32L443xx devices +==============================================================================*/ +#if defined (USB) +/** + * @brief Initializes the USB Core + * @param USBx: USB Instance + * @param cfg : pointer to a USB_CfgTypeDef structure that contains + * the configuration information for the specified USBx peripheral. + * @retval HAL status + */ +HAL_StatusTypeDef USB_CoreInit(USB_TypeDef *USBx, USB_CfgTypeDef cfg) +{ + /* NOTE : - This function is not required by USB Device FS peripheral, it is used + only by USB OTG FS peripheral. + - This function is added to ensure compatibility across platforms. + */ + + /* Prevent unused argument(s) compilation warning */ + UNUSED(USBx); + UNUSED(cfg); + + return HAL_OK; +} + +/** + * @brief USB_EnableGlobalInt + * Enables the controller's Global Int in the AHB Config reg + * @param USBx : Selected device + * @retval HAL status + */ +HAL_StatusTypeDef USB_EnableGlobalInt(USB_TypeDef *USBx) +{ + uint32_t winterruptmask = 0; + + /* Set winterruptmask variable */ + winterruptmask = USB_CNTR_CTRM | USB_CNTR_WKUPM | USB_CNTR_SUSPM | USB_CNTR_ERRM \ + | USB_CNTR_ESOFM | USB_CNTR_RESETM; + + /* Set interrupt mask */ + USBx->CNTR |= winterruptmask; + + return HAL_OK; +} + +/** + * @brief USB_DisableGlobalInt + * Disable the controller's Global Int in the AHB Config reg + * @param USBx : Selected device + * @retval HAL status +*/ +HAL_StatusTypeDef USB_DisableGlobalInt(USB_TypeDef *USBx) +{ + uint32_t winterruptmask = 0; + + /* Set winterruptmask variable */ + winterruptmask = USB_CNTR_CTRM | USB_CNTR_WKUPM | USB_CNTR_SUSPM | USB_CNTR_ERRM \ + | USB_CNTR_ESOFM | USB_CNTR_RESETM; + + /* Clear interrupt mask */ + USBx->CNTR &= ~winterruptmask; + + return HAL_OK; +} + +/** + * @brief USB_SetCurrentMode : Set functional mode + * @param USBx : Selected device + * @param mode : current core mode + * This parameter can be one of the these values: + * @arg USB_DEVICE_MODE: Peripheral mode mode + * @retval HAL status + */ +HAL_StatusTypeDef USB_SetCurrentMode(USB_TypeDef *USBx , USB_ModeTypeDef mode) +{ + /* NOTE : - This function is not required by USB Device FS peripheral, it is used + only by USB OTG FS peripheral. + - This function is added to ensure compatibility across platforms. + */ + + /* Prevent unused argument(s) compilation warning */ + UNUSED(USBx); + UNUSED(mode); + + return HAL_OK; +} + +/** + * @brief USB_DevInit : Initializes the USB controller registers + * for device mode + * @param USBx : Selected device + * @param cfg : pointer to a USB_CfgTypeDef structure that contains + * the configuration information for the specified USBx peripheral. + * @retval HAL status + */ +HAL_StatusTypeDef USB_DevInit (USB_TypeDef *USBx, USB_CfgTypeDef cfg) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(cfg); + + /* Init Device */ + /*CNTR_FRES = 1*/ + USBx->CNTR = USB_CNTR_FRES; + + /*CNTR_FRES = 0*/ + USBx->CNTR = 0; + + /*Clear pending interrupts*/ + USBx->ISTR = 0; + + /*Set Btable Address*/ + USBx->BTABLE = BTABLE_ADDRESS; + + return HAL_OK; +} + +/** + * @brief USB_FlushTxFifo : Flush a Tx FIFO + * @param USBx : Selected device + * @param num : FIFO number + * This parameter can be a value from 1 to 15 + 15 means Flush all Tx FIFOs + * @retval HAL status + */ +HAL_StatusTypeDef USB_FlushTxFifo (USB_TypeDef *USBx, uint32_t num ) +{ + /* NOTE : - This function is not required by USB Device FS peripheral, it is used + only by USB OTG FS peripheral. + - This function is added to ensure compatibility across platforms. + */ + + /* Prevent unused argument(s) compilation warning */ + UNUSED(USBx); + UNUSED(num); + + return HAL_OK; +} + +/** + * @brief USB_FlushRxFifo : Flush Rx FIFO + * @param USBx : Selected device + * @retval HAL status + */ +HAL_StatusTypeDef USB_FlushRxFifo(USB_TypeDef *USBx) +{ + /* NOTE : - This function is not required by USB Device FS peripheral, it is used + only by USB OTG FS peripheral. + - This function is added to ensure compatibility across platforms. + */ + + /* Prevent unused argument(s) compilation warning */ + UNUSED(USBx); + + return HAL_OK; +} + +/** + * @brief Activate and configure an endpoint + * @param USBx : Selected device + * @param ep: pointer to endpoint structure + * @retval HAL status + */ +HAL_StatusTypeDef USB_ActivateEndpoint(USB_TypeDef *USBx, USB_EPTypeDef *ep) +{ + /* initialize Endpoint */ + switch (ep->type) + { + case EP_TYPE_CTRL: + PCD_SET_EPTYPE(USBx, ep->num, USB_EP_CONTROL); + break; + case EP_TYPE_BULK: + PCD_SET_EPTYPE(USBx, ep->num, USB_EP_BULK); + break; + case EP_TYPE_INTR: + PCD_SET_EPTYPE(USBx, ep->num, USB_EP_INTERRUPT); + break; + case EP_TYPE_ISOC: + PCD_SET_EPTYPE(USBx, ep->num, USB_EP_ISOCHRONOUS); + break; + default: + break; + } + + PCD_SET_EP_ADDRESS(USBx, ep->num, ep->num); + + if (ep->doublebuffer == 0) + { + if (ep->is_in) + { + /*Set the endpoint Transmit buffer address */ + PCD_SET_EP_TX_ADDRESS(USBx, ep->num, ep->pmaadress); + PCD_CLEAR_TX_DTOG(USBx, ep->num); + /* Configure NAK status for the Endpoint*/ + PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK); + } + else + { + /*Set the endpoint Receive buffer address */ + PCD_SET_EP_RX_ADDRESS(USBx, ep->num, ep->pmaadress); + /*Set the endpoint Receive buffer counter*/ + PCD_SET_EP_RX_CNT(USBx, ep->num, ep->maxpacket); + PCD_CLEAR_RX_DTOG(USBx, ep->num); + /* Configure VALID status for the Endpoint*/ + PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID); + } + } + /*Double Buffer*/ + else + { + /*Set the endpoint as double buffered*/ + PCD_SET_EP_DBUF(USBx, ep->num); + /*Set buffer address for double buffered mode*/ + PCD_SET_EP_DBUF_ADDR(USBx, ep->num,ep->pmaaddr0, ep->pmaaddr1); + + if (ep->is_in==0) + { + /* Clear the data toggle bits for the endpoint IN/OUT*/ + PCD_CLEAR_RX_DTOG(USBx, ep->num); + PCD_CLEAR_TX_DTOG(USBx, ep->num); + + /* Reset value of the data toggle bits for the endpoint out*/ + PCD_TX_DTOG(USBx, ep->num); + + PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID); + PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS); + } + else + { + /* Clear the data toggle bits for the endpoint IN/OUT*/ + PCD_CLEAR_RX_DTOG(USBx, ep->num); + PCD_CLEAR_TX_DTOG(USBx, ep->num); + PCD_RX_DTOG(USBx, ep->num); + /* Configure DISABLE status for the Endpoint*/ + PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS); + PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS); + } + } + + return HAL_OK; +} + +/** + * @brief De-activate and de-initialize an endpoint + * @param USBx : Selected device + * @param ep: pointer to endpoint structure + * @retval HAL status + */ +HAL_StatusTypeDef USB_DeactivateEndpoint(USB_TypeDef *USBx, USB_EPTypeDef *ep) +{ + if (ep->doublebuffer == 0) + { + if (ep->is_in) + { + PCD_CLEAR_TX_DTOG(USBx, ep->num); + /* Configure DISABLE status for the Endpoint*/ + PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS); + } + else + { + PCD_CLEAR_RX_DTOG(USBx, ep->num); + /* Configure DISABLE status for the Endpoint*/ + PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS); + } + } + /*Double Buffer*/ + else + { + if (ep->is_in==0) + { + /* Clear the data toggle bits for the endpoint IN/OUT*/ + PCD_CLEAR_RX_DTOG(USBx, ep->num); + PCD_CLEAR_TX_DTOG(USBx, ep->num); + + /* Reset value of the data toggle bits for the endpoint out*/ + PCD_TX_DTOG(USBx, ep->num); + + PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS); + PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS); + } + else + { + /* Clear the data toggle bits for the endpoint IN/OUT*/ + PCD_CLEAR_RX_DTOG(USBx, ep->num); + PCD_CLEAR_TX_DTOG(USBx, ep->num); + PCD_RX_DTOG(USBx, ep->num); + /* Configure DISABLE status for the Endpoint*/ + PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS); + PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS); + } + } + + return HAL_OK; +} + +/** + * @brief USB_EPStartXfer : setup and starts a transfer over an EP + * @param USBx : Selected device + * @param ep: pointer to endpoint structure + * @retval HAL status + */ +HAL_StatusTypeDef USB_EPStartXfer(USB_TypeDef *USBx , USB_EPTypeDef *ep, uint8_t dma) +{ + uint16_t pmabuffer = 0; + uint32_t len = ep->xfer_len; + + /* IN endpoint */ + if (ep->is_in == 1) + { + /*Multi packet transfer*/ + if (ep->xfer_len > ep->maxpacket) + { + len=ep->maxpacket; + ep->xfer_len-=len; + } + else + { + len=ep->xfer_len; + ep->xfer_len =0; + } + + /* configure and validate Tx endpoint */ + if (ep->doublebuffer == 0) + { + USB_WritePMA(USBx, ep->xfer_buff, ep->pmaadress, len); + PCD_SET_EP_TX_CNT(USBx, ep->num, len); + } + else + { + /* Write the data to the USB endpoint */ + if (PCD_GET_ENDPOINT(USBx, ep->num)& USB_EP_DTOG_TX) + { + /* Set the Double buffer counter for pmabuffer1 */ + PCD_SET_EP_DBUF1_CNT(USBx, ep->num, ep->is_in, len); + pmabuffer = ep->pmaaddr1; + } + else + { + /* Set the Double buffer counter for pmabuffer0 */ + PCD_SET_EP_DBUF0_CNT(USBx, ep->num, ep->is_in, len); + pmabuffer = ep->pmaaddr0; + } + USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, len); + PCD_FreeUserBuffer(USBx, ep->num, ep->is_in); + } + + PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_VALID); + } + else /* OUT endpoint */ + { + /* Multi packet transfer*/ + if (ep->xfer_len > ep->maxpacket) + { + len=ep->maxpacket; + ep->xfer_len-=len; + } + else + { + len=ep->xfer_len; + ep->xfer_len =0; + } + + /* configure and validate Rx endpoint */ + if (ep->doublebuffer == 0) + { + /*Set RX buffer count*/ + PCD_SET_EP_RX_CNT(USBx, ep->num, len); + } + else + { + /*Set the Double buffer counter*/ + PCD_SET_EP_DBUF1_CNT(USBx, ep->num, ep->is_in, len); + } + + PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID); + } + + return HAL_OK; +} + +/** + * @brief USB_WritePacket : Writes a packet into the Tx FIFO associated + * with the EP/channel + * @param USBx : Selected device + * @param src : pointer to source buffer + * @param ch_ep_num : endpoint or host channel number + * @param len : Number of bytes to write + * @retval HAL status + */ +HAL_StatusTypeDef USB_WritePacket(USB_TypeDef *USBx, uint8_t *src, uint8_t ch_ep_num, uint16_t len) +{ + /* NOTE : - This function is not required by USB Device FS peripheral, it is used + only by USB OTG FS peripheral. + - This function is added to ensure compatibility across platforms. + */ + + /* Prevent unused argument(s) compilation warning */ + UNUSED(USBx); + UNUSED(src); + UNUSED(ch_ep_num); + UNUSED(len); + + return HAL_OK; +} + +/** + * @brief USB_ReadPacket : read a packet from the Tx FIFO associated + * with the EP/channel + * @param USBx : Selected device + * @param dest : destination pointer + * @param len : Number of bytes to read + * @retval pointer to destination buffer + */ +void *USB_ReadPacket(USB_TypeDef *USBx, uint8_t *dest, uint16_t len) +{ + /* NOTE : - This function is not required by USB Device FS peripheral, it is used + only by USB OTG FS peripheral. + - This function is added to ensure compatibility across platforms. + */ + + /* Prevent unused argument(s) compilation warning */ + UNUSED(USBx); + UNUSED(dest); + UNUSED(len); + + return ((void *)NULL); +} + +/** + * @brief USB_EPSetStall : set a stall condition over an EP + * @param USBx : Selected device + * @param ep: pointer to endpoint structure + * @retval HAL status + */ +HAL_StatusTypeDef USB_EPSetStall(USB_TypeDef *USBx , USB_EPTypeDef *ep) +{ + if (ep->num == 0) + { + /* This macro sets STALL status for RX & TX*/ + PCD_SET_EP_TXRX_STATUS(USBx, ep->num, USB_EP_RX_STALL, USB_EP_TX_STALL); + } + else + { + if (ep->is_in) + { + PCD_SET_EP_TX_STATUS(USBx, ep->num , USB_EP_TX_STALL); + } + else + { + PCD_SET_EP_RX_STATUS(USBx, ep->num , USB_EP_RX_STALL); + } + } + return HAL_OK; +} + +/** + * @brief USB_EPClearStall : Clear a stall condition over an EP + * @param USBx : Selected device + * @param ep: pointer to endpoint structure + * @retval HAL status + */ +HAL_StatusTypeDef USB_EPClearStall(USB_TypeDef *USBx, USB_EPTypeDef *ep) +{ + if (ep->is_in) + { + PCD_CLEAR_TX_DTOG(USBx, ep->num); + PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_VALID); + } + else + { + PCD_CLEAR_RX_DTOG(USBx, ep->num); + PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID); + } + return HAL_OK; +} + +/** + * @brief USB_StopDevice : Stop the usb device mode + * @param USBx : Selected device + * @retval HAL status + */ +HAL_StatusTypeDef USB_StopDevice(USB_TypeDef *USBx) +{ + /* disable all interrupts and force USB reset */ + USBx->CNTR = USB_CNTR_FRES; + + /* clear interrupt status register */ + USBx->ISTR = 0; + + /* switch-off device */ + USBx->CNTR = (USB_CNTR_FRES | USB_CNTR_PDWN); + + return HAL_OK; +} + +/** + * @brief USB_SetDevAddress : Stop the usb device mode + * @param USBx : Selected device + * @param address : new device address to be assigned + * This parameter can be a value from 0 to 255 + * @retval HAL status + */ +HAL_StatusTypeDef USB_SetDevAddress (USB_TypeDef *USBx, uint8_t address) +{ + if(address == 0) + { + /* set device address and enable function */ + USBx->DADDR = USB_DADDR_EF; + } + + return HAL_OK; +} + +/** + * @brief USB_DevConnect : Connect the USB device by enabling the pull-up/pull-down + * @param USBx : Selected device + * @retval HAL status + */ +HAL_StatusTypeDef USB_DevConnect (USB_TypeDef *USBx) +{ + /* Enabling DP Pull-Down bit to Connect internal pull-up on USB DP line */ + USB->BCDR |= USB_BCDR_DPPU; + + return HAL_OK; +} + +/** + * @brief USB_DevDisconnect : Disconnect the USB device by disabling the pull-up/pull-down + * @param USBx : Selected device + * @retval HAL status + */ +HAL_StatusTypeDef USB_DevDisconnect (USB_TypeDef *USBx) +{ + /* Disable DP Pull-Down bit*/ + USB->BCDR &= ~(USB_BCDR_DPPU); + + return HAL_OK; +} + +/** + * @brief USB_ReadInterrupts: return the global USB interrupt status + * @param USBx : Selected device + * @retval HAL status + */ +uint32_t USB_ReadInterrupts (USB_TypeDef *USBx) +{ + uint32_t tmpreg = 0; + + tmpreg = USBx->ISTR; + return tmpreg; +} + +/** + * @brief USB_ReadDevAllOutEpInterrupt: return the USB device OUT endpoints interrupt status + * @param USBx : Selected device + * @retval HAL status + */ +uint32_t USB_ReadDevAllOutEpInterrupt (USB_TypeDef *USBx) +{ + /* NOTE : - This function is not required by USB Device FS peripheral, it is used + only by USB OTG FS peripheral. + - This function is added to ensure compatibility across platforms. + */ + + /* Prevent unused argument(s) compilation warning */ + UNUSED(USBx); + + return (0); +} + +/** + * @brief USB_ReadDevAllInEpInterrupt: return the USB device IN endpoints interrupt status + * @param USBx : Selected device + * @retval HAL status + */ +uint32_t USB_ReadDevAllInEpInterrupt (USB_TypeDef *USBx) +{ + /* NOTE : - This function is not required by USB Device FS peripheral, it is used + only by USB OTG FS peripheral. + - This function is added to ensure compatibility across platforms. + */ + + /* Prevent unused argument(s) compilation warning */ + UNUSED(USBx); + + return (0); +} + +/** + * @brief Returns Device OUT EP Interrupt register + * @param USBx : Selected device + * @param epnum : endpoint number + * This parameter can be a value from 0 to 15 + * @retval Device OUT EP Interrupt register + */ +uint32_t USB_ReadDevOutEPInterrupt (USB_TypeDef *USBx , uint8_t epnum) +{ + /* NOTE : - This function is not required by USB Device FS peripheral, it is used + only by USB OTG FS peripheral. + - This function is added to ensure compatibility across platforms. + */ + + /* Prevent unused argument(s) compilation warning */ + UNUSED(USBx); + UNUSED(epnum); + + return (0); +} + +/** + * @brief Returns Device IN EP Interrupt register + * @param USBx : Selected device + * @param epnum : endpoint number + * This parameter can be a value from 0 to 15 + * @retval Device IN EP Interrupt register + */ +uint32_t USB_ReadDevInEPInterrupt (USB_TypeDef *USBx , uint8_t epnum) +{ + /* NOTE : - This function is not required by USB Device FS peripheral, it is used + only by USB OTG FS peripheral. + - This function is added to ensure compatibility across platforms. + */ + + /* Prevent unused argument(s) compilation warning */ + UNUSED(USBx); + UNUSED(epnum); + + return (0); +} + +/** + * @brief USB_ClearInterrupts: clear a USB interrupt + * @param USBx : Selected device + * @param interrupt : interrupt flag + * @retval None + */ +void USB_ClearInterrupts (USB_TypeDef *USBx, uint32_t interrupt) +{ + /* NOTE : - This function is not required by USB Device FS peripheral, it is used + only by USB OTG FS peripheral. + - This function is added to ensure compatibility across platforms. + */ + + /* Prevent unused argument(s) compilation warning */ + UNUSED(USBx); + UNUSED(interrupt); +} + +/** + * @brief Prepare the EP0 to start the first control setup + * @param USBx : Selected device + * @param psetup : pointer to setup packet + * @retval HAL status + */ +HAL_StatusTypeDef USB_EP0_OutStart(USB_TypeDef *USBx, uint8_t dma ,uint8_t *psetup) +{ + /* NOTE : - This function is not required by USB Device FS peripheral, it is used + only by USB OTG FS peripheral. + - This function is added to ensure compatibility across platforms. + */ + + /* Prevent unused argument(s) compilation warning */ + UNUSED(USBx); + UNUSED(psetup); + UNUSED(dma); + + return HAL_OK; +} + +/** + * @brief USB_ActivateRemoteWakeup : active remote wakeup signalling + * @param USBx : Selected device + * @retval HAL status + */ +HAL_StatusTypeDef USB_ActivateRemoteWakeup(USB_TypeDef *USBx) +{ + USBx->CNTR |= USB_CNTR_RESUME; + + return HAL_OK; +} + +/** + * @brief USB_DeActivateRemoteWakeup : de-active remote wakeup signalling + * @param USBx : Selected device + * @retval HAL status + */ +HAL_StatusTypeDef USB_DeActivateRemoteWakeup(USB_TypeDef *USBx) +{ + USBx->CNTR &= ~(USB_CNTR_RESUME); + return HAL_OK; +} + +/** + * @brief Copy a buffer from user memory area to packet memory area (PMA) + * @param USBx : pointer to USB register. + * @param pbUsrBuf : pointer to user memory area. + * @param wPMABufAddr : address into PMA. + * @param wNBytes : number of bytes to be copied. + * @retval None + */ +void USB_WritePMA(USB_TypeDef *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes) +{ + uint32_t n = (wNBytes + 1) >> 1; + uint32_t i; + uint16_t temp1, temp2; + uint16_t *pdwVal; + pdwVal = (uint16_t *)(wPMABufAddr + (uint32_t)USBx + 0x400); + + for (i = n; i != 0; i--) + { + temp1 = (uint16_t) * pbUsrBuf; + pbUsrBuf++; + temp2 = temp1 | (uint16_t) * pbUsrBuf << 8; + *pdwVal++ = temp2; + pbUsrBuf++; + } +} + +/** + * @brief Copy a buffer from user memory area to packet memory area (PMA) + * @param USBx : pointer to USB register. +* @param pbUsrBuf : pointer to user memory area. + * @param wPMABufAddr : address into PMA. + * @param wNBytes : number of bytes to be copied. + * @retval None + */ +void USB_ReadPMA(USB_TypeDef *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes) +{ + uint32_t n = (wNBytes + 1) >> 1; + uint32_t i; + uint16_t *pdwVal; + pdwVal = (uint16_t *)(wPMABufAddr + (uint32_t)USBx + 0x400); + for (i = n; i != 0; i--) + { + *(uint16_t*)pbUsrBuf++ = *pdwVal++; + pbUsrBuf++; + } +} +#endif /* USB */ +/** + * @} + */ +/** + * @} + */ + +#if defined (USB_OTG_FS) +/** @addtogroup USB_LL_Private_Functions + * @{ + */ +/** + * @brief Reset the USB Core (needed after USB clock settings change) + * @param USBx : Selected device + * @retval HAL status + */ +static HAL_StatusTypeDef USB_CoreReset(USB_OTG_GlobalTypeDef *USBx) +{ + uint32_t count = 0; + + /* Wait for AHB master IDLE state. */ + do + { + if (++count > 200000) + { + return HAL_TIMEOUT; + } + } + while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0); + + /* Core Soft Reset */ + count = 0; + USBx->GRSTCTL |= USB_OTG_GRSTCTL_CSRST; + + do + { + if (++count > 200000) + { + return HAL_TIMEOUT; + } + } + while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_CSRST) == USB_OTG_GRSTCTL_CSRST); + + return HAL_OK; +} +/** + * @} + */ +#endif /* USB_OTG_FS */ + +#endif /* STM32L432xx || STM32L433xx || STM32L442xx || STM32L443xx || */ + /* STM32L452xx || STM32L462xx || */ + /* STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx || */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#endif /* defined (HAL_PCD_MODULE_ENABLED) || defined (HAL_HCD_MODULE_ENABLED) */ +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/main.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/main.h new file mode 100644 index 0000000..d9797db --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/main.h @@ -0,0 +1,100 @@ +/** + ****************************************************************************** + * @file : main.h + * @brief : Header for main.c file. + * This file contains the common defines of the application. + ****************************************************************************** + * This notice applies to any and all portions of this file + * that are not between comment pairs USER CODE BEGIN and + * USER CODE END. Other portions of this file, whether + * inserted by the user or by software development tools + * are owned by their respective copyright owners. + * + * Copyright (c) 2018 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. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (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 to prevent recursive inclusion -------------------------------------*/ +#ifndef __MAIN_H__ +#define __MAIN_H__ + +/* Includes ------------------------------------------------------------------*/ + +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* Private define ------------------------------------------------------------*/ + +#define B1_Pin GPIO_PIN_13 +#define B1_GPIO_Port GPIOC +#define USART_TX_Pin GPIO_PIN_2 +#define USART_TX_GPIO_Port GPIOA +#define USART_RX_Pin GPIO_PIN_3 +#define USART_RX_GPIO_Port GPIOA +#define LD2_Pin GPIO_PIN_5 +#define LD2_GPIO_Port GPIOA +#define TMS_Pin GPIO_PIN_13 +#define TMS_GPIO_Port GPIOA +#define TCK_Pin GPIO_PIN_14 +#define TCK_GPIO_Port GPIOA +#define SWO_Pin GPIO_PIN_3 +#define SWO_GPIO_Port GPIOB + +/* ########################## Assert Selection ############################## */ +/** + * @brief Uncomment the line below to expanse the "assert_param" macro in the + * HAL drivers code + */ +/* #define USE_FULL_ASSERT 1U */ + +/* USER CODE BEGIN Private defines */ + +/* USER CODE END Private defines */ + +#ifdef __cplusplus + extern "C" { +#endif +void _Error_Handler(char *, int); + +#define Error_Handler() _Error_Handler(__FILE__, __LINE__) +#ifdef __cplusplus +} +#endif + +#endif /* __MAIN_H__ */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/stm32l4xx_hal_conf.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/stm32l4xx_hal_conf.h new file mode 100644 index 0000000..0d3dd60 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/stm32l4xx_hal_conf.h @@ -0,0 +1,430 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_conf.h + * @brief HAL configuration file. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2018 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_CONF_H +#define __STM32L4xx_HAL_CONF_H + +#ifdef __cplusplus + extern "C" { +#endif + +#include "main.h" +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* ########################## Module Selection ############################## */ +/** + * @brief This is the list of modules to be used in the HAL driver + */ + +#define HAL_MODULE_ENABLED +/*#define HAL_ADC_MODULE_ENABLED */ +/*#define HAL_CRYP_MODULE_ENABLED */ +/*#define HAL_CAN_MODULE_ENABLED */ +/*#define HAL_COMP_MODULE_ENABLED */ +/*#define HAL_CRC_MODULE_ENABLED */ +/*#define HAL_CRYP_MODULE_ENABLED */ +/*#define HAL_DAC_MODULE_ENABLED */ +/*#define HAL_DCMI_MODULE_ENABLED */ +/*#define HAL_DMA2D_MODULE_ENABLED */ +/*#define HAL_DFSDM_MODULE_ENABLED */ +/*#define HAL_DSI_MODULE_ENABLED */ +/*#define HAL_FIREWALL_MODULE_ENABLED */ +/*#define HAL_GFXMMU_MODULE_ENABLED */ +/*#define HAL_HCD_MODULE_ENABLED */ +/*#define HAL_HASH_MODULE_ENABLED */ +/*#define HAL_I2S_MODULE_ENABLED */ +/*#define HAL_IRDA_MODULE_ENABLED */ +/*#define HAL_IWDG_MODULE_ENABLED */ +/*#define HAL_LTDC_MODULE_ENABLED */ +/*#define HAL_LCD_MODULE_ENABLED */ +/*#define HAL_LPTIM_MODULE_ENABLED */ +/*#define HAL_NAND_MODULE_ENABLED */ +/*#define HAL_NOR_MODULE_ENABLED */ +/*#define HAL_OPAMP_MODULE_ENABLED */ +/*#define HAL_OSPI_MODULE_ENABLED */ +/*#define HAL_OSPI_MODULE_ENABLED */ +#define HAL_PCD_MODULE_ENABLED +/*#define HAL_QSPI_MODULE_ENABLED */ +/*#define HAL_QSPI_MODULE_ENABLED */ +#define HAL_RNG_MODULE_ENABLED +#define HAL_RTC_MODULE_ENABLED +/*#define HAL_SAI_MODULE_ENABLED */ +/*#define HAL_SD_MODULE_ENABLED */ +/*#define HAL_SMBUS_MODULE_ENABLED */ +/*#define HAL_SMARTCARD_MODULE_ENABLED */ +/*#define HAL_SPI_MODULE_ENABLED */ +/*#define HAL_SRAM_MODULE_ENABLED */ +/*#define HAL_SWPMI_MODULE_ENABLED */ +/*#define HAL_TIM_MODULE_ENABLED */ +/*#define HAL_TSC_MODULE_ENABLED */ +#define HAL_UART_MODULE_ENABLED +/*#define HAL_USART_MODULE_ENABLED */ +/*#define HAL_WWDG_MODULE_ENABLED */ +#define HAL_GPIO_MODULE_ENABLED +#define HAL_I2C_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED + +/* ########################## Oscillator Values adaptation ####################*/ +/** + * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSE is used as system clock source, directly or through the PLL). + */ +#if !defined (HSE_VALUE) + #define HSE_VALUE ((uint32_t)8000000U) /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSE_STARTUP_TIMEOUT) + #define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief Internal Multiple Speed oscillator (MSI) default value. + * This value is the default MSI range value after Reset. + */ +#if !defined (MSI_VALUE) + #define MSI_VALUE ((uint32_t)48000000U) /*!< Value of the Internal oscillator in Hz*/ +#endif /* MSI_VALUE */ +/** + * @brief Internal High Speed oscillator (HSI) value. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSI is used as system clock source, directly or through the PLL). + */ +#if !defined (HSI_VALUE) + #define HSI_VALUE ((uint32_t)16000000U) /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @brief Internal High Speed oscillator (HSI48) value for USB FS, SDMMC and RNG. + * This internal oscillator is mainly dedicated to provide a high precision clock to + * the USB peripheral by means of a special Clock Recovery System (CRS) circuitry. + * When the CRS is not used, the HSI48 RC oscillator runs on it default frequency + * which is subject to manufacturing process variations. + */ +#if !defined (HSI48_VALUE) + #define HSI48_VALUE ((uint32_t)48000000U) /*!< Value of the Internal High Speed oscillator for USB FS/SDMMC/RNG in Hz. + The real value my vary depending on manufacturing process variations.*/ +#endif /* HSI48_VALUE */ + +/** + * @brief Internal Low Speed oscillator (LSI) value. + */ +#if !defined (LSI_VALUE) + #define LSI_VALUE ((uint32_t)32000U) /*!< LSI Typical Value in Hz*/ +#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz + The real value may vary depending on the variations + in voltage and temperature.*/ + +/** + * @brief External Low Speed oscillator (LSE) value. + * This value is used by the UART, RTC HAL module to compute the system frequency + */ +#if !defined (LSE_VALUE) + #define LSE_VALUE ((uint32_t)32768U) /*!< Value of the External oscillator in Hz*/ +#endif /* LSE_VALUE */ + +#if !defined (LSE_STARTUP_TIMEOUT) + #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief External clock source for SAI1 peripheral + * This value is used by the RCC HAL module to compute the SAI1 & SAI2 clock source + * frequency. + */ +#if !defined (EXTERNAL_SAI1_CLOCK_VALUE) + #define EXTERNAL_SAI1_CLOCK_VALUE ((uint32_t)2097000U) /*!< Value of the SAI1 External clock source in Hz*/ +#endif /* EXTERNAL_SAI1_CLOCK_VALUE */ + +/** + * @brief External clock source for SAI2 peripheral + * This value is used by the RCC HAL module to compute the SAI1 & SAI2 clock source + * frequency. + */ +#if !defined (EXTERNAL_SAI2_CLOCK_VALUE) + #define EXTERNAL_SAI2_CLOCK_VALUE ((uint32_t)2097000U) /*!< Value of the SAI2 External clock source in Hz*/ +#endif /* EXTERNAL_SAI2_CLOCK_VALUE */ + +/* Tip: To avoid modifying this file each time you need to use different HSE, + === you can define the HSE value in your toolchain compiler preprocessor. */ + +/* ########################### System Configuration ######################### */ +/** + * @brief This is the HAL system configuration section + */ + +#define VDD_VALUE ((uint32_t)3300U) /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY ((uint32_t)0U) /*!< tick interrupt priority */ +#define USE_RTOS 0U +#define PREFETCH_ENABLE 1U +#define INSTRUCTION_CACHE_ENABLE 1U +#define DATA_CACHE_ENABLE 1U + +/* ########################## Assert Selection ############################## */ +/** + * @brief Uncomment the line below to expanse the "assert_param" macro in the + * HAL drivers code + */ +/* #define USE_FULL_ASSERT 1U */ + +/* ################## SPI peripheral configuration ########################## */ + +/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver + * Activated: CRC code is present inside driver + * Deactivated: CRC code cleaned from driver + */ + +#define USE_SPI_CRC 0U + +/* Includes ------------------------------------------------------------------*/ +/** + * @brief Include module's header file + */ + +#ifdef HAL_RCC_MODULE_ENABLED + #include "stm32l4xx_hal_rcc.h" + #include "stm32l4xx_hal_rcc_ex.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED + #include "stm32l4xx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_DMA_MODULE_ENABLED + #include "stm32l4xx_hal_dma.h" + #include "stm32l4xx_hal_dma_ex.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_DFSDM_MODULE_ENABLED + #include "stm32l4xx_hal_dfsdm.h" +#endif /* HAL_DFSDM_MODULE_ENABLED */ + +#ifdef HAL_CORTEX_MODULE_ENABLED + #include "stm32l4xx_hal_cortex.h" +#endif /* HAL_CORTEX_MODULE_ENABLED */ + +#ifdef HAL_ADC_MODULE_ENABLED + #include "stm32l4xx_hal_adc.h" +#endif /* HAL_ADC_MODULE_ENABLED */ + +#ifdef HAL_CAN_MODULE_ENABLED + #include "stm32l4xx_hal_can.h" +#endif /* HAL_CAN_MODULE_ENABLED */ + +#ifdef HAL_COMP_MODULE_ENABLED + #include "stm32l4xx_hal_comp.h" +#endif /* HAL_COMP_MODULE_ENABLED */ + +#ifdef HAL_CRC_MODULE_ENABLED + #include "stm32l4xx_hal_crc.h" +#endif /* HAL_CRC_MODULE_ENABLED */ + +#ifdef HAL_CRYP_MODULE_ENABLED + #include "stm32l4xx_hal_cryp.h" +#endif /* HAL_CRYP_MODULE_ENABLED */ + +#ifdef HAL_DAC_MODULE_ENABLED + #include "stm32l4xx_hal_dac.h" +#endif /* HAL_DAC_MODULE_ENABLED */ + +#ifdef HAL_DCMI_MODULE_ENABLED + #include "stm32l4xx_hal_dcmi.h" +#endif /* HAL_DCMI_MODULE_ENABLED */ + +#ifdef HAL_DMA2D_MODULE_ENABLED + #include "stm32l4xx_hal_dma2d.h" +#endif /* HAL_DMA2D_MODULE_ENABLED */ + +#ifdef HAL_DSI_MODULE_ENABLED + #include "stm32l4xx_hal_dsi.h" +#endif /* HAL_DSI_MODULE_ENABLED */ + +#ifdef HAL_FIREWALL_MODULE_ENABLED + #include "stm32l4xx_hal_firewall.h" +#endif /* HAL_FIREWALL_MODULE_ENABLED */ + +#ifdef HAL_FLASH_MODULE_ENABLED + #include "stm32l4xx_hal_flash.h" +#endif /* HAL_FLASH_MODULE_ENABLED */ + +#ifdef HAL_HASH_MODULE_ENABLED + #include "stm32l4xx_hal_hash.h" +#endif /* HAL_HASH_MODULE_ENABLED */ + +#ifdef HAL_SRAM_MODULE_ENABLED + #include "stm32l4xx_hal_sram.h" +#endif /* HAL_SRAM_MODULE_ENABLED */ + +#ifdef HAL_NOR_MODULE_ENABLED + #include "stm32l4xx_hal_nor.h" +#endif /* HAL_NOR_MODULE_ENABLED */ + +#ifdef HAL_NAND_MODULE_ENABLED + #include "stm32l4xx_hal_nand.h" +#endif /* HAL_NAND_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED + #include "stm32l4xx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED + #include "stm32l4xx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_LCD_MODULE_ENABLED + #include "stm32l4xx_hal_lcd.h" +#endif /* HAL_LCD_MODULE_ENABLED */ + +#ifdef HAL_LPTIM_MODULE_ENABLED + #include "stm32l4xx_hal_lptim.h" +#endif /* HAL_LPTIM_MODULE_ENABLED */ + +#ifdef HAL_LTDC_MODULE_ENABLED + #include "stm32l4xx_hal_ltdc.h" +#endif /* HAL_LTDC_MODULE_ENABLED */ + +#ifdef HAL_OPAMP_MODULE_ENABLED + #include "stm32l4xx_hal_opamp.h" +#endif /* HAL_OPAMP_MODULE_ENABLED */ + +#ifdef HAL_OSPI_MODULE_ENABLED + #include "stm32l4xx_hal_ospi.h" +#endif /* HAL_OSPI_MODULE_ENABLED */ + +#ifdef HAL_PWR_MODULE_ENABLED + #include "stm32l4xx_hal_pwr.h" +#endif /* HAL_PWR_MODULE_ENABLED */ + +#ifdef HAL_QSPI_MODULE_ENABLED + #include "stm32l4xx_hal_qspi.h" +#endif /* HAL_QSPI_MODULE_ENABLED */ + +#ifdef HAL_RNG_MODULE_ENABLED + #include "stm32l4xx_hal_rng.h" +#endif /* HAL_RNG_MODULE_ENABLED */ + +#ifdef HAL_RTC_MODULE_ENABLED + #include "stm32l4xx_hal_rtc.h" +#endif /* HAL_RTC_MODULE_ENABLED */ + +#ifdef HAL_SAI_MODULE_ENABLED + #include "stm32l4xx_hal_sai.h" +#endif /* HAL_SAI_MODULE_ENABLED */ + +#ifdef HAL_SD_MODULE_ENABLED + #include "stm32l4xx_hal_sd.h" +#endif /* HAL_SD_MODULE_ENABLED */ + +#ifdef HAL_SMBUS_MODULE_ENABLED + #include "stm32l4xx_hal_smbus.h" +#endif /* HAL_SMBUS_MODULE_ENABLED */ + +#ifdef HAL_SPI_MODULE_ENABLED + #include "stm32l4xx_hal_spi.h" +#endif /* HAL_SPI_MODULE_ENABLED */ + +#ifdef HAL_SWPMI_MODULE_ENABLED + #include "stm32l4xx_hal_swpmi.h" +#endif /* HAL_SWPMI_MODULE_ENABLED */ + +#ifdef HAL_TIM_MODULE_ENABLED + #include "stm32l4xx_hal_tim.h" +#endif /* HAL_TIM_MODULE_ENABLED */ + +#ifdef HAL_TSC_MODULE_ENABLED + #include "stm32l4xx_hal_tsc.h" +#endif /* HAL_TSC_MODULE_ENABLED */ + +#ifdef HAL_UART_MODULE_ENABLED + #include "stm32l4xx_hal_uart.h" +#endif /* HAL_UART_MODULE_ENABLED */ + +#ifdef HAL_USART_MODULE_ENABLED + #include "stm32l4xx_hal_usart.h" +#endif /* HAL_USART_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED + #include "stm32l4xx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_SMARTCARD_MODULE_ENABLED + #include "stm32l4xx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + +#ifdef HAL_WWDG_MODULE_ENABLED + #include "stm32l4xx_hal_wwdg.h" +#endif /* HAL_WWDG_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED + #include "stm32l4xx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +#ifdef HAL_HCD_MODULE_ENABLED + #include "stm32l4xx_hal_hcd.h" +#endif /* HAL_HCD_MODULE_ENABLED */ + +#ifdef HAL_GFXMMU_MODULE_ENABLED + #include "stm32l4xx_hal_gfxmmu.h" +#endif /* HAL_GFXMMU_MODULE_ENABLED */ + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr: If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ + #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ + void assert_failed(uint8_t* file, uint32_t line); +#else + #define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_HAL_CONF_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/stm32l4xx_it.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/stm32l4xx_it.h new file mode 100644 index 0000000..a346397 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/stm32l4xx_it.h @@ -0,0 +1,59 @@ +/** + ****************************************************************************** + * @file stm32l4xx_it.h + * @brief This file contains the headers of the interrupt handlers. + ****************************************************************************** + * + * COPYRIGHT(c) 2018 STMicroelectronics + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_IT_H +#define __STM32L4xx_IT_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" +#include "main.h" +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ + +void SysTick_Handler(void); +void OTG_FS_IRQHandler(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_IT_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/usb_device.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/usb_device.h new file mode 100644 index 0000000..3c661ea --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/usb_device.h @@ -0,0 +1,115 @@ +/** + ****************************************************************************** + * @file : usb_device.h + * @version : v2.0_Cube + * @brief : Header for usb_device.c file. + ****************************************************************************** + * This notice applies to any and all portions of this file + * that are not between comment pairs USER CODE BEGIN and + * USER CODE END. Other portions of this file, whether + * inserted by the user or by software development tools + * are owned by their respective copyright owners. + * + * Copyright (c) 2018 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. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (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 to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_DEVICE__H__ +#define __USB_DEVICE__H__ + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx.h" +#include "stm32l4xx_hal.h" +#include "usbd_def.h" + +/* USER CODE BEGIN INCLUDE */ + void MX_USB_DEVICE_DeInit(void); + +/* USER CODE END INCLUDE */ + +/** @addtogroup USBD_OTG_DRIVER + * @{ + */ + +/** @defgroup USBD_DEVICE USBD_DEVICE + * @brief Device file for Usb otg low level driver. + * @{ + */ + +/** @defgroup USBD_DEVICE_Exported_Variables USBD_DEVICE_Exported_Variables + * @brief Public variables. + * @{ + */ + +/** USB device core handle. */ +extern USBD_HandleTypeDef hUsbDeviceFS; + +/** + * @} + */ + +/** @defgroup USBD_DEVICE_Exported_FunctionsPrototype USBD_DEVICE_Exported_FunctionsPrototype + * @brief Declaration of public functions for Usb device. + * @{ + */ + +/** USB Device initialization function. */ +void MX_USB_DEVICE_Init(void); + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USB_DEVICE__H__ */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/usbd_cdc_if.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/usbd_cdc_if.h new file mode 100644 index 0000000..605b778 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/usbd_cdc_if.h @@ -0,0 +1,158 @@ +/** + ****************************************************************************** + * @file : usbd_cdc_if.h + * @version : v2.0_Cube + * @brief : Header for usbd_cdc_if.c file. + ****************************************************************************** + * This notice applies to any and all portions of this file + * that are not between comment pairs USER CODE BEGIN and + * USER CODE END. Other portions of this file, whether + * inserted by the user or by software development tools + * are owned by their respective copyright owners. + * + * Copyright (c) 2018 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. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (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 to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_CDC_IF_H__ +#define __USBD_CDC_IF_H__ + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_cdc.h" + +/* USER CODE BEGIN INCLUDE */ + +/* USER CODE END INCLUDE */ + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY + * @brief For Usb device. + * @{ + */ + +/** @defgroup USBD_CDC_IF USBD_CDC_IF + * @brief Usb VCP device module + * @{ + */ + +/** @defgroup USBD_CDC_IF_Exported_Defines USBD_CDC_IF_Exported_Defines + * @brief Defines. + * @{ + */ +/* USER CODE BEGIN EXPORTED_DEFINES */ + +/* USER CODE END EXPORTED_DEFINES */ + +/** + * @} + */ + +/** @defgroup USBD_CDC_IF_Exported_Types USBD_CDC_IF_Exported_Types + * @brief Types. + * @{ + */ + +/* USER CODE BEGIN EXPORTED_TYPES */ + +/* USER CODE END EXPORTED_TYPES */ + +/** + * @} + */ + +/** @defgroup USBD_CDC_IF_Exported_Macros USBD_CDC_IF_Exported_Macros + * @brief Aliases. + * @{ + */ + +/* USER CODE BEGIN EXPORTED_MACRO */ + +/* USER CODE END EXPORTED_MACRO */ + +/** + * @} + */ + +/** @defgroup USBD_CDC_IF_Exported_Variables USBD_CDC_IF_Exported_Variables + * @brief Public variables. + * @{ + */ + +/** CDC Interface callback. */ +extern USBD_CDC_ItfTypeDef USBD_Interface_fops_FS; + +/* USER CODE BEGIN EXPORTED_VARIABLES */ + +/* USER CODE END EXPORTED_VARIABLES */ + +/** + * @} + */ + +/** @defgroup USBD_CDC_IF_Exported_FunctionsPrototype USBD_CDC_IF_Exported_FunctionsPrototype + * @brief Public functions declaration. + * @{ + */ + +uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len); + +/* USER CODE BEGIN EXPORTED_FUNCTIONS */ + +/* USER CODE END EXPORTED_FUNCTIONS */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBD_CDC_IF_H__ */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/usbd_conf.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/usbd_conf.h new file mode 100644 index 0000000..df2e31c --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/usbd_conf.h @@ -0,0 +1,204 @@ +/** + ****************************************************************************** + * @file : usbd_conf.h + * @version : v2.0_Cube + * @brief : Header for usbd_conf.c file. + ****************************************************************************** + * This notice applies to any and all portions of this file + * that are not between comment pairs USER CODE BEGIN and + * USER CODE END. Other portions of this file, whether + * inserted by the user or by software development tools + * are owned by their respective copyright owners. + * + * Copyright (c) 2018 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. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (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 to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_CONF__H__ +#define __USBD_CONF__H__ + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include +#include +#include +#include "stm32l4xx.h" +#include "stm32l4xx_hal.h" + +/* USER CODE BEGIN INCLUDE */ + +/* USER CODE END INCLUDE */ + +/** @addtogroup USBD_OTG_DRIVER + * @brief Driver for Usb device. + * @{ + */ + +/** @defgroup USBD_CONF USBD_CONF + * @brief Configuration file for Usb otg low level driver. + * @{ + */ + +/** @defgroup USBD_CONF_Exported_Variables USBD_CONF_Exported_Variables + * @brief Public variables. + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_CONF_Exported_Defines USBD_CONF_Exported_Defines + * @brief Defines for configuration of the Usb device. + * @{ + */ + +/*---------- -----------*/ +#define USBD_MAX_NUM_INTERFACES 1 +/*---------- -----------*/ +#define USBD_MAX_NUM_CONFIGURATION 1 +/*---------- -----------*/ +#define USBD_MAX_STR_DESC_SIZ 512 +/*---------- -----------*/ +#define USBD_SUPPORT_USER_STRING 0 +/*---------- -----------*/ +#define USBD_DEBUG_LEVEL 0 +/*---------- -----------*/ +#define USBD_LPM_ENABLED 1 +/*---------- -----------*/ +#define USBD_SELF_POWERED 1 + +/****************************************/ +/* #define for FS and HS identification */ +#define DEVICE_FS 0 + +/** + * @} + */ + +/** @defgroup USBD_CONF_Exported_Macros USBD_CONF_Exported_Macros + * @brief Aliases. + * @{ + */ + +/* Memory management macros */ + +/** Alias for memory allocation. */ +#define USBD_malloc (uint32_t *)USBD_static_malloc + +/** Alias for memory release. */ +#define USBD_free USBD_static_free + +/** Alias for memory set. */ +#define USBD_memset /* Not used */ + +/** Alias for memory copy. */ +#define USBD_memcpy /* Not used */ + +/** Alias for delay. */ +#define USBD_Delay HAL_Delay + +/* DEBUG macros */ + +#if (USBD_DEBUG_LEVEL > 0) +#define USBD_UsrLog(...) printf(__VA_ARGS__);\ + printf("\n"); +#else +#define USBD_UsrLog(...) +#endif + +#if (USBD_DEBUG_LEVEL > 1) + +#define USBD_ErrLog(...) printf("ERROR: ") ;\ + printf(__VA_ARGS__);\ + printf("\n"); +#else +#define USBD_ErrLog(...) +#endif + +#if (USBD_DEBUG_LEVEL > 2) +#define USBD_DbgLog(...) printf("DEBUG : ") ;\ + printf(__VA_ARGS__);\ + printf("\n"); +#else +#define USBD_DbgLog(...) +#endif + +/** + * @} + */ + +/** @defgroup USBD_CONF_Exported_Types USBD_CONF_Exported_Types + * @brief Types. + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_CONF_Exported_FunctionsPrototype USBD_CONF_Exported_FunctionsPrototype + * @brief Declaration of public functions for Usb device. + * @{ + */ + +/* Exported functions -------------------------------------------------------*/ +void *USBD_static_malloc(uint32_t size); +void USBD_static_free(void *p); + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBD_CONF__H__ */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/usbd_desc.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/usbd_desc.h new file mode 100644 index 0000000..98fd79d --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Inc/usbd_desc.h @@ -0,0 +1,156 @@ +/** + ****************************************************************************** + * @file : usbd_desc.h + * @version : v2.0_Cube + * @brief : Header for usbd_desc.c file. + ****************************************************************************** + * This notice applies to any and all portions of this file + * that are not between comment pairs USER CODE BEGIN and + * USER CODE END. Other portions of this file, whether + * inserted by the user or by software development tools + * are owned by their respective copyright owners. + * + * Copyright (c) 2018 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. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (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 to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_DESC__H__ +#define __USBD_DESC__H__ + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_def.h" + +/* USER CODE BEGIN INCLUDE */ + +/* USER CODE END INCLUDE */ + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USBD_DESC USBD_DESC + * @brief Usb device descriptors module. + * @{ + */ + +/** @defgroup USBD_DESC_Exported_Defines USBD_DESC_Exported_Defines + * @brief Defines. + * @{ + */ + +/* USER CODE BEGIN EXPORTED_DEFINES */ + +/* USER CODE END EXPORTED_DEFINES */ + +/** + * @} + */ + +/** @defgroup USBD_DESC_Exported_TypesDefinitions USBD_DESC_Exported_TypesDefinitions + * @brief Types. + * @{ + */ + +/* USER CODE BEGIN EXPORTED_TYPES */ + +/* USER CODE END EXPORTED_TYPES */ + +/** + * @} + */ + +/** @defgroup USBD_DESC_Exported_Macros USBD_DESC_Exported_Macros + * @brief Aliases. + * @{ + */ + +/* USER CODE BEGIN EXPORTED_MACRO */ + +/* USER CODE END EXPORTED_MACRO */ + +/** + * @} + */ + +/** @defgroup USBD_DESC_Exported_Variables USBD_DESC_Exported_Variables + * @brief Public variables. + * @{ + */ + +/** Descriptor for the Usb device. */ +extern USBD_DescriptorsTypeDef FS_Desc; + +/* USER CODE BEGIN EXPORTED_VARIABLES */ + +/* USER CODE END EXPORTED_VARIABLES */ + +/** + * @} + */ + +/** @defgroup USBD_DESC_Exported_FunctionsPrototype USBD_DESC_Exported_FunctionsPrototype + * @brief Public functions declaration. + * @{ + */ + +/* USER CODE BEGIN EXPORTED_FUNCTIONS */ + +/* USER CODE END EXPORTED_FUNCTIONS */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBD_DESC__H__ */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc/usbd_cdc.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc/usbd_cdc.h new file mode 100644 index 0000000..36badcd --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc/usbd_cdc.h @@ -0,0 +1,179 @@ +/** + ****************************************************************************** + * @file usbd_cdc.h + * @author MCD Application Team + * @version V2.4.2 + * @date 11-December-2015 + * @brief header file for the usbd_cdc.c file. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2015 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (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.st.com/software_license_agreement_liberty_v2 + * + * 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_CDC_H +#define __USB_CDC_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_ioreq.h" + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup usbd_cdc + * @brief This file is the Header file for usbd_cdc.c + * @{ + */ + + +/** @defgroup usbd_cdc_Exported_Defines + * @{ + */ +#define CDC_IN_EP 0x81 /* EP1 for data IN */ +#define CDC_OUT_EP 0x01 /* EP1 for data OUT */ +#define CDC_CMD_EP 0x82 /* EP2 for CDC commands */ + +/* CDC Endpoints parameters: you can fine tune these values depending on the needed baudrates and performance. */ +#define CDC_DATA_HS_MAX_PACKET_SIZE 512 /* Endpoint IN & OUT Packet size */ +#define CDC_DATA_FS_MAX_PACKET_SIZE 64 /* Endpoint IN & OUT Packet size */ +#define CDC_CMD_PACKET_SIZE 8 /* Control Endpoint Packet size */ + +#define USB_CDC_CONFIG_DESC_SIZ 67 +#define CDC_DATA_HS_IN_PACKET_SIZE CDC_DATA_HS_MAX_PACKET_SIZE +#define CDC_DATA_HS_OUT_PACKET_SIZE CDC_DATA_HS_MAX_PACKET_SIZE + +#define CDC_DATA_FS_IN_PACKET_SIZE CDC_DATA_FS_MAX_PACKET_SIZE +#define CDC_DATA_FS_OUT_PACKET_SIZE CDC_DATA_FS_MAX_PACKET_SIZE + +/*---------------------------------------------------------------------*/ +/* CDC definitions */ +/*---------------------------------------------------------------------*/ +#define CDC_SEND_ENCAPSULATED_COMMAND 0x00 +#define CDC_GET_ENCAPSULATED_RESPONSE 0x01 +#define CDC_SET_COMM_FEATURE 0x02 +#define CDC_GET_COMM_FEATURE 0x03 +#define CDC_CLEAR_COMM_FEATURE 0x04 +#define CDC_SET_LINE_CODING 0x20 +#define CDC_GET_LINE_CODING 0x21 +#define CDC_SET_CONTROL_LINE_STATE 0x22 +#define CDC_SEND_BREAK 0x23 + +/** + * @} + */ + + +/** @defgroup USBD_CORE_Exported_TypesDefinitions + * @{ + */ + +/** + * @} + */ +typedef struct +{ + uint32_t bitrate; + uint8_t format; + uint8_t paritytype; + uint8_t datatype; +}USBD_CDC_LineCodingTypeDef; + +typedef struct _USBD_CDC_Itf +{ + int8_t (* Init) (void); + int8_t (* DeInit) (void); + int8_t (* Control) (uint8_t, uint8_t * , uint16_t); + int8_t (* Receive) (uint8_t *, uint32_t *); + +}USBD_CDC_ItfTypeDef; + + +typedef struct +{ + uint32_t data[CDC_DATA_HS_MAX_PACKET_SIZE/4]; /* Force 32bits alignment */ + uint8_t CmdOpCode; + uint8_t CmdLength; + uint8_t *RxBuffer; + uint8_t *TxBuffer; + uint32_t RxLength; + uint32_t TxLength; + + __IO uint32_t TxState; + __IO uint32_t RxState; +} +USBD_CDC_HandleTypeDef; + + + +/** @defgroup USBD_CORE_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_CORE_Exported_Variables + * @{ + */ + +extern USBD_ClassTypeDef USBD_CDC; +#define USBD_CDC_CLASS &USBD_CDC +/** + * @} + */ + +/** @defgroup USB_CORE_Exported_Functions + * @{ + */ +uint8_t USBD_CDC_RegisterInterface (USBD_HandleTypeDef *pdev, + USBD_CDC_ItfTypeDef *fops); + +uint8_t USBD_CDC_SetTxBuffer (USBD_HandleTypeDef *pdev, + uint8_t *pbuff, + uint16_t length); + +uint8_t USBD_CDC_SetRxBuffer (USBD_HandleTypeDef *pdev, + uint8_t *pbuff); + +uint8_t USBD_CDC_ReceivePacket (USBD_HandleTypeDef *pdev); + +uint8_t USBD_CDC_TransmitPacket (USBD_HandleTypeDef *pdev); +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USB_CDC_H */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c new file mode 100644 index 0000000..cb77a71 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c @@ -0,0 +1,925 @@ +/** + ****************************************************************************** + * @file usbd_cdc.c + * @author MCD Application Team + * @version V2.4.2 + * @date 11-December-2015 + * @brief This file provides the high layer firmware functions to manage the + * following functionalities of the USB CDC Class: + * - Initialization and Configuration of high and low layer + * - Enumeration as CDC Device (and enumeration for each implemented memory interface) + * - OUT/IN data transfer + * - Command IN transfer (class requests management) + * - Error management + * + * @verbatim + * + * =================================================================== + * CDC Class Driver Description + * =================================================================== + * This driver manages the "Universal Serial Bus Class Definitions for Communications Devices + * Revision 1.2 November 16, 2007" and the sub-protocol specification of "Universal Serial Bus + * Communications Class Subclass Specification for PSTN Devices Revision 1.2 February 9, 2007" + * This driver implements the following aspects of the specification: + * - Device descriptor management + * - Configuration descriptor management + * - Enumeration as CDC device with 2 data endpoints (IN and OUT) and 1 command endpoint (IN) + * - Requests management (as described in section 6.2 in specification) + * - Abstract Control Model compliant + * - Union Functional collection (using 1 IN endpoint for control) + * - Data interface class + * + * These aspects may be enriched or modified for a specific user application. + * + * This driver doesn't implement the following aspects of the specification + * (but it is possible to manage these features with some modifications on this driver): + * - Any class-specific aspect relative to communication classes should be managed by user application. + * - All communication classes other than PSTN are not managed + * + * @endverbatim + * + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2015 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (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.st.com/software_license_agreement_liberty_v2 + * + * 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_cdc.h" +#include "usbd_desc.h" +#include "usbd_ctlreq.h" + + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + + +/** @defgroup USBD_CDC + * @brief usbd core module + * @{ + */ + +/** @defgroup USBD_CDC_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_CDC_Private_Defines + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_CDC_Private_Macros + * @{ + */ + +/** + * @} + */ + + +/** @defgroup USBD_CDC_Private_FunctionPrototypes + * @{ + */ + + +static uint8_t USBD_CDC_Init (USBD_HandleTypeDef *pdev, + uint8_t cfgidx); + +static uint8_t USBD_CDC_DeInit (USBD_HandleTypeDef *pdev, + uint8_t cfgidx); + +static uint8_t USBD_CDC_Setup (USBD_HandleTypeDef *pdev, + USBD_SetupReqTypedef *req); + +static uint8_t USBD_CDC_DataIn (USBD_HandleTypeDef *pdev, + uint8_t epnum); + +static uint8_t USBD_CDC_DataOut (USBD_HandleTypeDef *pdev, + uint8_t epnum); + +static uint8_t USBD_CDC_EP0_RxReady (USBD_HandleTypeDef *pdev); + +static uint8_t *USBD_CDC_GetFSCfgDesc (uint16_t *length); + +static uint8_t *USBD_CDC_GetHSCfgDesc (uint16_t *length); + +static uint8_t *USBD_CDC_GetOtherSpeedCfgDesc (uint16_t *length); + +static uint8_t *USBD_CDC_GetOtherSpeedCfgDesc (uint16_t *length); + +uint8_t *USBD_CDC_GetDeviceQualifierDescriptor (uint16_t *length); + +/* USB Standard Device Descriptor */ +__ALIGN_BEGIN static uint8_t USBD_CDC_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END = +{ + USB_LEN_DEV_QUALIFIER_DESC, + USB_DESC_TYPE_DEVICE_QUALIFIER, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x40, + 0x01, + 0x00, +}; + +/** + * @} + */ + +/** @defgroup USBD_CDC_Private_Variables + * @{ + */ + + +/* CDC interface class callbacks structure */ +USBD_ClassTypeDef USBD_CDC = +{ + USBD_CDC_Init, + USBD_CDC_DeInit, + USBD_CDC_Setup, + NULL, /* EP0_TxSent, */ + USBD_CDC_EP0_RxReady, + USBD_CDC_DataIn, + USBD_CDC_DataOut, + NULL, + NULL, + NULL, + USBD_CDC_GetHSCfgDesc, + USBD_CDC_GetFSCfgDesc, + USBD_CDC_GetOtherSpeedCfgDesc, + USBD_CDC_GetDeviceQualifierDescriptor, +}; + +/* USB CDC device Configuration Descriptor */ +__ALIGN_BEGIN uint8_t USBD_CDC_CfgHSDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END = +{ + /*Configuration Descriptor*/ + 0x09, /* bLength: Configuration Descriptor size */ + USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ + USB_CDC_CONFIG_DESC_SIZ, /* wTotalLength:no of returned bytes */ + 0x00, + 0x02, /* bNumInterfaces: 2 interface */ + 0x01, /* bConfigurationValue: Configuration value */ + 0x00, /* iConfiguration: Index of string descriptor describing the configuration */ + 0xC0, /* bmAttributes: self powered */ + 0x32, /* MaxPower 0 mA */ + + /*---------------------------------------------------------------------------*/ + + /*Interface Descriptor */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */ + /* Interface descriptor type */ + 0x00, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x01, /* bNumEndpoints: One endpoints used */ + 0x02, /* bInterfaceClass: Communication Interface Class */ + 0x02, /* bInterfaceSubClass: Abstract Control Model */ + 0x01, /* bInterfaceProtocol: Common AT commands */ + 0x00, /* iInterface: */ + + /*Header Functional Descriptor*/ + 0x05, /* bLength: Endpoint Descriptor size */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x00, /* bDescriptorSubtype: Header Func Desc */ + 0x10, /* bcdCDC: spec release number */ + 0x01, + + /*Call Management Functional Descriptor*/ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x01, /* bDescriptorSubtype: Call Management Func Desc */ + 0x00, /* bmCapabilities: D0+D1 */ + 0x01, /* bDataInterface: 1 */ + + /*ACM Functional Descriptor*/ + 0x04, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x02, /* bDescriptorSubtype: Abstract Control Management desc */ + 0x02, /* bmCapabilities */ + + /*Union Functional Descriptor*/ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x06, /* bDescriptorSubtype: Union func desc */ + 0x00, /* bMasterInterface: Communication class interface */ + 0x01, /* bSlaveInterface0: Data Class Interface */ + + /*Endpoint 2 Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + CDC_CMD_EP, /* bEndpointAddress */ + 0x03, /* bmAttributes: Interrupt */ + LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_CMD_PACKET_SIZE), + 0x10, /* bInterval: */ + /*---------------------------------------------------------------------------*/ + + /*Data class interface descriptor*/ + 0x09, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */ + 0x01, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints: Two endpoints used */ + 0x0A, /* bInterfaceClass: CDC */ + 0x00, /* bInterfaceSubClass: */ + 0x00, /* bInterfaceProtocol: */ + 0x00, /* iInterface: */ + + /*Endpoint OUT Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + CDC_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), + 0x00, /* bInterval: ignore for Bulk transfer */ + + /*Endpoint IN Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + CDC_IN_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), + 0x00 /* bInterval: ignore for Bulk transfer */ +} ; + + +/* USB CDC device Configuration Descriptor */ +__ALIGN_BEGIN uint8_t USBD_CDC_CfgFSDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END = +{ + /*Configuration Descriptor*/ + 0x09, /* bLength: Configuration Descriptor size */ + USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ + USB_CDC_CONFIG_DESC_SIZ, /* wTotalLength:no of returned bytes */ + 0x00, + 0x02, /* bNumInterfaces: 2 interface */ + 0x01, /* bConfigurationValue: Configuration value */ + 0x00, /* iConfiguration: Index of string descriptor describing the configuration */ + 0xC0, /* bmAttributes: self powered */ + 0x32, /* MaxPower 0 mA */ + + /*---------------------------------------------------------------------------*/ + + /*Interface Descriptor */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */ + /* Interface descriptor type */ + 0x00, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x01, /* bNumEndpoints: One endpoints used */ + 0x02, /* bInterfaceClass: Communication Interface Class */ + 0x02, /* bInterfaceSubClass: Abstract Control Model */ + 0x01, /* bInterfaceProtocol: Common AT commands */ + 0x00, /* iInterface: */ + + /*Header Functional Descriptor*/ + 0x05, /* bLength: Endpoint Descriptor size */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x00, /* bDescriptorSubtype: Header Func Desc */ + 0x10, /* bcdCDC: spec release number */ + 0x01, + + /*Call Management Functional Descriptor*/ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x01, /* bDescriptorSubtype: Call Management Func Desc */ + 0x00, /* bmCapabilities: D0+D1 */ + 0x01, /* bDataInterface: 1 */ + + /*ACM Functional Descriptor*/ + 0x04, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x02, /* bDescriptorSubtype: Abstract Control Management desc */ + 0x02, /* bmCapabilities */ + + /*Union Functional Descriptor*/ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x06, /* bDescriptorSubtype: Union func desc */ + 0x00, /* bMasterInterface: Communication class interface */ + 0x01, /* bSlaveInterface0: Data Class Interface */ + + /*Endpoint 2 Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + CDC_CMD_EP, /* bEndpointAddress */ + 0x03, /* bmAttributes: Interrupt */ + LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_CMD_PACKET_SIZE), + 0x10, /* bInterval: */ + /*---------------------------------------------------------------------------*/ + + /*Data class interface descriptor*/ + 0x09, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */ + 0x01, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints: Two endpoints used */ + 0x0A, /* bInterfaceClass: CDC */ + 0x00, /* bInterfaceSubClass: */ + 0x00, /* bInterfaceProtocol: */ + 0x00, /* iInterface: */ + + /*Endpoint OUT Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + CDC_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), + 0x00, /* bInterval: ignore for Bulk transfer */ + + /*Endpoint IN Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + CDC_IN_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), + 0x00 /* bInterval: ignore for Bulk transfer */ +} ; + +__ALIGN_BEGIN uint8_t USBD_CDC_OtherSpeedCfgDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END = +{ + 0x09, /* bLength: Configuation Descriptor size */ + USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION, + USB_CDC_CONFIG_DESC_SIZ, + 0x00, + 0x02, /* bNumInterfaces: 2 interfaces */ + 0x01, /* bConfigurationValue: */ + 0x04, /* iConfiguration: */ + 0xC0, /* bmAttributes: */ + 0x32, /* MaxPower 100 mA */ + + /*Interface Descriptor */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */ + /* Interface descriptor type */ + 0x00, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x01, /* bNumEndpoints: One endpoints used */ + 0x02, /* bInterfaceClass: Communication Interface Class */ + 0x02, /* bInterfaceSubClass: Abstract Control Model */ + 0x01, /* bInterfaceProtocol: Common AT commands */ + 0x00, /* iInterface: */ + + /*Header Functional Descriptor*/ + 0x05, /* bLength: Endpoint Descriptor size */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x00, /* bDescriptorSubtype: Header Func Desc */ + 0x10, /* bcdCDC: spec release number */ + 0x01, + + /*Call Management Functional Descriptor*/ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x01, /* bDescriptorSubtype: Call Management Func Desc */ + 0x00, /* bmCapabilities: D0+D1 */ + 0x01, /* bDataInterface: 1 */ + + /*ACM Functional Descriptor*/ + 0x04, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x02, /* bDescriptorSubtype: Abstract Control Management desc */ + 0x02, /* bmCapabilities */ + + /*Union Functional Descriptor*/ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x06, /* bDescriptorSubtype: Union func desc */ + 0x00, /* bMasterInterface: Communication class interface */ + 0x01, /* bSlaveInterface0: Data Class Interface */ + + /*Endpoint 2 Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT , /* bDescriptorType: Endpoint */ + CDC_CMD_EP, /* bEndpointAddress */ + 0x03, /* bmAttributes: Interrupt */ + LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_CMD_PACKET_SIZE), + 0xFF, /* bInterval: */ + + /*---------------------------------------------------------------------------*/ + + /*Data class interface descriptor*/ + 0x09, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */ + 0x01, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints: Two endpoints used */ + 0x0A, /* bInterfaceClass: CDC */ + 0x00, /* bInterfaceSubClass: */ + 0x00, /* bInterfaceProtocol: */ + 0x00, /* iInterface: */ + + /*Endpoint OUT Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + CDC_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + 0x40, /* wMaxPacketSize: */ + 0x00, + 0x00, /* bInterval: ignore for Bulk transfer */ + + /*Endpoint IN Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + CDC_IN_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + 0x40, /* wMaxPacketSize: */ + 0x00, + 0x00 /* bInterval */ +}; + +/** + * @} + */ + +/** @defgroup USBD_CDC_Private_Functions + * @{ + */ + +/** + * @brief USBD_CDC_Init + * Initialize the CDC interface + * @param pdev: device instance + * @param cfgidx: Configuration index + * @retval status + */ +static uint8_t USBD_CDC_Init (USBD_HandleTypeDef *pdev, + uint8_t cfgidx) +{ + uint8_t ret = 0; + USBD_CDC_HandleTypeDef *hcdc; + + if(pdev->dev_speed == USBD_SPEED_HIGH ) + { + /* Open EP IN */ + USBD_LL_OpenEP(pdev, + CDC_IN_EP, + USBD_EP_TYPE_BULK, + CDC_DATA_HS_IN_PACKET_SIZE); + + /* Open EP OUT */ + USBD_LL_OpenEP(pdev, + CDC_OUT_EP, + USBD_EP_TYPE_BULK, + CDC_DATA_HS_OUT_PACKET_SIZE); + + } + else + { + /* Open EP IN */ + USBD_LL_OpenEP(pdev, + CDC_IN_EP, + USBD_EP_TYPE_BULK, + CDC_DATA_FS_IN_PACKET_SIZE); + + /* Open EP OUT */ + USBD_LL_OpenEP(pdev, + CDC_OUT_EP, + USBD_EP_TYPE_BULK, + CDC_DATA_FS_OUT_PACKET_SIZE); + } + /* Open Command IN EP */ + USBD_LL_OpenEP(pdev, + CDC_CMD_EP, + USBD_EP_TYPE_INTR, + CDC_CMD_PACKET_SIZE); + + + pdev->pClassData = USBD_malloc(sizeof (USBD_CDC_HandleTypeDef)); + + if(pdev->pClassData == NULL) + { + ret = 1; + } + else + { + hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData; + + /* Init physical Interface components */ + ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Init(); + + /* Init Xfer states */ + hcdc->TxState =0; + hcdc->RxState =0; + + if(pdev->dev_speed == USBD_SPEED_HIGH ) + { + /* Prepare Out endpoint to receive next packet */ + USBD_LL_PrepareReceive(pdev, + CDC_OUT_EP, + hcdc->RxBuffer, + CDC_DATA_HS_OUT_PACKET_SIZE); + } + else + { + /* Prepare Out endpoint to receive next packet */ + USBD_LL_PrepareReceive(pdev, + CDC_OUT_EP, + hcdc->RxBuffer, + CDC_DATA_FS_OUT_PACKET_SIZE); + } + + + } + return ret; +} + +/** + * @brief USBD_CDC_Init + * DeInitialize the CDC layer + * @param pdev: device instance + * @param cfgidx: Configuration index + * @retval status + */ +static uint8_t USBD_CDC_DeInit (USBD_HandleTypeDef *pdev, + uint8_t cfgidx) +{ + uint8_t ret = 0; + + /* Open EP IN */ + USBD_LL_CloseEP(pdev, + CDC_IN_EP); + + /* Open EP OUT */ + USBD_LL_CloseEP(pdev, + CDC_OUT_EP); + + /* Open Command IN EP */ + USBD_LL_CloseEP(pdev, + CDC_CMD_EP); + + + /* DeInit physical Interface components */ + if(pdev->pClassData != NULL) + { + ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->DeInit(); + USBD_free(pdev->pClassData); + pdev->pClassData = NULL; + } + + return ret; +} + +/** + * @brief USBD_CDC_Setup + * Handle the CDC specific requests + * @param pdev: instance + * @param req: usb requests + * @retval status + */ +static uint8_t USBD_CDC_Setup (USBD_HandleTypeDef *pdev, + USBD_SetupReqTypedef *req) +{ + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData; + static uint8_t ifalt = 0; + + switch (req->bmRequest & USB_REQ_TYPE_MASK) + { + case USB_REQ_TYPE_CLASS : + if (req->wLength) + { + if (req->bmRequest & 0x80) + { + ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Control(req->bRequest, + (uint8_t *)hcdc->data, + req->wLength); + USBD_CtlSendData (pdev, + (uint8_t *)hcdc->data, + req->wLength); + } + else + { + hcdc->CmdOpCode = req->bRequest; + hcdc->CmdLength = req->wLength; + + USBD_CtlPrepareRx (pdev, + (uint8_t *)hcdc->data, + req->wLength); + } + + } + else + { + ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Control(req->bRequest, + (uint8_t*)req, + 0); + } + break; + + case USB_REQ_TYPE_STANDARD: + switch (req->bRequest) + { + case USB_REQ_GET_INTERFACE : + USBD_CtlSendData (pdev, + &ifalt, + 1); + break; + + case USB_REQ_SET_INTERFACE : + break; + } + + default: + break; + } + return USBD_OK; +} + +/** + * @brief USBD_CDC_DataIn + * Data sent on non-control IN endpoint + * @param pdev: device instance + * @param epnum: endpoint number + * @retval status + */ +static uint8_t USBD_CDC_DataIn (USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData; + + if(pdev->pClassData != NULL) + { + + hcdc->TxState = 0; + + return USBD_OK; + } + else + { + return USBD_FAIL; + } +} + +/** + * @brief USBD_CDC_DataOut + * Data received on non-control Out endpoint + * @param pdev: device instance + * @param epnum: endpoint number + * @retval status + */ +static uint8_t USBD_CDC_DataOut (USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData; + + /* Get the received data length */ + hcdc->RxLength = USBD_LL_GetRxDataSize (pdev, epnum); + + /* USB data will be immediately processed, this allow next USB traffic being + NAKed till the end of the application Xfer */ + if(pdev->pClassData != NULL) + { + ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Receive(hcdc->RxBuffer, &hcdc->RxLength); + + return USBD_OK; + } + else + { + return USBD_FAIL; + } +} + + + +/** + * @brief USBD_CDC_DataOut + * Data received on non-control Out endpoint + * @param pdev: device instance + * @param epnum: endpoint number + * @retval status + */ +static uint8_t USBD_CDC_EP0_RxReady (USBD_HandleTypeDef *pdev) +{ + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData; + + if((pdev->pUserData != NULL) && (hcdc->CmdOpCode != 0xFF)) + { + ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Control(hcdc->CmdOpCode, + (uint8_t *)hcdc->data, + hcdc->CmdLength); + hcdc->CmdOpCode = 0xFF; + + } + return USBD_OK; +} + +/** + * @brief USBD_CDC_GetFSCfgDesc + * Return configuration descriptor + * @param speed : current device speed + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_CDC_GetFSCfgDesc (uint16_t *length) +{ + *length = sizeof (USBD_CDC_CfgFSDesc); + return USBD_CDC_CfgFSDesc; +} + +/** + * @brief USBD_CDC_GetHSCfgDesc + * Return configuration descriptor + * @param speed : current device speed + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_CDC_GetHSCfgDesc (uint16_t *length) +{ + *length = sizeof (USBD_CDC_CfgHSDesc); + return USBD_CDC_CfgHSDesc; +} + +/** + * @brief USBD_CDC_GetCfgDesc + * Return configuration descriptor + * @param speed : current device speed + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_CDC_GetOtherSpeedCfgDesc (uint16_t *length) +{ + *length = sizeof (USBD_CDC_OtherSpeedCfgDesc); + return USBD_CDC_OtherSpeedCfgDesc; +} + +/** +* @brief DeviceQualifierDescriptor +* return Device Qualifier descriptor +* @param length : pointer data length +* @retval pointer to descriptor buffer +*/ +uint8_t *USBD_CDC_GetDeviceQualifierDescriptor (uint16_t *length) +{ + *length = sizeof (USBD_CDC_DeviceQualifierDesc); + return USBD_CDC_DeviceQualifierDesc; +} + +/** +* @brief USBD_CDC_RegisterInterface + * @param pdev: device instance + * @param fops: CD Interface callback + * @retval status + */ +uint8_t USBD_CDC_RegisterInterface (USBD_HandleTypeDef *pdev, + USBD_CDC_ItfTypeDef *fops) +{ + uint8_t ret = USBD_FAIL; + + if(fops != NULL) + { + pdev->pUserData= fops; + ret = USBD_OK; + } + + return ret; +} + +/** + * @brief USBD_CDC_SetTxBuffer + * @param pdev: device instance + * @param pbuff: Tx Buffer + * @retval status + */ +uint8_t USBD_CDC_SetTxBuffer (USBD_HandleTypeDef *pdev, + uint8_t *pbuff, + uint16_t length) +{ + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData; + + hcdc->TxBuffer = pbuff; + hcdc->TxLength = length; + + return USBD_OK; +} + + +/** + * @brief USBD_CDC_SetRxBuffer + * @param pdev: device instance + * @param pbuff: Rx Buffer + * @retval status + */ +uint8_t USBD_CDC_SetRxBuffer (USBD_HandleTypeDef *pdev, + uint8_t *pbuff) +{ + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData; + + hcdc->RxBuffer = pbuff; + + return USBD_OK; +} + +/** + * @brief USBD_CDC_DataOut + * Data received on non-control Out endpoint + * @param pdev: device instance + * @param epnum: endpoint number + * @retval status + */ +uint8_t USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev) +{ + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData; + + if(pdev->pClassData != NULL) + { + if(hcdc->TxState == 0) + { + /* Tx Transfer in progress */ + hcdc->TxState = 1; + + /* Transmit next packet */ + USBD_LL_Transmit(pdev, + CDC_IN_EP, + hcdc->TxBuffer, + hcdc->TxLength); + + return USBD_OK; + } + else + { + return USBD_BUSY; + } + } + else + { + return USBD_FAIL; + } +} + + +/** + * @brief USBD_CDC_ReceivePacket + * prepare OUT Endpoint for reception + * @param pdev: device instance + * @retval status + */ +uint8_t USBD_CDC_ReceivePacket(USBD_HandleTypeDef *pdev) +{ + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData; + + /* Suspend or Resume USB Out process */ + if(pdev->pClassData != NULL) + { + if(pdev->dev_speed == USBD_SPEED_HIGH ) + { + /* Prepare Out endpoint to receive next packet */ + USBD_LL_PrepareReceive(pdev, + CDC_OUT_EP, + hcdc->RxBuffer, + CDC_DATA_HS_OUT_PACKET_SIZE); + } + else + { + /* Prepare Out endpoint to receive next packet */ + USBD_LL_PrepareReceive(pdev, + CDC_OUT_EP, + hcdc->RxBuffer, + CDC_DATA_FS_OUT_PACKET_SIZE); + } + return USBD_OK; + } + else + { + return USBD_FAIL; + } +} +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_core.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_core.h new file mode 100644 index 0000000..fcfffa1 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_core.h @@ -0,0 +1,167 @@ +/** + ****************************************************************************** + * @file usbd_core.h + * @author MCD Application Team + * @version V2.4.2 + * @date 11-December-2015 + * @brief Header file for usbd_core.c file + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2015 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (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.st.com/software_license_agreement_liberty_v2 + * + * 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_CORE_H +#define __USBD_CORE_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_conf.h" +#include "usbd_def.h" +#include "usbd_ioreq.h" +#include "usbd_ctlreq.h" + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USBD_CORE + * @brief This file is the Header file for usbd_core.c file + * @{ + */ + + +/** @defgroup USBD_CORE_Exported_Defines + * @{ + */ + +/** + * @} + */ + + +/** @defgroup USBD_CORE_Exported_TypesDefinitions + * @{ + */ + + +/** + * @} + */ + + + +/** @defgroup USBD_CORE_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_CORE_Exported_Variables + * @{ + */ +#define USBD_SOF USBD_LL_SOF +/** + * @} + */ + +/** @defgroup USBD_CORE_Exported_FunctionsPrototype + * @{ + */ +USBD_StatusTypeDef USBD_Init(USBD_HandleTypeDef *pdev, USBD_DescriptorsTypeDef *pdesc, uint8_t id); +USBD_StatusTypeDef USBD_DeInit(USBD_HandleTypeDef *pdev); +USBD_StatusTypeDef USBD_Start (USBD_HandleTypeDef *pdev); +USBD_StatusTypeDef USBD_Stop (USBD_HandleTypeDef *pdev); +USBD_StatusTypeDef USBD_RegisterClass(USBD_HandleTypeDef *pdev, USBD_ClassTypeDef *pclass); + +USBD_StatusTypeDef USBD_RunTestMode (USBD_HandleTypeDef *pdev); +USBD_StatusTypeDef USBD_SetClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx); +USBD_StatusTypeDef USBD_ClrClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx); + +USBD_StatusTypeDef USBD_LL_SetupStage(USBD_HandleTypeDef *pdev, uint8_t *psetup); +USBD_StatusTypeDef USBD_LL_DataOutStage(USBD_HandleTypeDef *pdev , uint8_t epnum, uint8_t *pdata); +USBD_StatusTypeDef USBD_LL_DataInStage(USBD_HandleTypeDef *pdev , uint8_t epnum, uint8_t *pdata); + +USBD_StatusTypeDef USBD_LL_Reset(USBD_HandleTypeDef *pdev); +USBD_StatusTypeDef USBD_LL_SetSpeed(USBD_HandleTypeDef *pdev, USBD_SpeedTypeDef speed); +USBD_StatusTypeDef USBD_LL_Suspend(USBD_HandleTypeDef *pdev); +USBD_StatusTypeDef USBD_LL_Resume(USBD_HandleTypeDef *pdev); + +USBD_StatusTypeDef USBD_LL_SOF(USBD_HandleTypeDef *pdev); +USBD_StatusTypeDef USBD_LL_IsoINIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum); +USBD_StatusTypeDef USBD_LL_IsoOUTIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum); + +USBD_StatusTypeDef USBD_LL_DevConnected(USBD_HandleTypeDef *pdev); +USBD_StatusTypeDef USBD_LL_DevDisconnected(USBD_HandleTypeDef *pdev); + +/* USBD Low Level Driver */ +USBD_StatusTypeDef USBD_LL_Init (USBD_HandleTypeDef *pdev); +USBD_StatusTypeDef USBD_LL_DeInit (USBD_HandleTypeDef *pdev); +USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev); +USBD_StatusTypeDef USBD_LL_Stop (USBD_HandleTypeDef *pdev); +USBD_StatusTypeDef USBD_LL_OpenEP (USBD_HandleTypeDef *pdev, + uint8_t ep_addr, + uint8_t ep_type, + uint16_t ep_mps); + +USBD_StatusTypeDef USBD_LL_CloseEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr); +USBD_StatusTypeDef USBD_LL_FlushEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr); +USBD_StatusTypeDef USBD_LL_StallEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr); +USBD_StatusTypeDef USBD_LL_ClearStallEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr); +uint8_t USBD_LL_IsStallEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr); +USBD_StatusTypeDef USBD_LL_SetUSBAddress (USBD_HandleTypeDef *pdev, uint8_t dev_addr); +USBD_StatusTypeDef USBD_LL_Transmit (USBD_HandleTypeDef *pdev, + uint8_t ep_addr, + uint8_t *pbuf, + uint16_t size); + +USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev, + uint8_t ep_addr, + uint8_t *pbuf, + uint16_t size); + +uint32_t USBD_LL_GetRxDataSize (USBD_HandleTypeDef *pdev, uint8_t ep_addr); +void USBD_LL_Delay (uint32_t Delay); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBD_CORE_H */ + +/** + * @} + */ + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + + + diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ctlreq.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ctlreq.h new file mode 100644 index 0000000..f4ddfb2 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ctlreq.h @@ -0,0 +1,113 @@ +/** + ****************************************************************************** + * @file usbd_req.h + * @author MCD Application Team + * @version V2.4.2 + * @date 11-December-2015 + * @brief Header file for the usbd_req.c file + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2015 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (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.st.com/software_license_agreement_liberty_v2 + * + * 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_REQUEST_H +#define __USB_REQUEST_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_def.h" + + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USBD_REQ + * @brief header file for the usbd_req.c file + * @{ + */ + +/** @defgroup USBD_REQ_Exported_Defines + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_REQ_Exported_Types + * @{ + */ +/** + * @} + */ + + + +/** @defgroup USBD_REQ_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USBD_REQ_Exported_Variables + * @{ + */ +/** + * @} + */ + +/** @defgroup USBD_REQ_Exported_FunctionsPrototype + * @{ + */ + +USBD_StatusTypeDef USBD_StdDevReq (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); +USBD_StatusTypeDef USBD_StdItfReq (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); +USBD_StatusTypeDef USBD_StdEPReq (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); + + +void USBD_CtlError (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); + +void USBD_ParseSetupRequest (USBD_SetupReqTypedef *req, uint8_t *pdata); + +void USBD_GetString (uint8_t *desc, uint8_t *unicode, uint16_t *len); +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USB_REQUEST_H */ + +/** + * @} + */ + +/** +* @} +*/ + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_def.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_def.h new file mode 100644 index 0000000..34a4220 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_def.h @@ -0,0 +1,330 @@ +/** + ****************************************************************************** + * @file usbd_def.h + * @author MCD Application Team + * @version V2.4.2 + * @date 11-December-2015 + * @brief General defines for the usb device library + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2015 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (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.st.com/software_license_agreement_liberty_v2 + * + * 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_DEF_H +#define __USBD_DEF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_conf.h" + +/** @addtogroup STM32_USBD_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USB_DEF + * @brief general defines for the usb device library file + * @{ + */ + +/** @defgroup USB_DEF_Exported_Defines + * @{ + */ + +#ifndef NULL +#define NULL 0 +#endif + + +#define USB_LEN_DEV_QUALIFIER_DESC 0x0A +#define USB_LEN_DEV_DESC 0x12 +#define USB_LEN_CFG_DESC 0x09 +#define USB_LEN_IF_DESC 0x09 +#define USB_LEN_EP_DESC 0x07 +#define USB_LEN_OTG_DESC 0x03 +#define USB_LEN_LANGID_STR_DESC 0x04 +#define USB_LEN_OTHER_SPEED_DESC_SIZ 0x09 + +#define USBD_IDX_LANGID_STR 0x00 +#define USBD_IDX_MFC_STR 0x01 +#define USBD_IDX_PRODUCT_STR 0x02 +#define USBD_IDX_SERIAL_STR 0x03 +#define USBD_IDX_CONFIG_STR 0x04 +#define USBD_IDX_INTERFACE_STR 0x05 + +#define USB_REQ_TYPE_STANDARD 0x00 +#define USB_REQ_TYPE_CLASS 0x20 +#define USB_REQ_TYPE_VENDOR 0x40 +#define USB_REQ_TYPE_MASK 0x60 + +#define USB_REQ_RECIPIENT_DEVICE 0x00 +#define USB_REQ_RECIPIENT_INTERFACE 0x01 +#define USB_REQ_RECIPIENT_ENDPOINT 0x02 +#define USB_REQ_RECIPIENT_MASK 0x03 + +#define USB_REQ_GET_STATUS 0x00 +#define USB_REQ_CLEAR_FEATURE 0x01 +#define USB_REQ_SET_FEATURE 0x03 +#define USB_REQ_SET_ADDRESS 0x05 +#define USB_REQ_GET_DESCRIPTOR 0x06 +#define USB_REQ_SET_DESCRIPTOR 0x07 +#define USB_REQ_GET_CONFIGURATION 0x08 +#define USB_REQ_SET_CONFIGURATION 0x09 +#define USB_REQ_GET_INTERFACE 0x0A +#define USB_REQ_SET_INTERFACE 0x0B +#define USB_REQ_SYNCH_FRAME 0x0C + +#define USB_DESC_TYPE_DEVICE 1 +#define USB_DESC_TYPE_CONFIGURATION 2 +#define USB_DESC_TYPE_STRING 3 +#define USB_DESC_TYPE_INTERFACE 4 +#define USB_DESC_TYPE_ENDPOINT 5 +#define USB_DESC_TYPE_DEVICE_QUALIFIER 6 +#define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION 7 +#define USB_DESC_TYPE_BOS 0x0F + +#define USB_CONFIG_REMOTE_WAKEUP 2 +#define USB_CONFIG_SELF_POWERED 1 + +#define USB_FEATURE_EP_HALT 0 +#define USB_FEATURE_REMOTE_WAKEUP 1 +#define USB_FEATURE_TEST_MODE 2 + +#define USB_DEVICE_CAPABITY_TYPE 0x10 + +#define USB_HS_MAX_PACKET_SIZE 512 +#define USB_FS_MAX_PACKET_SIZE 64 +#define USB_MAX_EP0_SIZE 64 + +/* Device Status */ +#define USBD_STATE_DEFAULT 1 +#define USBD_STATE_ADDRESSED 2 +#define USBD_STATE_CONFIGURED 3 +#define USBD_STATE_SUSPENDED 4 + + +/* EP0 State */ +#define USBD_EP0_IDLE 0 +#define USBD_EP0_SETUP 1 +#define USBD_EP0_DATA_IN 2 +#define USBD_EP0_DATA_OUT 3 +#define USBD_EP0_STATUS_IN 4 +#define USBD_EP0_STATUS_OUT 5 +#define USBD_EP0_STALL 6 + +#define USBD_EP_TYPE_CTRL 0 +#define USBD_EP_TYPE_ISOC 1 +#define USBD_EP_TYPE_BULK 2 +#define USBD_EP_TYPE_INTR 3 + + +/** + * @} + */ + + +/** @defgroup USBD_DEF_Exported_TypesDefinitions + * @{ + */ + +typedef struct usb_setup_req +{ + + uint8_t bmRequest; + uint8_t bRequest; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; +}USBD_SetupReqTypedef; + +struct _USBD_HandleTypeDef; + +typedef struct _Device_cb +{ + uint8_t (*Init) (struct _USBD_HandleTypeDef *pdev , uint8_t cfgidx); + uint8_t (*DeInit) (struct _USBD_HandleTypeDef *pdev , uint8_t cfgidx); + /* Control Endpoints*/ + uint8_t (*Setup) (struct _USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req); + uint8_t (*EP0_TxSent) (struct _USBD_HandleTypeDef *pdev ); + uint8_t (*EP0_RxReady) (struct _USBD_HandleTypeDef *pdev ); + /* Class Specific Endpoints*/ + uint8_t (*DataIn) (struct _USBD_HandleTypeDef *pdev , uint8_t epnum); + uint8_t (*DataOut) (struct _USBD_HandleTypeDef *pdev , uint8_t epnum); + uint8_t (*SOF) (struct _USBD_HandleTypeDef *pdev); + uint8_t (*IsoINIncomplete) (struct _USBD_HandleTypeDef *pdev , uint8_t epnum); + uint8_t (*IsoOUTIncomplete) (struct _USBD_HandleTypeDef *pdev , uint8_t epnum); + + uint8_t *(*GetHSConfigDescriptor)(uint16_t *length); + uint8_t *(*GetFSConfigDescriptor)(uint16_t *length); + uint8_t *(*GetOtherSpeedConfigDescriptor)(uint16_t *length); + uint8_t *(*GetDeviceQualifierDescriptor)(uint16_t *length); +#if (USBD_SUPPORT_USER_STRING == 1) + uint8_t *(*GetUsrStrDescriptor)(struct _USBD_HandleTypeDef *pdev ,uint8_t index, uint16_t *length); +#endif + +} USBD_ClassTypeDef; + +/* Following USB Device Speed */ +typedef enum +{ + USBD_SPEED_HIGH = 0, + USBD_SPEED_FULL = 1, + USBD_SPEED_LOW = 2, +}USBD_SpeedTypeDef; + +/* Following USB Device status */ +typedef enum { + USBD_OK = 0, + USBD_BUSY, + USBD_FAIL, +}USBD_StatusTypeDef; + +/* USB Device descriptors structure */ +typedef struct +{ + uint8_t *(*GetDeviceDescriptor)( USBD_SpeedTypeDef speed , uint16_t *length); + uint8_t *(*GetLangIDStrDescriptor)( USBD_SpeedTypeDef speed , uint16_t *length); + uint8_t *(*GetManufacturerStrDescriptor)( USBD_SpeedTypeDef speed , uint16_t *length); + uint8_t *(*GetProductStrDescriptor)( USBD_SpeedTypeDef speed , uint16_t *length); + uint8_t *(*GetSerialStrDescriptor)( USBD_SpeedTypeDef speed , uint16_t *length); + uint8_t *(*GetConfigurationStrDescriptor)( USBD_SpeedTypeDef speed , uint16_t *length); + uint8_t *(*GetInterfaceStrDescriptor)( USBD_SpeedTypeDef speed , uint16_t *length); +#if (USBD_LPM_ENABLED == 1) + uint8_t *(*GetBOSDescriptor)( USBD_SpeedTypeDef speed , uint16_t *length); +#endif +} USBD_DescriptorsTypeDef; + +/* USB Device handle structure */ +typedef struct +{ + uint32_t status; + uint32_t total_length; + uint32_t rem_length; + uint32_t maxpacket; +} USBD_EndpointTypeDef; + +/* USB Device handle structure */ +typedef struct _USBD_HandleTypeDef +{ + uint8_t id; + uint32_t dev_config; + uint32_t dev_default_config; + uint32_t dev_config_status; + USBD_SpeedTypeDef dev_speed; + USBD_EndpointTypeDef ep_in[15]; + USBD_EndpointTypeDef ep_out[15]; + uint32_t ep0_state; + uint32_t ep0_data_len; + uint8_t dev_state; + uint8_t dev_old_state; + uint8_t dev_address; + uint8_t dev_connection_status; + uint8_t dev_test_mode; + uint32_t dev_remote_wakeup; + + USBD_SetupReqTypedef request; + USBD_DescriptorsTypeDef *pDesc; + USBD_ClassTypeDef *pClass; + void *pClassData; + void *pUserData; + void *pData; +} USBD_HandleTypeDef; + +/** + * @} + */ + + + +/** @defgroup USBD_DEF_Exported_Macros + * @{ + */ +#define SWAPBYTE(addr) (((uint16_t)(*((uint8_t *)(addr)))) + \ + (((uint16_t)(*(((uint8_t *)(addr)) + 1))) << 8)) + +#define LOBYTE(x) ((uint8_t)(x & 0x00FF)) +#define HIBYTE(x) ((uint8_t)((x & 0xFF00) >>8)) +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) + + +#if defined ( __GNUC__ ) + #ifndef __weak + #define __weak __attribute__((weak)) + #endif /* __weak */ + #ifndef __packed + #define __packed __attribute__((__packed__)) + #endif /* __packed */ +#endif /* __GNUC__ */ + + +/* In HS mode and when the DMA is used, all variables and data structures dealing + with the DMA during the transaction process should be 4-bytes aligned */ + +#if defined (__GNUC__) /* GNU Compiler */ + #define __ALIGN_END __attribute__ ((aligned (4))) + #define __ALIGN_BEGIN +#else + #define __ALIGN_END + #if defined (__CC_ARM) /* ARM Compiler */ + #define __ALIGN_BEGIN __align(4) + #elif defined (__ICCARM__) /* IAR Compiler */ + #define __ALIGN_BEGIN + #elif defined (__TASKING__) /* TASKING Compiler */ + #define __ALIGN_BEGIN __align(4) + #endif /* __CC_ARM */ +#endif /* __GNUC__ */ + + +/** + * @} + */ + +/** @defgroup USBD_DEF_Exported_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_DEF_Exported_FunctionsPrototype + * @{ + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBD_DEF_H */ + +/** + * @} + */ + +/** +* @} +*/ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ioreq.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ioreq.h new file mode 100644 index 0000000..bb5d85c --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ioreq.h @@ -0,0 +1,128 @@ +/** + ****************************************************************************** + * @file usbd_ioreq.h + * @author MCD Application Team + * @version V2.4.2 + * @date 11-December-2015 + * @brief Header file for the usbd_ioreq.c file + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2015 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (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.st.com/software_license_agreement_liberty_v2 + * + * 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_IOREQ_H +#define __USBD_IOREQ_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_def.h" +#include "usbd_core.h" + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USBD_IOREQ + * @brief header file for the usbd_ioreq.c file + * @{ + */ + +/** @defgroup USBD_IOREQ_Exported_Defines + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_IOREQ_Exported_Types + * @{ + */ + + +/** + * @} + */ + + + +/** @defgroup USBD_IOREQ_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_IOREQ_Exported_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_IOREQ_Exported_FunctionsPrototype + * @{ + */ + +USBD_StatusTypeDef USBD_CtlSendData (USBD_HandleTypeDef *pdev, + uint8_t *buf, + uint16_t len); + +USBD_StatusTypeDef USBD_CtlContinueSendData (USBD_HandleTypeDef *pdev, + uint8_t *pbuf, + uint16_t len); + +USBD_StatusTypeDef USBD_CtlPrepareRx (USBD_HandleTypeDef *pdev, + uint8_t *pbuf, + uint16_t len); + +USBD_StatusTypeDef USBD_CtlContinueRx (USBD_HandleTypeDef *pdev, + uint8_t *pbuf, + uint16_t len); + +USBD_StatusTypeDef USBD_CtlSendStatus (USBD_HandleTypeDef *pdev); + +USBD_StatusTypeDef USBD_CtlReceiveStatus (USBD_HandleTypeDef *pdev); + +uint16_t USBD_GetRxCount (USBD_HandleTypeDef *pdev , + uint8_t epnum); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBD_IOREQ_H */ + +/** + * @} + */ + +/** +* @} +*/ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c new file mode 100644 index 0000000..ff3ed44 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c @@ -0,0 +1,565 @@ +/** + ****************************************************************************** + * @file usbd_core.c + * @author MCD Application Team + * @version V2.4.2 + * @date 11-December-2015 + * @brief This file provides all the USBD core functions. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2015 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (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.st.com/software_license_agreement_liberty_v2 + * + * 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_core.h" + +/** @addtogroup STM32_USBD_DEVICE_LIBRARY +* @{ +*/ + + +/** @defgroup USBD_CORE +* @brief usbd core module +* @{ +*/ + +/** @defgroup USBD_CORE_Private_TypesDefinitions +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USBD_CORE_Private_Defines +* @{ +*/ + +/** +* @} +*/ + + +/** @defgroup USBD_CORE_Private_Macros +* @{ +*/ +/** +* @} +*/ + + + + +/** @defgroup USBD_CORE_Private_FunctionPrototypes +* @{ +*/ + +/** +* @} +*/ + +/** @defgroup USBD_CORE_Private_Variables +* @{ +*/ + +/** +* @} +*/ + +/** @defgroup USBD_CORE_Private_Functions +* @{ +*/ + +/** +* @brief USBD_Init +* Initializes the device stack and load the class driver +* @param pdev: device instance +* @param pdesc: Descriptor structure address +* @param id: Low level core index +* @retval None +*/ +USBD_StatusTypeDef USBD_Init(USBD_HandleTypeDef *pdev, USBD_DescriptorsTypeDef *pdesc, uint8_t id) +{ + /* Check whether the USB Host handle is valid */ + if(pdev == NULL) + { + USBD_ErrLog("Invalid Device handle"); + return USBD_FAIL; + } + + /* Unlink previous class*/ + if(pdev->pClass != NULL) + { + pdev->pClass = NULL; + } + + /* Assign USBD Descriptors */ + if(pdesc != NULL) + { + pdev->pDesc = pdesc; + } + + /* Set Device initial State */ + pdev->dev_state = USBD_STATE_DEFAULT; + pdev->id = id; + /* Initialize low level driver */ + USBD_LL_Init(pdev); + + return USBD_OK; +} + +/** +* @brief USBD_DeInit +* Re-Initialize th device library +* @param pdev: device instance +* @retval status: status +*/ +USBD_StatusTypeDef USBD_DeInit(USBD_HandleTypeDef *pdev) +{ + /* Set Default State */ + pdev->dev_state = USBD_STATE_DEFAULT; + + /* Free Class Resources */ + pdev->pClass->DeInit(pdev, pdev->dev_config); + + /* Stop the low level driver */ + USBD_LL_Stop(pdev); + + /* Initialize low level driver */ + USBD_LL_DeInit(pdev); + + return USBD_OK; +} + + +/** + * @brief USBD_RegisterClass + * Link class driver to Device Core. + * @param pDevice : Device Handle + * @param pclass: Class handle + * @retval USBD Status + */ +USBD_StatusTypeDef USBD_RegisterClass(USBD_HandleTypeDef *pdev, USBD_ClassTypeDef *pclass) +{ + USBD_StatusTypeDef status = USBD_OK; + if(pclass != 0) + { + /* link the class to the USB Device handle */ + pdev->pClass = pclass; + status = USBD_OK; + } + else + { + USBD_ErrLog("Invalid Class handle"); + status = USBD_FAIL; + } + + return status; +} + +/** + * @brief USBD_Start + * Start the USB Device Core. + * @param pdev: Device Handle + * @retval USBD Status + */ +USBD_StatusTypeDef USBD_Start (USBD_HandleTypeDef *pdev) +{ + + /* Start the low level driver */ + USBD_LL_Start(pdev); + + return USBD_OK; +} + +/** + * @brief USBD_Stop + * Stop the USB Device Core. + * @param pdev: Device Handle + * @retval USBD Status + */ +USBD_StatusTypeDef USBD_Stop (USBD_HandleTypeDef *pdev) +{ + /* Free Class Resources */ + pdev->pClass->DeInit(pdev, pdev->dev_config); + + /* Stop the low level driver */ + USBD_LL_Stop(pdev); + + return USBD_OK; +} + +/** +* @brief USBD_RunTestMode +* Launch test mode process +* @param pdev: device instance +* @retval status +*/ +USBD_StatusTypeDef USBD_RunTestMode (USBD_HandleTypeDef *pdev) +{ + return USBD_OK; +} + + +/** +* @brief USBD_SetClassConfig +* Configure device and start the interface +* @param pdev: device instance +* @param cfgidx: configuration index +* @retval status +*/ + +USBD_StatusTypeDef USBD_SetClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx) +{ + USBD_StatusTypeDef ret = USBD_FAIL; + + if(pdev->pClass != NULL) + { + /* Set configuration and Start the Class*/ + if(pdev->pClass->Init(pdev, cfgidx) == 0) + { + ret = USBD_OK; + } + } + return ret; +} + +/** +* @brief USBD_ClrClassConfig +* Clear current configuration +* @param pdev: device instance +* @param cfgidx: configuration index +* @retval status: USBD_StatusTypeDef +*/ +USBD_StatusTypeDef USBD_ClrClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx) +{ + /* Clear configuration and De-initialize the Class process*/ + pdev->pClass->DeInit(pdev, cfgidx); + return USBD_OK; +} + + +/** +* @brief USBD_SetupStage +* Handle the setup stage +* @param pdev: device instance +* @retval status +*/ +USBD_StatusTypeDef USBD_LL_SetupStage(USBD_HandleTypeDef *pdev, uint8_t *psetup) +{ + + USBD_ParseSetupRequest(&pdev->request, psetup); + + pdev->ep0_state = USBD_EP0_SETUP; + pdev->ep0_data_len = pdev->request.wLength; + + switch (pdev->request.bmRequest & 0x1F) + { + case USB_REQ_RECIPIENT_DEVICE: + USBD_StdDevReq (pdev, &pdev->request); + break; + + case USB_REQ_RECIPIENT_INTERFACE: + USBD_StdItfReq(pdev, &pdev->request); + break; + + case USB_REQ_RECIPIENT_ENDPOINT: + USBD_StdEPReq(pdev, &pdev->request); + break; + + default: + USBD_LL_StallEP(pdev , pdev->request.bmRequest & 0x80); + break; + } + return USBD_OK; +} + +/** +* @brief USBD_DataOutStage +* Handle data OUT stage +* @param pdev: device instance +* @param epnum: endpoint index +* @retval status +*/ +USBD_StatusTypeDef USBD_LL_DataOutStage(USBD_HandleTypeDef *pdev , uint8_t epnum, uint8_t *pdata) +{ + USBD_EndpointTypeDef *pep; + + if(epnum == 0) + { + pep = &pdev->ep_out[0]; + + if ( pdev->ep0_state == USBD_EP0_DATA_OUT) + { + if(pep->rem_length > pep->maxpacket) + { + pep->rem_length -= pep->maxpacket; + + USBD_CtlContinueRx (pdev, + pdata, + MIN(pep->rem_length ,pep->maxpacket)); + } + else + { + if((pdev->pClass->EP0_RxReady != NULL)&& + (pdev->dev_state == USBD_STATE_CONFIGURED)) + { + pdev->pClass->EP0_RxReady(pdev); + } + USBD_CtlSendStatus(pdev); + } + } + } + else if((pdev->pClass->DataOut != NULL)&& + (pdev->dev_state == USBD_STATE_CONFIGURED)) + { + pdev->pClass->DataOut(pdev, epnum); + } + return USBD_OK; +} + +/** +* @brief USBD_DataInStage +* Handle data in stage +* @param pdev: device instance +* @param epnum: endpoint index +* @retval status +*/ +USBD_StatusTypeDef USBD_LL_DataInStage(USBD_HandleTypeDef *pdev ,uint8_t epnum, uint8_t *pdata) +{ + USBD_EndpointTypeDef *pep; + + if(epnum == 0) + { + pep = &pdev->ep_in[0]; + + if ( pdev->ep0_state == USBD_EP0_DATA_IN) + { + if(pep->rem_length > pep->maxpacket) + { + pep->rem_length -= pep->maxpacket; + + USBD_CtlContinueSendData (pdev, + pdata, + pep->rem_length); + + /* Prepare endpoint for premature end of transfer */ + USBD_LL_PrepareReceive (pdev, + 0, + NULL, + 0); + } + else + { /* last packet is MPS multiple, so send ZLP packet */ + if((pep->total_length % pep->maxpacket == 0) && + (pep->total_length >= pep->maxpacket) && + (pep->total_length < pdev->ep0_data_len )) + { + + USBD_CtlContinueSendData(pdev , NULL, 0); + pdev->ep0_data_len = 0; + + /* Prepare endpoint for premature end of transfer */ + USBD_LL_PrepareReceive (pdev, + 0, + NULL, + 0); + } + else + { + if((pdev->pClass->EP0_TxSent != NULL)&& + (pdev->dev_state == USBD_STATE_CONFIGURED)) + { + pdev->pClass->EP0_TxSent(pdev); + } + USBD_CtlReceiveStatus(pdev); + } + } + } + if (pdev->dev_test_mode == 1) + { + USBD_RunTestMode(pdev); + pdev->dev_test_mode = 0; + } + } + else if((pdev->pClass->DataIn != NULL)&& + (pdev->dev_state == USBD_STATE_CONFIGURED)) + { + pdev->pClass->DataIn(pdev, epnum); + } + return USBD_OK; +} + +/** +* @brief USBD_LL_Reset +* Handle Reset event +* @param pdev: device instance +* @retval status +*/ + +USBD_StatusTypeDef USBD_LL_Reset(USBD_HandleTypeDef *pdev) +{ + /* Open EP0 OUT */ + USBD_LL_OpenEP(pdev, + 0x00, + USBD_EP_TYPE_CTRL, + USB_MAX_EP0_SIZE); + + pdev->ep_out[0].maxpacket = USB_MAX_EP0_SIZE; + + /* Open EP0 IN */ + USBD_LL_OpenEP(pdev, + 0x80, + USBD_EP_TYPE_CTRL, + USB_MAX_EP0_SIZE); + + pdev->ep_in[0].maxpacket = USB_MAX_EP0_SIZE; + /* Upon Reset call user call back */ + pdev->dev_state = USBD_STATE_DEFAULT; + + if (pdev->pClassData) + pdev->pClass->DeInit(pdev, pdev->dev_config); + + + return USBD_OK; +} + + + + +/** +* @brief USBD_LL_Reset +* Handle Reset event +* @param pdev: device instance +* @retval status +*/ +USBD_StatusTypeDef USBD_LL_SetSpeed(USBD_HandleTypeDef *pdev, USBD_SpeedTypeDef speed) +{ + pdev->dev_speed = speed; + return USBD_OK; +} + +/** +* @brief USBD_Suspend +* Handle Suspend event +* @param pdev: device instance +* @retval status +*/ + +USBD_StatusTypeDef USBD_LL_Suspend(USBD_HandleTypeDef *pdev) +{ + pdev->dev_old_state = pdev->dev_state; + pdev->dev_state = USBD_STATE_SUSPENDED; + return USBD_OK; +} + +/** +* @brief USBD_Resume +* Handle Resume event +* @param pdev: device instance +* @retval status +*/ + +USBD_StatusTypeDef USBD_LL_Resume(USBD_HandleTypeDef *pdev) +{ + pdev->dev_state = pdev->dev_old_state; + return USBD_OK; +} + +/** +* @brief USBD_SOF +* Handle SOF event +* @param pdev: device instance +* @retval status +*/ + +USBD_StatusTypeDef USBD_LL_SOF(USBD_HandleTypeDef *pdev) +{ + if(pdev->dev_state == USBD_STATE_CONFIGURED) + { + if(pdev->pClass->SOF != NULL) + { + pdev->pClass->SOF(pdev); + } + } + return USBD_OK; +} + +/** +* @brief USBD_IsoINIncomplete +* Handle iso in incomplete event +* @param pdev: device instance +* @retval status +*/ +USBD_StatusTypeDef USBD_LL_IsoINIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + return USBD_OK; +} + +/** +* @brief USBD_IsoOUTIncomplete +* Handle iso out incomplete event +* @param pdev: device instance +* @retval status +*/ +USBD_StatusTypeDef USBD_LL_IsoOUTIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + return USBD_OK; +} + +/** +* @brief USBD_DevConnected +* Handle device connection event +* @param pdev: device instance +* @retval status +*/ +USBD_StatusTypeDef USBD_LL_DevConnected(USBD_HandleTypeDef *pdev) +{ + return USBD_OK; +} + +/** +* @brief USBD_DevDisconnected +* Handle device disconnection event +* @param pdev: device instance +* @retval status +*/ +USBD_StatusTypeDef USBD_LL_DevDisconnected(USBD_HandleTypeDef *pdev) +{ + /* Free Class Resources */ + pdev->dev_state = USBD_STATE_DEFAULT; + pdev->pClass->DeInit(pdev, pdev->dev_config); + + return USBD_OK; +} +/** +* @} +*/ + + +/** +* @} +*/ + + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c new file mode 100644 index 0000000..22f815d --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c @@ -0,0 +1,782 @@ +/** + ****************************************************************************** + * @file usbd_req.c + * @author MCD Application Team + * @version V2.4.2 + * @date 11-December-2015 + * @brief This file provides the standard USB requests following chapter 9. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2015 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (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.st.com/software_license_agreement_liberty_v2 + * + * 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_ctlreq.h" +#include "usbd_ioreq.h" + + +/** @addtogroup STM32_USBD_STATE_DEVICE_LIBRARY + * @{ + */ + + +/** @defgroup USBD_REQ + * @brief USB standard requests module + * @{ + */ + +/** @defgroup USBD_REQ_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_REQ_Private_Defines + * @{ + */ + +/** + * @} + */ + + +/** @defgroup USBD_REQ_Private_Macros + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_REQ_Private_Variables + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_REQ_Private_FunctionPrototypes + * @{ + */ +static void USBD_GetDescriptor(USBD_HandleTypeDef *pdev , + USBD_SetupReqTypedef *req); + +static void USBD_SetAddress(USBD_HandleTypeDef *pdev , + USBD_SetupReqTypedef *req); + +static void USBD_SetConfig(USBD_HandleTypeDef *pdev , + USBD_SetupReqTypedef *req); + +static void USBD_GetConfig(USBD_HandleTypeDef *pdev , + USBD_SetupReqTypedef *req); + +static void USBD_GetStatus(USBD_HandleTypeDef *pdev , + USBD_SetupReqTypedef *req); + +static void USBD_SetFeature(USBD_HandleTypeDef *pdev , + USBD_SetupReqTypedef *req); + +static void USBD_ClrFeature(USBD_HandleTypeDef *pdev , + USBD_SetupReqTypedef *req); + +static uint8_t USBD_GetLen(uint8_t *buf); + +/** + * @} + */ + + +/** @defgroup USBD_REQ_Private_Functions + * @{ + */ + + +/** +* @brief USBD_StdDevReq +* Handle standard usb device requests +* @param pdev: device instance +* @param req: usb request +* @retval status +*/ +USBD_StatusTypeDef USBD_StdDevReq (USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req) +{ + USBD_StatusTypeDef ret = USBD_OK; + + switch (req->bRequest) + { + case USB_REQ_GET_DESCRIPTOR: + + USBD_GetDescriptor (pdev, req) ; + break; + + case USB_REQ_SET_ADDRESS: + USBD_SetAddress(pdev, req); + break; + + case USB_REQ_SET_CONFIGURATION: + USBD_SetConfig (pdev , req); + break; + + case USB_REQ_GET_CONFIGURATION: + USBD_GetConfig (pdev , req); + break; + + case USB_REQ_GET_STATUS: + USBD_GetStatus (pdev , req); + break; + + + case USB_REQ_SET_FEATURE: + USBD_SetFeature (pdev , req); + break; + + case USB_REQ_CLEAR_FEATURE: + USBD_ClrFeature (pdev , req); + break; + + default: + USBD_CtlError(pdev , req); + break; + } + + return ret; +} + +/** +* @brief USBD_StdItfReq +* Handle standard usb interface requests +* @param pdev: device instance +* @param req: usb request +* @retval status +*/ +USBD_StatusTypeDef USBD_StdItfReq (USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req) +{ + USBD_StatusTypeDef ret = USBD_OK; + + switch (pdev->dev_state) + { + case USBD_STATE_CONFIGURED: + + if (LOBYTE(req->wIndex) <= USBD_MAX_NUM_INTERFACES) + { + pdev->pClass->Setup (pdev, req); + + if((req->wLength == 0)&& (ret == USBD_OK)) + { + USBD_CtlSendStatus(pdev); + } + } + else + { + USBD_CtlError(pdev , req); + } + break; + + default: + USBD_CtlError(pdev , req); + break; + } + return USBD_OK; +} + +/** +* @brief USBD_StdEPReq +* Handle standard usb endpoint requests +* @param pdev: device instance +* @param req: usb request +* @retval status +*/ +USBD_StatusTypeDef USBD_StdEPReq (USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req) +{ + + uint8_t ep_addr; + USBD_StatusTypeDef ret = USBD_OK; + USBD_EndpointTypeDef *pep; + ep_addr = LOBYTE(req->wIndex); + + /* Check if it is a class request */ + if ((req->bmRequest & 0x60) == 0x20) + { + pdev->pClass->Setup (pdev, req); + + return USBD_OK; + } + + switch (req->bRequest) + { + + case USB_REQ_SET_FEATURE : + + switch (pdev->dev_state) + { + case USBD_STATE_ADDRESSED: + if ((ep_addr != 0x00) && (ep_addr != 0x80)) + { + USBD_LL_StallEP(pdev , ep_addr); + } + break; + + case USBD_STATE_CONFIGURED: + if (req->wValue == USB_FEATURE_EP_HALT) + { + if ((ep_addr != 0x00) && (ep_addr != 0x80)) + { + USBD_LL_StallEP(pdev , ep_addr); + + } + } + pdev->pClass->Setup (pdev, req); + USBD_CtlSendStatus(pdev); + + break; + + default: + USBD_CtlError(pdev , req); + break; + } + break; + + case USB_REQ_CLEAR_FEATURE : + + switch (pdev->dev_state) + { + case USBD_STATE_ADDRESSED: + if ((ep_addr != 0x00) && (ep_addr != 0x80)) + { + USBD_LL_StallEP(pdev , ep_addr); + } + break; + + case USBD_STATE_CONFIGURED: + if (req->wValue == USB_FEATURE_EP_HALT) + { + if ((ep_addr & 0x7F) != 0x00) + { + USBD_LL_ClearStallEP(pdev , ep_addr); + pdev->pClass->Setup (pdev, req); + } + USBD_CtlSendStatus(pdev); + } + break; + + default: + USBD_CtlError(pdev , req); + break; + } + break; + + case USB_REQ_GET_STATUS: + switch (pdev->dev_state) + { + case USBD_STATE_ADDRESSED: + if ((ep_addr & 0x7F) != 0x00) + { + USBD_LL_StallEP(pdev , ep_addr); + } + break; + + case USBD_STATE_CONFIGURED: + pep = ((ep_addr & 0x80) == 0x80) ? &pdev->ep_in[ep_addr & 0x7F]:\ + &pdev->ep_out[ep_addr & 0x7F]; + if(USBD_LL_IsStallEP(pdev, ep_addr)) + { + pep->status = 0x0001; + } + else + { + pep->status = 0x0000; + } + + USBD_CtlSendData (pdev, + (uint8_t *)&pep->status, + 2); + break; + + default: + USBD_CtlError(pdev , req); + break; + } + break; + + default: + break; + } + return ret; +} +/** +* @brief USBD_GetDescriptor +* Handle Get Descriptor requests +* @param pdev: device instance +* @param req: usb request +* @retval status +*/ +static void USBD_GetDescriptor(USBD_HandleTypeDef *pdev , + USBD_SetupReqTypedef *req) +{ + uint16_t len; + uint8_t *pbuf; + + + switch (req->wValue >> 8) + { +#if (USBD_LPM_ENABLED == 1) + case USB_DESC_TYPE_BOS: + pbuf = pdev->pDesc->GetBOSDescriptor(pdev->dev_speed, &len); + break; +#endif + case USB_DESC_TYPE_DEVICE: + pbuf = pdev->pDesc->GetDeviceDescriptor(pdev->dev_speed, &len); + break; + + case USB_DESC_TYPE_CONFIGURATION: + if(pdev->dev_speed == USBD_SPEED_HIGH ) + { + pbuf = (uint8_t *)pdev->pClass->GetHSConfigDescriptor(&len); + pbuf[1] = USB_DESC_TYPE_CONFIGURATION; + } + else + { + pbuf = (uint8_t *)pdev->pClass->GetFSConfigDescriptor(&len); + pbuf[1] = USB_DESC_TYPE_CONFIGURATION; + } + break; + + case USB_DESC_TYPE_STRING: + switch ((uint8_t)(req->wValue)) + { + case USBD_IDX_LANGID_STR: + pbuf = pdev->pDesc->GetLangIDStrDescriptor(pdev->dev_speed, &len); + break; + + case USBD_IDX_MFC_STR: + pbuf = pdev->pDesc->GetManufacturerStrDescriptor(pdev->dev_speed, &len); + break; + + case USBD_IDX_PRODUCT_STR: + pbuf = pdev->pDesc->GetProductStrDescriptor(pdev->dev_speed, &len); + break; + + case USBD_IDX_SERIAL_STR: + pbuf = pdev->pDesc->GetSerialStrDescriptor(pdev->dev_speed, &len); + break; + + case USBD_IDX_CONFIG_STR: + pbuf = pdev->pDesc->GetConfigurationStrDescriptor(pdev->dev_speed, &len); + break; + + case USBD_IDX_INTERFACE_STR: + pbuf = pdev->pDesc->GetInterfaceStrDescriptor(pdev->dev_speed, &len); + break; + + default: +#if (USBD_SUPPORT_USER_STRING == 1) + pbuf = pdev->pClass->GetUsrStrDescriptor(pdev, (req->wValue) , &len); + break; +#else + USBD_CtlError(pdev , req); + return; +#endif + } + break; + case USB_DESC_TYPE_DEVICE_QUALIFIER: + + if(pdev->dev_speed == USBD_SPEED_HIGH ) + { + pbuf = (uint8_t *)pdev->pClass->GetDeviceQualifierDescriptor(&len); + break; + } + else + { + USBD_CtlError(pdev , req); + return; + } + + case USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION: + if(pdev->dev_speed == USBD_SPEED_HIGH ) + { + pbuf = (uint8_t *)pdev->pClass->GetOtherSpeedConfigDescriptor(&len); + pbuf[1] = USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION; + break; + } + else + { + USBD_CtlError(pdev , req); + return; + } + + default: + USBD_CtlError(pdev , req); + return; + } + + if((len != 0)&& (req->wLength != 0)) + { + + len = MIN(len , req->wLength); + + USBD_CtlSendData (pdev, + pbuf, + len); + } + +} + +/** +* @brief USBD_SetAddress +* Set device address +* @param pdev: device instance +* @param req: usb request +* @retval status +*/ +static void USBD_SetAddress(USBD_HandleTypeDef *pdev , + USBD_SetupReqTypedef *req) +{ + uint8_t dev_addr; + + if ((req->wIndex == 0) && (req->wLength == 0)) + { + dev_addr = (uint8_t)(req->wValue) & 0x7F; + + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + USBD_CtlError(pdev , req); + } + else + { + pdev->dev_address = dev_addr; + USBD_LL_SetUSBAddress(pdev, dev_addr); + USBD_CtlSendStatus(pdev); + + if (dev_addr != 0) + { + pdev->dev_state = USBD_STATE_ADDRESSED; + } + else + { + pdev->dev_state = USBD_STATE_DEFAULT; + } + } + } + else + { + USBD_CtlError(pdev , req); + } +} + +/** +* @brief USBD_SetConfig +* Handle Set device configuration request +* @param pdev: device instance +* @param req: usb request +* @retval status +*/ +static void USBD_SetConfig(USBD_HandleTypeDef *pdev , + USBD_SetupReqTypedef *req) +{ + + static uint8_t cfgidx; + + cfgidx = (uint8_t)(req->wValue); + + if (cfgidx > USBD_MAX_NUM_CONFIGURATION ) + { + USBD_CtlError(pdev , req); + } + else + { + switch (pdev->dev_state) + { + case USBD_STATE_ADDRESSED: + if (cfgidx) + { + pdev->dev_config = cfgidx; + pdev->dev_state = USBD_STATE_CONFIGURED; + if(USBD_SetClassConfig(pdev , cfgidx) == USBD_FAIL) + { + USBD_CtlError(pdev , req); + return; + } + USBD_CtlSendStatus(pdev); + } + else + { + USBD_CtlSendStatus(pdev); + } + break; + + case USBD_STATE_CONFIGURED: + if (cfgidx == 0) + { + pdev->dev_state = USBD_STATE_ADDRESSED; + pdev->dev_config = cfgidx; + USBD_ClrClassConfig(pdev , cfgidx); + USBD_CtlSendStatus(pdev); + + } + else if (cfgidx != pdev->dev_config) + { + /* Clear old configuration */ + USBD_ClrClassConfig(pdev , pdev->dev_config); + + /* set new configuration */ + pdev->dev_config = cfgidx; + if(USBD_SetClassConfig(pdev , cfgidx) == USBD_FAIL) + { + USBD_CtlError(pdev , req); + return; + } + USBD_CtlSendStatus(pdev); + } + else + { + USBD_CtlSendStatus(pdev); + } + break; + + default: + USBD_CtlError(pdev , req); + break; + } + } +} + +/** +* @brief USBD_GetConfig +* Handle Get device configuration request +* @param pdev: device instance +* @param req: usb request +* @retval status +*/ +static void USBD_GetConfig(USBD_HandleTypeDef *pdev , + USBD_SetupReqTypedef *req) +{ + + if (req->wLength != 1) + { + USBD_CtlError(pdev , req); + } + else + { + switch (pdev->dev_state ) + { + case USBD_STATE_ADDRESSED: + pdev->dev_default_config = 0; + USBD_CtlSendData (pdev, + (uint8_t *)&pdev->dev_default_config, + 1); + break; + + case USBD_STATE_CONFIGURED: + + USBD_CtlSendData (pdev, + (uint8_t *)&pdev->dev_config, + 1); + break; + + default: + USBD_CtlError(pdev , req); + break; + } + } +} + +/** +* @brief USBD_GetStatus +* Handle Get Status request +* @param pdev: device instance +* @param req: usb request +* @retval status +*/ +static void USBD_GetStatus(USBD_HandleTypeDef *pdev , + USBD_SetupReqTypedef *req) +{ + + + switch (pdev->dev_state) + { + case USBD_STATE_ADDRESSED: + case USBD_STATE_CONFIGURED: + +#if ( USBD_SELF_POWERED == 1) + pdev->dev_config_status = USB_CONFIG_SELF_POWERED; +#else + pdev->dev_config_status = 0; +#endif + + if (pdev->dev_remote_wakeup) + { + pdev->dev_config_status |= USB_CONFIG_REMOTE_WAKEUP; + } + + USBD_CtlSendData (pdev, + (uint8_t *)& pdev->dev_config_status, + 2); + break; + + default : + USBD_CtlError(pdev , req); + break; + } +} + + +/** +* @brief USBD_SetFeature +* Handle Set device feature request +* @param pdev: device instance +* @param req: usb request +* @retval status +*/ +static void USBD_SetFeature(USBD_HandleTypeDef *pdev , + USBD_SetupReqTypedef *req) +{ + + if (req->wValue == USB_FEATURE_REMOTE_WAKEUP) + { + pdev->dev_remote_wakeup = 1; + pdev->pClass->Setup (pdev, req); + USBD_CtlSendStatus(pdev); + } + +} + + +/** +* @brief USBD_ClrFeature +* Handle clear device feature request +* @param pdev: device instance +* @param req: usb request +* @retval status +*/ +static void USBD_ClrFeature(USBD_HandleTypeDef *pdev , + USBD_SetupReqTypedef *req) +{ + switch (pdev->dev_state) + { + case USBD_STATE_ADDRESSED: + case USBD_STATE_CONFIGURED: + if (req->wValue == USB_FEATURE_REMOTE_WAKEUP) + { + pdev->dev_remote_wakeup = 0; + pdev->pClass->Setup (pdev, req); + USBD_CtlSendStatus(pdev); + } + break; + + default : + USBD_CtlError(pdev , req); + break; + } +} + +/** +* @brief USBD_ParseSetupRequest +* Copy buffer into setup structure +* @param pdev: device instance +* @param req: usb request +* @retval None +*/ + +void USBD_ParseSetupRequest(USBD_SetupReqTypedef *req, uint8_t *pdata) +{ + req->bmRequest = *(uint8_t *) (pdata); + req->bRequest = *(uint8_t *) (pdata + 1); + req->wValue = SWAPBYTE (pdata + 2); + req->wIndex = SWAPBYTE (pdata + 4); + req->wLength = SWAPBYTE (pdata + 6); + +} + +/** +* @brief USBD_CtlError +* Handle USB low level Error +* @param pdev: device instance +* @param req: usb request +* @retval None +*/ + +void USBD_CtlError( USBD_HandleTypeDef *pdev , + USBD_SetupReqTypedef *req) +{ + USBD_LL_StallEP(pdev , 0x80); + USBD_LL_StallEP(pdev , 0); +} + + +/** + * @brief USBD_GetString + * Convert Ascii string into unicode one + * @param desc : descriptor buffer + * @param unicode : Formatted string buffer (unicode) + * @param len : descriptor length + * @retval None + */ +void USBD_GetString(uint8_t *desc, uint8_t *unicode, uint16_t *len) +{ + uint8_t idx = 0; + + if (desc != NULL) + { + *len = USBD_GetLen(desc) * 2 + 2; + unicode[idx++] = *len; + unicode[idx++] = USB_DESC_TYPE_STRING; + + while (*desc != '\0') + { + unicode[idx++] = *desc++; + unicode[idx++] = 0x00; + } + } +} + +/** + * @brief USBD_GetLen + * return the string length + * @param buf : pointer to the ascii string buffer + * @retval string length + */ +static uint8_t USBD_GetLen(uint8_t *buf) +{ + uint8_t len = 0; + + while (*buf != '\0') + { + len++; + buf++; + } + + return len; +} +/** + * @} + */ + + +/** + * @} + */ + + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c new file mode 100644 index 0000000..e1b9c75 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c @@ -0,0 +1,236 @@ +/** + ****************************************************************************** + * @file usbd_ioreq.c + * @author MCD Application Team + * @version V2.4.2 + * @date 11-December-2015 + * @brief This file provides the IO requests APIs for control endpoints. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2015 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (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.st.com/software_license_agreement_liberty_v2 + * + * 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_ioreq.h" + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + + +/** @defgroup USBD_IOREQ + * @brief control I/O requests module + * @{ + */ + +/** @defgroup USBD_IOREQ_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_IOREQ_Private_Defines + * @{ + */ + +/** + * @} + */ + + +/** @defgroup USBD_IOREQ_Private_Macros + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_IOREQ_Private_Variables + * @{ + */ + +/** + * @} + */ + + +/** @defgroup USBD_IOREQ_Private_FunctionPrototypes + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_IOREQ_Private_Functions + * @{ + */ + +/** +* @brief USBD_CtlSendData +* send data on the ctl pipe +* @param pdev: device instance +* @param buff: pointer to data buffer +* @param len: length of data to be sent +* @retval status +*/ +USBD_StatusTypeDef USBD_CtlSendData (USBD_HandleTypeDef *pdev, + uint8_t *pbuf, + uint16_t len) +{ + /* Set EP0 State */ + pdev->ep0_state = USBD_EP0_DATA_IN; + pdev->ep_in[0].total_length = len; + pdev->ep_in[0].rem_length = len; + /* Start the transfer */ + USBD_LL_Transmit (pdev, 0x00, pbuf, len); + + return USBD_OK; +} + +/** +* @brief USBD_CtlContinueSendData +* continue sending data on the ctl pipe +* @param pdev: device instance +* @param buff: pointer to data buffer +* @param len: length of data to be sent +* @retval status +*/ +USBD_StatusTypeDef USBD_CtlContinueSendData (USBD_HandleTypeDef *pdev, + uint8_t *pbuf, + uint16_t len) +{ + /* Start the next transfer */ + USBD_LL_Transmit (pdev, 0x00, pbuf, len); + + return USBD_OK; +} + +/** +* @brief USBD_CtlPrepareRx +* receive data on the ctl pipe +* @param pdev: device instance +* @param buff: pointer to data buffer +* @param len: length of data to be received +* @retval status +*/ +USBD_StatusTypeDef USBD_CtlPrepareRx (USBD_HandleTypeDef *pdev, + uint8_t *pbuf, + uint16_t len) +{ + /* Set EP0 State */ + pdev->ep0_state = USBD_EP0_DATA_OUT; + pdev->ep_out[0].total_length = len; + pdev->ep_out[0].rem_length = len; + /* Start the transfer */ + USBD_LL_PrepareReceive (pdev, + 0, + pbuf, + len); + + return USBD_OK; +} + +/** +* @brief USBD_CtlContinueRx +* continue receive data on the ctl pipe +* @param pdev: device instance +* @param buff: pointer to data buffer +* @param len: length of data to be received +* @retval status +*/ +USBD_StatusTypeDef USBD_CtlContinueRx (USBD_HandleTypeDef *pdev, + uint8_t *pbuf, + uint16_t len) +{ + + USBD_LL_PrepareReceive (pdev, + 0, + pbuf, + len); + return USBD_OK; +} +/** +* @brief USBD_CtlSendStatus +* send zero lzngth packet on the ctl pipe +* @param pdev: device instance +* @retval status +*/ +USBD_StatusTypeDef USBD_CtlSendStatus (USBD_HandleTypeDef *pdev) +{ + + /* Set EP0 State */ + pdev->ep0_state = USBD_EP0_STATUS_IN; + + /* Start the transfer */ + USBD_LL_Transmit (pdev, 0x00, NULL, 0); + + return USBD_OK; +} + +/** +* @brief USBD_CtlReceiveStatus +* receive zero lzngth packet on the ctl pipe +* @param pdev: device instance +* @retval status +*/ +USBD_StatusTypeDef USBD_CtlReceiveStatus (USBD_HandleTypeDef *pdev) +{ + /* Set EP0 State */ + pdev->ep0_state = USBD_EP0_STATUS_OUT; + + /* Start the transfer */ + USBD_LL_PrepareReceive ( pdev, + 0, + NULL, + 0); + + return USBD_OK; +} + + +/** +* @brief USBD_GetRxCount +* returns the received data length +* @param pdev: device instance +* @param ep_addr: endpoint address +* @retval Rx Data blength +*/ +uint16_t USBD_GetRxCount (USBD_HandleTypeDef *pdev , uint8_t ep_addr) +{ + return USBD_LL_GetRxDataSize(pdev, ep_addr); +} + +/** + * @} + */ + + +/** + * @} + */ + + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Nucleo-L476RG.elf.launch b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Nucleo-L476RG.elf.launch new file mode 100644 index 0000000..b2828f8 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Nucleo-L476RG.elf.launch @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Nucleo-L476RG.ioc b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Nucleo-L476RG.ioc new file mode 100644 index 0000000..fa582a9 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Nucleo-L476RG.ioc @@ -0,0 +1,227 @@ +#MicroXplorer Configuration settings - do not modify +File.Version=6 +KeepUserPlacement=false +Mcu.Family=STM32L4 +Mcu.IP0=NVIC +Mcu.IP1=RCC +Mcu.IP2=RNG +Mcu.IP3=RTC +Mcu.IP4=SYS +Mcu.IP5=USART2 +Mcu.IP6=USB_DEVICE +Mcu.IP7=USB_OTG_FS +Mcu.IPNb=8 +Mcu.Name=STM32L476R(C-E-G)Tx +Mcu.Package=LQFP64 +Mcu.Pin0=PC13 +Mcu.Pin1=PC14-OSC32_IN (PC14) +Mcu.Pin10=PA13 (JTMS-SWDIO) +Mcu.Pin11=PA14 (JTCK-SWCLK) +Mcu.Pin12=PB3 (JTDO-TRACESWO) +Mcu.Pin13=VP_RNG_VS_RNG +Mcu.Pin14=VP_RTC_VS_RTC_Activate +Mcu.Pin15=VP_RTC_VS_RTC_Calendar +Mcu.Pin16=VP_SYS_VS_Systick +Mcu.Pin17=VP_USB_DEVICE_VS_USB_DEVICE_CDC_FS +Mcu.Pin2=PC15-OSC32_OUT (PC15) +Mcu.Pin3=PH0-OSC_IN (PH0) +Mcu.Pin4=PH1-OSC_OUT (PH1) +Mcu.Pin5=PA2 +Mcu.Pin6=PA3 +Mcu.Pin7=PA5 +Mcu.Pin8=PA11 +Mcu.Pin9=PA12 +Mcu.PinsNb=18 +Mcu.ThirdPartyNb=0 +Mcu.UserConstants= +Mcu.UserName=STM32L476RGTx +MxCube.Version=4.25.0 +MxDb.Version=DB.4.0.250 +NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:false\:false +NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:false\:false +NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:false\:false +NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:false\:false +NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:false\:false +NVIC.OTG_FS_IRQn=true\:0\:0\:false\:false\:true\:false +NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:false\:false +NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4 +NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:false\:false +NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:true +NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:false\:false +PA11.Mode=Device_Only +PA11.Signal=USB_OTG_FS_DM +PA12.Mode=Device_Only +PA12.Signal=USB_OTG_FS_DP +PA13\ (JTMS-SWDIO).GPIOParameters=GPIO_Label +PA13\ (JTMS-SWDIO).GPIO_Label=TMS +PA13\ (JTMS-SWDIO).Locked=true +PA13\ (JTMS-SWDIO).Mode=Trace_Asynchronous_SW +PA13\ (JTMS-SWDIO).Signal=SYS_JTMS-SWDIO +PA14\ (JTCK-SWCLK).GPIOParameters=GPIO_Label +PA14\ (JTCK-SWCLK).GPIO_Label=TCK +PA14\ (JTCK-SWCLK).Locked=true +PA14\ (JTCK-SWCLK).Mode=Trace_Asynchronous_SW +PA14\ (JTCK-SWCLK).Signal=SYS_JTCK-SWCLK +PA2.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label,GPIO_Mode +PA2.GPIO_Label=USART_TX +PA2.GPIO_Mode=GPIO_MODE_AF_PP +PA2.GPIO_PuPd=GPIO_NOPULL +PA2.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH +PA2.Locked=true +PA2.Mode=Asynchronous +PA2.Signal=USART2_TX +PA3.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label,GPIO_Mode +PA3.GPIO_Label=USART_RX +PA3.GPIO_Mode=GPIO_MODE_AF_PP +PA3.GPIO_PuPd=GPIO_NOPULL +PA3.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH +PA3.Locked=true +PA3.Mode=Asynchronous +PA3.Signal=USART2_RX +PA5.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultOutputPP +PA5.GPIO_Label=LD2 [green Led] +PA5.GPIO_ModeDefaultOutputPP=GPIO_MODE_OUTPUT_PP +PA5.GPIO_PuPd=GPIO_NOPULL +PA5.GPIO_Speed=GPIO_SPEED_FREQ_LOW +PA5.Locked=true +PA5.Signal=GPIO_Output +PB3\ (JTDO-TRACESWO).GPIOParameters=GPIO_Label +PB3\ (JTDO-TRACESWO).GPIO_Label=SWO +PB3\ (JTDO-TRACESWO).Locked=true +PB3\ (JTDO-TRACESWO).Mode=Trace_Asynchronous_SW +PB3\ (JTDO-TRACESWO).Signal=SYS_JTDO-SWO +PC13.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultEXTI +PC13.GPIO_Label=B1 [Blue PushButton] +PC13.GPIO_ModeDefaultEXTI=GPIO_MODE_IT_FALLING +PC13.GPIO_PuPd=GPIO_NOPULL +PC13.Locked=true +PC13.Signal=GPXTI13 +PC14-OSC32_IN\ (PC14).Locked=true +PC14-OSC32_IN\ (PC14).Mode=LSE-External-Oscillator +PC14-OSC32_IN\ (PC14).Signal=RCC_OSC32_IN +PC15-OSC32_OUT\ (PC15).Locked=true +PC15-OSC32_OUT\ (PC15).Mode=LSE-External-Oscillator +PC15-OSC32_OUT\ (PC15).Signal=RCC_OSC32_OUT +PCC.Checker=true +PCC.Line=STM32L4x6 +PCC.MCU=STM32L476R(C-E-G)Tx +PCC.PartNumber=STM32L476RGTx +PCC.Seq0=0 +PCC.Series=STM32L4 +PCC.Temperature=25 +PCC.Vdd=3.0 +PH0-OSC_IN\ (PH0).Locked=true +PH0-OSC_IN\ (PH0).Signal=RCC_OSC_IN +PH1-OSC_OUT\ (PH1).Locked=true +PH1-OSC_OUT\ (PH1).Signal=RCC_OSC_OUT +PinOutPanel.RotationAngle=0 +ProjectManager.AskForMigrate=true +ProjectManager.BackupPrevious=false +ProjectManager.CompilerOptimize=3 +ProjectManager.ComputerToolchain=false +ProjectManager.CoupleFile=false +ProjectManager.CustomerFirmwarePackage=C\:/Users/Stefanth/STM32Cube/Repository/STM32Cube_FW_L4_V1.11.0 +ProjectManager.DefaultFWLocation=true +ProjectManager.DeletePrevious=true +ProjectManager.DeviceId=STM32L476RGTx +ProjectManager.FirmwarePackage=STM32Cube FW_L4 V1.11.0 +ProjectManager.FreePins=false +ProjectManager.HalAssertFull=false +ProjectManager.HeapSize=0x200 +ProjectManager.KeepUserCode=true +ProjectManager.LastFirmware=true +ProjectManager.LibraryCopy=1 +ProjectManager.MainLocation=Src +ProjectManager.PreviousToolchain=TrueSTUDIO +ProjectManager.ProjectBuild=false +ProjectManager.ProjectFileName=Nucleo-L476RG.ioc +ProjectManager.ProjectName=Nucleo-L476RG +ProjectManager.StackSize=0xf000 +ProjectManager.TargetToolchain=TrueSTUDIO +ProjectManager.ToolChainLocation= +ProjectManager.UnderRoot=true +ProjectManager.functionlistsort=1-MX_GPIO_Init-GPIO-false-HAL-true,2-SystemClock_Config-RCC-false-HAL-true,3-MX_RNG_Init-RNG-false-HAL-true,4-MX_RTC_Init-RTC-false-HAL-true,5-MX_USART2_UART_Init-USART2-false-HAL-true,6-MX_USB_DEVICE_Init-USB_DEVICE-false-HAL-true +RCC.ADCFreq_Value=64000000 +RCC.AHBFreq_Value=80000000 +RCC.APB1Freq_Value=80000000 +RCC.APB1TimFreq_Value=80000000 +RCC.APB2Freq_Value=80000000 +RCC.APB2TimFreq_Value=80000000 +RCC.CK48CLockSelection=RCC_USBCLKSOURCE_MSI +RCC.CortexFreq_Value=80000000 +RCC.DFSDMFreq_Value=80000000 +RCC.FCLKCortexFreq_Value=80000000 +RCC.FamilyName=M +RCC.HCLKFreq_Value=80000000 +RCC.HSE_VALUE=8000000 +RCC.HSI_VALUE=16000000 +RCC.I2C1Freq_Value=80000000 +RCC.I2C2Freq_Value=80000000 +RCC.I2C3Freq_Value=80000000 +RCC.IPParameters=ADCFreq_Value,AHBFreq_Value,APB1Freq_Value,APB1TimFreq_Value,APB2Freq_Value,APB2TimFreq_Value,CK48CLockSelection,CortexFreq_Value,DFSDMFreq_Value,FCLKCortexFreq_Value,FamilyName,HCLKFreq_Value,HSE_VALUE,HSI_VALUE,I2C1Freq_Value,I2C2Freq_Value,I2C3Freq_Value,LCDFreq_Value,LPTIM1Freq_Value,LPTIM2Freq_Value,LPUART1Freq_Value,LSCOPinFreq_Value,LSI_VALUE,MCO1PinFreq_Value,MSIClockRange,MSI_VALUE,PLLN,PLLPoutputFreq_Value,PLLQoutputFreq_Value,PLLRCLKFreq_Value,PLLSAI1PoutputFreq_Value,PLLSAI1QoutputFreq_Value,PLLSAI1RoutputFreq_Value,PLLSAI2PoutputFreq_Value,PLLSAI2RoutputFreq_Value,PLLSourceVirtual,PREFETCH_ENABLE,PWRFreq_Value,RNGFreq_Value,RTCClockSelection,RTCFreq_Value,SAI1Freq_Value,SAI2Freq_Value,SDMMCFreq_Value,SWPMI1Freq_Value,SYSCLKFreq_VALUE,SYSCLKSource,UART4Freq_Value,UART5Freq_Value,USART1Freq_Value,USART2Freq_Value,USART3Freq_Value,USBFreq_Value,VCOInputFreq_Value,VCOOutputFreq_Value,VCOSAI1OutputFreq_Value,VCOSAI2OutputFreq_Value +RCC.LCDFreq_Value=32768 +RCC.LPTIM1Freq_Value=80000000 +RCC.LPTIM2Freq_Value=80000000 +RCC.LPUART1Freq_Value=80000000 +RCC.LSCOPinFreq_Value=32000 +RCC.LSI_VALUE=32000 +RCC.MCO1PinFreq_Value=80000000 +RCC.MSIClockRange=RCC_MSIRANGE_11 +RCC.MSI_VALUE=48000000 +RCC.PLLN=10 +RCC.PLLPoutputFreq_Value=22857142.85714286 +RCC.PLLQoutputFreq_Value=80000000 +RCC.PLLRCLKFreq_Value=80000000 +RCC.PLLSAI1PoutputFreq_Value=18285714.285714287 +RCC.PLLSAI1QoutputFreq_Value=64000000 +RCC.PLLSAI1RoutputFreq_Value=64000000 +RCC.PLLSAI2PoutputFreq_Value=18285714.285714287 +RCC.PLLSAI2RoutputFreq_Value=64000000 +RCC.PLLSourceVirtual=RCC_PLLSOURCE_HSI +RCC.PREFETCH_ENABLE=1 +RCC.PWRFreq_Value=80000000 +RCC.RNGFreq_Value=48000000 +RCC.RTCClockSelection=RCC_RTCCLKSOURCE_LSE +RCC.RTCFreq_Value=32768 +RCC.SAI1Freq_Value=18285714.285714287 +RCC.SAI2Freq_Value=18285714.285714287 +RCC.SDMMCFreq_Value=48000000 +RCC.SWPMI1Freq_Value=80000000 +RCC.SYSCLKFreq_VALUE=80000000 +RCC.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK +RCC.UART4Freq_Value=80000000 +RCC.UART5Freq_Value=80000000 +RCC.USART1Freq_Value=80000000 +RCC.USART2Freq_Value=80000000 +RCC.USART3Freq_Value=80000000 +RCC.USBFreq_Value=48000000 +RCC.VCOInputFreq_Value=16000000 +RCC.VCOOutputFreq_Value=160000000 +RCC.VCOSAI1OutputFreq_Value=128000000 +RCC.VCOSAI2OutputFreq_Value=128000000 +RTC.Format=RTC_FORMAT_BIN +RTC.IPParameters=Format +SH.GPXTI13.0=GPIO_EXTI13 +SH.GPXTI13.ConfNb=1 +USART2.IPParameters=VirtualMode-Asynchronous,Mode,WordLength +USART2.Mode=MODE_TX +USART2.VirtualMode-Asynchronous=VM_ASYNC +USART2.WordLength=WORDLENGTH_8B +USB_DEVICE.CLASS_NAME_FS=CDC +USB_DEVICE.IPParameters=VirtualMode,VirtualModeFS,CLASS_NAME_FS +USB_DEVICE.VirtualMode=Cdc +USB_DEVICE.VirtualModeFS=Cdc_FS +USB_OTG_FS.IPParameters=VirtualMode +USB_OTG_FS.VirtualMode=Device_Only +VP_RNG_VS_RNG.Mode=RNG_Activate +VP_RNG_VS_RNG.Signal=RNG_VS_RNG +VP_RTC_VS_RTC_Activate.Mode=RTC_Enabled +VP_RTC_VS_RTC_Activate.Signal=RTC_VS_RTC_Activate +VP_RTC_VS_RTC_Calendar.Mode=RTC_Calendar +VP_RTC_VS_RTC_Calendar.Signal=RTC_VS_RTC_Calendar +VP_SYS_VS_Systick.Mode=SysTick +VP_SYS_VS_Systick.Signal=SYS_VS_Systick +VP_USB_DEVICE_VS_USB_DEVICE_CDC_FS.Mode=CDC_FS +VP_USB_DEVICE_VS_USB_DEVICE_CDC_FS.Signal=USB_DEVICE_VS_USB_DEVICE_CDC_FS +board=NUCLEO-L476RG +boardIOC=true diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Nucleo-L476RG.pdf b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Nucleo-L476RG.pdf new file mode 100644 index 0000000000000000000000000000000000000000..4e56c3045d7f85381774793b7377e6c29b2b5cb2 GIT binary patch literal 249470 zcmeFYWmp|+(kR*l2m}r8uEE_c!6CSNumoGUOOOPDyCi6WySuvvx8Ux<-A^Zb&wR7z zJag|o^PPL|`7vuf&02K#TdS(x@~Wm%6q8_NW#T}fT3s6+N8li3A+<5GAQcc`mN2(+ zG__}zurhQs6*D!qF)?L+ZEF3_(TtRnn?p#*!O`B-5Q5;EoT8@Zkj{eXwWTpHc?(dJ ziEJA~_ClPC#=dw};p^37Y3CbzKWtjkk_4@>p`fhKI~?>4;$5AwBn!fv)Fiu`ic!o`M|skY+e`HIUt844KI4G(}X7%G~jVjap&KQ@FJYFA1&7xotjfwAdg-F`UBc z>94ADNe4BGe&uZc4BMG~Xx!@z~ayh*Vqn4cw2ku8_g@*xoMf6M!uFW@q8cecM^(dteNw4)tXNFLNl2-wdeIf9N!^6>`H%7H;#$DzSgy zWbm?>VCUm-DZgi6ews5>`569*S{|R)s_Zc>cW30?lBf!`9K%#n%PO(}hgHQ^kGK_Y zfcyv(UN0i8{3i|l^BAA@_~3z$gRQ6<@B52;Z$zn^wH|@uF&Ga7Q)`ny1qu8H3LXO6 z9|8!HyxPXm4YzV(Lh$!wkwX zDYL4nt0O71Gz7fu)t{fDe|}2qF-w3De+f1#DeG^L5^SXGzrF~8FA%gn_-mw`zpu!d znwT5DvT@a60srOXbdQ6Fo0skH+V}Y5aT$0nBOxsTKs^BfDDVwD&HQ}7K%4m?4Ff<}XS>;yV|>Jb{9SegXpx3kw4S-t7fm2Vl@((aBg}KE+Tngd?}Z zWb=*s22b&-tPM+f^oWw($lmW60yYjV9zGQ{4ebj$4o)s^9$r3CF>wh=DQOuMRW)@D zO)YI>6Vtcv%*-tu9G#q9T;1G1eDn|a6c`j79TOWDpYZuhVtPhqR(4KqUVeE+WmR=e zZC!nPM`u@ePj6rU*!aZc)bx*;*_G9`^^MJ~?Va7@lhd>Fi_5F)n_qN60nmSt1^)em zuz#Wp4W#P{3=A|3+%LMIp16PqG#U&n8S7K@mr8Jkb{OPrzVMi@qP~^2J)>Y(KEg7x zA4R~X_G!2^tFAJZLmP7`VKlP4_|g&+#7~{6_}< zBLn}Df&a+Be`Mg_lz~D6tTs1?m4?rS@$VuV#n=4gqNSflz0M7b3NY))UALE{C;}i# zx=de8vmSwV>1^4RFod<&;aris=#RiVX;Z=|+#hsUP6n)ZgQ4(nP&!c!$P0>4;+X&9 z5Vzx=SvG%dFNK4rIqhI95XqP9)VdW8C7=qeQth!_L}n~doNA2QY#PQI`Q06GN7+h# z0{tAyKA86FlmC;Cit_=58nbDxM_}ecJK#uov?R%j*$?%*vk+@&MC=Kie8#KNJ3YkV zl^G?g=yRBhL(T?~3b)9@-Z7t#L_Kee0K6gAAzJ8&BhwinIuEspVk~2Z?Eb;Q$=p_J zyt|#oudF=-C{oaH2h-UaWZ4Qu_YLw5YN?D|yC;@5rJVWQ@fQPxVVJeEM7W`(-)XN?H}u5DsbRZeYM`Nlu6e?h8Yi+p#QSV>M9)~kBs3Q1)q4dphFt=segOC zyZkA?j>S*r_*v)B)Jaj1vEs9WwGCI5jzm>ZXiAdg>#0S3>`v}epdEHQ@Mvaz_=5lc z&|i9b^<$Kj^m(1RMS|?a6{6Mf*&)jSI)71g3JKCDdwo4hs*k`5=a~1_lFlR0hIRM| z;O996kCyV`)2ABXZ+B}NJ57?EW=Sb+jWMmt9kgL$oB4%SK=lz>@CdklThQsTvrgAAvR1va7?FZYv+F zvk2tqUWIYRIpNzlBYdrp00y4(QWPl?QDF^;9wT;4KbI6h&X+|BCZd$XKaPw2g-)cT zd&~pIAnI*>%fmBf;j2l&u~LKi5kN%j_^fmhvPR|-(T{IB8j1Ojh#)D0mY{V+c$X1G zTxa-!Q+W&X=MN%5tU<}Og(tFsWT%|)vu?_m?B*Iuc`k4A5joxm>3SiGl;B*S3->`=~fCqZxpnHacG^*EbaX^CN^4vrzO=(8dwM8 zk|+F6;1uCx#T}qmQ9sF#R4i5cF9>9f9fbO%cMry*9RSZVcq!m)yZHYn7IKq>pW&q9 z%33H@j%Cu0gN(?&{4YjK!dw+C?@(w_OfW6rJ}Im>9fcuYzIIHGbusC;i|G96?6iJK zf~z9gVme_IyxS{0%=qm(okafXj{j7P?-A(66Ru`T|0qiwkAr;`*gYP;ap^OVY8Q&u zqrKtzbdhMPQN<(g%9kle7e|V*i25_T2~re#j1TH~*0Y>^eDi{g9Rh+mFNyZWn=vKE zs!mG=Wt7lDHq>+1s$~Gh2bC`E|B{$-y#E6@I-&TlMazdT zkv{Pe_;@P%a8LqDtSl(8awN|^`JDYz?=zWpHkc9|O<=LPtiDFr0&;kLxcmXM&^iCB zY6dvQYT%|}H4;%;Qo8%kWdLdkuj@%a%#$$H%6YFLrOn|ey`qYcMGWy2GdAzBzil-g z=IMrCE0RgpDL0{uwC>xr)b%u!Bfd{i3Z^e0eFOxmKWzqj@vj{n4!Vbh?Kfu_+IX4M z#?P*D#=n4*P{)Hi;XK`H-=~*4&IzqTY*KpNrIfAtR1J3>DcRkc&`Xeh`=eMeXE>*- zIFy>|8-Nd>3nBWKZuwui>;K+)IL^FBp!X3-e*}IoJpzw_#H@Ok@virY@OH}uV#^~i zS{<8^O7`4f!1P_#(yodKRP8NkCDA+DdSyGwsWbfulZ zS3Lry#VLNv8a2-p?jboV>j&ov2KLLi(^xUmFN`OC_{%P9e*u&{vCl8`m zoZx+Ou< zk*d4(b}+>7x4N8%cxYGr4`N}^4{g;TXhutmQcp$!u4brFn%a0C!-&^4@1i9T@&&Ti zV_LDYYzoY$U7jq?DOM#qJpU|C*#F&_r(>CLpO^4#(}&l?`ek9sgsdjY6I&EVXqR{86enz#)Bv_x(u7Exm3QoJ5W}NKK(wy0E?{wiV-GU+eFe(_-#6No zFj5%*jIGK-*a( zj^dlT8}Z%rgHo_I*7ML_@BI+hp;5vN;kbQU*Hj-c3){W(Hj+H_tWQAQxq`t3-#LYY zjWS9)Z|8e>C_;HstrTf^x(~r$s3^*BKgt|^xom*iI7Vq<#i+<$3RIBOg?mJc5N8HY zL@1TTKj^?8LKaV`7O3j`v&9JQHF%+;u7iP1$4B6rR>S*z40K0g=5f>0WI3Qfy=wR+ zP-!<5uZzpI(tV)^$tAMlp!oqrR)mby^+>opav#=n>Gis?${o|H#K}3e@l&KO#F85m z(Uj1E!!|+7{z`*uDDy|)e4pgOkABigR`X|N5#J*9mncp>;iu-Q8k;8+1H26Gmz*2* zFv9TO<6gT=slEG_^5HV@A7A(uV)=v~D}{u-l;N z9jGwJJI0TIp`P#~AhVL!U1sDYIsWmxwF<$f_&Lm|$gJZ^Rv4nXA>MAf_yQN$gOqoS z4Ts`Wh3Pafo_${UEL)?o5$#PMw*8M>?t<{)?mvJr)0y_vq`mvw6zYPb9`TCMZ2k7Z zFD8@>!RcHkM(iDc>XEB)TfsD+vd%6a`JAi`Y*y2pfb-8eyN3w2pMl0{O(~6UD2zvd zcOZvP6o08q)^C+5`DYo_!O@n_u*;Pdcu(G3Rc)#mecbuXcjyH0=G{7|K`p(!Bm!gx9haB}MXD~>N_-+#1nDju9Afh62BQ z0$)_$))KA75hgI~1aV^9y`VjrBNJn&8GZ63-s-soeBU~83N7@2<3GqF-NHp2#4EFZ zTD|;r4#4(;nk=nRYA2?37%ojF548Wih@d8yn1S1brd>wI+0@4J`h->;CCoq66VOX_`DMEj;+jqnA`x$aH2jlH+gY2ENZ+@n-g9r@T7gwxh)0OoYB~kCKu;=cPC) zG5_$LzV3E9&66USd(5fEM0p@T8J(A8dqg8+dQ34Uj<)Yy>h?9q{Prv5g{*5>OeO6k ze@rD2@XP-v2jLXRbBc$MN8k;p`S%3ox*Pl1W!yoW5myq2%*OX;HeSuE@aY(CtUh`5 zv+6VhntgqUr%1%L+vmd9BxeS$)`PfTuD?emAMVTT})v@XL~eTDYHe3M!=WI3(Pq0i8mcycj2*V|GP zuH%q540AAyX@229N0;v}{Uj}NL+PZw-i>0M{OIB{M^Ll}MZpZ8Ou|#!pVOlW{C!m6 zt24X;n@urnAIaH|GQ<~6<{3Fo;lrTgV{t<*E8}2rX5lGq6)1{SMxNfk?HIQ7_tDoK zKni;s6=WmROZ}={f=74IM-?^Zu==SL9%S`OG^1)bo`TEW{ZsVYAS0tu*vRs@H)w&@ z@V8CkqAM6Hbxx>cocxw4GD8QVK!{qr)YjVw51A-|k|8Qvg~48jM4-wB6wULcd#68~ zr>J-KVDX;I=HRyquF&|C!Ft=%ln_$5{&?ZoX8;~!pEaCY(Ic?_{+9=<`Q^b1QJ?QR zhpl>qxY?X72pLpTWk_AJb&x8M%5CUlh!=rcd9iz#nGF^*!{>MNNO0IL~C8>pJ=*X_>|#VRd$nN;!z$ z*_Dn+W=hve@q8Zb(mi;804s0M+wH+;z+HSZmD3D1tT-!sZkVAou=gc|qnE(b5XvYt z%Y-slu?v;4Tj#H~GM^Yth#*1n1Vg2|ZldsDodv#1%Ou>{?6NWsqyKJI1Lki26K}zd z_gyS~%gxRoan+gFJIe@i*W~KY)~|PRDL&7RQitobl&@LDFqn{#2JnY3#lG1h-PNId zwj#%%(-@9YVK(NLix#hvOBN*){*=t2y0EC-b`(1(nJEy~B&xbRvyC9SUr*mCiswk(Xk20=3&KlyV-Cj)*N&nCA6N8LM2TW0a|v`?jL|h*G9HIbd;2q#;k@@_ju=|nMDB&* zyunYgeW}Tr){oJ?n$KmCN=VPQEx&(%-;=kxC491XC$aFI+xY@#Q|B|2Y4j|XlO$;m zieko^85~bUv&4afbf*yPBM^CcU)cf%v+fXs>FzS3oWv;=(RX%Fo_P-7j;15rzTyZD z=~j~3Y160s2bn`1-BYuH2R zBxs4KGr`edfMtQMyUU`LzNpjYV8yAmznSD|hbjOYr%G3lD@@iK)@(SJ5iQ8ZjB5Tt z>I+RdUsFtGp6xr7K`%Uq#%Rq0#+aBP%Ne2291Dh}74#cJyFgj1fKuQlUOBF~V8op^ZcW1R-Q#VR%7$C4!o!AayHRU?GL*dV_{iDVEX_7|cYBkp1`fwRy zTdowq|6~{&S`>6&WPL)IU%o3vU{m&{6UFEGQ#t~rw~qiqr5W?jv6I=={_dF-=ULP* z8((>MSu_d5CD?e25VOaVM8;am^=E$KsEkixShZ!eHU=6>t@*(h_S%q@UrA?4+YuFX zP^Z0vzAw3#34*aZ@V=1vnJNjLyC;H=zP(5?##uxxtM{}UG02*jC#Txq$ZW1JGI<}` zmJavLaWrZ+-Cv_gx|WYNj?bL%zTwA(Ef&Fq*&r3XKXogM)j||2m)ej(fme15J?+8f z_)C%#3nkm>qK_4#I(b0Sp}2>il~Nmh$s*xdsk)dI`VqC>{j0GL)HbXoXW)1vZ?+C1 zq6d=2g~ElUIZ{-&_6=8iG#ud;F7OW8haRKzW+=k0P*-bD^kwwa*d~E`b<^BMyp}rK zTL}g(y6X?ZFII35h-$L2p*wCg#}51l6E2EACD7Kf2Rs6DA;P?r$%NsJ#zeW$zDL>? zs3@Tv=>zVJqv>QmJH!h5tUj)S?i$j0vK}ZQG_#GOc5WA+SgxTxvK2E3zp%W-(-#r? zvZp)!p|GVA!qMO<<2}-`A80yfqElT`H|IND;=ao{F|{_Hahg7X-!9ep(Lj7tu)$`o z<~tpHpQ3BGC<^^%)ke~^v!`03zhv=YQ}e#CfgDQ23f!G<)$lDs+C8;j6MEy}U;l5q z<32LnZlTy?@jjRUORFuU>B02InY8J_!2g>EJ$N}PWZ2H=ajrhLR;mmBZpBiQDF}@Q(k?-KX-UaTFXEtJ%H=AMMyJ_2Y4t}RM+brb93){d84k!>c1 zi98w6w3Kg%r9@fZBG^mfwyqVXSs%mG5Wkpk+k1#GAAWe5eiw1|+Ea%85nwL!-eJJ9 z=h>$iU#qPRcEgv}1Hu)3U=cj>9?sp*cG?Rmc)Pg9w%^Xl_kM4P(P{Q4uRG>S-;VBK zi=dt`Tyt_15S@urSQ*Bgqn@hV7n*IK?yL`Wt{$aS{N^`Vo$iBa(h=hWN0T^y>bP`$ z28Lm+U^8ybG1dCZBOsLEeTCU_XI=6`xvEaB>B-N$`;1lL8~iGgJ2)@^U*k-=U=*>4 zwh-;)iJg@N=$v7*PJ;{f=S+GQqIC|>X za(xQMsDF^_R&Q{3z39CRwjYk`fi^v%YfiXkJ#Qr(Cf$l_=eq>WxZ0DlUO%!&0P2#r zBE|S2Kn{d7=Y5N0y`{by z*L9wc~BO(jh2|w8#+Y!8GuPwOzWZc!#{$H860~AwuZpc z&l9j56*l=Q`Are5jR^b0c(M1$K(6;vh`|H9>RROl`Go#G=e>v?ul?}G+=-r%`dWVv zIsB(PxcM!c!LgSA0x{+`tMQv|?O$}4(s~u>Jp$hn6d!>W5dXK|Y9abNXw=8pUk5<6 zGx~m`O-%l?A9ZEW;`dU0@8#c11@`G5JWITf7`?9+0F#+Vz|#DJ>q5PmY=WYuCd?>E zpuo6F^$pVJa#x~Vn`+CJGqzol%hkC@AawE(;0Gg%H2S4GM1u!z=`C~N(+!VDz}FJ& zMr=c4^Lt4!iXV;}Ou&vOFg)nBP)$);3l!Ru270%84MFZ}ejyzH2t3^BfSb|u_tl`| z>E038r}>Q)>#y$9TV3fwJ#xxL@)px@%}u5CIV1sVB2+YIQ@Eqea_-yoN)Qx!b+URd32pH|{1aT^t?s|U zRraT|bqQ6z#!x_&NopjIIg!R}UMle(>GOUB-ZQpbO^VtHRX7I5xCY<HWPgVQRztQsA}_9Nr-*JaB^BLUOw11#Syyg}Za1$vGxgCy4Jk z_f{M?2882m`kaDvBIpSN$w`h#9Fn|eL7@O)E&U0qg3e}pBpx~E+)Cfz9N z`9Dh;*U*~Q_)o~sBF~pze`v@0T*}|IL*F^#4+8Oj@6RZx9qpjWg;oJ~KoM49U*S2( zI1uUIj8loYRc3s7IIiD}BM&OI`adc4)M=&n_0cchfqwEA@4`UPIAERq7i=H8N5JCh z!$W}V;q5V45bVw;2wAZHr5ebm4EDcF?Y!Zd?Y3)31+DNWPVb@7mMyT*|0gEOZa3U_ zR|a4c(E{u{0-J`T`it<(A!^Nk2=i!#ih=zDg6zp$5ndS-Kd z1V-(@5mHOwoJZfo(9v$ARFt&ASk)2>)k+j`L&(5YTO)3~F*-Uk_+enryNHUiu)uTQ zJ9FjbQDRO^o**~2A@>Tgz^!<*ruoYoCGyV{C`4p$hvt!Md){ZHy?z)!wz&r!748TJ zz(QKp`Yh4HP}(Y2OO<{0`0GSB5k;3*6?1qvsT1}>h^Weir^MGOs z=Kb26m4lLc(-nZ~6_4;W2%RSy1)Qr?+eN^S8C%r;p+$ z9?bH7e|LqLYxN$lSZl59`9k`HlE$q{Vo2jYnfNgT>QLwc8=SC=q;2bp+QI znOobkw0-AGBdKq3l$DX0>{9sy7_Yx}wOj_W5T3Mx-H^%@8KQR*Ws{6k;(iy4{DD&< z(6CNOP;C@ELfJk{O5(;dS2~G zrN5pUt!*i=YPjDG^lu%aDrqZt*$`(Se~=EzOOG}iH@}WTc*?ue79}ifEP_p&e}OY~ zlbQnYen<1g(g|G-ai7AT1y&vv?8a0X`5_K6l8h*|(PD-U zdL%#O30*W5e*1=)7xrBPWfE?l%yw9JHko_<%v<4`E9qmL@H1JjvT)hD5h9fo`Xwm@ zhxAPCR#JpE36i{+4Q|EAMaug!Ezns{xegh$*|fsD2*Tx`vIn2iN5Duz*g9_*L!?Yk zoI9hWKRxWsB@?5hHNs|HC8ll!FK*;MAkSf925HTWzHBq@U4B<&s&7_GPC4sT)zma0*M!eA zDJ}HnNnoMCdTd?XO?6AJW5o{{yU?#=UUI{DmU+Y(xfaf)4cfa2(o~fj`n(7XXk`4j zPo8d2P&%Kj8yr=2HwgKmW*_kVwbxJr0ES-{-()-H~V9G{mDzfk&`+hzc{>nc0rt7ha-$Z zxdSi8daW)l&fY!xC3H)bWUd8rp}tO~Z68)v1&(^0b7i<{34$B&WWjwi7bY`3+6O@f zocT%;rvflzm48i>%>plIGrvBG4yFY%)00GCsW4*!rC*n4U;H`~{Kw_r3zVdPUH-KI z91|Z7c@Vu!JKuwQ@MknAylPn&28(q1rQX}hBXHs?{BxGfco}*fP8@9J39PZzmGLX# zCLi*<3+;T|x`kQwKIHfl&$cf(4x@`=ePo2Ktr@T43GSYAc|q$_%8!{cGejSFG}#>H zu*Pq8J|L@8U~Ec9t|vnEl3va_s14?ctg-OE$Fz$}_MKpPUG%I1%8s(GBu)It+;;oB zg(}?@Wj1-Nk!T)*0Qc#LP}_^yJcEG;+%fJl!s9EMRk3%YcOv=KJC^HRS-VP|$7Dvi z$N4a}h&79Fc?AjD5ua?ZuiuSTb?fZCG_`#i^8VWj!BL}l&&~Auo6~9Ez^8G`*v;XC z0?av$hZS^*XohHS5Q5-C(2}3qu0KcRDYChGc}E4-=c~bR!SAZ&Dsjyry=L=v`Wh>@ zl8lC(r>ZHXlHl!w z3Flj_52l44N)l_F5YTYSotf3^gPqDV_lD$B-BiWQ6|y}2PA*zE)Pt~S;6zr7r6O^3 z8OX7OI=g*hHpVXPlBp-nH!og}_C%{N|GicG(}iKckB{)k>s2tY?1{YMv5%nAf~-EWJY|<$i6RvRUnLGE++L2$0D5uB)lxfPcXy>YCq~T@QCgoB2AO{d ztxbGhma^{pOIhO)AF4>YkHDPn=((4-Vq;6~(Z;OUs8*(P302{uv4nMvTU2Ed5nOUI zHe6)uhAqjv<-N{e%bm(3&2ziFo$?M!2Gj%uNwb*1AIbjh^0fk`L?`s4xnEH!$2=*D z=C*IF7swx;6*4kRxiUM!B+tttcQt0dyq(reK$BvPg(8iK5i1xRaPu&mg{%*aX?nw3Z8o6<1E&Pc@O{QB_vrmL@RCljVGV6=#snfE z4)(@D>OVbOx##Wb%19Sd8WB=^+T1^4pXe>j_Ba$v=9w2K%uV!;N)n~(vX$`yfm<-P zn$Emf+h>Y!%qxg{a-CoQ5<|2vT!d4p7p|D)4tnZ^5=~`SL z4U8@8q3&kSBaq7X=>hpG7)Q}@3Ev%02p>V<9sx3q;aa_gA^xS3YZCIEMctuH?&ib0 z@CYdnS%MBb#yfsv`(i(AMsmCFkeUtSA1Rsdjmp2p^m((;zEg^Y%RcD5MQQO@`T^=_ z510tHRg&EKtCcWek79nWPo~?i8Pt3A?3G8{E&2L;@)SPgemab>sX4I3yuFh3qMKv) z)gHuPH$>YVCPKBLZiXhoowt=n==D3_>6#rq`M5kSi+UtxOWSe*7q(BKBwyId)+m+1@{d#qN*`;a$-Ag9Wg22t z%s`tCI)Ps%{|_eswrziz{ND?Lf1CW@3lyQGK_`HfhI9AnSJ!?D^&UaHMeEqR*ZuIJ z=?z#b%KD1@2q5q5=U;_y_H)fJ)N_u22Ct4Zem>(p64V`i6~6eY*+q?uwovBH#L2K7 zy?KqD#MGwpv#^v*#eN{nb>X3qxV^ETNcmR!n5gi^GlsIroDTzYwA=acaEL*oIO?xE;ey<590LA znJW5;+EA?_HANZErrQuK*q1+qKPA%^4>c-0U>Kl-qoGsZz;YU*!h=Z0Kc6Ump{%@U zcjw(3vHzOnG-Hnb`yKBw-FU|X`q6!Jj>UjQJ)}G+{Y@tnerVjyhou_#jm#_mB1zZk zOYNzwH>@q+-&WOXfCJnisuX*}V`T#DndYhN$Mg7B7)gS>#&x&Oy?##iMxYp;*2>%bs1!O1db9*jcaEDNnvmyc{k z_H?^i0-b0p2laLIUTt2$Z&g)-ExUaf^e%yN7_Z}xq5C4o!gQJIClbicmls@MEbCzC zMgqpN7#(cZU@S`(AW1=*8izF%W9V)zG;T?lzDYvvWF1ZOrsG?;{IhkFwIblnQgK;k z2tCzwPHl`zqpWFNZOtdAQnWsbIQZbqDB{U^lxKLuGE3tSroy6G`XU+2i$$3M0lN(U z*5#jSDno9qd#V`i?tC-D79;a=gk5-HUF&1DwD$gb^W_j43Ul0jDM!l%z6H_|X2^bQ zgTQ`n7w2AYCxCLwR=Vs$Q}fy$O2(WMVxT^yJgx=d5@Zt#paiFo4r=E3mkRt~+rA)0zPg%fk6|NEWi z2PbW~Fhosmdm?yzz*JQc@wg7(Sroyo1KUi9St2fX9xYryVR>}jz?(={yw$4A`i6zw z8?U86W{C3lF49C-#=*9*#M&0vxHQ_e=@b|WAhhV$N#AhTt|`95 z@S<7&$ULx$gjyf>UO^r0Y7i^%%v#sdHl47>eoF_hXo_w_2TjOi%Rc7AWM(ic`~w^; zv*5aIY}PST?rZ$X00$KeVSod+2sJSBc2lXVClATStF(%VoQ`dfD@!}7zUe?a8p4oL zI1n`iQ38!ycGl%`%$k+q^j84r*OXAvBH^wvqmaXsO!oy(1U zVtwXCH#{lJylgqW&IbxnK2s)m_ zF=&RmbhGbI<+1NUa>3~BLZXo=QS?QWV@RY6Mzm|hR3YNMm-TYJ9)`LW3(Z3Zm~WohFm=|!Url1pu)xYp zHSvpdKI%$}#FzBx+vBwn!eQ(cP|$@rX+4=@n_cY%R^<4{B}W@ zvA;dkpJ~c350yRoI}iE8L;YTm9xMYUCBGM70?L0&Q|LY#oDesF^HG|@XD=-7-*tiU z0XU?2@c|6Z<9#?PL(GcrOieLICF$<{&f8@+Fw67V4&F#S6&WV4=NF_N+fp&7D8qSS zV?|k8Rp}Dv*?#+~;00yq^LdPsQ(bpy7m~mt?f%6BH@Ucetg33aAN07B<@uSueiC-` zE?wrNQ|MzlYNJkVNQK3F_Yrn|x@&37f`hJCKl&!?KX_AYInYY4GUe5|WxY>yJZxDv zlg{dRdvjiR+@N6M(|KD8cNis2LAcJnva=JS?F~7G!hx!U7&echcf5cgyk!Umps5+c zKST|Q2#VyY%RvN+>V;|ra`j;zfgr&i_}d!PbFa%9LAM(Xn4?o0DdC3Uy9nxR^uolA z9LkoCtp^Fc&7^nUru6z7#xMPycpzI};ZB8L9_lP1Hlk98*=4zY+V7)HT(I`LHsLY} zA$b46ZL67{W!B;~z=vHc!VBzh3y|Di>W{B5a@+Xc@gnaxblE-q0wL%jk97nSm_j~3 zRAc>Wy`irwv{lxR0Q)wZw>iFb^6F|_&0!I^0VFsJ7A#lnY7TV=K7m5IB&WKwf( zQa}6+$xCPD*+Yr>g8Q1M&P!0PQgxi`8zz5}jxQqS`L##kH!WNqSYi{`Nthf)W{fiN4HeFhN^ zoAB08`cc6T!wl!%XvN71_(KKWL~#`hl0x5dbac{E>GPsO^S9>|B?4cn4KMZ$vF|tq zaeu7z@IjZdel27Y&GF>IG(aL+BI>f6#Bw7g92aef51_aHHy;-J^P%hE$*KZIbb2>t zZSS)n&(F$;<}@x|g;&q;E4(I*$E(aV1Xok29|83=QEVJ`ZO*D&ImQWcwxg1noY%gj zq#G$3xHQOfcmQ_hu}~Col1;8xUMgbz3xqDDXlV+h4Ka(X0py~n&``oPEW&1n(UqF& z&x5v0W=Nx5Sjl5Duaa3=^KleWVIo;9iIHhkM(3m&L*y)Htk8E6Kc|0z9(wB-Rs6gG zsH)F|#s!m4t60BU(Zw-u5F)OfqYm(v%OMhud0x zb?_?o0%k4|0gS0sFArw|T(F}@%1f*CdI$R6QHsx$Xi|I0>HQkUEN#oI0wgjfi%cU7 zx;ne{Q*k*cp0p{k$knZ z&^C*=0BJ6?gT053BlZK`=z&pf3e6YDo6!DCW$gh%SUBbK@{e{8JG}c!B_U_dzF7;N zT=hBevresXAx|l+Ou1ReG}oW-a1Ihdt0z7y;#d&6=#cj{j;Cjo+2uuB4|dHAqxf-H zE||M(?;U2#QZ*`Wd9$Nn9&3@ZrPI4$(FLdT{>IXvB z*VEB%$}b$q=Va8WkQBeb>xu`c!@Zx!;@#0H><=9JiKS{1Z3`3=<8oRGKAn?jINCVh z&nOJz(;l$0kD!PP5T(r3^21teC0b8)a^y0-O>rT`YT5B-3&hflnZD|R zA5*@>mN8)7Wkkq@P)<}aV`^I@xU0@Os>id>VWny&_ntH|#+}SGE3K!>KbzuVmbYmCnLDqeDiHI7G%suLp<_8P{iJrg;xL}CxdItM07l5c=A zgz&StG77J5w5=pG@%d?3!Ho3m{cxzYz*Oi$iA~_9aG7Jt%~P#MV96hxMJaMiZw-tw zpPIV3RN^`_TT`RFF+o^#HPp-|-_RF}B&Yk<8FFgs%hQUh58t=2FVju0GZTuA=pU5S z8(BQEP7)U=;JZZPFOFXkCQd`nGP&DcXtD+ISUTdtJO5R8L?!-Ov^8ha8(p$Mk!-wl zb30wpM_wId9sqYwZFB#WZiRsYJ~3-ysORKRk_Tq1FZ77-;+{Tx?3{p6<)wd7F}h^< zrsDC3Q)+bq6OZM!ZOfg!;Zy{@(TfQS4;i~O$FxOl(Cez3{WoidGJnf2F~QQ~uVm60 zOeVn`ek7~l{1x*x$^tlYT1j$)SqT(nF;%S6(~Cl2wtm*2V0(R&7{{ZGUw#8UsITx; zlZR23X_^H`L9W%Eo+ZbMw(!rr$=R6>Y;naL8y-sEZoYG@ zCi6n=LLBA!PPMztnwpv_W8%(5y}-A~^Dce-VXn2CP1WT!->(Ztd-m`LOVVWDw~X
uFZxC&{ylBDNaE;Xe4 z8(ho83WGyJaqV*kmdED;d0fqN?!r}@VB3rk3>TT=z?qN%;oGB@75&>~g=?BreDLuX zwUUQm?PG)sup|DD9i5Cg8Re~p{hQPwQC`_u2mbw=BpjTnixj(+qQGeA=d9e?fJgqox83%elk-g<%|%hnsnP4_ zV(JoXuwEB8B7fp(k^%DGaB=1Ilm^88@&4RXyQbZt>|#k3q3PtWNCFC5dihq!6y}FKA#SUh?q3Bmxtk zy4+QdbY%(jD|GTJBfZ}Z(aiQhebnJDkC}f#NFu7#vBrqLCjCJr+%f}V+XiVXOO_T= zWnt}B@d(S|Rg_>KewtAlp)}Dbhh5~7HIUr_c}G<)DNxoJT^T`uaa;Wc%kx`ka!QZy z68^OKl;be!mAd9Wb@ZXa=unyiY-5z$D0|OyX1vI2tNu~r7(d+eZ4rKcf;}&pA^ryS zw*jx08?D0HNc{?-V890h3TqqnG6wAgWG;Q*xJB!HDoufmbZSa}35GvHU>W*pVw7i| zN>($mD{;<3FB9vO=Bm{=cp_G=sYjrhiSzuux(`RapH zO^9;T{=u6>b1kl(O*cvb>r4|A9U8bqV8?OLXk0@Jf0C&^o6VYG(}&9)>lDicg)j8t zJik66*fEU!zVPr}BCj%5s)UY~K2L^Go7TD-txv2?qvQf-Or`-56w?9cTwZ0-i|vuVT z#vr>^tL1=d^i<0T)2bY|qfMcb(s~$Vj;3_dP(5|N_6V+zdF=fETX-<$d>5kA&$%A0Y`-t8YyY4lSq zt@0qy+((z9sg2f}wi?47YIT-?8%jBj(V?o+v(%mZRy{>EZa8il4ik=RO zY(g?M18J?$wdn;v+61eTZRZ!7<_D68wsVL3x?lOQhoS&GW3|W%s>htwC2lAw`GdB5 zB_XbmtN@}SgdYSM@MKT~pZDjbNnyA6LjZR{`!sa&aBt`ZQA&H^Bs;S}iqB#$NuT{v zx(ESWzxOJwy=dPE>&=2Cmw}G18 zJ0_fQ<~-xE31U6Cc|sZ$0u>L>_hrYt?+C$Et{2n0ohZ*896J5*x#jxFx6j-FZlFH zBt4DZIL!!THU4NxlCWeW$Y{dwvxJvS5=SpMDS~jo0Wp~u$10khrEEB*4(zWk*{DgN z&t6?|ej%i97d7D?TvgNq5&FW|G+|C@AJ(92cYgO&VMXQBAS;Ph7+vh@xN~{1#?IHR zm}Re|So5qC$$OhK6O$NyC& zHtzQFeS5d(CxjM&ie^D#QnvuZ1|MgzIaAMJZ_mTSB)Os=wIz^9^=CTYW#A;Q6pQ(- zLff5CH#v1xz51hStg@Pqk~kOGH2ixr@Na4PuPmGEcis)AFTXDTPRoBecIn>>z%FC- z-_mk%u)zE~Ems7ahBe;j`>0^kP%oeLj{pFy#)8%4r+QDE8eTIDK7?_j=`zq9ir>j$ z`b0o7_I}L#r5>-rq4O(mfA>e;e*8~)yXF5)-mWjfIxxGPFsOTd*R3Yll!4o#=5kGF z{jd88($opaNqbWj-TQ*k&=?1;B+cTKp$?HtpK`LamTT~l!#eHChfW6x3k}Gs1N)bq zZ?~rRMo@6HEnRyK^nSW2cdCXR!kgbuE-r-XffG9dPN;VTFG1;5J8VW|sqys`m^$tw zgnM1hni)Y0Klv@KlOrjHTCfJ6<$wuwR~t(Z@GD4ISLk^lc%L2@dD5CgARlp}YT(wfd|oMVY{@ zq&vm(z2Up@ul`%1Uh%VHij>L-*wM=Jh$gwqj_0V32e~C|pE}(eXV(TT^DH#*Wp=r^ zMs+LITTIQe0v4J*X_LM?yl7Lz#L@Rb(`yNGLJVUUjrMpIVtXoTL(p5N`Mo^TqxS&k z{Z9|Yr&U<}f#;f>-@Zw&BKE1D3?3LaK5zXW%)ND3mEG1ZzGw_2luijzQluM1N<@@y zq*-(~EJC^j1f)S)x*H@Ur4gjNyL)*izP|f=efRh6ea`t^`*)o`xGq@NnmqG)o;l|j z;~w|82W_R%VlbAVLs9Mxt}YyoN`98G4CA;j?S7YBF+@vi@p41N3N>|V%1L^+NT|Qu zq;}+fvZzm5guW6CamK}snVT3MX5%uaYKS|vh+ySAZo5GkA@-E$Np88PY}OJ10fFC|^~4CN->AT$dDP~`=qpVvjKz2QRe?*X5?4(4!wwS)e9(VTlI!nOLxzbDjA<2!~soEs9&xm+dAV zwPnpt-GT4RJXzn6sf;rmM_n-*F8(~L7dhy`@qf-pF3!7@OV=_Mm+^7}R89_M`A!oC zD0O%QsjS$m0{L7+sG#lnE0i(Yc*1S-thh0~h;8J`WMJiu)IWs}c~imNn{zZB)g&7e z4U-5j2Z&mCNGFS9UpwF6C^~?2UW~0n%`RW3YiPxDnNu6y-dMg$6276=J4-XM6!F*^ z$)4?sxz*XAl-svWWpeWXcX~v5@L30O_}J5`MeFoXBLwmm9=UbD*ZcZX-jrYGd1GZc zt%6y_^04DQJCS$kYSx^mrZ>!te?Y|RhcXl;w-$z|LlUsWIN3JQxZrnB?eZ~XluHKY zLw2Yw_1(h7@5wMkaIpG3Ly7m0LCk3kV$(14nlpd!;bm{}7nHn`uID6NEOar%l90vQ zdWM84D3!YfQ6?CzR*bVIKJpPZFkb2Mmrnzvb`;R~P>~{~1#kvJB2=%EOsO;NK4?6r z#lbFXOsxGnDNZ;w6#Bl>oqmuZU1BAA;j2-!!L!oXacXm4q3joKm^1AnYibPt6|bk< zRvIif;hL-HFTZt5iff3NnUSXEU9paoQ<8IJ!U^&U-$C>L7N*U@XOhB)fA^~7neQ!! z8fKcZY_fZVhQTFaj}dz19A0lI9g!M$OGQyuL&psRmL*auA{_L@M0N1ksb{+qYgbaJ zAxyC!*UmX71WUKxBJM90WFZ7#(nD@pJI;wCA%#YTFRU)dG+R4y9Q1ZN89oX{k5i(H zdCiIiAnsQ(NaZF*6v2;Y&qrumjdZGZP2cqp zN#2VYdAPcMUED2_E53BC zOTg8vx9Ww)=t?(4OBxOwEieQT#om={5JR|yJFfUx-fO3$X}L6Ccb9Zgl3GVqY#)V_sIj@u80e2s^ar3|q zb84loMUDpjM3+KZ}%;iZ1KbE%&*x`TYQ}h2Bup2&s=aspc(k&S1$PHfWV&?|L1^L2=bJ` z<5`-yauETPV=1Li09hxwM%ImBhmVX9Tc2pO&(j-}RMsZR>0A4lnI+lZY-2b5ltb|* zJi&o*XW^{x>O{AVgVQn!rYU$CES$$k~@ z?ng*CTyzc$WTbDpyKa#sp1Ss6Ns8%CT)TFPn0Kw<;V<$%Z zx}}rCeXhn5W35A^QNdj~n`?&a#3erRNCV35QGKhd2%oBci6lv&LipR~=oI_td^*)K zry_MM03}}z{{it}0o0$N)4OoV72n29T)++g7+v%DR9SncW4gY#jtnvBZv0rqj@e~{ zSV3B*s_{tkt&Xv9b)F{@12vCVyVgY>E$*YQoAB4srkBT!d%BPakBjY>-+BvGDUPI~ z_kA~ua1i;$Y(Rq+>WBZ9jf)+@1vlM)ZsFZCCjEV+k91V%4o)snuOYnF9D&CF_S{~7 zh{P(@&$dOTqF)xO%k~L(sj4c%>1ObpgT&XT!AS`1>?93@gZhJcwnL_CW^V$ceIG4` zN<1wXs1SX#u(ZIvQg1RKL?A9ce0ch?yq~%3f|vSs8*eSQd1AVufdTVM4mV@uyO-8B zefW8{RrzdbdX~2{#S>GQ$=0Y1oCw`@I%5ndP|s|d<_p2UF-Z}KwV*x5Xth7F;fXC^ z$7Vm^@vy9hidf2!bD;6r#1*(w-O1pKai@sjo#@2YwlOd)_mz;3$f4G>VfetbvfMY_ z#_#<6A!2#HPyYK#S+!?WCOOYa-z2aiD>t=UM6(ePkhnoj8O#oQc*dK11(`-hsD1BE zz8rpq7@YJHLTdcw9-z|wpZzG^{dj62Up)M=zAjqL|E_F95-+V$^Mq4rm#iKgf@%Bx zu4?KVcOHukO}rK&k1=pV-LvEv?RY}Kv=-DAnclhLwK z!}4+{`xJ|5=oVP>YqB$^=$%8)Ir_Ioa*^$ia&2aEayoR$;&*__iw+tc)pr(+}kkG z7^&mWT|1BQyW1Kkuj;cX``y1`jQm4H)uT#to2t9Pc0IO$h=f+KraBXJ_-!b2P_QJJ zW0Y=4ip@NXI(kqjm#q2a*DmGgo9?gMGrvR_tHuN}vP;#|neos|5pD(cF}&1s(!}dJ zGo5+3FGGvGO`;?z3ei1%*>+8L@B=)BYr4Y(ASwX5gE4`grKRwiyZ{BPBkKpm>K5h| zgKv%VQp5e((Io$h@&65Mrnxy&fWq%19VHw|I@d=(uE(3EJBN z*c|TA{p#p#msP+e4$pjc!Dhn1OqV8JnG&|6SK0MgGN+swb8=$BF@j%UdV5t1YBlkc zruIpxWNZ_0hN}m%zq98kAvdn>CfP$!IgkVBu_l1oM8A507AUx~4!b03`T^-WKTXb= zx5!skJtC3MQ;vWkGusKtu7AoIkerqhbJPRYuH;}E!YewnbF z6Uxt5If5_A%X-=`QR%vhq_WHTq0B0AvzkoDP{pUPfw}gt#ch}baD>w%-bh%-%^`S$ zA&3Qa3agq$TQFZTPNg?eea)eHR1wJbURFsM1eX6~%y3gv*JMq2>hPfNf*mAg-G)hJ zUh<<=-$SrynI@{)L+&fCi#IxT>RL1`@obaXC--%U7erXCIG$sobjfip3!`G@+PoKx z`SoC=hFDFRAz!zmB0$HN#Yc1t?q+O!U7qlkzGdbR6GUu-uswNL^WC|fbMQJAp@OHM zWHKC1q|i@2oa+Aw^RG$5zry_MT>C#f0^_4sVQ`Tctv}*?h|$_HK2LNbMtK^K^ddui zf5D=BU75XhE!BPb1T33SzYP2HFyEc&?dDsA-xdy*>gwtmgqh=+qbWu8#9mycFAyNT zDc}_GlTH3&$rM8`&Q+XHtoGJ#X$I5Y_w^`=8M$VAF}!aNb_oY{9NrRwXBt8nr6nU~ zd3BFWY_!>1A`}~D8sGS&s@7@LX=a!`rRA2_ zk)e-sHu35qZwcSFHROzomL2mL2Ed+`W35Xf5Vd!$3zlAjY8Jr~utf&J7I}rHrQ~|! z2ZZ{dMeF!xIVdxiQYZi0kV8zA4{Dzq$V?m;Ly7Ge z&+(5R>xeWw_Kx>7%hBF4Oq&$3Kd3N?Hx-TAu$lH>k^{f>s{D9%j-p00@wCmT)Z=g$PK=J8_HieWcA9L#i*eb+;mHkud zP?0rNA(zf#8!09dF2)aoH&Xq83>uk;S)3uL!bU+N==`=qMC7dy2aWgQeAyjxq%nNsz?cEBtosJDH;_tgvZv-E%(v|;7{r`g|`iuJiGc@>vQ*%ud{e|}ZWRa%f zU;1u0Zj6%ya%io*E{GAPMt{W!LilFPhD9UD$0v8ysw=Q#-}p;X=1z^LnaSoykGCU1 zSIX_q!~EHAkz!NED{#n8O@A=m*;xoh+gIdYnj!>psf66Go8&yCZIZ|?m@jGG-KsUI z_5YF{iZe2<@|{PWC`BYA0SG83gnT(!T~ zJJ6^35Gi@sRRQ)O9JSo|o`e>No zqO#V-4Pd^{RWKly(UzBj4HYi_WoC~kl?4VG7M^4I23>5_qb@C4Kj9`Tn=_dev7l~m zIev&8WiJq@D8`tW`l`LU)cZtu)tH_ceOh#mpWh$}dZcC|r7vNwfo$bub}t0|VT#!U z8rgQM&m?h!b&>K7Cd30D)mv>ZiaE!oja)lD10^QRNwV8NV18}k+7iMn+wFU6kxx}q z(a+{||DC?tCQDd|!h z9|H6RGFRuJ1kG<3F}#t(HzM0$W9Oq*LL{(O*cm=xKW%Km4$%sk3RU;E;x!yK#bs?Q zD0|A79PY?pJtpQpE~HMmlhq_ZUNN#$K(^;Fp_cMhJ22Xym&bnggk)j5HVjmlT)P}Q zf7o$NjgRXGMsaycMIjf~WKUYrEg-q45Lffzwa$AHD++Z$P_m!=i2FD1o??gM5|9SUX?J|g6bmx3i;Eo`BfYB96}ci+b0It z#ZSn?c25GuMlUT zaO5F9`RW0-s0S>M9%a&hx=)Q}FMl83yBmv3APOv6bO&F-RrNu^T~ucHgKC*g4A_Oh zEvL@369?Ea1jMD9K|%zLyMB(kaGxGv2qB=(d)_2# zm-aHU4+Hj{ZuD9rR5rH(@D3xK<_a%RRDmhYNV((npOh7^4)doHz>Iy`F~~j@_hsp8 zG4}mx|NEfM1TrDn#UVt6J2c9^(07K14{uh5!J|clNW}lN<*Q&fzcCp9}HR-1Eh zuw^o1Y%QHp@s}kI&6 z!4m5sH&U>-cjwfg2OZ4tv=I)|2lXTAuh==!*tQ;e-_s0}MfVl)jhnd%GRD8?XGg1^2sq&yvXNjFx6--nXJje@C|#uzc)< z#CO{;Ojz>^NdSW+wRs`2M^~3M0ohw3h#in5#E5w2%Ne00AA(?Dz;zQ%Rz_PB>62DN z)+Y_k&MLNj)-8jnvb)VI-`}|7ZjcE8rII=p$}cC|32G};J`~Zjp^nJz+=av`H#WDD z&d;X@DL+asD!;E3Ql2%Oh&xA}o~Bnb%AeCHe&&g7{qo*zguZeonHDpyDMz0j2@9s) zC)Vg~$6X%cvMh~RDVJ`>pq$s$A_s%BImVBESsk-9<;_b6OJ`eN2lAHPg21}kdEcz% zb-Xw|i~Y~ODu|uo)m4x}9Z28656I&?sPR9e-=EayU)j{_x*Y`q5R9_hfznIB&|j7P zHl9X)>08jaF%5jO=aBFH_lL9g)af(226`C`85HO4pEM08DMt&-ZtGWG+*f`3xVuXuWhCjEitbW9TDgUsozNRwNK1sRIph9As z+Lr|jlE(B+XP;C4BB%eZ(5ER{{o)X6%gx*+CWJQ-TGCzCReGL+-%(Nzp8sewqvcBnlEOKI$4z`&q+9Rv-aQ*^ z7_JHU;PXnd*~^hMH@!e@{vM0Eqi9MJTQni_Cia5e?YzuwEMc^4s&a@8)Gp(}yEut~ zqcoj&L3TceQX^!_1V}$sLSnt2nel8l9roSjuOEM#AgP_h`Xp>_Qpr+N;xh%7#H#Tv zE_d=7HU3srj`!gVdLnX2%i@t zPe&4F_93Of*yaE!HiB$KpKH9~XRhM9c=`IoqaSi7SzDeFPdf5OvU`C4PWV{|+C)T4 zvaqI}|9(etTk!TG-KXGa+7!h4QR!l7&KDIWVNk3#tdfGM);nrsE3|tlx8#2n%j!6$ zwRFytvUc1lo@{k!xlg)xBI8PSdWe>wQ)j$AIN!D{rIsD{Xn|LQxbg=?ZKmE0L0zUb zgy)8>V>#v&O)C!aWc%%PoBc3ZOs-ANS7zyL5VJB2g6iE<+O2xVOCc zed)XCOHK^|j6>6Y<;)59eUGp{{Q8xq22DuFm&w#%OR>Qs&Gd(z?Tz;k0Mvq0E>mt2 zzP4VaM!gu`X^0T!{$XOR*Ca5fkSXc-e12O9oJLS(W+COpg^4&RUZsYH$}<1#2q!!m z#(q35!sBHRev3Jv!9adHza^8V*5=Vy7iDHq!tKYmFi#o|G_^b5de?FcRem|ZjcW1_6a|~}aCNw6+7^y9zD+YU;23;Iv6)DsZ z-jgKpAdRB++uf>Xl@DdB89dt8HQTFm7CkigBj~DWBe0a19Zgs@`RRI<{Bpe>{Ily- zT)In8rk1?P|Je6^GbPbWgK5;~XKI`)BnuWVonN7Rw6(#=W6U`9`B_ni}6x)$b8zrhOF+@0O_ zt6Op6a0oE_t^LT26M&+5hzT-3l7Oq+mYcb&epmGrzh&eETk`fEG`f@8`jMg-_QPu} z^}WC)!QaP^%KT3FgslEY(W1D$mCK-8Kth^P@CQWdenIrV^R(_EG>tim?K9t4+h9A8 z`81)bMkivuN)^;?lx`#}iUeh$i{=f5ERIap6y%MB?wz`yQBP*)E>D!sdPld%;Uht; z$Ifc3RA6IpW&n1N!FHi&0PD{F8=gms7fIBf*_vy}o+QO8!b`=a(;BT4{5hJsLYUvp zc*~mnUk@j!oY`l0^oBPqTmw1An}0c6&~u3%?of`{l{H$QJl*0fj?$yOA|nB6Ja6{G zX34|kia9TXj$ub2R`kS$y!xlgBZN+>FO;3cB|KPNU6#V6=1Mry<*eW9ou*R6-Y{?VneOD+u z0Q9E;i={L>1%v!lf<5{C)(n8bq^>0cYKNIEDgbgbzhGd0Hi$owRMokV^63!l+mEiy zML!^6SHfxVP3+EEIPwDdNxNW-^Bmh1&xU-xl$u1GB!P!z`dehr>f-*}!Eq=2RMJ5b zgJyY@+{$t&)o1a!WLbpN3HCh@jRMyBm+6eIe9=OMu}%~O6jxtba4>~zN(*x?d3pAB z{GF30>RueLo&^pdi{O~cPAM-GcaFoRE*KzO`|Tp2?6$mB+gdE2Nt8tH!R z4@fV4V4>meog`B}TJx`@desJ1Z(1GZtTyEzT^fPb5P?m5f&p8uygFaM7CNp!d+c?i z6QexV`p(y2oQFuhAmPz&lQ#if^D?8N>EmOaUD&?~BR8I-lZp>8-_EE`tn6WpB`rc# zPKfl}dHt(6>^jGNUB~<@7Y+)Vp9`Mdo`Q|m37+4Jvd$3)cy@g9`H3IMwMKZbv&9pG zAS@IFVFr(X0oCPy1*)B?Jl56LY5wxx3W`S7$Y5Ko=*7b3Xs#G2|# zlJL?2@ls{Tjds`D=QkmfAAthMf9j{eq&<0`f%)of84$+;Nj24f?K@>7eJxAI+OS9& zpSe|An`#3!r%5{h`t%)8W{|k;_-xvPw|M<=+VXNutnHK{@gpyjn4!u$H=8V0NKm`( z(_!gtHEFl;9E9U&Kqb>3M6kITeNU&H(ssi+@{2}=EHfmbIcHJ~AYS(_{e<0#(lH)pd(h>UQ={rR+jXX4B-^bqDYhGjvqe zo!xxW?JH_DD@j;_=|XUJPdd3-^dhV!`67%he)FN^5x!`F#LnnE=J`d~4~S%HF35E? z0w>^Se21-QdUDHdp5IOI+_77kGQ@0c?vOai7w<4@9Pmjot5jj85bz6@@b-(X^-^x75z zydxz8VTxiZh_;(cAjCajzBUArG};~yRU~n!lbDd;ZhvA+C>l~IzljnY&mH7K1ZrSc z7ce+ev7axK^uB8OQUqIZJ2k`LI~p7krh$;LzDm+P1$I)r4XN^qq{TLrmM+hG5nZ}w z`AICJ{eXooIA^$_b+C~IYG{DpHNO#Dl?3*>VQghLeT+T-_k>7Qyc*n|k#K>Wv~6WeR321_JLKk9zvjxjZF*`K5Z_Iewq`MHY9C?Z=Q#uvM_k$XEiuo1 z3JMrahkHj>%}G4Avu-0mW|1amUHVZ0s@Lk~eEcm%#KNT3o2CZqdlNw?EvYl8V;rTo zvf-cH;{Q4*&8lk~!D7Hgu$XK-T(Nth{#`>8232k+O+~b96MGa*SN93)bND6oh|Stb z4za|s!_B}TDwY6`n=^I+?IPb#Qf?mp(~0)`(KZQ?f&cbwV=LPj+hh+Dn4ULr;Am!L zz`jAP;8H7Z_DP{+LV4DV@3`Q6@Ij!&zSQiB@4S>vzGp~qtM=(;0Aim>6m>g+Qe`$?Qg1L}OnQgJ%X zPkGKM60EPGdz*{e(g+d5U_zm?tRirxRjJ#J^_JsP5sUKg5e`)>$u+UG$cT46ZWJU{ zZc9D99_*k|#$TzjiSX+Mlj2_et1XcR zr`K%UC`iFoRs~8J2EC||qzZpt@;Crc*o4u7U!gAjCwmvzkO>6dxTL#Z9bn)kEiR)% zWjjqOy-49z-$bHYZ+q0|I0_fSf_;~J34D|9#&oW?jaHV21W1KVOza-`rJ|c}!H1AA zSTJMBJDxyZ?CS}k$tolCh>ehAMxZajZjR+d#p=F2b!zP^Lu?gYvY_LGo_QH6wAY(msidams!O# zdIN~!@}7pl8vwpAsQl;v)=~fGL5ejxq&>CTGT<)8Z0!SdP>Q_%S+fez)De4=`Rqq` zd+1+gheV8Q;|Xu4pXA5aJ9n8WNz`I@Q;k0-o1gnAAK}VHwS-0p(dAyQ?lObe*$X_X zEUq0f$KgKFoEGI%zk{pKBx2Jh+)kKf>`pycPS0FahYvNb%%x;-kx!?`5<;LpNU|E5 zuBM9^88?~8&d=}fWXr?7N1~UU53vRAT{tv9Cw{*2h7E3+Ws7w`LvSww2K^&TPF;e< zZ}j;x(!;hIJiW{FXAjDtK@t@kw6XOkhOwxarz1~P)H~gdAI?FU9NzB_EmMcq3nr?# z-I7%?Tfm#^={~b!v!=@B%$$`#TQ@=yBgYZq;|6^QbP1xBwS6Ci*$-j|bnBn;MLd2i z$&LHwv|x%))XENVQrwUx2G};tCp6=aKN}L>W*sR}YKeOvLpjY>5uqc&k}=63hCoZf z33;<`%+b%z!e2&jN^SD)#e+xK-#%~n%8HYo&3o{0*O?h-idPhm_vHlDhY>~Xw`#w{ zRInDa<}u7yAiF=PZ}O}fuLtX_KRpE_5y2LADv2C7mCmUcJ|_7#dUT7NR~nIN_@< zZ>GDe4dt8Lz;!5i-nz) z!8?&9&9`_FX&oY6NS>7MfLc0yjexrcU~FK^{+1P}f&De7`Himj|K|X7)?ha+Pe+7R zbBy5ucQj>5e6|VRC_?q$^R5XMm18%kheA4XrdMmD^)XQ6}_ilcgCz+ zNh6Yr(EQRWY+i0niD}0!yG|H7*SA&c*|1G%vEYl%60o(M-2LWN=IqGq;=?(=;Zu@> z^|TY%XZE`n%##$^KX#+W;Pn?jK&EoO+bg2rgh0wg!aql4vK?UxI zq8}0G4w#NU7)$k{uE0L?>6nTn(DZQN@1>I_Ze5KLWqONOu{S1VVVpzEW?4JCO|eZ& zZ8K8+{5fQYflqpFgVf;IMT)cB-y(ujao*sTkF@8VfrRj0*3MPPYyfqHB=yk)a3lZ7 z)BO*>{EYO1K%@tj`_qU51ulS^GlPevxd#LbU!l(Ure5RZCO>gQ@wh9(UT(2tLp951A@2lihgoY|V~A8l%2U ziIvg`LG@Xz&?_QI)O)B@&@T|9ACP~UD^eR`m%7N8d5WXa!kE7udcs8IUvQ?7a@Iu4 zEAej5lBL(CjbgVR*jFsojY^*E;iRFjj!Y4wodzgKWo9>55I)>yS#1fOMHKv7)cI|d z>|Yii87llnZ0JW5{!g|zR6hw(6q)~+VlD}-8*@tKp_rR9I0fBdWdV^g!y~#(&GEshoRQ^$`|aL=okI+DH*!79 z*!Wpd@AI6Ezw&d1&1kH0GE;?zcO0dM_IPpi?s z9|Ao5cYJWrNuRbZ860;I?y)xG7^@k_%2s?9>eVm@GCW5ze1eL%)}csu65AV}mxIHj zLhIm7H*59KsVtk z29DG5WvP6sRcBz5Ccmt-$TkV>H*}btcF+!*8oeXEM;?2Vhe{-K9V@Z0tR&H&6RFsd zn?xzm(eB@vZqtENglEeA42g>eEccwL_<~B!w^pebK1?S&V%9xG5|T`3N`tz`Y5C*0 zNJ!Tqu;m_wQ1L5uV{d}qD6pG9AhvIYX2gdcK=W-2v2NVlM3tt4O9zb_ZwGH_>3^P& zMGc#E$*p31GjPaFTUBwPCsFY_qJI(c1LEKzb=$CzYZba{ByhWWm?`gm|Dj<`nLKm> zkLA+yppw>{d)zSv1M@d9L1D;|=|;Zmt+@>s|8!r+vTnTy?t8gZ=sF$pQtIuk*vV*LQ}v)k+dVq_%gX-mCR?$# z^(-M~=}W{E*g&^(wT>}o;*{)`UEH#n_Tl%#-3N}xV`*=3e8%r#r5JJ>@S;6PMhz-} z)wmgpBOi5PBcVmlnVurCUpZ*L%rNgmpsuh5`u!JxQFhNPL59d?M0igL4~MpN-c z^lH^v%*>4xNArbedl;LI=5^JjE)R9Zs`jn7sbk}Lu_dW2x%pp&M0_VU`8PHaVt3^5 zyDo0i-$wkKwDChE>;EWMrH~BPQPg;h1AO#r2Chl`-lTP-&xaP|gEEH-*%INq&o5-x zAL!r;)84!>YoCJ2G2kkl-30v4-0s}&ZoNVGZ6gmQW9@L~2Mp`lR)Le^IE z9PM(IDMIfRjdr!A3cHaVefMDL2GG`ILfnHr#wZ}gJ>vY;D!ZF^wek(Z_6vE0mi5Mc zjt$UI_2`;Xr+95ktpBtnx4sa4uB>hte&ablBUhtT`5{;QzNpu)g187?XKM^RHv=<7 z!7b#lO&ByhKYdZ6HP7Xj#x|t#j{<<7aoqSHq?iBuee+Y^^rhh0Ep^x^dgI|Ex+yuC zfBf+fNll_YsYMyOwf&&d#IN_A_&RC?LL*-1gg&zbrrQ$!K%D(%PXSo??it7jlGJOe*Q9_?a9&Bm4oGaCZ3aK5-m&2rIt|a&H42jaQtAt%83* z^3H6A8mxLmvrdDgzmW+WonR8(hwRf;}&<4kMmR+Gn%tK-QP+nDss#F^w}wq1t-^ z)h9_FkLg@I%gf-)Ecbd~PuK}byR3gXBN7K$eN$gqlQd7DH+|eo6$6=5_OMENI~$tF zs-E>lPf~zXOPn${O+WmU=*KMPguCPYW~i5m&E<9gU)oZhtQl-OvASt? z*X@y3Q<10}&HFg9q)4&U8SB=2cep3rH5ck__f4YZ9OG1iE!(s57p5YK8q5hD?lIO< z-%YTEnDZ&P#FphNFeFU6Ma_vz;;kiidrZVIgr7{eWQm?D_41lP;k0etF`BAj?f`O! zHEmmu3Xl|)C8i`xmP+Cil079$qgcEnjK=+mGmZg0fFse&!ou#Zg;*%NtW2g*f!9^{ zG&d*9@K7s2OT#*t>%wWP_a+0<66VLzLb^) zafuObcKvfq?2L*ac8%Z{;)3mGm$OOm0RBn^IW4HKm^v&75V%lY1Hw0 z;pU!;4*O{}2#MpShHM7w$CF^@EBP)HhfKftbn%h^sUt5$=c02!7G*dU^aT_WQT3G=;FF*Jop6luU3j0Q39?y&(Xi8-*VADdRA6S7yB;p{=Wy7;3G^Ssx4>}F zwfMT>?_Y=8C;w%*EErz z2kw?f&(Fy((SYIPXXhZ3_xacGG%#GT@h`)HH=LZSbqR(ug)#r-4-dvc1)0Bo5ZOHp ziWf)0yNv$<2}-$T8zuMKC+Yh~n15UfV0H7Wh*LE3KR>Ae7r*{wjl-Dy-~gP^9$TOQ zt{hzA*}QF{7tvl1a7ECFCQ65#Gyvrw@Vr*h!*emG+0&(Jw4y>d>Zf zn~d;430p(O{|MmLe!FC)R*lLVP&2NHsN>XvCQYB2EkU(9ZuW|_acubqLxjc!R3VN3 zJ{pWB((*i__eLr3&WJ^H3Zx!vbs3^Cf7*dmAhBf4O;*kr6`f&{@91Vw3Z*I^Os}Y_ z@oy_;$kXOyn*Dy&ZL99uy%XfDUa1rpuRdc`SrN(bqPUy)^Xq$2H28YK))L4O5MJ>Y z2tv31pMrgvTU9X{18lhub91tMAE|Oa5t8S5Z)evwE3QB)od5ix@jR5>z-i`^juepQ zFl-LMvRGh)HKz{2R^N;Y@>;-IH3LL-kBkL78WwG?WH3PTdEtbr7oa7t)*25Vn&RE2MLace|p1u?5S4Tl&5XyMh2FN%-&V|ca))|MP&b=JCUK#(T# zmK?KARs6jEE@;rT1Rf%8B${8HsMY+9GWp8EFJA==mN`pId2yzCF(Z>=UN409tg>!L zHA7+h3gzVaD{%k8PeuzH($BAOe?aazzkIkNIHw7ES~;yIpOOOt7r`gzFmJxsnG@oC z{i~aWRv1+`+#c~}MCr(V<>%z;t8hLnG|pqjgLP1j!kcRx05e}s{Bb@{c+glGCyH+8 z;mjS!Ao;<(BXo+v5#nqdTTB;}6|9We*_#ruBm2?v#D|=^A>H@T5g?=yN5`0#C zGAj2l>a1SI;DMgEpUltd+TK(hPE;KoF4s&Ew@gzE+qw|PJK8ppjO=y9Z!e-jUx^9% z&n`?3s!oVr<)({aLB=!QQQIxg^Bl^c2o*ari)csmWKBfKT-m5@G>t|%ato}aM$az= zrmrwv7ZK@Q|@dKg&?%NdHcWG+>(b`cgTY2Tsv%OehU8e^#;S|?5Svt7PXEj!j z>gH9AAqantJ9A|VGOYtd`gTd4ec<8U1rKlK*FVYCbd+ngf8Dw-nt{#O%CS+gFH;Xh zSt2izVy%)*j|!FZ@?mg(2G}M&Fjs5pYzQl=7Cv>NpP-7)Z?V=)FotjNpw+#5toW*h z%m2Vz5jKamCwO@P%1Ssu7eWmU zb>H76=)qkGijQQjrhrp}L<4peyXHaDG*w9`Z3O?r0Q38m8kG@lYkJDVKOmphVhE4> zRFAs4fGu1YYzNx_29IhHA~VT66=_w?j55p?CW|hb5{gW5sYXK4zs>3&#>H+3$07$i z)|M(sru&VL#aZ#V(@PeQVk=D zLY&-Iye`G{Nn|LY&!ns{YPM=4ccduW(%~C_K6-E0KOX&!j6BX))T?CMLQN_nx96#P zF`PBaDW$X423yzn8gjCp)Fk+#Zj)fS1RDOfLOi(0PnD)=55e1ia^1z#w2o??c*|Pj z0re0{tGl^M!Q#Y4d8KY&R8kDf&l73$Td$)7{JFx;$jJ`~NUwxankPPb&YPNHZ{4{2 z=~C@#>-u;DZsG#F-0M@j`4EnA?qztpzKg%vXQ@ufDTZ8}B<;28Hn-Bz43{t3j-_y6 zyvAePp+_1!v1yC$593dpQVU&Xnq>gFI1DoZ%uuVJP{p&t*Qk^2#jpSOX4bevO z!9&g2vp6Y}xxDTk89bVON)CU930Bm1Ch&em87<^xSPIeyiyl(7Ut;fGs0z>y8`KU* zG_f6-(7N#`M2Lrv-0;I`Rx%hNhGC4_adQ-!%eo9KRpuKyeb@Nd*Y zq^<@gScgMP+OvU+ zGypk+LX(-Ro6{wSjJ(o~QunHBO?;t35#J{n5Fu*FAu})vB%h`&O*{_1@6q`KzKkCsIl2EyVkDdm(rc@s}DpxnH5&PVpLbrur;31jfagKfDHkamkSKz(dzmEVRNxaEvGpy z&oLhNDTrkB$s=+Nx*ehM`GBp2VB`g)AYPt6i#j2~kzhGGHK!qej+Z`18|y23F4uz) zHS4_ab?mlNE<)mWv$IyAC~r*q9hDUK4D#YeGE$*(s*)sBeO_PtEMGi?>z1vy7LYuI zU{*QtA*7kvnAz=~NV!Pl>3Xu~N+@ljF=C=oa^8xJL)eB)_wSm*zPj991VUpdJ zq@dM%yHBEPKG(rb;&~^?#>H@VR4n;r(S_UiT1746iW&%7$z(ltOoodEz&7@G0HL#NeY#(}qQ11WwCWoZ zt*_+M9^K<63lgcu0^$JHlcFl_lfqksD11^f#rtC+>~ci&7t9-tlW%^l$1^Wc_|VW4 z$!&dA$5=_yQ1p&XlcIih0=7awXN;-d9U4>9f$zGDx3gyrTxH z5n0r=js1t#@==5tmwo%9L0UMSR-ams#wbP24i&GI@;7DtuM!!hX+Hv8yviDJ&%u089npEZts#JY+|E)*+% zvyt_8zq2*Y-H&Bw6eDEoOzQ2m^DJQOi<=0Ryw6BLTzv5vb*kO_9g3hrZDqsY;YPgV zLK50HTcC*7^nQMy!cx47vZzij-^5w?TZnH`^lJubHl-kg6R~Y!f^{mYE-C~E$#4(e zn?n)GhP&HQ3`EJt31*+ZV>`URS~)jWx$pous^>(K5ds_WLgppszz#}A&rDS2|6=bg z;PP6MebEmK?(QzZ-JRe;g9Hc=+}$DYA;H}>NC*eb3Pbsmb?0k^6t&l%H~|ZS8zOZUmq)9tB+Fl z|27KM8-O7L|CL-Y7;nD85k;Ep#e^+$nK0hBWSsP?yu?^1BClD=yEfLqj(+$CKYvRv z8-0bWmsR!0`)oGj*spS+B{?=sxJ_x7#5K(tfo;;Qd@`@a=ckkLp==j3d7 z+xNzcnYuLE;Ld|HbUc(y3^2K--!xpM#1C1c`RLA9!HKW{!5?@IE~dR^nd~@A?qC}X zW4L+~1}R|}HQAb9A7}`!=ahQ?BBmN%o2gYM>wjb@e5pSu)OA@YUO(|l;YoM=Rp(G* zyC!;uffRK38IO0_FHeDNb+6;aCk`{`uCyo0$}tJwr|qE6P*Rd*M8RWO?B4Bi+SB-nh}vd#)7sudO6K=r<1E!5StcJ23(7!B*}Lc#V3Znx zMpaqR#~R5fRz!iO_w*4l>{`AXexo!sJ+&xzc))gTL32vSMuYAcZ{)_!N0}Z zqbRF%os@aRSuq3|#=b27GYcdgRe6?xZj$W~nhFO)oTbq8#> zgYc|3D9j@)*l&8b$zv1sK^2hdog^P1AAjj5k>aO=GBYf5sMzMNn2YSPPIiU#%_VSC zQf%~S2*nvh7qqPe;QIuIw%eWG7Mg*g;_I51?wPw^^uKAa6Nc;$B^zCZ_@fHSeFyO$ zKCdPtGDsI_>;~!8;ZS~V(!X>8)MH}H$(wH=O{YR~?`(&9pM4`rz%HHUnot*c+$^W_ zAa;IdI)0E?KEB;&9xB;^8XJ(|Me-KSLBan~Na^#f&7`a~l$C4ouvIj@l&&Q92Ys{G z`bBq(O4|O2n-h77UB{qFS$=#SwNQx%3 zxcmIT4q^9HH^`1&)G^`^gz)lkJ?4o=N9*eH%~Q=bo#hA2ylKVgwT-FTNa3e;&hnj1 z3&)Z$l|x@@tmptyeVL({oAn8F$r;J*5+Gv4C3;-|YWx_#u9K07AB$M8Q*q-7by;I` zq(Zsv2231TFvQ#9l_t80ma-EB*xj`XEL-GA(o+&5u%1VnLDPk5n$U zx#Wp{9h6b(nrLcAJ7Ovb%=9nE-csJ4(a63LGM~K&2$$lF7OlyYiy|=**H3F zlnX&w6jcQ4i^o_}g?3Wg#GNK2L;XO046d@xFZ{X%ht>tBrgpKydq)Zldso4L%Ib*< zbFDGG#t;rhHvck;85||EPoW_NOXiPD7BFHd0-$=40;k&YgMs7j-@w;tgLeW8%3FKh zZ7c8id~kQ27g)TSFAsK&zj5nP2dH4YT1crWCDPU%spkL;|8{D+ABfDH2D9`o(gEvm zzs96bJ+Q*dmFGU9DZv7^tRjG_l_t_hnh(N=$0a&>&F)rGtd!LsOg}Rf4}lDyEI^7E z(taA-QRMS(Y(1C)EOY*DPAU9TQ6<6^0^jOx^J>TDn@%pU8QRRWtFAo)i^$#7W>w8ePsh_{ttc7i~jj1IqGS%nm?Br#A;*GXu1R7Lgt6 z2in+DG}IqYMEAO}4VB=B!m88PsmeYJVZ zD-lTAyh3_pZ#Ajpe@{QXW4lB!76G@vga0wyvKoZvR}YFQhCizDR09KuCL)i43aCKD z-!H%p30J2M%mF=r^1aAP?qJvEr@88q;ilTOw%uqvnQ0a@3%K}R{z#2pU=QgjFw&y) zS5WKa_84()9&yc!3aCZ}UVeS@l2}!O^zgpDvE zP?3a>@?)qL9+5xXD}PkJ!hh(|ub4?^#d@x$x2}mur=B+GUAZ014`;Xq=TDJkS_!mL zszrSn(Vq5d4l!Yqu2h^cVBizDT0gSa%#us{WqCRJJN{Wpth6E2HtEy{)fhnv@Jm@! z%$2r3A+u?xqWAYYAW0l|&GaZLZzE}TawfMp$ikYQl*13PmwesX3D=5!MPm-FiYiThXM$sEe}qt5oV z?)&_Vc)SO=PLUz zYG>s}dVTJ_4-w9GW&zUx{0e~4fz2s$k1GLq2LVghgV9p{_^%lDj}s7Ry+ug42>R@+t_8sd*C5B~iNytp zr(r^2uFddTv%e27dSIXHRJj}gL&^i}$`cHLvGVW7JL-<+cUvMX@W2m8eG&3*?zfr_1Ncvr#?p7S{is!O8){Z~U}EAnNQo`nGe1wU5tlKVXiUxO}jTox>m0QF3!Y z%BQ=0I=4@4X4K{*dkJfE$s++jb2_T*%H8p2m z({Zw?6XDY4PIT<$c%3-ny5h_5W%OS%?H^_sPKd$X_bOD zU;+H(Wq;3U6aQtA&j;9?8>!n?gk*zI#WF?@%PH6?zJ#XtL{XkZGvI&4E-uo)=Pt-$ zi6je{diTp~{xbDi{519MyB+l|tyBny|0K7~82sb7Q6>GC1E93z#bwO`i&dlm2dsAG zl-bm_H_ozJU6X*Dp78r3%XRZrBLlioQLuAk$4#s0bnd6{&$o`2FFJ)*rZ|t-WsK-b zedbYE;e{$M1Xr91vi^QfrXoQ+E-UNO#Caqb%gLlgC5oMWRvLjK2F)x6n=ym*$2!E` zI7Iw}jpg$@c!KHEZ^X+g1H3u<8=63$g+3%wS+^W>#I~JZi3q zzaW2y-!{^A`c^N?!U&4bHEJ3=RQ@$mOg7RAM3#Xj!&m`|44vzp610C8srbKh zza~@3b=Y^1+>|X@O|7ohn~z(FE)LWMP^kzdCOUB-!rKE`zWK?SEUUE3`T{G@Ty10- zPEBP=8!M7h^X4neqyo~mQ`^W%RSBJ`X72zjED^$FHssHT02`j1 zxO`sJ?R8mKg0-lUbP*IEUxkj73Z*cFg@M&sr&z8JyvgxQ`P+LIoAc+1worHfI zQu@EsQ2(80)xEsty&4Z!{T0Tw<;XK^D2)=dK-(1qyY3ek!!IjDCRdN0g~_LxYwb{w zMQew|&y*V~!&b=>Ix#-b^Tlkwse&v)9yj9S1rZw)SdY2qe+Q|VDp9Nr%q?PJHUNR5 z*aVI65*41vB#>emU}tJ>Z_E zkE%aXr`;Me~8`%ESTqxLbMkNYt_#OE3O~(Qu7NXdLsH;Fv>VIWoIZN;O zuEq=jc6Z`Lso^Cxccorl^@7MdOc=sNXy2ad^3NXZEU@^*dG?RO!3u!9Dc|ZkDAgDl z-r?}Zh_$XiJ0<4@1snDI=oov@YkMtosO;mmIn>~?rL7gkQ^6_*_?Cmpng|s{e>ZIL zVns!{OeO8v(r6?}6C6MIkCWt+21&A}Rt;KO)Ug|8G3Dc;gkKx_d!J`$wEof+|DzN2 z|4&}W?z8eVO>`(3Wg6|QIPgff-8-tDtxrFVaAGXJM@^35cj#fLc<;+D$Y$hJ;O?_D zw~YryHs zxj6~u4TvhLNF9SHNqQZ!dPQUxmtMeG`1%##+~lmO-J)s3pup&Qn|Q8V8iz@aFO6PO zX*dr73(MOLl3iI8QJpYp2~ckH5bPUwsmi=KG_6}?yj~cR?M z4@F!Rr<7&RJ2sS`^uB!@dLvw6bs1CjYN4Ng;ouCzG*g0}xQ%6y++{tAKeM*}B?+P! zX;2Jx#${}JNi~rhqyf2v1Gy%cHA}VJ7@b3K;{u>5QvWEDgr6uY`zskXZmF zvBi67Y~!iGw{-EP;zQo9?wd(4Qz~j%F5$2)c`^+gD56`hEAyIdB(7rQ8v1TMA~{(w zPqNl}=N7av+sq_=JSBwEt>zi^1e9A|Ynuvqo*Va+&+NU?^W<2Y^hxEj=O&sjh00iT zQn5b#+*W)>9HlkyfFXhtu!Ozm!@1`#V(XPK<*9Oc<^!69)&2O7eB%BKp8z&V*x5Rp z*g89r{a~Fci<*bM35&9UnF))kiIbg+qmhXdaFep5ozV*uXEGfYn{wb@=A_e65ga2$~Y`v(_L-(Kqlm63}7PQ6P!NeN40(p9Vg#i=bnutR=~Osp=AAEliBH(VvjX&JKL5VP`Lsq4uRR zV1R_6iY;q;KTbezsKfSzEY!vZ>up&MRULN8k1P$*M8`#6>S@TOWo0%}Cw^5%_v8PL zhCvpp{4Sh2by*oBho2?37$p04mq=3C7n)r+K6JWkA2|C)B?_5VzT>>dyC^#W+yHOR z?+;1k0HtEwgFTfDlq1WDCb_Mx;*Ad!Lqz}w)S|M?|9K_IEdLD202KGO%wMsb?2a8E zPj)s;6eMfSKszzeU-K8*CM-6MwPWQ#vY$1eA!R6Z)D`l$)PTw&iDJyp(ZT6R0Jm$v z1GIGiAiVYmalf;rmSTcH4)~t(8X>Fl8&LdGolCh5ouO?j08FmiPp7VT6I}wAd>u_~vBtQTSC&Bp$7!8DANBUR{}sOQ2$vCBuE)U9eMh)90~&lAZK_Td3K=X3>f~# zG%KyH)3w+wdd=`+I*=RZy^9~IP#ZeJpZXkhQ>}DfZO8&)^H!rB9;sgso`~Y zh`B$+{m2N}uc1OIM!-6Uq7K{W2MJfSoftEbi!&jBv#&4BR@_+tFGS%BHqEW7;q4xDE zkUJTBD;ZXr4a|JkmV6j#Iy5$itOeGEdl6h*Oh!-O)X~NaI!c=;c6` z{+;Dr3|Cbi{?fgfj}3}y_!dt*>R^myVmQ`G=UH;_u&qb_z}hKiv-{jb>rGX?HBT3$ zNnXn;Y;W_y!NcO&#PFj}{V+36bTcha{#51V7sZj=nfKPw%+~7lm&5`*uo5d}{eOH28 zR_Z-CWfI3bNj)T92(3JG`#qWvm#DI$kD6X4qkDZqxys9vL`5C)IO?CQcdax@>DFvNN5mQ%bcaO?f|_QeyM&b zr1FxMLbQQ`+)fu%$6ZdjK8kG^|EAdoYqPnk48h?zah_I}{)08wiYELDDOGB%iMWi( zR)oB~l-DUT1R6W&0ek%0kar2auRMdaTnMO#Zbgy3u6EyiEWs|2-5Ov@CL({Q*CNp7 z^Kf_jPBWbl8qI3r8<)7?+Se>;)Y0_)wVU4h-0cUS`Ufk~`dkTTF6ugVKE#Yl^tXtK zxYWYPmL8w@lh$q*gZBqM+2R@tupPMj3LBYHBxpUrm~L#IoVaLiw_8g?JZC&r$MqP= zH`dEr-12hK;S4FaBMM z5`2TA4)fQP&ytIo5MqPNRXq;4NA>%=l1Z)SNENNs#?P{h-1{sE;HTeYtonSKCr3kb zNxy*p5b)X+UQ_KgJk9&mUx#;F{W@mrAN&6gh?LxOa@?bRc@3ta*l%sVX&qjhZ@ zjtIKs1eA+<$v6Vs^+d`vf-8h|KlxM>3998r1odgn*r6j|e2g(-+g&AN9+V}KYwt{p z6noWAWc4viQBfQ5`?}UFlArGx5t2n=fC(2)E(*$;r#3=(O@RLnTL`Y;%s2JfRWx(j zpqCul#$9nk3m%50`kKMXRt~L?ivpBi$aE`ywmoLT>$fvE3!Qx9Wds+x5@P{O!;_&2Yb5pp{WbKi{!lZLvrN%vr5;;>oRflD z06#neUMk6DuK0Qck_0p`hwe>FylXu#f1xAvHhlslu5lJq+Add(N1BLl_N(Tvt>^UosTYsp_PZQ+QY552P(xfAw(XK4)LDkN{ zQp`pOqg7ib&0ObAj9uK^p5G4d-frL?MNOdu6c+ZoBrEsRQma|C8|U<9KczwJ+d$*) z-3U>~9G>R6F+86v@nz_Gp41{=g*6d}w4g52-9yG)6dW16RaO%4y&SB?q}leaMc|5* zQ|`N%QCH@=M;AN1WQDyZxU@W&Lb{)X*@?0gL$IPU+AgHiqYS&3k&EfNT{mdb6DiF> zFZ^Y-w$rmt?P@hgMky$vkc%2osCw9{<)OGmn)E*GOTS@{;ZmgvyO#hLxAkQt9`<;? zP_=&D3LUgqg*rqtZZp^r9ZoZy#WbBjOR$0KJsQ>)5cVSFgzgc$%m_lO9QtfJJ7qDC z)^DWG0Y8?8!u@vrN>2jqF$1a8QZ=8;o<{8fCt;s^1^V`Qf347FjCOnQVsrIm zZ^|y0*+yDoAKwY1+L9|zHl1A|a4CYWLQ-0p`sJMv6xwcO2Cv~$Zi_@Lq?A~n=mEcm z>Fa>(+_N*Tv$Tjy5*SHN^1WBtHH#zQY}+X`q&>FcW#Jd+dg-)V@u#mqr~&G2+Z&=B ziuUMM8Uaz}g&q&KDevn?1S>OegjSX$F6O0CIM;ia42L;bKICj&5bA_2!JKsscn21I zm(%>-N_-_${wU^imzbT*QhiacaOvJQd-+CG2eM z?QDOj6TE-b_}F;3S^3!hPzS!xeqRBh$w|pdfgm73APC?e==(fK0tENu3G5RXI9OO% zcz8GjBrIekL_{Qf3`|rkVggbUVge!}GAd?TG73gYA|g7Tr;My@oSdAbw0uIm?1Ic3 zoa{d`fq;jHM?yrxLq^79Cnq9j|F{3Xw}a5(plM(dpdctfkmwLl=n&t#K%_uDVIY3{ z1KhNK`-6alf`)kl3kQ#Y2;5MM27-iuf`WvGf`NgC2JZF-u7jY_VKB(q#GYWP7{F3E zV6pqf=D<;kS9V~ljvZ5R7&`jHBjDiT;S*5P(9%7n=j7t%;pO9(cqS<&Eh8)ULQP#m z^QD%yk+F%XnYo3fle3Gfo4bc+z}vu};E>R;xcG#`q~w&;wD-9m^70D`i;AnNYijH2 z8ycHFcXoC6^!D`+j89BXP0!4Jom*X7-`L#R{%CJnE*AtIkT0Ro@bf@>g zDHWm8Hu6X8sWDNag5-6jn*);@)Z^U2lY;xps{7z;O-&$tZl->u$aZb=hREk=mY%G$ zxxrJ?Rb5>yhyf2D&hMbiY5f=g%u2A006c2N(gzN70ZMuLzbz$m6dwqd^4pCpe-v0Y zh!{%SGPxe(Uw1`8cg%L0lIsJ;$9H zuHWvrY?K#&(53Q6{TNDs*rETwEv32zye@x)Xi4w}XIw`D`f`S2kaL=S5&P6XhP!9a z*Nv!hMRj5Ck)Fd{9YcX;>>_WTQ*};o3m%$@5^az@2-X&KkeMG?-ZrCu3Y(Mj2UCCU zS{PP(KnQ|i+X+b<<~d{fDC913AtR z-e=knw|mGPOBp4Uix4)T6>4xV0m2-1^2`cv(aGCw%F76T7PG_uaeMcG*hp`&|lO>g?ACnmEQLX^{@$_sBqmT@}~WomKK^ zv=)x5WiO2}iqsGJFcp?LrA~n%BtRe@%TpWP;wOM?utM-)Y$x zD-ffrhQ>RJKiGP5nP;&^if)l*TxU|tfRfQcxRugX{w(8^b!fq8GqNd7bNoAqEzix! z=${NJ`k?p|ifJ2!@okm56y4f)iCt?;Y@1t~mvp+rnRrCo^<~x;pIB;D+}zf4Tz8UJTytUpWncjx#& zIrb;V{-@=LKl|AK_xl*v>N_Rnme#h~NhBNUN+>$EQL+b5P5D;^L2VnxGvK|73$Cdz z5Wl1M!ZNKd-{7tTKGcDa3c7;&yYUZWuX>}w8~Ol_H0}+T^9i_E=}HpB|MOAE-@hZZ zGCYd&16IF^$M{a|#N<41pY$srrzyZ$*4;|=pYI;hXBK!`Gili81*a3R!j0GuLA2}1 zb{uG_S|vMqY>m^t%zbCXE|gH-m(Ti@&3=1}cYTHv;>*~p<;%r|E0`Xl!#CkfMj{ zAE5wo3Re`Tu=o?;qj7&f4_*-fpE!H`a`P9MVtPWpw6%dHGZ1HNNesVn#N;GMMQf(% z{p>DUCxzTtKW5uuwucT`ArTobQRY-CPNNrZ*8^6Tj7ebARJR)jLOV%H%I(DLhz9e7SWbO`-@8 zLqTZ;8n}<2^!A|!=piBBpx8x_-N9;gesG_X&arFVB(SE&jN;>J+Nv#{Dz|;uI&MT=u3S0S07IL z@(&IDO!*S%?dH;>Y0a^1?>?sqzpwN6vQRIhU==@pHHa9}2g)&it)=)xjEYEO7|Z&J zP;d}uEAvhHzUtN!GdI?}jU}nA&5&Sl5#5i{rNb zl7jFDRd5p>#N~GWVl~Ch5*elvtmL*QC0|#SyIHIEQ<@qEu`^W3UE#5*ftE46$!{ zW*BJWJE-;z8Zoh;WI@+}pNLDThX*K*qfRVSc4NB?a9#OqvsIO z%tuU80AcJ)KhSAbob~V3#k|(qP+rY0h&^e`ljn?Or?T)MgWb)cYD{um|Dm*!X*ifSK5%Om0-UKES6tdYI?&Q}CnjMMXv! z$lTMOk4i)6qIhYKRgAHo0k1yxveSu*Pawf~-ypM~Owir45A*IoKI=C06(BM|lxTSt zgmAXv=(t}HHXKBDP;keS%i@hFiOsZ<9!GzLh!y}42Raga0eRz9R)i06TS#U%6N_;W zT{ynp)|S>NZ_k%~>0LUg%GNZ#8ml4-XJ>PwAgKkoIj^uU<%H75$kBo4gN->YEtz)Y zXHBY=4-@xL(W6`oU!bU6qi9`1H%;*2-kP)q$&jX&E+5pQF%BEJR^H@4l?B{?96S8) zmqi4#Ru{E77$Xr&8AHkOG@Kc;?|h}eY%eR#d0bECdyx-{yNMzh#4aT^ZD}bjg9%0V z;VEf_9Q3y!p+8Q9e<7PnKO#t_VSjFlzKc>*C==r7FlO({frG!07+`!=o6=FL;pRr0#~19x>)C(pG6LF%6%{~2 zs20V$@&xc4EP3K|lsHv}kb;OC#Wo9QolqyZtas}^>U1-mhrTxHdwG~AX>`K|dn~kD zwi$exmsDxAb))yjkLO^q{>oyWBDLfjOW_br&&IDndw{`iU$|e12`@?%BDC{`Zse)k?mAPh;8&zGIzb4 zVEvgPxS4L(Ah*Z^7Q-k$$|$W5l8A)7FcQe~!OHyhR)7Z#_tm9_gE)24W;&mD4!V?9 z6VU|}$%CX3Fv&6q#=m;VeWAs4m=~t=7UxcP0HWt$78DzQdZ&?iQQLbt{mvU&N%+E>7T^gD= zb8l8nWRAi^27S40pyL*fSqr91zPj7g+|@PJwy34ahf<}po-o=veT=vuPOleq3JV(i zjApS@Ak-4WG?f}t+g=Be$5{GgpXda@B0mtH<*zze4q-B^wrb{Ms>luuo_o#%N&$@E zI8U6S8v0fUW}sQ2i30k#hGgIGa^F%gyg@RxAApA7tSZb36$J7Rp~A+Ql|+RJVa*DQS?lt-DxDveg(VA zgXH+=@xWYu6h92&zw6d!PWPbBTRch@bYIAPkzowU2Sp554EO|RxH~=ii`+meJ<>#y zK1!ovfafb7!@0i9yjmAeS8=fUDm0^(b^2+Wky_iLW?a+CY^-)+yKR;Cc>4hwdUkXphDURVUgUR7f-BhIH7>R zN@f@e2o$FTMHKto#!XsYKD}$%RyzSny8n!!Cw*(+ zMR|dNowo`5sFed=+*91#r}$4wm8bj!0Bj6Vm_J_1=D$jo8~5yAPiPvCXbT$4tNsx7 zevvB+N-aYR+=C9~tv31J@{6PsXVfbijojO^20=Z-MBGh{{v?Bzl({z@$xNn=Ft`(A zWBGp_rAIBZkc!w-kU}`pALzl$P+;WZ;V&Ol68n=W)LgiDN)mTW10vN+};eY44Qu@}m^nC^QLAW1U4BA)*O~j7fYlpCM?J z_6tJ#&ovPrbkNolZYl$#3tmB#75e}~iDEc8tk!F<+LHO)+|Dp0@nanKnO&-zt$ApS zjksEL(>2*f+K#iX`bDhJ2DwOesCu0>@uBF=>@CuLLyu#@r24#8 zD%G_g3XD@#;y_0i_wHboG*8hZ}L(weXzAYGXQ!J;Z$;k7MSbZK8gnf-*D z79!;FsupB72H2N=!0DFNKit|q(ntRQ3e>T?J72z62g2BBiab<+_kdpFlMW~yxpx4V z%k=!?1JHM{MTudsN56xtmT%|5%YfVHT8X@TbJ{7swoQ7RLV#fm+#IT-w>jj+A0zAc zQ6??O;9$qdETe^%Ls<^jEh`C9zoS|{NBg1u0xR$u-7hKnDJ%%h{dn*f@$JVOKB2c~_nP+o z$KG(~cr)rHyH6v5pqQN*kZh}eMe?c78C8VMsIsRx?I9q1=W}GaP{Oh)Eig{U=y$|>sE!>QbRvPWP=#>!DkM<^UMW`QzuW#Qffyf z4K(~$VYuy5y3Ft8RolrGz^R!pfYL@%XAZ>&Ox^~;kF7xCeHpJ|8?g)krtMDD2Tx!H z$jLKThLDl2Wx|4hSzr>1?0V`uF4YIW6UX-ajO9CMdv5+a2oe}cAw>nLHV2!j9Sj7x zWG?Oag+4Pp4^W5TBLJY{x(OsW2n@DMV6e3Z{ow7dkN#pw_$84IHPi+SM=QH~IJ-xR zXm$Yl+qMMZHx6%!QIz|J#=)-�>uJ~PN-Avubh4$Nc+c0O8V4QkrV<0}T^vkqu zV6Xso0t4C~gCz_E8_)vy@{2D4-O85@d;)m=69XzX&N=x0N4&<+zo^(~M?X~T`dmQ8 zM$-SW_6NJ`KL)mv0>Qux0ghVPhJm_(MOWZ60HVY64dD52ks+n;$(MfUrgp%3-j3IH zoi_j8mrVqSD%SRZ=qd6D>i!+7#4QkjD$yAOq=P3ck2H1PvXPXoC0c;?{j*ko^6Jli z_2(G;H)n?E6WGo&M9m50yv%n1By=kFr!hNIzjoLdIH)oLmQE$)Z_UKk!;7C+ZtA5y zMhl5yH+2I6vlU=oJmqzde_RBgYXOlUO?9mlPMFKwEONc;5Zh?29*QV?x;j?QCbI@g z!B#+I=s>&sLg`2BMeT@USve-{u{)JVwWjK*M0MzOsv{5YM zqDj@gM0Pw`6fNdC9ZFQF%;IiD0%(H`>)B;W2Vg)~`BDail7$1*@91BXAKhhJ=YSbB z_tCTj69$+jSAdm>{0�rH1OlqGg-0PN<>(qUyAi%U6sTyd-r#>S(<6C?)N044IEJ zC!`Mu%Qwo=_jEsfr_UtFb+Z+@#sUw?qbo1~EAKHrIQGkoPzkW~uCKP;c><7xhJRO$ zlHxt>I6E(CA;3!3=l^QMWu@wZXscQfKL0vy;AUAvSB_4&6U(XW z;kxO}wv+pYqO-1xlITsV^Z=XgBKGGRx5u`MYgnV1+w<=rmZ38sMDg6@jN8Q0LWdO= z!RB;<0o+^8sC~G|InfR1o2nP)f{tG5hzgj!%Cnruk-E$_IW@6mhZhF4^USKR1}j@W z<8VKZEHI~vPB3gW4Z}(I@F4)}Gq+#ZwC(8tA`Qo&-Fb9Kz5Ond?G{ESaSQ8>8-oAA z^S~`~m3S+NS_sBq1p7|Dg0I&`-O2rVT8q2450TkcqqXwHT@FKG^GNdXjGIAjtKm2R z^ym34oi=Q0zg2mXp5Sr!;zVGr`=RyN;z#I1wCwXiXnUdSqgO85on?mGog~!iQab5_ z>5Y_?3n>lMv!6HX4eW^}F0T-6}T;mi+}KeKI+%EXuQSFE9ITY%u5d zo1emIAnD38!%+rl&-ybwi1gyl^^~BL8NAmK7ni3gCK!tnwlIzua*bY9S8Lw|^xp@p z!z-GBexi!bK9lIrvJ5?Ak}ggTE;g7*SV6K{>v#vJF%I)wQ!0`q0T(~p^?!WlQ$hy! z^#hPvGy1z$CFL(V^-tNY+Ad~p({{i8b&~`t>E!4>`~2;v1 zOS=3BUmWWra(k`6F*V@c`6%@iyq5vKg{zRK{|<7$;pki=y`tTXfVBVMD+`rQQQ1LBM$pNRJsTz&bvlJKaWf%R_g0b? z^t$lPsg%<2s6>z0EkQZh=vGmyHlk@P1U=AitK&u=pBI{|aYlIoC7n7QT z>r*C^CLA|;B$Xgj6ZOv5#3@Yg7JxWkaNC*4O4JEwxxEg~B($+Fv!m_$uuS;R8R7Xx zp`$%VvO3|JrY8Ft*+Q>~%GyTcU&kC|y<ly-Xy?Ic zVwk)?kgim&?kI3xTGAHUq!@dNOh3o-sr6xjot}F#WCbdzqn{)|I2hXtSZp!Ql~8c& zrFdorfuJMDJP6=9+kl<^%Zd;YP4;_{<6xOFMiUEYH_rg6&)g>SSc+mD>Ld>%p2iUJ zt9C)8vl{#Xuk=G%j;uFogtZ@csoyw{GCIN*j5puON7rg~IMmyv6MS0O#>d}#K509n zG+|ruPM)cSg@H~mrdSbnQxq@U%B5_VhT+V7`qpN9C>+!0JcXUV9`CH}WUic2CiCUG za$#Iwac(w56pXh2>ALJ>p0^YnS%7NGfDAJ`B?XA}D^x`Sm`&ZSH17Ggj@bN|lBa!? z9vjM#(@<7C!>c9X*G$v$2@P@7FW1~4G>k|N!q2#|Z0Y%U$&9$#UOKqD%3!#!&T#Rr z#YrVnDpA3uW_i%RX~}eC?GA$P-HU`H4Q8GUIkd4~s?S=;3asFUpbGY{8`&NPb`9w6FWY>-} zD0CG+0*D%v#Aaw4B=nv$Spj-qlNdTP;R16g5m6Xnzsb1TbJ7bSUi>n!A)?(^!f%^O zyt^QCg&P~oyddFt65Z75w>PRS>g=qcd5I))c31RcBP?rO`saiwLCvpMWgq-d!0T5p zfOTa@q{o-5u(VE7@Qxdr5xMof-Ba`rii=E zu5eb&$jN%T2maX=6Fv~uVlZTZ2P%i6ag^j5-KC6Xp}S~_vV%W{_T8q`g7`VDKgZ0j zz>HX)yDAfpTx}J9Q1;_910L#$Y~FKad-@z^P5T`q1buib4vQHc1ozCV8sOx3u`D-y-{eSx+swrq8W$6(mnaIWVT5;7 zJ6Mlz!f^Xh-$vy8J^yNp+41;Qm*-SMU2=KSiMWO=b2*7boDzuCaQjQlL!RU}4gG47a77VA!cVpXlU1v97$U`y`Q^O^!_%$8 zt2CC3-_=(og91&gBS<=zBS|5zy*cNZ_($gU^&~8unD(z6iqJXB@I$2WMci$u;&}T= zT0pM2Z6`N>GZAof8(2=S?VMkyZivoEY=sW6-jL=Hg*84z<1Am_egb-M{dW)n$Y1_W z{X`9C*aw zy&n-M;?z~-eRF1KKfD1%XlSs{5~jKdlGy?l&n)a_*Z6)5dhLEJr>dA}PN`?GixN*M z=P4Q)?4DS+&yrmybbM*CH=)fkHp_H!k*tT1 zlBI^EYr}MP+_szq!n@ErAFn)f-7F5%ZRok2y$5`+bzHG~uVBSJ175C9p8vXH6dw^* z$c}F>`%U_Zb93(;+ZWQ9sFpPSnTrSSbujS$CTiw+TeRB5>(($nO4(!qY7jfgTOtg0 z6lv&aaY>zG0-CfrsYt8W6E_D4E1wo~i+I)h=W>C!c98K}#gtILj-}Cp6~A62^+Hp5 zo|zF*GK9)u!OH;Br@SyB{bh)RcS4F|%=^qM&2{ktH2z`~+$bn`_8!oh0&54{M=y_q zLu>Zn-t098vUQWJG^g}r7{|b_Yc26i2ugc6*gAJj=GEa~N`)3Ihiim=J2>5N)OE}5 zSZ7+^AV^T5YYxoc}VR{uN{w(y?X6Bh&F>DbCq~d$4Q} zVImWBoL)}}9V~PaEfPmBcJNv&l+HAhAPW&@)soh-B-i2siJnoHVi`q=KkAS)o{*=8 zdR7ouN(*|v1%^elopo)4S*932c7tSw%oSqN3hST^FWCmfc$)V7$Z}F!^hH_Xd0X<$ z&NWzDzpnX&B)DKsXHjpD-=(&8;LzWqJQhPGVpEpaz#o;Qmin=_z@o|05|@W^zlzg} zuq$7mwGjgHEp(kMUOU(D@~ow&T^IbtwX>FsmsJ@T6K-D;b<)?^LF}&50HZ@#viQUe z=ltt;fk|1bI(NQIogk8t?blqW=Zvx#sO6WCC%GT zwpKp4VRAo5$4o7wpT96PolwH~{=>#=lE#8aeFe6f0OcCG>W7s2j0Q|I5ECda172Msm zkPzGhBxrE=!rci32=4Cg4wbia?(K7v)8};eeXrl|e&2idkEAH7*n8Ekwbz<+j4{Wg zpaxS>zWzjUU;cDn7@%|`&FU`cJNTFkPprnkos{yL=;yFEA{zy+nR^RK_nZ#)h68uZ zue?&%VF&VYA#yvAW3cPybybmZy6LbP(YpxTLai@PI*u*KGM`ex&7P8OFZ1>UZ??w1 z2kvEwBG;l1@kEbYVpNY9t4a)YpYS_<(=mIoelPi6{-@;7VmaZ@aQ>tx6PKL52Qr5` zA%>7BN5mv4x|rz9rz?kBm-3aWr?*y^64q~iX#`!yF?fY~X%1_X1A2qS<5vG2NH_D} z(jkQo{Y2&b4GI1?JmTsc!zSbc2I_%5wHk4O9+6N0Nk)of=&P?}vNlSOArF!_OYyA& zdU2NR+XSmDN5-aw=QF~j;!9Brw~M2YLtwudh1UkwYav)8kskjc97c ziivUz?;fYk6Xd?tgz#ZLmL%=jAiU9_-}Pb`nHqyZS|Wb_<6n+c;6~GoQB`4CQC|^9 z5w2UOjHb|~&^4~>%eFv?@Q_|3F;5E8*W4NOqF@^0%X4t~>N{u~4#<2K0rXQR6MFQL zOCz??Z>ui0u$s7`!X6~XCoTs$iPEebH2VQ4Tw25Cn@`mWa(2zQ$fQl??_vy;&Y{Ec z9B0~m(D3)c$7L(vhkLalU+SKw(BYwaU@!El@t=X|iK{nEDV+wsgWRgv(WR9q!uAVn zmqp*kO+({Sr~1$Y74sz@imw5R#+9T1lA4yYm8N)D9VCHwKCEP?hq-YKpU9-2 zYj@V+=||ef5_Cyq9gJMxL5kq3KaCFQ7#kkZs#_wpZLf%y#_d~jYAcG6-n>kC>26=` zU~oW{8czj6(oC2;f&^!l9u|dleKeMy(~wMuPFWenJzudGii5|a^9g_M3hyU6a(x9i zF{Go^#5XQf#-1hW$eD#4_(--Ps3@ASIQ{Vy#+MfeOo^C$u7j_FZ@S2+lNxNQ(o88Y zKd7OaWI(y@V@|d2B36qf&#snTpQoAMxj_=pn@hmQ#zhJ`W*mDO2a8p;p3a^W0UL+YsBm2|X>)Q0+iXb2raeFjWX?7UVOIqi?5sINtx<;)9~*TB{-w zTT%kwmF5xVrI61ijw-zF(G&B&F#LfbuTI0fPSm2gj^QiARmK~rp?_rQ%&jGveRq)q z(MHhX@F}0?t1o)Z`1YOFW{Ngte3Gq7pFkAM0>VO~61QAmg_ioa>3th6{XKK$X4`Gk zHL-H8$fwcq(rR)NpM`m(twpdAd>I&!OxR2-jotWG5MZ@M`3USh8AtS%CkfEwR z@M#}R2yM&@-CQ>Vl;>lOjoX{h?Km#myiSKp)TpEL_^3o7J>s`_lmFj%Gs`IKk(i^iW!|I~s(a%WV}HYHgVhvb zAb+IWb;RfF%kIVEu;nLA4im8cIu!;iq0!n4g$s9wMK{%41s&6U0=yLTZ%-QHn&#gL+Kg%TwM5?yhWuG2d;loQ#yBh z;>rHC)QEH=DiOgqB$_!{P59Ka{;LPjX_6*`(0JSYiVDQ%F`?167mZu&EPzit1R!81 zrG!qS=c_j1AKhR;u5Ke>x8wjPxeE|w8^=O7hmgzsuFT6 zD`o!XsA}FkN}teZ0k-Kf3r9;{O>=hMAb;_ad-wNlr36;-(R$_L%Ilw5ytRrTSas}2 zRkfDuoFof|HOCGN{?)nGVH8a{cUdNN?%KKxRy6k3p6o~r{GtO>xM{MG zxPFVc4X(^l7o;RVqOra{K!%0As;0?6aEqT*i5iY5GvHnVVfGXmM!gluAJa)h}9 zN<}y8J5S6zxE-V4ZbdW&VBjcBOQyTVJ}Br^7TzhJC~*dVrWh*$PWTT@<oA)WI(liE!`x19Vr92T0lI!1`M*_h{ORK# zgOiy;8GE2_AQ8|v5RmX}QFnqYhyDRQ`3LF}4!4!wn(|qz5*2w{8G8}$_JL%1ZM^1a z!DA{@BbyD*_Uq%)zLZ6SaJ-UYt-O)dap`Ax)*TObB9 z{NFJg{qJ@7m*)csSC|KN?hYBLIUnPT{dJ>Q%y^s4N1$U_9HI-JSuJ;Fc#5O2#Mn;#8tndmQ1 zfD>-nZeW@E$tme}Hgv4{vJkS32;6VLoe|s(`wYG!Dt9rs_~3OSR|s*u>zF71w(k(b zKT*BqZcitMak+S`Bth_4e6BxkEr@4>A1-*N*d0bse(eKUH4|Dc`wq&*hlyuzf>k*# zf>fl%@GnTw?Wdc8Gyo8ARF~Z0J^lSO86h$g`;~XR-$8FI*~N_47c~jFNOvNZ$>qkO zSu$^|WTj0V_Y(qN z>zb|37ASZlKk6Z1jviN(r(#rBMylI57oEY zu-}f75xfMORym?RZwuG1qNN=v0aBk}4<7g8NevCt>5c>~8y=>p!bC%D{}(YNQ8n;9 zOJ&^@LyUOdm2U4Yn$Th6)#f3|$TzQc+u4z%9-n0M2PWH}u&nx1jxJY}FgHBQcPVE^ zBjpkwonINKuSXDj_THq8$>244()%u141AJt!|Jv)Yh&Enari5zIL_84V9OI6A$0!F z%TppiFa6?>u`8^2dY)8;uyD6?vf5h%C+1NP$w7=Onm9{jhQQVo_y7>M;5*$kFGdLk zH*o1P9sqjuIL0RfOAJ;9nkHV|#IN9#pAtKbGr;k�(Z0%Plj5W-h_1*e*txyLWVF z(bAZ^m$p>iv8>{srd?E57ng{j%z|Wt?uBNDu(t>e7$?L9M$}=*RhaRss9t92@PZj0zk%qmIP2R%fIIBxTYJ&mN@vJY*@@i_s-6 zZ_g8;H-9t4f!fm`L{azNyq|TSXFY1Ps{%bV`XSOTHc6y_%b;5k=Ls0tdS$FH9~HyE zVa+PKO?iunGH(>1))+Gqj!Qjb%TKznCNS`3&-s#FuDp!NHL7)&h0x782ldG!z53m= zAr^gTRYSYcT>8m7(Wud^_E86KQtwU46zmX%jry8eXRCki#l2xe@hI*;IUT@265fX^ z?6dYyurU|f!>=4wnGlm<;;1QCdC=Q&)o#npzd~Ll+t55=4Cz`JAIk#Z^PSUL>ldT^ znAYd0Mf5k6ubZ2o;#Fm=-PVuQZMK^fQ&353DX?vL7gZJl9J|K%iv2rFrkD%&iKe$F zrPdK_eNimXdzA{{eOkBFcp<(V^ys25KJ2K(<0S|rIhD@zzwJhNsv0Z#0kn$*_qfUr zsKqgEpXL}yb}s_!G|+gyIvv2nW5^>)Pe+U7nXct`hWE>rPUCd$PGS09%V1d)t{@tbDZeHNOIMK915m$b^dmVcp zB_-`L{qJVN<*aH3^(2t9jQ_++MtLNasy2!(g0-xlqj9$CBD)RC^pU#1iBXl2k;Rut z6x{(ia3T+K(uuot+|t=IeOGG)mM&bqgatEWcxv$5l`1Z5*YlzTdUe%x8FqtQjeY^& z;HSm*Hb3D`@IP8hMK%XPcBxXYrL1)Kz;oKX- zc2O8jI8DX`;zDX5E{uk3Q8&8sLb~@00O6VD!5v*(BT4xOx-r{?y6Wu+dhQ~{Fhn{l z0PM&B@<1z>4A}cd;AC(`LYMvIGbzBvkX9lO;6~KRD3UFLoZtpHp%Pz}qyQDlt9MC2|!oXtik=N54dYy%8`9FEeMhs<&xDcSix zGcK5rqB>d`-O|)oS&Hy(Q1;na;xh9Uo+J4BB=I{)n0@bJ#-2e<)*b@jxk;(zINWdfSJbUh+z6*%3hsy-VmLsm=H-V^? zBOaJGJ26M|MJqG(s8a0xf&+-AzOT;X8EtMOadgwQ43eBz!#}`no~rWbJ1@8AXnZP5>)7@RbcHy=d`dHS7N4Sb(#rrJ5Z{+`$22Kq6q>?K$-<=p;Wy9s)pIb7r8_ z@Eg*0?bc7%xmi(d7t6=CkRumb)FhnQ>6S6LfN3%@PT4$lOmONPWa-u zR~|-*yTQV=DPq#oBTH%eZo6Fr9chAZp>CL9vl`+Kr$SxdLAm-Msr&2~2gId&H7IJv zq$mAK2Fv??S)rMS+S3wVM>?jQ)m&!z8iUd%diu?_rjG`w7ebL{Sz;zQCYhYVI`F!w z&{UZJcvZ=NxuR#v^s+e}9nl(z>bUVGkq(>9JLf>k@`|#A>4>R*rO%oy(UTKT<+->_ zQDKoizL)IgD3g1NV0JyXm4}#Z+Di`+eN#*38H@9ehE&x+VVmmb+ri-q!jT0tJPijy z%d@q{LW32L<9xI`sm$uS>INU<%9LkIR?#n)KER$-Kne635-yZ##M~>K*&htB>VoR+8z$q>O~%Ej~aJAuo@1EhzBxUjMo>E>^t-Vn<-b(U`h0;08QiV-Tt?Er@@5yR-2Dz}1&?YCa?bDtIck;Luo6D06V&GV3Z6c|W_t89m^7v1pKlAz4s4$b$Bk!WV7m zp#&t^Jndh=Q%oJf4Z?e0vid>#3oZp>Bi2;V`o`mp2;!Jt`%rHQ3jH)(@ULY$Lx3*0 zXJuLL1_&00jOvJXl1$#1F)`ND)@{eYRA<-T707TVyxOz4=B!V;_=g2Q6Qb(Qf=@;m zISfW4PK)F%JTa{mkHm7Ip+AZ-%B}MrHF-kw@K>I5E8zrY@wFqK@TPC7!MP)5IU9y zgyi7cz}lY7E>w{%4K~t@9FKEsOx9<$F8d zL1MwV;{M{x=_3{H#X-$$+CfPLA~e%xTNc;Q`ebw*1+4)2KR_UVrsRhEHAJvWAp(~8 z7;PZpX&#+W{hi(+ss1|@)}HLAAY!BwmM1ia1KR$Rxy<4q1dvYgur?rD%#1r*-2yPG zx{^D8>*mvZjk9DtP8rn>2HSv9tN_@(7NM-Sa)({LntcUmDhzlQ<@B7KFi;&SeV`aS@bo0?7@-N~S#mLyAL_|cm$PwsQg?Cb zoRu{^-5gSBSfg93$7}*DD*Q?3La}%Y7|_0+uW?O`V;i9)ctLvv@LN&nZU^icmU?@e z&0i14r30Iy!|uRWB$(&80g+LNNpzfteU48pR!B-MQn*(S>BW@j{NX`paN5?l^hIne z5tq`A9zAI>8_+8sihDx#JzwCDaOrMYD~t`mk9G`W-h-xBoi{FU>Dkjr(X}SZG_^cp?d$KY5TaA^TO94#eA!PDZJFv_z7u9thsowem zuwrR!04%msn3x*}`sY*~;q=0-pC+uX6Nr-Vpf>bE8o+jE3e1Qy$Yy8J1JIA=!!iZY zHmq(5eMiW*etG~%HY0cUG`!NBz5|))chvG50-NcC?OdN@)_hTB%){Ys20;ti7Ja90 zy`pd7BHOtMam4h-kE^os!KfjDD|F;&Wegx0oZmrb{g7Cd zG0Uum;Q6_SP&u10mRTe$*?mtDI(+z>v4%R1=v-wfVR+E}g@{|X_?st#Hx-b@m#IMM zmA&AT;o{2Vr&Ahp?Pgs{PSI*;84p@ZL5};#JX@)`qr%G^*sK+cR&>wrANa&X3_zR9 zfq=c93x)uE{hbPTQO0*u&4*9qV07MWJ5N?bnQdvO_E)Q+HGIXNMJ@*IaxU3!)pmC6 z%yVEp6|mifODtdy$CWr2OT91xc9tNa%Y0CGG&$2e0i%;>m1GD%GtsrleT4kA~P_UCPb3l>W-TvlX{7Zk=7 z>A_d0@fUj$0H}|-Xg+N68N*!y*zDRnQqO_yG`-(}qmOk*!#c>(yk3TQuT=Yr54G&6<;ZsjYmvJ9A}LsIppWk64JW&?KU0sY?=p8 zcszy_xFkqJqY)}oxK~^ou5eexFdn#4xY|9cS(<#W-A#&U_LH(7=ck`>{n}*qCt!%= zCmd=YnIeFoE&d91sfb>&JZ^nQ`R2*2G!EW&Tsd2D&j;_0^1Lq$F5M({ZWAI}7w64^ zz(i32s-NFMmLz_8rgS()To1r~fU;jtE!b2Ym`L7zx8d(=_rNd-a`f+@nF(0PFQd>_ z)fjD%&YYXuT+s6!8JPVJGLvF!e9jG&?w=Hy48`*BNEK*+&4hX<#En(*6BL4-8@&4V z8-npv-IANb&Ni*i_Fk;Wjxg%hY3idl5r4(rS5%?sK=&h{xQbhL#0Idq&*37I9vZ7H|r&fZSWpeU$i)6Lkicvn@ z!+$l5*8O^fp)j;k;+f9Hko7ej$&SQs1%906=*6-ClXPDgqH|?zj2wxgdVNaYjwjMa%K{QD$zJne*?(qWNIG&pARp)UkL^h4l zm{r!b@;YMRx-1MQCUNm^Qhg42n#;;#*-@N%c`i=o=909MtDeKfXO6v4X$BVPJ1(^6 z&v_8*o#J@~<6YfJ_r?>A1x8KurPh4Z$51G8^;qE$R^1Z{OqakIle~>7epxf+WrokE zy54c3^t9~wN_-n0UzmU#e{%z0@4<{@%ko`<4_d}ArUe?Iyp=;iaVST)SmvIxU zr>f3e-}(=MuK_TG$I^P4sRV%COf{SQtqq;6&8dJz&?3RI8ZGKRv96jEZ)g;(lx3zz zBU&zSI<_edBMCviFNyT-;x3&V-B&ogO*c z6~+uO#(3l}xUlInVA{BiqA!u7^E(|i2ROt@zkT_@BI5}|a<|FM@v(ik8-8j$urz?k zrXiY;)|&w)>)`64#4b5ZO{h)QZd6QeDN|K3?lFH1G-(wr)s8;>2s6l$@9|RiP~q-A zzDljyNA0giORrzAAS#!7>C^~*+@LhsBw|6sh)KpMKOcfnPu< zxtBGm>?HcWhyNb3tlC+@n_GqGdDRNfM@|{%omJsav*XmJG_aoQ>HDX0b5CQ{lG^q= zg)QCTe#FkCmoB zF+$(k)KaZvOXV65y-fsHk0Xpo*y3PXZN9Te;G|e;MdqfY@WrIf<<7os_zohTIYoql zvtV~}jO9l;Az6pveva(N_h}ldOiTL95o?0gU$}~{O=C!JfF5GW9T`E9!#qT*)|qKG z(_M1a7!Rc(&)%Mlc@$bLBxi=r@ZD{n`ebgU_YyzOnMRc))OgAtd%ObN$pxYJFeyo& z!oG}nR7Knfj_Avs$APJBj0QZ~ST2s?<|f!j#$k~B?;zTXYripw4rIOQK=cDqO4f46 zghN*~k!NG%GqQplGez=+aHoj5Y^S3dgJLfo*RG3qXX=%M_f2`T+Wb?t$9W9kvzK|g ztIR4Vd>wcg_7_Xb10>y{EQ9vhGo5Gy?{0g+y4(Uc*ALB|rss+I)QXB$)E4~_Y|~Gb z;X#;f(L?5I*9)gNJ_i>`gFl%iPW+4sJNzvRgzIzpd#7+!mcO@C6vp@ooc&wq49^V6 z(;~xxC>UG-q;-dYL}3ejj5Q&&a|St0AsYRR)+oZ1-2}zb{5sT05%sYgWe~Z9?*e0T zg*L(IV>L!K+nk1!wJi&x-v`QUkYb@7Xx}!~%I{V1#B`I6CgF_`Bw>TaG!rmV@o=&z zR)-C&FR62NC>6_Z_<7$aKyV!7uPAodxm^1s++3$_tismG`*P_8$VElim0)9M&?_!@ zV#mI57pUaY7b*}RuZNYu-tq#;QLn@A-V=J4zvM^xf6R}R{=}jT2l$=w4)_>d=xm(% zj-WD4{d(foPwvh!c{csm{1-X(Ft)`ZzxU^EPDK_|8oX$fq9swFrdh$JhUF z|0gf|v>$|{N|Hd9T;$RXhJC9(X(*}Ky_&N9c(p0{74$K6*I)~ z6k{4=rW{pahO_Ho8Wr`S%EjXc8P)n}>9q&HzFXp!0!9LSDrcBP3_z#mtpQ*Fd-Eag zchDEye(;ql3;_`KJo=}9ml2P7I}B_<03ty}G6qzSLKfwK(3zKrJ_P{8$N>u+3}9zC zh8!uUT$3fIUv>+_2CI)f7NFKwQx$=i+j4pNVMJ_op~<`Red*07f*rj@YU;go6VlFO zGi8%QKkmz4ePR9_nIQSu0``AoRr~X4>7fkx2n7o5QUfkQS+*);dM<@R=TCS=*_)L2 zk_t;Zh6P7!!#?`UOSSpBkmkZ$1$O{ftw0tKA$kI!BEkja)-2-k74+ch0=Tw^a?amD zUH_(c$^09S_1_uSz4HP~j=6VH!t&A|4Cf`a3Xod6hYJWfZXw;ppMb&^z%2L>vGk#BJyvT}&_l&sJzMx!5T(l_Y zq<$8xyLRC{Rj~!umXQK%%u%v{O&K7WyDy#$u=dx@u=~ZpQOB77>kL24Dp!=?WDyy& zx;`6x6ehpucRl}p^y-ZC}zQMv}@FUNr)b)fz{I!-zZpre) zd=UH%(MrzUWe&vDwE1MDL+FyG1~?!NBeH$iD0?b)D_NScG5TFUbixdPv@&4^bh_Fd zURMMqpX%3`SSGR5k2bv+Z(iavTf1@KmzM_4WgXK|mDPWGolkxdQdy^4ks=_G_J?Et z;VGj~amS1_8N_+%0G}e5?->*0-t_v>lw}gWxNC^S<9jZC=s9T&0`liO9Q}eYDX8>j zI@dwYYl8&Dr(w@n%B|!(m=85O$oRWoWW7HF5C@H< z`HJj$ut{75h7V&_uXbZgaMwC+0=6jn>ht5|MBCZSs1p*rClwqJ%$*n)XNe&8PD@!- ze4mv5&uR)Ene?Lxk-7pGjjbuI;gRYgdyHH#H`et~+q~h>df;xG>4Lihk$v{1_1FJ08~pstoaQUv{8ICiBb!pBG!?INT8GV zlN2d$ER|0SA#F+<5;}qf6}Io^tB|3ZZQxj#e|^rU_mYEmqxYZh_r`$gXUpLA$TBzb zIP7Xmu+)lRK}8f${6_`rSZfDw=QTX%udd&4_<3drTAtRdS5|785+cTajwGy^F62!9 zyn50-?#&xa|LN#8rgOR)Y6wk=HT1=?1PMCR>_f0OCPB|dVVGhsY(l**uD8p{_r9up zNMGR6?5?=Tf%mQZH{#?y-1UR>#sYRl(`wdPQYOGwl)`ArPAyv0=N&~-v}A$(G+502 zS>uS;oX1J)T0eC`Z<7iRX?PA+EML%|hST`M_&Ms9eQn$_0jKMT1o_9MNA7U75yEVv zH%hS~5MUu>k6^n4#|wTvJ$YVp>$HDojwxMM20Fy!q~l8s=I&-Bpi07wk^Cs>8a z+*vpKH37xn0^xr*9=r)jmw~N7=vs%UCf@txSX7O?x{G5lS~>~KxC>sW`wJEkrD5

x_ScFgq01UHo944uiKSK$sAiUsn?RdAO1b8Y9<~z^xnZ9+Lagh?~;M5Ur&~ zzn6tix%63;7nAS)zFOkz(a%91Kmqqsh7_JPbyba6*wjgickZB-%V*RS<3OQ}2>@>U z0dNNM|1wy=4o=G@l_TtKo(fIz`l-_U4-gqcA5FlgaUjMA@6twnZdM&;>IfpJ8l?`> z?z`*H(vGd@0g8}9hMs6Eyd zKDH#QZY!t^VAwn33iE2t>Rgpx?Qc5fI9}aYwMZfMYu)hM62|yP*Cab9@N}&<8nv%p zlLvjOvRb_uSEgN8t`~#V%jP-T_1KQUi#~aEjo#z=H9dQh_k_xA+^uvrF8tvFnb^iJ~{ib*Q!x#JX*J1u99sUQG>Gto>{bB;QAcS=9} z%1?Y6v~db}M)Cs$gH`i2!-S}oh1>d%&>F}PYJt!i$PfrC0&L4^F) zhZc|qXrCR9!cYx3)C6MF)SW8TPrM)=@4%GtAsV~?JLq0c6 z-wdTL^08OqXOGC#jO=RgIX>*S`u2!hbiHaElyvJ|El!b?QaL#Ru*LuIm~!_6tzi9k zU!@<3(A$?Z{=H`R7pu*b>-8V$5|C%q0O=BtXAs(cyxc}kE6UX^cpcc3-*{JPws8I<#P|zK>{yMzqnX!v6RenPj?~q`>Geh*O*kh)0 z_5kL{jzc?_Ej1v3FX3mm(D|~*lv!n>0!LEk-yXPvR*1{?c#<{b!uCSUMnW3g2g96q zYV^7Qz{RW;FtL`)8?_P36{vI|Q&BOMMS%gY#iaBG$|pVbk8j~pi{_lQ$N0GxHxHPi zdk<8jmaFek3~64K*9f~Zv?3j7B{>b^>mSC2#)vXRYH59WAWg)vwmN}8<&6xU=QDVi z;WtwK1`sZ^v1O8@r(#N(7!8MdsYdaaF!v?-)CTE>&)(J$bRm)o0WtHcV7Auve$moZ zTJ<;{smAhIo4RP`^hX0d+yt36^;e4^4CnBgP9WX!kI(8Ix1BOg=scZpDw`9J8&9k% z;G-egxL^5UwG2M|ei70kjrVsDTe~||>)80x8GYQR2k+r6vSqfP@3l~nBsAw-T1yUR zhiej3`>#MXsoPoZ;Zpl9COJ}Vai9nJq2v<@!eW{LdFiy+N+AL z*^!Jx@_@AWD2u+w4V@At|WReWbNj~=B!6Vih zlH3znuIdh1syzg-j-Wk8CPe6SX^!R;T#qwhNgH@<+_Ekk+exK>78sfFhs0-2(zFS> z`1UBVx1BNcWOw<}xwIyP2cx6s^SDF1Q2Ktn@zM62xvM6Fd*X&*Ha=e@DvH(Q0`L1< ziU&Otim|mZTh}Cjj3D?7f+n{VB7K$K6udsJ8K$@`SykshRU1izLw7)R=%swNo}1H= ztif(-Rrp!5JMhU!L(Se=v~smeL+f!KRWB>h*{ng;G~30A&*b#e8KKI}n-RU=WbDS(Kb6EQFs?V>deH4*hF;r-r;KG(bH(41A5-dp zg)TAAcxt>TKc3#1E7lH|&{mX>hGo8($3jbU5?A%GuVb+r5PrbwvNEAKp*+fXYl-MT zS|N~9pf{m%C`ZH)7cH*DZ;&G|>i314&Xr;;WC39l|Af6_dX^!~$y&PIonK;*?vcyW z6=XA?y}`UZh6dhmE@5Zxi6gdanyAuGgR9;~P*iOg=~I@W#&O?dglF~w?at&*V0GwM z5RLDk__NWu|BN$#^~U{wr|ZJ6ux;TlEpa~l4J-bC{P+<$p?A!KC(FEIMk;Tbad0Y# zr630SD0J09fN#7K2QJmw)Y>#%yVDZErmIvCkK+Myuls{ikIe4X+skOeQkByw*oUO&*c-ME$2RIARn`NZ9?4_~x zc2H1Y!wJYD!_R&jYdhzuX~4IpzQs>So}DPdO>Qi1Ier;U@M*>)u%zmB9LaME{rP-T zFXYr$<5nER?){uRr2AA70k4nOqOy!A^y6ie1- zaX?)9q%SWl-|ysUABrRJZ7lHs$sAvUb&JKt_bKBOqlbZe*>$AZTPxTgAZJL zQ&>j+`a_`GTcOH?zq(l((VBG~GRu;VU^1}f&5T+SpB3YG-Sj%r9hB3lmm2Ac&lWWz z|BAJ-K2yy@b$V-he(hiRwMpsq&3RnAcwb9*E?Iifn`RLz-{7a2&;OQt{{EO}j{hAr zr9lnLSaWSQsE&p(JI&oFRk8Vnt`yT_@hdG%5PQWo2q#8pGAJz5Fx4Q zIztaV?a3KuRC`oc2MAt${wc(ZJE-O2rvRI5967zi-%B-^YLcsDfVetipj^Y0eilg# zooU3$Oo4BPG;hBOR>=dAJeZ=L zj+3jaj{tcJ@d_3w_80I$+?cIDdKx7UJKv-N9*uw|bA9PwFy;U6*KquY{1W%;pD=pz z@VS4YO#3oSg_*b0%Ug8pcXq>$d_7*NX979K|7V?c{uSBsKY9=M0?}oL(&5?MM_=md z5gkIqy3y5<^@i|!AKS`b_9~I2evIbc8VzEEQJ5B%0Spzk4)KRdlf_WZW8IU6QQ~sF zsW{{Vr!JQwPyKccqq>=r;jIe7pg7_$Y3dKpRMqB0!y7o=64Fyp%j5`!0^yXplB%#Y z+ujQ?+_P)-+404Biv~9y-3Szh_mH36dC^b_;p|nSI7~r{Fpkfdt>R|Pw5Jag^^FM? zp0(?G?d%G;A8IY&H*nH4hN-NJnByGpho$M$#$2?B(46s;SSurwkbRl~Qlm%hYs8L~ zBda+Cf6`Q>~M@UxaozOC8s%M^v-nCASIaT$GuMNwjWxaYQ%9<9TUWS{( zlx3ZAo<-(dDbG{eui4Zz?xOpda%vm=*XOlA($UdpBlk*KcIOfld|A9h;;XFFBzave z$_}Z1 zpEjl3sMUoC$%qt*3En8r+j1 ztG1UA0vU~RhGy5gc|pCq$@KY|G9EL}dygg*KJV2f8(w36RRQ-SA+^dO4-vX4^~4>% zL?6SC3wK8cn?*u*w#o;DhHtUE!dmHraN-%1`w{??|x%C?^HBJVWf!DbzLpO&eU z(X@oWu4e@gM!poHj~-#I5D#K4|InQm`Nkd4+{OZ^jeq|$S&17|4Cw*4gU_)ccT_b+ zbsZBztISI!H}{2L(OU9Ib2xv_x&6+U|MWUR6a5il#Cs0```m>J6eSBd+c^CeczzXT ze-G!SzGl>|W9j^9^|}{P?5g&evJY~ReO<}UM$CCVv-2`%r*&FlS~l&%_Id=n@?GR) zp(7rQ*{z0FkzJN6cKN(z@=}7?-aP&0%h>@L+mV``R2u%!sD0PnVr($O1_1?mcgd25 z{AKgYBeJBv>;saNR(fCK#c88gD8@t7K5sM1Ct_*qE%gz`wRbx`mxp} zmc`@Bk+VHw>0|1XrRcVOlu$c;QwzHsib&CWm^rVuD~aPPMy!}9l}#x_%L^Q6OE0dS z3l)mzuVmYMtSbuoSf1D6E7P~Um=bRlu%BE(sxxUT%-9!TGE^+oJtD-Ky|iRrX|xXX zmG*uhIp}HhGWS*TJBzl6_{)1KQUkK4-Y!h^_Y3#<_03I5&P|QEVj)%@EuWv-5nwf& z%tRuIoNGC1q~uOJu9e#O4n<8nQ>=mL;K-(Q6N=1>Uz0s{hkpj)qDR1%?5q3$a`Kz1 z6<|{(w_47ux^ieg7<|#8a*KJi6ey@ zkVUp?P+lPfOn54WK947f?ijDq{o%R0YOZWXMclmFcJ^*j{Pe086 z`ANNU1`scGcv0D&#Ut{iqgmK=cPaBnsF7}wNN$dqLtfOE*6I#{+KEyNKBPTUFnLev4#E&2D{!d1WHLA#_L?Bm5A!fqym~ z|KadJ{(CbfarzbTQUokI^!Wn(Sv>4RTdj;{S5W3WZP?+IWMZtuX$AI8RIF!p@;L6)UjWsaAqh|2i}l)$MRJb6Te5$54Djsw<>p#xkrj+G~?>*%8>T3-=SCS z3EC6%{0xwBm8=xic;%bQQ)-=Q|6gnz=+lbbRRI-BcRS=9xOnNE*8Z0Zmxh2Et%5|Z zr4d;8vM2;uMpQff+Pmme`AZ}Ah*iH}e_(Z0A8_6!uG3%OS0-qBymgRw7kj$*>ZuTv zY6S0SoSC}#A+~A&6B~3f_Fk?~I|@<%I&8d-XvK_t`o)b$lYFYzqSxTM1vfZmf^QVhGz6>$L(!HG`5SIICa{&5OyHeb);xP#tmysZa<0 z^LDbtyy?62FD0K%SHj+v(IZl!%njJNJ-olCNk(>rm>T3T(Of3|&fhp1O-o{}X;m+0 zjXzvM)NdQnE(QD2lGfj9&+5sjh4l3F7pv?E*<+%`G6as+6U@YF63qA#jrqfX0Be2@ zT}M;L+*UW5y0|qB`ZpNkQ6Z%~QOB$9d6Hm96YRcp- zOVe1PweCc*f1#jP#<|+tP}g84s-CD!3{f=DizT-cjmX>Q;cCm;ipS#@_}}IR*ERc@ zrx8pxv2L%{U_b^17amZq$qb-#wde;IK#F!V5b4q_qL!VqqFh>48Lk|}WYp*_!D4{H z8M$#OYct8cLC~5Xb-5!Y$jD1l?W8~z7pXO^RXGjkU}yxVPu_VU(nHG^fIGO|1V3uY z;f@-CSy}#gT;=e6HJNgfx%sM3DQ`Rp22QAPHliS=KZ~Yjp#E6+5MmOTqx9yRtP$fy z&8%7|1T!zY$Z-aSd=+%|qkcYWD&pbh`~B^2=0vWwQ1R$>a%lFYveyasfD&40%y4>Y zrx!^j9TUeL9d>`2M_0?we(?SD4@s=%Y*)5;$&ALRdoU%wE864IeK9a&JXM6 zJBYr(DfCfz?Rsjl2lI_r7*b58S=koei?PL8-}$jXm_Ju=$!>px*I`l>;_Ab$ZvHDstGBfqtCYy(S$q_y4_*rM@Ceb^AMB|edI;8W zUW*m2mm$Q}sbIq)M#NBxKZ#~wv*xjoO7cdMm|IUAv1Yz}q6q->fXycPBNHyX3DxK3 zZWg5)`g^QdvlakW*Cf&g<4D90XAj~C3DI}gt8-9^(kjk4haM+2g!_nWjqz?o+XlCU zEP1q{@ZXu?)t38Cqtb@A>(RB+oUvw~tYh0?Jh*u~S{KkBGAE&3HIX@?8=+jq!f(Wf zO~Di`*#Xrt{)!SAUhhMQ9&K7QVGbh&D$zQ4*~*~fr-?UPyB25C^da>gSKmZ!BB)%r z`96?@yR4U5c{n4+B^H`hY@G-u>$+4a2-Fw!+1$huqu78jX1tCDFlAYR?e$W8rTw~c zZD_PzLzdXkzfPJ2tAfYLrd*l=O$vsdQ9|~qy^X8-nyF%GCwjbUL;1$CXdO?4jy>J3 zUi2P{Wv_jBhf(y_og+A_y}4u)@Lzbbvy2gD>B*R%H40Ptc%2qUrTCshzSH%s^PVAh z*Yoy-8h-uE!gJeM$?>u|({6=FvpA9~fj9(CjICco_9hZ~M+Hfzw6x`@-z|4NgYMK* zJ`8Q{=Rx=qJy&+&rVo1iAb4S^L*sSn>?Xd7oAS1)Ob+yLYbV}L{^~0{T6K>L&syD) zFEb!#2P)6J$tTtT9nNUoQS1jh(+f^T^=%@7{vK$;_4u9v-f=a`18)(8$oq4VYPP{! z=05Rl37Hx+QA>{D_jkvS`9caV^^cVmxv<|ByxKpmFJT;6r&?+Dl#_<&fDgq+|A151 z{^A4pJC5}S)BY6ZGbz|+v3_^+F>^N{Dn`9csB>u^qrFN0(;kUPOaVXY@34ROuq*i0 zG(uAeu4_kQy(Gsa#ob-cs48xrfFkfEftdZ{82vJm-K*!G&w1^Y9=(}JFCXC`eQ~42 zYg6T)U0WJHf_U+8k5#h1)JqE`;G$-LzC=b&=7h)ry-5r%Q`5K)F3G+cC__2pNI4h8 zjXo!y7%H6JM^Aq?kQg6fEmKrMNm};ehx6Paa>>~pL??5aq5A!Tih1HzaRT3$I7&Kk z{z_6DONB^*W6z!7Zw+sXrP5`n*VFi|pQz;|=XP2VAtfzki#&Xw*D7CMJ4?Xzg1#0S z^KztPxwoJ3-7%rj!zotRaJLFwSK84Lsc(Vu7J82ycmHn zw?i7p!Kr7*G{bvV7FM*r8``Og)L3m=neGd1lBg{W z2fX`_XLros>Y;f`Diang{EVWS`nUyW{8S1KbS@J*0Mr)VfasImyHQLj1+W0n+e*?HP~<0Q~O$s>sy)A8Tcr**YH| zzA9lpnATvW<;S4TyuP2aYz0WB&|EJrbpI?=UN~mi7Cmcfj0TwlNXhRBt~V2^RrVT^ z)y4+llI0)q{s6g;G?qU`tPLPg06IqNAnHgHQ7|F!@X=A;MdnmP#16J3b~{S~M{r;Dx0v{F66a`PpF~RqIQcE+$#Z9JO$OR&+*0 zuf#pQvZfozVaDe;fhEGsB=k)lbHNNn0L{*4^o(lT(9lvhvEziBn89XS!|V=CGd*WC z!O7w^9)wn4)79mjyz1MKERl;DZ;lVTldBJ$H&V3gQ1ND@*IMh;Y%GkzF$D!qsmJIE zUuUisFjxoEQmF#SZffd3(+`1+|ELA|$6u7>>O(}vU5VQ_v+IdTAnoD~H`aQwy+;{! zcDsq_1RR2JM6Z;>Zq3^+0?T#zjsXY51vclS8j);)PE=cTAv}Or@T>EyE8g{NdVIEn z@j1cB*UDY%#@w$XNhz1{6NRz3yJ5g%83d9rpDzKnblBf^e<#F9|1JfQ-4hHX67{bD ziH=ptJ^-djNx2dRfW=>~(Dc{s-?=Y;lY9`gNjU-LR60P?!Oj4_v4H?s-MylvBGLfR zp@dLd0Sp6JZ$-cT%oCWC`&FC|lv+*EOo2t~>y#edi86`)`g=7?j=(`VdeUZQZtF@< z9kV~L2%sj*bcmVB?brlaCPk-A$|=^)6i72N4Af4_t3gSnWc1P}sIh+c0lT(jmm)^t<`?k|sHI(?azNGj}h zmU=FZUIcFz{0a=PzzBo_M19NOP{4uR!0T+MfY=*ApaawQPpIzRdcxgI$}M&RFb1dM zXfrb-@cQ^~szfiz`2WQFXydIeEa8V-RzP+8PlJ|AX`Y4spNwZCz_pa-Fx0GZt_E1O zbu|J->|^PrjZ2gx@H#sH1t>BTd!r z4Ww0*jsc9EJT7f>A&1cuvzOzVmNdPQ(`(Zlg|4Nwe(g4q_mgdHxlEC>#uK1GB_Z+n zpl@-blh>Y5dnjI}hRUr7EiyXBqw@kP!FBIzD0}N z^Ro-m9=SZoGU_q+9`(?<)t0pGZzwC1boe(UioyGhE5laT>kHkvrlQB}W+`V|BnZ!+ zCf$l?22~wkpnYnH0 z=UWlz=u1xcV6hS(3yhlK>M3{DN_VJW@u3QoW&OP$=ig1+sv<&hzJEBstE=x#T-je) zJE#p!8yt-Sk1UTZ4eRYc{-!`6A9L07nUc7}AeqZ`Z2HHj{hcbD#Ej(paH=9CUp2FU zzJ;YG%4$xW41+=%Og3O)*Z6Ysel7ggP4vzQ7$c>4wevN3J{5i};~hIDPS%fM&X%MR zegG06V*huIu>O6UtpC$niLK6<71$Q`_$QuOp)YGM3z7oAzCljQXmm}Uo%|8=YT z@EK|NPh|V@pLUwRYZw1l$ad+zyX04G^RBN-!Ua8^cB?XmI;)<;Xp@nE!kA%p_YR=w6b6<7SxaO(;sL9MK&&0DLsp#(AY> z#N1yI()DV2ZIA0bisii#YWcgDURc=FNE;Ql2Zt9r#vVFQ{i7F%QN)NQKl>CvO7UYj zbKlJBZIaENMtPY3v4oq8Q|>|+SCaOMYI#{mY^RjFuj3U;EGU_uh&sBjps|SkQq)Nz z4H)XfZgK0Uhuv+K<}3|}qEGhu_Uym9nZ4EcL`edUc*Es0>J62X886@a&^o`RVdel` z7kQ_7QeK)!Nib^UKuJB;y1`4*7Be@ zUQYI@Gv*u}9SE~T@hgzTG0Ns-lPH@@X4KMtE`koa7T^Aq-+Rg7O$1_s@`H5jD%wm) z+{S@d*is+;9bA8675BD(Lv0*(nwP{kZy%kaTyw)C33?1M^r{AAX&J?JL!^=%!%z)lOVh7poM3JaVg+Iq(c*un5tXu1!Ij7P!(K zt|MLfy!DE+%aWY$-4sjd16exG)#1I3OHJwt-A00j>hZnBiPT|K?kg@*NVu|Gtt-K7_`Zf8ZpyuR-d92 zVQX$4a&nsZ_Mb{6=@dJl#W!^yc%R_1IyK7QC-;IbkN{q|EK_ zI^M8jdbHtF;%fUkw6gIm?@qLr9;jbS*|?%AK2i*R8)@TmQw=0z%QUZ)+S(Trgy7Cz z$;oFX+GFTJnFHS%lEy}@*{*0S)J^US6{7|(+IbD6^0wgmUASde^XqRZEkDj>3Yuzt zA)Q#{Lo$29fqQt?(I=a2s*#MJ&?>Yy;cvfD(*V{akiw;nNQq=;e3@!=JWMS3+#1we zx7MhCiKX;?rF8um;C`Ro? z^9v`G#OJ zKY8mMMe>cVJoo)rEwLkz926YKyY+k*SoAsPSLWI_b6oM^_e(bqV!DY88} zp29G09~&6OHW4|}R{yxt#XvGRj;|INDY&->EW+5}hd`>KIpmk^T5_h>|4t(#%KaI) zZQ@J`f&06%rdnbYqz<&R;JyEVROx?!FNmbmUbj533-IdEy`7+LMAe>c#ymasSBb(; z!ZTL&GMzR?vUAI}Dr0G&C-3IYt6ve^wpxkTp%l@0)KH#it63{8Xo!z)MCpx&Hc(ac z7HiJPbQb5w+xIifdU~^=d>W0RL#1`1I%YO(xzLEMWg#IsK$#VUwciUiYkA0#_2vBR zE6szg1sJ6L#<24v7wv-l&@&X!r=DF@$4AyKJ1UzKXs_po4%w-hDz)szqH`|B94NbZ1=j4s$y$RF_1ptdfL# zR!gt!mG@Fly($_T$3|q9`t_7)piq8b9TADicflog3$LPJ{!spfvimX_!74OveQ2&=L#vI; z)D2Oi>JqKfqK)WzvQp@>=}N98B9W^F-Gk*Qp%vsl%oQ!oHgGsb`CN_fVk&2eL`u9u zxeDI)Cfa3ZZgIYam3Spc%FRyZPe(-sLcO_i0*sb61W`+ zkL0+Cs<@uo6=0whb*$1%oL!QtL8%%1#dY0#GAU%=X~hgey1w(c!|o2^{Ap=LpM)yn zQcjJEDA-{HDfy>r;+ri66s*VdF=o{d&xDE@erg{@CFt73Bxv+$5TWhDWFp2U`HDn;oqd5#T1?o6l9w!?|t7yv>u1D%e#0>_J1^I#BNuWe@h+scw zqq?6=J63`9jO{}Uow-H%72A}NPJUQ-d%=RG1c5g$RzG*5OTEJf_YLpqS!t+&ur9jB zdr0-6HU|<7(?&9v6Smu#kY50CnhRw=K$YZ>h1uYt2Bce18sT~0qdaLcSa<>{AW>|< zW~g{cW(1yoz50TGgLHM#ZX!_5YNzoE12B5*|DZ(mWM02q$TIDDR#Lti7jK4kUyKQ= zm$e~wwaQ3hqTO(%y<1P*KHG8)0k(@>dl^$+dnEQ1tSUGMOe1gW8ujLIJ~qG8xIWPE z@iD^LGRxPmoh2~?nL{(>50G+Bc^~)9^L^c~+#>nNWk%5LD2ZX9`TiatVyz$DSHP0+7q3Yt$|bX<1`&7JSVMzFiJZ&gxHN zxlFH9T*A@~41^_0Zu4V4v;9~Qb}*O;(+k~@Eve^!zl_VhXN~1@ymunS|JGsUpo$hF zC5v|R9ABJ=9m#Yfjv<`HDsIAZByr=C5}B`gD_4Rb+Nd~%+_yoA5lnOMB{7(@8{oYxxKS2pL$YRBNLh!ky6PcMHKNBqqlvG z1@1$tcJjWKnH_6O=tHK}-ct3+h0Hd6U5w0%*#n(Si#Fv*B_<42Ap#8zg>wC>ca$DA zRXXk+8^T0DNw&H)>6RSCY|?zfNigOzDx(DsGj_1DgV_k>xu|wwe5tDuUkkvhTne@T zw=dP1VGx%WQ9yQ>Eysm)cbk>9rUmzO4a963;@&d{?~|%(!UR!*H+z;E_#of*L3Mtw zB$ZB~Q)yt(Tgx}rlwR$c1nLt_(@fC@L{rv^SL6uW6O`Zp&F{uKAdu~k2cYbU>#KV$ zK$TlqwvGgK8f6GhQvI;B{Z~`^xlciC)PhtP0^2QAhk^wPSncD~PpSi{gvOUun}Yiz zo1TbQ-SkItSghF;SLxaK1UF1Z}wTTzH!h*QO0{}0|eWQF;5}UC%5%C_hj1EjKkAle+ z&j+C%ibNkC`&E?1S?puN_~dHFq0jb4Yd;<0ttw~PZqQl&Xu96&aao43L5WA%?1R2o zTGD#O%#X{&KWVjpDuvtb(tJuuc~m@29e)IAJrAG*pYK7*W#rgD|3Fv8#lEL3IPkjn z1^Qqda;Z5^6}1*jb@Pk0IJMRZH_aoDS$pberR7>g1pp`6P1M zqg~d}g6Hv*cO(%FCy&W6?sLejBKNszkL|IsuZ_G?^@s*^t183YOS@>jTO&FjzxHiv z*IcD$)^g{~dKC0fMvvLIMpk=SDqQB$(KN}-pd*jD6xdFlzyBf`*Kbu z0DAjC31n-&2l{Wvcxnd7E|Wyqze-rYFAJ14o^FJOKOs_Q`++ar`!bqlk7GxdO6=V6 zcwXA^Xg^+Hp8j12l4g!UXyTrJcT59%sIcBqbf4e%%1WnN{m(Gg{kP@ue9)j3y3j0x zC*t17VT)D`{b>9$M~Wpm+ZV*|-2|fNw;8n+*qq0o26Pu4kc&mFBEL>kY!j-%t8`V*1s`SjMa)GC`4V z7^tBifBMTzoE?+g;$G4*7jAPp6R3`x+|X5li*`A4a&&Rn&pX0F}0EE-ps#P_c zwtdJOC^5`FCYJcf$~btSj0>rKsUnQ5a|0vvOWT{M=6H$DQWgyknQY;`qNlzIo*ZqI z#59bHs}3ts+A)>IQxN)wT8jYg3R^|N0asToEJzfPO!|#CZlcv=V`XfGwRM4(5uzME zwDQRCW=wQ?9Z;3>82HoRj0F5G^?oBX0pWEa`qL3jm*$sk?Q~CO&CCFcSD#ekWogVF zg=0ku*$j@w{|%M=J4*S>{sXO8?GbmmJl$#21(^3i*EBF#${dw&07+1W<2;&a1TBER zLV%1CkP-B?=h2XBl>)DOTXuOA2F{W7f8+h2RbJsCRCg|Tum}H{G%Nu0tL_2ed)V*0 zwdBv-oZ$o20O+!C8-54m2sc&$nJoAfK{8?j$X(uFxKa)SDh>bIW==~Fv%G6$(7-+r(|ZlWL#To07S0Wya27o^2N!^h;ctN%SF|<-fgy|F`E`f)PxHI~ zZ2gy8^PhL)_jf~QzhZ@z{blv{s_(UB-cUEm8b87P7`|!-cz5c_7^rgq037ezCX}mB zl7t4}DWpJ0Id{&xxUbghr#F_U5E;t}doLB_XCShI&NFUu&!|F`BrYdlxPkK??pt}p zNyLMgq06@&c8?}0%dM|WTu(w~{O7D*i!dy=EE_Zm3HjXbS<~81F^d;j2_Wdv{eGM5 zTtH2p8x*C@?6|GOMP-l$uw0<7uy6HswQbP@2bP)h8yh|iio}4Q@yc!`tB0{jfj}r3 zo^inBT05mL6NGj2q3jO0P;}J{;7}GZr`$cb|9#9$ib>ifXPfwSqv zpuCQ#JNVfnkkY)!Sl&MuvpCx;_W1#9g|Lb%d1CxI^a}Ya%b=b)ypH6jL-i)-5MeN0xs2rJZ>5onE@+q{chIU~2M-PKa7NUd zA^H)cle8aBsQd>cRqEHk!4`f~yZVM0@V~hby(C}&vc`YT2>*7o7J@w)s()|04AOnr zUAb5JhR$MuB7pK6mD~d{)KE#6ZYWp6v>)d#448qesAZ8KN=@9e~=3nHW>jViOhA&U(b%AB42S-H|( zp7Lp)U1+WCv#ZM((R+vES8yRvtD)^7=LiE2($00r==e~}s>K{#0;U5UQbm}Ube7sr zr<2=LK-{5`6*%vxozAT8q^6w1`*S;<1s=BTwhvPK0-33pALigds+G0zpa*_r?@{{) z2;mBWFT?;T|DDHck#M{YWSM4Ws2xi#CQ@Ag=s+QIBhBj~w6&w7=(*ss_VIV!f@vY| zrn}|1lKP_R_HS@4PaWhM&#p1xJJ+)dzhA@9PqFl?Ef`RD56rni-*U0)e4yqhpXd_a zW6JnJ$X2};P!b&kmOa^iyN>Pt6ek-Sk)!^1!bGHmstt0kQCpfS=I2!!%1x#U17DI2 zMP3nw+*>TU5J8$KO3SOf;OCnd@knllGz@(`V0)!o-+1w9XKzc43XLfG_op!oH`@kS zBjH2?cYt;@a80Q=I$_$YzQNNSffe8M)kh1`E00CWE2|kBxr~kmvbUkWG!JhfR?9s* zSZ*jEf~>nMzq0oGJm+V~F5;bcR$X5|(VwtnXNm7#8lP;a6R`C+*cW)w7~)`%xk4TZ z0s3>*tMyjN*UCXtjYGgaULph>ClPhPq?U4LF8bTvrfJUgoFzaW*9T|KoB*EglA_x` zWmXnV0CByr-}Y+Y1m;!a^CHIuY^x+#lrP5z^@Qp_=EpHxzK}KCs+svbJ-Nwj_`@l{ zo?Y^5md!WKe8=6V@k`lHZ2kLmdu2(lF!cguNvRk^*~%0ajtPrLqh7cB-#$q>qnUso zas#V;>0ftraR@yutKgmRKd+0{kS}bxftYa2f%!|J`yU`qHcPCc?l?-Do$LEM(6}Si zQi)|iI0gscEZr#5O5KO7Qgxxsmp{nKK>>s>DT;0YMg2cOBId)<-Iz zmn)S{rF?%{BmI;%%S%nU%>IX!1yTQHV=MW2%2GmI5EU}~xduhjigoIt;@CSyrbaK` zKF5P*VkNh<-r*-#=AB)n_R1guM~s<~z%?PoohP~5B=``m@)FoW4WT6&WifTeczsWY z9{&-sZ;@tJQW+#aJQB8!$^OO3Q1ltYSz(y$L`4Bql0DB9e`~|tNT$zoK?s19uY5tU zyI;G?=I<~1sCojNB`nu$Tt%jktwU2+_1*1g zbP)Y4dT+EUoh+DM-eNJG=#h6u&5Md`oux>G@MUNc3}(asd9k3a}{hG>Ezd*-| zB#_lqc+u?EWv@#gNyygZpv5Hy6o5#lJ_rqLCHcT0dh(a!+R*uL{&4_F0nG64JB*zo zRY|`4n{V6yGe;p7k#>6S?|TOAF*)96-Cd7i_#v#N{F4zURzer2cLEtn%0}6 z#ve*p_AupmA0~_tnSu;DDiAdX^hAX9QMz%fq?7W~B5&b#%p?K9Qx$*GM z#CQ?ZX=(5N^0c_WpRVK_sp~^nG1S$;fOM)I0He=VpBB9nCOaq)k>E>UE4}_`W(qi) zF5}Z0b5Okd){jZ+)$*VL%J6EU@GJ?l&;dt#N3Pm$9%rb9P)cJy7pzQ1$#+uohOt8> zWR^8^@M+lYjR?V#C+PWGri(37!(}Df#=Mm>i8Pjkx%K0m~4N8!cVdCD(i|Uo<0)Q>o zbjXMHXgQ~{VPdR~hnaEyTkmFwR;1UG+b;QoK-Af?Z2 zaaheN`cnkz;WT7q}EH)Z{n_>Po-~7~f%UystpLCbkh3l}`U_r#4 zw~z5ljS8x-=)=BlSgJt{Q}e00N_Q@4)qOLsKbZU^0RD9ezwd$Jo(K4wdO-@WSCmUM z_a+s1TNGcd;l|f}iR3)SZy*FvObx>~N9s{k{Hyf-nPai==H`C_1$c+Cs^kVr#rzS$Fz&mI_X}r}@>W~Zaaor^trrNoYB}i6&F8A| z{etW&H&lpb!9zY$d0H9)VQcXUV!fI#YHcUOe9^QmtJkt9*F6)t} zbZ_)DVBOnoleNC_IjQ^6C(p-3iZW4Tg;hVU3ju>F^WEv->#qR>?J+_jtt#y%*0>2} zJ?c250!Sqj0#9=nCiXu^Z(zBtKg2~^wN zx00ihiCm(-Y<;a0LsKo}b**I>A&Fc(N3Rs`KNJVq-g_FoU$k|(OLGXv84ydaU#Foq zADX8C51o9|F}In#i`l*-7Jkpy{2poLV<{`&>9So*YtC>Wsmdd%!0ECe_|46y)9O{dXu=lG3Beqnm|dF80M4G z2N)uUMWc?JuFr|uFAcRKp^YSZItn(d6%EVvDrLl+9p|Pg=D|l@3@A1E&_+^ojVNag z)%ZCJ3rmw5nb7ge-jSEEuhylE>Y&@y6&CJ=Kr4mYMm$!>lUrQ5^!jb~fRn3-9vKn= zZ0v6$LNaaRzM=)! zabUiow3t;Sp`;Wxk9D&8Vs8b+<3l=C{`I;q%8GzRVZ6z?#UO_Ba@^WUret`kJ8AU& zM3ZNeD9(-lzG64omkoKs2&=U?OE+mHF$OU=&0w8tL$37}r z)V%RcMNcEgxv}-gJobZu#|wc|tgi8?Mg7amkBlecZ)J6Re_)5d^qDU(L-3BTjRJ3B zg?2?g&0$!>Y2!3k3!z$P0m*?=+d82Rw*yMi+$jlsr|62q3GrQj-Bq1v!>M+^z%JDk z!4fkLV{>Tqdu$XNM(4zL+)3N>Se@)~6`O|jkF7}Np=UGKhz3c!&xaGY!SM%o4v4R{ zwSU8g!khmKuJ*qa4bu1oOaa&nXY;ss-rXhglHl^AN}HMKS0N3s17 z`<$hFLoc&hKc#}KIdUzonc`B+;Wji`o_7$af_BKkXY_11hy zOaHfzXnxxRxS*Q+*B*Yc**g03=Guwi%AxYo#u<88ZU)^Vz7lnG0ze?}r;n8h;q8-6 z(EvjqvYFg%szjyiFFIP-(|*ga7QWBS{425Ye;&*7C&l|ek39NMHfxcciZ4%3cI9#QElU+AV}ErR5y~nN;bI*3Q(;4h^gAmu*PFz#9ggW6MZs;9_HRz~9o5kLOA^a0)lUy|vCAWN%Q6^^N5 zu_7SdKl3<*aIf1_mbOTH z!#)JtRA@d4dVbT>a?YGGuPa+0mi!>uyOthaMyw&ls99{JJ2^o2P;e){*N{?#i%IxE zqko(hgEo=82sZGE4Oo1>C;`MktiW`3HcvRfZ(hokGB;crcAR5Xs+u5x;aBZ;H^kW%Aqf7lJ?Kl{lsq>kxte1cYAQJ zj()-;atK2BdrkO2NY&l7{$VQCoBz%>bqyszZ5vpg7oNa3+cR#sS`hBA#)DxXwV*_) z(n1N~mW2gtGhFTa#1=`P zG`&jv#m|T&+~5OPDYqE#!$QA6(AtuxxSgFq;8F5Ybb>vuZ?h-p%GD+%hZlb<-gO(6 zQy89p=QmzU%+NBQ3EI(x5h4v(SzRpwl@*=`2*STMi3W$nD0?5az}8)eRom7D zBhIy}XFGBP^pqM*w;qR#^#Hf*87bO|aTnUjs9WGzy61gPNkSw-@Ss@#kOVo2@RwXq z&Fd8H^Y*!aRZkEmIxL8 z2-NJ$F@gMB{^t`@=_C2t@<#6lVIn9kuqJ^=D}qg#krOQ(L5*B3O8TWB;3-Jz$I{YX zx(rmB-z70m58vL~$b-()FYMh>AiT$EF7Z=Vq<=k4Zimw0W}qy*%z{sKaQEzW5p*LNjyCe}|SYdPpw{ z6qMmmAiVf!F0oSpFFkbNhlnNM-l8iVW+4Xd4t~HJk8kCnGdIEqq?c~HvDP{kH;M;L zVmEfA?bgnl(41UrGjdpd5AXLRGwi$zJppx1$3-uVXW$%6+iwP+Ms2->Ksx;^|^ zY~uvT+j)wi-RQY!_)b55sD`qqj44RNu9p14yEc#!B{D^RWZ!D3F-1np%78R*Sq^{r z(Z+s>PH1*^fzDs7Hz0xK`5S31J(Toaversz^wR`t!-70NcWW-klfbQSsn{?PVRLiD zo9=WH)Oz_0xWKE!Uh5 z{kPBEG`QF^kI~ubC|&_te~!a+rGD~^wswy;NMGc0wnNL)YZ)irte8-IQBU8t*flgC zo@@Cw-D6Jwxq~otd~*^%q?0pDr8?p?H%8T5dA9Ao&|Ehv!X!obNhFmZDKJ`qIzSV$ zl6Zxm-{@G~iJnk?t70?SwTqX^0Z&9Ny0cllPB*p+}m;%cxBFof4gJ}B3z`3x_rCVIv=)pNaThqElJu+tg|Vfy5> z7a^ry>Eq+iBHoYDDHLq-eLux^!qMAgnzRIsB=@0B`Aw)_fr^@HCS7E(1>sgd+i^4y zi{&c-X}*7^=#YQeMrFz-11)aE>)dBdeW2Zr=YdAFzlz7Z1%$);>ixIPDEuh)>QX(g>7 z<(CerDxPUpS;jJc?U2b;H0QjeZZPAGro*J1?L;x(XTKePCzHsm*bS~2*%_LZ$k+<` zO2x4??$=b7poV-U%^+$=x-+0y!P^j>mHs+rytuivPWDL$sq+4UOQ=xP>_yIIp~Sb2 z%EJ`D-EoJCLqs&FI=GD^u$%Yf;TibHDvgAiSu*tyj~2B8v-HR=wRpw!_|y}Y=a|ae z+HaK6(E}FyaKXS5{gE+Su_%qrlM(cyExf7vAdEb52gqI#Vu_NI_Ca?h&~n0Mz> zWD1#)2S`ZOG|tFk&s}(PBtdVXdf0(#*y~0~3Z&2TWP{Y_(DA|3@wz0f_leU|dSWfu zWF?XJ7B{|S>tEVQjDgWc?O{SkZ*{|ig5HEn)mztj{aCa=Ef8Wv#&Tnp<9=3I;fKPE z9^OW(y9!DLz4Q>9#2)?#d9{SP(b*aOS=Nzh z9j1DfZq67n4O)5$%BTTaq7q4vdi96}J3ZIz6h!H9Kq@=S>(=%K7cS{JfmM56qIUmG z-PRJFEikuK@m(Ta%;pctaL2b{bwV^>~w z5KvuI%lzf&;5O(8fDfAi{f)wZVNR!F{3~_4NI^g~MW=pi<2k<49bHvHZrdQRcw%4H zzrkccL_)^Lels95b`C>`^#K7Az?B`!(XNPI7QI5@zjFctI;kx4L39RR_$r?0-A4dp zJ}uNvTh_-~fF{!qR$%GM?mj7&i;mIcyIQDMM|o>+yla>2!8GBwU$A#tDZ3H)G(o*F z^wBisMk@==8%{2rL@Q0CF%^@y_V6dZ!K zYwI|VH|j39422BfYMY&y4Q@TlzGqoP7cd&2)wBBQrYyx$Ht##}FmE3^z&G$)UQmou zY8WkKe|0q17@sZ?{#`2w^^p5y{I0ShOHW7I3Ys%Dz*FLK)Iqr2d$d9E1B2e^dvR-yY$UfuJTwi7C!x^o*!RH*l*`|2uP z<2%YPO$xLpiF|p2w3b6VU6hp=V%=B>0?5rEJ>7Lkp`k8wlRaFIWxhr}OAn+9 zexQ+bh31NfkYZZtDLT9xm8x388kQv$h;t*HRqbdafdw5 z)iEc~g-p-O^JDpg)v?pCkbDvsX(ZGO5#-w=W)m?HY>`#?io;1ty@ocfeg=;M-wtv4 zPIC@?d7*N=@}xmtb+|IXk?JP#xj)dGK2U5UDA7p^+3}a&saewnaz8nr!WJi?OUnI1 z_S{aH#$O3%-`@^u?NwmRrHiQ(p4z-s`MB!qg-H|b0gZv~9pQY{N!22K_R3|lipk+l zD~bYCu6(F9;On&6p?norO+cEXRXO|qs6Rz%F0M+?yE-`fW~>mppM@1|`Hgf6Z9`if zC%E?KeKZ$nKjc;z`o$5kjbzT8Z!*ftDL?S zgX33Z?{^U=q1vYBOzRXIdb=Wp3w97WoI)_|dqM=$M2&0AsNZOj$(p>|1(?V&bca&H z>N4&OnJt0|u+{vbFPT~g8*%iir0*o1m>IC8dmo4*>DuPJ)PKJ)e0ut{e=pj&?ua^p zH9=p;Oyl9Kjx-hv@vziT%v*t{QaJy@m^_R@(ALx+DXjbAw@}8MSf0>@6c2t3_@pPb z(fiTbIs-LS%q+~iTuM1VwwDB;O}<|JQv8!P$(87JVKb;+akw6nE;=itCpf-jY_@8K z8t8>$#ag{4rZ&*aow&Ms{@Jy_1Aoslbp-MK-7LIwB>Nu>czuJw0U-8^_}cPcIPx^Q zN2+E!JdGBm#bw_5j|=x#T%3A>Kg$eyPwv}I&{C4GGH#LQ{JzH0is$>zi)2ad2KiDL z9Y4K4@kH?T-5S#rV@n~X2+Af@aRMQQ6?T0FVEGcRKson+t@7{>wTFN8Z+?T7QZj-O z6^XRHt+Kp;M4k5WC_ZO$(gUb!V6{TCPG_8?tk#!GSB0^LRXu3)q2%K)LWjHS93P3= zK{p*fo1AiXX$c7l0ljr{bsXYD?QK|fn>`T_9&n0g3P0DvJED8^J;N6qnSxRq$ z@tSjD)qsn@BSB?rrEWLsu@})_yG$pF=(7^>b@-ehRoH?*XieKiDSyr|N_hO#V7!cb zU9yySRsLw-0+s^Do(8{CZ$5onZ8vgRJy0l^J3dd<5Qy=z@{`=b6$Q%vVo?`4Hb3al znW~?2bV%c@HhwlNcVu`DRpq0KXEhauxSS+W?_ZXpzY?d6|I*ql(C$6LR#jS>d&y{M zMrTUO^r*`))KeKfi71ly628%+21HK4x+M1I1Mb!FPh0|6XZ%YY?Jpl>{7-Aen4Ie1 zOMwB-C9%%YU+%st%A$z2fq%6)Q~3(-{D<$_7wE8vGVJ@D!(FhY)cbkIpvJ4Eb<6%{ zYsb^MW0R!M4#oC0BY%KQTJCOAZZV_&)N%R65zTJ8Fpny`Rrf*HS=z&z%0vqEI6`h? zN4{B0y4xQ{5yy$x>$SDS6Uc=rDW&0B2^OW_SlU8SiYb#_?^kFRn;&Th7(gK#%p#3E z;KFUVbB8xNj@(@%#_g3k{1OO5mC*|TI>2B1D!*+1|DmnTxv{;>v=&Qma%wgp=8gVo zo-E!yhGa#-+!utG>B*0)iObAL%=kfF7Jix?6O=_eV&u*3FvB+2QTE(z@DRj>S{tH6 zs2|7WyfJddYlpy7x(?fEyd?VrG@c<1j5RH-DL?rh>3#ORb9xQ0ZB>Fw%i*V=ZH6*1 z+q&f-Jtrp5|DF7ihJ+q$83w+d=}1=3n)O~X{G>gN)u9m{9Yqi8=wk8U7q(4+P@%m& zijLK9BF|@K7&#I8ofYx>UfC^%bL`7gZF3EB-@p#bX0t+aTLwn=vDwy$u<+>3%m}aH zI`Ztm{G^)3$1KmE78xc3ai<-PLV!-^TK<1?tV!rWIv%pj%M^K<^PFw$4j=MnWVc=(QRoMDZh54{x`>~_9hetp@ zi-q<^YV7z`7Ire&F6jn+|I5VykrewUSGR4rv4^l~AnqO}Pg}i1P#5$gYV=Z1@SXs@ zSRqA{zrLi6tA1+%zna2|+*m5^+v{LzBb$h6^2LAQa4X%yohVCN+`Q6cx_P$AQS%WK=YQo$b%JFOQ`CXXIfr&{~6HjpM$- zy0C8CySb}&k1}Z>+o$U}o?bI2+%5z=&w@kg+p_AdbtPdiZkc!w&Y*r+up3X9fbFXLRViaK8`R44!55Vx4MG`~kwcKRhE*JkGxRK5#^(f$!Xp z7(a@p7i`i$mzqobV^*v~&s*-`Q|9R5QU90_-(i?2+`m#Bhh*tNx8L@Y+xBfn1?P>Z%KL7_R82QY= zS98Pi=3#O{lfyO)cz9xrFQRsfu8^0R|)Sne^c`}|EG1yPj!B- zdZ24RdJkZnhw#nOpV$rH9F~BnYx)C}p;}>z;-^6EVJKM@ip?yMzs(h(C~Ch94GHs^ zcmNK+{BWTZDvMT_!Mjxh@vR-9p40C$En(hEs$7h*@x~-0-NdoF)HIPvK{RUs>J}QT ziqn?qI?)qsZwSKE?^U1QRMc}4d~^XfmvWc;j-waAo@SdovnsZT+_8r^9dv^4Pc2lD zG1b{6QfdHLuY6W|1SPVRdMUToUbg;c5L5#cx=aehKpoI79wpG__;cI!{TXEsK0!9B z`VDI=?^bUW=NHwyi5vX~P-O6PTVnO`Gh`W%1SZ}2%~=xt+If-H_Z}&~<)*{V3yl|Y zuZ8?1@6Fmjip);S-H`tt-vb%RYUC#=(`0$Mm>RZj9FF2OQUKeE&q`WPE|uEC3what z^^hDLCE8#z&?~NzJb#GJTXUb9(P)at7H0&Kh~kGLJc0VKMTGhe>iR4ro<8y!(U70S zvrb;0?9SNf_3Ru-F;te;@7}6@9rM%Ueq5Uq-vN&blUK@YXVJ>YK|`MCpk6$J>qs~` zXzIT;^!oYz!p8(E6CxzkIr#&C{yj04b`UGyUV&rwccz z;=r&T_+#9x1c($n|LY_sCbVrshjygc)ue_X902yzDVx@lh*y?U1v(OFWfq67jV< z9CTb|Ed&yNphSpd`wJBJD=dc`C_lXZTW9+B>@NPJZA@D!$M?&C{)h?SYk?K&@G=(B zjrJMD9s8xqT^s=Jz2IB8*n&5Eva0;sZ8)Nc=P8If01e0>FHoZm6fneV4g4g;6pVDK zw)uOoo>p7y*F6l$^Pj?gtviFdh-=WNo&p&uh>L-QV&aa^yni~W;j|^$Uza_NWk=V)U@AeU_lEuH8VLV`vU3w5Qih~) z*D@6!wS!M zs1CuptROXtBy!MPb5=aWV6t|lPE3GpcS|z=%>f}s3-3XH(OMrZ{ zg1xJ$@;K~H8!DC(-)dU-d^B2~_grscx9WULgu;h(A&oXm!OX;gcqYglGKZ_?T^@rCXCft~@4PbLgHHhv3@PfC zxzK^}OQR zHpM(v*Qk^5MJ~9n^iMDq`413$?b83(WXNwhm!V%z&xrT|pvDBii{;q`!9!6!+FN$MbP_4<}b$GT3o^)0}7j) zTiOHco=3(eCmhyBosXsG4ibYeKM;PgU#lRW>Ykd?_9q4khQeHe6TbfeIx->Mn|Rtl z9VjOU$!f$w+G#v102~ne-(7+q^OuBZ%3ARNHfI}j2lS28DCo2o2o3NaDFc;VpFNi| z0}u;+WZGx}7q=Lr^-}AUYKxWZd!)MfN~0!XZxp@WGEJY>bQ%W^_i^+)jqZ-0^jJlL zW5ljWSznfaBnJXafiBfAQYbFs6ADWEKr>(XmA7awL4Pm07UCOjwhDPGvAWo{4rKG@ z>M3t*bms`+`XK<(7jk{2c`|lsCh~y}F(0P&ah`LAMOAaZ%DESlpeS}7Cv&&cm=?4r z>o6V*$bS>r24K@79*(`F4R#_30hxvHi2yV z?Ge*FMHn9&OdK?Znhn1xpZy;$?&~F3<0#V$em}{Ajo9Fp;F0xbpaM_K#ut zf4}C1LP~owQAKsk{7P#r4|nStU8vk;bc9zEDsktdBLEU##wCRt%$g7KHnfJp-c=E= zGh=S(uFAHCkpC2R$Z|W`?7S7v<^QBQzHQ3FYGkAd*5xuoy$OFP*=a)_+3NYx^2(#_ z1)SjW!Ny)PKpp41F?s^bG0P^T^FG!n{y(e3lg(4ki&{oLR23{YJYRiDhIcF0hyRe{ zeyj21z1^3GE|h~+qtw$R0O_4q816rzJ=UTv2gfNN!DYkH4A7mt;*Z(oKC#<-!!tm* zL!Ojq{bSt9!Os1>@*+~J2i46`VVGO&pq{JPep=Hg_>f74cff!AnqV_;8TL4zii}*) zAvz+k(w4v6w=VgNYCh+1`D~vKkUn9%@t4(I85_Ib>0{pMYeYd~MG=cFg+zBBC2h%c}ce#dMJ3kl>^Qz*{!?It|1B&=CLle`M z0qaj#Me{mQqfS)0pN(1ZQC*eT8R@Q#0L?DaDt&OA&V(ST7YHWP7*_yZ8{U*@wC7ZGbE7m@vRnk#CCa!x+ z1Sn^qWXin}=JDVyib!S~=8{xPk+c=qPU>ME`i||Yg6_un49`!%le{6!O)?^vM=th9 z=N1FFKL5gLD21jCxgpl|@~NCHhcDl@;zJ&Jf!ZKz*Aew{i?qhQzg1nJM*bDoVke`3 z&O@PJa!J{my^56LRsDsnL52S*vzlr^kqA1c;=*gyDGpURRhMiPqU0;tj`$`zFV71|>_yPaagS(K-Kt69@Z8~z2spX6Mb zQ?aD{@wJ30@+gxzcgW|}Z)PpK(>3K@dKQ)2GX%IjWO4|IgZxB{%Cb^JrMpuVDkv&W zG@NMtR7oZnoS1r`b1}G^k^OA0*^85S<|3hrcn$PCQG-CHkQ?pdn4|$~pt@K;>bbu& z)@7Owk;Z2Cyp@Qu>J(A(L@4^BwDeEJ{@33>-I4#@E%|?U45y-51Dl$1JPbMH>X`&w z9OLIcng4jWT+5=pYq}9&W+z2vCJKE z^M4*)A8vC#&-1AoQ7&&t3hGhkqa*#n59ps>&NpPqD%5-axZENjz%I2(%fpsY(V`ga zBt327IkoyutLVUZcGoxP;JDjx<`H>o-rRIHOjX|mGLfsmP=uSfgxaP}0up-AgmmR- zNyW838;jBKZuHhNVk9N%7#_6jald0yLBX`j%M}zw-85Q3YXpRuZ?CI4mF0 z+}J?w&L$r6yQdzp_xCmceskb$N{g732+O$*FAt4MkJyKVtS#1CY=&I#4{i^wv)_YE zzaTt(6MME)A=Kfd8VZqB!PvK#OpK>(0;FD+)m%TSd)e^TUb1|g)PH5c|D5&-#Wk&K z=TL2COV;5Nol8IPEyfy9I3omS%=T3v&l=5mxA}z`dU%bEe^7_)oRU1mh>hdheyC2BOW&DIL$^_}4fd|Hycb#`s&&GZn zU1xn>d8XB9r|-7}7Kjvf86kcwzx6F|>pU3Qc3{rqNLHri^hKkf$D()D)49u+&uK(o zh)9WU-Z121idT3yM5dX_YVP{mEKIA(Od}f!-dP; zytWl!G{O55bU6x60vW?*TYrLbx|ziWeMD7>k_|5s1HR3FNOJu>=xQt0UlmzJN0h=Ln6J;XoFq_lU>}U-FKf41 zZb&AEZXj#Nx|X0C%^b8zt7}lwr{eE2NZQ!Yp?>C2`ut6)WRb3azn^QaZ&qz$Y`5sF zvuAvkruPDP(Xq1)^8qRbRU)@&g&m4r{{T*wr$9$mtDTGj)(0>M&%+7emDjAssT~hb z#)V}E$sZG4 z=djnCkmk7rvHNa4AaQDU-(~0du=F+-U0G)H=Vci!5)s%3#T9bl#%Y{qdw)~c+_?h^ zV~K=&3Wi~7z{=Zd;USzU2Hq^uTyj_0oyNvtpeIcMYWDHJhSf4qcePu#|aN) z8*^M9jB;Mze~jM5ktM`fa;;M4r=!0WiNEbEWH}Yd%3Z?@DyI_FcimO!PLR;c7 zHs?i6jeJ7ZSJ=`VGdHInu1p<{T5|z1pBFA0G=5daZ89~1nDX1p6lhz?&%To1-+^z^ zN6tMEe@q!D`Z(BmQsFA`%+PK|1?)VMq63**QGZmnT}^ax^D5LcFp}C@mdCQeVlW`j z+X}#>E}|2#?@|vl9nbLqjPxi0<}PrLg%<~WJb(oN*Zv=)qOxJI<2=_=8t*U&ZGY2g zNOqNIUoh$}L{>QB%H>dr_NYfqINAaGaZ${3kCti`}xatfX|hk1yv^!gPly1<#? z_TB505{C&#U5Q8>GqlFO=eBH$b*wg#OT#3f_j|DU2$@NfeqP}bQsmld3{9xygLPqn zzZX?v-n<%U{clqhS&OnrrD2;cuxe{98ezaZdw! zj=qc|pOs_luc1r14Qx=jats~yzjS=?gmJ@_KhOV>gtI31?(=t>f$`~dVpaEeGrzs3 zOUI>|!GR$>In3%s%V((IdYZ|yH*ugoZ-Jw6`v*p*Hk;KwGD2tPpvG;6Ah%#lVNa?c z9&kPR*jeBTT}IU5`Pg9qmljKvBlCfYC-MD zDfXVvk-sw1>E@T*wyG5PVNgH^CI3xJ4nhNtDIaBYXl?_GU!9&K4gyA20C0>+t+K^ynIy8D-QBPrmNXV)|jTU({+C!+eePj zut{U4k*ddz3p8lCCT=D3*;TqMzqDry_0T3Or>(wBRUfQa`^bA^r{NFu08lg%6L^Q3 zE8?`H8chqE1LO`L@rZ;@_^Mu7ls zZ{Om_(3DpK2BGwN*2qP+%lpsh9s-+SiK8m*!9pKZYlfzJ7IjT2xUCklMGMX=h)Hel zbrN3ydU~0bX>)?gvmuR8;LS6N!6PVB9iclq6lb$5n$G*}>*s^qa3Y_JY3qChgTAaZ zSfK{FP4L5TPbRK}HyT0^rfN5%Q>9712|ZRABF-)j0;5ecYb@?}nnf=x39~TvE#I26 z6TaFTS6(SWF#V4(|9{WQ{j(JCzeESDys4(VSJ1Tpwpn`lSeC}4z3ZCTZUI2Upr+&{ z_l0$+g;GYDQ$<1?Bfosule#^0(KJCe4xiTLty+w-+_CJ-^qM~!E&aP!&uN-R7VESI z&{A%uVm--2|7dbhupDi9zz6Y8yYA1f-?pvJ%_(6S>Dp8M&-tE^X!1M}(p?6k4Hym! zE>H;q|6=b?0?l3V!vSW0wAepjYP)5}lcI*sQ0iv^S$PRE0sWrZBxZ#DB5rEdcOO!& z#%U_@RS|9_k)!$w%@Nv8yl#U)-{y-SiuF@+;&sl%YOK#)-P*G0{_S0XSo>|{3!og* z2k26Mahnh3(jR6AYNL7|r@g<|g8N#|`pQY9U*ry3ed*>+@jaowk8WX;jfF8~!62N< z!1z1r#I@5(G9j$bU+;nYzK6LO1GaP@OY-k;n^SerD!fWIvk|FT<3l#3siFUtHe4zQ z$%p4cDQTjkE@n%bMp7a!!OT+(URK0+=5kzkt|-$$ZBm7%Fg-ov7?13OI$6?Y_FmHZ zROQDJjbPCgPyWmM7ipEY13w_S({u|m=nw1s0=q|?yO*PO6Yzpzk`lBfZNRMPtcUNHG&rZ9F2yw zrZgc+0SIM>h4mG6e zAf`)Q}$e_DMxA$%GzcaH2RBjfDsL-gI}sofE~JTppS--uNtoB{52 zultND63_6b)9lnBXl3zA;w6qgIJ^Yq!@%ag|ITt?f9NEiS9OF3K{K((OU#@S*WjJR# zVXw7soi0B9iLo{$6L)#*LKvjtZ-T>n*Q(cOQls>};3jcJ$NIXp=yQQ^ZJ@Fzu zE(Qb|t604p3kO!?CMW%8Vt-E$jg!iYEXARFeF?f`*Oo+bRcD`9eG=ckSvI~COsPF5 zZ#?4!R9ER^7P=cWeP2MEQvhA;^o0DuQ)O4HR|8HE4s*t0^eJ3-YMPPZljGd+ z8sb~g0QxE%`fRJAem$!WlUdS1*Z4&l`2vu1okPH*;I9n;KvaE5>~wo1w$lk{fzX?v zS2^d#KPvU;5dazG63kEKwi+nYh5%Psq!>C6WzvcO4Z*q^0e_Hbm>p1FGg$(U15pVN zP__fKSDc-n96ERFe}d8hNtvJs&Z>aA1anUT5-6!pV!X&^@{gtbpZ072{ohx*U*n#D zvO`3y;bznwH|i=5?RO&NX&c@wkF)9)Am*&{`GThM%YK6XC5-z+&<4``|M1TeK;+$6 zjv0@r<{13)P`m{QNUJB{{&1`2mB*on$djsbKT1peMo%iwElZ{NY>>FT05mk@`dFmv zF9N)pgxjMjuBCC3p$fGqM?xf0iGJVY|LYn%nwmjFVYq0yNbY9>oZ%f9Y+lWa!!5p* ztu^(VxmEnJO`U-vYZCg=P5~k&cd@^^QAfQ!-cyt+0i!@iWD!ilf?QHVEqvZ#?`u0J ztY&8f1w2OzccO!c-GYv~w0yy&-_tMwq1cRO0%0`s3yRJ3a1VpMX$h;6 zCnxx4Yz)tHFea15`7rX7eKtEt9UdG>(JS>~lK%{Ov@L@9gx*uOC7Bk&G~eMJ2z`&S zh(8ux-B`B}rpw4znXa=m$ zKuR$&RfVjJm1G}LOaP7I03Z$kG5T&J{%q#|z`Fh&%l%KsuG!CkH8ar=SQ0vC=Cuuq zLp!(3=K&@9CC}{Nzbi7!=Gra6CU7S2U`pC2?g!=bNtz~Sv~_1*++m)FyB}AxZ=sA~ zvEVJ^SlDNRTOQss!mSxc#l9%l5LyY?qg=$+9~Yt5hgVmg!RWPw<^pPV$;zsas68e4 z5d&;>-BAZ8Xs)hs`!ObQ1}UjjX;{wT!<>*w9LqW_Ltwwq82<>-QDo?8EbJDKg=LEr zIvTAlrKIrfcB8=81G!He>isV7CA+Mw>|-fq!p$vS7?i`Os$_Ip>?E&! zokw+HgS_ODJY$m6{c!t*-zn>bcw*GUj$@%$N#H+EC?Fm4c9Zc9&xdgC1m9vqn(*1mehAHJ*cN zl#Bz1aOS&7jGGC5Tr$EylPEkPL(4hXY{HAN+2=9}^1#*6ANP7X6D-9n{0^DxRN&U+Kimme)_ zk_{Z}>CM%NlsV;vT_8n2MmPpP3dgiqHwaxxWxri{DHhKYXh=3>qWO8EOgAlAD2*CT zXKRZIB%h$lB zyx*TDT;Q)-DmBseEho1t_fcSyED!+4uGqmkf&2c2lvYo+iHSxzLpQ@dx&{!jUH=ua zO=3+T_5Myh2aXAwjL(GjjIYpvEq*e2mbZ-aGywCW#IbYBYpU~*7zhLkSjzf7idw@$ zt8#jx%KgzsdO0@aRSVx&g_V68;9;fj^`gt$)!Dv0L0{gF28&dD>UIA?1sS;g`UwXK z{mr$GDF5Bn(@80!n8y>FjJYHMjQ(m7_$kPh)f1Ks9O|Y~ubL~^(KHpox2UV&dH&8T z-?oUNU$Ls+_}wl6Y+U|BbWpQg<`aUxF>?CawmAkH8`%SPrITJ{#)JvuekSFWb5;4Mev96P`}!gl?tX%ORu zq}9dvg~U@tERhZRFnS9l7PyMriU7pv7AOxi@0@9^S)No&XT|jOE+aEoJHO_8ILm=5 zu`U8OTxU-A+hRBAMw9Rb)Z&_kDlieixUXsux?g|f^0dB|Wx3@AGiT`nxJ}DL?B*&G z)<$<;G?LDg)bEN(yr@*-ZFpo-qqyr=Zm=ZxL>|vTMo0ANr)Fe2WCS{-mJ;qgsDK|g zu8v%|kC~u^(?>lek&Zf{s24=9Py`!w=!eNbRoi*`(Fz(~sfr%^Q6Z29ri-cO3_(>KGgVRk109^kxTeE!Ka#f-QBHP zNe)*Ig7b%->ybWMXTo-gGwX6hWgSc4x$B>x(6fmQUD_oW@!k2%%&+j_x05Tl|Bd)h z2^35_7XdUja2H4u0nXA!8EUykQ;Yz0!Z-GG%F*smT^`86E)x?-(SOffZJy0h$CGXt zUi#ILTwdxZ8o70v7j1Kbv=lX36yTxbJ;v1wib;<6){rr3+zknhb|Meo>Abfrw?hP! zo=!V7%C*P$?>m_s2>Ayf&bGyo!kU#ftK7{~4vxK*Aqz`&tHRcUCgy2zBN9Z85xL|a zaFf3vMMI1{p{%5A+u*+bLNz0s%A5XQjX2|rdpsU<-&{UE+)Z|1mGy%b;Cr}`eaU_E z)wSQ{YuUNJ(y7&Zi__?umX5eR0>RPVD94%}hb&EETlxh$U8$-kW_7_56cPAsV0~~p z@<)JB4@BU;MNj+I_Mc@JZSFzEFlwI1J2({6LQ<*1i<&Jx)!i6BEwqVKfLvGXP~}c7 zi_FT_7GxO@QoMZAmmq^Y^NDbpbuls~;?8+3lp0uyASO*y$kIpMgHPB zJ^Dx)g+1|=^<0J>qbJFeJ{3cVCY0yw8fOZ-QLeU_@3L8Qdh}j+a#9aK0t%^i_IEtF z6q%|{nq?F=Z-!lc;RW(o^bV2p)Qp7uHpK{}*K=^k(WVHR+FE&=zAmCH$)d)YiLp*8 zW1)A`xsgB{=K42V^d9U9l(aMM<+;BdxzuwJI|=!GB|(EW@6JQsm30;a(ZZtzvY6G* zH;_q#;HEpXs z?;8|z{J0=^b5NRhJBF8GP$tkU_AWuqoeWV)ogDnH9IbQchNcTyaXqX~ctQRFwMz>+(cga?;+rQ`$)zFND1 z2j6Tv{{&&zW8&Jn?AchcEz!ywgg9X)ZvPNqX`U}u6DLs#aW^KgiLbs|Z6Nuv8R`1j zjP0SGUo4EOwL|DP^5vXE)@3G#JV}!(b@=vBeGvA2-;ww;z>(re2=f*OBnF-3fWfiN z0(ktg>EXfnG#A58w|3Tiri#|iB3XdNDw>RlC?b#HO`Rj3v+^=@Ip&L2e;5_}URAcr zhitbG@VF@P`!(6BR>I`fzHJZ1z~&(~w|0FA?u-5X16bhp{}JE+>vIb3mAhf!%FdJh zpP*>at2q|acJOm+9A^hhN>T*>#h1>0b1$$~Yy!z9P3wd0xZ^ceI~q!SG}}KH@n$Q6 zo^)xGA(?hWXQ(dnYSr&-{ zcN)cZD(CSQJ}Bf;O;yKwevdWblfFD!^0?<@eMy(b$s;KeXF_wo5Tg)jQb%OOR>SR1 z2>u3S$4~4?Ghq*(_qjX0s6)X?6-~C$`}~F^1d}|=voCvZ zmN6vyc^1`VFK@wdK#!|cQ}48%Y?AmNU-7-8+ES2*SKDeamANu!iB|;gzyyPCmM?|u zP&mG@rrwpR-4Uhs(}0O@FntVn1WydNhBTa}h6zXrPTZZ} zknQD+NyZCBZ@uMimSZD7PY-Fj?SY|7QUU1RRdt!Jj?GocU36XjIrquaaCeP!on2zW z?KZa{0nvw1JWm8nm3}C#Z&N(1cqnYNUqxu=!SiT*T|WsAe?qT-wjKLxMel;l8ws4`HBtV8=3+A+4-VspnAotVpugQXJ8$$YUT`U^{6 zEOo!35I#*)208Qu@tIsyE;@M}r2J4b#vLWUYPD~*BdmlxXF`zw%tiAeDv8v)UmUQr z0+71_wg+FbXlZA`o#IM8@1db?rMc|m{f%Q@2S$D>4heG*jy%`VYGG!QP!LTJ+)ll} zZ0SC7?;UyAkq7QasQ|olkr|f)Man2vs@M^& zFNLO_FLXYH?7&5lV3o0RWitv@u&SKII7G!az3ykabyc#Y&5xp ziAKx4t9HAA6>dV>#iD&xj!lX&NT!=`DUB<>?f6ib%q87+YWot(_x#Ry`cx1?pC9+- zqKr>30is;PO`wiXw1S7WFItF!4zywC%rOkdK+nz(Ojak~lRAi}B&wgm0Jm9D!jj4X zrx9j57f$^9=eZn9hptvK8VSC#`w_r^^G+eNyC z$7Xi63iOYTliW=JyVQSpg-*#rd*vkjEmvyy` zgjb9)xeQ2%DfMIT)(K$mXaO+i|4yrm@P})`zZt~+4Z8?9kpY+buhsziIX6E+Ek8j% zVi$T--q$c`V0f?&PE=n8s2mUD_k)0xWG;vrH~|DfyR;Pb$E0t?^W)%;2FH;<`LSmMC{+sVEg7`A(MaqF=qx$jAkHWKLdZa%zteHsmghH2QTg3 zWHk=1<3|w=yN6GS z`d|YYQl&J=E&VF7bosm2q*U2*TSr?-loY|3LMCRL0dj~i>ZSuv{F<%5qv+TqxhF?aND76lpL|a=c@?vhwL05 z+M?Eq6qKl*Bk@;m92W?s+@Q9%DYy!qZnh;NFq;L{M zWHiIpRrCce;j8^WYak>wAPZcq${Ocx9_YOc*8==4Z#B^Mc@TqAVrqZ*93sBPV$LasSU33A89uQcu=*7!-WPbwZt~WyRMI!f>ChLYwe@Mx8L`-ewg!xrAGSEw!V)nwDX}s zXU?_-QAuyCpT=*C5t{g=Up%ANFJ2JjcK(dfnY?S1F4nYcFygS~pg=@tgAe(p^iI4m zo?y7$fe?{i_)=sRPqkhiS?g=rKKbck&gClk17U;hZ-aU`+kX~x3$hW%W@NugpFJvanm+uImD>@^cu{tdPQ%t z$J_y;^x3$MlSQ?R^}2MgL9Q({o5j!TflfCCN}sUwzA#t5)q1A~5o7TDs_|L@&A%D( zO-yiZr1)g+tiDF1+^1MIS4G33+9%510{&JxmDZE8sYG|#VTE=^sm4W?lSh`5?t3g*vk-y?$*7?`z@Fy`3JCcVVadr(J8Y@8v9aY$ zt#UW%L$1lT9tGS|f|7b00g_{vzo*6b#Kq>LuKrkDqii%TPMkskkeZ<4o&7@1@146p(Yc8=$RhY+hL0*2#$)8V=h0>9c z0NEknsRP_P;RXBNvA5T3En#ydV8MI9i`d}$-<|-&jl}>@$O2;8U&zwrrLZjYK4rQ4 zKtn7m;QM#$ib}p7U*#ItxhsM|_p*0Gw~n2x;^P#)5wjJ=%Fh0ET7j0IGA*kK+yP8p zLgL>R#J@`^azjK4pB~9|A?Fq42XRb)4J3*9s!s?NE27ODAyf3Ii;_7M#A)uLo~zXT z4l&A{Y>3IQvNen934Q#Omr^Jq3IoZf|K+)MIS{Gz_!?!Dutd*H)AV8w>f4ZF8%C6R zX)*>SQSVR}X_zqxNgI$slBp)^o7vE}1RXNHq*q1;;lr43(7fO>vkK@wBNyS{@ut|2 z)_X!6G8t?~t`100^6~AD=|Q*hgJXhQvqG^?ZSd#S^#{4PdSC_#MTO%iV%K__>Oos? zg545h8f-2*1i8ak_cSe=_~>=zkT{xHrei<1d+g-YrZ+~hYPbBT4s&9Izz)QxcH1q{ z9BJ#K3z-E;d#tDt&dPn0lZtJxzOKERK61*{!k}t-XQ8^n6^dw;INrfKt@G(~Tf)@p zw%$H{g02Zgc~2E*+e}ocXc#gir%Xt;a8-~)ONXQ!A^7pDQN_rZ=tp-+iQVZq5P9oX z*38B!nHpiLSzbAPbR zi>)!b#Ob$?`pxXUwjxR4q%B0b*5N~=1`WS?0|2!IByNxj0I}foHts%`x1(vrPosuV z6}9mcntv^G&BG8?#iYPU5*8$jci_gADAMU=X>mg>YGrz1oB|Qw^z!#O(fuBLR3WAwE;+s7zN66CGEHh#9=jRLHta!WiG<)t?(Rv-$kt%X zp{Me+cLhrDl^dKz!Eha9nxS!;7@Lu4wpztoX*z&i-?ot#`AE<|6>*pD_)SD#AkM#jZC1wr1?_ z1E30wf!hC>Y_5R~4d8iS_FhzSVn2zYLC!7=;)tz$^+Wruzj2|DCBWWhhhW~ilYicv zX88(xy2p=~iU+6vM_p&MragvK6v9B&f)UU7>7F|i3ke)r0k)QU7|wwr{aSf)Q8fo7 ziuRqCpXg2L;y;nPwUh&Z)OMElE#z!Mp95V%PXRyD-=1G^FG+rE02ujm14uThBPp|N z!P2l@Q7_&A&dWMHWFbBdhjy1fm;NH7vQ7xrPmt>_ph7JKf(vWdMA&_b*bVxx6;d3( zJmr*%ys?)`#SNFpf$BNYs&Ki&`WuLhH?&Rb`s%INGLQp&u>lZri~4NOJQv2oJT$cu zHsa@UY}vVhJ7v$zaw7_PRf_dYMKG!-+*#tU6nNL=xmQ?g7I?KPDZhX z+kj34Zi9#f$tk4qf|5M89*s>B9s1cT<$|sE9Jvmusz6Zul6-ul78I40Ty_59<^=$2Pj^V@z`%N8<)NI&SU4Izl8kfb84Kw z^7<%Y=Y_b#6^1QGY;)bOP$Q1rg|f8Ni-M!Y{rJg25Qq9-m3Gtb?_w%9D3m4l=>hC{ zDd#|srC3*}t|P0BizLBRT^?F4Bn8xSJHx?;G&y(jPWl>f+Q0h=lP@NdpKk)NLSPD% zaTf1?@J}T)tff3TQ@NSUxClI}AEkei7188rTVjpcVjzoITcONy-Pl!pmm+r;BoBhK zOCrMJF#j>DR%&!EFfI94kxt>+W%H@O>-&EP9Y8ShXGUi5d2H+MS+NH&2|p+O1eq+2 zKM*-+JBgkJplf(h6@OL#NA{(yIVObG3vyBECCp#{D>GxoCyE$r8l3ldv@e_r&Y1hi z#0ju*dL>F+eu9`yV6N)+B?VGsGo~qfvfKkTBvVE0I7*aXWr`NEzo4am8(!33dF(G= zzPuOTQM;^P(&;CDHZV4|9-rdJz{tDx%?x3u>P{!YI-9{vm)e8zdpG5qZ^1$lF~?KH z2l6bASoP{?SQQ%gSQ3cXGuQ)#myE2v#+buCq9JB1H;G3qSgaOGF#)KoNORPPQE1O* zpBhcAu&@*~MHiVznGjjn5I*RJo86?>$On@lcWBInn!E>312l7c)3SY?Gpa%U^TgX3 zxjEWV`TBBw?a#A%LxfZy?rUjHRopkpj>vSEWmmP{o>z~uCoftytVhaeWO&tszI~$p zBy3sc-DTb~`KYLZ&xS6!zRx9sH0CH#b&6cn7>l{B5Oqe7!yxe_v(bE(lxhq?*7@zuVeIrV7`gr%m zgH%KsU{YEF^rL^yG^Sw986JrOW(S8tR0lyn;^aT|1Kmm-=m=r%Sp9 zd&#`KSMkPQ%z|md6-Nr=3J~b#BN{6dyySBJ(;TLUO@9Jz?*pg%yH3ECIV%kM69jZ2 zn+5cn@nKgMVbGf;@LCbTg3_F>h@YJrThUdPz^12wY2^F{a@lCB)p}_t4trYigA@uA zZzmq51CBMnBxRibuh5#vu;+4v`I2>+>0U(R)o~FnfI$07uE`MdY~opFwwV%l%KzB2Fl&k(uR?w-B~T(oeSHq>0;*C?)7@lZAcZ2JcV+)aq?=_vjfk`ju$s zqBcJi3P>mpnx(%&IOL61WvLmLjBYF;eaDbX+Pb#*bmB_*o#Q8{+^H*sYV9UlSPRHD zSDc2ul`0m6gBE#GD0|MR)s%coK}$E-GFaPD*5CT%n07(RcI99kojy2g9;uw;Juen$ zK_M{CM`E{qOMbkk%?zd_wYx00Z(TDMYc?nrD%XbydiQQjR~KaaS%+mfSaHg8*;7ik z(zA`hfdC_bs2Q(KxrBY8aUAPwf<{aW6x~~heIhek0_jUX`S3x8b9SO{K;PTgaAyBX zm`rKY^gZLQSV~IzH&#(r-RBLZHqWYJY3ATYB+~I^%!OZX#GwHgJ7emGgGKe)R&tKl zO75ZOGhsewLu)nT@JB;7O>jN6P9C@4zE}<}e=)&LOn5R_DWd1Vi>eCA>TPHjs;w5z z7v?i1j1Re}2*CLXQk>x-Ww`K0!!VWGErX%<`b?1<1;OYEN@Q zdBVz)AcMM{*QWzO%)tILt)`RnBh1?v_U>1_2mFaEmhV47HwXm3q9|hB z0-gwA;`P`&0`6EST;#7z5{9*g2A*gs1b;&_hAM#^ENlHGHkdHcb!B}@((sW#NVgDp zPPq+|WqOtX{p8SpbUvV_%fdjw4%ais7cNTty>&E7YmQgznL)7Xkw`~6GE+zrVZXry zvUJhGomL%TfFKMtNX9w#9J6GfG3@P6&<@{E&}-nXztYRgh4THl3gPy`*6-+@!qT!? zazUPf3ld}OTo=2I2BaK%;D_W^hMyoLFx$x2;?vjXP{8MmzRJyw^}a_>Im7!Z#VaD^ ziT%6-p_U~!1E>)svH%jy{xTcQ_o`vGQgqsSim>~GMKVG7jA9i@>5%(*TXo%CschY zm@eC;eR#tZn3UhLM!3cV;Ut%g)~at2&Un8Al8voP7KJtW)3#N^CnF4n&{gU7MD~Yk z!;+$!lNcs9nYlxc2N9=>ovfoAVlq1$%GJk+oZ(Lu84yikFe}ZB#pjK9TACyghVwZY z9Md?lM=e%wp2NT>H`+?x^-Jf4R4lVe%TbNd|OT)s(D@_KxqJ zhBWgU!yx1_LZ#{Wx8Yk+VjXY4qZ;`V-CLZB1pKqbjX3_7XIz)Kpu*!QJQ)!=5@|M&dU)oH^uO^f7%zqDF{)6hOn8=>&$rKqAaCTU94F(i0LOuR`(_C`ihpYPK1HvxZtYQy ze3YVZDBp;!wx=vPAK`t=KC+9V)kX)ds=2=Y8hgk48SQIjE=PH|Te95Kc}UBxF#LS_ zRY$4e%Yvgsn#OXHx8{$NJcm#&RwEY3SI9Q%>_wj$F)aqP9zJUPap7xqM|$xiQLsjU zmiIU|8))sU+;|QY|ADQCau0ma`oKCaQ8&YKNy>^YGZ=Msja4y`M66hj7KPNuDdM78 zFXFgnRO9!aDjPY%D%j8O9lV_RtKbSa>IuNqI2hfzQ51fL`7##6$k@i0bmSRN6nk1h z{G4YJ7L$Ar%>W)k4IhS&@Fpo;h{G|NgO^S=#7|?EZRC@Lu%!T^btIwXtD)otedJ8+ z^p8m^jq~TzC&qJID~rZ=(-*K-QYAb!x!1qLJ_b7l>&3IeQZ9h;&7{q_o)lv8L=stG zfBbt_)wpJ7Q7y!Cz=qxf!QiWz?l$lh1DPGkQ>jYPpIfMRLhjyNKNkj8vZv0a^g=yk zWqo=!kcX_oJIz90^G0=f2E|gVc=H$Wkxx0^Qodi7IocE^@f0{&cQ8{`V%7gxSKB&u zlrH2Mybc8Tgb`e&FCMuOTc{{M7U&|SvcaV@G*fdb2av8F)$|twt{&0Sb&Kg@Fsg=_ z=W1T^#?9$3M{rjbytAAxJ*O&;svM{rjW2dsE!4-v(Vqo#_IQke_;(SkG&~&eFUsN3 z+f%7KhwR=1=wC38G1ih!*K4qFFC8mT7>kFe=r|*`aexAyD&l+ljRYOMx{PnXE&FzKDFVw*z;uV#21_afl z4@nQvBigt=GCRO3`pm$b2AC!C2yk!4oH-7p`m)IlWfeN=T3Yd)S4Pnf30&b#b+sq~ zW|Zi6NN%wAplGT94CzO!O){H>Q%P6JpqtO5-qGGX7AF+Rr5R*uw2=iu(%2?;u4(&A zyymzr##G0YlNT%fWjPyUo2R`-qpuHaixsma#e8s1qWd2ax>H>7G$L_{qyGMjM=)Vu zD(*})dQ^cEH%&lXM_kKqhF#cZ9M^M zy1_VlIw4&zxQi`K5uHsy^>J|7d68{9VF^?`L6WFk9A2-7$+tCujV(Sx?Cui$fX;Y; zC5u!FK>E~Z;7eeSyL+aJ)bIy9`xm17KX{DfcWUuG!+P~C5zpG)!GqFY%%5L`e1MMq zca>4=b3vj0{+vQWeKQn3|)(Bri} zEY#*DMY|B!r)JLQM%qHS*I8V0qEt5_I#`}D>0HswKVmg%AH;r!KTO{bis9dlfaJ%r z@0mT{6c66$D+^I!2y#74)5(XLp&o zKvRoArsg(H;{^^l6eHljV)t6;vq3fVVjo;WZU^<6D~2nd=~l0vt!aL)v%yxIdi1sw zqKr9COakric+UUbs-B~M8bA8Uxp6|leP7~07|e(6;f%pdCQ8_WX=vyeEe2_aGL{bT zeKA39koBRKwxOo%j&A_33S-X9q3!FV*)XdwEAJq_{|O=vD!44}VPU1lk)({rlzE8- z##T_PJnZq@Yl)Z46~>gvvGr)DT748nvYF6djyot8z7yB|*9X#{Q3CX1`Co+cgnTfM z&IjUdPdZ`%heWUpr9^!DBIq5zkZh5Y?LQ?XI^}PpApO>t4 zsD+SLS3kIv$MmS=%>daxrQ%=ZczK?qqWVcGkr@s}h92v)M^>U=F3SWB3+KF=IL5(l zzJ2ry^3FA(2yFewlQR6{FVE+q&5qRD@h2BXMatQIvgx9*>w^ia`$ez{@1&qtJnX zGtqo(>VTqc9 zQV;=oZyzHp4^Vs${J%j-#>QJh?gjO^lE`kB9rE0LTP{qOJ zfpZ1E%$%1OP$tI+&|oIqMwT$#ms$Xun)vo{c`rrHaM+{Bn58fg%Q8mCe<3TV? z=obXaP-jj?#n{_t_F@M^0NNxKTu)vEve37wqn%%JI)=@AV&!9#r;ymn(NJw|@)OY{ ze%Z;f1D4E3{SUtVKsB_(&@oBjU%u*+zM#3^xf&If#4u5h*gKfm9joB%AEQ4F*sBzJ z4j>|9ALG7@*+y*K>Ay`piZ34OF$>92nQMhG*=lyA+w^kZuU%LV6|s7zJMci(%B(~l zsyD>$o_3z)kpn8Fe;sQ}NozNSLGNQ>NB_$0Db^7CV{TOcW+A?pL50~`NV zCp3K2rp9*Oh{-`2$Q$qRBzuxI+R2w*Za1ySvj^kU($=E}gHk*Is*N?Q`yT&%V#|$q$~c+0}H- zs;-*zo#P$v7`4`b-dz^V&~maGmY05HZ@}t1EZ_}*>ryfVnzH`C&!GRl{nEh=#->ys z48KvYs7`~Psj7%(Lq;TCD65D$X@ztI)cp3Fy+{AHc9b*jhm)u zPtunRZ*19-eR(EV{Ng~+*EC#XYi!x`5j)mzbPWM=i6fBgm(h5~`!}7_o)o7Wnz(R> z-Vil}3Xc8)<06OM(D}0YUjE2e$SCM;V(WoK0(xMswHNXGlD*PZKK5isXf^TE@rEvf zwl=D#KrOCnxP{nBS3$eX0FbFJ1^00t-g#2S)8CPSFECCrE{eCSMNHll+j3wp&4rk{ z@p?LS<@*_wIi*s7?teXg{$9Ny^nlGkt=rD@V?wZe-VbAUlqVj9YUH3)Lelp361AWi z;1z)+SwJaqw!$8T#i zx!0eDf_Lv$k{>i9h1M70Qa)COx@AQ&`lIkT{LMduF_y=T&}vV|jJig8G_7|Z+^(V= zHhqMP1a&=Y;}=y}lDCs=z>?WFg->v2{J4N9>d)}w|Kt^E;EfGJR>=d=@DrqNVDN9% zVSi-tftZh?_OBFx>oK%Yi-zYkiE*X>k){ySi;D@2iSYt`#) zQI4@H!^sSbbOZ)s64g*J8PB0)Ac5-Tc$Al_+7aM>AjRx#;mYOTvVKq@p z)T}Adu`7vp@H{J$Hdg16;NuR;nhaYa{Vn9kmlPA#!=-y6ty??bn^WjzA^2YhlKXWa zhn{fn@qxfJS?TYSqP!_NomkXM)Cg9Xb*dgP>KepdO)q*+bEqT4*L!czRkmbe=d>K0 zw?FFb@HU0;Xa#eV(piwA{TQQGRr_1Mun6|0g!ZXn(hbv-f$e;kWZu|eDUn&igFN0p z{o_%mpG{FyRRChZ`$_x{jstqj+~+a%+D74#av0Swr>gWgbnLpv>eTJKvjDis$c(}0 zcDy1j?W|d3Qq?JWrPN_}gM|&=qqf@+vHU3yQ=>Za8nLGRE;gHAmDPb^9}AP>F;AVd zODdLTaD*=I329w=3bta3CFy%{1~$b?6cku@ihbPXrVQq1Vr z&c=?ArAI3tqlQ*o?4{^)ApqM(2?z57)#j5R&*x!Wi3k_>p^}jv*)|jp3J_1Y#>mT5 zL#}UIE0c5 zU(pGScw473^)g#U1aM4aOTWW;5UMyVr`nK)&9*l#V~@~J(qf)Kcbe89C~-=~({_mo z43s2On)m_~i1oFD{|G|FrLn*5H}7a$hakn8nFp+`&@wDcE5s_);5fy_q`eUkD7_6Q zras%HM!Y*kg8e?L{$6b1R`h$z6{+Z7A0$-x3DPQ?fIsr_#I8;4HsLLM(dFKsfmuB& z6!!W?sf&ACw7PeG)6(E;4NhbH*AueZ@#!(%GBbLbz-SqxH!69+B=84f`8}J&S;0lC zI-Irshb)hKGeFR8z4o(dy~F^jU9*3008X0XxzroC+TNnAqnGpm`tz<7kwJEdKmsJQ zfYs`6t!;RI*y++^#M+2yU96rrgmZ(3h85X%z@7nnYe+rPk0KU{bZo*+W*SE3WaDH* zCqE8B>sk6f;E9^eo7PK{)>2R4tpM)7EOXr{t-Yid`n?FA=i}Em2aT$VCMy)0n-Q?N-D|Iv z?cpa25`tng6Vgo&@0sDTCaT?Qr=Zr=SSOeasIcN0k59H%DUuB$l-8cH<);)>l2-ea zRU@lmt__z?G%7?cVAzNjCQKCbSnZ_Xyf`FIdBgrx$&TH=GN#dljhUra#0aC=sCsVx zyQ`}vY75_(vGyqZTf#<~o@+3sj#dj?k3q{Gx__;jbw>t9fPCjY*avYuYu z>+i2WK=-NvLq5;+F6e_@_;g7+cF=V9F09?SI3}w{@QeXTlb;&NCtx+I^SYkY9b_Nh$_1!&ATO zfOqTTKXz4SH$zWsICz()f%OE|UZJybq!7-~vR@Ef+{4EPvTt|jdK$cQFFz>SKJq12 ze&p9l_R|{0lp#bHUe0myTFyPsz`hloV{_m$ztO)C8 z!51>IaxZ0?oriisxRt|_iCgOQeJgh6a=bC`UA;w-ont{&KtX=OKF>iR@~SN&C96eWniV)WF&@<)FzuGyeQ*@E7nZ+fPsd zdLsbiLhro909rJi+xt5}GGRQz0NZ`W)oMDPK+w+qnj&7qI(}V9e8QXJ;+7G52AYK) z0Us`v`@La+?YzC70>K(cw$B=2IN6WCSLyz?lk@~&v!ATSZw<{!qMi#6!p9flj?L3X zV5Os%bkIv+EZadU0SGlfp66B6-<#D{!?KimO2Ox7F={V-A?Tzec%<510r$WPwJLB` zgi3eV{4@gEw$=K#v#8IpDci+2c$!%2KCxi?18ED0Z9KZTRc9;`k<(uU@fgkbBb;SV)NTlnsvTHwc z+O4PY&_D=8L+DM7aK(y1K(_l{Vdc)bAiS8&baKC`E)KUMTOpT}C{b-gawqLWLARi*RZA4y4vzdP9nHo&4&uH_n<m$qxP>#i9bWy|Mz7~Yl?{fjbQShM*2u$e~*u~4t1Y}y>;R*7KS%l2mQ{- zx2X!vNA*ABA4`J+c_u61+03y03Hq45F9bcsPX9p&+hV#%`jI`Na>%u%H8cdH+Ejtt z10Vvq&?fVZ(#jo5-fg$d)t9@~tMSeJg4^$#uPrZlB_@FtpyW272au_Fp3-`aJ`5aS8!dGeX(YvYp%8jAh_KzeaFp;LQ3^u_ z$b&b!l*&pd!}YZRY~C)c^q!cc#t-m#^EWpF=e)E`fG;3_Uy%LjJu7?@{KqMQe;wx6 zIa%Cx+uBoQB{`lExNvXC3c>ALzmo%dSux{0T+4gd8K29;>SE?*rDAqic*VcC@SMv709R+`R;`AE&Bf*-h99KY(hys1lO$FB|l}9NO9Qp9XIZkfyyR z?ERRMO=G7C=e@zMbLN;g@1hq**u^Ek|E=32d2)b%j}R~Yie8hwUP*f1LM zt!C@0j)Vf)M#0Xb?-(sF@q8X%7ORr|llJF80)3Oz4;x$IMovF8be20BtT%@Vhaqd; zgEr(TMG-XIVQPAeL>IIOwbf@)^;#5VS1)TMZk45c}($%btZ)=qvymX*d#r z(e}w-r0uG=#;nI`I-xS0G6}QKgSTK_)qqF(!kko|4cs8N%;|yl;yy0D$jy-lL$X;~ zrp@YXL*?{iJ?-R8y$_t`PfXlmhTaj2p<@kkt4Q7}nx#Gw(1y+?j3VBnSvG@QPL?`L ztsCCfaBR-cHIB@(O2|1!kZ6FrJIfgyxmjh)6;~cYT5LX?>(Sl~4O98L?*=G-*<_1I>L~V~W|$&PnXX5=C|v8ie|H7X zKZ1@i_1w= ze%Goc_9d-sPW@z01={yRUyqXN7Ro)GyuL%NE@zqetM>(&V;mV)x*~@!2X0n~RR)c) z&Q6i*uN+Db#3-&CZEP!s9q6wf0VXWfEiY*t(46kpFH}|m(Dptg*r3#0cSfYUXn=7j z<=lQ`$n|2hh1tszz4ZK<;g2&P;J#2n@TboK7~wzrKP&#_P3$)g{$T~}=S0J-!xhUe z^bpdB5fTv3m{*i9o1E6PgH{KmK(ESumiJ@m$2kRpC;sj97=hbzx7@_C@9|m=Ypj{X zBQ`$XR;nO+qY%EOtw$_BK|S?Xw{l*mI90+M2cQFoH9Cj!*R+CM>4m;e^7cHMfhei60s z6XbT+jjgr1AA!ge*soriE{>CSjHOM}p|gn3WH;feb?B3(0dd>Uq1U_>$`TCBta{6NVm$c^blipCJ37t@?6 z%CdQQ%UM(25OXH3*>1P>G1E%-TV{-@QEt8Q(`dea;gYpbLCt-KHqn*qskPF#6fLyJ zdb=LHV($3cN8My!EVr;I2hlZO5ylKedv1i|R42VYT0Y}+<*HfCs4c6TVocfdaFM3P zZ~5L)VJ8NC*mr9)VVP-Fo4!WY{1XIY_f)?XnDXt-(oxF$t{YSxG<1PiJ=__Rv&7d= zb{~s#LDERuVp9x1e5-IQGwq_MVY$Z6o&zTK(Uum!YrLw5cW;Ey?}_t`RIf0DlYs#N z2e{};rfNS$nd z3VGW{JosSQV4fV=kFOFnRvRU*SLW-S-Tp0?4PkYhP7gpTbe5usR)kkW3mk>X2fZ^k{~xJ*DKIqX%z0KruToUKF12yrVmP`57l3X;z1B1pi`akgW(SP9Sd_O_u?9EKT1oR0Ez>DR! zt&Ly=YCk~0)eIs)O1}#;+x}-;^|$Rm_ub6{ZnTeqn!>0(JuUzT{Kt0OtNOH2$=3QB zyEqvXQ9-13loD*?S3Ai~NxTc&6WRUeik^hLeu?H!Y7*C-RNKV7RcBUa&oX{#EZ9Sh z=e+=|)F05AdHLJ6#t3AMJcQ$QRaIjPv6_BgEQB$upP!B7sv_nK#wLv^4q_T@E2R29 zjDOz9yI={nC8Vm?OX|d6gc3soq+=rM_zer(%BO$(#=m`g_yt)wEW<=A#&@yNTyUH8 z=`*uh&JCtm@O4Mt)WM-`^*zR@7YVSmZF-;nM?px!%#LEi8>iv`==Zt0tTcBR44nPJ z=wIE2xODA1hmea`I!W z<`xqo9au506;b&ZY8mM11mI0blWMQhar=%epx84}gxia4MPqpBQ4>CIFvWJlNawDt ziP=~t_DrZr1GV)U9%b6xd0=D`hc;p2)B++J@fA{R@~{@05Yrb(Ti@8F3e(6hb#g87 zho{$0s68XJz7uTyc-%ma?W?$CZos!!o>OzvbWRNN6JDqduW=bwYQC|sk4(a) zPdftNhRjf(PXblG0} z+W>d|pL5aeKc}bZsOjof(VJnPmc(yRr`&9-)_Jn$g0d!jd7H6njUJ6W=E8fJJnPkl zCEkC|bpPs0{u%VJ_mH?2v3nC4Tt}%WTR$rXDU!B5rq|mMHJc>856Xe^A^CZ>t=0Z( zzWl<^A*5D4RsG~n35HdhrioT=mu*CU`F`@OD4dX4sh%mTI$eXgbu2__Ditqm=_hEL z!#7`KEege2bT%Y+%198a0#*>b<4I{TIiyBpa_@oEA{hS4YeTd3!zqX6Ru`FjZ4Rc0 zJ%?R>wI$~_%lP6H<*x(b&JS>S`ov{`_<*pgwsg(iP!AAPpwjoHus$ENir${kg)hSw z^z;PF9iU>od$L$NW2}1#Dm3=5+ex=IsaFr`2CnO7TGxE;zTD-N*&9~aV;DU}Xr^ca!mTze-{Did4=1F3toj`= zmSAdj)wK^PunJq#(Xc&uJmv6eXGX*zz^E$}^}SUuvy0!GlEhF&88i4w(iQpvkYyRY z9Rar|f6Z@fh>BQVrXUDk)rZb>B z>GLUkst@5DCt3AfD?~d3;WS&*9-W-`_9gb|EcYdoYm1S=7B3!Fb!XG;JGRLR;`?E| z_Mh^SAppK@_IBTDK#0+=h?#A_d|4Uj9B>LYZ&9Dq` z5l<0}KwudQ-DYeCQnBv=4hs|ypany~r?Ja51%Kvn{->`fM8A`eigrH|XT!ImA&=g!%RIwO&^7c8Ta6|*Z9R8BFp#4i4PxoQFu_w$`!zTD>qEe zR1OKzx~PA^!8hO4gNFXtP+PI7A+t**)>0Df1@jc@4xCUYISsHTlAxseM_$72Z9stX z5u?7Zyk#P&RKZELC%A>Bo6J6WxL1IL>^V!v&IiFbxu@6XM01KQk-842`=S?l1FE|h#o^oc zlZw;N#sOgxdgWpR19wqEY%Z5)ui(I9VhC`DP!HPAzr6#H9VnV{Slw{pqFvmez3ddb z{GMaI0E1f2ID2``#_MP+Zxz}b!o@k_8DLEvRRBKxnt#_YitzmkMA!l4-*ZPdv?>gS zGocp1Q5~Tx?J|>ubrqnPPi?~DZv+Ctx88$@RfI+}002=7g3lJA^fCwU)`69#`>68t zo}R*#8sxQks1CjSbN_%o5_EETxPnpOlzAnmE2Y4ue=*aPYk{#pETTFhv{(gSa4lDt zs298h_k>*niG4OFAh8cD7RPdm+&;%tSkN`FhvfAdiK(oCE3-V`+z^nOwvj__gd{Ok z1N*n~2rf-J^Hw>7;@1vXXl=aH%gYm&Odb&NJAb+#wBfP1Ts<@G9rm5WER=EynXejCfad+uG!oJmb?j79iC>W91VQX6brHtyBU zl=5cQWr{M746Tx^K%!f%6laR#yGGYlK=<~%!F#6LX(st`BdQaYUOaKR(z$0fv)gme(e*AtuaT-}FZ7u0L5Qjf0z0(B691;Ho65LtuX+XzAGvu{A0p4qO; zrBlmwYlsGnDURIZzG{)K2A6!SH}@*I!*#k{~i7_fyWt?HY3(zUCp!`pQ`*imhgO{u^3%&hF23^(e>= zEFS*hK6@7Vgr=v(Iwb-qrTQ`stR$H=!78+ENP|@ww{v}9y7k&uPy8^)w?%E)bvY!) zNor0s2~lh5#YIm%F9hhe&moo^L=%g8EPd}}1yNGB?0IIB%|731y-vcW=toqLqLV_q zyd$x7`!eq3R@HnS9CjcGf6=2ehF^8|%9~mtn3Dc^?ZU?POw7LVUMQ{qL9&f9+?BnyOBD<7Nj{O6ekMup3H@NinR_ zXT5^bAGoQ>p^!3oX~u6iMC4$+mhluHsl+&UE0pmha9>xwFVJ?ZF{nF$h4--48Y~(u z$q4FkzdruHOdZSO$|e`Aof{Fqy4K>|EtVDs20Ta9Pxp0aIz?4Cq4`%8FH5Y9zwER@ zO$?#4P3hP7i#`>40l$2Rz{Q<6uo%fm-eeA4e_lBSAceF_UsK~geWH}9jiHV2y z4R#;>`^>{78?__fg&R!+nix$)MDDpt%{dR_4MI)AIf+HudToD%;&qIO3~gH>59y=~ zX}8(d@Ve|c@|_mY&lEGJ$v*>d@Y|{wQQA4jIddfCCtoLxXKf$H3U>~{XpzCZ%g=D* zqT(z3ydvdbAf3pL5yB8acu(M6;s@P4}O4O%I@vT@`@%h$)l zgg;-k8t-FMhbi8b%+pv8BPu`FcGR@MW{H`TlUeB~Kk zV@>cHw+Ct>_g89tvT!S1=Z>*3OjUelS*Zv6tT>YNl)RAMW{s(LhXwPU*hA6w5OTIY z2D=_Pr~dWj+}bG}b3L1lha)RaJ#Xv5OX5*COzAL?{IzllW77+Xbjz_WNF?8bgr`2} z+$_8K^9=pG^9vy+?0svDXo@~-IKrb)-SQYk$w!!$gt=zH+>=lkt*l}A+vO&wVJ#o} z=P_9plQ7cE7v=cKv3{NM}33Aoq`AzrwpD`9-$MIhUw^05qBcl-p!~}hYU9IPMDt8REuwSCi zq5sieM{@+jaZNm>#`|-()lRIRpg~1zSgBq|$+y?x#&~a3dv)vop2K-Qqdt_HIYP!x z;VY0UZfd3h7s4xd8>ZXUPFzycejPgBbU7dWgunA3;NGgZqq9pS&+rhiBnR^XkqH}u zFkuZ_`6ozzGHAFg@!Q}&TWv6z7NarEQuGSGWkYbag^@|<+~|Gt zSfZvxLaaV5Hdf9xbom~Tk+PHCjAOrpi34iIeTGN@Sx0~Ahuq2-C=v<7rJ;BtLCuo} zosR4>t5mxCVtA?^tTkVegw53b_nd0Ul^CqoHubqt&D3vM3h`$;-h5!wA1hYbgGqbL z`OZNretcetO0PwD+9M8cbe1ATZ>PQSf5lC$7XyHvK1c~T5j6yWRCJB+J*L*lr$TvSTkerV9v?y~mZ7;}r^pZvrE|&*?~TY>T)N0lS^fFeE~Dr3dBO4; z$b+@+`y*Yc%%jV@sV6S*8rIUk9Zv3VElJPB!V=)g{EI{W_x-B+5b*&9;~v+$JzJe* zF%Sj*c*u8V!0l`}}fDkQX zH!ew%Zgvd5Lk9{$2^9gFHGxl37ZCQ7On{FxxBxP=CQz?3x}P{2g8F(49n{9~hpFQ0(mamS^K>*RjZLwSTZL(}l-Pg7qR=+6XCHPO2N^EP*l0dFCz7rcvil*U;FI zJn}6|Da^U(QH&X@a35Q(#MT1kaCz?s0ADNxG7YCp#W0Bhby0z;@sVTNAPf0t?lZe- zn#}DRvFM)SqQ{}%*^6l_pK7@b-1f7jR;Ih$VW3ol^nh^`IkJ{~Fk|OYPx!(41Z!b< zBBL^hFxWMzD&o~z2VOb4o{>!s6=LJ<`zNy1ujOc<5dg z(kJT~cX+vtxah$$Tw7NF(~Rzmv(}~iZQ!DxFw=6Ol%3css`>!L%yvmc=m)c47G7dY zWS-gt+VYrN120qTZ^vkX62r6Pt-CXZh{wURd&FRY-obD{+i>vLcrwvG^KC&6Pv_~X zfs|Bdrkd~p&b`8i;g|U@fRkr)xWn;Uon5C4YH9R*4K?AF!h(_M%i_pmkh0E!lfD_e z3Mtar)&2HuKRi#*qoM}h{a|Y=y*zJeF1DgP-^T{)h9Rcu3%v*=e&2L7^Yr|?HKyJ3 zwn4%lnW+1U@nCu{bj0=@uE_|?MI}EQ|3F5AXx4@)Grb5R;nn@*gQYZAO{1N6`_!W4 z?HIE&(Zgkc^p37DkCKmVaSw@^Dp~nRn<@llf#DclZTUZ4$^ZN3kek<+a!4zKNpt(I z%;S6Nu7e!D>4dqg8T;DNLojy)Ah?KynWe{|3@pRyH`xe(GC2gc8L$}iQmMX7NBCX; z*<8#<_7huQdt9_O$b}tZX9u%mxOw*4v}%gM^Zr&ui#)0?I7oBs%#hl^@m} zCdoOc>Gl5k7cqrQlS%V%Xm0K)+kHxTb7ZO0lZ!aSf%nU}?MDX1#P`L{XCWjSb+tyN zwIw)GSmGZaX`mJAEC=%~SvP!CqvvZte5c|IdQpH|vY750k7T09+8{8a%twlnmU9Zr zaM3x3dmMHTuZJ99EUn+CzRA8$gC-EC=F~#DlSo}=Fyzy|j?+c3s$ZxFWG`!bq)b`NZ-gzBk+Exc$e(2-=HoNqq zwMQ-a0Kv(>-*O}YJr&h5@BlORq+;B>00U#HB;nVIQoA!90Riri{AkZ|Qqs6VR=@ox zZ;Z6Wa6h{3hb2EFb{|u&wL-2OIpIoRaSAr}94LK0DQFW6zPy~gxW2-Ty2EKoTa}umezBH*bO-s^0t}HRa~4pG~d)2<lrto9@f zs-`r{|9^P5m85Z16YF%KiV-Rex$bes=}XI`F5Q2A~S^FSo1w9qBvfU+=?M z-pXpU-~}^xKOrz~j1yZRAsY=&(uxFJ<5@Bi*BIn;U-kzjL5F8k-_t}2_Z{k~%6)qp zv-RX9r_(GU-~hpBigPea9{ODUSe9jxou*LK;T8&{RL{-<7hKlX(9AqQ)#tnva5@Em ztt`5no(NhMLVW|dSWxuWm>B#=F}?cgK~vDB6vS=o%#lVTP0$Ib{w~&@9=sF&vLls%$~F{a9?@1kJ40>y?qojNwbCOihRIz06Z|h zhPNy-8?WM^D@i~&6uf4cEihKoa=NO4b}I4DH$4`<0y>zt;LDfwoa?Gd#&d-i(BmJk zfnK6qky%aI#S@tT)g#ZjdbgEqnDjA3Tu6;Es3gm$zNc4>r6WvVK1QoWGOwaM7BIEb_n-JPmQe!sCCt z^^Gxv;#x~Qee25iz0!C@p~3EGj+Ic&$qwCg@$EuA|G3ST18cq$F^c_=!^ldC@H)Z# zTWz_}s)aX?>wN^)Lq+uGTY5d?<2fD=7j#}2vd~L7D5DtwvSDTH}NfWFrgOlUff3WCG`pa4uG!N0qEMOB=O@9l|-^gAKKBJNxVbf zJ=L;5$zd5N)M^Sx(Vd@DN zud_Tb!mkezVfTUTDCr>o*9GpEyP|xb%&#{-rJt!+qDBk`&q(|7^{t6C{fE1knrOL6 z`e_X60l0%NP)F0f_UYMv7qQd!=%#0k0f~-;NqXFCu6~BwMWb}<2-n>(AI=3=p%X)f z;!QnII$o53`p42$w{?`?0n_w`niSMWDuS6d6l&qU^h243-yxfMdX45$LwX-V?eEtK z_pFCwU7vtOduj}nM>Y%==bASvB|r2Kg^QU%z6KjL1>A>w1@`c0NOVIv!p{|7bA0kH z*witOr7JJlVBiwz1N{Wy2xk|#3gjiSxGnHdeE5cE=2(m~dE)4UE8wh6?@|{)Ua!fj z@=ZsOXB6$=vx68WzBEODJWa8m?Nu*B_{FHm=&O8Popo6_gkzC4k^UqD{oaf~2MF!u zKlRE1f()Qn9v~Bg$FUnrRK zviQGO)DsTG9$nAIc98wn_ZqJGOM@}O>Ic>1uta(1@O5q4%gdEh+u1MW6}fHlrV2M z6NWaK1fyJy4_NaOesPytSheorBzwVfUxqouh_Z=3J3Sf5oPiT7eN&N6GJExr0sm?` zLiCzLQ6=D<&@Ivwi?D~po5Cq(U*pV2V&{jv4TtC%JH@^scb7gYMnanzJ$-nqHm{=dERm3% z8G8mty9~yVp*~flDEe*tI*8c5&xSnU9{u3!-m&Q?rG%HRqvo=$xeqIm<(s1X0}s`! zi-~lf)tn!{3!$?`Iu&8KVEV!Yvs?lm|L&+e59+?@Uh`)c&ys)H)fgJ6%g4^cZj2KqeT}Z)T)Wh>$Q~ERMja-Fb1u{8DEk|vBV7DN_Wz)KZ>}rIv;gFsZh?_5pv*NAF?fo zHZsEfa^5X?)1fsR)5DQ9d3qE=!`-&0_Iz)(MYVlSss~rOY0PiOp_)yJ|Ec}vqx(6J zXjzrDPbqLj-Ne*73*h>Oi#jrbyJ1FoFX6uWr&}c8APehcz8!bC>EkDFvTGAwStdk| zH9kmqg;7fJU?jbxmQ7#~K1?2b^Mv;E$d=^>XLsK#zO)SLTudM7%o$aE(`CY`{OScn z5J3+l*Bwt}xn%wX@&KnZO~p{kz^B2}eVi$YLhl7GC*MgaB?d}Vo9Y<)t3iH2^?nE9 z6y8i0>WfHW!sz6wqxt5ciQJBkuPS6Z{iq*u9NnMb&r+QB_^{bqCce>S;v@{dFUJf; zzDIvl7?LyJYsXH`;QBF;HqpY}*7fRR+@-l6v&t81!P$qolbv>?G8S=ru?p{EorQ`( zAHSN_iHuf@z1oReQ1r1sx3Uetc^&(hQv-sUgas1AkI0`C-`Vd;vGEX2go=OY?LQAe zwV)~hyu@XsIYaUX+4{!ig=#J$EMiQ|&zQ-rM7D%?hndP|zUh5-*K?nY?xou86GE1H zP@;eoH}7jQTMBZvwozK|s_l@~gqFb%SR19DY>l8RgZXr>HCBS$7`<)C`wkR}+Qx<* z589QH3`(3a2Ed%Gcd0hSAzUU;yEQwerOeqKseE%zpk(>Rs(I7+r@8Ji8$8{$th_@@ z7^}ts;142@CSLn(}C84I1c`C)=sMH`g*H2q51``{+~Q>0uO z4a86xz`Z7SxHqOr7 z88xM*k1{5HhTpD45a-M&%Aq3-v#z_4jbNSBe!Sp#8O%O zYt-(<9Q=50p7Tu)Pt4^QdM=^djd|yw6_D3Wu=gEM2I$9nsdn2tUZ-Ci4$;%i7$>Fp z`$-lD@1gk}ILeQJMa9}GWq4Uk(g>0t@?pO_Urn!;ETtebh!Etp@xTXKy89X!8HeVe0CU%haZ-^xl!=Aq zhQB`CKmC*Yw>R{$te(~0j@A?kMIK>t$1eYsQuKQHx3q5)yFnFUk2<2T?7KM!1R-(XNcz^Zeff9O9~dfm z5)P?a9d!kW&Am6l-1jif+1vhsEZpPmnq7$VUe)P~uI}=J&L}tJz~vi@`VW&*;kF&o ziFs?mWdBs%;Z1T+EVZ{ecCV+LMXp0fr>lgf1r%A}QWV_Xbmg+0MU=S;$B_@Vl832C zo2pX>tyh40FfdgguoF%7tJqAHIH_N5Pe?hh+uMj=_e{Lr1g2jdz-9G=I2yuFRuex<_| z`qtB7Jwk1wXJMZw2Ox)YI1#+XiPTVt8f+!pH#JW#FSM}skBjr48p9CJU9z6_Xn334 z{Z3Ge>g7sfqyyhgYMSu1>CArmtyd=EF{#5vBcfV!3n86IeKz257h5bQ%$Oas&akoH zgZot~1N}Lu=?WUkYxsi%_}K6MzOWBn*1ww-{i=EfqEW!(_w-j`jRv;5cGx-Ju*n4+{V(%La+x8`avoYs@5ddU{z4 zHC>?RLmq@zzV;#*hjtm5D>f+z{|oTN6!g}B`nPR~k)0CnEWX*>RAO=`DR z1<4a+MPZb07^qwR%YFji^Lpt9@#HfD%23hO@{ciMP6e=%X2zD~EKiI*ALYovJvDli zy*vnzj6(;g=qKh)Ow%AJJ&fqW3_gWkL>;%;k(Wgnn&o8q=MHHSv$Y;cRo8%jI$xwy z>Y5+txQ^4C_s^4e_xkyRl@3XU@X##u4_`CEvo`J2vnwyw!<9pJJ(!VJa#Vca`X5M9N-v|d6rWt2g5x_RT#VhAv#T>H9l3*dc zD%mg0fYPfAn#!u&oH_l@WXVvEEK@7=49!?9bGiZ@j8o088<8{FiRHWrS^cq2t}>MB zGP&q91F(u-9-NWvmB2ESMV{(|6DvW2Z0G7DQsQ;p`u{~K<3CpS&JVj&gEp{zJU+Y) z17_UWj-Q~%|6hWe8YzdDm(&MQo7UC8mm%sk0hA%|67|p@HbC(JGI^OzIPDVI$@6QA zYD%A-kH9!Rlt-qclSe062Sat{Jq>Ip5GW-+0tC9d9`ubLxhX*rt&=}Nkc^yp1;&-~ z?pUd4(^&U`Hq(5F{g@zv;<>H*eFB#r;1qN;R=S=LqG`&e7qU%+y2tI&A(nzC4c@kxW zB{EV2_dJWhuLEZsZh#)FYgDnlw#b6(eXysUCqd&>Amv*uf2zf>kxJpB`!p^TO~ixk zv*?n)CSLR#nxR`n)o$zM6_B$nS-&EyV8txH%NwNrv1oB3fUQH6Vq15-#JD?*<=D_< z`A#fIo>lu?{cgwO6BIB?nOV7fxN<9F@upHMMf&Kp_DIPFrFcx%yislZSt%?16VPBA zmdY}v=!{_0+QQAcd&!ItPrHrSxWNKFyVesD(05Fs{(edoR!1jo!|PKmQCRu3Cji?1 z*avVfe{3M3rn+eeWW=j$5vW3d>!$up(Hf;LCN}FPE+-r_#Zc6{bg%y~f%?JIy^v0t zc9XhT^hJ*^OvedT5}cF#X3djJoUb))6;NaOf|Lc!|go>1YP}n^^*1E^QH#VvU(otB5UqaoWAFwpLz_vZ|_&fD$d^8NW><2ndEqs>tPGauGm<@8C(Pp`N&_EkM@VNZ1E@lk{I*rZlJAen?iT z@7Y6kN?T%+SkOsUg4lA}(MLLa@(dYBF4Q@{q&Rxhwm-{{R4!wpQtGK|*1VGNz;lAv z-1D|>lJr};6=3KavF7P$*+c6BHhXZzn{OP+Lw-XLnT|o+d|tRAnFq zioX9H*GvD0c5*_omM=qDr0JqWud@^en)0Oxsxxlgm&DC=<&I^1fienx{~t^@U!mWn zkCFWZ3i4!k=`b|0ih1vepsN275f-al%2XZq)dAqvk&_1i9oPU0Y+V3Atp$Wa=@Gz< zfI$qsbq`$iM#jCCh4qgDD$zed6tD&!Nh(OrEpdeXM%}aki$YcS8VO}cyZBOwMEbhH zW}FGp=aOaJj*|vC6T3kE2zsBZn^+|W;|hQS8}nCQ7F5Ha=b6Jx`GppXyi6DcV=|X_ z&9q)4k_bnrh>uGWY1FWzSp3-?GYZ{uhhnq3n(Gu7hhGf(+yfBQy(#s}W(m{;=%!S& z%0H&954jVq0OG3t7vhS-c0&fe#@>PcngwN?mc@@Gib}ilJ58V*y-EKUd2bySRr{}t z4+5fqAP7o#Nq55tNC`-HcX#I?2+Bxzhja{G0#ec`-CY9GUE^>0*7p5=-@VU1*Y!Jp z>~sE@i^cp(lzg#p0u`D3oxUa z2WvDb9OI>ZY^cI2fxazbXX7>EH{roQElKntX4F!R6;-*>VShR5v(?{T&!`@{9t1c{ z2)I)tqF+h!8GsJvlB;NaUeCcI-*U`q>5VJzF9!Jw3vaeBN3|`-zLgd3a9Fy*IG0PT z4e(P)+f(kLn->~+-MH+0%e7?`*mVm2U`~_vQB$)|BpOeZkeDOf>JCSh$K6TkUm5^( z_6xmzlE>y|<(=>iLRJF=9F7{FIk?x3RU2Tqvv?uq4nd(?ot+DvVO<}&%mVwP#S zc$=bxX5uo!j-2_Nj8ntFWaa!rLv4!%;TMEd<<#$iD5n+EDg~eejQk6(2}&mf43K7K z6m>|K>PX-{q4$LdJ%grb&%%^8dpkIA2*=mEX-PW-NF9eKOSG&Q9N;et3>pxb(9#`u z@-N@jpW%0c^!`?g2?Pk=@+K*hBr=SR9iJ{Gm9pqzV`ic~S$Ek22Z2mrc{##eCayQ^ zi+yk{ZQdw^6V}c;5}WA54l&DoC~^1(_G@A1jw=edLo}9Ao(jV9!Qz=kOlApwT07ZE+#Le zwEalx>bJh>`x=;wuk*N-AOsUpFV(dbK&3(Ni4l;TFSkyMMj$<%e^vyZ-BL8T-`-l2 zUh)B@%(ZGrJ3~HXxC^lMfhjF;0c{rr6s*-@1m=p5gmS_=N9L9)n+Hnu@vI12^h2$1 zRqZce)bE_nvl|i=n$oxV29)rWkCih9rZSD7pyE785B)H_9_WRnpHQgPzOj}vIA%)e z7nfV~Mqf4tJLUe}!~%*%L!B#0WJ#Oh$JDXB9@E-u&UUmeEj$N=NTIi%{QZAEE(!qHF~MzY`Qq-2erGB$|? z5pC_zpBLxr$rR4+JQWt}MOP9vPV2izO0bc8bn~TekyC5e{V8I{Xz;7JCbj}x>k&V2b@R-51&L%#>N4|Q%2CzEZiLm&H=t<& zg~5C!rC;b3!x0rbZ&R{l$huJgALgQhWZ&AfbI+iamWJMRn3|MaW52VL*;|3f^|RUN zFV?cQlP5oh$0HI-jM;rZU}0t!%+WmG3p2Bv#!8K$^zWYW0!V&&x7B&PUT5dhdpf~> zfKn@86dxrbuH~m=gJ+%OzjEd zN}@TAleUqz&0uCkC!-X6)7o1Asou{zEG@P!8}`nde|b3Xnegl*EgB{IUNj%ZGml7w zdIJNaAST4vQ`>6WQoDZTx0mNXK(7h?21WN`u!M2;_` z85IRX9g5IMGfUC{hL%@CA2Mc@A;XoBB_L7*=m&FoZf|Js?!dQlriJx4_xR#@H)rva zU-p$bw^HWv_etkgOViGLu9TRdXG`a$T3*BPmPV<3XDoB`+WzWX{^lBTne2X^vvjgY z`rAR2^FnZ{m>tw(lKIxb<|Lh)lhk4OVMT@#9%BGcy>NJM zi#8^+AX_srALlWbLjBH}J-~a)O14%qP_>E*h>a^>a_?;h4VY#PBUIWovNAQ87~RTu zCogv;cfy{cu_5DPBr6n8&qIuykG_o>A=sOhqSSJ1*b(A1HVY7O)3r*v8cFD9#6|(k zQ-xfFGkeT7*mP?a`?SY7X2x;LQE$S%yp9euuL$P9kf79QtJFNJ`-p_Z2$|)n?*h$2 zM)~j%1H1K=wZMlFWigCm-#_xvguAH*b&&`)KIlj_HacYGy&ko=t{J@he)O910V1cN zkqIw`dN5VUeO7m7(C}w*@1mWjPC8vAiw0!`#oadRU7DYi-t4;cEEYA3|;Xq{8h% z0VX@?ia6;zm_p4YODXf7aTEaTFxFwKj*45SexrL6kaZ>5H^axfE5n^%tR?PB$rU!> z(2t`%$@2lJmN0Cv5npdD_1cNK)%pqu98OMv@X>z{XyP4r7TRmbZkpWBdnx+ysdBKv zXZH-P+@~$L-64=Fiun1DId6b~Y!M%)4DUOu{1i(0mLvewi~#BgrH4Q^tuuQ7P331g z4S0#U+a%N~&-Q3gja1vH7a$p|7D|8Arhic@I}3>%=s(w3(}`wvLX8@mt){{-b|j?l zQQ0%o@%J_{F+ahLj$fn%T_xwm%NsS=1d?76eMO4g#@22%3{-Cp7wU{fe!JI8^(Jwc z=pv6NxO#^Ccq3x4Lr+T(nw!l>)sX7YQR^gxl1pBDgcXWB!C8LSJ7z+841||3y4s^> z34ukHe&!b~RVLjVKuSUjlx#~TTi0h_>ffXg;h#Z;e+opw;X4gm>L;?i03WPXz*KmmsYY7nhjdeO45>5;8}?fw~&^QwHyK9BQD%Q zw`gWi%a#JiPp(iud)rbST`5LwQiaYv>{@;;Li#!uG!d-Lhd3SdV#cg);igdN73m5% zYhPe8DDIZ${hT{hVMi427xD|zsjNMfJwprQ;HL&d;kp5-dq~Ellkrn&evs=kAWsO; z==|i%zQ?y2K8up9Hb?N>jCTlBVCPDxE#ZB?!Gg;kts@x7ecg5s1kYSPm&) z11NGmwWVvKv%++1`lpDUKr-V`EDr&TV#_O+Xo^QeZ7S}xxR2xc)Y%%!&rmoK^j`tD z;+{Obkrw_zYrNz$3mkj~zW$zZ&GZk%Vt?fh{((dH*KO#liP&u9u@oVA$SmPf_^reF zv?pA|3nlK6csZ7F&Z(Uo9ZMIZkr1sR`9~UE4>ZrjG7hZjm~PiI(V{JrU8eM{;=3mH z!CS?mx!1;}95VKK+viZV*}hp^vH;2ub+R=f6d%kURlHj^V?w)U1cl%|tErcMl}cs7 zC93^sVal`x{IFiqs2Cgs;=84HK72x-J6C6>d)bbSQhL$8`YyCOunI)-7OPLWU3fkE zUOU#!X|^cKX@f@^d#z5o27ZUq!8Rjq?Ctt2fz4BI6TWJ29~`9FGrXZ>nSoLL1B7nr z?%eI^$<TgU zh(6ff?uN-wmq&kPcsISG?Svj@z&2LjNnKOaNt!@%jCSAMbuQHjgpytjlJw?I?{0N$?~{;6SFuR+450(2_>6!16&1U%>vwf>>+``-V?cmMNK$v1CqmM$MD z{2e6=LyKs+RF!n1t++p{TU{Mj=%1K7CnJtv$URaU56H-ur&v1B0WyZm&g?P-!~E6n zA0%Be!AA<13Gi1enl4*y%p;vRdTu3gC*e4LxJ1FtUpJ_|EwkBrDR6}(Zp||OY+T13 zH%gAC%1m6)xu+7x*M@@RE0P@v(47rj0cL1e@1)Q!f;y`dF$2(xX4qja0wV3SLp)qOgi>7q=%fO$kIL6&o(p8rCYv{I|Hg5-9Hn=fBU3>lwtaA2x^gZ317jS=>-9oj(2qoKa&S6Z;%ybWknr?XXi?R{a(fDMI{A zNF1c|SIQxUDg?)tD!h>3-oStZ4n|ILz>-2`qpG!azh@wJk#U?h6?!DA?{5Wr?Hd7a zLuametk%~^Wn^d>vN2Gng*krFZO126-B_#+FH_Ao&X!4H5x8jROOo?49wy2_tnmZy zDU8t_pNzQ+nlC2Yyl$1l0o&D{m?@0VCO4*%1W9cv>j5H1)X|)cVid{88 z?&A0sFjrtLb2uV^6YZR^72!I{*U6~fo`1RIwkUflBijq?4t+?g>?UhV+H93smX+Bw$iZU zitM%W-9cWlU@1`bfqZv95x4PnpWV{A(8(6kbam6>BY8uIPwdY4*lg(@7k1CO8Ty{1 z-*(R*oo)Kl{*Go<{wudi|2ZvHO|kN2{-!`u;zr_i%woxZ8}RsVz(|ej;A~gxf)dlw z#W7T$877lBjc5_%IR6MDr^V)p^4IinzXNBS1+XGw_OKre2`O-oT|z-Qv+%bf_ zY5JX7Dgq@{XwF*R13uCqHF)RPZSebU%6$j8@i3(np2GttcXV%(tx12%fK9lN$Q}#9 ztn3R@btt#&F$!5lx8K&aDjt_60F~C$!6KlTWpA)04-FQK3GmSK7}opLt+~%wEyV3% z+VIKR)5NLZcu6Wxxvh;F4m`bEZjG~03(D8oCn4Z4|Kfxy^SdgPpU!NsiVn2Qa+H zwv3b-;sMS7RA0zyB&;dMO7+_T3h{aR+%vDbH>!;ziQ?uimycdNGI^}aXqgtC8?ePo z7IB2D#g6%Y4YdA2a(K*Z?RwnEI!!|Ih7wuF);iUvNZ>8X0jXbxj#0JEcf-m@8_yZH zSSX3AGL*c(A{YHHJhWfEwSRj5e+7lC-9|Vzfiy18Q9K#?1jDa_43p6h@<1{K^+f(( zILFF!N<)Y1v>?Odq!)*fFj8B<#mo4~VggiNTh7tsug*WfFL8VW#^AodE!vE%&zDd| z=i4v__sjfAa1v2F`{%#v-yrAT-gE+1168=q5-43BL6+`?JKk_B+}Hv{D!{Vm8*!BT z=X(gU-aqf}&8_&`K5YQ;3d-fk`JDXKO&}bO`uQIw!|ZTwlYPD`e|7zH58(x1RImcT zv7+wR2CUD*BftbA%7Ne3q<_(xKSVN^l%Q1;mzy)iuG>~gH!E?s{O!J+=jkk(-Y!&l zFwZl?u-0rmKj9+23O_Ge;%$&X3R5%>i|UX_nd(2yHG%hvI2qo6>H#t^g6l=x1;*O__n*3?l|Y-7+Vag+ z=1!hS53uOPoFW#M4DWrzBsCguA$$&Q z_vcs(IC8lp_Z3hKU!7I6*rcJR25sWHlp3C{VFqva$sgvz7Xchee|#>GC{Tg~fg~A|L!azm1JrblJ;qqr zN6SY6FPQngh|DLe!Xwys zroB{8nZ7moB&TI9a7Vr=o|Y|Umuu2$gBjJ3>J0^*76Kl)<=Ew);tV5JU+S85#dOD* zqw!bND?VM(hGs{kV`NTNzD%HARK>{ZE2<+iSOY2msCV>n|Dn5ZW~MPYE7f6aCG{$f z7@>`iB#nW_*I0JcbsHnQU{*7PN!jpIn(;!g&6*=VK#mOh_N}DlQrd;|`q6gFB~Heg z5!KK;^dI+i-U2HhI3pE3gz^tecuLOYdIA< zkOPXR?plvWlY1T$WM4rWYAqg(brPV z`G&3P01K35zSVU9KDIP|Xt@!0g`U*40%FtOj!yUYDn_x201CewIhN=HQ&SDm!6e=#uUcqU z*$corGUyPHG zHhTKyFkv~;TT^0;l~gaq$+pogXK}}2m=)V%bHe#o^&1hU=Eae`<&u>1HA45TjUl#S z*~y84lkH@hT%NhG_1bUyB|C2--y$*Cg1k?O2-HW{YHPW^l`3r>12Ba85hhq(@+Jpj zuS3|)R0g4wh~QTA3zGIC=FcS(@`>M%AL){@ex&iKmFog1B=p#&1YL`2YvFa}4f@x! zTejj(A*({7boLw8B8(q=&pm8SW2sV$B0p4Uu=UcGA%50}YJaeQBKD;5`{x=wOS-|K=JC2jzxPxcn-cUJx|D7~w9=7f4PWL%z}YV=qiDIFq+a6}2@YR-*&CxvEzQOW5CnOnE^;#TPOkylyhqOiy1%=0xTt~7Vz0h z_$d%;KBE1pl1+f4205QdxX1@q8cXnHGPt&+TKG)TJq<>K6$o*q9XQzZZi<^Flnw7ytK6 zx4dnURhaQE!0xm8EiLtRN4Rm7eb|dKmN~9uPW^Q#!ZVyHh-T0glOvKs?v#93Nfp<0 z)s4y?ZefBqY5iOJw5)Q^wR|l({f@d}$1TeXWl5V!w%0+}>`_&G_>tvI)h+^FMj6@= z{mD0X5Pi>u5e+-cut(!XQ z9&y<=aeGAFAt96T+>t^cXl4xmW~Q4AVOMnO`lMV4;~2UIsXG&Vl|n=A8fC-G-CZuZ ziBN^Vkm}yOrloJwFqxoO&2|^h;Gk;HWH${zbR(tTBEAlvKMC?>xr1nh&rW}%DxJ ziWVslf%w-aB$!|KKw}it%@)P+OEs)`ASd&1(R41tmaFd&a&2ENNuDV(mziv?!AGLI zaBtEc<(6vZmaU50AeQ1Di1wS2P3Tthf)iu|_=Z<+9>~urU!e-UeRozsc&hen&JMg) z_;Z5}|7H}wI@;f7%PTXi_Gx*hQkigy(2;>y! zb1d}y2yk0Q1Y4Hwp0}^+ANa+3(~wLMaH=8*W-M|M5AM!&g-hHG6$W-ILv=!P6**o* za|?Fdl7-W!>PmO-u@@e%dg4{Fsv;;nrHZ}}I#4aSmC0Gku71W68@3Te6(F^Mi$UmA z8IVKLVLtnDGq?sf#&cDUy^lfN{Zqo8;#CDTEOiP)IU=#dY5-+`kIc1Lu4slP+ty&r zw&7D)E|f+Bsi4cb8zuc6O5isKPvrhsHKIkPQG@FGhR7w)r(@Mm__wDXRm7TxwEKPq zN9^B>M|osRrKrOPWI`Sd9pM?at(HI)J!5$&#`w0Xr+^3B>tyn$9uvT3xo!p6kw3InODp@)D&7I@L2<_6 zzG2GsKx(@fFa>|4#=JnK?UII6xlY*|s^7pQXKGV$3ABhm%0>+fkCXu7rl^25_-7y` z_!WSU|Lj`Lrzy02noE+tzquTEu!&W z>%HbRXz-eRQ%uMCbpUmvwxrErx#a^Vjlfh}%JPGylK~Qv@q>+KTlMeIDegU6ocI&A zr$^_gLH9k^qvvmwzHz8{#K>6O4)YrXi4|H~N*qdoO4TPVp?rPOuxjKj7K(I#e(7n8n1!XP<2q<{vVBP3rh~q}g<)&te~c zpREqO=ZAwZqPx^-%9Z295dSHmS1!}RL0<55d30&#>8xqW!lLv>>)ZRbxecipAlkxG z#an7$>Y&fnqJ4cDN$v~Ujn87=x-L3pZ}wxXpKaw@4ra{{ukdo#gpWR4W7{w?-ncD& zNEvz(db;Cvk@-kERvKMk3Q!X zjxJOi)>MmDqZpFOwlLu+ zCs$WWz6hc*@`O|OPIvMrz-8&K0@CrGEvLq+MY+T^^W>8ZiT9qlBV6|wGn3L%jD0(h}H~ zQRBmSYU4V-Zpu8*Von8Q!@TJalqQU@&ca=k*hc=X{WW6Gk3zyjXp+^zlX$RoBu+;% zRX#jH)GBe1O4V3ab-*k~(&CI@{bu6xNS3@8#Qr3go9Q;TXb0ToPuU+jZ-gEoA~e?@ zOqKu?o?D|Xb0v4#^3@59I#-d!rtd-Nk~#>(HQaNr0w%9zYRt_oI;8Ru3`K6~KzO7X zBI*VI))fItRh2FwufNgTbUZJ3%M!qg=>D4jwkxNx*1ABjrapOoOJJqzU>r;3ei$zx zZnOwoXh|epbAic)snz2>vMV(H2e1ohFhiux+-U6=YO1c5NMJ1b_PN)wQJHv@#Fw1KLU(AJ$ZSIu8qua6gW#Y`=kCcbF{78_N6fbpqNWlB@Ao2xP>PppEMb3l`q`Eq#k?aQjh|{nl)x@>b4}xh`SICAMV+wPmZp{X{dNL&+0+g)Rm9 zy;IuyGD22HnmJkXtsfW<=@d-wH5{5j*|Y>X5f z5URhB6Y^^x0k>rCiabdw#yZ(Sq)`EUjQx*d0k8QHqowli{PYiBhH1L?Z%*7z1J!j3g`A}%cCzsyO#&ru1 z5T)MO_j&HiwXV)4p8o~=!HE%ZC`-)(G^Q$l;K3UH-e|3>?V~d}r9QVvNpv=;621eN2o|^HJ0KoYZif(vqpaI2K)2-QuwM8asgZXU$5QXgqK)zAHRPmVXZTD7#m|=ZgZxFcmQV}8!#?yaY z?+~mi-o0ZQU)No@FMo#eJjJom?b*gw#(~`$v}I!n@aYEY;D|sy zau$65R&Y;31%yTd)Z@JTpIV~{e0aZ4QyrkWb`#xXnB;vZ)sx#$QQaJ7+*A{=g0s#z z@(y%;qCD~fOWf8Tv8ofvvC1Dm3PgqAkNMT5AbX6FLS5rKEJ_#M<|#EoZ1k&iev@>e z9Uviv?iN47X-nKBHIg46q;RkBZsZ#;k+w8z4ZFIdsfls|vuKps z>L_mS@_XK1;_DCjoeEU(909P}Patb8E4unx?~;1Y=+j0XH*~36tJp&l7S^f68w?=G%)GW@*Xoc{ID=>Y) z8}})@RJzOCh5Kc|ujCI4T@_!2hPA1>vRqz#05DD`C7)PWuxSllu2iXf3gNhgK)$@Y z`e%!O8mjbnVRhnOAL(2jYkrn#n4R$8^ZEcq)-DCAp7qe;N7Kro0UV)68kLv&%H`uE zx}0rZfPki$rz6D0IJU9;ZuudWvOj2+8w1(J_Cfu4t~7~3A-V}tT%<|Du&5BS%v}cN z#XjUW*_uz^TgteMb2%dGzcz`u=W2*B$K`cFP15o&{T{crvw1)*vZMe0XPmH)HC&Dd!KXiz`jI5hgtVV#Ht z%PT+qb)K@b`JXffzid#@)yi#h>?KM-csqh&M;we+AowIa*q`%H_)@^d9@r@3dy3y! z`IUErT{mtp7h$6e-zJMU<78=`wRgn>qfl1Xk+9F6yXhES(4}O&QgRFPFzT=_d}6Wt zB+KIp+vjTMgZ9X2O$u!N5>fPp!Z`@x?f&e{>*FQ4P?_SCDy#Rw(za?ucD)NttP9~U z2>H4{-&@^Z?OIbLs1n)e*|EyD7LK)Zd(#N@uuWR*2t^U`NkN}13u5v3Vs6)b-YiBT`tL6EJYX6<#@NRzjA zBkxL-5qlufqER^#2F6$K3&dQtzz(qGDAhP@5B;k+#`z3gug^Udb3kS>CTa}GxOx)0 zB;|zN_Cy_pwGye( zv-rSopLlP--Ro4Icy}vZ*0Q@Oe}^>D1T8Fv^!x{zs5C+GtOT(bb6Xq!o>WDS!TS*v zFS<@PnmP1WxM_Xp^x=@}@pQ*|tdTY2udGCHN+>87_Lto9Z{+e*eQ z!*}-Vg|AQ8EW>@KSDU(i-VdoQ3^jj%+-WB6Hn9l%NmHJrJC0>hoJR?DcIM>myo^>! z*XXCP#Zx0QFuC?hewwKr?Xf~f74^7hPT3LBare!R2RKfOW3l3Fn(|Y_NLDhJi}hq5 z065C`EW9bL9?~9Ys6r`Qj3>XH_iNDt(6`wE7Nz8xhEckN+0T2psQ)9U^J{+Rf8+iC zM3etSwPySWsP?-n6F-{tz|*nTqxpGG@Gb!j60YQs;77JMlNDScXH&6v`Ep~%@+|1a z=SwQS)6j7q^T?~8m>Z=UTLE)Ye8u_(<+jy4Y#yf2xr zc!q7ouAKv=5OC(l?yL$x=XM?w6zedgQ`m zd0o8EIh+$ut)Jbv>D+zz{_aMf_lEoR0AyHh`Ugn;V5*j*)8Y=eS%#~Zl7T9Rif_Rd z*fasG`g4xw&fme-7~jk?X-xcI9CfoKeUSqyUN?zEQ*T zZn6N({h$sUX3-SE83|u~iFy-a)UrTXaZxnOa_i9xbep(?ulaUA#%hJt{nYu_`bgpzKEt`8L-Wf4|T_ z+4%vw0P09#EHkAMw+$_Kr$9}f;XBdMzFK5OO=Km|Xp6tyDP5rB@!|W?!RTqZ;CL6; zb4)%UHqYQRFo;4#KV|nuIx+0vuthcdE)RM+B=Lr z*J`(%Jm%%am7aL7L(aG|A@jwYt&{5v|&19dnrqG5xNA zpKga3{Sn2MLV|v?%rrB_09HfSeh}qV>Z3-DGm!H*K*fPeSirM z)vEdR1HhW}dxIAuHI#3~!z|1MDo+1xjlT6z1f`$^aw*mX6z4@Zfl`=18{~+q4q#@1 zv=gsHTt5T2&=EfTtQW!`AD~0Ne#(I?qwC+w{Ul50@Zk6&kM_~ST}sWAjI_MF4RAQE zV@8D0ziD|qf>18jIvFc&NM2z;v`&lIprG~}#-{}5Nw&7wok(sx3Y-@t9=Bd^Q=yWex6TqH6?&OifzYCBro`HCLXFOZSh$J3 zRZ);O9xYy5&+y~a#Xa#6O}qH@orFPV?oak~2YSLv z+y)rncf{K*hY{MjCGm$k^R3aX<L?kd91Pv=Hf74bZPJUqikzVfseT?e|9c7|J3-= zGc353JK|1T(;gHSqL(JeKyq`Yz<;(ug!qKp*K^RFU!u^n*jmfyqCvGQjb*x2GJyjz zBOOD6@3uAb(M`PC0#=v_p`XJ#GU5_f+7q4aJTST74M!w}G@{K9kR#y5HOnu1bZR!g z$<@qKLs*!Yq9ydl>pm-Bg00uR{X$M++yg5o+5@e}oNd1#h_7>4Y^Q#6!6Md$n!X&^ zL-}?5EFsr;?>Z0VwpRY`X-(l@8LI!bEAodMgL{CzFU4jm_;|41XH3*o#~ly7>1MM^ zyey>7xp^6c)g z#>AChsgbdsvks9P@TRO9TbCBuid=MTy#*7%vSximK1hCoPc_y(4Olo%(Epr3DDO&{ zQCOz%H*e(YJq@e`l!M1Pkj83=4&0UcfUPV0APJ{z+4GJ=7OUOX*b;=G00>m^?xs&j za4?-<88tTj5eDGCA>Sm!aEbTG8<~GIzYf-UlO~e6NWo&%@3adr8i}EAOn1gU@K`+ldzdI{DgEjm`LK zj7lE+``t>b0smtQgh8aJfw7rt$Dvj}5PZjR$2)M2GCj@eEIl(piIX|(Q6GAf{1i#% z1<7h=T`1Xma>gifg$`p!TH3?aq-VFGY~EVn|5sUBQM)E2>=N$UZU=29CGxObFF zORlnZ_}upsDyHq=zRvAReIk|6SHBeP9@Mvd)R%e^9^}{3?&c`LP_t9wc{HXR(J*z! zM6t5BKZ;KQ?L?D(y~_OR6XAPQ)Y^7-T+ePqL05%}=m+y};uT&C$LU>2jGf`xlQ-64 zcY8jDx-$B?;}OV9Z;yI&;_-NX+D{omDy4(c(RK>(UQ`7883|? zxZL)*M5Yn_p>00y?0hRTjHZtHC`2)`frx$Gm~ydb-a^ZEcA!ezd`M~p+W7n)yC!#} z#Ar_RgSOiuf(Z_d8e2J$*Tl~Q-#|UKmAc-c78gRgtADffTDa;;KS4M^sM;Er|!`I0GVk(hQsRau7NDguiLdg z`v3Pg=IZkI66-SVO~kHaVFzGts9F45?c`_65PFy>;Yg{buGXAqPwh#^fDWDLAQsX^ zch3Ss@zZ4YIJ!@tVul;q?pE*~ruPY8PK_tG{F3fd;s9ua%2gGkJC+etVKoeB1HSR+ zvp%Vq^s07_sSZH1#RTqaIqlaW*_vEvDwZChoPB5~;e1=^&rK#cFYTK9neK{!(mPF( z*!Ag<1;U7iR+}@^fZGw(@efc*l*)Zb;f__>-=ylm7J(agrx130px&(*S~nIo{Mk&J zLT*);Uur>@pliMOc@L!zQQ!*#_KyvFuING!21O~Q60kmIo+?7qeka>*xda5%f4d_8 zr`WbH4!MTXobMU?RIoF9nFP>x;vmG3Byo*qjlZfSL$Hn9;N9;gWjo*A(<)+p{;${N zIgi49BCYT&>iMr6U(lDpG4@P39~x0YWg4wboR7mfzFU&2H>dZqFl8O@ZNyl`*LtRN zfz~T2O*Vpgx5v-c0CL1hw6f~5^y8C2CLohNtechi=2A&G#p=A*PVjOyH2Nc92qm9j zYMg<*-l@yI)Mpp7f$vM~Y>tRt9lt)`7ppS&PifP!VQ8ag$V2y{l$8?#_QzbO#VJbjKUbA2kzj|U$_C~4G zgIoGsy}=bJ6qi1?Hs&}y^?GFLdY|}VPJQ&g?)^=%r!!^vYgi{Wa@EsFTQU2r;G|i< zxCnP!WEec0Y0Rp(K=AE-DwDavXcUq3CU>d}7Y1JrxyWuK)E36e?UC{)$j1%*oN?Tg6)3^c>glF zM0Nir)apzk1Yj2Yz}J`h>l0(0@Ivqc4ru2eIt$obz*lIO3GjAlpd~;4tVW}O^fu^L z2B;ZQ{Q!;1c+LLfGyL;8{!d?(HCOr4al_!+$kZR=QC=;0hG)C^WusMWuJ>>%RU zNooxw#4-vX2Nkcr`IMADZ!bpc*T1@Y2Vm(PKL6a52sv2Jby51jgzB)ZDt`7miXVc^ ztN%y8fJ*HL>G&YE@s_pOpKY^4vHCNBhd&Q=5-7WZFM-YhAn9CS3cK&o1z(dp98ch$ z;+T^@|KKrDdl+J(>KR37g=;%l6Mlbe*s5!^Ce3=V3A(wtu@c_pxo6T?t6>(&04m+C zaZAr8R3}3Ww=QXjA9-K*>Fr=x<@aNP7Y}R-mmfc1h}!2+IVd@0Qd%Vp6O;Ty&mo^P zjFj(6T2vCyIy1k5>t{_SSF+W}eD*vIqd8yHeW_KGk>XC1%;dATp|Vf0Y&#QnHFsi8 zWR$}4;lYtwiapX4OJ0+sBtr_%^Z|QxP|i#Zp5N{UmHFUyYjMkAmGER zt8t%}$NI2~^S2cmISzAGQZKG3+CCtA$Fza4H9&GAPhl{bHGveV1N&U=i}H^15EJ1Z za#o2^wv_%JgMkiA4x#(=1hXkG4{JK)ap1&N@jQt`->zRTkCK#%yw6r5OvD> zDZqC=oW#>K7`${!UP4>9@nsV%1O>RfM z*o@w88;MR%(t_TYR=^##f6!5BS?DvVC}vfKNI>o>ZS?S}jZi`WBOhi(lVV7`(j>!R z+Q3I+8X}f@c2$wA{h7b-2grPmac|$v+&&GvdH$?R630bke$&RaxY)b@gQ;V|u+TL0 znP*e|A(?kChE0M zd^AH>%u>pEGmi zY@b6@81*f*6~lLU$mW^Sd_asw^|M9O>8x(>lq*u!|!WF3UU(7m`OoaX3x zn#L`YQ7xQdHMT}#Et*>q>e}Vys3c}=X;0Dns06DaGn8Ed;Q>Fhq`egqO&03B49cz3Tm&|A84Qd`yRaa}Zq>q}hKuMVGw!V#WDkgnmM9p)`E%})}DzOcA&7WcHzj~v&NYB1d%=+@xH(z0@wvn?y;VTv12~*^HTI^0kk(% ze%f|MV%)FyzC^4Dz8T^pAe~Eo!OIT|m$a{@y&NTWmfC{T#Ot*j9cHYFO*v=@BpzE{ zhwV()S4ZEkuA}=pbQG8LCNxMu<2K)NYc47r<3pqLsvOrMcUW@!daThyavY zal>e_A0Wn%*){k*PZ;t4FWne@86C|MS?<>7CdME#x|EBzD~_MsZi{3Aoz6`sDsISjUsPa3u zwh8`@hOT*JW*vdlUp&(|JGg%Jp}lq#lM?7!_Uu%jv^yh|f_0YWQ!dI7S=(AvNDOjp zZJJ+s=(ti^;AO)AfJUjU-GTiXu^RUTxN5ZHV-baf1nU0cMjI8;Q9u(adDA#}g&I1_ zaN^A6 z3~BFPuYGH9sT8;$y-G$-mNu(qobkH~O}@&q&;v_HVVa#Zl7QpZv@dj=oUi&ITs z68natyhXv~h23jDa*2NLpJt0lLPx$8wU-O6xyCQ4Qr)@|hBkUuWj;%D4hd z$*|V@RZEV=Nw?*fMeV1v#(@ix63sl1q!Hrl};`%+ou zJ-zJ1Gu@2R<%J1qM%d(2R@{olV90k-?JD%=LdNv!k*1a>VUs64b%xY8_qa9+(N$Ft zCM++=npB$&Q!qps6N%C#X3;dh*|yZ`?Ko07`!q_a)oDu{PSIIqqw$`GDzdZqynttq z>5JJ6zgu{kJkx^|xR*C+Lv}pp*`spBA%_dpQKj?5k!)?L10J_i{UnWg#&dJ?^Owm~iMZ~nsVv~y)oOW2@-MH*o`_1Ks?J+zldJ1ITnDmz(v)Tri0Z0o#0h;_Z3UJJid z+cXQC9K5bL%(*_1nTR`0p=F2ra>HN9xq5jQ2`_?3piY^h6tUIohwO;TztbPOw zqUf*#zo$wdh~5tpYMtFxBoLFWtoJ7A+zerv(mtu;Z6K%d(C>NK{W8PU@L#B4H@t<_8v$2)B1;;aK<#* z@{uvf1q?0GZe4FJqJc2$5eXKg2_X7Oujh@56F2QpN_NV9<$yv7qOP5Lhx3eHYEzmr z^eb6`>aPw+!#^C5(&3(iKqR32kHJp|UreTW_Qo!$RfN$w1|@cjkig+Y0c=LD03hm+ zeRXpQL?7=yKLhxL8AW%u*!Qd(A*!SG&tJ?RpHHYiF~X$3qGLuv$RQ?;g7-b*|9ZWe zV`CICuyu*?q8@AaYv>?0)M$&dr@bw9x1|m4Gc>4btEHgtAcyonQ}EJ&a#fg0@|_(} zGFHh2<^4&&Sn}toLbK5031}?#CK@-1YF7EXYnjU84@9!=5=+0!Vr zY{Q(NT}+RTDV>e+G*hRbgeH}Qz3p))X}V|qsR?@miQ(Be>&5{a!*VIPwn17o{#i5n zRJ+cao5pd$ySw(L5BUYr3em?}a+EnR(K^+<=iTX3L>y|!G#}2S%jX5HjpGX2lV`Hb z3ZBhtrqPD`B~#lD`shLof4 zT;B}r2R8rH7*_6Dn^;(9Rpr|FCS$EFz=mlxC|dyuDyA2;nK*1CT!cg%Czz_Ve>s5S zB+;Ov43p7f72ec*+y*qi#%>b$7x?QbY(yhW-7BkL|k90x=`~2lp87ipDell zzbJb6V4#t#iEMu&SfPO+7F-A6bb?UQFCq=Ta{Ksvv;wZAHrgmQmzTks@(V+W3iEb` z0w&_shb`4d<5o68y=(GyfRC^+CF-nWT@`-Ijz$#(Kl0@fYWv*9sH8qqK1;VXlH$g$ zJN|oWB;=FO+UBHt3suPg#)0J0Ug^kP%$}Fdw;$K@Ki3FX^GkKDB%E{|47)h;6#AcK zRvEwXIFDYmaDCd`eJ=fsDyIcnsSaJht~2#Cd$EmA)7;VGsXJAL|4Za@1!+on)G8ts zSyE5$AmY>YQvD&oZxA`}BTs?TnbT)0`|X$V*oBKuvGFY7uNPVAx_OCLN3mLKlj1U7 zsZZ%-oH{bXKdF)`!7*wre#}!6{2_KJ!8aZ|(Km`{c!x`AJL@^TQ|**CW95iMAv}A< z^wUail%)h!e+I&ZQ8h4Tx2vbEk<~bg%OJ^UOt2K}Iy*jW1TTLzNDs}iCeVCSR*Y3+ zhP*#0`RoEHxuvZZJXh6eh)y+&kVHApD`yHh73aF@Z zl#eZNU-`*ig;r-b53G!Qsb4&o#$|CWo?!uSa>-wL3#DybC5@o>g-Z)Mrn$H&t&9Um zLhv3Z+S-$h=~{^gu7<|RB>4KaY!qNh>{zeOMyVoKNN+X*8D&1&X#5DOn_L!lDZ|Y# zU!1~N&8A+@i@982g8;fiXMNK?*_xJS%&liT(3i-o3965!6XM;%k5-fFRT9NHo60&r z2MdI9@`*s24kp6bvn%-k*DpHz?;vfUK0TD4L(@=M8INcZhp91ZB_+@7xuhbq30|EBv*|P43lJsD1IMvzr~K=*7w^t%6Ek*? z#bAR5$#jNGeb^+F!(dQC(kQ;XvFKo@b&1oYfRd;RV>eo|CUUq9{nl@4e*GdNYfg^Q z+A^A_S8A84?{i#b_=ka!w<=v!CnKL7Gb~~ZF4Fm=hfWrjy%ySb(vNtK-$u@G_3P0->=04mU6)%*`zAIJoGh%CN zmqMB4LC~X?SlAGFVl{pz1`&*e)B(hSG~9Q8=#kL>JA3W-sF7QE=T%A?`48DEt#>Kh zm4qXSinGzAcaB4Ry!dh%!WnQnf^Dq@)R3v``<^>)Im#0mRjGh%@OfcL(dbSx)0i59 zqOYy&KhnN~DD8i+nQs=Kad62)O%Jl|FoVhaQuBFJ-{=U2I-{qXQ3|HrmZJQ0s zif4fRpu>Vcn9KU5l7?Yf(35F$Bxk#z2obRwYAEgftq!#cMAF5{@EZ5rS#@nOl$(}t zQn?m~++1bM&f?yp@1SgzHfLv)bhhv?(JqS8eGwtLVzSd;O4nkVa(a8r$-!CCm4@$Z zorPP$@__$Sfw)R}W8fjn^ZWp>qhB-!Gc;wu9FYimJw{-R0MRHgyNh0gxc%r(S_ZiDJnR0;`wkK>uuy;%HU>cK zNf?0CNbzgAr2_7DWV0CK<&gR5$`-#TVem+uGFw2!MhCCegXaAh*wp+;oW@;h9smn_ zlUj-anB7oQ0C#c%-t5Rzk>R(j7Ry&-fo0x@5s@Z}tz@tF7=oMm2T~D~j4isBwj4vZ zV2dQ<&O_r_qT&|k72fLzcn_5w2I^A3Az7-zeWM6z)|x2*e(40LKFG-bOo9@q1EdtL z?rjrX0Nl_fQ2O}?sJ-+jp)BZPxaXKYh)co4qZy;SSrxJx`FpEX&#eQNl|F{V!s;nW z+S;F2B)NZi^Pvlef?+IYkP%#`nhlL)RX|gLTRQWVx*CM2%c1}^8j_&m?j-lvI>{!+ z_;EX8UBS?v;t(1S={T^|&Jv2uoU0Y=NH%BaNL5VtQ_m&=buB494$kOwJpVLmHL(J8 zmqR4A%436|Uk50$NoTb`&cL~J$5jsgVywi~m6gCkS+Z(KA}4*$AZkm}G_8MZ_$We{ z(OL;j6egu5XEOy+sNKB0Xj*^9=;Xt32l57g)574}3gCWj4Z;pI zlyEua%n=8%(Wd!e`%@zk(yAy9K@Gj!{K-z@zATXDm^ZC4k8Hl`9Oh^6jJYQ@08|F$ z*Nu>a<56l;ZqhJroTL?pIU!{j{4FSS!P;VD3VK{Rn&kQS1d+Ao$G z&hx-SE+?HD)TMVBE5J}p(o0=try~za=@h;^Tq)vAV64#cG`Awx;;wReQzj5Z%z!CH zi|yl1$^X8PU&UmY6FJqGs$*fnlUC-LVN|-(QmRsO?&|9-$|_jmV_5h(V6b7Y$B-d3 z5_b*qA%Jn3Lnpr>wUCXQn3%A951TKg?LFqju57*31VA8jzE!I0&QtO~HqmR2aHHkv z#h9#WguSl1_5KyKIRve-ZLibxNhLLbc?BgFHB@mb)Lu3Z~J{pXV{a;0+7H~*p)&DRn+Uacq2UtSFQt_WY#-C@9klnF}nqKgv|CsnP;Nm zVm8gKP~9-ug7m_d;!eOTemVY|#D2;!1fCKPl@0fQxX>Ww90$ zqYSgv0}QD+30NYt)HZ+A28`vi}NCL=r;@1kDV&ODr#vp z?;eQ~TP?vGi6DXWU`|QsX-|6*qW~h3k(wA0T!4r%RYX=u98IW41)x$)l2I;4Bx#Gu zVZN5C40s|sd7vSXj$;$*CR^G~;+}I2^-a%H+2xiDYKO6_Zl*klFh7#c5r0c69z|&u zryN{Lw}FBPEW0~jD!mCD0un^$>aSzFjDU28vTvBkCX0m!Ei`(GrZvO4x=WnEvOtN? z)xg0;*GihO7uUT$}GzhFV##}@rc-ifIy{#u(3r1O3fkxjEg)$Ie7s+t@6`2~TTrtVp* zf{ld2`PIib?v#{f7a2(>O4Z^|uiwGLzY_db!AsLezITOaUxl#Nm1=3rajW%p{~b~ia0l)6h1=b z@9@gDr7EFCSkx)8UR)&V+N(-QK`RYh(;v5Oj#HK0dB<$%FImQ41+RSo1;2o_4N9-7 zo!qF7CeSr=l}Zh4m5=83a>072Z9RA-Z0o`A{vJ#TteJYRH*_39O~^oJVOT^@)Sb-9aJ0v z-lA@>R%LzCBMAn}gmZ#lur+qYeTw(?%6P~q0Mcd|&`vE$m{GRcZFP@v#BHASj!c%3-%SUq zxM{+Nd5$*vO6uet6oa zIRLpyYNfj1rbct2$9;r5JS{kZf_dEl-VU@apW%Se>hbB~0IJ%Dgil9khA8WpyMCZl z=Aih12u+w47Z8X&Fo)7dz{KW%Vk09O(%=o_!oH=5SAtx`zSf-md} zU{rI?p8Q%(&U4F+|2^~>Db<3u-hXAt!F?=KSt=8XNy{3APhKM^1v$+5lW|@toh3|q z-g!;aCK>SZ+;fTBhyS!So=Xc|G_ww*uHFpZosr$M692TNnw|2X=_gw~aeJx@+VGDA zqZcJ5CT52qJ9!D3l)Tg5H8Ejy#Y4DU^>S09X^L?Yk|>5(5lqr-rcOOZDLFoy!Ei$` znaJJ_?h(CN_`F5d=D}f#o}&e`zg%89To|A%UZdhMuhytvwFg6f`fcdWe^$phOVG2@4 zL*N@nxtdDnD5{d`<0(=!BQNxc^!RK1{h${n23e@&k@!NrBhkm?5UP@(*G-#hJmgLk zQmjhSM#1(Qf_ZW5krf@SZ{CXVNE{fFZ zlCpYLJg(vw_@HMc{#^)^MVWFSV~x2%&hdyhr6+6dN^bj@Ozoebp=hgDgj+3Layv7p zp6RhpYd!K6l2-rZ?!HqM!oH_kCIV-y4elBTVEwvk!q>z&E;H9NN60gCVtmk|X6Yzw z{PxPsTBLNN0OY7=<44@Ukz4_IQ@Im2c13yuTpll>%vfDxq+`U$fBkrY z!00A`DmQ<=8umm4N3G3+J%KsHO1>;mO5@h12iZUc=NmH7qaf98M@Nz|7SU^;+H$C#^j)BJV@sE_Qu5yP zA&3iZWvNE)37g6>pRHl!N5Gjix!{LE^#&z>I_*~_KYI^=u*pp&#R)QFpek2QM>(KA=K}O3 zNgzXBGyy<^+;dlpB{u9~xgGMAlY6qaSHFYI%#tPnq)7USN)0oPmN`|GU9Ng)j~D18 zp|whLF3^70SHN`$K)6Pk8)Ks6LG!7oH?11{COZB@pZ~x6n%y4<^XYK%HYon!&KZ(f zTe~K}2`nrh0}-MQIH$1i_XRqyEh*5ECbGNNPmV2;md}rD)fq85QLaeo(cC$X7R;m%$>b1 zCg8oS(i#1qFvqD+2B%Ol1~Zl+ya=)(`-N*5IFcd=mGDL1DhuOlifJ*CZ+u~*pKX| z-(GL>0xja5KX3ZE#SCUA;-Kijk2e&6*z4LfP5~T0nmz;8z8~DVAS>JzVd3{^C z%sXP8sA(?G_I26qS2v!{c?0{Is*OpfY6^2A#quSrP(cZ>=32RYU?bu9lq7X`>8AvP zmHp(j5McoYuPqxOrv*^Iep6rSir=Q0JiYm#V;r1s2%6l*m1aKT$* z@#xMBiYWC@%-9Tvo)#~(EK8^z6>IRS9>4}EQU@x2G%2VS_t}g#$k#F9O^XTPgYm5I zApC+_S{SSwbRY$qng{IGq?&wd5Vq+NdWWjnd3Rk7*q+^UFWd^f56jx}viseIiXJBv zF|atp`&MC&W585P`LL|+;38dBfv2$iVNCWv(E$$KHIl;;5qW1 z!ZfIc%0(R7)CU`Qg)m_OpX2KgqD`LbA((PgEP1d!SwBidPKfAmvp4~18fAgyOGTF; zC@&u9#NY9s|0!by&cK3Yp)g~^{75Ig5JOi)pM?i@#m%rOD7hADy<#JY$n3UzO)4^T zLoe-wQ_;DAsk1jnBRPE=TmX6*DbshICT+_x^xR9FPzvg*#;%4OS_&b-QDp>GBZwQT zMX=B1NLCI&ldIwsfa1Wd$klB+GvkA>#UcD0F-WTJe@J2JHspW3p=cDqSL62To_ z?4K4Y3vIrGO0t5fKeS0jFg35f9(;ektGzUpAzI1*gTBoN~0DqP= z@xuzipg?TB>^(Zj(wZugdZeEwTD&~FFTs?jUz+UWDU+u}JpcnTa3`Dx452qH??!KF z;&Hvs_;|o8GfyrMj?+1b#n*!kgU{(H_N|OINZ`-exV&(v?roNXXiuw$ZK9zwY#LB`fgQ!-o25 zUhDe7X`18Nq_f+>=e=OB61}WzfjQgl#Si^1Ts$|#*0;~u77twSETRjc#yCVg7pfqU z{YpCBs1XDxBhSIc0sNUCbt=W-Xv1Vm-YTN)nH=0^8k>-$AmrH`j}| za%9tZkm$vWv!=^w$Ll8m7>=P)E(=KlT`al7b;*Eft=L=beE}K|6 zc5^n0jz+P=TN<5i?`r3l{kGlK%eXMT;~W)21({vo^XfDyyP3>-sBWz_1RxGJ@d74^ z$rKd%(#vFsFQFvlK?Wd*7x=35G7Z=i{&jQaix=zL-sRA16d-!V6pwY)_nrB8d^TRr9C6 z_FYeY5!Ij`^Xgc@{M9*X!*|edbVb#VIU7+#Pjr=Z{9%QclRqnv4#Yt#5{RzlJZodB zR4-U{vV!r!4s*{>6uQ3LR(Li#*K1D6HO;Jt!T*g-f~yF$f&jxSXfHyPZ0yT>Y&cjr zEIF+ws1HDmn&I>Yb96{(2}S)i zE|G(csmk~W#V$t+2)Pa17QU)`!wtJ@3Xo}PJBwr*25?{Q5%mbWdyW8e}1Sal8oR3y0t{47U{)No;yNc~qJ!lOBi9 zA`_T=@R5AkS_Lzjy`u#FakS!ZM@QZ$ok0BVWFZh>xIY5)AVr8#Ols`?|QnRA)O)SiNW;vVswVfm09Yk7JsL(8w!XPCKb{L zgb&F?wl}9uKnQ32{`PVfya?RQ2hF%-)0)wrQPbJnKf*SD3Y0Gkz+W{rn@Mvyuw&g* zd(Cg{Y5h38syLT@j^O~a?CO2*^Dvnr0+Lz>eg)V`_+IJ8KzmT2FohiC8C>YXi&Q91 zmsZH4QY9X4rbIyFj(|Mrx1d!U7|NuyK>u@g&Y8A!cu$Q_rkT<*J=KSIeepuU7D^MV zQ@H^J>jo4tNL7WSL&t2iFfPaE3$1g5j*q)qkcT3qc|cIzG(##Hoby6NSniCal8BML z{7d1lTr*qinq<~na5`n>ySeJoI;C7!xDLrO(SKGG_TVZpiBc=L>P9^55 zibyZ_?7Fd}Pm-TJSSrzFkHC?qar%EsgG`*P1VlB9 zB5j=||D`c2yFX*5eAK6;z{|u6{J;v4H7O%tXK&c)}7VK`i9@*0N;*n0(B?y zQ;zG@FVo#wX3?q+VMhKq5}nUi;+vE&hNAvtx6V0igl~LL0hM6VBY6}Gxx(ReoM|Xb zW30_7H=E!tQ=vcKdla_(0^1*7;F|P{KS!bUUG&_KSpbBMtd1aM2p~no9Y5NH@0e4} zF!crXt`nSYEIyoqn&l<31Km{fb`z{u)C&{an-x>3?m-7H)|owjM$&mH1@B{H>h`(C z!!^*LB5=1{QS?#R2W9A6L)euJHetlgw`9Y%FA}rbiG3F27g^?M=7rnb3zKrT7mwi^ zffcs9@F|u^o7ZP2)QUI~<-{~9VyMwgI6i5i(Fzq}a=pI3I!E6ykic0E`8~Jz-w6Cy z1!G>Opg>+)qu3#J76CrD%GF0u3a_4z!nndHhK1f?h!CEtzMA1YxP}L8Mp%G!TF~&u zPSYvsXwxCURJ`oJAI{&tt@{oVndkowf&qr-f4c)Pjf%{3|9J=Sf7HT{Q~afc-}*q< z&@kT??^J0?B-qd$Uf-ahh~(CWOr{m9-AumQ-qyh?%>ZuCCA_u zoCZK)g$1HhaZR8=G#yQLvI4|1Z)0w0e;!~}^ZfjK#FGpK-xWc9;+**?0rx)k#l+Ip zM#8@0kZV7Q6$!Ho+20+kuo>Qs8)_3lnMzcdcBsNlk`gkdjp9=90F?Lhq*IpJI9e_z zBObx!M;$``g~(J-z06BUTp)>cN6R@NcS<(<72>kdORSkb*9ak%@b0|{FD}Dy;{Ym! z7IkPCx|f%}UDt&ETC;ApOnX$3Saa~K%%dmP1Olfdo)c*QWYVth$yJoOIGs_SY>eq2 zVy-E0077|KuqA>yxQxm+bF}w3aYB6_V=!XvVI`N(uLDdiovw)D z@OViCLj@UV-E6cPlpyO6hssHLn9pX~I0k_{2Fk=n_CD+jUqVI3QsX&-3!XpJm31d7 zt6Voh^<$_4LC+;5A;<`V3!0YRXPw=dS-0d(X)g?#;xwBt!FJV2b?_~%AP{U2w5wGf zk;VZ_2GZlcjb66w8;+D(7$0Svs~W*F4b?`xh7!IvZEEXUv2l>0(lCs73Ee(e_WZ>X z%N{OSWRaN^XV#NlEt$p~*|gd(*5YXb zB&kTXL3R>od@6Oa)lUj2YAfFy_SA(JOGpk)xFlxjY+a*7dx=rExNArpXS>#6M3#rQ zoMvqTWi3L~2EVCy(kO3rHxr8Wce?Pe73W}IJ)C+I%@7y2ND)dnzMCo|nGe zoieXy&f{#U=N#ttEaj5iraDbd{5E-4&-1n35CYJX5vz=kJvXp7%$O?13%LZ+y1WCT z2w4qWC#`CjlG*LHeAqRCuxe2Q$6af2vEE}FRbUyu_h*-h0Eh~p26$4dv@M9bp7NQV#Kv9iz!0iGe zehC!rzJViEqw}(Qv&D=`^f+vc(Cm*{BxV*bCTL-#Z3<>yVh&=2akZv)h#B&97V>sx z2vSKyvDQ|@=FmI(@KEk(?`o2)x+3D5zWW@?C;P$0C=vrjM9-t7Q^vS45e&CiDvfg+ zUeH!5*yc)~>g}NB0k0r|_5%CbAfys4hR@?KO!5B#miRw0$p7Xy6xpIHQjVe<_yr*1 z?bV#k|I7A|yNtMTELZQdqW|9fM4-=lHpDTBHL$m~>2U3sUT5B14e>pFX*ZGAn=;Kc zF=)gtLDB5SZd(AN38Zcs;XuY>&fh+oKM#{nf3{W?Eg39rBjLb*3})W}FjPPD6g6>y zaN?x($<31Dxfb~98{XX^Ep*PLQxLdI6?nMNShtp+M&B}A+MJ(j$p*}fNUfTE?e--C zsFnWqI|B?AH%v{phk!L5PN(`U!{J)RZdD9R!|I6C2nJm%^b7lP`_Mu&81o|QLe4v( z^#!ANvf_FD6}{%$L#K8NoLc=l)+aZxSl58mQXai0Ps(KZj;Fd|AkS{$14%+Z#Q>%O z7CzOcS#p^5Fb1&Q-9e8RC3*u=2R<>&DW}rU-Ug*!%hHJCU9-iWC?Mgee7(avTkc>jQZH#i!?@V)0aL2{qY)_oa*h(8x}Y)sXpw6Jav&-0jeLhTCw=zU&lQ z9pzP#5KKB!>2GMcB`q-mWb>;~gD)J%9F;cJCSPj4LXIOfFUT@N-2Nht57)z@@JVg*f_#t=e~KtkRW7VESEdKQ9XN274KIkY3)e&At(4=FDHd7s}mo&LcGeX0w+9QQ>tsJ8=KxB|gi6v(JDvX7`dLuH(bfJp6 zyfU%3-xfPap+jQ`tNcvYlT5~+gz|aS?CRD;_?|&;DI7kPUby!pvEtoZa-oi8tvW;- z>JXj6HQdlu9|2w2UcdEqh8Wwy60GsP(L0G4IBL zpJrb}DJirdg)s09T#w+VhiGMEv>mT$iXh&txD?O>sFm}?_qX3cTHr+h;YcW4zALY+%*!xX#1ftJphH z+&iv_X$Qx~MGLpcPH{?rCE7cne+^WY^uH*)NHAG<-WK0`OG2sLxJm+viGolFEMSj! zR|n+KhJGCbEGDOc_0+~Yz`rqV7l^2T3>XRsg3C{cHy21p-_Bhq%s+|EHuP~~8hmY% zC%zJjZduE;R6a(j5nKmZw+(NZackMRG*V3t5TG+$)?rcC#zN7x=<3Jx>Lgg zTna_sB;;I~Hb1&*1y=S_+)eX>NLv7cQyi$bM_V$2j1VY)MoI3~dK` zb>?hw)$=a9kUxC9p8w+G)$*&4SIPsv-_5()CxFZ`I(1n)wevyC zszj@6a|!{Lj{HP@rZC49?fsV*F>GxYFP}zsqlnJ=KYf8`z9HmOD@`eFXtpZuHiu)Z zAJ%*Zt0LtT%(h4>k!X%f%rgyLh;NGEJ!W)rAbAS{QkRaUb33x>nuAPdeVBsB&FNnW z%fmThQF^+MD}|Dl%W0C%(XnPUK3>Jcm>k!ZN}iO4vAvi(NjM6Ls$pb(k$W$vuD8VJ z>rd=^hJ!Vw(d|;@peb@e&r-&rS54|&lC&O@JZZZHEEp1W8k-7*K4!^M7Mn9uuxVe( z24KuF55x{G4Df=`H8=NcpAZ4$>6g!gZAt1Ko_!>puQ4G`h>$1!I#b@*ZpO4yb;Bt1 z+=xwbEjU-Si`)sHqixiRvYtD@*s4mBs;`9BF{z1*T|S$@m7Cl3Ep?=v?0RV+kxDH7 zFmjLVL-_&38P+LhK})_)&DyH^>Pj`jpp*Fzsji=UL!sdeM4^h&sX+Xba;{m^uXb;Y z6B`El_D;U2%_dcMEyrK0CQ?1dE3Pn$^Tjq(&LP($Hq0hgdNsL#eti>UDU8*f3u3a0 zQWhub8=14Bs}Da81{`YKyZYH%X69-$B4$g=KARbym_&=M^A``!Q}T2kVGUZH6-aNB3@suK+pCD+usyHst{Z zlK;KmI7!M6=PX>GpyW_|Fn~>iC+NLa*{1zpMNRxSP%B%@-$BaB`+@5Mp5H+fx8SqG zrtaMKz0LA56E_>Envky^%_pqd``Ze{Z+X(PNlcR}XwsZ7HGAfTSjs-jlok;2 zIzGmsn6J1hb7PgJS&?tmA(T`3iHd@E^DZmHQd>C9b3 zmrC0c+jm7u6R1xW6RC%!qnw^%Gsl^gwX>z=wGC`ls)6u$ZPXR)nwQXps`+P}Gc0_Q%j8q@+3U0IJZL4`$O-A>d zBKnJBQKrT?LchDR#1uFfFa&Qw)sq!zcWqJ zNXPMf0tR-NE$y_J7gqu)YtTjWP9Scxrat{;s2oVuaaHL&eaP#2nrz_rmmIYD#}JB^md?p_Vk8yiwj%~Cf~jS!QhCv zhoE=x4CT1JhV*#FJH8?$DmZKOb z@!l8eHC5DFrWt%8&<}j>Hv_Z0JOwZiLZ@5@;(ywI3Wl z64*WMm`O5(P+b8Ni)_3C*s~|4O+iSb-p=eJS3fJ3B9SLy5j`b8MlVTc^Pn9t`#nH~ z{+rnAZ~tC%)9{p|aolQk{84#Ssu+4Ai%t_=FGzk}+%__hU4;1A%sa4&w~~{(-^4UE zWad-rcTk;SsPF;GL$>M;`yCyd=&oxkRHC#TT>@r8XMywZ8rz&ajWh}`+&^U}<;FRK zg~iM9Jc4^>o3$m^S*VOo2N1|KefA*(Ku)kBdSIJih3nwt*|+!eLZ6`CVnKq*ZhWtl z2z|H>vCRo>-*_e2fi5_3!|@r1-!Tp48DRl9fwSLS=v6)zpkGGn0B;AS*3;jig7@y~ zw2}qtvI1cNahifx<`hn1#ovnipc7nMGTRHMVl%wB>zanGrU^)T(+VZ*!IrJd2LT#EOrM#sKVbbH$YU}y5{-7Cpg z2jCC2FxzH{5@Rw3CrDwkYd8<2=e<0jMqx2M&`xi(dObH^?`TArRpBhWCl9l;^PG@t zjP!)hdz@K-7;ld787VwYpfne4w8|gOade%;(_lRuZoZtoU`8b9r2gZYl(v3sl0)9k zQ)t;c877|Ds}evX$}Fbm6_e{jmolT!=X6`~C9p?xtz}{q-9#vWrXgoCpk^=jJK8hH zq}1&(H!gFDOnbqkV>Es)^wShrEr&qM}ZqKNgm}G#3l4zI5q|K$sW*_7EpLv z1nfHg*tIiKF_4ZxgQ}TY48+nW{LXPQ=~iL##=u;tmlsjWj>}kT@1o`wNDPN>bKAwC z7)%imdA{AN;eiqMocj5cnP?(BfOO-?jLan0LzyM`Xlj$$PAb#D2z=02^@L7xSDTZqH59lkFnD7zz5zXB@VDOV>+Oa8hic-wkNe3Y{D!l=&^;?0( zk0jM^$*TXU{|CmLWSLamXlia``k`wjsT;_l^ z*~WmI3ALb9TPMiW`@`LQ-5b7S8PMw(3@xfEwi0F6o*;)gK$k?C%8B?yt~k)OG5*}_ zHp*>+BRE706d5_?ytQ|!JW=Z=E!W(+`)#_0%pyrJrd?QFFXO%K*pXGlLOGb800y1AO-TxVOc`T1o z)D|_i&IK=KG0J`W)<`Vq95ou|ZsrVMeB*pS?)(I)_68LgT50%&Zb{htL1sEHu-u=l zb;P1H8%21cOxOp>00p_SYP0n&2@}!Ct$H+kmotK;v%HJwW$|!rq0UEDX|j zxaYmtZ?!$U7zySlZ2%1oQh*oSAaqn1tsMP?-c6kZYIS5cN}<0nFRy-QURnZRn{Tg;5AU4!h&86>7pO9o4JP@5+dg2M z3e!2TU#gJsfAdfNcE`27b#Opar{zi=A%^*8v;%uJG^a?aU1|JsxG40FzZ=LE#DipM zFd_==v>AT0(Yu+HPzhpTs%G8T_i~Viyb2Z*oNs7IU|?Aop+$PA)3-qa%GMv%T+NTk z4)5UAl7cJ=6-q7$%?s5Ng8b##HG^7gkEeyv?c5gxAG!`+gp$S;G_#6;(BSF*7=-h0 z_Dp8wtEEf=&k{RCeLBoz3VDs5A`Hb3r8lRbxC_V`5X$WWq00e`RHMvPr5I^Qqy*$q(!{r=w1ZohlUaJI zoSlA7S_Q^uTAvZK>Wx(vpY(xXf?$At)d^#nL#UI*lbT=P*lO8D<7xv;)43qB=834a znGOmQKWcZpzPqI^1rHFt&I?Z2JygY~*$sLie3&~@ixR;UJ?wVkY&2zl9EQE{883Q# z{e}?YG+JXe3DK)BdUi5N^Wa2zLr1$9|BlrFBK-*7nBX2neEq3oKD#%y$~hP>Ybt%< zhp_F^hE&{uJc#~BNW&|DP$Tnyf~=sG4Acc`zJq{bt>(y2Wdh|3T(w|Vj_{efv_1Nk zPhjYfRaa~%)m$P=Uwg(c-{9Bi<33XJ>^g?jpRSj`{R#%49!lUvbAU#scuoYci;p8A zH}VjAFSdSP0{l3|NX8aIf#5d1jU-83!L1>6M%FLTbz*S@DqKGE#r#lPy9~0sK>hS& zjppwB-n2@;3BY2|2_FD3>g8-`LVDX`VE7&UlzcG*25de20ngIc=|FOQ^gAdp1-1XD znJc#;$QCWx8rv5woW6MQDX3pP1-k6D$Vk!q3NG)2=S38=ea^R|T*nwO= z6>wb)s)3-M69E8+AXIA#ft3c>8;a|0zK}OggSUvll=}f-BEvBB9U znb|m=mAhva_C<@Ru1AE__S+qW3ZSOOhyM5XA`&2 zwv(hWW;NbDtzy@brkC2Cn$eI#n$708IC2g$rwX-od4$B!$=p869sSn2i3`laF5-^+ zkFN$jLnzktY?;5$R?my*%MiiUvd2eWX!2wQEN;1zyC>QeiQ8Ju!fzNlQY2)tfohWxa&Q){p;r z&Dw`XFQrIOn#x(&IeSNM%Q5Aju0MOSEqVk;-P$H2ynZh`utw;mwUu$hWuB&P0elfw zza?>#sS=thYVAxiDz+w0^&H2cuTUX@ z`0%ah0Q$?(01{Gw!8nys?+BrEZq+jUGH zWQ2;ai;ddh1{P#3iszUg>b4e^^m&i*fV>X^vll2vB1X2i3Y+~$aQSl*cJ2BK@ZY+pYf^bcH=p4*C+sa{DnQMyP*?3UB1fNp?Qqj9QHIX!prFVRqWYL zGjV*p$VywSU3gUTE*^iJ8YuD5iGb&JYl_)iP~whWB6~4|oZcLK^c~Pqm^8W%DK(>h zS--XKFe=!6S4D^Gx=gkk86!!(6iHL1HKidVoY7B% zM~wkrf+9VDC9-A!Zux22D zAm=*sJ#)lS;xDgpYVtbSg^L|*<5Uwn#pIOM~RVG|*g)bkJCs$j8bd8hY3LIeIR&bSC#Pg`~ zrYCj%(R0&PdW}uBxqDdRMjd zYnhX?TS|S5;T&!bM=(N1d1@c>oLstmS4u&CCMIfM%%i^ZebH$7u1x9Jr@kJr)?*@e zHQw*lo#g~Eu7`}7dtcA^-+Gp50jq~Ce?x$m2r+5&SJKd(8;LC!a6**xl?S;tmEXT} zQMi4uf1pXJAgYCyPbJxb24% ze#A@k;reIHK+00D90>pNG!4cEzu_^KG=EHQA(h;tulawY4FOoQCVfvp=wMH-Qp!|p z1P*DzPQl0cAZ%MXv44mVTI zp3kth^f0g*MiXH07UPb19f2^v{?x0a{Igz#{co-Y_5XcW19);~@(X^#Ty|@i{0<{v z{Fm^L-;h5%i{~NUrb%fP2bqHnEmy3qV^E7*vdvVIrwMuljrUb@oTo~3dzr$_dtqc}1L3K&%n}P{ zBUW)SUCaOw&4aDBQ8TU_wc?2`12Wc~+krrdZafKjnvKD7bYn76<=b1xhU$bmLW&olh z&vDpTCQ4nxW6hq^uF0x;cv(lvhFd!tvLK27n<^>tkL>;(-Ccg@+f4q= zsBts+#co=r=_#gn#DX#dVyp}#jc^30sTcyh(@nJhNj>a8sF#3B9;|xrWM6Zxm<6mp zRW?ph3nwN%89+unDMg`$ix2Gd%B@;JU6Sttsv*?<{4;9CLAn!kXt3L{Y;odW{EM{G z=yAO*GbhV*W0uu0#vh9Yz#2Qi-#G|j6orAdCHR8x3uVovUtyFP)kN z%_tUOMj<6S8u}e&{e>D#HD5jO=$@xbL|H0J(RXM^zLr1)8l^KaUfZMZVGo@zGDY-z zXE{<;S0m*=EY`S*hIAHxu zuzumtcjL~P6w0F+1$zfVc=39xZ*VV8tjyk>O8F%>20mr16CYVOqD9`E0mPhDEf5_YTk_Mi`z_e)b<3F{@L7 z5ky3^x`zb+mK`Ray^xfPv=u}^b5hVU6&FOwe9#_vLzqBnXU=r(4+1wwoepz;$9%y_ z<|CB_#va{G0TutuQ~hI}SLedZay2j7qeF=B_4)jYTGrj~k)YOzPe0D~4$H76bP?!B zRt5Tz4}sJcStfcD1NNQskA7rzAo1B&mvR5L5tGDYTYJoSa=UiIjxn&Wqx(2^mlou} z--sW0qllQNim!LIraNKnqC}DT29@P&rCxJyo-^s=)7IlqnOrDYOT98rgAP8Jv*W&6 zS1$t)i;e<|5TLPhJVF@pR{|C(Q0BP5UjVQ2flpn5q-gQqI9HOt9%`iP5pafj*AV}V zB?o^U9UG*L8n|U{?etm&B!QV{y_?9kD9NjHV`f3k!X}ZY+5rC;nbJX$fSsK3-(ayy zm4tCNVs~FE6XXU>Z@53Apci>0=_a&X9G_Su(B+()Q1vP{uVx6XGEo^uEF6Jsq-fr{ z`g2^qj-KSzr{WVrTATHG;kkyWw9{VxO}BMFu7VPIF>S*&Y1cG9vsZdnB|8dYedJF@ zm1fS1ZoiZk?Iu{d5cYq}wW>@?Y8@)^RDt=T#}d^lOhSVDE+x3IK!2sv@Jb46IDub> zf=}w37-=|Xr0@t4BxtG@pJTzBA)(e{>t$L6zc+|Lw`{mhY!Ao8$y*WO5I2r$sq=ei zY0k&I*4pyaJsdKYr07PPXoSg05^LCh7pZ9ljvZQ*sY9^}&nYFIY?T!-cHHrQ;%{AZ z(my)txV)#oNXfm8X{)M=+#5KWcJ~~qK^rFL!?V zaBjP+Onoe-ulVD9bp?}X7;Wy)w5TeFtaw?oQuVcyuc?f1&DWD%*Lb<{*f*Ie9bxGiW&-&pdcy(VbxD#B38R+kM^TkK9oAP9 zKHGy|8yMBYH-mt7C>Y$CacK*#Lcn~hNOqm}*#3EywYJmOdG2k~GylDBZazbj4R9Hy z8Vwa~fx2WNdsF-vX6g^5#_iKb|hw;QyHVy{KlWzEf= zNZ)0K2+{4d$8_XYpLBmKN!T*2{xXNA6p}W}(Woqa_ML|~a(~RMX>lt|sC-PQd}_;w zWo>^L%iTJ^z5yNf`2g|?>2iUfj?MAxc7cFZ%Q9xHEtirQy>F2xwFT7q+uCeAQ;!pj zUBu0Y$t$#va-HTLWz#rY}=3UfxRWVGYcS0loiHLbaR7nr4Xytor>VM+9$B12yHCe%Z#hV z&T%4zzZcw9W<|^zR+(26Ugosb$i0Gio4wEapC z8T7dyhea7;@BGSp_E9u}DZJA;scH%Mah;oYCKn48<{WQ2^cYVgORM-E5J&2dJ;08= zWtix|wSxn*q|Na#oXd7|HMsTs%gVDzR<@`%<$prEDcDadJ(u*9wuAs%mmo4SJvA z!(s)h=$HQaFJ>>xM%50(A7dZ9a_9^4O2FUDIGQfnu5Dh}M;Dehr>Y7?Z$YCD$~f*@ zeG;sfp7u}xmz7;v<|BfU!BgK5X_b;#C<|D;D}6${mzt=M@?Gf3`j*E+$+lK<_f*sDp z^P-a2E=p68cEPz4i5XW0TTHnxFfXXu8u}w9i71{WJwNQ_2AOQ9kVdxGs`CyoL^Yne zPJAxpei1jhu+Esx*c|f%A9Zl z*CNRaL@{v#pyZ|FTQAe}aPQ_7Y{WU49UM`Ypth0jmKva-G*SPvMEdLc^S@D8{#Tl- z;`|Q}%HSs2f5}5I+5w+EJ$?CSMb@hFpN!W2_vjtZxbp-UsE=+vT@fcs9f@*f8RIHO zx{cZ&k&N~&c@Vp1qCQRe=r+MfU&=8UUcz$rHot;&JFFZ)K1n6=`fHlLY2psKZHTG| z7AzJ}{9(cQc?PPpHHldDZ^@CG53?EPyK1VN;ZeL)im$mC?8u^E{TM7apwwDGzWg)r zJK2z$ea_wpS(S_PH$TY1>eKh?*%rbPVoJd@aDp0q8PFR7c9>dmaeLN95#qwMvaDbU zZVC=25N`P7-cvmHuXA&sBM-6&+m zEGh5^WXJ(@@Zv!r=T;*frswf$Q!)fH23VbDAp5n;vUH}eIEy-U!ifmJui79(VcvxdW8DT?MybX z*Ukdg4Ptc1)H1F;%C^WysYE^26~2AUOoDTrKUmmnXN%`y8Y!DF|M-wvFmS7bf`HsX zfl~EJ_Ofr_fwIm|s#obRRIktV!OF5Ok+O||V|FB-gvpaSS#y{Q3AeS^!YH(`2lHKO zzk%%7v=>XfG!z+&d$9orSpSaN_&>(+oN9Nr@2RdTVEIy5t1>b=sf}30jTKvUPl)&fpQ2V^PHV z%Wpt<;QDa5$Xl9MTH`21N?_)2^C*Db7{v?jJZ{9xIDD&gUcb|$!agqY6-E6OGVuhpap7l5GNazBKlcjs(c?yDP6>DA-!ji5A8JXv(2$_SlzCw>Zr7%(Jb`PB0E%MG4+ks;x1X&V4qn z8dk)Hg}-V5a*`%NWQQ?9Q*jop?xcLp8kwiz{X}(R+SVi%sl7ox!##m?{?%Qpb3754 zSalvWIN`&WYvFL?W%~|qqnZ9&)N~Z}C+^;`5}`k6d$q;%8&HYTA8LTM3vS>aK8|3} zkxcABpuq9u0~*27rr}r}_dO!6;U3MdFs@5EP}T#WPJmzQ@9v;&8+X7>R@VRHwyUKD z71e9Grd?F@yV{}+!!QxVz}e6=jEVtFM}#1dfr9|3=oWnME%f023CK-wXcbu-?KVhy zJA{pl*1(fvNeie8$b)pUiymSDyjbt5PB5b>WR#|SkY_uH1CNPrLvNyh%2&>>8=0sos`^#( z0ACC><8Dg`3cx~s+3+LcWo!y(X&9(&DUvLp<~2#-cvqJIDMe*eYdGVS*%@Co4uYQF!i|>9SHAeB8^v!_J55 zowP0W?Ii&<3*{MamVit#3)~5AjyOm$?ln^h)xA>?0yf(C$I+z5fz|B*3}3H_2*P&D z6OH#m^*x7TS+p)axdfbm^v2{QD^ZPNGiFZmApuEa{IBtS_g>7LMX7TQ&?uedj z4zs|)m?`ad;XTb71!{du4I6izvD}xD=NiqmgpMokw`*6}^F%ZvjY$oU{TnVe(me=> zSS`JLX7sHRdZv$rwu?pc9(Xs{>uybhvg7M2>w=`n-><8}6Psrq``@5E#y!ky)HSo# zw1clGt+C4>M~~IO>T;0oH9)M@oTB#j<=nG4A?4Pcp=f}gG@P_yI)XpZSde5^40si) z8sP88iYNzSIg|$EWrTOoR-k4(CJ#~#QA`FWuarI_6tX|LJ5dV<3qu^Z zsH(VEcS`;BU_2^D!lTzKvrypOyLpLa&6|kach39YQdi0BGF}7S@8hbaFAZDOSh#2% zb~@2Q#v-T9{u<#?M%rdBd|#M`C{Ekhd^24vbaaTRBw>Z2h(xy-_ZP;`I7#}h4-FQe z0Mw&E7H+)&$i($_l3lR=z>|mKHKKu-n_ibM5*v7 zmN+GWhPez*#Y0X%^t@Hqzwm4dyd=ITi&2w}KZpO!F62T>KrsbKci8utIFCic1|UQp z-TUa3p!YtiD8M8JoLR%EMg%8xj<3CbJW1XK4|peoD8UV3*!~DTM$~Dv%p0$2gb17XK)_J zWyGbw)lvQ1DDbxpKdSoru!$vdf7n-nD2+hIqAahd%>=*#J{7ti0^f_1{qh{7RkB;M z+B%gd`~JGb626F4fsR3Ri9du%JN(MlB%?C3rwmD++B|!dDFPd-C$eI zD2$~;RwV`fm&y3W%(V(%k$k;fwUl>b!wyw96?SLKbm^SBv!nEqI;!)uu%&eww&v`U zqTy6Yv@vsYA8hdn`UTo}z2>y@7O!RA$@3OTtwlX^j>>;Ck)Q3y#&m(sInQkzhPZ&X zViC?hvS6~EE`7=GvXvhvTa#cNn!<&(nBB{eTasHaf*`U{xT{VJpq#)B@_(8 zK1^8>oCqMSdt4PIXc2Q>C0w0Xq%l#m&ZpwAM7jkAo*Q5ZrW{ zc)1+yQyu?%3a z>xLFb%!?ckn{vtkD$8e$XTh^`SDz&`3V4iQXy8gg@(-b=4|9MO05u@jslgR3P#Qx+ zON9uOWdXWrnR?E%+=%DH(6CcxdR7F8PvLe02S5r2c>4eDf&Wi{qJIf2db~JrqTSEv zcBaD{{yv+Y;30S&aZB6`(EsV%0!tO7t-@GOQqy{}8^YQbG?9>b?a)s)O3&PFu>BCE z*Ne2RAnM8`N`32URIi*wPwVB*@L{=+mw!0R+vt0GhXh{&IvnSrx>0Ck@4i%1_Zo*3Ru6X-Bb?MwCZOWXrk>(qyx!C7PFveLPB}$PY&OS2vyPwwjo)Xp zQcG?Of~*a3YpOEk+P6;P>wh{KR;pQY!%%7#z1KIcLH;n zK#BemIcX7o(0!94JgJU5szYShN#CZeVYCEDsLYClzaJroBRVGiQ7EPGHWe}>5@N%u z>-GIhW{?3I%p|VNuYJ2e)n~9}c{Vdmro&Z_2{q%%L;IW?6AAEp!7|Ih>}7NDAVF|2{{}nP{+YqdOA3h+ZpEQSaPgCw`MQFlrigo9 z)1dCdku@|V6Q>*+kaIUM<`zfY5V`>73}=nNOubrg0mj`)IWvDfWf)%>M_^kfSmc?n zOZL5p{ror3>mM{~9GKi`>+AqLc#h9Cru6!~fz< z@`x_hyvpSRwdmtjSGsz9vPjE1M+K4sX)!w1!U*kx-esY9OG-Mb8to8qeDc*u0n1_( z328-l(gSIs_fEf(~W`f+TMA-edO*T|rU$vuGxTmL_}(tmH~gb_#dmrem~F1!iY zkf>LKFsW&LHsp8OLqM?8c=RIQX`_s9z1a5)4+oM@KLjbFMx3G%Lgn|c4PVB#WeyiN zWejQ7oiclerbWl5k&^%6Liedkh{9A^cg-aAh54I`@Qt{Id@oQ25OqdJh63z^(jSm$ zwGV0%S+0+kAVEObJ4mF*q8%v}N`HGZ88MFY>OcdJ>AQ&{+(Mpm6jTBTulL7) znmU4-28^OXt0qsz!ph0+!-3553_!`+u>_P3zc42M6?gK#dhLIoOR3ARzZdr~uG1R@ z-qeqRetCMs;c^NtQn(fe@&1cW8Z=)LPOFqVbH3y0sQO!WxLdVu(_Q_uClKJ|F2NV+ zgj4@}jX0H(_Yr^=^YRC`C2Le$^*s>XA*({c+XD-LN;Tc@WiqURL97>jc$|WCMTbem z2IZ<<59T`ZXHnr+zP2!C>~kJyJk$2QR|A=6F!saIN-0PcKx;*(134dE;C2)*)lCo& zC0P3Uv*!HBT#G{Bs-);3e1aB(CH`Uld=z(E@a1>U^;Wr-%Kg&9?zFGVZf9*E#KDXK zKLIV|jm9AA;8(FU1nOeZol~TjOis(hW0yog#C9@VVud%6i&Bb`3ojwO!$u&K%u)Cd z2V`Hwejwi79=3g-23bM8Eg-gx6L2mOEQ?Ux#RBAwXk0%;{|SK8+zOm<$PccY+seIF z)IsseEk4J~yKDR3Ks^Pp9yK4hO#)tNihb4mn7p`IuRJFN{A0X1ysFx&0H~Y+K#W^z z1L}>X?2nXGDvc0OiB0ZKg)#n%G3P(1PQ#V~iu@+kZzZN;!>B!ZO|T+x97(t0OSMa_ z-)aKRzG>W)y1z`2Ic$eBG7e8)+Be!-W3tUn7mtZSkP4%Yi5geI0>fx#oW#x^s-1Dj zalt{U)P>5AzGtEge%>RSJDndiHK&PtX0a)IV`Lb+_|14AmDqsP$>NjP)CQU@>!`YWsc~^$uBI z?=XlFa$7a%OI0;rEN6T+JJjxnK=d60Ghg2;h@F5sl^~b%s%M^7ZyuQ|WPZqDsJ|g9 z$%$EkCx6K!WdMofK0>ZSS%SSdfuPq%QV*QvV%R8HSlIu+Ao?`YbAilgPpb>L*!XWJCZdA zFxBeKdoCA?g_9b!W*~AOL6u1L!FRO)@vd3&a+voV#@O(>E9~hhKlI0BYY!E^&bS8?2SVWHi zGo$dJ{oSfsEe=e=7ou^MZ!UudzOjvDPwp8eFCUyxyW$y3vp*O{B7HIAq2b|2xuB3nwLm6Eybj!cucMsat6>sfw5RM*N=M<@DYA1IgpVrlgI{e|I zto_4BIe*kg&)M1}z_NFl=3Ugo#{L0MChXA>{x|8R_rhqFy{s(TD7@(zBe6ZGq4sZ= zoC2`FC2fQhf})*zKYI{kq<_wT~X1cR~T!)$!hMpa_sw_WwmY3k@6V8<#c}aGJdi9A@teV6}e9>;IYG|5rbG{)T8O zd()|Z#%kSmIdhw`_tz=FCH(3JQI`JlQX0BbX8bF}$)jzW<}TZhRw^?%0aRFlt8@nV7wqzL6#m=L?0*W|j4*Eq0pq&g=k~h&$H2f|d=9L- zIf1bE0wz<*M29tiZd~|%haXilo>A9ZmmmmBqQN6xx(&B^WHc`XHh(CUPWYUMw; zDm>uTW=dEKwgWfMs0whw0#iOv=5ZEA0-A=h{TNo3P>E1KWM{o&NhD7-hnuN29bLB; zHoqfUSfZpOB2ZqnQ65s?HozETiS^v5wbs?nTPmqL!$YQzr}A2z;vxipa=3n?t6b&PayC{X<&&)vwL`fO)P+HEsUksBf> zC}P8PNo8h{RGe7BvbY1+aq=ti+(nhtfOlY|9YmRFar&^l!DtZUZ2vX)dZgdKT57@m zvi$mwz)=YO&&7%QDT*Zgs@aG^h|2Qn^=*~Ss@B$no`G0J#xdHIXwl5RbWJT-x)w8# zld@gYdKd8#R+(r-j@WtM%k&)k0(N;{79%QcQ;h(>PwFr$>G?G7XPM}sAV4hE6ZR;7>05 zNaQrdL4z5^r1C(%h=2=4XpOc4-o!U}2fT5j3K))k9j4E}79krYc(BUry^qlPlh~^| zM;)qf7!L>V@+*cxTvoZ>Du$9)`M);E3+RHIte>s7ChEr>xI1dcSbeJR+%n(t0YB~r zoZHl_7WQU|YH5)#?|{^X`RhAD;Gz=27dipbr`4J0C=5aexA_n7K)tpdSX=@wR=#hb z0nFf4ATeStOo*cfp1V}IMe6tsRx9vRl=vK_9g?1W@DwePyfu%V%I$bDyi#|NS$xJ*1JDPXp#6f4nJ7j@-Gr+eD`uTR6lfVZLL{ zmCyBZI2q`*^jwL$=UY!x(4ExlnBP(fYV(ElgcX#0(=diuVm@DN36xw8fK~dk{R95= zsE3%$so*EOr@D~rRvpL3QO++PYF0D4)c?-pg`dz7!}|@yYB6c#8PVuB-?l6mxSS)q zFU>f-t}6`5#4^)_k;BM$m-#w%aaVXLAYFQ~wcuz`d9#+Idw?voJmMe>A8vv%ZPc}w z!0EK{I@aASL1{~#uuoyIMsOvOX_NwB%}WaJS%R&07Yyv{=MNkB3N5WRrPf$@ z((VG%CL0nOD;+J})f82*Uu%^zJb7VDK zdRTg4CM%m{M}cT*VS)j3(N{FHGqL!7%rs@f6>cgvKKk};K3-6^c8U8V+i|rcRBM0Y zkSD8#^)P-*Z|yALa#B1>vn=!DpNAr7E(H|a#wnt|QQ$N?(VzdM=$72_Z5H$M!FmWu%BK-DT<*Cd}?bEuj>j9~p1noe|)0{*o{xpPB zsez7$d?OF!ifx6bc8sOqX^%Y&E!0y5f}5kw^C_2X0f`>#x|*=7rK2}|S(+*hy*g#i zI^AE=iaQ=c;2}jZKlGcLt8ngp@l-4~T+9s4c%eqp^HjZsBvap*J}TX^ zC1wl<1;nsnr{||GAD)30XM+N1j&aQx5!;47S7e@)-fK~(=Sio~WyKs;HH3!{E%0>Q zs5o9;=GH=6fcseAan84H($cZVL@@g!4C0YxB5t3bNK9TzLN#Tn6#=aEpCpx6PBtjVRIV#g> zp<0>QVRUGJ_P;aGD4sq_PiC4@XA>cgZl{W%OnUY)Z4m@sy585CR`wO7gU&Rj`W8Jw zU5x}SO-8n{WJP#>%!VxcD$Y^5y_XP_E(?=cp|vTp<Wbt@wp!-ZAtmhklGapse#l&Pa(Lf{ExV~9*CPW(PbDI z?&z7gc+bC50ze9Vn(W6RWPir*naH*1tOCLd zcqtm;Sjj3t4U)D`;%%gtvl@AAFa$Rk3Bo<&SHz+Me0rgOMEyB;^ykoEbXn*F@WD@u zfc6m}EdZRJ;g7fdaeBZ3*MA%U2KG;9SN#V1>->M@4L%FT`Lz453&>*@_1b1Y2tjR* zzSb7TPr06mZE<#;6TjHHAlS2V=m?g4-m=k~jt;pjbr~}7jfd5$y8NBj3tI%X zvRr*F|4_y>LM`Y7-PtDN;&Jfv+;?3n7fs}7iyG+r_g zp=%j>dfVFQAzg*$sVoKiY|x}km7rUVcrSFzdR*5y&C7I>8>&fCo*xPmRrV8)Q&#e} z*ugOr_8E9Rwk+kRV|QpNsOnF9uYq9W+I}3i?fOB$%vN)GZ1LbZS#^s#48{B4oBOUs zE)#FAd|Yewfa5!N=`Z!w30n-NNm7-p2t*%Yu9FlIKJ2CVs2fel-l;TF!l24!oq3@* zje(v?a5jd!@V#*(x>HAHwqup8d5qoRQV zG4N0e0!e)0@j0EsceJd^|(}&L!;;7WR*dy_pp_JHXep2_rY?7DX5dmDSK<#wv=5uS!_4MZsq%>&x zr?~K1weKoJ@%A{xSo}3d+Rxx3ic{^jDZ(#GjxjWswC8j=HnGJ$of+imoIc4`?D%U| zAOLL(kjk~m4E2+(50->>oQZLo(#QwUWb zak(sw5*(%^n}vS%P*Y*ed^Em6^`~BhfZ9Q~4`}`$lc>jx%KGXOsriN)n0e zA27T?Z5ZggOZO}R8Ofs;h4w-l)1#-f1HeeTa9J?V{GC6T1fTfH>qxRBw!X8NzNK)? zb{Jt?Cb)+-wX?5@=WjqK$Y(R9p7jwg-%^T>R^f(q-pyOQ5C&9y8A)XAC>MidH^^2Q zm(u_e0OGGRhRCvJ>6&=blQN839cTBhW>WCX@m`;9tM+)?coF4{&7iFKuGf4Ohx3Q4)AaCr4fy$dTe*>lCkzGFk z<967X?t;WBoN=nlFieUj^|0 zky!6}V}q==B~7%H($Cat+apEk`$r}~&xtA!Ta11IPA$N@4a%YIV)TPSLq7?CI#<*I zc+Ag6lpH7)Am8%6jJn4Lx+PAF=HYN^07S@}{1~9G;;6s!v@ zm05F#3Hg!wy5M?@-#SNu2U;D%Arfh8zCJhJf-yeAh`4gs z3aHDq)N5`?GnV0aj6xTS zOsCpj(k0xVKhVO`LiIUWu9dFJCqY0pN7Y;Z2LHwHX0>~>B80XCmz0;(ML_#uUxy=5 z8VAmI$Nt|}NO04vT@p_FiDMQKuw^{z-SA&@IU(>8j%WX<)LMu=3})OT#QpTS5+yqV zq-3k?fa#^y|Jh#J+^-vNLdU65qWh3Nk`bikT;ay1_x@)C@L!|(AJ36q43GJJVh{Q@ z3TsZ^aO-E~7uN*>_tqu<&Ue5qRrx&4blANX&5ie-R4g(xzynAO)&GiQi24;nASkZ~ z*v{Rm?j%_9H>@uqo88Eo3!1U`d8M?$M=;VKqkiozal&P6)6I?Q8$*OS#oO|w%@ zErtUmxWXAUN1sJsZV*Z0$_h7q_vegof2g#FsRn3dx;}BnmOF^hA(-oO1#)baOW@wZ z@;(B8TUL00AA_BzjoWgJ4J*pLx)B-OzkO2{|Hh;Ut4fRF=P2rN%0=r72w&p5{fc3~?8ly;oi~kR!*FWXkAlDyy2=#>9dE}PD&l(FB#?5{(+ynwJG=6;N zk?}^2528bQddr$EhT(_sNtEd044~OtC-ABmU^pg6CLCMXwM=W^U;)S_avcX}pkJP6Sm^NaO(9ttS<;^F zQ-?v?J>erBvNV&VlsoaMpav|aLFvtiMdlv9(*O~{)U86N9wMjepFR!yKX=3wo=UCJHTxk&fmFJh|S6-RaGzPCTyCnn*uae1y^)|~k z-+4q^lp@#Du9?O%a;v@hRyN_meOzPm!nag2_uMK@U)Jm@Y@AVq(&WV^mXlj7Gn@a2 zCp)M~{r;Wn=%cN z7q(TDVP~$8&ai7B|@j@e{D-_+)HOJnvgmCF`WSu4a6d%tHyR6L6i# zFkkS?3Y4Bs$ESd6*A;5384B9(io=ad-EM!e+VjIa_zrFZE?j?BfIkB^?|it+xJL%Y zt+1b0_5W&TnIO>(p=W~kt{TEe-$KalIm*pD^!q5PCN#PpR*!C1Ey`HgoQ0Oiqt}OJ z_X+a7mNZ|~5e0U%iUY@IKivtE9WMd{qTCN2&fE!5zuX4EF~DTAUId_}Wae2gvK+Bm zg7^z&5o0po6GxSOAL*7^cPV=W@Z<}U29IcGJQrB8G-BowU8#l z_MMa?T2k0%(%L9-L}s8cX}8Wtug}@16hys)v^1LvQ0jX3eX{efy?@N?I$dO^$4>$7 zq2i;JLnbjOSReWwI4J6u=hfxOK{-WOq;e9uZj6o@GaTybF}CdA7#y!0%EFl2O-vj| z>%6=a5mv4evVi46IbcUh1Na$A{(VzbHIUYnJb)GHSXLMhTvLmA^8o(oaO}eyf79s4 zu~1c0kc;zL!~j!7vsAE$e!v~5aFBJs>1-aY>mzE}fhI4~!c}FrwDr`3pFA_?nN{Wd1rXanQd?EPsyp)j%31!v?5eMaxP5712TyQ z?aA}f87B(ryq|^cB4kIXX;+oOs0eo`$i;fzv)oSATNT5}fL8Dq^V=p*0p%Vd?>~y< z7F$(^8ol6R-W(n*I+TXNw}&1C>n+FK`Z%?|tdezgW2RL;tMWei=P2BOGy_w!=xK`h z=PXa0>u3>&n4Uh06!Hzq!chUvOa~K%Jcb zQ0fi%hFt*#axhcd_d}41J$ki>xt(eC**Kn3vcZ}IY~^!New_Ak#g343%|XB(`o^$|-vPpUUm$tFbS4Y)67 zXvjB>aa-Z_#9I_Y%%5cHjySzWVD;VSyHmUV#Sv{vR1+tjUJ4irqwIbc;Qza!y{idG z-EGMH2CA?vG=W52T}1(jWNos0B!$zT zdE`59Ngyo#6T04-^AG5{1+49Bjzqb}h-DS^@Is5|X0%%nvXIQSVSpuje@Us!psVzj z3S&Z)S?mkeyN|(!?F-Fcj;$7vXpQp1mcEmSb4tAROxa|`5AUOTF34HHy_Z8CrIUVHOIn^S2HT5~mEVg6Dk@}s zq%;e{#2wsi!)@X6_T|Vuug&SDkRX-AUqB>4D9oUgM0yz_aKOd8mBEpEIuvE@P)uoq?@ZMIt*yRd@NvdBgWlY&WN3jT$Rp8} zYk@B=0DOB1d?{jH>HNX5tj^!+7SlICQQL}Ir|YOuf9(3HQ-h0zT*`~Cs81!J3omq< z8`RSgM4&Vu@v~5HbN9k4YwmfK9+i71HcJ_@Jbq99M6!vwOG8zegCWsjh}9`{yIg)6spgtJCXm4}^O+3HkX z*HJk!I=));i=8=<4T805NQv&gR@YM|V_Vnl7T&P-YIe(Hl^%U#17q@4EKpgNi!L2` zEc_%RgaGL!zQ1T4uZeN0O6BgAVmFS`+(ND+=l5|V#V4)8y@+wcWHXxx=#hm*x_~v_ z(=%MAjg)0NV60S4Tk$}{l2UX~ASh)*xmrK&wJk9*Z%NH-o17qb z>#RY)5;Qcb^miq%VOPmef9{KWut zaZ|z8tx>RA|05r`jK3E8c26Qp#TQgaYY^~Dh47!_i+{OYO*MHexZ><+?`l)I_`Fz> zqcScUi8zGVc@o#|%+hxC{CQ2vZgtcPEdMWUe6$bNEUu-(6^LJNtD@d8m6HLMUi9@r zT%yHo3iwH~n-3umWbYWDINx=>ERn!wU(?^er2G^`$n(Ok``sb_t1RAi65<_AQ5`#P^Vb z?;+AnVPH(1bGy~Wg{URWk7w@2aDbQb&PfH{Y1EbESuP_zss&^X?7{jTSM-Vow0V1( zuOmXzR1!lg(!fA}L7wVzZvmSCmrTDZ#{nMZrAeGwNHMX=nkHB*wuq@UW8=2b;x0p?bT4TCIZqT5NaN71v9+Y zBFK?8atxMK>><$Gh5fLCm%?fG6b3)O1_e-zd~)%bg$2BBHz)=3HENiSMS z*Aj#+pkf^Cn@HjTsOy(QyVle2#M!5RZQd_>TU76i{GHb+ZX z%?y*4C7ciAu$RUkk{gR;W-+f3Gi2L}O3SA`rp|70n!tKE^kxtwsydc5WVl7|Zf$gC?@wApN1~B)1 z@%1p1Jj5HdlGHJu<(^~hLL#5(RtEdO?%3g8^`#XaNV&Z1E}T4EP11fS+Y!BfBr?nV z8o^`H(LdVjqU6(|jPFzR70xVA@Q$u?lV}d;B;AGFr1(AMC{LD4OSyebJ_a3O7-4!F430hpJ?U8qQIG$gpt!fOL zN#o20n(J|l&b$J}%@B#lvU#;xr#){<>W@x-A_%*R1~_GmGenKGoMKf8e~g(tjXf&T;` z0-3wtabJ%xye$I6wX?8DRds#QGMFD*xHsHif4Q_O5D~{w{^xAtf3p35dq(n|Spqg_=1g4TgyPJ7Q56>A1)r)y07OIFE>{%} zlhJ05o&GWnB0luGRp^cj;GJXuvBXalXc>Up`3A0b#k@HK-yI5lFB1CY`CdULhWg)+ z&+q)a@*xRTi??VXT-s$70sewxa$Fd>KD{O^%W~>>HJU~sRHFF!_J?`x*mh}CH`&?G zK9IH_eIRL?vS z7_%(G9!e;k;PGyN*;7FuQke1BGV`20i&Z%B;LOuT@><^xvg3t4QMfQ`RmhH@?Je*D zaAf7w6%;)^$6UJH?Sb?OBEzw0mZINQGh`j2M!G8oWYNG0eV+q8}`Y9 z(uwO@6OOi?wxmcCic$-aQ*IMU;@@sHd(pxnSkoHL)ZAHnDAS5Z^r?i32HmUza-pg7 z7atAYN8Opk+=4Inf)0u?LrY9z;wiL=vWI#>=qFC{d_#>>{Tf`_^BFfb5~K>(h=xaC zm}Ng?yOu`u+7hs3vk)6bSnjp)!tP9Dyjf32>85w+7VBbPmTqMb$Q(w}u>ZR7(AKc# zojAPVW9K7FiBm|dO2wh-z- z`8tGyL0`L=_d^XVpTA;^;lS0zOl@8W6u>F3XjC^gXuDX(n(Y#gNfVJGj}S-_llm6E zE;jd5UFu&s>&0&N$qinG^$HLemC0e}otjCQkyubbfSvtts4yY|e{=>-H9jq{tx1!W zvktXMpWAF;Wh)t3Q2oI63=w`~t3xlX*T>IROHafXG0kr14b|&SdJ#nU$HL?fR`Jk0 zfwE$AYuxhm*iObOTN~bYEKwg_guoYt7ky^+RZm62!;`Z1T)`w@yYC+YS?f?B{jHKTgsr3L<6ljN{@CJk?o49{9pncqF8>?8i=lM+e;++}5_zAvI-%BX(`S7E& z>mQ0UdbK zAXsVb2OS;vOTo_5|H0l{K-IN$*}}NHyC*mVcMG22E+M$POVHr%PLSa4?hqUT!9Br( zLvTO&H`hA3-|hZxcfanx-y5BgG4`olwfEta*IaYW)u&Zc6*XU1HpbZdaFbPhN#Z}R z0Bv^gq(lE{&Ii3MMwR)pK+wD0QUgix2dBIe*TwvTjKM}mGE+4@%D~MVb$n_w zZb-`beRX;^#mTLX&c;Nh&BiEhd_` z(U&ngd<<4N1K$l7RPJ+uJJps!Z7;=oLii($i4X&))HpS$B+5jc&IA95E6N7Bb}(a0 zTy>Z6!U5AQ+ooog#xxX!kUUTOsV89L+<==qBM01eY>u;8g@SR8rzuJ9^qa6sz;jqq z6o^_3nC~XtOZv7l)XkuLgOn4U4a$P2(I@9SAt-Coh)dwmTTEQOuL9|<49`_dT0d!J;Ec%OH`e&Y~MhiK$`U#0NnFS5lIpCJj zSYGnCp#I-`K0TJt;EWH@k2wKHu16QiY=C~J>=WTL@SB&U3g$B25+6Dw`jm_Gz$yD~ zPShe!8Wws2VThuyq@6gq8U{Qi88;r;ImNrs!W(0_(CI*`?USx-1kSTwbN4b?wle#? zqS3J~$dT8UQM2AGW(_hY=2fyjG#f7bb>q_!pv0y5BHpCpteZVxiM8a@{>B_!zdr6- z*iUVHV~aZon3afq2*8@n*NHhTHH_aZIlGFRC_KOu)A<|%yC9##?_kF*?>r-U`#cwt zxb=k#r18MOHmK6brWq=fz1p|hit8G7wve9jW}?0T^S^TiP^GMEq2m^zMyJY~?_mC* zyJCsL!t{hj+}VD2Fk0M<))e#@;g9lIS&NIdizJ`#o=<(0Igb9QGZNK|KbQ^I*;x16 zbLG%_d-!rH5pVgX9bPTU<$WQlYa|AX=R?`$U_-p!_4yShRH63}sA zJ^b;0ad{^brzP&^r71sjh9F1Q=Z8?148ER4<8_!9-F>DHmD=O?Zvj~)E&wzux1fQf zK1};nXX)`qStZ7v)?sDP1z|`T`CF;Ol_Zt6A<-zf8~V}$X$+}+9o57pIth_%RH|>f zk)F22cBa)r`Bw z!<_!`0?dZrZia6Oas)qg4yJ-pre4k97_t=!GIAc=biIIbF3{D6#~g9Tp{N)w zyQhcY;lG_+>?tNv%sqzdm$09rGK8G?HgL|q8SFq)RVPIjaaOK%j`k@A) zFf(F!U~dqTewcaR1D{I>0=LFeqX#D|nXgP;7c$9f@%F#+UW{9vAFA(UBMBXri{b-r z1iI?C?vEON(Lfpuz@M2*ANZH#K|-D-)Z z-@&*mPl&<-J_sWI_Gl-3W>wQyMeDgJO}Sqa6-5$oD~C^u>n?+s9X>;8AGk{Wyt&x;7?a z7SyZyc6KGCK8f0v<`k{?mGwDMCa;Gzry<{-V7kVKU%zlCjh@pY@)D9oT)Oh^1!@JOK*@ zUjJ7~hqdHR>YQx&1Jrw&3!&RzCPs;xgB5kf8O;z?O@%nOuG877`teXff=@MBR(CpG z-@%g9a^3IcMQ#9E{4wWgeMhCjB>9QRs?b4j2)sf&|d z9QZmM;k4U_Gy8e&BAeJ4yKlt;Q`;>`{@maD^%n-U%ejiU=MbAg!ACWl&R1hpg3Rrl zAjkTMA`Ez{xF>oIcbkiYH-=~6AKi8bb1YCr>)!)7pJa)yK%JI@`KiE%Mw)1Hy>vq| z+Tm>;*ptg5lM|f-wOZM9Ho8H@atKn+Wmv@a(=X`$nJ!V1+(X$Y!(m_L%AMbQ8IwC% zrOM>qf`3w1;(-)&LkwtF^w-XMy(TP&9naKdW(W_Jz7swjf%rmVe;VaJNZk(p9Srsx zp9Ot{e?J#4PJzbihZe0~dI?C3$y&5eNL0}7QOneNwAG+7PV_W`3!%_gj%|ux(Y|bc>4jnJ7DEaCr3ht6_x3hj9y8Hd7+9yK zI^aFH3y|oy0Ml+xx7wUyo!MH945!R!bu|=(Fx3OM^4w$*{zmf&NjkfD7)RnPyi)VS zCefEmz~`l82EUjf*8*%DAacg$0vKu~{UbMPzQW$1(+BG_Az`VR&qR6S&E+AJxBE#1 z??z_@a3GGY^qF`m3-~I)0_4nCCjtSr={^2Vy4fdn?I`>B_^RKjaiSG#Xe4=cEKsw|x->kA&-D~mf`@^v$&@-DQNaVJ zvvv*iFb;wOsK$MY4_T;JM?SwOPCN>?DxupJe+W6lb~B>lFWVq1;Emt2xG>sBhtGoE zl5MDcW|nU@kERf%;;)Hjp}d<(@=3=A8+or(-qnY4I7G&Mn}H>c8y_OvZ}!uxq}r0@ zWjBJ)3MOxOjNM+Qyo(2Gg7Tk+;JGCj%RD;L#6To$-mbEirD%*<8O*du88SWtq%dsm zK?%-{7gP7WxAy?O<9MfnP&v~}@Bv3V>lsuOiy=xe%{$_(V%CH|s~4sLw*(xwxST zGhze{$B8QQop7{#1vxuwd6P3bO`pfqg$GzQY$31=;*Bfs%PlV5PM}1E^~8#;GA0bO zT9=86#9qB*gQ5JqrTA*B{bMa)_C88vPjUDw67updp4@bFmJ=a;=;xWX2RKD63Wshs?H5J#(qP6zNB)v z*DtF ztvrWWJ(z?=IM8|?1E8icfLpElbyt&XcJkG}8Y1@cWf^74O-umwHTTU-@UAf7w3_av z>h`ZZasW>Hg-7l);RB4~P8UGQ*us}-%o(~lLZ06qpU?tUkBd|!v!DQ$V_OKVjk0`S z%PRwiYcBbKdML_=932LAEKyu=#Rmc4UBkMCi?TH2tV_Sf9=Ihk^e~)qbby^e?eXO; zCFK4(b(kNg9e0dTOIkNHL}q$jGH~fB^tlm!dc<|ko&^0Ci zc4DiQ1_ps7GL18DRsHfwEu33Cdph(XeJF=){1NOUGFc?GVPC!r{_*8PKa4*W-oNCX z>_30x-rsOH;s z9a8dp>l6X!&So$9*DaG5n1-;iHQ2!;VGiRQvtJioSZuOAf&}Y6

  • Kk77JDuprqD z9-G*b%xnpSu|90fJuc47(|}(3*~mL!3nv`9WUH$S(GtXdE8E!h~qMONnkG79P z)1S>d zY#W91al&gs`P?_v3b`0ba6VGH1234v#@}L_a#BB{|2YDqxtn`s+A-P!r*p0pvf+L6 zIEn?tw(6|)$NbA$;x3k>SdD;1Hs2;N({FCVs!&?U^KP8F}Do4xuDFs zFLeOiRXqwHTprz3^M&yjMAQ$*MH0?;yWe(Vren6pN{Ok?bF>@cfQ=22{Oyml^=cDhTxQ&~)FN^^V9>h5xE zk59J^r|51>1|fMTnFhA^_}0_Mx6S1nf1i76C_0JpP~2<;@|H;YSz(@jPSjo?|jOw zm$)pAG^*)`8l6x?ghPZOvMqR-d?>WEsMmVhF~MNtpAx$0;|@zHz&1zRF0ZxjiN7vS zstc!fCHXSl0mg>bWEE^0-RYwRUkOgW5R-Rmfa#fS5vUdxsA6HVNq*-XGKq|k8D5UBGvJRX;99W;8 z=z|f|n@5{c=SvXQFCq&6p-eDo;OwdGbGyb23MAGl(yy&=bojO;N{Iee5hBAIo8zYe zs2(@G`f|P!A9ayJP0a3tXCXcmtt3XK~ z7Fbx03Y{+)9+=C&g?s;w2tHovd9Pk-A3n#=b64YDcY2sU#xzQ#OrWInU#+tU%JH!` zF}M>lmGgOc~H+nX7nX3iuok%VON(SyKcWglQN^E$%W?soluC^&G|%ZP*`K z>dL)cN3DCvG0-`y3*BnAO*sE3+jv97`tHsg*g5Y20TI}M>8zp};Idf@ zT|WTgjjwD&@8wJ9uPqf?8oq&wE%_Caq*o5{6>ej{HuzA!nhOwo;ufu86y<{|?eUJp zQnAr?j@rftU6>@W1n8=wfVjtRi15DbkV@nxefLrX>W5g(+jO?iW@5!kws?u$8xJHl z^b+GB0RSM(ElRDy0##o_R2BGc#CC~%&wE}br-G4Bzl=ME(=2zQm zf{%%Y&v<0x!>#VOV*Q53hLuebEbW#9;pRUJ9#k}_?R#F81ia#fTk$7i^^c9sz+iRn z2fEH9Z~?A$)U$Xk#-uP<%^j=mj@abD3f_J1sAl#rQpmp_vj6|UV{m`QV^sdYTK-~5 z`-eO=GM*FFOQGMij~e!wPWx3`E$=vW>+oi|BCj>kU!t+yQ-8Jby14|)Vy5a)F``{+ zPRH*$eDI-r!;m!c6<;Pq@S7ehY*C*|eVcld3*0_kk*1!0uv{LID^aE-Ot~~obHs;` zYyBV-r6%Ir2`Ek~WO?QB`-{iLNmA=1$uEcAt5qq`i1c)rt$q9+%4nukD$epjiwBF9 zKLlTDkgUHMrdif2dA`PNf!vC_DX_EcmoP@ zio>CKg|horAS&L{(y_q&3R4_UGPPVGnar67+ZBZV4ie;>W($Il1m>kuabuqzwrrmX z)W;JmuoCnn0|j9Jr9g2SJ^hb&u#3Wq!T|c81Q;Y3!e1jSkLP<@`1O)i-9D2rqY=J$ z)&2eq+Y_j#u$~IgO^jZ028H>KI;JmVYV#10e<}ri~&SA;d|*FK{pzR?PCKM z7As@JxH9|kA`ZE)CxOFaMbxbWBT%LRu-B>4A|PRQ_#+Ms=-6jVm`Tl)$s{4Dpa8dX zSf0|$B)f&at)8Z#5f&a3fgu6uY&Zsn*YICkn_{G$c}toV167s!R8XzQ#yuZ^(0acN zmw)JEf2SY*jWXcKV|83E$Iu_78JM2!Y>)>x6^bL-iB^@+U-%|Dd1dNb(N`G_1dracB9Hu)anb z0Lh2`M?qb{_L`00+JOEVOxoB`Mj>4`a!`A0TwKa}AGIm~xKLJGiu ztylaO2NGDz|3Wk7mwQqkO0$9ur|?co&arWP;kiVuD2Oy+68#=gDo)w3V?{&k1*_d^ z(%20{^xGrRbKG|W^WId-2M0K-5{dI;cEHZb6q0)016BWi568@!aY2#4iJXEXiaD7Y zzyA%Ahw{NulK5wmZ#g|Jd^Y`VP?+OdU{<*#v{mExHvoTr$4;%?NX}=yWa>uf9e0vgbg z`8y`O|7;nE`jx=)Zy~RGYC^I`g;yZ;B0ypwXG1ecNMB%+`j_<6fA+)vl>c9Grc{3m zn%y*^{S>uwO$}=!wc`H~1qD@f(U(C{A%Ckb7GLQrP6Sy@OA{IG&cgYZv%{B+qY7o# zl=?<`VOjLI)ICw=ZqA6UTOW`$F5Njn7_*ySfvKP>QWl!QdsJeK3R$f-No&xuBP>%&&=B z=V}fW9U{m`fGzN%f!ITuK>Q1=`9? z{^XetCOF6S0D0tdTm-m;w)~W+S9v;<6Re;u5oVaAVxE8;GWM>-{i7To&8~rGr^JAhEZlB6x&!G$)cJZAs_Lr8k{J5uY zHQr%s1TPKp3_SN~vFK9~ja1tJH36io9BIWROJ3)#^9HrXDp`Asqd4wm7R3z5sEi5d z+h4W>;A6kX*%bfv)S_gXruDZL``}gR?-?gFklgMG(?@C>2QF zMz(K@*CCtiQ#S}tFZxUCQ;)h zN%kx*dfwC$ra@JiqPw_}9_bce!bZ`Kq?UTnI*%>?H8aK8+in|@eNUSOqQF%tp6x&| zXpU*c=gatsF3ITow5$uV_K-^{8XpEZ)ml(DR$%3Pzrw|NeUoh@p?@X@}s2U3Gk^_vVI2xd6jp5Bk#Np;|EZi zn@eDI>Q3#--MvA!ca!`b?CcQ0^Zby133jgw&^PNFK~MnE1Q7a1dlo60$ON{m zqKA3FYA;vP0YEMHciMoTtj`IS`%jN5!1AqkBKh_!Qg5$t17MT?doY zk6+WTZCwS`r}wwCVrajF)7WfC%(XiD2zUEtF1s7+>yhTRRJ;QPU2f8j#uen&W1nJGgG$4x3D}V9}CFb!4=(ijBpzdIhkF(G{O8mX08o;pr zA#L`<=l@LJ5U9)l_wO+GsUioMM~A=>1`=R*5zM^zW$pa=mQWP{EoH6zT;iu&|6Ahc zD*6xB$74hMQOzGarzmS?oHUibo<6t5vrgOE1RQ0#3@i)Eyi7qt=eobzseGA{rgO{H zS@V3{HUu7{ffiGwQd!aR1@mc23B_h3uti^&)crw%D)$)50!g$B%^h$7vgg>P8Ne|b z5WvRu2r&05S(GjjHK%_bM9Qhx>aCmvmNgm%wnI}vV*OmGR=Aj#;rYH*+;=eR7y3Rc z)dN{qL2&r547o2V8ebZDal%A?nyy4jM&`|YBemQ(JptYFSC;nw%kTX+z)MWQKhu3m z|5NbN-#FI)aavXrtdm@-lfMN$M)q!?7gDNz(^)%$<@dBc`D3`N@egn}ch8jJ&;D=V?FpNpvX@k{6qHe8hF>AHYg& z(Jp~^IashlZO~Vi2`S%=-Cbd#?SM9W(h#R+W+pvL6HF|PjmXU|FlTc6Ov`N0QuV-U z77&FInA6rR1TaOazFm|hwKz%8kcd7V`v7n^A}-hK%^>;iYz9a@e14S)DXo%8Mk}jM zqFLdhRlXsyc=6wIuKLfO%l^I3|ED~I0A@MGt*%OhKhTZXGAXalG&>)oU)OE?LahBDQF_q z&1C)=k>Aw%OvK-J+mb%xC*(1O)I956pf_y!S=@q3FNyn7QD} zdi2d5z?JF{x+9>;hW_z2kC|EjTIPT73;$n!?9Y`6dAJJDMzdO(?>4@JRp+9U#r|0CuRoZ_U z@4y)TY5x2vL6Z$k4nGtIhW`(#|9$k21?hjQ>DSfcf4jtgcb5=#Uw`Yf@%#4by)Uzy zwtQP-YkOO39QB(Zs2lhFk8jj}I4FXDUqCRnF>-WrFxIzz{A6ojfxyB>_KXbpK*rC{ zEMactWbD8!VWsb6EM{zIYh=tUV{BvUWJboy&L$}M+k;xQV|6d0RvS=jqP8|p#x_olWWQ9U60?fCoiVe5zNs;@ zlCh($vxA|rBT!1g!PZdO*ojP=SwT#Kj9JCl&54Xz+8QYK{I{#MSfg96vOBd$NxF1~*pF@g2RVrrP_BXitX$EE=hI zipfr?gf=qkNuveu@lVAct}Lm|wYcQ0gtf@YLZd&QZC(_6-I_vCbGng|lX;VvQW8Qe zNp_uD`|`)sDn5IwHyg3NZ?WtQb}Ha&#nQ39VVM|)C-nbOafXN5yM#CXf7#A@nSPK;lu*n0>Xmq?#xgwrG&5`*c3O)Kw2|2mYmr4D(oS6 zpQQBb<+##|&T_OG`OUf*BxzH`eZgyq3bO63fOowR?}d~x%Xk1YNI- zA^3tN*JNPFP(p$u#EBzh)B?@i0u6tLY;uN-wNxapSj0%hUrOD7unZ-=Fq3pX zGS0bY_=#senCL5-b1Bn_tZPzF4NNiU^zE}2if811iETG_XDf{IciwwS)NnOlUb_)y zp&F@D%H2RcW2s6%C+MkR1ujeZjWX(eK>Jh%IPKYP#1s_uRgtXOJ8H3#gy<=A^$R@$ za~Vv^DugW4V=^~G28byt#P87K8}4>@p5PT-?4NBB(>&8_GHljk((A^Qw2a)d+V)5q zicG66y52fit5p#}mC>v_wYN`}sDDTEIjB2^+HytU=3equyQlF8MWMSmP}A9o71ejI zS)Lk0o;Q{zr@L~$Kll8kN-3pw_5d!xN-hcg`PdBYJ*9_KqxkC})k8V+>){r$B+61` zjFp1(C;G8rB{S7^f{YFg2IAKU9m%EGBdszharJZstEyJnUAlA(0~UEilEKcRh>P2C z`y;Gb&c!n)F(}(iIZNu#3ZY;2KAc^vXO~caj=O+qX81<`CD7b|cbydN=*Gs4&ON|N z{9(5C_1O*6`Vn`a_G<>^*03}h-aNfoxD`;WsV`W8Z6u>Hd!1mbhi_X`Q{=V5 z(X>!fg5P{C9`bNX(_`V$IE=dr){tsgQ8lw?T|dr&|E1G4vjiI% z%P;e>An@VnTT#wCRv@HDiG7<0fh_bVDG{Dg z{dBJdL1aW?L;@Y?2^v4>NG3=#&vYv%Y_Sb(U`+c#n)+&_b;~~ zPPZUln&IV~=4~i(wgUdE@8cCY>#<9~mLe*fRA;sz7$iZ2UrZZ=A=_JHOsk+pV$D+( z4S^9PFHD%xh4dS%v8NqOc$CBj%}ybQK-X44q$GB|)l3FwXQ;~gq=JTwSZ2nKFT9~? zypdXSa!_-Ew18G>6+%mBkc`Y?LXU0_wE!#N)lX_y#kINV=7($8YFF=6o;{}qiE zmv?E)M$1#38B`r~IN6tJy}9mtm)e@i^22ZxMOiH^7G1Wvx|2ukZAr6-WfrULm+4o6 zrFZSg4;3b@Hnn|l8(%Vlc19U}?#?724A|e0M3UYpWy{yjeM%|z8FzUuIrP!U^+H{+ z#P4}o=5%VFHwI3I;oylSi*D%VLDa34LpaIQrt0V!5PUG7oeKQWiPT4KecMbkk3TvN zPxga$+|jKHZy|vPwd>yJ5z-3JF*-QS^QgB9j8R&JC#D@3CvOYQaLW4vYgG1~zRsek zj`wT2$9g>XvvD4CjIxPy8awkMy$PK3?6C{kqYHCy5l7s*e#QG_h@;`d|^= zcn#s5NK-SEXYxvZB&%Ze#D20H0WAw;dgjT~HV%%a6v1%X>T}lX9JW@?jNOru4~xjb z1^C~oKggTcL0i!rEg*foc&+w&u7Is|HbiMd;>G$swC~A%<^b8K5I@r<3*=;-TqX-~ z;xn*~jm$o>2t+g@;ZuBQqs z0|xp&=ro&JP4@5ZDPI!YJtp|Szk4lba-CAVN{uKz|88RfY7L$qPko@6fW&=xjsll9 zEsQ^z+RR1YiA$HS!VPCkapRrW!B_jfaOgDOR3fB`o`GZ*D`0vG8oVBaaJ*kWPJwb zwYO&H7;-n)nt;`G=GXnk#4>u{C~kquwQJ3-nf4WzE-kjVk=W$!Y6hmTE8K0FbKfqQ zhp(p)$|j>QFAn!NB)+vtL3^6SF2=eSxWC46e>?ptk)%loN}w`+dw~}^D%9dq$RonQ zi8kDYa+9Y4o&MaF!SacJI5(BRaXhVd;Y7;HCija2D1l>TT5akBf?5W7UvdT+4-;y` zdbxSL%vS~^Bd8{+IW4Fsja=W5x~O)VGe_rm6%DQSj9wtpFh`%if^qNo0BcW|%Ut`Z z@ssV?;3?%_EJ<8{u_Qgt`u|gxB-Y2H#6LeXu(PrLuq4$d=|nF+E=f1o9eKDi?>^k5 zwSq%DhX}&ZD^-0W)?H;zp87Or>ZtPb+$JKdzrd)P>Jl0$sgPiU?zW_;=z)BjWeVN` zRHhEB`O`3S!=)~>xh~YF9%HIgp!{K2)lP>`p^g|k6<#A>mDJAkH+GT`kP9(B`3eUH z#p_I_L{$j)mO`=1WDEC>K(Qy4KkqFTV<%I{Su=tlP^KkRPKqo}iliOtR~YV(F*YnR zHk7LQlvwl0cwxt4VJFV2N{Le=30Z9f=JUs(Cc1@hbl}LCG!x%yMzpAzFeuYEDw8-Wb1^CdP+(Zt-pAo9jz@&BVn!g& z+^AW9%6Uz9GUsIAt@Z)?#&Yr{E3!o)f~F2Nl_75lAEri zzoS`(X*Fzn;ZGx`e2dZNo+T4po8!pC zWL2-FwH9;1kn!p&C>gh+A{3Ke*b@%90mu98SQvM?9PJnkom>}0B z##?5!xx3Bo3t5KmjPwv!2m4J^D}^Du5kD{SA8x z8FyZ?)rT*Ps&c&&AJhoY&0TtTu-nBdRTQXYf?b;l3)yS(6p{VE@ufW@(HKTUxbO>l z+oDg{wy|QCAIk{DQp~)g$y)S#CJ%7^WvXn}sokl`{RPGDqo>*`%3)1YuLwcfKLU9K> zu1E$6`4arAVVRq)UV*>`5M3YA*WE-t>AD$hT7o9?25 z1k<5g4<~S3TyIeW!_aywo)e~(ZG3qWX|U#?LBQ2wg;G!uZmM{zVS%_lP949!YsGWb zPMiKwZ#g)0GkKH6ufFLE?%EO#R~gdx_ht5uG-FoviQn4wZF$^5Bk3M17~YU`z250M zg%k$r8!)lx+XV(+CP!2e+xP3YAGRj6-9*0_S7vW|2^>wtfb!m;mj^N0z~M7_i*3No zMx>IM#dU2lN>oO0lqFr-v1)m26kdMAYWPMd!VRgj0UJj$B}v6zN!Oc*uL`-lJ#TU@V{7%c>ZxU`enlZAG;d;2EhH>xFr|Mj{sJr>WahrXL#+~ zv<~L3{Y)`|)uPKCMEI$^i_C^F{bQAQ z$tD_>N}f0x<6$C|hOaV;RAK}(!{+~fG_#Hi=DrDT@k`#=M1(HUf)k&W^M)E93pLVPnXVxyL9f~%UXd1to?X{Wi@%eSG{CfPq}{qiwyhW zvYpldY41R4c$Ywv`;{Lfqpp;iPSa8xB6;1X!qZS~oV$C4sk-42h=9%dJZoA1DZ*Wx z3f*I7AsE6Sbxh8yE^4P$zabBjGS6dqtYGgdi1B!5Eh38!BOl2yy3gAIf}iclSL2KA zx2&(Vyh9jfW0wfR*X>5fzh_cQ$Eq8_zNaf6yuq{~RqIGG8~AaNgOgWz}g zXa>?s#A3+R)qO{?tVE%mG(3ByfpE~gIHL*edE5$C#gd%}t(S&oaFWLN6e%C3SCZL& zqr>psoNc=Cn%~>!wb}6A+jS*Vly)Oi4J)j=?XIIq?8|28w`a~VRwRN#4(K^Nn6!IS zy49`&cr=4;`zs?U;f$^UQS3HXEE>0^R2c&x!-+Q}nKW^S6&rpTqn-QB*=wEE1AKy_ z$r4AfClp3Yo}b=ag@-9L4CD_am?Jr>M7VBpwOwVHxT-{syG=~*m7LXT4?s4h;rYKA zM2*QQ>jJ_f*+zc1{$MMVhhyw$gvmXHt)?dNn{|Y?%Ka6Xz z{szSS+ryTX^Cw)RU2DlE1g)|~9(c$XuB2m!I+t8AwZ7JkN~xMW*>+DoX&B{P zF?x!2{50^|z_*+RoyI<}UeRdmj3AgQL3=W6n<3IVtxZWmiQPT@?PSA84*DFK{6)-d zm3Z5ORH%v@qJmLrNsL)8nSe!B{UXjpix?giok2-@Qf7p53nG9bF>kbv7lVmHqb%-O zv2TvX6X{w`o|kB7rBvF(5|&E7V)W7}`j$!|eRR?(*t@IEm> z3K~fq_|wTX|VPI2=x^gT4~DXf=H@yJdVW6nOQEnp?^fLtC^^H6>%dgMeT-oYK5u&Xvc9 zO7lvNdoY2Pu8TthTH5T1YKf-&38b*LP&I0iPwIW~L_Q6o?4`5PsZxh#*vQxYmhT;$ zxOrnk%PFIz)bDq`wv82td3iW8k>Z=4jmPJv2a6{^uzxpnm>&LK2%{l2uaYw2vtI5r zsdOW^JR9b(Dl13ckJ>6fVk6ML>Fj*R)VfgieMit5yOBjPplmJb=F_gn#f^FO62Dc} zZ0SM6o7c7xk^R_<^?tYyrdpQAD&iNKI*O%}iixHA#Tnmo!w!>7F5Im+-Yn_k zfM7Ye&95tCea@HWAK*_iQsBq?W=&r#>b+pL$!l*h`$Awa>K4m|^sLog$-D5D*Jz7D4v!j!>9l}bMW1b%$jCK7@=^7sAQYGo)G7#0P^3^Ulyqs@Cw3l{B%r-|lfsml_ic#+-w&GiNjRi*eTnRt!r)6*^nADaehR-c9d8XDUqwqgUQg zi_cH$*=_fvpafp~m-)zfeTS8@<-TCXC5`FF9kK1|>vPE_hi78x6i5a~ZGKVj8Dj02 zj_`6Y+*FCZ@c4>$N}|Dl_D*D2j`{Q5R>=x#5xFHtH;B(+{@Xc=G&SPOOzMi*J;_oG}2bU_&){zuTQOnSNJy=wfS;2jZfLm~L zc(S{+PlXlYgl?|uO zD4*th_rbgZU$xPl(s4+*wjjB6i5I6C<}9?ym8ZMbZY=TCI}un@XC(@z?qEvn5v~k~ zXHanHS!jGz5?7aW7W!_@Oks?^f%#JXbwQAO+pYRMl73SQGY@07 z_sz~?8#cBuo|P176GN6EPtQ+!#ivw6qWa=KMXiq8m_+p1iA8#Fi9L_FQ~3@HFLGC2 zODO;Rj$p`b3-%iw27=@b0S1ECy&e1^>W~u{Ej-Jj{{_D9j+|rMvawJ(&Pc`Q2HLs` zZ?S`h5&hvxlFY1&*lJbxc68GHq=WUQ#NjLb!L{!v4ww zRKVCgwsZA)L1B{&!3}#)BhbWH^S1B3HG)@?phMnvP_`_CzUo~7tkV<73doi?^0|@L zIB<2P&is}0>ZG-EVLbt{=)2>}cbLjobwW&V7?@DUs5UZ9O&i|KP*-(XxQXMgz9cZO zV0ZKfFB}Arn&LdntS`1k>vF_-_!(vhXkY2M~hCbji3ldHBBL}5bQq!1+a)Y1#XWG|mZ@1c*R zNiP-e1Pql4Lz`k>2(llM;OaE2@H679JbiP}utI%>{%tyCA!jC1s7_rY!*8_XRWf<9 z+Ys$byLT}MSMggF%6AFzD=w|CA53+_>n>v2J_VcRj#HXXgY6K+{hKut1^IZ z2rKGj4zvhiVM<#~ZN8FWRnNYLl6w|$g2ewtZL{i4W3IfAgFo^seX3VtM7}Jm`9xk? z>h1XA!wN**+Q-VF#Ib&op%0$hRI}Ua?ss(NjYuh~P=r!K5v^9=Ae&pLo7q7WAw7pg zbAdxfO0!nD#eNUmW_|6|pCl7k!@Y_l`per=dW;E3&DHq$Zc4P5>S^U)6sB-z^JhCD+!%az zR<<*|xG}OT*&;ycH$}G|E$Q~8EEr@sj$-fOuy?JPGTYK`NMNhU3gCjLDJeqBMV=eI zM+iQUT;M)e!3tN^w@pHS<%p~wQBr9@d54tSB0pL>s3pc(fZR={H=~WtQlChY@dPo{ zqE}U?K3MQQ4`N6?4s{-*l^vdfWbiXHdprf#U@}XW$ICNI`<;NgKxCBEeWIT1K61im z!K20~3%)!7n&G0qJR_yEjRwPrvg^x}$K)slJ4!yPMZ`;Pt?w^-!29^J5a59gOzWt{kQ&>m&{tx2%z=nVNN0r7B46v}vw zNwAHS_WYM;P8q$m*?syufFvk-h5-uvJhw}dwcja+0t^fbxqLQ6b zsN=d+Xts0CEQ-{Wgcj{+F*8jXrlw{l-9pwZ$(FjM&@BmSqOc|Pm=vpmn7=XAb&!ux(QjRKvm4(OUa=Wk8YUNRxSpX{1f z)1IM;+{Dvtxm8W^psnnH*BQk=sDQ?NSJ&aI!_S;ZwJ`BplNs1fUbj4L%Tyf*3km~-aY)?;F2vpiCGrN(y}e> zn|R!HSE~%Qmvl_#c3laskhcfCXlTjOc2CF}S#yisP(?le%aSi<;vU0hqfGdXPQ-Qo zl$!cO#%s1W`g)w@Pyf;MLBWnPzkO*bIw}6T<2)=Vp?CA73H-Hfrja?BSJOKxY_+U5 zU7LKe-{)YjroVgM57!yw81~o6hwJ7i9PxWOWz@XMtMa>^MO<3CJXx?e?os5{LwBj2 zR(Xp!zVQ!2E`3g3=5`Rcnb}+gzBl&%(V*@5t>=qGJ>74m>vsN{QRM(;+-Z`0-W27t z-llt8%g0EMqc$O3&S^I9lQQy`$5&-lY1v;nnb>bYqkr`b_mTJb#pjK3AK&({&=D0r zj@;X9utV(Y*BBN`tI`@B^ZA)rcl@%}hLu}WH?2>dh`dN~-kgA;+nYDlPk)?tI8fT| z^=g>#bY@NaktMm6aiMpt?+e$qTHT~`f_^t=i-N=dzy3iB#(qjH}@n9P3+y;&ThU3rFSM-SqIe^Y5Ln zhr~687ureX#{1s;y%?3Tpfr2wijCa$`maU=&z&hYK50IR-E3I=`4e}4P~{}k--YF4 zO!t}F*5&_L@ukq>bj^L|qK<{n%MS8gW>`H4*f|2aE7)m+1!YJ3*1f(lo|Pv}6C6wvuCAG2kP==F_mm*Y5B0)8}0>xVMSDa+~g(RB-RB zrYTvu)&eI{^gNC6)KRg2M2k5K4MrIJa!wM~;pXLEe)}0O`Alnu`vb3Ag|&7yfVhY` zPd_WCF*p?1uiI8p*V;9)Ll&|%=taQ3H@>BM4P8=4db5^gZ4S*2*t}C$!%i^p%mF6@ zjfF)|rY9zR^4Lu^3~rl~Ie5ve6AzxH&XTzPymmz%lZrxk2yN*53ON5@w#B^&tI5^|@nush&@o^3Q#F z-OO|xCi(dHqH_4avf3!em#0fd4y?Ceb7y(`J~nI2Fq&qykrKhrFx_RGb*iqpwd-ug zz`rZ!JDz6L9&r?(DWz*JD_-bZP;s?q)91X0U#g*==tUm&mS>BvZdp2E_lF7fCnUoR zUPrw6ft9j$&xo+f(Pn`msY#yi#C79uzG{#;W=KPJ?!q}xqMLP1yW;HEovKygP5E!}zN;U`%Du$+D?5C!1r(wRph} z+RKWfEVJDv9{F?G?zRsDE+);N8yr_Zi$Ce!@c7YAk3%jPn$3~TUcM_faKsO-CM5=N zmSdf(;ras8q#3Of%N!pKNpiYlaVYEO!dotDy4`lyOc~gno?El+$3@S$Gl9<+O{P(b z!pGTW>G{lmSG=Ppz$|*CcI?~e+54kQ&eXz;yagebr$>&t8zP=~@aS^;arcrun%~|i%Up$=pCq5iqZ(h_-;`7yn{v~5VbtM=Gi{@2dQJX2 zerQU)=;0zO`RF>TEayezhEFlvyQxo3M(*fn%CXXTlSn;kvHHo#SF|_3ylfXr)_!rH zqV?q6m)PphfA4QCthVVtvBy*QM^Am*OCDXfFAqGW-#oTzNPJ^M>NUC5V2Zrlt7)~* zmxOb|HS3-?`#!wZQ)LmyS!THNab88!VbPE^Qr7ZM{#~$(q~g+~&V;W#JOL`6MIbiq z7{30e=qEOQ---F}db*xYV{!|*6T|JRf!U?hcqmQ2-p{c{GDv8N0@`y{+1-e>Ec} zZoaES-LY`N#X|6W*2YGV9Vp zNzd(0n;iM*on2(5X5=G;D}CBpUt5azs@kUsn-hl_IC&Lo4}Q!!Rp)Op#>rp{y~W?P zX#G`t;rr5tzuL_i{r0z-fF_St%+;{rzZ~M&U3gx%S<~<3qpsr*Y3+$?Qz~Zp`sfVW zJ|$?<`$mu28*Zb1dP55sWf3#dZbIB8gI~us>?i}YQVi>lH`YDMcd4CfGqNKjICl1> z#Mv(^)yI?=jkCG3=Xv(CCDC(h zpvZvqWzxkrX63nOzbe&8=V``*I->?{8@Bj$?o^~u%a}%havRT8d_IAyH1qF3)e(&=4 za-k(pcI_Nn+BWe?UBWAeF!{-@rNauce;(7O<>PrlwP8s>W7s6V%zf z?{UfWO`R4!5!&@O6TA(IYruno(SJNSa=c%4@B#a=beGU_4{Za_ikpkyUP`3YaZ?XF zI?QM(|KR!i8Jo^02@71Z#Gh`CoK)ku<^I{C@WDPFZ|(%@-4|c~xcd51y`E5$2%qZt z$X^fG`_sD{dV9uq>OtA2$vNlpe#yKmFCQL1X5wyB79i7uL=?YGAX0 zo0-Tm&eVEfI(lPyMBaRF-LZ9ZX1`&-Jvu$C(ebE$-cw0a_5=CD32*ZSRdrFHW2-w$ za`)QrTi4>)CNPU&n~!cYjB$);XuNbpv+UN3gzkWSnZ2Rbc4PciDo2} zeSGeZ@_5$IVCT(7v#E6Rb$63N%YCu*O&YhR@(v7|(J2VmzcF{(mvK|xHLgGJK78@V z2aoNtd5Lp}oImRp7@9ZO`$JgOGn?PzS0(MYZ3?h8x|B3UHnU)<+bXL?)%C&+Yjv+g zR2F4s8V)g~Q*XTZsi{1vXcfQX;&6imx0PRU-&Y<~2k|RC|BLT&`|cI}XZI`&p zEtJWZV%Lz63uN+n0E@=(raGYan?SrTbQQ_PLSs6GP63cxQ0VO?lip|HL9~lSt~H^C zK#p&;uod_@4w)>>guJP}q!<*yp6f;;gWRzat^z>p8A>HdNO?4bk)-2idzh$92=1i` zBjTX~@}#^#A#w{2KrU;^MM2ADGyAwe*h&Irk`0KI8MHoWVG8)Klu2fQ6|Hiwb?Mmu zt)c+_mj5bOH1H;PGPTU%}i*Rdzppr84UnwhYp7pv8Cfk`n8Iu`<1gtoe z!yo}uSpUj}WOHmi0U&e&7dneza~1``h_!H)NFYT1kqM-tV7Wx9bS8|$0D}xBI>AVo zqlruikipQ+m4qTU?dUklAyt(Shd6V&UO`IO;MsSsNGg*97#f|a3weE?33yT*?Dlz` zz!n6VilBmUEZ~s3MFyaD#9J6Kor1bvCFrV#3(4uh^_qw2M9*YsG=l{XRcmz!W6*G z#nRc8q0S6`!ns@9xZ81UzG(-%DB;|38{&4rqCsf~rgEo- z*@1zt!z%^q4P56Si97(wwtzqqtzDmIi%Wbw!c8-1Qcyf_M8L==KQ6$U~S&;V`6CtQKMHej1$4A zI4>l%quBv7mI7RuUW!bCk1KV?SP)#wAOsOhX;dZ}vkr(C|BXBDMUr8eq*8(Hxskib zsx_WTL@t)j?L`9Qt}}9jSt=2Wu|kTxB3;G4Oj7BjlJJg`+GO~D$&AGsIA2odxoq%8tBTzgzU z1nmen*>~{5G$Eh^Ldg(#(Qze|SqfJTPc1kzq$Y9262VHqRVoyI4@-oAQc8nq=X$wFQ~D6jEjV)M?5v);$dbah)3#u zRg#Oc<>(a;ZY0>dh z3iJgSR4blLh<%tR6t5D>MFO6wl|<}EwFyFAO@cHFR1Z;*WspqN`@7NxXsG>H+TTG| z8L|ISWJkVO6cQ@@4i-uvEfD$1@NG4Kc^<&>AAn~j0M8ZxzA*&wT@Zjh1nvyr!3yA= z7E*V5-$&BxA3Cjf`^_YkeC+53Hyq9$b0C068-Sx4zyb9Yy3n`CVr&RxF*pJEInh_> z&>^KKS;~@w>A~g6d1A?OYA@t~-U@=eNJR#a^k%#xkPOj7+FpKKiIZqkTj z3V0A+(gL&;ubR zgJc&5h%hGe1tA2A@E5156PZPhV02Ym|>X$-kdK^lXQZ=BS0a3K4V0Wmn}*LkXInH+Q%r#c3+ zX=Iy1Ajl&72tpj9HV@{g`5dvbx~-Uq!eqXPd&&NQAS9!Z=Yg;qUJ$gP2~|}O#0cs# zGtp+8G!Ig@0R*f217xYwgVcQvfo!@u4>p>bRr!J(n)*DNy5E=(T9Q=P!Zfw`g!`NC?k1u>DtrnVMwy4n~E$&e%-Ot!kuSuk3A zRb^qp>iAsJh_x7Lbk?Q$Vs1FkiP`L>Xb9p&Kg*14l#K&h5!-@nF3HigP3d@ zhXo1vNIvGX*(^W)Y;!&b5(xeM=&--PKg$mm2v`DtA&27+@i{C%0UMs}O?8$?FLASH + + /* The program code and other data goes into FLASH */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >FLASH + + /* Constant data goes into FLASH */ + .rodata : + { + . = ALIGN(4); + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(4); + } >FLASH + + .integrity (NOLOAD): + { + . = ALIGN(4); + *(.integrity) /* .integrity internal integrity protection of NVFile */ + *(.integrity*) /* .integrity* internal integrity protection of NVFile */ + . = ALIGN(4); + } >INTEGRITY + + .nvfile (NOLOAD): + { + . = ALIGN(4); + *(.nvfile) /* .nvfile persisted NV storage for the TPM */ + *(.nvfile*) /* .nvfile* persisted NV storage for the TPM */ + . = ALIGN(4); + } >NVFILE + + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH + .ARM : { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } >FLASH + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH + + /* used by the startup to initialize data */ + _sidata = LOADADDR(.data); + + /* Initialized data sections goes into RAM, load LMA copy after code */ + .data : + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + } >RAM AT> FLASH + + + /* Uninitialized data section */ + . = ALIGN(4); + .bss2 : + { + . = ALIGN(4); + *(.ram2) + *(.ram2*) + Middlewares\Platform\Cancel.o + Middlewares\Platform\Clock.o + Middlewares\Platform\Entropy.o +/* Middlewares\Platform\LocalityPlat.o*/ +/* Middlewares\Platform\NVMem.o*/ + Middlewares\Platform\PlatformData.o +/* Middlewares\Platform\PowerPlat.o*/ +/* Middlewares\Platform\PPPlat.o*/ +/* Middlewares\Platform\RunCommand.o*/ +/* Middlewares\Platform\Unique.o*/ + . = ALIGN(4); + } >RAM2 + .bss : + { + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >RAM + + /* User_heap_stack section, used to check that there is enough RAM left */ + ._user_heap_stack : + { + . = ALIGN(4); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(4); + } >RAM + + + + /* Remove information from the standard libraries */ + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} + + diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/main.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/main.c new file mode 100644 index 0000000..a09cdc8 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/main.c @@ -0,0 +1,409 @@ + +/** + ****************************************************************************** + * @file : main.c + * @brief : Main program body + ****************************************************************************** + * This notice applies to any and all portions of this file + * that are not between comment pairs USER CODE BEGIN and + * USER CODE END. Other portions of this file, whether + * inserted by the user or by software development tools + * are owned by their respective copyright owners. + * + * Copyright (c) 2018 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. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ +/* Includes ------------------------------------------------------------------*/ +#include "main.h" +#include "stm32l4xx_hal.h" +#include "usb_device.h" + +/* USER CODE BEGIN Includes */ +#include +#include +#include +#include "TpmDevice.h" +#include "StmUtil.h" + +/* USER CODE END Includes */ + +/* Private variables ---------------------------------------------------------*/ +RNG_HandleTypeDef hrng; + +RTC_HandleTypeDef hrtc; + +UART_HandleTypeDef huart2; + +/* USER CODE BEGIN PV */ +/* Private variables ---------------------------------------------------------*/ + +/* USER CODE END PV */ + +/* Private function prototypes -----------------------------------------------*/ +void SystemClock_Config(void); +static void MX_GPIO_Init(void); +static void MX_RNG_Init(void); +static void MX_RTC_Init(void); +static void MX_USART2_UART_Init(void); + +/* USER CODE BEGIN PFP */ +/* Private function prototypes -----------------------------------------------*/ +#define CPU_CORE_FREQUENCY_HZ 800000000 /* CPU core frequency in Hz */ +void SWO_Init(uint32_t portBits, uint32_t cpuCoreFreqHz); +/* USER CODE END PFP */ + +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/** + * @brief The application entry point. + * + * @retval None + */ +int main(void) +{ + /* USER CODE BEGIN 1 */ + + /* USER CODE END 1 */ + + /* MCU Configuration----------------------------------------------------------*/ + + /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ + HAL_Init(); + + /* USER CODE BEGIN Init */ + + /* USER CODE END Init */ + + /* Configure the system clock */ + SystemClock_Config(); + + /* USER CODE BEGIN SysInit */ + + /* USER CODE END SysInit */ + + /* Initialize all configured peripherals */ + MX_GPIO_Init(); + MX_RNG_Init(); + MX_RTC_Init(); + MX_USART2_UART_Init(); + MX_USB_DEVICE_Init(); + /* USER CODE BEGIN 2 */ + InitializeITM(); + fprintf(stderr, "\r\n\r\n=========================\r\n" + "= Nucleo-L476RG TPM 2.0 =\r\n" + "=========================\r\n"); + printf("Nucleo-L476RG TPM 2.0\r\n"); + + if(!TpmInitializeDevice()) + { + _Error_Handler(__FILE__, __LINE__); + } + + /* USER CODE END 2 */ + + /* Infinite loop */ + /* USER CODE BEGIN WHILE */ + while (1) + { + + /* USER CODE END WHILE */ + + /* USER CODE BEGIN 3 */ + if(!TpmOperationsLoop()) + { + _Error_Handler(__FILE__, __LINE__); + } + + } + /* USER CODE END 3 */ + +} + +/** + * @brief System Clock Configuration + * @retval None + */ +void SystemClock_Config(void) +{ + + RCC_OscInitTypeDef RCC_OscInitStruct; + RCC_ClkInitTypeDef RCC_ClkInitStruct; + RCC_PeriphCLKInitTypeDef PeriphClkInit; + + /**Configure LSE Drive Capability + */ + HAL_PWR_EnableBkUpAccess(); + + __HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW); + + /**Initializes the CPU, AHB and APB busses clocks + */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_LSE + |RCC_OSCILLATORTYPE_MSI; + RCC_OscInitStruct.LSEState = RCC_LSE_ON; + RCC_OscInitStruct.HSIState = RCC_HSI_ON; + RCC_OscInitStruct.HSICalibrationValue = 16; + RCC_OscInitStruct.MSIState = RCC_MSI_ON; + RCC_OscInitStruct.MSICalibrationValue = 0; + RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_11; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; + RCC_OscInitStruct.PLL.PLLM = 1; // <-- This one gets dropped by V1.11.0 add me manually back in when CubeMX ran + RCC_OscInitStruct.PLL.PLLN = 10; + RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7; + RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2; + RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2; + if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) + { + _Error_Handler(__FILE__, __LINE__); + } + + /**Initializes the CPU, AHB and APB busses clocks + */ + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK + |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; + + if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) + { + _Error_Handler(__FILE__, __LINE__); + } + + PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC|RCC_PERIPHCLK_USART2 + |RCC_PERIPHCLK_USB|RCC_PERIPHCLK_RNG; + PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_PCLK1; + PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE; + PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_MSI; + PeriphClkInit.RngClockSelection = RCC_RNGCLKSOURCE_MSI; + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) + { + _Error_Handler(__FILE__, __LINE__); + } + + /**Configure the main internal regulator output voltage + */ + if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK) + { + _Error_Handler(__FILE__, __LINE__); + } + + /**Configure the Systick interrupt time + */ + HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000); + + /**Configure the Systick + */ + HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); + + /**Enable MSI Auto calibration + */ + HAL_RCCEx_EnableMSIPLLMode(); + + /* SysTick_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0); +} + +/* RNG init function */ +static void MX_RNG_Init(void) +{ + + hrng.Instance = RNG; + if (HAL_RNG_Init(&hrng) != HAL_OK) + { + _Error_Handler(__FILE__, __LINE__); + } + +} + +/* RTC init function */ +static void MX_RTC_Init(void) +{ + + RTC_TimeTypeDef sTime; + RTC_DateTypeDef sDate; + + /**Initialize RTC Only + */ + hrtc.Instance = RTC; +if(HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR0) != 0x32F2){ + hrtc.Init.HourFormat = RTC_HOURFORMAT_24; + hrtc.Init.AsynchPrediv = 127; + hrtc.Init.SynchPrediv = 255; + hrtc.Init.OutPut = RTC_OUTPUT_DISABLE; + hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE; + hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH; + hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN; + if (HAL_RTC_Init(&hrtc) != HAL_OK) + { + _Error_Handler(__FILE__, __LINE__); + } + + /**Initialize RTC and set the Time and Date + */ + sTime.Hours = 0; + sTime.Minutes = 0; + sTime.Seconds = 0; + sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE; + sTime.StoreOperation = RTC_STOREOPERATION_RESET; + if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN) != HAL_OK) + { + _Error_Handler(__FILE__, __LINE__); + } + + sDate.WeekDay = RTC_WEEKDAY_MONDAY; + sDate.Month = RTC_MONTH_JANUARY; + sDate.Date = 1; + sDate.Year = 0; + + if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN) != HAL_OK) + { + _Error_Handler(__FILE__, __LINE__); + } + + HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR0,0x32F2); + } + +} + +/* USART2 init function */ +static void MX_USART2_UART_Init(void) +{ + + huart2.Instance = USART2; + huart2.Init.BaudRate = 115200; + huart2.Init.WordLength = UART_WORDLENGTH_8B; + huart2.Init.StopBits = UART_STOPBITS_1; + huart2.Init.Parity = UART_PARITY_NONE; + huart2.Init.Mode = UART_MODE_TX; + huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE; + huart2.Init.OverSampling = UART_OVERSAMPLING_16; + huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE; + huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT; + if (HAL_UART_Init(&huart2) != HAL_OK) + { + _Error_Handler(__FILE__, __LINE__); + } + +} + +/** Configure pins as + * Analog + * Input + * Output + * EVENT_OUT + * EXTI +*/ +static void MX_GPIO_Init(void) +{ + + GPIO_InitTypeDef GPIO_InitStruct; + + /* GPIO Ports Clock Enable */ + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOH_CLK_ENABLE(); + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + + /*Configure GPIO pin Output Level */ + HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET); + + /*Configure GPIO pin : B1_Pin */ + GPIO_InitStruct.Pin = B1_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(B1_GPIO_Port, &GPIO_InitStruct); + + /*Configure GPIO pin : LD2_Pin */ + GPIO_InitStruct.Pin = LD2_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(LD2_GPIO_Port, &GPIO_InitStruct); + +} + +/* USER CODE BEGIN 4 */ + +/* USER CODE END 4 */ + +/** + * @brief This function is executed in case of error occurrence. + * @param file: The file name as string. + * @param line: The line in file as a number. + * @retval None + */ +void _Error_Handler(char *file, int line) +{ + /* USER CODE BEGIN Error_Handler_Debug */ + dbgPrint("PANIC: EXECUTION HALTED %s@%d\r\n", file, line); + /* User can add his own implementation to report the HAL error return state */ + while(1) + { + } + /* USER CODE END Error_Handler_Debug */ +} + +#ifdef USE_FULL_ASSERT +/** + * @brief Reports the name of the source file and the source line number + * where the assert_param error has occurred. + * @param file: pointer to the source file name + * @param line: assert_param error line source number + * @retval None + */ +void assert_failed(uint8_t* file, uint32_t line) +{ + /* USER CODE BEGIN 6 */ + /* User can add his own implementation to report the file name and line number, + tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ + /* USER CODE END 6 */ +} +#endif /* USE_FULL_ASSERT */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/stm32l4xx_hal_msp.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/stm32l4xx_hal_msp.c new file mode 100644 index 0000000..be26bc5 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/stm32l4xx_hal_msp.c @@ -0,0 +1,225 @@ +/** + ****************************************************************************** + * File Name : stm32l4xx_hal_msp.c + * Description : This file provides code for the MSP Initialization + * and de-Initialization codes. + ****************************************************************************** + * This notice applies to any and all portions of this file + * that are not between comment pairs USER CODE BEGIN and + * USER CODE END. Other portions of this file, whether + * inserted by the user or by software development tools + * are owned by their respective copyright owners. + * + * Copyright (c) 2018 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. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +extern void _Error_Handler(char *, int); +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ +/** + * Initializes the Global MSP. + */ +void HAL_MspInit(void) +{ + /* USER CODE BEGIN MspInit 0 */ + + /* USER CODE END MspInit 0 */ + + __HAL_RCC_SYSCFG_CLK_ENABLE(); + __HAL_RCC_PWR_CLK_ENABLE(); + + HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4); + + /* System interrupt init*/ + /* MemoryManagement_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(MemoryManagement_IRQn, 0, 0); + /* BusFault_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(BusFault_IRQn, 0, 0); + /* UsageFault_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(UsageFault_IRQn, 0, 0); + /* SVCall_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(SVCall_IRQn, 0, 0); + /* DebugMonitor_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(DebugMonitor_IRQn, 0, 0); + /* PendSV_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(PendSV_IRQn, 0, 0); + /* SysTick_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0); + + /* USER CODE BEGIN MspInit 1 */ + + /* USER CODE END MspInit 1 */ +} + +void HAL_RNG_MspInit(RNG_HandleTypeDef* hrng) +{ + + if(hrng->Instance==RNG) + { + /* USER CODE BEGIN RNG_MspInit 0 */ + + /* USER CODE END RNG_MspInit 0 */ + /* Peripheral clock enable */ + __HAL_RCC_RNG_CLK_ENABLE(); + /* USER CODE BEGIN RNG_MspInit 1 */ + + /* USER CODE END RNG_MspInit 1 */ + } + +} + +void HAL_RNG_MspDeInit(RNG_HandleTypeDef* hrng) +{ + + if(hrng->Instance==RNG) + { + /* USER CODE BEGIN RNG_MspDeInit 0 */ + + /* USER CODE END RNG_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_RNG_CLK_DISABLE(); + /* USER CODE BEGIN RNG_MspDeInit 1 */ + + /* USER CODE END RNG_MspDeInit 1 */ + } + +} + +void HAL_RTC_MspInit(RTC_HandleTypeDef* hrtc) +{ + + if(hrtc->Instance==RTC) + { + /* USER CODE BEGIN RTC_MspInit 0 */ + + /* USER CODE END RTC_MspInit 0 */ + /* Peripheral clock enable */ + __HAL_RCC_RTC_ENABLE(); + /* USER CODE BEGIN RTC_MspInit 1 */ + + /* USER CODE END RTC_MspInit 1 */ + } + +} + +void HAL_RTC_MspDeInit(RTC_HandleTypeDef* hrtc) +{ + + if(hrtc->Instance==RTC) + { + /* USER CODE BEGIN RTC_MspDeInit 0 */ + + /* USER CODE END RTC_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_RTC_DISABLE(); + /* USER CODE BEGIN RTC_MspDeInit 1 */ + + /* USER CODE END RTC_MspDeInit 1 */ + } + +} + +void HAL_UART_MspInit(UART_HandleTypeDef* huart) +{ + + GPIO_InitTypeDef GPIO_InitStruct; + if(huart->Instance==USART2) + { + /* USER CODE BEGIN USART2_MspInit 0 */ + + /* USER CODE END USART2_MspInit 0 */ + /* Peripheral clock enable */ + __HAL_RCC_USART2_CLK_ENABLE(); + + /**USART2 GPIO Configuration + PA2 ------> USART2_TX + PA3 ------> USART2_RX + */ + GPIO_InitStruct.Pin = USART_TX_Pin|USART_RX_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF7_USART2; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* USER CODE BEGIN USART2_MspInit 1 */ + + /* USER CODE END USART2_MspInit 1 */ + } + +} + +void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) +{ + + if(huart->Instance==USART2) + { + /* USER CODE BEGIN USART2_MspDeInit 0 */ + + /* USER CODE END USART2_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_USART2_CLK_DISABLE(); + + /**USART2 GPIO Configuration + PA2 ------> USART2_TX + PA3 ------> USART2_RX + */ + HAL_GPIO_DeInit(GPIOA, USART_TX_Pin|USART_RX_Pin); + + /* USER CODE BEGIN USART2_MspDeInit 1 */ + + /* USER CODE END USART2_MspDeInit 1 */ + } + +} + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/stm32l4xx_it.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/stm32l4xx_it.c new file mode 100644 index 0000000..1a173f8 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/stm32l4xx_it.c @@ -0,0 +1,88 @@ +/** + ****************************************************************************** + * @file stm32l4xx_it.c + * @brief Interrupt Service Routines. + ****************************************************************************** + * + * COPYRIGHT(c) 2018 STMicroelectronics + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" +#include "stm32l4xx.h" +#include "stm32l4xx_it.h" + +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/* External variables --------------------------------------------------------*/ +extern PCD_HandleTypeDef hpcd_USB_OTG_FS; + +/******************************************************************************/ +/* Cortex-M4 Processor Interruption and Exception Handlers */ +/******************************************************************************/ + +/** +* @brief This function handles System tick timer. +*/ +void SysTick_Handler(void) +{ + /* USER CODE BEGIN SysTick_IRQn 0 */ + + /* USER CODE END SysTick_IRQn 0 */ + HAL_IncTick(); + HAL_SYSTICK_IRQHandler(); + /* USER CODE BEGIN SysTick_IRQn 1 */ + + /* USER CODE END SysTick_IRQn 1 */ +} + +/******************************************************************************/ +/* STM32L4xx Peripheral Interrupt Handlers */ +/* Add here the Interrupt Handlers for the used peripherals. */ +/* For the available peripheral interrupt handler names, */ +/* please refer to the startup file (startup_stm32l4xx.s). */ +/******************************************************************************/ + +/** +* @brief This function handles USB OTG FS global interrupt. +*/ +void OTG_FS_IRQHandler(void) +{ + /* USER CODE BEGIN OTG_FS_IRQn 0 */ + + /* USER CODE END OTG_FS_IRQn 0 */ + HAL_PCD_IRQHandler(&hpcd_USB_OTG_FS); + /* USER CODE BEGIN OTG_FS_IRQn 1 */ + + /* USER CODE END OTG_FS_IRQn 1 */ +} + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/system_stm32l4xx.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/system_stm32l4xx.c new file mode 100644 index 0000000..c76fe45 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/system_stm32l4xx.c @@ -0,0 +1,353 @@ +/** + ****************************************************************************** + * @file system_stm32l4xx.c + * @author MCD Application Team + * @brief CMSIS Cortex-M4 Device Peripheral Access Layer System Source File + * + * This file provides two functions and one global variable to be called from + * user application: + * - SystemInit(): This function is called at startup just after reset and + * before branch to main program. This call is made inside + * the "startup_stm32l4xx.s" file. + * + * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used + * by the user application to setup the SysTick + * timer or configure other parameters. + * + * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must + * be called whenever the core clock is changed + * during program execution. + * + * After each device reset the MSI (4 MHz) is used as system clock source. + * Then SystemInit() function is called, in "startup_stm32l4xx.s" file, to + * configure the system clock before to branch to main program. + * + * This file configures the system clock as follows: + *============================================================================= + *----------------------------------------------------------------------------- + * System Clock source | MSI + *----------------------------------------------------------------------------- + * SYSCLK(Hz) | 4000000 + *----------------------------------------------------------------------------- + * HCLK(Hz) | 4000000 + *----------------------------------------------------------------------------- + * AHB Prescaler | 1 + *----------------------------------------------------------------------------- + * APB1 Prescaler | 1 + *----------------------------------------------------------------------------- + * APB2 Prescaler | 1 + *----------------------------------------------------------------------------- + * PLL_M | 1 + *----------------------------------------------------------------------------- + * PLL_N | 8 + *----------------------------------------------------------------------------- + * PLL_P | 7 + *----------------------------------------------------------------------------- + * PLL_Q | 2 + *----------------------------------------------------------------------------- + * PLL_R | 2 + *----------------------------------------------------------------------------- + * PLLSAI1_P | NA + *----------------------------------------------------------------------------- + * PLLSAI1_Q | NA + *----------------------------------------------------------------------------- + * PLLSAI1_R | NA + *----------------------------------------------------------------------------- + * PLLSAI2_P | NA + *----------------------------------------------------------------------------- + * PLLSAI2_Q | NA + *----------------------------------------------------------------------------- + * PLLSAI2_R | NA + *----------------------------------------------------------------------------- + * Require 48MHz for USB OTG FS, | Disabled + * SDIO and RNG clock | + *----------------------------------------------------------------------------- + *============================================================================= + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32l4xx_system + * @{ + */ + +/** @addtogroup STM32L4xx_System_Private_Includes + * @{ + */ + +#include "stm32l4xx.h" + +#if !defined (HSE_VALUE) + #define HSE_VALUE 8000000U /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (MSI_VALUE) + #define MSI_VALUE 4000000U /*!< Value of the Internal oscillator in Hz*/ +#endif /* MSI_VALUE */ + +#if !defined (HSI_VALUE) + #define HSI_VALUE 16000000U /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @} + */ + +/** @addtogroup STM32L4xx_System_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32L4xx_System_Private_Defines + * @{ + */ + +/************************* Miscellaneous Configuration ************************/ +/*!< Uncomment the following line if you need to relocate your vector Table in + Internal SRAM. */ +/* #define VECT_TAB_SRAM */ +#define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field. + This value must be a multiple of 0x200. */ +/******************************************************************************/ +/** + * @} + */ + +/** @addtogroup STM32L4xx_System_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32L4xx_System_Private_Variables + * @{ + */ + /* The SystemCoreClock variable is updated in three ways: + 1) by calling CMSIS function SystemCoreClockUpdate() + 2) by calling HAL API function HAL_RCC_GetHCLKFreq() + 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency + Note: If you use this function to configure the system clock; then there + is no need to call the 2 first functions listed above, since SystemCoreClock + variable is updated automatically. + */ + uint32_t SystemCoreClock = 4000000U; + + const uint8_t AHBPrescTable[16] = {0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 1U, 2U, 3U, 4U, 6U, 7U, 8U, 9U}; + const uint8_t APBPrescTable[8] = {0U, 0U, 0U, 0U, 1U, 2U, 3U, 4U}; + const uint32_t MSIRangeTable[12] = {100000U, 200000U, 400000U, 800000U, 1000000U, 2000000U, \ + 4000000U, 8000000U, 16000000U, 24000000U, 32000000U, 48000000U}; +/** + * @} + */ + +/** @addtogroup STM32L4xx_System_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32L4xx_System_Private_Functions + * @{ + */ + +/** + * @brief Setup the microcontroller system. + * @param None + * @retval None + */ + +void SystemInit(void) +{ + /* FPU settings ------------------------------------------------------------*/ + #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */ + #endif + + /* Reset the RCC clock configuration to the default reset state ------------*/ + /* Set MSION bit */ + RCC->CR |= RCC_CR_MSION; + + /* Reset CFGR register */ + RCC->CFGR = 0x00000000U; + + /* Reset HSEON, CSSON , HSION, and PLLON bits */ + RCC->CR &= 0xEAF6FFFFU; + + /* Reset PLLCFGR register */ + RCC->PLLCFGR = 0x00001000U; + + /* Reset HSEBYP bit */ + RCC->CR &= 0xFFFBFFFFU; + + /* Disable all interrupts */ + RCC->CIER = 0x00000000U; + + /* Configure the Vector Table location add offset address ------------------*/ +#ifdef VECT_TAB_SRAM + SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */ +#else + SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */ +#endif +} + +/** + * @brief Update SystemCoreClock variable according to Clock Register Values. + * The SystemCoreClock variable contains the core clock (HCLK), it can + * be used by the user application to setup the SysTick timer or configure + * other parameters. + * + * @note Each time the core clock (HCLK) changes, this function must be called + * to update SystemCoreClock variable value. Otherwise, any configuration + * based on this variable will be incorrect. + * + * @note - The system frequency computed by this function is not the real + * frequency in the chip. It is calculated based on the predefined + * constant and the selected clock source: + * + * - If SYSCLK source is MSI, SystemCoreClock will contain the MSI_VALUE(*) + * + * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(**) + * + * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(***) + * + * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(***) + * or HSI_VALUE(*) or MSI_VALUE(*) multiplied/divided by the PLL factors. + * + * (*) MSI_VALUE is a constant defined in stm32l4xx_hal.h file (default value + * 4 MHz) but the real value may vary depending on the variations + * in voltage and temperature. + * + * (**) HSI_VALUE is a constant defined in stm32l4xx_hal.h file (default value + * 16 MHz) but the real value may vary depending on the variations + * in voltage and temperature. + * + * (***) HSE_VALUE is a constant defined in stm32l4xx_hal.h file (default value + * 8 MHz), user has to ensure that HSE_VALUE is same as the real + * frequency of the crystal used. Otherwise, this function may + * have wrong result. + * + * - The result of this function could be not correct when using fractional + * value for HSE crystal. + * + * @param None + * @retval None + */ +void SystemCoreClockUpdate(void) +{ + uint32_t tmp = 0U, msirange = 0U, pllvco = 0U, pllr = 2U, pllsource = 0U, pllm = 2U; + + /* Get MSI Range frequency--------------------------------------------------*/ + if((RCC->CR & RCC_CR_MSIRGSEL) == RESET) + { /* MSISRANGE from RCC_CSR applies */ + msirange = (RCC->CSR & RCC_CSR_MSISRANGE) >> 8U; + } + else + { /* MSIRANGE from RCC_CR applies */ + msirange = (RCC->CR & RCC_CR_MSIRANGE) >> 4U; + } + /*MSI frequency range in HZ*/ + msirange = MSIRangeTable[msirange]; + + /* Get SYSCLK source -------------------------------------------------------*/ + switch (RCC->CFGR & RCC_CFGR_SWS) + { + case 0x00: /* MSI used as system clock source */ + SystemCoreClock = msirange; + break; + + case 0x04: /* HSI used as system clock source */ + SystemCoreClock = HSI_VALUE; + break; + + case 0x08: /* HSE used as system clock source */ + SystemCoreClock = HSE_VALUE; + break; + + case 0x0C: /* PLL used as system clock source */ + /* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLN + SYSCLK = PLL_VCO / PLLR + */ + pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC); + pllm = ((RCC->PLLCFGR & RCC_PLLCFGR_PLLM) >> 4U) + 1U ; + + switch (pllsource) + { + case 0x02: /* HSI used as PLL clock source */ + pllvco = (HSI_VALUE / pllm); + break; + + case 0x03: /* HSE used as PLL clock source */ + pllvco = (HSE_VALUE / pllm); + break; + + default: /* MSI used as PLL clock source */ + pllvco = (msirange / pllm); + break; + } + pllvco = pllvco * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 8U); + pllr = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> 25U) + 1U) * 2U; + SystemCoreClock = pllvco/pllr; + break; + + default: + SystemCoreClock = msirange; + break; + } + /* Compute HCLK clock frequency --------------------------------------------*/ + /* Get HCLK prescaler */ + tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4U)]; + /* HCLK clock frequency */ + SystemCoreClock >>= tmp; +} + + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/usb_device.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/usb_device.c new file mode 100644 index 0000000..75e5d8d --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/usb_device.c @@ -0,0 +1,173 @@ +/** + ****************************************************************************** + * @file : usb_device.c + * @version : v2.0_Cube + * @brief : This file implements the USB Device + ****************************************************************************** + * This notice applies to any and all portions of this file + * that are not between comment pairs USER CODE BEGIN and + * USER CODE END. Other portions of this file, whether + * inserted by the user or by software development tools + * are owned by their respective copyright owners. + * + * Copyright (c) 2018 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. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ + +#include "usb_device.h" +#include "usbd_core.h" +#include "usbd_desc.h" +#include "usbd_cdc.h" +#include "usbd_cdc_if.h" + +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* USER CODE BEGIN PV */ +/* Private variables ---------------------------------------------------------*/ + +/* USER CODE END PV */ + +/* USER CODE BEGIN PFP */ +/* Private function prototypes -----------------------------------------------*/ + +/* USER CODE END PFP */ + +/* Return USBD_OK if the Battery Charging Detection mode (BCD) is used, else USBD_FAIL. */ +extern USBD_StatusTypeDef USBD_LL_BatteryCharging(USBD_HandleTypeDef *pdev); + +/* USB Device Core handle declaration. */ +USBD_HandleTypeDef hUsbDeviceFS; + +/* + * -- Insert your variables declaration here -- + */ +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/* + * -- Insert your external function declaration here -- + */ +/* USER CODE BEGIN 1 */ +void MX_USB_DEVICE_DeInit(void) +{ + USBD_DeInit(&hUsbDeviceFS); +} + +/* USER CODE END 1 */ + +/** + * Init USB device Library, add supported class and start the library + * @retval None + */ +void MX_USB_DEVICE_Init(void) +{ + /* USER CODE BEGIN USB_DEVICE_Init_PreTreatment */ + + /* USER CODE END USB_DEVICE_Init_PreTreatment */ + + /* Init Device Library, add supported class and start the library. */ + USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS); + USBD_RegisterClass(&hUsbDeviceFS, &USBD_CDC); + USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops_FS); + /* Verify if the Battery Charging Detection mode (BCD) is used : */ + /* If yes, the USB device is started in the HAL_PCDEx_BCD_Callback */ + /* upon reception of PCD_BCD_DISCOVERY_COMPLETED message. */ + /* If no, the USB device is started now. */ + if (USBD_LL_BatteryCharging(&hUsbDeviceFS) != USBD_OK) { + USBD_Start(&hUsbDeviceFS); + } + /* USER CODE BEGIN USB_DEVICE_Init_PostTreatment */ + + /* USER CODE END USB_DEVICE_Init_PostTreatment */ +} + +/** + * @brief Send BCD message to user layer + * @param hpcd: PCD handle + * @param msg: LPM message + * @retval None + */ +void HAL_PCDEx_BCD_Callback(PCD_HandleTypeDef *hpcd, PCD_BCD_MsgTypeDef msg) +{ + USBD_HandleTypeDef usbdHandle = hUsbDeviceFS; + + /* USER CODE BEGIN 7 */ + if (hpcd->battery_charging_active == ENABLE) + { + switch(msg) + { + case PCD_BCD_CONTACT_DETECTION: + + break; + + case PCD_BCD_STD_DOWNSTREAM_PORT: + + break; + + case PCD_BCD_CHARGING_DOWNSTREAM_PORT: + + break; + + case PCD_BCD_DEDICATED_CHARGING_PORT: + + break; + + case PCD_BCD_DISCOVERY_COMPLETED: + USBD_Start(&usbdHandle); + break; + + case PCD_BCD_ERROR: + default: + break; + } + } + /* USER CODE END 7 */ +} + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/usbd_cdc_if.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/usbd_cdc_if.c new file mode 100644 index 0000000..f5490fe --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/usbd_cdc_if.c @@ -0,0 +1,392 @@ +/** + ****************************************************************************** + * @file : usbd_cdc_if.c + * @version : v2.0_Cube + * @brief : Usb device for Virtual Com Port. + ****************************************************************************** + * This notice applies to any and all portions of this file + * that are not between comment pairs USER CODE BEGIN and + * USER CODE END. Other portions of this file, whether + * inserted by the user or by software development tools + * are owned by their respective copyright owners. + * + * Copyright (c) 2018 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. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_cdc_if.h" + +/* USER CODE BEGIN INCLUDE */ +#include +#include +#include "StmUtil.h" +#include "stm32l4xx_hal.h" + +/* USER CODE END INCLUDE */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ + +/* USER CODE BEGIN PV */ +/* Private variables ---------------------------------------------------------*/ + +/* USER CODE END PV */ + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY + * @brief Usb device library. + * @{ + */ + +/** @addtogroup USBD_CDC_IF + * @{ + */ + +/** @defgroup USBD_CDC_IF_Private_TypesDefinitions USBD_CDC_IF_Private_TypesDefinitions + * @brief Private types. + * @{ + */ + +/* USER CODE BEGIN PRIVATE_TYPES */ +#define CDC_RTS_MASK 0x0002 +#define CDC_DTR_MASK 0x0001 +void TpmConnectionReset(void); +int TpmSignalEvent(uint8_t* Buf, uint32_t *Len); + +/* USER CODE END PRIVATE_TYPES */ + +/** + * @} + */ + +/** @defgroup USBD_CDC_IF_Private_Defines USBD_CDC_IF_Private_Defines + * @brief Private defines. + * @{ + */ + +/* USER CODE BEGIN PRIVATE_DEFINES */ +/* Define size for the receive and transmit buffer over CDC */ +/* It's up to user to redefine and/or remove those define */ +#define APP_RX_DATA_SIZE 2048 +#define APP_TX_DATA_SIZE 2048 +typedef struct +{ + uint8_t bReqType; + uint8_t bRequest; + uint16_t wVal; + uint16_t wIndex; + uint16_t wLength; +} USBD_SETUP_PKT, *PUSBD_SETUP_PKT; +extern RTC_HandleTypeDef hrtc; +/* USER CODE END PRIVATE_DEFINES */ + +/** + * @} + */ + +/** @defgroup USBD_CDC_IF_Private_Macros USBD_CDC_IF_Private_Macros + * @brief Private macros. + * @{ + */ + +/* USER CODE BEGIN PRIVATE_MACRO */ + +/* USER CODE END PRIVATE_MACRO */ + +/** + * @} + */ + +/** @defgroup USBD_CDC_IF_Private_Variables USBD_CDC_IF_Private_Variables + * @brief Private variables. + * @{ + */ +/* Create buffer for reception and transmission */ +/* It's up to user to redefine and/or remove those define */ +/** Received data over USB are stored in this buffer */ +uint8_t UserRxBufferFS[APP_RX_DATA_SIZE]; + +/** Data to send over USB CDC are stored in this buffer */ +uint8_t UserTxBufferFS[APP_TX_DATA_SIZE]; + +/* USER CODE BEGIN PRIVATE_VARIABLES */ + +/* USER CODE END PRIVATE_VARIABLES */ + +/** + * @} + */ + +/** @defgroup USBD_CDC_IF_Exported_Variables USBD_CDC_IF_Exported_Variables + * @brief Public variables. + * @{ + */ + +extern USBD_HandleTypeDef hUsbDeviceFS; + +/* USER CODE BEGIN EXPORTED_VARIABLES */ +USBD_CDC_LineCodingTypeDef LineCoding = +{ + 115200, /* baud rate*/ + 0x00, /* stop bits-1*/ + 0x00, /* parity - none*/ + 0x08 /* nb. of bits 8*/ +}; +volatile uint8_t CDC_RTS = 0; // RequestToSend +volatile uint8_t CDC_DTR = 0; // DataTerminalReady + +/* USER CODE END EXPORTED_VARIABLES */ + +/** + * @} + */ + +/** @defgroup USBD_CDC_IF_Private_FunctionPrototypes USBD_CDC_IF_Private_FunctionPrototypes + * @brief Private functions declaration. + * @{ + */ + +static int8_t CDC_Init_FS(void); +static int8_t CDC_DeInit_FS(void); +static int8_t CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t length); +static int8_t CDC_Receive_FS(uint8_t* pbuf, uint32_t *Len); + +/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */ + +/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */ + +/** + * @} + */ + +USBD_CDC_ItfTypeDef USBD_Interface_fops_FS = +{ + CDC_Init_FS, + CDC_DeInit_FS, + CDC_Control_FS, + CDC_Receive_FS +}; + +/* Private functions ---------------------------------------------------------*/ +/** + * @brief Initializes the CDC media low layer over the FS USB IP + * @retval USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CDC_Init_FS(void) +{ + /* USER CODE BEGIN 3 */ + /* Set Application Buffers */ + USBD_CDC_SetTxBuffer(&hUsbDeviceFS, UserTxBufferFS, 0); + USBD_CDC_SetRxBuffer(&hUsbDeviceFS, UserRxBufferFS); + return (USBD_OK); + /* USER CODE END 3 */ +} + +/** + * @brief DeInitializes the CDC media low layer + * @retval USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CDC_DeInit_FS(void) +{ + /* USER CODE BEGIN 4 */ + return (USBD_OK); + /* USER CODE END 4 */ +} + +/** + * @brief Manage the CDC class requests + * @param cmd: Command code + * @param pbuf: Buffer containing command data (request parameters) + * @param length: Number of data to be sent (in bytes) + * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t length) +{ + /* USER CODE BEGIN 5 */ + char parity[] = {'N', 'O', 'E', 'M', 'S'}; + uint8_t stop[] = {1, 15, 2}; + switch (cmd) + { + case CDC_SEND_ENCAPSULATED_COMMAND: + + break; + + case CDC_GET_ENCAPSULATED_RESPONSE: + + break; + + case CDC_SET_COMM_FEATURE: + + break; + + case CDC_GET_COMM_FEATURE: + + break; + + case CDC_CLEAR_COMM_FEATURE: + + break; + + /*******************************************************************************/ + /* Line Coding Structure */ + /*-----------------------------------------------------------------------------*/ + /* Offset | Field | Size | Value | Description */ + /* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/ + /* 4 | bCharFormat | 1 | Number | Stop bits */ + /* 0 - 1 Stop bit */ + /* 1 - 1.5 Stop bits */ + /* 2 - 2 Stop bits */ + /* 5 | bParityType | 1 | Number | Parity */ + /* 0 - None */ + /* 1 - Odd */ + /* 2 - Even */ + /* 3 - Mark */ + /* 4 - Space */ + /* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */ + /*******************************************************************************/ + case CDC_SET_LINE_CODING: + { + LineCoding.bitrate = pbuf[0] | (pbuf[1] << 8) | (pbuf[2] << 16) | (pbuf[3] << 24); + LineCoding.format = pbuf[4]; + LineCoding.paritytype = pbuf[5]; + LineCoding.datatype = pbuf[6]; + dbgPrint("CDC_SET_LINE_CODING: %lu-%d%c%d\r\n", LineCoding.bitrate, LineCoding.datatype, parity[LineCoding.paritytype], stop[LineCoding.format]); + break; + } + + case CDC_GET_LINE_CODING: + { + pbuf[0] = (uint8_t)(LineCoding.bitrate); + pbuf[1] = (uint8_t)(LineCoding.bitrate >> 8); + pbuf[2] = (uint8_t)(LineCoding.bitrate >> 16); + pbuf[3] = (uint8_t)(LineCoding.bitrate >> 24); + pbuf[4] = LineCoding.format; + pbuf[5] = LineCoding.paritytype; + pbuf[6] = LineCoding.datatype; + dbgPrint("CDC_GET_LINE_CODING: %lu-%d%c%d\r\n", LineCoding.bitrate, LineCoding.datatype, parity[LineCoding.paritytype], stop[LineCoding.format]); + break; + } + + case CDC_SET_CONTROL_LINE_STATE: + { + PUSBD_SETUP_PKT setupPkt = (PUSBD_SETUP_PKT)pbuf; + CDC_RTS = ((setupPkt->wVal & CDC_RTS_MASK) != 0); + CDC_DTR = ((setupPkt->wVal & CDC_DTR_MASK) != 0); + dbgPrint("CDC_SET_CONTROL_LINE_STATE: RTS=%d, DTR=%d\r\n", CDC_RTS, CDC_DTR); + // Reset any ongoing cmd transfers + TpmConnectionReset(); + break; + } + + case CDC_SEND_BREAK: + + break; + + default: + break; + } + + return (USBD_OK); + /* USER CODE END 5 */ +} + +/** + * @brief Data received over USB OUT endpoint are sent over CDC interface + * through this function. + * + * @note + * This function will block any OUT packet reception on USB endpoint + * untill exiting this function. If you exit this function before transfer + * is complete on CDC interface (ie. using DMA controller) it will result + * in receiving more data while previous ones are still not sent. + * + * @param Buf: Buffer of data to be received + * @param Len: Number of data received (in bytes) + * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len) +{ + /* USER CODE BEGIN 6 */ + if(!TpmSignalEvent(Buf, Len)) + { + return(USBD_FAIL); + } + + USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]); + USBD_CDC_ReceivePacket(&hUsbDeviceFS); + return (USBD_OK); + /* USER CODE END 6 */ +} + +/** + * @brief CDC_Transmit_FS + * Data to send over USB IN endpoint are sent over CDC interface + * through this function. + * @note + * + * + * @param Buf: Buffer of data to be sent + * @param Len: Number of data to be sent (in bytes) + * @retval USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY + */ +uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len) +{ + uint8_t result = USBD_OK; + /* USER CODE BEGIN 7 */ + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData; + if (hcdc->TxState != 0){ + return USBD_BUSY; + } + USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len); + result = USBD_CDC_TransmitPacket(&hUsbDeviceFS); + /* USER CODE END 7 */ + return result; +} + +/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */ + +/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/usbd_conf.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/usbd_conf.c new file mode 100644 index 0000000..1b9075f --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/usbd_conf.c @@ -0,0 +1,894 @@ +/** + ****************************************************************************** + * @file : usbd_conf.c + * @version : v2.0_Cube + * @brief : This file implements the board support package for the USB device library + ****************************************************************************** + * This notice applies to any and all portions of this file + * that are not between comment pairs USER CODE BEGIN and + * USER CODE END. Other portions of this file, whether + * inserted by the user or by software development tools + * are owned by their respective copyright owners. + * + * Copyright (c) 2018 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. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx.h" +#include "stm32l4xx_hal.h" +#include "usbd_def.h" +#include "usbd_core.h" +#include "usbd_cdc.h" + +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ + +/* USER CODE BEGIN PV */ +/* Private variables ---------------------------------------------------------*/ + +/* USER CODE END PV */ + +PCD_HandleTypeDef hpcd_USB_OTG_FS; +void _Error_Handler(char * file, int line); + +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/* Exported function prototypes ----------------------------------------------*/ +extern USBD_StatusTypeDef USBD_LL_BatteryCharging(USBD_HandleTypeDef *pdev); + +/* USER CODE BEGIN PFP */ +/* Private function prototypes -----------------------------------------------*/ + +/* USER CODE END PFP */ + +/* Private functions ---------------------------------------------------------*/ + +/* USER CODE BEGIN 1 */ +static void SystemClockConfig_Resume(void); + +/* USER CODE END 1 */ + +void HAL_PCDEx_SetConnectionState(PCD_HandleTypeDef *hpcd, uint8_t state); +extern void SystemClock_Config(void); + +/******************************************************************************* + LL Driver Callbacks (PCD -> USB Device Library) +*******************************************************************************/ +/* MSP Init */ + +void HAL_PCD_MspInit(PCD_HandleTypeDef* pcdHandle) +{ + GPIO_InitTypeDef GPIO_InitStruct; + if(pcdHandle->Instance==USB_OTG_FS) + { + /* USER CODE BEGIN USB_OTG_FS_MspInit 0 */ + + /* USER CODE END USB_OTG_FS_MspInit 0 */ + + /**USB_OTG_FS GPIO Configuration + PA11 ------> USB_OTG_FS_DM + PA12 ------> USB_OTG_FS_DP + */ + GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* Peripheral clock enable */ + __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); + + /* Enable VDDUSB */ + if(__HAL_RCC_PWR_IS_CLK_DISABLED()) + { + __HAL_RCC_PWR_CLK_ENABLE(); + HAL_PWREx_EnableVddUSB(); + __HAL_RCC_PWR_CLK_DISABLE(); + } + else + { + HAL_PWREx_EnableVddUSB(); + } + + /* Peripheral interrupt init */ + HAL_NVIC_SetPriority(OTG_FS_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(OTG_FS_IRQn); + /* USER CODE BEGIN USB_OTG_FS_MspInit 1 */ + + /* USER CODE END USB_OTG_FS_MspInit 1 */ + } +} + +void HAL_PCD_MspDeInit(PCD_HandleTypeDef* pcdHandle) +{ + if(pcdHandle->Instance==USB_OTG_FS) + { + /* USER CODE BEGIN USB_OTG_FS_MspDeInit 0 */ + + /* USER CODE END USB_OTG_FS_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_USB_OTG_FS_CLK_DISABLE(); + + /**USB_OTG_FS GPIO Configuration + PA11 ------> USB_OTG_FS_DM + PA12 ------> USB_OTG_FS_DP + */ + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11|GPIO_PIN_12); + + /* Disable VDDUSB */ + if(__HAL_RCC_PWR_IS_CLK_DISABLED()) + { + __HAL_RCC_PWR_CLK_ENABLE(); + HAL_PWREx_DisableVddUSB(); + __HAL_RCC_PWR_CLK_DISABLE(); + } + else + { + HAL_PWREx_DisableVddUSB(); + } + + /* Peripheral interrupt Deinit*/ + HAL_NVIC_DisableIRQ(OTG_FS_IRQn); + + /* USER CODE BEGIN USB_OTG_FS_MspDeInit 1 */ + + /* USER CODE END USB_OTG_FS_MspDeInit 1 */ + } +} + +/** + * @brief Setup stage callback + * @param hpcd: PCD handle + * @retval None + */ +void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd) +{ + USBD_LL_SetupStage((USBD_HandleTypeDef*)hpcd->pData, (uint8_t *)hpcd->Setup); +} + +/** + * @brief Data Out stage callback. + * @param hpcd: PCD handle + * @param epnum: Endpoint number + * @retval None + */ +void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) +{ + USBD_LL_DataOutStage((USBD_HandleTypeDef*)hpcd->pData, epnum, hpcd->OUT_ep[epnum].xfer_buff); +} + +/** + * @brief Data In stage callback. + * @param hpcd: PCD handle + * @param epnum: Endpoint number + * @retval None + */ +void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) +{ + USBD_LL_DataInStage((USBD_HandleTypeDef*)hpcd->pData, epnum, hpcd->IN_ep[epnum].xfer_buff); +} + +/** + * @brief SOF callback. + * @param hpcd: PCD handle + * @retval None + */ +void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) +{ + USBD_LL_SOF((USBD_HandleTypeDef*)hpcd->pData); +} + +/** + * @brief Reset callback. + * @param hpcd: PCD handle + * @retval None + */ +void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd) +{ + USBD_SpeedTypeDef speed = USBD_SPEED_FULL; + + /* Set USB current speed. */ + switch (hpcd->Init.speed) + { + case PCD_SPEED_FULL: + speed = USBD_SPEED_FULL; + break; + + default: + speed = USBD_SPEED_FULL; + break; + } + USBD_LL_SetSpeed((USBD_HandleTypeDef*)hpcd->pData, speed); + + /* Reset Device. */ + USBD_LL_Reset((USBD_HandleTypeDef*)hpcd->pData); +} + +/** + * @brief Suspend callback. + * When Low power mode is enabled the debug cannot be used (IAR, Keil doesn't support it) + * @param hpcd: PCD handle + * @retval None + */ +void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd) +{ + __HAL_PCD_GATE_PHYCLOCK(hpcd); + /* Inform USB library that core enters in suspend Mode. */ + USBD_LL_Suspend((USBD_HandleTypeDef*)hpcd->pData); + /* Enter in STOP mode. */ + /* USER CODE BEGIN 2 */ + if (hpcd->Init.low_power_enable) + { + /* Set SLEEPDEEP bit and SleepOnExit of Cortex System Control Register. */ + SCB->SCR |= (uint32_t)((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk)); + } + /* USER CODE END 2 */ +} + +/** + * @brief Resume callback. + * When Low power mode is enabled the debug cannot be used (IAR, Keil doesn't support it) + * @param hpcd: PCD handle + * @retval None + */ +void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd) +{ + __HAL_PCD_UNGATE_PHYCLOCK(hpcd); + + /* USER CODE BEGIN 3 */ + if (hpcd->Init.low_power_enable) + { + /* Reset SLEEPDEEP bit of Cortex System Control Register. */ + SCB->SCR &= (uint32_t)~((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk)); + SystemClockConfig_Resume(); + } + /* USER CODE END 3 */ + USBD_LL_Resume((USBD_HandleTypeDef*)hpcd->pData); +} + +/** + * @brief ISOOUTIncomplete callback. + * @param hpcd: PCD handle + * @param epnum: Endpoint number + * @retval None + */ +void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) +{ + USBD_LL_IsoOUTIncomplete((USBD_HandleTypeDef*)hpcd->pData, epnum); +} + +/** + * @brief ISOINIncomplete callback. + * @param hpcd: PCD handle + * @param epnum: Endpoint number + * @retval None + */ +void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) +{ + USBD_LL_IsoINIncomplete((USBD_HandleTypeDef*)hpcd->pData, epnum); +} + +/** + * @brief Connect callback. + * @param hpcd: PCD handle + * @retval None + */ +void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd) +{ + USBD_LL_DevConnected((USBD_HandleTypeDef*)hpcd->pData); +} + +/** + * @brief Disconnect callback. + * @param hpcd: PCD handle + * @retval None + */ +void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd) +{ + USBD_LL_DevDisconnected((USBD_HandleTypeDef*)hpcd->pData); +} + +/******************************************************************************* + LL Driver Interface (USB Device Library --> PCD) +*******************************************************************************/ + +/** + * @brief Initializes the low level portion of the device driver. + * @param pdev: Device handle + * @retval USBD status + */ +USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev) +{ + /* Init USB Ip. */ + if (pdev->id == DEVICE_FS) { + /* Enable USB power on Pwrctrl CR2 register. */ + /* Link the driver to the stack. */ + hpcd_USB_OTG_FS.pData = pdev; + pdev->pData = &hpcd_USB_OTG_FS; + + hpcd_USB_OTG_FS.Instance = USB_OTG_FS; + hpcd_USB_OTG_FS.Init.dev_endpoints = 6; + hpcd_USB_OTG_FS.Init.speed = PCD_SPEED_FULL; + hpcd_USB_OTG_FS.Init.ep0_mps = DEP0CTL_MPS_64; + hpcd_USB_OTG_FS.Init.phy_itface = PCD_PHY_EMBEDDED; + hpcd_USB_OTG_FS.Init.Sof_enable = DISABLE; + hpcd_USB_OTG_FS.Init.low_power_enable = DISABLE; + hpcd_USB_OTG_FS.Init.lpm_enable = DISABLE; + hpcd_USB_OTG_FS.Init.battery_charging_enable = DISABLE; + hpcd_USB_OTG_FS.Init.use_dedicated_ep1 = DISABLE; + hpcd_USB_OTG_FS.Init.vbus_sensing_enable = DISABLE; + if (HAL_PCD_Init(&hpcd_USB_OTG_FS) != HAL_OK) + { + _Error_Handler(__FILE__, __LINE__); + } + + HAL_PCDEx_SetRxFiFo(&hpcd_USB_OTG_FS, 0x80); + HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 0, 0x40); + HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 1, 0x80); + } + return USBD_OK; +} + +/** + * @brief De-Initializes the low level portion of the device driver. + * @param pdev: Device handle + * @retval USBD status + */ +USBD_StatusTypeDef USBD_LL_DeInit(USBD_HandleTypeDef *pdev) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBD_StatusTypeDef usb_status = USBD_OK; + + hal_status = HAL_PCD_DeInit(pdev->pData); + + switch (hal_status) { + case HAL_OK : + usb_status = USBD_OK; + break; + case HAL_ERROR : + usb_status = USBD_FAIL; + break; + case HAL_BUSY : + usb_status = USBD_BUSY; + break; + case HAL_TIMEOUT : + usb_status = USBD_FAIL; + break; + default : + usb_status = USBD_FAIL; + break; + } + return usb_status; +} + +/** + * @brief Starts the low level portion of the device driver. + * @param pdev: Device handle + * @retval USBD status + */ +USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBD_StatusTypeDef usb_status = USBD_OK; + + hal_status = HAL_PCD_Start(pdev->pData); + + switch (hal_status) { + case HAL_OK : + usb_status = USBD_OK; + break; + case HAL_ERROR : + usb_status = USBD_FAIL; + break; + case HAL_BUSY : + usb_status = USBD_BUSY; + break; + case HAL_TIMEOUT : + usb_status = USBD_FAIL; + break; + default : + usb_status = USBD_FAIL; + break; + } + return usb_status; +} + +/** + * @brief Stops the low level portion of the device driver. + * @param pdev: Device handle + * @retval USBD status + */ +USBD_StatusTypeDef USBD_LL_Stop(USBD_HandleTypeDef *pdev) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBD_StatusTypeDef usb_status = USBD_OK; + + hal_status = HAL_PCD_Stop(pdev->pData); + + switch (hal_status) { + case HAL_OK : + usb_status = USBD_OK; + break; + case HAL_ERROR : + usb_status = USBD_FAIL; + break; + case HAL_BUSY : + usb_status = USBD_BUSY; + break; + case HAL_TIMEOUT : + usb_status = USBD_FAIL; + break; + default : + usb_status = USBD_FAIL; + break; + } + return usb_status; +} + +/** + * @brief Opens an endpoint of the low level driver. + * @param pdev: Device handle + * @param ep_addr: Endpoint number + * @param ep_type: Endpoint type + * @param ep_mps: Endpoint max packet size + * @retval USBD status + */ +USBD_StatusTypeDef USBD_LL_OpenEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t ep_type, uint16_t ep_mps) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBD_StatusTypeDef usb_status = USBD_OK; + + hal_status = HAL_PCD_EP_Open(pdev->pData, ep_addr, ep_mps, ep_type); + + switch (hal_status) { + case HAL_OK : + usb_status = USBD_OK; + break; + case HAL_ERROR : + usb_status = USBD_FAIL; + break; + case HAL_BUSY : + usb_status = USBD_BUSY; + break; + case HAL_TIMEOUT : + usb_status = USBD_FAIL; + break; + default : + usb_status = USBD_FAIL; + break; + } + return usb_status; +} + +/** + * @brief Closes an endpoint of the low level driver. + * @param pdev: Device handle + * @param ep_addr: Endpoint number + * @retval USBD status + */ +USBD_StatusTypeDef USBD_LL_CloseEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBD_StatusTypeDef usb_status = USBD_OK; + + hal_status = HAL_PCD_EP_Close(pdev->pData, ep_addr); + + switch (hal_status) { + case HAL_OK : + usb_status = USBD_OK; + break; + case HAL_ERROR : + usb_status = USBD_FAIL; + break; + case HAL_BUSY : + usb_status = USBD_BUSY; + break; + case HAL_TIMEOUT : + usb_status = USBD_FAIL; + break; + default : + usb_status = USBD_FAIL; + break; + } + return usb_status; +} + +/** + * @brief Flushes an endpoint of the Low Level Driver. + * @param pdev: Device handle + * @param ep_addr: Endpoint number + * @retval USBD status + */ +USBD_StatusTypeDef USBD_LL_FlushEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBD_StatusTypeDef usb_status = USBD_OK; + + hal_status = HAL_PCD_EP_Flush(pdev->pData, ep_addr); + + switch (hal_status) { + case HAL_OK : + usb_status = USBD_OK; + break; + case HAL_ERROR : + usb_status = USBD_FAIL; + break; + case HAL_BUSY : + usb_status = USBD_BUSY; + break; + case HAL_TIMEOUT : + usb_status = USBD_FAIL; + break; + default : + usb_status = USBD_FAIL; + break; + } + return usb_status; +} + +/** + * @brief Sets a Stall condition on an endpoint of the Low Level Driver. + * @param pdev: Device handle + * @param ep_addr: Endpoint number + * @retval USBD status + */ +USBD_StatusTypeDef USBD_LL_StallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBD_StatusTypeDef usb_status = USBD_OK; + + hal_status = HAL_PCD_EP_SetStall(pdev->pData, ep_addr); + + switch (hal_status) { + case HAL_OK : + usb_status = USBD_OK; + break; + case HAL_ERROR : + usb_status = USBD_FAIL; + break; + case HAL_BUSY : + usb_status = USBD_BUSY; + break; + case HAL_TIMEOUT : + usb_status = USBD_FAIL; + break; + default : + usb_status = USBD_FAIL; + break; + } + return usb_status; +} + +/** + * @brief Clears a Stall condition on an endpoint of the Low Level Driver. + * @param pdev: Device handle + * @param ep_addr: Endpoint number + * @retval USBD status + */ +USBD_StatusTypeDef USBD_LL_ClearStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBD_StatusTypeDef usb_status = USBD_OK; + + hal_status = HAL_PCD_EP_ClrStall(pdev->pData, ep_addr); + + switch (hal_status) { + case HAL_OK : + usb_status = USBD_OK; + break; + case HAL_ERROR : + usb_status = USBD_FAIL; + break; + case HAL_BUSY : + usb_status = USBD_BUSY; + break; + case HAL_TIMEOUT : + usb_status = USBD_FAIL; + break; + default : + usb_status = USBD_FAIL; + break; + } + return usb_status; +} + +/** + * @brief Returns Stall condition. + * @param pdev: Device handle + * @param ep_addr: Endpoint number + * @retval Stall (1: Yes, 0: No) + */ +uint8_t USBD_LL_IsStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) +{ + PCD_HandleTypeDef *hpcd = (PCD_HandleTypeDef*) pdev->pData; + + if((ep_addr & 0x80) == 0x80) + { + return hpcd->IN_ep[ep_addr & 0x7F].is_stall; + } + else + { + return hpcd->OUT_ep[ep_addr & 0x7F].is_stall; + } +} + +/** + * @brief Assigns a USB address to the device. + * @param pdev: Device handle + * @param dev_addr: Device address + * @retval USBD status + */ +USBD_StatusTypeDef USBD_LL_SetUSBAddress(USBD_HandleTypeDef *pdev, uint8_t dev_addr) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBD_StatusTypeDef usb_status = USBD_OK; + + hal_status = HAL_PCD_SetAddress(pdev->pData, dev_addr); + + switch (hal_status) { + case HAL_OK : + usb_status = USBD_OK; + break; + case HAL_ERROR : + usb_status = USBD_FAIL; + break; + case HAL_BUSY : + usb_status = USBD_BUSY; + break; + case HAL_TIMEOUT : + usb_status = USBD_FAIL; + break; + default : + usb_status = USBD_FAIL; + break; + } + return usb_status; +} + +/** + * @brief Transmits data over an endpoint. + * @param pdev: Device handle + * @param ep_addr: Endpoint number + * @param pbuf: Pointer to data to be sent + * @param size: Data size + * @retval USBD status + */ +USBD_StatusTypeDef USBD_LL_Transmit(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t *pbuf, uint16_t size) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBD_StatusTypeDef usb_status = USBD_OK; + + hal_status = HAL_PCD_EP_Transmit(pdev->pData, ep_addr, pbuf, size); + + switch (hal_status) { + case HAL_OK : + usb_status = USBD_OK; + break; + case HAL_ERROR : + usb_status = USBD_FAIL; + break; + case HAL_BUSY : + usb_status = USBD_BUSY; + break; + case HAL_TIMEOUT : + usb_status = USBD_FAIL; + break; + default : + usb_status = USBD_FAIL; + break; + } + return usb_status; +} + +/** + * @brief Prepares an endpoint for reception. + * @param pdev: Device handle + * @param ep_addr: Endpoint number + * @param pbuf: Pointer to data to be received + * @param size: Data size + * @retval USBD status + */ +USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t *pbuf, uint16_t size) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBD_StatusTypeDef usb_status = USBD_OK; + + hal_status = HAL_PCD_EP_Receive(pdev->pData, ep_addr, pbuf, size); + + switch (hal_status) { + case HAL_OK : + usb_status = USBD_OK; + break; + case HAL_ERROR : + usb_status = USBD_FAIL; + break; + case HAL_BUSY : + usb_status = USBD_BUSY; + break; + case HAL_TIMEOUT : + usb_status = USBD_FAIL; + break; + default : + usb_status = USBD_FAIL; + break; + } + return usb_status; +} + +/** + * @brief Returns the last transfered packet size. + * @param pdev: Device handle + * @param ep_addr: Endpoint number + * @retval Recived Data Size + */ +uint32_t USBD_LL_GetRxDataSize(USBD_HandleTypeDef *pdev, uint8_t ep_addr) +{ + return HAL_PCD_EP_GetRxCount((PCD_HandleTypeDef*) pdev->pData, ep_addr); +} + +#if (USBD_LPM_ENABLED == 1) +/** + * @brief Send LPM message to user layer + * @param hpcd: PCD handle + * @param msg: LPM message + * @retval None + */ +void HAL_PCDEx_LPM_Callback(PCD_HandleTypeDef *hpcd, PCD_LPM_MsgTypeDef msg) +{ + switch (msg) + { + case PCD_LPM_L0_ACTIVE: + if (hpcd->Init.low_power_enable) + { + SystemClock_Config(); + + /* Reset SLEEPDEEP bit of Cortex System Control Register. */ + SCB->SCR &= (uint32_t)~((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk)); + } + __HAL_PCD_UNGATE_PHYCLOCK(hpcd); + USBD_LL_Resume(hpcd->pData); + break; + + case PCD_LPM_L1_ACTIVE: + __HAL_PCD_GATE_PHYCLOCK(hpcd); + USBD_LL_Suspend(hpcd->pData); + + /* Enter in STOP mode. */ + if (hpcd->Init.low_power_enable) + { + /* Set SLEEPDEEP bit and SleepOnExit of Cortex System Control Register. */ + SCB->SCR |= (uint32_t)((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk)); + } + break; + } +} +#endif /* (USBD_LPM_ENABLED == 1) */ + +/** + * @brief Delays routine for the USB Device Library. + * @param Delay: Delay in ms + * @retval None + */ +void USBD_LL_Delay(uint32_t Delay) +{ + HAL_Delay(Delay); +} + +/** + * @brief Static single allocation. + * @param size: Size of allocated memory + * @retval None + */ +void *USBD_static_malloc(uint32_t size) +{ + static uint32_t mem[(sizeof(USBD_CDC_HandleTypeDef)/4)+1];/* On 32-bit boundary */ + return mem; +} + +/** + * @brief Dummy memory free + * @param p: Pointer to allocated memory address + * @retval None + */ +void USBD_static_free(void *p) +{ + +} + +/* USER CODE BEGIN 5 */ +/** + * @brief Configures system clock after wake-up from USB resume callBack: + * enable HSI, PLL and select PLL as system clock source. + * @retval None + */ +static void SystemClockConfig_Resume(void) +{ + SystemClock_Config(); +} +/* USER CODE END 5 */ + +/** + * @brief Software device connection + * @param hpcd: PCD handle + * @param state: Connection state (0: disconnected / 1: connected) + * @retval None + */ +void HAL_PCDEx_SetConnectionState(PCD_HandleTypeDef *hpcd, uint8_t state) +{ + /* USER CODE BEGIN 6 */ + if (state == 1) + { + /* Configure Low connection state. */ + + } + else + { + /* Configure High connection state. */ + + } + /* USER CODE END 6 */ +} + +/** + * @brief Verify if the Battery Charging Detection mode (BCD) is used : + * return USBD_OK if true + * else return USBD_FAIL if false + * @param pdev: Device handle + * @retval USBD status + */ +USBD_StatusTypeDef USBD_LL_BatteryCharging(USBD_HandleTypeDef *pdev) +{ + PCD_HandleTypeDef *hpcd = (PCD_HandleTypeDef*)pdev->pData; + if (hpcd->Init.battery_charging_enable == ENABLE) + { + return USBD_OK; + } + else + { + return USBD_FAIL; + } +} + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/usbd_desc.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/usbd_desc.c new file mode 100644 index 0000000..2e3a7e1 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/Src/usbd_desc.c @@ -0,0 +1,405 @@ +/** + ****************************************************************************** + * @file : usbd_desc.c + * @version : v2.0_Cube + * @brief : This file implements the USB device descriptors. + ****************************************************************************** + * This notice applies to any and all portions of this file + * that are not between comment pairs USER CODE BEGIN and + * USER CODE END. Other portions of this file, whether + * inserted by the user or by software development tools + * are owned by their respective copyright owners. + * + * Copyright (c) 2018 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. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_core.h" +#include "usbd_desc.h" +#include "usbd_conf.h" + +/* USER CODE BEGIN INCLUDE */ + +/* USER CODE END INCLUDE */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ + +/* USER CODE BEGIN PV */ +/* Private variables ---------------------------------------------------------*/ + +/* USER CODE END PV */ + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY + * @{ + */ + +/** @addtogroup USBD_DESC + * @{ + */ + +/** @defgroup USBD_DESC_Private_TypesDefinitions USBD_DESC_Private_TypesDefinitions + * @brief Private types. + * @{ + */ + +/* USER CODE BEGIN PRIVATE_TYPES */ + +/* USER CODE END PRIVATE_TYPES */ + +/** + * @} + */ + +/** @defgroup USBD_DESC_Private_Defines USBD_DESC_Private_Defines + * @brief Private defines. + * @{ + */ + +#define USBD_VID 1155 +#define USBD_LANGID_STRING 1033 +#define USBD_MANUFACTURER_STRING "STMicroelectronics" +#define USBD_PID_FS 22336 +#define USBD_PRODUCT_STRING_FS "STM32 Virtual ComPort" +#define USBD_SERIALNUMBER_STRING_FS "00000000001A" +#define USBD_CONFIGURATION_STRING_FS "CDC Config" +#define USBD_INTERFACE_STRING_FS "CDC Interface" + +#define USB_SIZ_BOS_DESC 0x0C + +/* USER CODE BEGIN PRIVATE_DEFINES */ + +/* USER CODE END PRIVATE_DEFINES */ + +/** + * @} + */ + +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/** @defgroup USBD_DESC_Private_Macros USBD_DESC_Private_Macros + * @brief Private macros. + * @{ + */ + +/* USER CODE BEGIN PRIVATE_MACRO */ + +/* USER CODE END PRIVATE_MACRO */ + +/** + * @} + */ + +/** @defgroup USBD_DESC_Private_FunctionPrototypes USBD_DESC_Private_FunctionPrototypes + * @brief Private functions declaration. + * @{ + */ + +uint8_t * USBD_FS_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +uint8_t * USBD_FS_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +uint8_t * USBD_FS_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +uint8_t * USBD_FS_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +uint8_t * USBD_FS_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +uint8_t * USBD_FS_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +uint8_t * USBD_FS_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); + +#ifdef USB_SUPPORT_USER_STRING_DESC +uint8_t * USBD_FS_USRStringDesc(USBD_SpeedTypeDef speed, uint8_t idx, uint16_t *length); +#endif /* USB_SUPPORT_USER_STRING_DESC */ + +#if (USBD_LPM_ENABLED == 1) +uint8_t * USBD_FS_USR_BOSDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +#endif /* (USBD_LPM_ENABLED == 1) */ + +/** + * @} + */ + +/** @defgroup USBD_DESC_Private_Variables USBD_DESC_Private_Variables + * @brief Private variables. + * @{ + */ + +USBD_DescriptorsTypeDef FS_Desc = +{ + USBD_FS_DeviceDescriptor +, USBD_FS_LangIDStrDescriptor +, USBD_FS_ManufacturerStrDescriptor +, USBD_FS_ProductStrDescriptor +, USBD_FS_SerialStrDescriptor +, USBD_FS_ConfigStrDescriptor +, USBD_FS_InterfaceStrDescriptor +#if (USBD_LPM_ENABLED == 1) +, USBD_FS_USR_BOSDescriptor +#endif /* (USBD_LPM_ENABLED == 1) */ +}; + +#if defined ( __ICCARM__ ) /* IAR Compiler */ + #pragma data_alignment=4 +#endif /* defined ( __ICCARM__ ) */ +/** USB standard device descriptor. */ +__ALIGN_BEGIN uint8_t USBD_FS_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END = +{ + 0x12, /*bLength */ + USB_DESC_TYPE_DEVICE, /*bDescriptorType*/ +#if (USBD_LPM_ENABLED == 1) + 0x01, /*bcdUSB */ /* changed to USB version 2.01 + in order to support LPM L1 suspend + resume test of USBCV3.0*/ +#else + 0x00, /*bcdUSB */ +#endif /* (USBD_LPM_ENABLED == 1) */ + 0x02, + 0x02, /*bDeviceClass*/ + 0x02, /*bDeviceSubClass*/ + 0x00, /*bDeviceProtocol*/ + USB_MAX_EP0_SIZE, /*bMaxPacketSize*/ + LOBYTE(USBD_VID), /*idVendor*/ + HIBYTE(USBD_VID), /*idVendor*/ + LOBYTE(USBD_PID_FS), /*idProduct*/ + HIBYTE(USBD_PID_FS), /*idProduct*/ + 0x00, /*bcdDevice rel. 2.00*/ + 0x02, + USBD_IDX_MFC_STR, /*Index of manufacturer string*/ + USBD_IDX_PRODUCT_STR, /*Index of product string*/ + USBD_IDX_SERIAL_STR, /*Index of serial number string*/ + USBD_MAX_NUM_CONFIGURATION /*bNumConfigurations*/ +}; + +/* USB_DeviceDescriptor */ +/** BOS descriptor. */ +#if (USBD_LPM_ENABLED == 1) +#if defined ( __ICCARM__ ) /* IAR Compiler */ + #pragma data_alignment=4 +#endif /* defined ( __ICCARM__ ) */ +__ALIGN_BEGIN uint8_t USBD_FS_BOSDesc[USB_SIZ_BOS_DESC] __ALIGN_END = +{ + 0x5, + USB_DESC_TYPE_BOS, + 0xC, + 0x0, + 0x1, /* 1 device capability*/ + /* device capability*/ + 0x7, + USB_DEVICE_CAPABITY_TYPE, + 0x2, + 0x2, /* LPM capability bit set*/ + 0x0, + 0x0, + 0x0 +}; +#endif /* (USBD_LPM_ENABLED == 1) */ + +/** + * @} + */ + +/** @defgroup USBD_DESC_Private_Variables USBD_DESC_Private_Variables + * @brief Private variables. + * @{ + */ + +#if defined ( __ICCARM__ ) /* IAR Compiler */ + #pragma data_alignment=4 +#endif /* defined ( __ICCARM__ ) */ + +/** USB lang indentifier descriptor. */ +__ALIGN_BEGIN uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC] __ALIGN_END = +{ + USB_LEN_LANGID_STR_DESC, + USB_DESC_TYPE_STRING, + LOBYTE(USBD_LANGID_STRING), + HIBYTE(USBD_LANGID_STRING) +}; + +#if defined ( __ICCARM__ ) /* IAR Compiler */ + #pragma data_alignment=4 +#endif /* defined ( __ICCARM__ ) */ +/* Internal string descriptor. */ +__ALIGN_BEGIN uint8_t USBD_StrDesc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END; + +/** + * @} + */ + +/** @defgroup USBD_DESC_Private_Functions USBD_DESC_Private_Functions + * @brief Private functions. + * @{ + */ + +/** + * @brief Return the device descriptor + * @param speed : Current device speed + * @param length : Pointer to data length variable + * @retval Pointer to descriptor buffer + */ +uint8_t * USBD_FS_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) +{ + *length = sizeof(USBD_FS_DeviceDesc); + return USBD_FS_DeviceDesc; +} + +/** + * @brief Return the LangID string descriptor + * @param speed : Current device speed + * @param length : Pointer to data length variable + * @retval Pointer to descriptor buffer + */ +uint8_t * USBD_FS_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) +{ + *length = sizeof(USBD_LangIDDesc); + return USBD_LangIDDesc; +} + +/** + * @brief Return the product string descriptor + * @param speed : Current device speed + * @param length : Pointer to data length variable + * @retval Pointer to descriptor buffer + */ +uint8_t * USBD_FS_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) +{ + if(speed == 0) + { + USBD_GetString((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length); + } + else + { + USBD_GetString((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length); + } + return USBD_StrDesc; +} + +/** + * @brief Return the manufacturer string descriptor + * @param speed : Current device speed + * @param length : Pointer to data length variable + * @retval Pointer to descriptor buffer + */ +uint8_t * USBD_FS_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) +{ + USBD_GetString((uint8_t *)USBD_MANUFACTURER_STRING, USBD_StrDesc, length); + return USBD_StrDesc; +} + +/** + * @brief Return the serial number string descriptor + * @param speed : Current device speed + * @param length : Pointer to data length variable + * @retval Pointer to descriptor buffer + */ +uint8_t * USBD_FS_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) +{ + if(speed == USBD_SPEED_HIGH) + { + USBD_GetString((uint8_t *)USBD_SERIALNUMBER_STRING_FS, USBD_StrDesc, length); + } + else + { + USBD_GetString((uint8_t *)USBD_SERIALNUMBER_STRING_FS, USBD_StrDesc, length); + } + return USBD_StrDesc; +} + +/** + * @brief Return the configuration string descriptor + * @param speed : Current device speed + * @param length : Pointer to data length variable + * @retval Pointer to descriptor buffer + */ +uint8_t * USBD_FS_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) +{ + if(speed == USBD_SPEED_HIGH) + { + USBD_GetString((uint8_t *)USBD_CONFIGURATION_STRING_FS, USBD_StrDesc, length); + } + else + { + USBD_GetString((uint8_t *)USBD_CONFIGURATION_STRING_FS, USBD_StrDesc, length); + } + return USBD_StrDesc; +} + +/** + * @brief Return the interface string descriptor + * @param speed : Current device speed + * @param length : Pointer to data length variable + * @retval Pointer to descriptor buffer + */ +uint8_t * USBD_FS_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) +{ + if(speed == 0) + { + USBD_GetString((uint8_t *)USBD_INTERFACE_STRING_FS, USBD_StrDesc, length); + } + else + { + USBD_GetString((uint8_t *)USBD_INTERFACE_STRING_FS, USBD_StrDesc, length); + } + return USBD_StrDesc; +} + +#if (USBD_LPM_ENABLED == 1) +/** + * @brief Return the BOS descriptor + * @param speed : Current device speed + * @param length : Pointer to data length variable + * @retval Pointer to descriptor buffer + */ +uint8_t * USBD_FS_USR_BOSDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) +{ + *length = sizeof(USBD_FS_BOSDesc); + return (uint8_t*)USBD_FS_BOSDesc; +} +#endif /* (USBD_LPM_ENABLED == 1) */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/mx.scratch b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/mx.scratch new file mode 100644 index 0000000..aafcf5a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/mx.scratch @@ -0,0 +1,91 @@ + + +D:\VS\brianTPM\Samples\Nucleo-TPM\L476RG\\Nucleo-L476RG +C +..\Drivers\CMSIS +C:\Users\Stefanth\STM32Cube\Repository\STM32Cube_FW_L4_V1.11.0\Drivers\CMSIS +TrueSTUDIO +0 + + + + + + + + + + + + + + + + + Nucleo-L476RG + STM32L476RGTx + 0x200 + 0xf000 + + NUCLEO-L476RG + + true + swd + + 1 + + + + + + + + + + + + __weak=__attribute__((weak)) + __packed=__attribute__((__packed__)) + + + + + + + USE_FULL_LL_DRIVER + MBEDTLS_CONFIG_FILE="mbedtls_config.h" + + + + + ..\Inc + ..\Drivers\STM32L4xx_HAL_Driver\Inc + ..\Drivers\STM32L4xx_HAL_Driver\Inc\Legacy + ..\Middlewares\ST\STM32_USB_Device_Library\Core\Inc + ..\Middlewares\ST\STM32_USB_Device_Library\Class\CDC\Inc + ..\Drivers\CMSIS\Device\ST\STM32L4xx\Include + ..\Drivers\CMSIS\Include + + + + + + true + false + + + + Inc + + + Src + + + Drivers + + + Middlewares + + + + diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/startup/startup_stm32l476xx.s b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/startup/startup_stm32l476xx.s new file mode 100644 index 0000000..f353700 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L476RG/startup/startup_stm32l476xx.s @@ -0,0 +1,524 @@ +/** + ****************************************************************************** + * @file startup_stm32l476xx.s + * @author MCD Application Team + * @brief STM32L476xx devices vector table GCC toolchain. + * This module performs: + * - Set the initial SP + * - Set the initial PC == Reset_Handler, + * - Set the vector table entries with the exceptions ISR address, + * - Configure the clock system + * - Branches to main in the C library (which eventually + * calls main()). + * After Reset the Cortex-M4 processor is in Thread mode, + * priority is Privileged, and the Stack is set to Main. + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + + .syntax unified + .cpu cortex-m4 + .fpu softvfp + .thumb + +.global g_pfnVectors +.global Default_Handler + +/* start address for the initialization values of the .data section. +defined in linker script */ +.word _sidata +/* start address for the .data section. defined in linker script */ +.word _sdata +/* end address for the .data section. defined in linker script */ +.word _edata +/* start address for the .bss section. defined in linker script */ +.word _sbss +/* end address for the .bss section. defined in linker script */ +.word _ebss + +.equ BootRAM, 0xF1E0F85F +/** + * @brief This is the code that gets called when the processor first + * starts execution following a reset event. Only the absolutely + * necessary set is performed, after which the application + * supplied main() routine is called. + * @param None + * @retval : None +*/ + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + ldr sp, =_estack /* Atollic update: set stack pointer */ + +/* Copy the data segment initializers from flash to SRAM */ + movs r1, #0 + b LoopCopyDataInit + +CopyDataInit: + ldr r3, =_sidata + ldr r3, [r3, r1] + str r3, [r0, r1] + adds r1, r1, #4 + +LoopCopyDataInit: + ldr r0, =_sdata + ldr r3, =_edata + adds r2, r0, r1 + cmp r2, r3 + bcc CopyDataInit + ldr r2, =_sbss + b LoopFillZerobss +/* Zero fill the bss segment. */ +FillZerobss: + movs r3, #0 + str r3, [r2], #4 + +LoopFillZerobss: + ldr r3, = _ebss + cmp r2, r3 + bcc FillZerobss + +/* Call the clock system intitialization function.*/ + bl SystemInit +/* Call static constructors */ + bl __libc_init_array +/* Call the application's entry point.*/ + bl main + +LoopForever: + b LoopForever + +.size Reset_Handler, .-Reset_Handler + +/** + * @brief This is the code that gets called when the processor receives an + * unexpected interrupt. This simply enters an infinite loop, preserving + * the system state for examination by a debugger. + * + * @param None + * @retval : None +*/ + .section .text.Default_Handler,"ax",%progbits +Default_Handler: +Infinite_Loop: + b Infinite_Loop + .size Default_Handler, .-Default_Handler +/****************************************************************************** +* +* The minimal vector table for a Cortex-M4. Note that the proper constructs +* must be placed on this to ensure that it ends up at physical address +* 0x0000.0000. +* +******************************************************************************/ + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + .size g_pfnVectors, .-g_pfnVectors + + +g_pfnVectors: + .word _estack + .word Reset_Handler + .word NMI_Handler + .word HardFault_Handler + .word MemManage_Handler + .word BusFault_Handler + .word UsageFault_Handler + .word 0 + .word 0 + .word 0 + .word 0 + .word SVC_Handler + .word DebugMon_Handler + .word 0 + .word PendSV_Handler + .word SysTick_Handler + .word WWDG_IRQHandler + .word PVD_PVM_IRQHandler + .word TAMP_STAMP_IRQHandler + .word RTC_WKUP_IRQHandler + .word FLASH_IRQHandler + .word RCC_IRQHandler + .word EXTI0_IRQHandler + .word EXTI1_IRQHandler + .word EXTI2_IRQHandler + .word EXTI3_IRQHandler + .word EXTI4_IRQHandler + .word DMA1_Channel1_IRQHandler + .word DMA1_Channel2_IRQHandler + .word DMA1_Channel3_IRQHandler + .word DMA1_Channel4_IRQHandler + .word DMA1_Channel5_IRQHandler + .word DMA1_Channel6_IRQHandler + .word DMA1_Channel7_IRQHandler + .word ADC1_2_IRQHandler + .word CAN1_TX_IRQHandler + .word CAN1_RX0_IRQHandler + .word CAN1_RX1_IRQHandler + .word CAN1_SCE_IRQHandler + .word EXTI9_5_IRQHandler + .word TIM1_BRK_TIM15_IRQHandler + .word TIM1_UP_TIM16_IRQHandler + .word TIM1_TRG_COM_TIM17_IRQHandler + .word TIM1_CC_IRQHandler + .word TIM2_IRQHandler + .word TIM3_IRQHandler + .word TIM4_IRQHandler + .word I2C1_EV_IRQHandler + .word I2C1_ER_IRQHandler + .word I2C2_EV_IRQHandler + .word I2C2_ER_IRQHandler + .word SPI1_IRQHandler + .word SPI2_IRQHandler + .word USART1_IRQHandler + .word USART2_IRQHandler + .word USART3_IRQHandler + .word EXTI15_10_IRQHandler + .word RTC_Alarm_IRQHandler + .word DFSDM1_FLT3_IRQHandler + .word TIM8_BRK_IRQHandler + .word TIM8_UP_IRQHandler + .word TIM8_TRG_COM_IRQHandler + .word TIM8_CC_IRQHandler + .word ADC3_IRQHandler + .word FMC_IRQHandler + .word SDMMC1_IRQHandler + .word TIM5_IRQHandler + .word SPI3_IRQHandler + .word UART4_IRQHandler + .word UART5_IRQHandler + .word TIM6_DAC_IRQHandler + .word TIM7_IRQHandler + .word DMA2_Channel1_IRQHandler + .word DMA2_Channel2_IRQHandler + .word DMA2_Channel3_IRQHandler + .word DMA2_Channel4_IRQHandler + .word DMA2_Channel5_IRQHandler + .word DFSDM1_FLT0_IRQHandler + .word DFSDM1_FLT1_IRQHandler + .word DFSDM1_FLT2_IRQHandler + .word COMP_IRQHandler + .word LPTIM1_IRQHandler + .word LPTIM2_IRQHandler + .word OTG_FS_IRQHandler + .word DMA2_Channel6_IRQHandler + .word DMA2_Channel7_IRQHandler + .word LPUART1_IRQHandler + .word QUADSPI_IRQHandler + .word I2C3_EV_IRQHandler + .word I2C3_ER_IRQHandler + .word SAI1_IRQHandler + .word SAI2_IRQHandler + .word SWPMI1_IRQHandler + .word TSC_IRQHandler + .word LCD_IRQHandler + .word 0 + .word RNG_IRQHandler + .word FPU_IRQHandler + + +/******************************************************************************* +* +* Provide weak aliases for each Exception handler to the Default_Handler. +* As they are weak aliases, any function with the same name will override +* this definition. +* +*******************************************************************************/ + + .weak NMI_Handler + .thumb_set NMI_Handler,Default_Handler + + .weak HardFault_Handler + .thumb_set HardFault_Handler,Default_Handler + + .weak MemManage_Handler + .thumb_set MemManage_Handler,Default_Handler + + .weak BusFault_Handler + .thumb_set BusFault_Handler,Default_Handler + + .weak UsageFault_Handler + .thumb_set UsageFault_Handler,Default_Handler + + .weak SVC_Handler + .thumb_set SVC_Handler,Default_Handler + + .weak DebugMon_Handler + .thumb_set DebugMon_Handler,Default_Handler + + .weak PendSV_Handler + .thumb_set PendSV_Handler,Default_Handler + + .weak SysTick_Handler + .thumb_set SysTick_Handler,Default_Handler + + .weak WWDG_IRQHandler + .thumb_set WWDG_IRQHandler,Default_Handler + + .weak PVD_PVM_IRQHandler + .thumb_set PVD_PVM_IRQHandler,Default_Handler + + .weak TAMP_STAMP_IRQHandler + .thumb_set TAMP_STAMP_IRQHandler,Default_Handler + + .weak RTC_WKUP_IRQHandler + .thumb_set RTC_WKUP_IRQHandler,Default_Handler + + .weak FLASH_IRQHandler + .thumb_set FLASH_IRQHandler,Default_Handler + + .weak RCC_IRQHandler + .thumb_set RCC_IRQHandler,Default_Handler + + .weak EXTI0_IRQHandler + .thumb_set EXTI0_IRQHandler,Default_Handler + + .weak EXTI1_IRQHandler + .thumb_set EXTI1_IRQHandler,Default_Handler + + .weak EXTI2_IRQHandler + .thumb_set EXTI2_IRQHandler,Default_Handler + + .weak EXTI3_IRQHandler + .thumb_set EXTI3_IRQHandler,Default_Handler + + .weak EXTI4_IRQHandler + .thumb_set EXTI4_IRQHandler,Default_Handler + + .weak DMA1_Channel1_IRQHandler + .thumb_set DMA1_Channel1_IRQHandler,Default_Handler + + .weak DMA1_Channel2_IRQHandler + .thumb_set DMA1_Channel2_IRQHandler,Default_Handler + + .weak DMA1_Channel3_IRQHandler + .thumb_set DMA1_Channel3_IRQHandler,Default_Handler + + .weak DMA1_Channel4_IRQHandler + .thumb_set DMA1_Channel4_IRQHandler,Default_Handler + + .weak DMA1_Channel5_IRQHandler + .thumb_set DMA1_Channel5_IRQHandler,Default_Handler + + .weak DMA1_Channel6_IRQHandler + .thumb_set DMA1_Channel6_IRQHandler,Default_Handler + + .weak DMA1_Channel7_IRQHandler + .thumb_set DMA1_Channel7_IRQHandler,Default_Handler + + .weak ADC1_2_IRQHandler + .thumb_set ADC1_2_IRQHandler,Default_Handler + + .weak CAN1_TX_IRQHandler + .thumb_set CAN1_TX_IRQHandler,Default_Handler + + .weak CAN1_RX0_IRQHandler + .thumb_set CAN1_RX0_IRQHandler,Default_Handler + + .weak CAN1_RX1_IRQHandler + .thumb_set CAN1_RX1_IRQHandler,Default_Handler + + .weak CAN1_SCE_IRQHandler + .thumb_set CAN1_SCE_IRQHandler,Default_Handler + + .weak EXTI9_5_IRQHandler + .thumb_set EXTI9_5_IRQHandler,Default_Handler + + .weak TIM1_BRK_TIM15_IRQHandler + .thumb_set TIM1_BRK_TIM15_IRQHandler,Default_Handler + + .weak TIM1_UP_TIM16_IRQHandler + .thumb_set TIM1_UP_TIM16_IRQHandler,Default_Handler + + .weak TIM1_TRG_COM_TIM17_IRQHandler + .thumb_set TIM1_TRG_COM_TIM17_IRQHandler,Default_Handler + + .weak TIM1_CC_IRQHandler + .thumb_set TIM1_CC_IRQHandler,Default_Handler + + .weak TIM2_IRQHandler + .thumb_set TIM2_IRQHandler,Default_Handler + + .weak TIM3_IRQHandler + .thumb_set TIM3_IRQHandler,Default_Handler + + .weak TIM4_IRQHandler + .thumb_set TIM4_IRQHandler,Default_Handler + + .weak I2C1_EV_IRQHandler + .thumb_set I2C1_EV_IRQHandler,Default_Handler + + .weak I2C1_ER_IRQHandler + .thumb_set I2C1_ER_IRQHandler,Default_Handler + + .weak I2C2_EV_IRQHandler + .thumb_set I2C2_EV_IRQHandler,Default_Handler + + .weak I2C2_ER_IRQHandler + .thumb_set I2C2_ER_IRQHandler,Default_Handler + + .weak SPI1_IRQHandler + .thumb_set SPI1_IRQHandler,Default_Handler + + .weak SPI2_IRQHandler + .thumb_set SPI2_IRQHandler,Default_Handler + + .weak USART1_IRQHandler + .thumb_set USART1_IRQHandler,Default_Handler + + .weak USART2_IRQHandler + .thumb_set USART2_IRQHandler,Default_Handler + + .weak USART3_IRQHandler + .thumb_set USART3_IRQHandler,Default_Handler + + .weak EXTI15_10_IRQHandler + .thumb_set EXTI15_10_IRQHandler,Default_Handler + + .weak RTC_Alarm_IRQHandler + .thumb_set RTC_Alarm_IRQHandler,Default_Handler + + .weak DFSDM1_FLT3_IRQHandler + .thumb_set DFSDM1_FLT3_IRQHandler,Default_Handler + + .weak TIM8_BRK_IRQHandler + .thumb_set TIM8_BRK_IRQHandler,Default_Handler + + .weak TIM8_UP_IRQHandler + .thumb_set TIM8_UP_IRQHandler,Default_Handler + + .weak TIM8_TRG_COM_IRQHandler + .thumb_set TIM8_TRG_COM_IRQHandler,Default_Handler + + .weak TIM8_CC_IRQHandler + .thumb_set TIM8_CC_IRQHandler,Default_Handler + + .weak ADC3_IRQHandler + .thumb_set ADC3_IRQHandler,Default_Handler + + .weak FMC_IRQHandler + .thumb_set FMC_IRQHandler,Default_Handler + + .weak SDMMC1_IRQHandler + .thumb_set SDMMC1_IRQHandler,Default_Handler + + .weak TIM5_IRQHandler + .thumb_set TIM5_IRQHandler,Default_Handler + + .weak SPI3_IRQHandler + .thumb_set SPI3_IRQHandler,Default_Handler + + .weak UART4_IRQHandler + .thumb_set UART4_IRQHandler,Default_Handler + + .weak UART5_IRQHandler + .thumb_set UART5_IRQHandler,Default_Handler + + .weak TIM6_DAC_IRQHandler + .thumb_set TIM6_DAC_IRQHandler,Default_Handler + + .weak TIM7_IRQHandler + .thumb_set TIM7_IRQHandler,Default_Handler + + .weak DMA2_Channel1_IRQHandler + .thumb_set DMA2_Channel1_IRQHandler,Default_Handler + + .weak DMA2_Channel2_IRQHandler + .thumb_set DMA2_Channel2_IRQHandler,Default_Handler + + .weak DMA2_Channel3_IRQHandler + .thumb_set DMA2_Channel3_IRQHandler,Default_Handler + + .weak DMA2_Channel4_IRQHandler + .thumb_set DMA2_Channel4_IRQHandler,Default_Handler + + .weak DMA2_Channel5_IRQHandler + .thumb_set DMA2_Channel5_IRQHandler,Default_Handler + + .weak DFSDM1_FLT0_IRQHandler + .thumb_set DFSDM1_FLT0_IRQHandler,Default_Handler + + .weak DFSDM1_FLT1_IRQHandler + .thumb_set DFSDM1_FLT1_IRQHandler,Default_Handler + + .weak DFSDM1_FLT2_IRQHandler + .thumb_set DFSDM1_FLT2_IRQHandler,Default_Handler + + .weak COMP_IRQHandler + .thumb_set COMP_IRQHandler,Default_Handler + + .weak LPTIM1_IRQHandler + .thumb_set LPTIM1_IRQHandler,Default_Handler + + .weak LPTIM2_IRQHandler + .thumb_set LPTIM2_IRQHandler,Default_Handler + + .weak OTG_FS_IRQHandler + .thumb_set OTG_FS_IRQHandler,Default_Handler + + .weak DMA2_Channel6_IRQHandler + .thumb_set DMA2_Channel6_IRQHandler,Default_Handler + + .weak DMA2_Channel7_IRQHandler + .thumb_set DMA2_Channel7_IRQHandler,Default_Handler + + .weak LPUART1_IRQHandler + .thumb_set LPUART1_IRQHandler,Default_Handler + + .weak QUADSPI_IRQHandler + .thumb_set QUADSPI_IRQHandler,Default_Handler + + .weak I2C3_EV_IRQHandler + .thumb_set I2C3_EV_IRQHandler,Default_Handler + + .weak I2C3_ER_IRQHandler + .thumb_set I2C3_ER_IRQHandler,Default_Handler + + .weak SAI1_IRQHandler + .thumb_set SAI1_IRQHandler,Default_Handler + + .weak SAI2_IRQHandler + .thumb_set SAI2_IRQHandler,Default_Handler + + .weak SWPMI1_IRQHandler + .thumb_set SWPMI1_IRQHandler,Default_Handler + + .weak TSC_IRQHandler + .thumb_set TSC_IRQHandler,Default_Handler + + .weak LCD_IRQHandler + .thumb_set LCD_IRQHandler,Default_Handler + + .weak RNG_IRQHandler + .thumb_set RNG_IRQHandler,Default_Handler + + .weak FPU_IRQHandler + .thumb_set FPU_IRQHandler,Default_Handler +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/.cproject b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/.cproject new file mode 100644 index 0000000..7423747 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/.cproject @@ -0,0 +1,325 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/.mxproject b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/.mxproject new file mode 100644 index 0000000..8142fc1 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/.mxproject @@ -0,0 +1,14 @@ +[PreviousGenFiles] +HeaderPath=D:/VS/brianTPM/Samples/Nucleo-TPM/L4A6RG/Inc +HeaderFiles=usb_device.h;usbd_conf.h;usbd_desc.h;usbd_cdc_if.h;stm32l4xx_it.h;stm32l4xx_hal_conf.h;main.h; +SourcePath=D:/VS/brianTPM/Samples/Nucleo-TPM/L4A6RG/Src +SourceFiles=usb_device.c;usbd_conf.c;usbd_desc.c;usbd_cdc_if.c;stm32l4xx_it.c;stm32l4xx_hal_msp.c;main.c; + +[PreviousLibFiles] +LibFiles=Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pcd.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pcd_ex.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_usb.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rng.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rtc.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rtc_ex.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_tim.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_tim_ex.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_uart.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_uart_ex.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_def.h;Drivers/STM32L4xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_i2c.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_i2c_ex.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rcc.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rcc_ex.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash_ex.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash_ramfunc.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_gpio.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_gpio_ex.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_dma.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_dma_ex.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pwr.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pwr_ex.h;Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_cortex.h;Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_core.h;Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ctlreq.h;Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_def.h;Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ioreq.h;Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc/usbd_cdc.h;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pcd.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pcd_ex.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_usb.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rng.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rtc.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rtc_ex.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_tim.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_tim_ex.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_uart.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_uart_ex.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_i2c.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_i2c_ex.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rcc.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rcc_ex.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash_ex.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash_ramfunc.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_gpio.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_dma.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_dma_ex.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pwr.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pwr_ex.c;Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_cortex.c;Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c;Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c;Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c;Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c;Drivers/CMSIS/Device/ST/STM32L4xx/Include/stm32l4a6xx.h;Drivers/CMSIS/Device/ST/STM32L4xx/Include/stm32l4xx.h;Drivers/CMSIS/Device/ST/STM32L4xx/Include/system_stm32l4xx.h;Drivers/CMSIS/Device/ST/STM32L4xx/Source/Templates/system_stm32l4xx.c;Drivers/CMSIS/Include/arm_common_tables.h;Drivers/CMSIS/Include/arm_const_structs.h;Drivers/CMSIS/Include/arm_math.h;Drivers/CMSIS/Include/cmsis_armcc.h;Drivers/CMSIS/Include/cmsis_armcc_V6.h;Drivers/CMSIS/Include/cmsis_gcc.h;Drivers/CMSIS/Include/core_cm0.h;Drivers/CMSIS/Include/core_cm0plus.h;Drivers/CMSIS/Include/core_cm3.h;Drivers/CMSIS/Include/core_cm4.h;Drivers/CMSIS/Include/core_cm7.h;Drivers/CMSIS/Include/core_cmFunc.h;Drivers/CMSIS/Include/core_cmInstr.h;Drivers/CMSIS/Include/core_cmSimd.h;Drivers/CMSIS/Include/core_sc000.h;Drivers/CMSIS/Include/core_sc300.h; + +[PreviousUsedTStudioFiles] +SourceFiles=..\Src\main.c;..\Src\usb_device.c;..\Src\usbd_conf.c;..\Src\usbd_desc.c;..\Src\usbd_cdc_if.c;..\Src\stm32l4xx_it.c;..\Src\stm32l4xx_hal_msp.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pcd.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pcd_ex.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_usb.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rng.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rtc.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rtc_ex.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_tim.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_tim_ex.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_uart.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_uart_ex.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_i2c.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_i2c_ex.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rcc.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rcc_ex.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash_ex.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash_ramfunc.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_gpio.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_dma.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_dma_ex.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pwr.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pwr_ex.c;../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_cortex.c;../Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c;../Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c;../Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c;../Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c;../\Src/system_stm32l4xx.c;../Drivers/CMSIS/Device/ST/STM32L4xx/Source/Templates/system_stm32l4xx.c;null;../Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c;../Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c;../Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c;../Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c; +HeaderPath=..\Drivers\STM32L4xx_HAL_Driver\Inc;..\Drivers\STM32L4xx_HAL_Driver\Inc\Legacy;..\Middlewares\ST\STM32_USB_Device_Library\Core\Inc;..\Middlewares\ST\STM32_USB_Device_Library\Class\CDC\Inc;..\Drivers\CMSIS\Device\ST\STM32L4xx\Include;..\Drivers\CMSIS\Include;..\Inc; +CDefines=__weak:__attribute__((weak));__packed:__attribute__((__packed__)); + diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/.project b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/.project new file mode 100644 index 0000000..7413f29 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/.project @@ -0,0 +1,160 @@ + + + Nucleo-L4A6RG + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + ?children? + ?name?=outputEntries\|?children?=?name?=entry\\\\\\\|\\\|\|| + + + ?name? + + + + org.eclipse.cdt.make.core.append_environment + true + + + org.eclipse.cdt.make.core.buildArguments + + + + org.eclipse.cdt.make.core.buildCommand + make + + + org.eclipse.cdt.make.core.buildLocation + ${workspace_loc:/STM32100B-EVAL/Debug} + + + org.eclipse.cdt.make.core.contents + org.eclipse.cdt.make.core.activeConfigSettings + + + org.eclipse.cdt.make.core.enableAutoBuild + false + + + org.eclipse.cdt.make.core.enableCleanBuild + true + + + org.eclipse.cdt.make.core.enableFullBuild + true + + + org.eclipse.cdt.make.core.stopOnError + true + + + org.eclipse.cdt.make.core.useDefaultBuildCmd + true + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + + + Inc/Platform + 2 + PARENT-1-PROJECT_LOC/Shared/Platform/include + + + Inc/TPMCmd + 2 + PARENT-3-PROJECT_LOC/TPMCmd/tpm/include + + + Inc/TPMDevice + 2 + PARENT-1-PROJECT_LOC/Shared/TPMDevice/include + + + Middlewares/Platform + 2 + PARENT-1-PROJECT_LOC/Shared/Platform/src + + + Middlewares/TPMCmd + 2 + PARENT-3-PROJECT_LOC/TPMCmd/tpm/src + + + Middlewares/TPMDevice + 2 + PARENT-1-PROJECT_LOC/Shared/TPMDevice/src + + + Middlewares/WolfCypt + 2 + virtual:/virtual + + + Src/syscalls.c + 1 + $%7BPARENT-1-PROJECT_LOC%7D/Shared/syscalls.c + + + Middlewares/WolfCypt/aes.c + 1 + PARENT-3-PROJECT_LOC/external/wolfssl/wolfcrypt/src/aes.c + + + Middlewares/WolfCypt/ecc.c + 1 + PARENT-3-PROJECT_LOC/external/wolfssl/wolfcrypt/src/ecc.c + + + Middlewares/WolfCypt/integer.c + 1 + PARENT-3-PROJECT_LOC/external/wolfssl/wolfcrypt/src/integer.c + + + Middlewares/WolfCypt/memory.c + 1 + PARENT-3-PROJECT_LOC/external/wolfssl/wolfcrypt/src/memory.c + + + Middlewares/WolfCypt/sha.c + 1 + PARENT-3-PROJECT_LOC/external/wolfssl/wolfcrypt/src/sha.c + + + Middlewares/WolfCypt/sha256.c + 1 + PARENT-3-PROJECT_LOC/external/wolfssl/wolfcrypt/src/sha256.c + + + Middlewares/WolfCypt/sha512.c + 1 + PARENT-3-PROJECT_LOC/external/wolfssl/wolfcrypt/src/sha512.c + + + Middlewares/WolfCypt/tfm.c + 1 + PARENT-3-PROJECT_LOC/external/wolfssl/wolfcrypt/src/tfm.c + + + Middlewares/WolfCypt/wolfmath.c + 1 + PARENT-3-PROJECT_LOC/external/wolfssl/wolfcrypt/src/wolfmath.c + + + diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/.settings/com.atollic.truestudio.debug.hardware_device.prefs b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/.settings/com.atollic.truestudio.debug.hardware_device.prefs new file mode 100644 index 0000000..2fed9c1 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/.settings/com.atollic.truestudio.debug.hardware_device.prefs @@ -0,0 +1,11 @@ +BOARD=None +CODE_LOCATION=FLASH +ENDIAN=Little-endian +MCU=STM32L4A6RG +MCU_VENDOR=STMicroelectronics +MODEL=Lite +PROBE=ST-LINK +PROJECT_FORMAT_VERSION=2 +TARGET=ARM\u00AE +VERSION=4.1.0 +eclipse.preferences.version=1 diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/.settings/language.settings.xml b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/.settings/language.settings.xml new file mode 100644 index 0000000..175a203 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/.settings/language.settings.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/.settings/org.eclipse.cdt.managedbuilder.core.prefs b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/.settings/org.eclipse.cdt.managedbuilder.core.prefs new file mode 100644 index 0000000..66eb673 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/.settings/org.eclipse.cdt.managedbuilder.core.prefs @@ -0,0 +1,11 @@ +eclipse.preferences.version=1 +environment/buildEnvironmentInclude/com.atollic.truestudio.exe.debug.1518366166/CPATH/delimiter=; +environment/buildEnvironmentInclude/com.atollic.truestudio.exe.debug.1518366166/CPATH/operation=remove +environment/buildEnvironmentInclude/com.atollic.truestudio.exe.debug.1518366166/C_INCLUDE_PATH/delimiter=; +environment/buildEnvironmentInclude/com.atollic.truestudio.exe.debug.1518366166/C_INCLUDE_PATH/operation=remove +environment/buildEnvironmentInclude/com.atollic.truestudio.exe.debug.1518366166/append=true +environment/buildEnvironmentInclude/com.atollic.truestudio.exe.debug.1518366166/appendContributed=true +environment/buildEnvironmentLibrary/com.atollic.truestudio.exe.debug.1518366166/LIBRARY_PATH/delimiter=; +environment/buildEnvironmentLibrary/com.atollic.truestudio.exe.debug.1518366166/LIBRARY_PATH/operation=remove +environment/buildEnvironmentLibrary/com.atollic.truestudio.exe.debug.1518366166/append=true +environment/buildEnvironmentLibrary/com.atollic.truestudio.exe.debug.1518366166/appendContributed=true diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Device/ST/STM32L4xx/Include/stm32l4a6xx.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Device/ST/STM32L4xx/Include/stm32l4a6xx.h new file mode 100644 index 0000000..df8de8e --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Device/ST/STM32L4xx/Include/stm32l4a6xx.h @@ -0,0 +1,20127 @@ +/** + ****************************************************************************** + * @file stm32l4a6xx.h + * @author MCD Application Team + * @brief CMSIS STM32L4A6xx Device Peripheral Access Layer Header File. + * + * This file contains: + * - Data structures and the address mapping for all peripherals + * - Peripheral's registers declarations and bits definition + * - Macros to access peripheral’s registers hardware + * + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS_Device + * @{ + */ + +/** @addtogroup stm32l4a6xx + * @{ + */ + +#ifndef __STM32L4A6xx_H +#define __STM32L4A6xx_H + +#ifdef __cplusplus + extern "C" { +#endif /* __cplusplus */ + +/** @addtogroup Configuration_section_for_CMSIS + * @{ + */ + +/** + * @brief Configuration of the Cortex-M4 Processor and Core Peripherals + */ +#define __CM4_REV 0x0001 /*!< Cortex-M4 revision r0p1 */ +#define __MPU_PRESENT 1 /*!< STM32L4XX provides an MPU */ +#define __NVIC_PRIO_BITS 4 /*!< STM32L4XX uses 4 Bits for the Priority Levels */ +#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */ +#define __FPU_PRESENT 1 /*!< FPU present */ + +/** + * @} + */ + +/** @addtogroup Peripheral_interrupt_number_definition + * @{ + */ + +/** + * @brief STM32L4XX Interrupt Number Definition, according to the selected device + * in @ref Library_configuration_section + */ +typedef enum +{ +/****** Cortex-M4 Processor Exceptions Numbers ****************************************************************/ + NonMaskableInt_IRQn = -14, /*!< 2 Cortex-M4 Non Maskable Interrupt */ + HardFault_IRQn = -13, /*!< 3 Cortex-M4 Hard Fault Interrupt */ + MemoryManagement_IRQn = -12, /*!< 4 Cortex-M4 Memory Management Interrupt */ + BusFault_IRQn = -11, /*!< 5 Cortex-M4 Bus Fault Interrupt */ + UsageFault_IRQn = -10, /*!< 6 Cortex-M4 Usage Fault Interrupt */ + SVCall_IRQn = -5, /*!< 11 Cortex-M4 SV Call Interrupt */ + DebugMonitor_IRQn = -4, /*!< 12 Cortex-M4 Debug Monitor Interrupt */ + PendSV_IRQn = -2, /*!< 14 Cortex-M4 Pend SV Interrupt */ + SysTick_IRQn = -1, /*!< 15 Cortex-M4 System Tick Interrupt */ +/****** STM32 specific Interrupt Numbers **********************************************************************/ + WWDG_IRQn = 0, /*!< Window WatchDog Interrupt */ + PVD_PVM_IRQn = 1, /*!< PVD/PVM1/PVM2/PVM3/PVM4 through EXTI Line detection Interrupts */ + TAMP_STAMP_IRQn = 2, /*!< Tamper and TimeStamp interrupts through the EXTI line */ + RTC_WKUP_IRQn = 3, /*!< RTC Wakeup interrupt through the EXTI line */ + FLASH_IRQn = 4, /*!< FLASH global Interrupt */ + RCC_IRQn = 5, /*!< RCC global Interrupt */ + EXTI0_IRQn = 6, /*!< EXTI Line0 Interrupt */ + EXTI1_IRQn = 7, /*!< EXTI Line1 Interrupt */ + EXTI2_IRQn = 8, /*!< EXTI Line2 Interrupt */ + EXTI3_IRQn = 9, /*!< EXTI Line3 Interrupt */ + EXTI4_IRQn = 10, /*!< EXTI Line4 Interrupt */ + DMA1_Channel1_IRQn = 11, /*!< DMA1 Channel 1 global Interrupt */ + DMA1_Channel2_IRQn = 12, /*!< DMA1 Channel 2 global Interrupt */ + DMA1_Channel3_IRQn = 13, /*!< DMA1 Channel 3 global Interrupt */ + DMA1_Channel4_IRQn = 14, /*!< DMA1 Channel 4 global Interrupt */ + DMA1_Channel5_IRQn = 15, /*!< DMA1 Channel 5 global Interrupt */ + DMA1_Channel6_IRQn = 16, /*!< DMA1 Channel 6 global Interrupt */ + DMA1_Channel7_IRQn = 17, /*!< DMA1 Channel 7 global Interrupt */ + ADC1_2_IRQn = 18, /*!< ADC1, ADC2 SAR global Interrupts */ + CAN1_TX_IRQn = 19, /*!< CAN1 TX Interrupt */ + CAN1_RX0_IRQn = 20, /*!< CAN1 RX0 Interrupt */ + CAN1_RX1_IRQn = 21, /*!< CAN1 RX1 Interrupt */ + CAN1_SCE_IRQn = 22, /*!< CAN1 SCE Interrupt */ + EXTI9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */ + TIM1_BRK_TIM15_IRQn = 24, /*!< TIM1 Break interrupt and TIM15 global interrupt */ + TIM1_UP_TIM16_IRQn = 25, /*!< TIM1 Update Interrupt and TIM16 global interrupt */ + TIM1_TRG_COM_TIM17_IRQn = 26, /*!< TIM1 Trigger and Commutation Interrupt and TIM17 global interrupt */ + TIM1_CC_IRQn = 27, /*!< TIM1 Capture Compare Interrupt */ + TIM2_IRQn = 28, /*!< TIM2 global Interrupt */ + TIM3_IRQn = 29, /*!< TIM3 global Interrupt */ + TIM4_IRQn = 30, /*!< TIM4 global Interrupt */ + I2C1_EV_IRQn = 31, /*!< I2C1 Event Interrupt */ + I2C1_ER_IRQn = 32, /*!< I2C1 Error Interrupt */ + I2C2_EV_IRQn = 33, /*!< I2C2 Event Interrupt */ + I2C2_ER_IRQn = 34, /*!< I2C2 Error Interrupt */ + SPI1_IRQn = 35, /*!< SPI1 global Interrupt */ + SPI2_IRQn = 36, /*!< SPI2 global Interrupt */ + USART1_IRQn = 37, /*!< USART1 global Interrupt */ + USART2_IRQn = 38, /*!< USART2 global Interrupt */ + USART3_IRQn = 39, /*!< USART3 global Interrupt */ + EXTI15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */ + RTC_Alarm_IRQn = 41, /*!< RTC Alarm (A and B) through EXTI Line Interrupt */ + DFSDM1_FLT3_IRQn = 42, /*!< DFSDM1 Filter 3 global Interrupt */ + TIM8_BRK_IRQn = 43, /*!< TIM8 Break Interrupt */ + TIM8_UP_IRQn = 44, /*!< TIM8 Update Interrupt */ + TIM8_TRG_COM_IRQn = 45, /*!< TIM8 Trigger and Commutation Interrupt */ + TIM8_CC_IRQn = 46, /*!< TIM8 Capture Compare Interrupt */ + ADC3_IRQn = 47, /*!< ADC3 global Interrupt */ + FMC_IRQn = 48, /*!< FMC global Interrupt */ + SDMMC1_IRQn = 49, /*!< SDMMC1 global Interrupt */ + TIM5_IRQn = 50, /*!< TIM5 global Interrupt */ + SPI3_IRQn = 51, /*!< SPI3 global Interrupt */ + UART4_IRQn = 52, /*!< UART4 global Interrupt */ + UART5_IRQn = 53, /*!< UART5 global Interrupt */ + TIM6_DAC_IRQn = 54, /*!< TIM6 global and DAC1&2 underrun error interrupts */ + TIM7_IRQn = 55, /*!< TIM7 global interrupt */ + DMA2_Channel1_IRQn = 56, /*!< DMA2 Channel 1 global Interrupt */ + DMA2_Channel2_IRQn = 57, /*!< DMA2 Channel 2 global Interrupt */ + DMA2_Channel3_IRQn = 58, /*!< DMA2 Channel 3 global Interrupt */ + DMA2_Channel4_IRQn = 59, /*!< DMA2 Channel 4 global Interrupt */ + DMA2_Channel5_IRQn = 60, /*!< DMA2 Channel 5 global Interrupt */ + DFSDM1_FLT0_IRQn = 61, /*!< DFSDM1 Filter 0 global Interrupt */ + DFSDM1_FLT1_IRQn = 62, /*!< DFSDM1 Filter 1 global Interrupt */ + DFSDM1_FLT2_IRQn = 63, /*!< DFSDM1 Filter 2 global Interrupt */ + COMP_IRQn = 64, /*!< COMP1 and COMP2 Interrupts */ + LPTIM1_IRQn = 65, /*!< LP TIM1 interrupt */ + LPTIM2_IRQn = 66, /*!< LP TIM2 interrupt */ + OTG_FS_IRQn = 67, /*!< USB OTG FS global Interrupt */ + DMA2_Channel6_IRQn = 68, /*!< DMA2 Channel 6 global interrupt */ + DMA2_Channel7_IRQn = 69, /*!< DMA2 Channel 7 global interrupt */ + LPUART1_IRQn = 70, /*!< LP UART1 interrupt */ + QUADSPI_IRQn = 71, /*!< Quad SPI global interrupt */ + I2C3_EV_IRQn = 72, /*!< I2C3 event interrupt */ + I2C3_ER_IRQn = 73, /*!< I2C3 error interrupt */ + SAI1_IRQn = 74, /*!< Serial Audio Interface 1 global interrupt */ + SAI2_IRQn = 75, /*!< Serial Audio Interface 2 global interrupt */ + SWPMI1_IRQn = 76, /*!< Serial Wire Interface 1 global interrupt */ + TSC_IRQn = 77, /*!< Touch Sense Controller global interrupt */ + LCD_IRQn = 78, /*!< LCD global interrupt */ + AES_IRQn = 79, /*!< AES global interrupt */ + HASH_RNG_IRQn = 80, /*!< HASH and RNG global interrupt */ + FPU_IRQn = 81, /*!< FPU global interrupt */ + CRS_IRQn = 82, /*!< CRS global interrupt */ + I2C4_EV_IRQn = 83, /*!< I2C4 Event interrupt */ + I2C4_ER_IRQn = 84, /*!< I2C4 Error interrupt */ + DCMI_IRQn = 85, /*!< DCMI global interrupt */ + CAN2_TX_IRQn = 86, /*!< CAN2 TX interrupt */ + CAN2_RX0_IRQn = 87, /*!< CAN2 RX0 interrupt */ + CAN2_RX1_IRQn = 88, /*!< CAN2 RX1 interrupt */ + CAN2_SCE_IRQn = 89, /*!< CAN2 SCE interrupt */ + DMA2D_IRQn = 90 /*!< DMA2D global interrupt */ +} IRQn_Type; + +/** + * @} + */ + +#include "core_cm4.h" /* Cortex-M4 processor and core peripherals */ +#include "system_stm32l4xx.h" +#include + +/** @addtogroup Peripheral_registers_structures + * @{ + */ + +/** + * @brief Analog to Digital Converter + */ + +typedef struct +{ + __IO uint32_t ISR; /*!< ADC interrupt and status register, Address offset: 0x00 */ + __IO uint32_t IER; /*!< ADC interrupt enable register, Address offset: 0x04 */ + __IO uint32_t CR; /*!< ADC control register, Address offset: 0x08 */ + __IO uint32_t CFGR; /*!< ADC configuration register 1, Address offset: 0x0C */ + __IO uint32_t CFGR2; /*!< ADC configuration register 2, Address offset: 0x10 */ + __IO uint32_t SMPR1; /*!< ADC sampling time register 1, Address offset: 0x14 */ + __IO uint32_t SMPR2; /*!< ADC sampling time register 2, Address offset: 0x18 */ + uint32_t RESERVED1; /*!< Reserved, 0x1C */ + __IO uint32_t TR1; /*!< ADC analog watchdog 1 threshold register, Address offset: 0x20 */ + __IO uint32_t TR2; /*!< ADC analog watchdog 2 threshold register, Address offset: 0x24 */ + __IO uint32_t TR3; /*!< ADC analog watchdog 3 threshold register, Address offset: 0x28 */ + uint32_t RESERVED2; /*!< Reserved, 0x2C */ + __IO uint32_t SQR1; /*!< ADC group regular sequencer register 1, Address offset: 0x30 */ + __IO uint32_t SQR2; /*!< ADC group regular sequencer register 2, Address offset: 0x34 */ + __IO uint32_t SQR3; /*!< ADC group regular sequencer register 3, Address offset: 0x38 */ + __IO uint32_t SQR4; /*!< ADC group regular sequencer register 4, Address offset: 0x3C */ + __IO uint32_t DR; /*!< ADC group regular data register, Address offset: 0x40 */ + uint32_t RESERVED3; /*!< Reserved, 0x44 */ + uint32_t RESERVED4; /*!< Reserved, 0x48 */ + __IO uint32_t JSQR; /*!< ADC group injected sequencer register, Address offset: 0x4C */ + uint32_t RESERVED5[4]; /*!< Reserved, 0x50 - 0x5C */ + __IO uint32_t OFR1; /*!< ADC offset register 1, Address offset: 0x60 */ + __IO uint32_t OFR2; /*!< ADC offset register 2, Address offset: 0x64 */ + __IO uint32_t OFR3; /*!< ADC offset register 3, Address offset: 0x68 */ + __IO uint32_t OFR4; /*!< ADC offset register 4, Address offset: 0x6C */ + uint32_t RESERVED6[4]; /*!< Reserved, 0x70 - 0x7C */ + __IO uint32_t JDR1; /*!< ADC group injected rank 1 data register, Address offset: 0x80 */ + __IO uint32_t JDR2; /*!< ADC group injected rank 2 data register, Address offset: 0x84 */ + __IO uint32_t JDR3; /*!< ADC group injected rank 3 data register, Address offset: 0x88 */ + __IO uint32_t JDR4; /*!< ADC group injected rank 4 data register, Address offset: 0x8C */ + uint32_t RESERVED7[4]; /*!< Reserved, 0x090 - 0x09C */ + __IO uint32_t AWD2CR; /*!< ADC analog watchdog 1 configuration register, Address offset: 0xA0 */ + __IO uint32_t AWD3CR; /*!< ADC analog watchdog 3 Configuration Register, Address offset: 0xA4 */ + uint32_t RESERVED8; /*!< Reserved, 0x0A8 */ + uint32_t RESERVED9; /*!< Reserved, 0x0AC */ + __IO uint32_t DIFSEL; /*!< ADC differential mode selection register, Address offset: 0xB0 */ + __IO uint32_t CALFACT; /*!< ADC calibration factors, Address offset: 0xB4 */ + +} ADC_TypeDef; + +typedef struct +{ + __IO uint32_t CSR; /*!< ADC common status register, Address offset: ADC1 base address + 0x300 */ + uint32_t RESERVED; /*!< Reserved, Address offset: ADC1 base address + 0x304 */ + __IO uint32_t CCR; /*!< ADC common configuration register, Address offset: ADC1 base address + 0x308 */ + __IO uint32_t CDR; /*!< ADC common group regular data register Address offset: ADC1 base address + 0x30C */ +} ADC_Common_TypeDef; + +/** + * @brief DCMI + */ + +typedef struct +{ + __IO uint32_t CR; /*!< DCMI control register, Address offset: 0x00 */ + __IO uint32_t SR; /*!< DCMI status register, Address offset: 0x04 */ + __IO uint32_t RISR; /*!< DCMI raw interrupt status register, Address offset: 0x08 */ + __IO uint32_t IER; /*!< DCMI interrupt enable register, Address offset: 0x0C */ + __IO uint32_t MISR; /*!< DCMI masked interrupt status register, Address offset: 0x10 */ + __IO uint32_t ICR; /*!< DCMI interrupt clear register, Address offset: 0x14 */ + __IO uint32_t ESCR; /*!< DCMI embedded synchronization code register, Address offset: 0x18 */ + __IO uint32_t ESUR; /*!< DCMI embedded synchronization unmask register, Address offset: 0x1C */ + __IO uint32_t CWSTRTR; /*!< DCMI crop window start, Address offset: 0x20 */ + __IO uint32_t CWSIZER; /*!< DCMI crop window size, Address offset: 0x24 */ + __IO uint32_t DR; /*!< DCMI data register, Address offset: 0x28 */ +} DCMI_TypeDef; + +/** + * @brief Controller Area Network TxMailBox + */ + +typedef struct +{ + __IO uint32_t TIR; /*!< CAN TX mailbox identifier register */ + __IO uint32_t TDTR; /*!< CAN mailbox data length control and time stamp register */ + __IO uint32_t TDLR; /*!< CAN mailbox data low register */ + __IO uint32_t TDHR; /*!< CAN mailbox data high register */ +} CAN_TxMailBox_TypeDef; + +/** + * @brief Controller Area Network FIFOMailBox + */ + +typedef struct +{ + __IO uint32_t RIR; /*!< CAN receive FIFO mailbox identifier register */ + __IO uint32_t RDTR; /*!< CAN receive FIFO mailbox data length control and time stamp register */ + __IO uint32_t RDLR; /*!< CAN receive FIFO mailbox data low register */ + __IO uint32_t RDHR; /*!< CAN receive FIFO mailbox data high register */ +} CAN_FIFOMailBox_TypeDef; + +/** + * @brief Controller Area Network FilterRegister + */ + +typedef struct +{ + __IO uint32_t FR1; /*!< CAN Filter bank register 1 */ + __IO uint32_t FR2; /*!< CAN Filter bank register 1 */ +} CAN_FilterRegister_TypeDef; + +/** + * @brief Controller Area Network + */ + +typedef struct +{ + __IO uint32_t MCR; /*!< CAN master control register, Address offset: 0x00 */ + __IO uint32_t MSR; /*!< CAN master status register, Address offset: 0x04 */ + __IO uint32_t TSR; /*!< CAN transmit status register, Address offset: 0x08 */ + __IO uint32_t RF0R; /*!< CAN receive FIFO 0 register, Address offset: 0x0C */ + __IO uint32_t RF1R; /*!< CAN receive FIFO 1 register, Address offset: 0x10 */ + __IO uint32_t IER; /*!< CAN interrupt enable register, Address offset: 0x14 */ + __IO uint32_t ESR; /*!< CAN error status register, Address offset: 0x18 */ + __IO uint32_t BTR; /*!< CAN bit timing register, Address offset: 0x1C */ + uint32_t RESERVED0[88]; /*!< Reserved, 0x020 - 0x17F */ + CAN_TxMailBox_TypeDef sTxMailBox[3]; /*!< CAN Tx MailBox, Address offset: 0x180 - 0x1AC */ + CAN_FIFOMailBox_TypeDef sFIFOMailBox[2]; /*!< CAN FIFO MailBox, Address offset: 0x1B0 - 0x1CC */ + uint32_t RESERVED1[12]; /*!< Reserved, 0x1D0 - 0x1FF */ + __IO uint32_t FMR; /*!< CAN filter master register, Address offset: 0x200 */ + __IO uint32_t FM1R; /*!< CAN filter mode register, Address offset: 0x204 */ + uint32_t RESERVED2; /*!< Reserved, 0x208 */ + __IO uint32_t FS1R; /*!< CAN filter scale register, Address offset: 0x20C */ + uint32_t RESERVED3; /*!< Reserved, 0x210 */ + __IO uint32_t FFA1R; /*!< CAN filter FIFO assignment register, Address offset: 0x214 */ + uint32_t RESERVED4; /*!< Reserved, 0x218 */ + __IO uint32_t FA1R; /*!< CAN filter activation register, Address offset: 0x21C */ + uint32_t RESERVED5[8]; /*!< Reserved, 0x220-0x23F */ + CAN_FilterRegister_TypeDef sFilterRegister[28]; /*!< CAN Filter Register, Address offset: 0x240-0x31C */ +} CAN_TypeDef; + + +/** + * @brief Comparator + */ + +typedef struct +{ + __IO uint32_t CSR; /*!< COMP control and status register, Address offset: 0x00 */ +} COMP_TypeDef; + +typedef struct +{ + __IO uint32_t CSR; /*!< COMP control and status register, used for bits common to several COMP instances, Address offset: 0x00 */ +} COMP_Common_TypeDef; + +/** + * @brief CRC calculation unit + */ + +typedef struct +{ + __IO uint32_t DR; /*!< CRC Data register, Address offset: 0x00 */ + __IO uint8_t IDR; /*!< CRC Independent data register, Address offset: 0x04 */ + uint8_t RESERVED0; /*!< Reserved, 0x05 */ + uint16_t RESERVED1; /*!< Reserved, 0x06 */ + __IO uint32_t CR; /*!< CRC Control register, Address offset: 0x08 */ + uint32_t RESERVED2; /*!< Reserved, 0x0C */ + __IO uint32_t INIT; /*!< Initial CRC value register, Address offset: 0x10 */ + __IO uint32_t POL; /*!< CRC polynomial register, Address offset: 0x14 */ +} CRC_TypeDef; + +/** + * @brief Clock Recovery System + */ +typedef struct +{ +__IO uint32_t CR; /*!< CRS ccontrol register, Address offset: 0x00 */ +__IO uint32_t CFGR; /*!< CRS configuration register, Address offset: 0x04 */ +__IO uint32_t ISR; /*!< CRS interrupt and status register, Address offset: 0x08 */ +__IO uint32_t ICR; /*!< CRS interrupt flag clear register, Address offset: 0x0C */ +} CRS_TypeDef; + +/** + * @brief Digital to Analog Converter + */ + +typedef struct +{ + __IO uint32_t CR; /*!< DAC control register, Address offset: 0x00 */ + __IO uint32_t SWTRIGR; /*!< DAC software trigger register, Address offset: 0x04 */ + __IO uint32_t DHR12R1; /*!< DAC channel1 12-bit right-aligned data holding register, Address offset: 0x08 */ + __IO uint32_t DHR12L1; /*!< DAC channel1 12-bit left aligned data holding register, Address offset: 0x0C */ + __IO uint32_t DHR8R1; /*!< DAC channel1 8-bit right aligned data holding register, Address offset: 0x10 */ + __IO uint32_t DHR12R2; /*!< DAC channel2 12-bit right aligned data holding register, Address offset: 0x14 */ + __IO uint32_t DHR12L2; /*!< DAC channel2 12-bit left aligned data holding register, Address offset: 0x18 */ + __IO uint32_t DHR8R2; /*!< DAC channel2 8-bit right-aligned data holding register, Address offset: 0x1C */ + __IO uint32_t DHR12RD; /*!< Dual DAC 12-bit right-aligned data holding register, Address offset: 0x20 */ + __IO uint32_t DHR12LD; /*!< DUAL DAC 12-bit left aligned data holding register, Address offset: 0x24 */ + __IO uint32_t DHR8RD; /*!< DUAL DAC 8-bit right aligned data holding register, Address offset: 0x28 */ + __IO uint32_t DOR1; /*!< DAC channel1 data output register, Address offset: 0x2C */ + __IO uint32_t DOR2; /*!< DAC channel2 data output register, Address offset: 0x30 */ + __IO uint32_t SR; /*!< DAC status register, Address offset: 0x34 */ + __IO uint32_t CCR; /*!< DAC calibration control register, Address offset: 0x38 */ + __IO uint32_t MCR; /*!< DAC mode control register, Address offset: 0x3C */ + __IO uint32_t SHSR1; /*!< DAC Sample and Hold sample time register 1, Address offset: 0x40 */ + __IO uint32_t SHSR2; /*!< DAC Sample and Hold sample time register 2, Address offset: 0x44 */ + __IO uint32_t SHHR; /*!< DAC Sample and Hold hold time register, Address offset: 0x48 */ + __IO uint32_t SHRR; /*!< DAC Sample and Hold refresh time register, Address offset: 0x4C */ +} DAC_TypeDef; + +/** + * @brief DFSDM module registers + */ +typedef struct +{ + __IO uint32_t FLTCR1; /*!< DFSDM control register1, Address offset: 0x100 */ + __IO uint32_t FLTCR2; /*!< DFSDM control register2, Address offset: 0x104 */ + __IO uint32_t FLTISR; /*!< DFSDM interrupt and status register, Address offset: 0x108 */ + __IO uint32_t FLTICR; /*!< DFSDM interrupt flag clear register, Address offset: 0x10C */ + __IO uint32_t FLTJCHGR; /*!< DFSDM injected channel group selection register, Address offset: 0x110 */ + __IO uint32_t FLTFCR; /*!< DFSDM filter control register, Address offset: 0x114 */ + __IO uint32_t FLTJDATAR; /*!< DFSDM data register for injected group, Address offset: 0x118 */ + __IO uint32_t FLTRDATAR; /*!< DFSDM data register for regular group, Address offset: 0x11C */ + __IO uint32_t FLTAWHTR; /*!< DFSDM analog watchdog high threshold register, Address offset: 0x120 */ + __IO uint32_t FLTAWLTR; /*!< DFSDM analog watchdog low threshold register, Address offset: 0x124 */ + __IO uint32_t FLTAWSR; /*!< DFSDM analog watchdog status register Address offset: 0x128 */ + __IO uint32_t FLTAWCFR; /*!< DFSDM analog watchdog clear flag register Address offset: 0x12C */ + __IO uint32_t FLTEXMAX; /*!< DFSDM extreme detector maximum register, Address offset: 0x130 */ + __IO uint32_t FLTEXMIN; /*!< DFSDM extreme detector minimum register Address offset: 0x134 */ + __IO uint32_t FLTCNVTIMR; /*!< DFSDM conversion timer, Address offset: 0x138 */ +} DFSDM_Filter_TypeDef; + +/** + * @brief DFSDM channel configuration registers + */ +typedef struct +{ + __IO uint32_t CHCFGR1; /*!< DFSDM channel configuration register1, Address offset: 0x00 */ + __IO uint32_t CHCFGR2; /*!< DFSDM channel configuration register2, Address offset: 0x04 */ + __IO uint32_t CHAWSCDR; /*!< DFSDM channel analog watchdog and + short circuit detector register, Address offset: 0x08 */ + __IO uint32_t CHWDATAR; /*!< DFSDM channel watchdog filter data register, Address offset: 0x0C */ + __IO uint32_t CHDATINR; /*!< DFSDM channel data input register, Address offset: 0x10 */ +} DFSDM_Channel_TypeDef; + +/** + * @brief Debug MCU + */ + +typedef struct +{ + __IO uint32_t IDCODE; /*!< MCU device ID code, Address offset: 0x00 */ + __IO uint32_t CR; /*!< Debug MCU configuration register, Address offset: 0x04 */ + __IO uint32_t APB1FZR1; /*!< Debug MCU APB1 freeze register 1, Address offset: 0x08 */ + __IO uint32_t APB1FZR2; /*!< Debug MCU APB1 freeze register 2, Address offset: 0x0C */ + __IO uint32_t APB2FZ; /*!< Debug MCU APB2 freeze register, Address offset: 0x10 */ +} DBGMCU_TypeDef; + + +/** + * @brief DMA Controller + */ + +typedef struct +{ + __IO uint32_t CCR; /*!< DMA channel x configuration register */ + __IO uint32_t CNDTR; /*!< DMA channel x number of data register */ + __IO uint32_t CPAR; /*!< DMA channel x peripheral address register */ + __IO uint32_t CMAR; /*!< DMA channel x memory address register */ +} DMA_Channel_TypeDef; + +typedef struct +{ + __IO uint32_t ISR; /*!< DMA interrupt status register, Address offset: 0x00 */ + __IO uint32_t IFCR; /*!< DMA interrupt flag clear register, Address offset: 0x04 */ +} DMA_TypeDef; + +typedef struct +{ + __IO uint32_t CSELR; /*!< DMA channel selection register */ +} DMA_Request_TypeDef; + +/* Legacy define */ +#define DMA_request_TypeDef DMA_Request_TypeDef + + +/** + * @brief DMA2D Controller + */ + +typedef struct +{ + __IO uint32_t CR; /*!< DMA2D Control Register, Address offset: 0x00 */ + __IO uint32_t ISR; /*!< DMA2D Interrupt Status Register, Address offset: 0x04 */ + __IO uint32_t IFCR; /*!< DMA2D Interrupt Flag Clear Register, Address offset: 0x08 */ + __IO uint32_t FGMAR; /*!< DMA2D Foreground Memory Address Register, Address offset: 0x0C */ + __IO uint32_t FGOR; /*!< DMA2D Foreground Offset Register, Address offset: 0x10 */ + __IO uint32_t BGMAR; /*!< DMA2D Background Memory Address Register, Address offset: 0x14 */ + __IO uint32_t BGOR; /*!< DMA2D Background Offset Register, Address offset: 0x18 */ + __IO uint32_t FGPFCCR; /*!< DMA2D Foreground PFC Control Register, Address offset: 0x1C */ + __IO uint32_t FGCOLR; /*!< DMA2D Foreground Color Register, Address offset: 0x20 */ + __IO uint32_t BGPFCCR; /*!< DMA2D Background PFC Control Register, Address offset: 0x24 */ + __IO uint32_t BGCOLR; /*!< DMA2D Background Color Register, Address offset: 0x28 */ + __IO uint32_t FGCMAR; /*!< DMA2D Foreground CLUT Memory Address Register, Address offset: 0x2C */ + __IO uint32_t BGCMAR; /*!< DMA2D Background CLUT Memory Address Register, Address offset: 0x30 */ + __IO uint32_t OPFCCR; /*!< DMA2D Output PFC Control Register, Address offset: 0x34 */ + __IO uint32_t OCOLR; /*!< DMA2D Output Color Register, Address offset: 0x38 */ + __IO uint32_t OMAR; /*!< DMA2D Output Memory Address Register, Address offset: 0x3C */ + __IO uint32_t OOR; /*!< DMA2D Output Offset Register, Address offset: 0x40 */ + __IO uint32_t NLR; /*!< DMA2D Number of Line Register, Address offset: 0x44 */ + __IO uint32_t LWR; /*!< DMA2D Line Watermark Register, Address offset: 0x48 */ + __IO uint32_t AMTCR; /*!< DMA2D AHB Master Timer Configuration Register, Address offset: 0x4C */ + uint32_t RESERVED[236]; /*!< Reserved, Address offset: 0x50-0x3FF */ + __IO uint32_t FGCLUT[256]; /*!< DMA2D Foreground CLUT, Address offset:0x400-0x7FF */ + __IO uint32_t BGCLUT[256]; /*!< DMA2D Background CLUT, Address offset:0x800-0xBFF */ +} DMA2D_TypeDef; + +/** + * @brief External Interrupt/Event Controller + */ + +typedef struct +{ + __IO uint32_t IMR1; /*!< EXTI Interrupt mask register 1, Address offset: 0x00 */ + __IO uint32_t EMR1; /*!< EXTI Event mask register 1, Address offset: 0x04 */ + __IO uint32_t RTSR1; /*!< EXTI Rising trigger selection register 1, Address offset: 0x08 */ + __IO uint32_t FTSR1; /*!< EXTI Falling trigger selection register 1, Address offset: 0x0C */ + __IO uint32_t SWIER1; /*!< EXTI Software interrupt event register 1, Address offset: 0x10 */ + __IO uint32_t PR1; /*!< EXTI Pending register 1, Address offset: 0x14 */ + uint32_t RESERVED1; /*!< Reserved, 0x18 */ + uint32_t RESERVED2; /*!< Reserved, 0x1C */ + __IO uint32_t IMR2; /*!< EXTI Interrupt mask register 2, Address offset: 0x20 */ + __IO uint32_t EMR2; /*!< EXTI Event mask register 2, Address offset: 0x24 */ + __IO uint32_t RTSR2; /*!< EXTI Rising trigger selection register 2, Address offset: 0x28 */ + __IO uint32_t FTSR2; /*!< EXTI Falling trigger selection register 2, Address offset: 0x2C */ + __IO uint32_t SWIER2; /*!< EXTI Software interrupt event register 2, Address offset: 0x30 */ + __IO uint32_t PR2; /*!< EXTI Pending register 2, Address offset: 0x34 */ +} EXTI_TypeDef; + + +/** + * @brief Firewall + */ + +typedef struct +{ + __IO uint32_t CSSA; /*!< Code Segment Start Address register, Address offset: 0x00 */ + __IO uint32_t CSL; /*!< Code Segment Length register, Address offset: 0x04 */ + __IO uint32_t NVDSSA; /*!< NON volatile data Segment Start Address register, Address offset: 0x08 */ + __IO uint32_t NVDSL; /*!< NON volatile data Segment Length register, Address offset: 0x0C */ + __IO uint32_t VDSSA ; /*!< Volatile data Segment Start Address register, Address offset: 0x10 */ + __IO uint32_t VDSL ; /*!< Volatile data Segment Length register, Address offset: 0x14 */ + uint32_t RESERVED1; /*!< Reserved1, Address offset: 0x18 */ + uint32_t RESERVED2; /*!< Reserved2, Address offset: 0x1C */ + __IO uint32_t CR ; /*!< Configuration register, Address offset: 0x20 */ +} FIREWALL_TypeDef; + + +/** + * @brief FLASH Registers + */ + +typedef struct +{ + __IO uint32_t ACR; /*!< FLASH access control register, Address offset: 0x00 */ + __IO uint32_t PDKEYR; /*!< FLASH power down key register, Address offset: 0x04 */ + __IO uint32_t KEYR; /*!< FLASH key register, Address offset: 0x08 */ + __IO uint32_t OPTKEYR; /*!< FLASH option key register, Address offset: 0x0C */ + __IO uint32_t SR; /*!< FLASH status register, Address offset: 0x10 */ + __IO uint32_t CR; /*!< FLASH control register, Address offset: 0x14 */ + __IO uint32_t ECCR; /*!< FLASH ECC register, Address offset: 0x18 */ + __IO uint32_t RESERVED1; /*!< Reserved1, Address offset: 0x1C */ + __IO uint32_t OPTR; /*!< FLASH option register, Address offset: 0x20 */ + __IO uint32_t PCROP1SR; /*!< FLASH bank1 PCROP start address register, Address offset: 0x24 */ + __IO uint32_t PCROP1ER; /*!< FLASH bank1 PCROP end address register, Address offset: 0x28 */ + __IO uint32_t WRP1AR; /*!< FLASH bank1 WRP area A address register, Address offset: 0x2C */ + __IO uint32_t WRP1BR; /*!< FLASH bank1 WRP area B address register, Address offset: 0x30 */ + uint32_t RESERVED2[4]; /*!< Reserved2, Address offset: 0x34-0x40 */ + __IO uint32_t PCROP2SR; /*!< FLASH bank2 PCROP start address register, Address offset: 0x44 */ + __IO uint32_t PCROP2ER; /*!< FLASH bank2 PCROP end address register, Address offset: 0x48 */ + __IO uint32_t WRP2AR; /*!< FLASH bank2 WRP area A address register, Address offset: 0x4C */ + __IO uint32_t WRP2BR; /*!< FLASH bank2 WRP area B address register, Address offset: 0x50 */ +} FLASH_TypeDef; + + +/** + * @brief Flexible Memory Controller + */ + +typedef struct +{ + __IO uint32_t BTCR[8]; /*!< NOR/PSRAM chip-select control register(BCR) and chip-select timing register(BTR), Address offset: 0x00-1C */ +} FMC_Bank1_TypeDef; + +/** + * @brief Flexible Memory Controller Bank1E + */ + +typedef struct +{ + __IO uint32_t BWTR[7]; /*!< NOR/PSRAM write timing registers, Address offset: 0x104-0x11C */ +} FMC_Bank1E_TypeDef; + +/** + * @brief Flexible Memory Controller Bank3 + */ + +typedef struct +{ + __IO uint32_t PCR; /*!< NAND Flash control register, Address offset: 0x80 */ + __IO uint32_t SR; /*!< NAND Flash FIFO status and interrupt register, Address offset: 0x84 */ + __IO uint32_t PMEM; /*!< NAND Flash Common memory space timing register, Address offset: 0x88 */ + __IO uint32_t PATT; /*!< NAND Flash Attribute memory space timing register, Address offset: 0x8C */ + uint32_t RESERVED0; /*!< Reserved, 0x90 */ + __IO uint32_t ECCR; /*!< NAND Flash ECC result registers, Address offset: 0x94 */ +} FMC_Bank3_TypeDef; + +/** + * @brief General Purpose I/O + */ + +typedef struct +{ + __IO uint32_t MODER; /*!< GPIO port mode register, Address offset: 0x00 */ + __IO uint32_t OTYPER; /*!< GPIO port output type register, Address offset: 0x04 */ + __IO uint32_t OSPEEDR; /*!< GPIO port output speed register, Address offset: 0x08 */ + __IO uint32_t PUPDR; /*!< GPIO port pull-up/pull-down register, Address offset: 0x0C */ + __IO uint32_t IDR; /*!< GPIO port input data register, Address offset: 0x10 */ + __IO uint32_t ODR; /*!< GPIO port output data register, Address offset: 0x14 */ + __IO uint32_t BSRR; /*!< GPIO port bit set/reset register, Address offset: 0x18 */ + __IO uint32_t LCKR; /*!< GPIO port configuration lock register, Address offset: 0x1C */ + __IO uint32_t AFR[2]; /*!< GPIO alternate function registers, Address offset: 0x20-0x24 */ + __IO uint32_t BRR; /*!< GPIO Bit Reset register, Address offset: 0x28 */ + +} GPIO_TypeDef; + + +/** + * @brief Inter-integrated Circuit Interface + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< I2C Control register 1, Address offset: 0x00 */ + __IO uint32_t CR2; /*!< I2C Control register 2, Address offset: 0x04 */ + __IO uint32_t OAR1; /*!< I2C Own address 1 register, Address offset: 0x08 */ + __IO uint32_t OAR2; /*!< I2C Own address 2 register, Address offset: 0x0C */ + __IO uint32_t TIMINGR; /*!< I2C Timing register, Address offset: 0x10 */ + __IO uint32_t TIMEOUTR; /*!< I2C Timeout register, Address offset: 0x14 */ + __IO uint32_t ISR; /*!< I2C Interrupt and status register, Address offset: 0x18 */ + __IO uint32_t ICR; /*!< I2C Interrupt clear register, Address offset: 0x1C */ + __IO uint32_t PECR; /*!< I2C PEC register, Address offset: 0x20 */ + __IO uint32_t RXDR; /*!< I2C Receive data register, Address offset: 0x24 */ + __IO uint32_t TXDR; /*!< I2C Transmit data register, Address offset: 0x28 */ +} I2C_TypeDef; + +/** + * @brief Independent WATCHDOG + */ + +typedef struct +{ + __IO uint32_t KR; /*!< IWDG Key register, Address offset: 0x00 */ + __IO uint32_t PR; /*!< IWDG Prescaler register, Address offset: 0x04 */ + __IO uint32_t RLR; /*!< IWDG Reload register, Address offset: 0x08 */ + __IO uint32_t SR; /*!< IWDG Status register, Address offset: 0x0C */ + __IO uint32_t WINR; /*!< IWDG Window register, Address offset: 0x10 */ +} IWDG_TypeDef; + +/** + * @brief LCD + */ + +typedef struct +{ + __IO uint32_t CR; /*!< LCD control register, Address offset: 0x00 */ + __IO uint32_t FCR; /*!< LCD frame control register, Address offset: 0x04 */ + __IO uint32_t SR; /*!< LCD status register, Address offset: 0x08 */ + __IO uint32_t CLR; /*!< LCD clear register, Address offset: 0x0C */ + uint32_t RESERVED; /*!< Reserved, Address offset: 0x10 */ + __IO uint32_t RAM[16]; /*!< LCD display memory, Address offset: 0x14-0x50 */ +} LCD_TypeDef; + +/** + * @brief LPTIMER + */ +typedef struct +{ + __IO uint32_t ISR; /*!< LPTIM Interrupt and Status register, Address offset: 0x00 */ + __IO uint32_t ICR; /*!< LPTIM Interrupt Clear register, Address offset: 0x04 */ + __IO uint32_t IER; /*!< LPTIM Interrupt Enable register, Address offset: 0x08 */ + __IO uint32_t CFGR; /*!< LPTIM Configuration register, Address offset: 0x0C */ + __IO uint32_t CR; /*!< LPTIM Control register, Address offset: 0x10 */ + __IO uint32_t CMP; /*!< LPTIM Compare register, Address offset: 0x14 */ + __IO uint32_t ARR; /*!< LPTIM Autoreload register, Address offset: 0x18 */ + __IO uint32_t CNT; /*!< LPTIM Counter register, Address offset: 0x1C */ + __IO uint32_t OR; /*!< LPTIM Option register, Address offset: 0x20 */ +} LPTIM_TypeDef; + +/** + * @brief Operational Amplifier (OPAMP) + */ + +typedef struct +{ + __IO uint32_t CSR; /*!< OPAMP control/status register, Address offset: 0x00 */ + __IO uint32_t OTR; /*!< OPAMP offset trimming register for normal mode, Address offset: 0x04 */ + __IO uint32_t LPOTR; /*!< OPAMP offset trimming register for low power mode, Address offset: 0x08 */ +} OPAMP_TypeDef; + +typedef struct +{ + __IO uint32_t CSR; /*!< OPAMP control/status register, used for bits common to several OPAMP instances, Address offset: 0x00 */ +} OPAMP_Common_TypeDef; + +/** + * @brief Power Control + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< PWR power control register 1, Address offset: 0x00 */ + __IO uint32_t CR2; /*!< PWR power control register 2, Address offset: 0x04 */ + __IO uint32_t CR3; /*!< PWR power control register 3, Address offset: 0x08 */ + __IO uint32_t CR4; /*!< PWR power control register 4, Address offset: 0x0C */ + __IO uint32_t SR1; /*!< PWR power status register 1, Address offset: 0x10 */ + __IO uint32_t SR2; /*!< PWR power status register 2, Address offset: 0x14 */ + __IO uint32_t SCR; /*!< PWR power status reset register, Address offset: 0x18 */ + uint32_t RESERVED; /*!< Reserved, Address offset: 0x1C */ + __IO uint32_t PUCRA; /*!< Pull_up control register of portA, Address offset: 0x20 */ + __IO uint32_t PDCRA; /*!< Pull_Down control register of portA, Address offset: 0x24 */ + __IO uint32_t PUCRB; /*!< Pull_up control register of portB, Address offset: 0x28 */ + __IO uint32_t PDCRB; /*!< Pull_Down control register of portB, Address offset: 0x2C */ + __IO uint32_t PUCRC; /*!< Pull_up control register of portC, Address offset: 0x30 */ + __IO uint32_t PDCRC; /*!< Pull_Down control register of portC, Address offset: 0x34 */ + __IO uint32_t PUCRD; /*!< Pull_up control register of portD, Address offset: 0x38 */ + __IO uint32_t PDCRD; /*!< Pull_Down control register of portD, Address offset: 0x3C */ + __IO uint32_t PUCRE; /*!< Pull_up control register of portE, Address offset: 0x40 */ + __IO uint32_t PDCRE; /*!< Pull_Down control register of portE, Address offset: 0x44 */ + __IO uint32_t PUCRF; /*!< Pull_up control register of portF, Address offset: 0x48 */ + __IO uint32_t PDCRF; /*!< Pull_Down control register of portF, Address offset: 0x4C */ + __IO uint32_t PUCRG; /*!< Pull_up control register of portG, Address offset: 0x50 */ + __IO uint32_t PDCRG; /*!< Pull_Down control register of portG, Address offset: 0x54 */ + __IO uint32_t PUCRH; /*!< Pull_up control register of portH, Address offset: 0x58 */ + __IO uint32_t PDCRH; /*!< Pull_Down control register of portH, Address offset: 0x5C */ + __IO uint32_t PUCRI; /*!< Pull_up control register of portI, Address offset: 0x60 */ + __IO uint32_t PDCRI; /*!< Pull_Down control register of portI, Address offset: 0x64 */ +} PWR_TypeDef; + + +/** + * @brief QUAD Serial Peripheral Interface + */ + +typedef struct +{ + __IO uint32_t CR; /*!< QUADSPI Control register, Address offset: 0x00 */ + __IO uint32_t DCR; /*!< QUADSPI Device Configuration register, Address offset: 0x04 */ + __IO uint32_t SR; /*!< QUADSPI Status register, Address offset: 0x08 */ + __IO uint32_t FCR; /*!< QUADSPI Flag Clear register, Address offset: 0x0C */ + __IO uint32_t DLR; /*!< QUADSPI Data Length register, Address offset: 0x10 */ + __IO uint32_t CCR; /*!< QUADSPI Communication Configuration register, Address offset: 0x14 */ + __IO uint32_t AR; /*!< QUADSPI Address register, Address offset: 0x18 */ + __IO uint32_t ABR; /*!< QUADSPI Alternate Bytes register, Address offset: 0x1C */ + __IO uint32_t DR; /*!< QUADSPI Data register, Address offset: 0x20 */ + __IO uint32_t PSMKR; /*!< QUADSPI Polling Status Mask register, Address offset: 0x24 */ + __IO uint32_t PSMAR; /*!< QUADSPI Polling Status Match register, Address offset: 0x28 */ + __IO uint32_t PIR; /*!< QUADSPI Polling Interval register, Address offset: 0x2C */ + __IO uint32_t LPTR; /*!< QUADSPI Low Power Timeout register, Address offset: 0x30 */ +} QUADSPI_TypeDef; + + +/** + * @brief Reset and Clock Control + */ + +typedef struct +{ + __IO uint32_t CR; /*!< RCC clock control register, Address offset: 0x00 */ + __IO uint32_t ICSCR; /*!< RCC internal clock sources calibration register, Address offset: 0x04 */ + __IO uint32_t CFGR; /*!< RCC clock configuration register, Address offset: 0x08 */ + __IO uint32_t PLLCFGR; /*!< RCC system PLL configuration register, Address offset: 0x0C */ + __IO uint32_t PLLSAI1CFGR; /*!< RCC PLL SAI1 configuration register, Address offset: 0x10 */ + __IO uint32_t PLLSAI2CFGR; /*!< RCC PLL SAI2 configuration register, Address offset: 0x14 */ + __IO uint32_t CIER; /*!< RCC clock interrupt enable register, Address offset: 0x18 */ + __IO uint32_t CIFR; /*!< RCC clock interrupt flag register, Address offset: 0x1C */ + __IO uint32_t CICR; /*!< RCC clock interrupt clear register, Address offset: 0x20 */ + uint32_t RESERVED0; /*!< Reserved, Address offset: 0x24 */ + __IO uint32_t AHB1RSTR; /*!< RCC AHB1 peripheral reset register, Address offset: 0x28 */ + __IO uint32_t AHB2RSTR; /*!< RCC AHB2 peripheral reset register, Address offset: 0x2C */ + __IO uint32_t AHB3RSTR; /*!< RCC AHB3 peripheral reset register, Address offset: 0x30 */ + uint32_t RESERVED1; /*!< Reserved, Address offset: 0x34 */ + __IO uint32_t APB1RSTR1; /*!< RCC APB1 peripheral reset register 1, Address offset: 0x38 */ + __IO uint32_t APB1RSTR2; /*!< RCC APB1 peripheral reset register 2, Address offset: 0x3C */ + __IO uint32_t APB2RSTR; /*!< RCC APB2 peripheral reset register, Address offset: 0x40 */ + uint32_t RESERVED2; /*!< Reserved, Address offset: 0x44 */ + __IO uint32_t AHB1ENR; /*!< RCC AHB1 peripheral clocks enable register, Address offset: 0x48 */ + __IO uint32_t AHB2ENR; /*!< RCC AHB2 peripheral clocks enable register, Address offset: 0x4C */ + __IO uint32_t AHB3ENR; /*!< RCC AHB3 peripheral clocks enable register, Address offset: 0x50 */ + uint32_t RESERVED3; /*!< Reserved, Address offset: 0x54 */ + __IO uint32_t APB1ENR1; /*!< RCC APB1 peripheral clocks enable register 1, Address offset: 0x58 */ + __IO uint32_t APB1ENR2; /*!< RCC APB1 peripheral clocks enable register 2, Address offset: 0x5C */ + __IO uint32_t APB2ENR; /*!< RCC APB2 peripheral clocks enable register, Address offset: 0x60 */ + uint32_t RESERVED4; /*!< Reserved, Address offset: 0x64 */ + __IO uint32_t AHB1SMENR; /*!< RCC AHB1 peripheral clocks enable in sleep and stop modes register, Address offset: 0x68 */ + __IO uint32_t AHB2SMENR; /*!< RCC AHB2 peripheral clocks enable in sleep and stop modes register, Address offset: 0x6C */ + __IO uint32_t AHB3SMENR; /*!< RCC AHB3 peripheral clocks enable in sleep and stop modes register, Address offset: 0x70 */ + uint32_t RESERVED5; /*!< Reserved, Address offset: 0x74 */ + __IO uint32_t APB1SMENR1; /*!< RCC APB1 peripheral clocks enable in sleep mode and stop modes register 1, Address offset: 0x78 */ + __IO uint32_t APB1SMENR2; /*!< RCC APB1 peripheral clocks enable in sleep mode and stop modes register 2, Address offset: 0x7C */ + __IO uint32_t APB2SMENR; /*!< RCC APB2 peripheral clocks enable in sleep mode and stop modes register, Address offset: 0x80 */ + uint32_t RESERVED6; /*!< Reserved, Address offset: 0x84 */ + __IO uint32_t CCIPR; /*!< RCC peripherals independent clock configuration register, Address offset: 0x88 */ + uint32_t RESERVED7; /*!< Reserved, Address offset: 0x8C */ + __IO uint32_t BDCR; /*!< RCC backup domain control register, Address offset: 0x90 */ + __IO uint32_t CSR; /*!< RCC clock control & status register, Address offset: 0x94 */ + __IO uint32_t CRRCR; /*!< RCC clock recovery RC register, Address offset: 0x98 */ + __IO uint32_t CCIPR2; /*!< RCC peripherals independent clock configuration register 2, Address offset: 0x9C */ +} RCC_TypeDef; + +/** + * @brief Real-Time Clock + */ + +typedef struct +{ + __IO uint32_t TR; /*!< RTC time register, Address offset: 0x00 */ + __IO uint32_t DR; /*!< RTC date register, Address offset: 0x04 */ + __IO uint32_t CR; /*!< RTC control register, Address offset: 0x08 */ + __IO uint32_t ISR; /*!< RTC initialization and status register, Address offset: 0x0C */ + __IO uint32_t PRER; /*!< RTC prescaler register, Address offset: 0x10 */ + __IO uint32_t WUTR; /*!< RTC wakeup timer register, Address offset: 0x14 */ + uint32_t reserved; /*!< Reserved */ + __IO uint32_t ALRMAR; /*!< RTC alarm A register, Address offset: 0x1C */ + __IO uint32_t ALRMBR; /*!< RTC alarm B register, Address offset: 0x20 */ + __IO uint32_t WPR; /*!< RTC write protection register, Address offset: 0x24 */ + __IO uint32_t SSR; /*!< RTC sub second register, Address offset: 0x28 */ + __IO uint32_t SHIFTR; /*!< RTC shift control register, Address offset: 0x2C */ + __IO uint32_t TSTR; /*!< RTC time stamp time register, Address offset: 0x30 */ + __IO uint32_t TSDR; /*!< RTC time stamp date register, Address offset: 0x34 */ + __IO uint32_t TSSSR; /*!< RTC time-stamp sub second register, Address offset: 0x38 */ + __IO uint32_t CALR; /*!< RTC calibration register, Address offset: 0x3C */ + __IO uint32_t TAMPCR; /*!< RTC tamper configuration register, Address offset: 0x40 */ + __IO uint32_t ALRMASSR; /*!< RTC alarm A sub second register, Address offset: 0x44 */ + __IO uint32_t ALRMBSSR; /*!< RTC alarm B sub second register, Address offset: 0x48 */ + __IO uint32_t OR; /*!< RTC option register, Address offset: 0x4C */ + __IO uint32_t BKP0R; /*!< RTC backup register 0, Address offset: 0x50 */ + __IO uint32_t BKP1R; /*!< RTC backup register 1, Address offset: 0x54 */ + __IO uint32_t BKP2R; /*!< RTC backup register 2, Address offset: 0x58 */ + __IO uint32_t BKP3R; /*!< RTC backup register 3, Address offset: 0x5C */ + __IO uint32_t BKP4R; /*!< RTC backup register 4, Address offset: 0x60 */ + __IO uint32_t BKP5R; /*!< RTC backup register 5, Address offset: 0x64 */ + __IO uint32_t BKP6R; /*!< RTC backup register 6, Address offset: 0x68 */ + __IO uint32_t BKP7R; /*!< RTC backup register 7, Address offset: 0x6C */ + __IO uint32_t BKP8R; /*!< RTC backup register 8, Address offset: 0x70 */ + __IO uint32_t BKP9R; /*!< RTC backup register 9, Address offset: 0x74 */ + __IO uint32_t BKP10R; /*!< RTC backup register 10, Address offset: 0x78 */ + __IO uint32_t BKP11R; /*!< RTC backup register 11, Address offset: 0x7C */ + __IO uint32_t BKP12R; /*!< RTC backup register 12, Address offset: 0x80 */ + __IO uint32_t BKP13R; /*!< RTC backup register 13, Address offset: 0x84 */ + __IO uint32_t BKP14R; /*!< RTC backup register 14, Address offset: 0x88 */ + __IO uint32_t BKP15R; /*!< RTC backup register 15, Address offset: 0x8C */ + __IO uint32_t BKP16R; /*!< RTC backup register 16, Address offset: 0x90 */ + __IO uint32_t BKP17R; /*!< RTC backup register 17, Address offset: 0x94 */ + __IO uint32_t BKP18R; /*!< RTC backup register 18, Address offset: 0x98 */ + __IO uint32_t BKP19R; /*!< RTC backup register 19, Address offset: 0x9C */ + __IO uint32_t BKP20R; /*!< RTC backup register 20, Address offset: 0xA0 */ + __IO uint32_t BKP21R; /*!< RTC backup register 21, Address offset: 0xA4 */ + __IO uint32_t BKP22R; /*!< RTC backup register 22, Address offset: 0xA8 */ + __IO uint32_t BKP23R; /*!< RTC backup register 23, Address offset: 0xAC */ + __IO uint32_t BKP24R; /*!< RTC backup register 24, Address offset: 0xB0 */ + __IO uint32_t BKP25R; /*!< RTC backup register 25, Address offset: 0xB4 */ + __IO uint32_t BKP26R; /*!< RTC backup register 26, Address offset: 0xB8 */ + __IO uint32_t BKP27R; /*!< RTC backup register 27, Address offset: 0xBC */ + __IO uint32_t BKP28R; /*!< RTC backup register 28, Address offset: 0xC0 */ + __IO uint32_t BKP29R; /*!< RTC backup register 29, Address offset: 0xC4 */ + __IO uint32_t BKP30R; /*!< RTC backup register 30, Address offset: 0xC8 */ + __IO uint32_t BKP31R; /*!< RTC backup register 31, Address offset: 0xCC */ +} RTC_TypeDef; + + +/** + * @brief Serial Audio Interface + */ + +typedef struct +{ + __IO uint32_t GCR; /*!< SAI global configuration register, Address offset: 0x00 */ +} SAI_TypeDef; + +typedef struct +{ + __IO uint32_t CR1; /*!< SAI block x configuration register 1, Address offset: 0x04 */ + __IO uint32_t CR2; /*!< SAI block x configuration register 2, Address offset: 0x08 */ + __IO uint32_t FRCR; /*!< SAI block x frame configuration register, Address offset: 0x0C */ + __IO uint32_t SLOTR; /*!< SAI block x slot register, Address offset: 0x10 */ + __IO uint32_t IMR; /*!< SAI block x interrupt mask register, Address offset: 0x14 */ + __IO uint32_t SR; /*!< SAI block x status register, Address offset: 0x18 */ + __IO uint32_t CLRFR; /*!< SAI block x clear flag register, Address offset: 0x1C */ + __IO uint32_t DR; /*!< SAI block x data register, Address offset: 0x20 */ +} SAI_Block_TypeDef; + + +/** + * @brief Secure digital input/output Interface + */ + +typedef struct +{ + __IO uint32_t POWER; /*!< SDMMC power control register, Address offset: 0x00 */ + __IO uint32_t CLKCR; /*!< SDMMC clock control register, Address offset: 0x04 */ + __IO uint32_t ARG; /*!< SDMMC argument register, Address offset: 0x08 */ + __IO uint32_t CMD; /*!< SDMMC command register, Address offset: 0x0C */ + __I uint32_t RESPCMD; /*!< SDMMC command response register, Address offset: 0x10 */ + __I uint32_t RESP1; /*!< SDMMC response 1 register, Address offset: 0x14 */ + __I uint32_t RESP2; /*!< SDMMC response 2 register, Address offset: 0x18 */ + __I uint32_t RESP3; /*!< SDMMC response 3 register, Address offset: 0x1C */ + __I uint32_t RESP4; /*!< SDMMC response 4 register, Address offset: 0x20 */ + __IO uint32_t DTIMER; /*!< SDMMC data timer register, Address offset: 0x24 */ + __IO uint32_t DLEN; /*!< SDMMC data length register, Address offset: 0x28 */ + __IO uint32_t DCTRL; /*!< SDMMC data control register, Address offset: 0x2C */ + __I uint32_t DCOUNT; /*!< SDMMC data counter register, Address offset: 0x30 */ + __I uint32_t STA; /*!< SDMMC status register, Address offset: 0x34 */ + __IO uint32_t ICR; /*!< SDMMC interrupt clear register, Address offset: 0x38 */ + __IO uint32_t MASK; /*!< SDMMC mask register, Address offset: 0x3C */ + uint32_t RESERVED0[2]; /*!< Reserved, 0x40-0x44 */ + __I uint32_t FIFOCNT; /*!< SDMMC FIFO counter register, Address offset: 0x48 */ + uint32_t RESERVED1[13]; /*!< Reserved, 0x4C-0x7C */ + __IO uint32_t FIFO; /*!< SDMMC data FIFO register, Address offset: 0x80 */ +} SDMMC_TypeDef; + + +/** + * @brief Serial Peripheral Interface + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< SPI Control register 1, Address offset: 0x00 */ + __IO uint32_t CR2; /*!< SPI Control register 2, Address offset: 0x04 */ + __IO uint32_t SR; /*!< SPI Status register, Address offset: 0x08 */ + __IO uint32_t DR; /*!< SPI data register, Address offset: 0x0C */ + __IO uint32_t CRCPR; /*!< SPI CRC polynomial register, Address offset: 0x10 */ + __IO uint32_t RXCRCR; /*!< SPI Rx CRC register, Address offset: 0x14 */ + __IO uint32_t TXCRCR; /*!< SPI Tx CRC register, Address offset: 0x18 */ +} SPI_TypeDef; + + +/** + * @brief Single Wire Protocol Master Interface SPWMI + */ + +typedef struct +{ + __IO uint32_t CR; /*!< SWPMI Configuration/Control register, Address offset: 0x00 */ + __IO uint32_t BRR; /*!< SWPMI bitrate register, Address offset: 0x04 */ + uint32_t RESERVED1; /*!< Reserved, 0x08 */ + __IO uint32_t ISR; /*!< SWPMI Interrupt and Status register, Address offset: 0x0C */ + __IO uint32_t ICR; /*!< SWPMI Interrupt Flag Clear register, Address offset: 0x10 */ + __IO uint32_t IER; /*!< SWPMI Interrupt Enable register, Address offset: 0x14 */ + __IO uint32_t RFL; /*!< SWPMI Receive Frame Length register, Address offset: 0x18 */ + __IO uint32_t TDR; /*!< SWPMI Transmit data register, Address offset: 0x1C */ + __IO uint32_t RDR; /*!< SWPMI Receive data register, Address offset: 0x20 */ + __IO uint32_t OR; /*!< SWPMI Option register, Address offset: 0x24 */ +} SWPMI_TypeDef; + + +/** + * @brief System configuration controller + */ + +typedef struct +{ + __IO uint32_t MEMRMP; /*!< SYSCFG memory remap register, Address offset: 0x00 */ + __IO uint32_t CFGR1; /*!< SYSCFG configuration register 1, Address offset: 0x04 */ + __IO uint32_t EXTICR[4]; /*!< SYSCFG external interrupt configuration registers, Address offset: 0x08-0x14 */ + __IO uint32_t SCSR; /*!< SYSCFG SRAM2 control and status register, Address offset: 0x18 */ + __IO uint32_t CFGR2; /*!< SYSCFG configuration register 2, Address offset: 0x1C */ + __IO uint32_t SWPR; /*!< SYSCFG SRAM2 write protection register, Address offset: 0x20 */ + __IO uint32_t SKR; /*!< SYSCFG SRAM2 key register, Address offset: 0x24 */ + __IO uint32_t SWPR2; /*!< SYSCFG SRAM2 write protection register 2, Address offset: 0x28 */ +} SYSCFG_TypeDef; + + +/** + * @brief TIM + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< TIM control register 1, Address offset: 0x00 */ + __IO uint32_t CR2; /*!< TIM control register 2, Address offset: 0x04 */ + __IO uint32_t SMCR; /*!< TIM slave mode control register, Address offset: 0x08 */ + __IO uint32_t DIER; /*!< TIM DMA/interrupt enable register, Address offset: 0x0C */ + __IO uint32_t SR; /*!< TIM status register, Address offset: 0x10 */ + __IO uint32_t EGR; /*!< TIM event generation register, Address offset: 0x14 */ + __IO uint32_t CCMR1; /*!< TIM capture/compare mode register 1, Address offset: 0x18 */ + __IO uint32_t CCMR2; /*!< TIM capture/compare mode register 2, Address offset: 0x1C */ + __IO uint32_t CCER; /*!< TIM capture/compare enable register, Address offset: 0x20 */ + __IO uint32_t CNT; /*!< TIM counter register, Address offset: 0x24 */ + __IO uint32_t PSC; /*!< TIM prescaler, Address offset: 0x28 */ + __IO uint32_t ARR; /*!< TIM auto-reload register, Address offset: 0x2C */ + __IO uint32_t RCR; /*!< TIM repetition counter register, Address offset: 0x30 */ + __IO uint32_t CCR1; /*!< TIM capture/compare register 1, Address offset: 0x34 */ + __IO uint32_t CCR2; /*!< TIM capture/compare register 2, Address offset: 0x38 */ + __IO uint32_t CCR3; /*!< TIM capture/compare register 3, Address offset: 0x3C */ + __IO uint32_t CCR4; /*!< TIM capture/compare register 4, Address offset: 0x40 */ + __IO uint32_t BDTR; /*!< TIM break and dead-time register, Address offset: 0x44 */ + __IO uint32_t DCR; /*!< TIM DMA control register, Address offset: 0x48 */ + __IO uint32_t DMAR; /*!< TIM DMA address for full transfer, Address offset: 0x4C */ + __IO uint32_t OR1; /*!< TIM option register 1, Address offset: 0x50 */ + __IO uint32_t CCMR3; /*!< TIM capture/compare mode register 3, Address offset: 0x54 */ + __IO uint32_t CCR5; /*!< TIM capture/compare register5, Address offset: 0x58 */ + __IO uint32_t CCR6; /*!< TIM capture/compare register6, Address offset: 0x5C */ + __IO uint32_t OR2; /*!< TIM option register 2, Address offset: 0x60 */ + __IO uint32_t OR3; /*!< TIM option register 3, Address offset: 0x64 */ +} TIM_TypeDef; + + +/** + * @brief Touch Sensing Controller (TSC) + */ + +typedef struct +{ + __IO uint32_t CR; /*!< TSC control register, Address offset: 0x00 */ + __IO uint32_t IER; /*!< TSC interrupt enable register, Address offset: 0x04 */ + __IO uint32_t ICR; /*!< TSC interrupt clear register, Address offset: 0x08 */ + __IO uint32_t ISR; /*!< TSC interrupt status register, Address offset: 0x0C */ + __IO uint32_t IOHCR; /*!< TSC I/O hysteresis control register, Address offset: 0x10 */ + uint32_t RESERVED1; /*!< Reserved, Address offset: 0x14 */ + __IO uint32_t IOASCR; /*!< TSC I/O analog switch control register, Address offset: 0x18 */ + uint32_t RESERVED2; /*!< Reserved, Address offset: 0x1C */ + __IO uint32_t IOSCR; /*!< TSC I/O sampling control register, Address offset: 0x20 */ + uint32_t RESERVED3; /*!< Reserved, Address offset: 0x24 */ + __IO uint32_t IOCCR; /*!< TSC I/O channel control register, Address offset: 0x28 */ + uint32_t RESERVED4; /*!< Reserved, Address offset: 0x2C */ + __IO uint32_t IOGCSR; /*!< TSC I/O group control status register, Address offset: 0x30 */ + __IO uint32_t IOGXCR[8]; /*!< TSC I/O group x counter register, Address offset: 0x34-50 */ +} TSC_TypeDef; + +/** + * @brief Universal Synchronous Asynchronous Receiver Transmitter + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< USART Control register 1, Address offset: 0x00 */ + __IO uint32_t CR2; /*!< USART Control register 2, Address offset: 0x04 */ + __IO uint32_t CR3; /*!< USART Control register 3, Address offset: 0x08 */ + __IO uint32_t BRR; /*!< USART Baud rate register, Address offset: 0x0C */ + __IO uint16_t GTPR; /*!< USART Guard time and prescaler register, Address offset: 0x10 */ + uint16_t RESERVED2; /*!< Reserved, 0x12 */ + __IO uint32_t RTOR; /*!< USART Receiver Time Out register, Address offset: 0x14 */ + __IO uint16_t RQR; /*!< USART Request register, Address offset: 0x18 */ + uint16_t RESERVED3; /*!< Reserved, 0x1A */ + __IO uint32_t ISR; /*!< USART Interrupt and status register, Address offset: 0x1C */ + __IO uint32_t ICR; /*!< USART Interrupt flag Clear register, Address offset: 0x20 */ + __IO uint16_t RDR; /*!< USART Receive Data register, Address offset: 0x24 */ + uint16_t RESERVED4; /*!< Reserved, 0x26 */ + __IO uint16_t TDR; /*!< USART Transmit Data register, Address offset: 0x28 */ + uint16_t RESERVED5; /*!< Reserved, 0x2A */ +} USART_TypeDef; + +/** + * @brief VREFBUF + */ + +typedef struct +{ + __IO uint32_t CSR; /*!< VREFBUF control and status register, Address offset: 0x00 */ + __IO uint32_t CCR; /*!< VREFBUF calibration and control register, Address offset: 0x04 */ +} VREFBUF_TypeDef; + +/** + * @brief Window WATCHDOG + */ + +typedef struct +{ + __IO uint32_t CR; /*!< WWDG Control register, Address offset: 0x00 */ + __IO uint32_t CFR; /*!< WWDG Configuration register, Address offset: 0x04 */ + __IO uint32_t SR; /*!< WWDG Status register, Address offset: 0x08 */ +} WWDG_TypeDef; + +/** + * @brief AES hardware accelerator + */ + +typedef struct +{ + __IO uint32_t CR; /*!< AES control register, Address offset: 0x00 */ + __IO uint32_t SR; /*!< AES status register, Address offset: 0x04 */ + __IO uint32_t DINR; /*!< AES data input register, Address offset: 0x08 */ + __IO uint32_t DOUTR; /*!< AES data output register, Address offset: 0x0C */ + __IO uint32_t KEYR0; /*!< AES key register 0, Address offset: 0x10 */ + __IO uint32_t KEYR1; /*!< AES key register 1, Address offset: 0x14 */ + __IO uint32_t KEYR2; /*!< AES key register 2, Address offset: 0x18 */ + __IO uint32_t KEYR3; /*!< AES key register 3, Address offset: 0x1C */ + __IO uint32_t IVR0; /*!< AES initialization vector register 0, Address offset: 0x20 */ + __IO uint32_t IVR1; /*!< AES initialization vector register 1, Address offset: 0x24 */ + __IO uint32_t IVR2; /*!< AES initialization vector register 2, Address offset: 0x28 */ + __IO uint32_t IVR3; /*!< AES initialization vector register 3, Address offset: 0x2C */ + __IO uint32_t KEYR4; /*!< AES key register 4, Address offset: 0x30 */ + __IO uint32_t KEYR5; /*!< AES key register 5, Address offset: 0x34 */ + __IO uint32_t KEYR6; /*!< AES key register 6, Address offset: 0x38 */ + __IO uint32_t KEYR7; /*!< AES key register 7, Address offset: 0x3C */ + __IO uint32_t SUSP0R; /*!< AES Suspend register 0, Address offset: 0x40 */ + __IO uint32_t SUSP1R; /*!< AES Suspend register 1, Address offset: 0x44 */ + __IO uint32_t SUSP2R; /*!< AES Suspend register 2, Address offset: 0x48 */ + __IO uint32_t SUSP3R; /*!< AES Suspend register 3, Address offset: 0x4C */ + __IO uint32_t SUSP4R; /*!< AES Suspend register 4, Address offset: 0x50 */ + __IO uint32_t SUSP5R; /*!< AES Suspend register 5, Address offset: 0x54 */ + __IO uint32_t SUSP6R; /*!< AES Suspend register 6, Address offset: 0x58 */ + __IO uint32_t SUSP7R; /*!< AES Suspend register 7, Address offset: 0x6C */ +} AES_TypeDef; + +/** + * @brief HASH + */ + +typedef struct +{ + __IO uint32_t CR; /*!< HASH control register, Address offset: 0x00 */ + __IO uint32_t DIN; /*!< HASH data input register, Address offset: 0x04 */ + __IO uint32_t STR; /*!< HASH start register, Address offset: 0x08 */ + __IO uint32_t HR[5]; /*!< HASH digest registers, Address offset: 0x0C-0x1C */ + __IO uint32_t IMR; /*!< HASH interrupt enable register, Address offset: 0x20 */ + __IO uint32_t SR; /*!< HASH status register, Address offset: 0x24 */ + uint32_t RESERVED[52]; /*!< Reserved, 0x28-0xF4 */ + __IO uint32_t CSR[54]; /*!< HASH context swap registers, Address offset: 0x0F8-0x1CC */ +} HASH_TypeDef; + +/** + * @brief HASH_DIGEST + */ + +typedef struct +{ + __IO uint32_t HR[8]; /*!< HASH digest registers, Address offset: 0x310-0x32C */ +} HASH_DIGEST_TypeDef; + +/** + * @brief RNG + */ + +typedef struct +{ + __IO uint32_t CR; /*!< RNG control register, Address offset: 0x00 */ + __IO uint32_t SR; /*!< RNG status register, Address offset: 0x04 */ + __IO uint32_t DR; /*!< RNG data register, Address offset: 0x08 */ +} RNG_TypeDef; + +/** + * @brief USB_OTG_Core_register + */ +typedef struct +{ + __IO uint32_t GOTGCTL; /*!< USB_OTG Control and Status Register 000h*/ + __IO uint32_t GOTGINT; /*!< USB_OTG Interrupt Register 004h*/ + __IO uint32_t GAHBCFG; /*!< Core AHB Configuration Register 008h*/ + __IO uint32_t GUSBCFG; /*!< Core USB Configuration Register 00Ch*/ + __IO uint32_t GRSTCTL; /*!< Core Reset Register 010h*/ + __IO uint32_t GINTSTS; /*!< Core Interrupt Register 014h*/ + __IO uint32_t GINTMSK; /*!< Core Interrupt Mask Register 018h*/ + __IO uint32_t GRXSTSR; /*!< Receive Sts Q Read Register 01Ch*/ + __IO uint32_t GRXSTSP; /*!< Receive Sts Q Read & POP Register 020h*/ + __IO uint32_t GRXFSIZ; /* Receive FIFO Size Register 024h*/ + __IO uint32_t DIEPTXF0_HNPTXFSIZ; /*!< EP0 / Non Periodic Tx FIFO Size Register 028h*/ + __IO uint32_t HNPTXSTS; /*!< Non Periodic Tx FIFO/Queue Sts reg 02Ch*/ + uint32_t Reserved30[2]; /* Reserved 030h*/ + __IO uint32_t GCCFG; /* General Purpose IO Register 038h*/ + __IO uint32_t CID; /* User ID Register 03Ch*/ + __IO uint32_t GSNPSID; /* USB_OTG core ID 040h*/ + __IO uint32_t GHWCFG1; /* User HW config1 044h*/ + __IO uint32_t GHWCFG2; /* User HW config2 048h*/ + __IO uint32_t GHWCFG3; /* User HW config3 04Ch*/ + uint32_t Reserved6; /* Reserved 050h*/ + __IO uint32_t GLPMCFG; /* LPM Register 054h*/ + __IO uint32_t GPWRDN; /* Power Down Register 058h*/ + __IO uint32_t GDFIFOCFG; /* DFIFO Software Config Register 05Ch*/ + __IO uint32_t GADPCTL; /* ADP Timer, Control and Status Register 60Ch*/ + uint32_t Reserved43[39]; /* Reserved 058h-0FFh*/ + __IO uint32_t HPTXFSIZ; /* Host Periodic Tx FIFO Size Reg 100h*/ + __IO uint32_t DIEPTXF[0x0F]; /* dev Periodic Transmit FIFO */ +} USB_OTG_GlobalTypeDef; + +/** + * @brief USB_OTG_device_Registers + */ +typedef struct +{ + __IO uint32_t DCFG; /* dev Configuration Register 800h*/ + __IO uint32_t DCTL; /* dev Control Register 804h*/ + __IO uint32_t DSTS; /* dev Status Register (RO) 808h*/ + uint32_t Reserved0C; /* Reserved 80Ch*/ + __IO uint32_t DIEPMSK; /* dev IN Endpoint Mask 810h*/ + __IO uint32_t DOEPMSK; /* dev OUT Endpoint Mask 814h*/ + __IO uint32_t DAINT; /* dev All Endpoints Itr Reg 818h*/ + __IO uint32_t DAINTMSK; /* dev All Endpoints Itr Mask 81Ch*/ + uint32_t Reserved20; /* Reserved 820h*/ + uint32_t Reserved9; /* Reserved 824h*/ + __IO uint32_t DVBUSDIS; /* dev VBUS discharge Register 828h*/ + __IO uint32_t DVBUSPULSE; /* dev VBUS Pulse Register 82Ch*/ + __IO uint32_t DTHRCTL; /* dev thr 830h*/ + __IO uint32_t DIEPEMPMSK; /* dev empty msk 834h*/ + __IO uint32_t DEACHINT; /* dedicated EP interrupt 838h*/ + __IO uint32_t DEACHMSK; /* dedicated EP msk 83Ch*/ + uint32_t Reserved40; /* dedicated EP mask 840h*/ + __IO uint32_t DINEP1MSK; /* dedicated EP mask 844h*/ + uint32_t Reserved44[15]; /* Reserved 844-87Ch*/ + __IO uint32_t DOUTEP1MSK; /* dedicated EP msk 884h*/ +} USB_OTG_DeviceTypeDef; + +/** + * @brief USB_OTG_IN_Endpoint-Specific_Register + */ +typedef struct +{ + __IO uint32_t DIEPCTL; /* dev IN Endpoint Control Reg 900h + (ep_num * 20h) + 00h*/ + uint32_t Reserved04; /* Reserved 900h + (ep_num * 20h) + 04h*/ + __IO uint32_t DIEPINT; /* dev IN Endpoint Itr Reg 900h + (ep_num * 20h) + 08h*/ + uint32_t Reserved0C; /* Reserved 900h + (ep_num * 20h) + 0Ch*/ + __IO uint32_t DIEPTSIZ; /* IN Endpoint Txfer Size 900h + (ep_num * 20h) + 10h*/ + __IO uint32_t DIEPDMA; /* IN Endpoint DMA Address Reg 900h + (ep_num * 20h) + 14h*/ + __IO uint32_t DTXFSTS; /*IN Endpoint Tx FIFO Status Reg 900h + (ep_num * 20h) + 18h*/ + uint32_t Reserved18; /* Reserved 900h+(ep_num*20h)+1Ch-900h+ (ep_num * 20h) + 1Ch*/ +} USB_OTG_INEndpointTypeDef; + +/** + * @brief USB_OTG_OUT_Endpoint-Specific_Registers + */ +typedef struct +{ + __IO uint32_t DOEPCTL; /* dev OUT Endpoint Control Reg B00h + (ep_num * 20h) + 00h*/ + uint32_t Reserved04; /* Reserved B00h + (ep_num * 20h) + 04h*/ + __IO uint32_t DOEPINT; /* dev OUT Endpoint Itr Reg B00h + (ep_num * 20h) + 08h*/ + uint32_t Reserved0C; /* Reserved B00h + (ep_num * 20h) + 0Ch*/ + __IO uint32_t DOEPTSIZ; /* dev OUT Endpoint Txfer Size B00h + (ep_num * 20h) + 10h*/ + __IO uint32_t DOEPDMA; /* dev OUT Endpoint DMA Address B00h + (ep_num * 20h) + 14h*/ + uint32_t Reserved18[2]; /* Reserved B00h + (ep_num * 20h) + 18h - B00h + (ep_num * 20h) + 1Ch*/ +} USB_OTG_OUTEndpointTypeDef; + +/** + * @brief USB_OTG_Host_Mode_Register_Structures + */ +typedef struct +{ + __IO uint32_t HCFG; /* Host Configuration Register 400h*/ + __IO uint32_t HFIR; /* Host Frame Interval Register 404h*/ + __IO uint32_t HFNUM; /* Host Frame Nbr/Frame Remaining 408h*/ + uint32_t Reserved40C; /* Reserved 40Ch*/ + __IO uint32_t HPTXSTS; /* Host Periodic Tx FIFO/ Queue Status 410h*/ + __IO uint32_t HAINT; /* Host All Channels Interrupt Register 414h*/ + __IO uint32_t HAINTMSK; /* Host All Channels Interrupt Mask 418h*/ +} USB_OTG_HostTypeDef; + +/** + * @brief USB_OTG_Host_Channel_Specific_Registers + */ +typedef struct +{ + __IO uint32_t HCCHAR; + __IO uint32_t HCSPLT; + __IO uint32_t HCINT; + __IO uint32_t HCINTMSK; + __IO uint32_t HCTSIZ; + __IO uint32_t HCDMA; + uint32_t Reserved[2]; +} USB_OTG_HostChannelTypeDef; + +/** + * @} + */ + +/** @addtogroup Peripheral_memory_map + * @{ + */ +#define FLASH_BASE ((uint32_t)0x08000000U) /*!< FLASH(up to 1 MB) base address */ +#define SRAM1_BASE ((uint32_t)0x20000000U) /*!< SRAM1(up to 256 KB) base address */ +#define SRAM2_BASE ((uint32_t)0x10000000U) /*!< SRAM2(64 KB) base address */ +#define PERIPH_BASE ((uint32_t)0x40000000U) /*!< Peripheral base address */ +#define FMC_BASE ((uint32_t)0x60000000U) /*!< FMC base address */ +#define QSPI_BASE ((uint32_t)0x90000000U) /*!< QUADSPI memories accessible over AHB base address */ + +#define FMC_R_BASE ((uint32_t)0xA0000000U) /*!< FMC control registers base address */ +#define QSPI_R_BASE ((uint32_t)0xA0001000U) /*!< QUADSPI control registers base address */ +#define SRAM1_BB_BASE ((uint32_t)0x22000000U) /*!< SRAM1(96 KB) base address in the bit-band region */ +#define PERIPH_BB_BASE ((uint32_t)0x42000000U) /*!< Peripheral base address in the bit-band region */ + +/* Legacy defines */ +#define SRAM_BASE SRAM1_BASE +#define SRAM_BB_BASE SRAM1_BB_BASE + +#define SRAM1_SIZE_MAX ((uint32_t)0x00040000U) /*!< maximum SRAM1 size (up to 256 KBytes) */ +#define SRAM2_SIZE ((uint32_t)0x00010000U) /*!< SRAM2 size (64 KBytes) */ + +/*!< Peripheral memory map */ +#define APB1PERIPH_BASE PERIPH_BASE +#define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000U) +#define AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000U) +#define AHB2PERIPH_BASE (PERIPH_BASE + 0x08000000U) + +#define FMC_BANK1 FMC_BASE +#define FMC_BANK1_1 FMC_BANK1 +#define FMC_BANK1_2 (FMC_BANK1 + 0x04000000U) +#define FMC_BANK1_3 (FMC_BANK1 + 0x08000000U) +#define FMC_BANK1_4 (FMC_BANK1 + 0x0C000000U) +#define FMC_BANK3 (FMC_BASE + 0x20000000U) + +/*!< APB1 peripherals */ +#define TIM2_BASE (APB1PERIPH_BASE + 0x0000U) +#define TIM3_BASE (APB1PERIPH_BASE + 0x0400U) +#define TIM4_BASE (APB1PERIPH_BASE + 0x0800U) +#define TIM5_BASE (APB1PERIPH_BASE + 0x0C00U) +#define TIM6_BASE (APB1PERIPH_BASE + 0x1000U) +#define TIM7_BASE (APB1PERIPH_BASE + 0x1400U) +#define LCD_BASE (APB1PERIPH_BASE + 0x2400U) +#define RTC_BASE (APB1PERIPH_BASE + 0x2800U) +#define WWDG_BASE (APB1PERIPH_BASE + 0x2C00U) +#define IWDG_BASE (APB1PERIPH_BASE + 0x3000U) +#define SPI2_BASE (APB1PERIPH_BASE + 0x3800U) +#define SPI3_BASE (APB1PERIPH_BASE + 0x3C00U) +#define USART2_BASE (APB1PERIPH_BASE + 0x4400U) +#define USART3_BASE (APB1PERIPH_BASE + 0x4800U) +#define UART4_BASE (APB1PERIPH_BASE + 0x4C00U) +#define UART5_BASE (APB1PERIPH_BASE + 0x5000U) +#define I2C1_BASE (APB1PERIPH_BASE + 0x5400U) +#define I2C2_BASE (APB1PERIPH_BASE + 0x5800U) +#define I2C3_BASE (APB1PERIPH_BASE + 0x5C00U) +#define CRS_BASE (APB1PERIPH_BASE + 0x6000U) +#define CAN1_BASE (APB1PERIPH_BASE + 0x6400U) +#define CAN2_BASE (APB1PERIPH_BASE + 0x6800U) +#define I2C4_BASE (APB1PERIPH_BASE + 0x8400U) +#define PWR_BASE (APB1PERIPH_BASE + 0x7000U) +#define DAC_BASE (APB1PERIPH_BASE + 0x7400U) +#define DAC1_BASE (APB1PERIPH_BASE + 0x7400U) +#define OPAMP_BASE (APB1PERIPH_BASE + 0x7800U) +#define OPAMP1_BASE (APB1PERIPH_BASE + 0x7800U) +#define OPAMP2_BASE (APB1PERIPH_BASE + 0x7810U) +#define LPTIM1_BASE (APB1PERIPH_BASE + 0x7C00U) +#define LPUART1_BASE (APB1PERIPH_BASE + 0x8000U) +#define SWPMI1_BASE (APB1PERIPH_BASE + 0x8800U) +#define LPTIM2_BASE (APB1PERIPH_BASE + 0x9400U) + + +/*!< APB2 peripherals */ +#define SYSCFG_BASE (APB2PERIPH_BASE + 0x0000U) +#define VREFBUF_BASE (APB2PERIPH_BASE + 0x0030U) +#define COMP1_BASE (APB2PERIPH_BASE + 0x0200U) +#define COMP2_BASE (APB2PERIPH_BASE + 0x0204U) +#define EXTI_BASE (APB2PERIPH_BASE + 0x0400U) +#define FIREWALL_BASE (APB2PERIPH_BASE + 0x1C00U) +#define SDMMC1_BASE (APB2PERIPH_BASE + 0x2800U) +#define TIM1_BASE (APB2PERIPH_BASE + 0x2C00U) +#define SPI1_BASE (APB2PERIPH_BASE + 0x3000U) +#define TIM8_BASE (APB2PERIPH_BASE + 0x3400U) +#define USART1_BASE (APB2PERIPH_BASE + 0x3800U) +#define TIM15_BASE (APB2PERIPH_BASE + 0x4000U) +#define TIM16_BASE (APB2PERIPH_BASE + 0x4400U) +#define TIM17_BASE (APB2PERIPH_BASE + 0x4800U) +#define SAI1_BASE (APB2PERIPH_BASE + 0x5400U) +#define SAI1_Block_A_BASE (SAI1_BASE + 0x004) +#define SAI1_Block_B_BASE (SAI1_BASE + 0x024) +#define SAI2_BASE (APB2PERIPH_BASE + 0x5800U) +#define SAI2_Block_A_BASE (SAI2_BASE + 0x004) +#define SAI2_Block_B_BASE (SAI2_BASE + 0x024) +#define DFSDM1_BASE (APB2PERIPH_BASE + 0x6000U) +#define DFSDM1_Channel0_BASE (DFSDM1_BASE + 0x00) +#define DFSDM1_Channel1_BASE (DFSDM1_BASE + 0x20) +#define DFSDM1_Channel2_BASE (DFSDM1_BASE + 0x40) +#define DFSDM1_Channel3_BASE (DFSDM1_BASE + 0x60) +#define DFSDM1_Channel4_BASE (DFSDM1_BASE + 0x80) +#define DFSDM1_Channel5_BASE (DFSDM1_BASE + 0xA0) +#define DFSDM1_Channel6_BASE (DFSDM1_BASE + 0xC0) +#define DFSDM1_Channel7_BASE (DFSDM1_BASE + 0xE0) +#define DFSDM1_Filter0_BASE (DFSDM1_BASE + 0x100) +#define DFSDM1_Filter1_BASE (DFSDM1_BASE + 0x180) +#define DFSDM1_Filter2_BASE (DFSDM1_BASE + 0x200) +#define DFSDM1_Filter3_BASE (DFSDM1_BASE + 0x280) + +/*!< AHB1 peripherals */ +#define DMA1_BASE (AHB1PERIPH_BASE) +#define DMA2_BASE (AHB1PERIPH_BASE + 0x0400U) +#define RCC_BASE (AHB1PERIPH_BASE + 0x1000U) +#define FLASH_R_BASE (AHB1PERIPH_BASE + 0x2000U) +#define CRC_BASE (AHB1PERIPH_BASE + 0x3000U) +#define TSC_BASE (AHB1PERIPH_BASE + 0x4000U) +#define DMA2D_BASE (AHB1PERIPH_BASE + 0xB000U) + + +#define DMA1_Channel1_BASE (DMA1_BASE + 0x0008U) +#define DMA1_Channel2_BASE (DMA1_BASE + 0x001CU) +#define DMA1_Channel3_BASE (DMA1_BASE + 0x0030U) +#define DMA1_Channel4_BASE (DMA1_BASE + 0x0044U) +#define DMA1_Channel5_BASE (DMA1_BASE + 0x0058U) +#define DMA1_Channel6_BASE (DMA1_BASE + 0x006CU) +#define DMA1_Channel7_BASE (DMA1_BASE + 0x0080U) +#define DMA1_CSELR_BASE (DMA1_BASE + 0x00A8U) + + +#define DMA2_Channel1_BASE (DMA2_BASE + 0x0008U) +#define DMA2_Channel2_BASE (DMA2_BASE + 0x001CU) +#define DMA2_Channel3_BASE (DMA2_BASE + 0x0030U) +#define DMA2_Channel4_BASE (DMA2_BASE + 0x0044U) +#define DMA2_Channel5_BASE (DMA2_BASE + 0x0058U) +#define DMA2_Channel6_BASE (DMA2_BASE + 0x006CU) +#define DMA2_Channel7_BASE (DMA2_BASE + 0x0080U) +#define DMA2_CSELR_BASE (DMA2_BASE + 0x00A8U) + + +/*!< AHB2 peripherals */ +#define GPIOA_BASE (AHB2PERIPH_BASE + 0x0000U) +#define GPIOB_BASE (AHB2PERIPH_BASE + 0x0400U) +#define GPIOC_BASE (AHB2PERIPH_BASE + 0x0800U) +#define GPIOD_BASE (AHB2PERIPH_BASE + 0x0C00U) +#define GPIOE_BASE (AHB2PERIPH_BASE + 0x1000U) +#define GPIOF_BASE (AHB2PERIPH_BASE + 0x1400U) +#define GPIOG_BASE (AHB2PERIPH_BASE + 0x1800U) +#define GPIOH_BASE (AHB2PERIPH_BASE + 0x1C00U) +#define GPIOI_BASE (AHB2PERIPH_BASE + 0x2000U) + +#define USBOTG_BASE (AHB2PERIPH_BASE + 0x08000000U) + +#define ADC1_BASE (AHB2PERIPH_BASE + 0x08040000U) +#define ADC2_BASE (AHB2PERIPH_BASE + 0x08040100U) +#define ADC3_BASE (AHB2PERIPH_BASE + 0x08040200U) +#define ADC123_COMMON_BASE (AHB2PERIPH_BASE + 0x08040300U) + +#define DCMI_BASE (AHB2PERIPH_BASE + 0x08050000U) + +#define AES_BASE (AHB2PERIPH_BASE + 0x08060000U) +#define HASH_BASE (AHB2PERIPH_BASE + 0x08060400U) +#define HASH_DIGEST_BASE (AHB2PERIPH_BASE + 0x08060710U) +#define RNG_BASE (AHB2PERIPH_BASE + 0x08060800U) + + +/*!< FMC Banks registers base address */ +#define FMC_Bank1_R_BASE (FMC_R_BASE + 0x0000U) +#define FMC_Bank1E_R_BASE (FMC_R_BASE + 0x0104U) +#define FMC_Bank3_R_BASE (FMC_R_BASE + 0x0080U) + +/* Debug MCU registers base address */ +#define DBGMCU_BASE ((uint32_t)0xE0042000U) + +/*!< USB registers base address */ +#define USB_OTG_FS_PERIPH_BASE ((uint32_t)0x50000000U) + +#define USB_OTG_GLOBAL_BASE ((uint32_t)0x00000000U) +#define USB_OTG_DEVICE_BASE ((uint32_t)0x00000800U) +#define USB_OTG_IN_ENDPOINT_BASE ((uint32_t)0x00000900U) +#define USB_OTG_OUT_ENDPOINT_BASE ((uint32_t)0x00000B00U) +#define USB_OTG_EP_REG_SIZE ((uint32_t)0x00000020U) +#define USB_OTG_HOST_BASE ((uint32_t)0x00000400U) +#define USB_OTG_HOST_PORT_BASE ((uint32_t)0x00000440U) +#define USB_OTG_HOST_CHANNEL_BASE ((uint32_t)0x00000500U) +#define USB_OTG_HOST_CHANNEL_SIZE ((uint32_t)0x00000020U) +#define USB_OTG_PCGCCTL_BASE ((uint32_t)0x00000E00U) +#define USB_OTG_FIFO_BASE ((uint32_t)0x00001000U) +#define USB_OTG_FIFO_SIZE ((uint32_t)0x00001000U) + + +#define PACKAGE_BASE ((uint32_t)0x1FFF7500U) /*!< Package data register base address */ +#define UID_BASE ((uint32_t)0x1FFF7590U) /*!< Unique device ID register base address */ +#define FLASHSIZE_BASE ((uint32_t)0x1FFF75E0U) /*!< Flash size data register base address */ +/** + * @} + */ + +/** @addtogroup Peripheral_declaration + * @{ + */ +#define TIM2 ((TIM_TypeDef *) TIM2_BASE) +#define TIM3 ((TIM_TypeDef *) TIM3_BASE) +#define TIM4 ((TIM_TypeDef *) TIM4_BASE) +#define TIM5 ((TIM_TypeDef *) TIM5_BASE) +#define TIM6 ((TIM_TypeDef *) TIM6_BASE) +#define TIM7 ((TIM_TypeDef *) TIM7_BASE) +#define LCD ((LCD_TypeDef *) LCD_BASE) +#define RTC ((RTC_TypeDef *) RTC_BASE) +#define WWDG ((WWDG_TypeDef *) WWDG_BASE) +#define IWDG ((IWDG_TypeDef *) IWDG_BASE) +#define SPI2 ((SPI_TypeDef *) SPI2_BASE) +#define SPI3 ((SPI_TypeDef *) SPI3_BASE) +#define USART2 ((USART_TypeDef *) USART2_BASE) +#define USART3 ((USART_TypeDef *) USART3_BASE) +#define UART4 ((USART_TypeDef *) UART4_BASE) +#define UART5 ((USART_TypeDef *) UART5_BASE) +#define I2C1 ((I2C_TypeDef *) I2C1_BASE) +#define I2C2 ((I2C_TypeDef *) I2C2_BASE) +#define I2C3 ((I2C_TypeDef *) I2C3_BASE) +#define CRS ((CRS_TypeDef *) CRS_BASE) +#define CAN ((CAN_TypeDef *) CAN1_BASE) +#define CAN1 ((CAN_TypeDef *) CAN1_BASE) +#define CAN2 ((CAN_TypeDef *) CAN2_BASE) +#define I2C4 ((I2C_TypeDef *) I2C4_BASE) +#define PWR ((PWR_TypeDef *) PWR_BASE) +#define DAC ((DAC_TypeDef *) DAC1_BASE) +#define DAC1 ((DAC_TypeDef *) DAC1_BASE) +#define OPAMP ((OPAMP_TypeDef *) OPAMP_BASE) +#define OPAMP1 ((OPAMP_TypeDef *) OPAMP1_BASE) +#define OPAMP2 ((OPAMP_TypeDef *) OPAMP2_BASE) +#define OPAMP12_COMMON ((OPAMP_Common_TypeDef *) OPAMP1_BASE) +#define LPTIM1 ((LPTIM_TypeDef *) LPTIM1_BASE) +#define LPUART1 ((USART_TypeDef *) LPUART1_BASE) +#define SWPMI1 ((SWPMI_TypeDef *) SWPMI1_BASE) +#define LPTIM2 ((LPTIM_TypeDef *) LPTIM2_BASE) + +#define SYSCFG ((SYSCFG_TypeDef *) SYSCFG_BASE) +#define VREFBUF ((VREFBUF_TypeDef *) VREFBUF_BASE) +#define COMP1 ((COMP_TypeDef *) COMP1_BASE) +#define COMP2 ((COMP_TypeDef *) COMP2_BASE) +#define COMP12_COMMON ((COMP_Common_TypeDef *) COMP2_BASE) +#define EXTI ((EXTI_TypeDef *) EXTI_BASE) +#define FIREWALL ((FIREWALL_TypeDef *) FIREWALL_BASE) +#define SDMMC1 ((SDMMC_TypeDef *) SDMMC1_BASE) +#define TIM1 ((TIM_TypeDef *) TIM1_BASE) +#define SPI1 ((SPI_TypeDef *) SPI1_BASE) +#define TIM8 ((TIM_TypeDef *) TIM8_BASE) +#define USART1 ((USART_TypeDef *) USART1_BASE) +#define TIM15 ((TIM_TypeDef *) TIM15_BASE) +#define TIM16 ((TIM_TypeDef *) TIM16_BASE) +#define TIM17 ((TIM_TypeDef *) TIM17_BASE) +#define SAI1 ((SAI_TypeDef *) SAI1_BASE) +#define SAI1_Block_A ((SAI_Block_TypeDef *)SAI1_Block_A_BASE) +#define SAI1_Block_B ((SAI_Block_TypeDef *)SAI1_Block_B_BASE) +#define SAI2 ((SAI_TypeDef *) SAI2_BASE) +#define SAI2_Block_A ((SAI_Block_TypeDef *)SAI2_Block_A_BASE) +#define SAI2_Block_B ((SAI_Block_TypeDef *)SAI2_Block_B_BASE) +#define DFSDM1_Channel0 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel0_BASE) +#define DFSDM1_Channel1 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel1_BASE) +#define DFSDM1_Channel2 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel2_BASE) +#define DFSDM1_Channel3 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel3_BASE) +#define DFSDM1_Channel4 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel4_BASE) +#define DFSDM1_Channel5 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel5_BASE) +#define DFSDM1_Channel6 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel6_BASE) +#define DFSDM1_Channel7 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel7_BASE) +#define DFSDM1_Filter0 ((DFSDM_Filter_TypeDef *) DFSDM1_Filter0_BASE) +#define DFSDM1_Filter1 ((DFSDM_Filter_TypeDef *) DFSDM1_Filter1_BASE) +#define DFSDM1_Filter2 ((DFSDM_Filter_TypeDef *) DFSDM1_Filter2_BASE) +#define DFSDM1_Filter3 ((DFSDM_Filter_TypeDef *) DFSDM1_Filter3_BASE) +/* Aliases to keep compatibility after DFSDM renaming */ +#define DFSDM_Channel0 DFSDM1_Channel0 +#define DFSDM_Channel1 DFSDM1_Channel1 +#define DFSDM_Channel2 DFSDM1_Channel2 +#define DFSDM_Channel3 DFSDM1_Channel3 +#define DFSDM_Channel4 DFSDM1_Channel4 +#define DFSDM_Channel5 DFSDM1_Channel5 +#define DFSDM_Channel6 DFSDM1_Channel6 +#define DFSDM_Channel7 DFSDM1_Channel7 +#define DFSDM_Filter0 DFSDM1_Filter0 +#define DFSDM_Filter1 DFSDM1_Filter1 +#define DFSDM_Filter2 DFSDM1_Filter2 +#define DFSDM_Filter3 DFSDM1_Filter3 +#define DMA1 ((DMA_TypeDef *) DMA1_BASE) +#define DMA2 ((DMA_TypeDef *) DMA2_BASE) +#define RCC ((RCC_TypeDef *) RCC_BASE) +#define FLASH ((FLASH_TypeDef *) FLASH_R_BASE) +#define CRC ((CRC_TypeDef *) CRC_BASE) +#define TSC ((TSC_TypeDef *) TSC_BASE) + +#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE) +#define GPIOB ((GPIO_TypeDef *) GPIOB_BASE) +#define GPIOC ((GPIO_TypeDef *) GPIOC_BASE) +#define GPIOD ((GPIO_TypeDef *) GPIOD_BASE) +#define GPIOE ((GPIO_TypeDef *) GPIOE_BASE) +#define GPIOF ((GPIO_TypeDef *) GPIOF_BASE) +#define GPIOG ((GPIO_TypeDef *) GPIOG_BASE) +#define GPIOH ((GPIO_TypeDef *) GPIOH_BASE) +#define GPIOI ((GPIO_TypeDef *) GPIOI_BASE) +#define ADC1 ((ADC_TypeDef *) ADC1_BASE) +#define ADC2 ((ADC_TypeDef *) ADC2_BASE) +#define ADC3 ((ADC_TypeDef *) ADC3_BASE) +#define ADC123_COMMON ((ADC_Common_TypeDef *) ADC123_COMMON_BASE) +#define DCMI ((DCMI_TypeDef *) DCMI_BASE) +#define DMA2D ((DMA2D_TypeDef *)DMA2D_BASE) +#define HASH ((HASH_TypeDef *) HASH_BASE) +#define HASH_DIGEST ((HASH_DIGEST_TypeDef *) HASH_DIGEST_BASE) +#define AES ((AES_TypeDef *) AES_BASE) +#define RNG ((RNG_TypeDef *) RNG_BASE) + + +#define DMA1_Channel1 ((DMA_Channel_TypeDef *) DMA1_Channel1_BASE) +#define DMA1_Channel2 ((DMA_Channel_TypeDef *) DMA1_Channel2_BASE) +#define DMA1_Channel3 ((DMA_Channel_TypeDef *) DMA1_Channel3_BASE) +#define DMA1_Channel4 ((DMA_Channel_TypeDef *) DMA1_Channel4_BASE) +#define DMA1_Channel5 ((DMA_Channel_TypeDef *) DMA1_Channel5_BASE) +#define DMA1_Channel6 ((DMA_Channel_TypeDef *) DMA1_Channel6_BASE) +#define DMA1_Channel7 ((DMA_Channel_TypeDef *) DMA1_Channel7_BASE) +#define DMA1_CSELR ((DMA_Request_TypeDef *) DMA1_CSELR_BASE) + + +#define DMA2_Channel1 ((DMA_Channel_TypeDef *) DMA2_Channel1_BASE) +#define DMA2_Channel2 ((DMA_Channel_TypeDef *) DMA2_Channel2_BASE) +#define DMA2_Channel3 ((DMA_Channel_TypeDef *) DMA2_Channel3_BASE) +#define DMA2_Channel4 ((DMA_Channel_TypeDef *) DMA2_Channel4_BASE) +#define DMA2_Channel5 ((DMA_Channel_TypeDef *) DMA2_Channel5_BASE) +#define DMA2_Channel6 ((DMA_Channel_TypeDef *) DMA2_Channel6_BASE) +#define DMA2_Channel7 ((DMA_Channel_TypeDef *) DMA2_Channel7_BASE) +#define DMA2_CSELR ((DMA_Request_TypeDef *) DMA2_CSELR_BASE) + + +#define FMC_Bank1_R ((FMC_Bank1_TypeDef *) FMC_Bank1_R_BASE) +#define FMC_Bank1E_R ((FMC_Bank1E_TypeDef *) FMC_Bank1E_R_BASE) +#define FMC_Bank3_R ((FMC_Bank3_TypeDef *) FMC_Bank3_R_BASE) + +#define QUADSPI ((QUADSPI_TypeDef *) QSPI_R_BASE) + +#define DBGMCU ((DBGMCU_TypeDef *) DBGMCU_BASE) + +#define USB_OTG_FS ((USB_OTG_GlobalTypeDef *) USB_OTG_FS_PERIPH_BASE) +/** + * @} + */ + +/** @addtogroup Exported_constants + * @{ + */ + +/** @addtogroup Peripheral_Registers_Bits_Definition + * @{ + */ + +/******************************************************************************/ +/* Peripheral Registers_Bits_Definition */ +/******************************************************************************/ + +/******************************************************************************/ +/* */ +/* Analog to Digital Converter */ +/* */ +/******************************************************************************/ + +/* + * @brief Specific device feature definitions (not present on all devices in the STM32L4 serie) + */ +#define ADC_MULTIMODE_SUPPORT /*!< ADC feature available only on specific devices: multimode available on devices with several ADC instances */ + +/******************** Bit definition for ADC_ISR register *******************/ +#define ADC_ISR_ADRDY_Pos (0U) +#define ADC_ISR_ADRDY_Msk (0x1U << ADC_ISR_ADRDY_Pos) /*!< 0x00000001 */ +#define ADC_ISR_ADRDY ADC_ISR_ADRDY_Msk /*!< ADC ready flag */ +#define ADC_ISR_EOSMP_Pos (1U) +#define ADC_ISR_EOSMP_Msk (0x1U << ADC_ISR_EOSMP_Pos) /*!< 0x00000002 */ +#define ADC_ISR_EOSMP ADC_ISR_EOSMP_Msk /*!< ADC group regular end of sampling flag */ +#define ADC_ISR_EOC_Pos (2U) +#define ADC_ISR_EOC_Msk (0x1U << ADC_ISR_EOC_Pos) /*!< 0x00000004 */ +#define ADC_ISR_EOC ADC_ISR_EOC_Msk /*!< ADC group regular end of unitary conversion flag */ +#define ADC_ISR_EOS_Pos (3U) +#define ADC_ISR_EOS_Msk (0x1U << ADC_ISR_EOS_Pos) /*!< 0x00000008 */ +#define ADC_ISR_EOS ADC_ISR_EOS_Msk /*!< ADC group regular end of sequence conversions flag */ +#define ADC_ISR_OVR_Pos (4U) +#define ADC_ISR_OVR_Msk (0x1U << ADC_ISR_OVR_Pos) /*!< 0x00000010 */ +#define ADC_ISR_OVR ADC_ISR_OVR_Msk /*!< ADC group regular overrun flag */ +#define ADC_ISR_JEOC_Pos (5U) +#define ADC_ISR_JEOC_Msk (0x1U << ADC_ISR_JEOC_Pos) /*!< 0x00000020 */ +#define ADC_ISR_JEOC ADC_ISR_JEOC_Msk /*!< ADC group injected end of unitary conversion flag */ +#define ADC_ISR_JEOS_Pos (6U) +#define ADC_ISR_JEOS_Msk (0x1U << ADC_ISR_JEOS_Pos) /*!< 0x00000040 */ +#define ADC_ISR_JEOS ADC_ISR_JEOS_Msk /*!< ADC group injected end of sequence conversions flag */ +#define ADC_ISR_AWD1_Pos (7U) +#define ADC_ISR_AWD1_Msk (0x1U << ADC_ISR_AWD1_Pos) /*!< 0x00000080 */ +#define ADC_ISR_AWD1 ADC_ISR_AWD1_Msk /*!< ADC analog watchdog 1 flag */ +#define ADC_ISR_AWD2_Pos (8U) +#define ADC_ISR_AWD2_Msk (0x1U << ADC_ISR_AWD2_Pos) /*!< 0x00000100 */ +#define ADC_ISR_AWD2 ADC_ISR_AWD2_Msk /*!< ADC analog watchdog 2 flag */ +#define ADC_ISR_AWD3_Pos (9U) +#define ADC_ISR_AWD3_Msk (0x1U << ADC_ISR_AWD3_Pos) /*!< 0x00000200 */ +#define ADC_ISR_AWD3 ADC_ISR_AWD3_Msk /*!< ADC analog watchdog 3 flag */ +#define ADC_ISR_JQOVF_Pos (10U) +#define ADC_ISR_JQOVF_Msk (0x1U << ADC_ISR_JQOVF_Pos) /*!< 0x00000400 */ +#define ADC_ISR_JQOVF ADC_ISR_JQOVF_Msk /*!< ADC group injected contexts queue overflow flag */ + +/******************** Bit definition for ADC_IER register *******************/ +#define ADC_IER_ADRDYIE_Pos (0U) +#define ADC_IER_ADRDYIE_Msk (0x1U << ADC_IER_ADRDYIE_Pos) /*!< 0x00000001 */ +#define ADC_IER_ADRDYIE ADC_IER_ADRDYIE_Msk /*!< ADC ready interrupt */ +#define ADC_IER_EOSMPIE_Pos (1U) +#define ADC_IER_EOSMPIE_Msk (0x1U << ADC_IER_EOSMPIE_Pos) /*!< 0x00000002 */ +#define ADC_IER_EOSMPIE ADC_IER_EOSMPIE_Msk /*!< ADC group regular end of sampling interrupt */ +#define ADC_IER_EOCIE_Pos (2U) +#define ADC_IER_EOCIE_Msk (0x1U << ADC_IER_EOCIE_Pos) /*!< 0x00000004 */ +#define ADC_IER_EOCIE ADC_IER_EOCIE_Msk /*!< ADC group regular end of unitary conversion interrupt */ +#define ADC_IER_EOSIE_Pos (3U) +#define ADC_IER_EOSIE_Msk (0x1U << ADC_IER_EOSIE_Pos) /*!< 0x00000008 */ +#define ADC_IER_EOSIE ADC_IER_EOSIE_Msk /*!< ADC group regular end of sequence conversions interrupt */ +#define ADC_IER_OVRIE_Pos (4U) +#define ADC_IER_OVRIE_Msk (0x1U << ADC_IER_OVRIE_Pos) /*!< 0x00000010 */ +#define ADC_IER_OVRIE ADC_IER_OVRIE_Msk /*!< ADC group regular overrun interrupt */ +#define ADC_IER_JEOCIE_Pos (5U) +#define ADC_IER_JEOCIE_Msk (0x1U << ADC_IER_JEOCIE_Pos) /*!< 0x00000020 */ +#define ADC_IER_JEOCIE ADC_IER_JEOCIE_Msk /*!< ADC group injected end of unitary conversion interrupt */ +#define ADC_IER_JEOSIE_Pos (6U) +#define ADC_IER_JEOSIE_Msk (0x1U << ADC_IER_JEOSIE_Pos) /*!< 0x00000040 */ +#define ADC_IER_JEOSIE ADC_IER_JEOSIE_Msk /*!< ADC group injected end of sequence conversions interrupt */ +#define ADC_IER_AWD1IE_Pos (7U) +#define ADC_IER_AWD1IE_Msk (0x1U << ADC_IER_AWD1IE_Pos) /*!< 0x00000080 */ +#define ADC_IER_AWD1IE ADC_IER_AWD1IE_Msk /*!< ADC analog watchdog 1 interrupt */ +#define ADC_IER_AWD2IE_Pos (8U) +#define ADC_IER_AWD2IE_Msk (0x1U << ADC_IER_AWD2IE_Pos) /*!< 0x00000100 */ +#define ADC_IER_AWD2IE ADC_IER_AWD2IE_Msk /*!< ADC analog watchdog 2 interrupt */ +#define ADC_IER_AWD3IE_Pos (9U) +#define ADC_IER_AWD3IE_Msk (0x1U << ADC_IER_AWD3IE_Pos) /*!< 0x00000200 */ +#define ADC_IER_AWD3IE ADC_IER_AWD3IE_Msk /*!< ADC analog watchdog 3 interrupt */ +#define ADC_IER_JQOVFIE_Pos (10U) +#define ADC_IER_JQOVFIE_Msk (0x1U << ADC_IER_JQOVFIE_Pos) /*!< 0x00000400 */ +#define ADC_IER_JQOVFIE ADC_IER_JQOVFIE_Msk /*!< ADC group injected contexts queue overflow interrupt */ + +/* Legacy defines */ +#define ADC_IER_ADRDY (ADC_IER_ADRDYIE) +#define ADC_IER_EOSMP (ADC_IER_EOSMPIE) +#define ADC_IER_EOC (ADC_IER_EOCIE) +#define ADC_IER_EOS (ADC_IER_EOSIE) +#define ADC_IER_OVR (ADC_IER_OVRIE) +#define ADC_IER_JEOC (ADC_IER_JEOCIE) +#define ADC_IER_JEOS (ADC_IER_JEOSIE) +#define ADC_IER_AWD1 (ADC_IER_AWD1IE) +#define ADC_IER_AWD2 (ADC_IER_AWD2IE) +#define ADC_IER_AWD3 (ADC_IER_AWD3IE) +#define ADC_IER_JQOVF (ADC_IER_JQOVFIE) + +/******************** Bit definition for ADC_CR register ********************/ +#define ADC_CR_ADEN_Pos (0U) +#define ADC_CR_ADEN_Msk (0x1U << ADC_CR_ADEN_Pos) /*!< 0x00000001 */ +#define ADC_CR_ADEN ADC_CR_ADEN_Msk /*!< ADC enable */ +#define ADC_CR_ADDIS_Pos (1U) +#define ADC_CR_ADDIS_Msk (0x1U << ADC_CR_ADDIS_Pos) /*!< 0x00000002 */ +#define ADC_CR_ADDIS ADC_CR_ADDIS_Msk /*!< ADC disable */ +#define ADC_CR_ADSTART_Pos (2U) +#define ADC_CR_ADSTART_Msk (0x1U << ADC_CR_ADSTART_Pos) /*!< 0x00000004 */ +#define ADC_CR_ADSTART ADC_CR_ADSTART_Msk /*!< ADC group regular conversion start */ +#define ADC_CR_JADSTART_Pos (3U) +#define ADC_CR_JADSTART_Msk (0x1U << ADC_CR_JADSTART_Pos) /*!< 0x00000008 */ +#define ADC_CR_JADSTART ADC_CR_JADSTART_Msk /*!< ADC group injected conversion start */ +#define ADC_CR_ADSTP_Pos (4U) +#define ADC_CR_ADSTP_Msk (0x1U << ADC_CR_ADSTP_Pos) /*!< 0x00000010 */ +#define ADC_CR_ADSTP ADC_CR_ADSTP_Msk /*!< ADC group regular conversion stop */ +#define ADC_CR_JADSTP_Pos (5U) +#define ADC_CR_JADSTP_Msk (0x1U << ADC_CR_JADSTP_Pos) /*!< 0x00000020 */ +#define ADC_CR_JADSTP ADC_CR_JADSTP_Msk /*!< ADC group injected conversion stop */ +#define ADC_CR_ADVREGEN_Pos (28U) +#define ADC_CR_ADVREGEN_Msk (0x1U << ADC_CR_ADVREGEN_Pos) /*!< 0x10000000 */ +#define ADC_CR_ADVREGEN ADC_CR_ADVREGEN_Msk /*!< ADC voltage regulator enable */ +#define ADC_CR_DEEPPWD_Pos (29U) +#define ADC_CR_DEEPPWD_Msk (0x1U << ADC_CR_DEEPPWD_Pos) /*!< 0x20000000 */ +#define ADC_CR_DEEPPWD ADC_CR_DEEPPWD_Msk /*!< ADC deep power down enable */ +#define ADC_CR_ADCALDIF_Pos (30U) +#define ADC_CR_ADCALDIF_Msk (0x1U << ADC_CR_ADCALDIF_Pos) /*!< 0x40000000 */ +#define ADC_CR_ADCALDIF ADC_CR_ADCALDIF_Msk /*!< ADC differential mode for calibration */ +#define ADC_CR_ADCAL_Pos (31U) +#define ADC_CR_ADCAL_Msk (0x1U << ADC_CR_ADCAL_Pos) /*!< 0x80000000 */ +#define ADC_CR_ADCAL ADC_CR_ADCAL_Msk /*!< ADC calibration */ + +/******************** Bit definition for ADC_CFGR register ******************/ +#define ADC_CFGR_DMAEN_Pos (0U) +#define ADC_CFGR_DMAEN_Msk (0x1U << ADC_CFGR_DMAEN_Pos) /*!< 0x00000001 */ +#define ADC_CFGR_DMAEN ADC_CFGR_DMAEN_Msk /*!< ADC DMA transfer enable */ +#define ADC_CFGR_DMACFG_Pos (1U) +#define ADC_CFGR_DMACFG_Msk (0x1U << ADC_CFGR_DMACFG_Pos) /*!< 0x00000002 */ +#define ADC_CFGR_DMACFG ADC_CFGR_DMACFG_Msk /*!< ADC DMA transfer configuration */ + +#define ADC_CFGR_DFSDMCFG_Pos (2U) +#define ADC_CFGR_DFSDMCFG_Msk (0x1U << ADC_CFGR_DFSDMCFG_Pos) /*!< 0x00000004 */ +#define ADC_CFGR_DFSDMCFG ADC_CFGR_DFSDMCFG_Msk /*!< ADC DFSDM mode configuration */ + +#define ADC_CFGR_RES_Pos (3U) +#define ADC_CFGR_RES_Msk (0x3U << ADC_CFGR_RES_Pos) /*!< 0x00000018 */ +#define ADC_CFGR_RES ADC_CFGR_RES_Msk /*!< ADC data resolution */ +#define ADC_CFGR_RES_0 (0x1U << ADC_CFGR_RES_Pos) /*!< 0x00000008 */ +#define ADC_CFGR_RES_1 (0x2U << ADC_CFGR_RES_Pos) /*!< 0x00000010 */ + +#define ADC_CFGR_ALIGN_Pos (5U) +#define ADC_CFGR_ALIGN_Msk (0x1U << ADC_CFGR_ALIGN_Pos) /*!< 0x00000020 */ +#define ADC_CFGR_ALIGN ADC_CFGR_ALIGN_Msk /*!< ADC data alignement */ + +#define ADC_CFGR_EXTSEL_Pos (6U) +#define ADC_CFGR_EXTSEL_Msk (0xFU << ADC_CFGR_EXTSEL_Pos) /*!< 0x000003C0 */ +#define ADC_CFGR_EXTSEL ADC_CFGR_EXTSEL_Msk /*!< ADC group regular external trigger source */ +#define ADC_CFGR_EXTSEL_0 (0x1U << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000040 */ +#define ADC_CFGR_EXTSEL_1 (0x2U << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000080 */ +#define ADC_CFGR_EXTSEL_2 (0x4U << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000100 */ +#define ADC_CFGR_EXTSEL_3 (0x8U << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000200 */ + +#define ADC_CFGR_EXTEN_Pos (10U) +#define ADC_CFGR_EXTEN_Msk (0x3U << ADC_CFGR_EXTEN_Pos) /*!< 0x00000C00 */ +#define ADC_CFGR_EXTEN ADC_CFGR_EXTEN_Msk /*!< ADC group regular external trigger polarity */ +#define ADC_CFGR_EXTEN_0 (0x1U << ADC_CFGR_EXTEN_Pos) /*!< 0x00000400 */ +#define ADC_CFGR_EXTEN_1 (0x2U << ADC_CFGR_EXTEN_Pos) /*!< 0x00000800 */ + +#define ADC_CFGR_OVRMOD_Pos (12U) +#define ADC_CFGR_OVRMOD_Msk (0x1U << ADC_CFGR_OVRMOD_Pos) /*!< 0x00001000 */ +#define ADC_CFGR_OVRMOD ADC_CFGR_OVRMOD_Msk /*!< ADC group regular overrun configuration */ +#define ADC_CFGR_CONT_Pos (13U) +#define ADC_CFGR_CONT_Msk (0x1U << ADC_CFGR_CONT_Pos) /*!< 0x00002000 */ +#define ADC_CFGR_CONT ADC_CFGR_CONT_Msk /*!< ADC group regular continuous conversion mode */ +#define ADC_CFGR_AUTDLY_Pos (14U) +#define ADC_CFGR_AUTDLY_Msk (0x1U << ADC_CFGR_AUTDLY_Pos) /*!< 0x00004000 */ +#define ADC_CFGR_AUTDLY ADC_CFGR_AUTDLY_Msk /*!< ADC low power auto wait */ + +#define ADC_CFGR_DISCEN_Pos (16U) +#define ADC_CFGR_DISCEN_Msk (0x1U << ADC_CFGR_DISCEN_Pos) /*!< 0x00010000 */ +#define ADC_CFGR_DISCEN ADC_CFGR_DISCEN_Msk /*!< ADC group regular sequencer discontinuous mode */ + +#define ADC_CFGR_DISCNUM_Pos (17U) +#define ADC_CFGR_DISCNUM_Msk (0x7U << ADC_CFGR_DISCNUM_Pos) /*!< 0x000E0000 */ +#define ADC_CFGR_DISCNUM ADC_CFGR_DISCNUM_Msk /*!< ADC group regular sequencer discontinuous number of ranks */ +#define ADC_CFGR_DISCNUM_0 (0x1U << ADC_CFGR_DISCNUM_Pos) /*!< 0x00020000 */ +#define ADC_CFGR_DISCNUM_1 (0x2U << ADC_CFGR_DISCNUM_Pos) /*!< 0x00040000 */ +#define ADC_CFGR_DISCNUM_2 (0x4U << ADC_CFGR_DISCNUM_Pos) /*!< 0x00080000 */ + +#define ADC_CFGR_JDISCEN_Pos (20U) +#define ADC_CFGR_JDISCEN_Msk (0x1U << ADC_CFGR_JDISCEN_Pos) /*!< 0x00100000 */ +#define ADC_CFGR_JDISCEN ADC_CFGR_JDISCEN_Msk /*!< ADC group injected sequencer discontinuous mode */ +#define ADC_CFGR_JQM_Pos (21U) +#define ADC_CFGR_JQM_Msk (0x1U << ADC_CFGR_JQM_Pos) /*!< 0x00200000 */ +#define ADC_CFGR_JQM ADC_CFGR_JQM_Msk /*!< ADC group injected contexts queue mode */ +#define ADC_CFGR_AWD1SGL_Pos (22U) +#define ADC_CFGR_AWD1SGL_Msk (0x1U << ADC_CFGR_AWD1SGL_Pos) /*!< 0x00400000 */ +#define ADC_CFGR_AWD1SGL ADC_CFGR_AWD1SGL_Msk /*!< ADC analog watchdog 1 monitoring a single channel or all channels */ +#define ADC_CFGR_AWD1EN_Pos (23U) +#define ADC_CFGR_AWD1EN_Msk (0x1U << ADC_CFGR_AWD1EN_Pos) /*!< 0x00800000 */ +#define ADC_CFGR_AWD1EN ADC_CFGR_AWD1EN_Msk /*!< ADC analog watchdog 1 enable on scope ADC group regular */ +#define ADC_CFGR_JAWD1EN_Pos (24U) +#define ADC_CFGR_JAWD1EN_Msk (0x1U << ADC_CFGR_JAWD1EN_Pos) /*!< 0x01000000 */ +#define ADC_CFGR_JAWD1EN ADC_CFGR_JAWD1EN_Msk /*!< ADC analog watchdog 1 enable on scope ADC group injected */ +#define ADC_CFGR_JAUTO_Pos (25U) +#define ADC_CFGR_JAUTO_Msk (0x1U << ADC_CFGR_JAUTO_Pos) /*!< 0x02000000 */ +#define ADC_CFGR_JAUTO ADC_CFGR_JAUTO_Msk /*!< ADC group injected automatic trigger mode */ + +#define ADC_CFGR_AWD1CH_Pos (26U) +#define ADC_CFGR_AWD1CH_Msk (0x1FU << ADC_CFGR_AWD1CH_Pos) /*!< 0x7C000000 */ +#define ADC_CFGR_AWD1CH ADC_CFGR_AWD1CH_Msk /*!< ADC analog watchdog 1 monitored channel selection */ +#define ADC_CFGR_AWD1CH_0 (0x01U << ADC_CFGR_AWD1CH_Pos) /*!< 0x04000000 */ +#define ADC_CFGR_AWD1CH_1 (0x02U << ADC_CFGR_AWD1CH_Pos) /*!< 0x08000000 */ +#define ADC_CFGR_AWD1CH_2 (0x04U << ADC_CFGR_AWD1CH_Pos) /*!< 0x10000000 */ +#define ADC_CFGR_AWD1CH_3 (0x08U << ADC_CFGR_AWD1CH_Pos) /*!< 0x20000000 */ +#define ADC_CFGR_AWD1CH_4 (0x10U << ADC_CFGR_AWD1CH_Pos) /*!< 0x40000000 */ + +#define ADC_CFGR_JQDIS_Pos (31U) +#define ADC_CFGR_JQDIS_Msk (0x1U << ADC_CFGR_JQDIS_Pos) /*!< 0x80000000 */ +#define ADC_CFGR_JQDIS ADC_CFGR_JQDIS_Msk /*!< ADC group injected contexts queue disable */ + +/******************** Bit definition for ADC_CFGR2 register *****************/ +#define ADC_CFGR2_ROVSE_Pos (0U) +#define ADC_CFGR2_ROVSE_Msk (0x1U << ADC_CFGR2_ROVSE_Pos) /*!< 0x00000001 */ +#define ADC_CFGR2_ROVSE ADC_CFGR2_ROVSE_Msk /*!< ADC oversampler enable on scope ADC group regular */ +#define ADC_CFGR2_JOVSE_Pos (1U) +#define ADC_CFGR2_JOVSE_Msk (0x1U << ADC_CFGR2_JOVSE_Pos) /*!< 0x00000002 */ +#define ADC_CFGR2_JOVSE ADC_CFGR2_JOVSE_Msk /*!< ADC oversampler enable on scope ADC group injected */ + +#define ADC_CFGR2_OVSR_Pos (2U) +#define ADC_CFGR2_OVSR_Msk (0x7U << ADC_CFGR2_OVSR_Pos) /*!< 0x0000001C */ +#define ADC_CFGR2_OVSR ADC_CFGR2_OVSR_Msk /*!< ADC oversampling ratio */ +#define ADC_CFGR2_OVSR_0 (0x1U << ADC_CFGR2_OVSR_Pos) /*!< 0x00000004 */ +#define ADC_CFGR2_OVSR_1 (0x2U << ADC_CFGR2_OVSR_Pos) /*!< 0x00000008 */ +#define ADC_CFGR2_OVSR_2 (0x4U << ADC_CFGR2_OVSR_Pos) /*!< 0x00000010 */ + +#define ADC_CFGR2_OVSS_Pos (5U) +#define ADC_CFGR2_OVSS_Msk (0xFU << ADC_CFGR2_OVSS_Pos) /*!< 0x000001E0 */ +#define ADC_CFGR2_OVSS ADC_CFGR2_OVSS_Msk /*!< ADC oversampling shift */ +#define ADC_CFGR2_OVSS_0 (0x1U << ADC_CFGR2_OVSS_Pos) /*!< 0x00000020 */ +#define ADC_CFGR2_OVSS_1 (0x2U << ADC_CFGR2_OVSS_Pos) /*!< 0x00000040 */ +#define ADC_CFGR2_OVSS_2 (0x4U << ADC_CFGR2_OVSS_Pos) /*!< 0x00000080 */ +#define ADC_CFGR2_OVSS_3 (0x8U << ADC_CFGR2_OVSS_Pos) /*!< 0x00000100 */ + +#define ADC_CFGR2_TROVS_Pos (9U) +#define ADC_CFGR2_TROVS_Msk (0x1U << ADC_CFGR2_TROVS_Pos) /*!< 0x00000200 */ +#define ADC_CFGR2_TROVS ADC_CFGR2_TROVS_Msk /*!< ADC oversampling discontinuous mode (triggered mode) for ADC group regular */ +#define ADC_CFGR2_ROVSM_Pos (10U) +#define ADC_CFGR2_ROVSM_Msk (0x1U << ADC_CFGR2_ROVSM_Pos) /*!< 0x00000400 */ +#define ADC_CFGR2_ROVSM ADC_CFGR2_ROVSM_Msk /*!< ADC oversampling mode managing interlaced conversions of ADC group regular and group injected */ + +/******************** Bit definition for ADC_SMPR1 register *****************/ +#define ADC_SMPR1_SMP0_Pos (0U) +#define ADC_SMPR1_SMP0_Msk (0x7U << ADC_SMPR1_SMP0_Pos) /*!< 0x00000007 */ +#define ADC_SMPR1_SMP0 ADC_SMPR1_SMP0_Msk /*!< ADC channel 0 sampling time selection */ +#define ADC_SMPR1_SMP0_0 (0x1U << ADC_SMPR1_SMP0_Pos) /*!< 0x00000001 */ +#define ADC_SMPR1_SMP0_1 (0x2U << ADC_SMPR1_SMP0_Pos) /*!< 0x00000002 */ +#define ADC_SMPR1_SMP0_2 (0x4U << ADC_SMPR1_SMP0_Pos) /*!< 0x00000004 */ + +#define ADC_SMPR1_SMP1_Pos (3U) +#define ADC_SMPR1_SMP1_Msk (0x7U << ADC_SMPR1_SMP1_Pos) /*!< 0x00000038 */ +#define ADC_SMPR1_SMP1 ADC_SMPR1_SMP1_Msk /*!< ADC channel 1 sampling time selection */ +#define ADC_SMPR1_SMP1_0 (0x1U << ADC_SMPR1_SMP1_Pos) /*!< 0x00000008 */ +#define ADC_SMPR1_SMP1_1 (0x2U << ADC_SMPR1_SMP1_Pos) /*!< 0x00000010 */ +#define ADC_SMPR1_SMP1_2 (0x4U << ADC_SMPR1_SMP1_Pos) /*!< 0x00000020 */ + +#define ADC_SMPR1_SMP2_Pos (6U) +#define ADC_SMPR1_SMP2_Msk (0x7U << ADC_SMPR1_SMP2_Pos) /*!< 0x000001C0 */ +#define ADC_SMPR1_SMP2 ADC_SMPR1_SMP2_Msk /*!< ADC channel 2 sampling time selection */ +#define ADC_SMPR1_SMP2_0 (0x1U << ADC_SMPR1_SMP2_Pos) /*!< 0x00000040 */ +#define ADC_SMPR1_SMP2_1 (0x2U << ADC_SMPR1_SMP2_Pos) /*!< 0x00000080 */ +#define ADC_SMPR1_SMP2_2 (0x4U << ADC_SMPR1_SMP2_Pos) /*!< 0x00000100 */ + +#define ADC_SMPR1_SMP3_Pos (9U) +#define ADC_SMPR1_SMP3_Msk (0x7U << ADC_SMPR1_SMP3_Pos) /*!< 0x00000E00 */ +#define ADC_SMPR1_SMP3 ADC_SMPR1_SMP3_Msk /*!< ADC channel 3 sampling time selection */ +#define ADC_SMPR1_SMP3_0 (0x1U << ADC_SMPR1_SMP3_Pos) /*!< 0x00000200 */ +#define ADC_SMPR1_SMP3_1 (0x2U << ADC_SMPR1_SMP3_Pos) /*!< 0x00000400 */ +#define ADC_SMPR1_SMP3_2 (0x4U << ADC_SMPR1_SMP3_Pos) /*!< 0x00000800 */ + +#define ADC_SMPR1_SMP4_Pos (12U) +#define ADC_SMPR1_SMP4_Msk (0x7U << ADC_SMPR1_SMP4_Pos) /*!< 0x00007000 */ +#define ADC_SMPR1_SMP4 ADC_SMPR1_SMP4_Msk /*!< ADC channel 4 sampling time selection */ +#define ADC_SMPR1_SMP4_0 (0x1U << ADC_SMPR1_SMP4_Pos) /*!< 0x00001000 */ +#define ADC_SMPR1_SMP4_1 (0x2U << ADC_SMPR1_SMP4_Pos) /*!< 0x00002000 */ +#define ADC_SMPR1_SMP4_2 (0x4U << ADC_SMPR1_SMP4_Pos) /*!< 0x00004000 */ + +#define ADC_SMPR1_SMP5_Pos (15U) +#define ADC_SMPR1_SMP5_Msk (0x7U << ADC_SMPR1_SMP5_Pos) /*!< 0x00038000 */ +#define ADC_SMPR1_SMP5 ADC_SMPR1_SMP5_Msk /*!< ADC channel 5 sampling time selection */ +#define ADC_SMPR1_SMP5_0 (0x1U << ADC_SMPR1_SMP5_Pos) /*!< 0x00008000 */ +#define ADC_SMPR1_SMP5_1 (0x2U << ADC_SMPR1_SMP5_Pos) /*!< 0x00010000 */ +#define ADC_SMPR1_SMP5_2 (0x4U << ADC_SMPR1_SMP5_Pos) /*!< 0x00020000 */ + +#define ADC_SMPR1_SMP6_Pos (18U) +#define ADC_SMPR1_SMP6_Msk (0x7U << ADC_SMPR1_SMP6_Pos) /*!< 0x001C0000 */ +#define ADC_SMPR1_SMP6 ADC_SMPR1_SMP6_Msk /*!< ADC channel 6 sampling time selection */ +#define ADC_SMPR1_SMP6_0 (0x1U << ADC_SMPR1_SMP6_Pos) /*!< 0x00040000 */ +#define ADC_SMPR1_SMP6_1 (0x2U << ADC_SMPR1_SMP6_Pos) /*!< 0x00080000 */ +#define ADC_SMPR1_SMP6_2 (0x4U << ADC_SMPR1_SMP6_Pos) /*!< 0x00100000 */ + +#define ADC_SMPR1_SMP7_Pos (21U) +#define ADC_SMPR1_SMP7_Msk (0x7U << ADC_SMPR1_SMP7_Pos) /*!< 0x00E00000 */ +#define ADC_SMPR1_SMP7 ADC_SMPR1_SMP7_Msk /*!< ADC channel 7 sampling time selection */ +#define ADC_SMPR1_SMP7_0 (0x1U << ADC_SMPR1_SMP7_Pos) /*!< 0x00200000 */ +#define ADC_SMPR1_SMP7_1 (0x2U << ADC_SMPR1_SMP7_Pos) /*!< 0x00400000 */ +#define ADC_SMPR1_SMP7_2 (0x4U << ADC_SMPR1_SMP7_Pos) /*!< 0x00800000 */ + +#define ADC_SMPR1_SMP8_Pos (24U) +#define ADC_SMPR1_SMP8_Msk (0x7U << ADC_SMPR1_SMP8_Pos) /*!< 0x07000000 */ +#define ADC_SMPR1_SMP8 ADC_SMPR1_SMP8_Msk /*!< ADC channel 8 sampling time selection */ +#define ADC_SMPR1_SMP8_0 (0x1U << ADC_SMPR1_SMP8_Pos) /*!< 0x01000000 */ +#define ADC_SMPR1_SMP8_1 (0x2U << ADC_SMPR1_SMP8_Pos) /*!< 0x02000000 */ +#define ADC_SMPR1_SMP8_2 (0x4U << ADC_SMPR1_SMP8_Pos) /*!< 0x04000000 */ + +#define ADC_SMPR1_SMP9_Pos (27U) +#define ADC_SMPR1_SMP9_Msk (0x7U << ADC_SMPR1_SMP9_Pos) /*!< 0x38000000 */ +#define ADC_SMPR1_SMP9 ADC_SMPR1_SMP9_Msk /*!< ADC channel 9 sampling time selection */ +#define ADC_SMPR1_SMP9_0 (0x1U << ADC_SMPR1_SMP9_Pos) /*!< 0x08000000 */ +#define ADC_SMPR1_SMP9_1 (0x2U << ADC_SMPR1_SMP9_Pos) /*!< 0x10000000 */ +#define ADC_SMPR1_SMP9_2 (0x4U << ADC_SMPR1_SMP9_Pos) /*!< 0x20000000 */ + +#define ADC_SMPR1_SMPPLUS_Pos (31U) +#define ADC_SMPR1_SMPPLUS_Msk (0x1U << ADC_SMPR1_SMPPLUS_Pos) /*!< 0x80000000 */ +#define ADC_SMPR1_SMPPLUS ADC_SMPR1_SMPPLUS_Msk /*!< ADC channels sampling time additional setting */ + +/******************** Bit definition for ADC_SMPR2 register *****************/ +#define ADC_SMPR2_SMP10_Pos (0U) +#define ADC_SMPR2_SMP10_Msk (0x7U << ADC_SMPR2_SMP10_Pos) /*!< 0x00000007 */ +#define ADC_SMPR2_SMP10 ADC_SMPR2_SMP10_Msk /*!< ADC channel 10 sampling time selection */ +#define ADC_SMPR2_SMP10_0 (0x1U << ADC_SMPR2_SMP10_Pos) /*!< 0x00000001 */ +#define ADC_SMPR2_SMP10_1 (0x2U << ADC_SMPR2_SMP10_Pos) /*!< 0x00000002 */ +#define ADC_SMPR2_SMP10_2 (0x4U << ADC_SMPR2_SMP10_Pos) /*!< 0x00000004 */ + +#define ADC_SMPR2_SMP11_Pos (3U) +#define ADC_SMPR2_SMP11_Msk (0x7U << ADC_SMPR2_SMP11_Pos) /*!< 0x00000038 */ +#define ADC_SMPR2_SMP11 ADC_SMPR2_SMP11_Msk /*!< ADC channel 11 sampling time selection */ +#define ADC_SMPR2_SMP11_0 (0x1U << ADC_SMPR2_SMP11_Pos) /*!< 0x00000008 */ +#define ADC_SMPR2_SMP11_1 (0x2U << ADC_SMPR2_SMP11_Pos) /*!< 0x00000010 */ +#define ADC_SMPR2_SMP11_2 (0x4U << ADC_SMPR2_SMP11_Pos) /*!< 0x00000020 */ + +#define ADC_SMPR2_SMP12_Pos (6U) +#define ADC_SMPR2_SMP12_Msk (0x7U << ADC_SMPR2_SMP12_Pos) /*!< 0x000001C0 */ +#define ADC_SMPR2_SMP12 ADC_SMPR2_SMP12_Msk /*!< ADC channel 12 sampling time selection */ +#define ADC_SMPR2_SMP12_0 (0x1U << ADC_SMPR2_SMP12_Pos) /*!< 0x00000040 */ +#define ADC_SMPR2_SMP12_1 (0x2U << ADC_SMPR2_SMP12_Pos) /*!< 0x00000080 */ +#define ADC_SMPR2_SMP12_2 (0x4U << ADC_SMPR2_SMP12_Pos) /*!< 0x00000100 */ + +#define ADC_SMPR2_SMP13_Pos (9U) +#define ADC_SMPR2_SMP13_Msk (0x7U << ADC_SMPR2_SMP13_Pos) /*!< 0x00000E00 */ +#define ADC_SMPR2_SMP13 ADC_SMPR2_SMP13_Msk /*!< ADC channel 13 sampling time selection */ +#define ADC_SMPR2_SMP13_0 (0x1U << ADC_SMPR2_SMP13_Pos) /*!< 0x00000200 */ +#define ADC_SMPR2_SMP13_1 (0x2U << ADC_SMPR2_SMP13_Pos) /*!< 0x00000400 */ +#define ADC_SMPR2_SMP13_2 (0x4U << ADC_SMPR2_SMP13_Pos) /*!< 0x00000800 */ + +#define ADC_SMPR2_SMP14_Pos (12U) +#define ADC_SMPR2_SMP14_Msk (0x7U << ADC_SMPR2_SMP14_Pos) /*!< 0x00007000 */ +#define ADC_SMPR2_SMP14 ADC_SMPR2_SMP14_Msk /*!< ADC channel 14 sampling time selection */ +#define ADC_SMPR2_SMP14_0 (0x1U << ADC_SMPR2_SMP14_Pos) /*!< 0x00001000 */ +#define ADC_SMPR2_SMP14_1 (0x2U << ADC_SMPR2_SMP14_Pos) /*!< 0x00002000 */ +#define ADC_SMPR2_SMP14_2 (0x4U << ADC_SMPR2_SMP14_Pos) /*!< 0x00004000 */ + +#define ADC_SMPR2_SMP15_Pos (15U) +#define ADC_SMPR2_SMP15_Msk (0x7U << ADC_SMPR2_SMP15_Pos) /*!< 0x00038000 */ +#define ADC_SMPR2_SMP15 ADC_SMPR2_SMP15_Msk /*!< ADC channel 15 sampling time selection */ +#define ADC_SMPR2_SMP15_0 (0x1U << ADC_SMPR2_SMP15_Pos) /*!< 0x00008000 */ +#define ADC_SMPR2_SMP15_1 (0x2U << ADC_SMPR2_SMP15_Pos) /*!< 0x00010000 */ +#define ADC_SMPR2_SMP15_2 (0x4U << ADC_SMPR2_SMP15_Pos) /*!< 0x00020000 */ + +#define ADC_SMPR2_SMP16_Pos (18U) +#define ADC_SMPR2_SMP16_Msk (0x7U << ADC_SMPR2_SMP16_Pos) /*!< 0x001C0000 */ +#define ADC_SMPR2_SMP16 ADC_SMPR2_SMP16_Msk /*!< ADC channel 16 sampling time selection */ +#define ADC_SMPR2_SMP16_0 (0x1U << ADC_SMPR2_SMP16_Pos) /*!< 0x00040000 */ +#define ADC_SMPR2_SMP16_1 (0x2U << ADC_SMPR2_SMP16_Pos) /*!< 0x00080000 */ +#define ADC_SMPR2_SMP16_2 (0x4U << ADC_SMPR2_SMP16_Pos) /*!< 0x00100000 */ + +#define ADC_SMPR2_SMP17_Pos (21U) +#define ADC_SMPR2_SMP17_Msk (0x7U << ADC_SMPR2_SMP17_Pos) /*!< 0x00E00000 */ +#define ADC_SMPR2_SMP17 ADC_SMPR2_SMP17_Msk /*!< ADC channel 17 sampling time selection */ +#define ADC_SMPR2_SMP17_0 (0x1U << ADC_SMPR2_SMP17_Pos) /*!< 0x00200000 */ +#define ADC_SMPR2_SMP17_1 (0x2U << ADC_SMPR2_SMP17_Pos) /*!< 0x00400000 */ +#define ADC_SMPR2_SMP17_2 (0x4U << ADC_SMPR2_SMP17_Pos) /*!< 0x00800000 */ + +#define ADC_SMPR2_SMP18_Pos (24U) +#define ADC_SMPR2_SMP18_Msk (0x7U << ADC_SMPR2_SMP18_Pos) /*!< 0x07000000 */ +#define ADC_SMPR2_SMP18 ADC_SMPR2_SMP18_Msk /*!< ADC channel 18 sampling time selection */ +#define ADC_SMPR2_SMP18_0 (0x1U << ADC_SMPR2_SMP18_Pos) /*!< 0x01000000 */ +#define ADC_SMPR2_SMP18_1 (0x2U << ADC_SMPR2_SMP18_Pos) /*!< 0x02000000 */ +#define ADC_SMPR2_SMP18_2 (0x4U << ADC_SMPR2_SMP18_Pos) /*!< 0x04000000 */ + +/******************** Bit definition for ADC_TR1 register *******************/ +#define ADC_TR1_LT1_Pos (0U) +#define ADC_TR1_LT1_Msk (0xFFFU << ADC_TR1_LT1_Pos) /*!< 0x00000FFF */ +#define ADC_TR1_LT1 ADC_TR1_LT1_Msk /*!< ADC analog watchdog 1 threshold low */ +#define ADC_TR1_LT1_0 (0x001U << ADC_TR1_LT1_Pos) /*!< 0x00000001 */ +#define ADC_TR1_LT1_1 (0x002U << ADC_TR1_LT1_Pos) /*!< 0x00000002 */ +#define ADC_TR1_LT1_2 (0x004U << ADC_TR1_LT1_Pos) /*!< 0x00000004 */ +#define ADC_TR1_LT1_3 (0x008U << ADC_TR1_LT1_Pos) /*!< 0x00000008 */ +#define ADC_TR1_LT1_4 (0x010U << ADC_TR1_LT1_Pos) /*!< 0x00000010 */ +#define ADC_TR1_LT1_5 (0x020U << ADC_TR1_LT1_Pos) /*!< 0x00000020 */ +#define ADC_TR1_LT1_6 (0x040U << ADC_TR1_LT1_Pos) /*!< 0x00000040 */ +#define ADC_TR1_LT1_7 (0x080U << ADC_TR1_LT1_Pos) /*!< 0x00000080 */ +#define ADC_TR1_LT1_8 (0x100U << ADC_TR1_LT1_Pos) /*!< 0x00000100 */ +#define ADC_TR1_LT1_9 (0x200U << ADC_TR1_LT1_Pos) /*!< 0x00000200 */ +#define ADC_TR1_LT1_10 (0x400U << ADC_TR1_LT1_Pos) /*!< 0x00000400 */ +#define ADC_TR1_LT1_11 (0x800U << ADC_TR1_LT1_Pos) /*!< 0x00000800 */ + +#define ADC_TR1_HT1_Pos (16U) +#define ADC_TR1_HT1_Msk (0xFFFU << ADC_TR1_HT1_Pos) /*!< 0x0FFF0000 */ +#define ADC_TR1_HT1 ADC_TR1_HT1_Msk /*!< ADC Analog watchdog 1 threshold high */ +#define ADC_TR1_HT1_0 (0x001U << ADC_TR1_HT1_Pos) /*!< 0x00010000 */ +#define ADC_TR1_HT1_1 (0x002U << ADC_TR1_HT1_Pos) /*!< 0x00020000 */ +#define ADC_TR1_HT1_2 (0x004U << ADC_TR1_HT1_Pos) /*!< 0x00040000 */ +#define ADC_TR1_HT1_3 (0x008U << ADC_TR1_HT1_Pos) /*!< 0x00080000 */ +#define ADC_TR1_HT1_4 (0x010U << ADC_TR1_HT1_Pos) /*!< 0x00100000 */ +#define ADC_TR1_HT1_5 (0x020U << ADC_TR1_HT1_Pos) /*!< 0x00200000 */ +#define ADC_TR1_HT1_6 (0x040U << ADC_TR1_HT1_Pos) /*!< 0x00400000 */ +#define ADC_TR1_HT1_7 (0x080U << ADC_TR1_HT1_Pos) /*!< 0x00800000 */ +#define ADC_TR1_HT1_8 (0x100U << ADC_TR1_HT1_Pos) /*!< 0x01000000 */ +#define ADC_TR1_HT1_9 (0x200U << ADC_TR1_HT1_Pos) /*!< 0x02000000 */ +#define ADC_TR1_HT1_10 (0x400U << ADC_TR1_HT1_Pos) /*!< 0x04000000 */ +#define ADC_TR1_HT1_11 (0x800U << ADC_TR1_HT1_Pos) /*!< 0x08000000 */ + +/******************** Bit definition for ADC_TR2 register *******************/ +#define ADC_TR2_LT2_Pos (0U) +#define ADC_TR2_LT2_Msk (0xFFU << ADC_TR2_LT2_Pos) /*!< 0x000000FF */ +#define ADC_TR2_LT2 ADC_TR2_LT2_Msk /*!< ADC analog watchdog 2 threshold low */ +#define ADC_TR2_LT2_0 (0x01U << ADC_TR2_LT2_Pos) /*!< 0x00000001 */ +#define ADC_TR2_LT2_1 (0x02U << ADC_TR2_LT2_Pos) /*!< 0x00000002 */ +#define ADC_TR2_LT2_2 (0x04U << ADC_TR2_LT2_Pos) /*!< 0x00000004 */ +#define ADC_TR2_LT2_3 (0x08U << ADC_TR2_LT2_Pos) /*!< 0x00000008 */ +#define ADC_TR2_LT2_4 (0x10U << ADC_TR2_LT2_Pos) /*!< 0x00000010 */ +#define ADC_TR2_LT2_5 (0x20U << ADC_TR2_LT2_Pos) /*!< 0x00000020 */ +#define ADC_TR2_LT2_6 (0x40U << ADC_TR2_LT2_Pos) /*!< 0x00000040 */ +#define ADC_TR2_LT2_7 (0x80U << ADC_TR2_LT2_Pos) /*!< 0x00000080 */ + +#define ADC_TR2_HT2_Pos (16U) +#define ADC_TR2_HT2_Msk (0xFFU << ADC_TR2_HT2_Pos) /*!< 0x00FF0000 */ +#define ADC_TR2_HT2 ADC_TR2_HT2_Msk /*!< ADC analog watchdog 2 threshold high */ +#define ADC_TR2_HT2_0 (0x01U << ADC_TR2_HT2_Pos) /*!< 0x00010000 */ +#define ADC_TR2_HT2_1 (0x02U << ADC_TR2_HT2_Pos) /*!< 0x00020000 */ +#define ADC_TR2_HT2_2 (0x04U << ADC_TR2_HT2_Pos) /*!< 0x00040000 */ +#define ADC_TR2_HT2_3 (0x08U << ADC_TR2_HT2_Pos) /*!< 0x00080000 */ +#define ADC_TR2_HT2_4 (0x10U << ADC_TR2_HT2_Pos) /*!< 0x00100000 */ +#define ADC_TR2_HT2_5 (0x20U << ADC_TR2_HT2_Pos) /*!< 0x00200000 */ +#define ADC_TR2_HT2_6 (0x40U << ADC_TR2_HT2_Pos) /*!< 0x00400000 */ +#define ADC_TR2_HT2_7 (0x80U << ADC_TR2_HT2_Pos) /*!< 0x00800000 */ + +/******************** Bit definition for ADC_TR3 register *******************/ +#define ADC_TR3_LT3_Pos (0U) +#define ADC_TR3_LT3_Msk (0xFFU << ADC_TR3_LT3_Pos) /*!< 0x000000FF */ +#define ADC_TR3_LT3 ADC_TR3_LT3_Msk /*!< ADC analog watchdog 3 threshold low */ +#define ADC_TR3_LT3_0 (0x01U << ADC_TR3_LT3_Pos) /*!< 0x00000001 */ +#define ADC_TR3_LT3_1 (0x02U << ADC_TR3_LT3_Pos) /*!< 0x00000002 */ +#define ADC_TR3_LT3_2 (0x04U << ADC_TR3_LT3_Pos) /*!< 0x00000004 */ +#define ADC_TR3_LT3_3 (0x08U << ADC_TR3_LT3_Pos) /*!< 0x00000008 */ +#define ADC_TR3_LT3_4 (0x10U << ADC_TR3_LT3_Pos) /*!< 0x00000010 */ +#define ADC_TR3_LT3_5 (0x20U << ADC_TR3_LT3_Pos) /*!< 0x00000020 */ +#define ADC_TR3_LT3_6 (0x40U << ADC_TR3_LT3_Pos) /*!< 0x00000040 */ +#define ADC_TR3_LT3_7 (0x80U << ADC_TR3_LT3_Pos) /*!< 0x00000080 */ + +#define ADC_TR3_HT3_Pos (16U) +#define ADC_TR3_HT3_Msk (0xFFU << ADC_TR3_HT3_Pos) /*!< 0x00FF0000 */ +#define ADC_TR3_HT3 ADC_TR3_HT3_Msk /*!< ADC analog watchdog 3 threshold high */ +#define ADC_TR3_HT3_0 (0x01U << ADC_TR3_HT3_Pos) /*!< 0x00010000 */ +#define ADC_TR3_HT3_1 (0x02U << ADC_TR3_HT3_Pos) /*!< 0x00020000 */ +#define ADC_TR3_HT3_2 (0x04U << ADC_TR3_HT3_Pos) /*!< 0x00040000 */ +#define ADC_TR3_HT3_3 (0x08U << ADC_TR3_HT3_Pos) /*!< 0x00080000 */ +#define ADC_TR3_HT3_4 (0x10U << ADC_TR3_HT3_Pos) /*!< 0x00100000 */ +#define ADC_TR3_HT3_5 (0x20U << ADC_TR3_HT3_Pos) /*!< 0x00200000 */ +#define ADC_TR3_HT3_6 (0x40U << ADC_TR3_HT3_Pos) /*!< 0x00400000 */ +#define ADC_TR3_HT3_7 (0x80U << ADC_TR3_HT3_Pos) /*!< 0x00800000 */ + +/******************** Bit definition for ADC_SQR1 register ******************/ +#define ADC_SQR1_L_Pos (0U) +#define ADC_SQR1_L_Msk (0xFU << ADC_SQR1_L_Pos) /*!< 0x0000000F */ +#define ADC_SQR1_L ADC_SQR1_L_Msk /*!< ADC group regular sequencer scan length */ +#define ADC_SQR1_L_0 (0x1U << ADC_SQR1_L_Pos) /*!< 0x00000001 */ +#define ADC_SQR1_L_1 (0x2U << ADC_SQR1_L_Pos) /*!< 0x00000002 */ +#define ADC_SQR1_L_2 (0x4U << ADC_SQR1_L_Pos) /*!< 0x00000004 */ +#define ADC_SQR1_L_3 (0x8U << ADC_SQR1_L_Pos) /*!< 0x00000008 */ + +#define ADC_SQR1_SQ1_Pos (6U) +#define ADC_SQR1_SQ1_Msk (0x1FU << ADC_SQR1_SQ1_Pos) /*!< 0x000007C0 */ +#define ADC_SQR1_SQ1 ADC_SQR1_SQ1_Msk /*!< ADC group regular sequencer rank 1 */ +#define ADC_SQR1_SQ1_0 (0x01U << ADC_SQR1_SQ1_Pos) /*!< 0x00000040 */ +#define ADC_SQR1_SQ1_1 (0x02U << ADC_SQR1_SQ1_Pos) /*!< 0x00000080 */ +#define ADC_SQR1_SQ1_2 (0x04U << ADC_SQR1_SQ1_Pos) /*!< 0x00000100 */ +#define ADC_SQR1_SQ1_3 (0x08U << ADC_SQR1_SQ1_Pos) /*!< 0x00000200 */ +#define ADC_SQR1_SQ1_4 (0x10U << ADC_SQR1_SQ1_Pos) /*!< 0x00000400 */ + +#define ADC_SQR1_SQ2_Pos (12U) +#define ADC_SQR1_SQ2_Msk (0x1FU << ADC_SQR1_SQ2_Pos) /*!< 0x0001F000 */ +#define ADC_SQR1_SQ2 ADC_SQR1_SQ2_Msk /*!< ADC group regular sequencer rank 2 */ +#define ADC_SQR1_SQ2_0 (0x01U << ADC_SQR1_SQ2_Pos) /*!< 0x00001000 */ +#define ADC_SQR1_SQ2_1 (0x02U << ADC_SQR1_SQ2_Pos) /*!< 0x00002000 */ +#define ADC_SQR1_SQ2_2 (0x04U << ADC_SQR1_SQ2_Pos) /*!< 0x00004000 */ +#define ADC_SQR1_SQ2_3 (0x08U << ADC_SQR1_SQ2_Pos) /*!< 0x00008000 */ +#define ADC_SQR1_SQ2_4 (0x10U << ADC_SQR1_SQ2_Pos) /*!< 0x00010000 */ + +#define ADC_SQR1_SQ3_Pos (18U) +#define ADC_SQR1_SQ3_Msk (0x1FU << ADC_SQR1_SQ3_Pos) /*!< 0x007C0000 */ +#define ADC_SQR1_SQ3 ADC_SQR1_SQ3_Msk /*!< ADC group regular sequencer rank 3 */ +#define ADC_SQR1_SQ3_0 (0x01U << ADC_SQR1_SQ3_Pos) /*!< 0x00040000 */ +#define ADC_SQR1_SQ3_1 (0x02U << ADC_SQR1_SQ3_Pos) /*!< 0x00080000 */ +#define ADC_SQR1_SQ3_2 (0x04U << ADC_SQR1_SQ3_Pos) /*!< 0x00100000 */ +#define ADC_SQR1_SQ3_3 (0x08U << ADC_SQR1_SQ3_Pos) /*!< 0x00200000 */ +#define ADC_SQR1_SQ3_4 (0x10U << ADC_SQR1_SQ3_Pos) /*!< 0x00400000 */ + +#define ADC_SQR1_SQ4_Pos (24U) +#define ADC_SQR1_SQ4_Msk (0x1FU << ADC_SQR1_SQ4_Pos) /*!< 0x1F000000 */ +#define ADC_SQR1_SQ4 ADC_SQR1_SQ4_Msk /*!< ADC group regular sequencer rank 4 */ +#define ADC_SQR1_SQ4_0 (0x01U << ADC_SQR1_SQ4_Pos) /*!< 0x01000000 */ +#define ADC_SQR1_SQ4_1 (0x02U << ADC_SQR1_SQ4_Pos) /*!< 0x02000000 */ +#define ADC_SQR1_SQ4_2 (0x04U << ADC_SQR1_SQ4_Pos) /*!< 0x04000000 */ +#define ADC_SQR1_SQ4_3 (0x08U << ADC_SQR1_SQ4_Pos) /*!< 0x08000000 */ +#define ADC_SQR1_SQ4_4 (0x10U << ADC_SQR1_SQ4_Pos) /*!< 0x10000000 */ + +/******************** Bit definition for ADC_SQR2 register ******************/ +#define ADC_SQR2_SQ5_Pos (0U) +#define ADC_SQR2_SQ5_Msk (0x1FU << ADC_SQR2_SQ5_Pos) /*!< 0x0000001F */ +#define ADC_SQR2_SQ5 ADC_SQR2_SQ5_Msk /*!< ADC group regular sequencer rank 5 */ +#define ADC_SQR2_SQ5_0 (0x01U << ADC_SQR2_SQ5_Pos) /*!< 0x00000001 */ +#define ADC_SQR2_SQ5_1 (0x02U << ADC_SQR2_SQ5_Pos) /*!< 0x00000002 */ +#define ADC_SQR2_SQ5_2 (0x04U << ADC_SQR2_SQ5_Pos) /*!< 0x00000004 */ +#define ADC_SQR2_SQ5_3 (0x08U << ADC_SQR2_SQ5_Pos) /*!< 0x00000008 */ +#define ADC_SQR2_SQ5_4 (0x10U << ADC_SQR2_SQ5_Pos) /*!< 0x00000010 */ + +#define ADC_SQR2_SQ6_Pos (6U) +#define ADC_SQR2_SQ6_Msk (0x1FU << ADC_SQR2_SQ6_Pos) /*!< 0x000007C0 */ +#define ADC_SQR2_SQ6 ADC_SQR2_SQ6_Msk /*!< ADC group regular sequencer rank 6 */ +#define ADC_SQR2_SQ6_0 (0x01U << ADC_SQR2_SQ6_Pos) /*!< 0x00000040 */ +#define ADC_SQR2_SQ6_1 (0x02U << ADC_SQR2_SQ6_Pos) /*!< 0x00000080 */ +#define ADC_SQR2_SQ6_2 (0x04U << ADC_SQR2_SQ6_Pos) /*!< 0x00000100 */ +#define ADC_SQR2_SQ6_3 (0x08U << ADC_SQR2_SQ6_Pos) /*!< 0x00000200 */ +#define ADC_SQR2_SQ6_4 (0x10U << ADC_SQR2_SQ6_Pos) /*!< 0x00000400 */ + +#define ADC_SQR2_SQ7_Pos (12U) +#define ADC_SQR2_SQ7_Msk (0x1FU << ADC_SQR2_SQ7_Pos) /*!< 0x0001F000 */ +#define ADC_SQR2_SQ7 ADC_SQR2_SQ7_Msk /*!< ADC group regular sequencer rank 7 */ +#define ADC_SQR2_SQ7_0 (0x01U << ADC_SQR2_SQ7_Pos) /*!< 0x00001000 */ +#define ADC_SQR2_SQ7_1 (0x02U << ADC_SQR2_SQ7_Pos) /*!< 0x00002000 */ +#define ADC_SQR2_SQ7_2 (0x04U << ADC_SQR2_SQ7_Pos) /*!< 0x00004000 */ +#define ADC_SQR2_SQ7_3 (0x08U << ADC_SQR2_SQ7_Pos) /*!< 0x00008000 */ +#define ADC_SQR2_SQ7_4 (0x10U << ADC_SQR2_SQ7_Pos) /*!< 0x00010000 */ + +#define ADC_SQR2_SQ8_Pos (18U) +#define ADC_SQR2_SQ8_Msk (0x1FU << ADC_SQR2_SQ8_Pos) /*!< 0x007C0000 */ +#define ADC_SQR2_SQ8 ADC_SQR2_SQ8_Msk /*!< ADC group regular sequencer rank 8 */ +#define ADC_SQR2_SQ8_0 (0x01U << ADC_SQR2_SQ8_Pos) /*!< 0x00040000 */ +#define ADC_SQR2_SQ8_1 (0x02U << ADC_SQR2_SQ8_Pos) /*!< 0x00080000 */ +#define ADC_SQR2_SQ8_2 (0x04U << ADC_SQR2_SQ8_Pos) /*!< 0x00100000 */ +#define ADC_SQR2_SQ8_3 (0x08U << ADC_SQR2_SQ8_Pos) /*!< 0x00200000 */ +#define ADC_SQR2_SQ8_4 (0x10U << ADC_SQR2_SQ8_Pos) /*!< 0x00400000 */ + +#define ADC_SQR2_SQ9_Pos (24U) +#define ADC_SQR2_SQ9_Msk (0x1FU << ADC_SQR2_SQ9_Pos) /*!< 0x1F000000 */ +#define ADC_SQR2_SQ9 ADC_SQR2_SQ9_Msk /*!< ADC group regular sequencer rank 9 */ +#define ADC_SQR2_SQ9_0 (0x01U << ADC_SQR2_SQ9_Pos) /*!< 0x01000000 */ +#define ADC_SQR2_SQ9_1 (0x02U << ADC_SQR2_SQ9_Pos) /*!< 0x02000000 */ +#define ADC_SQR2_SQ9_2 (0x04U << ADC_SQR2_SQ9_Pos) /*!< 0x04000000 */ +#define ADC_SQR2_SQ9_3 (0x08U << ADC_SQR2_SQ9_Pos) /*!< 0x08000000 */ +#define ADC_SQR2_SQ9_4 (0x10U << ADC_SQR2_SQ9_Pos) /*!< 0x10000000 */ + +/******************** Bit definition for ADC_SQR3 register ******************/ +#define ADC_SQR3_SQ10_Pos (0U) +#define ADC_SQR3_SQ10_Msk (0x1FU << ADC_SQR3_SQ10_Pos) /*!< 0x0000001F */ +#define ADC_SQR3_SQ10 ADC_SQR3_SQ10_Msk /*!< ADC group regular sequencer rank 10 */ +#define ADC_SQR3_SQ10_0 (0x01U << ADC_SQR3_SQ10_Pos) /*!< 0x00000001 */ +#define ADC_SQR3_SQ10_1 (0x02U << ADC_SQR3_SQ10_Pos) /*!< 0x00000002 */ +#define ADC_SQR3_SQ10_2 (0x04U << ADC_SQR3_SQ10_Pos) /*!< 0x00000004 */ +#define ADC_SQR3_SQ10_3 (0x08U << ADC_SQR3_SQ10_Pos) /*!< 0x00000008 */ +#define ADC_SQR3_SQ10_4 (0x10U << ADC_SQR3_SQ10_Pos) /*!< 0x00000010 */ + +#define ADC_SQR3_SQ11_Pos (6U) +#define ADC_SQR3_SQ11_Msk (0x1FU << ADC_SQR3_SQ11_Pos) /*!< 0x000007C0 */ +#define ADC_SQR3_SQ11 ADC_SQR3_SQ11_Msk /*!< ADC group regular sequencer rank 11 */ +#define ADC_SQR3_SQ11_0 (0x01U << ADC_SQR3_SQ11_Pos) /*!< 0x00000040 */ +#define ADC_SQR3_SQ11_1 (0x02U << ADC_SQR3_SQ11_Pos) /*!< 0x00000080 */ +#define ADC_SQR3_SQ11_2 (0x04U << ADC_SQR3_SQ11_Pos) /*!< 0x00000100 */ +#define ADC_SQR3_SQ11_3 (0x08U << ADC_SQR3_SQ11_Pos) /*!< 0x00000200 */ +#define ADC_SQR3_SQ11_4 (0x10U << ADC_SQR3_SQ11_Pos) /*!< 0x00000400 */ + +#define ADC_SQR3_SQ12_Pos (12U) +#define ADC_SQR3_SQ12_Msk (0x1FU << ADC_SQR3_SQ12_Pos) /*!< 0x0001F000 */ +#define ADC_SQR3_SQ12 ADC_SQR3_SQ12_Msk /*!< ADC group regular sequencer rank 12 */ +#define ADC_SQR3_SQ12_0 (0x01U << ADC_SQR3_SQ12_Pos) /*!< 0x00001000 */ +#define ADC_SQR3_SQ12_1 (0x02U << ADC_SQR3_SQ12_Pos) /*!< 0x00002000 */ +#define ADC_SQR3_SQ12_2 (0x04U << ADC_SQR3_SQ12_Pos) /*!< 0x00004000 */ +#define ADC_SQR3_SQ12_3 (0x08U << ADC_SQR3_SQ12_Pos) /*!< 0x00008000 */ +#define ADC_SQR3_SQ12_4 (0x10U << ADC_SQR3_SQ12_Pos) /*!< 0x00010000 */ + +#define ADC_SQR3_SQ13_Pos (18U) +#define ADC_SQR3_SQ13_Msk (0x1FU << ADC_SQR3_SQ13_Pos) /*!< 0x007C0000 */ +#define ADC_SQR3_SQ13 ADC_SQR3_SQ13_Msk /*!< ADC group regular sequencer rank 13 */ +#define ADC_SQR3_SQ13_0 (0x01U << ADC_SQR3_SQ13_Pos) /*!< 0x00040000 */ +#define ADC_SQR3_SQ13_1 (0x02U << ADC_SQR3_SQ13_Pos) /*!< 0x00080000 */ +#define ADC_SQR3_SQ13_2 (0x04U << ADC_SQR3_SQ13_Pos) /*!< 0x00100000 */ +#define ADC_SQR3_SQ13_3 (0x08U << ADC_SQR3_SQ13_Pos) /*!< 0x00200000 */ +#define ADC_SQR3_SQ13_4 (0x10U << ADC_SQR3_SQ13_Pos) /*!< 0x00400000 */ + +#define ADC_SQR3_SQ14_Pos (24U) +#define ADC_SQR3_SQ14_Msk (0x1FU << ADC_SQR3_SQ14_Pos) /*!< 0x1F000000 */ +#define ADC_SQR3_SQ14 ADC_SQR3_SQ14_Msk /*!< ADC group regular sequencer rank 14 */ +#define ADC_SQR3_SQ14_0 (0x01U << ADC_SQR3_SQ14_Pos) /*!< 0x01000000 */ +#define ADC_SQR3_SQ14_1 (0x02U << ADC_SQR3_SQ14_Pos) /*!< 0x02000000 */ +#define ADC_SQR3_SQ14_2 (0x04U << ADC_SQR3_SQ14_Pos) /*!< 0x04000000 */ +#define ADC_SQR3_SQ14_3 (0x08U << ADC_SQR3_SQ14_Pos) /*!< 0x08000000 */ +#define ADC_SQR3_SQ14_4 (0x10U << ADC_SQR3_SQ14_Pos) /*!< 0x10000000 */ + +/******************** Bit definition for ADC_SQR4 register ******************/ +#define ADC_SQR4_SQ15_Pos (0U) +#define ADC_SQR4_SQ15_Msk (0x1FU << ADC_SQR4_SQ15_Pos) /*!< 0x0000001F */ +#define ADC_SQR4_SQ15 ADC_SQR4_SQ15_Msk /*!< ADC group regular sequencer rank 15 */ +#define ADC_SQR4_SQ15_0 (0x01U << ADC_SQR4_SQ15_Pos) /*!< 0x00000001 */ +#define ADC_SQR4_SQ15_1 (0x02U << ADC_SQR4_SQ15_Pos) /*!< 0x00000002 */ +#define ADC_SQR4_SQ15_2 (0x04U << ADC_SQR4_SQ15_Pos) /*!< 0x00000004 */ +#define ADC_SQR4_SQ15_3 (0x08U << ADC_SQR4_SQ15_Pos) /*!< 0x00000008 */ +#define ADC_SQR4_SQ15_4 (0x10U << ADC_SQR4_SQ15_Pos) /*!< 0x00000010 */ + +#define ADC_SQR4_SQ16_Pos (6U) +#define ADC_SQR4_SQ16_Msk (0x1FU << ADC_SQR4_SQ16_Pos) /*!< 0x000007C0 */ +#define ADC_SQR4_SQ16 ADC_SQR4_SQ16_Msk /*!< ADC group regular sequencer rank 16 */ +#define ADC_SQR4_SQ16_0 (0x01U << ADC_SQR4_SQ16_Pos) /*!< 0x00000040 */ +#define ADC_SQR4_SQ16_1 (0x02U << ADC_SQR4_SQ16_Pos) /*!< 0x00000080 */ +#define ADC_SQR4_SQ16_2 (0x04U << ADC_SQR4_SQ16_Pos) /*!< 0x00000100 */ +#define ADC_SQR4_SQ16_3 (0x08U << ADC_SQR4_SQ16_Pos) /*!< 0x00000200 */ +#define ADC_SQR4_SQ16_4 (0x10U << ADC_SQR4_SQ16_Pos) /*!< 0x00000400 */ + +/******************** Bit definition for ADC_DR register ********************/ +#define ADC_DR_RDATA_Pos (0U) +#define ADC_DR_RDATA_Msk (0xFFFFU << ADC_DR_RDATA_Pos) /*!< 0x0000FFFF */ +#define ADC_DR_RDATA ADC_DR_RDATA_Msk /*!< ADC group regular conversion data */ +#define ADC_DR_RDATA_0 (0x0001U << ADC_DR_RDATA_Pos) /*!< 0x00000001 */ +#define ADC_DR_RDATA_1 (0x0002U << ADC_DR_RDATA_Pos) /*!< 0x00000002 */ +#define ADC_DR_RDATA_2 (0x0004U << ADC_DR_RDATA_Pos) /*!< 0x00000004 */ +#define ADC_DR_RDATA_3 (0x0008U << ADC_DR_RDATA_Pos) /*!< 0x00000008 */ +#define ADC_DR_RDATA_4 (0x0010U << ADC_DR_RDATA_Pos) /*!< 0x00000010 */ +#define ADC_DR_RDATA_5 (0x0020U << ADC_DR_RDATA_Pos) /*!< 0x00000020 */ +#define ADC_DR_RDATA_6 (0x0040U << ADC_DR_RDATA_Pos) /*!< 0x00000040 */ +#define ADC_DR_RDATA_7 (0x0080U << ADC_DR_RDATA_Pos) /*!< 0x00000080 */ +#define ADC_DR_RDATA_8 (0x0100U << ADC_DR_RDATA_Pos) /*!< 0x00000100 */ +#define ADC_DR_RDATA_9 (0x0200U << ADC_DR_RDATA_Pos) /*!< 0x00000200 */ +#define ADC_DR_RDATA_10 (0x0400U << ADC_DR_RDATA_Pos) /*!< 0x00000400 */ +#define ADC_DR_RDATA_11 (0x0800U << ADC_DR_RDATA_Pos) /*!< 0x00000800 */ +#define ADC_DR_RDATA_12 (0x1000U << ADC_DR_RDATA_Pos) /*!< 0x00001000 */ +#define ADC_DR_RDATA_13 (0x2000U << ADC_DR_RDATA_Pos) /*!< 0x00002000 */ +#define ADC_DR_RDATA_14 (0x4000U << ADC_DR_RDATA_Pos) /*!< 0x00004000 */ +#define ADC_DR_RDATA_15 (0x8000U << ADC_DR_RDATA_Pos) /*!< 0x00008000 */ + +/******************** Bit definition for ADC_JSQR register ******************/ +#define ADC_JSQR_JL_Pos (0U) +#define ADC_JSQR_JL_Msk (0x3U << ADC_JSQR_JL_Pos) /*!< 0x00000003 */ +#define ADC_JSQR_JL ADC_JSQR_JL_Msk /*!< ADC group injected sequencer scan length */ +#define ADC_JSQR_JL_0 (0x1U << ADC_JSQR_JL_Pos) /*!< 0x00000001 */ +#define ADC_JSQR_JL_1 (0x2U << ADC_JSQR_JL_Pos) /*!< 0x00000002 */ + +#define ADC_JSQR_JEXTSEL_Pos (2U) +#define ADC_JSQR_JEXTSEL_Msk (0xFU << ADC_JSQR_JEXTSEL_Pos) /*!< 0x0000003C */ +#define ADC_JSQR_JEXTSEL ADC_JSQR_JEXTSEL_Msk /*!< ADC group injected external trigger source */ +#define ADC_JSQR_JEXTSEL_0 (0x1U << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000004 */ +#define ADC_JSQR_JEXTSEL_1 (0x2U << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000008 */ +#define ADC_JSQR_JEXTSEL_2 (0x4U << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000010 */ +#define ADC_JSQR_JEXTSEL_3 (0x8U << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000020 */ + +#define ADC_JSQR_JEXTEN_Pos (6U) +#define ADC_JSQR_JEXTEN_Msk (0x3U << ADC_JSQR_JEXTEN_Pos) /*!< 0x000000C0 */ +#define ADC_JSQR_JEXTEN ADC_JSQR_JEXTEN_Msk /*!< ADC group injected external trigger polarity */ +#define ADC_JSQR_JEXTEN_0 (0x1U << ADC_JSQR_JEXTEN_Pos) /*!< 0x00000040 */ +#define ADC_JSQR_JEXTEN_1 (0x2U << ADC_JSQR_JEXTEN_Pos) /*!< 0x00000080 */ + +#define ADC_JSQR_JSQ1_Pos (8U) +#define ADC_JSQR_JSQ1_Msk (0x1FU << ADC_JSQR_JSQ1_Pos) /*!< 0x00001F00 */ +#define ADC_JSQR_JSQ1 ADC_JSQR_JSQ1_Msk /*!< ADC group injected sequencer rank 1 */ +#define ADC_JSQR_JSQ1_0 (0x01U << ADC_JSQR_JSQ1_Pos) /*!< 0x00000100 */ +#define ADC_JSQR_JSQ1_1 (0x02U << ADC_JSQR_JSQ1_Pos) /*!< 0x00000200 */ +#define ADC_JSQR_JSQ1_2 (0x04U << ADC_JSQR_JSQ1_Pos) /*!< 0x00000400 */ +#define ADC_JSQR_JSQ1_3 (0x08U << ADC_JSQR_JSQ1_Pos) /*!< 0x00000800 */ +#define ADC_JSQR_JSQ1_4 (0x10U << ADC_JSQR_JSQ1_Pos) /*!< 0x00001000 */ + +#define ADC_JSQR_JSQ2_Pos (14U) +#define ADC_JSQR_JSQ2_Msk (0x1FU << ADC_JSQR_JSQ2_Pos) /*!< 0x0007C000 */ +#define ADC_JSQR_JSQ2 ADC_JSQR_JSQ2_Msk /*!< ADC group injected sequencer rank 2 */ +#define ADC_JSQR_JSQ2_0 (0x01U << ADC_JSQR_JSQ2_Pos) /*!< 0x00004000 */ +#define ADC_JSQR_JSQ2_1 (0x02U << ADC_JSQR_JSQ2_Pos) /*!< 0x00008000 */ +#define ADC_JSQR_JSQ2_2 (0x04U << ADC_JSQR_JSQ2_Pos) /*!< 0x00010000 */ +#define ADC_JSQR_JSQ2_3 (0x08U << ADC_JSQR_JSQ2_Pos) /*!< 0x00020000 */ +#define ADC_JSQR_JSQ2_4 (0x10U << ADC_JSQR_JSQ2_Pos) /*!< 0x00040000 */ + +#define ADC_JSQR_JSQ3_Pos (20U) +#define ADC_JSQR_JSQ3_Msk (0x1FU << ADC_JSQR_JSQ3_Pos) /*!< 0x01F00000 */ +#define ADC_JSQR_JSQ3 ADC_JSQR_JSQ3_Msk /*!< ADC group injected sequencer rank 3 */ +#define ADC_JSQR_JSQ3_0 (0x01U << ADC_JSQR_JSQ3_Pos) /*!< 0x00100000 */ +#define ADC_JSQR_JSQ3_1 (0x02U << ADC_JSQR_JSQ3_Pos) /*!< 0x00200000 */ +#define ADC_JSQR_JSQ3_2 (0x04U << ADC_JSQR_JSQ3_Pos) /*!< 0x00400000 */ +#define ADC_JSQR_JSQ3_3 (0x08U << ADC_JSQR_JSQ3_Pos) /*!< 0x00800000 */ +#define ADC_JSQR_JSQ3_4 (0x10U << ADC_JSQR_JSQ3_Pos) /*!< 0x01000000 */ + +#define ADC_JSQR_JSQ4_Pos (26U) +#define ADC_JSQR_JSQ4_Msk (0x1FU << ADC_JSQR_JSQ4_Pos) /*!< 0x7C000000 */ +#define ADC_JSQR_JSQ4 ADC_JSQR_JSQ4_Msk /*!< ADC group injected sequencer rank 4 */ +#define ADC_JSQR_JSQ4_0 (0x01U << ADC_JSQR_JSQ4_Pos) /*!< 0x04000000 */ +#define ADC_JSQR_JSQ4_1 (0x02U << ADC_JSQR_JSQ4_Pos) /*!< 0x08000000 */ +#define ADC_JSQR_JSQ4_2 (0x04U << ADC_JSQR_JSQ4_Pos) /*!< 0x10000000 */ +#define ADC_JSQR_JSQ4_3 (0x08U << ADC_JSQR_JSQ4_Pos) /*!< 0x20000000 */ +#define ADC_JSQR_JSQ4_4 (0x10U << ADC_JSQR_JSQ4_Pos) /*!< 0x40000000 */ + +/******************** Bit definition for ADC_OFR1 register ******************/ +#define ADC_OFR1_OFFSET1_Pos (0U) +#define ADC_OFR1_OFFSET1_Msk (0xFFFU << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000FFF */ +#define ADC_OFR1_OFFSET1 ADC_OFR1_OFFSET1_Msk /*!< ADC offset number 1 offset level */ +#define ADC_OFR1_OFFSET1_0 (0x001U << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000001 */ +#define ADC_OFR1_OFFSET1_1 (0x002U << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000002 */ +#define ADC_OFR1_OFFSET1_2 (0x004U << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000004 */ +#define ADC_OFR1_OFFSET1_3 (0x008U << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000008 */ +#define ADC_OFR1_OFFSET1_4 (0x010U << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000010 */ +#define ADC_OFR1_OFFSET1_5 (0x020U << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000020 */ +#define ADC_OFR1_OFFSET1_6 (0x040U << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000040 */ +#define ADC_OFR1_OFFSET1_7 (0x080U << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000080 */ +#define ADC_OFR1_OFFSET1_8 (0x100U << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000100 */ +#define ADC_OFR1_OFFSET1_9 (0x200U << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000200 */ +#define ADC_OFR1_OFFSET1_10 (0x400U << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000400 */ +#define ADC_OFR1_OFFSET1_11 (0x800U << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000800 */ + +#define ADC_OFR1_OFFSET1_CH_Pos (26U) +#define ADC_OFR1_OFFSET1_CH_Msk (0x1FU << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x7C000000 */ +#define ADC_OFR1_OFFSET1_CH ADC_OFR1_OFFSET1_CH_Msk /*!< ADC offset number 1 channel selection */ +#define ADC_OFR1_OFFSET1_CH_0 (0x01U << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x04000000 */ +#define ADC_OFR1_OFFSET1_CH_1 (0x02U << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x08000000 */ +#define ADC_OFR1_OFFSET1_CH_2 (0x04U << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x10000000 */ +#define ADC_OFR1_OFFSET1_CH_3 (0x08U << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x20000000 */ +#define ADC_OFR1_OFFSET1_CH_4 (0x10U << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x40000000 */ + +#define ADC_OFR1_OFFSET1_EN_Pos (31U) +#define ADC_OFR1_OFFSET1_EN_Msk (0x1U << ADC_OFR1_OFFSET1_EN_Pos) /*!< 0x80000000 */ +#define ADC_OFR1_OFFSET1_EN ADC_OFR1_OFFSET1_EN_Msk /*!< ADC offset number 1 enable */ + +/******************** Bit definition for ADC_OFR2 register ******************/ +#define ADC_OFR2_OFFSET2_Pos (0U) +#define ADC_OFR2_OFFSET2_Msk (0xFFFU << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000FFF */ +#define ADC_OFR2_OFFSET2 ADC_OFR2_OFFSET2_Msk /*!< ADC offset number 2 offset level */ +#define ADC_OFR2_OFFSET2_0 (0x001U << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000001 */ +#define ADC_OFR2_OFFSET2_1 (0x002U << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000002 */ +#define ADC_OFR2_OFFSET2_2 (0x004U << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000004 */ +#define ADC_OFR2_OFFSET2_3 (0x008U << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000008 */ +#define ADC_OFR2_OFFSET2_4 (0x010U << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000010 */ +#define ADC_OFR2_OFFSET2_5 (0x020U << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000020 */ +#define ADC_OFR2_OFFSET2_6 (0x040U << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000040 */ +#define ADC_OFR2_OFFSET2_7 (0x080U << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000080 */ +#define ADC_OFR2_OFFSET2_8 (0x100U << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000100 */ +#define ADC_OFR2_OFFSET2_9 (0x200U << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000200 */ +#define ADC_OFR2_OFFSET2_10 (0x400U << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000400 */ +#define ADC_OFR2_OFFSET2_11 (0x800U << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000800 */ + +#define ADC_OFR2_OFFSET2_CH_Pos (26U) +#define ADC_OFR2_OFFSET2_CH_Msk (0x1FU << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x7C000000 */ +#define ADC_OFR2_OFFSET2_CH ADC_OFR2_OFFSET2_CH_Msk /*!< ADC offset number 2 channel selection */ +#define ADC_OFR2_OFFSET2_CH_0 (0x01U << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x04000000 */ +#define ADC_OFR2_OFFSET2_CH_1 (0x02U << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x08000000 */ +#define ADC_OFR2_OFFSET2_CH_2 (0x04U << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x10000000 */ +#define ADC_OFR2_OFFSET2_CH_3 (0x08U << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x20000000 */ +#define ADC_OFR2_OFFSET2_CH_4 (0x10U << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x40000000 */ + +#define ADC_OFR2_OFFSET2_EN_Pos (31U) +#define ADC_OFR2_OFFSET2_EN_Msk (0x1U << ADC_OFR2_OFFSET2_EN_Pos) /*!< 0x80000000 */ +#define ADC_OFR2_OFFSET2_EN ADC_OFR2_OFFSET2_EN_Msk /*!< ADC offset number 2 enable */ + +/******************** Bit definition for ADC_OFR3 register ******************/ +#define ADC_OFR3_OFFSET3_Pos (0U) +#define ADC_OFR3_OFFSET3_Msk (0xFFFU << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000FFF */ +#define ADC_OFR3_OFFSET3 ADC_OFR3_OFFSET3_Msk /*!< ADC offset number 3 offset level */ +#define ADC_OFR3_OFFSET3_0 (0x001U << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000001 */ +#define ADC_OFR3_OFFSET3_1 (0x002U << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000002 */ +#define ADC_OFR3_OFFSET3_2 (0x004U << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000004 */ +#define ADC_OFR3_OFFSET3_3 (0x008U << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000008 */ +#define ADC_OFR3_OFFSET3_4 (0x010U << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000010 */ +#define ADC_OFR3_OFFSET3_5 (0x020U << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000020 */ +#define ADC_OFR3_OFFSET3_6 (0x040U << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000040 */ +#define ADC_OFR3_OFFSET3_7 (0x080U << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000080 */ +#define ADC_OFR3_OFFSET3_8 (0x100U << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000100 */ +#define ADC_OFR3_OFFSET3_9 (0x200U << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000200 */ +#define ADC_OFR3_OFFSET3_10 (0x400U << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000400 */ +#define ADC_OFR3_OFFSET3_11 (0x800U << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000800 */ + +#define ADC_OFR3_OFFSET3_CH_Pos (26U) +#define ADC_OFR3_OFFSET3_CH_Msk (0x1FU << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x7C000000 */ +#define ADC_OFR3_OFFSET3_CH ADC_OFR3_OFFSET3_CH_Msk /*!< ADC offset number 3 channel selection */ +#define ADC_OFR3_OFFSET3_CH_0 (0x01U << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x04000000 */ +#define ADC_OFR3_OFFSET3_CH_1 (0x02U << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x08000000 */ +#define ADC_OFR3_OFFSET3_CH_2 (0x04U << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x10000000 */ +#define ADC_OFR3_OFFSET3_CH_3 (0x08U << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x20000000 */ +#define ADC_OFR3_OFFSET3_CH_4 (0x10U << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x40000000 */ + +#define ADC_OFR3_OFFSET3_EN_Pos (31U) +#define ADC_OFR3_OFFSET3_EN_Msk (0x1U << ADC_OFR3_OFFSET3_EN_Pos) /*!< 0x80000000 */ +#define ADC_OFR3_OFFSET3_EN ADC_OFR3_OFFSET3_EN_Msk /*!< ADC offset number 3 enable */ + +/******************** Bit definition for ADC_OFR4 register ******************/ +#define ADC_OFR4_OFFSET4_Pos (0U) +#define ADC_OFR4_OFFSET4_Msk (0xFFFU << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000FFF */ +#define ADC_OFR4_OFFSET4 ADC_OFR4_OFFSET4_Msk /*!< ADC offset number 4 offset level */ +#define ADC_OFR4_OFFSET4_0 (0x001U << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000001 */ +#define ADC_OFR4_OFFSET4_1 (0x002U << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000002 */ +#define ADC_OFR4_OFFSET4_2 (0x004U << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000004 */ +#define ADC_OFR4_OFFSET4_3 (0x008U << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000008 */ +#define ADC_OFR4_OFFSET4_4 (0x010U << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000010 */ +#define ADC_OFR4_OFFSET4_5 (0x020U << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000020 */ +#define ADC_OFR4_OFFSET4_6 (0x040U << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000040 */ +#define ADC_OFR4_OFFSET4_7 (0x080U << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000080 */ +#define ADC_OFR4_OFFSET4_8 (0x100U << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000100 */ +#define ADC_OFR4_OFFSET4_9 (0x200U << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000200 */ +#define ADC_OFR4_OFFSET4_10 (0x400U << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000400 */ +#define ADC_OFR4_OFFSET4_11 (0x800U << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000800 */ + +#define ADC_OFR4_OFFSET4_CH_Pos (26U) +#define ADC_OFR4_OFFSET4_CH_Msk (0x1FU << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x7C000000 */ +#define ADC_OFR4_OFFSET4_CH ADC_OFR4_OFFSET4_CH_Msk /*!< ADC offset number 4 channel selection */ +#define ADC_OFR4_OFFSET4_CH_0 (0x01U << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x04000000 */ +#define ADC_OFR4_OFFSET4_CH_1 (0x02U << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x08000000 */ +#define ADC_OFR4_OFFSET4_CH_2 (0x04U << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x10000000 */ +#define ADC_OFR4_OFFSET4_CH_3 (0x08U << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x20000000 */ +#define ADC_OFR4_OFFSET4_CH_4 (0x10U << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x40000000 */ + +#define ADC_OFR4_OFFSET4_EN_Pos (31U) +#define ADC_OFR4_OFFSET4_EN_Msk (0x1U << ADC_OFR4_OFFSET4_EN_Pos) /*!< 0x80000000 */ +#define ADC_OFR4_OFFSET4_EN ADC_OFR4_OFFSET4_EN_Msk /*!< ADC offset number 4 enable */ + +/******************** Bit definition for ADC_JDR1 register ******************/ +#define ADC_JDR1_JDATA_Pos (0U) +#define ADC_JDR1_JDATA_Msk (0xFFFFU << ADC_JDR1_JDATA_Pos) /*!< 0x0000FFFF */ +#define ADC_JDR1_JDATA ADC_JDR1_JDATA_Msk /*!< ADC group injected sequencer rank 1 conversion data */ +#define ADC_JDR1_JDATA_0 (0x0001U << ADC_JDR1_JDATA_Pos) /*!< 0x00000001 */ +#define ADC_JDR1_JDATA_1 (0x0002U << ADC_JDR1_JDATA_Pos) /*!< 0x00000002 */ +#define ADC_JDR1_JDATA_2 (0x0004U << ADC_JDR1_JDATA_Pos) /*!< 0x00000004 */ +#define ADC_JDR1_JDATA_3 (0x0008U << ADC_JDR1_JDATA_Pos) /*!< 0x00000008 */ +#define ADC_JDR1_JDATA_4 (0x0010U << ADC_JDR1_JDATA_Pos) /*!< 0x00000010 */ +#define ADC_JDR1_JDATA_5 (0x0020U << ADC_JDR1_JDATA_Pos) /*!< 0x00000020 */ +#define ADC_JDR1_JDATA_6 (0x0040U << ADC_JDR1_JDATA_Pos) /*!< 0x00000040 */ +#define ADC_JDR1_JDATA_7 (0x0080U << ADC_JDR1_JDATA_Pos) /*!< 0x00000080 */ +#define ADC_JDR1_JDATA_8 (0x0100U << ADC_JDR1_JDATA_Pos) /*!< 0x00000100 */ +#define ADC_JDR1_JDATA_9 (0x0200U << ADC_JDR1_JDATA_Pos) /*!< 0x00000200 */ +#define ADC_JDR1_JDATA_10 (0x0400U << ADC_JDR1_JDATA_Pos) /*!< 0x00000400 */ +#define ADC_JDR1_JDATA_11 (0x0800U << ADC_JDR1_JDATA_Pos) /*!< 0x00000800 */ +#define ADC_JDR1_JDATA_12 (0x1000U << ADC_JDR1_JDATA_Pos) /*!< 0x00001000 */ +#define ADC_JDR1_JDATA_13 (0x2000U << ADC_JDR1_JDATA_Pos) /*!< 0x00002000 */ +#define ADC_JDR1_JDATA_14 (0x4000U << ADC_JDR1_JDATA_Pos) /*!< 0x00004000 */ +#define ADC_JDR1_JDATA_15 (0x8000U << ADC_JDR1_JDATA_Pos) /*!< 0x00008000 */ + +/******************** Bit definition for ADC_JDR2 register ******************/ +#define ADC_JDR2_JDATA_Pos (0U) +#define ADC_JDR2_JDATA_Msk (0xFFFFU << ADC_JDR2_JDATA_Pos) /*!< 0x0000FFFF */ +#define ADC_JDR2_JDATA ADC_JDR2_JDATA_Msk /*!< ADC group injected sequencer rank 2 conversion data */ +#define ADC_JDR2_JDATA_0 (0x0001U << ADC_JDR2_JDATA_Pos) /*!< 0x00000001 */ +#define ADC_JDR2_JDATA_1 (0x0002U << ADC_JDR2_JDATA_Pos) /*!< 0x00000002 */ +#define ADC_JDR2_JDATA_2 (0x0004U << ADC_JDR2_JDATA_Pos) /*!< 0x00000004 */ +#define ADC_JDR2_JDATA_3 (0x0008U << ADC_JDR2_JDATA_Pos) /*!< 0x00000008 */ +#define ADC_JDR2_JDATA_4 (0x0010U << ADC_JDR2_JDATA_Pos) /*!< 0x00000010 */ +#define ADC_JDR2_JDATA_5 (0x0020U << ADC_JDR2_JDATA_Pos) /*!< 0x00000020 */ +#define ADC_JDR2_JDATA_6 (0x0040U << ADC_JDR2_JDATA_Pos) /*!< 0x00000040 */ +#define ADC_JDR2_JDATA_7 (0x0080U << ADC_JDR2_JDATA_Pos) /*!< 0x00000080 */ +#define ADC_JDR2_JDATA_8 (0x0100U << ADC_JDR2_JDATA_Pos) /*!< 0x00000100 */ +#define ADC_JDR2_JDATA_9 (0x0200U << ADC_JDR2_JDATA_Pos) /*!< 0x00000200 */ +#define ADC_JDR2_JDATA_10 (0x0400U << ADC_JDR2_JDATA_Pos) /*!< 0x00000400 */ +#define ADC_JDR2_JDATA_11 (0x0800U << ADC_JDR2_JDATA_Pos) /*!< 0x00000800 */ +#define ADC_JDR2_JDATA_12 (0x1000U << ADC_JDR2_JDATA_Pos) /*!< 0x00001000 */ +#define ADC_JDR2_JDATA_13 (0x2000U << ADC_JDR2_JDATA_Pos) /*!< 0x00002000 */ +#define ADC_JDR2_JDATA_14 (0x4000U << ADC_JDR2_JDATA_Pos) /*!< 0x00004000 */ +#define ADC_JDR2_JDATA_15 (0x8000U << ADC_JDR2_JDATA_Pos) /*!< 0x00008000 */ + +/******************** Bit definition for ADC_JDR3 register ******************/ +#define ADC_JDR3_JDATA_Pos (0U) +#define ADC_JDR3_JDATA_Msk (0xFFFFU << ADC_JDR3_JDATA_Pos) /*!< 0x0000FFFF */ +#define ADC_JDR3_JDATA ADC_JDR3_JDATA_Msk /*!< ADC group injected sequencer rank 3 conversion data */ +#define ADC_JDR3_JDATA_0 (0x0001U << ADC_JDR3_JDATA_Pos) /*!< 0x00000001 */ +#define ADC_JDR3_JDATA_1 (0x0002U << ADC_JDR3_JDATA_Pos) /*!< 0x00000002 */ +#define ADC_JDR3_JDATA_2 (0x0004U << ADC_JDR3_JDATA_Pos) /*!< 0x00000004 */ +#define ADC_JDR3_JDATA_3 (0x0008U << ADC_JDR3_JDATA_Pos) /*!< 0x00000008 */ +#define ADC_JDR3_JDATA_4 (0x0010U << ADC_JDR3_JDATA_Pos) /*!< 0x00000010 */ +#define ADC_JDR3_JDATA_5 (0x0020U << ADC_JDR3_JDATA_Pos) /*!< 0x00000020 */ +#define ADC_JDR3_JDATA_6 (0x0040U << ADC_JDR3_JDATA_Pos) /*!< 0x00000040 */ +#define ADC_JDR3_JDATA_7 (0x0080U << ADC_JDR3_JDATA_Pos) /*!< 0x00000080 */ +#define ADC_JDR3_JDATA_8 (0x0100U << ADC_JDR3_JDATA_Pos) /*!< 0x00000100 */ +#define ADC_JDR3_JDATA_9 (0x0200U << ADC_JDR3_JDATA_Pos) /*!< 0x00000200 */ +#define ADC_JDR3_JDATA_10 (0x0400U << ADC_JDR3_JDATA_Pos) /*!< 0x00000400 */ +#define ADC_JDR3_JDATA_11 (0x0800U << ADC_JDR3_JDATA_Pos) /*!< 0x00000800 */ +#define ADC_JDR3_JDATA_12 (0x1000U << ADC_JDR3_JDATA_Pos) /*!< 0x00001000 */ +#define ADC_JDR3_JDATA_13 (0x2000U << ADC_JDR3_JDATA_Pos) /*!< 0x00002000 */ +#define ADC_JDR3_JDATA_14 (0x4000U << ADC_JDR3_JDATA_Pos) /*!< 0x00004000 */ +#define ADC_JDR3_JDATA_15 (0x8000U << ADC_JDR3_JDATA_Pos) /*!< 0x00008000 */ + +/******************** Bit definition for ADC_JDR4 register ******************/ +#define ADC_JDR4_JDATA_Pos (0U) +#define ADC_JDR4_JDATA_Msk (0xFFFFU << ADC_JDR4_JDATA_Pos) /*!< 0x0000FFFF */ +#define ADC_JDR4_JDATA ADC_JDR4_JDATA_Msk /*!< ADC group injected sequencer rank 4 conversion data */ +#define ADC_JDR4_JDATA_0 (0x0001U << ADC_JDR4_JDATA_Pos) /*!< 0x00000001 */ +#define ADC_JDR4_JDATA_1 (0x0002U << ADC_JDR4_JDATA_Pos) /*!< 0x00000002 */ +#define ADC_JDR4_JDATA_2 (0x0004U << ADC_JDR4_JDATA_Pos) /*!< 0x00000004 */ +#define ADC_JDR4_JDATA_3 (0x0008U << ADC_JDR4_JDATA_Pos) /*!< 0x00000008 */ +#define ADC_JDR4_JDATA_4 (0x0010U << ADC_JDR4_JDATA_Pos) /*!< 0x00000010 */ +#define ADC_JDR4_JDATA_5 (0x0020U << ADC_JDR4_JDATA_Pos) /*!< 0x00000020 */ +#define ADC_JDR4_JDATA_6 (0x0040U << ADC_JDR4_JDATA_Pos) /*!< 0x00000040 */ +#define ADC_JDR4_JDATA_7 (0x0080U << ADC_JDR4_JDATA_Pos) /*!< 0x00000080 */ +#define ADC_JDR4_JDATA_8 (0x0100U << ADC_JDR4_JDATA_Pos) /*!< 0x00000100 */ +#define ADC_JDR4_JDATA_9 (0x0200U << ADC_JDR4_JDATA_Pos) /*!< 0x00000200 */ +#define ADC_JDR4_JDATA_10 (0x0400U << ADC_JDR4_JDATA_Pos) /*!< 0x00000400 */ +#define ADC_JDR4_JDATA_11 (0x0800U << ADC_JDR4_JDATA_Pos) /*!< 0x00000800 */ +#define ADC_JDR4_JDATA_12 (0x1000U << ADC_JDR4_JDATA_Pos) /*!< 0x00001000 */ +#define ADC_JDR4_JDATA_13 (0x2000U << ADC_JDR4_JDATA_Pos) /*!< 0x00002000 */ +#define ADC_JDR4_JDATA_14 (0x4000U << ADC_JDR4_JDATA_Pos) /*!< 0x00004000 */ +#define ADC_JDR4_JDATA_15 (0x8000U << ADC_JDR4_JDATA_Pos) /*!< 0x00008000 */ + +/******************** Bit definition for ADC_AWD2CR register ****************/ +#define ADC_AWD2CR_AWD2CH_Pos (0U) +#define ADC_AWD2CR_AWD2CH_Msk (0x7FFFFU << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x0007FFFF */ +#define ADC_AWD2CR_AWD2CH ADC_AWD2CR_AWD2CH_Msk /*!< ADC analog watchdog 2 monitored channel selection */ +#define ADC_AWD2CR_AWD2CH_0 (0x00001U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000001 */ +#define ADC_AWD2CR_AWD2CH_1 (0x00002U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000002 */ +#define ADC_AWD2CR_AWD2CH_2 (0x00004U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000004 */ +#define ADC_AWD2CR_AWD2CH_3 (0x00008U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000008 */ +#define ADC_AWD2CR_AWD2CH_4 (0x00010U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000010 */ +#define ADC_AWD2CR_AWD2CH_5 (0x00020U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000020 */ +#define ADC_AWD2CR_AWD2CH_6 (0x00040U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000040 */ +#define ADC_AWD2CR_AWD2CH_7 (0x00080U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000080 */ +#define ADC_AWD2CR_AWD2CH_8 (0x00100U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000100 */ +#define ADC_AWD2CR_AWD2CH_9 (0x00200U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000200 */ +#define ADC_AWD2CR_AWD2CH_10 (0x00400U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000400 */ +#define ADC_AWD2CR_AWD2CH_11 (0x00800U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000800 */ +#define ADC_AWD2CR_AWD2CH_12 (0x01000U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00001000 */ +#define ADC_AWD2CR_AWD2CH_13 (0x02000U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00002000 */ +#define ADC_AWD2CR_AWD2CH_14 (0x04000U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00004000 */ +#define ADC_AWD2CR_AWD2CH_15 (0x08000U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00008000 */ +#define ADC_AWD2CR_AWD2CH_16 (0x10000U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00010000 */ +#define ADC_AWD2CR_AWD2CH_17 (0x20000U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00020000 */ +#define ADC_AWD2CR_AWD2CH_18 (0x40000U << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00040000 */ + +/******************** Bit definition for ADC_AWD3CR register ****************/ +#define ADC_AWD3CR_AWD3CH_Pos (0U) +#define ADC_AWD3CR_AWD3CH_Msk (0x7FFFFU << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x0007FFFF */ +#define ADC_AWD3CR_AWD3CH ADC_AWD3CR_AWD3CH_Msk /*!< ADC analog watchdog 3 monitored channel selection */ +#define ADC_AWD3CR_AWD3CH_0 (0x00001U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000001 */ +#define ADC_AWD3CR_AWD3CH_1 (0x00002U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000002 */ +#define ADC_AWD3CR_AWD3CH_2 (0x00004U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000004 */ +#define ADC_AWD3CR_AWD3CH_3 (0x00008U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000008 */ +#define ADC_AWD3CR_AWD3CH_4 (0x00010U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000010 */ +#define ADC_AWD3CR_AWD3CH_5 (0x00020U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000020 */ +#define ADC_AWD3CR_AWD3CH_6 (0x00040U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000040 */ +#define ADC_AWD3CR_AWD3CH_7 (0x00080U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000080 */ +#define ADC_AWD3CR_AWD3CH_8 (0x00100U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000100 */ +#define ADC_AWD3CR_AWD3CH_9 (0x00200U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000200 */ +#define ADC_AWD3CR_AWD3CH_10 (0x00400U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000400 */ +#define ADC_AWD3CR_AWD3CH_11 (0x00800U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000800 */ +#define ADC_AWD3CR_AWD3CH_12 (0x01000U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00001000 */ +#define ADC_AWD3CR_AWD3CH_13 (0x02000U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00002000 */ +#define ADC_AWD3CR_AWD3CH_14 (0x04000U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00004000 */ +#define ADC_AWD3CR_AWD3CH_15 (0x08000U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00008000 */ +#define ADC_AWD3CR_AWD3CH_16 (0x10000U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00010000 */ +#define ADC_AWD3CR_AWD3CH_17 (0x20000U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00020000 */ +#define ADC_AWD3CR_AWD3CH_18 (0x40000U << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00040000 */ + +/******************** Bit definition for ADC_DIFSEL register ****************/ +#define ADC_DIFSEL_DIFSEL_Pos (0U) +#define ADC_DIFSEL_DIFSEL_Msk (0x7FFFFU << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x0007FFFF */ +#define ADC_DIFSEL_DIFSEL ADC_DIFSEL_DIFSEL_Msk /*!< ADC channel differential or single-ended mode */ +#define ADC_DIFSEL_DIFSEL_0 (0x00001U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000001 */ +#define ADC_DIFSEL_DIFSEL_1 (0x00002U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000002 */ +#define ADC_DIFSEL_DIFSEL_2 (0x00004U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000004 */ +#define ADC_DIFSEL_DIFSEL_3 (0x00008U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000008 */ +#define ADC_DIFSEL_DIFSEL_4 (0x00010U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000010 */ +#define ADC_DIFSEL_DIFSEL_5 (0x00020U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000020 */ +#define ADC_DIFSEL_DIFSEL_6 (0x00040U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000040 */ +#define ADC_DIFSEL_DIFSEL_7 (0x00080U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000080 */ +#define ADC_DIFSEL_DIFSEL_8 (0x00100U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000100 */ +#define ADC_DIFSEL_DIFSEL_9 (0x00200U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000200 */ +#define ADC_DIFSEL_DIFSEL_10 (0x00400U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000400 */ +#define ADC_DIFSEL_DIFSEL_11 (0x00800U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000800 */ +#define ADC_DIFSEL_DIFSEL_12 (0x01000U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00001000 */ +#define ADC_DIFSEL_DIFSEL_13 (0x02000U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00002000 */ +#define ADC_DIFSEL_DIFSEL_14 (0x04000U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00004000 */ +#define ADC_DIFSEL_DIFSEL_15 (0x08000U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00008000 */ +#define ADC_DIFSEL_DIFSEL_16 (0x10000U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00010000 */ +#define ADC_DIFSEL_DIFSEL_17 (0x20000U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00020000 */ +#define ADC_DIFSEL_DIFSEL_18 (0x40000U << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00040000 */ + +/******************** Bit definition for ADC_CALFACT register ***************/ +#define ADC_CALFACT_CALFACT_S_Pos (0U) +#define ADC_CALFACT_CALFACT_S_Msk (0x7FU << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x0000007F */ +#define ADC_CALFACT_CALFACT_S ADC_CALFACT_CALFACT_S_Msk /*!< ADC calibration factor in single-ended mode */ +#define ADC_CALFACT_CALFACT_S_0 (0x01U << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000001 */ +#define ADC_CALFACT_CALFACT_S_1 (0x02U << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000002 */ +#define ADC_CALFACT_CALFACT_S_2 (0x04U << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000004 */ +#define ADC_CALFACT_CALFACT_S_3 (0x08U << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000008 */ +#define ADC_CALFACT_CALFACT_S_4 (0x10U << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000010 */ +#define ADC_CALFACT_CALFACT_S_5 (0x20U << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000020 */ +#define ADC_CALFACT_CALFACT_S_6 (0x40U << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000040 */ + +#define ADC_CALFACT_CALFACT_D_Pos (16U) +#define ADC_CALFACT_CALFACT_D_Msk (0x7FU << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x007F0000 */ +#define ADC_CALFACT_CALFACT_D ADC_CALFACT_CALFACT_D_Msk /*!< ADC calibration factor in differential mode */ +#define ADC_CALFACT_CALFACT_D_0 (0x01U << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00010000 */ +#define ADC_CALFACT_CALFACT_D_1 (0x02U << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00020000 */ +#define ADC_CALFACT_CALFACT_D_2 (0x04U << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00040000 */ +#define ADC_CALFACT_CALFACT_D_3 (0x08U << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00080000 */ +#define ADC_CALFACT_CALFACT_D_4 (0x10U << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00100000 */ +#define ADC_CALFACT_CALFACT_D_5 (0x20U << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00200000 */ +#define ADC_CALFACT_CALFACT_D_6 (0x40U << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00400000 */ + +/************************* ADC Common registers *****************************/ +/******************** Bit definition for ADC_CSR register *******************/ +#define ADC_CSR_ADRDY_MST_Pos (0U) +#define ADC_CSR_ADRDY_MST_Msk (0x1U << ADC_CSR_ADRDY_MST_Pos) /*!< 0x00000001 */ +#define ADC_CSR_ADRDY_MST ADC_CSR_ADRDY_MST_Msk /*!< ADC multimode master ready flag */ +#define ADC_CSR_EOSMP_MST_Pos (1U) +#define ADC_CSR_EOSMP_MST_Msk (0x1U << ADC_CSR_EOSMP_MST_Pos) /*!< 0x00000002 */ +#define ADC_CSR_EOSMP_MST ADC_CSR_EOSMP_MST_Msk /*!< ADC multimode master group regular end of sampling flag */ +#define ADC_CSR_EOC_MST_Pos (2U) +#define ADC_CSR_EOC_MST_Msk (0x1U << ADC_CSR_EOC_MST_Pos) /*!< 0x00000004 */ +#define ADC_CSR_EOC_MST ADC_CSR_EOC_MST_Msk /*!< ADC multimode master group regular end of unitary conversion flag */ +#define ADC_CSR_EOS_MST_Pos (3U) +#define ADC_CSR_EOS_MST_Msk (0x1U << ADC_CSR_EOS_MST_Pos) /*!< 0x00000008 */ +#define ADC_CSR_EOS_MST ADC_CSR_EOS_MST_Msk /*!< ADC multimode master group regular end of sequence conversions flag */ +#define ADC_CSR_OVR_MST_Pos (4U) +#define ADC_CSR_OVR_MST_Msk (0x1U << ADC_CSR_OVR_MST_Pos) /*!< 0x00000010 */ +#define ADC_CSR_OVR_MST ADC_CSR_OVR_MST_Msk /*!< ADC multimode master group regular overrun flag */ +#define ADC_CSR_JEOC_MST_Pos (5U) +#define ADC_CSR_JEOC_MST_Msk (0x1U << ADC_CSR_JEOC_MST_Pos) /*!< 0x00000020 */ +#define ADC_CSR_JEOC_MST ADC_CSR_JEOC_MST_Msk /*!< ADC multimode master group injected end of unitary conversion flag */ +#define ADC_CSR_JEOS_MST_Pos (6U) +#define ADC_CSR_JEOS_MST_Msk (0x1U << ADC_CSR_JEOS_MST_Pos) /*!< 0x00000040 */ +#define ADC_CSR_JEOS_MST ADC_CSR_JEOS_MST_Msk /*!< ADC multimode master group injected end of sequence conversions flag */ +#define ADC_CSR_AWD1_MST_Pos (7U) +#define ADC_CSR_AWD1_MST_Msk (0x1U << ADC_CSR_AWD1_MST_Pos) /*!< 0x00000080 */ +#define ADC_CSR_AWD1_MST ADC_CSR_AWD1_MST_Msk /*!< ADC multimode master analog watchdog 1 flag */ +#define ADC_CSR_AWD2_MST_Pos (8U) +#define ADC_CSR_AWD2_MST_Msk (0x1U << ADC_CSR_AWD2_MST_Pos) /*!< 0x00000100 */ +#define ADC_CSR_AWD2_MST ADC_CSR_AWD2_MST_Msk /*!< ADC multimode master analog watchdog 2 flag */ +#define ADC_CSR_AWD3_MST_Pos (9U) +#define ADC_CSR_AWD3_MST_Msk (0x1U << ADC_CSR_AWD3_MST_Pos) /*!< 0x00000200 */ +#define ADC_CSR_AWD3_MST ADC_CSR_AWD3_MST_Msk /*!< ADC multimode master analog watchdog 3 flag */ +#define ADC_CSR_JQOVF_MST_Pos (10U) +#define ADC_CSR_JQOVF_MST_Msk (0x1U << ADC_CSR_JQOVF_MST_Pos) /*!< 0x00000400 */ +#define ADC_CSR_JQOVF_MST ADC_CSR_JQOVF_MST_Msk /*!< ADC multimode master group injected contexts queue overflow flag */ + +#define ADC_CSR_ADRDY_SLV_Pos (16U) +#define ADC_CSR_ADRDY_SLV_Msk (0x1U << ADC_CSR_ADRDY_SLV_Pos) /*!< 0x00010000 */ +#define ADC_CSR_ADRDY_SLV ADC_CSR_ADRDY_SLV_Msk /*!< ADC multimode slave ready flag */ +#define ADC_CSR_EOSMP_SLV_Pos (17U) +#define ADC_CSR_EOSMP_SLV_Msk (0x1U << ADC_CSR_EOSMP_SLV_Pos) /*!< 0x00020000 */ +#define ADC_CSR_EOSMP_SLV ADC_CSR_EOSMP_SLV_Msk /*!< ADC multimode slave group regular end of sampling flag */ +#define ADC_CSR_EOC_SLV_Pos (18U) +#define ADC_CSR_EOC_SLV_Msk (0x1U << ADC_CSR_EOC_SLV_Pos) /*!< 0x00040000 */ +#define ADC_CSR_EOC_SLV ADC_CSR_EOC_SLV_Msk /*!< ADC multimode slave group regular end of unitary conversion flag */ +#define ADC_CSR_EOS_SLV_Pos (19U) +#define ADC_CSR_EOS_SLV_Msk (0x1U << ADC_CSR_EOS_SLV_Pos) /*!< 0x00080000 */ +#define ADC_CSR_EOS_SLV ADC_CSR_EOS_SLV_Msk /*!< ADC multimode slave group regular end of sequence conversions flag */ +#define ADC_CSR_OVR_SLV_Pos (20U) +#define ADC_CSR_OVR_SLV_Msk (0x1U << ADC_CSR_OVR_SLV_Pos) /*!< 0x00100000 */ +#define ADC_CSR_OVR_SLV ADC_CSR_OVR_SLV_Msk /*!< ADC multimode slave group regular overrun flag */ +#define ADC_CSR_JEOC_SLV_Pos (21U) +#define ADC_CSR_JEOC_SLV_Msk (0x1U << ADC_CSR_JEOC_SLV_Pos) /*!< 0x00200000 */ +#define ADC_CSR_JEOC_SLV ADC_CSR_JEOC_SLV_Msk /*!< ADC multimode slave group injected end of unitary conversion flag */ +#define ADC_CSR_JEOS_SLV_Pos (22U) +#define ADC_CSR_JEOS_SLV_Msk (0x1U << ADC_CSR_JEOS_SLV_Pos) /*!< 0x00400000 */ +#define ADC_CSR_JEOS_SLV ADC_CSR_JEOS_SLV_Msk /*!< ADC multimode slave group injected end of sequence conversions flag */ +#define ADC_CSR_AWD1_SLV_Pos (23U) +#define ADC_CSR_AWD1_SLV_Msk (0x1U << ADC_CSR_AWD1_SLV_Pos) /*!< 0x00800000 */ +#define ADC_CSR_AWD1_SLV ADC_CSR_AWD1_SLV_Msk /*!< ADC multimode slave analog watchdog 1 flag */ +#define ADC_CSR_AWD2_SLV_Pos (24U) +#define ADC_CSR_AWD2_SLV_Msk (0x1U << ADC_CSR_AWD2_SLV_Pos) /*!< 0x01000000 */ +#define ADC_CSR_AWD2_SLV ADC_CSR_AWD2_SLV_Msk /*!< ADC multimode slave analog watchdog 2 flag */ +#define ADC_CSR_AWD3_SLV_Pos (25U) +#define ADC_CSR_AWD3_SLV_Msk (0x1U << ADC_CSR_AWD3_SLV_Pos) /*!< 0x02000000 */ +#define ADC_CSR_AWD3_SLV ADC_CSR_AWD3_SLV_Msk /*!< ADC multimode slave analog watchdog 3 flag */ +#define ADC_CSR_JQOVF_SLV_Pos (26U) +#define ADC_CSR_JQOVF_SLV_Msk (0x1U << ADC_CSR_JQOVF_SLV_Pos) /*!< 0x04000000 */ +#define ADC_CSR_JQOVF_SLV ADC_CSR_JQOVF_SLV_Msk /*!< ADC multimode slave group injected contexts queue overflow flag */ + +/******************** Bit definition for ADC_CCR register *******************/ +#define ADC_CCR_DUAL_Pos (0U) +#define ADC_CCR_DUAL_Msk (0x1FU << ADC_CCR_DUAL_Pos) /*!< 0x0000001F */ +#define ADC_CCR_DUAL ADC_CCR_DUAL_Msk /*!< ADC multimode mode selection */ +#define ADC_CCR_DUAL_0 (0x01U << ADC_CCR_DUAL_Pos) /*!< 0x00000001 */ +#define ADC_CCR_DUAL_1 (0x02U << ADC_CCR_DUAL_Pos) /*!< 0x00000002 */ +#define ADC_CCR_DUAL_2 (0x04U << ADC_CCR_DUAL_Pos) /*!< 0x00000004 */ +#define ADC_CCR_DUAL_3 (0x08U << ADC_CCR_DUAL_Pos) /*!< 0x00000008 */ +#define ADC_CCR_DUAL_4 (0x10U << ADC_CCR_DUAL_Pos) /*!< 0x00000010 */ + +#define ADC_CCR_DELAY_Pos (8U) +#define ADC_CCR_DELAY_Msk (0xFU << ADC_CCR_DELAY_Pos) /*!< 0x00000F00 */ +#define ADC_CCR_DELAY ADC_CCR_DELAY_Msk /*!< ADC multimode delay between 2 sampling phases */ +#define ADC_CCR_DELAY_0 (0x1U << ADC_CCR_DELAY_Pos) /*!< 0x00000100 */ +#define ADC_CCR_DELAY_1 (0x2U << ADC_CCR_DELAY_Pos) /*!< 0x00000200 */ +#define ADC_CCR_DELAY_2 (0x4U << ADC_CCR_DELAY_Pos) /*!< 0x00000400 */ +#define ADC_CCR_DELAY_3 (0x8U << ADC_CCR_DELAY_Pos) /*!< 0x00000800 */ + +#define ADC_CCR_DMACFG_Pos (13U) +#define ADC_CCR_DMACFG_Msk (0x1U << ADC_CCR_DMACFG_Pos) /*!< 0x00002000 */ +#define ADC_CCR_DMACFG ADC_CCR_DMACFG_Msk /*!< ADC multimode DMA transfer configuration */ + +#define ADC_CCR_MDMA_Pos (14U) +#define ADC_CCR_MDMA_Msk (0x3U << ADC_CCR_MDMA_Pos) /*!< 0x0000C000 */ +#define ADC_CCR_MDMA ADC_CCR_MDMA_Msk /*!< ADC multimode DMA transfer enable */ +#define ADC_CCR_MDMA_0 (0x1U << ADC_CCR_MDMA_Pos) /*!< 0x00004000 */ +#define ADC_CCR_MDMA_1 (0x2U << ADC_CCR_MDMA_Pos) /*!< 0x00008000 */ + +#define ADC_CCR_CKMODE_Pos (16U) +#define ADC_CCR_CKMODE_Msk (0x3U << ADC_CCR_CKMODE_Pos) /*!< 0x00030000 */ +#define ADC_CCR_CKMODE ADC_CCR_CKMODE_Msk /*!< ADC common clock source and prescaler (prescaler only for clock source synchronous) */ +#define ADC_CCR_CKMODE_0 (0x1U << ADC_CCR_CKMODE_Pos) /*!< 0x00010000 */ +#define ADC_CCR_CKMODE_1 (0x2U << ADC_CCR_CKMODE_Pos) /*!< 0x00020000 */ + +#define ADC_CCR_PRESC_Pos (18U) +#define ADC_CCR_PRESC_Msk (0xFU << ADC_CCR_PRESC_Pos) /*!< 0x003C0000 */ +#define ADC_CCR_PRESC ADC_CCR_PRESC_Msk /*!< ADC common clock prescaler, only for clock source asynchronous */ +#define ADC_CCR_PRESC_0 (0x1U << ADC_CCR_PRESC_Pos) /*!< 0x00040000 */ +#define ADC_CCR_PRESC_1 (0x2U << ADC_CCR_PRESC_Pos) /*!< 0x00080000 */ +#define ADC_CCR_PRESC_2 (0x4U << ADC_CCR_PRESC_Pos) /*!< 0x00100000 */ +#define ADC_CCR_PRESC_3 (0x8U << ADC_CCR_PRESC_Pos) /*!< 0x00200000 */ + +#define ADC_CCR_VREFEN_Pos (22U) +#define ADC_CCR_VREFEN_Msk (0x1U << ADC_CCR_VREFEN_Pos) /*!< 0x00400000 */ +#define ADC_CCR_VREFEN ADC_CCR_VREFEN_Msk /*!< ADC internal path to VrefInt enable */ +#define ADC_CCR_TSEN_Pos (23U) +#define ADC_CCR_TSEN_Msk (0x1U << ADC_CCR_TSEN_Pos) /*!< 0x00800000 */ +#define ADC_CCR_TSEN ADC_CCR_TSEN_Msk /*!< ADC internal path to temperature sensor enable */ +#define ADC_CCR_VBATEN_Pos (24U) +#define ADC_CCR_VBATEN_Msk (0x1U << ADC_CCR_VBATEN_Pos) /*!< 0x01000000 */ +#define ADC_CCR_VBATEN ADC_CCR_VBATEN_Msk /*!< ADC internal path to battery voltage enable */ + +/******************** Bit definition for ADC_CDR register *******************/ +#define ADC_CDR_RDATA_MST_Pos (0U) +#define ADC_CDR_RDATA_MST_Msk (0xFFFFU << ADC_CDR_RDATA_MST_Pos) /*!< 0x0000FFFF */ +#define ADC_CDR_RDATA_MST ADC_CDR_RDATA_MST_Msk /*!< ADC multimode master group regular conversion data */ +#define ADC_CDR_RDATA_MST_0 (0x0001U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000001 */ +#define ADC_CDR_RDATA_MST_1 (0x0002U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000002 */ +#define ADC_CDR_RDATA_MST_2 (0x0004U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000004 */ +#define ADC_CDR_RDATA_MST_3 (0x0008U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000008 */ +#define ADC_CDR_RDATA_MST_4 (0x0010U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000010 */ +#define ADC_CDR_RDATA_MST_5 (0x0020U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000020 */ +#define ADC_CDR_RDATA_MST_6 (0x0040U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000040 */ +#define ADC_CDR_RDATA_MST_7 (0x0080U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000080 */ +#define ADC_CDR_RDATA_MST_8 (0x0100U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000100 */ +#define ADC_CDR_RDATA_MST_9 (0x0200U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000200 */ +#define ADC_CDR_RDATA_MST_10 (0x0400U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000400 */ +#define ADC_CDR_RDATA_MST_11 (0x0800U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000800 */ +#define ADC_CDR_RDATA_MST_12 (0x1000U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00001000 */ +#define ADC_CDR_RDATA_MST_13 (0x2000U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00002000 */ +#define ADC_CDR_RDATA_MST_14 (0x4000U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00004000 */ +#define ADC_CDR_RDATA_MST_15 (0x8000U << ADC_CDR_RDATA_MST_Pos) /*!< 0x00008000 */ + +#define ADC_CDR_RDATA_SLV_Pos (16U) +#define ADC_CDR_RDATA_SLV_Msk (0xFFFFU << ADC_CDR_RDATA_SLV_Pos) /*!< 0xFFFF0000 */ +#define ADC_CDR_RDATA_SLV ADC_CDR_RDATA_SLV_Msk /*!< ADC multimode slave group regular conversion data */ +#define ADC_CDR_RDATA_SLV_0 (0x0001U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x00010000 */ +#define ADC_CDR_RDATA_SLV_1 (0x0002U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x00020000 */ +#define ADC_CDR_RDATA_SLV_2 (0x0004U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x00040000 */ +#define ADC_CDR_RDATA_SLV_3 (0x0008U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x00080000 */ +#define ADC_CDR_RDATA_SLV_4 (0x0010U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x00100000 */ +#define ADC_CDR_RDATA_SLV_5 (0x0020U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x00200000 */ +#define ADC_CDR_RDATA_SLV_6 (0x0040U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x00400000 */ +#define ADC_CDR_RDATA_SLV_7 (0x0080U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x00800000 */ +#define ADC_CDR_RDATA_SLV_8 (0x0100U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x01000000 */ +#define ADC_CDR_RDATA_SLV_9 (0x0200U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x02000000 */ +#define ADC_CDR_RDATA_SLV_10 (0x0400U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x04000000 */ +#define ADC_CDR_RDATA_SLV_11 (0x0800U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x08000000 */ +#define ADC_CDR_RDATA_SLV_12 (0x1000U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x10000000 */ +#define ADC_CDR_RDATA_SLV_13 (0x2000U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x20000000 */ +#define ADC_CDR_RDATA_SLV_14 (0x4000U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x40000000 */ +#define ADC_CDR_RDATA_SLV_15 (0x8000U << ADC_CDR_RDATA_SLV_Pos) /*!< 0x80000000 */ + +/******************************************************************************/ +/* */ +/* Controller Area Network */ +/* */ +/******************************************************************************/ +/*!*/ +#define DAC_CR_CEN1_Pos (14U) +#define DAC_CR_CEN1_Msk (0x1U << DAC_CR_CEN1_Pos) /*!< 0x00004000 */ +#define DAC_CR_CEN1 DAC_CR_CEN1_Msk /*!*/ + +#define DAC_CR_EN2_Pos (16U) +#define DAC_CR_EN2_Msk (0x1U << DAC_CR_EN2_Pos) /*!< 0x00010000 */ +#define DAC_CR_EN2 DAC_CR_EN2_Msk /*!*/ +#define DAC_CR_CEN2_Pos (30U) +#define DAC_CR_CEN2_Msk (0x1U << DAC_CR_CEN2_Pos) /*!< 0x40000000 */ +#define DAC_CR_CEN2 DAC_CR_CEN2_Msk /*!*/ + +/***************** Bit definition for DAC_SWTRIGR register ******************/ +#define DAC_SWTRIGR_SWTRIG1_Pos (0U) +#define DAC_SWTRIGR_SWTRIG1_Msk (0x1U << DAC_SWTRIGR_SWTRIG1_Pos) /*!< 0x00000001 */ +#define DAC_SWTRIGR_SWTRIG1 DAC_SWTRIGR_SWTRIG1_Msk /*!
    © COPYRIGHT(c) 2017 STMicroelectronics
    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32l4xx + * @{ + */ + +#ifndef __STM32L4xx_H +#define __STM32L4xx_H + +#ifdef __cplusplus + extern "C" { +#endif /* __cplusplus */ + +/** @addtogroup Library_configuration_section + * @{ + */ + +/** + * @brief STM32 Family + */ +#if !defined (STM32L4) +#define STM32L4 +#endif /* STM32L4 */ + +/* Uncomment the line below according to the target STM32L4 device used in your + application + */ + +#if !defined (STM32L431xx) && !defined (STM32L432xx) && !defined (STM32L433xx) && !defined (STM32L442xx) && !defined (STM32L443xx) && \ + !defined (STM32L451xx) && !defined (STM32L452xx) && !defined (STM32L462xx) && \ + !defined (STM32L471xx) && !defined (STM32L475xx) && !defined (STM32L476xx) && !defined (STM32L485xx) && !defined (STM32L486xx) && \ + !defined (STM32L496xx) && !defined (STM32L4A6xx) && \ + !defined (STM32L4R5xx) && !defined (STM32L4R7xx) && !defined (STM32L4R9xx) && !defined (STM32L4S5xx) && !defined (STM32L4S7xx) && !defined (STM32L4S9xx) + /* #define STM32L431xx */ /*!< STM32L431xx Devices */ + /* #define STM32L432xx */ /*!< STM32L432xx Devices */ + /* #define STM32L433xx */ /*!< STM32L433xx Devices */ + /* #define STM32L442xx */ /*!< STM32L442xx Devices */ + /* #define STM32L443xx */ /*!< STM32L443xx Devices */ + /* #define STM32L451xx */ /*!< STM32L451xx Devices */ + /* #define STM32L452xx */ /*!< STM32L452xx Devices */ + /* #define STM32L462xx */ /*!< STM32L462xx Devices */ + /* #define STM32L471xx */ /*!< STM32L471xx Devices */ + /* #define STM32L475xx */ /*!< STM32L475xx Devices */ + /* #define STM32L476xx */ /*!< STM32L476xx Devices */ + /* #define STM32L485xx */ /*!< STM32L485xx Devices */ + /* #define STM32L486xx */ /*!< STM32L486xx Devices */ + /* #define STM32L496xx */ /*!< STM32L496xx Devices */ + /* #define STM32L4A6xx */ /*!< STM32L4A6xx Devices */ + /* #define STM32L4R5xx */ /*!< STM32L4R5xx Devices */ + /* #define STM32L4R7xx */ /*!< STM32L4R7xx Devices */ + /* #define STM32L4R9xx */ /*!< STM32L4R9xx Devices */ + /* #define STM32L4S5xx */ /*!< STM32L4S5xx Devices */ + /* #define STM32L4S7xx */ /*!< STM32L4S7xx Devices */ + /* #define STM32L4S9xx */ /*!< STM32L4S9xx Devices */ +#endif + +/* Tip: To avoid modifying this file each time you need to switch between these + devices, you can define the device in your toolchain compiler preprocessor. + */ +#if !defined (USE_HAL_DRIVER) +/** + * @brief Comment the line below if you will not use the peripherals drivers. + In this case, these drivers will not be included and the application code will + be based on direct access to peripherals registers + */ + /*#define USE_HAL_DRIVER */ +#endif /* USE_HAL_DRIVER */ + +/** + * @brief CMSIS Device version number + */ +#define __STM32L4_CMSIS_VERSION_MAIN (0x01) /*!< [31:24] main version */ +#define __STM32L4_CMSIS_VERSION_SUB1 (0x04) /*!< [23:16] sub1 version */ +#define __STM32L4_CMSIS_VERSION_SUB2 (0x02) /*!< [15:8] sub2 version */ +#define __STM32L4_CMSIS_VERSION_RC (0x00) /*!< [7:0] release candidate */ +#define __STM32L4_CMSIS_VERSION ((__STM32L4_CMSIS_VERSION_MAIN << 24)\ + |(__STM32L4_CMSIS_VERSION_SUB1 << 16)\ + |(__STM32L4_CMSIS_VERSION_SUB2 << 8 )\ + |(__STM32L4_CMSIS_VERSION_RC)) + +/** + * @} + */ + +/** @addtogroup Device_Included + * @{ + */ + +#if defined(STM32L431xx) + #include "stm32l431xx.h" +#elif defined(STM32L432xx) + #include "stm32l432xx.h" +#elif defined(STM32L433xx) + #include "stm32l433xx.h" +#elif defined(STM32L442xx) + #include "stm32l442xx.h" +#elif defined(STM32L443xx) + #include "stm32l443xx.h" +#elif defined(STM32L451xx) + #include "stm32l451xx.h" +#elif defined(STM32L452xx) + #include "stm32l452xx.h" +#elif defined(STM32L462xx) + #include "stm32l462xx.h" +#elif defined(STM32L471xx) + #include "stm32l471xx.h" +#elif defined(STM32L475xx) + #include "stm32l475xx.h" +#elif defined(STM32L476xx) + #include "stm32l476xx.h" +#elif defined(STM32L485xx) + #include "stm32l485xx.h" +#elif defined(STM32L486xx) + #include "stm32l486xx.h" +#elif defined(STM32L496xx) + #include "stm32l496xx.h" +#elif defined(STM32L4A6xx) + #include "stm32l4a6xx.h" +#elif defined(STM32L4R5xx) + #include "stm32l4r5xx.h" +#elif defined(STM32L4R7xx) + #include "stm32l4r7xx.h" +#elif defined(STM32L4R9xx) + #include "stm32l4r9xx.h" +#elif defined(STM32L4S5xx) + #include "stm32l4s5xx.h" +#elif defined(STM32L4S7xx) + #include "stm32l4s7xx.h" +#elif defined(STM32L4S9xx) + #include "stm32l4s9xx.h" +#else + #error "Please select first the target STM32L4xx device used in your application (in stm32l4xx.h file)" +#endif + +/** + * @} + */ + +/** @addtogroup Exported_types + * @{ + */ +typedef enum +{ + RESET = 0, + SET = !RESET +} FlagStatus, ITStatus; + +typedef enum +{ + DISABLE = 0, + ENABLE = !DISABLE +} FunctionalState; +#define IS_FUNCTIONAL_STATE(STATE) (((STATE) == DISABLE) || ((STATE) == ENABLE)) + +typedef enum +{ + ERROR = 0, + SUCCESS = !ERROR +} ErrorStatus; + +/** + * @} + */ + + +/** @addtogroup Exported_macros + * @{ + */ +#define SET_BIT(REG, BIT) ((REG) |= (BIT)) + +#define CLEAR_BIT(REG, BIT) ((REG) &= ~(BIT)) + +#define READ_BIT(REG, BIT) ((REG) & (BIT)) + +#define CLEAR_REG(REG) ((REG) = (0x0)) + +#define WRITE_REG(REG, VAL) ((REG) = (VAL)) + +#define READ_REG(REG) ((REG)) + +#define MODIFY_REG(REG, CLEARMASK, SETMASK) WRITE_REG((REG), (((READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK))) + +#define POSITION_VAL(VAL) (__CLZ(__RBIT(VAL))) + + +/** + * @} + */ + +#if defined (USE_HAL_DRIVER) + #include "stm32l4xx_hal.h" +#endif /* USE_HAL_DRIVER */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __STM32L4xx_H */ +/** + * @} + */ + +/** + * @} + */ + + + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Device/ST/STM32L4xx/Include/system_stm32l4xx.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Device/ST/STM32L4xx/Include/system_stm32l4xx.h new file mode 100644 index 0000000..e6e4376 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Device/ST/STM32L4xx/Include/system_stm32l4xx.h @@ -0,0 +1,123 @@ +/** + ****************************************************************************** + * @file system_stm32l4xx.h + * @author MCD Application Team + * @brief CMSIS Cortex-M4 Device System Source File for STM32L4xx devices. + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32l4xx_system + * @{ + */ + +/** + * @brief Define to prevent recursive inclusion + */ +#ifndef __SYSTEM_STM32L4XX_H +#define __SYSTEM_STM32L4XX_H + +#ifdef __cplusplus + extern "C" { +#endif + +/** @addtogroup STM32L4xx_System_Includes + * @{ + */ + +/** + * @} + */ + + +/** @addtogroup STM32L4xx_System_Exported_Variables + * @{ + */ + /* The SystemCoreClock variable is updated in three ways: + 1) by calling CMSIS function SystemCoreClockUpdate() + 2) by calling HAL API function HAL_RCC_GetSysClockFreq() + 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency + Note: If you use this function to configure the system clock; then there + is no need to call the 2 first functions listed above, since SystemCoreClock + variable is updated automatically. + */ +extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */ + +extern const uint8_t AHBPrescTable[16]; /*!< AHB prescalers table values */ +extern const uint8_t APBPrescTable[8]; /*!< APB prescalers table values */ +extern const uint32_t MSIRangeTable[12]; /*!< MSI ranges table values */ + +/** + * @} + */ + +/** @addtogroup STM32L4xx_System_Exported_Constants + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32L4xx_System_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32L4xx_System_Exported_Functions + * @{ + */ + +extern void SystemInit(void); +extern void SystemCoreClockUpdate(void); +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /*__SYSTEM_STM32L4XX_H */ + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/arm_common_tables.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/arm_common_tables.h new file mode 100644 index 0000000..8742a56 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/arm_common_tables.h @@ -0,0 +1,136 @@ +/* ---------------------------------------------------------------------- +* Copyright (C) 2010-2014 ARM Limited. All rights reserved. +* +* $Date: 19. October 2015 +* $Revision: V.1.4.5 a +* +* Project: CMSIS DSP Library +* Title: arm_common_tables.h +* +* Description: This file has extern declaration for common tables like Bitreverse, reciprocal etc which are used across different functions +* +* Target Processor: Cortex-M4/Cortex-M3 +* +* 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 LIMITED nor the names of its 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 _ARM_COMMON_TABLES_H +#define _ARM_COMMON_TABLES_H + +#include "arm_math.h" + +extern const uint16_t armBitRevTable[1024]; +extern const q15_t armRecipTableQ15[64]; +extern const q31_t armRecipTableQ31[64]; +/* extern const q31_t realCoefAQ31[1024]; */ +/* extern const q31_t realCoefBQ31[1024]; */ +extern const float32_t twiddleCoef_16[32]; +extern const float32_t twiddleCoef_32[64]; +extern const float32_t twiddleCoef_64[128]; +extern const float32_t twiddleCoef_128[256]; +extern const float32_t twiddleCoef_256[512]; +extern const float32_t twiddleCoef_512[1024]; +extern const float32_t twiddleCoef_1024[2048]; +extern const float32_t twiddleCoef_2048[4096]; +extern const float32_t twiddleCoef_4096[8192]; +#define twiddleCoef twiddleCoef_4096 +extern const q31_t twiddleCoef_16_q31[24]; +extern const q31_t twiddleCoef_32_q31[48]; +extern const q31_t twiddleCoef_64_q31[96]; +extern const q31_t twiddleCoef_128_q31[192]; +extern const q31_t twiddleCoef_256_q31[384]; +extern const q31_t twiddleCoef_512_q31[768]; +extern const q31_t twiddleCoef_1024_q31[1536]; +extern const q31_t twiddleCoef_2048_q31[3072]; +extern const q31_t twiddleCoef_4096_q31[6144]; +extern const q15_t twiddleCoef_16_q15[24]; +extern const q15_t twiddleCoef_32_q15[48]; +extern const q15_t twiddleCoef_64_q15[96]; +extern const q15_t twiddleCoef_128_q15[192]; +extern const q15_t twiddleCoef_256_q15[384]; +extern const q15_t twiddleCoef_512_q15[768]; +extern const q15_t twiddleCoef_1024_q15[1536]; +extern const q15_t twiddleCoef_2048_q15[3072]; +extern const q15_t twiddleCoef_4096_q15[6144]; +extern const float32_t twiddleCoef_rfft_32[32]; +extern const float32_t twiddleCoef_rfft_64[64]; +extern const float32_t twiddleCoef_rfft_128[128]; +extern const float32_t twiddleCoef_rfft_256[256]; +extern const float32_t twiddleCoef_rfft_512[512]; +extern const float32_t twiddleCoef_rfft_1024[1024]; +extern const float32_t twiddleCoef_rfft_2048[2048]; +extern const float32_t twiddleCoef_rfft_4096[4096]; + + +/* floating-point bit reversal tables */ +#define ARMBITREVINDEXTABLE__16_TABLE_LENGTH ((uint16_t)20 ) +#define ARMBITREVINDEXTABLE__32_TABLE_LENGTH ((uint16_t)48 ) +#define ARMBITREVINDEXTABLE__64_TABLE_LENGTH ((uint16_t)56 ) +#define ARMBITREVINDEXTABLE_128_TABLE_LENGTH ((uint16_t)208 ) +#define ARMBITREVINDEXTABLE_256_TABLE_LENGTH ((uint16_t)440 ) +#define ARMBITREVINDEXTABLE_512_TABLE_LENGTH ((uint16_t)448 ) +#define ARMBITREVINDEXTABLE1024_TABLE_LENGTH ((uint16_t)1800) +#define ARMBITREVINDEXTABLE2048_TABLE_LENGTH ((uint16_t)3808) +#define ARMBITREVINDEXTABLE4096_TABLE_LENGTH ((uint16_t)4032) + +extern const uint16_t armBitRevIndexTable16[ARMBITREVINDEXTABLE__16_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable32[ARMBITREVINDEXTABLE__32_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable64[ARMBITREVINDEXTABLE__64_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable128[ARMBITREVINDEXTABLE_128_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable256[ARMBITREVINDEXTABLE_256_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable512[ARMBITREVINDEXTABLE_512_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable1024[ARMBITREVINDEXTABLE1024_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable2048[ARMBITREVINDEXTABLE2048_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable4096[ARMBITREVINDEXTABLE4096_TABLE_LENGTH]; + +/* fixed-point bit reversal tables */ +#define ARMBITREVINDEXTABLE_FIXED___16_TABLE_LENGTH ((uint16_t)12 ) +#define ARMBITREVINDEXTABLE_FIXED___32_TABLE_LENGTH ((uint16_t)24 ) +#define ARMBITREVINDEXTABLE_FIXED___64_TABLE_LENGTH ((uint16_t)56 ) +#define ARMBITREVINDEXTABLE_FIXED__128_TABLE_LENGTH ((uint16_t)112 ) +#define ARMBITREVINDEXTABLE_FIXED__256_TABLE_LENGTH ((uint16_t)240 ) +#define ARMBITREVINDEXTABLE_FIXED__512_TABLE_LENGTH ((uint16_t)480 ) +#define ARMBITREVINDEXTABLE_FIXED_1024_TABLE_LENGTH ((uint16_t)992 ) +#define ARMBITREVINDEXTABLE_FIXED_2048_TABLE_LENGTH ((uint16_t)1984) +#define ARMBITREVINDEXTABLE_FIXED_4096_TABLE_LENGTH ((uint16_t)4032) + +extern const uint16_t armBitRevIndexTable_fixed_16[ARMBITREVINDEXTABLE_FIXED___16_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable_fixed_32[ARMBITREVINDEXTABLE_FIXED___32_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable_fixed_64[ARMBITREVINDEXTABLE_FIXED___64_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable_fixed_128[ARMBITREVINDEXTABLE_FIXED__128_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable_fixed_256[ARMBITREVINDEXTABLE_FIXED__256_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable_fixed_512[ARMBITREVINDEXTABLE_FIXED__512_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable_fixed_1024[ARMBITREVINDEXTABLE_FIXED_1024_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable_fixed_2048[ARMBITREVINDEXTABLE_FIXED_2048_TABLE_LENGTH]; +extern const uint16_t armBitRevIndexTable_fixed_4096[ARMBITREVINDEXTABLE_FIXED_4096_TABLE_LENGTH]; + +/* Tables for Fast Math Sine and Cosine */ +extern const float32_t sinTable_f32[FAST_MATH_TABLE_SIZE + 1]; +extern const q31_t sinTable_q31[FAST_MATH_TABLE_SIZE + 1]; +extern const q15_t sinTable_q15[FAST_MATH_TABLE_SIZE + 1]; + +#endif /* ARM_COMMON_TABLES_H */ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/arm_const_structs.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/arm_const_structs.h new file mode 100644 index 0000000..726d06e --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/arm_const_structs.h @@ -0,0 +1,79 @@ +/* ---------------------------------------------------------------------- +* Copyright (C) 2010-2014 ARM Limited. All rights reserved. +* +* $Date: 19. March 2015 +* $Revision: V.1.4.5 +* +* Project: CMSIS DSP Library +* Title: arm_const_structs.h +* +* Description: This file has constant structs that are initialized for +* user convenience. For example, some can be given as +* arguments to the arm_cfft_f32() function. +* +* Target Processor: Cortex-M4/Cortex-M3 +* +* 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 LIMITED nor the names of its 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 _ARM_CONST_STRUCTS_H +#define _ARM_CONST_STRUCTS_H + +#include "arm_math.h" +#include "arm_common_tables.h" + + extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len16; + extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len32; + extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len64; + extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len128; + extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len256; + extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len512; + extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len1024; + extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len2048; + extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len4096; + + extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len16; + extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len32; + extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len64; + extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len128; + extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len256; + extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len512; + extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len1024; + extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len2048; + extern const arm_cfft_instance_q31 arm_cfft_sR_q31_len4096; + + extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len16; + extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len32; + extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len64; + extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len128; + extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len256; + extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len512; + extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len1024; + extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len2048; + extern const arm_cfft_instance_q15 arm_cfft_sR_q15_len4096; + +#endif diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/arm_math.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/arm_math.h new file mode 100644 index 0000000..d33f8a9 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/arm_math.h @@ -0,0 +1,7154 @@ +/* ---------------------------------------------------------------------- +* Copyright (C) 2010-2015 ARM Limited. All rights reserved. +* +* $Date: 20. October 2015 +* $Revision: V1.4.5 b +* +* Project: CMSIS DSP Library +* Title: arm_math.h +* +* Description: Public header file for CMSIS DSP Library +* +* Target Processor: Cortex-M7/Cortex-M4/Cortex-M3/Cortex-M0 +* +* 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 LIMITED nor the names of its 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. + * -------------------------------------------------------------------- */ + +/** + \mainpage CMSIS DSP Software Library + * + * Introduction + * ------------ + * + * This user manual describes the CMSIS DSP software library, + * a suite of common signal processing functions for use on Cortex-M processor based devices. + * + * The library is divided into a number of functions each covering a specific category: + * - Basic math functions + * - Fast math functions + * - Complex math functions + * - Filters + * - Matrix functions + * - Transforms + * - Motor control functions + * - Statistical functions + * - Support functions + * - Interpolation functions + * + * The library has separate functions for operating on 8-bit integers, 16-bit integers, + * 32-bit integer and 32-bit floating-point values. + * + * Using the Library + * ------------ + * + * The library installer contains prebuilt versions of the libraries in the Lib folder. + * - arm_cortexM7lfdp_math.lib (Little endian and Double Precision Floating Point Unit on Cortex-M7) + * - arm_cortexM7bfdp_math.lib (Big endian and Double Precision Floating Point Unit on Cortex-M7) + * - arm_cortexM7lfsp_math.lib (Little endian and Single Precision Floating Point Unit on Cortex-M7) + * - arm_cortexM7bfsp_math.lib (Big endian and Single Precision Floating Point Unit on Cortex-M7) + * - arm_cortexM7l_math.lib (Little endian on Cortex-M7) + * - arm_cortexM7b_math.lib (Big endian on Cortex-M7) + * - arm_cortexM4lf_math.lib (Little endian and Floating Point Unit on Cortex-M4) + * - arm_cortexM4bf_math.lib (Big endian and Floating Point Unit on Cortex-M4) + * - arm_cortexM4l_math.lib (Little endian on Cortex-M4) + * - arm_cortexM4b_math.lib (Big endian on Cortex-M4) + * - arm_cortexM3l_math.lib (Little endian on Cortex-M3) + * - arm_cortexM3b_math.lib (Big endian on Cortex-M3) + * - arm_cortexM0l_math.lib (Little endian on Cortex-M0 / CortexM0+) + * - arm_cortexM0b_math.lib (Big endian on Cortex-M0 / CortexM0+) + * + * The library functions are declared in the public file arm_math.h which is placed in the Include folder. + * Simply include this file and link the appropriate library in the application and begin calling the library functions. The Library supports single + * public header file arm_math.h for Cortex-M7/M4/M3/M0/M0+ with little endian and big endian. Same header file will be used for floating point unit(FPU) variants. + * Define the appropriate pre processor MACRO ARM_MATH_CM7 or ARM_MATH_CM4 or ARM_MATH_CM3 or + * ARM_MATH_CM0 or ARM_MATH_CM0PLUS depending on the target processor in the application. + * + * Examples + * -------- + * + * The library ships with a number of examples which demonstrate how to use the library functions. + * + * Toolchain Support + * ------------ + * + * The library has been developed and tested with MDK-ARM version 5.14.0.0 + * The library is being tested in GCC and IAR toolchains and updates on this activity will be made available shortly. + * + * Building the Library + * ------------ + * + * The library installer contains a project file to re build libraries on MDK-ARM Tool chain in the CMSIS\\DSP_Lib\\Source\\ARM folder. + * - arm_cortexM_math.uvprojx + * + * + * The libraries can be built by opening the arm_cortexM_math.uvprojx project in MDK-ARM, selecting a specific target, and defining the optional pre processor MACROs detailed above. + * + * Pre-processor Macros + * ------------ + * + * Each library project have differant pre-processor macros. + * + * - UNALIGNED_SUPPORT_DISABLE: + * + * Define macro UNALIGNED_SUPPORT_DISABLE, If the silicon does not support unaligned memory access + * + * - ARM_MATH_BIG_ENDIAN: + * + * Define macro ARM_MATH_BIG_ENDIAN to build the library for big endian targets. By default library builds for little endian targets. + * + * - ARM_MATH_MATRIX_CHECK: + * + * Define macro ARM_MATH_MATRIX_CHECK for checking on the input and output sizes of matrices + * + * - ARM_MATH_ROUNDING: + * + * Define macro ARM_MATH_ROUNDING for rounding on support functions + * + * - ARM_MATH_CMx: + * + * Define macro ARM_MATH_CM4 for building the library on Cortex-M4 target, ARM_MATH_CM3 for building library on Cortex-M3 target + * and ARM_MATH_CM0 for building library on Cortex-M0 target, ARM_MATH_CM0PLUS for building library on Cortex-M0+ target, and + * ARM_MATH_CM7 for building the library on cortex-M7. + * + * - __FPU_PRESENT: + * + * Initialize macro __FPU_PRESENT = 1 when building on FPU supported Targets. Enable this macro for M4bf and M4lf libraries + * + *
    + * CMSIS-DSP in ARM::CMSIS Pack + * ----------------------------- + * + * The following files relevant to CMSIS-DSP are present in the ARM::CMSIS Pack directories: + * |File/Folder |Content | + * |------------------------------|------------------------------------------------------------------------| + * |\b CMSIS\\Documentation\\DSP | This documentation | + * |\b CMSIS\\DSP_Lib | Software license agreement (license.txt) | + * |\b CMSIS\\DSP_Lib\\Examples | Example projects demonstrating the usage of the library functions | + * |\b CMSIS\\DSP_Lib\\Source | Source files for rebuilding the library | + * + *
    + * Revision History of CMSIS-DSP + * ------------ + * Please refer to \ref ChangeLog_pg. + * + * Copyright Notice + * ------------ + * + * Copyright (C) 2010-2015 ARM Limited. All rights reserved. + */ + + +/** + * @defgroup groupMath Basic Math Functions + */ + +/** + * @defgroup groupFastMath Fast Math Functions + * This set of functions provides a fast approximation to sine, cosine, and square root. + * As compared to most of the other functions in the CMSIS math library, the fast math functions + * operate on individual values and not arrays. + * There are separate functions for Q15, Q31, and floating-point data. + * + */ + +/** + * @defgroup groupCmplxMath Complex Math Functions + * This set of functions operates on complex data vectors. + * The data in the complex arrays is stored in an interleaved fashion + * (real, imag, real, imag, ...). + * In the API functions, the number of samples in a complex array refers + * to the number of complex values; the array contains twice this number of + * real values. + */ + +/** + * @defgroup groupFilters Filtering Functions + */ + +/** + * @defgroup groupMatrix Matrix Functions + * + * This set of functions provides basic matrix math operations. + * The functions operate on matrix data structures. For example, + * the type + * definition for the floating-point matrix structure is shown + * below: + *
    + *     typedef struct
    + *     {
    + *       uint16_t numRows;     // number of rows of the matrix.
    + *       uint16_t numCols;     // number of columns of the matrix.
    + *       float32_t *pData;     // points to the data of the matrix.
    + *     } arm_matrix_instance_f32;
    + * 
    + * There are similar definitions for Q15 and Q31 data types. + * + * The structure specifies the size of the matrix and then points to + * an array of data. The array is of size numRows X numCols + * and the values are arranged in row order. That is, the + * matrix element (i, j) is stored at: + *
    + *     pData[i*numCols + j]
    + * 
    + * + * \par Init Functions + * There is an associated initialization function for each type of matrix + * data structure. + * The initialization function sets the values of the internal structure fields. + * Refer to the function arm_mat_init_f32(), arm_mat_init_q31() + * and arm_mat_init_q15() for floating-point, Q31 and Q15 types, respectively. + * + * \par + * Use of the initialization function is optional. However, if initialization function is used + * then the instance structure cannot be placed into a const data section. + * To place the instance structure in a const data + * section, manually initialize the data structure. For example: + *
    + * arm_matrix_instance_f32 S = {nRows, nColumns, pData};
    + * arm_matrix_instance_q31 S = {nRows, nColumns, pData};
    + * arm_matrix_instance_q15 S = {nRows, nColumns, pData};
    + * 
    + * where nRows specifies the number of rows, nColumns + * specifies the number of columns, and pData points to the + * data array. + * + * \par Size Checking + * By default all of the matrix functions perform size checking on the input and + * output matrices. For example, the matrix addition function verifies that the + * two input matrices and the output matrix all have the same number of rows and + * columns. If the size check fails the functions return: + *
    + *     ARM_MATH_SIZE_MISMATCH
    + * 
    + * Otherwise the functions return + *
    + *     ARM_MATH_SUCCESS
    + * 
    + * There is some overhead associated with this matrix size checking. + * The matrix size checking is enabled via the \#define + *
    + *     ARM_MATH_MATRIX_CHECK
    + * 
    + * within the library project settings. By default this macro is defined + * and size checking is enabled. By changing the project settings and + * undefining this macro size checking is eliminated and the functions + * run a bit faster. With size checking disabled the functions always + * return ARM_MATH_SUCCESS. + */ + +/** + * @defgroup groupTransforms Transform Functions + */ + +/** + * @defgroup groupController Controller Functions + */ + +/** + * @defgroup groupStats Statistics Functions + */ +/** + * @defgroup groupSupport Support Functions + */ + +/** + * @defgroup groupInterpolation Interpolation Functions + * These functions perform 1- and 2-dimensional interpolation of data. + * Linear interpolation is used for 1-dimensional data and + * bilinear interpolation is used for 2-dimensional data. + */ + +/** + * @defgroup groupExamples Examples + */ +#ifndef _ARM_MATH_H +#define _ARM_MATH_H + +/* ignore some GCC warnings */ +#if defined ( __GNUC__ ) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-conversion" +#pragma GCC diagnostic ignored "-Wconversion" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +#define __CMSIS_GENERIC /* disable NVIC and Systick functions */ + +#if defined(ARM_MATH_CM7) + #include "core_cm7.h" +#elif defined (ARM_MATH_CM4) + #include "core_cm4.h" +#elif defined (ARM_MATH_CM3) + #include "core_cm3.h" +#elif defined (ARM_MATH_CM0) + #include "core_cm0.h" + #define ARM_MATH_CM0_FAMILY +#elif defined (ARM_MATH_CM0PLUS) + #include "core_cm0plus.h" + #define ARM_MATH_CM0_FAMILY +#else + #error "Define according the used Cortex core ARM_MATH_CM7, ARM_MATH_CM4, ARM_MATH_CM3, ARM_MATH_CM0PLUS or ARM_MATH_CM0" +#endif + +#undef __CMSIS_GENERIC /* enable NVIC and Systick functions */ +#include "string.h" +#include "math.h" +#ifdef __cplusplus +extern "C" +{ +#endif + + + /** + * @brief Macros required for reciprocal calculation in Normalized LMS + */ + +#define DELTA_Q31 (0x100) +#define DELTA_Q15 0x5 +#define INDEX_MASK 0x0000003F +#ifndef PI +#define PI 3.14159265358979f +#endif + + /** + * @brief Macros required for SINE and COSINE Fast math approximations + */ + +#define FAST_MATH_TABLE_SIZE 512 +#define FAST_MATH_Q31_SHIFT (32 - 10) +#define FAST_MATH_Q15_SHIFT (16 - 10) +#define CONTROLLER_Q31_SHIFT (32 - 9) +#define TABLE_SIZE 256 +#define TABLE_SPACING_Q31 0x400000 +#define TABLE_SPACING_Q15 0x80 + + /** + * @brief Macros required for SINE and COSINE Controller functions + */ + /* 1.31(q31) Fixed value of 2/360 */ + /* -1 to +1 is divided into 360 values so total spacing is (2/360) */ +#define INPUT_SPACING 0xB60B61 + + /** + * @brief Macro for Unaligned Support + */ +#ifndef UNALIGNED_SUPPORT_DISABLE + #define ALIGN4 +#else + #if defined (__GNUC__) + #define ALIGN4 __attribute__((aligned(4))) + #else + #define ALIGN4 __align(4) + #endif +#endif /* #ifndef UNALIGNED_SUPPORT_DISABLE */ + + /** + * @brief Error status returned by some functions in the library. + */ + + typedef enum + { + ARM_MATH_SUCCESS = 0, /**< No error */ + ARM_MATH_ARGUMENT_ERROR = -1, /**< One or more arguments are incorrect */ + ARM_MATH_LENGTH_ERROR = -2, /**< Length of data buffer is incorrect */ + ARM_MATH_SIZE_MISMATCH = -3, /**< Size of matrices is not compatible with the operation. */ + ARM_MATH_NANINF = -4, /**< Not-a-number (NaN) or infinity is generated */ + ARM_MATH_SINGULAR = -5, /**< Generated by matrix inversion if the input matrix is singular and cannot be inverted. */ + ARM_MATH_TEST_FAILURE = -6 /**< Test Failed */ + } arm_status; + + /** + * @brief 8-bit fractional data type in 1.7 format. + */ + typedef int8_t q7_t; + + /** + * @brief 16-bit fractional data type in 1.15 format. + */ + typedef int16_t q15_t; + + /** + * @brief 32-bit fractional data type in 1.31 format. + */ + typedef int32_t q31_t; + + /** + * @brief 64-bit fractional data type in 1.63 format. + */ + typedef int64_t q63_t; + + /** + * @brief 32-bit floating-point type definition. + */ + typedef float float32_t; + + /** + * @brief 64-bit floating-point type definition. + */ + typedef double float64_t; + + /** + * @brief definition to read/write two 16 bit values. + */ +#if defined __CC_ARM + #define __SIMD32_TYPE int32_t __packed + #define CMSIS_UNUSED __attribute__((unused)) + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #define __SIMD32_TYPE int32_t + #define CMSIS_UNUSED __attribute__((unused)) + +#elif defined __GNUC__ + #define __SIMD32_TYPE int32_t + #define CMSIS_UNUSED __attribute__((unused)) + +#elif defined __ICCARM__ + #define __SIMD32_TYPE int32_t __packed + #define CMSIS_UNUSED + +#elif defined __CSMC__ + #define __SIMD32_TYPE int32_t + #define CMSIS_UNUSED + +#elif defined __TASKING__ + #define __SIMD32_TYPE __unaligned int32_t + #define CMSIS_UNUSED + +#else + #error Unknown compiler +#endif + +#define __SIMD32(addr) (*(__SIMD32_TYPE **) & (addr)) +#define __SIMD32_CONST(addr) ((__SIMD32_TYPE *)(addr)) +#define _SIMD32_OFFSET(addr) (*(__SIMD32_TYPE *) (addr)) +#define __SIMD64(addr) (*(int64_t **) & (addr)) + +#if defined (ARM_MATH_CM3) || defined (ARM_MATH_CM0_FAMILY) + /** + * @brief definition to pack two 16 bit values. + */ +#define __PKHBT(ARG1, ARG2, ARG3) ( (((int32_t)(ARG1) << 0) & (int32_t)0x0000FFFF) | \ + (((int32_t)(ARG2) << ARG3) & (int32_t)0xFFFF0000) ) +#define __PKHTB(ARG1, ARG2, ARG3) ( (((int32_t)(ARG1) << 0) & (int32_t)0xFFFF0000) | \ + (((int32_t)(ARG2) >> ARG3) & (int32_t)0x0000FFFF) ) + +#endif + + + /** + * @brief definition to pack four 8 bit values. + */ +#ifndef ARM_MATH_BIG_ENDIAN + +#define __PACKq7(v0,v1,v2,v3) ( (((int32_t)(v0) << 0) & (int32_t)0x000000FF) | \ + (((int32_t)(v1) << 8) & (int32_t)0x0000FF00) | \ + (((int32_t)(v2) << 16) & (int32_t)0x00FF0000) | \ + (((int32_t)(v3) << 24) & (int32_t)0xFF000000) ) +#else + +#define __PACKq7(v0,v1,v2,v3) ( (((int32_t)(v3) << 0) & (int32_t)0x000000FF) | \ + (((int32_t)(v2) << 8) & (int32_t)0x0000FF00) | \ + (((int32_t)(v1) << 16) & (int32_t)0x00FF0000) | \ + (((int32_t)(v0) << 24) & (int32_t)0xFF000000) ) + +#endif + + + /** + * @brief Clips Q63 to Q31 values. + */ + static __INLINE q31_t clip_q63_to_q31( + q63_t x) + { + return ((q31_t) (x >> 32) != ((q31_t) x >> 31)) ? + ((0x7FFFFFFF ^ ((q31_t) (x >> 63)))) : (q31_t) x; + } + + /** + * @brief Clips Q63 to Q15 values. + */ + static __INLINE q15_t clip_q63_to_q15( + q63_t x) + { + return ((q31_t) (x >> 32) != ((q31_t) x >> 31)) ? + ((0x7FFF ^ ((q15_t) (x >> 63)))) : (q15_t) (x >> 15); + } + + /** + * @brief Clips Q31 to Q7 values. + */ + static __INLINE q7_t clip_q31_to_q7( + q31_t x) + { + return ((q31_t) (x >> 24) != ((q31_t) x >> 23)) ? + ((0x7F ^ ((q7_t) (x >> 31)))) : (q7_t) x; + } + + /** + * @brief Clips Q31 to Q15 values. + */ + static __INLINE q15_t clip_q31_to_q15( + q31_t x) + { + return ((q31_t) (x >> 16) != ((q31_t) x >> 15)) ? + ((0x7FFF ^ ((q15_t) (x >> 31)))) : (q15_t) x; + } + + /** + * @brief Multiplies 32 X 64 and returns 32 bit result in 2.30 format. + */ + + static __INLINE q63_t mult32x64( + q63_t x, + q31_t y) + { + return ((((q63_t) (x & 0x00000000FFFFFFFF) * y) >> 32) + + (((q63_t) (x >> 32) * y))); + } + +/* + #if defined (ARM_MATH_CM0_FAMILY) && defined ( __CC_ARM ) + #define __CLZ __clz + #endif + */ +/* note: function can be removed when all toolchain support __CLZ for Cortex-M0 */ +#if defined (ARM_MATH_CM0_FAMILY) && ((defined (__ICCARM__)) ) + static __INLINE uint32_t __CLZ( + q31_t data); + + static __INLINE uint32_t __CLZ( + q31_t data) + { + uint32_t count = 0; + uint32_t mask = 0x80000000; + + while((data & mask) == 0) + { + count += 1u; + mask = mask >> 1u; + } + + return (count); + } +#endif + + /** + * @brief Function to Calculates 1/in (reciprocal) value of Q31 Data type. + */ + + static __INLINE uint32_t arm_recip_q31( + q31_t in, + q31_t * dst, + q31_t * pRecipTable) + { + q31_t out; + uint32_t tempVal; + uint32_t index, i; + uint32_t signBits; + + if(in > 0) + { + signBits = ((uint32_t) (__CLZ( in) - 1)); + } + else + { + signBits = ((uint32_t) (__CLZ(-in) - 1)); + } + + /* Convert input sample to 1.31 format */ + in = (in << signBits); + + /* calculation of index for initial approximated Val */ + index = (uint32_t)(in >> 24); + index = (index & INDEX_MASK); + + /* 1.31 with exp 1 */ + out = pRecipTable[index]; + + /* calculation of reciprocal value */ + /* running approximation for two iterations */ + for (i = 0u; i < 2u; i++) + { + tempVal = (uint32_t) (((q63_t) in * out) >> 31); + tempVal = 0x7FFFFFFFu - tempVal; + /* 1.31 with exp 1 */ + /* out = (q31_t) (((q63_t) out * tempVal) >> 30); */ + out = clip_q63_to_q31(((q63_t) out * tempVal) >> 30); + } + + /* write output */ + *dst = out; + + /* return num of signbits of out = 1/in value */ + return (signBits + 1u); + } + + + /** + * @brief Function to Calculates 1/in (reciprocal) value of Q15 Data type. + */ + static __INLINE uint32_t arm_recip_q15( + q15_t in, + q15_t * dst, + q15_t * pRecipTable) + { + q15_t out = 0; + uint32_t tempVal = 0; + uint32_t index = 0, i = 0; + uint32_t signBits = 0; + + if(in > 0) + { + signBits = ((uint32_t)(__CLZ( in) - 17)); + } + else + { + signBits = ((uint32_t)(__CLZ(-in) - 17)); + } + + /* Convert input sample to 1.15 format */ + in = (in << signBits); + + /* calculation of index for initial approximated Val */ + index = (uint32_t)(in >> 8); + index = (index & INDEX_MASK); + + /* 1.15 with exp 1 */ + out = pRecipTable[index]; + + /* calculation of reciprocal value */ + /* running approximation for two iterations */ + for (i = 0u; i < 2u; i++) + { + tempVal = (uint32_t) (((q31_t) in * out) >> 15); + tempVal = 0x7FFFu - tempVal; + /* 1.15 with exp 1 */ + out = (q15_t) (((q31_t) out * tempVal) >> 14); + /* out = clip_q31_to_q15(((q31_t) out * tempVal) >> 14); */ + } + + /* write output */ + *dst = out; + + /* return num of signbits of out = 1/in value */ + return (signBits + 1); + } + + + /* + * @brief C custom defined intrinisic function for only M0 processors + */ +#if defined(ARM_MATH_CM0_FAMILY) + static __INLINE q31_t __SSAT( + q31_t x, + uint32_t y) + { + int32_t posMax, negMin; + uint32_t i; + + posMax = 1; + for (i = 0; i < (y - 1); i++) + { + posMax = posMax * 2; + } + + if(x > 0) + { + posMax = (posMax - 1); + + if(x > posMax) + { + x = posMax; + } + } + else + { + negMin = -posMax; + + if(x < negMin) + { + x = negMin; + } + } + return (x); + } +#endif /* end of ARM_MATH_CM0_FAMILY */ + + + /* + * @brief C custom defined intrinsic function for M3 and M0 processors + */ +#if defined (ARM_MATH_CM3) || defined (ARM_MATH_CM0_FAMILY) + + /* + * @brief C custom defined QADD8 for M3 and M0 processors + */ + static __INLINE uint32_t __QADD8( + uint32_t x, + uint32_t y) + { + q31_t r, s, t, u; + + r = __SSAT(((((q31_t)x << 24) >> 24) + (((q31_t)y << 24) >> 24)), 8) & (int32_t)0x000000FF; + s = __SSAT(((((q31_t)x << 16) >> 24) + (((q31_t)y << 16) >> 24)), 8) & (int32_t)0x000000FF; + t = __SSAT(((((q31_t)x << 8) >> 24) + (((q31_t)y << 8) >> 24)), 8) & (int32_t)0x000000FF; + u = __SSAT(((((q31_t)x ) >> 24) + (((q31_t)y ) >> 24)), 8) & (int32_t)0x000000FF; + + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r ))); + } + + + /* + * @brief C custom defined QSUB8 for M3 and M0 processors + */ + static __INLINE uint32_t __QSUB8( + uint32_t x, + uint32_t y) + { + q31_t r, s, t, u; + + r = __SSAT(((((q31_t)x << 24) >> 24) - (((q31_t)y << 24) >> 24)), 8) & (int32_t)0x000000FF; + s = __SSAT(((((q31_t)x << 16) >> 24) - (((q31_t)y << 16) >> 24)), 8) & (int32_t)0x000000FF; + t = __SSAT(((((q31_t)x << 8) >> 24) - (((q31_t)y << 8) >> 24)), 8) & (int32_t)0x000000FF; + u = __SSAT(((((q31_t)x ) >> 24) - (((q31_t)y ) >> 24)), 8) & (int32_t)0x000000FF; + + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r ))); + } + + + /* + * @brief C custom defined QADD16 for M3 and M0 processors + */ + static __INLINE uint32_t __QADD16( + uint32_t x, + uint32_t y) + { +/* q31_t r, s; without initialisation 'arm_offset_q15 test' fails but 'intrinsic' tests pass! for armCC */ + q31_t r = 0, s = 0; + + r = __SSAT(((((q31_t)x << 16) >> 16) + (((q31_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((q31_t)x ) >> 16) + (((q31_t)y ) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined SHADD16 for M3 and M0 processors + */ + static __INLINE uint32_t __SHADD16( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = (((((q31_t)x << 16) >> 16) + (((q31_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((q31_t)x ) >> 16) + (((q31_t)y ) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined QSUB16 for M3 and M0 processors + */ + static __INLINE uint32_t __QSUB16( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = __SSAT(((((q31_t)x << 16) >> 16) - (((q31_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((q31_t)x ) >> 16) - (((q31_t)y ) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined SHSUB16 for M3 and M0 processors + */ + static __INLINE uint32_t __SHSUB16( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = (((((q31_t)x << 16) >> 16) - (((q31_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((q31_t)x ) >> 16) - (((q31_t)y ) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined QASX for M3 and M0 processors + */ + static __INLINE uint32_t __QASX( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = __SSAT(((((q31_t)x << 16) >> 16) - (((q31_t)y ) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((q31_t)x ) >> 16) + (((q31_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined SHASX for M3 and M0 processors + */ + static __INLINE uint32_t __SHASX( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = (((((q31_t)x << 16) >> 16) - (((q31_t)y ) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((q31_t)x ) >> 16) + (((q31_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined QSAX for M3 and M0 processors + */ + static __INLINE uint32_t __QSAX( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = __SSAT(((((q31_t)x << 16) >> 16) + (((q31_t)y ) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((q31_t)x ) >> 16) - (((q31_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined SHSAX for M3 and M0 processors + */ + static __INLINE uint32_t __SHSAX( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = (((((q31_t)x << 16) >> 16) + (((q31_t)y ) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((q31_t)x ) >> 16) - (((q31_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined SMUSDX for M3 and M0 processors + */ + static __INLINE uint32_t __SMUSDX( + uint32_t x, + uint32_t y) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) - + ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) )); + } + + /* + * @brief C custom defined SMUADX for M3 and M0 processors + */ + static __INLINE uint32_t __SMUADX( + uint32_t x, + uint32_t y) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) )); + } + + + /* + * @brief C custom defined QADD for M3 and M0 processors + */ + static __INLINE int32_t __QADD( + int32_t x, + int32_t y) + { + return ((int32_t)(clip_q63_to_q31((q63_t)x + (q31_t)y))); + } + + + /* + * @brief C custom defined QSUB for M3 and M0 processors + */ + static __INLINE int32_t __QSUB( + int32_t x, + int32_t y) + { + return ((int32_t)(clip_q63_to_q31((q63_t)x - (q31_t)y))); + } + + + /* + * @brief C custom defined SMLAD for M3 and M0 processors + */ + static __INLINE uint32_t __SMLAD( + uint32_t x, + uint32_t y, + uint32_t sum) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y << 16) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y ) >> 16)) + + ( ((q31_t)sum ) ) )); + } + + + /* + * @brief C custom defined SMLADX for M3 and M0 processors + */ + static __INLINE uint32_t __SMLADX( + uint32_t x, + uint32_t y, + uint32_t sum) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) + + ( ((q31_t)sum ) ) )); + } + + + /* + * @brief C custom defined SMLSDX for M3 and M0 processors + */ + static __INLINE uint32_t __SMLSDX( + uint32_t x, + uint32_t y, + uint32_t sum) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) - + ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) + + ( ((q31_t)sum ) ) )); + } + + + /* + * @brief C custom defined SMLALD for M3 and M0 processors + */ + static __INLINE uint64_t __SMLALD( + uint32_t x, + uint32_t y, + uint64_t sum) + { +/* return (sum + ((q15_t) (x >> 16) * (q15_t) (y >> 16)) + ((q15_t) x * (q15_t) y)); */ + return ((uint64_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y << 16) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y ) >> 16)) + + ( ((q63_t)sum ) ) )); + } + + + /* + * @brief C custom defined SMLALDX for M3 and M0 processors + */ + static __INLINE uint64_t __SMLALDX( + uint32_t x, + uint32_t y, + uint64_t sum) + { +/* return (sum + ((q15_t) (x >> 16) * (q15_t) y)) + ((q15_t) x * (q15_t) (y >> 16)); */ + return ((uint64_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) + + ( ((q63_t)sum ) ) )); + } + + + /* + * @brief C custom defined SMUAD for M3 and M0 processors + */ + static __INLINE uint32_t __SMUAD( + uint32_t x, + uint32_t y) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y << 16) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y ) >> 16)) )); + } + + + /* + * @brief C custom defined SMUSD for M3 and M0 processors + */ + static __INLINE uint32_t __SMUSD( + uint32_t x, + uint32_t y) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y << 16) >> 16)) - + ((((q31_t)x ) >> 16) * (((q31_t)y ) >> 16)) )); + } + + + /* + * @brief C custom defined SXTB16 for M3 and M0 processors + */ + static __INLINE uint32_t __SXTB16( + uint32_t x) + { + return ((uint32_t)(((((q31_t)x << 24) >> 24) & (q31_t)0x0000FFFF) | + ((((q31_t)x << 8) >> 8) & (q31_t)0xFFFF0000) )); + } + +#endif /* defined (ARM_MATH_CM3) || defined (ARM_MATH_CM0_FAMILY) */ + + + /** + * @brief Instance structure for the Q7 FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of filter coefficients in the filter. */ + q7_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q7_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + } arm_fir_instance_q7; + + /** + * @brief Instance structure for the Q15 FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of filter coefficients in the filter. */ + q15_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + } arm_fir_instance_q15; + + /** + * @brief Instance structure for the Q31 FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of filter coefficients in the filter. */ + q31_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + } arm_fir_instance_q31; + + /** + * @brief Instance structure for the floating-point FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of filter coefficients in the filter. */ + float32_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + } arm_fir_instance_f32; + + + /** + * @brief Processing function for the Q7 FIR filter. + * @param[in] S points to an instance of the Q7 FIR filter structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_q7( + const arm_fir_instance_q7 * S, + q7_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q7 FIR filter. + * @param[in,out] S points to an instance of the Q7 FIR structure. + * @param[in] numTaps Number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of samples that are processed. + */ + void arm_fir_init_q7( + arm_fir_instance_q7 * S, + uint16_t numTaps, + q7_t * pCoeffs, + q7_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q15 FIR filter. + * @param[in] S points to an instance of the Q15 FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_q15( + const arm_fir_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Processing function for the fast Q15 FIR filter for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q15 FIR filter structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_fast_q15( + const arm_fir_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q15 FIR filter. + * @param[in,out] S points to an instance of the Q15 FIR filter structure. + * @param[in] numTaps Number of filter coefficients in the filter. Must be even and greater than or equal to 4. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of samples that are processed at a time. + * @return The function returns ARM_MATH_SUCCESS if initialization was successful or ARM_MATH_ARGUMENT_ERROR if + * numTaps is not a supported value. + */ + arm_status arm_fir_init_q15( + arm_fir_instance_q15 * S, + uint16_t numTaps, + q15_t * pCoeffs, + q15_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 FIR filter. + * @param[in] S points to an instance of the Q31 FIR filter structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_q31( + const arm_fir_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Processing function for the fast Q31 FIR filter for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q31 FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_fast_q31( + const arm_fir_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 FIR filter. + * @param[in,out] S points to an instance of the Q31 FIR structure. + * @param[in] numTaps Number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of samples that are processed at a time. + */ + void arm_fir_init_q31( + arm_fir_instance_q31 * S, + uint16_t numTaps, + q31_t * pCoeffs, + q31_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the floating-point FIR filter. + * @param[in] S points to an instance of the floating-point FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_f32( + const arm_fir_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point FIR filter. + * @param[in,out] S points to an instance of the floating-point FIR filter structure. + * @param[in] numTaps Number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of samples that are processed at a time. + */ + void arm_fir_init_f32( + arm_fir_instance_f32 * S, + uint16_t numTaps, + float32_t * pCoeffs, + float32_t * pState, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q15 Biquad cascade filter. + */ + typedef struct + { + int8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + q15_t *pState; /**< Points to the array of state coefficients. The array is of length 4*numStages. */ + q15_t *pCoeffs; /**< Points to the array of coefficients. The array is of length 5*numStages. */ + int8_t postShift; /**< Additional shift, in bits, applied to each output sample. */ + } arm_biquad_casd_df1_inst_q15; + + /** + * @brief Instance structure for the Q31 Biquad cascade filter. + */ + typedef struct + { + uint32_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + q31_t *pState; /**< Points to the array of state coefficients. The array is of length 4*numStages. */ + q31_t *pCoeffs; /**< Points to the array of coefficients. The array is of length 5*numStages. */ + uint8_t postShift; /**< Additional shift, in bits, applied to each output sample. */ + } arm_biquad_casd_df1_inst_q31; + + /** + * @brief Instance structure for the floating-point Biquad cascade filter. + */ + typedef struct + { + uint32_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + float32_t *pState; /**< Points to the array of state coefficients. The array is of length 4*numStages. */ + float32_t *pCoeffs; /**< Points to the array of coefficients. The array is of length 5*numStages. */ + } arm_biquad_casd_df1_inst_f32; + + + /** + * @brief Processing function for the Q15 Biquad cascade filter. + * @param[in] S points to an instance of the Q15 Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df1_q15( + const arm_biquad_casd_df1_inst_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q15 Biquad cascade filter. + * @param[in,out] S points to an instance of the Q15 Biquad cascade structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] postShift Shift to be applied to the output. Varies according to the coefficients format + */ + void arm_biquad_cascade_df1_init_q15( + arm_biquad_casd_df1_inst_q15 * S, + uint8_t numStages, + q15_t * pCoeffs, + q15_t * pState, + int8_t postShift); + + + /** + * @brief Fast but less precise processing function for the Q15 Biquad cascade filter for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q15 Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df1_fast_q15( + const arm_biquad_casd_df1_inst_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 Biquad cascade filter + * @param[in] S points to an instance of the Q31 Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df1_q31( + const arm_biquad_casd_df1_inst_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Fast but less precise processing function for the Q31 Biquad cascade filter for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q31 Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df1_fast_q31( + const arm_biquad_casd_df1_inst_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 Biquad cascade filter. + * @param[in,out] S points to an instance of the Q31 Biquad cascade structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] postShift Shift to be applied to the output. Varies according to the coefficients format + */ + void arm_biquad_cascade_df1_init_q31( + arm_biquad_casd_df1_inst_q31 * S, + uint8_t numStages, + q31_t * pCoeffs, + q31_t * pState, + int8_t postShift); + + + /** + * @brief Processing function for the floating-point Biquad cascade filter. + * @param[in] S points to an instance of the floating-point Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df1_f32( + const arm_biquad_casd_df1_inst_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point Biquad cascade filter. + * @param[in,out] S points to an instance of the floating-point Biquad cascade structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + */ + void arm_biquad_cascade_df1_init_f32( + arm_biquad_casd_df1_inst_f32 * S, + uint8_t numStages, + float32_t * pCoeffs, + float32_t * pState); + + + /** + * @brief Instance structure for the floating-point matrix structure. + */ + typedef struct + { + uint16_t numRows; /**< number of rows of the matrix. */ + uint16_t numCols; /**< number of columns of the matrix. */ + float32_t *pData; /**< points to the data of the matrix. */ + } arm_matrix_instance_f32; + + + /** + * @brief Instance structure for the floating-point matrix structure. + */ + typedef struct + { + uint16_t numRows; /**< number of rows of the matrix. */ + uint16_t numCols; /**< number of columns of the matrix. */ + float64_t *pData; /**< points to the data of the matrix. */ + } arm_matrix_instance_f64; + + /** + * @brief Instance structure for the Q15 matrix structure. + */ + typedef struct + { + uint16_t numRows; /**< number of rows of the matrix. */ + uint16_t numCols; /**< number of columns of the matrix. */ + q15_t *pData; /**< points to the data of the matrix. */ + } arm_matrix_instance_q15; + + /** + * @brief Instance structure for the Q31 matrix structure. + */ + typedef struct + { + uint16_t numRows; /**< number of rows of the matrix. */ + uint16_t numCols; /**< number of columns of the matrix. */ + q31_t *pData; /**< points to the data of the matrix. */ + } arm_matrix_instance_q31; + + + /** + * @brief Floating-point matrix addition. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_add_f32( + const arm_matrix_instance_f32 * pSrcA, + const arm_matrix_instance_f32 * pSrcB, + arm_matrix_instance_f32 * pDst); + + + /** + * @brief Q15 matrix addition. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_add_q15( + const arm_matrix_instance_q15 * pSrcA, + const arm_matrix_instance_q15 * pSrcB, + arm_matrix_instance_q15 * pDst); + + + /** + * @brief Q31 matrix addition. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_add_q31( + const arm_matrix_instance_q31 * pSrcA, + const arm_matrix_instance_q31 * pSrcB, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Floating-point, complex, matrix multiplication. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_cmplx_mult_f32( + const arm_matrix_instance_f32 * pSrcA, + const arm_matrix_instance_f32 * pSrcB, + arm_matrix_instance_f32 * pDst); + + + /** + * @brief Q15, complex, matrix multiplication. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_cmplx_mult_q15( + const arm_matrix_instance_q15 * pSrcA, + const arm_matrix_instance_q15 * pSrcB, + arm_matrix_instance_q15 * pDst, + q15_t * pScratch); + + + /** + * @brief Q31, complex, matrix multiplication. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_cmplx_mult_q31( + const arm_matrix_instance_q31 * pSrcA, + const arm_matrix_instance_q31 * pSrcB, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Floating-point matrix transpose. + * @param[in] pSrc points to the input matrix + * @param[out] pDst points to the output matrix + * @return The function returns either ARM_MATH_SIZE_MISMATCH + * or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_trans_f32( + const arm_matrix_instance_f32 * pSrc, + arm_matrix_instance_f32 * pDst); + + + /** + * @brief Q15 matrix transpose. + * @param[in] pSrc points to the input matrix + * @param[out] pDst points to the output matrix + * @return The function returns either ARM_MATH_SIZE_MISMATCH + * or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_trans_q15( + const arm_matrix_instance_q15 * pSrc, + arm_matrix_instance_q15 * pDst); + + + /** + * @brief Q31 matrix transpose. + * @param[in] pSrc points to the input matrix + * @param[out] pDst points to the output matrix + * @return The function returns either ARM_MATH_SIZE_MISMATCH + * or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_trans_q31( + const arm_matrix_instance_q31 * pSrc, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Floating-point matrix multiplication + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_mult_f32( + const arm_matrix_instance_f32 * pSrcA, + const arm_matrix_instance_f32 * pSrcB, + arm_matrix_instance_f32 * pDst); + + + /** + * @brief Q15 matrix multiplication + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @param[in] pState points to the array for storing intermediate results + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_mult_q15( + const arm_matrix_instance_q15 * pSrcA, + const arm_matrix_instance_q15 * pSrcB, + arm_matrix_instance_q15 * pDst, + q15_t * pState); + + + /** + * @brief Q15 matrix multiplication (fast variant) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @param[in] pState points to the array for storing intermediate results + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_mult_fast_q15( + const arm_matrix_instance_q15 * pSrcA, + const arm_matrix_instance_q15 * pSrcB, + arm_matrix_instance_q15 * pDst, + q15_t * pState); + + + /** + * @brief Q31 matrix multiplication + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_mult_q31( + const arm_matrix_instance_q31 * pSrcA, + const arm_matrix_instance_q31 * pSrcB, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Q31 matrix multiplication (fast variant) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_mult_fast_q31( + const arm_matrix_instance_q31 * pSrcA, + const arm_matrix_instance_q31 * pSrcB, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Floating-point matrix subtraction + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_sub_f32( + const arm_matrix_instance_f32 * pSrcA, + const arm_matrix_instance_f32 * pSrcB, + arm_matrix_instance_f32 * pDst); + + + /** + * @brief Q15 matrix subtraction + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_sub_q15( + const arm_matrix_instance_q15 * pSrcA, + const arm_matrix_instance_q15 * pSrcB, + arm_matrix_instance_q15 * pDst); + + + /** + * @brief Q31 matrix subtraction + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_sub_q31( + const arm_matrix_instance_q31 * pSrcA, + const arm_matrix_instance_q31 * pSrcB, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Floating-point matrix scaling. + * @param[in] pSrc points to the input matrix + * @param[in] scale scale factor + * @param[out] pDst points to the output matrix + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_scale_f32( + const arm_matrix_instance_f32 * pSrc, + float32_t scale, + arm_matrix_instance_f32 * pDst); + + + /** + * @brief Q15 matrix scaling. + * @param[in] pSrc points to input matrix + * @param[in] scaleFract fractional portion of the scale factor + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to output matrix + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_scale_q15( + const arm_matrix_instance_q15 * pSrc, + q15_t scaleFract, + int32_t shift, + arm_matrix_instance_q15 * pDst); + + + /** + * @brief Q31 matrix scaling. + * @param[in] pSrc points to input matrix + * @param[in] scaleFract fractional portion of the scale factor + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_scale_q31( + const arm_matrix_instance_q31 * pSrc, + q31_t scaleFract, + int32_t shift, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Q31 matrix initialization. + * @param[in,out] S points to an instance of the floating-point matrix structure. + * @param[in] nRows number of rows in the matrix. + * @param[in] nColumns number of columns in the matrix. + * @param[in] pData points to the matrix data array. + */ + void arm_mat_init_q31( + arm_matrix_instance_q31 * S, + uint16_t nRows, + uint16_t nColumns, + q31_t * pData); + + + /** + * @brief Q15 matrix initialization. + * @param[in,out] S points to an instance of the floating-point matrix structure. + * @param[in] nRows number of rows in the matrix. + * @param[in] nColumns number of columns in the matrix. + * @param[in] pData points to the matrix data array. + */ + void arm_mat_init_q15( + arm_matrix_instance_q15 * S, + uint16_t nRows, + uint16_t nColumns, + q15_t * pData); + + + /** + * @brief Floating-point matrix initialization. + * @param[in,out] S points to an instance of the floating-point matrix structure. + * @param[in] nRows number of rows in the matrix. + * @param[in] nColumns number of columns in the matrix. + * @param[in] pData points to the matrix data array. + */ + void arm_mat_init_f32( + arm_matrix_instance_f32 * S, + uint16_t nRows, + uint16_t nColumns, + float32_t * pData); + + + + /** + * @brief Instance structure for the Q15 PID Control. + */ + typedef struct + { + q15_t A0; /**< The derived gain, A0 = Kp + Ki + Kd . */ +#ifdef ARM_MATH_CM0_FAMILY + q15_t A1; + q15_t A2; +#else + q31_t A1; /**< The derived gain A1 = -Kp - 2Kd | Kd.*/ +#endif + q15_t state[3]; /**< The state array of length 3. */ + q15_t Kp; /**< The proportional gain. */ + q15_t Ki; /**< The integral gain. */ + q15_t Kd; /**< The derivative gain. */ + } arm_pid_instance_q15; + + /** + * @brief Instance structure for the Q31 PID Control. + */ + typedef struct + { + q31_t A0; /**< The derived gain, A0 = Kp + Ki + Kd . */ + q31_t A1; /**< The derived gain, A1 = -Kp - 2Kd. */ + q31_t A2; /**< The derived gain, A2 = Kd . */ + q31_t state[3]; /**< The state array of length 3. */ + q31_t Kp; /**< The proportional gain. */ + q31_t Ki; /**< The integral gain. */ + q31_t Kd; /**< The derivative gain. */ + } arm_pid_instance_q31; + + /** + * @brief Instance structure for the floating-point PID Control. + */ + typedef struct + { + float32_t A0; /**< The derived gain, A0 = Kp + Ki + Kd . */ + float32_t A1; /**< The derived gain, A1 = -Kp - 2Kd. */ + float32_t A2; /**< The derived gain, A2 = Kd . */ + float32_t state[3]; /**< The state array of length 3. */ + float32_t Kp; /**< The proportional gain. */ + float32_t Ki; /**< The integral gain. */ + float32_t Kd; /**< The derivative gain. */ + } arm_pid_instance_f32; + + + + /** + * @brief Initialization function for the floating-point PID Control. + * @param[in,out] S points to an instance of the PID structure. + * @param[in] resetStateFlag flag to reset the state. 0 = no change in state 1 = reset the state. + */ + void arm_pid_init_f32( + arm_pid_instance_f32 * S, + int32_t resetStateFlag); + + + /** + * @brief Reset function for the floating-point PID Control. + * @param[in,out] S is an instance of the floating-point PID Control structure + */ + void arm_pid_reset_f32( + arm_pid_instance_f32 * S); + + + /** + * @brief Initialization function for the Q31 PID Control. + * @param[in,out] S points to an instance of the Q15 PID structure. + * @param[in] resetStateFlag flag to reset the state. 0 = no change in state 1 = reset the state. + */ + void arm_pid_init_q31( + arm_pid_instance_q31 * S, + int32_t resetStateFlag); + + + /** + * @brief Reset function for the Q31 PID Control. + * @param[in,out] S points to an instance of the Q31 PID Control structure + */ + + void arm_pid_reset_q31( + arm_pid_instance_q31 * S); + + + /** + * @brief Initialization function for the Q15 PID Control. + * @param[in,out] S points to an instance of the Q15 PID structure. + * @param[in] resetStateFlag flag to reset the state. 0 = no change in state 1 = reset the state. + */ + void arm_pid_init_q15( + arm_pid_instance_q15 * S, + int32_t resetStateFlag); + + + /** + * @brief Reset function for the Q15 PID Control. + * @param[in,out] S points to an instance of the q15 PID Control structure + */ + void arm_pid_reset_q15( + arm_pid_instance_q15 * S); + + + /** + * @brief Instance structure for the floating-point Linear Interpolate function. + */ + typedef struct + { + uint32_t nValues; /**< nValues */ + float32_t x1; /**< x1 */ + float32_t xSpacing; /**< xSpacing */ + float32_t *pYData; /**< pointer to the table of Y values */ + } arm_linear_interp_instance_f32; + + /** + * @brief Instance structure for the floating-point bilinear interpolation function. + */ + typedef struct + { + uint16_t numRows; /**< number of rows in the data table. */ + uint16_t numCols; /**< number of columns in the data table. */ + float32_t *pData; /**< points to the data table. */ + } arm_bilinear_interp_instance_f32; + + /** + * @brief Instance structure for the Q31 bilinear interpolation function. + */ + typedef struct + { + uint16_t numRows; /**< number of rows in the data table. */ + uint16_t numCols; /**< number of columns in the data table. */ + q31_t *pData; /**< points to the data table. */ + } arm_bilinear_interp_instance_q31; + + /** + * @brief Instance structure for the Q15 bilinear interpolation function. + */ + typedef struct + { + uint16_t numRows; /**< number of rows in the data table. */ + uint16_t numCols; /**< number of columns in the data table. */ + q15_t *pData; /**< points to the data table. */ + } arm_bilinear_interp_instance_q15; + + /** + * @brief Instance structure for the Q15 bilinear interpolation function. + */ + typedef struct + { + uint16_t numRows; /**< number of rows in the data table. */ + uint16_t numCols; /**< number of columns in the data table. */ + q7_t *pData; /**< points to the data table. */ + } arm_bilinear_interp_instance_q7; + + + /** + * @brief Q7 vector multiplication. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_mult_q7( + q7_t * pSrcA, + q7_t * pSrcB, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q15 vector multiplication. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_mult_q15( + q15_t * pSrcA, + q15_t * pSrcB, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q31 vector multiplication. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_mult_q31( + q31_t * pSrcA, + q31_t * pSrcB, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Floating-point vector multiplication. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_mult_f32( + float32_t * pSrcA, + float32_t * pSrcB, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q15 CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + q15_t *pTwiddle; /**< points to the Sin twiddle factor table. */ + uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + } arm_cfft_radix2_instance_q15; + +/* Deprecated */ + arm_status arm_cfft_radix2_init_q15( + arm_cfft_radix2_instance_q15 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + +/* Deprecated */ + void arm_cfft_radix2_q15( + const arm_cfft_radix2_instance_q15 * S, + q15_t * pSrc); + + + /** + * @brief Instance structure for the Q15 CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + q15_t *pTwiddle; /**< points to the twiddle factor table. */ + uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + } arm_cfft_radix4_instance_q15; + +/* Deprecated */ + arm_status arm_cfft_radix4_init_q15( + arm_cfft_radix4_instance_q15 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + +/* Deprecated */ + void arm_cfft_radix4_q15( + const arm_cfft_radix4_instance_q15 * S, + q15_t * pSrc); + + /** + * @brief Instance structure for the Radix-2 Q31 CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + q31_t *pTwiddle; /**< points to the Twiddle factor table. */ + uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + } arm_cfft_radix2_instance_q31; + +/* Deprecated */ + arm_status arm_cfft_radix2_init_q31( + arm_cfft_radix2_instance_q31 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + +/* Deprecated */ + void arm_cfft_radix2_q31( + const arm_cfft_radix2_instance_q31 * S, + q31_t * pSrc); + + /** + * @brief Instance structure for the Q31 CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + q31_t *pTwiddle; /**< points to the twiddle factor table. */ + uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + } arm_cfft_radix4_instance_q31; + +/* Deprecated */ + void arm_cfft_radix4_q31( + const arm_cfft_radix4_instance_q31 * S, + q31_t * pSrc); + +/* Deprecated */ + arm_status arm_cfft_radix4_init_q31( + arm_cfft_radix4_instance_q31 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + + /** + * @brief Instance structure for the floating-point CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + float32_t *pTwiddle; /**< points to the Twiddle factor table. */ + uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + float32_t onebyfftLen; /**< value of 1/fftLen. */ + } arm_cfft_radix2_instance_f32; + +/* Deprecated */ + arm_status arm_cfft_radix2_init_f32( + arm_cfft_radix2_instance_f32 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + +/* Deprecated */ + void arm_cfft_radix2_f32( + const arm_cfft_radix2_instance_f32 * S, + float32_t * pSrc); + + /** + * @brief Instance structure for the floating-point CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + float32_t *pTwiddle; /**< points to the Twiddle factor table. */ + uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + float32_t onebyfftLen; /**< value of 1/fftLen. */ + } arm_cfft_radix4_instance_f32; + +/* Deprecated */ + arm_status arm_cfft_radix4_init_f32( + arm_cfft_radix4_instance_f32 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + +/* Deprecated */ + void arm_cfft_radix4_f32( + const arm_cfft_radix4_instance_f32 * S, + float32_t * pSrc); + + /** + * @brief Instance structure for the fixed-point CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + const q15_t *pTwiddle; /**< points to the Twiddle factor table. */ + const uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t bitRevLength; /**< bit reversal table length. */ + } arm_cfft_instance_q15; + +void arm_cfft_q15( + const arm_cfft_instance_q15 * S, + q15_t * p1, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + + /** + * @brief Instance structure for the fixed-point CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + const q31_t *pTwiddle; /**< points to the Twiddle factor table. */ + const uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t bitRevLength; /**< bit reversal table length. */ + } arm_cfft_instance_q31; + +void arm_cfft_q31( + const arm_cfft_instance_q31 * S, + q31_t * p1, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + + /** + * @brief Instance structure for the floating-point CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + const float32_t *pTwiddle; /**< points to the Twiddle factor table. */ + const uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t bitRevLength; /**< bit reversal table length. */ + } arm_cfft_instance_f32; + + void arm_cfft_f32( + const arm_cfft_instance_f32 * S, + float32_t * p1, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + + /** + * @brief Instance structure for the Q15 RFFT/RIFFT function. + */ + typedef struct + { + uint32_t fftLenReal; /**< length of the real FFT. */ + uint8_t ifftFlagR; /**< flag that selects forward (ifftFlagR=0) or inverse (ifftFlagR=1) transform. */ + uint8_t bitReverseFlagR; /**< flag that enables (bitReverseFlagR=1) or disables (bitReverseFlagR=0) bit reversal of output. */ + uint32_t twidCoefRModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + q15_t *pTwiddleAReal; /**< points to the real twiddle factor table. */ + q15_t *pTwiddleBReal; /**< points to the imag twiddle factor table. */ + const arm_cfft_instance_q15 *pCfft; /**< points to the complex FFT instance. */ + } arm_rfft_instance_q15; + + arm_status arm_rfft_init_q15( + arm_rfft_instance_q15 * S, + uint32_t fftLenReal, + uint32_t ifftFlagR, + uint32_t bitReverseFlag); + + void arm_rfft_q15( + const arm_rfft_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst); + + /** + * @brief Instance structure for the Q31 RFFT/RIFFT function. + */ + typedef struct + { + uint32_t fftLenReal; /**< length of the real FFT. */ + uint8_t ifftFlagR; /**< flag that selects forward (ifftFlagR=0) or inverse (ifftFlagR=1) transform. */ + uint8_t bitReverseFlagR; /**< flag that enables (bitReverseFlagR=1) or disables (bitReverseFlagR=0) bit reversal of output. */ + uint32_t twidCoefRModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + q31_t *pTwiddleAReal; /**< points to the real twiddle factor table. */ + q31_t *pTwiddleBReal; /**< points to the imag twiddle factor table. */ + const arm_cfft_instance_q31 *pCfft; /**< points to the complex FFT instance. */ + } arm_rfft_instance_q31; + + arm_status arm_rfft_init_q31( + arm_rfft_instance_q31 * S, + uint32_t fftLenReal, + uint32_t ifftFlagR, + uint32_t bitReverseFlag); + + void arm_rfft_q31( + const arm_rfft_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst); + + /** + * @brief Instance structure for the floating-point RFFT/RIFFT function. + */ + typedef struct + { + uint32_t fftLenReal; /**< length of the real FFT. */ + uint16_t fftLenBy2; /**< length of the complex FFT. */ + uint8_t ifftFlagR; /**< flag that selects forward (ifftFlagR=0) or inverse (ifftFlagR=1) transform. */ + uint8_t bitReverseFlagR; /**< flag that enables (bitReverseFlagR=1) or disables (bitReverseFlagR=0) bit reversal of output. */ + uint32_t twidCoefRModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + float32_t *pTwiddleAReal; /**< points to the real twiddle factor table. */ + float32_t *pTwiddleBReal; /**< points to the imag twiddle factor table. */ + arm_cfft_radix4_instance_f32 *pCfft; /**< points to the complex FFT instance. */ + } arm_rfft_instance_f32; + + arm_status arm_rfft_init_f32( + arm_rfft_instance_f32 * S, + arm_cfft_radix4_instance_f32 * S_CFFT, + uint32_t fftLenReal, + uint32_t ifftFlagR, + uint32_t bitReverseFlag); + + void arm_rfft_f32( + const arm_rfft_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst); + + /** + * @brief Instance structure for the floating-point RFFT/RIFFT function. + */ +typedef struct + { + arm_cfft_instance_f32 Sint; /**< Internal CFFT structure. */ + uint16_t fftLenRFFT; /**< length of the real sequence */ + float32_t * pTwiddleRFFT; /**< Twiddle factors real stage */ + } arm_rfft_fast_instance_f32 ; + +arm_status arm_rfft_fast_init_f32 ( + arm_rfft_fast_instance_f32 * S, + uint16_t fftLen); + +void arm_rfft_fast_f32( + arm_rfft_fast_instance_f32 * S, + float32_t * p, float32_t * pOut, + uint8_t ifftFlag); + + /** + * @brief Instance structure for the floating-point DCT4/IDCT4 function. + */ + typedef struct + { + uint16_t N; /**< length of the DCT4. */ + uint16_t Nby2; /**< half of the length of the DCT4. */ + float32_t normalize; /**< normalizing factor. */ + float32_t *pTwiddle; /**< points to the twiddle factor table. */ + float32_t *pCosFactor; /**< points to the cosFactor table. */ + arm_rfft_instance_f32 *pRfft; /**< points to the real FFT instance. */ + arm_cfft_radix4_instance_f32 *pCfft; /**< points to the complex FFT instance. */ + } arm_dct4_instance_f32; + + + /** + * @brief Initialization function for the floating-point DCT4/IDCT4. + * @param[in,out] S points to an instance of floating-point DCT4/IDCT4 structure. + * @param[in] S_RFFT points to an instance of floating-point RFFT/RIFFT structure. + * @param[in] S_CFFT points to an instance of floating-point CFFT/CIFFT structure. + * @param[in] N length of the DCT4. + * @param[in] Nby2 half of the length of the DCT4. + * @param[in] normalize normalizing factor. + * @return arm_status function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if fftLenReal is not a supported transform length. + */ + arm_status arm_dct4_init_f32( + arm_dct4_instance_f32 * S, + arm_rfft_instance_f32 * S_RFFT, + arm_cfft_radix4_instance_f32 * S_CFFT, + uint16_t N, + uint16_t Nby2, + float32_t normalize); + + + /** + * @brief Processing function for the floating-point DCT4/IDCT4. + * @param[in] S points to an instance of the floating-point DCT4/IDCT4 structure. + * @param[in] pState points to state buffer. + * @param[in,out] pInlineBuffer points to the in-place input and output buffer. + */ + void arm_dct4_f32( + const arm_dct4_instance_f32 * S, + float32_t * pState, + float32_t * pInlineBuffer); + + + /** + * @brief Instance structure for the Q31 DCT4/IDCT4 function. + */ + typedef struct + { + uint16_t N; /**< length of the DCT4. */ + uint16_t Nby2; /**< half of the length of the DCT4. */ + q31_t normalize; /**< normalizing factor. */ + q31_t *pTwiddle; /**< points to the twiddle factor table. */ + q31_t *pCosFactor; /**< points to the cosFactor table. */ + arm_rfft_instance_q31 *pRfft; /**< points to the real FFT instance. */ + arm_cfft_radix4_instance_q31 *pCfft; /**< points to the complex FFT instance. */ + } arm_dct4_instance_q31; + + + /** + * @brief Initialization function for the Q31 DCT4/IDCT4. + * @param[in,out] S points to an instance of Q31 DCT4/IDCT4 structure. + * @param[in] S_RFFT points to an instance of Q31 RFFT/RIFFT structure + * @param[in] S_CFFT points to an instance of Q31 CFFT/CIFFT structure + * @param[in] N length of the DCT4. + * @param[in] Nby2 half of the length of the DCT4. + * @param[in] normalize normalizing factor. + * @return arm_status function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if N is not a supported transform length. + */ + arm_status arm_dct4_init_q31( + arm_dct4_instance_q31 * S, + arm_rfft_instance_q31 * S_RFFT, + arm_cfft_radix4_instance_q31 * S_CFFT, + uint16_t N, + uint16_t Nby2, + q31_t normalize); + + + /** + * @brief Processing function for the Q31 DCT4/IDCT4. + * @param[in] S points to an instance of the Q31 DCT4 structure. + * @param[in] pState points to state buffer. + * @param[in,out] pInlineBuffer points to the in-place input and output buffer. + */ + void arm_dct4_q31( + const arm_dct4_instance_q31 * S, + q31_t * pState, + q31_t * pInlineBuffer); + + + /** + * @brief Instance structure for the Q15 DCT4/IDCT4 function. + */ + typedef struct + { + uint16_t N; /**< length of the DCT4. */ + uint16_t Nby2; /**< half of the length of the DCT4. */ + q15_t normalize; /**< normalizing factor. */ + q15_t *pTwiddle; /**< points to the twiddle factor table. */ + q15_t *pCosFactor; /**< points to the cosFactor table. */ + arm_rfft_instance_q15 *pRfft; /**< points to the real FFT instance. */ + arm_cfft_radix4_instance_q15 *pCfft; /**< points to the complex FFT instance. */ + } arm_dct4_instance_q15; + + + /** + * @brief Initialization function for the Q15 DCT4/IDCT4. + * @param[in,out] S points to an instance of Q15 DCT4/IDCT4 structure. + * @param[in] S_RFFT points to an instance of Q15 RFFT/RIFFT structure. + * @param[in] S_CFFT points to an instance of Q15 CFFT/CIFFT structure. + * @param[in] N length of the DCT4. + * @param[in] Nby2 half of the length of the DCT4. + * @param[in] normalize normalizing factor. + * @return arm_status function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if N is not a supported transform length. + */ + arm_status arm_dct4_init_q15( + arm_dct4_instance_q15 * S, + arm_rfft_instance_q15 * S_RFFT, + arm_cfft_radix4_instance_q15 * S_CFFT, + uint16_t N, + uint16_t Nby2, + q15_t normalize); + + + /** + * @brief Processing function for the Q15 DCT4/IDCT4. + * @param[in] S points to an instance of the Q15 DCT4 structure. + * @param[in] pState points to state buffer. + * @param[in,out] pInlineBuffer points to the in-place input and output buffer. + */ + void arm_dct4_q15( + const arm_dct4_instance_q15 * S, + q15_t * pState, + q15_t * pInlineBuffer); + + + /** + * @brief Floating-point vector addition. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_add_f32( + float32_t * pSrcA, + float32_t * pSrcB, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q7 vector addition. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_add_q7( + q7_t * pSrcA, + q7_t * pSrcB, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q15 vector addition. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_add_q15( + q15_t * pSrcA, + q15_t * pSrcB, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q31 vector addition. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_add_q31( + q31_t * pSrcA, + q31_t * pSrcB, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Floating-point vector subtraction. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_sub_f32( + float32_t * pSrcA, + float32_t * pSrcB, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q7 vector subtraction. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_sub_q7( + q7_t * pSrcA, + q7_t * pSrcB, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q15 vector subtraction. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_sub_q15( + q15_t * pSrcA, + q15_t * pSrcB, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q31 vector subtraction. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_sub_q31( + q31_t * pSrcA, + q31_t * pSrcB, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Multiplies a floating-point vector by a scalar. + * @param[in] pSrc points to the input vector + * @param[in] scale scale factor to be applied + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_scale_f32( + float32_t * pSrc, + float32_t scale, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Multiplies a Q7 vector by a scalar. + * @param[in] pSrc points to the input vector + * @param[in] scaleFract fractional portion of the scale value + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_scale_q7( + q7_t * pSrc, + q7_t scaleFract, + int8_t shift, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Multiplies a Q15 vector by a scalar. + * @param[in] pSrc points to the input vector + * @param[in] scaleFract fractional portion of the scale value + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_scale_q15( + q15_t * pSrc, + q15_t scaleFract, + int8_t shift, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Multiplies a Q31 vector by a scalar. + * @param[in] pSrc points to the input vector + * @param[in] scaleFract fractional portion of the scale value + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_scale_q31( + q31_t * pSrc, + q31_t scaleFract, + int8_t shift, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q7 vector absolute value. + * @param[in] pSrc points to the input buffer + * @param[out] pDst points to the output buffer + * @param[in] blockSize number of samples in each vector + */ + void arm_abs_q7( + q7_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Floating-point vector absolute value. + * @param[in] pSrc points to the input buffer + * @param[out] pDst points to the output buffer + * @param[in] blockSize number of samples in each vector + */ + void arm_abs_f32( + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q15 vector absolute value. + * @param[in] pSrc points to the input buffer + * @param[out] pDst points to the output buffer + * @param[in] blockSize number of samples in each vector + */ + void arm_abs_q15( + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q31 vector absolute value. + * @param[in] pSrc points to the input buffer + * @param[out] pDst points to the output buffer + * @param[in] blockSize number of samples in each vector + */ + void arm_abs_q31( + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Dot product of floating-point vectors. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] blockSize number of samples in each vector + * @param[out] result output result returned here + */ + void arm_dot_prod_f32( + float32_t * pSrcA, + float32_t * pSrcB, + uint32_t blockSize, + float32_t * result); + + + /** + * @brief Dot product of Q7 vectors. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] blockSize number of samples in each vector + * @param[out] result output result returned here + */ + void arm_dot_prod_q7( + q7_t * pSrcA, + q7_t * pSrcB, + uint32_t blockSize, + q31_t * result); + + + /** + * @brief Dot product of Q15 vectors. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] blockSize number of samples in each vector + * @param[out] result output result returned here + */ + void arm_dot_prod_q15( + q15_t * pSrcA, + q15_t * pSrcB, + uint32_t blockSize, + q63_t * result); + + + /** + * @brief Dot product of Q31 vectors. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] blockSize number of samples in each vector + * @param[out] result output result returned here + */ + void arm_dot_prod_q31( + q31_t * pSrcA, + q31_t * pSrcB, + uint32_t blockSize, + q63_t * result); + + + /** + * @brief Shifts the elements of a Q7 vector a specified number of bits. + * @param[in] pSrc points to the input vector + * @param[in] shiftBits number of bits to shift. A positive value shifts left; a negative value shifts right. + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_shift_q7( + q7_t * pSrc, + int8_t shiftBits, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Shifts the elements of a Q15 vector a specified number of bits. + * @param[in] pSrc points to the input vector + * @param[in] shiftBits number of bits to shift. A positive value shifts left; a negative value shifts right. + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_shift_q15( + q15_t * pSrc, + int8_t shiftBits, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Shifts the elements of a Q31 vector a specified number of bits. + * @param[in] pSrc points to the input vector + * @param[in] shiftBits number of bits to shift. A positive value shifts left; a negative value shifts right. + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_shift_q31( + q31_t * pSrc, + int8_t shiftBits, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Adds a constant offset to a floating-point vector. + * @param[in] pSrc points to the input vector + * @param[in] offset is the offset to be added + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_offset_f32( + float32_t * pSrc, + float32_t offset, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Adds a constant offset to a Q7 vector. + * @param[in] pSrc points to the input vector + * @param[in] offset is the offset to be added + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_offset_q7( + q7_t * pSrc, + q7_t offset, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Adds a constant offset to a Q15 vector. + * @param[in] pSrc points to the input vector + * @param[in] offset is the offset to be added + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_offset_q15( + q15_t * pSrc, + q15_t offset, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Adds a constant offset to a Q31 vector. + * @param[in] pSrc points to the input vector + * @param[in] offset is the offset to be added + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_offset_q31( + q31_t * pSrc, + q31_t offset, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Negates the elements of a floating-point vector. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_negate_f32( + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Negates the elements of a Q7 vector. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_negate_q7( + q7_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Negates the elements of a Q15 vector. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_negate_q15( + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Negates the elements of a Q31 vector. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_negate_q31( + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Copies the elements of a floating-point vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_copy_f32( + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Copies the elements of a Q7 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_copy_q7( + q7_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Copies the elements of a Q15 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_copy_q15( + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Copies the elements of a Q31 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_copy_q31( + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Fills a constant value into a floating-point vector. + * @param[in] value input value to be filled + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_fill_f32( + float32_t value, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Fills a constant value into a Q7 vector. + * @param[in] value input value to be filled + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_fill_q7( + q7_t value, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Fills a constant value into a Q15 vector. + * @param[in] value input value to be filled + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_fill_q15( + q15_t value, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Fills a constant value into a Q31 vector. + * @param[in] value input value to be filled + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_fill_q31( + q31_t value, + q31_t * pDst, + uint32_t blockSize); + + +/** + * @brief Convolution of floating-point sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the location where the output result is written. Length srcALen+srcBLen-1. + */ + void arm_conv_f32( + float32_t * pSrcA, + uint32_t srcALen, + float32_t * pSrcB, + uint32_t srcBLen, + float32_t * pDst); + + + /** + * @brief Convolution of Q15 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + * @param[in] pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer of size min(srcALen, srcBLen). + */ + void arm_conv_opt_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + q15_t * pScratch1, + q15_t * pScratch2); + + +/** + * @brief Convolution of Q15 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the location where the output result is written. Length srcALen+srcBLen-1. + */ + void arm_conv_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst); + + + /** + * @brief Convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + */ + void arm_conv_fast_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst); + + + /** + * @brief Convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + * @param[in] pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer of size min(srcALen, srcBLen). + */ + void arm_conv_fast_opt_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + q15_t * pScratch1, + q15_t * pScratch2); + + + /** + * @brief Convolution of Q31 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + */ + void arm_conv_q31( + q31_t * pSrcA, + uint32_t srcALen, + q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst); + + + /** + * @brief Convolution of Q31 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + */ + void arm_conv_fast_q31( + q31_t * pSrcA, + uint32_t srcALen, + q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst); + + + /** + * @brief Convolution of Q7 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + * @param[in] pScratch1 points to scratch buffer(of type q15_t) of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer (of type q15_t) of size min(srcALen, srcBLen). + */ + void arm_conv_opt_q7( + q7_t * pSrcA, + uint32_t srcALen, + q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst, + q15_t * pScratch1, + q15_t * pScratch2); + + + /** + * @brief Convolution of Q7 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + */ + void arm_conv_q7( + q7_t * pSrcA, + uint32_t srcALen, + q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst); + + + /** + * @brief Partial convolution of floating-point sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_f32( + float32_t * pSrcA, + uint32_t srcALen, + float32_t * pSrcB, + uint32_t srcBLen, + float32_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Partial convolution of Q15 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @param[in] pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer of size min(srcALen, srcBLen). + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_opt_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + uint32_t firstIndex, + uint32_t numPoints, + q15_t * pScratch1, + q15_t * pScratch2); + + + /** + * @brief Partial convolution of Q15 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Partial convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_fast_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Partial convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @param[in] pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer of size min(srcALen, srcBLen). + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_fast_opt_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + uint32_t firstIndex, + uint32_t numPoints, + q15_t * pScratch1, + q15_t * pScratch2); + + + /** + * @brief Partial convolution of Q31 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_q31( + q31_t * pSrcA, + uint32_t srcALen, + q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Partial convolution of Q31 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_fast_q31( + q31_t * pSrcA, + uint32_t srcALen, + q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Partial convolution of Q7 sequences + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @param[in] pScratch1 points to scratch buffer(of type q15_t) of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer (of type q15_t) of size min(srcALen, srcBLen). + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_opt_q7( + q7_t * pSrcA, + uint32_t srcALen, + q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst, + uint32_t firstIndex, + uint32_t numPoints, + q15_t * pScratch1, + q15_t * pScratch2); + + +/** + * @brief Partial convolution of Q7 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_q7( + q7_t * pSrcA, + uint32_t srcALen, + q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Instance structure for the Q15 FIR decimator. + */ + typedef struct + { + uint8_t M; /**< decimation factor. */ + uint16_t numTaps; /**< number of coefficients in the filter. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + q15_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + } arm_fir_decimate_instance_q15; + + /** + * @brief Instance structure for the Q31 FIR decimator. + */ + typedef struct + { + uint8_t M; /**< decimation factor. */ + uint16_t numTaps; /**< number of coefficients in the filter. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + q31_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + } arm_fir_decimate_instance_q31; + + /** + * @brief Instance structure for the floating-point FIR decimator. + */ + typedef struct + { + uint8_t M; /**< decimation factor. */ + uint16_t numTaps; /**< number of coefficients in the filter. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + float32_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + } arm_fir_decimate_instance_f32; + + + /** + * @brief Processing function for the floating-point FIR decimator. + * @param[in] S points to an instance of the floating-point FIR decimator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_decimate_f32( + const arm_fir_decimate_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point FIR decimator. + * @param[in,out] S points to an instance of the floating-point FIR decimator structure. + * @param[in] numTaps number of coefficients in the filter. + * @param[in] M decimation factor. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * blockSize is not a multiple of M. + */ + arm_status arm_fir_decimate_init_f32( + arm_fir_decimate_instance_f32 * S, + uint16_t numTaps, + uint8_t M, + float32_t * pCoeffs, + float32_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q15 FIR decimator. + * @param[in] S points to an instance of the Q15 FIR decimator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_decimate_q15( + const arm_fir_decimate_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q15 FIR decimator (fast variant) for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q15 FIR decimator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_decimate_fast_q15( + const arm_fir_decimate_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q15 FIR decimator. + * @param[in,out] S points to an instance of the Q15 FIR decimator structure. + * @param[in] numTaps number of coefficients in the filter. + * @param[in] M decimation factor. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * blockSize is not a multiple of M. + */ + arm_status arm_fir_decimate_init_q15( + arm_fir_decimate_instance_q15 * S, + uint16_t numTaps, + uint8_t M, + q15_t * pCoeffs, + q15_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 FIR decimator. + * @param[in] S points to an instance of the Q31 FIR decimator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_decimate_q31( + const arm_fir_decimate_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + /** + * @brief Processing function for the Q31 FIR decimator (fast variant) for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q31 FIR decimator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_decimate_fast_q31( + arm_fir_decimate_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 FIR decimator. + * @param[in,out] S points to an instance of the Q31 FIR decimator structure. + * @param[in] numTaps number of coefficients in the filter. + * @param[in] M decimation factor. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * blockSize is not a multiple of M. + */ + arm_status arm_fir_decimate_init_q31( + arm_fir_decimate_instance_q31 * S, + uint16_t numTaps, + uint8_t M, + q31_t * pCoeffs, + q31_t * pState, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q15 FIR interpolator. + */ + typedef struct + { + uint8_t L; /**< upsample factor. */ + uint16_t phaseLength; /**< length of each polyphase filter component. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length L*phaseLength. */ + q15_t *pState; /**< points to the state variable array. The array is of length blockSize+phaseLength-1. */ + } arm_fir_interpolate_instance_q15; + + /** + * @brief Instance structure for the Q31 FIR interpolator. + */ + typedef struct + { + uint8_t L; /**< upsample factor. */ + uint16_t phaseLength; /**< length of each polyphase filter component. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length L*phaseLength. */ + q31_t *pState; /**< points to the state variable array. The array is of length blockSize+phaseLength-1. */ + } arm_fir_interpolate_instance_q31; + + /** + * @brief Instance structure for the floating-point FIR interpolator. + */ + typedef struct + { + uint8_t L; /**< upsample factor. */ + uint16_t phaseLength; /**< length of each polyphase filter component. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length L*phaseLength. */ + float32_t *pState; /**< points to the state variable array. The array is of length phaseLength+numTaps-1. */ + } arm_fir_interpolate_instance_f32; + + + /** + * @brief Processing function for the Q15 FIR interpolator. + * @param[in] S points to an instance of the Q15 FIR interpolator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_interpolate_q15( + const arm_fir_interpolate_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q15 FIR interpolator. + * @param[in,out] S points to an instance of the Q15 FIR interpolator structure. + * @param[in] L upsample factor. + * @param[in] numTaps number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficient buffer. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * the filter length numTaps is not a multiple of the interpolation factor L. + */ + arm_status arm_fir_interpolate_init_q15( + arm_fir_interpolate_instance_q15 * S, + uint8_t L, + uint16_t numTaps, + q15_t * pCoeffs, + q15_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 FIR interpolator. + * @param[in] S points to an instance of the Q15 FIR interpolator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_interpolate_q31( + const arm_fir_interpolate_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 FIR interpolator. + * @param[in,out] S points to an instance of the Q31 FIR interpolator structure. + * @param[in] L upsample factor. + * @param[in] numTaps number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficient buffer. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * the filter length numTaps is not a multiple of the interpolation factor L. + */ + arm_status arm_fir_interpolate_init_q31( + arm_fir_interpolate_instance_q31 * S, + uint8_t L, + uint16_t numTaps, + q31_t * pCoeffs, + q31_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the floating-point FIR interpolator. + * @param[in] S points to an instance of the floating-point FIR interpolator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_interpolate_f32( + const arm_fir_interpolate_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point FIR interpolator. + * @param[in,out] S points to an instance of the floating-point FIR interpolator structure. + * @param[in] L upsample factor. + * @param[in] numTaps number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficient buffer. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * the filter length numTaps is not a multiple of the interpolation factor L. + */ + arm_status arm_fir_interpolate_init_f32( + arm_fir_interpolate_instance_f32 * S, + uint8_t L, + uint16_t numTaps, + float32_t * pCoeffs, + float32_t * pState, + uint32_t blockSize); + + + /** + * @brief Instance structure for the high precision Q31 Biquad cascade filter. + */ + typedef struct + { + uint8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + q63_t *pState; /**< points to the array of state coefficients. The array is of length 4*numStages. */ + q31_t *pCoeffs; /**< points to the array of coefficients. The array is of length 5*numStages. */ + uint8_t postShift; /**< additional shift, in bits, applied to each output sample. */ + } arm_biquad_cas_df1_32x64_ins_q31; + + + /** + * @param[in] S points to an instance of the high precision Q31 Biquad cascade filter structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cas_df1_32x64_q31( + const arm_biquad_cas_df1_32x64_ins_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @param[in,out] S points to an instance of the high precision Q31 Biquad cascade filter structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] postShift shift to be applied to the output. Varies according to the coefficients format + */ + void arm_biquad_cas_df1_32x64_init_q31( + arm_biquad_cas_df1_32x64_ins_q31 * S, + uint8_t numStages, + q31_t * pCoeffs, + q63_t * pState, + uint8_t postShift); + + + /** + * @brief Instance structure for the floating-point transposed direct form II Biquad cascade filter. + */ + typedef struct + { + uint8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + float32_t *pState; /**< points to the array of state coefficients. The array is of length 2*numStages. */ + float32_t *pCoeffs; /**< points to the array of coefficients. The array is of length 5*numStages. */ + } arm_biquad_cascade_df2T_instance_f32; + + /** + * @brief Instance structure for the floating-point transposed direct form II Biquad cascade filter. + */ + typedef struct + { + uint8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + float32_t *pState; /**< points to the array of state coefficients. The array is of length 4*numStages. */ + float32_t *pCoeffs; /**< points to the array of coefficients. The array is of length 5*numStages. */ + } arm_biquad_cascade_stereo_df2T_instance_f32; + + /** + * @brief Instance structure for the floating-point transposed direct form II Biquad cascade filter. + */ + typedef struct + { + uint8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + float64_t *pState; /**< points to the array of state coefficients. The array is of length 2*numStages. */ + float64_t *pCoeffs; /**< points to the array of coefficients. The array is of length 5*numStages. */ + } arm_biquad_cascade_df2T_instance_f64; + + + /** + * @brief Processing function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in] S points to an instance of the filter data structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df2T_f32( + const arm_biquad_cascade_df2T_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Processing function for the floating-point transposed direct form II Biquad cascade filter. 2 channels + * @param[in] S points to an instance of the filter data structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_stereo_df2T_f32( + const arm_biquad_cascade_stereo_df2T_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Processing function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in] S points to an instance of the filter data structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df2T_f64( + const arm_biquad_cascade_df2T_instance_f64 * S, + float64_t * pSrc, + float64_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in,out] S points to an instance of the filter data structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + */ + void arm_biquad_cascade_df2T_init_f32( + arm_biquad_cascade_df2T_instance_f32 * S, + uint8_t numStages, + float32_t * pCoeffs, + float32_t * pState); + + + /** + * @brief Initialization function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in,out] S points to an instance of the filter data structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + */ + void arm_biquad_cascade_stereo_df2T_init_f32( + arm_biquad_cascade_stereo_df2T_instance_f32 * S, + uint8_t numStages, + float32_t * pCoeffs, + float32_t * pState); + + + /** + * @brief Initialization function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in,out] S points to an instance of the filter data structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + */ + void arm_biquad_cascade_df2T_init_f64( + arm_biquad_cascade_df2T_instance_f64 * S, + uint8_t numStages, + float64_t * pCoeffs, + float64_t * pState); + + + /** + * @brief Instance structure for the Q15 FIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of filter stages. */ + q15_t *pState; /**< points to the state variable array. The array is of length numStages. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numStages. */ + } arm_fir_lattice_instance_q15; + + /** + * @brief Instance structure for the Q31 FIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of filter stages. */ + q31_t *pState; /**< points to the state variable array. The array is of length numStages. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numStages. */ + } arm_fir_lattice_instance_q31; + + /** + * @brief Instance structure for the floating-point FIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of filter stages. */ + float32_t *pState; /**< points to the state variable array. The array is of length numStages. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numStages. */ + } arm_fir_lattice_instance_f32; + + + /** + * @brief Initialization function for the Q15 FIR lattice filter. + * @param[in] S points to an instance of the Q15 FIR lattice structure. + * @param[in] numStages number of filter stages. + * @param[in] pCoeffs points to the coefficient buffer. The array is of length numStages. + * @param[in] pState points to the state buffer. The array is of length numStages. + */ + void arm_fir_lattice_init_q15( + arm_fir_lattice_instance_q15 * S, + uint16_t numStages, + q15_t * pCoeffs, + q15_t * pState); + + + /** + * @brief Processing function for the Q15 FIR lattice filter. + * @param[in] S points to an instance of the Q15 FIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_lattice_q15( + const arm_fir_lattice_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 FIR lattice filter. + * @param[in] S points to an instance of the Q31 FIR lattice structure. + * @param[in] numStages number of filter stages. + * @param[in] pCoeffs points to the coefficient buffer. The array is of length numStages. + * @param[in] pState points to the state buffer. The array is of length numStages. + */ + void arm_fir_lattice_init_q31( + arm_fir_lattice_instance_q31 * S, + uint16_t numStages, + q31_t * pCoeffs, + q31_t * pState); + + + /** + * @brief Processing function for the Q31 FIR lattice filter. + * @param[in] S points to an instance of the Q31 FIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_fir_lattice_q31( + const arm_fir_lattice_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + +/** + * @brief Initialization function for the floating-point FIR lattice filter. + * @param[in] S points to an instance of the floating-point FIR lattice structure. + * @param[in] numStages number of filter stages. + * @param[in] pCoeffs points to the coefficient buffer. The array is of length numStages. + * @param[in] pState points to the state buffer. The array is of length numStages. + */ + void arm_fir_lattice_init_f32( + arm_fir_lattice_instance_f32 * S, + uint16_t numStages, + float32_t * pCoeffs, + float32_t * pState); + + + /** + * @brief Processing function for the floating-point FIR lattice filter. + * @param[in] S points to an instance of the floating-point FIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_fir_lattice_f32( + const arm_fir_lattice_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q15 IIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of stages in the filter. */ + q15_t *pState; /**< points to the state variable array. The array is of length numStages+blockSize. */ + q15_t *pkCoeffs; /**< points to the reflection coefficient array. The array is of length numStages. */ + q15_t *pvCoeffs; /**< points to the ladder coefficient array. The array is of length numStages+1. */ + } arm_iir_lattice_instance_q15; + + /** + * @brief Instance structure for the Q31 IIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of stages in the filter. */ + q31_t *pState; /**< points to the state variable array. The array is of length numStages+blockSize. */ + q31_t *pkCoeffs; /**< points to the reflection coefficient array. The array is of length numStages. */ + q31_t *pvCoeffs; /**< points to the ladder coefficient array. The array is of length numStages+1. */ + } arm_iir_lattice_instance_q31; + + /** + * @brief Instance structure for the floating-point IIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of stages in the filter. */ + float32_t *pState; /**< points to the state variable array. The array is of length numStages+blockSize. */ + float32_t *pkCoeffs; /**< points to the reflection coefficient array. The array is of length numStages. */ + float32_t *pvCoeffs; /**< points to the ladder coefficient array. The array is of length numStages+1. */ + } arm_iir_lattice_instance_f32; + + + /** + * @brief Processing function for the floating-point IIR lattice filter. + * @param[in] S points to an instance of the floating-point IIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_iir_lattice_f32( + const arm_iir_lattice_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point IIR lattice filter. + * @param[in] S points to an instance of the floating-point IIR lattice structure. + * @param[in] numStages number of stages in the filter. + * @param[in] pkCoeffs points to the reflection coefficient buffer. The array is of length numStages. + * @param[in] pvCoeffs points to the ladder coefficient buffer. The array is of length numStages+1. + * @param[in] pState points to the state buffer. The array is of length numStages+blockSize-1. + * @param[in] blockSize number of samples to process. + */ + void arm_iir_lattice_init_f32( + arm_iir_lattice_instance_f32 * S, + uint16_t numStages, + float32_t * pkCoeffs, + float32_t * pvCoeffs, + float32_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 IIR lattice filter. + * @param[in] S points to an instance of the Q31 IIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_iir_lattice_q31( + const arm_iir_lattice_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 IIR lattice filter. + * @param[in] S points to an instance of the Q31 IIR lattice structure. + * @param[in] numStages number of stages in the filter. + * @param[in] pkCoeffs points to the reflection coefficient buffer. The array is of length numStages. + * @param[in] pvCoeffs points to the ladder coefficient buffer. The array is of length numStages+1. + * @param[in] pState points to the state buffer. The array is of length numStages+blockSize. + * @param[in] blockSize number of samples to process. + */ + void arm_iir_lattice_init_q31( + arm_iir_lattice_instance_q31 * S, + uint16_t numStages, + q31_t * pkCoeffs, + q31_t * pvCoeffs, + q31_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q15 IIR lattice filter. + * @param[in] S points to an instance of the Q15 IIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_iir_lattice_q15( + const arm_iir_lattice_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + +/** + * @brief Initialization function for the Q15 IIR lattice filter. + * @param[in] S points to an instance of the fixed-point Q15 IIR lattice structure. + * @param[in] numStages number of stages in the filter. + * @param[in] pkCoeffs points to reflection coefficient buffer. The array is of length numStages. + * @param[in] pvCoeffs points to ladder coefficient buffer. The array is of length numStages+1. + * @param[in] pState points to state buffer. The array is of length numStages+blockSize. + * @param[in] blockSize number of samples to process per call. + */ + void arm_iir_lattice_init_q15( + arm_iir_lattice_instance_q15 * S, + uint16_t numStages, + q15_t * pkCoeffs, + q15_t * pvCoeffs, + q15_t * pState, + uint32_t blockSize); + + + /** + * @brief Instance structure for the floating-point LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + float32_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + float32_t mu; /**< step size that controls filter coefficient updates. */ + } arm_lms_instance_f32; + + + /** + * @brief Processing function for floating-point LMS filter. + * @param[in] S points to an instance of the floating-point LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_f32( + const arm_lms_instance_f32 * S, + float32_t * pSrc, + float32_t * pRef, + float32_t * pOut, + float32_t * pErr, + uint32_t blockSize); + + + /** + * @brief Initialization function for floating-point LMS filter. + * @param[in] S points to an instance of the floating-point LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to the coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_init_f32( + arm_lms_instance_f32 * S, + uint16_t numTaps, + float32_t * pCoeffs, + float32_t * pState, + float32_t mu, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q15 LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + q15_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + q15_t mu; /**< step size that controls filter coefficient updates. */ + uint32_t postShift; /**< bit shift applied to coefficients. */ + } arm_lms_instance_q15; + + + /** + * @brief Initialization function for the Q15 LMS filter. + * @param[in] S points to an instance of the Q15 LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to the coefficient buffer. + * @param[in] pState points to the state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + * @param[in] postShift bit shift applied to coefficients. + */ + void arm_lms_init_q15( + arm_lms_instance_q15 * S, + uint16_t numTaps, + q15_t * pCoeffs, + q15_t * pState, + q15_t mu, + uint32_t blockSize, + uint32_t postShift); + + + /** + * @brief Processing function for Q15 LMS filter. + * @param[in] S points to an instance of the Q15 LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_q15( + const arm_lms_instance_q15 * S, + q15_t * pSrc, + q15_t * pRef, + q15_t * pOut, + q15_t * pErr, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q31 LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + q31_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + q31_t mu; /**< step size that controls filter coefficient updates. */ + uint32_t postShift; /**< bit shift applied to coefficients. */ + } arm_lms_instance_q31; + + + /** + * @brief Processing function for Q31 LMS filter. + * @param[in] S points to an instance of the Q15 LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_q31( + const arm_lms_instance_q31 * S, + q31_t * pSrc, + q31_t * pRef, + q31_t * pOut, + q31_t * pErr, + uint32_t blockSize); + + + /** + * @brief Initialization function for Q31 LMS filter. + * @param[in] S points to an instance of the Q31 LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + * @param[in] postShift bit shift applied to coefficients. + */ + void arm_lms_init_q31( + arm_lms_instance_q31 * S, + uint16_t numTaps, + q31_t * pCoeffs, + q31_t * pState, + q31_t mu, + uint32_t blockSize, + uint32_t postShift); + + + /** + * @brief Instance structure for the floating-point normalized LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + float32_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + float32_t mu; /**< step size that control filter coefficient updates. */ + float32_t energy; /**< saves previous frame energy. */ + float32_t x0; /**< saves previous input sample. */ + } arm_lms_norm_instance_f32; + + + /** + * @brief Processing function for floating-point normalized LMS filter. + * @param[in] S points to an instance of the floating-point normalized LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_norm_f32( + arm_lms_norm_instance_f32 * S, + float32_t * pSrc, + float32_t * pRef, + float32_t * pOut, + float32_t * pErr, + uint32_t blockSize); + + + /** + * @brief Initialization function for floating-point normalized LMS filter. + * @param[in] S points to an instance of the floating-point LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_norm_init_f32( + arm_lms_norm_instance_f32 * S, + uint16_t numTaps, + float32_t * pCoeffs, + float32_t * pState, + float32_t mu, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q31 normalized LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + q31_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + q31_t mu; /**< step size that controls filter coefficient updates. */ + uint8_t postShift; /**< bit shift applied to coefficients. */ + q31_t *recipTable; /**< points to the reciprocal initial value table. */ + q31_t energy; /**< saves previous frame energy. */ + q31_t x0; /**< saves previous input sample. */ + } arm_lms_norm_instance_q31; + + + /** + * @brief Processing function for Q31 normalized LMS filter. + * @param[in] S points to an instance of the Q31 normalized LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_norm_q31( + arm_lms_norm_instance_q31 * S, + q31_t * pSrc, + q31_t * pRef, + q31_t * pOut, + q31_t * pErr, + uint32_t blockSize); + + + /** + * @brief Initialization function for Q31 normalized LMS filter. + * @param[in] S points to an instance of the Q31 normalized LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + * @param[in] postShift bit shift applied to coefficients. + */ + void arm_lms_norm_init_q31( + arm_lms_norm_instance_q31 * S, + uint16_t numTaps, + q31_t * pCoeffs, + q31_t * pState, + q31_t mu, + uint32_t blockSize, + uint8_t postShift); + + + /** + * @brief Instance structure for the Q15 normalized LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< Number of coefficients in the filter. */ + q15_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + q15_t mu; /**< step size that controls filter coefficient updates. */ + uint8_t postShift; /**< bit shift applied to coefficients. */ + q15_t *recipTable; /**< Points to the reciprocal initial value table. */ + q15_t energy; /**< saves previous frame energy. */ + q15_t x0; /**< saves previous input sample. */ + } arm_lms_norm_instance_q15; + + + /** + * @brief Processing function for Q15 normalized LMS filter. + * @param[in] S points to an instance of the Q15 normalized LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_norm_q15( + arm_lms_norm_instance_q15 * S, + q15_t * pSrc, + q15_t * pRef, + q15_t * pOut, + q15_t * pErr, + uint32_t blockSize); + + + /** + * @brief Initialization function for Q15 normalized LMS filter. + * @param[in] S points to an instance of the Q15 normalized LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + * @param[in] postShift bit shift applied to coefficients. + */ + void arm_lms_norm_init_q15( + arm_lms_norm_instance_q15 * S, + uint16_t numTaps, + q15_t * pCoeffs, + q15_t * pState, + q15_t mu, + uint32_t blockSize, + uint8_t postShift); + + + /** + * @brief Correlation of floating-point sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + void arm_correlate_f32( + float32_t * pSrcA, + uint32_t srcALen, + float32_t * pSrcB, + uint32_t srcBLen, + float32_t * pDst); + + + /** + * @brief Correlation of Q15 sequences + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + * @param[in] pScratch points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + */ + void arm_correlate_opt_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + q15_t * pScratch); + + + /** + * @brief Correlation of Q15 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + + void arm_correlate_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst); + + + /** + * @brief Correlation of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + + void arm_correlate_fast_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst); + + + /** + * @brief Correlation of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + * @param[in] pScratch points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + */ + void arm_correlate_fast_opt_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + q15_t * pScratch); + + + /** + * @brief Correlation of Q31 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + void arm_correlate_q31( + q31_t * pSrcA, + uint32_t srcALen, + q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst); + + + /** + * @brief Correlation of Q31 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + void arm_correlate_fast_q31( + q31_t * pSrcA, + uint32_t srcALen, + q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst); + + + /** + * @brief Correlation of Q7 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + * @param[in] pScratch1 points to scratch buffer(of type q15_t) of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer (of type q15_t) of size min(srcALen, srcBLen). + */ + void arm_correlate_opt_q7( + q7_t * pSrcA, + uint32_t srcALen, + q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst, + q15_t * pScratch1, + q15_t * pScratch2); + + + /** + * @brief Correlation of Q7 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + void arm_correlate_q7( + q7_t * pSrcA, + uint32_t srcALen, + q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst); + + + /** + * @brief Instance structure for the floating-point sparse FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + uint16_t stateIndex; /**< state buffer index. Points to the oldest sample in the state buffer. */ + float32_t *pState; /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + uint16_t maxDelay; /**< maximum offset specified by the pTapDelay array. */ + int32_t *pTapDelay; /**< points to the array of delay values. The array is of length numTaps. */ + } arm_fir_sparse_instance_f32; + + /** + * @brief Instance structure for the Q31 sparse FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + uint16_t stateIndex; /**< state buffer index. Points to the oldest sample in the state buffer. */ + q31_t *pState; /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + uint16_t maxDelay; /**< maximum offset specified by the pTapDelay array. */ + int32_t *pTapDelay; /**< points to the array of delay values. The array is of length numTaps. */ + } arm_fir_sparse_instance_q31; + + /** + * @brief Instance structure for the Q15 sparse FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + uint16_t stateIndex; /**< state buffer index. Points to the oldest sample in the state buffer. */ + q15_t *pState; /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + uint16_t maxDelay; /**< maximum offset specified by the pTapDelay array. */ + int32_t *pTapDelay; /**< points to the array of delay values. The array is of length numTaps. */ + } arm_fir_sparse_instance_q15; + + /** + * @brief Instance structure for the Q7 sparse FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + uint16_t stateIndex; /**< state buffer index. Points to the oldest sample in the state buffer. */ + q7_t *pState; /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */ + q7_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + uint16_t maxDelay; /**< maximum offset specified by the pTapDelay array. */ + int32_t *pTapDelay; /**< points to the array of delay values. The array is of length numTaps. */ + } arm_fir_sparse_instance_q7; + + + /** + * @brief Processing function for the floating-point sparse FIR filter. + * @param[in] S points to an instance of the floating-point sparse FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] pScratchIn points to a temporary buffer of size blockSize. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_sparse_f32( + arm_fir_sparse_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + float32_t * pScratchIn, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point sparse FIR filter. + * @param[in,out] S points to an instance of the floating-point sparse FIR structure. + * @param[in] numTaps number of nonzero coefficients in the filter. + * @param[in] pCoeffs points to the array of filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] pTapDelay points to the array of offset times. + * @param[in] maxDelay maximum offset time supported. + * @param[in] blockSize number of samples that will be processed per block. + */ + void arm_fir_sparse_init_f32( + arm_fir_sparse_instance_f32 * S, + uint16_t numTaps, + float32_t * pCoeffs, + float32_t * pState, + int32_t * pTapDelay, + uint16_t maxDelay, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 sparse FIR filter. + * @param[in] S points to an instance of the Q31 sparse FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] pScratchIn points to a temporary buffer of size blockSize. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_sparse_q31( + arm_fir_sparse_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + q31_t * pScratchIn, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 sparse FIR filter. + * @param[in,out] S points to an instance of the Q31 sparse FIR structure. + * @param[in] numTaps number of nonzero coefficients in the filter. + * @param[in] pCoeffs points to the array of filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] pTapDelay points to the array of offset times. + * @param[in] maxDelay maximum offset time supported. + * @param[in] blockSize number of samples that will be processed per block. + */ + void arm_fir_sparse_init_q31( + arm_fir_sparse_instance_q31 * S, + uint16_t numTaps, + q31_t * pCoeffs, + q31_t * pState, + int32_t * pTapDelay, + uint16_t maxDelay, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q15 sparse FIR filter. + * @param[in] S points to an instance of the Q15 sparse FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] pScratchIn points to a temporary buffer of size blockSize. + * @param[in] pScratchOut points to a temporary buffer of size blockSize. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_sparse_q15( + arm_fir_sparse_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + q15_t * pScratchIn, + q31_t * pScratchOut, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q15 sparse FIR filter. + * @param[in,out] S points to an instance of the Q15 sparse FIR structure. + * @param[in] numTaps number of nonzero coefficients in the filter. + * @param[in] pCoeffs points to the array of filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] pTapDelay points to the array of offset times. + * @param[in] maxDelay maximum offset time supported. + * @param[in] blockSize number of samples that will be processed per block. + */ + void arm_fir_sparse_init_q15( + arm_fir_sparse_instance_q15 * S, + uint16_t numTaps, + q15_t * pCoeffs, + q15_t * pState, + int32_t * pTapDelay, + uint16_t maxDelay, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q7 sparse FIR filter. + * @param[in] S points to an instance of the Q7 sparse FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] pScratchIn points to a temporary buffer of size blockSize. + * @param[in] pScratchOut points to a temporary buffer of size blockSize. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_sparse_q7( + arm_fir_sparse_instance_q7 * S, + q7_t * pSrc, + q7_t * pDst, + q7_t * pScratchIn, + q31_t * pScratchOut, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q7 sparse FIR filter. + * @param[in,out] S points to an instance of the Q7 sparse FIR structure. + * @param[in] numTaps number of nonzero coefficients in the filter. + * @param[in] pCoeffs points to the array of filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] pTapDelay points to the array of offset times. + * @param[in] maxDelay maximum offset time supported. + * @param[in] blockSize number of samples that will be processed per block. + */ + void arm_fir_sparse_init_q7( + arm_fir_sparse_instance_q7 * S, + uint16_t numTaps, + q7_t * pCoeffs, + q7_t * pState, + int32_t * pTapDelay, + uint16_t maxDelay, + uint32_t blockSize); + + + /** + * @brief Floating-point sin_cos function. + * @param[in] theta input value in degrees + * @param[out] pSinVal points to the processed sine output. + * @param[out] pCosVal points to the processed cos output. + */ + void arm_sin_cos_f32( + float32_t theta, + float32_t * pSinVal, + float32_t * pCosVal); + + + /** + * @brief Q31 sin_cos function. + * @param[in] theta scaled input value in degrees + * @param[out] pSinVal points to the processed sine output. + * @param[out] pCosVal points to the processed cosine output. + */ + void arm_sin_cos_q31( + q31_t theta, + q31_t * pSinVal, + q31_t * pCosVal); + + + /** + * @brief Floating-point complex conjugate. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_conj_f32( + float32_t * pSrc, + float32_t * pDst, + uint32_t numSamples); + + /** + * @brief Q31 complex conjugate. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_conj_q31( + q31_t * pSrc, + q31_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q15 complex conjugate. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_conj_q15( + q15_t * pSrc, + q15_t * pDst, + uint32_t numSamples); + + + /** + * @brief Floating-point complex magnitude squared + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_squared_f32( + float32_t * pSrc, + float32_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q31 complex magnitude squared + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_squared_q31( + q31_t * pSrc, + q31_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q15 complex magnitude squared + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_squared_q15( + q15_t * pSrc, + q15_t * pDst, + uint32_t numSamples); + + + /** + * @ingroup groupController + */ + + /** + * @defgroup PID PID Motor Control + * + * A Proportional Integral Derivative (PID) controller is a generic feedback control + * loop mechanism widely used in industrial control systems. + * A PID controller is the most commonly used type of feedback controller. + * + * This set of functions implements (PID) controllers + * for Q15, Q31, and floating-point data types. The functions operate on a single sample + * of data and each call to the function returns a single processed value. + * S points to an instance of the PID control data structure. in + * is the input sample value. The functions return the output value. + * + * \par Algorithm: + *
    +   *    y[n] = y[n-1] + A0 * x[n] + A1 * x[n-1] + A2 * x[n-2]
    +   *    A0 = Kp + Ki + Kd
    +   *    A1 = (-Kp ) - (2 * Kd )
    +   *    A2 = Kd  
    + * + * \par + * where \c Kp is proportional constant, \c Ki is Integral constant and \c Kd is Derivative constant + * + * \par + * \image html PID.gif "Proportional Integral Derivative Controller" + * + * \par + * The PID controller calculates an "error" value as the difference between + * the measured output and the reference input. + * The controller attempts to minimize the error by adjusting the process control inputs. + * The proportional value determines the reaction to the current error, + * the integral value determines the reaction based on the sum of recent errors, + * and the derivative value determines the reaction based on the rate at which the error has been changing. + * + * \par Instance Structure + * The Gains A0, A1, A2 and state variables for a PID controller are stored together in an instance data structure. + * A separate instance structure must be defined for each PID Controller. + * There are separate instance structure declarations for each of the 3 supported data types. + * + * \par Reset Functions + * There is also an associated reset function for each data type which clears the state array. + * + * \par Initialization Functions + * There is also an associated initialization function for each data type. + * The initialization function performs the following operations: + * - Initializes the Gains A0, A1, A2 from Kp,Ki, Kd gains. + * - Zeros out the values in the state buffer. + * + * \par + * Instance structure cannot be placed into a const data section and it is recommended to use the initialization function. + * + * \par Fixed-Point Behavior + * Care must be taken when using the fixed-point versions of the PID Controller functions. + * In particular, the overflow and saturation behavior of the accumulator used in each function must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ + + /** + * @addtogroup PID + * @{ + */ + + /** + * @brief Process function for the floating-point PID Control. + * @param[in,out] S is an instance of the floating-point PID Control structure + * @param[in] in input sample to process + * @return out processed output sample. + */ + static __INLINE float32_t arm_pid_f32( + arm_pid_instance_f32 * S, + float32_t in) + { + float32_t out; + + /* y[n] = y[n-1] + A0 * x[n] + A1 * x[n-1] + A2 * x[n-2] */ + out = (S->A0 * in) + + (S->A1 * S->state[0]) + (S->A2 * S->state[1]) + (S->state[2]); + + /* Update state */ + S->state[1] = S->state[0]; + S->state[0] = in; + S->state[2] = out; + + /* return to application */ + return (out); + + } + + /** + * @brief Process function for the Q31 PID Control. + * @param[in,out] S points to an instance of the Q31 PID Control structure + * @param[in] in input sample to process + * @return out processed output sample. + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using an internal 64-bit accumulator. + * The accumulator has a 2.62 format and maintains full precision of the intermediate multiplication results but provides only a single guard bit. + * Thus, if the accumulator result overflows it wraps around rather than clip. + * In order to avoid overflows completely the input signal must be scaled down by 2 bits as there are four additions. + * After all multiply-accumulates are performed, the 2.62 accumulator is truncated to 1.32 format and then saturated to 1.31 format. + */ + static __INLINE q31_t arm_pid_q31( + arm_pid_instance_q31 * S, + q31_t in) + { + q63_t acc; + q31_t out; + + /* acc = A0 * x[n] */ + acc = (q63_t) S->A0 * in; + + /* acc += A1 * x[n-1] */ + acc += (q63_t) S->A1 * S->state[0]; + + /* acc += A2 * x[n-2] */ + acc += (q63_t) S->A2 * S->state[1]; + + /* convert output to 1.31 format to add y[n-1] */ + out = (q31_t) (acc >> 31u); + + /* out += y[n-1] */ + out += S->state[2]; + + /* Update state */ + S->state[1] = S->state[0]; + S->state[0] = in; + S->state[2] = out; + + /* return to application */ + return (out); + } + + + /** + * @brief Process function for the Q15 PID Control. + * @param[in,out] S points to an instance of the Q15 PID Control structure + * @param[in] in input sample to process + * @return out processed output sample. + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using a 64-bit internal accumulator. + * Both Gains and state variables are represented in 1.15 format and multiplications yield a 2.30 result. + * The 2.30 intermediate results are accumulated in a 64-bit accumulator in 34.30 format. + * There is no risk of internal overflow with this approach and the full precision of intermediate multiplications is preserved. + * After all additions have been performed, the accumulator is truncated to 34.15 format by discarding low 15 bits. + * Lastly, the accumulator is saturated to yield a result in 1.15 format. + */ + static __INLINE q15_t arm_pid_q15( + arm_pid_instance_q15 * S, + q15_t in) + { + q63_t acc; + q15_t out; + +#ifndef ARM_MATH_CM0_FAMILY + __SIMD32_TYPE *vstate; + + /* Implementation of PID controller */ + + /* acc = A0 * x[n] */ + acc = (q31_t) __SMUAD((uint32_t)S->A0, (uint32_t)in); + + /* acc += A1 * x[n-1] + A2 * x[n-2] */ + vstate = __SIMD32_CONST(S->state); + acc = (q63_t)__SMLALD((uint32_t)S->A1, (uint32_t)*vstate, (uint64_t)acc); +#else + /* acc = A0 * x[n] */ + acc = ((q31_t) S->A0) * in; + + /* acc += A1 * x[n-1] + A2 * x[n-2] */ + acc += (q31_t) S->A1 * S->state[0]; + acc += (q31_t) S->A2 * S->state[1]; +#endif + + /* acc += y[n-1] */ + acc += (q31_t) S->state[2] << 15; + + /* saturate the output */ + out = (q15_t) (__SSAT((acc >> 15), 16)); + + /* Update state */ + S->state[1] = S->state[0]; + S->state[0] = in; + S->state[2] = out; + + /* return to application */ + return (out); + } + + /** + * @} end of PID group + */ + + + /** + * @brief Floating-point matrix inverse. + * @param[in] src points to the instance of the input floating-point matrix structure. + * @param[out] dst points to the instance of the output floating-point matrix structure. + * @return The function returns ARM_MATH_SIZE_MISMATCH, if the dimensions do not match. + * If the input matrix is singular (does not have an inverse), then the algorithm terminates and returns error status ARM_MATH_SINGULAR. + */ + arm_status arm_mat_inverse_f32( + const arm_matrix_instance_f32 * src, + arm_matrix_instance_f32 * dst); + + + /** + * @brief Floating-point matrix inverse. + * @param[in] src points to the instance of the input floating-point matrix structure. + * @param[out] dst points to the instance of the output floating-point matrix structure. + * @return The function returns ARM_MATH_SIZE_MISMATCH, if the dimensions do not match. + * If the input matrix is singular (does not have an inverse), then the algorithm terminates and returns error status ARM_MATH_SINGULAR. + */ + arm_status arm_mat_inverse_f64( + const arm_matrix_instance_f64 * src, + arm_matrix_instance_f64 * dst); + + + + /** + * @ingroup groupController + */ + + /** + * @defgroup clarke Vector Clarke Transform + * Forward Clarke transform converts the instantaneous stator phases into a two-coordinate time invariant vector. + * Generally the Clarke transform uses three-phase currents Ia, Ib and Ic to calculate currents + * in the two-phase orthogonal stator axis Ialpha and Ibeta. + * When Ialpha is superposed with Ia as shown in the figure below + * \image html clarke.gif Stator current space vector and its components in (a,b). + * and Ia + Ib + Ic = 0, in this condition Ialpha and Ibeta + * can be calculated using only Ia and Ib. + * + * The function operates on a single sample of data and each call to the function returns the processed output. + * The library provides separate functions for Q31 and floating-point data types. + * \par Algorithm + * \image html clarkeFormula.gif + * where Ia and Ib are the instantaneous stator phases and + * pIalpha and pIbeta are the two coordinates of time invariant vector. + * \par Fixed-Point Behavior + * Care must be taken when using the Q31 version of the Clarke transform. + * In particular, the overflow and saturation behavior of the accumulator used must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ + + /** + * @addtogroup clarke + * @{ + */ + + /** + * + * @brief Floating-point Clarke transform + * @param[in] Ia input three-phase coordinate a + * @param[in] Ib input three-phase coordinate b + * @param[out] pIalpha points to output two-phase orthogonal vector axis alpha + * @param[out] pIbeta points to output two-phase orthogonal vector axis beta + */ + static __INLINE void arm_clarke_f32( + float32_t Ia, + float32_t Ib, + float32_t * pIalpha, + float32_t * pIbeta) + { + /* Calculate pIalpha using the equation, pIalpha = Ia */ + *pIalpha = Ia; + + /* Calculate pIbeta using the equation, pIbeta = (1/sqrt(3)) * Ia + (2/sqrt(3)) * Ib */ + *pIbeta = ((float32_t) 0.57735026919 * Ia + (float32_t) 1.15470053838 * Ib); + } + + + /** + * @brief Clarke transform for Q31 version + * @param[in] Ia input three-phase coordinate a + * @param[in] Ib input three-phase coordinate b + * @param[out] pIalpha points to output two-phase orthogonal vector axis alpha + * @param[out] pIbeta points to output two-phase orthogonal vector axis beta + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using an internal 32-bit accumulator. + * The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format. + * There is saturation on the addition, hence there is no risk of overflow. + */ + static __INLINE void arm_clarke_q31( + q31_t Ia, + q31_t Ib, + q31_t * pIalpha, + q31_t * pIbeta) + { + q31_t product1, product2; /* Temporary variables used to store intermediate results */ + + /* Calculating pIalpha from Ia by equation pIalpha = Ia */ + *pIalpha = Ia; + + /* Intermediate product is calculated by (1/(sqrt(3)) * Ia) */ + product1 = (q31_t) (((q63_t) Ia * 0x24F34E8B) >> 30); + + /* Intermediate product is calculated by (2/sqrt(3) * Ib) */ + product2 = (q31_t) (((q63_t) Ib * 0x49E69D16) >> 30); + + /* pIbeta is calculated by adding the intermediate products */ + *pIbeta = __QADD(product1, product2); + } + + /** + * @} end of clarke group + */ + + /** + * @brief Converts the elements of the Q7 vector to Q31 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_q7_to_q31( + q7_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + + /** + * @ingroup groupController + */ + + /** + * @defgroup inv_clarke Vector Inverse Clarke Transform + * Inverse Clarke transform converts the two-coordinate time invariant vector into instantaneous stator phases. + * + * The function operates on a single sample of data and each call to the function returns the processed output. + * The library provides separate functions for Q31 and floating-point data types. + * \par Algorithm + * \image html clarkeInvFormula.gif + * where pIa and pIb are the instantaneous stator phases and + * Ialpha and Ibeta are the two coordinates of time invariant vector. + * \par Fixed-Point Behavior + * Care must be taken when using the Q31 version of the Clarke transform. + * In particular, the overflow and saturation behavior of the accumulator used must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ + + /** + * @addtogroup inv_clarke + * @{ + */ + + /** + * @brief Floating-point Inverse Clarke transform + * @param[in] Ialpha input two-phase orthogonal vector axis alpha + * @param[in] Ibeta input two-phase orthogonal vector axis beta + * @param[out] pIa points to output three-phase coordinate a + * @param[out] pIb points to output three-phase coordinate b + */ + static __INLINE void arm_inv_clarke_f32( + float32_t Ialpha, + float32_t Ibeta, + float32_t * pIa, + float32_t * pIb) + { + /* Calculating pIa from Ialpha by equation pIa = Ialpha */ + *pIa = Ialpha; + + /* Calculating pIb from Ialpha and Ibeta by equation pIb = -(1/2) * Ialpha + (sqrt(3)/2) * Ibeta */ + *pIb = -0.5f * Ialpha + 0.8660254039f * Ibeta; + } + + + /** + * @brief Inverse Clarke transform for Q31 version + * @param[in] Ialpha input two-phase orthogonal vector axis alpha + * @param[in] Ibeta input two-phase orthogonal vector axis beta + * @param[out] pIa points to output three-phase coordinate a + * @param[out] pIb points to output three-phase coordinate b + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using an internal 32-bit accumulator. + * The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format. + * There is saturation on the subtraction, hence there is no risk of overflow. + */ + static __INLINE void arm_inv_clarke_q31( + q31_t Ialpha, + q31_t Ibeta, + q31_t * pIa, + q31_t * pIb) + { + q31_t product1, product2; /* Temporary variables used to store intermediate results */ + + /* Calculating pIa from Ialpha by equation pIa = Ialpha */ + *pIa = Ialpha; + + /* Intermediate product is calculated by (1/(2*sqrt(3)) * Ia) */ + product1 = (q31_t) (((q63_t) (Ialpha) * (0x40000000)) >> 31); + + /* Intermediate product is calculated by (1/sqrt(3) * pIb) */ + product2 = (q31_t) (((q63_t) (Ibeta) * (0x6ED9EBA1)) >> 31); + + /* pIb is calculated by subtracting the products */ + *pIb = __QSUB(product2, product1); + } + + /** + * @} end of inv_clarke group + */ + + /** + * @brief Converts the elements of the Q7 vector to Q15 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_q7_to_q15( + q7_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + + /** + * @ingroup groupController + */ + + /** + * @defgroup park Vector Park Transform + * + * Forward Park transform converts the input two-coordinate vector to flux and torque components. + * The Park transform can be used to realize the transformation of the Ialpha and the Ibeta currents + * from the stationary to the moving reference frame and control the spatial relationship between + * the stator vector current and rotor flux vector. + * If we consider the d axis aligned with the rotor flux, the diagram below shows the + * current vector and the relationship from the two reference frames: + * \image html park.gif "Stator current space vector and its component in (a,b) and in the d,q rotating reference frame" + * + * The function operates on a single sample of data and each call to the function returns the processed output. + * The library provides separate functions for Q31 and floating-point data types. + * \par Algorithm + * \image html parkFormula.gif + * where Ialpha and Ibeta are the stator vector components, + * pId and pIq are rotor vector components and cosVal and sinVal are the + * cosine and sine values of theta (rotor flux position). + * \par Fixed-Point Behavior + * Care must be taken when using the Q31 version of the Park transform. + * In particular, the overflow and saturation behavior of the accumulator used must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ + + /** + * @addtogroup park + * @{ + */ + + /** + * @brief Floating-point Park transform + * @param[in] Ialpha input two-phase vector coordinate alpha + * @param[in] Ibeta input two-phase vector coordinate beta + * @param[out] pId points to output rotor reference frame d + * @param[out] pIq points to output rotor reference frame q + * @param[in] sinVal sine value of rotation angle theta + * @param[in] cosVal cosine value of rotation angle theta + * + * The function implements the forward Park transform. + * + */ + static __INLINE void arm_park_f32( + float32_t Ialpha, + float32_t Ibeta, + float32_t * pId, + float32_t * pIq, + float32_t sinVal, + float32_t cosVal) + { + /* Calculate pId using the equation, pId = Ialpha * cosVal + Ibeta * sinVal */ + *pId = Ialpha * cosVal + Ibeta * sinVal; + + /* Calculate pIq using the equation, pIq = - Ialpha * sinVal + Ibeta * cosVal */ + *pIq = -Ialpha * sinVal + Ibeta * cosVal; + } + + + /** + * @brief Park transform for Q31 version + * @param[in] Ialpha input two-phase vector coordinate alpha + * @param[in] Ibeta input two-phase vector coordinate beta + * @param[out] pId points to output rotor reference frame d + * @param[out] pIq points to output rotor reference frame q + * @param[in] sinVal sine value of rotation angle theta + * @param[in] cosVal cosine value of rotation angle theta + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using an internal 32-bit accumulator. + * The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format. + * There is saturation on the addition and subtraction, hence there is no risk of overflow. + */ + static __INLINE void arm_park_q31( + q31_t Ialpha, + q31_t Ibeta, + q31_t * pId, + q31_t * pIq, + q31_t sinVal, + q31_t cosVal) + { + q31_t product1, product2; /* Temporary variables used to store intermediate results */ + q31_t product3, product4; /* Temporary variables used to store intermediate results */ + + /* Intermediate product is calculated by (Ialpha * cosVal) */ + product1 = (q31_t) (((q63_t) (Ialpha) * (cosVal)) >> 31); + + /* Intermediate product is calculated by (Ibeta * sinVal) */ + product2 = (q31_t) (((q63_t) (Ibeta) * (sinVal)) >> 31); + + + /* Intermediate product is calculated by (Ialpha * sinVal) */ + product3 = (q31_t) (((q63_t) (Ialpha) * (sinVal)) >> 31); + + /* Intermediate product is calculated by (Ibeta * cosVal) */ + product4 = (q31_t) (((q63_t) (Ibeta) * (cosVal)) >> 31); + + /* Calculate pId by adding the two intermediate products 1 and 2 */ + *pId = __QADD(product1, product2); + + /* Calculate pIq by subtracting the two intermediate products 3 from 4 */ + *pIq = __QSUB(product4, product3); + } + + /** + * @} end of park group + */ + + /** + * @brief Converts the elements of the Q7 vector to floating-point vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q7_to_float( + q7_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @ingroup groupController + */ + + /** + * @defgroup inv_park Vector Inverse Park transform + * Inverse Park transform converts the input flux and torque components to two-coordinate vector. + * + * The function operates on a single sample of data and each call to the function returns the processed output. + * The library provides separate functions for Q31 and floating-point data types. + * \par Algorithm + * \image html parkInvFormula.gif + * where pIalpha and pIbeta are the stator vector components, + * Id and Iq are rotor vector components and cosVal and sinVal are the + * cosine and sine values of theta (rotor flux position). + * \par Fixed-Point Behavior + * Care must be taken when using the Q31 version of the Park transform. + * In particular, the overflow and saturation behavior of the accumulator used must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ + + /** + * @addtogroup inv_park + * @{ + */ + + /** + * @brief Floating-point Inverse Park transform + * @param[in] Id input coordinate of rotor reference frame d + * @param[in] Iq input coordinate of rotor reference frame q + * @param[out] pIalpha points to output two-phase orthogonal vector axis alpha + * @param[out] pIbeta points to output two-phase orthogonal vector axis beta + * @param[in] sinVal sine value of rotation angle theta + * @param[in] cosVal cosine value of rotation angle theta + */ + static __INLINE void arm_inv_park_f32( + float32_t Id, + float32_t Iq, + float32_t * pIalpha, + float32_t * pIbeta, + float32_t sinVal, + float32_t cosVal) + { + /* Calculate pIalpha using the equation, pIalpha = Id * cosVal - Iq * sinVal */ + *pIalpha = Id * cosVal - Iq * sinVal; + + /* Calculate pIbeta using the equation, pIbeta = Id * sinVal + Iq * cosVal */ + *pIbeta = Id * sinVal + Iq * cosVal; + } + + + /** + * @brief Inverse Park transform for Q31 version + * @param[in] Id input coordinate of rotor reference frame d + * @param[in] Iq input coordinate of rotor reference frame q + * @param[out] pIalpha points to output two-phase orthogonal vector axis alpha + * @param[out] pIbeta points to output two-phase orthogonal vector axis beta + * @param[in] sinVal sine value of rotation angle theta + * @param[in] cosVal cosine value of rotation angle theta + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using an internal 32-bit accumulator. + * The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format. + * There is saturation on the addition, hence there is no risk of overflow. + */ + static __INLINE void arm_inv_park_q31( + q31_t Id, + q31_t Iq, + q31_t * pIalpha, + q31_t * pIbeta, + q31_t sinVal, + q31_t cosVal) + { + q31_t product1, product2; /* Temporary variables used to store intermediate results */ + q31_t product3, product4; /* Temporary variables used to store intermediate results */ + + /* Intermediate product is calculated by (Id * cosVal) */ + product1 = (q31_t) (((q63_t) (Id) * (cosVal)) >> 31); + + /* Intermediate product is calculated by (Iq * sinVal) */ + product2 = (q31_t) (((q63_t) (Iq) * (sinVal)) >> 31); + + + /* Intermediate product is calculated by (Id * sinVal) */ + product3 = (q31_t) (((q63_t) (Id) * (sinVal)) >> 31); + + /* Intermediate product is calculated by (Iq * cosVal) */ + product4 = (q31_t) (((q63_t) (Iq) * (cosVal)) >> 31); + + /* Calculate pIalpha by using the two intermediate products 1 and 2 */ + *pIalpha = __QSUB(product1, product2); + + /* Calculate pIbeta by using the two intermediate products 3 and 4 */ + *pIbeta = __QADD(product4, product3); + } + + /** + * @} end of Inverse park group + */ + + + /** + * @brief Converts the elements of the Q31 vector to floating-point vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q31_to_float( + q31_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + /** + * @ingroup groupInterpolation + */ + + /** + * @defgroup LinearInterpolate Linear Interpolation + * + * Linear interpolation is a method of curve fitting using linear polynomials. + * Linear interpolation works by effectively drawing a straight line between two neighboring samples and returning the appropriate point along that line + * + * \par + * \image html LinearInterp.gif "Linear interpolation" + * + * \par + * A Linear Interpolate function calculates an output value(y), for the input(x) + * using linear interpolation of the input values x0, x1( nearest input values) and the output values y0 and y1(nearest output values) + * + * \par Algorithm: + *
    +   *       y = y0 + (x - x0) * ((y1 - y0)/(x1-x0))
    +   *       where x0, x1 are nearest values of input x
    +   *             y0, y1 are nearest values to output y
    +   * 
    + * + * \par + * This set of functions implements Linear interpolation process + * for Q7, Q15, Q31, and floating-point data types. The functions operate on a single + * sample of data and each call to the function returns a single processed value. + * S points to an instance of the Linear Interpolate function data structure. + * x is the input sample value. The functions returns the output value. + * + * \par + * if x is outside of the table boundary, Linear interpolation returns first value of the table + * if x is below input range and returns last value of table if x is above range. + */ + + /** + * @addtogroup LinearInterpolate + * @{ + */ + + /** + * @brief Process function for the floating-point Linear Interpolation Function. + * @param[in,out] S is an instance of the floating-point Linear Interpolation structure + * @param[in] x input sample to process + * @return y processed output sample. + * + */ + static __INLINE float32_t arm_linear_interp_f32( + arm_linear_interp_instance_f32 * S, + float32_t x) + { + float32_t y; + float32_t x0, x1; /* Nearest input values */ + float32_t y0, y1; /* Nearest output values */ + float32_t xSpacing = S->xSpacing; /* spacing between input values */ + int32_t i; /* Index variable */ + float32_t *pYData = S->pYData; /* pointer to output table */ + + /* Calculation of index */ + i = (int32_t) ((x - S->x1) / xSpacing); + + if(i < 0) + { + /* Iniatilize output for below specified range as least output value of table */ + y = pYData[0]; + } + else if((uint32_t)i >= S->nValues) + { + /* Iniatilize output for above specified range as last output value of table */ + y = pYData[S->nValues - 1]; + } + else + { + /* Calculation of nearest input values */ + x0 = S->x1 + i * xSpacing; + x1 = S->x1 + (i + 1) * xSpacing; + + /* Read of nearest output values */ + y0 = pYData[i]; + y1 = pYData[i + 1]; + + /* Calculation of output */ + y = y0 + (x - x0) * ((y1 - y0) / (x1 - x0)); + + } + + /* returns output value */ + return (y); + } + + + /** + * + * @brief Process function for the Q31 Linear Interpolation Function. + * @param[in] pYData pointer to Q31 Linear Interpolation table + * @param[in] x input sample to process + * @param[in] nValues number of table values + * @return y processed output sample. + * + * \par + * Input sample x is in 12.20 format which contains 12 bits for table index and 20 bits for fractional part. + * This function can support maximum of table size 2^12. + * + */ + static __INLINE q31_t arm_linear_interp_q31( + q31_t * pYData, + q31_t x, + uint32_t nValues) + { + q31_t y; /* output */ + q31_t y0, y1; /* Nearest output values */ + q31_t fract; /* fractional part */ + int32_t index; /* Index to read nearest output values */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + index = ((x & (q31_t)0xFFF00000) >> 20); + + if(index >= (int32_t)(nValues - 1)) + { + return (pYData[nValues - 1]); + } + else if(index < 0) + { + return (pYData[0]); + } + else + { + /* 20 bits for the fractional part */ + /* shift left by 11 to keep fract in 1.31 format */ + fract = (x & 0x000FFFFF) << 11; + + /* Read two nearest output values from the index in 1.31(q31) format */ + y0 = pYData[index]; + y1 = pYData[index + 1]; + + /* Calculation of y0 * (1-fract) and y is in 2.30 format */ + y = ((q31_t) ((q63_t) y0 * (0x7FFFFFFF - fract) >> 32)); + + /* Calculation of y0 * (1-fract) + y1 *fract and y is in 2.30 format */ + y += ((q31_t) (((q63_t) y1 * fract) >> 32)); + + /* Convert y to 1.31 format */ + return (y << 1u); + } + } + + + /** + * + * @brief Process function for the Q15 Linear Interpolation Function. + * @param[in] pYData pointer to Q15 Linear Interpolation table + * @param[in] x input sample to process + * @param[in] nValues number of table values + * @return y processed output sample. + * + * \par + * Input sample x is in 12.20 format which contains 12 bits for table index and 20 bits for fractional part. + * This function can support maximum of table size 2^12. + * + */ + static __INLINE q15_t arm_linear_interp_q15( + q15_t * pYData, + q31_t x, + uint32_t nValues) + { + q63_t y; /* output */ + q15_t y0, y1; /* Nearest output values */ + q31_t fract; /* fractional part */ + int32_t index; /* Index to read nearest output values */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + index = ((x & (int32_t)0xFFF00000) >> 20); + + if(index >= (int32_t)(nValues - 1)) + { + return (pYData[nValues - 1]); + } + else if(index < 0) + { + return (pYData[0]); + } + else + { + /* 20 bits for the fractional part */ + /* fract is in 12.20 format */ + fract = (x & 0x000FFFFF); + + /* Read two nearest output values from the index */ + y0 = pYData[index]; + y1 = pYData[index + 1]; + + /* Calculation of y0 * (1-fract) and y is in 13.35 format */ + y = ((q63_t) y0 * (0xFFFFF - fract)); + + /* Calculation of (y0 * (1-fract) + y1 * fract) and y is in 13.35 format */ + y += ((q63_t) y1 * (fract)); + + /* convert y to 1.15 format */ + return (q15_t) (y >> 20); + } + } + + + /** + * + * @brief Process function for the Q7 Linear Interpolation Function. + * @param[in] pYData pointer to Q7 Linear Interpolation table + * @param[in] x input sample to process + * @param[in] nValues number of table values + * @return y processed output sample. + * + * \par + * Input sample x is in 12.20 format which contains 12 bits for table index and 20 bits for fractional part. + * This function can support maximum of table size 2^12. + */ + static __INLINE q7_t arm_linear_interp_q7( + q7_t * pYData, + q31_t x, + uint32_t nValues) + { + q31_t y; /* output */ + q7_t y0, y1; /* Nearest output values */ + q31_t fract; /* fractional part */ + uint32_t index; /* Index to read nearest output values */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + if (x < 0) + { + return (pYData[0]); + } + index = (x >> 20) & 0xfff; + + if(index >= (nValues - 1)) + { + return (pYData[nValues - 1]); + } + else + { + /* 20 bits for the fractional part */ + /* fract is in 12.20 format */ + fract = (x & 0x000FFFFF); + + /* Read two nearest output values from the index and are in 1.7(q7) format */ + y0 = pYData[index]; + y1 = pYData[index + 1]; + + /* Calculation of y0 * (1-fract ) and y is in 13.27(q27) format */ + y = ((y0 * (0xFFFFF - fract))); + + /* Calculation of y1 * fract + y0 * (1-fract) and y is in 13.27(q27) format */ + y += (y1 * fract); + + /* convert y to 1.7(q7) format */ + return (q7_t) (y >> 20); + } + } + + /** + * @} end of LinearInterpolate group + */ + + /** + * @brief Fast approximation to the trigonometric sine function for floating-point data. + * @param[in] x input value in radians. + * @return sin(x). + */ + float32_t arm_sin_f32( + float32_t x); + + + /** + * @brief Fast approximation to the trigonometric sine function for Q31 data. + * @param[in] x Scaled input value in radians. + * @return sin(x). + */ + q31_t arm_sin_q31( + q31_t x); + + + /** + * @brief Fast approximation to the trigonometric sine function for Q15 data. + * @param[in] x Scaled input value in radians. + * @return sin(x). + */ + q15_t arm_sin_q15( + q15_t x); + + + /** + * @brief Fast approximation to the trigonometric cosine function for floating-point data. + * @param[in] x input value in radians. + * @return cos(x). + */ + float32_t arm_cos_f32( + float32_t x); + + + /** + * @brief Fast approximation to the trigonometric cosine function for Q31 data. + * @param[in] x Scaled input value in radians. + * @return cos(x). + */ + q31_t arm_cos_q31( + q31_t x); + + + /** + * @brief Fast approximation to the trigonometric cosine function for Q15 data. + * @param[in] x Scaled input value in radians. + * @return cos(x). + */ + q15_t arm_cos_q15( + q15_t x); + + + /** + * @ingroup groupFastMath + */ + + + /** + * @defgroup SQRT Square Root + * + * Computes the square root of a number. + * There are separate functions for Q15, Q31, and floating-point data types. + * The square root function is computed using the Newton-Raphson algorithm. + * This is an iterative algorithm of the form: + *
    +   *      x1 = x0 - f(x0)/f'(x0)
    +   * 
    + * where x1 is the current estimate, + * x0 is the previous estimate, and + * f'(x0) is the derivative of f() evaluated at x0. + * For the square root function, the algorithm reduces to: + *
    +   *     x0 = in/2                         [initial guess]
    +   *     x1 = 1/2 * ( x0 + in / x0)        [each iteration]
    +   * 
    + */ + + + /** + * @addtogroup SQRT + * @{ + */ + + /** + * @brief Floating-point square root function. + * @param[in] in input value. + * @param[out] pOut square root of input value. + * @return The function returns ARM_MATH_SUCCESS if input value is positive value or ARM_MATH_ARGUMENT_ERROR if + * in is negative value and returns zero output for negative values. + */ + static __INLINE arm_status arm_sqrt_f32( + float32_t in, + float32_t * pOut) + { + if(in >= 0.0f) + { + +#if (__FPU_USED == 1) && defined ( __CC_ARM ) + *pOut = __sqrtf(in); +#elif (__FPU_USED == 1) && (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)) + *pOut = __builtin_sqrtf(in); +#elif (__FPU_USED == 1) && defined(__GNUC__) + *pOut = __builtin_sqrtf(in); +#elif (__FPU_USED == 1) && defined ( __ICCARM__ ) && (__VER__ >= 6040000) + __ASM("VSQRT.F32 %0,%1" : "=t"(*pOut) : "t"(in)); +#else + *pOut = sqrtf(in); +#endif + + return (ARM_MATH_SUCCESS); + } + else + { + *pOut = 0.0f; + return (ARM_MATH_ARGUMENT_ERROR); + } + } + + + /** + * @brief Q31 square root function. + * @param[in] in input value. The range of the input value is [0 +1) or 0x00000000 to 0x7FFFFFFF. + * @param[out] pOut square root of input value. + * @return The function returns ARM_MATH_SUCCESS if input value is positive value or ARM_MATH_ARGUMENT_ERROR if + * in is negative value and returns zero output for negative values. + */ + arm_status arm_sqrt_q31( + q31_t in, + q31_t * pOut); + + + /** + * @brief Q15 square root function. + * @param[in] in input value. The range of the input value is [0 +1) or 0x0000 to 0x7FFF. + * @param[out] pOut square root of input value. + * @return The function returns ARM_MATH_SUCCESS if input value is positive value or ARM_MATH_ARGUMENT_ERROR if + * in is negative value and returns zero output for negative values. + */ + arm_status arm_sqrt_q15( + q15_t in, + q15_t * pOut); + + /** + * @} end of SQRT group + */ + + + /** + * @brief floating-point Circular write function. + */ + static __INLINE void arm_circularWrite_f32( + int32_t * circBuffer, + int32_t L, + uint16_t * writeOffset, + int32_t bufferInc, + const int32_t * src, + int32_t srcInc, + uint32_t blockSize) + { + uint32_t i = 0u; + int32_t wOffset; + + /* Copy the value of Index pointer that points + * to the current location where the input samples to be copied */ + wOffset = *writeOffset; + + /* Loop over the blockSize */ + i = blockSize; + + while(i > 0u) + { + /* copy the input sample to the circular buffer */ + circBuffer[wOffset] = *src; + + /* Update the input pointer */ + src += srcInc; + + /* Circularly update wOffset. Watch out for positive and negative value */ + wOffset += bufferInc; + if(wOffset >= L) + wOffset -= L; + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *writeOffset = (uint16_t)wOffset; + } + + + + /** + * @brief floating-point Circular Read function. + */ + static __INLINE void arm_circularRead_f32( + int32_t * circBuffer, + int32_t L, + int32_t * readOffset, + int32_t bufferInc, + int32_t * dst, + int32_t * dst_base, + int32_t dst_length, + int32_t dstInc, + uint32_t blockSize) + { + uint32_t i = 0u; + int32_t rOffset, dst_end; + + /* Copy the value of Index pointer that points + * to the current location from where the input samples to be read */ + rOffset = *readOffset; + dst_end = (int32_t) (dst_base + dst_length); + + /* Loop over the blockSize */ + i = blockSize; + + while(i > 0u) + { + /* copy the sample from the circular buffer to the destination buffer */ + *dst = circBuffer[rOffset]; + + /* Update the input pointer */ + dst += dstInc; + + if(dst == (int32_t *) dst_end) + { + dst = dst_base; + } + + /* Circularly update rOffset. Watch out for positive and negative value */ + rOffset += bufferInc; + + if(rOffset >= L) + { + rOffset -= L; + } + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *readOffset = rOffset; + } + + + /** + * @brief Q15 Circular write function. + */ + static __INLINE void arm_circularWrite_q15( + q15_t * circBuffer, + int32_t L, + uint16_t * writeOffset, + int32_t bufferInc, + const q15_t * src, + int32_t srcInc, + uint32_t blockSize) + { + uint32_t i = 0u; + int32_t wOffset; + + /* Copy the value of Index pointer that points + * to the current location where the input samples to be copied */ + wOffset = *writeOffset; + + /* Loop over the blockSize */ + i = blockSize; + + while(i > 0u) + { + /* copy the input sample to the circular buffer */ + circBuffer[wOffset] = *src; + + /* Update the input pointer */ + src += srcInc; + + /* Circularly update wOffset. Watch out for positive and negative value */ + wOffset += bufferInc; + if(wOffset >= L) + wOffset -= L; + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *writeOffset = (uint16_t)wOffset; + } + + + /** + * @brief Q15 Circular Read function. + */ + static __INLINE void arm_circularRead_q15( + q15_t * circBuffer, + int32_t L, + int32_t * readOffset, + int32_t bufferInc, + q15_t * dst, + q15_t * dst_base, + int32_t dst_length, + int32_t dstInc, + uint32_t blockSize) + { + uint32_t i = 0; + int32_t rOffset, dst_end; + + /* Copy the value of Index pointer that points + * to the current location from where the input samples to be read */ + rOffset = *readOffset; + + dst_end = (int32_t) (dst_base + dst_length); + + /* Loop over the blockSize */ + i = blockSize; + + while(i > 0u) + { + /* copy the sample from the circular buffer to the destination buffer */ + *dst = circBuffer[rOffset]; + + /* Update the input pointer */ + dst += dstInc; + + if(dst == (q15_t *) dst_end) + { + dst = dst_base; + } + + /* Circularly update wOffset. Watch out for positive and negative value */ + rOffset += bufferInc; + + if(rOffset >= L) + { + rOffset -= L; + } + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *readOffset = rOffset; + } + + + /** + * @brief Q7 Circular write function. + */ + static __INLINE void arm_circularWrite_q7( + q7_t * circBuffer, + int32_t L, + uint16_t * writeOffset, + int32_t bufferInc, + const q7_t * src, + int32_t srcInc, + uint32_t blockSize) + { + uint32_t i = 0u; + int32_t wOffset; + + /* Copy the value of Index pointer that points + * to the current location where the input samples to be copied */ + wOffset = *writeOffset; + + /* Loop over the blockSize */ + i = blockSize; + + while(i > 0u) + { + /* copy the input sample to the circular buffer */ + circBuffer[wOffset] = *src; + + /* Update the input pointer */ + src += srcInc; + + /* Circularly update wOffset. Watch out for positive and negative value */ + wOffset += bufferInc; + if(wOffset >= L) + wOffset -= L; + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *writeOffset = (uint16_t)wOffset; + } + + + /** + * @brief Q7 Circular Read function. + */ + static __INLINE void arm_circularRead_q7( + q7_t * circBuffer, + int32_t L, + int32_t * readOffset, + int32_t bufferInc, + q7_t * dst, + q7_t * dst_base, + int32_t dst_length, + int32_t dstInc, + uint32_t blockSize) + { + uint32_t i = 0; + int32_t rOffset, dst_end; + + /* Copy the value of Index pointer that points + * to the current location from where the input samples to be read */ + rOffset = *readOffset; + + dst_end = (int32_t) (dst_base + dst_length); + + /* Loop over the blockSize */ + i = blockSize; + + while(i > 0u) + { + /* copy the sample from the circular buffer to the destination buffer */ + *dst = circBuffer[rOffset]; + + /* Update the input pointer */ + dst += dstInc; + + if(dst == (q7_t *) dst_end) + { + dst = dst_base; + } + + /* Circularly update rOffset. Watch out for positive and negative value */ + rOffset += bufferInc; + + if(rOffset >= L) + { + rOffset -= L; + } + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *readOffset = rOffset; + } + + + /** + * @brief Sum of the squares of the elements of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_power_q31( + q31_t * pSrc, + uint32_t blockSize, + q63_t * pResult); + + + /** + * @brief Sum of the squares of the elements of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_power_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult); + + + /** + * @brief Sum of the squares of the elements of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_power_q15( + q15_t * pSrc, + uint32_t blockSize, + q63_t * pResult); + + + /** + * @brief Sum of the squares of the elements of a Q7 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_power_q7( + q7_t * pSrc, + uint32_t blockSize, + q31_t * pResult); + + + /** + * @brief Mean value of a Q7 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_mean_q7( + q7_t * pSrc, + uint32_t blockSize, + q7_t * pResult); + + + /** + * @brief Mean value of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_mean_q15( + q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult); + + + /** + * @brief Mean value of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_mean_q31( + q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult); + + + /** + * @brief Mean value of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_mean_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult); + + + /** + * @brief Variance of the elements of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_var_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult); + + + /** + * @brief Variance of the elements of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_var_q31( + q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult); + + + /** + * @brief Variance of the elements of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_var_q15( + q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult); + + + /** + * @brief Root Mean Square of the elements of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_rms_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult); + + + /** + * @brief Root Mean Square of the elements of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_rms_q31( + q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult); + + + /** + * @brief Root Mean Square of the elements of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_rms_q15( + q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult); + + + /** + * @brief Standard deviation of the elements of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_std_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult); + + + /** + * @brief Standard deviation of the elements of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_std_q31( + q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult); + + + /** + * @brief Standard deviation of the elements of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_std_q15( + q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult); + + + /** + * @brief Floating-point complex magnitude + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_f32( + float32_t * pSrc, + float32_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q31 complex magnitude + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_q31( + q31_t * pSrc, + q31_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q15 complex magnitude + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_q15( + q15_t * pSrc, + q15_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q15 complex dot product + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] numSamples number of complex samples in each vector + * @param[out] realResult real part of the result returned here + * @param[out] imagResult imaginary part of the result returned here + */ + void arm_cmplx_dot_prod_q15( + q15_t * pSrcA, + q15_t * pSrcB, + uint32_t numSamples, + q31_t * realResult, + q31_t * imagResult); + + + /** + * @brief Q31 complex dot product + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] numSamples number of complex samples in each vector + * @param[out] realResult real part of the result returned here + * @param[out] imagResult imaginary part of the result returned here + */ + void arm_cmplx_dot_prod_q31( + q31_t * pSrcA, + q31_t * pSrcB, + uint32_t numSamples, + q63_t * realResult, + q63_t * imagResult); + + + /** + * @brief Floating-point complex dot product + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] numSamples number of complex samples in each vector + * @param[out] realResult real part of the result returned here + * @param[out] imagResult imaginary part of the result returned here + */ + void arm_cmplx_dot_prod_f32( + float32_t * pSrcA, + float32_t * pSrcB, + uint32_t numSamples, + float32_t * realResult, + float32_t * imagResult); + + + /** + * @brief Q15 complex-by-real multiplication + * @param[in] pSrcCmplx points to the complex input vector + * @param[in] pSrcReal points to the real input vector + * @param[out] pCmplxDst points to the complex output vector + * @param[in] numSamples number of samples in each vector + */ + void arm_cmplx_mult_real_q15( + q15_t * pSrcCmplx, + q15_t * pSrcReal, + q15_t * pCmplxDst, + uint32_t numSamples); + + + /** + * @brief Q31 complex-by-real multiplication + * @param[in] pSrcCmplx points to the complex input vector + * @param[in] pSrcReal points to the real input vector + * @param[out] pCmplxDst points to the complex output vector + * @param[in] numSamples number of samples in each vector + */ + void arm_cmplx_mult_real_q31( + q31_t * pSrcCmplx, + q31_t * pSrcReal, + q31_t * pCmplxDst, + uint32_t numSamples); + + + /** + * @brief Floating-point complex-by-real multiplication + * @param[in] pSrcCmplx points to the complex input vector + * @param[in] pSrcReal points to the real input vector + * @param[out] pCmplxDst points to the complex output vector + * @param[in] numSamples number of samples in each vector + */ + void arm_cmplx_mult_real_f32( + float32_t * pSrcCmplx, + float32_t * pSrcReal, + float32_t * pCmplxDst, + uint32_t numSamples); + + + /** + * @brief Minimum value of a Q7 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] result is output pointer + * @param[in] index is the array index of the minimum value in the input buffer. + */ + void arm_min_q7( + q7_t * pSrc, + uint32_t blockSize, + q7_t * result, + uint32_t * index); + + + /** + * @brief Minimum value of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output pointer + * @param[in] pIndex is the array index of the minimum value in the input buffer. + */ + void arm_min_q15( + q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult, + uint32_t * pIndex); + + + /** + * @brief Minimum value of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output pointer + * @param[out] pIndex is the array index of the minimum value in the input buffer. + */ + void arm_min_q31( + q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult, + uint32_t * pIndex); + + + /** + * @brief Minimum value of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output pointer + * @param[out] pIndex is the array index of the minimum value in the input buffer. + */ + void arm_min_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult, + uint32_t * pIndex); + + +/** + * @brief Maximum value of a Q7 vector. + * @param[in] pSrc points to the input buffer + * @param[in] blockSize length of the input vector + * @param[out] pResult maximum value returned here + * @param[out] pIndex index of maximum value returned here + */ + void arm_max_q7( + q7_t * pSrc, + uint32_t blockSize, + q7_t * pResult, + uint32_t * pIndex); + + +/** + * @brief Maximum value of a Q15 vector. + * @param[in] pSrc points to the input buffer + * @param[in] blockSize length of the input vector + * @param[out] pResult maximum value returned here + * @param[out] pIndex index of maximum value returned here + */ + void arm_max_q15( + q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult, + uint32_t * pIndex); + + +/** + * @brief Maximum value of a Q31 vector. + * @param[in] pSrc points to the input buffer + * @param[in] blockSize length of the input vector + * @param[out] pResult maximum value returned here + * @param[out] pIndex index of maximum value returned here + */ + void arm_max_q31( + q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult, + uint32_t * pIndex); + + +/** + * @brief Maximum value of a floating-point vector. + * @param[in] pSrc points to the input buffer + * @param[in] blockSize length of the input vector + * @param[out] pResult maximum value returned here + * @param[out] pIndex index of maximum value returned here + */ + void arm_max_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult, + uint32_t * pIndex); + + + /** + * @brief Q15 complex-by-complex multiplication + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_mult_cmplx_q15( + q15_t * pSrcA, + q15_t * pSrcB, + q15_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q31 complex-by-complex multiplication + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_mult_cmplx_q31( + q31_t * pSrcA, + q31_t * pSrcB, + q31_t * pDst, + uint32_t numSamples); + + + /** + * @brief Floating-point complex-by-complex multiplication + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_mult_cmplx_f32( + float32_t * pSrcA, + float32_t * pSrcB, + float32_t * pDst, + uint32_t numSamples); + + + /** + * @brief Converts the elements of the floating-point vector to Q31 vector. + * @param[in] pSrc points to the floating-point input vector + * @param[out] pDst points to the Q31 output vector + * @param[in] blockSize length of the input vector + */ + void arm_float_to_q31( + float32_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the floating-point vector to Q15 vector. + * @param[in] pSrc points to the floating-point input vector + * @param[out] pDst points to the Q15 output vector + * @param[in] blockSize length of the input vector + */ + void arm_float_to_q15( + float32_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the floating-point vector to Q7 vector. + * @param[in] pSrc points to the floating-point input vector + * @param[out] pDst points to the Q7 output vector + * @param[in] blockSize length of the input vector + */ + void arm_float_to_q7( + float32_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the Q31 vector to Q15 vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q31_to_q15( + q31_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the Q31 vector to Q7 vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q31_to_q7( + q31_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the Q15 vector to floating-point vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q15_to_float( + q15_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the Q15 vector to Q31 vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q15_to_q31( + q15_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the Q15 vector to Q7 vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q15_to_q7( + q15_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @ingroup groupInterpolation + */ + + /** + * @defgroup BilinearInterpolate Bilinear Interpolation + * + * Bilinear interpolation is an extension of linear interpolation applied to a two dimensional grid. + * The underlying function f(x, y) is sampled on a regular grid and the interpolation process + * determines values between the grid points. + * Bilinear interpolation is equivalent to two step linear interpolation, first in the x-dimension and then in the y-dimension. + * Bilinear interpolation is often used in image processing to rescale images. + * The CMSIS DSP library provides bilinear interpolation functions for Q7, Q15, Q31, and floating-point data types. + * + * Algorithm + * \par + * The instance structure used by the bilinear interpolation functions describes a two dimensional data table. + * For floating-point, the instance structure is defined as: + *
    +   *   typedef struct
    +   *   {
    +   *     uint16_t numRows;
    +   *     uint16_t numCols;
    +   *     float32_t *pData;
    +   * } arm_bilinear_interp_instance_f32;
    +   * 
    + * + * \par + * where numRows specifies the number of rows in the table; + * numCols specifies the number of columns in the table; + * and pData points to an array of size numRows*numCols values. + * The data table pTable is organized in row order and the supplied data values fall on integer indexes. + * That is, table element (x,y) is located at pTable[x + y*numCols] where x and y are integers. + * + * \par + * Let (x, y) specify the desired interpolation point. Then define: + *
    +   *     XF = floor(x)
    +   *     YF = floor(y)
    +   * 
    + * \par + * The interpolated output point is computed as: + *
    +   *  f(x, y) = f(XF, YF) * (1-(x-XF)) * (1-(y-YF))
    +   *           + f(XF+1, YF) * (x-XF)*(1-(y-YF))
    +   *           + f(XF, YF+1) * (1-(x-XF))*(y-YF)
    +   *           + f(XF+1, YF+1) * (x-XF)*(y-YF)
    +   * 
    + * Note that the coordinates (x, y) contain integer and fractional components. + * The integer components specify which portion of the table to use while the + * fractional components control the interpolation processor. + * + * \par + * if (x,y) are outside of the table boundary, Bilinear interpolation returns zero output. + */ + + /** + * @addtogroup BilinearInterpolate + * @{ + */ + + + /** + * + * @brief Floating-point bilinear interpolation. + * @param[in,out] S points to an instance of the interpolation structure. + * @param[in] X interpolation coordinate. + * @param[in] Y interpolation coordinate. + * @return out interpolated value. + */ + static __INLINE float32_t arm_bilinear_interp_f32( + const arm_bilinear_interp_instance_f32 * S, + float32_t X, + float32_t Y) + { + float32_t out; + float32_t f00, f01, f10, f11; + float32_t *pData = S->pData; + int32_t xIndex, yIndex, index; + float32_t xdiff, ydiff; + float32_t b1, b2, b3, b4; + + xIndex = (int32_t) X; + yIndex = (int32_t) Y; + + /* Care taken for table outside boundary */ + /* Returns zero output when values are outside table boundary */ + if(xIndex < 0 || xIndex > (S->numRows - 1) || yIndex < 0 || yIndex > (S->numCols - 1)) + { + return (0); + } + + /* Calculation of index for two nearest points in X-direction */ + index = (xIndex - 1) + (yIndex - 1) * S->numCols; + + + /* Read two nearest points in X-direction */ + f00 = pData[index]; + f01 = pData[index + 1]; + + /* Calculation of index for two nearest points in Y-direction */ + index = (xIndex - 1) + (yIndex) * S->numCols; + + + /* Read two nearest points in Y-direction */ + f10 = pData[index]; + f11 = pData[index + 1]; + + /* Calculation of intermediate values */ + b1 = f00; + b2 = f01 - f00; + b3 = f10 - f00; + b4 = f00 - f01 - f10 + f11; + + /* Calculation of fractional part in X */ + xdiff = X - xIndex; + + /* Calculation of fractional part in Y */ + ydiff = Y - yIndex; + + /* Calculation of bi-linear interpolated output */ + out = b1 + b2 * xdiff + b3 * ydiff + b4 * xdiff * ydiff; + + /* return to application */ + return (out); + } + + + /** + * + * @brief Q31 bilinear interpolation. + * @param[in,out] S points to an instance of the interpolation structure. + * @param[in] X interpolation coordinate in 12.20 format. + * @param[in] Y interpolation coordinate in 12.20 format. + * @return out interpolated value. + */ + static __INLINE q31_t arm_bilinear_interp_q31( + arm_bilinear_interp_instance_q31 * S, + q31_t X, + q31_t Y) + { + q31_t out; /* Temporary output */ + q31_t acc = 0; /* output */ + q31_t xfract, yfract; /* X, Y fractional parts */ + q31_t x1, x2, y1, y2; /* Nearest output values */ + int32_t rI, cI; /* Row and column indices */ + q31_t *pYData = S->pData; /* pointer to output table values */ + uint32_t nCols = S->numCols; /* num of rows */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + rI = ((X & (q31_t)0xFFF00000) >> 20); + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + cI = ((Y & (q31_t)0xFFF00000) >> 20); + + /* Care taken for table outside boundary */ + /* Returns zero output when values are outside table boundary */ + if(rI < 0 || rI > (S->numRows - 1) || cI < 0 || cI > (S->numCols - 1)) + { + return (0); + } + + /* 20 bits for the fractional part */ + /* shift left xfract by 11 to keep 1.31 format */ + xfract = (X & 0x000FFFFF) << 11u; + + /* Read two nearest output values from the index */ + x1 = pYData[(rI) + (int32_t)nCols * (cI) ]; + x2 = pYData[(rI) + (int32_t)nCols * (cI) + 1]; + + /* 20 bits for the fractional part */ + /* shift left yfract by 11 to keep 1.31 format */ + yfract = (Y & 0x000FFFFF) << 11u; + + /* Read two nearest output values from the index */ + y1 = pYData[(rI) + (int32_t)nCols * (cI + 1) ]; + y2 = pYData[(rI) + (int32_t)nCols * (cI + 1) + 1]; + + /* Calculation of x1 * (1-xfract ) * (1-yfract) and acc is in 3.29(q29) format */ + out = ((q31_t) (((q63_t) x1 * (0x7FFFFFFF - xfract)) >> 32)); + acc = ((q31_t) (((q63_t) out * (0x7FFFFFFF - yfract)) >> 32)); + + /* x2 * (xfract) * (1-yfract) in 3.29(q29) and adding to acc */ + out = ((q31_t) ((q63_t) x2 * (0x7FFFFFFF - yfract) >> 32)); + acc += ((q31_t) ((q63_t) out * (xfract) >> 32)); + + /* y1 * (1 - xfract) * (yfract) in 3.29(q29) and adding to acc */ + out = ((q31_t) ((q63_t) y1 * (0x7FFFFFFF - xfract) >> 32)); + acc += ((q31_t) ((q63_t) out * (yfract) >> 32)); + + /* y2 * (xfract) * (yfract) in 3.29(q29) and adding to acc */ + out = ((q31_t) ((q63_t) y2 * (xfract) >> 32)); + acc += ((q31_t) ((q63_t) out * (yfract) >> 32)); + + /* Convert acc to 1.31(q31) format */ + return ((q31_t)(acc << 2)); + } + + + /** + * @brief Q15 bilinear interpolation. + * @param[in,out] S points to an instance of the interpolation structure. + * @param[in] X interpolation coordinate in 12.20 format. + * @param[in] Y interpolation coordinate in 12.20 format. + * @return out interpolated value. + */ + static __INLINE q15_t arm_bilinear_interp_q15( + arm_bilinear_interp_instance_q15 * S, + q31_t X, + q31_t Y) + { + q63_t acc = 0; /* output */ + q31_t out; /* Temporary output */ + q15_t x1, x2, y1, y2; /* Nearest output values */ + q31_t xfract, yfract; /* X, Y fractional parts */ + int32_t rI, cI; /* Row and column indices */ + q15_t *pYData = S->pData; /* pointer to output table values */ + uint32_t nCols = S->numCols; /* num of rows */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + rI = ((X & (q31_t)0xFFF00000) >> 20); + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + cI = ((Y & (q31_t)0xFFF00000) >> 20); + + /* Care taken for table outside boundary */ + /* Returns zero output when values are outside table boundary */ + if(rI < 0 || rI > (S->numRows - 1) || cI < 0 || cI > (S->numCols - 1)) + { + return (0); + } + + /* 20 bits for the fractional part */ + /* xfract should be in 12.20 format */ + xfract = (X & 0x000FFFFF); + + /* Read two nearest output values from the index */ + x1 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI) ]; + x2 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI) + 1]; + + /* 20 bits for the fractional part */ + /* yfract should be in 12.20 format */ + yfract = (Y & 0x000FFFFF); + + /* Read two nearest output values from the index */ + y1 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI + 1) ]; + y2 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI + 1) + 1]; + + /* Calculation of x1 * (1-xfract ) * (1-yfract) and acc is in 13.51 format */ + + /* x1 is in 1.15(q15), xfract in 12.20 format and out is in 13.35 format */ + /* convert 13.35 to 13.31 by right shifting and out is in 1.31 */ + out = (q31_t) (((q63_t) x1 * (0xFFFFF - xfract)) >> 4u); + acc = ((q63_t) out * (0xFFFFF - yfract)); + + /* x2 * (xfract) * (1-yfract) in 1.51 and adding to acc */ + out = (q31_t) (((q63_t) x2 * (0xFFFFF - yfract)) >> 4u); + acc += ((q63_t) out * (xfract)); + + /* y1 * (1 - xfract) * (yfract) in 1.51 and adding to acc */ + out = (q31_t) (((q63_t) y1 * (0xFFFFF - xfract)) >> 4u); + acc += ((q63_t) out * (yfract)); + + /* y2 * (xfract) * (yfract) in 1.51 and adding to acc */ + out = (q31_t) (((q63_t) y2 * (xfract)) >> 4u); + acc += ((q63_t) out * (yfract)); + + /* acc is in 13.51 format and down shift acc by 36 times */ + /* Convert out to 1.15 format */ + return ((q15_t)(acc >> 36)); + } + + + /** + * @brief Q7 bilinear interpolation. + * @param[in,out] S points to an instance of the interpolation structure. + * @param[in] X interpolation coordinate in 12.20 format. + * @param[in] Y interpolation coordinate in 12.20 format. + * @return out interpolated value. + */ + static __INLINE q7_t arm_bilinear_interp_q7( + arm_bilinear_interp_instance_q7 * S, + q31_t X, + q31_t Y) + { + q63_t acc = 0; /* output */ + q31_t out; /* Temporary output */ + q31_t xfract, yfract; /* X, Y fractional parts */ + q7_t x1, x2, y1, y2; /* Nearest output values */ + int32_t rI, cI; /* Row and column indices */ + q7_t *pYData = S->pData; /* pointer to output table values */ + uint32_t nCols = S->numCols; /* num of rows */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + rI = ((X & (q31_t)0xFFF00000) >> 20); + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + cI = ((Y & (q31_t)0xFFF00000) >> 20); + + /* Care taken for table outside boundary */ + /* Returns zero output when values are outside table boundary */ + if(rI < 0 || rI > (S->numRows - 1) || cI < 0 || cI > (S->numCols - 1)) + { + return (0); + } + + /* 20 bits for the fractional part */ + /* xfract should be in 12.20 format */ + xfract = (X & (q31_t)0x000FFFFF); + + /* Read two nearest output values from the index */ + x1 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI) ]; + x2 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI) + 1]; + + /* 20 bits for the fractional part */ + /* yfract should be in 12.20 format */ + yfract = (Y & (q31_t)0x000FFFFF); + + /* Read two nearest output values from the index */ + y1 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI + 1) ]; + y2 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI + 1) + 1]; + + /* Calculation of x1 * (1-xfract ) * (1-yfract) and acc is in 16.47 format */ + out = ((x1 * (0xFFFFF - xfract))); + acc = (((q63_t) out * (0xFFFFF - yfract))); + + /* x2 * (xfract) * (1-yfract) in 2.22 and adding to acc */ + out = ((x2 * (0xFFFFF - yfract))); + acc += (((q63_t) out * (xfract))); + + /* y1 * (1 - xfract) * (yfract) in 2.22 and adding to acc */ + out = ((y1 * (0xFFFFF - xfract))); + acc += (((q63_t) out * (yfract))); + + /* y2 * (xfract) * (yfract) in 2.22 and adding to acc */ + out = ((y2 * (yfract))); + acc += (((q63_t) out * (xfract))); + + /* acc in 16.47 format and down shift by 40 to convert to 1.7 format */ + return ((q7_t)(acc >> 40)); + } + + /** + * @} end of BilinearInterpolate group + */ + + +/* SMMLAR */ +#define multAcc_32x32_keep32_R(a, x, y) \ + a = (q31_t) (((((q63_t) a) << 32) + ((q63_t) x * y) + 0x80000000LL ) >> 32) + +/* SMMLSR */ +#define multSub_32x32_keep32_R(a, x, y) \ + a = (q31_t) (((((q63_t) a) << 32) - ((q63_t) x * y) + 0x80000000LL ) >> 32) + +/* SMMULR */ +#define mult_32x32_keep32_R(a, x, y) \ + a = (q31_t) (((q63_t) x * y + 0x80000000LL ) >> 32) + +/* SMMLA */ +#define multAcc_32x32_keep32(a, x, y) \ + a += (q31_t) (((q63_t) x * y) >> 32) + +/* SMMLS */ +#define multSub_32x32_keep32(a, x, y) \ + a -= (q31_t) (((q63_t) x * y) >> 32) + +/* SMMUL */ +#define mult_32x32_keep32(a, x, y) \ + a = (q31_t) (((q63_t) x * y ) >> 32) + + +#if defined ( __CC_ARM ) + /* Enter low optimization region - place directly above function definition */ + #if defined( ARM_MATH_CM4 ) || defined( ARM_MATH_CM7) + #define LOW_OPTIMIZATION_ENTER \ + _Pragma ("push") \ + _Pragma ("O1") + #else + #define LOW_OPTIMIZATION_ENTER + #endif + + /* Exit low optimization region - place directly after end of function definition */ + #if defined( ARM_MATH_CM4 ) || defined( ARM_MATH_CM7) + #define LOW_OPTIMIZATION_EXIT \ + _Pragma ("pop") + #else + #define LOW_OPTIMIZATION_EXIT + #endif + + /* Enter low optimization region - place directly above function definition */ + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + + /* Exit low optimization region - place directly after end of function definition */ + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #define LOW_OPTIMIZATION_ENTER + #define LOW_OPTIMIZATION_EXIT + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined(__GNUC__) + #define LOW_OPTIMIZATION_ENTER __attribute__(( optimize("-O1") )) + #define LOW_OPTIMIZATION_EXIT + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined(__ICCARM__) + /* Enter low optimization region - place directly above function definition */ + #if defined( ARM_MATH_CM4 ) || defined( ARM_MATH_CM7) + #define LOW_OPTIMIZATION_ENTER \ + _Pragma ("optimize=low") + #else + #define LOW_OPTIMIZATION_ENTER + #endif + + /* Exit low optimization region - place directly after end of function definition */ + #define LOW_OPTIMIZATION_EXIT + + /* Enter low optimization region - place directly above function definition */ + #if defined( ARM_MATH_CM4 ) || defined( ARM_MATH_CM7) + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER \ + _Pragma ("optimize=low") + #else + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + #endif + + /* Exit low optimization region - place directly after end of function definition */ + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined(__CSMC__) + #define LOW_OPTIMIZATION_ENTER + #define LOW_OPTIMIZATION_EXIT + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined(__TASKING__) + #define LOW_OPTIMIZATION_ENTER + #define LOW_OPTIMIZATION_EXIT + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#endif + + +#ifdef __cplusplus +} +#endif + + +#if defined ( __GNUC__ ) +#pragma GCC diagnostic pop +#endif + +#endif /* _ARM_MATH_H */ + +/** + * + * End of file. + */ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/cmsis_armcc.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/cmsis_armcc.h new file mode 100644 index 0000000..74c49c6 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/cmsis_armcc.h @@ -0,0 +1,734 @@ +/**************************************************************************//** + * @file cmsis_armcc.h + * @brief CMSIS Cortex-M Core Function/Instruction Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM 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: + - 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 COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (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 __CMSIS_ARMCC_H +#define __CMSIS_ARMCC_H + + +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 400677) + #error "Please use ARM Compiler Toolchain V4.0.677 or later!" +#endif + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +/* intrinsic void __enable_irq(); */ +/* intrinsic void __disable_irq(); */ + +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__STATIC_INLINE uint32_t __get_CONTROL(void) +{ + register uint32_t __regControl __ASM("control"); + return(__regControl); +} + + +/** + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set + */ +__STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + register uint32_t __regControl __ASM("control"); + __regControl = control; +} + + +/** + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value + */ +__STATIC_INLINE uint32_t __get_IPSR(void) +{ + register uint32_t __regIPSR __ASM("ipsr"); + return(__regIPSR); +} + + +/** + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value + */ +__STATIC_INLINE uint32_t __get_APSR(void) +{ + register uint32_t __regAPSR __ASM("apsr"); + return(__regAPSR); +} + + +/** + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + \return xPSR Register value + */ +__STATIC_INLINE uint32_t __get_xPSR(void) +{ + register uint32_t __regXPSR __ASM("xpsr"); + return(__regXPSR); +} + + +/** + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value + */ +__STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + return(__regProcessStackPointer); +} + + +/** + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + __regProcessStackPointer = topOfProcStack; +} + + +/** + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value + */ +__STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + return(__regMainStackPointer); +} + + +/** + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + __regMainStackPointer = topOfMainStack; +} + + +/** + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value + */ +__STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + register uint32_t __regPriMask __ASM("primask"); + return(__regPriMask); +} + + +/** + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask + */ +__STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + register uint32_t __regPriMask __ASM("primask"); + __regPriMask = (priMask); +} + + +#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) + +/** + \brief Enable FIQ + \details Enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __enable_fault_irq __enable_fiq + + +/** + \brief Disable FIQ + \details Disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __disable_fault_irq __disable_fiq + + +/** + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value + */ +__STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + register uint32_t __regBasePri __ASM("basepri"); + return(__regBasePri); +} + + +/** + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set + */ +__STATIC_INLINE void __set_BASEPRI(uint32_t basePri) +{ + register uint32_t __regBasePri __ASM("basepri"); + __regBasePri = (basePri & 0xFFU); +} + + +/** + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__STATIC_INLINE void __set_BASEPRI_MAX(uint32_t basePri) +{ + register uint32_t __regBasePriMax __ASM("basepri_max"); + __regBasePriMax = (basePri & 0xFFU); +} + + +/** + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value + */ +__STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + return(__regFaultMask); +} + + +/** + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + __regFaultMask = (faultMask & (uint32_t)1); +} + +#endif /* (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) */ + + +#if (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U) + +/** + \brief Get FPSCR + \details Returns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value + */ +__STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + register uint32_t __regfpscr __ASM("fpscr"); + return(__regfpscr); +#else + return(0U); +#endif +} + + +/** + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set + */ +__STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + register uint32_t __regfpscr __ASM("fpscr"); + __regfpscr = (fpscr); +#endif +} + +#endif /* (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U) */ + + + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP __nop + + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +#define __WFI __wfi + + +/** + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE __wfe + + +/** + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV __sev + + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +#define __ISB() do {\ + __schedule_barrier();\ + __isb(0xF);\ + __schedule_barrier();\ + } while (0U) + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +#define __DSB() do {\ + __schedule_barrier();\ + __dsb(0xF);\ + __schedule_barrier();\ + } while (0U) + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +#define __DMB() do {\ + __schedule_barrier();\ + __dmb(0xF);\ + __schedule_barrier();\ + } while (0U) + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in integer value. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV __rev + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in two unsigned short values. + \param [in] value Value to reverse + \return Reversed value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value) +{ + rev16 r0, r0 + bx lr +} +#endif + +/** + \brief Reverse byte order in signed short value + \details Reverses the byte order in a signed short value with sign extension to integer. + \param [in] value Value to reverse + \return Reversed value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value) +{ + revsh r0, r0 + bx lr +} +#endif + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] value Value to rotate + \param [in] value Number of Bits to rotate + \return Rotated value + */ +#define __ROR __ror + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __breakpoint(value) + + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) + #define __RBIT __rbit +#else +__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + int32_t s = 4 /*sizeof(v)*/ * 8 - 1; /* extra shift needed at end */ + + result = value; /* r will be reversed bits of v; first get LSB of v */ + for (value >>= 1U; value; value >>= 1U) + { + result <<= 1U; + result |= value & 1U; + s--; + } + result <<= s; /* shift when v's highest bits are zero */ + return(result); +} +#endif + + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +#define __CLZ __clz + + +#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) + +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr)) +#else + #define __LDREXB(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint8_t ) __ldrex(ptr)) _Pragma("pop") +#endif + + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __LDREXH(ptr) ((uint16_t) __ldrex(ptr)) +#else + #define __LDREXH(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint16_t) __ldrex(ptr)) _Pragma("pop") +#endif + + +/** + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr)) +#else + #define __LDREXW(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint32_t ) __ldrex(ptr)) _Pragma("pop") +#endif + + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __STREXB(value, ptr) __strex(value, ptr) +#else + #define __STREXB(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") +#endif + + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __STREXH(value, ptr) __strex(value, ptr) +#else + #define __STREXH(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") +#endif + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __STREXW(value, ptr) __strex(value, ptr) +#else + #define __STREXW(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") +#endif + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +#define __CLREX __clrex + + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT __ssat + + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT __usat + + +/** + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".rrx_text"))) __STATIC_INLINE __ASM uint32_t __RRX(uint32_t value) +{ + rrx r0, r0 + bx lr +} +#endif + + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDRBT(ptr) ((uint8_t ) __ldrt(ptr)) + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDRHT(ptr) ((uint16_t) __ldrt(ptr)) + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDRT(ptr) ((uint32_t ) __ldrt(ptr)) + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +#define __STRBT(value, ptr) __strt(value, ptr) + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +#define __STRHT(value, ptr) __strt(value, ptr) + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +#define __STRT(value, ptr) __strt(value, ptr) + +#endif /* (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) */ + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if (__CORTEX_M >= 0x04U) /* only for Cortex-M4 and above */ + +#define __SADD8 __sadd8 +#define __QADD8 __qadd8 +#define __SHADD8 __shadd8 +#define __UADD8 __uadd8 +#define __UQADD8 __uqadd8 +#define __UHADD8 __uhadd8 +#define __SSUB8 __ssub8 +#define __QSUB8 __qsub8 +#define __SHSUB8 __shsub8 +#define __USUB8 __usub8 +#define __UQSUB8 __uqsub8 +#define __UHSUB8 __uhsub8 +#define __SADD16 __sadd16 +#define __QADD16 __qadd16 +#define __SHADD16 __shadd16 +#define __UADD16 __uadd16 +#define __UQADD16 __uqadd16 +#define __UHADD16 __uhadd16 +#define __SSUB16 __ssub16 +#define __QSUB16 __qsub16 +#define __SHSUB16 __shsub16 +#define __USUB16 __usub16 +#define __UQSUB16 __uqsub16 +#define __UHSUB16 __uhsub16 +#define __SASX __sasx +#define __QASX __qasx +#define __SHASX __shasx +#define __UASX __uasx +#define __UQASX __uqasx +#define __UHASX __uhasx +#define __SSAX __ssax +#define __QSAX __qsax +#define __SHSAX __shsax +#define __USAX __usax +#define __UQSAX __uqsax +#define __UHSAX __uhsax +#define __USAD8 __usad8 +#define __USADA8 __usada8 +#define __SSAT16 __ssat16 +#define __USAT16 __usat16 +#define __UXTB16 __uxtb16 +#define __UXTAB16 __uxtab16 +#define __SXTB16 __sxtb16 +#define __SXTAB16 __sxtab16 +#define __SMUAD __smuad +#define __SMUADX __smuadx +#define __SMLAD __smlad +#define __SMLADX __smladx +#define __SMLALD __smlald +#define __SMLALDX __smlaldx +#define __SMUSD __smusd +#define __SMUSDX __smusdx +#define __SMLSD __smlsd +#define __SMLSDX __smlsdx +#define __SMLSLD __smlsld +#define __SMLSLDX __smlsldx +#define __SEL __sel +#define __QADD __qadd +#define __QSUB __qsub + +#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ + ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) + +#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ + ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) + +#define __SMMLA(ARG1,ARG2,ARG3) ( (int32_t)((((int64_t)(ARG1) * (ARG2)) + \ + ((int64_t)(ARG3) << 32U) ) >> 32U)) + +#endif /* (__CORTEX_M >= 0x04) */ +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#endif /* __CMSIS_ARMCC_H */ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/cmsis_armcc_V6.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/cmsis_armcc_V6.h new file mode 100644 index 0000000..cd13240 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/cmsis_armcc_V6.h @@ -0,0 +1,1800 @@ +/**************************************************************************//** + * @file cmsis_armcc_V6.h + * @brief CMSIS Cortex-M Core Function/Instruction Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM 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: + - 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 COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (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 __CMSIS_ARMCC_V6_H +#define __CMSIS_ARMCC_V6_H + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by clearing the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__((always_inline)) __STATIC_INLINE void __enable_irq(void) +{ + __ASM volatile ("cpsie i" : : : "memory"); +} + + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by setting the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__((always_inline)) __STATIC_INLINE void __disable_irq(void) +{ + __ASM volatile ("cpsid i" : : : "memory"); +} + + +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Control Register (non-secure) + \details Returns the content of the non-secure Control Register when in secure mode. + \return non-secure Control Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_CONTROL_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Control Register (non-secure) + \details Writes the given value to the non-secure Control Register when in secure state. + \param [in] control Control Register value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_CONTROL_NS(uint32_t control) +{ + __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory"); +} +#endif + + +/** + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get IPSR Register (non-secure) + \details Returns the content of the non-secure IPSR Register when in secure state. + \return IPSR Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_IPSR_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get APSR Register (non-secure) + \details Returns the content of the non-secure APSR Register when in secure state. + \return APSR Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_APSR_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + \return xPSR Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get xPSR Register (non-secure) + \details Returns the content of the non-secure xPSR Register when in secure state. + \return xPSR Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_xPSR_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, psp" : "=r" (result) ); + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Process Stack Pointer (non-secure) + \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state. + \return PSP Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_PSP_NS(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, psp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : "sp"); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Process Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state. + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : "sp"); +} +#endif + + +/** + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, msp" : "=r" (result) ); + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Main Stack Pointer (non-secure) + \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state. + \return MSP Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_MSP_NS(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, msp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : "sp"); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Main Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state. + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : "sp"); +} +#endif + + +/** + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) ); + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Priority Mask (non-secure) + \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state. + \return Priority Mask value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_PRIMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Priority Mask (non-secure) + \details Assigns the given value to the non-secure Priority Mask Register when in secure state. + \param [in] priMask Priority Mask + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) +{ + __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory"); +} +#endif + + +#if ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) /* ToDo: ARMCC_V6: check if this is ok for cortex >=3 */ + +/** + \brief Enable FIQ + \details Enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__((always_inline)) __STATIC_INLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f" : : : "memory"); +} + + +/** + \brief Disable FIQ + \details Disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__((always_inline)) __STATIC_INLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f" : : : "memory"); +} + + +/** + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri" : "=r" (result) ); + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Base Priority (non-secure) + \details Returns the current value of the non-secure Base Priority register when in secure state. + \return Base Priority register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_BASEPRI_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_BASEPRI(uint32_t value) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (value) : "memory"); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Base Priority (non-secure) + \details Assigns the given value to the non-secure Base Priority register when in secure state. + \param [in] basePri Base Priority value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_BASEPRI_NS(uint32_t value) +{ + __ASM volatile ("MSR basepri_ns, %0" : : "r" (value) : "memory"); +} +#endif + + +/** + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_BASEPRI_MAX(uint32_t value) +{ + __ASM volatile ("MSR basepri_max, %0" : : "r" (value) : "memory"); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Base Priority with condition (non_secure) + \details Assigns the given value to the non-secure Base Priority register when in secure state only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_BASEPRI_MAX_NS(uint32_t value) +{ + __ASM volatile ("MSR basepri_max_ns, %0" : : "r" (value) : "memory"); +} +#endif + + +/** + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Fault Mask (non-secure) + \details Returns the current value of the non-secure Fault Mask register when in secure state. + \return Fault Mask register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_FAULTMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); +} + + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Fault Mask (non-secure) + \details Assigns the given value to the non-secure Fault Mask register when in secure state. + \param [in] faultMask Fault Mask value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory"); +} +#endif + + +#endif /* ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_8M__ == 1U)) */ + + +#if (__ARM_ARCH_8M__ == 1U) + +/** + \brief Get Process Stack Pointer Limit + \details Returns the current value of the Process Stack Pointer Limit (PSPLIM). + \return PSPLIM Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_PSPLIM(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, psplim" : "=r" (result) ); + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) && (__ARM_ARCH_PROFILE == 'M') /* ToDo: ARMCC_V6: check predefined macro for mainline */ +/** + \brief Get Process Stack Pointer Limit (non-secure) + \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \return PSPLIM Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_PSPLIM_NS(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Process Stack Pointer Limit + \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM). + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) +{ + __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit)); +} + + +#if (__ARM_FEATURE_CMSE == 3U) && (__ARM_ARCH_PROFILE == 'M') /* ToDo: ARMCC_V6: check predefined macro for mainline */ +/** + \brief Set Process Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) +{ + __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit)); +} +#endif + + +/** + \brief Get Main Stack Pointer Limit + \details Returns the current value of the Main Stack Pointer Limit (MSPLIM). + \return MSPLIM Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_MSPLIM(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, msplim" : "=r" (result) ); + + return(result); +} + + +#if (__ARM_FEATURE_CMSE == 3U) && (__ARM_ARCH_PROFILE == 'M') /* ToDo: ARMCC_V6: check predefined macro for mainline */ +/** + \brief Get Main Stack Pointer Limit (non-secure) + \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state. + \return MSPLIM Register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_MSPLIM_NS(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Main Stack Pointer Limit + \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM). + \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) +{ + __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit)); +} + + +#if (__ARM_FEATURE_CMSE == 3U) && (__ARM_ARCH_PROFILE == 'M') /* ToDo: ARMCC_V6: check predefined macro for mainline */ +/** + \brief Set Main Stack Pointer Limit (non-secure) + \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state. + \param [in] MainStackPtrLimit Main Stack Pointer value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) +{ + __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit)); +} +#endif + +#endif /* (__ARM_ARCH_8M__ == 1U) */ + + +#if ((__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) /* ToDo: ARMCC_V6: check if this is ok for cortex >=4 */ + +/** + \brief Get FPSCR + \details eturns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value + */ +#define __get_FPSCR __builtin_arm_get_fpscr +#if 0 +__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + uint32_t result; + + __ASM volatile (""); /* Empty asm statement works as a scheduling barrier */ + __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); + __ASM volatile (""); + return(result); +#else + return(0); +#endif +} +#endif + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get FPSCR (non-secure) + \details Returns the current value of the non-secure Floating Point Status/Control register when in secure state. + \return Floating Point Status/Control register value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_FPSCR_NS(void) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + uint32_t result; + + __ASM volatile (""); /* Empty asm statement works as a scheduling barrier */ + __ASM volatile ("VMRS %0, fpscr_ns" : "=r" (result) ); + __ASM volatile (""); + return(result); +#else + return(0); +#endif +} +#endif + + +/** + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set + */ +#define __set_FPSCR __builtin_arm_set_fpscr +#if 0 +__attribute__((always_inline)) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + __ASM volatile (""); /* Empty asm statement works as a scheduling barrier */ + __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc"); + __ASM volatile (""); +#endif +} +#endif + +#if (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set FPSCR (non-secure) + \details Assigns the given value to the non-secure Floating Point Status/Control register when in secure state. + \param [in] fpscr Floating Point Status/Control value to set + */ +__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_FPSCR_NS(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + __ASM volatile (""); /* Empty asm statement works as a scheduling barrier */ + __ASM volatile ("VMSR fpscr_ns, %0" : : "r" (fpscr) : "vfpcc"); + __ASM volatile (""); +#endif +} +#endif + +#endif /* ((__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) */ + + + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/* Define macros for porting to both thumb1 and thumb2. + * For thumb1, use low register (r0-r7), specified by constraint "l" + * Otherwise, use general registers, specified by constraint "r" */ +#if defined (__thumb__) && !defined (__thumb2__) +#define __CMSIS_GCC_OUT_REG(r) "=l" (r) +#define __CMSIS_GCC_USE_REG(r) "l" (r) +#else +#define __CMSIS_GCC_OUT_REG(r) "=r" (r) +#define __CMSIS_GCC_USE_REG(r) "r" (r) +#endif + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP __builtin_arm_nop + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +#define __WFI __builtin_arm_wfi + + +/** + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE __builtin_arm_wfe + + +/** + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV __builtin_arm_sev + + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +#define __ISB() __builtin_arm_isb(0xF); + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +#define __DSB() __builtin_arm_dsb(0xF); + + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +#define __DMB() __builtin_arm_dmb(0xF); + + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in integer value. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV __builtin_bswap32 + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in two unsigned short values. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV16 __builtin_bswap16 /* ToDo: ARMCC_V6: check if __builtin_bswap16 could be used */ +#if 0 +__attribute__((always_inline)) __STATIC_INLINE uint32_t __REV16(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} +#endif + + +/** + \brief Reverse byte order in signed short value + \details Reverses the byte order in a signed short value with sign extension to integer. + \param [in] value Value to reverse + \return Reversed value + */ + /* ToDo: ARMCC_V6: check if __builtin_bswap16 could be used */ +__attribute__((always_inline)) __STATIC_INLINE int32_t __REVSH(int32_t value) +{ + int32_t result; + + __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] op1 Value to rotate + \param [in] op2 Number of Bits to rotate + \return Rotated value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + return (op1 >> op2) | (op1 << (32U - op2)); +} + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __ASM volatile ("bkpt "#value) + + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ + /* ToDo: ARMCC_V6: check if __builtin_arm_rbit is supported */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + +#if ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) /* ToDo: ARMCC_V6: check if this is ok for cortex >=3 */ + __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); +#else + int32_t s = 4 /*sizeof(v)*/ * 8 - 1; /* extra shift needed at end */ + + result = value; /* r will be reversed bits of v; first get LSB of v */ + for (value >>= 1U; value; value >>= 1U) + { + result <<= 1U; + result |= value & 1U; + s--; + } + result <<= s; /* shift when v's highest bits are zero */ +#endif + return(result); +} + + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +#define __CLZ __builtin_clz + + +#if ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) /* ToDo: ARMCC_V6: check if this is ok for cortex >=3 */ + +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDREXB (uint8_t)__builtin_arm_ldrex + + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDREXH (uint16_t)__builtin_arm_ldrex + + +/** + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDREXW (uint32_t)__builtin_arm_ldrex + + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXB (uint32_t)__builtin_arm_strex + + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXH (uint32_t)__builtin_arm_strex + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXW (uint32_t)__builtin_arm_strex + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +#define __CLREX __builtin_arm_clrex + + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +/*#define __SSAT __builtin_arm_ssat*/ +#define __SSAT(ARG1,ARG2) \ +({ \ + int32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT __builtin_arm_usat +#if 0 +#define __USAT(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) +#endif + + +/** + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __RRX(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint8_t __LDRBT(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint16_t __LDRHT(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __LDRT(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); +} + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__attribute__((always_inline)) __STATIC_INLINE void __STRBT(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__attribute__((always_inline)) __STATIC_INLINE void __STRHT(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__attribute__((always_inline)) __STATIC_INLINE void __STRT(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) ); +} + +#endif /* ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) */ + + +#if (__ARM_ARCH_8M__ == 1U) + +/** + \brief Load-Acquire (8 bit) + \details Executes a LDAB instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint8_t __LDAB(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint8_t) result); +} + + +/** + \brief Load-Acquire (16 bit) + \details Executes a LDAH instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint16_t __LDAH(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint16_t) result); +} + + +/** + \brief Load-Acquire (32 bit) + \details Executes a LDA instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __LDA(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); +} + + +/** + \brief Store-Release (8 bit) + \details Executes a STLB instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__attribute__((always_inline)) __STATIC_INLINE void __STLB(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief Store-Release (16 bit) + \details Executes a STLH instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__attribute__((always_inline)) __STATIC_INLINE void __STLH(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief Store-Release (32 bit) + \details Executes a STL instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__attribute__((always_inline)) __STATIC_INLINE void __STL(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief Load-Acquire Exclusive (8 bit) + \details Executes a LDAB exclusive instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDAEXB (uint8_t)__builtin_arm_ldaex + + +/** + \brief Load-Acquire Exclusive (16 bit) + \details Executes a LDAH exclusive instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDAEXH (uint16_t)__builtin_arm_ldaex + + +/** + \brief Load-Acquire Exclusive (32 bit) + \details Executes a LDA exclusive instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDAEX (uint32_t)__builtin_arm_ldaex + + +/** + \brief Store-Release Exclusive (8 bit) + \details Executes a STLB exclusive instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEXB (uint32_t)__builtin_arm_stlex + + +/** + \brief Store-Release Exclusive (16 bit) + \details Executes a STLH exclusive instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEXH (uint32_t)__builtin_arm_stlex + + +/** + \brief Store-Release Exclusive (32 bit) + \details Executes a STL exclusive instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEX (uint32_t)__builtin_arm_stlex + +#endif /* (__ARM_ARCH_8M__ == 1U) */ + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if (__ARM_FEATURE_DSP == 1U) /* ToDo: ARMCC_V6: This should be ARCH >= ARMv7-M + SIMD */ + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __QASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __USAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#define __SSAT16(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +#define __USAT16(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SEL (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE int32_t __QADD( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__((always_inline)) __STATIC_INLINE int32_t __QSUB( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +#define __PKHBT(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + __ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) + +#define __PKHTB(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + if (ARG3 == 0) \ + __ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \ + else \ + __ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) + +__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) +{ + int32_t result; + + __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#endif /* (__ARM_FEATURE_DSP == 1U) */ +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#endif /* __CMSIS_ARMCC_V6_H */ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/cmsis_gcc.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/cmsis_gcc.h new file mode 100644 index 0000000..bb89fbb --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/cmsis_gcc.h @@ -0,0 +1,1373 @@ +/**************************************************************************//** + * @file cmsis_gcc.h + * @brief CMSIS Cortex-M Core Function/Instruction Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM 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: + - 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 COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (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 __CMSIS_GCC_H +#define __CMSIS_GCC_H + +/* ignore some GCC warnings */ +#if defined ( __GNUC__ ) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-conversion" +#pragma GCC diagnostic ignored "-Wconversion" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by clearing the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void) +{ + __ASM volatile ("cpsie i" : : : "memory"); +} + + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by setting the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void) +{ + __ASM volatile ("cpsid i" : : : "memory"); +} + + +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); +} + + +/** + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + + \return xPSR Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, psp\n" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0\n" : : "r" (topOfProcStack) : "sp"); +} + + +/** + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t result; + + __ASM volatile ("MRS %0, msp\n" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) : "sp"); +} + + +/** + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); +} + + +#if (__CORTEX_M >= 0x03U) + +/** + \brief Enable FIQ + \details Enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f" : : : "memory"); +} + + +/** + \brief Disable FIQ + \details Disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f" : : : "memory"); +} + + +/** + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI(uint32_t value) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (value) : "memory"); +} + + +/** + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI_MAX(uint32_t value) +{ + __ASM volatile ("MSR basepri_max, %0" : : "r" (value) : "memory"); +} + + +/** + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); +} + +#endif /* (__CORTEX_M >= 0x03U) */ + + +#if (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U) + +/** + \brief Get FPSCR + \details Returns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + uint32_t result; + + /* Empty asm statement works as a scheduling barrier */ + __ASM volatile (""); + __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); + __ASM volatile (""); + return(result); +#else + return(0); +#endif +} + + +/** + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set + */ +__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) + /* Empty asm statement works as a scheduling barrier */ + __ASM volatile (""); + __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc"); + __ASM volatile (""); +#endif +} + +#endif /* (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U) */ + + + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/* Define macros for porting to both thumb1 and thumb2. + * For thumb1, use low register (r0-r7), specified by constraint "l" + * Otherwise, use general registers, specified by constraint "r" */ +#if defined (__thumb__) && !defined (__thumb2__) +#define __CMSIS_GCC_OUT_REG(r) "=l" (r) +#define __CMSIS_GCC_USE_REG(r) "l" (r) +#else +#define __CMSIS_GCC_OUT_REG(r) "=r" (r) +#define __CMSIS_GCC_USE_REG(r) "r" (r) +#endif + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +__attribute__((always_inline)) __STATIC_INLINE void __NOP(void) +{ + __ASM volatile ("nop"); +} + + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +__attribute__((always_inline)) __STATIC_INLINE void __WFI(void) +{ + __ASM volatile ("wfi"); +} + + +/** + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +__attribute__((always_inline)) __STATIC_INLINE void __WFE(void) +{ + __ASM volatile ("wfe"); +} + + +/** + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +__attribute__((always_inline)) __STATIC_INLINE void __SEV(void) +{ + __ASM volatile ("sev"); +} + + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +__attribute__((always_inline)) __STATIC_INLINE void __ISB(void) +{ + __ASM volatile ("isb 0xF":::"memory"); +} + + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +__attribute__((always_inline)) __STATIC_INLINE void __DSB(void) +{ + __ASM volatile ("dsb 0xF":::"memory"); +} + + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +__attribute__((always_inline)) __STATIC_INLINE void __DMB(void) +{ + __ASM volatile ("dmb 0xF":::"memory"); +} + + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in integer value. + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __REV(uint32_t value) +{ +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) + return __builtin_bswap32(value); +#else + uint32_t result; + + __ASM volatile ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +#endif +} + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in two unsigned short values. + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __REV16(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** + \brief Reverse byte order in signed short value + \details Reverses the byte order in a signed short value with sign extension to integer. + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__((always_inline)) __STATIC_INLINE int32_t __REVSH(int32_t value) +{ +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + return (short)__builtin_bswap16(value); +#else + int32_t result; + + __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +#endif +} + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] value Value to rotate + \param [in] value Number of Bits to rotate + \return Rotated value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + return (op1 >> op2) | (op1 << (32U - op2)); +} + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __ASM volatile ("bkpt "#value) + + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + +#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) + __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); +#else + int32_t s = 4 /*sizeof(v)*/ * 8 - 1; /* extra shift needed at end */ + + result = value; /* r will be reversed bits of v; first get LSB of v */ + for (value >>= 1U; value; value >>= 1U) + { + result <<= 1U; + result |= value & 1U; + s--; + } + result <<= s; /* shift when v's highest bits are zero */ +#endif + return(result); +} + + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +#define __CLZ __builtin_clz + + +#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) + +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint8_t __LDREXB(volatile uint8_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint16_t __LDREXH(volatile uint16_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __LDREXW(volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) ); + return(result); +} + + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); + return(result); +} + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +__attribute__((always_inline)) __STATIC_INLINE void __CLREX(void) +{ + __ASM volatile ("clrex" ::: "memory"); +} + + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __RRX(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint8_t __LDRBT(volatile uint8_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrbt %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint16_t __LDRHT(volatile uint16_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrht %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __LDRT(volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*addr) ); + return(result); +} + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__attribute__((always_inline)) __STATIC_INLINE void __STRBT(uint8_t value, volatile uint8_t *addr) +{ + __ASM volatile ("strbt %1, %0" : "=Q" (*addr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__attribute__((always_inline)) __STATIC_INLINE void __STRHT(uint16_t value, volatile uint16_t *addr) +{ + __ASM volatile ("strht %1, %0" : "=Q" (*addr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__attribute__((always_inline)) __STATIC_INLINE void __STRT(uint32_t value, volatile uint32_t *addr) +{ + __ASM volatile ("strt %1, %0" : "=Q" (*addr) : "r" (value) ); +} + +#endif /* (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) */ + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if (__CORTEX_M >= 0x04U) /* only for Cortex-M4 and above */ + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#define __SSAT16(ARG1,ARG2) \ +({ \ + int32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +#define __USAT16(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SEL (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __QADD( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __QSUB( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +#define __PKHBT(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + __ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) + +#define __PKHTB(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + if (ARG3 == 0) \ + __ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \ + else \ + __ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) + +__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) +{ + int32_t result; + + __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#endif /* (__CORTEX_M >= 0x04) */ +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#if defined ( __GNUC__ ) +#pragma GCC diagnostic pop +#endif + +#endif /* __CMSIS_GCC_H */ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cm0.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cm0.h new file mode 100644 index 0000000..711dad5 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cm0.h @@ -0,0 +1,798 @@ +/**************************************************************************//** + * @file core_cm0.h + * @brief CMSIS Cortex-M0 Core Peripheral Access Layer Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM 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: + - 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 COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (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 ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CM0_H_GENERIC +#define __CORE_CM0_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
    + Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
    + Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
    + Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_M0 + @{ + */ + +/* CMSIS CM0 definitions */ +#define __CM0_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */ +#define __CM0_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */ +#define __CM0_CMSIS_VERSION ((__CM0_CMSIS_VERSION_MAIN << 16U) | \ + __CM0_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + +#define __CORTEX_M (0x00U) /*!< Cortex-M Core */ + + +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ + #define __STATIC_INLINE static inline + +#elif defined ( __TMS470__ ) + #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __CSMC__ ) + #define __packed + #define __ASM _asm /*!< asm keyword for COSMIC Compiler */ + #define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */ + #define __STATIC_INLINE static inline + +#else + #error Unknown compiler +#endif + +/** __FPU_USED indicates whether an FPU is used or not. + This core does not support an FPU at all +*/ +#define __FPU_USED 0U + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_PCS_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TMS470__ ) + #if defined __TI_VFP_SUPPORT__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#endif + +#include "core_cmInstr.h" /* Core Instruction Access */ +#include "core_cmFunc.h" /* Core Function Access */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM0_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM0_H_DEPENDANT +#define __CORE_CM0_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM0_REV + #define __CM0_REV 0x0000U + #warning "__CM0_REV not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 2U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex_M0 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t _reserved0:1; /*!< bit: 0 Reserved */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[31U]; + __IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[31U]; + __IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[31U]; + __IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[31U]; + uint32_t RESERVED4[64U]; + __IOM uint32_t IP[8U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */ +} NVIC_Type; + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + uint32_t RESERVED0; + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + uint32_t RESERVED1; + __IOM uint32_t SHP[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Cortex-M0 Core Debug Registers (DCB registers, SHCSR, and DFSR) are only accessible over DAP and not via processor. + Therefore they are not covered by the Cortex-M0 header file. + @{ + */ +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Cortex-M0 Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ + + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +/* Interrupt Priorities are WORD accessible only under ARMv6M */ +/* The following MACROS handle generation of the register offset and byte masks */ +#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL) +#define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) ) +#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) ) + + +/** + \brief Enable External Interrupt + \details Enables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Disable External Interrupt + \details Disables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Get Pending Interrupt + \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of an external interrupt. + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of an external interrupt. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of an interrupt. + \note The priority cannot be set for every core interrupt. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) < 0) + { + SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } + else + { + NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of an interrupt. + The interrupt number can be positive to specify an external (device specific) interrupt, + or negative to specify an internal (core) interrupt. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) < 0) + { + return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__STATIC_INLINE void NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + SCB_AIRCR_SYSRESETREQ_Msk); + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM0_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cm0plus.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cm0plus.h new file mode 100644 index 0000000..b04aa39 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cm0plus.h @@ -0,0 +1,914 @@ +/**************************************************************************//** + * @file core_cm0plus.h + * @brief CMSIS Cortex-M0+ Core Peripheral Access Layer Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM 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: + - 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 COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (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 ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CM0PLUS_H_GENERIC +#define __CORE_CM0PLUS_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
    + Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
    + Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
    + Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex-M0+ + @{ + */ + +/* CMSIS CM0+ definitions */ +#define __CM0PLUS_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */ +#define __CM0PLUS_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */ +#define __CM0PLUS_CMSIS_VERSION ((__CM0PLUS_CMSIS_VERSION_MAIN << 16U) | \ + __CM0PLUS_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + +#define __CORTEX_M (0x00U) /*!< Cortex-M Core */ + + +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ + #define __STATIC_INLINE static inline + +#elif defined ( __TMS470__ ) + #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __CSMC__ ) + #define __packed + #define __ASM _asm /*!< asm keyword for COSMIC Compiler */ + #define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */ + #define __STATIC_INLINE static inline + +#else + #error Unknown compiler +#endif + +/** __FPU_USED indicates whether an FPU is used or not. + This core does not support an FPU at all +*/ +#define __FPU_USED 0U + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_PCS_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TMS470__ ) + #if defined __TI_VFP_SUPPORT__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#endif + +#include "core_cmInstr.h" /* Core Instruction Access */ +#include "core_cmFunc.h" /* Core Function Access */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM0PLUS_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM0PLUS_H_DEPENDANT +#define __CORE_CM0PLUS_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM0PLUS_REV + #define __CM0PLUS_REV 0x0000U + #warning "__CM0PLUS_REV not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __VTOR_PRESENT + #define __VTOR_PRESENT 0U + #warning "__VTOR_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 2U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex-M0+ */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core MPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[31U]; + __IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[31U]; + __IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[31U]; + __IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[31U]; + uint32_t RESERVED4[64U]; + __IOM uint32_t IP[8U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */ +} NVIC_Type; + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ +#if (__VTOR_PRESENT == 1U) + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ +#else + uint32_t RESERVED0; +#endif + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + uint32_t RESERVED1; + __IOM uint32_t SHP[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +#if (__VTOR_PRESENT == 1U) +/* SCB Interrupt Control State Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 8U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0xFFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ +#endif + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + +#if (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ +} MPU_Type; + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_ADDR_Pos 8U /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0xFFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register Definitions */ +#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Cortex-M0+ Core Debug Registers (DCB registers, SHCSR, and DFSR) are only accessible over DAP and not via processor. + Therefore they are not covered by the Cortex-M0+ header file. + @{ + */ +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Cortex-M0+ Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ + +#if (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +/* Interrupt Priorities are WORD accessible only under ARMv6M */ +/* The following MACROS handle generation of the register offset and byte masks */ +#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL) +#define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) ) +#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) ) + + +/** + \brief Enable External Interrupt + \details Enables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Disable External Interrupt + \details Disables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Get Pending Interrupt + \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of an external interrupt. + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of an external interrupt. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of an interrupt. + \note The priority cannot be set for every core interrupt. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) < 0) + { + SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } + else + { + NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of an interrupt. + The interrupt number can be positive to specify an external (device specific) interrupt, + or negative to specify an internal (core) interrupt. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) < 0) + { + return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__STATIC_INLINE void NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + SCB_AIRCR_SYSRESETREQ_Msk); + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM0PLUS_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cm3.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cm3.h new file mode 100644 index 0000000..b4ac4c7 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cm3.h @@ -0,0 +1,1763 @@ +/**************************************************************************//** + * @file core_cm3.h + * @brief CMSIS Cortex-M3 Core Peripheral Access Layer Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM 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: + - 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 COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (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 ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CM3_H_GENERIC +#define __CORE_CM3_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
    + Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
    + Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
    + Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_M3 + @{ + */ + +/* CMSIS CM3 definitions */ +#define __CM3_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */ +#define __CM3_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */ +#define __CM3_CMSIS_VERSION ((__CM3_CMSIS_VERSION_MAIN << 16U) | \ + __CM3_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + +#define __CORTEX_M (0x03U) /*!< Cortex-M Core */ + + +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ + #define __STATIC_INLINE static inline + +#elif defined ( __TMS470__ ) + #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __CSMC__ ) + #define __packed + #define __ASM _asm /*!< asm keyword for COSMIC Compiler */ + #define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */ + #define __STATIC_INLINE static inline + +#else + #error Unknown compiler +#endif + +/** __FPU_USED indicates whether an FPU is used or not. + This core does not support an FPU at all +*/ +#define __FPU_USED 0U + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_PCS_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TMS470__ ) + #if defined __TI_VFP_SUPPORT__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#endif + +#include "core_cmInstr.h" /* Core Instruction Access */ +#include "core_cmFunc.h" /* Core Function Access */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM3_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM3_H_DEPENDANT +#define __CORE_CM3_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM3_REV + #define __CM3_REV 0x0200U + #warning "__CM3_REV not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 4U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex_M3 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + +#define APSR_Q_Pos 27U /*!< APSR: Q Position */ +#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ +#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ + +#define xPSR_IT_Pos 25U /*!< xPSR: IT Position */ +#define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24U]; + __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[24U]; + __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24U]; + __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24U]; + __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56U]; + __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHP[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[5U]; + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#if (__CM3_REV < 0x0201U) /* core r2p1 */ +#define SCB_VTOR_TBLBASE_Pos 29U /*!< SCB VTOR: TBLBASE Position */ +#define SCB_VTOR_TBLBASE_Msk (1UL << SCB_VTOR_TBLBASE_Pos) /*!< SCB VTOR: TBLBASE Mask */ + +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x3FFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ +#else +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ +#endif + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +#define SCB_AIRCR_VECTRESET_Pos 0U /*!< SCB AIRCR: VECTRESET Position */ +#define SCB_AIRCR_VECTRESET_Msk (1UL /*<< SCB_AIRCR_VECTRESET_Pos*/) /*!< SCB AIRCR: VECTRESET Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +#define SCB_CCR_NONBASETHRDENA_Pos 0U /*!< SCB CCR: NONBASETHRDENA Position */ +#define SCB_CCR_NONBASETHRDENA_Msk (1UL /*<< SCB_CCR_NONBASETHRDENA_Pos*/) /*!< SCB CCR: NONBASETHRDENA Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Register Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* SCB Hard Fault Status Register Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ +#if ((defined __CM3_REV) && (__CM3_REV >= 0x200U)) + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +#else + uint32_t RESERVED1[1U]; +#endif +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ + +/* Auxiliary Control Register Definitions */ + +#define SCnSCB_ACTLR_DISFOLD_Pos 2U /*!< ACTLR: DISFOLD Position */ +#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ + +#define SCnSCB_ACTLR_DISDEFWBUF_Pos 1U /*!< ACTLR: DISDEFWBUF Position */ +#define SCnSCB_ACTLR_DISDEFWBUF_Msk (1UL << SCnSCB_ACTLR_DISDEFWBUF_Pos) /*!< ACTLR: DISDEFWBUF Mask */ + +#define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */ +#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** + \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[29U]; + __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ + __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ + __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TraceBusID_Pos 16U /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPrescale_Pos 8U /*!< ITM TCR: TSPrescale Position */ +#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ + +#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Integration Write Register Definitions */ +#define ITM_IWR_ATVALIDM_Pos 0U /*!< ITM IWR: ATVALIDM Position */ +#define ITM_IWR_ATVALIDM_Msk (1UL /*<< ITM_IWR_ATVALIDM_Pos*/) /*!< ITM IWR: ATVALIDM Mask */ + +/* ITM Integration Read Register Definitions */ +#define ITM_IRR_ATREADYM_Pos 0U /*!< ITM IRR: ATREADYM Position */ +#define ITM_IRR_ATREADYM_Msk (1UL /*<< ITM_IRR_ATREADYM_Pos*/) /*!< ITM IRR: ATREADYM Mask */ + +/* ITM Integration Mode Control Register Definitions */ +#define ITM_IMCR_INTEGRATION_Pos 0U /*!< ITM IMCR: INTEGRATION Position */ +#define ITM_IMCR_INTEGRATION_Msk (1UL /*<< ITM_IMCR_INTEGRATION_Pos*/) /*!< ITM IMCR: INTEGRATION Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Mask Register Definitions */ +#define DWT_MASK_MASK_Pos 0U /*!< DWT MASK: MASK Position */ +#define DWT_MASK_MASK_Msk (0x1FUL /*<< DWT_MASK_MASK_Pos*/) /*!< DWT MASK: MASK Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVADDR1_Pos 16U /*!< DWT FUNCTION: DATAVADDR1 Position */ +#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ + +#define DWT_FUNCTION_DATAVADDR0_Pos 12U /*!< DWT FUNCTION: DATAVADDR0 Position */ +#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_LNK1ENA_Pos 9U /*!< DWT FUNCTION: LNK1ENA Position */ +#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ + +#define DWT_FUNCTION_DATAVMATCH_Pos 8U /*!< DWT FUNCTION: DATAVMATCH Position */ +#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ + +#define DWT_FUNCTION_CYCMATCH_Pos 7U /*!< DWT FUNCTION: CYCMATCH Position */ +#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ + +#define DWT_FUNCTION_EMITRANGE_Pos 5U /*!< DWT FUNCTION: EMITRANGE Position */ +#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ + +#define DWT_FUNCTION_FUNCTION_Pos 0U /*!< DWT FUNCTION: FUNCTION Position */ +#define DWT_FUNCTION_FUNCTION_Msk (0xFUL /*<< DWT_FUNCTION_FUNCTION_Pos*/) /*!< DWT FUNCTION: FUNCTION Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IOM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ + __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY_Pos 0U /*!< TPI ITATBCTR2: ATREADY Position */ +#define TPI_ITATBCTR2_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY_Pos*/) /*!< TPI ITATBCTR2: ATREADY Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY_Pos 0U /*!< TPI ITATBCTR0: ATREADY Position */ +#define TPI_ITATBCTR0_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY_Pos*/) /*!< TPI ITATBCTR0: ATREADY Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x1UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_MajorType_Pos 4U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +#define TPI_DEVTYPE_SubType_Pos 0U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ +} MPU_Type; + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register Definitions */ +#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register Definitions */ +#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Cortex-M3 Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +/** + \brief Set Priority Grouping + \details Sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */ + SCB->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping + \details Reads the priority grouping field from the NVIC Interrupt Controller. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t NVIC_GetPriorityGrouping(void) +{ + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable External Interrupt + \details Enables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Disable External Interrupt + \details Disables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Get Pending Interrupt + \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t)(((NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of an external interrupt. + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of an external interrupt. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in NVIC and returns the active bit. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + */ +__STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) +{ + return((uint32_t)(((NVIC->IABR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of an interrupt. + \note The priority cannot be set for every core interrupt. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) < 0) + { + SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + NVIC->IP[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of an interrupt. + The interrupt number can be positive to specify an external (device specific) interrupt, + or negative to specify an internal (core) interrupt. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) < 0) + { + return(((uint32_t)SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)NVIC->IP[((uint32_t)(int32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__STATIC_INLINE void NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY 0x5AA55AA5U /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** + \brief ITM Send Character + \details Transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + \param [in] ch Character to transmit. + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; + } + return (ch); +} + + +/** + \brief ITM Receive Character + \details Inputs a character via the external variable \ref ITM_RxBuffer. + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) +{ + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** + \brief ITM Check Character + \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) +{ + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM3_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cm4.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cm4.h new file mode 100644 index 0000000..dc840eb --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cm4.h @@ -0,0 +1,1937 @@ +/**************************************************************************//** + * @file core_cm4.h + * @brief CMSIS Cortex-M4 Core Peripheral Access Layer Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM 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: + - 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 COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (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 ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CM4_H_GENERIC +#define __CORE_CM4_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
    + Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
    + Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
    + Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_M4 + @{ + */ + +/* CMSIS CM4 definitions */ +#define __CM4_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */ +#define __CM4_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */ +#define __CM4_CMSIS_VERSION ((__CM4_CMSIS_VERSION_MAIN << 16U) | \ + __CM4_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + +#define __CORTEX_M (0x04U) /*!< Cortex-M Core */ + + +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ + #define __STATIC_INLINE static inline + +#elif defined ( __TMS470__ ) + #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __CSMC__ ) + #define __packed + #define __ASM _asm /*!< asm keyword for COSMIC Compiler */ + #define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */ + #define __STATIC_INLINE static inline + +#else + #error Unknown compiler +#endif + +/** __FPU_USED indicates whether an FPU is used or not. + For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. +*/ +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_PCS_VFP + #if (__FPU_PRESENT == 1) + #define __FPU_USED 1U + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TMS470__ ) + #if defined __TI_VFP_SUPPORT__ + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#endif + +#include "core_cmInstr.h" /* Core Instruction Access */ +#include "core_cmFunc.h" /* Core Function Access */ +#include "core_cmSimd.h" /* Compiler specific SIMD Intrinsics */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM4_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM4_H_DEPENDANT +#define __CORE_CM4_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM4_REV + #define __CM4_REV 0x0000U + #warning "__CM4_REV not defined in device header file; using default!" + #endif + + #ifndef __FPU_PRESENT + #define __FPU_PRESENT 0U + #warning "__FPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 4U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex_M4 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + - Core FPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + +#define APSR_Q_Pos 27U /*!< APSR: Q Position */ +#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ + +#define APSR_GE_Pos 16U /*!< APSR: GE Position */ +#define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ +#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ + +#define xPSR_IT_Pos 25U /*!< xPSR: IT Position */ +#define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_GE_Pos 16U /*!< xPSR: GE Position */ +#define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */ + uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */ +#define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */ + +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24U]; + __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[24U]; + __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24U]; + __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24U]; + __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56U]; + __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHP[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[5U]; + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +#define SCB_AIRCR_VECTRESET_Pos 0U /*!< SCB AIRCR: VECTRESET Position */ +#define SCB_AIRCR_VECTRESET_Msk (1UL /*<< SCB_AIRCR_VECTRESET_Pos*/) /*!< SCB AIRCR: VECTRESET Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +#define SCB_CCR_NONBASETHRDENA_Pos 0U /*!< SCB CCR: NONBASETHRDENA Position */ +#define SCB_CCR_NONBASETHRDENA_Msk (1UL /*<< SCB_CCR_NONBASETHRDENA_Pos*/) /*!< SCB CCR: NONBASETHRDENA Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Register Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* SCB Hard Fault Status Register Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ + +/* Auxiliary Control Register Definitions */ +#define SCnSCB_ACTLR_DISOOFP_Pos 9U /*!< ACTLR: DISOOFP Position */ +#define SCnSCB_ACTLR_DISOOFP_Msk (1UL << SCnSCB_ACTLR_DISOOFP_Pos) /*!< ACTLR: DISOOFP Mask */ + +#define SCnSCB_ACTLR_DISFPCA_Pos 8U /*!< ACTLR: DISFPCA Position */ +#define SCnSCB_ACTLR_DISFPCA_Msk (1UL << SCnSCB_ACTLR_DISFPCA_Pos) /*!< ACTLR: DISFPCA Mask */ + +#define SCnSCB_ACTLR_DISFOLD_Pos 2U /*!< ACTLR: DISFOLD Position */ +#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ + +#define SCnSCB_ACTLR_DISDEFWBUF_Pos 1U /*!< ACTLR: DISDEFWBUF Position */ +#define SCnSCB_ACTLR_DISDEFWBUF_Msk (1UL << SCnSCB_ACTLR_DISDEFWBUF_Pos) /*!< ACTLR: DISDEFWBUF Mask */ + +#define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */ +#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** + \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[29U]; + __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ + __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ + __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TraceBusID_Pos 16U /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPrescale_Pos 8U /*!< ITM TCR: TSPrescale Position */ +#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ + +#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Integration Write Register Definitions */ +#define ITM_IWR_ATVALIDM_Pos 0U /*!< ITM IWR: ATVALIDM Position */ +#define ITM_IWR_ATVALIDM_Msk (1UL /*<< ITM_IWR_ATVALIDM_Pos*/) /*!< ITM IWR: ATVALIDM Mask */ + +/* ITM Integration Read Register Definitions */ +#define ITM_IRR_ATREADYM_Pos 0U /*!< ITM IRR: ATREADYM Position */ +#define ITM_IRR_ATREADYM_Msk (1UL /*<< ITM_IRR_ATREADYM_Pos*/) /*!< ITM IRR: ATREADYM Mask */ + +/* ITM Integration Mode Control Register Definitions */ +#define ITM_IMCR_INTEGRATION_Pos 0U /*!< ITM IMCR: INTEGRATION Position */ +#define ITM_IMCR_INTEGRATION_Msk (1UL /*<< ITM_IMCR_INTEGRATION_Pos*/) /*!< ITM IMCR: INTEGRATION Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Mask Register Definitions */ +#define DWT_MASK_MASK_Pos 0U /*!< DWT MASK: MASK Position */ +#define DWT_MASK_MASK_Msk (0x1FUL /*<< DWT_MASK_MASK_Pos*/) /*!< DWT MASK: MASK Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVADDR1_Pos 16U /*!< DWT FUNCTION: DATAVADDR1 Position */ +#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ + +#define DWT_FUNCTION_DATAVADDR0_Pos 12U /*!< DWT FUNCTION: DATAVADDR0 Position */ +#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_LNK1ENA_Pos 9U /*!< DWT FUNCTION: LNK1ENA Position */ +#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ + +#define DWT_FUNCTION_DATAVMATCH_Pos 8U /*!< DWT FUNCTION: DATAVMATCH Position */ +#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ + +#define DWT_FUNCTION_CYCMATCH_Pos 7U /*!< DWT FUNCTION: CYCMATCH Position */ +#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ + +#define DWT_FUNCTION_EMITRANGE_Pos 5U /*!< DWT FUNCTION: EMITRANGE Position */ +#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ + +#define DWT_FUNCTION_FUNCTION_Pos 0U /*!< DWT FUNCTION: FUNCTION Position */ +#define DWT_FUNCTION_FUNCTION_Msk (0xFUL /*<< DWT_FUNCTION_FUNCTION_Pos*/) /*!< DWT FUNCTION: FUNCTION Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IOM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ + __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY_Pos 0U /*!< TPI ITATBCTR2: ATREADY Position */ +#define TPI_ITATBCTR2_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY_Pos*/) /*!< TPI ITATBCTR2: ATREADY Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY_Pos 0U /*!< TPI ITATBCTR0: ATREADY Position */ +#define TPI_ITATBCTR0_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY_Pos*/) /*!< TPI ITATBCTR0: ATREADY Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x1UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_MajorType_Pos 4U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +#define TPI_DEVTYPE_SubType_Pos 0U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ +} MPU_Type; + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register Definitions */ +#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +#if (__FPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_FPU Floating Point Unit (FPU) + \brief Type definitions for the Floating Point Unit (FPU) + @{ + */ + +/** + \brief Structure type to access the Floating Point Unit (FPU). + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ + __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ + __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ + __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ +} FPU_Type; + +/* Floating-Point Context Control Register Definitions */ +#define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */ +#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */ + +#define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */ +#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */ + +#define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */ +#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */ + +#define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */ +#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */ + +#define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */ +#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */ + +#define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */ +#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */ + +#define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */ +#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */ + +#define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */ +#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */ + +#define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */ +#define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */ + +/* Floating-Point Context Address Register Definitions */ +#define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */ +#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */ + +/* Floating-Point Default Status Control Register Definitions */ +#define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */ +#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */ + +#define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */ +#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */ + +#define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */ +#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */ + +#define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */ +#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */ + +/* Media and FP Feature Register 0 Definitions */ +#define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */ +#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */ + +#define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */ +#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */ + +#define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */ +#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */ + +#define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */ +#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */ + +#define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */ +#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */ + +#define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */ +#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */ + +#define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */ +#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */ + +#define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */ +#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */ + +/* Media and FP Feature Register 1 Definitions */ +#define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */ +#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */ + +#define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */ +#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */ + +#define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */ +#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */ + +#define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */ +#define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */ + +/*@} end of group CMSIS_FPU */ +#endif + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register Definitions */ +#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Cortex-M4 Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +#if (__FPU_PRESENT == 1U) + #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ + #define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +/** + \brief Set Priority Grouping + \details Sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */ + SCB->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping + \details Reads the priority grouping field from the NVIC Interrupt Controller. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t NVIC_GetPriorityGrouping(void) +{ + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable External Interrupt + \details Enables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Disable External Interrupt + \details Disables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Get Pending Interrupt + \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t)(((NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of an external interrupt. + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of an external interrupt. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in NVIC and returns the active bit. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + */ +__STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) +{ + return((uint32_t)(((NVIC->IABR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of an interrupt. + \note The priority cannot be set for every core interrupt. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) < 0) + { + SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + NVIC->IP[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of an interrupt. + The interrupt number can be positive to specify an external (device specific) interrupt, + or negative to specify an internal (core) interrupt. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) < 0) + { + return(((uint32_t)SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)NVIC->IP[((uint32_t)(int32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__STATIC_INLINE void NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY 0x5AA55AA5U /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** + \brief ITM Send Character + \details Transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + \param [in] ch Character to transmit. + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; + } + return (ch); +} + + +/** + \brief ITM Receive Character + \details Inputs a character via the external variable \ref ITM_RxBuffer. + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) +{ + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** + \brief ITM Check Character + \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) +{ + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM4_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cm7.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cm7.h new file mode 100644 index 0000000..3b7530a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cm7.h @@ -0,0 +1,2512 @@ +/**************************************************************************//** + * @file core_cm7.h + * @brief CMSIS Cortex-M7 Core Peripheral Access Layer Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM 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: + - 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 COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (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 ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CM7_H_GENERIC +#define __CORE_CM7_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
    + Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
    + Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
    + Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_M7 + @{ + */ + +/* CMSIS CM7 definitions */ +#define __CM7_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */ +#define __CM7_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */ +#define __CM7_CMSIS_VERSION ((__CM7_CMSIS_VERSION_MAIN << 16U) | \ + __CM7_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + +#define __CORTEX_M (0x07U) /*!< Cortex-M Core */ + + +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ + #define __STATIC_INLINE static inline + +#elif defined ( __TMS470__ ) + #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __CSMC__ ) + #define __packed + #define __ASM _asm /*!< asm keyword for COSMIC Compiler */ + #define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */ + #define __STATIC_INLINE static inline + +#else + #error Unknown compiler +#endif + +/** __FPU_USED indicates whether an FPU is used or not. + For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. +*/ +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_PCS_VFP + #if (__FPU_PRESENT == 1) + #define __FPU_USED 1U + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TMS470__ ) + #if defined __TI_VFP_SUPPORT__ + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #if (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#endif + +#include "core_cmInstr.h" /* Core Instruction Access */ +#include "core_cmFunc.h" /* Core Function Access */ +#include "core_cmSimd.h" /* Compiler specific SIMD Intrinsics */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM7_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM7_H_DEPENDANT +#define __CORE_CM7_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM7_REV + #define __CM7_REV 0x0000U + #warning "__CM7_REV not defined in device header file; using default!" + #endif + + #ifndef __FPU_PRESENT + #define __FPU_PRESENT 0U + #warning "__FPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __ICACHE_PRESENT + #define __ICACHE_PRESENT 0U + #warning "__ICACHE_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __DCACHE_PRESENT + #define __DCACHE_PRESENT 0U + #warning "__DCACHE_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __DTCM_PRESENT + #define __DTCM_PRESENT 0U + #warning "__DTCM_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 3U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex_M7 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + - Core FPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + +#define APSR_Q_Pos 27U /*!< APSR: Q Position */ +#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ + +#define APSR_GE_Pos 16U /*!< APSR: GE Position */ +#define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ +#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ + +#define xPSR_IT_Pos 25U /*!< xPSR: IT Position */ +#define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_GE_Pos 16U /*!< xPSR: GE Position */ +#define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */ + uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */ +#define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */ + +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24U]; + __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[24U]; + __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24U]; + __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24U]; + __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56U]; + __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHPR[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t ID_PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t ID_DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ID_AFR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t ID_MFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ID_ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[1U]; + __IM uint32_t CLIDR; /*!< Offset: 0x078 (R/ ) Cache Level ID register */ + __IM uint32_t CTR; /*!< Offset: 0x07C (R/ ) Cache Type register */ + __IM uint32_t CCSIDR; /*!< Offset: 0x080 (R/ ) Cache Size ID Register */ + __IOM uint32_t CSSELR; /*!< Offset: 0x084 (R/W) Cache Size Selection Register */ + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ + uint32_t RESERVED3[93U]; + __OM uint32_t STIR; /*!< Offset: 0x200 ( /W) Software Triggered Interrupt Register */ + uint32_t RESERVED4[15U]; + __IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */ + __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 1 */ + uint32_t RESERVED5[1U]; + __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */ + uint32_t RESERVED6[1U]; + __OM uint32_t ICIMVAU; /*!< Offset: 0x258 ( /W) I-Cache Invalidate by MVA to PoU */ + __OM uint32_t DCIMVAC; /*!< Offset: 0x25C ( /W) D-Cache Invalidate by MVA to PoC */ + __OM uint32_t DCISW; /*!< Offset: 0x260 ( /W) D-Cache Invalidate by Set-way */ + __OM uint32_t DCCMVAU; /*!< Offset: 0x264 ( /W) D-Cache Clean by MVA to PoU */ + __OM uint32_t DCCMVAC; /*!< Offset: 0x268 ( /W) D-Cache Clean by MVA to PoC */ + __OM uint32_t DCCSW; /*!< Offset: 0x26C ( /W) D-Cache Clean by Set-way */ + __OM uint32_t DCCIMVAC; /*!< Offset: 0x270 ( /W) D-Cache Clean and Invalidate by MVA to PoC */ + __OM uint32_t DCCISW; /*!< Offset: 0x274 ( /W) D-Cache Clean and Invalidate by Set-way */ + uint32_t RESERVED7[6U]; + __IOM uint32_t ITCMCR; /*!< Offset: 0x290 (R/W) Instruction Tightly-Coupled Memory Control Register */ + __IOM uint32_t DTCMCR; /*!< Offset: 0x294 (R/W) Data Tightly-Coupled Memory Control Registers */ + __IOM uint32_t AHBPCR; /*!< Offset: 0x298 (R/W) AHBP Control Register */ + __IOM uint32_t CACR; /*!< Offset: 0x29C (R/W) L1 Cache Control Register */ + __IOM uint32_t AHBSCR; /*!< Offset: 0x2A0 (R/W) AHB Slave Control Register */ + uint32_t RESERVED8[1U]; + __IOM uint32_t ABFSR; /*!< Offset: 0x2A8 (R/W) Auxiliary Bus Fault Status Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +#define SCB_AIRCR_VECTRESET_Pos 0U /*!< SCB AIRCR: VECTRESET Position */ +#define SCB_AIRCR_VECTRESET_Msk (1UL /*<< SCB_AIRCR_VECTRESET_Pos*/) /*!< SCB AIRCR: VECTRESET Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_BP_Pos 18U /*!< SCB CCR: Branch prediction enable bit Position */ +#define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: Branch prediction enable bit Mask */ + +#define SCB_CCR_IC_Pos 17U /*!< SCB CCR: Instruction cache enable bit Position */ +#define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: Instruction cache enable bit Mask */ + +#define SCB_CCR_DC_Pos 16U /*!< SCB CCR: Cache enable bit Position */ +#define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: Cache enable bit Mask */ + +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +#define SCB_CCR_NONBASETHRDENA_Pos 0U /*!< SCB CCR: NONBASETHRDENA Position */ +#define SCB_CCR_NONBASETHRDENA_Msk (1UL /*<< SCB_CCR_NONBASETHRDENA_Pos*/) /*!< SCB CCR: NONBASETHRDENA Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Register Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* SCB Hard Fault Status Register Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ + +/* SCB Cache Level ID Register Definitions */ +#define SCB_CLIDR_LOUU_Pos 27U /*!< SCB CLIDR: LoUU Position */ +#define SCB_CLIDR_LOUU_Msk (7UL << SCB_CLIDR_LOUU_Pos) /*!< SCB CLIDR: LoUU Mask */ + +#define SCB_CLIDR_LOC_Pos 24U /*!< SCB CLIDR: LoC Position */ +#define SCB_CLIDR_LOC_Msk (7UL << SCB_CLIDR_LOC_Pos) /*!< SCB CLIDR: LoC Mask */ + +/* SCB Cache Type Register Definitions */ +#define SCB_CTR_FORMAT_Pos 29U /*!< SCB CTR: Format Position */ +#define SCB_CTR_FORMAT_Msk (7UL << SCB_CTR_FORMAT_Pos) /*!< SCB CTR: Format Mask */ + +#define SCB_CTR_CWG_Pos 24U /*!< SCB CTR: CWG Position */ +#define SCB_CTR_CWG_Msk (0xFUL << SCB_CTR_CWG_Pos) /*!< SCB CTR: CWG Mask */ + +#define SCB_CTR_ERG_Pos 20U /*!< SCB CTR: ERG Position */ +#define SCB_CTR_ERG_Msk (0xFUL << SCB_CTR_ERG_Pos) /*!< SCB CTR: ERG Mask */ + +#define SCB_CTR_DMINLINE_Pos 16U /*!< SCB CTR: DminLine Position */ +#define SCB_CTR_DMINLINE_Msk (0xFUL << SCB_CTR_DMINLINE_Pos) /*!< SCB CTR: DminLine Mask */ + +#define SCB_CTR_IMINLINE_Pos 0U /*!< SCB CTR: ImInLine Position */ +#define SCB_CTR_IMINLINE_Msk (0xFUL /*<< SCB_CTR_IMINLINE_Pos*/) /*!< SCB CTR: ImInLine Mask */ + +/* SCB Cache Size ID Register Definitions */ +#define SCB_CCSIDR_WT_Pos 31U /*!< SCB CCSIDR: WT Position */ +#define SCB_CCSIDR_WT_Msk (1UL << SCB_CCSIDR_WT_Pos) /*!< SCB CCSIDR: WT Mask */ + +#define SCB_CCSIDR_WB_Pos 30U /*!< SCB CCSIDR: WB Position */ +#define SCB_CCSIDR_WB_Msk (1UL << SCB_CCSIDR_WB_Pos) /*!< SCB CCSIDR: WB Mask */ + +#define SCB_CCSIDR_RA_Pos 29U /*!< SCB CCSIDR: RA Position */ +#define SCB_CCSIDR_RA_Msk (1UL << SCB_CCSIDR_RA_Pos) /*!< SCB CCSIDR: RA Mask */ + +#define SCB_CCSIDR_WA_Pos 28U /*!< SCB CCSIDR: WA Position */ +#define SCB_CCSIDR_WA_Msk (1UL << SCB_CCSIDR_WA_Pos) /*!< SCB CCSIDR: WA Mask */ + +#define SCB_CCSIDR_NUMSETS_Pos 13U /*!< SCB CCSIDR: NumSets Position */ +#define SCB_CCSIDR_NUMSETS_Msk (0x7FFFUL << SCB_CCSIDR_NUMSETS_Pos) /*!< SCB CCSIDR: NumSets Mask */ + +#define SCB_CCSIDR_ASSOCIATIVITY_Pos 3U /*!< SCB CCSIDR: Associativity Position */ +#define SCB_CCSIDR_ASSOCIATIVITY_Msk (0x3FFUL << SCB_CCSIDR_ASSOCIATIVITY_Pos) /*!< SCB CCSIDR: Associativity Mask */ + +#define SCB_CCSIDR_LINESIZE_Pos 0U /*!< SCB CCSIDR: LineSize Position */ +#define SCB_CCSIDR_LINESIZE_Msk (7UL /*<< SCB_CCSIDR_LINESIZE_Pos*/) /*!< SCB CCSIDR: LineSize Mask */ + +/* SCB Cache Size Selection Register Definitions */ +#define SCB_CSSELR_LEVEL_Pos 1U /*!< SCB CSSELR: Level Position */ +#define SCB_CSSELR_LEVEL_Msk (7UL << SCB_CSSELR_LEVEL_Pos) /*!< SCB CSSELR: Level Mask */ + +#define SCB_CSSELR_IND_Pos 0U /*!< SCB CSSELR: InD Position */ +#define SCB_CSSELR_IND_Msk (1UL /*<< SCB_CSSELR_IND_Pos*/) /*!< SCB CSSELR: InD Mask */ + +/* SCB Software Triggered Interrupt Register Definitions */ +#define SCB_STIR_INTID_Pos 0U /*!< SCB STIR: INTID Position */ +#define SCB_STIR_INTID_Msk (0x1FFUL /*<< SCB_STIR_INTID_Pos*/) /*!< SCB STIR: INTID Mask */ + +/* SCB D-Cache Invalidate by Set-way Register Definitions */ +#define SCB_DCISW_WAY_Pos 30U /*!< SCB DCISW: Way Position */ +#define SCB_DCISW_WAY_Msk (3UL << SCB_DCISW_WAY_Pos) /*!< SCB DCISW: Way Mask */ + +#define SCB_DCISW_SET_Pos 5U /*!< SCB DCISW: Set Position */ +#define SCB_DCISW_SET_Msk (0x1FFUL << SCB_DCISW_SET_Pos) /*!< SCB DCISW: Set Mask */ + +/* SCB D-Cache Clean by Set-way Register Definitions */ +#define SCB_DCCSW_WAY_Pos 30U /*!< SCB DCCSW: Way Position */ +#define SCB_DCCSW_WAY_Msk (3UL << SCB_DCCSW_WAY_Pos) /*!< SCB DCCSW: Way Mask */ + +#define SCB_DCCSW_SET_Pos 5U /*!< SCB DCCSW: Set Position */ +#define SCB_DCCSW_SET_Msk (0x1FFUL << SCB_DCCSW_SET_Pos) /*!< SCB DCCSW: Set Mask */ + +/* SCB D-Cache Clean and Invalidate by Set-way Register Definitions */ +#define SCB_DCCISW_WAY_Pos 30U /*!< SCB DCCISW: Way Position */ +#define SCB_DCCISW_WAY_Msk (3UL << SCB_DCCISW_WAY_Pos) /*!< SCB DCCISW: Way Mask */ + +#define SCB_DCCISW_SET_Pos 5U /*!< SCB DCCISW: Set Position */ +#define SCB_DCCISW_SET_Msk (0x1FFUL << SCB_DCCISW_SET_Pos) /*!< SCB DCCISW: Set Mask */ + +/* Instruction Tightly-Coupled Memory Control Register Definitions */ +#define SCB_ITCMCR_SZ_Pos 3U /*!< SCB ITCMCR: SZ Position */ +#define SCB_ITCMCR_SZ_Msk (0xFUL << SCB_ITCMCR_SZ_Pos) /*!< SCB ITCMCR: SZ Mask */ + +#define SCB_ITCMCR_RETEN_Pos 2U /*!< SCB ITCMCR: RETEN Position */ +#define SCB_ITCMCR_RETEN_Msk (1UL << SCB_ITCMCR_RETEN_Pos) /*!< SCB ITCMCR: RETEN Mask */ + +#define SCB_ITCMCR_RMW_Pos 1U /*!< SCB ITCMCR: RMW Position */ +#define SCB_ITCMCR_RMW_Msk (1UL << SCB_ITCMCR_RMW_Pos) /*!< SCB ITCMCR: RMW Mask */ + +#define SCB_ITCMCR_EN_Pos 0U /*!< SCB ITCMCR: EN Position */ +#define SCB_ITCMCR_EN_Msk (1UL /*<< SCB_ITCMCR_EN_Pos*/) /*!< SCB ITCMCR: EN Mask */ + +/* Data Tightly-Coupled Memory Control Register Definitions */ +#define SCB_DTCMCR_SZ_Pos 3U /*!< SCB DTCMCR: SZ Position */ +#define SCB_DTCMCR_SZ_Msk (0xFUL << SCB_DTCMCR_SZ_Pos) /*!< SCB DTCMCR: SZ Mask */ + +#define SCB_DTCMCR_RETEN_Pos 2U /*!< SCB DTCMCR: RETEN Position */ +#define SCB_DTCMCR_RETEN_Msk (1UL << SCB_DTCMCR_RETEN_Pos) /*!< SCB DTCMCR: RETEN Mask */ + +#define SCB_DTCMCR_RMW_Pos 1U /*!< SCB DTCMCR: RMW Position */ +#define SCB_DTCMCR_RMW_Msk (1UL << SCB_DTCMCR_RMW_Pos) /*!< SCB DTCMCR: RMW Mask */ + +#define SCB_DTCMCR_EN_Pos 0U /*!< SCB DTCMCR: EN Position */ +#define SCB_DTCMCR_EN_Msk (1UL /*<< SCB_DTCMCR_EN_Pos*/) /*!< SCB DTCMCR: EN Mask */ + +/* AHBP Control Register Definitions */ +#define SCB_AHBPCR_SZ_Pos 1U /*!< SCB AHBPCR: SZ Position */ +#define SCB_AHBPCR_SZ_Msk (7UL << SCB_AHBPCR_SZ_Pos) /*!< SCB AHBPCR: SZ Mask */ + +#define SCB_AHBPCR_EN_Pos 0U /*!< SCB AHBPCR: EN Position */ +#define SCB_AHBPCR_EN_Msk (1UL /*<< SCB_AHBPCR_EN_Pos*/) /*!< SCB AHBPCR: EN Mask */ + +/* L1 Cache Control Register Definitions */ +#define SCB_CACR_FORCEWT_Pos 2U /*!< SCB CACR: FORCEWT Position */ +#define SCB_CACR_FORCEWT_Msk (1UL << SCB_CACR_FORCEWT_Pos) /*!< SCB CACR: FORCEWT Mask */ + +#define SCB_CACR_ECCEN_Pos 1U /*!< SCB CACR: ECCEN Position */ +#define SCB_CACR_ECCEN_Msk (1UL << SCB_CACR_ECCEN_Pos) /*!< SCB CACR: ECCEN Mask */ + +#define SCB_CACR_SIWT_Pos 0U /*!< SCB CACR: SIWT Position */ +#define SCB_CACR_SIWT_Msk (1UL /*<< SCB_CACR_SIWT_Pos*/) /*!< SCB CACR: SIWT Mask */ + +/* AHBS Control Register Definitions */ +#define SCB_AHBSCR_INITCOUNT_Pos 11U /*!< SCB AHBSCR: INITCOUNT Position */ +#define SCB_AHBSCR_INITCOUNT_Msk (0x1FUL << SCB_AHBPCR_INITCOUNT_Pos) /*!< SCB AHBSCR: INITCOUNT Mask */ + +#define SCB_AHBSCR_TPRI_Pos 2U /*!< SCB AHBSCR: TPRI Position */ +#define SCB_AHBSCR_TPRI_Msk (0x1FFUL << SCB_AHBPCR_TPRI_Pos) /*!< SCB AHBSCR: TPRI Mask */ + +#define SCB_AHBSCR_CTL_Pos 0U /*!< SCB AHBSCR: CTL Position*/ +#define SCB_AHBSCR_CTL_Msk (3UL /*<< SCB_AHBPCR_CTL_Pos*/) /*!< SCB AHBSCR: CTL Mask */ + +/* Auxiliary Bus Fault Status Register Definitions */ +#define SCB_ABFSR_AXIMTYPE_Pos 8U /*!< SCB ABFSR: AXIMTYPE Position*/ +#define SCB_ABFSR_AXIMTYPE_Msk (3UL << SCB_ABFSR_AXIMTYPE_Pos) /*!< SCB ABFSR: AXIMTYPE Mask */ + +#define SCB_ABFSR_EPPB_Pos 4U /*!< SCB ABFSR: EPPB Position*/ +#define SCB_ABFSR_EPPB_Msk (1UL << SCB_ABFSR_EPPB_Pos) /*!< SCB ABFSR: EPPB Mask */ + +#define SCB_ABFSR_AXIM_Pos 3U /*!< SCB ABFSR: AXIM Position*/ +#define SCB_ABFSR_AXIM_Msk (1UL << SCB_ABFSR_AXIM_Pos) /*!< SCB ABFSR: AXIM Mask */ + +#define SCB_ABFSR_AHBP_Pos 2U /*!< SCB ABFSR: AHBP Position*/ +#define SCB_ABFSR_AHBP_Msk (1UL << SCB_ABFSR_AHBP_Pos) /*!< SCB ABFSR: AHBP Mask */ + +#define SCB_ABFSR_DTCM_Pos 1U /*!< SCB ABFSR: DTCM Position*/ +#define SCB_ABFSR_DTCM_Msk (1UL << SCB_ABFSR_DTCM_Pos) /*!< SCB ABFSR: DTCM Mask */ + +#define SCB_ABFSR_ITCM_Pos 0U /*!< SCB ABFSR: ITCM Position*/ +#define SCB_ABFSR_ITCM_Msk (1UL /*<< SCB_ABFSR_ITCM_Pos*/) /*!< SCB ABFSR: ITCM Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ + +/* Auxiliary Control Register Definitions */ +#define SCnSCB_ACTLR_DISITMATBFLUSH_Pos 12U /*!< ACTLR: DISITMATBFLUSH Position */ +#define SCnSCB_ACTLR_DISITMATBFLUSH_Msk (1UL << SCnSCB_ACTLR_DISITMATBFLUSH_Pos) /*!< ACTLR: DISITMATBFLUSH Mask */ + +#define SCnSCB_ACTLR_DISRAMODE_Pos 11U /*!< ACTLR: DISRAMODE Position */ +#define SCnSCB_ACTLR_DISRAMODE_Msk (1UL << SCnSCB_ACTLR_DISRAMODE_Pos) /*!< ACTLR: DISRAMODE Mask */ + +#define SCnSCB_ACTLR_FPEXCODIS_Pos 10U /*!< ACTLR: FPEXCODIS Position */ +#define SCnSCB_ACTLR_FPEXCODIS_Msk (1UL << SCnSCB_ACTLR_FPEXCODIS_Pos) /*!< ACTLR: FPEXCODIS Mask */ + +#define SCnSCB_ACTLR_DISFOLD_Pos 2U /*!< ACTLR: DISFOLD Position */ +#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ + +#define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */ +#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** + \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[29U]; + __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ + __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ + __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TraceBusID_Pos 16U /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPrescale_Pos 8U /*!< ITM TCR: TSPrescale Position */ +#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ + +#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Integration Write Register Definitions */ +#define ITM_IWR_ATVALIDM_Pos 0U /*!< ITM IWR: ATVALIDM Position */ +#define ITM_IWR_ATVALIDM_Msk (1UL /*<< ITM_IWR_ATVALIDM_Pos*/) /*!< ITM IWR: ATVALIDM Mask */ + +/* ITM Integration Read Register Definitions */ +#define ITM_IRR_ATREADYM_Pos 0U /*!< ITM IRR: ATREADYM Position */ +#define ITM_IRR_ATREADYM_Msk (1UL /*<< ITM_IRR_ATREADYM_Pos*/) /*!< ITM IRR: ATREADYM Mask */ + +/* ITM Integration Mode Control Register Definitions */ +#define ITM_IMCR_INTEGRATION_Pos 0U /*!< ITM IMCR: INTEGRATION Position */ +#define ITM_IMCR_INTEGRATION_Msk (1UL /*<< ITM_IMCR_INTEGRATION_Pos*/) /*!< ITM IMCR: INTEGRATION Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ + uint32_t RESERVED3[981U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( W) Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R ) Lock Status Register */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Mask Register Definitions */ +#define DWT_MASK_MASK_Pos 0U /*!< DWT MASK: MASK Position */ +#define DWT_MASK_MASK_Msk (0x1FUL /*<< DWT_MASK_MASK_Pos*/) /*!< DWT MASK: MASK Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVADDR1_Pos 16U /*!< DWT FUNCTION: DATAVADDR1 Position */ +#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ + +#define DWT_FUNCTION_DATAVADDR0_Pos 12U /*!< DWT FUNCTION: DATAVADDR0 Position */ +#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_LNK1ENA_Pos 9U /*!< DWT FUNCTION: LNK1ENA Position */ +#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ + +#define DWT_FUNCTION_DATAVMATCH_Pos 8U /*!< DWT FUNCTION: DATAVMATCH Position */ +#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ + +#define DWT_FUNCTION_CYCMATCH_Pos 7U /*!< DWT FUNCTION: CYCMATCH Position */ +#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ + +#define DWT_FUNCTION_EMITRANGE_Pos 5U /*!< DWT FUNCTION: EMITRANGE Position */ +#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ + +#define DWT_FUNCTION_FUNCTION_Pos 0U /*!< DWT FUNCTION: FUNCTION Position */ +#define DWT_FUNCTION_FUNCTION_Msk (0xFUL /*<< DWT_FUNCTION_FUNCTION_Pos*/) /*!< DWT FUNCTION: FUNCTION Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IOM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ + __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY_Pos 0U /*!< TPI ITATBCTR2: ATREADY Position */ +#define TPI_ITATBCTR2_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY_Pos*/) /*!< TPI ITATBCTR2: ATREADY Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY_Pos 0U /*!< TPI ITATBCTR0: ATREADY Position */ +#define TPI_ITATBCTR0_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY_Pos*/) /*!< TPI ITATBCTR0: ATREADY Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x1UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_MajorType_Pos 4U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +#define TPI_DEVTYPE_SubType_Pos 0U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ +} MPU_Type; + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register Definitions */ +#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +#if (__FPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_FPU Floating Point Unit (FPU) + \brief Type definitions for the Floating Point Unit (FPU) + @{ + */ + +/** + \brief Structure type to access the Floating Point Unit (FPU). + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ + __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ + __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ + __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ + __IM uint32_t MVFR2; /*!< Offset: 0x018 (R/ ) Media and FP Feature Register 2 */ +} FPU_Type; + +/* Floating-Point Context Control Register Definitions */ +#define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */ +#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */ + +#define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */ +#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */ + +#define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */ +#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */ + +#define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */ +#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */ + +#define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */ +#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */ + +#define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */ +#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */ + +#define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */ +#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */ + +#define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */ +#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */ + +#define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */ +#define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */ + +/* Floating-Point Context Address Register Definitions */ +#define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */ +#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */ + +/* Floating-Point Default Status Control Register Definitions */ +#define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */ +#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */ + +#define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */ +#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */ + +#define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */ +#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */ + +#define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */ +#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */ + +/* Media and FP Feature Register 0 Definitions */ +#define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */ +#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */ + +#define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */ +#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */ + +#define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */ +#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */ + +#define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */ +#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */ + +#define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */ +#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */ + +#define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */ +#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */ + +#define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */ +#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */ + +#define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */ +#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */ + +/* Media and FP Feature Register 1 Definitions */ +#define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */ +#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */ + +#define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */ +#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */ + +#define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */ +#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */ + +#define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */ +#define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */ + +/* Media and FP Feature Register 2 Definitions */ + +/*@} end of group CMSIS_FPU */ +#endif + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register Definitions */ +#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Cortex-M4 Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +#if (__FPU_PRESENT == 1U) + #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ + #define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +/** + \brief Set Priority Grouping + \details Sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */ + SCB->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping + \details Reads the priority grouping field from the NVIC Interrupt Controller. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t NVIC_GetPriorityGrouping(void) +{ + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable External Interrupt + \details Enables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Disable External Interrupt + \details Disables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Get Pending Interrupt + \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t)(((NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of an external interrupt. + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of an external interrupt. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in NVIC and returns the active bit. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + */ +__STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) +{ + return((uint32_t)(((NVIC->IABR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of an interrupt. + \note The priority cannot be set for every core interrupt. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) < 0) + { + SCB->SHPR[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + NVIC->IP[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of an interrupt. + The interrupt number can be positive to specify an external (device specific) interrupt, + or negative to specify an internal (core) interrupt. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) < 0) + { + return(((uint32_t)SCB->SHPR[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)NVIC->IP[((uint32_t)(int32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__STATIC_INLINE void NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + uint32_t mvfr0; + + mvfr0 = SCB->MVFR0; + if ((mvfr0 & 0x00000FF0UL) == 0x220UL) + { + return 2UL; /* Double + Single precision FPU */ + } + else if ((mvfr0 & 0x00000FF0UL) == 0x020UL) + { + return 1UL; /* Single precision FPU */ + } + else + { + return 0UL; /* No FPU */ + } +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + + + +/* ########################## Cache functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_CacheFunctions Cache Functions + \brief Functions that configure Instruction and Data cache. + @{ + */ + +/* Cache Size ID Register Macros */ +#define CCSIDR_WAYS(x) (((x) & SCB_CCSIDR_ASSOCIATIVITY_Msk) >> SCB_CCSIDR_ASSOCIATIVITY_Pos) +#define CCSIDR_SETS(x) (((x) & SCB_CCSIDR_NUMSETS_Msk ) >> SCB_CCSIDR_NUMSETS_Pos ) + + +/** + \brief Enable I-Cache + \details Turns on I-Cache + */ +__STATIC_INLINE void SCB_EnableICache (void) +{ + #if (__ICACHE_PRESENT == 1U) + __DSB(); + __ISB(); + SCB->ICIALLU = 0UL; /* invalidate I-Cache */ + SCB->CCR |= (uint32_t)SCB_CCR_IC_Msk; /* enable I-Cache */ + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Disable I-Cache + \details Turns off I-Cache + */ +__STATIC_INLINE void SCB_DisableICache (void) +{ + #if (__ICACHE_PRESENT == 1U) + __DSB(); + __ISB(); + SCB->CCR &= ~(uint32_t)SCB_CCR_IC_Msk; /* disable I-Cache */ + SCB->ICIALLU = 0UL; /* invalidate I-Cache */ + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Invalidate I-Cache + \details Invalidates I-Cache + */ +__STATIC_INLINE void SCB_InvalidateICache (void) +{ + #if (__ICACHE_PRESENT == 1U) + __DSB(); + __ISB(); + SCB->ICIALLU = 0UL; + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Enable D-Cache + \details Turns on D-Cache + */ +__STATIC_INLINE void SCB_EnableDCache (void) +{ + #if (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + SCB->CSSELR = (0U << 1U) | 0U; /* Level 1 data cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + /* invalidate D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCISW = (((sets << SCB_DCISW_SET_Pos) & SCB_DCISW_SET_Msk) | + ((ways << SCB_DCISW_WAY_Pos) & SCB_DCISW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways--); + } while(sets--); + __DSB(); + + SCB->CCR |= (uint32_t)SCB_CCR_DC_Msk; /* enable D-Cache */ + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Disable D-Cache + \details Turns off D-Cache + */ +__STATIC_INLINE void SCB_DisableDCache (void) +{ + #if (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + SCB->CSSELR = (0U << 1U) | 0U; /* Level 1 data cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + SCB->CCR &= ~(uint32_t)SCB_CCR_DC_Msk; /* disable D-Cache */ + + /* clean & invalidate D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCCISW = (((sets << SCB_DCCISW_SET_Pos) & SCB_DCCISW_SET_Msk) | + ((ways << SCB_DCCISW_WAY_Pos) & SCB_DCCISW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways--); + } while(sets--); + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Invalidate D-Cache + \details Invalidates D-Cache + */ +__STATIC_INLINE void SCB_InvalidateDCache (void) +{ + #if (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + SCB->CSSELR = (0U << 1U) | 0U; /* Level 1 data cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + /* invalidate D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCISW = (((sets << SCB_DCISW_SET_Pos) & SCB_DCISW_SET_Msk) | + ((ways << SCB_DCISW_WAY_Pos) & SCB_DCISW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways--); + } while(sets--); + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Clean D-Cache + \details Cleans D-Cache + */ +__STATIC_INLINE void SCB_CleanDCache (void) +{ + #if (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + SCB->CSSELR = (0U << 1U) | 0U; /* Level 1 data cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + /* clean D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCCSW = (((sets << SCB_DCCSW_SET_Pos) & SCB_DCCSW_SET_Msk) | + ((ways << SCB_DCCSW_WAY_Pos) & SCB_DCCSW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways--); + } while(sets--); + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Clean & Invalidate D-Cache + \details Cleans and Invalidates D-Cache + */ +__STATIC_INLINE void SCB_CleanInvalidateDCache (void) +{ + #if (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + SCB->CSSELR = (0U << 1U) | 0U; /* Level 1 data cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + /* clean & invalidate D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCCISW = (((sets << SCB_DCCISW_SET_Pos) & SCB_DCCISW_SET_Msk) | + ((ways << SCB_DCCISW_WAY_Pos) & SCB_DCCISW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways--); + } while(sets--); + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief D-Cache Invalidate by address + \details Invalidates D-Cache for the given address + \param[in] addr address (aligned to 32-byte boundary) + \param[in] dsize size of memory block (in number of bytes) +*/ +__STATIC_INLINE void SCB_InvalidateDCache_by_Addr (uint32_t *addr, int32_t dsize) +{ + #if (__DCACHE_PRESENT == 1U) + int32_t op_size = dsize; + uint32_t op_addr = (uint32_t)addr; + int32_t linesize = 32U; /* in Cortex-M7 size of cache line is fixed to 8 words (32 bytes) */ + + __DSB(); + + while (op_size > 0) { + SCB->DCIMVAC = op_addr; + op_addr += linesize; + op_size -= linesize; + } + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief D-Cache Clean by address + \details Cleans D-Cache for the given address + \param[in] addr address (aligned to 32-byte boundary) + \param[in] dsize size of memory block (in number of bytes) +*/ +__STATIC_INLINE void SCB_CleanDCache_by_Addr (uint32_t *addr, int32_t dsize) +{ + #if (__DCACHE_PRESENT == 1) + int32_t op_size = dsize; + uint32_t op_addr = (uint32_t) addr; + int32_t linesize = 32U; /* in Cortex-M7 size of cache line is fixed to 8 words (32 bytes) */ + + __DSB(); + + while (op_size > 0) { + SCB->DCCMVAC = op_addr; + op_addr += linesize; + op_size -= linesize; + } + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief D-Cache Clean and Invalidate by address + \details Cleans and invalidates D_Cache for the given address + \param[in] addr address (aligned to 32-byte boundary) + \param[in] dsize size of memory block (in number of bytes) +*/ +__STATIC_INLINE void SCB_CleanInvalidateDCache_by_Addr (uint32_t *addr, int32_t dsize) +{ + #if (__DCACHE_PRESENT == 1U) + int32_t op_size = dsize; + uint32_t op_addr = (uint32_t) addr; + int32_t linesize = 32U; /* in Cortex-M7 size of cache line is fixed to 8 words (32 bytes) */ + + __DSB(); + + while (op_size > 0) { + SCB->DCCIMVAC = op_addr; + op_addr += linesize; + op_size -= linesize; + } + + __DSB(); + __ISB(); + #endif +} + + +/*@} end of CMSIS_Core_CacheFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY 0x5AA55AA5U /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** + \brief ITM Send Character + \details Transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + \param [in] ch Character to transmit. + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; + } + return (ch); +} + + +/** + \brief ITM Receive Character + \details Inputs a character via the external variable \ref ITM_RxBuffer. + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) +{ + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** + \brief ITM Check Character + \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) +{ + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM7_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cmFunc.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cmFunc.h new file mode 100644 index 0000000..652a48a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cmFunc.h @@ -0,0 +1,87 @@ +/**************************************************************************//** + * @file core_cmFunc.h + * @brief CMSIS Cortex-M Core Function Access Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM 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: + - 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 COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (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 ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CMFUNC_H +#define __CORE_CMFUNC_H + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ +*/ + +/*------------------ RealView Compiler -----------------*/ +#if defined ( __CC_ARM ) + #include "cmsis_armcc.h" + +/*------------------ ARM Compiler V6 -------------------*/ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #include "cmsis_armcc_V6.h" + +/*------------------ GNU Compiler ----------------------*/ +#elif defined ( __GNUC__ ) + #include "cmsis_gcc.h" + +/*------------------ ICC Compiler ----------------------*/ +#elif defined ( __ICCARM__ ) + #include + +/*------------------ TI CCS Compiler -------------------*/ +#elif defined ( __TMS470__ ) + #include + +/*------------------ TASKING Compiler ------------------*/ +#elif defined ( __TASKING__ ) + /* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all intrinsics, + * Including the CMSIS ones. + */ + +/*------------------ COSMIC Compiler -------------------*/ +#elif defined ( __CSMC__ ) + #include + +#endif + +/*@} end of CMSIS_Core_RegAccFunctions */ + +#endif /* __CORE_CMFUNC_H */ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cmInstr.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cmInstr.h new file mode 100644 index 0000000..f474b0e --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cmInstr.h @@ -0,0 +1,87 @@ +/**************************************************************************//** + * @file core_cmInstr.h + * @brief CMSIS Cortex-M Core Instruction Access Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM 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: + - 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 COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (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 ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CMINSTR_H +#define __CORE_CMINSTR_H + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/*------------------ RealView Compiler -----------------*/ +#if defined ( __CC_ARM ) + #include "cmsis_armcc.h" + +/*------------------ ARM Compiler V6 -------------------*/ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #include "cmsis_armcc_V6.h" + +/*------------------ GNU Compiler ----------------------*/ +#elif defined ( __GNUC__ ) + #include "cmsis_gcc.h" + +/*------------------ ICC Compiler ----------------------*/ +#elif defined ( __ICCARM__ ) + #include + +/*------------------ TI CCS Compiler -------------------*/ +#elif defined ( __TMS470__ ) + #include + +/*------------------ TASKING Compiler ------------------*/ +#elif defined ( __TASKING__ ) + /* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all intrinsics, + * Including the CMSIS ones. + */ + +/*------------------ COSMIC Compiler -------------------*/ +#elif defined ( __CSMC__ ) + #include + +#endif + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + +#endif /* __CORE_CMINSTR_H */ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cmSimd.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cmSimd.h new file mode 100644 index 0000000..66bf5c2 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_cmSimd.h @@ -0,0 +1,96 @@ +/**************************************************************************//** + * @file core_cmSimd.h + * @brief CMSIS Cortex-M SIMD Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM 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: + - 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 COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (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 ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CMSIMD_H +#define __CORE_CMSIMD_H + +#ifdef __cplusplus + extern "C" { +#endif + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +/*------------------ RealView Compiler -----------------*/ +#if defined ( __CC_ARM ) + #include "cmsis_armcc.h" + +/*------------------ ARM Compiler V6 -------------------*/ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #include "cmsis_armcc_V6.h" + +/*------------------ GNU Compiler ----------------------*/ +#elif defined ( __GNUC__ ) + #include "cmsis_gcc.h" + +/*------------------ ICC Compiler ----------------------*/ +#elif defined ( __ICCARM__ ) + #include + +/*------------------ TI CCS Compiler -------------------*/ +#elif defined ( __TMS470__ ) + #include + +/*------------------ TASKING Compiler ------------------*/ +#elif defined ( __TASKING__ ) + /* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all intrinsics, + * Including the CMSIS ones. + */ + +/*------------------ COSMIC Compiler -------------------*/ +#elif defined ( __CSMC__ ) + #include + +#endif + +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CMSIMD_H */ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_sc000.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_sc000.h new file mode 100644 index 0000000..514dbd8 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_sc000.h @@ -0,0 +1,926 @@ +/**************************************************************************//** + * @file core_sc000.h + * @brief CMSIS SC000 Core Peripheral Access Layer Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM 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: + - 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 COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (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 ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_SC000_H_GENERIC +#define __CORE_SC000_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
    + Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
    + Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
    + Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup SC000 + @{ + */ + +/* CMSIS SC000 definitions */ +#define __SC000_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */ +#define __SC000_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */ +#define __SC000_CMSIS_VERSION ((__SC000_CMSIS_VERSION_MAIN << 16U) | \ + __SC000_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + +#define __CORTEX_SC (000U) /*!< Cortex secure core */ + + +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ + #define __STATIC_INLINE static inline + +#elif defined ( __TMS470__ ) + #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __CSMC__ ) + #define __packed + #define __ASM _asm /*!< asm keyword for COSMIC Compiler */ + #define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */ + #define __STATIC_INLINE static inline + +#else + #error Unknown compiler +#endif + +/** __FPU_USED indicates whether an FPU is used or not. + This core does not support an FPU at all +*/ +#define __FPU_USED 0U + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_PCS_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TMS470__ ) + #if defined __TI_VFP_SUPPORT__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#endif + +#include "core_cmInstr.h" /* Core Instruction Access */ +#include "core_cmFunc.h" /* Core Function Access */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_SC000_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_SC000_H_DEPENDANT +#define __CORE_SC000_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __SC000_REV + #define __SC000_REV 0x0000U + #warning "__SC000_REV not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 2U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group SC000 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core MPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t _reserved0:1; /*!< bit: 0 Reserved */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[31U]; + __IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[31U]; + __IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[31U]; + __IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[31U]; + uint32_t RESERVED4[64U]; + __IOM uint32_t IP[8U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */ +} NVIC_Type; + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + uint32_t RESERVED0[1U]; + __IOM uint32_t SHP[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + uint32_t RESERVED1[154U]; + __IOM uint32_t SFCR; /*!< Offset: 0x290 (R/W) Security Features Control Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +} SCnSCB_Type; + +/* Auxiliary Control Register Definitions */ +#define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */ +#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + +#if (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ +} MPU_Type; + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_ADDR_Pos 8U /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0xFFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register Definitions */ +#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief SC000 Core Debug Registers (DCB registers, SHCSR, and DFSR) are only accessible over DAP and not via processor. + Therefore they are not covered by the SC000 header file. + @{ + */ +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of SC000 Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ + +#if (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +/* Interrupt Priorities are WORD accessible only under ARMv6M */ +/* The following MACROS handle generation of the register offset and byte masks */ +#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL) +#define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) ) +#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) ) + + +/** + \brief Enable External Interrupt + \details Enables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Disable External Interrupt + \details Disables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Get Pending Interrupt + \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of an external interrupt. + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of an external interrupt. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of an interrupt. + \note The priority cannot be set for every core interrupt. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) < 0) + { + SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } + else + { + NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of an interrupt. + The interrupt number can be positive to specify an external (device specific) interrupt, + or negative to specify an internal (core) interrupt. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) < 0) + { + return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__STATIC_INLINE void NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + SCB_AIRCR_SYSRESETREQ_Msk); + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_SC000_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_sc300.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_sc300.h new file mode 100644 index 0000000..8bd18aa --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/CMSIS/Include/core_sc300.h @@ -0,0 +1,1745 @@ +/**************************************************************************//** + * @file core_sc300.h + * @brief CMSIS SC300 Core Peripheral Access Layer Header File + * @version V4.30 + * @date 20. October 2015 + ******************************************************************************/ +/* Copyright (c) 2009 - 2015 ARM 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: + - 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 COPYRIGHT HOLDERS AND CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (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 ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_SC300_H_GENERIC +#define __CORE_SC300_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
    + Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
    + Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
    + Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup SC3000 + @{ + */ + +/* CMSIS SC300 definitions */ +#define __SC300_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */ +#define __SC300_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */ +#define __SC300_CMSIS_VERSION ((__SC300_CMSIS_VERSION_MAIN << 16U) | \ + __SC300_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ + +#define __CORTEX_SC (300U) /*!< Cortex secure core */ + + +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + #define __STATIC_INLINE static __inline + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ + #define __STATIC_INLINE static inline + +#elif defined ( __TMS470__ ) + #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + #define __STATIC_INLINE static inline + +#elif defined ( __CSMC__ ) + #define __packed + #define __ASM _asm /*!< asm keyword for COSMIC Compiler */ + #define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */ + #define __STATIC_INLINE static inline + +#else + #error Unknown compiler +#endif + +/** __FPU_USED indicates whether an FPU is used or not. + This core does not support an FPU at all +*/ +#define __FPU_USED 0U + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_PCS_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TMS470__ ) + #if defined __TI_VFP_SUPPORT__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#endif + +#include "core_cmInstr.h" /* Core Instruction Access */ +#include "core_cmFunc.h" /* Core Function Access */ + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_SC300_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_SC300_H_DEPENDANT +#define __CORE_SC300_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __SC300_REV + #define __SC300_REV 0x0000U + #warning "__SC300_REV not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 4U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group SC300 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + +#define APSR_Q_Pos 27U /*!< APSR: Q Position */ +#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ +#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ + +#define xPSR_IT_Pos 25U /*!< xPSR: IT Position */ +#define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24U]; + __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[24U]; + __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24U]; + __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24U]; + __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56U]; + __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHP[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[5U]; + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ + uint32_t RESERVED1[129U]; + __IOM uint32_t SFCR; /*!< Offset: 0x290 (R/W) Security Features Control Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLBASE_Pos 29U /*!< SCB VTOR: TBLBASE Position */ +#define SCB_VTOR_TBLBASE_Msk (1UL << SCB_VTOR_TBLBASE_Pos) /*!< SCB VTOR: TBLBASE Mask */ + +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x3FFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +#define SCB_AIRCR_VECTRESET_Pos 0U /*!< SCB AIRCR: VECTRESET Position */ +#define SCB_AIRCR_VECTRESET_Msk (1UL /*<< SCB_AIRCR_VECTRESET_Pos*/) /*!< SCB AIRCR: VECTRESET Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +#define SCB_CCR_NONBASETHRDENA_Pos 0U /*!< SCB CCR: NONBASETHRDENA Position */ +#define SCB_CCR_NONBASETHRDENA_Msk (1UL /*<< SCB_CCR_NONBASETHRDENA_Pos*/) /*!< SCB CCR: NONBASETHRDENA Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Register Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* SCB Hard Fault Status Register Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ + uint32_t RESERVED1[1U]; +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** + \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[29U]; + __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ + __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ + __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TraceBusID_Pos 16U /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPrescale_Pos 8U /*!< ITM TCR: TSPrescale Position */ +#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ + +#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Integration Write Register Definitions */ +#define ITM_IWR_ATVALIDM_Pos 0U /*!< ITM IWR: ATVALIDM Position */ +#define ITM_IWR_ATVALIDM_Msk (1UL /*<< ITM_IWR_ATVALIDM_Pos*/) /*!< ITM IWR: ATVALIDM Mask */ + +/* ITM Integration Read Register Definitions */ +#define ITM_IRR_ATREADYM_Pos 0U /*!< ITM IRR: ATREADYM Position */ +#define ITM_IRR_ATREADYM_Msk (1UL /*<< ITM_IRR_ATREADYM_Pos*/) /*!< ITM IRR: ATREADYM Mask */ + +/* ITM Integration Mode Control Register Definitions */ +#define ITM_IMCR_INTEGRATION_Pos 0U /*!< ITM IMCR: INTEGRATION Position */ +#define ITM_IMCR_INTEGRATION_Msk (1UL /*<< ITM_IMCR_INTEGRATION_Pos*/) /*!< ITM IMCR: INTEGRATION Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Mask Register Definitions */ +#define DWT_MASK_MASK_Pos 0U /*!< DWT MASK: MASK Position */ +#define DWT_MASK_MASK_Msk (0x1FUL /*<< DWT_MASK_MASK_Pos*/) /*!< DWT MASK: MASK Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVADDR1_Pos 16U /*!< DWT FUNCTION: DATAVADDR1 Position */ +#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ + +#define DWT_FUNCTION_DATAVADDR0_Pos 12U /*!< DWT FUNCTION: DATAVADDR0 Position */ +#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_LNK1ENA_Pos 9U /*!< DWT FUNCTION: LNK1ENA Position */ +#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ + +#define DWT_FUNCTION_DATAVMATCH_Pos 8U /*!< DWT FUNCTION: DATAVMATCH Position */ +#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ + +#define DWT_FUNCTION_CYCMATCH_Pos 7U /*!< DWT FUNCTION: CYCMATCH Position */ +#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ + +#define DWT_FUNCTION_EMITRANGE_Pos 5U /*!< DWT FUNCTION: EMITRANGE Position */ +#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ + +#define DWT_FUNCTION_FUNCTION_Pos 0U /*!< DWT FUNCTION: FUNCTION Position */ +#define DWT_FUNCTION_FUNCTION_Msk (0xFUL /*<< DWT_FUNCTION_FUNCTION_Pos*/) /*!< DWT FUNCTION: FUNCTION Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IOM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ + __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY_Pos 0U /*!< TPI ITATBCTR2: ATREADY Position */ +#define TPI_ITATBCTR2_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY_Pos*/) /*!< TPI ITATBCTR2: ATREADY Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY_Pos 0U /*!< TPI ITATBCTR0: ATREADY Position */ +#define TPI_ITATBCTR0_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY_Pos*/) /*!< TPI ITATBCTR0: ATREADY Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x1UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_MajorType_Pos 4U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +#define TPI_DEVTYPE_SubType_Pos 0U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ +} MPU_Type; + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register Definitions */ +#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register Definitions */ +#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Cortex-M3 Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +/** + \brief Set Priority Grouping + \details Sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */ + SCB->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping + \details Reads the priority grouping field from the NVIC Interrupt Controller. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t NVIC_GetPriorityGrouping(void) +{ + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable External Interrupt + \details Enables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) +{ + NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Disable External Interrupt + \details Disables a device-specific interrupt in the NVIC interrupt controller. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) +{ + NVIC->ICER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Get Pending Interrupt + \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + */ +__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + return((uint32_t)(((NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of an external interrupt. + \param [in] IRQn Interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of an external interrupt. + \param [in] IRQn External interrupt number. Value cannot be negative. + */ +__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + NVIC->ICPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL)); +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in NVIC and returns the active bit. + \param [in] IRQn Interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + */ +__STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) +{ + return((uint32_t)(((NVIC->IABR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of an interrupt. + \note The priority cannot be set for every core interrupt. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + */ +__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) < 0) + { + SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + NVIC->IP[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of an interrupt. + The interrupt number can be positive to specify an external (device specific) interrupt, + or negative to specify an internal (core) interrupt. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) < 0) + { + return(((uint32_t)SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)NVIC->IP[((uint32_t)(int32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__STATIC_INLINE void NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY 0x5AA55AA5U /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** + \brief ITM Send Character + \details Transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + \param [in] ch Character to transmit. + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; + } + return (ch); +} + + +/** + \brief ITM Receive Character + \details Inputs a character via the external variable \ref ITM_RxBuffer. + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) +{ + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** + \brief ITM Check Character + \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) +{ + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_SC300_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h new file mode 100644 index 0000000..0ae9d0b --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h @@ -0,0 +1,3309 @@ +/** + ****************************************************************************** + * @file stm32_hal_legacy.h + * @author MCD Application Team + * @brief This file contains aliases definition for the STM32Cube HAL constants + * macros and functions maintained for legacy purpose. + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32_HAL_LEGACY +#define __STM32_HAL_LEGACY + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/** @defgroup HAL_AES_Aliased_Defines HAL CRYP Aliased Defines maintained for legacy purpose + * @{ + */ +#define AES_FLAG_RDERR CRYP_FLAG_RDERR +#define AES_FLAG_WRERR CRYP_FLAG_WRERR +#define AES_CLEARFLAG_CCF CRYP_CLEARFLAG_CCF +#define AES_CLEARFLAG_RDERR CRYP_CLEARFLAG_RDERR +#define AES_CLEARFLAG_WRERR CRYP_CLEARFLAG_WRERR + +/** + * @} + */ + +/** @defgroup HAL_ADC_Aliased_Defines HAL ADC Aliased Defines maintained for legacy purpose + * @{ + */ +#define ADC_RESOLUTION12b ADC_RESOLUTION_12B +#define ADC_RESOLUTION10b ADC_RESOLUTION_10B +#define ADC_RESOLUTION8b ADC_RESOLUTION_8B +#define ADC_RESOLUTION6b ADC_RESOLUTION_6B +#define OVR_DATA_OVERWRITTEN ADC_OVR_DATA_OVERWRITTEN +#define OVR_DATA_PRESERVED ADC_OVR_DATA_PRESERVED +#define EOC_SINGLE_CONV ADC_EOC_SINGLE_CONV +#define EOC_SEQ_CONV ADC_EOC_SEQ_CONV +#define EOC_SINGLE_SEQ_CONV ADC_EOC_SINGLE_SEQ_CONV +#define REGULAR_GROUP ADC_REGULAR_GROUP +#define INJECTED_GROUP ADC_INJECTED_GROUP +#define REGULAR_INJECTED_GROUP ADC_REGULAR_INJECTED_GROUP +#define AWD_EVENT ADC_AWD_EVENT +#define AWD1_EVENT ADC_AWD1_EVENT +#define AWD2_EVENT ADC_AWD2_EVENT +#define AWD3_EVENT ADC_AWD3_EVENT +#define OVR_EVENT ADC_OVR_EVENT +#define JQOVF_EVENT ADC_JQOVF_EVENT +#define ALL_CHANNELS ADC_ALL_CHANNELS +#define REGULAR_CHANNELS ADC_REGULAR_CHANNELS +#define INJECTED_CHANNELS ADC_INJECTED_CHANNELS +#define SYSCFG_FLAG_SENSOR_ADC ADC_FLAG_SENSOR +#define SYSCFG_FLAG_VREF_ADC ADC_FLAG_VREFINT +#define ADC_CLOCKPRESCALER_PCLK_DIV1 ADC_CLOCK_SYNC_PCLK_DIV1 +#define ADC_CLOCKPRESCALER_PCLK_DIV2 ADC_CLOCK_SYNC_PCLK_DIV2 +#define ADC_CLOCKPRESCALER_PCLK_DIV4 ADC_CLOCK_SYNC_PCLK_DIV4 +#define ADC_CLOCKPRESCALER_PCLK_DIV6 ADC_CLOCK_SYNC_PCLK_DIV6 +#define ADC_CLOCKPRESCALER_PCLK_DIV8 ADC_CLOCK_SYNC_PCLK_DIV8 +#define ADC_EXTERNALTRIG0_T6_TRGO ADC_EXTERNALTRIGCONV_T6_TRGO +#define ADC_EXTERNALTRIG1_T21_CC2 ADC_EXTERNALTRIGCONV_T21_CC2 +#define ADC_EXTERNALTRIG2_T2_TRGO ADC_EXTERNALTRIGCONV_T2_TRGO +#define ADC_EXTERNALTRIG3_T2_CC4 ADC_EXTERNALTRIGCONV_T2_CC4 +#define ADC_EXTERNALTRIG4_T22_TRGO ADC_EXTERNALTRIGCONV_T22_TRGO +#define ADC_EXTERNALTRIG7_EXT_IT11 ADC_EXTERNALTRIGCONV_EXT_IT11 +#define ADC_CLOCK_ASYNC ADC_CLOCK_ASYNC_DIV1 +#define ADC_EXTERNALTRIG_EDGE_NONE ADC_EXTERNALTRIGCONVEDGE_NONE +#define ADC_EXTERNALTRIG_EDGE_RISING ADC_EXTERNALTRIGCONVEDGE_RISING +#define ADC_EXTERNALTRIG_EDGE_FALLING ADC_EXTERNALTRIGCONVEDGE_FALLING +#define ADC_EXTERNALTRIG_EDGE_RISINGFALLING ADC_EXTERNALTRIGCONVEDGE_RISINGFALLING +#define ADC_SAMPLETIME_2CYCLE_5 ADC_SAMPLETIME_2CYCLES_5 + +#define HAL_ADC_STATE_BUSY_REG HAL_ADC_STATE_REG_BUSY +#define HAL_ADC_STATE_BUSY_INJ HAL_ADC_STATE_INJ_BUSY +#define HAL_ADC_STATE_EOC_REG HAL_ADC_STATE_REG_EOC +#define HAL_ADC_STATE_EOC_INJ HAL_ADC_STATE_INJ_EOC +#define HAL_ADC_STATE_ERROR HAL_ADC_STATE_ERROR_INTERNAL +#define HAL_ADC_STATE_BUSY HAL_ADC_STATE_BUSY_INTERNAL +#define HAL_ADC_STATE_AWD HAL_ADC_STATE_AWD1 +/** + * @} + */ + +/** @defgroup HAL_CEC_Aliased_Defines HAL CEC Aliased Defines maintained for legacy purpose + * @{ + */ + +#define __HAL_CEC_GET_IT __HAL_CEC_GET_FLAG + +/** + * @} + */ + +/** @defgroup HAL_COMP_Aliased_Defines HAL COMP Aliased Defines maintained for legacy purpose + * @{ + */ +#define COMP_WINDOWMODE_DISABLED COMP_WINDOWMODE_DISABLE +#define COMP_WINDOWMODE_ENABLED COMP_WINDOWMODE_ENABLE +#define COMP_EXTI_LINE_COMP1_EVENT COMP_EXTI_LINE_COMP1 +#define COMP_EXTI_LINE_COMP2_EVENT COMP_EXTI_LINE_COMP2 +#define COMP_EXTI_LINE_COMP3_EVENT COMP_EXTI_LINE_COMP3 +#define COMP_EXTI_LINE_COMP4_EVENT COMP_EXTI_LINE_COMP4 +#define COMP_EXTI_LINE_COMP5_EVENT COMP_EXTI_LINE_COMP5 +#define COMP_EXTI_LINE_COMP6_EVENT COMP_EXTI_LINE_COMP6 +#define COMP_EXTI_LINE_COMP7_EVENT COMP_EXTI_LINE_COMP7 +#if defined(STM32L0) +#define COMP_LPTIMCONNECTION_ENABLED ((uint32_t)0x00000003U) /*!< COMPX output generic naming: connected to LPTIM input 1 for COMP1, LPTIM input 2 for COMP2 */ +#endif +#define COMP_OUTPUT_COMP6TIM2OCREFCLR COMP_OUTPUT_COMP6_TIM2OCREFCLR +#if defined(STM32F373xC) || defined(STM32F378xx) +#define COMP_OUTPUT_TIM3IC1 COMP_OUTPUT_COMP1_TIM3IC1 +#define COMP_OUTPUT_TIM3OCREFCLR COMP_OUTPUT_COMP1_TIM3OCREFCLR +#endif /* STM32F373xC || STM32F378xx */ + +#if defined(STM32L0) || defined(STM32L4) +#define COMP_WINDOWMODE_ENABLE COMP_WINDOWMODE_COMP1_INPUT_PLUS_COMMON + +#define COMP_NONINVERTINGINPUT_IO1 COMP_INPUT_PLUS_IO1 +#define COMP_NONINVERTINGINPUT_IO2 COMP_INPUT_PLUS_IO2 +#define COMP_NONINVERTINGINPUT_IO3 COMP_INPUT_PLUS_IO3 +#define COMP_NONINVERTINGINPUT_IO4 COMP_INPUT_PLUS_IO4 +#define COMP_NONINVERTINGINPUT_IO5 COMP_INPUT_PLUS_IO5 +#define COMP_NONINVERTINGINPUT_IO6 COMP_INPUT_PLUS_IO6 + +#define COMP_INVERTINGINPUT_1_4VREFINT COMP_INPUT_MINUS_1_4VREFINT +#define COMP_INVERTINGINPUT_1_2VREFINT COMP_INPUT_MINUS_1_2VREFINT +#define COMP_INVERTINGINPUT_3_4VREFINT COMP_INPUT_MINUS_3_4VREFINT +#define COMP_INVERTINGINPUT_VREFINT COMP_INPUT_MINUS_VREFINT +#define COMP_INVERTINGINPUT_DAC1_CH1 COMP_INPUT_MINUS_DAC1_CH1 +#define COMP_INVERTINGINPUT_DAC1_CH2 COMP_INPUT_MINUS_DAC1_CH2 +#define COMP_INVERTINGINPUT_DAC1 COMP_INPUT_MINUS_DAC1_CH1 +#define COMP_INVERTINGINPUT_DAC2 COMP_INPUT_MINUS_DAC1_CH2 +#define COMP_INVERTINGINPUT_IO1 COMP_INPUT_MINUS_IO1 +#if defined(STM32L0) +/* Issue fixed on STM32L0 COMP driver: only 2 dedicated IO (IO1 and IO2), */ +/* IO2 was wrongly assigned to IO shared with DAC and IO3 was corresponding */ +/* to the second dedicated IO (only for COMP2). */ +#define COMP_INVERTINGINPUT_IO2 COMP_INPUT_MINUS_DAC1_CH2 +#define COMP_INVERTINGINPUT_IO3 COMP_INPUT_MINUS_IO2 +#else +#define COMP_INVERTINGINPUT_IO2 COMP_INPUT_MINUS_IO2 +#define COMP_INVERTINGINPUT_IO3 COMP_INPUT_MINUS_IO3 +#endif +#define COMP_INVERTINGINPUT_IO4 COMP_INPUT_MINUS_IO4 +#define COMP_INVERTINGINPUT_IO5 COMP_INPUT_MINUS_IO5 + +#define COMP_OUTPUTLEVEL_LOW COMP_OUTPUT_LEVEL_LOW +#define COMP_OUTPUTLEVEL_HIGH COMP_OUTPUT_LEVEL_HIGH + +/* Note: Literal "COMP_FLAG_LOCK" kept for legacy purpose. */ +/* To check COMP lock state, use macro "__HAL_COMP_IS_LOCKED()". */ +#if defined(COMP_CSR_LOCK) +#define COMP_FLAG_LOCK COMP_CSR_LOCK +#elif defined(COMP_CSR_COMP1LOCK) +#define COMP_FLAG_LOCK COMP_CSR_COMP1LOCK +#elif defined(COMP_CSR_COMPxLOCK) +#define COMP_FLAG_LOCK COMP_CSR_COMPxLOCK +#endif + +#if defined(STM32L4) +#define COMP_BLANKINGSRCE_TIM1OC5 COMP_BLANKINGSRC_TIM1_OC5_COMP1 +#define COMP_BLANKINGSRCE_TIM2OC3 COMP_BLANKINGSRC_TIM2_OC3_COMP1 +#define COMP_BLANKINGSRCE_TIM3OC3 COMP_BLANKINGSRC_TIM3_OC3_COMP1 +#define COMP_BLANKINGSRCE_TIM3OC4 COMP_BLANKINGSRC_TIM3_OC4_COMP2 +#define COMP_BLANKINGSRCE_TIM8OC5 COMP_BLANKINGSRC_TIM8_OC5_COMP2 +#define COMP_BLANKINGSRCE_TIM15OC1 COMP_BLANKINGSRC_TIM15_OC1_COMP2 +#define COMP_BLANKINGSRCE_NONE COMP_BLANKINGSRC_NONE +#endif + +#if defined(STM32L0) +#define COMP_MODE_HIGHSPEED COMP_POWERMODE_MEDIUMSPEED +#define COMP_MODE_LOWSPEED COMP_POWERMODE_ULTRALOWPOWER +#else +#define COMP_MODE_HIGHSPEED COMP_POWERMODE_HIGHSPEED +#define COMP_MODE_MEDIUMSPEED COMP_POWERMODE_MEDIUMSPEED +#define COMP_MODE_LOWPOWER COMP_POWERMODE_LOWPOWER +#define COMP_MODE_ULTRALOWPOWER COMP_POWERMODE_ULTRALOWPOWER +#endif + +#endif +/** + * @} + */ + +/** @defgroup HAL_CORTEX_Aliased_Defines HAL CORTEX Aliased Defines maintained for legacy purpose + * @{ + */ +#define __HAL_CORTEX_SYSTICKCLK_CONFIG HAL_SYSTICK_CLKSourceConfig +/** + * @} + */ + +/** @defgroup HAL_CRC_Aliased_Defines HAL CRC Aliased Defines maintained for legacy purpose + * @{ + */ + +#define CRC_OUTPUTDATA_INVERSION_DISABLED CRC_OUTPUTDATA_INVERSION_DISABLE +#define CRC_OUTPUTDATA_INVERSION_ENABLED CRC_OUTPUTDATA_INVERSION_ENABLE + +/** + * @} + */ + +/** @defgroup HAL_DAC_Aliased_Defines HAL DAC Aliased Defines maintained for legacy purpose + * @{ + */ + +#define DAC1_CHANNEL_1 DAC_CHANNEL_1 +#define DAC1_CHANNEL_2 DAC_CHANNEL_2 +#define DAC2_CHANNEL_1 DAC_CHANNEL_1 +#define DAC_WAVE_NONE 0x00000000U +#define DAC_WAVE_NOISE DAC_CR_WAVE1_0 +#define DAC_WAVE_TRIANGLE DAC_CR_WAVE1_1 +#define DAC_WAVEGENERATION_NONE DAC_WAVE_NONE +#define DAC_WAVEGENERATION_NOISE DAC_WAVE_NOISE +#define DAC_WAVEGENERATION_TRIANGLE DAC_WAVE_TRIANGLE + +/** + * @} + */ + +/** @defgroup HAL_DMA_Aliased_Defines HAL DMA Aliased Defines maintained for legacy purpose + * @{ + */ +#define HAL_REMAPDMA_ADC_DMA_CH2 DMA_REMAP_ADC_DMA_CH2 +#define HAL_REMAPDMA_USART1_TX_DMA_CH4 DMA_REMAP_USART1_TX_DMA_CH4 +#define HAL_REMAPDMA_USART1_RX_DMA_CH5 DMA_REMAP_USART1_RX_DMA_CH5 +#define HAL_REMAPDMA_TIM16_DMA_CH4 DMA_REMAP_TIM16_DMA_CH4 +#define HAL_REMAPDMA_TIM17_DMA_CH2 DMA_REMAP_TIM17_DMA_CH2 +#define HAL_REMAPDMA_USART3_DMA_CH32 DMA_REMAP_USART3_DMA_CH32 +#define HAL_REMAPDMA_TIM16_DMA_CH6 DMA_REMAP_TIM16_DMA_CH6 +#define HAL_REMAPDMA_TIM17_DMA_CH7 DMA_REMAP_TIM17_DMA_CH7 +#define HAL_REMAPDMA_SPI2_DMA_CH67 DMA_REMAP_SPI2_DMA_CH67 +#define HAL_REMAPDMA_USART2_DMA_CH67 DMA_REMAP_USART2_DMA_CH67 +#define HAL_REMAPDMA_I2C1_DMA_CH76 DMA_REMAP_I2C1_DMA_CH76 +#define HAL_REMAPDMA_TIM1_DMA_CH6 DMA_REMAP_TIM1_DMA_CH6 +#define HAL_REMAPDMA_TIM2_DMA_CH7 DMA_REMAP_TIM2_DMA_CH7 +#define HAL_REMAPDMA_TIM3_DMA_CH6 DMA_REMAP_TIM3_DMA_CH6 + +#define IS_HAL_REMAPDMA IS_DMA_REMAP +#define __HAL_REMAPDMA_CHANNEL_ENABLE __HAL_DMA_REMAP_CHANNEL_ENABLE +#define __HAL_REMAPDMA_CHANNEL_DISABLE __HAL_DMA_REMAP_CHANNEL_DISABLE + + + +/** + * @} + */ + +/** @defgroup HAL_FLASH_Aliased_Defines HAL FLASH Aliased Defines maintained for legacy purpose + * @{ + */ + +#define TYPEPROGRAM_BYTE FLASH_TYPEPROGRAM_BYTE +#define TYPEPROGRAM_HALFWORD FLASH_TYPEPROGRAM_HALFWORD +#define TYPEPROGRAM_WORD FLASH_TYPEPROGRAM_WORD +#define TYPEPROGRAM_DOUBLEWORD FLASH_TYPEPROGRAM_DOUBLEWORD +#define TYPEERASE_SECTORS FLASH_TYPEERASE_SECTORS +#define TYPEERASE_PAGES FLASH_TYPEERASE_PAGES +#define TYPEERASE_PAGEERASE FLASH_TYPEERASE_PAGES +#define TYPEERASE_MASSERASE FLASH_TYPEERASE_MASSERASE +#define WRPSTATE_DISABLE OB_WRPSTATE_DISABLE +#define WRPSTATE_ENABLE OB_WRPSTATE_ENABLE +#define HAL_FLASH_TIMEOUT_VALUE FLASH_TIMEOUT_VALUE +#define OBEX_PCROP OPTIONBYTE_PCROP +#define OBEX_BOOTCONFIG OPTIONBYTE_BOOTCONFIG +#define PCROPSTATE_DISABLE OB_PCROP_STATE_DISABLE +#define PCROPSTATE_ENABLE OB_PCROP_STATE_ENABLE +#define TYPEERASEDATA_BYTE FLASH_TYPEERASEDATA_BYTE +#define TYPEERASEDATA_HALFWORD FLASH_TYPEERASEDATA_HALFWORD +#define TYPEERASEDATA_WORD FLASH_TYPEERASEDATA_WORD +#define TYPEPROGRAMDATA_BYTE FLASH_TYPEPROGRAMDATA_BYTE +#define TYPEPROGRAMDATA_HALFWORD FLASH_TYPEPROGRAMDATA_HALFWORD +#define TYPEPROGRAMDATA_WORD FLASH_TYPEPROGRAMDATA_WORD +#define TYPEPROGRAMDATA_FASTBYTE FLASH_TYPEPROGRAMDATA_FASTBYTE +#define TYPEPROGRAMDATA_FASTHALFWORD FLASH_TYPEPROGRAMDATA_FASTHALFWORD +#define TYPEPROGRAMDATA_FASTWORD FLASH_TYPEPROGRAMDATA_FASTWORD +#define PAGESIZE FLASH_PAGE_SIZE +#define TYPEPROGRAM_FASTBYTE FLASH_TYPEPROGRAM_BYTE +#define TYPEPROGRAM_FASTHALFWORD FLASH_TYPEPROGRAM_HALFWORD +#define TYPEPROGRAM_FASTWORD FLASH_TYPEPROGRAM_WORD +#define VOLTAGE_RANGE_1 FLASH_VOLTAGE_RANGE_1 +#define VOLTAGE_RANGE_2 FLASH_VOLTAGE_RANGE_2 +#define VOLTAGE_RANGE_3 FLASH_VOLTAGE_RANGE_3 +#define VOLTAGE_RANGE_4 FLASH_VOLTAGE_RANGE_4 +#define TYPEPROGRAM_FAST FLASH_TYPEPROGRAM_FAST +#define TYPEPROGRAM_FAST_AND_LAST FLASH_TYPEPROGRAM_FAST_AND_LAST +#define WRPAREA_BANK1_AREAA OB_WRPAREA_BANK1_AREAA +#define WRPAREA_BANK1_AREAB OB_WRPAREA_BANK1_AREAB +#define WRPAREA_BANK2_AREAA OB_WRPAREA_BANK2_AREAA +#define WRPAREA_BANK2_AREAB OB_WRPAREA_BANK2_AREAB +#define IWDG_STDBY_FREEZE OB_IWDG_STDBY_FREEZE +#define IWDG_STDBY_ACTIVE OB_IWDG_STDBY_RUN +#define IWDG_STOP_FREEZE OB_IWDG_STOP_FREEZE +#define IWDG_STOP_ACTIVE OB_IWDG_STOP_RUN +#define FLASH_ERROR_NONE HAL_FLASH_ERROR_NONE +#define FLASH_ERROR_RD HAL_FLASH_ERROR_RD +#define FLASH_ERROR_PG HAL_FLASH_ERROR_PROG +#define FLASH_ERROR_PGP HAL_FLASH_ERROR_PGS +#define FLASH_ERROR_WRP HAL_FLASH_ERROR_WRP +#define FLASH_ERROR_OPTV HAL_FLASH_ERROR_OPTV +#define FLASH_ERROR_OPTVUSR HAL_FLASH_ERROR_OPTVUSR +#define FLASH_ERROR_PROG HAL_FLASH_ERROR_PROG +#define FLASH_ERROR_OP HAL_FLASH_ERROR_OPERATION +#define FLASH_ERROR_PGA HAL_FLASH_ERROR_PGA +#define FLASH_ERROR_SIZE HAL_FLASH_ERROR_SIZE +#define FLASH_ERROR_SIZ HAL_FLASH_ERROR_SIZE +#define FLASH_ERROR_PGS HAL_FLASH_ERROR_PGS +#define FLASH_ERROR_MIS HAL_FLASH_ERROR_MIS +#define FLASH_ERROR_FAST HAL_FLASH_ERROR_FAST +#define FLASH_ERROR_FWWERR HAL_FLASH_ERROR_FWWERR +#define FLASH_ERROR_NOTZERO HAL_FLASH_ERROR_NOTZERO +#define FLASH_ERROR_OPERATION HAL_FLASH_ERROR_OPERATION +#define FLASH_ERROR_ERS HAL_FLASH_ERROR_ERS +#define OB_WDG_SW OB_IWDG_SW +#define OB_WDG_HW OB_IWDG_HW +#define OB_SDADC12_VDD_MONITOR_SET OB_SDACD_VDD_MONITOR_SET +#define OB_SDADC12_VDD_MONITOR_RESET OB_SDACD_VDD_MONITOR_RESET +#define OB_RAM_PARITY_CHECK_SET OB_SRAM_PARITY_SET +#define OB_RAM_PARITY_CHECK_RESET OB_SRAM_PARITY_RESET +#define IS_OB_SDADC12_VDD_MONITOR IS_OB_SDACD_VDD_MONITOR +#define OB_RDP_LEVEL0 OB_RDP_LEVEL_0 +#define OB_RDP_LEVEL1 OB_RDP_LEVEL_1 +#define OB_RDP_LEVEL2 OB_RDP_LEVEL_2 + +/** + * @} + */ + +/** @defgroup HAL_SYSCFG_Aliased_Defines HAL SYSCFG Aliased Defines maintained for legacy purpose + * @{ + */ + +#define HAL_SYSCFG_FASTMODEPLUS_I2C_PA9 I2C_FASTMODEPLUS_PA9 +#define HAL_SYSCFG_FASTMODEPLUS_I2C_PA10 I2C_FASTMODEPLUS_PA10 +#define HAL_SYSCFG_FASTMODEPLUS_I2C_PB6 I2C_FASTMODEPLUS_PB6 +#define HAL_SYSCFG_FASTMODEPLUS_I2C_PB7 I2C_FASTMODEPLUS_PB7 +#define HAL_SYSCFG_FASTMODEPLUS_I2C_PB8 I2C_FASTMODEPLUS_PB8 +#define HAL_SYSCFG_FASTMODEPLUS_I2C_PB9 I2C_FASTMODEPLUS_PB9 +#define HAL_SYSCFG_FASTMODEPLUS_I2C1 I2C_FASTMODEPLUS_I2C1 +#define HAL_SYSCFG_FASTMODEPLUS_I2C2 I2C_FASTMODEPLUS_I2C2 +#define HAL_SYSCFG_FASTMODEPLUS_I2C3 I2C_FASTMODEPLUS_I2C3 +/** + * @} + */ + + +/** @defgroup LL_FMC_Aliased_Defines LL FMC Aliased Defines maintained for compatibility purpose + * @{ + */ +#if defined(STM32L4) || defined(STM32F7) || defined(STM32H7) || defined(STM32G4) +#define FMC_NAND_PCC_WAIT_FEATURE_DISABLE FMC_NAND_WAIT_FEATURE_DISABLE +#define FMC_NAND_PCC_WAIT_FEATURE_ENABLE FMC_NAND_WAIT_FEATURE_ENABLE +#define FMC_NAND_PCC_MEM_BUS_WIDTH_8 FMC_NAND_MEM_BUS_WIDTH_8 +#define FMC_NAND_PCC_MEM_BUS_WIDTH_16 FMC_NAND_MEM_BUS_WIDTH_16 +#else +#define FMC_NAND_WAIT_FEATURE_DISABLE FMC_NAND_PCC_WAIT_FEATURE_DISABLE +#define FMC_NAND_WAIT_FEATURE_ENABLE FMC_NAND_PCC_WAIT_FEATURE_ENABLE +#define FMC_NAND_MEM_BUS_WIDTH_8 FMC_NAND_PCC_MEM_BUS_WIDTH_8 +#define FMC_NAND_MEM_BUS_WIDTH_16 FMC_NAND_PCC_MEM_BUS_WIDTH_16 +#endif +/** + * @} + */ + +/** @defgroup LL_FSMC_Aliased_Defines LL FSMC Aliased Defines maintained for legacy purpose + * @{ + */ + +#define FSMC_NORSRAM_TYPEDEF FSMC_NORSRAM_TypeDef +#define FSMC_NORSRAM_EXTENDED_TYPEDEF FSMC_NORSRAM_EXTENDED_TypeDef +/** + * @} + */ + +/** @defgroup HAL_GPIO_Aliased_Macros HAL GPIO Aliased Macros maintained for legacy purpose + * @{ + */ +#define GET_GPIO_SOURCE GPIO_GET_INDEX +#define GET_GPIO_INDEX GPIO_GET_INDEX + +#if defined(STM32F4) +#define GPIO_AF12_SDMMC GPIO_AF12_SDIO +#define GPIO_AF12_SDMMC1 GPIO_AF12_SDIO +#endif + +#if defined(STM32F7) +#define GPIO_AF12_SDIO GPIO_AF12_SDMMC1 +#define GPIO_AF12_SDMMC GPIO_AF12_SDMMC1 +#endif + +#if defined(STM32L4) +#define GPIO_AF12_SDIO GPIO_AF12_SDMMC1 +#define GPIO_AF12_SDMMC GPIO_AF12_SDMMC1 +#endif + +#define GPIO_AF0_LPTIM GPIO_AF0_LPTIM1 +#define GPIO_AF1_LPTIM GPIO_AF1_LPTIM1 +#define GPIO_AF2_LPTIM GPIO_AF2_LPTIM1 + +#if defined(STM32L0) || defined(STM32L4) || defined(STM32F4) || defined(STM32F2) || defined(STM32F7) || defined(STM32G4) +#define GPIO_SPEED_LOW GPIO_SPEED_FREQ_LOW +#define GPIO_SPEED_MEDIUM GPIO_SPEED_FREQ_MEDIUM +#define GPIO_SPEED_FAST GPIO_SPEED_FREQ_HIGH +#define GPIO_SPEED_HIGH GPIO_SPEED_FREQ_VERY_HIGH +#endif /* STM32L0 || STM32L4 || STM32F4 || STM32F2 || STM32F7 || STM32G4 */ + +#if defined(STM32L1) + #define GPIO_SPEED_VERY_LOW GPIO_SPEED_FREQ_LOW + #define GPIO_SPEED_LOW GPIO_SPEED_FREQ_MEDIUM + #define GPIO_SPEED_MEDIUM GPIO_SPEED_FREQ_HIGH + #define GPIO_SPEED_HIGH GPIO_SPEED_FREQ_VERY_HIGH +#endif /* STM32L1 */ + +#if defined(STM32F0) || defined(STM32F3) || defined(STM32F1) + #define GPIO_SPEED_LOW GPIO_SPEED_FREQ_LOW + #define GPIO_SPEED_MEDIUM GPIO_SPEED_FREQ_MEDIUM + #define GPIO_SPEED_HIGH GPIO_SPEED_FREQ_HIGH +#endif /* STM32F0 || STM32F3 || STM32F1 */ + +#define GPIO_AF6_DFSDM GPIO_AF6_DFSDM1 +/** + * @} + */ + +/** @defgroup HAL_JPEG_Aliased_Macros HAL JPEG Aliased Macros maintained for legacy purpose + * @{ + */ + +#if defined(STM32H7) + #define __HAL_RCC_JPEG_CLK_ENABLE __HAL_RCC_JPGDECEN_CLK_ENABLE + #define __HAL_RCC_JPEG_CLK_DISABLE __HAL_RCC_JPGDECEN_CLK_DISABLE + #define __HAL_RCC_JPEG_FORCE_RESET __HAL_RCC_JPGDECRST_FORCE_RESET + #define __HAL_RCC_JPEG_RELEASE_RESET __HAL_RCC_JPGDECRST_RELEASE_RESET + #define __HAL_RCC_JPEG_CLK_SLEEP_ENABLE __HAL_RCC_JPGDEC_CLK_SLEEP_ENABLE + #define __HAL_RCC_JPEG_CLK_SLEEP_DISABLE __HAL_RCC_JPGDEC_CLK_SLEEP_DISABLE + + #define DMA_REQUEST_DAC1 DMA_REQUEST_DAC1_CH1 + #define DMA_REQUEST_DAC2 DMA_REQUEST_DAC1_CH2 + + #define BDMA_REQUEST_LP_UART1_RX BDMA_REQUEST_LPUART1_RX + #define BDMA_REQUEST_LP_UART1_TX BDMA_REQUEST_LPUART1_TX + + #define HAL_DMAMUX1_REQUEST_GEN_DMAMUX1_CH0_EVT HAL_DMAMUX1_REQ_GEN_DMAMUX1_CH0_EVT + #define HAL_DMAMUX1_REQUEST_GEN_DMAMUX1_CH1_EVT HAL_DMAMUX1_REQ_GEN_DMAMUX1_CH1_EVT + #define HAL_DMAMUX1_REQUEST_GEN_DMAMUX1_CH2_EVT HAL_DMAMUX1_REQ_GEN_DMAMUX1_CH2_EVT + #define HAL_DMAMUX1_REQUEST_GEN_LPTIM1_OUT HAL_DMAMUX1_REQ_GEN_LPTIM1_OUT + #define HAL_DMAMUX1_REQUEST_GEN_LPTIM2_OUT HAL_DMAMUX1_REQ_GEN_LPTIM2_OUT + #define HAL_DMAMUX1_REQUEST_GEN_LPTIM3_OUT HAL_DMAMUX1_REQ_GEN_LPTIM3_OUT + #define HAL_DMAMUX1_REQUEST_GEN_EXTI0 HAL_DMAMUX1_REQ_GEN_EXTI0 + #define HAL_DMAMUX1_REQUEST_GEN_TIM12_TRGO HAL_DMAMUX1_REQ_GEN_TIM12_TRGO + + #define HAL_DMAMUX2_REQUEST_GEN_DMAMUX2_CH0_EVT HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH0_EVT + #define HAL_DMAMUX2_REQUEST_GEN_DMAMUX2_CH1_EVT HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH1_EVT + #define HAL_DMAMUX2_REQUEST_GEN_DMAMUX2_CH2_EVT HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH2_EVT + #define HAL_DMAMUX2_REQUEST_GEN_DMAMUX2_CH3_EVT HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH3_EVT + #define HAL_DMAMUX2_REQUEST_GEN_DMAMUX2_CH4_EVT HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH4_EVT + #define HAL_DMAMUX2_REQUEST_GEN_DMAMUX2_CH5_EVT HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH5_EVT + #define HAL_DMAMUX2_REQUEST_GEN_DMAMUX2_CH6_EVT HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH6_EVT + #define HAL_DMAMUX2_REQUEST_GEN_LPUART1_RX_WKUP HAL_DMAMUX2_REQ_GEN_LPUART1_RX_WKUP + #define HAL_DMAMUX2_REQUEST_GEN_LPUART1_TX_WKUP HAL_DMAMUX2_REQ_GEN_LPUART1_TX_WKUP + #define HAL_DMAMUX2_REQUEST_GEN_LPTIM2_WKUP HAL_DMAMUX2_REQ_GEN_LPTIM2_WKUP + #define HAL_DMAMUX2_REQUEST_GEN_LPTIM2_OUT HAL_DMAMUX2_REQ_GEN_LPTIM2_OUT + #define HAL_DMAMUX2_REQUEST_GEN_LPTIM3_WKUP HAL_DMAMUX2_REQ_GEN_LPTIM3_WKUP + #define HAL_DMAMUX2_REQUEST_GEN_LPTIM3_OUT HAL_DMAMUX2_REQ_GEN_LPTIM3_OUT + #define HAL_DMAMUX2_REQUEST_GEN_LPTIM4_WKUP HAL_DMAMUX2_REQ_GEN_LPTIM4_WKUP + #define HAL_DMAMUX2_REQUEST_GEN_LPTIM5_WKUP HAL_DMAMUX2_REQ_GEN_LPTIM5_WKUP + #define HAL_DMAMUX2_REQUEST_GEN_I2C4_WKUP HAL_DMAMUX2_REQ_GEN_I2C4_WKUP + #define HAL_DMAMUX2_REQUEST_GEN_SPI6_WKUP HAL_DMAMUX2_REQ_GEN_SPI6_WKUP + #define HAL_DMAMUX2_REQUEST_GEN_COMP1_OUT HAL_DMAMUX2_REQ_GEN_COMP1_OUT + #define HAL_DMAMUX2_REQUEST_GEN_COMP2_OUT HAL_DMAMUX2_REQ_GEN_COMP2_OUT + #define HAL_DMAMUX2_REQUEST_GEN_RTC_WKUP HAL_DMAMUX2_REQ_GEN_RTC_WKUP + #define HAL_DMAMUX2_REQUEST_GEN_EXTI0 HAL_DMAMUX2_REQ_GEN_EXTI0 + #define HAL_DMAMUX2_REQUEST_GEN_EXTI2 HAL_DMAMUX2_REQ_GEN_EXTI2 + #define HAL_DMAMUX2_REQUEST_GEN_I2C4_IT_EVT HAL_DMAMUX2_REQ_GEN_I2C4_IT_EVT + #define HAL_DMAMUX2_REQUEST_GEN_SPI6_IT HAL_DMAMUX2_REQ_GEN_SPI6_IT + #define HAL_DMAMUX2_REQUEST_GEN_LPUART1_TX_IT HAL_DMAMUX2_REQ_GEN_LPUART1_TX_IT + #define HAL_DMAMUX2_REQUEST_GEN_LPUART1_RX_IT HAL_DMAMUX2_REQ_GEN_LPUART1_RX_IT + #define HAL_DMAMUX2_REQUEST_GEN_ADC3_IT HAL_DMAMUX2_REQ_GEN_ADC3_IT + #define HAL_DMAMUX2_REQUEST_GEN_ADC3_AWD1_OUT HAL_DMAMUX2_REQ_GEN_ADC3_AWD1_OUT + #define HAL_DMAMUX2_REQUEST_GEN_BDMA_CH0_IT HAL_DMAMUX2_REQ_GEN_BDMA_CH0_IT + #define HAL_DMAMUX2_REQUEST_GEN_BDMA_CH1_IT HAL_DMAMUX2_REQ_GEN_BDMA_CH1_IT + + #define HAL_DMAMUX_REQUEST_GEN_NO_EVENT HAL_DMAMUX_REQ_GEN_NO_EVENT + #define HAL_DMAMUX_REQUEST_GEN_RISING HAL_DMAMUX_REQ_GEN_RISING + #define HAL_DMAMUX_REQUEST_GEN_FALLING HAL_DMAMUX_REQ_GEN_FALLING + #define HAL_DMAMUX_REQUEST_GEN_RISING_FALLING HAL_DMAMUX_REQ_GEN_RISING_FALLING + + +#endif /* STM32H7 */ + + +/** + * @} + */ + + +/** @defgroup HAL_HRTIM_Aliased_Macros HAL HRTIM Aliased Macros maintained for legacy purpose + * @{ + */ +#define HRTIM_TIMDELAYEDPROTECTION_DISABLED HRTIM_TIMER_A_B_C_DELAYEDPROTECTION_DISABLED +#define HRTIM_TIMDELAYEDPROTECTION_DELAYEDOUT1_EEV68 HRTIM_TIMER_A_B_C_DELAYEDPROTECTION_DELAYEDOUT1_EEV6 +#define HRTIM_TIMDELAYEDPROTECTION_DELAYEDOUT2_EEV68 HRTIM_TIMER_A_B_C_DELAYEDPROTECTION_DELAYEDOUT2_EEV6 +#define HRTIM_TIMDELAYEDPROTECTION_DELAYEDBOTH_EEV68 HRTIM_TIMER_A_B_C_DELAYEDPROTECTION_DELAYEDBOTH_EEV6 +#define HRTIM_TIMDELAYEDPROTECTION_BALANCED_EEV68 HRTIM_TIMER_A_B_C_DELAYEDPROTECTION_BALANCED_EEV6 +#define HRTIM_TIMDELAYEDPROTECTION_DELAYEDOUT1_DEEV79 HRTIM_TIMER_A_B_C_DELAYEDPROTECTION_DELAYEDOUT1_DEEV7 +#define HRTIM_TIMDELAYEDPROTECTION_DELAYEDOUT2_DEEV79 HRTIM_TIMER_A_B_C_DELAYEDPROTECTION_DELAYEDOUT2_DEEV7 +#define HRTIM_TIMDELAYEDPROTECTION_DELAYEDBOTH_EEV79 HRTIM_TIMER_A_B_C_DELAYEDPROTECTION_DELAYEDBOTH_EEV7 +#define HRTIM_TIMDELAYEDPROTECTION_BALANCED_EEV79 HRTIM_TIMER_A_B_C_DELAYEDPROTECTION_BALANCED_EEV7 + +#define __HAL_HRTIM_SetCounter __HAL_HRTIM_SETCOUNTER +#define __HAL_HRTIM_GetCounter __HAL_HRTIM_GETCOUNTER +#define __HAL_HRTIM_SetPeriod __HAL_HRTIM_SETPERIOD +#define __HAL_HRTIM_GetPeriod __HAL_HRTIM_GETPERIOD +#define __HAL_HRTIM_SetClockPrescaler __HAL_HRTIM_SETCLOCKPRESCALER +#define __HAL_HRTIM_GetClockPrescaler __HAL_HRTIM_GETCLOCKPRESCALER +#define __HAL_HRTIM_SetCompare __HAL_HRTIM_SETCOMPARE +#define __HAL_HRTIM_GetCompare __HAL_HRTIM_GETCOMPARE +/** + * @} + */ + +/** @defgroup HAL_I2C_Aliased_Defines HAL I2C Aliased Defines maintained for legacy purpose + * @{ + */ +#define I2C_DUALADDRESS_DISABLED I2C_DUALADDRESS_DISABLE +#define I2C_DUALADDRESS_ENABLED I2C_DUALADDRESS_ENABLE +#define I2C_GENERALCALL_DISABLED I2C_GENERALCALL_DISABLE +#define I2C_GENERALCALL_ENABLED I2C_GENERALCALL_ENABLE +#define I2C_NOSTRETCH_DISABLED I2C_NOSTRETCH_DISABLE +#define I2C_NOSTRETCH_ENABLED I2C_NOSTRETCH_ENABLE +#define I2C_ANALOGFILTER_ENABLED I2C_ANALOGFILTER_ENABLE +#define I2C_ANALOGFILTER_DISABLED I2C_ANALOGFILTER_DISABLE +#if defined(STM32F0) || defined(STM32F1) || defined(STM32F3) || defined(STM32G0) || defined(STM32L4) || defined(STM32L1) || defined(STM32F7) +#define HAL_I2C_STATE_MEM_BUSY_TX HAL_I2C_STATE_BUSY_TX +#define HAL_I2C_STATE_MEM_BUSY_RX HAL_I2C_STATE_BUSY_RX +#define HAL_I2C_STATE_MASTER_BUSY_TX HAL_I2C_STATE_BUSY_TX +#define HAL_I2C_STATE_MASTER_BUSY_RX HAL_I2C_STATE_BUSY_RX +#define HAL_I2C_STATE_SLAVE_BUSY_TX HAL_I2C_STATE_BUSY_TX +#define HAL_I2C_STATE_SLAVE_BUSY_RX HAL_I2C_STATE_BUSY_RX +#endif +/** + * @} + */ + +/** @defgroup HAL_IRDA_Aliased_Defines HAL IRDA Aliased Defines maintained for legacy purpose + * @{ + */ +#define IRDA_ONE_BIT_SAMPLE_DISABLED IRDA_ONE_BIT_SAMPLE_DISABLE +#define IRDA_ONE_BIT_SAMPLE_ENABLED IRDA_ONE_BIT_SAMPLE_ENABLE + +/** + * @} + */ + +/** @defgroup HAL_IWDG_Aliased_Defines HAL IWDG Aliased Defines maintained for legacy purpose + * @{ + */ +#define KR_KEY_RELOAD IWDG_KEY_RELOAD +#define KR_KEY_ENABLE IWDG_KEY_ENABLE +#define KR_KEY_EWA IWDG_KEY_WRITE_ACCESS_ENABLE +#define KR_KEY_DWA IWDG_KEY_WRITE_ACCESS_DISABLE +/** + * @} + */ + +/** @defgroup HAL_LPTIM_Aliased_Defines HAL LPTIM Aliased Defines maintained for legacy purpose + * @{ + */ + +#define LPTIM_CLOCKSAMPLETIME_DIRECTTRANSISTION LPTIM_CLOCKSAMPLETIME_DIRECTTRANSITION +#define LPTIM_CLOCKSAMPLETIME_2TRANSISTIONS LPTIM_CLOCKSAMPLETIME_2TRANSITIONS +#define LPTIM_CLOCKSAMPLETIME_4TRANSISTIONS LPTIM_CLOCKSAMPLETIME_4TRANSITIONS +#define LPTIM_CLOCKSAMPLETIME_8TRANSISTIONS LPTIM_CLOCKSAMPLETIME_8TRANSITIONS + +#define LPTIM_CLOCKPOLARITY_RISINGEDGE LPTIM_CLOCKPOLARITY_RISING +#define LPTIM_CLOCKPOLARITY_FALLINGEDGE LPTIM_CLOCKPOLARITY_FALLING +#define LPTIM_CLOCKPOLARITY_BOTHEDGES LPTIM_CLOCKPOLARITY_RISING_FALLING + +#define LPTIM_TRIGSAMPLETIME_DIRECTTRANSISTION LPTIM_TRIGSAMPLETIME_DIRECTTRANSITION +#define LPTIM_TRIGSAMPLETIME_2TRANSISTIONS LPTIM_TRIGSAMPLETIME_2TRANSITIONS +#define LPTIM_TRIGSAMPLETIME_4TRANSISTIONS LPTIM_TRIGSAMPLETIME_4TRANSITIONS +#define LPTIM_TRIGSAMPLETIME_8TRANSISTIONS LPTIM_TRIGSAMPLETIME_8TRANSITIONS + +/* The following 3 definition have also been present in a temporary version of lptim.h */ +/* They need to be renamed also to the right name, just in case */ +#define LPTIM_TRIGSAMPLETIME_2TRANSITION LPTIM_TRIGSAMPLETIME_2TRANSITIONS +#define LPTIM_TRIGSAMPLETIME_4TRANSITION LPTIM_TRIGSAMPLETIME_4TRANSITIONS +#define LPTIM_TRIGSAMPLETIME_8TRANSITION LPTIM_TRIGSAMPLETIME_8TRANSITIONS + +/** + * @} + */ + +/** @defgroup HAL_NAND_Aliased_Defines HAL NAND Aliased Defines maintained for legacy purpose + * @{ + */ +#define HAL_NAND_Read_Page HAL_NAND_Read_Page_8b +#define HAL_NAND_Write_Page HAL_NAND_Write_Page_8b +#define HAL_NAND_Read_SpareArea HAL_NAND_Read_SpareArea_8b +#define HAL_NAND_Write_SpareArea HAL_NAND_Write_SpareArea_8b + +#define NAND_AddressTypedef NAND_AddressTypeDef + +#define __ARRAY_ADDRESS ARRAY_ADDRESS +#define __ADDR_1st_CYCLE ADDR_1ST_CYCLE +#define __ADDR_2nd_CYCLE ADDR_2ND_CYCLE +#define __ADDR_3rd_CYCLE ADDR_3RD_CYCLE +#define __ADDR_4th_CYCLE ADDR_4TH_CYCLE +/** + * @} + */ + +/** @defgroup HAL_NOR_Aliased_Defines HAL NOR Aliased Defines maintained for legacy purpose + * @{ + */ +#define NOR_StatusTypedef HAL_NOR_StatusTypeDef +#define NOR_SUCCESS HAL_NOR_STATUS_SUCCESS +#define NOR_ONGOING HAL_NOR_STATUS_ONGOING +#define NOR_ERROR HAL_NOR_STATUS_ERROR +#define NOR_TIMEOUT HAL_NOR_STATUS_TIMEOUT + +#define __NOR_WRITE NOR_WRITE +#define __NOR_ADDR_SHIFT NOR_ADDR_SHIFT +/** + * @} + */ + +/** @defgroup HAL_OPAMP_Aliased_Defines HAL OPAMP Aliased Defines maintained for legacy purpose + * @{ + */ + +#define OPAMP_NONINVERTINGINPUT_VP0 OPAMP_NONINVERTINGINPUT_IO0 +#define OPAMP_NONINVERTINGINPUT_VP1 OPAMP_NONINVERTINGINPUT_IO1 +#define OPAMP_NONINVERTINGINPUT_VP2 OPAMP_NONINVERTINGINPUT_IO2 +#define OPAMP_NONINVERTINGINPUT_VP3 OPAMP_NONINVERTINGINPUT_IO3 + +#define OPAMP_SEC_NONINVERTINGINPUT_VP0 OPAMP_SEC_NONINVERTINGINPUT_IO0 +#define OPAMP_SEC_NONINVERTINGINPUT_VP1 OPAMP_SEC_NONINVERTINGINPUT_IO1 +#define OPAMP_SEC_NONINVERTINGINPUT_VP2 OPAMP_SEC_NONINVERTINGINPUT_IO2 +#define OPAMP_SEC_NONINVERTINGINPUT_VP3 OPAMP_SEC_NONINVERTINGINPUT_IO3 + +#define OPAMP_INVERTINGINPUT_VM0 OPAMP_INVERTINGINPUT_IO0 +#define OPAMP_INVERTINGINPUT_VM1 OPAMP_INVERTINGINPUT_IO1 + +#define IOPAMP_INVERTINGINPUT_VM0 OPAMP_INVERTINGINPUT_IO0 +#define IOPAMP_INVERTINGINPUT_VM1 OPAMP_INVERTINGINPUT_IO1 + +#define OPAMP_SEC_INVERTINGINPUT_VM0 OPAMP_SEC_INVERTINGINPUT_IO0 +#define OPAMP_SEC_INVERTINGINPUT_VM1 OPAMP_SEC_INVERTINGINPUT_IO1 + +#define OPAMP_INVERTINGINPUT_VINM OPAMP_SEC_INVERTINGINPUT_IO1 + +#define OPAMP_PGACONNECT_NO OPAMP_PGA_CONNECT_INVERTINGINPUT_NO +#define OPAMP_PGACONNECT_VM0 OPAMP_PGA_CONNECT_INVERTINGINPUT_IO0 +#define OPAMP_PGACONNECT_VM1 OPAMP_PGA_CONNECT_INVERTINGINPUT_IO1 + +/** + * @} + */ + +/** @defgroup HAL_I2S_Aliased_Defines HAL I2S Aliased Defines maintained for legacy purpose + * @{ + */ +#define I2S_STANDARD_PHILLIPS I2S_STANDARD_PHILIPS +#if defined(STM32F7) + #define I2S_CLOCK_SYSCLK I2S_CLOCK_PLL +#endif +/** + * @} + */ + +/** @defgroup HAL_PCCARD_Aliased_Defines HAL PCCARD Aliased Defines maintained for legacy purpose + * @{ + */ + +/* Compact Flash-ATA registers description */ +#define CF_DATA ATA_DATA +#define CF_SECTOR_COUNT ATA_SECTOR_COUNT +#define CF_SECTOR_NUMBER ATA_SECTOR_NUMBER +#define CF_CYLINDER_LOW ATA_CYLINDER_LOW +#define CF_CYLINDER_HIGH ATA_CYLINDER_HIGH +#define CF_CARD_HEAD ATA_CARD_HEAD +#define CF_STATUS_CMD ATA_STATUS_CMD +#define CF_STATUS_CMD_ALTERNATE ATA_STATUS_CMD_ALTERNATE +#define CF_COMMON_DATA_AREA ATA_COMMON_DATA_AREA + +/* Compact Flash-ATA commands */ +#define CF_READ_SECTOR_CMD ATA_READ_SECTOR_CMD +#define CF_WRITE_SECTOR_CMD ATA_WRITE_SECTOR_CMD +#define CF_ERASE_SECTOR_CMD ATA_ERASE_SECTOR_CMD +#define CF_IDENTIFY_CMD ATA_IDENTIFY_CMD + +#define PCCARD_StatusTypedef HAL_PCCARD_StatusTypeDef +#define PCCARD_SUCCESS HAL_PCCARD_STATUS_SUCCESS +#define PCCARD_ONGOING HAL_PCCARD_STATUS_ONGOING +#define PCCARD_ERROR HAL_PCCARD_STATUS_ERROR +#define PCCARD_TIMEOUT HAL_PCCARD_STATUS_TIMEOUT +/** + * @} + */ + +/** @defgroup HAL_RTC_Aliased_Defines HAL RTC Aliased Defines maintained for legacy purpose + * @{ + */ + +#define FORMAT_BIN RTC_FORMAT_BIN +#define FORMAT_BCD RTC_FORMAT_BCD + +#define RTC_ALARMSUBSECONDMASK_None RTC_ALARMSUBSECONDMASK_NONE +#define RTC_TAMPERERASEBACKUP_DISABLED RTC_TAMPER_ERASE_BACKUP_DISABLE +#define RTC_TAMPERMASK_FLAG_DISABLED RTC_TAMPERMASK_FLAG_DISABLE +#define RTC_TAMPERMASK_FLAG_ENABLED RTC_TAMPERMASK_FLAG_ENABLE + +#define RTC_MASKTAMPERFLAG_DISABLED RTC_TAMPERMASK_FLAG_DISABLE +#define RTC_MASKTAMPERFLAG_ENABLED RTC_TAMPERMASK_FLAG_ENABLE +#define RTC_TAMPERERASEBACKUP_ENABLED RTC_TAMPER_ERASE_BACKUP_ENABLE +#define RTC_TAMPER1_2_INTERRUPT RTC_ALL_TAMPER_INTERRUPT +#define RTC_TAMPER1_2_3_INTERRUPT RTC_ALL_TAMPER_INTERRUPT + +#define RTC_TIMESTAMPPIN_PC13 RTC_TIMESTAMPPIN_DEFAULT +#define RTC_TIMESTAMPPIN_PA0 RTC_TIMESTAMPPIN_POS1 +#define RTC_TIMESTAMPPIN_PI8 RTC_TIMESTAMPPIN_POS1 +#define RTC_TIMESTAMPPIN_PC1 RTC_TIMESTAMPPIN_POS2 + +#define RTC_OUTPUT_REMAP_PC13 RTC_OUTPUT_REMAP_NONE +#define RTC_OUTPUT_REMAP_PB14 RTC_OUTPUT_REMAP_POS1 +#define RTC_OUTPUT_REMAP_PB2 RTC_OUTPUT_REMAP_POS1 + +#define RTC_TAMPERPIN_PC13 RTC_TAMPERPIN_DEFAULT +#define RTC_TAMPERPIN_PA0 RTC_TAMPERPIN_POS1 +#define RTC_TAMPERPIN_PI8 RTC_TAMPERPIN_POS1 + +/** + * @} + */ + + +/** @defgroup HAL_SMARTCARD_Aliased_Defines HAL SMARTCARD Aliased Defines maintained for legacy purpose + * @{ + */ +#define SMARTCARD_NACK_ENABLED SMARTCARD_NACK_ENABLE +#define SMARTCARD_NACK_DISABLED SMARTCARD_NACK_DISABLE + +#define SMARTCARD_ONEBIT_SAMPLING_DISABLED SMARTCARD_ONE_BIT_SAMPLE_DISABLE +#define SMARTCARD_ONEBIT_SAMPLING_ENABLED SMARTCARD_ONE_BIT_SAMPLE_ENABLE +#define SMARTCARD_ONEBIT_SAMPLING_DISABLE SMARTCARD_ONE_BIT_SAMPLE_DISABLE +#define SMARTCARD_ONEBIT_SAMPLING_ENABLE SMARTCARD_ONE_BIT_SAMPLE_ENABLE + +#define SMARTCARD_TIMEOUT_DISABLED SMARTCARD_TIMEOUT_DISABLE +#define SMARTCARD_TIMEOUT_ENABLED SMARTCARD_TIMEOUT_ENABLE + +#define SMARTCARD_LASTBIT_DISABLED SMARTCARD_LASTBIT_DISABLE +#define SMARTCARD_LASTBIT_ENABLED SMARTCARD_LASTBIT_ENABLE +/** + * @} + */ + + +/** @defgroup HAL_SMBUS_Aliased_Defines HAL SMBUS Aliased Defines maintained for legacy purpose + * @{ + */ +#define SMBUS_DUALADDRESS_DISABLED SMBUS_DUALADDRESS_DISABLE +#define SMBUS_DUALADDRESS_ENABLED SMBUS_DUALADDRESS_ENABLE +#define SMBUS_GENERALCALL_DISABLED SMBUS_GENERALCALL_DISABLE +#define SMBUS_GENERALCALL_ENABLED SMBUS_GENERALCALL_ENABLE +#define SMBUS_NOSTRETCH_DISABLED SMBUS_NOSTRETCH_DISABLE +#define SMBUS_NOSTRETCH_ENABLED SMBUS_NOSTRETCH_ENABLE +#define SMBUS_ANALOGFILTER_ENABLED SMBUS_ANALOGFILTER_ENABLE +#define SMBUS_ANALOGFILTER_DISABLED SMBUS_ANALOGFILTER_DISABLE +#define SMBUS_PEC_DISABLED SMBUS_PEC_DISABLE +#define SMBUS_PEC_ENABLED SMBUS_PEC_ENABLE +#define HAL_SMBUS_STATE_SLAVE_LISTEN HAL_SMBUS_STATE_LISTEN +/** + * @} + */ + +/** @defgroup HAL_SPI_Aliased_Defines HAL SPI Aliased Defines maintained for legacy purpose + * @{ + */ +#define SPI_TIMODE_DISABLED SPI_TIMODE_DISABLE +#define SPI_TIMODE_ENABLED SPI_TIMODE_ENABLE + +#define SPI_CRCCALCULATION_DISABLED SPI_CRCCALCULATION_DISABLE +#define SPI_CRCCALCULATION_ENABLED SPI_CRCCALCULATION_ENABLE + +#define SPI_NSS_PULSE_DISABLED SPI_NSS_PULSE_DISABLE +#define SPI_NSS_PULSE_ENABLED SPI_NSS_PULSE_ENABLE + +/** + * @} + */ + +/** @defgroup HAL_TIM_Aliased_Defines HAL TIM Aliased Defines maintained for legacy purpose + * @{ + */ +#define CCER_CCxE_MASK TIM_CCER_CCxE_MASK +#define CCER_CCxNE_MASK TIM_CCER_CCxNE_MASK + +#define TIM_DMABase_CR1 TIM_DMABASE_CR1 +#define TIM_DMABase_CR2 TIM_DMABASE_CR2 +#define TIM_DMABase_SMCR TIM_DMABASE_SMCR +#define TIM_DMABase_DIER TIM_DMABASE_DIER +#define TIM_DMABase_SR TIM_DMABASE_SR +#define TIM_DMABase_EGR TIM_DMABASE_EGR +#define TIM_DMABase_CCMR1 TIM_DMABASE_CCMR1 +#define TIM_DMABase_CCMR2 TIM_DMABASE_CCMR2 +#define TIM_DMABase_CCER TIM_DMABASE_CCER +#define TIM_DMABase_CNT TIM_DMABASE_CNT +#define TIM_DMABase_PSC TIM_DMABASE_PSC +#define TIM_DMABase_ARR TIM_DMABASE_ARR +#define TIM_DMABase_RCR TIM_DMABASE_RCR +#define TIM_DMABase_CCR1 TIM_DMABASE_CCR1 +#define TIM_DMABase_CCR2 TIM_DMABASE_CCR2 +#define TIM_DMABase_CCR3 TIM_DMABASE_CCR3 +#define TIM_DMABase_CCR4 TIM_DMABASE_CCR4 +#define TIM_DMABase_BDTR TIM_DMABASE_BDTR +#define TIM_DMABase_DCR TIM_DMABASE_DCR +#define TIM_DMABase_DMAR TIM_DMABASE_DMAR +#define TIM_DMABase_OR1 TIM_DMABASE_OR1 +#define TIM_DMABase_CCMR3 TIM_DMABASE_CCMR3 +#define TIM_DMABase_CCR5 TIM_DMABASE_CCR5 +#define TIM_DMABase_CCR6 TIM_DMABASE_CCR6 +#define TIM_DMABase_OR2 TIM_DMABASE_OR2 +#define TIM_DMABase_OR3 TIM_DMABASE_OR3 +#define TIM_DMABase_OR TIM_DMABASE_OR + +#define TIM_EventSource_Update TIM_EVENTSOURCE_UPDATE +#define TIM_EventSource_CC1 TIM_EVENTSOURCE_CC1 +#define TIM_EventSource_CC2 TIM_EVENTSOURCE_CC2 +#define TIM_EventSource_CC3 TIM_EVENTSOURCE_CC3 +#define TIM_EventSource_CC4 TIM_EVENTSOURCE_CC4 +#define TIM_EventSource_COM TIM_EVENTSOURCE_COM +#define TIM_EventSource_Trigger TIM_EVENTSOURCE_TRIGGER +#define TIM_EventSource_Break TIM_EVENTSOURCE_BREAK +#define TIM_EventSource_Break2 TIM_EVENTSOURCE_BREAK2 + +#define TIM_DMABurstLength_1Transfer TIM_DMABURSTLENGTH_1TRANSFER +#define TIM_DMABurstLength_2Transfers TIM_DMABURSTLENGTH_2TRANSFERS +#define TIM_DMABurstLength_3Transfers TIM_DMABURSTLENGTH_3TRANSFERS +#define TIM_DMABurstLength_4Transfers TIM_DMABURSTLENGTH_4TRANSFERS +#define TIM_DMABurstLength_5Transfers TIM_DMABURSTLENGTH_5TRANSFERS +#define TIM_DMABurstLength_6Transfers TIM_DMABURSTLENGTH_6TRANSFERS +#define TIM_DMABurstLength_7Transfers TIM_DMABURSTLENGTH_7TRANSFERS +#define TIM_DMABurstLength_8Transfers TIM_DMABURSTLENGTH_8TRANSFERS +#define TIM_DMABurstLength_9Transfers TIM_DMABURSTLENGTH_9TRANSFERS +#define TIM_DMABurstLength_10Transfers TIM_DMABURSTLENGTH_10TRANSFERS +#define TIM_DMABurstLength_11Transfers TIM_DMABURSTLENGTH_11TRANSFERS +#define TIM_DMABurstLength_12Transfers TIM_DMABURSTLENGTH_12TRANSFERS +#define TIM_DMABurstLength_13Transfers TIM_DMABURSTLENGTH_13TRANSFERS +#define TIM_DMABurstLength_14Transfers TIM_DMABURSTLENGTH_14TRANSFERS +#define TIM_DMABurstLength_15Transfers TIM_DMABURSTLENGTH_15TRANSFERS +#define TIM_DMABurstLength_16Transfers TIM_DMABURSTLENGTH_16TRANSFERS +#define TIM_DMABurstLength_17Transfers TIM_DMABURSTLENGTH_17TRANSFERS +#define TIM_DMABurstLength_18Transfers TIM_DMABURSTLENGTH_18TRANSFERS + +/** + * @} + */ + +/** @defgroup HAL_TSC_Aliased_Defines HAL TSC Aliased Defines maintained for legacy purpose + * @{ + */ +#define TSC_SYNC_POL_FALL TSC_SYNC_POLARITY_FALLING +#define TSC_SYNC_POL_RISE_HIGH TSC_SYNC_POLARITY_RISING +/** + * @} + */ + +/** @defgroup HAL_UART_Aliased_Defines HAL UART Aliased Defines maintained for legacy purpose + * @{ + */ +#define UART_ONEBIT_SAMPLING_DISABLED UART_ONE_BIT_SAMPLE_DISABLE +#define UART_ONEBIT_SAMPLING_ENABLED UART_ONE_BIT_SAMPLE_ENABLE +#define UART_ONE_BIT_SAMPLE_DISABLED UART_ONE_BIT_SAMPLE_DISABLE +#define UART_ONE_BIT_SAMPLE_ENABLED UART_ONE_BIT_SAMPLE_ENABLE + +#define __HAL_UART_ONEBIT_ENABLE __HAL_UART_ONE_BIT_SAMPLE_ENABLE +#define __HAL_UART_ONEBIT_DISABLE __HAL_UART_ONE_BIT_SAMPLE_DISABLE + +#define __DIV_SAMPLING16 UART_DIV_SAMPLING16 +#define __DIVMANT_SAMPLING16 UART_DIVMANT_SAMPLING16 +#define __DIVFRAQ_SAMPLING16 UART_DIVFRAQ_SAMPLING16 +#define __UART_BRR_SAMPLING16 UART_BRR_SAMPLING16 + +#define __DIV_SAMPLING8 UART_DIV_SAMPLING8 +#define __DIVMANT_SAMPLING8 UART_DIVMANT_SAMPLING8 +#define __DIVFRAQ_SAMPLING8 UART_DIVFRAQ_SAMPLING8 +#define __UART_BRR_SAMPLING8 UART_BRR_SAMPLING8 + +#define __DIV_LPUART UART_DIV_LPUART + +#define UART_WAKEUPMETHODE_IDLELINE UART_WAKEUPMETHOD_IDLELINE +#define UART_WAKEUPMETHODE_ADDRESSMARK UART_WAKEUPMETHOD_ADDRESSMARK + +/** + * @} + */ + + +/** @defgroup HAL_USART_Aliased_Defines HAL USART Aliased Defines maintained for legacy purpose + * @{ + */ + +#define USART_CLOCK_DISABLED USART_CLOCK_DISABLE +#define USART_CLOCK_ENABLED USART_CLOCK_ENABLE + +#define USARTNACK_ENABLED USART_NACK_ENABLE +#define USARTNACK_DISABLED USART_NACK_DISABLE +/** + * @} + */ + +/** @defgroup HAL_WWDG_Aliased_Defines HAL WWDG Aliased Defines maintained for legacy purpose + * @{ + */ +#define CFR_BASE WWDG_CFR_BASE + +/** + * @} + */ + +/** @defgroup HAL_CAN_Aliased_Defines HAL CAN Aliased Defines maintained for legacy purpose + * @{ + */ +#define CAN_FilterFIFO0 CAN_FILTER_FIFO0 +#define CAN_FilterFIFO1 CAN_FILTER_FIFO1 +#define CAN_IT_RQCP0 CAN_IT_TME +#define CAN_IT_RQCP1 CAN_IT_TME +#define CAN_IT_RQCP2 CAN_IT_TME +#define INAK_TIMEOUT CAN_TIMEOUT_VALUE +#define SLAK_TIMEOUT CAN_TIMEOUT_VALUE +#define CAN_TXSTATUS_FAILED ((uint8_t)0x00U) +#define CAN_TXSTATUS_OK ((uint8_t)0x01U) +#define CAN_TXSTATUS_PENDING ((uint8_t)0x02U) + +/** + * @} + */ + +/** @defgroup HAL_ETH_Aliased_Defines HAL ETH Aliased Defines maintained for legacy purpose + * @{ + */ + +#define VLAN_TAG ETH_VLAN_TAG +#define MIN_ETH_PAYLOAD ETH_MIN_ETH_PAYLOAD +#define MAX_ETH_PAYLOAD ETH_MAX_ETH_PAYLOAD +#define JUMBO_FRAME_PAYLOAD ETH_JUMBO_FRAME_PAYLOAD +#define MACMIIAR_CR_MASK ETH_MACMIIAR_CR_MASK +#define MACCR_CLEAR_MASK ETH_MACCR_CLEAR_MASK +#define MACFCR_CLEAR_MASK ETH_MACFCR_CLEAR_MASK +#define DMAOMR_CLEAR_MASK ETH_DMAOMR_CLEAR_MASK + +#define ETH_MMCCR 0x00000100U +#define ETH_MMCRIR 0x00000104U +#define ETH_MMCTIR 0x00000108U +#define ETH_MMCRIMR 0x0000010CU +#define ETH_MMCTIMR 0x00000110U +#define ETH_MMCTGFSCCR 0x0000014CU +#define ETH_MMCTGFMSCCR 0x00000150U +#define ETH_MMCTGFCR 0x00000168U +#define ETH_MMCRFCECR 0x00000194U +#define ETH_MMCRFAECR 0x00000198U +#define ETH_MMCRGUFCR 0x000001C4U + +#define ETH_MAC_TXFIFO_FULL 0x02000000U /* Tx FIFO full */ +#define ETH_MAC_TXFIFONOT_EMPTY 0x01000000U /* Tx FIFO not empty */ +#define ETH_MAC_TXFIFO_WRITE_ACTIVE 0x00400000U /* Tx FIFO write active */ +#define ETH_MAC_TXFIFO_IDLE 0x00000000U /* Tx FIFO read status: Idle */ +#define ETH_MAC_TXFIFO_READ 0x00100000U /* Tx FIFO read status: Read (transferring data to the MAC transmitter) */ +#define ETH_MAC_TXFIFO_WAITING 0x00200000U /* Tx FIFO read status: Waiting for TxStatus from MAC transmitter */ +#define ETH_MAC_TXFIFO_WRITING 0x00300000U /* Tx FIFO read status: Writing the received TxStatus or flushing the TxFIFO */ +#define ETH_MAC_TRANSMISSION_PAUSE 0x00080000U /* MAC transmitter in pause */ +#define ETH_MAC_TRANSMITFRAMECONTROLLER_IDLE 0x00000000U /* MAC transmit frame controller: Idle */ +#define ETH_MAC_TRANSMITFRAMECONTROLLER_WAITING 0x00020000U /* MAC transmit frame controller: Waiting for Status of previous frame or IFG/backoff period to be over */ +#define ETH_MAC_TRANSMITFRAMECONTROLLER_GENRATING_PCF 0x00040000U /* MAC transmit frame controller: Generating and transmitting a Pause control frame (in full duplex mode) */ +#define ETH_MAC_TRANSMITFRAMECONTROLLER_TRANSFERRING 0x00060000U /* MAC transmit frame controller: Transferring input frame for transmission */ +#define ETH_MAC_MII_TRANSMIT_ACTIVE 0x00010000U /* MAC MII transmit engine active */ +#define ETH_MAC_RXFIFO_EMPTY 0x00000000U /* Rx FIFO fill level: empty */ +#define ETH_MAC_RXFIFO_BELOW_THRESHOLD 0x00000100U /* Rx FIFO fill level: fill-level below flow-control de-activate threshold */ +#define ETH_MAC_RXFIFO_ABOVE_THRESHOLD 0x00000200U /* Rx FIFO fill level: fill-level above flow-control activate threshold */ +#define ETH_MAC_RXFIFO_FULL 0x00000300U /* Rx FIFO fill level: full */ +#if defined(STM32F1) +#else +#define ETH_MAC_READCONTROLLER_IDLE 0x00000000U /* Rx FIFO read controller IDLE state */ +#define ETH_MAC_READCONTROLLER_READING_DATA 0x00000020U /* Rx FIFO read controller Reading frame data */ +#define ETH_MAC_READCONTROLLER_READING_STATUS 0x00000040U /* Rx FIFO read controller Reading frame status (or time-stamp) */ +#endif +#define ETH_MAC_READCONTROLLER_FLUSHING 0x00000060U /* Rx FIFO read controller Flushing the frame data and status */ +#define ETH_MAC_RXFIFO_WRITE_ACTIVE 0x00000010U /* Rx FIFO write controller active */ +#define ETH_MAC_SMALL_FIFO_NOTACTIVE 0x00000000U /* MAC small FIFO read / write controllers not active */ +#define ETH_MAC_SMALL_FIFO_READ_ACTIVE 0x00000002U /* MAC small FIFO read controller active */ +#define ETH_MAC_SMALL_FIFO_WRITE_ACTIVE 0x00000004U /* MAC small FIFO write controller active */ +#define ETH_MAC_SMALL_FIFO_RW_ACTIVE 0x00000006U /* MAC small FIFO read / write controllers active */ +#define ETH_MAC_MII_RECEIVE_PROTOCOL_ACTIVE 0x00000001U /* MAC MII receive protocol engine active */ + +/** + * @} + */ + +/** @defgroup HAL_DCMI_Aliased_Defines HAL DCMI Aliased Defines maintained for legacy purpose + * @{ + */ +#define HAL_DCMI_ERROR_OVF HAL_DCMI_ERROR_OVR +#define DCMI_IT_OVF DCMI_IT_OVR +#define DCMI_FLAG_OVFRI DCMI_FLAG_OVRRI +#define DCMI_FLAG_OVFMI DCMI_FLAG_OVRMI + +#define HAL_DCMI_ConfigCROP HAL_DCMI_ConfigCrop +#define HAL_DCMI_EnableCROP HAL_DCMI_EnableCrop +#define HAL_DCMI_DisableCROP HAL_DCMI_DisableCrop + +/** + * @} + */ + +#if defined(STM32L4) || defined(STM32F7) || defined(STM32F427xx) || defined(STM32F437xx) ||\ + defined(STM32F429xx) || defined(STM32F439xx) || defined(STM32F469xx) || defined(STM32F479xx) +/** @defgroup HAL_DMA2D_Aliased_Defines HAL DMA2D Aliased Defines maintained for legacy purpose + * @{ + */ +#define DMA2D_ARGB8888 DMA2D_OUTPUT_ARGB8888 +#define DMA2D_RGB888 DMA2D_OUTPUT_RGB888 +#define DMA2D_RGB565 DMA2D_OUTPUT_RGB565 +#define DMA2D_ARGB1555 DMA2D_OUTPUT_ARGB1555 +#define DMA2D_ARGB4444 DMA2D_OUTPUT_ARGB4444 + +#define CM_ARGB8888 DMA2D_INPUT_ARGB8888 +#define CM_RGB888 DMA2D_INPUT_RGB888 +#define CM_RGB565 DMA2D_INPUT_RGB565 +#define CM_ARGB1555 DMA2D_INPUT_ARGB1555 +#define CM_ARGB4444 DMA2D_INPUT_ARGB4444 +#define CM_L8 DMA2D_INPUT_L8 +#define CM_AL44 DMA2D_INPUT_AL44 +#define CM_AL88 DMA2D_INPUT_AL88 +#define CM_L4 DMA2D_INPUT_L4 +#define CM_A8 DMA2D_INPUT_A8 +#define CM_A4 DMA2D_INPUT_A4 +/** + * @} + */ +#endif /* STM32L4 || STM32F7*/ + +/** @defgroup HAL_PPP_Aliased_Defines HAL PPP Aliased Defines maintained for legacy purpose + * @{ + */ + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup HAL_CRYP_Aliased_Functions HAL CRYP Aliased Functions maintained for legacy purpose + * @{ + */ +#define HAL_CRYP_ComputationCpltCallback HAL_CRYPEx_ComputationCpltCallback +/** + * @} + */ + +/** @defgroup HAL_HASH_Aliased_Functions HAL HASH Aliased Functions maintained for legacy purpose + * @{ + */ +#define HAL_HASH_STATETypeDef HAL_HASH_StateTypeDef +#define HAL_HASHPhaseTypeDef HAL_HASH_PhaseTypeDef +#define HAL_HMAC_MD5_Finish HAL_HASH_MD5_Finish +#define HAL_HMAC_SHA1_Finish HAL_HASH_SHA1_Finish +#define HAL_HMAC_SHA224_Finish HAL_HASH_SHA224_Finish +#define HAL_HMAC_SHA256_Finish HAL_HASH_SHA256_Finish + +/*HASH Algorithm Selection*/ + +#define HASH_AlgoSelection_SHA1 HASH_ALGOSELECTION_SHA1 +#define HASH_AlgoSelection_SHA224 HASH_ALGOSELECTION_SHA224 +#define HASH_AlgoSelection_SHA256 HASH_ALGOSELECTION_SHA256 +#define HASH_AlgoSelection_MD5 HASH_ALGOSELECTION_MD5 + +#define HASH_AlgoMode_HASH HASH_ALGOMODE_HASH +#define HASH_AlgoMode_HMAC HASH_ALGOMODE_HMAC + +#define HASH_HMACKeyType_ShortKey HASH_HMAC_KEYTYPE_SHORTKEY +#define HASH_HMACKeyType_LongKey HASH_HMAC_KEYTYPE_LONGKEY +/** + * @} + */ + +/** @defgroup HAL_Aliased_Functions HAL Generic Aliased Functions maintained for legacy purpose + * @{ + */ +#define HAL_EnableDBGSleepMode HAL_DBGMCU_EnableDBGSleepMode +#define HAL_DisableDBGSleepMode HAL_DBGMCU_DisableDBGSleepMode +#define HAL_EnableDBGStopMode HAL_DBGMCU_EnableDBGStopMode +#define HAL_DisableDBGStopMode HAL_DBGMCU_DisableDBGStopMode +#define HAL_EnableDBGStandbyMode HAL_DBGMCU_EnableDBGStandbyMode +#define HAL_DisableDBGStandbyMode HAL_DBGMCU_DisableDBGStandbyMode +#define HAL_DBG_LowPowerConfig(Periph, cmd) (((cmd)==ENABLE)? HAL_DBGMCU_DBG_EnableLowPowerConfig(Periph) : HAL_DBGMCU_DBG_DisableLowPowerConfig(Periph)) +#define HAL_VREFINT_OutputSelect HAL_SYSCFG_VREFINT_OutputSelect +#define HAL_Lock_Cmd(cmd) (((cmd)==ENABLE) ? HAL_SYSCFG_Enable_Lock_VREFINT() : HAL_SYSCFG_Disable_Lock_VREFINT()) +#if defined(STM32L0) +#else +#define HAL_VREFINT_Cmd(cmd) (((cmd)==ENABLE)? HAL_SYSCFG_EnableVREFINT() : HAL_SYSCFG_DisableVREFINT()) +#endif +#define HAL_ADC_EnableBuffer_Cmd(cmd) (((cmd)==ENABLE) ? HAL_ADCEx_EnableVREFINT() : HAL_ADCEx_DisableVREFINT()) +#define HAL_ADC_EnableBufferSensor_Cmd(cmd) (((cmd)==ENABLE) ? HAL_ADCEx_EnableVREFINTTempSensor() : HAL_ADCEx_DisableVREFINTTempSensor()) +/** + * @} + */ + +/** @defgroup HAL_FLASH_Aliased_Functions HAL FLASH Aliased Functions maintained for legacy purpose + * @{ + */ +#define FLASH_HalfPageProgram HAL_FLASHEx_HalfPageProgram +#define FLASH_EnableRunPowerDown HAL_FLASHEx_EnableRunPowerDown +#define FLASH_DisableRunPowerDown HAL_FLASHEx_DisableRunPowerDown +#define HAL_DATA_EEPROMEx_Unlock HAL_FLASHEx_DATAEEPROM_Unlock +#define HAL_DATA_EEPROMEx_Lock HAL_FLASHEx_DATAEEPROM_Lock +#define HAL_DATA_EEPROMEx_Erase HAL_FLASHEx_DATAEEPROM_Erase +#define HAL_DATA_EEPROMEx_Program HAL_FLASHEx_DATAEEPROM_Program + + /** + * @} + */ + +/** @defgroup HAL_I2C_Aliased_Functions HAL I2C Aliased Functions maintained for legacy purpose + * @{ + */ +#define HAL_I2CEx_AnalogFilter_Config HAL_I2CEx_ConfigAnalogFilter +#define HAL_I2CEx_DigitalFilter_Config HAL_I2CEx_ConfigDigitalFilter +#define HAL_FMPI2CEx_AnalogFilter_Config HAL_FMPI2CEx_ConfigAnalogFilter +#define HAL_FMPI2CEx_DigitalFilter_Config HAL_FMPI2CEx_ConfigDigitalFilter + +#define HAL_I2CFastModePlusConfig(SYSCFG_I2CFastModePlus, cmd) (((cmd)==ENABLE)? HAL_I2CEx_EnableFastModePlus(SYSCFG_I2CFastModePlus): HAL_I2CEx_DisableFastModePlus(SYSCFG_I2CFastModePlus)) + /** + * @} + */ + +/** @defgroup HAL_PWR_Aliased HAL PWR Aliased maintained for legacy purpose + * @{ + */ +#define HAL_PWR_PVDConfig HAL_PWR_ConfigPVD +#define HAL_PWR_DisableBkUpReg HAL_PWREx_DisableBkUpReg +#define HAL_PWR_DisableFlashPowerDown HAL_PWREx_DisableFlashPowerDown +#define HAL_PWR_DisableVddio2Monitor HAL_PWREx_DisableVddio2Monitor +#define HAL_PWR_EnableBkUpReg HAL_PWREx_EnableBkUpReg +#define HAL_PWR_EnableFlashPowerDown HAL_PWREx_EnableFlashPowerDown +#define HAL_PWR_EnableVddio2Monitor HAL_PWREx_EnableVddio2Monitor +#define HAL_PWR_PVD_PVM_IRQHandler HAL_PWREx_PVD_PVM_IRQHandler +#define HAL_PWR_PVDLevelConfig HAL_PWR_ConfigPVD +#define HAL_PWR_Vddio2Monitor_IRQHandler HAL_PWREx_Vddio2Monitor_IRQHandler +#define HAL_PWR_Vddio2MonitorCallback HAL_PWREx_Vddio2MonitorCallback +#define HAL_PWREx_ActivateOverDrive HAL_PWREx_EnableOverDrive +#define HAL_PWREx_DeactivateOverDrive HAL_PWREx_DisableOverDrive +#define HAL_PWREx_DisableSDADCAnalog HAL_PWREx_DisableSDADC +#define HAL_PWREx_EnableSDADCAnalog HAL_PWREx_EnableSDADC +#define HAL_PWREx_PVMConfig HAL_PWREx_ConfigPVM + +#define PWR_MODE_NORMAL PWR_PVD_MODE_NORMAL +#define PWR_MODE_IT_RISING PWR_PVD_MODE_IT_RISING +#define PWR_MODE_IT_FALLING PWR_PVD_MODE_IT_FALLING +#define PWR_MODE_IT_RISING_FALLING PWR_PVD_MODE_IT_RISING_FALLING +#define PWR_MODE_EVENT_RISING PWR_PVD_MODE_EVENT_RISING +#define PWR_MODE_EVENT_FALLING PWR_PVD_MODE_EVENT_FALLING +#define PWR_MODE_EVENT_RISING_FALLING PWR_PVD_MODE_EVENT_RISING_FALLING + +#define CR_OFFSET_BB PWR_CR_OFFSET_BB +#define CSR_OFFSET_BB PWR_CSR_OFFSET_BB +#define PMODE_BIT_NUMBER VOS_BIT_NUMBER +#define CR_PMODE_BB CR_VOS_BB + +#define DBP_BitNumber DBP_BIT_NUMBER +#define PVDE_BitNumber PVDE_BIT_NUMBER +#define PMODE_BitNumber PMODE_BIT_NUMBER +#define EWUP_BitNumber EWUP_BIT_NUMBER +#define FPDS_BitNumber FPDS_BIT_NUMBER +#define ODEN_BitNumber ODEN_BIT_NUMBER +#define ODSWEN_BitNumber ODSWEN_BIT_NUMBER +#define MRLVDS_BitNumber MRLVDS_BIT_NUMBER +#define LPLVDS_BitNumber LPLVDS_BIT_NUMBER +#define BRE_BitNumber BRE_BIT_NUMBER + +#define PWR_MODE_EVT PWR_PVD_MODE_NORMAL + + /** + * @} + */ + +/** @defgroup HAL_SMBUS_Aliased_Functions HAL SMBUS Aliased Functions maintained for legacy purpose + * @{ + */ +#define HAL_SMBUS_Slave_Listen_IT HAL_SMBUS_EnableListen_IT +#define HAL_SMBUS_SlaveAddrCallback HAL_SMBUS_AddrCallback +#define HAL_SMBUS_SlaveListenCpltCallback HAL_SMBUS_ListenCpltCallback +/** + * @} + */ + +/** @defgroup HAL_SPI_Aliased_Functions HAL SPI Aliased Functions maintained for legacy purpose + * @{ + */ +#define HAL_SPI_FlushRxFifo HAL_SPIEx_FlushRxFifo +/** + * @} + */ + +/** @defgroup HAL_TIM_Aliased_Functions HAL TIM Aliased Functions maintained for legacy purpose + * @{ + */ +#define HAL_TIM_DMADelayPulseCplt TIM_DMADelayPulseCplt +#define HAL_TIM_DMAError TIM_DMAError +#define HAL_TIM_DMACaptureCplt TIM_DMACaptureCplt +#define HAL_TIMEx_DMACommutationCplt TIMEx_DMACommutationCplt +/** + * @} + */ + +/** @defgroup HAL_UART_Aliased_Functions HAL UART Aliased Functions maintained for legacy purpose + * @{ + */ +#define HAL_UART_WakeupCallback HAL_UARTEx_WakeupCallback +/** + * @} + */ + +/** @defgroup HAL_LTDC_Aliased_Functions HAL LTDC Aliased Functions maintained for legacy purpose + * @{ + */ +#define HAL_LTDC_LineEvenCallback HAL_LTDC_LineEventCallback +#define HAL_LTDC_Relaod HAL_LTDC_Reload +#define HAL_LTDC_StructInitFromVideoConfig HAL_LTDCEx_StructInitFromVideoConfig +#define HAL_LTDC_StructInitFromAdaptedCommandConfig HAL_LTDCEx_StructInitFromAdaptedCommandConfig +/** + * @} + */ + + +/** @defgroup HAL_PPP_Aliased_Functions HAL PPP Aliased Functions maintained for legacy purpose + * @{ + */ + +/** + * @} + */ + +/* Exported macros ------------------------------------------------------------*/ + +/** @defgroup HAL_AES_Aliased_Macros HAL CRYP Aliased Macros maintained for legacy purpose + * @{ + */ +#define AES_IT_CC CRYP_IT_CC +#define AES_IT_ERR CRYP_IT_ERR +#define AES_FLAG_CCF CRYP_FLAG_CCF +/** + * @} + */ + +/** @defgroup HAL_Aliased_Macros HAL Generic Aliased Macros maintained for legacy purpose + * @{ + */ +#define __HAL_GET_BOOT_MODE __HAL_SYSCFG_GET_BOOT_MODE +#define __HAL_REMAPMEMORY_FLASH __HAL_SYSCFG_REMAPMEMORY_FLASH +#define __HAL_REMAPMEMORY_SYSTEMFLASH __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH +#define __HAL_REMAPMEMORY_SRAM __HAL_SYSCFG_REMAPMEMORY_SRAM +#define __HAL_REMAPMEMORY_FMC __HAL_SYSCFG_REMAPMEMORY_FMC +#define __HAL_REMAPMEMORY_FMC_SDRAM __HAL_SYSCFG_REMAPMEMORY_FMC_SDRAM +#define __HAL_REMAPMEMORY_FSMC __HAL_SYSCFG_REMAPMEMORY_FSMC +#define __HAL_REMAPMEMORY_QUADSPI __HAL_SYSCFG_REMAPMEMORY_QUADSPI +#define __HAL_FMC_BANK __HAL_SYSCFG_FMC_BANK +#define __HAL_GET_FLAG __HAL_SYSCFG_GET_FLAG +#define __HAL_CLEAR_FLAG __HAL_SYSCFG_CLEAR_FLAG +#define __HAL_VREFINT_OUT_ENABLE __HAL_SYSCFG_VREFINT_OUT_ENABLE +#define __HAL_VREFINT_OUT_DISABLE __HAL_SYSCFG_VREFINT_OUT_DISABLE +#define __HAL_SYSCFG_SRAM2_WRP_ENABLE __HAL_SYSCFG_SRAM2_WRP_0_31_ENABLE + +#define SYSCFG_FLAG_VREF_READY SYSCFG_FLAG_VREFINT_READY +#define SYSCFG_FLAG_RC48 RCC_FLAG_HSI48 +#define IS_SYSCFG_FASTMODEPLUS_CONFIG IS_I2C_FASTMODEPLUS +#define UFB_MODE_BitNumber UFB_MODE_BIT_NUMBER +#define CMP_PD_BitNumber CMP_PD_BIT_NUMBER + +/** + * @} + */ + + +/** @defgroup HAL_ADC_Aliased_Macros HAL ADC Aliased Macros maintained for legacy purpose + * @{ + */ +#define __ADC_ENABLE __HAL_ADC_ENABLE +#define __ADC_DISABLE __HAL_ADC_DISABLE +#define __HAL_ADC_ENABLING_CONDITIONS ADC_ENABLING_CONDITIONS +#define __HAL_ADC_DISABLING_CONDITIONS ADC_DISABLING_CONDITIONS +#define __HAL_ADC_IS_ENABLED ADC_IS_ENABLE +#define __ADC_IS_ENABLED ADC_IS_ENABLE +#define __HAL_ADC_IS_SOFTWARE_START_REGULAR ADC_IS_SOFTWARE_START_REGULAR +#define __HAL_ADC_IS_SOFTWARE_START_INJECTED ADC_IS_SOFTWARE_START_INJECTED +#define __HAL_ADC_IS_CONVERSION_ONGOING_REGULAR_INJECTED ADC_IS_CONVERSION_ONGOING_REGULAR_INJECTED +#define __HAL_ADC_IS_CONVERSION_ONGOING_REGULAR ADC_IS_CONVERSION_ONGOING_REGULAR +#define __HAL_ADC_IS_CONVERSION_ONGOING_INJECTED ADC_IS_CONVERSION_ONGOING_INJECTED +#define __HAL_ADC_IS_CONVERSION_ONGOING ADC_IS_CONVERSION_ONGOING +#define __HAL_ADC_CLEAR_ERRORCODE ADC_CLEAR_ERRORCODE + +#define __HAL_ADC_GET_RESOLUTION ADC_GET_RESOLUTION +#define __HAL_ADC_JSQR_RK ADC_JSQR_RK +#define __HAL_ADC_CFGR_AWD1CH ADC_CFGR_AWD1CH_SHIFT +#define __HAL_ADC_CFGR_AWD23CR ADC_CFGR_AWD23CR +#define __HAL_ADC_CFGR_INJECT_AUTO_CONVERSION ADC_CFGR_INJECT_AUTO_CONVERSION +#define __HAL_ADC_CFGR_INJECT_CONTEXT_QUEUE ADC_CFGR_INJECT_CONTEXT_QUEUE +#define __HAL_ADC_CFGR_INJECT_DISCCONTINUOUS ADC_CFGR_INJECT_DISCCONTINUOUS +#define __HAL_ADC_CFGR_REG_DISCCONTINUOUS ADC_CFGR_REG_DISCCONTINUOUS +#define __HAL_ADC_CFGR_DISCONTINUOUS_NUM ADC_CFGR_DISCONTINUOUS_NUM +#define __HAL_ADC_CFGR_AUTOWAIT ADC_CFGR_AUTOWAIT +#define __HAL_ADC_CFGR_CONTINUOUS ADC_CFGR_CONTINUOUS +#define __HAL_ADC_CFGR_OVERRUN ADC_CFGR_OVERRUN +#define __HAL_ADC_CFGR_DMACONTREQ ADC_CFGR_DMACONTREQ +#define __HAL_ADC_CFGR_EXTSEL ADC_CFGR_EXTSEL_SET +#define __HAL_ADC_JSQR_JEXTSEL ADC_JSQR_JEXTSEL_SET +#define __HAL_ADC_OFR_CHANNEL ADC_OFR_CHANNEL +#define __HAL_ADC_DIFSEL_CHANNEL ADC_DIFSEL_CHANNEL +#define __HAL_ADC_CALFACT_DIFF_SET ADC_CALFACT_DIFF_SET +#define __HAL_ADC_CALFACT_DIFF_GET ADC_CALFACT_DIFF_GET +#define __HAL_ADC_TRX_HIGHTHRESHOLD ADC_TRX_HIGHTHRESHOLD + +#define __HAL_ADC_OFFSET_SHIFT_RESOLUTION ADC_OFFSET_SHIFT_RESOLUTION +#define __HAL_ADC_AWD1THRESHOLD_SHIFT_RESOLUTION ADC_AWD1THRESHOLD_SHIFT_RESOLUTION +#define __HAL_ADC_AWD23THRESHOLD_SHIFT_RESOLUTION ADC_AWD23THRESHOLD_SHIFT_RESOLUTION +#define __HAL_ADC_COMMON_REGISTER ADC_COMMON_REGISTER +#define __HAL_ADC_COMMON_CCR_MULTI ADC_COMMON_CCR_MULTI +#define __HAL_ADC_MULTIMODE_IS_ENABLED ADC_MULTIMODE_IS_ENABLE +#define __ADC_MULTIMODE_IS_ENABLED ADC_MULTIMODE_IS_ENABLE +#define __HAL_ADC_NONMULTIMODE_OR_MULTIMODEMASTER ADC_NONMULTIMODE_OR_MULTIMODEMASTER +#define __HAL_ADC_COMMON_ADC_OTHER ADC_COMMON_ADC_OTHER +#define __HAL_ADC_MULTI_SLAVE ADC_MULTI_SLAVE + +#define __HAL_ADC_SQR1_L ADC_SQR1_L_SHIFT +#define __HAL_ADC_JSQR_JL ADC_JSQR_JL_SHIFT +#define __HAL_ADC_JSQR_RK_JL ADC_JSQR_RK_JL +#define __HAL_ADC_CR1_DISCONTINUOUS_NUM ADC_CR1_DISCONTINUOUS_NUM +#define __HAL_ADC_CR1_SCAN ADC_CR1_SCAN_SET +#define __HAL_ADC_CONVCYCLES_MAX_RANGE ADC_CONVCYCLES_MAX_RANGE +#define __HAL_ADC_CLOCK_PRESCALER_RANGE ADC_CLOCK_PRESCALER_RANGE +#define __HAL_ADC_GET_CLOCK_PRESCALER ADC_GET_CLOCK_PRESCALER + +#define __HAL_ADC_SQR1 ADC_SQR1 +#define __HAL_ADC_SMPR1 ADC_SMPR1 +#define __HAL_ADC_SMPR2 ADC_SMPR2 +#define __HAL_ADC_SQR3_RK ADC_SQR3_RK +#define __HAL_ADC_SQR2_RK ADC_SQR2_RK +#define __HAL_ADC_SQR1_RK ADC_SQR1_RK +#define __HAL_ADC_CR2_CONTINUOUS ADC_CR2_CONTINUOUS +#define __HAL_ADC_CR1_DISCONTINUOUS ADC_CR1_DISCONTINUOUS +#define __HAL_ADC_CR1_SCANCONV ADC_CR1_SCANCONV +#define __HAL_ADC_CR2_EOCSelection ADC_CR2_EOCSelection +#define __HAL_ADC_CR2_DMAContReq ADC_CR2_DMAContReq +#define __HAL_ADC_JSQR ADC_JSQR + +#define __HAL_ADC_CHSELR_CHANNEL ADC_CHSELR_CHANNEL +#define __HAL_ADC_CFGR1_REG_DISCCONTINUOUS ADC_CFGR1_REG_DISCCONTINUOUS +#define __HAL_ADC_CFGR1_AUTOOFF ADC_CFGR1_AUTOOFF +#define __HAL_ADC_CFGR1_AUTOWAIT ADC_CFGR1_AUTOWAIT +#define __HAL_ADC_CFGR1_CONTINUOUS ADC_CFGR1_CONTINUOUS +#define __HAL_ADC_CFGR1_OVERRUN ADC_CFGR1_OVERRUN +#define __HAL_ADC_CFGR1_SCANDIR ADC_CFGR1_SCANDIR +#define __HAL_ADC_CFGR1_DMACONTREQ ADC_CFGR1_DMACONTREQ + +/** + * @} + */ + +/** @defgroup HAL_DAC_Aliased_Macros HAL DAC Aliased Macros maintained for legacy purpose + * @{ + */ +#define __HAL_DHR12R1_ALIGNEMENT DAC_DHR12R1_ALIGNMENT +#define __HAL_DHR12R2_ALIGNEMENT DAC_DHR12R2_ALIGNMENT +#define __HAL_DHR12RD_ALIGNEMENT DAC_DHR12RD_ALIGNMENT +#define IS_DAC_GENERATE_WAVE IS_DAC_WAVE + +/** + * @} + */ + +/** @defgroup HAL_DBGMCU_Aliased_Macros HAL DBGMCU Aliased Macros maintained for legacy purpose + * @{ + */ +#define __HAL_FREEZE_TIM1_DBGMCU __HAL_DBGMCU_FREEZE_TIM1 +#define __HAL_UNFREEZE_TIM1_DBGMCU __HAL_DBGMCU_UNFREEZE_TIM1 +#define __HAL_FREEZE_TIM2_DBGMCU __HAL_DBGMCU_FREEZE_TIM2 +#define __HAL_UNFREEZE_TIM2_DBGMCU __HAL_DBGMCU_UNFREEZE_TIM2 +#define __HAL_FREEZE_TIM3_DBGMCU __HAL_DBGMCU_FREEZE_TIM3 +#define __HAL_UNFREEZE_TIM3_DBGMCU __HAL_DBGMCU_UNFREEZE_TIM3 +#define __HAL_FREEZE_TIM4_DBGMCU __HAL_DBGMCU_FREEZE_TIM4 +#define __HAL_UNFREEZE_TIM4_DBGMCU __HAL_DBGMCU_UNFREEZE_TIM4 +#define __HAL_FREEZE_TIM5_DBGMCU __HAL_DBGMCU_FREEZE_TIM5 +#define __HAL_UNFREEZE_TIM5_DBGMCU __HAL_DBGMCU_UNFREEZE_TIM5 +#define __HAL_FREEZE_TIM6_DBGMCU __HAL_DBGMCU_FREEZE_TIM6 +#define __HAL_UNFREEZE_TIM6_DBGMCU __HAL_DBGMCU_UNFREEZE_TIM6 +#define __HAL_FREEZE_TIM7_DBGMCU __HAL_DBGMCU_FREEZE_TIM7 +#define __HAL_UNFREEZE_TIM7_DBGMCU __HAL_DBGMCU_UNFREEZE_TIM7 +#define __HAL_FREEZE_TIM8_DBGMCU __HAL_DBGMCU_FREEZE_TIM8 +#define __HAL_UNFREEZE_TIM8_DBGMCU __HAL_DBGMCU_UNFREEZE_TIM8 + +#define __HAL_FREEZE_TIM9_DBGMCU __HAL_DBGMCU_FREEZE_TIM9 +#define __HAL_UNFREEZE_TIM9_DBGMCU __HAL_DBGMCU_UNFREEZE_TIM9 +#define __HAL_FREEZE_TIM10_DBGMCU __HAL_DBGMCU_FREEZE_TIM10 +#define __HAL_UNFREEZE_TIM10_DBGMCU __HAL_DBGMCU_UNFREEZE_TIM10 +#define __HAL_FREEZE_TIM11_DBGMCU __HAL_DBGMCU_FREEZE_TIM11 +#define __HAL_UNFREEZE_TIM11_DBGMCU __HAL_DBGMCU_UNFREEZE_TIM11 +#define __HAL_FREEZE_TIM12_DBGMCU __HAL_DBGMCU_FREEZE_TIM12 +#define __HAL_UNFREEZE_TIM12_DBGMCU __HAL_DBGMCU_UNFREEZE_TIM12 +#define __HAL_FREEZE_TIM13_DBGMCU __HAL_DBGMCU_FREEZE_TIM13 +#define __HAL_UNFREEZE_TIM13_DBGMCU __HAL_DBGMCU_UNFREEZE_TIM13 +#define __HAL_FREEZE_TIM14_DBGMCU __HAL_DBGMCU_FREEZE_TIM14 +#define __HAL_UNFREEZE_TIM14_DBGMCU __HAL_DBGMCU_UNFREEZE_TIM14 +#define __HAL_FREEZE_CAN2_DBGMCU __HAL_DBGMCU_FREEZE_CAN2 +#define __HAL_UNFREEZE_CAN2_DBGMCU __HAL_DBGMCU_UNFREEZE_CAN2 + + +#define __HAL_FREEZE_TIM15_DBGMCU __HAL_DBGMCU_FREEZE_TIM15 +#define __HAL_UNFREEZE_TIM15_DBGMCU __HAL_DBGMCU_UNFREEZE_TIM15 +#define __HAL_FREEZE_TIM16_DBGMCU __HAL_DBGMCU_FREEZE_TIM16 +#define __HAL_UNFREEZE_TIM16_DBGMCU __HAL_DBGMCU_UNFREEZE_TIM16 +#define __HAL_FREEZE_TIM17_DBGMCU __HAL_DBGMCU_FREEZE_TIM17 +#define __HAL_UNFREEZE_TIM17_DBGMCU __HAL_DBGMCU_UNFREEZE_TIM17 +#define __HAL_FREEZE_RTC_DBGMCU __HAL_DBGMCU_FREEZE_RTC +#define __HAL_UNFREEZE_RTC_DBGMCU __HAL_DBGMCU_UNFREEZE_RTC +#define __HAL_FREEZE_WWDG_DBGMCU __HAL_DBGMCU_FREEZE_WWDG +#define __HAL_UNFREEZE_WWDG_DBGMCU __HAL_DBGMCU_UNFREEZE_WWDG +#define __HAL_FREEZE_IWDG_DBGMCU __HAL_DBGMCU_FREEZE_IWDG +#define __HAL_UNFREEZE_IWDG_DBGMCU __HAL_DBGMCU_UNFREEZE_IWDG +#define __HAL_FREEZE_I2C1_TIMEOUT_DBGMCU __HAL_DBGMCU_FREEZE_I2C1_TIMEOUT +#define __HAL_UNFREEZE_I2C1_TIMEOUT_DBGMCU __HAL_DBGMCU_UNFREEZE_I2C1_TIMEOUT +#define __HAL_FREEZE_I2C2_TIMEOUT_DBGMCU __HAL_DBGMCU_FREEZE_I2C2_TIMEOUT +#define __HAL_UNFREEZE_I2C2_TIMEOUT_DBGMCU __HAL_DBGMCU_UNFREEZE_I2C2_TIMEOUT +#define __HAL_FREEZE_I2C3_TIMEOUT_DBGMCU __HAL_DBGMCU_FREEZE_I2C3_TIMEOUT +#define __HAL_UNFREEZE_I2C3_TIMEOUT_DBGMCU __HAL_DBGMCU_UNFREEZE_I2C3_TIMEOUT +#define __HAL_FREEZE_CAN1_DBGMCU __HAL_DBGMCU_FREEZE_CAN1 +#define __HAL_UNFREEZE_CAN1_DBGMCU __HAL_DBGMCU_UNFREEZE_CAN1 +#define __HAL_FREEZE_LPTIM1_DBGMCU __HAL_DBGMCU_FREEZE_LPTIM1 +#define __HAL_UNFREEZE_LPTIM1_DBGMCU __HAL_DBGMCU_UNFREEZE_LPTIM1 +#define __HAL_FREEZE_LPTIM2_DBGMCU __HAL_DBGMCU_FREEZE_LPTIM2 +#define __HAL_UNFREEZE_LPTIM2_DBGMCU __HAL_DBGMCU_UNFREEZE_LPTIM2 + +/** + * @} + */ + +/** @defgroup HAL_COMP_Aliased_Macros HAL COMP Aliased Macros maintained for legacy purpose + * @{ + */ +#if defined(STM32F3) +#define COMP_START __HAL_COMP_ENABLE +#define COMP_STOP __HAL_COMP_DISABLE +#define COMP_LOCK __HAL_COMP_LOCK + +#if defined(STM32F301x8) || defined(STM32F302x8) || defined(STM32F318xx) || defined(STM32F303x8) || defined(STM32F334x8) || defined(STM32F328xx) +#define __HAL_COMP_EXTI_RISING_IT_ENABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_ENABLE_RISING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_ENABLE_RISING_EDGE() : \ + __HAL_COMP_COMP6_EXTI_ENABLE_RISING_EDGE()) +#define __HAL_COMP_EXTI_RISING_IT_DISABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_DISABLE_RISING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_DISABLE_RISING_EDGE() : \ + __HAL_COMP_COMP6_EXTI_DISABLE_RISING_EDGE()) +#define __HAL_COMP_EXTI_FALLING_IT_ENABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_ENABLE_FALLING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_ENABLE_FALLING_EDGE() : \ + __HAL_COMP_COMP6_EXTI_ENABLE_FALLING_EDGE()) +#define __HAL_COMP_EXTI_FALLING_IT_DISABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_DISABLE_FALLING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_DISABLE_FALLING_EDGE() : \ + __HAL_COMP_COMP6_EXTI_DISABLE_FALLING_EDGE()) +#define __HAL_COMP_EXTI_ENABLE_IT(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_ENABLE_IT() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_ENABLE_IT() : \ + __HAL_COMP_COMP6_EXTI_ENABLE_IT()) +#define __HAL_COMP_EXTI_DISABLE_IT(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_DISABLE_IT() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_DISABLE_IT() : \ + __HAL_COMP_COMP6_EXTI_DISABLE_IT()) +#define __HAL_COMP_EXTI_GET_FLAG(__FLAG__) (((__FLAG__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_GET_FLAG() : \ + ((__FLAG__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_GET_FLAG() : \ + __HAL_COMP_COMP6_EXTI_GET_FLAG()) +#define __HAL_COMP_EXTI_CLEAR_FLAG(__FLAG__) (((__FLAG__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_CLEAR_FLAG() : \ + ((__FLAG__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_CLEAR_FLAG() : \ + __HAL_COMP_COMP6_EXTI_CLEAR_FLAG()) +# endif +# if defined(STM32F302xE) || defined(STM32F302xC) +#define __HAL_COMP_EXTI_RISING_IT_ENABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_ENABLE_RISING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_ENABLE_RISING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_ENABLE_RISING_EDGE() : \ + __HAL_COMP_COMP6_EXTI_ENABLE_RISING_EDGE()) +#define __HAL_COMP_EXTI_RISING_IT_DISABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_DISABLE_RISING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_DISABLE_RISING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_DISABLE_RISING_EDGE() : \ + __HAL_COMP_COMP6_EXTI_DISABLE_RISING_EDGE()) +#define __HAL_COMP_EXTI_FALLING_IT_ENABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_ENABLE_FALLING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_ENABLE_FALLING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_ENABLE_FALLING_EDGE() : \ + __HAL_COMP_COMP6_EXTI_ENABLE_FALLING_EDGE()) +#define __HAL_COMP_EXTI_FALLING_IT_DISABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_DISABLE_FALLING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_DISABLE_FALLING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_DISABLE_FALLING_EDGE() : \ + __HAL_COMP_COMP6_EXTI_DISABLE_FALLING_EDGE()) +#define __HAL_COMP_EXTI_ENABLE_IT(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_ENABLE_IT() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_ENABLE_IT() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_ENABLE_IT() : \ + __HAL_COMP_COMP6_EXTI_ENABLE_IT()) +#define __HAL_COMP_EXTI_DISABLE_IT(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_DISABLE_IT() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_DISABLE_IT() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_DISABLE_IT() : \ + __HAL_COMP_COMP6_EXTI_DISABLE_IT()) +#define __HAL_COMP_EXTI_GET_FLAG(__FLAG__) (((__FLAG__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_GET_FLAG() : \ + ((__FLAG__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_GET_FLAG() : \ + ((__FLAG__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_GET_FLAG() : \ + __HAL_COMP_COMP6_EXTI_GET_FLAG()) +#define __HAL_COMP_EXTI_CLEAR_FLAG(__FLAG__) (((__FLAG__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_CLEAR_FLAG() : \ + ((__FLAG__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_CLEAR_FLAG() : \ + ((__FLAG__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_CLEAR_FLAG() : \ + __HAL_COMP_COMP6_EXTI_CLEAR_FLAG()) +# endif +# if defined(STM32F303xE) || defined(STM32F398xx) || defined(STM32F303xC) || defined(STM32F358xx) +#define __HAL_COMP_EXTI_RISING_IT_ENABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_ENABLE_RISING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_ENABLE_RISING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP3) ? __HAL_COMP_COMP3_EXTI_ENABLE_RISING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_ENABLE_RISING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP5) ? __HAL_COMP_COMP5_EXTI_ENABLE_RISING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP6) ? __HAL_COMP_COMP6_EXTI_ENABLE_RISING_EDGE() : \ + __HAL_COMP_COMP7_EXTI_ENABLE_RISING_EDGE()) +#define __HAL_COMP_EXTI_RISING_IT_DISABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_DISABLE_RISING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_DISABLE_RISING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP3) ? __HAL_COMP_COMP3_EXTI_DISABLE_RISING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_DISABLE_RISING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP5) ? __HAL_COMP_COMP5_EXTI_DISABLE_RISING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP6) ? __HAL_COMP_COMP6_EXTI_DISABLE_RISING_EDGE() : \ + __HAL_COMP_COMP7_EXTI_DISABLE_RISING_EDGE()) +#define __HAL_COMP_EXTI_FALLING_IT_ENABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_ENABLE_FALLING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_ENABLE_FALLING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP3) ? __HAL_COMP_COMP3_EXTI_ENABLE_FALLING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_ENABLE_FALLING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP5) ? __HAL_COMP_COMP5_EXTI_ENABLE_FALLING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP6) ? __HAL_COMP_COMP6_EXTI_ENABLE_FALLING_EDGE() : \ + __HAL_COMP_COMP7_EXTI_ENABLE_FALLING_EDGE()) +#define __HAL_COMP_EXTI_FALLING_IT_DISABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_DISABLE_FALLING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_DISABLE_FALLING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP3) ? __HAL_COMP_COMP3_EXTI_DISABLE_FALLING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_DISABLE_FALLING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP5) ? __HAL_COMP_COMP5_EXTI_DISABLE_FALLING_EDGE() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP6) ? __HAL_COMP_COMP6_EXTI_DISABLE_FALLING_EDGE() : \ + __HAL_COMP_COMP7_EXTI_DISABLE_FALLING_EDGE()) +#define __HAL_COMP_EXTI_ENABLE_IT(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_ENABLE_IT() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_ENABLE_IT() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP3) ? __HAL_COMP_COMP3_EXTI_ENABLE_IT() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_ENABLE_IT() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP5) ? __HAL_COMP_COMP5_EXTI_ENABLE_IT() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP6) ? __HAL_COMP_COMP6_EXTI_ENABLE_IT() : \ + __HAL_COMP_COMP7_EXTI_ENABLE_IT()) +#define __HAL_COMP_EXTI_DISABLE_IT(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_DISABLE_IT() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_DISABLE_IT() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP3) ? __HAL_COMP_COMP3_EXTI_DISABLE_IT() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_DISABLE_IT() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP5) ? __HAL_COMP_COMP5_EXTI_DISABLE_IT() : \ + ((__EXTILINE__) == COMP_EXTI_LINE_COMP6) ? __HAL_COMP_COMP6_EXTI_DISABLE_IT() : \ + __HAL_COMP_COMP7_EXTI_DISABLE_IT()) +#define __HAL_COMP_EXTI_GET_FLAG(__FLAG__) (((__FLAG__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_GET_FLAG() : \ + ((__FLAG__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_GET_FLAG() : \ + ((__FLAG__) == COMP_EXTI_LINE_COMP3) ? __HAL_COMP_COMP3_EXTI_GET_FLAG() : \ + ((__FLAG__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_GET_FLAG() : \ + ((__FLAG__) == COMP_EXTI_LINE_COMP5) ? __HAL_COMP_COMP5_EXTI_GET_FLAG() : \ + ((__FLAG__) == COMP_EXTI_LINE_COMP6) ? __HAL_COMP_COMP6_EXTI_GET_FLAG() : \ + __HAL_COMP_COMP7_EXTI_GET_FLAG()) +#define __HAL_COMP_EXTI_CLEAR_FLAG(__FLAG__) (((__FLAG__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_CLEAR_FLAG() : \ + ((__FLAG__) == COMP_EXTI_LINE_COMP2) ? __HAL_COMP_COMP2_EXTI_CLEAR_FLAG() : \ + ((__FLAG__) == COMP_EXTI_LINE_COMP3) ? __HAL_COMP_COMP3_EXTI_CLEAR_FLAG() : \ + ((__FLAG__) == COMP_EXTI_LINE_COMP4) ? __HAL_COMP_COMP4_EXTI_CLEAR_FLAG() : \ + ((__FLAG__) == COMP_EXTI_LINE_COMP5) ? __HAL_COMP_COMP5_EXTI_CLEAR_FLAG() : \ + ((__FLAG__) == COMP_EXTI_LINE_COMP6) ? __HAL_COMP_COMP6_EXTI_CLEAR_FLAG() : \ + __HAL_COMP_COMP7_EXTI_CLEAR_FLAG()) +# endif +# if defined(STM32F373xC) ||defined(STM32F378xx) +#define __HAL_COMP_EXTI_RISING_IT_ENABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_ENABLE_RISING_EDGE() : \ + __HAL_COMP_COMP2_EXTI_ENABLE_RISING_EDGE()) +#define __HAL_COMP_EXTI_RISING_IT_DISABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_DISABLE_RISING_EDGE() : \ + __HAL_COMP_COMP2_EXTI_DISABLE_RISING_EDGE()) +#define __HAL_COMP_EXTI_FALLING_IT_ENABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_ENABLE_FALLING_EDGE() : \ + __HAL_COMP_COMP2_EXTI_ENABLE_FALLING_EDGE()) +#define __HAL_COMP_EXTI_FALLING_IT_DISABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_DISABLE_FALLING_EDGE() : \ + __HAL_COMP_COMP2_EXTI_DISABLE_FALLING_EDGE()) +#define __HAL_COMP_EXTI_ENABLE_IT(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_ENABLE_IT() : \ + __HAL_COMP_COMP2_EXTI_ENABLE_IT()) +#define __HAL_COMP_EXTI_DISABLE_IT(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_DISABLE_IT() : \ + __HAL_COMP_COMP2_EXTI_DISABLE_IT()) +#define __HAL_COMP_EXTI_GET_FLAG(__FLAG__) (((__FLAG__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_GET_FLAG() : \ + __HAL_COMP_COMP2_EXTI_GET_FLAG()) +#define __HAL_COMP_EXTI_CLEAR_FLAG(__FLAG__) (((__FLAG__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_CLEAR_FLAG() : \ + __HAL_COMP_COMP2_EXTI_CLEAR_FLAG()) +# endif +#else +#define __HAL_COMP_EXTI_RISING_IT_ENABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_ENABLE_RISING_EDGE() : \ + __HAL_COMP_COMP2_EXTI_ENABLE_RISING_EDGE()) +#define __HAL_COMP_EXTI_RISING_IT_DISABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_DISABLE_RISING_EDGE() : \ + __HAL_COMP_COMP2_EXTI_DISABLE_RISING_EDGE()) +#define __HAL_COMP_EXTI_FALLING_IT_ENABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_ENABLE_FALLING_EDGE() : \ + __HAL_COMP_COMP2_EXTI_ENABLE_FALLING_EDGE()) +#define __HAL_COMP_EXTI_FALLING_IT_DISABLE(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_DISABLE_FALLING_EDGE() : \ + __HAL_COMP_COMP2_EXTI_DISABLE_FALLING_EDGE()) +#define __HAL_COMP_EXTI_ENABLE_IT(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_ENABLE_IT() : \ + __HAL_COMP_COMP2_EXTI_ENABLE_IT()) +#define __HAL_COMP_EXTI_DISABLE_IT(__EXTILINE__) (((__EXTILINE__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_DISABLE_IT() : \ + __HAL_COMP_COMP2_EXTI_DISABLE_IT()) +#define __HAL_COMP_EXTI_GET_FLAG(__FLAG__) (((__FLAG__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_GET_FLAG() : \ + __HAL_COMP_COMP2_EXTI_GET_FLAG()) +#define __HAL_COMP_EXTI_CLEAR_FLAG(__FLAG__) (((__FLAG__) == COMP_EXTI_LINE_COMP1) ? __HAL_COMP_COMP1_EXTI_CLEAR_FLAG() : \ + __HAL_COMP_COMP2_EXTI_CLEAR_FLAG()) +#endif + +#define __HAL_COMP_GET_EXTI_LINE COMP_GET_EXTI_LINE + +#if defined(STM32L0) || defined(STM32L4) +/* Note: On these STM32 families, the only argument of this macro */ +/* is COMP_FLAG_LOCK. */ +/* This macro is replaced by __HAL_COMP_IS_LOCKED with only HAL handle */ +/* argument. */ +#define __HAL_COMP_GET_FLAG(__HANDLE__, __FLAG__) (__HAL_COMP_IS_LOCKED(__HANDLE__)) +#endif +/** + * @} + */ + +#if defined(STM32L0) || defined(STM32L4) +/** @defgroup HAL_COMP_Aliased_Functions HAL COMP Aliased Functions maintained for legacy purpose + * @{ + */ +#define HAL_COMP_Start_IT HAL_COMP_Start /* Function considered as legacy as EXTI event or IT configuration is done into HAL_COMP_Init() */ +#define HAL_COMP_Stop_IT HAL_COMP_Stop /* Function considered as legacy as EXTI event or IT configuration is done into HAL_COMP_Init() */ +/** + * @} + */ +#endif + +/** @defgroup HAL_DAC_Aliased_Macros HAL DAC Aliased Macros maintained for legacy purpose + * @{ + */ + +#define IS_DAC_WAVE(WAVE) (((WAVE) == DAC_WAVE_NONE) || \ + ((WAVE) == DAC_WAVE_NOISE)|| \ + ((WAVE) == DAC_WAVE_TRIANGLE)) + +/** + * @} + */ + +/** @defgroup HAL_FLASH_Aliased_Macros HAL FLASH Aliased Macros maintained for legacy purpose + * @{ + */ + +#define IS_WRPAREA IS_OB_WRPAREA +#define IS_TYPEPROGRAM IS_FLASH_TYPEPROGRAM +#define IS_TYPEPROGRAMFLASH IS_FLASH_TYPEPROGRAM +#define IS_TYPEERASE IS_FLASH_TYPEERASE +#define IS_NBSECTORS IS_FLASH_NBSECTORS +#define IS_OB_WDG_SOURCE IS_OB_IWDG_SOURCE + +/** + * @} + */ + +/** @defgroup HAL_I2C_Aliased_Macros HAL I2C Aliased Macros maintained for legacy purpose + * @{ + */ + +#define __HAL_I2C_RESET_CR2 I2C_RESET_CR2 +#define __HAL_I2C_GENERATE_START I2C_GENERATE_START +#if defined(STM32F1) +#define __HAL_I2C_FREQ_RANGE I2C_FREQRANGE +#else +#define __HAL_I2C_FREQ_RANGE I2C_FREQ_RANGE +#endif /* STM32F1 */ +#define __HAL_I2C_RISE_TIME I2C_RISE_TIME +#define __HAL_I2C_SPEED_STANDARD I2C_SPEED_STANDARD +#define __HAL_I2C_SPEED_FAST I2C_SPEED_FAST +#define __HAL_I2C_SPEED I2C_SPEED +#define __HAL_I2C_7BIT_ADD_WRITE I2C_7BIT_ADD_WRITE +#define __HAL_I2C_7BIT_ADD_READ I2C_7BIT_ADD_READ +#define __HAL_I2C_10BIT_ADDRESS I2C_10BIT_ADDRESS +#define __HAL_I2C_10BIT_HEADER_WRITE I2C_10BIT_HEADER_WRITE +#define __HAL_I2C_10BIT_HEADER_READ I2C_10BIT_HEADER_READ +#define __HAL_I2C_MEM_ADD_MSB I2C_MEM_ADD_MSB +#define __HAL_I2C_MEM_ADD_LSB I2C_MEM_ADD_LSB +#define __HAL_I2C_FREQRANGE I2C_FREQRANGE +/** + * @} + */ + +/** @defgroup HAL_I2S_Aliased_Macros HAL I2S Aliased Macros maintained for legacy purpose + * @{ + */ + +#define IS_I2S_INSTANCE IS_I2S_ALL_INSTANCE +#define IS_I2S_INSTANCE_EXT IS_I2S_ALL_INSTANCE_EXT + +/** + * @} + */ + +/** @defgroup HAL_IRDA_Aliased_Macros HAL IRDA Aliased Macros maintained for legacy purpose + * @{ + */ + +#define __IRDA_DISABLE __HAL_IRDA_DISABLE +#define __IRDA_ENABLE __HAL_IRDA_ENABLE + +#define __HAL_IRDA_GETCLOCKSOURCE IRDA_GETCLOCKSOURCE +#define __HAL_IRDA_MASK_COMPUTATION IRDA_MASK_COMPUTATION +#define __IRDA_GETCLOCKSOURCE IRDA_GETCLOCKSOURCE +#define __IRDA_MASK_COMPUTATION IRDA_MASK_COMPUTATION + +#define IS_IRDA_ONEBIT_SAMPLE IS_IRDA_ONE_BIT_SAMPLE + + +/** + * @} + */ + + +/** @defgroup HAL_IWDG_Aliased_Macros HAL IWDG Aliased Macros maintained for legacy purpose + * @{ + */ +#define __HAL_IWDG_ENABLE_WRITE_ACCESS IWDG_ENABLE_WRITE_ACCESS +#define __HAL_IWDG_DISABLE_WRITE_ACCESS IWDG_DISABLE_WRITE_ACCESS +/** + * @} + */ + + +/** @defgroup HAL_LPTIM_Aliased_Macros HAL LPTIM Aliased Macros maintained for legacy purpose + * @{ + */ + +#define __HAL_LPTIM_ENABLE_INTERRUPT __HAL_LPTIM_ENABLE_IT +#define __HAL_LPTIM_DISABLE_INTERRUPT __HAL_LPTIM_DISABLE_IT +#define __HAL_LPTIM_GET_ITSTATUS __HAL_LPTIM_GET_IT_SOURCE + +/** + * @} + */ + + +/** @defgroup HAL_OPAMP_Aliased_Macros HAL OPAMP Aliased Macros maintained for legacy purpose + * @{ + */ +#define __OPAMP_CSR_OPAXPD OPAMP_CSR_OPAXPD +#define __OPAMP_CSR_S3SELX OPAMP_CSR_S3SELX +#define __OPAMP_CSR_S4SELX OPAMP_CSR_S4SELX +#define __OPAMP_CSR_S5SELX OPAMP_CSR_S5SELX +#define __OPAMP_CSR_S6SELX OPAMP_CSR_S6SELX +#define __OPAMP_CSR_OPAXCAL_L OPAMP_CSR_OPAXCAL_L +#define __OPAMP_CSR_OPAXCAL_H OPAMP_CSR_OPAXCAL_H +#define __OPAMP_CSR_OPAXLPM OPAMP_CSR_OPAXLPM +#define __OPAMP_CSR_ALL_SWITCHES OPAMP_CSR_ALL_SWITCHES +#define __OPAMP_CSR_ANAWSELX OPAMP_CSR_ANAWSELX +#define __OPAMP_CSR_OPAXCALOUT OPAMP_CSR_OPAXCALOUT +#define __OPAMP_OFFSET_TRIM_BITSPOSITION OPAMP_OFFSET_TRIM_BITSPOSITION +#define __OPAMP_OFFSET_TRIM_SET OPAMP_OFFSET_TRIM_SET + +/** + * @} + */ + + +/** @defgroup HAL_PWR_Aliased_Macros HAL PWR Aliased Macros maintained for legacy purpose + * @{ + */ +#define __HAL_PVD_EVENT_DISABLE __HAL_PWR_PVD_EXTI_DISABLE_EVENT +#define __HAL_PVD_EVENT_ENABLE __HAL_PWR_PVD_EXTI_ENABLE_EVENT +#define __HAL_PVD_EXTI_FALLINGTRIGGER_DISABLE __HAL_PWR_PVD_EXTI_DISABLE_FALLING_EDGE +#define __HAL_PVD_EXTI_FALLINGTRIGGER_ENABLE __HAL_PWR_PVD_EXTI_ENABLE_FALLING_EDGE +#define __HAL_PVD_EXTI_RISINGTRIGGER_DISABLE __HAL_PWR_PVD_EXTI_DISABLE_RISING_EDGE +#define __HAL_PVD_EXTI_RISINGTRIGGER_ENABLE __HAL_PWR_PVD_EXTI_ENABLE_RISING_EDGE +#define __HAL_PVM_EVENT_DISABLE __HAL_PWR_PVM_EVENT_DISABLE +#define __HAL_PVM_EVENT_ENABLE __HAL_PWR_PVM_EVENT_ENABLE +#define __HAL_PVM_EXTI_FALLINGTRIGGER_DISABLE __HAL_PWR_PVM_EXTI_FALLINGTRIGGER_DISABLE +#define __HAL_PVM_EXTI_FALLINGTRIGGER_ENABLE __HAL_PWR_PVM_EXTI_FALLINGTRIGGER_ENABLE +#define __HAL_PVM_EXTI_RISINGTRIGGER_DISABLE __HAL_PWR_PVM_EXTI_RISINGTRIGGER_DISABLE +#define __HAL_PVM_EXTI_RISINGTRIGGER_ENABLE __HAL_PWR_PVM_EXTI_RISINGTRIGGER_ENABLE +#define __HAL_PWR_INTERNALWAKEUP_DISABLE HAL_PWREx_DisableInternalWakeUpLine +#define __HAL_PWR_INTERNALWAKEUP_ENABLE HAL_PWREx_EnableInternalWakeUpLine +#define __HAL_PWR_PULL_UP_DOWN_CONFIG_DISABLE HAL_PWREx_DisablePullUpPullDownConfig +#define __HAL_PWR_PULL_UP_DOWN_CONFIG_ENABLE HAL_PWREx_EnablePullUpPullDownConfig +#define __HAL_PWR_PVD_EXTI_CLEAR_EGDE_TRIGGER() do { __HAL_PWR_PVD_EXTI_DISABLE_RISING_EDGE();__HAL_PWR_PVD_EXTI_DISABLE_FALLING_EDGE(); } while(0) +#define __HAL_PWR_PVD_EXTI_EVENT_DISABLE __HAL_PWR_PVD_EXTI_DISABLE_EVENT +#define __HAL_PWR_PVD_EXTI_EVENT_ENABLE __HAL_PWR_PVD_EXTI_ENABLE_EVENT +#define __HAL_PWR_PVD_EXTI_FALLINGTRIGGER_DISABLE __HAL_PWR_PVD_EXTI_DISABLE_FALLING_EDGE +#define __HAL_PWR_PVD_EXTI_FALLINGTRIGGER_ENABLE __HAL_PWR_PVD_EXTI_ENABLE_FALLING_EDGE +#define __HAL_PWR_PVD_EXTI_RISINGTRIGGER_DISABLE __HAL_PWR_PVD_EXTI_DISABLE_RISING_EDGE +#define __HAL_PWR_PVD_EXTI_RISINGTRIGGER_ENABLE __HAL_PWR_PVD_EXTI_ENABLE_RISING_EDGE +#define __HAL_PWR_PVD_EXTI_SET_FALLING_EGDE_TRIGGER __HAL_PWR_PVD_EXTI_ENABLE_FALLING_EDGE +#define __HAL_PWR_PVD_EXTI_SET_RISING_EDGE_TRIGGER __HAL_PWR_PVD_EXTI_ENABLE_RISING_EDGE +#define __HAL_PWR_PVM_DISABLE() do { HAL_PWREx_DisablePVM1();HAL_PWREx_DisablePVM2();HAL_PWREx_DisablePVM3();HAL_PWREx_DisablePVM4(); } while(0) +#define __HAL_PWR_PVM_ENABLE() do { HAL_PWREx_EnablePVM1();HAL_PWREx_EnablePVM2();HAL_PWREx_EnablePVM3();HAL_PWREx_EnablePVM4(); } while(0) +#define __HAL_PWR_SRAM2CONTENT_PRESERVE_DISABLE HAL_PWREx_DisableSRAM2ContentRetention +#define __HAL_PWR_SRAM2CONTENT_PRESERVE_ENABLE HAL_PWREx_EnableSRAM2ContentRetention +#define __HAL_PWR_VDDIO2_DISABLE HAL_PWREx_DisableVddIO2 +#define __HAL_PWR_VDDIO2_ENABLE HAL_PWREx_EnableVddIO2 +#define __HAL_PWR_VDDIO2_EXTI_CLEAR_EGDE_TRIGGER __HAL_PWR_VDDIO2_EXTI_DISABLE_FALLING_EDGE +#define __HAL_PWR_VDDIO2_EXTI_SET_FALLING_EGDE_TRIGGER __HAL_PWR_VDDIO2_EXTI_ENABLE_FALLING_EDGE +#define __HAL_PWR_VDDUSB_DISABLE HAL_PWREx_DisableVddUSB +#define __HAL_PWR_VDDUSB_ENABLE HAL_PWREx_EnableVddUSB + +#if defined (STM32F4) +#define __HAL_PVD_EXTI_ENABLE_IT(PWR_EXTI_LINE_PVD) __HAL_PWR_PVD_EXTI_ENABLE_IT() +#define __HAL_PVD_EXTI_DISABLE_IT(PWR_EXTI_LINE_PVD) __HAL_PWR_PVD_EXTI_DISABLE_IT() +#define __HAL_PVD_EXTI_GET_FLAG(PWR_EXTI_LINE_PVD) __HAL_PWR_PVD_EXTI_GET_FLAG() +#define __HAL_PVD_EXTI_CLEAR_FLAG(PWR_EXTI_LINE_PVD) __HAL_PWR_PVD_EXTI_CLEAR_FLAG() +#define __HAL_PVD_EXTI_GENERATE_SWIT(PWR_EXTI_LINE_PVD) __HAL_PWR_PVD_EXTI_GENERATE_SWIT() +#else +#define __HAL_PVD_EXTI_CLEAR_FLAG __HAL_PWR_PVD_EXTI_CLEAR_FLAG +#define __HAL_PVD_EXTI_DISABLE_IT __HAL_PWR_PVD_EXTI_DISABLE_IT +#define __HAL_PVD_EXTI_ENABLE_IT __HAL_PWR_PVD_EXTI_ENABLE_IT +#define __HAL_PVD_EXTI_GENERATE_SWIT __HAL_PWR_PVD_EXTI_GENERATE_SWIT +#define __HAL_PVD_EXTI_GET_FLAG __HAL_PWR_PVD_EXTI_GET_FLAG +#endif /* STM32F4 */ +/** + * @} + */ + + +/** @defgroup HAL_RCC_Aliased HAL RCC Aliased maintained for legacy purpose + * @{ + */ + +#define RCC_StopWakeUpClock_MSI RCC_STOP_WAKEUPCLOCK_MSI +#define RCC_StopWakeUpClock_HSI RCC_STOP_WAKEUPCLOCK_HSI + +#define HAL_RCC_CCSCallback HAL_RCC_CSSCallback +#define HAL_RC48_EnableBuffer_Cmd(cmd) (((cmd)==ENABLE) ? HAL_RCCEx_EnableHSI48_VREFINT() : HAL_RCCEx_DisableHSI48_VREFINT()) + +#define __ADC_CLK_DISABLE __HAL_RCC_ADC_CLK_DISABLE +#define __ADC_CLK_ENABLE __HAL_RCC_ADC_CLK_ENABLE +#define __ADC_CLK_SLEEP_DISABLE __HAL_RCC_ADC_CLK_SLEEP_DISABLE +#define __ADC_CLK_SLEEP_ENABLE __HAL_RCC_ADC_CLK_SLEEP_ENABLE +#define __ADC_FORCE_RESET __HAL_RCC_ADC_FORCE_RESET +#define __ADC_RELEASE_RESET __HAL_RCC_ADC_RELEASE_RESET +#define __ADC1_CLK_DISABLE __HAL_RCC_ADC1_CLK_DISABLE +#define __ADC1_CLK_ENABLE __HAL_RCC_ADC1_CLK_ENABLE +#define __ADC1_FORCE_RESET __HAL_RCC_ADC1_FORCE_RESET +#define __ADC1_RELEASE_RESET __HAL_RCC_ADC1_RELEASE_RESET +#define __ADC1_CLK_SLEEP_ENABLE __HAL_RCC_ADC1_CLK_SLEEP_ENABLE +#define __ADC1_CLK_SLEEP_DISABLE __HAL_RCC_ADC1_CLK_SLEEP_DISABLE +#define __ADC2_CLK_DISABLE __HAL_RCC_ADC2_CLK_DISABLE +#define __ADC2_CLK_ENABLE __HAL_RCC_ADC2_CLK_ENABLE +#define __ADC2_FORCE_RESET __HAL_RCC_ADC2_FORCE_RESET +#define __ADC2_RELEASE_RESET __HAL_RCC_ADC2_RELEASE_RESET +#define __ADC3_CLK_DISABLE __HAL_RCC_ADC3_CLK_DISABLE +#define __ADC3_CLK_ENABLE __HAL_RCC_ADC3_CLK_ENABLE +#define __ADC3_FORCE_RESET __HAL_RCC_ADC3_FORCE_RESET +#define __ADC3_RELEASE_RESET __HAL_RCC_ADC3_RELEASE_RESET +#define __AES_CLK_DISABLE __HAL_RCC_AES_CLK_DISABLE +#define __AES_CLK_ENABLE __HAL_RCC_AES_CLK_ENABLE +#define __AES_CLK_SLEEP_DISABLE __HAL_RCC_AES_CLK_SLEEP_DISABLE +#define __AES_CLK_SLEEP_ENABLE __HAL_RCC_AES_CLK_SLEEP_ENABLE +#define __AES_FORCE_RESET __HAL_RCC_AES_FORCE_RESET +#define __AES_RELEASE_RESET __HAL_RCC_AES_RELEASE_RESET +#define __CRYP_CLK_SLEEP_ENABLE __HAL_RCC_CRYP_CLK_SLEEP_ENABLE +#define __CRYP_CLK_SLEEP_DISABLE __HAL_RCC_CRYP_CLK_SLEEP_DISABLE +#define __CRYP_CLK_ENABLE __HAL_RCC_CRYP_CLK_ENABLE +#define __CRYP_CLK_DISABLE __HAL_RCC_CRYP_CLK_DISABLE +#define __CRYP_FORCE_RESET __HAL_RCC_CRYP_FORCE_RESET +#define __CRYP_RELEASE_RESET __HAL_RCC_CRYP_RELEASE_RESET +#define __AFIO_CLK_DISABLE __HAL_RCC_AFIO_CLK_DISABLE +#define __AFIO_CLK_ENABLE __HAL_RCC_AFIO_CLK_ENABLE +#define __AFIO_FORCE_RESET __HAL_RCC_AFIO_FORCE_RESET +#define __AFIO_RELEASE_RESET __HAL_RCC_AFIO_RELEASE_RESET +#define __AHB_FORCE_RESET __HAL_RCC_AHB_FORCE_RESET +#define __AHB_RELEASE_RESET __HAL_RCC_AHB_RELEASE_RESET +#define __AHB1_FORCE_RESET __HAL_RCC_AHB1_FORCE_RESET +#define __AHB1_RELEASE_RESET __HAL_RCC_AHB1_RELEASE_RESET +#define __AHB2_FORCE_RESET __HAL_RCC_AHB2_FORCE_RESET +#define __AHB2_RELEASE_RESET __HAL_RCC_AHB2_RELEASE_RESET +#define __AHB3_FORCE_RESET __HAL_RCC_AHB3_FORCE_RESET +#define __AHB3_RELEASE_RESET __HAL_RCC_AHB3_RELEASE_RESET +#define __APB1_FORCE_RESET __HAL_RCC_APB1_FORCE_RESET +#define __APB1_RELEASE_RESET __HAL_RCC_APB1_RELEASE_RESET +#define __APB2_FORCE_RESET __HAL_RCC_APB2_FORCE_RESET +#define __APB2_RELEASE_RESET __HAL_RCC_APB2_RELEASE_RESET +#define __BKP_CLK_DISABLE __HAL_RCC_BKP_CLK_DISABLE +#define __BKP_CLK_ENABLE __HAL_RCC_BKP_CLK_ENABLE +#define __BKP_FORCE_RESET __HAL_RCC_BKP_FORCE_RESET +#define __BKP_RELEASE_RESET __HAL_RCC_BKP_RELEASE_RESET +#define __CAN1_CLK_DISABLE __HAL_RCC_CAN1_CLK_DISABLE +#define __CAN1_CLK_ENABLE __HAL_RCC_CAN1_CLK_ENABLE +#define __CAN1_CLK_SLEEP_DISABLE __HAL_RCC_CAN1_CLK_SLEEP_DISABLE +#define __CAN1_CLK_SLEEP_ENABLE __HAL_RCC_CAN1_CLK_SLEEP_ENABLE +#define __CAN1_FORCE_RESET __HAL_RCC_CAN1_FORCE_RESET +#define __CAN1_RELEASE_RESET __HAL_RCC_CAN1_RELEASE_RESET +#define __CAN_CLK_DISABLE __HAL_RCC_CAN1_CLK_DISABLE +#define __CAN_CLK_ENABLE __HAL_RCC_CAN1_CLK_ENABLE +#define __CAN_FORCE_RESET __HAL_RCC_CAN1_FORCE_RESET +#define __CAN_RELEASE_RESET __HAL_RCC_CAN1_RELEASE_RESET +#define __CAN2_CLK_DISABLE __HAL_RCC_CAN2_CLK_DISABLE +#define __CAN2_CLK_ENABLE __HAL_RCC_CAN2_CLK_ENABLE +#define __CAN2_FORCE_RESET __HAL_RCC_CAN2_FORCE_RESET +#define __CAN2_RELEASE_RESET __HAL_RCC_CAN2_RELEASE_RESET +#define __CEC_CLK_DISABLE __HAL_RCC_CEC_CLK_DISABLE +#define __CEC_CLK_ENABLE __HAL_RCC_CEC_CLK_ENABLE +#define __COMP_CLK_DISABLE __HAL_RCC_COMP_CLK_DISABLE +#define __COMP_CLK_ENABLE __HAL_RCC_COMP_CLK_ENABLE +#define __COMP_FORCE_RESET __HAL_RCC_COMP_FORCE_RESET +#define __COMP_RELEASE_RESET __HAL_RCC_COMP_RELEASE_RESET +#define __COMP_CLK_SLEEP_ENABLE __HAL_RCC_COMP_CLK_SLEEP_ENABLE +#define __COMP_CLK_SLEEP_DISABLE __HAL_RCC_COMP_CLK_SLEEP_DISABLE +#define __CEC_FORCE_RESET __HAL_RCC_CEC_FORCE_RESET +#define __CEC_RELEASE_RESET __HAL_RCC_CEC_RELEASE_RESET +#define __CRC_CLK_DISABLE __HAL_RCC_CRC_CLK_DISABLE +#define __CRC_CLK_ENABLE __HAL_RCC_CRC_CLK_ENABLE +#define __CRC_CLK_SLEEP_DISABLE __HAL_RCC_CRC_CLK_SLEEP_DISABLE +#define __CRC_CLK_SLEEP_ENABLE __HAL_RCC_CRC_CLK_SLEEP_ENABLE +#define __CRC_FORCE_RESET __HAL_RCC_CRC_FORCE_RESET +#define __CRC_RELEASE_RESET __HAL_RCC_CRC_RELEASE_RESET +#define __DAC_CLK_DISABLE __HAL_RCC_DAC_CLK_DISABLE +#define __DAC_CLK_ENABLE __HAL_RCC_DAC_CLK_ENABLE +#define __DAC_FORCE_RESET __HAL_RCC_DAC_FORCE_RESET +#define __DAC_RELEASE_RESET __HAL_RCC_DAC_RELEASE_RESET +#define __DAC1_CLK_DISABLE __HAL_RCC_DAC1_CLK_DISABLE +#define __DAC1_CLK_ENABLE __HAL_RCC_DAC1_CLK_ENABLE +#define __DAC1_CLK_SLEEP_DISABLE __HAL_RCC_DAC1_CLK_SLEEP_DISABLE +#define __DAC1_CLK_SLEEP_ENABLE __HAL_RCC_DAC1_CLK_SLEEP_ENABLE +#define __DAC1_FORCE_RESET __HAL_RCC_DAC1_FORCE_RESET +#define __DAC1_RELEASE_RESET __HAL_RCC_DAC1_RELEASE_RESET +#define __DBGMCU_CLK_ENABLE __HAL_RCC_DBGMCU_CLK_ENABLE +#define __DBGMCU_CLK_DISABLE __HAL_RCC_DBGMCU_CLK_DISABLE +#define __DBGMCU_FORCE_RESET __HAL_RCC_DBGMCU_FORCE_RESET +#define __DBGMCU_RELEASE_RESET __HAL_RCC_DBGMCU_RELEASE_RESET +#define __DFSDM_CLK_DISABLE __HAL_RCC_DFSDM_CLK_DISABLE +#define __DFSDM_CLK_ENABLE __HAL_RCC_DFSDM_CLK_ENABLE +#define __DFSDM_CLK_SLEEP_DISABLE __HAL_RCC_DFSDM_CLK_SLEEP_DISABLE +#define __DFSDM_CLK_SLEEP_ENABLE __HAL_RCC_DFSDM_CLK_SLEEP_ENABLE +#define __DFSDM_FORCE_RESET __HAL_RCC_DFSDM_FORCE_RESET +#define __DFSDM_RELEASE_RESET __HAL_RCC_DFSDM_RELEASE_RESET +#define __DMA1_CLK_DISABLE __HAL_RCC_DMA1_CLK_DISABLE +#define __DMA1_CLK_ENABLE __HAL_RCC_DMA1_CLK_ENABLE +#define __DMA1_CLK_SLEEP_DISABLE __HAL_RCC_DMA1_CLK_SLEEP_DISABLE +#define __DMA1_CLK_SLEEP_ENABLE __HAL_RCC_DMA1_CLK_SLEEP_ENABLE +#define __DMA1_FORCE_RESET __HAL_RCC_DMA1_FORCE_RESET +#define __DMA1_RELEASE_RESET __HAL_RCC_DMA1_RELEASE_RESET +#define __DMA2_CLK_DISABLE __HAL_RCC_DMA2_CLK_DISABLE +#define __DMA2_CLK_ENABLE __HAL_RCC_DMA2_CLK_ENABLE +#define __DMA2_CLK_SLEEP_DISABLE __HAL_RCC_DMA2_CLK_SLEEP_DISABLE +#define __DMA2_CLK_SLEEP_ENABLE __HAL_RCC_DMA2_CLK_SLEEP_ENABLE +#define __DMA2_FORCE_RESET __HAL_RCC_DMA2_FORCE_RESET +#define __DMA2_RELEASE_RESET __HAL_RCC_DMA2_RELEASE_RESET +#define __ETHMAC_CLK_DISABLE __HAL_RCC_ETHMAC_CLK_DISABLE +#define __ETHMAC_CLK_ENABLE __HAL_RCC_ETHMAC_CLK_ENABLE +#define __ETHMAC_FORCE_RESET __HAL_RCC_ETHMAC_FORCE_RESET +#define __ETHMAC_RELEASE_RESET __HAL_RCC_ETHMAC_RELEASE_RESET +#define __ETHMACRX_CLK_DISABLE __HAL_RCC_ETHMACRX_CLK_DISABLE +#define __ETHMACRX_CLK_ENABLE __HAL_RCC_ETHMACRX_CLK_ENABLE +#define __ETHMACTX_CLK_DISABLE __HAL_RCC_ETHMACTX_CLK_DISABLE +#define __ETHMACTX_CLK_ENABLE __HAL_RCC_ETHMACTX_CLK_ENABLE +#define __FIREWALL_CLK_DISABLE __HAL_RCC_FIREWALL_CLK_DISABLE +#define __FIREWALL_CLK_ENABLE __HAL_RCC_FIREWALL_CLK_ENABLE +#define __FLASH_CLK_DISABLE __HAL_RCC_FLASH_CLK_DISABLE +#define __FLASH_CLK_ENABLE __HAL_RCC_FLASH_CLK_ENABLE +#define __FLASH_CLK_SLEEP_DISABLE __HAL_RCC_FLASH_CLK_SLEEP_DISABLE +#define __FLASH_CLK_SLEEP_ENABLE __HAL_RCC_FLASH_CLK_SLEEP_ENABLE +#define __FLASH_FORCE_RESET __HAL_RCC_FLASH_FORCE_RESET +#define __FLASH_RELEASE_RESET __HAL_RCC_FLASH_RELEASE_RESET +#define __FLITF_CLK_DISABLE __HAL_RCC_FLITF_CLK_DISABLE +#define __FLITF_CLK_ENABLE __HAL_RCC_FLITF_CLK_ENABLE +#define __FLITF_FORCE_RESET __HAL_RCC_FLITF_FORCE_RESET +#define __FLITF_RELEASE_RESET __HAL_RCC_FLITF_RELEASE_RESET +#define __FLITF_CLK_SLEEP_ENABLE __HAL_RCC_FLITF_CLK_SLEEP_ENABLE +#define __FLITF_CLK_SLEEP_DISABLE __HAL_RCC_FLITF_CLK_SLEEP_DISABLE +#define __FMC_CLK_DISABLE __HAL_RCC_FMC_CLK_DISABLE +#define __FMC_CLK_ENABLE __HAL_RCC_FMC_CLK_ENABLE +#define __FMC_CLK_SLEEP_DISABLE __HAL_RCC_FMC_CLK_SLEEP_DISABLE +#define __FMC_CLK_SLEEP_ENABLE __HAL_RCC_FMC_CLK_SLEEP_ENABLE +#define __FMC_FORCE_RESET __HAL_RCC_FMC_FORCE_RESET +#define __FMC_RELEASE_RESET __HAL_RCC_FMC_RELEASE_RESET +#define __FSMC_CLK_DISABLE __HAL_RCC_FSMC_CLK_DISABLE +#define __FSMC_CLK_ENABLE __HAL_RCC_FSMC_CLK_ENABLE +#define __GPIOA_CLK_DISABLE __HAL_RCC_GPIOA_CLK_DISABLE +#define __GPIOA_CLK_ENABLE __HAL_RCC_GPIOA_CLK_ENABLE +#define __GPIOA_CLK_SLEEP_DISABLE __HAL_RCC_GPIOA_CLK_SLEEP_DISABLE +#define __GPIOA_CLK_SLEEP_ENABLE __HAL_RCC_GPIOA_CLK_SLEEP_ENABLE +#define __GPIOA_FORCE_RESET __HAL_RCC_GPIOA_FORCE_RESET +#define __GPIOA_RELEASE_RESET __HAL_RCC_GPIOA_RELEASE_RESET +#define __GPIOB_CLK_DISABLE __HAL_RCC_GPIOB_CLK_DISABLE +#define __GPIOB_CLK_ENABLE __HAL_RCC_GPIOB_CLK_ENABLE +#define __GPIOB_CLK_SLEEP_DISABLE __HAL_RCC_GPIOB_CLK_SLEEP_DISABLE +#define __GPIOB_CLK_SLEEP_ENABLE __HAL_RCC_GPIOB_CLK_SLEEP_ENABLE +#define __GPIOB_FORCE_RESET __HAL_RCC_GPIOB_FORCE_RESET +#define __GPIOB_RELEASE_RESET __HAL_RCC_GPIOB_RELEASE_RESET +#define __GPIOC_CLK_DISABLE __HAL_RCC_GPIOC_CLK_DISABLE +#define __GPIOC_CLK_ENABLE __HAL_RCC_GPIOC_CLK_ENABLE +#define __GPIOC_CLK_SLEEP_DISABLE __HAL_RCC_GPIOC_CLK_SLEEP_DISABLE +#define __GPIOC_CLK_SLEEP_ENABLE __HAL_RCC_GPIOC_CLK_SLEEP_ENABLE +#define __GPIOC_FORCE_RESET __HAL_RCC_GPIOC_FORCE_RESET +#define __GPIOC_RELEASE_RESET __HAL_RCC_GPIOC_RELEASE_RESET +#define __GPIOD_CLK_DISABLE __HAL_RCC_GPIOD_CLK_DISABLE +#define __GPIOD_CLK_ENABLE __HAL_RCC_GPIOD_CLK_ENABLE +#define __GPIOD_CLK_SLEEP_DISABLE __HAL_RCC_GPIOD_CLK_SLEEP_DISABLE +#define __GPIOD_CLK_SLEEP_ENABLE __HAL_RCC_GPIOD_CLK_SLEEP_ENABLE +#define __GPIOD_FORCE_RESET __HAL_RCC_GPIOD_FORCE_RESET +#define __GPIOD_RELEASE_RESET __HAL_RCC_GPIOD_RELEASE_RESET +#define __GPIOE_CLK_DISABLE __HAL_RCC_GPIOE_CLK_DISABLE +#define __GPIOE_CLK_ENABLE __HAL_RCC_GPIOE_CLK_ENABLE +#define __GPIOE_CLK_SLEEP_DISABLE __HAL_RCC_GPIOE_CLK_SLEEP_DISABLE +#define __GPIOE_CLK_SLEEP_ENABLE __HAL_RCC_GPIOE_CLK_SLEEP_ENABLE +#define __GPIOE_FORCE_RESET __HAL_RCC_GPIOE_FORCE_RESET +#define __GPIOE_RELEASE_RESET __HAL_RCC_GPIOE_RELEASE_RESET +#define __GPIOF_CLK_DISABLE __HAL_RCC_GPIOF_CLK_DISABLE +#define __GPIOF_CLK_ENABLE __HAL_RCC_GPIOF_CLK_ENABLE +#define __GPIOF_CLK_SLEEP_DISABLE __HAL_RCC_GPIOF_CLK_SLEEP_DISABLE +#define __GPIOF_CLK_SLEEP_ENABLE __HAL_RCC_GPIOF_CLK_SLEEP_ENABLE +#define __GPIOF_FORCE_RESET __HAL_RCC_GPIOF_FORCE_RESET +#define __GPIOF_RELEASE_RESET __HAL_RCC_GPIOF_RELEASE_RESET +#define __GPIOG_CLK_DISABLE __HAL_RCC_GPIOG_CLK_DISABLE +#define __GPIOG_CLK_ENABLE __HAL_RCC_GPIOG_CLK_ENABLE +#define __GPIOG_CLK_SLEEP_DISABLE __HAL_RCC_GPIOG_CLK_SLEEP_DISABLE +#define __GPIOG_CLK_SLEEP_ENABLE __HAL_RCC_GPIOG_CLK_SLEEP_ENABLE +#define __GPIOG_FORCE_RESET __HAL_RCC_GPIOG_FORCE_RESET +#define __GPIOG_RELEASE_RESET __HAL_RCC_GPIOG_RELEASE_RESET +#define __GPIOH_CLK_DISABLE __HAL_RCC_GPIOH_CLK_DISABLE +#define __GPIOH_CLK_ENABLE __HAL_RCC_GPIOH_CLK_ENABLE +#define __GPIOH_CLK_SLEEP_DISABLE __HAL_RCC_GPIOH_CLK_SLEEP_DISABLE +#define __GPIOH_CLK_SLEEP_ENABLE __HAL_RCC_GPIOH_CLK_SLEEP_ENABLE +#define __GPIOH_FORCE_RESET __HAL_RCC_GPIOH_FORCE_RESET +#define __GPIOH_RELEASE_RESET __HAL_RCC_GPIOH_RELEASE_RESET +#define __I2C1_CLK_DISABLE __HAL_RCC_I2C1_CLK_DISABLE +#define __I2C1_CLK_ENABLE __HAL_RCC_I2C1_CLK_ENABLE +#define __I2C1_CLK_SLEEP_DISABLE __HAL_RCC_I2C1_CLK_SLEEP_DISABLE +#define __I2C1_CLK_SLEEP_ENABLE __HAL_RCC_I2C1_CLK_SLEEP_ENABLE +#define __I2C1_FORCE_RESET __HAL_RCC_I2C1_FORCE_RESET +#define __I2C1_RELEASE_RESET __HAL_RCC_I2C1_RELEASE_RESET +#define __I2C2_CLK_DISABLE __HAL_RCC_I2C2_CLK_DISABLE +#define __I2C2_CLK_ENABLE __HAL_RCC_I2C2_CLK_ENABLE +#define __I2C2_CLK_SLEEP_DISABLE __HAL_RCC_I2C2_CLK_SLEEP_DISABLE +#define __I2C2_CLK_SLEEP_ENABLE __HAL_RCC_I2C2_CLK_SLEEP_ENABLE +#define __I2C2_FORCE_RESET __HAL_RCC_I2C2_FORCE_RESET +#define __I2C2_RELEASE_RESET __HAL_RCC_I2C2_RELEASE_RESET +#define __I2C3_CLK_DISABLE __HAL_RCC_I2C3_CLK_DISABLE +#define __I2C3_CLK_ENABLE __HAL_RCC_I2C3_CLK_ENABLE +#define __I2C3_CLK_SLEEP_DISABLE __HAL_RCC_I2C3_CLK_SLEEP_DISABLE +#define __I2C3_CLK_SLEEP_ENABLE __HAL_RCC_I2C3_CLK_SLEEP_ENABLE +#define __I2C3_FORCE_RESET __HAL_RCC_I2C3_FORCE_RESET +#define __I2C3_RELEASE_RESET __HAL_RCC_I2C3_RELEASE_RESET +#define __LCD_CLK_DISABLE __HAL_RCC_LCD_CLK_DISABLE +#define __LCD_CLK_ENABLE __HAL_RCC_LCD_CLK_ENABLE +#define __LCD_CLK_SLEEP_DISABLE __HAL_RCC_LCD_CLK_SLEEP_DISABLE +#define __LCD_CLK_SLEEP_ENABLE __HAL_RCC_LCD_CLK_SLEEP_ENABLE +#define __LCD_FORCE_RESET __HAL_RCC_LCD_FORCE_RESET +#define __LCD_RELEASE_RESET __HAL_RCC_LCD_RELEASE_RESET +#define __LPTIM1_CLK_DISABLE __HAL_RCC_LPTIM1_CLK_DISABLE +#define __LPTIM1_CLK_ENABLE __HAL_RCC_LPTIM1_CLK_ENABLE +#define __LPTIM1_CLK_SLEEP_DISABLE __HAL_RCC_LPTIM1_CLK_SLEEP_DISABLE +#define __LPTIM1_CLK_SLEEP_ENABLE __HAL_RCC_LPTIM1_CLK_SLEEP_ENABLE +#define __LPTIM1_FORCE_RESET __HAL_RCC_LPTIM1_FORCE_RESET +#define __LPTIM1_RELEASE_RESET __HAL_RCC_LPTIM1_RELEASE_RESET +#define __LPTIM2_CLK_DISABLE __HAL_RCC_LPTIM2_CLK_DISABLE +#define __LPTIM2_CLK_ENABLE __HAL_RCC_LPTIM2_CLK_ENABLE +#define __LPTIM2_CLK_SLEEP_DISABLE __HAL_RCC_LPTIM2_CLK_SLEEP_DISABLE +#define __LPTIM2_CLK_SLEEP_ENABLE __HAL_RCC_LPTIM2_CLK_SLEEP_ENABLE +#define __LPTIM2_FORCE_RESET __HAL_RCC_LPTIM2_FORCE_RESET +#define __LPTIM2_RELEASE_RESET __HAL_RCC_LPTIM2_RELEASE_RESET +#define __LPUART1_CLK_DISABLE __HAL_RCC_LPUART1_CLK_DISABLE +#define __LPUART1_CLK_ENABLE __HAL_RCC_LPUART1_CLK_ENABLE +#define __LPUART1_CLK_SLEEP_DISABLE __HAL_RCC_LPUART1_CLK_SLEEP_DISABLE +#define __LPUART1_CLK_SLEEP_ENABLE __HAL_RCC_LPUART1_CLK_SLEEP_ENABLE +#define __LPUART1_FORCE_RESET __HAL_RCC_LPUART1_FORCE_RESET +#define __LPUART1_RELEASE_RESET __HAL_RCC_LPUART1_RELEASE_RESET +#define __OPAMP_CLK_DISABLE __HAL_RCC_OPAMP_CLK_DISABLE +#define __OPAMP_CLK_ENABLE __HAL_RCC_OPAMP_CLK_ENABLE +#define __OPAMP_CLK_SLEEP_DISABLE __HAL_RCC_OPAMP_CLK_SLEEP_DISABLE +#define __OPAMP_CLK_SLEEP_ENABLE __HAL_RCC_OPAMP_CLK_SLEEP_ENABLE +#define __OPAMP_FORCE_RESET __HAL_RCC_OPAMP_FORCE_RESET +#define __OPAMP_RELEASE_RESET __HAL_RCC_OPAMP_RELEASE_RESET +#define __OTGFS_CLK_DISABLE __HAL_RCC_OTGFS_CLK_DISABLE +#define __OTGFS_CLK_ENABLE __HAL_RCC_OTGFS_CLK_ENABLE +#define __OTGFS_CLK_SLEEP_DISABLE __HAL_RCC_OTGFS_CLK_SLEEP_DISABLE +#define __OTGFS_CLK_SLEEP_ENABLE __HAL_RCC_OTGFS_CLK_SLEEP_ENABLE +#define __OTGFS_FORCE_RESET __HAL_RCC_OTGFS_FORCE_RESET +#define __OTGFS_RELEASE_RESET __HAL_RCC_OTGFS_RELEASE_RESET +#define __PWR_CLK_DISABLE __HAL_RCC_PWR_CLK_DISABLE +#define __PWR_CLK_ENABLE __HAL_RCC_PWR_CLK_ENABLE +#define __PWR_CLK_SLEEP_DISABLE __HAL_RCC_PWR_CLK_SLEEP_DISABLE +#define __PWR_CLK_SLEEP_ENABLE __HAL_RCC_PWR_CLK_SLEEP_ENABLE +#define __PWR_FORCE_RESET __HAL_RCC_PWR_FORCE_RESET +#define __PWR_RELEASE_RESET __HAL_RCC_PWR_RELEASE_RESET +#define __QSPI_CLK_DISABLE __HAL_RCC_QSPI_CLK_DISABLE +#define __QSPI_CLK_ENABLE __HAL_RCC_QSPI_CLK_ENABLE +#define __QSPI_CLK_SLEEP_DISABLE __HAL_RCC_QSPI_CLK_SLEEP_DISABLE +#define __QSPI_CLK_SLEEP_ENABLE __HAL_RCC_QSPI_CLK_SLEEP_ENABLE +#define __QSPI_FORCE_RESET __HAL_RCC_QSPI_FORCE_RESET +#define __QSPI_RELEASE_RESET __HAL_RCC_QSPI_RELEASE_RESET + +#if defined(STM32WB) +#define __HAL_RCC_QSPI_CLK_DISABLE __HAL_RCC_QUADSPI_CLK_DISABLE +#define __HAL_RCC_QSPI_CLK_ENABLE __HAL_RCC_QUADSPI_CLK_ENABLE +#define __HAL_RCC_QSPI_CLK_SLEEP_DISABLE __HAL_RCC_QUADSPI_CLK_SLEEP_DISABLE +#define __HAL_RCC_QSPI_CLK_SLEEP_ENABLE __HAL_RCC_QUADSPI_CLK_SLEEP_ENABLE +#define __HAL_RCC_QSPI_FORCE_RESET __HAL_RCC_QUADSPI_FORCE_RESET +#define __HAL_RCC_QSPI_RELEASE_RESET __HAL_RCC_QUADSPI_RELEASE_RESET +#define __HAL_RCC_QSPI_IS_CLK_ENABLED __HAL_RCC_QUADSPI_IS_CLK_ENABLED +#define __HAL_RCC_QSPI_IS_CLK_DISABLED __HAL_RCC_QUADSPI_IS_CLK_DISABLED +#define __HAL_RCC_QSPI_IS_CLK_SLEEP_ENABLED __HAL_RCC_QUADSPI_IS_CLK_SLEEP_ENABLED +#define __HAL_RCC_QSPI_IS_CLK_SLEEP_DISABLED __HAL_RCC_QUADSPI_IS_CLK_SLEEP_DISABLED +#define QSPI_IRQHandler QUADSPI_IRQHandler +#endif /* __HAL_RCC_QUADSPI_CLK_ENABLE */ + +#define __RNG_CLK_DISABLE __HAL_RCC_RNG_CLK_DISABLE +#define __RNG_CLK_ENABLE __HAL_RCC_RNG_CLK_ENABLE +#define __RNG_CLK_SLEEP_DISABLE __HAL_RCC_RNG_CLK_SLEEP_DISABLE +#define __RNG_CLK_SLEEP_ENABLE __HAL_RCC_RNG_CLK_SLEEP_ENABLE +#define __RNG_FORCE_RESET __HAL_RCC_RNG_FORCE_RESET +#define __RNG_RELEASE_RESET __HAL_RCC_RNG_RELEASE_RESET +#define __SAI1_CLK_DISABLE __HAL_RCC_SAI1_CLK_DISABLE +#define __SAI1_CLK_ENABLE __HAL_RCC_SAI1_CLK_ENABLE +#define __SAI1_CLK_SLEEP_DISABLE __HAL_RCC_SAI1_CLK_SLEEP_DISABLE +#define __SAI1_CLK_SLEEP_ENABLE __HAL_RCC_SAI1_CLK_SLEEP_ENABLE +#define __SAI1_FORCE_RESET __HAL_RCC_SAI1_FORCE_RESET +#define __SAI1_RELEASE_RESET __HAL_RCC_SAI1_RELEASE_RESET +#define __SAI2_CLK_DISABLE __HAL_RCC_SAI2_CLK_DISABLE +#define __SAI2_CLK_ENABLE __HAL_RCC_SAI2_CLK_ENABLE +#define __SAI2_CLK_SLEEP_DISABLE __HAL_RCC_SAI2_CLK_SLEEP_DISABLE +#define __SAI2_CLK_SLEEP_ENABLE __HAL_RCC_SAI2_CLK_SLEEP_ENABLE +#define __SAI2_FORCE_RESET __HAL_RCC_SAI2_FORCE_RESET +#define __SAI2_RELEASE_RESET __HAL_RCC_SAI2_RELEASE_RESET +#define __SDIO_CLK_DISABLE __HAL_RCC_SDIO_CLK_DISABLE +#define __SDIO_CLK_ENABLE __HAL_RCC_SDIO_CLK_ENABLE +#define __SDMMC_CLK_DISABLE __HAL_RCC_SDMMC_CLK_DISABLE +#define __SDMMC_CLK_ENABLE __HAL_RCC_SDMMC_CLK_ENABLE +#define __SDMMC_CLK_SLEEP_DISABLE __HAL_RCC_SDMMC_CLK_SLEEP_DISABLE +#define __SDMMC_CLK_SLEEP_ENABLE __HAL_RCC_SDMMC_CLK_SLEEP_ENABLE +#define __SDMMC_FORCE_RESET __HAL_RCC_SDMMC_FORCE_RESET +#define __SDMMC_RELEASE_RESET __HAL_RCC_SDMMC_RELEASE_RESET +#define __SPI1_CLK_DISABLE __HAL_RCC_SPI1_CLK_DISABLE +#define __SPI1_CLK_ENABLE __HAL_RCC_SPI1_CLK_ENABLE +#define __SPI1_CLK_SLEEP_DISABLE __HAL_RCC_SPI1_CLK_SLEEP_DISABLE +#define __SPI1_CLK_SLEEP_ENABLE __HAL_RCC_SPI1_CLK_SLEEP_ENABLE +#define __SPI1_FORCE_RESET __HAL_RCC_SPI1_FORCE_RESET +#define __SPI1_RELEASE_RESET __HAL_RCC_SPI1_RELEASE_RESET +#define __SPI2_CLK_DISABLE __HAL_RCC_SPI2_CLK_DISABLE +#define __SPI2_CLK_ENABLE __HAL_RCC_SPI2_CLK_ENABLE +#define __SPI2_CLK_SLEEP_DISABLE __HAL_RCC_SPI2_CLK_SLEEP_DISABLE +#define __SPI2_CLK_SLEEP_ENABLE __HAL_RCC_SPI2_CLK_SLEEP_ENABLE +#define __SPI2_FORCE_RESET __HAL_RCC_SPI2_FORCE_RESET +#define __SPI2_RELEASE_RESET __HAL_RCC_SPI2_RELEASE_RESET +#define __SPI3_CLK_DISABLE __HAL_RCC_SPI3_CLK_DISABLE +#define __SPI3_CLK_ENABLE __HAL_RCC_SPI3_CLK_ENABLE +#define __SPI3_CLK_SLEEP_DISABLE __HAL_RCC_SPI3_CLK_SLEEP_DISABLE +#define __SPI3_CLK_SLEEP_ENABLE __HAL_RCC_SPI3_CLK_SLEEP_ENABLE +#define __SPI3_FORCE_RESET __HAL_RCC_SPI3_FORCE_RESET +#define __SPI3_RELEASE_RESET __HAL_RCC_SPI3_RELEASE_RESET +#define __SRAM_CLK_DISABLE __HAL_RCC_SRAM_CLK_DISABLE +#define __SRAM_CLK_ENABLE __HAL_RCC_SRAM_CLK_ENABLE +#define __SRAM1_CLK_SLEEP_DISABLE __HAL_RCC_SRAM1_CLK_SLEEP_DISABLE +#define __SRAM1_CLK_SLEEP_ENABLE __HAL_RCC_SRAM1_CLK_SLEEP_ENABLE +#define __SRAM2_CLK_SLEEP_DISABLE __HAL_RCC_SRAM2_CLK_SLEEP_DISABLE +#define __SRAM2_CLK_SLEEP_ENABLE __HAL_RCC_SRAM2_CLK_SLEEP_ENABLE +#define __SWPMI1_CLK_DISABLE __HAL_RCC_SWPMI1_CLK_DISABLE +#define __SWPMI1_CLK_ENABLE __HAL_RCC_SWPMI1_CLK_ENABLE +#define __SWPMI1_CLK_SLEEP_DISABLE __HAL_RCC_SWPMI1_CLK_SLEEP_DISABLE +#define __SWPMI1_CLK_SLEEP_ENABLE __HAL_RCC_SWPMI1_CLK_SLEEP_ENABLE +#define __SWPMI1_FORCE_RESET __HAL_RCC_SWPMI1_FORCE_RESET +#define __SWPMI1_RELEASE_RESET __HAL_RCC_SWPMI1_RELEASE_RESET +#define __SYSCFG_CLK_DISABLE __HAL_RCC_SYSCFG_CLK_DISABLE +#define __SYSCFG_CLK_ENABLE __HAL_RCC_SYSCFG_CLK_ENABLE +#define __SYSCFG_CLK_SLEEP_DISABLE __HAL_RCC_SYSCFG_CLK_SLEEP_DISABLE +#define __SYSCFG_CLK_SLEEP_ENABLE __HAL_RCC_SYSCFG_CLK_SLEEP_ENABLE +#define __SYSCFG_FORCE_RESET __HAL_RCC_SYSCFG_FORCE_RESET +#define __SYSCFG_RELEASE_RESET __HAL_RCC_SYSCFG_RELEASE_RESET +#define __TIM1_CLK_DISABLE __HAL_RCC_TIM1_CLK_DISABLE +#define __TIM1_CLK_ENABLE __HAL_RCC_TIM1_CLK_ENABLE +#define __TIM1_CLK_SLEEP_DISABLE __HAL_RCC_TIM1_CLK_SLEEP_DISABLE +#define __TIM1_CLK_SLEEP_ENABLE __HAL_RCC_TIM1_CLK_SLEEP_ENABLE +#define __TIM1_FORCE_RESET __HAL_RCC_TIM1_FORCE_RESET +#define __TIM1_RELEASE_RESET __HAL_RCC_TIM1_RELEASE_RESET +#define __TIM10_CLK_DISABLE __HAL_RCC_TIM10_CLK_DISABLE +#define __TIM10_CLK_ENABLE __HAL_RCC_TIM10_CLK_ENABLE +#define __TIM10_FORCE_RESET __HAL_RCC_TIM10_FORCE_RESET +#define __TIM10_RELEASE_RESET __HAL_RCC_TIM10_RELEASE_RESET +#define __TIM11_CLK_DISABLE __HAL_RCC_TIM11_CLK_DISABLE +#define __TIM11_CLK_ENABLE __HAL_RCC_TIM11_CLK_ENABLE +#define __TIM11_FORCE_RESET __HAL_RCC_TIM11_FORCE_RESET +#define __TIM11_RELEASE_RESET __HAL_RCC_TIM11_RELEASE_RESET +#define __TIM12_CLK_DISABLE __HAL_RCC_TIM12_CLK_DISABLE +#define __TIM12_CLK_ENABLE __HAL_RCC_TIM12_CLK_ENABLE +#define __TIM12_FORCE_RESET __HAL_RCC_TIM12_FORCE_RESET +#define __TIM12_RELEASE_RESET __HAL_RCC_TIM12_RELEASE_RESET +#define __TIM13_CLK_DISABLE __HAL_RCC_TIM13_CLK_DISABLE +#define __TIM13_CLK_ENABLE __HAL_RCC_TIM13_CLK_ENABLE +#define __TIM13_FORCE_RESET __HAL_RCC_TIM13_FORCE_RESET +#define __TIM13_RELEASE_RESET __HAL_RCC_TIM13_RELEASE_RESET +#define __TIM14_CLK_DISABLE __HAL_RCC_TIM14_CLK_DISABLE +#define __TIM14_CLK_ENABLE __HAL_RCC_TIM14_CLK_ENABLE +#define __TIM14_FORCE_RESET __HAL_RCC_TIM14_FORCE_RESET +#define __TIM14_RELEASE_RESET __HAL_RCC_TIM14_RELEASE_RESET +#define __TIM15_CLK_DISABLE __HAL_RCC_TIM15_CLK_DISABLE +#define __TIM15_CLK_ENABLE __HAL_RCC_TIM15_CLK_ENABLE +#define __TIM15_CLK_SLEEP_DISABLE __HAL_RCC_TIM15_CLK_SLEEP_DISABLE +#define __TIM15_CLK_SLEEP_ENABLE __HAL_RCC_TIM15_CLK_SLEEP_ENABLE +#define __TIM15_FORCE_RESET __HAL_RCC_TIM15_FORCE_RESET +#define __TIM15_RELEASE_RESET __HAL_RCC_TIM15_RELEASE_RESET +#define __TIM16_CLK_DISABLE __HAL_RCC_TIM16_CLK_DISABLE +#define __TIM16_CLK_ENABLE __HAL_RCC_TIM16_CLK_ENABLE +#define __TIM16_CLK_SLEEP_DISABLE __HAL_RCC_TIM16_CLK_SLEEP_DISABLE +#define __TIM16_CLK_SLEEP_ENABLE __HAL_RCC_TIM16_CLK_SLEEP_ENABLE +#define __TIM16_FORCE_RESET __HAL_RCC_TIM16_FORCE_RESET +#define __TIM16_RELEASE_RESET __HAL_RCC_TIM16_RELEASE_RESET +#define __TIM17_CLK_DISABLE __HAL_RCC_TIM17_CLK_DISABLE +#define __TIM17_CLK_ENABLE __HAL_RCC_TIM17_CLK_ENABLE +#define __TIM17_CLK_SLEEP_DISABLE __HAL_RCC_TIM17_CLK_SLEEP_DISABLE +#define __TIM17_CLK_SLEEP_ENABLE __HAL_RCC_TIM17_CLK_SLEEP_ENABLE +#define __TIM17_FORCE_RESET __HAL_RCC_TIM17_FORCE_RESET +#define __TIM17_RELEASE_RESET __HAL_RCC_TIM17_RELEASE_RESET +#define __TIM2_CLK_DISABLE __HAL_RCC_TIM2_CLK_DISABLE +#define __TIM2_CLK_ENABLE __HAL_RCC_TIM2_CLK_ENABLE +#define __TIM2_CLK_SLEEP_DISABLE __HAL_RCC_TIM2_CLK_SLEEP_DISABLE +#define __TIM2_CLK_SLEEP_ENABLE __HAL_RCC_TIM2_CLK_SLEEP_ENABLE +#define __TIM2_FORCE_RESET __HAL_RCC_TIM2_FORCE_RESET +#define __TIM2_RELEASE_RESET __HAL_RCC_TIM2_RELEASE_RESET +#define __TIM3_CLK_DISABLE __HAL_RCC_TIM3_CLK_DISABLE +#define __TIM3_CLK_ENABLE __HAL_RCC_TIM3_CLK_ENABLE +#define __TIM3_CLK_SLEEP_DISABLE __HAL_RCC_TIM3_CLK_SLEEP_DISABLE +#define __TIM3_CLK_SLEEP_ENABLE __HAL_RCC_TIM3_CLK_SLEEP_ENABLE +#define __TIM3_FORCE_RESET __HAL_RCC_TIM3_FORCE_RESET +#define __TIM3_RELEASE_RESET __HAL_RCC_TIM3_RELEASE_RESET +#define __TIM4_CLK_DISABLE __HAL_RCC_TIM4_CLK_DISABLE +#define __TIM4_CLK_ENABLE __HAL_RCC_TIM4_CLK_ENABLE +#define __TIM4_CLK_SLEEP_DISABLE __HAL_RCC_TIM4_CLK_SLEEP_DISABLE +#define __TIM4_CLK_SLEEP_ENABLE __HAL_RCC_TIM4_CLK_SLEEP_ENABLE +#define __TIM4_FORCE_RESET __HAL_RCC_TIM4_FORCE_RESET +#define __TIM4_RELEASE_RESET __HAL_RCC_TIM4_RELEASE_RESET +#define __TIM5_CLK_DISABLE __HAL_RCC_TIM5_CLK_DISABLE +#define __TIM5_CLK_ENABLE __HAL_RCC_TIM5_CLK_ENABLE +#define __TIM5_CLK_SLEEP_DISABLE __HAL_RCC_TIM5_CLK_SLEEP_DISABLE +#define __TIM5_CLK_SLEEP_ENABLE __HAL_RCC_TIM5_CLK_SLEEP_ENABLE +#define __TIM5_FORCE_RESET __HAL_RCC_TIM5_FORCE_RESET +#define __TIM5_RELEASE_RESET __HAL_RCC_TIM5_RELEASE_RESET +#define __TIM6_CLK_DISABLE __HAL_RCC_TIM6_CLK_DISABLE +#define __TIM6_CLK_ENABLE __HAL_RCC_TIM6_CLK_ENABLE +#define __TIM6_CLK_SLEEP_DISABLE __HAL_RCC_TIM6_CLK_SLEEP_DISABLE +#define __TIM6_CLK_SLEEP_ENABLE __HAL_RCC_TIM6_CLK_SLEEP_ENABLE +#define __TIM6_FORCE_RESET __HAL_RCC_TIM6_FORCE_RESET +#define __TIM6_RELEASE_RESET __HAL_RCC_TIM6_RELEASE_RESET +#define __TIM7_CLK_DISABLE __HAL_RCC_TIM7_CLK_DISABLE +#define __TIM7_CLK_ENABLE __HAL_RCC_TIM7_CLK_ENABLE +#define __TIM7_CLK_SLEEP_DISABLE __HAL_RCC_TIM7_CLK_SLEEP_DISABLE +#define __TIM7_CLK_SLEEP_ENABLE __HAL_RCC_TIM7_CLK_SLEEP_ENABLE +#define __TIM7_FORCE_RESET __HAL_RCC_TIM7_FORCE_RESET +#define __TIM7_RELEASE_RESET __HAL_RCC_TIM7_RELEASE_RESET +#define __TIM8_CLK_DISABLE __HAL_RCC_TIM8_CLK_DISABLE +#define __TIM8_CLK_ENABLE __HAL_RCC_TIM8_CLK_ENABLE +#define __TIM8_CLK_SLEEP_DISABLE __HAL_RCC_TIM8_CLK_SLEEP_DISABLE +#define __TIM8_CLK_SLEEP_ENABLE __HAL_RCC_TIM8_CLK_SLEEP_ENABLE +#define __TIM8_FORCE_RESET __HAL_RCC_TIM8_FORCE_RESET +#define __TIM8_RELEASE_RESET __HAL_RCC_TIM8_RELEASE_RESET +#define __TIM9_CLK_DISABLE __HAL_RCC_TIM9_CLK_DISABLE +#define __TIM9_CLK_ENABLE __HAL_RCC_TIM9_CLK_ENABLE +#define __TIM9_FORCE_RESET __HAL_RCC_TIM9_FORCE_RESET +#define __TIM9_RELEASE_RESET __HAL_RCC_TIM9_RELEASE_RESET +#define __TSC_CLK_DISABLE __HAL_RCC_TSC_CLK_DISABLE +#define __TSC_CLK_ENABLE __HAL_RCC_TSC_CLK_ENABLE +#define __TSC_CLK_SLEEP_DISABLE __HAL_RCC_TSC_CLK_SLEEP_DISABLE +#define __TSC_CLK_SLEEP_ENABLE __HAL_RCC_TSC_CLK_SLEEP_ENABLE +#define __TSC_FORCE_RESET __HAL_RCC_TSC_FORCE_RESET +#define __TSC_RELEASE_RESET __HAL_RCC_TSC_RELEASE_RESET +#define __UART4_CLK_DISABLE __HAL_RCC_UART4_CLK_DISABLE +#define __UART4_CLK_ENABLE __HAL_RCC_UART4_CLK_ENABLE +#define __UART4_CLK_SLEEP_DISABLE __HAL_RCC_UART4_CLK_SLEEP_DISABLE +#define __UART4_CLK_SLEEP_ENABLE __HAL_RCC_UART4_CLK_SLEEP_ENABLE +#define __UART4_FORCE_RESET __HAL_RCC_UART4_FORCE_RESET +#define __UART4_RELEASE_RESET __HAL_RCC_UART4_RELEASE_RESET +#define __UART5_CLK_DISABLE __HAL_RCC_UART5_CLK_DISABLE +#define __UART5_CLK_ENABLE __HAL_RCC_UART5_CLK_ENABLE +#define __UART5_CLK_SLEEP_DISABLE __HAL_RCC_UART5_CLK_SLEEP_DISABLE +#define __UART5_CLK_SLEEP_ENABLE __HAL_RCC_UART5_CLK_SLEEP_ENABLE +#define __UART5_FORCE_RESET __HAL_RCC_UART5_FORCE_RESET +#define __UART5_RELEASE_RESET __HAL_RCC_UART5_RELEASE_RESET +#define __USART1_CLK_DISABLE __HAL_RCC_USART1_CLK_DISABLE +#define __USART1_CLK_ENABLE __HAL_RCC_USART1_CLK_ENABLE +#define __USART1_CLK_SLEEP_DISABLE __HAL_RCC_USART1_CLK_SLEEP_DISABLE +#define __USART1_CLK_SLEEP_ENABLE __HAL_RCC_USART1_CLK_SLEEP_ENABLE +#define __USART1_FORCE_RESET __HAL_RCC_USART1_FORCE_RESET +#define __USART1_RELEASE_RESET __HAL_RCC_USART1_RELEASE_RESET +#define __USART2_CLK_DISABLE __HAL_RCC_USART2_CLK_DISABLE +#define __USART2_CLK_ENABLE __HAL_RCC_USART2_CLK_ENABLE +#define __USART2_CLK_SLEEP_DISABLE __HAL_RCC_USART2_CLK_SLEEP_DISABLE +#define __USART2_CLK_SLEEP_ENABLE __HAL_RCC_USART2_CLK_SLEEP_ENABLE +#define __USART2_FORCE_RESET __HAL_RCC_USART2_FORCE_RESET +#define __USART2_RELEASE_RESET __HAL_RCC_USART2_RELEASE_RESET +#define __USART3_CLK_DISABLE __HAL_RCC_USART3_CLK_DISABLE +#define __USART3_CLK_ENABLE __HAL_RCC_USART3_CLK_ENABLE +#define __USART3_CLK_SLEEP_DISABLE __HAL_RCC_USART3_CLK_SLEEP_DISABLE +#define __USART3_CLK_SLEEP_ENABLE __HAL_RCC_USART3_CLK_SLEEP_ENABLE +#define __USART3_FORCE_RESET __HAL_RCC_USART3_FORCE_RESET +#define __USART3_RELEASE_RESET __HAL_RCC_USART3_RELEASE_RESET +#define __USART4_CLK_DISABLE __HAL_RCC_UART4_CLK_DISABLE +#define __USART4_CLK_ENABLE __HAL_RCC_UART4_CLK_ENABLE +#define __USART4_CLK_SLEEP_ENABLE __HAL_RCC_UART4_CLK_SLEEP_ENABLE +#define __USART4_CLK_SLEEP_DISABLE __HAL_RCC_UART4_CLK_SLEEP_DISABLE +#define __USART4_FORCE_RESET __HAL_RCC_UART4_FORCE_RESET +#define __USART4_RELEASE_RESET __HAL_RCC_UART4_RELEASE_RESET +#define __USART5_CLK_DISABLE __HAL_RCC_UART5_CLK_DISABLE +#define __USART5_CLK_ENABLE __HAL_RCC_UART5_CLK_ENABLE +#define __USART5_CLK_SLEEP_ENABLE __HAL_RCC_UART5_CLK_SLEEP_ENABLE +#define __USART5_CLK_SLEEP_DISABLE __HAL_RCC_UART5_CLK_SLEEP_DISABLE +#define __USART5_FORCE_RESET __HAL_RCC_UART5_FORCE_RESET +#define __USART5_RELEASE_RESET __HAL_RCC_UART5_RELEASE_RESET +#define __USART7_CLK_DISABLE __HAL_RCC_UART7_CLK_DISABLE +#define __USART7_CLK_ENABLE __HAL_RCC_UART7_CLK_ENABLE +#define __USART7_FORCE_RESET __HAL_RCC_UART7_FORCE_RESET +#define __USART7_RELEASE_RESET __HAL_RCC_UART7_RELEASE_RESET +#define __USART8_CLK_DISABLE __HAL_RCC_UART8_CLK_DISABLE +#define __USART8_CLK_ENABLE __HAL_RCC_UART8_CLK_ENABLE +#define __USART8_FORCE_RESET __HAL_RCC_UART8_FORCE_RESET +#define __USART8_RELEASE_RESET __HAL_RCC_UART8_RELEASE_RESET +#define __USB_CLK_DISABLE __HAL_RCC_USB_CLK_DISABLE +#define __USB_CLK_ENABLE __HAL_RCC_USB_CLK_ENABLE +#define __USB_FORCE_RESET __HAL_RCC_USB_FORCE_RESET +#define __USB_CLK_SLEEP_ENABLE __HAL_RCC_USB_CLK_SLEEP_ENABLE +#define __USB_CLK_SLEEP_DISABLE __HAL_RCC_USB_CLK_SLEEP_DISABLE +#define __USB_OTG_FS_CLK_DISABLE __HAL_RCC_USB_OTG_FS_CLK_DISABLE +#define __USB_OTG_FS_CLK_ENABLE __HAL_RCC_USB_OTG_FS_CLK_ENABLE +#define __USB_RELEASE_RESET __HAL_RCC_USB_RELEASE_RESET +#define __WWDG_CLK_DISABLE __HAL_RCC_WWDG_CLK_DISABLE +#define __WWDG_CLK_ENABLE __HAL_RCC_WWDG_CLK_ENABLE +#define __WWDG_CLK_SLEEP_DISABLE __HAL_RCC_WWDG_CLK_SLEEP_DISABLE +#define __WWDG_CLK_SLEEP_ENABLE __HAL_RCC_WWDG_CLK_SLEEP_ENABLE +#define __WWDG_FORCE_RESET __HAL_RCC_WWDG_FORCE_RESET +#define __WWDG_RELEASE_RESET __HAL_RCC_WWDG_RELEASE_RESET +#define __TIM21_CLK_ENABLE __HAL_RCC_TIM21_CLK_ENABLE +#define __TIM21_CLK_DISABLE __HAL_RCC_TIM21_CLK_DISABLE +#define __TIM21_FORCE_RESET __HAL_RCC_TIM21_FORCE_RESET +#define __TIM21_RELEASE_RESET __HAL_RCC_TIM21_RELEASE_RESET +#define __TIM21_CLK_SLEEP_ENABLE __HAL_RCC_TIM21_CLK_SLEEP_ENABLE +#define __TIM21_CLK_SLEEP_DISABLE __HAL_RCC_TIM21_CLK_SLEEP_DISABLE +#define __TIM22_CLK_ENABLE __HAL_RCC_TIM22_CLK_ENABLE +#define __TIM22_CLK_DISABLE __HAL_RCC_TIM22_CLK_DISABLE +#define __TIM22_FORCE_RESET __HAL_RCC_TIM22_FORCE_RESET +#define __TIM22_RELEASE_RESET __HAL_RCC_TIM22_RELEASE_RESET +#define __TIM22_CLK_SLEEP_ENABLE __HAL_RCC_TIM22_CLK_SLEEP_ENABLE +#define __TIM22_CLK_SLEEP_DISABLE __HAL_RCC_TIM22_CLK_SLEEP_DISABLE +#define __CRS_CLK_DISABLE __HAL_RCC_CRS_CLK_DISABLE +#define __CRS_CLK_ENABLE __HAL_RCC_CRS_CLK_ENABLE +#define __CRS_CLK_SLEEP_DISABLE __HAL_RCC_CRS_CLK_SLEEP_DISABLE +#define __CRS_CLK_SLEEP_ENABLE __HAL_RCC_CRS_CLK_SLEEP_ENABLE +#define __CRS_FORCE_RESET __HAL_RCC_CRS_FORCE_RESET +#define __CRS_RELEASE_RESET __HAL_RCC_CRS_RELEASE_RESET +#define __RCC_BACKUPRESET_FORCE __HAL_RCC_BACKUPRESET_FORCE +#define __RCC_BACKUPRESET_RELEASE __HAL_RCC_BACKUPRESET_RELEASE + +#define __USB_OTG_FS_FORCE_RESET __HAL_RCC_USB_OTG_FS_FORCE_RESET +#define __USB_OTG_FS_RELEASE_RESET __HAL_RCC_USB_OTG_FS_RELEASE_RESET +#define __USB_OTG_FS_CLK_SLEEP_ENABLE __HAL_RCC_USB_OTG_FS_CLK_SLEEP_ENABLE +#define __USB_OTG_FS_CLK_SLEEP_DISABLE __HAL_RCC_USB_OTG_FS_CLK_SLEEP_DISABLE +#define __USB_OTG_HS_CLK_DISABLE __HAL_RCC_USB_OTG_HS_CLK_DISABLE +#define __USB_OTG_HS_CLK_ENABLE __HAL_RCC_USB_OTG_HS_CLK_ENABLE +#define __USB_OTG_HS_ULPI_CLK_ENABLE __HAL_RCC_USB_OTG_HS_ULPI_CLK_ENABLE +#define __USB_OTG_HS_ULPI_CLK_DISABLE __HAL_RCC_USB_OTG_HS_ULPI_CLK_DISABLE +#define __TIM9_CLK_SLEEP_ENABLE __HAL_RCC_TIM9_CLK_SLEEP_ENABLE +#define __TIM9_CLK_SLEEP_DISABLE __HAL_RCC_TIM9_CLK_SLEEP_DISABLE +#define __TIM10_CLK_SLEEP_ENABLE __HAL_RCC_TIM10_CLK_SLEEP_ENABLE +#define __TIM10_CLK_SLEEP_DISABLE __HAL_RCC_TIM10_CLK_SLEEP_DISABLE +#define __TIM11_CLK_SLEEP_ENABLE __HAL_RCC_TIM11_CLK_SLEEP_ENABLE +#define __TIM11_CLK_SLEEP_DISABLE __HAL_RCC_TIM11_CLK_SLEEP_DISABLE +#define __ETHMACPTP_CLK_SLEEP_ENABLE __HAL_RCC_ETHMACPTP_CLK_SLEEP_ENABLE +#define __ETHMACPTP_CLK_SLEEP_DISABLE __HAL_RCC_ETHMACPTP_CLK_SLEEP_DISABLE +#define __ETHMACPTP_CLK_ENABLE __HAL_RCC_ETHMACPTP_CLK_ENABLE +#define __ETHMACPTP_CLK_DISABLE __HAL_RCC_ETHMACPTP_CLK_DISABLE +#define __HASH_CLK_ENABLE __HAL_RCC_HASH_CLK_ENABLE +#define __HASH_FORCE_RESET __HAL_RCC_HASH_FORCE_RESET +#define __HASH_RELEASE_RESET __HAL_RCC_HASH_RELEASE_RESET +#define __HASH_CLK_SLEEP_ENABLE __HAL_RCC_HASH_CLK_SLEEP_ENABLE +#define __HASH_CLK_SLEEP_DISABLE __HAL_RCC_HASH_CLK_SLEEP_DISABLE +#define __HASH_CLK_DISABLE __HAL_RCC_HASH_CLK_DISABLE +#define __SPI5_CLK_ENABLE __HAL_RCC_SPI5_CLK_ENABLE +#define __SPI5_CLK_DISABLE __HAL_RCC_SPI5_CLK_DISABLE +#define __SPI5_FORCE_RESET __HAL_RCC_SPI5_FORCE_RESET +#define __SPI5_RELEASE_RESET __HAL_RCC_SPI5_RELEASE_RESET +#define __SPI5_CLK_SLEEP_ENABLE __HAL_RCC_SPI5_CLK_SLEEP_ENABLE +#define __SPI5_CLK_SLEEP_DISABLE __HAL_RCC_SPI5_CLK_SLEEP_DISABLE +#define __SPI6_CLK_ENABLE __HAL_RCC_SPI6_CLK_ENABLE +#define __SPI6_CLK_DISABLE __HAL_RCC_SPI6_CLK_DISABLE +#define __SPI6_FORCE_RESET __HAL_RCC_SPI6_FORCE_RESET +#define __SPI6_RELEASE_RESET __HAL_RCC_SPI6_RELEASE_RESET +#define __SPI6_CLK_SLEEP_ENABLE __HAL_RCC_SPI6_CLK_SLEEP_ENABLE +#define __SPI6_CLK_SLEEP_DISABLE __HAL_RCC_SPI6_CLK_SLEEP_DISABLE +#define __LTDC_CLK_ENABLE __HAL_RCC_LTDC_CLK_ENABLE +#define __LTDC_CLK_DISABLE __HAL_RCC_LTDC_CLK_DISABLE +#define __LTDC_FORCE_RESET __HAL_RCC_LTDC_FORCE_RESET +#define __LTDC_RELEASE_RESET __HAL_RCC_LTDC_RELEASE_RESET +#define __LTDC_CLK_SLEEP_ENABLE __HAL_RCC_LTDC_CLK_SLEEP_ENABLE +#define __ETHMAC_CLK_SLEEP_ENABLE __HAL_RCC_ETHMAC_CLK_SLEEP_ENABLE +#define __ETHMAC_CLK_SLEEP_DISABLE __HAL_RCC_ETHMAC_CLK_SLEEP_DISABLE +#define __ETHMACTX_CLK_SLEEP_ENABLE __HAL_RCC_ETHMACTX_CLK_SLEEP_ENABLE +#define __ETHMACTX_CLK_SLEEP_DISABLE __HAL_RCC_ETHMACTX_CLK_SLEEP_DISABLE +#define __ETHMACRX_CLK_SLEEP_ENABLE __HAL_RCC_ETHMACRX_CLK_SLEEP_ENABLE +#define __ETHMACRX_CLK_SLEEP_DISABLE __HAL_RCC_ETHMACRX_CLK_SLEEP_DISABLE +#define __TIM12_CLK_SLEEP_ENABLE __HAL_RCC_TIM12_CLK_SLEEP_ENABLE +#define __TIM12_CLK_SLEEP_DISABLE __HAL_RCC_TIM12_CLK_SLEEP_DISABLE +#define __TIM13_CLK_SLEEP_ENABLE __HAL_RCC_TIM13_CLK_SLEEP_ENABLE +#define __TIM13_CLK_SLEEP_DISABLE __HAL_RCC_TIM13_CLK_SLEEP_DISABLE +#define __TIM14_CLK_SLEEP_ENABLE __HAL_RCC_TIM14_CLK_SLEEP_ENABLE +#define __TIM14_CLK_SLEEP_DISABLE __HAL_RCC_TIM14_CLK_SLEEP_DISABLE +#define __BKPSRAM_CLK_ENABLE __HAL_RCC_BKPSRAM_CLK_ENABLE +#define __BKPSRAM_CLK_DISABLE __HAL_RCC_BKPSRAM_CLK_DISABLE +#define __BKPSRAM_CLK_SLEEP_ENABLE __HAL_RCC_BKPSRAM_CLK_SLEEP_ENABLE +#define __BKPSRAM_CLK_SLEEP_DISABLE __HAL_RCC_BKPSRAM_CLK_SLEEP_DISABLE +#define __CCMDATARAMEN_CLK_ENABLE __HAL_RCC_CCMDATARAMEN_CLK_ENABLE +#define __CCMDATARAMEN_CLK_DISABLE __HAL_RCC_CCMDATARAMEN_CLK_DISABLE +#define __USART6_CLK_ENABLE __HAL_RCC_USART6_CLK_ENABLE +#define __USART6_CLK_DISABLE __HAL_RCC_USART6_CLK_DISABLE +#define __USART6_FORCE_RESET __HAL_RCC_USART6_FORCE_RESET +#define __USART6_RELEASE_RESET __HAL_RCC_USART6_RELEASE_RESET +#define __USART6_CLK_SLEEP_ENABLE __HAL_RCC_USART6_CLK_SLEEP_ENABLE +#define __USART6_CLK_SLEEP_DISABLE __HAL_RCC_USART6_CLK_SLEEP_DISABLE +#define __SPI4_CLK_ENABLE __HAL_RCC_SPI4_CLK_ENABLE +#define __SPI4_CLK_DISABLE __HAL_RCC_SPI4_CLK_DISABLE +#define __SPI4_FORCE_RESET __HAL_RCC_SPI4_FORCE_RESET +#define __SPI4_RELEASE_RESET __HAL_RCC_SPI4_RELEASE_RESET +#define __SPI4_CLK_SLEEP_ENABLE __HAL_RCC_SPI4_CLK_SLEEP_ENABLE +#define __SPI4_CLK_SLEEP_DISABLE __HAL_RCC_SPI4_CLK_SLEEP_DISABLE +#define __GPIOI_CLK_ENABLE __HAL_RCC_GPIOI_CLK_ENABLE +#define __GPIOI_CLK_DISABLE __HAL_RCC_GPIOI_CLK_DISABLE +#define __GPIOI_FORCE_RESET __HAL_RCC_GPIOI_FORCE_RESET +#define __GPIOI_RELEASE_RESET __HAL_RCC_GPIOI_RELEASE_RESET +#define __GPIOI_CLK_SLEEP_ENABLE __HAL_RCC_GPIOI_CLK_SLEEP_ENABLE +#define __GPIOI_CLK_SLEEP_DISABLE __HAL_RCC_GPIOI_CLK_SLEEP_DISABLE +#define __GPIOJ_CLK_ENABLE __HAL_RCC_GPIOJ_CLK_ENABLE +#define __GPIOJ_CLK_DISABLE __HAL_RCC_GPIOJ_CLK_DISABLE +#define __GPIOJ_FORCE_RESET __HAL_RCC_GPIOJ_FORCE_RESET +#define __GPIOJ_RELEASE_RESET __HAL_RCC_GPIOJ_RELEASE_RESET +#define __GPIOJ_CLK_SLEEP_ENABLE __HAL_RCC_GPIOJ_CLK_SLEEP_ENABLE +#define __GPIOJ_CLK_SLEEP_DISABLE __HAL_RCC_GPIOJ_CLK_SLEEP_DISABLE +#define __GPIOK_CLK_ENABLE __HAL_RCC_GPIOK_CLK_ENABLE +#define __GPIOK_CLK_DISABLE __HAL_RCC_GPIOK_CLK_DISABLE +#define __GPIOK_RELEASE_RESET __HAL_RCC_GPIOK_RELEASE_RESET +#define __GPIOK_CLK_SLEEP_ENABLE __HAL_RCC_GPIOK_CLK_SLEEP_ENABLE +#define __GPIOK_CLK_SLEEP_DISABLE __HAL_RCC_GPIOK_CLK_SLEEP_DISABLE +#define __ETH_CLK_ENABLE __HAL_RCC_ETH_CLK_ENABLE +#define __ETH_CLK_DISABLE __HAL_RCC_ETH_CLK_DISABLE +#define __DCMI_CLK_ENABLE __HAL_RCC_DCMI_CLK_ENABLE +#define __DCMI_CLK_DISABLE __HAL_RCC_DCMI_CLK_DISABLE +#define __DCMI_FORCE_RESET __HAL_RCC_DCMI_FORCE_RESET +#define __DCMI_RELEASE_RESET __HAL_RCC_DCMI_RELEASE_RESET +#define __DCMI_CLK_SLEEP_ENABLE __HAL_RCC_DCMI_CLK_SLEEP_ENABLE +#define __DCMI_CLK_SLEEP_DISABLE __HAL_RCC_DCMI_CLK_SLEEP_DISABLE +#define __UART7_CLK_ENABLE __HAL_RCC_UART7_CLK_ENABLE +#define __UART7_CLK_DISABLE __HAL_RCC_UART7_CLK_DISABLE +#define __UART7_RELEASE_RESET __HAL_RCC_UART7_RELEASE_RESET +#define __UART7_FORCE_RESET __HAL_RCC_UART7_FORCE_RESET +#define __UART7_CLK_SLEEP_ENABLE __HAL_RCC_UART7_CLK_SLEEP_ENABLE +#define __UART7_CLK_SLEEP_DISABLE __HAL_RCC_UART7_CLK_SLEEP_DISABLE +#define __UART8_CLK_ENABLE __HAL_RCC_UART8_CLK_ENABLE +#define __UART8_CLK_DISABLE __HAL_RCC_UART8_CLK_DISABLE +#define __UART8_FORCE_RESET __HAL_RCC_UART8_FORCE_RESET +#define __UART8_RELEASE_RESET __HAL_RCC_UART8_RELEASE_RESET +#define __UART8_CLK_SLEEP_ENABLE __HAL_RCC_UART8_CLK_SLEEP_ENABLE +#define __UART8_CLK_SLEEP_DISABLE __HAL_RCC_UART8_CLK_SLEEP_DISABLE +#define __OTGHS_CLK_SLEEP_ENABLE __HAL_RCC_USB_OTG_HS_CLK_SLEEP_ENABLE +#define __OTGHS_CLK_SLEEP_DISABLE __HAL_RCC_USB_OTG_HS_CLK_SLEEP_DISABLE +#define __OTGHS_FORCE_RESET __HAL_RCC_USB_OTG_HS_FORCE_RESET +#define __OTGHS_RELEASE_RESET __HAL_RCC_USB_OTG_HS_RELEASE_RESET +#define __OTGHSULPI_CLK_SLEEP_ENABLE __HAL_RCC_USB_OTG_HS_ULPI_CLK_SLEEP_ENABLE +#define __OTGHSULPI_CLK_SLEEP_DISABLE __HAL_RCC_USB_OTG_HS_ULPI_CLK_SLEEP_DISABLE +#define __HAL_RCC_OTGHS_CLK_SLEEP_ENABLE __HAL_RCC_USB_OTG_HS_CLK_SLEEP_ENABLE +#define __HAL_RCC_OTGHS_CLK_SLEEP_DISABLE __HAL_RCC_USB_OTG_HS_CLK_SLEEP_DISABLE +#define __HAL_RCC_OTGHS_IS_CLK_SLEEP_ENABLED __HAL_RCC_USB_OTG_HS_IS_CLK_SLEEP_ENABLED +#define __HAL_RCC_OTGHS_IS_CLK_SLEEP_DISABLED __HAL_RCC_USB_OTG_HS_IS_CLK_SLEEP_DISABLED +#define __HAL_RCC_OTGHS_FORCE_RESET __HAL_RCC_USB_OTG_HS_FORCE_RESET +#define __HAL_RCC_OTGHS_RELEASE_RESET __HAL_RCC_USB_OTG_HS_RELEASE_RESET +#define __HAL_RCC_OTGHSULPI_CLK_SLEEP_ENABLE __HAL_RCC_USB_OTG_HS_ULPI_CLK_SLEEP_ENABLE +#define __HAL_RCC_OTGHSULPI_CLK_SLEEP_DISABLE __HAL_RCC_USB_OTG_HS_ULPI_CLK_SLEEP_DISABLE +#define __HAL_RCC_OTGHSULPI_IS_CLK_SLEEP_ENABLED __HAL_RCC_USB_OTG_HS_ULPI_IS_CLK_SLEEP_ENABLED +#define __HAL_RCC_OTGHSULPI_IS_CLK_SLEEP_DISABLED __HAL_RCC_USB_OTG_HS_ULPI_IS_CLK_SLEEP_DISABLED +#define __SRAM3_CLK_SLEEP_ENABLE __HAL_RCC_SRAM3_CLK_SLEEP_ENABLE +#define __CAN2_CLK_SLEEP_ENABLE __HAL_RCC_CAN2_CLK_SLEEP_ENABLE +#define __CAN2_CLK_SLEEP_DISABLE __HAL_RCC_CAN2_CLK_SLEEP_DISABLE +#define __DAC_CLK_SLEEP_ENABLE __HAL_RCC_DAC_CLK_SLEEP_ENABLE +#define __DAC_CLK_SLEEP_DISABLE __HAL_RCC_DAC_CLK_SLEEP_DISABLE +#define __ADC2_CLK_SLEEP_ENABLE __HAL_RCC_ADC2_CLK_SLEEP_ENABLE +#define __ADC2_CLK_SLEEP_DISABLE __HAL_RCC_ADC2_CLK_SLEEP_DISABLE +#define __ADC3_CLK_SLEEP_ENABLE __HAL_RCC_ADC3_CLK_SLEEP_ENABLE +#define __ADC3_CLK_SLEEP_DISABLE __HAL_RCC_ADC3_CLK_SLEEP_DISABLE +#define __FSMC_FORCE_RESET __HAL_RCC_FSMC_FORCE_RESET +#define __FSMC_RELEASE_RESET __HAL_RCC_FSMC_RELEASE_RESET +#define __FSMC_CLK_SLEEP_ENABLE __HAL_RCC_FSMC_CLK_SLEEP_ENABLE +#define __FSMC_CLK_SLEEP_DISABLE __HAL_RCC_FSMC_CLK_SLEEP_DISABLE +#define __SDIO_FORCE_RESET __HAL_RCC_SDIO_FORCE_RESET +#define __SDIO_RELEASE_RESET __HAL_RCC_SDIO_RELEASE_RESET +#define __SDIO_CLK_SLEEP_DISABLE __HAL_RCC_SDIO_CLK_SLEEP_DISABLE +#define __SDIO_CLK_SLEEP_ENABLE __HAL_RCC_SDIO_CLK_SLEEP_ENABLE +#define __DMA2D_CLK_ENABLE __HAL_RCC_DMA2D_CLK_ENABLE +#define __DMA2D_CLK_DISABLE __HAL_RCC_DMA2D_CLK_DISABLE +#define __DMA2D_FORCE_RESET __HAL_RCC_DMA2D_FORCE_RESET +#define __DMA2D_RELEASE_RESET __HAL_RCC_DMA2D_RELEASE_RESET +#define __DMA2D_CLK_SLEEP_ENABLE __HAL_RCC_DMA2D_CLK_SLEEP_ENABLE +#define __DMA2D_CLK_SLEEP_DISABLE __HAL_RCC_DMA2D_CLK_SLEEP_DISABLE + +/* alias define maintained for legacy */ +#define __HAL_RCC_OTGFS_FORCE_RESET __HAL_RCC_USB_OTG_FS_FORCE_RESET +#define __HAL_RCC_OTGFS_RELEASE_RESET __HAL_RCC_USB_OTG_FS_RELEASE_RESET + +#define __ADC12_CLK_ENABLE __HAL_RCC_ADC12_CLK_ENABLE +#define __ADC12_CLK_DISABLE __HAL_RCC_ADC12_CLK_DISABLE +#define __ADC34_CLK_ENABLE __HAL_RCC_ADC34_CLK_ENABLE +#define __ADC34_CLK_DISABLE __HAL_RCC_ADC34_CLK_DISABLE +#define __DAC2_CLK_ENABLE __HAL_RCC_DAC2_CLK_ENABLE +#define __DAC2_CLK_DISABLE __HAL_RCC_DAC2_CLK_DISABLE +#define __TIM18_CLK_ENABLE __HAL_RCC_TIM18_CLK_ENABLE +#define __TIM18_CLK_DISABLE __HAL_RCC_TIM18_CLK_DISABLE +#define __TIM19_CLK_ENABLE __HAL_RCC_TIM19_CLK_ENABLE +#define __TIM19_CLK_DISABLE __HAL_RCC_TIM19_CLK_DISABLE +#define __TIM20_CLK_ENABLE __HAL_RCC_TIM20_CLK_ENABLE +#define __TIM20_CLK_DISABLE __HAL_RCC_TIM20_CLK_DISABLE +#define __HRTIM1_CLK_ENABLE __HAL_RCC_HRTIM1_CLK_ENABLE +#define __HRTIM1_CLK_DISABLE __HAL_RCC_HRTIM1_CLK_DISABLE +#define __SDADC1_CLK_ENABLE __HAL_RCC_SDADC1_CLK_ENABLE +#define __SDADC2_CLK_ENABLE __HAL_RCC_SDADC2_CLK_ENABLE +#define __SDADC3_CLK_ENABLE __HAL_RCC_SDADC3_CLK_ENABLE +#define __SDADC1_CLK_DISABLE __HAL_RCC_SDADC1_CLK_DISABLE +#define __SDADC2_CLK_DISABLE __HAL_RCC_SDADC2_CLK_DISABLE +#define __SDADC3_CLK_DISABLE __HAL_RCC_SDADC3_CLK_DISABLE + +#define __ADC12_FORCE_RESET __HAL_RCC_ADC12_FORCE_RESET +#define __ADC12_RELEASE_RESET __HAL_RCC_ADC12_RELEASE_RESET +#define __ADC34_FORCE_RESET __HAL_RCC_ADC34_FORCE_RESET +#define __ADC34_RELEASE_RESET __HAL_RCC_ADC34_RELEASE_RESET +#define __DAC2_FORCE_RESET __HAL_RCC_DAC2_FORCE_RESET +#define __DAC2_RELEASE_RESET __HAL_RCC_DAC2_RELEASE_RESET +#define __TIM18_FORCE_RESET __HAL_RCC_TIM18_FORCE_RESET +#define __TIM18_RELEASE_RESET __HAL_RCC_TIM18_RELEASE_RESET +#define __TIM19_FORCE_RESET __HAL_RCC_TIM19_FORCE_RESET +#define __TIM19_RELEASE_RESET __HAL_RCC_TIM19_RELEASE_RESET +#define __TIM20_FORCE_RESET __HAL_RCC_TIM20_FORCE_RESET +#define __TIM20_RELEASE_RESET __HAL_RCC_TIM20_RELEASE_RESET +#define __HRTIM1_FORCE_RESET __HAL_RCC_HRTIM1_FORCE_RESET +#define __HRTIM1_RELEASE_RESET __HAL_RCC_HRTIM1_RELEASE_RESET +#define __SDADC1_FORCE_RESET __HAL_RCC_SDADC1_FORCE_RESET +#define __SDADC2_FORCE_RESET __HAL_RCC_SDADC2_FORCE_RESET +#define __SDADC3_FORCE_RESET __HAL_RCC_SDADC3_FORCE_RESET +#define __SDADC1_RELEASE_RESET __HAL_RCC_SDADC1_RELEASE_RESET +#define __SDADC2_RELEASE_RESET __HAL_RCC_SDADC2_RELEASE_RESET +#define __SDADC3_RELEASE_RESET __HAL_RCC_SDADC3_RELEASE_RESET + +#define __ADC1_IS_CLK_ENABLED __HAL_RCC_ADC1_IS_CLK_ENABLED +#define __ADC1_IS_CLK_DISABLED __HAL_RCC_ADC1_IS_CLK_DISABLED +#define __ADC12_IS_CLK_ENABLED __HAL_RCC_ADC12_IS_CLK_ENABLED +#define __ADC12_IS_CLK_DISABLED __HAL_RCC_ADC12_IS_CLK_DISABLED +#define __ADC34_IS_CLK_ENABLED __HAL_RCC_ADC34_IS_CLK_ENABLED +#define __ADC34_IS_CLK_DISABLED __HAL_RCC_ADC34_IS_CLK_DISABLED +#define __CEC_IS_CLK_ENABLED __HAL_RCC_CEC_IS_CLK_ENABLED +#define __CEC_IS_CLK_DISABLED __HAL_RCC_CEC_IS_CLK_DISABLED +#define __CRC_IS_CLK_ENABLED __HAL_RCC_CRC_IS_CLK_ENABLED +#define __CRC_IS_CLK_DISABLED __HAL_RCC_CRC_IS_CLK_DISABLED +#define __DAC1_IS_CLK_ENABLED __HAL_RCC_DAC1_IS_CLK_ENABLED +#define __DAC1_IS_CLK_DISABLED __HAL_RCC_DAC1_IS_CLK_DISABLED +#define __DAC2_IS_CLK_ENABLED __HAL_RCC_DAC2_IS_CLK_ENABLED +#define __DAC2_IS_CLK_DISABLED __HAL_RCC_DAC2_IS_CLK_DISABLED +#define __DMA1_IS_CLK_ENABLED __HAL_RCC_DMA1_IS_CLK_ENABLED +#define __DMA1_IS_CLK_DISABLED __HAL_RCC_DMA1_IS_CLK_DISABLED +#define __DMA2_IS_CLK_ENABLED __HAL_RCC_DMA2_IS_CLK_ENABLED +#define __DMA2_IS_CLK_DISABLED __HAL_RCC_DMA2_IS_CLK_DISABLED +#define __FLITF_IS_CLK_ENABLED __HAL_RCC_FLITF_IS_CLK_ENABLED +#define __FLITF_IS_CLK_DISABLED __HAL_RCC_FLITF_IS_CLK_DISABLED +#define __FMC_IS_CLK_ENABLED __HAL_RCC_FMC_IS_CLK_ENABLED +#define __FMC_IS_CLK_DISABLED __HAL_RCC_FMC_IS_CLK_DISABLED +#define __GPIOA_IS_CLK_ENABLED __HAL_RCC_GPIOA_IS_CLK_ENABLED +#define __GPIOA_IS_CLK_DISABLED __HAL_RCC_GPIOA_IS_CLK_DISABLED +#define __GPIOB_IS_CLK_ENABLED __HAL_RCC_GPIOB_IS_CLK_ENABLED +#define __GPIOB_IS_CLK_DISABLED __HAL_RCC_GPIOB_IS_CLK_DISABLED +#define __GPIOC_IS_CLK_ENABLED __HAL_RCC_GPIOC_IS_CLK_ENABLED +#define __GPIOC_IS_CLK_DISABLED __HAL_RCC_GPIOC_IS_CLK_DISABLED +#define __GPIOD_IS_CLK_ENABLED __HAL_RCC_GPIOD_IS_CLK_ENABLED +#define __GPIOD_IS_CLK_DISABLED __HAL_RCC_GPIOD_IS_CLK_DISABLED +#define __GPIOE_IS_CLK_ENABLED __HAL_RCC_GPIOE_IS_CLK_ENABLED +#define __GPIOE_IS_CLK_DISABLED __HAL_RCC_GPIOE_IS_CLK_DISABLED +#define __GPIOF_IS_CLK_ENABLED __HAL_RCC_GPIOF_IS_CLK_ENABLED +#define __GPIOF_IS_CLK_DISABLED __HAL_RCC_GPIOF_IS_CLK_DISABLED +#define __GPIOG_IS_CLK_ENABLED __HAL_RCC_GPIOG_IS_CLK_ENABLED +#define __GPIOG_IS_CLK_DISABLED __HAL_RCC_GPIOG_IS_CLK_DISABLED +#define __GPIOH_IS_CLK_ENABLED __HAL_RCC_GPIOH_IS_CLK_ENABLED +#define __GPIOH_IS_CLK_DISABLED __HAL_RCC_GPIOH_IS_CLK_DISABLED +#define __HRTIM1_IS_CLK_ENABLED __HAL_RCC_HRTIM1_IS_CLK_ENABLED +#define __HRTIM1_IS_CLK_DISABLED __HAL_RCC_HRTIM1_IS_CLK_DISABLED +#define __I2C1_IS_CLK_ENABLED __HAL_RCC_I2C1_IS_CLK_ENABLED +#define __I2C1_IS_CLK_DISABLED __HAL_RCC_I2C1_IS_CLK_DISABLED +#define __I2C2_IS_CLK_ENABLED __HAL_RCC_I2C2_IS_CLK_ENABLED +#define __I2C2_IS_CLK_DISABLED __HAL_RCC_I2C2_IS_CLK_DISABLED +#define __I2C3_IS_CLK_ENABLED __HAL_RCC_I2C3_IS_CLK_ENABLED +#define __I2C3_IS_CLK_DISABLED __HAL_RCC_I2C3_IS_CLK_DISABLED +#define __PWR_IS_CLK_ENABLED __HAL_RCC_PWR_IS_CLK_ENABLED +#define __PWR_IS_CLK_DISABLED __HAL_RCC_PWR_IS_CLK_DISABLED +#define __SYSCFG_IS_CLK_ENABLED __HAL_RCC_SYSCFG_IS_CLK_ENABLED +#define __SYSCFG_IS_CLK_DISABLED __HAL_RCC_SYSCFG_IS_CLK_DISABLED +#define __SPI1_IS_CLK_ENABLED __HAL_RCC_SPI1_IS_CLK_ENABLED +#define __SPI1_IS_CLK_DISABLED __HAL_RCC_SPI1_IS_CLK_DISABLED +#define __SPI2_IS_CLK_ENABLED __HAL_RCC_SPI2_IS_CLK_ENABLED +#define __SPI2_IS_CLK_DISABLED __HAL_RCC_SPI2_IS_CLK_DISABLED +#define __SPI3_IS_CLK_ENABLED __HAL_RCC_SPI3_IS_CLK_ENABLED +#define __SPI3_IS_CLK_DISABLED __HAL_RCC_SPI3_IS_CLK_DISABLED +#define __SPI4_IS_CLK_ENABLED __HAL_RCC_SPI4_IS_CLK_ENABLED +#define __SPI4_IS_CLK_DISABLED __HAL_RCC_SPI4_IS_CLK_DISABLED +#define __SDADC1_IS_CLK_ENABLED __HAL_RCC_SDADC1_IS_CLK_ENABLED +#define __SDADC1_IS_CLK_DISABLED __HAL_RCC_SDADC1_IS_CLK_DISABLED +#define __SDADC2_IS_CLK_ENABLED __HAL_RCC_SDADC2_IS_CLK_ENABLED +#define __SDADC2_IS_CLK_DISABLED __HAL_RCC_SDADC2_IS_CLK_DISABLED +#define __SDADC3_IS_CLK_ENABLED __HAL_RCC_SDADC3_IS_CLK_ENABLED +#define __SDADC3_IS_CLK_DISABLED __HAL_RCC_SDADC3_IS_CLK_DISABLED +#define __SRAM_IS_CLK_ENABLED __HAL_RCC_SRAM_IS_CLK_ENABLED +#define __SRAM_IS_CLK_DISABLED __HAL_RCC_SRAM_IS_CLK_DISABLED +#define __TIM1_IS_CLK_ENABLED __HAL_RCC_TIM1_IS_CLK_ENABLED +#define __TIM1_IS_CLK_DISABLED __HAL_RCC_TIM1_IS_CLK_DISABLED +#define __TIM2_IS_CLK_ENABLED __HAL_RCC_TIM2_IS_CLK_ENABLED +#define __TIM2_IS_CLK_DISABLED __HAL_RCC_TIM2_IS_CLK_DISABLED +#define __TIM3_IS_CLK_ENABLED __HAL_RCC_TIM3_IS_CLK_ENABLED +#define __TIM3_IS_CLK_DISABLED __HAL_RCC_TIM3_IS_CLK_DISABLED +#define __TIM4_IS_CLK_ENABLED __HAL_RCC_TIM4_IS_CLK_ENABLED +#define __TIM4_IS_CLK_DISABLED __HAL_RCC_TIM4_IS_CLK_DISABLED +#define __TIM5_IS_CLK_ENABLED __HAL_RCC_TIM5_IS_CLK_ENABLED +#define __TIM5_IS_CLK_DISABLED __HAL_RCC_TIM5_IS_CLK_DISABLED +#define __TIM6_IS_CLK_ENABLED __HAL_RCC_TIM6_IS_CLK_ENABLED +#define __TIM6_IS_CLK_DISABLED __HAL_RCC_TIM6_IS_CLK_DISABLED +#define __TIM7_IS_CLK_ENABLED __HAL_RCC_TIM7_IS_CLK_ENABLED +#define __TIM7_IS_CLK_DISABLED __HAL_RCC_TIM7_IS_CLK_DISABLED +#define __TIM8_IS_CLK_ENABLED __HAL_RCC_TIM8_IS_CLK_ENABLED +#define __TIM8_IS_CLK_DISABLED __HAL_RCC_TIM8_IS_CLK_DISABLED +#define __TIM12_IS_CLK_ENABLED __HAL_RCC_TIM12_IS_CLK_ENABLED +#define __TIM12_IS_CLK_DISABLED __HAL_RCC_TIM12_IS_CLK_DISABLED +#define __TIM13_IS_CLK_ENABLED __HAL_RCC_TIM13_IS_CLK_ENABLED +#define __TIM13_IS_CLK_DISABLED __HAL_RCC_TIM13_IS_CLK_DISABLED +#define __TIM14_IS_CLK_ENABLED __HAL_RCC_TIM14_IS_CLK_ENABLED +#define __TIM14_IS_CLK_DISABLED __HAL_RCC_TIM14_IS_CLK_DISABLED +#define __TIM15_IS_CLK_ENABLED __HAL_RCC_TIM15_IS_CLK_ENABLED +#define __TIM15_IS_CLK_DISABLED __HAL_RCC_TIM15_IS_CLK_DISABLED +#define __TIM16_IS_CLK_ENABLED __HAL_RCC_TIM16_IS_CLK_ENABLED +#define __TIM16_IS_CLK_DISABLED __HAL_RCC_TIM16_IS_CLK_DISABLED +#define __TIM17_IS_CLK_ENABLED __HAL_RCC_TIM17_IS_CLK_ENABLED +#define __TIM17_IS_CLK_DISABLED __HAL_RCC_TIM17_IS_CLK_DISABLED +#define __TIM18_IS_CLK_ENABLED __HAL_RCC_TIM18_IS_CLK_ENABLED +#define __TIM18_IS_CLK_DISABLED __HAL_RCC_TIM18_IS_CLK_DISABLED +#define __TIM19_IS_CLK_ENABLED __HAL_RCC_TIM19_IS_CLK_ENABLED +#define __TIM19_IS_CLK_DISABLED __HAL_RCC_TIM19_IS_CLK_DISABLED +#define __TIM20_IS_CLK_ENABLED __HAL_RCC_TIM20_IS_CLK_ENABLED +#define __TIM20_IS_CLK_DISABLED __HAL_RCC_TIM20_IS_CLK_DISABLED +#define __TSC_IS_CLK_ENABLED __HAL_RCC_TSC_IS_CLK_ENABLED +#define __TSC_IS_CLK_DISABLED __HAL_RCC_TSC_IS_CLK_DISABLED +#define __UART4_IS_CLK_ENABLED __HAL_RCC_UART4_IS_CLK_ENABLED +#define __UART4_IS_CLK_DISABLED __HAL_RCC_UART4_IS_CLK_DISABLED +#define __UART5_IS_CLK_ENABLED __HAL_RCC_UART5_IS_CLK_ENABLED +#define __UART5_IS_CLK_DISABLED __HAL_RCC_UART5_IS_CLK_DISABLED +#define __USART1_IS_CLK_ENABLED __HAL_RCC_USART1_IS_CLK_ENABLED +#define __USART1_IS_CLK_DISABLED __HAL_RCC_USART1_IS_CLK_DISABLED +#define __USART2_IS_CLK_ENABLED __HAL_RCC_USART2_IS_CLK_ENABLED +#define __USART2_IS_CLK_DISABLED __HAL_RCC_USART2_IS_CLK_DISABLED +#define __USART3_IS_CLK_ENABLED __HAL_RCC_USART3_IS_CLK_ENABLED +#define __USART3_IS_CLK_DISABLED __HAL_RCC_USART3_IS_CLK_DISABLED +#define __USB_IS_CLK_ENABLED __HAL_RCC_USB_IS_CLK_ENABLED +#define __USB_IS_CLK_DISABLED __HAL_RCC_USB_IS_CLK_DISABLED +#define __WWDG_IS_CLK_ENABLED __HAL_RCC_WWDG_IS_CLK_ENABLED +#define __WWDG_IS_CLK_DISABLED __HAL_RCC_WWDG_IS_CLK_DISABLED + +#if defined(STM32F4) +#define __HAL_RCC_SDMMC1_FORCE_RESET __HAL_RCC_SDIO_FORCE_RESET +#define __HAL_RCC_SDMMC1_RELEASE_RESET __HAL_RCC_SDIO_RELEASE_RESET +#define __HAL_RCC_SDMMC1_CLK_SLEEP_ENABLE __HAL_RCC_SDIO_CLK_SLEEP_ENABLE +#define __HAL_RCC_SDMMC1_CLK_SLEEP_DISABLE __HAL_RCC_SDIO_CLK_SLEEP_DISABLE +#define __HAL_RCC_SDMMC1_CLK_ENABLE __HAL_RCC_SDIO_CLK_ENABLE +#define __HAL_RCC_SDMMC1_CLK_DISABLE __HAL_RCC_SDIO_CLK_DISABLE +#define __HAL_RCC_SDMMC1_IS_CLK_ENABLED __HAL_RCC_SDIO_IS_CLK_ENABLED +#define __HAL_RCC_SDMMC1_IS_CLK_DISABLED __HAL_RCC_SDIO_IS_CLK_DISABLED +#define Sdmmc1ClockSelection SdioClockSelection +#define RCC_PERIPHCLK_SDMMC1 RCC_PERIPHCLK_SDIO +#define RCC_SDMMC1CLKSOURCE_CLK48 RCC_SDIOCLKSOURCE_CK48 +#define RCC_SDMMC1CLKSOURCE_SYSCLK RCC_SDIOCLKSOURCE_SYSCLK +#define __HAL_RCC_SDMMC1_CONFIG __HAL_RCC_SDIO_CONFIG +#define __HAL_RCC_GET_SDMMC1_SOURCE __HAL_RCC_GET_SDIO_SOURCE +#endif + +#if defined(STM32F7) || defined(STM32L4) +#define __HAL_RCC_SDIO_FORCE_RESET __HAL_RCC_SDMMC1_FORCE_RESET +#define __HAL_RCC_SDIO_RELEASE_RESET __HAL_RCC_SDMMC1_RELEASE_RESET +#define __HAL_RCC_SDIO_CLK_SLEEP_ENABLE __HAL_RCC_SDMMC1_CLK_SLEEP_ENABLE +#define __HAL_RCC_SDIO_CLK_SLEEP_DISABLE __HAL_RCC_SDMMC1_CLK_SLEEP_DISABLE +#define __HAL_RCC_SDIO_CLK_ENABLE __HAL_RCC_SDMMC1_CLK_ENABLE +#define __HAL_RCC_SDIO_CLK_DISABLE __HAL_RCC_SDMMC1_CLK_DISABLE +#define __HAL_RCC_SDIO_IS_CLK_ENABLED __HAL_RCC_SDMMC1_IS_CLK_ENABLED +#define __HAL_RCC_SDIO_IS_CLK_DISABLED __HAL_RCC_SDMMC1_IS_CLK_DISABLED +#define SdioClockSelection Sdmmc1ClockSelection +#define RCC_PERIPHCLK_SDIO RCC_PERIPHCLK_SDMMC1 +#define __HAL_RCC_SDIO_CONFIG __HAL_RCC_SDMMC1_CONFIG +#define __HAL_RCC_GET_SDIO_SOURCE __HAL_RCC_GET_SDMMC1_SOURCE +#endif + +#if defined(STM32F7) +#define RCC_SDIOCLKSOURCE_CLK48 RCC_SDMMC1CLKSOURCE_CLK48 +#define RCC_SDIOCLKSOURCE_SYSCLK RCC_SDMMC1CLKSOURCE_SYSCLK +#endif + +#if defined(STM32H7) +#define __HAL_RCC_USB_OTG_HS_CLK_ENABLE() __HAL_RCC_USB1_OTG_HS_CLK_ENABLE() +#define __HAL_RCC_USB_OTG_HS_ULPI_CLK_ENABLE() __HAL_RCC_USB1_OTG_HS_ULPI_CLK_ENABLE() +#define __HAL_RCC_USB_OTG_HS_CLK_DISABLE() __HAL_RCC_USB1_OTG_HS_CLK_DISABLE() +#define __HAL_RCC_USB_OTG_HS_ULPI_CLK_DISABLE() __HAL_RCC_USB1_OTG_HS_ULPI_CLK_DISABLE() +#define __HAL_RCC_USB_OTG_HS_FORCE_RESET() __HAL_RCC_USB1_OTG_HS_FORCE_RESET() +#define __HAL_RCC_USB_OTG_HS_RELEASE_RESET() __HAL_RCC_USB1_OTG_HS_RELEASE_RESET() +#define __HAL_RCC_USB_OTG_HS_CLK_SLEEP_ENABLE() __HAL_RCC_USB1_OTG_HS_CLK_SLEEP_ENABLE() +#define __HAL_RCC_USB_OTG_HS_ULPI_CLK_SLEEP_ENABLE() __HAL_RCC_USB1_OTG_HS_ULPI_CLK_SLEEP_ENABLE() +#define __HAL_RCC_USB_OTG_HS_CLK_SLEEP_DISABLE() __HAL_RCC_USB1_OTG_HS_CLK_SLEEP_DISABLE() +#define __HAL_RCC_USB_OTG_HS_ULPI_CLK_SLEEP_DISABLE() __HAL_RCC_USB1_OTG_HS_ULPI_CLK_SLEEP_DISABLE() + +#define __HAL_RCC_USB_OTG_FS_CLK_ENABLE() __HAL_RCC_USB2_OTG_FS_CLK_ENABLE() +#define __HAL_RCC_USB_OTG_FS_ULPI_CLK_ENABLE() __HAL_RCC_USB2_OTG_FS_ULPI_CLK_ENABLE() +#define __HAL_RCC_USB_OTG_FS_CLK_DISABLE() __HAL_RCC_USB2_OTG_FS_CLK_DISABLE() +#define __HAL_RCC_USB_OTG_FS_ULPI_CLK_DISABLE() __HAL_RCC_USB2_OTG_FS_ULPI_CLK_DISABLE() +#define __HAL_RCC_USB_OTG_FS_FORCE_RESET() __HAL_RCC_USB2_OTG_FS_FORCE_RESET() +#define __HAL_RCC_USB_OTG_FS_RELEASE_RESET() __HAL_RCC_USB2_OTG_FS_RELEASE_RESET() +#define __HAL_RCC_USB_OTG_FS_CLK_SLEEP_ENABLE() __HAL_RCC_USB2_OTG_FS_CLK_SLEEP_ENABLE() +#define __HAL_RCC_USB_OTG_FS_ULPI_CLK_SLEEP_ENABLE() __HAL_RCC_USB2_OTG_FS_ULPI_CLK_SLEEP_ENABLE() +#define __HAL_RCC_USB_OTG_FS_CLK_SLEEP_DISABLE() __HAL_RCC_USB2_OTG_FS_CLK_SLEEP_DISABLE() +#define __HAL_RCC_USB_OTG_FS_ULPI_CLK_SLEEP_DISABLE() __HAL_RCC_USB2_OTG_FS_ULPI_CLK_SLEEP_DISABLE() +#endif + +#define __HAL_RCC_I2SCLK __HAL_RCC_I2S_CONFIG +#define __HAL_RCC_I2SCLK_CONFIG __HAL_RCC_I2S_CONFIG + +#define __RCC_PLLSRC RCC_GET_PLL_OSCSOURCE + +#define IS_RCC_MSIRANGE IS_RCC_MSI_CLOCK_RANGE +#define IS_RCC_RTCCLK_SOURCE IS_RCC_RTCCLKSOURCE +#define IS_RCC_SYSCLK_DIV IS_RCC_HCLK +#define IS_RCC_HCLK_DIV IS_RCC_PCLK +#define IS_RCC_PERIPHCLK IS_RCC_PERIPHCLOCK + +#define RCC_IT_HSI14 RCC_IT_HSI14RDY + +#define RCC_IT_CSSLSE RCC_IT_LSECSS +#define RCC_IT_CSSHSE RCC_IT_CSS + +#define RCC_PLLMUL_3 RCC_PLL_MUL3 +#define RCC_PLLMUL_4 RCC_PLL_MUL4 +#define RCC_PLLMUL_6 RCC_PLL_MUL6 +#define RCC_PLLMUL_8 RCC_PLL_MUL8 +#define RCC_PLLMUL_12 RCC_PLL_MUL12 +#define RCC_PLLMUL_16 RCC_PLL_MUL16 +#define RCC_PLLMUL_24 RCC_PLL_MUL24 +#define RCC_PLLMUL_32 RCC_PLL_MUL32 +#define RCC_PLLMUL_48 RCC_PLL_MUL48 + +#define RCC_PLLDIV_2 RCC_PLL_DIV2 +#define RCC_PLLDIV_3 RCC_PLL_DIV3 +#define RCC_PLLDIV_4 RCC_PLL_DIV4 + +#define IS_RCC_MCOSOURCE IS_RCC_MCO1SOURCE +#define __HAL_RCC_MCO_CONFIG __HAL_RCC_MCO1_CONFIG +#define RCC_MCO_NODIV RCC_MCODIV_1 +#define RCC_MCO_DIV1 RCC_MCODIV_1 +#define RCC_MCO_DIV2 RCC_MCODIV_2 +#define RCC_MCO_DIV4 RCC_MCODIV_4 +#define RCC_MCO_DIV8 RCC_MCODIV_8 +#define RCC_MCO_DIV16 RCC_MCODIV_16 +#define RCC_MCO_DIV32 RCC_MCODIV_32 +#define RCC_MCO_DIV64 RCC_MCODIV_64 +#define RCC_MCO_DIV128 RCC_MCODIV_128 +#define RCC_MCOSOURCE_NONE RCC_MCO1SOURCE_NOCLOCK +#define RCC_MCOSOURCE_LSI RCC_MCO1SOURCE_LSI +#define RCC_MCOSOURCE_LSE RCC_MCO1SOURCE_LSE +#define RCC_MCOSOURCE_SYSCLK RCC_MCO1SOURCE_SYSCLK +#define RCC_MCOSOURCE_HSI RCC_MCO1SOURCE_HSI +#define RCC_MCOSOURCE_HSI14 RCC_MCO1SOURCE_HSI14 +#define RCC_MCOSOURCE_HSI48 RCC_MCO1SOURCE_HSI48 +#define RCC_MCOSOURCE_HSE RCC_MCO1SOURCE_HSE +#define RCC_MCOSOURCE_PLLCLK_DIV1 RCC_MCO1SOURCE_PLLCLK +#define RCC_MCOSOURCE_PLLCLK_NODIV RCC_MCO1SOURCE_PLLCLK +#define RCC_MCOSOURCE_PLLCLK_DIV2 RCC_MCO1SOURCE_PLLCLK_DIV2 + +#if defined(STM32L4) +#define RCC_RTCCLKSOURCE_NO_CLK RCC_RTCCLKSOURCE_NONE +#elif defined(STM32WB) || defined(STM32G0) +#else +#define RCC_RTCCLKSOURCE_NONE RCC_RTCCLKSOURCE_NO_CLK +#endif + +#define RCC_USBCLK_PLLSAI1 RCC_USBCLKSOURCE_PLLSAI1 +#define RCC_USBCLK_PLL RCC_USBCLKSOURCE_PLL +#define RCC_USBCLK_MSI RCC_USBCLKSOURCE_MSI +#define RCC_USBCLKSOURCE_PLLCLK RCC_USBCLKSOURCE_PLL +#define RCC_USBPLLCLK_DIV1 RCC_USBCLKSOURCE_PLL +#define RCC_USBPLLCLK_DIV1_5 RCC_USBCLKSOURCE_PLL_DIV1_5 +#define RCC_USBPLLCLK_DIV2 RCC_USBCLKSOURCE_PLL_DIV2 +#define RCC_USBPLLCLK_DIV3 RCC_USBCLKSOURCE_PLL_DIV3 + +#define HSION_BitNumber RCC_HSION_BIT_NUMBER +#define HSION_BITNUMBER RCC_HSION_BIT_NUMBER +#define HSEON_BitNumber RCC_HSEON_BIT_NUMBER +#define HSEON_BITNUMBER RCC_HSEON_BIT_NUMBER +#define MSION_BITNUMBER RCC_MSION_BIT_NUMBER +#define CSSON_BitNumber RCC_CSSON_BIT_NUMBER +#define CSSON_BITNUMBER RCC_CSSON_BIT_NUMBER +#define PLLON_BitNumber RCC_PLLON_BIT_NUMBER +#define PLLON_BITNUMBER RCC_PLLON_BIT_NUMBER +#define PLLI2SON_BitNumber RCC_PLLI2SON_BIT_NUMBER +#define I2SSRC_BitNumber RCC_I2SSRC_BIT_NUMBER +#define RTCEN_BitNumber RCC_RTCEN_BIT_NUMBER +#define RTCEN_BITNUMBER RCC_RTCEN_BIT_NUMBER +#define BDRST_BitNumber RCC_BDRST_BIT_NUMBER +#define BDRST_BITNUMBER RCC_BDRST_BIT_NUMBER +#define RTCRST_BITNUMBER RCC_RTCRST_BIT_NUMBER +#define LSION_BitNumber RCC_LSION_BIT_NUMBER +#define LSION_BITNUMBER RCC_LSION_BIT_NUMBER +#define LSEON_BitNumber RCC_LSEON_BIT_NUMBER +#define LSEON_BITNUMBER RCC_LSEON_BIT_NUMBER +#define LSEBYP_BITNUMBER RCC_LSEBYP_BIT_NUMBER +#define PLLSAION_BitNumber RCC_PLLSAION_BIT_NUMBER +#define TIMPRE_BitNumber RCC_TIMPRE_BIT_NUMBER +#define RMVF_BitNumber RCC_RMVF_BIT_NUMBER +#define RMVF_BITNUMBER RCC_RMVF_BIT_NUMBER +#define RCC_CR2_HSI14TRIM_BitNumber RCC_HSI14TRIM_BIT_NUMBER +#define CR_BYTE2_ADDRESS RCC_CR_BYTE2_ADDRESS +#define CIR_BYTE1_ADDRESS RCC_CIR_BYTE1_ADDRESS +#define CIR_BYTE2_ADDRESS RCC_CIR_BYTE2_ADDRESS +#define BDCR_BYTE0_ADDRESS RCC_BDCR_BYTE0_ADDRESS +#define DBP_TIMEOUT_VALUE RCC_DBP_TIMEOUT_VALUE +#define LSE_TIMEOUT_VALUE RCC_LSE_TIMEOUT_VALUE + +#define CR_HSION_BB RCC_CR_HSION_BB +#define CR_CSSON_BB RCC_CR_CSSON_BB +#define CR_PLLON_BB RCC_CR_PLLON_BB +#define CR_PLLI2SON_BB RCC_CR_PLLI2SON_BB +#define CR_MSION_BB RCC_CR_MSION_BB +#define CSR_LSION_BB RCC_CSR_LSION_BB +#define CSR_LSEON_BB RCC_CSR_LSEON_BB +#define CSR_LSEBYP_BB RCC_CSR_LSEBYP_BB +#define CSR_RTCEN_BB RCC_CSR_RTCEN_BB +#define CSR_RTCRST_BB RCC_CSR_RTCRST_BB +#define CFGR_I2SSRC_BB RCC_CFGR_I2SSRC_BB +#define BDCR_RTCEN_BB RCC_BDCR_RTCEN_BB +#define BDCR_BDRST_BB RCC_BDCR_BDRST_BB +#define CR_HSEON_BB RCC_CR_HSEON_BB +#define CSR_RMVF_BB RCC_CSR_RMVF_BB +#define CR_PLLSAION_BB RCC_CR_PLLSAION_BB +#define DCKCFGR_TIMPRE_BB RCC_DCKCFGR_TIMPRE_BB + +#define __HAL_RCC_CRS_ENABLE_FREQ_ERROR_COUNTER __HAL_RCC_CRS_FREQ_ERROR_COUNTER_ENABLE +#define __HAL_RCC_CRS_DISABLE_FREQ_ERROR_COUNTER __HAL_RCC_CRS_FREQ_ERROR_COUNTER_DISABLE +#define __HAL_RCC_CRS_ENABLE_AUTOMATIC_CALIB __HAL_RCC_CRS_AUTOMATIC_CALIB_ENABLE +#define __HAL_RCC_CRS_DISABLE_AUTOMATIC_CALIB __HAL_RCC_CRS_AUTOMATIC_CALIB_DISABLE +#define __HAL_RCC_CRS_CALCULATE_RELOADVALUE __HAL_RCC_CRS_RELOADVALUE_CALCULATE + +#define __HAL_RCC_GET_IT_SOURCE __HAL_RCC_GET_IT + +#define RCC_CRS_SYNCWARM RCC_CRS_SYNCWARN +#define RCC_CRS_TRIMOV RCC_CRS_TRIMOVF + +#define RCC_PERIPHCLK_CK48 RCC_PERIPHCLK_CLK48 +#define RCC_CK48CLKSOURCE_PLLQ RCC_CLK48CLKSOURCE_PLLQ +#define RCC_CK48CLKSOURCE_PLLSAIP RCC_CLK48CLKSOURCE_PLLSAIP +#define RCC_CK48CLKSOURCE_PLLI2SQ RCC_CLK48CLKSOURCE_PLLI2SQ +#define IS_RCC_CK48CLKSOURCE IS_RCC_CLK48CLKSOURCE +#define RCC_SDIOCLKSOURCE_CK48 RCC_SDIOCLKSOURCE_CLK48 + +#define __HAL_RCC_DFSDM_CLK_ENABLE __HAL_RCC_DFSDM1_CLK_ENABLE +#define __HAL_RCC_DFSDM_CLK_DISABLE __HAL_RCC_DFSDM1_CLK_DISABLE +#define __HAL_RCC_DFSDM_IS_CLK_ENABLED __HAL_RCC_DFSDM1_IS_CLK_ENABLED +#define __HAL_RCC_DFSDM_IS_CLK_DISABLED __HAL_RCC_DFSDM1_IS_CLK_DISABLED +#define __HAL_RCC_DFSDM_FORCE_RESET __HAL_RCC_DFSDM1_FORCE_RESET +#define __HAL_RCC_DFSDM_RELEASE_RESET __HAL_RCC_DFSDM1_RELEASE_RESET +#define __HAL_RCC_DFSDM_CLK_SLEEP_ENABLE __HAL_RCC_DFSDM1_CLK_SLEEP_ENABLE +#define __HAL_RCC_DFSDM_CLK_SLEEP_DISABLE __HAL_RCC_DFSDM1_CLK_SLEEP_DISABLE +#define __HAL_RCC_DFSDM_IS_CLK_SLEEP_ENABLED __HAL_RCC_DFSDM1_IS_CLK_SLEEP_ENABLED +#define __HAL_RCC_DFSDM_IS_CLK_SLEEP_DISABLED __HAL_RCC_DFSDM1_IS_CLK_SLEEP_DISABLED +#define DfsdmClockSelection Dfsdm1ClockSelection +#define RCC_PERIPHCLK_DFSDM RCC_PERIPHCLK_DFSDM1 +#define RCC_DFSDMCLKSOURCE_PCLK RCC_DFSDM1CLKSOURCE_PCLK2 +#define RCC_DFSDMCLKSOURCE_SYSCLK RCC_DFSDM1CLKSOURCE_SYSCLK +#define __HAL_RCC_DFSDM_CONFIG __HAL_RCC_DFSDM1_CONFIG +#define __HAL_RCC_GET_DFSDM_SOURCE __HAL_RCC_GET_DFSDM1_SOURCE +#define RCC_DFSDM1CLKSOURCE_PCLK RCC_DFSDM1CLKSOURCE_PCLK2 +#define RCC_SWPMI1CLKSOURCE_PCLK RCC_SWPMI1CLKSOURCE_PCLK1 +#define RCC_LPTIM1CLKSOURCE_PCLK RCC_LPTIM1CLKSOURCE_PCLK1 +#define RCC_LPTIM2CLKSOURCE_PCLK RCC_LPTIM2CLKSOURCE_PCLK1 + +#define RCC_DFSDM1AUDIOCLKSOURCE_I2SAPB1 RCC_DFSDM1AUDIOCLKSOURCE_I2S1 +#define RCC_DFSDM1AUDIOCLKSOURCE_I2SAPB2 RCC_DFSDM1AUDIOCLKSOURCE_I2S2 +#define RCC_DFSDM2AUDIOCLKSOURCE_I2SAPB1 RCC_DFSDM2AUDIOCLKSOURCE_I2S1 +#define RCC_DFSDM2AUDIOCLKSOURCE_I2SAPB2 RCC_DFSDM2AUDIOCLKSOURCE_I2S2 +#define RCC_DFSDM1CLKSOURCE_APB2 RCC_DFSDM1CLKSOURCE_PCLK2 +#define RCC_DFSDM2CLKSOURCE_APB2 RCC_DFSDM2CLKSOURCE_PCLK2 +#define RCC_FMPI2C1CLKSOURCE_APB RCC_FMPI2C1CLKSOURCE_PCLK1 + +/** + * @} + */ + +/** @defgroup HAL_RNG_Aliased_Macros HAL RNG Aliased Macros maintained for legacy purpose + * @{ + */ +#define HAL_RNG_ReadyCallback(__HANDLE__) HAL_RNG_ReadyDataCallback((__HANDLE__), uint32_t random32bit) + +/** + * @} + */ + +/** @defgroup HAL_RTC_Aliased_Macros HAL RTC Aliased Macros maintained for legacy purpose + * @{ + */ +#if defined (STM32G0) +#else +#define __HAL_RTC_CLEAR_FLAG __HAL_RTC_EXTI_CLEAR_FLAG +#endif +#define __HAL_RTC_DISABLE_IT __HAL_RTC_EXTI_DISABLE_IT +#define __HAL_RTC_ENABLE_IT __HAL_RTC_EXTI_ENABLE_IT + +#if defined (STM32F1) +#define __HAL_RTC_EXTI_CLEAR_FLAG(RTC_EXTI_LINE_ALARM_EVENT) __HAL_RTC_ALARM_EXTI_CLEAR_FLAG() + +#define __HAL_RTC_EXTI_ENABLE_IT(RTC_EXTI_LINE_ALARM_EVENT) __HAL_RTC_ALARM_EXTI_ENABLE_IT() + +#define __HAL_RTC_EXTI_DISABLE_IT(RTC_EXTI_LINE_ALARM_EVENT) __HAL_RTC_ALARM_EXTI_DISABLE_IT() + +#define __HAL_RTC_EXTI_GET_FLAG(RTC_EXTI_LINE_ALARM_EVENT) __HAL_RTC_ALARM_EXTI_GET_FLAG() + +#define __HAL_RTC_EXTI_GENERATE_SWIT(RTC_EXTI_LINE_ALARM_EVENT) __HAL_RTC_ALARM_EXTI_GENERATE_SWIT() +#else +#define __HAL_RTC_EXTI_CLEAR_FLAG(__EXTI_LINE__) (((__EXTI_LINE__) == RTC_EXTI_LINE_ALARM_EVENT) ? __HAL_RTC_ALARM_EXTI_CLEAR_FLAG() : \ + (((__EXTI_LINE__) == RTC_EXTI_LINE_WAKEUPTIMER_EVENT) ? __HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG() : \ + __HAL_RTC_TAMPER_TIMESTAMP_EXTI_CLEAR_FLAG())) +#define __HAL_RTC_EXTI_ENABLE_IT(__EXTI_LINE__) (((__EXTI_LINE__) == RTC_EXTI_LINE_ALARM_EVENT) ? __HAL_RTC_ALARM_EXTI_ENABLE_IT() : \ + (((__EXTI_LINE__) == RTC_EXTI_LINE_WAKEUPTIMER_EVENT) ? __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_IT() : \ + __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_IT())) +#define __HAL_RTC_EXTI_DISABLE_IT(__EXTI_LINE__) (((__EXTI_LINE__) == RTC_EXTI_LINE_ALARM_EVENT) ? __HAL_RTC_ALARM_EXTI_DISABLE_IT() : \ + (((__EXTI_LINE__) == RTC_EXTI_LINE_WAKEUPTIMER_EVENT) ? __HAL_RTC_WAKEUPTIMER_EXTI_DISABLE_IT() : \ + __HAL_RTC_TAMPER_TIMESTAMP_EXTI_DISABLE_IT())) +#define __HAL_RTC_EXTI_GET_FLAG(__EXTI_LINE__) (((__EXTI_LINE__) == RTC_EXTI_LINE_ALARM_EVENT) ? __HAL_RTC_ALARM_EXTI_GET_FLAG() : \ + (((__EXTI_LINE__) == RTC_EXTI_LINE_WAKEUPTIMER_EVENT) ? __HAL_RTC_WAKEUPTIMER_EXTI_GET_FLAG() : \ + __HAL_RTC_TAMPER_TIMESTAMP_EXTI_GET_FLAG())) +#define __HAL_RTC_EXTI_GENERATE_SWIT(__EXTI_LINE__) (((__EXTI_LINE__) == RTC_EXTI_LINE_ALARM_EVENT) ? __HAL_RTC_ALARM_EXTI_GENERATE_SWIT() : \ + (((__EXTI_LINE__) == RTC_EXTI_LINE_WAKEUPTIMER_EVENT) ? __HAL_RTC_WAKEUPTIMER_EXTI_GENERATE_SWIT() : \ + __HAL_RTC_TAMPER_TIMESTAMP_EXTI_GENERATE_SWIT())) +#endif /* STM32F1 */ + +#define IS_ALARM IS_RTC_ALARM +#define IS_ALARM_MASK IS_RTC_ALARM_MASK +#define IS_TAMPER IS_RTC_TAMPER +#define IS_TAMPER_ERASE_MODE IS_RTC_TAMPER_ERASE_MODE +#define IS_TAMPER_FILTER IS_RTC_TAMPER_FILTER +#define IS_TAMPER_INTERRUPT IS_RTC_TAMPER_INTERRUPT +#define IS_TAMPER_MASKFLAG_STATE IS_RTC_TAMPER_MASKFLAG_STATE +#define IS_TAMPER_PRECHARGE_DURATION IS_RTC_TAMPER_PRECHARGE_DURATION +#define IS_TAMPER_PULLUP_STATE IS_RTC_TAMPER_PULLUP_STATE +#define IS_TAMPER_SAMPLING_FREQ IS_RTC_TAMPER_SAMPLING_FREQ +#define IS_TAMPER_TIMESTAMPONTAMPER_DETECTION IS_RTC_TAMPER_TIMESTAMPONTAMPER_DETECTION +#define IS_TAMPER_TRIGGER IS_RTC_TAMPER_TRIGGER +#define IS_WAKEUP_CLOCK IS_RTC_WAKEUP_CLOCK +#define IS_WAKEUP_COUNTER IS_RTC_WAKEUP_COUNTER + +#define __RTC_WRITEPROTECTION_ENABLE __HAL_RTC_WRITEPROTECTION_ENABLE +#define __RTC_WRITEPROTECTION_DISABLE __HAL_RTC_WRITEPROTECTION_DISABLE + +/** + * @} + */ + +/** @defgroup HAL_SD_Aliased_Macros HAL SD Aliased Macros maintained for legacy purpose + * @{ + */ + +#define SD_OCR_CID_CSD_OVERWRIETE SD_OCR_CID_CSD_OVERWRITE +#define SD_CMD_SD_APP_STAUS SD_CMD_SD_APP_STATUS + +#if defined(STM32F4) || defined(STM32F2) +#define SD_SDMMC_DISABLED SD_SDIO_DISABLED +#define SD_SDMMC_FUNCTION_BUSY SD_SDIO_FUNCTION_BUSY +#define SD_SDMMC_FUNCTION_FAILED SD_SDIO_FUNCTION_FAILED +#define SD_SDMMC_UNKNOWN_FUNCTION SD_SDIO_UNKNOWN_FUNCTION +#define SD_CMD_SDMMC_SEN_OP_COND SD_CMD_SDIO_SEN_OP_COND +#define SD_CMD_SDMMC_RW_DIRECT SD_CMD_SDIO_RW_DIRECT +#define SD_CMD_SDMMC_RW_EXTENDED SD_CMD_SDIO_RW_EXTENDED +#define __HAL_SD_SDMMC_ENABLE __HAL_SD_SDIO_ENABLE +#define __HAL_SD_SDMMC_DISABLE __HAL_SD_SDIO_DISABLE +#define __HAL_SD_SDMMC_DMA_ENABLE __HAL_SD_SDIO_DMA_ENABLE +#define __HAL_SD_SDMMC_DMA_DISABLE __HAL_SD_SDIO_DMA_DISABL +#define __HAL_SD_SDMMC_ENABLE_IT __HAL_SD_SDIO_ENABLE_IT +#define __HAL_SD_SDMMC_DISABLE_IT __HAL_SD_SDIO_DISABLE_IT +#define __HAL_SD_SDMMC_GET_FLAG __HAL_SD_SDIO_GET_FLAG +#define __HAL_SD_SDMMC_CLEAR_FLAG __HAL_SD_SDIO_CLEAR_FLAG +#define __HAL_SD_SDMMC_GET_IT __HAL_SD_SDIO_GET_IT +#define __HAL_SD_SDMMC_CLEAR_IT __HAL_SD_SDIO_CLEAR_IT +#define SDMMC_STATIC_FLAGS SDIO_STATIC_FLAGS +#define SDMMC_CMD0TIMEOUT SDIO_CMD0TIMEOUT +#define SD_SDMMC_SEND_IF_COND SD_SDIO_SEND_IF_COND +/* alias CMSIS */ +#define SDMMC1_IRQn SDIO_IRQn +#define SDMMC1_IRQHandler SDIO_IRQHandler +#endif + +#if defined(STM32F7) || defined(STM32L4) +#define SD_SDIO_DISABLED SD_SDMMC_DISABLED +#define SD_SDIO_FUNCTION_BUSY SD_SDMMC_FUNCTION_BUSY +#define SD_SDIO_FUNCTION_FAILED SD_SDMMC_FUNCTION_FAILED +#define SD_SDIO_UNKNOWN_FUNCTION SD_SDMMC_UNKNOWN_FUNCTION +#define SD_CMD_SDIO_SEN_OP_COND SD_CMD_SDMMC_SEN_OP_COND +#define SD_CMD_SDIO_RW_DIRECT SD_CMD_SDMMC_RW_DIRECT +#define SD_CMD_SDIO_RW_EXTENDED SD_CMD_SDMMC_RW_EXTENDED +#define __HAL_SD_SDIO_ENABLE __HAL_SD_SDMMC_ENABLE +#define __HAL_SD_SDIO_DISABLE __HAL_SD_SDMMC_DISABLE +#define __HAL_SD_SDIO_DMA_ENABLE __HAL_SD_SDMMC_DMA_ENABLE +#define __HAL_SD_SDIO_DMA_DISABL __HAL_SD_SDMMC_DMA_DISABLE +#define __HAL_SD_SDIO_ENABLE_IT __HAL_SD_SDMMC_ENABLE_IT +#define __HAL_SD_SDIO_DISABLE_IT __HAL_SD_SDMMC_DISABLE_IT +#define __HAL_SD_SDIO_GET_FLAG __HAL_SD_SDMMC_GET_FLAG +#define __HAL_SD_SDIO_CLEAR_FLAG __HAL_SD_SDMMC_CLEAR_FLAG +#define __HAL_SD_SDIO_GET_IT __HAL_SD_SDMMC_GET_IT +#define __HAL_SD_SDIO_CLEAR_IT __HAL_SD_SDMMC_CLEAR_IT +#define SDIO_STATIC_FLAGS SDMMC_STATIC_FLAGS +#define SDIO_CMD0TIMEOUT SDMMC_CMD0TIMEOUT +#define SD_SDIO_SEND_IF_COND SD_SDMMC_SEND_IF_COND +/* alias CMSIS for compatibilities */ +#define SDIO_IRQn SDMMC1_IRQn +#define SDIO_IRQHandler SDMMC1_IRQHandler +#endif + +#if defined(STM32F7) || defined(STM32F4) || defined(STM32F2) +#define HAL_SD_CardCIDTypedef HAL_SD_CardCIDTypeDef +#define HAL_SD_CardCSDTypedef HAL_SD_CardCSDTypeDef +#define HAL_SD_CardStatusTypedef HAL_SD_CardStatusTypeDef +#define HAL_SD_CardStateTypedef HAL_SD_CardStateTypeDef +#endif + +#if defined(STM32H7) +#define HAL_MMCEx_Read_DMADoubleBuffer0CpltCallback HAL_MMCEx_Read_DMADoubleBuf0CpltCallback +#define HAL_MMCEx_Read_DMADoubleBuffer1CpltCallback HAL_MMCEx_Read_DMADoubleBuf1CpltCallback +#define HAL_MMCEx_Write_DMADoubleBuffer0CpltCallback HAL_MMCEx_Write_DMADoubleBuf0CpltCallback +#define HAL_MMCEx_Write_DMADoubleBuffer1CpltCallback HAL_MMCEx_Write_DMADoubleBuf1CpltCallback +#define HAL_SDEx_Read_DMADoubleBuffer0CpltCallback HAL_SDEx_Read_DMADoubleBuf0CpltCallback +#define HAL_SDEx_Read_DMADoubleBuffer1CpltCallback HAL_SDEx_Read_DMADoubleBuf1CpltCallback +#define HAL_SDEx_Write_DMADoubleBuffer0CpltCallback HAL_SDEx_Write_DMADoubleBuf0CpltCallback +#define HAL_SDEx_Write_DMADoubleBuffer1CpltCallback HAL_SDEx_Write_DMADoubleBuf1CpltCallback +#endif +/** + * @} + */ + +/** @defgroup HAL_SMARTCARD_Aliased_Macros HAL SMARTCARD Aliased Macros maintained for legacy purpose + * @{ + */ + +#define __SMARTCARD_ENABLE_IT __HAL_SMARTCARD_ENABLE_IT +#define __SMARTCARD_DISABLE_IT __HAL_SMARTCARD_DISABLE_IT +#define __SMARTCARD_ENABLE __HAL_SMARTCARD_ENABLE +#define __SMARTCARD_DISABLE __HAL_SMARTCARD_DISABLE +#define __SMARTCARD_DMA_REQUEST_ENABLE __HAL_SMARTCARD_DMA_REQUEST_ENABLE +#define __SMARTCARD_DMA_REQUEST_DISABLE __HAL_SMARTCARD_DMA_REQUEST_DISABLE + +#define __HAL_SMARTCARD_GETCLOCKSOURCE SMARTCARD_GETCLOCKSOURCE +#define __SMARTCARD_GETCLOCKSOURCE SMARTCARD_GETCLOCKSOURCE + +#define IS_SMARTCARD_ONEBIT_SAMPLING IS_SMARTCARD_ONE_BIT_SAMPLE + +/** + * @} + */ + +/** @defgroup HAL_SMBUS_Aliased_Macros HAL SMBUS Aliased Macros maintained for legacy purpose + * @{ + */ +#define __HAL_SMBUS_RESET_CR1 SMBUS_RESET_CR1 +#define __HAL_SMBUS_RESET_CR2 SMBUS_RESET_CR2 +#define __HAL_SMBUS_GENERATE_START SMBUS_GENERATE_START +#define __HAL_SMBUS_GET_ADDR_MATCH SMBUS_GET_ADDR_MATCH +#define __HAL_SMBUS_GET_DIR SMBUS_GET_DIR +#define __HAL_SMBUS_GET_STOP_MODE SMBUS_GET_STOP_MODE +#define __HAL_SMBUS_GET_PEC_MODE SMBUS_GET_PEC_MODE +#define __HAL_SMBUS_GET_ALERT_ENABLED SMBUS_GET_ALERT_ENABLED +/** + * @} + */ + +/** @defgroup HAL_SPI_Aliased_Macros HAL SPI Aliased Macros maintained for legacy purpose + * @{ + */ + +#define __HAL_SPI_1LINE_TX SPI_1LINE_TX +#define __HAL_SPI_1LINE_RX SPI_1LINE_RX +#define __HAL_SPI_RESET_CRC SPI_RESET_CRC + +/** + * @} + */ + +/** @defgroup HAL_UART_Aliased_Macros HAL UART Aliased Macros maintained for legacy purpose + * @{ + */ + +#define __HAL_UART_GETCLOCKSOURCE UART_GETCLOCKSOURCE +#define __HAL_UART_MASK_COMPUTATION UART_MASK_COMPUTATION +#define __UART_GETCLOCKSOURCE UART_GETCLOCKSOURCE +#define __UART_MASK_COMPUTATION UART_MASK_COMPUTATION + +#define IS_UART_WAKEUPMETHODE IS_UART_WAKEUPMETHOD + +#define IS_UART_ONEBIT_SAMPLE IS_UART_ONE_BIT_SAMPLE +#define IS_UART_ONEBIT_SAMPLING IS_UART_ONE_BIT_SAMPLE + +/** + * @} + */ + + +/** @defgroup HAL_USART_Aliased_Macros HAL USART Aliased Macros maintained for legacy purpose + * @{ + */ + +#define __USART_ENABLE_IT __HAL_USART_ENABLE_IT +#define __USART_DISABLE_IT __HAL_USART_DISABLE_IT +#define __USART_ENABLE __HAL_USART_ENABLE +#define __USART_DISABLE __HAL_USART_DISABLE + +#define __HAL_USART_GETCLOCKSOURCE USART_GETCLOCKSOURCE +#define __USART_GETCLOCKSOURCE USART_GETCLOCKSOURCE + +/** + * @} + */ + +/** @defgroup HAL_USB_Aliased_Macros HAL USB Aliased Macros maintained for legacy purpose + * @{ + */ +#define USB_EXTI_LINE_WAKEUP USB_WAKEUP_EXTI_LINE + +#define USB_FS_EXTI_TRIGGER_RISING_EDGE USB_OTG_FS_WAKEUP_EXTI_RISING_EDGE +#define USB_FS_EXTI_TRIGGER_FALLING_EDGE USB_OTG_FS_WAKEUP_EXTI_FALLING_EDGE +#define USB_FS_EXTI_TRIGGER_BOTH_EDGE USB_OTG_FS_WAKEUP_EXTI_RISING_FALLING_EDGE +#define USB_FS_EXTI_LINE_WAKEUP USB_OTG_FS_WAKEUP_EXTI_LINE + +#define USB_HS_EXTI_TRIGGER_RISING_EDGE USB_OTG_HS_WAKEUP_EXTI_RISING_EDGE +#define USB_HS_EXTI_TRIGGER_FALLING_EDGE USB_OTG_HS_WAKEUP_EXTI_FALLING_EDGE +#define USB_HS_EXTI_TRIGGER_BOTH_EDGE USB_OTG_HS_WAKEUP_EXTI_RISING_FALLING_EDGE +#define USB_HS_EXTI_LINE_WAKEUP USB_OTG_HS_WAKEUP_EXTI_LINE + +#define __HAL_USB_EXTI_ENABLE_IT __HAL_USB_WAKEUP_EXTI_ENABLE_IT +#define __HAL_USB_EXTI_DISABLE_IT __HAL_USB_WAKEUP_EXTI_DISABLE_IT +#define __HAL_USB_EXTI_GET_FLAG __HAL_USB_WAKEUP_EXTI_GET_FLAG +#define __HAL_USB_EXTI_CLEAR_FLAG __HAL_USB_WAKEUP_EXTI_CLEAR_FLAG +#define __HAL_USB_EXTI_SET_RISING_EDGE_TRIGGER __HAL_USB_WAKEUP_EXTI_ENABLE_RISING_EDGE +#define __HAL_USB_EXTI_SET_FALLING_EDGE_TRIGGER __HAL_USB_WAKEUP_EXTI_ENABLE_FALLING_EDGE +#define __HAL_USB_EXTI_SET_FALLINGRISING_TRIGGER __HAL_USB_WAKEUP_EXTI_ENABLE_RISING_FALLING_EDGE + +#define __HAL_USB_FS_EXTI_ENABLE_IT __HAL_USB_OTG_FS_WAKEUP_EXTI_ENABLE_IT +#define __HAL_USB_FS_EXTI_DISABLE_IT __HAL_USB_OTG_FS_WAKEUP_EXTI_DISABLE_IT +#define __HAL_USB_FS_EXTI_GET_FLAG __HAL_USB_OTG_FS_WAKEUP_EXTI_GET_FLAG +#define __HAL_USB_FS_EXTI_CLEAR_FLAG __HAL_USB_OTG_FS_WAKEUP_EXTI_CLEAR_FLAG +#define __HAL_USB_FS_EXTI_SET_RISING_EGDE_TRIGGER __HAL_USB_OTG_FS_WAKEUP_EXTI_ENABLE_RISING_EDGE +#define __HAL_USB_FS_EXTI_SET_FALLING_EGDE_TRIGGER __HAL_USB_OTG_FS_WAKEUP_EXTI_ENABLE_FALLING_EDGE +#define __HAL_USB_FS_EXTI_SET_FALLINGRISING_TRIGGER __HAL_USB_OTG_FS_WAKEUP_EXTI_ENABLE_RISING_FALLING_EDGE +#define __HAL_USB_FS_EXTI_GENERATE_SWIT __HAL_USB_OTG_FS_WAKEUP_EXTI_GENERATE_SWIT + +#define __HAL_USB_HS_EXTI_ENABLE_IT __HAL_USB_OTG_HS_WAKEUP_EXTI_ENABLE_IT +#define __HAL_USB_HS_EXTI_DISABLE_IT __HAL_USB_OTG_HS_WAKEUP_EXTI_DISABLE_IT +#define __HAL_USB_HS_EXTI_GET_FLAG __HAL_USB_OTG_HS_WAKEUP_EXTI_GET_FLAG +#define __HAL_USB_HS_EXTI_CLEAR_FLAG __HAL_USB_OTG_HS_WAKEUP_EXTI_CLEAR_FLAG +#define __HAL_USB_HS_EXTI_SET_RISING_EGDE_TRIGGER __HAL_USB_OTG_HS_WAKEUP_EXTI_ENABLE_RISING_EDGE +#define __HAL_USB_HS_EXTI_SET_FALLING_EGDE_TRIGGER __HAL_USB_OTG_HS_WAKEUP_EXTI_ENABLE_FALLING_EDGE +#define __HAL_USB_HS_EXTI_SET_FALLINGRISING_TRIGGER __HAL_USB_OTG_HS_WAKEUP_EXTI_ENABLE_RISING_FALLING_EDGE +#define __HAL_USB_HS_EXTI_GENERATE_SWIT __HAL_USB_OTG_HS_WAKEUP_EXTI_GENERATE_SWIT + +#define HAL_PCD_ActiveRemoteWakeup HAL_PCD_ActivateRemoteWakeup +#define HAL_PCD_DeActiveRemoteWakeup HAL_PCD_DeActivateRemoteWakeup + +#define HAL_PCD_SetTxFiFo HAL_PCDEx_SetTxFiFo +#define HAL_PCD_SetRxFiFo HAL_PCDEx_SetRxFiFo +/** + * @} + */ + +/** @defgroup HAL_TIM_Aliased_Macros HAL TIM Aliased Macros maintained for legacy purpose + * @{ + */ +#define __HAL_TIM_SetICPrescalerValue TIM_SET_ICPRESCALERVALUE +#define __HAL_TIM_ResetICPrescalerValue TIM_RESET_ICPRESCALERVALUE + +#define TIM_GET_ITSTATUS __HAL_TIM_GET_IT_SOURCE +#define TIM_GET_CLEAR_IT __HAL_TIM_CLEAR_IT + +#define __HAL_TIM_GET_ITSTATUS __HAL_TIM_GET_IT_SOURCE + +#define __HAL_TIM_DIRECTION_STATUS __HAL_TIM_IS_TIM_COUNTING_DOWN +#define __HAL_TIM_PRESCALER __HAL_TIM_SET_PRESCALER +#define __HAL_TIM_SetCounter __HAL_TIM_SET_COUNTER +#define __HAL_TIM_GetCounter __HAL_TIM_GET_COUNTER +#define __HAL_TIM_SetAutoreload __HAL_TIM_SET_AUTORELOAD +#define __HAL_TIM_GetAutoreload __HAL_TIM_GET_AUTORELOAD +#define __HAL_TIM_SetClockDivision __HAL_TIM_SET_CLOCKDIVISION +#define __HAL_TIM_GetClockDivision __HAL_TIM_GET_CLOCKDIVISION +#define __HAL_TIM_SetICPrescaler __HAL_TIM_SET_ICPRESCALER +#define __HAL_TIM_GetICPrescaler __HAL_TIM_GET_ICPRESCALER +#define __HAL_TIM_SetCompare __HAL_TIM_SET_COMPARE +#define __HAL_TIM_GetCompare __HAL_TIM_GET_COMPARE + +#define TIM_BREAKINPUTSOURCE_DFSDM TIM_BREAKINPUTSOURCE_DFSDM1 +/** + * @} + */ + +/** @defgroup HAL_ETH_Aliased_Macros HAL ETH Aliased Macros maintained for legacy purpose + * @{ + */ + +#define __HAL_ETH_EXTI_ENABLE_IT __HAL_ETH_WAKEUP_EXTI_ENABLE_IT +#define __HAL_ETH_EXTI_DISABLE_IT __HAL_ETH_WAKEUP_EXTI_DISABLE_IT +#define __HAL_ETH_EXTI_GET_FLAG __HAL_ETH_WAKEUP_EXTI_GET_FLAG +#define __HAL_ETH_EXTI_CLEAR_FLAG __HAL_ETH_WAKEUP_EXTI_CLEAR_FLAG +#define __HAL_ETH_EXTI_SET_RISING_EGDE_TRIGGER __HAL_ETH_WAKEUP_EXTI_ENABLE_RISING_EDGE_TRIGGER +#define __HAL_ETH_EXTI_SET_FALLING_EGDE_TRIGGER __HAL_ETH_WAKEUP_EXTI_ENABLE_FALLING_EDGE_TRIGGER +#define __HAL_ETH_EXTI_SET_FALLINGRISING_TRIGGER __HAL_ETH_WAKEUP_EXTI_ENABLE_FALLINGRISING_TRIGGER + +#define ETH_PROMISCIOUSMODE_ENABLE ETH_PROMISCUOUS_MODE_ENABLE +#define ETH_PROMISCIOUSMODE_DISABLE ETH_PROMISCUOUS_MODE_DISABLE +#define IS_ETH_PROMISCIOUS_MODE IS_ETH_PROMISCUOUS_MODE +/** + * @} + */ + +/** @defgroup HAL_LTDC_Aliased_Macros HAL LTDC Aliased Macros maintained for legacy purpose + * @{ + */ +#define __HAL_LTDC_LAYER LTDC_LAYER +#define __HAL_LTDC_RELOAD_CONFIG __HAL_LTDC_RELOAD_IMMEDIATE_CONFIG +/** + * @} + */ + +/** @defgroup HAL_SAI_Aliased_Macros HAL SAI Aliased Macros maintained for legacy purpose + * @{ + */ +#define SAI_OUTPUTDRIVE_DISABLED SAI_OUTPUTDRIVE_DISABLE +#define SAI_OUTPUTDRIVE_ENABLED SAI_OUTPUTDRIVE_ENABLE +#define SAI_MASTERDIVIDER_ENABLED SAI_MASTERDIVIDER_ENABLE +#define SAI_MASTERDIVIDER_DISABLED SAI_MASTERDIVIDER_DISABLE +#define SAI_STREOMODE SAI_STEREOMODE +#define SAI_FIFOStatus_Empty SAI_FIFOSTATUS_EMPTY +#define SAI_FIFOStatus_Less1QuarterFull SAI_FIFOSTATUS_LESS1QUARTERFULL +#define SAI_FIFOStatus_1QuarterFull SAI_FIFOSTATUS_1QUARTERFULL +#define SAI_FIFOStatus_HalfFull SAI_FIFOSTATUS_HALFFULL +#define SAI_FIFOStatus_3QuartersFull SAI_FIFOSTATUS_3QUARTERFULL +#define SAI_FIFOStatus_Full SAI_FIFOSTATUS_FULL +#define IS_SAI_BLOCK_MONO_STREO_MODE IS_SAI_BLOCK_MONO_STEREO_MODE +#define SAI_SYNCHRONOUS_EXT SAI_SYNCHRONOUS_EXT_SAI1 +#define SAI_SYNCEXT_IN_ENABLE SAI_SYNCEXT_OUTBLOCKA_ENABLE +/** + * @} + */ + +/** @defgroup HAL_SPDIFRX_Aliased_Macros HAL SPDIFRX Aliased Macros maintained for legacy purpose + * @{ + */ +#if defined(STM32H7) +#define HAL_SPDIFRX_ReceiveControlFlow HAL_SPDIFRX_ReceiveCtrlFlow +#define HAL_SPDIFRX_ReceiveControlFlow_IT HAL_SPDIFRX_ReceiveCtrlFlow_IT +#define HAL_SPDIFRX_ReceiveControlFlow_DMA HAL_SPDIFRX_ReceiveCtrlFlow_DMA +#endif +/** + * @} + */ + +/** @defgroup HAL_PPP_Aliased_Macros HAL PPP Aliased Macros maintained for legacy purpose + * @{ + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* ___STM32_HAL_LEGACY */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal.h new file mode 100644 index 0000000..3b3c147 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal.h @@ -0,0 +1,669 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal.h + * @author MCD Application Team + * @brief This file contains all the functions prototypes for the HAL + * module driver. + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_H +#define __STM32L4xx_HAL_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_conf.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup HAL + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/** @defgroup SYSCFG_Exported_Constants SYSCFG Exported Constants + * @{ + */ + +/** @defgroup SYSCFG_BootMode Boot Mode + * @{ + */ +#define SYSCFG_BOOT_MAINFLASH ((uint32_t)0x00000000) +#define SYSCFG_BOOT_SYSTEMFLASH SYSCFG_MEMRMP_MEM_MODE_0 + +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define SYSCFG_BOOT_FMC SYSCFG_MEMRMP_MEM_MODE_1 +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx || */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#define SYSCFG_BOOT_SRAM (SYSCFG_MEMRMP_MEM_MODE_1 | SYSCFG_MEMRMP_MEM_MODE_0) + +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define SYSCFG_BOOT_OCTOPSPI1 (SYSCFG_MEMRMP_MEM_MODE_2) +#define SYSCFG_BOOT_OCTOPSPI2 (SYSCFG_MEMRMP_MEM_MODE_2 | SYSCFG_MEMRMP_MEM_MODE_0) +#else +#define SYSCFG_BOOT_QUADSPI (SYSCFG_MEMRMP_MEM_MODE_2 | SYSCFG_MEMRMP_MEM_MODE_1) +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +/** + * @} + */ + +/** @defgroup SYSCFG_FPU_Interrupts FPU Interrupts + * @{ + */ +#define SYSCFG_IT_FPU_IOC SYSCFG_CFGR1_FPU_IE_0 /*!< Floating Point Unit Invalid operation Interrupt */ +#define SYSCFG_IT_FPU_DZC SYSCFG_CFGR1_FPU_IE_1 /*!< Floating Point Unit Divide-by-zero Interrupt */ +#define SYSCFG_IT_FPU_UFC SYSCFG_CFGR1_FPU_IE_2 /*!< Floating Point Unit Underflow Interrupt */ +#define SYSCFG_IT_FPU_OFC SYSCFG_CFGR1_FPU_IE_3 /*!< Floating Point Unit Overflow Interrupt */ +#define SYSCFG_IT_FPU_IDC SYSCFG_CFGR1_FPU_IE_4 /*!< Floating Point Unit Input denormal Interrupt */ +#define SYSCFG_IT_FPU_IXC SYSCFG_CFGR1_FPU_IE_5 /*!< Floating Point Unit Inexact Interrupt */ + +/** + * @} + */ + +/** @defgroup SYSCFG_SRAM2WRP SRAM2 Page Write protection (0 to 31) + * @{ + */ +#define SYSCFG_SRAM2WRP_PAGE0 SYSCFG_SWPR_PAGE0 /*!< SRAM2 Write protection page 0 */ +#define SYSCFG_SRAM2WRP_PAGE1 SYSCFG_SWPR_PAGE1 /*!< SRAM2 Write protection page 1 */ +#define SYSCFG_SRAM2WRP_PAGE2 SYSCFG_SWPR_PAGE2 /*!< SRAM2 Write protection page 2 */ +#define SYSCFG_SRAM2WRP_PAGE3 SYSCFG_SWPR_PAGE3 /*!< SRAM2 Write protection page 3 */ +#define SYSCFG_SRAM2WRP_PAGE4 SYSCFG_SWPR_PAGE4 /*!< SRAM2 Write protection page 4 */ +#define SYSCFG_SRAM2WRP_PAGE5 SYSCFG_SWPR_PAGE5 /*!< SRAM2 Write protection page 5 */ +#define SYSCFG_SRAM2WRP_PAGE6 SYSCFG_SWPR_PAGE6 /*!< SRAM2 Write protection page 6 */ +#define SYSCFG_SRAM2WRP_PAGE7 SYSCFG_SWPR_PAGE7 /*!< SRAM2 Write protection page 7 */ +#define SYSCFG_SRAM2WRP_PAGE8 SYSCFG_SWPR_PAGE8 /*!< SRAM2 Write protection page 8 */ +#define SYSCFG_SRAM2WRP_PAGE9 SYSCFG_SWPR_PAGE9 /*!< SRAM2 Write protection page 9 */ +#define SYSCFG_SRAM2WRP_PAGE10 SYSCFG_SWPR_PAGE10 /*!< SRAM2 Write protection page 10 */ +#define SYSCFG_SRAM2WRP_PAGE11 SYSCFG_SWPR_PAGE11 /*!< SRAM2 Write protection page 11 */ +#define SYSCFG_SRAM2WRP_PAGE12 SYSCFG_SWPR_PAGE12 /*!< SRAM2 Write protection page 12 */ +#define SYSCFG_SRAM2WRP_PAGE13 SYSCFG_SWPR_PAGE13 /*!< SRAM2 Write protection page 13 */ +#define SYSCFG_SRAM2WRP_PAGE14 SYSCFG_SWPR_PAGE14 /*!< SRAM2 Write protection page 14 */ +#define SYSCFG_SRAM2WRP_PAGE15 SYSCFG_SWPR_PAGE15 /*!< SRAM2 Write protection page 15 */ +#if defined(SYSCFG_SWPR_PAGE31) +#define SYSCFG_SRAM2WRP_PAGE16 SYSCFG_SWPR_PAGE16 /*!< SRAM2 Write protection page 16 */ +#define SYSCFG_SRAM2WRP_PAGE17 SYSCFG_SWPR_PAGE17 /*!< SRAM2 Write protection page 17 */ +#define SYSCFG_SRAM2WRP_PAGE18 SYSCFG_SWPR_PAGE18 /*!< SRAM2 Write protection page 18 */ +#define SYSCFG_SRAM2WRP_PAGE19 SYSCFG_SWPR_PAGE19 /*!< SRAM2 Write protection page 19 */ +#define SYSCFG_SRAM2WRP_PAGE20 SYSCFG_SWPR_PAGE20 /*!< SRAM2 Write protection page 20 */ +#define SYSCFG_SRAM2WRP_PAGE21 SYSCFG_SWPR_PAGE21 /*!< SRAM2 Write protection page 21 */ +#define SYSCFG_SRAM2WRP_PAGE22 SYSCFG_SWPR_PAGE22 /*!< SRAM2 Write protection page 22 */ +#define SYSCFG_SRAM2WRP_PAGE23 SYSCFG_SWPR_PAGE23 /*!< SRAM2 Write protection page 23 */ +#define SYSCFG_SRAM2WRP_PAGE24 SYSCFG_SWPR_PAGE24 /*!< SRAM2 Write protection page 24 */ +#define SYSCFG_SRAM2WRP_PAGE25 SYSCFG_SWPR_PAGE25 /*!< SRAM2 Write protection page 25 */ +#define SYSCFG_SRAM2WRP_PAGE26 SYSCFG_SWPR_PAGE26 /*!< SRAM2 Write protection page 26 */ +#define SYSCFG_SRAM2WRP_PAGE27 SYSCFG_SWPR_PAGE27 /*!< SRAM2 Write protection page 27 */ +#define SYSCFG_SRAM2WRP_PAGE28 SYSCFG_SWPR_PAGE28 /*!< SRAM2 Write protection page 28 */ +#define SYSCFG_SRAM2WRP_PAGE29 SYSCFG_SWPR_PAGE29 /*!< SRAM2 Write protection page 29 */ +#define SYSCFG_SRAM2WRP_PAGE30 SYSCFG_SWPR_PAGE30 /*!< SRAM2 Write protection page 30 */ +#define SYSCFG_SRAM2WRP_PAGE31 SYSCFG_SWPR_PAGE31 /*!< SRAM2 Write protection page 31 */ +#endif /* SYSCFG_SWPR_PAGE31 */ + +/** + * @} + */ + +#if defined(SYSCFG_SWPR2_PAGE63) +/** @defgroup SYSCFG_SRAM2WRP_32_63 SRAM2 Page Write protection (32 to 63) + * @{ + */ +#define SYSCFG_SRAM2WRP_PAGE32 SYSCFG_SWPR2_PAGE32 /*!< SRAM2 Write protection page 32 */ +#define SYSCFG_SRAM2WRP_PAGE33 SYSCFG_SWPR2_PAGE33 /*!< SRAM2 Write protection page 33 */ +#define SYSCFG_SRAM2WRP_PAGE34 SYSCFG_SWPR2_PAGE34 /*!< SRAM2 Write protection page 34 */ +#define SYSCFG_SRAM2WRP_PAGE35 SYSCFG_SWPR2_PAGE35 /*!< SRAM2 Write protection page 35 */ +#define SYSCFG_SRAM2WRP_PAGE36 SYSCFG_SWPR2_PAGE36 /*!< SRAM2 Write protection page 36 */ +#define SYSCFG_SRAM2WRP_PAGE37 SYSCFG_SWPR2_PAGE37 /*!< SRAM2 Write protection page 37 */ +#define SYSCFG_SRAM2WRP_PAGE38 SYSCFG_SWPR2_PAGE38 /*!< SRAM2 Write protection page 38 */ +#define SYSCFG_SRAM2WRP_PAGE39 SYSCFG_SWPR2_PAGE39 /*!< SRAM2 Write protection page 39 */ +#define SYSCFG_SRAM2WRP_PAGE40 SYSCFG_SWPR2_PAGE40 /*!< SRAM2 Write protection page 40 */ +#define SYSCFG_SRAM2WRP_PAGE41 SYSCFG_SWPR2_PAGE41 /*!< SRAM2 Write protection page 41 */ +#define SYSCFG_SRAM2WRP_PAGE42 SYSCFG_SWPR2_PAGE42 /*!< SRAM2 Write protection page 42 */ +#define SYSCFG_SRAM2WRP_PAGE43 SYSCFG_SWPR2_PAGE43 /*!< SRAM2 Write protection page 43 */ +#define SYSCFG_SRAM2WRP_PAGE44 SYSCFG_SWPR2_PAGE44 /*!< SRAM2 Write protection page 44 */ +#define SYSCFG_SRAM2WRP_PAGE45 SYSCFG_SWPR2_PAGE45 /*!< SRAM2 Write protection page 45 */ +#define SYSCFG_SRAM2WRP_PAGE46 SYSCFG_SWPR2_PAGE46 /*!< SRAM2 Write protection page 46 */ +#define SYSCFG_SRAM2WRP_PAGE47 SYSCFG_SWPR2_PAGE47 /*!< SRAM2 Write protection page 47 */ +#define SYSCFG_SRAM2WRP_PAGE48 SYSCFG_SWPR2_PAGE48 /*!< SRAM2 Write protection page 48 */ +#define SYSCFG_SRAM2WRP_PAGE49 SYSCFG_SWPR2_PAGE49 /*!< SRAM2 Write protection page 49 */ +#define SYSCFG_SRAM2WRP_PAGE50 SYSCFG_SWPR2_PAGE50 /*!< SRAM2 Write protection page 50 */ +#define SYSCFG_SRAM2WRP_PAGE51 SYSCFG_SWPR2_PAGE51 /*!< SRAM2 Write protection page 51 */ +#define SYSCFG_SRAM2WRP_PAGE52 SYSCFG_SWPR2_PAGE52 /*!< SRAM2 Write protection page 52 */ +#define SYSCFG_SRAM2WRP_PAGE53 SYSCFG_SWPR2_PAGE53 /*!< SRAM2 Write protection page 53 */ +#define SYSCFG_SRAM2WRP_PAGE54 SYSCFG_SWPR2_PAGE54 /*!< SRAM2 Write protection page 54 */ +#define SYSCFG_SRAM2WRP_PAGE55 SYSCFG_SWPR2_PAGE55 /*!< SRAM2 Write protection page 55 */ +#define SYSCFG_SRAM2WRP_PAGE56 SYSCFG_SWPR2_PAGE56 /*!< SRAM2 Write protection page 56 */ +#define SYSCFG_SRAM2WRP_PAGE57 SYSCFG_SWPR2_PAGE57 /*!< SRAM2 Write protection page 57 */ +#define SYSCFG_SRAM2WRP_PAGE58 SYSCFG_SWPR2_PAGE58 /*!< SRAM2 Write protection page 58 */ +#define SYSCFG_SRAM2WRP_PAGE59 SYSCFG_SWPR2_PAGE59 /*!< SRAM2 Write protection page 59 */ +#define SYSCFG_SRAM2WRP_PAGE60 SYSCFG_SWPR2_PAGE60 /*!< SRAM2 Write protection page 60 */ +#define SYSCFG_SRAM2WRP_PAGE61 SYSCFG_SWPR2_PAGE61 /*!< SRAM2 Write protection page 61 */ +#define SYSCFG_SRAM2WRP_PAGE62 SYSCFG_SWPR2_PAGE62 /*!< SRAM2 Write protection page 62 */ +#define SYSCFG_SRAM2WRP_PAGE63 SYSCFG_SWPR2_PAGE63 /*!< SRAM2 Write protection page 63 */ + +/** + * @} + */ +#endif /* SYSCFG_SWPR2_PAGE63 */ + +#if defined(VREFBUF) +/** @defgroup SYSCFG_VREFBUF_VoltageScale VREFBUF Voltage Scale + * @{ + */ +#define SYSCFG_VREFBUF_VOLTAGE_SCALE0 ((uint32_t)0x00000000) /*!< Voltage reference scale 0 (VREF_OUT1) */ +#define SYSCFG_VREFBUF_VOLTAGE_SCALE1 VREFBUF_CSR_VRS /*!< Voltage reference scale 1 (VREF_OUT2) */ + +/** + * @} + */ + +/** @defgroup SYSCFG_VREFBUF_HighImpedance VREFBUF High Impedance + * @{ + */ +#define SYSCFG_VREFBUF_HIGH_IMPEDANCE_DISABLE ((uint32_t)0x00000000) /*!< VREF_plus pin is internally connected to Voltage reference buffer output */ +#define SYSCFG_VREFBUF_HIGH_IMPEDANCE_ENABLE VREFBUF_CSR_HIZ /*!< VREF_plus pin is high impedance */ + +/** + * @} + */ +#endif /* VREFBUF */ + +/** @defgroup SYSCFG_flags_definition Flags + * @{ + */ + +#define SYSCFG_FLAG_SRAM2_PE SYSCFG_CFGR2_SPF /*!< SRAM2 parity error */ +#define SYSCFG_FLAG_SRAM2_BUSY SYSCFG_SCSR_SRAM2BSY /*!< SRAM2 busy by erase operation */ + +/** + * @} + */ + +/** @defgroup SYSCFG_FastModePlus_GPIO Fast-mode Plus on GPIO + * @{ + */ + +/** @brief Fast-mode Plus driving capability on a specific GPIO + */ +#define SYSCFG_FASTMODEPLUS_PB6 SYSCFG_CFGR1_I2C_PB6_FMP /*!< Enable Fast-mode Plus on PB6 */ +#define SYSCFG_FASTMODEPLUS_PB7 SYSCFG_CFGR1_I2C_PB7_FMP /*!< Enable Fast-mode Plus on PB7 */ +#if defined(SYSCFG_CFGR1_I2C_PB8_FMP) +#define SYSCFG_FASTMODEPLUS_PB8 SYSCFG_CFGR1_I2C_PB8_FMP /*!< Enable Fast-mode Plus on PB8 */ +#endif /* SYSCFG_CFGR1_I2C_PB8_FMP */ +#if defined(SYSCFG_CFGR1_I2C_PB9_FMP) +#define SYSCFG_FASTMODEPLUS_PB9 SYSCFG_CFGR1_I2C_PB9_FMP /*!< Enable Fast-mode Plus on PB9 */ +#endif /* SYSCFG_CFGR1_I2C_PB9_FMP */ + +/** + * @} + */ + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ + +/** @defgroup DBGMCU_Exported_Macros DBGMCU Exported Macros + * @{ + */ + +/** @brief Freeze/Unfreeze Peripherals in Debug mode + */ +#if defined(DBGMCU_APB1FZR1_DBG_TIM2_STOP) +#define __HAL_DBGMCU_FREEZE_TIM2() SET_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_TIM2_STOP) +#define __HAL_DBGMCU_UNFREEZE_TIM2() CLEAR_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_TIM2_STOP) +#endif + +#if defined(DBGMCU_APB1FZR1_DBG_TIM3_STOP) +#define __HAL_DBGMCU_FREEZE_TIM3() SET_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_TIM3_STOP) +#define __HAL_DBGMCU_UNFREEZE_TIM3() CLEAR_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_TIM3_STOP) +#endif + +#if defined(DBGMCU_APB1FZR1_DBG_TIM4_STOP) +#define __HAL_DBGMCU_FREEZE_TIM4() SET_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_TIM4_STOP) +#define __HAL_DBGMCU_UNFREEZE_TIM4() CLEAR_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_TIM4_STOP) +#endif + +#if defined(DBGMCU_APB1FZR1_DBG_TIM5_STOP) +#define __HAL_DBGMCU_FREEZE_TIM5() SET_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_TIM5_STOP) +#define __HAL_DBGMCU_UNFREEZE_TIM5() CLEAR_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_TIM5_STOP) +#endif + +#if defined(DBGMCU_APB1FZR1_DBG_TIM6_STOP) +#define __HAL_DBGMCU_FREEZE_TIM6() SET_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_TIM6_STOP) +#define __HAL_DBGMCU_UNFREEZE_TIM6() CLEAR_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_TIM6_STOP) +#endif + +#if defined(DBGMCU_APB1FZR1_DBG_TIM7_STOP) +#define __HAL_DBGMCU_FREEZE_TIM7() SET_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_TIM7_STOP) +#define __HAL_DBGMCU_UNFREEZE_TIM7() CLEAR_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_TIM7_STOP) +#endif + +#if defined(DBGMCU_APB1FZR1_DBG_RTC_STOP) +#define __HAL_DBGMCU_FREEZE_RTC() SET_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_RTC_STOP) +#define __HAL_DBGMCU_UNFREEZE_RTC() CLEAR_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_RTC_STOP) +#endif + +#if defined(DBGMCU_APB1FZR1_DBG_WWDG_STOP) +#define __HAL_DBGMCU_FREEZE_WWDG() SET_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_WWDG_STOP) +#define __HAL_DBGMCU_UNFREEZE_WWDG() CLEAR_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_WWDG_STOP) +#endif + +#if defined(DBGMCU_APB1FZR1_DBG_IWDG_STOP) +#define __HAL_DBGMCU_FREEZE_IWDG() SET_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_IWDG_STOP) +#define __HAL_DBGMCU_UNFREEZE_IWDG() CLEAR_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_IWDG_STOP) +#endif + +#if defined(DBGMCU_APB1FZR1_DBG_I2C1_STOP) +#define __HAL_DBGMCU_FREEZE_I2C1_TIMEOUT() SET_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_I2C1_STOP) +#define __HAL_DBGMCU_UNFREEZE_I2C1_TIMEOUT() CLEAR_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_I2C1_STOP) +#endif + +#if defined(DBGMCU_APB1FZR1_DBG_I2C2_STOP) +#define __HAL_DBGMCU_FREEZE_I2C2_TIMEOUT() SET_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_I2C2_STOP) +#define __HAL_DBGMCU_UNFREEZE_I2C2_TIMEOUT() CLEAR_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_I2C2_STOP) +#endif + +#if defined(DBGMCU_APB1FZR1_DBG_I2C3_STOP) +#define __HAL_DBGMCU_FREEZE_I2C3_TIMEOUT() SET_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_I2C3_STOP) +#define __HAL_DBGMCU_UNFREEZE_I2C3_TIMEOUT() CLEAR_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_I2C3_STOP) +#endif + +#if defined(DBGMCU_APB1FZR2_DBG_I2C4_STOP) +#define __HAL_DBGMCU_FREEZE_I2C4_TIMEOUT() SET_BIT(DBGMCU->APB1FZR2, DBGMCU_APB1FZR2_DBG_I2C4_STOP) +#define __HAL_DBGMCU_UNFREEZE_I2C4_TIMEOUT() CLEAR_BIT(DBGMCU->APB1FZR2, DBGMCU_APB1FZR2_DBG_I2C4_STOP) +#endif + +#if defined(DBGMCU_APB1FZR1_DBG_CAN_STOP) +#define __HAL_DBGMCU_FREEZE_CAN1() SET_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_CAN_STOP) +#define __HAL_DBGMCU_UNFREEZE_CAN1() CLEAR_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_CAN_STOP) +#endif + +#if defined(DBGMCU_APB1FZR1_DBG_CAN2_STOP) +#define __HAL_DBGMCU_FREEZE_CAN2() SET_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_CAN2_STOP) +#define __HAL_DBGMCU_UNFREEZE_CAN2() CLEAR_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_CAN2_STOP) +#endif + +#if defined(DBGMCU_APB1FZR1_DBG_LPTIM1_STOP) +#define __HAL_DBGMCU_FREEZE_LPTIM1() SET_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_LPTIM1_STOP) +#define __HAL_DBGMCU_UNFREEZE_LPTIM1() CLEAR_BIT(DBGMCU->APB1FZR1, DBGMCU_APB1FZR1_DBG_LPTIM1_STOP) +#endif + +#if defined(DBGMCU_APB1FZR2_DBG_LPTIM2_STOP) +#define __HAL_DBGMCU_FREEZE_LPTIM2() SET_BIT(DBGMCU->APB1FZR2, DBGMCU_APB1FZR2_DBG_LPTIM2_STOP) +#define __HAL_DBGMCU_UNFREEZE_LPTIM2() CLEAR_BIT(DBGMCU->APB1FZR2, DBGMCU_APB1FZR2_DBG_LPTIM2_STOP) +#endif + +#if defined(DBGMCU_APB2FZ_DBG_TIM1_STOP) +#define __HAL_DBGMCU_FREEZE_TIM1() SET_BIT(DBGMCU->APB2FZ, DBGMCU_APB2FZ_DBG_TIM1_STOP) +#define __HAL_DBGMCU_UNFREEZE_TIM1() CLEAR_BIT(DBGMCU->APB2FZ, DBGMCU_APB2FZ_DBG_TIM1_STOP) +#endif + +#if defined(DBGMCU_APB2FZ_DBG_TIM8_STOP) +#define __HAL_DBGMCU_FREEZE_TIM8() SET_BIT(DBGMCU->APB2FZ, DBGMCU_APB2FZ_DBG_TIM8_STOP) +#define __HAL_DBGMCU_UNFREEZE_TIM8() CLEAR_BIT(DBGMCU->APB2FZ, DBGMCU_APB2FZ_DBG_TIM8_STOP) +#endif + +#if defined(DBGMCU_APB2FZ_DBG_TIM15_STOP) +#define __HAL_DBGMCU_FREEZE_TIM15() SET_BIT(DBGMCU->APB2FZ, DBGMCU_APB2FZ_DBG_TIM15_STOP) +#define __HAL_DBGMCU_UNFREEZE_TIM15() CLEAR_BIT(DBGMCU->APB2FZ, DBGMCU_APB2FZ_DBG_TIM15_STOP) +#endif + +#if defined(DBGMCU_APB2FZ_DBG_TIM16_STOP) +#define __HAL_DBGMCU_FREEZE_TIM16() SET_BIT(DBGMCU->APB2FZ, DBGMCU_APB2FZ_DBG_TIM16_STOP) +#define __HAL_DBGMCU_UNFREEZE_TIM16() CLEAR_BIT(DBGMCU->APB2FZ, DBGMCU_APB2FZ_DBG_TIM16_STOP) +#endif + +#if defined(DBGMCU_APB2FZ_DBG_TIM17_STOP) +#define __HAL_DBGMCU_FREEZE_TIM17() SET_BIT(DBGMCU->APB2FZ, DBGMCU_APB2FZ_DBG_TIM17_STOP) +#define __HAL_DBGMCU_UNFREEZE_TIM17() CLEAR_BIT(DBGMCU->APB2FZ, DBGMCU_APB2FZ_DBG_TIM17_STOP) +#endif + +/** + * @} + */ + +/** @defgroup SYSCFG_Exported_Macros SYSCFG Exported Macros + * @{ + */ + +/** @brief Main Flash memory mapped at 0x00000000. + */ +#define __HAL_SYSCFG_REMAPMEMORY_FLASH() CLEAR_BIT(SYSCFG->MEMRMP, SYSCFG_MEMRMP_MEM_MODE) + +/** @brief System Flash memory mapped at 0x00000000. + */ +#define __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH() MODIFY_REG(SYSCFG->MEMRMP, SYSCFG_MEMRMP_MEM_MODE, SYSCFG_MEMRMP_MEM_MODE_0) + +/** @brief Embedded SRAM mapped at 0x00000000. + */ +#define __HAL_SYSCFG_REMAPMEMORY_SRAM() MODIFY_REG(SYSCFG->MEMRMP, SYSCFG_MEMRMP_MEM_MODE, (SYSCFG_MEMRMP_MEM_MODE_1|SYSCFG_MEMRMP_MEM_MODE_0)) + +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + +/** @brief FMC Bank1 (NOR/PSRAM 1 and 2) mapped at 0x00000000. + */ +#define __HAL_SYSCFG_REMAPMEMORY_FMC() MODIFY_REG(SYSCFG->MEMRMP, SYSCFG_MEMRMP_MEM_MODE, SYSCFG_MEMRMP_MEM_MODE_1) + +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx || */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + +/** @brief OCTOSPI mapped at 0x00000000. + */ +#define __HAL_SYSCFG_REMAPMEMORY_OCTOSPI1() MODIFY_REG(SYSCFG->MEMRMP, SYSCFG_MEMRMP_MEM_MODE, (SYSCFG_MEMRMP_MEM_MODE_2)) +#define __HAL_SYSCFG_REMAPMEMORY_OCTOSPI2() MODIFY_REG(SYSCFG->MEMRMP, SYSCFG_MEMRMP_MEM_MODE, (SYSCFG_MEMRMP_MEM_MODE_2|SYSCFG_MEMRMP_MEM_MODE_0)) + +#else + +/** @brief QUADSPI mapped at 0x00000000. + */ +#define __HAL_SYSCFG_REMAPMEMORY_QUADSPI() MODIFY_REG(SYSCFG->MEMRMP, SYSCFG_MEMRMP_MEM_MODE, (SYSCFG_MEMRMP_MEM_MODE_2|SYSCFG_MEMRMP_MEM_MODE_1)) + +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +/** + * @brief Return the boot mode as configured by user. + * @retval The boot mode as configured by user. The returned value can be one + * of the following values: + * @arg @ref SYSCFG_BOOT_MAINFLASH + * @arg @ref SYSCFG_BOOT_SYSTEMFLASH + @if STM32L486xx + * @arg @ref SYSCFG_BOOT_FMC + @endif + * @arg @ref SYSCFG_BOOT_SRAM + * @arg @ref SYSCFG_BOOT_QUADSPI + */ +#define __HAL_SYSCFG_GET_BOOT_MODE() READ_BIT(SYSCFG->MEMRMP, SYSCFG_MEMRMP_MEM_MODE) + +/** @brief SRAM2 page 0 to 31 write protection enable macro + * @param __SRAM2WRP__ This parameter can be a combination of values of @ref SYSCFG_SRAM2WRP + * @note Write protection can only be disabled by a system reset + */ +#define __HAL_SYSCFG_SRAM2_WRP_1_31_ENABLE(__SRAM2WRP__) do {assert_param(IS_SYSCFG_SRAM2WRP_PAGE((__SRAM2WRP__)));\ + SET_BIT(SYSCFG->SWPR, (__SRAM2WRP__));\ + }while(0) + +#if defined(SYSCFG_SWPR2_PAGE63) +/** @brief SRAM2 page 32 to 63 write protection enable macro + * @param __SRAM2WRP__ This parameter can be a combination of values of @ref SYSCFG_SRAM2WRP_32_63 + * @note Write protection can only be disabled by a system reset + */ +#define __HAL_SYSCFG_SRAM2_WRP_32_63_ENABLE(__SRAM2WRP__) do {assert_param(IS_SYSCFG_SRAM2WRP_PAGE((__SRAM2WRP__)));\ + SET_BIT(SYSCFG->SWPR2, (__SRAM2WRP__));\ + }while(0) +#endif /* SYSCFG_SWPR2_PAGE63 */ + +/** @brief SRAM2 page write protection unlock prior to erase + * @note Writing a wrong key reactivates the write protection + */ +#define __HAL_SYSCFG_SRAM2_WRP_UNLOCK() do {SYSCFG->SKR = 0xCA;\ + SYSCFG->SKR = 0x53;\ + }while(0) + +/** @brief SRAM2 erase + * @note __SYSCFG_GET_FLAG(SYSCFG_FLAG_SRAM2_BUSY) may be used to check end of erase + */ +#define __HAL_SYSCFG_SRAM2_ERASE() SET_BIT(SYSCFG->SCSR, SYSCFG_SCSR_SRAM2ER) + +/** @brief Floating Point Unit interrupt enable/disable macros + * @param __INTERRUPT__ This parameter can be a value of @ref SYSCFG_FPU_Interrupts + */ +#define __HAL_SYSCFG_FPU_INTERRUPT_ENABLE(__INTERRUPT__) do {assert_param(IS_SYSCFG_FPU_INTERRUPT((__INTERRUPT__)));\ + SET_BIT(SYSCFG->CFGR1, (__INTERRUPT__));\ + }while(0) + +#define __HAL_SYSCFG_FPU_INTERRUPT_DISABLE(__INTERRUPT__) do {assert_param(IS_SYSCFG_FPU_INTERRUPT((__INTERRUPT__)));\ + CLEAR_BIT(SYSCFG->CFGR1, (__INTERRUPT__));\ + }while(0) + +/** @brief SYSCFG Break ECC lock. + * Enable and lock the connection of Flash ECC error connection to TIM1/8/15/16/17 Break input. + * @note The selected configuration is locked and can be unlocked only by system reset. + */ +#define __HAL_SYSCFG_BREAK_ECC_LOCK() SET_BIT(SYSCFG->CFGR2, SYSCFG_CFGR2_ECCL) + +/** @brief SYSCFG Break Cortex-M4 Lockup lock. + * Enable and lock the connection of Cortex-M4 LOCKUP (Hardfault) output to TIM1/8/15/16/17 Break input. + * @note The selected configuration is locked and can be unlocked only by system reset. + */ +#define __HAL_SYSCFG_BREAK_LOCKUP_LOCK() SET_BIT(SYSCFG->CFGR2, SYSCFG_CFGR2_CLL) + +/** @brief SYSCFG Break PVD lock. + * Enable and lock the PVD connection to Timer1/8/15/16/17 Break input, as well as the PVDE and PLS[2:0] in the PWR_CR2 register. + * @note The selected configuration is locked and can be unlocked only by system reset. + */ +#define __HAL_SYSCFG_BREAK_PVD_LOCK() SET_BIT(SYSCFG->CFGR2, SYSCFG_CFGR2_PVDL) + +/** @brief SYSCFG Break SRAM2 parity lock. + * Enable and lock the SRAM2 parity error signal connection to TIM1/8/15/16/17 Break input. + * @note The selected configuration is locked and can be unlocked by system reset. + */ +#define __HAL_SYSCFG_BREAK_SRAM2PARITY_LOCK() SET_BIT(SYSCFG->CFGR2, SYSCFG_CFGR2_SPL) + +/** @brief Check SYSCFG flag is set or not. + * @param __FLAG__ specifies the flag to check. + * This parameter can be one of the following values: + * @arg @ref SYSCFG_FLAG_SRAM2_PE SRAM2 Parity Error Flag + * @arg @ref SYSCFG_FLAG_SRAM2_BUSY SRAM2 Erase Ongoing + * @retval The new state of __FLAG__ (TRUE or FALSE). + */ +#define __HAL_SYSCFG_GET_FLAG(__FLAG__) ((((((__FLAG__) == SYSCFG_SCSR_SRAM2BSY)? SYSCFG->SCSR : SYSCFG->CFGR2) & (__FLAG__))!= 0) ? 1 : 0) + +/** @brief Set the SPF bit to clear the SRAM Parity Error Flag. + */ +#define __HAL_SYSCFG_CLEAR_FLAG() SET_BIT(SYSCFG->CFGR2, SYSCFG_CFGR2_SPF) + +/** @brief Fast-mode Plus driving capability enable/disable macros + * @param __FASTMODEPLUS__ This parameter can be a value of : + * @arg @ref SYSCFG_FASTMODEPLUS_PB6 Fast-mode Plus driving capability activation on PB6 + * @arg @ref SYSCFG_FASTMODEPLUS_PB7 Fast-mode Plus driving capability activation on PB7 + * @arg @ref SYSCFG_FASTMODEPLUS_PB8 Fast-mode Plus driving capability activation on PB8 + * @arg @ref SYSCFG_FASTMODEPLUS_PB9 Fast-mode Plus driving capability activation on PB9 + */ +#define __HAL_SYSCFG_FASTMODEPLUS_ENABLE(__FASTMODEPLUS__) do {assert_param(IS_SYSCFG_FASTMODEPLUS((__FASTMODEPLUS__)));\ + SET_BIT(SYSCFG->CFGR1, (__FASTMODEPLUS__));\ + }while(0) + +#define __HAL_SYSCFG_FASTMODEPLUS_DISABLE(__FASTMODEPLUS__) do {assert_param(IS_SYSCFG_FASTMODEPLUS((__FASTMODEPLUS__)));\ + CLEAR_BIT(SYSCFG->CFGR1, (__FASTMODEPLUS__));\ + }while(0) + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup SYSCFG_Private_Macros SYSCFG Private Macros + * @{ + */ + +#define IS_SYSCFG_FPU_INTERRUPT(__INTERRUPT__) ((((__INTERRUPT__) & SYSCFG_IT_FPU_IOC) == SYSCFG_IT_FPU_IOC) || \ + (((__INTERRUPT__) & SYSCFG_IT_FPU_DZC) == SYSCFG_IT_FPU_DZC) || \ + (((__INTERRUPT__) & SYSCFG_IT_FPU_UFC) == SYSCFG_IT_FPU_UFC) || \ + (((__INTERRUPT__) & SYSCFG_IT_FPU_OFC) == SYSCFG_IT_FPU_OFC) || \ + (((__INTERRUPT__) & SYSCFG_IT_FPU_IDC) == SYSCFG_IT_FPU_IDC) || \ + (((__INTERRUPT__) & SYSCFG_IT_FPU_IXC) == SYSCFG_IT_FPU_IXC)) + +#define IS_SYSCFG_BREAK_CONFIG(__CONFIG__) (((__CONFIG__) == SYSCFG_BREAK_ECC) || \ + ((__CONFIG__) == SYSCFG_BREAK_PVD) || \ + ((__CONFIG__) == SYSCFG_BREAK_SRAM2_PARITY) || \ + ((__CONFIG__) == SYSCFG_BREAK_LOCKUP)) + +#define IS_SYSCFG_SRAM2WRP_PAGE(__PAGE__) (((__PAGE__) > 0) && ((__PAGE__) <= 0xFFFFFFFF)) + +#if defined(VREFBUF) +#define IS_SYSCFG_VREFBUF_VOLTAGE_SCALE(__SCALE__) (((__SCALE__) == SYSCFG_VREFBUF_VOLTAGE_SCALE0) || \ + ((__SCALE__) == SYSCFG_VREFBUF_VOLTAGE_SCALE1)) + +#define IS_SYSCFG_VREFBUF_HIGH_IMPEDANCE(__VALUE__) (((__VALUE__) == SYSCFG_VREFBUF_HIGH_IMPEDANCE_DISABLE) || \ + ((__VALUE__) == SYSCFG_VREFBUF_HIGH_IMPEDANCE_ENABLE)) + +#define IS_SYSCFG_VREFBUF_TRIMMING(__VALUE__) (((__VALUE__) > 0) && ((__VALUE__) <= VREFBUF_CCR_TRIM)) +#endif /* VREFBUF */ + +#if defined(SYSCFG_FASTMODEPLUS_PB8) && defined(SYSCFG_FASTMODEPLUS_PB9) +#define IS_SYSCFG_FASTMODEPLUS(__PIN__) ((((__PIN__) & SYSCFG_FASTMODEPLUS_PB6) == SYSCFG_FASTMODEPLUS_PB6) || \ + (((__PIN__) & SYSCFG_FASTMODEPLUS_PB7) == SYSCFG_FASTMODEPLUS_PB7) || \ + (((__PIN__) & SYSCFG_FASTMODEPLUS_PB8) == SYSCFG_FASTMODEPLUS_PB8) || \ + (((__PIN__) & SYSCFG_FASTMODEPLUS_PB9) == SYSCFG_FASTMODEPLUS_PB9)) +#elif defined(SYSCFG_FASTMODEPLUS_PB8) +#define IS_SYSCFG_FASTMODEPLUS(__PIN__) ((((__PIN__) & SYSCFG_FASTMODEPLUS_PB6) == SYSCFG_FASTMODEPLUS_PB6) || \ + (((__PIN__) & SYSCFG_FASTMODEPLUS_PB7) == SYSCFG_FASTMODEPLUS_PB7) || \ + (((__PIN__) & SYSCFG_FASTMODEPLUS_PB8) == SYSCFG_FASTMODEPLUS_PB8)) +#elif defined(SYSCFG_FASTMODEPLUS_PB9) +#define IS_SYSCFG_FASTMODEPLUS(__PIN__) ((((__PIN__) & SYSCFG_FASTMODEPLUS_PB6) == SYSCFG_FASTMODEPLUS_PB6) || \ + (((__PIN__) & SYSCFG_FASTMODEPLUS_PB7) == SYSCFG_FASTMODEPLUS_PB7) || \ + (((__PIN__) & SYSCFG_FASTMODEPLUS_PB9) == SYSCFG_FASTMODEPLUS_PB9)) +#else +#define IS_SYSCFG_FASTMODEPLUS(__PIN__) ((((__PIN__) & SYSCFG_FASTMODEPLUS_PB6) == SYSCFG_FASTMODEPLUS_PB6) || \ + (((__PIN__) & SYSCFG_FASTMODEPLUS_PB7) == SYSCFG_FASTMODEPLUS_PB7)) +#endif +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ + +/** @addtogroup HAL_Exported_Functions + * @{ + */ + +/** @addtogroup HAL_Exported_Functions_Group1 + * @{ + */ + +/* Initialization and de-initialization functions ******************************/ +HAL_StatusTypeDef HAL_Init(void); +HAL_StatusTypeDef HAL_DeInit(void); +void HAL_MspInit(void); +void HAL_MspDeInit(void); +HAL_StatusTypeDef HAL_InitTick (uint32_t TickPriority); + +/** + * @} + */ + +/** @addtogroup HAL_Exported_Functions_Group2 + * @{ + */ + +/* Peripheral Control functions ************************************************/ +void HAL_IncTick(void); +void HAL_Delay(uint32_t Delay); +uint32_t HAL_GetTick(void); +void HAL_SuspendTick(void); +void HAL_ResumeTick(void); +uint32_t HAL_GetHalVersion(void); +uint32_t HAL_GetREVID(void); +uint32_t HAL_GetDEVID(void); +uint32_t HAL_GetUIDw0(void); +uint32_t HAL_GetUIDw1(void); +uint32_t HAL_GetUIDw2(void); + +/** + * @} + */ + +/** @addtogroup HAL_Exported_Functions_Group3 + * @{ + */ + +/* DBGMCU Peripheral Control functions *****************************************/ +void HAL_DBGMCU_EnableDBGSleepMode(void); +void HAL_DBGMCU_DisableDBGSleepMode(void); +void HAL_DBGMCU_EnableDBGStopMode(void); +void HAL_DBGMCU_DisableDBGStopMode(void); +void HAL_DBGMCU_EnableDBGStandbyMode(void); +void HAL_DBGMCU_DisableDBGStandbyMode(void); + +/** + * @} + */ + +/** @addtogroup HAL_Exported_Functions_Group4 + * @{ + */ + +/* SYSCFG Control functions ****************************************************/ +void HAL_SYSCFG_SRAM2Erase(void); +void HAL_SYSCFG_EnableMemorySwappingBank(void); +void HAL_SYSCFG_DisableMemorySwappingBank(void); + +#if defined(VREFBUF) +void HAL_SYSCFG_VREFBUF_VoltageScalingConfig(uint32_t VoltageScaling); +void HAL_SYSCFG_VREFBUF_HighImpedanceConfig(uint32_t Mode); +void HAL_SYSCFG_VREFBUF_TrimmingConfig(uint32_t TrimmingValue); +HAL_StatusTypeDef HAL_SYSCFG_EnableVREFBUF(void); +void HAL_SYSCFG_DisableVREFBUF(void); +#endif /* VREFBUF */ + +void HAL_SYSCFG_EnableIOAnalogSwitchBooster(void); +void HAL_SYSCFG_DisableIOAnalogSwitchBooster(void); + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_HAL_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_cortex.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_cortex.h new file mode 100644 index 0000000..b6e2e9f --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_cortex.h @@ -0,0 +1,433 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_cortex.h + * @author MCD Application Team + * @brief Header file of CORTEX HAL module. + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_CORTEX_H +#define __STM32L4xx_HAL_CORTEX_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup CORTEX CORTEX + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup CORTEX_Exported_Types CORTEX Exported Types + * @{ + */ + +#if (__MPU_PRESENT == 1) +/** @defgroup CORTEX_MPU_Region_Initialization_Structure_definition MPU Region Initialization Structure Definition + * @{ + */ +typedef struct +{ + uint8_t Enable; /*!< Specifies the status of the region. + This parameter can be a value of @ref CORTEX_MPU_Region_Enable */ + uint8_t Number; /*!< Specifies the number of the region to protect. + This parameter can be a value of @ref CORTEX_MPU_Region_Number */ + uint32_t BaseAddress; /*!< Specifies the base address of the region to protect. */ + uint8_t Size; /*!< Specifies the size of the region to protect. + This parameter can be a value of @ref CORTEX_MPU_Region_Size */ + uint8_t SubRegionDisable; /*!< Specifies the number of the subregion protection to disable. + This parameter must be a number between Min_Data = 0x00 and Max_Data = 0xFF */ + uint8_t TypeExtField; /*!< Specifies the TEX field level. + This parameter can be a value of @ref CORTEX_MPU_TEX_Levels */ + uint8_t AccessPermission; /*!< Specifies the region access permission type. + This parameter can be a value of @ref CORTEX_MPU_Region_Permission_Attributes */ + uint8_t DisableExec; /*!< Specifies the instruction access status. + This parameter can be a value of @ref CORTEX_MPU_Instruction_Access */ + uint8_t IsShareable; /*!< Specifies the shareability status of the protected region. + This parameter can be a value of @ref CORTEX_MPU_Access_Shareable */ + uint8_t IsCacheable; /*!< Specifies the cacheable status of the region protected. + This parameter can be a value of @ref CORTEX_MPU_Access_Cacheable */ + uint8_t IsBufferable; /*!< Specifies the bufferable status of the protected region. + This parameter can be a value of @ref CORTEX_MPU_Access_Bufferable */ +}MPU_Region_InitTypeDef; +/** + * @} + */ +#endif /* __MPU_PRESENT */ + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ + +/** @defgroup CORTEX_Exported_Constants CORTEX Exported Constants + * @{ + */ + +/** @defgroup CORTEX_Preemption_Priority_Group CORTEX Preemption Priority Group + * @{ + */ +#define NVIC_PRIORITYGROUP_0 ((uint32_t)0x00000007) /*!< 0 bit for pre-emption priority, + 4 bits for subpriority */ +#define NVIC_PRIORITYGROUP_1 ((uint32_t)0x00000006) /*!< 1 bit for pre-emption priority, + 3 bits for subpriority */ +#define NVIC_PRIORITYGROUP_2 ((uint32_t)0x00000005) /*!< 2 bits for pre-emption priority, + 2 bits for subpriority */ +#define NVIC_PRIORITYGROUP_3 ((uint32_t)0x00000004) /*!< 3 bits for pre-emption priority, + 1 bit for subpriority */ +#define NVIC_PRIORITYGROUP_4 ((uint32_t)0x00000003) /*!< 4 bits for pre-emption priority, + 0 bit for subpriority */ +/** + * @} + */ + +/** @defgroup CORTEX_SysTick_clock_source CORTEX SysTick clock source + * @{ + */ +#define SYSTICK_CLKSOURCE_HCLK_DIV8 ((uint32_t)0x00000000) +#define SYSTICK_CLKSOURCE_HCLK ((uint32_t)0x00000004) +/** + * @} + */ + +#if (__MPU_PRESENT == 1) +/** @defgroup CORTEX_MPU_HFNMI_PRIVDEF_Control CORTEX MPU HFNMI and PRIVILEGED Access control + * @{ + */ +#define MPU_HFNMI_PRIVDEF_NONE ((uint32_t)0x00000000) +#define MPU_HARDFAULT_NMI ((uint32_t)0x00000002) +#define MPU_PRIVILEGED_DEFAULT ((uint32_t)0x00000004) +#define MPU_HFNMI_PRIVDEF ((uint32_t)0x00000006) +/** + * @} + */ + +/** @defgroup CORTEX_MPU_Region_Enable CORTEX MPU Region Enable + * @{ + */ +#define MPU_REGION_ENABLE ((uint8_t)0x01) +#define MPU_REGION_DISABLE ((uint8_t)0x00) +/** + * @} + */ + +/** @defgroup CORTEX_MPU_Instruction_Access CORTEX MPU Instruction Access + * @{ + */ +#define MPU_INSTRUCTION_ACCESS_ENABLE ((uint8_t)0x00) +#define MPU_INSTRUCTION_ACCESS_DISABLE ((uint8_t)0x01) +/** + * @} + */ + +/** @defgroup CORTEX_MPU_Access_Shareable CORTEX MPU Instruction Access Shareable + * @{ + */ +#define MPU_ACCESS_SHAREABLE ((uint8_t)0x01) +#define MPU_ACCESS_NOT_SHAREABLE ((uint8_t)0x00) +/** + * @} + */ + +/** @defgroup CORTEX_MPU_Access_Cacheable CORTEX MPU Instruction Access Cacheable + * @{ + */ +#define MPU_ACCESS_CACHEABLE ((uint8_t)0x01) +#define MPU_ACCESS_NOT_CACHEABLE ((uint8_t)0x00) +/** + * @} + */ + +/** @defgroup CORTEX_MPU_Access_Bufferable CORTEX MPU Instruction Access Bufferable + * @{ + */ +#define MPU_ACCESS_BUFFERABLE ((uint8_t)0x01) +#define MPU_ACCESS_NOT_BUFFERABLE ((uint8_t)0x00) +/** + * @} + */ + +/** @defgroup CORTEX_MPU_TEX_Levels CORTEX MPU TEX Levels + * @{ + */ +#define MPU_TEX_LEVEL0 ((uint8_t)0x00) +#define MPU_TEX_LEVEL1 ((uint8_t)0x01) +#define MPU_TEX_LEVEL2 ((uint8_t)0x02) +/** + * @} + */ + +/** @defgroup CORTEX_MPU_Region_Size CORTEX MPU Region Size + * @{ + */ +#define MPU_REGION_SIZE_32B ((uint8_t)0x04) +#define MPU_REGION_SIZE_64B ((uint8_t)0x05) +#define MPU_REGION_SIZE_128B ((uint8_t)0x06) +#define MPU_REGION_SIZE_256B ((uint8_t)0x07) +#define MPU_REGION_SIZE_512B ((uint8_t)0x08) +#define MPU_REGION_SIZE_1KB ((uint8_t)0x09) +#define MPU_REGION_SIZE_2KB ((uint8_t)0x0A) +#define MPU_REGION_SIZE_4KB ((uint8_t)0x0B) +#define MPU_REGION_SIZE_8KB ((uint8_t)0x0C) +#define MPU_REGION_SIZE_16KB ((uint8_t)0x0D) +#define MPU_REGION_SIZE_32KB ((uint8_t)0x0E) +#define MPU_REGION_SIZE_64KB ((uint8_t)0x0F) +#define MPU_REGION_SIZE_128KB ((uint8_t)0x10) +#define MPU_REGION_SIZE_256KB ((uint8_t)0x11) +#define MPU_REGION_SIZE_512KB ((uint8_t)0x12) +#define MPU_REGION_SIZE_1MB ((uint8_t)0x13) +#define MPU_REGION_SIZE_2MB ((uint8_t)0x14) +#define MPU_REGION_SIZE_4MB ((uint8_t)0x15) +#define MPU_REGION_SIZE_8MB ((uint8_t)0x16) +#define MPU_REGION_SIZE_16MB ((uint8_t)0x17) +#define MPU_REGION_SIZE_32MB ((uint8_t)0x18) +#define MPU_REGION_SIZE_64MB ((uint8_t)0x19) +#define MPU_REGION_SIZE_128MB ((uint8_t)0x1A) +#define MPU_REGION_SIZE_256MB ((uint8_t)0x1B) +#define MPU_REGION_SIZE_512MB ((uint8_t)0x1C) +#define MPU_REGION_SIZE_1GB ((uint8_t)0x1D) +#define MPU_REGION_SIZE_2GB ((uint8_t)0x1E) +#define MPU_REGION_SIZE_4GB ((uint8_t)0x1F) +/** + * @} + */ + +/** @defgroup CORTEX_MPU_Region_Permission_Attributes CORTEX MPU Region Permission Attributes + * @{ + */ +#define MPU_REGION_NO_ACCESS ((uint8_t)0x00) +#define MPU_REGION_PRIV_RW ((uint8_t)0x01) +#define MPU_REGION_PRIV_RW_URO ((uint8_t)0x02) +#define MPU_REGION_FULL_ACCESS ((uint8_t)0x03) +#define MPU_REGION_PRIV_RO ((uint8_t)0x05) +#define MPU_REGION_PRIV_RO_URO ((uint8_t)0x06) +/** + * @} + */ + +/** @defgroup CORTEX_MPU_Region_Number CORTEX MPU Region Number + * @{ + */ +#define MPU_REGION_NUMBER0 ((uint8_t)0x00) +#define MPU_REGION_NUMBER1 ((uint8_t)0x01) +#define MPU_REGION_NUMBER2 ((uint8_t)0x02) +#define MPU_REGION_NUMBER3 ((uint8_t)0x03) +#define MPU_REGION_NUMBER4 ((uint8_t)0x04) +#define MPU_REGION_NUMBER5 ((uint8_t)0x05) +#define MPU_REGION_NUMBER6 ((uint8_t)0x06) +#define MPU_REGION_NUMBER7 ((uint8_t)0x07) +/** + * @} + */ +#endif /* __MPU_PRESENT */ + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ +/** @defgroup CORTEX_Exported_Macros CORTEX Exported Macros + * @{ + */ + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup CORTEX_Exported_Functions CORTEX Exported Functions + * @{ + */ + +/** @defgroup CORTEX_Exported_Functions_Group1 Initialization and Configuration functions + * @brief Initialization and Configuration functions + * @{ + */ +/* Initialization and Configuration functions *****************************/ +void HAL_NVIC_SetPriorityGrouping(uint32_t PriorityGroup); +void HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority); +void HAL_NVIC_EnableIRQ(IRQn_Type IRQn); +void HAL_NVIC_DisableIRQ(IRQn_Type IRQn); +void HAL_NVIC_SystemReset(void); +uint32_t HAL_SYSTICK_Config(uint32_t TicksNumb); + +/** + * @} + */ + +/** @defgroup CORTEX_Exported_Functions_Group2 Peripheral Control functions + * @brief Cortex control functions + * @{ + */ +/* Peripheral Control functions ***********************************************/ +uint32_t HAL_NVIC_GetPriorityGrouping(void); +void HAL_NVIC_GetPriority(IRQn_Type IRQn, uint32_t PriorityGroup, uint32_t* pPreemptPriority, uint32_t* pSubPriority); +uint32_t HAL_NVIC_GetPendingIRQ(IRQn_Type IRQn); +void HAL_NVIC_SetPendingIRQ(IRQn_Type IRQn); +void HAL_NVIC_ClearPendingIRQ(IRQn_Type IRQn); +uint32_t HAL_NVIC_GetActive(IRQn_Type IRQn); +void HAL_SYSTICK_CLKSourceConfig(uint32_t CLKSource); +void HAL_SYSTICK_IRQHandler(void); +void HAL_SYSTICK_Callback(void); + +#if (__MPU_PRESENT == 1) +void HAL_MPU_Enable(uint32_t MPU_Control); +void HAL_MPU_Disable(void); +void HAL_MPU_ConfigRegion(MPU_Region_InitTypeDef *MPU_Init); +#endif /* __MPU_PRESENT */ +/** + * @} + */ + +/** + * @} + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ +/** @defgroup CORTEX_Private_Macros CORTEX Private Macros + * @{ + */ +#define IS_NVIC_PRIORITY_GROUP(GROUP) (((GROUP) == NVIC_PRIORITYGROUP_0) || \ + ((GROUP) == NVIC_PRIORITYGROUP_1) || \ + ((GROUP) == NVIC_PRIORITYGROUP_2) || \ + ((GROUP) == NVIC_PRIORITYGROUP_3) || \ + ((GROUP) == NVIC_PRIORITYGROUP_4)) + +#define IS_NVIC_PREEMPTION_PRIORITY(PRIORITY) ((PRIORITY) < 0x10) + +#define IS_NVIC_SUB_PRIORITY(PRIORITY) ((PRIORITY) < 0x10) + +#define IS_NVIC_DEVICE_IRQ(IRQ) ((IRQ) >= 0x00) + +#define IS_SYSTICK_CLK_SOURCE(SOURCE) (((SOURCE) == SYSTICK_CLKSOURCE_HCLK) || \ + ((SOURCE) == SYSTICK_CLKSOURCE_HCLK_DIV8)) + +#if (__MPU_PRESENT == 1) +#define IS_MPU_REGION_ENABLE(STATE) (((STATE) == MPU_REGION_ENABLE) || \ + ((STATE) == MPU_REGION_DISABLE)) + +#define IS_MPU_INSTRUCTION_ACCESS(STATE) (((STATE) == MPU_INSTRUCTION_ACCESS_ENABLE) || \ + ((STATE) == MPU_INSTRUCTION_ACCESS_DISABLE)) + +#define IS_MPU_ACCESS_SHAREABLE(STATE) (((STATE) == MPU_ACCESS_SHAREABLE) || \ + ((STATE) == MPU_ACCESS_NOT_SHAREABLE)) + +#define IS_MPU_ACCESS_CACHEABLE(STATE) (((STATE) == MPU_ACCESS_CACHEABLE) || \ + ((STATE) == MPU_ACCESS_NOT_CACHEABLE)) + +#define IS_MPU_ACCESS_BUFFERABLE(STATE) (((STATE) == MPU_ACCESS_BUFFERABLE) || \ + ((STATE) == MPU_ACCESS_NOT_BUFFERABLE)) + +#define IS_MPU_TEX_LEVEL(TYPE) (((TYPE) == MPU_TEX_LEVEL0) || \ + ((TYPE) == MPU_TEX_LEVEL1) || \ + ((TYPE) == MPU_TEX_LEVEL2)) + +#define IS_MPU_REGION_PERMISSION_ATTRIBUTE(TYPE) (((TYPE) == MPU_REGION_NO_ACCESS) || \ + ((TYPE) == MPU_REGION_PRIV_RW) || \ + ((TYPE) == MPU_REGION_PRIV_RW_URO) || \ + ((TYPE) == MPU_REGION_FULL_ACCESS) || \ + ((TYPE) == MPU_REGION_PRIV_RO) || \ + ((TYPE) == MPU_REGION_PRIV_RO_URO)) + +#define IS_MPU_REGION_NUMBER(NUMBER) (((NUMBER) == MPU_REGION_NUMBER0) || \ + ((NUMBER) == MPU_REGION_NUMBER1) || \ + ((NUMBER) == MPU_REGION_NUMBER2) || \ + ((NUMBER) == MPU_REGION_NUMBER3) || \ + ((NUMBER) == MPU_REGION_NUMBER4) || \ + ((NUMBER) == MPU_REGION_NUMBER5) || \ + ((NUMBER) == MPU_REGION_NUMBER6) || \ + ((NUMBER) == MPU_REGION_NUMBER7)) + +#define IS_MPU_REGION_SIZE(SIZE) (((SIZE) == MPU_REGION_SIZE_32B) || \ + ((SIZE) == MPU_REGION_SIZE_64B) || \ + ((SIZE) == MPU_REGION_SIZE_128B) || \ + ((SIZE) == MPU_REGION_SIZE_256B) || \ + ((SIZE) == MPU_REGION_SIZE_512B) || \ + ((SIZE) == MPU_REGION_SIZE_1KB) || \ + ((SIZE) == MPU_REGION_SIZE_2KB) || \ + ((SIZE) == MPU_REGION_SIZE_4KB) || \ + ((SIZE) == MPU_REGION_SIZE_8KB) || \ + ((SIZE) == MPU_REGION_SIZE_16KB) || \ + ((SIZE) == MPU_REGION_SIZE_32KB) || \ + ((SIZE) == MPU_REGION_SIZE_64KB) || \ + ((SIZE) == MPU_REGION_SIZE_128KB) || \ + ((SIZE) == MPU_REGION_SIZE_256KB) || \ + ((SIZE) == MPU_REGION_SIZE_512KB) || \ + ((SIZE) == MPU_REGION_SIZE_1MB) || \ + ((SIZE) == MPU_REGION_SIZE_2MB) || \ + ((SIZE) == MPU_REGION_SIZE_4MB) || \ + ((SIZE) == MPU_REGION_SIZE_8MB) || \ + ((SIZE) == MPU_REGION_SIZE_16MB) || \ + ((SIZE) == MPU_REGION_SIZE_32MB) || \ + ((SIZE) == MPU_REGION_SIZE_64MB) || \ + ((SIZE) == MPU_REGION_SIZE_128MB) || \ + ((SIZE) == MPU_REGION_SIZE_256MB) || \ + ((SIZE) == MPU_REGION_SIZE_512MB) || \ + ((SIZE) == MPU_REGION_SIZE_1GB) || \ + ((SIZE) == MPU_REGION_SIZE_2GB) || \ + ((SIZE) == MPU_REGION_SIZE_4GB)) + +#define IS_MPU_SUB_REGION_DISABLE(SUBREGION) ((SUBREGION) < (uint16_t)0x00FF) +#endif /* __MPU_PRESENT */ + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_HAL_CORTEX_H */ + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_def.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_def.h new file mode 100644 index 0000000..bb9816b --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_def.h @@ -0,0 +1,213 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_def.h + * @author MCD Application Team + * @brief This file contains HAL common defines, enumeration, macros and + * structures definitions. + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_DEF +#define __STM32L4xx_HAL_DEF + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx.h" +#include "Legacy/stm32_hal_legacy.h" /* Aliases file for old names compatibility */ +#include + +/* Exported types ------------------------------------------------------------*/ + +/** + * @brief HAL Status structures definition + */ +typedef enum +{ + HAL_OK = 0x00, + HAL_ERROR = 0x01, + HAL_BUSY = 0x02, + HAL_TIMEOUT = 0x03 +} HAL_StatusTypeDef; + +/** + * @brief HAL Lock structures definition + */ +typedef enum +{ + HAL_UNLOCKED = 0x00, + HAL_LOCKED = 0x01 +} HAL_LockTypeDef; + +/* Exported macros -----------------------------------------------------------*/ + +#define HAL_MAX_DELAY 0xFFFFFFFFU + +#define HAL_IS_BIT_SET(REG, BIT) (((REG) & (BIT)) == (BIT)) +#define HAL_IS_BIT_CLR(REG, BIT) (((REG) & (BIT)) == RESET) + +#define __HAL_LINKDMA(__HANDLE__, __PPP_DMA_FIELD__, __DMA_HANDLE__) \ + do{ \ + (__HANDLE__)->__PPP_DMA_FIELD__ = &(__DMA_HANDLE__); \ + (__DMA_HANDLE__).Parent = (__HANDLE__); \ + } while(0) + +#define UNUSED(x) ((void)(x)) + +/** @brief Reset the Handle's State field. + * @param __HANDLE__: specifies the Peripheral Handle. + * @note This macro can be used for the following purpose: + * - When the Handle is declared as local variable; before passing it as parameter + * to HAL_PPP_Init() for the first time, it is mandatory to use this macro + * to set to 0 the Handle's "State" field. + * Otherwise, "State" field may have any random value and the first time the function + * HAL_PPP_Init() is called, the low level hardware initialization will be missed + * (i.e. HAL_PPP_MspInit() will not be executed). + * - When there is a need to reconfigure the low level hardware: instead of calling + * HAL_PPP_DeInit() then HAL_PPP_Init(), user can make a call to this macro then HAL_PPP_Init(). + * In this later function, when the Handle's "State" field is set to 0, it will execute the function + * HAL_PPP_MspInit() which will reconfigure the low level hardware. + * @retval None + */ +#define __HAL_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = 0) + +#if (USE_RTOS == 1) + /* Reserved for future use */ + #error " USE_RTOS should be 0 in the current HAL release " +#else + #define __HAL_LOCK(__HANDLE__) \ + do{ \ + if((__HANDLE__)->Lock == HAL_LOCKED) \ + { \ + return HAL_BUSY; \ + } \ + else \ + { \ + (__HANDLE__)->Lock = HAL_LOCKED; \ + } \ + }while (0) + + #define __HAL_UNLOCK(__HANDLE__) \ + do{ \ + (__HANDLE__)->Lock = HAL_UNLOCKED; \ + }while (0) +#endif /* USE_RTOS */ + +#if defined ( __GNUC__ ) && !defined (__CC_ARM) /* GNU Compiler */ + #ifndef __weak + #define __weak __attribute__((weak)) + #endif /* __weak */ + #ifndef __packed + #define __packed __attribute__((__packed__)) + #endif /* __packed */ +#endif /* __GNUC__ */ + + +/* Macro to get variable aligned on 4-bytes, for __ICCARM__ the directive "#pragma data_alignment=4" must be used instead */ +#if defined ( __GNUC__ ) && !defined (__CC_ARM) /* GNU Compiler */ + #ifndef __ALIGN_END + #define __ALIGN_END __attribute__ ((aligned (4))) + #endif /* __ALIGN_END */ + #ifndef __ALIGN_BEGIN + #define __ALIGN_BEGIN + #endif /* __ALIGN_BEGIN */ +#else + #ifndef __ALIGN_END + #define __ALIGN_END + #endif /* __ALIGN_END */ + #ifndef __ALIGN_BEGIN + #if defined (__CC_ARM) /* ARM Compiler */ + #define __ALIGN_BEGIN __align(4) + #elif defined (__ICCARM__) /* IAR Compiler */ + #define __ALIGN_BEGIN + #endif /* __CC_ARM */ + #endif /* __ALIGN_BEGIN */ +#endif /* __GNUC__ */ + +/** + * @brief __RAM_FUNC definition + */ +#if defined ( __CC_ARM ) +/* ARM Compiler + ------------ + RAM functions are defined using the toolchain options. + Functions that are executed in RAM should reside in a separate source module. + Using the 'Options for File' dialog you can simply change the 'Code / Const' + area of a module to a memory space in physical RAM. + Available memory areas are declared in the 'Target' tab of the 'Options for Target' + dialog. +*/ +#define __RAM_FUNC HAL_StatusTypeDef + +#elif defined ( __ICCARM__ ) +/* ICCARM Compiler + --------------- + RAM functions are defined using a specific toolchain keyword "__ramfunc". +*/ +#define __RAM_FUNC __ramfunc HAL_StatusTypeDef + +#elif defined ( __GNUC__ ) +/* GNU Compiler + ------------ + RAM functions are defined using a specific toolchain attribute + "__attribute__((section(".RamFunc")))". +*/ +#define __RAM_FUNC HAL_StatusTypeDef __attribute__((section(".RamFunc"))) + +#endif + +/** + * @brief __NOINLINE definition + */ +#if defined ( __CC_ARM ) || defined ( __GNUC__ ) +/* ARM & GNUCompiler + ---------------- +*/ +#define __NOINLINE __attribute__ ( (noinline) ) + +#elif defined ( __ICCARM__ ) +/* ICCARM Compiler + --------------- +*/ +#define __NOINLINE _Pragma("optimize = no_inline") + +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* ___STM32L4xx_HAL_DEF */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_dma.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_dma.h new file mode 100644 index 0000000..c11a47c --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_dma.h @@ -0,0 +1,766 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_dma.h + * @author MCD Application Team + * @brief Header file of DMA HAL module. + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_DMA_H +#define __STM32L4xx_HAL_DMA_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup DMA + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup DMA_Exported_Types DMA Exported Types + * @{ + */ + +/** + * @brief DMA Configuration Structure definition + */ +typedef struct +{ + uint32_t Request; /*!< Specifies the request selected for the specified channel. + This parameter can be a value of @ref DMA_request */ + + uint32_t Direction; /*!< Specifies if the data will be transferred from memory to peripheral, + from memory to memory or from peripheral to memory. + This parameter can be a value of @ref DMA_Data_transfer_direction */ + + uint32_t PeriphInc; /*!< Specifies whether the Peripheral address register should be incremented or not. + This parameter can be a value of @ref DMA_Peripheral_incremented_mode */ + + uint32_t MemInc; /*!< Specifies whether the memory address register should be incremented or not. + This parameter can be a value of @ref DMA_Memory_incremented_mode */ + + uint32_t PeriphDataAlignment; /*!< Specifies the Peripheral data width. + This parameter can be a value of @ref DMA_Peripheral_data_size */ + + uint32_t MemDataAlignment; /*!< Specifies the Memory data width. + This parameter can be a value of @ref DMA_Memory_data_size */ + + uint32_t Mode; /*!< Specifies the operation mode of the DMAy Channelx. + This parameter can be a value of @ref DMA_mode + @note The circular buffer mode cannot be used if the memory-to-memory + data transfer is configured on the selected Channel */ + + uint32_t Priority; /*!< Specifies the software priority for the DMAy Channelx. + This parameter can be a value of @ref DMA_Priority_level */ +} DMA_InitTypeDef; + +/** + * @brief HAL DMA State structures definition + */ +typedef enum +{ + HAL_DMA_STATE_RESET = 0x00, /*!< DMA not yet initialized or disabled */ + HAL_DMA_STATE_READY = 0x01, /*!< DMA initialized and ready for use */ + HAL_DMA_STATE_BUSY = 0x02, /*!< DMA process is ongoing */ + HAL_DMA_STATE_TIMEOUT = 0x03, /*!< DMA timeout state */ +}HAL_DMA_StateTypeDef; + +/** + * @brief HAL DMA Error Code structure definition + */ +typedef enum +{ + HAL_DMA_FULL_TRANSFER = 0x00, /*!< Full transfer */ + HAL_DMA_HALF_TRANSFER = 0x01 /*!< Half Transfer */ +}HAL_DMA_LevelCompleteTypeDef; + + +/** + * @brief HAL DMA Callback ID structure definition + */ +typedef enum +{ + HAL_DMA_XFER_CPLT_CB_ID = 0x00, /*!< Full transfer */ + HAL_DMA_XFER_HALFCPLT_CB_ID = 0x01, /*!< Half transfer */ + HAL_DMA_XFER_ERROR_CB_ID = 0x02, /*!< Error */ + HAL_DMA_XFER_ABORT_CB_ID = 0x03, /*!< Abort */ + HAL_DMA_XFER_ALL_CB_ID = 0x04 /*!< All */ + +}HAL_DMA_CallbackIDTypeDef; + +/** + * @brief DMA handle Structure definition + */ +typedef struct __DMA_HandleTypeDef +{ + DMA_Channel_TypeDef *Instance; /*!< Register base address */ + + DMA_InitTypeDef Init; /*!< DMA communication parameters */ + + HAL_LockTypeDef Lock; /*!< DMA locking object */ + + __IO HAL_DMA_StateTypeDef State; /*!< DMA transfer state */ + + void *Parent; /*!< Parent object state */ + + void (* XferCpltCallback)(struct __DMA_HandleTypeDef * hdma); /*!< DMA transfer complete callback */ + + void (* XferHalfCpltCallback)(struct __DMA_HandleTypeDef * hdma); /*!< DMA Half transfer complete callback */ + + void (* XferErrorCallback)(struct __DMA_HandleTypeDef * hdma); /*!< DMA transfer error callback */ + + void (* XferAbortCallback)( struct __DMA_HandleTypeDef * hdma); /*!< DMA transfer abort callback */ + + __IO uint32_t ErrorCode; /*!< DMA Error code */ + + DMA_TypeDef *DmaBaseAddress; /*!< DMA Channel Base Address */ + + uint32_t ChannelIndex; /*!< DMA Channel Index */ + +#if defined(DMAMUX1) + DMAMUX_Channel_TypeDef *DMAmuxChannel; /*!< Register base address */ + + DMAMUX_ChannelStatus_TypeDef *DMAmuxChannelStatus; /*!< DMAMUX Channels Status Base Address */ + + uint32_t DMAmuxChannelStatusMask; /*!< DMAMUX Channel Status Mask */ + + DMAMUX_RequestGen_TypeDef *DMAmuxRequestGen; /*!< DMAMUX request generator Base Address */ + + DMAMUX_RequestGenStatus_TypeDef *DMAmuxRequestGenStatus; /*!< DMAMUX request generator Address */ + + uint32_t DMAmuxRequestGenStatusMask; /*!< DMAMUX request generator Status mask */ + +#endif /* DMAMUX1 */ + +}DMA_HandleTypeDef; +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ + +/** @defgroup DMA_Exported_Constants DMA Exported Constants + * @{ + */ + +/** @defgroup DMA_Error_Code DMA Error Code + * @{ + */ +#define HAL_DMA_ERROR_NONE ((uint32_t)0x00000000U) /*!< No error */ +#define HAL_DMA_ERROR_TE ((uint32_t)0x00000001U) /*!< Transfer error */ +#define HAL_DMA_ERROR_NO_XFER ((uint32_t)0x00000004U) /*!< Abort requested with no Xfer ongoing */ +#define HAL_DMA_ERROR_TIMEOUT ((uint32_t)0x00000020U) /*!< Timeout error */ +#define HAL_DMA_ERROR_NOT_SUPPORTED ((uint32_t)0x00000100U) /*!< Not supported mode */ +#define HAL_DMA_ERROR_SYNC ((uint32_t)0x00000200U) /*!< DMAMUX sync overrun error */ +#define HAL_DMA_ERROR_REQGEN ((uint32_t)0x00000400U) /*!< DMAMUX request generator overrun error */ + +/** + * @} + */ + +/** @defgroup DMA_request DMA request + * @{ + */ +#if !defined (DMAMUX1) + +#define DMA_REQUEST_0 ((uint32_t)0x00000000) +#define DMA_REQUEST_1 ((uint32_t)0x00000001) +#define DMA_REQUEST_2 ((uint32_t)0x00000002) +#define DMA_REQUEST_3 ((uint32_t)0x00000003) +#define DMA_REQUEST_4 ((uint32_t)0x00000004) +#define DMA_REQUEST_5 ((uint32_t)0x00000005) +#define DMA_REQUEST_6 ((uint32_t)0x00000006) +#define DMA_REQUEST_7 ((uint32_t)0x00000007) + +#endif + +#if defined(DMAMUX1) + +#define DMA_REQUEST_MEM2MEM 0U /*!< memory to memory transfer */ + +#define DMA_REQUEST_GENERATOR0 1U /*!< DMAMUX1 request generator 0 */ +#define DMA_REQUEST_GENERATOR1 2U /*!< DMAMUX1 request generator 1 */ +#define DMA_REQUEST_GENERATOR2 3U /*!< DMAMUX1 request generator 2 */ +#define DMA_REQUEST_GENERATOR3 4U /*!< DMAMUX1 request generator 3 */ + +#define DMA_REQUEST_ADC1 5U /*!< DMAMUX1 ADC1 request */ + +#define DMA_REQUEST_DAC1_CH1 6U /*!< DMAMUX1 DAC1 CH1 request */ +#define DMA_REQUEST_DAC1_CH2 7U /*!< DMAMUX1 DAC1 CH2 request */ + +#define DMA_REQUEST_TIM6_UP 8U /*!< DMAMUX1 TIM6 UP request */ +#define DMA_REQUEST_TIM7_UP 9U /*!< DMAMUX1 TIM7 UP request */ + +#define DMA_REQUEST_SPI1_RX 10U /*!< DMAMUX1 SPI1 RX request */ +#define DMA_REQUEST_SPI1_TX 11U /*!< DMAMUX1 SPI1 TX request */ +#define DMA_REQUEST_SPI2_RX 12U /*!< DMAMUX1 SPI2 RX request */ +#define DMA_REQUEST_SPI2_TX 13U /*!< DMAMUX1 SPI2 TX request */ +#define DMA_REQUEST_SPI3_RX 14U /*!< DMAMUX1 SPI3 RX request */ +#define DMA_REQUEST_SPI3_TX 15U /*!< DMAMUX1 SPI3 TX request */ + +#define DMA_REQUEST_I2C1_RX 16U /*!< DMAMUX1 I2C1 RX request */ +#define DMA_REQUEST_I2C1_TX 17U /*!< DMAMUX1 I2C1 TX request */ +#define DMA_REQUEST_I2C2_RX 18U /*!< DMAMUX1 I2C2 RX request */ +#define DMA_REQUEST_I2C2_TX 19U /*!< DMAMUX1 I2C2 TX request */ +#define DMA_REQUEST_I2C3_RX 20U /*!< DMAMUX1 I2C3 RX request */ +#define DMA_REQUEST_I2C3_TX 21U /*!< DMAMUX1 I2C3 TX request */ +#define DMA_REQUEST_I2C4_RX 22U /*!< DMAMUX1 I2C4 RX request */ +#define DMA_REQUEST_I2C4_TX 23U /*!< DMAMUX1 I2C4 TX request */ + +#define DMA_REQUEST_USART1_RX 24U /*!< DMAMUX1 USART1 RX request */ +#define DMA_REQUEST_USART1_TX 25U /*!< DMAMUX1 USART1 TX request */ +#define DMA_REQUEST_USART2_RX 26U /*!< DMAMUX1 USART2 RX request */ +#define DMA_REQUEST_USART2_TX 27U /*!< DMAMUX1 USART2 TX request */ +#define DMA_REQUEST_USART3_RX 28U /*!< DMAMUX1 USART3 RX request */ +#define DMA_REQUEST_USART3_TX 29U /*!< DMAMUX1 USART3 TX request */ + +#define DMA_REQUEST_UART4_RX 30U /*!< DMAMUX1 UART4 RX request */ +#define DMA_REQUEST_UART4_TX 31U /*!< DMAMUX1 UART4 TX request */ +#define DMA_REQUEST_UART5_RX 32U /*!< DMAMUX1 UART5 RX request */ +#define DMA_REQUEST_UART5_TX 33U /*!< DMAMUX1 UART5 TX request */ + +#define DMA_REQUEST_LPUART1_RX 34U /*!< DMAMUX1 LP_UART1_RX request */ +#define DMA_REQUEST_LPUART1_TX 35U /*!< DMAMUX1 LP_UART1_RX request */ + +#define DMA_REQUEST_SAI1_A 36U /*!< DMAMUX1 SAI1 A request */ +#define DMA_REQUEST_SAI1_B 37U /*!< DMAMUX1 SAI1 B request */ +#define DMA_REQUEST_SAI2_A 38U /*!< DMAMUX1 SAI2 A request */ +#define DMA_REQUEST_SAI2_B 39U /*!< DMAMUX1 SAI2 B request */ + +#define DMA_REQUEST_OCTOSPI1 40U /*!< DMAMUX1 OCTOSPI1 request */ +#define DMA_REQUEST_OCTOSPI2 41U /*!< DMAMUX1 OCTOSPI2 request */ + +#define DMA_REQUEST_TIM1_CH1 42U /*!< DMAMUX1 TIM1 CH1 request */ +#define DMA_REQUEST_TIM1_CH2 43U /*!< DMAMUX1 TIM1 CH2 request */ +#define DMA_REQUEST_TIM1_CH3 44U /*!< DMAMUX1 TIM1 CH3 request */ +#define DMA_REQUEST_TIM1_CH4 45U /*!< DMAMUX1 TIM1 CH4 request */ +#define DMA_REQUEST_TIM1_UP 46U /*!< DMAMUX1 TIM1 UP request */ +#define DMA_REQUEST_TIM1_TRIG 47U /*!< DMAMUX1 TIM1 TRIG request */ +#define DMA_REQUEST_TIM1_COM 48U /*!< DMAMUX1 TIM1 COM request */ + +#define DMA_REQUEST_TIM8_CH1 49U /*!< DMAMUX1 TIM8 CH1 request */ +#define DMA_REQUEST_TIM8_CH2 50U /*!< DMAMUX1 TIM8 CH2 request */ +#define DMA_REQUEST_TIM8_CH3 51U /*!< DMAMUX1 TIM8 CH3 request */ +#define DMA_REQUEST_TIM8_CH4 52U /*!< DMAMUX1 TIM8 CH4 request */ +#define DMA_REQUEST_TIM8_UP 53U /*!< DMAMUX1 TIM8 UP request */ +#define DMA_REQUEST_TIM8_TRIG 54U /*!< DMAMUX1 TIM8 TRIG request */ +#define DMA_REQUEST_TIM8_COM 55U /*!< DMAMUX1 TIM8 COM request */ + +#define DMA_REQUEST_TIM2_CH1 56U /*!< DMAMUX1 TIM2 CH1 request */ +#define DMA_REQUEST_TIM2_CH2 57U /*!< DMAMUX1 TIM2 CH2 request */ +#define DMA_REQUEST_TIM2_CH3 58U /*!< DMAMUX1 TIM2 CH3 request */ +#define DMA_REQUEST_TIM2_CH4 59U /*!< DMAMUX1 TIM2 CH4 request */ +#define DMA_REQUEST_TIM2_UP 60U /*!< DMAMUX1 TIM2 UP request */ + +#define DMA_REQUEST_TIM3_CH1 61U /*!< DMAMUX1 TIM3 CH1 request */ +#define DMA_REQUEST_TIM3_CH2 62U /*!< DMAMUX1 TIM3 CH2 request */ +#define DMA_REQUEST_TIM3_CH3 63U /*!< DMAMUX1 TIM3 CH3 request */ +#define DMA_REQUEST_TIM3_CH4 64U /*!< DMAMUX1 TIM3 CH4 request */ +#define DMA_REQUEST_TIM3_UP 65U /*!< DMAMUX1 TIM3 UP request */ +#define DMA_REQUEST_TIM3_TRIG 66U /*!< DMAMUX1 TIM3 TRIG request */ + +#define DMA_REQUEST_TIM4_CH1 67U /*!< DMAMUX1 TIM4 CH1 request */ +#define DMA_REQUEST_TIM4_CH2 68U /*!< DMAMUX1 TIM4 CH2 request */ +#define DMA_REQUEST_TIM4_CH3 69U /*!< DMAMUX1 TIM4 CH3 request */ +#define DMA_REQUEST_TIM4_CH4 70U /*!< DMAMUX1 TIM4 CH4 request */ +#define DMA_REQUEST_TIM4_UP 71U /*!< DMAMUX1 TIM4 UP request */ + +#define DMA_REQUEST_TIM5_CH1 72U /*!< DMAMUX1 TIM5 CH1 request */ +#define DMA_REQUEST_TIM5_CH2 73U /*!< DMAMUX1 TIM5 CH2 request */ +#define DMA_REQUEST_TIM5_CH3 74U /*!< DMAMUX1 TIM5 CH3 request */ +#define DMA_REQUEST_TIM5_CH4 75U /*!< DMAMUX1 TIM5 CH4 request */ +#define DMA_REQUEST_TIM5_UP 76U /*!< DMAMUX1 TIM5 UP request */ +#define DMA_REQUEST_TIM5_TRIG 77U /*!< DMAMUX1 TIM5 TRIG request */ + +#define DMA_REQUEST_TIM15_CH1 78U /*!< DMAMUX1 TIM15 CH1 request */ +#define DMA_REQUEST_TIM15_UP 79U /*!< DMAMUX1 TIM15 UP request */ +#define DMA_REQUEST_TIM15_TRIG 80U /*!< DMAMUX1 TIM15 TRIG request */ +#define DMA_REQUEST_TIM15_COM 81U /*!< DMAMUX1 TIM15 COM request */ + +#define DMA_REQUEST_TIM16_CH1 82U /*!< DMAMUX1 TIM16 CH1 request */ +#define DMA_REQUEST_TIM16_UP 83U /*!< DMAMUX1 TIM16 UP request */ +#define DMA_REQUEST_TIM17_CH1 84U /*!< DMAMUX1 TIM17 CH1 request */ +#define DMA_REQUEST_TIM17_UP 85U /*!< DMAMUX1 TIM17 UP request */ + +#define DMA_REQUEST_DFSDM1_FLT0 86U /*!< DMAMUX1 DFSDM1 Filter0 request */ +#define DMA_REQUEST_DFSDM1_FLT1 87U /*!< DMAMUX1 DFSDM1 Filter1 request */ +#define DMA_REQUEST_DFSDM1_FLT2 88U /*!< DMAMUX1 DFSDM1 Filter2 request */ +#define DMA_REQUEST_DFSDM1_FLT3 89U /*!< DMAMUX1 DFSDM1 Filter3 request */ + +#define DMA_REQUEST_DCMI 90U /*!< DMAMUX1 DCMI request */ + +#define DMA_REQUEST_AES_IN 91U /*!< DMAMUX1 AES IN request */ +#define DMA_REQUEST_AES_OUT 92U /*!< DMAMUX1 AES OUT request */ + +#define DMA_REQUEST_HASH_IN 93U /*!< DMAMUX1 HASH IN request */ + +#endif /* DMAMUX1 */ + +/** + * @} + */ + +/** @defgroup DMA_Data_transfer_direction DMA Data transfer direction + * @{ + */ +#define DMA_PERIPH_TO_MEMORY ((uint32_t)0x00000000) /*!< Peripheral to memory direction */ +#define DMA_MEMORY_TO_PERIPH ((uint32_t)DMA_CCR_DIR) /*!< Memory to peripheral direction */ +#define DMA_MEMORY_TO_MEMORY ((uint32_t)DMA_CCR_MEM2MEM) /*!< Memory to memory direction */ +/** + * @} + */ + +/** @defgroup DMA_Peripheral_incremented_mode DMA Peripheral incremented mode + * @{ + */ +#define DMA_PINC_ENABLE ((uint32_t)DMA_CCR_PINC) /*!< Peripheral increment mode Enable */ +#define DMA_PINC_DISABLE ((uint32_t)0x00000000) /*!< Peripheral increment mode Disable */ +/** + * @} + */ + +/** @defgroup DMA_Memory_incremented_mode DMA Memory incremented mode + * @{ + */ +#define DMA_MINC_ENABLE ((uint32_t)DMA_CCR_MINC) /*!< Memory increment mode Enable */ +#define DMA_MINC_DISABLE ((uint32_t)0x00000000) /*!< Memory increment mode Disable */ +/** + * @} + */ + +/** @defgroup DMA_Peripheral_data_size DMA Peripheral data size + * @{ + */ +#define DMA_PDATAALIGN_BYTE ((uint32_t)0x00000000) /*!< Peripheral data alignment : Byte */ +#define DMA_PDATAALIGN_HALFWORD ((uint32_t)DMA_CCR_PSIZE_0) /*!< Peripheral data alignment : HalfWord */ +#define DMA_PDATAALIGN_WORD ((uint32_t)DMA_CCR_PSIZE_1) /*!< Peripheral data alignment : Word */ +/** + * @} + */ + +/** @defgroup DMA_Memory_data_size DMA Memory data size + * @{ + */ +#define DMA_MDATAALIGN_BYTE ((uint32_t)0x00000000) /*!< Memory data alignment : Byte */ +#define DMA_MDATAALIGN_HALFWORD ((uint32_t)DMA_CCR_MSIZE_0) /*!< Memory data alignment : HalfWord */ +#define DMA_MDATAALIGN_WORD ((uint32_t)DMA_CCR_MSIZE_1) /*!< Memory data alignment : Word */ +/** + * @} + */ + +/** @defgroup DMA_mode DMA mode + * @{ + */ +#define DMA_NORMAL ((uint32_t)0x00000000) /*!< Normal mode */ +#define DMA_CIRCULAR ((uint32_t)DMA_CCR_CIRC) /*!< Circular mode */ +/** + * @} + */ + +/** @defgroup DMA_Priority_level DMA Priority level + * @{ + */ +#define DMA_PRIORITY_LOW ((uint32_t)0x00000000) /*!< Priority level : Low */ +#define DMA_PRIORITY_MEDIUM ((uint32_t)DMA_CCR_PL_0) /*!< Priority level : Medium */ +#define DMA_PRIORITY_HIGH ((uint32_t)DMA_CCR_PL_1) /*!< Priority level : High */ +#define DMA_PRIORITY_VERY_HIGH ((uint32_t)DMA_CCR_PL) /*!< Priority level : Very_High */ +/** + * @} + */ + + +/** @defgroup DMA_interrupt_enable_definitions DMA interrupt enable definitions + * @{ + */ +#define DMA_IT_TC ((uint32_t)DMA_CCR_TCIE) +#define DMA_IT_HT ((uint32_t)DMA_CCR_HTIE) +#define DMA_IT_TE ((uint32_t)DMA_CCR_TEIE) +/** + * @} + */ + +/** @defgroup DMA_flag_definitions DMA flag definitions + * @{ + */ +#define DMA_FLAG_GL1 ((uint32_t)0x00000001) +#define DMA_FLAG_TC1 ((uint32_t)0x00000002) +#define DMA_FLAG_HT1 ((uint32_t)0x00000004) +#define DMA_FLAG_TE1 ((uint32_t)0x00000008) +#define DMA_FLAG_GL2 ((uint32_t)0x00000010) +#define DMA_FLAG_TC2 ((uint32_t)0x00000020) +#define DMA_FLAG_HT2 ((uint32_t)0x00000040) +#define DMA_FLAG_TE2 ((uint32_t)0x00000080) +#define DMA_FLAG_GL3 ((uint32_t)0x00000100) +#define DMA_FLAG_TC3 ((uint32_t)0x00000200) +#define DMA_FLAG_HT3 ((uint32_t)0x00000400) +#define DMA_FLAG_TE3 ((uint32_t)0x00000800) +#define DMA_FLAG_GL4 ((uint32_t)0x00001000) +#define DMA_FLAG_TC4 ((uint32_t)0x00002000) +#define DMA_FLAG_HT4 ((uint32_t)0x00004000) +#define DMA_FLAG_TE4 ((uint32_t)0x00008000) +#define DMA_FLAG_GL5 ((uint32_t)0x00010000) +#define DMA_FLAG_TC5 ((uint32_t)0x00020000) +#define DMA_FLAG_HT5 ((uint32_t)0x00040000) +#define DMA_FLAG_TE5 ((uint32_t)0x00080000) +#define DMA_FLAG_GL6 ((uint32_t)0x00100000) +#define DMA_FLAG_TC6 ((uint32_t)0x00200000) +#define DMA_FLAG_HT6 ((uint32_t)0x00400000) +#define DMA_FLAG_TE6 ((uint32_t)0x00800000) +#define DMA_FLAG_GL7 ((uint32_t)0x01000000) +#define DMA_FLAG_TC7 ((uint32_t)0x02000000) +#define DMA_FLAG_HT7 ((uint32_t)0x04000000) +#define DMA_FLAG_TE7 ((uint32_t)0x08000000) +/** + * @} + */ + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ +/** @defgroup DMA_Exported_Macros DMA Exported Macros + * @{ + */ + +/** @brief Reset DMA handle state. + * @param __HANDLE__: DMA handle + * @retval None + */ +#define __HAL_DMA_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_DMA_STATE_RESET) + +/** + * @brief Enable the specified DMA Channel. + * @param __HANDLE__: DMA handle + * @retval None + */ +#define __HAL_DMA_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CCR |= DMA_CCR_EN) + +/** + * @brief Disable the specified DMA Channel. + * @param __HANDLE__: DMA handle + * @retval None + */ +#define __HAL_DMA_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CCR &= ~DMA_CCR_EN) + + +/* Interrupt & Flag management */ + +/** + * @brief Return the current DMA Channel transfer complete flag. + * @param __HANDLE__: DMA handle + * @retval The specified transfer complete flag index. + */ + +#define __HAL_DMA_GET_TC_FLAG_INDEX(__HANDLE__) \ +(((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel1))? DMA_FLAG_TC1 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel1))? DMA_FLAG_TC1 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel2))? DMA_FLAG_TC2 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel2))? DMA_FLAG_TC2 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel3))? DMA_FLAG_TC3 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel3))? DMA_FLAG_TC3 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel4))? DMA_FLAG_TC4 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel4))? DMA_FLAG_TC4 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel5))? DMA_FLAG_TC5 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel5))? DMA_FLAG_TC5 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel6))? DMA_FLAG_TC6 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel6))? DMA_FLAG_TC6 :\ + DMA_FLAG_TC7) + +/** + * @brief Return the current DMA Channel half transfer complete flag. + * @param __HANDLE__: DMA handle + * @retval The specified half transfer complete flag index. + */ +#define __HAL_DMA_GET_HT_FLAG_INDEX(__HANDLE__)\ +(((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel1))? DMA_FLAG_HT1 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel1))? DMA_FLAG_HT1 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel2))? DMA_FLAG_HT2 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel2))? DMA_FLAG_HT2 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel3))? DMA_FLAG_HT3 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel3))? DMA_FLAG_HT3 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel4))? DMA_FLAG_HT4 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel4))? DMA_FLAG_HT4 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel5))? DMA_FLAG_HT5 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel5))? DMA_FLAG_HT5 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel6))? DMA_FLAG_HT6 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel6))? DMA_FLAG_HT6 :\ + DMA_FLAG_HT7) + +/** + * @brief Return the current DMA Channel transfer error flag. + * @param __HANDLE__: DMA handle + * @retval The specified transfer error flag index. + */ +#define __HAL_DMA_GET_TE_FLAG_INDEX(__HANDLE__)\ +(((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel1))? DMA_FLAG_TE1 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel1))? DMA_FLAG_TE1 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel2))? DMA_FLAG_TE2 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel2))? DMA_FLAG_TE2 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel3))? DMA_FLAG_TE3 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel3))? DMA_FLAG_TE3 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel4))? DMA_FLAG_TE4 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel4))? DMA_FLAG_TE4 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel5))? DMA_FLAG_TE5 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel5))? DMA_FLAG_TE5 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel6))? DMA_FLAG_TE6 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel6))? DMA_FLAG_TE6 :\ + DMA_FLAG_TE7) + +/** + * @brief Return the current DMA Channel Global interrupt flag. + * @param __HANDLE__: DMA handle + * @retval The specified transfer error flag index. + */ +#define __HAL_DMA_GET_GI_FLAG_INDEX(__HANDLE__)\ +(((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel1))? DMA_ISR_GIF1 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel1))? DMA_ISR_GIF1 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel2))? DMA_ISR_GIF2 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel2))? DMA_ISR_GIF2 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel3))? DMA_ISR_GIF3 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel3))? DMA_ISR_GIF3 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel4))? DMA_ISR_GIF4 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel4))? DMA_ISR_GIF4 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel5))? DMA_ISR_GIF5 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel5))? DMA_ISR_GIF5 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA1_Channel6))? DMA_ISR_GIF6 :\ + ((uint32_t)((__HANDLE__)->Instance) == ((uint32_t)DMA2_Channel6))? DMA_ISR_GIF6 :\ + DMA_ISR_GIF7) + +/** + * @brief Get the DMA Channel pending flags. + * @param __HANDLE__: DMA handle + * @param __FLAG__: Get the specified flag. + * This parameter can be any combination of the following values: + * @arg DMA_FLAG_TCx: Transfer complete flag + * @arg DMA_FLAG_HTx: Half transfer complete flag + * @arg DMA_FLAG_TEx: Transfer error flag + * @arg DMA_FLAG_GLx: Global interrupt flag + * Where x can be from 1 to 7 to select the DMA Channel x flag. + * @retval The state of FLAG (SET or RESET). + */ +#define __HAL_DMA_GET_FLAG(__HANDLE__, __FLAG__) (((uint32_t)((__HANDLE__)->Instance) > ((uint32_t)DMA1_Channel7))? \ + (DMA2->ISR & (__FLAG__)) : (DMA1->ISR & (__FLAG__))) + +/** + * @brief Clear the DMA Channel pending flags. + * @param __HANDLE__: DMA handle + * @param __FLAG__: specifies the flag to clear. + * This parameter can be any combination of the following values: + * @arg DMA_FLAG_TCx: Transfer complete flag + * @arg DMA_FLAG_HTx: Half transfer complete flag + * @arg DMA_FLAG_TEx: Transfer error flag + * @arg DMA_FLAG_GLx: Global interrupt flag + * Where x can be from 1 to 7 to select the DMA Channel x flag. + * @retval None + */ +#define __HAL_DMA_CLEAR_FLAG(__HANDLE__, __FLAG__) (((uint32_t)((__HANDLE__)->Instance) > ((uint32_t)DMA1_Channel7))? \ + (DMA2->IFCR = (__FLAG__)) : (DMA1->IFCR = (__FLAG__))) + +/** + * @brief Enable the specified DMA Channel interrupts. + * @param __HANDLE__: DMA handle + * @param __INTERRUPT__: specifies the DMA interrupt sources to be enabled or disabled. + * This parameter can be any combination of the following values: + * @arg DMA_IT_TC: Transfer complete interrupt mask + * @arg DMA_IT_HT: Half transfer complete interrupt mask + * @arg DMA_IT_TE: Transfer error interrupt mask + * @retval None + */ +#define __HAL_DMA_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CCR |= (__INTERRUPT__)) + +/** + * @brief Disable the specified DMA Channel interrupts. + * @param __HANDLE__: DMA handle + * @param __INTERRUPT__: specifies the DMA interrupt sources to be enabled or disabled. + * This parameter can be any combination of the following values: + * @arg DMA_IT_TC: Transfer complete interrupt mask + * @arg DMA_IT_HT: Half transfer complete interrupt mask + * @arg DMA_IT_TE: Transfer error interrupt mask + * @retval None + */ +#define __HAL_DMA_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CCR &= ~(__INTERRUPT__)) + +/** + * @brief Check whether the specified DMA Channel interrupt is enabled or not. + * @param __HANDLE__: DMA handle + * @param __INTERRUPT__: specifies the DMA interrupt source to check. + * This parameter can be one of the following values: + * @arg DMA_IT_TC: Transfer complete interrupt mask + * @arg DMA_IT_HT: Half transfer complete interrupt mask + * @arg DMA_IT_TE: Transfer error interrupt mask + * @retval The state of DMA_IT (SET or RESET). + */ +#define __HAL_DMA_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->CCR & (__INTERRUPT__))) + +/** + * @brief Return the number of remaining data units in the current DMA Channel transfer. + * @param __HANDLE__: DMA handle + * @retval The number of remaining data units in the current DMA Channel transfer. + */ +#define __HAL_DMA_GET_COUNTER(__HANDLE__) ((__HANDLE__)->Instance->CNDTR) + +/** + * @} + */ + +#if defined(DMAMUX1) +/* Include DMA HAL Extension module */ +#include "stm32l4xx_hal_dma_ex.h" +#endif /* DMAMUX1 */ + +/* Exported functions --------------------------------------------------------*/ + +/** @addtogroup DMA_Exported_Functions + * @{ + */ + +/** @addtogroup DMA_Exported_Functions_Group1 + * @{ + */ +/* Initialization and de-initialization functions *****************************/ +HAL_StatusTypeDef HAL_DMA_Init(DMA_HandleTypeDef *hdma); +HAL_StatusTypeDef HAL_DMA_DeInit (DMA_HandleTypeDef *hdma); +/** + * @} + */ + +/** @addtogroup DMA_Exported_Functions_Group2 + * @{ + */ +/* IO operation functions *****************************************************/ +HAL_StatusTypeDef HAL_DMA_Start (DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength); +HAL_StatusTypeDef HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength); +HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *hdma); +HAL_StatusTypeDef HAL_DMA_Abort_IT(DMA_HandleTypeDef *hdma); +HAL_StatusTypeDef HAL_DMA_PollForTransfer(DMA_HandleTypeDef *hdma, HAL_DMA_LevelCompleteTypeDef CompleteLevel, uint32_t Timeout); +void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma); +HAL_StatusTypeDef HAL_DMA_RegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID, void (* pCallback)( DMA_HandleTypeDef * _hdma)); +HAL_StatusTypeDef HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID); + +/** + * @} + */ + +/** @addtogroup DMA_Exported_Functions_Group3 + * @{ + */ +/* Peripheral State and Error functions ***************************************/ +HAL_DMA_StateTypeDef HAL_DMA_GetState(DMA_HandleTypeDef *hdma); +uint32_t HAL_DMA_GetError(DMA_HandleTypeDef *hdma); +/** + * @} + */ + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup DMA_Private_Macros DMA Private Macros + * @{ + */ + +#define IS_DMA_DIRECTION(DIRECTION) (((DIRECTION) == DMA_PERIPH_TO_MEMORY ) || \ + ((DIRECTION) == DMA_MEMORY_TO_PERIPH) || \ + ((DIRECTION) == DMA_MEMORY_TO_MEMORY)) + +#define IS_DMA_BUFFER_SIZE(SIZE) (((SIZE) >= 0x1) && ((SIZE) < 0x10000)) + +#define IS_DMA_PERIPHERAL_INC_STATE(STATE) (((STATE) == DMA_PINC_ENABLE) || \ + ((STATE) == DMA_PINC_DISABLE)) + +#define IS_DMA_MEMORY_INC_STATE(STATE) (((STATE) == DMA_MINC_ENABLE) || \ + ((STATE) == DMA_MINC_DISABLE)) + +#if !defined (DMAMUX1) + +#define IS_DMA_ALL_REQUEST(REQUEST) (((REQUEST) == DMA_REQUEST_0) || \ + ((REQUEST) == DMA_REQUEST_1) || \ + ((REQUEST) == DMA_REQUEST_2) || \ + ((REQUEST) == DMA_REQUEST_3) || \ + ((REQUEST) == DMA_REQUEST_4) || \ + ((REQUEST) == DMA_REQUEST_5) || \ + ((REQUEST) == DMA_REQUEST_6) || \ + ((REQUEST) == DMA_REQUEST_7)) +#endif + +#if defined(DMAMUX1) + +#define IS_DMA_ALL_REQUEST(REQUEST)((REQUEST) <= DMA_REQUEST_HASH_IN) + +#endif /* DMAMUX1 */ + +#define IS_DMA_PERIPHERAL_DATA_SIZE(SIZE) (((SIZE) == DMA_PDATAALIGN_BYTE) || \ + ((SIZE) == DMA_PDATAALIGN_HALFWORD) || \ + ((SIZE) == DMA_PDATAALIGN_WORD)) + +#define IS_DMA_MEMORY_DATA_SIZE(SIZE) (((SIZE) == DMA_MDATAALIGN_BYTE) || \ + ((SIZE) == DMA_MDATAALIGN_HALFWORD) || \ + ((SIZE) == DMA_MDATAALIGN_WORD )) + +#define IS_DMA_MODE(MODE) (((MODE) == DMA_NORMAL ) || \ + ((MODE) == DMA_CIRCULAR)) + +#define IS_DMA_PRIORITY(PRIORITY) (((PRIORITY) == DMA_PRIORITY_LOW ) || \ + ((PRIORITY) == DMA_PRIORITY_MEDIUM) || \ + ((PRIORITY) == DMA_PRIORITY_HIGH) || \ + ((PRIORITY) == DMA_PRIORITY_VERY_HIGH)) + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_HAL_DMA_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_dma_ex.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_dma_ex.h new file mode 100644 index 0000000..0ce4b2a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_dma_ex.h @@ -0,0 +1,298 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_dma_ex.h + * @author MCD Application Team + * @brief Header file of DMA HAL extension module. + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_DMA_EX_H +#define __STM32L4xx_HAL_DMA_EX_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(DMAMUX1) + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup DMAEx + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup DMAEx_Exported_Types DMAEx Exported Types + * @{ + */ + +/** + * @brief HAL DMA Synchro definition + */ + + +/** + * @brief HAL DMAMUX Synchronization configuration structure definition + */ +typedef struct +{ + uint32_t SyncSignalID; /*!< Specifies the synchronization signal gating the DMA request in periodic mode. + This parameter can be a value of @ref DMAEx_DMAMUX_SyncSignalID_selection */ + + uint32_t SyncPolarity; /*!< Specifies the polarity of the signal on which the DMA request is synchronized. + This parameter can be a value of @ref DMAEx_DMAMUX_SyncPolarity_selection */ + + FunctionalState SyncEnable; /*!< Specifies if the synchronization shall be enabled or disabled + This parameter can take the value ENABLE or DISABLE*/ + + + FunctionalState EventEnable; /*!< Specifies if an event shall be generated once the RequestNumber is reached. + This parameter can take the value ENABLE or DISABLE */ + + uint32_t RequestNumber; /*!< Specifies the number of DMA request that will be authorized after a sync event + This parameter must be a number between Min_Data = 1 and Max_Data = 32 */ + + +}HAL_DMA_MuxSyncConfigTypeDef; + + +/** + * @brief HAL DMAMUX request generator parameters structure definition + */ +typedef struct +{ + uint32_t SignalID; /*!< Specifies the ID of the signal used for DMAMUX request generator + This parameter can be a value of @ref DMAEx_DMAMUX_SignalGeneratorID_selection */ + + uint32_t Polarity; /*!< Specifies the polarity of the signal on which the request is generated. + This parameter can be a value of @ref DMAEx_DMAMUX_RequestGeneneratorPolarity_selection */ + + uint32_t RequestNumber; /*!< Specifies the number of DMA request that will be generated after a signal event + This parameter must be a number between Min_Data = 1 and Max_Data = 32 */ + +}HAL_DMA_MuxRequestGeneratorConfigTypeDef; + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup DMAEx_Exported_Constants DMAEx Exported Constants + * @{ + */ + +/** @defgroup DMAEx_DMAMUX_SyncSignalID_selection DMAMUX SyncSignalID selection + * @{ + */ +#define HAL_DMAMUX1_SYNC_EXTI0 0U /*!< Synchronization Signal is EXTI0 IT */ +#define HAL_DMAMUX1_SYNC_EXTI1 1U /*!< Synchronization Signal is EXTI1 IT */ +#define HAL_DMAMUX1_SYNC_EXTI2 2U /*!< Synchronization Signal is EXTI2 IT */ +#define HAL_DMAMUX1_SYNC_EXTI3 3U /*!< Synchronization Signal is EXTI3 IT */ +#define HAL_DMAMUX1_SYNC_EXTI4 4U /*!< Synchronization Signal is EXTI4 IT */ +#define HAL_DMAMUX1_SYNC_EXTI5 5U /*!< Synchronization Signal is EXTI5 IT */ +#define HAL_DMAMUX1_SYNC_EXTI6 6U /*!< Synchronization Signal is EXTI6 IT */ +#define HAL_DMAMUX1_SYNC_EXTI7 7U /*!< Synchronization Signal is EXTI7 IT */ +#define HAL_DMAMUX1_SYNC_EXTI8 8U /*!< Synchronization Signal is EXTI8 IT */ +#define HAL_DMAMUX1_SYNC_EXTI9 9U /*!< Synchronization Signal is EXTI9 IT */ +#define HAL_DMAMUX1_SYNC_EXTI10 10U /*!< Synchronization Signal is EXTI10 IT */ +#define HAL_DMAMUX1_SYNC_EXTI11 11U /*!< Synchronization Signal is EXTI11 IT */ +#define HAL_DMAMUX1_SYNC_EXTI12 12U /*!< Synchronization Signal is EXTI12 IT */ +#define HAL_DMAMUX1_SYNC_EXTI13 13U /*!< Synchronization Signal is EXTI13 IT */ +#define HAL_DMAMUX1_SYNC_EXTI14 14U /*!< Synchronization Signal is EXTI14 IT */ +#define HAL_DMAMUX1_SYNC_EXTI15 15U /*!< Synchronization Signal is EXTI15 IT */ +#define HAL_DMAMUX1_SYNC_DMAMUX1_CH0_EVT 16U /*!< Synchronization Signal is DMAMUX1 Channel0 Event */ +#define HAL_DMAMUX1_SYNC_DMAMUX1_CH1_EVT 17U /*!< Synchronization Signal is DMAMUX1 Channel1 Event */ +#define HAL_DMAMUX1_SYNC_DMAMUX1_CH2_EVT 18U /*!< Synchronization Signal is DMAMUX1 Channel2 Event */ +#define HAL_DMAMUX1_SYNC_DMAMUX1_CH3_EVT 19U /*!< Synchronization Signal is DMAMUX1 Channel3 Event */ +#define HAL_DMAMUX1_SYNC_LPTIM1_OUT 20U /*!< Synchronization Signal is LPTIM1 OUT */ +#define HAL_DMAMUX1_SYNC_LPTIM2_OUT 21U /*!< Synchronization Signal is LPTIM2 OUT */ +#define HAL_DMAMUX1_SYNC_DSI_TE 22U /*!< Synchronization Signal is DSI Tearing Effect */ +#define HAL_DMAMUX1_SYNC_DSI_EOT 23U /*!< Synchronization Signal is DSI End of refresh */ +#define HAL_DMAMUX1_SYNC_DMA2D_EOT 24U /*!< Synchronization Signal is DMA2D End of Transfer */ +#define HAL_DMAMUX1_SYNC_LDTC_IT 25U /*!< Synchronization Signal is LDTC IT */ + +/** + * @} + */ + +/** @defgroup DMAEx_DMAMUX_SyncPolarity_selection DMAMUX SyncPolarity selection + * @{ + */ +#define HAL_DMAMUX_SYNC_NO_EVENT 0U /*!< block synchronization events */ +#define HAL_DMAMUX_SYNC_RISING ((uint32_t)DMAMUX_CxCR_SPOL_0) /*!< synchronize with rising edge events */ +#define HAL_DMAMUX_SYNC_FALLING ((uint32_t)DMAMUX_CxCR_SPOL_1) /*!< synchronize with falling edge events */ +#define HAL_DMAMUX_SYNC_RISING_FALLING ((uint32_t)DMAMUX_CxCR_SPOL) /*!< synchronize with rising and falling edge events */ + +/** + * @} + */ + +/** @defgroup DMAEx_DMAMUX_SignalGeneratorID_selection DMAMUX SignalGeneratorID selection + * @{ + */ + +#define HAL_DMAMUX1_REQUEST_GEN_EXTI0 0U /*!< Request generator Signal is EXTI0 IT */ +#define HAL_DMAMUX1_REQUEST_GEN_EXTI1 1U /*!< Request generator Signal is EXTI1 IT */ +#define HAL_DMAMUX1_REQUEST_GEN_EXTI2 2U /*!< Request generator Signal is EXTI2 IT */ +#define HAL_DMAMUX1_REQUEST_GEN_EXTI3 3U /*!< Request generator Signal is EXTI3 IT */ +#define HAL_DMAMUX1_REQUEST_GEN_EXTI4 4U /*!< Request generator Signal is EXTI4 IT */ +#define HAL_DMAMUX1_REQUEST_GEN_EXTI5 5U /*!< Request generator Signal is EXTI5 IT */ +#define HAL_DMAMUX1_REQUEST_GEN_EXTI6 6U /*!< Request generator Signal is EXTI6 IT */ +#define HAL_DMAMUX1_REQUEST_GEN_EXTI7 7U /*!< Request generator Signal is EXTI7 IT */ +#define HAL_DMAMUX1_REQUEST_GEN_EXTI8 8U /*!< Request generator Signal is EXTI8 IT */ +#define HAL_DMAMUX1_REQUEST_GEN_EXTI9 9U /*!< Request generator Signal is EXTI9 IT */ +#define HAL_DMAMUX1_REQUEST_GEN_EXTI10 10U /*!< Request generator Signal is EXTI10 IT */ +#define HAL_DMAMUX1_REQUEST_GEN_EXTI11 11U /*!< Request generator Signal is EXTI11 IT */ +#define HAL_DMAMUX1_REQUEST_GEN_EXTI12 12U /*!< Request generator Signal is EXTI12 IT */ +#define HAL_DMAMUX1_REQUEST_GEN_EXTI13 13U /*!< Request generator Signal is EXTI13 IT */ +#define HAL_DMAMUX1_REQUEST_GEN_EXTI14 14U /*!< Request generator Signal is EXTI14 IT */ +#define HAL_DMAMUX1_REQUEST_GEN_EXTI15 15U /*!< Request generator Signal is EXTI15 IT */ +#define HAL_DMAMUX1_REQUEST_GEN_DMAMUX1_CH0_EVT 16U /*!< Request generator Signal is DMAMUX1 Channel0 Event */ +#define HAL_DMAMUX1_REQUEST_GEN_DMAMUX1_CH1_EVT 17U /*!< Request generator Signal is DMAMUX1 Channel1 Event */ +#define HAL_DMAMUX1_REQUEST_GEN_DMAMUX1_CH2_EVT 18U /*!< Request generator Signal is DMAMUX1 Channel2 Event */ +#define HAL_DMAMUX1_REQUEST_GEN_DMAMUX1_CH3_EVT 19U /*!< Request generator Signal is DMAMUX1 Channel3 Event */ +#define HAL_DMAMUX1_REQUEST_GEN_LPTIM1_OUT 20U /*!< Request generator Signal is LPTIM1 OUT */ +#define HAL_DMAMUX1_REQUEST_GEN_LPTIM2_OUT 21U /*!< Request generator Signal is LPTIM2 OUT */ +#define HAL_DMAMUX1_REQUEST_GEN_DSI_TE 22U /*!< Request generator Signal is DSI Tearing Effect */ +#define HAL_DMAMUX1_REQUEST_GEN_DSI_EOT 23U /*!< Request generator Signal is DSI End of refresh */ +#define HAL_DMAMUX1_REQUEST_GEN_DMA2D_EOT 24U /*!< Request generator Signal is DMA2D End of Transfer */ +#define HAL_DMAMUX1_REQUEST_GEN_LTDC_IT 25U /*!< Request generator Signal is LTDC IT */ + +/** + * @} + */ + +/** @defgroup DMAEx_DMAMUX_RequestGeneneratorPolarity_selection DMAMUX RequestGeneneratorPolarity selection + * @{ + */ +#define HAL_DMAMUX_REQUEST_GEN_NO_EVENT 0U /*!< block request generator events */ +#define HAL_DMAMUX_REQUEST_GEN_RISING DMAMUX_RGxCR_GPOL_0 /*!< generate request on rising edge events */ +#define HAL_DMAMUX_REQUEST_GEN_FALLING DMAMUX_RGxCR_GPOL_1 /*!< generate request on falling edge events */ +#define HAL_DMAMUX_REQUEST_GEN_RISING_FALLING DMAMUX_RGxCR_GPOL /*!< generate request on rising and falling edge events */ + +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup DMAEx_Exported_Functions + * @{ + */ + +/* IO operation functions *****************************************************/ +/** @addtogroup DMAEx_Exported_Functions_Group1 + * @{ + */ + +/* ------------------------- REQUEST -----------------------------------------*/ +HAL_StatusTypeDef HAL_DMAEx_ConfigMuxRequestGenerator (DMA_HandleTypeDef *hdma, + HAL_DMA_MuxRequestGeneratorConfigTypeDef *pRequestGeneratorConfig); +HAL_StatusTypeDef HAL_DMAEx_EnableMuxRequestGenerator (DMA_HandleTypeDef *hdma); +HAL_StatusTypeDef HAL_DMAEx_DisableMuxRequestGenerator (DMA_HandleTypeDef *hdma); +/* -------------------------------------------------------------------------- */ + +/* ------------------------- SYNCHRO -----------------------------------------*/ +HAL_StatusTypeDef HAL_DMAEx_ConfigMuxSync(DMA_HandleTypeDef *hdma, HAL_DMA_MuxSyncConfigTypeDef *pSyncConfig); +/* -------------------------------------------------------------------------- */ + +void HAL_DMAEx_MUX_IRQHandler(DMA_HandleTypeDef *hdma); + +/** + * @} + */ + +/** + * @} + */ + + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup DMAEx_Private_Macros DMAEx Private Macros + * @brief DMAEx private macros + * @{ + */ + +#define IS_DMAMUX_SYNC_SIGNAL_ID(SIGNAL_ID) ((SIGNAL_ID) <= HAL_DMAMUX1_SYNC_LDTC_IT) + +#define IS_DMAMUX_SYNC_REQUEST_NUMBER(REQUEST_NUMBER) (((REQUEST_NUMBER) > 0) && ((REQUEST_NUMBER) <= 32)) + +#define IS_DMAMUX_SYNC_POLARITY(POLARITY) (((POLARITY) == HAL_DMAMUX_SYNC_NO_EVENT) || \ + ((POLARITY) == HAL_DMAMUX_SYNC_RISING) || \ + ((POLARITY) == HAL_DMAMUX_SYNC_FALLING) || \ + ((POLARITY) == HAL_DMAMUX_SYNC_RISING_FALLING)) + +#define IS_DMAMUX_SYNC_STATE(SYNC) (((SYNC) == DISABLE) || ((SYNC) == ENABLE)) + +#define IS_DMAMUX_SYNC_EVENT(EVENT) (((EVENT) == DISABLE) || \ + ((EVENT) == ENABLE)) + +#define IS_DMAMUX_REQUEST_GEN_SIGNAL_ID(SIGNAL_ID) ((SIGNAL_ID) <= HAL_DMAMUX1_REQUEST_GEN_LTDC_IT) + +#define IS_DMAMUX_REQUEST_GEN_REQUEST_NUMBER(REQUEST_NUMBER) (((REQUEST_NUMBER) > 0) && ((REQUEST_NUMBER) <= 32)) + +#define IS_DMAMUX_REQUEST_GEN_POLARITY(POLARITY) (((POLARITY) == HAL_DMAMUX_REQUEST_GEN_NO_EVENT) || \ + ((POLARITY) == HAL_DMAMUX_REQUEST_GEN_RISING) || \ + ((POLARITY) == HAL_DMAMUX_REQUEST_GEN_FALLING) || \ + ((POLARITY) == HAL_DMAMUX_REQUEST_GEN_RISING_FALLING)) + +/** + * @} + */ + + +/** + * @} + */ + +/** + * @} + */ + +#endif /* DMAMUX1 */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_HAL_DMA_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash.h new file mode 100644 index 0000000..ef4ea30 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash.h @@ -0,0 +1,1022 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_flash.h + * @author MCD Application Team + * @brief Header file of FLASH HAL module. + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_FLASH_H +#define __STM32L4xx_HAL_FLASH_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup FLASH + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup FLASH_Exported_Types FLASH Exported Types + * @{ + */ + +/** + * @brief FLASH Erase structure definition + */ +typedef struct +{ + uint32_t TypeErase; /*!< Mass erase or page erase. + This parameter can be a value of @ref FLASH_Type_Erase */ + uint32_t Banks; /*!< Select bank to erase. + This parameter must be a value of @ref FLASH_Banks + (FLASH_BANK_BOTH should be used only for mass erase) */ + uint32_t Page; /*!< Initial Flash page to erase when page erase is disabled + This parameter must be a value between 0 and (max number of pages in the bank - 1) + (eg : 255 for 1MB dual bank) */ + uint32_t NbPages; /*!< Number of pages to be erased. + This parameter must be a value between 1 and (max number of pages in the bank - value of initial page)*/ +} FLASH_EraseInitTypeDef; + +/** + * @brief FLASH Option Bytes Program structure definition + */ +typedef struct +{ + uint32_t OptionType; /*!< Option byte to be configured. + This parameter can be a combination of the values of @ref FLASH_OB_Type */ + uint32_t WRPArea; /*!< Write protection area to be programmed (used for OPTIONBYTE_WRP). + Only one WRP area could be programmed at the same time. + This parameter can be value of @ref FLASH_OB_WRP_Area */ + uint32_t WRPStartOffset; /*!< Write protection start offset (used for OPTIONBYTE_WRP). + This parameter must be a value between 0 and (max number of pages in the bank - 1) + (eg : 25 for 1MB dual bank) */ + uint32_t WRPEndOffset; /*!< Write protection end offset (used for OPTIONBYTE_WRP). + This parameter must be a value between WRPStartOffset and (max number of pages in the bank - 1) */ + uint32_t RDPLevel; /*!< Set the read protection level.. (used for OPTIONBYTE_RDP). + This parameter can be a value of @ref FLASH_OB_Read_Protection */ + uint32_t USERType; /*!< User option byte(s) to be configured (used for OPTIONBYTE_USER). + This parameter can be a combination of @ref FLASH_OB_USER_Type */ + uint32_t USERConfig; /*!< Value of the user option byte (used for OPTIONBYTE_USER). + This parameter can be a combination of @ref FLASH_OB_USER_BOR_LEVEL, + @ref FLASH_OB_USER_nRST_STOP, @ref FLASH_OB_USER_nRST_STANDBY, + @ref FLASH_OB_USER_nRST_SHUTDOWN, @ref FLASH_OB_USER_IWDG_SW, + @ref FLASH_OB_USER_IWDG_STOP, @ref FLASH_OB_USER_IWDG_STANDBY, + @ref FLASH_OB_USER_WWDG_SW, @ref FLASH_OB_USER_BFB2, + @ref FLASH_OB_USER_DUALBANK, @ref FLASH_OB_USER_nBOOT1, + @ref FLASH_OB_USER_SRAM2_PE and @ref FLASH_OB_USER_SRAM2_RST */ + uint32_t PCROPConfig; /*!< Configuration of the PCROP (used for OPTIONBYTE_PCROP). + This parameter must be a combination of @ref FLASH_Banks (except FLASH_BANK_BOTH) + and @ref FLASH_OB_PCROP_RDP */ + uint32_t PCROPStartAddr; /*!< PCROP Start address (used for OPTIONBYTE_PCROP). + This parameter must be a value between begin and end of bank + => Be careful of the bank swapping for the address */ + uint32_t PCROPEndAddr; /*!< PCROP End address (used for OPTIONBYTE_PCROP). + This parameter must be a value between PCROP Start address and end of bank */ +} FLASH_OBProgramInitTypeDef; + +/** + * @brief FLASH Procedure structure definition + */ +typedef enum +{ + FLASH_PROC_NONE = 0, + FLASH_PROC_PAGE_ERASE, + FLASH_PROC_MASS_ERASE, + FLASH_PROC_PROGRAM, + FLASH_PROC_PROGRAM_LAST +} FLASH_ProcedureTypeDef; + +/** + * @brief FLASH Cache structure definition + */ +typedef enum +{ + FLASH_CACHE_DISABLED = 0, + FLASH_CACHE_ICACHE_ENABLED, + FLASH_CACHE_DCACHE_ENABLED, + FLASH_CACHE_ICACHE_DCACHE_ENABLED +} FLASH_CacheTypeDef; + +/** + * @brief FLASH handle Structure definition + */ +typedef struct +{ + HAL_LockTypeDef Lock; /* FLASH locking object */ + __IO uint32_t ErrorCode; /* FLASH error code */ + __IO FLASH_ProcedureTypeDef ProcedureOnGoing; /* Internal variable to indicate which procedure is ongoing or not in IT context */ + __IO uint32_t Address; /* Internal variable to save address selected for program in IT context */ + __IO uint32_t Bank; /* Internal variable to save current bank selected during erase in IT context */ + __IO uint32_t Page; /* Internal variable to define the current page which is erasing in IT context */ + __IO uint32_t NbPagesToErase; /* Internal variable to save the remaining pages to erase in IT context */ + __IO FLASH_CacheTypeDef CacheToReactivate; /* Internal variable to indicate which caches should be reactivated */ +}FLASH_ProcessTypeDef; + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup FLASH_Exported_Constants FLASH Exported Constants + * @{ + */ + +/** @defgroup FLASH_Error FLASH Error + * @{ + */ +#define HAL_FLASH_ERROR_NONE ((uint32_t)0x00000000) +#define HAL_FLASH_ERROR_OP ((uint32_t)0x00000001) +#define HAL_FLASH_ERROR_PROG ((uint32_t)0x00000002) +#define HAL_FLASH_ERROR_WRP ((uint32_t)0x00000004) +#define HAL_FLASH_ERROR_PGA ((uint32_t)0x00000008) +#define HAL_FLASH_ERROR_SIZ ((uint32_t)0x00000010) +#define HAL_FLASH_ERROR_PGS ((uint32_t)0x00000020) +#define HAL_FLASH_ERROR_MIS ((uint32_t)0x00000040) +#define HAL_FLASH_ERROR_FAST ((uint32_t)0x00000080) +#define HAL_FLASH_ERROR_RD ((uint32_t)0x00000100) +#define HAL_FLASH_ERROR_OPTV ((uint32_t)0x00000200) +#define HAL_FLASH_ERROR_ECCD ((uint32_t)0x00000400) +#if defined (STM32L431xx) || defined (STM32L432xx) || defined (STM32L433xx) || defined (STM32L442xx) || defined (STM32L443xx) || \ + defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define HAL_FLASH_ERROR_PEMPTY ((uint32_t)0x00000800) +#endif +/** + * @} + */ + +/** @defgroup FLASH_Type_Erase FLASH Erase Type + * @{ + */ +#define FLASH_TYPEERASE_PAGES ((uint32_t)0x00) /*!> 24) /*!< ECC Correction Interrupt source */ +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ +/** @defgroup FLASH_Exported_Macros FLASH Exported Macros + * @brief macros to control FLASH features + * @{ + */ + +/** + * @brief Set the FLASH Latency. + * @param __LATENCY__: FLASH Latency + * This parameter can be one of the following values : + * @arg FLASH_LATENCY_0: FLASH Zero wait state + * @arg FLASH_LATENCY_1: FLASH One wait state + * @arg FLASH_LATENCY_2: FLASH Two wait states + * @arg FLASH_LATENCY_3: FLASH Three wait states + * @arg FLASH_LATENCY_4: FLASH Four wait states + * @retval None + */ +#define __HAL_FLASH_SET_LATENCY(__LATENCY__) (MODIFY_REG(FLASH->ACR, FLASH_ACR_LATENCY, (__LATENCY__))) + +/** + * @brief Get the FLASH Latency. + * @retval FLASH Latency + * This parameter can be one of the following values : + * @arg FLASH_LATENCY_0: FLASH Zero wait state + * @arg FLASH_LATENCY_1: FLASH One wait state + * @arg FLASH_LATENCY_2: FLASH Two wait states + * @arg FLASH_LATENCY_3: FLASH Three wait states + * @arg FLASH_LATENCY_4: FLASH Four wait states + */ +#define __HAL_FLASH_GET_LATENCY() READ_BIT(FLASH->ACR, FLASH_ACR_LATENCY) + +/** + * @brief Enable the FLASH prefetch buffer. + * @retval None + */ +#define __HAL_FLASH_PREFETCH_BUFFER_ENABLE() SET_BIT(FLASH->ACR, FLASH_ACR_PRFTEN) + +/** + * @brief Disable the FLASH prefetch buffer. + * @retval None + */ +#define __HAL_FLASH_PREFETCH_BUFFER_DISABLE() CLEAR_BIT(FLASH->ACR, FLASH_ACR_PRFTEN) + +/** + * @brief Enable the FLASH instruction cache. + * @retval none + */ +#define __HAL_FLASH_INSTRUCTION_CACHE_ENABLE() SET_BIT(FLASH->ACR, FLASH_ACR_ICEN) + +/** + * @brief Disable the FLASH instruction cache. + * @retval none + */ +#define __HAL_FLASH_INSTRUCTION_CACHE_DISABLE() CLEAR_BIT(FLASH->ACR, FLASH_ACR_ICEN) + +/** + * @brief Enable the FLASH data cache. + * @retval none + */ +#define __HAL_FLASH_DATA_CACHE_ENABLE() SET_BIT(FLASH->ACR, FLASH_ACR_DCEN) + +/** + * @brief Disable the FLASH data cache. + * @retval none + */ +#define __HAL_FLASH_DATA_CACHE_DISABLE() CLEAR_BIT(FLASH->ACR, FLASH_ACR_DCEN) + +/** + * @brief Reset the FLASH instruction Cache. + * @note This function must be used only when the Instruction Cache is disabled. + * @retval None + */ +#define __HAL_FLASH_INSTRUCTION_CACHE_RESET() do { SET_BIT(FLASH->ACR, FLASH_ACR_ICRST); \ + CLEAR_BIT(FLASH->ACR, FLASH_ACR_ICRST); \ + } while (0) + +/** + * @brief Reset the FLASH data Cache. + * @note This function must be used only when the data Cache is disabled. + * @retval None + */ +#define __HAL_FLASH_DATA_CACHE_RESET() do { SET_BIT(FLASH->ACR, FLASH_ACR_DCRST); \ + CLEAR_BIT(FLASH->ACR, FLASH_ACR_DCRST); \ + } while (0) + +/** + * @brief Enable the FLASH power down during Low-power run mode. + * @note Writing this bit to 0 this bit, automatically the keys are + * loss and a new unlock sequence is necessary to re-write it to 1. + */ +#define __HAL_FLASH_POWER_DOWN_ENABLE() do { WRITE_REG(FLASH->PDKEYR, FLASH_PDKEY1); \ + WRITE_REG(FLASH->PDKEYR, FLASH_PDKEY2); \ + SET_BIT(FLASH->ACR, FLASH_ACR_RUN_PD); \ + } while (0) + +/** + * @brief Disable the FLASH power down during Low-power run mode. + * @note Writing this bit to 0 this bit, automatically the keys are + * loss and a new unlock sequence is necessary to re-write it to 1. + */ +#define __HAL_FLASH_POWER_DOWN_DISABLE() do { WRITE_REG(FLASH->PDKEYR, FLASH_PDKEY1); \ + WRITE_REG(FLASH->PDKEYR, FLASH_PDKEY2); \ + CLEAR_BIT(FLASH->ACR, FLASH_ACR_RUN_PD); \ + } while (0) + +/** + * @brief Enable the FLASH power down during Low-Power sleep mode + * @retval none + */ +#define __HAL_FLASH_SLEEP_POWERDOWN_ENABLE() SET_BIT(FLASH->ACR, FLASH_ACR_SLEEP_PD) + +/** + * @brief Disable the FLASH power down during Low-Power sleep mode + * @retval none + */ +#define __HAL_FLASH_SLEEP_POWERDOWN_DISABLE() CLEAR_BIT(FLASH->ACR, FLASH_ACR_SLEEP_PD) + +/** + * @} + */ + +/** @defgroup FLASH_Interrupt FLASH Interrupts Macros + * @brief macros to handle FLASH interrupts + * @{ + */ + +/** + * @brief Enable the specified FLASH interrupt. + * @param __INTERRUPT__: FLASH interrupt + * This parameter can be any combination of the following values: + * @arg FLASH_IT_EOP: End of FLASH Operation Interrupt + * @arg FLASH_IT_OPERR: Error Interrupt + * @arg FLASH_IT_RDERR: PCROP Read Error Interrupt + * @arg FLASH_IT_ECCC: ECC Correction Interrupt + * @retval none + */ +#define __HAL_FLASH_ENABLE_IT(__INTERRUPT__) do { if((__INTERRUPT__) & FLASH_IT_ECCC) { SET_BIT(FLASH->ECCR, FLASH_ECCR_ECCIE); }\ + if((__INTERRUPT__) & (~FLASH_IT_ECCC)) { SET_BIT(FLASH->CR, ((__INTERRUPT__) & (~FLASH_IT_ECCC))); }\ + } while(0) + +/** + * @brief Disable the specified FLASH interrupt. + * @param __INTERRUPT__: FLASH interrupt + * This parameter can be any combination of the following values: + * @arg FLASH_IT_EOP: End of FLASH Operation Interrupt + * @arg FLASH_IT_OPERR: Error Interrupt + * @arg FLASH_IT_RDERR: PCROP Read Error Interrupt + * @arg FLASH_IT_ECCC: ECC Correction Interrupt + * @retval none + */ +#define __HAL_FLASH_DISABLE_IT(__INTERRUPT__) do { if((__INTERRUPT__) & FLASH_IT_ECCC) { CLEAR_BIT(FLASH->ECCR, FLASH_ECCR_ECCIE); }\ + if((__INTERRUPT__) & (~FLASH_IT_ECCC)) { CLEAR_BIT(FLASH->CR, ((__INTERRUPT__) & (~FLASH_IT_ECCC))); }\ + } while(0) + +/** + * @brief Check whether the specified FLASH flag is set or not. + * @param __FLAG__: specifies the FLASH flag to check. + * This parameter can be one of the following values: + * @arg FLASH_FLAG_EOP: FLASH End of Operation flag + * @arg FLASH_FLAG_OPERR: FLASH Operation error flag + * @arg FLASH_FLAG_PROGERR: FLASH Programming error flag + * @arg FLASH_FLAG_WRPERR: FLASH Write protection error flag + * @arg FLASH_FLAG_PGAERR: FLASH Programming alignment error flag + * @arg FLASH_FLAG_SIZERR: FLASH Size error flag + * @arg FLASH_FLAG_PGSERR: FLASH Programming sequence error flag + * @arg FLASH_FLAG_MISERR: FLASH Fast programming data miss error flag + * @arg FLASH_FLAG_FASTERR: FLASH Fast programming error flag + * @arg FLASH_FLAG_RDERR: FLASH PCROP read error flag + * @arg FLASH_FLAG_OPTVERR: FLASH Option validity error flag + * @arg FLASH_FLAG_BSY: FLASH write/erase operations in progress flag + * @arg FLASH_FLAG_PEMPTY : FLASH Boot from not programmed flash (apply only for STM32L43x/STM32L44x devices) + * @arg FLASH_FLAG_ECCC: FLASH one ECC error has been detected and corrected + * @arg FLASH_FLAG_ECCD: FLASH two ECC errors have been detected + * @retval The new state of FLASH_FLAG (SET or RESET). + */ +#define __HAL_FLASH_GET_FLAG(__FLAG__) (((__FLAG__) & (FLASH_FLAG_ECCC | FLASH_FLAG_ECCD)) ? \ + (READ_BIT(FLASH->ECCR, (__FLAG__)) == (__FLAG__)) : \ + (READ_BIT(FLASH->SR, (__FLAG__)) == (__FLAG__))) + +/** + * @brief Clear the FLASH's pending flags. + * @param __FLAG__: specifies the FLASH flags to clear. + * This parameter can be any combination of the following values: + * @arg FLASH_FLAG_EOP: FLASH End of Operation flag + * @arg FLASH_FLAG_OPERR: FLASH Operation error flag + * @arg FLASH_FLAG_PROGERR: FLASH Programming error flag + * @arg FLASH_FLAG_WRPERR: FLASH Write protection error flag + * @arg FLASH_FLAG_PGAERR: FLASH Programming alignment error flag + * @arg FLASH_FLAG_SIZERR: FLASH Size error flag + * @arg FLASH_FLAG_PGSERR: FLASH Programming sequence error flag + * @arg FLASH_FLAG_MISERR: FLASH Fast programming data miss error flag + * @arg FLASH_FLAG_FASTERR: FLASH Fast programming error flag + * @arg FLASH_FLAG_RDERR: FLASH PCROP read error flag + * @arg FLASH_FLAG_OPTVERR: FLASH Option validity error flag + * @arg FLASH_FLAG_ECCC: FLASH one ECC error has been detected and corrected + * @arg FLASH_FLAG_ECCD: FLASH two ECC errors have been detected + * @arg FLASH_FLAG_ALL_ERRORS: FLASH All errors flags + * @retval None + */ +#define __HAL_FLASH_CLEAR_FLAG(__FLAG__) do { if((__FLAG__) & (FLASH_FLAG_ECCC | FLASH_FLAG_ECCD)) { SET_BIT(FLASH->ECCR, ((__FLAG__) & (FLASH_FLAG_ECCC | FLASH_FLAG_ECCD))); }\ + if((__FLAG__) & ~(FLASH_FLAG_ECCC | FLASH_FLAG_ECCD)) { WRITE_REG(FLASH->SR, ((__FLAG__) & ~(FLASH_FLAG_ECCC | FLASH_FLAG_ECCD))); }\ + } while(0) +/** + * @} + */ + +/* Include FLASH HAL Extended module */ +#include "stm32l4xx_hal_flash_ex.h" +#include "stm32l4xx_hal_flash_ramfunc.h" + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup FLASH_Exported_Functions + * @{ + */ + +/* Program operation functions ***********************************************/ +/** @addtogroup FLASH_Exported_Functions_Group1 + * @{ + */ +HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data); +HAL_StatusTypeDef HAL_FLASH_Program_IT(uint32_t TypeProgram, uint32_t Address, uint64_t Data); +/* FLASH IRQ handler method */ +void HAL_FLASH_IRQHandler(void); +/* Callbacks in non blocking modes */ +void HAL_FLASH_EndOfOperationCallback(uint32_t ReturnValue); +void HAL_FLASH_OperationErrorCallback(uint32_t ReturnValue); +/** + * @} + */ + +/* Peripheral Control functions **********************************************/ +/** @addtogroup FLASH_Exported_Functions_Group2 + * @{ + */ +HAL_StatusTypeDef HAL_FLASH_Unlock(void); +HAL_StatusTypeDef HAL_FLASH_Lock(void); +/* Option bytes control */ +HAL_StatusTypeDef HAL_FLASH_OB_Unlock(void); +HAL_StatusTypeDef HAL_FLASH_OB_Lock(void); +HAL_StatusTypeDef HAL_FLASH_OB_Launch(void); +/** + * @} + */ + +/* Peripheral State functions ************************************************/ +/** @addtogroup FLASH_Exported_Functions_Group3 + * @{ + */ +uint32_t HAL_FLASH_GetError(void); +/** + * @} + */ + +/** + * @} + */ + +/* Private constants --------------------------------------------------------*/ +/** @defgroup FLASH_Private_Constants FLASH Private Constants + * @{ + */ +#define FLASH_SIZE_DATA_REGISTER ((uint32_t)0x1FFF75E0) + +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define FLASH_SIZE ((((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) == 0xFFFF)) ? (0x800 << 10) : \ + (((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) & (0x0FFF)) << 10)) +#elif defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) +#define FLASH_SIZE ((((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) == 0xFFFF)) ? (0x200 << 10) : \ + (((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) & (0x0FFF)) << 10)) +#else +#define FLASH_SIZE ((((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) == 0xFFFF)) ? (0x400 << 10) : \ + (((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) & (0x0FFF)) << 10)) +#endif + +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define FLASH_BANK_SIZE (FLASH_SIZE >> 1) +#else +#define FLASH_BANK_SIZE (FLASH_SIZE) +#endif + +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define FLASH_PAGE_SIZE ((uint32_t)0x1000) +#define FLASH_PAGE_SIZE_128_BITS ((uint32_t)0x2000) +#else +#define FLASH_PAGE_SIZE ((uint32_t)0x800) +#endif + +#define FLASH_TIMEOUT_VALUE ((uint32_t)50000)/* 50 s */ +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup FLASH_Private_Macros FLASH Private Macros + * @{ + */ + +#define IS_FLASH_TYPEERASE(VALUE) (((VALUE) == FLASH_TYPEERASE_PAGES) || \ + ((VALUE) == FLASH_TYPEERASE_MASSERASE)) + +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define IS_FLASH_BANK(BANK) (((BANK) == FLASH_BANK_1) || \ + ((BANK) == FLASH_BANK_2) || \ + ((BANK) == FLASH_BANK_BOTH)) + +#define IS_FLASH_BANK_EXCLUSIVE(BANK) (((BANK) == FLASH_BANK_1) || \ + ((BANK) == FLASH_BANK_2)) +#else +#define IS_FLASH_BANK(BANK) ((BANK) == FLASH_BANK_1) + +#define IS_FLASH_BANK_EXCLUSIVE(BANK) ((BANK) == FLASH_BANK_1) +#endif + +#define IS_FLASH_TYPEPROGRAM(VALUE) (((VALUE) == FLASH_TYPEPROGRAM_DOUBLEWORD) || \ + ((VALUE) == FLASH_TYPEPROGRAM_FAST) || \ + ((VALUE) == FLASH_TYPEPROGRAM_FAST_AND_LAST)) + +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define IS_FLASH_MAIN_MEM_ADDRESS(ADDRESS) (((ADDRESS) >= FLASH_BASE) && ((ADDRESS) <= FLASH_BASE+0x1FFFFF)) +#else +#define IS_FLASH_MAIN_MEM_ADDRESS(ADDRESS) (((ADDRESS) >= FLASH_BASE) && ((((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) & (0x0FFF)) == 0x400) ? \ + ((ADDRESS) <= FLASH_BASE+0xFFFFF) : ((((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) & (0x0FFF)) == 0x200) ? \ + ((ADDRESS) <= FLASH_BASE+0x7FFFF) : ((((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) & (0x0FFF)) == 0x100) ? \ + ((ADDRESS) <= FLASH_BASE+0x3FFFF) : ((((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) & (0x0FFF)) == 0x80) ? \ + ((ADDRESS) <= FLASH_BASE+0x1FFFF) : ((ADDRESS) <= FLASH_BASE+0xFFFFF)))))) +#endif + +#define IS_FLASH_OTP_ADDRESS(ADDRESS) (((ADDRESS) >= 0x1FFF7000) && ((ADDRESS) <= 0x1FFF73FF)) + +#define IS_FLASH_PROGRAM_ADDRESS(ADDRESS) (IS_FLASH_MAIN_MEM_ADDRESS(ADDRESS) || IS_FLASH_OTP_ADDRESS(ADDRESS)) + +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define IS_FLASH_PAGE(PAGE) ((PAGE) < 256) +#elif defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || defined(STM32L496xx) || defined(STM32L4A6xx) +#define IS_FLASH_PAGE(PAGE) (((((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) & (0x0FFF)) == 0x400) ? ((PAGE) < 256) : \ + ((((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) & (0x0FFF)) == 0x200) ? ((PAGE) < 128) : \ + ((((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) & (0x0FFF)) == 0x100) ? ((PAGE) < 64) : \ + ((PAGE) < 256))))) +#elif defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) +#define IS_FLASH_PAGE(PAGE) (((((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) & (0x0FFF)) == 0x200) ? ((PAGE) < 256) : \ + ((((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) & (0x0FFF)) == 0x100) ? ((PAGE) < 128) : \ + ((PAGE) < 256)))) +#else +#define IS_FLASH_PAGE(PAGE) (((((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) & (0x0FFF)) == 0x100) ? ((PAGE) < 128) : \ + ((((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) & (0x0FFF)) == 0x80) ? ((PAGE) < 64) : \ + ((PAGE) < 128)))) +#endif + +#define IS_OPTIONBYTE(VALUE) (((VALUE) <= (OPTIONBYTE_WRP | OPTIONBYTE_RDP | OPTIONBYTE_USER | OPTIONBYTE_PCROP))) + +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define IS_OB_WRPAREA(VALUE) (((VALUE) == OB_WRPAREA_BANK1_AREAA) || ((VALUE) == OB_WRPAREA_BANK1_AREAB) || \ + ((VALUE) == OB_WRPAREA_BANK2_AREAA) || ((VALUE) == OB_WRPAREA_BANK2_AREAB)) +#else +#define IS_OB_WRPAREA(VALUE) (((VALUE) == OB_WRPAREA_BANK1_AREAA) || ((VALUE) == OB_WRPAREA_BANK1_AREAB)) +#endif + +#define IS_OB_RDP_LEVEL(LEVEL) (((LEVEL) == OB_RDP_LEVEL_0) ||\ + ((LEVEL) == OB_RDP_LEVEL_1)/* ||\ + ((LEVEL) == OB_RDP_LEVEL_2)*/) + +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define IS_OB_USER_TYPE(TYPE) (((TYPE) <= (uint32_t)0xFFFF) && ((TYPE) != 0)) +#elif defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || defined(STM32L496xx) || defined(STM32L4A6xx) +#define IS_OB_USER_TYPE(TYPE) (((TYPE) <= (uint32_t)0x1FFF) && ((TYPE) != 0)) +#else +#define IS_OB_USER_TYPE(TYPE) (((TYPE) <= (uint32_t)0x7E7F) && ((TYPE) != 0) && (((TYPE)&0x0180) == 0)) +#endif + +#define IS_OB_USER_BOR_LEVEL(LEVEL) (((LEVEL) == OB_BOR_LEVEL_0) || ((LEVEL) == OB_BOR_LEVEL_1) || \ + ((LEVEL) == OB_BOR_LEVEL_2) || ((LEVEL) == OB_BOR_LEVEL_3) || \ + ((LEVEL) == OB_BOR_LEVEL_4)) + +#define IS_OB_USER_STOP(VALUE) (((VALUE) == OB_STOP_RST) || ((VALUE) == OB_STOP_NORST)) + +#define IS_OB_USER_STANDBY(VALUE) (((VALUE) == OB_STANDBY_RST) || ((VALUE) == OB_STANDBY_NORST)) + +#define IS_OB_USER_SHUTDOWN(VALUE) (((VALUE) == OB_SHUTDOWN_RST) || ((VALUE) == OB_SHUTDOWN_NORST)) + +#define IS_OB_USER_IWDG(VALUE) (((VALUE) == OB_IWDG_HW) || ((VALUE) == OB_IWDG_SW)) + +#define IS_OB_USER_IWDG_STOP(VALUE) (((VALUE) == OB_IWDG_STOP_FREEZE) || ((VALUE) == OB_IWDG_STOP_RUN)) + +#define IS_OB_USER_IWDG_STDBY(VALUE) (((VALUE) == OB_IWDG_STDBY_FREEZE) || ((VALUE) == OB_IWDG_STDBY_RUN)) + +#define IS_OB_USER_WWDG(VALUE) (((VALUE) == OB_WWDG_HW) || ((VALUE) == OB_WWDG_SW)) + +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define IS_OB_USER_BFB2(VALUE) (((VALUE) == OB_BFB2_DISABLE) || ((VALUE) == OB_BFB2_ENABLE)) + +#define IS_OB_USER_DUALBANK(VALUE) (((VALUE) == OB_DUALBANK_SINGLE) || ((VALUE) == OB_DUALBANK_DUAL)) +#endif + +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define IS_OB_USER_DBANK(VALUE) (((VALUE) == OB_DBANK_128_BITS) || ((VALUE) == OB_DBANK_64_BITS)) +#endif + +#define IS_OB_USER_BOOT1(VALUE) (((VALUE) == OB_BOOT1_SRAM) || ((VALUE) == OB_BOOT1_SYSTEM)) + +#define IS_OB_USER_SRAM2_PARITY(VALUE) (((VALUE) == OB_SRAM2_PARITY_ENABLE) || ((VALUE) == OB_SRAM2_PARITY_DISABLE)) + +#define IS_OB_USER_SRAM2_RST(VALUE) (((VALUE) == OB_SRAM2_RST_ERASE) || ((VALUE) == OB_SRAM2_RST_NOT_ERASE)) + +#if defined (STM32L431xx) || defined (STM32L432xx) || defined (STM32L433xx) || defined (STM32L442xx) || \ + defined (STM32L443xx) || defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define IS_OB_USER_SWBOOT0(VALUE) (((VALUE) == OB_BOOT0_FROM_OB) || ((VALUE) == OB_BOOT0_FROM_PIN)) + +#define IS_OB_USER_BOOT0(VALUE) (((VALUE) == OB_BOOT0_RESET) || ((VALUE) == OB_BOOT0_SET)) +#endif + +#define IS_OB_PCROP_RDP(VALUE) (((VALUE) == OB_PCROP_RDP_NOT_ERASE) || ((VALUE) == OB_PCROP_RDP_ERASE)) + +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define IS_FLASH_LATENCY(LATENCY) (((LATENCY) == FLASH_LATENCY_0) || ((LATENCY) == FLASH_LATENCY_1) || \ + ((LATENCY) == FLASH_LATENCY_2) || ((LATENCY) == FLASH_LATENCY_3) || \ + ((LATENCY) == FLASH_LATENCY_4) || ((LATENCY) == FLASH_LATENCY_5) || \ + ((LATENCY) == FLASH_LATENCY_6) || ((LATENCY) == FLASH_LATENCY_7) || \ + ((LATENCY) == FLASH_LATENCY_8) || ((LATENCY) == FLASH_LATENCY_9) || \ + ((LATENCY) == FLASH_LATENCY_10) || ((LATENCY) == FLASH_LATENCY_11) || \ + ((LATENCY) == FLASH_LATENCY_12) || ((LATENCY) == FLASH_LATENCY_13) || \ + ((LATENCY) == FLASH_LATENCY_14) || ((LATENCY) == FLASH_LATENCY_15)) +#else +#define IS_FLASH_LATENCY(LATENCY) (((LATENCY) == FLASH_LATENCY_0) || \ + ((LATENCY) == FLASH_LATENCY_1) || \ + ((LATENCY) == FLASH_LATENCY_2) || \ + ((LATENCY) == FLASH_LATENCY_3) || \ + ((LATENCY) == FLASH_LATENCY_4)) +#endif +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_HAL_FLASH_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash_ex.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash_ex.h new file mode 100644 index 0000000..63d5c9f --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash_ex.h @@ -0,0 +1,134 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_flash_ex.h + * @author MCD Application Team + * @brief Header file of FLASH HAL Extended module. + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_FLASH_EX_H +#define __STM32L4xx_HAL_FLASH_EX_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup FLASHEx + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ + +/* Exported constants --------------------------------------------------------*/ +#if defined (FLASH_CFGR_LVEN) +/** @addtogroup FLASHEx_Exported_Constants + * @{ + */ +/** @defgroup FLASHEx_LVE_PIN_CFG FLASHEx LVE pin configuration + * @{ + */ +#define FLASH_LVE_PIN_CTRL 0x00000000U /*!< LVE FLASH pin controlled by power controller */ +#define FLASH_LVE_PIN_FORCED FLASH_CFGR_LVEN /*!< LVE FLASH pin enforced to low (external SMPS used) */ +/** + * @} + */ + +/** + * @} + */ +#endif /* FLASH_CFGR_LVEN */ + +/* Exported macro ------------------------------------------------------------*/ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup FLASHEx_Exported_Functions + * @{ + */ + +/* Extended Program operation functions *************************************/ +/** @addtogroup FLASHEx_Exported_Functions_Group1 + * @{ + */ +HAL_StatusTypeDef HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *PageError); +HAL_StatusTypeDef HAL_FLASHEx_Erase_IT(FLASH_EraseInitTypeDef *pEraseInit); +HAL_StatusTypeDef HAL_FLASHEx_OBProgram(FLASH_OBProgramInitTypeDef *pOBInit); +void HAL_FLASHEx_OBGetConfig(FLASH_OBProgramInitTypeDef *pOBInit); +/** + * @} + */ + +#if defined (FLASH_CFGR_LVEN) +/** @addtogroup FLASHEx_Exported_Functions_Group2 + * @{ + */ +HAL_StatusTypeDef HAL_FLASHEx_ConfigLVEPin(uint32_t ConfigLVE); +/** + * @} + */ +#endif /* FLASH_CFGR_LVEN */ + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** + @cond 0 + */ +#if defined (FLASH_CFGR_LVEN) +#define IS_FLASH_LVE_PIN(CFG) (((CFG) == FLASH_LVE_PIN_CTRL) || ((CFG) == FLASH_LVE_PIN_FORCED)) +#endif /* FLASH_CFGR_LVEN */ +/** + @endcond + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_HAL_FLASH_EX_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash_ramfunc.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash_ramfunc.h new file mode 100644 index 0000000..723157f --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_flash_ramfunc.h @@ -0,0 +1,126 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_flash_ramfunc.h + * @author MCD Application Team + * @brief Header file of FLASH RAMFUNC driver. + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_FLASH_RAMFUNC_H +#define __STM32L4xx_FLASH_RAMFUNC_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup FLASH_RAMFUNC + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ +/** + * @brief __RAM_FUNC definition + */ +#if defined ( __CC_ARM ) +/* ARM Compiler + ------------ + RAM functions are defined using the toolchain options. + Functions that are executed in RAM should reside in a separate source module. + Using the 'Options for File' dialog you can simply change the 'Code / Const' + area of a module to a memory space in physical RAM. + Available memory areas are declared in the 'Target' tab of the 'Options for Target' + dialog. +*/ +#define __RAM_FUNC HAL_StatusTypeDef + +#elif defined ( __ICCARM__ ) +/* ICCARM Compiler + --------------- + RAM functions are defined using a specific toolchain keyword "__ramfunc". +*/ +#define __RAM_FUNC __ramfunc HAL_StatusTypeDef + +#elif defined ( __GNUC__ ) +/* GNU Compiler + ------------ + RAM functions are defined using a specific toolchain attribute + "__attribute__((section(".RamFunc")))". +*/ +#define __RAM_FUNC HAL_StatusTypeDef __attribute__((section(".RamFunc"))) + +#endif + + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup FLASH_RAMFUNC_Exported_Functions + * @{ + */ + +/** @addtogroup FLASH_RAMFUNC_Exported_Functions_Group1 + * @{ + */ +/* Peripheral Control functions ************************************************/ +__RAM_FUNC HAL_FLASHEx_EnableRunPowerDown(void); +__RAM_FUNC HAL_FLASHEx_DisableRunPowerDown(void); +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +__RAM_FUNC HAL_FLASHEx_OB_DBankConfig(uint32_t DBankConfig); +#endif +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_FLASH_RAMFUNC_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_gpio.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_gpio.h new file mode 100644 index 0000000..bfae10d --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_gpio.h @@ -0,0 +1,316 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_gpio.h + * @author MCD Application Team + * @brief Header file of GPIO HAL module. + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_GPIO_H +#define __STM32L4xx_HAL_GPIO_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup GPIO + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ + +/** @defgroup GPIO_Exported_Types GPIO Exported Types + * @{ + */ +/** + * @brief GPIO Init structure definition + */ +typedef struct +{ + uint32_t Pin; /*!< Specifies the GPIO pins to be configured. + This parameter can be any value of @ref GPIO_pins */ + + uint32_t Mode; /*!< Specifies the operating mode for the selected pins. + This parameter can be a value of @ref GPIO_mode */ + + uint32_t Pull; /*!< Specifies the Pull-up or Pull-Down activation for the selected pins. + This parameter can be a value of @ref GPIO_pull */ + + uint32_t Speed; /*!< Specifies the speed for the selected pins. + This parameter can be a value of @ref GPIO_speed */ + + uint32_t Alternate; /*!< Peripheral to be connected to the selected pins + This parameter can be a value of @ref GPIOEx_Alternate_function_selection */ +}GPIO_InitTypeDef; + +/** + * @brief GPIO Bit SET and Bit RESET enumeration + */ +typedef enum +{ + GPIO_PIN_RESET = 0, + GPIO_PIN_SET +}GPIO_PinState; +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup GPIO_Exported_Constants GPIO Exported Constants + * @{ + */ +/** @defgroup GPIO_pins GPIO pins + * @{ + */ +#define GPIO_PIN_0 ((uint16_t)0x0001) /* Pin 0 selected */ +#define GPIO_PIN_1 ((uint16_t)0x0002) /* Pin 1 selected */ +#define GPIO_PIN_2 ((uint16_t)0x0004) /* Pin 2 selected */ +#define GPIO_PIN_3 ((uint16_t)0x0008) /* Pin 3 selected */ +#define GPIO_PIN_4 ((uint16_t)0x0010) /* Pin 4 selected */ +#define GPIO_PIN_5 ((uint16_t)0x0020) /* Pin 5 selected */ +#define GPIO_PIN_6 ((uint16_t)0x0040) /* Pin 6 selected */ +#define GPIO_PIN_7 ((uint16_t)0x0080) /* Pin 7 selected */ +#define GPIO_PIN_8 ((uint16_t)0x0100) /* Pin 8 selected */ +#define GPIO_PIN_9 ((uint16_t)0x0200) /* Pin 9 selected */ +#define GPIO_PIN_10 ((uint16_t)0x0400) /* Pin 10 selected */ +#define GPIO_PIN_11 ((uint16_t)0x0800) /* Pin 11 selected */ +#define GPIO_PIN_12 ((uint16_t)0x1000) /* Pin 12 selected */ +#define GPIO_PIN_13 ((uint16_t)0x2000) /* Pin 13 selected */ +#define GPIO_PIN_14 ((uint16_t)0x4000) /* Pin 14 selected */ +#define GPIO_PIN_15 ((uint16_t)0x8000) /* Pin 15 selected */ +#define GPIO_PIN_All ((uint16_t)0xFFFF) /* All pins selected */ + +#define GPIO_PIN_MASK ((uint32_t)0x0000FFFF) /* PIN mask for assert test */ +/** + * @} + */ + +/** @defgroup GPIO_mode GPIO mode + * @brief GPIO Configuration Mode + * Elements values convention: 0xX0yz00YZ + * - X : GPIO mode or EXTI Mode + * - y : External IT or Event trigger detection + * - z : IO configuration on External IT or Event + * - Y : Output type (Push Pull or Open Drain) + * - Z : IO Direction mode (Input, Output, Alternate or Analog) + * @{ + */ +#define GPIO_MODE_INPUT ((uint32_t)0x00000000) /*!< Input Floating Mode */ +#define GPIO_MODE_OUTPUT_PP ((uint32_t)0x00000001) /*!< Output Push Pull Mode */ +#define GPIO_MODE_OUTPUT_OD ((uint32_t)0x00000011) /*!< Output Open Drain Mode */ +#define GPIO_MODE_AF_PP ((uint32_t)0x00000002) /*!< Alternate Function Push Pull Mode */ +#define GPIO_MODE_AF_OD ((uint32_t)0x00000012) /*!< Alternate Function Open Drain Mode */ +#define GPIO_MODE_ANALOG ((uint32_t)0x00000003) /*!< Analog Mode */ +#define GPIO_MODE_ANALOG_ADC_CONTROL ((uint32_t)0x0000000B) /*!< Analog Mode for ADC conversion */ +#define GPIO_MODE_IT_RISING ((uint32_t)0x10110000) /*!< External Interrupt Mode with Rising edge trigger detection */ +#define GPIO_MODE_IT_FALLING ((uint32_t)0x10210000) /*!< External Interrupt Mode with Falling edge trigger detection */ +#define GPIO_MODE_IT_RISING_FALLING ((uint32_t)0x10310000) /*!< External Interrupt Mode with Rising/Falling edge trigger detection */ +#define GPIO_MODE_EVT_RISING ((uint32_t)0x10120000) /*!< External Event Mode with Rising edge trigger detection */ +#define GPIO_MODE_EVT_FALLING ((uint32_t)0x10220000) /*!< External Event Mode with Falling edge trigger detection */ +#define GPIO_MODE_EVT_RISING_FALLING ((uint32_t)0x10320000) /*!< External Event Mode with Rising/Falling edge trigger detection */ +/** + * @} + */ + +/** @defgroup GPIO_speed GPIO speed + * @brief GPIO Output Maximum frequency + * @{ + */ +#define GPIO_SPEED_FREQ_LOW ((uint32_t)0x00000000) /*!< range up to 5 MHz, please refer to the product datasheet */ +#define GPIO_SPEED_FREQ_MEDIUM ((uint32_t)0x00000001) /*!< range 5 MHz to 25 MHz, please refer to the product datasheet */ +#define GPIO_SPEED_FREQ_HIGH ((uint32_t)0x00000002) /*!< range 25 MHz to 50 MHz, please refer to the product datasheet */ +#define GPIO_SPEED_FREQ_VERY_HIGH ((uint32_t)0x00000003) /*!< range 50 MHz to 80 MHz, please refer to the product datasheet */ +/** + * @} + */ + + /** @defgroup GPIO_pull GPIO pull + * @brief GPIO Pull-Up or Pull-Down Activation + * @{ + */ +#define GPIO_NOPULL ((uint32_t)0x00000000) /*!< No Pull-up or Pull-down activation */ +#define GPIO_PULLUP ((uint32_t)0x00000001) /*!< Pull-up activation */ +#define GPIO_PULLDOWN ((uint32_t)0x00000002) /*!< Pull-down activation */ +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup GPIO_Exported_Macros GPIO Exported Macros + * @{ + */ + +/** + * @brief Check whether the specified EXTI line flag is set or not. + * @param __EXTI_LINE__: specifies the EXTI line flag to check. + * This parameter can be GPIO_PIN_x where x can be(0..15) + * @retval The new state of __EXTI_LINE__ (SET or RESET). + */ +#define __HAL_GPIO_EXTI_GET_FLAG(__EXTI_LINE__) (EXTI->PR1 & (__EXTI_LINE__)) + +/** + * @brief Clear the EXTI's line pending flags. + * @param __EXTI_LINE__: specifies the EXTI lines flags to clear. + * This parameter can be any combination of GPIO_PIN_x where x can be (0..15) + * @retval None + */ +#define __HAL_GPIO_EXTI_CLEAR_FLAG(__EXTI_LINE__) (EXTI->PR1 = (__EXTI_LINE__)) + +/** + * @brief Check whether the specified EXTI line is asserted or not. + * @param __EXTI_LINE__: specifies the EXTI line to check. + * This parameter can be GPIO_PIN_x where x can be(0..15) + * @retval The new state of __EXTI_LINE__ (SET or RESET). + */ +#define __HAL_GPIO_EXTI_GET_IT(__EXTI_LINE__) (EXTI->PR1 & (__EXTI_LINE__)) + +/** + * @brief Clear the EXTI's line pending bits. + * @param __EXTI_LINE__: specifies the EXTI lines to clear. + * This parameter can be any combination of GPIO_PIN_x where x can be (0..15) + * @retval None + */ +#define __HAL_GPIO_EXTI_CLEAR_IT(__EXTI_LINE__) (EXTI->PR1 = (__EXTI_LINE__)) + +/** + * @brief Generate a Software interrupt on selected EXTI line. + * @param __EXTI_LINE__: specifies the EXTI line to check. + * This parameter can be GPIO_PIN_x where x can be(0..15) + * @retval None + */ +#define __HAL_GPIO_EXTI_GENERATE_SWIT(__EXTI_LINE__) (EXTI->SWIER1 |= (__EXTI_LINE__)) + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @addtogroup GPIO_Private_Macros GPIO Private Macros + * @{ + */ +#define IS_GPIO_PIN_ACTION(ACTION) (((ACTION) == GPIO_PIN_RESET) || ((ACTION) == GPIO_PIN_SET)) + +#define IS_GPIO_PIN(__PIN__) ((((__PIN__) & GPIO_PIN_MASK) != (uint32_t)0x00) &&\ + (((__PIN__) & ~GPIO_PIN_MASK) == (uint32_t)0x00)) + +#define IS_GPIO_MODE(__MODE__) (((__MODE__) == GPIO_MODE_INPUT) ||\ + ((__MODE__) == GPIO_MODE_OUTPUT_PP) ||\ + ((__MODE__) == GPIO_MODE_OUTPUT_OD) ||\ + ((__MODE__) == GPIO_MODE_AF_PP) ||\ + ((__MODE__) == GPIO_MODE_AF_OD) ||\ + ((__MODE__) == GPIO_MODE_IT_RISING) ||\ + ((__MODE__) == GPIO_MODE_IT_FALLING) ||\ + ((__MODE__) == GPIO_MODE_IT_RISING_FALLING) ||\ + ((__MODE__) == GPIO_MODE_EVT_RISING) ||\ + ((__MODE__) == GPIO_MODE_EVT_FALLING) ||\ + ((__MODE__) == GPIO_MODE_EVT_RISING_FALLING) ||\ + ((__MODE__) == GPIO_MODE_ANALOG) ||\ + ((__MODE__) == GPIO_MODE_ANALOG_ADC_CONTROL)) + +#define IS_GPIO_SPEED(__SPEED__) (((__SPEED__) == GPIO_SPEED_FREQ_LOW) ||\ + ((__SPEED__) == GPIO_SPEED_FREQ_MEDIUM) ||\ + ((__SPEED__) == GPIO_SPEED_FREQ_HIGH) ||\ + ((__SPEED__) == GPIO_SPEED_FREQ_VERY_HIGH)) + +#define IS_GPIO_PULL(__PULL__) (((__PULL__) == GPIO_NOPULL) ||\ + ((__PULL__) == GPIO_PULLUP) || \ + ((__PULL__) == GPIO_PULLDOWN)) +/** + * @} + */ + +/* Include GPIO HAL Extended module */ +#include "stm32l4xx_hal_gpio_ex.h" + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup GPIO_Exported_Functions GPIO Exported Functions + * @{ + */ + +/** @addtogroup GPIO_Exported_Functions_Group1 Initialization/de-initialization functions + * @brief Initialization and Configuration functions + * @{ + */ + +/* Initialization and de-initialization functions *****************************/ +void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init); +void HAL_GPIO_DeInit(GPIO_TypeDef *GPIOx, uint32_t GPIO_Pin); + +/** + * @} + */ + +/** @addtogroup GPIO_Exported_Functions_Group2 IO operation functions + * @{ + */ + +/* IO operation functions *****************************************************/ +GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); +void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState); +void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); +HAL_StatusTypeDef HAL_GPIO_LockPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); +void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin); +void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin); + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_HAL_GPIO_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_gpio_ex.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_gpio_ex.h new file mode 100644 index 0000000..db5d8d7 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_gpio_ex.h @@ -0,0 +1,822 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_gpio_ex.h + * @author MCD Application Team + * @brief Header file of GPIO HAL Extended module. + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_GPIO_EX_H +#define __STM32L4xx_HAL_GPIO_EX_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup GPIOEx GPIOEx + * @brief GPIO Extended HAL module driver + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/** @defgroup GPIOEx_Exported_Constants GPIOEx Exported Constants + * @{ + */ + +/** @defgroup GPIOEx_Alternate_function_selection GPIOEx Alternate function selection + * @{ + */ + +#if defined(STM32L431xx) || defined(STM32L432xx) || defined(STM32L433xx) || defined(STM32L442xx) || defined(STM32L443xx) +/*--------------STM32L431xx/STM32L432xx/STM32L433xx/STM32L442xx/STM32L443xx---*/ +/** + * @brief AF 0 selection + */ +#define GPIO_AF0_RTC_50Hz ((uint8_t)0x00) /* RTC_50Hz Alternate Function mapping */ +#define GPIO_AF0_MCO ((uint8_t)0x00) /* MCO (MCO1 and MCO2) Alternate Function mapping */ +#define GPIO_AF0_SWJ ((uint8_t)0x00) /* SWJ (SWD and JTAG) Alternate Function mapping */ +#if defined(STM32L433xx) || defined(STM32L443xx) +#define GPIO_AF0_LCDBIAS ((uint8_t)0x00) /* LCDBIAS Alternate Function mapping */ +#endif /* STM32L433xx || STM32L443xx */ +#define GPIO_AF0_TRACE ((uint8_t)0x00) /* TRACE Alternate Function mapping */ + +/** + * @brief AF 1 selection + */ +#define GPIO_AF1_TIM1 ((uint8_t)0x01) /* TIM1 Alternate Function mapping */ +#define GPIO_AF1_TIM2 ((uint8_t)0x01) /* TIM2 Alternate Function mapping */ +#define GPIO_AF1_LPTIM1 ((uint8_t)0x01) /* LPTIM1 Alternate Function mapping */ +#define GPIO_AF1_IR ((uint8_t)0x01) /* IR Alternate Function mapping */ + +/** + * @brief AF 2 selection + */ +#define GPIO_AF2_TIM1 ((uint8_t)0x02) /* TIM1 Alternate Function mapping */ +#define GPIO_AF2_TIM2 ((uint8_t)0x02) /* TIM2 Alternate Function mapping */ + +/** + * @brief AF 3 selection + */ +#define GPIO_AF3_USART2 ((uint8_t)0x03) /* USART1 Alternate Function mapping */ +#define GPIO_AF3_TIM1_COMP2 ((uint8_t)0x03) /* TIM1/COMP2 Break in Alternate Function mapping */ +#define GPIO_AF3_TIM1_COMP1 ((uint8_t)0x03) /* TIM1/COMP1 Break in Alternate Function mapping */ + +/** + * @brief AF 4 selection + */ +#define GPIO_AF4_I2C1 ((uint8_t)0x04) /* I2C1 Alternate Function mapping */ +#define GPIO_AF4_I2C2 ((uint8_t)0x04) /* I2C2 Alternate Function mapping */ +#define GPIO_AF4_I2C3 ((uint8_t)0x04) /* I2C3 Alternate Function mapping */ + +/** + * @brief AF 5 selection + */ +#define GPIO_AF5_SPI1 ((uint8_t)0x05) /* SPI1 Alternate Function mapping */ +#define GPIO_AF5_SPI2 ((uint8_t)0x05) /* SPI2 Alternate Function mapping */ + +/** + * @brief AF 6 selection + */ +#define GPIO_AF6_SPI3 ((uint8_t)0x06) /* SPI3 Alternate Function mapping */ +#define GPIO_AF6_COMP1 ((uint8_t)0x06) /* COMP1 Alternate Function mapping */ + +/** + * @brief AF 7 selection + */ +#define GPIO_AF7_USART1 ((uint8_t)0x07) /* USART1 Alternate Function mapping */ +#define GPIO_AF7_USART2 ((uint8_t)0x07) /* USART2 Alternate Function mapping */ +#define GPIO_AF7_USART3 ((uint8_t)0x07) /* USART3 Alternate Function mapping */ + +/** + * @brief AF 8 selection + */ +#define GPIO_AF8_LPUART1 ((uint8_t)0x08) /* LPUART1 Alternate Function mapping */ + +/** + * @brief AF 9 selection + */ +#define GPIO_AF9_CAN1 ((uint8_t)0x09) /* CAN1 Alternate Function mapping */ +#define GPIO_AF9_TSC ((uint8_t)0x09) /* TSC Alternate Function mapping */ + +/** + * @brief AF 10 selection + */ +#if defined(STM32L432xx) || defined(STM32L433xx) || defined(STM32L442xx) || defined(STM32L443xx) +#define GPIO_AF10_USB_FS ((uint8_t)0x0A) /* USB_FS Alternate Function mapping */ +#endif /* STM32L432xx || STM32L433xx || STM32L442xx || STM32L443xx */ +#define GPIO_AF10_QUADSPI ((uint8_t)0x0A) /* QUADSPI Alternate Function mapping */ + +#if defined(STM32L433xx) || defined(STM32L443xx) +/** + * @brief AF 11 selection + */ +#define GPIO_AF11_LCD ((uint8_t)0x0B) /* LCD Alternate Function mapping */ +#endif /* STM32L433xx || STM32L443xx */ + +/** + * @brief AF 12 selection + */ +#define GPIO_AF12_SWPMI1 ((uint8_t)0x0C) /* SWPMI1 Alternate Function mapping */ +#define GPIO_AF12_COMP1 ((uint8_t)0x0C) /* COMP1 Alternate Function mapping */ +#define GPIO_AF12_COMP2 ((uint8_t)0x0C) /* COMP2 Alternate Function mapping */ +#define GPIO_AF12_SDMMC1 ((uint8_t)0x0C) /* SDMMC1 Alternate Function mapping */ + +/** + * @brief AF 13 selection + */ +#define GPIO_AF13_SAI1 ((uint8_t)0x0D) /* SAI1 Alternate Function mapping */ + +/** + * @brief AF 14 selection + */ +#define GPIO_AF14_TIM2 ((uint8_t)0x0E) /* TIM2 Alternate Function mapping */ +#define GPIO_AF14_TIM15 ((uint8_t)0x0E) /* TIM15 Alternate Function mapping */ +#define GPIO_AF14_TIM16 ((uint8_t)0x0E) /* TIM16 Alternate Function mapping */ +#define GPIO_AF14_LPTIM2 ((uint8_t)0x0E) /* LPTIM2 Alternate Function mapping */ + +/** + * @brief AF 15 selection + */ +#define GPIO_AF15_EVENTOUT ((uint8_t)0x0F) /* EVENTOUT Alternate Function mapping */ + +#define IS_GPIO_AF(AF) ((AF) <= (uint8_t)0x0F) + +#endif /* STM32L431xx || STM32L432xx || STM32L433xx || STM32L442xx || STM32L443xx */ + +#if defined(STM32L451xx) || defined(STM32L452xx) || defined(STM32L462xx) +/*--------------STM32L451xx/STM32L452xx/STM32L462xx---------------------------*/ +/** + * @brief AF 0 selection + */ +#define GPIO_AF0_RTC_50Hz ((uint8_t)0x00) /* RTC_50Hz Alternate Function mapping */ +#define GPIO_AF0_MCO ((uint8_t)0x00) /* MCO (MCO1 and MCO2) Alternate Function mapping */ +#define GPIO_AF0_SWJ ((uint8_t)0x00) /* SWJ (SWD and JTAG) Alternate Function mapping */ +#define GPIO_AF0_TRACE ((uint8_t)0x00) /* TRACE Alternate Function mapping */ + +/** + * @brief AF 1 selection + */ +#define GPIO_AF1_TIM1 ((uint8_t)0x01) /* TIM1 Alternate Function mapping */ +#define GPIO_AF1_TIM2 ((uint8_t)0x01) /* TIM2 Alternate Function mapping */ +#define GPIO_AF1_LPTIM1 ((uint8_t)0x01) /* LPTIM1 Alternate Function mapping */ +#define GPIO_AF1_IR ((uint8_t)0x01) /* IR Alternate Function mapping */ + +/** + * @brief AF 2 selection + */ +#define GPIO_AF2_TIM1 ((uint8_t)0x02) /* TIM1 Alternate Function mapping */ +#define GPIO_AF2_TIM2 ((uint8_t)0x02) /* TIM2 Alternate Function mapping */ +#define GPIO_AF2_TIM3 ((uint8_t)0x02) /* TIM3 Alternate Function mapping */ +#define GPIO_AF2_I2C4 ((uint8_t)0x02) /* I2C4 Alternate Function mapping */ + +/** + * @brief AF 3 selection + */ +#define GPIO_AF3_TIM1_COMP2 ((uint8_t)0x03) /* TIM1/COMP2 Break in Alternate Function mapping */ +#define GPIO_AF3_TIM1_COMP1 ((uint8_t)0x03) /* TIM1/COMP1 Break in Alternate Function mapping */ +#define GPIO_AF3_USART2 ((uint8_t)0x03) /* USART2 Alternate Function mapping */ +#define GPIO_AF3_CAN1 ((uint8_t)0x03) /* CAN1 Alternate Function mapping */ +#define GPIO_AF3_I2C4 ((uint8_t)0x03) /* I2C4 Alternate Function mapping */ + +/** + * @brief AF 4 selection + */ +#define GPIO_AF4_I2C1 ((uint8_t)0x04) /* I2C1 Alternate Function mapping */ +#define GPIO_AF4_I2C2 ((uint8_t)0x04) /* I2C2 Alternate Function mapping */ +#define GPIO_AF4_I2C3 ((uint8_t)0x04) /* I2C3 Alternate Function mapping */ +#define GPIO_AF4_I2C4 ((uint8_t)0x04) /* I2C4 Alternate Function mapping */ + +/** + * @brief AF 5 selection + */ +#define GPIO_AF5_SPI1 ((uint8_t)0x05) /* SPI1 Alternate Function mapping */ +#define GPIO_AF5_SPI2 ((uint8_t)0x05) /* SPI2 Alternate Function mapping */ +#define GPIO_AF5_I2C4 ((uint8_t)0x05) /* I2C4 Alternate Function mapping */ + +/** + * @brief AF 6 selection + */ +#define GPIO_AF6_SPI3 ((uint8_t)0x06) /* SPI3 Alternate Function mapping */ +#define GPIO_AF6_DFSDM1 ((uint8_t)0x06) /* DFSDM1 Alternate Function mapping */ +#define GPIO_AF6_COMP1 ((uint8_t)0x06) /* COMP1 Alternate Function mapping */ + +/** + * @brief AF 7 selection + */ +#define GPIO_AF7_USART1 ((uint8_t)0x07) /* USART1 Alternate Function mapping */ +#define GPIO_AF7_USART2 ((uint8_t)0x07) /* USART2 Alternate Function mapping */ +#define GPIO_AF7_USART3 ((uint8_t)0x07) /* USART3 Alternate Function mapping */ + +/** + * @brief AF 8 selection + */ +#define GPIO_AF8_UART4 ((uint8_t)0x08) /* UART4 Alternate Function mapping */ +#define GPIO_AF8_LPUART1 ((uint8_t)0x08) /* LPUART1 Alternate Function mapping */ +#define GPIO_AF8_CAN1 ((uint8_t)0x08) /* CAN1 Alternate Function mapping */ + + +/** + * @brief AF 9 selection + */ +#define GPIO_AF9_CAN1 ((uint8_t)0x09) /* CAN1 Alternate Function mapping */ +#define GPIO_AF9_TSC ((uint8_t)0x09) /* TSC Alternate Function mapping */ + +/** + * @brief AF 10 selection + */ +#if defined(STM32L452xx) || defined(STM32L462xx) +#define GPIO_AF10_USB_FS ((uint8_t)0x0A) /* USB_FS Alternate Function mapping */ +#endif /* STM32L452xx || STM32L462xx */ +#define GPIO_AF10_QUADSPI ((uint8_t)0x0A) /* QUADSPI Alternate Function mapping */ +#define GPIO_AF10_CAN1 ((uint8_t)0x0A) /* CAN1 Alternate Function mapping */ + +/** + * @brief AF 11 selection + */ + +/** + * @brief AF 12 selection + */ +#define GPIO_AF12_COMP1 ((uint8_t)0x0C) /* COMP1 Alternate Function mapping */ +#define GPIO_AF12_COMP2 ((uint8_t)0x0C) /* COMP2 Alternate Function mapping */ +#define GPIO_AF12_SDMMC1 ((uint8_t)0x0C) /* SDMMC1 Alternate Function mapping */ + +/** + * @brief AF 13 selection + */ +#define GPIO_AF13_SAI1 ((uint8_t)0x0D) /* SAI1 Alternate Function mapping */ + +/** + * @brief AF 14 selection + */ +#define GPIO_AF14_TIM2 ((uint8_t)0x0E) /* TIM2 Alternate Function mapping */ +#define GPIO_AF14_TIM15 ((uint8_t)0x0E) /* TIM15 Alternate Function mapping */ +#define GPIO_AF14_TIM16 ((uint8_t)0x0E) /* TIM16 Alternate Function mapping */ +#define GPIO_AF14_TIM17 ((uint8_t)0x0E) /* TIM17 Alternate Function mapping */ +#define GPIO_AF14_LPTIM2 ((uint8_t)0x0E) /* LPTIM2 Alternate Function mapping */ + +/** + * @brief AF 15 selection + */ +#define GPIO_AF15_EVENTOUT ((uint8_t)0x0F) /* EVENTOUT Alternate Function mapping */ + +#define IS_GPIO_AF(AF) ((AF) <= (uint8_t)0x0F) + +#endif /* STM32L451xx || STM32L452xx || STM32L462xx */ + +#if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) +/*--------------STM32L471xx/STM32L475xx/STM32L476xx/STM32L485xx/STM32L486xx---*/ +/** + * @brief AF 0 selection + */ +#define GPIO_AF0_RTC_50Hz ((uint8_t)0x00) /* RTC_50Hz Alternate Function mapping */ +#define GPIO_AF0_MCO ((uint8_t)0x00) /* MCO (MCO1 and MCO2) Alternate Function mapping */ +#define GPIO_AF0_SWJ ((uint8_t)0x00) /* SWJ (SWD and JTAG) Alternate Function mapping */ +#if defined(STM32L476xx) || defined(STM32L486xx) +#define GPIO_AF0_LCDBIAS ((uint8_t)0x00) /* LCDBIAS Alternate Function mapping */ +#endif /* STM32L476xx || STM32L486xx */ +#define GPIO_AF0_TRACE ((uint8_t)0x00) /* TRACE Alternate Function mapping */ + +/** + * @brief AF 1 selection + */ +#define GPIO_AF1_TIM1 ((uint8_t)0x01) /* TIM1 Alternate Function mapping */ +#define GPIO_AF1_TIM2 ((uint8_t)0x01) /* TIM2 Alternate Function mapping */ +#define GPIO_AF1_TIM5 ((uint8_t)0x01) /* TIM5 Alternate Function mapping */ +#define GPIO_AF1_TIM8 ((uint8_t)0x01) /* TIM8 Alternate Function mapping */ +#define GPIO_AF1_LPTIM1 ((uint8_t)0x01) /* LPTIM1 Alternate Function mapping */ +#define GPIO_AF1_IR ((uint8_t)0x01) /* IR Alternate Function mapping */ + +/** + * @brief AF 2 selection + */ +#define GPIO_AF2_TIM1 ((uint8_t)0x02) /* TIM1 Alternate Function mapping */ +#define GPIO_AF2_TIM2 ((uint8_t)0x02) /* TIM2 Alternate Function mapping */ +#define GPIO_AF2_TIM3 ((uint8_t)0x02) /* TIM3 Alternate Function mapping */ +#define GPIO_AF2_TIM4 ((uint8_t)0x02) /* TIM4 Alternate Function mapping */ +#define GPIO_AF2_TIM5 ((uint8_t)0x02) /* TIM5 Alternate Function mapping */ + +/** + * @brief AF 3 selection + */ +#define GPIO_AF3_TIM8 ((uint8_t)0x03) /* TIM8 Alternate Function mapping */ +#define GPIO_AF3_TIM1_COMP2 ((uint8_t)0x03) /* TIM1/COMP2 Break in Alternate Function mapping */ +#define GPIO_AF3_TIM1_COMP1 ((uint8_t)0x03) /* TIM1/COMP1 Break in Alternate Function mapping */ + +/** + * @brief AF 4 selection + */ +#define GPIO_AF4_I2C1 ((uint8_t)0x04) /* I2C1 Alternate Function mapping */ +#define GPIO_AF4_I2C2 ((uint8_t)0x04) /* I2C2 Alternate Function mapping */ +#define GPIO_AF4_I2C3 ((uint8_t)0x04) /* I2C3 Alternate Function mapping */ + +/** + * @brief AF 5 selection + */ +#define GPIO_AF5_SPI1 ((uint8_t)0x05) /* SPI1 Alternate Function mapping */ +#define GPIO_AF5_SPI2 ((uint8_t)0x05) /* SPI2 Alternate Function mapping */ + +/** + * @brief AF 6 selection + */ +#define GPIO_AF6_SPI3 ((uint8_t)0x06) /* SPI3 Alternate Function mapping */ +#define GPIO_AF6_DFSDM1 ((uint8_t)0x06) /* DFSDM1 Alternate Function mapping */ + +/** + * @brief AF 7 selection + */ +#define GPIO_AF7_USART1 ((uint8_t)0x07) /* USART1 Alternate Function mapping */ +#define GPIO_AF7_USART2 ((uint8_t)0x07) /* USART2 Alternate Function mapping */ +#define GPIO_AF7_USART3 ((uint8_t)0x07) /* USART3 Alternate Function mapping */ + +/** + * @brief AF 8 selection + */ +#define GPIO_AF8_UART4 ((uint8_t)0x08) /* UART4 Alternate Function mapping */ +#define GPIO_AF8_UART5 ((uint8_t)0x08) /* UART5 Alternate Function mapping */ +#define GPIO_AF8_LPUART1 ((uint8_t)0x08) /* LPUART1 Alternate Function mapping */ + + +/** + * @brief AF 9 selection + */ +#define GPIO_AF9_CAN1 ((uint8_t)0x09) /* CAN1 Alternate Function mapping */ +#define GPIO_AF9_TSC ((uint8_t)0x09) /* TSC Alternate Function mapping */ + +/** + * @brief AF 10 selection + */ +#if defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) +#define GPIO_AF10_OTG_FS ((uint8_t)0x0A) /* OTG_FS Alternate Function mapping */ +#endif /* STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx */ +#define GPIO_AF10_QUADSPI ((uint8_t)0x0A) /* QUADSPI Alternate Function mapping */ + +#if defined(STM32L476xx) || defined(STM32L486xx) +/** + * @brief AF 11 selection + */ +#define GPIO_AF11_LCD ((uint8_t)0x0B) /* LCD Alternate Function mapping */ +#endif /* STM32L476xx || STM32L486xx */ + +/** + * @brief AF 12 selection + */ +#define GPIO_AF12_FMC ((uint8_t)0x0C) /* FMC Alternate Function mapping */ +#define GPIO_AF12_SWPMI1 ((uint8_t)0x0C) /* SWPMI1 Alternate Function mapping */ +#define GPIO_AF12_COMP1 ((uint8_t)0x0C) /* COMP1 Alternate Function mapping */ +#define GPIO_AF12_COMP2 ((uint8_t)0x0C) /* COMP2 Alternate Function mapping */ +#define GPIO_AF12_SDMMC1 ((uint8_t)0x0C) /* SDMMC1 Alternate Function mapping */ + +/** + * @brief AF 13 selection + */ +#define GPIO_AF13_SAI1 ((uint8_t)0x0D) /* SAI1 Alternate Function mapping */ +#define GPIO_AF13_SAI2 ((uint8_t)0x0D) /* SAI2 Alternate Function mapping */ +#define GPIO_AF13_TIM8_COMP2 ((uint8_t)0x0D) /* TIM8/COMP2 Break in Alternate Function mapping */ +#define GPIO_AF13_TIM8_COMP1 ((uint8_t)0x0D) /* TIM8/COMP1 Break in Alternate Function mapping */ + +/** + * @brief AF 14 selection + */ +#define GPIO_AF14_TIM2 ((uint8_t)0x0E) /* TIM2 Alternate Function mapping */ +#define GPIO_AF14_TIM15 ((uint8_t)0x0E) /* TIM15 Alternate Function mapping */ +#define GPIO_AF14_TIM16 ((uint8_t)0x0E) /* TIM16 Alternate Function mapping */ +#define GPIO_AF14_TIM17 ((uint8_t)0x0E) /* TIM17 Alternate Function mapping */ +#define GPIO_AF14_LPTIM2 ((uint8_t)0x0E) /* LPTIM2 Alternate Function mapping */ +#define GPIO_AF14_TIM8_COMP1 ((uint8_t)0x0E) /* TIM8/COMP1 Break in Alternate Function mapping */ + +/** + * @brief AF 15 selection + */ +#define GPIO_AF15_EVENTOUT ((uint8_t)0x0F) /* EVENTOUT Alternate Function mapping */ + +#define IS_GPIO_AF(AF) ((AF) <= (uint8_t)0x0F) + +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx */ + +#if defined(STM32L496xx) || defined(STM32L4A6xx) +/*--------------------------------STM32L496xx/STM32L4A6xx---------------------*/ +/** + * @brief AF 0 selection + */ +#define GPIO_AF0_RTC_50Hz ((uint8_t)0x00) /* RTC_50Hz Alternate Function mapping */ +#define GPIO_AF0_MCO ((uint8_t)0x00) /* MCO (MCO1 and MCO2) Alternate Function mapping */ +#define GPIO_AF0_SWJ ((uint8_t)0x00) /* SWJ (SWD and JTAG) Alternate Function mapping */ +#define GPIO_AF0_TRACE ((uint8_t)0x00) /* TRACE Alternate Function mapping */ + +/** + * @brief AF 1 selection + */ +#define GPIO_AF1_TIM1 ((uint8_t)0x01) /* TIM1 Alternate Function mapping */ +#define GPIO_AF1_TIM2 ((uint8_t)0x01) /* TIM2 Alternate Function mapping */ +#define GPIO_AF1_TIM5 ((uint8_t)0x01) /* TIM5 Alternate Function mapping */ +#define GPIO_AF1_TIM8 ((uint8_t)0x01) /* TIM8 Alternate Function mapping */ +#define GPIO_AF1_LPTIM1 ((uint8_t)0x01) /* LPTIM1 Alternate Function mapping */ +#define GPIO_AF1_IR ((uint8_t)0x01) /* IR Alternate Function mapping */ + +/** + * @brief AF 2 selection + */ +#define GPIO_AF2_TIM1 ((uint8_t)0x02) /* TIM1 Alternate Function mapping */ +#define GPIO_AF2_TIM2 ((uint8_t)0x02) /* TIM2 Alternate Function mapping */ +#define GPIO_AF2_TIM3 ((uint8_t)0x02) /* TIM3 Alternate Function mapping */ +#define GPIO_AF2_TIM4 ((uint8_t)0x02) /* TIM4 Alternate Function mapping */ +#define GPIO_AF2_TIM5 ((uint8_t)0x02) /* TIM5 Alternate Function mapping */ +#define GPIO_AF2_I2C4 ((uint8_t)0x02) /* I2C4 Alternate Function mapping */ + +/** + * @brief AF 3 selection + */ +#define GPIO_AF3_TIM8 ((uint8_t)0x03) /* TIM8 Alternate Function mapping */ +#define GPIO_AF3_TIM1_COMP2 ((uint8_t)0x03) /* TIM1/COMP2 Break in Alternate Function mapping */ +#define GPIO_AF3_TIM1_COMP1 ((uint8_t)0x03) /* TIM1/COMP1 Break in Alternate Function mapping */ +#define GPIO_AF3_CAN2 ((uint8_t)0x03) /* CAN2 Alternate Function mapping */ +#define GPIO_AF3_I2C4 ((uint8_t)0x03) /* I2C4 Alternate Function mapping */ +#define GPIO_AF3_QUADSPI ((uint8_t)0x03) /* QUADSPI Alternate Function mapping */ +#define GPIO_AF3_SPI2 ((uint8_t)0x03) /* SPI2 Alternate Function mapping */ +#define GPIO_AF3_USART2 ((uint8_t)0x03) /* USART2 Alternate Function mapping */ + +/** + * @brief AF 4 selection + */ +#define GPIO_AF4_I2C1 ((uint8_t)0x04) /* I2C1 Alternate Function mapping */ +#define GPIO_AF4_I2C2 ((uint8_t)0x04) /* I2C2 Alternate Function mapping */ +#define GPIO_AF4_I2C3 ((uint8_t)0x04) /* I2C3 Alternate Function mapping */ +#define GPIO_AF4_I2C4 ((uint8_t)0x04) /* I2C4 Alternate Function mapping */ +#define GPIO_AF4_DCMI ((uint8_t)0x04) /* DCMI Alternate Function mapping */ + +/** + * @brief AF 5 selection + */ +#define GPIO_AF5_SPI1 ((uint8_t)0x05) /* SPI1 Alternate Function mapping */ +#define GPIO_AF5_SPI2 ((uint8_t)0x05) /* SPI2 Alternate Function mapping */ +#define GPIO_AF5_DCMI ((uint8_t)0x05) /* DCMI Alternate Function mapping */ +#define GPIO_AF5_I2C4 ((uint8_t)0x05) /* I2C4 Alternate Function mapping */ +#define GPIO_AF5_QUADSPI ((uint8_t)0x05) /* QUADSPI Alternate Function mapping */ + +/** + * @brief AF 6 selection + */ +#define GPIO_AF6_SPI3 ((uint8_t)0x06) /* SPI3 Alternate Function mapping */ +#define GPIO_AF6_DFSDM1 ((uint8_t)0x06) /* DFSDM1 Alternate Function mapping */ +#define GPIO_AF6_I2C3 ((uint8_t)0x06) /* I2C3 Alternate Function mapping */ + +/** + * @brief AF 7 selection + */ +#define GPIO_AF7_USART1 ((uint8_t)0x07) /* USART1 Alternate Function mapping */ +#define GPIO_AF7_USART2 ((uint8_t)0x07) /* USART2 Alternate Function mapping */ +#define GPIO_AF7_USART3 ((uint8_t)0x07) /* USART3 Alternate Function mapping */ + +/** + * @brief AF 8 selection + */ +#define GPIO_AF8_UART4 ((uint8_t)0x08) /* UART4 Alternate Function mapping */ +#define GPIO_AF8_UART5 ((uint8_t)0x08) /* UART5 Alternate Function mapping */ +#define GPIO_AF8_LPUART1 ((uint8_t)0x08) /* LPUART1 Alternate Function mapping */ +#define GPIO_AF8_CAN2 ((uint8_t)0x08) /* CAN2 Alternate Function mapping */ + +/** + * @brief AF 9 selection + */ +#define GPIO_AF9_CAN1 ((uint8_t)0x09) /* CAN1 Alternate Function mapping */ +#define GPIO_AF9_TSC ((uint8_t)0x09) /* TSC Alternate Function mapping */ + +/** + * @brief AF 10 selection + */ +#define GPIO_AF10_OTG_FS ((uint8_t)0x0A) /* OTG_FS Alternate Function mapping */ +#define GPIO_AF10_QUADSPI ((uint8_t)0x0A) /* QUADSPI Alternate Function mapping */ +#define GPIO_AF10_CAN2 ((uint8_t)0x0A) /* CAN2 Alternate Function mapping */ +#define GPIO_AF10_DCMI ((uint8_t)0x0A) /* DCMI Alternate Function mapping */ + +/** + * @brief AF 11 selection + */ +#define GPIO_AF11_LCD ((uint8_t)0x0B) /* LCD Alternate Function mapping */ + +/** + * @brief AF 12 selection + */ +#define GPIO_AF12_FMC ((uint8_t)0x0C) /* FMC Alternate Function mapping */ +#define GPIO_AF12_SWPMI1 ((uint8_t)0x0C) /* SWPMI1 Alternate Function mapping */ +#define GPIO_AF12_COMP1 ((uint8_t)0x0C) /* COMP1 Alternate Function mapping */ +#define GPIO_AF12_COMP2 ((uint8_t)0x0C) /* COMP2 Alternate Function mapping */ +#define GPIO_AF12_SDMMC1 ((uint8_t)0x0C) /* SDMMC1 Alternate Function mapping */ +#define GPIO_AF12_TIM1_COMP2 ((uint8_t)0x0C) /* TIM1/COMP2 Break in Alternate Function mapping */ +#define GPIO_AF12_TIM1_COMP1 ((uint8_t)0x0C) /* TIM1/COMP1 Break in Alternate Function mapping */ +#define GPIO_AF12_TIM8_COMP2 ((uint8_t)0x0C) /* TIM8/COMP2 Break in Alternate Function mapping */ + +/** + * @brief AF 13 selection + */ +#define GPIO_AF13_SAI1 ((uint8_t)0x0D) /* SAI1 Alternate Function mapping */ +#define GPIO_AF13_SAI2 ((uint8_t)0x0D) /* SAI2 Alternate Function mapping */ +#define GPIO_AF13_TIM8_COMP2 ((uint8_t)0x0D) /* TIM8/COMP2 Break in Alternate Function mapping */ +#define GPIO_AF13_TIM8_COMP1 ((uint8_t)0x0D) /* TIM8/COMP1 Break in Alternate Function mapping */ + +/** + * @brief AF 14 selection + */ +#define GPIO_AF14_TIM2 ((uint8_t)0x0E) /* TIM2 Alternate Function mapping */ +#define GPIO_AF14_TIM15 ((uint8_t)0x0E) /* TIM15 Alternate Function mapping */ +#define GPIO_AF14_TIM16 ((uint8_t)0x0E) /* TIM16 Alternate Function mapping */ +#define GPIO_AF14_TIM17 ((uint8_t)0x0E) /* TIM17 Alternate Function mapping */ +#define GPIO_AF14_LPTIM2 ((uint8_t)0x0E) /* LPTIM2 Alternate Function mapping */ +#define GPIO_AF14_TIM8_COMP1 ((uint8_t)0x0E) /* TIM8/COMP1 Break in Alternate Function mapping */ + +/** + * @brief AF 15 selection + */ +#define GPIO_AF15_EVENTOUT ((uint8_t)0x0F) /* EVENTOUT Alternate Function mapping */ + +#define IS_GPIO_AF(AF) ((AF) <= (uint8_t)0x0F) + +#endif /* STM32L496xx || STM32L4A6xx */ + +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +/*---STM32L4R5xx/STM32L4R7xx/STM32L4R9xx/STM32L4S5xx/STM32L4S7xx/STM32L4S9xx--*/ +/** + * @brief AF 0 selection + */ +#define GPIO_AF0_RTC_50Hz ((uint8_t)0x00) /* RTC_50Hz Alternate Function mapping */ +#define GPIO_AF0_MCO ((uint8_t)0x00) /* MCO (MCO1 and MCO2) Alternate Function mapping */ +#define GPIO_AF0_SWJ ((uint8_t)0x00) /* SWJ (SWD and JTAG) Alternate Function mapping */ +#define GPIO_AF0_TRACE ((uint8_t)0x00) /* TRACE Alternate Function mapping */ + +/** + * @brief AF 1 selection + */ +#define GPIO_AF1_TIM1 ((uint8_t)0x01) /* TIM1 Alternate Function mapping */ +#define GPIO_AF1_TIM2 ((uint8_t)0x01) /* TIM2 Alternate Function mapping */ +#define GPIO_AF1_TIM5 ((uint8_t)0x01) /* TIM5 Alternate Function mapping */ +#define GPIO_AF1_TIM8 ((uint8_t)0x01) /* TIM8 Alternate Function mapping */ +#define GPIO_AF1_LPTIM1 ((uint8_t)0x01) /* LPTIM1 Alternate Function mapping */ +#define GPIO_AF1_IR ((uint8_t)0x01) /* IR Alternate Function mapping */ + +/** + * @brief AF 2 selection + */ +#define GPIO_AF2_TIM1 ((uint8_t)0x02) /* TIM1 Alternate Function mapping */ +#define GPIO_AF2_TIM2 ((uint8_t)0x02) /* TIM2 Alternate Function mapping */ +#define GPIO_AF2_TIM3 ((uint8_t)0x02) /* TIM3 Alternate Function mapping */ +#define GPIO_AF2_TIM4 ((uint8_t)0x02) /* TIM4 Alternate Function mapping */ +#define GPIO_AF2_TIM5 ((uint8_t)0x02) /* TIM5 Alternate Function mapping */ + +/** + * @brief AF 3 selection + */ +#define GPIO_AF3_I2C4 ((uint8_t)0x03) /* I2C4 Alternate Function mapping */ +#define GPIO_AF3_OCTOSPIM_P1 ((uint8_t)0x03) /* OctoSPI Manager Port 1 Alternate Function mapping */ +#define GPIO_AF3_SAI1 ((uint8_t)0x03) /* SAI1 Alternate Function mapping */ +#define GPIO_AF3_SPI2 ((uint8_t)0x03) /* SPI2 Alternate Function mapping */ +#define GPIO_AF3_TIM1_COMP1 ((uint8_t)0x03) /* TIM1/COMP1 Break in Alternate Function mapping */ +#define GPIO_AF3_TIM1_COMP2 ((uint8_t)0x03) /* TIM1/COMP2 Break in Alternate Function mapping */ +#define GPIO_AF3_TIM8 ((uint8_t)0x03) /* TIM8 Alternate Function mapping */ +#define GPIO_AF3_TIM8_COMP1 ((uint8_t)0x03) /* TIM8/COMP1 Break in Alternate Function mapping */ +#define GPIO_AF3_TIM8_COMP2 ((uint8_t)0x03) /* TIM8/COMP2 Break in Alternate Function mapping */ +#define GPIO_AF3_USART2 ((uint8_t)0x03) /* USART2 Alternate Function mapping */ + +/** + * @brief AF 4 selection + */ +#define GPIO_AF4_I2C1 ((uint8_t)0x04) /* I2C1 Alternate Function mapping */ +#define GPIO_AF4_I2C2 ((uint8_t)0x04) /* I2C2 Alternate Function mapping */ +#define GPIO_AF4_I2C3 ((uint8_t)0x04) /* I2C3 Alternate Function mapping */ +#define GPIO_AF4_I2C4 ((uint8_t)0x04) /* I2C4 Alternate Function mapping */ +#define GPIO_AF4_DCMI ((uint8_t)0x04) /* DCMI Alternate Function mapping */ + +/** + * @brief AF 5 selection + */ +#define GPIO_AF5_DCMI ((uint8_t)0x05) /* DCMI Alternate Function mapping */ +#define GPIO_AF5_DFSDM1 ((uint8_t)0x05) /* DFSDM1 Alternate Function mapping */ +#define GPIO_AF5_I2C4 ((uint8_t)0x05) /* I2C4 Alternate Function mapping */ +#define GPIO_AF5_OCTOSPIM_P1 ((uint8_t)0x05) /* OctoSPI Manager Port 1 Alternate Function mapping */ +#define GPIO_AF5_OCTOSPIM_P2 ((uint8_t)0x05) /* OctoSPI Manager Port 2 Alternate Function mapping */ +#define GPIO_AF5_SPI1 ((uint8_t)0x05) /* SPI1 Alternate Function mapping */ +#define GPIO_AF5_SPI2 ((uint8_t)0x05) /* SPI2 Alternate Function mapping */ +#define GPIO_AF5_SPI3 ((uint8_t)0x05) /* SPI2 Alternate Function mapping */ + +/** + * @brief AF 6 selection + */ +#define GPIO_AF6_DFSDM1 ((uint8_t)0x06) /* DFSDM1 Alternate Function mapping */ +#define GPIO_AF6_I2C3 ((uint8_t)0x06) /* I2C3 Alternate Function mapping */ +#define GPIO_AF6_SPI3 ((uint8_t)0x06) /* SPI3 Alternate Function mapping */ + +/** + * @brief AF 7 selection + */ +#define GPIO_AF7_USART1 ((uint8_t)0x07) /* USART1 Alternate Function mapping */ +#define GPIO_AF7_USART2 ((uint8_t)0x07) /* USART2 Alternate Function mapping */ +#define GPIO_AF7_USART3 ((uint8_t)0x07) /* USART3 Alternate Function mapping */ + +/** + * @brief AF 8 selection + */ +#define GPIO_AF8_LPUART1 ((uint8_t)0x08) /* LPUART1 Alternate Function mapping */ +#define GPIO_AF8_SDMMC1 ((uint8_t)0x08) /* SDMMC1 Alternate Function mapping */ +#define GPIO_AF8_UART4 ((uint8_t)0x08) /* UART4 Alternate Function mapping */ +#define GPIO_AF8_UART5 ((uint8_t)0x08) /* UART5 Alternate Function mapping */ + +/** + * @brief AF 9 selection + */ +#define GPIO_AF9_CAN1 ((uint8_t)0x09) /* CAN1 Alternate Function mapping */ +#define GPIO_AF9_LTDC ((uint8_t)0x09) /* LTDC Alternate Function mapping */ +#define GPIO_AF9_TSC ((uint8_t)0x09) /* TSC Alternate Function mapping */ + +/** + * @brief AF 10 selection + */ +#define GPIO_AF10_DCMI ((uint8_t)0x0A) /* DCMI Alternate Function mapping */ +#define GPIO_AF10_OCTOSPIM_P1 ((uint8_t)0x0A) /* OctoSPI Manager Port 1 Alternate Function mapping */ +#define GPIO_AF10_OCTOSPIM_P2 ((uint8_t)0x0A) /* OctoSPI Manager Port 2 Alternate Function mapping */ +#define GPIO_AF10_OTG_FS ((uint8_t)0x0A) /* OTG_FS Alternate Function mapping */ + +/** + * @brief AF 11 selection + */ +#define GPIO_AF11_DSI ((uint8_t)0x0B) /* DSI Alternate Function mapping */ +#define GPIO_AF11_LTDC ((uint8_t)0x0B) /* LTDC Alternate Function mapping */ + +/** + * @brief AF 12 selection + */ +#define GPIO_AF12_COMP1 ((uint8_t)0x0C) /* COMP1 Alternate Function mapping */ +#define GPIO_AF12_COMP2 ((uint8_t)0x0C) /* COMP2 Alternate Function mapping */ +#define GPIO_AF12_DSI ((uint8_t)0x0C) /* FMC Alternate Function mapping */ +#define GPIO_AF12_FMC ((uint8_t)0x0C) /* FMC Alternate Function mapping */ +#define GPIO_AF12_SDMMC1 ((uint8_t)0x0C) /* SDMMC1 Alternate Function mapping */ +#define GPIO_AF12_TIM1_COMP1 ((uint8_t)0x0C) /* TIM1/COMP1 Break in Alternate Function mapping */ +#define GPIO_AF12_TIM1_COMP2 ((uint8_t)0x0C) /* TIM1/COMP2 Break in Alternate Function mapping */ +#define GPIO_AF12_TIM8_COMP2 ((uint8_t)0x0C) /* TIM8/COMP2 Break in Alternate Function mapping */ + +/** + * @brief AF 13 selection + */ +#define GPIO_AF13_SAI1 ((uint8_t)0x0D) /* SAI1 Alternate Function mapping */ +#define GPIO_AF13_SAI2 ((uint8_t)0x0D) /* SAI2 Alternate Function mapping */ +#define GPIO_AF13_TIM8_COMP1 ((uint8_t)0x0D) /* TIM8/COMP1 Break in Alternate Function mapping */ + +/** + * @brief AF 14 selection + */ +#define GPIO_AF14_TIM15 ((uint8_t)0x0E) /* TIM15 Alternate Function mapping */ +#define GPIO_AF14_TIM16 ((uint8_t)0x0E) /* TIM16 Alternate Function mapping */ +#define GPIO_AF14_TIM17 ((uint8_t)0x0E) /* TIM17 Alternate Function mapping */ +#define GPIO_AF14_LPTIM2 ((uint8_t)0x0E) /* LPTIM2 Alternate Function mapping */ +#define GPIO_AF14_TIM8_COMP2 ((uint8_t)0x0E) /* TIM8/COMP2 Break in Alternate Function mapping */ + +/** + * @brief AF 15 selection + */ +#define GPIO_AF15_EVENTOUT ((uint8_t)0x0F) /* EVENTOUT Alternate Function mapping */ + +#define IS_GPIO_AF(AF) ((AF) <= (uint8_t)0x0F) + +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup GPIOEx_Exported_Macros GPIOEx Exported Macros + * @{ + */ + +/** @defgroup GPIOEx_Get_Port_Index GPIOEx_Get Port Index +* @{ + */ +#if defined(STM32L431xx) || defined(STM32L433xx) || defined(STM32L443xx) + +#define GPIO_GET_INDEX(__GPIOx__) (((__GPIOx__) == (GPIOA))? 0U :\ + ((__GPIOx__) == (GPIOB))? 1U :\ + ((__GPIOx__) == (GPIOC))? 2U :\ + ((__GPIOx__) == (GPIOD))? 3U :\ + ((__GPIOx__) == (GPIOE))? 4U : 7U) + +#endif /* STM32L431xx || STM32L433xx || STM32L443xx */ + +#if defined(STM32L432xx) || defined(STM32L442xx) + +#define GPIO_GET_INDEX(__GPIOx__) (((__GPIOx__) == (GPIOA))? 0U :\ + ((__GPIOx__) == (GPIOB))? 1U :\ + ((__GPIOx__) == (GPIOC))? 2U : 7U) + +#endif /* STM32L432xx || STM32L442xx */ + +#if defined(STM32L451xx) || defined(STM32L452xx) || defined(STM32L462xx) + +#define GPIO_GET_INDEX(__GPIOx__) (((__GPIOx__) == (GPIOA))? 0U :\ + ((__GPIOx__) == (GPIOB))? 1U :\ + ((__GPIOx__) == (GPIOC))? 2U :\ + ((__GPIOx__) == (GPIOD))? 3U :\ + ((__GPIOx__) == (GPIOE))? 4U : 7U) + +#endif /* STM32L451xx || STM32L452xx || STM32L462xx */ + +#if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) + +#define GPIO_GET_INDEX(__GPIOx__) (((__GPIOx__) == (GPIOA))? 0U :\ + ((__GPIOx__) == (GPIOB))? 1U :\ + ((__GPIOx__) == (GPIOC))? 2U :\ + ((__GPIOx__) == (GPIOD))? 3U :\ + ((__GPIOx__) == (GPIOE))? 4U :\ + ((__GPIOx__) == (GPIOF))? 5U :\ + ((__GPIOx__) == (GPIOG))? 6U : 7U) + +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx */ + +#if defined(STM32L496xx) || defined(STM32L4A6xx) + +#define GPIO_GET_INDEX(__GPIOx__) (((__GPIOx__) == (GPIOA))? 0U :\ + ((__GPIOx__) == (GPIOB))? 1U :\ + ((__GPIOx__) == (GPIOC))? 2U :\ + ((__GPIOx__) == (GPIOD))? 3U :\ + ((__GPIOx__) == (GPIOE))? 4U :\ + ((__GPIOx__) == (GPIOF))? 5U :\ + ((__GPIOx__) == (GPIOG))? 6U :\ + ((__GPIOx__) == (GPIOH))? 7U : 8U) + +#endif /* STM32L496xx || STM32L4A6xx */ + +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + +#define GPIO_GET_INDEX(__GPIOx__) (((__GPIOx__) == (GPIOA))? 0U :\ + ((__GPIOx__) == (GPIOB))? 1U :\ + ((__GPIOx__) == (GPIOC))? 2U :\ + ((__GPIOx__) == (GPIOD))? 3U :\ + ((__GPIOx__) == (GPIOE))? 4U :\ + ((__GPIOx__) == (GPIOF))? 5U :\ + ((__GPIOx__) == (GPIOG))? 6U :\ + ((__GPIOx__) == (GPIOH))? 7U : 8U) + +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +/** + * @} + */ + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_HAL_GPIO_EX_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_i2c.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_i2c.h new file mode 100644 index 0000000..7a8f85f --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_i2c.h @@ -0,0 +1,708 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_i2c.h + * @author MCD Application Team + * @brief Header file of I2C HAL module. + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_I2C_H +#define __STM32L4xx_HAL_I2C_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup I2C + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup I2C_Exported_Types I2C Exported Types + * @{ + */ + +/** @defgroup I2C_Configuration_Structure_definition I2C Configuration Structure definition + * @brief I2C Configuration Structure definition + * @{ + */ +typedef struct +{ + uint32_t Timing; /*!< Specifies the I2C_TIMINGR_register value. + This parameter calculated by referring to I2C initialization + section in Reference manual */ + + uint32_t OwnAddress1; /*!< Specifies the first device own address. + This parameter can be a 7-bit or 10-bit address. */ + + uint32_t AddressingMode; /*!< Specifies if 7-bit or 10-bit addressing mode is selected. + This parameter can be a value of @ref I2C_ADDRESSING_MODE */ + + uint32_t DualAddressMode; /*!< Specifies if dual addressing mode is selected. + This parameter can be a value of @ref I2C_DUAL_ADDRESSING_MODE */ + + uint32_t OwnAddress2; /*!< Specifies the second device own address if dual addressing mode is selected + This parameter can be a 7-bit address. */ + + uint32_t OwnAddress2Masks; /*!< Specifies the acknowledge mask address second device own address if dual addressing mode is selected + This parameter can be a value of @ref I2C_OWN_ADDRESS2_MASKS */ + + uint32_t GeneralCallMode; /*!< Specifies if general call mode is selected. + This parameter can be a value of @ref I2C_GENERAL_CALL_ADDRESSING_MODE */ + + uint32_t NoStretchMode; /*!< Specifies if nostretch mode is selected. + This parameter can be a value of @ref I2C_NOSTRETCH_MODE */ + +} I2C_InitTypeDef; + +/** + * @} + */ + +/** @defgroup HAL_state_structure_definition HAL state structure definition + * @brief HAL State structure definition + * @note HAL I2C State value coding follow below described bitmap :\n + * b7-b6 Error information\n + * 00 : No Error\n + * 01 : Abort (Abort user request on going)\n + * 10 : Timeout\n + * 11 : Error\n + * b5 IP initilisation status\n + * 0 : Reset (IP not initialized)\n + * 1 : Init done (IP initialized and ready to use. HAL I2C Init function called)\n + * b4 (not used)\n + * x : Should be set to 0\n + * b3\n + * 0 : Ready or Busy (No Listen mode ongoing)\n + * 1 : Listen (IP in Address Listen Mode)\n + * b2 Intrinsic process state\n + * 0 : Ready\n + * 1 : Busy (IP busy with some configuration or internal operations)\n + * b1 Rx state\n + * 0 : Ready (no Rx operation ongoing)\n + * 1 : Busy (Rx operation ongoing)\n + * b0 Tx state\n + * 0 : Ready (no Tx operation ongoing)\n + * 1 : Busy (Tx operation ongoing) + * @{ + */ +typedef enum +{ + HAL_I2C_STATE_RESET = 0x00U, /*!< Peripheral is not yet Initialized */ + HAL_I2C_STATE_READY = 0x20U, /*!< Peripheral Initialized and ready for use */ + HAL_I2C_STATE_BUSY = 0x24U, /*!< An internal process is ongoing */ + HAL_I2C_STATE_BUSY_TX = 0x21U, /*!< Data Transmission process is ongoing */ + HAL_I2C_STATE_BUSY_RX = 0x22U, /*!< Data Reception process is ongoing */ + HAL_I2C_STATE_LISTEN = 0x28U, /*!< Address Listen Mode is ongoing */ + HAL_I2C_STATE_BUSY_TX_LISTEN = 0x29U, /*!< Address Listen Mode and Data Transmission + process is ongoing */ + HAL_I2C_STATE_BUSY_RX_LISTEN = 0x2AU, /*!< Address Listen Mode and Data Reception + process is ongoing */ + HAL_I2C_STATE_ABORT = 0x60U, /*!< Abort user request ongoing */ + HAL_I2C_STATE_TIMEOUT = 0xA0U, /*!< Timeout state */ + HAL_I2C_STATE_ERROR = 0xE0U /*!< Error */ + +} HAL_I2C_StateTypeDef; + +/** + * @} + */ + +/** @defgroup HAL_mode_structure_definition HAL mode structure definition + * @brief HAL Mode structure definition + * @note HAL I2C Mode value coding follow below described bitmap :\n + * b7 (not used)\n + * x : Should be set to 0\n + * b6\n + * 0 : None\n + * 1 : Memory (HAL I2C communication is in Memory Mode)\n + * b5\n + * 0 : None\n + * 1 : Slave (HAL I2C communication is in Slave Mode)\n + * b4\n + * 0 : None\n + * 1 : Master (HAL I2C communication is in Master Mode)\n + * b3-b2-b1-b0 (not used)\n + * xxxx : Should be set to 0000 + * @{ + */ +typedef enum +{ + HAL_I2C_MODE_NONE = 0x00U, /*!< No I2C communication on going */ + HAL_I2C_MODE_MASTER = 0x10U, /*!< I2C communication is in Master Mode */ + HAL_I2C_MODE_SLAVE = 0x20U, /*!< I2C communication is in Slave Mode */ + HAL_I2C_MODE_MEM = 0x40U /*!< I2C communication is in Memory Mode */ + +} HAL_I2C_ModeTypeDef; + +/** + * @} + */ + +/** @defgroup I2C_Error_Code_definition I2C Error Code definition + * @brief I2C Error Code definition + * @{ + */ +#define HAL_I2C_ERROR_NONE (0x00000000U) /*!< No error */ +#define HAL_I2C_ERROR_BERR (0x00000001U) /*!< BERR error */ +#define HAL_I2C_ERROR_ARLO (0x00000002U) /*!< ARLO error */ +#define HAL_I2C_ERROR_AF (0x00000004U) /*!< ACKF error */ +#define HAL_I2C_ERROR_OVR (0x00000008U) /*!< OVR error */ +#define HAL_I2C_ERROR_DMA (0x00000010U) /*!< DMA transfer error */ +#define HAL_I2C_ERROR_TIMEOUT (0x00000020U) /*!< Timeout error */ +#define HAL_I2C_ERROR_SIZE (0x00000040U) /*!< Size Management error */ +/** + * @} + */ + +/** @defgroup I2C_handle_Structure_definition I2C handle Structure definition + * @brief I2C handle Structure definition + * @{ + */ +typedef struct __I2C_HandleTypeDef +{ + I2C_TypeDef *Instance; /*!< I2C registers base address */ + + I2C_InitTypeDef Init; /*!< I2C communication parameters */ + + uint8_t *pBuffPtr; /*!< Pointer to I2C transfer buffer */ + + uint16_t XferSize; /*!< I2C transfer size */ + + __IO uint16_t XferCount; /*!< I2C transfer counter */ + + __IO uint32_t XferOptions; /*!< I2C sequantial transfer options, this parameter can + be a value of @ref I2C_XFEROPTIONS */ + + __IO uint32_t PreviousState; /*!< I2C communication Previous state */ + + HAL_StatusTypeDef(*XferISR)(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags, uint32_t ITSources); /*!< I2C transfer IRQ handler function pointer */ + + DMA_HandleTypeDef *hdmatx; /*!< I2C Tx DMA handle parameters */ + + DMA_HandleTypeDef *hdmarx; /*!< I2C Rx DMA handle parameters */ + + HAL_LockTypeDef Lock; /*!< I2C locking object */ + + __IO HAL_I2C_StateTypeDef State; /*!< I2C communication state */ + + __IO HAL_I2C_ModeTypeDef Mode; /*!< I2C communication mode */ + + __IO uint32_t ErrorCode; /*!< I2C Error code */ + + __IO uint32_t AddrEventCount; /*!< I2C Address Event counter */ +} I2C_HandleTypeDef; +/** + * @} + */ + +/** + * @} + */ +/* Exported constants --------------------------------------------------------*/ + +/** @defgroup I2C_Exported_Constants I2C Exported Constants + * @{ + */ + +/** @defgroup I2C_XFEROPTIONS I2C Sequential Transfer Options + * @{ + */ +#define I2C_FIRST_FRAME ((uint32_t)I2C_SOFTEND_MODE) +#define I2C_FIRST_AND_NEXT_FRAME ((uint32_t)(I2C_RELOAD_MODE | I2C_SOFTEND_MODE)) +#define I2C_NEXT_FRAME ((uint32_t)(I2C_RELOAD_MODE | I2C_SOFTEND_MODE)) +#define I2C_FIRST_AND_LAST_FRAME ((uint32_t)I2C_AUTOEND_MODE) +#define I2C_LAST_FRAME ((uint32_t)I2C_AUTOEND_MODE) +/** + * @} + */ + +/** @defgroup I2C_ADDRESSING_MODE I2C Addressing Mode + * @{ + */ +#define I2C_ADDRESSINGMODE_7BIT (0x00000001U) +#define I2C_ADDRESSINGMODE_10BIT (0x00000002U) +/** + * @} + */ + +/** @defgroup I2C_DUAL_ADDRESSING_MODE I2C Dual Addressing Mode + * @{ + */ +#define I2C_DUALADDRESS_DISABLE (0x00000000U) +#define I2C_DUALADDRESS_ENABLE I2C_OAR2_OA2EN +/** + * @} + */ + +/** @defgroup I2C_OWN_ADDRESS2_MASKS I2C Own Address2 Masks + * @{ + */ +#define I2C_OA2_NOMASK ((uint8_t)0x00U) +#define I2C_OA2_MASK01 ((uint8_t)0x01U) +#define I2C_OA2_MASK02 ((uint8_t)0x02U) +#define I2C_OA2_MASK03 ((uint8_t)0x03U) +#define I2C_OA2_MASK04 ((uint8_t)0x04U) +#define I2C_OA2_MASK05 ((uint8_t)0x05U) +#define I2C_OA2_MASK06 ((uint8_t)0x06U) +#define I2C_OA2_MASK07 ((uint8_t)0x07U) +/** + * @} + */ + +/** @defgroup I2C_GENERAL_CALL_ADDRESSING_MODE I2C General Call Addressing Mode + * @{ + */ +#define I2C_GENERALCALL_DISABLE (0x00000000U) +#define I2C_GENERALCALL_ENABLE I2C_CR1_GCEN +/** + * @} + */ + +/** @defgroup I2C_NOSTRETCH_MODE I2C No-Stretch Mode + * @{ + */ +#define I2C_NOSTRETCH_DISABLE (0x00000000U) +#define I2C_NOSTRETCH_ENABLE I2C_CR1_NOSTRETCH +/** + * @} + */ + +/** @defgroup I2C_MEMORY_ADDRESS_SIZE I2C Memory Address Size + * @{ + */ +#define I2C_MEMADD_SIZE_8BIT (0x00000001U) +#define I2C_MEMADD_SIZE_16BIT (0x00000002U) +/** + * @} + */ + +/** @defgroup I2C_XFERDIRECTION I2C Transfer Direction Master Point of View + * @{ + */ +#define I2C_DIRECTION_TRANSMIT (0x00000000U) +#define I2C_DIRECTION_RECEIVE (0x00000001U) +/** + * @} + */ + +/** @defgroup I2C_RELOAD_END_MODE I2C Reload End Mode + * @{ + */ +#define I2C_RELOAD_MODE I2C_CR2_RELOAD +#define I2C_AUTOEND_MODE I2C_CR2_AUTOEND +#define I2C_SOFTEND_MODE (0x00000000U) +/** + * @} + */ + +/** @defgroup I2C_START_STOP_MODE I2C Start or Stop Mode + * @{ + */ +#define I2C_NO_STARTSTOP (0x00000000U) +#define I2C_GENERATE_STOP (uint32_t)(0x80000000U | I2C_CR2_STOP) +#define I2C_GENERATE_START_READ (uint32_t)(0x80000000U | I2C_CR2_START | I2C_CR2_RD_WRN) +#define I2C_GENERATE_START_WRITE (uint32_t)(0x80000000U | I2C_CR2_START) +/** + * @} + */ + +/** @defgroup I2C_Interrupt_configuration_definition I2C Interrupt configuration definition + * @brief I2C Interrupt definition + * Elements values convention: 0xXXXXXXXX + * - XXXXXXXX : Interrupt control mask + * @{ + */ +#define I2C_IT_ERRI I2C_CR1_ERRIE +#define I2C_IT_TCI I2C_CR1_TCIE +#define I2C_IT_STOPI I2C_CR1_STOPIE +#define I2C_IT_NACKI I2C_CR1_NACKIE +#define I2C_IT_ADDRI I2C_CR1_ADDRIE +#define I2C_IT_RXI I2C_CR1_RXIE +#define I2C_IT_TXI I2C_CR1_TXIE +/** + * @} + */ + +/** @defgroup I2C_Flag_definition I2C Flag definition + * @{ + */ +#define I2C_FLAG_TXE I2C_ISR_TXE +#define I2C_FLAG_TXIS I2C_ISR_TXIS +#define I2C_FLAG_RXNE I2C_ISR_RXNE +#define I2C_FLAG_ADDR I2C_ISR_ADDR +#define I2C_FLAG_AF I2C_ISR_NACKF +#define I2C_FLAG_STOPF I2C_ISR_STOPF +#define I2C_FLAG_TC I2C_ISR_TC +#define I2C_FLAG_TCR I2C_ISR_TCR +#define I2C_FLAG_BERR I2C_ISR_BERR +#define I2C_FLAG_ARLO I2C_ISR_ARLO +#define I2C_FLAG_OVR I2C_ISR_OVR +#define I2C_FLAG_PECERR I2C_ISR_PECERR +#define I2C_FLAG_TIMEOUT I2C_ISR_TIMEOUT +#define I2C_FLAG_ALERT I2C_ISR_ALERT +#define I2C_FLAG_BUSY I2C_ISR_BUSY +#define I2C_FLAG_DIR I2C_ISR_DIR +/** + * @} + */ + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ + +/** @defgroup I2C_Exported_Macros I2C Exported Macros + * @{ + */ + +/** @brief Reset I2C handle state. + * @param __HANDLE__ specifies the I2C Handle. + * @retval None + */ +#define __HAL_I2C_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_I2C_STATE_RESET) + +/** @brief Enable the specified I2C interrupt. + * @param __HANDLE__ specifies the I2C Handle. + * @param __INTERRUPT__ specifies the interrupt source to enable. + * This parameter can be one of the following values: + * @arg @ref I2C_IT_ERRI Errors interrupt enable + * @arg @ref I2C_IT_TCI Transfer complete interrupt enable + * @arg @ref I2C_IT_STOPI STOP detection interrupt enable + * @arg @ref I2C_IT_NACKI NACK received interrupt enable + * @arg @ref I2C_IT_ADDRI Address match interrupt enable + * @arg @ref I2C_IT_RXI RX interrupt enable + * @arg @ref I2C_IT_TXI TX interrupt enable + * + * @retval None + */ +#define __HAL_I2C_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CR1 |= (__INTERRUPT__)) + +/** @brief Disable the specified I2C interrupt. + * @param __HANDLE__ specifies the I2C Handle. + * @param __INTERRUPT__ specifies the interrupt source to disable. + * This parameter can be one of the following values: + * @arg @ref I2C_IT_ERRI Errors interrupt enable + * @arg @ref I2C_IT_TCI Transfer complete interrupt enable + * @arg @ref I2C_IT_STOPI STOP detection interrupt enable + * @arg @ref I2C_IT_NACKI NACK received interrupt enable + * @arg @ref I2C_IT_ADDRI Address match interrupt enable + * @arg @ref I2C_IT_RXI RX interrupt enable + * @arg @ref I2C_IT_TXI TX interrupt enable + * + * @retval None + */ +#define __HAL_I2C_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CR1 &= (~(__INTERRUPT__))) + +/** @brief Check whether the specified I2C interrupt source is enabled or not. + * @param __HANDLE__ specifies the I2C Handle. + * @param __INTERRUPT__ specifies the I2C interrupt source to check. + * This parameter can be one of the following values: + * @arg @ref I2C_IT_ERRI Errors interrupt enable + * @arg @ref I2C_IT_TCI Transfer complete interrupt enable + * @arg @ref I2C_IT_STOPI STOP detection interrupt enable + * @arg @ref I2C_IT_NACKI NACK received interrupt enable + * @arg @ref I2C_IT_ADDRI Address match interrupt enable + * @arg @ref I2C_IT_RXI RX interrupt enable + * @arg @ref I2C_IT_TXI TX interrupt enable + * + * @retval The new state of __INTERRUPT__ (SET or RESET). + */ +#define __HAL_I2C_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) ((((__HANDLE__)->Instance->CR1 & (__INTERRUPT__)) == (__INTERRUPT__)) ? SET : RESET) + +/** @brief Check whether the specified I2C flag is set or not. + * @param __HANDLE__ specifies the I2C Handle. + * @param __FLAG__ specifies the flag to check. + * This parameter can be one of the following values: + * @arg @ref I2C_FLAG_TXE Transmit data register empty + * @arg @ref I2C_FLAG_TXIS Transmit interrupt status + * @arg @ref I2C_FLAG_RXNE Receive data register not empty + * @arg @ref I2C_FLAG_ADDR Address matched (slave mode) + * @arg @ref I2C_FLAG_AF Acknowledge failure received flag + * @arg @ref I2C_FLAG_STOPF STOP detection flag + * @arg @ref I2C_FLAG_TC Transfer complete (master mode) + * @arg @ref I2C_FLAG_TCR Transfer complete reload + * @arg @ref I2C_FLAG_BERR Bus error + * @arg @ref I2C_FLAG_ARLO Arbitration lost + * @arg @ref I2C_FLAG_OVR Overrun/Underrun + * @arg @ref I2C_FLAG_PECERR PEC error in reception + * @arg @ref I2C_FLAG_TIMEOUT Timeout or Tlow detection flag + * @arg @ref I2C_FLAG_ALERT SMBus alert + * @arg @ref I2C_FLAG_BUSY Bus busy + * @arg @ref I2C_FLAG_DIR Transfer direction (slave mode) + * + * @retval The new state of __FLAG__ (SET or RESET). + */ +#define __HAL_I2C_GET_FLAG(__HANDLE__, __FLAG__) (((((__HANDLE__)->Instance->ISR) & (__FLAG__)) == (__FLAG__)) ? SET : RESET) + +/** @brief Clear the I2C pending flags which are cleared by writing 1 in a specific bit. + * @param __HANDLE__ specifies the I2C Handle. + * @param __FLAG__ specifies the flag to clear. + * This parameter can be any combination of the following values: + * @arg @ref I2C_FLAG_TXE Transmit data register empty + * @arg @ref I2C_FLAG_ADDR Address matched (slave mode) + * @arg @ref I2C_FLAG_AF Acknowledge failure received flag + * @arg @ref I2C_FLAG_STOPF STOP detection flag + * @arg @ref I2C_FLAG_BERR Bus error + * @arg @ref I2C_FLAG_ARLO Arbitration lost + * @arg @ref I2C_FLAG_OVR Overrun/Underrun + * @arg @ref I2C_FLAG_PECERR PEC error in reception + * @arg @ref I2C_FLAG_TIMEOUT Timeout or Tlow detection flag + * @arg @ref I2C_FLAG_ALERT SMBus alert + * + * @retval None + */ +#define __HAL_I2C_CLEAR_FLAG(__HANDLE__, __FLAG__) (((__FLAG__) == I2C_FLAG_TXE) ? ((__HANDLE__)->Instance->ISR |= (__FLAG__)) \ + : ((__HANDLE__)->Instance->ICR = (__FLAG__))) + +/** @brief Enable the specified I2C peripheral. + * @param __HANDLE__ specifies the I2C Handle. + * @retval None + */ +#define __HAL_I2C_ENABLE(__HANDLE__) (SET_BIT((__HANDLE__)->Instance->CR1, I2C_CR1_PE)) + +/** @brief Disable the specified I2C peripheral. + * @param __HANDLE__ specifies the I2C Handle. + * @retval None + */ +#define __HAL_I2C_DISABLE(__HANDLE__) (CLEAR_BIT((__HANDLE__)->Instance->CR1, I2C_CR1_PE)) + +/** @brief Generate a Non-Acknowledge I2C peripheral in Slave mode. + * @param __HANDLE__ specifies the I2C Handle. + * @retval None + */ +#define __HAL_I2C_GENERATE_NACK(__HANDLE__) (SET_BIT((__HANDLE__)->Instance->CR2, I2C_CR2_NACK)) +/** + * @} + */ + +/* Include I2C HAL Extended module */ +#include "stm32l4xx_hal_i2c_ex.h" + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup I2C_Exported_Functions + * @{ + */ + +/** @addtogroup I2C_Exported_Functions_Group1 Initialization and de-initialization functions + * @{ + */ +/* Initialization and de-initialization functions******************************/ +HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c); +HAL_StatusTypeDef HAL_I2C_DeInit(I2C_HandleTypeDef *hi2c); +void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c); +void HAL_I2C_MspDeInit(I2C_HandleTypeDef *hi2c); +/** + * @} + */ + +/** @addtogroup I2C_Exported_Functions_Group2 Input and Output operation functions + * @{ + */ +/* IO operation functions ****************************************************/ +/******* Blocking mode: Polling */ +HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_I2C_Slave_Transmit(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_I2C_Slave_Receive(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_I2C_IsDeviceReady(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Trials, uint32_t Timeout); + +/******* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_I2C_Master_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Master_Receive_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Slave_Transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Slave_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Mem_Write_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Mem_Read_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size); + +HAL_StatusTypeDef HAL_I2C_Master_Sequential_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions); +HAL_StatusTypeDef HAL_I2C_Master_Sequential_Receive_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions); +HAL_StatusTypeDef HAL_I2C_Slave_Sequential_Transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions); +HAL_StatusTypeDef HAL_I2C_Slave_Sequential_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions); +HAL_StatusTypeDef HAL_I2C_EnableListen_IT(I2C_HandleTypeDef *hi2c); +HAL_StatusTypeDef HAL_I2C_DisableListen_IT(I2C_HandleTypeDef *hi2c); +HAL_StatusTypeDef HAL_I2C_Master_Abort_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress); + +/******* Non-Blocking mode: DMA */ +HAL_StatusTypeDef HAL_I2C_Master_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Master_Receive_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Slave_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Slave_Receive_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Mem_Write_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Mem_Read_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size); +/** + * @} + */ + +/** @addtogroup I2C_IRQ_Handler_and_Callbacks IRQ Handler and Callbacks + * @{ + */ +/******* I2C IRQHandler and Callbacks used in non blocking modes (Interrupt and DMA) */ +void HAL_I2C_EV_IRQHandler(I2C_HandleTypeDef *hi2c); +void HAL_I2C_ER_IRQHandler(I2C_HandleTypeDef *hi2c); +void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c); +void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c); +void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c); +void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c); +void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode); +void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c); +void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c); +void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c); +void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c); +void HAL_I2C_AbortCpltCallback(I2C_HandleTypeDef *hi2c); +/** + * @} + */ + +/** @addtogroup I2C_Exported_Functions_Group3 Peripheral State, Mode and Error functions + * @{ + */ +/* Peripheral State, Mode and Error functions *********************************/ +HAL_I2C_StateTypeDef HAL_I2C_GetState(I2C_HandleTypeDef *hi2c); +HAL_I2C_ModeTypeDef HAL_I2C_GetMode(I2C_HandleTypeDef *hi2c); +uint32_t HAL_I2C_GetError(I2C_HandleTypeDef *hi2c); + +/** + * @} + */ + +/** + * @} + */ + +/* Private constants ---------------------------------------------------------*/ +/** @defgroup I2C_Private_Constants I2C Private Constants + * @{ + */ + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup I2C_Private_Macro I2C Private Macros + * @{ + */ + +#define IS_I2C_ADDRESSING_MODE(MODE) (((MODE) == I2C_ADDRESSINGMODE_7BIT) || \ + ((MODE) == I2C_ADDRESSINGMODE_10BIT)) + +#define IS_I2C_DUAL_ADDRESS(ADDRESS) (((ADDRESS) == I2C_DUALADDRESS_DISABLE) || \ + ((ADDRESS) == I2C_DUALADDRESS_ENABLE)) + +#define IS_I2C_OWN_ADDRESS2_MASK(MASK) (((MASK) == I2C_OA2_NOMASK) || \ + ((MASK) == I2C_OA2_MASK01) || \ + ((MASK) == I2C_OA2_MASK02) || \ + ((MASK) == I2C_OA2_MASK03) || \ + ((MASK) == I2C_OA2_MASK04) || \ + ((MASK) == I2C_OA2_MASK05) || \ + ((MASK) == I2C_OA2_MASK06) || \ + ((MASK) == I2C_OA2_MASK07)) + +#define IS_I2C_GENERAL_CALL(CALL) (((CALL) == I2C_GENERALCALL_DISABLE) || \ + ((CALL) == I2C_GENERALCALL_ENABLE)) + +#define IS_I2C_NO_STRETCH(STRETCH) (((STRETCH) == I2C_NOSTRETCH_DISABLE) || \ + ((STRETCH) == I2C_NOSTRETCH_ENABLE)) + +#define IS_I2C_MEMADD_SIZE(SIZE) (((SIZE) == I2C_MEMADD_SIZE_8BIT) || \ + ((SIZE) == I2C_MEMADD_SIZE_16BIT)) + +#define IS_TRANSFER_MODE(MODE) (((MODE) == I2C_RELOAD_MODE) || \ + ((MODE) == I2C_AUTOEND_MODE) || \ + ((MODE) == I2C_SOFTEND_MODE)) + +#define IS_TRANSFER_REQUEST(REQUEST) (((REQUEST) == I2C_GENERATE_STOP) || \ + ((REQUEST) == I2C_GENERATE_START_READ) || \ + ((REQUEST) == I2C_GENERATE_START_WRITE) || \ + ((REQUEST) == I2C_NO_STARTSTOP)) + +#define IS_I2C_TRANSFER_OPTIONS_REQUEST(REQUEST) (((REQUEST) == I2C_FIRST_FRAME) || \ + ((REQUEST) == I2C_FIRST_AND_NEXT_FRAME) || \ + ((REQUEST) == I2C_NEXT_FRAME) || \ + ((REQUEST) == I2C_FIRST_AND_LAST_FRAME) || \ + ((REQUEST) == I2C_LAST_FRAME)) + +#define I2C_RESET_CR2(__HANDLE__) ((__HANDLE__)->Instance->CR2 &= (uint32_t)~((uint32_t)(I2C_CR2_SADD | I2C_CR2_HEAD10R | I2C_CR2_NBYTES | I2C_CR2_RELOAD | I2C_CR2_RD_WRN))) + +#define I2C_GET_ADDR_MATCH(__HANDLE__) (((__HANDLE__)->Instance->ISR & I2C_ISR_ADDCODE) >> 16U) +#define I2C_GET_DIR(__HANDLE__) (((__HANDLE__)->Instance->ISR & I2C_ISR_DIR) >> 16U) +#define I2C_GET_STOP_MODE(__HANDLE__) ((__HANDLE__)->Instance->CR2 & I2C_CR2_AUTOEND) +#define I2C_GET_OWN_ADDRESS1(__HANDLE__) ((__HANDLE__)->Instance->OAR1 & I2C_OAR1_OA1) +#define I2C_GET_OWN_ADDRESS2(__HANDLE__) ((__HANDLE__)->Instance->OAR2 & I2C_OAR2_OA2) + +#define IS_I2C_OWN_ADDRESS1(ADDRESS1) ((ADDRESS1) <= 0x000003FFU) +#define IS_I2C_OWN_ADDRESS2(ADDRESS2) ((ADDRESS2) <= (uint16_t)0x00FFU) + +#define I2C_MEM_ADD_MSB(__ADDRESS__) ((uint8_t)((uint16_t)(((uint16_t)((__ADDRESS__) & (uint16_t)(0xFF00U))) >> 8U))) +#define I2C_MEM_ADD_LSB(__ADDRESS__) ((uint8_t)((uint16_t)((__ADDRESS__) & (uint16_t)(0x00FFU)))) + +#define I2C_GENERATE_START(__ADDMODE__,__ADDRESS__) (((__ADDMODE__) == I2C_ADDRESSINGMODE_7BIT) ? (uint32_t)((((uint32_t)(__ADDRESS__) & (I2C_CR2_SADD)) | (I2C_CR2_START) | (I2C_CR2_AUTOEND)) & (~I2C_CR2_RD_WRN)) : \ + (uint32_t)((((uint32_t)(__ADDRESS__) & (I2C_CR2_SADD)) | (I2C_CR2_ADD10) | (I2C_CR2_START)) & (~I2C_CR2_RD_WRN))) +/** + * @} + */ + +/* Private Functions ---------------------------------------------------------*/ +/** @defgroup I2C_Private_Functions I2C Private Functions + * @{ + */ +/* Private functions are defined in stm32l4xx_hal_i2c.c file */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + + +#endif /* __STM32L4xx_HAL_I2C_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_i2c_ex.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_i2c_ex.h new file mode 100644 index 0000000..726a83f --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_i2c_ex.h @@ -0,0 +1,186 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_i2c_ex.h + * @author MCD Application Team + * @brief Header file of I2C HAL Extended module. + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_I2C_EX_H +#define __STM32L4xx_HAL_I2C_EX_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup I2CEx + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/** @defgroup I2CEx_Exported_Constants I2C Extended Exported Constants + * @{ + */ + +/** @defgroup I2CEx_Analog_Filter I2C Extended Analog Filter + * @{ + */ +#define I2C_ANALOGFILTER_ENABLE 0x00000000U +#define I2C_ANALOGFILTER_DISABLE I2C_CR1_ANFOFF +/** + * @} + */ + +/** @defgroup I2CEx_FastModePlus I2C Extended Fast Mode Plus + * @{ + */ +#define I2C_FMP_NOT_SUPPORTED 0xAAAA0000U /*!< Fast Mode Plus not supported */ +#define I2C_FASTMODEPLUS_PB6 SYSCFG_CFGR1_I2C_PB6_FMP /*!< Enable Fast Mode Plus on PB6 */ +#define I2C_FASTMODEPLUS_PB7 SYSCFG_CFGR1_I2C_PB7_FMP /*!< Enable Fast Mode Plus on PB7 */ +#if defined(SYSCFG_CFGR1_I2C_PB8_FMP) +#define I2C_FASTMODEPLUS_PB8 SYSCFG_CFGR1_I2C_PB8_FMP /*!< Enable Fast Mode Plus on PB8 */ +#define I2C_FASTMODEPLUS_PB9 SYSCFG_CFGR1_I2C_PB9_FMP /*!< Enable Fast Mode Plus on PB9 */ +#else +#define I2C_FASTMODEPLUS_PB8 (uint32_t)(0x00000010U | I2C_FMP_NOT_SUPPORTED) /*!< Fast Mode Plus PB8 not supported */ +#define I2C_FASTMODEPLUS_PB9 (uint32_t)(0x00000012U | I2C_FMP_NOT_SUPPORTED) /*!< Fast Mode Plus PB9 not supported */ +#endif +#define I2C_FASTMODEPLUS_I2C1 SYSCFG_CFGR1_I2C1_FMP /*!< Enable Fast Mode Plus on I2C1 pins */ +#if defined(SYSCFG_CFGR1_I2C2_FMP) +#define I2C_FASTMODEPLUS_I2C2 SYSCFG_CFGR1_I2C2_FMP /*!< Enable Fast Mode Plus on I2C2 pins */ +#else +#define I2C_FASTMODEPLUS_I2C2 (uint32_t)(0x00000200U | I2C_FMP_NOT_SUPPORTED) /*!< Fast Mode Plus I2C2 not supported */ +#endif +#define I2C_FASTMODEPLUS_I2C3 SYSCFG_CFGR1_I2C3_FMP /*!< Enable Fast Mode Plus on I2C3 pins */ +#if defined(SYSCFG_CFGR1_I2C4_FMP) +#define I2C_FASTMODEPLUS_I2C4 SYSCFG_CFGR1_I2C4_FMP /*!< Enable Fast Mode Plus on I2C4 pins */ +#else +#define I2C_FASTMODEPLUS_I2C4 (uint32_t)(0x00000800U | I2C_FMP_NOT_SUPPORTED) /*!< Fast Mode Plus I2C4 not supported */ +#endif +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/** @addtogroup I2CEx_Exported_Functions I2C Extended Exported Functions + * @{ + */ + +/** @addtogroup I2CEx_Exported_Functions_Group1 Extended features functions + * @brief Extended features functions + * @{ + */ + +/* Peripheral Control functions ************************************************/ +HAL_StatusTypeDef HAL_I2CEx_ConfigAnalogFilter(I2C_HandleTypeDef *hi2c, uint32_t AnalogFilter); +HAL_StatusTypeDef HAL_I2CEx_ConfigDigitalFilter(I2C_HandleTypeDef *hi2c, uint32_t DigitalFilter); +HAL_StatusTypeDef HAL_I2CEx_EnableWakeUp(I2C_HandleTypeDef *hi2c); +HAL_StatusTypeDef HAL_I2CEx_DisableWakeUp(I2C_HandleTypeDef *hi2c); +void HAL_I2CEx_EnableFastModePlus(uint32_t ConfigFastModePlus); +void HAL_I2CEx_DisableFastModePlus(uint32_t ConfigFastModePlus); + +/* Private constants ---------------------------------------------------------*/ +/** @defgroup I2CEx_Private_Constants I2C Extended Private Constants + * @{ + */ + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup I2CEx_Private_Macro I2C Extended Private Macros + * @{ + */ +#define IS_I2C_ANALOG_FILTER(FILTER) (((FILTER) == I2C_ANALOGFILTER_ENABLE) || \ + ((FILTER) == I2C_ANALOGFILTER_DISABLE)) + +#define IS_I2C_DIGITAL_FILTER(FILTER) ((FILTER) <= 0x0000000FU) + +#define IS_I2C_FASTMODEPLUS(__CONFIG__) ((((__CONFIG__) & I2C_FMP_NOT_SUPPORTED) != I2C_FMP_NOT_SUPPORTED) && \ + ((((__CONFIG__) & (I2C_FASTMODEPLUS_PB6)) == I2C_FASTMODEPLUS_PB6) || \ + (((__CONFIG__) & (I2C_FASTMODEPLUS_PB7)) == I2C_FASTMODEPLUS_PB7) || \ + (((__CONFIG__) & (I2C_FASTMODEPLUS_PB8)) == I2C_FASTMODEPLUS_PB8) || \ + (((__CONFIG__) & (I2C_FASTMODEPLUS_PB9)) == I2C_FASTMODEPLUS_PB9) || \ + (((__CONFIG__) & (I2C_FASTMODEPLUS_I2C1)) == I2C_FASTMODEPLUS_I2C1) || \ + (((__CONFIG__) & (I2C_FASTMODEPLUS_I2C2)) == I2C_FASTMODEPLUS_I2C2) || \ + (((__CONFIG__) & (I2C_FASTMODEPLUS_I2C3)) == I2C_FASTMODEPLUS_I2C3) || \ + (((__CONFIG__) & (I2C_FASTMODEPLUS_I2C4)) == I2C_FASTMODEPLUS_I2C4))) +/** + * @} + */ + +/* Private Functions ---------------------------------------------------------*/ +/** @defgroup I2CEx_Private_Functions I2C Extended Private Functions + * @{ + */ +/* Private functions are defined in stm32l4xx_hal_i2c_ex.c file */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_HAL_I2C_EX_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pcd.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pcd.h new file mode 100644 index 0000000..0fa4476 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pcd.h @@ -0,0 +1,874 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_pcd.h + * @author MCD Application Team + * @brief Header file of PCD HAL module. + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_PCD_H +#define __STM32L4xx_HAL_PCD_H + +#ifdef __cplusplus + extern "C" { +#endif + +#if defined(STM32L432xx) || defined(STM32L433xx) || defined(STM32L442xx) || defined(STM32L443xx) || \ + defined(STM32L452xx) || defined(STM32L462xx) || \ + defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || \ + defined(STM32L496xx) || defined(STM32L4A6xx) || \ + defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_ll_usb.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup PCD + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup PCD_Exported_Types PCD Exported Types + * @{ + */ + + /** + * @brief PCD State structure definition + */ +typedef enum +{ + HAL_PCD_STATE_RESET = 0x00, + HAL_PCD_STATE_READY = 0x01, + HAL_PCD_STATE_ERROR = 0x02, + HAL_PCD_STATE_BUSY = 0x03, + HAL_PCD_STATE_TIMEOUT = 0x04 +} PCD_StateTypeDef; + +/* Device LPM suspend state */ +typedef enum +{ + LPM_L0 = 0x00, /* on */ + LPM_L1 = 0x01, /* LPM L1 sleep */ + LPM_L2 = 0x02, /* suspend */ + LPM_L3 = 0x03, /* off */ +}PCD_LPM_StateTypeDef; + +#if defined (USB) +/** + * @brief PCD double buffered endpoint direction + */ +typedef enum +{ + PCD_EP_DBUF_OUT, + PCD_EP_DBUF_IN, + PCD_EP_DBUF_ERR, +}PCD_EP_DBUF_DIR; + +/** + * @brief PCD endpoint buffer number + */ +typedef enum +{ + PCD_EP_NOBUF, + PCD_EP_BUF0, + PCD_EP_BUF1 +}PCD_EP_BUF_NUM; +#endif /* USB */ + +#if defined (USB_OTG_FS) +typedef USB_OTG_GlobalTypeDef PCD_TypeDef; +typedef USB_OTG_CfgTypeDef PCD_InitTypeDef; +typedef USB_OTG_EPTypeDef PCD_EPTypeDef; +#endif /* USB_OTG_FS */ + +#if defined (USB) +typedef USB_TypeDef PCD_TypeDef; +typedef USB_CfgTypeDef PCD_InitTypeDef; +typedef USB_EPTypeDef PCD_EPTypeDef; +#endif /* USB */ + +/** + * @brief PCD Handle Structure definition + */ +typedef struct +{ + PCD_TypeDef *Instance; /*!< Register base address */ + PCD_InitTypeDef Init; /*!< PCD required parameters */ + __IO uint8_t USB_Address; /*!< USB Address: not used by USB OTG FS */ + PCD_EPTypeDef IN_ep[15]; /*!< IN endpoint parameters */ + PCD_EPTypeDef OUT_ep[15]; /*!< OUT endpoint parameters */ + HAL_LockTypeDef Lock; /*!< PCD peripheral status */ + __IO PCD_StateTypeDef State; /*!< PCD communication state */ + uint32_t Setup[12]; /*!< Setup packet buffer */ + PCD_LPM_StateTypeDef LPM_State; /*!< LPM State */ + uint32_t BESL; + + + uint32_t lpm_active; /*!< Enable or disable the Link Power Management . + This parameter can be set to ENABLE or DISABLE */ + + uint32_t battery_charging_active; /*!< Enable or disable Battery charging. + This parameter can be set to ENABLE or DISABLE */ + void *pData; /*!< Pointer to upper stack Handler */ + +} PCD_HandleTypeDef; + +/** + * @} + */ + +/* Include PCD HAL Extended module */ +#include "stm32l4xx_hal_pcd_ex.h" + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup PCD_Exported_Constants PCD Exported Constants + * @{ + */ + +/** @defgroup PCD_Speed PCD Speed + * @{ + */ +#define PCD_SPEED_FULL 1 +/** + * @} + */ + +/** @defgroup PCD_PHY_Module PCD PHY Module + * @{ + */ +#define PCD_PHY_EMBEDDED 1 +/** + * @} + */ + +/** @defgroup PCD_Turnaround_Timeout Turnaround Timeout Value + * @{ + */ +#ifndef USBD_FS_TRDT_VALUE + #define USBD_FS_TRDT_VALUE 5 +#endif /* USBD_FS_TRDT_VALUE */ +/** + * @} + */ + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ +/** @defgroup PCD_Exported_Macros PCD Exported Macros + * @brief macros to handle interrupts and specific clock configurations + * @{ + */ +#if defined (USB_OTG_FS) +#define __HAL_PCD_ENABLE(__HANDLE__) USB_EnableGlobalInt ((__HANDLE__)->Instance) +#define __HAL_PCD_DISABLE(__HANDLE__) USB_DisableGlobalInt ((__HANDLE__)->Instance) + +#define __HAL_PCD_GET_FLAG(__HANDLE__, __INTERRUPT__) ((USB_ReadInterrupts((__HANDLE__)->Instance) & (__INTERRUPT__)) == (__INTERRUPT__)) +#define __HAL_PCD_CLEAR_FLAG(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->GINTSTS) &= (__INTERRUPT__)) +#define __HAL_PCD_IS_INVALID_INTERRUPT(__HANDLE__) (USB_ReadInterrupts((__HANDLE__)->Instance) == 0) + + +#define __HAL_PCD_UNGATE_PHYCLOCK(__HANDLE__) *(__IO uint32_t *)((uint32_t)((__HANDLE__)->Instance) + USB_OTG_PCGCCTL_BASE) &= \ + ~(USB_OTG_PCGCCTL_STOPCLK) + +#define __HAL_PCD_GATE_PHYCLOCK(__HANDLE__) *(__IO uint32_t *)((uint32_t)((__HANDLE__)->Instance) + USB_OTG_PCGCCTL_BASE) |= USB_OTG_PCGCCTL_STOPCLK + +#define __HAL_PCD_IS_PHY_SUSPENDED(__HANDLE__) ((*(__IO uint32_t *)((uint32_t)((__HANDLE__)->Instance) + USB_OTG_PCGCCTL_BASE))&0x10) + +#define __HAL_USB_OTG_FS_WAKEUP_EXTI_ENABLE_IT() EXTI->IMR1 |= USB_OTG_FS_WAKEUP_EXTI_LINE +#define __HAL_USB_OTG_FS_WAKEUP_EXTI_DISABLE_IT() EXTI->IMR1 &= ~(USB_OTG_FS_WAKEUP_EXTI_LINE) +#define __HAL_USB_OTG_FS_WAKEUP_EXTI_GET_FLAG() EXTI->PR1 & (USB_OTG_FS_WAKEUP_EXTI_LINE) +#define __HAL_USB_OTG_FS_WAKEUP_EXTI_CLEAR_FLAG() EXTI->PR1 = USB_OTG_FS_WAKEUP_EXTI_LINE + +#define __HAL_USB_OTG_FS_WAKEUP_EXTI_ENABLE_RISING_EDGE() do {\ + EXTI->FTSR1 &= ~(USB_OTG_FS_WAKEUP_EXTI_LINE);\ + EXTI->RTSR1 |= USB_OTG_FS_WAKEUP_EXTI_LINE;\ + } while(0) + +#define __HAL_USB_OTG_FS_WAKEUP_EXTI_ENABLE_FALLING_EDGE() do {\ + EXTI->FTSR1 |= (USB_OTG_FS_WAKEUP_EXTI_LINE);\ + EXTI->RTSR1 &= ~(USB_OTG_FS_WAKEUP_EXTI_LINE);\ + } while(0) + +#define __HAL_USB_OTG_FS_WAKEUP_EXTI_ENABLE_RISING_FALLING_EDGE() do {\ + EXTI->RTSR1 &= ~(USB_OTG_FS_WAKEUP_EXTI_LINE);\ + EXTI->FTSR1 &= ~(USB_OTG_FS_WAKEUP_EXTI_LINE);\ + EXTI->RTSR1 |= USB_OTG_FS_WAKEUP_EXTI_LINE;\ + EXTI->FTSR1 |= USB_OTG_FS_WAKEUP_EXTI_LINE;\ + } while(0) + +#define __HAL_USB_OTG_FS_WAKEUP_EXTI_GENERATE_SWIT() (EXTI->SWIER1 |= USB_OTG_FS_WAKEUP_EXTI_LINE) + +#endif /* USB_OTG_FS */ + +#if defined (USB) +#define __HAL_PCD_ENABLE(__HANDLE__) USB_EnableGlobalInt ((__HANDLE__)->Instance) +#define __HAL_PCD_DISABLE(__HANDLE__) USB_DisableGlobalInt ((__HANDLE__)->Instance) +#define __HAL_PCD_GET_FLAG(__HANDLE__, __INTERRUPT__) ((USB_ReadInterrupts((__HANDLE__)->Instance) & (__INTERRUPT__)) == (__INTERRUPT__)) +#define __HAL_PCD_CLEAR_FLAG(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->ISTR) &= ~(__INTERRUPT__)) + +#define __HAL_USB_WAKEUP_EXTI_ENABLE_IT() EXTI->IMR1 |= USB_WAKEUP_EXTI_LINE +#define __HAL_USB_WAKEUP_EXTI_DISABLE_IT() EXTI->IMR1 &= ~(USB_WAKEUP_EXTI_LINE) +#define __HAL_USB_WAKEUP_EXTI_GET_FLAG() EXTI->PR1 & (USB_WAKEUP_EXTI_LINE) +#define __HAL_USB_WAKEUP_EXTI_CLEAR_FLAG() EXTI->PR1 = USB_WAKEUP_EXTI_LINE + +#define __HAL_USB_WAKEUP_EXTI_ENABLE_RISING_EDGE() do {\ + EXTI->FTSR1 &= ~(USB_WAKEUP_EXTI_LINE);\ + EXTI->RTSR1 |= USB_WAKEUP_EXTI_LINE;\ + } while(0) + +#define __HAL_USB_WAKEUP_EXTI_ENABLE_FALLING_EDGE() do {\ + EXTI->FTSR1 |= (USB_WAKEUP_EXTI_LINE);\ + EXTI->RTSR1 &= ~(USB_WAKEUP_EXTI_LINE);\ + } while(0) + +#define __HAL_USB_WAKEUP_EXTI_ENABLE_RISING_FALLING_EDGE() do {\ + EXTI->RTSR1 &= ~(USB_WAKEUP_EXTI_LINE);\ + EXTI->FTSR1 &= ~(USB_WAKEUP_EXTI_LINE);\ + EXTI->RTSR1 |= USB_WAKEUP_EXTI_LINE;\ + EXTI->FTSR1 |= USB_WAKEUP_EXTI_LINE;\ + } while(0) + +#define __HAL_USB_WAKEUP_EXTI_GENERATE_SWIT() (EXTI->SWIER1 |= USB_WAKEUP_EXTI_LINE) + +#endif /* USB */ + +/** + * @} + */ + +/** @addtogroup PCD_Exported_Functions PCD Exported Functions + * @{ + */ + +/* Initialization/de-initialization functions ********************************/ +/** @addtogroup PCD_Exported_Functions_Group1 Initialization and de-initialization functions + * @{ + */ +HAL_StatusTypeDef HAL_PCD_Init(PCD_HandleTypeDef *hpcd); +HAL_StatusTypeDef HAL_PCD_DeInit (PCD_HandleTypeDef *hpcd); +void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd); +void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd); +/** + * @} + */ + +/* I/O operation functions ***************************************************/ +/* Non-Blocking mode: Interrupt */ +/** @addtogroup PCD_Exported_Functions_Group2 Input and Output operation functions + * @{ + */ + /* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_PCD_Start(PCD_HandleTypeDef *hpcd); +HAL_StatusTypeDef HAL_PCD_Stop(PCD_HandleTypeDef *hpcd); +void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd); + +void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum); +void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum); +void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd); +void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd); +void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd); +void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd); +void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd); +void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum); +void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum); +void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd); +void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd); +/** + * @} + */ + +/* Peripheral Control functions **********************************************/ +/** @addtogroup PCD_Exported_Functions_Group3 Peripheral Control functions + * @{ + */ +HAL_StatusTypeDef HAL_PCD_DevConnect(PCD_HandleTypeDef *hpcd); +HAL_StatusTypeDef HAL_PCD_DevDisconnect(PCD_HandleTypeDef *hpcd); +HAL_StatusTypeDef HAL_PCD_SetAddress(PCD_HandleTypeDef *hpcd, uint8_t address); +HAL_StatusTypeDef HAL_PCD_EP_Open(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint16_t ep_mps, uint8_t ep_type); +HAL_StatusTypeDef HAL_PCD_EP_Close(PCD_HandleTypeDef *hpcd, uint8_t ep_addr); +HAL_StatusTypeDef HAL_PCD_EP_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len); +HAL_StatusTypeDef HAL_PCD_EP_Transmit(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len); +uint16_t HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef *hpcd, uint8_t ep_addr); +HAL_StatusTypeDef HAL_PCD_EP_SetStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr); +HAL_StatusTypeDef HAL_PCD_EP_ClrStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr); +HAL_StatusTypeDef HAL_PCD_EP_Flush(PCD_HandleTypeDef *hpcd, uint8_t ep_addr); +HAL_StatusTypeDef HAL_PCD_ActivateRemoteWakeup(PCD_HandleTypeDef *hpcd); +HAL_StatusTypeDef HAL_PCD_DeActivateRemoteWakeup(PCD_HandleTypeDef *hpcd); +/** + * @} + */ + +/* Peripheral State functions ************************************************/ +/** @addtogroup PCD_Exported_Functions_Group4 Peripheral State functions + * @{ + */ +PCD_StateTypeDef HAL_PCD_GetState(PCD_HandleTypeDef *hpcd); +/** + * @} + */ + +/** + * @} + */ + +/* Private constants ---------------------------------------------------------*/ +/** @defgroup PCD_Private_Constants PCD Private Constants + * @{ + */ +/** @defgroup USB_EXTI_Line_Interrupt USB EXTI line interrupt + * @{ + */ +#if defined (USB_OTG_FS) +#define USB_OTG_FS_WAKEUP_EXTI_RISING_EDGE ((uint32_t)0x08) +#define USB_OTG_FS_WAKEUP_EXTI_FALLING_EDGE ((uint32_t)0x0C) +#define USB_OTG_FS_WAKEUP_EXTI_RISING_FALLING_EDGE ((uint32_t)0x10) + +#define USB_OTG_FS_WAKEUP_EXTI_LINE ((uint32_t)0x00020000) /*!< External interrupt line 17 Connected to the USB EXTI Line */ +#endif /* USB_OTG_FS */ + +#if defined (USB) +#define USB_WAKEUP_EXTI_LINE ((uint32_t)0x00020000) /*!< External interrupt line 17Connected to the USB EXTI Line */ +#endif /* USB */ + +/** + * @} + */ + +#if defined (USB) +/** @defgroup PCD_EP0_MPS PCD EP0 MPS + * @{ + */ +#define PCD_EP0MPS_64 DEP0CTL_MPS_64 +#define PCD_EP0MPS_32 DEP0CTL_MPS_32 +#define PCD_EP0MPS_16 DEP0CTL_MPS_16 +#define PCD_EP0MPS_08 DEP0CTL_MPS_8 +/** + * @} + */ + +/** @defgroup PCD_ENDP PCD ENDP + * @{ + */ +#define PCD_ENDP0 ((uint8_t)0) +#define PCD_ENDP1 ((uint8_t)1) +#define PCD_ENDP2 ((uint8_t)2) +#define PCD_ENDP3 ((uint8_t)3) +#define PCD_ENDP4 ((uint8_t)4) +#define PCD_ENDP5 ((uint8_t)5) +#define PCD_ENDP6 ((uint8_t)6) +#define PCD_ENDP7 ((uint8_t)7) +/** + * @} + */ + +/** @defgroup PCD_ENDP_Kind PCD Endpoint Kind + * @{ + */ +#define PCD_SNG_BUF 0 +#define PCD_DBL_BUF 1 +/** + * @} + */ +#endif /* USB */ +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @addtogroup PCD_Private_Macros PCD Private Macros + * @{ + */ +#if defined (USB) +/* SetENDPOINT */ +#define PCD_SET_ENDPOINT(USBx, bEpNum,wRegValue) (*(&(USBx)->EP0R + (bEpNum) * 2)= (uint16_t)(wRegValue)) + +/* GetENDPOINT */ +#define PCD_GET_ENDPOINT(USBx, bEpNum) (*(&(USBx)->EP0R + (bEpNum) * 2)) + +/* ENDPOINT transfer */ +#define USB_EP0StartXfer USB_EPStartXfer + +/** + * @brief sets the type in the endpoint register(bits EP_TYPE[1:0]) + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @param wType: Endpoint Type. + * @retval None + */ +#define PCD_SET_EPTYPE(USBx, bEpNum,wType) (PCD_SET_ENDPOINT((USBx), (bEpNum),\ + ((PCD_GET_ENDPOINT((USBx), (bEpNum)) & USB_EP_T_MASK) | (wType) ))) + +/** + * @brief gets the type in the endpoint register(bits EP_TYPE[1:0]) + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @retval Endpoint Type + */ +#define PCD_GET_EPTYPE(USBx, bEpNum) (PCD_GET_ENDPOINT((USBx), (bEpNum)) & USB_EP_T_FIELD) + +/** + * @brief free buffer used from the application realizing it to the line + toggles bit SW_BUF in the double buffered endpoint register + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @param bDir: Direction + * @retval None + */ +#define PCD_FreeUserBuffer(USBx, bEpNum, bDir)\ +{\ + if ((bDir) == PCD_EP_DBUF_OUT)\ + { /* OUT double buffered endpoint */\ + PCD_TX_DTOG((USBx), (bEpNum));\ + }\ + else if ((bDir) == PCD_EP_DBUF_IN)\ + { /* IN double buffered endpoint */\ + PCD_RX_DTOG((USBx), (bEpNum));\ + }\ +} + +/** + * @brief gets direction of the double buffered endpoint + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @retval EP_DBUF_OUT, EP_DBUF_IN, + * EP_DBUF_ERR if the endpoint counter not yet programmed. + */ +#define PCD_GET_DB_DIR(USBx, bEpNum)\ +{\ + if ((uint16_t)(*PCD_EP_RX_CNT((USBx), (bEpNum)) & 0xFC00) != 0)\ + return(PCD_EP_DBUF_OUT);\ + else if (((uint16_t)(*PCD_EP_TX_CNT((USBx), (bEpNum))) & 0x03FF) != 0)\ + return(PCD_EP_DBUF_IN);\ + else\ + return(PCD_EP_DBUF_ERR);\ +} + +/** + * @brief sets the status for tx transfer (bits STAT_TX[1:0]). + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @param wState: new state + * @retval None + */ +#define PCD_SET_EP_TX_STATUS(USBx, bEpNum, wState) { register uint16_t _wRegVal;\ + \ + _wRegVal = PCD_GET_ENDPOINT((USBx), (bEpNum)) & USB_EPTX_DTOGMASK;\ + /* toggle first bit ? */ \ + if((USB_EPTX_DTOG1 & (wState))!= 0)\ + { \ + _wRegVal ^= USB_EPTX_DTOG1; \ + } \ + /* toggle second bit ? */ \ + if((USB_EPTX_DTOG2 & (wState))!= 0) \ + { \ + _wRegVal ^= USB_EPTX_DTOG2; \ + } \ + PCD_SET_ENDPOINT((USBx), (bEpNum), (_wRegVal | USB_EP_CTR_RX|USB_EP_CTR_TX));\ + } /* PCD_SET_EP_TX_STATUS */ + +/** + * @brief sets the status for rx transfer (bits STAT_TX[1:0]) + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @param wState: new state + * @retval None + */ +#define PCD_SET_EP_RX_STATUS(USBx, bEpNum,wState) {\ + register uint16_t _wRegVal; \ + \ + _wRegVal = PCD_GET_ENDPOINT((USBx), (bEpNum)) & USB_EPRX_DTOGMASK;\ + /* toggle first bit ? */ \ + if((USB_EPRX_DTOG1 & (wState))!= 0) \ + { \ + _wRegVal ^= USB_EPRX_DTOG1; \ + } \ + /* toggle second bit ? */ \ + if((USB_EPRX_DTOG2 & (wState))!= 0) \ + { \ + _wRegVal ^= USB_EPRX_DTOG2; \ + } \ + PCD_SET_ENDPOINT((USBx), (bEpNum), (_wRegVal | USB_EP_CTR_RX|USB_EP_CTR_TX)); \ + } /* PCD_SET_EP_RX_STATUS */ + +/** + * @brief sets the status for rx & tx (bits STAT_TX[1:0] & STAT_RX[1:0]) + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @param wStaterx: new state. + * @param wStatetx: new state. + * @retval None + */ +#define PCD_SET_EP_TXRX_STATUS(USBx,bEpNum,wStaterx,wStatetx) {\ + register uint32_t _wRegVal; \ + \ + _wRegVal = PCD_GET_ENDPOINT((USBx), (bEpNum)) & (USB_EPRX_DTOGMASK |USB_EPTX_STAT) ;\ + /* toggle first bit ? */ \ + if((USB_EPRX_DTOG1 & ((wStaterx)))!= 0) \ + { \ + _wRegVal ^= USB_EPRX_DTOG1; \ + } \ + /* toggle second bit ? */ \ + if((USB_EPRX_DTOG2 & (wStaterx))!= 0) \ + { \ + _wRegVal ^= USB_EPRX_DTOG2; \ + } \ + /* toggle first bit ? */ \ + if((USB_EPTX_DTOG1 & (wStatetx))!= 0) \ + { \ + _wRegVal ^= USB_EPTX_DTOG1; \ + } \ + /* toggle second bit ? */ \ + if((USB_EPTX_DTOG2 & (wStatetx))!= 0) \ + { \ + _wRegVal ^= USB_EPTX_DTOG2; \ + } \ + PCD_SET_ENDPOINT((USBx), (bEpNum), _wRegVal | USB_EP_CTR_RX|USB_EP_CTR_TX); \ + } /* PCD_SET_EP_TXRX_STATUS */ + +/** + * @brief gets the status for tx/rx transfer (bits STAT_TX[1:0] + * /STAT_RX[1:0]) + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @retval status + */ +#define PCD_GET_EP_TX_STATUS(USBx, bEpNum) ((uint16_t)PCD_GET_ENDPOINT((USBx), (bEpNum)) & USB_EPTX_STAT) +#define PCD_GET_EP_RX_STATUS(USBx, bEpNum) ((uint16_t)PCD_GET_ENDPOINT((USBx), (bEpNum)) & USB_EPRX_STAT) + +/** + * @brief sets directly the VALID tx/rx-status into the endpoint register + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @retval None + */ +#define PCD_SET_EP_TX_VALID(USBx, bEpNum) (PCD_SET_EP_TX_STATUS((USBx), (bEpNum), USB_EP_TX_VALID)) +#define PCD_SET_EP_RX_VALID(USBx, bEpNum) (PCD_SET_EP_RX_STATUS((USBx), (bEpNum), USB_EP_RX_VALID)) + +/** + * @brief checks stall condition in an endpoint. + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @retval TRUE = endpoint in stall condition. + */ +#define PCD_GET_EP_TX_STALL_STATUS(USBx, bEpNum) (PCD_GET_EP_TX_STATUS((USBx), (bEpNum)) \ + == USB_EP_TX_STALL) +#define PCD_GET_EP_RX_STALL_STATUS(USBx, bEpNum) (PCD_GET_EP_RX_STATUS((USBx), (bEpNum)) \ + == USB_EP_RX_STALL) + +/** + * @brief set & clear EP_KIND bit. + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @retval None + */ +#define PCD_SET_EP_KIND(USBx, bEpNum) (PCD_SET_ENDPOINT((USBx), (bEpNum), \ + (USB_EP_CTR_RX|USB_EP_CTR_TX|((PCD_GET_ENDPOINT((USBx), (bEpNum)) | USB_EP_KIND) & USB_EPREG_MASK)))) +#define PCD_CLEAR_EP_KIND(USBx, bEpNum) (PCD_SET_ENDPOINT((USBx), (bEpNum), \ + (USB_EP_CTR_RX|USB_EP_CTR_TX|(PCD_GET_ENDPOINT((USBx), (bEpNum)) & USB_EPKIND_MASK)))) + +/** + * @brief Sets/clears directly STATUS_OUT bit in the endpoint register. + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @retval None + */ +#define PCD_SET_OUT_STATUS(USBx, bEpNum) PCD_SET_EP_KIND((USBx), (bEpNum)) +#define PCD_CLEAR_OUT_STATUS(USBx, bEpNum) PCD_CLEAR_EP_KIND((USBx), (bEpNum)) + +/** + * @brief Sets/clears directly EP_KIND bit in the endpoint register. + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @retval None + */ +#define PCD_SET_EP_DBUF(USBx, bEpNum) PCD_SET_EP_KIND((USBx), (bEpNum)) +#define PCD_CLEAR_EP_DBUF(USBx, bEpNum) PCD_CLEAR_EP_KIND((USBx), (bEpNum)) + +/** + * @brief Clears bit CTR_RX / CTR_TX in the endpoint register. + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @retval None + */ +#define PCD_CLEAR_RX_EP_CTR(USBx, bEpNum) (PCD_SET_ENDPOINT((USBx), (bEpNum),\ + PCD_GET_ENDPOINT((USBx), (bEpNum)) & 0x7FFF & USB_EPREG_MASK)) +#define PCD_CLEAR_TX_EP_CTR(USBx, bEpNum) (PCD_SET_ENDPOINT((USBx), (bEpNum),\ + PCD_GET_ENDPOINT((USBx), (bEpNum)) & 0xFF7F & USB_EPREG_MASK)) + +/** + * @brief Toggles DTOG_RX / DTOG_TX bit in the endpoint register. + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @retval None + */ +#define PCD_RX_DTOG(USBx, bEpNum) (PCD_SET_ENDPOINT((USBx), (bEpNum), \ + USB_EP_CTR_RX|USB_EP_CTR_TX|USB_EP_DTOG_RX | (PCD_GET_ENDPOINT((USBx), (bEpNum)) & USB_EPREG_MASK))) +#define PCD_TX_DTOG(USBx, bEpNum) (PCD_SET_ENDPOINT((USBx), (bEpNum), \ + USB_EP_CTR_RX|USB_EP_CTR_TX|USB_EP_DTOG_TX | (PCD_GET_ENDPOINT((USBx), (bEpNum)) & USB_EPREG_MASK))) + +/** + * @brief Clears DTOG_RX / DTOG_TX bit in the endpoint register. + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @retval None + */ +#define PCD_CLEAR_RX_DTOG(USBx, bEpNum) if((PCD_GET_ENDPOINT((USBx), (bEpNum)) & USB_EP_DTOG_RX) != 0)\ + { \ + PCD_RX_DTOG((USBx), (bEpNum)); \ + } +#define PCD_CLEAR_TX_DTOG(USBx, bEpNum) if((PCD_GET_ENDPOINT((USBx), (bEpNum)) & USB_EP_DTOG_TX) != 0)\ + { \ + PCD_TX_DTOG((USBx), (bEpNum)); \ + } + +/** + * @brief Sets address in an endpoint register. + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @param bAddr: Address. + * @retval None + */ +#define PCD_SET_EP_ADDRESS(USBx, bEpNum,bAddr) PCD_SET_ENDPOINT((USBx), (bEpNum),\ + USB_EP_CTR_RX|USB_EP_CTR_TX|(PCD_GET_ENDPOINT((USBx), (bEpNum)) & USB_EPREG_MASK) | (bAddr)) + +#define PCD_GET_EP_ADDRESS(USBx, bEpNum) ((uint8_t)(PCD_GET_ENDPOINT((USBx), (bEpNum)) & USB_EPADDR_FIELD)) + +#define PCD_EP_TX_ADDRESS(USBx, bEpNum) ((uint16_t *)(((USBx)->BTABLE+(bEpNum)*8)+ ((uint32_t)(USBx) + 0x400))) +#define PCD_EP_TX_CNT(USBx, bEpNum) ((uint16_t *)(((USBx)->BTABLE+(bEpNum)*8+2)+ ((uint32_t)(USBx) + 0x400))) +#define PCD_EP_RX_ADDRESS(USBx, bEpNum) ((uint16_t *)(((USBx)->BTABLE+(bEpNum)*8+4)+ ((uint32_t)(USBx) + 0x400))) +#define PCD_EP_RX_CNT(USBx, bEpNum) ((uint16_t *)(((USBx)->BTABLE+(bEpNum)*8+6)+ ((uint32_t)(USBx) + 0x400))) + +#define PCD_SET_EP_RX_CNT(USBx, bEpNum,wCount) {\ + uint16_t *pdwReg = PCD_EP_RX_CNT((USBx), (bEpNum)); \ + PCD_SET_EP_CNT_RX_REG(pdwReg, (wCount));\ + } + +/** + * @brief sets address of the tx/rx buffer. + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @param wAddr: address to be set (must be word aligned). + * @retval None + */ +#define PCD_SET_EP_TX_ADDRESS(USBx, bEpNum,wAddr) (*PCD_EP_TX_ADDRESS((USBx), (bEpNum)) = (((wAddr) >> 1) << 1)) +#define PCD_SET_EP_RX_ADDRESS(USBx, bEpNum,wAddr) (*PCD_EP_RX_ADDRESS((USBx), (bEpNum)) = (((wAddr) >> 1) << 1)) + +/** + * @brief Gets address of the tx/rx buffer. + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @retval address of the buffer. + */ +#define PCD_GET_EP_TX_ADDRESS(USBx, bEpNum) ((uint16_t)*PCD_EP_TX_ADDRESS((USBx), (bEpNum))) +#define PCD_GET_EP_RX_ADDRESS(USBx, bEpNum) ((uint16_t)*PCD_EP_RX_ADDRESS((USBx), (bEpNum))) + +/** + * @brief Sets counter of rx buffer with no. of blocks. + * @param dwReg: Register + * @param wCount: Counter. + * @param wNBlocks: no. of Blocks. + * @retval None + */ +#define PCD_CALC_BLK32(dwReg,wCount,wNBlocks) {\ + (wNBlocks) = (wCount) >> 5;\ + if(((wCount) & 0x1f) == 0)\ + { \ + (wNBlocks)--;\ + } \ + *pdwReg = (uint16_t)((uint16_t)((wNBlocks) << 10) | 0x8000); \ + }/* PCD_CALC_BLK32 */ + +#define PCD_CALC_BLK2(dwReg,wCount,wNBlocks) {\ + (wNBlocks) = (wCount) >> 1;\ + if(((wCount) & 0x1) != 0)\ + { \ + (wNBlocks)++;\ + } \ + *pdwReg = (uint16_t)((wNBlocks) << 10);\ + }/* PCD_CALC_BLK2 */ + +#define PCD_SET_EP_CNT_RX_REG(dwReg,wCount) {\ + uint16_t wNBlocks;\ + if((wCount) > 62) \ + { \ + PCD_CALC_BLK32((dwReg),(wCount),wNBlocks); \ + } \ + else \ + { \ + PCD_CALC_BLK2((dwReg),(wCount),wNBlocks); \ + } \ + }/* PCD_SET_EP_CNT_RX_REG */ + +#define PCD_SET_EP_RX_DBUF0_CNT(USBx, bEpNum,wCount) {\ + uint16_t *pdwReg = PCD_EP_TX_CNT((USBx), (bEpNum)); \ + PCD_SET_EP_CNT_RX_REG(pdwReg, (wCount));\ + } + +/** + * @brief sets counter for the tx/rx buffer. + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @param wCount: Counter value. + * @retval None + */ +#define PCD_SET_EP_TX_CNT(USBx, bEpNum,wCount) (*PCD_EP_TX_CNT((USBx), (bEpNum)) = (wCount)) + + +/** + * @brief gets counter of the tx buffer. + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @retval Counter value + */ +#define PCD_GET_EP_TX_CNT(USBx, bEpNum) ((uint16_t)(*PCD_EP_TX_CNT((USBx), (bEpNum))) & 0x3ff) +#define PCD_GET_EP_RX_CNT(USBx, bEpNum) ((uint16_t)(*PCD_EP_RX_CNT((USBx), (bEpNum))) & 0x3ff) + +/** + * @brief Sets buffer 0/1 address in a double buffer endpoint. + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @param wBuf0Addr: buffer 0 address. + * @retval Counter value + */ +#define PCD_SET_EP_DBUF0_ADDR(USBx, bEpNum,wBuf0Addr) {PCD_SET_EP_TX_ADDRESS((USBx), (bEpNum), (wBuf0Addr));} +#define PCD_SET_EP_DBUF1_ADDR(USBx, bEpNum,wBuf1Addr) {PCD_SET_EP_RX_ADDRESS((USBx), (bEpNum), (wBuf1Addr));} + +/** + * @brief Sets addresses in a double buffer endpoint. + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @param wBuf0Addr: buffer 0 address. + * @param wBuf1Addr = buffer 1 address. + * @retval None + */ +#define PCD_SET_EP_DBUF_ADDR(USBx, bEpNum,wBuf0Addr,wBuf1Addr) { \ + PCD_SET_EP_DBUF0_ADDR((USBx), (bEpNum), (wBuf0Addr));\ + PCD_SET_EP_DBUF1_ADDR((USBx), (bEpNum), (wBuf1Addr));\ + } /* PCD_SET_EP_DBUF_ADDR */ + +/** + * @brief Gets buffer 0/1 address of a double buffer endpoint. + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @retval None + */ +#define PCD_GET_EP_DBUF0_ADDR(USBx, bEpNum) (PCD_GET_EP_TX_ADDRESS((USBx), (bEpNum))) +#define PCD_GET_EP_DBUF1_ADDR(USBx, bEpNum) (PCD_GET_EP_RX_ADDRESS((USBx), (bEpNum))) + +/** + * @brief Gets buffer 0/1 address of a double buffer endpoint. + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @param bDir: endpoint dir EP_DBUF_OUT = OUT + * EP_DBUF_IN = IN + * @param wCount: Counter value + * @retval None + */ +#define PCD_SET_EP_DBUF0_CNT(USBx, bEpNum, bDir, wCount) { \ + if((bDir) == PCD_EP_DBUF_OUT)\ + /* OUT endpoint */ \ + {PCD_SET_EP_RX_DBUF0_CNT((USBx), (bEpNum),(wCount));} \ + else if((bDir) == PCD_EP_DBUF_IN)\ + /* IN endpoint */ \ + *PCD_EP_TX_CNT((USBx), (bEpNum)) = (uint32_t)(wCount); \ + } /* SetEPDblBuf0Count*/ + +#define PCD_SET_EP_DBUF1_CNT(USBx, bEpNum, bDir, wCount) { \ + if((bDir) == PCD_EP_DBUF_OUT)\ + {/* OUT endpoint */ \ + PCD_SET_EP_RX_CNT((USBx), (bEpNum),(wCount)); \ + } \ + else if((bDir) == PCD_EP_DBUF_IN)\ + {/* IN endpoint */ \ + *PCD_EP_TX_CNT((USBx), (bEpNum)) = (uint32_t)(wCount); \ + } \ + } /* SetEPDblBuf1Count */ + +#define PCD_SET_EP_DBUF_CNT(USBx, bEpNum, bDir, wCount) {\ + PCD_SET_EP_DBUF0_CNT((USBx), (bEpNum), (bDir), (wCount)); \ + PCD_SET_EP_DBUF1_CNT((USBx), (bEpNum), (bDir), (wCount)); \ + } /* PCD_SET_EP_DBUF_CNT */ + +/** + * @brief Gets buffer 0/1 rx/tx counter for double buffering. + * @param USBx: USB peripheral instance register address. + * @param bEpNum: Endpoint Number. + * @retval None + */ +#define PCD_GET_EP_DBUF0_CNT(USBx, bEpNum) (PCD_GET_EP_TX_CNT((USBx), (bEpNum))) +#define PCD_GET_EP_DBUF1_CNT(USBx, bEpNum) (PCD_GET_EP_RX_CNT((USBx), (bEpNum))) + +#endif /* USB */ + +#if defined(STM32L432xx) || defined(STM32L433xx) || defined(STM32L442xx) || defined(STM32L443xx) || \ + defined(STM32L452xx) || defined(STM32L462xx) + +/** @defgroup PCD_Instance_definition PCD Instance definition + * @{ + */ +#define IS_PCD_ALL_INSTANCE IS_USB_ALL_INSTANCE +/** + * @} + */ +#endif /* STM32L432xx || STM32L433xx || STM32L442xx || STM32L443xx || */ + /* STM32L452xx || STM32L462xx */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* STM32L432xx || STM32L433xx || STM32L442xx || STM32L443xx || */ + /* STM32L452xx || STM32L462xx || */ + /* STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx || */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#ifdef __cplusplus +} +#endif + + +#endif /* __STM32L4xx_HAL_PCD_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pcd_ex.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pcd_ex.h new file mode 100644 index 0000000..5fce957 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pcd_ex.h @@ -0,0 +1,136 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_pcd_ex.h + * @author MCD Application Team + * @brief Header file of PCD HAL module. + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_PCD_EX_H +#define __STM32L4xx_HAL_PCD_EX_H + +#ifdef __cplusplus + extern "C" { +#endif + +#if defined(STM32L432xx) || defined(STM32L433xx) || defined(STM32L442xx) || defined(STM32L443xx) || \ + defined(STM32L452xx) || defined(STM32L462xx) || \ + defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || \ + defined(STM32L496xx) || defined(STM32L4A6xx) || \ + defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup PCDEx + * @{ + */ +/* Exported types ------------------------------------------------------------*/ +typedef enum +{ + PCD_LPM_L0_ACTIVE = 0x00, /* on */ + PCD_LPM_L1_ACTIVE = 0x01, /* LPM L1 sleep */ +}PCD_LPM_MsgTypeDef; + +typedef enum +{ + PCD_BCD_ERROR = 0xFF, + PCD_BCD_CONTACT_DETECTION = 0xFE, + PCD_BCD_STD_DOWNSTREAM_PORT = 0xFD, + PCD_BCD_CHARGING_DOWNSTREAM_PORT = 0xFC, + PCD_BCD_DEDICATED_CHARGING_PORT = 0xFB, + PCD_BCD_DISCOVERY_COMPLETED = 0x00, + +}PCD_BCD_MsgTypeDef; + +/* Exported constants --------------------------------------------------------*/ +/* Exported macros -----------------------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup PCDEx_Exported_Functions PCDEx Exported Functions + * @{ + */ +/** @addtogroup PCDEx_Exported_Functions_Group1 Peripheral Control functions + * @{ + */ + +#if defined(USB_OTG_FS) +HAL_StatusTypeDef HAL_PCDEx_SetTxFiFo(PCD_HandleTypeDef *hpcd, uint8_t fifo, uint16_t size); +HAL_StatusTypeDef HAL_PCDEx_SetRxFiFo(PCD_HandleTypeDef *hpcd, uint16_t size); +#endif /* USB_OTG_FS */ + +#if defined (USB) +HAL_StatusTypeDef HAL_PCDEx_PMAConfig(PCD_HandleTypeDef *hpcd, + uint16_t ep_addr, + uint16_t ep_kind, + uint32_t pmaadress); +#endif /* USB */ +HAL_StatusTypeDef HAL_PCDEx_ActivateLPM(PCD_HandleTypeDef *hpcd); +HAL_StatusTypeDef HAL_PCDEx_DeActivateLPM(PCD_HandleTypeDef *hpcd); +HAL_StatusTypeDef HAL_PCDEx_ActivateBCD(PCD_HandleTypeDef *hpcd); +HAL_StatusTypeDef HAL_PCDEx_DeActivateBCD(PCD_HandleTypeDef *hpcd); +void HAL_PCDEx_BCD_VBUSDetect(PCD_HandleTypeDef *hpcd); +void HAL_PCDEx_LPM_Callback(PCD_HandleTypeDef *hpcd, PCD_LPM_MsgTypeDef msg); +void HAL_PCDEx_BCD_Callback(PCD_HandleTypeDef *hpcd, PCD_BCD_MsgTypeDef msg); + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* STM32L432xx || STM32L433xx || STM32L442xx || STM32L443xx || */ + /* STM32L452xx || STM32L462xx || */ + /* STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx || */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#ifdef __cplusplus +} +#endif + + +#endif /* __STM32L4xx_HAL_PCD_EX_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pwr.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pwr.h new file mode 100644 index 0000000..75d18b1 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pwr.h @@ -0,0 +1,427 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_pwr.h + * @author MCD Application Team + * @brief Header file of PWR HAL module. + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_PWR_H +#define __STM32L4xx_HAL_PWR_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup PWR + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ + +/** @defgroup PWR_Exported_Types PWR Exported Types + * @{ + */ + +/** + * @brief PWR PVD configuration structure definition + */ +typedef struct +{ + uint32_t PVDLevel; /*!< PVDLevel: Specifies the PVD detection level. + This parameter can be a value of @ref PWR_PVD_detection_level. */ + + uint32_t Mode; /*!< Mode: Specifies the operating mode for the selected pins. + This parameter can be a value of @ref PWR_PVD_Mode. */ +}PWR_PVDTypeDef; + + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ + +/** @defgroup PWR_Exported_Constants PWR Exported Constants + * @{ + */ + + +/** @defgroup PWR_PVD_detection_level Programmable Voltage Detection levels + * @{ + */ +#define PWR_PVDLEVEL_0 PWR_CR2_PLS_LEV0 /*!< PVD threshold around 2.0 V */ +#define PWR_PVDLEVEL_1 PWR_CR2_PLS_LEV1 /*!< PVD threshold around 2.2 V */ +#define PWR_PVDLEVEL_2 PWR_CR2_PLS_LEV2 /*!< PVD threshold around 2.4 V */ +#define PWR_PVDLEVEL_3 PWR_CR2_PLS_LEV3 /*!< PVD threshold around 2.5 V */ +#define PWR_PVDLEVEL_4 PWR_CR2_PLS_LEV4 /*!< PVD threshold around 2.6 V */ +#define PWR_PVDLEVEL_5 PWR_CR2_PLS_LEV5 /*!< PVD threshold around 2.8 V */ +#define PWR_PVDLEVEL_6 PWR_CR2_PLS_LEV6 /*!< PVD threshold around 2.9 V */ +#define PWR_PVDLEVEL_7 PWR_CR2_PLS_LEV7 /*!< External input analog voltage (compared internally to VREFINT) */ +/** + * @} + */ + +/** @defgroup PWR_PVD_Mode PWR PVD interrupt and event mode + * @{ + */ +#define PWR_PVD_MODE_NORMAL ((uint32_t)0x00000000) /*!< Basic mode is used */ +#define PWR_PVD_MODE_IT_RISING ((uint32_t)0x00010001) /*!< External Interrupt Mode with Rising edge trigger detection */ +#define PWR_PVD_MODE_IT_FALLING ((uint32_t)0x00010002) /*!< External Interrupt Mode with Falling edge trigger detection */ +#define PWR_PVD_MODE_IT_RISING_FALLING ((uint32_t)0x00010003) /*!< External Interrupt Mode with Rising/Falling edge trigger detection */ +#define PWR_PVD_MODE_EVENT_RISING ((uint32_t)0x00020001) /*!< Event Mode with Rising edge trigger detection */ +#define PWR_PVD_MODE_EVENT_FALLING ((uint32_t)0x00020002) /*!< Event Mode with Falling edge trigger detection */ +#define PWR_PVD_MODE_EVENT_RISING_FALLING ((uint32_t)0x00020003) /*!< Event Mode with Rising/Falling edge trigger detection */ +/** + * @} + */ + + + + +/** @defgroup PWR_Regulator_state_in_SLEEP_STOP_mode PWR regulator mode + * @{ + */ +#define PWR_MAINREGULATOR_ON ((uint32_t)0x00000000) /*!< Regulator in main mode */ +#define PWR_LOWPOWERREGULATOR_ON PWR_CR1_LPR /*!< Regulator in low-power mode */ +/** + * @} + */ + +/** @defgroup PWR_SLEEP_mode_entry PWR SLEEP mode entry + * @{ + */ +#define PWR_SLEEPENTRY_WFI ((uint8_t)0x01) /*!< Wait For Interruption instruction to enter Sleep mode */ +#define PWR_SLEEPENTRY_WFE ((uint8_t)0x02) /*!< Wait For Event instruction to enter Sleep mode */ +/** + * @} + */ + +/** @defgroup PWR_STOP_mode_entry PWR STOP mode entry + * @{ + */ +#define PWR_STOPENTRY_WFI ((uint8_t)0x01) /*!< Wait For Interruption instruction to enter Stop mode */ +#define PWR_STOPENTRY_WFE ((uint8_t)0x02) /*!< Wait For Event instruction to enter Stop mode */ +/** + * @} + */ + + +/** @defgroup PWR_PVD_EXTI_LINE PWR PVD external interrupt line + * @{ + */ +#define PWR_EXTI_LINE_PVD ((uint32_t)0x00010000) /*!< External interrupt line 16 Connected to the PVD EXTI Line */ +/** + * @} + */ + +/** @defgroup PWR_PVD_EVENT_LINE PWR PVD event line + * @{ + */ +#define PWR_EVENT_LINE_PVD ((uint32_t)0x00010000) /*!< Event line 16 Connected to the PVD Event Line */ +/** + * @} + */ + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ +/** @defgroup PWR_Exported_Macros PWR Exported Macros + * @{ + */ + +/** @brief Check whether or not a specific PWR flag is set. + * @param __FLAG__: specifies the flag to check. + * This parameter can be one of the following values: + * @arg @ref PWR_FLAG_WUF1 Wake Up Flag 1. Indicates that a wakeup event + * was received from the WKUP pin 1. + * @arg @ref PWR_FLAG_WUF2 Wake Up Flag 2. Indicates that a wakeup event + * was received from the WKUP pin 2. + * @arg @ref PWR_FLAG_WUF3 Wake Up Flag 3. Indicates that a wakeup event + * was received from the WKUP pin 3. + * @arg @ref PWR_FLAG_WUF4 Wake Up Flag 4. Indicates that a wakeup event + * was received from the WKUP pin 4. + * @arg @ref PWR_FLAG_WUF5 Wake Up Flag 5. Indicates that a wakeup event + * was received from the WKUP pin 5. + * @arg @ref PWR_FLAG_SB StandBy Flag. Indicates that the system + * entered StandBy mode. + * @arg @ref PWR_FLAG_WUFI Wake-Up Flag Internal. Set when a wakeup is detected on + * the internal wakeup line. + * @arg @ref PWR_FLAG_REGLPS Low Power Regulator Started. Indicates whether or not the + * low-power regulator is ready. + * @arg @ref PWR_FLAG_REGLPF Low Power Regulator Flag. Indicates whether the + * regulator is ready in main mode or is in low-power mode. + * @arg @ref PWR_FLAG_VOSF Voltage Scaling Flag. Indicates whether the regulator is ready + * in the selected voltage range or is still changing to the required voltage level. + * @arg @ref PWR_FLAG_PVDO Power Voltage Detector Output. Indicates whether VDD voltage is + * below or above the selected PVD threshold. + * @arg @ref PWR_FLAG_PVMO1 Peripheral Voltage Monitoring Output 1. Indicates whether VDDUSB voltage is + * is below or above PVM1 threshold (applicable when USB feature is supported). + @if STM32L486xx + * @arg @ref PWR_FLAG_PVMO2 Peripheral Voltage Monitoring Output 2. Indicates whether VDDIO2 voltage is + * is below or above PVM2 threshold (applicable when VDDIO2 is present on device). + @endif + * @arg @ref PWR_FLAG_PVMO3 Peripheral Voltage Monitoring Output 3. Indicates whether VDDA voltage is + * is below or above PVM3 threshold. + * @arg @ref PWR_FLAG_PVMO4 Peripheral Voltage Monitoring Output 4. Indicates whether VDDA voltage is + * is below or above PVM4 threshold. + * + * @retval The new state of __FLAG__ (TRUE or FALSE). + */ +#define __HAL_PWR_GET_FLAG(__FLAG__) ( ((((uint8_t)(__FLAG__)) >> 5U) == 1) ?\ + (PWR->SR1 & (1U << ((__FLAG__) & 31U))) :\ + (PWR->SR2 & (1U << ((__FLAG__) & 31U))) ) + +/** @brief Clear a specific PWR flag. + * @param __FLAG__: specifies the flag to clear. + * This parameter can be one of the following values: + * @arg @ref PWR_FLAG_WUF1 Wake Up Flag 1. Indicates that a wakeup event + * was received from the WKUP pin 1. + * @arg @ref PWR_FLAG_WUF2 Wake Up Flag 2. Indicates that a wakeup event + * was received from the WKUP pin 2. + * @arg @ref PWR_FLAG_WUF3 Wake Up Flag 3. Indicates that a wakeup event + * was received from the WKUP pin 3. + * @arg @ref PWR_FLAG_WUF4 Wake Up Flag 4. Indicates that a wakeup event + * was received from the WKUP pin 4. + * @arg @ref PWR_FLAG_WUF5 Wake Up Flag 5. Indicates that a wakeup event + * was received from the WKUP pin 5. + * @arg @ref PWR_FLAG_WU Encompasses all five Wake Up Flags. + * @arg @ref PWR_FLAG_SB Standby Flag. Indicates that the system + * entered Standby mode. + * @retval None + */ +#define __HAL_PWR_CLEAR_FLAG(__FLAG__) ( (((uint8_t)(__FLAG__)) == PWR_FLAG_WU) ?\ + (PWR->SCR = (__FLAG__)) :\ + (PWR->SCR = (1U << ((__FLAG__) & 31U))) ) +/** + * @brief Enable the PVD Extended Interrupt Line. + * @retval None + */ +#define __HAL_PWR_PVD_EXTI_ENABLE_IT() SET_BIT(EXTI->IMR1, PWR_EXTI_LINE_PVD) + +/** + * @brief Disable the PVD Extended Interrupt Line. + * @retval None + */ +#define __HAL_PWR_PVD_EXTI_DISABLE_IT() CLEAR_BIT(EXTI->IMR1, PWR_EXTI_LINE_PVD) + +/** + * @brief Enable the PVD Event Line. + * @retval None + */ +#define __HAL_PWR_PVD_EXTI_ENABLE_EVENT() SET_BIT(EXTI->EMR1, PWR_EVENT_LINE_PVD) + +/** + * @brief Disable the PVD Event Line. + * @retval None + */ +#define __HAL_PWR_PVD_EXTI_DISABLE_EVENT() CLEAR_BIT(EXTI->EMR1, PWR_EVENT_LINE_PVD) + +/** + * @brief Enable the PVD Extended Interrupt Rising Trigger. + * @retval None + */ +#define __HAL_PWR_PVD_EXTI_ENABLE_RISING_EDGE() SET_BIT(EXTI->RTSR1, PWR_EXTI_LINE_PVD) + +/** + * @brief Disable the PVD Extended Interrupt Rising Trigger. + * @retval None + */ +#define __HAL_PWR_PVD_EXTI_DISABLE_RISING_EDGE() CLEAR_BIT(EXTI->RTSR1, PWR_EXTI_LINE_PVD) + +/** + * @brief Enable the PVD Extended Interrupt Falling Trigger. + * @retval None + */ +#define __HAL_PWR_PVD_EXTI_ENABLE_FALLING_EDGE() SET_BIT(EXTI->FTSR1, PWR_EXTI_LINE_PVD) + + +/** + * @brief Disable the PVD Extended Interrupt Falling Trigger. + * @retval None + */ +#define __HAL_PWR_PVD_EXTI_DISABLE_FALLING_EDGE() CLEAR_BIT(EXTI->FTSR1, PWR_EXTI_LINE_PVD) + + +/** + * @brief Enable the PVD Extended Interrupt Rising & Falling Trigger. + * @retval None + */ +#define __HAL_PWR_PVD_EXTI_ENABLE_RISING_FALLING_EDGE() \ + do { \ + __HAL_PWR_PVD_EXTI_ENABLE_RISING_EDGE(); \ + __HAL_PWR_PVD_EXTI_ENABLE_FALLING_EDGE(); \ + } while(0) + +/** + * @brief Disable the PVD Extended Interrupt Rising & Falling Trigger. + * @retval None + */ +#define __HAL_PWR_PVD_EXTI_DISABLE_RISING_FALLING_EDGE() \ + do { \ + __HAL_PWR_PVD_EXTI_DISABLE_RISING_EDGE(); \ + __HAL_PWR_PVD_EXTI_DISABLE_FALLING_EDGE(); \ + } while(0) + +/** + * @brief Generate a Software interrupt on selected EXTI line. + * @retval None + */ +#define __HAL_PWR_PVD_EXTI_GENERATE_SWIT() SET_BIT(EXTI->SWIER1, PWR_EXTI_LINE_PVD) + +/** + * @brief Check whether or not the PVD EXTI interrupt flag is set. + * @retval EXTI PVD Line Status. + */ +#define __HAL_PWR_PVD_EXTI_GET_FLAG() (EXTI->PR1 & PWR_EXTI_LINE_PVD) + +/** + * @brief Clear the PVD EXTI interrupt flag. + * @retval None + */ +#define __HAL_PWR_PVD_EXTI_CLEAR_FLAG() WRITE_REG(EXTI->PR1, PWR_EXTI_LINE_PVD) + +/** + * @} + */ + + +/* Private macros --------------------------------------------------------*/ +/** @addtogroup PWR_Private_Macros PWR Private Macros + * @{ + */ + +#define IS_PWR_PVD_LEVEL(LEVEL) (((LEVEL) == PWR_PVDLEVEL_0) || ((LEVEL) == PWR_PVDLEVEL_1)|| \ + ((LEVEL) == PWR_PVDLEVEL_2) || ((LEVEL) == PWR_PVDLEVEL_3)|| \ + ((LEVEL) == PWR_PVDLEVEL_4) || ((LEVEL) == PWR_PVDLEVEL_5)|| \ + ((LEVEL) == PWR_PVDLEVEL_6) || ((LEVEL) == PWR_PVDLEVEL_7)) + +#define IS_PWR_PVD_MODE(MODE) (((MODE) == PWR_PVD_MODE_NORMAL) ||\ + ((MODE) == PWR_PVD_MODE_IT_RISING) ||\ + ((MODE) == PWR_PVD_MODE_IT_FALLING) ||\ + ((MODE) == PWR_PVD_MODE_IT_RISING_FALLING) ||\ + ((MODE) == PWR_PVD_MODE_EVENT_RISING) ||\ + ((MODE) == PWR_PVD_MODE_EVENT_FALLING) ||\ + ((MODE) == PWR_PVD_MODE_EVENT_RISING_FALLING)) + +#define IS_PWR_REGULATOR(REGULATOR) (((REGULATOR) == PWR_MAINREGULATOR_ON) || \ + ((REGULATOR) == PWR_LOWPOWERREGULATOR_ON)) + +#define IS_PWR_SLEEP_ENTRY(ENTRY) (((ENTRY) == PWR_SLEEPENTRY_WFI) || ((ENTRY) == PWR_SLEEPENTRY_WFE)) + +#define IS_PWR_STOP_ENTRY(ENTRY) (((ENTRY) == PWR_STOPENTRY_WFI) || ((ENTRY) == PWR_STOPENTRY_WFE) ) + +/** + * @} + */ + +/* Include PWR HAL Extended module */ +#include "stm32l4xx_hal_pwr_ex.h" + +/* Exported functions --------------------------------------------------------*/ + +/** @addtogroup PWR_Exported_Functions PWR Exported Functions + * @{ + */ + +/** @addtogroup PWR_Exported_Functions_Group1 Initialization and de-initialization functions + * @{ + */ + +/* Initialization and de-initialization functions *******************************/ +void HAL_PWR_DeInit(void); +void HAL_PWR_EnableBkUpAccess(void); +void HAL_PWR_DisableBkUpAccess(void); + +/** + * @} + */ + +/** @addtogroup PWR_Exported_Functions_Group2 Peripheral Control functions + * @{ + */ + +/* Peripheral Control functions ************************************************/ +HAL_StatusTypeDef HAL_PWR_ConfigPVD(PWR_PVDTypeDef *sConfigPVD); +void HAL_PWR_EnablePVD(void); +void HAL_PWR_DisablePVD(void); + + +/* WakeUp pins configuration functions ****************************************/ +void HAL_PWR_EnableWakeUpPin(uint32_t WakeUpPinPolarity); +void HAL_PWR_DisableWakeUpPin(uint32_t WakeUpPinx); + +/* Low Power modes configuration functions ************************************/ +void HAL_PWR_EnterSLEEPMode(uint32_t Regulator, uint8_t SLEEPEntry); +void HAL_PWR_EnterSTOPMode(uint32_t Regulator, uint8_t STOPEntry); +void HAL_PWR_EnterSTANDBYMode(void); + +void HAL_PWR_EnableSleepOnExit(void); +void HAL_PWR_DisableSleepOnExit(void); +void HAL_PWR_EnableSEVOnPend(void); +void HAL_PWR_DisableSEVOnPend(void); + +void HAL_PWR_PVDCallback(void); + + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + + +#endif /* __STM32L4xx_HAL_PWR_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pwr_ex.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pwr_ex.h new file mode 100644 index 0000000..b9b9fa5 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_pwr_ex.h @@ -0,0 +1,906 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_pwr_ex.h + * @author MCD Application Team + * @brief Header file of PWR HAL Extended module. + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_PWR_EX_H +#define __STM32L4xx_HAL_PWR_EX_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup PWREx + * @{ + */ + + +/* Exported types ------------------------------------------------------------*/ + +/** @defgroup PWREx_Exported_Types PWR Extended Exported Types + * @{ + */ + + +/** + * @brief PWR PVM configuration structure definition + */ +typedef struct +{ + uint32_t PVMType; /*!< PVMType: Specifies which voltage is monitored and against which threshold. + This parameter can be a value of @ref PWREx_PVM_Type. + @arg @ref PWR_PVM_1 Peripheral Voltage Monitoring 1 enable: VDDUSB versus 1.2 V (applicable when USB feature is supported). +@if STM32L486xx + @arg @ref PWR_PVM_2 Peripheral Voltage Monitoring 2 enable: VDDIO2 versus 0.9 V (applicable when VDDIO2 is present on device). +@endif + @arg @ref PWR_PVM_3 Peripheral Voltage Monitoring 3 enable: VDDA versus 1.62 V. + @arg @ref PWR_PVM_4 Peripheral Voltage Monitoring 4 enable: VDDA versus 2.2 V. */ + + uint32_t Mode; /*!< Mode: Specifies the operating mode for the selected pins. + This parameter can be a value of @ref PWREx_PVM_Mode. */ +}PWR_PVMTypeDef; + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ + +/** @defgroup PWREx_Exported_Constants PWR Extended Exported Constants + * @{ + */ + +/** @defgroup PWREx_WUP_Polarity Shift to apply to retrieve polarity information from PWR_WAKEUP_PINy_xxx constants + * @{ + */ +#define PWR_WUP_POLARITY_SHIFT 0x05 /*!< Internal constant used to retrieve wakeup pin polariry */ +/** + * @} + */ + + +/** @defgroup PWREx_WakeUp_Pins PWR wake-up pins + * @{ + */ +#define PWR_WAKEUP_PIN1 PWR_CR3_EWUP1 /*!< Wakeup pin 1 (with high level polarity) */ +#define PWR_WAKEUP_PIN2 PWR_CR3_EWUP2 /*!< Wakeup pin 2 (with high level polarity) */ +#define PWR_WAKEUP_PIN3 PWR_CR3_EWUP3 /*!< Wakeup pin 3 (with high level polarity) */ +#define PWR_WAKEUP_PIN4 PWR_CR3_EWUP4 /*!< Wakeup pin 4 (with high level polarity) */ +#define PWR_WAKEUP_PIN5 PWR_CR3_EWUP5 /*!< Wakeup pin 5 (with high level polarity) */ +#define PWR_WAKEUP_PIN1_HIGH PWR_CR3_EWUP1 /*!< Wakeup pin 1 (with high level polarity) */ +#define PWR_WAKEUP_PIN2_HIGH PWR_CR3_EWUP2 /*!< Wakeup pin 2 (with high level polarity) */ +#define PWR_WAKEUP_PIN3_HIGH PWR_CR3_EWUP3 /*!< Wakeup pin 3 (with high level polarity) */ +#define PWR_WAKEUP_PIN4_HIGH PWR_CR3_EWUP4 /*!< Wakeup pin 4 (with high level polarity) */ +#define PWR_WAKEUP_PIN5_HIGH PWR_CR3_EWUP5 /*!< Wakeup pin 5 (with high level polarity) */ +#define PWR_WAKEUP_PIN1_LOW (uint32_t)((PWR_CR4_WP1<IMR2, PWR_EXTI_LINE_PVM1) + +/** + * @brief Disable the PVM1 Extended Interrupt Line. + * @retval None + */ +#define __HAL_PWR_PVM1_EXTI_DISABLE_IT() CLEAR_BIT(EXTI->IMR2, PWR_EXTI_LINE_PVM1) + +/** + * @brief Enable the PVM1 Event Line. + * @retval None + */ +#define __HAL_PWR_PVM1_EXTI_ENABLE_EVENT() SET_BIT(EXTI->EMR2, PWR_EVENT_LINE_PVM1) + +/** + * @brief Disable the PVM1 Event Line. + * @retval None + */ +#define __HAL_PWR_PVM1_EXTI_DISABLE_EVENT() CLEAR_BIT(EXTI->EMR2, PWR_EVENT_LINE_PVM1) + +/** + * @brief Enable the PVM1 Extended Interrupt Rising Trigger. + * @retval None + */ +#define __HAL_PWR_PVM1_EXTI_ENABLE_RISING_EDGE() SET_BIT(EXTI->RTSR2, PWR_EXTI_LINE_PVM1) + +/** + * @brief Disable the PVM1 Extended Interrupt Rising Trigger. + * @retval None + */ +#define __HAL_PWR_PVM1_EXTI_DISABLE_RISING_EDGE() CLEAR_BIT(EXTI->RTSR2, PWR_EXTI_LINE_PVM1) + +/** + * @brief Enable the PVM1 Extended Interrupt Falling Trigger. + * @retval None + */ +#define __HAL_PWR_PVM1_EXTI_ENABLE_FALLING_EDGE() SET_BIT(EXTI->FTSR2, PWR_EXTI_LINE_PVM1) + + +/** + * @brief Disable the PVM1 Extended Interrupt Falling Trigger. + * @retval None + */ +#define __HAL_PWR_PVM1_EXTI_DISABLE_FALLING_EDGE() CLEAR_BIT(EXTI->FTSR2, PWR_EXTI_LINE_PVM1) + + +/** + * @brief PVM1 EXTI line configuration: set rising & falling edge trigger. + * @retval None + */ +#define __HAL_PWR_PVM1_EXTI_ENABLE_RISING_FALLING_EDGE() \ + do { \ + __HAL_PWR_PVM1_EXTI_ENABLE_RISING_EDGE(); \ + __HAL_PWR_PVM1_EXTI_ENABLE_FALLING_EDGE(); \ + } while(0) + +/** + * @brief Disable the PVM1 Extended Interrupt Rising & Falling Trigger. + * @retval None + */ +#define __HAL_PWR_PVM1_EXTI_DISABLE_RISING_FALLING_EDGE() \ + do { \ + __HAL_PWR_PVM1_EXTI_DISABLE_RISING_EDGE(); \ + __HAL_PWR_PVM1_EXTI_DISABLE_FALLING_EDGE(); \ + } while(0) + +/** + * @brief Generate a Software interrupt on selected EXTI line. + * @retval None + */ +#define __HAL_PWR_PVM1_EXTI_GENERATE_SWIT() SET_BIT(EXTI->SWIER2, PWR_EXTI_LINE_PVM1) + +/** + * @brief Check whether the specified PVM1 EXTI interrupt flag is set or not. + * @retval EXTI PVM1 Line Status. + */ +#define __HAL_PWR_PVM1_EXTI_GET_FLAG() (EXTI->PR2 & PWR_EXTI_LINE_PVM1) + +/** + * @brief Clear the PVM1 EXTI flag. + * @retval None + */ +#define __HAL_PWR_PVM1_EXTI_CLEAR_FLAG() WRITE_REG(EXTI->PR2, PWR_EXTI_LINE_PVM1) + +#endif /* PWR_CR2_PVME1 */ + + +#if defined(PWR_CR2_PVME2) +/** + * @brief Enable the PVM2 Extended Interrupt Line. + * @retval None + */ +#define __HAL_PWR_PVM2_EXTI_ENABLE_IT() SET_BIT(EXTI->IMR2, PWR_EXTI_LINE_PVM2) + +/** + * @brief Disable the PVM2 Extended Interrupt Line. + * @retval None + */ +#define __HAL_PWR_PVM2_EXTI_DISABLE_IT() CLEAR_BIT(EXTI->IMR2, PWR_EXTI_LINE_PVM2) + +/** + * @brief Enable the PVM2 Event Line. + * @retval None + */ +#define __HAL_PWR_PVM2_EXTI_ENABLE_EVENT() SET_BIT(EXTI->EMR2, PWR_EVENT_LINE_PVM2) + +/** + * @brief Disable the PVM2 Event Line. + * @retval None + */ +#define __HAL_PWR_PVM2_EXTI_DISABLE_EVENT() CLEAR_BIT(EXTI->EMR2, PWR_EVENT_LINE_PVM2) + +/** + * @brief Enable the PVM2 Extended Interrupt Rising Trigger. + * @retval None + */ +#define __HAL_PWR_PVM2_EXTI_ENABLE_RISING_EDGE() SET_BIT(EXTI->RTSR2, PWR_EXTI_LINE_PVM2) + +/** + * @brief Disable the PVM2 Extended Interrupt Rising Trigger. + * @retval None + */ +#define __HAL_PWR_PVM2_EXTI_DISABLE_RISING_EDGE() CLEAR_BIT(EXTI->RTSR2, PWR_EXTI_LINE_PVM2) + +/** + * @brief Enable the PVM2 Extended Interrupt Falling Trigger. + * @retval None + */ +#define __HAL_PWR_PVM2_EXTI_ENABLE_FALLING_EDGE() SET_BIT(EXTI->FTSR2, PWR_EXTI_LINE_PVM2) + + +/** + * @brief Disable the PVM2 Extended Interrupt Falling Trigger. + * @retval None + */ +#define __HAL_PWR_PVM2_EXTI_DISABLE_FALLING_EDGE() CLEAR_BIT(EXTI->FTSR2, PWR_EXTI_LINE_PVM2) + + +/** + * @brief PVM2 EXTI line configuration: set rising & falling edge trigger. + * @retval None + */ +#define __HAL_PWR_PVM2_EXTI_ENABLE_RISING_FALLING_EDGE() \ + do { \ + __HAL_PWR_PVM2_EXTI_ENABLE_RISING_EDGE(); \ + __HAL_PWR_PVM2_EXTI_ENABLE_FALLING_EDGE(); \ + } while(0) + +/** + * @brief Disable the PVM2 Extended Interrupt Rising & Falling Trigger. + * @retval None + */ +#define __HAL_PWR_PVM2_EXTI_DISABLE_RISING_FALLING_EDGE() \ + do { \ + __HAL_PWR_PVM2_EXTI_DISABLE_RISING_EDGE(); \ + __HAL_PWR_PVM2_EXTI_DISABLE_FALLING_EDGE(); \ + } while(0) + +/** + * @brief Generate a Software interrupt on selected EXTI line. + * @retval None + */ +#define __HAL_PWR_PVM2_EXTI_GENERATE_SWIT() SET_BIT(EXTI->SWIER2, PWR_EXTI_LINE_PVM2) + +/** + * @brief Check whether the specified PVM2 EXTI interrupt flag is set or not. + * @retval EXTI PVM2 Line Status. + */ +#define __HAL_PWR_PVM2_EXTI_GET_FLAG() (EXTI->PR2 & PWR_EXTI_LINE_PVM2) + +/** + * @brief Clear the PVM2 EXTI flag. + * @retval None + */ +#define __HAL_PWR_PVM2_EXTI_CLEAR_FLAG() WRITE_REG(EXTI->PR2, PWR_EXTI_LINE_PVM2) + +#endif /* PWR_CR2_PVME2 */ + + +/** + * @brief Enable the PVM3 Extended Interrupt Line. + * @retval None + */ +#define __HAL_PWR_PVM3_EXTI_ENABLE_IT() SET_BIT(EXTI->IMR2, PWR_EXTI_LINE_PVM3) + +/** + * @brief Disable the PVM3 Extended Interrupt Line. + * @retval None + */ +#define __HAL_PWR_PVM3_EXTI_DISABLE_IT() CLEAR_BIT(EXTI->IMR2, PWR_EXTI_LINE_PVM3) + +/** + * @brief Enable the PVM3 Event Line. + * @retval None + */ +#define __HAL_PWR_PVM3_EXTI_ENABLE_EVENT() SET_BIT(EXTI->EMR2, PWR_EVENT_LINE_PVM3) + +/** + * @brief Disable the PVM3 Event Line. + * @retval None + */ +#define __HAL_PWR_PVM3_EXTI_DISABLE_EVENT() CLEAR_BIT(EXTI->EMR2, PWR_EVENT_LINE_PVM3) + +/** + * @brief Enable the PVM3 Extended Interrupt Rising Trigger. + * @retval None + */ +#define __HAL_PWR_PVM3_EXTI_ENABLE_RISING_EDGE() SET_BIT(EXTI->RTSR2, PWR_EXTI_LINE_PVM3) + +/** + * @brief Disable the PVM3 Extended Interrupt Rising Trigger. + * @retval None + */ +#define __HAL_PWR_PVM3_EXTI_DISABLE_RISING_EDGE() CLEAR_BIT(EXTI->RTSR2, PWR_EXTI_LINE_PVM3) + +/** + * @brief Enable the PVM3 Extended Interrupt Falling Trigger. + * @retval None + */ +#define __HAL_PWR_PVM3_EXTI_ENABLE_FALLING_EDGE() SET_BIT(EXTI->FTSR2, PWR_EXTI_LINE_PVM3) + + +/** + * @brief Disable the PVM3 Extended Interrupt Falling Trigger. + * @retval None + */ +#define __HAL_PWR_PVM3_EXTI_DISABLE_FALLING_EDGE() CLEAR_BIT(EXTI->FTSR2, PWR_EXTI_LINE_PVM3) + + +/** + * @brief PVM3 EXTI line configuration: set rising & falling edge trigger. + * @retval None + */ +#define __HAL_PWR_PVM3_EXTI_ENABLE_RISING_FALLING_EDGE() \ + do { \ + __HAL_PWR_PVM3_EXTI_ENABLE_RISING_EDGE(); \ + __HAL_PWR_PVM3_EXTI_ENABLE_FALLING_EDGE(); \ + } while(0) + +/** + * @brief Disable the PVM3 Extended Interrupt Rising & Falling Trigger. + * @retval None + */ +#define __HAL_PWR_PVM3_EXTI_DISABLE_RISING_FALLING_EDGE() \ + do { \ + __HAL_PWR_PVM3_EXTI_DISABLE_RISING_EDGE(); \ + __HAL_PWR_PVM3_EXTI_DISABLE_FALLING_EDGE(); \ + } while(0) + +/** + * @brief Generate a Software interrupt on selected EXTI line. + * @retval None + */ +#define __HAL_PWR_PVM3_EXTI_GENERATE_SWIT() SET_BIT(EXTI->SWIER2, PWR_EXTI_LINE_PVM3) + +/** + * @brief Check whether the specified PVM3 EXTI interrupt flag is set or not. + * @retval EXTI PVM3 Line Status. + */ +#define __HAL_PWR_PVM3_EXTI_GET_FLAG() (EXTI->PR2 & PWR_EXTI_LINE_PVM3) + +/** + * @brief Clear the PVM3 EXTI flag. + * @retval None + */ +#define __HAL_PWR_PVM3_EXTI_CLEAR_FLAG() WRITE_REG(EXTI->PR2, PWR_EXTI_LINE_PVM3) + + + + +/** + * @brief Enable the PVM4 Extended Interrupt Line. + * @retval None + */ +#define __HAL_PWR_PVM4_EXTI_ENABLE_IT() SET_BIT(EXTI->IMR2, PWR_EXTI_LINE_PVM4) + +/** + * @brief Disable the PVM4 Extended Interrupt Line. + * @retval None + */ +#define __HAL_PWR_PVM4_EXTI_DISABLE_IT() CLEAR_BIT(EXTI->IMR2, PWR_EXTI_LINE_PVM4) + +/** + * @brief Enable the PVM4 Event Line. + * @retval None + */ +#define __HAL_PWR_PVM4_EXTI_ENABLE_EVENT() SET_BIT(EXTI->EMR2, PWR_EVENT_LINE_PVM4) + +/** + * @brief Disable the PVM4 Event Line. + * @retval None + */ +#define __HAL_PWR_PVM4_EXTI_DISABLE_EVENT() CLEAR_BIT(EXTI->EMR2, PWR_EVENT_LINE_PVM4) + +/** + * @brief Enable the PVM4 Extended Interrupt Rising Trigger. + * @retval None + */ +#define __HAL_PWR_PVM4_EXTI_ENABLE_RISING_EDGE() SET_BIT(EXTI->RTSR2, PWR_EXTI_LINE_PVM4) + +/** + * @brief Disable the PVM4 Extended Interrupt Rising Trigger. + * @retval None + */ +#define __HAL_PWR_PVM4_EXTI_DISABLE_RISING_EDGE() CLEAR_BIT(EXTI->RTSR2, PWR_EXTI_LINE_PVM4) + +/** + * @brief Enable the PVM4 Extended Interrupt Falling Trigger. + * @retval None + */ +#define __HAL_PWR_PVM4_EXTI_ENABLE_FALLING_EDGE() SET_BIT(EXTI->FTSR2, PWR_EXTI_LINE_PVM4) + + +/** + * @brief Disable the PVM4 Extended Interrupt Falling Trigger. + * @retval None + */ +#define __HAL_PWR_PVM4_EXTI_DISABLE_FALLING_EDGE() CLEAR_BIT(EXTI->FTSR2, PWR_EXTI_LINE_PVM4) + + +/** + * @brief PVM4 EXTI line configuration: set rising & falling edge trigger. + * @retval None + */ +#define __HAL_PWR_PVM4_EXTI_ENABLE_RISING_FALLING_EDGE() \ + do { \ + __HAL_PWR_PVM4_EXTI_ENABLE_RISING_EDGE(); \ + __HAL_PWR_PVM4_EXTI_ENABLE_FALLING_EDGE(); \ + } while(0) + +/** + * @brief Disable the PVM4 Extended Interrupt Rising & Falling Trigger. + * @retval None + */ +#define __HAL_PWR_PVM4_EXTI_DISABLE_RISING_FALLING_EDGE() \ + do { \ + __HAL_PWR_PVM4_EXTI_DISABLE_RISING_EDGE(); \ + __HAL_PWR_PVM4_EXTI_DISABLE_FALLING_EDGE(); \ + } while(0) + +/** + * @brief Generate a Software interrupt on selected EXTI line. + * @retval None + */ +#define __HAL_PWR_PVM4_EXTI_GENERATE_SWIT() SET_BIT(EXTI->SWIER2, PWR_EXTI_LINE_PVM4) + +/** + * @brief Check whether or not the specified PVM4 EXTI interrupt flag is set. + * @retval EXTI PVM4 Line Status. + */ +#define __HAL_PWR_PVM4_EXTI_GET_FLAG() (EXTI->PR2 & PWR_EXTI_LINE_PVM4) + +/** + * @brief Clear the PVM4 EXTI flag. + * @retval None + */ +#define __HAL_PWR_PVM4_EXTI_CLEAR_FLAG() WRITE_REG(EXTI->PR2, PWR_EXTI_LINE_PVM4) + + +/** + * @brief Configure the main internal regulator output voltage. + * @param __REGULATOR__: specifies the regulator output voltage to achieve + * a tradeoff between performance and power consumption. + * This parameter can be one of the following values: + * @arg @ref PWR_REGULATOR_VOLTAGE_SCALE1 Regulator voltage output range 1 mode, + * typical output voltage at 1.2 V, + * system frequency up to 80 MHz. + * @arg @ref PWR_REGULATOR_VOLTAGE_SCALE2 Regulator voltage output range 2 mode, + * typical output voltage at 1.0 V, + * system frequency up to 26 MHz. + * @note This macro is similar to HAL_PWREx_ControlVoltageScaling() API but doesn't check + * whether or not VOSF flag is cleared when moving from range 2 to range 1. User + * may resort to __HAL_PWR_GET_FLAG() macro to check VOSF bit resetting. + * @retval None + */ +#define __HAL_PWR_VOLTAGESCALING_CONFIG(__REGULATOR__) do { \ + __IO uint32_t tmpreg; \ + MODIFY_REG(PWR->CR1, PWR_CR1_VOS, (__REGULATOR__)); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(PWR->CR1, PWR_CR1_VOS); \ + UNUSED(tmpreg); \ + } while(0) + +/** + * @} + */ + +/* Private macros --------------------------------------------------------*/ +/** @addtogroup PWREx_Private_Macros PWR Extended Private Macros + * @{ + */ + +#define IS_PWR_WAKEUP_PIN(PIN) (((PIN) == PWR_WAKEUP_PIN1) || \ + ((PIN) == PWR_WAKEUP_PIN2) || \ + ((PIN) == PWR_WAKEUP_PIN3) || \ + ((PIN) == PWR_WAKEUP_PIN4) || \ + ((PIN) == PWR_WAKEUP_PIN5) || \ + ((PIN) == PWR_WAKEUP_PIN1_HIGH) || \ + ((PIN) == PWR_WAKEUP_PIN2_HIGH) || \ + ((PIN) == PWR_WAKEUP_PIN3_HIGH) || \ + ((PIN) == PWR_WAKEUP_PIN4_HIGH) || \ + ((PIN) == PWR_WAKEUP_PIN5_HIGH) || \ + ((PIN) == PWR_WAKEUP_PIN1_LOW) || \ + ((PIN) == PWR_WAKEUP_PIN2_LOW) || \ + ((PIN) == PWR_WAKEUP_PIN3_LOW) || \ + ((PIN) == PWR_WAKEUP_PIN4_LOW) || \ + ((PIN) == PWR_WAKEUP_PIN5_LOW)) + +#if defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define IS_PWR_PVM_TYPE(TYPE) (((TYPE) == PWR_PVM_1) ||\ + ((TYPE) == PWR_PVM_2) ||\ + ((TYPE) == PWR_PVM_3) ||\ + ((TYPE) == PWR_PVM_4)) +#elif defined (STM32L471xx) +#define IS_PWR_PVM_TYPE(TYPE) (((TYPE) == PWR_PVM_2) ||\ + ((TYPE) == PWR_PVM_3) ||\ + ((TYPE) == PWR_PVM_4)) +#endif + +#if defined (STM32L433xx) || defined (STM32L443xx) || defined (STM32L452xx) || defined (STM32L462xx) +#define IS_PWR_PVM_TYPE(TYPE) (((TYPE) == PWR_PVM_1) ||\ + ((TYPE) == PWR_PVM_3) ||\ + ((TYPE) == PWR_PVM_4)) +#elif defined (STM32L431xx) || defined (STM32L432xx) || defined (STM32L442xx) || defined (STM32L451xx) +#define IS_PWR_PVM_TYPE(TYPE) (((TYPE) == PWR_PVM_3) ||\ + ((TYPE) == PWR_PVM_4)) +#endif + +#define IS_PWR_PVM_MODE(MODE) (((MODE) == PWR_PVM_MODE_NORMAL) ||\ + ((MODE) == PWR_PVM_MODE_IT_RISING) ||\ + ((MODE) == PWR_PVM_MODE_IT_FALLING) ||\ + ((MODE) == PWR_PVM_MODE_IT_RISING_FALLING) ||\ + ((MODE) == PWR_PVM_MODE_EVENT_RISING) ||\ + ((MODE) == PWR_PVM_MODE_EVENT_FALLING) ||\ + ((MODE) == PWR_PVM_MODE_EVENT_RISING_FALLING)) + +#if defined(PWR_CR5_R1MODE) +#define IS_PWR_VOLTAGE_SCALING_RANGE(RANGE) (((RANGE) == PWR_REGULATOR_VOLTAGE_SCALE1_BOOST) || \ + ((RANGE) == PWR_REGULATOR_VOLTAGE_SCALE1) || \ + ((RANGE) == PWR_REGULATOR_VOLTAGE_SCALE2)) +#else +#define IS_PWR_VOLTAGE_SCALING_RANGE(RANGE) (((RANGE) == PWR_REGULATOR_VOLTAGE_SCALE1) || \ + ((RANGE) == PWR_REGULATOR_VOLTAGE_SCALE2)) +#endif + + +#define IS_PWR_BATTERY_RESISTOR_SELECT(RESISTOR) (((RESISTOR) == PWR_BATTERY_CHARGING_RESISTOR_5) ||\ + ((RESISTOR) == PWR_BATTERY_CHARGING_RESISTOR_1_5)) + +#define IS_PWR_BATTERY_CHARGING(CHARGING) (((CHARGING) == PWR_BATTERY_CHARGING_DISABLE) ||\ + ((CHARGING) == PWR_BATTERY_CHARGING_ENABLE)) + +#define IS_PWR_GPIO_BIT_NUMBER(BIT_NUMBER) (((BIT_NUMBER) & GPIO_PIN_MASK) != (uint32_t)0x00) + + +#if defined (STM32L431xx) || defined (STM32L433xx) || defined (STM32L443xx) || \ + defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) +#define IS_PWR_GPIO(GPIO) (((GPIO) == PWR_GPIO_A) ||\ + ((GPIO) == PWR_GPIO_B) ||\ + ((GPIO) == PWR_GPIO_C) ||\ + ((GPIO) == PWR_GPIO_D) ||\ + ((GPIO) == PWR_GPIO_E) ||\ + ((GPIO) == PWR_GPIO_H)) +#elif defined (STM32L432xx) || defined (STM32L442xx) +#define IS_PWR_GPIO(GPIO) (((GPIO) == PWR_GPIO_A) ||\ + ((GPIO) == PWR_GPIO_B) ||\ + ((GPIO) == PWR_GPIO_C) ||\ + ((GPIO) == PWR_GPIO_H)) +#elif defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) +#define IS_PWR_GPIO(GPIO) (((GPIO) == PWR_GPIO_A) ||\ + ((GPIO) == PWR_GPIO_B) ||\ + ((GPIO) == PWR_GPIO_C) ||\ + ((GPIO) == PWR_GPIO_D) ||\ + ((GPIO) == PWR_GPIO_E) ||\ + ((GPIO) == PWR_GPIO_F) ||\ + ((GPIO) == PWR_GPIO_G) ||\ + ((GPIO) == PWR_GPIO_H)) +#elif defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define IS_PWR_GPIO(GPIO) (((GPIO) == PWR_GPIO_A) ||\ + ((GPIO) == PWR_GPIO_B) ||\ + ((GPIO) == PWR_GPIO_C) ||\ + ((GPIO) == PWR_GPIO_D) ||\ + ((GPIO) == PWR_GPIO_E) ||\ + ((GPIO) == PWR_GPIO_F) ||\ + ((GPIO) == PWR_GPIO_G) ||\ + ((GPIO) == PWR_GPIO_H) ||\ + ((GPIO) == PWR_GPIO_I)) +#endif + + +/** + * @} + */ + + +/** @addtogroup PWREx_Exported_Functions PWR Extended Exported Functions + * @{ + */ + +/** @addtogroup PWREx_Exported_Functions_Group1 Extended Peripheral Control functions + * @{ + */ + + +/* Peripheral Control functions **********************************************/ +uint32_t HAL_PWREx_GetVoltageRange(void); +HAL_StatusTypeDef HAL_PWREx_ControlVoltageScaling(uint32_t VoltageScaling); +void HAL_PWREx_EnableBatteryCharging(uint32_t ResistorSelection); +void HAL_PWREx_DisableBatteryCharging(void); +#if defined(PWR_CR2_USV) +void HAL_PWREx_EnableVddUSB(void); +void HAL_PWREx_DisableVddUSB(void); +#endif /* PWR_CR2_USV */ +#if defined(PWR_CR2_IOSV) +void HAL_PWREx_EnableVddIO2(void); +void HAL_PWREx_DisableVddIO2(void); +#endif /* PWR_CR2_IOSV */ +void HAL_PWREx_EnableInternalWakeUpLine(void); +void HAL_PWREx_DisableInternalWakeUpLine(void); +HAL_StatusTypeDef HAL_PWREx_EnableGPIOPullUp(uint32_t GPIO, uint32_t GPIONumber); +HAL_StatusTypeDef HAL_PWREx_DisableGPIOPullUp(uint32_t GPIO, uint32_t GPIONumber); +HAL_StatusTypeDef HAL_PWREx_EnableGPIOPullDown(uint32_t GPIO, uint32_t GPIONumber); +HAL_StatusTypeDef HAL_PWREx_DisableGPIOPullDown(uint32_t GPIO, uint32_t GPIONumber); +void HAL_PWREx_EnablePullUpPullDownConfig(void); +void HAL_PWREx_DisablePullUpPullDownConfig(void); +void HAL_PWREx_EnableSRAM2ContentRetention(void); +void HAL_PWREx_DisableSRAM2ContentRetention(void); +#if defined(PWR_CR1_RRSTP) +void HAL_PWREx_EnableSRAM3ContentRetention(void); +void HAL_PWREx_DisableSRAM3ContentRetention(void); +#endif /* PWR_CR1_RRSTP */ +#if defined(PWR_CR3_DSIPDEN) +void HAL_PWREx_EnableDSIPinsPDActivation(void); +void HAL_PWREx_DisableDSIPinsPDActivation(void); +#endif /* PWR_CR3_DSIPDEN */ +#if defined(PWR_CR2_PVME1) +void HAL_PWREx_EnablePVM1(void); +void HAL_PWREx_DisablePVM1(void); +#endif /* PWR_CR2_PVME1 */ +#if defined(PWR_CR2_PVME2) +void HAL_PWREx_EnablePVM2(void); +void HAL_PWREx_DisablePVM2(void); +#endif /* PWR_CR2_PVME2 */ +void HAL_PWREx_EnablePVM3(void); +void HAL_PWREx_DisablePVM3(void); +void HAL_PWREx_EnablePVM4(void); +void HAL_PWREx_DisablePVM4(void); +HAL_StatusTypeDef HAL_PWREx_ConfigPVM(PWR_PVMTypeDef *sConfigPVM); + + +/* Low Power modes configuration functions ************************************/ +void HAL_PWREx_EnableLowPowerRunMode(void); +HAL_StatusTypeDef HAL_PWREx_DisableLowPowerRunMode(void); +void HAL_PWREx_EnterSTOP0Mode(uint8_t STOPEntry); +void HAL_PWREx_EnterSTOP1Mode(uint8_t STOPEntry); +void HAL_PWREx_EnterSTOP2Mode(uint8_t STOPEntry); +void HAL_PWREx_EnterSHUTDOWNMode(void); + +void HAL_PWREx_PVD_PVM_IRQHandler(void); +#if defined(PWR_CR2_PVME1) +void HAL_PWREx_PVM1Callback(void); +#endif /* PWR_CR2_PVME1 */ +#if defined(PWR_CR2_PVME2) +void HAL_PWREx_PVM2Callback(void); +#endif /* PWR_CR2_PVME2 */ +void HAL_PWREx_PVM3Callback(void); +void HAL_PWREx_PVM4Callback(void); + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + + +#endif /* __STM32L4xx_HAL_PWR_EX_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rcc.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rcc.h new file mode 100644 index 0000000..9c8014c --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rcc.h @@ -0,0 +1,4594 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_rcc.h + * @author MCD Application Team + * @brief Header file of RCC HAL module. + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_RCC_H +#define __STM32L4xx_HAL_RCC_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup RCC + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup RCC_Exported_Types RCC Exported Types + * @{ + */ + +/** + * @brief RCC PLL configuration structure definition + */ +typedef struct +{ + uint32_t PLLState; /*!< The new state of the PLL. + This parameter can be a value of @ref RCC_PLL_Config */ + + uint32_t PLLSource; /*!< RCC_PLLSource: PLL entry clock source. + This parameter must be a value of @ref RCC_PLL_Clock_Source */ + + uint32_t PLLM; /*!< PLLM: Division factor for PLL VCO input clock. + This parameter must be a number between Min_Data = 1 and Max_Data = 16 on STM32L4Rx/STM32L4Sx devices. + This parameter must be a number between Min_Data = 1 and Max_Data = 8 on the other devices */ + + uint32_t PLLN; /*!< PLLN: Multiplication factor for PLL VCO output clock. + This parameter must be a number between Min_Data = 8 and Max_Data = 86 */ + + uint32_t PLLP; /*!< PLLP: Division factor for SAI clock. + This parameter must be a value of @ref RCC_PLLP_Clock_Divider */ + + uint32_t PLLQ; /*!< PLLQ: Division factor for SDMMC1, RNG and USB clocks. + This parameter must be a value of @ref RCC_PLLQ_Clock_Divider */ + + uint32_t PLLR; /*!< PLLR: Division for the main system clock. + User have to set the PLLR parameter correctly to not exceed max frequency 80MHZ. + This parameter must be a value of @ref RCC_PLLR_Clock_Divider */ + +}RCC_PLLInitTypeDef; + +/** + * @brief RCC Internal/External Oscillator (HSE, HSI, MSI, LSE and LSI) configuration structure definition + */ +typedef struct +{ + uint32_t OscillatorType; /*!< The oscillators to be configured. + This parameter can be a value of @ref RCC_Oscillator_Type */ + + uint32_t HSEState; /*!< The new state of the HSE. + This parameter can be a value of @ref RCC_HSE_Config */ + + uint32_t LSEState; /*!< The new state of the LSE. + This parameter can be a value of @ref RCC_LSE_Config */ + + uint32_t HSIState; /*!< The new state of the HSI. + This parameter can be a value of @ref RCC_HSI_Config */ + + uint32_t HSICalibrationValue; /*!< The calibration trimming value (default is RCC_HSICALIBRATION_DEFAULT). + This parameter must be a number between Min_Data = 0x00 and Max_Data = 0x1F on STM32L43x/STM32L44x/STM32L47x/STM32L48x devices. + This parameter must be a number between Min_Data = 0x00 and Max_Data = 0x7F on the other devices */ + + uint32_t LSIState; /*!< The new state of the LSI. + This parameter can be a value of @ref RCC_LSI_Config */ + + uint32_t MSIState; /*!< The new state of the MSI. + This parameter can be a value of @ref RCC_MSI_Config */ + + uint32_t MSICalibrationValue; /*!< The calibration trimming value (default is RCC_MSICALIBRATION_DEFAULT). + This parameter must be a number between Min_Data = 0x00 and Max_Data = 0xFF */ + + uint32_t MSIClockRange; /*!< The MSI frequency range. + This parameter can be a value of @ref RCC_MSI_Clock_Range */ + + uint32_t HSI48State; /*!< The new state of the HSI48 (only applicable to STM32L43x/STM32L44x/STM32L49x/STM32L4Ax devices). + This parameter can be a value of @ref RCC_HSI48_Config */ + + RCC_PLLInitTypeDef PLL; /*!< Main PLL structure parameters */ + +}RCC_OscInitTypeDef; + +/** + * @brief RCC System, AHB and APB busses clock configuration structure definition + */ +typedef struct +{ + uint32_t ClockType; /*!< The clock to be configured. + This parameter can be a value of @ref RCC_System_Clock_Type */ + + uint32_t SYSCLKSource; /*!< The clock source used as system clock (SYSCLK). + This parameter can be a value of @ref RCC_System_Clock_Source */ + + uint32_t AHBCLKDivider; /*!< The AHB clock (HCLK) divider. This clock is derived from the system clock (SYSCLK). + This parameter can be a value of @ref RCC_AHB_Clock_Source */ + + uint32_t APB1CLKDivider; /*!< The APB1 clock (PCLK1) divider. This clock is derived from the AHB clock (HCLK). + This parameter can be a value of @ref RCC_APB1_APB2_Clock_Source */ + + uint32_t APB2CLKDivider; /*!< The APB2 clock (PCLK2) divider. This clock is derived from the AHB clock (HCLK). + This parameter can be a value of @ref RCC_APB1_APB2_Clock_Source */ + +}RCC_ClkInitTypeDef; + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup RCC_Exported_Constants RCC Exported Constants + * @{ + */ + +/** @defgroup RCC_Timeout_Value Timeout Values + * @{ + */ +#define RCC_DBP_TIMEOUT_VALUE 2U /* 2 ms (minimum Tick + 1) */ +#define RCC_LSE_TIMEOUT_VALUE LSE_STARTUP_TIMEOUT +/** + * @} + */ + +/** @defgroup RCC_Oscillator_Type Oscillator Type + * @{ + */ +#define RCC_OSCILLATORTYPE_NONE 0x00000000U /*!< Oscillator configuration unchanged */ +#define RCC_OSCILLATORTYPE_HSE 0x00000001U /*!< HSE to configure */ +#define RCC_OSCILLATORTYPE_HSI 0x00000002U /*!< HSI to configure */ +#define RCC_OSCILLATORTYPE_LSE 0x00000004U /*!< LSE to configure */ +#define RCC_OSCILLATORTYPE_LSI 0x00000008U /*!< LSI to configure */ +#define RCC_OSCILLATORTYPE_MSI 0x00000010U /*!< MSI to configure */ +#if defined(RCC_HSI48_SUPPORT) +#define RCC_OSCILLATORTYPE_HSI48 0x00000020U /*!< HSI48 to configure */ +#endif /* RCC_HSI48_SUPPORT */ +/** + * @} + */ + +/** @defgroup RCC_HSE_Config HSE Config + * @{ + */ +#define RCC_HSE_OFF 0x00000000U /*!< HSE clock deactivation */ +#define RCC_HSE_ON RCC_CR_HSEON /*!< HSE clock activation */ +#define RCC_HSE_BYPASS (RCC_CR_HSEBYP | RCC_CR_HSEON) /*!< External clock source for HSE clock */ +/** + * @} + */ + +/** @defgroup RCC_LSE_Config LSE Config + * @{ + */ +#define RCC_LSE_OFF 0x00000000U /*!< LSE clock deactivation */ +#define RCC_LSE_ON RCC_BDCR_LSEON /*!< LSE clock activation */ +#define RCC_LSE_BYPASS (RCC_BDCR_LSEBYP | RCC_BDCR_LSEON) /*!< External clock source for LSE clock */ +/** + * @} + */ + +/** @defgroup RCC_HSI_Config HSI Config + * @{ + */ +#define RCC_HSI_OFF 0x00000000U /*!< HSI clock deactivation */ +#define RCC_HSI_ON RCC_CR_HSION /*!< HSI clock activation */ + +#if defined(STM32L431xx) || defined(STM32L432xx) || defined(STM32L433xx) || defined(STM32L442xx) || defined(STM32L443xx) || \ + defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) +#define RCC_HSICALIBRATION_DEFAULT 0x10U /* Default HSI calibration trimming value */ +#else +#define RCC_HSICALIBRATION_DEFAULT 0x40U /* Default HSI calibration trimming value */ +#endif /* STM32L431xx || STM32L432xx || STM32L433xx || STM32L442xx || STM32L443xx || */ + /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx */ +/** + * @} + */ + +/** @defgroup RCC_LSI_Config LSI Config + * @{ + */ +#define RCC_LSI_OFF 0x00000000U /*!< LSI clock deactivation */ +#define RCC_LSI_ON RCC_CSR_LSION /*!< LSI clock activation */ +/** + * @} + */ + +/** @defgroup RCC_MSI_Config MSI Config + * @{ + */ +#define RCC_MSI_OFF 0x00000000U /*!< MSI clock deactivation */ +#define RCC_MSI_ON RCC_CR_MSION /*!< MSI clock activation */ + +#define RCC_MSICALIBRATION_DEFAULT 0U /*!< Default MSI calibration trimming value */ +/** + * @} + */ + +#if defined(RCC_HSI48_SUPPORT) +/** @defgroup RCC_HSI48_Config HSI48 Config + * @{ + */ +#define RCC_HSI48_OFF 0x00000000U /*!< HSI48 clock deactivation */ +#define RCC_HSI48_ON RCC_CRRCR_HSI48ON /*!< HSI48 clock activation */ +/** + * @} + */ +#else +/** @defgroup RCC_HSI48_Config HSI48 Config + * @{ + */ +#define RCC_HSI48_OFF 0x00000000U /*!< HSI48 clock deactivation */ +/** + * @} + */ +#endif /* RCC_HSI48_SUPPORT */ + +/** @defgroup RCC_PLL_Config PLL Config + * @{ + */ +#define RCC_PLL_NONE 0x00000000U /*!< PLL configuration unchanged */ +#define RCC_PLL_OFF 0x00000001U /*!< PLL deactivation */ +#define RCC_PLL_ON 0x00000002U /*!< PLL activation */ +/** + * @} + */ + +/** @defgroup RCC_PLLP_Clock_Divider PLLP Clock Divider + * @{ + */ +#if defined(RCC_PLLP_DIV_2_31_SUPPORT) +#define RCC_PLLP_DIV2 0x00000002U /*!< PLLP division factor = 2 */ +#define RCC_PLLP_DIV3 0x00000003U /*!< PLLP division factor = 3 */ +#define RCC_PLLP_DIV4 0x00000004U /*!< PLLP division factor = 4 */ +#define RCC_PLLP_DIV5 0x00000005U /*!< PLLP division factor = 5 */ +#define RCC_PLLP_DIV6 0x00000006U /*!< PLLP division factor = 6 */ +#define RCC_PLLP_DIV7 0x00000007U /*!< PLLP division factor = 7 */ +#define RCC_PLLP_DIV8 0x00000008U /*!< PLLP division factor = 8 */ +#define RCC_PLLP_DIV9 0x00000009U /*!< PLLP division factor = 9 */ +#define RCC_PLLP_DIV10 0x0000000AU /*!< PLLP division factor = 10 */ +#define RCC_PLLP_DIV11 0x0000000BU /*!< PLLP division factor = 11 */ +#define RCC_PLLP_DIV12 0x0000000CU /*!< PLLP division factor = 12 */ +#define RCC_PLLP_DIV13 0x0000000DU /*!< PLLP division factor = 13 */ +#define RCC_PLLP_DIV14 0x0000000EU /*!< PLLP division factor = 14 */ +#define RCC_PLLP_DIV15 0x0000000FU /*!< PLLP division factor = 15 */ +#define RCC_PLLP_DIV16 0x00000010U /*!< PLLP division factor = 16 */ +#define RCC_PLLP_DIV17 0x00000011U /*!< PLLP division factor = 17 */ +#define RCC_PLLP_DIV18 0x00000012U /*!< PLLP division factor = 18 */ +#define RCC_PLLP_DIV19 0x00000013U /*!< PLLP division factor = 19 */ +#define RCC_PLLP_DIV20 0x00000014U /*!< PLLP division factor = 20 */ +#define RCC_PLLP_DIV21 0x00000015U /*!< PLLP division factor = 21 */ +#define RCC_PLLP_DIV22 0x00000016U /*!< PLLP division factor = 22 */ +#define RCC_PLLP_DIV23 0x00000017U /*!< PLLP division factor = 23 */ +#define RCC_PLLP_DIV24 0x00000018U /*!< PLLP division factor = 24 */ +#define RCC_PLLP_DIV25 0x00000019U /*!< PLLP division factor = 25 */ +#define RCC_PLLP_DIV26 0x0000001AU /*!< PLLP division factor = 26 */ +#define RCC_PLLP_DIV27 0x0000001BU /*!< PLLP division factor = 27 */ +#define RCC_PLLP_DIV28 0x0000001CU /*!< PLLP division factor = 28 */ +#define RCC_PLLP_DIV29 0x0000001DU /*!< PLLP division factor = 29 */ +#define RCC_PLLP_DIV30 0x0000001EU /*!< PLLP division factor = 30 */ +#define RCC_PLLP_DIV31 0x0000001FU /*!< PLLP division factor = 31 */ +#else +#define RCC_PLLP_DIV7 0x00000007U /*!< PLLP division factor = 7 */ +#define RCC_PLLP_DIV17 0x00000011U /*!< PLLP division factor = 17 */ +#endif /* RCC_PLLP_DIV_2_31_SUPPORT */ +/** + * @} + */ + +/** @defgroup RCC_PLLQ_Clock_Divider PLLQ Clock Divider + * @{ + */ +#define RCC_PLLQ_DIV2 0x00000002U /*!< PLLQ division factor = 2 */ +#define RCC_PLLQ_DIV4 0x00000004U /*!< PLLQ division factor = 4 */ +#define RCC_PLLQ_DIV6 0x00000006U /*!< PLLQ division factor = 6 */ +#define RCC_PLLQ_DIV8 0x00000008U /*!< PLLQ division factor = 8 */ +/** + * @} + */ + +/** @defgroup RCC_PLLR_Clock_Divider PLLR Clock Divider + * @{ + */ +#define RCC_PLLR_DIV2 0x00000002U /*!< PLLR division factor = 2 */ +#define RCC_PLLR_DIV4 0x00000004U /*!< PLLR division factor = 4 */ +#define RCC_PLLR_DIV6 0x00000006U /*!< PLLR division factor = 6 */ +#define RCC_PLLR_DIV8 0x00000008U /*!< PLLR division factor = 8 */ +/** + * @} + */ + +/** @defgroup RCC_PLL_Clock_Source PLL Clock Source + * @{ + */ +#define RCC_PLLSOURCE_NONE 0x00000000U /*!< No clock selected as PLL entry clock source */ +#define RCC_PLLSOURCE_MSI RCC_PLLCFGR_PLLSRC_MSI /*!< MSI clock selected as PLL entry clock source */ +#define RCC_PLLSOURCE_HSI RCC_PLLCFGR_PLLSRC_HSI /*!< HSI clock selected as PLL entry clock source */ +#define RCC_PLLSOURCE_HSE RCC_PLLCFGR_PLLSRC_HSE /*!< HSE clock selected as PLL entry clock source */ +/** + * @} + */ + +/** @defgroup RCC_PLL_Clock_Output PLL Clock Output + * @{ + */ +#if defined(RCC_PLLSAI2_SUPPORT) +#define RCC_PLL_SAI3CLK RCC_PLLCFGR_PLLPEN /*!< PLLSAI3CLK selection from main PLL (for devices with PLLSAI2) */ +#else +#define RCC_PLL_SAI2CLK RCC_PLLCFGR_PLLPEN /*!< PLLSAI2CLK selection from main PLL (for devices without PLLSAI2) */ +#endif /* RCC_PLLSAI2_SUPPORT */ +#define RCC_PLL_48M1CLK RCC_PLLCFGR_PLLQEN /*!< PLL48M1CLK selection from main PLL */ +#define RCC_PLL_SYSCLK RCC_PLLCFGR_PLLREN /*!< PLLCLK selection from main PLL */ +/** + * @} + */ + +/** @defgroup RCC_PLLSAI1_Clock_Output PLLSAI1 Clock Output + * @{ + */ +#define RCC_PLLSAI1_SAI1CLK RCC_PLLSAI1CFGR_PLLSAI1PEN /*!< PLLSAI1CLK selection from PLLSAI1 */ +#define RCC_PLLSAI1_48M2CLK RCC_PLLSAI1CFGR_PLLSAI1QEN /*!< PLL48M2CLK selection from PLLSAI1 */ +#define RCC_PLLSAI1_ADC1CLK RCC_PLLSAI1CFGR_PLLSAI1REN /*!< PLLADC1CLK selection from PLLSAI1 */ +/** + * @} + */ + +#if defined(RCC_PLLSAI2_SUPPORT) + +/** @defgroup RCC_PLLSAI2_Clock_Output PLLSAI2 Clock Output + * @{ + */ +#define RCC_PLLSAI2_SAI2CLK RCC_PLLSAI2CFGR_PLLSAI2PEN /*!< PLLSAI2CLK selection from PLLSAI2 */ +#if defined(RCC_PLLSAI2Q_DIV_SUPPORT) +#define RCC_PLLSAI2_DSICLK RCC_PLLSAI2CFGR_PLLSAI2QEN /*!< PLLDSICLK selection from PLLSAI2 */ +#endif /* RCC_PLLSAI2Q_DIV_SUPPORT */ +#if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || defined(STM32L496xx) || defined(STM32L4A6xx) +#define RCC_PLLSAI2_ADC2CLK RCC_PLLSAI2CFGR_PLLSAI2REN /*!< PLLADC2CLK selection from PLLSAI2 */ +#else +#define RCC_PLLSAI2_LTDCCLK RCC_PLLSAI2CFGR_PLLSAI2REN /*!< PLLLTDCCLK selection from PLLSAI2 */ +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || STM32L496xx || STM32L4A6xx */ +/** + * @} + */ + +#endif /* RCC_PLLSAI2_SUPPORT */ + +/** @defgroup RCC_MSI_Clock_Range MSI Clock Range + * @{ + */ +#define RCC_MSIRANGE_0 RCC_CR_MSIRANGE_0 /*!< MSI = 100 KHz */ +#define RCC_MSIRANGE_1 RCC_CR_MSIRANGE_1 /*!< MSI = 200 KHz */ +#define RCC_MSIRANGE_2 RCC_CR_MSIRANGE_2 /*!< MSI = 400 KHz */ +#define RCC_MSIRANGE_3 RCC_CR_MSIRANGE_3 /*!< MSI = 800 KHz */ +#define RCC_MSIRANGE_4 RCC_CR_MSIRANGE_4 /*!< MSI = 1 MHz */ +#define RCC_MSIRANGE_5 RCC_CR_MSIRANGE_5 /*!< MSI = 2 MHz */ +#define RCC_MSIRANGE_6 RCC_CR_MSIRANGE_6 /*!< MSI = 4 MHz */ +#define RCC_MSIRANGE_7 RCC_CR_MSIRANGE_7 /*!< MSI = 8 MHz */ +#define RCC_MSIRANGE_8 RCC_CR_MSIRANGE_8 /*!< MSI = 16 MHz */ +#define RCC_MSIRANGE_9 RCC_CR_MSIRANGE_9 /*!< MSI = 24 MHz */ +#define RCC_MSIRANGE_10 RCC_CR_MSIRANGE_10 /*!< MSI = 32 MHz */ +#define RCC_MSIRANGE_11 RCC_CR_MSIRANGE_11 /*!< MSI = 48 MHz */ +/** + * @} + */ + +/** @defgroup RCC_System_Clock_Type System Clock Type + * @{ + */ +#define RCC_CLOCKTYPE_SYSCLK 0x00000001U /*!< SYSCLK to configure */ +#define RCC_CLOCKTYPE_HCLK 0x00000002U /*!< HCLK to configure */ +#define RCC_CLOCKTYPE_PCLK1 0x00000004U /*!< PCLK1 to configure */ +#define RCC_CLOCKTYPE_PCLK2 0x00000008U /*!< PCLK2 to configure */ +/** + * @} + */ + +/** @defgroup RCC_System_Clock_Source System Clock Source + * @{ + */ +#define RCC_SYSCLKSOURCE_MSI RCC_CFGR_SW_MSI /*!< MSI selection as system clock */ +#define RCC_SYSCLKSOURCE_HSI RCC_CFGR_SW_HSI /*!< HSI selection as system clock */ +#define RCC_SYSCLKSOURCE_HSE RCC_CFGR_SW_HSE /*!< HSE selection as system clock */ +#define RCC_SYSCLKSOURCE_PLLCLK RCC_CFGR_SW_PLL /*!< PLL selection as system clock */ +/** + * @} + */ + +/** @defgroup RCC_System_Clock_Source_Status System Clock Source Status + * @{ + */ +#define RCC_SYSCLKSOURCE_STATUS_MSI RCC_CFGR_SWS_MSI /*!< MSI used as system clock */ +#define RCC_SYSCLKSOURCE_STATUS_HSI RCC_CFGR_SWS_HSI /*!< HSI used as system clock */ +#define RCC_SYSCLKSOURCE_STATUS_HSE RCC_CFGR_SWS_HSE /*!< HSE used as system clock */ +#define RCC_SYSCLKSOURCE_STATUS_PLLCLK RCC_CFGR_SWS_PLL /*!< PLL used as system clock */ +/** + * @} + */ + +/** @defgroup RCC_AHB_Clock_Source AHB Clock Source + * @{ + */ +#define RCC_SYSCLK_DIV1 RCC_CFGR_HPRE_DIV1 /*!< SYSCLK not divided */ +#define RCC_SYSCLK_DIV2 RCC_CFGR_HPRE_DIV2 /*!< SYSCLK divided by 2 */ +#define RCC_SYSCLK_DIV4 RCC_CFGR_HPRE_DIV4 /*!< SYSCLK divided by 4 */ +#define RCC_SYSCLK_DIV8 RCC_CFGR_HPRE_DIV8 /*!< SYSCLK divided by 8 */ +#define RCC_SYSCLK_DIV16 RCC_CFGR_HPRE_DIV16 /*!< SYSCLK divided by 16 */ +#define RCC_SYSCLK_DIV64 RCC_CFGR_HPRE_DIV64 /*!< SYSCLK divided by 64 */ +#define RCC_SYSCLK_DIV128 RCC_CFGR_HPRE_DIV128 /*!< SYSCLK divided by 128 */ +#define RCC_SYSCLK_DIV256 RCC_CFGR_HPRE_DIV256 /*!< SYSCLK divided by 256 */ +#define RCC_SYSCLK_DIV512 RCC_CFGR_HPRE_DIV512 /*!< SYSCLK divided by 512 */ +/** + * @} + */ + +/** @defgroup RCC_APB1_APB2_Clock_Source APB1 APB2 Clock Source + * @{ + */ +#define RCC_HCLK_DIV1 RCC_CFGR_PPRE1_DIV1 /*!< HCLK not divided */ +#define RCC_HCLK_DIV2 RCC_CFGR_PPRE1_DIV2 /*!< HCLK divided by 2 */ +#define RCC_HCLK_DIV4 RCC_CFGR_PPRE1_DIV4 /*!< HCLK divided by 4 */ +#define RCC_HCLK_DIV8 RCC_CFGR_PPRE1_DIV8 /*!< HCLK divided by 8 */ +#define RCC_HCLK_DIV16 RCC_CFGR_PPRE1_DIV16 /*!< HCLK divided by 16 */ +/** + * @} + */ + +/** @defgroup RCC_RTC_Clock_Source RTC Clock Source + * @{ + */ +#define RCC_RTCCLKSOURCE_NONE 0x00000000U /*!< No clock used as RTC clock */ +#define RCC_RTCCLKSOURCE_LSE RCC_BDCR_RTCSEL_0 /*!< LSE oscillator clock used as RTC clock */ +#define RCC_RTCCLKSOURCE_LSI RCC_BDCR_RTCSEL_1 /*!< LSI oscillator clock used as RTC clock */ +#define RCC_RTCCLKSOURCE_HSE_DIV32 RCC_BDCR_RTCSEL /*!< HSE oscillator clock divided by 32 used as RTC clock */ +/** + * @} + */ + +/** @defgroup RCC_MCO_Index MCO Index + * @{ + */ +#define RCC_MCO1 0x00000000U +#define RCC_MCO RCC_MCO1 /*!< MCO1 to be compliant with other families with 2 MCOs*/ +/** + * @} + */ + +/** @defgroup RCC_MCO1_Clock_Source MCO1 Clock Source + * @{ + */ +#define RCC_MCO1SOURCE_NOCLOCK 0x00000000U /*!< MCO1 output disabled, no clock on MCO1 */ +#define RCC_MCO1SOURCE_SYSCLK RCC_CFGR_MCOSEL_0 /*!< SYSCLK selection as MCO1 source */ +#define RCC_MCO1SOURCE_MSI RCC_CFGR_MCOSEL_1 /*!< MSI selection as MCO1 source */ +#define RCC_MCO1SOURCE_HSI (RCC_CFGR_MCOSEL_0| RCC_CFGR_MCOSEL_1) /*!< HSI selection as MCO1 source */ +#define RCC_MCO1SOURCE_HSE RCC_CFGR_MCOSEL_2 /*!< HSE selection as MCO1 source */ +#define RCC_MCO1SOURCE_PLLCLK (RCC_CFGR_MCOSEL_0|RCC_CFGR_MCOSEL_2) /*!< PLLCLK selection as MCO1 source */ +#define RCC_MCO1SOURCE_LSI (RCC_CFGR_MCOSEL_1|RCC_CFGR_MCOSEL_2) /*!< LSI selection as MCO1 source */ +#define RCC_MCO1SOURCE_LSE (RCC_CFGR_MCOSEL_0|RCC_CFGR_MCOSEL_1|RCC_CFGR_MCOSEL_2) /*!< LSE selection as MCO1 source */ +#if defined(RCC_HSI48_SUPPORT) +#define RCC_MCO1SOURCE_HSI48 RCC_CFGR_MCOSEL_3 /*!< HSI48 selection as MCO1 source (STM32L43x/STM32L44x devices) */ +#endif /* RCC_HSI48_SUPPORT */ +/** + * @} + */ + +/** @defgroup RCC_MCOx_Clock_Prescaler MCO1 Clock Prescaler + * @{ + */ +#define RCC_MCODIV_1 RCC_CFGR_MCOPRE_DIV1 /*!< MCO not divided */ +#define RCC_MCODIV_2 RCC_CFGR_MCOPRE_DIV2 /*!< MCO divided by 2 */ +#define RCC_MCODIV_4 RCC_CFGR_MCOPRE_DIV4 /*!< MCO divided by 4 */ +#define RCC_MCODIV_8 RCC_CFGR_MCOPRE_DIV8 /*!< MCO divided by 8 */ +#define RCC_MCODIV_16 RCC_CFGR_MCOPRE_DIV16 /*!< MCO divided by 16 */ +/** + * @} + */ + +/** @defgroup RCC_Interrupt Interrupts + * @{ + */ +#define RCC_IT_LSIRDY RCC_CIFR_LSIRDYF /*!< LSI Ready Interrupt flag */ +#define RCC_IT_LSERDY RCC_CIFR_LSERDYF /*!< LSE Ready Interrupt flag */ +#define RCC_IT_MSIRDY RCC_CIFR_MSIRDYF /*!< MSI Ready Interrupt flag */ +#define RCC_IT_HSIRDY RCC_CIFR_HSIRDYF /*!< HSI16 Ready Interrupt flag */ +#define RCC_IT_HSERDY RCC_CIFR_HSERDYF /*!< HSE Ready Interrupt flag */ +#define RCC_IT_PLLRDY RCC_CIFR_PLLRDYF /*!< PLL Ready Interrupt flag */ +#define RCC_IT_PLLSAI1RDY RCC_CIFR_PLLSAI1RDYF /*!< PLLSAI1 Ready Interrupt flag */ +#if defined(RCC_PLLSAI2_SUPPORT) +#define RCC_IT_PLLSAI2RDY RCC_CIFR_PLLSAI2RDYF /*!< PLLSAI2 Ready Interrupt flag */ +#endif /* RCC_PLLSAI2_SUPPORT */ +#define RCC_IT_CSS RCC_CIFR_CSSF /*!< Clock Security System Interrupt flag */ +#define RCC_IT_LSECSS RCC_CIFR_LSECSSF /*!< LSE Clock Security System Interrupt flag */ +#if defined(RCC_HSI48_SUPPORT) +#define RCC_IT_HSI48RDY RCC_CIFR_HSI48RDYF /*!< HSI48 Ready Interrupt flag */ +#endif /* RCC_HSI48_SUPPORT */ +/** + * @} + */ + +/** @defgroup RCC_Flag Flags + * Elements values convention: XXXYYYYYb + * - YYYYY : Flag position in the register + * - XXX : Register index + * - 001: CR register + * - 010: BDCR register + * - 011: CSR register + * - 100: CRRCR register + * @{ + */ +/* Flags in the CR register */ +#define RCC_FLAG_MSIRDY ((CR_REG_INDEX << 5U) | RCC_CR_MSIRDY_Pos) /*!< MSI Ready flag */ +#define RCC_FLAG_HSIRDY ((CR_REG_INDEX << 5U) | RCC_CR_HSIRDY_Pos) /*!< HSI Ready flag */ +#define RCC_FLAG_HSERDY ((CR_REG_INDEX << 5U) | RCC_CR_HSERDY_Pos) /*!< HSE Ready flag */ +#define RCC_FLAG_PLLRDY ((CR_REG_INDEX << 5U) | RCC_CR_PLLRDY_Pos) /*!< PLL Ready flag */ +#define RCC_FLAG_PLLSAI1RDY ((CR_REG_INDEX << 5U) | RCC_CR_PLLSAI1RDY_Pos) /*!< PLLSAI1 Ready flag */ +#if defined(RCC_PLLSAI2_SUPPORT) +#define RCC_FLAG_PLLSAI2RDY ((CR_REG_INDEX << 5U) | RCC_CR_PLLSAI2RDY_Pos) /*!< PLLSAI2 Ready flag */ +#endif /* RCC_PLLSAI2_SUPPORT */ + +/* Flags in the BDCR register */ +#define RCC_FLAG_LSERDY ((BDCR_REG_INDEX << 5U) | RCC_BDCR_LSERDY_Pos) /*!< LSE Ready flag */ +#define RCC_FLAG_LSECSSD ((BDCR_REG_INDEX << 5U) | RCC_BDCR_LSECSSD_Pos) /*!< LSE Clock Security System Interrupt flag */ + +/* Flags in the CSR register */ +#define RCC_FLAG_LSIRDY ((CSR_REG_INDEX << 5U) | RCC_CSR_LSIRDY_Pos) /*!< LSI Ready flag */ +#define RCC_FLAG_RMVF ((CSR_REG_INDEX << 5U) | RCC_CSR_RMVF_Pos) /*!< Remove reset flag */ +#define RCC_FLAG_FWRST ((CSR_REG_INDEX << 5U) | RCC_CSR_FWRSTF_Pos) /*!< Firewall reset flag */ +#define RCC_FLAG_OBLRST ((CSR_REG_INDEX << 5U) | RCC_CSR_OBLRSTF_Pos) /*!< Option Byte Loader reset flag */ +#define RCC_FLAG_PINRST ((CSR_REG_INDEX << 5U) | RCC_CSR_PINRSTF_Pos) /*!< PIN reset flag */ +#define RCC_FLAG_BORRST ((CSR_REG_INDEX << 5U) | RCC_CSR_BORRSTF_Pos) /*!< BOR reset flag */ +#define RCC_FLAG_SFTRST ((CSR_REG_INDEX << 5U) | RCC_CSR_SFTRSTF_Pos) /*!< Software Reset flag */ +#define RCC_FLAG_IWDGRST ((CSR_REG_INDEX << 5U) | RCC_CSR_IWDGRSTF_Pos) /*!< Independent Watchdog reset flag */ +#define RCC_FLAG_WWDGRST ((CSR_REG_INDEX << 5U) | RCC_CSR_WWDGRSTF_Pos) /*!< Window watchdog reset flag */ +#define RCC_FLAG_LPWRRST ((CSR_REG_INDEX << 5U) | RCC_CSR_LPWRRSTF_Pos) /*!< Low-Power reset flag */ + +#if defined(RCC_HSI48_SUPPORT) +/* Flags in the CRRCR register */ +#define RCC_FLAG_HSI48RDY ((CRRCR_REG_INDEX << 5U) | RCC_CRRCR_HSI48RDY_Pos) /*!< HSI48 Ready flag */ +#endif /* RCC_HSI48_SUPPORT */ +/** + * @} + */ + +/** @defgroup RCC_LSEDrive_Config LSE Drive Config + * @{ + */ +#define RCC_LSEDRIVE_LOW 0x00000000U /*!< LSE low drive capability */ +#define RCC_LSEDRIVE_MEDIUMLOW RCC_BDCR_LSEDRV_0 /*!< LSE medium low drive capability */ +#define RCC_LSEDRIVE_MEDIUMHIGH RCC_BDCR_LSEDRV_1 /*!< LSE medium high drive capability */ +#define RCC_LSEDRIVE_HIGH RCC_BDCR_LSEDRV /*!< LSE high drive capability */ +/** + * @} + */ + +/** @defgroup RCC_Stop_WakeUpClock Wake-Up from STOP Clock + * @{ + */ +#define RCC_STOP_WAKEUPCLOCK_MSI 0x00000000U /*!< MSI selection after wake-up from STOP */ +#define RCC_STOP_WAKEUPCLOCK_HSI RCC_CFGR_STOPWUCK /*!< HSI selection after wake-up from STOP */ +/** + * @} + */ + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ + +/** @defgroup RCC_Exported_Macros RCC Exported Macros + * @{ + */ + +/** @defgroup RCC_AHB1_Peripheral_Clock_Enable_Disable AHB1 Peripheral Clock Enable Disable + * @brief Enable or disable the AHB1 peripheral clock. + * @note After reset, the peripheral clock (used for registers read/write access) + * is disabled and the application software has to enable this clock before + * using it. + * @{ + */ + +#define __HAL_RCC_DMA1_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMA1EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMA1EN); \ + UNUSED(tmpreg); \ + } while(0) + +#define __HAL_RCC_DMA2_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMA2EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMA2EN); \ + UNUSED(tmpreg); \ + } while(0) + +#if defined(DMAMUX1) +#define __HAL_RCC_DMAMUX1_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMAMUX1EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMAMUX1EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* DMAMUX1 */ + +#define __HAL_RCC_FLASH_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_FLASHEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_FLASHEN); \ + UNUSED(tmpreg); \ + } while(0) + +#define __HAL_RCC_CRC_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_CRCEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_CRCEN); \ + UNUSED(tmpreg); \ + } while(0) + +#define __HAL_RCC_TSC_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_TSCEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_TSCEN); \ + UNUSED(tmpreg); \ + } while(0) + +#if defined(DMA2D) +#define __HAL_RCC_DMA2D_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMA2DEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMA2DEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* DMA2D */ + +#if defined(GFXMMU) +#define __HAL_RCC_GFXMMU_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GFXMMUEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GFXMMUEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* GFXMMU */ + + +#define __HAL_RCC_DMA1_CLK_DISABLE() CLEAR_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMA1EN) + +#define __HAL_RCC_DMA2_CLK_DISABLE() CLEAR_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMA2EN) + +#if defined(DMAMUX1) +#define __HAL_RCC_DMAMUX1_CLK_DISABLE() CLEAR_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMAMUX1EN) +#endif /* DMAMUX1 */ + +#define __HAL_RCC_FLASH_CLK_DISABLE() CLEAR_BIT(RCC->AHB1ENR, RCC_AHB1ENR_FLASHEN) + +#define __HAL_RCC_CRC_CLK_DISABLE() CLEAR_BIT(RCC->AHB1ENR, RCC_AHB1ENR_CRCEN) + +#define __HAL_RCC_TSC_CLK_DISABLE() CLEAR_BIT(RCC->AHB1ENR, RCC_AHB1ENR_TSCEN) + +#if defined(DMA2D) +#define __HAL_RCC_DMA2D_CLK_DISABLE() CLEAR_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMA2DEN) +#endif /* DMA2D */ + +#if defined(GFXMMU) +#define __HAL_RCC_GFXMMU_CLK_DISABLE() CLEAR_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GFXMMUEN) +#endif /* GFXMMU */ + +/** + * @} + */ + +/** @defgroup RCC_AHB2_Peripheral_Clock_Enable_Disable AHB2 Peripheral Clock Enable Disable + * @brief Enable or disable the AHB2 peripheral clock. + * @note After reset, the peripheral clock (used for registers read/write access) + * is disabled and the application software has to enable this clock before + * using it. + * @{ + */ + +#define __HAL_RCC_GPIOA_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOAEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOAEN); \ + UNUSED(tmpreg); \ + } while(0) + +#define __HAL_RCC_GPIOB_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOBEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOBEN); \ + UNUSED(tmpreg); \ + } while(0) + +#define __HAL_RCC_GPIOC_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOCEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOCEN); \ + UNUSED(tmpreg); \ + } while(0) + +#if defined(GPIOD) +#define __HAL_RCC_GPIOD_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIODEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIODEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* GPIOD */ + +#if defined(GPIOE) +#define __HAL_RCC_GPIOE_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOEEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOEEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* GPIOE */ + +#if defined(GPIOF) +#define __HAL_RCC_GPIOF_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOFEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOFEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* GPIOF */ + +#if defined(GPIOG) +#define __HAL_RCC_GPIOG_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOGEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOGEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* GPIOG */ + +#define __HAL_RCC_GPIOH_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOHEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOHEN); \ + UNUSED(tmpreg); \ + } while(0) + +#if defined(GPIOI) +#define __HAL_RCC_GPIOI_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOIEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOIEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* GPIOI */ + +#if defined(USB_OTG_FS) +#define __HAL_RCC_USB_OTG_FS_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_OTGFSEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_OTGFSEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* USB_OTG_FS */ + +#define __HAL_RCC_ADC_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_ADCEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_ADCEN); \ + UNUSED(tmpreg); \ + } while(0) + +#if defined(DCMI) +#define __HAL_RCC_DCMI_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_DCMIEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_DCMIEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* DCMI */ + +#if defined(AES) +#define __HAL_RCC_AES_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_AESEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_AESEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* AES */ + +#if defined(HASH) +#define __HAL_RCC_HASH_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_HASHEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_HASHEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* HASH */ + +#define __HAL_RCC_RNG_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_RNGEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_RNGEN); \ + UNUSED(tmpreg); \ + } while(0) + +#if defined(OCTOSPIM) +#define __HAL_RCC_OSPIM_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_OSPIMEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_OSPIMEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* OCTOSPIM */ + +#if defined(SDMMC1) && defined(RCC_AHB2ENR_SDMMC1EN) +#define __HAL_RCC_SDMMC1_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_SDMMC1EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_SDMMC1EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* SDMMC1 && RCC_AHB2ENR_SDMMC1EN */ + + +#define __HAL_RCC_GPIOA_CLK_DISABLE() CLEAR_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOAEN) + +#define __HAL_RCC_GPIOB_CLK_DISABLE() CLEAR_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOBEN) + +#define __HAL_RCC_GPIOC_CLK_DISABLE() CLEAR_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOCEN) + +#if defined(GPIOD) +#define __HAL_RCC_GPIOD_CLK_DISABLE() CLEAR_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIODEN) +#endif /* GPIOD */ + +#if defined(GPIOE) +#define __HAL_RCC_GPIOE_CLK_DISABLE() CLEAR_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOEEN) +#endif /* GPIOE */ + +#if defined(GPIOF) +#define __HAL_RCC_GPIOF_CLK_DISABLE() CLEAR_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOFEN) +#endif /* GPIOF */ + +#if defined(GPIOG) +#define __HAL_RCC_GPIOG_CLK_DISABLE() CLEAR_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOGEN) +#endif /* GPIOG */ + +#define __HAL_RCC_GPIOH_CLK_DISABLE() CLEAR_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOHEN) + +#if defined(GPIOI) +#define __HAL_RCC_GPIOI_CLK_DISABLE() CLEAR_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOIEN) +#endif /* GPIOI */ + +#if defined(USB_OTG_FS) +#define __HAL_RCC_USB_OTG_FS_CLK_DISABLE() CLEAR_BIT(RCC->AHB2ENR, RCC_AHB2ENR_OTGFSEN); +#endif /* USB_OTG_FS */ + +#define __HAL_RCC_ADC_CLK_DISABLE() CLEAR_BIT(RCC->AHB2ENR, RCC_AHB2ENR_ADCEN) + +#if defined(DCMI) +#define __HAL_RCC_DCMI_CLK_DISABLE() CLEAR_BIT(RCC->AHB2ENR, RCC_AHB2ENR_DCMIEN) +#endif /* DCMI */ + +#if defined(AES) +#define __HAL_RCC_AES_CLK_DISABLE() CLEAR_BIT(RCC->AHB2ENR, RCC_AHB2ENR_AESEN); +#endif /* AES */ + +#if defined(HASH) +#define __HAL_RCC_HASH_CLK_DISABLE() CLEAR_BIT(RCC->AHB2ENR, RCC_AHB2ENR_HASHEN) +#endif /* HASH */ + +#define __HAL_RCC_RNG_CLK_DISABLE() CLEAR_BIT(RCC->AHB2ENR, RCC_AHB2ENR_RNGEN) + +#if defined(OCTOSPIM) +#define __HAL_RCC_OSPIM_CLK_DISABLE() CLEAR_BIT(RCC->AHB2ENR, RCC_AHB2ENR_OSPIMEN) +#endif /* OCTOSPIM */ + +#if defined(SDMMC1) && defined(RCC_AHB2ENR_SDMMC1EN) +#define __HAL_RCC_SDMMC1_CLK_DISABLE() CLEAR_BIT(RCC->AHB2ENR, RCC_AHB2ENR_SDMMC1EN) +#endif /* SDMMC1 && RCC_AHB2ENR_SDMMC1EN */ + +/** + * @} + */ + +/** @defgroup RCC_AHB3_Clock_Enable_Disable AHB3 Peripheral Clock Enable Disable + * @brief Enable or disable the AHB3 peripheral clock. + * @note After reset, the peripheral clock (used for registers read/write access) + * is disabled and the application software has to enable this clock before + * using it. + * @{ + */ + +#if defined(FMC_BANK1) +#define __HAL_RCC_FMC_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* FMC_BANK1 */ + +#if defined(QUADSPI) +#define __HAL_RCC_QSPI_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB3ENR, RCC_AHB3ENR_QSPIEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_QSPIEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* QUADSPI */ + +#if defined(OCTOSPI1) +#define __HAL_RCC_OSPI1_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB3ENR, RCC_AHB3ENR_OSPI1EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_OSPI1EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* OCTOSPI1 */ + +#if defined(OCTOSPI2) +#define __HAL_RCC_OSPI2_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->AHB3ENR, RCC_AHB3ENR_OSPI2EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_OSPI2EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* OCTOSPI2 */ + +#if defined(FMC_BANK1) +#define __HAL_RCC_FMC_CLK_DISABLE() CLEAR_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN) +#endif /* FMC_BANK1 */ + +#if defined(QUADSPI) +#define __HAL_RCC_QSPI_CLK_DISABLE() CLEAR_BIT(RCC->AHB3ENR, RCC_AHB3ENR_QSPIEN) +#endif /* QUADSPI */ + +#if defined(OCTOSPI1) +#define __HAL_RCC_OSPI1_CLK_DISABLE() CLEAR_BIT(RCC->AHB3ENR, RCC_AHB3ENR_OSPI1EN) +#endif /* OCTOSPI1 */ + +#if defined(OCTOSPI2) +#define __HAL_RCC_OSPI2_CLK_DISABLE() CLEAR_BIT(RCC->AHB3ENR, RCC_AHB3ENR_OSPI2EN) +#endif /* OCTOSPI2 */ + +/** + * @} + */ + +/** @defgroup RCC_APB1_Clock_Enable_Disable APB1 Peripheral Clock Enable Disable + * @brief Enable or disable the APB1 peripheral clock. + * @note After reset, the peripheral clock (used for registers read/write access) + * is disabled and the application software has to enable this clock before + * using it. + * @{ + */ + +#define __HAL_RCC_TIM2_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM2EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM2EN); \ + UNUSED(tmpreg); \ + } while(0) + +#if defined(TIM3) +#define __HAL_RCC_TIM3_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM3EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM3EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* TIM3 */ + +#if defined(TIM4) +#define __HAL_RCC_TIM4_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM4EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM4EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* TIM4 */ + +#if defined(TIM5) +#define __HAL_RCC_TIM5_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM5EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM5EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* TIM5 */ + +#define __HAL_RCC_TIM6_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM6EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM6EN); \ + UNUSED(tmpreg); \ + } while(0) + +#define __HAL_RCC_TIM7_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM7EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM7EN); \ + UNUSED(tmpreg); \ + } while(0) + +#if defined(LCD) +#define __HAL_RCC_LCD_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_LCDEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_LCDEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* LCD */ + +#if defined(RCC_APB1ENR1_RTCAPBEN) +#define __HAL_RCC_RTCAPB_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_RTCAPBEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_RTCAPBEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* RCC_APB1ENR1_RTCAPBEN */ + +#define __HAL_RCC_WWDG_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_WWDGEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_WWDGEN); \ + UNUSED(tmpreg); \ + } while(0) + +#if defined(SPI2) +#define __HAL_RCC_SPI2_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_SPI2EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_SPI2EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* SPI2 */ + +#define __HAL_RCC_SPI3_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_SPI3EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_SPI3EN); \ + UNUSED(tmpreg); \ + } while(0) + +#define __HAL_RCC_USART2_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USART2EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USART2EN); \ + UNUSED(tmpreg); \ + } while(0) + +#if defined(USART3) +#define __HAL_RCC_USART3_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USART3EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USART3EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* USART3 */ + +#if defined(UART4) +#define __HAL_RCC_UART4_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_UART4EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_UART4EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* UART4 */ + +#if defined(UART5) +#define __HAL_RCC_UART5_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_UART5EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_UART5EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* UART5 */ + +#define __HAL_RCC_I2C1_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_I2C1EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_I2C1EN); \ + UNUSED(tmpreg); \ + } while(0) + +#if defined(I2C2) +#define __HAL_RCC_I2C2_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_I2C2EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_I2C2EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* I2C2 */ + +#define __HAL_RCC_I2C3_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_I2C3EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_I2C3EN); \ + UNUSED(tmpreg); \ + } while(0) + +#if defined(I2C4) +#define __HAL_RCC_I2C4_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR2, RCC_APB1ENR2_I2C4EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR2, RCC_APB1ENR2_I2C4EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* I2C4 */ + +#if defined(CRS) +#define __HAL_RCC_CRS_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_CRSEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_CRSEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* CRS */ + +#define __HAL_RCC_CAN1_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_CAN1EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_CAN1EN); \ + UNUSED(tmpreg); \ + } while(0) + +#if defined(CAN2) +#define __HAL_RCC_CAN2_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_CAN2EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_CAN2EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* CAN2 */ + +#if defined(USB) +#define __HAL_RCC_USB_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USBFSEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USBFSEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* USB */ + +#define __HAL_RCC_PWR_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_PWREN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_PWREN); \ + UNUSED(tmpreg); \ + } while(0) + +#define __HAL_RCC_DAC1_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_DAC1EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_DAC1EN); \ + UNUSED(tmpreg); \ + } while(0) + +#define __HAL_RCC_OPAMP_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_OPAMPEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_OPAMPEN); \ + UNUSED(tmpreg); \ + } while(0) + +#define __HAL_RCC_LPTIM1_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_LPTIM1EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_LPTIM1EN); \ + UNUSED(tmpreg); \ + } while(0) + +#define __HAL_RCC_LPUART1_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR2, RCC_APB1ENR2_LPUART1EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR2, RCC_APB1ENR2_LPUART1EN); \ + UNUSED(tmpreg); \ + } while(0) + +#if defined(SWPMI1) +#define __HAL_RCC_SWPMI1_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR2, RCC_APB1ENR2_SWPMI1EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR2, RCC_APB1ENR2_SWPMI1EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* SWPMI1 */ + +#define __HAL_RCC_LPTIM2_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB1ENR2, RCC_APB1ENR2_LPTIM2EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB1ENR2, RCC_APB1ENR2_LPTIM2EN); \ + UNUSED(tmpreg); \ + } while(0) + + +#define __HAL_RCC_TIM2_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM2EN) + +#if defined(TIM3) +#define __HAL_RCC_TIM3_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM3EN) +#endif /* TIM3 */ + +#if defined(TIM4) +#define __HAL_RCC_TIM4_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM4EN) +#endif /* TIM4 */ + +#if defined(TIM5) +#define __HAL_RCC_TIM5_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM5EN) +#endif /* TIM5 */ + +#define __HAL_RCC_TIM6_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM6EN) + +#define __HAL_RCC_TIM7_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM7EN) + +#if defined(LCD) +#define __HAL_RCC_LCD_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_LCDEN); +#endif /* LCD */ + +#if defined(RCC_APB1ENR1_RTCAPBEN) +#define __HAL_RCC_RTCAPB_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_RTCAPBEN); +#endif /* RCC_APB1ENR1_RTCAPBEN */ + +#if defined(SPI2) +#define __HAL_RCC_SPI2_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_SPI2EN) +#endif /* SPI2 */ + +#define __HAL_RCC_SPI3_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_SPI3EN) + +#define __HAL_RCC_USART2_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USART2EN) + +#if defined(USART3) +#define __HAL_RCC_USART3_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USART3EN) +#endif /* USART3 */ + +#if defined(UART4) +#define __HAL_RCC_UART4_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_UART4EN) +#endif /* UART4 */ + +#if defined(UART5) +#define __HAL_RCC_UART5_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_UART5EN) +#endif /* UART5 */ + +#define __HAL_RCC_I2C1_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_I2C1EN) + +#if defined(I2C2) +#define __HAL_RCC_I2C2_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_I2C2EN) +#endif /* I2C2 */ + +#define __HAL_RCC_I2C3_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_I2C3EN) + +#if defined(I2C4) +#define __HAL_RCC_I2C4_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR2, RCC_APB1ENR2_I2C4EN) +#endif /* I2C4 */ + +#if defined(CRS) +#define __HAL_RCC_CRS_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_CRSEN); +#endif /* CRS */ + +#define __HAL_RCC_CAN1_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_CAN1EN) + +#if defined(CAN2) +#define __HAL_RCC_CAN2_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_CAN2EN) +#endif /* CAN2 */ + +#if defined(USB) +#define __HAL_RCC_USB_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USBFSEN); +#endif /* USB */ + +#define __HAL_RCC_PWR_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_PWREN) + +#define __HAL_RCC_DAC1_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_DAC1EN) + +#define __HAL_RCC_OPAMP_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_OPAMPEN) + +#define __HAL_RCC_LPTIM1_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR1, RCC_APB1ENR1_LPTIM1EN) + +#define __HAL_RCC_LPUART1_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR2, RCC_APB1ENR2_LPUART1EN) + +#if defined(SWPMI1) +#define __HAL_RCC_SWPMI1_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR2, RCC_APB1ENR2_SWPMI1EN) +#endif /* SWPMI1 */ + +#define __HAL_RCC_LPTIM2_CLK_DISABLE() CLEAR_BIT(RCC->APB1ENR2, RCC_APB1ENR2_LPTIM2EN) + +/** + * @} + */ + +/** @defgroup RCC_APB2_Clock_Enable_Disable APB2 Peripheral Clock Enable Disable + * @brief Enable or disable the APB2 peripheral clock. + * @note After reset, the peripheral clock (used for registers read/write access) + * is disabled and the application software has to enable this clock before + * using it. + * @{ + */ + +#define __HAL_RCC_SYSCFG_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_SYSCFGEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_SYSCFGEN); \ + UNUSED(tmpreg); \ + } while(0) + +#define __HAL_RCC_FIREWALL_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_FWEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_FWEN); \ + UNUSED(tmpreg); \ + } while(0) + +#if defined(SDMMC1) && defined(RCC_APB2ENR_SDMMC1EN) +#define __HAL_RCC_SDMMC1_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_SDMMC1EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_SDMMC1EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* SDMMC1 && RCC_APB2ENR_SDMMC1EN */ + +#define __HAL_RCC_TIM1_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM1EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM1EN); \ + UNUSED(tmpreg); \ + } while(0) + +#define __HAL_RCC_SPI1_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_SPI1EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_SPI1EN); \ + UNUSED(tmpreg); \ + } while(0) + +#if defined(TIM8) +#define __HAL_RCC_TIM8_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM8EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM8EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* TIM8 */ + +#define __HAL_RCC_USART1_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_USART1EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_USART1EN); \ + UNUSED(tmpreg); \ + } while(0) + + +#define __HAL_RCC_TIM15_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM15EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM15EN); \ + UNUSED(tmpreg); \ + } while(0) + +#define __HAL_RCC_TIM16_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM16EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM16EN); \ + UNUSED(tmpreg); \ + } while(0) + +#if defined(TIM17) +#define __HAL_RCC_TIM17_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM17EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM17EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* TIM17 */ + +#define __HAL_RCC_SAI1_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_SAI1EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_SAI1EN); \ + UNUSED(tmpreg); \ + } while(0) + +#if defined(SAI2) +#define __HAL_RCC_SAI2_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_SAI2EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_SAI2EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* SAI2 */ + +#if defined(DFSDM1_Filter0) +#define __HAL_RCC_DFSDM1_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_DFSDM1EN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_DFSDM1EN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* DFSDM1_Filter0 */ + +#if defined(LTDC) +#define __HAL_RCC_LTDC_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_LTDCEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_LTDCEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* LTDC */ + +#if defined(DSI) +#define __HAL_RCC_DSI_CLK_ENABLE() do { \ + __IO uint32_t tmpreg; \ + SET_BIT(RCC->APB2ENR, RCC_APB2ENR_DSIEN); \ + /* Delay after an RCC peripheral clock enabling */ \ + tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_DSIEN); \ + UNUSED(tmpreg); \ + } while(0) +#endif /* DSI */ + + +#define __HAL_RCC_SYSCFG_CLK_DISABLE() CLEAR_BIT(RCC->APB2ENR, RCC_APB2ENR_SYSCFGEN) + +#if defined(SDMMC1) && defined(RCC_APB2ENR_SDMMC1EN) +#define __HAL_RCC_SDMMC1_CLK_DISABLE() CLEAR_BIT(RCC->APB2ENR, RCC_APB2ENR_SDMMC1EN) +#endif /* SDMMC1 && RCC_APB2ENR_SDMMC1EN */ + +#define __HAL_RCC_TIM1_CLK_DISABLE() CLEAR_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM1EN) + +#define __HAL_RCC_SPI1_CLK_DISABLE() CLEAR_BIT(RCC->APB2ENR, RCC_APB2ENR_SPI1EN) + +#if defined(TIM8) +#define __HAL_RCC_TIM8_CLK_DISABLE() CLEAR_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM8EN) +#endif /* TIM8 */ + +#define __HAL_RCC_USART1_CLK_DISABLE() CLEAR_BIT(RCC->APB2ENR, RCC_APB2ENR_USART1EN) + +#define __HAL_RCC_TIM15_CLK_DISABLE() CLEAR_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM15EN) + +#define __HAL_RCC_TIM16_CLK_DISABLE() CLEAR_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM16EN) + +#if defined(TIM17) +#define __HAL_RCC_TIM17_CLK_DISABLE() CLEAR_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM17EN) +#endif /* TIM17 */ + +#define __HAL_RCC_SAI1_CLK_DISABLE() CLEAR_BIT(RCC->APB2ENR, RCC_APB2ENR_SAI1EN) + +#if defined(SAI2) +#define __HAL_RCC_SAI2_CLK_DISABLE() CLEAR_BIT(RCC->APB2ENR, RCC_APB2ENR_SAI2EN) +#endif /* SAI2 */ + +#if defined(DFSDM1_Filter0) +#define __HAL_RCC_DFSDM1_CLK_DISABLE() CLEAR_BIT(RCC->APB2ENR, RCC_APB2ENR_DFSDM1EN) +#endif /* DFSDM1_Filter0 */ + +#if defined(LTDC) +#define __HAL_RCC_LTDC_CLK_DISABLE() CLEAR_BIT(RCC->APB2ENR, RCC_APB2ENR_LTDCEN) +#endif /* LTDC */ + +#if defined(DSI) +#define __HAL_RCC_DSI_CLK_DISABLE() CLEAR_BIT(RCC->APB2ENR, RCC_APB2ENR_DSIEN) +#endif /* DSI */ + +/** + * @} + */ + +/** @defgroup RCC_AHB1_Peripheral_Clock_Enable_Disable_Status AHB1 Peripheral Clock Enabled or Disabled Status + * @brief Check whether the AHB1 peripheral clock is enabled or not. + * @note After reset, the peripheral clock (used for registers read/write access) + * is disabled and the application software has to enable this clock before + * using it. + * @{ + */ + +#define __HAL_RCC_DMA1_IS_CLK_ENABLED() (READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMA1EN) != RESET) + +#define __HAL_RCC_DMA2_IS_CLK_ENABLED() (READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMA2EN) != RESET) + +#if defined(DMAMUX1) +#define __HAL_RCC_DMAMUX1_IS_CLK_ENABLED() (READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMAMUX1EN) != RESET) +#endif /* DMAMUX1 */ + +#define __HAL_RCC_FLASH_IS_CLK_ENABLED() (READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_FLASHEN) != RESET) + +#define __HAL_RCC_CRC_IS_CLK_ENABLED() (READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_CRCEN) != RESET) + +#define __HAL_RCC_TSC_IS_CLK_ENABLED() (READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_TSCEN) != RESET) + +#if defined(DMA2D) +#define __HAL_RCC_DMA2D_IS_CLK_ENABLED() (READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMA2DEN) != RESET) +#endif /* DMA2D */ + +#if defined(GFXMMU) +#define __HAL_RCC_GFXMMU_IS_CLK_ENABLED() (READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GFXMMUEN) != RESET) +#endif /* GFXMMU */ + + +#define __HAL_RCC_DMA1_IS_CLK_DISABLED() (READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMA1EN) == RESET) + +#define __HAL_RCC_DMA2_IS_CLK_DISABLED() (READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMA2EN) == RESET) + +#if defined(DMAMUX1) +#define __HAL_RCC_DMAMUX1_IS_CLK_DISABLED() (READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMAMUX1EN) == RESET) +#endif /* DMAMUX1 */ + +#define __HAL_RCC_FLASH_IS_CLK_DISABLED() (READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_FLASHEN) == RESET) + +#define __HAL_RCC_CRC_IS_CLK_DISABLED() (READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_CRCEN) == RESET) + +#define __HAL_RCC_TSC_IS_CLK_DISABLED() (READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_TSCEN) == RESET) + +#if defined(DMA2D) +#define __HAL_RCC_DMA2D_IS_CLK_DISABLED() (READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMA2DEN) == RESET) +#endif /* DMA2D */ + +#if defined(GFXMMU) +#define __HAL_RCC_GFXMMU_IS_CLK_DISABLED() (READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GFXMMUEN) == RESET) +#endif /* GFXMMU */ + +/** + * @} + */ + +/** @defgroup RCC_AHB2_Clock_Enable_Disable_Status AHB2 Peripheral Clock Enabled or Disabled Status + * @brief Check whether the AHB2 peripheral clock is enabled or not. + * @note After reset, the peripheral clock (used for registers read/write access) + * is disabled and the application software has to enable this clock before + * using it. + * @{ + */ + +#define __HAL_RCC_GPIOA_IS_CLK_ENABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOAEN) != RESET) + +#define __HAL_RCC_GPIOB_IS_CLK_ENABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOBEN) != RESET) + +#define __HAL_RCC_GPIOC_IS_CLK_ENABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOCEN) != RESET) + +#if defined(GPIOD) +#define __HAL_RCC_GPIOD_IS_CLK_ENABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIODEN) != RESET) +#endif /* GPIOD */ + +#if defined(GPIOE) +#define __HAL_RCC_GPIOE_IS_CLK_ENABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOEEN) != RESET) +#endif /* GPIOE */ + +#if defined(GPIOF) +#define __HAL_RCC_GPIOF_IS_CLK_ENABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOFEN) != RESET) +#endif /* GPIOF */ + +#if defined(GPIOG) +#define __HAL_RCC_GPIOG_IS_CLK_ENABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOGEN) != RESET) +#endif /* GPIOG */ + +#define __HAL_RCC_GPIOH_IS_CLK_ENABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOHEN) != RESET) + +#if defined(GPIOI) +#define __HAL_RCC_GPIOI_IS_CLK_ENABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOIEN) != RESET) +#endif /* GPIOI */ + +#if defined(USB_OTG_FS) +#define __HAL_RCC_USB_OTG_FS_IS_CLK_ENABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_OTGFSEN) != RESET) +#endif /* USB_OTG_FS */ + +#define __HAL_RCC_ADC_IS_CLK_ENABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_ADCEN) != RESET) + +#if defined(DCMI) +#define __HAL_RCC_DCMI_IS_CLK_ENABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_DCMIEN) != RESET) +#endif /* DCMI */ + +#if defined(AES) +#define __HAL_RCC_AES_IS_CLK_ENABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_AESEN) != RESET) +#endif /* AES */ + +#if defined(HASH) +#define __HAL_RCC_HASH_IS_CLK_ENABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_HASHEN) != RESET) +#endif /* HASH */ + +#define __HAL_RCC_RNG_IS_CLK_ENABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_RNGEN) != RESET) + + +#define __HAL_RCC_GPIOA_IS_CLK_DISABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOAEN) == RESET) + +#define __HAL_RCC_GPIOB_IS_CLK_DISABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOBEN) == RESET) + +#define __HAL_RCC_GPIOC_IS_CLK_DISABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOCEN) == RESET) + +#if defined(GPIOD) +#define __HAL_RCC_GPIOD_IS_CLK_DISABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIODEN) == RESET) +#endif /* GPIOD */ + +#if defined(GPIOE) +#define __HAL_RCC_GPIOE_IS_CLK_DISABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOEEN) == RESET) +#endif /* GPIOE */ + +#if defined(GPIOF) +#define __HAL_RCC_GPIOF_IS_CLK_DISABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOFEN) == RESET) +#endif /* GPIOF */ + +#if defined(GPIOG) +#define __HAL_RCC_GPIOG_IS_CLK_DISABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOGEN) == RESET) +#endif /* GPIOG */ + +#define __HAL_RCC_GPIOH_IS_CLK_DISABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOHEN) == RESET) + +#if defined(GPIOI) +#define __HAL_RCC_GPIOI_IS_CLK_DISABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOIEN) == RESET) +#endif /* GPIOI */ + +#if defined(USB_OTG_FS) +#define __HAL_RCC_USB_OTG_FS_IS_CLK_DISABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_OTGFSEN) == RESET) +#endif /* USB_OTG_FS */ + +#define __HAL_RCC_ADC_IS_CLK_DISABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_ADCEN) == RESET) + +#if defined(DCMI) +#define __HAL_RCC_DCMI_IS_CLK_DISABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_DCMIEN) == RESET) +#endif /* DCMI */ + +#if defined(AES) +#define __HAL_RCC_AES_IS_CLK_DISABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_AESEN) == RESET) +#endif /* AES */ + +#if defined(HASH) +#define __HAL_RCC_HASH_IS_CLK_DISABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_HASHEN) == RESET) +#endif /* HASH */ + +#define __HAL_RCC_RNG_IS_CLK_DISABLED() (READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_RNGEN) == RESET) + +/** + * @} + */ + +/** @defgroup RCC_AHB3_Clock_Enable_Disable_Status AHB3 Peripheral Clock Enabled or Disabled Status + * @brief Check whether the AHB3 peripheral clock is enabled or not. + * @note After reset, the peripheral clock (used for registers read/write access) + * is disabled and the application software has to enable this clock before + * using it. + * @{ + */ + +#if defined(FMC_BANK1) +#define __HAL_RCC_FMC_IS_CLK_ENABLED() (READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN) != RESET) +#endif /* FMC_BANK1 */ + +#if defined(QUADSPI) +#define __HAL_RCC_QSPI_IS_CLK_ENABLED() (READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_QSPIEN) != RESET) +#endif /* QUADSPI */ + +#if defined(FMC_BANK1) +#define __HAL_RCC_FMC_IS_CLK_DISABLED() (READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN) == RESET) +#endif /* FMC_BANK1 */ + +#if defined(QUADSPI) +#define __HAL_RCC_QSPI_IS_CLK_DISABLED() (READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_QSPIEN) == RESET) +#endif /* QUADSPI */ + +/** + * @} + */ + +/** @defgroup RCC_APB1_Clock_Enable_Disable_Status APB1 Peripheral Clock Enabled or Disabled Status + * @brief Check whether the APB1 peripheral clock is enabled or not. + * @note After reset, the peripheral clock (used for registers read/write access) + * is disabled and the application software has to enable this clock before + * using it. + * @{ + */ + +#define __HAL_RCC_TIM2_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM2EN) != RESET) + +#if defined(TIM3) +#define __HAL_RCC_TIM3_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM3EN) != RESET) +#endif /* TIM3 */ + +#if defined(TIM4) +#define __HAL_RCC_TIM4_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM4EN) != RESET) +#endif /* TIM4 */ + +#if defined(TIM5) +#define __HAL_RCC_TIM5_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM5EN) != RESET) +#endif /* TIM5 */ + +#define __HAL_RCC_TIM6_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM6EN) != RESET) + +#define __HAL_RCC_TIM7_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM7EN) != RESET) + +#if defined(LCD) +#define __HAL_RCC_LCD_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_LCDEN) != RESET) +#endif /* LCD */ + +#if defined(RCC_APB1ENR1_RTCAPBEN) +#define __HAL_RCC_RTCAPB_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_RTCAPBEN) != RESET) +#endif /* RCC_APB1ENR1_RTCAPBEN */ + +#define __HAL_RCC_WWDG_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_WWDGEN) != RESET) + +#if defined(SPI2) +#define __HAL_RCC_SPI2_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_SPI2EN) != RESET) +#endif /* SPI2 */ + +#define __HAL_RCC_SPI3_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_SPI3EN) != RESET) + +#define __HAL_RCC_USART2_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USART2EN) != RESET) + +#if defined(USART3) +#define __HAL_RCC_USART3_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USART3EN) != RESET) +#endif /* USART3 */ + +#if defined(UART4) +#define __HAL_RCC_UART4_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_UART4EN) != RESET) +#endif /* UART4 */ + +#if defined(UART5) +#define __HAL_RCC_UART5_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_UART5EN) != RESET) +#endif /* UART5 */ + +#define __HAL_RCC_I2C1_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_I2C1EN) != RESET) + +#if defined(I2C2) +#define __HAL_RCC_I2C2_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_I2C2EN) != RESET) +#endif /* I2C2 */ + +#define __HAL_RCC_I2C3_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_I2C3EN) != RESET) + +#if defined(I2C4) +#define __HAL_RCC_I2C4_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR2, RCC_APB1ENR2_I2C4EN) != RESET) +#endif /* I2C4 */ + +#if defined(CRS) +#define __HAL_RCC_CRS_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_CRSEN) != RESET) +#endif /* CRS */ + +#define __HAL_RCC_CAN1_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_CAN1EN) != RESET) + +#if defined(CAN2) +#define __HAL_RCC_CAN2_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_CAN2EN) != RESET) +#endif /* CAN2 */ + +#if defined(USB) +#define __HAL_RCC_USB_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USBFSEN) != RESET) +#endif /* USB */ + +#define __HAL_RCC_PWR_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_PWREN) != RESET) + +#define __HAL_RCC_DAC1_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_DAC1EN) != RESET) + +#define __HAL_RCC_OPAMP_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_OPAMPEN) != RESET) + +#define __HAL_RCC_LPTIM1_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_LPTIM1EN) != RESET) + +#define __HAL_RCC_LPUART1_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR2, RCC_APB1ENR2_LPUART1EN) != RESET) + +#if defined(SWPMI1) +#define __HAL_RCC_SWPMI1_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR2, RCC_APB1ENR2_SWPMI1EN) != RESET) +#endif /* SWPMI1 */ + +#define __HAL_RCC_LPTIM2_IS_CLK_ENABLED() (READ_BIT(RCC->APB1ENR2, RCC_APB1ENR2_LPTIM2EN) != RESET) + + +#define __HAL_RCC_TIM2_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM2EN) == RESET) + +#if defined(TIM3) +#define __HAL_RCC_TIM3_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM3EN) == RESET) +#endif /* TIM3 */ + +#if defined(TIM4) +#define __HAL_RCC_TIM4_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM4EN) == RESET) +#endif /* TIM4 */ + +#if defined(TIM5) +#define __HAL_RCC_TIM5_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM5EN) == RESET) +#endif /* TIM5 */ + +#define __HAL_RCC_TIM6_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM6EN) == RESET) + +#define __HAL_RCC_TIM7_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_TIM7EN) == RESET) + +#if defined(LCD) +#define __HAL_RCC_LCD_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_LCDEN) == RESET) +#endif /* LCD */ + +#if defined(RCC_APB1ENR1_RTCAPBEN) +#define __HAL_RCC_RTCAPB_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_RTCAPBEN) == RESET) +#endif /* RCC_APB1ENR1_RTCAPBEN */ + +#define __HAL_RCC_WWDG_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_WWDGEN) == RESET) + +#if defined(SPI2) +#define __HAL_RCC_SPI2_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_SPI2EN) == RESET) +#endif /* SPI2 */ + +#define __HAL_RCC_SPI3_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_SPI3EN) == RESET) + +#define __HAL_RCC_USART2_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USART2EN) == RESET) + +#if defined(USART3) +#define __HAL_RCC_USART3_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USART3EN) == RESET) +#endif /* USART3 */ + +#if defined(UART4) +#define __HAL_RCC_UART4_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_UART4EN) == RESET) +#endif /* UART4 */ + +#if defined(UART5) +#define __HAL_RCC_UART5_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_UART5EN) == RESET) +#endif /* UART5 */ + +#define __HAL_RCC_I2C1_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_I2C1EN) == RESET) + +#if defined(I2C2) +#define __HAL_RCC_I2C2_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_I2C2EN) == RESET) +#endif /* I2C2 */ + +#define __HAL_RCC_I2C3_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_I2C3EN) == RESET) + +#if defined(I2C4) +#define __HAL_RCC_I2C4_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR2, RCC_APB1ENR2_I2C4EN) == RESET) +#endif /* I2C4 */ + +#if defined(CRS) +#define __HAL_RCC_CRS_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_CRSEN) == RESET) +#endif /* CRS */ + +#define __HAL_RCC_CAN1_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_CAN1EN) == RESET) + +#if defined(CAN2) +#define __HAL_RCC_CAN2_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_CAN2EN) == RESET) +#endif /* CAN2 */ + +#if defined(USB) +#define __HAL_RCC_USB_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USBFSEN) == RESET) +#endif /* USB */ + +#define __HAL_RCC_PWR_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_PWREN) == RESET) + +#define __HAL_RCC_DAC1_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_DAC1EN) == RESET) + +#define __HAL_RCC_OPAMP_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_OPAMPEN) == RESET) + +#define __HAL_RCC_LPTIM1_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR1, RCC_APB1ENR1_LPTIM1EN) == RESET) + +#define __HAL_RCC_LPUART1_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR2, RCC_APB1ENR2_LPUART1EN) == RESET) + +#if defined(SWPMI1) +#define __HAL_RCC_SWPMI1_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR2, RCC_APB1ENR2_SWPMI1EN) == RESET) +#endif /* SWPMI1 */ + +#define __HAL_RCC_LPTIM2_IS_CLK_DISABLED() (READ_BIT(RCC->APB1ENR2, RCC_APB1ENR2_LPTIM2EN) == RESET) + +/** + * @} + */ + +/** @defgroup RCC_APB2_Clock_Enable_Disable_Status APB2 Peripheral Clock Enabled or Disabled Status + * @brief Check whether the APB2 peripheral clock is enabled or not. + * @note After reset, the peripheral clock (used for registers read/write access) + * is disabled and the application software has to enable this clock before + * using it. + * @{ + */ + +#define __HAL_RCC_SYSCFG_IS_CLK_ENABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_SYSCFGEN) != RESET) + +#define __HAL_RCC_FIREWALL_IS_CLK_ENABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_FWEN) != RESET) + +#if defined(SDMMC1) && defined(RCC_APB2ENR_SDMMC1EN) +#define __HAL_RCC_SDMMC1_IS_CLK_ENABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_SDMMC1EN) != RESET) +#endif /* SDMMC1 && RCC_APB2ENR_SDMMC1EN */ + +#define __HAL_RCC_TIM1_IS_CLK_ENABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM1EN) != RESET) + +#define __HAL_RCC_SPI1_IS_CLK_ENABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_SPI1EN) != RESET) + +#if defined(TIM8) +#define __HAL_RCC_TIM8_IS_CLK_ENABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM8EN) != RESET) +#endif /* TIM8 */ + +#define __HAL_RCC_USART1_IS_CLK_ENABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_USART1EN) != RESET) + +#define __HAL_RCC_TIM15_IS_CLK_ENABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM15EN) != RESET) + +#define __HAL_RCC_TIM16_IS_CLK_ENABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM16EN) != RESET) + +#if defined(TIM17) +#define __HAL_RCC_TIM17_IS_CLK_ENABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM17EN) != RESET) +#endif /* TIM17 */ + +#define __HAL_RCC_SAI1_IS_CLK_ENABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_SAI1EN) != RESET) + +#if defined(SAI2) +#define __HAL_RCC_SAI2_IS_CLK_ENABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_SAI2EN) != RESET) +#endif /* SAI2 */ + +#if defined(DFSDM1_Filter0) +#define __HAL_RCC_DFSDM1_IS_CLK_ENABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_DFSDM1EN) != RESET) +#endif /* DFSDM1_Filter0 */ + +#if defined(LTDC) +#define __HAL_RCC_LTDC_IS_CLK_ENABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_LTDCEN) != RESET) +#endif /* LTDC */ + +#if defined(DSI) +#define __HAL_RCC_DSI_IS_CLK_ENABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_DSIEN) != RESET) +#endif /* DSI */ + + +#define __HAL_RCC_SYSCFG_IS_CLK_DISABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_SYSCFGEN) == RESET) + +#if defined(SDMMC1) && defined(RCC_APB2ENR_SDMMC1EN) +#define __HAL_RCC_SDMMC1_IS_CLK_DISABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_SDMMC1EN) == RESET) +#endif /* SDMMC1 && RCC_APB2ENR_SDMMC1EN */ + +#define __HAL_RCC_TIM1_IS_CLK_DISABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM1EN) == RESET) + +#define __HAL_RCC_SPI1_IS_CLK_DISABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_SPI1EN) == RESET) + +#if defined(TIM8) +#define __HAL_RCC_TIM8_IS_CLK_DISABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM8EN) == RESET) +#endif /* TIM8 */ + +#define __HAL_RCC_USART1_IS_CLK_DISABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_USART1EN) == RESET) + +#define __HAL_RCC_TIM15_IS_CLK_DISABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM15EN) == RESET) + +#define __HAL_RCC_TIM16_IS_CLK_DISABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM16EN) == RESET) + +#if defined(TIM17) +#define __HAL_RCC_TIM17_IS_CLK_DISABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM17EN) == RESET) +#endif /* TIM17 */ + +#define __HAL_RCC_SAI1_IS_CLK_DISABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_SAI1EN) == RESET) + +#if defined(SAI2) +#define __HAL_RCC_SAI2_IS_CLK_DISABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_SAI2EN) == RESET) +#endif /* SAI2 */ + +#if defined(DFSDM1_Filter0) +#define __HAL_RCC_DFSDM1_IS_CLK_DISABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_DFSDM1EN) == RESET) +#endif /* DFSDM1_Filter0 */ + +#if defined(LTDC) +#define __HAL_RCC_LTDC_IS_CLK_DISABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_LTDCEN) == RESET) +#endif /* LTDC */ + +#if defined(DSI) +#define __HAL_RCC_DSI_IS_CLK_DISABLED() (READ_BIT(RCC->APB2ENR, RCC_APB2ENR_DSIEN) == RESET) +#endif /* DSI */ + +/** + * @} + */ + +/** @defgroup RCC_AHB1_Force_Release_Reset AHB1 Peripheral Force Release Reset + * @brief Force or release AHB1 peripheral reset. + * @{ + */ +#define __HAL_RCC_AHB1_FORCE_RESET() WRITE_REG(RCC->AHB1RSTR, 0xFFFFFFFFU) + +#define __HAL_RCC_DMA1_FORCE_RESET() SET_BIT(RCC->AHB1RSTR, RCC_AHB1RSTR_DMA1RST) + +#define __HAL_RCC_DMA2_FORCE_RESET() SET_BIT(RCC->AHB1RSTR, RCC_AHB1RSTR_DMA2RST) + +#if defined(DMAMUX1) +#define __HAL_RCC_DMAMUX1_FORCE_RESET() SET_BIT(RCC->AHB1RSTR, RCC_AHB1RSTR_DMAMUX1RST) +#endif /* DMAMUX1 */ + +#define __HAL_RCC_FLASH_FORCE_RESET() SET_BIT(RCC->AHB1RSTR, RCC_AHB1RSTR_FLASHRST) + +#define __HAL_RCC_CRC_FORCE_RESET() SET_BIT(RCC->AHB1RSTR, RCC_AHB1RSTR_CRCRST) + +#define __HAL_RCC_TSC_FORCE_RESET() SET_BIT(RCC->AHB1RSTR, RCC_AHB1RSTR_TSCRST) + +#if defined(DMA2D) +#define __HAL_RCC_DMA2D_FORCE_RESET() SET_BIT(RCC->AHB1RSTR, RCC_AHB1RSTR_DMA2DRST) +#endif /* DMA2D */ + +#if defined(GFXMMU) +#define __HAL_RCC_GFXMMU_FORCE_RESET() SET_BIT(RCC->AHB1RSTR, RCC_AHB1RSTR_GFXMMURST) +#endif /* GFXMMU */ + + +#define __HAL_RCC_AHB1_RELEASE_RESET() WRITE_REG(RCC->AHB1RSTR, 0x00000000U) + +#define __HAL_RCC_DMA1_RELEASE_RESET() CLEAR_BIT(RCC->AHB1RSTR, RCC_AHB1RSTR_DMA1RST) + +#define __HAL_RCC_DMA2_RELEASE_RESET() CLEAR_BIT(RCC->AHB1RSTR, RCC_AHB1RSTR_DMA2RST) + +#if defined(DMAMUX1) +#define __HAL_RCC_DMAMUX1_RELEASE_RESET() CLEAR_BIT(RCC->AHB1RSTR, RCC_AHB1RSTR_DMAMUX1RST) +#endif /* DMAMUX1 */ + +#define __HAL_RCC_FLASH_RELEASE_RESET() CLEAR_BIT(RCC->AHB1RSTR, RCC_AHB1RSTR_FLASHRST) + +#define __HAL_RCC_CRC_RELEASE_RESET() CLEAR_BIT(RCC->AHB1RSTR, RCC_AHB1RSTR_CRCRST) + +#define __HAL_RCC_TSC_RELEASE_RESET() CLEAR_BIT(RCC->AHB1RSTR, RCC_AHB1RSTR_TSCRST) + +#if defined(DMA2D) +#define __HAL_RCC_DMA2D_RELEASE_RESET() CLEAR_BIT(RCC->AHB1RSTR, RCC_AHB1RSTR_DMA2DRST) +#endif /* DMA2D */ + +#if defined(GFXMMU) +#define __HAL_RCC_GFXMMU_RELEASE_RESET() CLEAR_BIT(RCC->AHB1RSTR, RCC_AHB1RSTR_GFXMMURST) +#endif /* GFXMMU */ + +/** + * @} + */ + +/** @defgroup RCC_AHB2_Force_Release_Reset AHB2 Peripheral Force Release Reset + * @brief Force or release AHB2 peripheral reset. + * @{ + */ +#define __HAL_RCC_AHB2_FORCE_RESET() WRITE_REG(RCC->AHB2RSTR, 0xFFFFFFFFU) + +#define __HAL_RCC_GPIOA_FORCE_RESET() SET_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_GPIOARST) + +#define __HAL_RCC_GPIOB_FORCE_RESET() SET_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_GPIOBRST) + +#define __HAL_RCC_GPIOC_FORCE_RESET() SET_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_GPIOCRST) + +#if defined(GPIOD) +#define __HAL_RCC_GPIOD_FORCE_RESET() SET_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_GPIODRST) +#endif /* GPIOD */ + +#if defined(GPIOE) +#define __HAL_RCC_GPIOE_FORCE_RESET() SET_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_GPIOERST) +#endif /* GPIOE */ + +#if defined(GPIOF) +#define __HAL_RCC_GPIOF_FORCE_RESET() SET_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_GPIOFRST) +#endif /* GPIOF */ + +#if defined(GPIOG) +#define __HAL_RCC_GPIOG_FORCE_RESET() SET_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_GPIOGRST) +#endif /* GPIOG */ + +#define __HAL_RCC_GPIOH_FORCE_RESET() SET_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_GPIOHRST) + +#if defined(GPIOI) +#define __HAL_RCC_GPIOI_FORCE_RESET() SET_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_GPIOIRST) +#endif /* GPIOI */ + +#if defined(USB_OTG_FS) +#define __HAL_RCC_USB_OTG_FS_FORCE_RESET() SET_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_OTGFSRST) +#endif /* USB_OTG_FS */ + +#define __HAL_RCC_ADC_FORCE_RESET() SET_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_ADCRST) + +#if defined(DCMI) +#define __HAL_RCC_DCMI_FORCE_RESET() SET_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_DCMIRST) +#endif /* DCMI */ + +#if defined(AES) +#define __HAL_RCC_AES_FORCE_RESET() SET_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_AESRST) +#endif /* AES */ + +#if defined(HASH) +#define __HAL_RCC_HASH_FORCE_RESET() SET_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_HASHRST) +#endif /* HASH */ + +#define __HAL_RCC_RNG_FORCE_RESET() SET_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_RNGRST) + +#if defined(OCTOSPIM) +#define __HAL_RCC_OSPIM_FORCE_RESET() SET_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_OSPIMRST) +#endif /* OCTOSPIM */ + +#if defined(SDMMC1) && defined(RCC_AHB2RSTR_SDMMC1RST) +#define __HAL_RCC_SDMMC1_FORCE_RESET() SET_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_SDMMC1RST) +#endif /* SDMMC1 && RCC_AHB2RSTR_SDMMC1RST */ + + +#define __HAL_RCC_AHB2_RELEASE_RESET() WRITE_REG(RCC->AHB2RSTR, 0x00000000U) + +#define __HAL_RCC_GPIOA_RELEASE_RESET() CLEAR_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_GPIOARST) + +#define __HAL_RCC_GPIOB_RELEASE_RESET() CLEAR_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_GPIOBRST) + +#define __HAL_RCC_GPIOC_RELEASE_RESET() CLEAR_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_GPIOCRST) + +#if defined(GPIOD) +#define __HAL_RCC_GPIOD_RELEASE_RESET() CLEAR_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_GPIODRST) +#endif /* GPIOD */ + +#if defined(GPIOE) +#define __HAL_RCC_GPIOE_RELEASE_RESET() CLEAR_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_GPIOERST) +#endif /* GPIOE */ + +#if defined(GPIOF) +#define __HAL_RCC_GPIOF_RELEASE_RESET() CLEAR_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_GPIOFRST) +#endif /* GPIOF */ + +#if defined(GPIOG) +#define __HAL_RCC_GPIOG_RELEASE_RESET() CLEAR_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_GPIOGRST) +#endif /* GPIOG */ + +#define __HAL_RCC_GPIOH_RELEASE_RESET() CLEAR_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_GPIOHRST) + +#if defined(GPIOI) +#define __HAL_RCC_GPIOI_RELEASE_RESET() CLEAR_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_GPIOIRST) +#endif /* GPIOI */ + +#if defined(USB_OTG_FS) +#define __HAL_RCC_USB_OTG_FS_RELEASE_RESET() CLEAR_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_OTGFSRST) +#endif /* USB_OTG_FS */ + +#define __HAL_RCC_ADC_RELEASE_RESET() CLEAR_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_ADCRST) + +#if defined(DCMI) +#define __HAL_RCC_DCMI_RELEASE_RESET() CLEAR_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_DCMIRST) +#endif /* DCMI */ + +#if defined(AES) +#define __HAL_RCC_AES_RELEASE_RESET() CLEAR_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_AESRST) +#endif /* AES */ + +#if defined(HASH) +#define __HAL_RCC_HASH_RELEASE_RESET() CLEAR_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_HASHRST) +#endif /* HASH */ + +#define __HAL_RCC_RNG_RELEASE_RESET() CLEAR_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_RNGRST) + +#if defined(OCTOSPIM) +#define __HAL_RCC_OSPIM_RELEASE_RESET() CLEAR_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_OSPIMRST) +#endif /* OCTOSPIM */ + +#if defined(SDMMC1) && defined(RCC_AHB2RSTR_SDMMC1RST) +#define __HAL_RCC_SDMMC1_RELEASE_RESET() CLEAR_BIT(RCC->AHB2RSTR, RCC_AHB2RSTR_SDMMC1RST) +#endif /* SDMMC1 && RCC_AHB2RSTR_SDMMC1RST */ + +/** + * @} + */ + +/** @defgroup RCC_AHB3_Force_Release_Reset AHB3 Peripheral Force Release Reset + * @brief Force or release AHB3 peripheral reset. + * @{ + */ +#define __HAL_RCC_AHB3_FORCE_RESET() WRITE_REG(RCC->AHB3RSTR, 0xFFFFFFFFU) + +#if defined(FMC_BANK1) +#define __HAL_RCC_FMC_FORCE_RESET() SET_BIT(RCC->AHB3RSTR, RCC_AHB3RSTR_FMCRST) +#endif /* FMC_BANK1 */ + +#if defined(QUADSPI) +#define __HAL_RCC_QSPI_FORCE_RESET() SET_BIT(RCC->AHB3RSTR, RCC_AHB3RSTR_QSPIRST) +#endif /* QUADSPI */ + +#if defined(OCTOSPI1) +#define __HAL_RCC_OSPI1_FORCE_RESET() SET_BIT(RCC->AHB3RSTR, RCC_AHB3RSTR_OSPI1RST) +#endif /* OCTOSPI1 */ + +#if defined(OCTOSPI2) +#define __HAL_RCC_OSPI2_FORCE_RESET() SET_BIT(RCC->AHB3RSTR, RCC_AHB3RSTR_OSPI2RST) +#endif /* OCTOSPI2 */ + +#define __HAL_RCC_AHB3_RELEASE_RESET() WRITE_REG(RCC->AHB3RSTR, 0x00000000U) + +#if defined(FMC_BANK1) +#define __HAL_RCC_FMC_RELEASE_RESET() CLEAR_BIT(RCC->AHB3RSTR, RCC_AHB3RSTR_FMCRST) +#endif /* FMC_BANK1 */ + +#if defined(QUADSPI) +#define __HAL_RCC_QSPI_RELEASE_RESET() CLEAR_BIT(RCC->AHB3RSTR, RCC_AHB3RSTR_QSPIRST) +#endif /* QUADSPI */ + +#if defined(OCTOSPI1) +#define __HAL_RCC_OSPI1_RELEASE_RESET() CLEAR_BIT(RCC->AHB3RSTR, RCC_AHB3RSTR_OSPI1RST) +#endif /* OCTOSPI1 */ + +#if defined(OCTOSPI2) +#define __HAL_RCC_OSPI2_RELEASE_RESET() CLEAR_BIT(RCC->AHB3RSTR, RCC_AHB3RSTR_OSPI2RST) +#endif /* OCTOSPI2 */ + +/** + * @} + */ + +/** @defgroup RCC_APB1_Force_Release_Reset APB1 Peripheral Force Release Reset + * @brief Force or release APB1 peripheral reset. + * @{ + */ +#define __HAL_RCC_APB1_FORCE_RESET() WRITE_REG(RCC->APB1RSTR1, 0xFFFFFFFFU) + +#define __HAL_RCC_TIM2_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_TIM2RST) + +#if defined(TIM3) +#define __HAL_RCC_TIM3_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_TIM3RST) +#endif /* TIM3 */ + +#if defined(TIM4) +#define __HAL_RCC_TIM4_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_TIM4RST) +#endif /* TIM4 */ + +#if defined(TIM5) +#define __HAL_RCC_TIM5_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_TIM5RST) +#endif /* TIM5 */ + +#define __HAL_RCC_TIM6_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_TIM6RST) + +#define __HAL_RCC_TIM7_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_TIM7RST) + +#if defined(LCD) +#define __HAL_RCC_LCD_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_LCDRST) +#endif /* LCD */ + +#if defined(SPI2) +#define __HAL_RCC_SPI2_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_SPI2RST) +#endif /* SPI2 */ + +#define __HAL_RCC_SPI3_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_SPI3RST) + +#define __HAL_RCC_USART2_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_USART2RST) + +#if defined(USART3) +#define __HAL_RCC_USART3_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_USART3RST) +#endif /* USART3 */ + +#if defined(UART4) +#define __HAL_RCC_UART4_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_UART4RST) +#endif /* UART4 */ + +#if defined(UART5) +#define __HAL_RCC_UART5_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_UART5RST) +#endif /* UART5 */ + +#define __HAL_RCC_I2C1_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_I2C1RST) + +#if defined(I2C2) +#define __HAL_RCC_I2C2_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_I2C2RST) +#endif /* I2C2 */ + +#define __HAL_RCC_I2C3_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_I2C3RST) + +#if defined(I2C4) +#define __HAL_RCC_I2C4_FORCE_RESET() SET_BIT(RCC->APB1RSTR2, RCC_APB1RSTR2_I2C4RST) +#endif /* I2C4 */ + +#if defined(CRS) +#define __HAL_RCC_CRS_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_CRSRST) +#endif /* CRS */ + +#define __HAL_RCC_CAN1_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_CAN1RST) + +#if defined(CAN2) +#define __HAL_RCC_CAN2_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_CAN2RST) +#endif /* CAN2 */ + +#if defined(USB) +#define __HAL_RCC_USB_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_USBFSRST) +#endif /* USB */ + +#define __HAL_RCC_PWR_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_PWRRST) + +#define __HAL_RCC_DAC1_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_DAC1RST) + +#define __HAL_RCC_OPAMP_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_OPAMPRST) + +#define __HAL_RCC_LPTIM1_FORCE_RESET() SET_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_LPTIM1RST) + +#define __HAL_RCC_LPUART1_FORCE_RESET() SET_BIT(RCC->APB1RSTR2, RCC_APB1RSTR2_LPUART1RST) + +#if defined(SWPMI1) +#define __HAL_RCC_SWPMI1_FORCE_RESET() SET_BIT(RCC->APB1RSTR2, RCC_APB1RSTR2_SWPMI1RST) +#endif /* SWPMI1 */ + +#define __HAL_RCC_LPTIM2_FORCE_RESET() SET_BIT(RCC->APB1RSTR2, RCC_APB1RSTR2_LPTIM2RST) + + +#define __HAL_RCC_APB1_RELEASE_RESET() WRITE_REG(RCC->APB1RSTR1, 0x00000000U) + +#define __HAL_RCC_TIM2_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_TIM2RST) + +#if defined(TIM3) +#define __HAL_RCC_TIM3_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_TIM3RST) +#endif /* TIM3 */ + +#if defined(TIM4) +#define __HAL_RCC_TIM4_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_TIM4RST) +#endif /* TIM4 */ + +#if defined(TIM5) +#define __HAL_RCC_TIM5_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_TIM5RST) +#endif /* TIM5 */ + +#define __HAL_RCC_TIM6_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_TIM6RST) + +#define __HAL_RCC_TIM7_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_TIM7RST) + +#if defined(LCD) +#define __HAL_RCC_LCD_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_LCDRST) +#endif /* LCD */ + +#if defined(SPI2) +#define __HAL_RCC_SPI2_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_SPI2RST) +#endif /* SPI2 */ + +#define __HAL_RCC_SPI3_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_SPI3RST) + +#define __HAL_RCC_USART2_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_USART2RST) + +#if defined(USART3) +#define __HAL_RCC_USART3_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_USART3RST) +#endif /* USART3 */ + +#if defined(UART4) +#define __HAL_RCC_UART4_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_UART4RST) +#endif /* UART4 */ + +#if defined(UART5) +#define __HAL_RCC_UART5_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_UART5RST) +#endif /* UART5 */ + +#define __HAL_RCC_I2C1_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_I2C1RST) + +#if defined(I2C2) +#define __HAL_RCC_I2C2_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_I2C2RST) +#endif /* I2C2 */ + +#define __HAL_RCC_I2C3_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_I2C3RST) + +#if defined(I2C4) +#define __HAL_RCC_I2C4_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR2, RCC_APB1RSTR2_I2C4RST) +#endif /* I2C4 */ + +#if defined(CRS) +#define __HAL_RCC_CRS_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_CRSRST) +#endif /* CRS */ + +#define __HAL_RCC_CAN1_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_CAN1RST) + +#if defined(CAN2) +#define __HAL_RCC_CAN2_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_CAN2RST) +#endif /* CAN2 */ + +#if defined(USB) +#define __HAL_RCC_USB_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_USBFSRST) +#endif /* USB */ + +#define __HAL_RCC_PWR_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_PWRRST) + +#define __HAL_RCC_DAC1_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_DAC1RST) + +#define __HAL_RCC_OPAMP_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_OPAMPRST) + +#define __HAL_RCC_LPTIM1_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR1, RCC_APB1RSTR1_LPTIM1RST) + +#define __HAL_RCC_LPUART1_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR2, RCC_APB1RSTR2_LPUART1RST) + +#if defined(SWPMI1) +#define __HAL_RCC_SWPMI1_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR2, RCC_APB1RSTR2_SWPMI1RST) +#endif /* SWPMI1 */ + +#define __HAL_RCC_LPTIM2_RELEASE_RESET() CLEAR_BIT(RCC->APB1RSTR2, RCC_APB1RSTR2_LPTIM2RST) + +/** + * @} + */ + +/** @defgroup RCC_APB2_Force_Release_Reset APB2 Peripheral Force Release Reset + * @brief Force or release APB2 peripheral reset. + * @{ + */ +#define __HAL_RCC_APB2_FORCE_RESET() WRITE_REG(RCC->APB2RSTR, 0xFFFFFFFFU) + +#define __HAL_RCC_SYSCFG_FORCE_RESET() SET_BIT(RCC->APB2RSTR, RCC_APB2RSTR_SYSCFGRST) + +#if defined(SDMMC1) && defined(RCC_APB2RSTR_SDMMC1RST) +#define __HAL_RCC_SDMMC1_FORCE_RESET() SET_BIT(RCC->APB2RSTR, RCC_APB2RSTR_SDMMC1RST) +#endif /* SDMMC1 && RCC_APB2RSTR_SDMMC1RST */ + +#define __HAL_RCC_TIM1_FORCE_RESET() SET_BIT(RCC->APB2RSTR, RCC_APB2RSTR_TIM1RST) + +#define __HAL_RCC_SPI1_FORCE_RESET() SET_BIT(RCC->APB2RSTR, RCC_APB2RSTR_SPI1RST) + +#if defined(TIM8) +#define __HAL_RCC_TIM8_FORCE_RESET() SET_BIT(RCC->APB2RSTR, RCC_APB2RSTR_TIM8RST) +#endif /* TIM8 */ + +#define __HAL_RCC_USART1_FORCE_RESET() SET_BIT(RCC->APB2RSTR, RCC_APB2RSTR_USART1RST) + +#define __HAL_RCC_TIM15_FORCE_RESET() SET_BIT(RCC->APB2RSTR, RCC_APB2RSTR_TIM15RST) + +#define __HAL_RCC_TIM16_FORCE_RESET() SET_BIT(RCC->APB2RSTR, RCC_APB2RSTR_TIM16RST) + +#if defined(TIM17) +#define __HAL_RCC_TIM17_FORCE_RESET() SET_BIT(RCC->APB2RSTR, RCC_APB2RSTR_TIM17RST) +#endif /* TIM17 */ + +#define __HAL_RCC_SAI1_FORCE_RESET() SET_BIT(RCC->APB2RSTR, RCC_APB2RSTR_SAI1RST) + +#if defined(SAI2) +#define __HAL_RCC_SAI2_FORCE_RESET() SET_BIT(RCC->APB2RSTR, RCC_APB2RSTR_SAI2RST) +#endif /* SAI2 */ + +#if defined(DFSDM1_Filter0) +#define __HAL_RCC_DFSDM1_FORCE_RESET() SET_BIT(RCC->APB2RSTR, RCC_APB2RSTR_DFSDM1RST) +#endif /* DFSDM1_Filter0 */ + +#if defined(LTDC) +#define __HAL_RCC_LTDC_FORCE_RESET() SET_BIT(RCC->APB2RSTR, RCC_APB2RSTR_LTDCRST) +#endif /* LTDC */ + +#if defined(DSI) +#define __HAL_RCC_DSI_FORCE_RESET() SET_BIT(RCC->APB2RSTR, RCC_APB2RSTR_DSIRST) +#endif /* DSI */ + + +#define __HAL_RCC_APB2_RELEASE_RESET() WRITE_REG(RCC->APB2RSTR, 0x00000000U) + +#define __HAL_RCC_SYSCFG_RELEASE_RESET() CLEAR_BIT(RCC->APB2RSTR, RCC_APB2RSTR_SYSCFGRST) + +#if defined(SDMMC1) && defined(RCC_APB2RSTR_SDMMC1RST) +#define __HAL_RCC_SDMMC1_RELEASE_RESET() CLEAR_BIT(RCC->APB2RSTR, RCC_APB2RSTR_SDMMC1RST) +#endif /* SDMMC1 && RCC_APB2RSTR_SDMMC1RST */ + +#define __HAL_RCC_TIM1_RELEASE_RESET() CLEAR_BIT(RCC->APB2RSTR, RCC_APB2RSTR_TIM1RST) + +#define __HAL_RCC_SPI1_RELEASE_RESET() CLEAR_BIT(RCC->APB2RSTR, RCC_APB2RSTR_SPI1RST) + +#if defined(TIM8) +#define __HAL_RCC_TIM8_RELEASE_RESET() CLEAR_BIT(RCC->APB2RSTR, RCC_APB2RSTR_TIM8RST) +#endif /* TIM8 */ + +#define __HAL_RCC_USART1_RELEASE_RESET() CLEAR_BIT(RCC->APB2RSTR, RCC_APB2RSTR_USART1RST) + +#define __HAL_RCC_TIM15_RELEASE_RESET() CLEAR_BIT(RCC->APB2RSTR, RCC_APB2RSTR_TIM15RST) + +#define __HAL_RCC_TIM16_RELEASE_RESET() CLEAR_BIT(RCC->APB2RSTR, RCC_APB2RSTR_TIM16RST) + +#if defined(TIM17) +#define __HAL_RCC_TIM17_RELEASE_RESET() CLEAR_BIT(RCC->APB2RSTR, RCC_APB2RSTR_TIM17RST) +#endif /* TIM17 */ + +#define __HAL_RCC_SAI1_RELEASE_RESET() CLEAR_BIT(RCC->APB2RSTR, RCC_APB2RSTR_SAI1RST) + +#if defined(SAI2) +#define __HAL_RCC_SAI2_RELEASE_RESET() CLEAR_BIT(RCC->APB2RSTR, RCC_APB2RSTR_SAI2RST) +#endif /* SAI2 */ + +#if defined(DFSDM1_Filter0) +#define __HAL_RCC_DFSDM1_RELEASE_RESET() CLEAR_BIT(RCC->APB2RSTR, RCC_APB2RSTR_DFSDM1RST) +#endif /* DFSDM1_Filter0 */ + +#if defined(LTDC) +#define __HAL_RCC_LTDC_RELEASE_RESET() CLEAR_BIT(RCC->APB2RSTR, RCC_APB2RSTR_LTDCRST) +#endif /* LTDC */ + +#if defined(DSI) +#define __HAL_RCC_DSI_RELEASE_RESET() CLEAR_BIT(RCC->APB2RSTR, RCC_APB2RSTR_DSIRST) +#endif /* DSI */ + +/** + * @} + */ + +/** @defgroup RCC_AHB1_Clock_Sleep_Enable_Disable AHB1 Peripheral Clock Sleep Enable Disable + * @brief Enable or disable the AHB1 peripheral clock during Low Power (Sleep) mode. + * @note Peripheral clock gating in SLEEP mode can be used to further reduce + * power consumption. + * @note After wakeup from SLEEP mode, the peripheral clock is enabled again. + * @note By default, all peripheral clocks are enabled during SLEEP mode. + * @{ + */ + +#define __HAL_RCC_DMA1_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_DMA1SMEN) + +#define __HAL_RCC_DMA2_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_DMA2SMEN) + +#if defined(DMAMUX1) +#define __HAL_RCC_DMAMUX1_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_DMAMUX1SMEN) +#endif /* DMAMUX1 */ + +#define __HAL_RCC_FLASH_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_FLASHSMEN) + +#define __HAL_RCC_SRAM1_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_SRAM1SMEN) + +#define __HAL_RCC_CRC_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_CRCSMEN) + +#define __HAL_RCC_TSC_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_TSCSMEN) + +#if defined(DMA2D) +#define __HAL_RCC_DMA2D_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_DMA2DSMEN) +#endif /* DMA2D */ + +#if defined(GFXMMU) +#define __HAL_RCC_GFXMMU_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_GFXMMUSMEN) +#endif /* GFXMMU */ + + +#define __HAL_RCC_DMA1_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_DMA1SMEN) + +#define __HAL_RCC_DMA2_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_DMA2SMEN) + +#if defined(DMAMUX1) +#define __HAL_RCC_DMAMUX1_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_DMAMUX1SMEN) +#endif /* DMAMUX1 */ + +#define __HAL_RCC_FLASH_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_FLASHSMEN) + +#define __HAL_RCC_SRAM1_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_SRAM1SMEN) + +#define __HAL_RCC_CRC_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_CRCSMEN) + +#define __HAL_RCC_TSC_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_TSCSMEN) + +#if defined(DMA2D) +#define __HAL_RCC_DMA2D_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_DMA2DSMEN) +#endif /* DMA2D */ + +#if defined(GFXMMU) +#define __HAL_RCC_GFXMMU_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_GFXMMUSMEN) +#endif /* GFXMMU */ + +/** + * @} + */ + +/** @defgroup RCC_AHB2_Clock_Sleep_Enable_Disable AHB2 Peripheral Clock Sleep Enable Disable + * @brief Enable or disable the AHB2 peripheral clock during Low Power (Sleep) mode. + * @note Peripheral clock gating in SLEEP mode can be used to further reduce + * power consumption. + * @note After wakeup from SLEEP mode, the peripheral clock is enabled again. + * @note By default, all peripheral clocks are enabled during SLEEP mode. + * @{ + */ + +#define __HAL_RCC_GPIOA_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOASMEN) + +#define __HAL_RCC_GPIOB_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOBSMEN) + +#define __HAL_RCC_GPIOC_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOCSMEN) + +#if defined(GPIOD) +#define __HAL_RCC_GPIOD_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIODSMEN) +#endif /* GPIOD */ + +#if defined(GPIOE) +#define __HAL_RCC_GPIOE_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOESMEN) +#endif /* GPIOE */ + +#if defined(GPIOF) +#define __HAL_RCC_GPIOF_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOFSMEN) +#endif /* GPIOF */ + +#if defined(GPIOG) +#define __HAL_RCC_GPIOG_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOGSMEN) +#endif /* GPIOG */ + +#define __HAL_RCC_GPIOH_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOHSMEN) + +#if defined(GPIOI) +#define __HAL_RCC_GPIOI_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOISMEN) +#endif /* GPIOI */ + +#define __HAL_RCC_SRAM2_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_SRAM2SMEN) + +#if defined(SRAM3) +#define __HAL_RCC_SRAM3_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_SRAM3SMEN) +#endif /* SRAM3 */ + +#if defined(USB_OTG_FS) +#define __HAL_RCC_USB_OTG_FS_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_OTGFSSMEN) +#endif /* USB_OTG_FS */ + +#define __HAL_RCC_ADC_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_ADCSMEN) + +#if defined(DCMI) +#define __HAL_RCC_DCMI_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_DCMISMEN) +#endif /* DCMI */ + +#if defined(AES) +#define __HAL_RCC_AES_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_AESSMEN) +#endif /* AES */ + +#if defined(HASH) +#define __HAL_RCC_HASH_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_HASHSMEN) +#endif /* HASH */ + +#define __HAL_RCC_RNG_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_RNGSMEN) + +#if defined(OCTOSPIM) +#define __HAL_RCC_OSPIM_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_OSPIMSMEN) +#endif /* OCTOSPIM */ + +#if defined(SDMMC1) && defined(RCC_AHB2SMENR_SDMMC1SMEN) +#define __HAL_RCC_SDMMC1_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_SDMMC1SMEN) +#endif /* SDMMC1 && RCC_AHB2SMENR_SDMMC1SMEN */ + + +#define __HAL_RCC_GPIOA_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOASMEN) + +#define __HAL_RCC_GPIOB_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOBSMEN) + +#define __HAL_RCC_GPIOC_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOCSMEN) + +#if defined(GPIOD) +#define __HAL_RCC_GPIOD_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIODSMEN) +#endif /* GPIOD */ + +#if defined(GPIOE) +#define __HAL_RCC_GPIOE_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOESMEN) +#endif /* GPIOE */ + +#if defined(GPIOF) +#define __HAL_RCC_GPIOF_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOFSMEN) +#endif /* GPIOF */ + +#if defined(GPIOG) +#define __HAL_RCC_GPIOG_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOGSMEN) +#endif /* GPIOG */ + +#define __HAL_RCC_GPIOH_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOHSMEN) + +#if defined(GPIOI) +#define __HAL_RCC_GPIOI_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOISMEN) +#endif /* GPIOI */ + +#define __HAL_RCC_SRAM2_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_SRAM2SMEN) + +#if defined(SRAM3) +#define __HAL_RCC_SRAM3_IS_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_SRAM3SMEN) +#endif /* SRAM3 */ + +#if defined(USB_OTG_FS) +#define __HAL_RCC_USB_OTG_FS_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_OTGFSSMEN) +#endif /* USB_OTG_FS */ + +#define __HAL_RCC_ADC_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_ADCSMEN) + +#if defined(DCMI) +#define __HAL_RCC_DCMI_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_DCMISMEN) +#endif /* DCMI */ + +#if defined(AES) +#define __HAL_RCC_AES_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_AESSMEN) +#endif /* AES */ + +#if defined(HASH) +#define __HAL_RCC_HASH_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_HASHSMEN) +#endif /* HASH */ + +#define __HAL_RCC_RNG_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_RNGSMEN) + +#if defined(OCTOSPIM) +#define __HAL_RCC_OSPIM_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_OSPIMSMEN) +#endif /* OCTOSPIM */ + +#if defined(SDMMC1) && defined(RCC_AHB2SMENR_SDMMC1SMEN) +#define __HAL_RCC_SDMMC1_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_SDMMC1SMEN) +#endif /* SDMMC1 && RCC_AHB2SMENR_SDMMC1SMEN */ + +/** + * @} + */ + +/** @defgroup RCC_AHB3_Clock_Sleep_Enable_Disable AHB3 Peripheral Clock Sleep Enable Disable + * @brief Enable or disable the AHB3 peripheral clock during Low Power (Sleep) mode. + * @note Peripheral clock gating in SLEEP mode can be used to further reduce + * power consumption. + * @note After wakeup from SLEEP mode, the peripheral clock is enabled again. + * @note By default, all peripheral clocks are enabled during SLEEP mode. + * @{ + */ + +#if defined(QUADSPI) +#define __HAL_RCC_QSPI_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB3SMENR, RCC_AHB3SMENR_QSPISMEN) +#endif /* QUADSPI */ + +#if defined(OCTOSPI1) +#define __HAL_RCC_OSPI1_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB3SMENR, RCC_AHB3SMENR_OSPI1SMEN) +#endif /* OCTOSPI1 */ + +#if defined(OCTOSPI2) +#define __HAL_RCC_OSPI2_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB3SMENR, RCC_AHB3SMENR_OSPI2SMEN) +#endif /* OCTOSPI2 */ + +#if defined(FMC_BANK1) +#define __HAL_RCC_FMC_CLK_SLEEP_ENABLE() SET_BIT(RCC->AHB3SMENR, RCC_AHB3SMENR_FMCSMEN) +#endif /* FMC_BANK1 */ + +#if defined(QUADSPI) +#define __HAL_RCC_QSPI_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB3SMENR, RCC_AHB3SMENR_QSPISMEN) +#endif /* QUADSPI */ + +#if defined(OCTOSPI1) +#define __HAL_RCC_OSPI1_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB3SMENR, RCC_AHB3SMENR_OSPI1SMEN) +#endif /* OCTOSPI1 */ + +#if defined(OCTOSPI2) +#define __HAL_RCC_OSPI2_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB3SMENR, RCC_AHB3SMENR_OSPI2SMEN) +#endif /* OCTOSPI2 */ + +#if defined(FMC_BANK1) +#define __HAL_RCC_FMC_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->AHB3SMENR, RCC_AHB3SMENR_FMCSMEN) +#endif /* FMC_BANK1 */ + +/** + * @} + */ + +/** @defgroup RCC_APB1_Clock_Sleep_Enable_Disable APB1 Peripheral Clock Sleep Enable Disable + * @brief Enable or disable the APB1 peripheral clock during Low Power (Sleep) mode. + * @note Peripheral clock gating in SLEEP mode can be used to further reduce + * power consumption. + * @note After wakeup from SLEEP mode, the peripheral clock is enabled again. + * @note By default, all peripheral clocks are enabled during SLEEP mode. + * @{ + */ + +#define __HAL_RCC_TIM2_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM2SMEN) + +#if defined(TIM3) +#define __HAL_RCC_TIM3_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM3SMEN) +#endif /* TIM3 */ + +#if defined(TIM4) +#define __HAL_RCC_TIM4_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM4SMEN) +#endif /* TIM4 */ + +#if defined(TIM5) +#define __HAL_RCC_TIM5_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM5SMEN) +#endif /* TIM5 */ + +#define __HAL_RCC_TIM6_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM6SMEN) + +#define __HAL_RCC_TIM7_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM7SMEN) + +#if defined(LCD) +#define __HAL_RCC_LCD_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_LCDSMEN) +#endif /* LCD */ + +#if defined(RCC_APB1SMENR1_RTCAPBSMEN) +#define __HAL_RCC_RTCAPB_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_RTCAPBSMEN) +#endif /* RCC_APB1SMENR1_RTCAPBSMEN */ + +#define __HAL_RCC_WWDG_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_WWDGSMEN) + +#if defined(SPI2) +#define __HAL_RCC_SPI2_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_SPI2SMEN) +#endif /* SPI2 */ + +#define __HAL_RCC_SPI3_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_SPI3SMEN) + +#define __HAL_RCC_USART2_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_USART2SMEN) + +#if defined(USART3) +#define __HAL_RCC_USART3_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_USART3SMEN) +#endif /* USART3 */ + +#if defined(UART4) +#define __HAL_RCC_UART4_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_UART4SMEN) +#endif /* UART4 */ + +#if defined(UART5) +#define __HAL_RCC_UART5_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_UART5SMEN) +#endif /* UART5 */ + +#define __HAL_RCC_I2C1_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_I2C1SMEN) + +#if defined(I2C2) +#define __HAL_RCC_I2C2_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_I2C2SMEN) +#endif /* I2C2 */ + +#define __HAL_RCC_I2C3_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_I2C3SMEN) + +#if defined(I2C4) +#define __HAL_RCC_I2C4_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR2, RCC_APB1SMENR2_I2C4SMEN) +#endif /* I2C4 */ + +#if defined(CRS) +#define __HAL_RCC_CRS_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_CRSSMEN) +#endif /* CRS */ + +#define __HAL_RCC_CAN1_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_CAN1SMEN) + +#if defined(CAN2) +#define __HAL_RCC_CAN2_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_CAN2SMEN) +#endif /* CAN2 */ + +#if defined(USB) +#define __HAL_RCC_USB_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_USBFSSMEN) +#endif /* USB */ + +#define __HAL_RCC_PWR_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_PWRSMEN) + +#define __HAL_RCC_DAC1_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_DAC1SMEN) + +#define __HAL_RCC_OPAMP_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_OPAMPSMEN) + +#define __HAL_RCC_LPTIM1_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_LPTIM1SMEN) + +#define __HAL_RCC_LPUART1_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR2, RCC_APB1SMENR2_LPUART1SMEN) + +#if defined(SWPMI1) +#define __HAL_RCC_SWPMI1_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR2, RCC_APB1SMENR2_SWPMI1SMEN) +#endif /* SWPMI1 */ + +#define __HAL_RCC_LPTIM2_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB1SMENR2, RCC_APB1SMENR2_LPTIM2SMEN) + + +#define __HAL_RCC_TIM2_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM2SMEN) + +#if defined(TIM3) +#define __HAL_RCC_TIM3_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM3SMEN) +#endif /* TIM3 */ + +#if defined(TIM4) +#define __HAL_RCC_TIM4_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM4SMEN) +#endif /* TIM4 */ + +#if defined(TIM5) +#define __HAL_RCC_TIM5_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM5SMEN) +#endif /* TIM5 */ + +#define __HAL_RCC_TIM6_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM6SMEN) + +#define __HAL_RCC_TIM7_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM7SMEN) + +#if defined(LCD) +#define __HAL_RCC_LCD_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_LCDSMEN) +#endif /* LCD */ + +#if defined(RCC_APB1SMENR1_RTCAPBSMEN) +#define __HAL_RCC_RTCAPB_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_RTCAPBSMEN) +#endif /* RCC_APB1SMENR1_RTCAPBSMEN */ + +#define __HAL_RCC_WWDG_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_WWDGSMEN) + +#if defined(SPI2) +#define __HAL_RCC_SPI2_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_SPI2SMEN) +#endif /* SPI2 */ + +#define __HAL_RCC_SPI3_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_SPI3SMEN) + +#define __HAL_RCC_USART2_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_USART2SMEN) + +#if defined(USART3) +#define __HAL_RCC_USART3_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_USART3SMEN) +#endif /* USART3 */ + +#if defined(UART4) +#define __HAL_RCC_UART4_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_UART4SMEN) +#endif /* UART4 */ + +#if defined(UART5) +#define __HAL_RCC_UART5_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_UART5SMEN) +#endif /* UART5 */ + +#define __HAL_RCC_I2C1_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_I2C1SMEN) + +#if defined(I2C2) +#define __HAL_RCC_I2C2_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_I2C2SMEN) +#endif /* I2C2 */ + +#define __HAL_RCC_I2C3_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_I2C3SMEN) + +#if defined(I2C4) +#define __HAL_RCC_I2C4_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR2, RCC_APB1SMENR2_I2C4SMEN) +#endif /* I2C4 */ + +#if defined(CRS) +#define __HAL_RCC_CRS_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_CRSSMEN) +#endif /* CRS */ + +#define __HAL_RCC_CAN1_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_CAN1SMEN) + +#if defined(CAN2) +#define __HAL_RCC_CAN2_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_CAN2SMEN) +#endif /* CAN2 */ + +#if defined(USB) +#define __HAL_RCC_USB_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_USBFSSMEN) +#endif /* USB */ + +#define __HAL_RCC_PWR_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_PWRSMEN) + +#define __HAL_RCC_DAC1_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_DAC1SMEN) + +#define __HAL_RCC_OPAMP_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_OPAMPSMEN) + +#define __HAL_RCC_LPTIM1_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_LPTIM1SMEN) + +#define __HAL_RCC_LPUART1_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR2, RCC_APB1SMENR2_LPUART1SMEN) + +#if defined(SWPMI1) +#define __HAL_RCC_SWPMI1_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR2, RCC_APB1SMENR2_SWPMI1SMEN) +#endif /* SWPMI1 */ + +#define __HAL_RCC_LPTIM2_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB1SMENR2, RCC_APB1SMENR2_LPTIM2SMEN) + +/** + * @} + */ + +/** @defgroup RCC_APB2_Clock_Sleep_Enable_Disable APB2 Peripheral Clock Sleep Enable Disable + * @brief Enable or disable the APB2 peripheral clock during Low Power (Sleep) mode. + * @note Peripheral clock gating in SLEEP mode can be used to further reduce + * power consumption. + * @note After wakeup from SLEEP mode, the peripheral clock is enabled again. + * @note By default, all peripheral clocks are enabled during SLEEP mode. + * @{ + */ + +#define __HAL_RCC_SYSCFG_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SYSCFGSMEN) + +#if defined(SDMMC1) && defined(RCC_APB2SMENR_SDMMC1SMEN) +#define __HAL_RCC_SDMMC1_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SDMMC1SMEN) +#endif /* SDMMC1 && RCC_APB2SMENR_SDMMC1SMEN */ + +#define __HAL_RCC_TIM1_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM1SMEN) + +#define __HAL_RCC_SPI1_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SPI1SMEN) + +#if defined(TIM8) +#define __HAL_RCC_TIM8_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM8SMEN) +#endif /* TIM8 */ + +#define __HAL_RCC_USART1_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB2SMENR, RCC_APB2SMENR_USART1SMEN) + +#define __HAL_RCC_TIM15_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM15SMEN) + +#define __HAL_RCC_TIM16_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM16SMEN) + +#if defined(TIM17) +#define __HAL_RCC_TIM17_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM17SMEN) +#endif /* TIM17 */ + +#define __HAL_RCC_SAI1_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SAI1SMEN) + +#if defined(SAI2) +#define __HAL_RCC_SAI2_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SAI2SMEN) +#endif /* SAI2 */ + +#if defined(DFSDM1_Filter0) +#define __HAL_RCC_DFSDM1_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB2SMENR, RCC_APB2SMENR_DFSDM1SMEN) +#endif /* DFSDM1_Filter0 */ + +#if defined(LTDC) +#define __HAL_RCC_LTDC_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB2SMENR, RCC_APB2SMENR_LTDCSMEN) +#endif /* LTDC */ + +#if defined(DSI) +#define __HAL_RCC_DSI_CLK_SLEEP_ENABLE() SET_BIT(RCC->APB2SMENR, RCC_APB2SMENR_DSISMEN) +#endif /* DSI */ + + +#define __HAL_RCC_SYSCFG_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SYSCFGSMEN) + +#if defined(SDMMC1) && defined(RCC_APB2SMENR_SDMMC1SMEN) +#define __HAL_RCC_SDMMC1_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SDMMC1SMEN) +#endif /* SDMMC1 && RCC_APB2SMENR_SDMMC1SMEN */ + +#define __HAL_RCC_TIM1_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM1SMEN) + +#define __HAL_RCC_SPI1_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SPI1SMEN) + +#if defined(TIM8) +#define __HAL_RCC_TIM8_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM8SMEN) +#endif /* TIM8 */ + +#define __HAL_RCC_USART1_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB2SMENR, RCC_APB2SMENR_USART1SMEN) + +#define __HAL_RCC_TIM15_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM15SMEN) + +#define __HAL_RCC_TIM16_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM16SMEN) + +#if defined(TIM17) +#define __HAL_RCC_TIM17_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM17SMEN) +#endif /* TIM17 */ + +#define __HAL_RCC_SAI1_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SAI1SMEN) + +#if defined(SAI2) +#define __HAL_RCC_SAI2_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SAI2SMEN) +#endif /* SAI2 */ + +#if defined(DFSDM1_Filter0) +#define __HAL_RCC_DFSDM1_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB2SMENR, RCC_APB2SMENR_DFSDM1SMEN) +#endif /* DFSDM1_Filter0 */ + +#if defined(LTDC) +#define __HAL_RCC_LTDC_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB2SMENR, RCC_APB2SMENR_LTDCSMEN) +#endif /* LTDC */ + +#if defined(DSI) +#define __HAL_RCC_DSI_CLK_SLEEP_DISABLE() CLEAR_BIT(RCC->APB2SMENR, RCC_APB2SMENR_DSISMEN) +#endif /* DSI */ + +/** + * @} + */ + +/** @defgroup RCC_AHB1_Clock_Sleep_Enable_Disable_Status AHB1 Peripheral Clock Sleep Enabled or Disabled Status + * @brief Check whether the AHB1 peripheral clock during Low Power (Sleep) mode is enabled or not. + * @note Peripheral clock gating in SLEEP mode can be used to further reduce + * power consumption. + * @note After wakeup from SLEEP mode, the peripheral clock is enabled again. + * @note By default, all peripheral clocks are enabled during SLEEP mode. + * @{ + */ + +#define __HAL_RCC_DMA1_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_DMA1SMEN) != RESET) + +#define __HAL_RCC_DMA2_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_DMA2SMEN) != RESET) + +#if defined(DMAMUX1) +#define __HAL_RCC_DMAMUX1_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_DMAMUX1SMEN) != RESET) +#endif /* DMAMUX1 */ + +#define __HAL_RCC_FLASH_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_FLASHSMEN) != RESET) + +#define __HAL_RCC_SRAM1_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_SRAM1SMEN) != RESET) + +#define __HAL_RCC_CRC_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_CRCSMEN) != RESET) + +#define __HAL_RCC_TSC_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_TSCSMEN) != RESET) + +#if defined(DMA2D) +#define __HAL_RCC_DMA2D_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_DMA2DSMEN) != RESET) +#endif /* DMA2D */ + +#if defined(GFXMMU) +#define __HAL_RCC_GFXMMU_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_GFXMMUSMEN) != RESET) +#endif /* GFXMMU */ + + +#define __HAL_RCC_DMA1_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_DMA1SMEN) == RESET) + +#define __HAL_RCC_DMA2_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_DMA2SMEN) == RESET) + +#if defined(DMAMUX1) +#define __HAL_RCC_DMAMUX1_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_DMAMUX1SMEN) == RESET) +#endif /* DMAMUX1 */ + +#define __HAL_RCC_FLASH_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_FLASHSMEN) == RESET) + +#define __HAL_RCC_SRAM1_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_SRAM1SMEN) == RESET) + +#define __HAL_RCC_CRC_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_CRCSMEN) == RESET) + +#define __HAL_RCC_TSC_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_TSCSMEN) == RESET) + +#if defined(DMA2D) +#define __HAL_RCC_DMA2D_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_DMA2DSMEN) == RESET) +#endif /* DMA2D */ + +#if defined(GFXMMU) +#define __HAL_RCC_GFXMMU_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB1SMENR, RCC_AHB1SMENR_GFXMMUSMEN) == RESET) +#endif /* GFXMMU */ + +/** + * @} + */ + +/** @defgroup RCC_AHB2_Clock_Sleep_Enable_Disable_Status AHB2 Peripheral Clock Sleep Enabled or Disabled Status + * @brief Check whether the AHB2 peripheral clock during Low Power (Sleep) mode is enabled or not. + * @note Peripheral clock gating in SLEEP mode can be used to further reduce + * power consumption. + * @note After wakeup from SLEEP mode, the peripheral clock is enabled again. + * @note By default, all peripheral clocks are enabled during SLEEP mode. + * @{ + */ + +#define __HAL_RCC_GPIOA_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOASMEN) != RESET) + +#define __HAL_RCC_GPIOB_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOBSMEN) != RESET) + +#define __HAL_RCC_GPIOC_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOCSMEN) != RESET) + +#if defined(GPIOD) +#define __HAL_RCC_GPIOD_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIODSMEN) != RESET) +#endif /* GPIOD */ + +#if defined(GPIOE) +#define __HAL_RCC_GPIOE_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOESMEN) != RESET) +#endif /* GPIOE */ + +#if defined(GPIOF) +#define __HAL_RCC_GPIOF_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOFSMEN) != RESET) +#endif /* GPIOF */ + +#if defined(GPIOG) +#define __HAL_RCC_GPIOG_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOGSMEN) != RESET) +#endif /* GPIOG */ + +#define __HAL_RCC_GPIOH_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOHSMEN) != RESET) + +#if defined(GPIOI) +#define __HAL_RCC_GPIOI_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOISMEN) != RESET) +#endif /* GPIOI */ + +#define __HAL_RCC_SRAM2_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_SRAM2SMEN) != RESET) + +#if defined(SRAM3) +#define __HAL_RCC_SRAM3_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_SRAM3SMEN) != RESET) +#endif /* SRAM3 */ + +#if defined(USB_OTG_FS) +#define __HAL_RCC_USB_OTG_FS_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_OTGFSSMEN) != RESET) +#endif /* USB_OTG_FS */ + +#define __HAL_RCC_ADC_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_ADCSMEN) != RESET) + +#if defined(DCMI) +#define __HAL_RCC_DCMI_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_DCMISMEN) != RESET) +#endif /* DCMI */ + +#if defined(AES) +#define __HAL_RCC_AES_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_AESSMEN) != RESET) +#endif /* AES */ + +#if defined(HASH) +#define __HAL_RCC_HASH_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_HASHSMEN) != RESET) +#endif /* HASH */ + +#define __HAL_RCC_RNG_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_RNGSMEN) != RESET) + +#if defined(OCTOSPIM) +#define __HAL_RCC_OSPIM_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_OSPIMSMEN) != RESET) +#endif /* OCTOSPIM */ + +#if defined(SDMMC1) && defined(RCC_AHB2SMENR_SDMMC1SMEN) +#define __HAL_RCC_SDMMC1_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_SDMMC1SMEN) != RESET) +#endif /* SDMMC1 && RCC_AHB2SMENR_SDMMC1SMEN */ + + +#define __HAL_RCC_GPIOA_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOASMEN) == RESET) + +#define __HAL_RCC_GPIOB_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOBSMEN) == RESET) + +#define __HAL_RCC_GPIOC_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOCSMEN) == RESET) + +#if defined(GPIOD) +#define __HAL_RCC_GPIOD_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIODSMEN) == RESET) +#endif /* GPIOD */ + +#if defined(GPIOE) +#define __HAL_RCC_GPIOE_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOESMEN) == RESET) +#endif /* GPIOE */ + +#if defined(GPIOF) +#define __HAL_RCC_GPIOF_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOFSMEN) == RESET) +#endif /* GPIOF */ + +#if defined(GPIOG) +#define __HAL_RCC_GPIOG_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOGSMEN) == RESET) +#endif /* GPIOG */ + +#define __HAL_RCC_GPIOH_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOHSMEN) == RESET) + +#if defined(GPIOI) +#define __HAL_RCC_GPIOI_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_GPIOISMEN) == RESET) +#endif /* GPIOI */ + +#define __HAL_RCC_SRAM2_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_SRAM2SMEN) == RESET) + +#if defined(SRAM3) +#define __HAL_RCC_SRAM3_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_SRAM3SMEN) == RESET) +#endif /* SRAM3 */ + +#if defined(USB_OTG_FS) +#define __HAL_RCC_USB_OTG_FS_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_OTGFSSMEN) == RESET) +#endif /* USB_OTG_FS */ + +#define __HAL_RCC_ADC_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_ADCSMEN) == RESET) + +#if defined(DCMI) +#define __HAL_RCC_DCMI_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_DCMISMEN) == RESET) +#endif /* DCMI */ + +#if defined(AES) +#define __HAL_RCC_AES_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_AESSMEN) == RESET) +#endif /* AES */ + +#if defined(HASH) +#define __HAL_RCC_HASH_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_HASHSMEN) == RESET) +#endif /* HASH */ + +#define __HAL_RCC_RNG_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_RNGSMEN) == RESET) + +#if defined(OCTOSPIM) +#define __HAL_RCC_OSPIM_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_OSPIMSMEN) == RESET) +#endif /* OCTOSPIM */ + +#if defined(SDMMC1) && defined(RCC_AHB2SMENR_SDMMC1SMEN) +#define __HAL_RCC_SDMMC1_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB2SMENR, RCC_AHB2SMENR_SDMMC1SMEN) == RESET) +#endif /* SDMMC1 && RCC_AHB2SMENR_SDMMC1SMEN */ + +/** + * @} + */ + +/** @defgroup RCC_AHB3_Clock_Sleep_Enable_Disable_Status AHB3 Peripheral Clock Sleep Enabled or Disabled Status + * @brief Check whether the AHB3 peripheral clock during Low Power (Sleep) mode is enabled or not. + * @note Peripheral clock gating in SLEEP mode can be used to further reduce + * power consumption. + * @note After wakeup from SLEEP mode, the peripheral clock is enabled again. + * @note By default, all peripheral clocks are enabled during SLEEP mode. + * @{ + */ + +#if defined(QUADSPI) +#define __HAL_RCC_QSPI_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB3SMENR, RCC_AHB3SMENR_QSPISMEN) != RESET) +#endif /* QUADSPI */ + +#if defined(OCTOSPI1) +#define __HAL_RCC_OSPI1_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB3SMENR, RCC_AHB3SMENR_OSPI1SMEN) != RESET) +#endif /* OCTOSPI1 */ + +#if defined(OCTOSPI2) +#define __HAL_RCC_OSPI2_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB3SMENR, RCC_AHB3SMENR_OSPI2SMEN) != RESET) +#endif /* OCTOSPI2 */ + +#if defined(FMC_BANK1) +#define __HAL_RCC_FMC_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->AHB3SMENR, RCC_AHB3SMENR_FMCSMEN) != RESET) +#endif /* FMC_BANK1 */ + + +#if defined(QUADSPI) +#define __HAL_RCC_QSPI_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB3SMENR, RCC_AHB3SMENR_QSPISMEN) == RESET) +#endif /* QUADSPI */ + +#if defined(OCTOSPI1) +#define __HAL_RCC_OSPI1_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB3SMENR, RCC_AHB3SMENR_OSPI1SMEN) == RESET) +#endif /* OCTOSPI1 */ + +#if defined(OCTOSPI2) +#define __HAL_RCC_OSPI2_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB3SMENR, RCC_AHB3SMENR_OSPI2SMEN) == RESET) +#endif /* OCTOSPI2 */ + +#if defined(FMC_BANK1) +#define __HAL_RCC_FMC_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->AHB3SMENR, RCC_AHB3SMENR_FMCSMEN) == RESET) +#endif /* FMC_BANK1 */ + +/** + * @} + */ + +/** @defgroup RCC_APB1_Clock_Sleep_Enable_Disable_Status APB1 Peripheral Clock Sleep Enabled or Disabled Status + * @brief Check whether the APB1 peripheral clock during Low Power (Sleep) mode is enabled or not. + * @note Peripheral clock gating in SLEEP mode can be used to further reduce + * power consumption. + * @note After wakeup from SLEEP mode, the peripheral clock is enabled again. + * @note By default, all peripheral clocks are enabled during SLEEP mode. + * @{ + */ + +#define __HAL_RCC_TIM2_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM2SMEN) != RESET) + +#if defined(TIM3) +#define __HAL_RCC_TIM3_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM3SMEN) != RESET) +#endif /* TIM3 */ + +#if defined(TIM4) +#define __HAL_RCC_TIM4_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM4SMEN) != RESET) +#endif /* TIM4 */ + +#if defined(TIM5) +#define __HAL_RCC_TIM5_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM5SMEN) != RESET) +#endif /* TIM5 */ + +#define __HAL_RCC_TIM6_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM6SMEN) != RESET) + +#define __HAL_RCC_TIM7_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM7SMEN) != RESET) + +#if defined(LCD) +#define __HAL_RCC_LCD_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_LCDSMEN) != RESET) +#endif /* LCD */ + +#if defined(RCC_APB1SMENR1_RTCAPBSMEN) +#define __HAL_RCC_RTCAPB_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_RTCAPBSMEN) != RESET) +#endif /* RCC_APB1SMENR1_RTCAPBSMEN */ + +#define __HAL_RCC_WWDG_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_WWDGSMEN) != RESET) + +#if defined(SPI2) +#define __HAL_RCC_SPI2_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_SPI2SMEN) != RESET) +#endif /* SPI2 */ + +#define __HAL_RCC_SPI3_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_SPI3SMEN) != RESET) + +#define __HAL_RCC_USART2_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_USART2SMEN) != RESET) + +#if defined(USART3) +#define __HAL_RCC_USART3_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_USART3SMEN) != RESET) +#endif /* USART3 */ + +#if defined(UART4) +#define __HAL_RCC_UART4_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_UART4SMEN) != RESET) +#endif /* UART4 */ + +#if defined(UART5) +#define __HAL_RCC_UART5_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_UART5SMEN) != RESET) +#endif /* UART5 */ + +#define __HAL_RCC_I2C1_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_I2C1SMEN) != RESET) + +#if defined(I2C2) +#define __HAL_RCC_I2C2_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_I2C2SMEN) != RESET) +#endif /* I2C2 */ + +#define __HAL_RCC_I2C3_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_I2C3SMEN) != RESET) + +#if defined(I2C4) +#define __HAL_RCC_I2C4_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR2, RCC_APB1SMENR2_I2C4SMEN) != RESET) +#endif /* I2C4 */ + +#if defined(CRS) +#define __HAL_RCC_CRS_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_CRSSMEN) != RESET) +#endif /* CRS */ + +#define __HAL_RCC_CAN1_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_CAN1SMEN) != RESET) + +#if defined(CAN2) +#define __HAL_RCC_CAN2_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_CAN2SMEN) != RESET) +#endif /* CAN2 */ + +#if defined(USB) +#define __HAL_RCC_USB_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_USBFSSMEN) != RESET) +#endif /* USB */ + +#define __HAL_RCC_PWR_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_PWRSMEN) != RESET) + +#define __HAL_RCC_DAC1_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_DAC1SMEN) != RESET) + +#define __HAL_RCC_OPAMP_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_OPAMPSMEN) != RESET) + +#define __HAL_RCC_LPTIM1_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_LPTIM1SMEN) != RESET) + +#define __HAL_RCC_LPUART1_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR2, RCC_APB1SMENR2_LPUART1SMEN) != RESET) + +#if defined(SWPMI1) +#define __HAL_RCC_SWPMI1_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR2, RCC_APB1SMENR2_SWPMI1SMEN) != RESET) +#endif /* SWPMI1 */ + +#define __HAL_RCC_LPTIM2_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB1SMENR2, RCC_APB1SMENR2_LPTIM2SMEN) != RESET) + + +#define __HAL_RCC_TIM2_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM2SMEN) == RESET) + +#if defined(TIM3) +#define __HAL_RCC_TIM3_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM3SMEN) == RESET) +#endif /* TIM3 */ + +#if defined(TIM4) +#define __HAL_RCC_TIM4_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM4SMEN) == RESET) +#endif /* TIM4 */ + +#if defined(TIM5) +#define __HAL_RCC_TIM5_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM5SMEN) == RESET) +#endif /* TIM5 */ + +#define __HAL_RCC_TIM6_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM6SMEN) == RESET) + +#define __HAL_RCC_TIM7_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_TIM7SMEN) == RESET) + +#if defined(LCD) +#define __HAL_RCC_LCD_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_LCDSMEN) == RESET) +#endif /* LCD */ + +#if defined(RCC_APB1SMENR1_RTCAPBSMEN) +#define __HAL_RCC_RTCAPB_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_RTCAPBSMEN) == RESET) +#endif /* RCC_APB1SMENR1_RTCAPBSMEN */ + +#define __HAL_RCC_WWDG_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_WWDGSMEN) == RESET) + +#if defined(SPI2) +#define __HAL_RCC_SPI2_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_SPI2SMEN) == RESET) +#endif /* SPI2 */ + +#define __HAL_RCC_SPI3_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_SPI3SMEN) == RESET) + +#define __HAL_RCC_USART2_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_USART2SMEN) == RESET) + +#if defined(USART3) +#define __HAL_RCC_USART3_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_USART3SMEN) == RESET) +#endif /* USART3 */ + +#if defined(UART4) +#define __HAL_RCC_UART4_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_UART4SMEN) == RESET) +#endif /* UART4 */ + +#if defined(UART5) +#define __HAL_RCC_UART5_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_UART5SMEN) == RESET) +#endif /* UART5 */ + +#define __HAL_RCC_I2C1_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_I2C1SMEN) == RESET) + +#if defined(I2C2) +#define __HAL_RCC_I2C2_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_I2C2SMEN) == RESET) +#endif /* I2C2 */ + +#define __HAL_RCC_I2C3_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_I2C3SMEN) == RESET) + +#if defined(I2C4) +#define __HAL_RCC_I2C4_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR2, RCC_APB1SMENR2_I2C4SMEN) == RESET) +#endif /* I2C4 */ + +#if defined(CRS) +#define __HAL_RCC_CRS_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_CRSSMEN) == RESET) +#endif /* CRS */ + +#define __HAL_RCC_CAN1_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_CAN1SMEN) == RESET) + +#if defined(CAN2) +#define __HAL_RCC_CAN2_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_CAN2SMEN) == RESET) +#endif /* CAN2 */ + +#if defined(USB) +#define __HAL_RCC_USB_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_USBFSSMEN) == RESET) +#endif /* USB */ + +#define __HAL_RCC_PWR_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_PWRSMEN) == RESET) + +#define __HAL_RCC_DAC1_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_DAC1SMEN) == RESET) + +#define __HAL_RCC_OPAMP_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_OPAMPSMEN) == RESET) + +#define __HAL_RCC_LPTIM1_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR1, RCC_APB1SMENR1_LPTIM1SMEN) == RESET) + +#define __HAL_RCC_LPUART1_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR2, RCC_APB1SMENR2_LPUART1SMEN) == RESET) + +#if defined(SWPMI1) +#define __HAL_RCC_SWPMI1_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR2, RCC_APB1SMENR2_SWPMI1SMEN) == RESET) +#endif /* SWPMI1 */ + +#define __HAL_RCC_LPTIM2_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB1SMENR2, RCC_APB1SMENR2_LPTIM2SMEN) == RESET) + +/** + * @} + */ + +/** @defgroup RCC_APB2_Clock_Sleep_Enable_Disable_Status APB2 Peripheral Clock Sleep Enabled or Disabled Status + * @brief Check whether the APB2 peripheral clock during Low Power (Sleep) mode is enabled or not. + * @note Peripheral clock gating in SLEEP mode can be used to further reduce + * power consumption. + * @note After wakeup from SLEEP mode, the peripheral clock is enabled again. + * @note By default, all peripheral clocks are enabled during SLEEP mode. + * @{ + */ + +#define __HAL_RCC_SYSCFG_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SYSCFGSMEN) != RESET) + +#if defined(SDMMC1) && defined(RCC_APB2SMENR_SDMMC1SMEN) +#define __HAL_RCC_SDMMC1_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SDMMC1SMEN) != RESET) +#endif /* SDMMC1 && RCC_APB2SMENR_SDMMC1SMEN */ + +#define __HAL_RCC_TIM1_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM1SMEN) != RESET) + +#define __HAL_RCC_SPI1_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SPI1SMEN) != RESET) + +#if defined(TIM8) +#define __HAL_RCC_TIM8_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM8SMEN) != RESET) +#endif /* TIM8 */ + +#define __HAL_RCC_USART1_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_USART1SMEN) != RESET) + +#define __HAL_RCC_TIM15_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM15SMEN) != RESET) + +#define __HAL_RCC_TIM16_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM16SMEN) != RESET) + +#if defined(TIM17) +#define __HAL_RCC_TIM17_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM17SMEN) != RESET) +#endif /* TIM17 */ + +#define __HAL_RCC_SAI1_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SAI1SMEN) != RESET) + +#if defined(SAI2) +#define __HAL_RCC_SAI2_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SAI2SMEN) != RESET) +#endif /* SAI2 */ + +#if defined(DFSDM1_Filter0) +#define __HAL_RCC_DFSDM1_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_DFSDM1SMEN) != RESET) +#endif /* DFSDM1_Filter0 */ + +#if defined(LTDC) +#define __HAL_RCC_LTDC_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_LTDCSMEN) != RESET) +#endif /* LTDC */ + +#if defined(DSI) +#define __HAL_RCC_DSI_IS_CLK_SLEEP_ENABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_DSISMEN) != RESET) +#endif /* DSI */ + + +#define __HAL_RCC_SYSCFG_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SYSCFGSMEN) == RESET) + +#if defined(SDMMC1) && defined(RCC_APB2SMENR_SDMMC1SMEN) +#define __HAL_RCC_SDMMC1_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SDMMC1SMEN) == RESET) +#endif /* SDMMC1 && RCC_APB2SMENR_SDMMC1SMEN */ + +#define __HAL_RCC_TIM1_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM1SMEN) == RESET) + +#define __HAL_RCC_SPI1_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SPI1SMEN) == RESET) + +#if defined(TIM8) +#define __HAL_RCC_TIM8_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM8SMEN) == RESET) +#endif /* TIM8 */ + +#define __HAL_RCC_USART1_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_USART1SMEN) == RESET) + +#define __HAL_RCC_TIM15_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM15SMEN) == RESET) + +#define __HAL_RCC_TIM16_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM16SMEN) == RESET) + +#if defined(TIM17) +#define __HAL_RCC_TIM17_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_TIM17SMEN) == RESET) +#endif /* TIM17 */ + +#define __HAL_RCC_SAI1_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SAI1SMEN) == RESET) + +#if defined(SAI2) +#define __HAL_RCC_SAI2_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_SAI2SMEN) == RESET) +#endif /* SAI2 */ + +#if defined(DFSDM1_Filter0) +#define __HAL_RCC_DFSDM1_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_DFSDM1SMEN) == RESET) +#endif /* DFSDM1_Filter0 */ + +#if defined(LTDC) +#define __HAL_RCC_LTDC_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_LTDCSMEN) == RESET) +#endif /* LTDC */ + +#if defined(DSI) +#define __HAL_RCC_DSI_IS_CLK_SLEEP_DISABLED() (READ_BIT(RCC->APB2SMENR, RCC_APB2SMENR_DSISMEN) == RESET) +#endif /* DSI */ + +/** + * @} + */ + +/** @defgroup RCC_Backup_Domain_Reset RCC Backup Domain Reset + * @{ + */ + +/** @brief Macros to force or release the Backup domain reset. + * @note This function resets the RTC peripheral (including the backup registers) + * and the RTC clock source selection in RCC_CSR register. + * @note The BKPSRAM is not affected by this reset. + * @retval None + */ +#define __HAL_RCC_BACKUPRESET_FORCE() SET_BIT(RCC->BDCR, RCC_BDCR_BDRST) + +#define __HAL_RCC_BACKUPRESET_RELEASE() CLEAR_BIT(RCC->BDCR, RCC_BDCR_BDRST) + +/** + * @} + */ + +/** @defgroup RCC_RTC_Clock_Configuration RCC RTC Clock Configuration + * @{ + */ + +/** @brief Macros to enable or disable the RTC clock. + * @note As the RTC is in the Backup domain and write access is denied to + * this domain after reset, you have to enable write access using + * HAL_PWR_EnableBkUpAccess() function before to configure the RTC + * (to be done once after reset). + * @note These macros must be used after the RTC clock source was selected. + * @retval None + */ +#define __HAL_RCC_RTC_ENABLE() SET_BIT(RCC->BDCR, RCC_BDCR_RTCEN) + +#define __HAL_RCC_RTC_DISABLE() CLEAR_BIT(RCC->BDCR, RCC_BDCR_RTCEN) + +/** + * @} + */ + +/** @brief Macros to enable or disable the Internal High Speed 16MHz oscillator (HSI). + * @note The HSI is stopped by hardware when entering STOP and STANDBY modes. + * It is used (enabled by hardware) as system clock source after startup + * from Reset, wakeup from STOP and STANDBY mode, or in case of failure + * of the HSE used directly or indirectly as system clock (if the Clock + * Security System CSS is enabled). + * @note HSI can not be stopped if it is used as system clock source. In this case, + * you have to select another source of the system clock then stop the HSI. + * @note After enabling the HSI, the application software should wait on HSIRDY + * flag to be set indicating that HSI clock is stable and can be used as + * system clock source. + * This parameter can be: ENABLE or DISABLE. + * @note When the HSI is stopped, HSIRDY flag goes low after 6 HSI oscillator + * clock cycles. + * @retval None + */ +#define __HAL_RCC_HSI_ENABLE() SET_BIT(RCC->CR, RCC_CR_HSION) + +#define __HAL_RCC_HSI_DISABLE() CLEAR_BIT(RCC->CR, RCC_CR_HSION) + +/** @brief Macro to adjust the Internal High Speed 16MHz oscillator (HSI) calibration value. + * @note The calibration is used to compensate for the variations in voltage + * and temperature that influence the frequency of the internal HSI RC. + * @param __HSICALIBRATIONVALUE__ specifies the calibration trimming value + * (default is RCC_HSICALIBRATION_DEFAULT). + * This parameter must be a number between 0 and 0x1F (STM32L43x/STM32L44x/STM32L47x/STM32L48x) or 0x7F (for other devices). + * @retval None + */ +#define __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(__HSICALIBRATIONVALUE__) \ + MODIFY_REG(RCC->ICSCR, RCC_ICSCR_HSITRIM, (__HSICALIBRATIONVALUE__) << RCC_ICSCR_HSITRIM_Pos) + +/** + * @brief Macros to enable or disable the wakeup the Internal High Speed oscillator (HSI) + * in parallel to the Internal Multi Speed oscillator (MSI) used at system wakeup. + * @note The enable of this function has not effect on the HSION bit. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +#define __HAL_RCC_HSIAUTOMATIC_START_ENABLE() SET_BIT(RCC->CR, RCC_CR_HSIASFS) + +#define __HAL_RCC_HSIAUTOMATIC_START_DISABLE() CLEAR_BIT(RCC->CR, RCC_CR_HSIASFS) + +/** + * @brief Macros to enable or disable the force of the Internal High Speed oscillator (HSI) + * in STOP mode to be quickly available as kernel clock for USARTs and I2Cs. + * @note Keeping the HSI ON in STOP mode allows to avoid slowing down the communication + * speed because of the HSI startup time. + * @note The enable of this function has not effect on the HSION bit. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +#define __HAL_RCC_HSISTOP_ENABLE() SET_BIT(RCC->CR, RCC_CR_HSIKERON) + +#define __HAL_RCC_HSISTOP_DISABLE() CLEAR_BIT(RCC->CR, RCC_CR_HSIKERON) + +/** + * @brief Macros to enable or disable the Internal Multi Speed oscillator (MSI). + * @note The MSI is stopped by hardware when entering STOP and STANDBY modes. + * It is used (enabled by hardware) as system clock source after + * startup from Reset, wakeup from STOP and STANDBY mode, or in case + * of failure of the HSE used directly or indirectly as system clock + * (if the Clock Security System CSS is enabled). + * @note MSI can not be stopped if it is used as system clock source. + * In this case, you have to select another source of the system + * clock then stop the MSI. + * @note After enabling the MSI, the application software should wait on + * MSIRDY flag to be set indicating that MSI clock is stable and can + * be used as system clock source. + * @note When the MSI is stopped, MSIRDY flag goes low after 6 MSI oscillator + * clock cycles. + * @retval None + */ +#define __HAL_RCC_MSI_ENABLE() SET_BIT(RCC->CR, RCC_CR_MSION) + +#define __HAL_RCC_MSI_DISABLE() CLEAR_BIT(RCC->CR, RCC_CR_MSION) + +/** @brief Macro Adjusts the Internal Multi Speed oscillator (MSI) calibration value. + * @note The calibration is used to compensate for the variations in voltage + * and temperature that influence the frequency of the internal MSI RC. + * Refer to the Application Note AN3300 for more details on how to + * calibrate the MSI. + * @param __MSICALIBRATIONVALUE__ specifies the calibration trimming value + * (default is RCC_MSICALIBRATION_DEFAULT). + * This parameter must be a number between 0 and 255. + * @retval None + */ +#define __HAL_RCC_MSI_CALIBRATIONVALUE_ADJUST(__MSICALIBRATIONVALUE__) \ + MODIFY_REG(RCC->ICSCR, RCC_ICSCR_MSITRIM, (__MSICALIBRATIONVALUE__) << RCC_ICSCR_MSITRIM_Pos) + +/** + * @brief Macro configures the Internal Multi Speed oscillator (MSI) clock range in run mode + * @note After restart from Reset , the MSI clock is around 4 MHz. + * After stop the startup clock can be MSI (at any of its possible + * frequencies, the one that was used before entering stop mode) or HSI. + * After Standby its frequency can be selected between 4 possible values + * (1, 2, 4 or 8 MHz). + * @note MSIRANGE can be modified when MSI is OFF (MSION=0) or when MSI is ready + * (MSIRDY=1). + * @note The MSI clock range after reset can be modified on the fly. + * @param __MSIRANGEVALUE__ specifies the MSI clock range. + * This parameter must be one of the following values: + * @arg @ref RCC_MSIRANGE_0 MSI clock is around 100 KHz + * @arg @ref RCC_MSIRANGE_1 MSI clock is around 200 KHz + * @arg @ref RCC_MSIRANGE_2 MSI clock is around 400 KHz + * @arg @ref RCC_MSIRANGE_3 MSI clock is around 800 KHz + * @arg @ref RCC_MSIRANGE_4 MSI clock is around 1 MHz + * @arg @ref RCC_MSIRANGE_5 MSI clock is around 2 MHz + * @arg @ref RCC_MSIRANGE_6 MSI clock is around 4 MHz (default after Reset) + * @arg @ref RCC_MSIRANGE_7 MSI clock is around 8 MHz + * @arg @ref RCC_MSIRANGE_8 MSI clock is around 16 MHz + * @arg @ref RCC_MSIRANGE_9 MSI clock is around 24 MHz + * @arg @ref RCC_MSIRANGE_10 MSI clock is around 32 MHz + * @arg @ref RCC_MSIRANGE_11 MSI clock is around 48 MHz + * @retval None + */ +#define __HAL_RCC_MSI_RANGE_CONFIG(__MSIRANGEVALUE__) \ + do { \ + SET_BIT(RCC->CR, RCC_CR_MSIRGSEL); \ + MODIFY_REG(RCC->CR, RCC_CR_MSIRANGE, (__MSIRANGEVALUE__)); \ + } while(0) + +/** + * @brief Macro configures the Internal Multi Speed oscillator (MSI) clock range after Standby mode + * After Standby its frequency can be selected between 4 possible values (1, 2, 4 or 8 MHz). + * @param __MSIRANGEVALUE__ specifies the MSI clock range. + * This parameter must be one of the following values: + * @arg @ref RCC_MSIRANGE_4 MSI clock is around 1 MHz + * @arg @ref RCC_MSIRANGE_5 MSI clock is around 2 MHz + * @arg @ref RCC_MSIRANGE_6 MSI clock is around 4 MHz (default after Reset) + * @arg @ref RCC_MSIRANGE_7 MSI clock is around 8 MHz + * @retval None + */ +#define __HAL_RCC_MSI_STANDBY_RANGE_CONFIG(__MSIRANGEVALUE__) \ + MODIFY_REG(RCC->CSR, RCC_CSR_MSISRANGE, (__MSIRANGEVALUE__) << 4U) + +/** @brief Macro to get the Internal Multi Speed oscillator (MSI) clock range in run mode + * @retval MSI clock range. + * This parameter must be one of the following values: + * @arg @ref RCC_MSIRANGE_0 MSI clock is around 100 KHz + * @arg @ref RCC_MSIRANGE_1 MSI clock is around 200 KHz + * @arg @ref RCC_MSIRANGE_2 MSI clock is around 400 KHz + * @arg @ref RCC_MSIRANGE_3 MSI clock is around 800 KHz + * @arg @ref RCC_MSIRANGE_4 MSI clock is around 1 MHz + * @arg @ref RCC_MSIRANGE_5 MSI clock is around 2 MHz + * @arg @ref RCC_MSIRANGE_6 MSI clock is around 4 MHz (default after Reset) + * @arg @ref RCC_MSIRANGE_7 MSI clock is around 8 MHz + * @arg @ref RCC_MSIRANGE_8 MSI clock is around 16 MHz + * @arg @ref RCC_MSIRANGE_9 MSI clock is around 24 MHz + * @arg @ref RCC_MSIRANGE_10 MSI clock is around 32 MHz + * @arg @ref RCC_MSIRANGE_11 MSI clock is around 48 MHz + */ +#define __HAL_RCC_GET_MSI_RANGE() \ + ((READ_BIT(RCC->CR, RCC_CR_MSIRGSEL) != RESET) ? \ + READ_BIT(RCC->CR, RCC_CR_MSIRANGE) : \ + READ_BIT(RCC->CSR, RCC_CSR_MSISRANGE) >> 4U) + +/** @brief Macros to enable or disable the Internal Low Speed oscillator (LSI). + * @note After enabling the LSI, the application software should wait on + * LSIRDY flag to be set indicating that LSI clock is stable and can + * be used to clock the IWDG and/or the RTC. + * @note LSI can not be disabled if the IWDG is running. + * @note When the LSI is stopped, LSIRDY flag goes low after 6 LSI oscillator + * clock cycles. + * @retval None + */ +#define __HAL_RCC_LSI_ENABLE() SET_BIT(RCC->CSR, RCC_CSR_LSION) + +#define __HAL_RCC_LSI_DISABLE() CLEAR_BIT(RCC->CSR, RCC_CSR_LSION) + +/** + * @brief Macro to configure the External High Speed oscillator (HSE). + * @note Transition HSE Bypass to HSE On and HSE On to HSE Bypass are not + * supported by this macro. User should request a transition to HSE Off + * first and then HSE On or HSE Bypass. + * @note After enabling the HSE (RCC_HSE_ON or RCC_HSE_Bypass), the application + * software should wait on HSERDY flag to be set indicating that HSE clock + * is stable and can be used to clock the PLL and/or system clock. + * @note HSE state can not be changed if it is used directly or through the + * PLL as system clock. In this case, you have to select another source + * of the system clock then change the HSE state (ex. disable it). + * @note The HSE is stopped by hardware when entering STOP and STANDBY modes. + * @note This function reset the CSSON bit, so if the clock security system(CSS) + * was previously enabled you have to enable it again after calling this + * function. + * @param __STATE__ specifies the new state of the HSE. + * This parameter can be one of the following values: + * @arg @ref RCC_HSE_OFF Turn OFF the HSE oscillator, HSERDY flag goes low after + * 6 HSE oscillator clock cycles. + * @arg @ref RCC_HSE_ON Turn ON the HSE oscillator. + * @arg @ref RCC_HSE_BYPASS HSE oscillator bypassed with external clock. + * @retval None + */ +#define __HAL_RCC_HSE_CONFIG(__STATE__) \ + do { \ + if((__STATE__) == RCC_HSE_ON) \ + { \ + SET_BIT(RCC->CR, RCC_CR_HSEON); \ + } \ + else if((__STATE__) == RCC_HSE_BYPASS) \ + { \ + SET_BIT(RCC->CR, RCC_CR_HSEBYP); \ + SET_BIT(RCC->CR, RCC_CR_HSEON); \ + } \ + else \ + { \ + CLEAR_BIT(RCC->CR, RCC_CR_HSEON); \ + CLEAR_BIT(RCC->CR, RCC_CR_HSEBYP); \ + } \ + } while(0) + +/** + * @brief Macro to configure the External Low Speed oscillator (LSE). + * @note Transitions LSE Bypass to LSE On and LSE On to LSE Bypass are not + * supported by this macro. User should request a transition to LSE Off + * first and then LSE On or LSE Bypass. + * @note As the LSE is in the Backup domain and write access is denied to + * this domain after reset, you have to enable write access using + * HAL_PWR_EnableBkUpAccess() function before to configure the LSE + * (to be done once after reset). + * @note After enabling the LSE (RCC_LSE_ON or RCC_LSE_BYPASS), the application + * software should wait on LSERDY flag to be set indicating that LSE clock + * is stable and can be used to clock the RTC. + * @param __STATE__ specifies the new state of the LSE. + * This parameter can be one of the following values: + * @arg @ref RCC_LSE_OFF Turn OFF the LSE oscillator, LSERDY flag goes low after + * 6 LSE oscillator clock cycles. + * @arg @ref RCC_LSE_ON Turn ON the LSE oscillator. + * @arg @ref RCC_LSE_BYPASS LSE oscillator bypassed with external clock. + * @retval None + */ +#define __HAL_RCC_LSE_CONFIG(__STATE__) \ + do { \ + if((__STATE__) == RCC_LSE_ON) \ + { \ + SET_BIT(RCC->BDCR, RCC_BDCR_LSEON); \ + } \ + else if((__STATE__) == RCC_LSE_BYPASS) \ + { \ + SET_BIT(RCC->BDCR, RCC_BDCR_LSEBYP); \ + SET_BIT(RCC->BDCR, RCC_BDCR_LSEON); \ + } \ + else \ + { \ + CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSEON); \ + CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSEBYP); \ + } \ + } while(0) + +#if defined(RCC_HSI48_SUPPORT) + +/** @brief Macros to enable or disable the Internal High Speed 48MHz oscillator (HSI48). + * @note The HSI48 is stopped by hardware when entering STOP and STANDBY modes. + * @note After enabling the HSI48, the application software should wait on HSI48RDY + * flag to be set indicating that HSI48 clock is stable. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +#define __HAL_RCC_HSI48_ENABLE() SET_BIT(RCC->CRRCR, RCC_CRRCR_HSI48ON) + +#define __HAL_RCC_HSI48_DISABLE() CLEAR_BIT(RCC->CRRCR, RCC_CRRCR_HSI48ON) + +#endif /* RCC_HSI48_SUPPORT */ + +/** @brief Macros to configure the RTC clock (RTCCLK). + * @note As the RTC clock configuration bits are in the Backup domain and write + * access is denied to this domain after reset, you have to enable write + * access using the Power Backup Access macro before to configure + * the RTC clock source (to be done once after reset). + * @note Once the RTC clock is configured it cannot be changed unless the + * Backup domain is reset using __HAL_RCC_BACKUPRESET_FORCE() macro, or by + * a Power On Reset (POR). + * + * @param __RTC_CLKSOURCE__ specifies the RTC clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_RTCCLKSOURCE_NONE No clock selected as RTC clock. + * @arg @ref RCC_RTCCLKSOURCE_LSE LSE selected as RTC clock. + * @arg @ref RCC_RTCCLKSOURCE_LSI LSI selected as RTC clock. + * @arg @ref RCC_RTCCLKSOURCE_HSE_DIV32 HSE clock divided by 32 selected + * + * @note If the LSE or LSI is used as RTC clock source, the RTC continues to + * work in STOP and STANDBY modes, and can be used as wakeup source. + * However, when the HSE clock is used as RTC clock source, the RTC + * cannot be used in STOP and STANDBY modes. + * @note The maximum input clock frequency for RTC is 1MHz (when using HSE as + * RTC clock source). + * @retval None + */ +#define __HAL_RCC_RTC_CONFIG(__RTC_CLKSOURCE__) \ + MODIFY_REG( RCC->BDCR, RCC_BDCR_RTCSEL, (__RTC_CLKSOURCE__)) + + +/** @brief Macro to get the RTC clock source. + * @retval The returned value can be one of the following: + * @arg @ref RCC_RTCCLKSOURCE_NONE No clock selected as RTC clock. + * @arg @ref RCC_RTCCLKSOURCE_LSE LSE selected as RTC clock. + * @arg @ref RCC_RTCCLKSOURCE_LSI LSI selected as RTC clock. + * @arg @ref RCC_RTCCLKSOURCE_HSE_DIV32 HSE clock divided by 32 selected + */ +#define __HAL_RCC_GET_RTC_SOURCE() (READ_BIT(RCC->BDCR, RCC_BDCR_RTCSEL)) + +/** @brief Macros to enable or disable the main PLL. + * @note After enabling the main PLL, the application software should wait on + * PLLRDY flag to be set indicating that PLL clock is stable and can + * be used as system clock source. + * @note The main PLL can not be disabled if it is used as system clock source + * @note The main PLL is disabled by hardware when entering STOP and STANDBY modes. + * @retval None + */ +#define __HAL_RCC_PLL_ENABLE() SET_BIT(RCC->CR, RCC_CR_PLLON) + +#define __HAL_RCC_PLL_DISABLE() CLEAR_BIT(RCC->CR, RCC_CR_PLLON) + +/** @brief Macro to configure the PLL clock source. + * @note This function must be used only when the main PLL is disabled. + * @param __PLLSOURCE__ specifies the PLL entry clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_PLLSOURCE_NONE No clock selected as PLL clock entry + * @arg @ref RCC_PLLSOURCE_MSI MSI oscillator clock selected as PLL clock entry + * @arg @ref RCC_PLLSOURCE_HSI HSI oscillator clock selected as PLL clock entry + * @arg @ref RCC_PLLSOURCE_HSE HSE oscillator clock selected as PLL clock entry + * @note This clock source is common for the main PLL and audio PLL (PLLSAI1 and PLLSAI2). + * @retval None + * + */ +#define __HAL_RCC_PLL_PLLSOURCE_CONFIG(__PLLSOURCE__) \ + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, (__PLLSOURCE__)) + +/** @brief Macro to configure the PLL source division factor M. + * @note This function must be used only when the main PLL is disabled. + * @param __PLLM__ specifies the division factor for PLL VCO input clock + * This parameter must be a number between Min_Data = 1 and Max_Data = 16 on STM32L4Rx/STM32L4Sx devices. + * This parameter must be a number between Min_Data = 1 and Max_Data = 8 on other devices. + * @note You have to set the PLLM parameter correctly to ensure that the VCO input + * frequency ranges from 4 to 16 MHz. It is recommended to select a frequency + * of 16 MHz to limit PLL jitter. + * @retval None + * + */ +#define __HAL_RCC_PLL_PLLM_CONFIG(__PLLM__) \ + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLM, ((__PLLM__) - 1) << 4U) + +/** + * @brief Macro to configure the main PLL clock source, multiplication and division factors. + * @note This function must be used only when the main PLL is disabled. + * + * @param __PLLSOURCE__ specifies the PLL entry clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_PLLSOURCE_NONE No clock selected as PLL clock entry + * @arg @ref RCC_PLLSOURCE_MSI MSI oscillator clock selected as PLL clock entry + * @arg @ref RCC_PLLSOURCE_HSI HSI oscillator clock selected as PLL clock entry + * @arg @ref RCC_PLLSOURCE_HSE HSE oscillator clock selected as PLL clock entry + * @note This clock source is common for the main PLL and audio PLL (PLLSAI1 and PLLSAI2). + * + * @param __PLLM__ specifies the division factor for PLL VCO input clock. + * This parameter must be a number between Min_Data = 1 and Max_Data = 16 on STM32L4Rx/STM32L4Sx devices. + * This parameter must be a number between Min_Data = 1 and Max_Data = 8 on other devices. + * @note You have to set the PLLM parameter correctly to ensure that the VCO input + * frequency ranges from 4 to 16 MHz. It is recommended to select a frequency + * of 16 MHz to limit PLL jitter. + * + * @param __PLLN__ specifies the multiplication factor for PLL VCO output clock. + * This parameter must be a number between 8 and 86. + * @note You have to set the PLLN parameter correctly to ensure that the VCO + * output frequency is between 64 and 344 MHz. + * + * @param __PLLP__ specifies the division factor for SAI clock. + * This parameter must be a number in the range (7 or 17) for STM32L47x/STM32L48x + * else (2 to 31). + * + * @param __PLLQ__ specifies the division factor for OTG FS, SDMMC1 and RNG clocks. + * This parameter must be in the range (2, 4, 6 or 8). + * @note If the USB OTG FS is used in your application, you have to set the + * PLLQ parameter correctly to have 48 MHz clock for the USB. However, + * the SDMMC1 and RNG need a frequency lower than or equal to 48 MHz to work + * correctly. + * @param __PLLR__ specifies the division factor for the main system clock. + * @note You have to set the PLLR parameter correctly to not exceed 80MHZ. + * This parameter must be in the range (2, 4, 6 or 8). + * @retval None + */ +#if defined(RCC_PLLP_DIV_2_31_SUPPORT) + +#define __HAL_RCC_PLL_CONFIG(__PLLSOURCE__, __PLLM__, __PLLN__, __PLLP__, __PLLQ__,__PLLR__ ) \ + (RCC->PLLCFGR = (uint32_t)(((__PLLM__) - 1U) << 4U) | (uint32_t)((__PLLN__) << 8U) | \ + (__PLLSOURCE__) | (uint32_t)((((__PLLQ__) >> 1U) - 1U) << 21U) | (uint32_t)((((__PLLR__) >> 1U) - 1U) << 25U) | \ + ((uint32_t)(__PLLP__) << 27U)) +#else + +#define __HAL_RCC_PLL_CONFIG(__PLLSOURCE__, __PLLM__, __PLLN__, __PLLP__, __PLLQ__,__PLLR__ ) \ + (RCC->PLLCFGR = (uint32_t)(((__PLLM__) - 1U) << 4U) | (uint32_t)((__PLLN__) << 8U) | \ + (uint32_t)(((__PLLP__) >> 4U ) << 17U) | \ + (__PLLSOURCE__) | (uint32_t)((((__PLLQ__) >> 1U) - 1U) << 21U) | (uint32_t)((((__PLLR__) >> 1U) - 1U) << 25U)) + +#endif /* RCC_PLLP_DIV_2_31_SUPPORT */ + +/** @brief Macro to get the oscillator used as PLL clock source. + * @retval The oscillator used as PLL clock source. The returned value can be one + * of the following: + * - RCC_PLLSOURCE_NONE: No oscillator is used as PLL clock source. + * - RCC_PLLSOURCE_MSI: MSI oscillator is used as PLL clock source. + * - RCC_PLLSOURCE_HSI: HSI oscillator is used as PLL clock source. + * - RCC_PLLSOURCE_HSE: HSE oscillator is used as PLL clock source. + */ +#define __HAL_RCC_GET_PLL_OSCSOURCE() (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC)) + +/** + * @brief Enable or disable each clock output (RCC_PLL_SYSCLK, RCC_PLL_48M1CLK, RCC_PLL_SAI3CLK) + * @note Enabling/disabling clock outputs RCC_PLL_SAI3CLK and RCC_PLL_48M1CLK can be done at anytime + * without the need to stop the PLL in order to save power. But RCC_PLL_SYSCLK cannot + * be stopped if used as System Clock. + * @param __PLLCLOCKOUT__ specifies the PLL clock to be output. + * This parameter can be one or a combination of the following values: + * @arg @ref RCC_PLL_SAI3CLK This clock is used to generate an accurate clock to achieve + * high-quality audio performance on SAI interface in case. + * @arg @ref RCC_PLL_48M1CLK This Clock is used to generate the clock for the USB OTG FS (48 MHz), + * the random analog generator (<=48 MHz) and the SDMMC1 (<= 48 MHz). + * @arg @ref RCC_PLL_SYSCLK This Clock is used to generate the high speed system clock (up to 80MHz) + * @retval None + */ +#define __HAL_RCC_PLLCLKOUT_ENABLE(__PLLCLOCKOUT__) SET_BIT(RCC->PLLCFGR, (__PLLCLOCKOUT__)) + +#define __HAL_RCC_PLLCLKOUT_DISABLE(__PLLCLOCKOUT__) CLEAR_BIT(RCC->PLLCFGR, (__PLLCLOCKOUT__)) + +/** + * @brief Get clock output enable status (RCC_PLL_SYSCLK, RCC_PLL_48M1CLK, RCC_PLL_SAI3CLK) + * @param __PLLCLOCKOUT__ specifies the output PLL clock to be checked. + * This parameter can be one of the following values: + * @arg @ref RCC_PLL_SAI3CLK This clock is used to generate an accurate clock to achieve + * high-quality audio performance on SAI interface in case. + * @arg @ref RCC_PLL_48M1CLK This Clock is used to generate the clock for the USB OTG FS (48 MHz), + * the random analog generator (<=48 MHz) and the SDMMC1 (<= 48 MHz). + * @arg @ref RCC_PLL_SYSCLK This Clock is used to generate the high speed system clock (up to 80MHz) + * @retval SET / RESET + */ +#define __HAL_RCC_GET_PLLCLKOUT_CONFIG(__PLLCLOCKOUT__) READ_BIT(RCC->PLLCFGR, (__PLLCLOCKOUT__)) + +/** + * @brief Macro to configure the system clock source. + * @param __SYSCLKSOURCE__ specifies the system clock source. + * This parameter can be one of the following values: + * - RCC_SYSCLKSOURCE_MSI: MSI oscillator is used as system clock source. + * - RCC_SYSCLKSOURCE_HSI: HSI oscillator is used as system clock source. + * - RCC_SYSCLKSOURCE_HSE: HSE oscillator is used as system clock source. + * - RCC_SYSCLKSOURCE_PLLCLK: PLL output is used as system clock source. + * @retval None + */ +#define __HAL_RCC_SYSCLK_CONFIG(__SYSCLKSOURCE__) \ + MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, (__SYSCLKSOURCE__)) + +/** @brief Macro to get the clock source used as system clock. + * @retval The clock source used as system clock. The returned value can be one + * of the following: + * - RCC_SYSCLKSOURCE_STATUS_MSI: MSI used as system clock. + * - RCC_SYSCLKSOURCE_STATUS_HSI: HSI used as system clock. + * - RCC_SYSCLKSOURCE_STATUS_HSE: HSE used as system clock. + * - RCC_SYSCLKSOURCE_STATUS_PLLCLK: PLL used as system clock. + */ +#define __HAL_RCC_GET_SYSCLK_SOURCE() (READ_BIT(RCC->CFGR, RCC_CFGR_SWS)) + +/** + * @brief Macro to configure the External Low Speed oscillator (LSE) drive capability. + * @note As the LSE is in the Backup domain and write access is denied to + * this domain after reset, you have to enable write access using + * HAL_PWR_EnableBkUpAccess() function before to configure the LSE + * (to be done once after reset). + * @param __LSEDRIVE__ specifies the new state of the LSE drive capability. + * This parameter can be one of the following values: + * @arg @ref RCC_LSEDRIVE_LOW LSE oscillator low drive capability. + * @arg @ref RCC_LSEDRIVE_MEDIUMLOW LSE oscillator medium low drive capability. + * @arg @ref RCC_LSEDRIVE_MEDIUMHIGH LSE oscillator medium high drive capability. + * @arg @ref RCC_LSEDRIVE_HIGH LSE oscillator high drive capability. + * @retval None + */ +#define __HAL_RCC_LSEDRIVE_CONFIG(__LSEDRIVE__) \ + MODIFY_REG(RCC->BDCR, RCC_BDCR_LSEDRV, (__LSEDRIVE__)) + +/** + * @brief Macro to configure the wake up from stop clock. + * @param __STOPWUCLK__ specifies the clock source used after wake up from stop. + * This parameter can be one of the following values: + * @arg @ref RCC_STOP_WAKEUPCLOCK_MSI MSI selected as system clock source + * @arg @ref RCC_STOP_WAKEUPCLOCK_HSI HSI selected as system clock source + * @retval None + */ +#define __HAL_RCC_WAKEUPSTOP_CLK_CONFIG(__STOPWUCLK__) \ + MODIFY_REG(RCC->CFGR, RCC_CFGR_STOPWUCK, (__STOPWUCLK__)) + + +/** @brief Macro to configure the MCO clock. + * @param __MCOCLKSOURCE__ specifies the MCO clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_MCO1SOURCE_NOCLOCK MCO output disabled + * @arg @ref RCC_MCO1SOURCE_SYSCLK System clock selected as MCO source + * @arg @ref RCC_MCO1SOURCE_MSI MSI clock selected as MCO source + * @arg @ref RCC_MCO1SOURCE_HSI HSI clock selected as MCO source + * @arg @ref RCC_MCO1SOURCE_HSE HSE clock selected as MCO sourcee + * @arg @ref RCC_MCO1SOURCE_PLLCLK Main PLL clock selected as MCO source + * @arg @ref RCC_MCO1SOURCE_LSI LSI clock selected as MCO source + * @arg @ref RCC_MCO1SOURCE_LSE LSE clock selected as MCO source + @if STM32L443xx + * @arg @ref RCC_MCO1SOURCE_HSI48 HSI48 clock selected as MCO source for devices with HSI48 + @endif + @if STM32L4A6xx + * @arg @ref RCC_MCO1SOURCE_HSI48 HSI48 clock selected as MCO source for devices with HSI48 + @endif + * @param __MCODIV__ specifies the MCO clock prescaler. + * This parameter can be one of the following values: + * @arg @ref RCC_MCODIV_1 MCO clock source is divided by 1 + * @arg @ref RCC_MCODIV_2 MCO clock source is divided by 2 + * @arg @ref RCC_MCODIV_4 MCO clock source is divided by 4 + * @arg @ref RCC_MCODIV_8 MCO clock source is divided by 8 + * @arg @ref RCC_MCODIV_16 MCO clock source is divided by 16 + */ +#define __HAL_RCC_MCO1_CONFIG(__MCOCLKSOURCE__, __MCODIV__) \ + MODIFY_REG(RCC->CFGR, (RCC_CFGR_MCOSEL | RCC_CFGR_MCOPRE), ((__MCOCLKSOURCE__) | (__MCODIV__))) + +/** @defgroup RCC_Flags_Interrupts_Management Flags Interrupts Management + * @brief macros to manage the specified RCC Flags and interrupts. + * @{ + */ + +/** @brief Enable RCC interrupt(s). + * @param __INTERRUPT__ specifies the RCC interrupt source(s) to be enabled. + * This parameter can be any combination of the following values: + * @arg @ref RCC_IT_LSIRDY LSI ready interrupt + * @arg @ref RCC_IT_LSERDY LSE ready interrupt + * @arg @ref RCC_IT_MSIRDY HSI ready interrupt + * @arg @ref RCC_IT_HSIRDY HSI ready interrupt + * @arg @ref RCC_IT_HSERDY HSE ready interrupt + * @arg @ref RCC_IT_PLLRDY Main PLL ready interrupt + * @arg @ref RCC_IT_PLLSAI1RDY PLLSAI1 ready interrupt + * @arg @ref RCC_IT_PLLSAI2RDY PLLSAI2 ready interrupt for devices with PLLSAI2 + * @arg @ref RCC_IT_LSECSS LSE Clock security system interrupt + @if STM32L443xx + * @arg @ref RCC_IT_HSI48RDY HSI48 ready interrupt for devices with HSI48 + @endif + @if STM32L4A6xx + * @arg @ref RCC_IT_HSI48RDY HSI48 ready interrupt for devices with HSI48 + @endif + * @retval None + */ +#define __HAL_RCC_ENABLE_IT(__INTERRUPT__) SET_BIT(RCC->CIER, (__INTERRUPT__)) + +/** @brief Disable RCC interrupt(s). + * @param __INTERRUPT__ specifies the RCC interrupt source(s) to be disabled. + * This parameter can be any combination of the following values: + * @arg @ref RCC_IT_LSIRDY LSI ready interrupt + * @arg @ref RCC_IT_LSERDY LSE ready interrupt + * @arg @ref RCC_IT_MSIRDY HSI ready interrupt + * @arg @ref RCC_IT_HSIRDY HSI ready interrupt + * @arg @ref RCC_IT_HSERDY HSE ready interrupt + * @arg @ref RCC_IT_PLLRDY Main PLL ready interrupt + * @arg @ref RCC_IT_PLLSAI1RDY PLLSAI1 ready interrupt + * @arg @ref RCC_IT_PLLSAI2RDY PLLSAI2 ready interrupt for devices with PLLSAI2 + * @arg @ref RCC_IT_LSECSS LSE Clock security system interrupt + @if STM32L443xx + * @arg @ref RCC_IT_HSI48RDY HSI48 ready interrupt for devices with HSI48 + @endif + @if STM32L4A6xx + * @arg @ref RCC_IT_HSI48RDY HSI48 ready interrupt for devices with HSI48 + @endif + * @retval None + */ +#define __HAL_RCC_DISABLE_IT(__INTERRUPT__) CLEAR_BIT(RCC->CIER, (__INTERRUPT__)) + +/** @brief Clear the RCC's interrupt pending bits. + * @param __INTERRUPT__ specifies the interrupt pending bit to clear. + * This parameter can be any combination of the following values: + * @arg @ref RCC_IT_LSIRDY LSI ready interrupt + * @arg @ref RCC_IT_LSERDY LSE ready interrupt + * @arg @ref RCC_IT_MSIRDY MSI ready interrupt + * @arg @ref RCC_IT_HSIRDY HSI ready interrupt + * @arg @ref RCC_IT_HSERDY HSE ready interrupt + * @arg @ref RCC_IT_PLLRDY Main PLL ready interrupt + * @arg @ref RCC_IT_PLLSAI1RDY PLLSAI1 ready interrupt + * @arg @ref RCC_IT_PLLSAI2RDY PLLSAI2 ready interrupt for devices with PLLSAI2 + * @arg @ref RCC_IT_CSS HSE Clock security system interrupt + * @arg @ref RCC_IT_LSECSS LSE Clock security system interrupt + @if STM32L443xx + * @arg @ref RCC_IT_HSI48RDY HSI48 ready interrupt for devices with HSI48 + @endif + @if STM32L4A6xx + * @arg @ref RCC_IT_HSI48RDY HSI48 ready interrupt for devices with HSI48 + @endif + * @retval None + */ +#define __HAL_RCC_CLEAR_IT(__INTERRUPT__) WRITE_REG(RCC->CICR, (__INTERRUPT__)) + +/** @brief Check whether the RCC interrupt has occurred or not. + * @param __INTERRUPT__ specifies the RCC interrupt source to check. + * This parameter can be one of the following values: + * @arg @ref RCC_IT_LSIRDY LSI ready interrupt + * @arg @ref RCC_IT_LSERDY LSE ready interrupt + * @arg @ref RCC_IT_MSIRDY MSI ready interrupt + * @arg @ref RCC_IT_HSIRDY HSI ready interrupt + * @arg @ref RCC_IT_HSERDY HSE ready interrupt + * @arg @ref RCC_IT_PLLRDY Main PLL ready interrupt + * @arg @ref RCC_IT_PLLSAI1RDY PLLSAI1 ready interrupt + * @arg @ref RCC_IT_PLLSAI2RDY PLLSAI2 ready interrupt for devices with PLLSAI2 + * @arg @ref RCC_IT_CSS HSE Clock security system interrupt + * @arg @ref RCC_IT_LSECSS LSE Clock security system interrupt + @if STM32L443xx + * @arg @ref RCC_IT_HSI48RDY HSI48 ready interrupt for devices with HSI48 + @endif + @if STM32L4A6xx + * @arg @ref RCC_IT_HSI48RDY HSI48 ready interrupt for devices with HSI48 + @endif + * @retval The new state of __INTERRUPT__ (TRUE or FALSE). + */ +#define __HAL_RCC_GET_IT(__INTERRUPT__) (READ_BIT(RCC->CIFR, (__INTERRUPT__)) == (__INTERRUPT__)) + +/** @brief Set RMVF bit to clear the reset flags. + * The reset flags are: RCC_FLAG_FWRRST, RCC_FLAG_OBLRST, RCC_FLAG_PINRST, RCC_FLAG_BORRST, + * RCC_FLAG_SFTRST, RCC_FLAG_IWDGRST, RCC_FLAG_WWDGRST and RCC_FLAG_LPWRRST. + * @retval None + */ +#define __HAL_RCC_CLEAR_RESET_FLAGS() SET_BIT(RCC->CSR, RCC_CSR_RMVF) + +/** @brief Check whether the selected RCC flag is set or not. + * @param __FLAG__ specifies the flag to check. + * This parameter can be one of the following values: + * @arg @ref RCC_FLAG_MSIRDY MSI oscillator clock ready + * @arg @ref RCC_FLAG_HSIRDY HSI oscillator clock ready + * @arg @ref RCC_FLAG_HSERDY HSE oscillator clock ready + * @arg @ref RCC_FLAG_PLLRDY Main PLL clock ready + * @arg @ref RCC_FLAG_PLLSAI1RDY PLLSAI1 clock ready + * @arg @ref RCC_FLAG_PLLSAI2RDY PLLSAI2 clock ready for devices with PLLSAI2 + @if STM32L443xx + * @arg @ref RCC_FLAG_HSI48RDY HSI48 clock ready for devices with HSI48 + @endif + @if STM32L4A6xx + * @arg @ref RCC_FLAG_HSI48RDY HSI48 clock ready for devices with HSI48 + @endif + * @arg @ref RCC_FLAG_LSERDY LSE oscillator clock ready + * @arg @ref RCC_FLAG_LSECSSD Clock security system failure on LSE oscillator detection + * @arg @ref RCC_FLAG_LSIRDY LSI oscillator clock ready + * @arg @ref RCC_FLAG_BORRST BOR reset + * @arg @ref RCC_FLAG_OBLRST OBLRST reset + * @arg @ref RCC_FLAG_PINRST Pin reset + * @arg @ref RCC_FLAG_FWRST FIREWALL reset + * @arg @ref RCC_FLAG_RMVF Remove reset Flag + * @arg @ref RCC_FLAG_SFTRST Software reset + * @arg @ref RCC_FLAG_IWDGRST Independent Watchdog reset + * @arg @ref RCC_FLAG_WWDGRST Window Watchdog reset + * @arg @ref RCC_FLAG_LPWRRST Low Power reset + * @retval The new state of __FLAG__ (TRUE or FALSE). + */ +#if defined(RCC_HSI48_SUPPORT) +#define __HAL_RCC_GET_FLAG(__FLAG__) (((((((__FLAG__) >> 5U) == 1U) ? RCC->CR : \ + ((((__FLAG__) >> 5U) == 4U) ? RCC->CRRCR : \ + ((((__FLAG__) >> 5U) == 2U) ? RCC->BDCR : \ + ((((__FLAG__) >> 5U) == 3U) ? RCC->CSR : RCC->CIFR)))) & \ + (1U << ((__FLAG__) & RCC_FLAG_MASK))) != RESET) ? 1U : 0U) +#else +#define __HAL_RCC_GET_FLAG(__FLAG__) (((((((__FLAG__) >> 5U) == 1U) ? RCC->CR : \ + ((((__FLAG__) >> 5U) == 2U) ? RCC->BDCR : \ + ((((__FLAG__) >> 5U) == 3U) ? RCC->CSR : RCC->CIFR))) & \ + (1U << ((__FLAG__) & RCC_FLAG_MASK))) != RESET) ? 1U : 0U) +#endif /* RCC_HSI48_SUPPORT */ + +/** + * @} + */ + +/** + * @} + */ + +/* Private constants ---------------------------------------------------------*/ +/** @defgroup RCC_Private_Constants RCC Private Constants + * @{ + */ +/* Defines used for Flags */ +#define CR_REG_INDEX 1U +#define BDCR_REG_INDEX 2U +#define CSR_REG_INDEX 3U +#if defined(RCC_HSI48_SUPPORT) +#define CRRCR_REG_INDEX 4U +#endif /* RCC_HSI48_SUPPORT */ + +#define RCC_FLAG_MASK 0x1FU +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @addtogroup RCC_Private_Macros + * @{ + */ + +#if defined(RCC_HSI48_SUPPORT) +#define IS_RCC_OSCILLATORTYPE(__OSCILLATOR__) (((__OSCILLATOR__) == RCC_OSCILLATORTYPE_NONE) || \ + (((__OSCILLATOR__) & RCC_OSCILLATORTYPE_HSE) == RCC_OSCILLATORTYPE_HSE) || \ + (((__OSCILLATOR__) & RCC_OSCILLATORTYPE_HSI) == RCC_OSCILLATORTYPE_HSI) || \ + (((__OSCILLATOR__) & RCC_OSCILLATORTYPE_HSI48) == RCC_OSCILLATORTYPE_HSI48) || \ + (((__OSCILLATOR__) & RCC_OSCILLATORTYPE_MSI) == RCC_OSCILLATORTYPE_MSI) || \ + (((__OSCILLATOR__) & RCC_OSCILLATORTYPE_LSI) == RCC_OSCILLATORTYPE_LSI) || \ + (((__OSCILLATOR__) & RCC_OSCILLATORTYPE_LSE) == RCC_OSCILLATORTYPE_LSE)) +#else +#define IS_RCC_OSCILLATORTYPE(__OSCILLATOR__) (((__OSCILLATOR__) == RCC_OSCILLATORTYPE_NONE) || \ + (((__OSCILLATOR__) & RCC_OSCILLATORTYPE_HSE) == RCC_OSCILLATORTYPE_HSE) || \ + (((__OSCILLATOR__) & RCC_OSCILLATORTYPE_HSI) == RCC_OSCILLATORTYPE_HSI) || \ + (((__OSCILLATOR__) & RCC_OSCILLATORTYPE_MSI) == RCC_OSCILLATORTYPE_MSI) || \ + (((__OSCILLATOR__) & RCC_OSCILLATORTYPE_LSI) == RCC_OSCILLATORTYPE_LSI) || \ + (((__OSCILLATOR__) & RCC_OSCILLATORTYPE_LSE) == RCC_OSCILLATORTYPE_LSE)) +#endif /* RCC_HSI48_SUPPORT */ + +#define IS_RCC_HSE(__HSE__) (((__HSE__) == RCC_HSE_OFF) || ((__HSE__) == RCC_HSE_ON) || \ + ((__HSE__) == RCC_HSE_BYPASS)) + +#define IS_RCC_LSE(__LSE__) (((__LSE__) == RCC_LSE_OFF) || ((__LSE__) == RCC_LSE_ON) || \ + ((__LSE__) == RCC_LSE_BYPASS)) + +#define IS_RCC_HSI(__HSI__) (((__HSI__) == RCC_HSI_OFF) || ((__HSI__) == RCC_HSI_ON)) + +#define IS_RCC_HSI_CALIBRATION_VALUE(__VALUE__) ((__VALUE__) <= (RCC_ICSCR_HSITRIM >> RCC_ICSCR_HSITRIM_Pos)) + +#define IS_RCC_LSI(__LSI__) (((__LSI__) == RCC_LSI_OFF) || ((__LSI__) == RCC_LSI_ON)) + +#define IS_RCC_MSI(__MSI__) (((__MSI__) == RCC_MSI_OFF) || ((__MSI__) == RCC_MSI_ON)) + +#define IS_RCC_MSICALIBRATION_VALUE(__VALUE__) ((__VALUE__) <= 255U) + +#if defined(RCC_HSI48_SUPPORT) +#define IS_RCC_HSI48(__HSI48__) (((__HSI48__) == RCC_HSI48_OFF) || ((__HSI48__) == RCC_HSI48_ON)) +#endif /* RCC_HSI48_SUPPORT */ + +#define IS_RCC_PLL(__PLL__) (((__PLL__) == RCC_PLL_NONE) ||((__PLL__) == RCC_PLL_OFF) || \ + ((__PLL__) == RCC_PLL_ON)) + +#define IS_RCC_PLLSOURCE(__SOURCE__) (((__SOURCE__) == RCC_PLLSOURCE_NONE) || \ + ((__SOURCE__) == RCC_PLLSOURCE_MSI) || \ + ((__SOURCE__) == RCC_PLLSOURCE_HSI) || \ + ((__SOURCE__) == RCC_PLLSOURCE_HSE)) + +#if defined(RCC_PLLM_DIV_1_16_SUPPORT) +#define IS_RCC_PLLM_VALUE(__VALUE__) ((1U <= (__VALUE__)) && ((__VALUE__) <= 16U)) +#else +#define IS_RCC_PLLM_VALUE(__VALUE__) ((1U <= (__VALUE__)) && ((__VALUE__) <= 8U)) +#endif /*RCC_PLLM_DIV_1_16_SUPPORT */ + +#define IS_RCC_PLLN_VALUE(__VALUE__) ((8U <= (__VALUE__)) && ((__VALUE__) <= 86U)) + +#if defined(RCC_PLLP_DIV_2_31_SUPPORT) +#define IS_RCC_PLLP_VALUE(__VALUE__) (((__VALUE__) >= 2U) && ((__VALUE__) <= 31U)) +#else +#define IS_RCC_PLLP_VALUE(__VALUE__) (((__VALUE__) == 7U) || ((__VALUE__) == 17U)) +#endif /*RCC_PLLP_DIV_2_31_SUPPORT */ + +#define IS_RCC_PLLQ_VALUE(__VALUE__) (((__VALUE__) == 2U) || ((__VALUE__) == 4U) || \ + ((__VALUE__) == 6U) || ((__VALUE__) == 8U)) + +#define IS_RCC_PLLR_VALUE(__VALUE__) (((__VALUE__) == 2U) || ((__VALUE__) == 4U) || \ + ((__VALUE__) == 6U) || ((__VALUE__) == 8U)) + +#define IS_RCC_PLLSAI1CLOCKOUT_VALUE(__VALUE__) (((((__VALUE__) & RCC_PLLSAI1_SAI1CLK) == RCC_PLLSAI1_SAI1CLK) || \ + (((__VALUE__) & RCC_PLLSAI1_48M2CLK) == RCC_PLLSAI1_48M2CLK) || \ + (((__VALUE__) & RCC_PLLSAI1_ADC1CLK) == RCC_PLLSAI1_ADC1CLK)) && \ + (((__VALUE__) & ~(RCC_PLLSAI1_SAI1CLK|RCC_PLLSAI1_48M2CLK|RCC_PLLSAI1_ADC1CLK)) == 0U)) + +#if defined(RCC_PLLSAI2_SUPPORT) +#if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || defined(STM32L496xx) || defined(STM32L4A6xx) +#define IS_RCC_PLLSAI2CLOCKOUT_VALUE(__VALUE__) (((((__VALUE__) & RCC_PLLSAI2_SAI2CLK) == RCC_PLLSAI2_SAI2CLK) || \ + (((__VALUE__) & RCC_PLLSAI2_ADC2CLK) == RCC_PLLSAI2_ADC2CLK)) && \ + (((__VALUE__) & ~(RCC_PLLSAI2_SAI2CLK|RCC_PLLSAI2_ADC2CLK)) == 0U)) +#elif defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +#define IS_RCC_PLLSAI2CLOCKOUT_VALUE(__VALUE__) (((((__VALUE__) & RCC_PLLSAI2_SAI2CLK) == RCC_PLLSAI2_SAI2CLK) || \ + (((__VALUE__) & RCC_PLLSAI2_DSICLK) == RCC_PLLSAI2_DSICLK) || \ + (((__VALUE__) & RCC_PLLSAI2_LTDCCLK) == RCC_PLLSAI2_LTDCCLK)) && \ + (((__VALUE__) & ~(RCC_PLLSAI2_SAI2CLK|RCC_PLLSAI2_DSICLK|RCC_PLLSAI2_LTDCCLK)) == 0U)) +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || STM32L496xx || STM32L4A6xx */ +#endif /* RCC_PLLSAI2_SUPPORT */ + +#define IS_RCC_MSI_CLOCK_RANGE(__RANGE__) (((__RANGE__) == RCC_MSIRANGE_0) || \ + ((__RANGE__) == RCC_MSIRANGE_1) || \ + ((__RANGE__) == RCC_MSIRANGE_2) || \ + ((__RANGE__) == RCC_MSIRANGE_3) || \ + ((__RANGE__) == RCC_MSIRANGE_4) || \ + ((__RANGE__) == RCC_MSIRANGE_5) || \ + ((__RANGE__) == RCC_MSIRANGE_6) || \ + ((__RANGE__) == RCC_MSIRANGE_7) || \ + ((__RANGE__) == RCC_MSIRANGE_8) || \ + ((__RANGE__) == RCC_MSIRANGE_9) || \ + ((__RANGE__) == RCC_MSIRANGE_10) || \ + ((__RANGE__) == RCC_MSIRANGE_11)) + +#define IS_RCC_MSI_STANDBY_CLOCK_RANGE(__RANGE__) (((__RANGE__) == RCC_MSIRANGE_4) || \ + ((__RANGE__) == RCC_MSIRANGE_5) || \ + ((__RANGE__) == RCC_MSIRANGE_6) || \ + ((__RANGE__) == RCC_MSIRANGE_7)) + +#define IS_RCC_CLOCKTYPE(__CLK__) ((1U <= (__CLK__)) && ((__CLK__) <= 15U)) + +#define IS_RCC_SYSCLKSOURCE(__SOURCE__) (((__SOURCE__) == RCC_SYSCLKSOURCE_MSI) || \ + ((__SOURCE__) == RCC_SYSCLKSOURCE_HSI) || \ + ((__SOURCE__) == RCC_SYSCLKSOURCE_HSE) || \ + ((__SOURCE__) == RCC_SYSCLKSOURCE_PLLCLK)) + +#define IS_RCC_HCLK(__HCLK__) (((__HCLK__) == RCC_SYSCLK_DIV1) || ((__HCLK__) == RCC_SYSCLK_DIV2) || \ + ((__HCLK__) == RCC_SYSCLK_DIV4) || ((__HCLK__) == RCC_SYSCLK_DIV8) || \ + ((__HCLK__) == RCC_SYSCLK_DIV16) || ((__HCLK__) == RCC_SYSCLK_DIV64) || \ + ((__HCLK__) == RCC_SYSCLK_DIV128) || ((__HCLK__) == RCC_SYSCLK_DIV256) || \ + ((__HCLK__) == RCC_SYSCLK_DIV512)) + +#define IS_RCC_PCLK(__PCLK__) (((__PCLK__) == RCC_HCLK_DIV1) || ((__PCLK__) == RCC_HCLK_DIV2) || \ + ((__PCLK__) == RCC_HCLK_DIV4) || ((__PCLK__) == RCC_HCLK_DIV8) || \ + ((__PCLK__) == RCC_HCLK_DIV16)) + +#define IS_RCC_RTCCLKSOURCE(__SOURCE__) (((__SOURCE__) == RCC_RTCCLKSOURCE_NONE) || \ + ((__SOURCE__) == RCC_RTCCLKSOURCE_LSE) || \ + ((__SOURCE__) == RCC_RTCCLKSOURCE_LSI) || \ + ((__SOURCE__) == RCC_RTCCLKSOURCE_HSE_DIV32)) + +#define IS_RCC_MCO(__MCOX__) ((__MCOX__) == RCC_MCO1) + +#if defined(RCC_HSI48_SUPPORT) +#define IS_RCC_MCO1SOURCE(__SOURCE__) (((__SOURCE__) == RCC_MCO1SOURCE_NOCLOCK) || \ + ((__SOURCE__) == RCC_MCO1SOURCE_SYSCLK) || \ + ((__SOURCE__) == RCC_MCO1SOURCE_MSI) || \ + ((__SOURCE__) == RCC_MCO1SOURCE_HSI) || \ + ((__SOURCE__) == RCC_MCO1SOURCE_HSE) || \ + ((__SOURCE__) == RCC_MCO1SOURCE_PLLCLK) || \ + ((__SOURCE__) == RCC_MCO1SOURCE_LSI) || \ + ((__SOURCE__) == RCC_MCO1SOURCE_LSE) || \ + ((__SOURCE__) == RCC_MCO1SOURCE_HSI48)) +#else +#define IS_RCC_MCO1SOURCE(__SOURCE__) (((__SOURCE__) == RCC_MCO1SOURCE_NOCLOCK) || \ + ((__SOURCE__) == RCC_MCO1SOURCE_SYSCLK) || \ + ((__SOURCE__) == RCC_MCO1SOURCE_MSI) || \ + ((__SOURCE__) == RCC_MCO1SOURCE_HSI) || \ + ((__SOURCE__) == RCC_MCO1SOURCE_HSE) || \ + ((__SOURCE__) == RCC_MCO1SOURCE_PLLCLK) || \ + ((__SOURCE__) == RCC_MCO1SOURCE_LSI) || \ + ((__SOURCE__) == RCC_MCO1SOURCE_LSE)) +#endif /* RCC_HSI48_SUPPORT */ + +#define IS_RCC_MCODIV(__DIV__) (((__DIV__) == RCC_MCODIV_1) || ((__DIV__) == RCC_MCODIV_2) || \ + ((__DIV__) == RCC_MCODIV_4) || ((__DIV__) == RCC_MCODIV_8) || \ + ((__DIV__) == RCC_MCODIV_16)) + +#define IS_RCC_LSE_DRIVE(__DRIVE__) (((__DRIVE__) == RCC_LSEDRIVE_LOW) || \ + ((__DRIVE__) == RCC_LSEDRIVE_MEDIUMLOW) || \ + ((__DRIVE__) == RCC_LSEDRIVE_MEDIUMHIGH) || \ + ((__DRIVE__) == RCC_LSEDRIVE_HIGH)) + +#define IS_RCC_STOP_WAKEUPCLOCK(__SOURCE__) (((__SOURCE__) == RCC_STOP_WAKEUPCLOCK_MSI) || \ + ((__SOURCE__) == RCC_STOP_WAKEUPCLOCK_HSI)) +/** + * @} + */ + +/* Include RCC HAL Extended module */ +#include "stm32l4xx_hal_rcc_ex.h" + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup RCC_Exported_Functions + * @{ + */ + + +/** @addtogroup RCC_Exported_Functions_Group1 + * @{ + */ + +/* Initialization and de-initialization functions ******************************/ +HAL_StatusTypeDef HAL_RCC_DeInit(void); +HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct); +HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, uint32_t FLatency); + +/** + * @} + */ + +/** @addtogroup RCC_Exported_Functions_Group2 + * @{ + */ + +/* Peripheral Control functions ************************************************/ +void HAL_RCC_MCOConfig(uint32_t RCC_MCOx, uint32_t RCC_MCOSource, uint32_t RCC_MCODiv); +void HAL_RCC_EnableCSS(void); +uint32_t HAL_RCC_GetSysClockFreq(void); +uint32_t HAL_RCC_GetHCLKFreq(void); +uint32_t HAL_RCC_GetPCLK1Freq(void); +uint32_t HAL_RCC_GetPCLK2Freq(void); +void HAL_RCC_GetOscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct); +void HAL_RCC_GetClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, uint32_t *pFLatency); +/* CSS NMI IRQ handler */ +void HAL_RCC_NMI_IRQHandler(void); +/* User Callbacks in non blocking mode (IT mode) */ +void HAL_RCC_CSSCallback(void); + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_HAL_RCC_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rcc_ex.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rcc_ex.h new file mode 100644 index 0000000..b0000a7 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rcc_ex.h @@ -0,0 +1,3018 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_rcc_ex.h + * @author MCD Application Team + * @brief Header file of RCC HAL Extended module. + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_RCC_EX_H +#define __STM32L4xx_HAL_RCC_EX_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup RCCEx + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ + +/** @defgroup RCCEx_Exported_Types RCCEx Exported Types + * @{ + */ + +/** + * @brief PLLSAI1 Clock structure definition + */ +typedef struct +{ + + uint32_t PLLSAI1Source; /*!< PLLSAI1Source: PLLSAI1 entry clock source. + This parameter must be a value of @ref RCC_PLL_Clock_Source */ + +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + uint32_t PLLSAI1M; /*!< PLLSAI1M: specifies the division factor for PLLSAI1 input clock. + This parameter must be a number between Min_Data = 1 and Max_Data = 16 */ +#else + uint32_t PLLSAI1M; /*!< PLLSAI1M: specifies the division factor for PLLSAI1 input clock. + This parameter must be a number between Min_Data = 1 and Max_Data = 8 */ +#endif + + uint32_t PLLSAI1N; /*!< PLLSAI1N: specifies the multiplication factor for PLLSAI1 VCO output clock. + This parameter must be a number between 8 and 86 or 127 depending on devices. */ + + uint32_t PLLSAI1P; /*!< PLLSAI1P: specifies the division factor for SAI clock. + This parameter must be a value of @ref RCC_PLLP_Clock_Divider */ + + uint32_t PLLSAI1Q; /*!< PLLSAI1Q: specifies the division factor for USB/RNG/SDMMC1 clock. + This parameter must be a value of @ref RCC_PLLQ_Clock_Divider */ + + uint32_t PLLSAI1R; /*!< PLLSAI1R: specifies the division factor for ADC clock. + This parameter must be a value of @ref RCC_PLLR_Clock_Divider */ + + uint32_t PLLSAI1ClockOut; /*!< PLLSAIClockOut: specifies PLLSAI1 output clock to be enabled. + This parameter must be a value of @ref RCC_PLLSAI1_Clock_Output */ +}RCC_PLLSAI1InitTypeDef; + +#if defined(RCC_PLLSAI2_SUPPORT) + +/** + * @brief PLLSAI2 Clock structure definition + */ +typedef struct +{ + + uint32_t PLLSAI2Source; /*!< PLLSAI2Source: PLLSAI2 entry clock source. + This parameter must be a value of @ref RCC_PLL_Clock_Source */ + +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + uint32_t PLLSAI2M; /*!< PLLSAI2M: specifies the division factor for PLLSAI2 input clock. + This parameter must be a number between Min_Data = 1 and Max_Data = 16 */ +#else + uint32_t PLLSAI2M; /*!< PLLSAI2M: specifies the division factor for PLLSAI2 input clock. + This parameter must be a number between Min_Data = 1 and Max_Data = 8 */ +#endif + + uint32_t PLLSAI2N; /*!< PLLSAI2N: specifies the multiplication factor for PLLSAI2 VCO output clock. + This parameter must be a number between 8 and 86 or 127 depending on devices. */ + + uint32_t PLLSAI2P; /*!< PLLSAI2P: specifies the division factor for SAI clock. + This parameter must be a value of @ref RCC_PLLP_Clock_Divider */ + +#if defined(RCC_PLLSAI2Q_DIV_SUPPORT) + uint32_t PLLSAI2Q; /*!< PLLSAI2Q: specifies the division factor for DSI clock. + This parameter must be a value of @ref RCC_PLLQ_Clock_Divider */ +#endif + + uint32_t PLLSAI2R; /*!< PLLSAI2R: specifies the division factor for ADC clock. + This parameter must be a value of @ref RCC_PLLR_Clock_Divider */ + + uint32_t PLLSAI2ClockOut; /*!< PLLSAIClockOut: specifies PLLSAI2 output clock to be enabled. + This parameter must be a value of @ref RCC_PLLSAI2_Clock_Output */ +}RCC_PLLSAI2InitTypeDef; + +#endif /* RCC_PLLSAI2_SUPPORT */ + +/** + * @brief RCC extended clocks structure definition + */ +typedef struct +{ + uint32_t PeriphClockSelection; /*!< The Extended Clock to be configured. + This parameter can be a value of @ref RCCEx_Periph_Clock_Selection */ + + RCC_PLLSAI1InitTypeDef PLLSAI1; /*!< PLLSAI1 structure parameters. + This parameter will be used only when PLLSAI1 is selected as Clock Source for SAI1, USB/RNG/SDMMC1 or ADC */ + +#if defined(RCC_PLLSAI2_SUPPORT) + + RCC_PLLSAI2InitTypeDef PLLSAI2; /*!< PLLSAI2 structure parameters. + This parameter will be used only when PLLSAI2 is selected as Clock Source for SAI2 or ADC */ + +#endif /* RCC_PLLSAI2_SUPPORT */ + + uint32_t Usart1ClockSelection; /*!< Specifies USART1 clock source. + This parameter can be a value of @ref RCCEx_USART1_Clock_Source */ + + uint32_t Usart2ClockSelection; /*!< Specifies USART2 clock source. + This parameter can be a value of @ref RCCEx_USART2_Clock_Source */ + +#if defined(USART3) + + uint32_t Usart3ClockSelection; /*!< Specifies USART3 clock source. + This parameter can be a value of @ref RCCEx_USART3_Clock_Source */ + +#endif /* USART3 */ + +#if defined(UART4) + + uint32_t Uart4ClockSelection; /*!< Specifies UART4 clock source. + This parameter can be a value of @ref RCCEx_UART4_Clock_Source */ + +#endif /* UART4 */ + +#if defined(UART5) + + uint32_t Uart5ClockSelection; /*!< Specifies UART5 clock source. + This parameter can be a value of @ref RCCEx_UART5_Clock_Source */ + +#endif /* UART5 */ + + uint32_t Lpuart1ClockSelection; /*!< Specifies LPUART1 clock source. + This parameter can be a value of @ref RCCEx_LPUART1_Clock_Source */ + + uint32_t I2c1ClockSelection; /*!< Specifies I2C1 clock source. + This parameter can be a value of @ref RCCEx_I2C1_Clock_Source */ + +#if defined(I2C2) + + uint32_t I2c2ClockSelection; /*!< Specifies I2C2 clock source. + This parameter can be a value of @ref RCCEx_I2C2_Clock_Source */ + +#endif /* I2C2 */ + + uint32_t I2c3ClockSelection; /*!< Specifies I2C3 clock source. + This parameter can be a value of @ref RCCEx_I2C3_Clock_Source */ + +#if defined(I2C4) + + uint32_t I2c4ClockSelection; /*!< Specifies I2C4 clock source. + This parameter can be a value of @ref RCCEx_I2C4_Clock_Source */ + +#endif /* I2C4 */ + + uint32_t Lptim1ClockSelection; /*!< Specifies LPTIM1 clock source. + This parameter can be a value of @ref RCCEx_LPTIM1_Clock_Source */ + + uint32_t Lptim2ClockSelection; /*!< Specifies LPTIM2 clock source. + This parameter can be a value of @ref RCCEx_LPTIM2_Clock_Source */ + + uint32_t Sai1ClockSelection; /*!< Specifies SAI1 clock source. + This parameter can be a value of @ref RCCEx_SAI1_Clock_Source */ + +#if defined(SAI2) + + uint32_t Sai2ClockSelection; /*!< Specifies SAI2 clock source. + This parameter can be a value of @ref RCCEx_SAI2_Clock_Source */ + +#endif /* SAI2 */ + +#if defined(USB_OTG_FS) || defined(USB) + + uint32_t UsbClockSelection; /*!< Specifies USB clock source (warning: same source for SDMMC1 and RNG). + This parameter can be a value of @ref RCCEx_USB_Clock_Source */ + +#endif /* USB_OTG_FS || USB */ + +#if defined(SDMMC1) + + uint32_t Sdmmc1ClockSelection; /*!< Specifies SDMMC1 clock source (warning: same source for USB and RNG). + This parameter can be a value of @ref RCCEx_SDMMC1_Clock_Source */ + +#endif /* SDMMC1 */ + + uint32_t RngClockSelection; /*!< Specifies RNG clock source (warning: same source for USB and SDMMC1). + This parameter can be a value of @ref RCCEx_RNG_Clock_Source */ + + uint32_t AdcClockSelection; /*!< Specifies ADC interface clock source. + This parameter can be a value of @ref RCCEx_ADC_Clock_Source */ + +#if defined(SWPMI1) + + uint32_t Swpmi1ClockSelection; /*!< Specifies SWPMI1 clock source. + This parameter can be a value of @ref RCCEx_SWPMI1_Clock_Source */ + +#endif /* SWPMI1 */ + +#if defined(DFSDM1_Filter0) + + uint32_t Dfsdm1ClockSelection; /*!< Specifies DFSDM1 clock source. + This parameter can be a value of @ref RCCEx_DFSDM1_Clock_Source */ + +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + uint32_t Dfsdm1AudioClockSelection; /*!< Specifies DFSDM1 audio clock source. + This parameter can be a value of @ref RCCEx_DFSDM1_Audio_Clock_Source */ + +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#endif /* DFSDM1_Filter0 */ + +#if defined(LTDC) + + uint32_t LtdcClockSelection; /*!< Specifies LTDC clock source. + This parameter can be a value of @ref RCCEx_LTDC_Clock_Source */ + +#endif /* LTDC */ + +#if defined(DSI) + + uint32_t DsiClockSelection; /*!< Specifies DSI clock source. + This parameter can be a value of @ref RCCEx_DSI_Clock_Source */ + +#endif /* DSI */ + +#if defined(OCTOSPI1) || defined(OCTOSPI2) + + uint32_t OspiClockSelection; /*!< Specifies OctoSPI clock source. + This parameter can be a value of @ref RCCEx_OSPI_Clock_Source */ + +#endif + + uint32_t RTCClockSelection; /*!< Specifies RTC clock source. + This parameter can be a value of @ref RCC_RTC_Clock_Source */ +}RCC_PeriphCLKInitTypeDef; + +#if defined(CRS) + +/** + * @brief RCC_CRS Init structure definition + */ +typedef struct +{ + uint32_t Prescaler; /*!< Specifies the division factor of the SYNC signal. + This parameter can be a value of @ref RCCEx_CRS_SynchroDivider */ + + uint32_t Source; /*!< Specifies the SYNC signal source. + This parameter can be a value of @ref RCCEx_CRS_SynchroSource */ + + uint32_t Polarity; /*!< Specifies the input polarity for the SYNC signal source. + This parameter can be a value of @ref RCCEx_CRS_SynchroPolarity */ + + uint32_t ReloadValue; /*!< Specifies the value to be loaded in the frequency error counter with each SYNC event. + It can be calculated in using macro __HAL_RCC_CRS_RELOADVALUE_CALCULATE(__FTARGET__, __FSYNC__) + This parameter must be a number between 0 and 0xFFFF or a value of @ref RCCEx_CRS_ReloadValueDefault .*/ + + uint32_t ErrorLimitValue; /*!< Specifies the value to be used to evaluate the captured frequency error value. + This parameter must be a number between 0 and 0xFF or a value of @ref RCCEx_CRS_ErrorLimitDefault */ + + uint32_t HSI48CalibrationValue; /*!< Specifies a user-programmable trimming value to the HSI48 oscillator. + This parameter must be a number between 0 and 0x3F or a value of @ref RCCEx_CRS_HSI48CalibrationDefault */ + +}RCC_CRSInitTypeDef; + +/** + * @brief RCC_CRS Synchronization structure definition + */ +typedef struct +{ + uint32_t ReloadValue; /*!< Specifies the value loaded in the Counter reload value. + This parameter must be a number between 0 and 0xFFFF */ + + uint32_t HSI48CalibrationValue; /*!< Specifies value loaded in HSI48 oscillator smooth trimming. + This parameter must be a number between 0 and 0x3F */ + + uint32_t FreqErrorCapture; /*!< Specifies the value loaded in the .FECAP, the frequency error counter + value latched in the time of the last SYNC event. + This parameter must be a number between 0 and 0xFFFF */ + + uint32_t FreqErrorDirection; /*!< Specifies the value loaded in the .FEDIR, the counting direction of the + frequency error counter latched in the time of the last SYNC event. + It shows whether the actual frequency is below or above the target. + This parameter must be a value of @ref RCCEx_CRS_FreqErrorDirection*/ + +}RCC_CRSSynchroInfoTypeDef; + +#endif /* CRS */ +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup RCCEx_Exported_Constants RCCEx Exported Constants + * @{ + */ + +/** @defgroup RCCEx_LSCO_Clock_Source Low Speed Clock Source + * @{ + */ +#define RCC_LSCOSOURCE_LSI 0x00000000U /*!< LSI selection for low speed clock output */ +#define RCC_LSCOSOURCE_LSE RCC_BDCR_LSCOSEL /*!< LSE selection for low speed clock output */ +/** + * @} + */ + +/** @defgroup RCCEx_Periph_Clock_Selection Periph Clock Selection + * @{ + */ +#define RCC_PERIPHCLK_USART1 0x00000001U +#define RCC_PERIPHCLK_USART2 0x00000002U +#if defined(USART3) +#define RCC_PERIPHCLK_USART3 0x00000004U +#endif +#if defined(UART4) +#define RCC_PERIPHCLK_UART4 0x00000008U +#endif +#if defined(UART5) +#define RCC_PERIPHCLK_UART5 0x00000010U +#endif +#define RCC_PERIPHCLK_LPUART1 0x00000020U +#define RCC_PERIPHCLK_I2C1 0x00000040U +#if defined(I2C2) +#define RCC_PERIPHCLK_I2C2 0x00000080U +#endif +#define RCC_PERIPHCLK_I2C3 0x00000100U +#define RCC_PERIPHCLK_LPTIM1 0x00000200U +#define RCC_PERIPHCLK_LPTIM2 0x00000400U +#define RCC_PERIPHCLK_SAI1 0x00000800U +#if defined(SAI2) +#define RCC_PERIPHCLK_SAI2 0x00001000U +#endif +#if defined(USB_OTG_FS) || defined(USB) +#define RCC_PERIPHCLK_USB 0x00002000U +#endif +#define RCC_PERIPHCLK_ADC 0x00004000U +#if defined(SWPMI1) +#define RCC_PERIPHCLK_SWPMI1 0x00008000U +#endif +#if defined(DFSDM1_Filter0) +#define RCC_PERIPHCLK_DFSDM1 0x00010000U +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +#define RCC_PERIPHCLK_DFSDM1AUDIO 0x00200000U +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ +#endif +#define RCC_PERIPHCLK_RTC 0x00020000U +#define RCC_PERIPHCLK_RNG 0x00040000U +#if defined(SDMMC1) +#define RCC_PERIPHCLK_SDMMC1 0x00080000U +#endif +#if defined(I2C4) +#define RCC_PERIPHCLK_I2C4 0x00100000U +#endif +#if defined(LTDC) +#define RCC_PERIPHCLK_LTDC 0x00400000U +#endif +#if defined(DSI) +#define RCC_PERIPHCLK_DSI 0x00800000U +#endif +#if defined(OCTOSPI1) || defined(OCTOSPI2) +#define RCC_PERIPHCLK_OSPI 0x01000000U +#endif +/** + * @} + */ + + +/** @defgroup RCCEx_USART1_Clock_Source USART1 Clock Source + * @{ + */ +#define RCC_USART1CLKSOURCE_PCLK2 0x00000000U +#define RCC_USART1CLKSOURCE_SYSCLK RCC_CCIPR_USART1SEL_0 +#define RCC_USART1CLKSOURCE_HSI RCC_CCIPR_USART1SEL_1 +#define RCC_USART1CLKSOURCE_LSE (RCC_CCIPR_USART1SEL_0 | RCC_CCIPR_USART1SEL_1) +/** + * @} + */ + +/** @defgroup RCCEx_USART2_Clock_Source USART2 Clock Source + * @{ + */ +#define RCC_USART2CLKSOURCE_PCLK1 0x00000000U +#define RCC_USART2CLKSOURCE_SYSCLK RCC_CCIPR_USART2SEL_0 +#define RCC_USART2CLKSOURCE_HSI RCC_CCIPR_USART2SEL_1 +#define RCC_USART2CLKSOURCE_LSE (RCC_CCIPR_USART2SEL_0 | RCC_CCIPR_USART2SEL_1) +/** + * @} + */ + +#if defined(USART3) +/** @defgroup RCCEx_USART3_Clock_Source USART3 Clock Source + * @{ + */ +#define RCC_USART3CLKSOURCE_PCLK1 0x00000000U +#define RCC_USART3CLKSOURCE_SYSCLK RCC_CCIPR_USART3SEL_0 +#define RCC_USART3CLKSOURCE_HSI RCC_CCIPR_USART3SEL_1 +#define RCC_USART3CLKSOURCE_LSE (RCC_CCIPR_USART3SEL_0 | RCC_CCIPR_USART3SEL_1) +/** + * @} + */ +#endif /* USART3 */ + +#if defined(UART4) +/** @defgroup RCCEx_UART4_Clock_Source UART4 Clock Source + * @{ + */ +#define RCC_UART4CLKSOURCE_PCLK1 0x00000000U +#define RCC_UART4CLKSOURCE_SYSCLK RCC_CCIPR_UART4SEL_0 +#define RCC_UART4CLKSOURCE_HSI RCC_CCIPR_UART4SEL_1 +#define RCC_UART4CLKSOURCE_LSE (RCC_CCIPR_UART4SEL_0 | RCC_CCIPR_UART4SEL_1) +/** + * @} + */ +#endif /* UART4 */ + +#if defined(UART5) +/** @defgroup RCCEx_UART5_Clock_Source UART5 Clock Source + * @{ + */ +#define RCC_UART5CLKSOURCE_PCLK1 0x00000000U +#define RCC_UART5CLKSOURCE_SYSCLK RCC_CCIPR_UART5SEL_0 +#define RCC_UART5CLKSOURCE_HSI RCC_CCIPR_UART5SEL_1 +#define RCC_UART5CLKSOURCE_LSE (RCC_CCIPR_UART5SEL_0 | RCC_CCIPR_UART5SEL_1) +/** + * @} + */ +#endif /* UART5 */ + +/** @defgroup RCCEx_LPUART1_Clock_Source LPUART1 Clock Source + * @{ + */ +#define RCC_LPUART1CLKSOURCE_PCLK1 0x00000000U +#define RCC_LPUART1CLKSOURCE_SYSCLK RCC_CCIPR_LPUART1SEL_0 +#define RCC_LPUART1CLKSOURCE_HSI RCC_CCIPR_LPUART1SEL_1 +#define RCC_LPUART1CLKSOURCE_LSE (RCC_CCIPR_LPUART1SEL_0 | RCC_CCIPR_LPUART1SEL_1) +/** + * @} + */ + +/** @defgroup RCCEx_I2C1_Clock_Source I2C1 Clock Source + * @{ + */ +#define RCC_I2C1CLKSOURCE_PCLK1 0x00000000U +#define RCC_I2C1CLKSOURCE_SYSCLK RCC_CCIPR_I2C1SEL_0 +#define RCC_I2C1CLKSOURCE_HSI RCC_CCIPR_I2C1SEL_1 +/** + * @} + */ + +#if defined(I2C2) +/** @defgroup RCCEx_I2C2_Clock_Source I2C2 Clock Source + * @{ + */ +#define RCC_I2C2CLKSOURCE_PCLK1 0x00000000U +#define RCC_I2C2CLKSOURCE_SYSCLK RCC_CCIPR_I2C2SEL_0 +#define RCC_I2C2CLKSOURCE_HSI RCC_CCIPR_I2C2SEL_1 +/** + * @} + */ +#endif /* I2C2 */ + +/** @defgroup RCCEx_I2C3_Clock_Source I2C3 Clock Source + * @{ + */ +#define RCC_I2C3CLKSOURCE_PCLK1 0x00000000U +#define RCC_I2C3CLKSOURCE_SYSCLK RCC_CCIPR_I2C3SEL_0 +#define RCC_I2C3CLKSOURCE_HSI RCC_CCIPR_I2C3SEL_1 +/** + * @} + */ + +#if defined(I2C4) +/** @defgroup RCCEx_I2C4_Clock_Source I2C4 Clock Source + * @{ + */ +#define RCC_I2C4CLKSOURCE_PCLK1 0x00000000U +#define RCC_I2C4CLKSOURCE_SYSCLK RCC_CCIPR2_I2C4SEL_0 +#define RCC_I2C4CLKSOURCE_HSI RCC_CCIPR2_I2C4SEL_1 +/** + * @} + */ +#endif /* I2C4 */ + +/** @defgroup RCCEx_SAI1_Clock_Source SAI1 Clock Source + * @{ + */ +#define RCC_SAI1CLKSOURCE_PLLSAI1 0x00000000U +#if defined(RCC_PLLSAI2_SUPPORT) +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +#define RCC_SAI1CLKSOURCE_PLLSAI2 RCC_CCIPR2_SAI1SEL_0 +#else +#define RCC_SAI1CLKSOURCE_PLLSAI2 RCC_CCIPR_SAI1SEL_0 +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ +#endif /* RCC_PLLSAI2_SUPPORT */ +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +#define RCC_SAI1CLKSOURCE_PLL RCC_CCIPR2_SAI1SEL_1 +#define RCC_SAI1CLKSOURCE_PIN (RCC_CCIPR2_SAI1SEL_1 | RCC_CCIPR2_SAI1SEL_0) +#define RCC_SAI1CLKSOURCE_HSI RCC_CCIPR2_SAI1SEL_2 +#else +#define RCC_SAI1CLKSOURCE_PLL RCC_CCIPR_SAI1SEL_1 +#define RCC_SAI1CLKSOURCE_PIN RCC_CCIPR_SAI1SEL +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ +/** + * @} + */ + +#if defined(SAI2) +/** @defgroup RCCEx_SAI2_Clock_Source SAI2 Clock Source + * @{ + */ +#define RCC_SAI2CLKSOURCE_PLLSAI1 0x00000000U +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +#define RCC_SAI2CLKSOURCE_PLLSAI2 RCC_CCIPR2_SAI2SEL_0 +#define RCC_SAI2CLKSOURCE_PLL RCC_CCIPR2_SAI2SEL_1 +#define RCC_SAI2CLKSOURCE_PIN (RCC_CCIPR2_SAI2SEL_1 | RCC_CCIPR2_SAI2SEL_0) +#define RCC_SAI2CLKSOURCE_HSI RCC_CCIPR2_SAI2SEL_2 +#else +#define RCC_SAI2CLKSOURCE_PLLSAI2 RCC_CCIPR_SAI2SEL_0 +#define RCC_SAI2CLKSOURCE_PLL RCC_CCIPR_SAI2SEL_1 +#define RCC_SAI2CLKSOURCE_PIN RCC_CCIPR_SAI2SEL +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ +/** + * @} + */ +#endif /* SAI2 */ + +/** @defgroup RCCEx_LPTIM1_Clock_Source LPTIM1 Clock Source + * @{ + */ +#define RCC_LPTIM1CLKSOURCE_PCLK1 0x00000000U +#define RCC_LPTIM1CLKSOURCE_LSI RCC_CCIPR_LPTIM1SEL_0 +#define RCC_LPTIM1CLKSOURCE_HSI RCC_CCIPR_LPTIM1SEL_1 +#define RCC_LPTIM1CLKSOURCE_LSE RCC_CCIPR_LPTIM1SEL +/** + * @} + */ + +/** @defgroup RCCEx_LPTIM2_Clock_Source LPTIM2 Clock Source + * @{ + */ +#define RCC_LPTIM2CLKSOURCE_PCLK1 0x00000000U +#define RCC_LPTIM2CLKSOURCE_LSI RCC_CCIPR_LPTIM2SEL_0 +#define RCC_LPTIM2CLKSOURCE_HSI RCC_CCIPR_LPTIM2SEL_1 +#define RCC_LPTIM2CLKSOURCE_LSE RCC_CCIPR_LPTIM2SEL +/** + * @} + */ + +#if defined(SDMMC1) +/** @defgroup RCCEx_SDMMC1_Clock_Source SDMMC1 Clock Source + * @{ + */ +#if defined(RCC_HSI48_SUPPORT) +#define RCC_SDMMC1CLKSOURCE_HSI48 0x00000000U /*!< HSI48 clock selected as SDMMC1 clock */ +#else +#define RCC_SDMMC1CLKSOURCE_NONE 0x00000000U /*!< No clock selected as SDMMC1 clock */ +#endif /* RCC_HSI48_SUPPORT */ +#define RCC_SDMMC1CLKSOURCE_PLLSAI1 RCC_CCIPR_CLK48SEL_0 /*!< PLLSAI1 "Q" clock selected as SDMMC1 clock */ +#define RCC_SDMMC1CLKSOURCE_PLL RCC_CCIPR_CLK48SEL_1 /*!< PLL "Q" clock selected as SDMMC1 clock */ +#define RCC_SDMMC1CLKSOURCE_MSI RCC_CCIPR_CLK48SEL /*!< MSI clock selected as SDMMC1 clock */ +#if defined(RCC_CCIPR2_SDMMCSEL) +#define RCC_SDMMC1CLKSOURCE_PLLP RCC_CCIPR2_SDMMCSEL /*!< PLL "P" clock selected as SDMMC1 kernel clock */ +#endif /* RCC_CCIPR2_SDMMCSEL */ +/** + * @} + */ +#endif /* SDMMC1 */ + +/** @defgroup RCCEx_RNG_Clock_Source RNG Clock Source + * @{ + */ +#if defined(RCC_HSI48_SUPPORT) +#define RCC_RNGCLKSOURCE_HSI48 0x00000000U +#else +#define RCC_RNGCLKSOURCE_NONE 0x00000000U +#endif /* RCC_HSI48_SUPPORT */ +#define RCC_RNGCLKSOURCE_PLLSAI1 RCC_CCIPR_CLK48SEL_0 +#define RCC_RNGCLKSOURCE_PLL RCC_CCIPR_CLK48SEL_1 +#define RCC_RNGCLKSOURCE_MSI RCC_CCIPR_CLK48SEL +/** + * @} + */ + +#if defined(USB_OTG_FS) || defined(USB) +/** @defgroup RCCEx_USB_Clock_Source USB Clock Source + * @{ + */ +#if defined(RCC_HSI48_SUPPORT) +#define RCC_USBCLKSOURCE_HSI48 0x00000000U +#else +#define RCC_USBCLKSOURCE_NONE 0x00000000U +#endif /* RCC_HSI48_SUPPORT */ +#define RCC_USBCLKSOURCE_PLLSAI1 RCC_CCIPR_CLK48SEL_0 +#define RCC_USBCLKSOURCE_PLL RCC_CCIPR_CLK48SEL_1 +#define RCC_USBCLKSOURCE_MSI RCC_CCIPR_CLK48SEL +/** + * @} + */ +#endif /* USB_OTG_FS || USB */ + +/** @defgroup RCCEx_ADC_Clock_Source ADC Clock Source + * @{ + */ +#define RCC_ADCCLKSOURCE_NONE 0x00000000U +#define RCC_ADCCLKSOURCE_PLLSAI1 RCC_CCIPR_ADCSEL_0 +#if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || defined(STM32L496xx) || defined(STM32L4A6xx) +#define RCC_ADCCLKSOURCE_PLLSAI2 RCC_CCIPR_ADCSEL_1 +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || STM32L496xx || STM32L4A6xx */ +#define RCC_ADCCLKSOURCE_SYSCLK RCC_CCIPR_ADCSEL +/** + * @} + */ + +#if defined(SWPMI1) +/** @defgroup RCCEx_SWPMI1_Clock_Source SWPMI1 Clock Source + * @{ + */ +#define RCC_SWPMI1CLKSOURCE_PCLK1 0x00000000U +#define RCC_SWPMI1CLKSOURCE_HSI RCC_CCIPR_SWPMI1SEL +/** + * @} + */ +#endif /* SWPMI1 */ + +#if defined(DFSDM1_Filter0) +/** @defgroup RCCEx_DFSDM1_Clock_Source DFSDM1 Clock Source + * @{ + */ +#define RCC_DFSDM1CLKSOURCE_PCLK2 0x00000000U +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +#define RCC_DFSDM1CLKSOURCE_SYSCLK RCC_CCIPR2_DFSDM1SEL +#else +#define RCC_DFSDM1CLKSOURCE_SYSCLK RCC_CCIPR_DFSDM1SEL +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ +/** + * @} + */ + +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +/** @defgroup RCCEx_DFSDM1_Audio_Clock_Source DFSDM1 Audio Clock Source + * @{ + */ +#define RCC_DFSDM1AUDIOCLKSOURCE_SAI1 0x00000000U +#define RCC_DFSDM1AUDIOCLKSOURCE_HSI RCC_CCIPR2_ADFSDM1SEL_0 +#define RCC_DFSDM1AUDIOCLKSOURCE_MSI RCC_CCIPR2_ADFSDM1SEL_1 +/** + * @} + */ +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ +#endif /* DFSDM1_Filter0 */ + +#if defined(LTDC) +/** @defgroup RCCEx_LTDC_Clock_Source LTDC Clock Source + * @{ + */ +#define RCC_LTDCCLKSOURCE_PLLSAI2_DIV2 0x00000000U +#define RCC_LTDCCLKSOURCE_PLLSAI2_DIV4 RCC_CCIPR2_PLLSAI2DIVR_0 +#define RCC_LTDCCLKSOURCE_PLLSAI2_DIV8 RCC_CCIPR2_PLLSAI2DIVR_1 +#define RCC_LTDCCLKSOURCE_PLLSAI2_DIV16 RCC_CCIPR2_PLLSAI2DIVR +/** + * @} + */ +#endif /* LTDC */ + +#if defined(DSI) +/** @defgroup RCCEx_DSI_Clock_Source DSI Clock Source + * @{ + */ +#define RCC_DSICLKSOURCE_DSIPHY 0x00000000U +#define RCC_DSICLKSOURCE_PLLSAI2 RCC_CCIPR2_DSISEL +/** + * @} + */ +#endif /* DSI */ + +#if defined(OCTOSPI1) || defined(OCTOSPI2) +/** @defgroup RCCEx_OSPI_Clock_Source OctoSPI Clock Source + * @{ + */ +#define RCC_OSPICLKSOURCE_SYSCLK 0x00000000U +#define RCC_OSPICLKSOURCE_MSI RCC_CCIPR2_OSPISEL_0 +#define RCC_OSPICLKSOURCE_PLL RCC_CCIPR2_OSPISEL_1 +/** + * @} + */ +#endif /* OCTOSPI1 || OCTOSPI2 */ + +/** @defgroup RCCEx_EXTI_LINE_LSECSS RCC LSE CSS external interrupt line + * @{ + */ +#define RCC_EXTI_LINE_LSECSS EXTI_IMR1_IM19 /*!< External interrupt line 19 connected to the LSE CSS EXTI Line */ +/** + * @} + */ + +#if defined(CRS) + +/** @defgroup RCCEx_CRS_Status RCCEx CRS Status + * @{ + */ +#define RCC_CRS_NONE 0x00000000U +#define RCC_CRS_TIMEOUT 0x00000001U +#define RCC_CRS_SYNCOK 0x00000002U +#define RCC_CRS_SYNCWARN 0x00000004U +#define RCC_CRS_SYNCERR 0x00000008U +#define RCC_CRS_SYNCMISS 0x00000010U +#define RCC_CRS_TRIMOVF 0x00000020U +/** + * @} + */ + +/** @defgroup RCCEx_CRS_SynchroSource RCCEx CRS SynchroSource + * @{ + */ +#define RCC_CRS_SYNC_SOURCE_GPIO 0x00000000U /*!< Synchro Signal source GPIO */ +#define RCC_CRS_SYNC_SOURCE_LSE CRS_CFGR_SYNCSRC_0 /*!< Synchro Signal source LSE */ +#define RCC_CRS_SYNC_SOURCE_USB CRS_CFGR_SYNCSRC_1 /*!< Synchro Signal source USB SOF (default)*/ +/** + * @} + */ + +/** @defgroup RCCEx_CRS_SynchroDivider RCCEx CRS SynchroDivider + * @{ + */ +#define RCC_CRS_SYNC_DIV1 0x00000000U /*!< Synchro Signal not divided (default) */ +#define RCC_CRS_SYNC_DIV2 CRS_CFGR_SYNCDIV_0 /*!< Synchro Signal divided by 2 */ +#define RCC_CRS_SYNC_DIV4 CRS_CFGR_SYNCDIV_1 /*!< Synchro Signal divided by 4 */ +#define RCC_CRS_SYNC_DIV8 (CRS_CFGR_SYNCDIV_1 | CRS_CFGR_SYNCDIV_0) /*!< Synchro Signal divided by 8 */ +#define RCC_CRS_SYNC_DIV16 CRS_CFGR_SYNCDIV_2 /*!< Synchro Signal divided by 16 */ +#define RCC_CRS_SYNC_DIV32 (CRS_CFGR_SYNCDIV_2 | CRS_CFGR_SYNCDIV_0) /*!< Synchro Signal divided by 32 */ +#define RCC_CRS_SYNC_DIV64 (CRS_CFGR_SYNCDIV_2 | CRS_CFGR_SYNCDIV_1) /*!< Synchro Signal divided by 64 */ +#define RCC_CRS_SYNC_DIV128 CRS_CFGR_SYNCDIV /*!< Synchro Signal divided by 128 */ +/** + * @} + */ + +/** @defgroup RCCEx_CRS_SynchroPolarity RCCEx CRS SynchroPolarity + * @{ + */ +#define RCC_CRS_SYNC_POLARITY_RISING 0x00000000U /*!< Synchro Active on rising edge (default) */ +#define RCC_CRS_SYNC_POLARITY_FALLING CRS_CFGR_SYNCPOL /*!< Synchro Active on falling edge */ +/** + * @} + */ + +/** @defgroup RCCEx_CRS_ReloadValueDefault RCCEx CRS ReloadValueDefault + * @{ + */ +#define RCC_CRS_RELOADVALUE_DEFAULT 0x0000BB7FU /*!< The reset value of the RELOAD field corresponds + to a target frequency of 48 MHz and a synchronization signal frequency of 1 kHz (SOF signal from USB). */ +/** + * @} + */ + +/** @defgroup RCCEx_CRS_ErrorLimitDefault RCCEx CRS ErrorLimitDefault + * @{ + */ +#define RCC_CRS_ERRORLIMIT_DEFAULT 0x00000022U /*!< Default Frequency error limit */ +/** + * @} + */ + +/** @defgroup RCCEx_CRS_HSI48CalibrationDefault RCCEx CRS HSI48CalibrationDefault + * @{ + */ +#define RCC_CRS_HSI48CALIBRATION_DEFAULT 0x00000020U /*!< The default value is 32, which corresponds to the middle of the trimming interval. + The trimming step is around 67 kHz between two consecutive TRIM steps. A higher TRIM value + corresponds to a higher output frequency */ +/** + * @} + */ + +/** @defgroup RCCEx_CRS_FreqErrorDirection RCCEx CRS FreqErrorDirection + * @{ + */ +#define RCC_CRS_FREQERRORDIR_UP 0x00000000U /*!< Upcounting direction, the actual frequency is above the target */ +#define RCC_CRS_FREQERRORDIR_DOWN CRS_ISR_FEDIR /*!< Downcounting direction, the actual frequency is below the target */ +/** + * @} + */ + +/** @defgroup RCCEx_CRS_Interrupt_Sources RCCEx CRS Interrupt Sources + * @{ + */ +#define RCC_CRS_IT_SYNCOK CRS_CR_SYNCOKIE /*!< SYNC event OK */ +#define RCC_CRS_IT_SYNCWARN CRS_CR_SYNCWARNIE /*!< SYNC warning */ +#define RCC_CRS_IT_ERR CRS_CR_ERRIE /*!< Error */ +#define RCC_CRS_IT_ESYNC CRS_CR_ESYNCIE /*!< Expected SYNC */ +#define RCC_CRS_IT_SYNCERR CRS_CR_ERRIE /*!< SYNC error */ +#define RCC_CRS_IT_SYNCMISS CRS_CR_ERRIE /*!< SYNC missed */ +#define RCC_CRS_IT_TRIMOVF CRS_CR_ERRIE /*!< Trimming overflow or underflow */ + +/** + * @} + */ + +/** @defgroup RCCEx_CRS_Flags RCCEx CRS Flags + * @{ + */ +#define RCC_CRS_FLAG_SYNCOK CRS_ISR_SYNCOKF /*!< SYNC event OK flag */ +#define RCC_CRS_FLAG_SYNCWARN CRS_ISR_SYNCWARNF /*!< SYNC warning flag */ +#define RCC_CRS_FLAG_ERR CRS_ISR_ERRF /*!< Error flag */ +#define RCC_CRS_FLAG_ESYNC CRS_ISR_ESYNCF /*!< Expected SYNC flag */ +#define RCC_CRS_FLAG_SYNCERR CRS_ISR_SYNCERR /*!< SYNC error */ +#define RCC_CRS_FLAG_SYNCMISS CRS_ISR_SYNCMISS /*!< SYNC missed*/ +#define RCC_CRS_FLAG_TRIMOVF CRS_ISR_TRIMOVF /*!< Trimming overflow or underflow */ + +/** + * @} + */ + +#endif /* CRS */ + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ +/** @defgroup RCCEx_Exported_Macros RCCEx Exported Macros + * @{ + */ + + +/** + * @brief Macro to configure the PLLSAI1 clock multiplication and division factors. + * + * @note This function must be used only when the PLLSAI1 is disabled. + * @note PLLSAI1 clock source is common with the main PLL (configured through + * __HAL_RCC_PLL_CONFIG() macro) + * + @if STM32L4S9xx + * @param __PLLSAI1M__ specifies the division factor of PLLSAI1 input clock. + * This parameter must be a number between Min_Data = 1 and Max_Data = 16. + * + @endif + * @param __PLLSAI1N__ specifies the multiplication factor for PLLSAI1 VCO output clock. + * This parameter must be a number between 8 and 86. + * @note You have to set the PLLSAI1N parameter correctly to ensure that the VCO + * output frequency is between 64 and 344 MHz. + * PLLSAI1 clock frequency = f(PLLSAI1) multiplied by PLLSAI1N + * + * @param __PLLSAI1P__ specifies the division factor for SAI clock. + * This parameter must be a number in the range (7 or 17) for STM32L47xxx/L48xxx + * else (2 to 31). + * SAI1 clock frequency = f(PLLSAI1) / PLLSAI1P + * + * @param __PLLSAI1Q__ specifies the division factor for USB/RNG/SDMMC1 clock. + * This parameter must be in the range (2, 4, 6 or 8). + * USB/RNG/SDMMC1 clock frequency = f(PLLSAI1) / PLLSAI1Q + * + * @param __PLLSAI1R__ specifies the division factor for SAR ADC clock. + * This parameter must be in the range (2, 4, 6 or 8). + * ADC clock frequency = f(PLLSAI1) / PLLSAI1R + * + * @retval None + */ +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + +#if defined(RCC_PLLSAI1P_DIV_2_31_SUPPORT) + +#define __HAL_RCC_PLLSAI1_CONFIG(__PLLSAI1M__, __PLLSAI1N__, __PLLSAI1P__, __PLLSAI1Q__, __PLLSAI1R__) \ + WRITE_REG(RCC->PLLSAI1CFGR, ((__PLLSAI1N__) << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) | \ + ((((__PLLSAI1Q__) >> 1U) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1Q_Pos) | \ + ((((__PLLSAI1R__) >> 1U) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1R_Pos) | \ + ((__PLLSAI1P__) << RCC_PLLSAI1CFGR_PLLSAI1PDIV_Pos) | \ + (((__PLLSAI1M__) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1M_Pos)) + +#else + +#define __HAL_RCC_PLLSAI1_CONFIG(__PLLSAI1M__, __PLLSAI1N__, __PLLSAI1P__, __PLLSAI1Q__, __PLLSAI1R__) \ + WRITE_REG(RCC->PLLSAI1CFGR, ((__PLLSAI1N__) << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) | \ + (((__PLLSAI1P__) >> 4U) << RCC_PLLSAI1CFGR_PLLSAI1P_Pos) | \ + ((((__PLLSAI1Q__) >> 1U) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1Q_Pos) | \ + ((((__PLLSAI1R__) >> 1U) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1R_Pos) | \ + (((__PLLSAI1M__) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1M_Pos)) + +#endif /* RCC_PLLSAI1P_DIV_2_31_SUPPORT */ + +#else + +#if defined(RCC_PLLSAI1P_DIV_2_31_SUPPORT) + +#define __HAL_RCC_PLLSAI1_CONFIG(__PLLSAI1N__, __PLLSAI1P__, __PLLSAI1Q__, __PLLSAI1R__) \ + WRITE_REG(RCC->PLLSAI1CFGR, ((__PLLSAI1N__) << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) | \ + ((((__PLLSAI1Q__) >> 1U) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1Q_Pos) | \ + ((((__PLLSAI1R__) >> 1U) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1R_Pos) | \ + ((__PLLSAI1P__) << RCC_PLLSAI1CFGR_PLLSAI1PDIV_Pos)) + +#else + +#define __HAL_RCC_PLLSAI1_CONFIG(__PLLSAI1N__, __PLLSAI1P__, __PLLSAI1Q__, __PLLSAI1R__) \ + WRITE_REG(RCC->PLLSAI1CFGR, ((__PLLSAI1N__) << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) | \ + (((__PLLSAI1P__) >> 4U) << RCC_PLLSAI1CFGR_PLLSAI1P_Pos) | \ + ((((__PLLSAI1Q__) >> 1U) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1Q_Pos) | \ + ((((__PLLSAI1R__) >> 1U) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1R_Pos)) + +#endif /* RCC_PLLSAI1P_DIV_2_31_SUPPORT */ + +#endif /* RCC_PLLSAI1M_DIV_1_16_SUPPORT */ + +/** + * @brief Macro to configure the PLLSAI1 clock multiplication factor N. + * + * @note This function must be used only when the PLLSAI1 is disabled. + * @note PLLSAI1 clock source is common with the main PLL (configured through + * __HAL_RCC_PLL_CONFIG() macro) + * + * @param __PLLSAI1N__ specifies the multiplication factor for PLLSAI1 VCO output clock. + * This parameter must be a number between 8 and 86. + * @note You have to set the PLLSAI1N parameter correctly to ensure that the VCO + * output frequency is between 64 and 344 MHz. + * Use to set PLLSAI1 clock frequency = f(PLLSAI1) multiplied by PLLSAI1N + * + * @retval None + */ +#define __HAL_RCC_PLLSAI1_MULN_CONFIG(__PLLSAI1N__) \ + MODIFY_REG(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N, (__PLLSAI1N__) << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) + +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + +/** @brief Macro to configure the PLLSAI1 input clock division factor M. + * + * @note This function must be used only when the PLLSAI1 is disabled. + * @note PLLSAI1 clock source is common with the main PLL (configured through + * __HAL_RCC_PLL_CONFIG() macro) + * + * @param __PLLSAI1M__ specifies the division factor for PLLSAI1 clock. + * This parameter must be a number between Min_Data = 1 and Max_Data = 16. + * + * @retval None + */ + +#define __HAL_RCC_PLLSAI1_DIVM_CONFIG(__PLLSAI1M__) \ + MODIFY_REG(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1M, ((__PLLSAI1M__) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1M_Pos) + +#endif /* RCC_PLLSAI1M_DIV_1_16_SUPPORT */ + +/** @brief Macro to configure the PLLSAI1 clock division factor P. + * + * @note This function must be used only when the PLLSAI1 is disabled. + * @note PLLSAI1 clock source is common with the main PLL (configured through + * __HAL_RCC_PLL_CONFIG() macro) + * + * @param __PLLSAI1P__ specifies the division factor for SAI clock. + * This parameter must be a number in the range (7 or 17) for STM32L47xxx/L48xxx + * else (2 to 31). + * Use to set SAI1 clock frequency = f(PLLSAI1) / PLLSAI1P + * + * @retval None + */ +#if defined(RCC_PLLSAI1P_DIV_2_31_SUPPORT) + +#define __HAL_RCC_PLLSAI1_DIVP_CONFIG(__PLLSAI1P__) \ + MODIFY_REG(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1PDIV, (__PLLSAI1P__) << RCC_PLLSAI1CFGR_PLLSAI1PDIV_Pos) + +#else + +#define __HAL_RCC_PLLSAI1_DIVP_CONFIG(__PLLSAI1P__) \ + MODIFY_REG(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1P, ((__PLLSAI1P__) >> 4U) << RCC_PLLSAI1CFGR_PLLSAI1P_Pos) + +#endif /* RCC_PLLSAI1P_DIV_2_31_SUPPORT */ + +/** @brief Macro to configure the PLLSAI1 clock division factor Q. + * + * @note This function must be used only when the PLLSAI1 is disabled. + * @note PLLSAI1 clock source is common with the main PLL (configured through + * __HAL_RCC_PLL_CONFIG() macro) + * + * @param __PLLSAI1Q__ specifies the division factor for USB/RNG/SDMMC1 clock. + * This parameter must be in the range (2, 4, 6 or 8). + * Use to set USB/RNG/SDMMC1 clock frequency = f(PLLSAI1) / PLLSAI1Q + * + * @retval None + */ +#define __HAL_RCC_PLLSAI1_DIVQ_CONFIG(__PLLSAI1Q__) \ + MODIFY_REG(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1Q, (((__PLLSAI1Q__) >> 1U) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1Q_Pos) + +/** @brief Macro to configure the PLLSAI1 clock division factor R. + * + * @note This function must be used only when the PLLSAI1 is disabled. + * @note PLLSAI1 clock source is common with the main PLL (configured through + * __HAL_RCC_PLL_CONFIG() macro) + * + * @param __PLLSAI1R__ specifies the division factor for ADC clock. + * This parameter must be in the range (2, 4, 6 or 8) + * Use to set ADC clock frequency = f(PLLSAI1) / PLLSAI1R + * + * @retval None + */ +#define __HAL_RCC_PLLSAI1_DIVR_CONFIG(__PLLSAI1R__) \ + MODIFY_REG(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1R, (((__PLLSAI1R__) >> 1U) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1R_Pos) + +/** + * @brief Macros to enable or disable the PLLSAI1. + * @note The PLLSAI1 is disabled by hardware when entering STOP and STANDBY modes. + * @retval None + */ + +#define __HAL_RCC_PLLSAI1_ENABLE() SET_BIT(RCC->CR, RCC_CR_PLLSAI1ON) + +#define __HAL_RCC_PLLSAI1_DISABLE() CLEAR_BIT(RCC->CR, RCC_CR_PLLSAI1ON) + +/** + * @brief Macros to enable or disable each clock output (PLLSAI1_SAI1, PLLSAI1_USB2 and PLLSAI1_ADC1). + * @note Enabling and disabling those clocks can be done without the need to stop the PLL. + * This is mainly used to save Power. + * @param __PLLSAI1_CLOCKOUT__ specifies the PLLSAI1 clock to be output. + * This parameter can be one or a combination of the following values: + * @arg @ref RCC_PLLSAI1_SAI1CLK This clock is used to generate an accurate clock to achieve + * high-quality audio performance on SAI interface in case. + * @arg @ref RCC_PLLSAI1_48M2CLK This clock is used to generate the clock for the USB OTG FS (48 MHz), + * the random number generator (<=48 MHz) and the SDIO (<= 48 MHz). + * @arg @ref RCC_PLLSAI1_ADC1CLK Clock used to clock ADC peripheral. + * @retval None + */ + +#define __HAL_RCC_PLLSAI1CLKOUT_ENABLE(__PLLSAI1_CLOCKOUT__) SET_BIT(RCC->PLLSAI1CFGR, (__PLLSAI1_CLOCKOUT__)) + +#define __HAL_RCC_PLLSAI1CLKOUT_DISABLE(__PLLSAI1_CLOCKOUT__) CLEAR_BIT(RCC->PLLSAI1CFGR, (__PLLSAI1_CLOCKOUT__)) + +/** + * @brief Macro to get clock output enable status (PLLSAI1_SAI1, PLLSAI1_USB2 and PLLSAI1_ADC1). + * @param __PLLSAI1_CLOCKOUT__ specifies the PLLSAI1 clock to be output. + * This parameter can be one of the following values: + * @arg @ref RCC_PLLSAI1_SAI1CLK This clock is used to generate an accurate clock to achieve + * high-quality audio performance on SAI interface in case. + * @arg @ref RCC_PLLSAI1_48M2CLK This clock is used to generate the clock for the USB OTG FS (48 MHz), + * the random number generator (<=48 MHz) and the SDIO (<= 48 MHz). + * @arg @ref RCC_PLLSAI1_ADC1CLK Clock used to clock ADC peripheral. + * @retval SET / RESET + */ +#define __HAL_RCC_GET_PLLSAI1CLKOUT_CONFIG(__PLLSAI1_CLOCKOUT__) READ_BIT(RCC->PLLSAI1CFGR, (__PLLSAI1_CLOCKOUT__)) + +#if defined(RCC_PLLSAI2_SUPPORT) + +/** + * @brief Macro to configure the PLLSAI2 clock multiplication and division factors. + * + * @note This function must be used only when the PLLSAI2 is disabled. + * @note PLLSAI2 clock source is common with the main PLL (configured through + * __HAL_RCC_PLL_CONFIG() macro) + * + @if STM32L4S9xx + * @param __PLLSAI2M__ specifies the division factor of PLLSAI2 input clock. + * This parameter must be a number between Min_Data = 1 and Max_Data = 16. + * + @endif + * @param __PLLSAI2N__ specifies the multiplication factor for PLLSAI2 VCO output clock. + * This parameter must be a number between 8 and 86. + * @note You have to set the PLLSAI2N parameter correctly to ensure that the VCO + * output frequency is between 64 and 344 MHz. + * + * @param __PLLSAI2P__ specifies the division factor for SAI clock. + * This parameter must be a number in the range (7 or 17) for STM32L47xxx/L48xxx + * else (2 to 31). + * SAI2 clock frequency = f(PLLSAI2) / PLLSAI2P + * + @if STM32L4S9xx + * @param __PLLSAI2Q__ specifies the division factor for DSI clock. + * This parameter must be in the range (2, 4, 6 or 8). + * DSI clock frequency = f(PLLSAI2) / PLLSAI2Q + * + @endif + * @param __PLLSAI2R__ specifies the division factor for SAR ADC clock. + * This parameter must be in the range (2, 4, 6 or 8). + * + * @retval None + */ + +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + +# if defined(RCC_PLLSAI2P_DIV_2_31_SUPPORT) && defined(RCC_PLLSAI2Q_DIV_SUPPORT) + +#define __HAL_RCC_PLLSAI2_CONFIG(__PLLSAI2M__, __PLLSAI2N__, __PLLSAI2P__, __PLLSAI2Q__, __PLLSAI2R__) \ + WRITE_REG(RCC->PLLSAI2CFGR, ((__PLLSAI2N__) << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | \ + ((((__PLLSAI2Q__) >> 1U) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2Q_Pos) | \ + ((((__PLLSAI2R__) >> 1U) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2R_Pos) | \ + ((__PLLSAI2P__) << RCC_PLLSAI2CFGR_PLLSAI2PDIV_Pos) | \ + (((__PLLSAI2M__) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2M_Pos)) + +# elif defined(RCC_PLLSAI2P_DIV_2_31_SUPPORT) + +#define __HAL_RCC_PLLSAI2_CONFIG(__PLLSAI2M__, __PLLSAI2N__, __PLLSAI2P__, __PLLSAI2R__) \ + WRITE_REG(RCC->PLLSAI2CFGR, ((__PLLSAI2N__) << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | \ + ((((__PLLSAI2R__) >> 1U) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2R_Pos) | \ + ((__PLLSAI2P__) << RCC_PLLSAI2CFGR_PLLSAI2PDIV_Pos) | \ + (((__PLLSAI2M__) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2M_Pos)) + +# else + +#define __HAL_RCC_PLLSAI2_CONFIG(__PLLSAI2M__, __PLLSAI2N__, __PLLSAI2P__, __PLLSAI2R__) \ + WRITE_REG(RCC->PLLSAI2CFGR, ((__PLLSAI2N__) << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | \ + (((__PLLSAI2P__) >> 4U) << RCC_PLLSAI2CFGR_PLLSAI2P_Pos) | \ + ((((__PLLSAI2R__) >> 1U) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2R_Pos) | \ + (((__PLLSAI2M__) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2M_Pos)) + +# endif /* RCC_PLLSAI2P_DIV_2_31_SUPPORT && RCC_PLLSAI2Q_DIV_SUPPORT */ + +#else + +# if defined(RCC_PLLSAI2P_DIV_2_31_SUPPORT) && defined(RCC_PLLSAI2Q_DIV_SUPPORT) + +#define __HAL_RCC_PLLSAI2_CONFIG(__PLLSAI2N__, __PLLSAI2P__, __PLLSAI2Q__, __PLLSAI2R__) \ + WRITE_REG(RCC->PLLSAI2CFGR, ((__PLLSAI2N__) << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | \ + ((((__PLLSAI2Q__) >> 1U) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2Q_Pos) | \ + ((((__PLLSAI2R__) >> 1U) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2R_Pos) | \ + ((__PLLSAI2P__) << RCC_PLLSAI2CFGR_PLLSAI2PDIV_Pos)) + +# elif defined(RCC_PLLSAI2P_DIV_2_31_SUPPORT) + +#define __HAL_RCC_PLLSAI2_CONFIG(__PLLSAI2N__, __PLLSAI2P__, __PLLSAI2R__) \ + WRITE_REG(RCC->PLLSAI2CFGR, ((__PLLSAI2N__) << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | \ + ((((__PLLSAI2R__) >> 1U) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2R_Pos) | \ + ((__PLLSAI2P__) << RCC_PLLSAI2CFGR_PLLSAI2PDIV_Pos)) + +# else + +#define __HAL_RCC_PLLSAI2_CONFIG(__PLLSAI2N__, __PLLSAI2P__, __PLLSAI2R__) \ + WRITE_REG(RCC->PLLSAI2CFGR, ((__PLLSAI2N__) << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | \ + (((__PLLSAI2P__) >> 4U) << RCC_PLLSAI2CFGR_PLLSAI2P_Pos) | \ + ((((__PLLSAI2R__) >> 1U) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2R_Pos)) + +# endif /* RCC_PLLSAI2P_DIV_2_31_SUPPORT && RCC_PLLSAI2Q_DIV_SUPPORT */ + +#endif /* RCC_PLLSAI2M_DIV_1_16_SUPPORT */ + + +/** + * @brief Macro to configure the PLLSAI2 clock multiplication factor N. + * + * @note This function must be used only when the PLLSAI2 is disabled. + * @note PLLSAI2 clock source is common with the main PLL (configured through + * __HAL_RCC_PLL_CONFIG() macro) + * + * @param __PLLSAI2N__ specifies the multiplication factor for PLLSAI2 VCO output clock. + * This parameter must be a number between 8 and 86. + * @note You have to set the PLLSAI2N parameter correctly to ensure that the VCO + * output frequency is between 64 and 344 MHz. + * PLLSAI1 clock frequency = f(PLLSAI1) multiplied by PLLSAI2N + * + * @retval None + */ +#define __HAL_RCC_PLLSAI2_MULN_CONFIG(__PLLSAI2N__) \ + MODIFY_REG(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2N, (__PLLSAI2N__) << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) + +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + +/** @brief Macro to configure the PLLSAI2 input clock division factor M. + * + * @note This function must be used only when the PLLSAI2 is disabled. + * @note PLLSAI2 clock source is common with the main PLL (configured through + * __HAL_RCC_PLL_CONFIG() macro) + * + * @param __PLLSAI2M__ specifies the division factor for PLLSAI2 clock. + * This parameter must be a number between Min_Data = 1 and Max_Data = 16. + * + * @retval None + */ + +#define __HAL_RCC_PLLSAI2_DIVM_CONFIG(__PLLSAI2M__) \ + MODIFY_REG(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2M, ((__PLLSAI2M__) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2M_Pos) + +#endif /* RCC_PLLSAI2M_DIV_1_16_SUPPORT */ + +/** @brief Macro to configure the PLLSAI2 clock division factor P. + * + * @note This function must be used only when the PLLSAI2 is disabled. + * @note PLLSAI2 clock source is common with the main PLL (configured through + * __HAL_RCC_PLL_CONFIG() macro) + * + * @param __PLLSAI2P__ specifies the division factor. + * This parameter must be a number in the range (7 or 17). + * Use to set SAI2 clock frequency = f(PLLSAI2) / __PLLSAI2P__ + * + * @retval None + */ +#define __HAL_RCC_PLLSAI2_DIVP_CONFIG(__PLLSAI2P__) \ + MODIFY_REG(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2P, ((__PLLSAI2P__) >> 4U) << RCC_PLLSAI2CFGR_PLLSAI2P_Pos) + +#if defined(RCC_PLLSAI2Q_DIV_SUPPORT) + +/** @brief Macro to configure the PLLSAI2 clock division factor Q. + * + * @note This function must be used only when the PLLSAI2 is disabled. + * @note PLLSAI2 clock source is common with the main PLL (configured through + * __HAL_RCC_PLL_CONFIG() macro) + * + * @param __PLLSAI2Q__ specifies the division factor for USB/RNG/SDMMC1 clock. + * This parameter must be in the range (2, 4, 6 or 8). + * Use to set USB/RNG/SDMMC1 clock frequency = f(PLLSAI2) / PLLSAI2Q + * + * @retval None + */ +#define __HAL_RCC_PLLSAI2_DIVQ_CONFIG(__PLLSAI2Q__) \ + MODIFY_REG(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2Q, (((__PLLSAI2Q__) >> 1U) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2Q_Pos) + +#endif /* RCC_PLLSAI2Q_DIV_SUPPORT */ + +/** @brief Macro to configure the PLLSAI2 clock division factor R. + * + * @note This function must be used only when the PLLSAI2 is disabled. + * @note PLLSAI2 clock source is common with the main PLL (configured through + * __HAL_RCC_PLL_CONFIG() macro) + * + * @param __PLLSAI2R__ specifies the division factor. + * This parameter must be in the range (2, 4, 6 or 8). + * Use to set ADC clock frequency = f(PLLSAI2) / __PLLSAI2R__ + * + * @retval None + */ +#define __HAL_RCC_PLLSAI2_DIVR_CONFIG(__PLLSAI2R__) \ + MODIFY_REG(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2R, (((__PLLSAI2R__) >> 1U) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2R_Pos) + +/** + * @brief Macros to enable or disable the PLLSAI2. + * @note The PLLSAI2 is disabled by hardware when entering STOP and STANDBY modes. + * @retval None + */ + +#define __HAL_RCC_PLLSAI2_ENABLE() SET_BIT(RCC->CR, RCC_CR_PLLSAI2ON) + +#define __HAL_RCC_PLLSAI2_DISABLE() CLEAR_BIT(RCC->CR, RCC_CR_PLLSAI2ON) + +/** + * @brief Macros to enable or disable each clock output (PLLSAI2_SAI2, PLLSAI2_ADC2 and RCC_PLLSAI2_DSICLK). + * @note Enabling and disabling those clocks can be done without the need to stop the PLL. + * This is mainly used to save Power. + * @param __PLLSAI2_CLOCKOUT__ specifies the PLLSAI2 clock to be output. + * This parameter can be one or a combination of the following values: + @if STM32L486xx + * @arg @ref RCC_PLLSAI2_SAI2CLK This clock is used to generate an accurate clock to achieve + * high-quality audio performance on SAI interface in case. + * @arg @ref RCC_PLLSAI2_ADC2CLK Clock used to clock ADC peripheral. + @endif + @if STM32L4A6xx + * @arg @ref RCC_PLLSAI2_SAI2CLK This clock is used to generate an accurate clock to achieve + * high-quality audio performance on SAI interface in case. + * @arg @ref RCC_PLLSAI2_ADC2CLK Clock used to clock ADC peripheral. + @endif + @if STM32L4S9xx + * @arg @ref RCC_PLLSAI2_SAI2CLK This clock is used to generate an accurate clock to achieve + * high-quality audio performance on SAI interface in case. + * @arg @ref RCC_PLLSAI2_DSICLK Clock used to clock DSI peripheral. + @endif + * @retval None + */ + +#define __HAL_RCC_PLLSAI2CLKOUT_ENABLE(__PLLSAI2_CLOCKOUT__) SET_BIT(RCC->PLLSAI2CFGR, (__PLLSAI2_CLOCKOUT__)) + +#define __HAL_RCC_PLLSAI2CLKOUT_DISABLE(__PLLSAI2_CLOCKOUT__) CLEAR_BIT(RCC->PLLSAI2CFGR, (__PLLSAI2_CLOCKOUT__)) + +/** + * @brief Macro to get clock output enable status (PLLSAI2_SAI2, PLLSAI2_ADC2 and RCC_PLLSAI2_DSICLK). + * @param __PLLSAI2_CLOCKOUT__ specifies the PLLSAI2 clock to be output. + * This parameter can be one of the following values: + @if STM32L486xx + * @arg @ref RCC_PLLSAI2_SAI2CLK This clock is used to generate an accurate clock to achieve + * high-quality audio performance on SAI interface in case. + * @arg @ref RCC_PLLSAI2_ADC2CLK Clock used to clock ADC peripheral. + @endif + @if STM32L4A6xx + * @arg @ref RCC_PLLSAI2_SAI2CLK This clock is used to generate an accurate clock to achieve + * high-quality audio performance on SAI interface in case. + * @arg @ref RCC_PLLSAI2_ADC2CLK Clock used to clock ADC peripheral. + @endif + @if STM32L4S9xx + * @arg @ref RCC_PLLSAI2_SAI2CLK This clock is used to generate an accurate clock to achieve + * high-quality audio performance on SAI interface in case. + * @arg @ref RCC_PLLSAI2_DSICLK Clock used to clock DSI peripheral. + @endif + * @retval SET / RESET + */ +#define __HAL_RCC_GET_PLLSAI2CLKOUT_CONFIG(__PLLSAI2_CLOCKOUT__) READ_BIT(RCC->PLLSAI2CFGR, (__PLLSAI2_CLOCKOUT__)) + +#endif /* RCC_PLLSAI2_SUPPORT */ + +/** + * @brief Macro to configure the SAI1 clock source. + * @param __SAI1_CLKSOURCE__ defines the SAI1 clock source. This clock is derived + * from the PLLSAI1, system PLL or external clock (through a dedicated pin). + * This parameter can be one of the following values: + * @arg @ref RCC_SAI1CLKSOURCE_PLLSAI1 SAI1 clock = PLLSAI1 "P" clock (PLLSAI1CLK) + @if STM32L486xx + * @arg @ref RCC_SAI1CLKSOURCE_PLLSAI2 SAI1 clock = PLLSAI2 "P" clock (PLLSAI2CLK) for devices with PLLSAI2 + @endif + * @arg @ref RCC_SAI1CLKSOURCE_PLL SAI1 clock = PLL "P" clock (PLLSAI3CLK if PLLSAI2 exists, else PLLSAI2CLK) + * @arg @ref RCC_SAI1CLKSOURCE_PIN SAI1 clock = External Clock (SAI1_EXTCLK) + @if STM32L4S9xx + * @arg @ref RCC_SAI1CLKSOURCE_HSI SAI1 clock = HSI16 + @endif + * + @if STM32L443xx + * @note HSI16 is automatically set as SAI1 clock source when PLL are disabled for devices without PLLSAI2. + @endif + * + * @retval None + */ +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +#define __HAL_RCC_SAI1_CONFIG(__SAI1_CLKSOURCE__)\ + MODIFY_REG(RCC->CCIPR2, RCC_CCIPR2_SAI1SEL, (__SAI1_CLKSOURCE__)) +#else +#define __HAL_RCC_SAI1_CONFIG(__SAI1_CLKSOURCE__)\ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_SAI1SEL, (__SAI1_CLKSOURCE__)) +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +/** @brief Macro to get the SAI1 clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_SAI1CLKSOURCE_PLLSAI1 SAI1 clock = PLLSAI1 "P" clock (PLLSAI1CLK) + @if STM32L486xx + * @arg @ref RCC_SAI1CLKSOURCE_PLLSAI2 SAI1 clock = PLLSAI2 "P" clock (PLLSAI2CLK) for devices with PLLSAI2 + @endif + * @arg @ref RCC_SAI1CLKSOURCE_PLL SAI1 clock = PLL "P" clock (PLLSAI3CLK if PLLSAI2 exists, else PLLSAI2CLK) + * @arg @ref RCC_SAI1CLKSOURCE_PIN SAI1 clock = External Clock (SAI1_EXTCLK) + * + * @note Despite returned values RCC_SAI1CLKSOURCE_PLLSAI1 or RCC_SAI1CLKSOURCE_PLL, HSI16 is automatically set as SAI1 + * clock source when PLLs are disabled for devices without PLLSAI2. + * + */ +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +#define __HAL_RCC_GET_SAI1_SOURCE() (READ_BIT(RCC->CCIPR2, RCC_CCIPR2_SAI1SEL)) +#else +#define __HAL_RCC_GET_SAI1_SOURCE() (READ_BIT(RCC->CCIPR, RCC_CCIPR_SAI1SEL)) +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#if defined(SAI2) + +/** + * @brief Macro to configure the SAI2 clock source. + * @param __SAI2_CLKSOURCE__ defines the SAI2 clock source. This clock is derived + * from the PLLSAI2, system PLL or external clock (through a dedicated pin). + * This parameter can be one of the following values: + * @arg @ref RCC_SAI2CLKSOURCE_PLLSAI1 SAI2 clock = PLLSAI1 "P" clock (PLLSAI1CLK) + * @arg @ref RCC_SAI2CLKSOURCE_PLLSAI2 SAI2 clock = PLLSAI2 "P" clock (PLLSAI2CLK) + * @arg @ref RCC_SAI2CLKSOURCE_PLL SAI2 clock = PLL "P" clock (PLLSAI3CLK) + * @arg @ref RCC_SAI2CLKSOURCE_PIN SAI2 clock = External Clock (SAI2_EXTCLK) + @if STM32L4S9xx + * @arg @ref RCC_SAI2CLKSOURCE_HSI SAI2 clock = HSI16 + @endif + * + * @retval None + */ +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +#define __HAL_RCC_SAI2_CONFIG(__SAI2_CLKSOURCE__ )\ + MODIFY_REG(RCC->CCIPR2, RCC_CCIPR2_SAI2SEL, (__SAI2_CLKSOURCE__)) +#else +#define __HAL_RCC_SAI2_CONFIG(__SAI2_CLKSOURCE__ )\ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_SAI2SEL, (__SAI2_CLKSOURCE__)) +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +/** @brief Macro to get the SAI2 clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_SAI2CLKSOURCE_PLLSAI1 SAI2 clock = PLLSAI1 "P" clock (PLLSAI1CLK) + * @arg @ref RCC_SAI2CLKSOURCE_PLLSAI2 SAI2 clock = PLLSAI2 "P" clock (PLLSAI2CLK) + * @arg @ref RCC_SAI2CLKSOURCE_PLL SAI2 clock = PLL "P" clock (PLLSAI3CLK) + * @arg @ref RCC_SAI2CLKSOURCE_PIN SAI2 clock = External Clock (SAI2_EXTCLK) + */ +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +#define __HAL_RCC_GET_SAI2_SOURCE() (READ_BIT(RCC->CCIPR2, RCC_CCIPR2_SAI2SEL)) +#else +#define __HAL_RCC_GET_SAI2_SOURCE() (READ_BIT(RCC->CCIPR, RCC_CCIPR_SAI2SEL)) +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#endif /* SAI2 */ + +/** @brief Macro to configure the I2C1 clock (I2C1CLK). + * + * @param __I2C1_CLKSOURCE__ specifies the I2C1 clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_I2C1CLKSOURCE_PCLK1 PCLK1 selected as I2C1 clock + * @arg @ref RCC_I2C1CLKSOURCE_HSI HSI selected as I2C1 clock + * @arg @ref RCC_I2C1CLKSOURCE_SYSCLK System Clock selected as I2C1 clock + * @retval None + */ +#define __HAL_RCC_I2C1_CONFIG(__I2C1_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_I2C1SEL, (__I2C1_CLKSOURCE__)) + +/** @brief Macro to get the I2C1 clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_I2C1CLKSOURCE_PCLK1 PCLK1 selected as I2C1 clock + * @arg @ref RCC_I2C1CLKSOURCE_HSI HSI selected as I2C1 clock + * @arg @ref RCC_I2C1CLKSOURCE_SYSCLK System Clock selected as I2C1 clock + */ +#define __HAL_RCC_GET_I2C1_SOURCE() (READ_BIT(RCC->CCIPR, RCC_CCIPR_I2C1SEL)) + +#if defined(I2C2) + +/** @brief Macro to configure the I2C2 clock (I2C2CLK). + * + * @param __I2C2_CLKSOURCE__ specifies the I2C2 clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_I2C2CLKSOURCE_PCLK1 PCLK1 selected as I2C2 clock + * @arg @ref RCC_I2C2CLKSOURCE_HSI HSI selected as I2C2 clock + * @arg @ref RCC_I2C2CLKSOURCE_SYSCLK System Clock selected as I2C2 clock + * @retval None + */ +#define __HAL_RCC_I2C2_CONFIG(__I2C2_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_I2C2SEL, (__I2C2_CLKSOURCE__)) + +/** @brief Macro to get the I2C2 clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_I2C2CLKSOURCE_PCLK1 PCLK1 selected as I2C2 clock + * @arg @ref RCC_I2C2CLKSOURCE_HSI HSI selected as I2C2 clock + * @arg @ref RCC_I2C2CLKSOURCE_SYSCLK System Clock selected as I2C2 clock + */ +#define __HAL_RCC_GET_I2C2_SOURCE() (READ_BIT(RCC->CCIPR, RCC_CCIPR_I2C2SEL)) + +#endif /* I2C2 */ + +/** @brief Macro to configure the I2C3 clock (I2C3CLK). + * + * @param __I2C3_CLKSOURCE__ specifies the I2C3 clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_I2C3CLKSOURCE_PCLK1 PCLK1 selected as I2C3 clock + * @arg @ref RCC_I2C3CLKSOURCE_HSI HSI selected as I2C3 clock + * @arg @ref RCC_I2C3CLKSOURCE_SYSCLK System Clock selected as I2C3 clock + * @retval None + */ +#define __HAL_RCC_I2C3_CONFIG(__I2C3_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_I2C3SEL, (__I2C3_CLKSOURCE__)) + +/** @brief Macro to get the I2C3 clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_I2C3CLKSOURCE_PCLK1 PCLK1 selected as I2C3 clock + * @arg @ref RCC_I2C3CLKSOURCE_HSI HSI selected as I2C3 clock + * @arg @ref RCC_I2C3CLKSOURCE_SYSCLK System Clock selected as I2C3 clock + */ +#define __HAL_RCC_GET_I2C3_SOURCE() (READ_BIT(RCC->CCIPR, RCC_CCIPR_I2C3SEL)) + +#if defined(I2C4) + +/** @brief Macro to configure the I2C4 clock (I2C4CLK). + * + * @param __I2C4_CLKSOURCE__ specifies the I2C4 clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_I2C4CLKSOURCE_PCLK1 PCLK1 selected as I2C4 clock + * @arg @ref RCC_I2C4CLKSOURCE_HSI HSI selected as I2C4 clock + * @arg @ref RCC_I2C4CLKSOURCE_SYSCLK System Clock selected as I2C4 clock + * @retval None + */ +#define __HAL_RCC_I2C4_CONFIG(__I2C4_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR2, RCC_CCIPR2_I2C4SEL, (__I2C4_CLKSOURCE__)) + +/** @brief Macro to get the I2C4 clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_I2C4CLKSOURCE_PCLK1 PCLK1 selected as I2C4 clock + * @arg @ref RCC_I2C4CLKSOURCE_HSI HSI selected as I2C4 clock + * @arg @ref RCC_I2C4CLKSOURCE_SYSCLK System Clock selected as I2C4 clock + */ +#define __HAL_RCC_GET_I2C4_SOURCE() (READ_BIT(RCC->CCIPR2, RCC_CCIPR2_I2C4SEL)) + +#endif /* I2C4 */ + + +/** @brief Macro to configure the USART1 clock (USART1CLK). + * + * @param __USART1_CLKSOURCE__ specifies the USART1 clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_USART1CLKSOURCE_PCLK2 PCLK2 selected as USART1 clock + * @arg @ref RCC_USART1CLKSOURCE_HSI HSI selected as USART1 clock + * @arg @ref RCC_USART1CLKSOURCE_SYSCLK System Clock selected as USART1 clock + * @arg @ref RCC_USART1CLKSOURCE_LSE SE selected as USART1 clock + * @retval None + */ +#define __HAL_RCC_USART1_CONFIG(__USART1_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_USART1SEL, (__USART1_CLKSOURCE__)) + +/** @brief Macro to get the USART1 clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_USART1CLKSOURCE_PCLK2 PCLK2 selected as USART1 clock + * @arg @ref RCC_USART1CLKSOURCE_HSI HSI selected as USART1 clock + * @arg @ref RCC_USART1CLKSOURCE_SYSCLK System Clock selected as USART1 clock + * @arg @ref RCC_USART1CLKSOURCE_LSE LSE selected as USART1 clock + */ +#define __HAL_RCC_GET_USART1_SOURCE() (READ_BIT(RCC->CCIPR, RCC_CCIPR_USART1SEL)) + +/** @brief Macro to configure the USART2 clock (USART2CLK). + * + * @param __USART2_CLKSOURCE__ specifies the USART2 clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_USART2CLKSOURCE_PCLK1 PCLK1 selected as USART2 clock + * @arg @ref RCC_USART2CLKSOURCE_HSI HSI selected as USART2 clock + * @arg @ref RCC_USART2CLKSOURCE_SYSCLK System Clock selected as USART2 clock + * @arg @ref RCC_USART2CLKSOURCE_LSE LSE selected as USART2 clock + * @retval None + */ +#define __HAL_RCC_USART2_CONFIG(__USART2_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_USART2SEL, (__USART2_CLKSOURCE__)) + +/** @brief Macro to get the USART2 clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_USART2CLKSOURCE_PCLK1 PCLK1 selected as USART2 clock + * @arg @ref RCC_USART2CLKSOURCE_HSI HSI selected as USART2 clock + * @arg @ref RCC_USART2CLKSOURCE_SYSCLK System Clock selected as USART2 clock + * @arg @ref RCC_USART2CLKSOURCE_LSE LSE selected as USART2 clock + */ +#define __HAL_RCC_GET_USART2_SOURCE() (READ_BIT(RCC->CCIPR, RCC_CCIPR_USART2SEL)) + +#if defined(USART3) + +/** @brief Macro to configure the USART3 clock (USART3CLK). + * + * @param __USART3_CLKSOURCE__ specifies the USART3 clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_USART3CLKSOURCE_PCLK1 PCLK1 selected as USART3 clock + * @arg @ref RCC_USART3CLKSOURCE_HSI HSI selected as USART3 clock + * @arg @ref RCC_USART3CLKSOURCE_SYSCLK System Clock selected as USART3 clock + * @arg @ref RCC_USART3CLKSOURCE_LSE LSE selected as USART3 clock + * @retval None + */ +#define __HAL_RCC_USART3_CONFIG(__USART3_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_USART3SEL, (__USART3_CLKSOURCE__)) + +/** @brief Macro to get the USART3 clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_USART3CLKSOURCE_PCLK1 PCLK1 selected as USART3 clock + * @arg @ref RCC_USART3CLKSOURCE_HSI HSI selected as USART3 clock + * @arg @ref RCC_USART3CLKSOURCE_SYSCLK System Clock selected as USART3 clock + * @arg @ref RCC_USART3CLKSOURCE_LSE LSE selected as USART3 clock + */ +#define __HAL_RCC_GET_USART3_SOURCE() (READ_BIT(RCC->CCIPR, RCC_CCIPR_USART3SEL)) + +#endif /* USART3 */ + +#if defined(UART4) + +/** @brief Macro to configure the UART4 clock (UART4CLK). + * + * @param __UART4_CLKSOURCE__ specifies the UART4 clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_UART4CLKSOURCE_PCLK1 PCLK1 selected as UART4 clock + * @arg @ref RCC_UART4CLKSOURCE_HSI HSI selected as UART4 clock + * @arg @ref RCC_UART4CLKSOURCE_SYSCLK System Clock selected as UART4 clock + * @arg @ref RCC_UART4CLKSOURCE_LSE LSE selected as UART4 clock + * @retval None + */ +#define __HAL_RCC_UART4_CONFIG(__UART4_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_UART4SEL, (__UART4_CLKSOURCE__)) + +/** @brief Macro to get the UART4 clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_UART4CLKSOURCE_PCLK1 PCLK1 selected as UART4 clock + * @arg @ref RCC_UART4CLKSOURCE_HSI HSI selected as UART4 clock + * @arg @ref RCC_UART4CLKSOURCE_SYSCLK System Clock selected as UART4 clock + * @arg @ref RCC_UART4CLKSOURCE_LSE LSE selected as UART4 clock + */ +#define __HAL_RCC_GET_UART4_SOURCE() (READ_BIT(RCC->CCIPR, RCC_CCIPR_UART4SEL)) + +#endif /* UART4 */ + +#if defined(UART5) + +/** @brief Macro to configure the UART5 clock (UART5CLK). + * + * @param __UART5_CLKSOURCE__ specifies the UART5 clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_UART5CLKSOURCE_PCLK1 PCLK1 selected as UART5 clock + * @arg @ref RCC_UART5CLKSOURCE_HSI HSI selected as UART5 clock + * @arg @ref RCC_UART5CLKSOURCE_SYSCLK System Clock selected as UART5 clock + * @arg @ref RCC_UART5CLKSOURCE_LSE LSE selected as UART5 clock + * @retval None + */ +#define __HAL_RCC_UART5_CONFIG(__UART5_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_UART5SEL, (__UART5_CLKSOURCE__)) + +/** @brief Macro to get the UART5 clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_UART5CLKSOURCE_PCLK1 PCLK1 selected as UART5 clock + * @arg @ref RCC_UART5CLKSOURCE_HSI HSI selected as UART5 clock + * @arg @ref RCC_UART5CLKSOURCE_SYSCLK System Clock selected as UART5 clock + * @arg @ref RCC_UART5CLKSOURCE_LSE LSE selected as UART5 clock + */ +#define __HAL_RCC_GET_UART5_SOURCE() (READ_BIT(RCC->CCIPR, RCC_CCIPR_UART5SEL)) + +#endif /* UART5 */ + +/** @brief Macro to configure the LPUART1 clock (LPUART1CLK). + * + * @param __LPUART1_CLKSOURCE__ specifies the LPUART1 clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_LPUART1CLKSOURCE_PCLK1 PCLK1 selected as LPUART1 clock + * @arg @ref RCC_LPUART1CLKSOURCE_HSI HSI selected as LPUART1 clock + * @arg @ref RCC_LPUART1CLKSOURCE_SYSCLK System Clock selected as LPUART1 clock + * @arg @ref RCC_LPUART1CLKSOURCE_LSE LSE selected as LPUART1 clock + * @retval None + */ +#define __HAL_RCC_LPUART1_CONFIG(__LPUART1_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_LPUART1SEL, (__LPUART1_CLKSOURCE__)) + +/** @brief Macro to get the LPUART1 clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_LPUART1CLKSOURCE_PCLK1 PCLK1 selected as LPUART1 clock + * @arg @ref RCC_LPUART1CLKSOURCE_HSI HSI selected as LPUART1 clock + * @arg @ref RCC_LPUART1CLKSOURCE_SYSCLK System Clock selected as LPUART1 clock + * @arg @ref RCC_LPUART1CLKSOURCE_LSE LSE selected as LPUART1 clock + */ +#define __HAL_RCC_GET_LPUART1_SOURCE() (READ_BIT(RCC->CCIPR, RCC_CCIPR_LPUART1SEL)) + +/** @brief Macro to configure the LPTIM1 clock (LPTIM1CLK). + * + * @param __LPTIM1_CLKSOURCE__ specifies the LPTIM1 clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_LPTIM1CLKSOURCE_PCLK1 PCLK1 selected as LPTIM1 clock + * @arg @ref RCC_LPTIM1CLKSOURCE_LSI HSI selected as LPTIM1 clock + * @arg @ref RCC_LPTIM1CLKSOURCE_HSI LSI selected as LPTIM1 clock + * @arg @ref RCC_LPTIM1CLKSOURCE_LSE LSE selected as LPTIM1 clock + * @retval None + */ +#define __HAL_RCC_LPTIM1_CONFIG(__LPTIM1_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_LPTIM1SEL, (__LPTIM1_CLKSOURCE__)) + +/** @brief Macro to get the LPTIM1 clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_LPTIM1CLKSOURCE_PCLK1 PCLK1 selected as LPUART1 clock + * @arg @ref RCC_LPTIM1CLKSOURCE_LSI HSI selected as LPUART1 clock + * @arg @ref RCC_LPTIM1CLKSOURCE_HSI System Clock selected as LPUART1 clock + * @arg @ref RCC_LPTIM1CLKSOURCE_LSE LSE selected as LPUART1 clock + */ +#define __HAL_RCC_GET_LPTIM1_SOURCE() (READ_BIT(RCC->CCIPR, RCC_CCIPR_LPTIM1SEL)) + +/** @brief Macro to configure the LPTIM2 clock (LPTIM2CLK). + * + * @param __LPTIM2_CLKSOURCE__ specifies the LPTIM2 clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_LPTIM2CLKSOURCE_PCLK1 PCLK1 selected as LPTIM2 clock + * @arg @ref RCC_LPTIM2CLKSOURCE_LSI HSI selected as LPTIM2 clock + * @arg @ref RCC_LPTIM2CLKSOURCE_HSI LSI selected as LPTIM2 clock + * @arg @ref RCC_LPTIM2CLKSOURCE_LSE LSE selected as LPTIM2 clock + * @retval None + */ +#define __HAL_RCC_LPTIM2_CONFIG(__LPTIM2_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_LPTIM2SEL, (__LPTIM2_CLKSOURCE__)) + +/** @brief Macro to get the LPTIM2 clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_LPTIM2CLKSOURCE_PCLK1 PCLK1 selected as LPUART1 clock + * @arg @ref RCC_LPTIM2CLKSOURCE_LSI HSI selected as LPUART1 clock + * @arg @ref RCC_LPTIM2CLKSOURCE_HSI System Clock selected as LPUART1 clock + * @arg @ref RCC_LPTIM2CLKSOURCE_LSE LSE selected as LPUART1 clock + */ +#define __HAL_RCC_GET_LPTIM2_SOURCE() (READ_BIT(RCC->CCIPR, RCC_CCIPR_LPTIM2SEL)) + +#if defined(SDMMC1) + +/** @brief Macro to configure the SDMMC1 clock. + * + @if STM32L486xx + * @note USB, RNG and SDMMC1 peripherals share the same 48MHz clock source. + @endif + * + @if STM32L443xx + * @note USB, RNG and SDMMC1 peripherals share the same 48MHz clock source. + @endif + * + * @param __SDMMC1_CLKSOURCE__ specifies the SDMMC1 clock source. + * This parameter can be one of the following values: + @if STM32L486xx + * @arg @ref RCC_SDMMC1CLKSOURCE_NONE No clock selected as SDMMC1 clock for devices without HSI48 + * @arg @ref RCC_SDMMC1CLKSOURCE_MSI MSI selected as SDMMC1 clock + * @arg @ref RCC_SDMMC1CLKSOURCE_PLLSAI1 PLLSAI1 "Q" Clock selected as SDMMC1 clock + @endif + @if STM32L443xx + * @arg @ref RCC_SDMMC1CLKSOURCE_HSI48 HSI48 selected as SDMMC1 clock for devices with HSI48 + * @arg @ref RCC_SDMMC1CLKSOURCE_MSI MSI selected as SDMMC1 clock + * @arg @ref RCC_SDMMC1CLKSOURCE_PLLSAI1 PLLSAI1 "Q" Clock selected as SDMMC1 clock + @endif + @if STM32L4S9xx + * @arg @ref RCC_SDMMC1CLKSOURCE_HSI48 HSI48 selected as SDMMC1 clock for devices with HSI48 + * @arg @ref RCC_SDMMC1CLKSOURCE_MSI MSI selected as SDMMC1 clock + * @arg @ref RCC_SDMMC1CLKSOURCE_PLLSAI1 PLLSAI1 "Q" Clock selected as SDMMC1 clock + * @arg @ref RCC_SDMMC1CLKSOURCE_PLLP PLL "P" Clock selected as SDMMC1 clock + @endif + * @arg @ref RCC_SDMMC1CLKSOURCE_PLL PLL "Q" Clock selected as SDMMC1 clock + * @retval None + */ +#if defined(RCC_CCIPR2_SDMMCSEL) +#define __HAL_RCC_SDMMC1_CONFIG(__SDMMC1_CLKSOURCE__) \ + do \ + { \ + if((__SDMMC1_CLKSOURCE__) == RCC_SDMMC1CLKSOURCE_PLLP) \ + { \ + SET_BIT(RCC->CCIPR2, RCC_CCIPR2_SDMMCSEL); \ + } \ + else \ + { \ + CLEAR_BIT(RCC->CCIPR2, RCC_CCIPR2_SDMMCSEL); \ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_CLK48SEL, (__SDMMC1_CLKSOURCE__)); \ + } \ + } while(0) +#else +#define __HAL_RCC_SDMMC1_CONFIG(__SDMMC1_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_CLK48SEL, (__SDMMC1_CLKSOURCE__)) +#endif /* RCC_CCIPR2_SDMMCSEL */ + +/** @brief Macro to get the SDMMC1 clock. + * @retval The clock source can be one of the following values: + @if STM32L486xx + * @arg @ref RCC_SDMMC1CLKSOURCE_NONE No clock selected as SDMMC1 clock for devices without HSI48 + * @arg @ref RCC_SDMMC1CLKSOURCE_MSI MSI selected as SDMMC1 clock + * @arg @ref RCC_SDMMC1CLKSOURCE_PLLSAI1 PLLSAI1 "Q" clock (PLL48M2CLK) selected as SDMMC1 clock + @endif + @if STM32L443xx + * @arg @ref RCC_SDMMC1CLKSOURCE_HSI48 HSI48 selected as SDMMC1 clock for devices with HSI48 + * @arg @ref RCC_SDMMC1CLKSOURCE_MSI MSI selected as SDMMC1 clock + * @arg @ref RCC_SDMMC1CLKSOURCE_PLLSAI1 PLLSAI1 "Q" clock (PLL48M2CLK) selected as SDMMC1 clock + @endif + @if STM32L4S9xx + * @arg @ref RCC_SDMMC1CLKSOURCE_HSI48 HSI48 selected as SDMMC1 clock for devices with HSI48 + * @arg @ref RCC_SDMMC1CLKSOURCE_MSI MSI selected as SDMMC1 clock + * @arg @ref RCC_SDMMC1CLKSOURCE_PLLSAI1 PLLSAI1 "Q" clock (PLL48M2CLK) selected as SDMMC1 clock + * @arg @ref RCC_SDMMC1CLKSOURCE_PLLP PLL "P" clock (PLLSAI3CLK) selected as SDMMC1 kernel clock + @endif + * @arg @ref RCC_SDMMC1CLKSOURCE_PLL PLL "Q" clock (PLL48M1CLK) selected as SDMMC1 clock + */ +#if defined(RCC_CCIPR2_SDMMCSEL) +#define __HAL_RCC_GET_SDMMC1_SOURCE() \ + ((READ_BIT(RCC->CCIPR2, RCC_CCIPR2_SDMMCSEL) != RESET) ? RCC_SDMMC1CLKSOURCE_PLLP : (READ_BIT(RCC->CCIPR, RCC_CCIPR_CLK48SEL))) +#else +#define __HAL_RCC_GET_SDMMC1_SOURCE() \ + (READ_BIT(RCC->CCIPR, RCC_CCIPR_CLK48SEL)) +#endif /* RCC_CCIPR2_SDMMCSEL */ + +#endif /* SDMMC1 */ + +/** @brief Macro to configure the RNG clock. + * + * @note USB, RNG and SDMMC1 peripherals share the same 48MHz clock source. + * + * @param __RNG_CLKSOURCE__ specifies the RNG clock source. + * This parameter can be one of the following values: + @if STM32L486xx + * @arg @ref RCC_RNGCLKSOURCE_NONE No clock selected as RNG clock for devices without HSI48 + @endif + @if STM32L443xx + * @arg @ref RCC_RNGCLKSOURCE_HSI48 HSI48 selected as RNG clock clock for devices with HSI48 + @endif + * @arg @ref RCC_RNGCLKSOURCE_MSI MSI selected as RNG clock + * @arg @ref RCC_RNGCLKSOURCE_PLLSAI1 PLLSAI1 Clock selected as RNG clock + * @arg @ref RCC_RNGCLKSOURCE_PLL PLL Clock selected as RNG clock + * @retval None + */ +#define __HAL_RCC_RNG_CONFIG(__RNG_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_CLK48SEL, (__RNG_CLKSOURCE__)) + +/** @brief Macro to get the RNG clock. + * @retval The clock source can be one of the following values: + @if STM32L486xx + * @arg @ref RCC_RNGCLKSOURCE_NONE No clock selected as RNG clock for devices without HSI48 + @endif + @if STM32L443xx + * @arg @ref RCC_RNGCLKSOURCE_HSI48 HSI48 selected as RNG clock clock for devices with HSI48 + @endif + * @arg @ref RCC_RNGCLKSOURCE_MSI MSI selected as RNG clock + * @arg @ref RCC_RNGCLKSOURCE_PLLSAI1 PLLSAI1 "Q" clock (PLL48M2CLK) selected as RNG clock + * @arg @ref RCC_RNGCLKSOURCE_PLL PLL "Q" clock (PLL48M1CLK) selected as RNG clock + */ +#define __HAL_RCC_GET_RNG_SOURCE() (READ_BIT(RCC->CCIPR, RCC_CCIPR_CLK48SEL)) + +#if defined(USB_OTG_FS) || defined(USB) + +/** @brief Macro to configure the USB clock (USBCLK). + * + * @note USB, RNG and SDMMC1 peripherals share the same 48MHz clock source. + * + * @param __USB_CLKSOURCE__ specifies the USB clock source. + * This parameter can be one of the following values: + @if STM32L486xx + * @arg @ref RCC_USBCLKSOURCE_NONE No clock selected as 48MHz clock for devices without HSI48 + @endif + @if STM32L443xx + * @arg @ref RCC_USBCLKSOURCE_HSI48 HSI48 selected as 48MHz clock for devices with HSI48 + @endif + * @arg @ref RCC_USBCLKSOURCE_MSI MSI selected as USB clock + * @arg @ref RCC_USBCLKSOURCE_PLLSAI1 PLLSAI1 "Q" clock (PLL48M2CLK) selected as USB clock + * @arg @ref RCC_USBCLKSOURCE_PLL PLL "Q" clock (PLL48M1CLK) selected as USB clock + * @retval None + */ +#define __HAL_RCC_USB_CONFIG(__USB_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_CLK48SEL, (__USB_CLKSOURCE__)) + +/** @brief Macro to get the USB clock source. + * @retval The clock source can be one of the following values: + @if STM32L486xx + * @arg @ref RCC_USBCLKSOURCE_NONE No clock selected as 48MHz clock for devices without HSI48 + @endif + @if STM32L443xx + * @arg @ref RCC_USBCLKSOURCE_HSI48 HSI48 selected as 48MHz clock for devices with HSI48 + @endif + * @arg @ref RCC_USBCLKSOURCE_MSI MSI selected as USB clock + * @arg @ref RCC_USBCLKSOURCE_PLLSAI1 PLLSAI1 "Q" clock (PLL48M2CLK) selected as USB clock + * @arg @ref RCC_USBCLKSOURCE_PLL PLL "Q" clock (PLL48M1CLK) selected as USB clock + */ +#define __HAL_RCC_GET_USB_SOURCE() (READ_BIT(RCC->CCIPR, RCC_CCIPR_CLK48SEL)) + +#endif /* USB_OTG_FS || USB */ + +/** @brief Macro to configure the ADC interface clock. + * @param __ADC_CLKSOURCE__ specifies the ADC digital interface clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_ADCCLKSOURCE_NONE No clock selected as ADC clock + * @arg @ref RCC_ADCCLKSOURCE_PLLSAI1 PLLSAI1 Clock selected as ADC clock + @if STM32L486xx + * @arg @ref RCC_ADCCLKSOURCE_PLLSAI2 PLLSAI2 Clock selected as ADC clock for STM32L47x/STM32L48x/STM32L49x/STM32L4Ax devices + @endif + * @arg @ref RCC_ADCCLKSOURCE_SYSCLK System Clock selected as ADC clock + * @retval None + */ +#define __HAL_RCC_ADC_CONFIG(__ADC_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_ADCSEL, (__ADC_CLKSOURCE__)) + +/** @brief Macro to get the ADC clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_ADCCLKSOURCE_NONE No clock selected as ADC clock + * @arg @ref RCC_ADCCLKSOURCE_PLLSAI1 PLLSAI1 Clock selected as ADC clock + @if STM32L486xx + * @arg @ref RCC_ADCCLKSOURCE_PLLSAI2 PLLSAI2 Clock selected as ADC clock for STM32L47x/STM32L48x/STM32L49x/STM32L4Ax devices + @endif + * @arg @ref RCC_ADCCLKSOURCE_SYSCLK System Clock selected as ADC clock + */ +#define __HAL_RCC_GET_ADC_SOURCE() (READ_BIT(RCC->CCIPR, RCC_CCIPR_ADCSEL)) + +#if defined(SWPMI1) + +/** @brief Macro to configure the SWPMI1 clock. + * @param __SWPMI1_CLKSOURCE__ specifies the SWPMI1 clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_SWPMI1CLKSOURCE_PCLK1 PCLK1 Clock selected as SWPMI1 clock + * @arg @ref RCC_SWPMI1CLKSOURCE_HSI HSI Clock selected as SWPMI1 clock + * @retval None + */ +#define __HAL_RCC_SWPMI1_CONFIG(__SWPMI1_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_SWPMI1SEL, (__SWPMI1_CLKSOURCE__)) + +/** @brief Macro to get the SWPMI1 clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_SWPMI1CLKSOURCE_PCLK1 PCLK1 Clock selected as SWPMI1 clock + * @arg @ref RCC_SWPMI1CLKSOURCE_HSI HSI Clock selected as SWPMI1 clock + */ +#define __HAL_RCC_GET_SWPMI1_SOURCE() (READ_BIT(RCC->CCIPR, RCC_CCIPR_SWPMI1SEL)) + +#endif /* SWPMI1 */ + +#if defined(DFSDM1_Filter0) +/** @brief Macro to configure the DFSDM1 clock. + * @param __DFSDM1_CLKSOURCE__ specifies the DFSDM1 clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_DFSDM1CLKSOURCE_PCLK2 PCLK2 Clock selected as DFSDM1 clock + * @arg @ref RCC_DFSDM1CLKSOURCE_SYSCLK System Clock selected as DFSDM1 clock + * @retval None + */ +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +#define __HAL_RCC_DFSDM1_CONFIG(__DFSDM1_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR2, RCC_CCIPR2_DFSDM1SEL, (__DFSDM1_CLKSOURCE__)) +#else +#define __HAL_RCC_DFSDM1_CONFIG(__DFSDM1_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_DFSDM1SEL, (__DFSDM1_CLKSOURCE__)) +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +/** @brief Macro to get the DFSDM1 clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_DFSDM1CLKSOURCE_PCLK2 PCLK2 Clock selected as DFSDM1 clock + * @arg @ref RCC_DFSDM1CLKSOURCE_SYSCLK System Clock selected as DFSDM1 clock + */ +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +#define __HAL_RCC_GET_DFSDM1_SOURCE() (READ_BIT(RCC->CCIPR2, RCC_CCIPR2_DFSDM1SEL)) +#else +#define __HAL_RCC_GET_DFSDM1_SOURCE() (READ_BIT(RCC->CCIPR, RCC_CCIPR_DFSDM1SEL)) +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + +/** @brief Macro to configure the DFSDM1 audio clock. + * @param __DFSDM1AUDIO_CLKSOURCE__ specifies the DFSDM1 audio clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_DFSDM1AUDIOCLKSOURCE_SAI1 SAI1 clock selected as DFSDM1 audio clock + * @arg @ref RCC_DFSDM1AUDIOCLKSOURCE_HSI HSI clock selected as DFSDM1 audio clock + * @arg @ref RCC_DFSDM1AUDIOCLKSOURCE_MSI MSI clock selected as DFSDM1 audio clock + * @retval None + */ +#define __HAL_RCC_DFSDM1AUDIO_CONFIG(__DFSDM1AUDIO_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR2, RCC_CCIPR2_ADFSDM1SEL, (__DFSDM1AUDIO_CLKSOURCE__)) + +/** @brief Macro to get the DFSDM1 audio clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_DFSDM1AUDIOCLKSOURCE_SAI1 SAI1 clock selected as DFSDM1 audio clock + * @arg @ref RCC_DFSDM1AUDIOCLKSOURCE_HSI HSI clock selected as DFSDM1 audio clock + * @arg @ref RCC_DFSDM1AUDIOCLKSOURCE_MSI MSI clock selected as DFSDM1 audio clock + */ +#define __HAL_RCC_GET_DFSDM1AUDIO_SOURCE() (READ_BIT(RCC->CCIPR2, RCC_CCIPR2_ADFSDM1SEL)) + +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#endif /* DFSDM1_Filter0 */ + +#if defined(LTDC) + +/** @brief Macro to configure the LTDC clock. + * @param __LTDC_CLKSOURCE__ specifies the DSI clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_LTDCCLKSOURCE_PLLSAI2_DIV2 PLLSAI2 divider R divided by 2 clock selected as LTDC clock + * @arg @ref RCC_LTDCCLKSOURCE_PLLSAI2_DIV4 PLLSAI2 divider R divided by 4 clock selected as LTDC clock + * @arg @ref RCC_LTDCCLKSOURCE_PLLSAI2_DIV8 PLLSAI2 divider R divided by 8 clock selected as LTDC clock + * @arg @ref RCC_LTDCCLKSOURCE_PLLSAI2_DIV16 PLLSAI2 divider R divided by 16 clock selected as LTDC clock + * @retval None + */ +#define __HAL_RCC_LTDC_CONFIG(__LTDC_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR2, RCC_CCIPR2_PLLSAI2DIVR, (__LTDC_CLKSOURCE__)) + +/** @brief Macro to get the LTDC clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_LTDCCLKSOURCE_PLLSAI2_DIV2 PLLSAI2 divider R divided by 2 clock selected as LTDC clock + * @arg @ref RCC_LTDCCLKSOURCE_PLLSAI2_DIV4 PLLSAI2 divider R divided by 4 clock selected as LTDC clock + * @arg @ref RCC_LTDCCLKSOURCE_PLLSAI2_DIV8 PLLSAI2 divider R divided by 8 clock selected as LTDC clock + * @arg @ref RCC_LTDCCLKSOURCE_PLLSAI2_DIV16 PLLSAI2 divider R divided by 16 clock selected as LTDC clock + */ +#define __HAL_RCC_GET_LTDC_SOURCE() (READ_BIT(RCC->CCIPR2, RCC_CCIPR2_PLLSAI2DIVR)) + +#endif /* LTDC */ + +#if defined(DSI) + +/** @brief Macro to configure the DSI clock. + * @param __DSI_CLKSOURCE__ specifies the DSI clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_DSICLKSOURCE_DSIPHY DSI-PHY clock selected as DSI clock + * @arg @ref RCC_DSICLKSOURCE_PLLSAI2 PLLSAI2 R divider clock selected as DSI clock + * @retval None + */ +#define __HAL_RCC_DSI_CONFIG(__DSI_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR2, RCC_CCIPR2_DSISEL, (__DSI_CLKSOURCE__)) + +/** @brief Macro to get the DSI clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_DSICLKSOURCE_DSIPHY DSI-PHY clock selected as DSI clock + * @arg @ref RCC_DSICLKSOURCE_PLLSAI2 PLLSAI2 R divider clock selected as DSI clock + */ +#define __HAL_RCC_GET_DSI_SOURCE() (READ_BIT(RCC->CCIPR2, RCC_CCIPR2_DSISEL)) + +#endif /* DSI */ + +#if defined(OCTOSPI1) || defined(OCTOSPI2) + +/** @brief Macro to configure the OctoSPI clock. + * @param __OSPI_CLKSOURCE__ specifies the OctoSPI clock source. + * This parameter can be one of the following values: + * @arg @ref RCC_OSPICLKSOURCE_SYSCLK System Clock selected as OctoSPI clock + * @arg @ref RCC_OSPICLKSOURCE_MSI MSI clock selected as OctoSPI clock + * @arg @ref RCC_OSPICLKSOURCE_PLL PLL Q divider clock selected as OctoSPI clock + * @retval None + */ +#define __HAL_RCC_OSPI_CONFIG(__OSPI_CLKSOURCE__) \ + MODIFY_REG(RCC->CCIPR2, RCC_CCIPR2_OSPISEL, (__OSPI_CLKSOURCE__)) + +/** @brief Macro to get the OctoSPI clock source. + * @retval The clock source can be one of the following values: + * @arg @ref RCC_OSPICLKSOURCE_SYSCLK System Clock selected as OctoSPI clock + * @arg @ref RCC_OSPICLKSOURCE_MSI MSI clock selected as OctoSPI clock + * @arg @ref RCC_OSPICLKSOURCE_PLL PLL Q divider clock selected as OctoSPI clock + */ +#define __HAL_RCC_GET_OSPI_SOURCE() (READ_BIT(RCC->CCIPR2, RCC_CCIPR2_OSPISEL)) + +#endif /* OCTOSPI1 || OCTOSPI2 */ + +/** @defgroup RCCEx_Flags_Interrupts_Management Flags Interrupts Management + * @brief macros to manage the specified RCC Flags and interrupts. + * @{ + */ + +/** @brief Enable PLLSAI1RDY interrupt. + * @retval None + */ +#define __HAL_RCC_PLLSAI1_ENABLE_IT() SET_BIT(RCC->CIER, RCC_CIER_PLLSAI1RDYIE) + +/** @brief Disable PLLSAI1RDY interrupt. + * @retval None + */ +#define __HAL_RCC_PLLSAI1_DISABLE_IT() CLEAR_BIT(RCC->CIER, RCC_CIER_PLLSAI1RDYIE) + +/** @brief Clear the PLLSAI1RDY interrupt pending bit. + * @retval None + */ +#define __HAL_RCC_PLLSAI1_CLEAR_IT() WRITE_REG(RCC->CICR, RCC_CICR_PLLSAI1RDYC) + +/** @brief Check whether PLLSAI1RDY interrupt has occurred or not. + * @retval TRUE or FALSE. + */ +#define __HAL_RCC_PLLSAI1_GET_IT_SOURCE() (READ_BIT(RCC->CIFR, RCC_CIFR_PLLSAI1RDYF) == RCC_CIFR_PLLSAI1RDYF) + +/** @brief Check whether the PLLSAI1RDY flag is set or not. + * @retval TRUE or FALSE. + */ +#define __HAL_RCC_PLLSAI1_GET_FLAG() (READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) == (RCC_CR_PLLSAI1RDY)) + +#if defined(RCC_PLLSAI2_SUPPORT) + +/** @brief Enable PLLSAI2RDY interrupt. + * @retval None + */ +#define __HAL_RCC_PLLSAI2_ENABLE_IT() SET_BIT(RCC->CIER, RCC_CIER_PLLSAI2RDYIE) + +/** @brief Disable PLLSAI2RDY interrupt. + * @retval None + */ +#define __HAL_RCC_PLLSAI2_DISABLE_IT() CLEAR_BIT(RCC->CIER, RCC_CIER_PLLSAI2RDYIE) + +/** @brief Clear the PLLSAI2RDY interrupt pending bit. + * @retval None + */ +#define __HAL_RCC_PLLSAI2_CLEAR_IT() WRITE_REG(RCC->CICR, RCC_CICR_PLLSAI2RDYC) + +/** @brief Check whether the PLLSAI2RDY interrupt has occurred or not. + * @retval TRUE or FALSE. + */ +#define __HAL_RCC_PLLSAI2_GET_IT_SOURCE() (READ_BIT(RCC->CIFR, RCC_CIFR_PLLSAI2RDYF) == RCC_CIFR_PLLSAI2RDYF) + +/** @brief Check whether the PLLSAI2RDY flag is set or not. + * @retval TRUE or FALSE. + */ +#define __HAL_RCC_PLLSAI2_GET_FLAG() (READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) == (RCC_CR_PLLSAI2RDY)) + +#endif /* RCC_PLLSAI2_SUPPORT */ + + +/** + * @brief Enable the RCC LSE CSS Extended Interrupt Line. + * @retval None + */ +#define __HAL_RCC_LSECSS_EXTI_ENABLE_IT() SET_BIT(EXTI->IMR1, RCC_EXTI_LINE_LSECSS) + +/** + * @brief Disable the RCC LSE CSS Extended Interrupt Line. + * @retval None + */ +#define __HAL_RCC_LSECSS_EXTI_DISABLE_IT() CLEAR_BIT(EXTI->IMR1, RCC_EXTI_LINE_LSECSS) + +/** + * @brief Enable the RCC LSE CSS Event Line. + * @retval None. + */ +#define __HAL_RCC_LSECSS_EXTI_ENABLE_EVENT() SET_BIT(EXTI->EMR1, RCC_EXTI_LINE_LSECSS) + +/** + * @brief Disable the RCC LSE CSS Event Line. + * @retval None. + */ +#define __HAL_RCC_LSECSS_EXTI_DISABLE_EVENT() CLEAR_BIT(EXTI->EMR1, RCC_EXTI_LINE_LSECSS) + + +/** + * @brief Enable the RCC LSE CSS Extended Interrupt Falling Trigger. + * @retval None. + */ +#define __HAL_RCC_LSECSS_EXTI_ENABLE_FALLING_EDGE() SET_BIT(EXTI->FTSR1, RCC_EXTI_LINE_LSECSS) + + +/** + * @brief Disable the RCC LSE CSS Extended Interrupt Falling Trigger. + * @retval None. + */ +#define __HAL_RCC_LSECSS_EXTI_DISABLE_FALLING_EDGE() CLEAR_BIT(EXTI->FTSR1, RCC_EXTI_LINE_LSECSS) + + +/** + * @brief Enable the RCC LSE CSS Extended Interrupt Rising Trigger. + * @retval None. + */ +#define __HAL_RCC_LSECSS_EXTI_ENABLE_RISING_EDGE() SET_BIT(EXTI->RTSR1, RCC_EXTI_LINE_LSECSS) + +/** + * @brief Disable the RCC LSE CSS Extended Interrupt Rising Trigger. + * @retval None. + */ +#define __HAL_RCC_LSECSS_EXTI_DISABLE_RISING_EDGE() CLEAR_BIT(EXTI->RTSR1, RCC_EXTI_LINE_LSECSS) + +/** + * @brief Enable the RCC LSE CSS Extended Interrupt Rising & Falling Trigger. + * @retval None. + */ +#define __HAL_RCC_LSECSS_EXTI_ENABLE_RISING_FALLING_EDGE() \ + do { \ + __HAL_RCC_LSECSS_EXTI_ENABLE_RISING_EDGE(); \ + __HAL_RCC_LSECSS_EXTI_ENABLE_FALLING_EDGE(); \ + } while(0) + +/** + * @brief Disable the RCC LSE CSS Extended Interrupt Rising & Falling Trigger. + * @retval None. + */ +#define __HAL_RCC_LSECSS_EXTI_DISABLE_RISING_FALLING_EDGE() \ + do { \ + __HAL_RCC_LSECSS_EXTI_DISABLE_RISING_EDGE(); \ + __HAL_RCC_LSECSS_EXTI_DISABLE_FALLING_EDGE(); \ + } while(0) + +/** + * @brief Check whether the specified RCC LSE CSS EXTI interrupt flag is set or not. + * @retval EXTI RCC LSE CSS Line Status. + */ +#define __HAL_RCC_LSECSS_EXTI_GET_FLAG() (READ_BIT(EXTI->PR1, RCC_EXTI_LINE_LSECSS) == RCC_EXTI_LINE_LSECSS) + +/** + * @brief Clear the RCC LSE CSS EXTI flag. + * @retval None. + */ +#define __HAL_RCC_LSECSS_EXTI_CLEAR_FLAG() WRITE_REG(EXTI->PR1, RCC_EXTI_LINE_LSECSS) + +/** + * @brief Generate a Software interrupt on the RCC LSE CSS EXTI line. + * @retval None. + */ +#define __HAL_RCC_LSECSS_EXTI_GENERATE_SWIT() SET_BIT(EXTI->SWIER1, RCC_EXTI_LINE_LSECSS) + + +#if defined(CRS) + +/** + * @brief Enable the specified CRS interrupts. + * @param __INTERRUPT__ specifies the CRS interrupt sources to be enabled. + * This parameter can be any combination of the following values: + * @arg @ref RCC_CRS_IT_SYNCOK SYNC event OK interrupt + * @arg @ref RCC_CRS_IT_SYNCWARN SYNC warning interrupt + * @arg @ref RCC_CRS_IT_ERR Synchronization or trimming error interrupt + * @arg @ref RCC_CRS_IT_ESYNC Expected SYNC interrupt + * @retval None + */ +#define __HAL_RCC_CRS_ENABLE_IT(__INTERRUPT__) SET_BIT(CRS->CR, (__INTERRUPT__)) + +/** + * @brief Disable the specified CRS interrupts. + * @param __INTERRUPT__ specifies the CRS interrupt sources to be disabled. + * This parameter can be any combination of the following values: + * @arg @ref RCC_CRS_IT_SYNCOK SYNC event OK interrupt + * @arg @ref RCC_CRS_IT_SYNCWARN SYNC warning interrupt + * @arg @ref RCC_CRS_IT_ERR Synchronization or trimming error interrupt + * @arg @ref RCC_CRS_IT_ESYNC Expected SYNC interrupt + * @retval None + */ +#define __HAL_RCC_CRS_DISABLE_IT(__INTERRUPT__) CLEAR_BIT(CRS->CR, (__INTERRUPT__)) + +/** @brief Check whether the CRS interrupt has occurred or not. + * @param __INTERRUPT__ specifies the CRS interrupt source to check. + * This parameter can be one of the following values: + * @arg @ref RCC_CRS_IT_SYNCOK SYNC event OK interrupt + * @arg @ref RCC_CRS_IT_SYNCWARN SYNC warning interrupt + * @arg @ref RCC_CRS_IT_ERR Synchronization or trimming error interrupt + * @arg @ref RCC_CRS_IT_ESYNC Expected SYNC interrupt + * @retval The new state of __INTERRUPT__ (SET or RESET). + */ +#define __HAL_RCC_CRS_GET_IT_SOURCE(__INTERRUPT__) ((READ_BIT(CRS->CR, (__INTERRUPT__)) != RESET) ? SET : RESET) + +/** @brief Clear the CRS interrupt pending bits + * @param __INTERRUPT__ specifies the interrupt pending bit to clear. + * This parameter can be any combination of the following values: + * @arg @ref RCC_CRS_IT_SYNCOK SYNC event OK interrupt + * @arg @ref RCC_CRS_IT_SYNCWARN SYNC warning interrupt + * @arg @ref RCC_CRS_IT_ERR Synchronization or trimming error interrupt + * @arg @ref RCC_CRS_IT_ESYNC Expected SYNC interrupt + * @arg @ref RCC_CRS_IT_TRIMOVF Trimming overflow or underflow interrupt + * @arg @ref RCC_CRS_IT_SYNCERR SYNC error interrupt + * @arg @ref RCC_CRS_IT_SYNCMISS SYNC missed interrupt + */ +/* CRS IT Error Mask */ +#define RCC_CRS_IT_ERROR_MASK (RCC_CRS_IT_TRIMOVF | RCC_CRS_IT_SYNCERR | RCC_CRS_IT_SYNCMISS) + +#define __HAL_RCC_CRS_CLEAR_IT(__INTERRUPT__) do { \ + if(((__INTERRUPT__) & RCC_CRS_IT_ERROR_MASK) != RESET) \ + { \ + WRITE_REG(CRS->ICR, CRS_ICR_ERRC | ((__INTERRUPT__) & ~RCC_CRS_IT_ERROR_MASK)); \ + } \ + else \ + { \ + WRITE_REG(CRS->ICR, (__INTERRUPT__)); \ + } \ + } while(0) + +/** + * @brief Check whether the specified CRS flag is set or not. + * @param __FLAG__ specifies the flag to check. + * This parameter can be one of the following values: + * @arg @ref RCC_CRS_FLAG_SYNCOK SYNC event OK + * @arg @ref RCC_CRS_FLAG_SYNCWARN SYNC warning + * @arg @ref RCC_CRS_FLAG_ERR Error + * @arg @ref RCC_CRS_FLAG_ESYNC Expected SYNC + * @arg @ref RCC_CRS_FLAG_TRIMOVF Trimming overflow or underflow + * @arg @ref RCC_CRS_FLAG_SYNCERR SYNC error + * @arg @ref RCC_CRS_FLAG_SYNCMISS SYNC missed + * @retval The new state of _FLAG_ (TRUE or FALSE). + */ +#define __HAL_RCC_CRS_GET_FLAG(__FLAG__) (READ_BIT(CRS->ISR, (__FLAG__)) == (__FLAG__)) + +/** + * @brief Clear the CRS specified FLAG. + * @param __FLAG__ specifies the flag to clear. + * This parameter can be one of the following values: + * @arg @ref RCC_CRS_FLAG_SYNCOK SYNC event OK + * @arg @ref RCC_CRS_FLAG_SYNCWARN SYNC warning + * @arg @ref RCC_CRS_FLAG_ERR Error + * @arg @ref RCC_CRS_FLAG_ESYNC Expected SYNC + * @arg @ref RCC_CRS_FLAG_TRIMOVF Trimming overflow or underflow + * @arg @ref RCC_CRS_FLAG_SYNCERR SYNC error + * @arg @ref RCC_CRS_FLAG_SYNCMISS SYNC missed + * @note RCC_CRS_FLAG_ERR clears RCC_CRS_FLAG_TRIMOVF, RCC_CRS_FLAG_SYNCERR, RCC_CRS_FLAG_SYNCMISS and consequently RCC_CRS_FLAG_ERR + * @retval None + */ + +/* CRS Flag Error Mask */ +#define RCC_CRS_FLAG_ERROR_MASK (RCC_CRS_FLAG_TRIMOVF | RCC_CRS_FLAG_SYNCERR | RCC_CRS_FLAG_SYNCMISS) + +#define __HAL_RCC_CRS_CLEAR_FLAG(__FLAG__) do { \ + if(((__FLAG__) & RCC_CRS_FLAG_ERROR_MASK) != RESET) \ + { \ + WRITE_REG(CRS->ICR, CRS_ICR_ERRC | ((__FLAG__) & ~RCC_CRS_FLAG_ERROR_MASK)); \ + } \ + else \ + { \ + WRITE_REG(CRS->ICR, (__FLAG__)); \ + } \ + } while(0) + +#endif /* CRS */ + +/** + * @} + */ + +#if defined(CRS) + +/** @defgroup RCCEx_CRS_Extended_Features RCCEx CRS Extended Features + * @{ + */ +/** + * @brief Enable the oscillator clock for frequency error counter. + * @note when the CEN bit is set the CRS_CFGR register becomes write-protected. + * @retval None + */ +#define __HAL_RCC_CRS_FREQ_ERROR_COUNTER_ENABLE() SET_BIT(CRS->CR, CRS_CR_CEN) + +/** + * @brief Disable the oscillator clock for frequency error counter. + * @retval None + */ +#define __HAL_RCC_CRS_FREQ_ERROR_COUNTER_DISABLE() CLEAR_BIT(CRS->CR, CRS_CR_CEN) + +/** + * @brief Enable the automatic hardware adjustement of TRIM bits. + * @note When the AUTOTRIMEN bit is set the CRS_CFGR register becomes write-protected. + * @retval None + */ +#define __HAL_RCC_CRS_AUTOMATIC_CALIB_ENABLE() SET_BIT(CRS->CR, CRS_CR_AUTOTRIMEN) + +/** + * @brief Enable or disable the automatic hardware adjustement of TRIM bits. + * @retval None + */ +#define __HAL_RCC_CRS_AUTOMATIC_CALIB_DISABLE() CLEAR_BIT(CRS->CR, CRS_CR_AUTOTRIMEN) + +/** + * @brief Macro to calculate reload value to be set in CRS register according to target and sync frequencies + * @note The RELOAD value should be selected according to the ratio between the target frequency and the frequency + * of the synchronization source after prescaling. It is then decreased by one in order to + * reach the expected synchronization on the zero value. The formula is the following: + * RELOAD = (fTARGET / fSYNC) -1 + * @param __FTARGET__ Target frequency (value in Hz) + * @param __FSYNC__ Synchronization signal frequency (value in Hz) + * @retval None + */ +#define __HAL_RCC_CRS_RELOADVALUE_CALCULATE(__FTARGET__, __FSYNC__) (((__FTARGET__) / (__FSYNC__)) - 1U) + +/** + * @} + */ + +#endif /* CRS */ + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup RCCEx_Exported_Functions + * @{ + */ + +/** @addtogroup RCCEx_Exported_Functions_Group1 + * @{ + */ + +HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit); +void HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit); +uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk); + +/** + * @} + */ + +/** @addtogroup RCCEx_Exported_Functions_Group2 + * @{ + */ + +HAL_StatusTypeDef HAL_RCCEx_EnablePLLSAI1(RCC_PLLSAI1InitTypeDef *PLLSAI1Init); +HAL_StatusTypeDef HAL_RCCEx_DisablePLLSAI1(void); + +#if defined(RCC_PLLSAI2_SUPPORT) + +HAL_StatusTypeDef HAL_RCCEx_EnablePLLSAI2(RCC_PLLSAI2InitTypeDef *PLLSAI2Init); +HAL_StatusTypeDef HAL_RCCEx_DisablePLLSAI2(void); + +#endif /* RCC_PLLSAI2_SUPPORT */ + +void HAL_RCCEx_WakeUpStopCLKConfig(uint32_t WakeUpClk); +void HAL_RCCEx_StandbyMSIRangeConfig(uint32_t MSIRange); +void HAL_RCCEx_EnableLSECSS(void); +void HAL_RCCEx_DisableLSECSS(void); +void HAL_RCCEx_EnableLSECSS_IT(void); +void HAL_RCCEx_LSECSS_IRQHandler(void); +void HAL_RCCEx_LSECSS_Callback(void); +void HAL_RCCEx_EnableLSCO(uint32_t LSCOSource); +void HAL_RCCEx_DisableLSCO(void); +void HAL_RCCEx_EnableMSIPLLMode(void); +void HAL_RCCEx_DisableMSIPLLMode(void); + +/** + * @} + */ + +#if defined(CRS) + +/** @addtogroup RCCEx_Exported_Functions_Group3 + * @{ + */ + +void HAL_RCCEx_CRSConfig(RCC_CRSInitTypeDef *pInit); +void HAL_RCCEx_CRSSoftwareSynchronizationGenerate(void); +void HAL_RCCEx_CRSGetSynchronizationInfo(RCC_CRSSynchroInfoTypeDef *pSynchroInfo); +uint32_t HAL_RCCEx_CRSWaitSynchronization(uint32_t Timeout); +void HAL_RCCEx_CRS_IRQHandler(void); +void HAL_RCCEx_CRS_SyncOkCallback(void); +void HAL_RCCEx_CRS_SyncWarnCallback(void); +void HAL_RCCEx_CRS_ExpectedSyncCallback(void); +void HAL_RCCEx_CRS_ErrorCallback(uint32_t Error); + +/** + * @} + */ + +#endif /* CRS */ + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @addtogroup RCCEx_Private_Macros + * @{ + */ + +#define IS_RCC_LSCOSOURCE(__SOURCE__) (((__SOURCE__) == RCC_LSCOSOURCE_LSI) || \ + ((__SOURCE__) == RCC_LSCOSOURCE_LSE)) + +#if defined(STM32L431xx) + +#define IS_RCC_PERIPHCLOCK(__SELECTION__) \ + ((((__SELECTION__) & RCC_PERIPHCLK_USART1) == RCC_PERIPHCLK_USART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART2) == RCC_PERIPHCLK_USART2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART3) == RCC_PERIPHCLK_USART3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPUART1) == RCC_PERIPHCLK_LPUART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C1) == RCC_PERIPHCLK_I2C1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C2) == RCC_PERIPHCLK_I2C2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C3) == RCC_PERIPHCLK_I2C3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM1) == RCC_PERIPHCLK_LPTIM1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM2) == RCC_PERIPHCLK_LPTIM2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_ADC) == RCC_PERIPHCLK_ADC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SWPMI1) == RCC_PERIPHCLK_SWPMI1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RNG) == RCC_PERIPHCLK_RNG) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SDMMC1) == RCC_PERIPHCLK_SDMMC1)) + +#elif defined(STM32L432xx) || defined(STM32L442xx) + +#define IS_RCC_PERIPHCLOCK(__SELECTION__) \ + ((((__SELECTION__) & RCC_PERIPHCLK_USART1) == RCC_PERIPHCLK_USART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART2) == RCC_PERIPHCLK_USART2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPUART1) == RCC_PERIPHCLK_LPUART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C1) == RCC_PERIPHCLK_I2C1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C3) == RCC_PERIPHCLK_I2C3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM1) == RCC_PERIPHCLK_LPTIM1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM2) == RCC_PERIPHCLK_LPTIM2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USB) == RCC_PERIPHCLK_USB) || \ + (((__SELECTION__) & RCC_PERIPHCLK_ADC) == RCC_PERIPHCLK_ADC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SWPMI1) == RCC_PERIPHCLK_SWPMI1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RNG) == RCC_PERIPHCLK_RNG)) + +#elif defined(STM32L433xx) || defined(STM32L443xx) + +#define IS_RCC_PERIPHCLOCK(__SELECTION__) \ + ((((__SELECTION__) & RCC_PERIPHCLK_USART1) == RCC_PERIPHCLK_USART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART2) == RCC_PERIPHCLK_USART2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART3) == RCC_PERIPHCLK_USART3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPUART1) == RCC_PERIPHCLK_LPUART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C1) == RCC_PERIPHCLK_I2C1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C2) == RCC_PERIPHCLK_I2C2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C3) == RCC_PERIPHCLK_I2C3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM1) == RCC_PERIPHCLK_LPTIM1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM2) == RCC_PERIPHCLK_LPTIM2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USB) == RCC_PERIPHCLK_USB) || \ + (((__SELECTION__) & RCC_PERIPHCLK_ADC) == RCC_PERIPHCLK_ADC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SWPMI1) == RCC_PERIPHCLK_SWPMI1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RNG) == RCC_PERIPHCLK_RNG) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SDMMC1) == RCC_PERIPHCLK_SDMMC1)) + +#elif defined(STM32L451xx) + +#define IS_RCC_PERIPHCLOCK(__SELECTION__) \ + ((((__SELECTION__) & RCC_PERIPHCLK_USART1) == RCC_PERIPHCLK_USART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART2) == RCC_PERIPHCLK_USART2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART3) == RCC_PERIPHCLK_USART3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_UART4) == RCC_PERIPHCLK_UART4) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPUART1) == RCC_PERIPHCLK_LPUART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C1) == RCC_PERIPHCLK_I2C1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C2) == RCC_PERIPHCLK_I2C2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C3) == RCC_PERIPHCLK_I2C3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C4) == RCC_PERIPHCLK_I2C4) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM1) == RCC_PERIPHCLK_LPTIM1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM2) == RCC_PERIPHCLK_LPTIM2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_ADC) == RCC_PERIPHCLK_ADC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_DFSDM1) == RCC_PERIPHCLK_DFSDM1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RNG) == RCC_PERIPHCLK_RNG) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SDMMC1) == RCC_PERIPHCLK_SDMMC1)) + +#elif defined(STM32L452xx) || defined(STM32L462xx) + +#define IS_RCC_PERIPHCLOCK(__SELECTION__) \ + ((((__SELECTION__) & RCC_PERIPHCLK_USART1) == RCC_PERIPHCLK_USART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART2) == RCC_PERIPHCLK_USART2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART3) == RCC_PERIPHCLK_USART3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_UART4) == RCC_PERIPHCLK_UART4) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPUART1) == RCC_PERIPHCLK_LPUART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C1) == RCC_PERIPHCLK_I2C1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C2) == RCC_PERIPHCLK_I2C2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C3) == RCC_PERIPHCLK_I2C3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C4) == RCC_PERIPHCLK_I2C4) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM1) == RCC_PERIPHCLK_LPTIM1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM2) == RCC_PERIPHCLK_LPTIM2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USB) == RCC_PERIPHCLK_USB) || \ + (((__SELECTION__) & RCC_PERIPHCLK_ADC) == RCC_PERIPHCLK_ADC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_DFSDM1) == RCC_PERIPHCLK_DFSDM1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RNG) == RCC_PERIPHCLK_RNG) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SDMMC1) == RCC_PERIPHCLK_SDMMC1)) + +#elif defined(STM32L471xx) + +#define IS_RCC_PERIPHCLOCK(__SELECTION__) \ + ((((__SELECTION__) & RCC_PERIPHCLK_USART1) == RCC_PERIPHCLK_USART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART2) == RCC_PERIPHCLK_USART2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART3) == RCC_PERIPHCLK_USART3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_UART4) == RCC_PERIPHCLK_UART4) || \ + (((__SELECTION__) & RCC_PERIPHCLK_UART5) == RCC_PERIPHCLK_UART5) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPUART1) == RCC_PERIPHCLK_LPUART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C1) == RCC_PERIPHCLK_I2C1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C2) == RCC_PERIPHCLK_I2C2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C3) == RCC_PERIPHCLK_I2C3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM1) == RCC_PERIPHCLK_LPTIM1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM2) == RCC_PERIPHCLK_LPTIM2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SAI2) == RCC_PERIPHCLK_SAI2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_ADC) == RCC_PERIPHCLK_ADC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SWPMI1) == RCC_PERIPHCLK_SWPMI1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_DFSDM1) == RCC_PERIPHCLK_DFSDM1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RNG) == RCC_PERIPHCLK_RNG) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SDMMC1) == RCC_PERIPHCLK_SDMMC1)) + +#elif defined(STM32L496xx) || defined(STM32L4A6xx) + +#define IS_RCC_PERIPHCLOCK(__SELECTION__) \ + ((((__SELECTION__) & RCC_PERIPHCLK_USART1) == RCC_PERIPHCLK_USART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART2) == RCC_PERIPHCLK_USART2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART3) == RCC_PERIPHCLK_USART3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_UART4) == RCC_PERIPHCLK_UART4) || \ + (((__SELECTION__) & RCC_PERIPHCLK_UART5) == RCC_PERIPHCLK_UART5) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPUART1) == RCC_PERIPHCLK_LPUART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C1) == RCC_PERIPHCLK_I2C1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C2) == RCC_PERIPHCLK_I2C2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C3) == RCC_PERIPHCLK_I2C3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C4) == RCC_PERIPHCLK_I2C4) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM1) == RCC_PERIPHCLK_LPTIM1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM2) == RCC_PERIPHCLK_LPTIM2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SAI2) == RCC_PERIPHCLK_SAI2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USB) == RCC_PERIPHCLK_USB) || \ + (((__SELECTION__) & RCC_PERIPHCLK_ADC) == RCC_PERIPHCLK_ADC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SWPMI1) == RCC_PERIPHCLK_SWPMI1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_DFSDM1) == RCC_PERIPHCLK_DFSDM1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RNG) == RCC_PERIPHCLK_RNG) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SDMMC1) == RCC_PERIPHCLK_SDMMC1)) + +#elif defined(STM32L4R5xx) || defined(STM32L4S5xx) + +#define IS_RCC_PERIPHCLOCK(__SELECTION__) \ + ((((__SELECTION__) & RCC_PERIPHCLK_USART1) == RCC_PERIPHCLK_USART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART2) == RCC_PERIPHCLK_USART2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART3) == RCC_PERIPHCLK_USART3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_UART4) == RCC_PERIPHCLK_UART4) || \ + (((__SELECTION__) & RCC_PERIPHCLK_UART5) == RCC_PERIPHCLK_UART5) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPUART1) == RCC_PERIPHCLK_LPUART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C1) == RCC_PERIPHCLK_I2C1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C2) == RCC_PERIPHCLK_I2C2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C3) == RCC_PERIPHCLK_I2C3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C4) == RCC_PERIPHCLK_I2C4) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM1) == RCC_PERIPHCLK_LPTIM1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM2) == RCC_PERIPHCLK_LPTIM2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SAI2) == RCC_PERIPHCLK_SAI2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USB) == RCC_PERIPHCLK_USB) || \ + (((__SELECTION__) & RCC_PERIPHCLK_ADC) == RCC_PERIPHCLK_ADC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_DFSDM1) == RCC_PERIPHCLK_DFSDM1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_DFSDM1AUDIO) == RCC_PERIPHCLK_DFSDM1AUDIO) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RNG) == RCC_PERIPHCLK_RNG) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SDMMC1) == RCC_PERIPHCLK_SDMMC1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_OSPI) == RCC_PERIPHCLK_OSPI)) + +#elif defined(STM32L4R7xx) || defined(STM32L4S7xx) + +#define IS_RCC_PERIPHCLOCK(__SELECTION__) \ + ((((__SELECTION__) & RCC_PERIPHCLK_USART1) == RCC_PERIPHCLK_USART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART2) == RCC_PERIPHCLK_USART2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART3) == RCC_PERIPHCLK_USART3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_UART4) == RCC_PERIPHCLK_UART4) || \ + (((__SELECTION__) & RCC_PERIPHCLK_UART5) == RCC_PERIPHCLK_UART5) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPUART1) == RCC_PERIPHCLK_LPUART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C1) == RCC_PERIPHCLK_I2C1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C2) == RCC_PERIPHCLK_I2C2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C3) == RCC_PERIPHCLK_I2C3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C4) == RCC_PERIPHCLK_I2C4) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM1) == RCC_PERIPHCLK_LPTIM1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM2) == RCC_PERIPHCLK_LPTIM2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SAI2) == RCC_PERIPHCLK_SAI2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USB) == RCC_PERIPHCLK_USB) || \ + (((__SELECTION__) & RCC_PERIPHCLK_ADC) == RCC_PERIPHCLK_ADC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_DFSDM1) == RCC_PERIPHCLK_DFSDM1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_DFSDM1AUDIO) == RCC_PERIPHCLK_DFSDM1AUDIO) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RNG) == RCC_PERIPHCLK_RNG) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SDMMC1) == RCC_PERIPHCLK_SDMMC1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_OSPI) == RCC_PERIPHCLK_OSPI) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LTDC) == RCC_PERIPHCLK_LTDC)) + +#elif defined(STM32L4R9xx) || defined(STM32L4S9xx) + +#define IS_RCC_PERIPHCLOCK(__SELECTION__) \ + ((((__SELECTION__) & RCC_PERIPHCLK_USART1) == RCC_PERIPHCLK_USART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART2) == RCC_PERIPHCLK_USART2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART3) == RCC_PERIPHCLK_USART3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_UART4) == RCC_PERIPHCLK_UART4) || \ + (((__SELECTION__) & RCC_PERIPHCLK_UART5) == RCC_PERIPHCLK_UART5) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPUART1) == RCC_PERIPHCLK_LPUART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C1) == RCC_PERIPHCLK_I2C1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C2) == RCC_PERIPHCLK_I2C2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C3) == RCC_PERIPHCLK_I2C3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C4) == RCC_PERIPHCLK_I2C4) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM1) == RCC_PERIPHCLK_LPTIM1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM2) == RCC_PERIPHCLK_LPTIM2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SAI2) == RCC_PERIPHCLK_SAI2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USB) == RCC_PERIPHCLK_USB) || \ + (((__SELECTION__) & RCC_PERIPHCLK_ADC) == RCC_PERIPHCLK_ADC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_DFSDM1) == RCC_PERIPHCLK_DFSDM1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_DFSDM1AUDIO) == RCC_PERIPHCLK_DFSDM1AUDIO) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RNG) == RCC_PERIPHCLK_RNG) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SDMMC1) == RCC_PERIPHCLK_SDMMC1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_OSPI) == RCC_PERIPHCLK_OSPI) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LTDC) == RCC_PERIPHCLK_LTDC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_DSI) == RCC_PERIPHCLK_DSI)) + +#else + +#define IS_RCC_PERIPHCLOCK(__SELECTION__) \ + ((((__SELECTION__) & RCC_PERIPHCLK_USART1) == RCC_PERIPHCLK_USART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART2) == RCC_PERIPHCLK_USART2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USART3) == RCC_PERIPHCLK_USART3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_UART4) == RCC_PERIPHCLK_UART4) || \ + (((__SELECTION__) & RCC_PERIPHCLK_UART5) == RCC_PERIPHCLK_UART5) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPUART1) == RCC_PERIPHCLK_LPUART1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C1) == RCC_PERIPHCLK_I2C1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C2) == RCC_PERIPHCLK_I2C2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_I2C3) == RCC_PERIPHCLK_I2C3) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM1) == RCC_PERIPHCLK_LPTIM1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_LPTIM2) == RCC_PERIPHCLK_LPTIM2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SAI2) == RCC_PERIPHCLK_SAI2) || \ + (((__SELECTION__) & RCC_PERIPHCLK_USB) == RCC_PERIPHCLK_USB) || \ + (((__SELECTION__) & RCC_PERIPHCLK_ADC) == RCC_PERIPHCLK_ADC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SWPMI1) == RCC_PERIPHCLK_SWPMI1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_DFSDM1) == RCC_PERIPHCLK_DFSDM1) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC) || \ + (((__SELECTION__) & RCC_PERIPHCLK_RNG) == RCC_PERIPHCLK_RNG) || \ + (((__SELECTION__) & RCC_PERIPHCLK_SDMMC1) == RCC_PERIPHCLK_SDMMC1)) + +#endif /* STM32L431xx */ + +#define IS_RCC_USART1CLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_USART1CLKSOURCE_PCLK2) || \ + ((__SOURCE__) == RCC_USART1CLKSOURCE_SYSCLK) || \ + ((__SOURCE__) == RCC_USART1CLKSOURCE_LSE) || \ + ((__SOURCE__) == RCC_USART1CLKSOURCE_HSI)) + +#define IS_RCC_USART2CLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_USART2CLKSOURCE_PCLK1) || \ + ((__SOURCE__) == RCC_USART2CLKSOURCE_SYSCLK) || \ + ((__SOURCE__) == RCC_USART2CLKSOURCE_LSE) || \ + ((__SOURCE__) == RCC_USART2CLKSOURCE_HSI)) + +#if defined(USART3) + +#define IS_RCC_USART3CLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_USART3CLKSOURCE_PCLK1) || \ + ((__SOURCE__) == RCC_USART3CLKSOURCE_SYSCLK) || \ + ((__SOURCE__) == RCC_USART3CLKSOURCE_LSE) || \ + ((__SOURCE__) == RCC_USART3CLKSOURCE_HSI)) + +#endif /* USART3 */ + +#if defined(UART4) + +#define IS_RCC_UART4CLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_UART4CLKSOURCE_PCLK1) || \ + ((__SOURCE__) == RCC_UART4CLKSOURCE_SYSCLK) || \ + ((__SOURCE__) == RCC_UART4CLKSOURCE_LSE) || \ + ((__SOURCE__) == RCC_UART4CLKSOURCE_HSI)) + +#endif /* UART4 */ + +#if defined(UART5) + +#define IS_RCC_UART5CLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_UART5CLKSOURCE_PCLK1) || \ + ((__SOURCE__) == RCC_UART5CLKSOURCE_SYSCLK) || \ + ((__SOURCE__) == RCC_UART5CLKSOURCE_LSE) || \ + ((__SOURCE__) == RCC_UART5CLKSOURCE_HSI)) + +#endif /* UART5 */ + +#define IS_RCC_LPUART1CLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_LPUART1CLKSOURCE_PCLK1) || \ + ((__SOURCE__) == RCC_LPUART1CLKSOURCE_SYSCLK) || \ + ((__SOURCE__) == RCC_LPUART1CLKSOURCE_LSE) || \ + ((__SOURCE__) == RCC_LPUART1CLKSOURCE_HSI)) + +#define IS_RCC_I2C1CLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_I2C1CLKSOURCE_PCLK1) || \ + ((__SOURCE__) == RCC_I2C1CLKSOURCE_SYSCLK)|| \ + ((__SOURCE__) == RCC_I2C1CLKSOURCE_HSI)) + +#if defined(I2C2) + +#define IS_RCC_I2C2CLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_I2C2CLKSOURCE_PCLK1) || \ + ((__SOURCE__) == RCC_I2C2CLKSOURCE_SYSCLK)|| \ + ((__SOURCE__) == RCC_I2C2CLKSOURCE_HSI)) + +#endif /* I2C2 */ + +#define IS_RCC_I2C3CLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_I2C3CLKSOURCE_PCLK1) || \ + ((__SOURCE__) == RCC_I2C3CLKSOURCE_SYSCLK)|| \ + ((__SOURCE__) == RCC_I2C3CLKSOURCE_HSI)) + +#if defined(I2C4) + +#define IS_RCC_I2C4CLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_I2C4CLKSOURCE_PCLK1) || \ + ((__SOURCE__) == RCC_I2C4CLKSOURCE_SYSCLK)|| \ + ((__SOURCE__) == RCC_I2C4CLKSOURCE_HSI)) + +#endif /* I2C4 */ + +#if defined(RCC_PLLSAI2_SUPPORT) + +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +#define IS_RCC_SAI1CLK(__SOURCE__) \ + (((__SOURCE__) == RCC_SAI1CLKSOURCE_PLLSAI1) || \ + ((__SOURCE__) == RCC_SAI1CLKSOURCE_PLLSAI2) || \ + ((__SOURCE__) == RCC_SAI1CLKSOURCE_PLL) || \ + ((__SOURCE__) == RCC_SAI1CLKSOURCE_PIN) || \ + ((__SOURCE__) == RCC_SAI1CLKSOURCE_HSI)) +#else +#define IS_RCC_SAI1CLK(__SOURCE__) \ + (((__SOURCE__) == RCC_SAI1CLKSOURCE_PLLSAI1) || \ + ((__SOURCE__) == RCC_SAI1CLKSOURCE_PLLSAI2) || \ + ((__SOURCE__) == RCC_SAI1CLKSOURCE_PLL) || \ + ((__SOURCE__) == RCC_SAI1CLKSOURCE_PIN)) +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#else + +#define IS_RCC_SAI1CLK(__SOURCE__) \ + (((__SOURCE__) == RCC_SAI1CLKSOURCE_PLLSAI1) || \ + ((__SOURCE__) == RCC_SAI1CLKSOURCE_PLL) || \ + ((__SOURCE__) == RCC_SAI1CLKSOURCE_PIN)) + +#endif /* RCC_PLLSAI2_SUPPORT */ + +#if defined(RCC_PLLSAI2_SUPPORT) + +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +#define IS_RCC_SAI2CLK(__SOURCE__) \ + (((__SOURCE__) == RCC_SAI2CLKSOURCE_PLLSAI1) || \ + ((__SOURCE__) == RCC_SAI2CLKSOURCE_PLLSAI2) || \ + ((__SOURCE__) == RCC_SAI2CLKSOURCE_PLL) || \ + ((__SOURCE__) == RCC_SAI2CLKSOURCE_PIN) || \ + ((__SOURCE__) == RCC_SAI2CLKSOURCE_HSI)) +#else +#define IS_RCC_SAI2CLK(__SOURCE__) \ + (((__SOURCE__) == RCC_SAI2CLKSOURCE_PLLSAI1) || \ + ((__SOURCE__) == RCC_SAI2CLKSOURCE_PLLSAI2) || \ + ((__SOURCE__) == RCC_SAI2CLKSOURCE_PLL) || \ + ((__SOURCE__) == RCC_SAI2CLKSOURCE_PIN)) +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#endif /* RCC_PLLSAI2_SUPPORT */ + +#define IS_RCC_LPTIM1CLK(__SOURCE__) \ + (((__SOURCE__) == RCC_LPTIM1CLKSOURCE_PCLK1) || \ + ((__SOURCE__) == RCC_LPTIM1CLKSOURCE_LSI) || \ + ((__SOURCE__) == RCC_LPTIM1CLKSOURCE_HSI) || \ + ((__SOURCE__) == RCC_LPTIM1CLKSOURCE_LSE)) + +#define IS_RCC_LPTIM2CLK(__SOURCE__) \ + (((__SOURCE__) == RCC_LPTIM2CLKSOURCE_PCLK1) || \ + ((__SOURCE__) == RCC_LPTIM2CLKSOURCE_LSI) || \ + ((__SOURCE__) == RCC_LPTIM2CLKSOURCE_HSI) || \ + ((__SOURCE__) == RCC_LPTIM2CLKSOURCE_LSE)) + +#if defined(SDMMC1) +#if defined(RCC_HSI48_SUPPORT) && defined(RCC_CCIPR2_SDMMCSEL) + +#define IS_RCC_SDMMC1CLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_SDMMC1CLKSOURCE_PLLP) || \ + ((__SOURCE__) == RCC_SDMMC1CLKSOURCE_HSI48) || \ + ((__SOURCE__) == RCC_SDMMC1CLKSOURCE_PLLSAI1) || \ + ((__SOURCE__) == RCC_SDMMC1CLKSOURCE_PLL) || \ + ((__SOURCE__) == RCC_SDMMC1CLKSOURCE_MSI)) + +#elif defined(RCC_HSI48_SUPPORT) + +#define IS_RCC_SDMMC1CLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_SDMMC1CLKSOURCE_HSI48) || \ + ((__SOURCE__) == RCC_SDMMC1CLKSOURCE_PLLSAI1) || \ + ((__SOURCE__) == RCC_SDMMC1CLKSOURCE_PLL) || \ + ((__SOURCE__) == RCC_SDMMC1CLKSOURCE_MSI)) +#else + +#define IS_RCC_SDMMC1CLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_SDMMC1CLKSOURCE_NONE) || \ + ((__SOURCE__) == RCC_SDMMC1CLKSOURCE_PLLSAI1) || \ + ((__SOURCE__) == RCC_SDMMC1CLKSOURCE_PLL) || \ + ((__SOURCE__) == RCC_SDMMC1CLKSOURCE_MSI)) + +#endif /* RCC_HSI48_SUPPORT */ +#endif /* SDMMC1 */ + +#if defined(RCC_HSI48_SUPPORT) + +#define IS_RCC_RNGCLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_RNGCLKSOURCE_HSI48) || \ + ((__SOURCE__) == RCC_RNGCLKSOURCE_PLLSAI1) || \ + ((__SOURCE__) == RCC_RNGCLKSOURCE_PLL) || \ + ((__SOURCE__) == RCC_RNGCLKSOURCE_MSI)) + +#else + +#define IS_RCC_RNGCLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_RNGCLKSOURCE_NONE) || \ + ((__SOURCE__) == RCC_RNGCLKSOURCE_PLLSAI1) || \ + ((__SOURCE__) == RCC_RNGCLKSOURCE_PLL) || \ + ((__SOURCE__) == RCC_RNGCLKSOURCE_MSI)) + +#endif /* RCC_HSI48_SUPPORT */ + +#if defined(USB_OTG_FS) || defined(USB) +#if defined(RCC_HSI48_SUPPORT) + +#define IS_RCC_USBCLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_USBCLKSOURCE_HSI48) || \ + ((__SOURCE__) == RCC_USBCLKSOURCE_PLLSAI1) || \ + ((__SOURCE__) == RCC_USBCLKSOURCE_PLL) || \ + ((__SOURCE__) == RCC_USBCLKSOURCE_MSI)) + +#else + +#define IS_RCC_USBCLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_USBCLKSOURCE_NONE) || \ + ((__SOURCE__) == RCC_USBCLKSOURCE_PLLSAI1) || \ + ((__SOURCE__) == RCC_USBCLKSOURCE_PLL) || \ + ((__SOURCE__) == RCC_USBCLKSOURCE_MSI)) + +#endif /* RCC_HSI48_SUPPORT */ +#endif /* USB_OTG_FS || USB */ + +#if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || defined(STM32L496xx) || defined(STM32L4A6xx) + +#define IS_RCC_ADCCLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_ADCCLKSOURCE_NONE) || \ + ((__SOURCE__) == RCC_ADCCLKSOURCE_PLLSAI1) || \ + ((__SOURCE__) == RCC_ADCCLKSOURCE_PLLSAI2) || \ + ((__SOURCE__) == RCC_ADCCLKSOURCE_SYSCLK)) + +#else + +#define IS_RCC_ADCCLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_ADCCLKSOURCE_NONE) || \ + ((__SOURCE__) == RCC_ADCCLKSOURCE_PLLSAI1) || \ + ((__SOURCE__) == RCC_ADCCLKSOURCE_SYSCLK)) + +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || STM32L496xx || STM32L4A6xx */ + +#if defined(SWPMI1) + +#define IS_RCC_SWPMI1CLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_SWPMI1CLKSOURCE_PCLK1) || \ + ((__SOURCE__) == RCC_SWPMI1CLKSOURCE_HSI)) + +#endif /* SWPMI1 */ + +#if defined(DFSDM1_Filter0) + +#define IS_RCC_DFSDM1CLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_DFSDM1CLKSOURCE_PCLK2) || \ + ((__SOURCE__) == RCC_DFSDM1CLKSOURCE_SYSCLK)) + +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + +#define IS_RCC_DFSDM1AUDIOCLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_DFSDM1AUDIOCLKSOURCE_SAI1) || \ + ((__SOURCE__) == RCC_DFSDM1AUDIOCLKSOURCE_HSI) || \ + ((__SOURCE__) == RCC_DFSDM1AUDIOCLKSOURCE_MSI)) + +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#endif /* DFSDM1_Filter0 */ + +#if defined(LTDC) + +#define IS_RCC_LTDCCLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_LTDCCLKSOURCE_PLLSAI2_DIV2) || \ + ((__SOURCE__) == RCC_LTDCCLKSOURCE_PLLSAI2_DIV4) || \ + ((__SOURCE__) == RCC_LTDCCLKSOURCE_PLLSAI2_DIV8) || \ + ((__SOURCE__) == RCC_LTDCCLKSOURCE_PLLSAI2_DIV16)) + +#endif /* LTDC */ + +#if defined(DSI) + +#define IS_RCC_DSICLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_DSICLKSOURCE_DSIPHY) || \ + ((__SOURCE__) == RCC_DSICLKSOURCE_PLLSAI2)) + +#endif /* DSI */ + +#if defined(OCTOSPI1) || defined(OCTOSPI2) + +#define IS_RCC_OSPICLKSOURCE(__SOURCE__) \ + (((__SOURCE__) == RCC_OSPICLKSOURCE_SYSCLK) || \ + ((__SOURCE__) == RCC_OSPICLKSOURCE_MSI) || \ + ((__SOURCE__) == RCC_OSPICLKSOURCE_PLL)) + +#endif /* OCTOSPI1 || OCTOSPI2 */ + +#define IS_RCC_PLLSAI1SOURCE(__VALUE__) IS_RCC_PLLSOURCE(__VALUE__) + +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) +#define IS_RCC_PLLSAI1M_VALUE(__VALUE__) ((1U <= (__VALUE__)) && ((__VALUE__) <= 16U)) +#else +#define IS_RCC_PLLSAI1M_VALUE(__VALUE__) ((1U <= (__VALUE__)) && ((__VALUE__) <= 8U)) +#endif /* RCC_PLLSAI1M_DIV_1_16_SUPPORT */ + +#define IS_RCC_PLLSAI1N_VALUE(__VALUE__) ((8U <= (__VALUE__)) && ((__VALUE__) <= 86U)) + +#if defined(RCC_PLLSAI1P_DIV_2_31_SUPPORT) +#define IS_RCC_PLLSAI1P_VALUE(__VALUE__) (((__VALUE__) >= 2U) && ((__VALUE__) <= 31U)) +#else +#define IS_RCC_PLLSAI1P_VALUE(__VALUE__) (((__VALUE__) == 7U) || ((__VALUE__) == 17U)) +#endif /* RCC_PLLSAI1P_DIV_2_31_SUPPORT */ + +#define IS_RCC_PLLSAI1Q_VALUE(__VALUE__) (((__VALUE__) == 2U) || ((__VALUE__) == 4U) || \ + ((__VALUE__) == 6U) || ((__VALUE__) == 8U)) + +#define IS_RCC_PLLSAI1R_VALUE(__VALUE__) (((__VALUE__) == 2U) || ((__VALUE__) == 4U) || \ + ((__VALUE__) == 6U) || ((__VALUE__) == 8U)) + +#if defined(RCC_PLLSAI2_SUPPORT) + +#define IS_RCC_PLLSAI2SOURCE(__VALUE__) IS_RCC_PLLSOURCE(__VALUE__) + +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) +#define IS_RCC_PLLSAI2M_VALUE(__VALUE__) ((1U <= (__VALUE__)) && ((__VALUE__) <= 16U)) +#else +#define IS_RCC_PLLSAI2M_VALUE(__VALUE__) ((1U <= (__VALUE__)) && ((__VALUE__) <= 8U)) +#endif /* RCC_PLLSAI2M_DIV_1_16_SUPPORT */ + +#define IS_RCC_PLLSAI2N_VALUE(__VALUE__) ((8U <= (__VALUE__)) && ((__VALUE__) <= 86U)) + +#if defined(RCC_PLLSAI2P_DIV_2_31_SUPPORT) +#define IS_RCC_PLLSAI2P_VALUE(__VALUE__) (((__VALUE__) >= 2U) && ((__VALUE__) <= 31U)) +#else +#define IS_RCC_PLLSAI2P_VALUE(__VALUE__) (((__VALUE__) == 7U) || ((__VALUE__) == 17U)) +#endif /* RCC_PLLSAI2P_DIV_2_31_SUPPORT */ + +#if defined(RCC_PLLSAI2Q_DIV_SUPPORT) +#define IS_RCC_PLLSAI2Q_VALUE(__VALUE__) (((__VALUE__) == 2U) || ((__VALUE__) == 4U) || \ + ((__VALUE__) == 6U) || ((__VALUE__) == 8U)) +#endif /* RCC_PLLSAI2Q_DIV_SUPPORT */ + +#define IS_RCC_PLLSAI2R_VALUE(__VALUE__) (((__VALUE__) == 2U) || ((__VALUE__) == 4U) || \ + ((__VALUE__) == 6U) || ((__VALUE__) == 8U)) + +#endif /* RCC_PLLSAI2_SUPPORT */ + +#if defined(CRS) + +#define IS_RCC_CRS_SYNC_SOURCE(__SOURCE__) (((__SOURCE__) == RCC_CRS_SYNC_SOURCE_GPIO) || \ + ((__SOURCE__) == RCC_CRS_SYNC_SOURCE_LSE) || \ + ((__SOURCE__) == RCC_CRS_SYNC_SOURCE_USB)) + +#define IS_RCC_CRS_SYNC_DIV(__DIV__) (((__DIV__) == RCC_CRS_SYNC_DIV1) || ((__DIV__) == RCC_CRS_SYNC_DIV2) || \ + ((__DIV__) == RCC_CRS_SYNC_DIV4) || ((__DIV__) == RCC_CRS_SYNC_DIV8) || \ + ((__DIV__) == RCC_CRS_SYNC_DIV16) || ((__DIV__) == RCC_CRS_SYNC_DIV32) || \ + ((__DIV__) == RCC_CRS_SYNC_DIV64) || ((__DIV__) == RCC_CRS_SYNC_DIV128)) + +#define IS_RCC_CRS_SYNC_POLARITY(__POLARITY__) (((__POLARITY__) == RCC_CRS_SYNC_POLARITY_RISING) || \ + ((__POLARITY__) == RCC_CRS_SYNC_POLARITY_FALLING)) + +#define IS_RCC_CRS_RELOADVALUE(__VALUE__) (((__VALUE__) <= 0xFFFFU)) + +#define IS_RCC_CRS_ERRORLIMIT(__VALUE__) (((__VALUE__) <= 0xFFU)) + +#define IS_RCC_CRS_HSI48CALIBRATION(__VALUE__) (((__VALUE__) <= 0x3FU)) + +#define IS_RCC_CRS_FREQERRORDIR(__DIR__) (((__DIR__) == RCC_CRS_FREQERRORDIR_UP) || \ + ((__DIR__) == RCC_CRS_FREQERRORDIR_DOWN)) + +#endif /* CRS */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_HAL_RCC_EX_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rng.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rng.h new file mode 100644 index 0000000..6939084 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rng.h @@ -0,0 +1,325 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_rng.h + * @author MCD Application Team + * @brief Header file of RNG HAL module. + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_RNG_H +#define __STM32L4xx_HAL_RNG_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup RNG + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup RNG_Exported_Types RNG Exported Types + * @{ + */ + +#if defined(RNG_CR_CED) +/** + * @brief RNG Configuration Structure definition + */ +typedef struct +{ + uint32_t ClockErrorDetection; /*!< Clock error detection */ +}RNG_InitTypeDef; +#endif /* defined(RNG_CR_CED) */ + +/** + * @brief RNG HAL State Structure definition + */ +typedef enum +{ + HAL_RNG_STATE_RESET = 0x00, /*!< RNG not yet initialized or disabled */ + HAL_RNG_STATE_READY = 0x01, /*!< RNG initialized and ready for use */ + HAL_RNG_STATE_BUSY = 0x02, /*!< RNG internal process is ongoing */ + HAL_RNG_STATE_TIMEOUT = 0x03, /*!< RNG timeout state */ + HAL_RNG_STATE_ERROR = 0x04 /*!< RNG error state */ + +}HAL_RNG_StateTypeDef; + +/** + * @brief RNG Handle Structure definition + */ +typedef struct +{ + RNG_TypeDef *Instance; /*!< Register base address */ + +#if defined(RNG_CR_CED) + RNG_InitTypeDef Init; /*!< RNG configuration parameters */ +#endif /* defined(RNG_CR_CED) */ + + HAL_LockTypeDef Lock; /*!< RNG locking object */ + + __IO HAL_RNG_StateTypeDef State; /*!< RNG communication state */ + + uint32_t RandomNumber; /*!< Last Generated RNG Data */ + +}RNG_HandleTypeDef; + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup RNG_Exported_Constants RNG Exported Constants + * @{ + */ + +/** @defgroup RNG_Interrupt_definition RNG Interrupts Definition + * @{ + */ +#define RNG_IT_DRDY RNG_SR_DRDY /*!< Data Ready interrupt */ +#define RNG_IT_CEI RNG_SR_CEIS /*!< Clock error interrupt */ +#define RNG_IT_SEI RNG_SR_SEIS /*!< Seed error interrupt */ +/** + * @} + */ + +/** @defgroup RNG_Flag_definition RNG Flags Definition + * @{ + */ +#define RNG_FLAG_DRDY RNG_SR_DRDY /*!< Data ready */ +#define RNG_FLAG_CECS RNG_SR_CECS /*!< Clock error current status */ +#define RNG_FLAG_SECS RNG_SR_SECS /*!< Seed error current status */ +/** + * @} + */ + +#if defined(RNG_CR_CED) +/** @defgroup RNG_Clock_Error_Detection RNG Clock Error Detection + * @{ + */ +#define RNG_CED_ENABLE ((uint32_t)0x00000000) /*!< Clock error detection enabled */ +#define RNG_CED_DISABLE RNG_CR_CED /*!< Clock error detection disabled */ +/** + * @} + */ +#endif /* defined(RNG_CR_CED) */ + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ +/** @defgroup RNG_Exported_Macros RNG Exported Macros + * @{ + */ + +/** @brief Reset RNG handle state. + * @param __HANDLE__: RNG Handle + * @retval None + */ +#define __HAL_RNG_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_RNG_STATE_RESET) + +/** + * @brief Enable the RNG peripheral. + * @param __HANDLE__: RNG Handle + * @retval None + */ +#define __HAL_RNG_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR |= RNG_CR_RNGEN) + +/** + * @brief Disable the RNG peripheral. + * @param __HANDLE__: RNG Handle + * @retval None + */ +#define __HAL_RNG_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR &= ~RNG_CR_RNGEN) + +/** + * @brief Check whether the specified RNG flag is set or not. + * @param __HANDLE__: RNG Handle + * @param __FLAG__: RNG flag + * This parameter can be one of the following values: + * @arg RNG_FLAG_DRDY: Data ready + * @arg RNG_FLAG_CECS: Clock error current status + * @arg RNG_FLAG_SECS: Seed error current status + * @retval The new state of __FLAG__ (SET or RESET). + */ +#define __HAL_RNG_GET_FLAG(__HANDLE__, __FLAG__) (((__HANDLE__)->Instance->SR & (__FLAG__)) == (__FLAG__)) + + +/** + * @brief Clear the selected RNG flag status. + * @param __HANDLE__: RNG handle + * @param __FLAG__: RNG flag to clear + * @note WARNING: This is a dummy macro for HAL code alignment, + * flags RNG_FLAG_DRDY, RNG_FLAG_CECS and RNG_FLAG_SECS are read-only. + * @retval None + */ +#define __HAL_RNG_CLEAR_FLAG(__HANDLE__, __FLAG__) /* dummy macro */ + + + +/** + * @brief Enable the RNG interrupt. + * @param __HANDLE__: RNG Handle + * @retval None + */ +#define __HAL_RNG_ENABLE_IT(__HANDLE__) ((__HANDLE__)->Instance->CR |= RNG_CR_IE) + +/** + * @brief Disable the RNG interrupt. + * @param __HANDLE__: RNG Handle + * @retval None + */ +#define __HAL_RNG_DISABLE_IT(__HANDLE__) ((__HANDLE__)->Instance->CR &= ~RNG_CR_IE) + +/** + * @brief Check whether the specified RNG interrupt has occurred or not. + * @param __HANDLE__: RNG Handle + * @param __INTERRUPT__: specifies the RNG interrupt status flag to check. + * This parameter can be one of the following values: + * @arg RNG_IT_DRDY: Data ready interrupt + * @arg RNG_IT_CEI: Clock error interrupt + * @arg RNG_IT_SEI: Seed error interrupt + * @retval The new state of __INTERRUPT__ (SET or RESET). + */ +#define __HAL_RNG_GET_IT(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->SR & (__INTERRUPT__)) == (__INTERRUPT__)) + +/** + * @brief Clear the RNG interrupt status flags. + * @param __HANDLE__: RNG Handle + * @param __INTERRUPT__: specifies the RNG interrupt status flag to clear. + * This parameter can be one of the following values: + * @arg RNG_IT_CEI: Clock error interrupt + * @arg RNG_IT_SEI: Seed error interrupt + * @note RNG_IT_DRDY flag is read-only, reading RNG_DR register automatically clears RNG_IT_DRDY. + * @retval None + */ +#define __HAL_RNG_CLEAR_IT(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->SR) = ~(__INTERRUPT__)) + +/** + * @} + */ + + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup RNG_Exported_Functions RNG Exported Functions + * @{ + */ + +/* Initialization and de-initialization functions ******************************/ +/** @defgroup RNG_Exported_Functions_Group1 Initialization and de-initialization functions + * @{ + */ +HAL_StatusTypeDef HAL_RNG_Init(RNG_HandleTypeDef *hrng); +HAL_StatusTypeDef HAL_RNG_DeInit (RNG_HandleTypeDef *hrng); +void HAL_RNG_MspInit(RNG_HandleTypeDef *hrng); +void HAL_RNG_MspDeInit(RNG_HandleTypeDef *hrng); +/** + * @} + */ + +/* Peripheral Control functions ************************************************/ +/** @defgroup RNG_Exported_Functions_Group2 Peripheral Control functions + * @{ + */ +uint32_t HAL_RNG_GetRandomNumber(RNG_HandleTypeDef *hrng); /* Obsolete, use HAL_RNG_GenerateRandomNumber() instead */ +uint32_t HAL_RNG_GetRandomNumber_IT(RNG_HandleTypeDef *hrng); /* Obsolete, use HAL_RNG_GenerateRandomNumber_IT() instead */ + +HAL_StatusTypeDef HAL_RNG_GenerateRandomNumber(RNG_HandleTypeDef *hrng, uint32_t *random32bit); +HAL_StatusTypeDef HAL_RNG_GenerateRandomNumber_IT(RNG_HandleTypeDef *hrng); +uint32_t HAL_RNG_ReadLastRandomNumber(RNG_HandleTypeDef *hrng); + +void HAL_RNG_IRQHandler(RNG_HandleTypeDef *hrng); +void HAL_RNG_ErrorCallback(RNG_HandleTypeDef *hrng); +void HAL_RNG_ReadyDataCallback(RNG_HandleTypeDef* hrng, uint32_t random32bit); +/** + * @} + */ + +/* Peripheral State functions **************************************************/ +/** @defgroup RNG_Exported_Functions_Group3 Peripheral State functions + * @{ + */ +HAL_RNG_StateTypeDef HAL_RNG_GetState(RNG_HandleTypeDef *hrng); +/** + * @} + */ + +/** + * @} + */ + +/* Private types -------------------------------------------------------------*/ +/* Private defines -----------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ +/** @addtogroup RNG_Private_Macros RNG Private Macros + * @{ + */ + +#if defined(RNG_CR_CED) +/** + * @brief Verify the RNG Clock Error Detection mode. + * @param __MODE__: RNG Clock Error Detection mode + * @retval SET (__MODE__ is valid) or RESET (__MODE__ is invalid) + */ +#define IS_RNG_CED(__MODE__) (((__MODE__) == RNG_CED_ENABLE) || \ + ((__MODE__) == RNG_CED_DISABLE)) +#endif /* defined(RNG_CR_CED) */ + +/** + * @} + */ +/* Private functions prototypes ----------------------------------------------*/ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_HAL_RNG_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rtc.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rtc.h new file mode 100644 index 0000000..5d6ce90 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rtc.h @@ -0,0 +1,861 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_rtc.h + * @author MCD Application Team + * @brief Header file of RTC HAL module. + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_RTC_H +#define __STM32L4xx_HAL_RTC_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup RTC + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup RTC_Exported_Types RTC Exported Types + * @{ + */ +/** + * @brief HAL State structures definition + */ +typedef enum +{ + HAL_RTC_STATE_RESET = 0x00, /*!< RTC not yet initialized or disabled */ + HAL_RTC_STATE_READY = 0x01, /*!< RTC initialized and ready for use */ + HAL_RTC_STATE_BUSY = 0x02, /*!< RTC process is ongoing */ + HAL_RTC_STATE_TIMEOUT = 0x03, /*!< RTC timeout state */ + HAL_RTC_STATE_ERROR = 0x04 /*!< RTC error state */ + +}HAL_RTCStateTypeDef; + +/** + * @brief RTC Configuration Structure definition + */ +typedef struct +{ + uint32_t HourFormat; /*!< Specifies the RTC Hour Format. + This parameter can be a value of @ref RTC_Hour_Formats */ + + uint32_t AsynchPrediv; /*!< Specifies the RTC Asynchronous Predivider value. + This parameter must be a number between Min_Data = 0x00 and Max_Data = 0x7F */ + + uint32_t SynchPrediv; /*!< Specifies the RTC Synchronous Predivider value. + This parameter must be a number between Min_Data = 0x00 and Max_Data = 0x7FFF */ + + uint32_t OutPut; /*!< Specifies which signal will be routed to the RTC output. + This parameter can be a value of @ref RTCEx_Output_selection_Definitions */ + + uint32_t OutPutRemap; /*!< Specifies the remap for RTC output. + This parameter can be a value of @ref RTC_Output_ALARM_OUT_Remap */ + + uint32_t OutPutPolarity; /*!< Specifies the polarity of the output signal. + This parameter can be a value of @ref RTC_Output_Polarity_Definitions */ + + uint32_t OutPutType; /*!< Specifies the RTC Output Pin mode. + This parameter can be a value of @ref RTC_Output_Type_ALARM_OUT */ +}RTC_InitTypeDef; + +/** + * @brief RTC Time structure definition + */ +typedef struct +{ + uint8_t Hours; /*!< Specifies the RTC Time Hour. + This parameter must be a number between Min_Data = 0 and Max_Data = 12 if the RTC_HourFormat_12 is selected. + This parameter must be a number between Min_Data = 0 and Max_Data = 23 if the RTC_HourFormat_24 is selected */ + + uint8_t Minutes; /*!< Specifies the RTC Time Minutes. + This parameter must be a number between Min_Data = 0 and Max_Data = 59 */ + + uint8_t Seconds; /*!< Specifies the RTC Time Seconds. + This parameter must be a number between Min_Data = 0 and Max_Data = 59 */ + + uint8_t TimeFormat; /*!< Specifies the RTC AM/PM Time. + This parameter can be a value of @ref RTC_AM_PM_Definitions */ + + uint32_t SubSeconds; /*!< Specifies the RTC_SSR RTC Sub Second register content. + This parameter corresponds to a time unit range between [0-1] Second + with [1 Sec / SecondFraction +1] granularity */ + + uint32_t SecondFraction; /*!< Specifies the range or granularity of Sub Second register content + corresponding to Synchronous pre-scaler factor value (PREDIV_S) + This parameter corresponds to a time unit range between [0-1] Second + with [1 Sec / SecondFraction +1] granularity. + This field will be used only by HAL_RTC_GetTime function */ + + uint32_t DayLightSaving; /*!< Specifies RTC_DayLightSaveOperation: the value of hour adjustment. + This parameter can be a value of @ref RTC_DayLightSaving_Definitions */ + + uint32_t StoreOperation; /*!< Specifies RTC_StoreOperation value to be written in the BCK bit + in CR register to store the operation. + This parameter can be a value of @ref RTC_StoreOperation_Definitions */ +}RTC_TimeTypeDef; + +/** + * @brief RTC Date structure definition + */ +typedef struct +{ + uint8_t WeekDay; /*!< Specifies the RTC Date WeekDay. + This parameter can be a value of @ref RTC_WeekDay_Definitions */ + + uint8_t Month; /*!< Specifies the RTC Date Month (in BCD format). + This parameter can be a value of @ref RTC_Month_Date_Definitions */ + + uint8_t Date; /*!< Specifies the RTC Date. + This parameter must be a number between Min_Data = 1 and Max_Data = 31 */ + + uint8_t Year; /*!< Specifies the RTC Date Year. + This parameter must be a number between Min_Data = 0 and Max_Data = 99 */ + +}RTC_DateTypeDef; + +/** + * @brief RTC Alarm structure definition + */ +typedef struct +{ + RTC_TimeTypeDef AlarmTime; /*!< Specifies the RTC Alarm Time members */ + + uint32_t AlarmMask; /*!< Specifies the RTC Alarm Masks. + This parameter can be a value of @ref RTC_AlarmMask_Definitions */ + + uint32_t AlarmSubSecondMask; /*!< Specifies the RTC Alarm SubSeconds Masks. + This parameter can be a value of @ref RTC_Alarm_Sub_Seconds_Masks_Definitions */ + + uint32_t AlarmDateWeekDaySel; /*!< Specifies the RTC Alarm is on Date or WeekDay. + This parameter can be a value of @ref RTC_AlarmDateWeekDay_Definitions */ + + uint8_t AlarmDateWeekDay; /*!< Specifies the RTC Alarm Date/WeekDay. + If the Alarm Date is selected, this parameter must be set to a value in the 1-31 range. + If the Alarm WeekDay is selected, this parameter can be a value of @ref RTC_WeekDay_Definitions */ + + uint32_t Alarm; /*!< Specifies the alarm . + This parameter can be a value of @ref RTC_Alarms_Definitions */ +}RTC_AlarmTypeDef; + +/** + * @brief Time Handle Structure definition + */ +typedef struct +{ + RTC_TypeDef *Instance; /*!< Register base address */ + + RTC_InitTypeDef Init; /*!< RTC required parameters */ + + HAL_LockTypeDef Lock; /*!< RTC locking object */ + + __IO HAL_RTCStateTypeDef State; /*!< Time communication state */ + +}RTC_HandleTypeDef; + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup RTC_Exported_Constants RTC Exported Constants + * @{ + */ + +/** @defgroup RTC_Hour_Formats RTC Hour Formats + * @{ + */ +#define RTC_HOURFORMAT_24 ((uint32_t)0x00000000) +#define RTC_HOURFORMAT_12 ((uint32_t)0x00000040) +/** + * @} + */ + +/** @defgroup RTC_Output_Polarity_Definitions RTC Output Polarity Definitions + * @{ + */ +#define RTC_OUTPUT_POLARITY_HIGH ((uint32_t)0x00000000) +#define RTC_OUTPUT_POLARITY_LOW ((uint32_t)0x00100000) +/** + * @} + */ + +/** @defgroup RTC_Output_Type_ALARM_OUT RTC Output Type ALARM OUT + * @{ + */ +#define RTC_OUTPUT_TYPE_OPENDRAIN ((uint32_t)0x00000000) +#define RTC_OUTPUT_TYPE_PUSHPULL ((uint32_t)RTC_OR_ALARMOUTTYPE) +/** + * @} + */ + +/** @defgroup RTC_Output_ALARM_OUT_Remap RTC Output ALARM OUT Remap + * @{ + */ +#define RTC_OUTPUT_REMAP_NONE ((uint32_t)0x00000000) +#define RTC_OUTPUT_REMAP_POS1 ((uint32_t)RTC_OR_OUT_RMP) +/** + * @} + */ + +/** @defgroup RTC_AM_PM_Definitions RTC AM PM Definitions + * @{ + */ +#define RTC_HOURFORMAT12_AM ((uint8_t)0x00) +#define RTC_HOURFORMAT12_PM ((uint8_t)0x40) +/** + * @} + */ + +/** @defgroup RTC_DayLightSaving_Definitions RTC DayLight Saving Definitions + * @{ + */ +#define RTC_DAYLIGHTSAVING_SUB1H ((uint32_t)0x00020000) +#define RTC_DAYLIGHTSAVING_ADD1H ((uint32_t)0x00010000) +#define RTC_DAYLIGHTSAVING_NONE ((uint32_t)0x00000000) +/** + * @} + */ + +/** @defgroup RTC_StoreOperation_Definitions RTC Store Operation Definitions + * @{ + */ +#define RTC_STOREOPERATION_RESET ((uint32_t)0x00000000) +#define RTC_STOREOPERATION_SET ((uint32_t)0x00040000) +/** + * @} + */ + +/** @defgroup RTC_Input_parameter_format_definitions RTC Input Parameter Format Definitions + * @{ + */ +#define RTC_FORMAT_BIN ((uint32_t)0x00000000) +#define RTC_FORMAT_BCD ((uint32_t)0x00000001) +/** + * @} + */ + +/** @defgroup RTC_Month_Date_Definitions RTC Month Date Definitions + * @{ + */ + +/* Coded in BCD format */ +#define RTC_MONTH_JANUARY ((uint8_t)0x01) +#define RTC_MONTH_FEBRUARY ((uint8_t)0x02) +#define RTC_MONTH_MARCH ((uint8_t)0x03) +#define RTC_MONTH_APRIL ((uint8_t)0x04) +#define RTC_MONTH_MAY ((uint8_t)0x05) +#define RTC_MONTH_JUNE ((uint8_t)0x06) +#define RTC_MONTH_JULY ((uint8_t)0x07) +#define RTC_MONTH_AUGUST ((uint8_t)0x08) +#define RTC_MONTH_SEPTEMBER ((uint8_t)0x09) +#define RTC_MONTH_OCTOBER ((uint8_t)0x10) +#define RTC_MONTH_NOVEMBER ((uint8_t)0x11) +#define RTC_MONTH_DECEMBER ((uint8_t)0x12) +/** + * @} + */ + +/** @defgroup RTC_WeekDay_Definitions RTC WeekDay Definitions + * @{ + */ +#define RTC_WEEKDAY_MONDAY ((uint8_t)0x01) +#define RTC_WEEKDAY_TUESDAY ((uint8_t)0x02) +#define RTC_WEEKDAY_WEDNESDAY ((uint8_t)0x03) +#define RTC_WEEKDAY_THURSDAY ((uint8_t)0x04) +#define RTC_WEEKDAY_FRIDAY ((uint8_t)0x05) +#define RTC_WEEKDAY_SATURDAY ((uint8_t)0x06) +#define RTC_WEEKDAY_SUNDAY ((uint8_t)0x07) +/** + * @} + */ + +/** @defgroup RTC_AlarmDateWeekDay_Definitions RTC Alarm Date WeekDay Definitions + * @{ + */ +#define RTC_ALARMDATEWEEKDAYSEL_DATE ((uint32_t)0x00000000) +#define RTC_ALARMDATEWEEKDAYSEL_WEEKDAY ((uint32_t)0x40000000) +/** + * @} + */ + + +/** @defgroup RTC_AlarmMask_Definitions RTC Alarm Mask Definitions + * @{ + */ +#define RTC_ALARMMASK_NONE ((uint32_t)0x00000000) +#define RTC_ALARMMASK_DATEWEEKDAY RTC_ALRMAR_MSK4 +#define RTC_ALARMMASK_HOURS RTC_ALRMAR_MSK3 +#define RTC_ALARMMASK_MINUTES RTC_ALRMAR_MSK2 +#define RTC_ALARMMASK_SECONDS RTC_ALRMAR_MSK1 +#define RTC_ALARMMASK_ALL ((uint32_t)0x80808080) +/** + * @} + */ + +/** @defgroup RTC_Alarms_Definitions RTC Alarms Definitions + * @{ + */ +#define RTC_ALARM_A RTC_CR_ALRAE +#define RTC_ALARM_B RTC_CR_ALRBE +/** + * @} + */ + +/** @defgroup RTC_Alarm_Sub_Seconds_Masks_Definitions RTC Alarm Sub Seconds Masks Definitions + * @{ + */ +#define RTC_ALARMSUBSECONDMASK_ALL ((uint32_t)0x00000000) /*!< All Alarm SS fields are masked. + There is no comparison on sub seconds + for Alarm */ +#define RTC_ALARMSUBSECONDMASK_SS14_1 ((uint32_t)0x01000000) /*!< SS[14:1] are don't care in Alarm + comparison. Only SS[0] is compared. */ +#define RTC_ALARMSUBSECONDMASK_SS14_2 ((uint32_t)0x02000000) /*!< SS[14:2] are don't care in Alarm + comparison. Only SS[1:0] are compared */ +#define RTC_ALARMSUBSECONDMASK_SS14_3 ((uint32_t)0x03000000) /*!< SS[14:3] are don't care in Alarm + comparison. Only SS[2:0] are compared */ +#define RTC_ALARMSUBSECONDMASK_SS14_4 ((uint32_t)0x04000000) /*!< SS[14:4] are don't care in Alarm + comparison. Only SS[3:0] are compared */ +#define RTC_ALARMSUBSECONDMASK_SS14_5 ((uint32_t)0x05000000) /*!< SS[14:5] are don't care in Alarm + comparison. Only SS[4:0] are compared */ +#define RTC_ALARMSUBSECONDMASK_SS14_6 ((uint32_t)0x06000000) /*!< SS[14:6] are don't care in Alarm + comparison. Only SS[5:0] are compared */ +#define RTC_ALARMSUBSECONDMASK_SS14_7 ((uint32_t)0x07000000) /*!< SS[14:7] are don't care in Alarm + comparison. Only SS[6:0] are compared */ +#define RTC_ALARMSUBSECONDMASK_SS14_8 ((uint32_t)0x08000000) /*!< SS[14:8] are don't care in Alarm + comparison. Only SS[7:0] are compared */ +#define RTC_ALARMSUBSECONDMASK_SS14_9 ((uint32_t)0x09000000) /*!< SS[14:9] are don't care in Alarm + comparison. Only SS[8:0] are compared */ +#define RTC_ALARMSUBSECONDMASK_SS14_10 ((uint32_t)0x0A000000) /*!< SS[14:10] are don't care in Alarm + comparison. Only SS[9:0] are compared */ +#define RTC_ALARMSUBSECONDMASK_SS14_11 ((uint32_t)0x0B000000) /*!< SS[14:11] are don't care in Alarm + comparison. Only SS[10:0] are compared */ +#define RTC_ALARMSUBSECONDMASK_SS14_12 ((uint32_t)0x0C000000) /*!< SS[14:12] are don't care in Alarm + comparison. Only SS[11:0] are compared */ +#define RTC_ALARMSUBSECONDMASK_SS14_13 ((uint32_t)0x0D000000) /*!< SS[14:13] are don't care in Alarm + comparison. Only SS[12:0] are compared */ +#define RTC_ALARMSUBSECONDMASK_SS14 ((uint32_t)0x0E000000) /*!< SS[14] is don't care in Alarm + comparison. Only SS[13:0] are compared */ +#define RTC_ALARMSUBSECONDMASK_NONE ((uint32_t)0x0F000000) /*!< SS[14:0] are compared and must match + to activate alarm. */ +/** + * @} + */ + +/** @defgroup RTC_Interrupts_Definitions RTC Interrupts Definitions + * @{ + */ +#define RTC_IT_TS ((uint32_t)RTC_CR_TSIE) /*!< Enable Timestamp Interrupt */ +#define RTC_IT_WUT ((uint32_t)RTC_CR_WUTIE) /*!< Enable Wakeup timer Interrupt */ +#define RTC_IT_ALRA ((uint32_t)RTC_CR_ALRAIE) /*!< Enable Alarm A Interrupt */ +#define RTC_IT_ALRB ((uint32_t)RTC_CR_ALRBIE) /*!< Enable Alarm B Interrupt */ +#define RTC_IT_TAMP ((uint32_t)RTC_TAMPCR_TAMPIE) /*!< Enable all Tamper Interrupt */ +#define RTC_IT_TAMP1 ((uint32_t)RTC_TAMPCR_TAMP1IE) /*!< Enable Tamper 1 Interrupt */ +#define RTC_IT_TAMP2 ((uint32_t)RTC_TAMPCR_TAMP2IE) /*!< Enable Tamper 2 Interrupt */ +#define RTC_IT_TAMP3 ((uint32_t)RTC_TAMPCR_TAMP3IE) /*!< Enable Tamper 3 Interrupt */ +/** + * @} + */ + +/** @defgroup RTC_Flags_Definitions RTC Flags Definitions + * @{ + */ +#define RTC_FLAG_RECALPF ((uint32_t)RTC_ISR_RECALPF) +#define RTC_FLAG_TAMP3F ((uint32_t)RTC_ISR_TAMP3F) +#define RTC_FLAG_TAMP2F ((uint32_t)RTC_ISR_TAMP2F) +#define RTC_FLAG_TAMP1F ((uint32_t)RTC_ISR_TAMP1F) +#define RTC_FLAG_TSOVF ((uint32_t)RTC_ISR_TSOVF) +#define RTC_FLAG_TSF ((uint32_t)RTC_ISR_TSF) +#define RTC_FLAG_ITSF ((uint32_t)RTC_ISR_ITSF) +#define RTC_FLAG_WUTF ((uint32_t)RTC_ISR_WUTF) +#define RTC_FLAG_ALRBF ((uint32_t)RTC_ISR_ALRBF) +#define RTC_FLAG_ALRAF ((uint32_t)RTC_ISR_ALRAF) +#define RTC_FLAG_INITF ((uint32_t)RTC_ISR_INITF) +#define RTC_FLAG_RSF ((uint32_t)RTC_ISR_RSF) +#define RTC_FLAG_INITS ((uint32_t)RTC_ISR_INITS) +#define RTC_FLAG_SHPF ((uint32_t)RTC_ISR_SHPF) +#define RTC_FLAG_WUTWF ((uint32_t)RTC_ISR_WUTWF) +#define RTC_FLAG_ALRBWF ((uint32_t)RTC_ISR_ALRBWF) +#define RTC_FLAG_ALRAWF ((uint32_t)RTC_ISR_ALRAWF) +/** + * @} + */ + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ +/** @defgroup RTC_Exported_Macros RTC Exported Macros + * @{ + */ + +/** @brief Reset RTC handle state. + * @param __HANDLE__: RTC handle. + * @retval None + */ +#define __HAL_RTC_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_RTC_STATE_RESET) + +/** + * @brief Disable the write protection for RTC registers. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_WRITEPROTECTION_DISABLE(__HANDLE__) \ + do{ \ + (__HANDLE__)->Instance->WPR = 0xCA; \ + (__HANDLE__)->Instance->WPR = 0x53; \ + } while(0) + +/** + * @brief Enable the write protection for RTC registers. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_WRITEPROTECTION_ENABLE(__HANDLE__) \ + do{ \ + (__HANDLE__)->Instance->WPR = 0xFF; \ + } while(0) + + +/** + * @brief Enable the RTC ALARMA peripheral. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_ALARMA_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR |= (RTC_CR_ALRAE)) + +/** + * @brief Disable the RTC ALARMA peripheral. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_ALARMA_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR &= ~(RTC_CR_ALRAE)) + +/** + * @brief Enable the RTC ALARMB peripheral. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_ALARMB_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR |= (RTC_CR_ALRBE)) + +/** + * @brief Disable the RTC ALARMB peripheral. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_ALARMB_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR &= ~(RTC_CR_ALRBE)) + +/** + * @brief Enable the RTC Alarm interrupt. + * @param __HANDLE__: specifies the RTC handle. + * @param __INTERRUPT__: specifies the RTC Alarm interrupt sources to be enabled or disabled. + * This parameter can be any combination of the following values: + * @arg RTC_IT_ALRA: Alarm A interrupt + * @arg RTC_IT_ALRB: Alarm B interrupt + * @retval None + */ +#define __HAL_RTC_ALARM_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CR |= (__INTERRUPT__)) + +/** + * @brief Disable the RTC Alarm interrupt. + * @param __HANDLE__: specifies the RTC handle. + * @param __INTERRUPT__: specifies the RTC Alarm interrupt sources to be enabled or disabled. + * This parameter can be any combination of the following values: + * @arg RTC_IT_ALRA: Alarm A interrupt + * @arg RTC_IT_ALRB: Alarm B interrupt + * @retval None + */ +#define __HAL_RTC_ALARM_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CR &= ~(__INTERRUPT__)) + +/** + * @brief Check whether the specified RTC Alarm interrupt has occurred or not. + * @param __HANDLE__: specifies the RTC handle. + * @param __INTERRUPT__: specifies the RTC Alarm interrupt sources to check. + * This parameter can be: + * @arg RTC_IT_ALRA: Alarm A interrupt + * @arg RTC_IT_ALRB: Alarm B interrupt + * @retval None + */ +#define __HAL_RTC_ALARM_GET_IT(__HANDLE__, __INTERRUPT__) (((((__HANDLE__)->Instance->ISR)& ((__INTERRUPT__)>> 4)) != RESET) ? SET : RESET) + +/** + * @brief Get the selected RTC Alarm's flag status. + * @param __HANDLE__: specifies the RTC handle. + * @param __FLAG__: specifies the RTC Alarm Flag sources to check. + * This parameter can be: + * @arg RTC_FLAG_ALRAF + * @arg RTC_FLAG_ALRBF + * @arg RTC_FLAG_ALRAWF + * @arg RTC_FLAG_ALRBWF + * @retval None + */ +#define __HAL_RTC_ALARM_GET_FLAG(__HANDLE__, __FLAG__) (((((__HANDLE__)->Instance->ISR) & (__FLAG__)) != RESET) ? SET : RESET) + +/** + * @brief Clear the RTC Alarm's pending flags. + * @param __HANDLE__: specifies the RTC handle. + * @param __FLAG__: specifies the RTC Alarm Flag sources to clear. + * This parameter can be: + * @arg RTC_FLAG_ALRAF + * @arg RTC_FLAG_ALRBF + * @retval None + */ +#define __HAL_RTC_ALARM_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->ISR) = (~((__FLAG__) | RTC_ISR_INIT)|((__HANDLE__)->Instance->ISR & RTC_ISR_INIT)) + +/** + * @brief Check whether the specified RTC Alarm interrupt is enabled or not. + * @param __HANDLE__: specifies the RTC handle. + * @param __INTERRUPT__: specifies the RTC Alarm interrupt sources to check. + * This parameter can be: + * @arg RTC_IT_ALRA: Alarm A interrupt + * @arg RTC_IT_ALRB: Alarm B interrupt + * @retval None + */ +#define __HAL_RTC_ALARM_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) (((((__HANDLE__)->Instance->CR) & (__INTERRUPT__)) != RESET) ? SET : RESET) + +/** + * @brief Enable interrupt on the RTC Alarm associated Exti line. + * @retval None + */ +#define __HAL_RTC_ALARM_EXTI_ENABLE_IT() (EXTI->IMR1 |= RTC_EXTI_LINE_ALARM_EVENT) + +/** + * @brief Disable interrupt on the RTC Alarm associated Exti line. + * @retval None + */ +#define __HAL_RTC_ALARM_EXTI_DISABLE_IT() (EXTI->IMR1 &= ~(RTC_EXTI_LINE_ALARM_EVENT)) + +/** + * @brief Enable event on the RTC Alarm associated Exti line. + * @retval None + */ +#define __HAL_RTC_ALARM_EXTI_ENABLE_EVENT() (EXTI->EMR1 |= RTC_EXTI_LINE_ALARM_EVENT) + +/** + * @brief Disable event on the RTC Alarm associated Exti line. + * @retval None + */ +#define __HAL_RTC_ALARM_EXTI_DISABLE_EVENT() (EXTI->EMR1 &= ~(RTC_EXTI_LINE_ALARM_EVENT)) + +/** + * @brief Enable falling edge trigger on the RTC Alarm associated Exti line. + * @retval None + */ +#define __HAL_RTC_ALARM_EXTI_ENABLE_FALLING_EDGE() (EXTI->FTSR1 |= RTC_EXTI_LINE_ALARM_EVENT) + +/** + * @brief Disable falling edge trigger on the RTC Alarm associated Exti line. + * @retval None + */ +#define __HAL_RTC_ALARM_EXTI_DISABLE_FALLING_EDGE() (EXTI->FTSR1 &= ~(RTC_EXTI_LINE_ALARM_EVENT)) + +/** + * @brief Enable rising edge trigger on the RTC Alarm associated Exti line. + * @retval None + */ +#define __HAL_RTC_ALARM_EXTI_ENABLE_RISING_EDGE() (EXTI->RTSR1 |= RTC_EXTI_LINE_ALARM_EVENT) + +/** + * @brief Disable rising edge trigger on the RTC Alarm associated Exti line. + * @retval None + */ +#define __HAL_RTC_ALARM_EXTI_DISABLE_RISING_EDGE() (EXTI->RTSR1 &= ~(RTC_EXTI_LINE_ALARM_EVENT)) + +/** + * @brief Enable rising & falling edge trigger on the RTC Alarm associated Exti line. + * @retval None + */ +#define __HAL_RTC_ALARM_EXTI_ENABLE_RISING_FALLING_EDGE() do { \ + __HAL_RTC_ALARM_EXTI_ENABLE_RISING_EDGE(); \ + __HAL_RTC_ALARM_EXTI_ENABLE_FALLING_EDGE(); \ + } while(0) + +/** + * @brief Disable rising & falling edge trigger on the RTC Alarm associated Exti line. + * @retval None + */ +#define __HAL_RTC_ALARM_EXTI_DISABLE_RISING_FALLING_EDGE() do { \ + __HAL_RTC_ALARM_EXTI_DISABLE_RISING_EDGE(); \ + __HAL_RTC_ALARM_EXTI_DISABLE_FALLING_EDGE(); \ + } while(0) + +/** + * @brief Check whether the RTC Alarm associated Exti line interrupt flag is set or not. + * @retval Line Status. + */ +#define __HAL_RTC_ALARM_EXTI_GET_FLAG() (EXTI->PR1 & RTC_EXTI_LINE_ALARM_EVENT) + +/** + * @brief Clear the RTC Alarm associated Exti line flag. + * @retval None + */ +#define __HAL_RTC_ALARM_EXTI_CLEAR_FLAG() (EXTI->PR1 = RTC_EXTI_LINE_ALARM_EVENT) + +/** + * @brief Generate a Software interrupt on RTC Alarm associated Exti line. + * @retval None + */ +#define __HAL_RTC_ALARM_EXTI_GENERATE_SWIT() (EXTI->SWIER1 |= RTC_EXTI_LINE_ALARM_EVENT) + +/** + * @} + */ + +/* Include RTC HAL Extended module */ +#include "stm32l4xx_hal_rtc_ex.h" + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup RTC_Exported_Functions + * @{ + */ + +/** @addtogroup RTC_Exported_Functions_Group1 + * @{ + */ +/* Initialization and de-initialization functions ****************************/ +HAL_StatusTypeDef HAL_RTC_Init(RTC_HandleTypeDef *hrtc); +HAL_StatusTypeDef HAL_RTC_DeInit(RTC_HandleTypeDef *hrtc); +void HAL_RTC_MspInit(RTC_HandleTypeDef *hrtc); +void HAL_RTC_MspDeInit(RTC_HandleTypeDef *hrtc); +/** + * @} + */ + +/** @addtogroup RTC_Exported_Functions_Group2 + * @{ + */ +/* RTC Time and Date functions ************************************************/ +HAL_StatusTypeDef HAL_RTC_SetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format); +HAL_StatusTypeDef HAL_RTC_GetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format); +HAL_StatusTypeDef HAL_RTC_SetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format); +HAL_StatusTypeDef HAL_RTC_GetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format); +/** + * @} + */ + +/** @addtogroup RTC_Exported_Functions_Group3 + * @{ + */ +/* RTC Alarm functions ********************************************************/ +HAL_StatusTypeDef HAL_RTC_SetAlarm(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Format); +HAL_StatusTypeDef HAL_RTC_SetAlarm_IT(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Format); +HAL_StatusTypeDef HAL_RTC_DeactivateAlarm(RTC_HandleTypeDef *hrtc, uint32_t Alarm); +HAL_StatusTypeDef HAL_RTC_GetAlarm(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Alarm, uint32_t Format); +void HAL_RTC_AlarmIRQHandler(RTC_HandleTypeDef *hrtc); +HAL_StatusTypeDef HAL_RTC_PollForAlarmAEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout); +void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc); +/** + * @} + */ + +/** @addtogroup RTC_Exported_Functions_Group4 + * @{ + */ +/* Peripheral Control functions ***********************************************/ +HAL_StatusTypeDef HAL_RTC_WaitForSynchro(RTC_HandleTypeDef* hrtc); +/** + * @} + */ + +/** @addtogroup RTC_Exported_Functions_Group5 + * @{ + */ +/* Peripheral State functions *************************************************/ +HAL_RTCStateTypeDef HAL_RTC_GetState(RTC_HandleTypeDef *hrtc); + +/** + * @} + */ + +/** + * @} + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** @defgroup RTC_Private_Constants RTC Private Constants + * @{ + */ +/* Masks Definition */ +#define RTC_TR_RESERVED_MASK 0x007F7F7FU +#define RTC_DR_RESERVED_MASK 0x00FFFF3FU +#define RTC_INIT_MASK 0xFFFFFFFFU +#define RTC_RSF_MASK 0xFFFFFF5FU + +#define RTC_TIMEOUT_VALUE 1000 + +#define RTC_EXTI_LINE_ALARM_EVENT ((uint32_t)0x00040000) /*!< External interrupt line 18 Connected to the RTC Alarm event */ + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup RTC_Private_Macros RTC Private Macros + * @{ + */ + +/** @defgroup RTC_IS_RTC_Definitions RTC Private macros to check input parameters + * @{ + */ + +#define IS_RTC_HOUR_FORMAT(FORMAT) (((FORMAT) == RTC_HOURFORMAT_12) || \ + ((FORMAT) == RTC_HOURFORMAT_24)) + +#define IS_RTC_OUTPUT_POL(POL) (((POL) == RTC_OUTPUT_POLARITY_HIGH) || \ + ((POL) == RTC_OUTPUT_POLARITY_LOW)) + +#define IS_RTC_OUTPUT_TYPE(TYPE) (((TYPE) == RTC_OUTPUT_TYPE_OPENDRAIN) || \ + ((TYPE) == RTC_OUTPUT_TYPE_PUSHPULL)) + +#define IS_RTC_OUTPUT_REMAP(REMAP) (((REMAP) == RTC_OUTPUT_REMAP_NONE) || \ + ((REMAP) == RTC_OUTPUT_REMAP_POS1)) + +#define IS_RTC_HOURFORMAT12(PM) (((PM) == RTC_HOURFORMAT12_AM) || ((PM) == RTC_HOURFORMAT12_PM)) + +#define IS_RTC_DAYLIGHT_SAVING(SAVE) (((SAVE) == RTC_DAYLIGHTSAVING_SUB1H) || \ + ((SAVE) == RTC_DAYLIGHTSAVING_ADD1H) || \ + ((SAVE) == RTC_DAYLIGHTSAVING_NONE)) + +#define IS_RTC_STORE_OPERATION(OPERATION) (((OPERATION) == RTC_STOREOPERATION_RESET) || \ + ((OPERATION) == RTC_STOREOPERATION_SET)) + +#define IS_RTC_FORMAT(FORMAT) (((FORMAT) == RTC_FORMAT_BIN) || ((FORMAT) == RTC_FORMAT_BCD)) + +#define IS_RTC_YEAR(YEAR) ((YEAR) <= (uint32_t)99) + +#define IS_RTC_MONTH(MONTH) (((MONTH) >= (uint32_t)1) && ((MONTH) <= (uint32_t)12)) + +#define IS_RTC_DATE(DATE) (((DATE) >= (uint32_t)1) && ((DATE) <= (uint32_t)31)) + +#define IS_RTC_WEEKDAY(WEEKDAY) (((WEEKDAY) == RTC_WEEKDAY_MONDAY) || \ + ((WEEKDAY) == RTC_WEEKDAY_TUESDAY) || \ + ((WEEKDAY) == RTC_WEEKDAY_WEDNESDAY) || \ + ((WEEKDAY) == RTC_WEEKDAY_THURSDAY) || \ + ((WEEKDAY) == RTC_WEEKDAY_FRIDAY) || \ + ((WEEKDAY) == RTC_WEEKDAY_SATURDAY) || \ + ((WEEKDAY) == RTC_WEEKDAY_SUNDAY)) + +#define IS_RTC_ALARM_DATE_WEEKDAY_DATE(DATE) (((DATE) >(uint32_t) 0) && ((DATE) <= (uint32_t)31)) + +#define IS_RTC_ALARM_DATE_WEEKDAY_WEEKDAY(WEEKDAY) (((WEEKDAY) == RTC_WEEKDAY_MONDAY) || \ + ((WEEKDAY) == RTC_WEEKDAY_TUESDAY) || \ + ((WEEKDAY) == RTC_WEEKDAY_WEDNESDAY) || \ + ((WEEKDAY) == RTC_WEEKDAY_THURSDAY) || \ + ((WEEKDAY) == RTC_WEEKDAY_FRIDAY) || \ + ((WEEKDAY) == RTC_WEEKDAY_SATURDAY) || \ + ((WEEKDAY) == RTC_WEEKDAY_SUNDAY)) + +#define IS_RTC_ALARM_DATE_WEEKDAY_SEL(SEL) (((SEL) == RTC_ALARMDATEWEEKDAYSEL_DATE) || \ + ((SEL) == RTC_ALARMDATEWEEKDAYSEL_WEEKDAY)) + +#define IS_RTC_ALARM_MASK(MASK) (((MASK) & 0x7F7F7F7F) == (uint32_t)RESET) + +#define IS_RTC_ALARM(ALARM) (((ALARM) == RTC_ALARM_A) || ((ALARM) == RTC_ALARM_B)) + +#define IS_RTC_ALARM_SUB_SECOND_VALUE(VALUE) ((VALUE) <= (uint32_t)0x00007FFF) + +#define IS_RTC_ALARM_SUB_SECOND_MASK(MASK) (((MASK) == RTC_ALARMSUBSECONDMASK_ALL) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14_1) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14_2) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14_3) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14_4) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14_5) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14_6) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14_7) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14_8) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14_9) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14_10) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14_11) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14_12) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14_13) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_NONE)) + +#define IS_RTC_ASYNCH_PREDIV(PREDIV) ((PREDIV) <= (uint32_t)0x7F) + +#define IS_RTC_SYNCH_PREDIV(PREDIV) ((PREDIV) <= (uint32_t)0x7FFF) + +#define IS_RTC_HOUR12(HOUR) (((HOUR) > (uint32_t)0) && ((HOUR) <= (uint32_t)12)) + +#define IS_RTC_HOUR24(HOUR) ((HOUR) <= (uint32_t)23) + +#define IS_RTC_MINUTES(MINUTES) ((MINUTES) <= (uint32_t)59) + +#define IS_RTC_SECONDS(SECONDS) ((SECONDS) <= (uint32_t)59) + +/** + * @} + */ + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ +/** @addtogroup RTC_Private_Functions + * @{ + */ + +HAL_StatusTypeDef RTC_EnterInitMode(RTC_HandleTypeDef* hrtc); +uint8_t RTC_ByteToBcd2(uint8_t Value); +uint8_t RTC_Bcd2ToByte(uint8_t Value); + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_HAL_RTC_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rtc_ex.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rtc_ex.h new file mode 100644 index 0000000..8ba89b0 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_rtc_ex.h @@ -0,0 +1,1100 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_rtc_ex.h + * @author MCD Application Team + * @brief Header file of RTC HAL Extended module. + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_RTC_EX_H +#define __STM32L4xx_HAL_RTC_EX_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup RTCEx + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup RTCEx_Exported_Types RTCEx Exported Types + * @{ + */ +/** + * @brief RTC Tamper structure definition + */ +typedef struct +{ + uint32_t Tamper; /*!< Specifies the Tamper Pin. + This parameter can be a value of @ref RTCEx_Tamper_Pins_Definitions */ + + uint32_t Interrupt; /*!< Specifies the Tamper Interrupt. + This parameter can be a value of @ref RTCEx_Tamper_Interrupt_Definitions */ + + uint32_t Trigger; /*!< Specifies the Tamper Trigger. + This parameter can be a value of @ref RTCEx_Tamper_Trigger_Definitions */ + + uint32_t NoErase; /*!< Specifies the Tamper no erase mode. + This parameter can be a value of @ref RTCEx_Tamper_EraseBackUp_Definitions */ + + uint32_t MaskFlag; /*!< Specifies the Tamper Flag masking. + This parameter can be a value of @ref RTCEx_Tamper_MaskFlag_Definitions */ + + uint32_t Filter; /*!< Specifies the RTC Filter Tamper. + This parameter can be a value of @ref RTCEx_Tamper_Filter_Definitions */ + + uint32_t SamplingFrequency; /*!< Specifies the sampling frequency. + This parameter can be a value of @ref RTCEx_Tamper_Sampling_Frequencies_Definitions */ + + uint32_t PrechargeDuration; /*!< Specifies the Precharge Duration . + This parameter can be a value of @ref RTCEx_Tamper_Pin_Precharge_Duration_Definitions */ + + uint32_t TamperPullUp; /*!< Specifies the Tamper PullUp . + This parameter can be a value of @ref RTCEx_Tamper_Pull_UP_Definitions */ + + uint32_t TimeStampOnTamperDetection; /*!< Specifies the TimeStampOnTamperDetection. + This parameter can be a value of @ref RTCEx_Tamper_TimeStampOnTamperDetection_Definitions */ +}RTC_TamperTypeDef; + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup RTCEx_Exported_Constants RTCEx Exported Constants + * @{ + */ + +/** @defgroup RTCEx_Output_selection_Definitions RTC Output Selection Definitions + * @{ + */ +#define RTC_OUTPUT_DISABLE ((uint32_t)0x00000000) +#define RTC_OUTPUT_ALARMA ((uint32_t)0x00200000) +#define RTC_OUTPUT_ALARMB ((uint32_t)0x00400000) +#define RTC_OUTPUT_WAKEUP ((uint32_t)0x00600000) +/** + * @} + */ + +/** @defgroup RTCEx_Backup_Registers_Definitions RTC Backup Registers Definitions + * @{ + */ +#define RTC_BKP_DR0 ((uint32_t)0x00000000) +#define RTC_BKP_DR1 ((uint32_t)0x00000001) +#define RTC_BKP_DR2 ((uint32_t)0x00000002) +#define RTC_BKP_DR3 ((uint32_t)0x00000003) +#define RTC_BKP_DR4 ((uint32_t)0x00000004) +#define RTC_BKP_DR5 ((uint32_t)0x00000005) +#define RTC_BKP_DR6 ((uint32_t)0x00000006) +#define RTC_BKP_DR7 ((uint32_t)0x00000007) +#define RTC_BKP_DR8 ((uint32_t)0x00000008) +#define RTC_BKP_DR9 ((uint32_t)0x00000009) +#define RTC_BKP_DR10 ((uint32_t)0x0000000A) +#define RTC_BKP_DR11 ((uint32_t)0x0000000B) +#define RTC_BKP_DR12 ((uint32_t)0x0000000C) +#define RTC_BKP_DR13 ((uint32_t)0x0000000D) +#define RTC_BKP_DR14 ((uint32_t)0x0000000E) +#define RTC_BKP_DR15 ((uint32_t)0x0000000F) +#define RTC_BKP_DR16 ((uint32_t)0x00000010) +#define RTC_BKP_DR17 ((uint32_t)0x00000011) +#define RTC_BKP_DR18 ((uint32_t)0x00000012) +#define RTC_BKP_DR19 ((uint32_t)0x00000013) +#define RTC_BKP_DR20 ((uint32_t)0x00000014) +#define RTC_BKP_DR21 ((uint32_t)0x00000015) +#define RTC_BKP_DR22 ((uint32_t)0x00000016) +#define RTC_BKP_DR23 ((uint32_t)0x00000017) +#define RTC_BKP_DR24 ((uint32_t)0x00000018) +#define RTC_BKP_DR25 ((uint32_t)0x00000019) +#define RTC_BKP_DR26 ((uint32_t)0x0000001A) +#define RTC_BKP_DR27 ((uint32_t)0x0000001B) +#define RTC_BKP_DR28 ((uint32_t)0x0000001C) +#define RTC_BKP_DR29 ((uint32_t)0x0000001D) +#define RTC_BKP_DR30 ((uint32_t)0x0000001E) +#define RTC_BKP_DR31 ((uint32_t)0x0000001F) +/** + * @} + */ + +/** @defgroup RTCEx_TimeStamp_Edges_definitions RTC TimeStamp Edges Definitions + * @{ + */ +#define RTC_TIMESTAMPEDGE_RISING ((uint32_t)0x00000000) +#define RTC_TIMESTAMPEDGE_FALLING ((uint32_t)0x00000008) +/** + * @} + */ + +/** @defgroup RTCEx_TimeStamp_Pin_Selection RTC TimeStamp Pins Selection + * @{ + */ +#define RTC_TIMESTAMPPIN_DEFAULT ((uint32_t)0x00000000) +/** + * @} + */ + +/** @defgroup RTCEx_Tamper_Pins_Definitions RTC Tamper Pins Definitions + * @{ + */ +#if defined(RTC_TAMPER1_SUPPORT) +#define RTC_TAMPER_1 RTC_TAMPCR_TAMP1E +#endif /* RTC_TAMPER1_SUPPORT */ +#define RTC_TAMPER_2 RTC_TAMPCR_TAMP2E +#if defined(RTC_TAMPER3_SUPPORT) +#define RTC_TAMPER_3 RTC_TAMPCR_TAMP3E +#endif /* RTC_TAMPER3_SUPPORT */ +/** + * @} + */ + +/** @defgroup RTCEx_Tamper_Interrupt_Definitions RTC Tamper Interrupts Definitions + * @{ + */ +#if defined(RTC_TAMPER1_SUPPORT) +#define RTC_TAMPER1_INTERRUPT RTC_TAMPCR_TAMP1IE +#endif /* RTC_TAMPER1_SUPPORT */ +#define RTC_TAMPER2_INTERRUPT RTC_TAMPCR_TAMP2IE +#if defined(RTC_TAMPER3_SUPPORT) +#define RTC_TAMPER3_INTERRUPT RTC_TAMPCR_TAMP3IE +#endif /* RTC_TAMPER3_SUPPORT */ +#define RTC_ALL_TAMPER_INTERRUPT RTC_TAMPCR_TAMPIE +/** + * @} + */ + +/** @defgroup RTCEx_Tamper_Trigger_Definitions RTC Tamper Triggers Definitions + * @{ + */ +#define RTC_TAMPERTRIGGER_RISINGEDGE ((uint32_t)0x00000000) +#define RTC_TAMPERTRIGGER_FALLINGEDGE ((uint32_t)0x00000002) +#define RTC_TAMPERTRIGGER_LOWLEVEL RTC_TAMPERTRIGGER_RISINGEDGE +#define RTC_TAMPERTRIGGER_HIGHLEVEL RTC_TAMPERTRIGGER_FALLINGEDGE +/** + * @} + */ + +/** @defgroup RTCEx_Tamper_EraseBackUp_Definitions RTC Tamper EraseBackUp Definitions +* @{ +*/ +#define RTC_TAMPER_ERASE_BACKUP_ENABLE ((uint32_t)0x00000000) +#define RTC_TAMPER_ERASE_BACKUP_DISABLE ((uint32_t)0x00020000) +/** + * @} + */ + +/** @defgroup RTCEx_Tamper_MaskFlag_Definitions RTC Tamper Mask Flag Definitions +* @{ +*/ +#define RTC_TAMPERMASK_FLAG_DISABLE ((uint32_t)0x00000000) +#define RTC_TAMPERMASK_FLAG_ENABLE ((uint32_t)0x00040000) +/** + * @} + */ + +/** @defgroup RTCEx_Tamper_Filter_Definitions RTC Tamper Filter Definitions + * @{ + */ +#define RTC_TAMPERFILTER_DISABLE ((uint32_t)0x00000000) /*!< Tamper filter is disabled */ + +#define RTC_TAMPERFILTER_2SAMPLE ((uint32_t)0x00000800) /*!< Tamper is activated after 2 + consecutive samples at the active level */ +#define RTC_TAMPERFILTER_4SAMPLE ((uint32_t)0x00001000) /*!< Tamper is activated after 4 + consecutive samples at the active level */ +#define RTC_TAMPERFILTER_8SAMPLE ((uint32_t)0x00001800) /*!< Tamper is activated after 8 + consecutive samples at the active level. */ +/** + * @} + */ + +/** @defgroup RTCEx_Tamper_Sampling_Frequencies_Definitions RTC Tamper Sampling Frequencies Definitions + * @{ + */ +#define RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV32768 ((uint32_t)0x00000000) /*!< Each of the tamper inputs are sampled + with a frequency = RTCCLK / 32768 */ +#define RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV16384 ((uint32_t)0x00000100) /*!< Each of the tamper inputs are sampled + with a frequency = RTCCLK / 16384 */ +#define RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV8192 ((uint32_t)0x00000200) /*!< Each of the tamper inputs are sampled + with a frequency = RTCCLK / 8192 */ +#define RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV4096 ((uint32_t)0x00000300) /*!< Each of the tamper inputs are sampled + with a frequency = RTCCLK / 4096 */ +#define RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV2048 ((uint32_t)0x00000400) /*!< Each of the tamper inputs are sampled + with a frequency = RTCCLK / 2048 */ +#define RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV1024 ((uint32_t)0x00000500) /*!< Each of the tamper inputs are sampled + with a frequency = RTCCLK / 1024 */ +#define RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV512 ((uint32_t)0x00000600) /*!< Each of the tamper inputs are sampled + with a frequency = RTCCLK / 512 */ +#define RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV256 ((uint32_t)0x00000700) /*!< Each of the tamper inputs are sampled + with a frequency = RTCCLK / 256 */ +/** + * @} + */ + +/** @defgroup RTCEx_Tamper_Pin_Precharge_Duration_Definitions RTC Tamper Pin Precharge Duration Definitions + * @{ + */ +#define RTC_TAMPERPRECHARGEDURATION_1RTCCLK ((uint32_t)0x00000000) /*!< Tamper pins are pre-charged before + sampling during 1 RTCCLK cycle */ +#define RTC_TAMPERPRECHARGEDURATION_2RTCCLK ((uint32_t)0x00002000) /*!< Tamper pins are pre-charged before + sampling during 2 RTCCLK cycles */ +#define RTC_TAMPERPRECHARGEDURATION_4RTCCLK ((uint32_t)0x00004000) /*!< Tamper pins are pre-charged before + sampling during 4 RTCCLK cycles */ +#define RTC_TAMPERPRECHARGEDURATION_8RTCCLK ((uint32_t)0x00006000) /*!< Tamper pins are pre-charged before + sampling during 8 RTCCLK cycles */ +/** + * @} + */ + +/** @defgroup RTCEx_Tamper_TimeStampOnTamperDetection_Definitions RTC Tamper TimeStamp On Tamper Detection Definitions + * @{ + */ +#define RTC_TIMESTAMPONTAMPERDETECTION_ENABLE ((uint32_t)RTC_TAMPCR_TAMPTS) /*!< TimeStamp on Tamper Detection event saved */ +#define RTC_TIMESTAMPONTAMPERDETECTION_DISABLE ((uint32_t)0x00000000) /*!< TimeStamp on Tamper Detection event is not saved */ +/** + * @} + */ + +/** @defgroup RTCEx_Tamper_Pull_UP_Definitions RTC Tamper Pull Up Definitions + * @{ + */ +#define RTC_TAMPER_PULLUP_ENABLE ((uint32_t)0x00000000) /*!< TimeStamp on Tamper Detection event saved */ +#define RTC_TAMPER_PULLUP_DISABLE ((uint32_t)RTC_TAMPCR_TAMPPUDIS) /*!< TimeStamp on Tamper Detection event is not saved */ +/** + * @} + */ + +/** @defgroup RTCEx_Wakeup_Timer_Definitions RTC Wakeup Timer Definitions + * @{ + */ +#define RTC_WAKEUPCLOCK_RTCCLK_DIV16 ((uint32_t)0x00000000) +#define RTC_WAKEUPCLOCK_RTCCLK_DIV8 ((uint32_t)0x00000001) +#define RTC_WAKEUPCLOCK_RTCCLK_DIV4 ((uint32_t)0x00000002) +#define RTC_WAKEUPCLOCK_RTCCLK_DIV2 ((uint32_t)0x00000003) +#define RTC_WAKEUPCLOCK_CK_SPRE_16BITS ((uint32_t)0x00000004) +#define RTC_WAKEUPCLOCK_CK_SPRE_17BITS ((uint32_t)0x00000006) +/** + * @} + */ + +/** @defgroup RTCEx_Smooth_calib_period_Definitions RTC Smooth Calib Period Definitions + * @{ + */ +#define RTC_SMOOTHCALIB_PERIOD_32SEC ((uint32_t)0x00000000) /*!< If RTCCLK = 32768 Hz, Smooth calibration + period is 32s, else 2exp20 RTCCLK seconds */ +#define RTC_SMOOTHCALIB_PERIOD_16SEC ((uint32_t)0x00002000) /*!< If RTCCLK = 32768 Hz, Smooth calibration + period is 16s, else 2exp19 RTCCLK seconds */ +#define RTC_SMOOTHCALIB_PERIOD_8SEC ((uint32_t)0x00004000) /*!< If RTCCLK = 32768 Hz, Smooth calibration + period is 8s, else 2exp18 RTCCLK seconds */ +/** + * @} + */ + +/** @defgroup RTCEx_Smooth_calib_Plus_pulses_Definitions RTC Smooth Calib Plus Pulses Definitions + * @{ + */ +#define RTC_SMOOTHCALIB_PLUSPULSES_SET ((uint32_t)0x00008000) /*!< The number of RTCCLK pulses added + during a X -second window = Y - CALM[8:0] + with Y = 512, 256, 128 when X = 32, 16, 8 */ +#define RTC_SMOOTHCALIB_PLUSPULSES_RESET ((uint32_t)0x00000000) /*!< The number of RTCCLK pulses subbstited + during a 32-second window = CALM[8:0] */ +/** + * @} + */ + +/** @defgroup RTCEx_Calib_Output_selection_Definitions RTC Calib Output Selection Definitions + * @{ + */ +#define RTC_CALIBOUTPUT_512HZ ((uint32_t)0x00000000) +#define RTC_CALIBOUTPUT_1HZ ((uint32_t)0x00080000) +/** + * @} + */ + +/** @defgroup RTCEx_Add_1_Second_Parameter_Definitions RTC Add 1 Second Parameter Definitions + * @{ + */ +#define RTC_SHIFTADD1S_RESET ((uint32_t)0x00000000) +#define RTC_SHIFTADD1S_SET ((uint32_t)0x80000000) +/** + * @} + */ + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ +/** @defgroup RTCEx_Exported_Macros RTCEx Exported Macros + * @{ + */ + +/** + * @brief Enable the RTC WakeUp Timer peripheral. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR |= (RTC_CR_WUTE)) + +/** + * @brief Disable the RTC WakeUp Timer peripheral. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR &= ~(RTC_CR_WUTE)) + +/** + * @brief Enable the RTC WakeUpTimer interrupt. + * @param __HANDLE__: specifies the RTC handle. + * @param __INTERRUPT__: specifies the RTC WakeUpTimer interrupt sources to be enabled. + * This parameter can be: + * @arg RTC_IT_WUT: WakeUpTimer interrupt + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CR |= (__INTERRUPT__)) + +/** + * @brief Disable the RTC WakeUpTimer interrupt. + * @param __HANDLE__: specifies the RTC handle. + * @param __INTERRUPT__: specifies the RTC WakeUpTimer interrupt sources to be disabled. + * This parameter can be: + * @arg RTC_IT_WUT: WakeUpTimer interrupt + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CR &= ~(__INTERRUPT__)) + +/** + * @brief Check whether the specified RTC WakeUpTimer interrupt has occurred or not. + * @param __HANDLE__: specifies the RTC handle. + * @param __INTERRUPT__: specifies the RTC WakeUpTimer interrupt sources to check. + * This parameter can be: + * @arg RTC_IT_WUT: WakeUpTimer interrupt + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_GET_IT(__HANDLE__, __INTERRUPT__) (((((__HANDLE__)->Instance->ISR) & ((__INTERRUPT__)>> 4)) != RESET) ? SET : RESET) + +/** + * @brief Check whether the specified RTC Wake Up timer interrupt is enabled or not. + * @param __HANDLE__: specifies the RTC handle. + * @param __INTERRUPT__: specifies the RTC Wake Up timer interrupt sources to check. + * This parameter can be: + * @arg RTC_IT_WUT: WakeUpTimer interrupt + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) (((((__HANDLE__)->Instance->CR) & (__INTERRUPT__)) != RESET) ? SET : RESET) + +/** + * @brief Get the selected RTC WakeUpTimer's flag status. + * @param __HANDLE__: specifies the RTC handle. + * @param __FLAG__: specifies the RTC WakeUpTimer Flag is pending or not. + * This parameter can be: + * @arg RTC_FLAG_WUTF + * @arg RTC_FLAG_WUTWF + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_GET_FLAG(__HANDLE__, __FLAG__) (((((__HANDLE__)->Instance->ISR) & (__FLAG__)) != RESET) ? SET : RESET) + +/** + * @brief Clear the RTC Wake Up timer's pending flags. + * @param __HANDLE__: specifies the RTC handle. + * @param __FLAG__: specifies the RTC WakeUpTimer Flag to clear. + * This parameter can be: + * @arg RTC_FLAG_WUTF + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->ISR) = (~((__FLAG__) | RTC_ISR_INIT)|((__HANDLE__)->Instance->ISR & RTC_ISR_INIT)) + +#if defined(RTC_TAMPER1_SUPPORT) +/** + * @brief Enable the RTC Tamper1 input detection. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_TAMPER1_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->TAMPCR |= (RTC_TAMPCR_TAMP1E)) + +/** + * @brief Disable the RTC Tamper1 input detection. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_TAMPER1_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->TAMPCR &= ~(RTC_TAMPCR_TAMP1E)) +#endif /* RTC_TAMPER1_SUPPORT */ + +/** + * @brief Enable the RTC Tamper2 input detection. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_TAMPER2_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->TAMPCR |= (RTC_TAMPCR_TAMP2E)) + +/** + * @brief Disable the RTC Tamper2 input detection. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_TAMPER2_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->TAMPCR &= ~(RTC_TAMPCR_TAMP2E)) + +#if defined(RTC_TAMPER3_SUPPORT) +/** + * @brief Enable the RTC Tamper3 input detection. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_TAMPER3_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->TAMPCR |= (RTC_TAMPCR_TAMP3E)) + +/** + * @brief Disable the RTC Tamper3 input detection. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_TAMPER3_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->TAMPCR &= ~(RTC_TAMPCR_TAMP3E)) +#endif /* RTC_TAMPER3_SUPPORT */ + +/** + * @brief Enable the RTC Tamper interrupt. + * @param __HANDLE__: specifies the RTC handle. + * @param __INTERRUPT__: specifies the RTC Tamper interrupt sources to be enabled. + * This parameter can be any combination of the following values: + * @arg RTC_IT_TAMP: All tampers interrupts + * @arg RTC_IT_TAMP1: Tamper1 interrupt + * @arg RTC_IT_TAMP2: Tamper2 interrupt + * @arg RTC_IT_TAMP3: Tamper3 interrupt + * @retval None + */ +#define __HAL_RTC_TAMPER_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->TAMPCR |= (__INTERRUPT__)) + +/** + * @brief Disable the RTC Tamper interrupt. + * @param __HANDLE__: specifies the RTC handle. + * @param __INTERRUPT__: specifies the RTC Tamper interrupt sources to be disabled. + * This parameter can be any combination of the following values: + * @arg RTC_IT_TAMP: All tampers interrupts + * @arg RTC_IT_TAMP1: Tamper1 interrupt + * @arg RTC_IT_TAMP2: Tamper2 interrupt + * @arg RTC_IT_TAMP3: Tamper3 interrupt + * @retval None + */ +#define __HAL_RTC_TAMPER_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->TAMPCR &= ~(__INTERRUPT__)) + +/** + * @brief Check whether the specified RTC Tamper interrupt has occurred or not. + * @param __HANDLE__: specifies the RTC handle. + * @param __INTERRUPT__: specifies the RTC Tamper interrupt to check. + * This parameter can be: + * @arg RTC_IT_TAMP1: Tamper1 interrupt + * @arg RTC_IT_TAMP2: Tamper2 interrupt + * @arg RTC_IT_TAMP3: Tamper3 interrupt + * @retval None + */ +#if defined(RTC_TAMPER1_SUPPORT) && defined(RTC_TAMPER3_SUPPORT) +#define __HAL_RTC_TAMPER_GET_IT(__HANDLE__, __INTERRUPT__) (((__INTERRUPT__) == RTC_IT_TAMP1) ? (((((__HANDLE__)->Instance->ISR) & ((__INTERRUPT__)>> 3)) != RESET) ? SET : RESET) : \ + ((__INTERRUPT__) == RTC_IT_TAMP2) ? (((((__HANDLE__)->Instance->ISR) & ((__INTERRUPT__)>> 5)) != RESET) ? SET : RESET) : \ + (((((__HANDLE__)->Instance->ISR) & ((__INTERRUPT__)>> 7)) != RESET) ? SET : RESET)) +#else +#define __HAL_RTC_TAMPER_GET_IT(__HANDLE__, __INTERRUPT__) (((((__HANDLE__)->Instance->ISR) & ((__INTERRUPT__)>> 5)) != RESET) ? SET : RESET) +#endif /* RTC_TAMPER1_SUPPORT && RTC_TAMPER3_SUPPORT */ + +/** + * @brief Check whether the specified RTC Tamper interrupt is enabled or not. + * @param __HANDLE__: specifies the RTC handle. + * @param __INTERRUPT__: specifies the RTC Tamper interrupt source to check. + * This parameter can be: + * @arg RTC_IT_TAMP: All tampers interrupts + * @arg RTC_IT_TAMP1: Tamper1 interrupt + * @arg RTC_IT_TAMP2: Tamper2 interrupt + * @arg RTC_IT_TAMP3: Tamper3 interrupt + * @retval None + */ +#define __HAL_RTC_TAMPER_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) (((((__HANDLE__)->Instance->TAMPCR) & (__INTERRUPT__)) != RESET) ? SET : RESET) + +/** + * @brief Get the selected RTC Tamper's flag status. + * @param __HANDLE__: specifies the RTC handle. + * @param __FLAG__: specifies the RTC Tamper Flag is pending or not. + * This parameter can be: + * @arg RTC_FLAG_TAMP1F: Tamper1 flag + * @arg RTC_FLAG_TAMP2F: Tamper2 flag + * @arg RTC_FLAG_TAMP3F: Tamper3 flag + * @retval None + */ +#define __HAL_RTC_TAMPER_GET_FLAG(__HANDLE__, __FLAG__) (((((__HANDLE__)->Instance->ISR) & (__FLAG__)) != RESET) ? SET : RESET) + +/** + * @brief Clear the RTC Tamper's pending flags. + * @param __HANDLE__: specifies the RTC handle. + * @param __FLAG__: specifies the RTC Tamper Flag sources to clear. + * This parameter can be: + * @arg RTC_FLAG_TAMP1F: Tamper1 flag + * @arg RTC_FLAG_TAMP2F: Tamper2 flag + * @arg RTC_FLAG_TAMP3F: Tamper3 flag + * @retval None + */ +#define __HAL_RTC_TAMPER_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->ISR) = (~((__FLAG__) | RTC_ISR_INIT)|((__HANDLE__)->Instance->ISR & RTC_ISR_INIT)) + +/** + * @brief Enable the RTC TimeStamp peripheral. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_TIMESTAMP_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR |= (RTC_CR_TSE)) + +/** + * @brief Disable the RTC TimeStamp peripheral. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_TIMESTAMP_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR &= ~(RTC_CR_TSE)) + +/** + * @brief Enable the RTC TimeStamp interrupt. + * @param __HANDLE__: specifies the RTC handle. + * @param __INTERRUPT__: specifies the RTC TimeStamp interrupt source to be enabled. + * This parameter can be: + * @arg RTC_IT_TS: TimeStamp interrupt + * @retval None + */ +#define __HAL_RTC_TIMESTAMP_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CR |= (__INTERRUPT__)) + +/** + * @brief Disable the RTC TimeStamp interrupt. + * @param __HANDLE__: specifies the RTC handle. + * @param __INTERRUPT__: specifies the RTC TimeStamp interrupt source to be disabled. + * This parameter can be: + * @arg RTC_IT_TS: TimeStamp interrupt + * @retval None + */ +#define __HAL_RTC_TIMESTAMP_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CR &= ~(__INTERRUPT__)) + +/** + * @brief Check whether the specified RTC TimeStamp interrupt has occurred or not. + * @param __HANDLE__: specifies the RTC handle. + * @param __INTERRUPT__: specifies the RTC TimeStamp interrupt source to check. + * This parameter can be: + * @arg RTC_IT_TS: TimeStamp interrupt + * @retval None + */ +#define __HAL_RTC_TIMESTAMP_GET_IT(__HANDLE__, __INTERRUPT__) (((((__HANDLE__)->Instance->ISR) & ((__INTERRUPT__)>> 4)) != RESET) ? SET : RESET) + +/** + * @brief Check whether the specified RTC Time Stamp interrupt is enabled or not. + * @param __HANDLE__: specifies the RTC handle. + * @param __INTERRUPT__: specifies the RTC Time Stamp interrupt source to check. + * This parameter can be: + * @arg RTC_IT_TS: TimeStamp interrupt + * @retval None + */ +#define __HAL_RTC_TIMESTAMP_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) (((((__HANDLE__)->Instance->CR) & (__INTERRUPT__)) != RESET) ? SET : RESET) + +/** + * @brief Get the selected RTC TimeStamp's flag status. + * @param __HANDLE__: specifies the RTC handle. + * @param __FLAG__: specifies the RTC TimeStamp Flag is pending or not. + * This parameter can be: + * @arg RTC_FLAG_TSF + * @arg RTC_FLAG_TSOVF + * @retval None + */ +#define __HAL_RTC_TIMESTAMP_GET_FLAG(__HANDLE__, __FLAG__) (((((__HANDLE__)->Instance->ISR) & (__FLAG__)) != RESET) ? SET : RESET) + +/** + * @brief Clear the RTC Time Stamp's pending flags. + * @param __HANDLE__: specifies the RTC handle. + * @param __FLAG__: specifies the RTC Alarm Flag sources to clear. + * This parameter can be: + * @arg RTC_FLAG_TSF + * @arg RTC_FLAG_TSOVF + * @retval None + */ +#define __HAL_RTC_TIMESTAMP_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->ISR) = (~((__FLAG__) | RTC_ISR_INIT)|((__HANDLE__)->Instance->ISR & RTC_ISR_INIT)) + +/** + * @brief Enable the RTC internal TimeStamp peripheral. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_INTERNAL_TIMESTAMP_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR |= (RTC_CR_ITSE)) + +/** + * @brief Disable the RTC internal TimeStamp peripheral. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_INTERNAL_TIMESTAMP_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR &= ~(RTC_CR_ITSE)) + +/** + * @brief Get the selected RTC Internal Time Stamp's flag status. + * @param __HANDLE__: specifies the RTC handle. + * @param __FLAG__: specifies the RTC Internal Time Stamp Flag is pending or not. + * This parameter can be: + * @arg RTC_FLAG_ITSF + * @retval None + */ +#define __HAL_RTC_INTERNAL_TIMESTAMP_GET_FLAG(__HANDLE__, __FLAG__) (((((__HANDLE__)->Instance->ISR) & (__FLAG__)) != RESET) ? SET : RESET) + +/** + * @brief Clear the RTC Internal Time Stamp's pending flags. + * @param __HANDLE__: specifies the RTC handle. + * @param __FLAG__: specifies the RTC Internal Time Stamp Flag source to clear. + * This parameter can be: + * @arg RTC_FLAG_ITSF + * @retval None + */ +#define __HAL_RTC_INTERNAL_TIMESTAMP_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->ISR) = (~((__FLAG__) | RTC_ISR_INIT)|((__HANDLE__)->Instance->ISR & RTC_ISR_INIT)) + +/** + * @brief Enable the RTC calibration output. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_CALIBRATION_OUTPUT_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR |= (RTC_CR_COE)) + +/** + * @brief Disable the calibration output. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_CALIBRATION_OUTPUT_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR &= ~(RTC_CR_COE)) + +/** + * @brief Enable the clock reference detection. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_CLOCKREF_DETECTION_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR |= (RTC_CR_REFCKON)) + +/** + * @brief Disable the clock reference detection. + * @param __HANDLE__: specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_CLOCKREF_DETECTION_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR &= ~(RTC_CR_REFCKON)) + +/** + * @brief Get the selected RTC shift operation's flag status. + * @param __HANDLE__: specifies the RTC handle. + * @param __FLAG__: specifies the RTC shift operation Flag is pending or not. + * This parameter can be: + * @arg RTC_FLAG_SHPF + * @retval None + */ +#define __HAL_RTC_SHIFT_GET_FLAG(__HANDLE__, __FLAG__) (((((__HANDLE__)->Instance->ISR) & (__FLAG__)) != RESET) ? SET : RESET) + +/** + * @brief Enable interrupt on the RTC WakeUp Timer associated Exti line. + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_IT() (EXTI->IMR1 |= RTC_EXTI_LINE_WAKEUPTIMER_EVENT) + +/** + * @brief Disable interrupt on the RTC WakeUp Timer associated Exti line. + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_EXTI_DISABLE_IT() (EXTI->IMR1 &= ~(RTC_EXTI_LINE_WAKEUPTIMER_EVENT)) + +/** + * @brief Enable event on the RTC WakeUp Timer associated Exti line. + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_EVENT() (EXTI->EMR1 |= RTC_EXTI_LINE_WAKEUPTIMER_EVENT) + +/** + * @brief Disable event on the RTC WakeUp Timer associated Exti line. + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_EXTI_DISABLE_EVENT() (EXTI->EMR1 &= ~(RTC_EXTI_LINE_WAKEUPTIMER_EVENT)) + +/** + * @brief Enable falling edge trigger on the RTC WakeUp Timer associated Exti line. + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_FALLING_EDGE() (EXTI->FTSR1 |= RTC_EXTI_LINE_WAKEUPTIMER_EVENT) + +/** + * @brief Disable falling edge trigger on the RTC WakeUp Timer associated Exti line. + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_EXTI_DISABLE_FALLING_EDGE() (EXTI->FTSR1 &= ~(RTC_EXTI_LINE_WAKEUPTIMER_EVENT)) + +/** + * @brief Enable rising edge trigger on the RTC WakeUp Timer associated Exti line. + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_RISING_EDGE() (EXTI->RTSR1 |= RTC_EXTI_LINE_WAKEUPTIMER_EVENT) + +/** + * @brief Disable rising edge trigger on the RTC WakeUp Timer associated Exti line. + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_EXTI_DISABLE_RISING_EDGE() (EXTI->RTSR1 &= ~(RTC_EXTI_LINE_WAKEUPTIMER_EVENT)) + +/** + * @brief Enable rising & falling edge trigger on the RTC WakeUp Timer associated Exti line. + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_RISING_FALLING_EDGE() do { \ + __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_RISING_EDGE(); \ + __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_FALLING_EDGE(); \ + } while(0) + +/** + * @brief Disable rising & falling edge trigger on the RTC WakeUp Timer associated Exti line. + * This parameter can be: + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_EXTI_DISABLE_RISING_FALLING_EDGE() do { \ + __HAL_RTC_WAKEUPTIMER_EXTI_DISABLE_RISING_EDGE(); \ + __HAL_RTC_WAKEUPTIMER_EXTI_DISABLE_FALLING_EDGE(); \ + } while(0) + +/** + * @brief Check whether the RTC WakeUp Timer associated Exti line interrupt flag is set or not. + * @retval Line Status. + */ +#define __HAL_RTC_WAKEUPTIMER_EXTI_GET_FLAG() (EXTI->PR1 & RTC_EXTI_LINE_WAKEUPTIMER_EVENT) + +/** + * @brief Clear the RTC WakeUp Timer associated Exti line flag. + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG() (EXTI->PR1 = RTC_EXTI_LINE_WAKEUPTIMER_EVENT) + +/** + * @brief Generate a Software interrupt on the RTC WakeUp Timer associated Exti line. + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_EXTI_GENERATE_SWIT() (EXTI->SWIER1 |= RTC_EXTI_LINE_WAKEUPTIMER_EVENT) + +/** + * @brief Enable interrupt on the RTC Tamper and Timestamp associated Exti line. + * @retval None + */ +#define __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_IT() (EXTI->IMR1 |= RTC_EXTI_LINE_TAMPER_TIMESTAMP_EVENT) + +/** + * @brief Disable interrupt on the RTC Tamper and Timestamp associated Exti line. + * @retval None + */ +#define __HAL_RTC_TAMPER_TIMESTAMP_EXTI_DISABLE_IT() (EXTI->IMR1 &= ~(RTC_EXTI_LINE_TAMPER_TIMESTAMP_EVENT)) + +/** + * @brief Enable event on the RTC Tamper and Timestamp associated Exti line. + * @retval None + */ +#define __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_EVENT() (EXTI->EMR1 |= RTC_EXTI_LINE_TAMPER_TIMESTAMP_EVENT) + +/** + * @brief Disable event on the RTC Tamper and Timestamp associated Exti line. + * @retval None + */ +#define __HAL_RTC_TAMPER_TIMESTAMP_EXTI_DISABLE_EVENT() (EXTI->EMR1 &= ~(RTC_EXTI_LINE_TAMPER_TIMESTAMP_EVENT)) + +/** + * @brief Enable falling edge trigger on the RTC Tamper and Timestamp associated Exti line. + * @retval None + */ +#define __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_FALLING_EDGE() (EXTI->FTSR1 |= RTC_EXTI_LINE_TAMPER_TIMESTAMP_EVENT) + +/** + * @brief Disable falling edge trigger on the RTC Tamper and Timestamp associated Exti line. + * @retval None + */ +#define __HAL_RTC_TAMPER_TIMESTAMP_EXTI_DISABLE_FALLING_EDGE() (EXTI->FTSR1 &= ~(RTC_EXTI_LINE_TAMPER_TIMESTAMP_EVENT)) + +/** + * @brief Enable rising edge trigger on the RTC Tamper and Timestamp associated Exti line. + * @retval None + */ +#define __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_RISING_EDGE() (EXTI->RTSR1 |= RTC_EXTI_LINE_TAMPER_TIMESTAMP_EVENT) + +/** + * @brief Disable rising edge trigger on the RTC Tamper and Timestamp associated Exti line. + * @retval None + */ +#define __HAL_RTC_TAMPER_TIMESTAMP_EXTI_DISABLE_RISING_EDGE() (EXTI->RTSR1 &= ~(RTC_EXTI_LINE_TAMPER_TIMESTAMP_EVENT)) + +/** + * @brief Enable rising & falling edge trigger on the RTC Tamper and Timestamp associated Exti line. + * @retval None + */ +#define __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_RISING_FALLING_EDGE() do { \ + __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_RISING_EDGE(); \ + __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_FALLING_EDGE(); \ + } while(0) + +/** + * @brief Disable rising & falling edge trigger on the RTC Tamper and Timestamp associated Exti line. + * This parameter can be: + * @retval None + */ +#define __HAL_RTC_TAMPER_TIMESTAMP_EXTI_DISABLE_RISING_FALLING_EDGE() do { \ + __HAL_RTC_TAMPER_TIMESTAMP_EXTI_DISABLE_RISING_EDGE(); \ + __HAL_RTC_TAMPER_TIMESTAMP_EXTI_DISABLE_FALLING_EDGE(); \ + } while(0) + +/** + * @brief Check whether the RTC Tamper and Timestamp associated Exti line interrupt flag is set or not. + * @retval Line Status. + */ +#define __HAL_RTC_TAMPER_TIMESTAMP_EXTI_GET_FLAG() (EXTI->PR1 & RTC_EXTI_LINE_TAMPER_TIMESTAMP_EVENT) + +/** + * @brief Clear the RTC Tamper and Timestamp associated Exti line flag. + * @retval None + */ +#define __HAL_RTC_TAMPER_TIMESTAMP_EXTI_CLEAR_FLAG() (EXTI->PR1 = RTC_EXTI_LINE_TAMPER_TIMESTAMP_EVENT) + +/** + * @brief Generate a Software interrupt on the RTC Tamper and Timestamp associated Exti line + * @retval None + */ +#define __HAL_RTC_TAMPER_TIMESTAMP_EXTI_GENERATE_SWIT() (EXTI->SWIER1 |= RTC_EXTI_LINE_TAMPER_TIMESTAMP_EVENT) + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup RTCEx_Exported_Functions + * @{ + */ + +/* RTC TimeStamp and Tamper functions *****************************************/ +/** @addtogroup RTCEx_Exported_Functions_Group1 + * @{ + */ +HAL_StatusTypeDef HAL_RTCEx_SetTimeStamp(RTC_HandleTypeDef *hrtc, uint32_t TimeStampEdge, uint32_t RTC_TimeStampPin); +HAL_StatusTypeDef HAL_RTCEx_SetTimeStamp_IT(RTC_HandleTypeDef *hrtc, uint32_t TimeStampEdge, uint32_t RTC_TimeStampPin); +HAL_StatusTypeDef HAL_RTCEx_DeactivateTimeStamp(RTC_HandleTypeDef *hrtc); +HAL_StatusTypeDef HAL_RTCEx_SetInternalTimeStamp(RTC_HandleTypeDef *hrtc); +HAL_StatusTypeDef HAL_RTCEx_DeactivateInternalTimeStamp(RTC_HandleTypeDef *hrtc); +HAL_StatusTypeDef HAL_RTCEx_GetTimeStamp(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTimeStamp, RTC_DateTypeDef *sTimeStampDate, uint32_t Format); + +HAL_StatusTypeDef HAL_RTCEx_SetTamper(RTC_HandleTypeDef *hrtc, RTC_TamperTypeDef* sTamper); +HAL_StatusTypeDef HAL_RTCEx_SetTamper_IT(RTC_HandleTypeDef *hrtc, RTC_TamperTypeDef* sTamper); +HAL_StatusTypeDef HAL_RTCEx_DeactivateTamper(RTC_HandleTypeDef *hrtc, uint32_t Tamper); +void HAL_RTCEx_TamperTimeStampIRQHandler(RTC_HandleTypeDef *hrtc); + +#if defined(RTC_TAMPER1_SUPPORT) +void HAL_RTCEx_Tamper1EventCallback(RTC_HandleTypeDef *hrtc); +#endif /* RTC_TAMPER1_SUPPORT */ +void HAL_RTCEx_Tamper2EventCallback(RTC_HandleTypeDef *hrtc); +#if defined(RTC_TAMPER3_SUPPORT) +void HAL_RTCEx_Tamper3EventCallback(RTC_HandleTypeDef *hrtc); +#endif /* RTC_TAMPER3_SUPPORT */ +void HAL_RTCEx_TimeStampEventCallback(RTC_HandleTypeDef *hrtc); +HAL_StatusTypeDef HAL_RTCEx_PollForTimeStampEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout); +#if defined(RTC_TAMPER1_SUPPORT) +HAL_StatusTypeDef HAL_RTCEx_PollForTamper1Event(RTC_HandleTypeDef *hrtc, uint32_t Timeout); +#endif /* RTC_TAMPER1_SUPPORT */ +HAL_StatusTypeDef HAL_RTCEx_PollForTamper2Event(RTC_HandleTypeDef *hrtc, uint32_t Timeout); +#if defined(RTC_TAMPER3_SUPPORT) +HAL_StatusTypeDef HAL_RTCEx_PollForTamper3Event(RTC_HandleTypeDef *hrtc, uint32_t Timeout); +#endif /* RTC_TAMPER3_SUPPORT */ +/** + * @} + */ + +/* RTC Wake-up functions ******************************************************/ +/** @addtogroup RTCEx_Exported_Functions_Group2 + * @{ + */ +HAL_StatusTypeDef HAL_RTCEx_SetWakeUpTimer(RTC_HandleTypeDef *hrtc, uint32_t WakeUpCounter, uint32_t WakeUpClock); +HAL_StatusTypeDef HAL_RTCEx_SetWakeUpTimer_IT(RTC_HandleTypeDef *hrtc, uint32_t WakeUpCounter, uint32_t WakeUpClock); +uint32_t HAL_RTCEx_DeactivateWakeUpTimer(RTC_HandleTypeDef *hrtc); +uint32_t HAL_RTCEx_GetWakeUpTimer(RTC_HandleTypeDef *hrtc); +void HAL_RTCEx_WakeUpTimerIRQHandler(RTC_HandleTypeDef *hrtc); +void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc); +HAL_StatusTypeDef HAL_RTCEx_PollForWakeUpTimerEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout); +/** + * @} + */ + +/* Extended Control functions ************************************************/ +/** @addtogroup RTCEx_Exported_Functions_Group3 + * @{ + */ +void HAL_RTCEx_BKUPWrite(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister, uint32_t Data); +uint32_t HAL_RTCEx_BKUPRead(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister); + +HAL_StatusTypeDef HAL_RTCEx_SetSmoothCalib(RTC_HandleTypeDef *hrtc, uint32_t SmoothCalibPeriod, uint32_t SmoothCalibPlusPulses, uint32_t SmoothCalibMinusPulsesValue); +HAL_StatusTypeDef HAL_RTCEx_SetSynchroShift(RTC_HandleTypeDef *hrtc, uint32_t ShiftAdd1S, uint32_t ShiftSubFS); +HAL_StatusTypeDef HAL_RTCEx_SetCalibrationOutPut(RTC_HandleTypeDef *hrtc, uint32_t CalibOutput); +HAL_StatusTypeDef HAL_RTCEx_DeactivateCalibrationOutPut(RTC_HandleTypeDef *hrtc); +HAL_StatusTypeDef HAL_RTCEx_SetRefClock(RTC_HandleTypeDef *hrtc); +HAL_StatusTypeDef HAL_RTCEx_DeactivateRefClock(RTC_HandleTypeDef *hrtc); +HAL_StatusTypeDef HAL_RTCEx_EnableBypassShadow(RTC_HandleTypeDef *hrtc); +HAL_StatusTypeDef HAL_RTCEx_DisableBypassShadow(RTC_HandleTypeDef *hrtc); +/** + * @} + */ + +/* Extended RTC features functions *******************************************/ +/** @addtogroup RTCEx_Exported_Functions_Group4 + * @{ + */ +void HAL_RTCEx_AlarmBEventCallback(RTC_HandleTypeDef *hrtc); +HAL_StatusTypeDef HAL_RTCEx_PollForAlarmBEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout); +/** + * @} + */ + +/** + * @} + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** @defgroup RTCEx_Private_Constants RTCEx Private Constants + * @{ + */ +#define RTC_EXTI_LINE_TAMPER_TIMESTAMP_EVENT ((uint32_t)0x00080000) /*!< External interrupt line 19 Connected to the RTC Tamper and Time Stamp events */ +#define RTC_EXTI_LINE_WAKEUPTIMER_EVENT ((uint32_t)0x00100000) /*!< External interrupt line 20 Connected to the RTC Wakeup event */ + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup RTCEx_Private_Macros RTCEx Private Macros + * @{ + */ + +/** @defgroup RTCEx_IS_RTC_Definitions Private macros to check input parameters + * @{ + */ + +#define IS_RTC_OUTPUT(OUTPUT) (((OUTPUT) == RTC_OUTPUT_DISABLE) || \ + ((OUTPUT) == RTC_OUTPUT_ALARMA) || \ + ((OUTPUT) == RTC_OUTPUT_ALARMB) || \ + ((OUTPUT) == RTC_OUTPUT_WAKEUP)) + +#define IS_RTC_BKP(BKP) ((BKP) < (uint32_t) RTC_BKP_NUMBER) + +#define IS_TIMESTAMP_EDGE(EDGE) (((EDGE) == RTC_TIMESTAMPEDGE_RISING) || \ + ((EDGE) == RTC_TIMESTAMPEDGE_FALLING)) + +#define IS_RTC_TAMPER(TAMPER) ((((TAMPER) & (uint32_t)0xFFFFFFD6) == 0x00) && ((TAMPER) != (uint32_t)RESET)) + +#define IS_RTC_TAMPER_INTERRUPT(INTERRUPT) ((((INTERRUPT) & (uint32_t)0xFFB6FFFB) == 0x00) && ((INTERRUPT) != (uint32_t)RESET)) + +#define IS_RTC_TIMESTAMP_PIN(PIN) (((PIN) == RTC_TIMESTAMPPIN_DEFAULT)) + +#define IS_RTC_TAMPER_TRIGGER(TRIGGER) (((TRIGGER) == RTC_TAMPERTRIGGER_RISINGEDGE) || \ + ((TRIGGER) == RTC_TAMPERTRIGGER_FALLINGEDGE) || \ + ((TRIGGER) == RTC_TAMPERTRIGGER_LOWLEVEL) || \ + ((TRIGGER) == RTC_TAMPERTRIGGER_HIGHLEVEL)) + +#define IS_RTC_TAMPER_ERASE_MODE(MODE) (((MODE) == RTC_TAMPER_ERASE_BACKUP_ENABLE) || \ + ((MODE) == RTC_TAMPER_ERASE_BACKUP_DISABLE)) + +#define IS_RTC_TAMPER_MASKFLAG_STATE(STATE) (((STATE) == RTC_TAMPERMASK_FLAG_ENABLE) || \ + ((STATE) == RTC_TAMPERMASK_FLAG_DISABLE)) + +#define IS_RTC_TAMPER_FILTER(FILTER) (((FILTER) == RTC_TAMPERFILTER_DISABLE) || \ + ((FILTER) == RTC_TAMPERFILTER_2SAMPLE) || \ + ((FILTER) == RTC_TAMPERFILTER_4SAMPLE) || \ + ((FILTER) == RTC_TAMPERFILTER_8SAMPLE)) + +#define IS_RTC_TAMPER_SAMPLING_FREQ(FREQ) (((FREQ) == RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV32768)|| \ + ((FREQ) == RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV16384)|| \ + ((FREQ) == RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV8192) || \ + ((FREQ) == RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV4096) || \ + ((FREQ) == RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV2048) || \ + ((FREQ) == RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV1024) || \ + ((FREQ) == RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV512) || \ + ((FREQ) == RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV256)) + +#define IS_RTC_TAMPER_PRECHARGE_DURATION(DURATION) (((DURATION) == RTC_TAMPERPRECHARGEDURATION_1RTCCLK) || \ + ((DURATION) == RTC_TAMPERPRECHARGEDURATION_2RTCCLK) || \ + ((DURATION) == RTC_TAMPERPRECHARGEDURATION_4RTCCLK) || \ + ((DURATION) == RTC_TAMPERPRECHARGEDURATION_8RTCCLK)) + +#define IS_RTC_TAMPER_TIMESTAMPONTAMPER_DETECTION(DETECTION) (((DETECTION) == RTC_TIMESTAMPONTAMPERDETECTION_ENABLE) || \ + ((DETECTION) == RTC_TIMESTAMPONTAMPERDETECTION_DISABLE)) + +#define IS_RTC_TAMPER_PULLUP_STATE(STATE) (((STATE) == RTC_TAMPER_PULLUP_ENABLE) || \ + ((STATE) == RTC_TAMPER_PULLUP_DISABLE)) + +#define IS_RTC_WAKEUP_CLOCK(CLOCK) (((CLOCK) == RTC_WAKEUPCLOCK_RTCCLK_DIV16) || \ + ((CLOCK) == RTC_WAKEUPCLOCK_RTCCLK_DIV8) || \ + ((CLOCK) == RTC_WAKEUPCLOCK_RTCCLK_DIV4) || \ + ((CLOCK) == RTC_WAKEUPCLOCK_RTCCLK_DIV2) || \ + ((CLOCK) == RTC_WAKEUPCLOCK_CK_SPRE_16BITS) || \ + ((CLOCK) == RTC_WAKEUPCLOCK_CK_SPRE_17BITS)) + +#define IS_RTC_WAKEUP_COUNTER(COUNTER) ((COUNTER) <= 0xFFFF) + +#define IS_RTC_SMOOTH_CALIB_PERIOD(PERIOD) (((PERIOD) == RTC_SMOOTHCALIB_PERIOD_32SEC) || \ + ((PERIOD) == RTC_SMOOTHCALIB_PERIOD_16SEC) || \ + ((PERIOD) == RTC_SMOOTHCALIB_PERIOD_8SEC)) + +#define IS_RTC_SMOOTH_CALIB_PLUS(PLUS) (((PLUS) == RTC_SMOOTHCALIB_PLUSPULSES_SET) || \ + ((PLUS) == RTC_SMOOTHCALIB_PLUSPULSES_RESET)) + +#define IS_RTC_SMOOTH_CALIB_MINUS(VALUE) ((VALUE) <= 0x000001FF) + +#define IS_RTC_SHIFT_ADD1S(SEL) (((SEL) == RTC_SHIFTADD1S_RESET) || \ + ((SEL) == RTC_SHIFTADD1S_SET)) + +#define IS_RTC_SHIFT_SUBFS(FS) ((FS) <= 0x00007FFF) + +#define IS_RTC_CALIB_OUTPUT(OUTPUT) (((OUTPUT) == RTC_CALIBOUTPUT_512HZ) || \ + ((OUTPUT) == RTC_CALIBOUTPUT_1HZ)) + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_HAL_RTC_EX_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_tim.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_tim.h new file mode 100644 index 0000000..bfc0194 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_tim.h @@ -0,0 +1,2043 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_tim.h + * @author MCD Application Team + * @brief Header file of TIM HAL module. + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_TIM_H +#define __STM32L4xx_HAL_TIM_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup TIM + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup TIM_Exported_Types TIM Exported Types + * @{ + */ + +/** + * @brief TIM Time base Configuration Structure definition + */ +typedef struct +{ + uint32_t Prescaler; /*!< Specifies the prescaler value used to divide the TIM clock. + This parameter can be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF */ + + uint32_t CounterMode; /*!< Specifies the counter mode. + This parameter can be a value of @ref TIM_Counter_Mode */ + + uint32_t Period; /*!< Specifies the period value to be loaded into the active + Auto-Reload Register at the next update event. + This parameter can be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */ + + uint32_t ClockDivision; /*!< Specifies the clock division. + This parameter can be a value of @ref TIM_ClockDivision */ + + uint32_t RepetitionCounter; /*!< Specifies the repetition counter value. Each time the RCR downcounter + reaches zero, an update event is generated and counting restarts + from the RCR value (N). + This means in PWM mode that (N+1) corresponds to: + - the number of PWM periods in edge-aligned mode + - the number of half PWM period in center-aligned mode + This parameter must be a number between Min_Data = 0x00 and Max_Data = 0xFF. + @note This parameter is valid only for TIM1 and TIM8. */ + + uint32_t AutoReloadPreload; /*!< Specifies the auto-reload preload. + This parameter can be a value of @ref TIM_AutoReloadPreload */ +} TIM_Base_InitTypeDef; + +/** + * @brief TIM Output Compare Configuration Structure definition + */ +typedef struct +{ + uint32_t OCMode; /*!< Specifies the TIM mode. + This parameter can be a value of @ref TIM_Output_Compare_and_PWM_modes */ + + uint32_t Pulse; /*!< Specifies the pulse value to be loaded into the Capture Compare Register. + This parameter can be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF */ + + uint32_t OCPolarity; /*!< Specifies the output polarity. + This parameter can be a value of @ref TIM_Output_Compare_Polarity */ + + uint32_t OCNPolarity; /*!< Specifies the complementary output polarity. + This parameter can be a value of @ref TIM_Output_Compare_N_Polarity + @note This parameter is valid only for TIM1 and TIM8. */ + + uint32_t OCFastMode; /*!< Specifies the Fast mode state. + This parameter can be a value of @ref TIM_Output_Fast_State + @note This parameter is valid only in PWM1 and PWM2 mode. */ + + + uint32_t OCIdleState; /*!< Specifies the TIM Output Compare pin state during Idle state. + This parameter can be a value of @ref TIM_Output_Compare_Idle_State + @note This parameter is valid only for TIM1 and TIM8. */ + + uint32_t OCNIdleState; /*!< Specifies the TIM Output Compare pin state during Idle state. + This parameter can be a value of @ref TIM_Output_Compare_N_Idle_State + @note This parameter is valid only for TIM1 and TIM8. */ +} TIM_OC_InitTypeDef; + +/** + * @brief TIM One Pulse Mode Configuration Structure definition + */ +typedef struct +{ + uint32_t OCMode; /*!< Specifies the TIM mode. + This parameter can be a value of @ref TIM_Output_Compare_and_PWM_modes */ + + uint32_t Pulse; /*!< Specifies the pulse value to be loaded into the Capture Compare Register. + This parameter can be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF */ + + uint32_t OCPolarity; /*!< Specifies the output polarity. + This parameter can be a value of @ref TIM_Output_Compare_Polarity */ + + uint32_t OCNPolarity; /*!< Specifies the complementary output polarity. + This parameter can be a value of @ref TIM_Output_Compare_N_Polarity + @note This parameter is valid only for TIM1 and TIM8. */ + + uint32_t OCIdleState; /*!< Specifies the TIM Output Compare pin state during Idle state. + This parameter can be a value of @ref TIM_Output_Compare_Idle_State + @note This parameter is valid only for TIM1 and TIM8. */ + + uint32_t OCNIdleState; /*!< Specifies the TIM Output Compare pin state during Idle state. + This parameter can be a value of @ref TIM_Output_Compare_N_Idle_State + @note This parameter is valid only for TIM1 and TIM8. */ + + uint32_t ICPolarity; /*!< Specifies the active edge of the input signal. + This parameter can be a value of @ref TIM_Input_Capture_Polarity */ + + uint32_t ICSelection; /*!< Specifies the input. + This parameter can be a value of @ref TIM_Input_Capture_Selection */ + + uint32_t ICFilter; /*!< Specifies the input capture filter. + This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */ +} TIM_OnePulse_InitTypeDef; + + +/** + * @brief TIM Input Capture Configuration Structure definition + */ +typedef struct +{ + uint32_t ICPolarity; /*!< Specifies the active edge of the input signal. + This parameter can be a value of @ref TIM_Input_Capture_Polarity */ + + uint32_t ICSelection; /*!< Specifies the input. + This parameter can be a value of @ref TIM_Input_Capture_Selection */ + + uint32_t ICPrescaler; /*!< Specifies the Input Capture Prescaler. + This parameter can be a value of @ref TIM_Input_Capture_Prescaler */ + + uint32_t ICFilter; /*!< Specifies the input capture filter. + This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */ +} TIM_IC_InitTypeDef; + +/** + * @brief TIM Encoder Configuration Structure definition + */ +typedef struct +{ + uint32_t EncoderMode; /*!< Specifies the active edge of the input signal. + This parameter can be a value of @ref TIM_Encoder_Mode */ + + uint32_t IC1Polarity; /*!< Specifies the active edge of the input signal. + This parameter can be a value of @ref TIM_Input_Capture_Polarity */ + + uint32_t IC1Selection; /*!< Specifies the input. + This parameter can be a value of @ref TIM_Input_Capture_Selection */ + + uint32_t IC1Prescaler; /*!< Specifies the Input Capture Prescaler. + This parameter can be a value of @ref TIM_Input_Capture_Prescaler */ + + uint32_t IC1Filter; /*!< Specifies the input capture filter. + This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */ + + uint32_t IC2Polarity; /*!< Specifies the active edge of the input signal. + This parameter can be a value of @ref TIM_Input_Capture_Polarity */ + + uint32_t IC2Selection; /*!< Specifies the input. + This parameter can be a value of @ref TIM_Input_Capture_Selection */ + + uint32_t IC2Prescaler; /*!< Specifies the Input Capture Prescaler. + This parameter can be a value of @ref TIM_Input_Capture_Prescaler */ + + uint32_t IC2Filter; /*!< Specifies the input capture filter. + This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */ +} TIM_Encoder_InitTypeDef; + + +/** + * @brief Clock Configuration Handle Structure definition + */ +typedef struct +{ + uint32_t ClockSource; /*!< TIM clock sources + This parameter can be a value of @ref TIM_Clock_Source */ + uint32_t ClockPolarity; /*!< TIM clock polarity + This parameter can be a value of @ref TIM_Clock_Polarity */ + uint32_t ClockPrescaler; /*!< TIM clock prescaler + This parameter can be a value of @ref TIM_Clock_Prescaler */ + uint32_t ClockFilter; /*!< TIM clock filter + This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */ +}TIM_ClockConfigTypeDef; + +/** + * @brief Clear Input Configuration Handle Structure definition + */ +typedef struct +{ + uint32_t ClearInputState; /*!< TIM clear Input state + This parameter can be ENABLE or DISABLE */ + uint32_t ClearInputSource; /*!< TIM clear Input sources + This parameter can be a value of @ref TIM_ClearInput_Source */ + uint32_t ClearInputPolarity; /*!< TIM Clear Input polarity + This parameter can be a value of @ref TIM_ClearInput_Polarity */ + uint32_t ClearInputPrescaler; /*!< TIM Clear Input prescaler + This parameter can be a value of @ref TIM_ClearInput_Prescaler */ + uint32_t ClearInputFilter; /*!< TIM Clear Input filter + This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */ +}TIM_ClearInputConfigTypeDef; + +/** + * @brief TIM Master configuration Structure definition + * @note Advanced timers provide TRGO2 internal line which is redirected + * to the ADC + */ +typedef struct { + uint32_t MasterOutputTrigger; /*!< Trigger output (TRGO) selection + This parameter can be a value of @ref TIM_Master_Mode_Selection */ + uint32_t MasterOutputTrigger2; /*!< Trigger output2 (TRGO2) selection + This parameter can be a value of @ref TIM_Master_Mode_Selection_2 */ + uint32_t MasterSlaveMode; /*!< Master/slave mode selection + This parameter can be a value of @ref TIM_Master_Slave_Mode */ +}TIM_MasterConfigTypeDef; + +/** + * @brief TIM Slave configuration Structure definition + */ +typedef struct { + uint32_t SlaveMode; /*!< Slave mode selection + This parameter can be a value of @ref TIM_Slave_Mode */ + uint32_t InputTrigger; /*!< Input Trigger source + This parameter can be a value of @ref TIM_Trigger_Selection */ + uint32_t TriggerPolarity; /*!< Input Trigger polarity + This parameter can be a value of @ref TIM_Trigger_Polarity */ + uint32_t TriggerPrescaler; /*!< Input trigger prescaler + This parameter can be a value of @ref TIM_Trigger_Prescaler */ + uint32_t TriggerFilter; /*!< Input trigger filter + This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */ + +}TIM_SlaveConfigTypeDef; + +/** + * @brief TIM Break input(s) and Dead time configuration Structure definition + * @note 2 break inputs can be configured (BKIN and BKIN2) with configurable + * filter and polarity. + */ +typedef struct +{ + uint32_t OffStateRunMode; /*!< TIM off state in run mode + This parameter can be a value of @ref TIM_OSSR_Off_State_Selection_for_Run_mode_state */ + uint32_t OffStateIDLEMode; /*!< TIM off state in IDLE mode + This parameter can be a value of @ref TIM_OSSI_Off_State_Selection_for_Idle_mode_state */ + uint32_t LockLevel; /*!< TIM Lock level + This parameter can be a value of @ref TIM_Lock_level */ + uint32_t DeadTime; /*!< TIM dead Time + This parameter can be a number between Min_Data = 0x00 and Max_Data = 0xFF */ + uint32_t BreakState; /*!< TIM Break State + This parameter can be a value of @ref TIM_Break_Input_enable_disable */ + uint32_t BreakPolarity; /*!< TIM Break input polarity + This parameter can be a value of @ref TIM_Break_Polarity */ + uint32_t BreakFilter; /*!< Specifies the break input filter. + This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */ + uint32_t Break2State; /*!< TIM Break2 State + This parameter can be a value of @ref TIM_Break2_Input_enable_disable */ + uint32_t Break2Polarity; /*!< TIM Break2 input polarity + This parameter can be a value of @ref TIM_Break2_Polarity */ + uint32_t Break2Filter; /*!< TIM break2 input filter. + This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */ + uint32_t AutomaticOutput; /*!< TIM Automatic Output Enable state + This parameter can be a value of @ref TIM_AOE_Bit_Set_Reset */ +} TIM_BreakDeadTimeConfigTypeDef; + +/** + * @brief HAL State structures definition + */ +typedef enum +{ + HAL_TIM_STATE_RESET = 0x00, /*!< Peripheral not yet initialized or disabled */ + HAL_TIM_STATE_READY = 0x01, /*!< Peripheral Initialized and ready for use */ + HAL_TIM_STATE_BUSY = 0x02, /*!< An internal process is ongoing */ + HAL_TIM_STATE_TIMEOUT = 0x03, /*!< Timeout state */ + HAL_TIM_STATE_ERROR = 0x04 /*!< Reception process is ongoing */ +}HAL_TIM_StateTypeDef; + +/** + * @brief HAL Active channel structures definition + */ +typedef enum +{ + HAL_TIM_ACTIVE_CHANNEL_1 = 0x01, /*!< The active channel is 1 */ + HAL_TIM_ACTIVE_CHANNEL_2 = 0x02, /*!< The active channel is 2 */ + HAL_TIM_ACTIVE_CHANNEL_3 = 0x04, /*!< The active channel is 3 */ + HAL_TIM_ACTIVE_CHANNEL_4 = 0x08, /*!< The active channel is 4 */ + HAL_TIM_ACTIVE_CHANNEL_5 = 0x10, /*!< The active channel is 5 */ + HAL_TIM_ACTIVE_CHANNEL_6 = 0x20, /*!< The active channel is 6 */ + HAL_TIM_ACTIVE_CHANNEL_CLEARED = 0x00 /*!< All active channels cleared */ +}HAL_TIM_ActiveChannel; + +/** + * @brief TIM Time Base Handle Structure definition + */ +typedef struct +{ + TIM_TypeDef *Instance; /*!< Register base address */ + TIM_Base_InitTypeDef Init; /*!< TIM Time Base required parameters */ + HAL_TIM_ActiveChannel Channel; /*!< Active channel */ + DMA_HandleTypeDef *hdma[7]; /*!< DMA Handlers array + This array is accessed by a @ref DMA_Handle_index */ + HAL_LockTypeDef Lock; /*!< Locking object */ + __IO HAL_TIM_StateTypeDef State; /*!< TIM operation state */ +}TIM_HandleTypeDef; + +/** + * @} + */ +/* End of exported types -----------------------------------------------------*/ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup TIM_Exported_Constants TIM Exported Constants + * @{ + */ + +/** @defgroup TIM_ClearInput_Source TIM Clear Input Source + * @{ + */ +#define TIM_CLEARINPUTSOURCE_ETR ((uint32_t)0x0001) +#define TIM_CLEARINPUTSOURCE_OCREFCLR ((uint32_t)0x0002) +#define TIM_CLEARINPUTSOURCE_NONE ((uint32_t)0x0000) +/** + * @} + */ + +/** @defgroup TIM_DMA_Base_address TIM DMA Base Address + * @{ + */ +#define TIM_DMABASE_CR1 (0x00000000) +#define TIM_DMABASE_CR2 (0x00000001) +#define TIM_DMABASE_SMCR (0x00000002) +#define TIM_DMABASE_DIER (0x00000003) +#define TIM_DMABASE_SR (0x00000004) +#define TIM_DMABASE_EGR (0x00000005) +#define TIM_DMABASE_CCMR1 (0x00000006) +#define TIM_DMABASE_CCMR2 (0x00000007) +#define TIM_DMABASE_CCER (0x00000008) +#define TIM_DMABASE_CNT (0x00000009) +#define TIM_DMABASE_PSC (0x0000000A) +#define TIM_DMABASE_ARR (0x0000000B) +#define TIM_DMABASE_RCR (0x0000000C) +#define TIM_DMABASE_CCR1 (0x0000000D) +#define TIM_DMABASE_CCR2 (0x0000000E) +#define TIM_DMABASE_CCR3 (0x0000000F) +#define TIM_DMABASE_CCR4 (0x00000010) +#define TIM_DMABASE_BDTR (0x00000011) +#define TIM_DMABASE_DCR (0x00000012) +#define TIM_DMABASE_DMAR (0x00000013) +#define TIM_DMABASE_OR1 (0x00000014) +#define TIM_DMABASE_CCMR3 (0x00000015) +#define TIM_DMABASE_CCR5 (0x00000016) +#define TIM_DMABASE_CCR6 (0x00000017) +#define TIM_DMABASE_OR2 (0x00000018) +#define TIM_DMABASE_OR3 (0x00000019) +/** + * @} + */ + +/** @defgroup TIM_Event_Source TIM Extended Event Source + * @{ + */ +#define TIM_EVENTSOURCE_UPDATE TIM_EGR_UG /*!< Reinitialize the counter and generates an update of the registers */ +#define TIM_EVENTSOURCE_CC1 TIM_EGR_CC1G /*!< A capture/compare event is generated on channel 1 */ +#define TIM_EVENTSOURCE_CC2 TIM_EGR_CC2G /*!< A capture/compare event is generated on channel 2 */ +#define TIM_EVENTSOURCE_CC3 TIM_EGR_CC3G /*!< A capture/compare event is generated on channel 3 */ +#define TIM_EVENTSOURCE_CC4 TIM_EGR_CC4G /*!< A capture/compare event is generated on channel 4 */ +#define TIM_EVENTSOURCE_COM TIM_EGR_COMG /*!< A commutation event is generated */ +#define TIM_EVENTSOURCE_TRIGGER TIM_EGR_TG /*!< A trigger event is generated */ +#define TIM_EVENTSOURCE_BREAK TIM_EGR_BG /*!< A break event is generated */ +#define TIM_EVENTSOURCE_BREAK2 TIM_EGR_B2G /*!< A break 2 event is generated */ +/** + * @} + */ + +/** @defgroup TIM_Input_Channel_Polarity TIM Input Channel polarity + * @{ + */ +#define TIM_INPUTCHANNELPOLARITY_RISING ((uint32_t)0x00000000) /*!< Polarity for TIx source */ +#define TIM_INPUTCHANNELPOLARITY_FALLING (TIM_CCER_CC1P) /*!< Polarity for TIx source */ +#define TIM_INPUTCHANNELPOLARITY_BOTHEDGE (TIM_CCER_CC1P | TIM_CCER_CC1NP) /*!< Polarity for TIx source */ +/** + * @} + */ + +/** @defgroup TIM_ETR_Polarity TIM ETR Polarity + * @{ + */ +#define TIM_ETRPOLARITY_INVERTED (TIM_SMCR_ETP) /*!< Polarity for ETR source */ +#define TIM_ETRPOLARITY_NONINVERTED ((uint32_t)0x0000) /*!< Polarity for ETR source */ +/** + * @} + */ + +/** @defgroup TIM_ETR_Prescaler TIM ETR Prescaler + * @{ + */ +#define TIM_ETRPRESCALER_DIV1 ((uint32_t)0x0000) /*!< No prescaler is used */ +#define TIM_ETRPRESCALER_DIV2 (TIM_SMCR_ETPS_0) /*!< ETR input source is divided by 2 */ +#define TIM_ETRPRESCALER_DIV4 (TIM_SMCR_ETPS_1) /*!< ETR input source is divided by 4 */ +#define TIM_ETRPRESCALER_DIV8 (TIM_SMCR_ETPS) /*!< ETR input source is divided by 8 */ +/** + * @} + */ + +/** @defgroup TIM_Counter_Mode TIM Counter Mode + * @{ + */ +#define TIM_COUNTERMODE_UP ((uint32_t)0x0000) +#define TIM_COUNTERMODE_DOWN TIM_CR1_DIR +#define TIM_COUNTERMODE_CENTERALIGNED1 TIM_CR1_CMS_0 +#define TIM_COUNTERMODE_CENTERALIGNED2 TIM_CR1_CMS_1 +#define TIM_COUNTERMODE_CENTERALIGNED3 TIM_CR1_CMS +/** + * @} + */ + +/** @defgroup TIM_ClockDivision TIM Clock Division + * @{ + */ +#define TIM_CLOCKDIVISION_DIV1 ((uint32_t)0x0000) +#define TIM_CLOCKDIVISION_DIV2 (TIM_CR1_CKD_0) +#define TIM_CLOCKDIVISION_DIV4 (TIM_CR1_CKD_1) +/** + * @} + */ + +/** @defgroup TIM_AutoReloadPreload TIM Auto-Reload Preload + * @{ + */ +#define TIM_AUTORELOAD_PRELOAD_DISABLE ((uint32_t)0x0000) /*!< TIMx_ARR register is not buffered */ +#define TIM_AUTORELOAD_PRELOAD_ENABLE (TIM_CR1_ARPE) /*!< TIMx_ARR register is buffered */ +/** + * @} + */ + +/** @defgroup TIM_Output_Compare_State TIM Output Compare State + * @{ + */ +#define TIM_OUTPUTSTATE_DISABLE ((uint32_t)0x0000) +#define TIM_OUTPUTSTATE_ENABLE (TIM_CCER_CC1E) +/** + * @} + */ + +/** @defgroup TIM_Output_Compare_N_State TIM Complementary Output Compare State + * @{ + */ +#define TIM_OUTPUTNSTATE_DISABLE ((uint32_t)0x0000) +#define TIM_OUTPUTNSTATE_ENABLE (TIM_CCER_CC1NE) +/** + * @} + */ + +/** @defgroup TIM_Output_Fast_State TIM Output Fast State + * @{ + */ +#define TIM_OCFAST_DISABLE ((uint32_t)0x0000) +#define TIM_OCFAST_ENABLE (TIM_CCMR1_OC1FE) +/** + * @} + */ + +/** @defgroup TIM_Output_Compare_Polarity TIM Output Compare Polarity + * @{ + */ +#define TIM_OCPOLARITY_HIGH ((uint32_t)0x0000) +#define TIM_OCPOLARITY_LOW (TIM_CCER_CC1P) +/** + * @} + */ + +/** @defgroup TIM_Output_Compare_N_Polarity TIM Complementary Output Compare Polarity + * @{ + */ +#define TIM_OCNPOLARITY_HIGH ((uint32_t)0x0000) +#define TIM_OCNPOLARITY_LOW (TIM_CCER_CC1NP) +/** + * @} + */ + +/** @defgroup TIM_Output_Compare_Idle_State TIM Output Compare Idle State + * @{ + */ +#define TIM_OCIDLESTATE_SET (TIM_CR2_OIS1) +#define TIM_OCIDLESTATE_RESET ((uint32_t)0x0000) +/** + * @} + */ + +/** @defgroup TIM_Output_Compare_N_Idle_State TIM Complementary Output Compare Idle State + * @{ + */ +#define TIM_OCNIDLESTATE_SET (TIM_CR2_OIS1N) +#define TIM_OCNIDLESTATE_RESET ((uint32_t)0x0000) +/** + * @} + */ + +/** @defgroup TIM_Input_Capture_Polarity TIM Input Capture Polarity + * @{ + */ +#define TIM_ICPOLARITY_RISING TIM_INPUTCHANNELPOLARITY_RISING +#define TIM_ICPOLARITY_FALLING TIM_INPUTCHANNELPOLARITY_FALLING +#define TIM_ICPOLARITY_BOTHEDGE TIM_INPUTCHANNELPOLARITY_BOTHEDGE +/** + * @} + */ + +/** @defgroup TIM_Input_Capture_Selection TIM Input Capture Selection + * @{ + */ +#define TIM_ICSELECTION_DIRECTTI (TIM_CCMR1_CC1S_0) /*!< TIM Input 1, 2, 3 or 4 is selected to be + connected to IC1, IC2, IC3 or IC4, respectively */ +#define TIM_ICSELECTION_INDIRECTTI (TIM_CCMR1_CC1S_1) /*!< TIM Input 1, 2, 3 or 4 is selected to be + connected to IC2, IC1, IC4 or IC3, respectively */ +#define TIM_ICSELECTION_TRC (TIM_CCMR1_CC1S) /*!< TIM Input 1, 2, 3 or 4 is selected to be connected to TRC */ +/** + * @} + */ + +/** @defgroup TIM_Input_Capture_Prescaler TIM Input Capture Prescaler + * @{ + */ +#define TIM_ICPSC_DIV1 ((uint32_t)0x0000) /*!< Capture performed each time an edge is detected on the capture input */ +#define TIM_ICPSC_DIV2 (TIM_CCMR1_IC1PSC_0) /*!< Capture performed once every 2 events */ +#define TIM_ICPSC_DIV4 (TIM_CCMR1_IC1PSC_1) /*!< Capture performed once every 4 events */ +#define TIM_ICPSC_DIV8 (TIM_CCMR1_IC1PSC) /*!< Capture performed once every 8 events */ +/** + * @} + */ + +/** @defgroup TIM_One_Pulse_Mode TIM One Pulse Mode + * @{ + */ +#define TIM_OPMODE_SINGLE (TIM_CR1_OPM) +#define TIM_OPMODE_REPETITIVE ((uint32_t)0x0000) +/** + * @} + */ + +/** @defgroup TIM_Encoder_Mode TIM Encoder Mode + * @{ + */ +#define TIM_ENCODERMODE_TI1 (TIM_SMCR_SMS_0) +#define TIM_ENCODERMODE_TI2 (TIM_SMCR_SMS_1) +#define TIM_ENCODERMODE_TI12 (TIM_SMCR_SMS_1 | TIM_SMCR_SMS_0) +/** + * @} + */ + +/** @defgroup TIM_Interrupt_definition TIM interrupt Definition + * @{ + */ +#define TIM_IT_UPDATE (TIM_DIER_UIE) +#define TIM_IT_CC1 (TIM_DIER_CC1IE) +#define TIM_IT_CC2 (TIM_DIER_CC2IE) +#define TIM_IT_CC3 (TIM_DIER_CC3IE) +#define TIM_IT_CC4 (TIM_DIER_CC4IE) +#define TIM_IT_COM (TIM_DIER_COMIE) +#define TIM_IT_TRIGGER (TIM_DIER_TIE) +#define TIM_IT_BREAK (TIM_DIER_BIE) +/** + * @} + */ + +/** @defgroup TIM_Commutation_Source TIM Commutation Source + * @{ + */ +#define TIM_COMMUTATION_TRGI (TIM_CR2_CCUS) +#define TIM_COMMUTATION_SOFTWARE ((uint32_t)0x0000) +/** + * @} + */ + +/** @defgroup TIM_DMA_sources TIM DMA Sources + * @{ + */ +#define TIM_DMA_UPDATE (TIM_DIER_UDE) +#define TIM_DMA_CC1 (TIM_DIER_CC1DE) +#define TIM_DMA_CC2 (TIM_DIER_CC2DE) +#define TIM_DMA_CC3 (TIM_DIER_CC3DE) +#define TIM_DMA_CC4 (TIM_DIER_CC4DE) +#define TIM_DMA_COM (TIM_DIER_COMDE) +#define TIM_DMA_TRIGGER (TIM_DIER_TDE) +/** + * @} + */ + +/** @defgroup TIM_Flag_definition TIM Flag Definition + * @{ + */ +#define TIM_FLAG_UPDATE (TIM_SR_UIF) +#define TIM_FLAG_CC1 (TIM_SR_CC1IF) +#define TIM_FLAG_CC2 (TIM_SR_CC2IF) +#define TIM_FLAG_CC3 (TIM_SR_CC3IF) +#define TIM_FLAG_CC4 (TIM_SR_CC4IF) +#define TIM_FLAG_CC5 (TIM_SR_CC5IF) +#define TIM_FLAG_CC6 (TIM_SR_CC6IF) +#define TIM_FLAG_COM (TIM_SR_COMIF) +#define TIM_FLAG_TRIGGER (TIM_SR_TIF) +#define TIM_FLAG_BREAK (TIM_SR_BIF) +#define TIM_FLAG_BREAK2 (TIM_SR_B2IF) +#define TIM_FLAG_SYSTEM_BREAK (TIM_SR_SBIF) +#define TIM_FLAG_CC1OF (TIM_SR_CC1OF) +#define TIM_FLAG_CC2OF (TIM_SR_CC2OF) +#define TIM_FLAG_CC3OF (TIM_SR_CC3OF) +#define TIM_FLAG_CC4OF (TIM_SR_CC4OF) +/** + * @} + */ + +/** @defgroup TIM_Channel TIM Channel + * @{ + */ +#define TIM_CHANNEL_1 ((uint32_t)0x0000) +#define TIM_CHANNEL_2 ((uint32_t)0x0004) +#define TIM_CHANNEL_3 ((uint32_t)0x0008) +#define TIM_CHANNEL_4 ((uint32_t)0x000C) +#define TIM_CHANNEL_5 ((uint32_t)0x0010) +#define TIM_CHANNEL_6 ((uint32_t)0x0014) +#define TIM_CHANNEL_ALL ((uint32_t)0x003C) +/** + * @} + */ + +/** @defgroup TIM_Clock_Source TIM Clock Source + * @{ + */ +#define TIM_CLOCKSOURCE_ETRMODE2 (TIM_SMCR_ETPS_1) +#define TIM_CLOCKSOURCE_INTERNAL (TIM_SMCR_ETPS_0) +#define TIM_CLOCKSOURCE_ITR0 ((uint32_t)0x0000) +#define TIM_CLOCKSOURCE_ITR1 (TIM_SMCR_TS_0) +#define TIM_CLOCKSOURCE_ITR2 (TIM_SMCR_TS_1) +#define TIM_CLOCKSOURCE_ITR3 (TIM_SMCR_TS_0 | TIM_SMCR_TS_1) +#define TIM_CLOCKSOURCE_TI1ED (TIM_SMCR_TS_2) +#define TIM_CLOCKSOURCE_TI1 (TIM_SMCR_TS_0 | TIM_SMCR_TS_2) +#define TIM_CLOCKSOURCE_TI2 (TIM_SMCR_TS_1 | TIM_SMCR_TS_2) +#define TIM_CLOCKSOURCE_ETRMODE1 (TIM_SMCR_TS) +/** + * @} + */ + +/** @defgroup TIM_Clock_Polarity TIM Clock Polarity + * @{ + */ +#define TIM_CLOCKPOLARITY_INVERTED TIM_ETRPOLARITY_INVERTED /*!< Polarity for ETRx clock sources */ +#define TIM_CLOCKPOLARITY_NONINVERTED TIM_ETRPOLARITY_NONINVERTED /*!< Polarity for ETRx clock sources */ +#define TIM_CLOCKPOLARITY_RISING TIM_INPUTCHANNELPOLARITY_RISING /*!< Polarity for TIx clock sources */ +#define TIM_CLOCKPOLARITY_FALLING TIM_INPUTCHANNELPOLARITY_FALLING /*!< Polarity for TIx clock sources */ +#define TIM_CLOCKPOLARITY_BOTHEDGE TIM_INPUTCHANNELPOLARITY_BOTHEDGE /*!< Polarity for TIx clock sources */ +/** + * @} + */ + +/** @defgroup TIM_Clock_Prescaler TIM Clock Prescaler + * @{ + */ +#define TIM_CLOCKPRESCALER_DIV1 TIM_ETRPRESCALER_DIV1 /*!< No prescaler is used */ +#define TIM_CLOCKPRESCALER_DIV2 TIM_ETRPRESCALER_DIV2 /*!< Prescaler for External ETR Clock: Capture performed once every 2 events. */ +#define TIM_CLOCKPRESCALER_DIV4 TIM_ETRPRESCALER_DIV4 /*!< Prescaler for External ETR Clock: Capture performed once every 4 events. */ +#define TIM_CLOCKPRESCALER_DIV8 TIM_ETRPRESCALER_DIV8 /*!< Prescaler for External ETR Clock: Capture performed once every 8 events. */ +/** + * @} + */ + +/** @defgroup TIM_ClearInput_Polarity TIM Clear Input Polarity + * @{ + */ +#define TIM_CLEARINPUTPOLARITY_INVERTED TIM_ETRPOLARITY_INVERTED /*!< Polarity for ETRx pin */ +#define TIM_CLEARINPUTPOLARITY_NONINVERTED TIM_ETRPOLARITY_NONINVERTED /*!< Polarity for ETRx pin */ +/** + * @} + */ + +/** @defgroup TIM_ClearInput_Prescaler TIM Clear Input Prescaler + * @{ + */ +#define TIM_CLEARINPUTPRESCALER_DIV1 TIM_ETRPRESCALER_DIV1 /*!< No prescaler is used */ +#define TIM_CLEARINPUTPRESCALER_DIV2 TIM_ETRPRESCALER_DIV2 /*!< Prescaler for External ETR pin: Capture performed once every 2 events. */ +#define TIM_CLEARINPUTPRESCALER_DIV4 TIM_ETRPRESCALER_DIV4 /*!< Prescaler for External ETR pin: Capture performed once every 4 events. */ +#define TIM_CLEARINPUTPRESCALER_DIV8 TIM_ETRPRESCALER_DIV8 /*!< Prescaler for External ETR pin: Capture performed once every 8 events. */ +/** + * @} + */ + +/** @defgroup TIM_OSSR_Off_State_Selection_for_Run_mode_state TIM OSSR OffState Selection for Run mode state + * @{ + */ +#define TIM_OSSR_ENABLE (TIM_BDTR_OSSR) +#define TIM_OSSR_DISABLE ((uint32_t)0x0000) +/** + * @} + */ + +/** @defgroup TIM_OSSI_Off_State_Selection_for_Idle_mode_state TIM OSSI OffState Selection for Idle mode state + * @{ + */ +#define TIM_OSSI_ENABLE (TIM_BDTR_OSSI) +#define TIM_OSSI_DISABLE ((uint32_t)0x0000) +/** + * @} + */ +/** @defgroup TIM_Lock_level TIM Lock level + * @{ + */ +#define TIM_LOCKLEVEL_OFF ((uint32_t)0x0000) +#define TIM_LOCKLEVEL_1 (TIM_BDTR_LOCK_0) +#define TIM_LOCKLEVEL_2 (TIM_BDTR_LOCK_1) +#define TIM_LOCKLEVEL_3 (TIM_BDTR_LOCK) +/** + * @} + */ + +/** @defgroup TIM_Break_Input_enable_disable TIM Break Input Enable + * @{ + */ +#define TIM_BREAK_ENABLE (TIM_BDTR_BKE) +#define TIM_BREAK_DISABLE ((uint32_t)0x0000) +/** + * @} + */ + +/** @defgroup TIM_Break_Polarity TIM Break Input Polarity + * @{ + */ +#define TIM_BREAKPOLARITY_LOW ((uint32_t)0x0000) +#define TIM_BREAKPOLARITY_HIGH (TIM_BDTR_BKP) +/** + * @} + */ + +/** @defgroup TIM_Break2_Input_enable_disable TIM Break input 2 Enable + * @{ + */ +#define TIM_BREAK2_DISABLE ((uint32_t)0x00000000) +#define TIM_BREAK2_ENABLE ((uint32_t)TIM_BDTR_BK2E) +/** + * @} + */ + +/** @defgroup TIM_Break2_Polarity TIM Break Input 2 Polarity + * @{ + */ +#define TIM_BREAK2POLARITY_LOW ((uint32_t)0x00000000) +#define TIM_BREAK2POLARITY_HIGH ((uint32_t)TIM_BDTR_BK2P) +/** + * @} + */ + +/** @defgroup TIM_AOE_Bit_Set_Reset TIM Automatic Output Enable + * @{ + */ +#define TIM_AUTOMATICOUTPUT_ENABLE (TIM_BDTR_AOE) +#define TIM_AUTOMATICOUTPUT_DISABLE ((uint32_t)0x0000) +/** + * @} + */ + +/** @defgroup TIM_Group_Channel5 Group Channel 5 and Channel 1, 2 or 3 + * @{ + */ +#define TIM_GROUPCH5_NONE (uint32_t)0x00000000 /* !< No effect of OC5REF on OC1REFC, OC2REFC and OC3REFC */ +#define TIM_GROUPCH5_OC1REFC (TIM_CCR5_GC5C1) /* !< OC1REFC is the logical AND of OC1REFC and OC5REF */ +#define TIM_GROUPCH5_OC2REFC (TIM_CCR5_GC5C2) /* !< OC2REFC is the logical AND of OC2REFC and OC5REF */ +#define TIM_GROUPCH5_OC3REFC (TIM_CCR5_GC5C3) /* !< OC3REFC is the logical AND of OC3REFC and OC5REF */ +/** + * @} + */ + +/** @defgroup TIM_Master_Mode_Selection TIM Master Mode Selection + * @{ + */ +#define TIM_TRGO_RESET ((uint32_t)0x0000) +#define TIM_TRGO_ENABLE (TIM_CR2_MMS_0) +#define TIM_TRGO_UPDATE (TIM_CR2_MMS_1) +#define TIM_TRGO_OC1 ((TIM_CR2_MMS_1 | TIM_CR2_MMS_0)) +#define TIM_TRGO_OC1REF (TIM_CR2_MMS_2) +#define TIM_TRGO_OC2REF ((TIM_CR2_MMS_2 | TIM_CR2_MMS_0)) +#define TIM_TRGO_OC3REF ((TIM_CR2_MMS_2 | TIM_CR2_MMS_1)) +#define TIM_TRGO_OC4REF ((TIM_CR2_MMS_2 | TIM_CR2_MMS_1 | TIM_CR2_MMS_0)) +/** + * @} + */ + +/** @defgroup TIM_Master_Mode_Selection_2 TIM Master Mode Selection 2 (TRGO2) + * @{ + */ +#define TIM_TRGO2_RESET ((uint32_t)0x00000000) +#define TIM_TRGO2_ENABLE ((uint32_t)(TIM_CR2_MMS2_0)) +#define TIM_TRGO2_UPDATE ((uint32_t)(TIM_CR2_MMS2_1)) +#define TIM_TRGO2_OC1 ((uint32_t)(TIM_CR2_MMS2_1 | TIM_CR2_MMS2_0)) +#define TIM_TRGO2_OC1REF ((uint32_t)(TIM_CR2_MMS2_2)) +#define TIM_TRGO2_OC2REF ((uint32_t)(TIM_CR2_MMS2_2 | TIM_CR2_MMS2_0)) +#define TIM_TRGO2_OC3REF ((uint32_t)(TIM_CR2_MMS2_2 | TIM_CR2_MMS2_1)) +#define TIM_TRGO2_OC4REF ((uint32_t)(TIM_CR2_MMS2_2 | TIM_CR2_MMS2_1 | TIM_CR2_MMS2_0)) +#define TIM_TRGO2_OC5REF ((uint32_t)(TIM_CR2_MMS2_3)) +#define TIM_TRGO2_OC6REF ((uint32_t)(TIM_CR2_MMS2_3 | TIM_CR2_MMS2_0)) +#define TIM_TRGO2_OC4REF_RISINGFALLING ((uint32_t)(TIM_CR2_MMS2_3 | TIM_CR2_MMS2_1)) +#define TIM_TRGO2_OC6REF_RISINGFALLING ((uint32_t)(TIM_CR2_MMS2_3 | TIM_CR2_MMS2_1 | TIM_CR2_MMS2_0)) +#define TIM_TRGO2_OC4REF_RISING_OC6REF_RISING ((uint32_t)(TIM_CR2_MMS2_3 | TIM_CR2_MMS2_2)) +#define TIM_TRGO2_OC4REF_RISING_OC6REF_FALLING ((uint32_t)(TIM_CR2_MMS2_3 | TIM_CR2_MMS2_2 | TIM_CR2_MMS2_0)) +#define TIM_TRGO2_OC5REF_RISING_OC6REF_RISING ((uint32_t)(TIM_CR2_MMS2_3 | TIM_CR2_MMS2_2 |TIM_CR2_MMS2_1)) +#define TIM_TRGO2_OC5REF_RISING_OC6REF_FALLING ((uint32_t)(TIM_CR2_MMS2_3 | TIM_CR2_MMS2_2 | TIM_CR2_MMS2_1 | TIM_CR2_MMS2_0)) +/** + * @} + */ + +/** @defgroup TIM_Master_Slave_Mode TIM Master/Slave Mode + * @{ + */ +#define TIM_MASTERSLAVEMODE_ENABLE ((uint32_t)0x0080) +#define TIM_MASTERSLAVEMODE_DISABLE ((uint32_t)0x0000) +/** + * @} + */ + +/** @defgroup TIM_Slave_Mode TIM Slave mode + * @{ + */ +#define TIM_SLAVEMODE_DISABLE ((uint32_t)0x0000) +#define TIM_SLAVEMODE_RESET ((uint32_t)(TIM_SMCR_SMS_2)) +#define TIM_SLAVEMODE_GATED ((uint32_t)(TIM_SMCR_SMS_2 | TIM_SMCR_SMS_0)) +#define TIM_SLAVEMODE_TRIGGER ((uint32_t)(TIM_SMCR_SMS_2 | TIM_SMCR_SMS_1)) +#define TIM_SLAVEMODE_EXTERNAL1 ((uint32_t)(TIM_SMCR_SMS_2 | TIM_SMCR_SMS_1 | TIM_SMCR_SMS_0)) +#define TIM_SLAVEMODE_COMBINED_RESETTRIGGER ((uint32_t)(TIM_SMCR_SMS_3)) +/** + * @} + */ + +/** @defgroup TIM_Output_Compare_and_PWM_modes TIM Output Compare and PWM Modes + * @{ + */ +#define TIM_OCMODE_TIMING ((uint32_t)0x0000) +#define TIM_OCMODE_ACTIVE ((uint32_t)TIM_CCMR1_OC1M_0) +#define TIM_OCMODE_INACTIVE ((uint32_t)TIM_CCMR1_OC1M_1) +#define TIM_OCMODE_TOGGLE ((uint32_t)TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_0) +#define TIM_OCMODE_PWM1 ((uint32_t)TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1) +#define TIM_OCMODE_PWM2 ((uint32_t)TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_0) +#define TIM_OCMODE_FORCED_ACTIVE ((uint32_t)TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_0) +#define TIM_OCMODE_FORCED_INACTIVE ((uint32_t)TIM_CCMR1_OC1M_2) + +#define TIM_OCMODE_RETRIGERRABLE_OPM1 ((uint32_t)TIM_CCMR1_OC1M_3) +#define TIM_OCMODE_RETRIGERRABLE_OPM2 ((uint32_t)TIM_CCMR1_OC1M_3 | TIM_CCMR1_OC1M_0) +#define TIM_OCMODE_COMBINED_PWM1 ((uint32_t)TIM_CCMR1_OC1M_3 | TIM_CCMR1_OC1M_2) +#define TIM_OCMODE_COMBINED_PWM2 ((uint32_t)TIM_CCMR1_OC1M_3 | TIM_CCMR1_OC1M_0 | TIM_CCMR1_OC1M_2) +#define TIM_OCMODE_ASSYMETRIC_PWM1 ((uint32_t)TIM_CCMR1_OC1M_3 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2) +#define TIM_OCMODE_ASSYMETRIC_PWM2 ((uint32_t)TIM_CCMR1_OC1M_3 | TIM_CCMR1_OC1M) +/** + * @} + */ + +/** @defgroup TIM_Trigger_Selection TIM Trigger Selection + * @{ + */ +#define TIM_TS_ITR0 ((uint32_t)0x0000) +#define TIM_TS_ITR1 ((uint32_t)0x0010) +#define TIM_TS_ITR2 ((uint32_t)0x0020) +#define TIM_TS_ITR3 ((uint32_t)0x0030) +#define TIM_TS_TI1F_ED ((uint32_t)0x0040) +#define TIM_TS_TI1FP1 ((uint32_t)0x0050) +#define TIM_TS_TI2FP2 ((uint32_t)0x0060) +#define TIM_TS_ETRF ((uint32_t)0x0070) +#define TIM_TS_NONE ((uint32_t)0xFFFF) +/** + * @} + */ + +/** @defgroup TIM_Trigger_Polarity TIM Trigger Polarity + * @{ + */ +#define TIM_TRIGGERPOLARITY_INVERTED TIM_ETRPOLARITY_INVERTED /*!< Polarity for ETRx trigger sources */ +#define TIM_TRIGGERPOLARITY_NONINVERTED TIM_ETRPOLARITY_NONINVERTED /*!< Polarity for ETRx trigger sources */ +#define TIM_TRIGGERPOLARITY_RISING TIM_INPUTCHANNELPOLARITY_RISING /*!< Polarity for TIxFPx or TI1_ED trigger sources */ +#define TIM_TRIGGERPOLARITY_FALLING TIM_INPUTCHANNELPOLARITY_FALLING /*!< Polarity for TIxFPx or TI1_ED trigger sources */ +#define TIM_TRIGGERPOLARITY_BOTHEDGE TIM_INPUTCHANNELPOLARITY_BOTHEDGE /*!< Polarity for TIxFPx or TI1_ED trigger sources */ +/** + * @} + */ + +/** @defgroup TIM_Trigger_Prescaler TIM Trigger Prescaler + * @{ + */ +#define TIM_TRIGGERPRESCALER_DIV1 TIM_ETRPRESCALER_DIV1 /*!< No prescaler is used */ +#define TIM_TRIGGERPRESCALER_DIV2 TIM_ETRPRESCALER_DIV2 /*!< Prescaler for External ETR Trigger: Capture performed once every 2 events. */ +#define TIM_TRIGGERPRESCALER_DIV4 TIM_ETRPRESCALER_DIV4 /*!< Prescaler for External ETR Trigger: Capture performed once every 4 events. */ +#define TIM_TRIGGERPRESCALER_DIV8 TIM_ETRPRESCALER_DIV8 /*!< Prescaler for External ETR Trigger: Capture performed once every 8 events. */ +/** + * @} + */ + +/** @defgroup TIM_TI1_Selection TIM TI1 Input Selection + * @{ + */ +#define TIM_TI1SELECTION_CH1 ((uint32_t)0x0000) +#define TIM_TI1SELECTION_XORCOMBINATION (TIM_CR2_TI1S) +/** + * @} + */ + +/** @defgroup TIM_DMA_Burst_Length TIM DMA Burst Length + * @{ + */ +#define TIM_DMABURSTLENGTH_1TRANSFER (0x00000000) +#define TIM_DMABURSTLENGTH_2TRANSFERS (0x00000100) +#define TIM_DMABURSTLENGTH_3TRANSFERS (0x00000200) +#define TIM_DMABURSTLENGTH_4TRANSFERS (0x00000300) +#define TIM_DMABURSTLENGTH_5TRANSFERS (0x00000400) +#define TIM_DMABURSTLENGTH_6TRANSFERS (0x00000500) +#define TIM_DMABURSTLENGTH_7TRANSFERS (0x00000600) +#define TIM_DMABURSTLENGTH_8TRANSFERS (0x00000700) +#define TIM_DMABURSTLENGTH_9TRANSFERS (0x00000800) +#define TIM_DMABURSTLENGTH_10TRANSFERS (0x00000900) +#define TIM_DMABURSTLENGTH_11TRANSFERS (0x00000A00) +#define TIM_DMABURSTLENGTH_12TRANSFERS (0x00000B00) +#define TIM_DMABURSTLENGTH_13TRANSFERS (0x00000C00) +#define TIM_DMABURSTLENGTH_14TRANSFERS (0x00000D00) +#define TIM_DMABURSTLENGTH_15TRANSFERS (0x00000E00) +#define TIM_DMABURSTLENGTH_16TRANSFERS (0x00000F00) +#define TIM_DMABURSTLENGTH_17TRANSFERS (0x00001000) +#define TIM_DMABURSTLENGTH_18TRANSFERS (0x00001100) +/** + * @} + */ + +/** @defgroup DMA_Handle_index TIM DMA Handle Index + * @{ + */ +#define TIM_DMA_ID_UPDATE ((uint16_t) 0x0) /*!< Index of the DMA handle used for Update DMA requests */ +#define TIM_DMA_ID_CC1 ((uint16_t) 0x1) /*!< Index of the DMA handle used for Capture/Compare 1 DMA requests */ +#define TIM_DMA_ID_CC2 ((uint16_t) 0x2) /*!< Index of the DMA handle used for Capture/Compare 2 DMA requests */ +#define TIM_DMA_ID_CC3 ((uint16_t) 0x3) /*!< Index of the DMA handle used for Capture/Compare 3 DMA requests */ +#define TIM_DMA_ID_CC4 ((uint16_t) 0x4) /*!< Index of the DMA handle used for Capture/Compare 4 DMA requests */ +#define TIM_DMA_ID_COMMUTATION ((uint16_t) 0x5) /*!< Index of the DMA handle used for Commutation DMA requests */ +#define TIM_DMA_ID_TRIGGER ((uint16_t) 0x6) /*!< Index of the DMA handle used for Trigger DMA requests */ +/** + * @} + */ + +/** @defgroup Channel_CC_State TIM Capture/Compare Channel State + * @{ + */ +#define TIM_CCx_ENABLE ((uint32_t)0x0001) +#define TIM_CCx_DISABLE ((uint32_t)0x0000) +#define TIM_CCxN_ENABLE ((uint32_t)0x0004) +#define TIM_CCxN_DISABLE ((uint32_t)0x0000) +/** + * @} + */ + +/** @defgroup TIM_Break_System TIM Break System + * @{ + */ +#define TIM_BREAK_SYSTEM_ECC SYSCFG_CFGR2_ECCL /*!< Enables and locks the ECC error signal with Break Input of TIM1/8/15/16/17 */ +#define TIM_BREAK_SYSTEM_PVD SYSCFG_CFGR2_PVDL /*!< Enables and locks the PVD connection with TIM1/8/15/16/17 Break Input and also the PVDE and PLS bits of the Power Control Interface */ +#define TIM_BREAK_SYSTEM_SRAM2_PARITY_ERROR SYSCFG_CFGR2_SPL /*!< Enables and locks the SRAM2_PARITY error signal with Break Input of TIM1/8/15/16/17 */ +#define TIM_BREAK_SYSTEM_LOCKUP SYSCFG_CFGR2_CLL /*!< Enables and locks the LOCKUP output of CortexM4 with Break Input of TIM1/15/16/17 */ +/** + * @} + */ + +/** + * @} + */ +/* End of exported constants -------------------------------------------------*/ + +/* Exported macros -----------------------------------------------------------*/ +/** @defgroup TIM_Exported_Macros TIM Exported Macros + * @{ + */ + +/** @brief Reset TIM handle state. + * @param __HANDLE__ TIM handle. + * @retval None + */ +#define __HAL_TIM_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_TIM_STATE_RESET) + +/** + * @brief Enable the TIM peripheral. + * @param __HANDLE__ TIM handle + * @retval None + */ +#define __HAL_TIM_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR1|=(TIM_CR1_CEN)) + +/** + * @brief Enable the TIM main Output. + * @param __HANDLE__ TIM handle + * @retval None + */ +#define __HAL_TIM_MOE_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->BDTR|=(TIM_BDTR_MOE)) + +/** + * @brief Disable the TIM peripheral. + * @param __HANDLE__ TIM handle + * @retval None + */ +#define __HAL_TIM_DISABLE(__HANDLE__) \ + do { \ + if (((__HANDLE__)->Instance->CCER & TIM_CCER_CCxE_MASK) == 0) \ + { \ + if(((__HANDLE__)->Instance->CCER & TIM_CCER_CCxNE_MASK) == 0) \ + { \ + (__HANDLE__)->Instance->CR1 &= ~(TIM_CR1_CEN); \ + } \ + } \ + } while(0) + +/** + * @brief Disable the TIM main Output. + * @param __HANDLE__ TIM handle + * @retval None + * @note The Main Output Enable of a timer instance is disabled only if all the CCx and CCxN channels have been disabled + */ +#define __HAL_TIM_MOE_DISABLE(__HANDLE__) \ + do { \ + if (((__HANDLE__)->Instance->CCER & TIM_CCER_CCxE_MASK) == 0) \ + { \ + if(((__HANDLE__)->Instance->CCER & TIM_CCER_CCxNE_MASK) == 0) \ + { \ + (__HANDLE__)->Instance->BDTR &= ~(TIM_BDTR_MOE); \ + } \ + } \ + } while(0) + +/** + * @brief Disable the TIM main Output. + * @param __HANDLE__ TIM handle + * @retval None + * @note The Main Output Enable of a timer instance is disabled unconditionally + */ +#define __HAL_TIM_MOE_DISABLE_UNCONDITIONALLY(__HANDLE__) (__HANDLE__)->Instance->BDTR &= ~(TIM_BDTR_MOE) + +/** @brief Enable the specified TIM interrupt. + * @param __HANDLE__ specifies the TIM Handle. + * @param __INTERRUPT__ specifies the TIM interrupt source to enable. + * This parameter can be one of the following values: + * @arg TIM_IT_UPDATE: Update interrupt + * @arg TIM_IT_CC1: Capture/Compare 1 interrupt + * @arg TIM_IT_CC2: Capture/Compare 2 interrupt + * @arg TIM_IT_CC3: Capture/Compare 3 interrupt + * @arg TIM_IT_CC4: Capture/Compare 4 interrupt + * @arg TIM_IT_COM: Commutation interrupt + * @arg TIM_IT_TRIGGER: Trigger interrupt + * @arg TIM_IT_BREAK: Break interrupt + * @retval None + */ +#define __HAL_TIM_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->DIER |= (__INTERRUPT__)) + + +/** @brief Disable the specified TIM interrupt. + * @param __HANDLE__ specifies the TIM Handle. + * @param __INTERRUPT__ specifies the TIM interrupt source to disable. + * This parameter can be one of the following values: + * @arg TIM_IT_UPDATE: Update interrupt + * @arg TIM_IT_CC1: Capture/Compare 1 interrupt + * @arg TIM_IT_CC2: Capture/Compare 2 interrupt + * @arg TIM_IT_CC3: Capture/Compare 3 interrupt + * @arg TIM_IT_CC4: Capture/Compare 4 interrupt + * @arg TIM_IT_COM: Commutation interrupt + * @arg TIM_IT_TRIGGER: Trigger interrupt + * @arg TIM_IT_BREAK: Break interrupt + * @retval None + */ +#define __HAL_TIM_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->DIER &= ~(__INTERRUPT__)) + +/** @brief Enable the specified DMA request. + * @param __HANDLE__ specifies the TIM Handle. + * @param __DMA__ specifies the TIM DMA request to enable. + * This parameter can be one of the following values: + * @arg TIM_DMA_UPDATE: Update DMA request + * @arg TIM_DMA_CC1: Capture/Compare 1 DMA request + * @arg TIM_DMA_CC2: Capture/Compare 2 DMA request + * @arg TIM_DMA_CC3: Capture/Compare 3 DMA request + * @arg TIM_DMA_CC4: Capture/Compare 4 DMA request + * @arg TIM_DMA_COM: Commutation DMA request + * @arg TIM_DMA_TRIGGER: Trigger DMA request + * @retval None + */ +#define __HAL_TIM_ENABLE_DMA(__HANDLE__, __DMA__) ((__HANDLE__)->Instance->DIER |= (__DMA__)) + +/** @brief Disable the specified DMA request. + * @param __HANDLE__ specifies the TIM Handle. + * @param __DMA__ specifies the TIM DMA request to disable. + * This parameter can be one of the following values: + * @arg TIM_DMA_UPDATE: Update DMA request + * @arg TIM_DMA_CC1: Capture/Compare 1 DMA request + * @arg TIM_DMA_CC2: Capture/Compare 2 DMA request + * @arg TIM_DMA_CC3: Capture/Compare 3 DMA request + * @arg TIM_DMA_CC4: Capture/Compare 4 DMA request + * @arg TIM_DMA_COM: Commutation DMA request + * @arg TIM_DMA_TRIGGER: Trigger DMA request + * @retval None + */ +#define __HAL_TIM_DISABLE_DMA(__HANDLE__, __DMA__) ((__HANDLE__)->Instance->DIER &= ~(__DMA__)) + +/** @brief Check whether the specified TIM interrupt flag is set or not. + * @param __HANDLE__ specifies the TIM Handle. + * @param __FLAG__ specifies the TIM interrupt flag to check. + * This parameter can be one of the following values: + * @arg TIM_FLAG_UPDATE: Update interrupt flag + * @arg TIM_FLAG_CC1: Capture/Compare 1 interrupt flag + * @arg TIM_FLAG_CC2: Capture/Compare 2 interrupt flag + * @arg TIM_FLAG_CC3: Capture/Compare 3 interrupt flag + * @arg TIM_FLAG_CC4: Capture/Compare 4 interrupt flag + * @arg TIM_FLAG_CC5: Compare 5 interrupt flag + * @arg TIM_FLAG_CC6: Compare 6 interrupt flag + * @arg TIM_FLAG_COM: Commutation interrupt flag + * @arg TIM_FLAG_TRIGGER: Trigger interrupt flag + * @arg TIM_FLAG_BREAK: Break interrupt flag + * @arg TIM_FLAG_BREAK2: Break 2 interrupt flag + * @arg TIM_FLAG_SYSTEM_BREAK: System Break interrupt flag + * @arg TIM_FLAG_CC1OF: Capture/Compare 1 overcapture flag + * @arg TIM_FLAG_CC2OF: Capture/Compare 2 overcapture flag + * @arg TIM_FLAG_CC3OF: Capture/Compare 3 overcapture flag + * @arg TIM_FLAG_CC4OF: Capture/Compare 4 overcapture flag + * @retval The new state of __FLAG__ (TRUE or FALSE). + */ +#define __HAL_TIM_GET_FLAG(__HANDLE__, __FLAG__) (((__HANDLE__)->Instance->SR &(__FLAG__)) == (__FLAG__)) + +/** @brief Clear the specified TIM interrupt flag. + * @param __HANDLE__ specifies the TIM Handle. + * @param __FLAG__ specifies the TIM interrupt flag to clear. + * This parameter can be one of the following values: + * @arg TIM_FLAG_UPDATE: Update interrupt flag + * @arg TIM_FLAG_CC1: Capture/Compare 1 interrupt flag + * @arg TIM_FLAG_CC2: Capture/Compare 2 interrupt flag + * @arg TIM_FLAG_CC3: Capture/Compare 3 interrupt flag + * @arg TIM_FLAG_CC4: Capture/Compare 4 interrupt flag + * @arg TIM_FLAG_CC5: Compare 5 interrupt flag + * @arg TIM_FLAG_CC6: Compare 6 interrupt flag + * @arg TIM_FLAG_COM: Commutation interrupt flag + * @arg TIM_FLAG_TRIGGER: Trigger interrupt flag + * @arg TIM_FLAG_BREAK: Break interrupt flag + * @arg TIM_FLAG_BREAK2: Break 2 interrupt flag + * @arg TIM_FLAG_SYSTEM_BREAK: System Break interrupt flag + * @arg TIM_FLAG_CC1OF: Capture/Compare 1 overcapture flag + * @arg TIM_FLAG_CC2OF: Capture/Compare 2 overcapture flag + * @arg TIM_FLAG_CC3OF: Capture/Compare 3 overcapture flag + * @arg TIM_FLAG_CC4OF: Capture/Compare 4 overcapture flag + * @retval The new state of __FLAG__ (TRUE or FALSE). + */ +#define __HAL_TIM_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->SR = ~(__FLAG__)) + +/** + * @brief Check whether the specified TIM interrupt source is enabled or not. + * @param __HANDLE__ TIM handle + * @param __INTERRUPT__ specifies the TIM interrupt source to check. + * This parameter can be one of the following values: + * @arg TIM_IT_UPDATE: Update interrupt + * @arg TIM_IT_CC1: Capture/Compare 1 interrupt + * @arg TIM_IT_CC2: Capture/Compare 2 interrupt + * @arg TIM_IT_CC3: Capture/Compare 3 interrupt + * @arg TIM_IT_CC4: Capture/Compare 4 interrupt + * @arg TIM_IT_COM: Commutation interrupt + * @arg TIM_IT_TRIGGER: Trigger interrupt + * @arg TIM_IT_BREAK: Break interrupt + * @retval The state of TIM_IT (SET or RESET). + */ +#define __HAL_TIM_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) ((((__HANDLE__)->Instance->DIER & (__INTERRUPT__)) == (__INTERRUPT__)) ? SET : RESET) + +/** @brief Clear the TIM interrupt pending bits. + * @param __HANDLE__ TIM handle + * @param __INTERRUPT__ specifies the interrupt pending bit to clear. + * This parameter can be one of the following values: + * @arg TIM_IT_UPDATE: Update interrupt + * @arg TIM_IT_CC1: Capture/Compare 1 interrupt + * @arg TIM_IT_CC2: Capture/Compare 2 interrupt + * @arg TIM_IT_CC3: Capture/Compare 3 interrupt + * @arg TIM_IT_CC4: Capture/Compare 4 interrupt + * @arg TIM_IT_COM: Commutation interrupt + * @arg TIM_IT_TRIGGER: Trigger interrupt + * @arg TIM_IT_BREAK: Break interrupt + * @retval None + */ +#define __HAL_TIM_CLEAR_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->SR = ~(__INTERRUPT__)) + +/** + * @brief Indicates whether or not the TIM Counter is used as downcounter. + * @param __HANDLE__ TIM handle. + * @retval False (Counter used as upcounter) or True (Counter used as downcounter) + * @note This macro is particularly useful to get the counting mode when the timer operates in Center-aligned mode or Encoder +mode. + */ +#define __HAL_TIM_IS_TIM_COUNTING_DOWN(__HANDLE__) (((__HANDLE__)->Instance->CR1 &(TIM_CR1_DIR)) == (TIM_CR1_DIR)) + + +/** + * @brief Set the TIM Prescaler on runtime. + * @param __HANDLE__ TIM handle. + * @param __PRESC__ specifies the Prescaler new value. + * @retval None + */ +#define __HAL_TIM_SET_PRESCALER(__HANDLE__, __PRESC__) ((__HANDLE__)->Instance->PSC = (__PRESC__)) + +/** + * @brief Set the TIM Counter Register value on runtime. + * @param __HANDLE__ TIM handle. + * @param __COUNTER__ specifies the Counter register new value. + * @retval None + */ +#define __HAL_TIM_SET_COUNTER(__HANDLE__, __COUNTER__) ((__HANDLE__)->Instance->CNT = (__COUNTER__)) + +/** + * @brief Get the TIM Counter Register value on runtime. + * @param __HANDLE__ TIM handle. + * @retval 16-bit or 32-bit value of the timer counter register (TIMx_CNT) + */ +#define __HAL_TIM_GET_COUNTER(__HANDLE__) \ + ((__HANDLE__)->Instance->CNT) + +/** + * @brief Set the TIM Autoreload Register value on runtime without calling another time any Init function. + * @param __HANDLE__ TIM handle. + * @param __AUTORELOAD__ specifies the Counter register new value. + * @retval None + */ +#define __HAL_TIM_SET_AUTORELOAD(__HANDLE__, __AUTORELOAD__) \ + do{ \ + (__HANDLE__)->Instance->ARR = (__AUTORELOAD__); \ + (__HANDLE__)->Init.Period = (__AUTORELOAD__); \ + } while(0) + +/** + * @brief Get the TIM Autoreload Register value on runtime. + * @param __HANDLE__ TIM handle. + * @retval 16-bit or 32-bit value of the timer auto-reload register(TIMx_ARR) + */ +#define __HAL_TIM_GET_AUTORELOAD(__HANDLE__) \ + ((__HANDLE__)->Instance->ARR) + +/** + * @brief Set the TIM Clock Division value on runtime without calling another time any Init function. + * @param __HANDLE__ TIM handle. + * @param __CKD__ specifies the clock division value. + * This parameter can be one of the following value: + * @arg TIM_CLOCKDIVISION_DIV1: tDTS=tCK_INT + * @arg TIM_CLOCKDIVISION_DIV2: tDTS=2*tCK_INT + * @arg TIM_CLOCKDIVISION_DIV4: tDTS=4*tCK_INT + * @retval None + */ +#define __HAL_TIM_SET_CLOCKDIVISION(__HANDLE__, __CKD__) \ + do{ \ + (__HANDLE__)->Instance->CR1 &= (uint16_t)(~TIM_CR1_CKD); \ + (__HANDLE__)->Instance->CR1 |= (__CKD__); \ + (__HANDLE__)->Init.ClockDivision = (__CKD__); \ + } while(0) + +/** + * @brief Get the TIM Clock Division value on runtime. + * @param __HANDLE__ TIM handle. + * @retval The clock division can be one of the following values: + * @arg TIM_CLOCKDIVISION_DIV1: tDTS=tCK_INT + * @arg TIM_CLOCKDIVISION_DIV2: tDTS=2*tCK_INT + * @arg TIM_CLOCKDIVISION_DIV4: tDTS=4*tCK_INT + */ +#define __HAL_TIM_GET_CLOCKDIVISION(__HANDLE__) \ + ((__HANDLE__)->Instance->CR1 & TIM_CR1_CKD) + +/** + * @brief Set the TIM Input Capture prescaler on runtime without calling another time HAL_TIM_IC_ConfigChannel() function. + * @param __HANDLE__ TIM handle. + * @param __CHANNEL__ TIM Channels to be configured. + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @param __ICPSC__ specifies the Input Capture4 prescaler new value. + * This parameter can be one of the following values: + * @arg TIM_ICPSC_DIV1: no prescaler + * @arg TIM_ICPSC_DIV2: capture is done once every 2 events + * @arg TIM_ICPSC_DIV4: capture is done once every 4 events + * @arg TIM_ICPSC_DIV8: capture is done once every 8 events + * @retval None + */ +#define __HAL_TIM_SET_ICPRESCALER(__HANDLE__, __CHANNEL__, __ICPSC__) \ + do{ \ + TIM_RESET_ICPRESCALERVALUE((__HANDLE__), (__CHANNEL__)); \ + TIM_SET_ICPRESCALERVALUE((__HANDLE__), (__CHANNEL__), (__ICPSC__)); \ + } while(0) + +/** + * @brief Get the TIM Input Capture prescaler on runtime. + * @param __HANDLE__ TIM handle. + * @param __CHANNEL__ TIM Channels to be configured. + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: get input capture 1 prescaler value + * @arg TIM_CHANNEL_2: get input capture 2 prescaler value + * @arg TIM_CHANNEL_3: get input capture 3 prescaler value + * @arg TIM_CHANNEL_4: get input capture 4 prescaler value + * @retval The input capture prescaler can be one of the following values: + * @arg TIM_ICPSC_DIV1: no prescaler + * @arg TIM_ICPSC_DIV2: capture is done once every 2 events + * @arg TIM_ICPSC_DIV4: capture is done once every 4 events + * @arg TIM_ICPSC_DIV8: capture is done once every 8 events + */ +#define __HAL_TIM_GET_ICPRESCALER(__HANDLE__, __CHANNEL__) \ + (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCMR1 & TIM_CCMR1_IC1PSC) :\ + ((__CHANNEL__) == TIM_CHANNEL_2) ? (((__HANDLE__)->Instance->CCMR1 & TIM_CCMR1_IC2PSC) >> 8) :\ + ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCMR2 & TIM_CCMR2_IC3PSC) :\ + (((__HANDLE__)->Instance->CCMR2 & TIM_CCMR2_IC4PSC)) >> 8) + +/** + * @brief Set the TIM Capture Compare Register value on runtime without calling another time ConfigChannel function. + * @param __HANDLE__ TIM handle. + * @param __CHANNEL__ TIM Channels to be configured. + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @arg TIM_CHANNEL_5: TIM Channel 5 selected + * @arg TIM_CHANNEL_6: TIM Channel 6 selected + * @param __COMPARE__ specifies the Capture Compare register new value. + * @retval None + */ +#define __HAL_TIM_SET_COMPARE(__HANDLE__, __CHANNEL__, __COMPARE__) \ +(((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCR1 = (__COMPARE__)) :\ + ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCR2 = (__COMPARE__)) :\ + ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCR3 = (__COMPARE__)) :\ + ((__CHANNEL__) == TIM_CHANNEL_4) ? ((__HANDLE__)->Instance->CCR4 = (__COMPARE__)) :\ + ((__CHANNEL__) == TIM_CHANNEL_5) ? ((__HANDLE__)->Instance->CCR5 = (__COMPARE__)) :\ + ((__HANDLE__)->Instance->CCR6 = (__COMPARE__))) + +/** + * @brief Get the TIM Capture Compare Register value on runtime. + * @param __HANDLE__ TIM handle. + * @param __CHANNEL__ TIM Channel associated with the capture compare register + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: get capture/compare 1 register value + * @arg TIM_CHANNEL_2: get capture/compare 2 register value + * @arg TIM_CHANNEL_3: get capture/compare 3 register value + * @arg TIM_CHANNEL_4: get capture/compare 4 register value + * @arg TIM_CHANNEL_5: get capture/compare 5 register value + * @arg TIM_CHANNEL_6: get capture/compare 6 register value + * @retval 16-bit or 32-bit value of the capture/compare register (TIMx_CCRy) + */ +#define __HAL_TIM_GET_COMPARE(__HANDLE__, __CHANNEL__) \ +(((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCR1) :\ + ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCR2) :\ + ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCR3) :\ + ((__CHANNEL__) == TIM_CHANNEL_4) ? ((__HANDLE__)->Instance->CCR4) :\ + ((__CHANNEL__) == TIM_CHANNEL_5) ? ((__HANDLE__)->Instance->CCR5) :\ + ((__HANDLE__)->Instance->CCR6)) + +/** + * @brief Set the TIM Output compare preload. + * @param __HANDLE__ TIM handle. + * @param __CHANNEL__ TIM Channels to be configured. + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @arg TIM_CHANNEL_5: TIM Channel 5 selected + * @arg TIM_CHANNEL_6: TIM Channel 6 selected + * @retval None + */ +#define __HAL_TIM_ENABLE_OCxPRELOAD(__HANDLE__, __CHANNEL__) \ + (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCMR1 |= TIM_CCMR1_OC1PE) :\ + ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCMR1 |= TIM_CCMR1_OC2PE) :\ + ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCMR2 |= TIM_CCMR2_OC3PE) :\ + ((__CHANNEL__) == TIM_CHANNEL_4) ? ((__HANDLE__)->Instance->CCMR2 |= TIM_CCMR2_OC4PE) :\ + ((__CHANNEL__) == TIM_CHANNEL_5) ? ((__HANDLE__)->Instance->CCMR3 |= TIM_CCMR3_OC5PE) :\ + ((__HANDLE__)->Instance->CCMR3 |= TIM_CCMR3_OC6PE)) + +/** + * @brief Reset the TIM Output compare preload. + * @param __HANDLE__ TIM handle. + * @param __CHANNEL__ TIM Channels to be configured. + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @arg TIM_CHANNEL_5: TIM Channel 5 selected + * @arg TIM_CHANNEL_6: TIM Channel 6 selected + * @retval None + */ +#define __HAL_TIM_DISABLE_OCxPRELOAD(__HANDLE__, __CHANNEL__) \ + (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCMR1 &= (uint16_t)~TIM_CCMR1_OC1PE) :\ + ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCMR1 &= (uint16_t)~TIM_CCMR1_OC2PE) :\ + ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCMR2 &= (uint16_t)~TIM_CCMR2_OC3PE) :\ + ((__CHANNEL__) == TIM_CHANNEL_4) ? ((__HANDLE__)->Instance->CCMR2 &= (uint16_t)~TIM_CCMR2_OC4PE) :\ + ((__CHANNEL__) == TIM_CHANNEL_5) ? ((__HANDLE__)->Instance->CCMR3 &= (uint16_t)~TIM_CCMR3_OC5PE) :\ + ((__HANDLE__)->Instance->CCMR3 &= (uint16_t)~TIM_CCMR3_OC6PE)) + +/** + * @brief Set the Update Request Source (URS) bit of the TIMx_CR1 register. + * @param __HANDLE__ TIM handle. + * @note When the USR bit of the TIMx_CR1 register is set, only counter + * overflow/underflow generates an update interrupt or DMA request (if + * enabled) + * @retval None + */ +#define __HAL_TIM_URS_ENABLE(__HANDLE__) \ + ((__HANDLE__)->Instance->CR1|= (TIM_CR1_URS)) + +/** + * @brief Reset the Update Request Source (URS) bit of the TIMx_CR1 register. + * @param __HANDLE__ TIM handle. + * @note When the USR bit of the TIMx_CR1 register is reset, any of the + * following events generate an update interrupt or DMA request (if + * enabled): + * _ Counter overflow underflow + * _ Setting the UG bit + * _ Update generation through the slave mode controller + * @retval None + */ +#define __HAL_TIM_URS_DISABLE(__HANDLE__) \ + ((__HANDLE__)->Instance->CR1&=~(TIM_CR1_URS)) + +/** + * @brief Set the TIM Capture x input polarity on runtime. + * @param __HANDLE__ TIM handle. + * @param __CHANNEL__ TIM Channels to be configured. + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @param __POLARITY__ Polarity for TIx source + * @arg TIM_INPUTCHANNELPOLARITY_RISING: Rising Edge + * @arg TIM_INPUTCHANNELPOLARITY_FALLING: Falling Edge + * @arg TIM_INPUTCHANNELPOLARITY_BOTHEDGE: Rising and Falling Edge + * @retval None + */ +#define __HAL_TIM_SET_CAPTUREPOLARITY(__HANDLE__, __CHANNEL__, __POLARITY__) \ + do{ \ + TIM_RESET_CAPTUREPOLARITY((__HANDLE__), (__CHANNEL__)); \ + TIM_SET_CAPTUREPOLARITY((__HANDLE__), (__CHANNEL__), (__POLARITY__)); \ + }while(0) + +/** + * @} + */ +/* End of exported macros ----------------------------------------------------*/ + +/* Private constants ---------------------------------------------------------*/ +/** @defgroup TIM_Private_Constants TIM Private Constants + * @{ + */ +/* The counter of a timer instance is disabled only if all the CCx and CCxN + channels have been disabled */ +#define TIM_CCER_CCxE_MASK ((uint32_t)(TIM_CCER_CC1E | TIM_CCER_CC2E | TIM_CCER_CC3E | TIM_CCER_CC4E)) +#define TIM_CCER_CCxNE_MASK ((uint32_t)(TIM_CCER_CC1NE | TIM_CCER_CC2NE | TIM_CCER_CC3NE)) +/** + * @} + */ +/* End of private constants --------------------------------------------------*/ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup TIM_Private_Macros TIM Private Macros + * @{ + */ + +#define IS_TIM_CLEARINPUT_SOURCE(__MODE__) (((__MODE__) == TIM_CLEARINPUTSOURCE_ETR) || \ + ((__MODE__) == TIM_CLEARINPUTSOURCE_OCREFCLR) || \ + ((__MODE__) == TIM_CLEARINPUTSOURCE_NONE)) + +#define IS_TIM_DMA_BASE(__BASE__) (((__BASE__) == TIM_DMABASE_CR1) || \ + ((__BASE__) == TIM_DMABASE_CR2) || \ + ((__BASE__) == TIM_DMABASE_SMCR) || \ + ((__BASE__) == TIM_DMABASE_DIER) || \ + ((__BASE__) == TIM_DMABASE_SR) || \ + ((__BASE__) == TIM_DMABASE_EGR) || \ + ((__BASE__) == TIM_DMABASE_CCMR1) || \ + ((__BASE__) == TIM_DMABASE_CCMR2) || \ + ((__BASE__) == TIM_DMABASE_CCER) || \ + ((__BASE__) == TIM_DMABASE_CNT) || \ + ((__BASE__) == TIM_DMABASE_PSC) || \ + ((__BASE__) == TIM_DMABASE_ARR) || \ + ((__BASE__) == TIM_DMABASE_RCR) || \ + ((__BASE__) == TIM_DMABASE_CCR1) || \ + ((__BASE__) == TIM_DMABASE_CCR2) || \ + ((__BASE__) == TIM_DMABASE_CCR3) || \ + ((__BASE__) == TIM_DMABASE_CCR4) || \ + ((__BASE__) == TIM_DMABASE_BDTR) || \ + ((__BASE__) == TIM_DMABASE_CCMR3) || \ + ((__BASE__) == TIM_DMABASE_CCR5) || \ + ((__BASE__) == TIM_DMABASE_CCR6) || \ + ((__BASE__) == TIM_DMABASE_OR1) || \ + ((__BASE__) == TIM_DMABASE_OR2) || \ + ((__BASE__) == TIM_DMABASE_OR3)) + + +#define IS_TIM_EVENT_SOURCE(__SOURCE__) ((((__SOURCE__) & 0xFFFFFE00U) == 0x00000000U) && ((__SOURCE__) != 0x00000000U)) + + +#define IS_TIM_COUNTER_MODE(__MODE__) (((__MODE__) == TIM_COUNTERMODE_UP) || \ + ((__MODE__) == TIM_COUNTERMODE_DOWN) || \ + ((__MODE__) == TIM_COUNTERMODE_CENTERALIGNED1) || \ + ((__MODE__) == TIM_COUNTERMODE_CENTERALIGNED2) || \ + ((__MODE__) == TIM_COUNTERMODE_CENTERALIGNED3)) + +#define IS_TIM_CLOCKDIVISION_DIV(__DIV__) (((__DIV__) == TIM_CLOCKDIVISION_DIV1) || \ + ((__DIV__) == TIM_CLOCKDIVISION_DIV2) || \ + ((__DIV__) == TIM_CLOCKDIVISION_DIV4)) + +#define IS_TIM_AUTORELOAD_PRELOAD(PRELOAD) (((PRELOAD) == TIM_AUTORELOAD_PRELOAD_DISABLE) || \ + ((PRELOAD) == TIM_AUTORELOAD_PRELOAD_ENABLE)) + +#define IS_TIM_FAST_STATE(__STATE__) (((__STATE__) == TIM_OCFAST_DISABLE) || \ + ((__STATE__) == TIM_OCFAST_ENABLE)) + +#define IS_TIM_OC_POLARITY(__POLARITY__) (((__POLARITY__) == TIM_OCPOLARITY_HIGH) || \ + ((__POLARITY__) == TIM_OCPOLARITY_LOW)) + +#define IS_TIM_OCN_POLARITY(__POLARITY__) (((__POLARITY__) == TIM_OCNPOLARITY_HIGH) || \ + ((__POLARITY__) == TIM_OCNPOLARITY_LOW)) + +#define IS_TIM_OCIDLE_STATE(__STATE__) (((__STATE__) == TIM_OCIDLESTATE_SET) || \ + ((__STATE__) == TIM_OCIDLESTATE_RESET)) + +#define IS_TIM_OCNIDLE_STATE(__STATE__) (((__STATE__) == TIM_OCNIDLESTATE_SET) || \ + ((__STATE__) == TIM_OCNIDLESTATE_RESET)) + +#define IS_TIM_IC_POLARITY(__POLARITY__) (((__POLARITY__) == TIM_ICPOLARITY_RISING) || \ + ((__POLARITY__) == TIM_ICPOLARITY_FALLING) || \ + ((__POLARITY__) == TIM_ICPOLARITY_BOTHEDGE)) + +#define IS_TIM_IC_SELECTION(__SELECTION__) (((__SELECTION__) == TIM_ICSELECTION_DIRECTTI) || \ + ((__SELECTION__) == TIM_ICSELECTION_INDIRECTTI) || \ + ((__SELECTION__) == TIM_ICSELECTION_TRC)) + +#define IS_TIM_IC_PRESCALER(__PRESCALER__) (((__PRESCALER__) == TIM_ICPSC_DIV1) || \ + ((__PRESCALER__) == TIM_ICPSC_DIV2) || \ + ((__PRESCALER__) == TIM_ICPSC_DIV4) || \ + ((__PRESCALER__) == TIM_ICPSC_DIV8)) + +#define IS_TIM_OPM_MODE(__MODE__) (((__MODE__) == TIM_OPMODE_SINGLE) || \ + ((__MODE__) == TIM_OPMODE_REPETITIVE)) + +#define IS_TIM_ENCODER_MODE(__MODE__) (((__MODE__) == TIM_ENCODERMODE_TI1) || \ + ((__MODE__) == TIM_ENCODERMODE_TI2) || \ + ((__MODE__) == TIM_ENCODERMODE_TI12)) + +#define IS_TIM_DMA_SOURCE(__SOURCE__) ((((__SOURCE__) & 0xFFFF80FFU) == 0x00000000U) && ((__SOURCE__) != 0x00000000U)) + +#define IS_TIM_CHANNELS(__CHANNEL__) (((__CHANNEL__) == TIM_CHANNEL_1) || \ + ((__CHANNEL__) == TIM_CHANNEL_2) || \ + ((__CHANNEL__) == TIM_CHANNEL_3) || \ + ((__CHANNEL__) == TIM_CHANNEL_4) || \ + ((__CHANNEL__) == TIM_CHANNEL_5) || \ + ((__CHANNEL__) == TIM_CHANNEL_6) || \ + ((__CHANNEL__) == TIM_CHANNEL_ALL)) + +#define IS_TIM_OPM_CHANNELS(__CHANNEL__) (((__CHANNEL__) == TIM_CHANNEL_1) || \ + ((__CHANNEL__) == TIM_CHANNEL_2)) + +#define IS_TIM_COMPLEMENTARY_CHANNELS(__CHANNEL__) (((__CHANNEL__) == TIM_CHANNEL_1) || \ + ((__CHANNEL__) == TIM_CHANNEL_2) || \ + ((__CHANNEL__) == TIM_CHANNEL_3)) + +#define IS_TIM_CLOCKSOURCE(__CLOCK__) (((__CLOCK__) == TIM_CLOCKSOURCE_INTERNAL) || \ + ((__CLOCK__) == TIM_CLOCKSOURCE_ETRMODE2) || \ + ((__CLOCK__) == TIM_CLOCKSOURCE_ITR0) || \ + ((__CLOCK__) == TIM_CLOCKSOURCE_ITR1) || \ + ((__CLOCK__) == TIM_CLOCKSOURCE_ITR2) || \ + ((__CLOCK__) == TIM_CLOCKSOURCE_ITR3) || \ + ((__CLOCK__) == TIM_CLOCKSOURCE_TI1ED) || \ + ((__CLOCK__) == TIM_CLOCKSOURCE_TI1) || \ + ((__CLOCK__) == TIM_CLOCKSOURCE_TI2) || \ + ((__CLOCK__) == TIM_CLOCKSOURCE_ETRMODE1)) + +#define IS_TIM_CLOCKPOLARITY(__POLARITY__) (((__POLARITY__) == TIM_CLOCKPOLARITY_INVERTED) || \ + ((__POLARITY__) == TIM_CLOCKPOLARITY_NONINVERTED) || \ + ((__POLARITY__) == TIM_CLOCKPOLARITY_RISING) || \ + ((__POLARITY__) == TIM_CLOCKPOLARITY_FALLING) || \ + ((__POLARITY__) == TIM_CLOCKPOLARITY_BOTHEDGE)) + +#define IS_TIM_CLOCKPRESCALER(__PRESCALER__) (((__PRESCALER__) == TIM_CLOCKPRESCALER_DIV1) || \ + ((__PRESCALER__) == TIM_CLOCKPRESCALER_DIV2) || \ + ((__PRESCALER__) == TIM_CLOCKPRESCALER_DIV4) || \ + ((__PRESCALER__) == TIM_CLOCKPRESCALER_DIV8)) + +#define IS_TIM_CLOCKFILTER(ICFILTER) ((ICFILTER) <= 0xF) + +#define IS_TIM_CLEARINPUT_POLARITY(__POLARITY__) (((__POLARITY__) == TIM_CLEARINPUTPOLARITY_INVERTED) || \ + ((__POLARITY__) == TIM_CLEARINPUTPOLARITY_NONINVERTED)) + +#define IS_TIM_CLEARINPUT_PRESCALER(__PRESCALER__) (((__PRESCALER__) == TIM_CLEARINPUTPRESCALER_DIV1) || \ + ((__PRESCALER__) == TIM_CLEARINPUTPRESCALER_DIV2) || \ + ((__PRESCALER__) == TIM_CLEARINPUTPRESCALER_DIV4) || \ + ((__PRESCALER__) == TIM_CLEARINPUTPRESCALER_DIV8)) + +#define IS_TIM_CLEARINPUT_FILTER(__ICFILTER__) ((__ICFILTER__) <= 0xF) + + +#define IS_TIM_OSSR_STATE(__STATE__) (((__STATE__) == TIM_OSSR_ENABLE) || \ + ((__STATE__) == TIM_OSSR_DISABLE)) + +#define IS_TIM_OSSI_STATE(__STATE__) (((__STATE__) == TIM_OSSI_ENABLE) || \ + ((__STATE__) == TIM_OSSI_DISABLE)) + +#define IS_TIM_LOCK_LEVEL(__LEVEL__) (((__LEVEL__) == TIM_LOCKLEVEL_OFF) || \ + ((__LEVEL__) == TIM_LOCKLEVEL_1) || \ + ((__LEVEL__) == TIM_LOCKLEVEL_2) || \ + ((__LEVEL__) == TIM_LOCKLEVEL_3)) + +#define IS_TIM_BREAK_FILTER(__BRKFILTER__) ((__BRKFILTER__) <= 0xF) + + +#define IS_TIM_BREAK_STATE(__STATE__) (((__STATE__) == TIM_BREAK_ENABLE) || \ + ((__STATE__) == TIM_BREAK_DISABLE)) + +#define IS_TIM_BREAK_POLARITY(__POLARITY__) (((__POLARITY__) == TIM_BREAKPOLARITY_LOW) || \ + ((__POLARITY__) == TIM_BREAKPOLARITY_HIGH)) + +#define IS_TIM_BREAK2_STATE(__STATE__) (((__STATE__) == TIM_BREAK2_ENABLE) || \ + ((__STATE__) == TIM_BREAK2_DISABLE)) + +#define IS_TIM_BREAK2_POLARITY(__POLARITY__) (((__POLARITY__) == TIM_BREAK2POLARITY_LOW) || \ + ((__POLARITY__) == TIM_BREAK2POLARITY_HIGH)) + +#define IS_TIM_AUTOMATIC_OUTPUT_STATE(__STATE__) (((__STATE__) == TIM_AUTOMATICOUTPUT_ENABLE) || \ + ((__STATE__) == TIM_AUTOMATICOUTPUT_DISABLE)) + +#define IS_TIM_GROUPCH5(__OCREF__) ((((__OCREF__) & 0x1FFFFFFF) == 0x00000000)) + +#define IS_TIM_TRGO_SOURCE(__SOURCE__) (((__SOURCE__) == TIM_TRGO_RESET) || \ + ((__SOURCE__) == TIM_TRGO_ENABLE) || \ + ((__SOURCE__) == TIM_TRGO_UPDATE) || \ + ((__SOURCE__) == TIM_TRGO_OC1) || \ + ((__SOURCE__) == TIM_TRGO_OC1REF) || \ + ((__SOURCE__) == TIM_TRGO_OC2REF) || \ + ((__SOURCE__) == TIM_TRGO_OC3REF) || \ + ((__SOURCE__) == TIM_TRGO_OC4REF)) + +#define IS_TIM_TRGO2_SOURCE(__SOURCE__) (((__SOURCE__) == TIM_TRGO2_RESET) || \ + ((__SOURCE__) == TIM_TRGO2_ENABLE) || \ + ((__SOURCE__) == TIM_TRGO2_UPDATE) || \ + ((__SOURCE__) == TIM_TRGO2_OC1) || \ + ((__SOURCE__) == TIM_TRGO2_OC1REF) || \ + ((__SOURCE__) == TIM_TRGO2_OC2REF) || \ + ((__SOURCE__) == TIM_TRGO2_OC3REF) || \ + ((__SOURCE__) == TIM_TRGO2_OC3REF) || \ + ((__SOURCE__) == TIM_TRGO2_OC4REF) || \ + ((__SOURCE__) == TIM_TRGO2_OC5REF) || \ + ((__SOURCE__) == TIM_TRGO2_OC6REF) || \ + ((__SOURCE__) == TIM_TRGO2_OC4REF_RISINGFALLING) || \ + ((__SOURCE__) == TIM_TRGO2_OC6REF_RISINGFALLING) || \ + ((__SOURCE__) == TIM_TRGO2_OC4REF_RISING_OC6REF_RISING) || \ + ((__SOURCE__) == TIM_TRGO2_OC4REF_RISING_OC6REF_FALLING) || \ + ((__SOURCE__) == TIM_TRGO2_OC5REF_RISING_OC6REF_RISING) || \ + ((__SOURCE__) == TIM_TRGO2_OC5REF_RISING_OC6REF_FALLING)) + +#define IS_TIM_MSM_STATE(__STATE__) (((__STATE__) == TIM_MASTERSLAVEMODE_ENABLE) || \ + ((__STATE__) == TIM_MASTERSLAVEMODE_DISABLE)) + +#define IS_TIM_SLAVE_MODE(__MODE__) (((__MODE__) == TIM_SLAVEMODE_DISABLE) || \ + ((__MODE__) == TIM_SLAVEMODE_RESET) || \ + ((__MODE__) == TIM_SLAVEMODE_GATED) || \ + ((__MODE__) == TIM_SLAVEMODE_TRIGGER) || \ + ((__MODE__) == TIM_SLAVEMODE_EXTERNAL1) || \ + ((__MODE__) == TIM_SLAVEMODE_COMBINED_RESETTRIGGER)) + +#define IS_TIM_PWM_MODE(__MODE__) (((__MODE__) == TIM_OCMODE_PWM1) || \ + ((__MODE__) == TIM_OCMODE_PWM2) || \ + ((__MODE__) == TIM_OCMODE_COMBINED_PWM1) || \ + ((__MODE__) == TIM_OCMODE_COMBINED_PWM2) || \ + ((__MODE__) == TIM_OCMODE_ASSYMETRIC_PWM1) || \ + ((__MODE__) == TIM_OCMODE_ASSYMETRIC_PWM2)) + +#define IS_TIM_OC_MODE(__MODE__) (((__MODE__) == TIM_OCMODE_TIMING) || \ + ((__MODE__) == TIM_OCMODE_ACTIVE) || \ + ((__MODE__) == TIM_OCMODE_INACTIVE) || \ + ((__MODE__) == TIM_OCMODE_TOGGLE) || \ + ((__MODE__) == TIM_OCMODE_FORCED_ACTIVE) || \ + ((__MODE__) == TIM_OCMODE_FORCED_INACTIVE) || \ + ((__MODE__) == TIM_OCMODE_RETRIGERRABLE_OPM1) || \ + ((__MODE__) == TIM_OCMODE_RETRIGERRABLE_OPM2)) + +#define IS_TIM_TRIGGER_SELECTION(__SELECTION__) (((__SELECTION__) == TIM_TS_ITR0) || \ + ((__SELECTION__) == TIM_TS_ITR1) || \ + ((__SELECTION__) == TIM_TS_ITR2) || \ + ((__SELECTION__) == TIM_TS_ITR3) || \ + ((__SELECTION__) == TIM_TS_TI1F_ED) || \ + ((__SELECTION__) == TIM_TS_TI1FP1) || \ + ((__SELECTION__) == TIM_TS_TI2FP2) || \ + ((__SELECTION__) == TIM_TS_ETRF)) + +#define IS_TIM_INTERNAL_TRIGGEREVENT_SELECTION(__SELECTION__) (((__SELECTION__) == TIM_TS_ITR0) || \ + ((__SELECTION__) == TIM_TS_ITR1) || \ + ((__SELECTION__) == TIM_TS_ITR2) || \ + ((__SELECTION__) == TIM_TS_ITR3) || \ + ((__SELECTION__) == TIM_TS_NONE)) + + +#define IS_TIM_TRIGGERPOLARITY(__POLARITY__) (((__POLARITY__) == TIM_TRIGGERPOLARITY_INVERTED ) || \ + ((__POLARITY__) == TIM_TRIGGERPOLARITY_NONINVERTED) || \ + ((__POLARITY__) == TIM_TRIGGERPOLARITY_RISING ) || \ + ((__POLARITY__) == TIM_TRIGGERPOLARITY_FALLING ) || \ + ((__POLARITY__) == TIM_TRIGGERPOLARITY_BOTHEDGE )) + +#define IS_TIM_TRIGGERPRESCALER(__PRESCALER__) (((__PRESCALER__) == TIM_TRIGGERPRESCALER_DIV1) || \ + ((__PRESCALER__) == TIM_TRIGGERPRESCALER_DIV2) || \ + ((__PRESCALER__) == TIM_TRIGGERPRESCALER_DIV4) || \ + ((__PRESCALER__) == TIM_TRIGGERPRESCALER_DIV8)) + +#define IS_TIM_TRIGGERFILTER(__ICFILTER__) ((__ICFILTER__) <= 0xF) + +#define IS_TIM_TI1SELECTION(__TI1SELECTION__) (((__TI1SELECTION__) == TIM_TI1SELECTION_CH1) || \ + ((__TI1SELECTION__) == TIM_TI1SELECTION_XORCOMBINATION)) + +#define IS_TIM_DMA_LENGTH(__LENGTH__) (((__LENGTH__) == TIM_DMABURSTLENGTH_1TRANSFER) || \ + ((__LENGTH__) == TIM_DMABURSTLENGTH_2TRANSFERS) || \ + ((__LENGTH__) == TIM_DMABURSTLENGTH_3TRANSFERS) || \ + ((__LENGTH__) == TIM_DMABURSTLENGTH_4TRANSFERS) || \ + ((__LENGTH__) == TIM_DMABURSTLENGTH_5TRANSFERS) || \ + ((__LENGTH__) == TIM_DMABURSTLENGTH_6TRANSFERS) || \ + ((__LENGTH__) == TIM_DMABURSTLENGTH_7TRANSFERS) || \ + ((__LENGTH__) == TIM_DMABURSTLENGTH_8TRANSFERS) || \ + ((__LENGTH__) == TIM_DMABURSTLENGTH_9TRANSFERS) || \ + ((__LENGTH__) == TIM_DMABURSTLENGTH_10TRANSFERS) || \ + ((__LENGTH__) == TIM_DMABURSTLENGTH_11TRANSFERS) || \ + ((__LENGTH__) == TIM_DMABURSTLENGTH_12TRANSFERS) || \ + ((__LENGTH__) == TIM_DMABURSTLENGTH_13TRANSFERS) || \ + ((__LENGTH__) == TIM_DMABURSTLENGTH_14TRANSFERS) || \ + ((__LENGTH__) == TIM_DMABURSTLENGTH_15TRANSFERS) || \ + ((__LENGTH__) == TIM_DMABURSTLENGTH_16TRANSFERS) || \ + ((__LENGTH__) == TIM_DMABURSTLENGTH_17TRANSFERS) || \ + ((__LENGTH__) == TIM_DMABURSTLENGTH_18TRANSFERS)) + +#define IS_TIM_IC_FILTER(__ICFILTER__) ((__ICFILTER__) <= 0xF) + +#define IS_TIM_DEADTIME(__DEADTIME__) ((__DEADTIME__) <= 0xFF) + +#define IS_TIM_BREAK_SYSTEM(__CONFIG__) (((__CONFIG__) == TIM_BREAK_SYSTEM_ECC) || \ + ((__CONFIG__) == TIM_BREAK_SYSTEM_PVD) || \ + ((__CONFIG__) == TIM_BREAK_SYSTEM_SRAM2_PARITY_ERROR) || \ + ((__CONFIG__) == TIM_BREAK_SYSTEM_LOCKUP)) + +#define TIM_SET_ICPRESCALERVALUE(__HANDLE__, __CHANNEL__, __ICPSC__) \ +(((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCMR1 |= (__ICPSC__)) :\ + ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCMR1 |= ((__ICPSC__) << 8)) :\ + ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCMR2 |= (__ICPSC__)) :\ + ((__HANDLE__)->Instance->CCMR2 |= ((__ICPSC__) << 8))) + +#define TIM_RESET_ICPRESCALERVALUE(__HANDLE__, __CHANNEL__) \ +(((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCMR1 &= (uint16_t)~TIM_CCMR1_IC1PSC) :\ + ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCMR1 &= (uint16_t)~TIM_CCMR1_IC2PSC) :\ + ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCMR2 &= (uint16_t)~TIM_CCMR2_IC3PSC) :\ + ((__HANDLE__)->Instance->CCMR2 &= (uint16_t)~TIM_CCMR2_IC4PSC)) + +#define TIM_SET_CAPTUREPOLARITY(__HANDLE__, __CHANNEL__, __POLARITY__) \ +(((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCER |= (__POLARITY__)) :\ + ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCER |= ((__POLARITY__) << 4)) :\ + ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCER |= ((__POLARITY__) << 8)) :\ + ((__HANDLE__)->Instance->CCER |= (((__POLARITY__) << 12)))) + +#define TIM_RESET_CAPTUREPOLARITY(__HANDLE__, __CHANNEL__) \ +(((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCER &= (uint16_t)~(TIM_CCER_CC1P | TIM_CCER_CC1NP)) :\ + ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCER &= (uint16_t)~(TIM_CCER_CC2P | TIM_CCER_CC2NP)) :\ + ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCER &= (uint16_t)~(TIM_CCER_CC3P | TIM_CCER_CC3NP)) :\ + ((__HANDLE__)->Instance->CCER &= (uint16_t)~(TIM_CCER_CC4P | TIM_CCER_CC4NP))) + +/** + * @} + */ +/* End of private macros -----------------------------------------------------*/ + +/* Include TIM HAL Extended module */ +#include "stm32l4xx_hal_tim_ex.h" + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup TIM_Exported_Functions TIM Exported Functions + * @{ + */ + +/** @addtogroup TIM_Exported_Functions_Group1 Time Base functions + * @brief Time Base functions + * @{ + */ +/* Time Base functions ********************************************************/ +HAL_StatusTypeDef HAL_TIM_Base_Init(TIM_HandleTypeDef *htim); +HAL_StatusTypeDef HAL_TIM_Base_DeInit(TIM_HandleTypeDef *htim); +void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim); +void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef *htim); +/* Blocking mode: Polling */ +HAL_StatusTypeDef HAL_TIM_Base_Start(TIM_HandleTypeDef *htim); +HAL_StatusTypeDef HAL_TIM_Base_Stop(TIM_HandleTypeDef *htim); +/* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim); +HAL_StatusTypeDef HAL_TIM_Base_Stop_IT(TIM_HandleTypeDef *htim); +/* Non-Blocking mode: DMA */ +HAL_StatusTypeDef HAL_TIM_Base_Start_DMA(TIM_HandleTypeDef *htim, uint32_t *pData, uint16_t Length); +HAL_StatusTypeDef HAL_TIM_Base_Stop_DMA(TIM_HandleTypeDef *htim); +/** + * @} + */ + +/** @addtogroup TIM_Exported_Functions_Group2 Time Output Compare functions + * @brief Time Output Compare functions + * @{ + */ +/* Timer Output Compare functions *********************************************/ +HAL_StatusTypeDef HAL_TIM_OC_Init(TIM_HandleTypeDef *htim); +HAL_StatusTypeDef HAL_TIM_OC_DeInit(TIM_HandleTypeDef *htim); +void HAL_TIM_OC_MspInit(TIM_HandleTypeDef *htim); +void HAL_TIM_OC_MspDeInit(TIM_HandleTypeDef *htim); +/* Blocking mode: Polling */ +HAL_StatusTypeDef HAL_TIM_OC_Start(TIM_HandleTypeDef *htim, uint32_t Channel); +HAL_StatusTypeDef HAL_TIM_OC_Stop(TIM_HandleTypeDef *htim, uint32_t Channel); +/* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_TIM_OC_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel); +HAL_StatusTypeDef HAL_TIM_OC_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel); +/* Non-Blocking mode: DMA */ +HAL_StatusTypeDef HAL_TIM_OC_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length); +HAL_StatusTypeDef HAL_TIM_OC_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel); +/** + * @} + */ + +/** @addtogroup TIM_Exported_Functions_Group3 Time PWM functions + * @brief Time PWM functions + * @{ + */ +/* Timer PWM functions ********************************************************/ +HAL_StatusTypeDef HAL_TIM_PWM_Init(TIM_HandleTypeDef *htim); +HAL_StatusTypeDef HAL_TIM_PWM_DeInit(TIM_HandleTypeDef *htim); +void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim); +void HAL_TIM_PWM_MspDeInit(TIM_HandleTypeDef *htim); +/* Blocking mode: Polling */ +HAL_StatusTypeDef HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim, uint32_t Channel); +HAL_StatusTypeDef HAL_TIM_PWM_Stop(TIM_HandleTypeDef *htim, uint32_t Channel); +/* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_TIM_PWM_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel); +HAL_StatusTypeDef HAL_TIM_PWM_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel); +/* Non-Blocking mode: DMA */ +HAL_StatusTypeDef HAL_TIM_PWM_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length); +HAL_StatusTypeDef HAL_TIM_PWM_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel); +/** + * @} + */ + +/** @addtogroup TIM_Exported_Functions_Group4 Time Input Capture functions + * @brief Time Input Capture functions + * @{ + */ +/* Timer Input Capture functions **********************************************/ +HAL_StatusTypeDef HAL_TIM_IC_Init(TIM_HandleTypeDef *htim); +HAL_StatusTypeDef HAL_TIM_IC_DeInit(TIM_HandleTypeDef *htim); +void HAL_TIM_IC_MspInit(TIM_HandleTypeDef *htim); +void HAL_TIM_IC_MspDeInit(TIM_HandleTypeDef *htim); +/* Blocking mode: Polling */ +HAL_StatusTypeDef HAL_TIM_IC_Start(TIM_HandleTypeDef *htim, uint32_t Channel); +HAL_StatusTypeDef HAL_TIM_IC_Stop(TIM_HandleTypeDef *htim, uint32_t Channel); +/* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_TIM_IC_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel); +HAL_StatusTypeDef HAL_TIM_IC_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel); +/* Non-Blocking mode: DMA */ +HAL_StatusTypeDef HAL_TIM_IC_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length); +HAL_StatusTypeDef HAL_TIM_IC_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel); +/** + * @} + */ + +/** @addtogroup TIM_Exported_Functions_Group5 Time One Pulse functions + * @brief Time One Pulse functions + * @{ + */ +/* Timer One Pulse functions **************************************************/ +HAL_StatusTypeDef HAL_TIM_OnePulse_Init(TIM_HandleTypeDef *htim, uint32_t OnePulseMode); +HAL_StatusTypeDef HAL_TIM_OnePulse_DeInit(TIM_HandleTypeDef *htim); +void HAL_TIM_OnePulse_MspInit(TIM_HandleTypeDef *htim); +void HAL_TIM_OnePulse_MspDeInit(TIM_HandleTypeDef *htim); +/* Blocking mode: Polling */ +HAL_StatusTypeDef HAL_TIM_OnePulse_Start(TIM_HandleTypeDef *htim, uint32_t OutputChannel); +HAL_StatusTypeDef HAL_TIM_OnePulse_Stop(TIM_HandleTypeDef *htim, uint32_t OutputChannel); +/* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_TIM_OnePulse_Start_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel); +HAL_StatusTypeDef HAL_TIM_OnePulse_Stop_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel); +/** + * @} + */ + +/** @addtogroup TIM_Exported_Functions_Group6 Time Encoder functions + * @brief Time Encoder functions + * @{ + */ +/* Timer Encoder functions ****************************************************/ +HAL_StatusTypeDef HAL_TIM_Encoder_Init(TIM_HandleTypeDef *htim, TIM_Encoder_InitTypeDef* sConfig); +HAL_StatusTypeDef HAL_TIM_Encoder_DeInit(TIM_HandleTypeDef *htim); +void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef *htim); +void HAL_TIM_Encoder_MspDeInit(TIM_HandleTypeDef *htim); + /* Blocking mode: Polling */ +HAL_StatusTypeDef HAL_TIM_Encoder_Start(TIM_HandleTypeDef *htim, uint32_t Channel); +HAL_StatusTypeDef HAL_TIM_Encoder_Stop(TIM_HandleTypeDef *htim, uint32_t Channel); +/* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_TIM_Encoder_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel); +HAL_StatusTypeDef HAL_TIM_Encoder_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel); +/* Non-Blocking mode: DMA */ +HAL_StatusTypeDef HAL_TIM_Encoder_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData1, uint32_t *pData2, uint16_t Length); +HAL_StatusTypeDef HAL_TIM_Encoder_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel); +/** + * @} + */ + +/** @addtogroup TIM_Exported_Functions_Group7 TIM IRQ handler management + * @brief IRQ handler management + * @{ + */ +/* Interrupt Handler functions ***********************************************/ +void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim); +/** + * @} + */ + +/** @defgroup TIM_Exported_Functions_Group8 Peripheral Control functions + * @brief Peripheral Control functions + * @{ + */ +/* Control functions *********************************************************/ +HAL_StatusTypeDef HAL_TIM_OC_ConfigChannel(TIM_HandleTypeDef *htim, TIM_OC_InitTypeDef* sConfig, uint32_t Channel); +HAL_StatusTypeDef HAL_TIM_PWM_ConfigChannel(TIM_HandleTypeDef *htim, TIM_OC_InitTypeDef* sConfig, uint32_t Channel); +HAL_StatusTypeDef HAL_TIM_IC_ConfigChannel(TIM_HandleTypeDef *htim, TIM_IC_InitTypeDef* sConfig, uint32_t Channel); +HAL_StatusTypeDef HAL_TIM_OnePulse_ConfigChannel(TIM_HandleTypeDef *htim, TIM_OnePulse_InitTypeDef* sConfig, uint32_t OutputChannel, uint32_t InputChannel); +HAL_StatusTypeDef HAL_TIM_ConfigOCrefClear(TIM_HandleTypeDef *htim, TIM_ClearInputConfigTypeDef * sClearInputConfig, uint32_t Channel); +HAL_StatusTypeDef HAL_TIM_ConfigClockSource(TIM_HandleTypeDef *htim, TIM_ClockConfigTypeDef * sClockSourceConfig); +HAL_StatusTypeDef HAL_TIM_ConfigTI1Input(TIM_HandleTypeDef *htim, uint32_t TI1_Selection); +HAL_StatusTypeDef HAL_TIM_SlaveConfigSynchronization(TIM_HandleTypeDef *htim, TIM_SlaveConfigTypeDef * sSlaveConfig); +HAL_StatusTypeDef HAL_TIM_SlaveConfigSynchronization_IT(TIM_HandleTypeDef *htim, TIM_SlaveConfigTypeDef * sSlaveConfig); +HAL_StatusTypeDef HAL_TIM_DMABurst_WriteStart(TIM_HandleTypeDef *htim, uint32_t BurstBaseAddress, uint32_t BurstRequestSrc, \ + uint32_t *BurstBuffer, uint32_t BurstLength); +HAL_StatusTypeDef HAL_TIM_DMABurst_WriteStop(TIM_HandleTypeDef *htim, uint32_t BurstRequestSrc); +HAL_StatusTypeDef HAL_TIM_DMABurst_ReadStart(TIM_HandleTypeDef *htim, uint32_t BurstBaseAddress, uint32_t BurstRequestSrc, \ + uint32_t *BurstBuffer, uint32_t BurstLength); +HAL_StatusTypeDef HAL_TIM_DMABurst_ReadStop(TIM_HandleTypeDef *htim, uint32_t BurstRequestSrc); +HAL_StatusTypeDef HAL_TIM_GenerateEvent(TIM_HandleTypeDef *htim, uint32_t EventSource); +uint32_t HAL_TIM_ReadCapturedValue(TIM_HandleTypeDef *htim, uint32_t Channel); +/** + * @} + */ + +/** @defgroup TIM_Exported_Functions_Group9 TIM Callbacks functions + * @brief TIM Callbacks functions + * @{ + */ +/* Callback in non blocking modes (Interrupt and DMA) *************************/ +void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim); +void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim); +void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim); +void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim); +void HAL_TIM_TriggerCallback(TIM_HandleTypeDef *htim); +void HAL_TIM_ErrorCallback(TIM_HandleTypeDef *htim); +/** + * @} + */ + +/** @defgroup TIM_Exported_Functions_Group10 Peripheral State functions + * @brief Peripheral State functions + * @{ + */ +/* Peripheral State functions ************************************************/ +HAL_TIM_StateTypeDef HAL_TIM_Base_GetState(TIM_HandleTypeDef *htim); +HAL_TIM_StateTypeDef HAL_TIM_OC_GetState(TIM_HandleTypeDef *htim); +HAL_TIM_StateTypeDef HAL_TIM_PWM_GetState(TIM_HandleTypeDef *htim); +HAL_TIM_StateTypeDef HAL_TIM_IC_GetState(TIM_HandleTypeDef *htim); +HAL_TIM_StateTypeDef HAL_TIM_OnePulse_GetState(TIM_HandleTypeDef *htim); +HAL_TIM_StateTypeDef HAL_TIM_Encoder_GetState(TIM_HandleTypeDef *htim); +/** + * @} + */ + +/** + * @} + */ +/* End of exported functions -------------------------------------------------*/ + +/* Private functions----------------------------------------------------------*/ +/** @defgroup TIM_Private_Functions TIM Private Functions +* @{ +*/ +void TIM_Base_SetConfig(TIM_TypeDef *TIMx, TIM_Base_InitTypeDef *Structure); +void TIM_TI1_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection, uint32_t TIM_ICFilter); +void TIM_OC2_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config); +void TIM_ETR_SetConfig(TIM_TypeDef* TIMx, uint32_t TIM_ExtTRGPrescaler, + uint32_t TIM_ExtTRGPolarity, uint32_t ExtTRGFilter); + +void TIM_DMADelayPulseCplt(DMA_HandleTypeDef *hdma); +void TIM_DMAError(DMA_HandleTypeDef *hdma); +void TIM_DMACaptureCplt(DMA_HandleTypeDef *hdma); +void TIM_CCxChannelCmd(TIM_TypeDef* TIMx, uint32_t Channel, uint32_t ChannelState); +/** +* @} +*/ +/* End of private functions --------------------------------------------------*/ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_HAL_TIM_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_tim_ex.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_tim_ex.h new file mode 100644 index 0000000..eae1c9a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_tim_ex.h @@ -0,0 +1,484 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_tim_ex.h + * @author MCD Application Team + * @brief Header file of TIM HAL Extended module. + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_TIM_EX_H +#define __STM32L4xx_HAL_TIM_EX_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup TIMEx + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup TIMEx_Exported_Types TIM Extended Exported Types + * @{ + */ + +/** + * @brief TIM Hall sensor Configuration Structure definition + */ + +typedef struct +{ + + uint32_t IC1Polarity; /*!< Specifies the active edge of the input signal. + This parameter can be a value of @ref TIM_Input_Capture_Polarity */ + + uint32_t IC1Prescaler; /*!< Specifies the Input Capture Prescaler. + This parameter can be a value of @ref TIM_Input_Capture_Prescaler */ + + uint32_t IC1Filter; /*!< Specifies the input capture filter. + This parameter can be a number between Min_Data = 0x0 and Max_Data = 0xF */ + + uint32_t Commutation_Delay; /*!< Specifies the pulse value to be loaded into the Capture Compare Register. + This parameter can be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF */ +} TIM_HallSensor_InitTypeDef; + +/** + * @brief TIM Break/Break2 input configuration + */ +typedef struct { + uint32_t Source; /*!< Specifies the source of the timer break input. + This parameter can be a value of @ref TIMEx_Break_Input_Source */ + uint32_t Enable; /*!< Specifies whether or not the break input source is enabled. + This parameter can be a value of @ref TIMEx_Break_Input_Source_Enable */ + uint32_t Polarity; /*!< Specifies the break input source polarity. + This parameter can be a value of @ref TIMEx_Break_Input_Source_Polarity + Not relevant when analog watchdog output of the DFSDM1 used as break input source */ +} TIMEx_BreakInputConfigTypeDef; + +/** + * @} + */ +/* End of exported types -----------------------------------------------------*/ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup TIMEx_Exported_Constants TIM Extended Exported Constants + * @{ + */ + +/** @defgroup TIMEx_Remap TIM Extended Remapping + * @{ + */ +#define TIM_TIM1_ETR_ADC1_NONE ((uint32_t)(0x00000000)) /* !< TIM1_ETR is not connected to any AWD (analog watchdog)*/ +#define TIM_TIM1_ETR_ADC1_AWD1 (TIM1_OR1_ETR_ADC1_RMP_0) /* !< TIM1_ETR is connected to ADC1 AWD1 */ +#define TIM_TIM1_ETR_ADC1_AWD2 (TIM1_OR1_ETR_ADC1_RMP_1) /* !< TIM1_ETR is connected to ADC1 AWD2 */ +#define TIM_TIM1_ETR_ADC1_AWD3 (TIM1_OR1_ETR_ADC1_RMP_1 | TIM1_OR1_ETR_ADC1_RMP_0) /* !< TIM1_ETR is connected to ADC1 AWD3 */ +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) +#define TIM_TIM1_ETR_ADC3_NONE ((uint32_t)(0x00000000)) /* !< TIM1_ETR is not connected to any AWD (analog watchdog)*/ +#define TIM_TIM1_ETR_ADC3_AWD1 (TIM1_OR1_ETR_ADC3_RMP_0) /* !< TIM1_ETR is connected to ADC3 AWD1 */ +#define TIM_TIM1_ETR_ADC3_AWD2 (TIM1_OR1_ETR_ADC3_RMP_1) /* !< TIM1_ETR is connected to ADC3 AWD2 */ +#define TIM_TIM1_ETR_ADC3_AWD3 (TIM1_OR1_ETR_ADC3_RMP_1 | TIM1_OR1_ETR_ADC3_RMP_0) /* !< TIM1_ETR is connected to ADC3 AWD3 */ +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx */ +#define TIM_TIM1_TI1_GPIO ((uint32_t)(0x00000000)) /* !< TIM1 TI1 is connected to GPIO */ +#define TIM_TIM1_TI1_COMP1 (TIM1_OR1_TI1_RMP) /* !< TIM1 TI1 is connected to COMP1 */ +#define TIM_TIM1_ETR_GPIO ((uint32_t)(0x00000000)) /* !< TIM1_ETR is connected to GPIO */ +#define TIM_TIM1_ETR_COMP1 (TIM1_OR2_ETRSEL_0) /* !< TIM1_ETR is connected to COMP1 output */ +#define TIM_TIM1_ETR_COMP2 (TIM1_OR2_ETRSEL_1) /* !< TIM1_ETR is connected to COMP2 output */ + +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define TIM_TIM2_ITR1_TIM8_TRGO ((uint32_t)(0x00000000)) /* !< TIM2_ITR1 is connected to TIM8_TRGO */ +#define TIM_TIM2_ITR1_OTG_FS_SOF (TIM2_OR1_ITR1_RMP) /* !< TIM2_ITR1 is connected to OTG_FS SOF */ +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx || */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ +#if defined (STM32L431xx) || defined (STM32L432xx) || defined (STM32L433xx) || defined (STM32L442xx) || defined (STM32L443xx) || \ + defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) +#define TIM_TIM2_ITR1_NONE ((uint32_t)(0x00000000)) /* !< No internal trigger on TIM2_ITR1 */ +#define TIM_TIM2_ITR1_USB_SOF (TIM2_OR1_ITR1_RMP) /* !< TIM2_ITR1 is connected to USB SOF */ +#endif /* STM32L431xx || STM32L432xx || STM32L442xx || STM32L433xx || STM32L443xx || */ + /* STM32L451xx || STM32L452xx || STM32L462xx */ +#define TIM_TIM2_ETR_GPIO ((uint32_t)(0x00000000)) /* !< TIM2_ETR is connected to GPIO */ +#define TIM_TIM2_ETR_LSE (TIM2_OR1_ETR1_RMP) /* !< TIM2_ETR is connected to LSE */ +#define TIM_TIM2_ETR_COMP1 (TIM2_OR2_ETRSEL_0) /* !< TIM2_ETR is connected to COMP1 output */ +#define TIM_TIM2_ETR_COMP2 (TIM2_OR2_ETRSEL_1) /* !< TIM2_ETR is connected to COMP2 output */ +#define TIM_TIM2_TI4_GPIO ((uint32_t)(0x00000000)) /* !< TIM2 TI4 is connected to GPIO */ +#define TIM_TIM2_TI4_COMP1 (TIM2_OR1_TI4_RMP_0) /* !< TIM2 TI4 is connected to COMP1 output */ +#define TIM_TIM2_TI4_COMP2 (TIM2_OR1_TI4_RMP_1) /* !< TIM2 TI4 is connected to COMP2 output */ +#define TIM_TIM2_TI4_COMP1_COMP2 (TIM2_OR1_TI4_RMP_1| TIM2_OR1_TI4_RMP_0) /* !< TIM2 TI4 is connected to logical OR between COMP1 and COMP2 output2 */ + +#if defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || \ + defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define TIM_TIM3_TI1_GPIO ((uint32_t)(0x00000000)) /* !< TIM3 TI1 is connected to GPIO */ +#define TIM_TIM3_TI1_COMP1 (TIM3_OR1_TI1_RMP_0) /* !< TIM3 TI1 is connected to COMP1 output */ +#define TIM_TIM3_TI1_COMP2 (TIM3_OR1_TI1_RMP_1) /* !< TIM3 TI1 is connected to COMP2 output */ +#define TIM_TIM3_TI1_COMP1_COMP2 (TIM3_OR1_TI1_RMP_1 | TIM3_OR1_TI1_RMP_0) /* !< TIM3 TI1 is connected to logical OR between COMP1 and COMP2 output2 */ +#define TIM_TIM3_ETR_GPIO ((uint32_t)(0x00000000)) /* !< TIM3_ETR is connected to GPIO */ +#define TIM_TIM3_ETR_COMP1 (TIM3_OR2_ETRSEL_0) /* !< TIM3_ETR is connected to COMP1 output */ +#endif /* STM32L451xx || STM32L452xx || STM32L462xx || */ + /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx || */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) +#define TIM_TIM8_ETR_ADC2_NONE ((uint32_t)(0x00000000)) /* !< TIM8_ETR is not connected to any AWD (analog watchdog)*/ +#define TIM_TIM8_ETR_ADC2_AWD1 (TIM8_OR1_ETR_ADC2_RMP_0) /* !< TIM8_ETR is connected to ADC2 AWD1 */ +#define TIM_TIM8_ETR_ADC2_AWD2 (TIM8_OR1_ETR_ADC2_RMP_1) /* !< TIM8_ETR is connected to ADC2 AWD2 */ +#define TIM_TIM8_ETR_ADC2_AWD3 (TIM8_OR1_ETR_ADC2_RMP_1 | TIM8_OR1_ETR_ADC2_RMP_0) /* !< TIM8_ETR is connected to ADC2 AWD3 */ +#define TIM_TIM8_ETR_ADC3_NONE ((uint32_t)(0x00000000)) /* !< TIM8_ETR is not connected to any AWD (analog watchdog)*/ +#define TIM_TIM8_ETR_ADC3_AWD1 (TIM8_OR1_ETR_ADC3_RMP_0) /* !< TIM8_ETR is connected to ADC3 AWD1 */ +#define TIM_TIM8_ETR_ADC3_AWD2 (TIM8_OR1_ETR_ADC3_RMP_1) /* !< TIM8_ETR is connected to ADC3 AWD2 */ +#define TIM_TIM8_ETR_ADC3_AWD3 (TIM8_OR1_ETR_ADC3_RMP_1 | TIM8_OR1_ETR_ADC3_RMP_0) /* !< TIM8_ETR is connected to ADC3 AWD3 */ +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx */ +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define TIM_TIM8_TI1_GPIO ((uint32_t)(0x00000000)) /* !< TIM8 TI1 is connected to GPIO */ +#define TIM_TIM8_TI1_COMP2 (TIM8_OR1_TI1_RMP) /* !< TIM8 TI1 is connected to COMP1 */ +#define TIM_TIM8_ETR_GPIO ((uint32_t)(0x00000000)) /* !< TIM8_ETR is connected to GPIO */ +#define TIM_TIM8_ETR_COMP1 (TIM8_OR2_ETRSEL_0) /* !< TIM8_ETR is connected to COMP1 output */ +#define TIM_TIM8_ETR_COMP2 (TIM8_OR2_ETRSEL_1) /* !< TIM8_ETR is connected to COMP2 output */ +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx || */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#define TIM_TIM15_TI1_GPIO ((uint32_t)(0x00000000)) /* !< TIM15 TI1 is connected to GPIO */ +#define TIM_TIM15_TI1_LSE (TIM15_OR1_TI1_RMP) /* !< TIM15 TI1 is connected to LSE */ +#define TIM_TIM15_ENCODERMODE_NONE ((uint32_t)(0x00000000)) /* !< No redirection */ +#define TIM_TIM15_ENCODERMODE_TIM2 (TIM15_OR1_ENCODER_MODE_0) /* !< TIM2 IC1 and TIM2 IC2 are connected to TIM15 IC1 and TIM15 IC2 respectively */ +#if defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || \ + defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define TIM_TIM15_ENCODERMODE_TIM3 (TIM15_OR1_ENCODER_MODE_1) /* !< TIM3 IC1 and TIM3 IC2 are connected to TIM15 IC1 and TIM15 IC2 respectively */ +#endif /* STM32L451xx || STM32L452xx || STM32L462xx */ + /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx || */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define TIM_TIM15_ENCODERMODE_TIM4 (TIM15_OR1_ENCODER_MODE_1 | TIM15_OR1_ENCODER_MODE_0) /* !< TIM4 IC1 and TIM4 IC2 are connected to TIM15 IC1 and TIM15 IC2 respectively */ +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx || */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#define TIM_TIM16_TI1_GPIO ((uint32_t)(0x00000000)) /* !< TIM16 TI1 is connected to GPIO */ +#define TIM_TIM16_TI1_LSI (TIM16_OR1_TI1_RMP_0) /* !< TIM16 TI1 is connected to LSI */ +#define TIM_TIM16_TI1_LSE (TIM16_OR1_TI1_RMP_1) /* !< TIM16 TI1 is connected to LSE */ +#define TIM_TIM16_TI1_RTC (TIM16_OR1_TI1_RMP_1 | TIM16_OR1_TI1_RMP_0) /* !< TIM16 TI1 is connected to RTC wakeup interrupt */ +#if defined (STM32L431xx) || defined (STM32L432xx) || defined (STM32L433xx) || defined (STM32L442xx) || defined (STM32L443xx) || \ + defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) +#define TIM_TIM16_TI1_MSI (TIM16_OR1_TI1_RMP_2) /* !< TIM16 TI1 is connected to MSI */ +#define TIM_TIM16_TI1_HSE_32 (TIM16_OR1_TI1_RMP_2 | TIM16_OR1_TI1_RMP_0) /* !< TIM16 TI1 is connected to HSE div 32 */ +#define TIM_TIM16_TI1_MCO (TIM16_OR1_TI1_RMP_2 | TIM16_OR1_TI1_RMP_1) /* !< TIM16 TI1 is connected to MCO */ +#endif /* STM32L431xx || STM32L432xx || STM32L442xx || STM32L433xx || STM32L443xx || */ + /* STM32L451xx || STM32L452xx || STM32L462xx || */ + /* STM32L496xx || STM32L4A6xx */ + +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define TIM_TIM17_TI1_GPIO ((uint32_t)(0x00000000)) /* !< TIM17 TI1 is connected to GPIO */ +#define TIM_TIM17_TI1_MSI (TIM17_OR1_TI1_RMP_0) /* !< TIM17 TI1 is connected to MSI */ +#define TIM_TIM17_TI1_HSE_32 (TIM17_OR1_TI1_RMP_1) /* !< TIM17 TI1 is connected to HSE div 32 */ +#define TIM_TIM17_TI1_MCO (TIM17_OR1_TI1_RMP_1 | TIM17_OR1_TI1_RMP_0) /* !< TIM17 TI1 is connected to MCO */ +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx || */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ +/** + * @} + */ + +/** @defgroup TIMEx_Break_Input TIM Extended Break input + * @{ + */ +#define TIM_BREAKINPUT_BRK ((uint32_t)(0x00000001)) /* !< Timer break input */ +#define TIM_BREAKINPUT_BRK2 ((uint32_t)(0x00000002)) /* !< Timer break2 input */ +/** + * @} + */ + +/** @defgroup TIMEx_Break_Input_Source TIM Extended Break input source + * @{ + */ +#define TIM_BREAKINPUTSOURCE_BKIN ((uint32_t)(0x00000001)) /* !< An external source (GPIO) is connected to the BKIN pin */ +#define TIM_BREAKINPUTSOURCE_COMP1 ((uint32_t)(0x00000002)) /* !< The COMP1 output is connected to the break input */ +#define TIM_BREAKINPUTSOURCE_COMP2 ((uint32_t)(0x00000004)) /* !< The COMP2 output is connected to the break input */ +#if defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || \ + defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define TIM_BREAKINPUTSOURCE_DFSDM1 ((uint32_t)(0x00000008)) /* !< The analog watchdog output of the DFSDM1 peripheral is connected to the break input */ +#endif /* STM32L451xx || STM32L452xx || STM32L462xx || */ + /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx || */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ +/** + * @} + */ + +/** @defgroup TIMEx_Break_Input_Source_Enable TIM Extended Break input source enabling + * @{ + */ +#define TIM_BREAKINPUTSOURCE_DISABLE ((uint32_t)(0x00000000)) /* !< Break input source is disabled */ +#define TIM_BREAKINPUTSOURCE_ENABLE ((uint32_t)(0x00000001)) /* !< Break input source is enabled */ +/** + * @} + */ + +/** @defgroup TIMEx_Break_Input_Source_Polarity TIM Extended Break input polarity + * @{ + */ +#define TIM_BREAKINPUTSOURCE_POLARITY_LOW ((uint32_t)(0x00000001)) /* !< Break input source is active low */ +#define TIM_BREAKINPUTSOURCE_POLARITY_HIGH ((uint32_t)(0x00000000)) /* !< Break input source is active_high */ +/** + * @} + */ + +/** + * @} + */ +/* End of exported constants -------------------------------------------------*/ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup TIMEx_Exported_Macros TIM Extended Exported Macros + * @{ + */ + +/** + * @} + */ +/* End of exported macro -----------------------------------------------------*/ + +/* Private macro -------------------------------------------------------------*/ +/** @defgroup TIMEx_Private_Macros TIM Extended Private Macros + * @{ + */ +#define IS_TIM_REMAP(__REMAP__) (((__REMAP__) <= (uint32_t)0x0001C01F)) + +#define IS_TIM_BREAKINPUT(__BREAKINPUT__) (((__BREAKINPUT__) == TIM_BREAKINPUT_BRK) || \ + ((__BREAKINPUT__) == TIM_BREAKINPUT_BRK2)) + +#if defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || \ + defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define IS_TIM_BREAKINPUTSOURCE(__SOURCE__) (((__SOURCE__) == TIM_BREAKINPUTSOURCE_BKIN) || \ + ((__SOURCE__) == TIM_BREAKINPUTSOURCE_COMP1) || \ + ((__SOURCE__) == TIM_BREAKINPUTSOURCE_COMP2) || \ + ((__SOURCE__) == TIM_BREAKINPUTSOURCE_DFSDM1)) +#else +#define IS_TIM_BREAKINPUTSOURCE(__SOURCE__) (((__SOURCE__) == TIM_BREAKINPUTSOURCE_BKIN) || \ + ((__SOURCE__) == TIM_BREAKINPUTSOURCE_COMP1) || \ + ((__SOURCE__) == TIM_BREAKINPUTSOURCE_COMP2)) +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx || */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#define IS_TIM_BREAKINPUTSOURCE_STATE(__STATE__) (((__STATE__) == TIM_BREAKINPUTSOURCE_DISABLE) || \ + ((__STATE__) == TIM_BREAKINPUTSOURCE_ENABLE)) + +#define IS_TIM_BREAKINPUTSOURCE_POLARITY(__POLARITY__) (((__POLARITY__) == TIM_BREAKINPUTSOURCE_POLARITY_LOW) || \ + ((__POLARITY__) == TIM_BREAKINPUTSOURCE_POLARITY_HIGH)) +/** + * @} + */ +/* End of private macro ------------------------------------------------------*/ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup TIMEx_Exported_Functions TIM Extended Exported Functions + * @{ + */ + +/** @addtogroup TIMEx_Exported_Functions_Group1 Extended Timer Hall Sensor functions + * @brief Timer Hall Sensor functions + * @{ + */ +/* Timer Hall Sensor functions **********************************************/ +HAL_StatusTypeDef HAL_TIMEx_HallSensor_Init(TIM_HandleTypeDef *htim, TIM_HallSensor_InitTypeDef* sConfig); +HAL_StatusTypeDef HAL_TIMEx_HallSensor_DeInit(TIM_HandleTypeDef *htim); + +void HAL_TIMEx_HallSensor_MspInit(TIM_HandleTypeDef *htim); +void HAL_TIMEx_HallSensor_MspDeInit(TIM_HandleTypeDef *htim); + + /* Blocking mode: Polling */ +HAL_StatusTypeDef HAL_TIMEx_HallSensor_Start(TIM_HandleTypeDef *htim); +HAL_StatusTypeDef HAL_TIMEx_HallSensor_Stop(TIM_HandleTypeDef *htim); +/* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_TIMEx_HallSensor_Start_IT(TIM_HandleTypeDef *htim); +HAL_StatusTypeDef HAL_TIMEx_HallSensor_Stop_IT(TIM_HandleTypeDef *htim); +/* Non-Blocking mode: DMA */ +HAL_StatusTypeDef HAL_TIMEx_HallSensor_Start_DMA(TIM_HandleTypeDef *htim, uint32_t *pData, uint16_t Length); +HAL_StatusTypeDef HAL_TIMEx_HallSensor_Stop_DMA(TIM_HandleTypeDef *htim); +/** + * @} + */ + +/** @addtogroup TIMEx_Exported_Functions_Group2 Extended Timer Complementary Output Compare functions + * @brief Timer Complementary Output Compare functions + * @{ + */ +/* Timer Complementary Output Compare functions *****************************/ +/* Blocking mode: Polling */ +HAL_StatusTypeDef HAL_TIMEx_OCN_Start(TIM_HandleTypeDef *htim, uint32_t Channel); +HAL_StatusTypeDef HAL_TIMEx_OCN_Stop(TIM_HandleTypeDef *htim, uint32_t Channel); + +/* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_TIMEx_OCN_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel); +HAL_StatusTypeDef HAL_TIMEx_OCN_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel); + +/* Non-Blocking mode: DMA */ +HAL_StatusTypeDef HAL_TIMEx_OCN_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length); +HAL_StatusTypeDef HAL_TIMEx_OCN_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel); +/** + * @} + */ + +/** @addtogroup TIMEx_Exported_Functions_Group3 Extended Timer Complementary PWM functions + * @brief Timer Complementary PWM functions + * @{ + */ +/* Timer Complementary PWM functions ****************************************/ +/* Blocking mode: Polling */ +HAL_StatusTypeDef HAL_TIMEx_PWMN_Start(TIM_HandleTypeDef *htim, uint32_t Channel); +HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop(TIM_HandleTypeDef *htim, uint32_t Channel); + +/* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_TIMEx_PWMN_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel); +HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel); +/* Non-Blocking mode: DMA */ +HAL_StatusTypeDef HAL_TIMEx_PWMN_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length); +HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel); +/** + * @} + */ + +/** @addtogroup TIMEx_Exported_Functions_Group4 Extended Timer Complementary One Pulse functions + * @brief Timer Complementary One Pulse functions + * @{ + */ +/* Timer Complementary One Pulse functions **********************************/ +/* Blocking mode: Polling */ +HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Start(TIM_HandleTypeDef *htim, uint32_t OutputChannel); +HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Stop(TIM_HandleTypeDef *htim, uint32_t OutputChannel); + +/* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Start_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel); +HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Stop_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel); +/** + * @} + */ + +/** @addtogroup TIMEx_Exported_Functions_Group5 Extended Peripheral Control functions + * @brief Peripheral Control functions + * @{ + */ +/* Extended Control functions ************************************************/ +HAL_StatusTypeDef HAL_TIMEx_ConfigCommutationEvent(TIM_HandleTypeDef *htim, uint32_t InputTrigger, uint32_t CommutationSource); +HAL_StatusTypeDef HAL_TIMEx_ConfigCommutationEvent_IT(TIM_HandleTypeDef *htim, uint32_t InputTrigger, uint32_t CommutationSource); +HAL_StatusTypeDef HAL_TIMEx_ConfigCommutationEvent_DMA(TIM_HandleTypeDef *htim, uint32_t InputTrigger, uint32_t CommutationSource); +HAL_StatusTypeDef HAL_TIMEx_MasterConfigSynchronization(TIM_HandleTypeDef *htim, TIM_MasterConfigTypeDef * sMasterConfig); +HAL_StatusTypeDef HAL_TIMEx_ConfigBreakDeadTime(TIM_HandleTypeDef *htim, TIM_BreakDeadTimeConfigTypeDef *sBreakDeadTimeConfig); +HAL_StatusTypeDef HAL_TIMEx_ConfigBreakInput(TIM_HandleTypeDef *htim, uint32_t BreakInput, TIMEx_BreakInputConfigTypeDef *sBreakInputConfig); +HAL_StatusTypeDef HAL_TIMEx_GroupChannel5(TIM_HandleTypeDef *htim, uint32_t Channels); +HAL_StatusTypeDef HAL_TIMEx_RemapConfig(TIM_HandleTypeDef *htim, uint32_t Remap); + +/** + * @} + */ + +/** @addtogroup TIMEx_Exported_Functions_Group6 Extended Callbacks functions + * @brief Extended Callbacks functions + * @{ + */ +/* Extended Callback **********************************************************/ +void HAL_TIMEx_CommutationCallback(TIM_HandleTypeDef *htim); +void HAL_TIMEx_BreakCallback(TIM_HandleTypeDef *htim); +/** + * @} + */ + +/** @addtogroup TIMEx_Exported_Functions_Group7 Extended Peripheral State functions + * @brief Extended Peripheral State functions + * @{ + */ +/* Extended Peripheral State functions ***************************************/ +HAL_TIM_StateTypeDef HAL_TIMEx_HallSensor_GetState(TIM_HandleTypeDef *htim); +/** + * @} + */ + +/** + * @} + */ +/* End of exported functions -------------------------------------------------*/ + +/* Private functions----------------------------------------------------------*/ +/** @defgroup TIMEx_Private_Functions TIMEx Private Functions +* @{ +*/ +void TIMEx_DMACommutationCplt(DMA_HandleTypeDef *hdma); +/** +* @} +*/ +/* End of private functions --------------------------------------------------*/ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + + +#endif /* __STM32L4xx_HAL_TIM_EX_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_uart.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_uart.h new file mode 100644 index 0000000..c1b0489 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_uart.h @@ -0,0 +1,1638 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_uart.h + * @author MCD Application Team + * @brief Header file of UART HAL module. + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_UART_H +#define __STM32L4xx_HAL_UART_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup UART + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup UART_Exported_Types UART Exported Types + * @{ + */ + +/** + * @brief UART Init Structure definition + */ +typedef struct +{ + uint32_t BaudRate; /*!< This member configures the UART communication baud rate. + The baud rate register is computed using the following formula: + UART: + ===== + - If oversampling is 16 or in LIN mode, + Baud Rate Register = ((uart_ker_ckpres) / ((huart->Init.BaudRate))) + - If oversampling is 8, + Baud Rate Register[15:4] = ((2 * uart_ker_ckpres) / ((huart->Init.BaudRate)))[15:4] + Baud Rate Register[3] = 0 + Baud Rate Register[2:0] = (((2 * uart_ker_ckpres) / ((huart->Init.BaudRate)))[3:0]) >> 1 + LPUART: + ======= + Baud Rate Register = ((256 * lpuart_ker_ckpres) / ((huart->Init.BaudRate))) + + where (uart/lpuart)_ker_ck_pres is the UART input clock divided by a prescaler */ + + uint32_t WordLength; /*!< Specifies the number of data bits transmitted or received in a frame. + This parameter can be a value of @ref UARTEx_Word_Length. */ + + uint32_t StopBits; /*!< Specifies the number of stop bits transmitted. + This parameter can be a value of @ref UART_Stop_Bits. */ + + uint32_t Parity; /*!< Specifies the parity mode. + This parameter can be a value of @ref UART_Parity + @note When parity is enabled, the computed parity is inserted + at the MSB position of the transmitted data (9th bit when + the word length is set to 9 data bits; 8th bit when the + word length is set to 8 data bits). */ + + uint32_t Mode; /*!< Specifies whether the Receive or Transmit mode is enabled or disabled. + This parameter can be a value of @ref UART_Mode. */ + + uint32_t HwFlowCtl; /*!< Specifies whether the hardware flow control mode is enabled + or disabled. + This parameter can be a value of @ref UART_Hardware_Flow_Control. */ + + uint32_t OverSampling; /*!< Specifies whether the Over sampling 8 is enabled or disabled, to achieve higher speed (up to f_PCLK/8). + This parameter can be a value of @ref UART_Over_Sampling. */ + + uint32_t OneBitSampling; /*!< Specifies whether a single sample or three samples' majority vote is selected. + Selecting the single sample method increases the receiver tolerance to clock + deviations. This parameter can be a value of @ref UART_OneBit_Sampling. */ + +#if defined(USART_PRESC_PRESCALER) + uint32_t ClockPrescaler; /*!< Specifies the prescaler value used to divide the UART clock source. + This parameter can be a value of @ref UART_ClockPrescaler. */ +#endif + +}UART_InitTypeDef; + +/** + * @brief UART Advanced Features initalization structure definition + */ +typedef struct +{ + uint32_t AdvFeatureInit; /*!< Specifies which advanced UART features is initialized. Several + Advanced Features may be initialized at the same time . + This parameter can be a value of @ref UART_Advanced_Features_Initialization_Type. */ + + uint32_t TxPinLevelInvert; /*!< Specifies whether the TX pin active level is inverted. + This parameter can be a value of @ref UART_Tx_Inv. */ + + uint32_t RxPinLevelInvert; /*!< Specifies whether the RX pin active level is inverted. + This parameter can be a value of @ref UART_Rx_Inv. */ + + uint32_t DataInvert; /*!< Specifies whether data are inverted (positive/direct logic + vs negative/inverted logic). + This parameter can be a value of @ref UART_Data_Inv. */ + + uint32_t Swap; /*!< Specifies whether TX and RX pins are swapped. + This parameter can be a value of @ref UART_Rx_Tx_Swap. */ + + uint32_t OverrunDisable; /*!< Specifies whether the reception overrun detection is disabled. + This parameter can be a value of @ref UART_Overrun_Disable. */ + + uint32_t DMADisableonRxError; /*!< Specifies whether the DMA is disabled in case of reception error. + This parameter can be a value of @ref UART_DMA_Disable_on_Rx_Error. */ + + uint32_t AutoBaudRateEnable; /*!< Specifies whether auto Baud rate detection is enabled. + This parameter can be a value of @ref UART_AutoBaudRate_Enable */ + + uint32_t AutoBaudRateMode; /*!< If auto Baud rate detection is enabled, specifies how the rate + detection is carried out. + This parameter can be a value of @ref UART_AutoBaud_Rate_Mode. */ + + uint32_t MSBFirst; /*!< Specifies whether MSB is sent first on UART line. + This parameter can be a value of @ref UART_MSB_First. */ +} UART_AdvFeatureInitTypeDef; + + + +/** + * @brief HAL UART State structures definition + * @note HAL UART State value is a combination of 2 different substates: gState and RxState. + * - gState contains UART state information related to global Handle management + * and also information related to Tx operations. + * gState value coding follow below described bitmap : + * b7-b6 Error information + * 00 : No Error + * 01 : (Not Used) + * 10 : Timeout + * 11 : Error + * b5 IP initilisation status + * 0 : Reset (IP not initialized) + * 1 : Init done (IP not initialized. HAL UART Init function already called) + * b4-b3 (not used) + * xx : Should be set to 00 + * b2 Intrinsic process state + * 0 : Ready + * 1 : Busy (IP busy with some configuration or internal operations) + * b1 (not used) + * x : Should be set to 0 + * b0 Tx state + * 0 : Ready (no Tx operation ongoing) + * 1 : Busy (Tx operation ongoing) + * - RxState contains information related to Rx operations. + * RxState value coding follow below described bitmap : + * b7-b6 (not used) + * xx : Should be set to 00 + * b5 IP initilisation status + * 0 : Reset (IP not initialized) + * 1 : Init done (IP not initialized) + * b4-b2 (not used) + * xxx : Should be set to 000 + * b1 Rx state + * 0 : Ready (no Rx operation ongoing) + * 1 : Busy (Rx operation ongoing) + * b0 (not used) + * x : Should be set to 0. + */ +typedef enum +{ + HAL_UART_STATE_RESET = 0x00U, /*!< Peripheral is not initialized + Value is allowed for gState and RxState */ + HAL_UART_STATE_READY = 0x20U, /*!< Peripheral Initialized and ready for use + Value is allowed for gState and RxState */ + HAL_UART_STATE_BUSY = 0x24U, /*!< an internal process is ongoing + Value is allowed for gState only */ + HAL_UART_STATE_BUSY_TX = 0x21U, /*!< Data Transmission process is ongoing + Value is allowed for gState only */ + HAL_UART_STATE_BUSY_RX = 0x22U, /*!< Data Reception process is ongoing + Value is allowed for RxState only */ + HAL_UART_STATE_BUSY_TX_RX = 0x23U, /*!< Data Transmission and Reception process is ongoing + Not to be used for neither gState nor RxState. + Value is result of combination (Or) between gState and RxState values */ + HAL_UART_STATE_TIMEOUT = 0xA0U, /*!< Timeout state + Value is allowed for gState only */ + HAL_UART_STATE_ERROR = 0xE0U /*!< Error + Value is allowed for gState only */ +}HAL_UART_StateTypeDef; + +/** + * @brief HAL UART Error Code structure definition + */ +typedef enum +{ + HAL_UART_ERROR_NONE = 0x00U, /*!< No error */ + HAL_UART_ERROR_PE = 0x01U, /*!< Parity error */ + HAL_UART_ERROR_NE = 0x02U, /*!< Noise error */ + HAL_UART_ERROR_FE = 0x04U, /*!< frame error */ + HAL_UART_ERROR_ORE = 0x08U, /*!< Overrun error */ + HAL_UART_ERROR_DMA = 0x10U /*!< DMA transfer error */ +}HAL_UART_ErrorTypeDef; + +/** + * @brief UART clock sources definition + */ +typedef enum +{ + UART_CLOCKSOURCE_PCLK1 = 0x00U, /*!< PCLK1 clock source */ + UART_CLOCKSOURCE_PCLK2 = 0x01U, /*!< PCLK2 clock source */ + UART_CLOCKSOURCE_HSI = 0x02U, /*!< HSI clock source */ + UART_CLOCKSOURCE_SYSCLK = 0x04U, /*!< SYSCLK clock source */ + UART_CLOCKSOURCE_LSE = 0x08U, /*!< LSE clock source */ + UART_CLOCKSOURCE_UNDEFINED = 0x10U /*!< Undefined clock source */ +}UART_ClockSourceTypeDef; + +/** + * @brief UART handle Structure definition + */ +typedef struct __UART_HandleTypeDef +{ + USART_TypeDef *Instance; /*!< UART registers base address */ + + UART_InitTypeDef Init; /*!< UART communication parameters */ + + UART_AdvFeatureInitTypeDef AdvancedInit; /*!< UART Advanced Features initialization parameters */ + + uint8_t *pTxBuffPtr; /*!< Pointer to UART Tx transfer Buffer */ + + uint16_t TxXferSize; /*!< UART Tx Transfer size */ + + __IO uint16_t TxXferCount; /*!< UART Tx Transfer Counter */ + + uint8_t *pRxBuffPtr; /*!< Pointer to UART Rx transfer Buffer */ + + uint16_t RxXferSize; /*!< UART Rx Transfer size */ + + __IO uint16_t RxXferCount; /*!< UART Rx Transfer Counter */ + + uint16_t Mask; /*!< UART Rx RDR register mask */ + +#if defined(USART_CR1_FIFOEN) + uint16_t NbRxDataToProcess; /*!< Number of data to process during RX ISR execution */ + + uint16_t NbTxDataToProcess; /*!< Number of data to process during TX ISR execution */ + + uint32_t FifoMode; /*!< Specifies if the FIFO mode is being used. + This parameter can be a value of @ref UARTEx_FIFO_mode. */ +#endif + +#if defined(USART_CR2_SLVEN) + uint32_t SlaveMode; /*!< Specifies if the UART SPI Slave mode is being used. + This parameter can be a value of @ref UARTEx_Slave_Mode. */ +#endif + + void (*RxISR)(struct __UART_HandleTypeDef *huart); /*!< Function pointer on Rx IRQ handler */ + + void (*TxISR)(struct __UART_HandleTypeDef *huart); /*!< Function pointer on Tx IRQ handler */ + + DMA_HandleTypeDef *hdmatx; /*!< UART Tx DMA Handle parameters */ + + DMA_HandleTypeDef *hdmarx; /*!< UART Rx DMA Handle parameters */ + + HAL_LockTypeDef Lock; /*!< Locking object */ + + __IO HAL_UART_StateTypeDef gState; /*!< UART state information related to global Handle management + and also related to Tx operations. + This parameter can be a value of @ref HAL_UART_StateTypeDef */ + + __IO HAL_UART_StateTypeDef RxState; /*!< UART state information related to Rx operations. + This parameter can be a value of @ref HAL_UART_StateTypeDef */ + + __IO uint32_t ErrorCode; /*!< UART Error code */ + +}UART_HandleTypeDef; + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup UART_Exported_Constants UART Exported Constants + * @{ + */ + +/** @defgroup UART_Stop_Bits UART Number of Stop Bits + * @{ + */ +#define UART_STOPBITS_0_5 USART_CR2_STOP_0 /*!< UART frame with 0.5 stop bit */ +#define UART_STOPBITS_1 0x00000000U /*!< UART frame with 1 stop bit */ +#define UART_STOPBITS_1_5 (USART_CR2_STOP_0 | USART_CR2_STOP_1) /*!< UART frame with 1.5 stop bits */ +#define UART_STOPBITS_2 USART_CR2_STOP_1 /*!< UART frame with 2 stop bits */ +/** + * @} + */ + +/** @defgroup UART_Parity UART Parity + * @{ + */ +#define UART_PARITY_NONE 0x00000000U /*!< No parity */ +#define UART_PARITY_EVEN USART_CR1_PCE /*!< Even parity */ +#define UART_PARITY_ODD (USART_CR1_PCE | USART_CR1_PS) /*!< Odd parity */ +/** + * @} + */ + +/** @defgroup UART_Hardware_Flow_Control UART Hardware Flow Control + * @{ + */ +#define UART_HWCONTROL_NONE 0x00000000U /*!< No hardware control */ +#define UART_HWCONTROL_RTS USART_CR3_RTSE /*!< Request To Send */ +#define UART_HWCONTROL_CTS USART_CR3_CTSE /*!< Clear To Send */ +#define UART_HWCONTROL_RTS_CTS (USART_CR3_RTSE | USART_CR3_CTSE) /*!< Request and Clear To Send */ +/** + * @} + */ + +/** @defgroup UART_Mode UART Transfer Mode + * @{ + */ +#define UART_MODE_RX USART_CR1_RE /*!< RX mode */ +#define UART_MODE_TX USART_CR1_TE /*!< TX mode */ +#define UART_MODE_TX_RX (USART_CR1_TE |USART_CR1_RE) /*!< RX and TX mode */ +/** + * @} + */ + +/** @defgroup UART_State UART State + * @{ + */ +#define UART_STATE_DISABLE 0x00000000U /*!< UART disabled */ +#define UART_STATE_ENABLE USART_CR1_UE /*!< UART enabled */ +/** + * @} + */ + +/** @defgroup UART_Over_Sampling UART Over Sampling + * @{ + */ +#define UART_OVERSAMPLING_16 0x00000000U /*!< Oversampling by 16 */ +#define UART_OVERSAMPLING_8 USART_CR1_OVER8 /*!< Oversampling by 8 */ +/** + * @} + */ + +/** @defgroup UART_OneBit_Sampling UART One Bit Sampling Method + * @{ + */ +#define UART_ONE_BIT_SAMPLE_DISABLE 0x00000000U /*!< One-bit sampling disable */ +#define UART_ONE_BIT_SAMPLE_ENABLE USART_CR3_ONEBIT /*!< One-bit sampling enable */ +/** + * @} + */ + +#if defined(USART_PRESC_PRESCALER) +/** @defgroup UART_ClockPrescaler UART Clock Prescaler + * @{ + */ +#define UART_PRESCALER_DIV1 0x00000000U /*!< fclk_pres = fclk */ +#define UART_PRESCALER_DIV2 0x00000001U /*!< fclk_pres = fclk/2 */ +#define UART_PRESCALER_DIV4 0x00000002U /*!< fclk_pres = fclk/4 */ +#define UART_PRESCALER_DIV6 0x00000003U /*!< fclk_pres = fclk/6 */ +#define UART_PRESCALER_DIV8 0x00000004U /*!< fclk_pres = fclk/8 */ +#define UART_PRESCALER_DIV10 0x00000005U /*!< fclk_pres = fclk/10 */ +#define UART_PRESCALER_DIV12 0x00000006U /*!< fclk_pres = fclk/12 */ +#define UART_PRESCALER_DIV16 0x00000007U /*!< fclk_pres = fclk/16 */ +#define UART_PRESCALER_DIV32 0x00000008U /*!< fclk_pres = fclk/32 */ +#define UART_PRESCALER_DIV64 0x00000009U /*!< fclk_pres = fclk/64 */ +#define UART_PRESCALER_DIV128 0x0000000AU /*!< fclk_pres = fclk/128 */ +#define UART_PRESCALER_DIV256 0x0000000BU /*!< fclk_pres = fclk/256 */ +/** + * @} + */ +#endif + +/** @defgroup UART_AutoBaud_Rate_Mode UART Advanced Feature AutoBaud Rate Mode + * @{ + */ +#define UART_ADVFEATURE_AUTOBAUDRATE_ONSTARTBIT 0x00000000U /*!< Auto Baud rate detection on start bit */ +#define UART_ADVFEATURE_AUTOBAUDRATE_ONFALLINGEDGE USART_CR2_ABRMODE_0 /*!< Auto Baud rate detection on falling edge */ +#define UART_ADVFEATURE_AUTOBAUDRATE_ON0X7FFRAME USART_CR2_ABRMODE_1 /*!< Auto Baud rate detection on 0x7F frame detection */ +#define UART_ADVFEATURE_AUTOBAUDRATE_ON0X55FRAME USART_CR2_ABRMODE /*!< Auto Baud rate detection on 0x55 frame detection */ +/** + * @} + */ + +/** @defgroup UART_Receiver_TimeOut UART Receiver TimeOut + * @{ + */ +#define UART_RECEIVER_TIMEOUT_DISABLE 0x00000000U /*!< UART receiver timeout disable */ +#define UART_RECEIVER_TIMEOUT_ENABLE USART_CR2_RTOEN /*!< UART receiver timeout enable */ +/** + * @} + */ + +/** @defgroup UART_LIN UART Local Interconnection Network mode + * @{ + */ +#define UART_LIN_DISABLE 0x00000000U /*!< Local Interconnect Network disable */ +#define UART_LIN_ENABLE USART_CR2_LINEN /*!< Local Interconnect Network enable */ +/** + * @} + */ + +/** @defgroup UART_LIN_Break_Detection UART LIN Break Detection + * @{ + */ +#define UART_LINBREAKDETECTLENGTH_10B 0x00000000U /*!< LIN 10-bit break detection length */ +#define UART_LINBREAKDETECTLENGTH_11B USART_CR2_LBDL /*!< LIN 11-bit break detection length */ +/** + * @} + */ + +/** @defgroup UART_DMA_Tx UART DMA Tx + * @{ + */ +#define UART_DMA_TX_DISABLE 0x00000000U /*!< UART DMA TX disabled */ +#define UART_DMA_TX_ENABLE USART_CR3_DMAT /*!< UART DMA TX enabled */ +/** + * @} + */ + +/** @defgroup UART_DMA_Rx UART DMA Rx + * @{ + */ +#define UART_DMA_RX_DISABLE 0x00000000U /*!< UART DMA RX disabled */ +#define UART_DMA_RX_ENABLE USART_CR3_DMAR /*!< UART DMA RX enabled */ +/** + * @} + */ + +/** @defgroup UART_Half_Duplex_Selection UART Half Duplex Selection + * @{ + */ +#define UART_HALF_DUPLEX_DISABLE 0x00000000U /*!< UART half-duplex disabled */ +#define UART_HALF_DUPLEX_ENABLE USART_CR3_HDSEL /*!< UART half-duplex enabled */ +/** + * @} + */ + +/** @defgroup UART_WakeUp_Methods UART WakeUp Methods + * @{ + */ +#define UART_WAKEUPMETHOD_IDLELINE 0x00000000U /*!< UART wake-up on idle line */ +#define UART_WAKEUPMETHOD_ADDRESSMARK USART_CR1_WAKE /*!< UART wake-up on address mark */ +/** + * @} + */ + +/** @defgroup UART_Request_Parameters UART Request Parameters + * @{ + */ +#define UART_AUTOBAUD_REQUEST USART_RQR_ABRRQ /*!< Auto-Baud Rate Request */ +#define UART_SENDBREAK_REQUEST USART_RQR_SBKRQ /*!< Send Break Request */ +#define UART_MUTE_MODE_REQUEST USART_RQR_MMRQ /*!< Mute Mode Request */ +#define UART_RXDATA_FLUSH_REQUEST USART_RQR_RXFRQ /*!< Receive Data flush Request */ +#define UART_TXDATA_FLUSH_REQUEST USART_RQR_TXFRQ /*!< Transmit data flush Request */ +/** + * @} + */ + +/** @defgroup UART_Advanced_Features_Initialization_Type UART Advanced Feature Initialization Type + * @{ + */ +#define UART_ADVFEATURE_NO_INIT 0x00000000U /*!< No advanced feature initialization */ +#define UART_ADVFEATURE_TXINVERT_INIT 0x00000001U /*!< TX pin active level inversion */ +#define UART_ADVFEATURE_RXINVERT_INIT 0x00000002U /*!< RX pin active level inversion */ +#define UART_ADVFEATURE_DATAINVERT_INIT 0x00000004U /*!< Binary data inversion */ +#define UART_ADVFEATURE_SWAP_INIT 0x00000008U /*!< TX/RX pins swap */ +#define UART_ADVFEATURE_RXOVERRUNDISABLE_INIT 0x00000010U /*!< RX overrun disable */ +#define UART_ADVFEATURE_DMADISABLEONERROR_INIT 0x00000020U /*!< DMA disable on Reception Error */ +#define UART_ADVFEATURE_AUTOBAUDRATE_INIT 0x00000040U /*!< Auto Baud rate detection initialization */ +#define UART_ADVFEATURE_MSBFIRST_INIT 0x00000080U /*!< Most significant bit sent/received first */ +/** + * @} + */ + +/** @defgroup UART_Tx_Inv UART Advanced Feature TX Pin Active Level Inversion + * @{ + */ +#define UART_ADVFEATURE_TXINV_DISABLE 0x00000000U /*!< TX pin active level inversion disable */ +#define UART_ADVFEATURE_TXINV_ENABLE USART_CR2_TXINV /*!< TX pin active level inversion enable */ +/** + * @} + */ + +/** @defgroup UART_Rx_Inv UART Advanced Feature RX Pin Active Level Inversion + * @{ + */ +#define UART_ADVFEATURE_RXINV_DISABLE 0x00000000U /*!< RX pin active level inversion disable */ +#define UART_ADVFEATURE_RXINV_ENABLE USART_CR2_RXINV /*!< RX pin active level inversion enable */ +/** + * @} + */ + +/** @defgroup UART_Data_Inv UART Advanced Feature Binary Data Inversion + * @{ + */ +#define UART_ADVFEATURE_DATAINV_DISABLE 0x00000000U /*!< Binary data inversion disable */ +#define UART_ADVFEATURE_DATAINV_ENABLE USART_CR2_DATAINV /*!< Binary data inversion enable */ +/** + * @} + */ + +/** @defgroup UART_Rx_Tx_Swap UART Advanced Feature RX TX Pins Swap + * @{ + */ +#define UART_ADVFEATURE_SWAP_DISABLE 0x00000000U /*!< TX/RX pins swap disable */ +#define UART_ADVFEATURE_SWAP_ENABLE USART_CR2_SWAP /*!< TX/RX pins swap enable */ +/** + * @} + */ + +/** @defgroup UART_Overrun_Disable UART Advanced Feature Overrun Disable + * @{ + */ +#define UART_ADVFEATURE_OVERRUN_ENABLE 0x00000000U /*!< RX overrun enable */ +#define UART_ADVFEATURE_OVERRUN_DISABLE USART_CR3_OVRDIS /*!< RX overrun disable */ +/** + * @} + */ + +/** @defgroup UART_AutoBaudRate_Enable UART Advanced Feature Auto BaudRate Enable + * @{ + */ +#define UART_ADVFEATURE_AUTOBAUDRATE_DISABLE 0x00000000U /*!< RX Auto Baud rate detection enable */ +#define UART_ADVFEATURE_AUTOBAUDRATE_ENABLE USART_CR2_ABREN /*!< RX Auto Baud rate detection disable */ +/** + * @} + */ + +/** @defgroup UART_DMA_Disable_on_Rx_Error UART Advanced Feature DMA Disable On Rx Error + * @{ + */ +#define UART_ADVFEATURE_DMA_ENABLEONRXERROR 0x00000000U /*!< DMA enable on Reception Error */ +#define UART_ADVFEATURE_DMA_DISABLEONRXERROR USART_CR3_DDRE /*!< DMA disable on Reception Error */ +/** + * @} + */ + +/** @defgroup UART_MSB_First UART Advanced Feature MSB First + * @{ + */ +#define UART_ADVFEATURE_MSBFIRST_DISABLE 0x00000000U /*!< Most significant bit sent/received first disable */ +#define UART_ADVFEATURE_MSBFIRST_ENABLE USART_CR2_MSBFIRST /*!< Most significant bit sent/received first enable */ +/** + * @} + */ + +/** @defgroup UART_Stop_Mode_Enable UART Advanced Feature Stop Mode Enable + * @{ + */ +#define UART_ADVFEATURE_STOPMODE_DISABLE 0x00000000U /*!< UART stop mode disable */ +#define UART_ADVFEATURE_STOPMODE_ENABLE USART_CR1_UESM /*!< UART stop mode enable */ +/** + * @} + */ + +/** @defgroup UART_Mute_Mode UART Advanced Feature Mute Mode Enable + * @{ + */ +#define UART_ADVFEATURE_MUTEMODE_DISABLE 0x00000000U /*!< UART mute mode disable */ +#define UART_ADVFEATURE_MUTEMODE_ENABLE USART_CR1_MME /*!< UART mute mode enable */ +/** + * @} + */ + +/** @defgroup UART_CR2_ADDRESS_LSB_POS UART Address-matching LSB Position In CR2 Register + * @{ + */ +#define UART_CR2_ADDRESS_LSB_POS 24U /*!< UART address-matching LSB position in CR2 register */ +/** + * @} + */ + +/** @defgroup UART_WakeUp_from_Stop_Selection UART WakeUp From Stop Selection + * @{ + */ +#define UART_WAKEUP_ON_ADDRESS 0x00000000U /*!< UART wake-up on address */ +#define UART_WAKEUP_ON_STARTBIT USART_CR3_WUS_1 /*!< UART wake-up on start bit */ +#define UART_WAKEUP_ON_READDATA_NONEMPTY USART_CR3_WUS /*!< UART wake-up on receive data register not empty or RXFIFO is not empty */ +/** + * @} + */ + +/** @defgroup UART_DriverEnable_Polarity UART DriverEnable Polarity + * @{ + */ +#define UART_DE_POLARITY_HIGH 0x00000000U /*!< Driver enable signal is active high */ +#define UART_DE_POLARITY_LOW USART_CR3_DEP /*!< Driver enable signal is active low */ +/** + * @} + */ + +/** @defgroup UART_CR1_DEAT_ADDRESS_LSB_POS UART Driver Enable Assertion Time LSB Position In CR1 Register + * @{ + */ +#define UART_CR1_DEAT_ADDRESS_LSB_POS 21U /*!< UART Driver Enable assertion time LSB position in CR1 register */ +/** + * @} + */ + +/** @defgroup UART_CR1_DEDT_ADDRESS_LSB_POS UART Driver Enable DeAssertion Time LSB Position In CR1 Register + * @{ + */ +#define UART_CR1_DEDT_ADDRESS_LSB_POS 16U /*!< UART Driver Enable de-assertion time LSB position in CR1 register */ +/** + * @} + */ + +/** @defgroup UART_Interruption_Mask UART Interruptions Flag Mask + * @{ + */ +#define UART_IT_MASK 0x001FU /*!< UART interruptions flags mask */ +/** + * @} + */ + +/** @defgroup UART_TimeOut_Value UART polling-based communications time-out value + * @{ + */ +#define HAL_UART_TIMEOUT_VALUE 0x1FFFFFFU /*!< UART polling-based communications time-out value */ +/** + * @} + */ + +/** @defgroup UART_Flags UART Status Flags + * Elements values convention: 0xXXXX + * - 0xXXXX : Flag mask in the ISR register + * @{ + */ +#define UART_FLAG_TXFT USART_ISR_TXFT /*!< UART TXFIFO threshold flag */ +#define UART_FLAG_RXFT USART_ISR_RXFT /*!< UART RXFIFO threshold flag */ +#define UART_FLAG_RXFF USART_ISR_RXFF /*!< UART RXFIFO Full flag */ +#define UART_FLAG_TXFE USART_ISR_TXFE /*!< UART TXFIFO Empty flag */ +#define UART_FLAG_REACK USART_ISR_REACK /*!< UART receive enable acknowledge flag */ +#define UART_FLAG_TEACK USART_ISR_TEACK /*!< UART transmit enable acknowledge flag */ +#define UART_FLAG_WUF USART_ISR_WUF /*!< UART wake-up from stop mode flag */ +#define UART_FLAG_RWU USART_ISR_RWU /*!< UART receiver wake-up from mute mode flag */ +#define UART_FLAG_SBKF USART_ISR_SBKF /*!< UART send break flag */ +#define UART_FLAG_CMF USART_ISR_CMF /*!< UART character match flag */ +#define UART_FLAG_BUSY USART_ISR_BUSY /*!< UART busy flag */ +#define UART_FLAG_ABRF USART_ISR_ABRF /*!< UART auto Baud rate flag */ +#define UART_FLAG_ABRE USART_ISR_ABRE /*!< UART auto Baud rate error */ +#define UART_FLAG_CTS USART_ISR_CTS /*!< UART clear to send flag */ +#define UART_FLAG_CTSIF USART_ISR_CTSIF /*!< UART clear to send interrupt flag */ +#define UART_FLAG_LBDF USART_ISR_LBDF /*!< UART LIN break detection flag */ +#if defined(USART_CR1_FIFOEN) +#define UART_FLAG_TXE USART_ISR_TXE_TXFNF /*!< UART transmit data register empty */ +#define UART_FLAG_TXFNF USART_ISR_TXE_TXFNF /*!< UART TXFIFO not full */ +#else +#define UART_FLAG_TXE USART_ISR_TXE /*!< UART transmit data register empty */ +#endif +#define UART_FLAG_TC USART_ISR_TC /*!< UART transmission complete */ +#if defined(USART_CR1_FIFOEN) +#define UART_FLAG_RXNE USART_ISR_RXNE_RXFNE /*!< UART read data register not empty */ +#define UART_FLAG_RXFNE USART_ISR_RXNE_RXFNE /*!< UART RXFIFO not empty */ +#else +#define UART_FLAG_RXNE USART_ISR_RXNE /*!< UART read data register not empty */ +#endif +#define UART_FLAG_IDLE USART_ISR_IDLE /*!< UART idle flag */ +#define UART_FLAG_ORE USART_ISR_ORE /*!< UART overrun error */ +#define UART_FLAG_NE USART_ISR_NE /*!< UART noise error */ +#define UART_FLAG_FE USART_ISR_FE /*!< UART frame error */ +#define UART_FLAG_PE USART_ISR_PE /*!< UART parity error */ +/** + * @} + */ + +/** @defgroup UART_Interrupt_definition UART Interrupts Definition + * Elements values convention: 000ZZZZZ0XXYYYYYb + * - YYYYY : Interrupt source position in the XX register (5bits) + * - XX : Interrupt source register (2bits) + * - 01: CR1 register + * - 10: CR2 register + * - 11: CR3 register + * - ZZZZZ : Flag position in the ISR register(5bits) + * @{ + */ +#define UART_IT_PE 0x0028U /*!< UART parity error interruption */ +#define UART_IT_TXE 0x0727U /*!< UART transmit data register empty interruption */ +#if defined(USART_CR1_FIFOEN) +#define UART_IT_TXFNF 0x0727U /*!< UART TX FIFO not full interruption */ +#endif +#define UART_IT_TC 0x0626U /*!< UART transmission complete interruption */ +#define UART_IT_RXNE 0x0525U /*!< UART read data register not empty interruption */ +#if defined(USART_CR1_FIFOEN) +#define UART_IT_RXFNE 0x0525U /*!< UART RXFIFO not empty interruption */ +#endif +#define UART_IT_IDLE 0x0424U /*!< UART idle interruption */ +#define UART_IT_LBD 0x0846U /*!< UART LIN break detection interruption */ +#define UART_IT_CTS 0x096AU /*!< UART CTS interruption */ +#define UART_IT_CM 0x112EU /*!< UART character match interruption */ +#define UART_IT_WUF 0x1476U /*!< UART wake-up from stop mode interruption */ +#if defined(USART_CR1_FIFOEN) +#define UART_IT_RXFF 0x183FU /*!< UART RXFIFO full interruption */ +#define UART_IT_TXFE 0x173EU /*!< UART TXFIFO empty interruption */ +#define UART_IT_RXFT 0x1A7CU /*!< UART RXFIFO threshold reached interruption */ +#define UART_IT_TXFT 0x1B77U /*!< UART TXFIFO threshold reached interruption */ +#endif + +/* Elements values convention: 000000000XXYYYYYb + - YYYYY : Interrupt source position in the XX register (5bits) + - XX : Interrupt source register (2bits) + - 01: CR1 register + - 10: CR2 register + - 11: CR3 register */ +#define UART_IT_ERR 0x0060U /*!< UART error interruption */ + +/* Elements values convention: 0000ZZZZ00000000b + - ZZZZ : Flag position in the ISR register(4bits) */ +#define UART_IT_ORE 0x0300U /*!< UART overrun error interruption */ +#define UART_IT_NE 0x0200U /*!< UART noise error interruption */ +#define UART_IT_FE 0x0100U /*!< UART frame error interruption */ +/** + * @} + */ + +/** @defgroup UART_IT_CLEAR_Flags UART Interruption Clear Flags + * @{ + */ +#define UART_CLEAR_PEF USART_ICR_PECF /*!< Parity Error Clear Flag */ +#define UART_CLEAR_FEF USART_ICR_FECF /*!< Framing Error Clear Flag */ +#define UART_CLEAR_NEF USART_ICR_NCF /*!< Noise detected Clear Flag */ +#define UART_CLEAR_OREF USART_ICR_ORECF /*!< Overrun Error Clear Flag */ +#define UART_CLEAR_IDLEF USART_ICR_IDLECF /*!< IDLE line detected Clear Flag */ +#if defined(USART_CR1_FIFOEN) +#define UART_CLEAR_TXFECF USART_ICR_TXFECF /*!< TXFIFO empty clear flag */ +#endif +#define UART_CLEAR_TCF USART_ICR_TCCF /*!< Transmission Complete Clear Flag */ +#define UART_CLEAR_LBDF USART_ICR_LBDCF /*!< LIN Break Detection Clear Flag */ +#define UART_CLEAR_CTSF USART_ICR_CTSCF /*!< CTS Interrupt Clear Flag */ +#define UART_CLEAR_CMF USART_ICR_CMCF /*!< Character Match Clear Flag */ +#define UART_CLEAR_WUF USART_ICR_WUCF /*!< Wake Up from stop mode Clear Flag */ +/** + * @} + */ + + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ +/** @defgroup UART_Exported_Macros UART Exported Macros + * @{ + */ + +/** @brief Reset UART handle states. + * @param __HANDLE__ UART handle. + * @retval None + */ +#define __HAL_UART_RESET_HANDLE_STATE(__HANDLE__) do{ \ + (__HANDLE__)->gState = HAL_UART_STATE_RESET; \ + (__HANDLE__)->RxState = HAL_UART_STATE_RESET; \ + } while(0) +/** @brief Flush the UART Data registers. + * @param __HANDLE__ specifies the UART Handle. + * @retval None + */ +#define __HAL_UART_FLUSH_DRREGISTER(__HANDLE__) \ + do{ \ + SET_BIT((__HANDLE__)->Instance->RQR, UART_RXDATA_FLUSH_REQUEST); \ + SET_BIT((__HANDLE__)->Instance->RQR, UART_TXDATA_FLUSH_REQUEST); \ + } while(0) + +/** @brief Clear the specified UART pending flag. + * @param __HANDLE__ specifies the UART Handle. + * @param __FLAG__ specifies the flag to check. + * This parameter can be any combination of the following values: + * @arg @ref UART_CLEAR_PEF Parity Error Clear Flag + * @arg @ref UART_CLEAR_FEF Framing Error Clear Flag + * @arg @ref UART_CLEAR_NEF Noise detected Clear Flag + * @arg @ref UART_CLEAR_OREF Overrun Error Clear Flag + * @arg @ref UART_CLEAR_IDLEF IDLE line detected Clear Flag + * @arg @ref UART_CLEAR_TXFECF TXFIFO empty clear Flag + * @arg @ref UART_CLEAR_TCF Transmission Complete Clear Flag + * @arg @ref UART_CLEAR_LBDF LIN Break Detection Clear Flag + * @arg @ref UART_CLEAR_CTSF CTS Interrupt Clear Flag + * @arg @ref UART_CLEAR_CMF Character Match Clear Flag + * @arg @ref UART_CLEAR_WUF Wake Up from stop mode Clear Flag + * @retval None + */ +#define __HAL_UART_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->ICR = (__FLAG__)) + +/** @brief Clear the UART PE pending flag. + * @param __HANDLE__ specifies the UART Handle. + * @retval None + */ +#define __HAL_UART_CLEAR_PEFLAG(__HANDLE__) __HAL_UART_CLEAR_FLAG((__HANDLE__), UART_CLEAR_PEF) + +/** @brief Clear the UART FE pending flag. + * @param __HANDLE__ specifies the UART Handle. + * @retval None + */ +#define __HAL_UART_CLEAR_FEFLAG(__HANDLE__) __HAL_UART_CLEAR_FLAG((__HANDLE__), UART_CLEAR_FEF) + +/** @brief Clear the UART NE pending flag. + * @param __HANDLE__ specifies the UART Handle. + * @retval None + */ +#define __HAL_UART_CLEAR_NEFLAG(__HANDLE__) __HAL_UART_CLEAR_FLAG((__HANDLE__), UART_CLEAR_NEF) + +/** @brief Clear the UART ORE pending flag. + * @param __HANDLE__ specifies the UART Handle. + * @retval None + */ +#define __HAL_UART_CLEAR_OREFLAG(__HANDLE__) __HAL_UART_CLEAR_FLAG((__HANDLE__), UART_CLEAR_OREF) + +/** @brief Clear the UART IDLE pending flag. + * @param __HANDLE__ specifies the UART Handle. + * @retval None + */ +#define __HAL_UART_CLEAR_IDLEFLAG(__HANDLE__) __HAL_UART_CLEAR_FLAG((__HANDLE__), UART_CLEAR_IDLEF) + +#if defined(USART_CR1_FIFOEN) +/** @brief Clear the UART TX FIFO empty clear flag. + * @param __HANDLE__ specifies the UART Handle. + * @retval None + */ +#define __HAL_UART_CLEAR_TXFECF(__HANDLE__) __HAL_UART_CLEAR_FLAG((__HANDLE__), UART_CLEAR_TXFECF) +#endif + +/** @brief Check whether the specified UART flag is set or not. + * @param __HANDLE__ specifies the UART Handle. + * @param __FLAG__ specifies the flag to check. + * This parameter can be one of the following values: + * @arg @ref UART_FLAG_TXFT TXFIFO threshold flag + * @arg @ref UART_FLAG_RXFT RXFIFO threshold flag + * @arg @ref UART_FLAG_RXFF RXFIFO Full flag + * @arg @ref UART_FLAG_TXFE TXFIFO Empty flag + * @arg @ref UART_FLAG_REACK Receive enable acknowledge flag + * @arg @ref UART_FLAG_TEACK Transmit enable acknowledge flag + * @arg @ref UART_FLAG_WUF Wake up from stop mode flag + * @arg @ref UART_FLAG_RWU Receiver wake up flag (if the UART in mute mode) + * @arg @ref UART_FLAG_SBKF Send Break flag + * @arg @ref UART_FLAG_CMF Character match flag + * @arg @ref UART_FLAG_BUSY Busy flag + * @arg @ref UART_FLAG_ABRF Auto Baud rate detection flag + * @arg @ref UART_FLAG_ABRE Auto Baud rate detection error flag + * @arg @ref UART_FLAG_CTS CTS Change flag + * @arg @ref UART_FLAG_LBDF LIN Break detection flag + * @arg @ref UART_FLAG_TXE Transmit data register empty flag + * @arg @ref UART_FLAG_TXFNF UART TXFIFO not full flag + * @arg @ref UART_FLAG_TC Transmission Complete flag + * @arg @ref UART_FLAG_RXNE Receive data register not empty flag + * @arg @ref UART_FLAG_RXFNE UART RXFIFO not empty flag + * @arg @ref UART_FLAG_IDLE Idle Line detection flag + * @arg @ref UART_FLAG_ORE Overrun Error flag + * @arg @ref UART_FLAG_NE Noise Error flag + * @arg @ref UART_FLAG_FE Framing Error flag + * @arg @ref UART_FLAG_PE Parity Error flag + * @retval The new state of __FLAG__ (TRUE or FALSE). + */ +#define __HAL_UART_GET_FLAG(__HANDLE__, __FLAG__) (((__HANDLE__)->Instance->ISR & (__FLAG__)) == (__FLAG__)) + +/** @brief Enable the specified UART interrupt. + * @param __HANDLE__ specifies the UART Handle. + * @param __INTERRUPT__ specifies the UART interrupt source to enable. + * This parameter can be one of the following values: + * @arg @ref UART_IT_RXFF RXFIFO Full interrupt + * @arg @ref UART_IT_TXFE TXFIFO Empty interrupt + * @arg @ref UART_IT_RXFT RXFIFO threshold interrupt + * @arg @ref UART_IT_TXFT TXFIFO threshold interrupt + * @arg @ref UART_IT_WUF Wakeup from stop mode interrupt + * @arg @ref UART_IT_CM Character match interrupt + * @arg @ref UART_IT_CTS CTS change interrupt + * @arg @ref UART_IT_LBD LIN Break detection interrupt + * @arg @ref UART_IT_TXE Transmit Data Register empty interrupt + * @arg @ref UART_IT_TXFNF TX FIFO not full interrupt + * @arg @ref UART_IT_TC Transmission complete interrupt + * @arg @ref UART_IT_RXNE Receive Data register not empty interrupt + * @arg @ref UART_IT_RXFNE RXFIFO not empty interrupt + * @arg @ref UART_IT_IDLE Idle line detection interrupt + * @arg @ref UART_IT_PE Parity Error interrupt + * @arg @ref UART_IT_ERR Error interrupt (Frame error, noise error, overrun error) + * @retval None + */ +#define __HAL_UART_ENABLE_IT(__HANDLE__, __INTERRUPT__) (((((uint8_t)(__INTERRUPT__)) >> 5U) == 1U)? ((__HANDLE__)->Instance->CR1 |= (1U << ((__INTERRUPT__) & UART_IT_MASK))): \ + ((((uint8_t)(__INTERRUPT__)) >> 5U) == 2U)? ((__HANDLE__)->Instance->CR2 |= (1U << ((__INTERRUPT__) & UART_IT_MASK))): \ + ((__HANDLE__)->Instance->CR3 |= (1U << ((__INTERRUPT__) & UART_IT_MASK)))) + + +/** @brief Disable the specified UART interrupt. + * @param __HANDLE__ specifies the UART Handle. + * @param __INTERRUPT__ specifies the UART interrupt source to disable. + * This parameter can be one of the following values: + * @arg @ref UART_IT_RXFF RXFIFO Full interrupt + * @arg @ref UART_IT_TXFE TXFIFO Empty interrupt + * @arg @ref UART_IT_RXFT RXFIFO threshold interrupt + * @arg @ref UART_IT_TXFT TXFIFO threshold interrupt + * @arg @ref UART_IT_WUF Wakeup from stop mode interrupt + * @arg @ref UART_IT_CM Character match interrupt + * @arg @ref UART_IT_CTS CTS change interrupt + * @arg @ref UART_IT_LBD LIN Break detection interrupt + * @arg @ref UART_IT_TXE Transmit Data Register empty interrupt + * @arg @ref UART_IT_TXFNF TX FIFO not full interrupt + * @arg @ref UART_IT_TC Transmission complete interrupt + * @arg @ref UART_IT_RXNE Receive Data register not empty interrupt + * @arg @ref UART_IT_RXFNE RXFIFO not empty interrupt + * @arg @ref UART_IT_IDLE Idle line detection interrupt + * @arg @ref UART_IT_PE Parity Error interrupt + * @arg @ref UART_IT_ERR Error interrupt (Frame error, noise error, overrun error) + * @retval None + */ +#define __HAL_UART_DISABLE_IT(__HANDLE__, __INTERRUPT__) (((((uint8_t)(__INTERRUPT__)) >> 5U) == 1U)? ((__HANDLE__)->Instance->CR1 &= ~ (1U << ((__INTERRUPT__) & UART_IT_MASK))): \ + ((((uint8_t)(__INTERRUPT__)) >> 5U) == 2U)? ((__HANDLE__)->Instance->CR2 &= ~ (1U << ((__INTERRUPT__) & UART_IT_MASK))): \ + ((__HANDLE__)->Instance->CR3 &= ~ (1U << ((__INTERRUPT__) & UART_IT_MASK)))) + +/** @brief Check whether the specified UART interrupt has occurred or not. + * @param __HANDLE__ specifies the UART Handle. + * @param __INTERRUPT__ specifies the UART interrupt to check. + * This parameter can be one of the following values: + * @arg @ref UART_IT_RXFF RXFIFO Full interrupt + * @arg @ref UART_IT_TXFE TXFIFO Empty interrupt + * @arg @ref UART_IT_RXFT RXFIFO threshold interrupt + * @arg @ref UART_IT_TXFT TXFIFO threshold interrupt + * @arg @ref UART_IT_WUF Wakeup from stop mode interrupt + * @arg @ref UART_IT_CM Character match interrupt + * @arg @ref UART_IT_CTS CTS change interrupt + * @arg @ref UART_IT_LBD LIN Break detection interrupt + * @arg @ref UART_IT_TXE Transmit Data Register empty interrupt + * @arg @ref UART_IT_TXFNF TX FIFO not full interrupt + * @arg @ref UART_IT_TC Transmission complete interrupt + * @arg @ref UART_IT_RXNE Receive Data register not empty interrupt + * @arg @ref UART_IT_RXFNE RXFIFO not empty interrupt + * @arg @ref UART_IT_IDLE Idle line detection interrupt + * @arg @ref UART_IT_PE Parity Error interrupt + * @arg @ref UART_IT_ERR Error interrupt (Frame error, noise error, overrun error) + * @retval The new state of __INTERRUPT__ (SET or RESET). + */ +#define __HAL_UART_GET_IT(__HANDLE__, __INTERRUPT__) ((((__HANDLE__)->Instance->ISR & (1U << ((__INTERRUPT__)>> 8U))) != RESET) ? SET : RESET) + +/** @brief Check whether the specified UART interrupt source is enabled or not. + * @param __HANDLE__ specifies the UART Handle. + * @param __INTERRUPT__ specifies the UART interrupt source to check. + * This parameter can be one of the following values: + * @arg @ref UART_IT_RXFF RXFIFO Full interrupt + * @arg @ref UART_IT_TXFE TXFIFO Empty interrupt + * @arg @ref UART_IT_RXFT RXFIFO threshold interrupt + * @arg @ref UART_IT_TXFT TXFIFO threshold interrupt + * @arg @ref UART_IT_WUF Wakeup from stop mode interrupt + * @arg @ref UART_IT_CM Character match interrupt + * @arg @ref UART_IT_CTS CTS change interrupt + * @arg @ref UART_IT_LBD LIN Break detection interrupt + * @arg @ref UART_IT_TXE Transmit Data Register empty interrupt + * @arg @ref UART_IT_TXFNF TX FIFO not full interrupt + * @arg @ref UART_IT_TC Transmission complete interrupt + * @arg @ref UART_IT_RXNE Receive Data register not empty interrupt + * @arg @ref UART_IT_RXFNE RXFIFO not empty interrupt + * @arg @ref UART_IT_IDLE Idle line detection interrupt + * @arg @ref UART_IT_PE Parity Error interrupt + * @arg @ref UART_IT_ERR Error interrupt (Frame error, noise error, overrun error) + * @retval The new state of __INTERRUPT__ (SET or RESET). + */ +#define __HAL_UART_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) ((((((((uint8_t)(__INTERRUPT__)) >> 5U) == 1U) ? (__HANDLE__)->Instance->CR1 : \ + (((((uint8_t)(__INTERRUPT__)) >> 5U) == 2U) ? (__HANDLE__)->Instance->CR2 : \ + (__HANDLE__)->Instance->CR3)) & (1U << (((uint16_t)(__INTERRUPT__)) & UART_IT_MASK))) != RESET) ? SET : RESET) + +/** @brief Clear the specified UART ISR flag, in setting the proper ICR register flag. + * @param __HANDLE__ specifies the UART Handle. + * @param __IT_CLEAR__ specifies the interrupt clear register flag that needs to be set + * to clear the corresponding interrupt + * This parameter can be one of the following values: + * @arg @ref UART_CLEAR_PEF Parity Error Clear Flag + * @arg @ref UART_CLEAR_FEF Framing Error Clear Flag + * @arg @ref UART_CLEAR_NEF Noise detected Clear Flag + * @arg @ref UART_CLEAR_OREF Overrun Error Clear Flag + * @arg @ref UART_CLEAR_IDLEF IDLE line detected Clear Flag + * @arg @ref UART_CLEAR_TXFECF TXFIFO empty Clear Flag + * @arg @ref UART_CLEAR_TCF Transmission Complete Clear Flag + * @arg @ref UART_CLEAR_LBDF LIN Break Detection Clear Flag + * @arg @ref UART_CLEAR_CTSF CTS Interrupt Clear Flag + * @arg @ref UART_CLEAR_CMF Character Match Clear Flag + * @arg @ref UART_CLEAR_WUF Wake Up from stop mode Clear Flag + * @retval None + */ +#define __HAL_UART_CLEAR_IT(__HANDLE__, __IT_CLEAR__) ((__HANDLE__)->Instance->ICR = (uint32_t)(__IT_CLEAR__)) + +/** @brief Set a specific UART request flag. + * @param __HANDLE__ specifies the UART Handle. + * @param __REQ__ specifies the request flag to set + * This parameter can be one of the following values: + * @arg @ref UART_AUTOBAUD_REQUEST Auto-Baud Rate Request + * @arg @ref UART_SENDBREAK_REQUEST Send Break Request + * @arg @ref UART_MUTE_MODE_REQUEST Mute Mode Request + * @arg @ref UART_RXDATA_FLUSH_REQUEST Receive Data flush Request + * @arg @ref UART_TXDATA_FLUSH_REQUEST Transmit data flush Request + * @retval None + */ +#define __HAL_UART_SEND_REQ(__HANDLE__, __REQ__) ((__HANDLE__)->Instance->RQR |= (__REQ__)) + +/** @brief Enable the UART one bit sample method. + * @param __HANDLE__ specifies the UART Handle. + * @retval None + */ +#define __HAL_UART_ONE_BIT_SAMPLE_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR3|= USART_CR3_ONEBIT) + +/** @brief Disable the UART one bit sample method. + * @param __HANDLE__ specifies the UART Handle. + * @retval None + */ +#define __HAL_UART_ONE_BIT_SAMPLE_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR3 &= ~USART_CR3_ONEBIT) + +/** @brief Enable UART. + * @param __HANDLE__ specifies the UART Handle. + * @retval None + */ +#define __HAL_UART_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR1 |= USART_CR1_UE) + +/** @brief Disable UART. + * @param __HANDLE__ specifies the UART Handle. + * @retval None + */ +#define __HAL_UART_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR1 &= ~USART_CR1_UE) + +/** @brief Enable CTS flow control. + * @note This macro allows to enable CTS hardware flow control for a given UART instance, + * without need to call HAL_UART_Init() function. + * As involving direct access to UART registers, usage of this macro should be fully endorsed by user. + * @note As macro is expected to be used for modifying CTS Hw flow control feature activation, without need + * for USART instance Deinit/Init, following conditions for macro call should be fulfilled : + * - UART instance should have already been initialised (through call of HAL_UART_Init() ) + * - macro could only be called when corresponding UART instance is disabled (i.e. __HAL_UART_DISABLE(__HANDLE__)) + * and should be followed by an Enable macro (i.e. __HAL_UART_ENABLE(__HANDLE__)). + * @param __HANDLE__ specifies the UART Handle. + * @retval None + */ +#define __HAL_UART_HWCONTROL_CTS_ENABLE(__HANDLE__) \ + do{ \ + SET_BIT((__HANDLE__)->Instance->CR3, USART_CR3_CTSE); \ + (__HANDLE__)->Init.HwFlowCtl |= USART_CR3_CTSE; \ + } while(0) + +/** @brief Disable CTS flow control. + * @note This macro allows to disable CTS hardware flow control for a given UART instance, + * without need to call HAL_UART_Init() function. + * As involving direct access to UART registers, usage of this macro should be fully endorsed by user. + * @note As macro is expected to be used for modifying CTS Hw flow control feature activation, without need + * for USART instance Deinit/Init, following conditions for macro call should be fulfilled : + * - UART instance should have already been initialised (through call of HAL_UART_Init() ) + * - macro could only be called when corresponding UART instance is disabled (i.e. __HAL_UART_DISABLE(__HANDLE__)) + * and should be followed by an Enable macro (i.e. __HAL_UART_ENABLE(__HANDLE__)). + * @param __HANDLE__ specifies the UART Handle. + * @retval None + */ +#define __HAL_UART_HWCONTROL_CTS_DISABLE(__HANDLE__) \ + do{ \ + CLEAR_BIT((__HANDLE__)->Instance->CR3, USART_CR3_CTSE); \ + (__HANDLE__)->Init.HwFlowCtl &= ~(USART_CR3_CTSE); \ + } while(0) + +/** @brief Enable RTS flow control. + * @note This macro allows to enable RTS hardware flow control for a given UART instance, + * without need to call HAL_UART_Init() function. + * As involving direct access to UART registers, usage of this macro should be fully endorsed by user. + * @note As macro is expected to be used for modifying RTS Hw flow control feature activation, without need + * for USART instance Deinit/Init, following conditions for macro call should be fulfilled : + * - UART instance should have already been initialised (through call of HAL_UART_Init() ) + * - macro could only be called when corresponding UART instance is disabled (i.e. __HAL_UART_DISABLE(__HANDLE__)) + * and should be followed by an Enable macro (i.e. __HAL_UART_ENABLE(__HANDLE__)). + * @param __HANDLE__ specifies the UART Handle. + * @retval None + */ +#define __HAL_UART_HWCONTROL_RTS_ENABLE(__HANDLE__) \ + do{ \ + SET_BIT((__HANDLE__)->Instance->CR3, USART_CR3_RTSE); \ + (__HANDLE__)->Init.HwFlowCtl |= USART_CR3_RTSE; \ + } while(0) + +/** @brief Disable RTS flow control. + * @note This macro allows to disable RTS hardware flow control for a given UART instance, + * without need to call HAL_UART_Init() function. + * As involving direct access to UART registers, usage of this macro should be fully endorsed by user. + * @note As macro is expected to be used for modifying RTS Hw flow control feature activation, without need + * for USART instance Deinit/Init, following conditions for macro call should be fulfilled : + * - UART instance should have already been initialised (through call of HAL_UART_Init() ) + * - macro could only be called when corresponding UART instance is disabled (i.e. __HAL_UART_DISABLE(__HANDLE__)) + * and should be followed by an Enable macro (i.e. __HAL_UART_ENABLE(__HANDLE__)). + * @param __HANDLE__ specifies the UART Handle. + * @retval None + */ +#define __HAL_UART_HWCONTROL_RTS_DISABLE(__HANDLE__) \ + do{ \ + CLEAR_BIT((__HANDLE__)->Instance->CR3, USART_CR3_RTSE);\ + (__HANDLE__)->Init.HwFlowCtl &= ~(USART_CR3_RTSE); \ + } while(0) +/** + * @} + */ + +/* Private variables -----------------------------------------------------*/ +#if defined(USART_PRESC_PRESCALER) +/** @defgroup UART_Private_Variables UART Private Variables + * @{ + */ +static const uint16_t UARTPrescTable[12] = {1, 2, 4, 6, 8, 10, 12, 16, 32, 64, 128, 256}; +/** + * @} + */ +#endif + +/* Private macros --------------------------------------------------------*/ +/** @defgroup UART_Private_Macros UART Private Macros + * @{ + */ +#if defined(USART_PRESC_PRESCALER) + +/** @brief BRR division operation to set BRR register with LPUART. + * @param __PCLK__ LPUART clock. + * @param __BAUD__ Baud rate set by the user. + * @param __CLOCKPRESCALER__ UART prescaler value. + * @retval Division result + */ +#define UART_DIV_LPUART(__PCLK__, __BAUD__, __CLOCKPRESCALER__) ((((((uint64_t)(__PCLK__)/UARTPrescTable[(__CLOCKPRESCALER__)])*256)) + ((__BAUD__)/2)) / (__BAUD__)) + +/** @brief BRR division operation to set BRR register in 8-bit oversampling mode. + * @param __PCLK__ UART clock. + * @param __BAUD__ Baud rate set by the user. + * @param __CLOCKPRESCALER__ UART prescaler value. + * @retval Division result + */ +#define UART_DIV_SAMPLING8(__PCLK__, __BAUD__, __CLOCKPRESCALER__) (((((__PCLK__)/UARTPrescTable[(__CLOCKPRESCALER__)])*2) + ((__BAUD__)/2)) / (__BAUD__)) + +/** @brief BRR division operation to set BRR register in 16-bit oversampling mode. + * @param __PCLK__ UART clock. + * @param __BAUD__ Baud rate set by the user. + * @param __CLOCKPRESCALER__ UART prescaler value. + * @retval Division result + */ +#define UART_DIV_SAMPLING16(__PCLK__, __BAUD__, __CLOCKPRESCALER__) ((((__PCLK__)/UARTPrescTable[(__CLOCKPRESCALER__)]) + ((__BAUD__)/2)) / (__BAUD__)) + +#else + +/** @brief BRR division operation to set BRR register with LPUART. + * @param __PCLK__ LPUART clock. + * @param __BAUD__ Baud rate set by the user. + * @retval Division result + */ +#define UART_DIV_LPUART(__PCLK__, __BAUD__) (((((uint64_t)(__PCLK__)*256)) + ((__BAUD__)/2)) / (__BAUD__)) + +/** @brief BRR division operation to set BRR register in 8-bit oversampling mode. + * @param __PCLK__ UART clock. + * @param __BAUD__ Baud rate set by the user. + * @retval Division result + */ +#define UART_DIV_SAMPLING8(__PCLK__, __BAUD__) ((((__PCLK__)*2) + ((__BAUD__)/2)) / (__BAUD__)) + +/** @brief BRR division operation to set BRR register in 16-bit oversampling mode. + * @param __PCLK__ UART clock. + * @param __BAUD__ Baud rate set by the user. + * @retval Division result + */ +#define UART_DIV_SAMPLING16(__PCLK__, __BAUD__) (((__PCLK__) + ((__BAUD__)/2)) / (__BAUD__)) + +#endif /* USART_PRESC_PRESCALER */ + +/** @brief Check whether or not UART instance is Low Power UART. + * @param __HANDLE__ specifies the UART Handle. + * @retval SET (instance is LPUART) or RESET (instance isn't LPUART) + */ +#define UART_INSTANCE_LOWPOWER(__HANDLE__) (IS_LPUART_INSTANCE(__HANDLE__->Instance)) + +/** @brief Check UART Baud rate. + * @param __BAUDRATE__ Baudrate specified by the user. + * The maximum Baud Rate is derived from the maximum clock on G0 (i.e. 52 MHz) + * divided by the smallest oversampling used on the USART (i.e. 8) + * @retval SET (__BAUDRATE__ is valid) or RESET (__BAUDRATE__ is invalid) + */ +#define IS_UART_BAUDRATE(__BAUDRATE__) ((__BAUDRATE__) < 6500001U) + +/** @brief Check UART assertion time. + * @param __TIME__ 5-bit value assertion time. + * @retval Test result (TRUE or FALSE). + */ +#define IS_UART_ASSERTIONTIME(__TIME__) ((__TIME__) <= 0x1FU) + +/** @brief Check UART deassertion time. + * @param __TIME__ 5-bit value deassertion time. + * @retval Test result (TRUE or FALSE). + */ +#define IS_UART_DEASSERTIONTIME(__TIME__) ((__TIME__) <= 0x1FU) + +/** + * @brief Ensure that UART frame number of stop bits is valid. + * @param __STOPBITS__ UART frame number of stop bits. + * @retval SET (__STOPBITS__ is valid) or RESET (__STOPBITS__ is invalid) + */ +#define IS_UART_STOPBITS(__STOPBITS__) (((__STOPBITS__) == UART_STOPBITS_0_5) || \ + ((__STOPBITS__) == UART_STOPBITS_1) || \ + ((__STOPBITS__) == UART_STOPBITS_1_5) || \ + ((__STOPBITS__) == UART_STOPBITS_2)) + +/** + * @brief Ensure that LPUART frame number of stop bits is valid. + * @param __STOPBITS__ LPUART frame number of stop bits. + * @retval SET (__STOPBITS__ is valid) or RESET (__STOPBITS__ is invalid) + */ +#define IS_LPUART_STOPBITS(__STOPBITS__) (((__STOPBITS__) == UART_STOPBITS_1) || \ + ((__STOPBITS__) == UART_STOPBITS_2)) + +/** + * @brief Ensure that UART frame parity is valid. + * @param __PARITY__ UART frame parity. + * @retval SET (__PARITY__ is valid) or RESET (__PARITY__ is invalid) + */ +#define IS_UART_PARITY(__PARITY__) (((__PARITY__) == UART_PARITY_NONE) || \ + ((__PARITY__) == UART_PARITY_EVEN) || \ + ((__PARITY__) == UART_PARITY_ODD)) + +/** + * @brief Ensure that UART hardware flow control is valid. + * @param __CONTROL__ UART hardware flow control. + * @retval SET (__CONTROL__ is valid) or RESET (__CONTROL__ is invalid) + */ +#define IS_UART_HARDWARE_FLOW_CONTROL(__CONTROL__)\ + (((__CONTROL__) == UART_HWCONTROL_NONE) || \ + ((__CONTROL__) == UART_HWCONTROL_RTS) || \ + ((__CONTROL__) == UART_HWCONTROL_CTS) || \ + ((__CONTROL__) == UART_HWCONTROL_RTS_CTS)) + +/** + * @brief Ensure that UART communication mode is valid. + * @param __MODE__ UART communication mode. + * @retval SET (__MODE__ is valid) or RESET (__MODE__ is invalid) + */ +#define IS_UART_MODE(__MODE__) ((((__MODE__) & (~((uint32_t)(UART_MODE_TX_RX)))) == 0x00U) && ((__MODE__) != 0x00U)) + +/** + * @brief Ensure that UART state is valid. + * @param __STATE__ UART state. + * @retval SET (__STATE__ is valid) or RESET (__STATE__ is invalid) + */ +#define IS_UART_STATE(__STATE__) (((__STATE__) == UART_STATE_DISABLE) || \ + ((__STATE__) == UART_STATE_ENABLE)) + +/** + * @brief Ensure that UART oversampling is valid. + * @param __SAMPLING__ UART oversampling. + * @retval SET (__SAMPLING__ is valid) or RESET (__SAMPLING__ is invalid) + */ +#define IS_UART_OVERSAMPLING(__SAMPLING__) (((__SAMPLING__) == UART_OVERSAMPLING_16) || \ + ((__SAMPLING__) == UART_OVERSAMPLING_8)) + +/** + * @brief Ensure that UART frame sampling is valid. + * @param __ONEBIT__ UART frame sampling. + * @retval SET (__ONEBIT__ is valid) or RESET (__ONEBIT__ is invalid) + */ +#define IS_UART_ONE_BIT_SAMPLE(__ONEBIT__) (((__ONEBIT__) == UART_ONE_BIT_SAMPLE_DISABLE) || \ + ((__ONEBIT__) == UART_ONE_BIT_SAMPLE_ENABLE)) + +/** + * @brief Ensure that UART auto Baud rate detection mode is valid. + * @param __MODE__ UART auto Baud rate detection mode. + * @retval SET (__MODE__ is valid) or RESET (__MODE__ is invalid) + */ +#define IS_UART_ADVFEATURE_AUTOBAUDRATEMODE(__MODE__) (((__MODE__) == UART_ADVFEATURE_AUTOBAUDRATE_ONSTARTBIT) || \ + ((__MODE__) == UART_ADVFEATURE_AUTOBAUDRATE_ONFALLINGEDGE) || \ + ((__MODE__) == UART_ADVFEATURE_AUTOBAUDRATE_ON0X7FFRAME) || \ + ((__MODE__) == UART_ADVFEATURE_AUTOBAUDRATE_ON0X55FRAME)) + +/** + * @brief Ensure that UART receiver timeout setting is valid. + * @param __TIMEOUT__ UART receiver timeout setting. + * @retval SET (__TIMEOUT__ is valid) or RESET (__TIMEOUT__ is invalid) + */ +#define IS_UART_RECEIVER_TIMEOUT(__TIMEOUT__) (((__TIMEOUT__) == UART_RECEIVER_TIMEOUT_DISABLE) || \ + ((__TIMEOUT__) == UART_RECEIVER_TIMEOUT_ENABLE)) + +/** + * @brief Ensure that UART LIN state is valid. + * @param __LIN__ UART LIN state. + * @retval SET (__LIN__ is valid) or RESET (__LIN__ is invalid) + */ +#define IS_UART_LIN(__LIN__) (((__LIN__) == UART_LIN_DISABLE) || \ + ((__LIN__) == UART_LIN_ENABLE)) + +/** + * @brief Ensure that UART LIN break detection length is valid. + * @param __LENGTH__ UART LIN break detection length. + * @retval SET (__LENGTH__ is valid) or RESET (__LENGTH__ is invalid) + */ +#define IS_UART_LIN_BREAK_DETECT_LENGTH(__LENGTH__) (((__LENGTH__) == UART_LINBREAKDETECTLENGTH_10B) || \ + ((__LENGTH__) == UART_LINBREAKDETECTLENGTH_11B)) + +/** + * @brief Ensure that UART DMA TX state is valid. + * @param __DMATX__ UART DMA TX state. + * @retval SET (__DMATX__ is valid) or RESET (__DMATX__ is invalid) + */ +#define IS_UART_DMA_TX(__DMATX__) (((__DMATX__) == UART_DMA_TX_DISABLE) || \ + ((__DMATX__) == UART_DMA_TX_ENABLE)) + +/** + * @brief Ensure that UART DMA RX state is valid. + * @param __DMARX__ UART DMA RX state. + * @retval SET (__DMARX__ is valid) or RESET (__DMARX__ is invalid) + */ +#define IS_UART_DMA_RX(__DMARX__) (((__DMARX__) == UART_DMA_RX_DISABLE) || \ + ((__DMARX__) == UART_DMA_RX_ENABLE)) + +/** + * @brief Ensure that UART half-duplex state is valid. + * @param __HDSEL__ UART half-duplex state. + * @retval SET (__HDSEL__ is valid) or RESET (__HDSEL__ is invalid) + */ +#define IS_UART_HALF_DUPLEX(__HDSEL__) (((__HDSEL__) == UART_HALF_DUPLEX_DISABLE) || \ + ((__HDSEL__) == UART_HALF_DUPLEX_ENABLE)) + +/** + * @brief Ensure that UART wake-up method is valid. + * @param __WAKEUP__ UART wake-up method . + * @retval SET (__WAKEUP__ is valid) or RESET (__WAKEUP__ is invalid) + */ +#define IS_UART_WAKEUPMETHOD(__WAKEUP__) (((__WAKEUP__) == UART_WAKEUPMETHOD_IDLELINE) || \ + ((__WAKEUP__) == UART_WAKEUPMETHOD_ADDRESSMARK)) + +/** + * @brief Ensure that UART request parameter is valid. + * @param __PARAM__ UART request parameter. + * @retval SET (__PARAM__ is valid) or RESET (__PARAM__ is invalid) + */ +#define IS_UART_REQUEST_PARAMETER(__PARAM__) (((__PARAM__) == UART_AUTOBAUD_REQUEST) || \ + ((__PARAM__) == UART_SENDBREAK_REQUEST) || \ + ((__PARAM__) == UART_MUTE_MODE_REQUEST) || \ + ((__PARAM__) == UART_RXDATA_FLUSH_REQUEST) || \ + ((__PARAM__) == UART_TXDATA_FLUSH_REQUEST)) + +/** + * @brief Ensure that UART advanced features initialization is valid. + * @param __INIT__ UART advanced features initialization. + * @retval SET (__INIT__ is valid) or RESET (__INIT__ is invalid) + */ +#define IS_UART_ADVFEATURE_INIT(__INIT__) ((__INIT__) <= (UART_ADVFEATURE_NO_INIT | \ + UART_ADVFEATURE_TXINVERT_INIT | \ + UART_ADVFEATURE_RXINVERT_INIT | \ + UART_ADVFEATURE_DATAINVERT_INIT | \ + UART_ADVFEATURE_SWAP_INIT | \ + UART_ADVFEATURE_RXOVERRUNDISABLE_INIT | \ + UART_ADVFEATURE_DMADISABLEONERROR_INIT | \ + UART_ADVFEATURE_AUTOBAUDRATE_INIT | \ + UART_ADVFEATURE_MSBFIRST_INIT)) + +/** + * @brief Ensure that UART frame TX inversion setting is valid. + * @param __TXINV__ UART frame TX inversion setting. + * @retval SET (__TXINV__ is valid) or RESET (__TXINV__ is invalid) + */ +#define IS_UART_ADVFEATURE_TXINV(__TXINV__) (((__TXINV__) == UART_ADVFEATURE_TXINV_DISABLE) || \ + ((__TXINV__) == UART_ADVFEATURE_TXINV_ENABLE)) + +/** + * @brief Ensure that UART frame RX inversion setting is valid. + * @param __RXINV__ UART frame RX inversion setting. + * @retval SET (__RXINV__ is valid) or RESET (__RXINV__ is invalid) + */ +#define IS_UART_ADVFEATURE_RXINV(__RXINV__) (((__RXINV__) == UART_ADVFEATURE_RXINV_DISABLE) || \ + ((__RXINV__) == UART_ADVFEATURE_RXINV_ENABLE)) + +/** + * @brief Ensure that UART frame data inversion setting is valid. + * @param __DATAINV__ UART frame data inversion setting. + * @retval SET (__DATAINV__ is valid) or RESET (__DATAINV__ is invalid) + */ +#define IS_UART_ADVFEATURE_DATAINV(__DATAINV__) (((__DATAINV__) == UART_ADVFEATURE_DATAINV_DISABLE) || \ + ((__DATAINV__) == UART_ADVFEATURE_DATAINV_ENABLE)) + +/** + * @brief Ensure that UART frame RX/TX pins swap setting is valid. + * @param __SWAP__ UART frame RX/TX pins swap setting. + * @retval SET (__SWAP__ is valid) or RESET (__SWAP__ is invalid) + */ +#define IS_UART_ADVFEATURE_SWAP(__SWAP__) (((__SWAP__) == UART_ADVFEATURE_SWAP_DISABLE) || \ + ((__SWAP__) == UART_ADVFEATURE_SWAP_ENABLE)) + +/** + * @brief Ensure that UART frame overrun setting is valid. + * @param __OVERRUN__ UART frame overrun setting. + * @retval SET (__OVERRUN__ is valid) or RESET (__OVERRUN__ is invalid) + */ +#define IS_UART_OVERRUN(__OVERRUN__) (((__OVERRUN__) == UART_ADVFEATURE_OVERRUN_ENABLE) || \ + ((__OVERRUN__) == UART_ADVFEATURE_OVERRUN_DISABLE)) + +/** + * @brief Ensure that UART auto Baud rate state is valid. + * @param __AUTOBAUDRATE__ UART auto Baud rate state. + * @retval SET (__AUTOBAUDRATE__ is valid) or RESET (__AUTOBAUDRATE__ is invalid) + */ +#define IS_UART_ADVFEATURE_AUTOBAUDRATE(__AUTOBAUDRATE__) (((__AUTOBAUDRATE__) == UART_ADVFEATURE_AUTOBAUDRATE_DISABLE) || \ + ((__AUTOBAUDRATE__) == UART_ADVFEATURE_AUTOBAUDRATE_ENABLE)) + +/** + * @brief Ensure that UART DMA enabling or disabling on error setting is valid. + * @param __DMA__ UART DMA enabling or disabling on error setting. + * @retval SET (__DMA__ is valid) or RESET (__DMA__ is invalid) + */ +#define IS_UART_ADVFEATURE_DMAONRXERROR(__DMA__) (((__DMA__) == UART_ADVFEATURE_DMA_ENABLEONRXERROR) || \ + ((__DMA__) == UART_ADVFEATURE_DMA_DISABLEONRXERROR)) + +/** + * @brief Ensure that UART frame MSB first setting is valid. + * @param __MSBFIRST__ UART frame MSB first setting. + * @retval SET (__MSBFIRST__ is valid) or RESET (__MSBFIRST__ is invalid) + */ +#define IS_UART_ADVFEATURE_MSBFIRST(__MSBFIRST__) (((__MSBFIRST__) == UART_ADVFEATURE_MSBFIRST_DISABLE) || \ + ((__MSBFIRST__) == UART_ADVFEATURE_MSBFIRST_ENABLE)) + +/** + * @brief Ensure that UART stop mode state is valid. + * @param __STOPMODE__ UART stop mode state. + * @retval SET (__STOPMODE__ is valid) or RESET (__STOPMODE__ is invalid) + */ +#define IS_UART_ADVFEATURE_STOPMODE(__STOPMODE__) (((__STOPMODE__) == UART_ADVFEATURE_STOPMODE_DISABLE) || \ + ((__STOPMODE__) == UART_ADVFEATURE_STOPMODE_ENABLE)) + +/** + * @brief Ensure that UART mute mode state is valid. + * @param __MUTE__ UART mute mode state. + * @retval SET (__MUTE__ is valid) or RESET (__MUTE__ is invalid) + */ +#define IS_UART_MUTE_MODE(__MUTE__) (((__MUTE__) == UART_ADVFEATURE_MUTEMODE_DISABLE) || \ + ((__MUTE__) == UART_ADVFEATURE_MUTEMODE_ENABLE)) + +/** + * @brief Ensure that UART wake-up selection is valid. + * @param __WAKE__ UART wake-up selection. + * @retval SET (__WAKE__ is valid) or RESET (__WAKE__ is invalid) + */ +#define IS_UART_WAKEUP_SELECTION(__WAKE__) (((__WAKE__) == UART_WAKEUP_ON_ADDRESS) || \ + ((__WAKE__) == UART_WAKEUP_ON_STARTBIT) || \ + ((__WAKE__) == UART_WAKEUP_ON_READDATA_NONEMPTY)) + +/** + * @brief Ensure that UART driver enable polarity is valid. + * @param __POLARITY__ UART driver enable polarity. + * @retval SET (__POLARITY__ is valid) or RESET (__POLARITY__ is invalid) + */ +#define IS_UART_DE_POLARITY(__POLARITY__) (((__POLARITY__) == UART_DE_POLARITY_HIGH) || \ + ((__POLARITY__) == UART_DE_POLARITY_LOW)) + +#if defined(USART_PRESC_PRESCALER) +/** + * @brief Ensure that UART Prescaler is valid. + * @param __CLOCKPRESCALER__ UART Prescaler value. + * @retval SET (__CLOCKPRESCALER__ is valid) or RESET (__CLOCKPRESCALER__ is invalid) + */ +#define IS_UART_PRESCALER(__CLOCKPRESCALER__) (((__CLOCKPRESCALER__) == UART_PRESCALER_DIV1) || \ + ((__CLOCKPRESCALER__) == UART_PRESCALER_DIV2) || \ + ((__CLOCKPRESCALER__) == UART_PRESCALER_DIV4) || \ + ((__CLOCKPRESCALER__) == UART_PRESCALER_DIV6) || \ + ((__CLOCKPRESCALER__) == UART_PRESCALER_DIV8) || \ + ((__CLOCKPRESCALER__) == UART_PRESCALER_DIV10) || \ + ((__CLOCKPRESCALER__) == UART_PRESCALER_DIV12) || \ + ((__CLOCKPRESCALER__) == UART_PRESCALER_DIV16) || \ + ((__CLOCKPRESCALER__) == UART_PRESCALER_DIV32) || \ + ((__CLOCKPRESCALER__) == UART_PRESCALER_DIV64) || \ + ((__CLOCKPRESCALER__) == UART_PRESCALER_DIV128) || \ + ((__CLOCKPRESCALER__) == UART_PRESCALER_DIV256)) +#endif + +#if defined(USART_CR1_FIFOEN) +/** + * @brief Ensure that UART TXFIFO threshold level is valid. + * @param __THRESHOLD__ UART TXFIFO threshold level. + * @retval SET (__THRESHOLD__ is valid) or RESET (__THRESHOLD__ is invalid) + */ +#define IS_UART_TXFIFO_THRESHOLD(__THRESHOLD__) (((__THRESHOLD__) == UART_TXFIFO_THRESHOLD_1_8) || \ + ((__THRESHOLD__) == UART_TXFIFO_THRESHOLD_1_4) || \ + ((__THRESHOLD__) == UART_TXFIFO_THRESHOLD_1_2) || \ + ((__THRESHOLD__) == UART_TXFIFO_THRESHOLD_3_4) || \ + ((__THRESHOLD__) == UART_TXFIFO_THRESHOLD_7_8) || \ + ((__THRESHOLD__) == UART_TXFIFO_THRESHOLD_8_8)) + +/** + * @brief Ensure that UART RXFIFO threshold level is valid. + * @param __THRESHOLD__ UART RXFIFO threshold level. + * @retval SET (__THRESHOLD__ is valid) or RESET (__THRESHOLD__ is invalid) + */ +#define IS_UART_RXFIFO_THRESHOLD(__THRESHOLD__) (((__THRESHOLD__) == UART_RXFIFO_THRESHOLD_1_8) || \ + ((__THRESHOLD__) == UART_RXFIFO_THRESHOLD_1_4) || \ + ((__THRESHOLD__) == UART_RXFIFO_THRESHOLD_1_2) || \ + ((__THRESHOLD__) == UART_RXFIFO_THRESHOLD_3_4) || \ + ((__THRESHOLD__) == UART_RXFIFO_THRESHOLD_7_8) || \ + ((__THRESHOLD__) == UART_RXFIFO_THRESHOLD_8_8)) +#endif + +/** + * @} + */ + +/* Include UART HAL Extended module */ +#include "stm32l4xx_hal_uart_ex.h" + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup UART_Exported_Functions UART Exported Functions + * @{ + */ + +/** @addtogroup UART_Exported_Functions_Group1 Initialization and de-initialization functions + * @{ + */ + +/* Initialization and de-initialization functions ****************************/ +HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_HalfDuplex_Init(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_LIN_Init(UART_HandleTypeDef *huart, uint32_t BreakDetectLength); +HAL_StatusTypeDef HAL_MultiProcessor_Init(UART_HandleTypeDef *huart, uint8_t Address, uint32_t WakeUpMethod); +HAL_StatusTypeDef HAL_UART_DeInit (UART_HandleTypeDef *huart); +void HAL_UART_MspInit(UART_HandleTypeDef *huart); +void HAL_UART_MspDeInit(UART_HandleTypeDef *huart); + +/** + * @} + */ + +/** @addtogroup UART_Exported_Functions_Group2 IO operation functions + * @{ + */ + +/* IO operation functions *****************************************************/ +HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_UART_DMAPause(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_UART_DMAResume(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_UART_DMAStop(UART_HandleTypeDef *huart); +/* Transfer Abort functions */ +HAL_StatusTypeDef HAL_UART_Abort(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_UART_AbortTransmit(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_UART_AbortReceive(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_UART_Abort_IT(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_UART_AbortTransmit_IT(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_UART_AbortReceive_IT(UART_HandleTypeDef *huart); + +void HAL_UART_IRQHandler(UART_HandleTypeDef *huart); +void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart); +void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart); +void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart); +void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart); +void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart); +void HAL_UART_AbortCpltCallback (UART_HandleTypeDef *huart); +void HAL_UART_AbortTransmitCpltCallback (UART_HandleTypeDef *huart); +void HAL_UART_AbortReceiveCpltCallback (UART_HandleTypeDef *huart); + +/** + * @} + */ + +/** @addtogroup UART_Exported_Functions_Group3 Peripheral Control functions + * @{ + */ + +/* Peripheral Control functions ************************************************/ +HAL_StatusTypeDef HAL_LIN_SendBreak(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_MultiProcessor_EnableMuteMode(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_MultiProcessor_DisableMuteMode(UART_HandleTypeDef *huart); +void HAL_MultiProcessor_EnterMuteMode(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_HalfDuplex_EnableTransmitter(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_HalfDuplex_EnableReceiver(UART_HandleTypeDef *huart); + +/** + * @} + */ + +/** @addtogroup UART_Exported_Functions_Group4 Peripheral State and Error functions + * @{ + */ + +/* Peripheral State and Errors functions **************************************************/ +HAL_UART_StateTypeDef HAL_UART_GetState(UART_HandleTypeDef *huart); +uint32_t HAL_UART_GetError(UART_HandleTypeDef *huart); + +/** + * @} + */ + +/** + * @} + */ + +/* Private functions -----------------------------------------------------------*/ +/** @addtogroup UART_Private_Functions UART Private Functions + * @{ + */ + +HAL_StatusTypeDef UART_SetConfig(UART_HandleTypeDef *huart); +HAL_StatusTypeDef UART_CheckIdleState(UART_HandleTypeDef *huart); +HAL_StatusTypeDef UART_WaitOnFlagUntilTimeout(UART_HandleTypeDef *huart, uint32_t Flag, FlagStatus Status, uint32_t Tickstart, uint32_t Timeout); +void UART_AdvFeatureConfig(UART_HandleTypeDef *huart); + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_HAL_UART_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_uart_ex.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_uart_ex.h new file mode 100644 index 0000000..06d6c92 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_hal_uart_ex.h @@ -0,0 +1,771 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_uart_ex.h + * @author MCD Application Team + * @brief Header file of UART HAL Extended module. + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_UART_EX_H +#define __STM32L4xx_HAL_UART_EX_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup UARTEx + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup UARTEx_Exported_Types UARTEx Exported Types + * @{ + */ + +/** + * @brief UART wake up from stop mode parameters + */ +typedef struct +{ + uint32_t WakeUpEvent; /*!< Specifies which event will activat the Wakeup from Stop mode flag (WUF). + This parameter can be a value of @ref UART_WakeUp_from_Stop_Selection. + If set to UART_WAKEUP_ON_ADDRESS, the two other fields below must + be filled up. */ + + uint16_t AddressLength; /*!< Specifies whether the address is 4 or 7-bit long. + This parameter can be a value of @ref UARTEx_WakeUp_Address_Length. */ + + uint8_t Address; /*!< UART/USART node address (7-bit long max). */ +} UART_WakeUpTypeDef; + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup UARTEx_Exported_Constants UARTEx Exported Constants + * @{ + */ + +/** @defgroup UARTEx_Word_Length UARTEx Word Length + * @{ + */ +#define UART_WORDLENGTH_7B USART_CR1_M1 /*!< 7-bit long UART frame */ +#define UART_WORDLENGTH_8B 0x00000000U /*!< 8-bit long UART frame */ +#define UART_WORDLENGTH_9B USART_CR1_M0 /*!< 9-bit long UART frame */ +/** + * @} + */ + +/** @defgroup UARTEx_WakeUp_Address_Length UARTEx WakeUp Address Length + * @{ + */ +#define UART_ADDRESS_DETECT_4B 0x00000000U /*!< 4-bit long wake-up address */ +#define UART_ADDRESS_DETECT_7B USART_CR2_ADDM7 /*!< 7-bit long wake-up address */ +/** + * @} + */ + +#if defined(USART_CR2_SLVEN) +/** @defgroup UARTEx_Slave_Select_management UARTEx Slave Select Management + * @{ + */ +#define UART_NSS_HARD 0x00000000U /*!< SPI slave selection depends on NSS input pin */ +#define UART_NSS_SOFT USART_CR2_DIS_NSS /*!< SPI slave is always selected and NSS input pin is ignored */ +/** + * @} + */ +#endif + +#if defined(USART_CR1_FIFOEN) +/** @defgroup UARTEx_TXFIFO_threshold_level UARTEx TXFIFO threshold level + * @brief UART TXFIFO level + * @{ + */ +#define UART_TXFIFO_THRESHOLD_1_8 0x00000000U /*!< TXFIFO reaches 1/8 of its depth */ +#define UART_TXFIFO_THRESHOLD_1_4 USART_CR3_TXFTCFG_0 /*!< TXFIFO reaches 1/4 of its depth */ +#define UART_TXFIFO_THRESHOLD_1_2 USART_CR3_TXFTCFG_1 /*!< TXFIFO reaches 1/2 of its depth */ +#define UART_TXFIFO_THRESHOLD_3_4 (USART_CR3_TXFTCFG_0|USART_CR3_TXFTCFG_1) /*!< TXFIFO reaches 3/4 of its depth */ +#define UART_TXFIFO_THRESHOLD_7_8 USART_CR3_TXFTCFG_2 /*!< TXFIFO reaches 7/8 of its depth */ +#define UART_TXFIFO_THRESHOLD_8_8 (USART_CR3_TXFTCFG_2|USART_CR3_TXFTCFG_0) /*!< TXFIFO becomes empty */ +/** + * @} + */ + +/** @defgroup UARTEx_RXFIFO_threshold_level UARTEx RXFIFO threshold level + * @brief UART RXFIFO level + * @{ + */ +#define UART_RXFIFO_THRESHOLD_1_8 0x00000000U /*!< RXFIFO FIFO reaches 1/8 of its depth */ +#define UART_RXFIFO_THRESHOLD_1_4 USART_CR3_RXFTCFG_0 /*!< RXFIFO FIFO reaches 1/4 of its depth */ +#define UART_RXFIFO_THRESHOLD_1_2 USART_CR3_RXFTCFG_1 /*!< RXFIFO FIFO reaches 1/2 of its depth */ +#define UART_RXFIFO_THRESHOLD_3_4 (USART_CR3_RXFTCFG_0|USART_CR3_RXFTCFG_1) /*!< RXFIFO FIFO reaches 3/4 of its depth */ +#define UART_RXFIFO_THRESHOLD_7_8 USART_CR3_RXFTCFG_2 /*!< RXFIFO FIFO reaches 7/8 of its depth */ +#define UART_RXFIFO_THRESHOLD_8_8 (USART_CR3_RXFTCFG_2|USART_CR3_RXFTCFG_0) /*!< RXFIFO FIFO becomes full */ +/** + * @} + */ +#endif + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup UARTEx_Exported_Functions + * @{ + */ + +/** @addtogroup UARTEx_Exported_Functions_Group1 + * @{ + */ + +/* Initialization and de-initialization functions ****************************/ +HAL_StatusTypeDef HAL_RS485Ex_Init(UART_HandleTypeDef *huart, uint32_t Polarity, uint32_t AssertionTime, uint32_t DeassertionTime); + +/** + * @} + */ + +/** @addtogroup UARTEx_Exported_Functions_Group2 + * @{ + */ + +/* IO operation functions *****************************************************/ +void HAL_UARTEx_WakeupCallback(UART_HandleTypeDef *huart); + +#if defined(USART_CR1_FIFOEN) +void HAL_UARTEx_RxFifoFullCallback(UART_HandleTypeDef *huart); +void HAL_UARTEx_TxFifoEmptyCallback(UART_HandleTypeDef *huart); +#endif + +/** + * @} + */ + +/** @addtogroup UARTEx_Exported_Functions_Group3 + * @{ + */ + +/* Peripheral Control functions **********************************************/ +HAL_StatusTypeDef HAL_UARTEx_StopModeWakeUpSourceConfig(UART_HandleTypeDef *huart, UART_WakeUpTypeDef WakeUpSelection); +HAL_StatusTypeDef HAL_UARTEx_EnableStopMode(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_UARTEx_DisableStopMode(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_MultiProcessorEx_AddressLength_Set(UART_HandleTypeDef *huart, uint32_t AddressLength); + +#if defined(USART_CR2_SLVEN) +HAL_StatusTypeDef HAL_UARTEx_EnableSlaveMode(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_UARTEx_DisableSlaveMode(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_UARTEx_ConfigNSS(UART_HandleTypeDef *huart, uint32_t NSSConfig); +#endif + +#if defined(USART_CR1_FIFOEN) +HAL_StatusTypeDef HAL_UARTEx_EnableFifoMode(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_UARTEx_DisableFifoMode(UART_HandleTypeDef *huart); +HAL_StatusTypeDef HAL_UARTEx_SetTxFifoThreshold(UART_HandleTypeDef *huart, uint32_t Threshold); +HAL_StatusTypeDef HAL_UARTEx_SetRxFifoThreshold(UART_HandleTypeDef *huart, uint32_t Threshold); +#endif + + +/** + * @} + */ + +/** + * @} + */ + +/* Private constants ---------------------------------------------------------*/ +/** @defgroup UARTEx_Private_Constants UARTEx Private Constants + * @{ + */ +#if defined(USART_CR2_SLVEN) +/** @defgroup UARTEx_Slave_Mode UARTEx Synchronous Slave mode + * @{ + */ +#define UART_SLAVEMODE_DISABLE 0x00000000U /*!< USART SPI Slave Mode Enable */ +#define UART_SLAVEMODE_ENABLE USART_CR2_SLVEN /*!< USART SPI Slave Mode Disable */ +/** + * @} + */ +#endif + +#if defined(USART_CR1_FIFOEN) +/** @defgroup UARTEx_FIFO_mode UARTEx FIFO mode + * @{ + */ +#define UART_FIFOMODE_DISABLE 0x00000000U /*!< FIFO mode disable */ +#define UART_FIFOMODE_ENABLE USART_CR1_FIFOEN /*!< FIFO mode enable */ +/** + * @} + */ +#endif +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup UARTEx_Private_Macros UARTEx Private Macros + * @{ + */ + +/** @brief Report the UART clock source. + * @param __HANDLE__ specifies the UART Handle. + * @param __CLOCKSOURCE__ output variable. + * @retval UART clocking source, written in __CLOCKSOURCE__. + */ +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define UART_GETCLOCKSOURCE(__HANDLE__,__CLOCKSOURCE__) \ + do { \ + if((__HANDLE__)->Instance == USART1) \ + { \ + switch(__HAL_RCC_GET_USART1_SOURCE()) \ + { \ + case RCC_USART1CLKSOURCE_PCLK2: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK2; \ + break; \ + case RCC_USART1CLKSOURCE_HSI: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \ + break; \ + case RCC_USART1CLKSOURCE_SYSCLK: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \ + break; \ + case RCC_USART1CLKSOURCE_LSE: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \ + break; \ + default: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \ + break; \ + } \ + } \ + else if((__HANDLE__)->Instance == USART2) \ + { \ + switch(__HAL_RCC_GET_USART2_SOURCE()) \ + { \ + case RCC_USART2CLKSOURCE_PCLK1: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \ + break; \ + case RCC_USART2CLKSOURCE_HSI: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \ + break; \ + case RCC_USART2CLKSOURCE_SYSCLK: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \ + break; \ + case RCC_USART2CLKSOURCE_LSE: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \ + break; \ + default: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \ + break; \ + } \ + } \ + else if((__HANDLE__)->Instance == USART3) \ + { \ + switch(__HAL_RCC_GET_USART3_SOURCE()) \ + { \ + case RCC_USART3CLKSOURCE_PCLK1: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \ + break; \ + case RCC_USART3CLKSOURCE_HSI: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \ + break; \ + case RCC_USART3CLKSOURCE_SYSCLK: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \ + break; \ + case RCC_USART3CLKSOURCE_LSE: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \ + break; \ + default: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \ + break; \ + } \ + } \ + else if((__HANDLE__)->Instance == UART4) \ + { \ + switch(__HAL_RCC_GET_UART4_SOURCE()) \ + { \ + case RCC_UART4CLKSOURCE_PCLK1: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \ + break; \ + case RCC_UART4CLKSOURCE_HSI: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \ + break; \ + case RCC_UART4CLKSOURCE_SYSCLK: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \ + break; \ + case RCC_UART4CLKSOURCE_LSE: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \ + break; \ + default: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \ + break; \ + } \ + } \ + else if((__HANDLE__)->Instance == UART5) \ + { \ + switch(__HAL_RCC_GET_UART5_SOURCE()) \ + { \ + case RCC_UART5CLKSOURCE_PCLK1: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \ + break; \ + case RCC_UART5CLKSOURCE_HSI: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \ + break; \ + case RCC_UART5CLKSOURCE_SYSCLK: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \ + break; \ + case RCC_UART5CLKSOURCE_LSE: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \ + break; \ + default: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \ + break; \ + } \ + } \ + else if((__HANDLE__)->Instance == LPUART1) \ + { \ + switch(__HAL_RCC_GET_LPUART1_SOURCE()) \ + { \ + case RCC_LPUART1CLKSOURCE_PCLK1: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \ + break; \ + case RCC_LPUART1CLKSOURCE_HSI: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \ + break; \ + case RCC_LPUART1CLKSOURCE_SYSCLK: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \ + break; \ + case RCC_LPUART1CLKSOURCE_LSE: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \ + break; \ + default: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \ + break; \ + } \ + } \ + } while(0) +#elif defined (STM32L431xx) || defined (STM32L433xx) || defined (STM32L443xx) +#define UART_GETCLOCKSOURCE(__HANDLE__,__CLOCKSOURCE__) \ + do { \ + if((__HANDLE__)->Instance == USART1) \ + { \ + switch(__HAL_RCC_GET_USART1_SOURCE()) \ + { \ + case RCC_USART1CLKSOURCE_PCLK2: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK2; \ + break; \ + case RCC_USART1CLKSOURCE_HSI: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \ + break; \ + case RCC_USART1CLKSOURCE_SYSCLK: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \ + break; \ + case RCC_USART1CLKSOURCE_LSE: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \ + break; \ + default: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \ + break; \ + } \ + } \ + else if((__HANDLE__)->Instance == USART2) \ + { \ + switch(__HAL_RCC_GET_USART2_SOURCE()) \ + { \ + case RCC_USART2CLKSOURCE_PCLK1: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \ + break; \ + case RCC_USART2CLKSOURCE_HSI: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \ + break; \ + case RCC_USART2CLKSOURCE_SYSCLK: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \ + break; \ + case RCC_USART2CLKSOURCE_LSE: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \ + break; \ + default: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \ + break; \ + } \ + } \ + else if((__HANDLE__)->Instance == USART3) \ + { \ + switch(__HAL_RCC_GET_USART3_SOURCE()) \ + { \ + case RCC_USART3CLKSOURCE_PCLK1: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \ + break; \ + case RCC_USART3CLKSOURCE_HSI: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \ + break; \ + case RCC_USART3CLKSOURCE_SYSCLK: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \ + break; \ + case RCC_USART3CLKSOURCE_LSE: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \ + break; \ + default: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \ + break; \ + } \ + } \ + else if((__HANDLE__)->Instance == LPUART1) \ + { \ + switch(__HAL_RCC_GET_LPUART1_SOURCE()) \ + { \ + case RCC_LPUART1CLKSOURCE_PCLK1: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \ + break; \ + case RCC_LPUART1CLKSOURCE_HSI: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \ + break; \ + case RCC_LPUART1CLKSOURCE_SYSCLK: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \ + break; \ + case RCC_LPUART1CLKSOURCE_LSE: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \ + break; \ + default: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \ + break; \ + } \ + } \ + } while(0) +#elif defined (STM32L432xx) || defined (STM32L442xx) +#define UART_GETCLOCKSOURCE(__HANDLE__,__CLOCKSOURCE__) \ + do { \ + if((__HANDLE__)->Instance == USART1) \ + { \ + switch(__HAL_RCC_GET_USART1_SOURCE()) \ + { \ + case RCC_USART1CLKSOURCE_PCLK2: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK2; \ + break; \ + case RCC_USART1CLKSOURCE_HSI: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \ + break; \ + case RCC_USART1CLKSOURCE_SYSCLK: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \ + break; \ + case RCC_USART1CLKSOURCE_LSE: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \ + break; \ + default: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \ + break; \ + } \ + } \ + else if((__HANDLE__)->Instance == USART2) \ + { \ + switch(__HAL_RCC_GET_USART2_SOURCE()) \ + { \ + case RCC_USART2CLKSOURCE_PCLK1: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \ + break; \ + case RCC_USART2CLKSOURCE_HSI: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \ + break; \ + case RCC_USART2CLKSOURCE_SYSCLK: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \ + break; \ + case RCC_USART2CLKSOURCE_LSE: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \ + break; \ + default: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \ + break; \ + } \ + } \ + else if((__HANDLE__)->Instance == LPUART1) \ + { \ + switch(__HAL_RCC_GET_LPUART1_SOURCE()) \ + { \ + case RCC_LPUART1CLKSOURCE_PCLK1: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \ + break; \ + case RCC_LPUART1CLKSOURCE_HSI: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \ + break; \ + case RCC_LPUART1CLKSOURCE_SYSCLK: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \ + break; \ + case RCC_LPUART1CLKSOURCE_LSE: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \ + break; \ + default: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \ + break; \ + } \ + } \ + } while(0) +#elif defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) +#define UART_GETCLOCKSOURCE(__HANDLE__,__CLOCKSOURCE__) \ + do { \ + if((__HANDLE__)->Instance == USART1) \ + { \ + switch(__HAL_RCC_GET_USART1_SOURCE()) \ + { \ + case RCC_USART1CLKSOURCE_PCLK2: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK2; \ + break; \ + case RCC_USART1CLKSOURCE_HSI: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \ + break; \ + case RCC_USART1CLKSOURCE_SYSCLK: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \ + break; \ + case RCC_USART1CLKSOURCE_LSE: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \ + break; \ + default: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \ + break; \ + } \ + } \ + else if((__HANDLE__)->Instance == USART2) \ + { \ + switch(__HAL_RCC_GET_USART2_SOURCE()) \ + { \ + case RCC_USART2CLKSOURCE_PCLK1: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \ + break; \ + case RCC_USART2CLKSOURCE_HSI: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \ + break; \ + case RCC_USART2CLKSOURCE_SYSCLK: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \ + break; \ + case RCC_USART2CLKSOURCE_LSE: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \ + break; \ + default: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \ + break; \ + } \ + } \ + else if((__HANDLE__)->Instance == USART3) \ + { \ + switch(__HAL_RCC_GET_USART3_SOURCE()) \ + { \ + case RCC_USART3CLKSOURCE_PCLK1: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \ + break; \ + case RCC_USART3CLKSOURCE_HSI: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \ + break; \ + case RCC_USART3CLKSOURCE_SYSCLK: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \ + break; \ + case RCC_USART3CLKSOURCE_LSE: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \ + break; \ + default: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \ + break; \ + } \ + } \ + else if((__HANDLE__)->Instance == UART4) \ + { \ + switch(__HAL_RCC_GET_UART4_SOURCE()) \ + { \ + case RCC_UART4CLKSOURCE_PCLK1: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \ + break; \ + case RCC_UART4CLKSOURCE_HSI: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \ + break; \ + case RCC_UART4CLKSOURCE_SYSCLK: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \ + break; \ + case RCC_UART4CLKSOURCE_LSE: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \ + break; \ + default: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \ + break; \ + } \ + } \ + else if((__HANDLE__)->Instance == LPUART1) \ + { \ + switch(__HAL_RCC_GET_LPUART1_SOURCE()) \ + { \ + case RCC_LPUART1CLKSOURCE_PCLK1: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \ + break; \ + case RCC_LPUART1CLKSOURCE_HSI: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \ + break; \ + case RCC_LPUART1CLKSOURCE_SYSCLK: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \ + break; \ + case RCC_LPUART1CLKSOURCE_LSE: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \ + break; \ + default: \ + (__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \ + break; \ + } \ + } \ + } while(0) +#endif + +/** @brief Report the UART mask to apply to retrieve the received data + * according to the word length and to the parity bits activation. + * @note If PCE = 1, the parity bit is not included in the data extracted + * by the reception API(). + * This masking operation is not carried out in the case of + * DMA transfers. + * @param __HANDLE__: specifies the UART Handle. + * @retval None, the mask to apply to UART RDR register is stored in (__HANDLE__)->Mask field. + */ +#define UART_MASK_COMPUTATION(__HANDLE__) \ + do { \ + if ((__HANDLE__)->Init.WordLength == UART_WORDLENGTH_9B) \ + { \ + if ((__HANDLE__)->Init.Parity == UART_PARITY_NONE) \ + { \ + (__HANDLE__)->Mask = 0x01FF ; \ + } \ + else \ + { \ + (__HANDLE__)->Mask = 0x00FF ; \ + } \ + } \ + else if ((__HANDLE__)->Init.WordLength == UART_WORDLENGTH_8B) \ + { \ + if ((__HANDLE__)->Init.Parity == UART_PARITY_NONE) \ + { \ + (__HANDLE__)->Mask = 0x00FF ; \ + } \ + else \ + { \ + (__HANDLE__)->Mask = 0x007F ; \ + } \ + } \ + else if ((__HANDLE__)->Init.WordLength == UART_WORDLENGTH_7B) \ + { \ + if ((__HANDLE__)->Init.Parity == UART_PARITY_NONE) \ + { \ + (__HANDLE__)->Mask = 0x007F ; \ + } \ + else \ + { \ + (__HANDLE__)->Mask = 0x003F ; \ + } \ + } \ +} while(0) + + +/** + * @brief Ensure that UART frame length is valid. + * @param __LENGTH__ UART frame length. + * @retval SET (__LENGTH__ is valid) or RESET (__LENGTH__ is invalid) + */ +#define IS_UART_WORD_LENGTH(__LENGTH__) (((__LENGTH__) == UART_WORDLENGTH_7B) || \ + ((__LENGTH__) == UART_WORDLENGTH_8B) || \ + ((__LENGTH__) == UART_WORDLENGTH_9B)) + +/** + * @brief Ensure that UART wake-up address length is valid. + * @param __ADDRESS__ UART wake-up address length. + * @retval SET (__ADDRESS__ is valid) or RESET (__ADDRESS__ is invalid) + */ +#define IS_UART_ADDRESSLENGTH_DETECT(__ADDRESS__) (((__ADDRESS__) == UART_ADDRESS_DETECT_4B) || \ + ((__ADDRESS__) == UART_ADDRESS_DETECT_7B)) + +#if defined(USART_CR2_SLVEN) +/** + * @brief Ensure that UART Negative Slave Select (NSS) pin management is valid. + * @param __NSS__ UART Negative Slave Select pin management. + * @retval SET (__NSS__ is valid) or RESET (__NSS__ is invalid) + */ +#define IS_UART_NSS(__NSS__) (((__NSS__) == UART_NSS_HARD) || \ + ((__NSS__) == UART_NSS_SOFT)) +#endif + +#if defined(USART_CR1_FIFOEN) +/** + * @brief Ensure that UART TXFIFO threshold level is valid. + * @param __THRESHOLD__ UART TXFIFO threshold level. + * @retval SET (__THRESHOLD__ is valid) or RESET (__THRESHOLD__ is invalid) + */ +#define IS_UART_TXFIFO_THRESHOLD(__THRESHOLD__) (((__THRESHOLD__) == UART_TXFIFO_THRESHOLD_1_8) || \ + ((__THRESHOLD__) == UART_TXFIFO_THRESHOLD_1_4) || \ + ((__THRESHOLD__) == UART_TXFIFO_THRESHOLD_1_2) || \ + ((__THRESHOLD__) == UART_TXFIFO_THRESHOLD_3_4) || \ + ((__THRESHOLD__) == UART_TXFIFO_THRESHOLD_7_8) || \ + ((__THRESHOLD__) == UART_TXFIFO_THRESHOLD_8_8)) + +/** + * @brief Ensure that USART RXFIFO threshold level is valid. + * @param __THRESHOLD__ USART RXFIFO threshold level. + * @retval SET (__THRESHOLD__ is valid) or RESET (__THRESHOLD__ is invalid) + */ +#define IS_UART_RXFIFO_THRESHOLD(__THRESHOLD__) (((__THRESHOLD__) == UART_RXFIFO_THRESHOLD_1_8) || \ + ((__THRESHOLD__) == UART_RXFIFO_THRESHOLD_1_4) || \ + ((__THRESHOLD__) == UART_RXFIFO_THRESHOLD_1_2) || \ + ((__THRESHOLD__) == UART_RXFIFO_THRESHOLD_3_4) || \ + ((__THRESHOLD__) == UART_RXFIFO_THRESHOLD_7_8) || \ + ((__THRESHOLD__) == UART_RXFIFO_THRESHOLD_8_8)) +#endif + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_HAL_UART_EX_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_usb.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_usb.h new file mode 100644 index 0000000..d4a19ed --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_usb.h @@ -0,0 +1,617 @@ +/** + ****************************************************************************** + * @file stm32l4xx_ll_usb.h + * @author MCD Application Team + * @brief Header file of USB Core HAL module. + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_LL_USB_H +#define __STM32L4xx_LL_USB_H + +#ifdef __cplusplus + extern "C" { +#endif + +#if defined(STM32L432xx) || defined(STM32L433xx) || defined(STM32L442xx) || defined(STM32L443xx) || \ + defined(STM32L452xx) || defined(STM32L462xx) || \ + defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || \ + defined(STM32L496xx) || defined(STM32L4A6xx) || \ + defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal_def.h" + +/** @addtogroup STM32L4xx_HAL + * @{ + */ + +/** @addtogroup USB_Core + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ + +/** + * @brief USB Mode definition + */ +typedef enum +{ + USB_DEVICE_MODE = 0, + USB_HOST_MODE = 1, + USB_DRD_MODE = 2 + +}USB_ModeTypeDef; + +#if defined (USB_OTG_FS) +/** + * @brief URB States definition + */ +typedef enum { + URB_IDLE = 0, + URB_DONE, + URB_NOTREADY, + URB_NYET, + URB_ERROR, + URB_STALL + +}USB_OTG_URBStateTypeDef; + +/** + * @brief Host channel States definition + */ +typedef enum { + HC_IDLE = 0, + HC_XFRC, + HC_HALTED, + HC_NAK, + HC_NYET, + HC_STALL, + HC_XACTERR, + HC_BBLERR, + HC_DATATGLERR + +}USB_OTG_HCStateTypeDef; + +/** + * @brief PCD Initialization Structure definition + */ +typedef struct +{ + uint32_t dev_endpoints; /*!< Device Endpoints number. + This parameter depends on the used USB core. + This parameter must be a number between Min_Data = 1 and Max_Data = 15 */ + + uint32_t Host_channels; /*!< Host Channels number. + This parameter Depends on the used USB core. + This parameter must be a number between Min_Data = 1 and Max_Data = 15 */ + + uint32_t speed; /*!< USB Core speed. + This parameter can be any value of @ref USB_Core_Speed_ */ + + uint32_t dma_enable; /*!< Enable or disable of the USB embedded DMA. */ + + uint32_t ep0_mps; /*!< Set the Endpoint 0 Max Packet size. + This parameter can be any value of @ref USB_EP0_MPS_ */ + + uint32_t phy_itface; /*!< Select the used PHY interface. + This parameter can be any value of @ref USB_Core_PHY_ */ + + uint32_t Sof_enable; /*!< Enable or disable the output of the SOF signal. */ + + uint32_t low_power_enable; /*!< Enable or disable the low power mode. */ + + uint32_t lpm_enable; /*!< Enable or disable Battery charging. */ + + uint32_t battery_charging_enable; /*!< Enable or disable Battery charging. */ + + uint32_t vbus_sensing_enable; /*!< Enable or disable the VBUS Sensing feature. */ + + uint32_t use_dedicated_ep1; /*!< Enable or disable the use of the dedicated EP1 interrupt. */ + + uint32_t use_external_vbus; /*!< Enable or disable the use of the external VBUS. */ + +}USB_OTG_CfgTypeDef; + +typedef struct +{ + uint8_t num; /*!< Endpoint number + This parameter must be a number between Min_Data = 1 and Max_Data = 15 */ + + uint8_t is_in; /*!< Endpoint direction + This parameter must be a number between Min_Data = 0 and Max_Data = 1 */ + + uint8_t is_stall; /*!< Endpoint stall condition + This parameter must be a number between Min_Data = 0 and Max_Data = 1 */ + + uint8_t type; /*!< Endpoint type + This parameter can be any value of @ref USB_EP_Type_ */ + + uint8_t data_pid_start; /*!< Initial data PID + This parameter must be a number between Min_Data = 0 and Max_Data = 1 */ + + uint8_t even_odd_frame; /*!< IFrame parity + This parameter must be a number between Min_Data = 0 and Max_Data = 1 */ + + uint16_t tx_fifo_num; /*!< Transmission FIFO number + This parameter must be a number between Min_Data = 1 and Max_Data = 15 */ + + uint32_t maxpacket; /*!< Endpoint Max packet size + This parameter must be a number between Min_Data = 0 and Max_Data = 64KB */ + + uint8_t *xfer_buff; /*!< Pointer to transfer buffer */ + + uint32_t dma_addr; /*!< 32 bits aligned transfer buffer address */ + + uint32_t xfer_len; /*!< Current transfer length */ + + uint32_t xfer_count; /*!< Partial transfer length in case of multi packet transfer */ + +}USB_OTG_EPTypeDef; + +typedef struct +{ + uint8_t dev_addr ; /*!< USB device address. + This parameter must be a number between Min_Data = 1 and Max_Data = 255 */ + + uint8_t ch_num; /*!< Host channel number. + This parameter must be a number between Min_Data = 1 and Max_Data = 15 */ + + uint8_t ep_num; /*!< Endpoint number. + This parameter must be a number between Min_Data = 1 and Max_Data = 15 */ + + uint8_t ep_is_in; /*!< Endpoint direction + This parameter must be a number between Min_Data = 0 and Max_Data = 1 */ + + uint8_t speed; /*!< USB Host speed. + This parameter can be any value of @ref USB_Core_Speed_ */ + + uint8_t do_ping; /*!< Enable or disable the use of the PING protocol for HS mode. */ + + uint8_t process_ping; /*!< Execute the PING protocol for HS mode. */ + + uint8_t ep_type; /*!< Endpoint Type. + This parameter can be any value of @ref USB_EP_Type_ */ + + uint16_t max_packet; /*!< Endpoint Max packet size. + This parameter must be a number between Min_Data = 0 and Max_Data = 64KB */ + + uint8_t data_pid; /*!< Initial data PID. + This parameter must be a number between Min_Data = 0 and Max_Data = 1 */ + + uint8_t *xfer_buff; /*!< Pointer to transfer buffer. */ + + uint32_t xfer_len; /*!< Current transfer length. */ + + uint32_t xfer_count; /*!< Partial transfer length in case of multi packet transfer. */ + + uint8_t toggle_in; /*!< IN transfer current toggle flag. + This parameter must be a number between Min_Data = 0 and Max_Data = 1 */ + + uint8_t toggle_out; /*!< OUT transfer current toggle flag + This parameter must be a number between Min_Data = 0 and Max_Data = 1 */ + + uint32_t dma_addr; /*!< 32 bits aligned transfer buffer address. */ + + uint32_t ErrCnt; /*!< Host channel error count.*/ + + USB_OTG_URBStateTypeDef urb_state; /*!< URB state. + This parameter can be any value of @ref USB_OTG_URBStateTypeDef */ + + USB_OTG_HCStateTypeDef state; /*!< Host Channel state. + This parameter can be any value of @ref USB_OTG_HCStateTypeDef */ + +}USB_OTG_HCTypeDef; +#endif /* USB_OTG_FS */ + +#if defined (USB) +/** + * @brief USB Initialization Structure definition + */ +typedef struct +{ + uint32_t dev_endpoints; /*!< Device Endpoints number. + This parameter depends on the used USB core. + This parameter must be a number between Min_Data = 1 and Max_Data = 15 */ + + uint32_t speed; /*!< USB Core speed. + This parameter can be any value of @ref USB_Core_Speed */ + + uint32_t dma_enable; /*!< Enable or disable of the USB embedded DMA. */ + + uint32_t ep0_mps; /*!< Set the Endpoint 0 Max Packet size. + This parameter can be any value of @ref USB_EP0_MPS */ + + uint32_t phy_itface; /*!< Select the used PHY interface. + This parameter can be any value of @ref USB_Core_PHY */ + + uint32_t Sof_enable; /*!< Enable or disable the output of the SOF signal. */ + + uint32_t low_power_enable; /*!< Enable or disable Low Power mode */ + + uint32_t lpm_enable; /*!< Enable or disable Battery charging. */ + + uint32_t battery_charging_enable; /*!< Enable or disable Battery charging. */ +} USB_CfgTypeDef; + +typedef struct +{ + uint8_t num; /*!< Endpoint number + This parameter must be a number between Min_Data = 1 and Max_Data = 15 */ + + uint8_t is_in; /*!< Endpoint direction + This parameter must be a number between Min_Data = 0 and Max_Data = 1 */ + + uint8_t is_stall; /*!< Endpoint stall condition + This parameter must be a number between Min_Data = 0 and Max_Data = 1 */ + + uint8_t type; /*!< Endpoint type + This parameter can be any value of @ref USB_EP_Type */ + + uint16_t pmaadress; /*!< PMA Address + This parameter can be any value between Min_addr = 0 and Max_addr = 1K */ + + uint16_t pmaaddr0; /*!< PMA Address0 + This parameter can be any value between Min_addr = 0 and Max_addr = 1K */ + + uint16_t pmaaddr1; /*!< PMA Address1 + This parameter can be any value between Min_addr = 0 and Max_addr = 1K */ + + uint8_t doublebuffer; /*!< Double buffer enable + This parameter can be 0 or 1 */ + + uint16_t tx_fifo_num; /*!< This parameter is not required by USB Device FS peripheral, it is used + only by USB OTG FS peripheral + This parameter is added to ensure compatibility across USB peripherals */ + + uint32_t maxpacket; /*!< Endpoint Max packet size + This parameter must be a number between Min_Data = 0 and Max_Data = 64KB */ + + uint8_t *xfer_buff; /*!< Pointer to transfer buffer */ + + uint32_t xfer_len; /*!< Current transfer length */ + + uint32_t xfer_count; /*!< Partial transfer length in case of multi packet transfer */ + +} USB_EPTypeDef; +#endif /* USB */ + +/* Exported constants --------------------------------------------------------*/ + +/** @defgroup PCD_Exported_Constants PCD Exported Constants + * @{ + */ +#if defined (USB_OTG_FS) +/** @defgroup USB_Core_Mode_ USB Core Mode + * @{ + */ +#define USB_OTG_MODE_DEVICE 0 +#define USB_OTG_MODE_HOST 1 +#define USB_OTG_MODE_DRD 2 +/** + * @} + */ + +/** @defgroup USB_Core_Speed_ USB Core Speed + * @{ + */ +#define USB_OTG_SPEED_HIGH 0 +#define USB_OTG_SPEED_HIGH_IN_FULL 1 +#define USB_OTG_SPEED_LOW 2 +#define USB_OTG_SPEED_FULL 3 +/** + * @} + */ + +/** @defgroup USB_Core_PHY_ USB Core PHY + * @{ + */ +#define USB_OTG_EMBEDDED_PHY 1 +/** + * @} + */ + +/** @defgroup USB_Core_MPS_ USB Core MPS + * @{ + */ +#define USB_OTG_FS_MAX_PACKET_SIZE 64 +#define USB_OTG_MAX_EP0_SIZE 64 +/** + * @} + */ + +/** @defgroup USB_Core_Phy_Frequency_ USB Core Phy Frequency + * @{ + */ +#define DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ (0 << 1) +#define DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ (1 << 1) +#define DSTS_ENUMSPD_LS_PHY_6MHZ (2 << 1) +#define DSTS_ENUMSPD_FS_PHY_48MHZ (3 << 1) +/** + * @} + */ + +/** @defgroup USB_CORE_Frame_Interval_ USB CORE Frame Interval + * @{ + */ +#define DCFG_FRAME_INTERVAL_80 0 +#define DCFG_FRAME_INTERVAL_85 1 +#define DCFG_FRAME_INTERVAL_90 2 +#define DCFG_FRAME_INTERVAL_95 3 +/** + * @} + */ + +/** @defgroup USB_EP0_MPS_ USB EP0 MPS + * @{ + */ +#define DEP0CTL_MPS_64 0 +#define DEP0CTL_MPS_32 1 +#define DEP0CTL_MPS_16 2 +#define DEP0CTL_MPS_8 3 +/** + * @} + */ + +/** @defgroup USB_EP_Speed_ USB EP Speed + * @{ + */ +#define EP_SPEED_LOW 0 +#define EP_SPEED_FULL 1 +#define EP_SPEED_HIGH 2 +/** + * @} + */ + +/** @defgroup USB_EP_Type_ USB EP Type + * @{ + */ +#define EP_TYPE_CTRL 0 +#define EP_TYPE_ISOC 1 +#define EP_TYPE_BULK 2 +#define EP_TYPE_INTR 3 +#define EP_TYPE_MSK 3 +/** + * @} + */ + +/** @defgroup USB_STS_Defines_ USB STS Defines + * @{ + */ +#define STS_GOUT_NAK 1 +#define STS_DATA_UPDT 2 +#define STS_XFER_COMP 3 +#define STS_SETUP_COMP 4 +#define STS_SETUP_UPDT 6 +/** + * @} + */ + +/** @defgroup HCFG_SPEED_Defines_ HCFG SPEED Defines + * @{ + */ +#define HCFG_30_60_MHZ 0 +#define HCFG_48_MHZ 1 +#define HCFG_6_MHZ 2 +/** + * @} + */ + +/** @defgroup HPRT0_PRTSPD_SPEED_Defines_ HPRT0 PRTSPD SPEED Defines + * @{ + */ +#define HPRT0_PRTSPD_HIGH_SPEED 0 +#define HPRT0_PRTSPD_FULL_SPEED 1 +#define HPRT0_PRTSPD_LOW_SPEED 2 +/** + * @} + */ + +#define HCCHAR_CTRL 0 +#define HCCHAR_ISOC 1 +#define HCCHAR_BULK 2 +#define HCCHAR_INTR 3 + +#define HC_PID_DATA0 0 +#define HC_PID_DATA2 1 +#define HC_PID_DATA1 2 +#define HC_PID_SETUP 3 + +#define GRXSTS_PKTSTS_IN 2 +#define GRXSTS_PKTSTS_IN_XFER_COMP 3 +#define GRXSTS_PKTSTS_DATA_TOGGLE_ERR 5 +#define GRXSTS_PKTSTS_CH_HALTED 7 + +#define USBx_PCGCCTL *(__IO uint32_t *)((uint32_t)USBx + USB_OTG_PCGCCTL_BASE) +#define USBx_HPRT0 *(__IO uint32_t *)((uint32_t)USBx + USB_OTG_HOST_PORT_BASE) + +#define USBx_DEVICE ((USB_OTG_DeviceTypeDef *)((uint32_t )USBx + USB_OTG_DEVICE_BASE)) +#define USBx_INEP(i) ((USB_OTG_INEndpointTypeDef *)((uint32_t)USBx + USB_OTG_IN_ENDPOINT_BASE + (i)*USB_OTG_EP_REG_SIZE)) +#define USBx_OUTEP(i) ((USB_OTG_OUTEndpointTypeDef *)((uint32_t)USBx + USB_OTG_OUT_ENDPOINT_BASE + (i)*USB_OTG_EP_REG_SIZE)) +#define USBx_DFIFO(i) *(__IO uint32_t *)((uint32_t)USBx + USB_OTG_FIFO_BASE + (i) * USB_OTG_FIFO_SIZE) + +#define USBx_HOST ((USB_OTG_HostTypeDef *)((uint32_t )USBx + USB_OTG_HOST_BASE)) +#define USBx_HC(i) ((USB_OTG_HostChannelTypeDef *)((uint32_t)USBx + USB_OTG_HOST_CHANNEL_BASE + (i)*USB_OTG_HOST_CHANNEL_SIZE)) + +#endif /* USB_OTG_FS */ + +#if defined (USB) +/** @defgroup USB_LL_EP0_MPS USB Low Layer EP0 MPS + * @{ + */ +#define DEP0CTL_MPS_64 0 +#define DEP0CTL_MPS_32 1 +#define DEP0CTL_MPS_16 2 +#define DEP0CTL_MPS_8 3 +/** + * @} + */ + +/** @defgroup USB_LL_EP_Type USB Low Layer EP Type + * @{ + */ +#define EP_TYPE_CTRL 0 +#define EP_TYPE_ISOC 1 +#define EP_TYPE_BULK 2 +#define EP_TYPE_INTR 3 +#define EP_TYPE_MSK 3 +/** + * @} + */ + +#define BTABLE_ADDRESS (0x000) +#endif /* USB */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +#if defined (USB_OTG_FS) +#define USB_MASK_INTERRUPT(__INSTANCE__, __INTERRUPT__) ((__INSTANCE__)->GINTMSK &= ~(__INTERRUPT__)) +#define USB_UNMASK_INTERRUPT(__INSTANCE__, __INTERRUPT__) ((__INSTANCE__)->GINTMSK |= (__INTERRUPT__)) + +#define CLEAR_IN_EP_INTR(__EPNUM__, __INTERRUPT__) (USBx_INEP(__EPNUM__)->DIEPINT = (__INTERRUPT__)) +#define CLEAR_OUT_EP_INTR(__EPNUM__, __INTERRUPT__) (USBx_OUTEP(__EPNUM__)->DOEPINT = (__INTERRUPT__)) +#endif /* USB_OTG_FS */ + +/* Exported functions --------------------------------------------------------*/ +#if defined (USB_OTG_FS) +HAL_StatusTypeDef USB_CoreInit(USB_OTG_GlobalTypeDef *USBx, USB_OTG_CfgTypeDef Init); +HAL_StatusTypeDef USB_DevInit(USB_OTG_GlobalTypeDef *USBx, USB_OTG_CfgTypeDef Init); +HAL_StatusTypeDef USB_EnableGlobalInt(USB_OTG_GlobalTypeDef *USBx); +HAL_StatusTypeDef USB_DisableGlobalInt(USB_OTG_GlobalTypeDef *USBx); +HAL_StatusTypeDef USB_SetCurrentMode(USB_OTG_GlobalTypeDef *USBx , USB_ModeTypeDef mode); +HAL_StatusTypeDef USB_SetDevSpeed(USB_OTG_GlobalTypeDef *USBx , uint8_t speed); +HAL_StatusTypeDef USB_FlushRxFifo (USB_OTG_GlobalTypeDef *USBx); +HAL_StatusTypeDef USB_FlushTxFifo (USB_OTG_GlobalTypeDef *USBx, uint32_t num ); +HAL_StatusTypeDef USB_ActivateEndpoint(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep); +HAL_StatusTypeDef USB_DeactivateEndpoint(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep); +HAL_StatusTypeDef USB_ActivateDedicatedEndpoint(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep); +HAL_StatusTypeDef USB_DeactivateDedicatedEndpoint(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep); +HAL_StatusTypeDef USB_EPStartXfer(USB_OTG_GlobalTypeDef *USBx , USB_OTG_EPTypeDef *ep, uint8_t dma); +HAL_StatusTypeDef USB_EP0StartXfer(USB_OTG_GlobalTypeDef *USBx , USB_OTG_EPTypeDef *ep, uint8_t dma); +HAL_StatusTypeDef USB_WritePacket(USB_OTG_GlobalTypeDef *USBx, uint8_t *src, uint8_t ch_ep_num, uint16_t len, uint8_t dma); +void * USB_ReadPacket(USB_OTG_GlobalTypeDef *USBx, uint8_t *dest, uint16_t len); +HAL_StatusTypeDef USB_EPSetStall(USB_OTG_GlobalTypeDef *USBx , USB_OTG_EPTypeDef *ep); +HAL_StatusTypeDef USB_EPClearStall(USB_OTG_GlobalTypeDef *USBx , USB_OTG_EPTypeDef *ep); +HAL_StatusTypeDef USB_SetDevAddress (USB_OTG_GlobalTypeDef *USBx, uint8_t address); +HAL_StatusTypeDef USB_DevConnect (USB_OTG_GlobalTypeDef *USBx); +HAL_StatusTypeDef USB_DevDisconnect (USB_OTG_GlobalTypeDef *USBx); +HAL_StatusTypeDef USB_StopDevice(USB_OTG_GlobalTypeDef *USBx); +HAL_StatusTypeDef USB_ActivateSetup (USB_OTG_GlobalTypeDef *USBx); +HAL_StatusTypeDef USB_EP0_OutStart(USB_OTG_GlobalTypeDef *USBx, uint8_t dma, uint8_t *psetup); +uint8_t USB_GetDevSpeed(USB_OTG_GlobalTypeDef *USBx); +uint32_t USB_GetMode(USB_OTG_GlobalTypeDef *USBx); +uint32_t USB_ReadInterrupts (USB_OTG_GlobalTypeDef *USBx); +uint32_t USB_ReadDevAllOutEpInterrupt (USB_OTG_GlobalTypeDef *USBx); +uint32_t USB_ReadDevOutEPInterrupt (USB_OTG_GlobalTypeDef *USBx , uint8_t epnum); +uint32_t USB_ReadDevAllInEpInterrupt (USB_OTG_GlobalTypeDef *USBx); +uint32_t USB_ReadDevInEPInterrupt (USB_OTG_GlobalTypeDef *USBx , uint8_t epnum); +void USB_ClearInterrupts (USB_OTG_GlobalTypeDef *USBx, uint32_t interrupt); + +HAL_StatusTypeDef USB_HostInit (USB_OTG_GlobalTypeDef *USBx, USB_OTG_CfgTypeDef cfg); +HAL_StatusTypeDef USB_InitFSLSPClkSel(USB_OTG_GlobalTypeDef *USBx , uint8_t freq); +HAL_StatusTypeDef USB_ResetPort(USB_OTG_GlobalTypeDef *USBx); +HAL_StatusTypeDef USB_DriveVbus (USB_OTG_GlobalTypeDef *USBx, uint8_t state); +uint32_t USB_GetHostSpeed (USB_OTG_GlobalTypeDef *USBx); +uint32_t USB_GetCurrentFrame (USB_OTG_GlobalTypeDef *USBx); +HAL_StatusTypeDef USB_HC_Init(USB_OTG_GlobalTypeDef *USBx, + uint8_t ch_num, + uint8_t epnum, + uint8_t dev_address, + uint8_t speed, + uint8_t ep_type, + uint16_t mps); +HAL_StatusTypeDef USB_HC_StartXfer(USB_OTG_GlobalTypeDef *USBx, USB_OTG_HCTypeDef *hc, uint8_t dma); +uint32_t USB_HC_ReadInterrupt (USB_OTG_GlobalTypeDef *USBx); +HAL_StatusTypeDef USB_HC_Halt(USB_OTG_GlobalTypeDef *USBx , uint8_t hc_num); +HAL_StatusTypeDef USB_DoPing(USB_OTG_GlobalTypeDef *USBx , uint8_t ch_num); +HAL_StatusTypeDef USB_StopHost(USB_OTG_GlobalTypeDef *USBx); +HAL_StatusTypeDef USB_ActivateRemoteWakeup(USB_OTG_GlobalTypeDef *USBx); +HAL_StatusTypeDef USB_DeActivateRemoteWakeup(USB_OTG_GlobalTypeDef *USBx); +#endif /* USB_OTG_FS */ + +#if defined (USB) +HAL_StatusTypeDef USB_CoreInit(USB_TypeDef *USBx, USB_CfgTypeDef Init); +HAL_StatusTypeDef USB_DevInit(USB_TypeDef *USBx, USB_CfgTypeDef Init); +HAL_StatusTypeDef USB_EnableGlobalInt(USB_TypeDef *USBx); +HAL_StatusTypeDef USB_DisableGlobalInt(USB_TypeDef *USBx); +HAL_StatusTypeDef USB_SetCurrentMode(USB_TypeDef *USBx , USB_ModeTypeDef mode); +HAL_StatusTypeDef USB_SetDevSpeed(USB_TypeDef *USBx , uint8_t speed); +HAL_StatusTypeDef USB_FlushRxFifo (USB_TypeDef *USBx); +HAL_StatusTypeDef USB_FlushTxFifo (USB_TypeDef *USBx, uint32_t num ); +HAL_StatusTypeDef USB_ActivateEndpoint(USB_TypeDef *USBx, USB_EPTypeDef *ep); +HAL_StatusTypeDef USB_DeactivateEndpoint(USB_TypeDef *USBx, USB_EPTypeDef *ep); +HAL_StatusTypeDef USB_EPStartXfer(USB_TypeDef *USBx , USB_EPTypeDef *ep ,uint8_t dma); +HAL_StatusTypeDef USB_WritePacket(USB_TypeDef *USBx, uint8_t *src, uint8_t ch_ep_num, uint16_t len); +void * USB_ReadPacket(USB_TypeDef *USBx, uint8_t *dest, uint16_t len); +HAL_StatusTypeDef USB_EPSetStall(USB_TypeDef *USBx , USB_EPTypeDef *ep); +HAL_StatusTypeDef USB_EPClearStall(USB_TypeDef *USBx , USB_EPTypeDef *ep); +HAL_StatusTypeDef USB_SetDevAddress (USB_TypeDef *USBx, uint8_t address); +HAL_StatusTypeDef USB_DevConnect (USB_TypeDef *USBx); +HAL_StatusTypeDef USB_DevDisconnect (USB_TypeDef *USBx); +HAL_StatusTypeDef USB_StopDevice(USB_TypeDef *USBx); +HAL_StatusTypeDef USB_EP0_OutStart(USB_TypeDef *USBx, uint8_t dma, uint8_t *psetup); +uint32_t USB_ReadInterrupts (USB_TypeDef *USBx); +uint32_t USB_ReadDevAllOutEpInterrupt (USB_TypeDef *USBx); +uint32_t USB_ReadDevOutEPInterrupt (USB_TypeDef *USBx , uint8_t epnum); +uint32_t USB_ReadDevAllInEpInterrupt (USB_TypeDef *USBx); +uint32_t USB_ReadDevInEPInterrupt (USB_TypeDef *USBx , uint8_t epnum); +void USB_ClearInterrupts (USB_TypeDef *USBx, uint32_t interrupt); + +HAL_StatusTypeDef USB_ActivateRemoteWakeup(USB_TypeDef *USBx); +HAL_StatusTypeDef USB_DeActivateRemoteWakeup(USB_TypeDef *USBx); +void USB_WritePMA(USB_TypeDef *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes); +void USB_ReadPMA(USB_TypeDef *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes); +#endif /* USB */ +/** + * @} + */ + +/** + * @} + */ + +#endif /* STM32L432xx || STM32L433xx || STM32L442xx || STM32L443xx || */ + /* STM32L452xx || STM32L462xx || */ + /* STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx || */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#ifdef __cplusplus +} +#endif + + +#endif /* __STM32L4xx_LL_USB_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal.c new file mode 100644 index 0000000..1870606 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal.c @@ -0,0 +1,693 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal.c + * @author MCD Application Team + * @brief HAL module driver. + * This is the common part of the HAL initialization + * + @verbatim + ============================================================================== + ##### How to use this driver ##### + ============================================================================== + [..] + The common HAL driver contains a set of generic and common APIs that can be + used by the PPP peripheral drivers and the user to start using the HAL. + [..] + The HAL contains two APIs' categories: + (+) Common HAL APIs + (+) Services HAL APIs + + @endverbatim + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup HAL HAL + * @brief HAL module driver + * @{ + */ + +#ifdef HAL_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/** + * @brief STM32L4xx HAL Driver version number + */ +#define __STM32L4xx_HAL_VERSION_MAIN (0x01) /*!< [31:24] main version */ +#define __STM32L4xx_HAL_VERSION_SUB1 (0x08) /*!< [23:16] sub1 version */ +#define __STM32L4xx_HAL_VERSION_SUB2 (0x02) /*!< [15:8] sub2 version */ +#define __STM32L4xx_HAL_VERSION_RC (0x00) /*!< [7:0] release candidate */ +#define __STM32L4xx_HAL_VERSION ((__STM32L4xx_HAL_VERSION_MAIN << 24)\ + |(__STM32L4xx_HAL_VERSION_SUB1 << 16)\ + |(__STM32L4xx_HAL_VERSION_SUB2 << 8 )\ + |(__STM32L4xx_HAL_VERSION_RC)) + +#if defined(VREFBUF) +#define VREFBUF_TIMEOUT_VALUE (uint32_t)10 /* 10 ms (to be confirmed) */ +#endif /* VREFBUF */ + +/* ------------ SYSCFG registers bit address in the alias region ------------ */ +#define SYSCFG_OFFSET (SYSCFG_BASE - PERIPH_BASE) +/* --- MEMRMP Register ---*/ +/* Alias word address of FB_MODE bit */ +#define MEMRMP_OFFSET SYSCFG_OFFSET +#define FB_MODE_BitNumber ((uint8_t)0x8) +#define FB_MODE_BB (PERIPH_BB_BASE + (MEMRMP_OFFSET * 32) + (FB_MODE_BitNumber * 4)) + +/* --- SCSR Register ---*/ +/* Alias word address of SRAM2ER bit */ +#define SCSR_OFFSET (SYSCFG_OFFSET + 0x18) +#define BRER_BitNumber ((uint8_t)0x0) +#define SCSR_SRAM2ER_BB (PERIPH_BB_BASE + (SCSR_OFFSET * 32) + (BRER_BitNumber * 4)) + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +__IO uint32_t uwTick; + +/* Private function prototypes -----------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup HAL_Exported_Functions HAL Exported Functions + * @{ + */ + +/** @defgroup HAL_Exported_Functions_Group1 Initialization and de-initialization Functions + * @brief Initialization and de-initialization functions + * +@verbatim + =============================================================================== + ##### Initialization and de-initialization functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Initialize the Flash interface the NVIC allocation and initial time base + clock configuration. + (+) De-initialize common part of the HAL. + (+) Configure the time base source to have 1ms time base with a dedicated + Tick interrupt priority. + (++) SysTick timer is used by default as source of time base, but user + can eventually implement his proper time base source (a general purpose + timer for example or other time source), keeping in mind that Time base + duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and + handled in milliseconds basis. + (++) Time base configuration function (HAL_InitTick ()) is called automatically + at the beginning of the program after reset by HAL_Init() or at any time + when clock is configured, by HAL_RCC_ClockConfig(). + (++) Source of time base is configured to generate interrupts at regular + time intervals. Care must be taken if HAL_Delay() is called from a + peripheral ISR process, the Tick interrupt line must have higher priority + (numerically lower) than the peripheral interrupt. Otherwise the caller + ISR process will be blocked. + (++) functions affecting time base configurations are declared as __weak + to make override possible in case of other implementations in user file. +@endverbatim + * @{ + */ + +/** + * @brief Configure the Flash prefetch, the Instruction and Data caches, + * the time base source, NVIC and any required global low level hardware + * by calling the HAL_MspInit() callback function to be optionally defined in user file + * stm32l4xx_hal_msp.c. + * + * @note HAL_Init() function is called at the beginning of program after reset and before + * the clock configuration. + * + * @note In the default implementation the System Timer (Systick) is used as source of time base. + * The Systick configuration is based on MSI clock, as MSI is the clock + * used after a system Reset and the NVIC configuration is set to Priority group 4. + * Once done, time base tick starts incrementing: the tick variable counter is incremented + * each 1ms in the SysTick_Handler() interrupt handler. + * + * @retval HAL status + */ +HAL_StatusTypeDef HAL_Init(void) +{ + /* Configure Flash prefetch, Instruction cache, Data cache */ + /* Default configuration at reset is: */ + /* - Prefetch disabled */ + /* - Instruction cache enabled */ + /* - Data cache enabled */ +#if (INSTRUCTION_CACHE_ENABLE == 0) + __HAL_FLASH_INSTRUCTION_CACHE_DISABLE(); +#endif /* INSTRUCTION_CACHE_ENABLE */ + +#if (DATA_CACHE_ENABLE == 0) + __HAL_FLASH_DATA_CACHE_DISABLE(); +#endif /* DATA_CACHE_ENABLE */ + +#if (PREFETCH_ENABLE != 0) + __HAL_FLASH_PREFETCH_BUFFER_ENABLE(); +#endif /* PREFETCH_ENABLE */ + + /* Set Interrupt Group Priority */ + HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4); + + /* Use SysTick as time base source and configure 1ms tick (default clock after Reset is MSI) */ + HAL_InitTick(TICK_INT_PRIORITY); + + /* Init the low level hardware */ + HAL_MspInit(); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief De-initialize common part of the HAL and stop the source of time base. + * @note This function is optional. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DeInit(void) +{ + /* Reset of all peripherals */ + __HAL_RCC_APB1_FORCE_RESET(); + __HAL_RCC_APB1_RELEASE_RESET(); + + __HAL_RCC_APB2_FORCE_RESET(); + __HAL_RCC_APB2_RELEASE_RESET(); + + __HAL_RCC_AHB1_FORCE_RESET(); + __HAL_RCC_AHB1_RELEASE_RESET(); + + __HAL_RCC_AHB2_FORCE_RESET(); + __HAL_RCC_AHB2_RELEASE_RESET(); + + __HAL_RCC_AHB3_FORCE_RESET(); + __HAL_RCC_AHB3_RELEASE_RESET(); + + /* De-Init the low level hardware */ + HAL_MspDeInit(); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Initialize the MSP. + * @retval None + */ +__weak void HAL_MspInit(void) +{ + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitialize the MSP. + * @retval None + */ +__weak void HAL_MspDeInit(void) +{ + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_MspDeInit could be implemented in the user file + */ +} + +/** + * @brief This function configures the source of the time base: + * The time source is configured to have 1ms time base with a dedicated + * Tick interrupt priority. + * @note This function is called automatically at the beginning of program after + * reset by HAL_Init() or at any time when clock is reconfigured by HAL_RCC_ClockConfig(). + * @note In the default implementation, SysTick timer is the source of time base. + * It is used to generate interrupts at regular time intervals. + * Care must be taken if HAL_Delay() is called from a peripheral ISR process, + * The SysTick interrupt must have higher priority (numerically lower) + * than the peripheral interrupt. Otherwise the caller ISR process will be blocked. + * The function is declared as __weak to be overwritten in case of other + * implementation in user file. + * @param TickPriority Tick interrupt priority. + * @retval HAL status + */ +__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority) +{ + /*Configure the SysTick to have interrupt in 1ms time basis*/ + HAL_SYSTICK_Config(SystemCoreClock/1000); + + /*Configure the SysTick IRQ priority */ + HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority ,0); + + /* Return function status */ + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup HAL_Exported_Functions_Group2 HAL Control functions + * @brief HAL Control functions + * +@verbatim + =============================================================================== + ##### HAL Control functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Provide a tick value in millisecond + (+) Provide a blocking delay in millisecond + (+) Suspend the time base source interrupt + (+) Resume the time base source interrupt + (+) Get the HAL API driver version + (+) Get the device identifier + (+) Get the device revision identifier + +@endverbatim + * @{ + */ + +/** + * @brief This function is called to increment a global variable "uwTick" + * used as application time base. + * @note In the default implementation, this variable is incremented each 1ms + * in SysTick ISR. + * @note This function is declared as __weak to be overwritten in case of other + * implementations in user file. + * @retval None + */ +__weak void HAL_IncTick(void) +{ + uwTick++; +} + +/** + * @brief Provide a tick value in millisecond. + * @note This function is declared as __weak to be overwritten in case of other + * implementations in user file. + * @retval tick value + */ +__weak uint32_t HAL_GetTick(void) +{ + return uwTick; +} + +/** + * @brief This function provides minimum delay (in milliseconds) based + * on variable incremented. + * @note In the default implementation , SysTick timer is the source of time base. + * It is used to generate interrupts at regular time intervals where uwTick + * is incremented. + * @note This function is declared as __weak to be overwritten in case of other + * implementations in user file. + * @param Delay specifies the delay time length, in milliseconds. + * @retval None + */ +__weak void HAL_Delay(uint32_t Delay) +{ + uint32_t tickstart = HAL_GetTick(); + uint32_t wait = Delay; + + /* Add a period to guaranty minimum wait */ + if (wait < HAL_MAX_DELAY) + { + wait++; + } + + while((HAL_GetTick() - tickstart) < wait) + { + } +} + +/** + * @brief Suspend Tick increment. + * @note In the default implementation , SysTick timer is the source of time base. It is + * used to generate interrupts at regular time intervals. Once HAL_SuspendTick() + * is called, the SysTick interrupt will be disabled and so Tick increment + * is suspended. + * @note This function is declared as __weak to be overwritten in case of other + * implementations in user file. + * @retval None + */ +__weak void HAL_SuspendTick(void) +{ + /* Disable SysTick Interrupt */ + SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk; +} + +/** + * @brief Resume Tick increment. + * @note In the default implementation , SysTick timer is the source of time base. It is + * used to generate interrupts at regular time intervals. Once HAL_ResumeTick() + * is called, the SysTick interrupt will be enabled and so Tick increment + * is resumed. + * @note This function is declared as __weak to be overwritten in case of other + * implementations in user file. + * @retval None + */ +__weak void HAL_ResumeTick(void) +{ + /* Enable SysTick Interrupt */ + SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk; +} + +/** + * @brief Return the HAL revision. + * @retval version : 0xXYZR (8bits for each decimal, R for RC) + */ +uint32_t HAL_GetHalVersion(void) +{ + return __STM32L4xx_HAL_VERSION; +} + +/** + * @brief Return the device revision identifier. + * @retval Device revision identifier + */ +uint32_t HAL_GetREVID(void) +{ + return((DBGMCU->IDCODE & DBGMCU_IDCODE_REV_ID) >> 16); +} + +/** + * @brief Return the device identifier. + * @retval Device identifier + */ +uint32_t HAL_GetDEVID(void) +{ + return(DBGMCU->IDCODE & DBGMCU_IDCODE_DEV_ID); +} + +/** + * @brief Return the first word of the unique device identifier (UID based on 96 bits) + * @retval Device identifier + */ +uint32_t HAL_GetUIDw0(void) +{ + return(READ_REG(*((uint32_t *)UID_BASE))); +} + +/** + * @brief Return the second word of the unique device identifier (UID based on 96 bits) + * @retval Device identifier + */ +uint32_t HAL_GetUIDw1(void) +{ + return(READ_REG(*((uint32_t *)(UID_BASE + 4U)))); +} + +/** + * @brief Return the third word of the unique device identifier (UID based on 96 bits) + * @retval Device identifier + */ +uint32_t HAL_GetUIDw2(void) +{ + return(READ_REG(*((uint32_t *)(UID_BASE + 8U)))); +} + +/** + * @} + */ + +/** @defgroup HAL_Exported_Functions_Group3 HAL Debug functions + * @brief HAL Debug functions + * +@verbatim + =============================================================================== + ##### HAL Debug functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Enable/Disable Debug module during SLEEP mode + (+) Enable/Disable Debug module during STOP0/STOP1/STOP2 modes + (+) Enable/Disable Debug module during STANDBY mode + +@endverbatim + * @{ + */ + +/** + * @brief Enable the Debug Module during SLEEP mode. + * @retval None + */ +void HAL_DBGMCU_EnableDBGSleepMode(void) +{ + SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_SLEEP); +} + +/** + * @brief Disable the Debug Module during SLEEP mode. + * @retval None + */ +void HAL_DBGMCU_DisableDBGSleepMode(void) +{ + CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_SLEEP); +} + +/** + * @brief Enable the Debug Module during STOP0/STOP1/STOP2 modes. + * @retval None + */ +void HAL_DBGMCU_EnableDBGStopMode(void) +{ + SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STOP); +} + +/** + * @brief Disable the Debug Module during STOP0/STOP1/STOP2 modes. + * @retval None + */ +void HAL_DBGMCU_DisableDBGStopMode(void) +{ + CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STOP); +} + +/** + * @brief Enable the Debug Module during STANDBY mode. + * @retval None + */ +void HAL_DBGMCU_EnableDBGStandbyMode(void) +{ + SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STANDBY); +} + +/** + * @brief Disable the Debug Module during STANDBY mode. + * @retval None + */ +void HAL_DBGMCU_DisableDBGStandbyMode(void) +{ + CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STANDBY); +} + +/** + * @} + */ + +/** @defgroup HAL_Exported_Functions_Group4 HAL SYSCFG configuration functions + * @brief HAL SYSCFG configuration functions + * +@verbatim + =============================================================================== + ##### HAL SYSCFG configuration functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Start a hardware SRAM2 erase operation + (+) Enable/Disable the Internal FLASH Bank Swapping + (+) Configure the Voltage reference buffer + (+) Enable/Disable the Voltage reference buffer + (+) Enable/Disable the I/O analog switch voltage booster + +@endverbatim + * @{ + */ + +/** + * @brief Start a hardware SRAM2 erase operation. + * @note As long as SRAM2 is not erased the SRAM2ER bit will be set. + * This bit is automatically reset at the end of the SRAM2 erase operation. + * @retval None + */ +void HAL_SYSCFG_SRAM2Erase(void) +{ + /* unlock the write protection of the SRAM2ER bit */ + SYSCFG->SKR = 0xCA; + SYSCFG->SKR = 0x53; + /* Starts a hardware SRAM2 erase operation*/ + *(__IO uint32_t *) SCSR_SRAM2ER_BB = (uint8_t)0x00000001; +} + +/** + * @brief Enable the Internal FLASH Bank Swapping. + * + * @note This function can be used only for STM32L4xx devices. + * + * @note Flash Bank2 mapped at 0x08000000 (and aliased @0x00000000) + * and Flash Bank1 mapped at 0x08100000 (and aliased at 0x00100000) + * + * @retval None + */ +void HAL_SYSCFG_EnableMemorySwappingBank(void) +{ + *(__IO uint32_t *)FB_MODE_BB = (uint32_t)ENABLE; +} + +/** + * @brief Disable the Internal FLASH Bank Swapping. + * + * @note This function can be used only for STM32L4xx devices. + * + * @note The default state : Flash Bank1 mapped at 0x08000000 (and aliased @0x0000 0000) + * and Flash Bank2 mapped at 0x08100000 (and aliased at 0x00100000) + * + * @retval None + */ +void HAL_SYSCFG_DisableMemorySwappingBank(void) +{ + + *(__IO uint32_t *)FB_MODE_BB = (uint32_t)DISABLE; +} + +#if defined(VREFBUF) +/** + * @brief Configure the internal voltage reference buffer voltage scale. + * @param VoltageScaling specifies the output voltage to achieve + * This parameter can be one of the following values: + * @arg SYSCFG_VREFBUF_VOLTAGE_SCALE0: VREF_OUT1 around 2.048 V. + * This requires VDDA equal to or higher than 2.4 V. + * @arg SYSCFG_VREFBUF_VOLTAGE_SCALE1: VREF_OUT2 around 2.5 V. + * This requires VDDA equal to or higher than 2.8 V. + * @retval None + */ +void HAL_SYSCFG_VREFBUF_VoltageScalingConfig(uint32_t VoltageScaling) +{ + /* Check the parameters */ + assert_param(IS_SYSCFG_VREFBUF_VOLTAGE_SCALE(VoltageScaling)); + + MODIFY_REG(VREFBUF->CSR, VREFBUF_CSR_VRS, VoltageScaling); +} + +/** + * @brief Configure the internal voltage reference buffer high impedance mode. + * @param Mode specifies the high impedance mode + * This parameter can be one of the following values: + * @arg SYSCFG_VREFBUF_HIGH_IMPEDANCE_DISABLE: VREF+ pin is internally connect to VREFINT output. + * @arg SYSCFG_VREFBUF_HIGH_IMPEDANCE_ENABLE: VREF+ pin is high impedance. + * @retval None + */ +void HAL_SYSCFG_VREFBUF_HighImpedanceConfig(uint32_t Mode) +{ + /* Check the parameters */ + assert_param(IS_SYSCFG_VREFBUF_HIGH_IMPEDANCE(Mode)); + + MODIFY_REG(VREFBUF->CSR, VREFBUF_CSR_HIZ, Mode); +} + +/** + * @brief Tune the Internal Voltage Reference buffer (VREFBUF). + * @retval None + */ +void HAL_SYSCFG_VREFBUF_TrimmingConfig(uint32_t TrimmingValue) +{ + /* Check the parameters */ + assert_param(IS_SYSCFG_VREFBUF_TRIMMING(TrimmingValue)); + + MODIFY_REG(VREFBUF->CCR, VREFBUF_CCR_TRIM, TrimmingValue); +} + +/** + * @brief Enable the Internal Voltage Reference buffer (VREFBUF). + * @retval HAL_OK/HAL_TIMEOUT + */ +HAL_StatusTypeDef HAL_SYSCFG_EnableVREFBUF(void) +{ + uint32_t tickstart = 0; + + SET_BIT(VREFBUF->CSR, VREFBUF_CSR_ENVR); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait for VRR bit */ + while(READ_BIT(VREFBUF->CSR, VREFBUF_CSR_VRR) == RESET) + { + if((HAL_GetTick() - tickstart) > VREFBUF_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + + return HAL_OK; +} + +/** + * @brief Disable the Internal Voltage Reference buffer (VREFBUF). + * + * @retval None + */ +void HAL_SYSCFG_DisableVREFBUF(void) +{ + CLEAR_BIT(VREFBUF->CSR, VREFBUF_CSR_ENVR); +} +#endif /* VREFBUF */ + +/** + * @brief Enable the I/O analog switch voltage booster + * + * @retval None + */ +void HAL_SYSCFG_EnableIOAnalogSwitchBooster(void) +{ + SET_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_BOOSTEN); +} + +/** + * @brief Disable the I/O analog switch voltage booster + * + * @retval None + */ +void HAL_SYSCFG_DisableIOAnalogSwitchBooster(void) +{ + CLEAR_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_BOOSTEN); +} + +/** + * @} + */ + +/** + * @} + */ + +#endif /* HAL_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_cortex.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_cortex.c new file mode 100644 index 0000000..4c99c72 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_cortex.c @@ -0,0 +1,539 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_cortex.c + * @author MCD Application Team + * @brief CORTEX HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the CORTEX: + * + Initialization and Configuration functions + * + Peripheral Control functions + * + @verbatim + ============================================================================== + ##### How to use this driver ##### + ============================================================================== + + [..] + *** How to configure Interrupts using CORTEX HAL driver *** + =========================================================== + [..] + This section provides functions allowing to configure the NVIC interrupts (IRQ). + The Cortex-M4 exceptions are managed by CMSIS functions. + + (#) Configure the NVIC Priority Grouping using HAL_NVIC_SetPriorityGrouping() function. + (#) Configure the priority of the selected IRQ Channels using HAL_NVIC_SetPriority(). + (#) Enable the selected IRQ Channels using HAL_NVIC_EnableIRQ(). + + -@- When the NVIC_PRIORITYGROUP_0 is selected, IRQ pre-emption is no more possible. + The pending IRQ priority will be managed only by the sub priority. + + -@- IRQ priority order (sorted by highest to lowest priority): + (+@) Lowest pre-emption priority + (+@) Lowest sub priority + (+@) Lowest hardware priority (IRQ number) + + [..] + *** How to configure SysTick using CORTEX HAL driver *** + ======================================================== + [..] + Setup SysTick Timer for time base. + + (+) The HAL_SYSTICK_Config() function calls the SysTick_Config() function which + is a CMSIS function that: + (++) Configures the SysTick Reload register with value passed as function parameter. + (++) Configures the SysTick IRQ priority to the lowest value (0x0F). + (++) Resets the SysTick Counter register. + (++) Configures the SysTick Counter clock source to be Core Clock Source (HCLK). + (++) Enables the SysTick Interrupt. + (++) Starts the SysTick Counter. + + (+) You can change the SysTick Clock source to be HCLK_Div8 by calling the macro + __HAL_CORTEX_SYSTICKCLK_CONFIG(SYSTICK_CLKSOURCE_HCLK_DIV8) just after the + HAL_SYSTICK_Config() function call. The __HAL_CORTEX_SYSTICKCLK_CONFIG() macro is defined + inside the stm32l4xx_hal_cortex.h file. + + (+) You can change the SysTick IRQ priority by calling the + HAL_NVIC_SetPriority(SysTick_IRQn,...) function just after the HAL_SYSTICK_Config() function + call. The HAL_NVIC_SetPriority() call the NVIC_SetPriority() function which is a CMSIS function. + + (+) To adjust the SysTick time base, use the following formula: + + Reload Value = SysTick Counter Clock (Hz) x Desired Time base (s) + (++) Reload Value is the parameter to be passed for HAL_SYSTICK_Config() function + (++) Reload Value should not exceed 0xFFFFFF + + @endverbatim + ****************************************************************************** + + The table below gives the allowed values of the pre-emption priority and subpriority according + to the Priority Grouping configuration performed by HAL_NVIC_SetPriorityGrouping() function. + + ========================================================================================================================== + NVIC_PriorityGroup | NVIC_IRQChannelPreemptionPriority | NVIC_IRQChannelSubPriority | Description + ========================================================================================================================== + NVIC_PRIORITYGROUP_0 | 0 | 0-15 | 0 bit for pre-emption priority + | | | 4 bits for subpriority + -------------------------------------------------------------------------------------------------------------------------- + NVIC_PRIORITYGROUP_1 | 0-1 | 0-7 | 1 bit for pre-emption priority + | | | 3 bits for subpriority + -------------------------------------------------------------------------------------------------------------------------- + NVIC_PRIORITYGROUP_2 | 0-3 | 0-3 | 2 bits for pre-emption priority + | | | 2 bits for subpriority + -------------------------------------------------------------------------------------------------------------------------- + NVIC_PRIORITYGROUP_3 | 0-7 | 0-1 | 3 bits for pre-emption priority + | | | 1 bit for subpriority + -------------------------------------------------------------------------------------------------------------------------- + NVIC_PRIORITYGROUP_4 | 0-15 | 0 | 4 bits for pre-emption priority + | | | 0 bit for subpriority + ========================================================================================================================== + + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @addtogroup CORTEX + * @{ + */ + +#ifdef HAL_CORTEX_MODULE_ENABLED + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/** @addtogroup CORTEX_Exported_Functions + * @{ + */ + + +/** @addtogroup CORTEX_Exported_Functions_Group1 + * @brief Initialization and Configuration functions + * +@verbatim + ============================================================================== + ##### Initialization and Configuration functions ##### + ============================================================================== + [..] + This section provides the CORTEX HAL driver functions allowing to configure Interrupts + SysTick functionalities + +@endverbatim + * @{ + */ + + +/** + * @brief Set the priority grouping field (pre-emption priority and subpriority) + * using the required unlock sequence. + * @param PriorityGroup: The priority grouping bits length. + * This parameter can be one of the following values: + * @arg NVIC_PRIORITYGROUP_0: 0 bit for pre-emption priority, + * 4 bits for subpriority + * @arg NVIC_PRIORITYGROUP_1: 1 bit for pre-emption priority, + * 3 bits for subpriority + * @arg NVIC_PRIORITYGROUP_2: 2 bits for pre-emption priority, + * 2 bits for subpriority + * @arg NVIC_PRIORITYGROUP_3: 3 bits for pre-emption priority, + * 1 bit for subpriority + * @arg NVIC_PRIORITYGROUP_4: 4 bits for pre-emption priority, + * 0 bit for subpriority + * @note When the NVIC_PriorityGroup_0 is selected, IRQ pre-emption is no more possible. + * The pending IRQ priority will be managed only by the subpriority. + * @retval None + */ +void HAL_NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + /* Check the parameters */ + assert_param(IS_NVIC_PRIORITY_GROUP(PriorityGroup)); + + /* Set the PRIGROUP[10:8] bits according to the PriorityGroup parameter value */ + NVIC_SetPriorityGrouping(PriorityGroup); +} + +/** + * @brief Set the priority of an interrupt. + * @param IRQn: External interrupt number. + * This parameter can be an enumerator of IRQn_Type enumeration + * (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32l4xxxx.h)) + * @param PreemptPriority: The pre-emption priority for the IRQn channel. + * This parameter can be a value between 0 and 15 + * A lower priority value indicates a higher priority + * @param SubPriority: the subpriority level for the IRQ channel. + * This parameter can be a value between 0 and 15 + * A lower priority value indicates a higher priority. + * @retval None + */ +void HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t prioritygroup = 0x00; + + /* Check the parameters */ + assert_param(IS_NVIC_SUB_PRIORITY(SubPriority)); + assert_param(IS_NVIC_PREEMPTION_PRIORITY(PreemptPriority)); + + prioritygroup = NVIC_GetPriorityGrouping(); + + NVIC_SetPriority(IRQn, NVIC_EncodePriority(prioritygroup, PreemptPriority, SubPriority)); +} + +/** + * @brief Enable a device specific interrupt in the NVIC interrupt controller. + * @note To configure interrupts priority correctly, the NVIC_PriorityGroupConfig() + * function should be called before. + * @param IRQn External interrupt number. + * This parameter can be an enumerator of IRQn_Type enumeration + * (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32l4xxxx.h)) + * @retval None + */ +void HAL_NVIC_EnableIRQ(IRQn_Type IRQn) +{ + /* Check the parameters */ + assert_param(IS_NVIC_DEVICE_IRQ(IRQn)); + + /* Enable interrupt */ + NVIC_EnableIRQ(IRQn); +} + +/** + * @brief Disable a device specific interrupt in the NVIC interrupt controller. + * @param IRQn External interrupt number. + * This parameter can be an enumerator of IRQn_Type enumeration + * (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32l4xxxx.h)) + * @retval None + */ +void HAL_NVIC_DisableIRQ(IRQn_Type IRQn) +{ + /* Check the parameters */ + assert_param(IS_NVIC_DEVICE_IRQ(IRQn)); + + /* Disable interrupt */ + NVIC_DisableIRQ(IRQn); +} + +/** + * @brief Initiate a system reset request to reset the MCU. + * @retval None + */ +void HAL_NVIC_SystemReset(void) +{ + /* System Reset */ + NVIC_SystemReset(); +} + +/** + * @brief Initialize the System Timer with interrupt enabled and start the System Tick Timer (SysTick): + * Counter is in free running mode to generate periodic interrupts. + * @param TicksNumb: Specifies the ticks Number of ticks between two interrupts. + * @retval status: - 0 Function succeeded. + * - 1 Function failed. + */ +uint32_t HAL_SYSTICK_Config(uint32_t TicksNumb) +{ + return SysTick_Config(TicksNumb); +} +/** + * @} + */ + +/** @addtogroup CORTEX_Exported_Functions_Group2 + * @brief Cortex control functions + * +@verbatim + ============================================================================== + ##### Peripheral Control functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to control the CORTEX + (NVIC, SYSTICK, MPU) functionalities. + + +@endverbatim + * @{ + */ + +/** + * @brief Get the priority grouping field from the NVIC Interrupt Controller. + * @retval Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field) + */ +uint32_t HAL_NVIC_GetPriorityGrouping(void) +{ + /* Get the PRIGROUP[10:8] field value */ + return NVIC_GetPriorityGrouping(); +} + +/** + * @brief Get the priority of an interrupt. + * @param IRQn: External interrupt number. + * This parameter can be an enumerator of IRQn_Type enumeration + * (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32l4xxxx.h)) + * @param PriorityGroup: the priority grouping bits length. + * This parameter can be one of the following values: + * @arg NVIC_PRIORITYGROUP_0: 0 bit for pre-emption priority, + * 4 bits for subpriority + * @arg NVIC_PRIORITYGROUP_1: 1 bit for pre-emption priority, + * 3 bits for subpriority + * @arg NVIC_PRIORITYGROUP_2: 2 bits for pre-emption priority, + * 2 bits for subpriority + * @arg NVIC_PRIORITYGROUP_3: 3 bits for pre-emption priority, + * 1 bit for subpriority + * @arg NVIC_PRIORITYGROUP_4: 4 bits for pre-emption priority, + * 0 bit for subpriority + * @param pPreemptPriority: Pointer on the Preemptive priority value (starting from 0). + * @param pSubPriority: Pointer on the Subpriority value (starting from 0). + * @retval None + */ +void HAL_NVIC_GetPriority(IRQn_Type IRQn, uint32_t PriorityGroup, uint32_t *pPreemptPriority, uint32_t *pSubPriority) +{ + /* Check the parameters */ + assert_param(IS_NVIC_PRIORITY_GROUP(PriorityGroup)); + /* Get priority for Cortex-M system or device specific interrupts */ + NVIC_DecodePriority(NVIC_GetPriority(IRQn), PriorityGroup, pPreemptPriority, pSubPriority); +} + +/** + * @brief Set Pending bit of an external interrupt. + * @param IRQn External interrupt number + * This parameter can be an enumerator of IRQn_Type enumeration + * (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32l4xxxx.h)) + * @retval None + */ +void HAL_NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + /* Check the parameters */ + assert_param(IS_NVIC_DEVICE_IRQ(IRQn)); + + /* Set interrupt pending */ + NVIC_SetPendingIRQ(IRQn); +} + +/** + * @brief Get Pending Interrupt (read the pending register in the NVIC + * and return the pending bit for the specified interrupt). + * @param IRQn External interrupt number. + * This parameter can be an enumerator of IRQn_Type enumeration + * (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32l4xxxx.h)) + * @retval status: - 0 Interrupt status is not pending. + * - 1 Interrupt status is pending. + */ +uint32_t HAL_NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + /* Check the parameters */ + assert_param(IS_NVIC_DEVICE_IRQ(IRQn)); + + /* Return 1 if pending else 0 */ + return NVIC_GetPendingIRQ(IRQn); +} + +/** + * @brief Clear the pending bit of an external interrupt. + * @param IRQn External interrupt number. + * This parameter can be an enumerator of IRQn_Type enumeration + * (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32l4xxxx.h)) + * @retval None + */ +void HAL_NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + /* Check the parameters */ + assert_param(IS_NVIC_DEVICE_IRQ(IRQn)); + + /* Clear pending interrupt */ + NVIC_ClearPendingIRQ(IRQn); +} + +/** + * @brief Get active interrupt (read the active register in NVIC and return the active bit). + * @param IRQn External interrupt number + * This parameter can be an enumerator of IRQn_Type enumeration + * (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32l4xxxx.h)) + * @retval status: - 0 Interrupt status is not pending. + * - 1 Interrupt status is pending. + */ +uint32_t HAL_NVIC_GetActive(IRQn_Type IRQn) +{ + /* Return 1 if active else 0 */ + return NVIC_GetActive(IRQn); +} + +/** + * @brief Configure the SysTick clock source. + * @param CLKSource: specifies the SysTick clock source. + * This parameter can be one of the following values: + * @arg SYSTICK_CLKSOURCE_HCLK_DIV8: AHB clock divided by 8 selected as SysTick clock source. + * @arg SYSTICK_CLKSOURCE_HCLK: AHB clock selected as SysTick clock source. + * @retval None + */ +void HAL_SYSTICK_CLKSourceConfig(uint32_t CLKSource) +{ + /* Check the parameters */ + assert_param(IS_SYSTICK_CLK_SOURCE(CLKSource)); + if (CLKSource == SYSTICK_CLKSOURCE_HCLK) + { + SysTick->CTRL |= SYSTICK_CLKSOURCE_HCLK; + } + else + { + SysTick->CTRL &= ~SYSTICK_CLKSOURCE_HCLK; + } +} + +/** + * @brief Handle SYSTICK interrupt request. + * @retval None + */ +void HAL_SYSTICK_IRQHandler(void) +{ + HAL_SYSTICK_Callback(); +} + +/** + * @brief SYSTICK callback. + * @retval None + */ +__weak void HAL_SYSTICK_Callback(void) +{ + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SYSTICK_Callback could be implemented in the user file + */ +} + +#if (__MPU_PRESENT == 1) +/** + * @brief Disable the MPU. + * @retval None + */ +void HAL_MPU_Disable(void) +{ + /* Make sure outstanding transfers are done */ + __DMB(); + + /* Disable fault exceptions */ + SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk; + + /* Disable the MPU and clear the control register*/ + MPU->CTRL = 0U; +} + +/** + * @brief Enable the MPU. + * @param MPU_Control: Specifies the control mode of the MPU during hard fault, + * NMI, FAULTMASK and privileged accessto the default memory + * This parameter can be one of the following values: + * @arg MPU_HFNMI_PRIVDEF_NONE + * @arg MPU_HARDFAULT_NMI + * @arg MPU_PRIVILEGED_DEFAULT + * @arg MPU_HFNMI_PRIVDEF + * @retval None + */ +void HAL_MPU_Enable(uint32_t MPU_Control) +{ + /* Enable the MPU */ + MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk; + + /* Enable fault exceptions */ + SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; + + /* Ensure MPU settings take effects */ + __DSB(); + __ISB(); +} + +/** + * @brief Initialize and configure the Region and the memory to be protected. + * @param MPU_Init: Pointer to a MPU_Region_InitTypeDef structure that contains + * the initialization and configuration information. + * @retval None + */ +void HAL_MPU_ConfigRegion(MPU_Region_InitTypeDef *MPU_Init) +{ + /* Check the parameters */ + assert_param(IS_MPU_REGION_NUMBER(MPU_Init->Number)); + assert_param(IS_MPU_REGION_ENABLE(MPU_Init->Enable)); + + /* Set the Region number */ + MPU->RNR = MPU_Init->Number; + + if ((MPU_Init->Enable) != RESET) + { + /* Check the parameters */ + assert_param(IS_MPU_INSTRUCTION_ACCESS(MPU_Init->DisableExec)); + assert_param(IS_MPU_REGION_PERMISSION_ATTRIBUTE(MPU_Init->AccessPermission)); + assert_param(IS_MPU_TEX_LEVEL(MPU_Init->TypeExtField)); + assert_param(IS_MPU_ACCESS_SHAREABLE(MPU_Init->IsShareable)); + assert_param(IS_MPU_ACCESS_CACHEABLE(MPU_Init->IsCacheable)); + assert_param(IS_MPU_ACCESS_BUFFERABLE(MPU_Init->IsBufferable)); + assert_param(IS_MPU_SUB_REGION_DISABLE(MPU_Init->SubRegionDisable)); + assert_param(IS_MPU_REGION_SIZE(MPU_Init->Size)); + + MPU->RBAR = MPU_Init->BaseAddress; + MPU->RASR = ((uint32_t)MPU_Init->DisableExec << MPU_RASR_XN_Pos) | + ((uint32_t)MPU_Init->AccessPermission << MPU_RASR_AP_Pos) | + ((uint32_t)MPU_Init->TypeExtField << MPU_RASR_TEX_Pos) | + ((uint32_t)MPU_Init->IsShareable << MPU_RASR_S_Pos) | + ((uint32_t)MPU_Init->IsCacheable << MPU_RASR_C_Pos) | + ((uint32_t)MPU_Init->IsBufferable << MPU_RASR_B_Pos) | + ((uint32_t)MPU_Init->SubRegionDisable << MPU_RASR_SRD_Pos) | + ((uint32_t)MPU_Init->Size << MPU_RASR_SIZE_Pos) | + ((uint32_t)MPU_Init->Enable << MPU_RASR_ENABLE_Pos); + } + else + { + MPU->RBAR = 0x00; + MPU->RASR = 0x00; + } +} +#endif /* __MPU_PRESENT */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* HAL_CORTEX_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_dma.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_dma.c new file mode 100644 index 0000000..8d30b49 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_dma.c @@ -0,0 +1,1179 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_dma.c + * @author MCD Application Team + * @brief DMA HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Direct Memory Access (DMA) peripheral: + * + Initialization and de-initialization functions + * + IO operation functions + * + Peripheral State and errors functions + @verbatim + ============================================================================== + ##### How to use this driver ##### + ============================================================================== + [..] + (#) Enable and configure the peripheral to be connected to the DMA Channel + (except for internal SRAM / FLASH memories: no initialization is + necessary). Please refer to the Reference manual for connection between peripherals + and DMA requests. + + (#) For a given Channel, program the required configuration through the following parameters: + Channel request, Transfer Direction, Source and Destination data formats, + Circular or Normal mode, Channel Priority level, Source and Destination Increment mode + using HAL_DMA_Init() function. + + Prior to HAL_DMA_Init the peripheral clock shall be enabled for both DMA & DMAMUX + thanks to: + (##) DMA1 or DMA2: __HAL_RCC_DMA1_CLK_ENABLE() or __HAL_RCC_DMA2_CLK_ENABLE() ; + (##) DMAMUX1: __HAL_RCC_DMAMUX1_CLK_ENABLE(); + + (#) Use HAL_DMA_GetState() function to return the DMA state and HAL_DMA_GetError() in case of error + detection. + + (#) Use HAL_DMA_Abort() function to abort the current transfer + + -@- In Memory-to-Memory transfer mode, Circular mode is not allowed. + + *** Polling mode IO operation *** + ================================= + [..] + (+) Use HAL_DMA_Start() to start DMA transfer after the configuration of Source + address and destination address and the Length of data to be transferred + (+) Use HAL_DMA_PollForTransfer() to poll for the end of current transfer, in this + case a fixed Timeout can be configured by User depending from his application. + + *** Interrupt mode IO operation *** + =================================== + [..] + (+) Configure the DMA interrupt priority using HAL_NVIC_SetPriority() + (+) Enable the DMA IRQ handler using HAL_NVIC_EnableIRQ() + (+) Use HAL_DMA_Start_IT() to start DMA transfer after the configuration of + Source address and destination address and the Length of data to be transferred. + In this case the DMA interrupt is configured + (+) Use HAL_DMA_IRQHandler() called under DMA_IRQHandler() Interrupt subroutine + (+) At the end of data transfer HAL_DMA_IRQHandler() function is executed and user can + add his own function to register callbacks with HAL_DMA_RegisterCallback(). + + *** DMA HAL driver macros list *** + ============================================= + [..] + Below the list of macros in DMA HAL driver. + + (+) __HAL_DMA_ENABLE: Enable the specified DMA Channel. + (+) __HAL_DMA_DISABLE: Disable the specified DMA Channel. + (+) __HAL_DMA_GET_FLAG: Get the DMA Channel pending flags. + (+) __HAL_DMA_CLEAR_FLAG: Clear the DMA Channel pending flags. + (+) __HAL_DMA_ENABLE_IT: Enable the specified DMA Channel interrupts. + (+) __HAL_DMA_DISABLE_IT: Disable the specified DMA Channel interrupts. + (+) __HAL_DMA_GET_IT_SOURCE: Check whether the specified DMA Channel interrupt is enabled or not. + + [..] + (@) You can refer to the DMA HAL driver header file for more useful macros + + @endverbatim + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup DMA DMA + * @brief DMA HAL module driver + * @{ + */ + +#ifdef HAL_DMA_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/** @defgroup DMA_Private_Functions DMA Private Functions + * @{ + */ +static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength); +#if defined(DMAMUX1) +static void DMA_CalcDMAMUXChannelBaseAndMask(DMA_HandleTypeDef *hdma); +static void DMA_CalcDMAMUXRequestGenBaseAndMask(DMA_HandleTypeDef *hdma); +#endif /* DMAMUX1 */ + +/** + * @} + */ + +/* Exported functions ---------------------------------------------------------*/ + +/** @defgroup DMA_Exported_Functions DMA Exported Functions + * @{ + */ + +/** @defgroup DMA_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and de-initialization functions + * +@verbatim + =============================================================================== + ##### Initialization and de-initialization functions ##### + =============================================================================== + [..] + This section provides functions allowing to initialize the DMA Channel source + and destination addresses, incrementation and data sizes, transfer direction, + circular/normal mode selection, memory-to-memory mode selection and Channel priority value. + [..] + The HAL_DMA_Init() function follows the DMA configuration procedures as described in + reference manual. + +@endverbatim + * @{ + */ + +/** + * @brief Initialize the DMA according to the specified + * parameters in the DMA_InitTypeDef and initialize the associated handle. + * @param hdma: Pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA Channel. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA_Init(DMA_HandleTypeDef *hdma) +{ + uint32_t tmp = 0; + + /* Check the DMA handle allocation */ + if(hdma == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance)); + assert_param(IS_DMA_DIRECTION(hdma->Init.Direction)); + assert_param(IS_DMA_PERIPHERAL_INC_STATE(hdma->Init.PeriphInc)); + assert_param(IS_DMA_MEMORY_INC_STATE(hdma->Init.MemInc)); + assert_param(IS_DMA_PERIPHERAL_DATA_SIZE(hdma->Init.PeriphDataAlignment)); + assert_param(IS_DMA_MEMORY_DATA_SIZE(hdma->Init.MemDataAlignment)); + assert_param(IS_DMA_MODE(hdma->Init.Mode)); + assert_param(IS_DMA_PRIORITY(hdma->Init.Priority)); + + assert_param(IS_DMA_ALL_REQUEST(hdma->Init.Request)); + + /* Compute the channel index */ + if ((uint32_t)(hdma->Instance) < (uint32_t)(DMA2_Channel1)) + { + /* DMA1 */ + hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2; + hdma->DmaBaseAddress = DMA1; + } + else + { + /* DMA2 */ + hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA2_Channel1) / ((uint32_t)DMA2_Channel2 - (uint32_t)DMA2_Channel1)) << 2; + hdma->DmaBaseAddress = DMA2; + } + + /* Change DMA peripheral state */ + hdma->State = HAL_DMA_STATE_BUSY; + + /* Get the CR register value */ + tmp = hdma->Instance->CCR; + + /* Clear PL, MSIZE, PSIZE, MINC, PINC, CIRC, DIR and MEM2MEM bits */ + tmp &= ((uint32_t)~(DMA_CCR_PL | DMA_CCR_MSIZE | DMA_CCR_PSIZE | + DMA_CCR_MINC | DMA_CCR_PINC | DMA_CCR_CIRC | + DMA_CCR_DIR | DMA_CCR_MEM2MEM)); + + /* Prepare the DMA Channel configuration */ + tmp |= hdma->Init.Direction | + hdma->Init.PeriphInc | hdma->Init.MemInc | + hdma->Init.PeriphDataAlignment | hdma->Init.MemDataAlignment | + hdma->Init.Mode | hdma->Init.Priority; + + /* Write to DMA Channel CR register */ + hdma->Instance->CCR = tmp; + + +#if defined(DMAMUX1) + /* Initialize parameters for DMAMUX channel : + DMAmuxChannel, DMAmuxChannelStatus and DMAmuxChannelStatusMask + */ + DMA_CalcDMAMUXChannelBaseAndMask(hdma); + + if(hdma->Init.Direction == DMA_MEMORY_TO_MEMORY) + { + /* if memory to memory force the request to 0*/ + hdma->Init.Request = DMA_REQUEST_MEM2MEM; + } + + /* Set peripheral request to DMAMUX channel */ + hdma->DMAmuxChannel->CCR = (hdma->Init.Request & DMAMUX_CxCR_DMAREQ_ID); + + /* Clear the DMAMUX synchro overrun flag */ + hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask; + + if(((hdma->Init.Request > 0) && (hdma->Init.Request <= DMA_REQUEST_GENERATOR3))) + { + /* Initialize parameters for DMAMUX request generator : + DMAmuxRequestGen, DMAmuxRequestGenStatus and DMAmuxRequestGenStatusMask + */ + DMA_CalcDMAMUXRequestGenBaseAndMask(hdma); + + /* Reset the DMAMUX request generator register*/ + hdma->DMAmuxRequestGen->RGCR = 0U; + + /* Clear the DMAMUX request generator overrun flag */ + hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask; + } + else + { + hdma->DMAmuxRequestGen = 0U; + hdma->DMAmuxRequestGenStatus = 0U; + hdma->DMAmuxRequestGenStatusMask = 0U; + } +#endif /* DMAMUX1 */ + +#if !defined (DMAMUX1) + + /* Set request selection */ + if(hdma->Init.Direction != DMA_MEMORY_TO_MEMORY) + { + /* Write to DMA channel selection register */ + if (DMA1 == hdma->DmaBaseAddress) + { + /* Reset request selection for DMA1 Channelx */ + DMA1_CSELR->CSELR &= ~(DMA_CSELR_C1S << hdma->ChannelIndex); + + /* Configure request selection for DMA1 Channelx */ + DMA1_CSELR->CSELR |= (uint32_t) (hdma->Init.Request << (hdma->ChannelIndex)); + } + else /* DMA2 */ + { + /* Reset request selection for DMA2 Channelx */ + DMA2_CSELR->CSELR &= ~(DMA_CSELR_C1S << hdma->ChannelIndex); + + /* Configure request selection for DMA2 Channelx */ + DMA2_CSELR->CSELR |= (uint32_t) (hdma->Init.Request << (hdma->ChannelIndex)); + } + } + +#endif /* STM32L431xx || STM32L432xx || STM32L433xx || STM32L442xx || STM32L443xx */ + /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L442xx || STM32L486xx */ + /* STM32L496xx || STM32L4A6xx */ + + /* Clean callbacks */ + hdma->XferCpltCallback = NULL; + hdma->XferHalfCpltCallback = NULL; + hdma->XferErrorCallback = NULL; + hdma->XferAbortCallback = NULL; + + /* Initialise the error code */ + hdma->ErrorCode = HAL_DMA_ERROR_NONE; + + /* Initialize the DMA state*/ + hdma->State = HAL_DMA_STATE_READY; + + /* Allocate lock resource and initialize it */ + hdma->Lock = HAL_UNLOCKED; + + return HAL_OK; +} + +/** + * @brief DeInitialize the DMA peripheral. + * @param hdma: pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA Channel. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA_DeInit(DMA_HandleTypeDef *hdma) +{ + + /* Check the DMA handle allocation */ + if (NULL == hdma ) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance)); + + /* Disable the selected DMA Channelx */ + __HAL_DMA_DISABLE(hdma); + + /* Compute the channel index */ + if ((uint32_t)(hdma->Instance) < (uint32_t)(DMA2_Channel1)) + { + /* DMA1 */ + hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2; + hdma->DmaBaseAddress = DMA1; + } + else + { + /* DMA2 */ + hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA2_Channel1) / ((uint32_t)DMA2_Channel2 - (uint32_t)DMA2_Channel1)) << 2; + hdma->DmaBaseAddress = DMA2; + } + + /* Reset DMA Channel control register */ + hdma->Instance->CCR = 0; + + /* Clear all flags */ + hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex)); + +#if !defined (DMAMUX1) + + /* Reset DMA channel selection register */ + if (DMA1 == hdma->DmaBaseAddress) + { + /* DMA1 */ + DMA1_CSELR->CSELR &= ~(DMA_CSELR_C1S << (hdma->ChannelIndex)); + } + else + { + /* DMA2 */ + DMA2_CSELR->CSELR &= ~(DMA_CSELR_C1S << (hdma->ChannelIndex)); + } +#endif /* STM32L431xx || STM32L432xx || STM32L433xx || STM32L442xx || STM32L443xx */ + /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L442xx || STM32L486xx */ + /* STM32L496xx || STM32L4A6xx */ + +#if defined(DMAMUX1) + + /* Initialize parameters for DMAMUX channel : + DMAmuxChannel, DMAmuxChannelStatus and DMAmuxChannelStatusMask */ + + DMA_CalcDMAMUXChannelBaseAndMask(hdma); + + /* Reset the DMAMUX channel that corresponds to the DMA channel */ + hdma->DMAmuxChannel->CCR = 0; + + /* Clear the DMAMUX synchro overrun flag */ + hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask; + + /* Reset Request generator parameters if any */ + if(((hdma->Init.Request > 0) && (hdma->Init.Request <= DMA_REQUEST_GENERATOR3))) + { + /* Initialize parameters for DMAMUX request generator : + DMAmuxRequestGen, DMAmuxRequestGenStatus and DMAmuxRequestGenStatusMask + */ + DMA_CalcDMAMUXRequestGenBaseAndMask(hdma); + + /* Reset the DMAMUX request generator register*/ + hdma->DMAmuxRequestGen->RGCR = 0U; + + /* Clear the DMAMUX request generator overrun flag */ + hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask; + } + + hdma->DMAmuxRequestGen = 0U; + hdma->DMAmuxRequestGenStatus = 0U; + hdma->DMAmuxRequestGenStatusMask = 0U; + +#endif /* DMAMUX1 */ + + /* Initialise the error code */ + hdma->ErrorCode = HAL_DMA_ERROR_NONE; + + /* Initialize the DMA state */ + hdma->State = HAL_DMA_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(hdma); + + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup DMA_Exported_Functions_Group2 Input and Output operation functions + * @brief Input and Output operation functions + * +@verbatim + =============================================================================== + ##### IO operation functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Configure the source, destination address and data length and Start DMA transfer + (+) Configure the source, destination address and data length and + Start DMA transfer with interrupt + (+) Abort DMA transfer + (+) Poll for transfer complete + (+) Handle DMA interrupt request + +@endverbatim + * @{ + */ + +/** + * @brief Start the DMA Transfer. + * @param hdma: pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA Channel. + * @param SrcAddress: The source memory Buffer address + * @param DstAddress: The destination memory Buffer address + * @param DataLength: The length of data to be transferred from source to destination + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA_Start(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check the parameters */ + assert_param(IS_DMA_BUFFER_SIZE(DataLength)); + + /* Process locked */ + __HAL_LOCK(hdma); + + if(HAL_DMA_STATE_READY == hdma->State) + { + /* Change DMA peripheral state */ + hdma->State = HAL_DMA_STATE_BUSY; + hdma->ErrorCode = HAL_DMA_ERROR_NONE; + + /* Disable the peripheral */ + __HAL_DMA_DISABLE(hdma); + + /* Configure the source, destination address and the data length & clear flags*/ + DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength); + + /* Enable the Peripheral */ + __HAL_DMA_ENABLE(hdma); + } + else + { + /* Process Unlocked */ + __HAL_UNLOCK(hdma); + status = HAL_BUSY; + } + return status; +} + +/** + * @brief Start the DMA Transfer with interrupt enabled. + * @param hdma: pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA Channel. + * @param SrcAddress: The source memory Buffer address + * @param DstAddress: The destination memory Buffer address + * @param DataLength: The length of data to be transferred from source to destination + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check the parameters */ + assert_param(IS_DMA_BUFFER_SIZE(DataLength)); + + /* Process locked */ + __HAL_LOCK(hdma); + + if(HAL_DMA_STATE_READY == hdma->State) + { + /* Change DMA peripheral state */ + hdma->State = HAL_DMA_STATE_BUSY; + hdma->ErrorCode = HAL_DMA_ERROR_NONE; + + /* Disable the peripheral */ + __HAL_DMA_DISABLE(hdma); + + /* Configure the source, destination address and the data length & clear flags*/ + DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength); + + /* Enable the transfer complete interrupt */ + /* Enable the transfer Error interrupt */ + if(NULL != hdma->XferHalfCpltCallback ) + { + /* Enable the Half transfer complete interrupt as well */ + __HAL_DMA_ENABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE)); + } + else + { + __HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT); + __HAL_DMA_ENABLE_IT(hdma, (DMA_IT_TC | DMA_IT_TE)); + } + +#ifdef DMAMUX1 + + /* Check if DMAMUX Synchronization is enabled*/ + if((hdma->DMAmuxChannel->CCR & DMAMUX_CxCR_SE) != 0U) + { + /* Enable DMAMUX sync overrun IT*/ + hdma->DMAmuxChannel->CCR |= DMAMUX_CxCR_SOIE; + } + + if(hdma->DMAmuxRequestGen != 0U) + { + /* if using DMAMUX request generator, enable the DMAMUX request generator overrun IT*/ + /* enable the request gen overrun IT*/ + hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_OIE; + } + +#endif /* DMAMUX1 */ + + /* Enable the Peripheral */ + __HAL_DMA_ENABLE(hdma); + } + else + { + /* Process Unlocked */ + __HAL_UNLOCK(hdma); + + /* Remain BUSY */ + status = HAL_BUSY; + } + return status; +} + +/** + * @brief Abort the DMA Transfer. + * @param hdma: pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA Channel. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *hdma) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check the DMA peripheral handle */ + if(NULL == hdma) + { + return HAL_ERROR; + } + + /* Disable DMA IT */ + __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE)); + +#if defined(DMAMUX1) + /* disable the DMAMUX sync overrun IT*/ + hdma->DMAmuxChannel->CCR &= ~DMAMUX_CxCR_SOIE; +#endif /* DMAMUX1 */ + + /* Disable the channel */ + __HAL_DMA_DISABLE(hdma); + + /* Clear all flags */ + hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << hdma->ChannelIndex); + +#if defined(DMAMUX1) + /* Clear the DMAMUX synchro overrun flag */ + hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask; + + if(hdma->DMAmuxRequestGen != 0U) + { + /* if using DMAMUX request generator, disable the DMAMUX request generator overrun IT*/ + /* disable the request gen overrun IT*/ + hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_OIE; + + /* Clear the DMAMUX request generator overrun flag */ + hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask; + } + +#endif /* DMAMUX1 */ + + /* Change the DMA state */ + hdma->State = HAL_DMA_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hdma); + + return status; +} + +/** + * @brief Aborts the DMA Transfer in Interrupt mode. + * @param hdma : pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA Channel. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA_Abort_IT(DMA_HandleTypeDef *hdma) +{ + HAL_StatusTypeDef status = HAL_OK; + + if(HAL_DMA_STATE_BUSY != hdma->State) + { + /* no transfer ongoing */ + hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER; + + status = HAL_ERROR; + } + else + { + /* Disable DMA IT */ + __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE)); + + /* Disable the channel */ + __HAL_DMA_DISABLE(hdma); + +#if defined(DMAMUX1) + /* disable the DMAMUX sync overrun IT*/ + hdma->DMAmuxChannel->CCR &= ~DMAMUX_CxCR_SOIE; + + /* Clear all flags */ + hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << hdma->ChannelIndex); + + /* Clear the DMAMUX synchro overrun flag */ + hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask; + + if(hdma->DMAmuxRequestGen != 0U) + { + /* if using DMAMUX request generator, disable the DMAMUX request generator overrun IT*/ + /* disable the request gen overrun IT*/ + hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_OIE; + + /* Clear the DMAMUX request generator overrun flag */ + hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask; + } + +#else + /* Clear all flags */ + hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << hdma->ChannelIndex); +#endif /* DMAMUX1 */ + + /* Change the DMA state */ + hdma->State = HAL_DMA_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hdma); + + /* Call User Abort callback */ + if(hdma->XferAbortCallback != NULL) + { + hdma->XferAbortCallback(hdma); + } + } + return status; +} + +/** + * @brief Polling for transfer complete. + * @param hdma: pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA Channel. + * @param CompleteLevel: Specifies the DMA level complete. + * @param Timeout: Timeout duration. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA_PollForTransfer(DMA_HandleTypeDef *hdma, HAL_DMA_LevelCompleteTypeDef CompleteLevel, uint32_t Timeout) +{ + uint32_t temp; + uint32_t tickstart = 0; + + if(HAL_DMA_STATE_BUSY != hdma->State) + { + /* no transfer ongoing */ + hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER; + __HAL_UNLOCK(hdma); + return HAL_ERROR; + } + + /* Polling mode not supported in circular mode */ + if (RESET != (hdma->Instance->CCR & DMA_CCR_CIRC)) + { + hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED; + return HAL_ERROR; + } + + /* Get the level transfer complete flag */ + if (HAL_DMA_FULL_TRANSFER == CompleteLevel) + { + /* Transfer Complete flag */ + temp = DMA_FLAG_TC1 << hdma->ChannelIndex; + } + else + { + /* Half Transfer Complete flag */ + temp = DMA_FLAG_HT1 << hdma->ChannelIndex; + } + + /* Get tick */ + tickstart = HAL_GetTick(); + + while(RESET == (hdma->DmaBaseAddress->ISR & temp)) + { + if((RESET != (hdma->DmaBaseAddress->ISR & (DMA_FLAG_TE1 << hdma->ChannelIndex)))) + { + /* When a DMA transfer error occurs */ + /* A hardware clear of its EN bits is performed */ + /* Clear all flags */ + hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << hdma->ChannelIndex); + + /* Update error code */ + hdma->ErrorCode = HAL_DMA_ERROR_TE; + + /* Change the DMA state */ + hdma->State= HAL_DMA_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hdma); + + return HAL_ERROR; + } + /* Check for the Timeout */ + if(Timeout != HAL_MAX_DELAY) + { + if((Timeout == 0) || ((HAL_GetTick() - tickstart) > Timeout)) + { + /* Update error code */ + hdma->ErrorCode = HAL_DMA_ERROR_TIMEOUT; + + /* Change the DMA state */ + hdma->State = HAL_DMA_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hdma); + + return HAL_ERROR; + } + } + } + +#if defined(DMAMUX1) + /*Check for DMAMUX Request generator (if used) overrun status */ + if(hdma->DMAmuxRequestGen != 0U) + { + /* if using DMAMUX request generator Check for DMAMUX request generator overrun */ + if((hdma->DMAmuxRequestGenStatus->RGSR & hdma->DMAmuxRequestGenStatusMask) != 0U) + { + /* Disable the request gen overrun interrupt */ + hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_OIE; + + /* Clear the DMAMUX request generator overrun flag */ + hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask; + + /* Update error code */ + hdma->ErrorCode |= HAL_DMA_ERROR_REQGEN; + } + } + + /* Check for DMAMUX Synchronization overrun */ + if((hdma->DMAmuxChannelStatus->CSR & hdma->DMAmuxChannelStatusMask) != 0U) + { + /* Clear the DMAMUX synchro overrun flag */ + hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask; + + /* Update error code */ + hdma->ErrorCode |= HAL_DMA_ERROR_SYNC; + } +#endif /* DMAMUX1 */ + + if(HAL_DMA_FULL_TRANSFER == CompleteLevel) + { + /* Clear the transfer complete flag */ + hdma->DmaBaseAddress->IFCR = (DMA_FLAG_TC1 << hdma->ChannelIndex); + + /* The selected Channelx EN bit is cleared (DMA is disabled and + all transfers are complete) */ + hdma->State = HAL_DMA_STATE_READY; + } + else + { + /* Clear the half transfer complete flag */ + hdma->DmaBaseAddress->IFCR = (DMA_FLAG_HT1 << hdma->ChannelIndex); + } + + /* Process unlocked */ + __HAL_UNLOCK(hdma); + + return HAL_OK; +} + +/** + * @brief Handle DMA interrupt request. + * @param hdma: pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA Channel. + * @retval None + */ +void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma) +{ + uint32_t flag_it = hdma->DmaBaseAddress->ISR; + uint32_t source_it = hdma->Instance->CCR; + + /* Half Transfer Complete Interrupt management ******************************/ + if ((RESET != (flag_it & (DMA_FLAG_HT1 << hdma->ChannelIndex))) && (RESET != (source_it & DMA_IT_HT))) + { + /* Disable the half transfer interrupt if the DMA mode is not CIRCULAR */ + if((hdma->Instance->CCR & DMA_CCR_CIRC) == 0) + { + /* Disable the half transfer interrupt */ + __HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT); + } + /* Clear the half transfer complete flag */ + hdma->DmaBaseAddress->IFCR = (DMA_ISR_HTIF1 << hdma->ChannelIndex); + + /* DMA peripheral state is not updated in Half Transfer */ + /* but in Transfer Complete case */ + + if(hdma->XferHalfCpltCallback != NULL) + { + /* Half transfer callback */ + hdma->XferHalfCpltCallback(hdma); + } + } + + /* Transfer Complete Interrupt management ***********************************/ + else if ((RESET != (flag_it & (DMA_FLAG_TC1 << hdma->ChannelIndex))) && (RESET != (source_it & DMA_IT_TC))) + { + if((hdma->Instance->CCR & DMA_CCR_CIRC) == 0) + { + /* Disable the transfer complete and error interrupt */ + __HAL_DMA_DISABLE_IT(hdma, DMA_IT_TE | DMA_IT_TC); + + /* Change the DMA state */ + hdma->State = HAL_DMA_STATE_READY; + } + /* Clear the transfer complete flag */ + hdma->DmaBaseAddress->IFCR = (DMA_ISR_TCIF1 << hdma->ChannelIndex); + + /* Process Unlocked */ + __HAL_UNLOCK(hdma); + + if(hdma->XferCpltCallback != NULL) + { + /* Transfer complete callback */ + hdma->XferCpltCallback(hdma); + } + } + + /* Transfer Error Interrupt management **************************************/ + else if (( RESET != (flag_it & (DMA_FLAG_TE1 << hdma->ChannelIndex))) && (RESET != (source_it & DMA_IT_TE))) + { + /* When a DMA transfer error occurs */ + /* A hardware clear of its EN bits is performed */ + /* Disable ALL DMA IT */ + __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE)); + + /* Clear all flags */ + hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << hdma->ChannelIndex); + + /* Update error code */ + hdma->ErrorCode = HAL_DMA_ERROR_TE; + + /* Change the DMA state */ + hdma->State = HAL_DMA_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hdma); + + if (hdma->XferErrorCallback != NULL) + { + /* Transfer error callback */ + hdma->XferErrorCallback(hdma); + } + } + return; +} + +/** + * @brief Register callbacks + * @param hdma: pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA Channel. + * @param CallbackID: User Callback identifer + * a HAL_DMA_CallbackIDTypeDef ENUM as parameter. + * @param pCallback: pointer to private callbacsk function which has pointer to + * a DMA_HandleTypeDef structure as parameter. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA_RegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID, void (* pCallback)( DMA_HandleTypeDef * _hdma)) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(hdma); + + if(HAL_DMA_STATE_READY == hdma->State) + { + switch (CallbackID) + { + case HAL_DMA_XFER_CPLT_CB_ID: + hdma->XferCpltCallback = pCallback; + break; + + case HAL_DMA_XFER_HALFCPLT_CB_ID: + hdma->XferHalfCpltCallback = pCallback; + break; + + case HAL_DMA_XFER_ERROR_CB_ID: + hdma->XferErrorCallback = pCallback; + break; + + case HAL_DMA_XFER_ABORT_CB_ID: + hdma->XferAbortCallback = pCallback; + break; + + default: + status = HAL_ERROR; + break; + } + } + else + { + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hdma); + + return status; +} + +/** + * @brief UnRegister callbacks + * @param hdma: pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA Channel. + * @param CallbackID: User Callback identifer + * a HAL_DMA_CallbackIDTypeDef ENUM as parameter. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(hdma); + + if(HAL_DMA_STATE_READY == hdma->State) + { + switch (CallbackID) + { + case HAL_DMA_XFER_CPLT_CB_ID: + hdma->XferCpltCallback = NULL; + break; + + case HAL_DMA_XFER_HALFCPLT_CB_ID: + hdma->XferHalfCpltCallback = NULL; + break; + + case HAL_DMA_XFER_ERROR_CB_ID: + hdma->XferErrorCallback = NULL; + break; + + case HAL_DMA_XFER_ABORT_CB_ID: + hdma->XferAbortCallback = NULL; + break; + + case HAL_DMA_XFER_ALL_CB_ID: + hdma->XferCpltCallback = NULL; + hdma->XferHalfCpltCallback = NULL; + hdma->XferErrorCallback = NULL; + hdma->XferAbortCallback = NULL; + break; + + default: + status = HAL_ERROR; + break; + } + } + else + { + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hdma); + + return status; +} + +/** + * @} + */ + + + +/** @defgroup DMA_Exported_Functions_Group3 Peripheral State and Errors functions + * @brief Peripheral State and Errors functions + * +@verbatim + =============================================================================== + ##### Peripheral State and Errors functions ##### + =============================================================================== + [..] + This subsection provides functions allowing to + (+) Check the DMA state + (+) Get error code + +@endverbatim + * @{ + */ + +/** + * @brief Return the DMA hande state. + * @param hdma: pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA Channel. + * @retval HAL state + */ +HAL_DMA_StateTypeDef HAL_DMA_GetState(DMA_HandleTypeDef *hdma) +{ + /* Return DMA handle state */ + return hdma->State; +} + +/** + * @brief Return the DMA error code. + * @param hdma : pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA Channel. + * @retval DMA Error Code + */ +uint32_t HAL_DMA_GetError(DMA_HandleTypeDef *hdma) +{ + return hdma->ErrorCode; +} + +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup DMA_Private_Functions + * @{ + */ + +/** + * @brief Sets the DMA Transfer parameter. + * @param hdma: pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA Channel. + * @param SrcAddress: The source memory Buffer address + * @param DstAddress: The destination memory Buffer address + * @param DataLength: The length of data to be transferred from source to destination + * @retval HAL status + */ +static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength) +{ +#if defined(DMAMUX1) + /* Clear the DMAMUX synchro overrun flag */ + hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask; + + if(hdma->DMAmuxRequestGen != 0U) + { + /* Clear the DMAMUX request generator overrun flag */ + hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask; + } +#endif + + /* Clear all flags */ + hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << hdma->ChannelIndex); + + /* Configure DMA Channel data length */ + hdma->Instance->CNDTR = DataLength; + + /* Peripheral to Memory */ + if((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH) + { + /* Configure DMA Channel destination address */ + hdma->Instance->CPAR = DstAddress; + + /* Configure DMA Channel source address */ + hdma->Instance->CMAR = SrcAddress; + } + /* Memory to Peripheral */ + else + { + /* Configure DMA Channel source address */ + hdma->Instance->CPAR = SrcAddress; + + /* Configure DMA Channel destination address */ + hdma->Instance->CMAR = DstAddress; + } +} + +#if defined(DMAMUX1) + +/** + * @brief Updates the DMA handle with the DMAMUX channel and status mask depending on stream number + * @param hdma: pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA Stream. + * @retval None + */ +static void DMA_CalcDMAMUXChannelBaseAndMask(DMA_HandleTypeDef *hdma) +{ + uint32_t channel_number = 0; + DMAMUX_Channel_TypeDef *DMAMUX1_ChannelBase; + + /* check if instance is not outside the DMA channel range */ + if ((uint32_t)hdma->Instance < (uint32_t)DMA2_Channel1) + { + /* DMA1 */ + DMAMUX1_ChannelBase = DMAMUX1_Channel0; + } + else + { + /* DMA2 */ + DMAMUX1_ChannelBase = DMAMUX1_Channel7; + } + channel_number = (((uint32_t)hdma->Instance & 0xFF) - 8) / 20; + hdma->DMAmuxChannel = (DMAMUX_Channel_TypeDef *)(uint32_t)((uint32_t)DMAMUX1_ChannelBase + (hdma->ChannelIndex >> 2) * ((uint32_t)DMAMUX1_Channel1 - (uint32_t)DMAMUX1_Channel0)); + hdma->DMAmuxChannelStatus = DMAMUX1_ChannelStatus; + hdma->DMAmuxChannelStatusMask = 1U << channel_number; +} + +/** + * @brief Updates the DMA handle with the DMAMUX request generator params + * @param hdma: pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA Stream. + * @retval None + */ + +static void DMA_CalcDMAMUXRequestGenBaseAndMask(DMA_HandleTypeDef *hdma) +{ + uint32_t request = hdma->Init.Request & DMAMUX_CxCR_DMAREQ_ID; + + /* DMA Channels are connected to DMAMUX1 request generator blocks*/ + hdma->DMAmuxRequestGen = (DMAMUX_RequestGen_TypeDef *)((uint32_t)(((uint32_t)DMAMUX1_RequestGenerator0) + ((request - 1U) * 4U))); + + hdma->DMAmuxRequestGenStatus = DMAMUX1_RequestGenStatus; + + hdma->DMAmuxRequestGenStatusMask = 1U << (request - 1U); +} + +#endif /* DMAMUX1 */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* HAL_DMA_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_dma_ex.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_dma_ex.c new file mode 100644 index 0000000..50b09d5 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_dma_ex.c @@ -0,0 +1,319 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_dma_ex.c + * @author MCD Application Team + * @brief DMA Extension HAL module driver + * This file provides firmware functions to manage the following + * functionalities of the DMA Extension peripheral: + * + Extended features functions + * + @verbatim + ============================================================================== + ##### How to use this driver ##### + ============================================================================== + [..] + The DMA Extension HAL driver can be used as follows: + + (+) Configure the DMA_MUX Synchronization Block using HAL_DMAEx_ConfigMuxSync function. + (+) Configure the DMA_MUX Request Generator Block using HAL_DMAEx_ConfigMuxRequestGenerator function. + Functions HAL_DMAEx_EnableMuxRequestGenerator and HAL_DMAEx_DisableMuxRequestGenerator can then be used + to respectively enable/disable the request generator. + + (+) To handle the DMAMUX Interrupts, the function HAL_DMAEx_MUX_IRQHandler should be called from + the DMAMUX IRQ handler i.e DMAMUX1_OVR_IRQHandler. + As only one interrupt line is available for all DMAMUX channels and request generators , HAL_DMAEx_MUX_IRQHandler should be + called with, as parameter, the appropriate DMA handle as many as used DMAs in the user project + (exception done if a given DMA is not using the DMAMUX SYNC block neither a request generator) + + @endverbatim + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +#if defined(DMAMUX1) + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup DMAEx DMAEx + * @brief DMA Extended HAL module driver + * @{ + */ + +#ifdef HAL_DMA_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private Constants ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + + +/** @defgroup DMAEx_Exported_Functions DMAEx Exported Functions + * @{ + */ + +/** @defgroup DMAEx_Exported_Functions_Group1 DMAEx Extended features functions + * @brief Extended features functions + * +@verbatim + =============================================================================== + ##### Extended features functions ##### + =============================================================================== + [..] This section provides functions allowing to: + + (+) Configure the DMAMUX Synchronization Block using HAL_DMAEx_ConfigMuxSync function. + (+) Configure the DMAMUX Request Generator Block using HAL_DMAEx_ConfigMuxRequestGenerator function. + Functions HAL_DMAEx_EnableMuxRequestGenerator and HAL_DMAEx_DisableMuxRequestGenerator can then be used + to respectively enable/disable the request generator. + +@endverbatim + * @{ + */ + + +/** + * @brief Configure the DMAMUX synchronization parameters for a given DMA channel (instance). + * @param hdma: pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA channel. + * @param pSyncConfig : pointer to HAL_DMA_MuxSyncConfigTypeDef : contains the DMAMUX synchronization parameters + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMAEx_ConfigMuxSync(DMA_HandleTypeDef *hdma, HAL_DMA_MuxSyncConfigTypeDef *pSyncConfig) +{ + /* Check the parameters */ + assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance)); + + assert_param(IS_DMAMUX_SYNC_SIGNAL_ID(pSyncConfig->SyncSignalID)); + + assert_param(IS_DMAMUX_SYNC_POLARITY(pSyncConfig-> SyncPolarity)); + assert_param(IS_DMAMUX_SYNC_STATE(pSyncConfig->SyncEnable)); + assert_param(IS_DMAMUX_SYNC_EVENT(pSyncConfig->EventEnable)); + assert_param(IS_DMAMUX_SYNC_REQUEST_NUMBER(pSyncConfig->RequestNumber)); + + /*Check if the DMA state is ready */ + if(hdma->State == HAL_DMA_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hdma); + + /* Set the new synchronization parameters (and keep the request ID filled during the Init)*/ + MODIFY_REG( hdma->DMAmuxChannel->CCR, \ + (~DMAMUX_CxCR_DMAREQ_ID) , \ + ((pSyncConfig->SyncSignalID) << DMAMUX_CxCR_SYNC_ID_Pos) | ((pSyncConfig->RequestNumber - 1U) << DMAMUX_CxCR_NBREQ_Pos) | \ + pSyncConfig->SyncPolarity | (pSyncConfig->SyncEnable << DMAMUX_CxCR_SE_Pos) | \ + (pSyncConfig->EventEnable << DMAMUX_CxCR_EGE_Pos)); + + /* Process UnLocked */ + __HAL_UNLOCK(hdma); + + return HAL_OK; + } + else + { + /*DMA State not Ready*/ + return HAL_ERROR; + } +} + +/** + * @brief Configure the DMAMUX request generator block used by the given DMA channel (instance). + * @param hdma: pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA channel. + * @param pRequestGeneratorConfig : pointer to HAL_DMA_MuxRequestGeneratorConfigTypeDef : + * contains the request generator parameters. + * + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMAEx_ConfigMuxRequestGenerator (DMA_HandleTypeDef *hdma, HAL_DMA_MuxRequestGeneratorConfigTypeDef *pRequestGeneratorConfig) +{ + /* Check the parameters */ + assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance)); + + assert_param(IS_DMAMUX_REQUEST_GEN_SIGNAL_ID(pRequestGeneratorConfig->SignalID)); + + assert_param(IS_DMAMUX_REQUEST_GEN_POLARITY(pRequestGeneratorConfig->Polarity)); + assert_param(IS_DMAMUX_REQUEST_GEN_REQUEST_NUMBER(pRequestGeneratorConfig->RequestNumber)); + + /* check if the DMA state is ready + and DMA is using a DMAMUX request generator block + */ + if((hdma->State == HAL_DMA_STATE_READY) && (hdma->DMAmuxRequestGen != 0U)) + { + /* Process Locked */ + __HAL_LOCK(hdma); + + /* Set the request generator new parameters*/ + hdma->DMAmuxRequestGen->RGCR = pRequestGeneratorConfig->SignalID | \ + ((pRequestGeneratorConfig->RequestNumber - 1U) << POSITION_VAL(DMAMUX_RGxCR_GNBREQ))| \ + pRequestGeneratorConfig->Polarity; + /* Process UnLocked */ + __HAL_UNLOCK(hdma); + + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Enable the DMAMUX request generator block used by the given DMA channel (instance). + * @param hdma: pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA channel. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMAEx_EnableMuxRequestGenerator (DMA_HandleTypeDef *hdma) +{ + /* Check the parameters */ + assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance)); + + /* check if the DMA state is ready + and DMA is using a DMAMUX request generator block + */ + if((hdma->State != HAL_DMA_STATE_RESET) && (hdma->DMAmuxRequestGen != 0)) + { + + /* Enable the request generator*/ + hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_GE; + + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Disable the DMAMUX request generator block used by the given DMA channel (instance). + * @param hdma: pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA channel. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMAEx_DisableMuxRequestGenerator (DMA_HandleTypeDef *hdma) +{ + /* Check the parameters */ + assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance)); + + /* check if the DMA state is ready + and DMA is using a DMAMUX request generator block + */ + if((hdma->State != HAL_DMA_STATE_RESET) && (hdma->DMAmuxRequestGen != 0)) + { + + /* Disable the request generator*/ + hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_GE; + + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Handles DMAMUX interrupt request. + * @param hdma: pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA channel. + * @retval None + */ +void HAL_DMAEx_MUX_IRQHandler(DMA_HandleTypeDef *hdma) +{ + /* Check for DMAMUX Synchronization overrun */ + if((hdma->DMAmuxChannelStatus->CSR & hdma->DMAmuxChannelStatusMask) != 0U) + { + /* Disable the synchro overrun interrupt */ + hdma->DMAmuxChannel->CCR &= ~DMAMUX_CxCR_SOIE; + + /* Clear the DMAMUX synchro overrun flag */ + hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask; + + /* Update error code */ + hdma->ErrorCode |= HAL_DMA_ERROR_SYNC; + + if(hdma->XferErrorCallback != NULL) + { + /* Transfer error callback */ + hdma->XferErrorCallback(hdma); + } + } + + if(hdma->DMAmuxRequestGen != 0) + { + /* if using a DMAMUX request generator block Check for DMAMUX request generator overrun */ + if((hdma->DMAmuxRequestGenStatus->RGSR & hdma->DMAmuxRequestGenStatusMask) != 0U) + { + /* Disable the request gen overrun interrupt */ + hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_OIE; + + /* Clear the DMAMUX request generator overrun flag */ + hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask; + + /* Update error code */ + hdma->ErrorCode |= HAL_DMA_ERROR_REQGEN; + + if(hdma->XferErrorCallback != NULL) + { + /* Transfer error callback */ + hdma->XferErrorCallback(hdma); + } + } + } +} + +/** + * @} + */ + +/** + * @} + */ + +#endif /* HAL_DMA_MODULE_ENABLED */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* DMAMUX1 */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash.c new file mode 100644 index 0000000..0c035a6 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash.c @@ -0,0 +1,835 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_flash.c + * @author MCD Application Team + * @brief FLASH HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the internal FLASH memory: + * + Program operations functions + * + Memory Control functions + * + Peripheral Errors functions + * + @verbatim + ============================================================================== + ##### FLASH peripheral features ##### + ============================================================================== + + [..] The Flash memory interface manages CPU AHB I-Code and D-Code accesses + to the Flash memory. It implements the erase and program Flash memory operations + and the read and write protection mechanisms. + + [..] The Flash memory interface accelerates code execution with a system of instruction + prefetch and cache lines. + + [..] The FLASH main features are: + (+) Flash memory read operations + (+) Flash memory program/erase operations + (+) Read / write protections + (+) Option bytes programming + (+) Prefetch on I-Code + (+) 32 cache lines of 4*64 bits on I-Code + (+) 8 cache lines of 4*64 bits on D-Code + (+) Error code correction (ECC) : Data in flash are 72-bits word + (8 bits added per double word) + + + ##### How to use this driver ##### + ============================================================================== + [..] + This driver provides functions and macros to configure and program the FLASH + memory of all STM32L4xx devices. + + (#) Flash Memory IO Programming functions: + (++) Lock and Unlock the FLASH interface using HAL_FLASH_Unlock() and + HAL_FLASH_Lock() functions + (++) Program functions: double word and fast program (full row programming) + (++) There Two modes of programming : + (+++) Polling mode using HAL_FLASH_Program() function + (+++) Interrupt mode using HAL_FLASH_Program_IT() function + + (#) Interrupts and flags management functions : + (++) Handle FLASH interrupts by calling HAL_FLASH_IRQHandler() + (++) Callback functions are called when the flash operations are finished : + HAL_FLASH_EndOfOperationCallback() when everything is ok, otherwise + HAL_FLASH_OperationErrorCallback() + (++) Get error flag status by calling HAL_GetError() + + (#) Option bytes management functions : + (++) Lock and Unlock the option bytes using HAL_FLASH_OB_Unlock() and + HAL_FLASH_OB_Lock() functions + (++) Launch the reload of the option bytes using HAL_FLASH_Launch() function. + In this case, a reset is generated + + [..] + In addition to these functions, this driver includes a set of macros allowing + to handle the following operations: + (+) Set the latency + (+) Enable/Disable the prefetch buffer + (+) Enable/Disable the Instruction cache and the Data cache + (+) Reset the Instruction cache and the Data cache + (+) Enable/Disable the Flash power-down during low-power run and sleep modes + (+) Enable/Disable the Flash interrupts + (+) Monitor the Flash flags status + + @endverbatim + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup FLASH FLASH + * @brief FLASH HAL module driver + * @{ + */ + +#ifdef HAL_FLASH_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private defines -----------------------------------------------------------*/ +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define FLASH_NB_DOUBLE_WORDS_IN_ROW 64 +#else +#define FLASH_NB_DOUBLE_WORDS_IN_ROW 32 +#endif +/* Private macros ------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/** @defgroup FLASH_Private_Variables FLASH Private Variables + * @{ + */ +/** + * @brief Variable used for Program/Erase sectors under interruption + */ +FLASH_ProcessTypeDef pFlash; +/** + * @} + */ + +/* Private function prototypes -----------------------------------------------*/ +/** @defgroup FLASH_Private_Functions FLASH Private Functions + * @{ + */ +HAL_StatusTypeDef FLASH_WaitForLastOperation(uint32_t Timeout); +extern void FLASH_PageErase(uint32_t Page, uint32_t Banks); +extern void FLASH_FlushCaches(void); +static void FLASH_SetErrorCode(void); +static void FLASH_Program_DoubleWord(uint32_t Address, uint64_t Data); +static void FLASH_Program_Fast(uint32_t Address, uint32_t DataAddress); +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup FLASH_Exported_Functions FLASH Exported Functions + * @{ + */ + +/** @defgroup FLASH_Exported_Functions_Group1 Programming operation functions + * @brief Programming operation functions + * +@verbatim + =============================================================================== + ##### Programming operation functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to manage the FLASH + program operations. + +@endverbatim + * @{ + */ + +/** + * @brief Program double word or fast program of a row at a specified address. + * @param TypeProgram: Indicate the way to program at a specified address. + * This parameter can be a value of @ref FLASH_Type_Program + * @param Address: specifies the address to be programmed. + * @param Data: specifies the data to be programmed + * This parameter is the data for the double word program and the address where + * are stored the data for the row fast program + * + * @retval HAL_StatusTypeDef HAL Status + */ +HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data) +{ + HAL_StatusTypeDef status = HAL_ERROR; + uint32_t prog_bit = 0; + + /* Process Locked */ + __HAL_LOCK(&pFlash); + + /* Check the parameters */ + assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram)); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); + + if(status == HAL_OK) + { + pFlash.ErrorCode = HAL_FLASH_ERROR_NONE; + + /* Deactivate the data cache if they are activated to avoid data misbehavior */ + if(READ_BIT(FLASH->ACR, FLASH_ACR_DCEN) != RESET) + { + /* Disable data cache */ + __HAL_FLASH_DATA_CACHE_DISABLE(); + pFlash.CacheToReactivate = FLASH_CACHE_DCACHE_ENABLED; + } + else + { + pFlash.CacheToReactivate = FLASH_CACHE_DISABLED; + } + + if(TypeProgram == FLASH_TYPEPROGRAM_DOUBLEWORD) + { + /* Program double-word (64-bit) at a specified address */ + FLASH_Program_DoubleWord(Address, Data); + prog_bit = FLASH_CR_PG; + } + else if((TypeProgram == FLASH_TYPEPROGRAM_FAST) || (TypeProgram == FLASH_TYPEPROGRAM_FAST_AND_LAST)) + { + /* Fast program a 32 row double-word (64-bit) at a specified address */ + FLASH_Program_Fast(Address, (uint32_t)Data); + + /* If it is the last row, the bit will be cleared at the end of the operation */ + if(TypeProgram == FLASH_TYPEPROGRAM_FAST_AND_LAST) + { + prog_bit = FLASH_CR_FSTPG; + } + } + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); + + /* If the program operation is completed, disable the PG or FSTPG Bit */ + if (prog_bit != 0) + { + CLEAR_BIT(FLASH->CR, prog_bit); + } + + /* Flush the caches to be sure of the data consistency */ + FLASH_FlushCaches(); + } + + /* Process Unlocked */ + __HAL_UNLOCK(&pFlash); + + return status; +} + +/** + * @brief Program double word or fast program of a row at a specified address with interrupt enabled. + * @param TypeProgram: Indicate the way to program at a specified address. + * This parameter can be a value of @ref FLASH_Type_Program + * @param Address: specifies the address to be programmed. + * @param Data: specifies the data to be programmed + * This parameter is the data for the double word program and the address where + * are stored the data for the row fast program + * + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_FLASH_Program_IT(uint32_t TypeProgram, uint32_t Address, uint64_t Data) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check the parameters */ + assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram)); + + /* Process Locked */ + __HAL_LOCK(&pFlash); + + pFlash.ErrorCode = HAL_FLASH_ERROR_NONE; + + /* Deactivate the data cache if they are activated to avoid data misbehavior */ + if(READ_BIT(FLASH->ACR, FLASH_ACR_DCEN) != RESET) + { + /* Disable data cache */ + __HAL_FLASH_DATA_CACHE_DISABLE(); + pFlash.CacheToReactivate = FLASH_CACHE_DCACHE_ENABLED; + } + else + { + pFlash.CacheToReactivate = FLASH_CACHE_DISABLED; + } + + /* Set internal variables used by the IRQ handler */ + if(TypeProgram == FLASH_TYPEPROGRAM_FAST_AND_LAST) + { + pFlash.ProcedureOnGoing = FLASH_PROC_PROGRAM_LAST; + } + else + { + pFlash.ProcedureOnGoing = FLASH_PROC_PROGRAM; + } + pFlash.Address = Address; + + /* Enable End of Operation and Error interrupts */ + __HAL_FLASH_ENABLE_IT(FLASH_IT_EOP | FLASH_IT_OPERR); + + if(TypeProgram == FLASH_TYPEPROGRAM_DOUBLEWORD) + { + /* Program double-word (64-bit) at a specified address */ + FLASH_Program_DoubleWord(Address, Data); + } + else if((TypeProgram == FLASH_TYPEPROGRAM_FAST) || (TypeProgram == FLASH_TYPEPROGRAM_FAST_AND_LAST)) + { + /* Fast program a 32 row double-word (64-bit) at a specified address */ + FLASH_Program_Fast(Address, (uint32_t)Data); + } + + return status; +} + +/** + * @brief Handle FLASH interrupt request. + * @retval None + */ +void HAL_FLASH_IRQHandler(void) +{ + uint32_t tmp_page; + + /* If the operation is completed, disable the PG, PNB, MER1, MER2 and PER Bit */ + CLEAR_BIT(FLASH->CR, (FLASH_CR_PG | FLASH_CR_MER1 | FLASH_CR_PER | FLASH_CR_PNB)); +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + CLEAR_BIT(FLASH->CR, FLASH_CR_MER2); +#endif + + /* Disable the FSTPG Bit only if it is the last row programmed */ + if(pFlash.ProcedureOnGoing == FLASH_PROC_PROGRAM_LAST) + { + CLEAR_BIT(FLASH->CR, FLASH_CR_FSTPG); + } + + /* Check FLASH operation error flags */ + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) || +#if defined (STM32L431xx) || defined (STM32L432xx) || defined (STM32L433xx) || defined (STM32L442xx) || defined (STM32L443xx) || \ + defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PEMPTY))) +#else + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD))) +#endif + { + /*Save the error code*/ + FLASH_SetErrorCode(); + + /* Flush the caches to be sure of the data consistency */ + FLASH_FlushCaches() ; + + /* FLASH error interrupt user callback */ + if(pFlash.ProcedureOnGoing == FLASH_PROC_PAGE_ERASE) + { + HAL_FLASH_OperationErrorCallback(pFlash.Page); + } + else if(pFlash.ProcedureOnGoing == FLASH_PROC_MASS_ERASE) + { + HAL_FLASH_OperationErrorCallback(pFlash.Bank); + } + else if((pFlash.ProcedureOnGoing == FLASH_PROC_PROGRAM) || + (pFlash.ProcedureOnGoing == FLASH_PROC_PROGRAM_LAST)) + { + HAL_FLASH_OperationErrorCallback(pFlash.Address); + } + + /*Stop the procedure ongoing*/ + pFlash.ProcedureOnGoing = FLASH_PROC_NONE; + } + + /* Check FLASH End of Operation flag */ + if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP)) + { + /* Clear FLASH End of Operation pending bit */ + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP); + + if(pFlash.ProcedureOnGoing == FLASH_PROC_PAGE_ERASE) + { + /* Nb of pages to erased can be decreased */ + pFlash.NbPagesToErase--; + + /* Check if there are still pages to erase*/ + if(pFlash.NbPagesToErase != 0) + { + /* Indicate user which page has been erased*/ + HAL_FLASH_EndOfOperationCallback(pFlash.Page); + + /* Increment page number */ + pFlash.Page++; + tmp_page = pFlash.Page; + FLASH_PageErase(tmp_page, pFlash.Bank); + } + else + { + /* No more pages to Erase */ + /* Reset Address and stop Erase pages procedure */ + pFlash.Page = 0xFFFFFFFF; + pFlash.ProcedureOnGoing = FLASH_PROC_NONE; + + /* Flush the caches to be sure of the data consistency */ + FLASH_FlushCaches() ; + + /* FLASH EOP interrupt user callback */ + HAL_FLASH_EndOfOperationCallback(pFlash.Page); + } + } + else + { + /* Flush the caches to be sure of the data consistency */ + FLASH_FlushCaches() ; + + if(pFlash.ProcedureOnGoing == FLASH_PROC_MASS_ERASE) + { + /* MassErase ended. Return the selected bank */ + /* FLASH EOP interrupt user callback */ + HAL_FLASH_EndOfOperationCallback(pFlash.Bank); + } + else if((pFlash.ProcedureOnGoing == FLASH_PROC_PROGRAM) || + (pFlash.ProcedureOnGoing == FLASH_PROC_PROGRAM_LAST)) + { + /* Program ended. Return the selected address */ + /* FLASH EOP interrupt user callback */ + HAL_FLASH_EndOfOperationCallback(pFlash.Address); + } + + /*Clear the procedure ongoing*/ + pFlash.ProcedureOnGoing = FLASH_PROC_NONE; + } + } + + if(pFlash.ProcedureOnGoing == FLASH_PROC_NONE) + { + /* Disable End of Operation and Error interrupts */ + __HAL_FLASH_DISABLE_IT(FLASH_IT_EOP | FLASH_IT_OPERR); + + /* Process Unlocked */ + __HAL_UNLOCK(&pFlash); + } +} + +/** + * @brief FLASH end of operation interrupt callback. + * @param ReturnValue: The value saved in this parameter depends on the ongoing procedure + * Mass Erase: Bank number which has been requested to erase + * Page Erase: Page which has been erased + * (if 0xFFFFFFFF, it means that all the selected pages have been erased) + * Program: Address which was selected for data program + * @retval None + */ +__weak void HAL_FLASH_EndOfOperationCallback(uint32_t ReturnValue) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(ReturnValue); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_FLASH_EndOfOperationCallback could be implemented in the user file + */ +} + +/** + * @brief FLASH operation error interrupt callback. + * @param ReturnValue: The value saved in this parameter depends on the ongoing procedure + * Mass Erase: Bank number which has been requested to erase + * Page Erase: Page number which returned an error + * Program: Address which was selected for data program + * @retval None + */ +__weak void HAL_FLASH_OperationErrorCallback(uint32_t ReturnValue) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(ReturnValue); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_FLASH_OperationErrorCallback could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup FLASH_Exported_Functions_Group2 Peripheral Control functions + * @brief Management functions + * +@verbatim + =============================================================================== + ##### Peripheral Control functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to control the FLASH + memory operations. + +@endverbatim + * @{ + */ + +/** + * @brief Unlock the FLASH control register access. + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_FLASH_Unlock(void) +{ + HAL_StatusTypeDef status = HAL_OK; + + if(READ_BIT(FLASH->CR, FLASH_CR_LOCK) != RESET) + { + /* Authorize the FLASH Registers access */ + WRITE_REG(FLASH->KEYR, FLASH_KEY1); + WRITE_REG(FLASH->KEYR, FLASH_KEY2); + + /* Verify Flash is unlocked */ + if(READ_BIT(FLASH->CR, FLASH_CR_LOCK) != RESET) + { + status = HAL_ERROR; + } + } + + return status; +} + +/** + * @brief Lock the FLASH control register access. + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_FLASH_Lock(void) +{ + /* Set the LOCK Bit to lock the FLASH Registers access */ + SET_BIT(FLASH->CR, FLASH_CR_LOCK); + + return HAL_OK; +} + +/** + * @brief Unlock the FLASH Option Bytes Registers access. + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_FLASH_OB_Unlock(void) +{ + if(READ_BIT(FLASH->CR, FLASH_CR_OPTLOCK) != RESET) + { + /* Authorizes the Option Byte register programming */ + WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY1); + WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY2); + } + else + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief Lock the FLASH Option Bytes Registers access. + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_FLASH_OB_Lock(void) +{ + /* Set the OPTLOCK Bit to lock the FLASH Option Byte Registers access */ + SET_BIT(FLASH->CR, FLASH_CR_OPTLOCK); + + return HAL_OK; +} + +/** + * @brief Launch the option byte loading. + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_FLASH_OB_Launch(void) +{ + /* Set the bit to force the option byte reloading */ + SET_BIT(FLASH->CR, FLASH_CR_OBL_LAUNCH); + + /* Wait for last operation to be completed */ + return(FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE)); +} + +/** + * @} + */ + +/** @defgroup FLASH_Exported_Functions_Group3 Peripheral State and Errors functions + * @brief Peripheral Errors functions + * +@verbatim + =============================================================================== + ##### Peripheral Errors functions ##### + =============================================================================== + [..] + This subsection permits to get in run-time Errors of the FLASH peripheral. + +@endverbatim + * @{ + */ + +/** + * @brief Get the specific FLASH error flag. + * @retval FLASH_ErrorCode: The returned value can be: + * @arg HAL_FLASH_ERROR_RD: FLASH Read Protection error flag (PCROP) + * @arg HAL_FLASH_ERROR_PGS: FLASH Programming Sequence error flag + * @arg HAL_FLASH_ERROR_PGP: FLASH Programming Parallelism error flag + * @arg HAL_FLASH_ERROR_PGA: FLASH Programming Alignment error flag + * @arg HAL_FLASH_ERROR_WRP: FLASH Write protected error flag + * @arg HAL_FLASH_ERROR_OPERATION: FLASH operation Error flag + * @arg HAL_FLASH_ERROR_NONE: No error set + * @arg HAL_FLASH_ERROR_OP: FLASH Operation error + * @arg HAL_FLASH_ERROR_PROG: FLASH Programming error + * @arg HAL_FLASH_ERROR_WRP: FLASH Write protection error + * @arg HAL_FLASH_ERROR_PGA: FLASH Programming alignment error + * @arg HAL_FLASH_ERROR_SIZ: FLASH Size error + * @arg HAL_FLASH_ERROR_PGS: FLASH Programming sequence error + * @arg HAL_FLASH_ERROR_MIS: FLASH Fast programming data miss error + * @arg HAL_FLASH_ERROR_FAST: FLASH Fast programming error + * @arg HAL_FLASH_ERROR_RD: FLASH PCROP read error + * @arg HAL_FLASH_ERROR_OPTV: FLASH Option validity error + * @arg FLASH_FLAG_PEMPTY : FLASH Boot from not programmed flash (apply only for STM32L43x/STM32L44x devices) + * @arg HAL_FLASH_ERROR_ECCD: FLASH two ECC errors have been detected + */ +uint32_t HAL_FLASH_GetError(void) +{ + return pFlash.ErrorCode; +} + +/** + * @} + */ + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ + +/** @addtogroup FLASH_Private_Functions + * @{ + */ + +/** + * @brief Wait for a FLASH operation to complete. + * @param Timeout: maximum flash operation timeout + * @retval HAL_StatusTypeDef HAL Status + */ +HAL_StatusTypeDef FLASH_WaitForLastOperation(uint32_t Timeout) +{ + /* Wait for the FLASH operation to complete by polling on BUSY flag to be reset. + Even if the FLASH operation fails, the BUSY flag will be reset and an error + flag will be set */ + + uint32_t tickstart = HAL_GetTick(); + + while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) + { + if(Timeout != HAL_MAX_DELAY) + { + if((HAL_GetTick() - tickstart) >= Timeout) + { + return HAL_TIMEOUT; + } + } + } + + if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) || + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) || +#if defined (STM32L431xx) || defined (STM32L432xx) || defined (STM32L433xx) || defined (STM32L442xx) || defined (STM32L443xx) || \ + defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PEMPTY))) +#else + (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD))) +#endif + { + /*Save the error code*/ + FLASH_SetErrorCode(); + + return HAL_ERROR; + } + + /* Check FLASH End of Operation flag */ + if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP)) + { + /* Clear FLASH End of Operation pending bit */ + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP); + } + + /* If there is an error flag set */ + return HAL_OK; +} + +/** + * @brief Set the specific FLASH error flag. + * @retval None + */ +static void FLASH_SetErrorCode(void) +{ + if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR)) + { + pFlash.ErrorCode |= HAL_FLASH_ERROR_OP; + } + + if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) + { + pFlash.ErrorCode |= HAL_FLASH_ERROR_PROG; + } + + if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) + { + pFlash.ErrorCode |= HAL_FLASH_ERROR_WRP; + } + + if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR)) + { + pFlash.ErrorCode |= HAL_FLASH_ERROR_PGA; + } + + if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) + { + pFlash.ErrorCode |= HAL_FLASH_ERROR_SIZ; + } + + if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR)) + { + pFlash.ErrorCode |= HAL_FLASH_ERROR_PGS; + } + + if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) + { + pFlash.ErrorCode |= HAL_FLASH_ERROR_MIS; + } + + if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) + { + pFlash.ErrorCode |= HAL_FLASH_ERROR_FAST; + } + + if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR)) + { + pFlash.ErrorCode |= HAL_FLASH_ERROR_RD; + } + + if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) + { + pFlash.ErrorCode |= HAL_FLASH_ERROR_OPTV; + } + + if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD)) + { + pFlash.ErrorCode |= HAL_FLASH_ERROR_ECCD; + } + +#if defined (STM32L431xx) || defined (STM32L432xx) || defined (STM32L433xx) || defined (STM32L442xx) || defined (STM32L443xx) || \ + defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_PEMPTY)) + { + pFlash.ErrorCode |= HAL_FLASH_ERROR_PEMPTY; + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_PEMPTY); + } +#endif + + /* Clear error programming flags */ + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS); +} + +/** + * @brief Program double-word (64-bit) at a specified address. + * @param Address: specifies the address to be programmed. + * @param Data: specifies the data to be programmed. + * @retval None + */ +static void FLASH_Program_DoubleWord(uint32_t Address, uint64_t Data) +{ + /* Check the parameters */ + assert_param(IS_FLASH_PROGRAM_ADDRESS(Address)); + + /* Set PG bit */ + SET_BIT(FLASH->CR, FLASH_CR_PG); + + /* Program the double word */ + *(__IO uint32_t*)Address = (uint32_t)Data; + *(__IO uint32_t*)(Address+4) = (uint32_t)(Data >> 32); +} + +/** + * @brief Fast program a row double-word (64-bit) at a specified address. + * @param Address: specifies the address to be programmed. + * @param DataAddress: specifies the address where the data are stored. + * @retval None + */ +static void FLASH_Program_Fast(uint32_t Address, uint32_t DataAddress) +{ + uint8_t row_index = (2*FLASH_NB_DOUBLE_WORDS_IN_ROW); + __IO uint32_t *dest_addr = (__IO uint32_t*)Address; + __IO uint32_t *src_addr = (__IO uint32_t*)DataAddress; + + /* Check the parameters */ + assert_param(IS_FLASH_MAIN_MEM_ADDRESS(Address)); + + /* Set FSTPG bit */ + SET_BIT(FLASH->CR, FLASH_CR_FSTPG); + + /* Disable interrupts to avoid any interruption during the loop */ + __disable_irq(); + + /* Program the double word of the row */ + do + { + *dest_addr++ = *src_addr++; + } while (--row_index != 0); + + /* Re-enable the interrupts */ + __enable_irq(); +} + +/** + * @} + */ + +#endif /* HAL_FLASH_MODULE_ENABLED */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash_ex.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash_ex.c new file mode 100644 index 0000000..8f09359 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash_ex.c @@ -0,0 +1,1305 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_flash_ex.c + * @author MCD Application Team + * @brief Extended FLASH HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the FLASH extended peripheral: + * + Extended programming operations functions + * + @verbatim + ============================================================================== + ##### Flash Extended features ##### + ============================================================================== + + [..] Comparing to other previous devices, the FLASH interface for STM32L4xx + devices contains the following additional features + + (+) Capacity up to 2 Mbyte with dual bank architecture supporting read-while-write + capability (RWW) + (+) Dual bank memory organization + (+) PCROP protection for all banks + + ##### How to use this driver ##### + ============================================================================== + [..] This driver provides functions to configure and program the FLASH memory + of all STM32L4xx devices. It includes + (#) Flash Memory Erase functions: + (++) Lock and Unlock the FLASH interface using HAL_FLASH_Unlock() and + HAL_FLASH_Lock() functions + (++) Erase function: Erase page, erase all sectors + (++) There are two modes of erase : + (+++) Polling Mode using HAL_FLASHEx_Erase() + (+++) Interrupt Mode using HAL_FLASHEx_Erase_IT() + + (#) Option Bytes Programming function: Use HAL_FLASHEx_OBProgram() to : + (++) Set/Reset the write protection + (++) Set the Read protection Level + (++) Program the user Option Bytes + (++) Configure the PCROP protection + + (#) Get Option Bytes Configuration function: Use HAL_FLASHEx_OBGetConfig() to : + (++) Get the value of a write protection area + (++) Know if the read protection is activated + (++) Get the value of the user Option Bytes + (++) Get the value of a PCROP area + + @endverbatim + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup FLASHEx FLASHEx + * @brief FLASH Extended HAL module driver + * @{ + */ + +#ifdef HAL_FLASH_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/** @defgroup FLASHEx_Private_Variables FLASHEx Private Variables + * @{ + */ +extern FLASH_ProcessTypeDef pFlash; +/** + * @} + */ + +/* Private function prototypes -----------------------------------------------*/ +/** @defgroup FLASHEx_Private_Functions FLASHEx Private Functions + * @{ + */ +extern HAL_StatusTypeDef FLASH_WaitForLastOperation(uint32_t Timeout); +void FLASH_PageErase(uint32_t Page, uint32_t Banks); +static void FLASH_MassErase(uint32_t Banks); +void FLASH_FlushCaches(void); +static HAL_StatusTypeDef FLASH_OB_WRPConfig(uint32_t WRPArea, uint32_t WRPStartOffset, uint32_t WRDPEndOffset); +static HAL_StatusTypeDef FLASH_OB_RDPConfig(uint32_t RDPLevel); +static HAL_StatusTypeDef FLASH_OB_UserConfig(uint32_t UserType, uint32_t UserConfig); +static HAL_StatusTypeDef FLASH_OB_PCROPConfig(uint32_t PCROPConfig, uint32_t PCROPStartAddr, uint32_t PCROPEndAddr); +static void FLASH_OB_GetWRP(uint32_t WRPArea, uint32_t * WRPStartOffset, uint32_t * WRDPEndOffset); +static uint32_t FLASH_OB_GetRDP(void); +static uint32_t FLASH_OB_GetUser(void); +static void FLASH_OB_GetPCROP(uint32_t * PCROPConfig, uint32_t * PCROPStartAddr, uint32_t * PCROPEndAddr); +/** + * @} + */ + +/* Exported functions -------------------------------------------------------*/ +/** @defgroup FLASHEx_Exported_Functions FLASHEx Exported Functions + * @{ + */ + +/** @defgroup FLASHEx_Exported_Functions_Group1 Extended IO operation functions + * @brief Extended IO operation functions + * +@verbatim + =============================================================================== + ##### Extended programming operation functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to manage the Extended FLASH + programming operations Operations. + +@endverbatim + * @{ + */ +/** + * @brief Perform a mass erase or erase the specified FLASH memory pages. + * @param[in] pEraseInit: pointer to an FLASH_EraseInitTypeDef structure that + * contains the configuration information for the erasing. + * + * @param[out] PageError : pointer to variable that contains the configuration + * information on faulty page in case of error (0xFFFFFFFF means that all + * the pages have been correctly erased) + * + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *PageError) +{ + HAL_StatusTypeDef status = HAL_ERROR; + uint32_t page_index = 0; + + /* Process Locked */ + __HAL_LOCK(&pFlash); + + /* Check the parameters */ + assert_param(IS_FLASH_TYPEERASE(pEraseInit->TypeErase)); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); + + if (status == HAL_OK) + { + pFlash.ErrorCode = HAL_FLASH_ERROR_NONE; + + /* Deactivate the cache if they are activated to avoid data misbehavior */ + if(READ_BIT(FLASH->ACR, FLASH_ACR_ICEN) != RESET) + { + /* Disable instruction cache */ + __HAL_FLASH_INSTRUCTION_CACHE_DISABLE(); + + if(READ_BIT(FLASH->ACR, FLASH_ACR_DCEN) != RESET) + { + /* Disable data cache */ + __HAL_FLASH_DATA_CACHE_DISABLE(); + pFlash.CacheToReactivate = FLASH_CACHE_ICACHE_DCACHE_ENABLED; + } + else + { + pFlash.CacheToReactivate = FLASH_CACHE_ICACHE_ENABLED; + } + } + else if(READ_BIT(FLASH->ACR, FLASH_ACR_DCEN) != RESET) + { + /* Disable data cache */ + __HAL_FLASH_DATA_CACHE_DISABLE(); + pFlash.CacheToReactivate = FLASH_CACHE_DCACHE_ENABLED; + } + else + { + pFlash.CacheToReactivate = FLASH_CACHE_DISABLED; + } + + if (pEraseInit->TypeErase == FLASH_TYPEERASE_MASSERASE) + { + /* Mass erase to be done */ + FLASH_MassErase(pEraseInit->Banks); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); + +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + /* If the erase operation is completed, disable the MER1 and MER2 Bits */ + CLEAR_BIT(FLASH->CR, (FLASH_CR_MER1 | FLASH_CR_MER2)); +#else + /* If the erase operation is completed, disable the MER1 Bit */ + CLEAR_BIT(FLASH->CR, (FLASH_CR_MER1)); +#endif + } + else + { + /*Initialization of PageError variable*/ + *PageError = 0xFFFFFFFF; + + for(page_index = pEraseInit->Page; page_index < (pEraseInit->Page + pEraseInit->NbPages); page_index++) + { + FLASH_PageErase(page_index, pEraseInit->Banks); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); + + /* If the erase operation is completed, disable the PER Bit */ + CLEAR_BIT(FLASH->CR, (FLASH_CR_PER | FLASH_CR_PNB)); + + if (status != HAL_OK) + { + /* In case of error, stop erase procedure and return the faulty address */ + *PageError = page_index; + break; + } + } + } + + /* Flush the caches to be sure of the data consistency */ + FLASH_FlushCaches(); + } + + /* Process Unlocked */ + __HAL_UNLOCK(&pFlash); + + return status; +} + +/** + * @brief Perform a mass erase or erase the specified FLASH memory pages with interrupt enabled. + * @param pEraseInit: pointer to an FLASH_EraseInitTypeDef structure that + * contains the configuration information for the erasing. + * + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_FLASHEx_Erase_IT(FLASH_EraseInitTypeDef *pEraseInit) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process Locked */ + __HAL_LOCK(&pFlash); + + /* Check the parameters */ + assert_param(IS_FLASH_TYPEERASE(pEraseInit->TypeErase)); + + pFlash.ErrorCode = HAL_FLASH_ERROR_NONE; + + /* Deactivate the cache if they are activated to avoid data misbehavior */ + if(READ_BIT(FLASH->ACR, FLASH_ACR_ICEN) != RESET) + { + /* Disable instruction cache */ + __HAL_FLASH_INSTRUCTION_CACHE_DISABLE(); + + if(READ_BIT(FLASH->ACR, FLASH_ACR_DCEN) != RESET) + { + /* Disable data cache */ + __HAL_FLASH_DATA_CACHE_DISABLE(); + pFlash.CacheToReactivate = FLASH_CACHE_ICACHE_DCACHE_ENABLED; + } + else + { + pFlash.CacheToReactivate = FLASH_CACHE_ICACHE_ENABLED; + } + } + else if(READ_BIT(FLASH->ACR, FLASH_ACR_DCEN) != RESET) + { + /* Disable data cache */ + __HAL_FLASH_DATA_CACHE_DISABLE(); + pFlash.CacheToReactivate = FLASH_CACHE_DCACHE_ENABLED; + } + else + { + pFlash.CacheToReactivate = FLASH_CACHE_DISABLED; + } + + /* Enable End of Operation and Error interrupts */ + __HAL_FLASH_ENABLE_IT(FLASH_IT_EOP | FLASH_IT_OPERR); + + pFlash.Bank = pEraseInit->Banks; + + if (pEraseInit->TypeErase == FLASH_TYPEERASE_MASSERASE) + { + /* Mass erase to be done */ + pFlash.ProcedureOnGoing = FLASH_PROC_MASS_ERASE; + FLASH_MassErase(pEraseInit->Banks); + } + else + { + /* Erase by page to be done */ + pFlash.ProcedureOnGoing = FLASH_PROC_PAGE_ERASE; + pFlash.NbPagesToErase = pEraseInit->NbPages; + pFlash.Page = pEraseInit->Page; + + /*Erase 1st page and wait for IT */ + FLASH_PageErase(pEraseInit->Page, pEraseInit->Banks); + } + + return status; +} + +/** + * @brief Program Option bytes. + * @param pOBInit: pointer to an FLASH_OBInitStruct structure that + * contains the configuration information for the programming. + * + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_FLASHEx_OBProgram(FLASH_OBProgramInitTypeDef *pOBInit) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process Locked */ + __HAL_LOCK(&pFlash); + + /* Check the parameters */ + assert_param(IS_OPTIONBYTE(pOBInit->OptionType)); + + pFlash.ErrorCode = HAL_FLASH_ERROR_NONE; + + /* Write protection configuration */ + if((pOBInit->OptionType & OPTIONBYTE_WRP) != RESET) + { + /* Configure of Write protection on the selected area */ + if(FLASH_OB_WRPConfig(pOBInit->WRPArea, pOBInit->WRPStartOffset, pOBInit->WRPEndOffset) != HAL_OK) + { + status = HAL_ERROR; + } + + } + + /* Read protection configuration */ + if((pOBInit->OptionType & OPTIONBYTE_RDP) != RESET) + { + /* Configure the Read protection level */ + if(FLASH_OB_RDPConfig(pOBInit->RDPLevel) != HAL_OK) + { + status = HAL_ERROR; + } + } + + /* User Configuration */ + if((pOBInit->OptionType & OPTIONBYTE_USER) != RESET) + { + /* Configure the user option bytes */ + if(FLASH_OB_UserConfig(pOBInit->USERType, pOBInit->USERConfig) != HAL_OK) + { + status = HAL_ERROR; + } + } + + /* PCROP Configuration */ + if((pOBInit->OptionType & OPTIONBYTE_PCROP) != RESET) + { + if (pOBInit->PCROPStartAddr != pOBInit->PCROPEndAddr) + { + /* Configure the Proprietary code readout protection */ + if(FLASH_OB_PCROPConfig(pOBInit->PCROPConfig, pOBInit->PCROPStartAddr, pOBInit->PCROPEndAddr) != HAL_OK) + { + status = HAL_ERROR; + } + } + } + + /* Process Unlocked */ + __HAL_UNLOCK(&pFlash); + + return status; +} + +/** + * @brief Get the Option bytes configuration. + * @param pOBInit: pointer to an FLASH_OBInitStruct structure that contains the + * configuration information. + * @note The fields pOBInit->WRPArea and pOBInit->PCROPConfig should indicate + * which area is requested for the WRP and PCROP, else no information will be returned + * + * @retval None + */ +void HAL_FLASHEx_OBGetConfig(FLASH_OBProgramInitTypeDef *pOBInit) +{ + pOBInit->OptionType = (OPTIONBYTE_RDP | OPTIONBYTE_USER); + +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + if((pOBInit->WRPArea == OB_WRPAREA_BANK1_AREAA) || (pOBInit->WRPArea == OB_WRPAREA_BANK1_AREAB) || + (pOBInit->WRPArea == OB_WRPAREA_BANK2_AREAA) || (pOBInit->WRPArea == OB_WRPAREA_BANK2_AREAB)) +#else + if((pOBInit->WRPArea == OB_WRPAREA_BANK1_AREAA) || (pOBInit->WRPArea == OB_WRPAREA_BANK1_AREAB)) +#endif + { + pOBInit->OptionType |= OPTIONBYTE_WRP; + /* Get write protection on the selected area */ + FLASH_OB_GetWRP(pOBInit->WRPArea, &(pOBInit->WRPStartOffset), &(pOBInit->WRPEndOffset)); + } + + /* Get Read protection level */ + pOBInit->RDPLevel = FLASH_OB_GetRDP(); + + /* Get the user option bytes */ + pOBInit->USERConfig = FLASH_OB_GetUser(); + +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + if((pOBInit->PCROPConfig == FLASH_BANK_1) || (pOBInit->PCROPConfig == FLASH_BANK_2)) +#else + if(pOBInit->PCROPConfig == FLASH_BANK_1) +#endif + { + pOBInit->OptionType |= OPTIONBYTE_PCROP; + /* Get the Proprietary code readout protection */ + FLASH_OB_GetPCROP(&(pOBInit->PCROPConfig), &(pOBInit->PCROPStartAddr), &(pOBInit->PCROPEndAddr)); + } +} + +/** + * @} + */ + +#if defined (FLASH_CFGR_LVEN) +/** @defgroup FLASHEx_Exported_Functions_Group2 Extended specific configuration functions + * @brief Extended specific configuration functions + * +@verbatim + =============================================================================== + ##### Extended specific configuration functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to manage the Extended FLASH + specific configurations. + +@endverbatim + * @{ + */ + +/** + * @brief Configuration of the LVE pin of the Flash (managed by power controller + * or forced to low in order to use an external SMPS) + * @param ConfigLVE: Configuration of the LVE pin, + * This parameter can be one of the following values: + * @arg FLASH_LVE_PIN_CTRL: LVE FLASH pin controlled by power controller + * @arg FLASH_LVE_PIN_FORCED: LVE FLASH pin enforced to low (external SMPS used) + * + * @note Before enforcing the LVE pin to low, the SOC should be in low voltage + * range 2 and the voltage VDD12 should be higher than 1.08V and SMPS is ON. + * + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_FLASHEx_ConfigLVEPin(uint32_t ConfigLVE) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process Locked */ + __HAL_LOCK(&pFlash); + + /* Check the parameters */ + assert_param(IS_FLASH_LVE_PIN(ConfigLVE)); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); + + if (status == HAL_OK) + { + /* Check that the voltage scaling is range 2 */ + if (HAL_PWREx_GetVoltageRange() == PWR_REGULATOR_VOLTAGE_SCALE2) + { + /* Configure the LVEN bit */ + MODIFY_REG(FLASH->CFGR, FLASH_CFGR_LVEN, ConfigLVE); + + /* Check that the bit has been correctly configured */ + if (READ_BIT(FLASH->CFGR, FLASH_CFGR_LVEN) != ConfigLVE) + { + status = HAL_ERROR; + } + } + else + { + /* Not allow to force Flash LVE pin if not in voltage range 2 */ + status = HAL_ERROR; + } + } + + /* Process Unlocked */ + __HAL_UNLOCK(&pFlash); + + return status; +} + +/** + * @} + */ +#endif /* FLASH_CFGR_LVEN */ + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ + +/** @addtogroup FLASHEx_Private_Functions + * @{ + */ +/** + * @brief Mass erase of FLASH memory. + * @param Banks: Banks to be erased + * This parameter can be one of the following values: + * @arg FLASH_BANK_1: Bank1 to be erased + * @arg FLASH_BANK_2: Bank2 to be erased + * @arg FLASH_BANK_BOTH: Bank1 and Bank2 to be erased + * @retval None + */ +static void FLASH_MassErase(uint32_t Banks) +{ +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + if (READ_BIT(FLASH->OPTR, FLASH_OPTR_DBANK) != RESET) +#endif + { + /* Check the parameters */ + assert_param(IS_FLASH_BANK(Banks)); + + /* Set the Mass Erase Bit for the bank 1 if requested */ + if((Banks & FLASH_BANK_1) != RESET) + { + SET_BIT(FLASH->CR, FLASH_CR_MER1); + } + +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + /* Set the Mass Erase Bit for the bank 2 if requested */ + if((Banks & FLASH_BANK_2) != RESET) + { + SET_BIT(FLASH->CR, FLASH_CR_MER2); + } +#endif + } +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + else + { + SET_BIT(FLASH->CR, (FLASH_CR_MER1 | FLASH_CR_MER2)); + } +#endif + + /* Proceed to erase all sectors */ + SET_BIT(FLASH->CR, FLASH_CR_STRT); +} + +/** + * @brief Erase the specified FLASH memory page. + * @param Page: FLASH page to erase + * This parameter must be a value between 0 and (max number of pages in the bank - 1) + * @param Banks: Bank(s) where the page will be erased + * This parameter can be one of the following values: + * @arg FLASH_BANK_1: Page in bank 1 to be erased + * @arg FLASH_BANK_2: Page in bank 2 to be erased + * @retval None + */ +void FLASH_PageErase(uint32_t Page, uint32_t Banks) +{ + /* Check the parameters */ + assert_param(IS_FLASH_PAGE(Page)); + +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + if(READ_BIT(FLASH->OPTR, FLASH_OPTR_DBANK) == RESET) + { + CLEAR_BIT(FLASH->CR, FLASH_CR_BKER); + } + else +#endif + { + assert_param(IS_FLASH_BANK_EXCLUSIVE(Banks)); + + if((Banks & FLASH_BANK_1) != RESET) + { + CLEAR_BIT(FLASH->CR, FLASH_CR_BKER); + } + else + { + SET_BIT(FLASH->CR, FLASH_CR_BKER); + } + } +#endif + + /* Proceed to erase the page */ + MODIFY_REG(FLASH->CR, FLASH_CR_PNB, (Page << POSITION_VAL(FLASH_CR_PNB))); + SET_BIT(FLASH->CR, FLASH_CR_PER); + SET_BIT(FLASH->CR, FLASH_CR_STRT); +} + +/** + * @brief Flush the instruction and data caches. + * @retval None + */ +void FLASH_FlushCaches(void) +{ + /* Flush instruction cache */ + if((pFlash.CacheToReactivate == FLASH_CACHE_ICACHE_ENABLED) || + (pFlash.CacheToReactivate == FLASH_CACHE_ICACHE_DCACHE_ENABLED)) + { + /* Reset instruction cache */ + __HAL_FLASH_INSTRUCTION_CACHE_RESET(); + /* Enable instruction cache */ + __HAL_FLASH_INSTRUCTION_CACHE_ENABLE(); + } + + /* Flush data cache */ + if((pFlash.CacheToReactivate == FLASH_CACHE_DCACHE_ENABLED) || + (pFlash.CacheToReactivate == FLASH_CACHE_ICACHE_DCACHE_ENABLED)) + { + /* Reset data cache */ + __HAL_FLASH_DATA_CACHE_RESET(); + /* Enable data cache */ + __HAL_FLASH_DATA_CACHE_ENABLE(); + } + + /* Reset internal variable */ + pFlash.CacheToReactivate = FLASH_CACHE_DISABLED; +} + +/** + * @brief Configure the write protection of the desired pages. + * + * @note When the memory read protection level is selected (RDP level = 1), + * it is not possible to program or erase Flash memory if the CPU debug + * features are connected (JTAG or single wire) or boot code is being + * executed from RAM or System flash, even if WRP is not activated. + * @note To configure the WRP options, the option lock bit OPTLOCK must be + * cleared with the call of the HAL_FLASH_OB_Unlock() function. + * @note To validate the WRP options, the option bytes must be reloaded + * through the call of the HAL_FLASH_OB_Launch() function. + * + * @param WRPArea: specifies the area to be configured. + * This parameter can be one of the following values: + * @arg OB_WRPAREA_BANK1_AREAA: Flash Bank 1 Area A + * @arg OB_WRPAREA_BANK1_AREAB: Flash Bank 1 Area B + * @arg OB_WRPAREA_BANK2_AREAA: Flash Bank 2 Area A (don't apply for STM32L43x/STM32L44x devices) + * @arg OB_WRPAREA_BANK2_AREAB: Flash Bank 2 Area B (don't apply for STM32L43x/STM32L44x devices) + * + * @param WRPStartOffset: specifies the start page of the write protected area + * This parameter can be page number between 0 and (max number of pages in the bank - 1) + * + * @param WRDPEndOffset: specifies the end page of the write protected area + * This parameter can be page number between WRPStartOffset and (max number of pages in the bank - 1) + * + * @retval HAL Status + */ +static HAL_StatusTypeDef FLASH_OB_WRPConfig(uint32_t WRPArea, uint32_t WRPStartOffset, uint32_t WRDPEndOffset) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check the parameters */ + assert_param(IS_OB_WRPAREA(WRPArea)); + assert_param(IS_FLASH_PAGE(WRPStartOffset)); + assert_param(IS_FLASH_PAGE(WRDPEndOffset)); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); + + if(status == HAL_OK) + { + /* Configure the write protected area */ + if(WRPArea == OB_WRPAREA_BANK1_AREAA) + { + MODIFY_REG(FLASH->WRP1AR, (FLASH_WRP1AR_WRP1A_STRT | FLASH_WRP1AR_WRP1A_END), + (WRPStartOffset | (WRDPEndOffset << 16))); + } + else if(WRPArea == OB_WRPAREA_BANK1_AREAB) + { + MODIFY_REG(FLASH->WRP1BR, (FLASH_WRP1BR_WRP1B_STRT | FLASH_WRP1BR_WRP1B_END), + (WRPStartOffset | (WRDPEndOffset << 16))); + } +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + else if(WRPArea == OB_WRPAREA_BANK2_AREAA) + { + MODIFY_REG(FLASH->WRP2AR, (FLASH_WRP2AR_WRP2A_STRT | FLASH_WRP2AR_WRP2A_END), + (WRPStartOffset | (WRDPEndOffset << 16))); + } + else if(WRPArea == OB_WRPAREA_BANK2_AREAB) + { + MODIFY_REG(FLASH->WRP2BR, (FLASH_WRP2BR_WRP2B_STRT | FLASH_WRP2BR_WRP2B_END), + (WRPStartOffset | (WRDPEndOffset << 16))); + } +#endif + + /* Set OPTSTRT Bit */ + SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); + + /* If the option byte program operation is completed, disable the OPTSTRT Bit */ + CLEAR_BIT(FLASH->CR, FLASH_CR_OPTSTRT); + } + + return status; +} + +/** + * @brief Set the read protection level. + * + * @note To configure the RDP level, the option lock bit OPTLOCK must be + * cleared with the call of the HAL_FLASH_OB_Unlock() function. + * @note To validate the RDP level, the option bytes must be reloaded + * through the call of the HAL_FLASH_OB_Launch() function. + * @note !!! Warning : When enabling OB_RDP level 2 it's no more possible + * to go back to level 1 or 0 !!! + * + * @param RDPLevel: specifies the read protection level. + * This parameter can be one of the following values: + * @arg OB_RDP_LEVEL_0: No protection + * @arg OB_RDP_LEVEL_1: Read protection of the memory + * @arg OB_RDP_LEVEL_2: Full chip protection + * + * @retval HAL status + */ +static HAL_StatusTypeDef FLASH_OB_RDPConfig(uint32_t RDPLevel) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check the parameters */ + assert_param(IS_OB_RDP_LEVEL(RDPLevel)); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); + + if(status == HAL_OK) + { + /* Configure the RDP level in the option bytes register */ + MODIFY_REG(FLASH->OPTR, FLASH_OPTR_RDP, RDPLevel); + + /* Set OPTSTRT Bit */ + SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); + + /* If the option byte program operation is completed, disable the OPTSTRT Bit */ + CLEAR_BIT(FLASH->CR, FLASH_CR_OPTSTRT); + } + + return status; +} + +/** + * @brief Program the FLASH User Option Byte. + * + * @note To configure the user option bytes, the option lock bit OPTLOCK must + * be cleared with the call of the HAL_FLASH_OB_Unlock() function. + * @note To validate the user option bytes, the option bytes must be reloaded + * through the call of the HAL_FLASH_OB_Launch() function. + * + * @param UserType: The FLASH User Option Bytes to be modified + * @param UserConfig: The FLASH User Option Bytes values: + * BOR_LEV(Bit8-10), nRST_STOP(Bit12), nRST_STDBY(Bit13), IWDG_SW(Bit16), + * IWDG_STOP(Bit17), IWDG_STDBY(Bit18), WWDG_SW(Bit19), BFB2(Bit20), + * DUALBANK(Bit21), nBOOT1(Bit23), SRAM2_PE(Bit24) and SRAM2_RST(Bit25). + * + * @retval HAL status + */ +static HAL_StatusTypeDef FLASH_OB_UserConfig(uint32_t UserType, uint32_t UserConfig) +{ + uint32_t optr_reg_val = 0; + uint32_t optr_reg_mask = 0; + HAL_StatusTypeDef status = HAL_OK; + + /* Check the parameters */ + assert_param(IS_OB_USER_TYPE(UserType)); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); + + if(status == HAL_OK) + { + if((UserType & OB_USER_BOR_LEV) != RESET) + { + /* BOR level option byte should be modified */ + assert_param(IS_OB_USER_BOR_LEVEL(UserConfig & FLASH_OPTR_BOR_LEV)); + + /* Set value and mask for BOR level option byte */ + optr_reg_val |= (UserConfig & FLASH_OPTR_BOR_LEV); + optr_reg_mask |= FLASH_OPTR_BOR_LEV; + } + + if((UserType & OB_USER_nRST_STOP) != RESET) + { + /* nRST_STOP option byte should be modified */ + assert_param(IS_OB_USER_STOP(UserConfig & FLASH_OPTR_nRST_STOP)); + + /* Set value and mask for nRST_STOP option byte */ + optr_reg_val |= (UserConfig & FLASH_OPTR_nRST_STOP); + optr_reg_mask |= FLASH_OPTR_nRST_STOP; + } + + if((UserType & OB_USER_nRST_STDBY) != RESET) + { + /* nRST_STDBY option byte should be modified */ + assert_param(IS_OB_USER_STANDBY(UserConfig & FLASH_OPTR_nRST_STDBY)); + + /* Set value and mask for nRST_STDBY option byte */ + optr_reg_val |= (UserConfig & FLASH_OPTR_nRST_STDBY); + optr_reg_mask |= FLASH_OPTR_nRST_STDBY; + } + + if((UserType & OB_USER_nRST_SHDW) != RESET) + { + /* nRST_SHDW option byte should be modified */ + assert_param(IS_OB_USER_SHUTDOWN(UserConfig & FLASH_OPTR_nRST_SHDW)); + + /* Set value and mask for nRST_SHDW option byte */ + optr_reg_val |= (UserConfig & FLASH_OPTR_nRST_SHDW); + optr_reg_mask |= FLASH_OPTR_nRST_SHDW; + } + + if((UserType & OB_USER_IWDG_SW) != RESET) + { + /* IWDG_SW option byte should be modified */ + assert_param(IS_OB_USER_IWDG(UserConfig & FLASH_OPTR_IWDG_SW)); + + /* Set value and mask for IWDG_SW option byte */ + optr_reg_val |= (UserConfig & FLASH_OPTR_IWDG_SW); + optr_reg_mask |= FLASH_OPTR_IWDG_SW; + } + + if((UserType & OB_USER_IWDG_STOP) != RESET) + { + /* IWDG_STOP option byte should be modified */ + assert_param(IS_OB_USER_IWDG_STOP(UserConfig & FLASH_OPTR_IWDG_STOP)); + + /* Set value and mask for IWDG_STOP option byte */ + optr_reg_val |= (UserConfig & FLASH_OPTR_IWDG_STOP); + optr_reg_mask |= FLASH_OPTR_IWDG_STOP; + } + + if((UserType & OB_USER_IWDG_STDBY) != RESET) + { + /* IWDG_STDBY option byte should be modified */ + assert_param(IS_OB_USER_IWDG_STDBY(UserConfig & FLASH_OPTR_IWDG_STDBY)); + + /* Set value and mask for IWDG_STDBY option byte */ + optr_reg_val |= (UserConfig & FLASH_OPTR_IWDG_STDBY); + optr_reg_mask |= FLASH_OPTR_IWDG_STDBY; + } + + if((UserType & OB_USER_WWDG_SW) != RESET) + { + /* WWDG_SW option byte should be modified */ + assert_param(IS_OB_USER_WWDG(UserConfig & FLASH_OPTR_WWDG_SW)); + + /* Set value and mask for WWDG_SW option byte */ + optr_reg_val |= (UserConfig & FLASH_OPTR_WWDG_SW); + optr_reg_mask |= FLASH_OPTR_WWDG_SW; + } + +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + if((UserType & OB_USER_BFB2) != RESET) + { + /* BFB2 option byte should be modified */ + assert_param(IS_OB_USER_BFB2(UserConfig & FLASH_OPTR_BFB2)); + + /* Set value and mask for BFB2 option byte */ + optr_reg_val |= (UserConfig & FLASH_OPTR_BFB2); + optr_reg_mask |= FLASH_OPTR_BFB2; + } + + if((UserType & OB_USER_DUALBANK) != RESET) + { +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + /* DUALBANK option byte should be modified */ + assert_param(IS_OB_USER_DUALBANK(UserConfig & FLASH_OPTR_DB1M)); + + /* Set value and mask for DUALBANK option byte */ + optr_reg_val |= (UserConfig & FLASH_OPTR_DB1M); + optr_reg_mask |= FLASH_OPTR_DB1M; +#else + /* DUALBANK option byte should be modified */ + assert_param(IS_OB_USER_DUALBANK(UserConfig & FLASH_OPTR_DUALBANK)); + + /* Set value and mask for DUALBANK option byte */ + optr_reg_val |= (UserConfig & FLASH_OPTR_DUALBANK); + optr_reg_mask |= FLASH_OPTR_DUALBANK; +#endif + } +#endif + + if((UserType & OB_USER_nBOOT1) != RESET) + { + /* nBOOT1 option byte should be modified */ + assert_param(IS_OB_USER_BOOT1(UserConfig & FLASH_OPTR_nBOOT1)); + + /* Set value and mask for nBOOT1 option byte */ + optr_reg_val |= (UserConfig & FLASH_OPTR_nBOOT1); + optr_reg_mask |= FLASH_OPTR_nBOOT1; + } + + if((UserType & OB_USER_SRAM2_PE) != RESET) + { + /* SRAM2_PE option byte should be modified */ + assert_param(IS_OB_USER_SRAM2_PARITY(UserConfig & FLASH_OPTR_SRAM2_PE)); + + /* Set value and mask for SRAM2_PE option byte */ + optr_reg_val |= (UserConfig & FLASH_OPTR_SRAM2_PE); + optr_reg_mask |= FLASH_OPTR_SRAM2_PE; + } + + if((UserType & OB_USER_SRAM2_RST) != RESET) + { + /* SRAM2_RST option byte should be modified */ + assert_param(IS_OB_USER_SRAM2_RST(UserConfig & FLASH_OPTR_SRAM2_RST)); + + /* Set value and mask for SRAM2_RST option byte */ + optr_reg_val |= (UserConfig & FLASH_OPTR_SRAM2_RST); + optr_reg_mask |= FLASH_OPTR_SRAM2_RST; + } + +#if defined (STM32L431xx) || defined (STM32L432xx) || defined (STM32L433xx) || defined (STM32L442xx) || \ + defined (STM32L443xx) || defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + if((UserType & OB_USER_nSWBOOT0) != RESET) + { + /* nSWBOOT0 option byte should be modified */ + assert_param(IS_OB_USER_SWBOOT0(UserConfig & FLASH_OPTR_nSWBOOT0)); + + /* Set value and mask for nSWBOOT0 option byte */ + optr_reg_val |= (UserConfig & FLASH_OPTR_nSWBOOT0); + optr_reg_mask |= FLASH_OPTR_nSWBOOT0; + } + + if((UserType & OB_USER_nBOOT0) != RESET) + { + /* nBOOT0 option byte should be modified */ + assert_param(IS_OB_USER_BOOT0(UserConfig & FLASH_OPTR_nBOOT0)); + + /* Set value and mask for nBOOT0 option byte */ + optr_reg_val |= (UserConfig & FLASH_OPTR_nBOOT0); + optr_reg_mask |= FLASH_OPTR_nBOOT0; + } +#endif + + /* Configure the option bytes register */ + MODIFY_REG(FLASH->OPTR, optr_reg_mask, optr_reg_val); + + /* Set OPTSTRT Bit */ + SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); + + /* If the option byte program operation is completed, disable the OPTSTRT Bit */ + CLEAR_BIT(FLASH->CR, FLASH_CR_OPTSTRT); + } + + return status; +} + +/** + * @brief Configure the Proprietary code readout protection of the desired addresses. + * + * @note To configure the PCROP options, the option lock bit OPTLOCK must be + * cleared with the call of the HAL_FLASH_OB_Unlock() function. + * @note To validate the PCROP options, the option bytes must be reloaded + * through the call of the HAL_FLASH_OB_Launch() function. + * + * @param PCROPConfig: specifies the configuration (Bank to be configured and PCROP_RDP option). + * This parameter must be a combination of FLASH_BANK_1 or FLASH_BANK_2 + * with OB_PCROP_RDP_NOT_ERASE or OB_PCROP_RDP_ERASE + * + * @param PCROPStartAddr: specifies the start address of the Proprietary code readout protection + * This parameter can be an address between begin and end of the bank + * + * @param PCROPEndAddr: specifies the end address of the Proprietary code readout protection + * This parameter can be an address between PCROPStartAddr and end of the bank + * + * @retval HAL Status + */ +static HAL_StatusTypeDef FLASH_OB_PCROPConfig(uint32_t PCROPConfig, uint32_t PCROPStartAddr, uint32_t PCROPEndAddr) +{ + HAL_StatusTypeDef status = HAL_OK; + uint32_t reg_value = 0; + uint32_t bank1_addr; +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + uint32_t bank2_addr; +#endif + + /* Check the parameters */ + assert_param(IS_FLASH_BANK_EXCLUSIVE(PCROPConfig & FLASH_BANK_BOTH)); + assert_param(IS_OB_PCROP_RDP(PCROPConfig & FLASH_PCROP1ER_PCROP_RDP)); + assert_param(IS_FLASH_MAIN_MEM_ADDRESS(PCROPStartAddr)); + assert_param(IS_FLASH_MAIN_MEM_ADDRESS(PCROPEndAddr)); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); + + if(status == HAL_OK) + { +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + /* Get the information about the bank swapping */ + if (READ_BIT(SYSCFG->MEMRMP, SYSCFG_MEMRMP_FB_MODE) == 0) + { + bank1_addr = FLASH_BASE; + bank2_addr = FLASH_BASE + FLASH_BANK_SIZE; + } + else + { + bank1_addr = FLASH_BASE + FLASH_BANK_SIZE; + bank2_addr = FLASH_BASE; + } +#else + bank1_addr = FLASH_BASE; +#endif + +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + if (READ_BIT(FLASH->OPTR, FLASH_OPTR_DBANK) == RESET) + { + /* Configure the Proprietary code readout protection */ + if((PCROPConfig & FLASH_BANK_BOTH) == FLASH_BANK_1) + { + reg_value = ((PCROPStartAddr - FLASH_BASE) >> 4); + MODIFY_REG(FLASH->PCROP1SR, FLASH_PCROP1SR_PCROP1_STRT, reg_value); + + reg_value = ((PCROPEndAddr - FLASH_BASE) >> 4); + MODIFY_REG(FLASH->PCROP1ER, FLASH_PCROP1ER_PCROP1_END, reg_value); + } + else if((PCROPConfig & FLASH_BANK_BOTH) == FLASH_BANK_2) + { + reg_value = ((PCROPStartAddr - FLASH_BASE) >> 4); + MODIFY_REG(FLASH->PCROP2SR, FLASH_PCROP2SR_PCROP2_STRT, reg_value); + + reg_value = ((PCROPEndAddr - FLASH_BASE) >> 4); + MODIFY_REG(FLASH->PCROP2ER, FLASH_PCROP2ER_PCROP2_END, reg_value); + } + } + else +#endif + { + /* Configure the Proprietary code readout protection */ + if((PCROPConfig & FLASH_BANK_BOTH) == FLASH_BANK_1) + { + reg_value = ((PCROPStartAddr - bank1_addr) >> 3); + MODIFY_REG(FLASH->PCROP1SR, FLASH_PCROP1SR_PCROP1_STRT, reg_value); + + reg_value = ((PCROPEndAddr - bank1_addr) >> 3); + MODIFY_REG(FLASH->PCROP1ER, FLASH_PCROP1ER_PCROP1_END, reg_value); + } +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + else if((PCROPConfig & FLASH_BANK_BOTH) == FLASH_BANK_2) + { + reg_value = ((PCROPStartAddr - bank2_addr) >> 3); + MODIFY_REG(FLASH->PCROP2SR, FLASH_PCROP2SR_PCROP2_STRT, reg_value); + + reg_value = ((PCROPEndAddr - bank2_addr) >> 3); + MODIFY_REG(FLASH->PCROP2ER, FLASH_PCROP2ER_PCROP2_END, reg_value); + } +#endif + } + + MODIFY_REG(FLASH->PCROP1ER, FLASH_PCROP1ER_PCROP_RDP, (PCROPConfig & FLASH_PCROP1ER_PCROP_RDP)); + + /* Set OPTSTRT Bit */ + SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); + + /* If the option byte program operation is completed, disable the OPTSTRT Bit */ + CLEAR_BIT(FLASH->CR, FLASH_CR_OPTSTRT); + } + + return status; +} + +/** + * @brief Return the FLASH Write Protection Option Bytes value. + * + * @param[in] WRPArea: specifies the area to be returned. + * This parameter can be one of the following values: + * @arg OB_WRPAREA_BANK1_AREAA: Flash Bank 1 Area A + * @arg OB_WRPAREA_BANK1_AREAB: Flash Bank 1 Area B + * @arg OB_WRPAREA_BANK2_AREAA: Flash Bank 2 Area A (don't apply to STM32L43x/STM32L44x devices) + * @arg OB_WRPAREA_BANK2_AREAB: Flash Bank 2 Area B (don't apply to STM32L43x/STM32L44x devices) + * + * @param[out] WRPStartOffset: specifies the address where to copied the start page + * of the write protected area + * + * @param[out] WRDPEndOffset: specifies the address where to copied the end page of + * the write protected area + * + * @retval None + */ +static void FLASH_OB_GetWRP(uint32_t WRPArea, uint32_t * WRPStartOffset, uint32_t * WRDPEndOffset) +{ + /* Get the configuration of the write protected area */ + if(WRPArea == OB_WRPAREA_BANK1_AREAA) + { + *WRPStartOffset = READ_BIT(FLASH->WRP1AR, FLASH_WRP1AR_WRP1A_STRT); + *WRDPEndOffset = (READ_BIT(FLASH->WRP1AR, FLASH_WRP1AR_WRP1A_END) >> 16); + } + else if(WRPArea == OB_WRPAREA_BANK1_AREAB) + { + *WRPStartOffset = READ_BIT(FLASH->WRP1BR, FLASH_WRP1BR_WRP1B_STRT); + *WRDPEndOffset = (READ_BIT(FLASH->WRP1BR, FLASH_WRP1BR_WRP1B_END) >> 16); + } +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + else if(WRPArea == OB_WRPAREA_BANK2_AREAA) + { + *WRPStartOffset = READ_BIT(FLASH->WRP2AR, FLASH_WRP2AR_WRP2A_STRT); + *WRDPEndOffset = (READ_BIT(FLASH->WRP2AR, FLASH_WRP2AR_WRP2A_END) >> 16); + } + else if(WRPArea == OB_WRPAREA_BANK2_AREAB) + { + *WRPStartOffset = READ_BIT(FLASH->WRP2BR, FLASH_WRP2BR_WRP2B_STRT); + *WRDPEndOffset = (READ_BIT(FLASH->WRP2BR, FLASH_WRP2BR_WRP2B_END) >> 16); + } +#endif +} + +/** + * @brief Return the FLASH Read Protection level. + * @retval FLASH ReadOut Protection Status: + * This return value can be one of the following values: + * @arg OB_RDP_LEVEL_0: No protection + * @arg OB_RDP_LEVEL_1: Read protection of the memory + * @arg OB_RDP_LEVEL_2: Full chip protection + */ +static uint32_t FLASH_OB_GetRDP(void) +{ + if ((READ_BIT(FLASH->OPTR, FLASH_OPTR_RDP) != OB_RDP_LEVEL_0) && + (READ_BIT(FLASH->OPTR, FLASH_OPTR_RDP) != OB_RDP_LEVEL_2)) + { + return (OB_RDP_LEVEL_1); + } + else + { + return (READ_BIT(FLASH->OPTR, FLASH_OPTR_RDP)); + } +} + +/** + * @brief Return the FLASH User Option Byte value. + * @retval The FLASH User Option Bytes values: + * For STM32L47x/STM32L48x devices : + * BOR_LEV(Bit8-10), nRST_STOP(Bit12), nRST_STDBY(Bit13), nRST_SHDW(Bit14), + * IWDG_SW(Bit16), IWDG_STOP(Bit17), IWDG_STDBY(Bit18), WWDG_SW(Bit19), + * BFB2(Bit20), DUALBANK(Bit21), nBOOT1(Bit23), SRAM2_PE(Bit24) and SRAM2_RST(Bit25). + * For STM32L43x/STM32L44x devices : + * BOR_LEV(Bit8-10), nRST_STOP(Bit12), nRST_STDBY(Bit13), nRST_SHDW(Bit14), + * IWDG_SW(Bit16), IWDG_STOP(Bit17), IWDG_STDBY(Bit18), WWDG_SW(Bit19), + * nBOOT1(Bit23), SRAM2_PE(Bit24), SRAM2_RST(Bit25), nSWBOOT0(Bit26) and nBOOT0(Bit27). + */ +static uint32_t FLASH_OB_GetUser(void) +{ + uint32_t user_config = READ_REG(FLASH->OPTR); + CLEAR_BIT(user_config, FLASH_OPTR_RDP); + + return user_config; +} + +/** + * @brief Return the FLASH Write Protection Option Bytes value. + * + * @param PCROPConfig [inout]: specifies the configuration (Bank to be configured and PCROP_RDP option). + * This parameter must be a combination of FLASH_BANK_1 or FLASH_BANK_2 + * with OB_PCROP_RDP_NOT_ERASE or OB_PCROP_RDP_ERASE + * + * @param PCROPStartAddr [out]: specifies the address where to copied the start address + * of the Proprietary code readout protection + * + * @param PCROPEndAddr [out]: specifies the address where to copied the end address of + * the Proprietary code readout protection + * + * @retval None + */ +static void FLASH_OB_GetPCROP(uint32_t * PCROPConfig, uint32_t * PCROPStartAddr, uint32_t * PCROPEndAddr) +{ + uint32_t reg_value = 0; + uint32_t bank1_addr; +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + uint32_t bank2_addr; +#endif + +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + /* Get the information about the bank swapping */ + if (READ_BIT(SYSCFG->MEMRMP, SYSCFG_MEMRMP_FB_MODE) == 0) + { + bank1_addr = FLASH_BASE; + bank2_addr = FLASH_BASE + FLASH_BANK_SIZE; + } + else + { + bank1_addr = FLASH_BASE + FLASH_BANK_SIZE; + bank2_addr = FLASH_BASE; + } +#else + bank1_addr = FLASH_BASE; +#endif + +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + if (READ_BIT(FLASH->OPTR, FLASH_OPTR_DBANK) == RESET) + { + if(((*PCROPConfig) & FLASH_BANK_BOTH) == FLASH_BANK_1) + { + reg_value = (READ_REG(FLASH->PCROP1SR) & FLASH_PCROP1SR_PCROP1_STRT); + *PCROPStartAddr = (reg_value << 4) + FLASH_BASE; + + reg_value = (READ_REG(FLASH->PCROP1ER) & FLASH_PCROP1ER_PCROP1_END); + *PCROPEndAddr = (reg_value << 4) + FLASH_BASE; + } + else if(((*PCROPConfig) & FLASH_BANK_BOTH) == FLASH_BANK_2) + { + reg_value = (READ_REG(FLASH->PCROP2SR) & FLASH_PCROP2SR_PCROP2_STRT); + *PCROPStartAddr = (reg_value << 4) + FLASH_BASE; + + reg_value = (READ_REG(FLASH->PCROP2ER) & FLASH_PCROP2ER_PCROP2_END); + *PCROPEndAddr = (reg_value << 4) + FLASH_BASE; + } + } + else +#endif + { + if(((*PCROPConfig) & FLASH_BANK_BOTH) == FLASH_BANK_1) + { + reg_value = (READ_REG(FLASH->PCROP1SR) & FLASH_PCROP1SR_PCROP1_STRT); + *PCROPStartAddr = (reg_value << 3) + bank1_addr; + + reg_value = (READ_REG(FLASH->PCROP1ER) & FLASH_PCROP1ER_PCROP1_END); + *PCROPEndAddr = (reg_value << 3) + bank1_addr; + } +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + else if(((*PCROPConfig) & FLASH_BANK_BOTH) == FLASH_BANK_2) + { + reg_value = (READ_REG(FLASH->PCROP2SR) & FLASH_PCROP2SR_PCROP2_STRT); + *PCROPStartAddr = (reg_value << 3) + bank2_addr; + + reg_value = (READ_REG(FLASH->PCROP2ER) & FLASH_PCROP2ER_PCROP2_END); + *PCROPEndAddr = (reg_value << 3) + bank2_addr; + } +#endif + } + + *PCROPConfig |= (READ_REG(FLASH->PCROP1ER) & FLASH_PCROP1ER_PCROP_RDP); +} +/** + * @} + */ + +/** + * @} + */ + +#endif /* HAL_FLASH_MODULE_ENABLED */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash_ramfunc.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash_ramfunc.c new file mode 100644 index 0000000..537560f --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash_ramfunc.c @@ -0,0 +1,271 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_flash_ramfunc.c + * @author MCD Application Team + * @brief FLASH RAMFUNC driver. + * This file provides a Flash firmware functions which should be + * executed from internal SRAM + * + FLASH HalfPage Programming + * + FLASH Power Down in Run mode + * + * @verbatim + ============================================================================== + ##### Flash RAM functions ##### + ============================================================================== + + *** ARM Compiler *** + -------------------- + [..] RAM functions are defined using the toolchain options. + Functions that are executed in RAM should reside in a separate + source module. Using the 'Options for File' dialog you can simply change + the 'Code / Const' area of a module to a memory space in physical RAM. + Available memory areas are declared in the 'Target' tab of the + Options for Target' dialog. + + *** ICCARM Compiler *** + ----------------------- + [..] RAM functions are defined using a specific toolchain keyword "__ramfunc". + + *** GNU Compiler *** + -------------------- + [..] RAM functions are defined using a specific toolchain attribute + "__attribute__((section(".RamFunc")))". + + @endverbatim + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup FLASH_RAMFUNC FLASH_RAMFUNC + * @brief FLASH functions executed from RAM + * @{ + */ + +#ifdef HAL_FLASH_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +extern FLASH_ProcessTypeDef pFlash; + +/* Private function prototypes -----------------------------------------------*/ +/* Exported functions -------------------------------------------------------*/ + +/** @defgroup FLASH_RAMFUNC_Exported_Functions FLASH in RAM function Exported Functions + * @{ + */ + +/** @defgroup FLASH_RAMFUNC_Exported_Functions_Group1 Peripheral features functions + * @brief Data transfers functions + * +@verbatim + =============================================================================== + ##### ramfunc functions ##### + =============================================================================== + [..] + This subsection provides a set of functions that should be executed from RAM. + +@endverbatim + * @{ + */ + +/** + * @brief Enable the Power down in Run Mode + * @note This function should be called and executed from SRAM memory + * @retval None + */ +__RAM_FUNC HAL_FLASHEx_EnableRunPowerDown(void) +{ + /* Enable the Power Down in Run mode*/ + __HAL_FLASH_POWER_DOWN_ENABLE(); + + return HAL_OK; + +} + +/** + * @brief Disable the Power down in Run Mode + * @note This function should be called and executed from SRAM memory + * @retval None + */ +__RAM_FUNC HAL_FLASHEx_DisableRunPowerDown(void) +{ + /* Disable the Power Down in Run mode*/ + __HAL_FLASH_POWER_DOWN_DISABLE(); + + return HAL_OK; +} + +#if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +/** + * @brief Program the FLASH DBANK User Option Byte. + * + * @note To configure the user option bytes, the option lock bit OPTLOCK must + * be cleared with the call of the HAL_FLASH_OB_Unlock() function. + * @note To modify the DBANK option byte, no PCROP region should be defined. + * To deactivate PCROP, user should perform RDP changing + * + * @param DBankConfig: The FLASH DBANK User Option Byte value. + * This parameter can be one of the following values: + * @arg OB_DBANK_128_BITS: Single-bank with 128-bits data + * @arg OB_DBANK_64_BITS: Dual-bank with 64-bits data + * + * @retval HAL status + */ +__RAM_FUNC HAL_FLASHEx_OB_DBankConfig(uint32_t DBankConfig) +{ + register uint32_t count, reg; + HAL_StatusTypeDef status = HAL_ERROR; + + /* Process Locked */ + __HAL_LOCK(&pFlash); + + /* Check if the PCROP is disabled */ + reg = FLASH->PCROP1SR; + if (reg > FLASH->PCROP1ER) + { + reg = FLASH->PCROP2SR; + if (reg > FLASH->PCROP2ER) + { + /* Disable Flash prefetch */ + __HAL_FLASH_PREFETCH_BUFFER_DISABLE(); + + if (READ_BIT(FLASH->ACR, FLASH_ACR_ICEN) != RESET) + { + /* Disable Flash instruction cache */ + __HAL_FLASH_INSTRUCTION_CACHE_DISABLE(); + + /* Flush Flash instruction cache */ + __HAL_FLASH_INSTRUCTION_CACHE_RESET(); + } + + if (READ_BIT(FLASH->ACR, FLASH_ACR_DCEN) != RESET) + { + /* Disable Flash data cache */ + __HAL_FLASH_DATA_CACHE_DISABLE(); + + /* Flush Flash data cache */ + __HAL_FLASH_DATA_CACHE_RESET(); + } + + /* Disable WRP zone 1 of 1st bank if needed */ + reg = FLASH->WRP1AR; + if (((reg & FLASH_WRP1AR_WRP1A_STRT) >> POSITION_VAL(FLASH_WRP1AR_WRP1A_STRT)) <= + ((reg & FLASH_WRP1AR_WRP1A_END) >> POSITION_VAL(FLASH_WRP1AR_WRP1A_END))) + { + MODIFY_REG(FLASH->WRP1AR, (FLASH_WRP1AR_WRP1A_STRT | FLASH_WRP1AR_WRP1A_END), FLASH_WRP1AR_WRP1A_STRT); + } + + /* Disable WRP zone 2 of 1st bank if needed */ + reg = FLASH->WRP1BR; + if (((reg & FLASH_WRP1BR_WRP1B_STRT) >> POSITION_VAL(FLASH_WRP1BR_WRP1B_STRT)) <= + ((reg & FLASH_WRP1BR_WRP1B_END) >> POSITION_VAL(FLASH_WRP1BR_WRP1B_END))) + { + MODIFY_REG(FLASH->WRP1BR, (FLASH_WRP1BR_WRP1B_STRT | FLASH_WRP1BR_WRP1B_END), FLASH_WRP1BR_WRP1B_STRT); + } + + /* Disable WRP zone 1 of 2nd bank if needed */ + reg = FLASH->WRP2AR; + if (((reg & FLASH_WRP2AR_WRP2A_STRT) >> POSITION_VAL(FLASH_WRP2AR_WRP2A_STRT)) <= + ((reg & FLASH_WRP2AR_WRP2A_END) >> POSITION_VAL(FLASH_WRP2AR_WRP2A_END))) + { + MODIFY_REG(FLASH->WRP2AR, (FLASH_WRP2AR_WRP2A_STRT | FLASH_WRP2AR_WRP2A_END), FLASH_WRP2AR_WRP2A_STRT); + } + + /* Disable WRP zone 2 of 2nd bank if needed */ + reg = FLASH->WRP2BR; + if (((reg & FLASH_WRP2BR_WRP2B_STRT) >> POSITION_VAL(FLASH_WRP2BR_WRP2B_STRT)) <= + ((reg & FLASH_WRP2BR_WRP2B_END) >> POSITION_VAL(FLASH_WRP2BR_WRP2B_END))) + { + MODIFY_REG(FLASH->WRP2BR, (FLASH_WRP2BR_WRP2B_STRT | FLASH_WRP2BR_WRP2B_END), FLASH_WRP2BR_WRP2B_STRT); + } + + /* Modify the DBANK user option byte */ + MODIFY_REG(FLASH->OPTR, FLASH_OPTR_DBANK, DBankConfig); + + /* Set OPTSTRT Bit */ + SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT); + + /* Wait for last operation to be completed */ + /* 8 is the number of required instruction cycles for the below loop statement (timeout expressed in ms) */ + count = FLASH_TIMEOUT_VALUE * (SystemCoreClock / 8 / 1000); + do + { + if (count-- == 0) + { + break; + } + } while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY) != RESET); + + /* If the option byte program operation is completed, disable the OPTSTRT Bit */ + CLEAR_BIT(FLASH->CR, FLASH_CR_OPTSTRT); + + /* Set the bit to force the option byte reloading */ + SET_BIT(FLASH->CR, FLASH_CR_OBL_LAUNCH); + } + } + + /* Process Unlocked */ + __HAL_UNLOCK(&pFlash); + + return status; +} +#endif + +/** + * @} + */ + +/** + * @} + */ +#endif /* HAL_FLASH_MODULE_ENABLED */ + + + +/** + * @} + */ + +/** + * @} + */ + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + + diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_gpio.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_gpio.c new file mode 100644 index 0000000..a2cf329 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_gpio.c @@ -0,0 +1,568 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_gpio.c + * @author MCD Application Team + * @brief GPIO HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the General Purpose Input/Output (GPIO) peripheral: + * + Initialization and de-initialization functions + * + IO operation functions + * + @verbatim + ============================================================================== + ##### GPIO Peripheral features ##### + ============================================================================== + [..] + (+) Each port bit of the general-purpose I/O (GPIO) ports can be individually + configured by software in several modes: + (++) Input mode + (++) Analog mode + (++) Output mode + (++) Alternate function mode + (++) External interrupt/event lines + + (+) During and just after reset, the alternate functions and external interrupt + lines are not active and the I/O ports are configured in input floating mode. + + (+) All GPIO pins have weak internal pull-up and pull-down resistors, which can be + activated or not. + + (+) In Output or Alternate mode, each IO can be configured on open-drain or push-pull + type and the IO speed can be selected depending on the VDD value. + + (+) The microcontroller IO pins are connected to onboard peripherals/modules through a + multiplexer that allows only one peripheral alternate function (AF) connected + to an IO pin at a time. In this way, there can be no conflict between peripherals + sharing the same IO pin. + + (+) All ports have external interrupt/event capability. To use external interrupt + lines, the port must be configured in input mode. All available GPIO pins are + connected to the 16 external interrupt/event lines from EXTI0 to EXTI15. + + (+) The external interrupt/event controller consists of up to 39 edge detectors + (16 lines are connected to GPIO) for generating event/interrupt requests (each + input line can be independently configured to select the type (interrupt or event) + and the corresponding trigger event (rising or falling or both). Each line can + also be masked independently. + + ##### How to use this driver ##### + ============================================================================== + [..] + (#) Enable the GPIO AHB clock using the following function: __HAL_RCC_GPIOx_CLK_ENABLE(). + + (#) Configure the GPIO pin(s) using HAL_GPIO_Init(). + (++) Configure the IO mode using "Mode" member from GPIO_InitTypeDef structure + (++) Activate Pull-up, Pull-down resistor using "Pull" member from GPIO_InitTypeDef + structure. + (++) In case of Output or alternate function mode selection: the speed is + configured through "Speed" member from GPIO_InitTypeDef structure. + (++) In alternate mode is selection, the alternate function connected to the IO + is configured through "Alternate" member from GPIO_InitTypeDef structure. + (++) Analog mode is required when a pin is to be used as ADC channel + or DAC output. + (++) In case of external interrupt/event selection the "Mode" member from + GPIO_InitTypeDef structure select the type (interrupt or event) and + the corresponding trigger event (rising or falling or both). + + (#) In case of external interrupt/event mode selection, configure NVIC IRQ priority + mapped to the EXTI line using HAL_NVIC_SetPriority() and enable it using + HAL_NVIC_EnableIRQ(). + + (#) To get the level of a pin configured in input mode use HAL_GPIO_ReadPin(). + + (#) To set/reset the level of a pin configured in output mode use + HAL_GPIO_WritePin()/HAL_GPIO_TogglePin(). + + (#) To lock pin configuration until next reset use HAL_GPIO_LockPin(). + + (#) During and just after reset, the alternate functions are not + active and the GPIO pins are configured in input floating mode (except JTAG + pins). + + (#) The LSE oscillator pins OSC32_IN and OSC32_OUT can be used as general purpose + (PC14 and PC15, respectively) when the LSE oscillator is off. The LSE has + priority over the GPIO function. + + (#) The HSE oscillator pins OSC_IN/OSC_OUT can be used as + general purpose PH0 and PH1, respectively, when the HSE oscillator is off. + The HSE has priority over the GPIO function. + + @endverbatim + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup GPIO GPIO + * @brief GPIO HAL module driver + * @{ + */ + +#ifdef HAL_GPIO_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private defines -----------------------------------------------------------*/ +/** @defgroup GPIO_Private_Defines GPIO Private Defines + * @{ + */ +#define GPIO_MODE ((uint32_t)0x00000003) +#define ANALOG_MODE ((uint32_t)0x00000008) +#define EXTI_MODE ((uint32_t)0x10000000) +#define GPIO_MODE_IT ((uint32_t)0x00010000) +#define GPIO_MODE_EVT ((uint32_t)0x00020000) +#define RISING_EDGE ((uint32_t)0x00100000) +#define FALLING_EDGE ((uint32_t)0x00200000) +#define GPIO_OUTPUT_TYPE ((uint32_t)0x00000010) + +#define GPIO_NUMBER ((uint32_t)16) +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ +/** @defgroup GPIO_Private_Macros GPIO Private Macros + * @{ + */ +/** + * @} + */ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup GPIO_Exported_Functions GPIO Exported Functions + * @{ + */ + +/** @defgroup GPIO_Exported_Functions_Group1 Initialization/de-initialization functions + * @brief Initialization and Configuration functions + * +@verbatim + =============================================================================== + ##### Initialization and de-initialization functions ##### + =============================================================================== + +@endverbatim + * @{ + */ + +/** + * @brief Initialize the GPIOx peripheral according to the specified parameters in the GPIO_Init. + * @param GPIOx: where x can be (A..H) to select the GPIO peripheral for STM32L4 family + * @param GPIO_Init: pointer to a GPIO_InitTypeDef structure that contains + * the configuration information for the specified GPIO peripheral. + * @retval None + */ +void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init) +{ + uint32_t position = 0x00; + uint32_t iocurrent = 0x00; + uint32_t temp = 0x00; + + /* Check the parameters */ + assert_param(IS_GPIO_ALL_INSTANCE(GPIOx)); + assert_param(IS_GPIO_PIN(GPIO_Init->Pin)); + assert_param(IS_GPIO_MODE(GPIO_Init->Mode)); + assert_param(IS_GPIO_PULL(GPIO_Init->Pull)); + + /* Configure the port pins */ + while (((GPIO_Init->Pin) >> position) != RESET) + { + /* Get current io position */ + iocurrent = (GPIO_Init->Pin) & (1U << position); + + if(iocurrent) + { + /*--------------------- GPIO Mode Configuration ------------------------*/ + /* In case of Alternate function mode selection */ + if((GPIO_Init->Mode == GPIO_MODE_AF_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_OD)) + { + /* Check the Alternate function parameters */ + assert_param(IS_GPIO_AF_INSTANCE(GPIOx)); + assert_param(IS_GPIO_AF(GPIO_Init->Alternate)); + + /* Configure Alternate function mapped with the current IO */ + temp = GPIOx->AFR[position >> 3]; + temp &= ~((uint32_t)0xF << ((uint32_t)(position & (uint32_t)0x07) * 4)) ; + temp |= ((uint32_t)(GPIO_Init->Alternate) << (((uint32_t)position & (uint32_t)0x07) * 4)); + GPIOx->AFR[position >> 3] = temp; + } + + /* Configure IO Direction mode (Input, Output, Alternate or Analog) */ + temp = GPIOx->MODER; + temp &= ~(GPIO_MODER_MODE0 << (position * 2)); + temp |= ((GPIO_Init->Mode & GPIO_MODE) << (position * 2)); + GPIOx->MODER = temp; + + /* In case of Output or Alternate function mode selection */ + if((GPIO_Init->Mode == GPIO_MODE_OUTPUT_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_PP) || + (GPIO_Init->Mode == GPIO_MODE_OUTPUT_OD) || (GPIO_Init->Mode == GPIO_MODE_AF_OD)) + { + /* Check the Speed parameter */ + assert_param(IS_GPIO_SPEED(GPIO_Init->Speed)); + /* Configure the IO Speed */ + temp = GPIOx->OSPEEDR; + temp &= ~(GPIO_OSPEEDR_OSPEED0 << (position * 2)); + temp |= (GPIO_Init->Speed << (position * 2)); + GPIOx->OSPEEDR = temp; + + /* Configure the IO Output Type */ + temp = GPIOx->OTYPER; + temp &= ~(GPIO_OTYPER_OT0 << position) ; + temp |= (((GPIO_Init->Mode & GPIO_OUTPUT_TYPE) >> 4) << position); + GPIOx->OTYPER = temp; + } + +#if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) + + /* In case of Analog mode, check if ADC control mode is selected */ + if((GPIO_Init->Mode & GPIO_MODE_ANALOG) == GPIO_MODE_ANALOG) + { + /* Configure the IO Output Type */ + temp = GPIOx->ASCR; + temp &= ~(GPIO_ASCR_ASC0 << position) ; + temp |= (((GPIO_Init->Mode & ANALOG_MODE) >> 3) << position); + GPIOx->ASCR = temp; + } + +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx */ + + /* Activate the Pull-up or Pull down resistor for the current IO */ + temp = GPIOx->PUPDR; + temp &= ~(GPIO_PUPDR_PUPD0 << (position * 2)); + temp |= ((GPIO_Init->Pull) << (position * 2)); + GPIOx->PUPDR = temp; + + /*--------------------- EXTI Mode Configuration ------------------------*/ + /* Configure the External Interrupt or event for the current IO */ + if((GPIO_Init->Mode & EXTI_MODE) == EXTI_MODE) + { + /* Enable SYSCFG Clock */ + __HAL_RCC_SYSCFG_CLK_ENABLE(); + + temp = SYSCFG->EXTICR[position >> 2]; + temp &= ~(((uint32_t)0x0F) << (4 * (position & 0x03))); + temp |= (GPIO_GET_INDEX(GPIOx) << (4 * (position & 0x03))); + SYSCFG->EXTICR[position >> 2] = temp; + + /* Clear EXTI line configuration */ + temp = EXTI->IMR1; + temp &= ~((uint32_t)iocurrent); + if((GPIO_Init->Mode & GPIO_MODE_IT) == GPIO_MODE_IT) + { + temp |= iocurrent; + } + EXTI->IMR1 = temp; + + temp = EXTI->EMR1; + temp &= ~((uint32_t)iocurrent); + if((GPIO_Init->Mode & GPIO_MODE_EVT) == GPIO_MODE_EVT) + { + temp |= iocurrent; + } + EXTI->EMR1 = temp; + + /* Clear Rising Falling edge configuration */ + temp = EXTI->RTSR1; + temp &= ~((uint32_t)iocurrent); + if((GPIO_Init->Mode & RISING_EDGE) == RISING_EDGE) + { + temp |= iocurrent; + } + EXTI->RTSR1 = temp; + + temp = EXTI->FTSR1; + temp &= ~((uint32_t)iocurrent); + if((GPIO_Init->Mode & FALLING_EDGE) == FALLING_EDGE) + { + temp |= iocurrent; + } + EXTI->FTSR1 = temp; + } + } + + position++; + } +} + +/** + * @brief De-initialize the GPIOx peripheral registers to their default reset values. + * @param GPIOx: where x can be (A..H) to select the GPIO peripheral for STM32L4 family + * @param GPIO_Pin: specifies the port bit to be written. + * This parameter can be one of GPIO_PIN_x where x can be (0..15). + * @retval None + */ +void HAL_GPIO_DeInit(GPIO_TypeDef *GPIOx, uint32_t GPIO_Pin) +{ + uint32_t position = 0x00; + uint32_t iocurrent = 0x00; + uint32_t tmp = 0x00; + + /* Check the parameters */ + assert_param(IS_GPIO_ALL_INSTANCE(GPIOx)); + assert_param(IS_GPIO_PIN(GPIO_Pin)); + + /* Configure the port pins */ + while ((GPIO_Pin >> position) != RESET) + { + /* Get current io position */ + iocurrent = (GPIO_Pin) & (1U << position); + + if (iocurrent) + { + /*------------------------- GPIO Mode Configuration --------------------*/ + /* Configure IO in Analog Mode */ + GPIOx->MODER |= (GPIO_MODER_MODE0 << (position * 2)); + + /* Configure the default Alternate Function in current IO */ + GPIOx->AFR[position >> 3] &= ~((uint32_t)0xF << ((uint32_t)(position & (uint32_t)0x07) * 4)) ; + + /* Configure the default value for IO Speed */ + GPIOx->OSPEEDR &= ~(GPIO_OSPEEDR_OSPEED0 << (position * 2)); + + /* Configure the default value IO Output Type */ + GPIOx->OTYPER &= ~(GPIO_OTYPER_OT0 << position) ; + + /* Deactivate the Pull-up and Pull-down resistor for the current IO */ + GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPD0 << (position * 2)); + +#if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) + + /* Deactivate the Control bit of Analog mode for the current IO */ + GPIOx->ASCR &= ~(GPIO_ASCR_ASC0<< position); + +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx */ + + /*------------------------- EXTI Mode Configuration --------------------*/ + /* Clear the External Interrupt or Event for the current IO */ + + tmp = SYSCFG->EXTICR[position >> 2]; + tmp &= (((uint32_t)0x0F) << (4 * (position & 0x03))); + if(tmp == (GPIO_GET_INDEX(GPIOx) << (4 * (position & 0x03)))) + { + tmp = ((uint32_t)0x0F) << (4 * (position & 0x03)); + SYSCFG->EXTICR[position >> 2] &= ~tmp; + + /* Clear EXTI line configuration */ + EXTI->IMR1 &= ~((uint32_t)iocurrent); + EXTI->EMR1 &= ~((uint32_t)iocurrent); + + /* Clear Rising Falling edge configuration */ + EXTI->RTSR1 &= ~((uint32_t)iocurrent); + EXTI->FTSR1 &= ~((uint32_t)iocurrent); + } + } + + position++; + } +} + +/** + * @} + */ + +/** @defgroup GPIO_Exported_Functions_Group2 IO operation functions + * @brief GPIO Read, Write, Toggle, Lock and EXTI management functions. + * +@verbatim + =============================================================================== + ##### IO operation functions ##### + =============================================================================== + +@endverbatim + * @{ + */ + +/** + * @brief Read the specified input port pin. + * @param GPIOx: where x can be (A..H) to select the GPIO peripheral for STM32L4 family + * @param GPIO_Pin: specifies the port bit to read. + * This parameter can be GPIO_PIN_x where x can be (0..15). + * @retval The input port pin value. + */ +GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) +{ + GPIO_PinState bitstatus; + + /* Check the parameters */ + assert_param(IS_GPIO_PIN(GPIO_Pin)); + + if((GPIOx->IDR & GPIO_Pin) != (uint32_t)GPIO_PIN_RESET) + { + bitstatus = GPIO_PIN_SET; + } + else + { + bitstatus = GPIO_PIN_RESET; + } + return bitstatus; +} + +/** + * @brief Set or clear the selected data port bit. + * + * @note This function uses GPIOx_BSRR and GPIOx_BRR registers to allow atomic read/modify + * accesses. In this way, there is no risk of an IRQ occurring between + * the read and the modify access. + * + * @param GPIOx: where x can be (A..H) to select the GPIO peripheral for STM32L4 family + * @param GPIO_Pin: specifies the port bit to be written. + * This parameter can be one of GPIO_PIN_x where x can be (0..15). + * @param PinState: specifies the value to be written to the selected bit. + * This parameter can be one of the GPIO_PinState enum values: + * @arg GPIO_PIN_RESET: to clear the port pin + * @arg GPIO_PIN_SET: to set the port pin + * @retval None + */ +void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState) +{ + /* Check the parameters */ + assert_param(IS_GPIO_PIN(GPIO_Pin)); + assert_param(IS_GPIO_PIN_ACTION(PinState)); + + if(PinState != GPIO_PIN_RESET) + { + GPIOx->BSRR = (uint32_t)GPIO_Pin; + } + else + { + GPIOx->BRR = (uint32_t)GPIO_Pin; + } +} + +/** + * @brief Toggle the specified GPIO pin. + * @param GPIOx: where x can be (A..H) to select the GPIO peripheral for STM32L4 family + * @param GPIO_Pin: specifies the pin to be toggled. + * @retval None + */ +void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) +{ + /* Check the parameters */ + assert_param(IS_GPIO_PIN(GPIO_Pin)); + + GPIOx->ODR ^= GPIO_Pin; +} + +/** +* @brief Lock GPIO Pins configuration registers. + * @note The locked registers are GPIOx_MODER, GPIOx_OTYPER, GPIOx_OSPEEDR, + * GPIOx_PUPDR, GPIOx_AFRL and GPIOx_AFRH. + * @note The configuration of the locked GPIO pins can no longer be modified + * until the next reset. + * @param GPIOx: where x can be (A..H) to select the GPIO peripheral for STM32L4 family + * @param GPIO_Pin: specifies the port bits to be locked. + * This parameter can be any combination of GPIO_Pin_x where x can be (0..15). + * @retval None + */ +HAL_StatusTypeDef HAL_GPIO_LockPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) +{ + __IO uint32_t tmp = GPIO_LCKR_LCKK; + + /* Check the parameters */ + assert_param(IS_GPIO_LOCK_INSTANCE(GPIOx)); + assert_param(IS_GPIO_PIN(GPIO_Pin)); + + /* Apply lock key write sequence */ + tmp |= GPIO_Pin; + /* Set LCKx bit(s): LCKK='1' + LCK[15-0] */ + GPIOx->LCKR = tmp; + /* Reset LCKx bit(s): LCKK='0' + LCK[15-0] */ + GPIOx->LCKR = GPIO_Pin; + /* Set LCKx bit(s): LCKK='1' + LCK[15-0] */ + GPIOx->LCKR = tmp; + /* Read LCKK bit*/ + tmp = GPIOx->LCKR; + + if((GPIOx->LCKR & GPIO_LCKR_LCKK) != RESET) + { + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Handle EXTI interrupt request. + * @param GPIO_Pin: Specifies the port pin connected to corresponding EXTI line. + * @retval None + */ +void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin) +{ + /* EXTI line interrupt detected */ + if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != RESET) + { + __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin); + HAL_GPIO_EXTI_Callback(GPIO_Pin); + } +} + +/** + * @brief EXTI line detection callback. + * @param GPIO_Pin: Specifies the port pin connected to corresponding EXTI line. + * @retval None + */ +__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(GPIO_Pin); + + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_GPIO_EXTI_Callback could be implemented in the user file + */ +} + +/** + * @} + */ + + +/** + * @} + */ + +#endif /* HAL_GPIO_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_i2c.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_i2c.c new file mode 100644 index 0000000..63d38c3 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_i2c.c @@ -0,0 +1,4868 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_i2c.c + * @author MCD Application Team + * @brief I2C HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Inter Integrated Circuit (I2C) peripheral: + * + Initialization and de-initialization functions + * + IO operation functions + * + Peripheral State and Errors functions + * + @verbatim + ============================================================================== + ##### How to use this driver ##### + ============================================================================== + [..] + The I2C HAL driver can be used as follows: + + (#) Declare a I2C_HandleTypeDef handle structure, for example: + I2C_HandleTypeDef hi2c; + + (#)Initialize the I2C low level resources by implementing the HAL_I2C_MspInit() API: + (##) Enable the I2Cx interface clock + (##) I2C pins configuration + (+++) Enable the clock for the I2C GPIOs + (+++) Configure I2C pins as alternate function open-drain + (##) NVIC configuration if you need to use interrupt process + (+++) Configure the I2Cx interrupt priority + (+++) Enable the NVIC I2C IRQ Channel + (##) DMA Configuration if you need to use DMA process + (+++) Declare a DMA_HandleTypeDef handle structure for the transmit or receive channel + (+++) Enable the DMAx interface clock using + (+++) Configure the DMA handle parameters + (+++) Configure the DMA Tx or Rx channel + (+++) Associate the initialized DMA handle to the hi2c DMA Tx or Rx handle + (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on + the DMA Tx or Rx channel + + (#) Configure the Communication Clock Timing, Own Address1, Master Addressing mode, Dual Addressing mode, + Own Address2, Own Address2 Mask, General call and Nostretch mode in the hi2c Init structure. + + (#) Initialize the I2C registers by calling the HAL_I2C_Init(), configures also the low level Hardware + (GPIO, CLOCK, NVIC...etc) by calling the customized HAL_I2C_MspInit(&hi2c) API. + + (#) To check if target device is ready for communication, use the function HAL_I2C_IsDeviceReady() + + (#) For I2C IO and IO MEM operations, three operation modes are available within this driver : + + *** Polling mode IO operation *** + ================================= + [..] + (+) Transmit in master mode an amount of data in blocking mode using HAL_I2C_Master_Transmit() + (+) Receive in master mode an amount of data in blocking mode using HAL_I2C_Master_Receive() + (+) Transmit in slave mode an amount of data in blocking mode using HAL_I2C_Slave_Transmit() + (+) Receive in slave mode an amount of data in blocking mode using HAL_I2C_Slave_Receive() + + *** Polling mode IO MEM operation *** + ===================================== + [..] + (+) Write an amount of data in blocking mode to a specific memory address using HAL_I2C_Mem_Write() + (+) Read an amount of data in blocking mode from a specific memory address using HAL_I2C_Mem_Read() + + + *** Interrupt mode IO operation *** + =================================== + [..] + (+) Transmit in master mode an amount of data in non-blocking mode using HAL_I2C_Master_Transmit_IT() + (+) At transmission end of transfer, HAL_I2C_MasterTxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_MasterTxCpltCallback() + (+) Receive in master mode an amount of data in non-blocking mode using HAL_I2C_Master_Receive_IT() + (+) At reception end of transfer, HAL_I2C_MasterRxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_MasterRxCpltCallback() + (+) Transmit in slave mode an amount of data in non-blocking mode using HAL_I2C_Slave_Transmit_IT() + (+) At transmission end of transfer, HAL_I2C_SlaveTxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_SlaveTxCpltCallback() + (+) Receive in slave mode an amount of data in non-blocking mode using HAL_I2C_Slave_Receive_IT() + (+) At reception end of transfer, HAL_I2C_SlaveRxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_SlaveRxCpltCallback() + (+) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_I2C_ErrorCallback() + (+) Abort a master I2C process communication with Interrupt using HAL_I2C_Master_Abort_IT() + (+) End of abort process, HAL_I2C_AbortCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_AbortCpltCallback() + (+) Discard a slave I2C process communication using __HAL_I2C_GENERATE_NACK() macro. + This action will inform Master to generate a Stop condition to discard the communication. + + + *** Interrupt mode IO sequential operation *** + ============================================== + [..] + (@) These interfaces allow to manage a sequential transfer with a repeated start condition + when a direction change during transfer + [..] + (+) A specific option field manage the different steps of a sequential transfer + (+) Option field values are defined through @ref I2C_XFEROPTIONS and are listed below: + (++) I2C_FIRST_AND_LAST_FRAME: No sequential usage, functionnal is same as associated interfaces in no sequential mode + (++) I2C_FIRST_FRAME: Sequential usage, this option allow to manage a sequence with start condition, address + and data to transfer without a final stop condition + (++) I2C_FIRST_AND_NEXT_FRAME: Sequential usage (Master only), this option allow to manage a sequence with start condition, address + and data to transfer without a final stop condition, an then permit a call the same master sequential interface + several times (like HAL_I2C_Master_Sequential_Transmit_IT() then HAL_I2C_Master_Sequential_Transmit_IT()) + (++) I2C_NEXT_FRAME: Sequential usage, this option allow to manage a sequence with a restart condition, address + and with new data to transfer if the direction change or manage only the new data to transfer + if no direction change and without a final stop condition in both cases + (++) I2C_LAST_FRAME: Sequential usage, this option allow to manage a sequance with a restart condition, address + and with new data to transfer if the direction change or manage only the new data to transfer + if no direction change and with a final stop condition in both cases + + (+) Differents sequential I2C interfaces are listed below: + (++) Sequential transmit in master I2C mode an amount of data in non-blocking mode using HAL_I2C_Master_Sequential_Transmit_IT() + (+++) At transmission end of current frame transfer, HAL_I2C_MasterTxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_MasterTxCpltCallback() + (++) Sequential receive in master I2C mode an amount of data in non-blocking mode using HAL_I2C_Master_Sequential_Receive_IT() + (+++) At reception end of current frame transfer, HAL_I2C_MasterRxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_MasterRxCpltCallback() + (++) Abort a master I2C process communication with Interrupt using HAL_I2C_Master_Abort_IT() + (+++) End of abort process, HAL_I2C_AbortCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_AbortCpltCallback() + (++) Enable/disable the Address listen mode in slave I2C mode using HAL_I2C_EnableListen_IT() HAL_I2C_DisableListen_IT() + (+++) When address slave I2C match, HAL_I2C_AddrCallback() is executed and user can + add his own code to check the Address Match Code and the transmission direction request by master (Write/Read). + (+++) At Listen mode end HAL_I2C_ListenCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_ListenCpltCallback() + (++) Sequential transmit in slave I2C mode an amount of data in non-blocking mode using HAL_I2C_Slave_Sequential_Transmit_IT() + (+++) At transmission end of current frame transfer, HAL_I2C_SlaveTxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_SlaveTxCpltCallback() + (++) Sequential receive in slave I2C mode an amount of data in non-blocking mode using HAL_I2C_Slave_Sequential_Receive_IT() + (+++) At reception end of current frame transfer, HAL_I2C_SlaveRxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_SlaveRxCpltCallback() + (++) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_I2C_ErrorCallback() + (++) Abort a master I2C process communication with Interrupt using HAL_I2C_Master_Abort_IT() + (++) End of abort process, HAL_I2C_AbortCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_AbortCpltCallback() + (++) Discard a slave I2C process communication using __HAL_I2C_GENERATE_NACK() macro. + This action will inform Master to generate a Stop condition to discard the communication. + + *** Interrupt mode IO MEM operation *** + ======================================= + [..] + (+) Write an amount of data in non-blocking mode with Interrupt to a specific memory address using + HAL_I2C_Mem_Write_IT() + (+) At Memory end of write transfer, HAL_I2C_MemTxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_MemTxCpltCallback() + (+) Read an amount of data in non-blocking mode with Interrupt from a specific memory address using + HAL_I2C_Mem_Read_IT() + (+) At Memory end of read transfer, HAL_I2C_MemRxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_MemRxCpltCallback() + (+) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_I2C_ErrorCallback() + + *** DMA mode IO operation *** + ============================== + [..] + (+) Transmit in master mode an amount of data in non-blocking mode (DMA) using + HAL_I2C_Master_Transmit_DMA() + (+) At transmission end of transfer, HAL_I2C_MasterTxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_MasterTxCpltCallback() + (+) Receive in master mode an amount of data in non-blocking mode (DMA) using + HAL_I2C_Master_Receive_DMA() + (+) At reception end of transfer, HAL_I2C_MasterRxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_MasterRxCpltCallback() + (+) Transmit in slave mode an amount of data in non-blocking mode (DMA) using + HAL_I2C_Slave_Transmit_DMA() + (+) At transmission end of transfer, HAL_I2C_SlaveTxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_SlaveTxCpltCallback() + (+) Receive in slave mode an amount of data in non-blocking mode (DMA) using + HAL_I2C_Slave_Receive_DMA() + (+) At reception end of transfer, HAL_I2C_SlaveRxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_SlaveRxCpltCallback() + (+) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_I2C_ErrorCallback() + (+) Abort a master I2C process communication with Interrupt using HAL_I2C_Master_Abort_IT() + (+) End of abort process, HAL_I2C_AbortCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_AbortCpltCallback() + (+) Discard a slave I2C process communication using __HAL_I2C_GENERATE_NACK() macro. + This action will inform Master to generate a Stop condition to discard the communication. + + *** DMA mode IO MEM operation *** + ================================= + [..] + (+) Write an amount of data in non-blocking mode with DMA to a specific memory address using + HAL_I2C_Mem_Write_DMA() + (+) At Memory end of write transfer, HAL_I2C_MemTxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_MemTxCpltCallback() + (+) Read an amount of data in non-blocking mode with DMA from a specific memory address using + HAL_I2C_Mem_Read_DMA() + (+) At Memory end of read transfer, HAL_I2C_MemRxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_MemRxCpltCallback() + (+) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_I2C_ErrorCallback() + + + *** I2C HAL driver macros list *** + ================================== + [..] + Below the list of most used macros in I2C HAL driver. + + (+) __HAL_I2C_ENABLE: Enable the I2C peripheral + (+) __HAL_I2C_DISABLE: Disable the I2C peripheral + (+) __HAL_I2C_GENERATE_NACK: Generate a Non-Acknowledge I2C peripheral in Slave mode + (+) __HAL_I2C_GET_FLAG: Check whether the specified I2C flag is set or not + (+) __HAL_I2C_CLEAR_FLAG: Clear the specified I2C pending flag + (+) __HAL_I2C_ENABLE_IT: Enable the specified I2C interrupt + (+) __HAL_I2C_DISABLE_IT: Disable the specified I2C interrupt + + [..] + (@) You can refer to the I2C HAL driver header file for more useful macros + + @endverbatim + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup I2C I2C + * @brief I2C HAL module driver + * @{ + */ + +#ifdef HAL_I2C_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ + +/** @defgroup I2C_Private_Define I2C Private Define + * @{ + */ +#define TIMING_CLEAR_MASK (0xF0FFFFFFU) /*!< I2C TIMING clear register Mask */ +#define I2C_TIMEOUT_ADDR (10000U) /*!< 10 s */ +#define I2C_TIMEOUT_BUSY (25U) /*!< 25 ms */ +#define I2C_TIMEOUT_DIR (25U) /*!< 25 ms */ +#define I2C_TIMEOUT_RXNE (25U) /*!< 25 ms */ +#define I2C_TIMEOUT_STOPF (25U) /*!< 25 ms */ +#define I2C_TIMEOUT_TC (25U) /*!< 25 ms */ +#define I2C_TIMEOUT_TCR (25U) /*!< 25 ms */ +#define I2C_TIMEOUT_TXIS (25U) /*!< 25 ms */ +#define I2C_TIMEOUT_FLAG (25U) /*!< 25 ms */ + +#define MAX_NBYTE_SIZE 255U +#define SlaveAddr_SHIFT 7U +#define SlaveAddr_MSK 0x06U + +/* Private define for @ref PreviousState usage */ +#define I2C_STATE_MSK ((uint32_t)((HAL_I2C_STATE_BUSY_TX | HAL_I2C_STATE_BUSY_RX) & (~((uint32_t)HAL_I2C_STATE_READY)))) /*!< Mask State define, keep only RX and TX bits */ +#define I2C_STATE_NONE ((uint32_t)(HAL_I2C_MODE_NONE)) /*!< Default Value */ +#define I2C_STATE_MASTER_BUSY_TX ((uint32_t)((HAL_I2C_STATE_BUSY_TX & I2C_STATE_MSK) | HAL_I2C_MODE_MASTER)) /*!< Master Busy TX, combinaison of State LSB and Mode enum */ +#define I2C_STATE_MASTER_BUSY_RX ((uint32_t)((HAL_I2C_STATE_BUSY_RX & I2C_STATE_MSK) | HAL_I2C_MODE_MASTER)) /*!< Master Busy RX, combinaison of State LSB and Mode enum */ +#define I2C_STATE_SLAVE_BUSY_TX ((uint32_t)((HAL_I2C_STATE_BUSY_TX & I2C_STATE_MSK) | HAL_I2C_MODE_SLAVE)) /*!< Slave Busy TX, combinaison of State LSB and Mode enum */ +#define I2C_STATE_SLAVE_BUSY_RX ((uint32_t)((HAL_I2C_STATE_BUSY_RX & I2C_STATE_MSK) | HAL_I2C_MODE_SLAVE)) /*!< Slave Busy RX, combinaison of State LSB and Mode enum */ +#define I2C_STATE_MEM_BUSY_TX ((uint32_t)((HAL_I2C_STATE_BUSY_TX & I2C_STATE_MSK) | HAL_I2C_MODE_MEM)) /*!< Memory Busy TX, combinaison of State LSB and Mode enum */ +#define I2C_STATE_MEM_BUSY_RX ((uint32_t)((HAL_I2C_STATE_BUSY_RX & I2C_STATE_MSK) | HAL_I2C_MODE_MEM)) /*!< Memory Busy RX, combinaison of State LSB and Mode enum */ + + +/* Private define to centralize the enable/disable of Interrupts */ +#define I2C_XFER_TX_IT (0x00000001U) +#define I2C_XFER_RX_IT (0x00000002U) +#define I2C_XFER_LISTEN_IT (0x00000004U) + +#define I2C_XFER_ERROR_IT (0x00000011U) +#define I2C_XFER_CPLT_IT (0x00000012U) +#define I2C_XFER_RELOAD_IT (0x00000012U) + +/* Private define Sequential Transfer Options default/reset value */ +#define I2C_NO_OPTION_FRAME (0xFFFF0000U) +/** + * @} + */ + +/* Private macro -------------------------------------------------------------*/ +#define I2C_GET_DMA_REMAIN_DATA(__HANDLE__) ((((__HANDLE__)->State) == HAL_I2C_STATE_BUSY_TX) ? \ + ((uint32_t)(((DMA_Channel_TypeDef *)(__HANDLE__)->hdmatx->Instance)->CNDTR)) : \ + ((uint32_t)(((DMA_Channel_TypeDef *)(__HANDLE__)->hdmarx->Instance)->CNDTR))) + +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ + +/** @defgroup I2C_Private_Functions I2C Private Functions + * @{ + */ +/* Private functions to handle DMA transfer */ +static void I2C_DMAMasterTransmitCplt(DMA_HandleTypeDef *hdma); +static void I2C_DMAMasterReceiveCplt(DMA_HandleTypeDef *hdma); +static void I2C_DMASlaveTransmitCplt(DMA_HandleTypeDef *hdma); +static void I2C_DMASlaveReceiveCplt(DMA_HandleTypeDef *hdma); +static void I2C_DMAError(DMA_HandleTypeDef *hdma); +static void I2C_DMAAbort(DMA_HandleTypeDef *hdma); + +/* Private functions to handle IT transfer */ +static void I2C_ITAddrCplt(I2C_HandleTypeDef *hi2c, uint32_t ITFlags); +static void I2C_ITMasterSequentialCplt(I2C_HandleTypeDef *hi2c); +static void I2C_ITSlaveSequentialCplt(I2C_HandleTypeDef *hi2c); +static void I2C_ITMasterCplt(I2C_HandleTypeDef *hi2c, uint32_t ITFlags); +static void I2C_ITSlaveCplt(I2C_HandleTypeDef *hi2c, uint32_t ITFlags); +static void I2C_ITListenCplt(I2C_HandleTypeDef *hi2c, uint32_t ITFlags); +static void I2C_ITError(I2C_HandleTypeDef *hi2c, uint32_t ErrorCode); + +/* Private functions to handle IT transfer */ +static HAL_StatusTypeDef I2C_RequestMemoryWrite(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout, uint32_t Tickstart); +static HAL_StatusTypeDef I2C_RequestMemoryRead(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout, uint32_t Tickstart); + +/* Private functions for I2C transfer IRQ handler */ +static HAL_StatusTypeDef I2C_Master_ISR_IT(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags, uint32_t ITSources); +static HAL_StatusTypeDef I2C_Slave_ISR_IT(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags, uint32_t ITSources); +static HAL_StatusTypeDef I2C_Master_ISR_DMA(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags, uint32_t ITSources); +static HAL_StatusTypeDef I2C_Slave_ISR_DMA(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags, uint32_t ITSources); + +/* Private functions to handle flags during polling transfer */ +static HAL_StatusTypeDef I2C_WaitOnFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, FlagStatus Status, uint32_t Timeout, uint32_t Tickstart); +static HAL_StatusTypeDef I2C_WaitOnTXISFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart); +static HAL_StatusTypeDef I2C_WaitOnRXNEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart); +static HAL_StatusTypeDef I2C_WaitOnSTOPFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart); +static HAL_StatusTypeDef I2C_IsAcknowledgeFailed(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart); + +/* Private functions to centralize the enable/disable of Interrupts */ +static HAL_StatusTypeDef I2C_Enable_IRQ(I2C_HandleTypeDef *hi2c, uint16_t InterruptRequest); +static HAL_StatusTypeDef I2C_Disable_IRQ(I2C_HandleTypeDef *hi2c, uint16_t InterruptRequest); + +/* Private functions to flush TXDR register */ +static void I2C_Flush_TXDR(I2C_HandleTypeDef *hi2c); + +/* Private functions to handle start, restart or stop a transfer */ +static void I2C_TransferConfig(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t Size, uint32_t Mode, uint32_t Request); +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup I2C_Exported_Functions I2C Exported Functions + * @{ + */ + +/** @defgroup I2C_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions + * +@verbatim + =============================================================================== + ##### Initialization and de-initialization functions ##### + =============================================================================== + [..] This subsection provides a set of functions allowing to initialize and + deinitialize the I2Cx peripheral: + + (+) User must Implement HAL_I2C_MspInit() function in which he configures + all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ). + + (+) Call the function HAL_I2C_Init() to configure the selected device with + the selected configuration: + (++) Clock Timing + (++) Own Address 1 + (++) Addressing mode (Master, Slave) + (++) Dual Addressing mode + (++) Own Address 2 + (++) Own Address 2 Mask + (++) General call mode + (++) Nostretch mode + + (+) Call the function HAL_I2C_DeInit() to restore the default configuration + of the selected I2Cx peripheral. + +@endverbatim + * @{ + */ + +/** + * @brief Initializes the I2C according to the specified parameters + * in the I2C_InitTypeDef and initialize the associated handle. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c) +{ + /* Check the I2C handle allocation */ + if (hi2c == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance)); + assert_param(IS_I2C_OWN_ADDRESS1(hi2c->Init.OwnAddress1)); + assert_param(IS_I2C_ADDRESSING_MODE(hi2c->Init.AddressingMode)); + assert_param(IS_I2C_DUAL_ADDRESS(hi2c->Init.DualAddressMode)); + assert_param(IS_I2C_OWN_ADDRESS2(hi2c->Init.OwnAddress2)); + assert_param(IS_I2C_OWN_ADDRESS2_MASK(hi2c->Init.OwnAddress2Masks)); + assert_param(IS_I2C_GENERAL_CALL(hi2c->Init.GeneralCallMode)); + assert_param(IS_I2C_NO_STRETCH(hi2c->Init.NoStretchMode)); + + if (hi2c->State == HAL_I2C_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hi2c->Lock = HAL_UNLOCKED; + + /* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */ + HAL_I2C_MspInit(hi2c); + } + + hi2c->State = HAL_I2C_STATE_BUSY; + + /* Disable the selected I2C peripheral */ + __HAL_I2C_DISABLE(hi2c); + + /*---------------------------- I2Cx TIMINGR Configuration ------------------*/ + /* Configure I2Cx: Frequency range */ + hi2c->Instance->TIMINGR = hi2c->Init.Timing & TIMING_CLEAR_MASK; + + /*---------------------------- I2Cx OAR1 Configuration ---------------------*/ + /* Disable Own Address1 before set the Own Address1 configuration */ + hi2c->Instance->OAR1 &= ~I2C_OAR1_OA1EN; + + /* Configure I2Cx: Own Address1 and ack own address1 mode */ + if (hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_7BIT) + { + hi2c->Instance->OAR1 = (I2C_OAR1_OA1EN | hi2c->Init.OwnAddress1); + } + else /* I2C_ADDRESSINGMODE_10BIT */ + { + hi2c->Instance->OAR1 = (I2C_OAR1_OA1EN | I2C_OAR1_OA1MODE | hi2c->Init.OwnAddress1); + } + + /*---------------------------- I2Cx CR2 Configuration ----------------------*/ + /* Configure I2Cx: Addressing Master mode */ + if (hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_10BIT) + { + hi2c->Instance->CR2 = (I2C_CR2_ADD10); + } + /* Enable the AUTOEND by default, and enable NACK (should be disable only during Slave process */ + hi2c->Instance->CR2 |= (I2C_CR2_AUTOEND | I2C_CR2_NACK); + + /*---------------------------- I2Cx OAR2 Configuration ---------------------*/ + /* Disable Own Address2 before set the Own Address2 configuration */ + hi2c->Instance->OAR2 &= ~I2C_DUALADDRESS_ENABLE; + + /* Configure I2Cx: Dual mode and Own Address2 */ + hi2c->Instance->OAR2 = (hi2c->Init.DualAddressMode | hi2c->Init.OwnAddress2 | (hi2c->Init.OwnAddress2Masks << 8)); + + /*---------------------------- I2Cx CR1 Configuration ----------------------*/ + /* Configure I2Cx: Generalcall and NoStretch mode */ + hi2c->Instance->CR1 = (hi2c->Init.GeneralCallMode | hi2c->Init.NoStretchMode); + + /* Enable the selected I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->Mode = HAL_I2C_MODE_NONE; + + return HAL_OK; +} + +/** + * @brief DeInitialize the I2C peripheral. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_DeInit(I2C_HandleTypeDef *hi2c) +{ + /* Check the I2C handle allocation */ + if (hi2c == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance)); + + hi2c->State = HAL_I2C_STATE_BUSY; + + /* Disable the I2C Peripheral Clock */ + __HAL_I2C_DISABLE(hi2c); + + /* DeInit the low level hardware: GPIO, CLOCK, NVIC */ + HAL_I2C_MspDeInit(hi2c); + + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + hi2c->State = HAL_I2C_STATE_RESET; + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Release Lock */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; +} + +/** + * @brief Initialize the I2C MSP. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitialize the I2C MSP. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_MspDeInit(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_MspDeInit could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup I2C_Exported_Functions_Group2 Input and Output operation functions + * @brief Data transfers functions + * +@verbatim + =============================================================================== + ##### IO operation functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to manage the I2C data + transfers. + + (#) There are two modes of transfer: + (++) Blocking mode : The communication is performed in the polling mode. + The status of all data processing is returned by the same function + after finishing transfer. + (++) No-Blocking mode : The communication is performed using Interrupts + or DMA. These functions return the status of the transfer startup. + The end of the data processing will be indicated through the + dedicated I2C IRQ when using Interrupt mode or the DMA IRQ when + using DMA mode. + + (#) Blocking mode functions are : + (++) HAL_I2C_Master_Transmit() + (++) HAL_I2C_Master_Receive() + (++) HAL_I2C_Slave_Transmit() + (++) HAL_I2C_Slave_Receive() + (++) HAL_I2C_Mem_Write() + (++) HAL_I2C_Mem_Read() + (++) HAL_I2C_IsDeviceReady() + + (#) No-Blocking mode functions with Interrupt are : + (++) HAL_I2C_Master_Transmit_IT() + (++) HAL_I2C_Master_Receive_IT() + (++) HAL_I2C_Slave_Transmit_IT() + (++) HAL_I2C_Slave_Receive_IT() + (++) HAL_I2C_Mem_Write_IT() + (++) HAL_I2C_Mem_Read_IT() + + (#) No-Blocking mode functions with DMA are : + (++) HAL_I2C_Master_Transmit_DMA() + (++) HAL_I2C_Master_Receive_DMA() + (++) HAL_I2C_Slave_Transmit_DMA() + (++) HAL_I2C_Slave_Receive_DMA() + (++) HAL_I2C_Mem_Write_DMA() + (++) HAL_I2C_Mem_Read_DMA() + + (#) A set of Transfer Complete Callbacks are provided in non Blocking mode: + (++) HAL_I2C_MemTxCpltCallback() + (++) HAL_I2C_MemRxCpltCallback() + (++) HAL_I2C_MasterTxCpltCallback() + (++) HAL_I2C_MasterRxCpltCallback() + (++) HAL_I2C_SlaveTxCpltCallback() + (++) HAL_I2C_SlaveRxCpltCallback() + (++) HAL_I2C_ErrorCallback() + +@endverbatim + * @{ + */ + +/** + * @brief Transmits in master mode an amount of data in blocking mode. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shift at right before call interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + uint32_t tickstart = 0U; + + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_MASTER; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferISR = NULL; + + /* Send Slave Address */ + /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */ + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_RELOAD_MODE, I2C_GENERATE_START_WRITE); + } + else + { + hi2c->XferSize = hi2c->XferCount; + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_GENERATE_START_WRITE); + } + + while (hi2c->XferCount > 0U) + { + /* Wait until TXIS flag is set */ + if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + /* Write data to TXDR */ + hi2c->Instance->TXDR = (*hi2c->pBuffPtr++); + hi2c->XferCount--; + hi2c->XferSize--; + + if ((hi2c->XferSize == 0U) && (hi2c->XferCount != 0U)) + { + /* Wait until TCR flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_RELOAD_MODE, I2C_NO_STARTSTOP); + } + else + { + hi2c->XferSize = hi2c->XferCount; + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP); + } + } + } + + /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */ + /* Wait until STOPF flag is set */ + if (I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + /* Clear STOP Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); + + /* Clear Configuration Register 2 */ + I2C_RESET_CR2(hi2c); + + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receives in master mode an amount of data in blocking mode. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shift at right before call interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + uint32_t tickstart = 0U; + + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_MASTER; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferISR = NULL; + + /* Send Slave Address */ + /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */ + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_RELOAD_MODE, I2C_GENERATE_START_READ); + } + else + { + hi2c->XferSize = hi2c->XferCount; + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_GENERATE_START_READ); + } + + while (hi2c->XferCount > 0U) + { + /* Wait until RXNE flag is set */ + if (I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + /* Read data from RXDR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->RXDR; + hi2c->XferSize--; + hi2c->XferCount--; + + if ((hi2c->XferSize == 0U) && (hi2c->XferCount != 0U)) + { + /* Wait until TCR flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_RELOAD_MODE, I2C_NO_STARTSTOP); + } + else + { + hi2c->XferSize = hi2c->XferCount; + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP); + } + } + } + + /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */ + /* Wait until STOPF flag is set */ + if (I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + /* Clear STOP Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); + + /* Clear Configuration Register 2 */ + I2C_RESET_CR2(hi2c); + + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Transmits in slave mode an amount of data in blocking mode. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Slave_Transmit(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + uint32_t tickstart = 0U; + + if (hi2c->State == HAL_I2C_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_SLAVE; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferISR = NULL; + + /* Enable Address Acknowledge */ + hi2c->Instance->CR2 &= ~I2C_CR2_NACK; + + /* Wait until ADDR flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, RESET, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + hi2c->Instance->CR2 |= I2C_CR2_NACK; + return HAL_TIMEOUT; + } + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR); + + /* If 10bit addressing mode is selected */ + if (hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_10BIT) + { + /* Wait until ADDR flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, RESET, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + hi2c->Instance->CR2 |= I2C_CR2_NACK; + return HAL_TIMEOUT; + } + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR); + } + + /* Wait until DIR flag is set Transmitter mode */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_DIR, RESET, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + hi2c->Instance->CR2 |= I2C_CR2_NACK; + return HAL_TIMEOUT; + } + + while (hi2c->XferCount > 0U) + { + /* Wait until TXIS flag is set */ + if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + hi2c->Instance->CR2 |= I2C_CR2_NACK; + + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + /* Write data to TXDR */ + hi2c->Instance->TXDR = (*hi2c->pBuffPtr++); + hi2c->XferCount--; + } + + /* Wait until STOP flag is set */ + if (I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + hi2c->Instance->CR2 |= I2C_CR2_NACK; + + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Normal use case for Transmitter mode */ + /* A NACK is generated to confirm the end of transfer */ + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + } + else + { + return HAL_TIMEOUT; + } + } + + /* Clear STOP flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); + + /* Wait until BUSY flag is reset */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + hi2c->Instance->CR2 |= I2C_CR2_NACK; + return HAL_TIMEOUT; + } + + /* Disable Address Acknowledge */ + hi2c->Instance->CR2 |= I2C_CR2_NACK; + + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive in slave mode an amount of data in blocking mode + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Slave_Receive(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + uint32_t tickstart = 0U; + + if (hi2c->State == HAL_I2C_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_SLAVE; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferISR = NULL; + + /* Enable Address Acknowledge */ + hi2c->Instance->CR2 &= ~I2C_CR2_NACK; + + /* Wait until ADDR flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, RESET, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + hi2c->Instance->CR2 |= I2C_CR2_NACK; + return HAL_TIMEOUT; + } + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR); + + /* Wait until DIR flag is reset Receiver mode */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_DIR, SET, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + hi2c->Instance->CR2 |= I2C_CR2_NACK; + return HAL_TIMEOUT; + } + + while (hi2c->XferCount > 0U) + { + /* Wait until RXNE flag is set */ + if (I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + hi2c->Instance->CR2 |= I2C_CR2_NACK; + + /* Store Last receive data if any */ + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == SET) + { + /* Read data from RXDR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->RXDR; + hi2c->XferCount--; + } + + if (hi2c->ErrorCode == HAL_I2C_ERROR_TIMEOUT) + { + return HAL_TIMEOUT; + } + else + { + return HAL_ERROR; + } + } + + /* Read data from RXDR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->RXDR; + hi2c->XferCount--; + } + + /* Wait until STOP flag is set */ + if (I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + hi2c->Instance->CR2 |= I2C_CR2_NACK; + + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + /* Clear STOP flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); + + /* Wait until BUSY flag is reset */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + hi2c->Instance->CR2 |= I2C_CR2_NACK; + return HAL_TIMEOUT; + } + + /* Disable Address Acknowledge */ + hi2c->Instance->CR2 |= I2C_CR2_NACK; + + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Transmit in master mode an amount of data in non-blocking mode with Interrupt + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shift at right before call interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size) +{ + uint32_t xfermode = 0U; + + if (hi2c->State == HAL_I2C_STATE_READY) + { + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_MASTER; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferISR = I2C_Master_ISR_IT; + + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + xfermode = I2C_RELOAD_MODE; + } + else + { + hi2c->XferSize = hi2c->XferCount; + xfermode = I2C_AUTOEND_MODE; + } + + /* Send Slave Address */ + /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE */ + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, xfermode, I2C_GENERATE_START_WRITE); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable ERR, TC, STOP, NACK, TXI interrupt */ + /* possible to enable all of these */ + /* I2C_IT_ERRI | I2C_IT_TCI| I2C_IT_STOPI| I2C_IT_NACKI | I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */ + I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive in master mode an amount of data in non-blocking mode with Interrupt + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shift at right before call interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Receive_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size) +{ + uint32_t xfermode = 0U; + + if (hi2c->State == HAL_I2C_STATE_READY) + { + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_MASTER; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferISR = I2C_Master_ISR_IT; + + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + xfermode = I2C_RELOAD_MODE; + } + else + { + hi2c->XferSize = hi2c->XferCount; + xfermode = I2C_AUTOEND_MODE; + } + + /* Send Slave Address */ + /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE */ + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, xfermode, I2C_GENERATE_START_READ); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable ERR, TC, STOP, NACK, RXI interrupt */ + /* possible to enable all of these */ + /* I2C_IT_ERRI | I2C_IT_TCI| I2C_IT_STOPI| I2C_IT_NACKI | I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */ + I2C_Enable_IRQ(hi2c, I2C_XFER_RX_IT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Transmit in slave mode an amount of data in non-blocking mode with Interrupt + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Slave_Transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size) +{ + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hi2c); + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_SLAVE; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Enable Address Acknowledge */ + hi2c->Instance->CR2 &= ~I2C_CR2_NACK; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferISR = I2C_Slave_ISR_IT; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable ERR, TC, STOP, NACK, TXI interrupt */ + /* possible to enable all of these */ + /* I2C_IT_ERRI | I2C_IT_TCI| I2C_IT_STOPI| I2C_IT_NACKI | I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */ + I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT | I2C_XFER_LISTEN_IT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive in slave mode an amount of data in non-blocking mode with Interrupt + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Slave_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size) +{ + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hi2c); + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_SLAVE; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Enable Address Acknowledge */ + hi2c->Instance->CR2 &= ~I2C_CR2_NACK; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferISR = I2C_Slave_ISR_IT; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable ERR, TC, STOP, NACK, RXI interrupt */ + /* possible to enable all of these */ + /* I2C_IT_ERRI | I2C_IT_TCI| I2C_IT_STOPI| I2C_IT_NACKI | I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */ + I2C_Enable_IRQ(hi2c, I2C_XFER_RX_IT | I2C_XFER_LISTEN_IT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Transmit in master mode an amount of data in non-blocking mode with DMA + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shift at right before call interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size) +{ + uint32_t xfermode = 0U; + + if (hi2c->State == HAL_I2C_STATE_READY) + { + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_MASTER; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferISR = I2C_Master_ISR_DMA; + + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + xfermode = I2C_RELOAD_MODE; + } + else + { + hi2c->XferSize = hi2c->XferCount; + xfermode = I2C_AUTOEND_MODE; + } + + if (hi2c->XferSize > 0U) + { + /* Set the I2C DMA transfer complete callback */ + hi2c->hdmatx->XferCpltCallback = I2C_DMAMasterTransmitCplt; + + /* Set the DMA error callback */ + hi2c->hdmatx->XferErrorCallback = I2C_DMAError; + + /* Set the unused DMA callbacks to NULL */ + hi2c->hdmatx->XferHalfCpltCallback = NULL; + hi2c->hdmatx->XferAbortCallback = NULL; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)pData, (uint32_t)&hi2c->Instance->TXDR, hi2c->XferSize); + + /* Send Slave Address */ + /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */ + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, xfermode, I2C_GENERATE_START_WRITE); + + /* Update XferCount value */ + hi2c->XferCount -= hi2c->XferSize; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + /* Enable ERR and NACK interrupts */ + I2C_Enable_IRQ(hi2c, I2C_XFER_ERROR_IT); + + /* Enable DMA Request */ + hi2c->Instance->CR1 |= I2C_CR1_TXDMAEN; + } + else + { + /* Update Transfer ISR function pointer */ + hi2c->XferISR = I2C_Master_ISR_IT; + + /* Send Slave Address */ + /* Set NBYTES to write and generate START condition */ + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_GENERATE_START_WRITE); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + /* Enable ERR, TC, STOP, NACK, TXI interrupt */ + /* possible to enable all of these */ + /* I2C_IT_ERRI | I2C_IT_TCI| I2C_IT_STOPI| I2C_IT_NACKI | I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */ + I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT); + } + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive in master mode an amount of data in non-blocking mode with DMA + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shift at right before call interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Receive_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size) +{ + uint32_t xfermode = 0U; + + if (hi2c->State == HAL_I2C_STATE_READY) + { + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_MASTER; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferISR = I2C_Master_ISR_DMA; + + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + xfermode = I2C_RELOAD_MODE; + } + else + { + hi2c->XferSize = hi2c->XferCount; + xfermode = I2C_AUTOEND_MODE; + } + + if (hi2c->XferSize > 0U) + { + /* Set the I2C DMA transfer complete callback */ + hi2c->hdmarx->XferCpltCallback = I2C_DMAMasterReceiveCplt; + + /* Set the DMA error callback */ + hi2c->hdmarx->XferErrorCallback = I2C_DMAError; + + /* Set the unused DMA callbacks to NULL */ + hi2c->hdmarx->XferHalfCpltCallback = NULL; + hi2c->hdmarx->XferAbortCallback = NULL; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->RXDR, (uint32_t)pData, hi2c->XferSize); + + /* Send Slave Address */ + /* Set NBYTES to read and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */ + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, xfermode, I2C_GENERATE_START_READ); + + /* Update XferCount value */ + hi2c->XferCount -= hi2c->XferSize; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + /* Enable ERR and NACK interrupts */ + I2C_Enable_IRQ(hi2c, I2C_XFER_ERROR_IT); + + /* Enable DMA Request */ + hi2c->Instance->CR1 |= I2C_CR1_RXDMAEN; + } + else + { + /* Update Transfer ISR function pointer */ + hi2c->XferISR = I2C_Master_ISR_IT; + + /* Send Slave Address */ + /* Set NBYTES to read and generate START condition */ + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_GENERATE_START_READ); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + /* Enable ERR, TC, STOP, NACK, TXI interrupt */ + /* possible to enable all of these */ + /* I2C_IT_ERRI | I2C_IT_TCI| I2C_IT_STOPI| I2C_IT_NACKI | I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */ + I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT); + } + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Transmit in slave mode an amount of data in non-blocking mode with DMA + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Slave_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size) +{ + if (hi2c->State == HAL_I2C_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + /* Process Locked */ + __HAL_LOCK(hi2c); + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_SLAVE; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferISR = I2C_Slave_ISR_DMA; + + /* Set the I2C DMA transfer complete callback */ + hi2c->hdmatx->XferCpltCallback = I2C_DMASlaveTransmitCplt; + + /* Set the DMA error callback */ + hi2c->hdmatx->XferErrorCallback = I2C_DMAError; + + /* Set the unused DMA callbacks to NULL */ + hi2c->hdmatx->XferHalfCpltCallback = NULL; + hi2c->hdmatx->XferAbortCallback = NULL; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)pData, (uint32_t)&hi2c->Instance->TXDR, hi2c->XferSize); + + /* Enable Address Acknowledge */ + hi2c->Instance->CR2 &= ~I2C_CR2_NACK; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + /* Enable ERR, STOP, NACK, ADDR interrupts */ + I2C_Enable_IRQ(hi2c, I2C_XFER_LISTEN_IT); + + /* Enable DMA Request */ + hi2c->Instance->CR1 |= I2C_CR1_TXDMAEN; + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive in slave mode an amount of data in non-blocking mode with DMA + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Slave_Receive_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size) +{ + if (hi2c->State == HAL_I2C_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + /* Process Locked */ + __HAL_LOCK(hi2c); + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_SLAVE; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferISR = I2C_Slave_ISR_DMA; + + /* Set the I2C DMA transfer complete callback */ + hi2c->hdmarx->XferCpltCallback = I2C_DMASlaveReceiveCplt; + + /* Set the DMA error callback */ + hi2c->hdmarx->XferErrorCallback = I2C_DMAError; + + /* Set the unused DMA callbacks to NULL */ + hi2c->hdmarx->XferHalfCpltCallback = NULL; + hi2c->hdmarx->XferAbortCallback = NULL; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->RXDR, (uint32_t)pData, hi2c->XferSize); + + /* Enable Address Acknowledge */ + hi2c->Instance->CR2 &= ~I2C_CR2_NACK; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + /* Enable ERR, STOP, NACK, ADDR interrupts */ + I2C_Enable_IRQ(hi2c, I2C_XFER_LISTEN_IT); + + /* Enable DMA Request */ + hi2c->Instance->CR1 |= I2C_CR1_RXDMAEN; + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} +/** + * @brief Write an amount of data in blocking mode to a specific memory address + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shift at right before call interface + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + uint32_t tickstart = 0U; + + /* Check the parameters */ + assert_param(IS_I2C_MEMADD_SIZE(MemAddSize)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_MEM; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferISR = NULL; + + /* Send Slave Address and Memory Address */ + if (I2C_RequestMemoryWrite(hi2c, DevAddress, MemAddress, MemAddSize, Timeout, tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_ERROR; + } + else + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_TIMEOUT; + } + } + + /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE */ + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_RELOAD_MODE, I2C_NO_STARTSTOP); + } + else + { + hi2c->XferSize = hi2c->XferCount; + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP); + } + + do + { + /* Wait until TXIS flag is set */ + if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + /* Write data to TXDR */ + hi2c->Instance->TXDR = (*hi2c->pBuffPtr++); + hi2c->XferCount--; + hi2c->XferSize--; + + if ((hi2c->XferSize == 0U) && (hi2c->XferCount != 0U)) + { + /* Wait until TCR flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_RELOAD_MODE, I2C_NO_STARTSTOP); + } + else + { + hi2c->XferSize = hi2c->XferCount; + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP); + } + } + + } + while (hi2c->XferCount > 0U); + + /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */ + /* Wait until STOPF flag is reset */ + if (I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + /* Clear STOP Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); + + /* Clear Configuration Register 2 */ + I2C_RESET_CR2(hi2c); + + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Read an amount of data in blocking mode from a specific memory address + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shift at right before call interface + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + uint32_t tickstart = 0U; + + /* Check the parameters */ + assert_param(IS_I2C_MEMADD_SIZE(MemAddSize)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_MEM; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferISR = NULL; + + /* Send Slave Address and Memory Address */ + if (I2C_RequestMemoryRead(hi2c, DevAddress, MemAddress, MemAddSize, Timeout, tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_ERROR; + } + else + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_TIMEOUT; + } + } + + /* Send Slave Address */ + /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */ + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_RELOAD_MODE, I2C_GENERATE_START_READ); + } + else + { + hi2c->XferSize = hi2c->XferCount; + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_GENERATE_START_READ); + } + + do + { + /* Wait until RXNE flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_RXNE, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + /* Read data from RXDR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->RXDR; + hi2c->XferSize--; + hi2c->XferCount--; + + if ((hi2c->XferSize == 0U) && (hi2c->XferCount != 0U)) + { + /* Wait until TCR flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_RELOAD_MODE, I2C_NO_STARTSTOP); + } + else + { + hi2c->XferSize = hi2c->XferCount; + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP); + } + } + } + while (hi2c->XferCount > 0U); + + /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */ + /* Wait until STOPF flag is reset */ + if (I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + /* Clear STOP Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); + + /* Clear Configuration Register 2 */ + I2C_RESET_CR2(hi2c); + + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} +/** + * @brief Write an amount of data in non-blocking mode with Interrupt to a specific memory address + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shift at right before call interface + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Mem_Write_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size) +{ + uint32_t tickstart = 0U; + uint32_t xfermode = 0U; + + /* Check the parameters */ + assert_param(IS_I2C_MEMADD_SIZE(MemAddSize)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_MEM; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferISR = I2C_Master_ISR_IT; + + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + xfermode = I2C_RELOAD_MODE; + } + else + { + hi2c->XferSize = hi2c->XferCount; + xfermode = I2C_AUTOEND_MODE; + } + + /* Send Slave Address and Memory Address */ + if (I2C_RequestMemoryWrite(hi2c, DevAddress, MemAddress, MemAddSize, I2C_TIMEOUT_FLAG, tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_ERROR; + } + else + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_TIMEOUT; + } + } + + /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */ + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, xfermode, I2C_NO_STARTSTOP); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable ERR, TC, STOP, NACK, TXI interrupt */ + /* possible to enable all of these */ + /* I2C_IT_ERRI | I2C_IT_TCI| I2C_IT_STOPI| I2C_IT_NACKI | I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */ + I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Read an amount of data in non-blocking mode with Interrupt from a specific memory address + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shift at right before call interface + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Mem_Read_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size) +{ + uint32_t tickstart = 0U; + uint32_t xfermode = 0U; + + /* Check the parameters */ + assert_param(IS_I2C_MEMADD_SIZE(MemAddSize)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_MEM; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferISR = I2C_Master_ISR_IT; + + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + xfermode = I2C_RELOAD_MODE; + } + else + { + hi2c->XferSize = hi2c->XferCount; + xfermode = I2C_AUTOEND_MODE; + } + + /* Send Slave Address and Memory Address */ + if (I2C_RequestMemoryRead(hi2c, DevAddress, MemAddress, MemAddSize, I2C_TIMEOUT_FLAG, tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_ERROR; + } + else + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_TIMEOUT; + } + } + + /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */ + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, xfermode, I2C_GENERATE_START_READ); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable ERR, TC, STOP, NACK, RXI interrupt */ + /* possible to enable all of these */ + /* I2C_IT_ERRI | I2C_IT_TCI| I2C_IT_STOPI| I2C_IT_NACKI | I2C_IT_ADDRI | I2C_IT_RXI | I2C_IT_TXI */ + I2C_Enable_IRQ(hi2c, I2C_XFER_RX_IT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} +/** + * @brief Write an amount of data in non-blocking mode with DMA to a specific memory address + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shift at right before call interface + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Mem_Write_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size) +{ + uint32_t tickstart = 0U; + uint32_t xfermode = 0U; + + /* Check the parameters */ + assert_param(IS_I2C_MEMADD_SIZE(MemAddSize)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_MEM; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferISR = I2C_Master_ISR_DMA; + + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + xfermode = I2C_RELOAD_MODE; + } + else + { + hi2c->XferSize = hi2c->XferCount; + xfermode = I2C_AUTOEND_MODE; + } + + /* Send Slave Address and Memory Address */ + if (I2C_RequestMemoryWrite(hi2c, DevAddress, MemAddress, MemAddSize, I2C_TIMEOUT_FLAG, tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_ERROR; + } + else + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_TIMEOUT; + } + } + + /* Set the I2C DMA transfer complete callback */ + hi2c->hdmatx->XferCpltCallback = I2C_DMAMasterTransmitCplt; + + /* Set the DMA error callback */ + hi2c->hdmatx->XferErrorCallback = I2C_DMAError; + + /* Set the unused DMA callbacks to NULL */ + hi2c->hdmatx->XferHalfCpltCallback = NULL; + hi2c->hdmatx->XferAbortCallback = NULL; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)pData, (uint32_t)&hi2c->Instance->TXDR, hi2c->XferSize); + + /* Send Slave Address */ + /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */ + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, xfermode, I2C_NO_STARTSTOP); + + /* Update XferCount value */ + hi2c->XferCount -= hi2c->XferSize; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + /* Enable ERR and NACK interrupts */ + I2C_Enable_IRQ(hi2c, I2C_XFER_ERROR_IT); + + /* Enable DMA Request */ + hi2c->Instance->CR1 |= I2C_CR1_TXDMAEN; + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Reads an amount of data in non-blocking mode with DMA from a specific memory address. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shift at right before call interface + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param pData Pointer to data buffer + * @param Size Amount of data to be read + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Mem_Read_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size) +{ + uint32_t tickstart = 0U; + uint32_t xfermode = 0U; + + /* Check the parameters */ + assert_param(IS_I2C_MEMADD_SIZE(MemAddSize)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_MEM; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferISR = I2C_Master_ISR_DMA; + + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + xfermode = I2C_RELOAD_MODE; + } + else + { + hi2c->XferSize = hi2c->XferCount; + xfermode = I2C_AUTOEND_MODE; + } + + /* Send Slave Address and Memory Address */ + if (I2C_RequestMemoryRead(hi2c, DevAddress, MemAddress, MemAddSize, I2C_TIMEOUT_FLAG, tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_ERROR; + } + else + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_TIMEOUT; + } + } + + /* Set the I2C DMA transfer complete callback */ + hi2c->hdmarx->XferCpltCallback = I2C_DMAMasterReceiveCplt; + + /* Set the DMA error callback */ + hi2c->hdmarx->XferErrorCallback = I2C_DMAError; + + /* Set the unused DMA callbacks to NULL */ + hi2c->hdmarx->XferHalfCpltCallback = NULL; + hi2c->hdmarx->XferAbortCallback = NULL; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->RXDR, (uint32_t)pData, hi2c->XferSize); + + /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */ + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, xfermode, I2C_GENERATE_START_READ); + + /* Update XferCount value */ + hi2c->XferCount -= hi2c->XferSize; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Enable DMA Request */ + hi2c->Instance->CR1 |= I2C_CR1_RXDMAEN; + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + /* Enable ERR and NACK interrupts */ + I2C_Enable_IRQ(hi2c, I2C_XFER_ERROR_IT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Checks if target device is ready for communication. + * @note This function is used with Memory devices + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shift at right before call interface + * @param Trials Number of trials + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_IsDeviceReady(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Trials, uint32_t Timeout) +{ + uint32_t tickstart = 0U; + + __IO uint32_t I2C_Trials = 0U; + + if (hi2c->State == HAL_I2C_STATE_READY) + { + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) == SET) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + hi2c->State = HAL_I2C_STATE_BUSY; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + do + { + /* Generate Start */ + hi2c->Instance->CR2 = I2C_GENERATE_START(hi2c->Init.AddressingMode, DevAddress); + + /* 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*/ + tickstart = HAL_GetTick(); + while ((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == RESET) && (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == RESET) && (hi2c->State != HAL_I2C_STATE_TIMEOUT)) + { + if (Timeout != HAL_MAX_DELAY) + { + if ((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout)) + { + /* Device is ready */ + hi2c->State = HAL_I2C_STATE_READY; + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_TIMEOUT; + } + } + } + + /* Check if the NACKF flag has not been set */ + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == RESET) + { + /* Wait until STOPF flag is reset */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_STOPF, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + /* Clear STOP Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); + + /* Device is ready */ + hi2c->State = HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + /* Wait until STOPF flag is reset */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_STOPF, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + /* Clear NACK Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + + /* Clear STOP Flag, auto generated with autoend*/ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); + } + + /* Check if the maximum allowed number of trials has been reached */ + if (I2C_Trials++ == Trials) + { + /* Generate Stop */ + hi2c->Instance->CR2 |= I2C_CR2_STOP; + + /* Wait until STOPF flag is reset */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_STOPF, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + /* Clear STOP Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); + } + } + while (I2C_Trials < Trials); + + hi2c->State = HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_TIMEOUT; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Sequential transmit in master I2C mode an amount of data in non-blocking mode with Interrupt. + * @note This interface allow to manage repeated start condition when a direction change during transfer + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shift at right before call interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param XferOptions Options of Transfer, value of @ref I2C_XFEROPTIONS + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Sequential_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions) +{ + uint32_t xfermode = 0U; + uint32_t xferrequest = I2C_GENERATE_START_WRITE; + + /* Check the parameters */ + assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hi2c); + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_MASTER; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferOptions = XferOptions; + hi2c->XferISR = I2C_Master_ISR_IT; + + /* If size > MAX_NBYTE_SIZE, use reload mode */ + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + xfermode = I2C_RELOAD_MODE; + } + else + { + hi2c->XferSize = hi2c->XferCount; + xfermode = hi2c->XferOptions; + } + + /* If transfer direction not change, do not generate Restart Condition */ + /* Mean Previous state is same as current state */ + if (hi2c->PreviousState == I2C_STATE_MASTER_BUSY_TX) + { + xferrequest = I2C_NO_STARTSTOP; + } + + /* Send Slave Address and set NBYTES to write */ + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, xfermode, xferrequest); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Sequential receive in master I2C mode an amount of data in non-blocking mode with Interrupt + * @note This interface allow to manage repeated start condition when a direction change during transfer + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shift at right before call interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param XferOptions Options of Transfer, value of @ref I2C_XFEROPTIONS + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Sequential_Receive_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions) +{ + uint32_t xfermode = 0U; + uint32_t xferrequest = I2C_GENERATE_START_READ; + + /* Check the parameters */ + assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hi2c); + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_MASTER; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferOptions = XferOptions; + hi2c->XferISR = I2C_Master_ISR_IT; + + /* If hi2c->XferCount > MAX_NBYTE_SIZE, use reload mode */ + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + xfermode = I2C_RELOAD_MODE; + } + else + { + hi2c->XferSize = hi2c->XferCount; + xfermode = hi2c->XferOptions; + } + + /* If transfer direction not change, do not generate Restart Condition */ + /* Mean Previous state is same as current state */ + if (hi2c->PreviousState == I2C_STATE_MASTER_BUSY_RX) + { + xferrequest = I2C_NO_STARTSTOP; + } + + /* Send Slave Address and set NBYTES to read */ + I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, xfermode, xferrequest); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + I2C_Enable_IRQ(hi2c, I2C_XFER_RX_IT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Sequential transmit in slave/device I2C mode an amount of data in non-blocking mode with Interrupt + * @note This interface allow to manage repeated start condition when a direction change during transfer + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param XferOptions Options of Transfer, value of @ref I2C_XFEROPTIONS + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Slave_Sequential_Transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions) +{ + /* Check the parameters */ + assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions)); + + if ((hi2c->State & HAL_I2C_STATE_LISTEN) == HAL_I2C_STATE_LISTEN) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Disable Interrupts, to prevent preemption during treatment in case of multicall */ + I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT | I2C_XFER_TX_IT); + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* I2C cannot manage full duplex exchange so disable previous IT enabled if any */ + /* and then toggle the HAL slave RX state to TX state */ + if (hi2c->State == HAL_I2C_STATE_BUSY_RX_LISTEN) + { + /* Disable associated Interrupts */ + I2C_Disable_IRQ(hi2c, I2C_XFER_RX_IT); + } + + hi2c->State = HAL_I2C_STATE_BUSY_TX_LISTEN; + hi2c->Mode = HAL_I2C_MODE_SLAVE; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Enable Address Acknowledge */ + hi2c->Instance->CR2 &= ~I2C_CR2_NACK; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = XferOptions; + hi2c->XferISR = I2C_Slave_ISR_IT; + + if (I2C_GET_DIR(hi2c) == I2C_DIRECTION_RECEIVE) + { + /* Clear ADDR flag after prepare the transfer parameters */ + /* This action will generate an acknowledge to the Master */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + /* REnable ADDR interrupt */ + I2C_Enable_IRQ(hi2c, I2C_XFER_TX_IT | I2C_XFER_LISTEN_IT); + + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Sequential receive in slave/device I2C mode an amount of data in non-blocking mode with Interrupt + * @note This interface allow to manage repeated start condition when a direction change during transfer + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param XferOptions Options of Transfer, value of @ref I2C_XFEROPTIONS + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Slave_Sequential_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions) +{ + /* Check the parameters */ + assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions)); + + if ((hi2c->State & HAL_I2C_STATE_LISTEN) == HAL_I2C_STATE_LISTEN) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Disable Interrupts, to prevent preemption during treatment in case of multicall */ + I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT | I2C_XFER_RX_IT); + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* I2C cannot manage full duplex exchange so disable previous IT enabled if any */ + /* and then toggle the HAL slave TX state to RX state */ + if (hi2c->State == HAL_I2C_STATE_BUSY_TX_LISTEN) + { + /* Disable associated Interrupts */ + I2C_Disable_IRQ(hi2c, I2C_XFER_TX_IT); + } + + hi2c->State = HAL_I2C_STATE_BUSY_RX_LISTEN; + hi2c->Mode = HAL_I2C_MODE_SLAVE; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Enable Address Acknowledge */ + hi2c->Instance->CR2 &= ~I2C_CR2_NACK; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = XferOptions; + hi2c->XferISR = I2C_Slave_ISR_IT; + + if (I2C_GET_DIR(hi2c) == I2C_DIRECTION_TRANSMIT) + { + /* Clear ADDR flag after prepare the transfer parameters */ + /* This action will generate an acknowledge to the Master */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + /* REnable ADDR interrupt */ + I2C_Enable_IRQ(hi2c, I2C_XFER_RX_IT | I2C_XFER_LISTEN_IT); + + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Enable the Address listen mode with Interrupt. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_EnableListen_IT(I2C_HandleTypeDef *hi2c) +{ + if (hi2c->State == HAL_I2C_STATE_READY) + { + hi2c->State = HAL_I2C_STATE_LISTEN; + hi2c->XferISR = I2C_Slave_ISR_IT; + + /* Enable the Address Match interrupt */ + I2C_Enable_IRQ(hi2c, I2C_XFER_LISTEN_IT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Disable the Address listen mode with Interrupt. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_DisableListen_IT(I2C_HandleTypeDef *hi2c) +{ + /* Declaration of tmp to prevent undefined behavior of volatile usage */ + uint32_t tmp; + + /* Disable Address listen mode only if a transfer is not ongoing */ + if (hi2c->State == HAL_I2C_STATE_LISTEN) + { + tmp = (uint32_t)(hi2c->State) & I2C_STATE_MSK; + hi2c->PreviousState = tmp | (uint32_t)(hi2c->Mode); + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->XferISR = NULL; + + /* Disable the Address Match interrupt */ + I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Abort a master I2C IT or DMA process communication with Interrupt. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shift at right before call interface + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Abort_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress) +{ + if (hi2c->Mode == HAL_I2C_MODE_MASTER) + { + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Disable Interrupts */ + I2C_Disable_IRQ(hi2c, I2C_XFER_RX_IT); + I2C_Disable_IRQ(hi2c, I2C_XFER_TX_IT); + + /* Set State at HAL_I2C_STATE_ABORT */ + hi2c->State = HAL_I2C_STATE_ABORT; + + /* Set NBYTES to 1 to generate a dummy read on I2C peripheral */ + /* Set AUTOEND mode, this will generate a NACK then STOP condition to abort the current transfer */ + I2C_TransferConfig(hi2c, DevAddress, 1, I2C_AUTOEND_MODE, I2C_GENERATE_STOP); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + I2C_Enable_IRQ(hi2c, I2C_XFER_CPLT_IT); + + return HAL_OK; + } + else + { + /* Wrong usage of abort function */ + /* This function should be used only in case of abort monitored by master device */ + return HAL_ERROR; + } +} + +/** + * @} + */ + +/** @defgroup I2C_IRQ_Handler_and_Callbacks IRQ Handler and Callbacks + * @{ + */ + +/** + * @brief This function handles I2C event interrupt request. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +void HAL_I2C_EV_IRQHandler(I2C_HandleTypeDef *hi2c) +{ + /* Get current IT Flags and IT sources value */ + uint32_t itflags = READ_REG(hi2c->Instance->ISR); + uint32_t itsources = READ_REG(hi2c->Instance->CR1); + + /* I2C events treatment -------------------------------------*/ + if (hi2c->XferISR != NULL) + { + hi2c->XferISR(hi2c, itflags, itsources); + } +} + +/** + * @brief This function handles I2C error interrupt request. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +void HAL_I2C_ER_IRQHandler(I2C_HandleTypeDef *hi2c) +{ + uint32_t itflags = READ_REG(hi2c->Instance->ISR); + uint32_t itsources = READ_REG(hi2c->Instance->CR1); + + /* I2C Bus error interrupt occurred ------------------------------------*/ + if (((itflags & I2C_FLAG_BERR) != RESET) && ((itsources & I2C_IT_ERRI) != RESET)) + { + hi2c->ErrorCode |= HAL_I2C_ERROR_BERR; + + /* Clear BERR flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_BERR); + } + + /* I2C Over-Run/Under-Run interrupt occurred ----------------------------------------*/ + if (((itflags & I2C_FLAG_OVR) != RESET) && ((itsources & I2C_IT_ERRI) != RESET)) + { + hi2c->ErrorCode |= HAL_I2C_ERROR_OVR; + + /* Clear OVR flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_OVR); + } + + /* I2C Arbitration Loss error interrupt occurred -------------------------------------*/ + if (((itflags & I2C_FLAG_ARLO) != RESET) && ((itsources & I2C_IT_ERRI) != RESET)) + { + hi2c->ErrorCode |= HAL_I2C_ERROR_ARLO; + + /* Clear ARLO flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ARLO); + } + + /* Call the Error Callback in case of Error detected */ + if ((hi2c->ErrorCode & (HAL_I2C_ERROR_BERR | HAL_I2C_ERROR_OVR | HAL_I2C_ERROR_ARLO)) != HAL_I2C_ERROR_NONE) + { + I2C_ITError(hi2c, hi2c->ErrorCode); + } +} + +/** + * @brief Master Tx Transfer completed callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_MasterTxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Master Rx Transfer completed callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_MasterRxCpltCallback could be implemented in the user file + */ +} + +/** @brief Slave Tx Transfer completed callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_SlaveTxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Slave Rx Transfer completed callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_SlaveRxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Slave Address Match callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param TransferDirection Master request Transfer Direction (Write/Read), value of @ref I2C_XFERDIRECTION + * @param AddrMatchCode Address Match Code + * @retval None + */ +__weak void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + UNUSED(TransferDirection); + UNUSED(AddrMatchCode); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_AddrCallback() could be implemented in the user file + */ +} + +/** + * @brief Listen Complete callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_ListenCpltCallback() could be implemented in the user file + */ +} + +/** + * @brief Memory Tx Transfer completed callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_MemTxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Memory Rx Transfer completed callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_MemRxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief I2C error callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_ErrorCallback could be implemented in the user file + */ +} + +/** + * @brief I2C abort callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_AbortCpltCallback(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_AbortCpltCallback could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup I2C_Exported_Functions_Group3 Peripheral State, Mode and Error functions + * @brief Peripheral State, Mode and Error functions + * +@verbatim + =============================================================================== + ##### Peripheral State, Mode and Error functions ##### + =============================================================================== + [..] + This subsection permit to get in run-time the status of the peripheral + and the data flow. + +@endverbatim + * @{ + */ + +/** + * @brief Return the I2C handle state. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval HAL state + */ +HAL_I2C_StateTypeDef HAL_I2C_GetState(I2C_HandleTypeDef *hi2c) +{ + /* Return I2C handle state */ + return hi2c->State; +} + +/** + * @brief Returns the I2C Master, Slave, Memory or no mode. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @retval HAL mode + */ +HAL_I2C_ModeTypeDef HAL_I2C_GetMode(I2C_HandleTypeDef *hi2c) +{ + return hi2c->Mode; +} + +/** +* @brief Return the I2C error code. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. +* @retval I2C Error Code +*/ +uint32_t HAL_I2C_GetError(I2C_HandleTypeDef *hi2c) +{ + return hi2c->ErrorCode; +} + +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup I2C_Private_Functions + * @{ + */ + +/** + * @brief Interrupt Sub-Routine which handle the Interrupt Flags Master Mode with Interrupt. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param ITFlags Interrupt flags to handle. + * @param ITSources Interrupt sources enabled. + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_Master_ISR_IT(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags, uint32_t ITSources) +{ + uint16_t devaddress = 0U; + + /* Process Locked */ + __HAL_LOCK(hi2c); + + if (((ITFlags & I2C_FLAG_AF) != RESET) && ((ITSources & I2C_IT_NACKI) != RESET)) + { + /* Clear NACK Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + + /* Set corresponding Error Code */ + /* No need to generate STOP, it is automatically done */ + /* Error callback will be send during stop flag treatment */ + hi2c->ErrorCode |= HAL_I2C_ERROR_AF; + + /* Flush TX register */ + I2C_Flush_TXDR(hi2c); + } + else if (((ITFlags & I2C_FLAG_RXNE) != RESET) && ((ITSources & I2C_IT_RXI) != RESET)) + { + /* Read data from RXDR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->RXDR; + hi2c->XferSize--; + hi2c->XferCount--; + } + else if (((ITFlags & I2C_FLAG_TXIS) != RESET) && ((ITSources & I2C_IT_TXI) != RESET)) + { + /* Write data to TXDR */ + hi2c->Instance->TXDR = (*hi2c->pBuffPtr++); + hi2c->XferSize--; + hi2c->XferCount--; + } + else if (((ITFlags & I2C_FLAG_TCR) != RESET) && ((ITSources & I2C_IT_TCI) != RESET)) + { + if ((hi2c->XferSize == 0U) && (hi2c->XferCount != 0U)) + { + devaddress = (hi2c->Instance->CR2 & I2C_CR2_SADD); + + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + I2C_TransferConfig(hi2c, devaddress, hi2c->XferSize, I2C_RELOAD_MODE, I2C_NO_STARTSTOP); + } + else + { + hi2c->XferSize = hi2c->XferCount; + if (hi2c->XferOptions != I2C_NO_OPTION_FRAME) + { + I2C_TransferConfig(hi2c, devaddress, hi2c->XferSize, hi2c->XferOptions, I2C_NO_STARTSTOP); + } + else + { + I2C_TransferConfig(hi2c, devaddress, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP); + } + } + } + else + { + /* Call TxCpltCallback() if no stop mode is set */ + if (I2C_GET_STOP_MODE(hi2c) != I2C_AUTOEND_MODE) + { + /* Call I2C Master Sequential complete process */ + I2C_ITMasterSequentialCplt(hi2c); + } + else + { + /* Wrong size Status regarding TCR flag event */ + /* Call the corresponding callback to inform upper layer of End of Transfer */ + I2C_ITError(hi2c, HAL_I2C_ERROR_SIZE); + } + } + } + else if (((ITFlags & I2C_FLAG_TC) != RESET) && ((ITSources & I2C_IT_TCI) != RESET)) + { + if (hi2c->XferCount == 0U) + { + if (I2C_GET_STOP_MODE(hi2c) != I2C_AUTOEND_MODE) + { + /* Generate a stop condition in case of no transfer option */ + if (hi2c->XferOptions == I2C_NO_OPTION_FRAME) + { + /* Generate Stop */ + hi2c->Instance->CR2 |= I2C_CR2_STOP; + } + else + { + /* Call I2C Master Sequential complete process */ + I2C_ITMasterSequentialCplt(hi2c); + } + } + } + else + { + /* Wrong size Status regarding TC flag event */ + /* Call the corresponding callback to inform upper layer of End of Transfer */ + I2C_ITError(hi2c, HAL_I2C_ERROR_SIZE); + } + } + + if (((ITFlags & I2C_FLAG_STOPF) != RESET) && ((ITSources & I2C_IT_STOPI) != RESET)) + { + /* Call I2C Master complete process */ + I2C_ITMasterCplt(hi2c, ITFlags); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; +} + +/** + * @brief Interrupt Sub-Routine which handle the Interrupt Flags Slave Mode with Interrupt. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param ITFlags Interrupt flags to handle. + * @param ITSources Interrupt sources enabled. + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_Slave_ISR_IT(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags, uint32_t ITSources) +{ + /* Process locked */ + __HAL_LOCK(hi2c); + + if (((ITFlags & I2C_FLAG_AF) != RESET) && ((ITSources & I2C_IT_NACKI) != RESET)) + { + /* Check that I2C transfer finished */ + /* if yes, normal use case, a NACK is sent by the MASTER when Transfer is finished */ + /* Mean XferCount == 0*/ + /* So clear Flag NACKF only */ + if (hi2c->XferCount == 0U) + { + if (((hi2c->XferOptions == I2C_FIRST_AND_LAST_FRAME) || (hi2c->XferOptions == I2C_LAST_FRAME)) && \ + (hi2c->State == HAL_I2C_STATE_LISTEN)) + { + /* Call I2C Listen complete process */ + I2C_ITListenCplt(hi2c, ITFlags); + } + else if ((hi2c->XferOptions != I2C_NO_OPTION_FRAME) && (hi2c->State == HAL_I2C_STATE_BUSY_TX_LISTEN)) + { + /* Clear NACK Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + + /* Flush TX register */ + I2C_Flush_TXDR(hi2c); + + /* Last Byte is Transmitted */ + /* Call I2C Slave Sequential complete process */ + I2C_ITSlaveSequentialCplt(hi2c); + } + else + { + /* Clear NACK Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + } + } + else + { + /* if no, error use case, a Non-Acknowledge of last Data is generated by the MASTER*/ + /* Clear NACK Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + + /* Set ErrorCode corresponding to a Non-Acknowledge */ + hi2c->ErrorCode |= HAL_I2C_ERROR_AF; + } + } + else if (((ITFlags & I2C_FLAG_RXNE) != RESET) && ((ITSources & I2C_IT_RXI) != RESET)) + { + if (hi2c->XferCount > 0U) + { + /* Read data from RXDR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->RXDR; + hi2c->XferSize--; + hi2c->XferCount--; + } + + if ((hi2c->XferCount == 0U) && \ + (hi2c->XferOptions != I2C_NO_OPTION_FRAME)) + { + /* Call I2C Slave Sequential complete process */ + I2C_ITSlaveSequentialCplt(hi2c); + } + } + else if (((ITFlags & I2C_FLAG_ADDR) != RESET) && ((ITSources & I2C_IT_ADDRI) != RESET)) + { + I2C_ITAddrCplt(hi2c, ITFlags); + } + else if (((ITFlags & I2C_FLAG_TXIS) != RESET) && ((ITSources & I2C_IT_TXI) != RESET)) + { + /* Write data to TXDR only if XferCount not reach "0" */ + /* A TXIS flag can be set, during STOP treatment */ + /* Check if all Datas have already been sent */ + /* If it is the case, this last write in TXDR is not sent, correspond to a dummy TXIS event */ + if (hi2c->XferCount > 0U) + { + /* Write data to TXDR */ + hi2c->Instance->TXDR = (*hi2c->pBuffPtr++); + hi2c->XferCount--; + hi2c->XferSize--; + } + else + { + if ((hi2c->XferOptions == I2C_NEXT_FRAME) || (hi2c->XferOptions == I2C_FIRST_FRAME)) + { + /* Last Byte is Transmitted */ + /* Call I2C Slave Sequential complete process */ + I2C_ITSlaveSequentialCplt(hi2c); + } + } + } + + /* Check if STOPF is set */ + if (((ITFlags & I2C_FLAG_STOPF) != RESET) && ((ITSources & I2C_IT_STOPI) != RESET)) + { + /* Call I2C Slave complete process */ + I2C_ITSlaveCplt(hi2c, ITFlags); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; +} + +/** + * @brief Interrupt Sub-Routine which handle the Interrupt Flags Master Mode with DMA. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param ITFlags Interrupt flags to handle. + * @param ITSources Interrupt sources enabled. + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_Master_ISR_DMA(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags, uint32_t ITSources) +{ + uint16_t devaddress = 0U; + uint32_t xfermode = 0U; + + /* Process Locked */ + __HAL_LOCK(hi2c); + + if (((ITFlags & I2C_FLAG_AF) != RESET) && ((ITSources & I2C_IT_NACKI) != RESET)) + { + /* Clear NACK Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + + /* Set corresponding Error Code */ + hi2c->ErrorCode |= HAL_I2C_ERROR_AF; + + /* No need to generate STOP, it is automatically done */ + /* But enable STOP interrupt, to treat it */ + /* Error callback will be send during stop flag treatment */ + I2C_Enable_IRQ(hi2c, I2C_XFER_CPLT_IT); + + /* Flush TX register */ + I2C_Flush_TXDR(hi2c); + } + else if (((ITFlags & I2C_FLAG_TCR) != RESET) && ((ITSources & I2C_IT_TCI) != RESET)) + { + /* Disable TC interrupt */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_TCI); + + if (hi2c->XferCount != 0U) + { + /* Recover Slave address */ + devaddress = (hi2c->Instance->CR2 & I2C_CR2_SADD); + + /* Prepare the new XferSize to transfer */ + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + xfermode = I2C_RELOAD_MODE; + } + else + { + hi2c->XferSize = hi2c->XferCount; + xfermode = I2C_AUTOEND_MODE; + } + + /* Set the new XferSize in Nbytes register */ + I2C_TransferConfig(hi2c, devaddress, hi2c->XferSize, xfermode, I2C_NO_STARTSTOP); + + /* Update XferCount value */ + hi2c->XferCount -= hi2c->XferSize; + + /* Enable DMA Request */ + if (hi2c->State == HAL_I2C_STATE_BUSY_RX) + { + hi2c->Instance->CR1 |= I2C_CR1_RXDMAEN; + } + else + { + hi2c->Instance->CR1 |= I2C_CR1_TXDMAEN; + } + } + else + { + /* Wrong size Status regarding TCR flag event */ + /* Call the corresponding callback to inform upper layer of End of Transfer */ + I2C_ITError(hi2c, HAL_I2C_ERROR_SIZE); + } + } + else if (((ITFlags & I2C_FLAG_STOPF) != RESET) && ((ITSources & I2C_IT_STOPI) != RESET)) + { + /* Call I2C Master complete process */ + I2C_ITMasterCplt(hi2c, ITFlags); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; +} + +/** + * @brief Interrupt Sub-Routine which handle the Interrupt Flags Slave Mode with DMA. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param ITFlags Interrupt flags to handle. + * @param ITSources Interrupt sources enabled. + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_Slave_ISR_DMA(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags, uint32_t ITSources) +{ + /* Process locked */ + __HAL_LOCK(hi2c); + + if (((ITFlags & I2C_FLAG_AF) != RESET) && ((ITSources & I2C_IT_NACKI) != RESET)) + { + /* Check that I2C transfer finished */ + /* if yes, normal use case, a NACK is sent by the MASTER when Transfer is finished */ + /* Mean XferCount == 0 */ + /* So clear Flag NACKF only */ + if (I2C_GET_DMA_REMAIN_DATA(hi2c) == 0U) + { + /* Clear NACK Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + } + else + { + /* if no, error use case, a Non-Acknowledge of last Data is generated by the MASTER*/ + /* Clear NACK Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + + /* Set ErrorCode corresponding to a Non-Acknowledge */ + hi2c->ErrorCode |= HAL_I2C_ERROR_AF; + } + } + else if (((ITFlags & I2C_FLAG_ADDR) != RESET) && ((ITSources & I2C_IT_ADDRI) != RESET)) + { + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR); + } + else if (((ITFlags & I2C_FLAG_STOPF) != RESET) && ((ITSources & I2C_IT_STOPI) != RESET)) + { + /* Call I2C Slave complete process */ + I2C_ITSlaveCplt(hi2c, ITFlags); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; +} + +/** + * @brief Master sends target device address followed by internal memory address for write request. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shift at right before call interface + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_RequestMemoryWrite(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout, uint32_t Tickstart) +{ + I2C_TransferConfig(hi2c, DevAddress, MemAddSize, I2C_RELOAD_MODE, I2C_GENERATE_START_WRITE); + + /* Wait until TXIS flag is set */ + if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + /* If Memory address size is 8Bit */ + if (MemAddSize == I2C_MEMADD_SIZE_8BIT) + { + /* Send Memory Address */ + hi2c->Instance->TXDR = I2C_MEM_ADD_LSB(MemAddress); + } + /* If Memory address size is 16Bit */ + else + { + /* Send MSB of Memory Address */ + hi2c->Instance->TXDR = I2C_MEM_ADD_MSB(MemAddress); + + /* Wait until TXIS flag is set */ + if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + /* Send LSB of Memory Address */ + hi2c->Instance->TXDR = I2C_MEM_ADD_LSB(MemAddress); + } + + /* Wait until TCR flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout, Tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + return HAL_OK; +} + +/** + * @brief Master sends target device address followed by internal memory address for read request. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shift at right before call interface + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_RequestMemoryRead(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout, uint32_t Tickstart) +{ + I2C_TransferConfig(hi2c, DevAddress, MemAddSize, I2C_SOFTEND_MODE, I2C_GENERATE_START_WRITE); + + /* Wait until TXIS flag is set */ + if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + /* If Memory address size is 8Bit */ + if (MemAddSize == I2C_MEMADD_SIZE_8BIT) + { + /* Send Memory Address */ + hi2c->Instance->TXDR = I2C_MEM_ADD_LSB(MemAddress); + } + /* If Memory address size is 16Bit */ + else + { + /* Send MSB of Memory Address */ + hi2c->Instance->TXDR = I2C_MEM_ADD_MSB(MemAddress); + + /* Wait until TXIS flag is set */ + if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + return HAL_ERROR; + } + else + { + return HAL_TIMEOUT; + } + } + + /* Send LSB of Memory Address */ + hi2c->Instance->TXDR = I2C_MEM_ADD_LSB(MemAddress); + } + + /* Wait until TC flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TC, RESET, Timeout, Tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + return HAL_OK; +} + +/** + * @brief I2C Address complete process callback. + * @param hi2c I2C handle. + * @param ITFlags Interrupt flags to handle. + * @retval None + */ +static void I2C_ITAddrCplt(I2C_HandleTypeDef *hi2c, uint32_t ITFlags) +{ + uint8_t transferdirection = 0U; + uint16_t slaveaddrcode = 0U; + uint16_t ownadd1code = 0U; + uint16_t ownadd2code = 0U; + + /* Prevent unused argument(s) compilation warning */ + UNUSED(ITFlags); + + /* In case of Listen state, need to inform upper layer of address match code event */ + if ((hi2c->State & HAL_I2C_STATE_LISTEN) == HAL_I2C_STATE_LISTEN) + { + transferdirection = I2C_GET_DIR(hi2c); + slaveaddrcode = I2C_GET_ADDR_MATCH(hi2c); + ownadd1code = I2C_GET_OWN_ADDRESS1(hi2c); + ownadd2code = I2C_GET_OWN_ADDRESS2(hi2c); + + /* If 10bits addressing mode is selected */ + if (hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_10BIT) + { + if ((slaveaddrcode & SlaveAddr_MSK) == ((ownadd1code >> SlaveAddr_SHIFT) & SlaveAddr_MSK)) + { + slaveaddrcode = ownadd1code; + hi2c->AddrEventCount++; + if (hi2c->AddrEventCount == 2U) + { + /* Reset Address Event counter */ + hi2c->AddrEventCount = 0U; + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Call Slave Addr callback */ + HAL_I2C_AddrCallback(hi2c, transferdirection, slaveaddrcode); + } + } + else + { + slaveaddrcode = ownadd2code; + + /* Disable ADDR Interrupts */ + I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Call Slave Addr callback */ + HAL_I2C_AddrCallback(hi2c, transferdirection, slaveaddrcode); + } + } + /* else 7 bits addressing mode is selected */ + else + { + /* Disable ADDR Interrupts */ + I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Call Slave Addr callback */ + HAL_I2C_AddrCallback(hi2c, transferdirection, slaveaddrcode); + } + } + /* Else clear address flag only */ + else + { + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + } +} + +/** + * @brief I2C Master sequential complete process. + * @param hi2c I2C handle. + * @retval None + */ +static void I2C_ITMasterSequentialCplt(I2C_HandleTypeDef *hi2c) +{ + /* Reset I2C handle mode */ + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* No Generate Stop, to permit restart mode */ + /* The stop will be done at the end of transfer, when I2C_AUTOEND_MODE enable */ + if (hi2c->State == HAL_I2C_STATE_BUSY_TX) + { + hi2c->State = HAL_I2C_STATE_READY; + hi2c->PreviousState = I2C_STATE_MASTER_BUSY_TX; + hi2c->XferISR = NULL; + + /* Disable Interrupts */ + I2C_Disable_IRQ(hi2c, I2C_XFER_TX_IT); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ + HAL_I2C_MasterTxCpltCallback(hi2c); + } + /* hi2c->State == HAL_I2C_STATE_BUSY_RX */ + else + { + hi2c->State = HAL_I2C_STATE_READY; + hi2c->PreviousState = I2C_STATE_MASTER_BUSY_RX; + hi2c->XferISR = NULL; + + /* Disable Interrupts */ + I2C_Disable_IRQ(hi2c, I2C_XFER_RX_IT); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ + HAL_I2C_MasterRxCpltCallback(hi2c); + } +} + +/** + * @brief I2C Slave sequential complete process. + * @param hi2c I2C handle. + * @retval None + */ +static void I2C_ITSlaveSequentialCplt(I2C_HandleTypeDef *hi2c) +{ + /* Reset I2C handle mode */ + hi2c->Mode = HAL_I2C_MODE_NONE; + + if (hi2c->State == HAL_I2C_STATE_BUSY_TX_LISTEN) + { + /* Remove HAL_I2C_STATE_SLAVE_BUSY_TX, keep only HAL_I2C_STATE_LISTEN */ + hi2c->State = HAL_I2C_STATE_LISTEN; + hi2c->PreviousState = I2C_STATE_SLAVE_BUSY_TX; + + /* Disable Interrupts */ + I2C_Disable_IRQ(hi2c, I2C_XFER_TX_IT); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Call the Tx complete callback to inform upper layer of the end of transmit process */ + HAL_I2C_SlaveTxCpltCallback(hi2c); + } + + else if (hi2c->State == HAL_I2C_STATE_BUSY_RX_LISTEN) + { + /* Remove HAL_I2C_STATE_SLAVE_BUSY_RX, keep only HAL_I2C_STATE_LISTEN */ + hi2c->State = HAL_I2C_STATE_LISTEN; + hi2c->PreviousState = I2C_STATE_SLAVE_BUSY_RX; + + /* Disable Interrupts */ + I2C_Disable_IRQ(hi2c, I2C_XFER_RX_IT); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Call the Rx complete callback to inform upper layer of the end of receive process */ + HAL_I2C_SlaveRxCpltCallback(hi2c); + } +} + +/** + * @brief I2C Master complete process. + * @param hi2c I2C handle. + * @param ITFlags Interrupt flags to handle. + * @retval None + */ +static void I2C_ITMasterCplt(I2C_HandleTypeDef *hi2c, uint32_t ITFlags) +{ + /* Clear STOP Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); + + /* Clear Configuration Register 2 */ + I2C_RESET_CR2(hi2c); + + /* Reset handle parameters */ + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->XferISR = NULL; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + + if ((ITFlags & I2C_FLAG_AF) != RESET) + { + /* Clear NACK Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + + /* Set acknowledge error code */ + hi2c->ErrorCode |= HAL_I2C_ERROR_AF; + } + + /* Flush TX register */ + I2C_Flush_TXDR(hi2c); + + /* Disable Interrupts */ + I2C_Disable_IRQ(hi2c, I2C_XFER_TX_IT | I2C_XFER_RX_IT); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ + if ((hi2c->ErrorCode != HAL_I2C_ERROR_NONE) || (hi2c->State == HAL_I2C_STATE_ABORT)) + { + /* Call the corresponding callback to inform upper layer of End of Transfer */ + I2C_ITError(hi2c, hi2c->ErrorCode); + } + /* hi2c->State == HAL_I2C_STATE_BUSY_TX */ + else if (hi2c->State == HAL_I2C_STATE_BUSY_TX) + { + hi2c->State = HAL_I2C_STATE_READY; + + if (hi2c->Mode == HAL_I2C_MODE_MEM) + { + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ + HAL_I2C_MemTxCpltCallback(hi2c); + } + else + { + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ + HAL_I2C_MasterTxCpltCallback(hi2c); + } + } + /* hi2c->State == HAL_I2C_STATE_BUSY_RX */ + else if (hi2c->State == HAL_I2C_STATE_BUSY_RX) + { + hi2c->State = HAL_I2C_STATE_READY; + + if (hi2c->Mode == HAL_I2C_MODE_MEM) + { + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + HAL_I2C_MemRxCpltCallback(hi2c); + } + else + { + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + HAL_I2C_MasterRxCpltCallback(hi2c); + } + } +} + +/** + * @brief I2C Slave complete process. + * @param hi2c I2C handle. + * @param ITFlags Interrupt flags to handle. + * @retval None + */ +static void I2C_ITSlaveCplt(I2C_HandleTypeDef *hi2c, uint32_t ITFlags) +{ + /* Clear STOP Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR); + + /* Disable all interrupts */ + I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT | I2C_XFER_TX_IT | I2C_XFER_RX_IT); + + /* Disable Address Acknowledge */ + hi2c->Instance->CR2 |= I2C_CR2_NACK; + + /* Clear Configuration Register 2 */ + I2C_RESET_CR2(hi2c); + + /* Flush TX register */ + I2C_Flush_TXDR(hi2c); + + /* If a DMA is ongoing, Update handle size context */ + if (((hi2c->Instance->CR1 & I2C_CR1_TXDMAEN) == I2C_CR1_TXDMAEN) || + ((hi2c->Instance->CR1 & I2C_CR1_RXDMAEN) == I2C_CR1_RXDMAEN)) + { + hi2c->XferCount = I2C_GET_DMA_REMAIN_DATA(hi2c); + } + + /* All data are not transferred, so set error code accordingly */ + if (hi2c->XferCount != 0U) + { + /* Set ErrorCode corresponding to a Non-Acknowledge */ + hi2c->ErrorCode |= HAL_I2C_ERROR_AF; + } + + /* Store Last receive data if any */ + if (((ITFlags & I2C_FLAG_RXNE) != RESET)) + { + /* Read data from RXDR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->RXDR; + + if ((hi2c->XferSize > 0U)) + { + hi2c->XferSize--; + hi2c->XferCount--; + + /* Set ErrorCode corresponding to a Non-Acknowledge */ + hi2c->ErrorCode |= HAL_I2C_ERROR_AF; + } + } + + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->XferISR = NULL; + + if (hi2c->ErrorCode != HAL_I2C_ERROR_NONE) + { + /* Call the corresponding callback to inform upper layer of End of Transfer */ + I2C_ITError(hi2c, hi2c->ErrorCode); + + /* Call the Listen Complete callback, to inform upper layer of the end of Listen usecase */ + if (hi2c->State == HAL_I2C_STATE_LISTEN) + { + /* Call I2C Listen complete process */ + I2C_ITListenCplt(hi2c, ITFlags); + } + } + else if (hi2c->XferOptions != I2C_NO_OPTION_FRAME) + { + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->State = HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Call the Listen Complete callback, to inform upper layer of the end of Listen usecase */ + HAL_I2C_ListenCpltCallback(hi2c); + } + /* Call the corresponding callback to inform upper layer of End of Transfer */ + else if (hi2c->State == HAL_I2C_STATE_BUSY_RX) + { + hi2c->State = HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Call the Slave Rx Complete callback */ + HAL_I2C_SlaveRxCpltCallback(hi2c); + } + else + { + hi2c->State = HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Call the Slave Tx Complete callback */ + HAL_I2C_SlaveTxCpltCallback(hi2c); + } +} + +/** + * @brief I2C Listen complete process. + * @param hi2c I2C handle. + * @param ITFlags Interrupt flags to handle. + * @retval None + */ +static void I2C_ITListenCplt(I2C_HandleTypeDef *hi2c, uint32_t ITFlags) +{ + /* Reset handle parameters */ + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->XferISR = NULL; + + /* Store Last receive data if any */ + if (((ITFlags & I2C_FLAG_RXNE) != RESET)) + { + /* Read data from RXDR */ + (*hi2c->pBuffPtr++) = hi2c->Instance->RXDR; + + if ((hi2c->XferSize > 0U)) + { + hi2c->XferSize--; + hi2c->XferCount--; + + /* Set ErrorCode corresponding to a Non-Acknowledge */ + hi2c->ErrorCode |= HAL_I2C_ERROR_AF; + } + } + + /* Disable all Interrupts*/ + I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT | I2C_XFER_RX_IT | I2C_XFER_TX_IT); + + /* Clear NACK Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Call the Listen Complete callback, to inform upper layer of the end of Listen usecase */ + HAL_I2C_ListenCpltCallback(hi2c); +} + +/** + * @brief I2C interrupts error process. + * @param hi2c I2C handle. + * @param ErrorCode Error code to handle. + * @retval None + */ +static void I2C_ITError(I2C_HandleTypeDef *hi2c, uint32_t ErrorCode) +{ + /* Reset handle parameters */ + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->XferCount = 0U; + + /* Set new error code */ + hi2c->ErrorCode |= ErrorCode; + + /* Disable Interrupts */ + if ((hi2c->State == HAL_I2C_STATE_LISTEN) || + (hi2c->State == HAL_I2C_STATE_BUSY_TX_LISTEN) || + (hi2c->State == HAL_I2C_STATE_BUSY_RX_LISTEN)) + { + /* Disable all interrupts, except interrupts related to LISTEN state */ + I2C_Disable_IRQ(hi2c, I2C_XFER_RX_IT | I2C_XFER_TX_IT); + + /* keep HAL_I2C_STATE_LISTEN if set */ + hi2c->State = HAL_I2C_STATE_LISTEN; + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->XferISR = I2C_Slave_ISR_IT; + } + else + { + /* Disable all interrupts */ + I2C_Disable_IRQ(hi2c, I2C_XFER_LISTEN_IT | I2C_XFER_RX_IT | I2C_XFER_TX_IT); + + /* If state is an abort treatment on goind, don't change state */ + /* This change will be do later */ + if (hi2c->State != HAL_I2C_STATE_ABORT) + { + /* Set HAL_I2C_STATE_READY */ + hi2c->State = HAL_I2C_STATE_READY; + } + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->XferISR = NULL; + } + + /* Abort DMA TX transfer if any */ + if ((hi2c->Instance->CR1 & I2C_CR1_TXDMAEN) == I2C_CR1_TXDMAEN) + { + hi2c->Instance->CR1 &= ~I2C_CR1_TXDMAEN; + + /* Set the I2C DMA Abort callback : + will lead to call HAL_I2C_ErrorCallback() at end of DMA abort procedure */ + hi2c->hdmatx->XferAbortCallback = I2C_DMAAbort; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Abort DMA TX */ + if (HAL_DMA_Abort_IT(hi2c->hdmatx) != HAL_OK) + { + /* Call Directly XferAbortCallback function in case of error */ + hi2c->hdmatx->XferAbortCallback(hi2c->hdmatx); + } + } + /* Abort DMA RX transfer if any */ + else if ((hi2c->Instance->CR1 & I2C_CR1_RXDMAEN) == I2C_CR1_RXDMAEN) + { + hi2c->Instance->CR1 &= ~I2C_CR1_RXDMAEN; + + /* Set the I2C DMA Abort callback : + will lead to call HAL_I2C_ErrorCallback() at end of DMA abort procedure */ + hi2c->hdmarx->XferAbortCallback = I2C_DMAAbort; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Abort DMA RX */ + if (HAL_DMA_Abort_IT(hi2c->hdmarx) != HAL_OK) + { + /* Call Directly hi2c->hdmarx->XferAbortCallback function in case of error */ + hi2c->hdmarx->XferAbortCallback(hi2c->hdmarx); + } + } + else if (hi2c->State == HAL_I2C_STATE_ABORT) + { + hi2c->State = HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ + HAL_I2C_AbortCpltCallback(hi2c); + } + else + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ + HAL_I2C_ErrorCallback(hi2c); + } +} + +/** + * @brief I2C Tx data register flush process. + * @param hi2c I2C handle. + * @retval None + */ +static void I2C_Flush_TXDR(I2C_HandleTypeDef *hi2c) +{ + /* If a pending TXIS flag is set */ + /* Write a dummy data in TXDR to clear it */ + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXIS) != RESET) + { + hi2c->Instance->TXDR = 0x00U; + } + + /* Flush TX register if not empty */ + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXE) == RESET) + { + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_TXE); + } +} + +/** + * @brief DMA I2C master transmit process complete callback. + * @param hdma DMA handle + * @retval None + */ +static void I2C_DMAMasterTransmitCplt(DMA_HandleTypeDef *hdma) +{ + I2C_HandleTypeDef *hi2c = (I2C_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + /* Disable DMA Request */ + hi2c->Instance->CR1 &= ~I2C_CR1_TXDMAEN; + + /* If last transfer, enable STOP interrupt */ + if (hi2c->XferCount == 0U) + { + /* Enable STOP interrupt */ + I2C_Enable_IRQ(hi2c, I2C_XFER_CPLT_IT); + } + /* else prepare a new DMA transfer and enable TCReload interrupt */ + else + { + /* Update Buffer pointer */ + hi2c->pBuffPtr += hi2c->XferSize; + + /* Set the XferSize to transfer */ + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + } + else + { + hi2c->XferSize = hi2c->XferCount; + } + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)hi2c->pBuffPtr, (uint32_t)&hi2c->Instance->TXDR, hi2c->XferSize); + + /* Enable TC interrupts */ + I2C_Enable_IRQ(hi2c, I2C_XFER_RELOAD_IT); + } +} + +/** + * @brief DMA I2C slave transmit process complete callback. + * @param hdma DMA handle + * @retval None + */ +static void I2C_DMASlaveTransmitCplt(DMA_HandleTypeDef *hdma) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hdma); + + /* No specific action, Master fully manage the generation of STOP condition */ + /* Mean that this generation can arrive at any time, at the end or during DMA process */ + /* So STOP condition should be manage through Interrupt treatment */ +} + +/** + * @brief DMA I2C master receive process complete callback. + * @param hdma DMA handle + * @retval None + */ +static void I2C_DMAMasterReceiveCplt(DMA_HandleTypeDef *hdma) +{ + I2C_HandleTypeDef *hi2c = (I2C_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + /* Disable DMA Request */ + hi2c->Instance->CR1 &= ~I2C_CR1_RXDMAEN; + + /* If last transfer, enable STOP interrupt */ + if (hi2c->XferCount == 0U) + { + /* Enable STOP interrupt */ + I2C_Enable_IRQ(hi2c, I2C_XFER_CPLT_IT); + } + /* else prepare a new DMA transfer and enable TCReload interrupt */ + else + { + /* Update Buffer pointer */ + hi2c->pBuffPtr += hi2c->XferSize; + + /* Set the XferSize to transfer */ + if (hi2c->XferCount > MAX_NBYTE_SIZE) + { + hi2c->XferSize = MAX_NBYTE_SIZE; + } + else + { + hi2c->XferSize = hi2c->XferCount; + } + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->RXDR, (uint32_t)hi2c->pBuffPtr, hi2c->XferSize); + + /* Enable TC interrupts */ + I2C_Enable_IRQ(hi2c, I2C_XFER_RELOAD_IT); + } +} + +/** + * @brief DMA I2C slave receive process complete callback. + * @param hdma DMA handle + * @retval None + */ +static void I2C_DMASlaveReceiveCplt(DMA_HandleTypeDef *hdma) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hdma); + + /* No specific action, Master fully manage the generation of STOP condition */ + /* Mean that this generation can arrive at any time, at the end or during DMA process */ + /* So STOP condition should be manage through Interrupt treatment */ +} + +/** + * @brief DMA I2C communication error callback. + * @param hdma DMA handle + * @retval None + */ +static void I2C_DMAError(DMA_HandleTypeDef *hdma) +{ + I2C_HandleTypeDef *hi2c = (I2C_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + /* Disable Acknowledge */ + hi2c->Instance->CR2 |= I2C_CR2_NACK; + + /* Call the corresponding callback to inform upper layer of End of Transfer */ + I2C_ITError(hi2c, HAL_I2C_ERROR_DMA); +} + +/** + * @brief DMA I2C communication abort callback + * (To be called at end of DMA Abort procedure). + * @param hdma DMA handle. + * @retval None + */ +static void I2C_DMAAbort(DMA_HandleTypeDef *hdma) +{ + I2C_HandleTypeDef *hi2c = (I2C_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + /* Disable Acknowledge */ + hi2c->Instance->CR2 |= I2C_CR2_NACK; + + /* Reset AbortCpltCallback */ + hi2c->hdmatx->XferAbortCallback = NULL; + hi2c->hdmarx->XferAbortCallback = NULL; + + /* Check if come from abort from user */ + if (hi2c->State == HAL_I2C_STATE_ABORT) + { + hi2c->State = HAL_I2C_STATE_READY; + + /* Call the corresponding callback to inform upper layer of End of Transfer */ + HAL_I2C_AbortCpltCallback(hi2c); + } + else + { + /* Call the corresponding callback to inform upper layer of End of Transfer */ + HAL_I2C_ErrorCallback(hi2c); + } +} + +/** + * @brief This function handles I2C Communication Timeout. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param Flag Specifies the I2C flag to check. + * @param Status The new Flag status (SET or RESET). + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_WaitOnFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, FlagStatus Status, uint32_t Timeout, uint32_t Tickstart) +{ + while (__HAL_I2C_GET_FLAG(hi2c, Flag) == Status) + { + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if ((Timeout == 0U) || ((HAL_GetTick() - Tickstart) > Timeout)) + { + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_TIMEOUT; + } + } + } + return HAL_OK; +} + +/** + * @brief This function handles I2C Communication Timeout for specific usage of TXIS flag. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_WaitOnTXISFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart) +{ + while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXIS) == RESET) + { + /* Check if a NACK is detected */ + if (I2C_IsAcknowledgeFailed(hi2c, Timeout, Tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if ((Timeout == 0U) || ((HAL_GetTick() - Tickstart) > Timeout)) + { + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_TIMEOUT; + } + } + } + return HAL_OK; +} + +/** + * @brief This function handles I2C Communication Timeout for specific usage of STOP flag. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_WaitOnSTOPFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart) +{ + while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == RESET) + { + /* Check if a NACK is detected */ + if (I2C_IsAcknowledgeFailed(hi2c, Timeout, Tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Check for the Timeout */ + if ((Timeout == 0U) || ((HAL_GetTick() - Tickstart) > Timeout)) + { + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_TIMEOUT; + } + } + return HAL_OK; +} + +/** + * @brief This function handles I2C Communication Timeout for specific usage of RXNE flag. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_WaitOnRXNEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart) +{ + while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == RESET) + { + /* Check if a NACK is detected */ + if (I2C_IsAcknowledgeFailed(hi2c, Timeout, Tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Check if a STOPF is detected */ + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == SET) + { + /* Check if an RXNE is pending */ + /* Store Last receive data if any */ + if ((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == SET) && (hi2c->XferSize > 0U)) + { + /* Return HAL_OK */ + /* The Reading of data from RXDR will be done in caller function */ + return HAL_OK; + } + else + { + /* Clear STOP Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); + + /* Clear Configuration Register 2 */ + I2C_RESET_CR2(hi2c); + + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + } + + /* Check for the Timeout */ + if ((Timeout == 0U) || ((HAL_GetTick() - Tickstart) > Timeout)) + { + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + hi2c->State = HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_TIMEOUT; + } + } + return HAL_OK; +} + +/** + * @brief This function handles Acknowledge failed detection during an I2C Communication. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_IsAcknowledgeFailed(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart) +{ + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET) + { + /* Wait until STOP Flag is reset */ + /* AutoEnd should be initiate after AF */ + while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == RESET) + { + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if ((Timeout == 0U) || ((HAL_GetTick() - Tickstart) > Timeout)) + { + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + return HAL_TIMEOUT; + } + } + } + + /* Clear NACKF Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + + /* Clear STOP Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); + + /* Flush TX register */ + I2C_Flush_TXDR(hi2c); + + /* Clear Configuration Register 2 */ + I2C_RESET_CR2(hi2c); + + hi2c->ErrorCode = HAL_I2C_ERROR_AF; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + return HAL_OK; +} + +/** + * @brief Handles I2Cx communication when starting transfer or during transfer (TC or TCR flag are set). + * @param hi2c I2C handle. + * @param DevAddress Specifies the slave address to be programmed. + * @param Size Specifies the number of bytes to be programmed. + * This parameter must be a value between 0 and 255. + * @param Mode New state of the I2C START condition generation. + * This parameter can be one of the following values: + * @arg @ref I2C_RELOAD_MODE Enable Reload mode . + * @arg @ref I2C_AUTOEND_MODE Enable Automatic end mode. + * @arg @ref I2C_SOFTEND_MODE Enable Software end mode. + * @param Request New state of the I2C START condition generation. + * This parameter can be one of the following values: + * @arg @ref I2C_NO_STARTSTOP Don't Generate stop and start condition. + * @arg @ref I2C_GENERATE_STOP Generate stop condition (Size should be set to 0). + * @arg @ref I2C_GENERATE_START_READ Generate Restart for read request. + * @arg @ref I2C_GENERATE_START_WRITE Generate Restart for write request. + * @retval None + */ +static void I2C_TransferConfig(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t Size, uint32_t Mode, uint32_t Request) +{ + /* Check the parameters */ + assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance)); + assert_param(IS_TRANSFER_MODE(Mode)); + assert_param(IS_TRANSFER_REQUEST(Request)); + + /* update CR2 register */ + MODIFY_REG(hi2c->Instance->CR2, ((I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD | I2C_CR2_AUTOEND | (I2C_CR2_RD_WRN & (uint32_t)(Request >> (31U - I2C_CR2_RD_WRN_Pos))) | I2C_CR2_START | I2C_CR2_STOP)), \ + (uint32_t)(((uint32_t)DevAddress & I2C_CR2_SADD) | (((uint32_t)Size << I2C_CR2_NBYTES_Pos) & I2C_CR2_NBYTES) | (uint32_t)Mode | (uint32_t)Request)); +} + +/** + * @brief Manage the enabling of Interrupts. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param InterruptRequest Value of @ref I2C_Interrupt_configuration_definition. + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_Enable_IRQ(I2C_HandleTypeDef *hi2c, uint16_t InterruptRequest) +{ + uint32_t tmpisr = 0U; + + if ((hi2c->XferISR == I2C_Master_ISR_DMA) || \ + (hi2c->XferISR == I2C_Slave_ISR_DMA)) + { + if ((InterruptRequest & I2C_XFER_LISTEN_IT) == I2C_XFER_LISTEN_IT) + { + /* Enable ERR, STOP, NACK and ADDR interrupts */ + tmpisr |= I2C_IT_ADDRI | I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_ERRI; + } + + if ((InterruptRequest & I2C_XFER_ERROR_IT) == I2C_XFER_ERROR_IT) + { + /* Enable ERR and NACK interrupts */ + tmpisr |= I2C_IT_ERRI | I2C_IT_NACKI; + } + + if ((InterruptRequest & I2C_XFER_CPLT_IT) == I2C_XFER_CPLT_IT) + { + /* Enable STOP interrupts */ + tmpisr |= I2C_IT_STOPI; + } + + if ((InterruptRequest & I2C_XFER_RELOAD_IT) == I2C_XFER_RELOAD_IT) + { + /* Enable TC interrupts */ + tmpisr |= I2C_IT_TCI; + } + } + else + { + if ((InterruptRequest & I2C_XFER_LISTEN_IT) == I2C_XFER_LISTEN_IT) + { + /* Enable ERR, STOP, NACK, and ADDR interrupts */ + tmpisr |= I2C_IT_ADDRI | I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_ERRI; + } + + if ((InterruptRequest & I2C_XFER_TX_IT) == I2C_XFER_TX_IT) + { + /* Enable ERR, TC, STOP, NACK and RXI interrupts */ + tmpisr |= I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_TXI; + } + + if ((InterruptRequest & I2C_XFER_RX_IT) == I2C_XFER_RX_IT) + { + /* Enable ERR, TC, STOP, NACK and TXI interrupts */ + tmpisr |= I2C_IT_ERRI | I2C_IT_TCI | I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_RXI; + } + + if ((InterruptRequest & I2C_XFER_CPLT_IT) == I2C_XFER_CPLT_IT) + { + /* Enable STOP interrupts */ + tmpisr |= I2C_IT_STOPI; + } + } + + /* Enable interrupts only at the end */ + /* to avoid the risk of I2C interrupt handle execution before */ + /* all interrupts requested done */ + __HAL_I2C_ENABLE_IT(hi2c, tmpisr); + + return HAL_OK; +} + +/** + * @brief Manage the disabling of Interrupts. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param InterruptRequest Value of @ref I2C_Interrupt_configuration_definition. + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_Disable_IRQ(I2C_HandleTypeDef *hi2c, uint16_t InterruptRequest) +{ + uint32_t tmpisr = 0U; + + if ((InterruptRequest & I2C_XFER_TX_IT) == I2C_XFER_TX_IT) + { + /* Disable TC and TXI interrupts */ + tmpisr |= I2C_IT_TCI | I2C_IT_TXI; + + if ((hi2c->State & HAL_I2C_STATE_LISTEN) != HAL_I2C_STATE_LISTEN) + { + /* Disable NACK and STOP interrupts */ + tmpisr |= I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_ERRI; + } + } + + if ((InterruptRequest & I2C_XFER_RX_IT) == I2C_XFER_RX_IT) + { + /* Disable TC and RXI interrupts */ + tmpisr |= I2C_IT_TCI | I2C_IT_RXI; + + if ((hi2c->State & HAL_I2C_STATE_LISTEN) != HAL_I2C_STATE_LISTEN) + { + /* Disable NACK and STOP interrupts */ + tmpisr |= I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_ERRI; + } + } + + if ((InterruptRequest & I2C_XFER_LISTEN_IT) == I2C_XFER_LISTEN_IT) + { + /* Disable ADDR, NACK and STOP interrupts */ + tmpisr |= I2C_IT_ADDRI | I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_ERRI; + } + + if ((InterruptRequest & I2C_XFER_ERROR_IT) == I2C_XFER_ERROR_IT) + { + /* Enable ERR and NACK interrupts */ + tmpisr |= I2C_IT_ERRI | I2C_IT_NACKI; + } + + if ((InterruptRequest & I2C_XFER_CPLT_IT) == I2C_XFER_CPLT_IT) + { + /* Enable STOP interrupts */ + tmpisr |= I2C_IT_STOPI; + } + + if ((InterruptRequest & I2C_XFER_RELOAD_IT) == I2C_XFER_RELOAD_IT) + { + /* Enable TC interrupts */ + tmpisr |= I2C_IT_TCI; + } + + /* Disable interrupts only at the end */ + /* to avoid a breaking situation like at "t" time */ + /* all disable interrupts request are not done */ + __HAL_I2C_DISABLE_IT(hi2c, tmpisr); + + return HAL_OK; +} + +/** + * @} + */ + +#endif /* HAL_I2C_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_i2c_ex.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_i2c_ex.c new file mode 100644 index 0000000..bd4e329 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_i2c_ex.c @@ -0,0 +1,355 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_i2c_ex.c + * @author MCD Application Team + * @brief I2C Extended HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of I2C Extended peripheral: + * + Extended features functions + * + @verbatim + ============================================================================== + ##### I2C peripheral Extended features ##### + ============================================================================== + + [..] Comparing to other previous devices, the I2C interface for STM32L4xx + devices contains the following additional features + + (+) Possibility to disable or enable Analog Noise Filter + (+) Use of a configured Digital Noise Filter + (+) Disable or enable wakeup from Stop mode(s) + (+) Disable or enable Fast Mode Plus + + ##### How to use this driver ##### + ============================================================================== + [..] This driver provides functions to configure Noise Filter and Wake Up Feature + (#) Configure I2C Analog noise filter using the function HAL_I2CEx_ConfigAnalogFilter() + (#) Configure I2C Digital noise filter using the function HAL_I2CEx_ConfigDigitalFilter() + (#) Configure the enable or disable of I2C Wake Up Mode using the functions : + (++) HAL_I2CEx_EnableWakeUp() + (++) HAL_I2CEx_DisableWakeUp() + (#) Configure the enable or disable of fast mode plus driving capability using the functions : + (++) HAL_I2CEx_EnableFastModePlus() + (++) HAL_I2CEx_DisableFastModePlus() + @endverbatim + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup I2CEx I2CEx + * @brief I2C Extended HAL module driver + * @{ + */ + +#ifdef HAL_I2C_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + +/** @defgroup I2CEx_Exported_Functions I2C Extended Exported Functions + * @{ + */ + +/** @defgroup I2CEx_Exported_Functions_Group1 Extended features functions + * @brief Extended features functions + * +@verbatim + =============================================================================== + ##### Extended features functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Configure Noise Filters + (+) Configure Wake Up Feature + (+) Configure Fast Mode Plus + +@endverbatim + * @{ + */ + +/** + * @brief Configure I2C Analog noise filter. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2Cx peripheral. + * @param AnalogFilter New state of the Analog filter. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2CEx_ConfigAnalogFilter(I2C_HandleTypeDef *hi2c, uint32_t AnalogFilter) +{ + /* Check the parameters */ + assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance)); + assert_param(IS_I2C_ANALOG_FILTER(AnalogFilter)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hi2c); + + hi2c->State = HAL_I2C_STATE_BUSY; + + /* Disable the selected I2C peripheral */ + __HAL_I2C_DISABLE(hi2c); + + /* Reset I2Cx ANOFF bit */ + hi2c->Instance->CR1 &= ~(I2C_CR1_ANFOFF); + + /* Set analog filter bit*/ + hi2c->Instance->CR1 |= AnalogFilter; + + __HAL_I2C_ENABLE(hi2c); + + hi2c->State = HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Configure I2C Digital noise filter. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2Cx peripheral. + * @param DigitalFilter Coefficient of digital noise filter between Min_Data=0x00 and Max_Data=0x0F. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2CEx_ConfigDigitalFilter(I2C_HandleTypeDef *hi2c, uint32_t DigitalFilter) +{ + uint32_t tmpreg = 0U; + + /* Check the parameters */ + assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance)); + assert_param(IS_I2C_DIGITAL_FILTER(DigitalFilter)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hi2c); + + hi2c->State = HAL_I2C_STATE_BUSY; + + /* Disable the selected I2C peripheral */ + __HAL_I2C_DISABLE(hi2c); + + /* Get the old register value */ + tmpreg = hi2c->Instance->CR1; + + /* Reset I2Cx DNF bits [11:8] */ + tmpreg &= ~(I2C_CR1_DNF); + + /* Set I2Cx DNF coefficient */ + tmpreg |= DigitalFilter << 8U; + + /* Store the new register value */ + hi2c->Instance->CR1 = tmpreg; + + __HAL_I2C_ENABLE(hi2c); + + hi2c->State = HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Enable I2C wakeup from Stop mode(s). + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2Cx peripheral. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2CEx_EnableWakeUp(I2C_HandleTypeDef *hi2c) +{ + /* Check the parameters */ + assert_param(IS_I2C_WAKEUP_FROMSTOP_INSTANCE(hi2c->Instance)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hi2c); + + hi2c->State = HAL_I2C_STATE_BUSY; + + /* Disable the selected I2C peripheral */ + __HAL_I2C_DISABLE(hi2c); + + /* Enable wakeup from stop mode */ + hi2c->Instance->CR1 |= I2C_CR1_WUPEN; + + __HAL_I2C_ENABLE(hi2c); + + hi2c->State = HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Disable I2C wakeup from Stop mode(s). + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2Cx peripheral. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2CEx_DisableWakeUp(I2C_HandleTypeDef *hi2c) +{ + /* Check the parameters */ + assert_param(IS_I2C_WAKEUP_FROMSTOP_INSTANCE(hi2c->Instance)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hi2c); + + hi2c->State = HAL_I2C_STATE_BUSY; + + /* Disable the selected I2C peripheral */ + __HAL_I2C_DISABLE(hi2c); + + /* Enable wakeup from stop mode */ + hi2c->Instance->CR1 &= ~(I2C_CR1_WUPEN); + + __HAL_I2C_ENABLE(hi2c); + + hi2c->State = HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Enable the I2C fast mode plus driving capability. + * @param ConfigFastModePlus Selects the pin. + * This parameter can be one of the @ref I2CEx_FastModePlus values + * @note For I2C1, fast mode plus driving capability can be enabled on all selected + * I2C1 pins using I2C_FASTMODEPLUS_I2C1 parameter or independently + * on each one of the following pins PB6, PB7, PB8 and PB9. + * @note For remaining I2C1 pins (PA14, PA15...) fast mode plus driving capability + * can be enabled only by using I2C_FASTMODEPLUS_I2C1 parameter. + * @note For all I2C2 pins fast mode plus driving capability can be enabled + * only by using I2C_FASTMODEPLUS_I2C2 parameter. + * @note For all I2C3 pins fast mode plus driving capability can be enabled + * only by using I2C_FASTMODEPLUS_I2C3 parameter. + * @note For all I2C4 pins fast mode plus driving capability can be enabled + * only by using I2C_FASTMODEPLUS_I2C4 parameter. + * @retval None + */ +void HAL_I2CEx_EnableFastModePlus(uint32_t ConfigFastModePlus) +{ + /* Check the parameter */ + assert_param(IS_I2C_FASTMODEPLUS(ConfigFastModePlus)); + + /* Enable SYSCFG clock */ + __HAL_RCC_SYSCFG_CLK_ENABLE(); + + /* Enable fast mode plus driving capability for selected pin */ + SET_BIT(SYSCFG->CFGR1, (uint32_t)ConfigFastModePlus); +} + +/** + * @brief Disable the I2C fast mode plus driving capability. + * @param ConfigFastModePlus Selects the pin. + * This parameter can be one of the @ref I2CEx_FastModePlus values + * @note For I2C1, fast mode plus driving capability can be disabled on all selected + * I2C1 pins using I2C_FASTMODEPLUS_I2C1 parameter or independently + * on each one of the following pins PB6, PB7, PB8 and PB9. + * @note For remaining I2C1 pins (PA14, PA15...) fast mode plus driving capability + * can be disabled only by using I2C_FASTMODEPLUS_I2C1 parameter. + * @note For all I2C2 pins fast mode plus driving capability can be disabled + * only by using I2C_FASTMODEPLUS_I2C2 parameter. + * @note For all I2C3 pins fast mode plus driving capability can be disabled + * only by using I2C_FASTMODEPLUS_I2C3 parameter. + * @note For all I2C4 pins fast mode plus driving capability can be disabled + * only by using I2C_FASTMODEPLUS_I2C4 parameter. + * @retval None + */ +void HAL_I2CEx_DisableFastModePlus(uint32_t ConfigFastModePlus) +{ + /* Check the parameter */ + assert_param(IS_I2C_FASTMODEPLUS(ConfigFastModePlus)); + + /* Enable SYSCFG clock */ + __HAL_RCC_SYSCFG_CLK_ENABLE(); + + /* Disable fast mode plus driving capability for selected pin */ + CLEAR_BIT(SYSCFG->CFGR1, (uint32_t)ConfigFastModePlus); +} + +/** + * @} + */ + +/** + * @} + */ + +#endif /* HAL_I2C_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pcd.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pcd.c new file mode 100644 index 0000000..de415ad --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pcd.c @@ -0,0 +1,1675 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_pcd.c + * @author MCD Application Team + * @brief PCD HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the USB Peripheral Controller: + * + Initialization and de-initialization functions + * + IO operation functions + * + Peripheral Control functions + * + Peripheral State functions + * + @verbatim + ============================================================================== + ##### How to use this driver ##### + ============================================================================== + [..] + The PCD HAL driver can be used as follows: + + (#) Declare a PCD_HandleTypeDef handle structure, for example: + PCD_HandleTypeDef hpcd; + + (#) Fill parameters of Init structure in HCD handle + + (#) Call HAL_PCD_Init() API to initialize the PCD peripheral (Core, Device core, ...) + + (#) Initialize the PCD low level resources through the HAL_PCD_MspInit() API: + (##) Enable the PCD/USB Low Level interface clock using + (+++) __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); + (##) Initialize the related GPIO clocks + (##) Configure PCD pin-out + (##) Configure PCD NVIC interrupt + + (#)Associate the Upper USB device stack to the HAL PCD Driver: + (##) hpcd.pData = pdev; + + (#)Enable PCD transmission and reception: + (##) HAL_PCD_Start(); + + @endverbatim + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup PCD PCD + * @brief PCD HAL module driver + * @{ + */ + +#ifdef HAL_PCD_MODULE_ENABLED + +#if defined(STM32L432xx) || defined(STM32L433xx) || defined(STM32L442xx) || defined(STM32L443xx) || \ + defined(STM32L452xx) || defined(STM32L462xx) || \ + defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || \ + defined(STM32L496xx) || defined(STM32L4A6xx) || \ + defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** + * USB_OTG_CORE VERSION ID + */ +#define USB_OTG_CORE_ID_310A 0x4F54310A +#define USB_OTG_CORE_ID_320A 0x4F54320A + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup PCD_Private_Macros PCD Private Macros + * @{ + */ +#define PCD_MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define PCD_MAX(a, b) (((a) > (b)) ? (a) : (b)) +/** + * @} + */ + +/* Private functions prototypes ----------------------------------------------*/ +/** @defgroup PCD_Private_Functions PCD Private Functions + * @{ + */ +#if defined (USB_OTG_FS) +static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum); +#endif /* USB_OTG_FS */ +#if defined (USB) +static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd); +#endif /* USB */ +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup PCD_Exported_Functions PCD Exported Functions + * @{ + */ + +/** @defgroup PCD_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions + * +@verbatim + =============================================================================== + ##### Initialization and de-initialization functions ##### + =============================================================================== + [..] This section provides functions allowing to: + +@endverbatim + * @{ + */ + +/** + * @brief Initializes the PCD according to the specified + * parameters in the PCD_InitTypeDef and initialize the associated handle. + * @param hpcd: PCD handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCD_Init(PCD_HandleTypeDef *hpcd) +{ + uint32_t index = 0U; + + /* Check the PCD handle allocation */ + if(hpcd == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_PCD_ALL_INSTANCE(hpcd->Instance)); + + if(hpcd->State == HAL_PCD_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hpcd->Lock = HAL_UNLOCKED; + + /* Init the low level hardware : GPIO, CLOCK, NVIC... */ + HAL_PCD_MspInit(hpcd); + } + + hpcd->State = HAL_PCD_STATE_BUSY; + + /* Disable the Interrupts */ + __HAL_PCD_DISABLE(hpcd); + + /*Init the Core (common init.) */ + USB_CoreInit(hpcd->Instance, hpcd->Init); + + /* Force Device Mode*/ + USB_SetCurrentMode(hpcd->Instance , USB_DEVICE_MODE); + + /* Init endpoints structures */ + for (index = 0; index < hpcd->Init.dev_endpoints ; index++) + { + /* Init ep structure */ + hpcd->IN_ep[index].is_in = 1; + hpcd->IN_ep[index].num = index; + hpcd->IN_ep[index].tx_fifo_num = index; + /* Control until ep is activated */ + hpcd->IN_ep[index].type = EP_TYPE_CTRL; + hpcd->IN_ep[index].maxpacket = 0; + hpcd->IN_ep[index].xfer_buff = 0; + hpcd->IN_ep[index].xfer_len = 0; + } + + for (index = 0; index < 15 ; index++) + { + hpcd->OUT_ep[index].is_in = 0; + hpcd->OUT_ep[index].num = index; + hpcd->IN_ep[index].tx_fifo_num = index; + /* Control until ep is activated */ + hpcd->OUT_ep[index].type = EP_TYPE_CTRL; + hpcd->OUT_ep[index].maxpacket = 0; + hpcd->OUT_ep[index].xfer_buff = 0; + hpcd->OUT_ep[index].xfer_len = 0; + } + + /* Init Device */ + USB_DevInit(hpcd->Instance, hpcd->Init); + + hpcd->USB_Address = 0; + + hpcd->State= HAL_PCD_STATE_READY; + + /* Activate LPM */ + if (hpcd->Init.lpm_enable ==1) + { + HAL_PCDEx_ActivateLPM(hpcd); + } + /* Activate Battery charging */ + if (hpcd->Init.battery_charging_enable ==1) + { + HAL_PCDEx_ActivateBCD(hpcd); + } + USB_DevDisconnect (hpcd->Instance); + return HAL_OK; +} + +/** + * @brief DeInitializes the PCD peripheral. + * @param hpcd: PCD handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCD_DeInit(PCD_HandleTypeDef *hpcd) +{ + /* Check the PCD handle allocation */ + if(hpcd == NULL) + { + return HAL_ERROR; + } + + hpcd->State = HAL_PCD_STATE_BUSY; + + /* Stop Device */ + HAL_PCD_Stop(hpcd); + + /* DeInit the low level hardware */ + HAL_PCD_MspDeInit(hpcd); + + hpcd->State = HAL_PCD_STATE_RESET; + + return HAL_OK; +} + +/** + * @brief Initializes the PCD MSP. + * @param hpcd: PCD handle + * @retval None + */ +__weak void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hpcd); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_PCD_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitializes PCD MSP. + * @param hpcd: PCD handle + * @retval None + */ +__weak void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hpcd); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_PCD_MspDeInit could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup PCD_Exported_Functions_Group2 Input and Output operation functions + * @brief Data transfers functions + * +@verbatim + =============================================================================== + ##### IO operation functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to manage the PCD data + transfers. + +@endverbatim + * @{ + */ + +/** + * @brief Start The USB OTG Device. + * @param hpcd: PCD handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCD_Start(PCD_HandleTypeDef *hpcd) +{ + __HAL_LOCK(hpcd); + USB_DevConnect (hpcd->Instance); + __HAL_PCD_ENABLE(hpcd); + __HAL_UNLOCK(hpcd); + return HAL_OK; +} + +/** + * @brief Stop The USB OTG Device. + * @param hpcd: PCD handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCD_Stop(PCD_HandleTypeDef *hpcd) +{ + __HAL_LOCK(hpcd); + __HAL_PCD_DISABLE(hpcd); + USB_StopDevice(hpcd->Instance); + USB_DevDisconnect (hpcd->Instance); + __HAL_UNLOCK(hpcd); + return HAL_OK; +} +#if defined (USB_OTG_FS) +/** + * @brief Handles PCD interrupt request. + * @param hpcd: PCD handle + * @retval HAL status + */ +void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd) +{ + USB_OTG_GlobalTypeDef *USBx = hpcd->Instance; + uint32_t index = 0U, ep_intr = 0U, epint = 0U, epnum = 0U; + uint32_t fifoemptymsk = 0U, temp = 0U; + USB_OTG_EPTypeDef *ep = NULL; + uint32_t hclk = 80000000; + + /* ensure that we are in device mode */ + if (USB_GetMode(hpcd->Instance) == USB_OTG_MODE_DEVICE) + { + /* avoid spurious interrupt */ + if(__HAL_PCD_IS_INVALID_INTERRUPT(hpcd)) + { + return; + } + + if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_MMIS)) + { + /* incorrect mode, acknowledge the interrupt */ + __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_MMIS); + } + + if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OEPINT)) + { + epnum = 0; + + /* Read in the device interrupt bits */ + ep_intr = USB_ReadDevAllOutEpInterrupt(hpcd->Instance); + + while (ep_intr) + { + if (ep_intr & 0x1) + { + epint = USB_ReadDevOutEPInterrupt(hpcd->Instance, epnum); + + if (( epint & USB_OTG_DOEPINT_XFRC) == USB_OTG_DOEPINT_XFRC) + { + CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_XFRC); + + /* setup/out transaction management for Core ID 310A */ + if (USBx->GSNPSID == USB_OTG_CORE_ID_310A) + { + if (!(USBx_OUTEP(0)->DOEPINT & (0x1 << 15))) + { + if (hpcd->Init.dma_enable == 1) + { + hpcd->OUT_ep[epnum].xfer_count = + hpcd->OUT_ep[epnum].maxpacket - + (USBx_OUTEP(epnum)->DOEPTSIZ & USB_OTG_DOEPTSIZ_XFRSIZ); + + hpcd->OUT_ep[epnum].xfer_buff += + hpcd->OUT_ep[epnum].maxpacket; + } + + HAL_PCD_DataOutStageCallback(hpcd, epnum); + + if (hpcd->Init.dma_enable == 1) + { + if (!epnum && !hpcd->OUT_ep[epnum].xfer_len) + { + /* this is ZLP, so prepare EP0 for next setup */ + USB_EP0_OutStart(hpcd->Instance, 1, (uint8_t *)hpcd->Setup); + } + } + } + + /* Clear the SetPktRcvd flag*/ + USBx_OUTEP(0)->DOEPINT |= (0x1 << 15) | (0x1 << 5); + } + else + { + if (hpcd->Init.dma_enable == 1) + { + hpcd->OUT_ep[epnum].xfer_count = + hpcd->OUT_ep[epnum].maxpacket - + (USBx_OUTEP(epnum)->DOEPTSIZ & USB_OTG_DOEPTSIZ_XFRSIZ); + hpcd->OUT_ep[epnum].xfer_buff += hpcd->OUT_ep[epnum].maxpacket; + } + + HAL_PCD_DataOutStageCallback(hpcd, epnum); + + if (hpcd->Init.dma_enable == 1) + { + if (!epnum && !hpcd->OUT_ep[epnum].xfer_len) + { + /* this is ZLP, so prepare EP0 for next setup */ + USB_EP0_OutStart(hpcd->Instance, 1, (uint8_t *)hpcd->Setup); + } + } + } + } + + if(( epint & USB_OTG_DOEPINT_STUP) == USB_OTG_DOEPINT_STUP) + { + /* Inform the upper layer that a setup packet is available */ + HAL_PCD_SetupStageCallback(hpcd); + CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STUP); + } + + if(( epint & USB_OTG_DOEPINT_OTEPDIS) == USB_OTG_DOEPINT_OTEPDIS) + { + CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPDIS); + } + +#ifdef USB_OTG_DOEPINT_OTEPSPR + /* Clear Status Phase Received interrupt */ + if(( epint & USB_OTG_DOEPINT_OTEPSPR) == USB_OTG_DOEPINT_OTEPSPR) + { + CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPSPR); + } +#endif /* USB_OTG_DOEPINT_OTEPSPR */ + } + epnum++; + ep_intr >>= 1; + } + } + + if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IEPINT)) + { + /* Read in the device interrupt bits */ + ep_intr = USB_ReadDevAllInEpInterrupt(hpcd->Instance); + + epnum = 0; + + while ( ep_intr ) + { + if (ep_intr & 0x1) /* In ITR */ + { + epint = USB_ReadDevInEPInterrupt(hpcd->Instance, epnum); + + if(( epint & USB_OTG_DIEPINT_XFRC) == USB_OTG_DIEPINT_XFRC) + { + fifoemptymsk = 0x1 << epnum; + USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk; + + CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_XFRC); + + if (hpcd->Init.dma_enable == 1) + { + hpcd->IN_ep[epnum].xfer_buff += hpcd->IN_ep[epnum].maxpacket; + } + + HAL_PCD_DataInStageCallback(hpcd, epnum); + + if (hpcd->Init.dma_enable == 1) + { + /* this is ZLP, so prepare EP0 for next setup */ + if((epnum == 0) && (hpcd->IN_ep[epnum].xfer_len == 0)) + { + /* prepare to rx more setup packets */ + USB_EP0_OutStart(hpcd->Instance, 1, (uint8_t *)hpcd->Setup); + } + } + } + if(( epint & USB_OTG_DIEPINT_TOC) == USB_OTG_DIEPINT_TOC) + { + CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_TOC); + } + if(( epint & USB_OTG_DIEPINT_ITTXFE) == USB_OTG_DIEPINT_ITTXFE) + { + CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_ITTXFE); + } + if(( epint & USB_OTG_DIEPINT_INEPNE) == USB_OTG_DIEPINT_INEPNE) + { + CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_INEPNE); + } + if(( epint & USB_OTG_DIEPINT_EPDISD) == USB_OTG_DIEPINT_EPDISD) + { + CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_EPDISD); + } + if(( epint & USB_OTG_DIEPINT_TXFE) == USB_OTG_DIEPINT_TXFE) + { + PCD_WriteEmptyTxFifo(hpcd , epnum); + } + } + epnum++; + ep_intr >>= 1; + } + } + + /* Handle Resume Interrupt */ + if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT)) + { + /* Clear the Remote Wake-up Signaling */ + USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG; + + if(hpcd->LPM_State == LPM_L1) + { + hpcd->LPM_State = LPM_L0; + HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L0_ACTIVE); + } + else + { + HAL_PCD_ResumeCallback(hpcd); + } + + __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT); + } + + /* Handle Suspend Interrupt */ + if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP)) + { + if((USBx_DEVICE->DSTS & USB_OTG_DSTS_SUSPSTS) == USB_OTG_DSTS_SUSPSTS) + { + + HAL_PCD_SuspendCallback(hpcd); + } + __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP); + } + + /* Handle LPM Interrupt */ + if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_LPMINT)) + { + __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_LPMINT); + if( hpcd->LPM_State == LPM_L0) + { + hpcd->LPM_State = LPM_L1; + hpcd->BESL = (hpcd->Instance->GLPMCFG & USB_OTG_GLPMCFG_BESL) >>2 ; + HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L1_ACTIVE); + } + else + { + HAL_PCD_SuspendCallback(hpcd); + } + } + + /* Handle Reset Interrupt */ + if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBRST)) + { + USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG; + USB_FlushTxFifo(hpcd->Instance , 0x10); + + for (index = 0; index < hpcd->Init.dev_endpoints ; index++) + { + USBx_INEP(index)->DIEPINT = 0xFF; + USBx_OUTEP(index)->DOEPINT = 0xFF; + } + USBx_DEVICE->DAINT = 0xFFFFFFFF; + USBx_DEVICE->DAINTMSK |= 0x10001; + + if(hpcd->Init.use_dedicated_ep1) + { + USBx_DEVICE->DOUTEP1MSK |= (USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM | USB_OTG_DOEPMSK_EPDM); + USBx_DEVICE->DINEP1MSK |= (USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM | USB_OTG_DIEPMSK_EPDM); + } + else + { +#ifdef USB_OTG_DOEPINT_OTEPSPR + USBx_DEVICE->DOEPMSK |= (USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM | USB_OTG_DOEPMSK_EPDM | USB_OTG_DOEPMSK_OTEPSPRM); +#else + USBx_DEVICE->DOEPMSK |= (USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM | USB_OTG_DOEPMSK_EPDM); +#endif /* USB_OTG_DOEPINT_OTEPSPR */ + USBx_DEVICE->DIEPMSK |= (USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM | USB_OTG_DIEPMSK_EPDM); + } + + /* Set Default Address to 0 */ + USBx_DEVICE->DCFG &= ~USB_OTG_DCFG_DAD; + + /* setup EP0 to receive SETUP packets */ + USB_EP0_OutStart(hpcd->Instance, hpcd->Init.dma_enable, (uint8_t *)hpcd->Setup); + + __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBRST); + } + + /* Handle Enumeration done Interrupt */ + if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE)) + { + USB_ActivateSetup(hpcd->Instance); + hpcd->Instance->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT; + + hpcd->Init.speed = USB_OTG_SPEED_FULL; + hpcd->Init.ep0_mps = USB_OTG_FS_MAX_PACKET_SIZE ; + + /* The USBTRD is configured according to the tables below, depending on AHB frequency + used by application. In the low AHB frequency range it is used to stretch enough the USB response + time to IN tokens, the USB turnaround time, so to compensate for the longer AHB read access + latency to the Data FIFO */ + + /* Get hclk frequency value */ + hclk = HAL_RCC_GetHCLKFreq(); + + if((hclk >= 14200000)&&(hclk < 15000000)) + { + /* hclk Clock Range between 14.2-15 MHz */ + hpcd->Instance->GUSBCFG |= (uint32_t)((0xF << 10) & USB_OTG_GUSBCFG_TRDT); + } + + else if((hclk >= 15000000)&&(hclk < 16000000)) + { + /* hclk Clock Range between 15-16 MHz */ + hpcd->Instance->GUSBCFG |= (uint32_t)((0xE << 10) & USB_OTG_GUSBCFG_TRDT); + } + + else if((hclk >= 16000000)&&(hclk < 17200000)) + { + /* hclk Clock Range between 16-17.2 MHz */ + hpcd->Instance->GUSBCFG |= (uint32_t)((0xD << 10) & USB_OTG_GUSBCFG_TRDT); + } + + else if((hclk >= 17200000)&&(hclk < 18500000)) + { + /* hclk Clock Range between 17.2-18.5 MHz */ + hpcd->Instance->GUSBCFG |= (uint32_t)((0xC << 10) & USB_OTG_GUSBCFG_TRDT); + } + + else if((hclk >= 18500000)&&(hclk < 20000000)) + { + /* hclk Clock Range between 18.5-20 MHz */ + hpcd->Instance->GUSBCFG |= (uint32_t)((0xB << 10) & USB_OTG_GUSBCFG_TRDT); + } + + else if((hclk >= 20000000)&&(hclk < 21800000)) + { + /* hclk Clock Range between 20-21.8 MHz */ + hpcd->Instance->GUSBCFG |= (uint32_t)((0xA << 10) & USB_OTG_GUSBCFG_TRDT); + } + + else if((hclk >= 21800000)&&(hclk < 24000000)) + { + /* hclk Clock Range between 21.8-24 MHz */ + hpcd->Instance->GUSBCFG |= (uint32_t)((0x9 << 10) & USB_OTG_GUSBCFG_TRDT); + } + + else if((hclk >= 24000000)&&(hclk < 27700000)) + { + /* hclk Clock Range between 24-27.7 MHz */ + hpcd->Instance->GUSBCFG |= (uint32_t)((0x8 << 10) & USB_OTG_GUSBCFG_TRDT); + } + + else if((hclk >= 27700000)&&(hclk < 32000000)) + { + /* hclk Clock Range between 27.7-32 MHz */ + hpcd->Instance->GUSBCFG |= (uint32_t)((0x7 << 10) & USB_OTG_GUSBCFG_TRDT); + } + + else /* if(hclk >= 32000000) */ + { + /* hclk Clock Range between 32-80 MHz */ + hpcd->Instance->GUSBCFG |= (uint32_t)((0x6 << 10) & USB_OTG_GUSBCFG_TRDT); + } + + HAL_PCD_ResetCallback(hpcd); + + __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE); + } + + /* Handle RxQLevel Interrupt */ + if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_RXFLVL)) + { + USB_MASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL); + + temp = USBx->GRXSTSP; + + ep = &hpcd->OUT_ep[temp & USB_OTG_GRXSTSP_EPNUM]; + + if(((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17) == STS_DATA_UPDT) + { + if((temp & USB_OTG_GRXSTSP_BCNT) != 0) + { + USB_ReadPacket(USBx, ep->xfer_buff, (temp & USB_OTG_GRXSTSP_BCNT) >> 4); + ep->xfer_buff += (temp & USB_OTG_GRXSTSP_BCNT) >> 4; + ep->xfer_count += (temp & USB_OTG_GRXSTSP_BCNT) >> 4; + } + } + else if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17) == STS_SETUP_UPDT) + { + USB_ReadPacket(USBx, (uint8_t *)hpcd->Setup, 8); + ep->xfer_count += (temp & USB_OTG_GRXSTSP_BCNT) >> 4; + } + USB_UNMASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL); + } + + /* Handle SOF Interrupt */ + if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SOF)) + { + HAL_PCD_SOFCallback(hpcd); + __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SOF); + } + + /* Handle Incomplete ISO IN Interrupt */ + if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR)) + { + HAL_PCD_ISOINIncompleteCallback(hpcd, epnum); + __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR); + } + + /* Handle Incomplete ISO OUT Interrupt */ + if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT)) + { + HAL_PCD_ISOOUTIncompleteCallback(hpcd, epnum); + __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT); + } + + /* Handle Connection event Interrupt */ + if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT)) + { + HAL_PCD_ConnectCallback(hpcd); + __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT); + } + + /* Handle Disconnection event Interrupt */ + if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OTGINT)) + { + temp = hpcd->Instance->GOTGINT; + + if((temp & USB_OTG_GOTGINT_SEDET) == USB_OTG_GOTGINT_SEDET) + { + HAL_PCD_DisconnectCallback(hpcd); + } + hpcd->Instance->GOTGINT |= temp; + } + } +} + +#endif /* USB_OTG_FS */ + +#if defined (USB) +/** + * @brief This function handles PCD interrupt request. + * @param hpcd: PCD handle + * @retval HAL status + */ +void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd) +{ + uint32_t wInterrupt_Mask = 0; + + if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_CTR)) + { + /* servicing of the endpoint correct transfer interrupt */ + /* clear of the CTR flag into the sub */ + PCD_EP_ISR_Handler(hpcd); + } + + if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_RESET)) + { + __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_RESET); + HAL_PCD_ResetCallback(hpcd); + HAL_PCD_SetAddress(hpcd, 0); + } + + if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_PMAOVR)) + { + __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_PMAOVR); + } + + if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_ERR)) + { + __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_ERR); + } + + if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_WKUP)) + { + + hpcd->Instance->CNTR &= ~(USB_CNTR_LPMODE); + + /*set wInterrupt_Mask global variable*/ + wInterrupt_Mask = USB_CNTR_CTRM | USB_CNTR_WKUPM | USB_CNTR_SUSPM | USB_CNTR_ERRM \ + | USB_CNTR_SOFM | USB_CNTR_ESOFM | USB_CNTR_RESETM; + + /*Set interrupt mask*/ + hpcd->Instance->CNTR = wInterrupt_Mask; + + /* enable L1REQ interrupt */ + if (hpcd->Init.lpm_enable ==1) + { + wInterrupt_Mask |= USB_CNTR_L1REQM; + + /* Enable LPM support and enable ACK answer to LPM request*/ + USB_TypeDef *USBx = hpcd->Instance; + hpcd->lpm_active = ENABLE; + hpcd->LPM_State = LPM_L0; + + USBx->LPMCSR |= (USB_LPMCSR_LMPEN); + USBx->LPMCSR |= (USB_LPMCSR_LPMACK); + } + + if(hpcd->LPM_State == LPM_L1) + { + hpcd->LPM_State = LPM_L0; + HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L0_ACTIVE); + } + + HAL_PCD_ResumeCallback(hpcd); + + __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_WKUP); + } + + if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_SUSP)) + { + /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */ + __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_SUSP); + + /* Force low-power mode in the macrocell */ + hpcd->Instance->CNTR |= USB_CNTR_FSUSP; + hpcd->Instance->CNTR |= USB_CNTR_LPMODE; + + if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_WKUP) == 0) + { + HAL_PCD_SuspendCallback(hpcd); + } + } + + /* Handle LPM Interrupt */ + if(__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_L1REQ)) + { + __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_L1REQ); + if( hpcd->LPM_State == LPM_L0) + { + /* Force suspend and low-power mode before going to L1 state*/ + hpcd->Instance->CNTR |= USB_CNTR_LPMODE; + hpcd->Instance->CNTR |= USB_CNTR_FSUSP; + + hpcd->LPM_State = LPM_L1; + hpcd->BESL = (hpcd->Instance->LPMCSR & USB_LPMCSR_BESL) >>2 ; + HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L1_ACTIVE); + } + else + { + HAL_PCD_SuspendCallback(hpcd); + } + } + + if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_SOF)) + { + __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_SOF); + HAL_PCD_SOFCallback(hpcd); + } + + if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_ESOF)) + { + /* clear ESOF flag in ISTR */ + __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_ESOF); + } +} +#endif /* USB */ + +/** + * @brief Data OUT stage callback. + * @param hpcd: PCD handle + * @param epnum: endpoint number + * @retval None + */ +__weak void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hpcd); + UNUSED(epnum); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_PCD_DataOutStageCallback could be implemented in the user file + */ +} + +/** + * @brief Data IN stage callback. + * @param hpcd: PCD handle + * @param epnum: endpoint number + * @retval None + */ +__weak void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hpcd); + UNUSED(epnum); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_PCD_DataInStageCallback could be implemented in the user file + */ +} +/** + * @brief Setup stage callback. + * @param hpcd: PCD handle + * @retval None + */ +__weak void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hpcd); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_PCD_SetupStageCallback could be implemented in the user file + */ +} + +/** + * @brief USB Start Of Frame callback. + * @param hpcd: PCD handle + * @retval None + */ +__weak void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hpcd); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_PCD_SOFCallback could be implemented in the user file + */ +} + +/** + * @brief USB Reset callback. + * @param hpcd: PCD handle + * @retval None + */ +__weak void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hpcd); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_PCD_ResetCallback could be implemented in the user file + */ +} + +/** + * @brief Suspend event callback. + * @param hpcd: PCD handle + * @retval None + */ +__weak void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hpcd); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_PCD_SuspendCallback could be implemented in the user file + */ +} + +/** + * @brief Resume event callback. + * @param hpcd: PCD handle + * @retval None + */ +__weak void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hpcd); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_PCD_ResumeCallback could be implemented in the user file + */ +} + +/** + * @brief Incomplete ISO OUT callback. + * @param hpcd: PCD handle + * @param epnum: endpoint number + * @retval None + */ +__weak void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hpcd); + UNUSED(epnum); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_PCD_ISOOUTIncompleteCallback could be implemented in the user file + */ +} + +/** + * @brief Incomplete ISO IN callback. + * @param hpcd: PCD handle + * @param epnum: endpoint number + * @retval None + */ +__weak void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hpcd); + UNUSED(epnum); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_PCD_ISOINIncompleteCallback could be implemented in the user file + */ +} + +/** + * @brief Connection event callback. + * @param hpcd: PCD handle + * @retval None + */ +__weak void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hpcd); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_PCD_ConnectCallback could be implemented in the user file + */ +} + +/** + * @brief Disconnection event callback. + * @param hpcd: PCD handle + * @retval None + */ +__weak void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hpcd); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_PCD_DisconnectCallback could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup PCD_Exported_Functions_Group3 Peripheral Control functions + * @brief management functions + * +@verbatim + =============================================================================== + ##### Peripheral Control functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to control the PCD data + transfers. + +@endverbatim + * @{ + */ + +/** + * @brief Connect the USB device. + * @param hpcd: PCD handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCD_DevConnect(PCD_HandleTypeDef *hpcd) +{ + __HAL_LOCK(hpcd); + USB_DevConnect(hpcd->Instance); + __HAL_UNLOCK(hpcd); + return HAL_OK; +} + +/** + * @brief Disconnect the USB device. + * @param hpcd: PCD handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCD_DevDisconnect(PCD_HandleTypeDef *hpcd) +{ + __HAL_LOCK(hpcd); + USB_DevDisconnect(hpcd->Instance); + __HAL_UNLOCK(hpcd); + return HAL_OK; +} + +/** + * @brief Set the USB Device address. + * @param hpcd: PCD handle + * @param address: new device address + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCD_SetAddress(PCD_HandleTypeDef *hpcd, uint8_t address) +{ + __HAL_LOCK(hpcd); + hpcd->USB_Address = address; + USB_SetDevAddress(hpcd->Instance, address); + __HAL_UNLOCK(hpcd); + return HAL_OK; +} +/** + * @brief Open and configure an endpoint. + * @param hpcd: PCD handle + * @param ep_addr: endpoint address + * @param ep_mps: endpoint max packet size + * @param ep_type: endpoint type + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCD_EP_Open(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint16_t ep_mps, uint8_t ep_type) +{ + HAL_StatusTypeDef ret = HAL_OK; + PCD_EPTypeDef *ep = NULL; + + if ((ep_addr & 0x80) == 0x80) + { + ep = &hpcd->IN_ep[ep_addr & 0x7F]; + } + else + { + ep = &hpcd->OUT_ep[ep_addr & 0x7F]; + } + ep->num = ep_addr & 0x7F; + + ep->is_in = (0x80 & ep_addr) != 0; + ep->maxpacket = ep_mps; + ep->type = ep_type; + + __HAL_LOCK(hpcd); + USB_ActivateEndpoint(hpcd->Instance , ep); + __HAL_UNLOCK(hpcd); + return ret; + +} + + +/** + * @brief Deactivate an endpoint. + * @param hpcd: PCD handle + * @param ep_addr: endpoint address + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCD_EP_Close(PCD_HandleTypeDef *hpcd, uint8_t ep_addr) +{ + PCD_EPTypeDef *ep = NULL; + + if ((ep_addr & 0x80) == 0x80) + { + ep = &hpcd->IN_ep[ep_addr & 0x7F]; + } + else + { + ep = &hpcd->OUT_ep[ep_addr & 0x7F]; + } + ep->num = ep_addr & 0x7F; + + ep->is_in = (0x80 & ep_addr) != 0; + + __HAL_LOCK(hpcd); + USB_DeactivateEndpoint(hpcd->Instance , ep); + __HAL_UNLOCK(hpcd); + return HAL_OK; +} + + +/** + * @brief Receive an amount of data. + * @param hpcd: PCD handle + * @param ep_addr: endpoint address + * @param pBuf: pointer to the reception buffer + * @param len: amount of data to be received + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCD_EP_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len) +{ + PCD_EPTypeDef *ep = NULL; + + ep = &hpcd->OUT_ep[ep_addr & 0x7F]; + + /*setup and start the Xfer */ + ep->xfer_buff = pBuf; + ep->xfer_len = len; + ep->xfer_count = 0; + ep->is_in = 0; + ep->num = ep_addr & 0x7F; + + if ((ep_addr & 0x7F) == 0 ) + { + USB_EP0StartXfer(hpcd->Instance, ep, hpcd->Init.dma_enable); + } + else + { + USB_EPStartXfer(hpcd->Instance, ep, hpcd->Init.dma_enable); + } + + return HAL_OK; +} + +/** + * @brief Get Received Data Size. + * @param hpcd: PCD handle + * @param ep_addr: endpoint address + * @retval Data Size + */ +uint16_t HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef *hpcd, uint8_t ep_addr) +{ + return hpcd->OUT_ep[ep_addr & 0x7F].xfer_count; +} +/** + * @brief Send an amount of data. + * @param hpcd: PCD handle + * @param ep_addr: endpoint address + * @param pBuf: pointer to the transmission buffer + * @param len: amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCD_EP_Transmit(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len) +{ + PCD_EPTypeDef *ep = NULL; + + ep = &hpcd->IN_ep[ep_addr & 0x7F]; + + /*setup and start the Xfer */ + ep->xfer_buff = pBuf; + ep->xfer_len = len; + ep->xfer_count = 0; + ep->is_in = 1; + ep->num = ep_addr & 0x7F; + + if ((ep_addr & 0x7F) == 0 ) + { + USB_EP0StartXfer(hpcd->Instance,ep, hpcd->Init.dma_enable); + } + else + { + USB_EPStartXfer(hpcd->Instance, ep, hpcd->Init.dma_enable); + } + + return HAL_OK; +} + +/** + * @brief Set a STALL condition over an endpoint. + * @param hpcd: PCD handle + * @param ep_addr: endpoint address + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCD_EP_SetStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr) +{ + PCD_EPTypeDef *ep = NULL; + + if ((0x80 & ep_addr) == 0x80) + { + ep = &hpcd->IN_ep[ep_addr & 0x7F]; + } + else + { + ep = &hpcd->OUT_ep[ep_addr]; + } + + ep->is_stall = 1; + ep->num = ep_addr & 0x7F; + ep->is_in = ((ep_addr & 0x80) == 0x80); + + __HAL_LOCK(hpcd); + USB_EPSetStall(hpcd->Instance , ep); + if((ep_addr & 0x7F) == 0) + { + USB_EP0_OutStart(hpcd->Instance, hpcd->Init.dma_enable, (uint8_t *)hpcd->Setup); + } + __HAL_UNLOCK(hpcd); + + return HAL_OK; +} + +/** + * @brief Clear a STALL condition over in an endpoint. + * @param hpcd: PCD handle + * @param ep_addr: endpoint address + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCD_EP_ClrStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr) +{ + PCD_EPTypeDef *ep = NULL; + + if ((0x80 & ep_addr) == 0x80) + { + ep = &hpcd->IN_ep[ep_addr & 0x7F]; + } + else + { + ep = &hpcd->OUT_ep[ep_addr]; + } + + ep->is_stall = 0; + ep->num = ep_addr & 0x7F; + ep->is_in = ((ep_addr & 0x80) == 0x80); + + __HAL_LOCK(hpcd); + USB_EPClearStall(hpcd->Instance , ep); + __HAL_UNLOCK(hpcd); + + return HAL_OK; +} + +/** + * @brief Flush an endpoint. + * @param hpcd: PCD handle + * @param ep_addr: endpoint address + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCD_EP_Flush(PCD_HandleTypeDef *hpcd, uint8_t ep_addr) +{ + __HAL_LOCK(hpcd); + + if ((ep_addr & 0x80) == 0x80) + { + USB_FlushTxFifo(hpcd->Instance, ep_addr & 0x7F); + } + else + { + USB_FlushRxFifo(hpcd->Instance); + } + + __HAL_UNLOCK(hpcd); + + return HAL_OK; +} + +/** + * @brief Activate remote wakeup signalling. + * @param hpcd: PCD handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCD_ActivateRemoteWakeup(PCD_HandleTypeDef *hpcd) +{ + return(USB_ActivateRemoteWakeup(hpcd->Instance)); +} + +/** + * @brief De-activate remote wakeup signalling. + * @param hpcd: PCD handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCD_DeActivateRemoteWakeup(PCD_HandleTypeDef *hpcd) +{ + return(USB_DeActivateRemoteWakeup(hpcd->Instance)); +} +/** + * @} + */ + +/** @defgroup PCD_Exported_Functions_Group4 Peripheral State functions + * @brief Peripheral State functions + * +@verbatim + =============================================================================== + ##### Peripheral State functions ##### + =============================================================================== + [..] + This subsection permits to get in run-time the status of the peripheral + and the data flow. + +@endverbatim + * @{ + */ + +/** + * @brief Return the PCD handle state. + * @param hpcd: PCD handle + * @retval HAL state + */ +PCD_StateTypeDef HAL_PCD_GetState(PCD_HandleTypeDef *hpcd) +{ + return hpcd->State; +} +/** + * @} + */ + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ +/** @addtogroup PCD_Private_Functions + * @{ + */ +#if defined (USB_OTG_FS) +/** + * @brief Check FIFO for the next packet to be loaded. + * @param hpcd: PCD handle + * @param epnum: endpoint number + * @retval HAL status + */ +static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum) +{ + USB_OTG_GlobalTypeDef *USBx = hpcd->Instance; + USB_OTG_EPTypeDef *ep = NULL; + int32_t len = 0U; + uint32_t len32b = 0; + uint32_t fifoemptymsk = 0; + + ep = &hpcd->IN_ep[epnum]; + len = ep->xfer_len - ep->xfer_count; + + if (len > ep->maxpacket) + { + len = ep->maxpacket; + } + + + len32b = (len + 3) / 4; + + while ( (USBx_INEP(epnum)->DTXFSTS & USB_OTG_DTXFSTS_INEPTFSAV) > len32b && + ep->xfer_count < ep->xfer_len && + ep->xfer_len != 0) + { + /* Write the FIFO */ + len = ep->xfer_len - ep->xfer_count; + + if (len > ep->maxpacket) + { + len = ep->maxpacket; + } + len32b = (len + 3) / 4; + + USB_WritePacket(USBx, ep->xfer_buff, epnum, len, hpcd->Init.dma_enable); + + ep->xfer_buff += len; + ep->xfer_count += len; + } + + if(len <= 0) + { + fifoemptymsk = 0x1 << epnum; + USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk; + + } + + return HAL_OK; +} +#endif /* USB_OTG_FS */ + +#if defined (USB) +/** + * @brief This function handles PCD Endpoint interrupt request. + * @param hpcd: PCD handle + * @retval HAL status + */ +static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd) +{ + PCD_EPTypeDef *ep = NULL; + uint16_t count = 0; + uint8_t epindex = 0; + __IO uint16_t wIstr = 0; + __IO uint16_t wEPVal = 0; + + /* stay in loop while pending interrupts */ + while (((wIstr = hpcd->Instance->ISTR) & USB_ISTR_CTR) != 0) + { + /* extract highest priority endpoint number */ + epindex = (uint8_t)(wIstr & USB_ISTR_EP_ID); + + if (epindex == 0) + { + /* Decode and service control endpoint interrupt */ + + /* DIR bit = origin of the interrupt */ + if ((wIstr & USB_ISTR_DIR) == 0) + { + /* DIR = 0 */ + + /* DIR = 0 => IN int */ + /* DIR = 0 implies that (EP_CTR_TX = 1) always */ + PCD_CLEAR_TX_EP_CTR(hpcd->Instance, PCD_ENDP0); + ep = &hpcd->IN_ep[0]; + + ep->xfer_count = PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num); + ep->xfer_buff += ep->xfer_count; + + /* TX COMPLETE */ + HAL_PCD_DataInStageCallback(hpcd, 0); + + + if((hpcd->USB_Address > 0)&& ( ep->xfer_len == 0)) + { + hpcd->Instance->DADDR = (hpcd->USB_Address | USB_DADDR_EF); + hpcd->USB_Address = 0; + } + + } + else + { + /* DIR = 1 */ + + /* DIR = 1 & CTR_RX => SETUP or OUT int */ + /* DIR = 1 & (CTR_TX | CTR_RX) => 2 int pending */ + ep = &hpcd->OUT_ep[0]; + wEPVal = PCD_GET_ENDPOINT(hpcd->Instance, PCD_ENDP0); + + if ((wEPVal & USB_EP_SETUP) != 0) + { + /* Get SETUP Packet*/ + ep->xfer_count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num); + USB_ReadPMA(hpcd->Instance, (uint8_t*)hpcd->Setup ,ep->pmaadress , ep->xfer_count); + /* SETUP bit kept frozen while CTR_RX = 1*/ + PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0); + + /* Process SETUP Packet*/ + HAL_PCD_SetupStageCallback(hpcd); + } + + else if ((wEPVal & USB_EP_CTR_RX) != 0) + { + PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0); + /* Get Control Data OUT Packet*/ + ep->xfer_count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num); + + if (ep->xfer_count != 0) + { + USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, ep->xfer_count); + ep->xfer_buff+=ep->xfer_count; + } + + /* Process Control Data OUT Packet*/ + HAL_PCD_DataOutStageCallback(hpcd, 0); + + PCD_SET_EP_RX_CNT(hpcd->Instance, PCD_ENDP0, ep->maxpacket); + PCD_SET_EP_RX_STATUS(hpcd->Instance, PCD_ENDP0, USB_EP_RX_VALID); + } + } + } + else + { + /* Decode and service non control endpoints interrupt */ + + /* process related endpoint register */ + wEPVal = PCD_GET_ENDPOINT(hpcd->Instance, epindex); + if ((wEPVal & USB_EP_CTR_RX) != 0) + { + /* clear int flag */ + PCD_CLEAR_RX_EP_CTR(hpcd->Instance, epindex); + ep = &hpcd->OUT_ep[epindex]; + + /* OUT double Buffering*/ + if (ep->doublebuffer == 0) + { + count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num); + if (count != 0) + { + USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, count); + } + } + else + { + if (PCD_GET_ENDPOINT(hpcd->Instance, ep->num) & USB_EP_DTOG_RX) + { + /*read from endpoint BUF0Addr buffer*/ + count = PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num); + if (count != 0) + { + USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr0, count); + } + } + else + { + /*read from endpoint BUF1Addr buffer*/ + count = PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num); + if (count != 0) + { + USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr1, count); + } + } + PCD_FreeUserBuffer(hpcd->Instance, ep->num, PCD_EP_DBUF_OUT); + } + /*multi-packet on the NON control OUT endpoint*/ + ep->xfer_count+=count; + ep->xfer_buff+=count; + + if ((ep->xfer_len == 0) || (count < ep->maxpacket)) + { + /* RX COMPLETE */ + HAL_PCD_DataOutStageCallback(hpcd, ep->num); + } + else + { + HAL_PCD_EP_Receive(hpcd, ep->num, ep->xfer_buff, ep->xfer_len); + } + + } /* if((wEPVal & EP_CTR_RX) */ + + if ((wEPVal & USB_EP_CTR_TX) != 0) + { + ep = &hpcd->IN_ep[epindex]; + + /* clear int flag */ + PCD_CLEAR_TX_EP_CTR(hpcd->Instance, epindex); + + /* IN double Buffering*/ + if (ep->doublebuffer == 0) + { + ep->xfer_count = PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num); + if (ep->xfer_count != 0) + { + USB_WritePMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, ep->xfer_count); + } + } + else + { + if (PCD_GET_ENDPOINT(hpcd->Instance, ep->num) & USB_EP_DTOG_TX) + { + /*read from endpoint BUF0Addr buffer*/ + ep->xfer_count = PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num); + if (ep->xfer_count != 0) + { + USB_WritePMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr0, ep->xfer_count); + } + } + else + { + /*read from endpoint BUF1Addr buffer*/ + ep->xfer_count = PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num); + if (ep->xfer_count != 0) + { + USB_WritePMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr1, ep->xfer_count); + } + } + PCD_FreeUserBuffer(hpcd->Instance, ep->num, PCD_EP_DBUF_IN); + } + /*multi-packet on the NON control IN endpoint*/ + ep->xfer_count = PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num); + ep->xfer_buff+=ep->xfer_count; + + /* Zero Length Packet? */ + if (ep->xfer_len == 0) + { + /* TX COMPLETE */ + HAL_PCD_DataInStageCallback(hpcd, ep->num); + } + else + { + HAL_PCD_EP_Transmit(hpcd, ep->num, ep->xfer_buff, ep->xfer_len); + } + } + } + } + return HAL_OK; +} +#endif /* USB */ + +/** + * @} + */ + +#endif /* STM32L432xx || STM32L433xx || STM32L442xx || STM32L443xx || */ + /* STM32L452xx || STM32L462xx || */ + /* STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx || */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#endif /* HAL_PCD_MODULE_ENABLED */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pcd_ex.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pcd_ex.c new file mode 100644 index 0000000..80fc7f9 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pcd_ex.c @@ -0,0 +1,523 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_pcd_ex.c + * @author MCD Application Team + * @brief PCD Extended HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the USB Peripheral Controller: + * + Extended features functions + * + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup PCDEx PCDEx + * @brief PCD Extended HAL module driver + * @{ + */ + +#ifdef HAL_PCD_MODULE_ENABLED + +#if defined(STM32L432xx) || defined(STM32L433xx) || defined(STM32L442xx) || defined(STM32L443xx) || \ + defined(STM32L452xx) || defined(STM32L462xx) || \ + defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || \ + defined(STM32L496xx) || defined(STM32L4A6xx) || \ + defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup PCDEx_Exported_Functions PCDEx Exported Functions + * @{ + */ + +/** @defgroup PCDEx_Exported_Functions_Group1 Peripheral Control functions + * @brief PCDEx control functions + * +@verbatim + =============================================================================== + ##### Extended features functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Update FIFO configuration + +@endverbatim + * @{ + */ +#if defined (USB_OTG_FS) +/** + * @brief Set Tx FIFO + * @param hpcd: PCD handle + * @param fifo: The number of Tx fifo + * @param size: Fifo size + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCDEx_SetTxFiFo(PCD_HandleTypeDef *hpcd, uint8_t fifo, uint16_t size) +{ + uint8_t index = 0; + uint32_t Tx_Offset = 0; + + /* TXn min size = 16 words. (n : Transmit FIFO index) + When a TxFIFO is not used, the Configuration should be as follows: + case 1 : n > m and Txn is not used (n,m : Transmit FIFO indexes) + --> Txm can use the space allocated for Txn. + case2 : n < m and Txn is not used (n,m : Transmit FIFO indexes) + --> Txn should be configured with the minimum space of 16 words + The FIFO is used optimally when used TxFIFOs are allocated in the top + of the FIFO.Ex: use EP1 and EP2 as IN instead of EP1 and EP3 as IN ones. + When DMA is used 3n * FIFO locations should be reserved for internal DMA registers */ + + Tx_Offset = hpcd->Instance->GRXFSIZ; + + if(fifo == 0) + { + hpcd->Instance->DIEPTXF0_HNPTXFSIZ = (size << 16) | Tx_Offset; + } + else + { + Tx_Offset += (hpcd->Instance->DIEPTXF0_HNPTXFSIZ) >> 16; + for (index = 0; index < (fifo - 1); index++) + { + Tx_Offset += (hpcd->Instance->DIEPTXF[index] >> 16); + } + + /* Multiply Tx_Size by 2 to get higher performance */ + hpcd->Instance->DIEPTXF[fifo - 1] = (size << 16) | Tx_Offset; + } + + return HAL_OK; +} + +/** + * @brief Set Rx FIFO + * @param hpcd: PCD handle + * @param size: Size of Rx fifo + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCDEx_SetRxFiFo(PCD_HandleTypeDef *hpcd, uint16_t size) +{ + hpcd->Instance->GRXFSIZ = size; + + return HAL_OK; +} + +/** + * @brief Activate LPM feature. + * @param hpcd: PCD handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCDEx_ActivateLPM(PCD_HandleTypeDef *hpcd) +{ + USB_OTG_GlobalTypeDef *USBx = hpcd->Instance; + + hpcd->lpm_active = ENABLE; + hpcd->LPM_State = LPM_L0; + USBx->GINTMSK |= USB_OTG_GINTMSK_LPMINTM; + USBx->GLPMCFG |= (USB_OTG_GLPMCFG_LPMEN | USB_OTG_GLPMCFG_LPMACK | USB_OTG_GLPMCFG_ENBESL); + + return HAL_OK; +} + +/** + * @brief Deactivate LPM feature. + * @param hpcd: PCD handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCDEx_DeActivateLPM(PCD_HandleTypeDef *hpcd) +{ + USB_OTG_GlobalTypeDef *USBx = hpcd->Instance; + + hpcd->lpm_active = DISABLE; + USBx->GINTMSK &= ~USB_OTG_GINTMSK_LPMINTM; + USBx->GLPMCFG &= ~(USB_OTG_GLPMCFG_LPMEN | USB_OTG_GLPMCFG_LPMACK | USB_OTG_GLPMCFG_ENBESL); + + return HAL_OK; +} + +/** + * @brief Handle BatteryCharging Process. + * @param hpcd: PCD handle + * @retval HAL status + */ +void HAL_PCDEx_BCD_VBUSDetect(PCD_HandleTypeDef *hpcd) +{ + USB_OTG_GlobalTypeDef *USBx = hpcd->Instance; + uint32_t tickstart = HAL_GetTick(); + + /* Start BCD When device is connected */ + if (USBx_DEVICE->DCTL & USB_OTG_DCTL_SDIS) + { + /* Enable DCD : Data Contact Detect */ + USBx->GCCFG |= USB_OTG_GCCFG_DCDEN; + + /* Wait Detect flag or a timeout is happen*/ + while ((USBx->GCCFG & USB_OTG_GCCFG_DCDET) == 0) + { + /* Check for the Timeout */ + if((HAL_GetTick() - tickstart ) > 1000) + { + HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_ERROR); + return; + } + } + + /* Right response got */ + HAL_Delay(100); + + /* Check Detect flag*/ + if (USBx->GCCFG & USB_OTG_GCCFG_DCDET) + { + HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_CONTACT_DETECTION); + } + + /*Primary detection: checks if connected to Standard Downstream Port + (without charging capability) */ + USBx->GCCFG &=~ USB_OTG_GCCFG_DCDEN; + USBx->GCCFG |= USB_OTG_GCCFG_PDEN; + HAL_Delay(100); + + if (!(USBx->GCCFG & USB_OTG_GCCFG_PDET)) + { + /* Case of Standard Downstream Port */ + HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_STD_DOWNSTREAM_PORT); + } + else + { + /* start secondary detection to check connection to Charging Downstream + Port or Dedicated Charging Port */ + USBx->GCCFG &=~ USB_OTG_GCCFG_PDEN; + USBx->GCCFG |= USB_OTG_GCCFG_SDEN; + HAL_Delay(100); + + if ((USBx->GCCFG) & USB_OTG_GCCFG_SDET) + { + /* case Dedicated Charging Port */ + HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_DEDICATED_CHARGING_PORT); + } + else + { + /* case Charging Downstream Port */ + HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_CHARGING_DOWNSTREAM_PORT); + } + } + /* Battery Charging capability discovery finished */ + HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_DISCOVERY_COMPLETED); + } +} + +/** + * @brief Activate BatteryCharging feature. + * @param hpcd: PCD handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCDEx_ActivateBCD(PCD_HandleTypeDef *hpcd) +{ + USB_OTG_GlobalTypeDef *USBx = hpcd->Instance; + + hpcd->battery_charging_active = ENABLE; + USBx->GCCFG |= (USB_OTG_GCCFG_BCDEN); + + return HAL_OK; +} + +/** + * @brief Deactivate BatteryCharging feature. + * @param hpcd: PCD handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCDEx_DeActivateBCD(PCD_HandleTypeDef *hpcd) +{ + USB_OTG_GlobalTypeDef *USBx = hpcd->Instance; + hpcd->battery_charging_active = DISABLE; + USBx->GCCFG &= ~(USB_OTG_GCCFG_BCDEN); + return HAL_OK; +} +#endif /* USB_OTG_FS */ + +#if defined (USB) +/** + * @brief Configure PMA for EP + * @param hpcd : Device instance + * @param ep_addr: endpoint address + * @param ep_kind: endpoint Kind + * USB_SNG_BUF: Single Buffer used + * USB_DBL_BUF: Double Buffer used + * @param pmaadress: EP address in The PMA: In case of single buffer endpoint + * this parameter is 16-bit value providing the address + * in PMA allocated to endpoint. + * In case of double buffer endpoint this parameter + * is a 32-bit value providing the endpoint buffer 0 address + * in the LSB part of 32-bit value and endpoint buffer 1 address + * in the MSB part of 32-bit value. + * @retval HAL status + */ + +HAL_StatusTypeDef HAL_PCDEx_PMAConfig(PCD_HandleTypeDef *hpcd, + uint16_t ep_addr, + uint16_t ep_kind, + uint32_t pmaadress) + +{ + PCD_EPTypeDef *ep = NULL; + + /* initialize ep structure*/ + if ((0x80 & ep_addr) == 0x80) + { + ep = &hpcd->IN_ep[ep_addr & 0x7F]; + } + else + { + ep = &hpcd->OUT_ep[ep_addr]; + } + + /* Here we check if the endpoint is single or double Buffer*/ + if (ep_kind == PCD_SNG_BUF) + { + /*Single Buffer*/ + ep->doublebuffer = 0; + /*Configure te PMA*/ + ep->pmaadress = (uint16_t)pmaadress; + } + else /*USB_DBL_BUF*/ + { + /*Double Buffer Endpoint*/ + ep->doublebuffer = 1; + /*Configure the PMA*/ + ep->pmaaddr0 = pmaadress & 0xFFFF; + ep->pmaaddr1 = (pmaadress & 0xFFFF0000) >> 16; + } + + return HAL_OK; +} + +/** + * @brief Activate BatteryCharging feature. + * @param hpcd: PCD handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCDEx_ActivateBCD(PCD_HandleTypeDef *hpcd) +{ + USB_TypeDef *USBx = hpcd->Instance; + hpcd->battery_charging_active = ENABLE; + + USBx->BCDR |= (USB_BCDR_BCDEN); + /* Enable DCD : Data Contact Detect */ + USBx->BCDR |= (USB_BCDR_DCDEN); + + return HAL_OK; +} + +/** + * @brief Deactivate BatteryCharging feature. + * @param hpcd: PCD handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCDEx_DeActivateBCD(PCD_HandleTypeDef *hpcd) +{ + USB_TypeDef *USBx = hpcd->Instance; + hpcd->battery_charging_active = DISABLE; + + USBx->BCDR &= ~(USB_BCDR_BCDEN); + return HAL_OK; +} + +/** + * @brief Handle BatteryCharging Process. + * @param hpcd: PCD handle + * @retval HAL status + */ +void HAL_PCDEx_BCD_VBUSDetect(PCD_HandleTypeDef *hpcd) +{ + USB_TypeDef *USBx = hpcd->Instance; + uint32_t tickstart = HAL_GetTick(); + + /* Wait Detect flag or a timeout is happen*/ + while ((USBx->BCDR & USB_BCDR_DCDET) == 0) + { + /* Check for the Timeout */ + if((HAL_GetTick() - tickstart ) > 1000) + { + HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_ERROR); + return; + } + } + + HAL_Delay(300); + + /* Data Pin Contact ? Check Detect flag */ + if (USBx->BCDR & USB_BCDR_DCDET) + { + HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_CONTACT_DETECTION); + } + /* Primary detection: checks if connected to Standard Downstream Port + (without charging capability) */ + USBx->BCDR &= ~(USB_BCDR_DCDEN); + USBx->BCDR |= (USB_BCDR_PDEN); + HAL_Delay(300); + + /* If Charger detect ? */ + if (USBx->BCDR & USB_BCDR_PDET) + { + /* Start secondary detection to check connection to Charging Downstream + Port or Dedicated Charging Port */ + USBx->BCDR &= ~(USB_BCDR_PDEN); + USBx->BCDR |= (USB_BCDR_SDEN); + HAL_Delay(300); + + /* If CDP ? */ + if (USBx->BCDR & USB_BCDR_SDET) + { + /* Dedicated Downstream Port DCP */ + HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_DEDICATED_CHARGING_PORT); + } + else + { + /* Charging Downstream Port CDP */ + HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_CHARGING_DOWNSTREAM_PORT); + + /* Battery Charging capability discovery finished + Start Enumeration*/ + HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_DISCOVERY_COMPLETED); + } + } + else /* NO */ + { + /* Standard Downstream Port */ + HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_STD_DOWNSTREAM_PORT); + } +} + +/** + * @brief Activate LPM feature. + * @param hpcd: PCD handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCDEx_ActivateLPM(PCD_HandleTypeDef *hpcd) +{ + + USB_TypeDef *USBx = hpcd->Instance; + hpcd->lpm_active = ENABLE; + hpcd->LPM_State = LPM_L0; + + USBx->LPMCSR |= (USB_LPMCSR_LMPEN); + USBx->LPMCSR |= (USB_LPMCSR_LPMACK); + + + return HAL_OK; +} + +/** + * @brief Deactivate LPM feature. + * @param hpcd: PCD handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCDEx_DeActivateLPM(PCD_HandleTypeDef *hpcd) +{ + USB_TypeDef *USBx = hpcd->Instance; + + hpcd->lpm_active = DISABLE; + + USBx->LPMCSR &= ~ (USB_LPMCSR_LMPEN); + USBx->LPMCSR &= ~ (USB_LPMCSR_LPMACK); + + return HAL_OK; +} + +#endif /* USB */ + +/** + * @brief Send LPM message to user layer callback. + * @param hpcd: PCD handle + * @param msg: LPM message + * @retval HAL status + */ +__weak void HAL_PCDEx_LPM_Callback(PCD_HandleTypeDef *hpcd, PCD_LPM_MsgTypeDef msg) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hpcd); + UNUSED(msg); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_PCDEx_LPM_Callback could be implemented in the user file + */ +} + +/** + * @brief Send BatteryCharging message to user layer callback. + * @param hpcd: PCD handle + * @param msg: LPM message + * @retval HAL status + */ +__weak void HAL_PCDEx_BCD_Callback(PCD_HandleTypeDef *hpcd, PCD_BCD_MsgTypeDef msg) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hpcd); + UNUSED(msg); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_PCDEx_BCD_Callback could be implemented in the user file + */ +} + +/** + * @} + */ + +/** + * @} + */ + +#endif /* STM32L432xx || STM32L433xx || STM32L442xx || STM32L443xx || */ + /* STM32L452xx || STM32L462xx || */ + /* STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx || */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#endif /* HAL_PCD_MODULE_ENABLED */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pwr.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pwr.c new file mode 100644 index 0000000..919b992 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pwr.c @@ -0,0 +1,674 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_pwr.c + * @author MCD Application Team + * @brief PWR HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Power Controller (PWR) peripheral: + * + Initialization/de-initialization functions + * + Peripheral Control functions + * + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup PWR PWR + * @brief PWR HAL module driver + * @{ + */ + +#ifdef HAL_PWR_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ + +/** @defgroup PWR_Private_Defines PWR Private Defines + * @{ + */ + +/** @defgroup PWR_PVD_Mode_Mask PWR PVD Mode Mask + * @{ + */ +#define PVD_MODE_IT ((uint32_t)0x00010000) /*!< Mask for interruption yielded by PVD threshold crossing */ +#define PVD_MODE_EVT ((uint32_t)0x00020000) /*!< Mask for event yielded by PVD threshold crossing */ +#define PVD_RISING_EDGE ((uint32_t)0x00000001) /*!< Mask for rising edge set as PVD trigger */ +#define PVD_FALLING_EDGE ((uint32_t)0x00000002) /*!< Mask for falling edge set as PVD trigger */ +/** + * @} + */ + +/** + * @} + */ + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup PWR_Exported_Functions PWR Exported Functions + * @{ + */ + +/** @defgroup PWR_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and de-initialization functions + * +@verbatim + =============================================================================== + ##### Initialization and de-initialization functions ##### + =============================================================================== + [..] + +@endverbatim + * @{ + */ + +/** + * @brief Deinitialize the HAL PWR peripheral registers to their default reset values. + * @retval None + */ +void HAL_PWR_DeInit(void) +{ + __HAL_RCC_PWR_FORCE_RESET(); + __HAL_RCC_PWR_RELEASE_RESET(); +} + +/** + * @brief Enable access to the backup domain + * (RTC registers, RTC backup data registers). + * @note After reset, the backup domain is protected against + * possible unwanted write accesses. + * @note RTCSEL that sets the RTC clock source selection is in the RTC back-up domain. + * In order to set or modify the RTC clock, the backup domain access must be + * disabled. + * @note LSEON bit that switches on and off the LSE crystal belongs as well to the + * back-up domain. + * @retval None + */ +void HAL_PWR_EnableBkUpAccess(void) +{ + SET_BIT(PWR->CR1, PWR_CR1_DBP); +} + +/** + * @brief Disable access to the backup domain + * (RTC registers, RTC backup data registers). + * @retval None + */ +void HAL_PWR_DisableBkUpAccess(void) +{ + CLEAR_BIT(PWR->CR1, PWR_CR1_DBP); +} + + + + +/** + * @} + */ + + + +/** @defgroup PWR_Exported_Functions_Group2 Peripheral Control functions + * @brief Low Power modes configuration functions + * +@verbatim + + =============================================================================== + ##### Peripheral Control functions ##### + =============================================================================== + + [..] + *** PVD configuration *** + ========================= + [..] + (+) The PVD is used to monitor the VDD power supply by comparing it to a + threshold selected by the PVD Level (PLS[2:0] bits in PWR_CR2 register). + + (+) PVDO flag is available to indicate if VDD/VDDA is higher or lower + than the PVD threshold. This event is internally connected to the EXTI + line16 and can generate an interrupt if enabled. This is done through + __HAL_PVD_EXTI_ENABLE_IT() macro. + (+) The PVD is stopped in Standby mode. + + + *** WakeUp pin configuration *** + ================================ + [..] + (+) WakeUp pins are used to wakeup the system from Standby mode or Shutdown mode. + The polarity of these pins can be set to configure event detection on high + level (rising edge) or low level (falling edge). + + + + *** Low Power modes configuration *** + ===================================== + [..] + The devices feature 8 low-power modes: + (+) Low-power Run mode: core and peripherals are running, main regulator off, low power regulator on. + (+) Sleep mode: Cortex-M4 core stopped, peripherals kept running, main and low power regulators on. + (+) Low-power Sleep mode: Cortex-M4 core stopped, peripherals kept running, main regulator off, low power regulator on. + (+) Stop 0 mode: all clocks are stopped except LSI and LSE, main and low power regulators on. + (+) Stop 1 mode: all clocks are stopped except LSI and LSE, main regulator off, low power regulator on. + (+) Stop 2 mode: all clocks are stopped except LSI and LSE, main regulator off, low power regulator on, reduced set of waking up IPs compared to Stop 1 mode. + (+) Standby mode with SRAM2: all clocks are stopped except LSI and LSE, SRAM2 content preserved, main regulator off, low power regulator on. + (+) Standby mode without SRAM2: all clocks are stopped except LSI and LSE, main and low power regulators off. + (+) Shutdown mode: all clocks are stopped except LSE, main and low power regulators off. + + + *** Low-power run mode *** + ========================== + [..] + (+) Entry: (from main run mode) + (++) set LPR bit with HAL_PWREx_EnableLowPowerRunMode() API after having decreased the system clock below 2 MHz. + + (+) Exit: + (++) clear LPR bit then wait for REGLP bit to be reset with HAL_PWREx_DisableLowPowerRunMode() API. Only + then can the system clock frequency be increased above 2 MHz. + + + *** Sleep mode / Low-power sleep mode *** + ========================================= + [..] + (+) Entry: + The Sleep mode / Low-power Sleep mode is entered thru HAL_PWR_EnterSLEEPMode() API + in specifying whether or not the regulator is forced to low-power mode and if exit is interrupt or event-triggered. + (++) PWR_MAINREGULATOR_ON: Sleep mode (regulator in main mode). + (++) PWR_LOWPOWERREGULATOR_ON: Low-power sleep (regulator in low power mode). + In the latter case, the system clock frequency must have been decreased below 2 MHz beforehand. + (++) PWR_SLEEPENTRY_WFI: enter SLEEP mode with WFI instruction + (++) PWR_SLEEPENTRY_WFE: enter SLEEP mode with WFE instruction + + (+) WFI Exit: + (++) Any peripheral interrupt acknowledged by the nested vectored interrupt + controller (NVIC) or any wake-up event. + + (+) WFE Exit: + (++) Any wake-up event such as an EXTI line configured in event mode. + + [..] When exiting the Low-power sleep mode by issuing an interrupt or a wakeup event, + the MCU is in Low-power Run mode. + + *** Stop 0, Stop 1 and Stop 2 modes *** + =============================== + [..] + (+) Entry: + The Stop 0, Stop 1 or Stop 2 modes are entered thru the following API's: + (++) HAL_PWREx_EnterSTOP0Mode() for mode 0 or HAL_PWREx_EnterSTOP1Mode() for mode 1 or for porting reasons HAL_PWR_EnterSTOPMode(). + (++) HAL_PWREx_EnterSTOP2Mode() for mode 2. + (+) Regulator setting (applicable to HAL_PWR_EnterSTOPMode() only): + (++) PWR_MAINREGULATOR_ON + (++) PWR_LOWPOWERREGULATOR_ON + (+) Exit (interrupt or event-triggered, specified when entering STOP mode): + (++) PWR_STOPENTRY_WFI: enter Stop mode with WFI instruction + (++) PWR_STOPENTRY_WFE: enter Stop mode with WFE instruction + + (+) WFI Exit: + (++) Any EXTI Line (Internal or External) configured in Interrupt mode. + (++) Some specific communication peripherals (USART, LPUART, I2C) interrupts + when programmed in wakeup mode. + (+) WFE Exit: + (++) Any EXTI Line (Internal or External) configured in Event mode. + + [..] + When exiting Stop 0 and Stop 1 modes, the MCU is either in Run mode or in Low-power Run mode + depending on the LPR bit setting. + When exiting Stop 2 mode, the MCU is in Run mode. + + *** Standby mode *** + ==================== + [..] + The Standby mode offers two options: + (+) option a) all clocks off except LSI and LSE, RRS bit set (keeps voltage regulator in low power mode). + SRAM and registers contents are lost except for the SRAM2 content, the RTC registers, RTC backup registers + and Standby circuitry. + (+) option b) all clocks off except LSI and LSE, RRS bit cleared (voltage regulator then disabled). + SRAM and register contents are lost except for the RTC registers, RTC backup registers + and Standby circuitry. + + (++) Entry: + (+++) The Standby mode is entered thru HAL_PWR_EnterSTANDBYMode() API. + SRAM1 and register contents are lost except for registers in the Backup domain and + Standby circuitry. SRAM2 content can be preserved if the bit RRS is set in PWR_CR3 register. + To enable this feature, the user can resort to HAL_PWREx_EnableSRAM2ContentRetention() API + to set RRS bit. + + (++) Exit: + (+++) WKUP pin rising edge, RTC alarm or wakeup, tamper event, time-stamp event, + external reset in NRST pin, IWDG reset. + + [..] After waking up from Standby mode, program execution restarts in the same way as after a Reset. + + + *** Shutdown mode *** + ====================== + [..] + In Shutdown mode, + voltage regulator is disabled, all clocks are off except LSE, RRS bit is cleared. + SRAM and registers contents are lost except for backup domain registers. + + (+) Entry: + The Shutdown mode is entered thru HAL_PWREx_EnterSHUTDOWNMode() API. + + (+) Exit: + (++) WKUP pin rising edge, RTC alarm or wakeup, tamper event, time-stamp event, + external reset in NRST pin. + + [..] After waking up from Shutdown mode, program execution restarts in the same way as after a Reset. + + + *** Auto-wakeup (AWU) from low-power mode *** + ============================================= + [..] + The MCU can be woken up from low-power mode by an RTC Alarm event, an RTC + Wakeup event, a tamper event or a time-stamp event, without depending on + an external interrupt (Auto-wakeup mode). + + (+) RTC auto-wakeup (AWU) from the Stop, Standby and Shutdown modes + + + (++) To wake up from the Stop mode with an RTC alarm event, it is necessary to + configure the RTC to generate the RTC alarm using the HAL_RTC_SetAlarm_IT() function. + + (++) To wake up from the Stop mode with an RTC Tamper or time stamp event, it + is necessary to configure the RTC to detect the tamper or time stamp event using the + HAL_RTCEx_SetTimeStamp_IT() or HAL_RTCEx_SetTamper_IT() functions. + + (++) To wake up from the Stop mode with an RTC WakeUp event, it is necessary to + configure the RTC to generate the RTC WakeUp event using the HAL_RTCEx_SetWakeUpTimer_IT() function. + +@endverbatim + * @{ + */ + + + +/** + * @brief Configure the voltage threshold detected by the Power Voltage Detector (PVD). + * @param sConfigPVD: pointer to a PWR_PVDTypeDef structure that contains the PVD + * configuration information. + * @note Refer to the electrical characteristics of your device datasheet for + * more details about the voltage thresholds corresponding to each + * detection level. + * @retval None + */ +HAL_StatusTypeDef HAL_PWR_ConfigPVD(PWR_PVDTypeDef *sConfigPVD) +{ + /* Check the parameters */ + assert_param(IS_PWR_PVD_LEVEL(sConfigPVD->PVDLevel)); + assert_param(IS_PWR_PVD_MODE(sConfigPVD->Mode)); + + /* Set PLS bits according to PVDLevel value */ + MODIFY_REG(PWR->CR2, PWR_CR2_PLS, sConfigPVD->PVDLevel); + + /* Clear any previous config. Keep it clear if no event or IT mode is selected */ + __HAL_PWR_PVD_EXTI_DISABLE_EVENT(); + __HAL_PWR_PVD_EXTI_DISABLE_IT(); + __HAL_PWR_PVD_EXTI_DISABLE_FALLING_EDGE(); + __HAL_PWR_PVD_EXTI_DISABLE_RISING_EDGE(); + + /* Configure interrupt mode */ + if((sConfigPVD->Mode & PVD_MODE_IT) == PVD_MODE_IT) + { + __HAL_PWR_PVD_EXTI_ENABLE_IT(); + } + + /* Configure event mode */ + if((sConfigPVD->Mode & PVD_MODE_EVT) == PVD_MODE_EVT) + { + __HAL_PWR_PVD_EXTI_ENABLE_EVENT(); + } + + /* Configure the edge */ + if((sConfigPVD->Mode & PVD_RISING_EDGE) == PVD_RISING_EDGE) + { + __HAL_PWR_PVD_EXTI_ENABLE_RISING_EDGE(); + } + + if((sConfigPVD->Mode & PVD_FALLING_EDGE) == PVD_FALLING_EDGE) + { + __HAL_PWR_PVD_EXTI_ENABLE_FALLING_EDGE(); + } + + return HAL_OK; +} + + +/** + * @brief Enable the Power Voltage Detector (PVD). + * @retval None + */ +void HAL_PWR_EnablePVD(void) +{ + SET_BIT(PWR->CR2, PWR_CR2_PVDE); +} + +/** + * @brief Disable the Power Voltage Detector (PVD). + * @retval None + */ +void HAL_PWR_DisablePVD(void) +{ + CLEAR_BIT(PWR->CR2, PWR_CR2_PVDE); +} + + + + +/** + * @brief Enable the WakeUp PINx functionality. + * @param WakeUpPinPolarity: Specifies which Wake-Up pin to enable. + * This parameter can be one of the following legacy values which set the default polarity + * i.e. detection on high level (rising edge): + * @arg @ref PWR_WAKEUP_PIN1, PWR_WAKEUP_PIN2, PWR_WAKEUP_PIN3, PWR_WAKEUP_PIN4, PWR_WAKEUP_PIN5 + * + * or one of the following value where the user can explicitly specify the enabled pin and + * the chosen polarity: + * @arg @ref PWR_WAKEUP_PIN1_HIGH or PWR_WAKEUP_PIN1_LOW + * @arg @ref PWR_WAKEUP_PIN2_HIGH or PWR_WAKEUP_PIN2_LOW + * @arg @ref PWR_WAKEUP_PIN3_HIGH or PWR_WAKEUP_PIN3_LOW + * @arg @ref PWR_WAKEUP_PIN4_HIGH or PWR_WAKEUP_PIN4_LOW + * @arg @ref PWR_WAKEUP_PIN5_HIGH or PWR_WAKEUP_PIN5_LOW + * @note PWR_WAKEUP_PINx and PWR_WAKEUP_PINx_HIGH are equivalent. + * @retval None + */ +void HAL_PWR_EnableWakeUpPin(uint32_t WakeUpPinPolarity) +{ + assert_param(IS_PWR_WAKEUP_PIN(WakeUpPinPolarity)); + + /* Specifies the Wake-Up pin polarity for the event detection + (rising or falling edge) */ + MODIFY_REG(PWR->CR4, (PWR_CR3_EWUP & WakeUpPinPolarity), (WakeUpPinPolarity >> PWR_WUP_POLARITY_SHIFT)); + + /* Enable wake-up pin */ + SET_BIT(PWR->CR3, (PWR_CR3_EWUP & WakeUpPinPolarity)); + + +} + +/** + * @brief Disable the WakeUp PINx functionality. + * @param WakeUpPinx: Specifies the Power Wake-Up pin to disable. + * This parameter can be one of the following values: + * @arg @ref PWR_WAKEUP_PIN1, PWR_WAKEUP_PIN2, PWR_WAKEUP_PIN3, PWR_WAKEUP_PIN4, PWR_WAKEUP_PIN5 + * @retval None + */ +void HAL_PWR_DisableWakeUpPin(uint32_t WakeUpPinx) +{ + assert_param(IS_PWR_WAKEUP_PIN(WakeUpPinx)); + + CLEAR_BIT(PWR->CR3, (PWR_CR3_EWUP & WakeUpPinx)); +} + + +/** + * @brief Enter Sleep or Low-power Sleep mode. + * @note In Sleep/Low-power Sleep mode, all I/O pins keep the same state as in Run mode. + * @param Regulator: Specifies the regulator state in Sleep/Low-power Sleep mode. + * This parameter can be one of the following values: + * @arg @ref PWR_MAINREGULATOR_ON Sleep mode (regulator in main mode) + * @arg @ref PWR_LOWPOWERREGULATOR_ON Low-power Sleep mode (regulator in low-power mode) + * @note Low-power Sleep mode is entered from Low-power Run mode. Therefore, if not yet + * in Low-power Run mode before calling HAL_PWR_EnterSLEEPMode() with Regulator set + * to PWR_LOWPOWERREGULATOR_ON, the user can optionally configure the + * Flash in power-down monde in setting the SLEEP_PD bit in FLASH_ACR register. + * Additionally, the clock frequency must be reduced below 2 MHz. + * Setting SLEEP_PD in FLASH_ACR then appropriately reducing the clock frequency must + * be done before calling HAL_PWR_EnterSLEEPMode() API. + * @note When exiting Low-power Sleep mode, the MCU is in Low-power Run mode. To move in + * Run mode, the user must resort to HAL_PWREx_DisableLowPowerRunMode() API. + * @param SLEEPEntry: Specifies if Sleep mode is entered with WFI or WFE instruction. + * This parameter can be one of the following values: + * @arg @ref PWR_SLEEPENTRY_WFI enter Sleep or Low-power Sleep mode with WFI instruction + * @arg @ref PWR_SLEEPENTRY_WFE enter Sleep or Low-power Sleep mode with WFE instruction + * @note When WFI entry is used, tick interrupt have to be disabled if not desired as + * the interrupt wake up source. + * @retval None + */ +void HAL_PWR_EnterSLEEPMode(uint32_t Regulator, uint8_t SLEEPEntry) +{ + /* Check the parameters */ + assert_param(IS_PWR_REGULATOR(Regulator)); + assert_param(IS_PWR_SLEEP_ENTRY(SLEEPEntry)); + + /* Set Regulator parameter */ + if (Regulator == PWR_MAINREGULATOR_ON) + { + /* If in low-power run mode at this point, exit it */ + if (HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_REGLPF)) + { + HAL_PWREx_DisableLowPowerRunMode(); + } + /* Regulator now in main mode. */ + } + else + { + /* If in run mode, first move to low-power run mode. + The system clock frequency must be below 2 MHz at this point. */ + if (HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_REGLPF) == RESET) + { + HAL_PWREx_EnableLowPowerRunMode(); + } + } + + /* Clear SLEEPDEEP bit of Cortex System Control Register */ + CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk)); + + /* Select SLEEP mode entry -------------------------------------------------*/ + if(SLEEPEntry == PWR_SLEEPENTRY_WFI) + { + /* Request Wait For Interrupt */ + __WFI(); + } + else + { + /* Request Wait For Event */ + __SEV(); + __WFE(); + __WFE(); + } + +} + + +/** + * @brief Enter Stop mode + * @note This API is named HAL_PWR_EnterSTOPMode to ensure compatibility with legacy code running + * on devices where only "Stop mode" is mentioned with main or low power regulator ON. + * @note In Stop mode, all I/O pins keep the same state as in Run mode. + * @note All clocks in the VCORE domain are stopped; the PLL, the MSI, + * the HSI and the HSE oscillators are disabled. Some peripherals with the wakeup capability + * (I2Cx, USARTx and LPUART) can switch on the HSI to receive a frame, and switch off the HSI + * after receiving the frame if it is not a wakeup frame. In this case, the HSI clock is propagated + * only to the peripheral requesting it. + * SRAM1, SRAM2 and register contents are preserved. + * The BOR is available. + * The voltage regulator can be configured either in normal (Stop 0) or low-power mode (Stop 1). + * @note When exiting Stop 0 or Stop 1 mode by issuing an interrupt or a wakeup event, + * the HSI RC oscillator is selected as system clock if STOPWUCK bit in RCC_CFGR register + * is set; the MSI oscillator is selected if STOPWUCK is cleared. + * @note When the voltage regulator operates in low power mode (Stop 1), an additional + * startup delay is incurred when waking up. + * By keeping the internal regulator ON during Stop mode (Stop 0), the consumption + * is higher although the startup time is reduced. + * @param Regulator: Specifies the regulator state in Stop mode. + * This parameter can be one of the following values: + * @arg @ref PWR_MAINREGULATOR_ON Stop 0 mode (main regulator ON) + * @arg @ref PWR_LOWPOWERREGULATOR_ON Stop 1 mode (low power regulator ON) + * @param STOPEntry: Specifies Stop 0 or Stop 1 mode is entered with WFI or WFE instruction. + * This parameter can be one of the following values: + * @arg @ref PWR_STOPENTRY_WFI Enter Stop 0 or Stop 1 mode with WFI instruction. + * @arg @ref PWR_STOPENTRY_WFE Enter Stop 0 or Stop 1 mode with WFE instruction. + * @retval None + */ +void HAL_PWR_EnterSTOPMode(uint32_t Regulator, uint8_t STOPEntry) +{ + /* Check the parameters */ + assert_param(IS_PWR_REGULATOR(Regulator)); + + if(Regulator == PWR_LOWPOWERREGULATOR_ON) + { + HAL_PWREx_EnterSTOP1Mode(STOPEntry); + } + else + { + HAL_PWREx_EnterSTOP0Mode(STOPEntry); + } +} + +/** + * @brief Enter Standby mode. + * @note In Standby mode, the PLL, the HSI, the MSI and the HSE oscillators are switched + * off. The voltage regulator is disabled, except when SRAM2 content is preserved + * in which case the regulator is in low-power mode. + * SRAM1 and register contents are lost except for registers in the Backup domain and + * Standby circuitry. SRAM2 content can be preserved if the bit RRS is set in PWR_CR3 register. + * To enable this feature, the user can resort to HAL_PWREx_EnableSRAM2ContentRetention() API + * to set RRS bit. + * The BOR is available. + * @note The I/Os can be configured either with a pull-up or pull-down or can be kept in analog state. + * HAL_PWREx_EnableGPIOPullUp() and HAL_PWREx_EnableGPIOPullDown() respectively enable Pull Up and + * Pull Down state, HAL_PWREx_DisableGPIOPullUp() and HAL_PWREx_DisableGPIOPullDown() disable the + * same. + * These states are effective in Standby mode only if APC bit is set through + * HAL_PWREx_EnablePullUpPullDownConfig() API. + * @retval None + */ +void HAL_PWR_EnterSTANDBYMode(void) +{ + /* Set Stand-by mode */ + MODIFY_REG(PWR->CR1, PWR_CR1_LPMS, PWR_CR1_LPMS_STANDBY); + + /* Set SLEEPDEEP bit of Cortex System Control Register */ + SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk)); + +/* This option is used to ensure that store operations are completed */ +#if defined ( __CC_ARM) + __force_stores(); +#endif + /* Request Wait For Interrupt */ + __WFI(); +} + + + +/** + * @brief Indicate Sleep-On-Exit when returning from Handler mode to Thread mode. + * @note Set SLEEPONEXIT bit of SCR register. When this bit is set, the processor + * re-enters SLEEP mode when an interruption handling is over. + * Setting this bit is useful when the processor is expected to run only on + * interruptions handling. + * @retval None + */ +void HAL_PWR_EnableSleepOnExit(void) +{ + /* Set SLEEPONEXIT bit of Cortex System Control Register */ + SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPONEXIT_Msk)); +} + + +/** + * @brief Disable Sleep-On-Exit feature when returning from Handler mode to Thread mode. + * @note Clear SLEEPONEXIT bit of SCR register. When this bit is set, the processor + * re-enters SLEEP mode when an interruption handling is over. + * @retval None + */ +void HAL_PWR_DisableSleepOnExit(void) +{ + /* Clear SLEEPONEXIT bit of Cortex System Control Register */ + CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPONEXIT_Msk)); +} + + + +/** + * @brief Enable CORTEX M4 SEVONPEND bit. + * @note Set SEVONPEND bit of SCR register. When this bit is set, this causes + * WFE to wake up when an interrupt moves from inactive to pended. + * @retval None + */ +void HAL_PWR_EnableSEVOnPend(void) +{ + /* Set SEVONPEND bit of Cortex System Control Register */ + SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SEVONPEND_Msk)); +} + + +/** + * @brief Disable CORTEX M4 SEVONPEND bit. + * @note Clear SEVONPEND bit of SCR register. When this bit is set, this causes + * WFE to wake up when an interrupt moves from inactive to pended. + * @retval None + */ +void HAL_PWR_DisableSEVOnPend(void) +{ + /* Clear SEVONPEND bit of Cortex System Control Register */ + CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SEVONPEND_Msk)); +} + + + + + +/** + * @brief PWR PVD interrupt callback + * @retval None + */ +__weak void HAL_PWR_PVDCallback(void) +{ + /* NOTE : This function should not be modified; when the callback is needed, + the HAL_PWR_PVDCallback can be implemented in the user file + */ +} + +/** + * @} + */ + +/** + * @} + */ + +#endif /* HAL_PWR_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pwr_ex.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pwr_ex.c new file mode 100644 index 0000000..bdd8960 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_pwr_ex.c @@ -0,0 +1,1399 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_pwr_ex.c + * @author MCD Application Team + * @brief Extended PWR HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Power Controller (PWR) peripheral: + * + Extended Initialization and de-initialization functions + * + Extended Peripheral Control functions + * + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup PWREx PWREx + * @brief PWR Extended HAL module driver + * @{ + */ + +#ifdef HAL_PWR_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ + +#if defined (STM32L431xx) || defined (STM32L432xx) || defined (STM32L433xx) || defined (STM32L442xx) || defined (STM32L443xx) +#define PWR_PORTH_AVAILABLE_PINS ((uint32_t)0x0000000B) /* PH0/PH1/PH3 */ +#elif defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) +#define PWR_PORTH_AVAILABLE_PINS ((uint32_t)0x0000000B) /* PH0/PH1/PH3 */ +#elif defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) +#define PWR_PORTH_AVAILABLE_PINS ((uint32_t)0x00000003) /* PH0/PH1 */ +#elif defined (STM32L496xx) || defined (STM32L4A6xx) || defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define PWR_PORTH_AVAILABLE_PINS ((uint32_t)0x0000FFFF) /* PH0..PH15 */ +#endif + +#if defined (STM32L496xx) || defined (STM32L4A6xx) || defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) +#define PWR_PORTI_AVAILABLE_PINS ((uint32_t)0x00000FFF) /* PI0..PI11 */ +#endif + +/** @defgroup PWR_Extended_Private_Defines PWR Extended Private Defines + * @{ + */ + +/** @defgroup PWREx_PVM_Mode_Mask PWR PVM Mode Mask + * @{ + */ +#define PVM_MODE_IT ((uint32_t)0x00010000) /*!< Mask for interruption yielded by PVM threshold crossing */ +#define PVM_MODE_EVT ((uint32_t)0x00020000) /*!< Mask for event yielded by PVM threshold crossing */ +#define PVM_RISING_EDGE ((uint32_t)0x00000001) /*!< Mask for rising edge set as PVM trigger */ +#define PVM_FALLING_EDGE ((uint32_t)0x00000002) /*!< Mask for falling edge set as PVM trigger */ +/** + * @} + */ + +/** @defgroup PWREx_TimeOut_Value PWR Extended Flag Setting Time Out Value + * @{ + */ +#define PWR_FLAG_SETTING_DELAY_US 50 /*!< Time out value for REGLPF and VOSF flags setting */ +/** + * @} + */ + + + +/** + * @} + */ + + + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup PWREx_Exported_Functions PWR Extended Exported Functions + * @{ + */ + +/** @defgroup PWREx_Exported_Functions_Group1 Extended Peripheral Control functions + * @brief Extended Peripheral Control functions + * +@verbatim + =============================================================================== + ##### Extended Peripheral Initialization and de-initialization functions ##### + =============================================================================== + [..] + +@endverbatim + * @{ + */ + + +/** + * @brief Return Voltage Scaling Range. + * @retval VOS bit field (PWR_REGULATOR_VOLTAGE_RANGE1 or PWR_REGULATOR_VOLTAGE_RANGE2 + * or PWR_REGULATOR_VOLTAGE_SCALE1_BOOST when applicable) + */ +uint32_t HAL_PWREx_GetVoltageRange(void) +{ +#if defined(PWR_CR5_R1MODE) + if (READ_BIT(PWR->CR1, PWR_CR1_VOS) == PWR_REGULATOR_VOLTAGE_SCALE2) + { + return PWR_REGULATOR_VOLTAGE_SCALE2; + } + else if (READ_BIT(PWR->CR5, PWR_CR5_R1MODE) == PWR_CR5_R1MODE) + { + /* PWR_CR5_R1MODE bit set means that Range 1 Boost is disabled */ + return PWR_REGULATOR_VOLTAGE_SCALE1; + } + else + { + return PWR_REGULATOR_VOLTAGE_SCALE1_BOOST; + } +#else + return (PWR->CR1 & PWR_CR1_VOS); +#endif +} + + + +/** + * @brief Configure the main internal regulator output voltage. + * @param VoltageScaling: specifies the regulator output voltage to achieve + * a tradeoff between performance and power consumption. + * This parameter can be one of the following values: + @if STM32L4S9xx + * @arg @ref PWR_REGULATOR_VOLTAGE_SCALE1_BOOST when available, Regulator voltage output range 1 boost mode, + * typical output voltage at 1.2 V, + * system frequency up to 120 MHz. + @endif + * @arg @ref PWR_REGULATOR_VOLTAGE_SCALE1 Regulator voltage output range 1 mode, + * typical output voltage at 1.2 V, + * system frequency up to 80 MHz. + * @arg @ref PWR_REGULATOR_VOLTAGE_SCALE2 Regulator voltage output range 2 mode, + * typical output voltage at 1.0 V, + * system frequency up to 26 MHz. + * @note When moving from Range 1 to Range 2, the system frequency must be decreased to + * a value below 26 MHz before calling HAL_PWREx_ControlVoltageScaling() API. + * When moving from Range 2 to Range 1, the system frequency can be increased to + * a value up to 80 MHz after calling HAL_PWREx_ControlVoltageScaling() API. For + * some devices, the system frequency can be increased up to 120 MHz. + * @note When moving from Range 2 to Range 1, the API waits for VOSF flag to be + * cleared before returning the status. If the flag is not cleared within + * 50 microseconds, HAL_TIMEOUT status is reported. + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_PWREx_ControlVoltageScaling(uint32_t VoltageScaling) +{ + uint32_t wait_loop_index = 0; + + assert_param(IS_PWR_VOLTAGE_SCALING_RANGE(VoltageScaling)); + +#if defined(PWR_CR5_R1MODE) + if (VoltageScaling == PWR_REGULATOR_VOLTAGE_SCALE1_BOOST) + { + /* If current range is range 2 */ + if (READ_BIT(PWR->CR1, PWR_CR1_VOS) == PWR_REGULATOR_VOLTAGE_SCALE2) + { + /* Make sure Range 1 Boost is enabled */ + CLEAR_BIT(PWR->CR5, PWR_CR5_R1MODE); + + /* Set Range 1 */ + MODIFY_REG(PWR->CR1, PWR_CR1_VOS, PWR_REGULATOR_VOLTAGE_SCALE1); + + /* Wait until VOSF is cleared */ + wait_loop_index = (PWR_FLAG_SETTING_DELAY_US * (SystemCoreClock / 1000000)); + while ((wait_loop_index != 0) && (HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_VOSF))) + { + wait_loop_index--; + } + if (HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_VOSF)) + { + return HAL_TIMEOUT; + } + } + /* If current range is range 1 normal or boost mode */ + else + { + /* Enable Range 1 Boost (no issue if bit already reset) */ + CLEAR_BIT(PWR->CR5, PWR_CR5_R1MODE); + } + } + else if (VoltageScaling == PWR_REGULATOR_VOLTAGE_SCALE1) + { + /* If current range is range 2 */ + if (READ_BIT(PWR->CR1, PWR_CR1_VOS) == PWR_REGULATOR_VOLTAGE_SCALE2) + { + /* Make sure Range 1 Boost is disabled */ + SET_BIT(PWR->CR5, PWR_CR5_R1MODE); + + /* Set Range 1 */ + MODIFY_REG(PWR->CR1, PWR_CR1_VOS, PWR_REGULATOR_VOLTAGE_SCALE1); + + /* Wait until VOSF is cleared */ + wait_loop_index = (PWR_FLAG_SETTING_DELAY_US * (SystemCoreClock / 1000000)); + while ((wait_loop_index != 0) && (HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_VOSF))) + { + wait_loop_index--; + } + if (HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_VOSF)) + { + return HAL_TIMEOUT; + } + } + /* If current range is range 1 normal or boost mode */ + else + { + /* Disable Range 1 Boost (no issue if bit already set) */ + SET_BIT(PWR->CR5, PWR_CR5_R1MODE); + } + } + else + { + /* Set Range 2 */ + MODIFY_REG(PWR->CR1, PWR_CR1_VOS, PWR_REGULATOR_VOLTAGE_SCALE2); + /* No need to wait for VOSF to be cleared for this transition */ + /* PWR_CR5_R1MODE bit setting has no effect in Range 2 */ + } + +#else + + /* If Set Range 1 */ + if (VoltageScaling == PWR_REGULATOR_VOLTAGE_SCALE1) + { + if (READ_BIT(PWR->CR1, PWR_CR1_VOS) != PWR_REGULATOR_VOLTAGE_SCALE1) + { + /* Set Range 1 */ + MODIFY_REG(PWR->CR1, PWR_CR1_VOS, PWR_REGULATOR_VOLTAGE_SCALE1); + + /* Wait until VOSF is cleared */ + wait_loop_index = (PWR_FLAG_SETTING_DELAY_US * (SystemCoreClock / 1000000)); + while ((wait_loop_index != 0) && (HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_VOSF))) + { + wait_loop_index--; + } + if (HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_VOSF)) + { + return HAL_TIMEOUT; + } + } + } + else + { + if (READ_BIT(PWR->CR1, PWR_CR1_VOS) != PWR_REGULATOR_VOLTAGE_SCALE2) + { + /* Set Range 2 */ + MODIFY_REG(PWR->CR1, PWR_CR1_VOS, PWR_REGULATOR_VOLTAGE_SCALE2); + /* No need to wait for VOSF to be cleared for this transition */ + } + } +#endif + + return HAL_OK; +} + + +/** + * @brief Enable battery charging. + * When VDD is present, charge the external battery on VBAT thru an internal resistor. + * @param ResistorSelection: specifies the resistor impedance. + * This parameter can be one of the following values: + * @arg @ref PWR_BATTERY_CHARGING_RESISTOR_5 5 kOhms resistor + * @arg @ref PWR_BATTERY_CHARGING_RESISTOR_1_5 1.5 kOhms resistor + * @retval None + */ +void HAL_PWREx_EnableBatteryCharging(uint32_t ResistorSelection) +{ + assert_param(IS_PWR_BATTERY_RESISTOR_SELECT(ResistorSelection)); + + /* Specify resistor selection */ + MODIFY_REG(PWR->CR4, PWR_CR4_VBRS, ResistorSelection); + + /* Enable battery charging */ + SET_BIT(PWR->CR4, PWR_CR4_VBE); +} + + +/** + * @brief Disable battery charging. + * @retval None + */ +void HAL_PWREx_DisableBatteryCharging(void) +{ + CLEAR_BIT(PWR->CR4, PWR_CR4_VBE); +} + + +#if defined(PWR_CR2_USV) +/** + * @brief Enable VDDUSB supply. + * @note Remove VDDUSB electrical and logical isolation, once VDDUSB supply is present. + * @retval None + */ +void HAL_PWREx_EnableVddUSB(void) +{ + SET_BIT(PWR->CR2, PWR_CR2_USV); +} + + +/** + * @brief Disable VDDUSB supply. + * @retval None + */ +void HAL_PWREx_DisableVddUSB(void) +{ + CLEAR_BIT(PWR->CR2, PWR_CR2_USV); +} +#endif /* PWR_CR2_USV */ + +#if defined(PWR_CR2_IOSV) +/** + * @brief Enable VDDIO2 supply. + * @note Remove VDDIO2 electrical and logical isolation, once VDDIO2 supply is present. + * @retval None + */ +void HAL_PWREx_EnableVddIO2(void) +{ + SET_BIT(PWR->CR2, PWR_CR2_IOSV); +} + + +/** + * @brief Disable VDDIO2 supply. + * @retval None + */ +void HAL_PWREx_DisableVddIO2(void) +{ + CLEAR_BIT(PWR->CR2, PWR_CR2_IOSV); +} +#endif /* PWR_CR2_IOSV */ + + +/** + * @brief Enable Internal Wake-up Line. + * @retval None + */ +void HAL_PWREx_EnableInternalWakeUpLine(void) +{ + SET_BIT(PWR->CR3, PWR_CR3_EIWF); +} + + +/** + * @brief Disable Internal Wake-up Line. + * @retval None + */ +void HAL_PWREx_DisableInternalWakeUpLine(void) +{ + CLEAR_BIT(PWR->CR3, PWR_CR3_EIWF); +} + + + +/** + * @brief Enable GPIO pull-up state in Standby and Shutdown modes. + * @note Set the relevant PUy bits of PWR_PUCRx register to configure the I/O in + * pull-up state in Standby and Shutdown modes. + * @note This state is effective in Standby and Shutdown modes only if APC bit + * is set through HAL_PWREx_EnablePullUpPullDownConfig() API. + * @note The configuration is lost when exiting the Shutdown mode due to the + * power-on reset, maintained when exiting the Standby mode. + * @note To avoid any conflict at Standby and Shutdown modes exits, the corresponding + * PDy bit of PWR_PDCRx register is cleared unless it is reserved. + * @note Even if a PUy bit to set is reserved, the other PUy bits entered as input + * parameter at the same time are set. + * @param GPIO: Specify the IO port. This parameter can be PWR_GPIO_A, ..., PWR_GPIO_H + * (or PWR_GPIO_I depending on the devices) to select the GPIO peripheral. + * @param GPIONumber: Specify the I/O pins numbers. + * This parameter can be one of the following values: + * PWR_GPIO_BIT_0, ..., PWR_GPIO_BIT_15 (except for the port where less + * I/O pins are available) or the logical OR of several of them to set + * several bits for a given port in a single API call. + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_PWREx_EnableGPIOPullUp(uint32_t GPIO, uint32_t GPIONumber) +{ + assert_param(IS_PWR_GPIO(GPIO)); + assert_param(IS_PWR_GPIO_BIT_NUMBER(GPIONumber)); + + switch (GPIO) + { + case PWR_GPIO_A: + SET_BIT(PWR->PUCRA, (GPIONumber & (~(PWR_GPIO_BIT_14)))); + CLEAR_BIT(PWR->PDCRA, (GPIONumber & (~(PWR_GPIO_BIT_13|PWR_GPIO_BIT_15)))); + break; + case PWR_GPIO_B: + SET_BIT(PWR->PUCRB, GPIONumber); + CLEAR_BIT(PWR->PDCRB, (GPIONumber & (~(PWR_GPIO_BIT_4)))); + break; + case PWR_GPIO_C: + SET_BIT(PWR->PUCRC, GPIONumber); + CLEAR_BIT(PWR->PDCRC, GPIONumber); + break; +#if defined(GPIOD) + case PWR_GPIO_D: + SET_BIT(PWR->PUCRD, GPIONumber); + CLEAR_BIT(PWR->PDCRD, GPIONumber); + break; +#endif +#if defined(GPIOE) + case PWR_GPIO_E: + SET_BIT(PWR->PUCRE, GPIONumber); + CLEAR_BIT(PWR->PDCRE, GPIONumber); + break; +#endif +#if defined(GPIOF) + case PWR_GPIO_F: + SET_BIT(PWR->PUCRF, GPIONumber); + CLEAR_BIT(PWR->PDCRF, GPIONumber); + break; +#endif +#if defined(GPIOG) + case PWR_GPIO_G: + SET_BIT(PWR->PUCRG, GPIONumber); + CLEAR_BIT(PWR->PDCRG, GPIONumber); + break; +#endif + case PWR_GPIO_H: + SET_BIT(PWR->PUCRH, (GPIONumber & PWR_PORTH_AVAILABLE_PINS)); +#if defined (STM32L496xx) || defined (STM32L4A6xx) + CLEAR_BIT(PWR->PDCRH, ((GPIONumber & PWR_PORTH_AVAILABLE_PINS) & (~(PWR_GPIO_BIT_3)))); +#else + CLEAR_BIT(PWR->PDCRH, (GPIONumber & PWR_PORTH_AVAILABLE_PINS)); +#endif + break; +#if defined(GPIOI) + case PWR_GPIO_I: + SET_BIT(PWR->PUCRI, (GPIONumber & PWR_PORTI_AVAILABLE_PINS)); + CLEAR_BIT(PWR->PDCRI, (GPIONumber & PWR_PORTI_AVAILABLE_PINS)); + break; +#endif + default: + return HAL_ERROR; + } + + return HAL_OK; +} + + +/** + * @brief Disable GPIO pull-up state in Standby mode and Shutdown modes. + * @note Reset the relevant PUy bits of PWR_PUCRx register used to configure the I/O + * in pull-up state in Standby and Shutdown modes. + * @note Even if a PUy bit to reset is reserved, the other PUy bits entered as input + * parameter at the same time are reset. + * @param GPIO: Specifies the IO port. This parameter can be PWR_GPIO_A, ..., PWR_GPIO_H + * (or PWR_GPIO_I depending on the devices) to select the GPIO peripheral. + * @param GPIONumber: Specify the I/O pins numbers. + * This parameter can be one of the following values: + * PWR_GPIO_BIT_0, ..., PWR_GPIO_BIT_15 (except for the port where less + * I/O pins are available) or the logical OR of several of them to reset + * several bits for a given port in a single API call. + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_PWREx_DisableGPIOPullUp(uint32_t GPIO, uint32_t GPIONumber) +{ + assert_param(IS_PWR_GPIO(GPIO)); + assert_param(IS_PWR_GPIO_BIT_NUMBER(GPIONumber)); + + switch (GPIO) + { + case PWR_GPIO_A: + CLEAR_BIT(PWR->PUCRA, (GPIONumber & (~(PWR_GPIO_BIT_14)))); + break; + case PWR_GPIO_B: + CLEAR_BIT(PWR->PUCRB, GPIONumber); + break; + case PWR_GPIO_C: + CLEAR_BIT(PWR->PUCRC, GPIONumber); + break; +#if defined(GPIOD) + case PWR_GPIO_D: + CLEAR_BIT(PWR->PUCRD, GPIONumber); + break; +#endif +#if defined(GPIOE) + case PWR_GPIO_E: + CLEAR_BIT(PWR->PUCRE, GPIONumber); + break; +#endif +#if defined(GPIOF) + case PWR_GPIO_F: + CLEAR_BIT(PWR->PUCRF, GPIONumber); + break; +#endif +#if defined(GPIOG) + case PWR_GPIO_G: + CLEAR_BIT(PWR->PUCRG, GPIONumber); + break; +#endif + case PWR_GPIO_H: + CLEAR_BIT(PWR->PUCRH, (GPIONumber & PWR_PORTH_AVAILABLE_PINS)); + break; +#if defined(GPIOI) + case PWR_GPIO_I: + CLEAR_BIT(PWR->PUCRI, (GPIONumber & PWR_PORTI_AVAILABLE_PINS)); + break; +#endif + default: + return HAL_ERROR; + } + + return HAL_OK; +} + + + +/** + * @brief Enable GPIO pull-down state in Standby and Shutdown modes. + * @note Set the relevant PDy bits of PWR_PDCRx register to configure the I/O in + * pull-down state in Standby and Shutdown modes. + * @note This state is effective in Standby and Shutdown modes only if APC bit + * is set through HAL_PWREx_EnablePullUpPullDownConfig() API. + * @note The configuration is lost when exiting the Shutdown mode due to the + * power-on reset, maintained when exiting the Standby mode. + * @note To avoid any conflict at Standby and Shutdown modes exits, the corresponding + * PUy bit of PWR_PUCRx register is cleared unless it is reserved. + * @note Even if a PDy bit to set is reserved, the other PDy bits entered as input + * parameter at the same time are set. + * @param GPIO: Specify the IO port. This parameter can be PWR_GPIO_A..PWR_GPIO_H + * (or PWR_GPIO_I depending on the devices) to select the GPIO peripheral. + * @param GPIONumber: Specify the I/O pins numbers. + * This parameter can be one of the following values: + * PWR_GPIO_BIT_0, ..., PWR_GPIO_BIT_15 (except for the port where less + * I/O pins are available) or the logical OR of several of them to set + * several bits for a given port in a single API call. + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_PWREx_EnableGPIOPullDown(uint32_t GPIO, uint32_t GPIONumber) +{ + assert_param(IS_PWR_GPIO(GPIO)); + assert_param(IS_PWR_GPIO_BIT_NUMBER(GPIONumber)); + + switch (GPIO) + { + case PWR_GPIO_A: + SET_BIT(PWR->PDCRA, (GPIONumber & (~(PWR_GPIO_BIT_13|PWR_GPIO_BIT_15)))); + CLEAR_BIT(PWR->PUCRA, (GPIONumber & (~(PWR_GPIO_BIT_14)))); + break; + case PWR_GPIO_B: + SET_BIT(PWR->PDCRB, (GPIONumber & (~(PWR_GPIO_BIT_4)))); + CLEAR_BIT(PWR->PUCRB, GPIONumber); + break; + case PWR_GPIO_C: + SET_BIT(PWR->PDCRC, GPIONumber); + CLEAR_BIT(PWR->PUCRC, GPIONumber); + break; +#if defined(GPIOD) + case PWR_GPIO_D: + SET_BIT(PWR->PDCRD, GPIONumber); + CLEAR_BIT(PWR->PUCRD, GPIONumber); + break; +#endif +#if defined(GPIOE) + case PWR_GPIO_E: + SET_BIT(PWR->PDCRE, GPIONumber); + CLEAR_BIT(PWR->PUCRE, GPIONumber); + break; +#endif +#if defined(GPIOF) + case PWR_GPIO_F: + SET_BIT(PWR->PDCRF, GPIONumber); + CLEAR_BIT(PWR->PUCRF, GPIONumber); + break; +#endif +#if defined(GPIOG) + case PWR_GPIO_G: + SET_BIT(PWR->PDCRG, GPIONumber); + CLEAR_BIT(PWR->PUCRG, GPIONumber); + break; +#endif + case PWR_GPIO_H: +#if defined (STM32L496xx) || defined (STM32L4A6xx) + SET_BIT(PWR->PDCRH, ((GPIONumber & PWR_PORTH_AVAILABLE_PINS) & (~(PWR_GPIO_BIT_3)))); +#else + SET_BIT(PWR->PDCRH, (GPIONumber & PWR_PORTH_AVAILABLE_PINS)); +#endif + CLEAR_BIT(PWR->PUCRH, (GPIONumber & PWR_PORTH_AVAILABLE_PINS)); + break; +#if defined(GPIOI) + case PWR_GPIO_I: + SET_BIT(PWR->PDCRI, (GPIONumber & PWR_PORTI_AVAILABLE_PINS)); + CLEAR_BIT(PWR->PUCRI, (GPIONumber & PWR_PORTI_AVAILABLE_PINS)); + break; +#endif + default: + return HAL_ERROR; + } + + return HAL_OK; +} + + +/** + * @brief Disable GPIO pull-down state in Standby and Shutdown modes. + * @note Reset the relevant PDy bits of PWR_PDCRx register used to configure the I/O + * in pull-down state in Standby and Shutdown modes. + * @note Even if a PDy bit to reset is reserved, the other PDy bits entered as input + * parameter at the same time are reset. + * @param GPIO: Specifies the IO port. This parameter can be PWR_GPIO_A..PWR_GPIO_H + * (or PWR_GPIO_I depending on the devices) to select the GPIO peripheral. + * @param GPIONumber: Specify the I/O pins numbers. + * This parameter can be one of the following values: + * PWR_GPIO_BIT_0, ..., PWR_GPIO_BIT_15 (except for the port where less + * I/O pins are available) or the logical OR of several of them to reset + * several bits for a given port in a single API call. + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_PWREx_DisableGPIOPullDown(uint32_t GPIO, uint32_t GPIONumber) +{ + assert_param(IS_PWR_GPIO(GPIO)); + assert_param(IS_PWR_GPIO_BIT_NUMBER(GPIONumber)); + + switch (GPIO) + { + case PWR_GPIO_A: + CLEAR_BIT(PWR->PDCRA, (GPIONumber & (~(PWR_GPIO_BIT_13|PWR_GPIO_BIT_15)))); + break; + case PWR_GPIO_B: + CLEAR_BIT(PWR->PDCRB, (GPIONumber & (~(PWR_GPIO_BIT_4)))); + break; + case PWR_GPIO_C: + CLEAR_BIT(PWR->PDCRC, GPIONumber); + break; +#if defined(GPIOD) + case PWR_GPIO_D: + CLEAR_BIT(PWR->PDCRD, GPIONumber); + break; +#endif +#if defined(GPIOE) + case PWR_GPIO_E: + CLEAR_BIT(PWR->PDCRE, GPIONumber); + break; +#endif +#if defined(GPIOF) + case PWR_GPIO_F: + CLEAR_BIT(PWR->PDCRF, GPIONumber); + break; +#endif +#if defined(GPIOG) + case PWR_GPIO_G: + CLEAR_BIT(PWR->PDCRG, GPIONumber); + break; +#endif + case PWR_GPIO_H: +#if defined (STM32L496xx) || defined (STM32L4A6xx) + CLEAR_BIT(PWR->PDCRH, ((GPIONumber & PWR_PORTH_AVAILABLE_PINS) & (~(PWR_GPIO_BIT_3)))); +#else + CLEAR_BIT(PWR->PDCRH, (GPIONumber & PWR_PORTH_AVAILABLE_PINS)); +#endif + break; +#if defined(GPIOI) + case PWR_GPIO_I: + CLEAR_BIT(PWR->PDCRI, (GPIONumber & PWR_PORTI_AVAILABLE_PINS)); + break; +#endif + default: + return HAL_ERROR; + } + + return HAL_OK; +} + + + +/** + * @brief Enable pull-up and pull-down configuration. + * @note When APC bit is set, the I/O pull-up and pull-down configurations defined in + * PWR_PUCRx and PWR_PDCRx registers are applied in Standby and Shutdown modes. + * @note Pull-up set by PUy bit of PWR_PUCRx register is not activated if the corresponding + * PDy bit of PWR_PDCRx register is also set (pull-down configuration priority is higher). + * HAL_PWREx_EnableGPIOPullUp() and HAL_PWREx_EnableGPIOPullDown() API's ensure there + * is no conflict when setting PUy or PDy bit. + * @retval None + */ +void HAL_PWREx_EnablePullUpPullDownConfig(void) +{ + SET_BIT(PWR->CR3, PWR_CR3_APC); +} + + +/** + * @brief Disable pull-up and pull-down configuration. + * @note When APC bit is cleared, the I/O pull-up and pull-down configurations defined in + * PWR_PUCRx and PWR_PDCRx registers are not applied in Standby and Shutdown modes. + * @retval None + */ +void HAL_PWREx_DisablePullUpPullDownConfig(void) +{ + CLEAR_BIT(PWR->CR3, PWR_CR3_APC); +} + + + +/** + * @brief Enable SRAM2 content retention in Standby mode. + * @note When RRS bit is set, SRAM2 is powered by the low-power regulator in + * Standby mode and its content is kept. + * @retval None + */ +void HAL_PWREx_EnableSRAM2ContentRetention(void) +{ + SET_BIT(PWR->CR3, PWR_CR3_RRS); +} + + +/** + * @brief Disable SRAM2 content retention in Standby mode. + * @note When RRS bit is reset, SRAM2 is powered off in Standby mode + * and its content is lost. + * @retval None + */ +void HAL_PWREx_DisableSRAM2ContentRetention(void) +{ + CLEAR_BIT(PWR->CR3, PWR_CR3_RRS); +} + + +#if defined(PWR_CR1_RRSTP) +/** + * @brief Enable SRAM3 content retention in Stop 2 mode. + * @note When RRSTP bit is set, SRAM3 is powered by the low-power regulator in + * Stop 2 mode and its content is kept. + * @retval None + */ +void HAL_PWREx_EnableSRAM3ContentRetention(void) +{ + SET_BIT(PWR->CR1, PWR_CR1_RRSTP); +} + + +/** + * @brief Disable SRAM3 content retention in Stop 2 mode. + * @note When RRSTP bit is reset, SRAM3 is powered off in Stop 2 mode + * and its content is lost. + * @retval None + */ +void HAL_PWREx_DisableSRAM3ContentRetention(void) +{ + CLEAR_BIT(PWR->CR1, PWR_CR1_RRSTP); +} +#endif /* PWR_CR1_RRSTP */ + +#if defined(PWR_CR3_DSIPDEN) +/** + * @brief Enable pull-down activation on DSI pins. + * @retval None + */ +void HAL_PWREx_EnableDSIPinsPDActivation(void) +{ + SET_BIT(PWR->CR3, PWR_CR3_DSIPDEN); +} + + +/** + * @brief Disable pull-down activation on DSI pins. + * @retval None + */ +void HAL_PWREx_DisableDSIPinsPDActivation(void) +{ + CLEAR_BIT(PWR->CR3, PWR_CR3_DSIPDEN); +} +#endif /* PWR_CR3_DSIPDEN */ + +#if defined(PWR_CR2_PVME1) +/** + * @brief Enable the Power Voltage Monitoring 1: VDDUSB versus 1.2V. + * @retval None + */ +void HAL_PWREx_EnablePVM1(void) +{ + SET_BIT(PWR->CR2, PWR_PVM_1); +} + +/** + * @brief Disable the Power Voltage Monitoring 1: VDDUSB versus 1.2V. + * @retval None + */ +void HAL_PWREx_DisablePVM1(void) +{ + CLEAR_BIT(PWR->CR2, PWR_PVM_1); +} +#endif /* PWR_CR2_PVME1 */ + + +#if defined(PWR_CR2_PVME2) +/** + * @brief Enable the Power Voltage Monitoring 2: VDDIO2 versus 0.9V. + * @retval None + */ +void HAL_PWREx_EnablePVM2(void) +{ + SET_BIT(PWR->CR2, PWR_PVM_2); +} + +/** + * @brief Disable the Power Voltage Monitoring 2: VDDIO2 versus 0.9V. + * @retval None + */ +void HAL_PWREx_DisablePVM2(void) +{ + CLEAR_BIT(PWR->CR2, PWR_PVM_2); +} +#endif /* PWR_CR2_PVME2 */ + + +/** + * @brief Enable the Power Voltage Monitoring 3: VDDA versus 1.62V. + * @retval None + */ +void HAL_PWREx_EnablePVM3(void) +{ + SET_BIT(PWR->CR2, PWR_PVM_3); +} + +/** + * @brief Disable the Power Voltage Monitoring 3: VDDA versus 1.62V. + * @retval None + */ +void HAL_PWREx_DisablePVM3(void) +{ + CLEAR_BIT(PWR->CR2, PWR_PVM_3); +} + + +/** + * @brief Enable the Power Voltage Monitoring 4: VDDA versus 2.2V. + * @retval None + */ +void HAL_PWREx_EnablePVM4(void) +{ + SET_BIT(PWR->CR2, PWR_PVM_4); +} + +/** + * @brief Disable the Power Voltage Monitoring 4: VDDA versus 2.2V. + * @retval None + */ +void HAL_PWREx_DisablePVM4(void) +{ + CLEAR_BIT(PWR->CR2, PWR_PVM_4); +} + + + + +/** + * @brief Configure the Peripheral Voltage Monitoring (PVM). + * @param sConfigPVM: pointer to a PWR_PVMTypeDef structure that contains the + * PVM configuration information. + * @note The API configures a single PVM according to the information contained + * in the input structure. To configure several PVMs, the API must be singly + * called for each PVM used. + * @note Refer to the electrical characteristics of your device datasheet for + * more details about the voltage thresholds corresponding to each + * detection level and to each monitored supply. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PWREx_ConfigPVM(PWR_PVMTypeDef *sConfigPVM) +{ + /* Check the parameters */ + assert_param(IS_PWR_PVM_TYPE(sConfigPVM->PVMType)); + assert_param(IS_PWR_PVM_MODE(sConfigPVM->Mode)); + + + /* Configure EXTI 35 to 38 interrupts if so required: + scan thru PVMType to detect which PVMx is set and + configure the corresponding EXTI line accordingly. */ + switch (sConfigPVM->PVMType) + { +#if defined(PWR_CR2_PVME1) + case PWR_PVM_1: + /* Clear any previous config. Keep it clear if no event or IT mode is selected */ + __HAL_PWR_PVM1_EXTI_DISABLE_EVENT(); + __HAL_PWR_PVM1_EXTI_DISABLE_IT(); + __HAL_PWR_PVM1_EXTI_DISABLE_FALLING_EDGE(); + __HAL_PWR_PVM1_EXTI_DISABLE_RISING_EDGE(); + + /* Configure interrupt mode */ + if((sConfigPVM->Mode & PVM_MODE_IT) == PVM_MODE_IT) + { + __HAL_PWR_PVM1_EXTI_ENABLE_IT(); + } + + /* Configure event mode */ + if((sConfigPVM->Mode & PVM_MODE_EVT) == PVM_MODE_EVT) + { + __HAL_PWR_PVM1_EXTI_ENABLE_EVENT(); + } + + /* Configure the edge */ + if((sConfigPVM->Mode & PVM_RISING_EDGE) == PVM_RISING_EDGE) + { + __HAL_PWR_PVM1_EXTI_ENABLE_RISING_EDGE(); + } + + if((sConfigPVM->Mode & PVM_FALLING_EDGE) == PVM_FALLING_EDGE) + { + __HAL_PWR_PVM1_EXTI_ENABLE_FALLING_EDGE(); + } + break; +#endif /* PWR_CR2_PVME1 */ + +#if defined(PWR_CR2_PVME2) + case PWR_PVM_2: + /* Clear any previous config. Keep it clear if no event or IT mode is selected */ + __HAL_PWR_PVM2_EXTI_DISABLE_EVENT(); + __HAL_PWR_PVM2_EXTI_DISABLE_IT(); + __HAL_PWR_PVM2_EXTI_DISABLE_FALLING_EDGE(); + __HAL_PWR_PVM2_EXTI_DISABLE_RISING_EDGE(); + + /* Configure interrupt mode */ + if((sConfigPVM->Mode & PVM_MODE_IT) == PVM_MODE_IT) + { + __HAL_PWR_PVM2_EXTI_ENABLE_IT(); + } + + /* Configure event mode */ + if((sConfigPVM->Mode & PVM_MODE_EVT) == PVM_MODE_EVT) + { + __HAL_PWR_PVM2_EXTI_ENABLE_EVENT(); + } + + /* Configure the edge */ + if((sConfigPVM->Mode & PVM_RISING_EDGE) == PVM_RISING_EDGE) + { + __HAL_PWR_PVM2_EXTI_ENABLE_RISING_EDGE(); + } + + if((sConfigPVM->Mode & PVM_FALLING_EDGE) == PVM_FALLING_EDGE) + { + __HAL_PWR_PVM2_EXTI_ENABLE_FALLING_EDGE(); + } + break; +#endif /* PWR_CR2_PVME2 */ + + case PWR_PVM_3: + /* Clear any previous config. Keep it clear if no event or IT mode is selected */ + __HAL_PWR_PVM3_EXTI_DISABLE_EVENT(); + __HAL_PWR_PVM3_EXTI_DISABLE_IT(); + __HAL_PWR_PVM3_EXTI_DISABLE_FALLING_EDGE(); + __HAL_PWR_PVM3_EXTI_DISABLE_RISING_EDGE(); + + /* Configure interrupt mode */ + if((sConfigPVM->Mode & PVM_MODE_IT) == PVM_MODE_IT) + { + __HAL_PWR_PVM3_EXTI_ENABLE_IT(); + } + + /* Configure event mode */ + if((sConfigPVM->Mode & PVM_MODE_EVT) == PVM_MODE_EVT) + { + __HAL_PWR_PVM3_EXTI_ENABLE_EVENT(); + } + + /* Configure the edge */ + if((sConfigPVM->Mode & PVM_RISING_EDGE) == PVM_RISING_EDGE) + { + __HAL_PWR_PVM3_EXTI_ENABLE_RISING_EDGE(); + } + + if((sConfigPVM->Mode & PVM_FALLING_EDGE) == PVM_FALLING_EDGE) + { + __HAL_PWR_PVM3_EXTI_ENABLE_FALLING_EDGE(); + } + break; + + case PWR_PVM_4: + /* Clear any previous config. Keep it clear if no event or IT mode is selected */ + __HAL_PWR_PVM4_EXTI_DISABLE_EVENT(); + __HAL_PWR_PVM4_EXTI_DISABLE_IT(); + __HAL_PWR_PVM4_EXTI_DISABLE_FALLING_EDGE(); + __HAL_PWR_PVM4_EXTI_DISABLE_RISING_EDGE(); + + /* Configure interrupt mode */ + if((sConfigPVM->Mode & PVM_MODE_IT) == PVM_MODE_IT) + { + __HAL_PWR_PVM4_EXTI_ENABLE_IT(); + } + + /* Configure event mode */ + if((sConfigPVM->Mode & PVM_MODE_EVT) == PVM_MODE_EVT) + { + __HAL_PWR_PVM4_EXTI_ENABLE_EVENT(); + } + + /* Configure the edge */ + if((sConfigPVM->Mode & PVM_RISING_EDGE) == PVM_RISING_EDGE) + { + __HAL_PWR_PVM4_EXTI_ENABLE_RISING_EDGE(); + } + + if((sConfigPVM->Mode & PVM_FALLING_EDGE) == PVM_FALLING_EDGE) + { + __HAL_PWR_PVM4_EXTI_ENABLE_FALLING_EDGE(); + } + break; + + default: + return HAL_ERROR; + + } + + + return HAL_OK; +} + + + +/** + * @brief Enter Low-power Run mode + * @note In Low-power Run mode, all I/O pins keep the same state as in Run mode. + * @note When Regulator is set to PWR_LOWPOWERREGULATOR_ON, the user can optionally configure the + * Flash in power-down monde in setting the RUN_PD bit in FLASH_ACR register. + * Additionally, the clock frequency must be reduced below 2 MHz. + * Setting RUN_PD in FLASH_ACR then appropriately reducing the clock frequency must + * be done before calling HAL_PWREx_EnableLowPowerRunMode() API. + * @retval None + */ +void HAL_PWREx_EnableLowPowerRunMode(void) +{ + /* Set Regulator parameter */ + SET_BIT(PWR->CR1, PWR_CR1_LPR); +} + + +/** + * @brief Exit Low-power Run mode. + * @note Before HAL_PWREx_DisableLowPowerRunMode() completion, the function checks that + * REGLPF has been properly reset (otherwise, HAL_PWREx_DisableLowPowerRunMode + * returns HAL_TIMEOUT status). The system clock frequency can then be + * increased above 2 MHz. + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_PWREx_DisableLowPowerRunMode(void) +{ + uint32_t wait_loop_index = 0; + + /* Clear LPR bit */ + CLEAR_BIT(PWR->CR1, PWR_CR1_LPR); + + /* Wait until REGLPF is reset */ + wait_loop_index = (PWR_FLAG_SETTING_DELAY_US * (SystemCoreClock / 1000000)); + while ((wait_loop_index != 0) && (HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_REGLPF))) + { + wait_loop_index--; + } + if (HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_REGLPF)) + { + return HAL_TIMEOUT; + } + + return HAL_OK; +} + + +/** + * @brief Enter Stop 0 mode. + * @note In Stop 0 mode, main and low voltage regulators are ON. + * @note In Stop 0 mode, all I/O pins keep the same state as in Run mode. + * @note All clocks in the VCORE domain are stopped; the PLL, the MSI, + * the HSI and the HSE oscillators are disabled. Some peripherals with the wakeup capability + * (I2Cx, USARTx and LPUART) can switch on the HSI to receive a frame, and switch off the HSI + * after receiving the frame if it is not a wakeup frame. In this case, the HSI clock is propagated + * only to the peripheral requesting it. + * SRAM1, SRAM2 and register contents are preserved. + * The BOR is available. + * @note When exiting Stop 0 mode by issuing an interrupt or a wakeup event, + * the HSI RC oscillator is selected as system clock if STOPWUCK bit in RCC_CFGR register + * is set; the MSI oscillator is selected if STOPWUCK is cleared. + * @note By keeping the internal regulator ON during Stop 0 mode, the consumption + * is higher although the startup time is reduced. + * @param STOPEntry specifies if Stop mode in entered with WFI or WFE instruction. + * This parameter can be one of the following values: + * @arg @ref PWR_STOPENTRY_WFI Enter Stop mode with WFI instruction + * @arg @ref PWR_STOPENTRY_WFE Enter Stop mode with WFE instruction + * @retval None + */ +void HAL_PWREx_EnterSTOP0Mode(uint8_t STOPEntry) +{ + /* Check the parameters */ + assert_param(IS_PWR_STOP_ENTRY(STOPEntry)); + + /* Stop 0 mode with Main Regulator */ + MODIFY_REG(PWR->CR1, PWR_CR1_LPMS, PWR_CR1_LPMS_STOP0); + + /* Set SLEEPDEEP bit of Cortex System Control Register */ + SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk)); + + /* Select Stop mode entry --------------------------------------------------*/ + if(STOPEntry == PWR_STOPENTRY_WFI) + { + /* Request Wait For Interrupt */ + __WFI(); + } + else + { + /* Request Wait For Event */ + __SEV(); + __WFE(); + __WFE(); + } + + /* Reset SLEEPDEEP bit of Cortex System Control Register */ + CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk)); +} + + +/** + * @brief Enter Stop 1 mode. + * @note In Stop 1 mode, only low power voltage regulator is ON. + * @note In Stop 1 mode, all I/O pins keep the same state as in Run mode. + * @note All clocks in the VCORE domain are stopped; the PLL, the MSI, + * the HSI and the HSE oscillators are disabled. Some peripherals with the wakeup capability + * (I2Cx, USARTx and LPUART) can switch on the HSI to receive a frame, and switch off the HSI + * after receiving the frame if it is not a wakeup frame. In this case, the HSI clock is propagated + * only to the peripheral requesting it. + * SRAM1, SRAM2 and register contents are preserved. + * The BOR is available. + * @note When exiting Stop 1 mode by issuing an interrupt or a wakeup event, + * the HSI RC oscillator is selected as system clock if STOPWUCK bit in RCC_CFGR register + * is set; the MSI oscillator is selected if STOPWUCK is cleared. + * @note Due to low power mode, an additional startup delay is incurred when waking up from Stop 1 mode. + * @param STOPEntry specifies if Stop mode in entered with WFI or WFE instruction. + * This parameter can be one of the following values: + * @arg @ref PWR_STOPENTRY_WFI Enter Stop mode with WFI instruction + * @arg @ref PWR_STOPENTRY_WFE Enter Stop mode with WFE instruction + * @retval None + */ +void HAL_PWREx_EnterSTOP1Mode(uint8_t STOPEntry) +{ + /* Check the parameters */ + assert_param(IS_PWR_STOP_ENTRY(STOPEntry)); + + /* Stop 1 mode with Low-Power Regulator */ + MODIFY_REG(PWR->CR1, PWR_CR1_LPMS, PWR_CR1_LPMS_STOP1); + + /* Set SLEEPDEEP bit of Cortex System Control Register */ + SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk)); + + /* Select Stop mode entry --------------------------------------------------*/ + if(STOPEntry == PWR_STOPENTRY_WFI) + { + /* Request Wait For Interrupt */ + __WFI(); + } + else + { + /* Request Wait For Event */ + __SEV(); + __WFE(); + __WFE(); + } + + /* Reset SLEEPDEEP bit of Cortex System Control Register */ + CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk)); +} + + +/** + * @brief Enter Stop 2 mode. + * @note In Stop 2 mode, only low power voltage regulator is ON. + * @note In Stop 2 mode, all I/O pins keep the same state as in Run mode. + * @note All clocks in the VCORE domain are stopped, the PLL, the MSI, + * the HSI and the HSE oscillators are disabled. Some peripherals with wakeup capability + * (LCD, LPTIM1, I2C3 and LPUART) can switch on the HSI to receive a frame, and switch off the HSI after + * receiving the frame if it is not a wakeup frame. In this case the HSI clock is propagated only + * to the peripheral requesting it. + * SRAM1, SRAM2 and register contents are preserved. + * The BOR is available. + * The voltage regulator is set in low-power mode but LPR bit must be cleared to enter stop 2 mode. + * Otherwise, Stop 1 mode is entered. + * @note When exiting Stop 2 mode by issuing an interrupt or a wakeup event, + * the HSI RC oscillator is selected as system clock if STOPWUCK bit in RCC_CFGR register + * is set; the MSI oscillator is selected if STOPWUCK is cleared. + * @param STOPEntry specifies if Stop mode in entered with WFI or WFE instruction. + * This parameter can be one of the following values: + * @arg @ref PWR_STOPENTRY_WFI Enter Stop mode with WFI instruction + * @arg @ref PWR_STOPENTRY_WFE Enter Stop mode with WFE instruction + * @retval None + */ +void HAL_PWREx_EnterSTOP2Mode(uint8_t STOPEntry) +{ + /* Check the parameter */ + assert_param(IS_PWR_STOP_ENTRY(STOPEntry)); + + /* Set Stop mode 2 */ + MODIFY_REG(PWR->CR1, PWR_CR1_LPMS, PWR_CR1_LPMS_STOP2); + + /* Set SLEEPDEEP bit of Cortex System Control Register */ + SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk)); + + /* Select Stop mode entry --------------------------------------------------*/ + if(STOPEntry == PWR_STOPENTRY_WFI) + { + /* Request Wait For Interrupt */ + __WFI(); + } + else + { + /* Request Wait For Event */ + __SEV(); + __WFE(); + __WFE(); + } + + /* Reset SLEEPDEEP bit of Cortex System Control Register */ + CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk)); +} + + + + + +/** + * @brief Enter Shutdown mode. + * @note In Shutdown mode, the PLL, the HSI, the MSI, the LSI and the HSE oscillators are switched + * off. The voltage regulator is disabled and Vcore domain is powered off. + * SRAM1, SRAM2 and registers contents are lost except for registers in the Backup domain. + * The BOR is not available. + * @note The I/Os can be configured either with a pull-up or pull-down or can be kept in analog state. + * @retval None + */ +void HAL_PWREx_EnterSHUTDOWNMode(void) +{ + + /* Set Shutdown mode */ + MODIFY_REG(PWR->CR1, PWR_CR1_LPMS, PWR_CR1_LPMS_SHUTDOWN); + + /* Set SLEEPDEEP bit of Cortex System Control Register */ + SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk)); + +/* This option is used to ensure that store operations are completed */ +#if defined ( __CC_ARM) + __force_stores(); +#endif + /* Request Wait For Interrupt */ + __WFI(); +} + + + + +/** + * @brief This function handles the PWR PVD/PVMx interrupt request. + * @note This API should be called under the PVD_PVM_IRQHandler(). + * @retval None + */ +void HAL_PWREx_PVD_PVM_IRQHandler(void) +{ + /* Check PWR exti flag */ + if(__HAL_PWR_PVD_EXTI_GET_FLAG() != RESET) + { + /* PWR PVD interrupt user callback */ + HAL_PWR_PVDCallback(); + + /* Clear PVD exti pending bit */ + __HAL_PWR_PVD_EXTI_CLEAR_FLAG(); + } + /* Next, successively check PVMx exti flags */ +#if defined(PWR_CR2_PVME1) + if(__HAL_PWR_PVM1_EXTI_GET_FLAG() != RESET) + { + /* PWR PVM1 interrupt user callback */ + HAL_PWREx_PVM1Callback(); + + /* Clear PVM1 exti pending bit */ + __HAL_PWR_PVM1_EXTI_CLEAR_FLAG(); + } +#endif /* PWR_CR2_PVME1 */ +#if defined(PWR_CR2_PVME2) + if(__HAL_PWR_PVM2_EXTI_GET_FLAG() != RESET) + { + /* PWR PVM2 interrupt user callback */ + HAL_PWREx_PVM2Callback(); + + /* Clear PVM2 exti pending bit */ + __HAL_PWR_PVM2_EXTI_CLEAR_FLAG(); + } +#endif /* PWR_CR2_PVME2 */ + if(__HAL_PWR_PVM3_EXTI_GET_FLAG() != RESET) + { + /* PWR PVM3 interrupt user callback */ + HAL_PWREx_PVM3Callback(); + + /* Clear PVM3 exti pending bit */ + __HAL_PWR_PVM3_EXTI_CLEAR_FLAG(); + } + if(__HAL_PWR_PVM4_EXTI_GET_FLAG() != RESET) + { + /* PWR PVM4 interrupt user callback */ + HAL_PWREx_PVM4Callback(); + + /* Clear PVM4 exti pending bit */ + __HAL_PWR_PVM4_EXTI_CLEAR_FLAG(); + } +} + + +#if defined(PWR_CR2_PVME1) +/** + * @brief PWR PVM1 interrupt callback + * @retval None + */ +__weak void HAL_PWREx_PVM1Callback(void) +{ + /* NOTE : This function should not be modified; when the callback is needed, + HAL_PWREx_PVM1Callback() API can be implemented in the user file + */ +} +#endif /* PWR_CR2_PVME1 */ + +#if defined(PWR_CR2_PVME2) +/** + * @brief PWR PVM2 interrupt callback + * @retval None + */ +__weak void HAL_PWREx_PVM2Callback(void) +{ + /* NOTE : This function should not be modified; when the callback is needed, + HAL_PWREx_PVM2Callback() API can be implemented in the user file + */ +} +#endif /* PWR_CR2_PVME2 */ + +/** + * @brief PWR PVM3 interrupt callback + * @retval None + */ +__weak void HAL_PWREx_PVM3Callback(void) +{ + /* NOTE : This function should not be modified; when the callback is needed, + HAL_PWREx_PVM3Callback() API can be implemented in the user file + */ +} + +/** + * @brief PWR PVM4 interrupt callback + * @retval None + */ +__weak void HAL_PWREx_PVM4Callback(void) +{ + /* NOTE : This function should not be modified; when the callback is needed, + HAL_PWREx_PVM4Callback() API can be implemented in the user file + */ +} + + +/** + * @} + */ + +/** + * @} + */ + +#endif /* HAL_PWR_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rcc.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rcc.c new file mode 100644 index 0000000..06a9b26 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rcc.c @@ -0,0 +1,1730 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_rcc.c + * @author MCD Application Team + * @brief RCC HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Reset and Clock Control (RCC) peripheral: + * + Initialization and de-initialization functions + * + Peripheral Control functions + * + @verbatim + ============================================================================== + ##### RCC specific features ##### + ============================================================================== + [..] + After reset the device is running from Multiple Speed Internal oscillator + (4 MHz) with Flash 0 wait state. Flash prefetch buffer, D-Cache + and I-Cache are disabled, and all peripherals are off except internal + SRAM, Flash and JTAG. + + (+) There is no prescaler on High speed (AHBs) and Low speed (APBs) busses: + all peripherals mapped on these busses are running at MSI speed. + (+) The clock for all peripherals is switched off, except the SRAM and FLASH. + (+) All GPIOs are in analog mode, except the JTAG pins which + are assigned to be used for debug purpose. + + [..] + Once the device started from reset, the user application has to: + (+) Configure the clock source to be used to drive the System clock + (if the application needs higher frequency/performance) + (+) Configure the System clock frequency and Flash settings + (+) Configure the AHB and APB busses prescalers + (+) Enable the clock for the peripheral(s) to be used + (+) Configure the clock source(s) for peripherals which clocks are not + derived from the System clock (SAIx, RTC, ADC, USB OTG FS/SDMMC1/RNG) + + @endverbatim + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup RCC RCC + * @brief RCC HAL module driver + * @{ + */ + +#ifdef HAL_RCC_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/** @defgroup RCC_Private_Constants RCC Private Constants + * @{ + */ +#define HSE_TIMEOUT_VALUE HSE_STARTUP_TIMEOUT +#define HSI_TIMEOUT_VALUE 2U /* 2 ms (minimum Tick + 1) */ +#define MSI_TIMEOUT_VALUE 2U /* 2 ms (minimum Tick + 1) */ +#define LSI_TIMEOUT_VALUE 2U /* 2 ms (minimum Tick + 1) */ +#define HSI48_TIMEOUT_VALUE 2U /* 2 ms (minimum Tick + 1) */ +#define PLL_TIMEOUT_VALUE 2U /* 2 ms (minimum Tick + 1) */ +#define CLOCKSWITCH_TIMEOUT_VALUE 5000U /* 5 s */ +/** + * @} + */ + +/* Private macro -------------------------------------------------------------*/ +/** @defgroup RCC_Private_Macros RCC Private Macros + * @{ + */ +#define __MCO1_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE() +#define MCO1_GPIO_PORT GPIOA +#define MCO1_PIN GPIO_PIN_8 + +#define RCC_PLL_OSCSOURCE_CONFIG(__HAL_RCC_PLLSOURCE__) \ + (MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, (__HAL_RCC_PLLSOURCE__))) +/** + * @} + */ + +/* Private variables ---------------------------------------------------------*/ + +/* Private function prototypes -----------------------------------------------*/ +/** @defgroup RCC_Private_Functions RCC Private Functions + * @{ + */ +static HAL_StatusTypeDef RCC_SetFlashLatencyFromMSIRange(uint32_t msirange); +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +static uint32_t RCC_GetSysClockFreqFromPLLSource(void); +#endif +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup RCC_Exported_Functions RCC Exported Functions + * @{ + */ + +/** @defgroup RCC_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions + * + @verbatim + =============================================================================== + ##### Initialization and de-initialization functions ##### + =============================================================================== + [..] + This section provides functions allowing to configure the internal and external oscillators + (HSE, HSI, LSE, MSI, LSI, PLL, CSS and MCO) and the System busses clocks (SYSCLK, AHB, APB1 + and APB2). + + [..] Internal/external clock and PLL configuration + (+) HSI (high-speed internal): 16 MHz factory-trimmed RC used directly or through + the PLL as System clock source. + + (+) MSI (Mutiple Speed Internal): Its frequency is software trimmable from 100KHZ to 48MHZ. + It can be used to generate the clock for the USB OTG FS (48 MHz). + The number of flash wait states is automatically adjusted when MSI range is updated with + HAL_RCC_OscConfig() and the MSI is used as System clock source. + + (+) LSI (low-speed internal): 32 KHz low consumption RC used as IWDG and/or RTC + clock source. + + (+) HSE (high-speed external): 4 to 48 MHz crystal oscillator used directly or + through the PLL as System clock source. Can be used also optionally as RTC clock source. + + (+) LSE (low-speed external): 32.768 KHz oscillator used optionally as RTC clock source. + + (+) PLL (clocked by HSI, HSE or MSI) providing up to three independent output clocks: + (++) The first output is used to generate the high speed system clock (up to 80MHz). + (++) The second output is used to generate the clock for the USB OTG FS (48 MHz), + the random analog generator (<=48 MHz) and the SDMMC1 (<= 48 MHz). + (++) The third output is used to generate an accurate clock to achieve + high-quality audio performance on SAI interface. + + (+) PLLSAI1 (clocked by HSI, HSE or MSI) providing up to three independent output clocks: + (++) The first output is used to generate SAR ADC1 clock. + (++) The second output is used to generate the clock for the USB OTG FS (48 MHz), + the random analog generator (<=48 MHz) and the SDMMC1 (<= 48 MHz). + (++) The Third output is used to generate an accurate clock to achieve + high-quality audio performance on SAI interface. + + (+) PLLSAI2 (clocked by HSI , HSE or MSI) providing up to two independent output clocks: + (++) The first output is used to generate SAR ADC2 clock. + (++) The second output is used to generate an accurate clock to achieve + high-quality audio performance on SAI interface. + + (+) CSS (Clock security system): once enabled, if a HSE clock failure occurs + (HSE used directly or through PLL as System clock source), the System clock + is automatically switched to HSI and an interrupt is generated if enabled. + The interrupt is linked to the Cortex-M4 NMI (Non-Maskable Interrupt) + exception vector. + + (+) MCO (microcontroller clock output): used to output MSI, LSI, HSI, LSE, HSE or + main PLL clock (through a configurable prescaler) on PA8 pin. + + [..] System, AHB and APB busses clocks configuration + (+) Several clock sources can be used to drive the System clock (SYSCLK): MSI, HSI, + HSE and main PLL. + The AHB clock (HCLK) is derived from System clock through configurable + prescaler and used to clock the CPU, memory and peripherals mapped + on AHB bus (DMA, GPIO...). APB1 (PCLK1) and APB2 (PCLK2) clocks are derived + from AHB clock through configurable prescalers and used to clock + the peripherals mapped on these busses. You can use + "HAL_RCC_GetSysClockFreq()" function to retrieve the frequencies of these clocks. + + -@- All the peripheral clocks are derived from the System clock (SYSCLK) except: + + (+@) SAI: the SAI clock can be derived either from a specific PLL (PLLSAI1) or (PLLSAI2) or + from an external clock mapped on the SAI_CKIN pin. + You have to use HAL_RCCEx_PeriphCLKConfig() function to configure this clock. + (+@) RTC: the RTC clock can be derived either from the LSI, LSE or HSE clock + divided by 2 to 31. + You have to use __HAL_RCC_RTC_ENABLE() and HAL_RCCEx_PeriphCLKConfig() function + to configure this clock. + (+@) USB OTG FS, SDMMC1 and RNG: USB OTG FS requires a frequency equal to 48 MHz + to work correctly, while the SDMMC1 and RNG peripherals require a frequency + equal or lower than to 48 MHz. This clock is derived of the main PLL or PLLSAI1 + through PLLQ divider. You have to enable the peripheral clock and use + HAL_RCCEx_PeriphCLKConfig() function to configure this clock. + (+@) IWDG clock which is always the LSI clock. + + + (+) The maximum frequency of the SYSCLK, HCLK, PCLK1 and PCLK2 is 80 MHz. + The clock source frequency should be adapted depending on the device voltage range + as listed in the Reference Manual "Clock source frequency versus voltage scaling" chapter. + + @endverbatim + + Table 1. HCLK clock frequency for STM32L4Rx/STM32L4Sx devices + +--------------------------------------------------------+ + | Latency | HCLK clock frequency (MHz) | + | |--------------------------------------| + | | voltage range 1 | voltage range 2 | + | | 1.2 V | 1.0 V | + |-----------------|-------------------|------------------| + |0WS(1 CPU cycles)| 0 < HCLK <= 20 | 0 < HCLK <= 8 | + |-----------------|-------------------|------------------| + |1WS(2 CPU cycles)| 20 < HCLK <= 40 | 8 < HCLK <= 16 | + |-----------------|-------------------|------------------| + |2WS(3 CPU cycles)| 40 < HCLK <= 60 | 16 < HCLK <= 26 | + |-----------------|-------------------|------------------| + |3WS(4 CPU cycles)| 60 < HCLK <= 80 | 16 < HCLK <= 26 | + |-----------------|-------------------|------------------| + |4WS(5 CPU cycles)| 80 < HCLK <= 100 | 16 < HCLK <= 26 | + |-----------------|-------------------|------------------| + |5WS(6 CPU cycles)| 100 < HCLK <= 120 | 16 < HCLK <= 26 | + +--------------------------------------------------------+ + + Table 2. HCLK clock frequency for other STM32L4 devices + +-------------------------------------------------------+ + | Latency | HCLK clock frequency (MHz) | + | |-------------------------------------| + | | voltage range 1 | voltage range 2 | + | | 1.2 V | 1.0 V | + |-----------------|------------------|------------------| + |0WS(1 CPU cycles)| 0 < HCLK <= 16 | 0 < HCLK <= 6 | + |-----------------|------------------|------------------| + |1WS(2 CPU cycles)| 16 < HCLK <= 32 | 6 < HCLK <= 12 | + |-----------------|------------------|------------------| + |2WS(3 CPU cycles)| 32 < HCLK <= 48 | 12 < HCLK <= 18 | + |-----------------|------------------|------------------| + |3WS(4 CPU cycles)| 48 < HCLK <= 64 | 18 < HCLK <= 26 | + |-----------------|------------------|------------------| + |4WS(5 CPU cycles)| 64 < HCLK <= 80 | 18 < HCLK <= 26 | + +-------------------------------------------------------+ + * @{ + */ + +/** + * @brief Reset the RCC clock configuration to the default reset state. + * @note The default reset state of the clock configuration is given below: + * - MSI ON and used as system clock source + * - HSE, HSI, PLL, PLLSAI1 and PLLISAI2 OFF + * - AHB, APB1 and APB2 prescaler set to 1. + * - CSS, MCO1 OFF + * - All interrupts disabled + * - All interrupt and reset flags cleared + * @note This function doesn't modify the configuration of the + * - Peripheral clocks + * - LSI, LSE and RTC clocks + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RCC_DeInit(void) +{ + uint32_t tickstart = 0; + + /* Set MSION bit */ + SET_BIT(RCC->CR, RCC_CR_MSION); + + /* Insure MSIRDY bit is set before writing default MSIRANGE value */ + /* Get start tick */ + tickstart = HAL_GetTick(); + + /* Wait till MSI is ready */ + while(READ_BIT(RCC->CR, RCC_CR_MSIRDY) == RESET) + { + if((HAL_GetTick() - tickstart) > MSI_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + + /* Set MSIRANGE default value */ + MODIFY_REG(RCC->CR, RCC_CR_MSIRANGE, RCC_MSIRANGE_6); + + /* Reset CFGR register (MSI is selected as system clock source) */ + CLEAR_REG(RCC->CFGR); + + /* Update the SystemCoreClock global variable for MSI as system clock source */ + SystemCoreClock = MSI_VALUE; + + /* Configure the source of time base considering new system clock settings */ + if(HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK) + { + return HAL_ERROR; + } + + /* Insure MSI selected as system clock source */ + /* Get start tick */ + tickstart = HAL_GetTick(); + + /* Wait till system clock source is ready */ + while(READ_BIT(RCC->CFGR, RCC_CFGR_SWS) != RCC_CFGR_SWS_MSI) + { + if((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + + /* Reset HSION, HSIKERON, HSIASFS, HSEON, HSECSSON, PLLON, PLLSAIxON bits */ +#if defined(RCC_PLLSAI2_SUPPORT) + + CLEAR_BIT(RCC->CR, RCC_CR_HSEON | RCC_CR_HSION | RCC_CR_HSIKERON| RCC_CR_HSIASFS | RCC_CR_PLLON | RCC_CR_PLLSAI1ON | RCC_CR_PLLSAI2ON); + +#else + + CLEAR_BIT(RCC->CR, RCC_CR_HSEON | RCC_CR_HSION | RCC_CR_HSIKERON| RCC_CR_HSIASFS | RCC_CR_PLLON | RCC_CR_PLLSAI1ON); + +#endif /* RCC_PLLSAI2_SUPPORT */ + + /* Insure PLLRDY, PLLSAI1RDY and PLLSAI2RDY (if present) are reset */ + /* Get start tick */ + tickstart = HAL_GetTick(); + +#if defined(RCC_PLLSAI2_SUPPORT) + + while(READ_BIT(RCC->CR, RCC_CR_PLLRDY | RCC_CR_PLLSAI1RDY | RCC_CR_PLLSAI2RDY) != 0U) + +#else + + while(READ_BIT(RCC->CR, RCC_CR_PLLRDY | RCC_CR_PLLSAI1RDY) != 0U) + +#endif + { + if((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + + /* Reset PLLCFGR register */ + CLEAR_REG(RCC->PLLCFGR); + SET_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN_4 ); + + /* Reset PLLSAI1CFGR register */ + CLEAR_REG(RCC->PLLSAI1CFGR); + SET_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N_4 ); + +#if defined(RCC_PLLSAI2_SUPPORT) + + /* Reset PLLSAI2CFGR register */ + CLEAR_REG(RCC->PLLSAI2CFGR); + SET_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2N_4 ); + +#endif /* RCC_PLLSAI2_SUPPORT */ + + /* Reset HSEBYP bit */ + CLEAR_BIT(RCC->CR, RCC_CR_HSEBYP); + + /* Disable all interrupts */ + CLEAR_REG(RCC->CIER); + + /* Clear all interrupt flags */ + WRITE_REG(RCC->CICR, 0xFFFFFFFFU); + + /* Clear all reset flags */ + SET_BIT(RCC->CSR, RCC_CSR_RMVF); + + return HAL_OK; +} + +/** + * @brief Initialize the RCC Oscillators according to the specified parameters in the + * RCC_OscInitTypeDef. + * @param RCC_OscInitStruct pointer to an RCC_OscInitTypeDef structure that + * contains the configuration information for the RCC Oscillators. + * @note The PLL is not disabled when used as system clock. + * @note Transitions LSE Bypass to LSE On and LSE On to LSE Bypass are not + * supported by this macro. User should request a transition to LSE Off + * first and then LSE On or LSE Bypass. + * @note Transition HSE Bypass to HSE On and HSE On to HSE Bypass are not + * supported by this macro. User should request a transition to HSE Off + * first and then HSE On or HSE Bypass. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) +{ + uint32_t tickstart = 0; + + /* Check the parameters */ + assert_param(RCC_OscInitStruct != NULL); + assert_param(IS_RCC_OSCILLATORTYPE(RCC_OscInitStruct->OscillatorType)); + + /*----------------------------- MSI Configuration --------------------------*/ + if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_MSI) == RCC_OSCILLATORTYPE_MSI) + { + /* Check the parameters */ + assert_param(IS_RCC_MSI(RCC_OscInitStruct->MSIState)); + assert_param(IS_RCC_MSICALIBRATION_VALUE(RCC_OscInitStruct->MSICalibrationValue)); + assert_param(IS_RCC_MSI_CLOCK_RANGE(RCC_OscInitStruct->MSIClockRange)); + + /* When the MSI is used as system clock it will not be disabled */ + if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_MSI) ) + { + if((READ_BIT(RCC->CR, RCC_CR_MSIRDY) != RESET) && (RCC_OscInitStruct->MSIState == RCC_MSI_OFF)) + { + return HAL_ERROR; + } + + /* Otherwise, just the calibration and MSI range change are allowed */ + else + { + /* To correctly read data from FLASH memory, the number of wait states (LATENCY) + must be correctly programmed according to the frequency of the CPU clock + (HCLK) and the supply voltage of the device. */ + if(RCC_OscInitStruct->MSIClockRange > __HAL_RCC_GET_MSI_RANGE()) + { + /* First increase number of wait states update if necessary */ + if(RCC_SetFlashLatencyFromMSIRange(RCC_OscInitStruct->MSIClockRange) != HAL_OK) + { + return HAL_ERROR; + } + + /* Selects the Multiple Speed oscillator (MSI) clock range .*/ + __HAL_RCC_MSI_RANGE_CONFIG(RCC_OscInitStruct->MSIClockRange); + /* Adjusts the Multiple Speed oscillator (MSI) calibration value.*/ + __HAL_RCC_MSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->MSICalibrationValue); + } + else + { + /* Else, keep current flash latency while decreasing applies */ + /* Selects the Multiple Speed oscillator (MSI) clock range .*/ + __HAL_RCC_MSI_RANGE_CONFIG(RCC_OscInitStruct->MSIClockRange); + /* Adjusts the Multiple Speed oscillator (MSI) calibration value.*/ + __HAL_RCC_MSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->MSICalibrationValue); + + /* Decrease number of wait states update if necessary */ + if(RCC_SetFlashLatencyFromMSIRange(RCC_OscInitStruct->MSIClockRange) != HAL_OK) + { + return HAL_ERROR; + } + } + + /* Update the SystemCoreClock global variable */ + SystemCoreClock = HAL_RCC_GetSysClockFreq() >> AHBPrescTable[READ_BIT(RCC->CFGR, RCC_CFGR_HPRE) >> RCC_CFGR_HPRE_Pos]; + + /* Configure the source of time base considering new system clocks settings*/ + HAL_InitTick (TICK_INT_PRIORITY); + } + } + else + { + /* Check the MSI State */ + if(RCC_OscInitStruct->MSIState != RCC_MSI_OFF) + { + /* Enable the Internal High Speed oscillator (MSI). */ + __HAL_RCC_MSI_ENABLE(); + + /* Get timeout */ + tickstart = HAL_GetTick(); + + /* Wait till MSI is ready */ + while(READ_BIT(RCC->CR, RCC_CR_MSIRDY) == RESET) + { + if((HAL_GetTick() - tickstart) > MSI_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + /* Selects the Multiple Speed oscillator (MSI) clock range .*/ + __HAL_RCC_MSI_RANGE_CONFIG(RCC_OscInitStruct->MSIClockRange); + /* Adjusts the Multiple Speed oscillator (MSI) calibration value.*/ + __HAL_RCC_MSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->MSICalibrationValue); + + } + else + { + /* Disable the Internal High Speed oscillator (MSI). */ + __HAL_RCC_MSI_DISABLE(); + + /* Get timeout */ + tickstart = HAL_GetTick(); + + /* Wait till MSI is ready */ + while(READ_BIT(RCC->CR, RCC_CR_MSIRDY) != RESET) + { + if((HAL_GetTick() - tickstart) > MSI_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + } + } + /*------------------------------- HSE Configuration ------------------------*/ + if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSE) == RCC_OSCILLATORTYPE_HSE) + { + /* Check the parameters */ + assert_param(IS_RCC_HSE(RCC_OscInitStruct->HSEState)); + + /* When the HSE is used as system clock or clock source for PLL in these cases it is not allowed to be disabled */ + if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSE) || + ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && (__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSE))) + { + if((READ_BIT(RCC->CR, RCC_CR_HSERDY) != RESET) && (RCC_OscInitStruct->HSEState == RCC_HSE_OFF)) + { + return HAL_ERROR; + } + } + else + { + /* Set the new HSE configuration ---------------------------------------*/ + __HAL_RCC_HSE_CONFIG(RCC_OscInitStruct->HSEState); + + /* Check the HSE State */ + if(RCC_OscInitStruct->HSEState != RCC_HSE_OFF) + { + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till HSE is ready */ + while(READ_BIT(RCC->CR, RCC_CR_HSERDY) == RESET) + { + if((HAL_GetTick() - tickstart) > HSE_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + else + { + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till HSE is disabled */ + while(READ_BIT(RCC->CR, RCC_CR_HSERDY) != RESET) + { + if((HAL_GetTick() - tickstart) > HSE_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + } + } + /*----------------------------- HSI Configuration --------------------------*/ + if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSI) == RCC_OSCILLATORTYPE_HSI) + { + /* Check the parameters */ + assert_param(IS_RCC_HSI(RCC_OscInitStruct->HSIState)); + assert_param(IS_RCC_HSI_CALIBRATION_VALUE(RCC_OscInitStruct->HSICalibrationValue)); + + /* Check if HSI is used as system clock or as PLL source when PLL is selected as system clock */ + if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSI) || + ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && (__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSI))) + { + /* When HSI is used as system clock it will not be disabled */ + if((READ_BIT(RCC->CR, RCC_CR_HSIRDY) != RESET) && (RCC_OscInitStruct->HSIState == RCC_HSI_OFF)) + { + return HAL_ERROR; + } + /* Otherwise, just the calibration is allowed */ + else + { + /* Adjusts the Internal High Speed oscillator (HSI) calibration value.*/ + __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->HSICalibrationValue); + } + } + else + { + /* Check the HSI State */ + if(RCC_OscInitStruct->HSIState != RCC_HSI_OFF) + { + /* Enable the Internal High Speed oscillator (HSI). */ + __HAL_RCC_HSI_ENABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till HSI is ready */ + while(READ_BIT(RCC->CR, RCC_CR_HSIRDY) == RESET) + { + if((HAL_GetTick() - tickstart) > HSI_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + + /* Adjusts the Internal High Speed oscillator (HSI) calibration value.*/ + __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->HSICalibrationValue); + } + else + { + /* Disable the Internal High Speed oscillator (HSI). */ + __HAL_RCC_HSI_DISABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till HSI is disabled */ + while(READ_BIT(RCC->CR, RCC_CR_HSIRDY) != RESET) + { + if((HAL_GetTick() - tickstart) > HSI_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + } + } + /*------------------------------ LSI Configuration -------------------------*/ + if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSI) == RCC_OSCILLATORTYPE_LSI) + { + /* Check the parameters */ + assert_param(IS_RCC_LSI(RCC_OscInitStruct->LSIState)); + + /* Check the LSI State */ + if(RCC_OscInitStruct->LSIState != RCC_LSI_OFF) + { + /* Enable the Internal Low Speed oscillator (LSI). */ + __HAL_RCC_LSI_ENABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till LSI is ready */ + while(READ_BIT(RCC->CSR, RCC_CSR_LSIRDY) == RESET) + { + if((HAL_GetTick() - tickstart) > LSI_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + else + { + /* Disable the Internal Low Speed oscillator (LSI). */ + __HAL_RCC_LSI_DISABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till LSI is disabled */ + while(READ_BIT(RCC->CSR, RCC_CSR_LSIRDY) != RESET) + { + if((HAL_GetTick() - tickstart) > LSI_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + } + /*------------------------------ LSE Configuration -------------------------*/ + if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSE) == RCC_OSCILLATORTYPE_LSE) + { + FlagStatus pwrclkchanged = RESET; + + /* Check the parameters */ + assert_param(IS_RCC_LSE(RCC_OscInitStruct->LSEState)); + + /* Update LSE configuration in Backup Domain control register */ + /* Requires to enable write access to Backup Domain of necessary */ + if(HAL_IS_BIT_CLR(RCC->APB1ENR1, RCC_APB1ENR1_PWREN)) + { + __HAL_RCC_PWR_CLK_ENABLE(); + pwrclkchanged = SET; + } + + if(HAL_IS_BIT_CLR(PWR->CR1, PWR_CR1_DBP)) + { + /* Enable write access to Backup domain */ + SET_BIT(PWR->CR1, PWR_CR1_DBP); + + /* Wait for Backup domain Write protection disable */ + tickstart = HAL_GetTick(); + + while(HAL_IS_BIT_CLR(PWR->CR1, PWR_CR1_DBP)) + { + if((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + + /* Set the new LSE configuration -----------------------------------------*/ + __HAL_RCC_LSE_CONFIG(RCC_OscInitStruct->LSEState); + + /* Check the LSE State */ + if(RCC_OscInitStruct->LSEState != RCC_LSE_OFF) + { + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till LSE is ready */ + while(READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) == RESET) + { + if((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + else + { + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till LSE is disabled */ + while(READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) != RESET) + { + if((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + + /* Restore clock configuration if changed */ + if(pwrclkchanged == SET) + { + __HAL_RCC_PWR_CLK_DISABLE(); + } + } +#if defined(RCC_HSI48_SUPPORT) + /*------------------------------ HSI48 Configuration -----------------------*/ + if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSI48) == RCC_OSCILLATORTYPE_HSI48) + { + /* Check the parameters */ + assert_param(IS_RCC_HSI48(RCC_OscInitStruct->HSI48State)); + + /* Check the LSI State */ + if(RCC_OscInitStruct->HSI48State != RCC_HSI48_OFF) + { + /* Enable the Internal Low Speed oscillator (HSI48). */ + __HAL_RCC_HSI48_ENABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till HSI48 is ready */ + while(READ_BIT(RCC->CRRCR, RCC_CRRCR_HSI48RDY) == RESET) + { + if((HAL_GetTick() - tickstart) > HSI48_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + else + { + /* Disable the Internal Low Speed oscillator (HSI48). */ + __HAL_RCC_HSI48_DISABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till HSI48 is disabled */ + while(READ_BIT(RCC->CRRCR, RCC_CRRCR_HSI48RDY) != RESET) + { + if((HAL_GetTick() - tickstart) > HSI48_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + } +#endif /* RCC_HSI48_SUPPORT */ + /*-------------------------------- PLL Configuration -----------------------*/ + /* Check the parameters */ + assert_param(IS_RCC_PLL(RCC_OscInitStruct->PLL.PLLState)); + + if(RCC_OscInitStruct->PLL.PLLState != RCC_PLL_NONE) + { + /* Check if the PLL is used as system clock or not */ + if(__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL) + { + if(RCC_OscInitStruct->PLL.PLLState == RCC_PLL_ON) + { + /* Check the parameters */ + assert_param(IS_RCC_PLLSOURCE(RCC_OscInitStruct->PLL.PLLSource)); + assert_param(IS_RCC_PLLM_VALUE(RCC_OscInitStruct->PLL.PLLM)); + assert_param(IS_RCC_PLLN_VALUE(RCC_OscInitStruct->PLL.PLLN)); + assert_param(IS_RCC_PLLP_VALUE(RCC_OscInitStruct->PLL.PLLP)); + assert_param(IS_RCC_PLLQ_VALUE(RCC_OscInitStruct->PLL.PLLQ)); + assert_param(IS_RCC_PLLR_VALUE(RCC_OscInitStruct->PLL.PLLR)); + + /* Disable the main PLL. */ + __HAL_RCC_PLL_DISABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till PLL is ready */ + while(READ_BIT(RCC->CR, RCC_CR_PLLRDY) != RESET) + { + if((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + + /* Configure the main PLL clock source, multiplication and division factors. */ + __HAL_RCC_PLL_CONFIG(RCC_OscInitStruct->PLL.PLLSource, + RCC_OscInitStruct->PLL.PLLM, + RCC_OscInitStruct->PLL.PLLN, + RCC_OscInitStruct->PLL.PLLP, + RCC_OscInitStruct->PLL.PLLQ, + RCC_OscInitStruct->PLL.PLLR); + + /* Enable the main PLL. */ + __HAL_RCC_PLL_ENABLE(); + + /* Enable PLL System Clock output. */ + __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_SYSCLK); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till PLL is ready */ + while(READ_BIT(RCC->CR, RCC_CR_PLLRDY) == RESET) + { + if((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + else + { + /* Disable the main PLL. */ + __HAL_RCC_PLL_DISABLE(); + + /* Disable all PLL outputs to save power if no PLLs on */ + if((READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) == RESET) +#if defined(RCC_PLLSAI2_SUPPORT) + && + (READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) == RESET) +#endif /* RCC_PLLSAI2_SUPPORT */ + ) + { + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, RCC_PLLSOURCE_NONE); + } + +#if defined(RCC_PLLSAI2_SUPPORT) + __HAL_RCC_PLLCLKOUT_DISABLE(RCC_PLL_SYSCLK | RCC_PLL_48M1CLK | RCC_PLL_SAI3CLK); +#else + __HAL_RCC_PLLCLKOUT_DISABLE(RCC_PLL_SYSCLK | RCC_PLL_48M1CLK | RCC_PLL_SAI2CLK); +#endif /* RCC_PLLSAI2_SUPPORT */ + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till PLL is disabled */ + while(READ_BIT(RCC->CR, RCC_CR_PLLRDY) != RESET) + { + if((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + } + else + { + return HAL_ERROR; + } + } + return HAL_OK; +} + +/** + * @brief Initialize the CPU, AHB and APB busses clocks according to the specified + * parameters in the RCC_ClkInitStruct. + * @param RCC_ClkInitStruct pointer to an RCC_OscInitTypeDef structure that + * contains the configuration information for the RCC peripheral. + * @param FLatency FLASH Latency + * This parameter can be one of the following values: + * @arg FLASH_LATENCY_0 FLASH 0 Latency cycle + * @arg FLASH_LATENCY_1 FLASH 1 Latency cycle + * @arg FLASH_LATENCY_2 FLASH 2 Latency cycles + * @arg FLASH_LATENCY_3 FLASH 3 Latency cycles + * @arg FLASH_LATENCY_4 FLASH 4 Latency cycles + @if STM32L4S9xx + * @arg FLASH_LATENCY_5 FLASH 5 Latency cycles + * @arg FLASH_LATENCY_6 FLASH 6 Latency cycles + * @arg FLASH_LATENCY_7 FLASH 7 Latency cycles + * @arg FLASH_LATENCY_8 FLASH 8 Latency cycles + * @arg FLASH_LATENCY_9 FLASH 9 Latency cycles + * @arg FLASH_LATENCY_10 FLASH 10 Latency cycles + * @arg FLASH_LATENCY_11 FLASH 11 Latency cycles + * @arg FLASH_LATENCY_12 FLASH 12 Latency cycles + * @arg FLASH_LATENCY_13 FLASH 13 Latency cycles + * @arg FLASH_LATENCY_14 FLASH 14 Latency cycles + * @arg FLASH_LATENCY_15 FLASH 15 Latency cycles + @endif + * + * @note The SystemCoreClock CMSIS variable is used to store System Clock Frequency + * and updated by HAL_RCC_GetHCLKFreq() function called within this function + * + * @note The MSI is used by default as system clock source after + * startup from Reset, wake-up from STANDBY mode. After restart from Reset, + * the MSI frequency is set to its default value 4 MHz. + * + * @note The HSI can be selected as system clock source after + * from STOP modes or in case of failure of the HSE used directly or indirectly + * as system clock (if the Clock Security System CSS is enabled). + * + * @note A switch from one clock source to another occurs only if the target + * clock source is ready (clock stable after startup delay or PLL locked). + * If a clock source which is not yet ready is selected, the switch will + * occur when the clock source is ready. + * + * @note You can use HAL_RCC_GetClockConfig() function to know which clock is + * currently used as system clock source. + * + * @note Depending on the device voltage range, the software has to set correctly + * HPRE[3:0] bits to ensure that HCLK not exceed the maximum allowed frequency + * (for more details refer to section above "Initialization/de-initialization functions") + * @retval None + */ +HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, uint32_t FLatency) +{ + uint32_t tickstart = 0; +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + uint32_t pllfreq = 0; + uint32_t hpre = RCC_SYSCLK_DIV1; +#endif + + /* Check the parameters */ + assert_param(RCC_ClkInitStruct != NULL); + assert_param(IS_RCC_CLOCKTYPE(RCC_ClkInitStruct->ClockType)); + assert_param(IS_FLASH_LATENCY(FLatency)); + + /* To correctly read data from FLASH memory, the number of wait states (LATENCY) + must be correctly programmed according to the frequency of the CPU clock + (HCLK) and the supply voltage of the device. */ + + /* Increasing the number of wait states because of higher CPU frequency */ + if(FLatency > READ_BIT(FLASH->ACR, FLASH_ACR_LATENCY)) + { + /* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */ + __HAL_FLASH_SET_LATENCY(FLatency); + + /* Check that the new number of wait states is taken into account to access the Flash + memory by reading the FLASH_ACR register */ + if(READ_BIT(FLASH->ACR, FLASH_ACR_LATENCY) != FLatency) + { + return HAL_ERROR; + } + } + + /*------------------------- SYSCLK Configuration ---------------------------*/ + if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_SYSCLK) == RCC_CLOCKTYPE_SYSCLK) + { + assert_param(IS_RCC_SYSCLKSOURCE(RCC_ClkInitStruct->SYSCLKSource)); + + /* PLL is selected as System Clock Source */ + if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_PLLCLK) + { + /* Check the PLL ready flag */ + if(READ_BIT(RCC->CR, RCC_CR_PLLRDY) == RESET) + { + return HAL_ERROR; + } +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + /* Undershoot management when selection PLL as SYSCLK source and frequency above 80Mhz */ + /* Compute target PLL output frequency */ + pllfreq = RCC_GetSysClockFreqFromPLLSource(); + + /* Intermediate step with HCLK prescaler 2 necessary before to go over 80Mhz */ + if((pllfreq > 80000000U) && + (((((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_HCLK) == RCC_CLOCKTYPE_HCLK) && (RCC_ClkInitStruct->AHBCLKDivider == RCC_SYSCLK_DIV1)) + || + ((READ_BIT(RCC->CFGR, RCC_CFGR_HPRE) == RCC_SYSCLK_DIV1)))) + { + MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_SYSCLK_DIV2); + hpre = RCC_SYSCLK_DIV2; + } +#endif + } + else + { + /* HSE is selected as System Clock Source */ + if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_HSE) + { + /* Check the HSE ready flag */ + if(READ_BIT(RCC->CR, RCC_CR_HSERDY) == RESET) + { + return HAL_ERROR; + } + } + /* MSI is selected as System Clock Source */ + else if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_MSI) + { + /* Check the MSI ready flag */ + if(READ_BIT(RCC->CR, RCC_CR_MSIRDY) == RESET) + { + return HAL_ERROR; + } + } + /* HSI is selected as System Clock Source */ + else + { + /* Check the HSI ready flag */ + if(READ_BIT(RCC->CR, RCC_CR_HSIRDY) == RESET) + { + return HAL_ERROR; + } + } +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + /* Overshoot management when going down from PLL as SYSCLK source and frequency above 80Mhz */ + pllfreq = HAL_RCC_GetSysClockFreq(); + + /* Intermediate step with HCLK prescaler 2 necessary before to go under 80Mhz */ + if(pllfreq > 80000000U) + { + MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_SYSCLK_DIV2); + hpre = RCC_SYSCLK_DIV2; + } +#endif + + } + + MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_ClkInitStruct->SYSCLKSource); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_PLLCLK) + { + while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL) + { + if((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + else + { + if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_HSE) + { + while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_HSE) + { + if((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + else if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_MSI) + { + while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_MSI) + { + if((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + else + { + while(__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_HSI) + { + if((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + } + } + + /*-------------------------- HCLK Configuration --------------------------*/ + if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_HCLK) == RCC_CLOCKTYPE_HCLK) + { + assert_param(IS_RCC_HCLK(RCC_ClkInitStruct->AHBCLKDivider)); + MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_ClkInitStruct->AHBCLKDivider); + } +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + else + { + /* Is intermediate HCLK prescaler 2 applied internally, complete with HCLK prescaler 1 */ + if(hpre == RCC_SYSCLK_DIV2) + { + MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_SYSCLK_DIV1); + } + } +#endif + + /* Decreasing the number of wait states because of lower CPU frequency */ + if(FLatency < READ_BIT(FLASH->ACR, FLASH_ACR_LATENCY)) + { + /* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */ + __HAL_FLASH_SET_LATENCY(FLatency); + + /* Check that the new number of wait states is taken into account to access the Flash + memory by reading the FLASH_ACR register */ + if(READ_BIT(FLASH->ACR, FLASH_ACR_LATENCY) != FLatency) + { + return HAL_ERROR; + } + } + + /*-------------------------- PCLK1 Configuration ---------------------------*/ + if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK1) == RCC_CLOCKTYPE_PCLK1) + { + assert_param(IS_RCC_PCLK(RCC_ClkInitStruct->APB1CLKDivider)); + MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE1, RCC_ClkInitStruct->APB1CLKDivider); + } + + /*-------------------------- PCLK2 Configuration ---------------------------*/ + if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK2) == RCC_CLOCKTYPE_PCLK2) + { + assert_param(IS_RCC_PCLK(RCC_ClkInitStruct->APB2CLKDivider)); + MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE2, ((RCC_ClkInitStruct->APB2CLKDivider) << 3U)); + } + + /* Update the SystemCoreClock global variable */ + SystemCoreClock = HAL_RCC_GetSysClockFreq() >> AHBPrescTable[READ_BIT(RCC->CFGR, RCC_CFGR_HPRE) >> RCC_CFGR_HPRE_Pos]; + + /* Configure the source of time base considering new system clocks settings*/ + HAL_InitTick (TICK_INT_PRIORITY); + + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup RCC_Exported_Functions_Group2 Peripheral Control functions + * @brief RCC clocks control functions + * +@verbatim + =============================================================================== + ##### Peripheral Control functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to: + + (+) Ouput clock to MCO pin. + (+) Retrieve current clock frequencies. + (+) Enable the Clock Security System. + +@endverbatim + * @{ + */ + +/** + * @brief Select the clock source to output on MCO pin(PA8). + * @note PA8 should be configured in alternate function mode. + * @param RCC_MCOx specifies the output direction for the clock source. + * For STM32L4xx family this parameter can have only one value: + * @arg @ref RCC_MCO1 Clock source to output on MCO1 pin(PA8). + * @param RCC_MCOSource specifies the clock source to output. + * This parameter can be one of the following values: + * @arg @ref RCC_MCO1SOURCE_NOCLOCK MCO output disabled, no clock on MCO + * @arg @ref RCC_MCO1SOURCE_SYSCLK system clock selected as MCO source + * @arg @ref RCC_MCO1SOURCE_MSI MSI clock selected as MCO source + * @arg @ref RCC_MCO1SOURCE_HSI HSI clock selected as MCO source + * @arg @ref RCC_MCO1SOURCE_HSE HSE clock selected as MCO sourcee + * @arg @ref RCC_MCO1SOURCE_PLLCLK main PLL clock selected as MCO source + * @arg @ref RCC_MCO1SOURCE_LSI LSI clock selected as MCO source + * @arg @ref RCC_MCO1SOURCE_LSE LSE clock selected as MCO source + @if STM32L443xx + * @arg @ref RCC_MCO1SOURCE_HSI48 HSI48 clock selected as MCO source for devices with HSI48 + @endif + * @param RCC_MCODiv specifies the MCO prescaler. + * This parameter can be one of the following values: + * @arg @ref RCC_MCODIV_1 no division applied to MCO clock + * @arg @ref RCC_MCODIV_2 division by 2 applied to MCO clock + * @arg @ref RCC_MCODIV_4 division by 4 applied to MCO clock + * @arg @ref RCC_MCODIV_8 division by 8 applied to MCO clock + * @arg @ref RCC_MCODIV_16 division by 16 applied to MCO clock + * @retval None + */ +void HAL_RCC_MCOConfig( uint32_t RCC_MCOx, uint32_t RCC_MCOSource, uint32_t RCC_MCODiv) +{ + GPIO_InitTypeDef GPIO_InitStruct; + /* Check the parameters */ + assert_param(IS_RCC_MCO(RCC_MCOx)); + assert_param(IS_RCC_MCODIV(RCC_MCODiv)); + assert_param(IS_RCC_MCO1SOURCE(RCC_MCOSource)); + + /* MCO Clock Enable */ + __MCO1_CLK_ENABLE(); + + /* Configue the MCO1 pin in alternate function mode */ + GPIO_InitStruct.Pin = MCO1_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Alternate = GPIO_AF0_MCO; + HAL_GPIO_Init(MCO1_GPIO_PORT, &GPIO_InitStruct); + + /* Mask MCOSEL[] and MCOPRE[] bits then set MCO1 clock source and prescaler */ + MODIFY_REG(RCC->CFGR, (RCC_CFGR_MCOSEL | RCC_CFGR_MCOPRE), (RCC_MCOSource | RCC_MCODiv )); +} + +/** + * @brief Return the SYSCLK frequency. + * + * @note The system frequency computed by this function is not the real + * frequency in the chip. It is calculated based on the predefined + * constant and the selected clock source: + * @note If SYSCLK source is MSI, function returns values based on MSI + * Value as defined by the MSI range. + * @note If SYSCLK source is HSI, function returns values based on HSI_VALUE(*) + * @note If SYSCLK source is HSE, function returns values based on HSE_VALUE(**) + * @note If SYSCLK source is PLL, function returns values based on HSE_VALUE(**), + * HSI_VALUE(*) or MSI Value multiplied/divided by the PLL factors. + * @note (*) HSI_VALUE is a constant defined in stm32l4xx_hal_conf.h file (default value + * 16 MHz) but the real value may vary depending on the variations + * in voltage and temperature. + * @note (**) HSE_VALUE is a constant defined in stm32l4xx_hal_conf.h file (default value + * 8 MHz), user has to ensure that HSE_VALUE is same as the real + * frequency of the crystal used. Otherwise, this function may + * have wrong result. + * + * @note The result of this function could be not correct when using fractional + * value for HSE crystal. + * + * @note This function can be used by the user application to compute the + * baudrate for the communication peripherals or configure other parameters. + * + * @note Each time SYSCLK changes, this function must be called to update the + * right SYSCLK value. Otherwise, any configuration based on this function will be incorrect. + * + * + * @retval SYSCLK frequency + */ +uint32_t HAL_RCC_GetSysClockFreq(void) +{ + uint32_t msirange = 0U, pllvco = 0U, pllsource = 0U, pllr = 2U, pllm = 2U; + uint32_t sysclockfreq = 0U; + + if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_MSI) || + ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && (__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_MSI))) + { + /* MSI or PLL with MSI source used as system clock source */ + + /* Get SYSCLK source */ + if(READ_BIT(RCC->CR, RCC_CR_MSIRGSEL) == RESET) + { /* MSISRANGE from RCC_CSR applies */ + msirange = READ_BIT(RCC->CSR, RCC_CSR_MSISRANGE) >> RCC_CSR_MSISRANGE_Pos; + } + else + { /* MSIRANGE from RCC_CR applies */ + msirange = READ_BIT(RCC->CR, RCC_CR_MSIRANGE) >> RCC_CR_MSIRANGE_Pos; + } + /*MSI frequency range in HZ*/ + msirange = MSIRangeTable[msirange]; + + if(__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_MSI) + { + /* MSI used as system clock source */ + sysclockfreq = msirange; + } + } + else if(__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSI) + { + /* HSI used as system clock source */ + sysclockfreq = HSI_VALUE; + } + else if(__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSE) + { + /* HSE used as system clock source */ + sysclockfreq = HSE_VALUE; + } + + if(__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) + { + /* PLL used as system clock source */ + + /* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLN + SYSCLK = PLL_VCO / PLLR + */ + pllsource = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC); + pllm = (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U ; + + switch (pllsource) + { + case RCC_PLLSOURCE_HSI: /* HSI used as PLL clock source */ + pllvco = (HSI_VALUE / pllm) * (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos); + break; + + case RCC_PLLSOURCE_HSE: /* HSE used as PLL clock source */ + pllvco = (HSE_VALUE / pllm) * (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos); + break; + + case RCC_PLLSOURCE_MSI: /* MSI used as PLL clock source */ + default: + pllvco = (msirange / pllm) * (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos); + break; + } + pllr = ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLR) >> RCC_PLLCFGR_PLLR_Pos) + 1U ) * 2U; + sysclockfreq = pllvco/pllr; + } + + return sysclockfreq; +} + +/** + * @brief Return the HCLK frequency. + * @note Each time HCLK changes, this function must be called to update the + * right HCLK value. Otherwise, any configuration based on this function will be incorrect. + * + * @note The SystemCoreClock CMSIS variable is used to store System Clock Frequency. + * @retval HCLK frequency in Hz + */ +uint32_t HAL_RCC_GetHCLKFreq(void) +{ + return SystemCoreClock; +} + +/** + * @brief Return the PCLK1 frequency. + * @note Each time PCLK1 changes, this function must be called to update the + * right PCLK1 value. Otherwise, any configuration based on this function will be incorrect. + * @retval PCLK1 frequency in Hz + */ +uint32_t HAL_RCC_GetPCLK1Freq(void) +{ + /* Get HCLK source and Compute PCLK1 frequency ---------------------------*/ + return (HAL_RCC_GetHCLKFreq() >> APBPrescTable[READ_BIT(RCC->CFGR, RCC_CFGR_PPRE1) >> RCC_CFGR_PPRE1_Pos]); +} + +/** + * @brief Return the PCLK2 frequency. + * @note Each time PCLK2 changes, this function must be called to update the + * right PCLK2 value. Otherwise, any configuration based on this function will be incorrect. + * @retval PCLK2 frequency in Hz + */ +uint32_t HAL_RCC_GetPCLK2Freq(void) +{ + /* Get HCLK source and Compute PCLK2 frequency ---------------------------*/ + return (HAL_RCC_GetHCLKFreq()>> APBPrescTable[READ_BIT(RCC->CFGR, RCC_CFGR_PPRE2) >> RCC_CFGR_PPRE2_Pos]); +} + +/** + * @brief Configure the RCC_OscInitStruct according to the internal + * RCC configuration registers. + * @param RCC_OscInitStruct pointer to an RCC_OscInitTypeDef structure that + * will be configured. + * @retval None + */ +void HAL_RCC_GetOscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) +{ + /* Check the parameters */ + assert_param(RCC_OscInitStruct != NULL); + + /* Set all possible values for the Oscillator type parameter ---------------*/ +#if defined(RCC_HSI48_SUPPORT) + RCC_OscInitStruct->OscillatorType = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_MSI | \ + RCC_OSCILLATORTYPE_LSE | RCC_OSCILLATORTYPE_LSI | RCC_OSCILLATORTYPE_HSI48; +#else + RCC_OscInitStruct->OscillatorType = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_MSI | \ + RCC_OSCILLATORTYPE_LSE | RCC_OSCILLATORTYPE_LSI; +#endif /* RCC_HSI48_SUPPORT */ + + /* Get the HSE configuration -----------------------------------------------*/ + if(READ_BIT(RCC->CR, RCC_CR_HSEBYP) == RCC_CR_HSEBYP) + { + RCC_OscInitStruct->HSEState = RCC_HSE_BYPASS; + } + else if(READ_BIT(RCC->CR, RCC_CR_HSEON) == RCC_CR_HSEON) + { + RCC_OscInitStruct->HSEState = RCC_HSE_ON; + } + else + { + RCC_OscInitStruct->HSEState = RCC_HSE_OFF; + } + + /* Get the MSI configuration -----------------------------------------------*/ + if(READ_BIT(RCC->CR, RCC_CR_MSION) == RCC_CR_MSION) + { + RCC_OscInitStruct->MSIState = RCC_MSI_ON; + } + else + { + RCC_OscInitStruct->MSIState = RCC_MSI_OFF; + } + + RCC_OscInitStruct->MSICalibrationValue = READ_BIT(RCC->ICSCR, RCC_ICSCR_MSITRIM) >> RCC_ICSCR_MSITRIM_Pos; + RCC_OscInitStruct->MSIClockRange = READ_BIT(RCC->CR, RCC_CR_MSIRANGE); + + /* Get the HSI configuration -----------------------------------------------*/ + if(READ_BIT(RCC->CR, RCC_CR_HSION) == RCC_CR_HSION) + { + RCC_OscInitStruct->HSIState = RCC_HSI_ON; + } + else + { + RCC_OscInitStruct->HSIState = RCC_HSI_OFF; + } + + RCC_OscInitStruct->HSICalibrationValue = READ_BIT(RCC->ICSCR, RCC_ICSCR_HSITRIM) >> RCC_ICSCR_HSITRIM_Pos; + + /* Get the LSE configuration -----------------------------------------------*/ + if(READ_BIT(RCC->BDCR, RCC_BDCR_LSEBYP) == RCC_BDCR_LSEBYP) + { + RCC_OscInitStruct->LSEState = RCC_LSE_BYPASS; + } + else if(READ_BIT(RCC->BDCR, RCC_BDCR_LSEON) == RCC_BDCR_LSEON) + { + RCC_OscInitStruct->LSEState = RCC_LSE_ON; + } + else + { + RCC_OscInitStruct->LSEState = RCC_LSE_OFF; + } + + /* Get the LSI configuration -----------------------------------------------*/ + if(READ_BIT(RCC->CSR, RCC_CSR_LSION) == RCC_CSR_LSION) + { + RCC_OscInitStruct->LSIState = RCC_LSI_ON; + } + else + { + RCC_OscInitStruct->LSIState = RCC_LSI_OFF; + } + +#if defined(RCC_HSI48_SUPPORT) + /* Get the HSI48 configuration ---------------------------------------------*/ + if(READ_BIT(RCC->CRRCR, RCC_CRRCR_HSI48ON) == RCC_CRRCR_HSI48ON) + { + RCC_OscInitStruct->HSI48State = RCC_HSI48_ON; + } + else + { + RCC_OscInitStruct->HSI48State = RCC_HSI48_OFF; + } +#else + RCC_OscInitStruct->HSI48State = RCC_HSI48_OFF; +#endif /* RCC_HSI48_SUPPORT */ + + /* Get the PLL configuration -----------------------------------------------*/ + if(READ_BIT(RCC->CR, RCC_CR_PLLON) == RCC_CR_PLLON) + { + RCC_OscInitStruct->PLL.PLLState = RCC_PLL_ON; + } + else + { + RCC_OscInitStruct->PLL.PLLState = RCC_PLL_OFF; + } + RCC_OscInitStruct->PLL.PLLSource = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC); + RCC_OscInitStruct->PLL.PLLM = (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U; + RCC_OscInitStruct->PLL.PLLN = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos; + RCC_OscInitStruct->PLL.PLLQ = (((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLQ) >> RCC_PLLCFGR_PLLQ_Pos) + 1U) << 1U); + RCC_OscInitStruct->PLL.PLLR = (((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLR) >> RCC_PLLCFGR_PLLR_Pos) + 1U) << 1U); +#if defined(RCC_PLLP_DIV_2_31_SUPPORT) + RCC_OscInitStruct->PLL.PLLP = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLPDIV) >> RCC_PLLCFGR_PLLPDIV_Pos; +#else + if(READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLP) != RESET) + { + RCC_OscInitStruct->PLL.PLLP = RCC_PLLP_DIV17; + } + else + { + RCC_OscInitStruct->PLL.PLLP = RCC_PLLP_DIV7; + } +#endif /* RCC_PLLP_DIV_2_31_SUPPORT */ +} + +/** + * @brief Configure the RCC_ClkInitStruct according to the internal + * RCC configuration registers. + * @param RCC_ClkInitStruct pointer to an RCC_ClkInitTypeDef structure that + * will be configured. + * @param pFLatency Pointer on the Flash Latency. + * @retval None + */ +void HAL_RCC_GetClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, uint32_t *pFLatency) +{ + /* Check the parameters */ + assert_param(RCC_ClkInitStruct != NULL); + assert_param(pFLatency != NULL); + + /* Set all possible values for the Clock type parameter --------------------*/ + RCC_ClkInitStruct->ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; + + /* Get the SYSCLK configuration --------------------------------------------*/ + RCC_ClkInitStruct->SYSCLKSource = READ_BIT(RCC->CFGR, RCC_CFGR_SW); + + /* Get the HCLK configuration ----------------------------------------------*/ + RCC_ClkInitStruct->AHBCLKDivider = READ_BIT(RCC->CFGR, RCC_CFGR_HPRE); + + /* Get the APB1 configuration ----------------------------------------------*/ + RCC_ClkInitStruct->APB1CLKDivider = READ_BIT(RCC->CFGR, RCC_CFGR_PPRE1); + + /* Get the APB2 configuration ----------------------------------------------*/ + RCC_ClkInitStruct->APB2CLKDivider = (READ_BIT(RCC->CFGR, RCC_CFGR_PPRE2) >> 3U); + + /* Get the Flash Wait State (Latency) configuration ------------------------*/ + *pFLatency = READ_BIT(FLASH->ACR, FLASH_ACR_LATENCY); +} + +/** + * @brief Enable the Clock Security System. + * @note If a failure is detected on the HSE oscillator clock, this oscillator + * is automatically disabled and an interrupt is generated to inform the + * software about the failure (Clock Security System Interrupt, CSSI), + * allowing the MCU to perform rescue operations. The CSSI is linked to + * the Cortex-M4 NMI (Non-Maskable Interrupt) exception vector. + * @note The Clock Security System can only be cleared by reset. + * @retval None + */ +void HAL_RCC_EnableCSS(void) +{ + SET_BIT(RCC->CR, RCC_CR_CSSON) ; +} + +/** + * @brief Handle the RCC Clock Security System interrupt request. + * @note This API should be called under the NMI_Handler(). + * @retval None + */ +void HAL_RCC_NMI_IRQHandler(void) +{ + /* Check RCC CSSF interrupt flag */ + if(__HAL_RCC_GET_IT(RCC_IT_CSS)) + { + /* RCC Clock Security System interrupt user callback */ + HAL_RCC_CSSCallback(); + + /* Clear RCC CSS pending bit */ + __HAL_RCC_CLEAR_IT(RCC_IT_CSS); + } +} + +/** + * @brief RCC Clock Security System interrupt callback. + * @retval none + */ +__weak void HAL_RCC_CSSCallback(void) +{ + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_RCC_CSSCallback should be implemented in the user file + */ +} + +/** + * @} + */ + +/** + * @} + */ + +/* Private function prototypes -----------------------------------------------*/ +/** @addtogroup RCC_Private_Functions + * @{ + */ +/** + * @brief Update number of Flash wait states in line with MSI range and current + voltage range. + * @param msirange MSI range value from RCC_MSIRANGE_0 to RCC_MSIRANGE_11 + * @retval HAL status + */ +static HAL_StatusTypeDef RCC_SetFlashLatencyFromMSIRange(uint32_t msirange) +{ + uint32_t vos = 0; + uint32_t latency = FLASH_LATENCY_0; /* default value 0WS */ + + if(__HAL_RCC_PWR_IS_CLK_ENABLED()) + { + vos = HAL_PWREx_GetVoltageRange(); + } + else + { + __HAL_RCC_PWR_CLK_ENABLE(); + vos = HAL_PWREx_GetVoltageRange(); + __HAL_RCC_PWR_CLK_DISABLE(); + } + + if(vos == PWR_REGULATOR_VOLTAGE_SCALE1) + { + if(msirange > RCC_MSIRANGE_8) + { + /* MSI > 16Mhz */ + if(msirange > RCC_MSIRANGE_10) + { + /* MSI 48Mhz */ + latency = FLASH_LATENCY_2; /* 2WS */ + } + else + { + /* MSI 24Mhz or 32Mhz */ + latency = FLASH_LATENCY_1; /* 1WS */ + } + } + /* else MSI <= 16Mhz default FLASH_LATENCY_0 0WS */ + } + else + { +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + if(msirange >= RCC_MSIRANGE_8) + { + /* MSI >= 16Mhz */ + latency = FLASH_LATENCY_2; /* 2WS */ + } + else + { + if(msirange == RCC_MSIRANGE_7) + { + /* MSI 8Mhz */ + latency = FLASH_LATENCY_1; /* 1WS */ + } + /* else MSI < 8Mhz default FLASH_LATENCY_0 0WS */ + } +#else + if(msirange > RCC_MSIRANGE_8) + { + /* MSI > 16Mhz */ + latency = FLASH_LATENCY_3; /* 3WS */ + } + else + { + if(msirange == RCC_MSIRANGE_8) + { + /* MSI 16Mhz */ + latency = FLASH_LATENCY_2; /* 2WS */ + } + else if(msirange == RCC_MSIRANGE_7) + { + /* MSI 8Mhz */ + latency = FLASH_LATENCY_1; /* 1WS */ + } + /* else MSI < 8Mhz default FLASH_LATENCY_0 0WS */ + } +#endif + } + + __HAL_FLASH_SET_LATENCY(latency); + + /* Check that the new number of wait states is taken into account to access the Flash + memory by reading the FLASH_ACR register */ + if(READ_BIT(FLASH->ACR, FLASH_ACR_LATENCY) != latency) + { + return HAL_ERROR; + } + + return HAL_OK; +} + +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +/** + * @brief Compute SYSCLK frequency based on PLL SYSCLK source. + * @retval SYSCLK frequency + */ +static uint32_t RCC_GetSysClockFreqFromPLLSource(void) +{ + uint32_t msirange = 0U, pllvco = 0U, pllsource = 0U, pllr = 2U, pllm = 2U; + uint32_t sysclockfreq = 0U; + + if(__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_MSI) + { + /* Get MSI range source */ + if(READ_BIT(RCC->CR, RCC_CR_MSIRGSEL) == RESET) + { /* MSISRANGE from RCC_CSR applies */ + msirange = READ_BIT(RCC->CSR, RCC_CSR_MSISRANGE) >> RCC_CSR_MSISRANGE_Pos; + } + else + { /* MSIRANGE from RCC_CR applies */ + msirange = READ_BIT(RCC->CR, RCC_CR_MSIRANGE) >> RCC_CR_MSIRANGE_Pos; + } + /*MSI frequency range in HZ*/ + msirange = MSIRangeTable[msirange]; + } + + /* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLN + SYSCLK = PLL_VCO / PLLR + */ + pllsource = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC); + pllm = (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U ; + + switch (pllsource) + { + case RCC_PLLSOURCE_HSI: /* HSI used as PLL clock source */ + pllvco = (HSI_VALUE / pllm) * (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos); + break; + + case RCC_PLLSOURCE_HSE: /* HSE used as PLL clock source */ + pllvco = (HSE_VALUE / pllm) * (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos); + break; + + case RCC_PLLSOURCE_MSI: /* MSI used as PLL clock source */ + default: + pllvco = (msirange / pllm) * (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos); + break; + } + + pllr = ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLR) >> RCC_PLLCFGR_PLLR_Pos) + 1U ) * 2U; + sysclockfreq = pllvco/pllr; + + return sysclockfreq; +} +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +/** + * @} + */ + +#endif /* HAL_RCC_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rcc_ex.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rcc_ex.c new file mode 100644 index 0000000..7c31e73 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rcc_ex.c @@ -0,0 +1,3358 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_rcc_ex.c + * @author MCD Application Team + * @brief Extended RCC HAL module driver. + * This file provides firmware functions to manage the following + * functionalities RCC extended peripheral: + * + Extended Peripheral Control functions + * + Extended Clock management functions + * + Extended Clock Recovery System Control functions + * + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup RCCEx RCCEx + * @brief RCC Extended HAL module driver + * @{ + */ + +#ifdef HAL_RCC_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private defines -----------------------------------------------------------*/ +/** @defgroup RCCEx_Private_Constants RCCEx Private Constants + * @{ + */ +#define PLLSAI1_TIMEOUT_VALUE 2U /* 2 ms (minimum Tick + 1) */ +#define PLLSAI2_TIMEOUT_VALUE 2U /* 2 ms (minimum Tick + 1) */ +#define PLL_TIMEOUT_VALUE 2U /* 2 ms (minimum Tick + 1) */ + +#define DIVIDER_P_UPDATE 0U +#define DIVIDER_Q_UPDATE 1U +#define DIVIDER_R_UPDATE 2U + +#define __LSCO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE() +#define LSCO_GPIO_PORT GPIOA +#define LSCO_PIN GPIO_PIN_2 +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/** @defgroup RCCEx_Private_Functions RCCEx Private Functions + * @{ + */ +static HAL_StatusTypeDef RCCEx_PLLSAI1_Config(RCC_PLLSAI1InitTypeDef *PllSai1, uint32_t Divider); + +#if defined(RCC_PLLSAI2_SUPPORT) + +static HAL_StatusTypeDef RCCEx_PLLSAI2_Config(RCC_PLLSAI2InitTypeDef *PllSai2, uint32_t Divider); + +#endif /* RCC_PLLSAI2_SUPPORT */ + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup RCCEx_Exported_Functions RCCEx Exported Functions + * @{ + */ + +/** @defgroup RCCEx_Exported_Functions_Group1 Extended Peripheral Control functions + * @brief Extended Peripheral Control functions + * +@verbatim + =============================================================================== + ##### Extended Peripheral Control functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to control the RCC Clocks + frequencies. + [..] + (@) Important note: Care must be taken when HAL_RCCEx_PeriphCLKConfig() is used to + select the RTC clock source; in this case the Backup domain will be reset in + order to modify the RTC Clock source, as consequence RTC registers (including + the backup registers) are set to their reset values. + +@endverbatim + * @{ + */ +/** + * @brief Initialize the RCC extended peripherals clocks according to the specified + * parameters in the RCC_PeriphCLKInitTypeDef. + * @param PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that + * contains a field PeriphClockSelection which can be a combination of the following values: + * @arg @ref RCC_PERIPHCLK_RTC RTC peripheral clock + * @arg @ref RCC_PERIPHCLK_ADC ADC peripheral clock + @if STM32L462xx + * @arg @ref RCC_PERIPHCLK_DFSDM1 DFSDM1 peripheral clock (only for devices with DFSDM1) + @endif + @if STM32L486xx + * @arg @ref RCC_PERIPHCLK_DFSDM1 DFSDM1 peripheral clock (only for devices with DFSDM1) + @endif + @if STM32L4A6xx + * @arg @ref RCC_PERIPHCLK_DFSDM1 DFSDM1 peripheral clock (only for devices with DFSDM1) + @endif + * @arg @ref RCC_PERIPHCLK_I2C1 I2C1 peripheral clock + * @arg @ref RCC_PERIPHCLK_I2C2 I2C2 peripheral clock + * @arg @ref RCC_PERIPHCLK_I2C3 I2C3 peripheral clock + @if STM32L462xx + * @arg @ref RCC_PERIPHCLK_I2C4 I2C4 peripheral clock (only for devices with I2C4) + @endif + @if STM32L4A6xx + * @arg @ref RCC_PERIPHCLK_I2C4 I2C4 peripheral clock (only for devices with I2C4) + @endif + @if STM32L4S9xx + * @arg @ref RCC_PERIPHCLK_I2C4 I2C4 peripheral clock (only for devices with I2C4) + @endif + * @arg @ref RCC_PERIPHCLK_LPTIM1 LPTIM1 peripheral clock + * @arg @ref RCC_PERIPHCLK_LPTIM2 LPTIM2 peripheral clock + * @arg @ref RCC_PERIPHCLK_LPUART1 LPUART1 peripheral clock + * @arg @ref RCC_PERIPHCLK_RNG RNG peripheral clock + * @arg @ref RCC_PERIPHCLK_SAI1 SAI1 peripheral clock + @if STM32L486xx + * @arg @ref RCC_PERIPHCLK_SAI2 SAI2 peripheral clock (only for devices with SAI2) + @endif + @if STM32L4A6xx + * @arg @ref RCC_PERIPHCLK_SAI2 SAI2 peripheral clock (only for devices with SAI2) + @endif + @if STM32L4S9xx + * @arg @ref RCC_PERIPHCLK_SAI2 SAI2 peripheral clock (only for devices with SAI2) + @endif + * @arg @ref RCC_PERIPHCLK_SDMMC1 SDMMC1 peripheral clock + @if STM32L443xx + * @arg @ref RCC_PERIPHCLK_SWPMI1 SWPMI1 peripheral clock (only for devices with SWPMI1) + @endif + @if STM32L486xx + * @arg @ref RCC_PERIPHCLK_SWPMI1 SWPMI1 peripheral clock (only for devices with SWPMI1) + @endif + @if STM32L4A6xx + * @arg @ref RCC_PERIPHCLK_SWPMI1 SWPMI1 peripheral clock (only for devices with SWPMI1) + @endif + * @arg @ref RCC_PERIPHCLK_USART1 USART1 peripheral clock + * @arg @ref RCC_PERIPHCLK_USART2 USART1 peripheral clock + * @arg @ref RCC_PERIPHCLK_USART3 USART1 peripheral clock + @if STM32L462xx + * @arg @ref RCC_PERIPHCLK_UART4 USART1 peripheral clock (only for devices with UART4) + @endif + @if STM32L486xx + * @arg @ref RCC_PERIPHCLK_UART4 USART1 peripheral clock (only for devices with UART4) + * @arg @ref RCC_PERIPHCLK_UART5 USART1 peripheral clock (only for devices with UART5) + * @arg @ref RCC_PERIPHCLK_USB USB peripheral clock (only for devices with USB) + @endif + @if STM32L4A6xx + * @arg @ref RCC_PERIPHCLK_UART4 USART1 peripheral clock (only for devices with UART4) + * @arg @ref RCC_PERIPHCLK_UART5 USART1 peripheral clock (only for devices with UART5) + * @arg @ref RCC_PERIPHCLK_USB USB peripheral clock (only for devices with USB) + @endif + @if STM32L4S9xx + * @arg @ref RCC_PERIPHCLK_UART4 USART1 peripheral clock (only for devices with UART4) + * @arg @ref RCC_PERIPHCLK_UART5 USART1 peripheral clock (only for devices with UART5) + * @arg @ref RCC_PERIPHCLK_USB USB peripheral clock (only for devices with USB) + * @arg @ref RCC_PERIPHCLK_DFSDM1 DFSDM1 peripheral kernel clock (only for devices with DFSDM1) + * @arg @ref RCC_PERIPHCLK_DFSDM1AUDIO DFSDM1 peripheral audio clock (only for devices with DFSDM1) + * @arg @ref RCC_PERIPHCLK_LTDC LTDC peripheral clock (only for devices with LTDC) + * @arg @ref RCC_PERIPHCLK_DSI DSI peripheral clock (only for devices with DSI) + * @arg @ref RCC_PERIPHCLK_OSPI OctoSPI peripheral clock (only for devices with OctoSPI) + @endif + * + * @note Care must be taken when HAL_RCCEx_PeriphCLKConfig() is used to select + * the RTC clock source: in this case the access to Backup domain is enabled. + * + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit) +{ + uint32_t tmpregister = 0; + uint32_t tickstart = 0U; + HAL_StatusTypeDef ret = HAL_OK; /* Intermediate status */ + HAL_StatusTypeDef status = HAL_OK; /* Final status */ + + /* Check the parameters */ + assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection)); + + /*-------------------------- SAI1 clock source configuration ---------------------*/ + if((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1)) + { + /* Check the parameters */ + assert_param(IS_RCC_SAI1CLK(PeriphClkInit->Sai1ClockSelection)); + + switch(PeriphClkInit->Sai1ClockSelection) + { + case RCC_SAI1CLKSOURCE_PLL: /* PLL is used as clock source for SAI1*/ + /* Enable SAI Clock output generated form System PLL . */ +#if defined(RCC_PLLSAI2_SUPPORT) + __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_SAI3CLK); +#else + __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_SAI2CLK); +#endif /* RCC_PLLSAI2_SUPPORT */ + /* SAI1 clock source config set later after clock selection check */ + break; + + case RCC_SAI1CLKSOURCE_PLLSAI1: /* PLLSAI1 is used as clock source for SAI1*/ + /* PLLSAI1 input clock, parameters M, N & P configuration and clock output (PLLSAI1ClockOut) */ + ret = RCCEx_PLLSAI1_Config(&(PeriphClkInit->PLLSAI1), DIVIDER_P_UPDATE); + /* SAI1 clock source config set later after clock selection check */ + break; + +#if defined(RCC_PLLSAI2_SUPPORT) + + case RCC_SAI1CLKSOURCE_PLLSAI2: /* PLLSAI2 is used as clock source for SAI1*/ + /* PLLSAI2 input clock, parameters M, N & P configuration clock output (PLLSAI2ClockOut) */ + ret = RCCEx_PLLSAI2_Config(&(PeriphClkInit->PLLSAI2), DIVIDER_P_UPDATE); + /* SAI1 clock source config set later after clock selection check */ + break; + +#endif /* RCC_PLLSAI2_SUPPORT */ + + case RCC_SAI1CLKSOURCE_PIN: /* External clock is used as source of SAI1 clock*/ +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + case RCC_SAI1CLKSOURCE_HSI: /* HSI is used as source of SAI1 clock*/ +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + /* SAI1 clock source config set later after clock selection check */ + break; + + default: + ret = HAL_ERROR; + break; + } + + if(ret == HAL_OK) + { + /* Set the source of SAI1 clock*/ + __HAL_RCC_SAI1_CONFIG(PeriphClkInit->Sai1ClockSelection); + } + else + { + /* set overall return value */ + status = ret; + } + } + +#if defined(SAI2) + + /*-------------------------- SAI2 clock source configuration ---------------------*/ + if((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI2) == RCC_PERIPHCLK_SAI2)) + { + /* Check the parameters */ + assert_param(IS_RCC_SAI2CLK(PeriphClkInit->Sai2ClockSelection)); + + switch(PeriphClkInit->Sai2ClockSelection) + { + case RCC_SAI2CLKSOURCE_PLL: /* PLL is used as clock source for SAI2*/ + /* Enable SAI Clock output generated form System PLL . */ + __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_SAI3CLK); + /* SAI2 clock source config set later after clock selection check */ + break; + + case RCC_SAI2CLKSOURCE_PLLSAI1: /* PLLSAI1 is used as clock source for SAI2*/ + /* PLLSAI1 input clock, parameters M, N & P configuration and clock output (PLLSAI1ClockOut) */ + ret = RCCEx_PLLSAI1_Config(&(PeriphClkInit->PLLSAI1), DIVIDER_P_UPDATE); + /* SAI2 clock source config set later after clock selection check */ + break; + + case RCC_SAI2CLKSOURCE_PLLSAI2: /* PLLSAI2 is used as clock source for SAI2*/ + /* PLLSAI2 input clock, parameters M, N & P configuration and clock output (PLLSAI2ClockOut) */ + ret = RCCEx_PLLSAI2_Config(&(PeriphClkInit->PLLSAI2), DIVIDER_P_UPDATE); + /* SAI2 clock source config set later after clock selection check */ + break; + + case RCC_SAI2CLKSOURCE_PIN: /* External clock is used as source of SAI2 clock*/ +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + case RCC_SAI2CLKSOURCE_HSI: /* HSI is used as source of SAI2 clock*/ +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + /* SAI2 clock source config set later after clock selection check */ + break; + + default: + ret = HAL_ERROR; + break; + } + + if(ret == HAL_OK) + { + /* Set the source of SAI2 clock*/ + __HAL_RCC_SAI2_CONFIG(PeriphClkInit->Sai2ClockSelection); + } + else + { + /* set overall return value */ + status = ret; + } + } +#endif /* SAI2 */ + + /*-------------------------- RTC clock source configuration ----------------------*/ + if((PeriphClkInit->PeriphClockSelection & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC) + { + FlagStatus pwrclkchanged = RESET; + + /* Check for RTC Parameters used to output RTCCLK */ + assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection)); + + /* Enable Power Clock */ + if(__HAL_RCC_PWR_IS_CLK_DISABLED()) + { + __HAL_RCC_PWR_CLK_ENABLE(); + pwrclkchanged = SET; + } + + /* Enable write access to Backup domain */ + SET_BIT(PWR->CR1, PWR_CR1_DBP); + + /* Wait for Backup domain Write protection disable */ + tickstart = HAL_GetTick(); + + while(READ_BIT(PWR->CR1, PWR_CR1_DBP) == RESET) + { + if((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE) + { + ret = HAL_TIMEOUT; + break; + } + } + + if(ret == HAL_OK) + { + /* Reset the Backup domain only if the RTC Clock source selection is modified from default */ + tmpregister = READ_BIT(RCC->BDCR, RCC_BDCR_RTCSEL); + + if((tmpregister != RCC_RTCCLKSOURCE_NONE) && (tmpregister != PeriphClkInit->RTCClockSelection)) + { + /* Store the content of BDCR register before the reset of Backup Domain */ + tmpregister = READ_BIT(RCC->BDCR, ~(RCC_BDCR_RTCSEL)); + /* RTC Clock selection can be changed only if the Backup Domain is reset */ + __HAL_RCC_BACKUPRESET_FORCE(); + __HAL_RCC_BACKUPRESET_RELEASE(); + /* Restore the Content of BDCR register */ + RCC->BDCR = tmpregister; + } + + /* Wait for LSE reactivation if LSE was enable prior to Backup Domain reset */ + if (HAL_IS_BIT_SET(tmpregister, RCC_BDCR_LSEON)) + { + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till LSE is ready */ + while(READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) == RESET) + { + if((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE) + { + ret = HAL_TIMEOUT; + break; + } + } + } + + if(ret == HAL_OK) + { + /* Apply new RTC clock source selection */ + __HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection); + } + else + { + /* set overall return value */ + status = ret; + } + } + else + { + /* set overall return value */ + status = ret; + } + + /* Restore clock configuration if changed */ + if(pwrclkchanged == SET) + { + __HAL_RCC_PWR_CLK_DISABLE(); + } + } + + /*-------------------------- USART1 clock source configuration -------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_USART1) == RCC_PERIPHCLK_USART1) + { + /* Check the parameters */ + assert_param(IS_RCC_USART1CLKSOURCE(PeriphClkInit->Usart1ClockSelection)); + + /* Configure the USART1 clock source */ + __HAL_RCC_USART1_CONFIG(PeriphClkInit->Usart1ClockSelection); + } + + /*-------------------------- USART2 clock source configuration -------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_USART2) == RCC_PERIPHCLK_USART2) + { + /* Check the parameters */ + assert_param(IS_RCC_USART2CLKSOURCE(PeriphClkInit->Usart2ClockSelection)); + + /* Configure the USART2 clock source */ + __HAL_RCC_USART2_CONFIG(PeriphClkInit->Usart2ClockSelection); + } + +#if defined(USART3) + + /*-------------------------- USART3 clock source configuration -------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_USART3) == RCC_PERIPHCLK_USART3) + { + /* Check the parameters */ + assert_param(IS_RCC_USART3CLKSOURCE(PeriphClkInit->Usart3ClockSelection)); + + /* Configure the USART3 clock source */ + __HAL_RCC_USART3_CONFIG(PeriphClkInit->Usart3ClockSelection); + } + +#endif /* USART3 */ + +#if defined(UART4) + + /*-------------------------- UART4 clock source configuration --------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_UART4) == RCC_PERIPHCLK_UART4) + { + /* Check the parameters */ + assert_param(IS_RCC_UART4CLKSOURCE(PeriphClkInit->Uart4ClockSelection)); + + /* Configure the UART4 clock source */ + __HAL_RCC_UART4_CONFIG(PeriphClkInit->Uart4ClockSelection); + } + +#endif /* UART4 */ + +#if defined(UART5) + + /*-------------------------- UART5 clock source configuration --------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_UART5) == RCC_PERIPHCLK_UART5) + { + /* Check the parameters */ + assert_param(IS_RCC_UART5CLKSOURCE(PeriphClkInit->Uart5ClockSelection)); + + /* Configure the UART5 clock source */ + __HAL_RCC_UART5_CONFIG(PeriphClkInit->Uart5ClockSelection); + } + +#endif /* UART5 */ + + /*-------------------------- LPUART1 clock source configuration ------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LPUART1) == RCC_PERIPHCLK_LPUART1) + { + /* Check the parameters */ + assert_param(IS_RCC_LPUART1CLKSOURCE(PeriphClkInit->Lpuart1ClockSelection)); + + /* Configure the LPUAR1 clock source */ + __HAL_RCC_LPUART1_CONFIG(PeriphClkInit->Lpuart1ClockSelection); + } + + /*-------------------------- LPTIM1 clock source configuration -------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LPTIM1) == (RCC_PERIPHCLK_LPTIM1)) + { + assert_param(IS_RCC_LPTIM1CLK(PeriphClkInit->Lptim1ClockSelection)); + __HAL_RCC_LPTIM1_CONFIG(PeriphClkInit->Lptim1ClockSelection); + } + + /*-------------------------- LPTIM2 clock source configuration -------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LPTIM2) == (RCC_PERIPHCLK_LPTIM2)) + { + assert_param(IS_RCC_LPTIM2CLK(PeriphClkInit->Lptim2ClockSelection)); + __HAL_RCC_LPTIM2_CONFIG(PeriphClkInit->Lptim2ClockSelection); + } + + /*-------------------------- I2C1 clock source configuration ---------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2C1) == RCC_PERIPHCLK_I2C1) + { + /* Check the parameters */ + assert_param(IS_RCC_I2C1CLKSOURCE(PeriphClkInit->I2c1ClockSelection)); + + /* Configure the I2C1 clock source */ + __HAL_RCC_I2C1_CONFIG(PeriphClkInit->I2c1ClockSelection); + } + +#if defined(I2C2) + + /*-------------------------- I2C2 clock source configuration ---------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2C2) == RCC_PERIPHCLK_I2C2) + { + /* Check the parameters */ + assert_param(IS_RCC_I2C2CLKSOURCE(PeriphClkInit->I2c2ClockSelection)); + + /* Configure the I2C2 clock source */ + __HAL_RCC_I2C2_CONFIG(PeriphClkInit->I2c2ClockSelection); + } + +#endif /* I2C2 */ + + /*-------------------------- I2C3 clock source configuration ---------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2C3) == RCC_PERIPHCLK_I2C3) + { + /* Check the parameters */ + assert_param(IS_RCC_I2C3CLKSOURCE(PeriphClkInit->I2c3ClockSelection)); + + /* Configure the I2C3 clock source */ + __HAL_RCC_I2C3_CONFIG(PeriphClkInit->I2c3ClockSelection); + } + +#if defined(I2C4) + + /*-------------------------- I2C4 clock source configuration ---------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2C4) == RCC_PERIPHCLK_I2C4) + { + /* Check the parameters */ + assert_param(IS_RCC_I2C4CLKSOURCE(PeriphClkInit->I2c4ClockSelection)); + + /* Configure the I2C4 clock source */ + __HAL_RCC_I2C4_CONFIG(PeriphClkInit->I2c4ClockSelection); + } + +#endif /* I2C4 */ + +#if defined(USB_OTG_FS) || defined(USB) + + /*-------------------------- USB clock source configuration ----------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_USB) == (RCC_PERIPHCLK_USB)) + { + assert_param(IS_RCC_USBCLKSOURCE(PeriphClkInit->UsbClockSelection)); + __HAL_RCC_USB_CONFIG(PeriphClkInit->UsbClockSelection); + + if(PeriphClkInit->UsbClockSelection == RCC_USBCLKSOURCE_PLL) + { + /* Enable PLL48M1CLK output */ + __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_48M1CLK); + } + else + { + if(PeriphClkInit->UsbClockSelection == RCC_USBCLKSOURCE_PLLSAI1) + { + /* PLLSAI1 input clock, parameters M, N & Q configuration and clock output (PLLSAI1ClockOut) */ + ret = RCCEx_PLLSAI1_Config(&(PeriphClkInit->PLLSAI1), DIVIDER_Q_UPDATE); + + if(ret != HAL_OK) + { + /* set overall return value */ + status = ret; + } + } + } + } + +#endif /* USB_OTG_FS || USB */ + +#if defined(SDMMC1) + + /*-------------------------- SDMMC1 clock source configuration -------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SDMMC1) == (RCC_PERIPHCLK_SDMMC1)) + { + assert_param(IS_RCC_SDMMC1CLKSOURCE(PeriphClkInit->Sdmmc1ClockSelection)); + __HAL_RCC_SDMMC1_CONFIG(PeriphClkInit->Sdmmc1ClockSelection); + + if(PeriphClkInit->Sdmmc1ClockSelection == RCC_SDMMC1CLKSOURCE_PLL) /* PLL "Q" ? */ + { + /* Enable PLL48M1CLK output */ + __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_48M1CLK); + } +#if defined(RCC_CCIPR2_SDMMCSEL) + else if(PeriphClkInit->Sdmmc1ClockSelection == RCC_SDMMC1CLKSOURCE_PLLP) /* PLL "P" ? */ + { + /* Enable PLLSAI3CLK output */ + __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_SAI3CLK); + } +#endif + else if(PeriphClkInit->Sdmmc1ClockSelection == RCC_SDMMC1CLKSOURCE_PLLSAI1) + { + /* PLLSAI1 input clock, parameters M, N & Q configuration and clock output (PLLSAI1ClockOut) */ + ret = RCCEx_PLLSAI1_Config(&(PeriphClkInit->PLLSAI1), DIVIDER_Q_UPDATE); + + if(ret != HAL_OK) + { + /* set overall return value */ + status = ret; + } + } + } + +#endif /* SDMMC1 */ + + /*-------------------------- RNG clock source configuration ----------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RNG) == (RCC_PERIPHCLK_RNG)) + { + assert_param(IS_RCC_RNGCLKSOURCE(PeriphClkInit->RngClockSelection)); + __HAL_RCC_RNG_CONFIG(PeriphClkInit->RngClockSelection); + + if(PeriphClkInit->RngClockSelection == RCC_RNGCLKSOURCE_PLL) + { + /* Enable PLL48M1CLK output */ + __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_48M1CLK); + } + else if(PeriphClkInit->RngClockSelection == RCC_RNGCLKSOURCE_PLLSAI1) + { + /* PLLSAI1 input clock, parameters M, N & Q configuration and clock output (PLLSAI1ClockOut) */ + ret = RCCEx_PLLSAI1_Config(&(PeriphClkInit->PLLSAI1), DIVIDER_Q_UPDATE); + + if(ret != HAL_OK) + { + /* set overall return value */ + status = ret; + } + } + } + + /*-------------------------- ADC clock source configuration ----------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_ADC) == RCC_PERIPHCLK_ADC) + { + /* Check the parameters */ + assert_param(IS_RCC_ADCCLKSOURCE(PeriphClkInit->AdcClockSelection)); + + /* Configure the ADC interface clock source */ + __HAL_RCC_ADC_CONFIG(PeriphClkInit->AdcClockSelection); + + if(PeriphClkInit->AdcClockSelection == RCC_ADCCLKSOURCE_PLLSAI1) + { + /* PLLSAI1 input clock, parameters M, N & R configuration and clock output (PLLSAI1ClockOut) */ + ret = RCCEx_PLLSAI1_Config(&(PeriphClkInit->PLLSAI1), DIVIDER_R_UPDATE); + + if(ret != HAL_OK) + { + /* set overall return value */ + status = ret; + } + } + +#if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || defined(STM32L496xx) || defined(STM32L4A6xx) + + else if(PeriphClkInit->AdcClockSelection == RCC_ADCCLKSOURCE_PLLSAI2) + { + /* PLLSAI2 input clock, parameters M, N & R configuration and clock output (PLLSAI2ClockOut) */ + ret = RCCEx_PLLSAI2_Config(&(PeriphClkInit->PLLSAI2), DIVIDER_R_UPDATE); + + if(ret != HAL_OK) + { + /* set overall return value */ + status = ret; + } + } + +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || STM32L496xx || STM32L4A6xx */ + + } + +#if defined(SWPMI1) + + /*-------------------------- SWPMI1 clock source configuration -------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SWPMI1) == RCC_PERIPHCLK_SWPMI1) + { + /* Check the parameters */ + assert_param(IS_RCC_SWPMI1CLKSOURCE(PeriphClkInit->Swpmi1ClockSelection)); + + /* Configure the SWPMI1 clock source */ + __HAL_RCC_SWPMI1_CONFIG(PeriphClkInit->Swpmi1ClockSelection); + } + +#endif /* SWPMI1 */ + +#if defined(DFSDM1_Filter0) + + /*-------------------------- DFSDM1 clock source configuration -------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_DFSDM1) == RCC_PERIPHCLK_DFSDM1) + { + /* Check the parameters */ + assert_param(IS_RCC_DFSDM1CLKSOURCE(PeriphClkInit->Dfsdm1ClockSelection)); + + /* Configure the DFSDM1 interface clock source */ + __HAL_RCC_DFSDM1_CONFIG(PeriphClkInit->Dfsdm1ClockSelection); + } + +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + /*-------------------------- DFSDM1 audio clock source configuration -------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_DFSDM1AUDIO) == RCC_PERIPHCLK_DFSDM1AUDIO) + { + /* Check the parameters */ + assert_param(IS_RCC_DFSDM1AUDIOCLKSOURCE(PeriphClkInit->Dfsdm1AudioClockSelection)); + + /* Configure the DFSDM1 interface audio clock source */ + __HAL_RCC_DFSDM1AUDIO_CONFIG(PeriphClkInit->Dfsdm1AudioClockSelection); + } + +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#endif /* DFSDM1_Filter0 */ + +#if defined(LTDC) + + /*-------------------------- LTDC clock source configuration --------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LTDC) == RCC_PERIPHCLK_LTDC) + { + /* Check the parameters */ + assert_param(IS_RCC_LTDCCLKSOURCE(PeriphClkInit->LtdcClockSelection)); + + /* Disable the PLLSAI2 */ + __HAL_RCC_PLLSAI2_DISABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till PLLSAI2 is ready */ + while(READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) != RESET) + { + if((HAL_GetTick() - tickstart) > PLLSAI2_TIMEOUT_VALUE) + { + ret = HAL_TIMEOUT; + break; + } + } + + if(ret == HAL_OK) + { + /* Configure the LTDC clock source */ + __HAL_RCC_LTDC_CONFIG(PeriphClkInit->LtdcClockSelection); + + /* PLLSAI2 input clock, parameters M, N & R configuration and clock output (PLLSAI2ClockOut) */ + ret = RCCEx_PLLSAI2_Config(&(PeriphClkInit->PLLSAI2), DIVIDER_R_UPDATE); + } + + if(ret != HAL_OK) + { + /* set overall return value */ + status = ret; + } + } + +#endif /* LTDC */ + +#if defined(DSI) + + /*-------------------------- DSI clock source configuration ---------------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_DSI) == RCC_PERIPHCLK_DSI) + { + /* Check the parameters */ + assert_param(IS_RCC_DSICLKSOURCE(PeriphClkInit->DsiClockSelection)); + + /* Configure the DSI clock source */ + __HAL_RCC_DSI_CONFIG(PeriphClkInit->DsiClockSelection); + + if(PeriphClkInit->DsiClockSelection == RCC_DSICLKSOURCE_PLLSAI2) + { + /* PLLSAI2 input clock, parameters M, N & Q configuration and clock output (PLLSAI2ClockOut) */ + ret = RCCEx_PLLSAI2_Config(&(PeriphClkInit->PLLSAI2), DIVIDER_Q_UPDATE); + + if(ret != HAL_OK) + { + /* set overall return value */ + status = ret; + } + } + } + +#endif /* DSI */ + +#if defined(OCTOSPI1) || defined(OCTOSPI2) + + /*-------------------------- OctoSPIx clock source configuration ----------------*/ + if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_OSPI) == RCC_PERIPHCLK_OSPI) + { + /* Check the parameters */ + assert_param(IS_RCC_OSPICLKSOURCE(PeriphClkInit->OspiClockSelection)); + + /* Configure the OctoSPI clock source */ + __HAL_RCC_OSPI_CONFIG(PeriphClkInit->OspiClockSelection); + + if(PeriphClkInit->OspiClockSelection == RCC_OSPICLKSOURCE_PLL) + { + /* Enable PLL48M1CLK output */ + __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_48M1CLK); + } + } + +#endif /* OCTOSPI1 || OCTOSPI2 */ + + return status; +} + +/** + * @brief Get the RCC_ClkInitStruct according to the internal RCC configuration registers. + * @param PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that + * returns the configuration information for the Extended Peripherals + * clocks(SAI1, SAI2, LPTIM1, LPTIM2, I2C1, I2C2, I2C3, I2C4, LPUART, + * USART1, USART2, USART3, UART4, UART5, RTC, ADCx, DFSDMx, SWPMI1, USB, SDMMC1 and RNG). + * @retval None + */ +void HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit) +{ + /* Set all possible values for the extended clock type parameter------------*/ + +#if defined(STM32L431xx) + + PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | \ + RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 | RCC_PERIPHCLK_I2C3 | \ + RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_SAI1 | \ + RCC_PERIPHCLK_SDMMC1 | RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_SWPMI1 | \ + RCC_PERIPHCLK_RTC ; + +#elif defined(STM32L432xx) || defined(STM32L442xx) + + PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | \ + RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C3 | \ + RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_SAI1 | RCC_PERIPHCLK_USB | \ + RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_SWPMI1 | \ + RCC_PERIPHCLK_RTC ; + +#elif defined(STM32L433xx) || defined(STM32L443xx) + + PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | \ + RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 | RCC_PERIPHCLK_I2C3 | \ + RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_SAI1 | RCC_PERIPHCLK_USB | \ + RCC_PERIPHCLK_SDMMC1 | RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_SWPMI1 | \ + RCC_PERIPHCLK_RTC ; + +#elif defined(STM32L451xx) + + PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | RCC_PERIPHCLK_UART4 | \ + RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 | RCC_PERIPHCLK_I2C3 | RCC_PERIPHCLK_I2C4 | \ + RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_SAI1 | \ + RCC_PERIPHCLK_SDMMC1 | RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_DFSDM1 | \ + RCC_PERIPHCLK_RTC ; + +#elif defined(STM32L452xx) || defined(STM32L462xx) + + PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | RCC_PERIPHCLK_UART4 | \ + RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 | RCC_PERIPHCLK_I2C3 | RCC_PERIPHCLK_I2C4 | \ + RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_SAI1 | RCC_PERIPHCLK_USB | \ + RCC_PERIPHCLK_SDMMC1 | RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_DFSDM1 | \ + RCC_PERIPHCLK_RTC ; + +#elif defined(STM32L471xx) + + PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | RCC_PERIPHCLK_UART4 | RCC_PERIPHCLK_UART5 | \ + RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 | RCC_PERIPHCLK_I2C3 | \ + RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_SAI1 | RCC_PERIPHCLK_SAI2 | \ + RCC_PERIPHCLK_SDMMC1 | RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_SWPMI1 | RCC_PERIPHCLK_DFSDM1 | \ + RCC_PERIPHCLK_RTC ; + +#elif defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) + + PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | RCC_PERIPHCLK_UART4 | RCC_PERIPHCLK_UART5 | \ + RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 | RCC_PERIPHCLK_I2C3 | \ + RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_SAI1 | RCC_PERIPHCLK_SAI2 | RCC_PERIPHCLK_USB | \ + RCC_PERIPHCLK_SDMMC1 | RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_SWPMI1 | RCC_PERIPHCLK_DFSDM1 | \ + RCC_PERIPHCLK_RTC ; + +#elif defined(STM32L496xx) || defined(STM32L4A6xx) + + PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | RCC_PERIPHCLK_UART4 | RCC_PERIPHCLK_UART5 | \ + RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 | RCC_PERIPHCLK_I2C3 | RCC_PERIPHCLK_I2C4 | \ + RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_SAI1 | RCC_PERIPHCLK_SAI2 | RCC_PERIPHCLK_USB | \ + RCC_PERIPHCLK_SDMMC1 | RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_SWPMI1 | RCC_PERIPHCLK_DFSDM1 | \ + RCC_PERIPHCLK_RTC ; + +#elif defined(STM32L4R5xx) || defined(STM32L4S5xx) + + PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | RCC_PERIPHCLK_UART4 | RCC_PERIPHCLK_UART5 | \ + RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 | RCC_PERIPHCLK_I2C3 | RCC_PERIPHCLK_I2C4 | \ + RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_SAI1 | RCC_PERIPHCLK_SAI2 | RCC_PERIPHCLK_USB | \ + RCC_PERIPHCLK_SDMMC1 | RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_DFSDM1 | \ + RCC_PERIPHCLK_DFSDM1AUDIO | RCC_PERIPHCLK_RTC | RCC_PERIPHCLK_OSPI; + +#elif defined(STM32L4R7xx) || defined(STM32L4S7xx) + + PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | RCC_PERIPHCLK_UART4 | RCC_PERIPHCLK_UART5 | \ + RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 | RCC_PERIPHCLK_I2C3 | RCC_PERIPHCLK_I2C4 | \ + RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_SAI1 | RCC_PERIPHCLK_SAI2 | RCC_PERIPHCLK_USB | \ + RCC_PERIPHCLK_SDMMC1 | RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_DFSDM1 | \ + RCC_PERIPHCLK_DFSDM1AUDIO | RCC_PERIPHCLK_RTC | RCC_PERIPHCLK_OSPI | RCC_PERIPHCLK_LTDC; + +#elif defined(STM32L4R9xx) || defined(STM32L4S9xx) + + PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | RCC_PERIPHCLK_UART4 | RCC_PERIPHCLK_UART5 | \ + RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 | RCC_PERIPHCLK_I2C3 | RCC_PERIPHCLK_I2C4 | \ + RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_SAI1 | RCC_PERIPHCLK_SAI2 | RCC_PERIPHCLK_USB | \ + RCC_PERIPHCLK_SDMMC1 | RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_DFSDM1 | \ + RCC_PERIPHCLK_DFSDM1AUDIO | RCC_PERIPHCLK_RTC | RCC_PERIPHCLK_OSPI | RCC_PERIPHCLK_LTDC | RCC_PERIPHCLK_DSI; + +#endif /* STM32L431xx */ + + /* Get the PLLSAI1 Clock configuration -----------------------------------------------*/ + + PeriphClkInit->PLLSAI1.PLLSAI1Source = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC) >> RCC_PLLCFGR_PLLSRC_Pos; +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + PeriphClkInit->PLLSAI1.PLLSAI1M = (READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1M) >> RCC_PLLSAI1CFGR_PLLSAI1M_Pos) + 1U; +#else + PeriphClkInit->PLLSAI1.PLLSAI1M = (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U; +#endif /* RCC_PLLSAI1M_DIV_1_16_SUPPORT */ + PeriphClkInit->PLLSAI1.PLLSAI1N = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos; + PeriphClkInit->PLLSAI1.PLLSAI1P = ((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1P) >> RCC_PLLSAI1CFGR_PLLSAI1P_Pos) << 4U) + 7U; + PeriphClkInit->PLLSAI1.PLLSAI1Q = ((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1Q) >> RCC_PLLSAI1CFGR_PLLSAI1Q_Pos) + 1U) * 2U; + PeriphClkInit->PLLSAI1.PLLSAI1R = ((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1R) >> RCC_PLLSAI1CFGR_PLLSAI1R_Pos) + 1U) * 2U; + +#if defined(RCC_PLLSAI2_SUPPORT) + + /* Get the PLLSAI2 Clock configuration -----------------------------------------------*/ + + PeriphClkInit->PLLSAI2.PLLSAI2Source = PeriphClkInit->PLLSAI1.PLLSAI1Source; +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + PeriphClkInit->PLLSAI2.PLLSAI2M = (READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2M) >> RCC_PLLSAI2CFGR_PLLSAI2M_Pos) + 1U; +#else + PeriphClkInit->PLLSAI2.PLLSAI2M = PeriphClkInit->PLLSAI1.PLLSAI1M; +#endif /* RCC_PLLSAI2M_DIV_1_16_SUPPORT */ + PeriphClkInit->PLLSAI2.PLLSAI2N = READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2N) >> RCC_PLLSAI2CFGR_PLLSAI2N_Pos; + PeriphClkInit->PLLSAI2.PLLSAI2P = ((READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2P) >> RCC_PLLSAI2CFGR_PLLSAI2P_Pos) << 4U) + 7U; +#if defined(RCC_PLLSAI2Q_DIV_SUPPORT) + PeriphClkInit->PLLSAI2.PLLSAI2Q = ((READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2Q) >> RCC_PLLSAI2CFGR_PLLSAI2Q_Pos) + 1U) * 2U; +#endif /* RCC_PLLSAI2Q_DIV_SUPPORT */ + PeriphClkInit->PLLSAI2.PLLSAI2R = ((READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2R)>> RCC_PLLSAI2CFGR_PLLSAI2R_Pos) + 1U) * 2U; + +#endif /* RCC_PLLSAI2_SUPPORT */ + + /* Get the USART1 clock source ---------------------------------------------*/ + PeriphClkInit->Usart1ClockSelection = __HAL_RCC_GET_USART1_SOURCE(); + /* Get the USART2 clock source ---------------------------------------------*/ + PeriphClkInit->Usart2ClockSelection = __HAL_RCC_GET_USART2_SOURCE(); + +#if defined(USART3) + /* Get the USART3 clock source ---------------------------------------------*/ + PeriphClkInit->Usart3ClockSelection = __HAL_RCC_GET_USART3_SOURCE(); +#endif /* USART3 */ + +#if defined(UART4) + /* Get the UART4 clock source ----------------------------------------------*/ + PeriphClkInit->Uart4ClockSelection = __HAL_RCC_GET_UART4_SOURCE(); +#endif /* UART4 */ + +#if defined(UART5) + /* Get the UART5 clock source ----------------------------------------------*/ + PeriphClkInit->Uart5ClockSelection = __HAL_RCC_GET_UART5_SOURCE(); +#endif /* UART5 */ + + /* Get the LPUART1 clock source --------------------------------------------*/ + PeriphClkInit->Lpuart1ClockSelection = __HAL_RCC_GET_LPUART1_SOURCE(); + + /* Get the I2C1 clock source -----------------------------------------------*/ + PeriphClkInit->I2c1ClockSelection = __HAL_RCC_GET_I2C1_SOURCE(); + +#if defined(I2C2) + /* Get the I2C2 clock source ----------------------------------------------*/ + PeriphClkInit->I2c2ClockSelection = __HAL_RCC_GET_I2C2_SOURCE(); +#endif /* I2C2 */ + + /* Get the I2C3 clock source -----------------------------------------------*/ + PeriphClkInit->I2c3ClockSelection = __HAL_RCC_GET_I2C3_SOURCE(); + +#if defined(I2C4) + /* Get the I2C4 clock source -----------------------------------------------*/ + PeriphClkInit->I2c4ClockSelection = __HAL_RCC_GET_I2C4_SOURCE(); +#endif /* I2C4 */ + + /* Get the LPTIM1 clock source ---------------------------------------------*/ + PeriphClkInit->Lptim1ClockSelection = __HAL_RCC_GET_LPTIM1_SOURCE(); + + /* Get the LPTIM2 clock source ---------------------------------------------*/ + PeriphClkInit->Lptim2ClockSelection = __HAL_RCC_GET_LPTIM2_SOURCE(); + + /* Get the SAI1 clock source -----------------------------------------------*/ + PeriphClkInit->Sai1ClockSelection = __HAL_RCC_GET_SAI1_SOURCE(); + +#if defined(SAI2) + /* Get the SAI2 clock source -----------------------------------------------*/ + PeriphClkInit->Sai2ClockSelection = __HAL_RCC_GET_SAI2_SOURCE(); +#endif /* SAI2 */ + + /* Get the RTC clock source ------------------------------------------------*/ + PeriphClkInit->RTCClockSelection = __HAL_RCC_GET_RTC_SOURCE(); + +#if defined(USB_OTG_FS) || defined(USB) + /* Get the USB clock source ------------------------------------------------*/ + PeriphClkInit->UsbClockSelection = __HAL_RCC_GET_USB_SOURCE(); +#endif /* USB_OTG_FS || USB */ + +#if defined(SDMMC1) + /* Get the SDMMC1 clock source ---------------------------------------------*/ + PeriphClkInit->Sdmmc1ClockSelection = __HAL_RCC_GET_SDMMC1_SOURCE(); +#endif /* SDMMC1 */ + + /* Get the RNG clock source ------------------------------------------------*/ + PeriphClkInit->RngClockSelection = __HAL_RCC_GET_RNG_SOURCE(); + + /* Get the ADC clock source ------------------------------------------------*/ + PeriphClkInit->AdcClockSelection = __HAL_RCC_GET_ADC_SOURCE(); + +#if defined(SWPMI1) + /* Get the SWPMI1 clock source ---------------------------------------------*/ + PeriphClkInit->Swpmi1ClockSelection = __HAL_RCC_GET_SWPMI1_SOURCE(); +#endif /* SWPMI1 */ + +#if defined(DFSDM1_Filter0) + /* Get the DFSDM1 clock source ---------------------------------------------*/ + PeriphClkInit->Dfsdm1ClockSelection = __HAL_RCC_GET_DFSDM1_SOURCE(); + +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + /* Get the DFSDM1 audio clock source ---------------------------------------*/ + PeriphClkInit->Dfsdm1AudioClockSelection = __HAL_RCC_GET_DFSDM1AUDIO_SOURCE(); +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ +#endif /* DFSDM1_Filter0 */ + +#if defined(LTDC) + /* Get the LTDC clock source -----------------------------------------------*/ + PeriphClkInit->LtdcClockSelection = __HAL_RCC_GET_LTDC_SOURCE(); +#endif /* LTDC */ + +#if defined(DSI) + /* Get the DSI clock source ------------------------------------------------*/ + PeriphClkInit->DsiClockSelection = __HAL_RCC_GET_DSI_SOURCE(); +#endif /* DSI */ + +#if defined(OCTOSPI1) || defined(OCTOSPI2) + /* Get the OctoSPIclock source --------------------------------------------*/ + PeriphClkInit->OspiClockSelection = __HAL_RCC_GET_OSPI_SOURCE(); +#endif /* OCTOSPI1 || OCTOSPI2 */ +} + +/** + * @brief Return the peripheral clock frequency for peripherals with clock source from PLLSAIs + * @note Return 0 if peripheral clock identifier not managed by this API + * @param PeriphClk Peripheral clock identifier + * This parameter can be one of the following values: + * @arg @ref RCC_PERIPHCLK_RTC RTC peripheral clock + * @arg @ref RCC_PERIPHCLK_ADC ADC peripheral clock + @if STM32L462xx + * @arg @ref RCC_PERIPHCLK_DFSDM1 DFSDM1 peripheral clock (only for devices with DFSDM) + @endif + @if STM32L486xx + * @arg @ref RCC_PERIPHCLK_DFSDM1 DFSDM1 peripheral clock (only for devices with DFSDM) + @endif + @if STM32L4A6xx + * @arg @ref RCC_PERIPHCLK_DFSDM1 DFSDM1 peripheral clock (only for devices with DFSDM) + @endif + * @arg @ref RCC_PERIPHCLK_I2C1 I2C1 peripheral clock + * @arg @ref RCC_PERIPHCLK_I2C2 I2C2 peripheral clock + * @arg @ref RCC_PERIPHCLK_I2C3 I2C3 peripheral clock + @if STM32L462xx + * @arg @ref RCC_PERIPHCLK_I2C4 I2C4 peripheral clock (only for devices with I2C4) + @endif + @if STM32L4A6xx + * @arg @ref RCC_PERIPHCLK_I2C4 I2C4 peripheral clock (only for devices with I2C4) + @endif + @if STM32L4S9xx + * @arg @ref RCC_PERIPHCLK_I2C4 I2C4 peripheral clock (only for devices with I2C4) + @endif + * @arg @ref RCC_PERIPHCLK_LPTIM1 LPTIM1 peripheral clock + * @arg @ref RCC_PERIPHCLK_LPTIM2 LPTIM2 peripheral clock + * @arg @ref RCC_PERIPHCLK_LPUART1 LPUART1 peripheral clock + * @arg @ref RCC_PERIPHCLK_RNG RNG peripheral clock + * @arg @ref RCC_PERIPHCLK_SAI1 SAI1 peripheral clock + @if STM32L486xx + * @arg @ref RCC_PERIPHCLK_SAI2 SAI2 peripheral clock (only for devices with SAI2) + @endif + @if STM32L4A6xx + * @arg @ref RCC_PERIPHCLK_SAI2 SAI2 peripheral clock (only for devices with SAI2) + @endif + @if STM32L4S9xx + * @arg @ref RCC_PERIPHCLK_SAI2 SAI2 peripheral clock (only for devices with SAI2) + @endif + * @arg @ref RCC_PERIPHCLK_SDMMC1 SDMMC1 peripheral clock + @if STM32L443xx + * @arg @ref RCC_PERIPHCLK_SWPMI1 SWPMI1 peripheral clock (only for devices with SWPMI1) + @endif + @if STM32L486xx + * @arg @ref RCC_PERIPHCLK_SWPMI1 SWPMI1 peripheral clock (only for devices with SWPMI1) + @endif + @if STM32L4A6xx + * @arg @ref RCC_PERIPHCLK_SWPMI1 SWPMI1 peripheral clock (only for devices with SWPMI1) + @endif + * @arg @ref RCC_PERIPHCLK_USART1 USART1 peripheral clock + * @arg @ref RCC_PERIPHCLK_USART2 USART1 peripheral clock + * @arg @ref RCC_PERIPHCLK_USART3 USART1 peripheral clock + @if STM32L462xx + * @arg @ref RCC_PERIPHCLK_UART4 UART4 peripheral clock (only for devices with UART4) + * @arg @ref RCC_PERIPHCLK_USB USB peripheral clock (only for devices with USB) + @endif + @if STM32L486xx + * @arg @ref RCC_PERIPHCLK_UART4 UART4 peripheral clock (only for devices with UART4) + * @arg @ref RCC_PERIPHCLK_UART5 UART5 peripheral clock (only for devices with UART5) + * @arg @ref RCC_PERIPHCLK_USB USB peripheral clock (only for devices with USB) + @endif + @if STM32L4A6xx + * @arg @ref RCC_PERIPHCLK_UART4 UART4 peripheral clock (only for devices with UART4) + * @arg @ref RCC_PERIPHCLK_UART5 UART5 peripheral clock (only for devices with UART5) + * @arg @ref RCC_PERIPHCLK_USB USB peripheral clock (only for devices with USB) + @endif + @if STM32L4S9xx + * @arg @ref RCC_PERIPHCLK_UART4 USART1 peripheral clock (only for devices with UART4) + * @arg @ref RCC_PERIPHCLK_UART5 USART1 peripheral clock (only for devices with UART5) + * @arg @ref RCC_PERIPHCLK_USB USB peripheral clock (only for devices with USB) + * @arg @ref RCC_PERIPHCLK_DFSDM1 DFSDM1 peripheral kernel clock (only for devices with DFSDM1) + * @arg @ref RCC_PERIPHCLK_DFSDM1AUDIO DFSDM1 peripheral audio clock (only for devices with DFSDM1) + * @arg @ref RCC_PERIPHCLK_LTDC LTDC peripheral clock (only for devices with LTDC) + * @arg @ref RCC_PERIPHCLK_DSI DSI peripheral clock (only for devices with DSI) + * @arg @ref RCC_PERIPHCLK_OSPI OctoSPI peripheral clock (only for devices with OctoSPI) + @endif + * @retval Frequency in Hz + */ +uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk) +{ + uint32_t frequency = 0U; + uint32_t srcclk = 0U; + uint32_t pllvco = 0U, plln = 0U, pllp = 0U; + + /* Check the parameters */ + assert_param(IS_RCC_PERIPHCLOCK(PeriphClk)); + + if(PeriphClk == RCC_PERIPHCLK_RTC) + { + /* Get the current RTC source */ + srcclk = __HAL_RCC_GET_RTC_SOURCE(); + + /* Check if LSE is ready and if RTC clock selection is LSE */ + if ((srcclk == RCC_RTCCLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))) + { + frequency = LSE_VALUE; + } + /* Check if LSI is ready and if RTC clock selection is LSI */ + else if ((srcclk == RCC_RTCCLKSOURCE_LSI) && (HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIRDY))) + { + frequency = LSI_VALUE; + } + /* Check if HSE is ready and if RTC clock selection is HSI_DIV32*/ + else if ((srcclk == RCC_RTCCLKSOURCE_HSE_DIV32) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY))) + { + frequency = HSE_VALUE / 32U; + } + /* Clock not enabled for RTC*/ + else + { + frequency = 0U; + } + } + else + { + /* Other external peripheral clock source than RTC */ + + /* Compute PLL clock input */ + if(__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_MSI) /* MSI ? */ + { + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_MSIRDY)) + { + /*MSI frequency range in HZ*/ + pllvco = MSIRangeTable[(__HAL_RCC_GET_MSI_RANGE() >> 4U)]; + } + else + { + pllvco = 0U; + } + } + else if(__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSI) /* HSI ? */ + { + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) + { + pllvco = HSI_VALUE; + } + else + { + pllvco = 0U; + } + } + else if(__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSE) /* HSE ? */ + { + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY)) + { + pllvco = HSE_VALUE; + } + else + { + pllvco = 0U; + } + } + else /* No source */ + { + pllvco = 0U; + } + +#if !defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) && !defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + /* f(PLL Source) / PLLM */ + pllvco = (pllvco / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U)); +#endif + + switch(PeriphClk) + { +#if defined(SAI2) + + case RCC_PERIPHCLK_SAI1: + case RCC_PERIPHCLK_SAI2: + + if(PeriphClk == RCC_PERIPHCLK_SAI1) + { + srcclk = __HAL_RCC_GET_SAI1_SOURCE(); + + if(srcclk == RCC_SAI1CLKSOURCE_PIN) + { + frequency = EXTERNAL_SAI1_CLOCK_VALUE; + } + /* Else, PLL clock output to check below */ + } + else /* RCC_PERIPHCLK_SAI2 */ + { + srcclk = __HAL_RCC_GET_SAI2_SOURCE(); + + if(srcclk == RCC_SAI2CLKSOURCE_PIN) + { + frequency = EXTERNAL_SAI2_CLOCK_VALUE; + } + /* Else, PLL clock output to check below */ + } + +#else + + case RCC_PERIPHCLK_SAI1: + + if(PeriphClk == RCC_PERIPHCLK_SAI1) + { + srcclk = READ_BIT(RCC->CCIPR, RCC_CCIPR_SAI1SEL); + + if(srcclk == RCC_SAI1CLKSOURCE_PIN) + { + frequency = EXTERNAL_SAI1_CLOCK_VALUE; + } + /* Else, PLL clock output to check below */ + } + +#endif /* SAI2 */ + + if(frequency == 0U) + { +#if defined(SAI2) + if((srcclk == RCC_SAI1CLKSOURCE_PLL) || (srcclk == RCC_SAI2CLKSOURCE_PLL)) + { + if(__HAL_RCC_GET_PLLCLKOUT_CONFIG(RCC_PLL_SAI3CLK) != RESET) + { + /* f(PLLSAI3CLK) = f(VCO input) * PLLN / PLLP */ + plln = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos; +#if defined(RCC_PLLP_DIV_2_31_SUPPORT) + pllp = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLPDIV) >> RCC_PLLCFGR_PLLPDIV_Pos; +#endif + if(pllp == 0U) + { + if(READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLP) != RESET) + { + pllp = 17U; + } + else + { + pllp = 7U; + } + } + frequency = (pllvco * plln) / pllp; + } + } + else if(srcclk == 0U) /* RCC_SAI1CLKSOURCE_PLLSAI1 || RCC_SAI2CLKSOURCE_PLLSAI1 */ + { + if(__HAL_RCC_GET_PLLSAI1CLKOUT_CONFIG(RCC_PLLSAI1_SAI1CLK) != RESET) + { +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + /* f(PLLSAI1 Source) / PLLSAI1M */ + pllvco = (pllvco / ((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1M) >> RCC_PLLSAI1CFGR_PLLSAI1M_Pos) + 1U)); +#endif + /* f(PLLSAI1CLK) = f(VCOSAI1 input) * PLLSAI1N / PLLSAI1P */ + plln = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos; +#if defined(RCC_PLLSAI1P_DIV_2_31_SUPPORT) + pllp = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1PDIV) >> RCC_PLLSAI1CFGR_PLLSAI1PDIV_Pos; +#endif + if(pllp == 0U) + { + if(READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1P) != RESET) + { + pllp = 17U; + } + else + { + pllp = 7U; + } + } + frequency = (pllvco * plln) / pllp; + } + } +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + else if((srcclk == RCC_SAI1CLKSOURCE_HSI) || (srcclk == RCC_SAI2CLKSOURCE_HSI)) + { + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) + { + frequency = HSI_VALUE; + } + } +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#else + if(srcclk == RCC_SAI1CLKSOURCE_PLL) + { + if(__HAL_RCC_GET_PLLCLKOUT_CONFIG(RCC_PLL_SAI2CLK) != RESET) + { + /* f(PLLSAI2CLK) = f(VCO input) * PLLN / PLLP */ + plln = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos; +#if defined(RCC_PLLP_DIV_2_31_SUPPORT) + pllp = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLPDIV) >> RCC_PLLCFGR_PLLPDIV_Pos; +#endif + if(pllp == 0U) + { + if(READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLP) != RESET) + { + pllp = 17U; + } + else + { + pllp = 7U; + } + } + + frequency = (pllvco * plln) / pllp; + } + else if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) + { + /* HSI automatically selected as clock source if PLLs not enabled */ + frequency = HSI_VALUE; + } + else + { + /* No clock source */ + frequency = 0U; + } + } + else if(srcclk == RCC_SAI1CLKSOURCE_PLLSAI1) + { + if(__HAL_RCC_GET_PLLSAI1CLKOUT_CONFIG(RCC_PLLSAI1_SAI1CLK) != RESET) + { +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + /* f(PLLSAI1 Source) / PLLSAI1M */ + pllvco = (pllvco / ((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1M) >> RCC_PLLSAI1CFGR_PLLSAI1M_Pos) + 1U)); +#endif + /* f(PLLSAI1CLK) = f(VCOSAI1 input) * PLLSAI1N / PLLSAI1P */ + plln = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos; +#if defined(RCC_PLLSAI1P_DIV_2_31_SUPPORT) + pllp = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1PDIV) >> RCC_PLLSAI1CFGR_PLLSAI1PDIV_Pos; +#endif + if(pllp == 0U) + { + if(READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1P) != RESET) + { + pllp = 17U; + } + else + { + pllp = 7U; + } + } + + frequency = (pllvco * plln) / pllp; + } + else if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)) + { + /* HSI automatically selected as clock source if PLLs not enabled */ + frequency = HSI_VALUE; + } + else + { + /* No clock source */ + frequency = 0U; + } + } +#endif /* SAI2 */ + +#if defined(RCC_PLLSAI2_SUPPORT) + + else if((srcclk == RCC_SAI1CLKSOURCE_PLLSAI2) || (srcclk == RCC_SAI2CLKSOURCE_PLLSAI2)) + { + if(__HAL_RCC_GET_PLLSAI2CLKOUT_CONFIG(RCC_PLLSAI2_SAI2CLK) != RESET) + { +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + /* f(PLLSAI2 Source) / PLLSAI2M */ + pllvco = (pllvco / ((READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2M) >> RCC_PLLSAI2CFGR_PLLSAI2M_Pos) + 1U)); +#endif + /* f(PLLSAI2CLK) = f(VCOSAI2 input) * PLLSAI2N / PLLSAI2P */ + plln = READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2N) >> RCC_PLLSAI2CFGR_PLLSAI2N_Pos; +#if defined(RCC_PLLSAI2P_DIV_2_31_SUPPORT) + pllp = READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2PDIV) >> RCC_PLLSAI2CFGR_PLLSAI2PDIV_Pos; +#endif + if(pllp == 0U) + { + if(READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2P) != RESET) + { + pllp = 17U; + } + else + { + pllp = 7U; + } + } + frequency = (pllvco * plln) / pllp; + } + } + +#endif /* RCC_PLLSAI2_SUPPORT */ + + else + { + /* No clock source */ + frequency = 0U; + } + } + break; + +#if defined(USB_OTG_FS) || defined(USB) + + case RCC_PERIPHCLK_USB: + +#endif /* USB_OTG_FS || USB */ + + case RCC_PERIPHCLK_RNG: + +#if defined(SDMMC1) && !defined(RCC_CCIPR2_SDMMCSEL) + + case RCC_PERIPHCLK_SDMMC1: + +#endif /* SDMMC1 && !RCC_CCIPR2_SDMMCSEL */ + + srcclk = READ_BIT(RCC->CCIPR, RCC_CCIPR_CLK48SEL); + + if(srcclk == RCC_CCIPR_CLK48SEL) /* MSI ? */ + { + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_MSIRDY)) + { + /*MSI frequency range in HZ*/ + frequency = MSIRangeTable[(__HAL_RCC_GET_MSI_RANGE() >> 4U)]; + } + else + { + frequency = 0U; + } + } + else if(srcclk == RCC_CCIPR_CLK48SEL_1) /* PLL ? */ + { + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLRDY) && HAL_IS_BIT_SET(RCC->PLLCFGR, RCC_PLLCFGR_PLLQEN)) + { +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) || defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + /* f(PLL Source) / PLLM */ + pllvco = (pllvco / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U)); +#endif + /* f(PLL48M1CLK) = f(VCO input) * PLLN / PLLQ */ + plln = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos; + frequency = (pllvco * plln) / (((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLQ) >> RCC_PLLCFGR_PLLQ_Pos) + 1U) << 1U); + } + else + { + frequency = 0U; + } + } + else if(srcclk == RCC_CCIPR_CLK48SEL_0) /* PLLSAI1 ? */ + { + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLSAI1RDY) && HAL_IS_BIT_SET(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1QEN)) + { +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + /* f(PLLSAI1 Source) / PLLSAI1M */ + pllvco = (pllvco / ((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1M) >> RCC_PLLSAI1CFGR_PLLSAI1M_Pos) + 1U)); +#endif + /* f(PLL48M2CLK) = f(VCOSAI1 input) * PLLSAI1N / PLLSAI1Q */ + plln = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos; + frequency = (pllvco * plln) / (((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1Q) >> RCC_PLLSAI1CFGR_PLLSAI1Q_Pos) + 1U) << 1U); + } + else + { + frequency = 0U; + } + } +#if defined(RCC_HSI48_SUPPORT) + else if((srcclk == 0U) && (HAL_IS_BIT_SET(RCC->CRRCR, RCC_CRRCR_HSI48RDY))) /* HSI48 ? */ + { + frequency = HSI48_VALUE; + } + else /* No clock source */ + { + frequency = 0U; + } +#else + else /* No clock source */ + { + frequency = 0U; + } +#endif /* RCC_HSI48_SUPPORT */ + break; + +#if defined(SDMMC1) && defined(RCC_CCIPR2_SDMMCSEL) + + case RCC_PERIPHCLK_SDMMC1: + + if(HAL_IS_BIT_SET(RCC->CCIPR2, RCC_CCIPR2_SDMMCSEL)) /* PLL "P" ? */ + { + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLRDY) && HAL_IS_BIT_SET(RCC->PLLCFGR, RCC_PLLCFGR_PLLPEN)) + { +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) || defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + /* f(PLL Source) / PLLM */ + pllvco = (pllvco / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U)); +#endif + /* f(PLLSAI3CLK) = f(VCO input) * PLLN / PLLP */ + plln = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos; +#if defined(RCC_PLLP_DIV_2_31_SUPPORT) + pllp = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLPDIV) >> RCC_PLLCFGR_PLLPDIV_Pos; +#endif + if(pllp == 0U) + { + if(READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLP) != RESET) + { + pllp = 17U; + } + else + { + pllp = 7U; + } + } + frequency = (pllvco * plln) / pllp; + } + else + { + frequency = 0U; + } + } + else /* 48MHz from PLL "Q" or MSI or PLLSAI1Q or HSI48 */ + { + srcclk = READ_BIT(RCC->CCIPR, RCC_CCIPR_CLK48SEL); + + if(srcclk == RCC_CCIPR_CLK48SEL) /* MSI ? */ + { + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_MSIRDY)) + { + /*MSI frequency range in HZ*/ + frequency = MSIRangeTable[(__HAL_RCC_GET_MSI_RANGE() >> 4U)]; + } + else + { + frequency = 0U; + } + } + else if(srcclk == RCC_CCIPR_CLK48SEL_1) /* PLL "Q" ? */ + { + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLRDY) && HAL_IS_BIT_SET(RCC->PLLCFGR, RCC_PLLCFGR_PLLQEN)) + { +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) || defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + /* f(PLL Source) / PLLM */ + pllvco = (pllvco / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U)); +#endif + /* f(PLL48M1CLK) = f(VCO input) * PLLN / PLLQ */ + plln = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos; + frequency = (pllvco * plln) / (((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLQ) >> RCC_PLLCFGR_PLLQ_Pos) + 1U) << 1U); + } + else + { + frequency = 0U; + } + } + else if(srcclk == RCC_CCIPR_CLK48SEL_0) /* PLLSAI1 ? */ + { + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLSAI1RDY) && HAL_IS_BIT_SET(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1QEN)) + { +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + /* f(PLLSAI1 Source) / PLLSAI1M */ + pllvco = (pllvco / ((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1M) >> RCC_PLLSAI1CFGR_PLLSAI1M_Pos) + 1U)); +#endif + /* f(PLL48M2CLK) = f(VCOSAI1 input) * PLLSAI1N / PLLSAI1Q */ + plln = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos; + frequency = (pllvco * plln) / (((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1Q) >> RCC_PLLSAI1CFGR_PLLSAI1Q_Pos) + 1U) << 1U); + } + else + { + frequency = 0U; + } + } + else if((srcclk == 0U) && (HAL_IS_BIT_SET(RCC->CRRCR, RCC_CRRCR_HSI48RDY))) /* HSI48 ? */ + { + frequency = HSI48_VALUE; + } + else /* No clock source */ + { + frequency = 0U; + } + } + break; + +#endif /* SDMMC1 && RCC_CCIPR2_SDMMCSEL */ + + case RCC_PERIPHCLK_USART1: + /* Get the current USART1 source */ + srcclk = __HAL_RCC_GET_USART1_SOURCE(); + + if(srcclk == RCC_USART1CLKSOURCE_PCLK2) + { + frequency = HAL_RCC_GetPCLK2Freq(); + } + else if(srcclk == RCC_USART1CLKSOURCE_SYSCLK) + { + frequency = HAL_RCC_GetSysClockFreq(); + } + else if((srcclk == RCC_USART1CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + { + frequency = HSI_VALUE; + } + else if((srcclk == RCC_USART1CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))) + { + frequency = LSE_VALUE; + } + /* Clock not enabled for USART1 */ + else + { + frequency = 0U; + } + break; + + case RCC_PERIPHCLK_USART2: + /* Get the current USART2 source */ + srcclk = __HAL_RCC_GET_USART2_SOURCE(); + + if(srcclk == RCC_USART2CLKSOURCE_PCLK1) + { + frequency = HAL_RCC_GetPCLK1Freq(); + } + else if(srcclk == RCC_USART2CLKSOURCE_SYSCLK) + { + frequency = HAL_RCC_GetSysClockFreq(); + } + else if((srcclk == RCC_USART2CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + { + frequency = HSI_VALUE; + } + else if((srcclk == RCC_USART2CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))) + { + frequency = LSE_VALUE; + } + /* Clock not enabled for USART2 */ + else + { + frequency = 0U; + } + break; + +#if defined(USART3) + + case RCC_PERIPHCLK_USART3: + /* Get the current USART3 source */ + srcclk = __HAL_RCC_GET_USART3_SOURCE(); + + if(srcclk == RCC_USART3CLKSOURCE_PCLK1) + { + frequency = HAL_RCC_GetPCLK1Freq(); + } + else if(srcclk == RCC_USART3CLKSOURCE_SYSCLK) + { + frequency = HAL_RCC_GetSysClockFreq(); + } + else if((srcclk == RCC_USART3CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + { + frequency = HSI_VALUE; + } + else if((srcclk == RCC_USART3CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))) + { + frequency = LSE_VALUE; + } + /* Clock not enabled for USART3 */ + else + { + frequency = 0U; + } + break; + +#endif /* USART3 */ + +#if defined(UART4) + + case RCC_PERIPHCLK_UART4: + /* Get the current UART4 source */ + srcclk = __HAL_RCC_GET_UART4_SOURCE(); + + if(srcclk == RCC_UART4CLKSOURCE_PCLK1) + { + frequency = HAL_RCC_GetPCLK1Freq(); + } + else if(srcclk == RCC_UART4CLKSOURCE_SYSCLK) + { + frequency = HAL_RCC_GetSysClockFreq(); + } + else if((srcclk == RCC_UART4CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + { + frequency = HSI_VALUE; + } + else if((srcclk == RCC_UART4CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))) + { + frequency = LSE_VALUE; + } + /* Clock not enabled for UART4 */ + else + { + frequency = 0U; + } + break; + +#endif /* UART4 */ + +#if defined(UART5) + + case RCC_PERIPHCLK_UART5: + /* Get the current UART5 source */ + srcclk = __HAL_RCC_GET_UART5_SOURCE(); + + if(srcclk == RCC_UART5CLKSOURCE_PCLK1) + { + frequency = HAL_RCC_GetPCLK1Freq(); + } + else if(srcclk == RCC_UART5CLKSOURCE_SYSCLK) + { + frequency = HAL_RCC_GetSysClockFreq(); + } + else if((srcclk == RCC_UART5CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + { + frequency = HSI_VALUE; + } + else if((srcclk == RCC_UART5CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))) + { + frequency = LSE_VALUE; + } + /* Clock not enabled for UART5 */ + else + { + frequency = 0U; + } + break; + +#endif /* UART5 */ + + case RCC_PERIPHCLK_LPUART1: + /* Get the current LPUART1 source */ + srcclk = __HAL_RCC_GET_LPUART1_SOURCE(); + + if(srcclk == RCC_LPUART1CLKSOURCE_PCLK1) + { + frequency = HAL_RCC_GetPCLK1Freq(); + } + else if(srcclk == RCC_LPUART1CLKSOURCE_SYSCLK) + { + frequency = HAL_RCC_GetSysClockFreq(); + } + else if((srcclk == RCC_LPUART1CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + { + frequency = HSI_VALUE; + } + else if((srcclk == RCC_LPUART1CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))) + { + frequency = LSE_VALUE; + } + /* Clock not enabled for LPUART1 */ + else + { + frequency = 0U; + } + break; + + case RCC_PERIPHCLK_ADC: + + srcclk = __HAL_RCC_GET_ADC_SOURCE(); + + if(srcclk == RCC_ADCCLKSOURCE_SYSCLK) + { + frequency = HAL_RCC_GetSysClockFreq(); + } + else if(srcclk == RCC_ADCCLKSOURCE_PLLSAI1) + { + if(__HAL_RCC_GET_PLLSAI1CLKOUT_CONFIG(RCC_PLLSAI1_ADC1CLK) != RESET) + { +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + /* f(PLLSAI1 Source) / PLLSAI1M */ + pllvco = (pllvco / ((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1M) >> RCC_PLLSAI1CFGR_PLLSAI1M_Pos) + 1U)); +#endif + /* f(PLLADC1CLK) = f(VCOSAI1 input) * PLLSAI1N / PLLSAI1R */ + plln = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos; + frequency = (pllvco * plln) / (((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1R) >> RCC_PLLSAI1CFGR_PLLSAI1R_Pos) + 1U) << 1U); + } + } +#if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || defined(STM32L496xx) || defined(STM32L4A6xx) + else if(srcclk == RCC_ADCCLKSOURCE_PLLSAI2) + { + if(__HAL_RCC_GET_PLLSAI2CLKOUT_CONFIG(RCC_PLLSAI2_ADC2CLK) != RESET) + { +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + /* f(PLLSAI2 Source) / PLLSAI2M */ + pllvco = (pllvco / ((READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2M) >> RCC_PLLSAI2CFGR_PLLSAI2M_Pos) + 1U)); +#endif + /* f(PLLADC2CLK) = f(VCOSAI2 input) * PLLSAI2N / PLLSAI2R */ + plln = READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2N) >> RCC_PLLSAI2CFGR_PLLSAI2N_Pos; + frequency = (pllvco * plln) / (((READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2R) >> RCC_PLLSAI2CFGR_PLLSAI2R_Pos) + 1U) << 1U); + } + } +#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || STM32L496xx || STM32L4A6xx */ + /* Clock not enabled for ADC */ + else + { + frequency = 0U; + } + break; + +#if defined(DFSDM1_Filter0) + + case RCC_PERIPHCLK_DFSDM1: + /* Get the current DFSDM1 source */ + srcclk = __HAL_RCC_GET_DFSDM1_SOURCE(); + + if(srcclk == RCC_DFSDM1CLKSOURCE_PCLK2) + { + frequency = HAL_RCC_GetPCLK2Freq(); + } + else + { + frequency = HAL_RCC_GetSysClockFreq(); + } + break; + +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + + case RCC_PERIPHCLK_DFSDM1AUDIO: + /* Get the current DFSDM1 audio source */ + srcclk = __HAL_RCC_GET_DFSDM1AUDIO_SOURCE(); + + if(srcclk == RCC_DFSDM1AUDIOCLKSOURCE_SAI1) + { + frequency = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI1); + } + else if((srcclk == RCC_DFSDM1AUDIOCLKSOURCE_MSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_MSIRDY))) + { + /*MSI frequency range in HZ*/ + frequency = MSIRangeTable[(__HAL_RCC_GET_MSI_RANGE() >> 4U)]; + } + else if((srcclk == RCC_DFSDM1AUDIOCLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + { + frequency = HSI_VALUE; + } + /* Clock not enabled for DFSDM1 audio source */ + else + { + frequency = 0U; + } + break; + +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#endif /* DFSDM1_Filter0 */ + + case RCC_PERIPHCLK_I2C1: + /* Get the current I2C1 source */ + srcclk = __HAL_RCC_GET_I2C1_SOURCE(); + + if(srcclk == RCC_I2C1CLKSOURCE_PCLK1) + { + frequency = HAL_RCC_GetPCLK1Freq(); + } + else if(srcclk == RCC_I2C1CLKSOURCE_SYSCLK) + { + frequency = HAL_RCC_GetSysClockFreq(); + } + else if((srcclk == RCC_I2C1CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + { + frequency = HSI_VALUE; + } + /* Clock not enabled for I2C1 */ + else + { + frequency = 0U; + } + break; + +#if defined(I2C2) + + case RCC_PERIPHCLK_I2C2: + /* Get the current I2C2 source */ + srcclk = __HAL_RCC_GET_I2C2_SOURCE(); + + if(srcclk == RCC_I2C2CLKSOURCE_PCLK1) + { + frequency = HAL_RCC_GetPCLK1Freq(); + } + else if(srcclk == RCC_I2C2CLKSOURCE_SYSCLK) + { + frequency = HAL_RCC_GetSysClockFreq(); + } + else if((srcclk == RCC_I2C2CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + { + frequency = HSI_VALUE; + } + /* Clock not enabled for I2C2 */ + else + { + frequency = 0U; + } + break; + +#endif /* I2C2 */ + + case RCC_PERIPHCLK_I2C3: + /* Get the current I2C3 source */ + srcclk = __HAL_RCC_GET_I2C3_SOURCE(); + + if(srcclk == RCC_I2C3CLKSOURCE_PCLK1) + { + frequency = HAL_RCC_GetPCLK1Freq(); + } + else if(srcclk == RCC_I2C3CLKSOURCE_SYSCLK) + { + frequency = HAL_RCC_GetSysClockFreq(); + } + else if((srcclk == RCC_I2C3CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + { + frequency = HSI_VALUE; + } + /* Clock not enabled for I2C3 */ + else + { + frequency = 0U; + } + break; + +#if defined(I2C4) + + case RCC_PERIPHCLK_I2C4: + /* Get the current I2C4 source */ + srcclk = __HAL_RCC_GET_I2C4_SOURCE(); + + if(srcclk == RCC_I2C4CLKSOURCE_PCLK1) + { + frequency = HAL_RCC_GetPCLK1Freq(); + } + else if(srcclk == RCC_I2C4CLKSOURCE_SYSCLK) + { + frequency = HAL_RCC_GetSysClockFreq(); + } + else if((srcclk == RCC_I2C4CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + { + frequency = HSI_VALUE; + } + /* Clock not enabled for I2C4 */ + else + { + frequency = 0U; + } + break; + +#endif /* I2C4 */ + + case RCC_PERIPHCLK_LPTIM1: + /* Get the current LPTIM1 source */ + srcclk = __HAL_RCC_GET_LPTIM1_SOURCE(); + + if(srcclk == RCC_LPTIM1CLKSOURCE_PCLK1) + { + frequency = HAL_RCC_GetPCLK1Freq(); + } + else if((srcclk == RCC_LPTIM1CLKSOURCE_LSI) && (HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIRDY))) + { + frequency = LSI_VALUE; + } + else if((srcclk == RCC_LPTIM1CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + { + frequency = HSI_VALUE; + } + else if ((srcclk == RCC_LPTIM1CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))) + { + frequency = LSE_VALUE; + } + /* Clock not enabled for LPTIM1 */ + else + { + frequency = 0U; + } + break; + + case RCC_PERIPHCLK_LPTIM2: + /* Get the current LPTIM2 source */ + srcclk = __HAL_RCC_GET_LPTIM2_SOURCE(); + + if(srcclk == RCC_LPTIM2CLKSOURCE_PCLK1) + { + frequency = HAL_RCC_GetPCLK1Freq(); + } + else if((srcclk == RCC_LPTIM2CLKSOURCE_LSI) && (HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIRDY))) + { + frequency = LSI_VALUE; + } + else if((srcclk == RCC_LPTIM2CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + { + frequency = HSI_VALUE; + } + else if ((srcclk == RCC_LPTIM2CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))) + { + frequency = LSE_VALUE; + } + /* Clock not enabled for LPTIM2 */ + else + { + frequency = 0U; + } + break; + +#if defined(SWPMI1) + + case RCC_PERIPHCLK_SWPMI1: + /* Get the current SWPMI1 source */ + srcclk = __HAL_RCC_GET_SWPMI1_SOURCE(); + + if(srcclk == RCC_SWPMI1CLKSOURCE_PCLK1) + { + frequency = HAL_RCC_GetPCLK1Freq(); + } + else if((srcclk == RCC_SWPMI1CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))) + { + frequency = HSI_VALUE; + } + /* Clock not enabled for SWPMI1 */ + else + { + frequency = 0U; + } + break; + +#endif /* SWPMI1 */ + +#if defined(OCTOSPI1) || defined(OCTOSPI2) + + case RCC_PERIPHCLK_OSPI: + /* Get the current OctoSPI clock source */ + srcclk = __HAL_RCC_GET_OSPI_SOURCE(); + + if(srcclk == RCC_OSPICLKSOURCE_SYSCLK) + { + frequency = HAL_RCC_GetSysClockFreq(); + } + else if((srcclk == RCC_OSPICLKSOURCE_MSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_MSIRDY))) + { + /*MSI frequency range in HZ*/ + frequency = MSIRangeTable[(__HAL_RCC_GET_MSI_RANGE() >> 4U)]; + } + else if(srcclk == RCC_OSPICLKSOURCE_PLL) + { + if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLRDY) && HAL_IS_BIT_SET(RCC->PLLCFGR, RCC_PLLCFGR_PLLQEN)) + { + /* f(PLL Source) / PLLM */ + pllvco = (pllvco / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U)); + /* f(PLL48M1CLK) = f(VCO input) * PLLN / PLLQ */ + plln = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos; + frequency = (pllvco * plln) / (((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLQ) >> RCC_PLLCFGR_PLLQ_Pos) + 1U) << 1U); + } + else + { + frequency = 0U; + } + } + /* Clock not enabled for OctoSPI */ + else + { + frequency = 0U; + } + break; + +#endif /* OCTOSPI1 || OCTOSPI2 */ + + default: + break; + } + } + + return(frequency); +} + +/** + * @} + */ + +/** @defgroup RCCEx_Exported_Functions_Group2 Extended Clock management functions + * @brief Extended Clock management functions + * +@verbatim + =============================================================================== + ##### Extended clock management functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to control the + activation or deactivation of MSI PLL-mode, PLLSAI1, PLLSAI2, LSE CSS, + Low speed clock output and clock after wake-up from STOP mode. +@endverbatim + * @{ + */ + +/** + * @brief Enable PLLSAI1. + * @param PLLSAI1Init pointer to an RCC_PLLSAI1InitTypeDef structure that + * contains the configuration information for the PLLSAI1 + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RCCEx_EnablePLLSAI1(RCC_PLLSAI1InitTypeDef *PLLSAI1Init) +{ + uint32_t tickstart = 0U; + HAL_StatusTypeDef status = HAL_OK; + + /* check for PLLSAI1 Parameters used to output PLLSAI1CLK */ + assert_param(IS_RCC_PLLSAI1SOURCE(PLLSAI1Init->PLLSAI1Source)); + assert_param(IS_RCC_PLLSAI1M_VALUE(PLLSAI1Init->PLLSAI1M)); + assert_param(IS_RCC_PLLSAI1N_VALUE(PLLSAI1Init->PLLSAI1N)); + assert_param(IS_RCC_PLLSAI1P_VALUE(PLLSAI1Init->PLLSAI1P)); + assert_param(IS_RCC_PLLSAI1Q_VALUE(PLLSAI1Init->PLLSAI1Q)); + assert_param(IS_RCC_PLLSAI1R_VALUE(PLLSAI1Init->PLLSAI1R)); + assert_param(IS_RCC_PLLSAI1CLOCKOUT_VALUE(PLLSAI1Init->PLLSAI1ClockOut)); + + /* Disable the PLLSAI1 */ + __HAL_RCC_PLLSAI1_DISABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till PLLSAI1 is ready to be updated */ + while(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) != RESET) + { + if((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE) + { + status = HAL_TIMEOUT; + break; + } + } + + if(status == HAL_OK) + { +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + /* Configure the PLLSAI1 Multiplication factor N */ + /* Configure the PLLSAI1 Division factors M, P, Q and R */ + __HAL_RCC_PLLSAI1_CONFIG(PLLSAI1Init->PLLSAI1M, PLLSAI1Init->PLLSAI1N, PLLSAI1Init->PLLSAI1P, PLLSAI1Init->PLLSAI1Q, PLLSAI1Init->PLLSAI1R); +#else + /* Configure the PLLSAI1 Multiplication factor N */ + /* Configure the PLLSAI1 Division factors P, Q and R */ + __HAL_RCC_PLLSAI1_CONFIG(PLLSAI1Init->PLLSAI1N, PLLSAI1Init->PLLSAI1P, PLLSAI1Init->PLLSAI1Q, PLLSAI1Init->PLLSAI1R); +#endif /* RCC_PLLSAI1M_DIV_1_16_SUPPORT */ + /* Configure the PLLSAI1 Clock output(s) */ + __HAL_RCC_PLLSAI1CLKOUT_ENABLE(PLLSAI1Init->PLLSAI1ClockOut); + + /* Enable the PLLSAI1 again by setting PLLSAI1ON to 1*/ + __HAL_RCC_PLLSAI1_ENABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till PLLSAI1 is ready */ + while(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) == RESET) + { + if((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE) + { + status = HAL_TIMEOUT; + break; + } + } + } + + return status; +} + +/** + * @brief Disable PLLSAI1. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RCCEx_DisablePLLSAI1(void) +{ + uint32_t tickstart = 0U; + HAL_StatusTypeDef status = HAL_OK; + + /* Disable the PLLSAI1 */ + __HAL_RCC_PLLSAI1_DISABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till PLLSAI1 is ready */ + while(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) != RESET) + { + if((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE) + { + status = HAL_TIMEOUT; + break; + } + } + + /* Disable the PLLSAI1 Clock outputs */ + __HAL_RCC_PLLSAI1CLKOUT_DISABLE(RCC_PLLSAI1CFGR_PLLSAI1PEN|RCC_PLLSAI1CFGR_PLLSAI1QEN|RCC_PLLSAI1CFGR_PLLSAI1REN); + + /* Reset PLL source to save power if no PLLs on */ + if((READ_BIT(RCC->CR, RCC_CR_PLLRDY) == RESET) +#if defined(RCC_PLLSAI2_SUPPORT) + && + (READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) == RESET) +#endif /* RCC_PLLSAI2_SUPPORT */ + ) + { + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, RCC_PLLSOURCE_NONE); + } + + return status; +} + +#if defined(RCC_PLLSAI2_SUPPORT) + +/** + * @brief Enable PLLSAI2. + * @param PLLSAI2Init pointer to an RCC_PLLSAI2InitTypeDef structure that + * contains the configuration information for the PLLSAI2 + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RCCEx_EnablePLLSAI2(RCC_PLLSAI2InitTypeDef *PLLSAI2Init) +{ + uint32_t tickstart = 0U; + HAL_StatusTypeDef status = HAL_OK; + + /* check for PLLSAI2 Parameters used to output PLLSAI2CLK */ + assert_param(IS_RCC_PLLSAI2SOURCE(PLLSAI2Init->PLLSAI2Source)); + assert_param(IS_RCC_PLLSAI2M_VALUE(PLLSAI2Init->PLLSAI2M)); + assert_param(IS_RCC_PLLSAI2N_VALUE(PLLSAI2Init->PLLSAI2N)); + assert_param(IS_RCC_PLLSAI2P_VALUE(PLLSAI2Init->PLLSAI2P)); +#if defined(RCC_PLLSAI2Q_DIV_SUPPORT) + assert_param(IS_RCC_PLLSAI2Q_VALUE(PLLSAI2Init->PLLSAI2Q)); +#endif /* RCC_PLLSAI2Q_DIV_SUPPORT */ + assert_param(IS_RCC_PLLSAI2R_VALUE(PLLSAI2Init->PLLSAI2R)); + assert_param(IS_RCC_PLLSAI2CLOCKOUT_VALUE(PLLSAI2Init->PLLSAI2ClockOut)); + + /* Disable the PLLSAI2 */ + __HAL_RCC_PLLSAI2_DISABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till PLLSAI2 is ready to be updated */ + while(READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) != RESET) + { + if((HAL_GetTick() - tickstart) > PLLSAI2_TIMEOUT_VALUE) + { + status = HAL_TIMEOUT; + break; + } + } + + if(status == HAL_OK) + { +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) && defined(RCC_PLLSAI2Q_DIV_SUPPORT) + /* Configure the PLLSAI2 Multiplication factor N */ + /* Configure the PLLSAI2 Division factors M, P, Q and R */ + __HAL_RCC_PLLSAI2_CONFIG(PLLSAI2Init->PLLSAI2M, PLLSAI2Init->PLLSAI2N, PLLSAI2Init->PLLSAI2P, PLLSAI2Init->PLLSAI2Q, PLLSAI2Init->PLLSAI2R); +#elif defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + /* Configure the PLLSAI2 Multiplication factor N */ + /* Configure the PLLSAI2 Division factors M, P and R */ + __HAL_RCC_PLLSAI2_CONFIG(PLLSAI2Init->PLLSAI2M, PLLSAI2Init->PLLSAI2N, PLLSAI2Init->PLLSAI2P, PLLSAI2Init->PLLSAI2R); +#elif defined(RCC_PLLSAI2Q_DIV_SUPPORT) + /* Configure the PLLSAI2 Multiplication factor N */ + /* Configure the PLLSAI2 Division factors P, Q and R */ + __HAL_RCC_PLLSAI2_CONFIG(PLLSAI2Init->PLLSAI2N, PLLSAI2Init->PLLSAI2P, PLLSAI2Init->PLLSAI2Q, PLLSAI2Init->PLLSAI2R); +#else + /* Configure the PLLSAI2 Multiplication factor N */ + /* Configure the PLLSAI2 Division factors P and R */ + __HAL_RCC_PLLSAI2_CONFIG(PLLSAI2Init->PLLSAI2N, PLLSAI2Init->PLLSAI2P, PLLSAI2Init->PLLSAI2R); +#endif /* RCC_PLLSAI2M_DIV_1_16_SUPPORT && RCC_PLLSAI2Q_DIV_SUPPORT */ + /* Configure the PLLSAI2 Clock output(s) */ + __HAL_RCC_PLLSAI2CLKOUT_ENABLE(PLLSAI2Init->PLLSAI2ClockOut); + + /* Enable the PLLSAI2 again by setting PLLSAI2ON to 1*/ + __HAL_RCC_PLLSAI2_ENABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till PLLSAI2 is ready */ + while(READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) == RESET) + { + if((HAL_GetTick() - tickstart) > PLLSAI2_TIMEOUT_VALUE) + { + status = HAL_TIMEOUT; + break; + } + } + } + + return status; +} + +/** + * @brief Disable PLLISAI2. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RCCEx_DisablePLLSAI2(void) +{ + uint32_t tickstart = 0U; + HAL_StatusTypeDef status = HAL_OK; + + /* Disable the PLLSAI2 */ + __HAL_RCC_PLLSAI2_DISABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till PLLSAI2 is ready */ + while(READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) != RESET) + { + if((HAL_GetTick() - tickstart) > PLLSAI2_TIMEOUT_VALUE) + { + status = HAL_TIMEOUT; + break; + } + } + + /* Disable the PLLSAI2 Clock outputs */ +#if defined(RCC_PLLSAI2Q_DIV_SUPPORT) + __HAL_RCC_PLLSAI2CLKOUT_DISABLE(RCC_PLLSAI2CFGR_PLLSAI2PEN|RCC_PLLSAI2CFGR_PLLSAI2QEN|RCC_PLLSAI2CFGR_PLLSAI2REN); +#else + __HAL_RCC_PLLSAI2CLKOUT_DISABLE(RCC_PLLSAI2CFGR_PLLSAI2PEN|RCC_PLLSAI2CFGR_PLLSAI2REN); +#endif /* RCC_PLLSAI2M_DIV_1_16_SUPPORT && RCC_PLLSAI2Q_DIV_SUPPORT */ + + /* Reset PLL source to save power if no PLLs on */ + if((READ_BIT(RCC->CR, RCC_CR_PLLRDY) == RESET) + && + (READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) == RESET) + ) + { + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, RCC_PLLSOURCE_NONE); + } + + return status; +} + +#endif /* RCC_PLLSAI2_SUPPORT */ + +/** + * @brief Configure the oscillator clock source for wakeup from Stop and CSS backup clock. + * @param WakeUpClk Wakeup clock + * This parameter can be one of the following values: + * @arg @ref RCC_STOP_WAKEUPCLOCK_MSI MSI oscillator selection + * @arg @ref RCC_STOP_WAKEUPCLOCK_HSI HSI oscillator selection + * @note This function shall not be called after the Clock Security System on HSE has been + * enabled. + * @retval None + */ +void HAL_RCCEx_WakeUpStopCLKConfig(uint32_t WakeUpClk) +{ + assert_param(IS_RCC_STOP_WAKEUPCLOCK(WakeUpClk)); + + __HAL_RCC_WAKEUPSTOP_CLK_CONFIG(WakeUpClk); +} + +/** + * @brief Configure the MSI range after standby mode. + * @note After Standby its frequency can be selected between 4 possible values (1, 2, 4 or 8 MHz). + * @param MSIRange MSI range + * This parameter can be one of the following values: + * @arg @ref RCC_MSIRANGE_4 Range 4 around 1 MHz + * @arg @ref RCC_MSIRANGE_5 Range 5 around 2 MHz + * @arg @ref RCC_MSIRANGE_6 Range 6 around 4 MHz (reset value) + * @arg @ref RCC_MSIRANGE_7 Range 7 around 8 MHz + * @retval None + */ +void HAL_RCCEx_StandbyMSIRangeConfig(uint32_t MSIRange) +{ + assert_param(IS_RCC_MSI_STANDBY_CLOCK_RANGE(MSIRange)); + + __HAL_RCC_MSI_STANDBY_RANGE_CONFIG(MSIRange); +} + +/** + * @brief Enable the LSE Clock Security System. + * @note Prior to enable the LSE Clock Security System, LSE oscillator is to be enabled + * with HAL_RCC_OscConfig() and the LSE oscillator clock is to be selected as RTC + * clock with HAL_RCCEx_PeriphCLKConfig(). + * @retval None + */ +void HAL_RCCEx_EnableLSECSS(void) +{ + SET_BIT(RCC->BDCR, RCC_BDCR_LSECSSON) ; +} + +/** + * @brief Disable the LSE Clock Security System. + * @note LSE Clock Security System can only be disabled after a LSE failure detection. + * @retval None + */ +void HAL_RCCEx_DisableLSECSS(void) +{ + CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSECSSON) ; + + /* Disable LSE CSS IT if any */ + __HAL_RCC_DISABLE_IT(RCC_IT_LSECSS); +} + +/** + * @brief Enable the LSE Clock Security System Interrupt & corresponding EXTI line. + * @note LSE Clock Security System Interrupt is mapped on RTC EXTI line 19 + * @retval None + */ +void HAL_RCCEx_EnableLSECSS_IT(void) +{ + /* Enable LSE CSS */ + SET_BIT(RCC->BDCR, RCC_BDCR_LSECSSON) ; + + /* Enable LSE CSS IT */ + __HAL_RCC_ENABLE_IT(RCC_IT_LSECSS); + + /* Enable IT on EXTI Line 19 */ + __HAL_RCC_LSECSS_EXTI_ENABLE_IT(); + __HAL_RCC_LSECSS_EXTI_ENABLE_RISING_EDGE(); +} + +/** + * @brief Handle the RCC LSE Clock Security System interrupt request. + * @retval None + */ +void HAL_RCCEx_LSECSS_IRQHandler(void) +{ + /* Check RCC LSE CSSF flag */ + if(__HAL_RCC_GET_IT(RCC_IT_LSECSS)) + { + /* RCC LSE Clock Security System interrupt user callback */ + HAL_RCCEx_LSECSS_Callback(); + + /* Clear RCC LSE CSS pending bit */ + __HAL_RCC_CLEAR_IT(RCC_IT_LSECSS); + } +} + +/** + * @brief RCCEx LSE Clock Security System interrupt callback. + * @retval none + */ +__weak void HAL_RCCEx_LSECSS_Callback(void) +{ + /* NOTE : This function should not be modified, when the callback is needed, + the @ref HAL_RCCEx_LSECSS_Callback should be implemented in the user file + */ +} + +/** + * @brief Select the Low Speed clock source to output on LSCO pin (PA2). + * @param LSCOSource specifies the Low Speed clock source to output. + * This parameter can be one of the following values: + * @arg @ref RCC_LSCOSOURCE_LSI LSI clock selected as LSCO source + * @arg @ref RCC_LSCOSOURCE_LSE LSE clock selected as LSCO source + * @retval None + */ +void HAL_RCCEx_EnableLSCO(uint32_t LSCOSource) +{ + GPIO_InitTypeDef GPIO_InitStruct; + FlagStatus pwrclkchanged = RESET; + FlagStatus backupchanged = RESET; + + /* Check the parameters */ + assert_param(IS_RCC_LSCOSOURCE(LSCOSource)); + + /* LSCO Pin Clock Enable */ + __LSCO_CLK_ENABLE(); + + /* Configue the LSCO pin in analog mode */ + GPIO_InitStruct.Pin = LSCO_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(LSCO_GPIO_PORT, &GPIO_InitStruct); + + /* Update LSCOSEL clock source in Backup Domain control register */ + if(__HAL_RCC_PWR_IS_CLK_DISABLED()) + { + __HAL_RCC_PWR_CLK_ENABLE(); + pwrclkchanged = SET; + } + if(HAL_IS_BIT_CLR(PWR->CR1, PWR_CR1_DBP)) + { + HAL_PWR_EnableBkUpAccess(); + backupchanged = SET; + } + + MODIFY_REG(RCC->BDCR, RCC_BDCR_LSCOSEL | RCC_BDCR_LSCOEN, LSCOSource | RCC_BDCR_LSCOEN); + + if(backupchanged == SET) + { + HAL_PWR_DisableBkUpAccess(); + } + if(pwrclkchanged == SET) + { + __HAL_RCC_PWR_CLK_DISABLE(); + } +} + +/** + * @brief Disable the Low Speed clock output. + * @retval None + */ +void HAL_RCCEx_DisableLSCO(void) +{ + FlagStatus pwrclkchanged = RESET; + FlagStatus backupchanged = RESET; + + /* Update LSCOEN bit in Backup Domain control register */ + if(__HAL_RCC_PWR_IS_CLK_DISABLED()) + { + __HAL_RCC_PWR_CLK_ENABLE(); + pwrclkchanged = SET; + } + if(HAL_IS_BIT_CLR(PWR->CR1, PWR_CR1_DBP)) + { + /* Enable access to the backup domain */ + HAL_PWR_EnableBkUpAccess(); + backupchanged = SET; + } + + CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSCOEN); + + /* Restore previous configuration */ + if(backupchanged == SET) + { + /* Disable access to the backup domain */ + HAL_PWR_DisableBkUpAccess(); + } + if(pwrclkchanged == SET) + { + __HAL_RCC_PWR_CLK_DISABLE(); + } +} + +/** + * @brief Enable the PLL-mode of the MSI. + * @note Prior to enable the PLL-mode of the MSI for automatic hardware + * calibration LSE oscillator is to be enabled with HAL_RCC_OscConfig(). + * @retval None + */ +void HAL_RCCEx_EnableMSIPLLMode(void) +{ + SET_BIT(RCC->CR, RCC_CR_MSIPLLEN) ; +} + +/** + * @brief Disable the PLL-mode of the MSI. + * @note PLL-mode of the MSI is automatically reset when LSE oscillator is disabled. + * @retval None + */ +void HAL_RCCEx_DisableMSIPLLMode(void) +{ + CLEAR_BIT(RCC->CR, RCC_CR_MSIPLLEN) ; +} + +/** + * @} + */ + +#if defined(CRS) + +/** @defgroup RCCEx_Exported_Functions_Group3 Extended Clock Recovery System Control functions + * @brief Extended Clock Recovery System Control functions + * +@verbatim + =============================================================================== + ##### Extended Clock Recovery System Control functions ##### + =============================================================================== + [..] + For devices with Clock Recovery System feature (CRS), RCC Extention HAL driver can be used as follows: + + (#) In System clock config, HSI48 needs to be enabled + + (#) Enable CRS clock in IP MSP init which will use CRS functions + + (#) Call CRS functions as follows: + (##) Prepare synchronization configuration necessary for HSI48 calibration + (+++) Default values can be set for frequency Error Measurement (reload and error limit) + and also HSI48 oscillator smooth trimming. + (+++) Macro __HAL_RCC_CRS_RELOADVALUE_CALCULATE can be also used to calculate + directly reload value with target and sychronization frequencies values + (##) Call function HAL_RCCEx_CRSConfig which + (+++) Resets CRS registers to their default values. + (+++) Configures CRS registers with synchronization configuration + (+++) Enables automatic calibration and frequency error counter feature + Note: When using USB LPM (Link Power Management) and the device is in Sleep mode, the + periodic USB SOF will not be generated by the host. No SYNC signal will therefore be + provided to the CRS to calibrate the HSI48 on the run. To guarantee the required clock + precision after waking up from Sleep mode, the LSE or reference clock on the GPIOs + should be used as SYNC signal. + + (##) A polling function is provided to wait for complete synchronization + (+++) Call function HAL_RCCEx_CRSWaitSynchronization() + (+++) According to CRS status, user can decide to adjust again the calibration or continue + application if synchronization is OK + + (#) User can retrieve information related to synchronization in calling function + HAL_RCCEx_CRSGetSynchronizationInfo() + + (#) Regarding synchronization status and synchronization information, user can try a new calibration + in changing synchronization configuration and call again HAL_RCCEx_CRSConfig. + Note: When the SYNC event is detected during the downcounting phase (before reaching the zero value), + it means that the actual frequency is lower than the target (and so, that the TRIM value should be + incremented), while when it is detected during the upcounting phase it means that the actual frequency + is higher (and that the TRIM value should be decremented). + + (#) In interrupt mode, user can resort to the available macros (__HAL_RCC_CRS_XXX_IT). Interrupts will go + through CRS Handler (CRS_IRQn/CRS_IRQHandler) + (++) Call function HAL_RCCEx_CRSConfig() + (++) Enable CRS_IRQn (thanks to NVIC functions) + (++) Enable CRS interrupt (__HAL_RCC_CRS_ENABLE_IT) + (++) Implement CRS status management in the following user callbacks called from + HAL_RCCEx_CRS_IRQHandler(): + (+++) HAL_RCCEx_CRS_SyncOkCallback() + (+++) HAL_RCCEx_CRS_SyncWarnCallback() + (+++) HAL_RCCEx_CRS_ExpectedSyncCallback() + (+++) HAL_RCCEx_CRS_ErrorCallback() + + (#) To force a SYNC EVENT, user can use the function HAL_RCCEx_CRSSoftwareSynchronizationGenerate(). + This function can be called before calling HAL_RCCEx_CRSConfig (for instance in Systick handler) + +@endverbatim + * @{ + */ + +/** + * @brief Start automatic synchronization for polling mode + * @param pInit Pointer on RCC_CRSInitTypeDef structure + * @retval None + */ +void HAL_RCCEx_CRSConfig(RCC_CRSInitTypeDef *pInit) +{ + uint32_t value = 0; + + /* Check the parameters */ + assert_param(IS_RCC_CRS_SYNC_DIV(pInit->Prescaler)); + assert_param(IS_RCC_CRS_SYNC_SOURCE(pInit->Source)); + assert_param(IS_RCC_CRS_SYNC_POLARITY(pInit->Polarity)); + assert_param(IS_RCC_CRS_RELOADVALUE(pInit->ReloadValue)); + assert_param(IS_RCC_CRS_ERRORLIMIT(pInit->ErrorLimitValue)); + assert_param(IS_RCC_CRS_HSI48CALIBRATION(pInit->HSI48CalibrationValue)); + + /* CONFIGURATION */ + + /* Before configuration, reset CRS registers to their default values*/ + __HAL_RCC_CRS_FORCE_RESET(); + __HAL_RCC_CRS_RELEASE_RESET(); + + /* Set the SYNCDIV[2:0] bits according to Prescaler value */ + /* Set the SYNCSRC[1:0] bits according to Source value */ + /* Set the SYNCSPOL bit according to Polarity value */ + value = (pInit->Prescaler | pInit->Source | pInit->Polarity); + /* Set the RELOAD[15:0] bits according to ReloadValue value */ + value |= pInit->ReloadValue; + /* Set the FELIM[7:0] bits according to ErrorLimitValue value */ + value |= (pInit->ErrorLimitValue << CRS_CFGR_FELIM_Pos); + WRITE_REG(CRS->CFGR, value); + + /* Adjust HSI48 oscillator smooth trimming */ + /* Set the TRIM[5:0] bits according to RCC_CRS_HSI48CalibrationValue value */ + MODIFY_REG(CRS->CR, CRS_CR_TRIM, (pInit->HSI48CalibrationValue << CRS_CR_TRIM_Pos)); + + /* START AUTOMATIC SYNCHRONIZATION*/ + + /* Enable Automatic trimming & Frequency error counter */ + SET_BIT(CRS->CR, CRS_CR_AUTOTRIMEN | CRS_CR_CEN); +} + +/** + * @brief Generate the software synchronization event + * @retval None + */ +void HAL_RCCEx_CRSSoftwareSynchronizationGenerate(void) +{ + SET_BIT(CRS->CR, CRS_CR_SWSYNC); +} + +/** + * @brief Return synchronization info + * @param pSynchroInfo Pointer on RCC_CRSSynchroInfoTypeDef structure + * @retval None + */ +void HAL_RCCEx_CRSGetSynchronizationInfo(RCC_CRSSynchroInfoTypeDef *pSynchroInfo) +{ + /* Check the parameter */ + assert_param(pSynchroInfo != NULL); + + /* Get the reload value */ + pSynchroInfo->ReloadValue = (READ_BIT(CRS->CFGR, CRS_CFGR_RELOAD)); + + /* Get HSI48 oscillator smooth trimming */ + pSynchroInfo->HSI48CalibrationValue = (READ_BIT(CRS->CR, CRS_CR_TRIM) >> CRS_CR_TRIM_Pos); + + /* Get Frequency error capture */ + pSynchroInfo->FreqErrorCapture = (READ_BIT(CRS->ISR, CRS_ISR_FECAP) >> CRS_ISR_FECAP_Pos); + + /* Get Frequency error direction */ + pSynchroInfo->FreqErrorDirection = (READ_BIT(CRS->ISR, CRS_ISR_FEDIR)); +} + +/** +* @brief Wait for CRS Synchronization status. +* @param Timeout Duration of the timeout +* @note Timeout is based on the maximum time to receive a SYNC event based on synchronization +* frequency. +* @note If Timeout set to HAL_MAX_DELAY, HAL_TIMEOUT will be never returned. +* @retval Combination of Synchronization status +* This parameter can be a combination of the following values: +* @arg @ref RCC_CRS_TIMEOUT +* @arg @ref RCC_CRS_SYNCOK +* @arg @ref RCC_CRS_SYNCWARN +* @arg @ref RCC_CRS_SYNCERR +* @arg @ref RCC_CRS_SYNCMISS +* @arg @ref RCC_CRS_TRIMOVF +*/ +uint32_t HAL_RCCEx_CRSWaitSynchronization(uint32_t Timeout) +{ + uint32_t crsstatus = RCC_CRS_NONE; + uint32_t tickstart = 0U; + + /* Get timeout */ + tickstart = HAL_GetTick(); + + /* Wait for CRS flag or timeout detection */ + do + { + if(Timeout != HAL_MAX_DELAY) + { + if((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout)) + { + crsstatus = RCC_CRS_TIMEOUT; + } + } + /* Check CRS SYNCOK flag */ + if(__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_SYNCOK)) + { + /* CRS SYNC event OK */ + crsstatus |= RCC_CRS_SYNCOK; + + /* Clear CRS SYNC event OK bit */ + __HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_SYNCOK); + } + + /* Check CRS SYNCWARN flag */ + if(__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_SYNCWARN)) + { + /* CRS SYNC warning */ + crsstatus |= RCC_CRS_SYNCWARN; + + /* Clear CRS SYNCWARN bit */ + __HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_SYNCWARN); + } + + /* Check CRS TRIM overflow flag */ + if(__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_TRIMOVF)) + { + /* CRS SYNC Error */ + crsstatus |= RCC_CRS_TRIMOVF; + + /* Clear CRS Error bit */ + __HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_TRIMOVF); + } + + /* Check CRS Error flag */ + if(__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_SYNCERR)) + { + /* CRS SYNC Error */ + crsstatus |= RCC_CRS_SYNCERR; + + /* Clear CRS Error bit */ + __HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_SYNCERR); + } + + /* Check CRS SYNC Missed flag */ + if(__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_SYNCMISS)) + { + /* CRS SYNC Missed */ + crsstatus |= RCC_CRS_SYNCMISS; + + /* Clear CRS SYNC Missed bit */ + __HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_SYNCMISS); + } + + /* Check CRS Expected SYNC flag */ + if(__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_ESYNC)) + { + /* frequency error counter reached a zero value */ + __HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_ESYNC); + } + } while(RCC_CRS_NONE == crsstatus); + + return crsstatus; +} + +/** + * @brief Handle the Clock Recovery System interrupt request. + * @retval None + */ +void HAL_RCCEx_CRS_IRQHandler(void) +{ + uint32_t crserror = RCC_CRS_NONE; + /* Get current IT flags and IT sources values */ + uint32_t itflags = READ_REG(CRS->ISR); + uint32_t itsources = READ_REG(CRS->CR); + + /* Check CRS SYNCOK flag */ + if(((itflags & RCC_CRS_FLAG_SYNCOK) != RESET) && ((itsources & RCC_CRS_IT_SYNCOK) != RESET)) + { + /* Clear CRS SYNC event OK flag */ + WRITE_REG(CRS->ICR, CRS_ICR_SYNCOKC); + + /* user callback */ + HAL_RCCEx_CRS_SyncOkCallback(); + } + /* Check CRS SYNCWARN flag */ + else if(((itflags & RCC_CRS_FLAG_SYNCWARN) != RESET) && ((itsources & RCC_CRS_IT_SYNCWARN) != RESET)) + { + /* Clear CRS SYNCWARN flag */ + WRITE_REG(CRS->ICR, CRS_ICR_SYNCWARNC); + + /* user callback */ + HAL_RCCEx_CRS_SyncWarnCallback(); + } + /* Check CRS Expected SYNC flag */ + else if(((itflags & RCC_CRS_FLAG_ESYNC) != RESET) && ((itsources & RCC_CRS_IT_ESYNC) != RESET)) + { + /* frequency error counter reached a zero value */ + WRITE_REG(CRS->ICR, CRS_ICR_ESYNCC); + + /* user callback */ + HAL_RCCEx_CRS_ExpectedSyncCallback(); + } + /* Check CRS Error flags */ + else + { + if(((itflags & RCC_CRS_FLAG_ERR) != RESET) && ((itsources & RCC_CRS_IT_ERR) != RESET)) + { + if((itflags & RCC_CRS_FLAG_SYNCERR) != RESET) + { + crserror |= RCC_CRS_SYNCERR; + } + if((itflags & RCC_CRS_FLAG_SYNCMISS) != RESET) + { + crserror |= RCC_CRS_SYNCMISS; + } + if((itflags & RCC_CRS_FLAG_TRIMOVF) != RESET) + { + crserror |= RCC_CRS_TRIMOVF; + } + + /* Clear CRS Error flags */ + WRITE_REG(CRS->ICR, CRS_ICR_ERRC); + + /* user error callback */ + HAL_RCCEx_CRS_ErrorCallback(crserror); + } + } +} + +/** + * @brief RCCEx Clock Recovery System SYNCOK interrupt callback. + * @retval none + */ +__weak void HAL_RCCEx_CRS_SyncOkCallback(void) +{ + /* NOTE : This function should not be modified, when the callback is needed, + the @ref HAL_RCCEx_CRS_SyncOkCallback should be implemented in the user file + */ +} + +/** + * @brief RCCEx Clock Recovery System SYNCWARN interrupt callback. + * @retval none + */ +__weak void HAL_RCCEx_CRS_SyncWarnCallback(void) +{ + /* NOTE : This function should not be modified, when the callback is needed, + the @ref HAL_RCCEx_CRS_SyncWarnCallback should be implemented in the user file + */ +} + +/** + * @brief RCCEx Clock Recovery System Expected SYNC interrupt callback. + * @retval none + */ +__weak void HAL_RCCEx_CRS_ExpectedSyncCallback(void) +{ + /* NOTE : This function should not be modified, when the callback is needed, + the @ref HAL_RCCEx_CRS_ExpectedSyncCallback should be implemented in the user file + */ +} + +/** + * @brief RCCEx Clock Recovery System Error interrupt callback. + * @param Error Combination of Error status. + * This parameter can be a combination of the following values: + * @arg @ref RCC_CRS_SYNCERR + * @arg @ref RCC_CRS_SYNCMISS + * @arg @ref RCC_CRS_TRIMOVF + * @retval none + */ +__weak void HAL_RCCEx_CRS_ErrorCallback(uint32_t Error) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(Error); + + /* NOTE : This function should not be modified, when the callback is needed, + the @ref HAL_RCCEx_CRS_ErrorCallback should be implemented in the user file + */ +} + +/** + * @} + */ + +#endif /* CRS */ + +/** + * @} + */ + +/** @addtogroup RCCEx_Private_Functions + * @{ + */ + +/** + * @brief Configure the parameters N & P & optionally M of PLLSAI1 and enable PLLSAI1 output clock(s). + * @param PllSai1 pointer to an RCC_PLLSAI1InitTypeDef structure that + * contains the configuration parameters N & P & optionally M as well as PLLSAI1 output clock(s) + * @param Divider divider parameter to be updated + * + * @note PLLSAI1 is temporary disable to apply new parameters + * + * @retval HAL status + */ +static HAL_StatusTypeDef RCCEx_PLLSAI1_Config(RCC_PLLSAI1InitTypeDef *PllSai1, uint32_t Divider) +{ + uint32_t tickstart = 0U; + HAL_StatusTypeDef status = HAL_OK; + + /* check for PLLSAI1 Parameters used to output PLLSAI1CLK */ + /* P, Q and R dividers are verified in each specific divider case below */ + assert_param(IS_RCC_PLLSAI1SOURCE(PllSai1->PLLSAI1Source)); + assert_param(IS_RCC_PLLSAI1M_VALUE(PllSai1->PLLSAI1M)); + assert_param(IS_RCC_PLLSAI1N_VALUE(PllSai1->PLLSAI1N)); + assert_param(IS_RCC_PLLSAI1CLOCKOUT_VALUE(PllSai1->PLLSAI1ClockOut)); + + /* Check that PLLSAI1 clock source and divider M can be applied */ + if(__HAL_RCC_GET_PLL_OSCSOURCE() != RCC_PLLSOURCE_NONE) + { + /* PLL clock source and divider M already set, check that no request for change */ + if((__HAL_RCC_GET_PLL_OSCSOURCE() != PllSai1->PLLSAI1Source) + || + (PllSai1->PLLSAI1Source == RCC_PLLSOURCE_NONE) +#if !defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + || + (((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U) != PllSai1->PLLSAI1M) +#endif + ) + { + status = HAL_ERROR; + } + } + else + { + /* Check PLLSAI1 clock source availability */ + switch(PllSai1->PLLSAI1Source) + { + case RCC_PLLSOURCE_MSI: + if(HAL_IS_BIT_CLR(RCC->CR, RCC_CR_MSIRDY)) + { + status = HAL_ERROR; + } + break; + case RCC_PLLSOURCE_HSI: + if(HAL_IS_BIT_CLR(RCC->CR, RCC_CR_HSIRDY)) + { + status = HAL_ERROR; + } + break; + case RCC_PLLSOURCE_HSE: + if(HAL_IS_BIT_CLR(RCC->CR, RCC_CR_HSERDY) && HAL_IS_BIT_CLR(RCC->CR, RCC_CR_HSEBYP)) + { + status = HAL_ERROR; + } + break; + default: + status = HAL_ERROR; + break; + } + + if(status == HAL_OK) + { +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + /* Set PLLSAI1 clock source */ + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, PllSai1->PLLSAI1Source); +#else + /* Set PLLSAI1 clock source and divider M */ + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC | RCC_PLLCFGR_PLLM, PllSai1->PLLSAI1Source | (PllSai1->PLLSAI1M - 1U) << RCC_PLLCFGR_PLLM_Pos); +#endif + } + } + + if(status == HAL_OK) + { + /* Disable the PLLSAI1 */ + __HAL_RCC_PLLSAI1_DISABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till PLLSAI1 is ready to be updated */ + while(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) != RESET) + { + if((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE) + { + status = HAL_TIMEOUT; + break; + } + } + + if(status == HAL_OK) + { + if(Divider == DIVIDER_P_UPDATE) + { + assert_param(IS_RCC_PLLSAI1P_VALUE(PllSai1->PLLSAI1P)); +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + + /* Configure the PLLSAI1 Division factor M, P and Multiplication factor N*/ +#if defined(RCC_PLLSAI1P_DIV_2_31_SUPPORT) + MODIFY_REG(RCC->PLLSAI1CFGR, + RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1PDIV | RCC_PLLSAI1CFGR_PLLSAI1M, + (PllSai1->PLLSAI1N << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) | + (PllSai1->PLLSAI1P << RCC_PLLSAI1CFGR_PLLSAI1PDIV_Pos) | + ((PllSai1->PLLSAI1M - 1U) << RCC_PLLSAI1CFGR_PLLSAI1M_Pos)); +#else + MODIFY_REG(RCC->PLLSAI1CFGR, + RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1P | RCC_PLLSAI1CFGR_PLLSAI1M, + (PllSai1->PLLSAI1N << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) | + ((PllSai1->PLLSAI1P >> 4U) << RCC_PLLSAI1CFGR_PLLSAI1P_Pos) | + ((PllSai1->PLLSAI1M - 1U) << RCC_PLLSAI1CFGR_PLLSAI1M_Pos)); +#endif /* RCC_PLLSAI1P_DIV_2_31_SUPPORT */ + +#else + /* Configure the PLLSAI1 Division factor P and Multiplication factor N*/ +#if defined(RCC_PLLSAI1P_DIV_2_31_SUPPORT) + MODIFY_REG(RCC->PLLSAI1CFGR, + RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1PDIV, + (PllSai1->PLLSAI1N << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) | + (PllSai1->PLLSAI1P << RCC_PLLSAI1CFGR_PLLSAI1PDIV_Pos)); +#else + MODIFY_REG(RCC->PLLSAI1CFGR, + RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1P, + (PllSai1->PLLSAI1N << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) | + ((PllSai1->PLLSAI1P >> 4U) << RCC_PLLSAI1CFGR_PLLSAI1P_Pos)); +#endif /* RCC_PLLSAI1P_DIV_2_31_SUPPORT */ + +#endif /* RCC_PLLSAI1M_DIV_1_16_SUPPORT */ + } + else if(Divider == DIVIDER_Q_UPDATE) + { + assert_param(IS_RCC_PLLSAI1Q_VALUE(PllSai1->PLLSAI1Q)); +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + /* Configure the PLLSAI1 Division factor M, Q and Multiplication factor N*/ + MODIFY_REG(RCC->PLLSAI1CFGR, + RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1Q | RCC_PLLSAI1CFGR_PLLSAI1M, + (PllSai1->PLLSAI1N << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) | + (((PllSai1->PLLSAI1Q >> 1U) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1Q_Pos) | + ((PllSai1->PLLSAI1M - 1U) << RCC_PLLSAI1CFGR_PLLSAI1M_Pos)); +#else + /* Configure the PLLSAI1 Division factor Q and Multiplication factor N*/ + MODIFY_REG(RCC->PLLSAI1CFGR, + RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1Q, + (PllSai1->PLLSAI1N << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) | + (((PllSai1->PLLSAI1Q >> 1U) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1Q_Pos)); +#endif /* RCC_PLLSAI1M_DIV_1_16_SUPPORT */ + } + else + { + assert_param(IS_RCC_PLLSAI1R_VALUE(PllSai1->PLLSAI1R)); +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) + /* Configure the PLLSAI1 Division factor M, R and Multiplication factor N*/ + MODIFY_REG(RCC->PLLSAI1CFGR, + RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1R | RCC_PLLSAI1CFGR_PLLSAI1M, + (PllSai1->PLLSAI1N << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) | + (((PllSai1->PLLSAI1R >> 1U) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1R_Pos) | + ((PllSai1->PLLSAI1M - 1U) << RCC_PLLSAI1CFGR_PLLSAI1M_Pos)); +#else + /* Configure the PLLSAI1 Division factor R and Multiplication factor N*/ + MODIFY_REG(RCC->PLLSAI1CFGR, + RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1R, + (PllSai1->PLLSAI1N << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) | + (((PllSai1->PLLSAI1R >> 1U) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1R_Pos)); +#endif /* RCC_PLLSAI1M_DIV_1_16_SUPPORT */ + } + + /* Enable the PLLSAI1 again by setting PLLSAI1ON to 1*/ + __HAL_RCC_PLLSAI1_ENABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till PLLSAI1 is ready */ + while(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) == RESET) + { + if((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE) + { + status = HAL_TIMEOUT; + break; + } + } + + if(status == HAL_OK) + { + /* Configure the PLLSAI1 Clock output(s) */ + __HAL_RCC_PLLSAI1CLKOUT_ENABLE(PllSai1->PLLSAI1ClockOut); + } + } + } + + return status; +} + +#if defined(RCC_PLLSAI2_SUPPORT) + +/** + * @brief Configure the parameters N & P & optionally M of PLLSAI2 and enable PLLSAI2 output clock(s). + * @param PllSai2 pointer to an RCC_PLLSAI2InitTypeDef structure that + * contains the configuration parameters N & P & optionally M as well as PLLSAI2 output clock(s) + * @param Divider divider parameter to be updated + * + * @note PLLSAI2 is temporary disable to apply new parameters + * + * @retval HAL status + */ +static HAL_StatusTypeDef RCCEx_PLLSAI2_Config(RCC_PLLSAI2InitTypeDef *PllSai2, uint32_t Divider) +{ + uint32_t tickstart = 0U; + HAL_StatusTypeDef status = HAL_OK; + + /* check for PLLSAI2 Parameters used to output PLLSAI2CLK */ + /* P, Q and R dividers are verified in each specific divider case below */ + assert_param(IS_RCC_PLLSAI2SOURCE(PllSai2->PLLSAI2Source)); + assert_param(IS_RCC_PLLSAI2M_VALUE(PllSai2->PLLSAI2M)); + assert_param(IS_RCC_PLLSAI2N_VALUE(PllSai2->PLLSAI2N)); + assert_param(IS_RCC_PLLSAI2CLOCKOUT_VALUE(PllSai2->PLLSAI2ClockOut)); + + /* Check that PLLSAI2 clock source and divider M can be applied */ + if(__HAL_RCC_GET_PLL_OSCSOURCE() != RCC_PLLSOURCE_NONE) + { + /* PLL clock source and divider M already set, check that no request for change */ + if((__HAL_RCC_GET_PLL_OSCSOURCE() != PllSai2->PLLSAI2Source) + || + (PllSai2->PLLSAI2Source == RCC_PLLSOURCE_NONE) +#if !defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + || + (((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U) != PllSai2->PLLSAI2M) +#endif + ) + { + status = HAL_ERROR; + } + } + else + { + /* Check PLLSAI2 clock source availability */ + switch(PllSai2->PLLSAI2Source) + { + case RCC_PLLSOURCE_MSI: + if(HAL_IS_BIT_CLR(RCC->CR, RCC_CR_MSIRDY)) + { + status = HAL_ERROR; + } + break; + case RCC_PLLSOURCE_HSI: + if(HAL_IS_BIT_CLR(RCC->CR, RCC_CR_HSIRDY)) + { + status = HAL_ERROR; + } + break; + case RCC_PLLSOURCE_HSE: + if(HAL_IS_BIT_CLR(RCC->CR, RCC_CR_HSERDY) && HAL_IS_BIT_CLR(RCC->CR, RCC_CR_HSEBYP)) + { + status = HAL_ERROR; + } + break; + default: + status = HAL_ERROR; + break; + } + + if(status == HAL_OK) + { +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + /* Set PLLSAI2 clock source */ + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, PllSai2->PLLSAI2Source); +#else + /* Set PLLSAI2 clock source and divider M */ + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC | RCC_PLLCFGR_PLLM, PllSai2->PLLSAI2Source | (PllSai2->PLLSAI2M - 1U) << RCC_PLLCFGR_PLLM_Pos); +#endif + } + } + + if(status == HAL_OK) + { + /* Disable the PLLSAI2 */ + __HAL_RCC_PLLSAI2_DISABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till PLLSAI2 is ready to be updated */ + while(READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) != RESET) + { + if((HAL_GetTick() - tickstart) > PLLSAI2_TIMEOUT_VALUE) + { + status = HAL_TIMEOUT; + break; + } + } + + if(status == HAL_OK) + { + if(Divider == DIVIDER_P_UPDATE) + { + assert_param(IS_RCC_PLLSAI2P_VALUE(PllSai2->PLLSAI2P)); +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + + /* Configure the PLLSAI2 Division factor M, P and Multiplication factor N*/ +#if defined(RCC_PLLSAI2P_DIV_2_31_SUPPORT) + MODIFY_REG(RCC->PLLSAI2CFGR, + RCC_PLLSAI2CFGR_PLLSAI2N | RCC_PLLSAI2CFGR_PLLSAI2PDIV | RCC_PLLSAI2CFGR_PLLSAI2M, + (PllSai2->PLLSAI2N << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | + (PllSai2->PLLSAI2P << RCC_PLLSAI2CFGR_PLLSAI2PDIV_Pos) | + ((PllSai2->PLLSAI2M - 1U) << RCC_PLLSAI2CFGR_PLLSAI2M_Pos)); +#else + MODIFY_REG(RCC->PLLSAI2CFGR, + RCC_PLLSAI2CFGR_PLLSAI2N | RCC_PLLSAI2CFGR_PLLSAI2P | RCC_PLLSAI2CFGR_PLLSAI2M, + (PllSai2->PLLSAI2N << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | + ((PllSai2->PLLSAI2P >> 4U) << RCC_PLLSAI2CFGR_PLLSAI2P_Pos) | + ((PllSai2->PLLSAI2M - 1U) << RCC_PLLSAI2CFGR_PLLSAI2M_Pos)); +#endif /* RCC_PLLSAI2P_DIV_2_31_SUPPORT */ + +#else + /* Configure the PLLSAI2 Division factor P and Multiplication factor N*/ +#if defined(RCC_PLLSAI2P_DIV_2_31_SUPPORT) + MODIFY_REG(RCC->PLLSAI2CFGR, + RCC_PLLSAI2CFGR_PLLSAI2N | RCC_PLLSAI2CFGR_PLLSAI2PDIV, + (PllSai2->PLLSAI2N << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | + (PllSai2->PLLSAI2P << RCC_PLLSAI2CFGR_PLLSAI2PDIV_Pos)); +#else + MODIFY_REG(RCC->PLLSAI2CFGR, + RCC_PLLSAI2CFGR_PLLSAI2N | RCC_PLLSAI2CFGR_PLLSAI2P, + (PllSai2->PLLSAI2N << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | + ((PllSai2->PLLSAI2P >> 4U) << RCC_PLLSAI2CFGR_PLLSAI2P_Pos)); +#endif /* RCC_PLLSAI2P_DIV_2_31_SUPPORT */ + +#endif /* RCC_PLLSAI2M_DIV_1_16_SUPPORT */ + } +#if defined(RCC_PLLSAI2Q_DIV_SUPPORT) + else if(Divider == DIVIDER_Q_UPDATE) + { + assert_param(IS_RCC_PLLSAI2Q_VALUE(PllSai2->PLLSAI2Q)); +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + /* Configure the PLLSAI2 Division factor M, Q and Multiplication factor N*/ + MODIFY_REG(RCC->PLLSAI2CFGR, + RCC_PLLSAI2CFGR_PLLSAI2N | RCC_PLLSAI2CFGR_PLLSAI2Q | RCC_PLLSAI2CFGR_PLLSAI2M, + (PllSai2->PLLSAI2N << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | + (((PllSai2->PLLSAI2Q >> 1U) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2Q_Pos) | + ((PllSai2->PLLSAI2M - 1U) << RCC_PLLSAI2CFGR_PLLSAI2M_Pos)); +#else + /* Configure the PLLSAI2 Division factor Q and Multiplication factor N*/ + MODIFY_REG(RCC->PLLSAI2CFGR, + RCC_PLLSAI2CFGR_PLLSAI2N | RCC_PLLSAI2CFGR_PLLSAI2Q, + (PllSai2->PLLSAI2N << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | + (((PllSai2->PLLSAI2Q >> 1U) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2Q_Pos)); +#endif /* RCC_PLLSAI2M_DIV_1_16_SUPPORT */ + } +#endif /* RCC_PLLSAI2Q_DIV_SUPPORT */ + else + { + assert_param(IS_RCC_PLLSAI2R_VALUE(PllSai2->PLLSAI2R)); +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + /* Configure the PLLSAI2 Division factor M, R and Multiplication factor N*/ + MODIFY_REG(RCC->PLLSAI2CFGR, + RCC_PLLSAI2CFGR_PLLSAI2N | RCC_PLLSAI2CFGR_PLLSAI2R | RCC_PLLSAI2CFGR_PLLSAI2M, + (PllSai2->PLLSAI2N << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | + (((PllSai2->PLLSAI2R >> 1U) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2R_Pos) | + ((PllSai2->PLLSAI2M - 1U) << RCC_PLLSAI2CFGR_PLLSAI2M_Pos)); +#else + /* Configure the PLLSAI2 Division factor R and Multiplication factor N*/ + MODIFY_REG(RCC->PLLSAI2CFGR, + RCC_PLLSAI2CFGR_PLLSAI2N | RCC_PLLSAI2CFGR_PLLSAI2R, + (PllSai2->PLLSAI2N << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | + (((PllSai2->PLLSAI2R >> 1U) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2R_Pos)); +#endif /* RCC_PLLSAI2M_DIV_1_16_SUPPORT */ + } + + /* Enable the PLLSAI2 again by setting PLLSAI2ON to 1*/ + __HAL_RCC_PLLSAI2_ENABLE(); + + /* Get Start Tick*/ + tickstart = HAL_GetTick(); + + /* Wait till PLLSAI2 is ready */ + while(READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) == RESET) + { + if((HAL_GetTick() - tickstart) > PLLSAI2_TIMEOUT_VALUE) + { + status = HAL_TIMEOUT; + break; + } + } + + if(status == HAL_OK) + { + /* Configure the PLLSAI2 Clock output(s) */ + __HAL_RCC_PLLSAI2CLKOUT_ENABLE(PllSai2->PLLSAI2ClockOut); + } + } + } + + return status; +} + +#endif /* RCC_PLLSAI2_SUPPORT */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* HAL_RCC_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rng.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rng.c new file mode 100644 index 0000000..b5df280 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rng.c @@ -0,0 +1,527 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_rng.c + * @author MCD Application Team + * @brief RNG HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Random Number Generator (RNG) peripheral: + * + Initialization/de-initialization functions + * + Peripheral Control functions + * + Peripheral State functions + * + @verbatim + ============================================================================== + ##### How to use this driver ##### + ============================================================================== + [..] + The RNG HAL driver can be used as follows: + + (#) Enable the RNG controller clock using __HAL_RCC_RNG_CLK_ENABLE() macro + in HAL_RNG_MspInit(). + (#) Activate the RNG peripheral using HAL_RNG_Init() function. + (#) Wait until the 32-bit Random Number Generator contains a valid + random data using (polling/interrupt) mode. + (#) Get the 32 bit random number using HAL_RNG_GenerateRandomNumber() function. + + @endverbatim + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup RNG RNG + * @brief RNG HAL module driver. + * @{ + */ + +#ifdef HAL_RNG_MODULE_ENABLED + + + +/* Private types -------------------------------------------------------------*/ +/* Private defines -----------------------------------------------------------*/ +/** @defgroup RNG_Private_Constants RNG_Private_Constants + * @{ + */ +#define RNG_TIMEOUT_VALUE 2 +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/** @addtogroup RNG_Exported_Functions + * @{ + */ + +/** @addtogroup RNG_Exported_Functions_Group1 + * @brief Initialization and de-initialization functions + * +@verbatim + =============================================================================== + ##### Initialization and de-initialization functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Initialize the RNG according to the specified parameters + in the RNG_InitTypeDef and create the associated handle + (+) DeInitialize the RNG peripheral + (+) Initialize the RNG MSP (MCU Specific Package) + (+) DeInitialize the RNG MSP + +@endverbatim + * @{ + */ + +/** + * @brief Initialize the RNG peripheral and initialize the associated handle. + * @param hrng: pointer to a RNG_HandleTypeDef structure. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RNG_Init(RNG_HandleTypeDef *hrng) +{ + /* Check the RNG handle allocation */ + if(hrng == NULL) + { + return HAL_ERROR; + } + + assert_param(IS_RNG_ALL_INSTANCE(hrng->Instance)); +#if defined(RNG_CR_CED) + assert_param(IS_RNG_CED(hrng->Init.ClockErrorDetection)); +#endif /* defined(RNG_CR_CED) */ + + if(hrng->State == HAL_RNG_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hrng->Lock = HAL_UNLOCKED; + + /* Init the low level hardware */ + HAL_RNG_MspInit(hrng); + } + + /* Change RNG peripheral state */ + hrng->State = HAL_RNG_STATE_BUSY; + +#if defined(RNG_CR_CED) + /* Clock Error Detection configuration */ + MODIFY_REG(hrng->Instance->CR, RNG_CR_CED, hrng->Init.ClockErrorDetection); +#endif /* defined(RNG_CR_CED) */ + + /* Enable the RNG Peripheral */ + __HAL_RNG_ENABLE(hrng); + + /* Initialize the RNG state */ + hrng->State = HAL_RNG_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief DeInitialize the RNG peripheral. + * @param hrng: pointer to a RNG_HandleTypeDef structure. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RNG_DeInit(RNG_HandleTypeDef *hrng) +{ + /* Check the RNG handle allocation */ + if(hrng == NULL) + { + return HAL_ERROR; + } + +#if defined(RNG_CR_CED) + /* Clear Clock Error Detection bit */ + CLEAR_BIT(hrng->Instance->CR, RNG_CR_CED); +#endif /* defined(RNG_CR_CED) */ + + /* Disable the RNG Peripheral */ + CLEAR_BIT(hrng->Instance->CR, RNG_CR_IE | RNG_CR_RNGEN); + + /* Clear RNG interrupt status flags */ + CLEAR_BIT(hrng->Instance->SR, RNG_SR_CEIS | RNG_SR_SEIS); + + /* DeInit the low level hardware */ + HAL_RNG_MspDeInit(hrng); + + /* Update the RNG state */ + hrng->State = HAL_RNG_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(hrng); + + /* Return the function status */ + return HAL_OK; +} + +/** + * @brief Initialize the RNG MSP. + * @param hrng: pointer to a RNG_HandleTypeDef structure. + * @retval None + */ +__weak void HAL_RNG_MspInit(RNG_HandleTypeDef *hrng) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hrng); + + /* NOTE : This function should not be modified. When the callback is needed, + function HAL_RNG_MspInit must be implemented in the user file. + */ +} + +/** + * @brief DeInitialize the RNG MSP. + * @param hrng: pointer to a RNG_HandleTypeDef structure. + * @retval None + */ +__weak void HAL_RNG_MspDeInit(RNG_HandleTypeDef *hrng) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hrng); + + /* NOTE : This function should not be modified. When the callback is needed, + function HAL_RNG_MspDeInit must be implemented in the user file. + */ +} + +/** + * @} + */ + +/** @addtogroup RNG_Exported_Functions_Group2 + * @brief Management functions. + * +@verbatim + =============================================================================== + ##### Peripheral Control functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Get the 32 bit Random number + (+) Get the 32 bit Random number with interrupt enabled + (+) Handle RNG interrupt request + +@endverbatim + * @{ + */ + +/** + * @brief Generate a 32-bit random number. + * @note Each time the random number data is read the RNG_FLAG_DRDY flag + * is automatically cleared. + * @param hrng: pointer to a RNG_HandleTypeDef structure. + * @param random32bit: pointer to generated random number variable if successful. + * @retval HAL status + */ + +HAL_StatusTypeDef HAL_RNG_GenerateRandomNumber(RNG_HandleTypeDef *hrng, uint32_t *random32bit) +{ + uint32_t tickstart = 0; + HAL_StatusTypeDef status = HAL_OK; + + /* Process Locked */ + __HAL_LOCK(hrng); + + /* Check RNS peripheral state */ + if(hrng->State == HAL_RNG_STATE_READY) + { + /* Change RNG peripheral state */ + hrng->State = HAL_RNG_STATE_BUSY; + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Check if data register contains valid random data */ + while(__HAL_RNG_GET_FLAG(hrng, RNG_FLAG_DRDY) == RESET) + { + if((HAL_GetTick() - tickstart ) > RNG_TIMEOUT_VALUE) + { + hrng->State = HAL_RNG_STATE_ERROR; + + /* Process Unlocked */ + __HAL_UNLOCK(hrng); + + return HAL_TIMEOUT; + } + } + + /* Get a 32bit Random number */ + hrng->RandomNumber = hrng->Instance->DR; + *random32bit = hrng->RandomNumber; + + hrng->State = HAL_RNG_STATE_READY; + } + else + { + status = HAL_ERROR; + } + + /* Process Unlocked */ + __HAL_UNLOCK(hrng); + + return status; +} + +/** + * @brief Generate a 32-bit random number in interrupt mode. + * @param hrng: pointer to a RNG_HandleTypeDef structure. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RNG_GenerateRandomNumber_IT(RNG_HandleTypeDef *hrng) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process Locked */ + __HAL_LOCK(hrng); + + /* Check RNG peripheral state */ + if(hrng->State == HAL_RNG_STATE_READY) + { + /* Change RNG peripheral state */ + hrng->State = HAL_RNG_STATE_BUSY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrng); + + /* Enable the RNG Interrupts: Data Ready, Clock error, Seed error */ + __HAL_RNG_ENABLE_IT(hrng); + } + else + { + /* Process Unlocked */ + __HAL_UNLOCK(hrng); + + status = HAL_ERROR; + } + + return status; +} + +/** + * @brief Handle RNG interrupt request. + * @note In the case of a clock error, the RNG is no more able to generate + * random numbers because the PLL48CLK clock is not correct. User has + * to check that the clock controller is correctly configured to provide + * the RNG clock and clear the CEIS bit using __HAL_RNG_CLEAR_IT(). + * The clock error has no impact on the previously generated + * random numbers, and the RNG_DR register contents can be used. + * @note In the case of a seed error, the generation of random numbers is + * interrupted as long as the SECS bit is '1'. If a number is + * available in the RNG_DR register, it must not be used because it may + * not have enough entropy. In this case, it is recommended to clear the + * SEIS bit using __HAL_RNG_CLEAR_IT(), then disable and enable + * the RNG peripheral to reinitialize and restart the RNG. + * @note User-written HAL_RNG_ErrorCallback() API is called once whether SEIS + * or CEIS are set. + * @param hrng: pointer to a RNG_HandleTypeDef structure. + * @retval None + + */ +void HAL_RNG_IRQHandler(RNG_HandleTypeDef *hrng) +{ + /* RNG clock error interrupt occurred */ + if((__HAL_RNG_GET_IT(hrng, RNG_IT_CEI) != RESET) || (__HAL_RNG_GET_IT(hrng, RNG_IT_SEI) != RESET)) + { + /* Change RNG peripheral state */ + hrng->State = HAL_RNG_STATE_ERROR; + + HAL_RNG_ErrorCallback(hrng); + + /* Clear the clock error flag */ + __HAL_RNG_CLEAR_IT(hrng, RNG_IT_CEI|RNG_IT_SEI); + + } + + /* Check RNG data ready interrupt occurred */ + if(__HAL_RNG_GET_IT(hrng, RNG_IT_DRDY) != RESET) + { + /* Generate random number once, so disable the IT */ + __HAL_RNG_DISABLE_IT(hrng); + + /* Get the 32bit Random number (DRDY flag automatically cleared) */ + hrng->RandomNumber = hrng->Instance->DR; + + if(hrng->State != HAL_RNG_STATE_ERROR) + { + /* Change RNG peripheral state */ + hrng->State = HAL_RNG_STATE_READY; + + /* Data Ready callback */ + HAL_RNG_ReadyDataCallback(hrng, hrng->RandomNumber); + } + } +} + +/** + * @brief Return generated random number in polling mode (Obsolete). + * @note Use HAL_RNG_GenerateRandomNumber() API instead. + * @param hrng: pointer to a RNG_HandleTypeDef structure that contains + * the configuration information for RNG. + * @retval random value + */ +uint32_t HAL_RNG_GetRandomNumber(RNG_HandleTypeDef *hrng) +{ + if(HAL_RNG_GenerateRandomNumber(hrng, &(hrng->RandomNumber)) == HAL_OK) + { + return hrng->RandomNumber; + } + else + { + return 0; + } +} + + +/** + * @brief Return a 32-bit random number with interrupt enabled (Obsolete). + * @note Use HAL_RNG_GenerateRandomNumber_IT() API instead. + * @param hrng: RNG handle + * @retval 32-bit random number + */ +uint32_t HAL_RNG_GetRandomNumber_IT(RNG_HandleTypeDef *hrng) +{ + uint32_t random32bit = 0; + + /* Process locked */ + __HAL_LOCK(hrng); + + /* Change RNG peripheral state */ + hrng->State = HAL_RNG_STATE_BUSY; + + /* Get a 32bit Random number */ + random32bit = hrng->Instance->DR; + + /* Enable the RNG Interrupts: Data Ready, Clock error, Seed error */ + __HAL_RNG_ENABLE_IT(hrng); + + /* Return the 32 bit random number */ + return random32bit; +} + + + +/** + * @brief Read latest generated random number. + * @param hrng: pointer to a RNG_HandleTypeDef structure. + * @retval random value + */ +uint32_t HAL_RNG_ReadLastRandomNumber(RNG_HandleTypeDef *hrng) +{ + return(hrng->RandomNumber); +} + +/** + * @brief Data Ready callback in non-blocking mode. + * @param hrng: pointer to a RNG_HandleTypeDef structure. + * @param random32bit: generated random value + * @retval None + */ +__weak void HAL_RNG_ReadyDataCallback(RNG_HandleTypeDef *hrng, uint32_t random32bit) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hrng); + UNUSED(random32bit); + + /* NOTE : This function should not be modified. When the callback is needed, + function HAL_RNG_ReadyDataCallback must be implemented in the user file. + */ +} + +/** + * @brief RNG error callback. + * @param hrng: pointer to a RNG_HandleTypeDef structure. + * @retval None + */ +__weak void HAL_RNG_ErrorCallback(RNG_HandleTypeDef *hrng) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hrng); + + /* NOTE : This function should not be modified. When the callback is needed, + function HAL_RNG_ErrorCallback must be implemented in the user file. + */ +} + +/** + * @} + */ + +/** @addtogroup RNG_Exported_Functions_Group3 + * @brief Peripheral State functions. + * +@verbatim + =============================================================================== + ##### Peripheral State functions ##### + =============================================================================== + [..] + This subsection permits to get in run-time the status of the peripheral. + +@endverbatim + * @{ + */ + +/** + * @brief Return the RNG handle state. + * @param hrng: pointer to a RNG_HandleTypeDef structure. + * @retval HAL state + */ +HAL_RNG_StateTypeDef HAL_RNG_GetState(RNG_HandleTypeDef *hrng) +{ + /* Return RNG handle state */ + return hrng->State; +} + +/** + * @} + */ + +/** + * @} + */ + + +#endif /* HAL_RNG_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rtc.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rtc.c new file mode 100644 index 0000000..eb08d77 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rtc.c @@ -0,0 +1,1539 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_rtc.c + * @author MCD Application Team + * @brief RTC HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Real-Time Clock (RTC) peripheral: + * + Initialization + * + Calendar (Time and Date) configuration + * + Alarms (Alarm A and Alarm B) configuration + * + WakeUp Timer configuration + * + TimeStamp configuration + * + Tampers configuration + * + Backup Data Registers configuration + * + RTC Tamper and TimeStamp Pins Selection + * + Interrupts and flags management + * + @verbatim + =============================================================================== + ##### RTC Operating Condition ##### + =============================================================================== + [..] The real-time clock (RTC) and the RTC backup registers can be powered + from the VBAT voltage when the main VDD supply is powered off. + To retain the content of the RTC backup registers and supply the RTC + when VDD is turned off, VBAT pin can be connected to an optional + standby voltage supplied by a battery or by another source. + + ##### Backup Domain Reset ##### + =============================================================================== + [..] The backup domain reset sets all RTC registers and the RCC_BDCR register + to their reset values. + A backup domain reset is generated when one of the following events occurs: + (#) Software reset, triggered by setting the BDRST bit in the + RCC Backup domain control register (RCC_BDCR). + (#) VDD or VBAT power on, if both supplies have previously been powered off. + (#) Tamper detection event resets all data backup registers. + + ##### Backup Domain Access ##### + =================================================================== + [..] After reset, the backup domain (RTC registers, RTC backup data + registers and backup SRAM) is protected against possible unwanted write + accesses. + + [..] To enable access to the RTC Domain and RTC registers, proceed as follows: + (#) Call the function HAL_RCCEx_PeriphCLKConfig with RCC_PERIPHCLK_RTC for + PeriphClockSelection and select RTCClockSelection (LSE, LSI or HSEdiv32) + (#) Enable RTC Clock using the __HAL_RCC_RTC_ENABLE() macro. + + ##### How to use RTC Driver ##### + =================================================================== + [..] + (#) Enable the RTC domain access (see description in the section above). + (#) Configure the RTC Prescaler (Asynchronous and Synchronous) and RTC hour + format using the HAL_RTC_Init() function. + + *** Time and Date configuration *** + =================================== + [..] + (#) To configure the RTC Calendar (Time and Date) use the HAL_RTC_SetTime() + and HAL_RTC_SetDate() functions. + (#) To read the RTC Calendar, use the HAL_RTC_GetTime() and HAL_RTC_GetDate() functions. + + *** Alarm configuration *** + =========================== + [..] + (#) To configure the RTC Alarm use the HAL_RTC_SetAlarm() function. + You can also configure the RTC Alarm with interrupt mode using the + HAL_RTC_SetAlarm_IT() function. + (#) To read the RTC Alarm, use the HAL_RTC_GetAlarm() function. + + ##### RTC and low power modes ##### + =================================================================== + [..] The MCU can be woken up from a low power mode by an RTC alternate + function. + [..] The RTC alternate functions are the RTC alarms (Alarm A and Alarm B), + RTC wakeup, RTC tamper event detection and RTC time stamp event detection. + These RTC alternate functions can wake up the system from the Stop and + Standby low power modes. + [..] The system can also wake up from low power modes without depending + on an external interrupt (Auto-wakeup mode), by using the RTC alarm + or the RTC wakeup events. + [..] The RTC provides a programmable time base for waking up from the + Stop or Standby mode at regular intervals. + Wakeup from STOP and Standby modes is possible only when the RTC clock source + is LSE or LSI. + + @endverbatim + + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup RTC RTC + * @brief RTC HAL module driver + * @{ + */ + +#ifdef HAL_RTC_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup RTC_Exported_Functions RTC Exported Functions + * @{ + */ + +/** @defgroup RTC_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions + * +@verbatim + =============================================================================== + ##### Initialization and de-initialization functions ##### + =============================================================================== + [..] This section provide functions allowing to initialize and configure the + RTC Prescaler (Synchronous and Asynchronous), RTC Hour format, disable + RTC registers Write protection, enter and exit the RTC initialization mode, + RTC registers synchronization check and reference clock detection enable. + (#) The RTC Prescaler is programmed to generate the RTC 1Hz time base. + It is split into 2 programmable prescalers to minimize power consumption. + (++) A 7-bit asynchronous prescaler and a 15-bit synchronous prescaler. + (++) When both prescalers are used, it is recommended to configure the + asynchronous prescaler to a high value to minimize power consumption. + (#) All RTC registers are Write protected. Writing to the RTC registers + is enabled by writing a key into the Write Protection register, RTC_WPR. + (#) To configure the RTC Calendar, user application should enter + initialization mode. In this mode, the calendar counter is stopped + and its value can be updated. When the initialization sequence is + complete, the calendar restarts counting after 4 RTCCLK cycles. + (#) To read the calendar through the shadow registers after Calendar + initialization, calendar update or after wakeup from low power modes + the software must first clear the RSF flag. The software must then + wait until it is set again before reading the calendar, which means + that the calendar registers have been correctly copied into the + RTC_TR and RTC_DR shadow registers. The HAL_RTC_WaitForSynchro() function + implements the above software sequence (RSF clear and RSF check). + +@endverbatim + * @{ + */ + +/** + * @brief Initialize the RTC according to the specified parameters + * in the RTC_InitTypeDef structure and initialize the associated handle. + * @param hrtc: RTC handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTC_Init(RTC_HandleTypeDef *hrtc) +{ + /* Check the RTC peripheral state */ + if(hrtc == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_RTC_ALL_INSTANCE(hrtc->Instance)); + assert_param(IS_RTC_HOUR_FORMAT(hrtc->Init.HourFormat)); + assert_param(IS_RTC_ASYNCH_PREDIV(hrtc->Init.AsynchPrediv)); + assert_param(IS_RTC_SYNCH_PREDIV(hrtc->Init.SynchPrediv)); + assert_param(IS_RTC_OUTPUT(hrtc->Init.OutPut)); + assert_param(IS_RTC_OUTPUT_REMAP(hrtc->Init.OutPutRemap)); + assert_param(IS_RTC_OUTPUT_POL(hrtc->Init.OutPutPolarity)); + assert_param(IS_RTC_OUTPUT_TYPE(hrtc->Init.OutPutType)); + + if(hrtc->State == HAL_RTC_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hrtc->Lock = HAL_UNLOCKED; + + /* Initialize RTC MSP */ + HAL_RTC_MspInit(hrtc); + } + + /* Set RTC state */ + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Set Initialization mode */ + if(RTC_EnterInitMode(hrtc) != HAL_OK) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Set RTC state */ + hrtc->State = HAL_RTC_STATE_ERROR; + + return HAL_ERROR; + } + else + { + /* Clear RTC_CR FMT, OSEL and POL Bits */ + hrtc->Instance->CR &= ((uint32_t)~(RTC_CR_FMT | RTC_CR_OSEL | RTC_CR_POL)); + /* Set RTC_CR register */ + hrtc->Instance->CR |= (uint32_t)(hrtc->Init.HourFormat | hrtc->Init.OutPut | hrtc->Init.OutPutPolarity); + + /* Configure the RTC PRER */ + hrtc->Instance->PRER = (uint32_t)(hrtc->Init.SynchPrediv); + hrtc->Instance->PRER |= (uint32_t)(hrtc->Init.AsynchPrediv << 16); + + /* Exit Initialization mode */ + hrtc->Instance->ISR &= ((uint32_t)~RTC_ISR_INIT); + + /* If CR_BYPSHAD bit = 0, wait for synchro else this check is not needed */ + if((hrtc->Instance->CR & RTC_CR_BYPSHAD) == RESET) + { + if(HAL_RTC_WaitForSynchro(hrtc) != HAL_OK) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_ERROR; + + return HAL_ERROR; + } + } + + hrtc->Instance->OR &= (uint32_t)~(RTC_OR_ALARMOUTTYPE | RTC_OR_OUT_RMP); + hrtc->Instance->OR |= (uint32_t)(hrtc->Init.OutPutType | hrtc->Init.OutPutRemap); + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Set RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + return HAL_OK; + } +} + +/** + * @brief DeInitialize the RTC peripheral. + * @param hrtc: RTC handle + * @note This function doesn't reset the RTC Backup Data registers. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTC_DeInit(RTC_HandleTypeDef *hrtc) +{ + uint32_t tickstart = 0; + + /* Check the parameters */ + assert_param(IS_RTC_ALL_INSTANCE(hrtc->Instance)); + + /* Set RTC state */ + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Set Initialization mode */ + if(RTC_EnterInitMode(hrtc) != HAL_OK) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Set RTC state */ + hrtc->State = HAL_RTC_STATE_ERROR; + + return HAL_ERROR; + } + else + { + /* Reset TR, DR and CR registers */ + hrtc->Instance->TR = (uint32_t)0x00000000; + hrtc->Instance->DR = ((uint32_t)(RTC_DR_WDU_0 | RTC_DR_MU_0 | RTC_DR_DU_0)); + /* Reset All CR bits except CR[2:0] */ + hrtc->Instance->CR &= RTC_CR_WUCKSEL; + + tickstart = HAL_GetTick(); + + /* Wait till WUTWF flag is set and if Time out is reached exit */ + while(((hrtc->Instance->ISR) & RTC_ISR_WUTWF) == (uint32_t)RESET) + { + if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Set RTC state */ + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + return HAL_TIMEOUT; + } + } + + /* Reset all RTC CR register bits */ + hrtc->Instance->CR &= (uint32_t)0x00000000; + hrtc->Instance->WUTR = RTC_WUTR_WUT; + hrtc->Instance->PRER = ((uint32_t)(RTC_PRER_PREDIV_A | 0x000000FF)); + hrtc->Instance->ALRMAR = (uint32_t)0x00000000; + hrtc->Instance->ALRMBR = (uint32_t)0x00000000; + hrtc->Instance->SHIFTR = (uint32_t)0x00000000; + hrtc->Instance->CALR = (uint32_t)0x00000000; + hrtc->Instance->ALRMASSR = (uint32_t)0x00000000; + hrtc->Instance->ALRMBSSR = (uint32_t)0x00000000; + + /* Reset ISR register and exit initialization mode */ + hrtc->Instance->ISR = (uint32_t)0x00000000; + + /* Reset Tamper configuration register */ + hrtc->Instance->TAMPCR = 0x00000000; + + /* Reset Option register */ + hrtc->Instance->OR = 0x00000000; + + /* If RTC_CR_BYPSHAD bit = 0, wait for synchro else this check is not needed */ + if((hrtc->Instance->CR & RTC_CR_BYPSHAD) == RESET) + { + if(HAL_RTC_WaitForSynchro(hrtc) != HAL_OK) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_ERROR; + + return HAL_ERROR; + } + } + } + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* De-Initialize RTC MSP */ + HAL_RTC_MspDeInit(hrtc); + + hrtc->State = HAL_RTC_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Initialize the RTC MSP. + * @param hrtc: RTC handle + * @retval None + */ +__weak void HAL_RTC_MspInit(RTC_HandleTypeDef* hrtc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hrtc); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_RTC_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitialize the RTC MSP. + * @param hrtc: RTC handle + * @retval None + */ +__weak void HAL_RTC_MspDeInit(RTC_HandleTypeDef* hrtc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hrtc); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_RTC_MspDeInit could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup RTC_Exported_Functions_Group2 RTC Time and Date functions + * @brief RTC Time and Date functions + * +@verbatim + =============================================================================== + ##### RTC Time and Date functions ##### + =============================================================================== + + [..] This section provides functions allowing to configure Time and Date features + +@endverbatim + * @{ + */ + +/** + * @brief Set RTC current time. + * @param hrtc: RTC handle + * @param sTime: Pointer to Time structure + * @param Format: Specifies the format of the entered parameters. + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN: Binary data format + * @arg RTC_FORMAT_BCD: BCD data format + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTC_SetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_RTC_FORMAT(Format)); + assert_param(IS_RTC_DAYLIGHT_SAVING(sTime->DayLightSaving)); + assert_param(IS_RTC_STORE_OPERATION(sTime->StoreOperation)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + if(Format == RTC_FORMAT_BIN) + { + if((hrtc->Instance->CR & RTC_CR_FMT) != (uint32_t)RESET) + { + assert_param(IS_RTC_HOUR12(sTime->Hours)); + assert_param(IS_RTC_HOURFORMAT12(sTime->TimeFormat)); + } + else + { + sTime->TimeFormat = 0x00; + assert_param(IS_RTC_HOUR24(sTime->Hours)); + } + assert_param(IS_RTC_MINUTES(sTime->Minutes)); + assert_param(IS_RTC_SECONDS(sTime->Seconds)); + + tmpreg = (uint32_t)(((uint32_t)RTC_ByteToBcd2(sTime->Hours) << 16) | \ + ((uint32_t)RTC_ByteToBcd2(sTime->Minutes) << 8) | \ + ((uint32_t)RTC_ByteToBcd2(sTime->Seconds)) | \ + (((uint32_t)sTime->TimeFormat) << 16)); + } + else + { + if((hrtc->Instance->CR & RTC_CR_FMT) != (uint32_t)RESET) + { + tmpreg = RTC_Bcd2ToByte(sTime->Hours); + assert_param(IS_RTC_HOUR12(tmpreg)); + assert_param(IS_RTC_HOURFORMAT12(sTime->TimeFormat)); + } + else + { + sTime->TimeFormat = 0x00; + assert_param(IS_RTC_HOUR24(RTC_Bcd2ToByte(sTime->Hours))); + } + assert_param(IS_RTC_MINUTES(RTC_Bcd2ToByte(sTime->Minutes))); + assert_param(IS_RTC_SECONDS(RTC_Bcd2ToByte(sTime->Seconds))); + tmpreg = (((uint32_t)(sTime->Hours) << 16) | \ + ((uint32_t)(sTime->Minutes) << 8) | \ + ((uint32_t)sTime->Seconds) | \ + ((uint32_t)(sTime->TimeFormat) << 16)); + } + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Set Initialization mode */ + if(RTC_EnterInitMode(hrtc) != HAL_OK) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Set RTC state */ + hrtc->State = HAL_RTC_STATE_ERROR; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_ERROR; + } + else + { + /* Set the RTC_TR register */ + hrtc->Instance->TR = (uint32_t)(tmpreg & RTC_TR_RESERVED_MASK); + + /* Clear the bits to be configured */ + hrtc->Instance->CR &= ((uint32_t)~RTC_CR_BCK); + + /* Configure the RTC_CR register */ + hrtc->Instance->CR |= (uint32_t)(sTime->DayLightSaving | sTime->StoreOperation); + + /* Exit Initialization mode */ + hrtc->Instance->ISR &= ((uint32_t)~RTC_ISR_INIT); + + /* If CR_BYPSHAD bit = 0, wait for synchro else this check is not needed */ + if((hrtc->Instance->CR & RTC_CR_BYPSHAD) == RESET) + { + if(HAL_RTC_WaitForSynchro(hrtc) != HAL_OK) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_ERROR; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_ERROR; + } + } + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_READY; + + __HAL_UNLOCK(hrtc); + + return HAL_OK; + } +} + +/** + * @brief Get RTC current time. + * @param hrtc: RTC handle + * @param sTime: Pointer to Time structure with Hours, Minutes and Seconds fields returned + * with input format (BIN or BCD), also SubSeconds field returning the + * RTC_SSR register content and SecondFraction field the Synchronous pre-scaler + * factor to be used for second fraction ratio computation. + * @param Format: Specifies the format of the entered parameters. + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN: Binary data format + * @arg RTC_FORMAT_BCD: BCD data format + * @note You can use SubSeconds and SecondFraction (sTime structure fields returned) to convert SubSeconds + * value in second fraction ratio with time unit following generic formula: + * Second fraction ratio * time_unit= [(SecondFraction-SubSeconds)/(SecondFraction+1)] * time_unit + * This conversion can be performed only if no shift operation is pending (ie. SHFP=0) when PREDIV_S >= SS + * @note You must call HAL_RTC_GetDate() after HAL_RTC_GetTime() to unlock the values + * in the higher-order calendar shadow registers to ensure consistency between the time and date values. + * Reading RTC current time locks the values in calendar shadow registers until Current date is read + * to ensure consistency between the time and date values. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTC_GetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_RTC_FORMAT(Format)); + + /* Get subseconds structure field from the corresponding register*/ + sTime->SubSeconds = (uint32_t)(hrtc->Instance->SSR); + + /* Get SecondFraction structure field from the corresponding register field*/ + sTime->SecondFraction = (uint32_t)(hrtc->Instance->PRER & RTC_PRER_PREDIV_S); + + /* Get the TR register */ + tmpreg = (uint32_t)(hrtc->Instance->TR & RTC_TR_RESERVED_MASK); + + /* Fill the structure fields with the read parameters */ + sTime->Hours = (uint8_t)((tmpreg & (RTC_TR_HT | RTC_TR_HU)) >> 16); + sTime->Minutes = (uint8_t)((tmpreg & (RTC_TR_MNT | RTC_TR_MNU)) >>8); + sTime->Seconds = (uint8_t)(tmpreg & (RTC_TR_ST | RTC_TR_SU)); + sTime->TimeFormat = (uint8_t)((tmpreg & (RTC_TR_PM)) >> 16); + + /* Check the input parameters format */ + if(Format == RTC_FORMAT_BIN) + { + /* Convert the time structure parameters to Binary format */ + sTime->Hours = (uint8_t)RTC_Bcd2ToByte(sTime->Hours); + sTime->Minutes = (uint8_t)RTC_Bcd2ToByte(sTime->Minutes); + sTime->Seconds = (uint8_t)RTC_Bcd2ToByte(sTime->Seconds); + } + + return HAL_OK; +} + +/** + * @brief Set RTC current date. + * @param hrtc: RTC handle + * @param sDate: Pointer to date structure + * @param Format: specifies the format of the entered parameters. + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN: Binary data format + * @arg RTC_FORMAT_BCD: BCD data format + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTC_SetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format) +{ + uint32_t datetmpreg = 0; + + /* Check the parameters */ + assert_param(IS_RTC_FORMAT(Format)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + if((Format == RTC_FORMAT_BIN) && ((sDate->Month & 0x10U) == 0x10U)) + { + sDate->Month = (uint8_t)((sDate->Month & (uint8_t)~(0x10U)) + (uint8_t)0x0AU); + } + + assert_param(IS_RTC_WEEKDAY(sDate->WeekDay)); + + if(Format == RTC_FORMAT_BIN) + { + assert_param(IS_RTC_YEAR(sDate->Year)); + assert_param(IS_RTC_MONTH(sDate->Month)); + assert_param(IS_RTC_DATE(sDate->Date)); + + datetmpreg = (((uint32_t)RTC_ByteToBcd2(sDate->Year) << 16) | \ + ((uint32_t)RTC_ByteToBcd2(sDate->Month) << 8) | \ + ((uint32_t)RTC_ByteToBcd2(sDate->Date)) | \ + ((uint32_t)sDate->WeekDay << 13)); + } + else + { + assert_param(IS_RTC_YEAR(RTC_Bcd2ToByte(sDate->Year))); + datetmpreg = RTC_Bcd2ToByte(sDate->Month); + assert_param(IS_RTC_MONTH(datetmpreg)); + datetmpreg = RTC_Bcd2ToByte(sDate->Date); + assert_param(IS_RTC_DATE(datetmpreg)); + + datetmpreg = ((((uint32_t)sDate->Year) << 16) | \ + (((uint32_t)sDate->Month) << 8) | \ + ((uint32_t)sDate->Date) | \ + (((uint32_t)sDate->WeekDay) << 13)); + } + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Set Initialization mode */ + if(RTC_EnterInitMode(hrtc) != HAL_OK) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Set RTC state*/ + hrtc->State = HAL_RTC_STATE_ERROR; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_ERROR; + } + else + { + /* Set the RTC_DR register */ + hrtc->Instance->DR = (uint32_t)(datetmpreg & RTC_DR_RESERVED_MASK); + + /* Exit Initialization mode */ + hrtc->Instance->ISR &= ((uint32_t)~RTC_ISR_INIT); + + /* If CR_BYPSHAD bit = 0, wait for synchro else this check is not needed */ + if((hrtc->Instance->CR & RTC_CR_BYPSHAD) == RESET) + { + if(HAL_RTC_WaitForSynchro(hrtc) != HAL_OK) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_ERROR; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_ERROR; + } + } + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_READY ; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; + } +} + +/** + * @brief Get RTC current date. + * @param hrtc: RTC handle + * @param sDate: Pointer to Date structure + * @param Format: Specifies the format of the entered parameters. + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN: Binary data format + * @arg RTC_FORMAT_BCD: BCD data format + * @note You must call HAL_RTC_GetDate() after HAL_RTC_GetTime() to unlock the values + * in the higher-order calendar shadow registers to ensure consistency between the time and date values. + * Reading RTC current time locks the values in calendar shadow registers until Current date is read. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTC_GetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format) +{ + uint32_t datetmpreg = 0; + + /* Check the parameters */ + assert_param(IS_RTC_FORMAT(Format)); + + /* Get the DR register */ + datetmpreg = (uint32_t)(hrtc->Instance->DR & RTC_DR_RESERVED_MASK); + + /* Fill the structure fields with the read parameters */ + sDate->Year = (uint8_t)((datetmpreg & (RTC_DR_YT | RTC_DR_YU)) >> 16); + sDate->Month = (uint8_t)((datetmpreg & (RTC_DR_MT | RTC_DR_MU)) >> 8); + sDate->Date = (uint8_t)(datetmpreg & (RTC_DR_DT | RTC_DR_DU)); + sDate->WeekDay = (uint8_t)((datetmpreg & (RTC_DR_WDU)) >> 13); + + /* Check the input parameters format */ + if(Format == RTC_FORMAT_BIN) + { + /* Convert the date structure parameters to Binary format */ + sDate->Year = (uint8_t)RTC_Bcd2ToByte(sDate->Year); + sDate->Month = (uint8_t)RTC_Bcd2ToByte(sDate->Month); + sDate->Date = (uint8_t)RTC_Bcd2ToByte(sDate->Date); + } + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup RTC_Exported_Functions_Group3 RTC Alarm functions + * @brief RTC Alarm functions + * +@verbatim + =============================================================================== + ##### RTC Alarm functions ##### + =============================================================================== + + [..] This section provides functions allowing to configure Alarm feature + +@endverbatim + * @{ + */ +/** + * @brief Set the specified RTC Alarm. + * @param hrtc: RTC handle + * @param sAlarm: Pointer to Alarm structure + * @param Format: Specifies the format of the entered parameters. + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN: Binary data format + * @arg RTC_FORMAT_BCD: BCD data format + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTC_SetAlarm(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Format) +{ + uint32_t tickstart = 0; + uint32_t tmpreg = 0, subsecondtmpreg = 0; + + /* Check the parameters */ + assert_param(IS_RTC_FORMAT(Format)); + assert_param(IS_RTC_ALARM(sAlarm->Alarm)); + assert_param(IS_RTC_ALARM_MASK(sAlarm->AlarmMask)); + assert_param(IS_RTC_ALARM_DATE_WEEKDAY_SEL(sAlarm->AlarmDateWeekDaySel)); + assert_param(IS_RTC_ALARM_SUB_SECOND_VALUE(sAlarm->AlarmTime.SubSeconds)); + assert_param(IS_RTC_ALARM_SUB_SECOND_MASK(sAlarm->AlarmSubSecondMask)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + if(Format == RTC_FORMAT_BIN) + { + if((hrtc->Instance->CR & RTC_CR_FMT) != (uint32_t)RESET) + { + assert_param(IS_RTC_HOUR12(sAlarm->AlarmTime.Hours)); + assert_param(IS_RTC_HOURFORMAT12(sAlarm->AlarmTime.TimeFormat)); + } + else + { + sAlarm->AlarmTime.TimeFormat = 0x00; + assert_param(IS_RTC_HOUR24(sAlarm->AlarmTime.Hours)); + } + assert_param(IS_RTC_MINUTES(sAlarm->AlarmTime.Minutes)); + assert_param(IS_RTC_SECONDS(sAlarm->AlarmTime.Seconds)); + + if(sAlarm->AlarmDateWeekDaySel == RTC_ALARMDATEWEEKDAYSEL_DATE) + { + assert_param(IS_RTC_ALARM_DATE_WEEKDAY_DATE(sAlarm->AlarmDateWeekDay)); + } + else + { + assert_param(IS_RTC_ALARM_DATE_WEEKDAY_WEEKDAY(sAlarm->AlarmDateWeekDay)); + } + + tmpreg = (((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmTime.Hours) << 16) | \ + ((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmTime.Minutes) << 8) | \ + ((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmTime.Seconds)) | \ + ((uint32_t)(sAlarm->AlarmTime.TimeFormat) << 16) | \ + ((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmDateWeekDay) << 24) | \ + ((uint32_t)sAlarm->AlarmDateWeekDaySel) | \ + ((uint32_t)sAlarm->AlarmMask)); + } + else + { + if((hrtc->Instance->CR & RTC_CR_FMT) != (uint32_t)RESET) + { + tmpreg = RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours); + assert_param(IS_RTC_HOUR12(tmpreg)); + assert_param(IS_RTC_HOURFORMAT12(sAlarm->AlarmTime.TimeFormat)); + } + else + { + sAlarm->AlarmTime.TimeFormat = 0x00; + assert_param(IS_RTC_HOUR24(RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours))); + } + + assert_param(IS_RTC_MINUTES(RTC_Bcd2ToByte(sAlarm->AlarmTime.Minutes))); + assert_param(IS_RTC_SECONDS(RTC_Bcd2ToByte(sAlarm->AlarmTime.Seconds))); + + if(sAlarm->AlarmDateWeekDaySel == RTC_ALARMDATEWEEKDAYSEL_DATE) + { + tmpreg = RTC_Bcd2ToByte(sAlarm->AlarmDateWeekDay); + assert_param(IS_RTC_ALARM_DATE_WEEKDAY_DATE(tmpreg)); + } + else + { + tmpreg = RTC_Bcd2ToByte(sAlarm->AlarmDateWeekDay); + assert_param(IS_RTC_ALARM_DATE_WEEKDAY_WEEKDAY(tmpreg)); + } + + tmpreg = (((uint32_t)(sAlarm->AlarmTime.Hours) << 16) | \ + ((uint32_t)(sAlarm->AlarmTime.Minutes) << 8) | \ + ((uint32_t) sAlarm->AlarmTime.Seconds) | \ + ((uint32_t)(sAlarm->AlarmTime.TimeFormat) << 16) | \ + ((uint32_t)(sAlarm->AlarmDateWeekDay) << 24) | \ + ((uint32_t)sAlarm->AlarmDateWeekDaySel) | \ + ((uint32_t)sAlarm->AlarmMask)); + } + + /* Configure the Alarm A or Alarm B Sub Second registers */ + subsecondtmpreg = (uint32_t)((uint32_t)(sAlarm->AlarmTime.SubSeconds) | (uint32_t)(sAlarm->AlarmSubSecondMask)); + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Configure the Alarm register */ + if(sAlarm->Alarm == RTC_ALARM_A) + { + /* Disable the Alarm A interrupt */ + __HAL_RTC_ALARMA_DISABLE(hrtc); + + /* In case of interrupt mode is used, the interrupt source must disabled */ + __HAL_RTC_ALARM_DISABLE_IT(hrtc, RTC_IT_ALRA); + + tickstart = HAL_GetTick(); + /* Wait till RTC ALRAWF flag is set and if Time out is reached exit */ + while(__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAWF) == RESET) + { + if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_TIMEOUT; + } + } + + hrtc->Instance->ALRMAR = (uint32_t)tmpreg; + /* Configure the Alarm A Sub Second register */ + hrtc->Instance->ALRMASSR = subsecondtmpreg; + /* Configure the Alarm state: Enable Alarm */ + __HAL_RTC_ALARMA_ENABLE(hrtc); + } + else + { + /* Disable the Alarm B interrupt */ + __HAL_RTC_ALARMB_DISABLE(hrtc); + + /* In case of interrupt mode is used, the interrupt source must disabled */ + __HAL_RTC_ALARM_DISABLE_IT(hrtc, RTC_IT_ALRB); + + tickstart = HAL_GetTick(); + /* Wait till RTC ALRBWF flag is set and if Time out is reached exit */ + while(__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRBWF) == RESET) + { + if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_TIMEOUT; + } + } + + hrtc->Instance->ALRMBR = (uint32_t)tmpreg; + /* Configure the Alarm B Sub Second register */ + hrtc->Instance->ALRMBSSR = subsecondtmpreg; + /* Configure the Alarm state: Enable Alarm */ + __HAL_RTC_ALARMB_ENABLE(hrtc); + } + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Set the specified RTC Alarm with Interrupt. + * @param hrtc: RTC handle + * @param sAlarm: Pointer to Alarm structure + * @param Format: Specifies the format of the entered parameters. + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN: Binary data format + * @arg RTC_FORMAT_BCD: BCD data format + * @note The Alarm register can only be written when the corresponding Alarm + * is disabled (Use the HAL_RTC_DeactivateAlarm()). + * @note The HAL_RTC_SetTime() must be called before enabling the Alarm feature. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTC_SetAlarm_IT(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Format) +{ + uint32_t tickstart = 0; + uint32_t tmpreg = 0, subsecondtmpreg = 0; + + /* Check the parameters */ + assert_param(IS_RTC_FORMAT(Format)); + assert_param(IS_RTC_ALARM(sAlarm->Alarm)); + assert_param(IS_RTC_ALARM_MASK(sAlarm->AlarmMask)); + assert_param(IS_RTC_ALARM_DATE_WEEKDAY_SEL(sAlarm->AlarmDateWeekDaySel)); + assert_param(IS_RTC_ALARM_SUB_SECOND_VALUE(sAlarm->AlarmTime.SubSeconds)); + assert_param(IS_RTC_ALARM_SUB_SECOND_MASK(sAlarm->AlarmSubSecondMask)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + if(Format == RTC_FORMAT_BIN) + { + if((hrtc->Instance->CR & RTC_CR_FMT) != (uint32_t)RESET) + { + assert_param(IS_RTC_HOUR12(sAlarm->AlarmTime.Hours)); + assert_param(IS_RTC_HOURFORMAT12(sAlarm->AlarmTime.TimeFormat)); + } + else + { + sAlarm->AlarmTime.TimeFormat = 0x00; + assert_param(IS_RTC_HOUR24(sAlarm->AlarmTime.Hours)); + } + assert_param(IS_RTC_MINUTES(sAlarm->AlarmTime.Minutes)); + assert_param(IS_RTC_SECONDS(sAlarm->AlarmTime.Seconds)); + + if(sAlarm->AlarmDateWeekDaySel == RTC_ALARMDATEWEEKDAYSEL_DATE) + { + assert_param(IS_RTC_ALARM_DATE_WEEKDAY_DATE(sAlarm->AlarmDateWeekDay)); + } + else + { + assert_param(IS_RTC_ALARM_DATE_WEEKDAY_WEEKDAY(sAlarm->AlarmDateWeekDay)); + } + tmpreg = (((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmTime.Hours) << 16) | \ + ((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmTime.Minutes) << 8) | \ + ((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmTime.Seconds)) | \ + ((uint32_t)(sAlarm->AlarmTime.TimeFormat) << 16) | \ + ((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmDateWeekDay) << 24) | \ + ((uint32_t)sAlarm->AlarmDateWeekDaySel) | \ + ((uint32_t)sAlarm->AlarmMask)); + } + else + { + if((hrtc->Instance->CR & RTC_CR_FMT) != (uint32_t)RESET) + { + tmpreg = RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours); + assert_param(IS_RTC_HOUR12(tmpreg)); + assert_param(IS_RTC_HOURFORMAT12(sAlarm->AlarmTime.TimeFormat)); + } + else + { + sAlarm->AlarmTime.TimeFormat = 0x00; + assert_param(IS_RTC_HOUR24(RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours))); + } + + assert_param(IS_RTC_MINUTES(RTC_Bcd2ToByte(sAlarm->AlarmTime.Minutes))); + assert_param(IS_RTC_SECONDS(RTC_Bcd2ToByte(sAlarm->AlarmTime.Seconds))); + + if(sAlarm->AlarmDateWeekDaySel == RTC_ALARMDATEWEEKDAYSEL_DATE) + { + tmpreg = RTC_Bcd2ToByte(sAlarm->AlarmDateWeekDay); + assert_param(IS_RTC_ALARM_DATE_WEEKDAY_DATE(tmpreg)); + } + else + { + tmpreg = RTC_Bcd2ToByte(sAlarm->AlarmDateWeekDay); + assert_param(IS_RTC_ALARM_DATE_WEEKDAY_WEEKDAY(tmpreg)); + } + tmpreg = (((uint32_t)(sAlarm->AlarmTime.Hours) << 16) | \ + ((uint32_t)(sAlarm->AlarmTime.Minutes) << 8) | \ + ((uint32_t) sAlarm->AlarmTime.Seconds) | \ + ((uint32_t)(sAlarm->AlarmTime.TimeFormat) << 16) | \ + ((uint32_t)(sAlarm->AlarmDateWeekDay) << 24) | \ + ((uint32_t)sAlarm->AlarmDateWeekDaySel) | \ + ((uint32_t)sAlarm->AlarmMask)); + } + /* Configure the Alarm A or Alarm B Sub Second registers */ + subsecondtmpreg = (uint32_t)((uint32_t)(sAlarm->AlarmTime.SubSeconds) | (uint32_t)(sAlarm->AlarmSubSecondMask)); + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Configure the Alarm register */ + if(sAlarm->Alarm == RTC_ALARM_A) + { + /* Disable the Alarm A interrupt */ + __HAL_RTC_ALARMA_DISABLE(hrtc); + + /* Clear flag alarm A */ + __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF); + + tickstart = HAL_GetTick(); + /* Wait till RTC ALRAWF flag is set and if Time out is reached exit */ + while(__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAWF) == RESET) + { + if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_TIMEOUT; + } + } + + hrtc->Instance->ALRMAR = (uint32_t)tmpreg; + /* Configure the Alarm A Sub Second register */ + hrtc->Instance->ALRMASSR = subsecondtmpreg; + /* Configure the Alarm state: Enable Alarm */ + __HAL_RTC_ALARMA_ENABLE(hrtc); + /* Configure the Alarm interrupt */ + __HAL_RTC_ALARM_ENABLE_IT(hrtc,RTC_IT_ALRA); + } + else + { + /* Disable the Alarm B interrupt */ + __HAL_RTC_ALARMB_DISABLE(hrtc); + + /* Clear flag alarm B */ + __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRBF); + + tickstart = HAL_GetTick(); + /* Wait till RTC ALRBWF flag is set and if Time out is reached exit */ + while(__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRBWF) == RESET) + { + if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_TIMEOUT; + } + } + + hrtc->Instance->ALRMBR = (uint32_t)tmpreg; + /* Configure the Alarm B Sub Second register */ + hrtc->Instance->ALRMBSSR = subsecondtmpreg; + /* Configure the Alarm state: Enable Alarm */ + __HAL_RTC_ALARMB_ENABLE(hrtc); + /* Configure the Alarm interrupt */ + __HAL_RTC_ALARM_ENABLE_IT(hrtc, RTC_IT_ALRB); + } + + /* RTC Alarm Interrupt Configuration: EXTI configuration */ + __HAL_RTC_ALARM_EXTI_ENABLE_IT(); + + __HAL_RTC_ALARM_EXTI_ENABLE_RISING_EDGE(); + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Deactivate the specified RTC Alarm. + * @param hrtc: RTC handle + * @param Alarm: Specifies the Alarm. + * This parameter can be one of the following values: + * @arg RTC_ALARM_A: AlarmA + * @arg RTC_ALARM_B: AlarmB + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTC_DeactivateAlarm(RTC_HandleTypeDef *hrtc, uint32_t Alarm) +{ + uint32_t tickstart = 0; + + /* Check the parameters */ + assert_param(IS_RTC_ALARM(Alarm)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + if(Alarm == RTC_ALARM_A) + { + /* AlarmA */ + __HAL_RTC_ALARMA_DISABLE(hrtc); + + /* In case of interrupt mode is used, the interrupt source must disabled */ + __HAL_RTC_ALARM_DISABLE_IT(hrtc, RTC_IT_ALRA); + + tickstart = HAL_GetTick(); + + /* Wait till RTC ALRxWF flag is set and if Time out is reached exit */ + while(__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAWF) == RESET) + { + if( (HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_TIMEOUT; + } + } + } + else + { + /* AlarmB */ + __HAL_RTC_ALARMB_DISABLE(hrtc); + + /* In case of interrupt mode is used, the interrupt source must disabled */ + __HAL_RTC_ALARM_DISABLE_IT(hrtc,RTC_IT_ALRB); + + tickstart = HAL_GetTick(); + + /* Wait till RTC ALRxWF flag is set and if Time out is reached exit */ + while(__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRBWF) == RESET) + { + if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_TIMEOUT; + } + } + } + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Get the RTC Alarm value and masks. + * @param hrtc: RTC handle + * @param sAlarm: Pointer to Date structure + * @param Alarm: Specifies the Alarm. + * This parameter can be one of the following values: + * @arg RTC_ALARM_A: AlarmA + * @arg RTC_ALARM_B: AlarmB + * @param Format: Specifies the format of the entered parameters. + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN: Binary data format + * @arg RTC_FORMAT_BCD: BCD data format + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTC_GetAlarm(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Alarm, uint32_t Format) +{ + uint32_t tmpreg = 0, subsecondtmpreg = 0; + + /* Check the parameters */ + assert_param(IS_RTC_FORMAT(Format)); + assert_param(IS_RTC_ALARM(Alarm)); + + if(Alarm == RTC_ALARM_A) + { + /* AlarmA */ + sAlarm->Alarm = RTC_ALARM_A; + + tmpreg = (uint32_t)(hrtc->Instance->ALRMAR); + subsecondtmpreg = (uint32_t)((hrtc->Instance->ALRMASSR ) & RTC_ALRMASSR_SS); + } + else + { + sAlarm->Alarm = RTC_ALARM_B; + + tmpreg = (uint32_t)(hrtc->Instance->ALRMBR); + subsecondtmpreg = (uint32_t)((hrtc->Instance->ALRMBSSR) & RTC_ALRMBSSR_SS); + } + + /* Fill the structure with the read parameters */ + /* ALRMAR/ALRMBR registers have same mapping) */ + sAlarm->AlarmTime.Hours = (uint32_t)((tmpreg & (RTC_ALRMAR_HT | RTC_ALRMAR_HU)) >> 16); + sAlarm->AlarmTime.Minutes = (uint32_t)((tmpreg & (RTC_ALRMAR_MNT | RTC_ALRMAR_MNU)) >> 8); + sAlarm->AlarmTime.Seconds = (uint32_t)(tmpreg & (RTC_ALRMAR_ST | RTC_ALRMAR_SU)); + sAlarm->AlarmTime.TimeFormat = (uint32_t)((tmpreg & RTC_ALRMAR_PM) >> 16); + sAlarm->AlarmTime.SubSeconds = (uint32_t) subsecondtmpreg; + sAlarm->AlarmDateWeekDay = (uint32_t)((tmpreg & (RTC_ALRMAR_DT | RTC_ALRMAR_DU)) >> 24); + sAlarm->AlarmDateWeekDaySel = (uint32_t)(tmpreg & RTC_ALRMAR_WDSEL); + sAlarm->AlarmMask = (uint32_t)(tmpreg & RTC_ALARMMASK_ALL); + + if(Format == RTC_FORMAT_BIN) + { + sAlarm->AlarmTime.Hours = RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours); + sAlarm->AlarmTime.Minutes = RTC_Bcd2ToByte(sAlarm->AlarmTime.Minutes); + sAlarm->AlarmTime.Seconds = RTC_Bcd2ToByte(sAlarm->AlarmTime.Seconds); + sAlarm->AlarmDateWeekDay = RTC_Bcd2ToByte(sAlarm->AlarmDateWeekDay); + } + + return HAL_OK; +} + +/** + * @brief Handle Alarm interrupt request. + * @param hrtc: RTC handle + * @retval None + */ +void HAL_RTC_AlarmIRQHandler(RTC_HandleTypeDef* hrtc) +{ + /* Clear the EXTI's line Flag for RTC Alarm */ + __HAL_RTC_ALARM_EXTI_CLEAR_FLAG(); + + /* As alarms are sharing the same EXTI line, exit when no more pending Alarm event */ + while(((__HAL_RTC_ALARM_GET_IT_SOURCE(hrtc, RTC_IT_ALRA) != RESET) && (__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAF) != RESET)) || + ((__HAL_RTC_ALARM_GET_IT_SOURCE(hrtc, RTC_IT_ALRB) != RESET) && (__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRBF) != RESET))) + { + /* Get the AlarmA interrupt source enable status and pending flag status*/ + if((__HAL_RTC_ALARM_GET_IT_SOURCE(hrtc, RTC_IT_ALRA) != RESET) && (__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAF) != RESET)) + { + /* Clear the AlarmA interrupt pending bit */ + __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF); + + /* AlarmA callback */ + HAL_RTC_AlarmAEventCallback(hrtc); + } + + /* Get the AlarmB interrupt source enable status and pending flag status*/ + if((__HAL_RTC_ALARM_GET_IT_SOURCE(hrtc, RTC_IT_ALRB) != RESET) && (__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRBF) != RESET)) + { + /* Clear the AlarmB interrupt pending bit */ + __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRBF); + + /* AlarmB callback */ + HAL_RTCEx_AlarmBEventCallback(hrtc); + } + } + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; +} + +/** + * @brief Alarm A callback. + * @param hrtc: RTC handle + * @retval None + */ +__weak void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hrtc); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_RTC_AlarmAEventCallback could be implemented in the user file + */ +} + +/** + * @brief Handle AlarmA Polling request. + * @param hrtc: RTC handle + * @param Timeout: Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTC_PollForAlarmAEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout) +{ + + uint32_t tickstart = HAL_GetTick(); + + while(__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAF) == RESET) + { + if(Timeout != HAL_MAX_DELAY) + { + if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)) + { + hrtc->State = HAL_RTC_STATE_TIMEOUT; + return HAL_TIMEOUT; + } + } + } + + /* Clear the Alarm interrupt pending bit */ + __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup RTC_Exported_Functions_Group4 Peripheral Control functions + * @brief Peripheral Control functions + * +@verbatim + =============================================================================== + ##### Peripheral Control functions ##### + =============================================================================== + [..] + This subsection provides functions allowing to + (+) Wait for RTC Time and Date Synchronization + +@endverbatim + * @{ + */ + +/** + * @brief Wait until the RTC Time and Date registers (RTC_TR and RTC_DR) are + * synchronized with RTC APB clock. + * @note The RTC Resynchronization mode is write protected, use the + * __HAL_RTC_WRITEPROTECTION_DISABLE() before calling this function. + * @note To read the calendar through the shadow registers after Calendar + * initialization, calendar update or after wakeup from low power modes + * the software must first clear the RSF flag. + * The software must then wait until it is set again before reading + * the calendar, which means that the calendar registers have been + * correctly copied into the RTC_TR and RTC_DR shadow registers. + * @param hrtc: RTC handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTC_WaitForSynchro(RTC_HandleTypeDef* hrtc) +{ + uint32_t tickstart = 0; + + /* Clear RSF flag */ + hrtc->Instance->ISR &= (uint32_t)RTC_RSF_MASK; + + tickstart = HAL_GetTick(); + + /* Wait the registers to be synchronised */ + while((hrtc->Instance->ISR & RTC_ISR_RSF) == (uint32_t)RESET) + { + if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup RTC_Exported_Functions_Group5 Peripheral State functions + * @brief Peripheral State functions + * +@verbatim + =============================================================================== + ##### Peripheral State functions ##### + =============================================================================== + [..] + This subsection provides functions allowing to + (+) Get RTC state + +@endverbatim + * @{ + */ +/** + * @brief Return the RTC handle state. + * @param hrtc: RTC handle + * @retval HAL state + */ +HAL_RTCStateTypeDef HAL_RTC_GetState(RTC_HandleTypeDef* hrtc) +{ + /* Return RTC handle state */ + return hrtc->State; +} + +/** + * @} + */ + +/** + * @} + */ + +/** @defgroup RTC_Private_Functions RTC Private functions + * @{ + */ +/** + * @brief Enter the RTC Initialization mode. + * @note The RTC Initialization mode is write protected, use the + * __HAL_RTC_WRITEPROTECTION_DISABLE() before calling this function. + * @param hrtc: RTC handle + * @retval HAL status + */ +HAL_StatusTypeDef RTC_EnterInitMode(RTC_HandleTypeDef* hrtc) +{ + uint32_t tickstart = 0; + + /* Check if the Initialization mode is set */ + if((hrtc->Instance->ISR & RTC_ISR_INITF) == (uint32_t)RESET) + { + /* Set the Initialization mode */ + hrtc->Instance->ISR = (uint32_t)RTC_INIT_MASK; + + tickstart = HAL_GetTick(); + /* Wait till RTC is in INIT state and if Time out is reached exit */ + while((hrtc->Instance->ISR & RTC_ISR_INITF) == (uint32_t)RESET) + { + if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + } + + return HAL_OK; +} + + +/** + * @brief Convert a 2 digit decimal to BCD format. + * @param Value: Byte to be converted + * @retval Converted byte + */ +uint8_t RTC_ByteToBcd2(uint8_t Value) +{ + uint32_t bcdhigh = 0; + + while(Value >= 10) + { + bcdhigh++; + Value -= 10; + } + + return ((uint8_t)(bcdhigh << 4) | Value); +} + +/** + * @brief Convert from 2 digit BCD to Binary. + * @param Value: BCD value to be converted + * @retval Converted word + */ +uint8_t RTC_Bcd2ToByte(uint8_t Value) +{ + uint32_t tmp = 0; + tmp = ((uint8_t)(Value & (uint8_t)0xF0) >> (uint8_t)0x4) * 10; + return (tmp + (Value & (uint8_t)0x0F)); +} + +/** + * @} + */ + +#endif /* HAL_RTC_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rtc_ex.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rtc_ex.c new file mode 100644 index 0000000..35be397 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_rtc_ex.c @@ -0,0 +1,1875 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_rtc_ex.c + * @author MCD Application Team + * @brief Extended RTC HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Real Time Clock (RTC) Extended peripheral: + * + RTC Time Stamp functions + * + RTC Tamper functions + * + RTC Wake-up functions + * + Extended Control functions + * + Extended RTC features functions + * + @verbatim + ============================================================================== + ##### How to use this driver ##### + ============================================================================== + [..] + (+) Enable the RTC domain access. + (+) Configure the RTC Prescaler (Asynchronous and Synchronous) and RTC hour + format using the HAL_RTC_Init() function. + + *** RTC Wakeup configuration *** + ================================ + [..] + (+) To configure the RTC Wakeup Clock source and Counter use the HAL_RTCEx_SetWakeUpTimer() + function. You can also configure the RTC Wakeup timer with interrupt mode + using the HAL_RTCEx_SetWakeUpTimer_IT() function. + (+) To read the RTC WakeUp Counter register, use the HAL_RTCEx_GetWakeUpTimer() + function. + + *** Outputs configuration *** + ============================= + [..] The RTC has 2 different outputs: + (+) RTC_ALARM: this output is used to manage the RTC Alarm A, Alarm B + and WaKeUp signals. + To output the selected RTC signal, use the HAL_RTC_Init() function. + (+) RTC_CALIB: this output is 512Hz signal or 1Hz. + To enable the RTC_CALIB, use the HAL_RTCEx_SetCalibrationOutPut() function. + (+) Two pins can be used as RTC_ALARM or RTC_CALIB (PC13, PB2) managed on + the RTC_OR register. + (+) When the RTC_CALIB or RTC_ALARM output is selected, the RTC_OUT pin is + automatically configured in output alternate function. + + *** Smooth digital Calibration configuration *** + ================================================ + [..] + (+) Configure the RTC Original Digital Calibration Value and the corresponding + calibration cycle period (32s,16s and 8s) using the HAL_RTCEx_SetSmoothCalib() + function. + + *** TimeStamp configuration *** + =============================== + [..] + (+) Enable the RTC TimeStamp using the HAL_RTCEx_SetTimeStamp() function. + You can also configure the RTC TimeStamp with interrupt mode using the + HAL_RTCEx_SetTimeStamp_IT() function. + (+) To read the RTC TimeStamp Time and Date register, use the HAL_RTCEx_GetTimeStamp() + function. + + *** Internal TimeStamp configuration *** + =============================== + [..] + (+) Enable the RTC internal TimeStamp using the HAL_RTCEx_SetInternalTimeStamp() function. + User has to check internal timestamp occurrence using __HAL_RTC_INTERNAL_TIMESTAMP_GET_FLAG. + (+) To read the RTC TimeStamp Time and Date register, use the HAL_RTCEx_GetTimeStamp() + function. + + *** Tamper configuration *** + ============================ + [..] + (+) Enable the RTC Tamper and configure the Tamper filter count, trigger Edge + or Level according to the Tamper filter (if equal to 0 Edge else Level) + value, sampling frequency, NoErase, MaskFlag, precharge or discharge and + Pull-UP using the HAL_RTCEx_SetTamper() function. You can configure RTC Tamper + with interrupt mode using HAL_RTCEx_SetTamper_IT() function. + (+) The default configuration of the Tamper erases the backup registers. To avoid + erase, enable the NoErase field on the RTC_TAMPCR register. + + *** Backup Data Registers configuration *** + =========================================== + [..] + (+) To write to the RTC Backup Data registers, use the HAL_RTCEx_BKUPWrite() + function. + (+) To read the RTC Backup Data registers, use the HAL_RTCEx_BKUPRead() + function. + + @endverbatim + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup RTCEx RTCEx + * @brief RTC Extended HAL module driver + * @{ + */ + +#ifdef HAL_RTC_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +#if defined(RTC_TAMPER1_SUPPORT) && defined(RTC_TAMPER3_SUPPORT) +#define RTC_TAMPCR_MASK ((uint32_t)RTC_TAMPCR_TAMPTS |\ + (uint32_t)RTC_TAMPCR_TAMPFREQ | (uint32_t)RTC_TAMPCR_TAMPFLT | (uint32_t)RTC_TAMPCR_TAMPPRCH |\ + (uint32_t)RTC_TAMPCR_TAMPPUDIS | (uint32_t)RTC_TAMPCR_TAMPIE |\ + (uint32_t)RTC_TAMPCR_TAMP1IE | (uint32_t)RTC_TAMPCR_TAMP1NOERASE | (uint32_t)RTC_TAMPCR_TAMP1MF |\ + (uint32_t)RTC_TAMPCR_TAMP2IE | (uint32_t)RTC_TAMPCR_TAMP2NOERASE | (uint32_t)RTC_TAMPCR_TAMP2MF |\ + (uint32_t)RTC_TAMPCR_TAMP3IE | (uint32_t)RTC_TAMPCR_TAMP3NOERASE | (uint32_t)RTC_TAMPCR_TAMP3MF) +#elif defined(RTC_TAMPER1_SUPPORT) +#define RTC_TAMPCR_MASK ((uint32_t)RTC_TAMPCR_TAMPTS |\ + (uint32_t)RTC_TAMPCR_TAMPFREQ | (uint32_t)RTC_TAMPCR_TAMPFLT | (uint32_t)RTC_TAMPCR_TAMPPRCH |\ + (uint32_t)RTC_TAMPCR_TAMPPUDIS | (uint32_t)RTC_TAMPCR_TAMPIE |\ + (uint32_t)RTC_TAMPCR_TAMP1IE | (uint32_t)RTC_TAMPCR_TAMP1NOERASE | (uint32_t)RTC_TAMPCR_TAMP1MF |\ + (uint32_t)RTC_TAMPCR_TAMP2IE | (uint32_t)RTC_TAMPCR_TAMP2NOERASE | (uint32_t)RTC_TAMPCR_TAMP2MF) +#elif defined(RTC_TAMPER3_SUPPORT) +#define RTC_TAMPCR_MASK ((uint32_t)RTC_TAMPCR_TAMPTS |\ + (uint32_t)RTC_TAMPCR_TAMPFREQ | (uint32_t)RTC_TAMPCR_TAMPFLT | (uint32_t)RTC_TAMPCR_TAMPPRCH |\ + (uint32_t)RTC_TAMPCR_TAMPPUDIS | (uint32_t)RTC_TAMPCR_TAMPIE |\ + (uint32_t)RTC_TAMPCR_TAMP2IE | (uint32_t)RTC_TAMPCR_TAMP2NOERASE | (uint32_t)RTC_TAMPCR_TAMP2MF |\ + (uint32_t)RTC_TAMPCR_TAMP3IE | (uint32_t)RTC_TAMPCR_TAMP3NOERASE | (uint32_t)RTC_TAMPCR_TAMP3MF) +#else +#define RTC_TAMPCR_MASK ((uint32_t)RTC_TAMPCR_TAMPTS |\ + (uint32_t)RTC_TAMPCR_TAMPFREQ | (uint32_t)RTC_TAMPCR_TAMPFLT | (uint32_t)RTC_TAMPCR_TAMPPRCH |\ + (uint32_t)RTC_TAMPCR_TAMPPUDIS | (uint32_t)RTC_TAMPCR_TAMPIE |\ + (uint32_t)RTC_TAMPCR_TAMP2IE | (uint32_t)RTC_TAMPCR_TAMP2NOERASE | (uint32_t)RTC_TAMPCR_TAMP2MF) +#endif /* RTC_TAMPER1_SUPPORT && RTC_TAMPER3_SUPPORT */ + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup RTCEx_Exported_Functions RTCEx Exported Functions + * @{ + */ + + +/** @defgroup RTCEx_Exported_Functions_Group1 RTC TimeStamp and Tamper functions + * @brief RTC TimeStamp and Tamper functions + * +@verbatim + =============================================================================== + ##### RTC TimeStamp and Tamper functions ##### + =============================================================================== + + [..] This section provide functions allowing to configure TimeStamp feature + +@endverbatim + * @{ + */ + +/** + * @brief Set TimeStamp. + * @note This API must be called before enabling the TimeStamp feature. + * @param hrtc: RTC handle + * @param TimeStampEdge: Specifies the pin edge on which the TimeStamp is + * activated. + * This parameter can be one of the following values: + * @arg RTC_TIMESTAMPEDGE_RISING: the Time stamp event occurs on the + * rising edge of the related pin. + * @arg RTC_TIMESTAMPEDGE_FALLING: the Time stamp event occurs on the + * falling edge of the related pin. + * @param RTC_TimeStampPin: specifies the RTC TimeStamp Pin. + * This parameter can be one of the following values: + * @arg RTC_TIMESTAMPPIN_DEFAULT: PC13 is selected as RTC TimeStamp Pin. + * The RTC TimeStamp Pin is per default PC13, but for reasons of + * compatibility, this parameter is required. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_SetTimeStamp(RTC_HandleTypeDef *hrtc, uint32_t TimeStampEdge, uint32_t RTC_TimeStampPin) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_TIMESTAMP_EDGE(TimeStampEdge)); + assert_param(IS_RTC_TIMESTAMP_PIN(RTC_TimeStampPin)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Get the RTC_CR register and clear the bits to be configured */ + tmpreg = (uint32_t)(hrtc->Instance->CR & (uint32_t)~(RTC_CR_TSEDGE | RTC_CR_TSE)); + + tmpreg|= TimeStampEdge; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Configure the Time Stamp TSEDGE and Enable bits */ + hrtc->Instance->CR = (uint32_t)tmpreg; + + __HAL_RTC_TIMESTAMP_ENABLE(hrtc); + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Set TimeStamp with Interrupt. + * @param hrtc: RTC handle + * @note This API must be called before enabling the TimeStamp feature. + * @param TimeStampEdge: Specifies the pin edge on which the TimeStamp is + * activated. + * This parameter can be one of the following values: + * @arg RTC_TIMESTAMPEDGE_RISING: the Time stamp event occurs on the + * rising edge of the related pin. + * @arg RTC_TIMESTAMPEDGE_FALLING: the Time stamp event occurs on the + * falling edge of the related pin. + * @param RTC_TimeStampPin: Specifies the RTC TimeStamp Pin. + * This parameter can be one of the following values: + * @arg RTC_TIMESTAMPPIN_DEFAULT: PC13 is selected as RTC TimeStamp Pin. + * The RTC TimeStamp Pin is per default PC13, but for reasons of + * compatibility, this parameter is required. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_SetTimeStamp_IT(RTC_HandleTypeDef *hrtc, uint32_t TimeStampEdge, uint32_t RTC_TimeStampPin) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_TIMESTAMP_EDGE(TimeStampEdge)); + assert_param(IS_RTC_TIMESTAMP_PIN(RTC_TimeStampPin)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Get the RTC_CR register and clear the bits to be configured */ + tmpreg = (uint32_t)(hrtc->Instance->CR & (uint32_t)~(RTC_CR_TSEDGE | RTC_CR_TSE)); + + tmpreg |= TimeStampEdge; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Configure the Time Stamp TSEDGE and Enable bits */ + hrtc->Instance->CR = (uint32_t)tmpreg; + + __HAL_RTC_TIMESTAMP_ENABLE(hrtc); + + /* Enable IT timestamp */ + __HAL_RTC_TIMESTAMP_ENABLE_IT(hrtc,RTC_IT_TS); + + /* RTC timestamp Interrupt Configuration: EXTI configuration */ + __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_IT(); + + __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_RISING_EDGE(); + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Deactivate TimeStamp. + * @param hrtc: RTC handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_DeactivateTimeStamp(RTC_HandleTypeDef *hrtc) +{ + uint32_t tmpreg = 0; + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* In case of interrupt mode is used, the interrupt source must disabled */ + __HAL_RTC_TIMESTAMP_DISABLE_IT(hrtc, RTC_IT_TS); + + /* Get the RTC_CR register and clear the bits to be configured */ + tmpreg = (uint32_t)(hrtc->Instance->CR & (uint32_t)~(RTC_CR_TSEDGE | RTC_CR_TSE)); + + /* Configure the Time Stamp TSEDGE and Enable bits */ + hrtc->Instance->CR = (uint32_t)tmpreg; + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Set Internal TimeStamp. + * @note This API must be called before enabling the internal TimeStamp feature. + * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_SetInternalTimeStamp(RTC_HandleTypeDef *hrtc) +{ + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Configure the internal Time Stamp Enable bits */ + __HAL_RTC_INTERNAL_TIMESTAMP_ENABLE(hrtc); + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Deactivate Internal TimeStamp. + * @param hrtc: pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_DeactivateInternalTimeStamp(RTC_HandleTypeDef *hrtc) +{ + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Configure the internal Time Stamp Enable bits */ + __HAL_RTC_INTERNAL_TIMESTAMP_DISABLE(hrtc); + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Get the RTC TimeStamp value. + * @param hrtc: RTC handle + * @param sTimeStamp: Pointer to Time structure + * @param sTimeStampDate: Pointer to Date structure + * @param Format: specifies the format of the entered parameters. + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN: Binary data format + * @arg RTC_FORMAT_BCD: BCD data format + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_GetTimeStamp(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef* sTimeStamp, RTC_DateTypeDef* sTimeStampDate, uint32_t Format) +{ + uint32_t tmptime = 0, tmpdate = 0; + + /* Check the parameters */ + assert_param(IS_RTC_FORMAT(Format)); + + /* Get the TimeStamp time and date registers values */ + tmptime = (uint32_t)(hrtc->Instance->TSTR & RTC_TR_RESERVED_MASK); + tmpdate = (uint32_t)(hrtc->Instance->TSDR & RTC_DR_RESERVED_MASK); + + /* Fill the Time structure fields with the read parameters */ + sTimeStamp->Hours = (uint8_t)((tmptime & (RTC_TR_HT | RTC_TR_HU)) >> 16); + sTimeStamp->Minutes = (uint8_t)((tmptime & (RTC_TR_MNT | RTC_TR_MNU)) >> 8); + sTimeStamp->Seconds = (uint8_t)(tmptime & (RTC_TR_ST | RTC_TR_SU)); + sTimeStamp->TimeFormat = (uint8_t)((tmptime & (RTC_TR_PM)) >> 16); + sTimeStamp->SubSeconds = (uint32_t) hrtc->Instance->TSSSR; + + /* Fill the Date structure fields with the read parameters */ + sTimeStampDate->Year = 0; + sTimeStampDate->Month = (uint8_t)((tmpdate & (RTC_DR_MT | RTC_DR_MU)) >> 8); + sTimeStampDate->Date = (uint8_t)(tmpdate & (RTC_DR_DT | RTC_DR_DU)); + sTimeStampDate->WeekDay = (uint8_t)((tmpdate & (RTC_DR_WDU)) >> 13); + + /* Check the input parameters format */ + if(Format == RTC_FORMAT_BIN) + { + /* Convert the TimeStamp structure parameters to Binary format */ + sTimeStamp->Hours = (uint8_t)RTC_Bcd2ToByte(sTimeStamp->Hours); + sTimeStamp->Minutes = (uint8_t)RTC_Bcd2ToByte(sTimeStamp->Minutes); + sTimeStamp->Seconds = (uint8_t)RTC_Bcd2ToByte(sTimeStamp->Seconds); + + /* Convert the DateTimeStamp structure parameters to Binary format */ + sTimeStampDate->Month = (uint8_t)RTC_Bcd2ToByte(sTimeStampDate->Month); + sTimeStampDate->Date = (uint8_t)RTC_Bcd2ToByte(sTimeStampDate->Date); + sTimeStampDate->WeekDay = (uint8_t)RTC_Bcd2ToByte(sTimeStampDate->WeekDay); + } + + /* Clear the TIMESTAMP Flags */ + __HAL_RTC_INTERNAL_TIMESTAMP_CLEAR_FLAG(hrtc, RTC_FLAG_ITSF); + __HAL_RTC_TIMESTAMP_CLEAR_FLAG(hrtc, RTC_FLAG_TSF); + + return HAL_OK; +} + +/** + * @brief Set Tamper. + * @note By calling this API we disable the tamper interrupt for all tampers. + * @param hrtc: RTC handle + * @param sTamper: Pointer to Tamper Structure. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_SetTamper(RTC_HandleTypeDef *hrtc, RTC_TamperTypeDef* sTamper) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_RTC_TAMPER(sTamper->Tamper)); + assert_param(IS_RTC_TAMPER_TRIGGER(sTamper->Trigger)); + assert_param(IS_RTC_TAMPER_ERASE_MODE(sTamper->NoErase)); + assert_param(IS_RTC_TAMPER_MASKFLAG_STATE(sTamper->MaskFlag)); + assert_param(IS_RTC_TAMPER_FILTER(sTamper->Filter)); + assert_param(IS_RTC_TAMPER_SAMPLING_FREQ(sTamper->SamplingFrequency)); + assert_param(IS_RTC_TAMPER_PRECHARGE_DURATION(sTamper->PrechargeDuration)); + assert_param(IS_RTC_TAMPER_PULLUP_STATE(sTamper->TamperPullUp)); + assert_param(IS_RTC_TAMPER_TIMESTAMPONTAMPER_DETECTION(sTamper->TimeStampOnTamperDetection)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Configure the tamper trigger */ + if(sTamper->Trigger != RTC_TAMPERTRIGGER_RISINGEDGE) + { + sTamper->Trigger = (uint32_t)(sTamper->Tamper << 1); + } + + if(sTamper->NoErase != RTC_TAMPER_ERASE_BACKUP_ENABLE) + { + sTamper->NoErase = 0; +#if defined(RTC_TAMPER1_SUPPORT) + if((sTamper->Tamper & RTC_TAMPER_1) != 0) + { + sTamper->NoErase |= RTC_TAMPCR_TAMP1NOERASE; + } +#endif /* RTC_TAMPER1_SUPPORT */ + if((sTamper->Tamper & RTC_TAMPER_2) != 0) + { + sTamper->NoErase |= RTC_TAMPCR_TAMP2NOERASE; + } +#if defined(RTC_TAMPER3_SUPPORT) + if((sTamper->Tamper & RTC_TAMPER_3) != 0) + { + sTamper->NoErase |= RTC_TAMPCR_TAMP3NOERASE; + } +#endif /* RTC_TAMPER3_SUPPORT */ + } + + if(sTamper->MaskFlag != RTC_TAMPERMASK_FLAG_DISABLE) + { + sTamper->MaskFlag = 0; +#if defined(RTC_TAMPER1_SUPPORT) + if((sTamper->Tamper & RTC_TAMPER_1) != 0) + { + sTamper->MaskFlag |= RTC_TAMPCR_TAMP1MF; + } +#endif /* RTC_TAMPER1_SUPPORT */ + if((sTamper->Tamper & RTC_TAMPER_2) != 0) + { + sTamper->MaskFlag |= RTC_TAMPCR_TAMP2MF; + } +#if defined(RTC_TAMPER3_SUPPORT) + if((sTamper->Tamper & RTC_TAMPER_3) != 0) + { + sTamper->MaskFlag |= RTC_TAMPCR_TAMP3MF; + } +#endif /* RTC_TAMPER3_SUPPORT */ + } + + tmpreg = ((uint32_t)sTamper->Tamper | (uint32_t)sTamper->Trigger | (uint32_t)sTamper->NoErase |\ + (uint32_t)sTamper->MaskFlag | (uint32_t)sTamper->Filter | (uint32_t)sTamper->SamplingFrequency |\ + (uint32_t)sTamper->PrechargeDuration | (uint32_t)sTamper->TamperPullUp | sTamper->TimeStampOnTamperDetection); + + hrtc->Instance->TAMPCR &= (uint32_t)~((uint32_t)sTamper->Tamper | (uint32_t)(sTamper->Tamper << 1) | RTC_TAMPCR_MASK); + + hrtc->Instance->TAMPCR |= tmpreg; + + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Set Tamper with interrupt. + * @note By calling this API we force the tamper interrupt for all tampers. + * @param hrtc: RTC handle + * @param sTamper: Pointer to RTC Tamper. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_SetTamper_IT(RTC_HandleTypeDef *hrtc, RTC_TamperTypeDef* sTamper) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_RTC_TAMPER(sTamper->Tamper)); + assert_param(IS_RTC_TAMPER_INTERRUPT(sTamper->Interrupt)); + assert_param(IS_RTC_TAMPER_TRIGGER(sTamper->Trigger)); + assert_param(IS_RTC_TAMPER_ERASE_MODE(sTamper->NoErase)); + assert_param(IS_RTC_TAMPER_MASKFLAG_STATE(sTamper->MaskFlag)); + assert_param(IS_RTC_TAMPER_FILTER(sTamper->Filter)); + assert_param(IS_RTC_TAMPER_SAMPLING_FREQ(sTamper->SamplingFrequency)); + assert_param(IS_RTC_TAMPER_PRECHARGE_DURATION(sTamper->PrechargeDuration)); + assert_param(IS_RTC_TAMPER_PULLUP_STATE(sTamper->TamperPullUp)); + assert_param(IS_RTC_TAMPER_TIMESTAMPONTAMPER_DETECTION(sTamper->TimeStampOnTamperDetection)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Configure the tamper trigger */ + if(sTamper->Trigger != RTC_TAMPERTRIGGER_RISINGEDGE) + { + sTamper->Trigger = (uint32_t)(sTamper->Tamper << 1); + } + + if(sTamper->NoErase != RTC_TAMPER_ERASE_BACKUP_ENABLE) + { + sTamper->NoErase = 0; +#if defined(RTC_TAMPER1_SUPPORT) + if((sTamper->Tamper & RTC_TAMPER_1) != 0) + { + sTamper->NoErase |= RTC_TAMPCR_TAMP1NOERASE; + } +#endif /* RTC_TAMPER1_SUPPORT */ + if((sTamper->Tamper & RTC_TAMPER_2) != 0) + { + sTamper->NoErase |= RTC_TAMPCR_TAMP2NOERASE; + } +#if defined(RTC_TAMPER3_SUPPORT) + if((sTamper->Tamper & RTC_TAMPER_3) != 0) + { + sTamper->NoErase |= RTC_TAMPCR_TAMP3NOERASE; + } +#endif /* RTC_TAMPER3_SUPPORT */ + } + + if(sTamper->MaskFlag != RTC_TAMPERMASK_FLAG_DISABLE) + { + sTamper->MaskFlag = 0; +#if defined(RTC_TAMPER1_SUPPORT) + if((sTamper->Tamper & RTC_TAMPER_1) != 0) + { + sTamper->MaskFlag |= RTC_TAMPCR_TAMP1MF; + } +#endif /* RTC_TAMPER1_SUPPORT */ + if((sTamper->Tamper & RTC_TAMPER_2) != 0) + { + sTamper->MaskFlag |= RTC_TAMPCR_TAMP2MF; + } +#if defined(RTC_TAMPER3_SUPPORT) + if((sTamper->Tamper & RTC_TAMPER_3) != 0) + { + sTamper->MaskFlag |= RTC_TAMPCR_TAMP3MF; + } +#endif /* RTC_TAMPER3_SUPPORT */ + } + + tmpreg = ((uint32_t)sTamper->Tamper | (uint32_t)sTamper->Interrupt | (uint32_t)sTamper->Trigger | (uint32_t)sTamper->NoErase |\ + (uint32_t)sTamper->MaskFlag | (uint32_t)sTamper->Filter | (uint32_t)sTamper->SamplingFrequency |\ + (uint32_t)sTamper->PrechargeDuration | (uint32_t)sTamper->TamperPullUp | sTamper->TimeStampOnTamperDetection); + + hrtc->Instance->TAMPCR &= (uint32_t)~((uint32_t)sTamper->Tamper | (uint32_t)(sTamper->Tamper << 1) | RTC_TAMPCR_MASK); + + hrtc->Instance->TAMPCR |= tmpreg; + + /* RTC Tamper Interrupt Configuration: EXTI configuration */ + __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_IT(); + + __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_RISING_EDGE(); + + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Deactivate Tamper. + * @param hrtc: RTC handle + * @param Tamper: Selected tamper pin. + * This parameter can be any combination of RTC_TAMPER_1, RTC_TAMPER_2 and RTC_TAMPER_3. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_DeactivateTamper(RTC_HandleTypeDef *hrtc, uint32_t Tamper) +{ + assert_param(IS_RTC_TAMPER(Tamper)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the selected Tamper pin */ + hrtc->Instance->TAMPCR &= ((uint32_t)~Tamper); + +#if defined(RTC_TAMPER1_SUPPORT) + if ((Tamper & RTC_TAMPER_1) != 0) + { + /* Disable the Tamper1 interrupt */ + hrtc->Instance->TAMPCR &= ((uint32_t)~(RTC_IT_TAMP | RTC_IT_TAMP1)); + } +#endif /* RTC_TAMPER1_SUPPORT */ + if ((Tamper & RTC_TAMPER_2) != 0) + { + /* Disable the Tamper2 interrupt */ + hrtc->Instance->TAMPCR &= ((uint32_t)~(RTC_IT_TAMP | RTC_IT_TAMP2)); + } +#if defined(RTC_TAMPER3_SUPPORT) + if ((Tamper & RTC_TAMPER_3) != 0) + { + /* Disable the Tamper3 interrupt */ + hrtc->Instance->TAMPCR &= ((uint32_t)~(RTC_IT_TAMP | RTC_IT_TAMP3)); + } +#endif /* RTC_TAMPER3_SUPPORT */ + + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Handle TimeStamp interrupt request. + * @param hrtc: RTC handle + * @retval None + */ +void HAL_RTCEx_TamperTimeStampIRQHandler(RTC_HandleTypeDef *hrtc) +{ + /* Clear the EXTI's Flag for RTC TimeStamp and Tamper */ + __HAL_RTC_TAMPER_TIMESTAMP_EXTI_CLEAR_FLAG(); + + /* As Tampers and TimeStamp are sharing the same EXTI line, exit when no more pending event */ + while( + ((__HAL_RTC_TIMESTAMP_GET_IT_SOURCE(hrtc, RTC_IT_TS) != RESET) && (__HAL_RTC_TIMESTAMP_GET_FLAG(hrtc, RTC_FLAG_TSF) != RESET)) +#if defined(RTC_TAMPER1_SUPPORT) + || ((__HAL_RTC_TAMPER_GET_IT_SOURCE(hrtc, RTC_IT_TAMP | RTC_IT_TAMP1) != RESET) && (__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP1F) != RESET)) +#endif /* RTC_TAMPER1_SUPPORT */ + || ((__HAL_RTC_TAMPER_GET_IT_SOURCE(hrtc, RTC_IT_TAMP | RTC_IT_TAMP2) != RESET) && (__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP2F) != RESET)) +#if defined(RTC_TAMPER3_SUPPORT) + || ((__HAL_RTC_TAMPER_GET_IT_SOURCE(hrtc, RTC_IT_TAMP | RTC_IT_TAMP3) != RESET) && (__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP3F) != RESET)) +#endif /* RTC_TAMPER3_SUPPORT */ + ) + { + + /* Get the TimeStamp interrupt source enable status and pending flag status */ + if((__HAL_RTC_TIMESTAMP_GET_IT_SOURCE(hrtc, RTC_IT_TS) != RESET) && (__HAL_RTC_TIMESTAMP_GET_FLAG(hrtc, RTC_FLAG_TSF) != RESET)) + { + /* TIMESTAMP callback */ + HAL_RTCEx_TimeStampEventCallback(hrtc); + + /* Clear the TIMESTAMP interrupt pending bit (this will clear timestamp time and date registers) */ + __HAL_RTC_TIMESTAMP_CLEAR_FLAG(hrtc, RTC_FLAG_TSF); + } + +#if defined(RTC_TAMPER1_SUPPORT) + /* Get the Tamper1 interrupt source enable status and pending flag status */ + if((__HAL_RTC_TAMPER_GET_IT_SOURCE(hrtc, RTC_IT_TAMP | RTC_IT_TAMP1) != RESET) && (__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP1F) != RESET)) + { + /* Clear the Tamper1 interrupt pending bit */ + __HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP1F); + + /* Tamper1 callback */ + HAL_RTCEx_Tamper1EventCallback(hrtc); + } +#endif /* RTC_TAMPER1_SUPPORT */ + + /* Get the Tamper2 interrupt source enable status and pending flag status */ + if((__HAL_RTC_TAMPER_GET_IT_SOURCE(hrtc, RTC_IT_TAMP | RTC_IT_TAMP2) != RESET) && (__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP2F) != RESET)) + { + /* Clear the Tamper2 interrupt pending bit */ + __HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP2F); + + /* Tamper2 callback */ + HAL_RTCEx_Tamper2EventCallback(hrtc); + } + +#if defined(RTC_TAMPER3_SUPPORT) + /* Get the Tamper3 interrupts source enable status and pending flag status */ + if((__HAL_RTC_TAMPER_GET_IT_SOURCE(hrtc, RTC_IT_TAMP | RTC_IT_TAMP3) != RESET) && (__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP3F) != RESET)) + { + /* Clear the Tamper3 interrupt pending bit */ + __HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP3F); + + /* Tamper3 callback */ + HAL_RTCEx_Tamper3EventCallback(hrtc); + } +#endif /* RTC_TAMPER3_SUPPORT */ + + } + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; +} + +/** + * @brief TimeStamp callback. + * @param hrtc: RTC handle + * @retval None + */ +__weak void HAL_RTCEx_TimeStampEventCallback(RTC_HandleTypeDef *hrtc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hrtc); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_RTCEx_TimeStampEventCallback could be implemented in the user file + */ +} + +#if defined(RTC_TAMPER1_SUPPORT) +/** + * @brief Tamper 1 callback. + * @param hrtc: RTC handle + * @retval None + */ +__weak void HAL_RTCEx_Tamper1EventCallback(RTC_HandleTypeDef *hrtc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hrtc); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_RTCEx_Tamper1EventCallback could be implemented in the user file + */ +} +#endif /* RTC_TAMPER1_SUPPORT */ + +/** + * @brief Tamper 2 callback. + * @param hrtc: RTC handle + * @retval None + */ +__weak void HAL_RTCEx_Tamper2EventCallback(RTC_HandleTypeDef *hrtc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hrtc); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_RTCEx_Tamper2EventCallback could be implemented in the user file + */ +} + +#if defined(RTC_TAMPER3_SUPPORT) +/** + * @brief Tamper 3 callback. + * @param hrtc: RTC handle + * @retval None + */ +__weak void HAL_RTCEx_Tamper3EventCallback(RTC_HandleTypeDef *hrtc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hrtc); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_RTCEx_Tamper3EventCallback could be implemented in the user file + */ +} +#endif /* RTC_TAMPER3_SUPPORT */ + +/** + * @brief Handle TimeStamp polling request. + * @param hrtc: RTC handle + * @param Timeout: Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_PollForTimeStampEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout) +{ + uint32_t tickstart = HAL_GetTick(); + + while(__HAL_RTC_TIMESTAMP_GET_FLAG(hrtc, RTC_FLAG_TSF) == RESET) + { + if(__HAL_RTC_TIMESTAMP_GET_FLAG(hrtc, RTC_FLAG_TSOVF) != RESET) + { + /* Clear the TIMESTAMP OverRun Flag */ + __HAL_RTC_TIMESTAMP_CLEAR_FLAG(hrtc, RTC_FLAG_TSOVF); + + /* Change TIMESTAMP state */ + hrtc->State = HAL_RTC_STATE_ERROR; + + return HAL_ERROR; + } + + if(Timeout != HAL_MAX_DELAY) + { + if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)) + { + hrtc->State = HAL_RTC_STATE_TIMEOUT; + return HAL_TIMEOUT; + } + } + } + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + return HAL_OK; +} + +#if defined(RTC_TAMPER1_SUPPORT) +/** + * @brief Handle Tamper 1 Polling. + * @param hrtc: RTC handle + * @param Timeout: Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_PollForTamper1Event(RTC_HandleTypeDef *hrtc, uint32_t Timeout) +{ + uint32_t tickstart = HAL_GetTick(); + + /* Get the status of the Interrupt */ + while(__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP1F)== RESET) + { + if(Timeout != HAL_MAX_DELAY) + { + if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)) + { + hrtc->State = HAL_RTC_STATE_TIMEOUT; + return HAL_TIMEOUT; + } + } + } + + /* Clear the Tamper Flag */ + __HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP1F); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + return HAL_OK; +} +#endif /* RTC_TAMPER1_SUPPORT */ + +/** + * @brief Handle Tamper 2 Polling. + * @param hrtc: RTC handle + * @param Timeout: Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_PollForTamper2Event(RTC_HandleTypeDef *hrtc, uint32_t Timeout) +{ + uint32_t tickstart = HAL_GetTick(); + + /* Get the status of the Interrupt */ + while(__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP2F) == RESET) + { + if(Timeout != HAL_MAX_DELAY) + { + if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)) + { + hrtc->State = HAL_RTC_STATE_TIMEOUT; + return HAL_TIMEOUT; + } + } + } + + /* Clear the Tamper Flag */ + __HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP2F); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + return HAL_OK; +} + +#if defined(RTC_TAMPER3_SUPPORT) +/** + * @brief Handle Tamper 3 Polling. + * @param hrtc: RTC handle + * @param Timeout: Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_PollForTamper3Event(RTC_HandleTypeDef *hrtc, uint32_t Timeout) +{ + uint32_t tickstart = HAL_GetTick(); + + /* Get the status of the Interrupt */ + while(__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP3F) == RESET) + { + if(Timeout != HAL_MAX_DELAY) + { + if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)) + { + hrtc->State = HAL_RTC_STATE_TIMEOUT; + return HAL_TIMEOUT; + } + } + } + + /* Clear the Tamper Flag */ + __HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP3F); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + return HAL_OK; +} +#endif /* RTC_TAMPER3_SUPPORT */ + +/** + * @} + */ + +/** @defgroup RTCEx_Exported_Functions_Group2 RTC Wake-up functions + * @brief RTC Wake-up functions + * +@verbatim + =============================================================================== + ##### RTC Wake-up functions ##### + =============================================================================== + + [..] This section provide functions allowing to configure Wake-up feature + +@endverbatim + * @{ + */ + +/** + * @brief Set wake up timer. + * @param hrtc: RTC handle + * @param WakeUpCounter: Wake up counter + * @param WakeUpClock: Wake up clock + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_SetWakeUpTimer(RTC_HandleTypeDef *hrtc, uint32_t WakeUpCounter, uint32_t WakeUpClock) +{ + uint32_t tickstart = 0; + + /* Check the parameters */ + assert_param(IS_RTC_WAKEUP_CLOCK(WakeUpClock)); + assert_param(IS_RTC_WAKEUP_COUNTER(WakeUpCounter)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /*Check RTC WUTWF flag is reset only when wake up timer enabled*/ + if((hrtc->Instance->CR & RTC_CR_WUTE) != RESET) + { + tickstart = HAL_GetTick(); + + /* Wait till RTC WUTWF flag is reset and if Time out is reached exit */ + while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTWF) == SET) + { + if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_TIMEOUT; + } + } + } + + __HAL_RTC_WAKEUPTIMER_DISABLE(hrtc); + + tickstart = HAL_GetTick(); + + /* Wait till RTC WUTWF flag is set and if Time out is reached exit */ + while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTWF) == RESET) + { + if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_TIMEOUT; + } + } + + /* Clear the Wakeup Timer clock source bits in CR register */ + hrtc->Instance->CR &= (uint32_t)~RTC_CR_WUCKSEL; + + /* Configure the clock source */ + hrtc->Instance->CR |= (uint32_t)WakeUpClock; + + /* Configure the Wakeup Timer counter */ + hrtc->Instance->WUTR = (uint32_t)WakeUpCounter; + + /* Enable the Wakeup Timer */ + __HAL_RTC_WAKEUPTIMER_ENABLE(hrtc); + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Set wake up timer with interrupt. + * @param hrtc: RTC handle + * @param WakeUpCounter: Wake up counter + * @param WakeUpClock: Wake up clock + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_SetWakeUpTimer_IT(RTC_HandleTypeDef *hrtc, uint32_t WakeUpCounter, uint32_t WakeUpClock) +{ + uint32_t tickstart = 0; + + /* Check the parameters */ + assert_param(IS_RTC_WAKEUP_CLOCK(WakeUpClock)); + assert_param(IS_RTC_WAKEUP_COUNTER(WakeUpCounter)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /*Check RTC WUTWF flag is reset only when wake up timer enabled*/ + if((hrtc->Instance->CR & RTC_CR_WUTE) != RESET) + { + tickstart = HAL_GetTick(); + + /* Wait till RTC WUTWF flag is reset and if Time out is reached exit */ + while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTWF) == SET) + { + if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_TIMEOUT; + } + } + } + /* Disable the Wake-Up timer */ + __HAL_RTC_WAKEUPTIMER_DISABLE(hrtc); + + /* Clear flag Wake-Up */ + __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(hrtc, RTC_FLAG_WUTF); + + tickstart = HAL_GetTick(); + + /* Wait till RTC WUTWF flag is set and if Time out is reached exit */ + while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTWF) == RESET) + { + if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_TIMEOUT; + } + } + + /* Configure the Wakeup Timer counter */ + hrtc->Instance->WUTR = (uint32_t)WakeUpCounter; + + /* Clear the Wakeup Timer clock source bits in CR register */ + hrtc->Instance->CR &= (uint32_t)~RTC_CR_WUCKSEL; + + /* Configure the clock source */ + hrtc->Instance->CR |= (uint32_t)WakeUpClock; + + /* RTC WakeUpTimer Interrupt Configuration: EXTI configuration */ + __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_IT(); + + __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_RISING_EDGE(); + + /* Configure the Interrupt in the RTC_CR register */ + __HAL_RTC_WAKEUPTIMER_ENABLE_IT(hrtc,RTC_IT_WUT); + + /* Enable the Wakeup Timer */ + __HAL_RTC_WAKEUPTIMER_ENABLE(hrtc); + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Deactivate wake up timer counter. + * @param hrtc: RTC handle + * @retval HAL status + */ +uint32_t HAL_RTCEx_DeactivateWakeUpTimer(RTC_HandleTypeDef *hrtc) +{ + uint32_t tickstart = 0; + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Disable the Wakeup Timer */ + __HAL_RTC_WAKEUPTIMER_DISABLE(hrtc); + + /* In case of interrupt mode is used, the interrupt source must disabled */ + __HAL_RTC_WAKEUPTIMER_DISABLE_IT(hrtc,RTC_IT_WUT); + + tickstart = HAL_GetTick(); + /* Wait till RTC WUTWF flag is set and if Time out is reached exit */ + while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTWF) == RESET) + { + if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_TIMEOUT; + } + } + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Get wake up timer counter. + * @param hrtc: RTC handle + * @retval Counter value + */ +uint32_t HAL_RTCEx_GetWakeUpTimer(RTC_HandleTypeDef *hrtc) +{ + /* Get the counter value */ + return ((uint32_t)(hrtc->Instance->WUTR & RTC_WUTR_WUT)); +} + +/** + * @brief Handle Wake Up Timer interrupt request. + * @param hrtc: RTC handle + * @retval None + */ +void HAL_RTCEx_WakeUpTimerIRQHandler(RTC_HandleTypeDef *hrtc) +{ + /* Clear the EXTI's line Flag for RTC WakeUpTimer */ + __HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG(); + + /* Get the pending status of the WAKEUPTIMER Interrupt */ + if(__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTF) != RESET) + { + /* Clear the WAKEUPTIMER interrupt pending bit */ + __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(hrtc, RTC_FLAG_WUTF); + + /* WAKEUPTIMER callback */ + HAL_RTCEx_WakeUpTimerEventCallback(hrtc); + } + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; +} + +/** + * @brief Wake Up Timer callback. + * @param hrtc: RTC handle + * @retval None + */ +__weak void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hrtc); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_RTCEx_WakeUpTimerEventCallback could be implemented in the user file + */ +} + +/** + * @brief Handle Wake Up Timer Polling. + * @param hrtc: RTC handle + * @param Timeout: Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_PollForWakeUpTimerEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout) +{ + uint32_t tickstart = HAL_GetTick(); + + while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTF) == RESET) + { + if(Timeout != HAL_MAX_DELAY) + { + if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)) + { + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + return HAL_TIMEOUT; + } + } + } + + /* Clear the WAKEUPTIMER Flag */ + __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(hrtc, RTC_FLAG_WUTF); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + return HAL_OK; +} + +/** + * @} + */ + + +/** @defgroup RTCEx_Exported_Functions_Group3 Extended Peripheral Control functions + * @brief Extended Peripheral Control functions + * +@verbatim + =============================================================================== + ##### Extended Peripheral Control functions ##### + =============================================================================== + [..] + This subsection provides functions allowing to + (+) Write a data in a specified RTC Backup data register + (+) Read a data in a specified RTC Backup data register + (+) Set the Coarse calibration parameters. + (+) Deactivate the Coarse calibration parameters + (+) Set the Smooth calibration parameters. + (+) Configure the Synchronization Shift Control Settings. + (+) Configure the Calibration Pinout (RTC_CALIB) Selection (1Hz or 512Hz). + (+) Deactivate the Calibration Pinout (RTC_CALIB) Selection (1Hz or 512Hz). + (+) Enable the RTC reference clock detection. + (+) Disable the RTC reference clock detection. + (+) Enable the Bypass Shadow feature. + (+) Disable the Bypass Shadow feature. + +@endverbatim + * @{ + */ + +/** + * @brief Write a data in a specified RTC Backup data register. + * @param hrtc: RTC handle + * @param BackupRegister: RTC Backup data Register number. + * This parameter can be: RTC_BKP_DRx where x can be from 0 to 19 to + * specify the register. + * @param Data: Data to be written in the specified RTC Backup data register. + * @retval None + */ +void HAL_RTCEx_BKUPWrite(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister, uint32_t Data) +{ + uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_RTC_BKP(BackupRegister)); + + tmp = (uint32_t)&(hrtc->Instance->BKP0R); + tmp += (BackupRegister * 4); + + /* Write the specified register */ + *(__IO uint32_t *)tmp = (uint32_t)Data; +} + +/** + * @brief Read data from the specified RTC Backup data Register. + * @param hrtc: RTC handle + * @param BackupRegister: RTC Backup data Register number. + * This parameter can be: RTC_BKP_DRx where x can be from 0 to 19 to + * specify the register. + * @retval Read value + */ +uint32_t HAL_RTCEx_BKUPRead(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister) +{ + uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_RTC_BKP(BackupRegister)); + + tmp = (uint32_t)&(hrtc->Instance->BKP0R); + tmp += (BackupRegister * 4); + + /* Read the specified register */ + return (*(__IO uint32_t *)tmp); +} + +/** + * @brief Set the Smooth calibration parameters. + * @param hrtc: RTC handle + * @param SmoothCalibPeriod: Select the Smooth Calibration Period. + * This parameter can be can be one of the following values : + * @arg RTC_SMOOTHCALIB_PERIOD_32SEC: The smooth calibration period is 32s. + * @arg RTC_SMOOTHCALIB_PERIOD_16SEC: The smooth calibration period is 16s. + * @arg RTC_SMOOTHCALIB_PERIOD_8SEC: The smooth calibration period is 8s. + * @param SmoothCalibPlusPulses: Select to Set or reset the CALP bit. + * This parameter can be one of the following values: + * @arg RTC_SMOOTHCALIB_PLUSPULSES_SET: Add one RTCCLK pulse every 2*11 pulses. + * @arg RTC_SMOOTHCALIB_PLUSPULSES_RESET: No RTCCLK pulses are added. + * @param SmoothCalibMinusPulsesValue: Select the value of CALM[8:0] bits. + * This parameter can be one any value from 0 to 0x000001FF. + * @note To deactivate the smooth calibration, the field SmoothCalibPlusPulses + * must be equal to SMOOTHCALIB_PLUSPULSES_RESET and the field + * SmoothCalibMinusPulsesValue must be equal to 0. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_SetSmoothCalib(RTC_HandleTypeDef* hrtc, uint32_t SmoothCalibPeriod, uint32_t SmoothCalibPlusPulses, uint32_t SmoothCalibMinusPulsesValue) +{ + uint32_t tickstart = 0; + + /* Check the parameters */ + assert_param(IS_RTC_SMOOTH_CALIB_PERIOD(SmoothCalibPeriod)); + assert_param(IS_RTC_SMOOTH_CALIB_PLUS(SmoothCalibPlusPulses)); + assert_param(IS_RTC_SMOOTH_CALIB_MINUS(SmoothCalibMinusPulsesValue)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* check if a calibration is pending*/ + if((hrtc->Instance->ISR & RTC_ISR_RECALPF) != RESET) + { + tickstart = HAL_GetTick(); + + /* check if a calibration is pending*/ + while((hrtc->Instance->ISR & RTC_ISR_RECALPF) != RESET) + { + if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_TIMEOUT; + } + } + } + + /* Configure the Smooth calibration settings */ + hrtc->Instance->CALR = (uint32_t)((uint32_t)SmoothCalibPeriod | (uint32_t)SmoothCalibPlusPulses | (uint32_t)SmoothCalibMinusPulsesValue); + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Configure the Synchronization Shift Control Settings. + * @note When REFCKON is set, firmware must not write to Shift control register. + * @param hrtc: RTC handle + * @param ShiftAdd1S: Select to add or not 1 second to the time calendar. + * This parameter can be one of the following values : + * @arg RTC_SHIFTADD1S_SET: Add one second to the clock calendar. + * @arg RTC_SHIFTADD1S_RESET: No effect. + * @param ShiftSubFS: Select the number of Second Fractions to substitute. + * This parameter can be one any value from 0 to 0x7FFF. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_SetSynchroShift(RTC_HandleTypeDef* hrtc, uint32_t ShiftAdd1S, uint32_t ShiftSubFS) +{ + uint32_t tickstart = 0; + + /* Check the parameters */ + assert_param(IS_RTC_SHIFT_ADD1S(ShiftAdd1S)); + assert_param(IS_RTC_SHIFT_SUBFS(ShiftSubFS)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + tickstart = HAL_GetTick(); + + /* Wait until the shift is completed*/ + while((hrtc->Instance->ISR & RTC_ISR_SHPF) != RESET) + { + if((HAL_GetTick() - tickstart ) > RTC_TIMEOUT_VALUE) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_TIMEOUT; + } + } + + /* Check if the reference clock detection is disabled */ + if((hrtc->Instance->CR & RTC_CR_REFCKON) == RESET) + { + /* Configure the Shift settings */ + hrtc->Instance->SHIFTR = (uint32_t)(uint32_t)(ShiftSubFS) | (uint32_t)(ShiftAdd1S); + + /* If RTC_CR_BYPSHAD bit = 0, wait for synchro else this check is not needed */ + if((hrtc->Instance->CR & RTC_CR_BYPSHAD) == RESET) + { + if(HAL_RTC_WaitForSynchro(hrtc) != HAL_OK) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_ERROR; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_ERROR; + } + } + } + else + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_ERROR; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_ERROR; + } + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Configure the Calibration Pinout (RTC_CALIB) Selection (1Hz or 512Hz). + * @param hrtc: RTC handle + * @param CalibOutput : Select the Calibration output Selection . + * This parameter can be one of the following values: + * @arg RTC_CALIBOUTPUT_512HZ: A signal has a regular waveform at 512Hz. + * @arg RTC_CALIBOUTPUT_1HZ: A signal has a regular waveform at 1Hz. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_SetCalibrationOutPut(RTC_HandleTypeDef* hrtc, uint32_t CalibOutput) +{ + /* Check the parameters */ + assert_param(IS_RTC_CALIB_OUTPUT(CalibOutput)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Clear flags before config */ + hrtc->Instance->CR &= (uint32_t)~RTC_CR_COSEL; + + /* Configure the RTC_CR register */ + hrtc->Instance->CR |= (uint32_t)CalibOutput; + + __HAL_RTC_CALIBRATION_OUTPUT_ENABLE(hrtc); + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Deactivate the Calibration Pinout (RTC_CALIB) Selection (1Hz or 512Hz). + * @param hrtc: RTC handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_DeactivateCalibrationOutPut(RTC_HandleTypeDef* hrtc) +{ + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + __HAL_RTC_CALIBRATION_OUTPUT_DISABLE(hrtc); + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Enable the RTC reference clock detection. + * @param hrtc: RTC handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_SetRefClock(RTC_HandleTypeDef* hrtc) +{ + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Set Initialization mode */ + if(RTC_EnterInitMode(hrtc) != HAL_OK) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Set RTC state*/ + hrtc->State = HAL_RTC_STATE_ERROR; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_ERROR; + } + else + { + __HAL_RTC_CLOCKREF_DETECTION_ENABLE(hrtc); + + /* Exit Initialization mode */ + hrtc->Instance->ISR &= (uint32_t)~RTC_ISR_INIT; + } + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Disable the RTC reference clock detection. + * @param hrtc: RTC handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_DeactivateRefClock(RTC_HandleTypeDef* hrtc) +{ + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Set Initialization mode */ + if(RTC_EnterInitMode(hrtc) != HAL_OK) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Set RTC state*/ + hrtc->State = HAL_RTC_STATE_ERROR; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_ERROR; + } + else + { + __HAL_RTC_CLOCKREF_DETECTION_DISABLE(hrtc); + + /* Exit Initialization mode */ + hrtc->Instance->ISR &= (uint32_t)~RTC_ISR_INIT; + } + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Enable the Bypass Shadow feature. + * @param hrtc: RTC handle + * @note When the Bypass Shadow is enabled the calendar value are taken + * directly from the Calendar counter. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_EnableBypassShadow(RTC_HandleTypeDef* hrtc) +{ + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Set the BYPSHAD bit */ + hrtc->Instance->CR |= (uint8_t)RTC_CR_BYPSHAD; + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Disable the Bypass Shadow feature. + * @param hrtc: RTC handle + * @note When the Bypass Shadow is enabled the calendar value are taken + * directly from the Calendar counter. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_DisableBypassShadow(RTC_HandleTypeDef* hrtc) +{ + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Reset the BYPSHAD bit */ + hrtc->Instance->CR &= ((uint8_t)~RTC_CR_BYPSHAD); + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup RTCEx_Exported_Functions_Group4 Extended features functions + * @brief Extended features functions + * +@verbatim + =============================================================================== + ##### Extended features functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) RTC Alarm B callback + (+) RTC Poll for Alarm B request + +@endverbatim + * @{ + */ + +/** + * @brief Alarm B callback. + * @param hrtc: RTC handle + * @retval None + */ +__weak void HAL_RTCEx_AlarmBEventCallback(RTC_HandleTypeDef *hrtc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hrtc); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_RTCEx_AlarmBEventCallback could be implemented in the user file + */ +} + +/** + * @brief Handle Alarm B Polling request. + * @param hrtc: RTC handle + * @param Timeout: Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_PollForAlarmBEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout) +{ + uint32_t tickstart = HAL_GetTick(); + + while(__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRBF) == RESET) + { + if(Timeout != HAL_MAX_DELAY) + { + if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)) + { + hrtc->State = HAL_RTC_STATE_TIMEOUT; + return HAL_TIMEOUT; + } + } + } + + /* Clear the Alarm Flag */ + __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRBF); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + return HAL_OK; +} + +/** + * @} + */ + +/** + * @} + */ + +#endif /* HAL_RTC_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_tim.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_tim.c new file mode 100644 index 0000000..41d343d --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_tim.c @@ -0,0 +1,5675 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_tim.c + * @author MCD Application Team + * @brief TIM HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Timer (TIM) peripheral: + * + Time Base Initialization + * + Time Base Start + * + Time Base Start Interruption + * + Time Base Start DMA + * + Time Output Compare/PWM Initialization + * + Time Output Compare/PWM Channel Configuration + * + Time Output Compare/PWM Start + * + Time Output Compare/PWM Start Interruption + * + Time Output Compare/PWM Start DMA + * + Time Input Capture Initialization + * + Time Input Capture Channel Configuration + * + Time Input Capture Start + * + Time Input Capture Start Interruption + * + Time Input Capture Start DMA + * + Time One Pulse Initialization + * + Time One Pulse Channel Configuration + * + Time One Pulse Start + * + Time Encoder Interface Initialization + * + Time Encoder Interface Start + * + Time Encoder Interface Start Interruption + * + Time Encoder Interface Start DMA + * + Commutation Event configuration with Interruption and DMA + * + Time OCRef clear configuration + * + Time External Clock configuration + @verbatim + ============================================================================== + ##### TIMER Generic features ##### + ============================================================================== + [..] The Timer features include: + (#) 16-bit up, down, up/down auto-reload counter. + (#) 16-bit programmable prescaler allowing dividing (also on the fly) the + counter clock frequency either by any factor between 1 and 65536. + (#) Up to 4 independent channels for: + (++) Input Capture + (++) Output Compare + (++) PWM generation (Edge and Center-aligned Mode) + (++) One-pulse mode output + + ##### How to use this driver ##### + ============================================================================== + [..] + (#) Initialize the TIM low level resources by implementing the following functions + depending on the selected feature: + (++) Time Base : HAL_TIM_Base_MspInit() + (++) Input Capture : HAL_TIM_IC_MspInit() + (++) Output Compare : HAL_TIM_OC_MspInit() + (++) PWM generation : HAL_TIM_PWM_MspInit() + (++) One-pulse mode output : HAL_TIM_OnePulse_MspInit() + (++) Encoder mode output : HAL_TIM_Encoder_MspInit() + + (#) Initialize the TIM low level resources : + (##) Enable the TIM interface clock using __HAL_RCC_TIMx_CLK_ENABLE(); + (##) TIM pins configuration + (+++) Enable the clock for the TIM GPIOs using the following function: + __HAL_RCC_GPIOx_CLK_ENABLE(); + (+++) Configure these TIM pins in Alternate function mode using HAL_GPIO_Init(); + + (#) The external Clock can be configured, if needed (the default clock is the + internal clock from the APBx), using the following function: + HAL_TIM_ConfigClockSource, the clock configuration should be done before + any start function. + + (#) Configure the TIM in the desired functioning mode using one of the + Initialization function of this driver: + (++) HAL_TIM_Base_Init: to use the Timer to generate a simple time base + (++) HAL_TIM_OC_Init and HAL_TIM_OC_ConfigChannel: to use the Timer to generate an + Output Compare signal. + (++) HAL_TIM_PWM_Init and HAL_TIM_PWM_ConfigChannel: to use the Timer to generate a + PWM signal. + (++) HAL_TIM_IC_Init and HAL_TIM_IC_ConfigChannel: to use the Timer to measure an + external signal. + (++) HAL_TIM_OnePulse_Init and HAL_TIM_OnePulse_ConfigChannel: to use the Timer + in One Pulse Mode. + (++) HAL_TIM_Encoder_Init: to use the Timer Encoder Interface. + + (#) Activate the TIM peripheral using one of the start functions depending from the feature used: + (++) Time Base : HAL_TIM_Base_Start(), HAL_TIM_Base_Start_DMA(), HAL_TIM_Base_Start_IT() + (++) Input Capture : HAL_TIM_IC_Start(), HAL_TIM_IC_Start_DMA(), HAL_TIM_IC_Start_IT() + (++) Output Compare : HAL_TIM_OC_Start(), HAL_TIM_OC_Start_DMA(), HAL_TIM_OC_Start_IT() + (++) PWM generation : HAL_TIM_PWM_Start(), HAL_TIM_PWM_Start_DMA(), HAL_TIM_PWM_Start_IT() + (++) One-pulse mode output : HAL_TIM_OnePulse_Start(), HAL_TIM_OnePulse_Start_IT() + (++) Encoder mode output : HAL_TIM_Encoder_Start(), HAL_TIM_Encoder_Start_DMA(), HAL_TIM_Encoder_Start_IT(). + + (#) The DMA Burst is managed with the two following functions: + HAL_TIM_DMABurst_WriteStart() + HAL_TIM_DMABurst_ReadStart() + + @endverbatim + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup TIM TIM + * @brief TIM HAL module driver + * @{ + */ + +#ifdef HAL_TIM_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +static void TIM_OC1_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config); +static void TIM_OC3_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config); +static void TIM_OC4_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config); +static void TIM_OC5_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config); +static void TIM_OC6_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config); +static void TIM_TI1_ConfigInputStage(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICFilter); +static void TIM_TI2_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection, + uint32_t TIM_ICFilter); +static void TIM_TI2_ConfigInputStage(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICFilter); +static void TIM_TI3_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection, + uint32_t TIM_ICFilter); +static void TIM_TI4_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection, + uint32_t TIM_ICFilter); +static void TIM_ITRx_SetConfig(TIM_TypeDef* TIMx, uint16_t InputTriggerSource); +static void TIM_DMAPeriodElapsedCplt(DMA_HandleTypeDef *hdma); +static void TIM_DMATriggerCplt(DMA_HandleTypeDef *hdma); +static void TIM_SlaveTimer_SetConfig(TIM_HandleTypeDef *htim, + TIM_SlaveConfigTypeDef * sSlaveConfig); +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup TIM_Exported_Functions TIM Exported Functions + * @{ + */ + +/** @defgroup TIM_Exported_Functions_Group1 Time Base functions + * @brief Time Base functions + * +@verbatim + ============================================================================== + ##### Time Base functions ##### + ============================================================================== + [..] + This section provides functions allowing to: + (+) Initialize and configure the TIM base. + (+) De-initialize the TIM base. + (+) Start the Time Base. + (+) Stop the Time Base. + (+) Start the Time Base and enable interrupt. + (+) Stop the Time Base and disable interrupt. + (+) Start the Time Base and enable DMA transfer. + (+) Stop the Time Base and disable DMA transfer. + +@endverbatim + * @{ + */ +/** + * @brief Initializes the TIM Time base Unit according to the specified + * parameters in the TIM_HandleTypeDef and initialize the associated handle. + * @note Switching from Center Aligned counter mode to Edge counter mode (or reverse) + * requires a timer reset to avoid unexpected direction + * due to DIR bit readonly in center aligned mode. + * Ex: call @ref HAL_TIM_Base_DeInit() before HAL_TIM_Base_Init() + * @param htim TIM Base handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_Base_Init(TIM_HandleTypeDef *htim) +{ + /* Check the TIM handle allocation */ + if(htim == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_TIM_INSTANCE(htim->Instance)); + assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode)); + assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision)); + assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload)); + + if(htim->State == HAL_TIM_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + htim->Lock = HAL_UNLOCKED; + + /* Init the low level hardware : GPIO, CLOCK, NVIC */ + HAL_TIM_Base_MspInit(htim); + } + + /* Set the TIM state */ + htim->State= HAL_TIM_STATE_BUSY; + + /* Set the Time Base configuration */ + TIM_Base_SetConfig(htim->Instance, &htim->Init); + + /* Initialize the TIM state*/ + htim->State= HAL_TIM_STATE_READY; + + return HAL_OK; +} + +/** + * @brief DeInitialize the TIM Base peripheral + * @param htim TIM Base handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_Base_DeInit(TIM_HandleTypeDef *htim) +{ + /* Check the parameters */ + assert_param(IS_TIM_INSTANCE(htim->Instance)); + + htim->State = HAL_TIM_STATE_BUSY; + + /* Disable the TIM Peripheral Clock */ + __HAL_TIM_DISABLE(htim); + + /* DeInit the low level hardware: GPIO, CLOCK, NVIC */ + HAL_TIM_Base_MspDeInit(htim); + + /* Change TIM state */ + htim->State = HAL_TIM_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @brief Initializes the TIM Base MSP. + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_TIM_Base_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitialize TIM Base MSP. + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_TIM_Base_MspDeInit could be implemented in the user file + */ +} + + +/** + * @brief Starts the TIM Base generation. + * @param htim TIM handle + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_Base_Start(TIM_HandleTypeDef *htim) +{ + /* Check the parameters */ + assert_param(IS_TIM_INSTANCE(htim->Instance)); + + /* Set the TIM state */ + htim->State= HAL_TIM_STATE_BUSY; + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Change the TIM state*/ + htim->State= HAL_TIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM Base generation. + * @param htim TIM handle + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_Base_Stop(TIM_HandleTypeDef *htim) +{ + /* Check the parameters */ + assert_param(IS_TIM_INSTANCE(htim->Instance)); + + /* Set the TIM state */ + htim->State= HAL_TIM_STATE_BUSY; + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Change the TIM state*/ + htim->State= HAL_TIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Starts the TIM Base generation in interrupt mode. + * @param htim TIM handle + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim) +{ + /* Check the parameters */ + assert_param(IS_TIM_INSTANCE(htim->Instance)); + + /* Enable the TIM Update interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_UPDATE); + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM Base generation in interrupt mode. + * @param htim TIM handle + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_Base_Stop_IT(TIM_HandleTypeDef *htim) +{ + /* Check the parameters */ + assert_param(IS_TIM_INSTANCE(htim->Instance)); + /* Disable the TIM Update interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_UPDATE); + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Starts the TIM Base generation in DMA mode. + * @param htim TIM handle + * @param pData The source Buffer address. + * @param Length The length of data to be transferred from memory to peripheral. + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_Base_Start_DMA(TIM_HandleTypeDef *htim, uint32_t *pData, uint16_t Length) +{ + /* Check the parameters */ + assert_param(IS_TIM_DMA_INSTANCE(htim->Instance)); + + if((htim->State == HAL_TIM_STATE_BUSY)) + { + return HAL_BUSY; + } + else if((htim->State == HAL_TIM_STATE_READY)) + { + if((pData == 0 ) && (Length > 0)) + { + return HAL_ERROR; + } + else + { + htim->State = HAL_TIM_STATE_BUSY; + } + } + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_UPDATE]->XferCpltCallback = TIM_DMAPeriodElapsedCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_UPDATE]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_UPDATE], (uint32_t)pData, (uint32_t)&htim->Instance->ARR, Length); + + /* Enable the TIM Update DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_UPDATE); + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM Base generation in DMA mode. + * @param htim TIM handle + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_Base_Stop_DMA(TIM_HandleTypeDef *htim) +{ + /* Check the parameters */ + assert_param(IS_TIM_DMA_INSTANCE(htim->Instance)); + + /* Disable the TIM Update DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_UPDATE); + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Change the htim state */ + htim->State = HAL_TIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup TIM_Exported_Functions_Group2 Time Output Compare functions + * @brief Time Output Compare functions + * +@verbatim + ============================================================================== + ##### Time Output Compare functions ##### + ============================================================================== + [..] + This section provides functions allowing to: + (+) Initialize and configure the TIM Output Compare. + (+) De-initialize the TIM Output Compare. + (+) Start the Time Output Compare. + (+) Stop the Time Output Compare. + (+) Start the Time Output Compare and enable interrupt. + (+) Stop the Time Output Compare and disable interrupt. + (+) Start the Time Output Compare and enable DMA transfer. + (+) Stop the Time Output Compare and disable DMA transfer. + +@endverbatim + * @{ + */ +/** + * @brief Initializes the TIM Output Compare according to the specified + * parameters in the TIM_HandleTypeDef and initialize the associated handle. + * @note Switching from Center Aligned counter mode to Edge counter mode (or reverse) + * requires a timer reset to avoid unexpected direction + * due to DIR bit readonly in center aligned mode. + * Ex: call @ref HAL_TIM_OC_DeInit() before HAL_TIM_OC_Init() + * @param htim TIM Output Compare handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_OC_Init(TIM_HandleTypeDef* htim) +{ + /* Check the TIM handle allocation */ + if(htim == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_TIM_INSTANCE(htim->Instance)); + assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode)); + assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision)); + assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload)); + + if(htim->State == HAL_TIM_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + htim->Lock = HAL_UNLOCKED; + + /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */ + HAL_TIM_OC_MspInit(htim); + } + + /* Set the TIM state */ + htim->State= HAL_TIM_STATE_BUSY; + + /* Init the base time for the Output Compare */ + TIM_Base_SetConfig(htim->Instance, &htim->Init); + + /* Initialize the TIM state*/ + htim->State= HAL_TIM_STATE_READY; + + return HAL_OK; +} + +/** + * @brief DeInitialize the TIM peripheral + * @param htim TIM Output Compare handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_OC_DeInit(TIM_HandleTypeDef *htim) +{ + /* Check the parameters */ + assert_param(IS_TIM_INSTANCE(htim->Instance)); + + htim->State = HAL_TIM_STATE_BUSY; + + /* Disable the TIM Peripheral Clock */ + __HAL_TIM_DISABLE(htim); + + /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */ + HAL_TIM_OC_MspDeInit(htim); + + /* Change TIM state */ + htim->State = HAL_TIM_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @brief Initializes the TIM Output Compare MSP. + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIM_OC_MspInit(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_TIM_OC_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitialize TIM Output Compare MSP. + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIM_OC_MspDeInit(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_TIM_OC_MspDeInit could be implemented in the user file + */ +} + +/** + * @brief Starts the TIM Output Compare signal generation. + * @param htim TIM Output Compare handle + * @param Channel TIM Channel to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @arg TIM_CHANNEL_5: TIM Channel 5 selected + * @arg TIM_CHANNEL_6: TIM Channel 6 selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_OC_Start(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel)); + + /* Enable the Output compare channel */ + TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE); + + if(IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET) + { + /* Enable the main output */ + __HAL_TIM_MOE_ENABLE(htim); + } + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM Output Compare signal generation. + * @param htim TIM handle + * @param Channel TIM Channel to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @arg TIM_CHANNEL_5: TIM Channel 5 selected + * @arg TIM_CHANNEL_6: TIM Channel 6 selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_OC_Stop(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel)); + + /* Disable the Output compare channel */ + TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE); + + if(IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET) + { + /* Disable the Main Ouput */ + __HAL_TIM_MOE_DISABLE(htim); + } + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Starts the TIM Output Compare signal generation in interrupt mode. + * @param htim TIM OC handle + * @param Channel TIM Channel to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @arg TIM_CHANNEL_5: TIM Channel 5 selected + * @arg TIM_CHANNEL_6: TIM Channel 6 selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_OC_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel)); + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Enable the TIM Capture/Compare 1 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Enable the TIM Capture/Compare 2 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2); + } + break; + + case TIM_CHANNEL_3: + { + /* Enable the TIM Capture/Compare 3 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Enable the TIM Capture/Compare 4 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC4); + } + break; + + default: + break; + } + + /* Enable the Output compare channel */ + TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE); + + if(IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET) + { + /* Enable the main output */ + __HAL_TIM_MOE_ENABLE(htim); + } + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM Output Compare signal generation in interrupt mode. + * @param htim TIM Output Compare handle + * @param Channel TIM Channel to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @arg TIM_CHANNEL_5: TIM Channel 5 selected + * @arg TIM_CHANNEL_6: TIM Channel 6 selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_OC_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel)); + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Disable the TIM Capture/Compare 1 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Disable the TIM Capture/Compare 2 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2); + } + break; + + case TIM_CHANNEL_3: + { + /* Disable the TIM Capture/Compare 3 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Disable the TIM Capture/Compare 4 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC4); + } + break; + + default: + break; + } + + /* Disable the Output compare channel */ + TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE); + + if(IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET) + { + /* Disable the Main Ouput */ + __HAL_TIM_MOE_DISABLE(htim); + } + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Starts the TIM Output Compare signal generation in DMA mode. + * @param htim TIM Output Compare handle + * @param Channel TIM Channel to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @arg TIM_CHANNEL_5: TIM Channel 5 selected + * @arg TIM_CHANNEL_6: TIM Channel 6 selected + * @param pData The source Buffer address. + * @param Length The length of data to be transferred from memory to TIM peripheral + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_OC_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel)); + + if((htim->State == HAL_TIM_STATE_BUSY)) + { + return HAL_BUSY; + } + else if((htim->State == HAL_TIM_STATE_READY)) + { + if(((uint32_t)pData == 0 ) && (Length > 0)) + { + return HAL_ERROR; + } + else + { + htim->State = HAL_TIM_STATE_BUSY; + } + } + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)pData, (uint32_t)&htim->Instance->CCR1, Length); + + /* Enable the TIM Capture/Compare 1 DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)pData, (uint32_t)&htim->Instance->CCR2, Length); + + /* Enable the TIM Capture/Compare 2 DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2); + } + break; + + case TIM_CHANNEL_3: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)pData, (uint32_t)&htim->Instance->CCR3,Length); + + /* Enable the TIM Capture/Compare 3 DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC4]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC4], (uint32_t)pData, (uint32_t)&htim->Instance->CCR4, Length); + + /* Enable the TIM Capture/Compare 4 DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC4); + } + break; + + default: + break; + } + + /* Enable the Output compare channel */ + TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE); + + if(IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET) + { + /* Enable the main output */ + __HAL_TIM_MOE_ENABLE(htim); + } + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM Output Compare signal generation in DMA mode. + * @param htim TIM Output Compare handle + * @param Channel TIM Channel to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @arg TIM_CHANNEL_5: TIM Channel 5 selected + * @arg TIM_CHANNEL_6: TIM Channel 6 selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_OC_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel)); + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Disable the TIM Capture/Compare 1 DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Disable the TIM Capture/Compare 2 DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2); + } + break; + + case TIM_CHANNEL_3: + { + /* Disable the TIM Capture/Compare 3 DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Disable the TIM Capture/Compare 4 interrupt */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC4); + } + break; + + default: + break; + } + + /* Disable the Output compare channel */ + TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE); + + if(IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET) + { + /* Disable the Main Ouput */ + __HAL_TIM_MOE_DISABLE(htim); + } + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Change the htim state */ + htim->State = HAL_TIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup TIM_Exported_Functions_Group3 Time PWM functions + * @brief Time PWM functions + * +@verbatim + ============================================================================== + ##### Time PWM functions ##### + ============================================================================== + [..] + This section provides functions allowing to: + (+) Initialize and configure the TIM OPWM. + (+) De-initialize the TIM PWM. + (+) Start the Time PWM. + (+) Stop the Time PWM. + (+) Start the Time PWM and enable interrupt. + (+) Stop the Time PWM and disable interrupt. + (+) Start the Time PWM and enable DMA transfer. + (+) Stop the Time PWM and disable DMA transfer. + +@endverbatim + * @{ + */ +/** + * @brief Initializes the TIM PWM Time Base according to the specified + * parameters in the TIM_HandleTypeDef and initialize the associated handle. + * @note Switching from Center Aligned counter mode to Edge counter mode (or reverse) + * requires a timer reset to avoid unexpected direction + * due to DIR bit readonly in center aligned mode. + * Ex: call @ref HAL_TIM_PWM_DeInit() before HAL_TIM_PWM_Init() + * @param htim TIM handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_PWM_Init(TIM_HandleTypeDef *htim) +{ + /* Check the TIM handle allocation */ + if(htim == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_TIM_INSTANCE(htim->Instance)); + assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode)); + assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision)); + assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload)); + + if(htim->State == HAL_TIM_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + htim->Lock = HAL_UNLOCKED; + + /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */ + HAL_TIM_PWM_MspInit(htim); + } + + /* Set the TIM state */ + htim->State= HAL_TIM_STATE_BUSY; + + /* Init the base time for the PWM */ + TIM_Base_SetConfig(htim->Instance, &htim->Init); + + /* Initialize the TIM state*/ + htim->State= HAL_TIM_STATE_READY; + + return HAL_OK; +} + +/** + * @brief DeInitialize the TIM peripheral + * @param htim TIM handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_PWM_DeInit(TIM_HandleTypeDef *htim) +{ + /* Check the parameters */ + assert_param(IS_TIM_INSTANCE(htim->Instance)); + + htim->State = HAL_TIM_STATE_BUSY; + + /* Disable the TIM Peripheral Clock */ + __HAL_TIM_DISABLE(htim); + + /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */ + HAL_TIM_PWM_MspDeInit(htim); + + /* Change TIM state */ + htim->State = HAL_TIM_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @brief Initializes the TIM PWM MSP. + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_TIM_PWM_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitialize TIM PWM MSP. + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIM_PWM_MspDeInit(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_TIM_PWM_MspDeInit could be implemented in the user file + */ +} + +/** + * @brief Starts the PWM signal generation. + * @param htim TIM handle + * @param Channel TIM Channels to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @arg TIM_CHANNEL_5: TIM Channel 5 selected + * @arg TIM_CHANNEL_6: TIM Channel 6 selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel)); + + /* Enable the Capture compare channel */ + TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE); + + if(IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET) + { + /* Enable the main output */ + __HAL_TIM_MOE_ENABLE(htim); + } + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the PWM signal generation. + * @param htim TIM handle + * @param Channel TIM Channels to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @arg TIM_CHANNEL_5: TIM Channel 5 selected + * @arg TIM_CHANNEL_6: TIM Channel 6 selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_PWM_Stop(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel)); + + /* Disable the Capture compare channel */ + TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE); + + if(IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET) + { + /* Disable the Main Ouput */ + __HAL_TIM_MOE_DISABLE(htim); + } + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Change the htim state */ + htim->State = HAL_TIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Starts the PWM signal generation in interrupt mode. + * @param htim TIM handle + * @param Channel TIM Channel to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_PWM_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel)); + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Enable the TIM Capture/Compare 1 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Enable the TIM Capture/Compare 2 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2); + } + break; + + case TIM_CHANNEL_3: + { + /* Enable the TIM Capture/Compare 3 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Enable the TIM Capture/Compare 4 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC4); + } + break; + + default: + break; + } + + /* Enable the Capture compare channel */ + TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE); + + if(IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET) + { + /* Enable the main output */ + __HAL_TIM_MOE_ENABLE(htim); + } + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the PWM signal generation in interrupt mode. + * @param htim TIM handle + * @param Channel TIM Channels to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_PWM_Stop_IT (TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel)); + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Disable the TIM Capture/Compare 1 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Disable the TIM Capture/Compare 2 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2); + } + break; + + case TIM_CHANNEL_3: + { + /* Disable the TIM Capture/Compare 3 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Disable the TIM Capture/Compare 4 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC4); + } + break; + + default: + break; + } + + /* Disable the Capture compare channel */ + TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE); + + if(IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET) + { + /* Disable the Main Ouput */ + __HAL_TIM_MOE_DISABLE(htim); + } + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Starts the TIM PWM signal generation in DMA mode. + * @param htim TIM handle + * @param Channel TIM Channels to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @param pData The source Buffer address. + * @param Length The length of data to be transferred from memory to TIM peripheral + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_PWM_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel)); + + if((htim->State == HAL_TIM_STATE_BUSY)) + { + return HAL_BUSY; + } + else if((htim->State == HAL_TIM_STATE_READY)) + { + if(((uint32_t)pData == 0 ) && (Length > 0)) + { + return HAL_ERROR; + } + else + { + htim->State = HAL_TIM_STATE_BUSY; + } + } + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)pData, (uint32_t)&htim->Instance->CCR1, Length); + + /* Enable the TIM Capture/Compare 1 DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)pData, (uint32_t)&htim->Instance->CCR2, Length); + + /* Enable the TIM Capture/Compare 2 DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2); + } + break; + + case TIM_CHANNEL_3: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)pData, (uint32_t)&htim->Instance->CCR3,Length); + + /* Enable the TIM Output Capture/Compare 3 request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC4]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC4], (uint32_t)pData, (uint32_t)&htim->Instance->CCR4, Length); + + /* Enable the TIM Capture/Compare 4 DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC4); + } + break; + + default: + break; + } + + /* Enable the Capture compare channel */ + TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE); + + if(IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET) + { + /* Enable the main output */ + __HAL_TIM_MOE_ENABLE(htim); + } + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM PWM signal generation in DMA mode. + * @param htim TIM handle + * @param Channel TIM Channels to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_PWM_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel)); + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Disable the TIM Capture/Compare 1 DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Disable the TIM Capture/Compare 2 DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2); + } + break; + + case TIM_CHANNEL_3: + { + /* Disable the TIM Capture/Compare 3 DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Disable the TIM Capture/Compare 4 interrupt */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC4); + } + break; + + default: + break; + } + + /* Disable the Capture compare channel */ + TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE); + + if(IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET) + { + /* Disable the Main Ouput */ + __HAL_TIM_MOE_DISABLE(htim); + } + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Change the htim state */ + htim->State = HAL_TIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup TIM_Exported_Functions_Group4 Time Input Capture functions + * @brief Time Input Capture functions + * +@verbatim + ============================================================================== + ##### Time Input Capture functions ##### + ============================================================================== + [..] + This section provides functions allowing to: + (+) Initialize and configure the TIM Input Capture. + (+) De-initialize the TIM Input Capture. + (+) Start the Time Input Capture. + (+) Stop the Time Input Capture. + (+) Start the Time Input Capture and enable interrupt. + (+) Stop the Time Input Capture and disable interrupt. + (+) Start the Time Input Capture and enable DMA transfer. + (+) Stop the Time Input Capture and disable DMA transfer. + +@endverbatim + * @{ + */ +/** + * @brief Initializes the TIM Input Capture Time base according to the specified + * parameters in the TIM_HandleTypeDef and initialize the associated handle. + * @note Switching from Center Aligned counter mode to Edge counter mode (or reverse) + * requires a timer reset to avoid unexpected direction + * due to DIR bit readonly in center aligned mode. + * Ex: call @ref HAL_TIM_IC_DeInit() before HAL_TIM_IC_Init() + * @param htim TIM Input Capture handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_IC_Init(TIM_HandleTypeDef *htim) +{ + /* Check the TIM handle allocation */ + if(htim == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_TIM_INSTANCE(htim->Instance)); + assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode)); + assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision)); + assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload)); + + if(htim->State == HAL_TIM_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + htim->Lock = HAL_UNLOCKED; + + /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */ + HAL_TIM_IC_MspInit(htim); + } + + /* Set the TIM state */ + htim->State= HAL_TIM_STATE_BUSY; + + /* Init the base time for the input capture */ + TIM_Base_SetConfig(htim->Instance, &htim->Init); + + /* Initialize the TIM state*/ + htim->State= HAL_TIM_STATE_READY; + + return HAL_OK; +} + +/** + * @brief DeInitialize the TIM peripheral + * @param htim TIM Input Capture handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_IC_DeInit(TIM_HandleTypeDef *htim) +{ + /* Check the parameters */ + assert_param(IS_TIM_INSTANCE(htim->Instance)); + + htim->State = HAL_TIM_STATE_BUSY; + + /* Disable the TIM Peripheral Clock */ + __HAL_TIM_DISABLE(htim); + + /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */ + HAL_TIM_IC_MspDeInit(htim); + + /* Change TIM state */ + htim->State = HAL_TIM_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @brief Initializes the TIM INput Capture MSP. + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIM_IC_MspInit(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_TIM_IC_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitialize TIM Input Capture MSP. + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIM_IC_MspDeInit(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_TIM_IC_MspDeInit could be implemented in the user file + */ +} + +/** + * @brief Starts the TIM Input Capture measurement. + * @param htim TIM Input Capture handle + * @param Channel TIM Channels to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_IC_Start (TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel)); + + /* Enable the Input Capture channel */ + TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE); + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM Input Capture measurement. + * @param htim TIM handle + * @param Channel TIM Channels to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_IC_Stop(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel)); + + /* Disable the Input Capture channel */ + TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE); + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Starts the TIM Input Capture measurement in interrupt mode. + * @param htim TIM Input Capture handle + * @param Channel TIM Channels to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_IC_Start_IT (TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel)); + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Enable the TIM Capture/Compare 1 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Enable the TIM Capture/Compare 2 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2); + } + break; + + case TIM_CHANNEL_3: + { + /* Enable the TIM Capture/Compare 3 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Enable the TIM Capture/Compare 4 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC4); + } + break; + + default: + break; + } + /* Enable the Input Capture channel */ + TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE); + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM Input Capture measurement in interrupt mode. + * @param htim TIM handle + * @param Channel TIM Channels to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_IC_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel)); + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Disable the TIM Capture/Compare 1 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Disable the TIM Capture/Compare 2 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2); + } + break; + + case TIM_CHANNEL_3: + { + /* Disable the TIM Capture/Compare 3 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Disable the TIM Capture/Compare 4 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC4); + } + break; + + default: + break; + } + + /* Disable the Input Capture channel */ + TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE); + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Starts the TIM Input Capture measurement on in DMA mode. + * @param htim TIM Input Capture handle + * @param Channel TIM Channels to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @param pData The destination Buffer address. + * @param Length The length of data to be transferred from TIM peripheral to memory. + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_IC_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel)); + assert_param(IS_TIM_DMA_CC_INSTANCE(htim->Instance)); + + if((htim->State == HAL_TIM_STATE_BUSY)) + { + return HAL_BUSY; + } + else if((htim->State == HAL_TIM_STATE_READY)) + { + if((pData == 0 ) && (Length > 0)) + { + return HAL_ERROR; + } + else + { + htim->State = HAL_TIM_STATE_BUSY; + } + } + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMACaptureCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)&htim->Instance->CCR1, (uint32_t)pData, Length); + + /* Enable the TIM Capture/Compare 1 DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMACaptureCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)&htim->Instance->CCR2, (uint32_t)pData, Length); + + /* Enable the TIM Capture/Compare 2 DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2); + } + break; + + case TIM_CHANNEL_3: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMACaptureCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)&htim->Instance->CCR3, (uint32_t)pData, Length); + + /* Enable the TIM Capture/Compare 3 DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC4]->XferCpltCallback = TIM_DMACaptureCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC4], (uint32_t)&htim->Instance->CCR4, (uint32_t)pData, Length); + + /* Enable the TIM Capture/Compare 4 DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC4); + } + break; + + default: + break; + } + + /* Enable the Input Capture channel */ + TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE); + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM Input Capture measurement in DMA mode. + * @param htim TIM Input Capture handle + * @param Channel TIM Channels to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_IC_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel)); + assert_param(IS_TIM_DMA_CC_INSTANCE(htim->Instance)); + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Disable the TIM Capture/Compare 1 DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Disable the TIM Capture/Compare 2 DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2); + } + break; + + case TIM_CHANNEL_3: + { + /* Disable the TIM Capture/Compare 3 DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Disable the TIM Capture/Compare 4 DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC4); + } + break; + + default: + break; + } + + /* Disable the Input Capture channel */ + TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_DISABLE); + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Change the htim state */ + htim->State = HAL_TIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} +/** + * @} + */ + +/** @defgroup TIM_Exported_Functions_Group5 Time One Pulse functions + * @brief Time One Pulse functions + * +@verbatim + ============================================================================== + ##### Time One Pulse functions ##### + ============================================================================== + [..] + This section provides functions allowing to: + (+) Initialize and configure the TIM One Pulse. + (+) De-initialize the TIM One Pulse. + (+) Start the Time One Pulse. + (+) Stop the Time One Pulse. + (+) Start the Time One Pulse and enable interrupt. + (+) Stop the Time One Pulse and disable interrupt. + (+) Start the Time One Pulse and enable DMA transfer. + (+) Stop the Time One Pulse and disable DMA transfer. + +@endverbatim + * @{ + */ +/** + * @brief Initializes the TIM One Pulse Time Base according to the specified + * parameters in the TIM_HandleTypeDef and initialize the associated handle. + * @note Switching from Center Aligned counter mode to Edge counter mode (or reverse) + * requires a timer reset to avoid unexpected direction + * due to DIR bit readonly in center aligned mode. + * Ex: call @ref HAL_TIM_OnePulse_DeInit() before HAL_TIM_OnePulse_Init() + * @param htim TIM OnePulse handle + * @param OnePulseMode Select the One pulse mode. + * This parameter can be one of the following values: + * @arg TIM_OPMODE_SINGLE: Only one pulse will be generated. + * @arg TIM_OPMODE_REPETITIVE: Repetitive pulses will be generated. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_OnePulse_Init(TIM_HandleTypeDef *htim, uint32_t OnePulseMode) +{ + /* Check the TIM handle allocation */ + if(htim == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_TIM_INSTANCE(htim->Instance)); + assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode)); + assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision)); + assert_param(IS_TIM_OPM_MODE(OnePulseMode)); + assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload)); + + if(htim->State == HAL_TIM_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + htim->Lock = HAL_UNLOCKED; + + /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */ + HAL_TIM_OnePulse_MspInit(htim); + } + + /* Set the TIM state */ + htim->State= HAL_TIM_STATE_BUSY; + + /* Configure the Time base in the One Pulse Mode */ + TIM_Base_SetConfig(htim->Instance, &htim->Init); + + /* Reset the OPM Bit */ + htim->Instance->CR1 &= ~TIM_CR1_OPM; + + /* Configure the OPM Mode */ + htim->Instance->CR1 |= OnePulseMode; + + /* Initialize the TIM state*/ + htim->State= HAL_TIM_STATE_READY; + + return HAL_OK; +} + +/** + * @brief DeInitialize the TIM One Pulse + * @param htim TIM One Pulse handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_OnePulse_DeInit(TIM_HandleTypeDef *htim) +{ + /* Check the parameters */ + assert_param(IS_TIM_INSTANCE(htim->Instance)); + + htim->State = HAL_TIM_STATE_BUSY; + + /* Disable the TIM Peripheral Clock */ + __HAL_TIM_DISABLE(htim); + + /* DeInit the low level hardware: GPIO, CLOCK, NVIC */ + HAL_TIM_OnePulse_MspDeInit(htim); + + /* Change TIM state */ + htim->State = HAL_TIM_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @brief Initializes the TIM One Pulse MSP. + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIM_OnePulse_MspInit(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_TIM_OnePulse_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitialize TIM One Pulse MSP. + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIM_OnePulse_MspDeInit(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_TIM_OnePulse_MspDeInit could be implemented in the user file + */ +} + +/** + * @brief Starts the TIM One Pulse signal generation. + * @param htim TIM One Pulse handle + * @param OutputChannel TIM Channels to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_OnePulse_Start(TIM_HandleTypeDef *htim, uint32_t OutputChannel) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(OutputChannel); + + /* Enable the Capture compare and the Input Capture channels + (in the OPM Mode the two possible channels that can be used are TIM_CHANNEL_1 and TIM_CHANNEL_2) + if TIM_CHANNEL_1 is used as output, the TIM_CHANNEL_2 will be used as input and + if TIM_CHANNEL_1 is used as input, the TIM_CHANNEL_2 will be used as output + in all combinations, the TIM_CHANNEL_1 and TIM_CHANNEL_2 should be enabled together + + No need to enable the counter, it's enabled automatically by hardware + (the counter starts in response to a stimulus and generate a pulse */ + + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE); + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE); + + if(IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET) + { + /* Enable the main output */ + __HAL_TIM_MOE_ENABLE(htim); + } + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM One Pulse signal generation. + * @param htim TIM One Pulse handle + * @param OutputChannel TIM Channels to be disable + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_OnePulse_Stop(TIM_HandleTypeDef *htim, uint32_t OutputChannel) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(OutputChannel); + + /* Disable the Capture compare and the Input Capture channels + (in the OPM Mode the two possible channels that can be used are TIM_CHANNEL_1 and TIM_CHANNEL_2) + if TIM_CHANNEL_1 is used as output, the TIM_CHANNEL_2 will be used as input and + if TIM_CHANNEL_1 is used as input, the TIM_CHANNEL_2 will be used as output + in all combinations, the TIM_CHANNEL_1 and TIM_CHANNEL_2 should be disabled together */ + + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE); + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE); + + if(IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET) + { + /* Disable the Main Ouput */ + __HAL_TIM_MOE_DISABLE(htim); + } + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Starts the TIM One Pulse signal generation in interrupt mode. + * @param htim TIM One Pulse handle + * @param OutputChannel TIM Channels to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_OnePulse_Start_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(OutputChannel); + + /* Enable the Capture compare and the Input Capture channels + (in the OPM Mode the two possible channels that can be used are TIM_CHANNEL_1 and TIM_CHANNEL_2) + if TIM_CHANNEL_1 is used as output, the TIM_CHANNEL_2 will be used as input and + if TIM_CHANNEL_1 is used as input, the TIM_CHANNEL_2 will be used as output + in all combinations, the TIM_CHANNEL_1 and TIM_CHANNEL_2 should be enabled together + + No need to enable the counter, it's enabled automatically by hardware + (the counter starts in response to a stimulus and generate a pulse */ + + /* Enable the TIM Capture/Compare 1 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1); + + /* Enable the TIM Capture/Compare 2 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2); + + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE); + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE); + + if(IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET) + { + /* Enable the main output */ + __HAL_TIM_MOE_ENABLE(htim); + } + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM One Pulse signal generation in interrupt mode. + * @param htim TIM One Pulse handle + * @param OutputChannel TIM Channels to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_OnePulse_Stop_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(OutputChannel); + + /* Disable the TIM Capture/Compare 1 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1); + + /* Disable the TIM Capture/Compare 2 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2); + + /* Disable the Capture compare and the Input Capture channels + (in the OPM Mode the two possible channels that can be used are TIM_CHANNEL_1 and TIM_CHANNEL_2) + if TIM_CHANNEL_1 is used as output, the TIM_CHANNEL_2 will be used as input and + if TIM_CHANNEL_1 is used as input, the TIM_CHANNEL_2 will be used as output + in all combinations, the TIM_CHANNEL_1 and TIM_CHANNEL_2 should be disabled together */ + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE); + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE); + + if(IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET) + { + /* Disable the Main Ouput */ + __HAL_TIM_MOE_DISABLE(htim); + } + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup TIM_Exported_Functions_Group6 Time Encoder functions + * @brief Time Encoder functions + * +@verbatim + ============================================================================== + ##### Time Encoder functions ##### + ============================================================================== + [..] + This section provides functions allowing to: + (+) Initialize and configure the TIM Encoder. + (+) De-initialize the TIM Encoder. + (+) Start the Time Encoder. + (+) Stop the Time Encoder. + (+) Start the Time Encoder and enable interrupt. + (+) Stop the Time Encoder and disable interrupt. + (+) Start the Time Encoder and enable DMA transfer. + (+) Stop the Time Encoder and disable DMA transfer. + +@endverbatim + * @{ + */ +/** + * @brief Initializes the TIM Encoder Interface and initialize the associated handle. + * @note Switching from Center Aligned counter mode to Edge counter mode (or reverse) + * requires a timer reset to avoid unexpected direction + * due to DIR bit readonly in center aligned mode. + * Ex: call @ref HAL_TIM_Encoder_DeInit() before HAL_TIM_Encoder_Init() + * @param htim TIM Encoder Interface handle + * @param sConfig TIM Encoder Interface configuration structure + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_Encoder_Init(TIM_HandleTypeDef *htim, TIM_Encoder_InitTypeDef* sConfig) +{ + uint32_t tmpsmcr = 0; + uint32_t tmpccmr1 = 0; + uint32_t tmpccer = 0; + + /* Check the TIM handle allocation */ + if(htim == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_TIM_CC2_INSTANCE(htim->Instance)); + assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode)); + assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision)); + assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload)); + assert_param(IS_TIM_ENCODER_MODE(sConfig->EncoderMode)); + assert_param(IS_TIM_IC_SELECTION(sConfig->IC1Selection)); + assert_param(IS_TIM_IC_SELECTION(sConfig->IC2Selection)); + assert_param(IS_TIM_IC_POLARITY(sConfig->IC1Polarity)); + assert_param(IS_TIM_IC_POLARITY(sConfig->IC2Polarity)); + assert_param(IS_TIM_IC_PRESCALER(sConfig->IC1Prescaler)); + assert_param(IS_TIM_IC_PRESCALER(sConfig->IC2Prescaler)); + assert_param(IS_TIM_IC_FILTER(sConfig->IC1Filter)); + assert_param(IS_TIM_IC_FILTER(sConfig->IC2Filter)); + + if(htim->State == HAL_TIM_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + htim->Lock = HAL_UNLOCKED; + + /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */ + HAL_TIM_Encoder_MspInit(htim); + } + + /* Set the TIM state */ + htim->State= HAL_TIM_STATE_BUSY; + + /* Reset the SMS bits */ + htim->Instance->SMCR &= ~TIM_SMCR_SMS; + + /* Configure the Time base in the Encoder Mode */ + TIM_Base_SetConfig(htim->Instance, &htim->Init); + + /* Get the TIMx SMCR register value */ + tmpsmcr = htim->Instance->SMCR; + + /* Get the TIMx CCMR1 register value */ + tmpccmr1 = htim->Instance->CCMR1; + + /* Get the TIMx CCER register value */ + tmpccer = htim->Instance->CCER; + + /* Set the encoder Mode */ + tmpsmcr |= sConfig->EncoderMode; + + /* Select the Capture Compare 1 and the Capture Compare 2 as input */ + tmpccmr1 &= ~(TIM_CCMR1_CC1S | TIM_CCMR1_CC2S); + tmpccmr1 |= (sConfig->IC1Selection | (sConfig->IC2Selection << 8)); + + /* Set the Capture Compare 1 and the Capture Compare 2 prescalers and filters */ + tmpccmr1 &= ~(TIM_CCMR1_IC1PSC | TIM_CCMR1_IC2PSC); + tmpccmr1 &= ~(TIM_CCMR1_IC1F | TIM_CCMR1_IC2F); + tmpccmr1 |= sConfig->IC1Prescaler | (sConfig->IC2Prescaler << 8); + tmpccmr1 |= (sConfig->IC1Filter << 4) | (sConfig->IC2Filter << 12); + + /* Set the TI1 and the TI2 Polarities */ + tmpccer &= ~(TIM_CCER_CC1P | TIM_CCER_CC2P); + tmpccer &= ~(TIM_CCER_CC1NP | TIM_CCER_CC2NP); + tmpccer |= sConfig->IC1Polarity | (sConfig->IC2Polarity << 4); + + /* Write to TIMx SMCR */ + htim->Instance->SMCR = tmpsmcr; + + /* Write to TIMx CCMR1 */ + htim->Instance->CCMR1 = tmpccmr1; + + /* Write to TIMx CCER */ + htim->Instance->CCER = tmpccer; + + /* Initialize the TIM state*/ + htim->State= HAL_TIM_STATE_READY; + + return HAL_OK; +} + + +/** + * @brief DeInitialize the TIM Encoder interface + * @param htim TIM Encoder handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_Encoder_DeInit(TIM_HandleTypeDef *htim) +{ + /* Check the parameters */ + assert_param(IS_TIM_INSTANCE(htim->Instance)); + + htim->State = HAL_TIM_STATE_BUSY; + + /* Disable the TIM Peripheral Clock */ + __HAL_TIM_DISABLE(htim); + + /* DeInit the low level hardware: GPIO, CLOCK, NVIC */ + HAL_TIM_Encoder_MspDeInit(htim); + + /* Change TIM state */ + htim->State = HAL_TIM_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @brief Initializes the TIM Encoder Interface MSP. + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_TIM_Encoder_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitialize TIM Encoder Interface MSP. + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIM_Encoder_MspDeInit(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_TIM_Encoder_MspDeInit could be implemented in the user file + */ +} + +/** + * @brief Starts the TIM Encoder Interface. + * @param htim TIM Encoder Interface handle + * @param Channel TIM Channels to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_ALL: TIM Channel 1 and TIM Channel 2 are selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_Encoder_Start(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CC2_INSTANCE(htim->Instance)); + + /* Enable the encoder interface channels */ + switch (Channel) + { + case TIM_CHANNEL_1: + { + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE); + } + break; + + case TIM_CHANNEL_2: + { + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE); + } + break; + + default : + { + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE); + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE); + } + break; + } + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM Encoder Interface. + * @param htim TIM Encoder Interface handle + * @param Channel TIM Channels to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_ALL: TIM Channel 1 and TIM Channel 2 are selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_Encoder_Stop(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CC2_INSTANCE(htim->Instance)); + + /* Disable the Input Capture channels 1 and 2 + (in the EncoderInterface the two possible channels that can be used are TIM_CHANNEL_1 and TIM_CHANNEL_2) */ + switch (Channel) + { + case TIM_CHANNEL_1: + { + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE); + } + break; + + case TIM_CHANNEL_2: + { + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE); + } + break; + + default : + { + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE); + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE); + } + break; + } + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Starts the TIM Encoder Interface in interrupt mode. + * @param htim TIM Encoder Interface handle + * @param Channel TIM Channels to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_ALL: TIM Channel 1 and TIM Channel 2 are selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_Encoder_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CC2_INSTANCE(htim->Instance)); + + /* Enable the encoder interface channels */ + /* Enable the capture compare Interrupts 1 and/or 2 */ + switch (Channel) + { + case TIM_CHANNEL_1: + { + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE); + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1); + } + break; + + case TIM_CHANNEL_2: + { + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE); + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2); + } + break; + + default : + { + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE); + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE); + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1); + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2); + } + break; + } + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM Encoder Interface in interrupt mode. + * @param htim TIM Encoder Interface handle + * @param Channel TIM Channels to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_ALL: TIM Channel 1 and TIM Channel 2 are selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_Encoder_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CC2_INSTANCE(htim->Instance)); + + /* Disable the Input Capture channels 1 and 2 + (in the EncoderInterface the two possible channels that can be used are TIM_CHANNEL_1 and TIM_CHANNEL_2) */ + if(Channel == TIM_CHANNEL_1) + { + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE); + + /* Disable the capture compare Interrupts 1 */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1); + } + else if(Channel == TIM_CHANNEL_2) + { + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE); + + /* Disable the capture compare Interrupts 2 */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2); + } + else + { + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE); + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE); + + /* Disable the capture compare Interrupts 1 and 2 */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1); + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2); + } + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Change the htim state */ + htim->State = HAL_TIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Starts the TIM Encoder Interface in DMA mode. + * @param htim TIM Encoder Interface handle + * @param Channel TIM Channels to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_ALL: TIM Channel 1 and TIM Channel 2 are selected + * @param pData1 The destination Buffer address for IC1. + * @param pData2 The destination Buffer address for IC2. + * @param Length The length of data to be transferred from TIM peripheral to memory. + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_Encoder_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData1, uint32_t *pData2, uint16_t Length) +{ + /* Check the parameters */ + assert_param(IS_TIM_DMA_CC_INSTANCE(htim->Instance)); + + if((htim->State == HAL_TIM_STATE_BUSY)) + { + return HAL_BUSY; + } + else if((htim->State == HAL_TIM_STATE_READY)) + { + if((((pData1 == 0) || (pData2 == 0) )) && (Length > 0)) + { + return HAL_ERROR; + } + else + { + htim->State = HAL_TIM_STATE_BUSY; + } + } + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMACaptureCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)&htim->Instance->CCR1, (uint32_t )pData1, Length); + + /* Enable the TIM Input Capture DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1); + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Enable the Capture compare channel */ + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE); + } + break; + + case TIM_CHANNEL_2: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMACaptureCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError; + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)&htim->Instance->CCR2, (uint32_t)pData2, Length); + + /* Enable the TIM Input Capture DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2); + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Enable the Capture compare channel */ + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE); + } + break; + + case TIM_CHANNEL_ALL: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMACaptureCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)&htim->Instance->CCR1, (uint32_t)pData1, Length); + + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMACaptureCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)&htim->Instance->CCR2, (uint32_t)pData2, Length); + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Enable the Capture compare channel */ + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE); + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE); + + /* Enable the TIM Input Capture DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1); + /* Enable the TIM Input Capture DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2); + } + break; + + default: + break; + } + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM Encoder Interface in DMA mode. + * @param htim TIM Encoder Interface handle + * @param Channel TIM Channels to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_ALL: TIM Channel 1 and TIM Channel 2 are selected + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_TIM_Encoder_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_DMA_CC_INSTANCE(htim->Instance)); + + /* Disable the Input Capture channels 1 and 2 + (in the EncoderInterface the two possible channels that can be used are TIM_CHANNEL_1 and TIM_CHANNEL_2) */ + if(Channel == TIM_CHANNEL_1) + { + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE); + + /* Disable the capture compare DMA Request 1 */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1); + } + else if(Channel == TIM_CHANNEL_2) + { + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE); + + /* Disable the capture compare DMA Request 2 */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2); + } + else + { + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE); + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_2, TIM_CCx_DISABLE); + + /* Disable the capture compare DMA Request 1 and 2 */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1); + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2); + } + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Change the htim state */ + htim->State = HAL_TIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @} + */ +/** @defgroup TIM_Exported_Functions_Group7 TIM IRQ handler management + * @brief IRQ handler management + * +@verbatim + ============================================================================== + ##### IRQ handler management ##### + ============================================================================== + [..] + This section provides Timer IRQ handler function. + +@endverbatim + * @{ + */ +/** + * @brief This function handles TIM interrupts requests. + * @param htim TIM handle + * @retval None + */ +void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim) +{ + /* Capture compare 1 event */ + if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC1) != RESET) + { + if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC1) !=RESET) + { + { + __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC1); + htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1; + + /* Input capture event */ + if((htim->Instance->CCMR1 & TIM_CCMR1_CC1S) != 0x00) + { + HAL_TIM_IC_CaptureCallback(htim); + } + /* Output compare event */ + else + { + HAL_TIM_OC_DelayElapsedCallback(htim); + HAL_TIM_PWM_PulseFinishedCallback(htim); + } + htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED; + } + } + } + /* Capture compare 2 event */ + if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC2) != RESET) + { + if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC2) !=RESET) + { + __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC2); + htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2; + /* Input capture event */ + if((htim->Instance->CCMR1 & TIM_CCMR1_CC2S) != 0x00) + { + HAL_TIM_IC_CaptureCallback(htim); + } + /* Output compare event */ + else + { + HAL_TIM_OC_DelayElapsedCallback(htim); + HAL_TIM_PWM_PulseFinishedCallback(htim); + } + htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED; + } + } + /* Capture compare 3 event */ + if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC3) != RESET) + { + if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC3) !=RESET) + { + __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC3); + htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3; + /* Input capture event */ + if((htim->Instance->CCMR2 & TIM_CCMR2_CC3S) != 0x00) + { + HAL_TIM_IC_CaptureCallback(htim); + } + /* Output compare event */ + else + { + HAL_TIM_OC_DelayElapsedCallback(htim); + HAL_TIM_PWM_PulseFinishedCallback(htim); + } + htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED; + } + } + /* Capture compare 4 event */ + if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC4) != RESET) + { + if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC4) !=RESET) + { + __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC4); + htim->Channel = HAL_TIM_ACTIVE_CHANNEL_4; + /* Input capture event */ + if((htim->Instance->CCMR2 & TIM_CCMR2_CC4S) != 0x00) + { + HAL_TIM_IC_CaptureCallback(htim); + } + /* Output compare event */ + else + { + HAL_TIM_OC_DelayElapsedCallback(htim); + HAL_TIM_PWM_PulseFinishedCallback(htim); + } + htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED; + } + } + /* TIM Update event */ + if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_UPDATE) != RESET) + { + if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_UPDATE) !=RESET) + { + __HAL_TIM_CLEAR_IT(htim, TIM_IT_UPDATE); + HAL_TIM_PeriodElapsedCallback(htim); + } + } + /* TIM Break input event */ + if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_BREAK) != RESET) + { + if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_BREAK) !=RESET) + { + __HAL_TIM_CLEAR_IT(htim, TIM_IT_BREAK); + HAL_TIMEx_BreakCallback(htim); + } + } + /* TIM Trigger detection event */ + if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_TRIGGER) != RESET) + { + if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_TRIGGER) !=RESET) + { + __HAL_TIM_CLEAR_IT(htim, TIM_IT_TRIGGER); + HAL_TIM_TriggerCallback(htim); + } + } + /* TIM commutation event */ + if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_COM) != RESET) + { + if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_COM) !=RESET) + { + __HAL_TIM_CLEAR_IT(htim, TIM_FLAG_COM); + HAL_TIMEx_CommutationCallback(htim); + } + } +} + +/** + * @} + */ + +/** @defgroup TIM_Exported_Functions_Group8 Peripheral Control functions + * @brief Peripheral Control functions + * +@verbatim + ============================================================================== + ##### Peripheral Control functions ##### + ============================================================================== + [..] + This section provides functions allowing to: + (+) Configure The Input Output channels for OC, PWM, IC or One Pulse mode. + (+) Configure External Clock source. + (+) Configure Complementary channels, break features and dead time. + (+) Configure Master and the Slave synchronization. + (+) Configure the DMA Burst Mode. + +@endverbatim + * @{ + */ + +/** + * @brief Initializes the TIM Output Compare Channels according to the specified + * parameters in the TIM_OC_InitTypeDef. + * @param htim TIM Output Compare handle + * @param sConfig TIM Output Compare configuration structure + * @param Channel TIM Channels to configure + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @arg TIM_CHANNEL_5: TIM Channel 5 selected + * @arg TIM_CHANNEL_6: TIM Channel 6 selected + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_OC_ConfigChannel(TIM_HandleTypeDef *htim, + TIM_OC_InitTypeDef* sConfig, + uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CHANNELS(Channel)); + assert_param(IS_TIM_OC_MODE(sConfig->OCMode)); + assert_param(IS_TIM_OC_POLARITY(sConfig->OCPolarity)); + + /* Process Locked */ + __HAL_LOCK(htim); + + htim->State = HAL_TIM_STATE_BUSY; + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Check the parameters */ + assert_param(IS_TIM_CC1_INSTANCE(htim->Instance)); + + /* Configure the TIM Channel 1 in Output Compare */ + TIM_OC1_SetConfig(htim->Instance, sConfig); + } + break; + + case TIM_CHANNEL_2: + { + /* Check the parameters */ + assert_param(IS_TIM_CC2_INSTANCE(htim->Instance)); + + /* Configure the TIM Channel 2 in Output Compare */ + TIM_OC2_SetConfig(htim->Instance, sConfig); + } + break; + + case TIM_CHANNEL_3: + { + /* Check the parameters */ + assert_param(IS_TIM_CC3_INSTANCE(htim->Instance)); + + /* Configure the TIM Channel 3 in Output Compare */ + TIM_OC3_SetConfig(htim->Instance, sConfig); + } + break; + + case TIM_CHANNEL_4: + { + /* Check the parameters */ + assert_param(IS_TIM_CC4_INSTANCE(htim->Instance)); + + /* Configure the TIM Channel 4 in Output Compare */ + TIM_OC4_SetConfig(htim->Instance, sConfig); + } + break; + + case TIM_CHANNEL_5: + { + /* Check the parameters */ + assert_param(IS_TIM_CC5_INSTANCE(htim->Instance)); + + /* Configure the TIM Channel 5 in Output Compare */ + TIM_OC5_SetConfig(htim->Instance, sConfig); + } + break; + + case TIM_CHANNEL_6: + { + /* Check the parameters */ + assert_param(IS_TIM_CC6_INSTANCE(htim->Instance)); + + /* Configure the TIM Channel 6 in Output Compare */ + TIM_OC6_SetConfig(htim->Instance, sConfig); + } + break; + + default: + break; + } + + htim->State = HAL_TIM_STATE_READY; + + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @brief Initializes the TIM Input Capture Channels according to the specified + * parameters in the TIM_IC_InitTypeDef. + * @param htim TIM IC handle + * @param sConfig TIM Input Capture configuration structure + * @param Channel TIM Channels to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_IC_ConfigChannel(TIM_HandleTypeDef *htim, TIM_IC_InitTypeDef* sConfig, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CC1_INSTANCE(htim->Instance)); + assert_param(IS_TIM_IC_POLARITY(sConfig->ICPolarity)); + assert_param(IS_TIM_IC_SELECTION(sConfig->ICSelection)); + assert_param(IS_TIM_IC_PRESCALER(sConfig->ICPrescaler)); + assert_param(IS_TIM_IC_FILTER(sConfig->ICFilter)); + + /* Process Locked */ + __HAL_LOCK(htim); + + htim->State = HAL_TIM_STATE_BUSY; + + if (Channel == TIM_CHANNEL_1) + { + /* TI1 Configuration */ + TIM_TI1_SetConfig(htim->Instance, + sConfig->ICPolarity, + sConfig->ICSelection, + sConfig->ICFilter); + + /* Reset the IC1PSC Bits */ + htim->Instance->CCMR1 &= ~TIM_CCMR1_IC1PSC; + + /* Set the IC1PSC value */ + htim->Instance->CCMR1 |= sConfig->ICPrescaler; + } + else if (Channel == TIM_CHANNEL_2) + { + /* TI2 Configuration */ + assert_param(IS_TIM_CC2_INSTANCE(htim->Instance)); + + TIM_TI2_SetConfig(htim->Instance, + sConfig->ICPolarity, + sConfig->ICSelection, + sConfig->ICFilter); + + /* Reset the IC2PSC Bits */ + htim->Instance->CCMR1 &= ~TIM_CCMR1_IC2PSC; + + /* Set the IC2PSC value */ + htim->Instance->CCMR1 |= (sConfig->ICPrescaler << 8); + } + else if (Channel == TIM_CHANNEL_3) + { + /* TI3 Configuration */ + assert_param(IS_TIM_CC3_INSTANCE(htim->Instance)); + + TIM_TI3_SetConfig(htim->Instance, + sConfig->ICPolarity, + sConfig->ICSelection, + sConfig->ICFilter); + + /* Reset the IC3PSC Bits */ + htim->Instance->CCMR2 &= ~TIM_CCMR2_IC3PSC; + + /* Set the IC3PSC value */ + htim->Instance->CCMR2 |= sConfig->ICPrescaler; + } + else + { + /* TI4 Configuration */ + assert_param(IS_TIM_CC4_INSTANCE(htim->Instance)); + + TIM_TI4_SetConfig(htim->Instance, + sConfig->ICPolarity, + sConfig->ICSelection, + sConfig->ICFilter); + + /* Reset the IC4PSC Bits */ + htim->Instance->CCMR2 &= ~TIM_CCMR2_IC4PSC; + + /* Set the IC4PSC value */ + htim->Instance->CCMR2 |= (sConfig->ICPrescaler << 8); + } + + htim->State = HAL_TIM_STATE_READY; + + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @brief Initializes the TIM PWM channels according to the specified + * parameters in the TIM_OC_InitTypeDef. + * @param htim TIM PWM handle + * @param sConfig TIM PWM configuration structure + * @param Channel TIM Channels to be configured + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @arg TIM_CHANNEL_5: TIM Channel 5 selected + * @arg TIM_CHANNEL_6: TIM Channel 6 selected + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_PWM_ConfigChannel(TIM_HandleTypeDef *htim, + TIM_OC_InitTypeDef* sConfig, + uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CHANNELS(Channel)); + assert_param(IS_TIM_PWM_MODE(sConfig->OCMode)); + assert_param(IS_TIM_OC_POLARITY(sConfig->OCPolarity)); + assert_param(IS_TIM_FAST_STATE(sConfig->OCFastMode)); + + /* Process Locked */ + __HAL_LOCK(htim); + + htim->State = HAL_TIM_STATE_BUSY; + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Check the parameters */ + assert_param(IS_TIM_CC1_INSTANCE(htim->Instance)); + + /* Configure the Channel 1 in PWM mode */ + TIM_OC1_SetConfig(htim->Instance, sConfig); + + /* Set the Preload enable bit for channel1 */ + htim->Instance->CCMR1 |= TIM_CCMR1_OC1PE; + + /* Configure the Output Fast mode */ + htim->Instance->CCMR1 &= ~TIM_CCMR1_OC1FE; + htim->Instance->CCMR1 |= sConfig->OCFastMode; + } + break; + + case TIM_CHANNEL_2: + { + /* Check the parameters */ + assert_param(IS_TIM_CC2_INSTANCE(htim->Instance)); + + /* Configure the Channel 2 in PWM mode */ + TIM_OC2_SetConfig(htim->Instance, sConfig); + + /* Set the Preload enable bit for channel2 */ + htim->Instance->CCMR1 |= TIM_CCMR1_OC2PE; + + /* Configure the Output Fast mode */ + htim->Instance->CCMR1 &= ~TIM_CCMR1_OC2FE; + htim->Instance->CCMR1 |= sConfig->OCFastMode << 8; + } + break; + + case TIM_CHANNEL_3: + { + /* Check the parameters */ + assert_param(IS_TIM_CC3_INSTANCE(htim->Instance)); + + /* Configure the Channel 3 in PWM mode */ + TIM_OC3_SetConfig(htim->Instance, sConfig); + + /* Set the Preload enable bit for channel3 */ + htim->Instance->CCMR2 |= TIM_CCMR2_OC3PE; + + /* Configure the Output Fast mode */ + htim->Instance->CCMR2 &= ~TIM_CCMR2_OC3FE; + htim->Instance->CCMR2 |= sConfig->OCFastMode; + } + break; + + case TIM_CHANNEL_4: + { + /* Check the parameters */ + assert_param(IS_TIM_CC4_INSTANCE(htim->Instance)); + + /* Configure the Channel 4 in PWM mode */ + TIM_OC4_SetConfig(htim->Instance, sConfig); + + /* Set the Preload enable bit for channel4 */ + htim->Instance->CCMR2 |= TIM_CCMR2_OC4PE; + + /* Configure the Output Fast mode */ + htim->Instance->CCMR2 &= ~TIM_CCMR2_OC4FE; + htim->Instance->CCMR2 |= sConfig->OCFastMode << 8; + } + break; + + case TIM_CHANNEL_5: + { + /* Check the parameters */ + assert_param(IS_TIM_CC5_INSTANCE(htim->Instance)); + + /* Configure the Channel 5 in PWM mode */ + TIM_OC5_SetConfig(htim->Instance, sConfig); + + /* Set the Preload enable bit for channel5*/ + htim->Instance->CCMR3 |= TIM_CCMR3_OC5PE; + + /* Configure the Output Fast mode */ + htim->Instance->CCMR3 &= ~TIM_CCMR3_OC5FE; + htim->Instance->CCMR3 |= sConfig->OCFastMode; + } + break; + + case TIM_CHANNEL_6: + { + /* Check the parameters */ + assert_param(IS_TIM_CC6_INSTANCE(htim->Instance)); + + /* Configure the Channel 5 in PWM mode */ + TIM_OC6_SetConfig(htim->Instance, sConfig); + + /* Set the Preload enable bit for channel6 */ + htim->Instance->CCMR3 |= TIM_CCMR3_OC6PE; + + /* Configure the Output Fast mode */ + htim->Instance->CCMR3 &= ~TIM_CCMR3_OC6FE; + htim->Instance->CCMR3 |= sConfig->OCFastMode << 8; + } + break; + + default: + break; + } + + htim->State = HAL_TIM_STATE_READY; + + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @brief Initializes the TIM One Pulse Channels according to the specified + * parameters in the TIM_OnePulse_InitTypeDef. + * @param htim TIM One Pulse handle + * @param sConfig TIM One Pulse configuration structure + * @param OutputChannel TIM Channels to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @param InputChannel TIM Channels to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_OnePulse_ConfigChannel(TIM_HandleTypeDef *htim, TIM_OnePulse_InitTypeDef* sConfig, uint32_t OutputChannel, uint32_t InputChannel) +{ + TIM_OC_InitTypeDef temp1; + + /* Check the parameters */ + assert_param(IS_TIM_OPM_CHANNELS(OutputChannel)); + assert_param(IS_TIM_OPM_CHANNELS(InputChannel)); + + if(OutputChannel != InputChannel) + { + /* Process Locked */ + __HAL_LOCK(htim); + + htim->State = HAL_TIM_STATE_BUSY; + + /* Extract the Ouput compare configuration from sConfig structure */ + temp1.OCMode = sConfig->OCMode; + temp1.Pulse = sConfig->Pulse; + temp1.OCPolarity = sConfig->OCPolarity; + temp1.OCNPolarity = sConfig->OCNPolarity; + temp1.OCIdleState = sConfig->OCIdleState; + temp1.OCNIdleState = sConfig->OCNIdleState; + + switch (OutputChannel) + { + case TIM_CHANNEL_1: + { + assert_param(IS_TIM_CC1_INSTANCE(htim->Instance)); + + TIM_OC1_SetConfig(htim->Instance, &temp1); + } + break; + case TIM_CHANNEL_2: + { + assert_param(IS_TIM_CC2_INSTANCE(htim->Instance)); + + TIM_OC2_SetConfig(htim->Instance, &temp1); + } + break; + default: + break; + } + + switch (InputChannel) + { + case TIM_CHANNEL_1: + { + assert_param(IS_TIM_CC1_INSTANCE(htim->Instance)); + + TIM_TI1_SetConfig(htim->Instance, sConfig->ICPolarity, + sConfig->ICSelection, sConfig->ICFilter); + + /* Reset the IC1PSC Bits */ + htim->Instance->CCMR1 &= ~TIM_CCMR1_IC1PSC; + + /* Select the Trigger source */ + htim->Instance->SMCR &= ~TIM_SMCR_TS; + htim->Instance->SMCR |= TIM_TS_TI1FP1; + + /* Select the Slave Mode */ + htim->Instance->SMCR &= ~TIM_SMCR_SMS; + htim->Instance->SMCR |= TIM_SLAVEMODE_TRIGGER; + } + break; + case TIM_CHANNEL_2: + { + assert_param(IS_TIM_CC2_INSTANCE(htim->Instance)); + + TIM_TI2_SetConfig(htim->Instance, sConfig->ICPolarity, + sConfig->ICSelection, sConfig->ICFilter); + + /* Reset the IC2PSC Bits */ + htim->Instance->CCMR1 &= ~TIM_CCMR1_IC2PSC; + + /* Select the Trigger source */ + htim->Instance->SMCR &= ~TIM_SMCR_TS; + htim->Instance->SMCR |= TIM_TS_TI2FP2; + + /* Select the Slave Mode */ + htim->Instance->SMCR &= ~TIM_SMCR_SMS; + htim->Instance->SMCR |= TIM_SLAVEMODE_TRIGGER; + } + break; + + default: + break; + } + + htim->State = HAL_TIM_STATE_READY; + + __HAL_UNLOCK(htim); + + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Configure the DMA Burst to transfer Data from the memory to the TIM peripheral + * @param htim TIM handle + * @param BurstBaseAddress TIM Base address from when the DMA will starts the Data write + * This parameters can be on of the following values: + * @arg TIM_DMABASE_CR1 + * @arg TIM_DMABASE_CR2 + * @arg TIM_DMABASE_SMCR + * @arg TIM_DMABASE_DIER + * @arg TIM_DMABASE_SR + * @arg TIM_DMABASE_EGR + * @arg TIM_DMABASE_CCMR1 + * @arg TIM_DMABASE_CCMR2 + * @arg TIM_DMABASE_CCER + * @arg TIM_DMABASE_CNT + * @arg TIM_DMABASE_PSC + * @arg TIM_DMABASE_ARR + * @arg TIM_DMABASE_RCR + * @arg TIM_DMABASE_CCR1 + * @arg TIM_DMABASE_CCR2 + * @arg TIM_DMABASE_CCR3 + * @arg TIM_DMABASE_CCR4 + * @arg TIM_DMABASE_BDTR + * @arg TIM_DMABASE_DCR + * @param BurstRequestSrc TIM DMA Request sources + * This parameters can be on of the following values: + * @arg TIM_DMA_UPDATE: TIM update Interrupt source + * @arg TIM_DMA_CC1: TIM Capture Compare 1 DMA source + * @arg TIM_DMA_CC2: TIM Capture Compare 2 DMA source + * @arg TIM_DMA_CC3: TIM Capture Compare 3 DMA source + * @arg TIM_DMA_CC4: TIM Capture Compare 4 DMA source + * @arg TIM_DMA_COM: TIM Commutation DMA source + * @arg TIM_DMA_TRIGGER: TIM Trigger DMA source + * @param BurstBuffer The Buffer address. + * @param BurstLength DMA Burst length. This parameter can be one value + * between: TIM_DMABurstLength_1Transfer and TIM_DMABurstLength_18Transfers. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_DMABurst_WriteStart(TIM_HandleTypeDef *htim, uint32_t BurstBaseAddress, uint32_t BurstRequestSrc, + uint32_t* BurstBuffer, uint32_t BurstLength) +{ + /* Check the parameters */ + assert_param(IS_TIM_DMABURST_INSTANCE(htim->Instance)); + assert_param(IS_TIM_DMA_BASE(BurstBaseAddress)); + assert_param(IS_TIM_DMA_SOURCE(BurstRequestSrc)); + assert_param(IS_TIM_DMA_LENGTH(BurstLength)); + + if((htim->State == HAL_TIM_STATE_BUSY)) + { + return HAL_BUSY; + } + else if((htim->State == HAL_TIM_STATE_READY)) + { + if((BurstBuffer == 0 ) && (BurstLength > 0)) + { + return HAL_ERROR; + } + else + { + htim->State = HAL_TIM_STATE_BUSY; + } + } + switch(BurstRequestSrc) + { + case TIM_DMA_UPDATE: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_UPDATE]->XferCpltCallback = TIM_DMAPeriodElapsedCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_UPDATE]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_UPDATE], (uint32_t)BurstBuffer, (uint32_t)&htim->Instance->DMAR, ((BurstLength) >> 8) + 1); + } + break; + case TIM_DMA_CC1: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)BurstBuffer, (uint32_t)&htim->Instance->DMAR, ((BurstLength) >> 8) + 1); + } + break; + case TIM_DMA_CC2: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)BurstBuffer, (uint32_t)&htim->Instance->DMAR, ((BurstLength) >> 8) + 1); + } + break; + case TIM_DMA_CC3: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)BurstBuffer, (uint32_t)&htim->Instance->DMAR, ((BurstLength) >> 8) + 1); + } + break; + case TIM_DMA_CC4: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC4]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC4], (uint32_t)BurstBuffer, (uint32_t)&htim->Instance->DMAR, ((BurstLength) >> 8) + 1); + } + break; + case TIM_DMA_COM: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_COMMUTATION]->XferCpltCallback = TIMEx_DMACommutationCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_COMMUTATION]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_COMMUTATION], (uint32_t)BurstBuffer, (uint32_t)&htim->Instance->DMAR, ((BurstLength) >> 8) + 1); + } + break; + case TIM_DMA_TRIGGER: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_TRIGGER]->XferCpltCallback = TIM_DMATriggerCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_TRIGGER]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_TRIGGER], (uint32_t)BurstBuffer, (uint32_t)&htim->Instance->DMAR, ((BurstLength) >> 8) + 1); + } + break; + default: + break; + } + /* configure the DMA Burst Mode */ + htim->Instance->DCR = BurstBaseAddress | BurstLength; + + /* Enable the TIM DMA Request */ + __HAL_TIM_ENABLE_DMA(htim, BurstRequestSrc); + + htim->State = HAL_TIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM DMA Burst mode + * @param htim TIM handle + * @param BurstRequestSrc TIM DMA Request sources to disable + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_DMABurst_WriteStop(TIM_HandleTypeDef *htim, uint32_t BurstRequestSrc) +{ + /* Check the parameters */ + assert_param(IS_TIM_DMA_SOURCE(BurstRequestSrc)); + + /* Abort the DMA transfer (at least disable the DMA channel) */ + switch(BurstRequestSrc) + { + case TIM_DMA_UPDATE: + { + HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_UPDATE]); + } + break; + case TIM_DMA_CC1: + { + HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_CC1]); + } + break; + case TIM_DMA_CC2: + { + HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_CC2]); + } + break; + case TIM_DMA_CC3: + { + HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_CC3]); + } + break; + case TIM_DMA_CC4: + { + HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_CC4]); + } + break; + case TIM_DMA_COM: + { + HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_COMMUTATION]); + } + break; + case TIM_DMA_TRIGGER: + { + HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_TRIGGER]); + } + break; + default: + break; + } + + /* Disable the TIM Update DMA request */ + __HAL_TIM_DISABLE_DMA(htim, BurstRequestSrc); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Configure the DMA Burst to transfer Data from the TIM peripheral to the memory + * @param htim TIM handle + * @param BurstBaseAddress TIM Base address from when the DMA will starts the Data read + * This parameters can be on of the following values: + * @arg TIM_DMABASE_CR1 + * @arg TIM_DMABASE_CR2 + * @arg TIM_DMABASE_SMCR + * @arg TIM_DMABASE_DIER + * @arg TIM_DMABASE_SR + * @arg TIM_DMABASE_EGR + * @arg TIM_DMABASE_CCMR1 + * @arg TIM_DMABASE_CCMR2 + * @arg TIM_DMABASE_CCER + * @arg TIM_DMABASE_CNT + * @arg TIM_DMABASE_PSC + * @arg TIM_DMABASE_ARR + * @arg TIM_DMABASE_RCR + * @arg TIM_DMABASE_CCR1 + * @arg TIM_DMABASE_CCR2 + * @arg TIM_DMABASE_CCR3 + * @arg TIM_DMABASE_CCR4 + * @arg TIM_DMABASE_BDTR + * @arg TIM_DMABASE_DCR + * @param BurstRequestSrc TIM DMA Request sources + * This parameters can be on of the following values: + * @arg TIM_DMA_UPDATE: TIM update Interrupt source + * @arg TIM_DMA_CC1: TIM Capture Compare 1 DMA source + * @arg TIM_DMA_CC2: TIM Capture Compare 2 DMA source + * @arg TIM_DMA_CC3: TIM Capture Compare 3 DMA source + * @arg TIM_DMA_CC4: TIM Capture Compare 4 DMA source + * @arg TIM_DMA_COM: TIM Commutation DMA source + * @arg TIM_DMA_TRIGGER: TIM Trigger DMA source + * @param BurstBuffer The Buffer address. + * @param BurstLength DMA Burst length. This parameter can be one value + * between: TIM_DMABurstLength_1Transfer and TIM_DMABurstLength_18Transfers. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_DMABurst_ReadStart(TIM_HandleTypeDef *htim, uint32_t BurstBaseAddress, uint32_t BurstRequestSrc, + uint32_t *BurstBuffer, uint32_t BurstLength) +{ + /* Check the parameters */ + assert_param(IS_TIM_DMABURST_INSTANCE(htim->Instance)); + assert_param(IS_TIM_DMA_BASE(BurstBaseAddress)); + assert_param(IS_TIM_DMA_SOURCE(BurstRequestSrc)); + assert_param(IS_TIM_DMA_LENGTH(BurstLength)); + + if((htim->State == HAL_TIM_STATE_BUSY)) + { + return HAL_BUSY; + } + else if((htim->State == HAL_TIM_STATE_READY)) + { + if((BurstBuffer == 0 ) && (BurstLength > 0)) + { + return HAL_ERROR; + } + else + { + htim->State = HAL_TIM_STATE_BUSY; + } + } + switch(BurstRequestSrc) + { + case TIM_DMA_UPDATE: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_UPDATE]->XferCpltCallback = TIM_DMAPeriodElapsedCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_UPDATE]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_UPDATE], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer, ((BurstLength) >> 8) + 1); + } + break; + case TIM_DMA_CC1: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMACaptureCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer, ((BurstLength) >> 8) + 1); + } + break; + case TIM_DMA_CC2: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMACaptureCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer, ((BurstLength) >> 8) + 1); + } + break; + case TIM_DMA_CC3: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMACaptureCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer, ((BurstLength) >> 8) + 1); + } + break; + case TIM_DMA_CC4: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC4]->XferCpltCallback = TIM_DMACaptureCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC4], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer, ((BurstLength) >> 8) + 1); + } + break; + case TIM_DMA_COM: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_COMMUTATION]->XferCpltCallback = TIMEx_DMACommutationCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_COMMUTATION]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_COMMUTATION], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer, ((BurstLength) >> 8) + 1); + } + break; + case TIM_DMA_TRIGGER: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_TRIGGER]->XferCpltCallback = TIM_DMATriggerCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_TRIGGER]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_TRIGGER], (uint32_t)&htim->Instance->DMAR, (uint32_t)BurstBuffer, ((BurstLength) >> 8) + 1); + } + break; + default: + break; + } + + /* configure the DMA Burst Mode */ + htim->Instance->DCR = BurstBaseAddress | BurstLength; + + /* Enable the TIM DMA Request */ + __HAL_TIM_ENABLE_DMA(htim, BurstRequestSrc); + + htim->State = HAL_TIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stop the DMA burst reading + * @param htim TIM handle + * @param BurstRequestSrc TIM DMA Request sources to disable. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_DMABurst_ReadStop(TIM_HandleTypeDef *htim, uint32_t BurstRequestSrc) +{ + /* Check the parameters */ + assert_param(IS_TIM_DMA_SOURCE(BurstRequestSrc)); + + /* Abort the DMA transfer (at least disable the DMA channel) */ + switch(BurstRequestSrc) + { + case TIM_DMA_UPDATE: + { + HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_UPDATE]); + } + break; + case TIM_DMA_CC1: + { + HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_CC1]); + } + break; + case TIM_DMA_CC2: + { + HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_CC2]); + } + break; + case TIM_DMA_CC3: + { + HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_CC3]); + } + break; + case TIM_DMA_CC4: + { + HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_CC4]); + } + break; + case TIM_DMA_COM: + { + HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_COMMUTATION]); + } + break; + case TIM_DMA_TRIGGER: + { + HAL_DMA_Abort(htim->hdma[TIM_DMA_ID_TRIGGER]); + } + break; + default: + break; + } + + /* Disable the TIM Update DMA request */ + __HAL_TIM_DISABLE_DMA(htim, BurstRequestSrc); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Generate a software event + * @param htim TIM handle + * @param EventSource specifies the event source. + * This parameter can be one of the following values: + * @arg TIM_EVENTSOURCE_UPDATE: Timer update Event source + * @arg TIM_EVENTSOURCE_CC1: Timer Capture Compare 1 Event source + * @arg TIM_EVENTSOURCE_CC2: Timer Capture Compare 2 Event source + * @arg TIM_EVENTSOURCE_CC3: Timer Capture Compare 3 Event source + * @arg TIM_EVENTSOURCE_CC4: Timer Capture Compare 4 Event source + * @arg TIM_EVENTSOURCE_COM: Timer COM event source + * @arg TIM_EVENTSOURCE_TRIGGER: Timer Trigger Event source + * @arg TIM_EVENTSOURCE_BREAK: Timer Break event source + * @arg TIM_EVENTSOURCE_BREAK2: Timer Break2 event source + * @retval HAL status + */ + +HAL_StatusTypeDef HAL_TIM_GenerateEvent(TIM_HandleTypeDef *htim, uint32_t EventSource) +{ + /* Check the parameters */ + assert_param(IS_TIM_INSTANCE(htim->Instance)); + assert_param(IS_TIM_EVENT_SOURCE(EventSource)); + + /* Process Locked */ + __HAL_LOCK(htim); + + /* Change the TIM state */ + htim->State = HAL_TIM_STATE_BUSY; + + /* Set the event sources */ + htim->Instance->EGR = EventSource; + + /* Change the TIM state */ + htim->State = HAL_TIM_STATE_READY; + + __HAL_UNLOCK(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Configures the OCRef clear feature + * @param htim TIM handle + * @param sClearInputConfig pointer to a TIM_ClearInputConfigTypeDef structure that + * contains the OCREF clear feature and parameters for the TIM peripheral. + * @param Channel specifies the TIM Channel + * This parameter can be one of the following values: + * @arg TIM_Channel_1: TIM Channel 1 + * @arg TIM_Channel_2: TIM Channel 2 + * @arg TIM_Channel_3: TIM Channel 3 + * @arg TIM_Channel_4: TIM Channel 4 + * @arg TIM_Channel_5: TIM Channel 5 + * @arg TIM_Channel_6: TIM Channel 6 + * @retval None + */ +HAL_StatusTypeDef HAL_TIM_ConfigOCrefClear(TIM_HandleTypeDef *htim, + TIM_ClearInputConfigTypeDef *sClearInputConfig, + uint32_t Channel) +{ + uint32_t tmpsmcr = 0; + + /* Check the parameters */ + assert_param(IS_TIM_OCXREF_CLEAR_INSTANCE(htim->Instance)); + assert_param(IS_TIM_CLEARINPUT_SOURCE(sClearInputConfig->ClearInputSource)); + + /* Process Locked */ + __HAL_LOCK(htim); + + switch (sClearInputConfig->ClearInputSource) + { + case TIM_CLEARINPUTSOURCE_NONE: + { + /* Get the TIMx SMCR register value */ + tmpsmcr = htim->Instance->SMCR; + + /* Clear the OCREF clear selection bit */ + tmpsmcr &= ~TIM_SMCR_OCCS; + + /* Clear the ETR Bits */ + tmpsmcr &= ~(TIM_SMCR_ETF | TIM_SMCR_ETPS | TIM_SMCR_ECE | TIM_SMCR_ETP); + + /* Set TIMx_SMCR */ + htim->Instance->SMCR = tmpsmcr; + } + break; + + case TIM_CLEARINPUTSOURCE_OCREFCLR: + { + /* Clear the OCREF clear selection bit */ + htim->Instance->SMCR &= ~TIM_SMCR_OCCS; + } + break; + + case TIM_CLEARINPUTSOURCE_ETR: + { + /* Check the parameters */ + assert_param(IS_TIM_CLEARINPUT_POLARITY(sClearInputConfig->ClearInputPolarity)); + assert_param(IS_TIM_CLEARINPUT_PRESCALER(sClearInputConfig->ClearInputPrescaler)); + assert_param(IS_TIM_CLEARINPUT_FILTER(sClearInputConfig->ClearInputFilter)); + + TIM_ETR_SetConfig(htim->Instance, + sClearInputConfig->ClearInputPrescaler, + sClearInputConfig->ClearInputPolarity, + sClearInputConfig->ClearInputFilter); + + /* Set the OCREF clear selection bit */ + htim->Instance->SMCR |= TIM_SMCR_OCCS; + } + break; + + default: + break; + } + + switch (Channel) + { + case TIM_CHANNEL_1: + { + if(sClearInputConfig->ClearInputState != RESET) + { + /* Enable the OCREF clear feature for Channel 1 */ + htim->Instance->CCMR1 |= TIM_CCMR1_OC1CE; + } + else + { + /* Disable the OCREF clear feature for Channel 1 */ + htim->Instance->CCMR1 &= ~TIM_CCMR1_OC1CE; + } + } + break; + case TIM_CHANNEL_2: + { + if(sClearInputConfig->ClearInputState != RESET) + { + /* Enable the OCREF clear feature for Channel 2 */ + htim->Instance->CCMR1 |= TIM_CCMR1_OC2CE; + } + else + { + /* Disable the OCREF clear feature for Channel 2 */ + htim->Instance->CCMR1 &= ~TIM_CCMR1_OC2CE; + } + } + break; + case TIM_CHANNEL_3: + { + if(sClearInputConfig->ClearInputState != RESET) + { + /* Enable the OCREF clear feature for Channel 3 */ + htim->Instance->CCMR2 |= TIM_CCMR2_OC3CE; + } + else + { + /* Disable the OCREF clear feature for Channel 3 */ + htim->Instance->CCMR2 &= ~TIM_CCMR2_OC3CE; + } + } + break; + case TIM_CHANNEL_4: + { + if(sClearInputConfig->ClearInputState != RESET) + { + /* Enable the OCREF clear feature for Channel 4 */ + htim->Instance->CCMR2 |= TIM_CCMR2_OC4CE; + } + else + { + /* Disable the OCREF clear feature for Channel 4 */ + htim->Instance->CCMR2 &= ~TIM_CCMR2_OC4CE; + } + } + break; + case TIM_CHANNEL_5: + { + if(sClearInputConfig->ClearInputState != RESET) + { + /* Enable the OCREF clear feature for Channel 1 */ + htim->Instance->CCMR3 |= TIM_CCMR3_OC5CE; + } + else + { + /* Disable the OCREF clear feature for Channel 1 */ + htim->Instance->CCMR3 &= ~TIM_CCMR3_OC5CE; + } + } + break; + case TIM_CHANNEL_6: + { + if(sClearInputConfig->ClearInputState != RESET) + { + /* Enable the OCREF clear feature for Channel 1 */ + htim->Instance->CCMR3 |= TIM_CCMR3_OC6CE; + } + else + { + /* Disable the OCREF clear feature for Channel 1 */ + htim->Instance->CCMR3 &= ~TIM_CCMR3_OC6CE; + } + } + break; + default: + break; + } + + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @brief Configures the clock source to be used + * @param htim TIM handle + * @param sClockSourceConfig pointer to a TIM_ClockConfigTypeDef structure that + * contains the clock source information for the TIM peripheral. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_ConfigClockSource(TIM_HandleTypeDef *htim, TIM_ClockConfigTypeDef * sClockSourceConfig) +{ + uint32_t tmpsmcr = 0; + + /* Process Locked */ + __HAL_LOCK(htim); + + htim->State = HAL_TIM_STATE_BUSY; + + /* Check the parameters */ + assert_param(IS_TIM_CLOCKSOURCE(sClockSourceConfig->ClockSource)); + + /* Reset the SMS, TS, ECE, ETPS and ETRF bits */ + tmpsmcr = htim->Instance->SMCR; + tmpsmcr &= ~(TIM_SMCR_SMS | TIM_SMCR_TS); + tmpsmcr &= ~(TIM_SMCR_ETF | TIM_SMCR_ETPS | TIM_SMCR_ECE | TIM_SMCR_ETP); + htim->Instance->SMCR = tmpsmcr; + + switch (sClockSourceConfig->ClockSource) + { + case TIM_CLOCKSOURCE_INTERNAL: + { + assert_param(IS_TIM_INSTANCE(htim->Instance)); + /* Disable slave mode to clock the prescaler directly with the internal clock */ + htim->Instance->SMCR &= ~TIM_SMCR_SMS; + } + break; + + case TIM_CLOCKSOURCE_ETRMODE1: + { + /* Check whether or not the timer instance supports external trigger input mode 1 (ETRF)*/ + assert_param(IS_TIM_CLOCKSOURCE_ETRMODE1_INSTANCE(htim->Instance)); + + /* Check ETR input conditioning related parameters */ + assert_param(IS_TIM_CLOCKPRESCALER(sClockSourceConfig->ClockPrescaler)); + assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity)); + assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter)); + + /* Configure the ETR Clock source */ + TIM_ETR_SetConfig(htim->Instance, + sClockSourceConfig->ClockPrescaler, + sClockSourceConfig->ClockPolarity, + sClockSourceConfig->ClockFilter); + /* Get the TIMx SMCR register value */ + tmpsmcr = htim->Instance->SMCR; + /* Reset the SMS and TS Bits */ + tmpsmcr &= ~(TIM_SMCR_SMS | TIM_SMCR_TS); + /* Select the External clock mode1 and the ETRF trigger */ + tmpsmcr |= (TIM_SLAVEMODE_EXTERNAL1 | TIM_CLOCKSOURCE_ETRMODE1); + /* Write to TIMx SMCR */ + htim->Instance->SMCR = tmpsmcr; + } + break; + + case TIM_CLOCKSOURCE_ETRMODE2: + { + /* Check whether or not the timer instance supports external trigger input mode 2 (ETRF)*/ + assert_param(IS_TIM_CLOCKSOURCE_ETRMODE2_INSTANCE(htim->Instance)); + + /* Check ETR input conditioning related parameters */ + assert_param(IS_TIM_CLOCKPRESCALER(sClockSourceConfig->ClockPrescaler)); + assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity)); + assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter)); + + /* Configure the ETR Clock source */ + TIM_ETR_SetConfig(htim->Instance, + sClockSourceConfig->ClockPrescaler, + sClockSourceConfig->ClockPolarity, + sClockSourceConfig->ClockFilter); + /* Enable the External clock mode2 */ + htim->Instance->SMCR |= TIM_SMCR_ECE; + } + break; + + case TIM_CLOCKSOURCE_TI1: + { + /* Check whether or not the timer instance supports external clock mode 1 */ + assert_param(IS_TIM_CLOCKSOURCE_TIX_INSTANCE(htim->Instance)); + + /* Check TI1 input conditioning related parameters */ + assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity)); + assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter)); + + TIM_TI1_ConfigInputStage(htim->Instance, + sClockSourceConfig->ClockPolarity, + sClockSourceConfig->ClockFilter); + TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_TI1); + } + break; + + case TIM_CLOCKSOURCE_TI2: + { + /* Check whether or not the timer instance supports external clock mode 1 (ETRF)*/ + assert_param(IS_TIM_CLOCKSOURCE_TIX_INSTANCE(htim->Instance)); + + /* Check TI2 input conditioning related parameters */ + assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity)); + assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter)); + + TIM_TI2_ConfigInputStage(htim->Instance, + sClockSourceConfig->ClockPolarity, + sClockSourceConfig->ClockFilter); + TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_TI2); + } + break; + + case TIM_CLOCKSOURCE_TI1ED: + { + /* Check whether or not the timer instance supports external clock mode 1 */ + assert_param(IS_TIM_CLOCKSOURCE_TIX_INSTANCE(htim->Instance)); + + /* Check TI1 input conditioning related parameters */ + assert_param(IS_TIM_CLOCKPOLARITY(sClockSourceConfig->ClockPolarity)); + assert_param(IS_TIM_CLOCKFILTER(sClockSourceConfig->ClockFilter)); + + TIM_TI1_ConfigInputStage(htim->Instance, + sClockSourceConfig->ClockPolarity, + sClockSourceConfig->ClockFilter); + TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_TI1ED); + } + break; + + case TIM_CLOCKSOURCE_ITR0: + { + /* Check whether or not the timer instance supports internal trigger input */ + assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance)); + + TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_ITR0); + } + break; + + case TIM_CLOCKSOURCE_ITR1: + { + /* Check whether or not the timer instance supports internal trigger input */ + assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance)); + + TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_ITR1); + } + break; + + case TIM_CLOCKSOURCE_ITR2: + { + /* Check whether or not the timer instance supports internal trigger input */ + assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance)); + + TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_ITR2); + } + break; + + case TIM_CLOCKSOURCE_ITR3: + { + /* Check whether or not the timer instance supports internal trigger input */ + assert_param(IS_TIM_CLOCKSOURCE_ITRX_INSTANCE(htim->Instance)); + + TIM_ITRx_SetConfig(htim->Instance, TIM_CLOCKSOURCE_ITR3); + } + break; + + default: + break; + } + htim->State = HAL_TIM_STATE_READY; + + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @brief Selects the signal connected to the TI1 input: direct from CH1_input + * or a XOR combination between CH1_input, CH2_input & CH3_input + * @param htim TIM handle. + * @param TI1_Selection Indicate whether or not channel 1 is connected to the + * output of a XOR gate. + * This parameter can be one of the following values: + * @arg TIM_TI1SELECTION_CH1: The TIMx_CH1 pin is connected to TI1 input + * @arg TIM_TI1SELECTION_XORCOMBINATION: The TIMx_CH1, CH2 and CH3 + * pins are connected to the TI1 input (XOR combination) + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_ConfigTI1Input(TIM_HandleTypeDef *htim, uint32_t TI1_Selection) +{ + uint32_t tmpcr2 = 0; + + /* Check the parameters */ + assert_param(IS_TIM_XOR_INSTANCE(htim->Instance)); + assert_param(IS_TIM_TI1SELECTION(TI1_Selection)); + + /* Get the TIMx CR2 register value */ + tmpcr2 = htim->Instance->CR2; + + /* Reset the TI1 selection */ + tmpcr2 &= ~TIM_CR2_TI1S; + + /* Set the TI1 selection */ + tmpcr2 |= TI1_Selection; + + /* Write to TIMxCR2 */ + htim->Instance->CR2 = tmpcr2; + + return HAL_OK; +} + +/** + * @brief Configures the TIM in Slave mode + * @param htim TIM handle. + * @param sSlaveConfig pointer to a TIM_SlaveConfigTypeDef structure that + * contains the selected trigger (internal trigger input, filtered + * timer input or external trigger input) and the ) and the Slave + * mode (Disable, Reset, Gated, Trigger, External clock mode 1). + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_SlaveConfigSynchronization(TIM_HandleTypeDef *htim, TIM_SlaveConfigTypeDef * sSlaveConfig) +{ + /* Check the parameters */ + assert_param(IS_TIM_SLAVE_INSTANCE(htim->Instance)); + assert_param(IS_TIM_SLAVE_MODE(sSlaveConfig->SlaveMode)); + assert_param(IS_TIM_TRIGGER_SELECTION(sSlaveConfig->InputTrigger)); + + __HAL_LOCK(htim); + + htim->State = HAL_TIM_STATE_BUSY; + + TIM_SlaveTimer_SetConfig(htim, sSlaveConfig); + + /* Disable Trigger Interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_TRIGGER); + + /* Disable Trigger DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_TRIGGER); + + htim->State = HAL_TIM_STATE_READY; + + __HAL_UNLOCK(htim); + + return HAL_OK; + } + +/** + * @brief Configures the TIM in Slave mode in interrupt mode + * @param htim TIM handle. + * @param sSlaveConfig pointer to a TIM_SlaveConfigTypeDef structure that + * contains the selected trigger (internal trigger input, filtered + * timer input or external trigger input) and the ) and the Slave + * mode (Disable, Reset, Gated, Trigger, External clock mode 1). + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIM_SlaveConfigSynchronization_IT(TIM_HandleTypeDef *htim, + TIM_SlaveConfigTypeDef * sSlaveConfig) + { + /* Check the parameters */ + assert_param(IS_TIM_SLAVE_INSTANCE(htim->Instance)); + assert_param(IS_TIM_SLAVE_MODE(sSlaveConfig->SlaveMode)); + assert_param(IS_TIM_TRIGGER_SELECTION(sSlaveConfig->InputTrigger)); + + __HAL_LOCK(htim); + + htim->State = HAL_TIM_STATE_BUSY; + + TIM_SlaveTimer_SetConfig(htim, sSlaveConfig); + + /* Enable Trigger Interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_TRIGGER); + + /* Disable Trigger DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_TRIGGER); + + htim->State = HAL_TIM_STATE_READY; + + __HAL_UNLOCK(htim); + + return HAL_OK; + } + +/** + * @brief Read the captured value from Capture Compare unit + * @param htim TIM handle. + * @param Channel TIM Channels to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @arg TIM_CHANNEL_4: TIM Channel 4 selected + * @retval Captured value + */ +uint32_t HAL_TIM_ReadCapturedValue(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + uint32_t tmpreg = 0; + + __HAL_LOCK(htim); + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Check the parameters */ + assert_param(IS_TIM_CC1_INSTANCE(htim->Instance)); + + /* Return the capture 1 value */ + tmpreg = htim->Instance->CCR1; + + break; + } + case TIM_CHANNEL_2: + { + /* Check the parameters */ + assert_param(IS_TIM_CC2_INSTANCE(htim->Instance)); + + /* Return the capture 2 value */ + tmpreg = htim->Instance->CCR2; + + break; + } + + case TIM_CHANNEL_3: + { + /* Check the parameters */ + assert_param(IS_TIM_CC3_INSTANCE(htim->Instance)); + + /* Return the capture 3 value */ + tmpreg = htim->Instance->CCR3; + + break; + } + + case TIM_CHANNEL_4: + { + /* Check the parameters */ + assert_param(IS_TIM_CC4_INSTANCE(htim->Instance)); + + /* Return the capture 4 value */ + tmpreg = htim->Instance->CCR4; + + break; + } + + default: + break; + } + + __HAL_UNLOCK(htim); + return tmpreg; +} + +/** + * @} + */ + +/** @defgroup TIM_Exported_Functions_Group9 TIM Callbacks functions + * @brief TIM Callbacks functions + * +@verbatim + ============================================================================== + ##### TIM Callbacks functions ##### + ============================================================================== + [..] + This section provides TIM callback functions: + (+) Timer Period elapsed callback + (+) Timer Output Compare callback + (+) Timer Input capture callback + (+) Timer Trigger callback + (+) Timer Error callback + +@endverbatim + * @{ + */ + +/** + * @brief Period elapsed callback in non-blocking mode + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the __HAL_TIM_PeriodElapsedCallback could be implemented in the user file + */ + +} +/** + * @brief Output Compare callback in non-blocking mode + * @param htim TIM OC handle + * @retval None + */ +__weak void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the __HAL_TIM_OC_DelayElapsedCallback could be implemented in the user file + */ +} +/** + * @brief Input Capture callback in non-blocking mode + * @param htim TIM IC handle + * @retval None + */ +__weak void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the __HAL_TIM_IC_CaptureCallback could be implemented in the user file + */ +} + +/** + * @brief PWM Pulse finished callback in non-blocking mode + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the __HAL_TIM_PWM_PulseFinishedCallback could be implemented in the user file + */ +} + +/** + * @brief Hall Trigger detection callback in non-blocking mode + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIM_TriggerCallback(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_TIM_TriggerCallback could be implemented in the user file + */ +} + +/** + * @brief Timer error callback in non-blocking mode + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIM_ErrorCallback(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_TIM_ErrorCallback could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup TIM_Exported_Functions_Group10 Peripheral State functions + * @brief Peripheral State functions + * +@verbatim + ============================================================================== + ##### Peripheral State functions ##### + ============================================================================== + [..] + This subsection permits to get in run-time the status of the peripheral + and the data flow. + +@endverbatim + * @{ + */ + +/** + * @brief Return the TIM Base handle state. + * @param htim TIM Base handle + * @retval HAL state + */ +HAL_TIM_StateTypeDef HAL_TIM_Base_GetState(TIM_HandleTypeDef *htim) +{ + return htim->State; +} + +/** + * @brief Return the TIM OC handle state. + * @param htim TIM Ouput Compare handle + * @retval HAL state + */ +HAL_TIM_StateTypeDef HAL_TIM_OC_GetState(TIM_HandleTypeDef *htim) +{ + return htim->State; +} + +/** + * @brief Return the TIM PWM handle state. + * @param htim TIM handle + * @retval HAL state + */ +HAL_TIM_StateTypeDef HAL_TIM_PWM_GetState(TIM_HandleTypeDef *htim) +{ + return htim->State; +} + +/** + * @brief Return the TIM Input Capture handle state. + * @param htim TIM IC handle + * @retval HAL state + */ +HAL_TIM_StateTypeDef HAL_TIM_IC_GetState(TIM_HandleTypeDef *htim) +{ + return htim->State; +} + +/** + * @brief Return the TIM One Pulse Mode handle state. + * @param htim TIM OPM handle + * @retval HAL state + */ +HAL_TIM_StateTypeDef HAL_TIM_OnePulse_GetState(TIM_HandleTypeDef *htim) +{ + return htim->State; +} + +/** + * @brief Return the TIM Encoder Mode handle state. + * @param htim TIM Encoder handle + * @retval HAL state + */ +HAL_TIM_StateTypeDef HAL_TIM_Encoder_GetState(TIM_HandleTypeDef *htim) +{ + return htim->State; +} + +/** + * @} + */ + +/** + * @brief TIM DMA error callback + * @param hdma pointer to DMA handle. + * @retval None + */ +void TIM_DMAError(DMA_HandleTypeDef *hdma) +{ + TIM_HandleTypeDef* htim = ( TIM_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; + + htim->State= HAL_TIM_STATE_READY; + + HAL_TIM_ErrorCallback(htim); +} + +/** + * @brief TIM DMA Delay Pulse complete callback. + * @param hdma pointer to DMA handle. + * @retval None + */ +void TIM_DMADelayPulseCplt(DMA_HandleTypeDef *hdma) +{ + TIM_HandleTypeDef* htim = ( TIM_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; + + htim->State= HAL_TIM_STATE_READY; + + if (hdma == htim->hdma[TIM_DMA_ID_CC1]) + { + htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1; + } + else if (hdma == htim->hdma[TIM_DMA_ID_CC2]) + { + htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2; + } + else if (hdma == htim->hdma[TIM_DMA_ID_CC3]) + { + htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3; + } + else if (hdma == htim->hdma[TIM_DMA_ID_CC4]) + { + htim->Channel = HAL_TIM_ACTIVE_CHANNEL_4; + } + + HAL_TIM_PWM_PulseFinishedCallback(htim); + + htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED; +} +/** + * @brief TIM DMA Capture complete callback. + * @param hdma pointer to DMA handle. + * @retval None + */ +void TIM_DMACaptureCplt(DMA_HandleTypeDef *hdma) +{ + TIM_HandleTypeDef* htim = ( TIM_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; + + htim->State= HAL_TIM_STATE_READY; + + if (hdma == htim->hdma[TIM_DMA_ID_CC1]) + { + htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1; + } + else if (hdma == htim->hdma[TIM_DMA_ID_CC2]) + { + htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2; + } + else if (hdma == htim->hdma[TIM_DMA_ID_CC3]) + { + htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3; + } + else if (hdma == htim->hdma[TIM_DMA_ID_CC4]) + { + htim->Channel = HAL_TIM_ACTIVE_CHANNEL_4; + } + + HAL_TIM_IC_CaptureCallback(htim); + + htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED; +} + +/** + * @brief TIM DMA Period Elapse complete callback. + * @param hdma pointer to DMA handle. + * @retval None + */ +static void TIM_DMAPeriodElapsedCplt(DMA_HandleTypeDef *hdma) +{ + TIM_HandleTypeDef* htim = ( TIM_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; + + htim->State= HAL_TIM_STATE_READY; + + HAL_TIM_PeriodElapsedCallback(htim); +} + +/** + * @brief TIM DMA Trigger callback. + * @param hdma pointer to DMA handle. + * @retval None + */ +static void TIM_DMATriggerCplt(DMA_HandleTypeDef *hdma) +{ + TIM_HandleTypeDef* htim = ( TIM_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; + + htim->State= HAL_TIM_STATE_READY; + + HAL_TIM_TriggerCallback(htim); +} + +/** + * @brief Time Base configuration + * @param TIMx TIM peripheral + * @param Structure TIM Base configuration structure + * @retval None + */ +void TIM_Base_SetConfig(TIM_TypeDef *TIMx, TIM_Base_InitTypeDef *Structure) +{ + uint32_t tmpcr1 = 0; + tmpcr1 = TIMx->CR1; + + /* Set TIM Time Base Unit parameters ---------------------------------------*/ + if (IS_TIM_COUNTER_MODE_SELECT_INSTANCE(TIMx)) + { + /* Select the Counter Mode */ + tmpcr1 &= ~(TIM_CR1_DIR | TIM_CR1_CMS); + tmpcr1 |= Structure->CounterMode; + } + + if(IS_TIM_CLOCK_DIVISION_INSTANCE(TIMx)) + { + /* Set the clock division */ + tmpcr1 &= ~TIM_CR1_CKD; + tmpcr1 |= (uint32_t)Structure->ClockDivision; + } + + /* Set the auto-reload preload */ + tmpcr1 &= ~TIM_CR1_ARPE; + tmpcr1 |= (uint32_t)Structure->AutoReloadPreload; + + TIMx->CR1 = tmpcr1; + + /* Set the Autoreload value */ + TIMx->ARR = (uint32_t)Structure->Period ; + + /* Set the Prescaler value */ + TIMx->PSC = (uint32_t)Structure->Prescaler; + + if (IS_TIM_REPETITION_COUNTER_INSTANCE(TIMx)) + { + /* Set the Repetition Counter value */ + TIMx->RCR = Structure->RepetitionCounter; + } + + /* Generate an update event to reload the Prescaler + and the repetition counter(only for TIM1 and TIM8) value immediately */ + TIMx->EGR = TIM_EGR_UG; +} + +/** + * @brief Time Ouput Compare 1 configuration + * @param TIMx to select the TIM peripheral + * @param OC_Config The ouput configuration structure + * @retval None + */ +static void TIM_OC1_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config) +{ + uint32_t tmpccmrx = 0; + uint32_t tmpccer = 0; + uint32_t tmpcr2 = 0; + + /* Disable the Channel 1: Reset the CC1E Bit */ + TIMx->CCER &= ~TIM_CCER_CC1E; + + /* Get the TIMx CCER register value */ + tmpccer = TIMx->CCER; + /* Get the TIMx CR2 register value */ + tmpcr2 = TIMx->CR2; + + /* Get the TIMx CCMR1 register value */ + tmpccmrx = TIMx->CCMR1; + + /* Reset the Output Compare Mode Bits */ + tmpccmrx &= ~TIM_CCMR1_OC1M; + tmpccmrx &= ~TIM_CCMR1_CC1S; + /* Select the Output Compare Mode */ + tmpccmrx |= OC_Config->OCMode; + + /* Reset the Output Polarity level */ + tmpccer &= ~TIM_CCER_CC1P; + /* Set the Output Compare Polarity */ + tmpccer |= OC_Config->OCPolarity; + + if(IS_TIM_CCXN_INSTANCE(TIMx, TIM_CHANNEL_1)) + { + /* Check parameters */ + assert_param(IS_TIM_OCN_POLARITY(OC_Config->OCNPolarity)); + + /* Reset the Output N Polarity level */ + tmpccer &= ~TIM_CCER_CC1NP; + /* Set the Output N Polarity */ + tmpccer |= OC_Config->OCNPolarity; + /* Reset the Output N State */ + tmpccer &= ~TIM_CCER_CC1NE; + } + + if(IS_TIM_BREAK_INSTANCE(TIMx)) + { + /* Check parameters */ + assert_param(IS_TIM_OCNIDLE_STATE(OC_Config->OCNIdleState)); + assert_param(IS_TIM_OCIDLE_STATE(OC_Config->OCIdleState)); + + /* Reset the Output Compare and Output Compare N IDLE State */ + tmpcr2 &= ~TIM_CR2_OIS1; + tmpcr2 &= ~TIM_CR2_OIS1N; + /* Set the Output Idle state */ + tmpcr2 |= OC_Config->OCIdleState; + /* Set the Output N Idle state */ + tmpcr2 |= OC_Config->OCNIdleState; + } + /* Write to TIMx CR2 */ + TIMx->CR2 = tmpcr2; + + /* Write to TIMx CCMR1 */ + TIMx->CCMR1 = tmpccmrx; + + /* Set the Capture Compare Register value */ + TIMx->CCR1 = OC_Config->Pulse; + + /* Write to TIMx CCER */ + TIMx->CCER = tmpccer; +} + +/** + * @brief Time Ouput Compare 2 configuration + * @param TIMx to select the TIM peripheral + * @param OC_Config The ouput configuration structure + * @retval None + */ +void TIM_OC2_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config) +{ + uint32_t tmpccmrx = 0; + uint32_t tmpccer = 0; + uint32_t tmpcr2 = 0; + + /* Disable the Channel 2: Reset the CC2E Bit */ + TIMx->CCER &= ~TIM_CCER_CC2E; + + /* Get the TIMx CCER register value */ + tmpccer = TIMx->CCER; + /* Get the TIMx CR2 register value */ + tmpcr2 = TIMx->CR2; + + /* Get the TIMx CCMR1 register value */ + tmpccmrx = TIMx->CCMR1; + + /* Reset the Output Compare mode and Capture/Compare selection Bits */ + tmpccmrx &= ~TIM_CCMR1_OC2M; + tmpccmrx &= ~TIM_CCMR1_CC2S; + + /* Select the Output Compare Mode */ + tmpccmrx |= (OC_Config->OCMode << 8); + + /* Reset the Output Polarity level */ + tmpccer &= ~TIM_CCER_CC2P; + /* Set the Output Compare Polarity */ + tmpccer |= (OC_Config->OCPolarity << 4); + + if(IS_TIM_CCXN_INSTANCE(TIMx, TIM_CHANNEL_2)) + { + assert_param(IS_TIM_OCN_POLARITY(OC_Config->OCNPolarity)); + + /* Reset the Output N Polarity level */ + tmpccer &= ~TIM_CCER_CC2NP; + /* Set the Output N Polarity */ + tmpccer |= (OC_Config->OCNPolarity << 4); + /* Reset the Output N State */ + tmpccer &= ~TIM_CCER_CC2NE; + + } + + if(IS_TIM_BREAK_INSTANCE(TIMx)) + { + /* Check parameters */ + assert_param(IS_TIM_OCNIDLE_STATE(OC_Config->OCNIdleState)); + assert_param(IS_TIM_OCIDLE_STATE(OC_Config->OCIdleState)); + + /* Reset the Output Compare and Output Compare N IDLE State */ + tmpcr2 &= ~TIM_CR2_OIS2; + tmpcr2 &= ~TIM_CR2_OIS2N; + /* Set the Output Idle state */ + tmpcr2 |= (OC_Config->OCIdleState << 2); + /* Set the Output N Idle state */ + tmpcr2 |= (OC_Config->OCNIdleState << 2); + } + + /* Write to TIMx CR2 */ + TIMx->CR2 = tmpcr2; + + /* Write to TIMx CCMR1 */ + TIMx->CCMR1 = tmpccmrx; + + /* Set the Capture Compare Register value */ + TIMx->CCR2 = OC_Config->Pulse; + + /* Write to TIMx CCER */ + TIMx->CCER = tmpccer; +} + +/** + * @brief Time Ouput Compare 3 configuration + * @param TIMx to select the TIM peripheral + * @param OC_Config The ouput configuration structure + * @retval None + */ +static void TIM_OC3_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config) +{ + uint32_t tmpccmrx = 0; + uint32_t tmpccer = 0; + uint32_t tmpcr2 = 0; + + /* Disable the Channel 3: Reset the CC2E Bit */ + TIMx->CCER &= ~TIM_CCER_CC3E; + + /* Get the TIMx CCER register value */ + tmpccer = TIMx->CCER; + /* Get the TIMx CR2 register value */ + tmpcr2 = TIMx->CR2; + + /* Get the TIMx CCMR2 register value */ + tmpccmrx = TIMx->CCMR2; + + /* Reset the Output Compare mode and Capture/Compare selection Bits */ + tmpccmrx &= ~TIM_CCMR2_OC3M; + tmpccmrx &= ~TIM_CCMR2_CC3S; + /* Select the Output Compare Mode */ + tmpccmrx |= OC_Config->OCMode; + + /* Reset the Output Polarity level */ + tmpccer &= ~TIM_CCER_CC3P; + /* Set the Output Compare Polarity */ + tmpccer |= (OC_Config->OCPolarity << 8); + + if(IS_TIM_CCXN_INSTANCE(TIMx, TIM_CHANNEL_3)) + { + assert_param(IS_TIM_OCN_POLARITY(OC_Config->OCNPolarity)); + + /* Reset the Output N Polarity level */ + tmpccer &= ~TIM_CCER_CC3NP; + /* Set the Output N Polarity */ + tmpccer |= (OC_Config->OCNPolarity << 8); + /* Reset the Output N State */ + tmpccer &= ~TIM_CCER_CC3NE; + } + + if(IS_TIM_BREAK_INSTANCE(TIMx)) + { + /* Check parameters */ + assert_param(IS_TIM_OCNIDLE_STATE(OC_Config->OCNIdleState)); + assert_param(IS_TIM_OCIDLE_STATE(OC_Config->OCIdleState)); + + /* Reset the Output Compare and Output Compare N IDLE State */ + tmpcr2 &= ~TIM_CR2_OIS3; + tmpcr2 &= ~TIM_CR2_OIS3N; + /* Set the Output Idle state */ + tmpcr2 |= (OC_Config->OCIdleState << 4); + /* Set the Output N Idle state */ + tmpcr2 |= (OC_Config->OCNIdleState << 4); + } + + /* Write to TIMx CR2 */ + TIMx->CR2 = tmpcr2; + + /* Write to TIMx CCMR2 */ + TIMx->CCMR2 = tmpccmrx; + + /* Set the Capture Compare Register value */ + TIMx->CCR3 = OC_Config->Pulse; + + /* Write to TIMx CCER */ + TIMx->CCER = tmpccer; +} + +/** + * @brief Time Ouput Compare 4 configuration + * @param TIMx to select the TIM peripheral + * @param OC_Config The ouput configuration structure + * @retval None + */ +static void TIM_OC4_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config) +{ + uint32_t tmpccmrx = 0; + uint32_t tmpccer = 0; + uint32_t tmpcr2 = 0; + + /* Disable the Channel 4: Reset the CC4E Bit */ + TIMx->CCER &= ~TIM_CCER_CC4E; + + /* Get the TIMx CCER register value */ + tmpccer = TIMx->CCER; + /* Get the TIMx CR2 register value */ + tmpcr2 = TIMx->CR2; + + /* Get the TIMx CCMR2 register value */ + tmpccmrx = TIMx->CCMR2; + + /* Reset the Output Compare mode and Capture/Compare selection Bits */ + tmpccmrx &= ~TIM_CCMR2_OC4M; + tmpccmrx &= ~TIM_CCMR2_CC4S; + + /* Select the Output Compare Mode */ + tmpccmrx |= (OC_Config->OCMode << 8); + + /* Reset the Output Polarity level */ + tmpccer &= ~TIM_CCER_CC4P; + /* Set the Output Compare Polarity */ + tmpccer |= (OC_Config->OCPolarity << 12); + + if(IS_TIM_BREAK_INSTANCE(TIMx)) + { + assert_param(IS_TIM_OCIDLE_STATE(OC_Config->OCIdleState)); + + /* Reset the Output Compare IDLE State */ + tmpcr2 &= ~TIM_CR2_OIS4; + /* Set the Output Idle state */ + tmpcr2 |= (OC_Config->OCIdleState << 6); + } + + /* Write to TIMx CR2 */ + TIMx->CR2 = tmpcr2; + + /* Write to TIMx CCMR2 */ + TIMx->CCMR2 = tmpccmrx; + + /* Set the Capture Compare Register value */ + TIMx->CCR4 = OC_Config->Pulse; + + /* Write to TIMx CCER */ + TIMx->CCER = tmpccer; +} + +/** + * @brief Timer Ouput Compare 5 configuration + * @param TIMx to select the TIM peripheral + * @param OC_Config The ouput configuration structure + * @retval None + */ +static void TIM_OC5_SetConfig(TIM_TypeDef *TIMx, + TIM_OC_InitTypeDef *OC_Config) +{ + uint32_t tmpccmrx = 0; + uint32_t tmpccer = 0; + uint32_t tmpcr2 = 0; + + /* Disable the output: Reset the CCxE Bit */ + TIMx->CCER &= ~TIM_CCER_CC5E; + + /* Get the TIMx CCER register value */ + tmpccer = TIMx->CCER; + /* Get the TIMx CR2 register value */ + tmpcr2 = TIMx->CR2; + /* Get the TIMx CCMR1 register value */ + tmpccmrx = TIMx->CCMR3; + + /* Reset the Output Compare Mode Bits */ + tmpccmrx &= ~(TIM_CCMR3_OC5M); + /* Select the Output Compare Mode */ + tmpccmrx |= OC_Config->OCMode; + + /* Reset the Output Polarity level */ + tmpccer &= ~TIM_CCER_CC5P; + /* Set the Output Compare Polarity */ + tmpccer |= (OC_Config->OCPolarity << 16); + + if(IS_TIM_BREAK_INSTANCE(TIMx)) + { + /* Reset the Output Compare IDLE State */ + tmpcr2 &= ~TIM_CR2_OIS5; + /* Set the Output Idle state */ + tmpcr2 |= (OC_Config->OCIdleState << 8); + } + /* Write to TIMx CR2 */ + TIMx->CR2 = tmpcr2; + + /* Write to TIMx CCMR3 */ + TIMx->CCMR3 = tmpccmrx; + + /* Set the Capture Compare Register value */ + TIMx->CCR5 = OC_Config->Pulse; + + /* Write to TIMx CCER */ + TIMx->CCER = tmpccer; +} + +/** + * @brief Timer Ouput Compare 6 configuration + * @param TIMx to select the TIM peripheral + * @param OC_Config The ouput configuration structure + * @retval None + */ +static void TIM_OC6_SetConfig(TIM_TypeDef *TIMx, + TIM_OC_InitTypeDef *OC_Config) +{ + uint32_t tmpccmrx = 0; + uint32_t tmpccer = 0; + uint32_t tmpcr2 = 0; + + /* Disable the output: Reset the CCxE Bit */ + TIMx->CCER &= ~TIM_CCER_CC6E; + + /* Get the TIMx CCER register value */ + tmpccer = TIMx->CCER; + /* Get the TIMx CR2 register value */ + tmpcr2 = TIMx->CR2; + /* Get the TIMx CCMR1 register value */ + tmpccmrx = TIMx->CCMR3; + + /* Reset the Output Compare Mode Bits */ + tmpccmrx &= ~(TIM_CCMR3_OC6M); + /* Select the Output Compare Mode */ + tmpccmrx |= (OC_Config->OCMode << 8); + + /* Reset the Output Polarity level */ + tmpccer &= (uint32_t)~TIM_CCER_CC6P; + /* Set the Output Compare Polarity */ + tmpccer |= (OC_Config->OCPolarity << 20); + + if(IS_TIM_BREAK_INSTANCE(TIMx)) + { + /* Reset the Output Compare IDLE State */ + tmpcr2 &= ~TIM_CR2_OIS6; + /* Set the Output Idle state */ + tmpcr2 |= (OC_Config->OCIdleState << 10); + } + + /* Write to TIMx CR2 */ + TIMx->CR2 = tmpcr2; + + /* Write to TIMx CCMR3 */ + TIMx->CCMR3 = tmpccmrx; + + /* Set the Capture Compare Register value */ + TIMx->CCR6 = OC_Config->Pulse; + + /* Write to TIMx CCER */ + TIMx->CCER = tmpccer; +} + +static void TIM_SlaveTimer_SetConfig(TIM_HandleTypeDef *htim, + TIM_SlaveConfigTypeDef * sSlaveConfig) +{ + uint32_t tmpsmcr = 0; + uint32_t tmpccmr1 = 0; + uint32_t tmpccer = 0; + + /* Get the TIMx SMCR register value */ + tmpsmcr = htim->Instance->SMCR; + + /* Reset the Trigger Selection Bits */ + tmpsmcr &= ~TIM_SMCR_TS; + /* Set the Input Trigger source */ + tmpsmcr |= sSlaveConfig->InputTrigger; + + /* Reset the slave mode Bits */ + tmpsmcr &= ~TIM_SMCR_SMS; + /* Set the slave mode */ + tmpsmcr |= sSlaveConfig->SlaveMode; + + /* Write to TIMx SMCR */ + htim->Instance->SMCR = tmpsmcr; + + /* Configure the trigger prescaler, filter, and polarity */ + switch (sSlaveConfig->InputTrigger) + { + case TIM_TS_ETRF: + { + /* Check the parameters */ + assert_param(IS_TIM_CLOCKSOURCE_ETRMODE1_INSTANCE(htim->Instance)); + assert_param(IS_TIM_TRIGGERPRESCALER(sSlaveConfig->TriggerPrescaler)); + assert_param(IS_TIM_TRIGGERPOLARITY(sSlaveConfig->TriggerPolarity)); + assert_param(IS_TIM_TRIGGERFILTER(sSlaveConfig->TriggerFilter)); + /* Configure the ETR Trigger source */ + TIM_ETR_SetConfig(htim->Instance, + sSlaveConfig->TriggerPrescaler, + sSlaveConfig->TriggerPolarity, + sSlaveConfig->TriggerFilter); + } + break; + + case TIM_TS_TI1F_ED: + { + /* Check the parameters */ + assert_param(IS_TIM_CC1_INSTANCE(htim->Instance)); + assert_param(IS_TIM_TRIGGERFILTER(sSlaveConfig->TriggerFilter)); + + /* Disable the Channel 1: Reset the CC1E Bit */ + tmpccer = htim->Instance->CCER; + htim->Instance->CCER &= ~TIM_CCER_CC1E; + tmpccmr1 = htim->Instance->CCMR1; + + /* Set the filter */ + tmpccmr1 &= ~TIM_CCMR1_IC1F; + tmpccmr1 |= ((sSlaveConfig->TriggerFilter) << 4); + + /* Write to TIMx CCMR1 and CCER registers */ + htim->Instance->CCMR1 = tmpccmr1; + htim->Instance->CCER = tmpccer; + + } + break; + + case TIM_TS_TI1FP1: + { + /* Check the parameters */ + assert_param(IS_TIM_CC1_INSTANCE(htim->Instance)); + assert_param(IS_TIM_TRIGGERPOLARITY(sSlaveConfig->TriggerPolarity)); + assert_param(IS_TIM_TRIGGERFILTER(sSlaveConfig->TriggerFilter)); + + /* Configure TI1 Filter and Polarity */ + TIM_TI1_ConfigInputStage(htim->Instance, + sSlaveConfig->TriggerPolarity, + sSlaveConfig->TriggerFilter); + } + break; + + case TIM_TS_TI2FP2: + { + /* Check the parameters */ + assert_param(IS_TIM_CC2_INSTANCE(htim->Instance)); + assert_param(IS_TIM_TRIGGERPOLARITY(sSlaveConfig->TriggerPolarity)); + assert_param(IS_TIM_TRIGGERFILTER(sSlaveConfig->TriggerFilter)); + + /* Configure TI2 Filter and Polarity */ + TIM_TI2_ConfigInputStage(htim->Instance, + sSlaveConfig->TriggerPolarity, + sSlaveConfig->TriggerFilter); + } + break; + + case TIM_TS_ITR0: + { + /* Check the parameter */ + assert_param(IS_TIM_CC2_INSTANCE(htim->Instance)); + } + break; + + case TIM_TS_ITR1: + { + /* Check the parameter */ + assert_param(IS_TIM_CC2_INSTANCE(htim->Instance)); + } + break; + + case TIM_TS_ITR2: + { + /* Check the parameter */ + assert_param(IS_TIM_CC2_INSTANCE(htim->Instance)); + } + break; + + case TIM_TS_ITR3: + { + /* Check the parameter */ + assert_param(IS_TIM_CC2_INSTANCE(htim->Instance)); + } + break; + + default: + break; + } +} + +/** + * @brief Configure the TI1 as Input. + * @param TIMx to select the TIM peripheral. + * @param TIM_ICPolarity The Input Polarity. + * This parameter can be one of the following values: + * @arg TIM_ICPolarity_Rising + * @arg TIM_ICPolarity_Falling + * @arg TIM_ICPolarity_BothEdge + * @param TIM_ICSelection specifies the input to be used. + * This parameter can be one of the following values: + * @arg TIM_ICSelection_DirectTI: TIM Input 1 is selected to be connected to IC1. + * @arg TIM_ICSelection_IndirectTI: TIM Input 1 is selected to be connected to IC2. + * @arg TIM_ICSelection_TRC: TIM Input 1 is selected to be connected to TRC. + * @param TIM_ICFilter Specifies the Input Capture Filter. + * This parameter must be a value between 0x00 and 0x0F. + * @retval None + * @note TIM_ICFilter and TIM_ICPolarity are not used in INDIRECT mode as TI2FP1 + * (on channel2 path) is used as the input signal. Therefore CCMR1 must be + * protected against un-initialized filter and polarity values. + */ +void TIM_TI1_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection, + uint32_t TIM_ICFilter) +{ + uint32_t tmpccmr1 = 0; + uint32_t tmpccer = 0; + + /* Disable the Channel 1: Reset the CC1E Bit */ + TIMx->CCER &= ~TIM_CCER_CC1E; + tmpccmr1 = TIMx->CCMR1; + tmpccer = TIMx->CCER; + + /* Select the Input */ + if(IS_TIM_CC2_INSTANCE(TIMx) != RESET) + { + tmpccmr1 &= ~TIM_CCMR1_CC1S; + tmpccmr1 |= TIM_ICSelection; + } + else + { + tmpccmr1 |= TIM_CCMR1_CC1S_0; + } + + /* Set the filter */ + tmpccmr1 &= ~TIM_CCMR1_IC1F; + tmpccmr1 |= ((TIM_ICFilter << 4) & TIM_CCMR1_IC1F); + + /* Select the Polarity and set the CC1E Bit */ + tmpccer &= ~(TIM_CCER_CC1P | TIM_CCER_CC1NP); + tmpccer |= (TIM_ICPolarity & (TIM_CCER_CC1P | TIM_CCER_CC1NP)); + + /* Write to TIMx CCMR1 and CCER registers */ + TIMx->CCMR1 = tmpccmr1; + TIMx->CCER = tmpccer; +} + +/** + * @brief Configure the Polarity and Filter for TI1. + * @param TIMx to select the TIM peripheral. + * @param TIM_ICPolarity The Input Polarity. + * This parameter can be one of the following values: + * @arg TIM_ICPolarity_Rising + * @arg TIM_ICPolarity_Falling + * @arg TIM_ICPolarity_BothEdge + * @param TIM_ICFilter Specifies the Input Capture Filter. + * This parameter must be a value between 0x00 and 0x0F. + * @retval None + */ +static void TIM_TI1_ConfigInputStage(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICFilter) +{ + uint32_t tmpccmr1 = 0; + uint32_t tmpccer = 0; + + /* Disable the Channel 1: Reset the CC1E Bit */ + tmpccer = TIMx->CCER; + TIMx->CCER &= ~TIM_CCER_CC1E; + tmpccmr1 = TIMx->CCMR1; + + /* Set the filter */ + tmpccmr1 &= ~TIM_CCMR1_IC1F; + tmpccmr1 |= (TIM_ICFilter << 4); + + /* Select the Polarity and set the CC1E Bit */ + tmpccer &= ~(TIM_CCER_CC1P | TIM_CCER_CC1NP); + tmpccer |= TIM_ICPolarity; + + /* Write to TIMx CCMR1 and CCER registers */ + TIMx->CCMR1 = tmpccmr1; + TIMx->CCER = tmpccer; +} + +/** + * @brief Configure the TI2 as Input. + * @param TIMx to select the TIM peripheral + * @param TIM_ICPolarity The Input Polarity. + * This parameter can be one of the following values: + * @arg TIM_ICPolarity_Rising + * @arg TIM_ICPolarity_Falling + * @arg TIM_ICPolarity_BothEdge + * @param TIM_ICSelection specifies the input to be used. + * This parameter can be one of the following values: + * @arg TIM_ICSelection_DirectTI: TIM Input 2 is selected to be connected to IC2. + * @arg TIM_ICSelection_IndirectTI: TIM Input 2 is selected to be connected to IC1. + * @arg TIM_ICSelection_TRC: TIM Input 2 is selected to be connected to TRC. + * @param TIM_ICFilter Specifies the Input Capture Filter. + * This parameter must be a value between 0x00 and 0x0F. + * @retval None + * @note TIM_ICFilter and TIM_ICPolarity are not used in INDIRECT mode as TI1FP2 + * (on channel1 path) is used as the input signal. Therefore CCMR1 must be + * protected against un-initialized filter and polarity values. + */ +static void TIM_TI2_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection, + uint32_t TIM_ICFilter) +{ + uint32_t tmpccmr1 = 0; + uint32_t tmpccer = 0; + + /* Disable the Channel 2: Reset the CC2E Bit */ + TIMx->CCER &= ~TIM_CCER_CC2E; + tmpccmr1 = TIMx->CCMR1; + tmpccer = TIMx->CCER; + + /* Select the Input */ + tmpccmr1 &= ~TIM_CCMR1_CC2S; + tmpccmr1 |= (TIM_ICSelection << 8); + + /* Set the filter */ + tmpccmr1 &= ~TIM_CCMR1_IC2F; + tmpccmr1 |= ((TIM_ICFilter << 12) & TIM_CCMR1_IC2F); + + /* Select the Polarity and set the CC2E Bit */ + tmpccer &= ~(TIM_CCER_CC2P | TIM_CCER_CC2NP); + tmpccer |= ((TIM_ICPolarity << 4) & (TIM_CCER_CC2P | TIM_CCER_CC2NP)); + + /* Write to TIMx CCMR1 and CCER registers */ + TIMx->CCMR1 = tmpccmr1 ; + TIMx->CCER = tmpccer; +} + +/** + * @brief Configure the Polarity and Filter for TI2. + * @param TIMx to select the TIM peripheral. + * @param TIM_ICPolarity The Input Polarity. + * This parameter can be one of the following values: + * @arg TIM_ICPolarity_Rising + * @arg TIM_ICPolarity_Falling + * @arg TIM_ICPolarity_BothEdge + * @param TIM_ICFilter Specifies the Input Capture Filter. + * This parameter must be a value between 0x00 and 0x0F. + * @retval None + */ +static void TIM_TI2_ConfigInputStage(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICFilter) +{ + uint32_t tmpccmr1 = 0; + uint32_t tmpccer = 0; + + /* Disable the Channel 2: Reset the CC2E Bit */ + TIMx->CCER &= ~TIM_CCER_CC2E; + tmpccmr1 = TIMx->CCMR1; + tmpccer = TIMx->CCER; + + /* Set the filter */ + tmpccmr1 &= ~TIM_CCMR1_IC2F; + tmpccmr1 |= (TIM_ICFilter << 12); + + /* Select the Polarity and set the CC2E Bit */ + tmpccer &= ~(TIM_CCER_CC2P | TIM_CCER_CC2NP); + tmpccer |= (TIM_ICPolarity << 4); + + /* Write to TIMx CCMR1 and CCER registers */ + TIMx->CCMR1 = tmpccmr1 ; + TIMx->CCER = tmpccer; +} + +/** + * @brief Configure the TI3 as Input. + * @param TIMx to select the TIM peripheral + * @param TIM_ICPolarity The Input Polarity. + * This parameter can be one of the following values: + * @arg TIM_ICPolarity_Rising + * @arg TIM_ICPolarity_Falling + * @arg TIM_ICPolarity_BothEdge + * @param TIM_ICSelection specifies the input to be used. + * This parameter can be one of the following values: + * @arg TIM_ICSelection_DirectTI: TIM Input 3 is selected to be connected to IC3. + * @arg TIM_ICSelection_IndirectTI: TIM Input 3 is selected to be connected to IC4. + * @arg TIM_ICSelection_TRC: TIM Input 3 is selected to be connected to TRC. + * @param TIM_ICFilter Specifies the Input Capture Filter. + * This parameter must be a value between 0x00 and 0x0F. + * @retval None + * @note TIM_ICFilter and TIM_ICPolarity are not used in INDIRECT mode as TI3FP4 + * (on channel1 path) is used as the input signal. Therefore CCMR2 must be + * protected against un-initialized filter and polarity values. + */ +static void TIM_TI3_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection, + uint32_t TIM_ICFilter) +{ + uint32_t tmpccmr2 = 0; + uint32_t tmpccer = 0; + + /* Disable the Channel 3: Reset the CC3E Bit */ + TIMx->CCER &= ~TIM_CCER_CC3E; + tmpccmr2 = TIMx->CCMR2; + tmpccer = TIMx->CCER; + + /* Select the Input */ + tmpccmr2 &= ~TIM_CCMR2_CC3S; + tmpccmr2 |= TIM_ICSelection; + + /* Set the filter */ + tmpccmr2 &= ~TIM_CCMR2_IC3F; + tmpccmr2 |= ((TIM_ICFilter << 4) & TIM_CCMR2_IC3F); + + /* Select the Polarity and set the CC3E Bit */ + tmpccer &= ~(TIM_CCER_CC3P | TIM_CCER_CC3NP); + tmpccer |= ((TIM_ICPolarity << 8) & (TIM_CCER_CC3P | TIM_CCER_CC3NP)); + + /* Write to TIMx CCMR2 and CCER registers */ + TIMx->CCMR2 = tmpccmr2; + TIMx->CCER = tmpccer; +} + +/** + * @brief Configure the TI4 as Input. + * @param TIMx to select the TIM peripheral + * @param TIM_ICPolarity The Input Polarity. + * This parameter can be one of the following values: + * @arg TIM_ICPolarity_Rising + * @arg TIM_ICPolarity_Falling + * @arg TIM_ICPolarity_BothEdge + * @param TIM_ICSelection specifies the input to be used. + * This parameter can be one of the following values: + * @arg TIM_ICSelection_DirectTI: TIM Input 4 is selected to be connected to IC4. + * @arg TIM_ICSelection_IndirectTI: TIM Input 4 is selected to be connected to IC3. + * @arg TIM_ICSelection_TRC: TIM Input 4 is selected to be connected to TRC. + * @param TIM_ICFilter Specifies the Input Capture Filter. + * This parameter must be a value between 0x00 and 0x0F. + * @note TIM_ICFilter and TIM_ICPolarity are not used in INDIRECT mode as TI4FP3 + * (on channel1 path) is used as the input signal. Therefore CCMR2 must be + * protected against un-initialized filter and polarity values. + * @retval None + */ +static void TIM_TI4_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection, + uint32_t TIM_ICFilter) +{ + uint32_t tmpccmr2 = 0; + uint32_t tmpccer = 0; + + /* Disable the Channel 4: Reset the CC4E Bit */ + TIMx->CCER &= ~TIM_CCER_CC4E; + tmpccmr2 = TIMx->CCMR2; + tmpccer = TIMx->CCER; + + /* Select the Input */ + tmpccmr2 &= ~TIM_CCMR2_CC4S; + tmpccmr2 |= (TIM_ICSelection << 8); + + /* Set the filter */ + tmpccmr2 &= ~TIM_CCMR2_IC4F; + tmpccmr2 |= ((TIM_ICFilter << 12) & TIM_CCMR2_IC4F); + + /* Select the Polarity and set the CC4E Bit */ + tmpccer &= ~(TIM_CCER_CC4P | TIM_CCER_CC4NP); + tmpccer |= ((TIM_ICPolarity << 12) & (TIM_CCER_CC4P | TIM_CCER_CC4NP)); + + /* Write to TIMx CCMR2 and CCER registers */ + TIMx->CCMR2 = tmpccmr2; + TIMx->CCER = tmpccer ; +} + +/** + * @brief Selects the Input Trigger source + * @param TIMx to select the TIM peripheral + * @param InputTriggerSource The Input Trigger source. + * This parameter can be one of the following values: + * @arg TIM_TS_ITR0: Internal Trigger 0 + * @arg TIM_TS_ITR1: Internal Trigger 1 + * @arg TIM_TS_ITR2: Internal Trigger 2 + * @arg TIM_TS_ITR3: Internal Trigger 3 + * @arg TIM_TS_TI1F_ED: TI1 Edge Detector + * @arg TIM_TS_TI1FP1: Filtered Timer Input 1 + * @arg TIM_TS_TI2FP2: Filtered Timer Input 2 + * @arg TIM_TS_ETRF: External Trigger input + * @retval None + */ +static void TIM_ITRx_SetConfig(TIM_TypeDef *TIMx, uint16_t InputTriggerSource) +{ + uint32_t tmpsmcr = 0; + + /* Get the TIMx SMCR register value */ + tmpsmcr = TIMx->SMCR; + /* Reset the TS Bits */ + tmpsmcr &= ~TIM_SMCR_TS; + /* Set the Input Trigger source and the slave mode*/ + tmpsmcr |= InputTriggerSource | TIM_SLAVEMODE_EXTERNAL1; + /* Write to TIMx SMCR */ + TIMx->SMCR = tmpsmcr; +} +/** + * @brief Configures the TIMx External Trigger (ETR). + * @param TIMx to select the TIM peripheral + * @param TIM_ExtTRGPrescaler The external Trigger Prescaler. + * This parameter can be one of the following values: + * @arg TIM_ETRPRESCALER_DIV1 : ETRP Prescaler OFF. + * @arg TIM_ETRPRESCALER_DIV2 : ETRP frequency divided by 2. + * @arg TIM_ETRPRESCALER_DIV4 : ETRP frequency divided by 4. + * @arg TIM_ETRPRESCALER_DIV8 : ETRP frequency divided by 8. + * @param TIM_ExtTRGPolarity The external Trigger Polarity. + * This parameter can be one of the following values: + * @arg TIM_ETRPOLARITY_INVERTED : active low or falling edge active. + * @arg TIM_ETRPOLARITY_NONINVERTED : active high or rising edge active. + * @param ExtTRGFilter External Trigger Filter. + * This parameter must be a value between 0x00 and 0x0F + * @retval None + */ +void TIM_ETR_SetConfig(TIM_TypeDef* TIMx, uint32_t TIM_ExtTRGPrescaler, + uint32_t TIM_ExtTRGPolarity, uint32_t ExtTRGFilter) +{ + uint32_t tmpsmcr = 0; + + tmpsmcr = TIMx->SMCR; + + /* Reset the ETR Bits */ + tmpsmcr &= ~(TIM_SMCR_ETF | TIM_SMCR_ETPS | TIM_SMCR_ECE | TIM_SMCR_ETP); + + /* Set the Prescaler, the Filter value and the Polarity */ + tmpsmcr |= (uint32_t)(TIM_ExtTRGPrescaler | (TIM_ExtTRGPolarity | (ExtTRGFilter << 8))); + + /* Write to TIMx SMCR */ + TIMx->SMCR = tmpsmcr; +} + +/** + * @brief Enables or disables the TIM Capture Compare Channel x. + * @param TIMx to select the TIM peripheral + * @param Channel specifies the TIM Channel + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 + * @arg TIM_CHANNEL_2: TIM Channel 2 + * @arg TIM_CHANNEL_3: TIM Channel 3 + * @arg TIM_CHANNEL_4: TIM Channel 4 + * @param ChannelState: specifies the TIM Channel CCxE bit new state. + * This parameter can be: TIM_CCx_ENABLE or TIM_CCx_Disable. + * @retval None + */ +void TIM_CCxChannelCmd(TIM_TypeDef* TIMx, uint32_t Channel, uint32_t ChannelState) +{ + uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_TIM_CC1_INSTANCE(TIMx)); + assert_param(IS_TIM_CHANNELS(Channel)); + + tmp = TIM_CCER_CC1E << Channel; + + /* Reset the CCxE Bit */ + TIMx->CCER &= ~tmp; + + /* Set or reset the CCxE Bit */ + TIMx->CCER |= (uint32_t)(ChannelState << Channel); +} + + +/** + * @} + */ + +#endif /* HAL_TIM_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_tim_ex.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_tim_ex.c new file mode 100644 index 0000000..754c1a7 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_tim_ex.c @@ -0,0 +1,2243 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_tim_ex.c + * @author MCD Application Team + * @brief TIM HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Timer Extended peripheral: + * + Time Hall Sensor Interface Initialization + * + Time Hall Sensor Interface Start + * + Time Complementary signal break and dead time configuration + * + Time Master and Slave synchronization configuration + * + Time Output Compare/PWM Channel Configuration (for channels 5 and 6) + * + Time OCRef clear configuration + * + Timer remapping capabilities configuration + @verbatim + ============================================================================== + ##### TIMER Extended features ##### + ============================================================================== + [..] + The Timer Extended features include: + (#) Complementary outputs with programmable dead-time for : + (++) Output Compare + (++) PWM generation (Edge and Center-aligned Mode) + (++) One-pulse mode output + (#) Synchronization circuit to control the timer with external signals and to + interconnect several timers together. + (#) Break input to put the timer output signals in reset state or in a known state. + (#) Supports incremental (quadrature) encoder and hall-sensor circuitry for + positioning purposes + + ##### How to use this driver ##### + ============================================================================== + [..] + (#) Initialize the TIM low level resources by implementing the following functions + depending on the selected feature: + (++) Hall Sensor output : HAL_TIMEx_HallSensor_MspInit() + + (#) Initialize the TIM low level resources : + (##) Enable the TIM interface clock using __HAL_RCC_TIMx_CLK_ENABLE(); + (##) TIM pins configuration + (+++) Enable the clock for the TIM GPIOs using the following function: + __HAL_RCC_GPIOx_CLK_ENABLE(); + (+++) Configure these TIM pins in Alternate function mode using HAL_GPIO_Init(); + + (#) The external Clock can be configured, if needed (the default clock is the + internal clock from the APBx), using the following function: + HAL_TIM_ConfigClockSource, the clock configuration should be done before + any start function. + + (#) Configure the TIM in the desired functioning mode using one of the + initialization function of this driver: + (++) HAL_TIMEx_HallSensor_Init() and HAL_TIMEx_ConfigCommutationEvent(): to use the + Timer Hall Sensor Interface and the commutation event with the corresponding + Interrupt and DMA request if needed (Note that One Timer is used to interface + with the Hall sensor Interface and another Timer should be used to use + the commutation event). + + (#) Activate the TIM peripheral using one of the start functions: + (++) Complementary Output Compare : HAL_TIMEx_OCN_Start(), HAL_TIMEx_OCN_Start_DMA(), HAL_TIMEx_OC_Start_IT() + (++) Complementary PWM generation : HAL_TIMEx_PWMN_Start(), HAL_TIMEx_PWMN_Start_DMA(), HAL_TIMEx_PWMN_Start_IT() + (++) Complementary One-pulse mode output : HAL_TIMEx_OnePulseN_Start(), HAL_TIMEx_OnePulseN_Start_IT() + (++) Hall Sensor output : HAL_TIMEx_HallSensor_Start(), HAL_TIMEx_HallSensor_Start_DMA(), HAL_TIMEx_HallSensor_Start_IT(). + + + @endverbatim + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** +*/ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup TIMEx TIMEx + * @brief TIM Extended HAL module driver + * @{ + */ + +#ifdef HAL_TIM_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +#define BDTR_BKF_SHIFT (16) +#define BDTR_BK2F_SHIFT (20) +#define TIMx_ETRSEL_MASK ((uint32_t)0x0003C000) + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +static void TIM_CCxNChannelCmd(TIM_TypeDef* TIMx, uint32_t Channel, uint32_t ChannelNState); + +/* Private functions ---------------------------------------------------------*/ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup TIMEx_Exported_Functions TIM Extended Exported Functions + * @{ + */ + +/** @defgroup TIMEx_Exported_Functions_Group1 Extended Timer Hall Sensor functions + * @brief Timer Hall Sensor functions + * +@verbatim + ============================================================================== + ##### Timer Hall Sensor functions ##### + ============================================================================== + [..] + This section provides functions allowing to: + (+) Initialize and configure TIM HAL Sensor. + (+) De-initialize TIM HAL Sensor. + (+) Start the Hall Sensor Interface. + (+) Stop the Hall Sensor Interface. + (+) Start the Hall Sensor Interface and enable interrupts. + (+) Stop the Hall Sensor Interface and disable interrupts. + (+) Start the Hall Sensor Interface and enable DMA transfers. + (+) Stop the Hall Sensor Interface and disable DMA transfers. + +@endverbatim + * @{ + */ +/** + * @brief Initializes the TIM Hall Sensor Interface and initialize the associated handle. + * @param htim TIM Encoder Interface handle + * @param sConfig TIM Hall Sensor configuration structure + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_HallSensor_Init(TIM_HandleTypeDef *htim, TIM_HallSensor_InitTypeDef* sConfig) +{ + TIM_OC_InitTypeDef OC_Config; + + /* Check the TIM handle allocation */ + if(htim == NULL) + { + return HAL_ERROR; + } + + assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance)); + assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode)); + assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision)); + assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload)); + assert_param(IS_TIM_IC_POLARITY(sConfig->IC1Polarity)); + assert_param(IS_TIM_IC_PRESCALER(sConfig->IC1Prescaler)); + assert_param(IS_TIM_IC_FILTER(sConfig->IC1Filter)); + + if(htim->State == HAL_TIM_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + htim->Lock = HAL_UNLOCKED; + + /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */ + HAL_TIMEx_HallSensor_MspInit(htim); + } + + /* Set the TIM state */ + htim->State = HAL_TIM_STATE_BUSY; + + /* Configure the Time base in the Encoder Mode */ + TIM_Base_SetConfig(htim->Instance, &htim->Init); + + /* Configure the Channel 1 as Input Channel to interface with the three Outputs of the Hall sensor */ + TIM_TI1_SetConfig(htim->Instance, sConfig->IC1Polarity, TIM_ICSELECTION_TRC, sConfig->IC1Filter); + + /* Reset the IC1PSC Bits */ + htim->Instance->CCMR1 &= ~TIM_CCMR1_IC1PSC; + /* Set the IC1PSC value */ + htim->Instance->CCMR1 |= sConfig->IC1Prescaler; + + /* Enable the Hall sensor interface (XOR function of the three inputs) */ + htim->Instance->CR2 |= TIM_CR2_TI1S; + + /* Select the TIM_TS_TI1F_ED signal as Input trigger for the TIM */ + htim->Instance->SMCR &= ~TIM_SMCR_TS; + htim->Instance->SMCR |= TIM_TS_TI1F_ED; + + /* Use the TIM_TS_TI1F_ED signal to reset the TIM counter each edge detection */ + htim->Instance->SMCR &= ~TIM_SMCR_SMS; + htim->Instance->SMCR |= TIM_SLAVEMODE_RESET; + + /* Program channel 2 in PWM 2 mode with the desired Commutation_Delay*/ + OC_Config.OCFastMode = TIM_OCFAST_DISABLE; + OC_Config.OCIdleState = TIM_OCIDLESTATE_RESET; + OC_Config.OCMode = TIM_OCMODE_PWM2; + OC_Config.OCNIdleState = TIM_OCNIDLESTATE_RESET; + OC_Config.OCNPolarity = TIM_OCNPOLARITY_HIGH; + OC_Config.OCPolarity = TIM_OCPOLARITY_HIGH; + OC_Config.Pulse = sConfig->Commutation_Delay; + + TIM_OC2_SetConfig(htim->Instance, &OC_Config); + + /* Select OC2REF as trigger output on TRGO: write the MMS bits in the TIMx_CR2 + register to 101 */ + htim->Instance->CR2 &= ~TIM_CR2_MMS; + htim->Instance->CR2 |= TIM_TRGO_OC2REF; + + /* Initialize the TIM state*/ + htim->State= HAL_TIM_STATE_READY; + + return HAL_OK; +} + +/** + * @brief DeInitialize the TIM Hall Sensor interface + * @param htim TIM Hall Sensor handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_HallSensor_DeInit(TIM_HandleTypeDef *htim) +{ + /* Check the parameters */ + assert_param(IS_TIM_INSTANCE(htim->Instance)); + + htim->State = HAL_TIM_STATE_BUSY; + + /* Disable the TIM Peripheral Clock */ + __HAL_TIM_DISABLE(htim); + + /* DeInit the low level hardware: GPIO, CLOCK, NVIC */ + HAL_TIMEx_HallSensor_MspDeInit(htim); + + /* Change TIM state */ + htim->State = HAL_TIM_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @brief Initializes the TIM Hall Sensor MSP. + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIMEx_HallSensor_MspInit(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_TIMEx_HallSensor_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitialize TIM Hall Sensor MSP. + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIMEx_HallSensor_MspDeInit(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_TIMEx_HallSensor_MspDeInit could be implemented in the user file + */ +} + +/** + * @brief Starts the TIM Hall Sensor Interface. + * @param htim TIM Hall Sensor handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_HallSensor_Start(TIM_HandleTypeDef *htim) +{ + /* Check the parameters */ + assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance)); + + /* Enable the Input Capture channel 1 + (in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1, TIM_CHANNEL_2 and TIM_CHANNEL_3) */ + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE); + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM Hall sensor Interface. + * @param htim TIM Hall Sensor handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_HallSensor_Stop(TIM_HandleTypeDef *htim) +{ + /* Check the parameters */ + assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance)); + + /* Disable the Input Capture channels 1, 2 and 3 + (in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1, TIM_CHANNEL_2 and TIM_CHANNEL_3) */ + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE); + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Starts the TIM Hall Sensor Interface in interrupt mode. + * @param htim TIM Hall Sensor handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_HallSensor_Start_IT(TIM_HandleTypeDef *htim) +{ + /* Check the parameters */ + assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance)); + + /* Enable the capture compare Interrupts 1 event */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1); + + /* Enable the Input Capture channel 1 + (in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1, TIM_CHANNEL_2 and TIM_CHANNEL_3) */ + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE); + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM Hall Sensor Interface in interrupt mode. + * @param htim TIM handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_HallSensor_Stop_IT(TIM_HandleTypeDef *htim) +{ + /* Check the parameters */ + assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance)); + + /* Disable the Input Capture channel 1 + (in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1, TIM_CHANNEL_2 and TIM_CHANNEL_3) */ + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE); + + /* Disable the capture compare Interrupts event */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1); + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Starts the TIM Hall Sensor Interface in DMA mode. + * @param htim TIM Hall Sensor handle + * @param pData The destination Buffer address. + * @param Length The length of data to be transferred from TIM peripheral to memory. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_HallSensor_Start_DMA(TIM_HandleTypeDef *htim, uint32_t *pData, uint16_t Length) +{ + /* Check the parameters */ + assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance)); + + if((htim->State == HAL_TIM_STATE_BUSY)) + { + return HAL_BUSY; + } + else if((htim->State == HAL_TIM_STATE_READY)) + { + if(((uint32_t)pData == 0 ) && (Length > 0)) + { + return HAL_ERROR; + } + else + { + htim->State = HAL_TIM_STATE_BUSY; + } + } + /* Enable the Input Capture channel 1 + (in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1, TIM_CHANNEL_2 and TIM_CHANNEL_3) */ + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE); + + /* Set the DMA Input Capture 1 Callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMACaptureCplt; + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel for Capture 1*/ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)&htim->Instance->CCR1, (uint32_t)pData, Length); + + /* Enable the capture compare 1 Interrupt */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1); + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM Hall Sensor Interface in DMA mode. + * @param htim TIM handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_HallSensor_Stop_DMA(TIM_HandleTypeDef *htim) +{ + /* Check the parameters */ + assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance)); + + /* Disable the Input Capture channel 1 + (in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1, TIM_CHANNEL_2 and TIM_CHANNEL_3) */ + TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE); + + + /* Disable the capture compare Interrupts 1 event */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1); + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup TIMEx_Exported_Functions_Group2 Extended Timer Complementary Output Compare functions + * @brief Timer Complementary Output Compare functions + * +@verbatim + ============================================================================== + ##### Timer Complementary Output Compare functions ##### + ============================================================================== + [..] + This section provides functions allowing to: + (+) Start the Complementary Output Compare/PWM. + (+) Stop the Complementary Output Compare/PWM. + (+) Start the Complementary Output Compare/PWM and enable interrupts. + (+) Stop the Complementary Output Compare/PWM and disable interrupts. + (+) Start the Complementary Output Compare/PWM and enable DMA transfers. + (+) Stop the Complementary Output Compare/PWM and disable DMA transfers. + +@endverbatim + * @{ + */ + +/** + * @brief Starts the TIM Output Compare signal generation on the complementary + * output. + * @param htim TIM Output Compare handle + * @param Channel TIM Channel to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_OCN_Start(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel)); + + /* Enable the Capture compare channel N */ + TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE); + + /* Enable the Main Ouput */ + __HAL_TIM_MOE_ENABLE(htim); + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM Output Compare signal generation on the complementary + * output. + * @param htim TIM handle + * @param Channel TIM Channel to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_OCN_Stop(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel)); + + /* Disable the Capture compare channel N */ + TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE); + + /* Disable the Main Ouput */ + __HAL_TIM_MOE_DISABLE(htim); + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Starts the TIM Output Compare signal generation in interrupt mode + * on the complementary output. + * @param htim TIM OC handle + * @param Channel TIM Channel to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_OCN_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel)); + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Enable the TIM Output Compare interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Enable the TIM Output Compare interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2); + } + break; + + case TIM_CHANNEL_3: + { + /* Enable the TIM Output Compare interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Enable the TIM Output Compare interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC4); + } + break; + + default: + break; + } + + /* Enable the TIM Break interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_BREAK); + + /* Enable the Capture compare channel N */ + TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE); + + /* Enable the Main Ouput */ + __HAL_TIM_MOE_ENABLE(htim); + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM Output Compare signal generation in interrupt mode + * on the complementary output. + * @param htim TIM Output Compare handle + * @param Channel TIM Channel to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_OCN_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + uint32_t tmpccer = 0; + + /* Check the parameters */ + assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel)); + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Disable the TIM Output Compare interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Disable the TIM Output Compare interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2); + } + break; + + case TIM_CHANNEL_3: + { + /* Disable the TIM Output Compare interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Disable the TIM Output Compare interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC4); + } + break; + + default: + break; + } + + /* Disable the Capture compare channel N */ + TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE); + + /* Disable the TIM Break interrupt (only if no more channel is active) */ + tmpccer = htim->Instance->CCER; + if ((tmpccer & (TIM_CCER_CC1NE | TIM_CCER_CC2NE | TIM_CCER_CC3NE)) == RESET) + { + __HAL_TIM_DISABLE_IT(htim, TIM_IT_BREAK); + } + + /* Disable the Main Ouput */ + __HAL_TIM_MOE_DISABLE(htim); + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Starts the TIM Output Compare signal generation in DMA mode + * on the complementary output. + * @param htim TIM Output Compare handle + * @param Channel TIM Channel to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @param pData The source Buffer address. + * @param Length The length of data to be transferred from memory to TIM peripheral + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_OCN_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel)); + + if((htim->State == HAL_TIM_STATE_BUSY)) + { + return HAL_BUSY; + } + else if((htim->State == HAL_TIM_STATE_READY)) + { + if(((uint32_t)pData == 0 ) && (Length > 0)) + { + return HAL_ERROR; + } + else + { + htim->State = HAL_TIM_STATE_BUSY; + } + } + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)pData, (uint32_t)&htim->Instance->CCR1, Length); + + /* Enable the TIM Output Compare DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)pData, (uint32_t)&htim->Instance->CCR2, Length); + + /* Enable the TIM Output Compare DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2); + } + break; + + case TIM_CHANNEL_3: +{ + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)pData, (uint32_t)&htim->Instance->CCR3,Length); + + /* Enable the TIM Output Compare DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC4]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC4], (uint32_t)pData, (uint32_t)&htim->Instance->CCR4, Length); + + /* Enable the TIM Output Compare DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC4); + } + break; + + default: + break; + } + + /* Enable the Capture compare channel N */ + TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE); + + /* Enable the Main Ouput */ + __HAL_TIM_MOE_ENABLE(htim); + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM Output Compare signal generation in DMA mode + * on the complementary output. + * @param htim TIM Output Compare handle + * @param Channel TIM Channel to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_OCN_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel)); + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Disable the TIM Output Compare DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Disable the TIM Output Compare DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2); + } + break; + + case TIM_CHANNEL_3: + { + /* Disable the TIM Output Compare DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Disable the TIM Output Compare interrupt */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC4); + } + break; + + default: + break; + } + + /* Disable the Capture compare channel N */ + TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE); + + /* Disable the Main Ouput */ + __HAL_TIM_MOE_DISABLE(htim); + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Change the htim state */ + htim->State = HAL_TIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup TIMEx_Exported_Functions_Group3 Extended Timer Complementary PWM functions + * @brief Timer Complementary PWM functions + * +@verbatim + ============================================================================== + ##### Timer Complementary PWM functions ##### + ============================================================================== + [..] + This section provides functions allowing to: + (+) Start the Complementary PWM. + (+) Stop the Complementary PWM. + (+) Start the Complementary PWM and enable interrupts. + (+) Stop the Complementary PWM and disable interrupts. + (+) Start the Complementary PWM and enable DMA transfers. + (+) Stop the Complementary PWM and disable DMA transfers. + (+) Start the Complementary Input Capture measurement. + (+) Stop the Complementary Input Capture. + (+) Start the Complementary Input Capture and enable interrupts. + (+) Stop the Complementary Input Capture and disable interrupts. + (+) Start the Complementary Input Capture and enable DMA transfers. + (+) Stop the Complementary Input Capture and disable DMA transfers. + (+) Start the Complementary One Pulse generation. + (+) Stop the Complementary One Pulse. + (+) Start the Complementary One Pulse and enable interrupts. + (+) Stop the Complementary One Pulse and disable interrupts. + +@endverbatim + * @{ + */ + +/** + * @brief Starts the PWM signal generation on the complementary output. + * @param htim TIM handle + * @param Channel TIM Channel to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_PWMN_Start(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel)); + + /* Enable the complementary PWM output */ + TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE); + + /* Enable the Main Ouput */ + __HAL_TIM_MOE_ENABLE(htim); + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the PWM signal generation on the complementary output. + * @param htim TIM handle + * @param Channel TIM Channel to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel)); + + /* Disable the complementary PWM output */ + TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE); + + /* Disable the Main Ouput */ + __HAL_TIM_MOE_DISABLE(htim); + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Starts the PWM signal generation in interrupt mode on the + * complementary output. + * @param htim TIM handle + * @param Channel TIM Channel to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_PWMN_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel)); + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Enable the TIM Capture/Compare 1 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Enable the TIM Capture/Compare 2 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2); + } + break; + + case TIM_CHANNEL_3: + { + /* Enable the TIM Capture/Compare 3 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Enable the TIM Capture/Compare 4 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC4); + } + break; + + default: + break; + } + + /* Enable the TIM Break interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_BREAK); + + /* Enable the complementary PWM output */ + TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE); + + /* Enable the Main Ouput */ + __HAL_TIM_MOE_ENABLE(htim); + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the PWM signal generation in interrupt mode on the + * complementary output. + * @param htim TIM handle + * @param Channel TIM Channel to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop_IT (TIM_HandleTypeDef *htim, uint32_t Channel) +{ + uint32_t tmpccer = 0; + + /* Check the parameters */ + assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel)); + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Disable the TIM Capture/Compare 1 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Disable the TIM Capture/Compare 2 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2); + } + break; + + case TIM_CHANNEL_3: + { + /* Disable the TIM Capture/Compare 3 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Disable the TIM Capture/Compare 3 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC4); + } + break; + + default: + break; + } + + /* Disable the complementary PWM output */ + TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE); + + + /* Disable the TIM Break interrupt (only if no more channel is active) */ + tmpccer = htim->Instance->CCER; + if ((tmpccer & (TIM_CCER_CC1NE | TIM_CCER_CC2NE | TIM_CCER_CC3NE)) == RESET) + { + __HAL_TIM_DISABLE_IT(htim, TIM_IT_BREAK); + } + + /* Disable the Main Ouput */ + __HAL_TIM_MOE_DISABLE(htim); + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Starts the TIM PWM signal generation in DMA mode on the + * complementary output + * @param htim TIM handle + * @param Channel TIM Channel to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @param pData The source Buffer address. + * @param Length The length of data to be transferred from memory to TIM peripheral + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_PWMN_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel)); + + if((htim->State == HAL_TIM_STATE_BUSY)) + { + return HAL_BUSY; + } + else if((htim->State == HAL_TIM_STATE_READY)) + { + if(((uint32_t)pData == 0 ) && (Length > 0)) + { + return HAL_ERROR; + } + else + { + htim->State = HAL_TIM_STATE_BUSY; + } + } + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)pData, (uint32_t)&htim->Instance->CCR1, Length); + + /* Enable the TIM Capture/Compare 1 DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)pData, (uint32_t)&htim->Instance->CCR2, Length); + + /* Enable the TIM Capture/Compare 2 DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2); + } + break; + + case TIM_CHANNEL_3: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)pData, (uint32_t)&htim->Instance->CCR3,Length); + + /* Enable the TIM Capture/Compare 3 DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Set the DMA Period elapsed callback */ + htim->hdma[TIM_DMA_ID_CC4]->XferCpltCallback = TIM_DMADelayPulseCplt; + + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_CC4]->XferErrorCallback = TIM_DMAError ; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC4], (uint32_t)pData, (uint32_t)&htim->Instance->CCR4, Length); + + /* Enable the TIM Capture/Compare 4 DMA request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC4); + } + break; + + default: + break; + } + + /* Enable the complementary PWM output */ + TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE); + + /* Enable the Main Ouput */ + __HAL_TIM_MOE_ENABLE(htim); + + /* Enable the Peripheral */ + __HAL_TIM_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM PWM signal generation in DMA mode on the complementary + * output + * @param htim TIM handle + * @param Channel TIM Channel to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @arg TIM_CHANNEL_3: TIM Channel 3 selected + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel)); + + switch (Channel) + { + case TIM_CHANNEL_1: + { + /* Disable the TIM Capture/Compare 1 DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1); + } + break; + + case TIM_CHANNEL_2: + { + /* Disable the TIM Capture/Compare 2 DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2); + } + break; + + case TIM_CHANNEL_3: + { + /* Disable the TIM Capture/Compare 3 DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC3); + } + break; + + case TIM_CHANNEL_4: + { + /* Disable the TIM Capture/Compare 4 DMA request */ + __HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC4); + } + break; + + default: + break; + } + + /* Disable the complementary PWM output */ + TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE); + + /* Disable the Main Ouput */ + __HAL_TIM_MOE_DISABLE(htim); + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Change the htim state */ + htim->State = HAL_TIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup TIMEx_Exported_Functions_Group4 Extended Timer Complementary One Pulse functions + * @brief Timer Complementary One Pulse functions + * +@verbatim + ============================================================================== + ##### Timer Complementary One Pulse functions ##### + ============================================================================== + [..] + This section provides functions allowing to: + (+) Start the Complementary One Pulse generation. + (+) Stop the Complementary One Pulse. + (+) Start the Complementary One Pulse and enable interrupts. + (+) Stop the Complementary One Pulse and disable interrupts. + +@endverbatim + * @{ + */ + +/** + * @brief Starts the TIM One Pulse signal generation on the complementary + * output. + * @param htim TIM One Pulse handle + * @param OutputChannel TIM Channel to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Start(TIM_HandleTypeDef *htim, uint32_t OutputChannel) + { + /* Check the parameters */ + assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, OutputChannel)); + + /* Enable the complementary One Pulse output */ + TIM_CCxNChannelCmd(htim->Instance, OutputChannel, TIM_CCxN_ENABLE); + + /* Enable the Main Ouput */ + __HAL_TIM_MOE_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM One Pulse signal generation on the complementary + * output. + * @param htim TIM One Pulse handle + * @param OutputChannel TIM Channel to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Stop(TIM_HandleTypeDef *htim, uint32_t OutputChannel) +{ + + /* Check the parameters */ + assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, OutputChannel)); + + /* Disable the complementary One Pulse output */ + TIM_CCxNChannelCmd(htim->Instance, OutputChannel, TIM_CCxN_DISABLE); + + /* Disable the Main Ouput */ + __HAL_TIM_MOE_DISABLE(htim); + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Starts the TIM One Pulse signal generation in interrupt mode on the + * complementary channel. + * @param htim TIM One Pulse handle + * @param OutputChannel TIM Channel to be enabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Start_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, OutputChannel)); + + /* Enable the TIM Capture/Compare 1 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1); + + /* Enable the TIM Capture/Compare 2 interrupt */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2); + + /* Enable the complementary One Pulse output */ + TIM_CCxNChannelCmd(htim->Instance, OutputChannel, TIM_CCxN_ENABLE); + + /* Enable the Main Ouput */ + __HAL_TIM_MOE_ENABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stops the TIM One Pulse signal generation in interrupt mode on the + * complementary channel. + * @param htim TIM One Pulse handle + * @param OutputChannel TIM Channel to be disabled + * This parameter can be one of the following values: + * @arg TIM_CHANNEL_1: TIM Channel 1 selected + * @arg TIM_CHANNEL_2: TIM Channel 2 selected + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Stop_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel) +{ + /* Check the parameters */ + assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, OutputChannel)); + + /* Disable the TIM Capture/Compare 1 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1); + + /* Disable the TIM Capture/Compare 2 interrupt */ + __HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2); + + /* Disable the complementary One Pulse output */ + TIM_CCxNChannelCmd(htim->Instance, OutputChannel, TIM_CCxN_DISABLE); + + /* Disable the Main Ouput */ + __HAL_TIM_MOE_DISABLE(htim); + + /* Disable the Peripheral */ + __HAL_TIM_DISABLE(htim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup TIMEx_Exported_Functions_Group5 Extended Peripheral Control functions + * @brief Peripheral Control functions + * +@verbatim + ============================================================================== + ##### Peripheral Control functions ##### + ============================================================================== + [..] + This section provides functions allowing to: + (+) Configure the commutation event in case of use of the Hall sensor interface. + (+) Configure Output channels for OC and PWM mode. + + (+) Configure Complementary channels, break features and dead time. + (+) Configure Master synchronization. + (+) Configure timer remapping capabilities. + (+) Enable or disable channel grouping + +@endverbatim + * @{ + */ + +/** + * @brief Configure the TIM commutation event sequence. + * @note This function is mandatory to use the commutation event in order to + * update the configuration at each commutation detection on the TRGI input of the Timer, + * the typical use of this feature is with the use of another Timer(interface Timer) + * configured in Hall sensor interface, this interface Timer will generate the + * commutation at its TRGO output (connected to Timer used in this function) each time + * the TI1 of the Interface Timer detect a commutation at its input TI1. + * @param htim TIM handle + * @param InputTrigger the Internal trigger corresponding to the Timer Interfacing with the Hall sensor + * This parameter can be one of the following values: + * @arg TIM_TS_ITR0: Internal trigger 0 selected + * @arg TIM_TS_ITR1: Internal trigger 1 selected + * @arg TIM_TS_ITR2: Internal trigger 2 selected + * @arg TIM_TS_ITR3: Internal trigger 3 selected + * @arg TIM_TS_NONE: No trigger is needed + * @param CommutationSource the Commutation Event source + * This parameter can be one of the following values: + * @arg TIM_COMMUTATION_TRGI: Commutation source is the TRGI of the Interface Timer + * @arg TIM_COMMUTATION_SOFTWARE: Commutation source is set by software using the COMG bit + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_ConfigCommutationEvent(TIM_HandleTypeDef *htim, uint32_t InputTrigger, uint32_t CommutationSource) +{ + /* Check the parameters */ + assert_param(IS_TIM_COMMUTATION_EVENT_INSTANCE(htim->Instance)); + assert_param(IS_TIM_INTERNAL_TRIGGEREVENT_SELECTION(InputTrigger)); + + __HAL_LOCK(htim); + + if ((InputTrigger == TIM_TS_ITR0) || (InputTrigger == TIM_TS_ITR1) || + (InputTrigger == TIM_TS_ITR2) || (InputTrigger == TIM_TS_ITR3)) + { + /* Select the Input trigger */ + htim->Instance->SMCR &= ~TIM_SMCR_TS; + htim->Instance->SMCR |= InputTrigger; + } + + /* Select the Capture Compare preload feature */ + htim->Instance->CR2 |= TIM_CR2_CCPC; + /* Select the Commutation event source */ + htim->Instance->CR2 &= ~TIM_CR2_CCUS; + htim->Instance->CR2 |= CommutationSource; + + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @brief Configure the TIM commutation event sequence with interrupt. + * @note This function is mandatory to use the commutation event in order to + * update the configuration at each commutation detection on the TRGI input of the Timer, + * the typical use of this feature is with the use of another Timer(interface Timer) + * configured in Hall sensor interface, this interface Timer will generate the + * commutation at its TRGO output (connected to Timer used in this function) each time + * the TI1 of the Interface Timer detect a commutation at its input TI1. + * @param htim TIM handle + * @param InputTrigger the Internal trigger corresponding to the Timer Interfacing with the Hall sensor + * This parameter can be one of the following values: + * @arg TIM_TS_ITR0: Internal trigger 0 selected + * @arg TIM_TS_ITR1: Internal trigger 1 selected + * @arg TIM_TS_ITR2: Internal trigger 2 selected + * @arg TIM_TS_ITR3: Internal trigger 3 selected + * @arg TIM_TS_NONE: No trigger is needed + * @param CommutationSource the Commutation Event source + * This parameter can be one of the following values: + * @arg TIM_COMMUTATION_TRGI: Commutation source is the TRGI of the Interface Timer + * @arg TIM_COMMUTATION_SOFTWARE: Commutation source is set by software using the COMG bit + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_ConfigCommutationEvent_IT(TIM_HandleTypeDef *htim, uint32_t InputTrigger, uint32_t CommutationSource) +{ + /* Check the parameters */ + assert_param(IS_TIM_COMMUTATION_EVENT_INSTANCE(htim->Instance)); + assert_param(IS_TIM_INTERNAL_TRIGGEREVENT_SELECTION(InputTrigger)); + + __HAL_LOCK(htim); + + if ((InputTrigger == TIM_TS_ITR0) || (InputTrigger == TIM_TS_ITR1) || + (InputTrigger == TIM_TS_ITR2) || (InputTrigger == TIM_TS_ITR3)) + { + /* Select the Input trigger */ + htim->Instance->SMCR &= ~TIM_SMCR_TS; + htim->Instance->SMCR |= InputTrigger; + } + + /* Select the Capture Compare preload feature */ + htim->Instance->CR2 |= TIM_CR2_CCPC; + /* Select the Commutation event source */ + htim->Instance->CR2 &= ~TIM_CR2_CCUS; + htim->Instance->CR2 |= CommutationSource; + + /* Enable the Commutation Interrupt Request */ + __HAL_TIM_ENABLE_IT(htim, TIM_IT_COM); + + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @brief Configure the TIM commutation event sequence with DMA. + * @note This function is mandatory to use the commutation event in order to + * update the configuration at each commutation detection on the TRGI input of the Timer, + * the typical use of this feature is with the use of another Timer(interface Timer) + * configured in Hall sensor interface, this interface Timer will generate the + * commutation at its TRGO output (connected to Timer used in this function) each time + * the TI1 of the Interface Timer detect a commutation at its input TI1. + * @note The user should configure the DMA in his own software, in This function only the COMDE bit is set + * @param htim TIM handle + * @param InputTrigger the Internal trigger corresponding to the Timer Interfacing with the Hall sensor + * This parameter can be one of the following values: + * @arg TIM_TS_ITR0: Internal trigger 0 selected + * @arg TIM_TS_ITR1: Internal trigger 1 selected + * @arg TIM_TS_ITR2: Internal trigger 2 selected + * @arg TIM_TS_ITR3: Internal trigger 3 selected + * @arg TIM_TS_NONE: No trigger is needed + * @param CommutationSource the Commutation Event source + * This parameter can be one of the following values: + * @arg TIM_COMMUTATION_TRGI: Commutation source is the TRGI of the Interface Timer + * @arg TIM_COMMUTATION_SOFTWARE: Commutation source is set by software using the COMG bit + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_ConfigCommutationEvent_DMA(TIM_HandleTypeDef *htim, uint32_t InputTrigger, uint32_t CommutationSource) +{ + /* Check the parameters */ + assert_param(IS_TIM_COMMUTATION_EVENT_INSTANCE(htim->Instance)); + assert_param(IS_TIM_INTERNAL_TRIGGEREVENT_SELECTION(InputTrigger)); + + __HAL_LOCK(htim); + + if ((InputTrigger == TIM_TS_ITR0) || (InputTrigger == TIM_TS_ITR1) || + (InputTrigger == TIM_TS_ITR2) || (InputTrigger == TIM_TS_ITR3)) + { + /* Select the Input trigger */ + htim->Instance->SMCR &= ~TIM_SMCR_TS; + htim->Instance->SMCR |= InputTrigger; + } + + /* Select the Capture Compare preload feature */ + htim->Instance->CR2 |= TIM_CR2_CCPC; + /* Select the Commutation event source */ + htim->Instance->CR2 &= ~TIM_CR2_CCUS; + htim->Instance->CR2 |= CommutationSource; + + /* Enable the Commutation DMA Request */ + /* Set the DMA Commutation Callback */ + htim->hdma[TIM_DMA_ID_COMMUTATION]->XferCpltCallback = TIMEx_DMACommutationCplt; + /* Set the DMA error callback */ + htim->hdma[TIM_DMA_ID_COMMUTATION]->XferErrorCallback = TIM_DMAError; + + /* Enable the Commutation DMA Request */ + __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_COM); + + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @brief Configures the TIM in master mode. + * @param htim TIM handle. + * @param sMasterConfig pointer to a TIM_MasterConfigTypeDef structure that + * contains the selected trigger output (TRGO) and the Master/Slave + * mode. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_MasterConfigSynchronization(TIM_HandleTypeDef *htim, + TIM_MasterConfigTypeDef * sMasterConfig) +{ + uint32_t tmpcr2; + uint32_t tmpsmcr; + + /* Check the parameters */ + assert_param(IS_TIM_SYNCHRO_INSTANCE(htim->Instance)); + assert_param(IS_TIM_TRGO_SOURCE(sMasterConfig->MasterOutputTrigger)); + assert_param(IS_TIM_MSM_STATE(sMasterConfig->MasterSlaveMode)); + + /* Check input state */ + __HAL_LOCK(htim); + + /* Get the TIMx CR2 register value */ + tmpcr2 = htim->Instance->CR2; + + /* Get the TIMx SMCR register value */ + tmpsmcr = htim->Instance->SMCR; + + /* If the timer supports ADC synchronization through TRGO2, set the master mode selection 2 */ + if (IS_TIM_TRGO2_INSTANCE(htim->Instance)) + { + /* Check the parameters */ + assert_param(IS_TIM_TRGO2_SOURCE(sMasterConfig->MasterOutputTrigger2)); + + /* Clear the MMS2 bits */ + tmpcr2 &= ~TIM_CR2_MMS2; + /* Select the TRGO2 source*/ + tmpcr2 |= sMasterConfig->MasterOutputTrigger2; + } + + /* Reset the MMS Bits */ + tmpcr2 &= ~TIM_CR2_MMS; + /* Select the TRGO source */ + tmpcr2 |= sMasterConfig->MasterOutputTrigger; + + /* Reset the MSM Bit */ + tmpsmcr &= ~TIM_SMCR_MSM; + /* Set master mode */ + tmpsmcr |= sMasterConfig->MasterSlaveMode; + + /* Update TIMx CR2 */ + htim->Instance->CR2 = tmpcr2; + + /* Update TIMx SMCR */ + htim->Instance->SMCR = tmpsmcr; + + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @brief Configures the Break feature, dead time, Lock level, OSSI/OSSR State + * and the AOE(automatic output enable). + * @param htim TIM handle + * @param sBreakDeadTimeConfig pointer to a TIM_ConfigBreakDeadConfigTypeDef structure that + * contains the BDTR Register configuration information for the TIM peripheral. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_ConfigBreakDeadTime(TIM_HandleTypeDef *htim, + TIM_BreakDeadTimeConfigTypeDef * sBreakDeadTimeConfig) +{ + uint32_t tmpbdtr = 0; + + /* Check the parameters */ + assert_param(IS_TIM_BREAK_INSTANCE(htim->Instance)); + assert_param(IS_TIM_OSSR_STATE(sBreakDeadTimeConfig->OffStateRunMode)); + assert_param(IS_TIM_OSSI_STATE(sBreakDeadTimeConfig->OffStateIDLEMode)); + assert_param(IS_TIM_LOCK_LEVEL(sBreakDeadTimeConfig->LockLevel)); + assert_param(IS_TIM_DEADTIME(sBreakDeadTimeConfig->DeadTime)); + assert_param(IS_TIM_BREAK_STATE(sBreakDeadTimeConfig->BreakState)); + assert_param(IS_TIM_BREAK_POLARITY(sBreakDeadTimeConfig->BreakPolarity)); + assert_param(IS_TIM_BREAK_FILTER(sBreakDeadTimeConfig->BreakFilter)); + assert_param(IS_TIM_AUTOMATIC_OUTPUT_STATE(sBreakDeadTimeConfig->AutomaticOutput)); + + /* Check input state */ + __HAL_LOCK(htim); + + /* Set the Lock level, the Break enable Bit and the Polarity, the OSSR State, + the OSSI State, the dead time value and the Automatic Output Enable Bit */ + + /* Set the BDTR bits */ + MODIFY_REG(tmpbdtr, TIM_BDTR_DTG, sBreakDeadTimeConfig->DeadTime); + MODIFY_REG(tmpbdtr, TIM_BDTR_LOCK, sBreakDeadTimeConfig->LockLevel); + MODIFY_REG(tmpbdtr, TIM_BDTR_OSSI, sBreakDeadTimeConfig->OffStateIDLEMode); + MODIFY_REG(tmpbdtr, TIM_BDTR_OSSR, sBreakDeadTimeConfig->OffStateRunMode); + MODIFY_REG(tmpbdtr, TIM_BDTR_BKE, sBreakDeadTimeConfig->BreakState); + MODIFY_REG(tmpbdtr, TIM_BDTR_BKP, sBreakDeadTimeConfig->BreakPolarity); + MODIFY_REG(tmpbdtr, TIM_BDTR_AOE, sBreakDeadTimeConfig->AutomaticOutput); + MODIFY_REG(tmpbdtr, TIM_BDTR_MOE, sBreakDeadTimeConfig->AutomaticOutput); + MODIFY_REG(tmpbdtr, TIM_BDTR_BKF, (sBreakDeadTimeConfig->BreakFilter << BDTR_BKF_SHIFT)); + + if (IS_TIM_BKIN2_INSTANCE(htim->Instance)) + { + /* Check the parameters */ + assert_param(IS_TIM_BREAK2_STATE(sBreakDeadTimeConfig->Break2State)); + assert_param(IS_TIM_BREAK2_POLARITY(sBreakDeadTimeConfig->Break2Polarity)); + assert_param(IS_TIM_BREAK_FILTER(sBreakDeadTimeConfig->Break2Filter)); + + /* Set the BREAK2 input related BDTR bits */ + MODIFY_REG(tmpbdtr, TIM_BDTR_BK2F, (sBreakDeadTimeConfig->Break2Filter << BDTR_BK2F_SHIFT)); + MODIFY_REG(tmpbdtr, TIM_BDTR_BK2E, sBreakDeadTimeConfig->Break2State); + MODIFY_REG(tmpbdtr, TIM_BDTR_BK2P, sBreakDeadTimeConfig->Break2Polarity); + } + + /* Set TIMx_BDTR */ + htim->Instance->BDTR = tmpbdtr; + + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @brief Configures the break input source. + * @param htim TIM handle. + * @param BreakInput Break input to configure + * This parameter can be one of the following values: + * @arg TIM_BREAKINPUT_BRK: Timer break input + * @arg TIM_BREAKINPUT_BRK2: Timer break 2 input + * @param sBreakInputConfig Break input source configuration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_ConfigBreakInput(TIM_HandleTypeDef *htim, + uint32_t BreakInput, + TIMEx_BreakInputConfigTypeDef *sBreakInputConfig) + +{ + uint32_t tmporx = 0; + uint32_t bkin_enable_mask = 0; + uint32_t bkin_polarity_mask = 0; + uint32_t bkin_enable_bitpos = 0; + uint32_t bkin_polarity_bitpos = 0; + + /* Check the parameters */ + assert_param(IS_TIM_BREAK_INSTANCE(htim->Instance)); + assert_param(IS_TIM_BREAKINPUT(BreakInput)); + assert_param(IS_TIM_BREAKINPUTSOURCE(sBreakInputConfig->Source)); + assert_param(IS_TIM_BREAKINPUTSOURCE_STATE(sBreakInputConfig->Enable)); + +#if defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || \ + defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + if (sBreakInputConfig->Source != TIM_BREAKINPUTSOURCE_DFSDM1) + { + assert_param(IS_TIM_BREAKINPUTSOURCE_POLARITY(sBreakInputConfig->Polarity)); + } +#else + assert_param(IS_TIM_BREAKINPUTSOURCE_POLARITY(sBreakInputConfig->Polarity)); +#endif /* STM32L451xx || STM32L452xx || STM32L462xx || */ + /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx || */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + + /* Check input state */ + __HAL_LOCK(htim); + + switch(sBreakInputConfig->Source) + { + case TIM_BREAKINPUTSOURCE_BKIN: + { + bkin_enable_mask = TIM1_OR2_BKINE; + bkin_enable_bitpos = 0; + bkin_polarity_mask = TIM1_OR2_BKINP; + bkin_polarity_bitpos = 9; + } + break; + case TIM_BREAKINPUTSOURCE_COMP1: + { + bkin_enable_mask = TIM1_OR2_BKCMP1E; + bkin_enable_bitpos = 1; + bkin_polarity_mask = TIM1_OR2_BKCMP1P; + bkin_polarity_bitpos = 10; + } + break; + case TIM_BREAKINPUTSOURCE_COMP2: + { + bkin_enable_mask = TIM1_OR2_BKCMP2E; + bkin_enable_bitpos = 2; + bkin_polarity_mask = TIM1_OR2_BKCMP2P; + bkin_polarity_bitpos = 11; + } + break; + +#if defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || \ + defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + case TIM_BREAKINPUTSOURCE_DFSDM1: + { + bkin_enable_mask = TIM1_OR2_BKDF1BK0E; + bkin_enable_bitpos = 8; + } + break; +#endif /* STM32L451xx || STM32L452xx || STM32L462xx || */ + /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx || */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + + default: + break; + } + + switch(BreakInput) + { + case TIM_BREAKINPUT_BRK: + { + /* Get the TIMx_OR2 register value */ + tmporx = htim->Instance->OR2; + + /* Enable the break input */ + tmporx &= ~bkin_enable_mask; + tmporx |= (sBreakInputConfig->Enable << bkin_enable_bitpos) & bkin_enable_mask; + + /* Set the break input polarity */ +#if defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || \ + defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + if (sBreakInputConfig->Source != TIM_BREAKINPUTSOURCE_DFSDM1) +#endif /* STM32L451xx || STM32L452xx || STM32L462xx || */ + /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx || */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + { + tmporx &= ~bkin_polarity_mask; + tmporx |= (sBreakInputConfig->Polarity << bkin_polarity_bitpos) & bkin_polarity_mask; + } + + /* Set TIMx_OR2 */ + htim->Instance->OR2 = tmporx; + } + break; + case TIM_BREAKINPUT_BRK2: + { + /* Get the TIMx_OR3 register value */ + tmporx = htim->Instance->OR3; + + /* Enable the break input */ + tmporx &= ~bkin_enable_mask; + tmporx |= (sBreakInputConfig->Enable << bkin_enable_bitpos) & bkin_enable_mask; + + /* Set the break input polarity */ +#if defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || \ + defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ + defined (STM32L496xx) || defined (STM32L4A6xx) || \ + defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) + if (sBreakInputConfig->Source != TIM_BREAKINPUTSOURCE_DFSDM1) +#endif /* STM32L451xx || STM32L452xx || STM32L462xx */ + /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + { + tmporx &= ~bkin_polarity_mask; + tmporx |= (sBreakInputConfig->Polarity << bkin_polarity_bitpos) & bkin_polarity_mask; + } + + /* Set TIMx_OR3 */ + htim->Instance->OR3 = tmporx; + } + break; + default: + break; + } + + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @brief Configures the TIMx Remapping input capabilities. + * @param htim TIM handle. + * @param Remap: specifies the TIM remapping source. + * + @if STM32L486xx + * For TIM1, the parameter is a combination of 4 fields (field1 | field2 | field3 | field4): + * + * field1 can have the following values: + * @arg TIM_TIM1_ETR_ADC1_NONE: TIM1_ETR is not connected to any ADC1 AWD (analog watchdog) + * @arg TIM_TIM1_ETR_ADC1_AWD1: TIM1_ETR is connected to ADC1 AWD1 + * @arg TIM_TIM1_ETR_ADC1_AWD2: TIM1_ETR is connected to ADC1 AWD2 + * @arg TIM_TIM1_ETR_ADC1_AWD3: TIM1_ETR is connected to ADC1 AWD3 + * + * field2 can have the following values: + * @arg TIM_TIM1_ETR_ADC3_NONE: TIM1_ETR is not connected to any ADC3 AWD (analog watchdog) + * @arg TIM_TIM1_ETR_ADC3_AWD1: TIM1_ETR is connected to ADC3 AWD1 + * @arg TIM_TIM1_ETR_ADC3_AWD2: TIM1_ETR is connected to ADC3 AWD2 + * @arg TIM_TIM1_ETR_ADC3_AWD3: TIM1_ETR is connected to ADC3 AWD3 + * + * field3 can have the following values: + * @arg TIM_TIM1_TI1_GPIO: TIM1 TI1 is connected to GPIO + * @arg TIM_TIM1_TI1_COMP1: TIM1 TI1 is connected to COMP1 output + * + * field4 can have the following values: + * @arg TIM_TIM1_ETR_COMP1: TIM1_ETR is connected to COMP1 output + * @arg TIM_TIM1_ETR_COMP2: TIM1_ETR is connected to COMP2 output + * @note When field4 is set to TIM_TIM1_ETR_COMP1 or TIM_TIM1_ETR_COMP2 field1 and field2 values are not significant + @endif + @if STM32L443xx + * For TIM1, the parameter is a combination of 3 fields (field1 | field2 | field3): + * + * field1 can have the following values: + * @arg TIM_TIM1_ETR_ADC1_NONE: TIM1_ETR is not connected to any ADC1 AWD (analog watchdog) + * @arg TIM_TIM1_ETR_ADC1_AWD1: TIM1_ETR is connected to ADC1 AWD1 + * @arg TIM_TIM1_ETR_ADC1_AWD2: TIM1_ETR is connected to ADC1 AWD2 + * @arg TIM_TIM1_ETR_ADC1_AWD3: TIM1_ETR is connected to ADC1 AWD3 + * + * field2 can have the following values: + * @arg TIM_TIM1_TI1_GPIO: TIM1 TI1 is connected to GPIO + * @arg TIM_TIM1_TI1_COMP1: TIM1 TI1 is connected to COMP1 output + * + * field3 can have the following values: + * @arg TIM_TIM1_ETR_COMP1: TIM1_ETR is connected to COMP1 output + * @arg TIM_TIM1_ETR_COMP2: TIM1_ETR is connected to COMP2 output + * + * @note When field3 is set to TIM_TIM1_ETR_COMP1 or TIM_TIM1_ETR_COMP2 field1 values is not significant + * + @endif + @if STM32L486xx + * For TIM2, the parameter is a combination of 3 fields (field1 | field2 | field3): + * + * field1 can have the following values: + * @arg TIM_TIM2_ITR1_TIM8_TRGO: TIM2_ITR1 is connected to TIM8_TRGO + * @arg TIM_TIM2_ITR1_OTG_FS_SOF: TIM2_ITR1 is connected to OTG_FS SOF + * + * field2 can have the following values: + * @arg TIM_TIM2_ETR_GPIO: TIM2_ETR is connected to GPIO + * @arg TIM_TIM2_ETR_LSE: TIM2_ETR is connected to LSE + * @arg TIM_TIM2_ETR_COMP1: TIM2_ETR is connected to COMP1 output + * @arg TIM_TIM2_ETR_COMP2: TIM2_ETR is connected to COMP2 output + * + * field3 can have the following values: + * @arg TIM_TIM2_TI4_GPIO: TIM2 TI4 is connected to GPIO + * @arg TIM_TIM2_TI4_COMP1: TIM2 TI4 is connected to COMP1 output + * @arg TIM_TIM2_TI4_COMP2: TIM2 TI4 is connected to COMP2 output + * @arg TIM_TIM2_TI4_COMP1_COMP2: TIM2 TI4 is connected to logical OR between COMP1 and COMP2 output + @endif + @if STM32L443xx + * For TIM2, the parameter is a combination of 3 fields (field1 | field2 | field3): + * + * field1 can have the following values: + * @arg TIM_TIM2_ITR1_NONE: No internal trigger on TIM2_ITR1 + * @arg TIM_TIM2_ITR1_USB_SOF: TIM2_ITR1 is connected to USB SOF + * + * field2 can have the following values: + * @arg TIM_TIM2_ETR_GPIO: TIM2_ETR is connected to GPIO + * @arg TIM_TIM2_ETR_LSE: TIM2_ETR is connected to LSE + * @arg TIM_TIM2_ETR_COMP1: TIM2_ETR is connected to COMP1 output + * @arg TIM_TIM2_ETR_COMP2: TIM2_ETR is connected to COMP2 output + * + * field3 can have the following values: + * @arg TIM_TIM2_TI4_GPIO: TIM2 TI4 is connected to GPIO + * @arg TIM_TIM2_TI4_COMP1: TIM2 TI4 is connected to COMP1 output + * @arg TIM_TIM2_TI4_COMP2: TIM2 TI4 is connected to COMP2 output + * @arg TIM_TIM2_TI4_COMP1_COMP2: TIM2 TI4 is connected to logical OR between COMP1 and COMP2 output + * + @endif + @if STM32L486xx + * For TIM3, the parameter is a combination 2 fields(field1 | field2): + * + * field1 can have the following values: + * @arg TIM_TIM3_TI1_GPIO: TIM3 TI1 is connected to GPIO + * @arg TIM_TIM3_TI1_COMP1: TIM3 TI1 is connected to COMP1 output + * @arg TIM_TIM3_TI1_COMP2: TIM3 TI1 is connected to COMP2 output + * @arg TIM_TIM3_TI1_COMP1_COMP2: TIM3 TI1 is connected to logical OR between COMP1 and COMP2 output + * + * field2 can have the following values: + * @arg TIM_TIM3_ETR_GPIO: TIM3_ETR is connected to GPIO + * @arg TIM_TIM3_ETR_COMP1: TIM3_ETR is connected to COMP1 output + * + @endif + @if STM32L486xx + * For TIM8, the parameter is a combination of 3 fields (field1 | field2 | field3): + * + * field1 can have the following values: + * @arg TIM_TIM8_ETR_ADC2_NONE: TIM8_ETR is not connected to any ADC2 AWD (analog watchdog) + * @arg TIM_TIM8_ETR_ADC2_AWD1: TIM8_ETR is connected to ADC2 AWD1 + * @arg TIM_TIM8_ETR_ADC2_AWD2: TIM8_ETR is connected to ADC2 AWD2 + * @arg TIM_TIM8_ETR_ADC2_AWD3: TIM8_ETR is connected to ADC2 AWD3 + * + * field2 can have the following values: + * @arg TIM_TIM8_ETR_ADC3_NONE: TIM8_ETR is not connected to any ADC3 AWD (analog watchdog) + * @arg TIM_TIM8_ETR_ADC3_AWD1: TIM8_ETR is connected to ADC3 AWD1 + * @arg TIM_TIM8_ETR_ADC3_AWD2: TIM8_ETR is connected to ADC3 AWD2 + * @arg TIM_TIM8_ETR_ADC3_AWD3: TIM8_ETR is connected to ADC3 AWD3 + * + * field3 can have the following values: + * @arg TIM_TIM8_TI1_GPIO: TIM8 TI1 is connected to GPIO + * @arg TIM_TIM8_TI1_COMP2: TIM8 TI1 is connected to COMP2 output + * + * field4 can have the following values: + * @arg TIM_TIM8_ETR_COMP1: TIM8_ETR is connected to COMP1 output + * @arg TIM_TIM8_ETR_COMP2: TIM8_ETR is connected to COMP2 output + * @note When field4 is set to TIM_TIM8_ETR_COMP1 or TIM_TIM8_ETR_COMP2 field1 and field2 values are not significant + * + @endif + * For TIM15, the parameter is a combination of 3 fields (field1 | field2): + * + * field1 can have the following values: + * @arg TIM_TIM15_TI1_GPIO: TIM15 TI1 is connected to GPIO + * @arg TIM_TIM15_TI1_LSE: TIM15 TI1 is connected to LSE + * + * field2 can have the following values: + * @arg TIM_TIM15_ENCODERMODE_NONE: No redirection + * @arg TIM_TIM15_ENCODERMODE_TIM2: TIM2 IC1 and TIM2 IC2 are connected to TIM15 IC1 and TIM15 IC2 respectively + * @arg TIM_TIM15_ENCODERMODE_TIM3: TIM3 IC1 and TIM3 IC2 are connected to TIM15 IC1 and TIM15 IC2 respectively + * @arg TIM_TIM15_ENCODERMODE_TIM4: TIM4 IC1 and TIM4 IC2 are connected to TIM15 IC1 and TIM15 IC2 respectively + * + @if STM32L486xx + * @arg TIM_TIM16_TI1_GPIO: TIM16 TI1 is connected to GPIO + * @arg TIM_TIM16_TI1_LSI: TIM16 TI1 is connected to LSI + * @arg TIM_TIM16_TI1_LSE: TIM16 TI1 is connected to LSE + * @arg TIM_TIM16_TI1_RTC: TIM16 TI1 is connected to RTC wakeup interrupt + * + @endif + @if STM32L443xx + * For TIM16, the parameter can have the following values: + * @arg TIM_TIM16_TI1_GPIO: TIM16 TI1 is connected to GPIO + * @arg TIM_TIM16_TI1_LSI: TIM16 TI1 is connected to LSI + * @arg TIM_TIM16_TI1_LSE: TIM16 TI1 is connected to LSE + * @arg TIM_TIM16_TI1_RTC: TIM16 TI1 is connected to RTC wakeup interrupt + * @arg TIM_TIM16_TI1_MSI: TIM16 TI1 is connected to MSI (contraints: MSI clock < 1/4 TIM APB clock) + * @arg TIM_TIM16_TI1_HSE_32: TIM16 TI1 is connected to HSE div 32 (note that HSE div 32 must be selected as RTC clock source) + * @arg TIM_TIM16_TI1_MCO: TIM16 TI1 is connected to MCO + * + @endif + @if STM32L486xx + * For TIM17, the parameter can have the following values: + * @arg TIM_TIM17_TI1_GPIO: TIM17 TI1 is connected to GPIO + * @arg TIM_TIM17_TI1_MSI: TIM17 TI1 is connected to MSI (contraints: MSI clock < 1/4 TIM APB clock) + * @arg TIM_TIM17_TI1_HSE_32: TIM17 TI1 is connected to HSE div 32 + * @arg TIM_TIM17_TI1_MCO: TIM17 TI1 is connected to MCO + @endif + * + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_RemapConfig(TIM_HandleTypeDef *htim, uint32_t Remap) +{ + uint32_t tmpor1 = 0; + uint32_t tmpor2 = 0; + + __HAL_LOCK(htim); + + /* Check parameters */ + assert_param(IS_TIM_REMAP_INSTANCE(htim->Instance)); + assert_param(IS_TIM_REMAP(Remap)); + + /* Set ETR_SEL bit field (if required) */ + if (IS_TIM_ETRSEL_INSTANCE(htim->Instance)) + { + tmpor2 = htim->Instance->OR2; + tmpor2 &= ~TIMx_ETRSEL_MASK; + tmpor2 |= (Remap & TIMx_ETRSEL_MASK); + + /* Set TIMx_OR2 */ + htim->Instance->OR2 = tmpor2; + } + + /* Set other remapping capabilities */ + tmpor1 = Remap; + tmpor1 &= ~TIMx_ETRSEL_MASK; + + /* Set TIMx_OR1 */ + htim->Instance->OR1 = tmpor1; + + htim->State = HAL_TIM_STATE_READY; + + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @brief Group channel 5 and channel 1, 2 or 3 + * @param htim TIM handle. + * @param Channels specifies the reference signal(s) the OC5REF is combined with. + * This parameter can be any combination of the following values: + * TIM_GROUPCH5_NONE: No effect of OC5REF on OC1REFC, OC2REFC and OC3REFC + * TIM_GROUPCH5_OC1REFC: OC1REFC is the logical AND of OC1REFC and OC5REF + * TIM_GROUPCH5_OC2REFC: OC2REFC is the logical AND of OC2REFC and OC5REF + * TIM_GROUPCH5_OC3REFC: OC3REFC is the logical AND of OC3REFC and OC5REF + * @retval HAL status + */ +HAL_StatusTypeDef HAL_TIMEx_GroupChannel5(TIM_HandleTypeDef *htim, uint32_t Channels) +{ + /* Check parameters */ + assert_param(IS_TIM_COMBINED3PHASEPWM_INSTANCE(htim->Instance)); + assert_param(IS_TIM_GROUPCH5(Channels)); + + /* Process Locked */ + __HAL_LOCK(htim); + + htim->State = HAL_TIM_STATE_BUSY; + + /* Clear GC5Cx bit fields */ + htim->Instance->CCR5 &= ~(TIM_CCR5_GC5C3|TIM_CCR5_GC5C2|TIM_CCR5_GC5C1); + + /* Set GC5Cx bit fields */ + htim->Instance->CCR5 |= Channels; + + htim->State = HAL_TIM_STATE_READY; + + __HAL_UNLOCK(htim); + + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup TIMEx_Exported_Functions_Group6 Extended Callbacks functions + * @brief Extended Callbacks functions + * +@verbatim + ============================================================================== + ##### Extended Callbacks functions ##### + ============================================================================== + [..] + This section provides Extended TIM callback functions: + (+) Timer Commutation callback + (+) Timer Break callback + +@endverbatim + * @{ + */ + +/** + * @brief Hall commutation changed callback in non-blocking mode + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIMEx_CommutationCallback(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_TIMEx_CommutationCallback could be implemented in the user file + */ +} + +/** + * @brief Hall Break detection callback in non-blocking mode + * @param htim TIM handle + * @retval None + */ +__weak void HAL_TIMEx_BreakCallback(TIM_HandleTypeDef *htim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(htim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_TIMEx_BreakCallback could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup TIMEx_Exported_Functions_Group7 Extended Peripheral State functions + * @brief Extended Peripheral State functions + * +@verbatim + ============================================================================== + ##### Extended Peripheral State functions ##### + ============================================================================== + [..] + This subsection permits to get in run-time the status of the peripheral + and the data flow. + +@endverbatim + * @{ + */ + +/** + * @brief Return the TIM Hall Sensor interface handle state. + * @param htim TIM Hall Sensor handle + * @retval HAL state + */ +HAL_TIM_StateTypeDef HAL_TIMEx_HallSensor_GetState(TIM_HandleTypeDef *htim) +{ + return htim->State; +} + +/** + * @} + */ + +/** + * @brief TIM DMA Commutation callback. + * @param hdma pointer to DMA handle. + * @retval None + */ +void TIMEx_DMACommutationCplt(DMA_HandleTypeDef *hdma) +{ + TIM_HandleTypeDef* htim = ( TIM_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; + + htim->State= HAL_TIM_STATE_READY; + + HAL_TIMEx_CommutationCallback(htim); +} + +/** + * @brief Enables or disables the TIM Capture Compare Channel xN. + * @param TIMx to select the TIM peripheral + * @param Channel specifies the TIM Channel + * This parameter can be one of the following values: + * @arg TIM_Channel_1: TIM Channel 1 + * @arg TIM_Channel_2: TIM Channel 2 + * @arg TIM_Channel_3: TIM Channel 3 + * @param ChannelNState specifies the TIM Channel CCxNE bit new state. + * This parameter can be: TIM_CCxN_ENABLE or TIM_CCxN_Disable. + * @retval None + */ +static void TIM_CCxNChannelCmd(TIM_TypeDef* TIMx, uint32_t Channel, uint32_t ChannelNState) +{ + uint32_t tmp = 0; + + tmp = TIM_CCER_CC1NE << Channel; + + /* Reset the CCxNE Bit */ + TIMx->CCER &= ~tmp; + + /* Set or reset the CCxNE Bit */ + TIMx->CCER |= (uint32_t)(ChannelNState << Channel); +} + +/** + * @} + */ + +#endif /* HAL_TIM_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_uart.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_uart.c new file mode 100644 index 0000000..7cbb858 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_uart.c @@ -0,0 +1,3448 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_uart.c + * @author MCD Application Team + * @brief UART HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Universal Asynchronous Receiver Transmitter Peripheral (UART). + * + Initialization and de-initialization functions + * + IO operation functions + * + Peripheral Control functions + * + * + @verbatim + =============================================================================== + ##### How to use this driver ##### + =============================================================================== + [..] + The UART HAL driver can be used as follows: + + (#) Declare a UART_HandleTypeDef handle structure (eg. UART_HandleTypeDef huart). + (#) Initialize the UART low level resources by implementing the HAL_UART_MspInit() API: + (++) Enable the USARTx interface clock. + (++) UART pins configuration: + (+++) Enable the clock for the UART GPIOs. + (+++) Configure these UART pins as alternate function pull-up. + (++) NVIC configuration if you need to use interrupt process (HAL_UART_Transmit_IT() + and HAL_UART_Receive_IT() APIs): + (+++) Configure the USARTx interrupt priority. + (+++) Enable the NVIC USART IRQ handle. + (++) UART interrupts handling: + -@@- The specific UART interrupts (Transmission complete interrupt, + RXNE interrupt, RX/TX FIFOs related interrupts and Error Interrupts) + are managed using the macros __HAL_UART_ENABLE_IT() and __HAL_UART_DISABLE_IT() + inside the transmit and receive processes. + (++) DMA Configuration if you need to use DMA process (HAL_UART_Transmit_DMA() + and HAL_UART_Receive_DMA() APIs): + (+++) Declare a DMA handle structure for the Tx/Rx channel. + (+++) Enable the DMAx interface clock. + (+++) Configure the declared DMA handle structure with the required Tx/Rx parameters. + (+++) Configure the DMA Tx/Rx channel. + (+++) Associate the initialized DMA handle to the UART DMA Tx/Rx handle. + (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the DMA Tx/Rx channel. + + (#) Program the Baud Rate, Word Length, Stop Bit, Parity, Prescaler value , Hardware + flow control and Mode (Receiver/Transmitter) in the huart handle Init structure. + + (#) If required, program UART advanced features (TX/RX pins swap, auto Baud rate detection,...) + in the huart handle AdvancedInit structure. + + (#) For the UART asynchronous mode, initialize the UART registers by calling + the HAL_UART_Init() API. + + (#) For the UART Half duplex mode, initialize the UART registers by calling + the HAL_HalfDuplex_Init() API. + + (#) For the UART LIN (Local Interconnection Network) mode, initialize the UART registers + by calling the HAL_LIN_Init() API. + + (#) For the UART Multiprocessor mode, initialize the UART registers + by calling the HAL_MultiProcessor_Init() API. + + (#) For the UART RS485 Driver Enabled mode, initialize the UART registers + by calling the HAL_RS485Ex_Init() API. + + [..] + (@) These API's (HAL_UART_Init(), HAL_HalfDuplex_Init(), HAL_LIN_Init(), HAL_MultiProcessor_Init(), + also configure the low level Hardware GPIO, CLOCK, CORTEX...etc) by + calling the customized HAL_UART_MspInit() API. + + @endverbatim + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup UART UART + * @brief HAL UART module driver + * @{ + */ + +#ifdef HAL_UART_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/** @defgroup UART_Private_Constants UART Private Constants + * @{ + */ +#if defined(USART_CR1_FIFOEN) +#define USART_CR1_FIELDS ((uint32_t)(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | \ + USART_CR1_TE | USART_CR1_RE | USART_CR1_OVER8| \ + USART_CR1_FIFOEN )) /*!< UART or USART CR1 fields of parameters set by UART_SetConfig API */ +#else +#define USART_CR1_FIELDS ((uint32_t)(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | \ + USART_CR1_TE | USART_CR1_RE | USART_CR1_OVER8 )) /*!< UART or USART CR1 fields of parameters set by UART_SetConfig API */ +#endif + +#if defined(USART_CR1_FIFOEN) +#define USART_CR3_FIELDS ((uint32_t)(USART_CR3_RTSE | USART_CR3_CTSE | USART_CR3_ONEBIT| \ + USART_CR3_TXFTCFG | USART_CR3_RXFTCFG )) /*!< UART or USART CR3 fields of parameters set by UART_SetConfig API */ +#else +#define USART_CR3_FIELDS ((uint32_t)(USART_CR3_RTSE | USART_CR3_CTSE | USART_CR3_ONEBIT)) /*!< UART or USART CR3 fields of parameters set by UART_SetConfig API */ +#endif + +#define LPUART_BRR_MIN 0x00000300U /* LPUART BRR minimum authorized value */ +#define LPUART_BRR_MAX 0x000FFFFFU /* LPUART BRR maximum authorized value */ + +#define UART_BRR_MIN 0x10U /* UART BRR minimum authorized value */ +#define UART_BRR_MAX 0x0000FFFFU /* UART BRR maximum authorized value */ + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/** @addtogroup UART_Private_Functions + * @{ + */ +static void UART_EndTxTransfer(UART_HandleTypeDef *huart); +static void UART_EndRxTransfer(UART_HandleTypeDef *huart); +static void UART_DMATransmitCplt(DMA_HandleTypeDef *hdma); +static void UART_DMAReceiveCplt(DMA_HandleTypeDef *hdma); +static void UART_DMARxHalfCplt(DMA_HandleTypeDef *hdma); +static void UART_DMATxHalfCplt(DMA_HandleTypeDef *hdma); +static void UART_DMAError(DMA_HandleTypeDef *hdma); +static void UART_DMAAbortOnError(DMA_HandleTypeDef *hdma); +static void UART_DMATxAbortCallback(DMA_HandleTypeDef *hdma); +static void UART_DMARxAbortCallback(DMA_HandleTypeDef *hdma); +static void UART_DMATxOnlyAbortCallback(DMA_HandleTypeDef *hdma); +static void UART_DMARxOnlyAbortCallback(DMA_HandleTypeDef *hdma); +static void UART_TxISR_8BIT(UART_HandleTypeDef *huart); +static void UART_TxISR_16BIT(UART_HandleTypeDef *huart); +#if defined(USART_CR1_FIFOEN) +static void UART_TxISR_8BIT_FIFOEN(UART_HandleTypeDef *huart); +static void UART_TxISR_16BIT_FIFOEN(UART_HandleTypeDef *huart); +#endif +static void UART_EndTransmit_IT(UART_HandleTypeDef *huart); +static void UART_RxISR_8BIT(UART_HandleTypeDef *huart); +static void UART_RxISR_16BIT(UART_HandleTypeDef *huart); +#if defined(USART_CR1_FIFOEN) +static void UART_RxISR_8BIT_FIFOEN(UART_HandleTypeDef *huart); +static void UART_RxISR_16BIT_FIFOEN(UART_HandleTypeDef *huart); +#endif + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup UART_Exported_Functions UART Exported Functions + * @{ + */ + +/** @defgroup UART_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions + * +@verbatim +=============================================================================== + ##### Initialization and Configuration functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to initialize the USARTx or the UARTy + in asynchronous mode. + (+) For the asynchronous mode the parameters below can be configured: + (++) Baud Rate + (++) Word Length + (++) Stop Bit + (++) Parity: If the parity is enabled, then the MSB bit of the data written + in the data register is transmitted but is changed by the parity bit. + (++) Hardware flow control + (++) Receiver/transmitter modes + (++) Over Sampling Method + (++) One-Bit Sampling Method + (+) For the asynchronous mode, the following advanced features can be configured as well: + (++) TX and/or RX pin level inversion + (++) data logical level inversion + (++) RX and TX pins swap + (++) RX overrun detection disabling + (++) DMA disabling on RX error + (++) MSB first on communication line + (++) auto Baud rate detection + [..] + The HAL_UART_Init(), HAL_HalfDuplex_Init(), HAL_LIN_Init()and HAL_MultiProcessor_Init()API + follow respectively the UART asynchronous, UART Half duplex, UART LIN mode + and UART multiprocessor mode configuration procedures (details for the procedures + are available in reference manual). + +@endverbatim + + Depending on the frame length defined by the M1 and M0 bits (7-bit, + 8-bit or 9-bit), the possible UART formats are listed in the + following table. + + Table 1. UART frame format. + +-----------------------------------------------------------------------+ + | M1 bit | M0 bit | PCE bit | UART frame | + |---------|---------|-----------|---------------------------------------| + | 0 | 0 | 0 | | SB | 8 bit data | STB | | + |---------|---------|-----------|---------------------------------------| + | 0 | 0 | 1 | | SB | 7 bit data | PB | STB | | + |---------|---------|-----------|---------------------------------------| + | 0 | 1 | 0 | | SB | 9 bit data | STB | | + |---------|---------|-----------|---------------------------------------| + | 0 | 1 | 1 | | SB | 8 bit data | PB | STB | | + |---------|---------|-----------|---------------------------------------| + | 1 | 0 | 0 | | SB | 7 bit data | STB | | + |---------|---------|-----------|---------------------------------------| + | 1 | 0 | 1 | | SB | 6 bit data | PB | STB | | + +-----------------------------------------------------------------------+ + + * @{ + */ + +/** + * @brief Initialize the UART mode according to the specified + * parameters in the UART_InitTypeDef and initialize the associated handle. + * @param huart UART handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart) +{ + /* Check the UART handle allocation */ + if(huart == NULL) + { + return HAL_ERROR; + } + + if(huart->Init.HwFlowCtl != UART_HWCONTROL_NONE) + { + /* Check the parameters */ + assert_param(IS_UART_HWFLOW_INSTANCE(huart->Instance)); + } + else + { + /* Check the parameters */ + assert_param((IS_UART_INSTANCE(huart->Instance)) || (IS_LPUART_INSTANCE(huart->Instance))); + } + + if(huart->gState == HAL_UART_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + huart->Lock = HAL_UNLOCKED; + + /* Init the low level hardware : GPIO, CLOCK */ + HAL_UART_MspInit(huart); + } + + huart->gState = HAL_UART_STATE_BUSY; + + /* Disable the Peripheral */ + __HAL_UART_DISABLE(huart); + + /* Set the UART Communication parameters */ + if (UART_SetConfig(huart) == HAL_ERROR) + { + return HAL_ERROR; + } + + if (huart->AdvancedInit.AdvFeatureInit != UART_ADVFEATURE_NO_INIT) + { + UART_AdvFeatureConfig(huart); + } + + /* In asynchronous mode, the following bits must be kept cleared: + - LINEN and CLKEN bits in the USART_CR2 register, + - SCEN, HDSEL and IREN bits in the USART_CR3 register.*/ + CLEAR_BIT(huart->Instance->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN)); + CLEAR_BIT(huart->Instance->CR3, (USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN)); + + /* Enable the Peripheral */ + __HAL_UART_ENABLE(huart); + + /* TEACK and/or REACK to check before moving huart->gState and huart->RxState to Ready */ + return (UART_CheckIdleState(huart)); +} + +/** + * @brief Initialize the half-duplex mode according to the specified + * parameters in the UART_InitTypeDef and creates the associated handle. + * @param huart UART handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HalfDuplex_Init(UART_HandleTypeDef *huart) +{ + /* Check the UART handle allocation */ + if(huart == NULL) + { + return HAL_ERROR; + } + + /* Check UART instance */ + assert_param(IS_UART_HALFDUPLEX_INSTANCE(huart->Instance)); + + if(huart->gState == HAL_UART_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + huart->Lock = HAL_UNLOCKED; + + /* Init the low level hardware : GPIO, CLOCK */ + HAL_UART_MspInit(huart); + } + + huart->gState = HAL_UART_STATE_BUSY; + + /* Disable the Peripheral */ + __HAL_UART_DISABLE(huart); + + /* Set the UART Communication parameters */ + if (UART_SetConfig(huart) == HAL_ERROR) + { + return HAL_ERROR; + } + + if (huart->AdvancedInit.AdvFeatureInit != UART_ADVFEATURE_NO_INIT) + { + UART_AdvFeatureConfig(huart); + } + + /* In half-duplex mode, the following bits must be kept cleared: + - LINEN and CLKEN bits in the USART_CR2 register, + - SCEN and IREN bits in the USART_CR3 register.*/ + CLEAR_BIT(huart->Instance->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN)); + CLEAR_BIT(huart->Instance->CR3, (USART_CR3_IREN | USART_CR3_SCEN)); + + /* Enable the Half-Duplex mode by setting the HDSEL bit in the CR3 register */ + SET_BIT(huart->Instance->CR3, USART_CR3_HDSEL); + + /* Enable the Peripheral */ + __HAL_UART_ENABLE(huart); + + /* TEACK and/or REACK to check before moving huart->gState and huart->RxState to Ready */ + return (UART_CheckIdleState(huart)); +} + + +/** + * @brief Initialize the LIN mode according to the specified + * parameters in the UART_InitTypeDef and creates the associated handle . + * @param huart UART handle. + * @param BreakDetectLength Specifies the LIN break detection length. + * This parameter can be one of the following values: + * @arg @ref UART_LINBREAKDETECTLENGTH_10B 10-bit break detection + * @arg @ref UART_LINBREAKDETECTLENGTH_11B 11-bit break detection + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LIN_Init(UART_HandleTypeDef *huart, uint32_t BreakDetectLength) +{ + /* Check the UART handle allocation */ + if(huart == NULL) + { + return HAL_ERROR; + } + + /* Check the LIN UART instance */ + assert_param(IS_UART_LIN_INSTANCE(huart->Instance)); + /* Check the Break detection length parameter */ + assert_param(IS_UART_LIN_BREAK_DETECT_LENGTH(BreakDetectLength)); + + /* LIN mode limited to 16-bit oversampling only */ + if(huart->Init.OverSampling == UART_OVERSAMPLING_8) + { + return HAL_ERROR; + } + /* LIN mode limited to 8-bit data length */ + if(huart->Init.WordLength != UART_WORDLENGTH_8B) + { + return HAL_ERROR; + } + + if(huart->gState == HAL_UART_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + huart->Lock = HAL_UNLOCKED; + + /* Init the low level hardware : GPIO, CLOCK */ + HAL_UART_MspInit(huart); + } + + huart->gState = HAL_UART_STATE_BUSY; + + /* Disable the Peripheral */ + __HAL_UART_DISABLE(huart); + + /* Set the UART Communication parameters */ + if (UART_SetConfig(huart) == HAL_ERROR) + { + return HAL_ERROR; + } + + if (huart->AdvancedInit.AdvFeatureInit != UART_ADVFEATURE_NO_INIT) + { + UART_AdvFeatureConfig(huart); + } + + /* In LIN mode, the following bits must be kept cleared: + - LINEN and CLKEN bits in the USART_CR2 register, + - SCEN and IREN bits in the USART_CR3 register.*/ + CLEAR_BIT(huart->Instance->CR2, USART_CR2_CLKEN); + CLEAR_BIT(huart->Instance->CR3, (USART_CR3_HDSEL | USART_CR3_IREN | USART_CR3_SCEN)); + + /* Enable the LIN mode by setting the LINEN bit in the CR2 register */ + SET_BIT(huart->Instance->CR2, USART_CR2_LINEN); + + /* Set the USART LIN Break detection length. */ + MODIFY_REG(huart->Instance->CR2, USART_CR2_LBDL, BreakDetectLength); + + /* Enable the Peripheral */ + __HAL_UART_ENABLE(huart); + + /* TEACK and/or REACK to check before moving huart->gState and huart->RxState to Ready */ + return (UART_CheckIdleState(huart)); +} + + +/** + * @brief Initialize the multiprocessor mode according to the specified + * parameters in the UART_InitTypeDef and initialize the associated handle. + * @param huart UART handle. + * @param Address UART node address (4-, 6-, 7- or 8-bit long). + * @param WakeUpMethod Specifies the UART wakeup method. + * This parameter can be one of the following values: + * @arg @ref UART_WAKEUPMETHOD_IDLELINE WakeUp by an idle line detection + * @arg @ref UART_WAKEUPMETHOD_ADDRESSMARK WakeUp by an address mark + * @note If the user resorts to idle line detection wake up, the Address parameter + * is useless and ignored by the initialization function. + * @note If the user resorts to address mark wake up, the address length detection + * is configured by default to 4 bits only. For the UART to be able to + * manage 6-, 7- or 8-bit long addresses detection, the API + * HAL_MultiProcessorEx_AddressLength_Set() must be called after + * HAL_MultiProcessor_Init(). + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MultiProcessor_Init(UART_HandleTypeDef *huart, uint8_t Address, uint32_t WakeUpMethod) +{ + /* Check the UART handle allocation */ + if(huart == NULL) + { + return HAL_ERROR; + } + + /* Check the wake up method parameter */ + assert_param(IS_UART_WAKEUPMETHOD(WakeUpMethod)); + + if(huart->gState == HAL_UART_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + huart->Lock = HAL_UNLOCKED; + + /* Init the low level hardware : GPIO, CLOCK */ + HAL_UART_MspInit(huart); + } + + huart->gState = HAL_UART_STATE_BUSY; + + /* Disable the Peripheral */ + __HAL_UART_DISABLE(huart); + + /* Set the UART Communication parameters */ + if (UART_SetConfig(huart) == HAL_ERROR) + { + return HAL_ERROR; + } + + if (huart->AdvancedInit.AdvFeatureInit != UART_ADVFEATURE_NO_INIT) + { + UART_AdvFeatureConfig(huart); + } + + /* In multiprocessor mode, the following bits must be kept cleared: + - LINEN and CLKEN bits in the USART_CR2 register, + - SCEN, HDSEL and IREN bits in the USART_CR3 register. */ + CLEAR_BIT(huart->Instance->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN)); + CLEAR_BIT(huart->Instance->CR3, (USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN)); + + if (WakeUpMethod == UART_WAKEUPMETHOD_ADDRESSMARK) + { + /* If address mark wake up method is chosen, set the USART address node */ + MODIFY_REG(huart->Instance->CR2, USART_CR2_ADD, ((uint32_t)Address << UART_CR2_ADDRESS_LSB_POS)); + } + + /* Set the wake up method by setting the WAKE bit in the CR1 register */ + MODIFY_REG(huart->Instance->CR1, USART_CR1_WAKE, WakeUpMethod); + + /* Enable the Peripheral */ + __HAL_UART_ENABLE(huart); + + /* TEACK and/or REACK to check before moving huart->gState and huart->RxState to Ready */ + return (UART_CheckIdleState(huart)); +} + + +/** + * @brief DeInitialize the UART peripheral. + * @param huart UART handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_DeInit(UART_HandleTypeDef *huart) +{ + /* Check the UART handle allocation */ + if(huart == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param((IS_UART_INSTANCE(huart->Instance)) || (IS_LPUART_INSTANCE(huart->Instance))); + + huart->gState = HAL_UART_STATE_BUSY; + + /* Disable the Peripheral */ + __HAL_UART_DISABLE(huart); + + huart->Instance->CR1 = 0x0U; + huart->Instance->CR2 = 0x0U; + huart->Instance->CR3 = 0x0U; + + /* DeInit the low level hardware */ + HAL_UART_MspDeInit(huart); + + huart->ErrorCode = HAL_UART_ERROR_NONE; + huart->gState = HAL_UART_STATE_RESET; + huart->RxState = HAL_UART_STATE_RESET; + + /* Process Unlock */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +/** + * @brief Initialize the UART MSP. + * @param huart UART handle. + * @retval None + */ +__weak void HAL_UART_MspInit(UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_UART_MspInit can be implemented in the user file + */ +} + +/** + * @brief DeInitialize the UART MSP. + * @param huart UART handle. + * @retval None + */ +__weak void HAL_UART_MspDeInit(UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_UART_MspDeInit can be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup UART_Exported_Functions_Group2 IO operation functions + * @brief UART Transmit/Receive functions + * +@verbatim + =============================================================================== + ##### IO operation functions ##### + =============================================================================== + This subsection provides a set of functions allowing to manage the UART asynchronous + and Half duplex data transfers. + + (#) There are two mode of transfer: + (+) Blocking mode: The communication is performed in polling mode. + The HAL status of all data processing is returned by the same function + after finishing transfer. + (+) Non-Blocking mode: The communication is performed using Interrupts + or DMA, These API's return the HAL status. + The end of the data processing will be indicated through the + dedicated UART IRQ when using Interrupt mode or the DMA IRQ when + using DMA mode. + The HAL_UART_TxCpltCallback(), HAL_UART_RxCpltCallback() user callbacks + will be executed respectively at the end of the transmit or Receive process + The HAL_UART_ErrorCallback()user callback will be executed when a communication error is detected + + (#) Blocking mode API's are : + (+) HAL_UART_Transmit() + (+) HAL_UART_Receive() + + (#) Non-Blocking mode API's with Interrupt are : + (+) HAL_UART_Transmit_IT() + (+) HAL_UART_Receive_IT() + (+) HAL_UART_IRQHandler() + + (#) Non-Blocking mode API's with DMA are : + (+) HAL_UART_Transmit_DMA() + (+) HAL_UART_Receive_DMA() + (+) HAL_UART_DMAPause() + (+) HAL_UART_DMAResume() + (+) HAL_UART_DMAStop() + + (#) A set of Transfer Complete Callbacks are provided in Non_Blocking mode: + (+) HAL_UART_TxHalfCpltCallback() + (+) HAL_UART_TxCpltCallback() + (+) HAL_UART_RxHalfCpltCallback() + (+) HAL_UART_RxCpltCallback() + (+) HAL_UART_ErrorCallback() + + (#) Non-Blocking mode transfers could be aborted using Abort API's : + (+) HAL_UART_Abort() + (+) HAL_UART_AbortTransmit() + (+) HAL_UART_AbortReceive() + (+) HAL_UART_Abort_IT() + (+) HAL_UART_AbortTransmit_IT() + (+) HAL_UART_AbortReceive_IT() + + (#) For Abort services based on interrupts (HAL_UART_Abortxxx_IT), a set of Abort Complete Callbacks are provided: + (+) HAL_UART_AbortCpltCallback() + (+) HAL_UART_AbortTransmitCpltCallback() + (+) HAL_UART_AbortReceiveCpltCallback() + + (#) In Non-Blocking mode transfers, possible errors are split into 2 categories. + Errors are handled as follows : + (+) Error is considered as Recoverable and non blocking : Transfer could go till end, but error severity is + to be evaluated by user : this concerns Frame Error, Parity Error or Noise Error in Interrupt mode reception . + Received character is then retrieved and stored in Rx buffer, Error code is set to allow user to identify error type, + and HAL_UART_ErrorCallback() user callback is executed. Transfer is kept ongoing on UART side. + If user wants to abort it, Abort services should be called by user. + (+) Error is considered as Blocking : Transfer could not be completed properly and is aborted. + This concerns Overrun Error In Interrupt mode reception and all errors in DMA mode. + Error code is set to allow user to identify error type, and HAL_UART_ErrorCallback() user callback is executed. + + -@- In the Half duplex communication, it is forbidden to run the transmit + and receive process in parallel, the UART state HAL_UART_STATE_BUSY_TX_RX can't be useful. + +@endverbatim + * @{ + */ + +/** + * @brief Send an amount of data in blocking mode. + * @note When FIFO mode is enabled, writing a data in the TDR register adds one + * data to the TXFIFO. Write operations to the TDR register are performed + * when TXFNF flag is set. From hardware perspective, TXFNF flag and + * TXE are mapped on the same bit-field. + * @param huart UART handle. + * @param pData Pointer to data buffer. + * @param Size Amount of data to be sent. + * @param Timeout Timeout duration. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + uint16_t* tmp; + uint32_t tickstart = 0U; + + /* Check that a Tx process is not already ongoing */ + if(huart->gState == HAL_UART_STATE_READY) + { + if((pData == NULL ) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->ErrorCode = HAL_UART_ERROR_NONE; + huart->gState = HAL_UART_STATE_BUSY_TX; + + /* Init tickstart for timeout managment*/ + tickstart = HAL_GetTick(); + + huart->TxXferSize = Size; + huart->TxXferCount = Size; + + while(huart->TxXferCount > 0U) + { + if(UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } + if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE)) + { + tmp = (uint16_t*) pData; + huart->Instance->TDR = (*tmp & (uint16_t)0x01FFU); + pData += 2U; + } + else + { + huart->Instance->TDR = (*pData++ & (uint8_t)0xFFU); + } + huart->TxXferCount--; + } + + if(UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TC, RESET, tickstart, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } + + /* At end of Tx process, restore huart->gState to Ready */ + huart->gState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive an amount of data in blocking mode. + * @note When FIFO mode is enabled, the RXFNE flag is set as long as the RXFIFO + * is not empty. Read operations from the RDR register are performed when + * RXFNE flag is set. From hardware perspective, RXFNE flag and + * RXNE are mapped on the same bit-field. + * @param huart UART handle. + * @param pData Pointer to data buffer. + * @param Size Amount of data to be received. + * @param Timeout Timeout duration. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + uint16_t* tmp; + uint16_t uhMask; + uint32_t tickstart = 0; + + /* Check that a Rx process is not already ongoing */ + if(huart->RxState == HAL_UART_STATE_READY) + { + if((pData == NULL ) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->ErrorCode = HAL_UART_ERROR_NONE; + huart->RxState = HAL_UART_STATE_BUSY_RX; + + /* Init tickstart for timeout managment*/ + tickstart = HAL_GetTick(); + + huart->RxXferSize = Size; + huart->RxXferCount = Size; + + /* Computation of UART mask to apply to RDR register */ + UART_MASK_COMPUTATION(huart); + uhMask = huart->Mask; + + /* as long as data have to be received */ + while(huart->RxXferCount > 0U) + { + if(UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } + if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE)) + { + tmp = (uint16_t*) pData ; + *tmp = (uint16_t)(huart->Instance->RDR & uhMask); + pData +=2U; + } + else + { + *pData++ = (uint8_t)(huart->Instance->RDR & (uint8_t)uhMask); + } + huart->RxXferCount--; + } + + /* At end of Rx process, restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Send an amount of data in interrupt mode. + * @param huart UART handle. + * @param pData Pointer to data buffer. + * @param Size Amount of data to be sent. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) +{ + /* Check that a Tx process is not already ongoing */ + if(huart->gState == HAL_UART_STATE_READY) + { + if((pData == NULL ) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->pTxBuffPtr = pData; + huart->TxXferSize = Size; + huart->TxXferCount = Size; + huart->TxISR = NULL; + + huart->ErrorCode = HAL_UART_ERROR_NONE; + huart->gState = HAL_UART_STATE_BUSY_TX; + +#if defined(USART_CR1_FIFOEN) + /* Configure Tx interrupt processing */ + if (huart->FifoMode == UART_FIFOMODE_ENABLE) + { + /* Set the Tx ISR function pointer according to the data word length */ + if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE)) + { + huart->TxISR = UART_TxISR_16BIT_FIFOEN; + } + else + { + huart->TxISR = UART_TxISR_8BIT_FIFOEN; + } + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + /* Enable the TX FIFO threshold interrupt */ + SET_BIT(huart->Instance->CR3, USART_CR3_TXFTIE); + } + else +#endif + { + /* Set the Tx ISR function pointer according to the data word length */ + if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE)) + { + huart->TxISR = UART_TxISR_16BIT; + } + else + { + huart->TxISR = UART_TxISR_8BIT; + } + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + /* Enable the Transmit Data Register Empty interrupt */ +#if defined(USART_CR1_FIFOEN) + SET_BIT(huart->Instance->CR1, USART_CR1_TXEIE_TXFNFIE); +#else + SET_BIT(huart->Instance->CR1, USART_CR1_TXEIE); +#endif + } + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive an amount of data in interrupt mode. + * @param huart UART handle. + * @param pData Pointer to data buffer. + * @param Size Amount of data to be received. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) +{ + /* Check that a Rx process is not already ongoing */ + if(huart->RxState == HAL_UART_STATE_READY) + { + if((pData == NULL ) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->pRxBuffPtr = pData; + huart->RxXferSize = Size; + huart->RxXferCount = Size; + huart->RxISR = NULL; + + /* Computation of UART mask to apply to RDR register */ + UART_MASK_COMPUTATION(huart); + + huart->ErrorCode = HAL_UART_ERROR_NONE; + huart->RxState = HAL_UART_STATE_BUSY_RX; + + /* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */ + SET_BIT(huart->Instance->CR3, USART_CR3_EIE); + +#if defined(USART_CR1_FIFOEN) + /* Configure Rx interrupt processing*/ + if ((huart->FifoMode == UART_FIFOMODE_ENABLE) && (Size >= huart->NbRxDataToProcess)) + { + /* Set the Rx ISR function pointer according to the data word length */ + if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE)) + { + huart->RxISR = UART_RxISR_16BIT_FIFOEN; + } + else + { + huart->RxISR = UART_RxISR_8BIT_FIFOEN; + } + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + /* Enable the UART Parity Error interrupt and RX FIFO Threshold interrupt */ + SET_BIT(huart->Instance->CR1, USART_CR1_PEIE); + SET_BIT(huart->Instance->CR3, USART_CR3_RXFTIE); + } + else +#endif + { + /* Set the Rx ISR function pointer according to the data word length */ + if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE)) + { + huart->RxISR = UART_RxISR_16BIT; + } + else + { + huart->RxISR = UART_RxISR_8BIT; + } + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + /* Enable the UART Parity Error interrupt and Data Register Not Empty interrupt */ +#if defined(USART_CR1_FIFOEN) + SET_BIT(huart->Instance->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE_RXFNEIE); +#else + SET_BIT(huart->Instance->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE); +#endif + } + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Send an amount of data in DMA mode. + * @param huart UART handle. + * @param pData Pointer to data buffer. + * @param Size Amount of data to be sent. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) +{ + /* Check that a Tx process is not already ongoing */ + if(huart->gState == HAL_UART_STATE_READY) + { + if((pData == NULL ) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->pTxBuffPtr = pData; + huart->TxXferSize = Size; + huart->TxXferCount = Size; + + huart->ErrorCode = HAL_UART_ERROR_NONE; + huart->gState = HAL_UART_STATE_BUSY_TX; + + /* Set the UART DMA transfer complete callback */ + huart->hdmatx->XferCpltCallback = UART_DMATransmitCplt; + + /* Set the UART DMA Half transfer complete callback */ + huart->hdmatx->XferHalfCpltCallback = UART_DMATxHalfCplt; + + /* Set the DMA error callback */ + huart->hdmatx->XferErrorCallback = UART_DMAError; + + /* Set the DMA abort callback */ + huart->hdmatx->XferAbortCallback = NULL; + + /* Enable the UART transmit DMA channel */ + HAL_DMA_Start_IT(huart->hdmatx, (uint32_t)huart->pTxBuffPtr, (uint32_t)&huart->Instance->TDR, Size); + + /* Clear the TC flag in the ICR register */ + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_TCF); + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + /* Enable the DMA transfer for transmit request by setting the DMAT bit + in the UART CR3 register */ + SET_BIT(huart->Instance->CR3, USART_CR3_DMAT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive an amount of data in DMA mode. + * @param huart UART handle. + * @param pData Pointer to data buffer. + * @param Size Amount of data to be received. + * @note When the UART parity is enabled (PCE = 1), the received data contain + * the parity bit (MSB position). + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) +{ + /* Check that a Rx process is not already ongoing */ + if(huart->RxState == HAL_UART_STATE_READY) + { + if((pData == NULL ) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->pRxBuffPtr = pData; + huart->RxXferSize = Size; + + huart->ErrorCode = HAL_UART_ERROR_NONE; + huart->RxState = HAL_UART_STATE_BUSY_RX; + + /* Set the UART DMA transfer complete callback */ + huart->hdmarx->XferCpltCallback = UART_DMAReceiveCplt; + + /* Set the UART DMA Half transfer complete callback */ + huart->hdmarx->XferHalfCpltCallback = UART_DMARxHalfCplt; + + /* Set the DMA error callback */ + huart->hdmarx->XferErrorCallback = UART_DMAError; + + /* Set the DMA abort callback */ + huart->hdmarx->XferAbortCallback = NULL; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(huart->hdmarx, (uint32_t)&huart->Instance->RDR, (uint32_t)huart->pRxBuffPtr, Size); + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + /* Enable the UART Parity Error Interrupt */ + SET_BIT(huart->Instance->CR1, USART_CR1_PEIE); + + /* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */ + SET_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Enable the DMA transfer for the receiver request by setting the DMAR bit + in the UART CR3 register */ + SET_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Pause the DMA Transfer. + * @param huart UART handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_DMAPause(UART_HandleTypeDef *huart) +{ + /* Process Locked */ + __HAL_LOCK(huart); + + if ((huart->gState == HAL_UART_STATE_BUSY_TX) && + (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT))) + { + /* Disable the UART DMA Tx request */ + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT); + } + if ((huart->RxState == HAL_UART_STATE_BUSY_RX) && + (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))) + { + /* Disable PE and ERR (Frame error, noise error, overrun error) interrupts */ + CLEAR_BIT(huart->Instance->CR1, USART_CR1_PEIE); + CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Disable the UART DMA Rx request */ + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + } + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +/** + * @brief Resume the DMA Transfer. + * @param huart UART handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_DMAResume(UART_HandleTypeDef *huart) +{ + /* Process Locked */ + __HAL_LOCK(huart); + + if(huart->gState == HAL_UART_STATE_BUSY_TX) + { + /* Enable the UART DMA Tx request */ + SET_BIT(huart->Instance->CR3, USART_CR3_DMAT); + } + if(huart->RxState == HAL_UART_STATE_BUSY_RX) + { + /* Clear the Overrun flag before resuming the Rx transfer */ + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF); + + /* Reenable PE and ERR (Frame error, noise error, overrun error) interrupts */ + SET_BIT(huart->Instance->CR1, USART_CR1_PEIE); + SET_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Enable the UART DMA Rx request */ + SET_BIT(huart->Instance->CR3, USART_CR3_DMAR); + } + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +/** + * @brief Stop the DMA Transfer. + * @param huart UART handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UART_DMAStop(UART_HandleTypeDef *huart) +{ + /* The Lock is not implemented on this API to allow the user application + to call the HAL UART API under callbacks HAL_UART_TxCpltCallback() / HAL_UART_RxCpltCallback() / + HAL_UART_TxHalfCpltCallback / HAL_UART_RxHalfCpltCallback: + indeed, when HAL_DMA_Abort() API is called, the DMA TX/RX Transfer or Half Transfer complete + interrupt is generated if the DMA transfer interruption occurs at the middle or at the end of + the stream and the corresponding call back is executed. */ + + /* Stop UART DMA Tx request if ongoing */ + if ((huart->gState == HAL_UART_STATE_BUSY_TX) && + (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT))) + { + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT); + + /* Abort the UART DMA Tx channel */ + if(huart->hdmatx != NULL) + { + HAL_DMA_Abort(huart->hdmatx); + } + + UART_EndTxTransfer(huart); + } + + /* Stop UART DMA Rx request if ongoing */ + if ((huart->RxState == HAL_UART_STATE_BUSY_RX) && + (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))) + { + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + /* Abort the UART DMA Rx channel */ + if(huart->hdmarx != NULL) + { + HAL_DMA_Abort(huart->hdmarx); + } + + UART_EndRxTransfer(huart); + } + + return HAL_OK; +} + +/** + * @brief Abort ongoing transfers (blocking mode). + * @param huart UART handle. + * @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable UART Interrupts (Tx and Rx) + * - Disable the DMA transfer in the peripheral register (if enabled) + * - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode) + * - Set handle State to READY + * @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed. + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_UART_Abort(UART_HandleTypeDef *huart) +{ + /* Disable TXEIE, TCIE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ +#if defined(USART_CR1_FIFOEN) + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE | USART_CR1_TXEIE_TXFNFIE | USART_CR1_TCIE)); +#else + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE)); +#endif + CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Disable the UART DMA Tx request if enabled */ + if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT)) + { + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT); + + /* Abort the UART DMA Tx channel : use blocking DMA Abort API (no callback) */ + if(huart->hdmatx != NULL) + { + /* Set the UART DMA Abort callback to Null. + No call back execution at end of DMA abort procedure */ + huart->hdmatx->XferAbortCallback = NULL; + + HAL_DMA_Abort(huart->hdmatx); + } + } + + /* Disable the UART DMA Rx request if enabled */ + if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) + { + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + /* Abort the UART DMA Rx channel : use blocking DMA Abort API (no callback) */ + if(huart->hdmarx != NULL) + { + /* Set the UART DMA Abort callback to Null. + No call back execution at end of DMA abort procedure */ + huart->hdmarx->XferAbortCallback = NULL; + + HAL_DMA_Abort(huart->hdmarx); + } + } + + /* Reset Tx and Rx transfer counters */ + huart->TxXferCount = 0U; + huart->RxXferCount = 0U; + + /* Clear the Error flags in the ICR register */ + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_PEF | UART_CLEAR_FEF); + +#if defined(USART_CR1_FIFOEN) + /* Flush the whole TX FIFO (if needed) */ + if (huart->FifoMode == UART_FIFOMODE_ENABLE) + { + __HAL_UART_SEND_REQ(huart, UART_TXDATA_FLUSH_REQUEST); + } +#endif + + /* Discard the received data */ + __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST); + + /* Restore huart->gState and huart->RxState to Ready */ + huart->gState = HAL_UART_STATE_READY; + huart->RxState = HAL_UART_STATE_READY; + + /* Reset Handle ErrorCode to No Error */ + huart->ErrorCode = HAL_UART_ERROR_NONE; + + return HAL_OK; +} + +/** + * @brief Abort ongoing Transmit transfer (blocking mode). + * @param huart UART handle. + * @note This procedure could be used for aborting any ongoing Tx transfer started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable UART Interrupts (Tx) + * - Disable the DMA transfer in the peripheral register (if enabled) + * - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode) + * - Set handle State to READY + * @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed. + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_UART_AbortTransmit(UART_HandleTypeDef *huart) +{ + /* Disable TXEIE and TCIE interrupts */ +#if defined(USART_CR1_FIFOEN) + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_TXEIE_TXFNFIE | USART_CR1_TCIE)); +#else + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE)); +#endif + + /* Disable the UART DMA Tx request if enabled */ + if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT)) + { + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT); + + /* Abort the UART DMA Tx channel : use blocking DMA Abort API (no callback) */ + if(huart->hdmatx != NULL) + { + /* Set the UART DMA Abort callback to Null. + No call back execution at end of DMA abort procedure */ + huart->hdmatx->XferAbortCallback = NULL; + + HAL_DMA_Abort(huart->hdmatx); + } + } + + /* Reset Tx transfer counter */ + huart->TxXferCount = 0U; + +#if defined(USART_CR1_FIFOEN) + /* Flush the whole TX FIFO (if needed) */ + if (huart->FifoMode == UART_FIFOMODE_ENABLE) + { + __HAL_UART_SEND_REQ(huart, UART_TXDATA_FLUSH_REQUEST); + } +#endif + + /* Restore huart->gState to Ready */ + huart->gState = HAL_UART_STATE_READY; + + return HAL_OK; +} + +/** + * @brief Abort ongoing Receive transfer (blocking mode). + * @param huart UART handle. + * @note This procedure could be used for aborting any ongoing Rx transfer started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable UART Interrupts (Rx) + * - Disable the DMA transfer in the peripheral register (if enabled) + * - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode) + * - Set handle State to READY + * @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed. + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_UART_AbortReceive(UART_HandleTypeDef *huart) +{ + /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ +#if defined(USART_CR1_FIFOEN) + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE)); +#else + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE)); +#endif + CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Disable the UART DMA Rx request if enabled */ + if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) + { + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + /* Abort the UART DMA Rx channel : use blocking DMA Abort API (no callback) */ + if(huart->hdmarx != NULL) + { + /* Set the UART DMA Abort callback to Null. + No call back execution at end of DMA abort procedure */ + huart->hdmarx->XferAbortCallback = NULL; + + HAL_DMA_Abort(huart->hdmarx); + } + } + + /* Reset Rx transfer counter */ + huart->RxXferCount = 0U; + + /* Clear the Error flags in the ICR register */ + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_PEF | UART_CLEAR_FEF); + + /* Discard the received data */ + __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST); + + /* Restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + + return HAL_OK; +} + +/** + * @brief Abort ongoing transfers (Interrupt mode). + * @param huart UART handle. + * @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable UART Interrupts (Tx and Rx) + * - Disable the DMA transfer in the peripheral register (if enabled) + * - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode) + * - Set handle State to READY + * - At abort completion, call user abort complete callback + * @note This procedure is executed in Interrupt mode, meaning that abort procedure could be + * considered as completed only when user abort complete callback is executed (not when exiting function). + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_UART_Abort_IT(UART_HandleTypeDef *huart) +{ + uint32_t abortcplt = 1U; + + /* Disable TXEIE, TCIE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ +#if defined(USART_CR1_FIFOEN) + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE | USART_CR1_TXEIE_TXFNFIE | USART_CR1_TCIE)); +#else + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE)); +#endif + CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* If DMA Tx and/or DMA Rx Handles are associated to UART Handle, DMA Abort complete callbacks should be initialised + before any call to DMA Abort functions */ + /* DMA Tx Handle is valid */ + if(huart->hdmatx != NULL) + { + /* Set DMA Abort Complete callback if UART DMA Tx request if enabled. + Otherwise, set it to NULL */ + if(HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT)) + { + huart->hdmatx->XferAbortCallback = UART_DMATxAbortCallback; + } + else + { + huart->hdmatx->XferAbortCallback = NULL; + } + } + /* DMA Rx Handle is valid */ + if(huart->hdmarx != NULL) + { + /* Set DMA Abort Complete callback if UART DMA Rx request if enabled. + Otherwise, set it to NULL */ + if(HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) + { + huart->hdmarx->XferAbortCallback = UART_DMARxAbortCallback; + } + else + { + huart->hdmarx->XferAbortCallback = NULL; + } + } + + /* Disable the UART DMA Tx request if enabled */ + if(HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT)) + { + /* Disable DMA Tx at UART level */ + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT); + + /* Abort the UART DMA Tx channel : use non blocking DMA Abort API (callback) */ + if(huart->hdmatx != NULL) + { + /* UART Tx DMA Abort callback has already been initialised : + will lead to call HAL_UART_AbortCpltCallback() at end of DMA abort procedure */ + + /* Abort DMA TX */ + if(HAL_DMA_Abort_IT(huart->hdmatx) != HAL_OK) + { + huart->hdmatx->XferAbortCallback = NULL; + } + else + { + abortcplt = 0U; + } + } + } + + /* Disable the UART DMA Rx request if enabled */ + if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) + { + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + /* Abort the UART DMA Rx channel : use non blocking DMA Abort API (callback) */ + if(huart->hdmarx != NULL) + { + /* UART Rx DMA Abort callback has already been initialised : + will lead to call HAL_UART_AbortCpltCallback() at end of DMA abort procedure */ + + /* Abort DMA RX */ + if(HAL_DMA_Abort_IT(huart->hdmarx) != HAL_OK) + { + huart->hdmarx->XferAbortCallback = NULL; + abortcplt = 1U; + } + else + { + abortcplt = 0U; + } + } + } + + /* if no DMA abort complete callback execution is required => call user Abort Complete callback */ + if (abortcplt == 1U) + { + /* Reset Tx and Rx transfer counters */ + huart->TxXferCount = 0U; + huart->RxXferCount = 0U; + + /* Clear ISR function pointers */ + huart->RxISR = NULL; + huart->TxISR = NULL; + + /* Reset errorCode */ + huart->ErrorCode = HAL_UART_ERROR_NONE; + + /* Clear the Error flags in the ICR register */ + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_PEF | UART_CLEAR_FEF); + +#if defined(USART_CR1_FIFOEN) + /* Flush the whole TX FIFO (if needed) */ + if (huart->FifoMode == UART_FIFOMODE_ENABLE) + { + __HAL_UART_SEND_REQ(huart, UART_TXDATA_FLUSH_REQUEST); + } +#endif + + /* Discard the received data */ + __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST); + + /* Restore huart->gState and huart->RxState to Ready */ + huart->gState = HAL_UART_STATE_READY; + huart->RxState = HAL_UART_STATE_READY; + + /* As no DMA to be aborted, call directly user Abort complete callback */ + HAL_UART_AbortCpltCallback(huart); + } + + return HAL_OK; +} + +/** + * @brief Abort ongoing Transmit transfer (Interrupt mode). + * @param huart UART handle. + * @note This procedure could be used for aborting any ongoing Tx transfer started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable UART Interrupts (Tx) + * - Disable the DMA transfer in the peripheral register (if enabled) + * - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode) + * - Set handle State to READY + * - At abort completion, call user abort complete callback + * @note This procedure is executed in Interrupt mode, meaning that abort procedure could be + * considered as completed only when user abort complete callback is executed (not when exiting function). + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_UART_AbortTransmit_IT(UART_HandleTypeDef *huart) +{ + /* Disable TXEIE and TCIE interrupts */ +#if defined(USART_CR1_FIFOEN) + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_TXEIE_TXFNFIE | USART_CR1_TCIE)); +#else + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE)); +#endif + + /* Disable the UART DMA Tx request if enabled */ + if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT)) + { + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT); + + /* Abort the UART DMA Tx channel : use non blocking DMA Abort API (callback) */ + if(huart->hdmatx != NULL) + { + /* Set the UART DMA Abort callback : + will lead to call HAL_UART_AbortCpltCallback() at end of DMA abort procedure */ + huart->hdmatx->XferAbortCallback = UART_DMATxOnlyAbortCallback; + + /* Abort DMA TX */ + if(HAL_DMA_Abort_IT(huart->hdmatx) != HAL_OK) + { + /* Call Directly huart->hdmatx->XferAbortCallback function in case of error */ + huart->hdmatx->XferAbortCallback(huart->hdmatx); + } + } + else + { + /* Reset Tx transfer counter */ + huart->TxXferCount = 0U; + + /* Clear TxISR function pointers */ + huart->TxISR = NULL; + + /* Restore huart->gState to Ready */ + huart->gState = HAL_UART_STATE_READY; + + /* As no DMA to be aborted, call directly user Abort complete callback */ + HAL_UART_AbortTransmitCpltCallback(huart); + } + } + else + { + /* Reset Tx transfer counter */ + huart->TxXferCount = 0U; + + /* Clear TxISR function pointers */ + huart->TxISR = NULL; + +#if defined(USART_CR1_FIFOEN) + /* Flush the whole TX FIFO (if needed) */ + if (huart->FifoMode == UART_FIFOMODE_ENABLE) + { + __HAL_UART_SEND_REQ(huart, UART_TXDATA_FLUSH_REQUEST); + } +#endif + + /* Restore huart->gState to Ready */ + huart->gState = HAL_UART_STATE_READY; + + /* As no DMA to be aborted, call directly user Abort complete callback */ + HAL_UART_AbortTransmitCpltCallback(huart); + } + + return HAL_OK; +} + +/** + * @brief Abort ongoing Receive transfer (Interrupt mode). + * @param huart UART handle. + * @note This procedure could be used for aborting any ongoing Rx transfer started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable UART Interrupts (Rx) + * - Disable the DMA transfer in the peripheral register (if enabled) + * - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode) + * - Set handle State to READY + * - At abort completion, call user abort complete callback + * @note This procedure is executed in Interrupt mode, meaning that abort procedure could be + * considered as completed only when user abort complete callback is executed (not when exiting function). + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_UART_AbortReceive_IT(UART_HandleTypeDef *huart) +{ + /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ +#if defined(USART_CR1_FIFOEN) + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE)); +#else + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE)); +#endif + CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Disable the UART DMA Rx request if enabled */ + if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) + { + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + /* Abort the UART DMA Rx channel : use non blocking DMA Abort API (callback) */ + if(huart->hdmarx != NULL) + { + /* Set the UART DMA Abort callback : + will lead to call HAL_UART_AbortCpltCallback() at end of DMA abort procedure */ + huart->hdmarx->XferAbortCallback = UART_DMARxOnlyAbortCallback; + + /* Abort DMA RX */ + if(HAL_DMA_Abort_IT(huart->hdmarx) != HAL_OK) + { + /* Call Directly huart->hdmarx->XferAbortCallback function in case of error */ + huart->hdmarx->XferAbortCallback(huart->hdmarx); + } + } + else + { + /* Reset Rx transfer counter */ + huart->RxXferCount = 0U; + + /* Clear RxISR function pointer */ + huart->pRxBuffPtr = NULL; + + /* Clear the Error flags in the ICR register */ + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_PEF | UART_CLEAR_FEF); + + /* Discard the received data */ + __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST); + + /* Restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + + /* As no DMA to be aborted, call directly user Abort complete callback */ + HAL_UART_AbortReceiveCpltCallback(huart); + } + } + else + { + /* Reset Rx transfer counter */ + huart->RxXferCount = 0U; + + /* Clear RxISR function pointer */ + huart->pRxBuffPtr = NULL; + + /* Clear the Error flags in the ICR register */ + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_PEF | UART_CLEAR_FEF); + + /* Restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + + /* As no DMA to be aborted, call directly user Abort complete callback */ + HAL_UART_AbortReceiveCpltCallback(huart); + } + + return HAL_OK; +} + +/** + * @brief Handle UART interrupt request. + * @param huart UART handle. + * @retval None + */ +void HAL_UART_IRQHandler(UART_HandleTypeDef *huart) +{ + uint32_t isrflags = READ_REG(huart->Instance->ISR); + uint32_t cr1its = READ_REG(huart->Instance->CR1); + uint32_t cr3its = READ_REG(huart->Instance->CR3); + uint32_t errorflags; + + /* If no error occurs */ + errorflags = (isrflags & (uint32_t)(USART_ISR_PE | USART_ISR_FE | USART_ISR_ORE | USART_ISR_NE)); + if (errorflags == RESET) + { + /* UART in mode Receiver ---------------------------------------------------*/ +#if defined(USART_CR1_FIFOEN) + if(((isrflags & USART_ISR_RXNE_RXFNE) != RESET) + && ( ((cr1its & USART_CR1_RXNEIE_RXFNEIE) != RESET) + || ((cr3its & USART_CR3_RXFTIE) != RESET)) ) +#else + if(((isrflags & USART_ISR_RXNE) != RESET) + && ((cr1its & USART_CR1_RXNEIE) != RESET)) +#endif + { + if (huart->RxISR != NULL) {huart->RxISR(huart);} + return; + } + } + + /* If some errors occur */ +#if defined(USART_CR1_FIFOEN) + if( (errorflags != RESET) + && ( (((cr3its & (USART_CR3_RXFTIE | USART_CR3_EIE)) != RESET) + || ((cr1its & (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE)) != RESET))) ) +#else + if( (errorflags != RESET) + && ( ((cr3its & USART_CR3_EIE) != RESET) + || ((cr1its & (USART_CR1_RXNEIE | USART_CR1_PEIE)) != RESET)) ) +#endif + { + /* UART parity error interrupt occurred -------------------------------------*/ + if(((isrflags & USART_ISR_PE) != RESET) && ((cr1its & USART_CR1_PEIE) != RESET)) + { + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_PEF); + + huart->ErrorCode |= HAL_UART_ERROR_PE; + } + + /* UART frame error interrupt occurred --------------------------------------*/ + if(((isrflags & USART_ISR_FE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET)) + { + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_FEF); + + huart->ErrorCode |= HAL_UART_ERROR_FE; + } + + /* UART noise error interrupt occurred --------------------------------------*/ + if(((isrflags & USART_ISR_NE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET)) + { + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_NEF); + + huart->ErrorCode |= HAL_UART_ERROR_NE; + } + + /* UART Over-Run interrupt occurred -----------------------------------------*/ +#if defined(USART_CR1_FIFOEN) + if( ((isrflags & USART_ISR_ORE) != RESET) + &&( ((cr1its & USART_CR1_RXNEIE_RXFNEIE) != RESET) || + ((cr3its & (USART_CR3_RXFTIE | USART_CR3_EIE)) != RESET))) +#else + if( ((isrflags & USART_ISR_ORE) != RESET) + &&( ((cr1its & USART_CR1_RXNEIE) != RESET) || + ((cr3its & USART_CR3_EIE) != RESET))) +#endif + { + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF); + + huart->ErrorCode |= HAL_UART_ERROR_ORE; + } + + /* Call UART Error Call back function if need be --------------------------*/ + if(huart->ErrorCode != HAL_UART_ERROR_NONE) + { + /* UART in mode Receiver ---------------------------------------------------*/ +#if defined(USART_CR1_FIFOEN) + if(((isrflags & USART_ISR_RXNE_RXFNE) != RESET) + && ( ((cr1its & USART_CR1_RXNEIE_RXFNEIE) != RESET) + || ((cr3its & USART_CR3_RXFTIE) != RESET)) ) +#else + if(((isrflags & USART_ISR_RXNE) != RESET) + && ((cr1its & USART_CR1_RXNEIE) != RESET)) +#endif + { + if (huart->RxISR != NULL) {huart->RxISR(huart);} + } + + /* If Overrun error occurs, or if any error occurs in DMA mode reception, + consider error as blocking */ + if (((huart->ErrorCode & HAL_UART_ERROR_ORE) != RESET) || + (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))) + { + /* Blocking error : transfer is aborted + Set the UART state ready to be able to start again the process, + Disable Rx Interrupts, and disable Rx DMA request, if ongoing */ + UART_EndRxTransfer(huart); + + /* Disable the UART DMA Rx request if enabled */ + if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) + { + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + /* Abort the UART DMA Rx channel */ + if(huart->hdmarx != NULL) + { + /* Set the UART DMA Abort callback : + will lead to call HAL_UART_ErrorCallback() at end of DMA abort procedure */ + huart->hdmarx->XferAbortCallback = UART_DMAAbortOnError; + + /* Abort DMA RX */ + if(HAL_DMA_Abort_IT(huart->hdmarx) != HAL_OK) + { + /* Call Directly huart->hdmarx->XferAbortCallback function in case of error */ + huart->hdmarx->XferAbortCallback(huart->hdmarx); + } + } + else + { + /* Call user error callback */ + HAL_UART_ErrorCallback(huart); + } + } + else + { + /* Call user error callback */ + HAL_UART_ErrorCallback(huart); + } + } + else + { + /* Non Blocking error : transfer could go on. + Error is notified to user through user error callback */ + HAL_UART_ErrorCallback(huart); + huart->ErrorCode = HAL_UART_ERROR_NONE; + } + } + return; + + } /* End if some error occurs */ + + /* UART wakeup from Stop mode interrupt occurred ---------------------------*/ + if(((isrflags & USART_ISR_WUF) != RESET) && ((cr3its & USART_CR3_WUFIE) != RESET)) + { + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_WUF); + /* Set the UART state ready to be able to start again the process */ + huart->gState = HAL_UART_STATE_READY; + huart->RxState = HAL_UART_STATE_READY; + HAL_UARTEx_WakeupCallback(huart); + return; + } + + /* UART in mode Transmitter ------------------------------------------------*/ +#if defined(USART_CR1_FIFOEN) + if(((isrflags & USART_ISR_TXE_TXFNF) != RESET) + && ( ((cr1its & USART_CR1_TXEIE_TXFNFIE) != RESET) + || ((cr3its & USART_CR3_TXFTIE) != RESET)) ) +#else + if(((isrflags & USART_ISR_TXE) != RESET) + && ((cr1its & USART_CR1_TXEIE) != RESET)) +#endif + { + if (huart->TxISR != NULL) {huart->TxISR(huart);} + return; + } + + /* UART in mode Transmitter (transmission end) -----------------------------*/ + if(((isrflags & USART_ISR_TC) != RESET) && ((cr1its & USART_CR1_TCIE) != RESET)) + { + UART_EndTransmit_IT(huart); + return; + } + +#if defined(USART_CR1_FIFOEN) + /* UART TX Fifo Empty occurred ----------------------------------------------*/ + if(((isrflags & USART_ISR_TXFE) != RESET) && ((cr1its & USART_CR1_TXFEIE) != RESET)) + { + HAL_UARTEx_TxFifoEmptyCallback(huart); + return; + } + + /* UART RX Fifo Full occurred ----------------------------------------------*/ + if(((isrflags & USART_ISR_RXFF) != RESET) && ((cr1its & USART_CR1_RXFFIE) != RESET)) + { + HAL_UARTEx_RxFifoFullCallback(huart); + return; + } +#endif +} + +/** + * @brief Tx Transfer completed callback. + * @param huart UART handle. + * @retval None + */ +__weak void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_UART_TxCpltCallback can be implemented in the user file. + */ +} + +/** + * @brief Tx Half Transfer completed callback. + * @param huart UART handle. + * @retval None + */ +__weak void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_UART_TxHalfCpltCallback can be implemented in the user file. + */ +} + +/** + * @brief Rx Transfer completed callback. + * @param huart UART handle. + * @retval None + */ +__weak void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_UART_RxCpltCallback can be implemented in the user file. + */ +} + +/** + * @brief Rx Half Transfer completed callback. + * @param huart UART handle. + * @retval None + */ +__weak void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_UART_RxHalfCpltCallback can be implemented in the user file. + */ +} + +/** + * @brief UART error callback. + * @param huart UART handle. + * @retval None + */ +__weak void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_UART_ErrorCallback can be implemented in the user file. + */ +} + +/** + * @brief UART Abort Complete callback. + * @param huart UART handle. + * @retval None + */ +__weak void HAL_UART_AbortCpltCallback (UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_UART_AbortCpltCallback can be implemented in the user file. + */ +} + +/** + * @brief UART Abort Complete callback. + * @param huart UART handle. + * @retval None + */ +__weak void HAL_UART_AbortTransmitCpltCallback (UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_UART_AbortTransmitCpltCallback can be implemented in the user file. + */ +} + +/** + * @brief UART Abort Receive Complete callback. + * @param huart UART handle. + * @retval None + */ +__weak void HAL_UART_AbortReceiveCpltCallback (UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_UART_AbortReceiveCpltCallback can be implemented in the user file. + */ +} + +/** + * @} + */ + +/** @defgroup UART_Exported_Functions_Group3 Peripheral Control functions + * @brief UART control functions + * +@verbatim + =============================================================================== + ##### Peripheral Control functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to control the UART. + (+) HAL_MultiProcessor_EnableMuteMode() API enables mute mode + (+) HAL_MultiProcessor_DisableMuteMode() API disables mute mode + (+) HAL_MultiProcessor_EnterMuteMode() API enters mute mode + (+) HAL_MultiProcessor_EnableMuteMode() API enables mute mode + (+) UART_SetConfig() API configures the UART peripheral + (+) UART_AdvFeatureConfig() API optionally configures the UART advanced features + (+) UART_CheckIdleState() API ensures that TEACK and/or REACK are set after initialization + (+) UART_Wakeup_AddressConfig() API configures the wake-up from stop mode parameters + (+) HAL_HalfDuplex_EnableTransmitter() API disables receiver and enables transmitter + (+) HAL_HalfDuplex_EnableReceiver() API disables transmitter and enables receiver + (+) HAL_LIN_SendBreak() API transmits the break characters +@endverbatim + * @{ + */ + +/** + * @brief Enable UART in mute mode (does not mean UART enters mute mode; + * to enter mute mode, HAL_MultiProcessor_EnterMuteMode() API must be called). + * @param huart UART handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MultiProcessor_EnableMuteMode(UART_HandleTypeDef *huart) +{ + /* Process Locked */ + __HAL_LOCK(huart); + + huart->gState = HAL_UART_STATE_BUSY; + + /* Enable USART mute mode by setting the MME bit in the CR1 register */ + SET_BIT(huart->Instance->CR1, USART_CR1_MME); + + huart->gState = HAL_UART_STATE_READY; + + return (UART_CheckIdleState(huart)); +} + +/** + * @brief Disable UART mute mode (does not mean the UART actually exits mute mode + * as it may not have been in mute mode at this very moment). + * @param huart UART handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MultiProcessor_DisableMuteMode(UART_HandleTypeDef *huart) +{ + /* Process Locked */ + __HAL_LOCK(huart); + + huart->gState = HAL_UART_STATE_BUSY; + + /* Disable USART mute mode by clearing the MME bit in the CR1 register */ + CLEAR_BIT(huart->Instance->CR1, USART_CR1_MME); + + huart->gState = HAL_UART_STATE_READY; + + return (UART_CheckIdleState(huart)); +} + +/** + * @brief Enter UART mute mode (means UART actually enters mute mode). + * @note To exit from mute mode, HAL_MultiProcessor_DisableMuteMode() API must be called. + * @param huart UART handle. + * @retval None + */ +void HAL_MultiProcessor_EnterMuteMode(UART_HandleTypeDef *huart) +{ + __HAL_UART_SEND_REQ(huart, UART_MUTE_MODE_REQUEST); +} + +/** + * @brief Enable the UART transmitter and disable the UART receiver. + * @param huart UART handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HalfDuplex_EnableTransmitter(UART_HandleTypeDef *huart) +{ + /* Process Locked */ + __HAL_LOCK(huart); + huart->gState = HAL_UART_STATE_BUSY; + + /* Clear TE and RE bits */ + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_TE | USART_CR1_RE)); + + /* Enable the USART's transmit interface by setting the TE bit in the USART CR1 register */ + SET_BIT(huart->Instance->CR1, USART_CR1_TE); + + huart->gState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +/** + * @brief Enable the UART receiver and disable the UART transmitter. + * @param huart UART handle. + * @retval HAL status. + */ +HAL_StatusTypeDef HAL_HalfDuplex_EnableReceiver(UART_HandleTypeDef *huart) +{ + /* Process Locked */ + __HAL_LOCK(huart); + huart->gState = HAL_UART_STATE_BUSY; + + /* Clear TE and RE bits */ + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_TE | USART_CR1_RE)); + + /* Enable the USART's receive interface by setting the RE bit in the USART CR1 register */ + SET_BIT(huart->Instance->CR1, USART_CR1_RE); + + huart->gState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + + +/** + * @brief Transmit break characters. + * @param huart UART handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LIN_SendBreak(UART_HandleTypeDef *huart) +{ + /* Check the parameters */ + assert_param(IS_UART_LIN_INSTANCE(huart->Instance)); + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->gState = HAL_UART_STATE_BUSY; + + /* Send break characters */ + SET_BIT(huart->Instance->RQR, UART_SENDBREAK_REQUEST); + + huart->gState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup UART_Exported_Functions_Group4 Peripheral State and Error functions + * @brief UART Peripheral State functions + * +@verbatim + ============================================================================== + ##### Peripheral State and Error functions ##### + ============================================================================== + [..] + This subsection provides functions allowing to : + (+) Return the UART handle state. + (+) Return the UART handle error code + +@endverbatim + * @{ + */ + +/** + * @brief Return the UART handle state. + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART. + * @retval HAL state + */ +HAL_UART_StateTypeDef HAL_UART_GetState(UART_HandleTypeDef *huart) +{ + uint32_t temp1= 0x00U, temp2 = 0x00U; + temp1 = huart->gState; + temp2 = huart->RxState; + + return (HAL_UART_StateTypeDef)(temp1 | temp2); +} + +/** +* @brief Return the UART handle error code. + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART. +* @retval UART Error Code +*/ +uint32_t HAL_UART_GetError(UART_HandleTypeDef *huart) +{ + return huart->ErrorCode; +} +/** + * @} + */ + +/** + * @} + */ + +/** @defgroup UART_Private_Functions UART Private Functions + * @{ + */ + +/** + * @brief Configure the UART peripheral. + * @param huart UART handle. + * @retval HAL status + */ +HAL_StatusTypeDef UART_SetConfig(UART_HandleTypeDef *huart) +{ + uint32_t tmpreg = 0x00000000U; + UART_ClockSourceTypeDef clocksource = UART_CLOCKSOURCE_UNDEFINED; + uint16_t brrtemp = 0x0000U; + uint32_t usartdiv = 0x00000000U; + HAL_StatusTypeDef ret = HAL_OK; + uint32_t lpuart_ker_ck_pres = 0x00000000U; + + /* Check the parameters */ + assert_param(IS_UART_BAUDRATE(huart->Init.BaudRate)); + assert_param(IS_UART_WORD_LENGTH(huart->Init.WordLength)); + if(UART_INSTANCE_LOWPOWER(huart)) + { + assert_param(IS_LPUART_STOPBITS(huart->Init.StopBits)); + } + else + { + assert_param(IS_UART_STOPBITS(huart->Init.StopBits)); + assert_param(IS_UART_ONE_BIT_SAMPLE(huart->Init.OneBitSampling)); + } + + assert_param(IS_UART_PARITY(huart->Init.Parity)); + assert_param(IS_UART_MODE(huart->Init.Mode)); + assert_param(IS_UART_HARDWARE_FLOW_CONTROL(huart->Init.HwFlowCtl)); + assert_param(IS_UART_OVERSAMPLING(huart->Init.OverSampling)); +#if defined(USART_PRESC_PRESCALER) + assert_param(IS_UART_PRESCALER(huart->Init.ClockPrescaler)); +#endif + + /*-------------------------- USART CR1 Configuration -----------------------*/ + /* Clear M, PCE, PS, TE, RE and OVER8 bits and configure + * the UART Word Length, Parity, Mode and oversampling: + * set the M bits according to huart->Init.WordLength value + * set PCE and PS bits according to huart->Init.Parity value + * set TE and RE bits according to huart->Init.Mode value + * set OVER8 bit according to huart->Init.OverSampling value */ + tmpreg = (uint32_t)huart->Init.WordLength | huart->Init.Parity | huart->Init.Mode | huart->Init.OverSampling ; + MODIFY_REG(huart->Instance->CR1, USART_CR1_FIELDS, tmpreg); + + /*-------------------------- USART CR2 Configuration -----------------------*/ + /* Configure the UART Stop Bits: Set STOP[13:12] bits according + * to huart->Init.StopBits value */ + MODIFY_REG(huart->Instance->CR2, USART_CR2_STOP, huart->Init.StopBits); + + /*-------------------------- USART CR3 Configuration -----------------------*/ + /* Configure + * - UART HardWare Flow Control: set CTSE and RTSE bits according + * to huart->Init.HwFlowCtl value + * - one-bit sampling method versus three samples' majority rule according + * to huart->Init.OneBitSampling (not applicable to LPUART) + * - set TXFTCFG bit according to huart->Init.TxFifoThreshold value + * - set RXFTCFG bit according to huart->Init.RxFifoThreshold value */ + tmpreg = (uint32_t)huart->Init.HwFlowCtl; + + if (!(UART_INSTANCE_LOWPOWER(huart))) + { + tmpreg |= huart->Init.OneBitSampling; + } + MODIFY_REG(huart->Instance->CR3, USART_CR3_FIELDS, tmpreg); + +#if defined(USART_PRESC_PRESCALER) + /*-------------------------- USART PRESC Configuration -----------------------*/ + /* Configure + * - UART Clock Prescaler : set PRESCALER according to huart->Init.ClockPrescaler value */ + MODIFY_REG(huart->Instance->PRESC, USART_PRESC_PRESCALER, huart->Init.ClockPrescaler); +#endif + + /*-------------------------- USART BRR Configuration -----------------------*/ + UART_GETCLOCKSOURCE(huart, clocksource); + + /* Check LPUART instance */ + if(UART_INSTANCE_LOWPOWER(huart)) + { + /* Retrieve frequency clock */ + switch (clocksource) + { + case UART_CLOCKSOURCE_PCLK1: +#if defined(USART_PRESC_PRESCALER) + lpuart_ker_ck_pres = (HAL_RCC_GetPCLK1Freq()/UARTPrescTable[huart->Init.ClockPrescaler]); +#else + lpuart_ker_ck_pres = HAL_RCC_GetPCLK1Freq(); +#endif + break; + case UART_CLOCKSOURCE_HSI: +#if defined(USART_PRESC_PRESCALER) + lpuart_ker_ck_pres = ((uint32_t)HSI_VALUE/UARTPrescTable[huart->Init.ClockPrescaler]); +#else + lpuart_ker_ck_pres = (uint32_t)HSI_VALUE; +#endif + break; + case UART_CLOCKSOURCE_SYSCLK: +#if defined(USART_PRESC_PRESCALER) + lpuart_ker_ck_pres = (HAL_RCC_GetSysClockFreq()/UARTPrescTable[huart->Init.ClockPrescaler]); +#else + lpuart_ker_ck_pres = HAL_RCC_GetSysClockFreq(); +#endif + break; + case UART_CLOCKSOURCE_LSE: +#if defined(USART_PRESC_PRESCALER) + lpuart_ker_ck_pres = ((uint32_t)LSE_VALUE/UARTPrescTable[huart->Init.ClockPrescaler]); +#else + lpuart_ker_ck_pres = (uint32_t)LSE_VALUE; +#endif + break; + case UART_CLOCKSOURCE_UNDEFINED: + default: + ret = HAL_ERROR; + break; + } + + /* if proper clock source reported */ + if (lpuart_ker_ck_pres != 0U) + { + /* ensure that Frequency clock is in the range [3 * baudrate, 4096 * baudrate] */ + if ( (lpuart_ker_ck_pres < (3 * huart->Init.BaudRate) ) || + (lpuart_ker_ck_pres > (4096 * huart->Init.BaudRate) )) + { + ret = HAL_ERROR; + } + else + { + switch (clocksource) + { + case UART_CLOCKSOURCE_PCLK1: +#if defined(USART_PRESC_PRESCALER) + usartdiv = (uint32_t)(UART_DIV_LPUART(HAL_RCC_GetPCLK1Freq(), huart->Init.BaudRate, huart->Init.ClockPrescaler)); +#else + usartdiv = (uint32_t)(UART_DIV_LPUART(HAL_RCC_GetPCLK1Freq(), huart->Init.BaudRate)); +#endif + break; + case UART_CLOCKSOURCE_HSI: +#if defined(USART_PRESC_PRESCALER) + usartdiv = (uint32_t)(UART_DIV_LPUART(HSI_VALUE, huart->Init.BaudRate, huart->Init.ClockPrescaler)); +#else + usartdiv = (uint32_t)(UART_DIV_LPUART(HSI_VALUE, huart->Init.BaudRate)); +#endif + break; + case UART_CLOCKSOURCE_SYSCLK: +#if defined(USART_PRESC_PRESCALER) + usartdiv = (uint32_t)(UART_DIV_LPUART(HAL_RCC_GetSysClockFreq(), huart->Init.BaudRate, huart->Init.ClockPrescaler)); +#else + usartdiv = (uint32_t)(UART_DIV_LPUART(HAL_RCC_GetSysClockFreq(), huart->Init.BaudRate)); +#endif + break; + case UART_CLOCKSOURCE_LSE: +#if defined(USART_PRESC_PRESCALER) + usartdiv = (uint32_t)(UART_DIV_LPUART(LSE_VALUE, huart->Init.BaudRate, huart->Init.ClockPrescaler)); +#else + usartdiv = (uint32_t)(UART_DIV_LPUART(LSE_VALUE, huart->Init.BaudRate)); +#endif + break; + case UART_CLOCKSOURCE_UNDEFINED: + default: + ret = HAL_ERROR; + break; + } + + /* It is forbidden to write values lower than 0x300 in the LPUART_BRR register */ + if ((usartdiv >= LPUART_BRR_MIN) && (usartdiv <= LPUART_BRR_MAX)) + { + huart->Instance->BRR = usartdiv; + } + else + { + ret = HAL_ERROR; + } + } /* if ( (tmpreg < (3 * huart->Init.BaudRate) ) || (tmpreg > (4096 * huart->Init.BaudRate) )) */ + } /* if (tmpreg != 0) */ + } + /* Check UART Over Sampling to set Baud Rate Register */ + else if (huart->Init.OverSampling == UART_OVERSAMPLING_8) + { + switch (clocksource) + { + case UART_CLOCKSOURCE_PCLK1: +#if defined(USART_PRESC_PRESCALER) + usartdiv = (uint16_t)(UART_DIV_SAMPLING8(HAL_RCC_GetPCLK1Freq(), huart->Init.BaudRate, huart->Init.ClockPrescaler)); +#else + usartdiv = (uint16_t)(UART_DIV_SAMPLING8(HAL_RCC_GetPCLK1Freq(), huart->Init.BaudRate)); +#endif + break; + case UART_CLOCKSOURCE_PCLK2: +#if defined(USART_PRESC_PRESCALER) + usartdiv = (uint16_t)(UART_DIV_SAMPLING8(HAL_RCC_GetPCLK2Freq(), huart->Init.BaudRate, huart->Init.ClockPrescaler)); +#else + usartdiv = (uint16_t)(UART_DIV_SAMPLING8(HAL_RCC_GetPCLK2Freq(), huart->Init.BaudRate)); +#endif + break; + case UART_CLOCKSOURCE_HSI: +#if defined(USART_PRESC_PRESCALER) + usartdiv = (uint16_t)(UART_DIV_SAMPLING8(HSI_VALUE, huart->Init.BaudRate, huart->Init.ClockPrescaler)); +#else + usartdiv = (uint16_t)(UART_DIV_SAMPLING8(HSI_VALUE, huart->Init.BaudRate)); +#endif + break; + case UART_CLOCKSOURCE_SYSCLK: +#if defined(USART_PRESC_PRESCALER) + usartdiv = (uint16_t)(UART_DIV_SAMPLING8(HAL_RCC_GetSysClockFreq(), huart->Init.BaudRate, huart->Init.ClockPrescaler)); +#else + usartdiv = (uint16_t)(UART_DIV_SAMPLING8(HAL_RCC_GetSysClockFreq(), huart->Init.BaudRate)); +#endif + break; + case UART_CLOCKSOURCE_LSE: +#if defined(USART_PRESC_PRESCALER) + usartdiv = (uint16_t)(UART_DIV_SAMPLING8(LSE_VALUE, huart->Init.BaudRate, huart->Init.ClockPrescaler)); +#else + usartdiv = (uint16_t)(UART_DIV_SAMPLING8(LSE_VALUE, huart->Init.BaudRate)); +#endif + break; + case UART_CLOCKSOURCE_UNDEFINED: + default: + ret = HAL_ERROR; + break; + } + + /* USARTDIV must be greater than or equal to 0d16 */ + if ((usartdiv >= UART_BRR_MIN) && (usartdiv <= UART_BRR_MAX)) + { + brrtemp = usartdiv & 0xFFF0U; + brrtemp |= (uint16_t)((usartdiv & (uint16_t)0x000FU) >> 1U); + huart->Instance->BRR = brrtemp; + } + else + { + ret = HAL_ERROR; + } + } + else + { + switch (clocksource) + { + case UART_CLOCKSOURCE_PCLK1: +#if defined(USART_PRESC_PRESCALER) + usartdiv = (uint16_t)(UART_DIV_SAMPLING16(HAL_RCC_GetPCLK1Freq(), huart->Init.BaudRate, huart->Init.ClockPrescaler)); +#else + usartdiv = (uint16_t)(UART_DIV_SAMPLING16(HAL_RCC_GetPCLK1Freq(), huart->Init.BaudRate)); +#endif + break; + case UART_CLOCKSOURCE_PCLK2: +#if defined(USART_PRESC_PRESCALER) + usartdiv = (uint16_t)(UART_DIV_SAMPLING16(HAL_RCC_GetPCLK2Freq(), huart->Init.BaudRate, huart->Init.ClockPrescaler)); +#else + usartdiv = (uint16_t)(UART_DIV_SAMPLING16(HAL_RCC_GetPCLK2Freq(), huart->Init.BaudRate)); +#endif + break; + case UART_CLOCKSOURCE_HSI: +#if defined(USART_PRESC_PRESCALER) + usartdiv = (uint16_t)(UART_DIV_SAMPLING16(HSI_VALUE, huart->Init.BaudRate, huart->Init.ClockPrescaler)); +#else + usartdiv = (uint16_t)(UART_DIV_SAMPLING16(HSI_VALUE, huart->Init.BaudRate)); +#endif + break; + case UART_CLOCKSOURCE_SYSCLK: +#if defined(USART_PRESC_PRESCALER) + usartdiv = (uint16_t)(UART_DIV_SAMPLING16(HAL_RCC_GetSysClockFreq(), huart->Init.BaudRate, huart->Init.ClockPrescaler)); +#else + usartdiv = (uint16_t)(UART_DIV_SAMPLING16(HAL_RCC_GetSysClockFreq(), huart->Init.BaudRate)); +#endif + break; + case UART_CLOCKSOURCE_LSE: +#if defined(USART_PRESC_PRESCALER) + usartdiv = (uint16_t)(UART_DIV_SAMPLING16(LSE_VALUE, huart->Init.BaudRate, huart->Init.ClockPrescaler)); +#else + usartdiv = (uint16_t)(UART_DIV_SAMPLING16(LSE_VALUE, huart->Init.BaudRate)); +#endif + break; + case UART_CLOCKSOURCE_UNDEFINED: + default: + ret = HAL_ERROR; + break; + } + + /* USARTDIV must be greater than or equal to 0d16 */ + if ((usartdiv >= UART_BRR_MIN) && (usartdiv <= UART_BRR_MAX)) + { + huart->Instance->BRR = usartdiv; + } + else + { + ret = HAL_ERROR; + } + } + +#if defined(USART_CR1_FIFOEN) + /* Initialize the number of data to process during RX/TX ISR execution */ + huart->NbTxDataToProcess = 1; + huart->NbRxDataToProcess = 1; +#endif + + /* Clear ISR function pointers */ + huart->RxISR = NULL; + huart->TxISR = NULL; + + return ret; +} + +/** + * @brief Configure the UART peripheral advanced features. + * @param huart UART handle. + * @retval None + */ +void UART_AdvFeatureConfig(UART_HandleTypeDef *huart) +{ + /* Check whether the set of advanced features to configure is properly set */ + assert_param(IS_UART_ADVFEATURE_INIT(huart->AdvancedInit.AdvFeatureInit)); + + /* if required, configure TX pin active level inversion */ + if(HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_TXINVERT_INIT)) + { + assert_param(IS_UART_ADVFEATURE_TXINV(huart->AdvancedInit.TxPinLevelInvert)); + MODIFY_REG(huart->Instance->CR2, USART_CR2_TXINV, huart->AdvancedInit.TxPinLevelInvert); + } + + /* if required, configure RX pin active level inversion */ + if(HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_RXINVERT_INIT)) + { + assert_param(IS_UART_ADVFEATURE_RXINV(huart->AdvancedInit.RxPinLevelInvert)); + MODIFY_REG(huart->Instance->CR2, USART_CR2_RXINV, huart->AdvancedInit.RxPinLevelInvert); + } + + /* if required, configure data inversion */ + if(HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_DATAINVERT_INIT)) + { + assert_param(IS_UART_ADVFEATURE_DATAINV(huart->AdvancedInit.DataInvert)); + MODIFY_REG(huart->Instance->CR2, USART_CR2_DATAINV, huart->AdvancedInit.DataInvert); + } + + /* if required, configure RX/TX pins swap */ + if(HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_SWAP_INIT)) + { + assert_param(IS_UART_ADVFEATURE_SWAP(huart->AdvancedInit.Swap)); + MODIFY_REG(huart->Instance->CR2, USART_CR2_SWAP, huart->AdvancedInit.Swap); + } + + /* if required, configure RX overrun detection disabling */ + if(HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_RXOVERRUNDISABLE_INIT)) + { + assert_param(IS_UART_OVERRUN(huart->AdvancedInit.OverrunDisable)); + MODIFY_REG(huart->Instance->CR3, USART_CR3_OVRDIS, huart->AdvancedInit.OverrunDisable); + } + + /* if required, configure DMA disabling on reception error */ + if(HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_DMADISABLEONERROR_INIT)) + { + assert_param(IS_UART_ADVFEATURE_DMAONRXERROR(huart->AdvancedInit.DMADisableonRxError)); + MODIFY_REG(huart->Instance->CR3, USART_CR3_DDRE, huart->AdvancedInit.DMADisableonRxError); + } + + /* if required, configure auto Baud rate detection scheme */ + if(HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_AUTOBAUDRATE_INIT)) + { + assert_param(IS_USART_AUTOBAUDRATE_DETECTION_INSTANCE(huart->Instance)); + assert_param(IS_UART_ADVFEATURE_AUTOBAUDRATE(huart->AdvancedInit.AutoBaudRateEnable)); + MODIFY_REG(huart->Instance->CR2, USART_CR2_ABREN, huart->AdvancedInit.AutoBaudRateEnable); + /* set auto Baudrate detection parameters if detection is enabled */ + if(huart->AdvancedInit.AutoBaudRateEnable == UART_ADVFEATURE_AUTOBAUDRATE_ENABLE) + { + assert_param(IS_UART_ADVFEATURE_AUTOBAUDRATEMODE(huart->AdvancedInit.AutoBaudRateMode)); + MODIFY_REG(huart->Instance->CR2, USART_CR2_ABRMODE, huart->AdvancedInit.AutoBaudRateMode); + } + } + + /* if required, configure MSB first on communication line */ + if(HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_MSBFIRST_INIT)) + { + assert_param(IS_UART_ADVFEATURE_MSBFIRST(huart->AdvancedInit.MSBFirst)); + MODIFY_REG(huart->Instance->CR2, USART_CR2_MSBFIRST, huart->AdvancedInit.MSBFirst); + } +} + +/** + * @brief Check the UART Idle State. + * @param huart UART handle. + * @retval HAL status + */ +HAL_StatusTypeDef UART_CheckIdleState(UART_HandleTypeDef *huart) +{ + uint32_t tickstart = 0U; + + /* Initialize the UART ErrorCode */ + huart->ErrorCode = HAL_UART_ERROR_NONE; + + /* Init tickstart for timeout managment*/ + tickstart = HAL_GetTick(); + + /* Check if the Transmitter is enabled */ + if((huart->Instance->CR1 & USART_CR1_TE) == USART_CR1_TE) + { + /* Wait until TEACK flag is set */ + if(UART_WaitOnFlagUntilTimeout(huart, USART_ISR_TEACK, RESET, tickstart, HAL_UART_TIMEOUT_VALUE) != HAL_OK) + { + /* Timeout occurred */ + return HAL_TIMEOUT; + } + } + /* Check if the Receiver is enabled */ + if((huart->Instance->CR1 & USART_CR1_RE) == USART_CR1_RE) + { + /* Wait until REACK flag is set */ + if(UART_WaitOnFlagUntilTimeout(huart, USART_ISR_REACK, RESET, tickstart, HAL_UART_TIMEOUT_VALUE) != HAL_OK) + { + /* Timeout occurred */ + return HAL_TIMEOUT; + } + } + + /* Initialize the UART State */ + huart->gState= HAL_UART_STATE_READY; + huart->RxState= HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +/** + * @brief Handle UART Communication Timeout. + * @param huart UART handle. + * @param Flag Specifies the UART flag to check + * @param Status Flag status (SET or RESET) + * @param Tickstart Tick start value + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef UART_WaitOnFlagUntilTimeout(UART_HandleTypeDef *huart, uint32_t Flag, FlagStatus Status, uint32_t Tickstart, uint32_t Timeout) +{ + /* Wait until flag is set */ + while((__HAL_UART_GET_FLAG(huart, Flag) ? SET : RESET) == Status) + { + /* Check for the Timeout */ + if(Timeout != HAL_MAX_DELAY) + { + if((Timeout == 0U) || ((HAL_GetTick()-Tickstart) > Timeout)) + { + /* Disable TXE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts for the interrupt process */ +#if defined(USART_CR1_FIFOEN) + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE | USART_CR1_TXEIE_TXFNFIE)); +#else + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE)); +#endif + CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + huart->gState = HAL_UART_STATE_READY; + huart->RxState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_TIMEOUT; + } + } + } + return HAL_OK; +} + + +/** + * @brief End ongoing Tx transfer on UART peripheral (following error detection or Transmit completion). + * @param huart UART handle. + * @retval None + */ +static void UART_EndTxTransfer(UART_HandleTypeDef *huart) +{ + /* Disable TXEIE and TCIE interrupts */ +#if defined(USART_CR1_FIFOEN) + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_TXEIE_TXFNFIE | USART_CR1_TCIE)); +#else + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE)); +#endif + + /* At end of Tx process, restore huart->gState to Ready */ + huart->gState = HAL_UART_STATE_READY; +} + + +/** + * @brief End ongoing Rx transfer on UART peripheral (following error detection or Reception completion). + * @param huart UART handle. + * @retval None + */ +static void UART_EndRxTransfer(UART_HandleTypeDef *huart) +{ + /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ +#if defined(USART_CR1_FIFOEN) + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE)); +#else + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE)); +#endif + CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* At end of Rx process, restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + + /* Reset RxIsr function pointer */ + huart->RxISR = NULL; +} + + +/** + * @brief DMA UART transmit process complete callback. + * @param hdma DMA handle. + * @retval None + */ +static void UART_DMATransmitCplt(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef* huart = (UART_HandleTypeDef*)(hdma->Parent); + + /* DMA Normal mode */ + if ( HAL_IS_BIT_CLR(hdma->Instance->CCR, DMA_CCR_CIRC) ) + { + huart->TxXferCount = 0U; + + /* Disable the DMA transfer for transmit request by resetting the DMAT bit + in the UART CR3 register */ + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT); + + /* Enable the UART Transmit Complete Interrupt */ + SET_BIT(huart->Instance->CR1, USART_CR1_TCIE); + } + /* DMA Circular mode */ + else + { + HAL_UART_TxCpltCallback(huart); + } +} + +/** + * @brief DMA UART transmit process half complete callback. + * @param hdma DMA handle. + * @retval None + */ +static void UART_DMATxHalfCplt(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef* huart = (UART_HandleTypeDef*)(hdma->Parent); + + HAL_UART_TxHalfCpltCallback(huart); +} + +/** + * @brief DMA UART receive process complete callback. + * @param hdma DMA handle. + * @retval None + */ +static void UART_DMAReceiveCplt(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef* huart = (UART_HandleTypeDef*)(hdma->Parent); + + /* DMA Normal mode */ + if ( HAL_IS_BIT_CLR(hdma->Instance->CCR, DMA_CCR_CIRC) ) + { + huart->RxXferCount = 0U; + + /* Disable PE and ERR (Frame error, noise error, overrun error) interrupts */ + CLEAR_BIT(huart->Instance->CR1, USART_CR1_PEIE); + CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Disable the DMA transfer for the receiver request by resetting the DMAR bit + in the UART CR3 register */ + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + /* At end of Rx process, restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + } + + HAL_UART_RxCpltCallback(huart); +} + +/** + * @brief DMA UART receive process half complete callback. + * @param hdma DMA handle. + * @retval None + */ +static void UART_DMARxHalfCplt(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef* huart = (UART_HandleTypeDef*)(hdma->Parent); + + HAL_UART_RxHalfCpltCallback(huart); +} + +/** + * @brief DMA UART communication error callback. + * @param hdma DMA handle. + * @retval None + */ +static void UART_DMAError(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef* huart = (UART_HandleTypeDef*)(hdma->Parent); + + /* Stop UART DMA Tx request if ongoing */ + if ( (huart->gState == HAL_UART_STATE_BUSY_TX) + &&(HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT)) ) + { + huart->TxXferCount = 0U; + UART_EndTxTransfer(huart); + } + + /* Stop UART DMA Rx request if ongoing */ + if ( (huart->RxState == HAL_UART_STATE_BUSY_RX) + &&(HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) ) + { + huart->RxXferCount = 0U; + UART_EndRxTransfer(huart); + } + + huart->ErrorCode |= HAL_UART_ERROR_DMA; + HAL_UART_ErrorCallback(huart); +} + +/** + * @brief DMA UART communication abort callback, when initiated by HAL services on Error + * (To be called at end of DMA Abort procedure following error occurrence). + * @param hdma DMA handle. + * @retval None + */ +static void UART_DMAAbortOnError(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef* huart = (UART_HandleTypeDef*)(hdma->Parent); + huart->RxXferCount = 0U; + huart->TxXferCount = 0U; + + HAL_UART_ErrorCallback(huart); +} + +/** + * @brief DMA UART Tx communication abort callback, when initiated by user + * (To be called at end of DMA Tx Abort procedure following user abort request). + * @note When this callback is executed, User Abort complete call back is called only if no + * Abort still ongoing for Rx DMA Handle. + * @param hdma DMA handle. + * @retval None + */ +static void UART_DMATxAbortCallback(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef* huart = (UART_HandleTypeDef* )(hdma->Parent); + + huart->hdmatx->XferAbortCallback = NULL; + + /* Check if an Abort process is still ongoing */ + if(huart->hdmarx != NULL) + { + if(huart->hdmarx->XferAbortCallback != NULL) + { + return; + } + } + + /* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */ + huart->TxXferCount = 0U; + huart->RxXferCount = 0U; + + /* Reset errorCode */ + huart->ErrorCode = HAL_UART_ERROR_NONE; + + /* Clear the Error flags in the ICR register */ + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_PEF | UART_CLEAR_FEF); + +#if defined(USART_CR1_FIFOEN) + /* Flush the whole TX FIFO (if needed) */ + if (huart->FifoMode == UART_FIFOMODE_ENABLE) + { + __HAL_UART_SEND_REQ(huart, UART_TXDATA_FLUSH_REQUEST); + } +#endif + + /* Restore huart->gState and huart->RxState to Ready */ + huart->gState = HAL_UART_STATE_READY; + huart->RxState = HAL_UART_STATE_READY; + + /* Call user Abort complete callback */ + HAL_UART_AbortCpltCallback(huart); +} + + +/** + * @brief DMA UART Rx communication abort callback, when initiated by user + * (To be called at end of DMA Rx Abort procedure following user abort request). + * @note When this callback is executed, User Abort complete call back is called only if no + * Abort still ongoing for Tx DMA Handle. + * @param hdma DMA handle. + * @retval None + */ +static void UART_DMARxAbortCallback(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef* huart = (UART_HandleTypeDef* )(hdma->Parent); + + huart->hdmarx->XferAbortCallback = NULL; + + /* Check if an Abort process is still ongoing */ + if(huart->hdmatx != NULL) + { + if(huart->hdmatx->XferAbortCallback != NULL) + { + return; + } + } + + /* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */ + huart->TxXferCount = 0U; + huart->RxXferCount = 0U; + + /* Reset errorCode */ + huart->ErrorCode = HAL_UART_ERROR_NONE; + + /* Clear the Error flags in the ICR register */ + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_PEF | UART_CLEAR_FEF); + + /* Discard the received data */ + __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST); + + /* Restore huart->gState and huart->RxState to Ready */ + huart->gState = HAL_UART_STATE_READY; + huart->RxState = HAL_UART_STATE_READY; + + /* Call user Abort complete callback */ + HAL_UART_AbortCpltCallback(huart); +} + + +/** + * @brief DMA UART Tx communication abort callback, when initiated by user by a call to + * HAL_UART_AbortTransmit_IT API (Abort only Tx transfer) + * (This callback is executed at end of DMA Tx Abort procedure following user abort request, + * and leads to user Tx Abort Complete callback execution). + * @param hdma DMA handle. + * @retval None + */ +static void UART_DMATxOnlyAbortCallback(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef* huart = (UART_HandleTypeDef*)(hdma->Parent); + + huart->TxXferCount = 0U; + +#if defined(USART_CR1_FIFOEN) + /* Flush the whole TX FIFO (if needed) */ + if (huart->FifoMode == UART_FIFOMODE_ENABLE) + { + __HAL_UART_SEND_REQ(huart, UART_TXDATA_FLUSH_REQUEST); + } +#endif + + /* Restore huart->gState to Ready */ + huart->gState = HAL_UART_STATE_READY; + + /* Call user Abort complete callback */ + HAL_UART_AbortTransmitCpltCallback(huart); +} + +/** + * @brief DMA UART Rx communication abort callback, when initiated by user by a call to + * HAL_UART_AbortReceive_IT API (Abort only Rx transfer) + * (This callback is executed at end of DMA Rx Abort procedure following user abort request, + * and leads to user Rx Abort Complete callback execution). + * @param hdma DMA handle. + * @retval None + */ +static void UART_DMARxOnlyAbortCallback(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef* huart = ( UART_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; + + huart->RxXferCount = 0U; + + /* Clear the Error flags in the ICR register */ + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_PEF | UART_CLEAR_FEF); + + /* Discard the received data */ + __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST); + + /* Restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + + /* Call user Abort complete callback */ + HAL_UART_AbortReceiveCpltCallback(huart); +} + +/** + * @brief TX interrrupt handler for 7 or 8 bits data word length . + * @note Function is called under interruption only, once + * interruptions have been enabled by HAL_UART_Transmit_IT(). + * @param huart UART handle. + * @retval None + */ +static void UART_TxISR_8BIT(UART_HandleTypeDef *huart) +{ + /* Check that a Tx process is ongoing */ + if (huart->gState == HAL_UART_STATE_BUSY_TX) + { + if(huart->TxXferCount == 0) + { + /* Disable the UART Transmit Data Register Empty Interrupt */ +#if defined(USART_CR1_FIFOEN) + CLEAR_BIT(huart->Instance->CR1, USART_CR1_TXEIE_TXFNFIE); +#else + CLEAR_BIT(huart->Instance->CR1, USART_CR1_TXEIE); +#endif + + /* Enable the UART Transmit Complete Interrupt */ + SET_BIT(huart->Instance->CR1, USART_CR1_TCIE); + } + else + { + huart->Instance->TDR = (uint8_t)(*huart->pTxBuffPtr++ & (uint8_t)0xFF); + huart->TxXferCount--; + } + } +} + +/** + * @brief TX interrrupt handler for 9 bits data word length. + * @note Function is called under interruption only, once + * interruptions have been enabled by HAL_UART_Transmit_IT(). + * @param huart UART handle. + * @retval None + */ +static void UART_TxISR_16BIT(UART_HandleTypeDef *huart) +{ + uint16_t* tmp; + + /* Check that a Tx process is ongoing */ + if (huart->gState == HAL_UART_STATE_BUSY_TX) + { + if(huart->TxXferCount == 0) + { + /* Disable the UART Transmit Data Register Empty Interrupt */ +#if defined(USART_CR1_FIFOEN) + CLEAR_BIT(huart->Instance->CR1, USART_CR1_TXEIE_TXFNFIE); +#else + CLEAR_BIT(huart->Instance->CR1, USART_CR1_TXEIE); +#endif + + /* Enable the UART Transmit Complete Interrupt */ + SET_BIT(huart->Instance->CR1, USART_CR1_TCIE); + } + else + { + tmp = (uint16_t*) huart->pTxBuffPtr; + huart->Instance->TDR = (*tmp & (uint16_t)0x01FF); + huart->pTxBuffPtr += 2; + huart->TxXferCount--; + } + } +} + +#if defined(USART_CR1_FIFOEN) +/** + * @brief TX interrrupt handler for 7 or 8 bits data word length and FIFO mode is enabled. + * @note Function is called under interruption only, once + * interruptions have been enabled by HAL_UART_Transmit_IT(). + * @param huart UART handle. + * @retval None + */ +static void UART_TxISR_8BIT_FIFOEN(UART_HandleTypeDef *huart) +{ + uint8_t nb_tx_data; + + /* Check that a Tx process is ongoing */ + if (huart->gState == HAL_UART_STATE_BUSY_TX) + { + for(nb_tx_data = huart->NbTxDataToProcess ; nb_tx_data > 0 ; nb_tx_data--) + { + if(huart->TxXferCount == 0U) + { + /* Disable the TX FIFO threshold interrupt */ + CLEAR_BIT(huart->Instance->CR3, USART_CR3_TXFTIE); + + /* Enable the UART Transmit Complete Interrupt */ + SET_BIT(huart->Instance->CR1, USART_CR1_TCIE); + + break; /* force exit loop */ + } + else if (READ_BIT(huart->Instance->ISR, USART_ISR_TXE_TXFNF) != RESET) + { + huart->Instance->TDR = (uint8_t)(*huart->pTxBuffPtr++ & (uint8_t)0xFF); + huart->TxXferCount--; + } + } + } +} + +/** + * @brief TX interrrupt handler for 9 bits data word length and FIFO mode is enabled. + * @note Function is called under interruption only, once + * interruptions have been enabled by HAL_UART_Transmit_IT(). + * @param huart UART handle. + * @retval None + */ +static void UART_TxISR_16BIT_FIFOEN(UART_HandleTypeDef *huart) +{ + uint16_t* tmp; + uint8_t nb_tx_data; + + /* Check that a Tx process is ongoing */ + if (huart->gState == HAL_UART_STATE_BUSY_TX) + { + for(nb_tx_data = huart->NbTxDataToProcess ; nb_tx_data > 0 ; nb_tx_data--) + { + if(huart->TxXferCount == 0U) + { + /* Disable the TX FIFO threshold interrupt */ + CLEAR_BIT(huart->Instance->CR3, USART_CR3_TXFTIE); + + /* Enable the UART Transmit Complete Interrupt */ + SET_BIT(huart->Instance->CR1, USART_CR1_TCIE); + + break; /* force exit loop */ + } + else if (READ_BIT(huart->Instance->ISR, USART_ISR_TXE_TXFNF) != RESET) + { + tmp = (uint16_t*) huart->pTxBuffPtr; + huart->Instance->TDR = (*tmp & (uint16_t)0x01FFU); + huart->pTxBuffPtr += 2U; + huart->TxXferCount--; + } + } + } +} +#endif + +/** + * @brief Wrap up transmission in non-blocking mode. + * @param huart pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval None + */ +static void UART_EndTransmit_IT(UART_HandleTypeDef *huart) +{ + /* Disable the UART Transmit Complete Interrupt */ + CLEAR_BIT(huart->Instance->CR1, USART_CR1_TCIE); + + /* Tx process is ended, restore huart->gState to Ready */ + huart->gState = HAL_UART_STATE_READY; + + /* Cleat TxISR function pointer */ + huart->TxISR = NULL; + + HAL_UART_TxCpltCallback(huart); +} + +/** + * @brief RX interrrupt handler for 7 or 8 bits data word length . + * @param huart UART handle. + * @retval None + */ +static void UART_RxISR_8BIT(UART_HandleTypeDef *huart) +{ + uint16_t uhMask = huart->Mask; + uint16_t uhdata; + + /* Check that a Rx process is ongoing */ + if(huart->RxState == HAL_UART_STATE_BUSY_RX) + { + uhdata = (uint16_t) READ_REG(huart->Instance->RDR); + *huart->pRxBuffPtr++ = (uint8_t)(uhdata & (uint8_t)uhMask); + + if(--huart->RxXferCount == 0) + { + /* Disable the UART Parity Error Interrupt and RXNE interrupt*/ +#if defined(USART_CR1_FIFOEN) + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE)); +#else + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE)); +#endif + + /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */ + CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Rx process is completed, restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + + /* Clear RxISR function pointer */ + huart->RxISR = NULL; + + HAL_UART_RxCpltCallback(huart); + } + } + else + { + /* Clear RXNE interrupt flag */ + __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST); + } +} + +/** + * @brief RX interrrupt handler for 9 bits data word length . + * @note Function is called under interruption only, once + * interruptions have been enabled by HAL_UART_Receive_IT() + * @param huart UART handle. + * @retval None + */ +static void UART_RxISR_16BIT(UART_HandleTypeDef *huart) +{ + uint16_t* tmp; + uint16_t uhMask = huart->Mask; + uint16_t uhdata; + + /* Check that a Rx process is ongoing */ + if(huart->RxState == HAL_UART_STATE_BUSY_RX) + { + uhdata = (uint16_t) READ_REG(huart->Instance->RDR); + tmp = (uint16_t*) huart->pRxBuffPtr ; + *tmp = (uint16_t)(uhdata & uhMask); + huart->pRxBuffPtr +=2; + + if(--huart->RxXferCount == 0) + { + /* Disable the UART Parity Error Interrupt and RXNE interrupt*/ +#if defined(USART_CR1_FIFOEN) + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE_RXFNEIE | USART_CR1_PEIE)); +#else + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE)); +#endif + + /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */ + CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Rx process is completed, restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + + /* Clear RxISR function pointer */ + huart->RxISR = NULL; + + HAL_UART_RxCpltCallback(huart); + } + } + else + { + /* Clear RXNE interrupt flag */ + __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST); + } +} + +#if defined(USART_CR1_FIFOEN) +/** + * @brief RX interrrupt handler for 7 or 8 bits data word length and FIFO mode is enabled. + * @note Function is called under interruption only, once + * interruptions have been enabled by HAL_UART_Receive_IT() + * @param huart UART handle. + * @retval None + */ +static void UART_RxISR_8BIT_FIFOEN(UART_HandleTypeDef *huart) +{ + uint16_t uhMask = huart->Mask; + uint16_t uhdata; + uint8_t nb_rx_data; + + /* Check that a Rx process is ongoing */ + if(huart->RxState == HAL_UART_STATE_BUSY_RX) + { + for(nb_rx_data = huart->NbRxDataToProcess ; nb_rx_data > 0 ; nb_rx_data--) + { + uhdata = (uint16_t) READ_REG(huart->Instance->RDR); + *huart->pRxBuffPtr++ = (uint8_t)(uhdata & (uint8_t)uhMask); + huart->RxXferCount--; + + if(huart->RxXferCount == 0U) + { + /* Disable the UART Parity Error Interrupt and RXFT interrupt*/ + CLEAR_BIT(huart->Instance->CR1, USART_CR1_PEIE); + + /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) and RX FIFO Threshold interrupt */ + CLEAR_BIT(huart->Instance->CR3, (USART_CR3_EIE | USART_CR3_RXFTIE)); + + /* Rx process is completed, restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + + /* Clear RxISR function pointer */ + huart->RxISR = NULL; + + HAL_UART_RxCpltCallback(huart); + } + } + + /* When remaining number of bytes to receive is less than the RX FIFO + threshold, next incoming frames are processed as if FIFO mode was + disabled (i.e. one interrupt per received frame). + */ + if (((huart->RxXferCount != 0U)) && (huart->RxXferCount < huart->NbRxDataToProcess)) + { + /* Disable the UART RXFT interrupt*/ + CLEAR_BIT(huart->Instance->CR3, USART_CR3_RXFTIE); + + /* Update the RxISR function pointer */ + huart->RxISR = UART_RxISR_8BIT; + + /* Enable the UART Data Register Not Empty interrupt */ + SET_BIT(huart->Instance->CR1, USART_CR1_RXNEIE_RXFNEIE); + } + } + else + { + /* Clear RXNE interrupt flag */ + __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST); + } +} + +/** + * @brief RX interrrupt handler for 9 bits data word length and FIFO mode is enabled. + * @note Function is called under interruption only, once + * interruptions have been enabled by HAL_UART_Receive_IT() + * @param huart UART handle. + * @retval None + */ +static void UART_RxISR_16BIT_FIFOEN(UART_HandleTypeDef *huart) +{ + uint16_t* tmp; + uint16_t uhMask = huart->Mask; + uint16_t uhdata; + uint8_t nb_rx_data; + + /* Check that a Rx process is ongoing */ + if(huart->RxState == HAL_UART_STATE_BUSY_RX) + { + for(nb_rx_data = huart->NbRxDataToProcess ; nb_rx_data > 0 ; nb_rx_data--) + { + uhdata = (uint16_t) READ_REG(huart->Instance->RDR); + tmp = (uint16_t*) huart->pRxBuffPtr ; + *tmp = (uint16_t)(uhdata & uhMask); + huart->pRxBuffPtr +=2; + huart->RxXferCount--; + + if(huart->RxXferCount == 0U) + { + /* Disable the UART Parity Error Interrupt and RXFT interrupt*/ + CLEAR_BIT(huart->Instance->CR1, USART_CR1_PEIE); + + /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) and RX FIFO Threshold interrupt */ + CLEAR_BIT(huart->Instance->CR3, (USART_CR3_EIE | USART_CR3_RXFTIE)); + + /* Rx process is completed, restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + + /* Clear RxISR function pointer */ + huart->RxISR = NULL; + + HAL_UART_RxCpltCallback(huart); + } + } + + /* When remaining number of bytes to receive is less than the RX FIFO + threshold, next incoming frames are processed as if FIFO mode was + disabled (i.e. one interrupt per received frame). + */ + if (((huart->RxXferCount != 0U)) && (huart->RxXferCount < huart->NbRxDataToProcess)) + { + /* Disable the UART RXFT interrupt*/ + CLEAR_BIT(huart->Instance->CR3, USART_CR3_RXFTIE); + + /* Update the RxISR function pointer */ + huart->RxISR = UART_RxISR_16BIT; + + /* Enable the UART Data Register Not Empty interrupt */ + SET_BIT(huart->Instance->CR1, USART_CR1_RXNEIE_RXFNEIE); + } + } + else + { + /* Clear RXNE interrupt flag */ + __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST); + } +} +#endif + +/** + * @} + */ + +#endif /* HAL_UART_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_uart_ex.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_uart_ex.c new file mode 100644 index 0000000..c8c80f5 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_uart_ex.c @@ -0,0 +1,900 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_uart_ex.c + * @author MCD Application Team + * @brief Extended UART HAL module driver. + * This file provides firmware functions to manage the following extended + * functionalities of the Universal Asynchronous Receiver Transmitter Peripheral (UART). + * + Initialization and de-initialization functions + * + Peripheral Control functions + * + * + @verbatim + ============================================================================== + ##### UART peripheral extended features ##### + ============================================================================== + + (#) Declare a UART_HandleTypeDef handle structure. + + (#) For the UART RS485 Driver Enable mode, initialize the UART registers + by calling the HAL_RS485Ex_Init() API. + + (#) FIFO mode enabling/disabling and RX/TX FIFO threshold programming. + + -@- When USART operates in FIFO mode, FIFO mode must be enabled prior + starting RX/TX transfers. Also RX/TX FIFO thresholds must be + configured prior starting RX/TX transfers. + + (#) Slave mode enabling/disabling and NSS pin configuration. + + -@- When USART operates in Slave mode, Slave mode must be enabled prior + starting RX/TX transfers. + + @endverbatim + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @addtogroup STM32L4xx_HAL_Driver + * @{ + */ + +/** @defgroup UARTEx UARTEx + * @brief UART Extended HAL module driver + * @{ + */ + +#ifdef HAL_UART_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/** @defgroup UARTEx_Private_Functions UARTEx Private Functions + * @{ + */ +static void UARTEx_Wakeup_AddressConfig(UART_HandleTypeDef *huart, UART_WakeUpTypeDef WakeUpSelection); +#if defined(USART_CR1_FIFOEN) +static void UARTEx_SetNbDataToProcess(UART_HandleTypeDef *huart); +#endif +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup UARTEx_Exported_Functions UARTEx Exported Functions + * @{ + */ + +/** @defgroup UARTEx_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Extended Initialization and Configuration Functions + * +@verbatim +=============================================================================== + ##### Initialization and Configuration functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to initialize the USARTx or the UARTy + in asynchronous mode. + (+) For the asynchronous mode the parameters below can be configured: + (++) Baud Rate + (++) Word Length + (++) Stop Bit + (++) Parity: If the parity is enabled, then the MSB bit of the data written + in the data register is transmitted but is changed by the parity bit. + (++) Hardware flow control + (++) Receiver/transmitter modes + (++) Over Sampling Method + (++) One-Bit Sampling Method + (+) For the asynchronous mode, the following advanced features can be configured as well: + (++) TX and/or RX pin level inversion + (++) data logical level inversion + (++) RX and TX pins swap + (++) RX overrun detection disabling + (++) DMA disabling on RX error + (++) MSB first on communication line + (++) auto Baud rate detection + [..] + The HAL_RS485Ex_Init() API follows the UART RS485 mode configuration + procedures (details for the procedures are available in reference manual). + +@endverbatim + + Depending on the frame length defined by the M1 and M0 bits (7-bit, + 8-bit or 9-bit), the possible UART formats are listed in the + following table. + + Table 1. UART frame format. + +-----------------------------------------------------------------------+ + | M1 bit | M0 bit | PCE bit | UART frame | + |---------|---------|-----------|---------------------------------------| + | 0 | 0 | 0 | | SB | 8 bit data | STB | | + |---------|---------|-----------|---------------------------------------| + | 0 | 0 | 1 | | SB | 7 bit data | PB | STB | | + |---------|---------|-----------|---------------------------------------| + | 0 | 1 | 0 | | SB | 9 bit data | STB | | + |---------|---------|-----------|---------------------------------------| + | 0 | 1 | 1 | | SB | 8 bit data | PB | STB | | + |---------|---------|-----------|---------------------------------------| + | 1 | 0 | 0 | | SB | 7 bit data | STB | | + |---------|---------|-----------|---------------------------------------| + | 1 | 0 | 1 | | SB | 6 bit data | PB | STB | | + +-----------------------------------------------------------------------+ + + * @{ + */ + +/** + * @brief Initialize the RS485 Driver enable feature according to the specified + * parameters in the UART_InitTypeDef and creates the associated handle. + * @param huart UART handle. + * @param Polarity Select the driver enable polarity. + * This parameter can be one of the following values: + * @arg @ref UART_DE_POLARITY_HIGH DE signal is active high + * @arg @ref UART_DE_POLARITY_LOW DE signal is active low + * @param AssertionTime Driver Enable assertion time: + * 5-bit value defining the time between the activation of the DE (Driver Enable) + * signal and the beginning of the start bit. It is expressed in sample time + * units (1/8 or 1/16 bit time, depending on the oversampling rate) + * @param DeassertionTime Driver Enable deassertion time: + * 5-bit value defining the time between the end of the last stop bit, in a + * transmitted message, and the de-activation of the DE (Driver Enable) signal. + * It is expressed in sample time units (1/8 or 1/16 bit time, depending on the + * oversampling rate). + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RS485Ex_Init(UART_HandleTypeDef *huart, uint32_t Polarity, uint32_t AssertionTime, uint32_t DeassertionTime) +{ + uint32_t temp = 0x0; + + /* Check the UART handle allocation */ + if(huart == NULL) + { + return HAL_ERROR; + } + /* Check the Driver Enable UART instance */ + assert_param(IS_UART_DRIVER_ENABLE_INSTANCE(huart->Instance)); + + /* Check the Driver Enable polarity */ + assert_param(IS_UART_DE_POLARITY(Polarity)); + + /* Check the Driver Enable assertion time */ + assert_param(IS_UART_ASSERTIONTIME(AssertionTime)); + + /* Check the Driver Enable deassertion time */ + assert_param(IS_UART_DEASSERTIONTIME(DeassertionTime)); + + if(huart->gState == HAL_UART_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + huart->Lock = HAL_UNLOCKED; + + /* Init the low level hardware : GPIO, CLOCK, CORTEX */ + HAL_UART_MspInit(huart); + } + + huart->gState = HAL_UART_STATE_BUSY; + + /* Disable the Peripheral */ + __HAL_UART_DISABLE(huart); + + /* Set the UART Communication parameters */ + if (UART_SetConfig(huart) == HAL_ERROR) + { + return HAL_ERROR; + } + + if(huart->AdvancedInit.AdvFeatureInit != UART_ADVFEATURE_NO_INIT) + { + UART_AdvFeatureConfig(huart); + } + + /* Enable the Driver Enable mode by setting the DEM bit in the CR3 register */ + SET_BIT(huart->Instance->CR3, USART_CR3_DEM); + + /* Set the Driver Enable polarity */ + MODIFY_REG(huart->Instance->CR3, USART_CR3_DEP, Polarity); + + /* Set the Driver Enable assertion and deassertion times */ + temp = (AssertionTime << UART_CR1_DEAT_ADDRESS_LSB_POS); + temp |= (DeassertionTime << UART_CR1_DEDT_ADDRESS_LSB_POS); + MODIFY_REG(huart->Instance->CR1, (USART_CR1_DEDT|USART_CR1_DEAT), temp); + + /* Enable the Peripheral */ + __HAL_UART_ENABLE(huart); + + /* TEACK and/or REACK to check before moving huart->gState and huart->RxState to Ready */ + return (UART_CheckIdleState(huart)); +} + + +/** + * @} + */ + +/** @defgroup UARTEx_Exported_Functions_Group2 IO operation functions + * @brief Extended functions + * +@verbatim + =============================================================================== + ##### IO operation functions ##### + =============================================================================== + This subsection provides a set of Wakeup and FIFO mode related callback functions. + + (#) Wakeup from Stop mode Callback: + (+) HAL_UARTEx_WakeupCallback() + + (#) TX/RX Fifos Callbacks: + (+) HAL_UARTEx_RxFifoFullCallback() + (+) HAL_UARTEx_TxFifoEmptyCallback() + +@endverbatim + * @{ + */ + +/** + * @brief UART wakeup from Stop mode callback. + * @param huart UART handle. + * @retval None + */ + __weak void HAL_UARTEx_WakeupCallback(UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_UARTEx_WakeupCallback can be implemented in the user file. + */ +} + +#if defined(USART_CR1_FIFOEN) +/** + * @brief UART RX Fifo full callback. + * @param huart UART handle. + * @retval None + */ +__weak void HAL_UARTEx_RxFifoFullCallback (UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_UARTEx_RxFifoFullCallback can be implemented in the user file. + */ +} + +/** + * @brief UART TX Fifo empty callback. + * @param huart UART handle. + * @retval None + */ +__weak void HAL_UARTEx_TxFifoEmptyCallback (UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_UARTEx_TxFifoEmptyCallback can be implemented in the user file. + */ +} +#endif + +/** + * @} + */ + +/** @defgroup UARTEx_Exported_Functions_Group3 Peripheral Control functions + * @brief Extended Peripheral Control functions + * +@verbatim + =============================================================================== + ##### Peripheral Control functions ##### + =============================================================================== + [..] This section provides the following functions: + (+) HAL_UARTEx_EnableClockStopMode() API enables the UART clock (HSI or LSE only) during stop mode + (+) HAL_UARTEx_DisableClockStopMode() API disables the above functionality + (+) HAL_MultiProcessorEx_AddressLength_Set() API optionally sets the UART node address + detection length to more than 4 bits for multiprocessor address mark wake up. + (+) HAL_UARTEx_StopModeWakeUpSourceConfig() API defines the wake-up from stop mode + trigger: address match, Start Bit detection or RXNE bit status. + (+) HAL_UARTEx_EnableStopMode() API enables the UART to wake up the MCU from stop mode + (+) HAL_UARTEx_DisableStopMode() API disables the above functionality + (+) HAL_UARTEx_WakeupCallback() called upon UART wakeup interrupt + (+) HAL_UARTEx_EnableSPISlaveMode() API enables the SPI slave mode + (+) HAL_UARTEx_DisableSPISlaveMode() API disables the SPI slave mode + (+) HAL_UARTEx_ConfigNSS API configures the Slave Select input pin (NSS) + (+) HAL_UARTEx_EnableFifoMode() API enables the FIFO mode + (+) HAL_UARTEx_DisableFifoMode() API disables the FIFO mode + (+) HAL_UARTEx_SetTxFifoThreshold() API sets the TX FIFO threshold + (+) HAL_UARTEx_SetRxFifoThreshold() API sets the RX FIFO threshold + +@endverbatim + * @{ + */ + + + + +/** + * @brief By default in multiprocessor mode, when the wake up method is set + * to address mark, the UART handles only 4-bit long addresses detection; + * this API allows to enable longer addresses detection (6-, 7- or 8-bit + * long). + * @note Addresses detection lengths are: 6-bit address detection in 7-bit data mode, + * 7-bit address detection in 8-bit data mode, 8-bit address detection in 9-bit data mode. + * @param huart UART handle. + * @param AddressLength This parameter can be one of the following values: + * @arg @ref UART_ADDRESS_DETECT_4B 4-bit long address + * @arg @ref UART_ADDRESS_DETECT_7B 6-, 7- or 8-bit long address + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MultiProcessorEx_AddressLength_Set(UART_HandleTypeDef *huart, uint32_t AddressLength) +{ + /* Check the UART handle allocation */ + if(huart == NULL) + { + return HAL_ERROR; + } + + /* Check the address length parameter */ + assert_param(IS_UART_ADDRESSLENGTH_DETECT(AddressLength)); + + huart->gState = HAL_UART_STATE_BUSY; + + /* Disable the Peripheral */ + __HAL_UART_DISABLE(huart); + + /* Set the address length */ + MODIFY_REG(huart->Instance->CR2, USART_CR2_ADDM7, AddressLength); + + /* Enable the Peripheral */ + __HAL_UART_ENABLE(huart); + + /* TEACK and/or REACK to check before moving huart->gState to Ready */ + return (UART_CheckIdleState(huart)); +} + + +/** + * @brief Set Wakeup from Stop mode interrupt flag selection. + * @note It is the application responsibility to enable the interrupt used as + * usart_wkup interrupt source before entering low-power mode. + * @param huart UART handle. + * @param WakeUpSelection Address match, Start Bit detection or RXNE/RXFNE bit status. + * This parameter can be one of the following values: + * @arg @ref UART_WAKEUP_ON_ADDRESS + * @arg @ref UART_WAKEUP_ON_STARTBIT + * @arg @ref UART_WAKEUP_ON_READDATA_NONEMPTY + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UARTEx_StopModeWakeUpSourceConfig(UART_HandleTypeDef *huart, UART_WakeUpTypeDef WakeUpSelection) +{ + HAL_StatusTypeDef status = HAL_OK; + uint32_t tickstart = 0; + + /* check the wake-up from stop mode UART instance */ + assert_param(IS_UART_WAKEUP_FROMSTOP_INSTANCE(huart->Instance)); + /* check the wake-up selection parameter */ + assert_param(IS_UART_WAKEUP_SELECTION(WakeUpSelection.WakeUpEvent)); + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->gState = HAL_UART_STATE_BUSY; + + /* Disable the Peripheral */ + __HAL_UART_DISABLE(huart); + + /* Set the wake-up selection scheme */ + MODIFY_REG(huart->Instance->CR3, USART_CR3_WUS, WakeUpSelection.WakeUpEvent); + + if (WakeUpSelection.WakeUpEvent == UART_WAKEUP_ON_ADDRESS) + { + UARTEx_Wakeup_AddressConfig(huart, WakeUpSelection); + } + + /* Enable the Peripheral */ + __HAL_UART_ENABLE(huart); + + /* Init tickstart for timeout managment*/ + tickstart = HAL_GetTick(); + + /* Wait until REACK flag is set */ + if(UART_WaitOnFlagUntilTimeout(huart, USART_ISR_REACK, RESET, tickstart, HAL_UART_TIMEOUT_VALUE) != HAL_OK) + { + status = HAL_TIMEOUT; + } + else + { + /* Initialize the UART State */ + huart->gState = HAL_UART_STATE_READY; + } + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return status; +} + + +/** + * @brief Enable UART Stop Mode. + * @note The UART is able to wake up the MCU from Stop 1 mode as long as UART clock is HSI or LSE. + * @param huart UART handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UARTEx_EnableStopMode(UART_HandleTypeDef *huart) +{ + /* Process Locked */ + __HAL_LOCK(huart); + + huart->gState = HAL_UART_STATE_BUSY; + + /* Set UESM bit */ + SET_BIT(huart->Instance->CR1, USART_CR1_UESM); + + huart->gState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +/** + * @brief Disable UART Stop Mode. + * @param huart UART handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UARTEx_DisableStopMode(UART_HandleTypeDef *huart) +{ + /* Process Locked */ + __HAL_LOCK(huart); + + huart->gState = HAL_UART_STATE_BUSY; + + /* Clear UESM bit */ + CLEAR_BIT(huart->Instance->CR1, USART_CR1_UESM); + + huart->gState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +#if defined(USART_CR2_SLVEN) +/** + * @brief Enable the SPI slave mode. + * @note When the UART operates in SPI slave mode, it handles data flow using + * the serial interface clock derived from the external SCLK signal + * provided by the external master SPI device. + * @note In SPI slave mode, the UART must be enabled before starting the master + * communications (or between frames while the clock is stable). Otherwise, + * if the UART slave is enabled while the master is in the middle of a + * frame, it will become desynchronized with the master. + * @note The data register of the slave needs to be ready before the first edge + * of the communication clock or before the end of the ongoing communication, + * otherwise the SPI slave will transmit zeros. + * @param huart UART handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UARTEx_EnableSlaveMode(UART_HandleTypeDef *huart) +{ + uint32_t tmpcr1 = 0; + + /* Check parameters */ + assert_param(IS_UART_SPI_SLAVE_INSTANCE(huart->Instance)); + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->gState = HAL_UART_STATE_BUSY; + + /* Save actual UART configuration */ + tmpcr1 = READ_REG(huart->Instance->CR1); + + /* Disable UART */ + __HAL_UART_DISABLE(huart); + + /* In SPI slave mode mode, the following bits must be kept cleared: + - LINEN and CLKEN bit in the USART_CR2 register + - HDSEL, SCEN and IREN bits in the USART_CR3 register.*/ + CLEAR_BIT(huart->Instance->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN)); + CLEAR_BIT(huart->Instance->CR3, (USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN)); + + /* Enable SPI slave mode */ + SET_BIT(huart->Instance->CR2, USART_CR2_SLVEN); + + /* Restore UART configuration */ + WRITE_REG(huart->Instance->CR1, tmpcr1); + + huart->SlaveMode = UART_SLAVEMODE_ENABLE; + + huart->gState = HAL_UART_STATE_READY; + + /* Enable UART */ + __HAL_UART_ENABLE(huart); + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +/** + * @brief Disable the SPI slave mode. + * @param huart UART handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UARTEx_DisableSlaveMode(UART_HandleTypeDef *huart) +{ + uint32_t tmpcr1 = 0; + + /* Check parameters */ + assert_param(IS_UART_SPI_SLAVE_INSTANCE(huart->Instance)); + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->gState = HAL_UART_STATE_BUSY; + + /* Save actual UART configuration */ + tmpcr1 = READ_REG(huart->Instance->CR1); + + /* Disable UART */ + __HAL_UART_DISABLE(huart); + + /* Disable SPI slave mode */ + CLEAR_BIT(huart->Instance->CR2, USART_CR2_SLVEN); + + /* Restore UART configuration */ + WRITE_REG(huart->Instance->CR1, tmpcr1); + + huart->SlaveMode = UART_SLAVEMODE_ENABLE; + + huart->gState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +/** + * @brief Configure the Slave Select input pin (NSS). + * @note Software NSS management: SPI slave will always be selected and NSS + * input pin will be ignored. + * @note Hardware NSS management: the SPI slave selection depends on NSS + * input pin. The slave is selected when NSS is low and deselected when + * NSS is high. + * @param huart UART handle. + * @param NSSConfig NSS configuration. + * This parameter can be one of the following values: + * @arg @ref UART_NSS_HARD + * @arg @ref UART_NSS_SOFT + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UARTEx_ConfigNSS(UART_HandleTypeDef *huart, uint32_t NSSConfig) +{ + uint32_t tmpcr1 = 0; + + /* Check parameters */ + assert_param(IS_UART_SPI_SLAVE_INSTANCE(huart->Instance)); + assert_param(IS_UART_NSS(NSSConfig)); + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->gState = HAL_UART_STATE_BUSY; + + /* Save actual UART configuration */ + tmpcr1 = READ_REG(huart->Instance->CR1); + + /* Disable UART */ + __HAL_UART_DISABLE(huart); + + /* Program DIS_NSS bit in the USART_CR2 register */ + MODIFY_REG(huart->Instance->CR2, USART_CR2_DIS_NSS, NSSConfig); + + /* Restore UART configuration */ + WRITE_REG(huart->Instance->CR1, tmpcr1); + + huart->gState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} +#endif + +#if defined(USART_CR1_FIFOEN) +/** + * @brief Enable the FIFO mode. + * @param huart UART handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UARTEx_EnableFifoMode(UART_HandleTypeDef *huart) +{ + uint32_t tmpcr1 = 0; + + /* Check parameters */ + assert_param(IS_UART_FIFO_INSTANCE(huart->Instance)); + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->gState = HAL_UART_STATE_BUSY; + + /* Save actual UART configuration */ + tmpcr1 = READ_REG(huart->Instance->CR1); + + /* Disable UART */ + __HAL_UART_DISABLE(huart); + + /* Enable FIFO mode */ + SET_BIT(tmpcr1, USART_CR1_FIFOEN); + huart->FifoMode = UART_FIFOMODE_ENABLE; + + /* Restore UART configuration */ + WRITE_REG(huart->Instance->CR1, tmpcr1); + + /* Determine the number of data to process during RX/TX ISR execution */ + UARTEx_SetNbDataToProcess(huart); + + huart->gState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +/** + * @brief Disable the FIFO mode. + * @param huart UART handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UARTEx_DisableFifoMode(UART_HandleTypeDef *huart) +{ + uint32_t tmpcr1 = 0; + + /* Check parameters */ + assert_param(IS_UART_FIFO_INSTANCE(huart->Instance)); + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->gState = HAL_UART_STATE_BUSY; + + /* Save actual UART configuration */ + tmpcr1 = READ_REG(huart->Instance->CR1); + + /* Disable UART */ + __HAL_UART_DISABLE(huart); + + /* Enable FIFO mode */ + CLEAR_BIT(tmpcr1, USART_CR1_FIFOEN); + huart->FifoMode = UART_FIFOMODE_DISABLE; + + /* Restore UART configuration */ + WRITE_REG(huart->Instance->CR1, tmpcr1); + + huart->gState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +/** + * @brief Set the TXFIFO threshold. + * @param huart UART handle. + * @param Threshold TX FIFO threshold value + * This parameter can be one of the following values: + * @arg @ref UART_TXFIFO_THRESHOLD_1_8 + * @arg @ref UART_TXFIFO_THRESHOLD_1_4 + * @arg @ref UART_TXFIFO_THRESHOLD_1_2 + * @arg @ref UART_TXFIFO_THRESHOLD_3_4 + * @arg @ref UART_TXFIFO_THRESHOLD_7_8 + * @arg @ref UART_TXFIFO_THRESHOLD_8_8 + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UARTEx_SetTxFifoThreshold(UART_HandleTypeDef *huart, uint32_t Threshold) +{ + uint32_t tmpcr1 = 0; + + /* Check parameters */ + assert_param(IS_UART_FIFO_INSTANCE(huart->Instance)); + assert_param(IS_UART_TXFIFO_THRESHOLD(Threshold)); + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->gState = HAL_UART_STATE_BUSY; + + /* Save actual UART configuration */ + tmpcr1 = READ_REG(huart->Instance->CR1); + + /* Disable UART */ + __HAL_UART_DISABLE(huart); + + /* Update TX threshold configuration */ + MODIFY_REG(huart->Instance->CR3, USART_CR3_TXFTCFG, Threshold); + + /* Determine the number of data to process during RX/TX ISR execution */ + UARTEx_SetNbDataToProcess(huart); + + /* Restore UART configuration */ + WRITE_REG(huart->Instance->CR1, tmpcr1); + + huart->gState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +/** + * @brief Set the RXFIFO threshold. + * @param huart UART handle. + * @param Threshold RX FIFO threshold value + * This parameter can be one of the following values: + * @arg @ref UART_RXFIFO_THRESHOLD_1_8 + * @arg @ref UART_RXFIFO_THRESHOLD_1_4 + * @arg @ref UART_RXFIFO_THRESHOLD_1_2 + * @arg @ref UART_RXFIFO_THRESHOLD_3_4 + * @arg @ref UART_RXFIFO_THRESHOLD_7_8 + * @arg @ref UART_RXFIFO_THRESHOLD_8_8 + * @retval HAL status + */ +HAL_StatusTypeDef HAL_UARTEx_SetRxFifoThreshold(UART_HandleTypeDef *huart, uint32_t Threshold) +{ + uint32_t tmpcr1 = 0; + + /* Check the parameters */ + assert_param(IS_UART_FIFO_INSTANCE(huart->Instance)); + assert_param(IS_UART_RXFIFO_THRESHOLD(Threshold)); + + /* Process Locked */ + __HAL_LOCK(huart); + + huart->gState = HAL_UART_STATE_BUSY; + + /* Save actual UART configuration */ + tmpcr1 = READ_REG(huart->Instance->CR1); + + /* Disable UART */ + __HAL_UART_DISABLE(huart); + + /* Update RX threshold configuration */ + MODIFY_REG(huart->Instance->CR3, USART_CR3_RXFTCFG, Threshold); + + /* Determine the number of data to process during RX/TX ISR execution */ + UARTEx_SetNbDataToProcess(huart); + + /* Restore UART configuration */ + WRITE_REG(huart->Instance->CR1, tmpcr1); + + huart->gState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} +#endif + +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup UARTEx_Private_Functions + * @{ + */ + +/** + * @brief Initialize the UART wake-up from stop mode parameters when triggered by address detection. + * @param huart UART handle. + * @param WakeUpSelection UART wake up from stop mode parameters. + * @retval None + */ +static void UARTEx_Wakeup_AddressConfig(UART_HandleTypeDef *huart, UART_WakeUpTypeDef WakeUpSelection) +{ + assert_param(IS_UART_ADDRESSLENGTH_DETECT(WakeUpSelection.AddressLength)); + + /* Set the USART address length */ + MODIFY_REG(huart->Instance->CR2, USART_CR2_ADDM7, WakeUpSelection.AddressLength); + + /* Set the USART address node */ + MODIFY_REG(huart->Instance->CR2, USART_CR2_ADD, ((uint32_t)WakeUpSelection.Address << UART_CR2_ADDRESS_LSB_POS)); +} + +#if defined(USART_CR1_FIFOEN) +/** + * @brief Calculate the number of data to process in RX/TX ISR. + * @note The RX FIFO depth and the TX FIFO depth is extracted from + * the UART configuration registers. + * @param huart UART handle. + * @retval None + */ +void UARTEx_SetNbDataToProcess(UART_HandleTypeDef *huart) +{ + uint8_t rx_fifo_depth; + uint8_t tx_fifo_depth; + uint8_t rx_fifo_threshold; + uint8_t tx_fifo_threshold; + uint8_t numerator[] = {1, 1, 1, 3, 7, 1}; + uint8_t denominator[] = {8, 4, 2, 4, 8, 1}; + + if (huart->FifoMode == UART_FIFOMODE_DISABLE) + { + huart->NbTxDataToProcess = 1; + huart->NbRxDataToProcess = 1; + } + else + { + rx_fifo_depth = 8; /* RX Fifo size */ + tx_fifo_depth = 8; /* TX Fifo size */ + rx_fifo_threshold = (uint8_t)(READ_BIT(huart->Instance->CR3, USART_CR3_RXFTCFG) >> USART_CR3_RXFTCFG_Pos); + tx_fifo_threshold = (uint8_t)(READ_BIT(huart->Instance->CR3, USART_CR3_TXFTCFG) >> USART_CR3_TXFTCFG_Pos); + huart->NbTxDataToProcess = (uint8_t)(tx_fifo_depth * numerator[tx_fifo_threshold])/denominator[tx_fifo_threshold]; + huart->NbRxDataToProcess = (uint8_t)(rx_fifo_depth * numerator[rx_fifo_threshold])/denominator[rx_fifo_threshold]; + } +} +#endif + +/** + * @} + */ + +#endif /* HAL_UART_MODULE_ENABLED */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_usb.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_usb.c new file mode 100644 index 0000000..875c0c5 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_usb.c @@ -0,0 +1,2397 @@ +/** + ****************************************************************************** + * @file stm32l4xx_ll_usb.c + * @author MCD Application Team + * @brief USB Low Layer HAL module driver. + * + * This file provides firmware functions to manage the following + * functionalities of the USB Peripheral Controller: + * + Initialization/de-initialization functions + * + I/O operation functions + * + Peripheral Control functions + * + Peripheral State functions + * + @verbatim + ============================================================================== + ##### How to use this driver ##### + ============================================================================== + [..] + (#) Fill parameters of Init structure in USB_OTG_CfgTypeDef structure. + + (#) Call USB_CoreInit() API to initialize the USB Core peripheral. + + (#) The upper HAL HCD/PCD driver will call the right routines for its internal processes. + + @endverbatim + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +/** @defgroup USB_LL USB Low Layer + * @brief Low layer module for USB_FS and USB_OTG_FS drivers + * @{ + */ +#if defined (HAL_PCD_MODULE_ENABLED) || defined (HAL_HCD_MODULE_ENABLED) + +#if defined(STM32L432xx) || defined(STM32L433xx) || defined(STM32L442xx) || defined(STM32L443xx) || \ + defined(STM32L452xx) || defined(STM32L462xx) || \ + defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || \ + defined(STM32L496xx) || defined(STM32L4A6xx) || \ + defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + +/** @addtogroup STM32L4xx_LL_USB_DRIVER + * @{ + */ + + + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ +#if defined (USB_OTG_FS) +/** @defgroup USB_LL_Private_Functions USB Low Layer Private Functions + * @{ + */ +static HAL_StatusTypeDef USB_CoreReset(USB_OTG_GlobalTypeDef *USBx); +/** + * @} + */ +#endif /* USB_OTG_FS */ +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup LL_USB_Exported_Functions USB Low Layer Exported Functions + * @{ + */ + +/** @defgroup LL_USB_Group1 Initialization/de-initialization functions + * @brief Initialization and Configuration functions + * +@verbatim + =============================================================================== + ##### Initialization/de-initialization functions ##### + =============================================================================== + [..] This section provides functions allowing to: + +@endverbatim + * @{ + */ +/*============================================================================== + USB OTG FS peripheral available on STM32L475xx, STM32L476xx, STM32L485xx and + STM32L486xx devices +==============================================================================*/ +#if defined (USB_OTG_FS) +/** + * @brief Initializes the USB Core + * @param USBx: USB Instance + * @param cfg: pointer to a USB_OTG_CfgTypeDef structure that contains + * the configuration information for the specified USBx peripheral. + * @retval HAL status + */ +HAL_StatusTypeDef USB_CoreInit(USB_OTG_GlobalTypeDef *USBx, USB_OTG_CfgTypeDef cfg) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(cfg); + + /* Select FS Embedded PHY */ + USBx->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL; + + /* Reset after a PHY select and set Host mode */ + USB_CoreReset(USBx); + + /* Deactivate the power down*/ + USBx->GCCFG = USB_OTG_GCCFG_PWRDWN; + + return HAL_OK; +} + +/** + * @brief USB_EnableGlobalInt + * Enables the controller's Global Int in the AHB Config reg + * @param USBx: Selected device + * @retval HAL status + */ +HAL_StatusTypeDef USB_EnableGlobalInt(USB_OTG_GlobalTypeDef *USBx) +{ + USBx->GAHBCFG |= USB_OTG_GAHBCFG_GINT; + return HAL_OK; +} + + +/** + * @brief USB_DisableGlobalInt + * Disable the controller's Global Int in the AHB Config reg + * @param USBx: Selected device + * @retval HAL status +*/ +HAL_StatusTypeDef USB_DisableGlobalInt(USB_OTG_GlobalTypeDef *USBx) +{ + USBx->GAHBCFG &= ~USB_OTG_GAHBCFG_GINT; + return HAL_OK; +} + +/** + * @brief USB_SetCurrentMode : Set functional mode + * @param USBx: Selected device + * @param mode: current core mode + * This parameter can be one of these values: + * @arg USB_OTG_DEVICE_MODE: Peripheral mode + * @arg USB_OTG_HOST_MODE: Host mode + * @arg USB_OTG_DRD_MODE: Dual Role Device mode + * @retval HAL status + */ +HAL_StatusTypeDef USB_SetCurrentMode(USB_OTG_GlobalTypeDef *USBx , USB_ModeTypeDef mode) +{ + USBx->GUSBCFG &= ~(USB_OTG_GUSBCFG_FHMOD | USB_OTG_GUSBCFG_FDMOD); + + if ( mode == USB_HOST_MODE) + { + USBx->GUSBCFG |= USB_OTG_GUSBCFG_FHMOD; + } + else if ( mode == USB_DEVICE_MODE) + { + USBx->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD; + } + HAL_Delay(50); + + return HAL_OK; +} + +/** + * @brief USB_DevInit : Initializes the USB_OTG controller registers + * for device mode + * @param USBx: Selected device + * @param cfg: pointer to a USB_OTG_CfgTypeDef structure that contains + * the configuration information for the specified USBx peripheral. + * @retval HAL status + */ +HAL_StatusTypeDef USB_DevInit (USB_OTG_GlobalTypeDef *USBx, USB_OTG_CfgTypeDef cfg) +{ + uint32_t index = 0; + + /*Activate VBUS Sensing B */ + USBx->GCCFG |= USB_OTG_GCCFG_VBDEN; + + if (cfg.vbus_sensing_enable == 0) + { + /* Deactivate VBUS Sensing B */ + USBx->GCCFG &= ~ USB_OTG_GCCFG_VBDEN; + + /* B-peripheral session valid override enable*/ + USBx->GOTGCTL |= USB_OTG_GOTGCTL_BVALOEN; + USBx->GOTGCTL |= USB_OTG_GOTGCTL_BVALOVAL; + } + + /* Restart the Phy Clock */ + USBx_PCGCCTL = 0; + + /* Device mode configuration */ + USBx_DEVICE->DCFG |= DCFG_FRAME_INTERVAL_80; + + /* Set Full speed phy */ + USB_SetDevSpeed (USBx , USB_OTG_SPEED_FULL); + + /* Flush the FIFOs */ + USB_FlushTxFifo(USBx , 0x10); /* all Tx FIFOs */ + USB_FlushRxFifo(USBx); + + /* Clear all pending Device Interrupts */ + USBx_DEVICE->DIEPMSK = 0; + USBx_DEVICE->DOEPMSK = 0; + USBx_DEVICE->DAINT = 0xFFFFFFFF; + USBx_DEVICE->DAINTMSK = 0; + + for (index = 0; index < cfg.dev_endpoints; index++) + { + if ((USBx_INEP(index)->DIEPCTL & USB_OTG_DIEPCTL_EPENA) == USB_OTG_DIEPCTL_EPENA) + { + USBx_INEP(index)->DIEPCTL = (USB_OTG_DIEPCTL_EPDIS | USB_OTG_DIEPCTL_SNAK); + } + else + { + USBx_INEP(index)->DIEPCTL = 0; + } + + USBx_INEP(index)->DIEPTSIZ = 0; + USBx_INEP(index)->DIEPINT = 0xFF; + } + + for (index = 0; index < cfg.dev_endpoints; index++) + { + if ((USBx_OUTEP(index)->DOEPCTL & USB_OTG_DOEPCTL_EPENA) == USB_OTG_DOEPCTL_EPENA) + { + USBx_OUTEP(index)->DOEPCTL = (USB_OTG_DOEPCTL_EPDIS | USB_OTG_DOEPCTL_SNAK); + } + else + { + USBx_OUTEP(index)->DOEPCTL = 0; + } + + USBx_OUTEP(index)->DOEPTSIZ = 0; + USBx_OUTEP(index)->DOEPINT = 0xFF; + } + + USBx_DEVICE->DIEPMSK &= ~(USB_OTG_DIEPMSK_TXFURM); + + if (cfg.dma_enable == 1) + { + /*Set threshold parameters */ + USBx_DEVICE->DTHRCTL = (USB_OTG_DTHRCTL_TXTHRLEN_6 | USB_OTG_DTHRCTL_RXTHRLEN_6); + USBx_DEVICE->DTHRCTL |= (USB_OTG_DTHRCTL_RXTHREN | USB_OTG_DTHRCTL_ISOTHREN | USB_OTG_DTHRCTL_NONISOTHREN); + + index= USBx_DEVICE->DTHRCTL; + } + + /* Disable all interrupts. */ + USBx->GINTMSK = 0; + + /* Clear any pending interrupts */ + USBx->GINTSTS = 0xBFFFFFFF; + + /* Enable the common interrupts */ + if (cfg.dma_enable == DISABLE) + { + USBx->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM; + } + + /* Enable interrupts matching to the Device mode ONLY */ + USBx->GINTMSK |= (USB_OTG_GINTMSK_USBSUSPM | USB_OTG_GINTMSK_USBRST |\ + USB_OTG_GINTMSK_ENUMDNEM | USB_OTG_GINTMSK_IEPINT |\ + USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IISOIXFRM|\ + USB_OTG_GINTMSK_PXFRM_IISOOXFRM | USB_OTG_GINTMSK_WUIM); + + if(cfg.Sof_enable) + { + USBx->GINTMSK |= USB_OTG_GINTMSK_SOFM; + } + + if (cfg.vbus_sensing_enable == ENABLE) + { + USBx->GINTMSK |= (USB_OTG_GINTMSK_SRQIM | USB_OTG_GINTMSK_OTGINT); + } + + return HAL_OK; +} + + +/** + * @brief USB_OTG_FlushTxFifo : Flush a Tx FIFO + * @param USBx: Selected device + * @param num: FIFO number + * This parameter can be a value from 1 to 15 + 15 means Flush all Tx FIFOs + * @retval HAL status + */ +HAL_StatusTypeDef USB_FlushTxFifo (USB_OTG_GlobalTypeDef *USBx, uint32_t num) +{ + uint32_t count = 0; + + USBx->GRSTCTL = ( USB_OTG_GRSTCTL_TXFFLSH |(uint32_t)( num << 6)); + + do + { + if (++count > 200000) + { + return HAL_TIMEOUT; + } + } + while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_TXFFLSH) == USB_OTG_GRSTCTL_TXFFLSH); + + return HAL_OK; +} + + +/** + * @brief USB_FlushRxFifo : Flush Rx FIFO + * @param USBx: Selected device + * @retval HAL status + */ +HAL_StatusTypeDef USB_FlushRxFifo(USB_OTG_GlobalTypeDef *USBx) +{ + uint32_t count = 0; + + USBx->GRSTCTL = USB_OTG_GRSTCTL_RXFFLSH; + + do + { + if (++count > 200000) + { + return HAL_TIMEOUT; + } + } + while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_RXFFLSH) == USB_OTG_GRSTCTL_RXFFLSH); + + return HAL_OK; +} + +/** + * @brief USB_SetDevSpeed :Initializes the DevSpd field of DCFG register + * depending the PHY type and the enumeration speed of the device. + * @param USBx: Selected device + * @param speed: device speed + * This parameter can be one of these values: + * @arg USB_OTG_SPEED_HIGH: High speed mode + * @arg USB_OTG_SPEED_HIGH_IN_FULL: High speed core in Full Speed mode + * @arg USB_OTG_SPEED_FULL: Full speed mode + * @arg USB_OTG_SPEED_LOW: Low speed mode + * @retval Hal status + */ +HAL_StatusTypeDef USB_SetDevSpeed(USB_OTG_GlobalTypeDef *USBx , uint8_t speed) +{ + USBx_DEVICE->DCFG |= speed; + return HAL_OK; +} + +/** + * @brief USB_GetDevSpeed :Return the Dev Speed + * @param USBx: Selected device + * @retval speed : device speed + * This parameter can be one of these values: + * @arg USB_OTG_SPEED_HIGH: High speed mode + * @arg USB_OTG_SPEED_FULL: Full speed mode + * @arg USB_OTG_SPEED_LOW: Low speed mode + */ +uint8_t USB_GetDevSpeed(USB_OTG_GlobalTypeDef *USBx) +{ + uint8_t speed = 0; + + if((USBx_DEVICE->DSTS & USB_OTG_DSTS_ENUMSPD) == DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ) + { + speed = USB_OTG_SPEED_HIGH; + } + else if (((USBx_DEVICE->DSTS & USB_OTG_DSTS_ENUMSPD) == DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ)|| + ((USBx_DEVICE->DSTS & USB_OTG_DSTS_ENUMSPD) == DSTS_ENUMSPD_FS_PHY_48MHZ)) + { + speed = USB_OTG_SPEED_FULL; + } + else if((USBx_DEVICE->DSTS & USB_OTG_DSTS_ENUMSPD) == DSTS_ENUMSPD_LS_PHY_6MHZ) + { + speed = USB_OTG_SPEED_LOW; + } + + return speed; +} + +/** + * @brief Activate and configure an endpoint + * @param USBx: Selected device + * @param ep: pointer to endpoint structure + * @retval HAL status + */ +HAL_StatusTypeDef USB_ActivateEndpoint(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep) +{ + if (ep->is_in == 1) + { + USBx_DEVICE->DAINTMSK |= USB_OTG_DAINTMSK_IEPM & ((1 << (ep->num))); + + if (((USBx_INEP(ep->num)->DIEPCTL) & USB_OTG_DIEPCTL_USBAEP) == 0) + { + USBx_INEP(ep->num)->DIEPCTL |= ((ep->maxpacket & USB_OTG_DIEPCTL_MPSIZ ) | (ep->type << 18 ) |\ + ((ep->num) << 22 ) | (USB_OTG_DIEPCTL_SD0PID_SEVNFRM) | (USB_OTG_DIEPCTL_USBAEP)); + } + + } + else + { + USBx_DEVICE->DAINTMSK |= USB_OTG_DAINTMSK_OEPM & ((1 << (ep->num)) << 16); + + if (((USBx_OUTEP(ep->num)->DOEPCTL) & USB_OTG_DOEPCTL_USBAEP) == 0) + { + USBx_OUTEP(ep->num)->DOEPCTL |= ((ep->maxpacket & USB_OTG_DOEPCTL_MPSIZ ) | (ep->type << 18 ) |\ + (USB_OTG_DIEPCTL_SD0PID_SEVNFRM)| (USB_OTG_DOEPCTL_USBAEP)); + } + } + return HAL_OK; +} +/** + * @brief Activate and configure a dedicated endpoint + * @param USBx: Selected device + * @param ep: pointer to endpoint structure + * @retval HAL status + */ +HAL_StatusTypeDef USB_ActivateDedicatedEndpoint(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep) +{ + static __IO uint32_t debug = 0; + + /* Read DEPCTLn register */ + if (ep->is_in == 1) + { + if (((USBx_INEP(ep->num)->DIEPCTL) & USB_OTG_DIEPCTL_USBAEP) == 0) + { + USBx_INEP(ep->num)->DIEPCTL |= ((ep->maxpacket & USB_OTG_DIEPCTL_MPSIZ ) | (ep->type << 18 ) |\ + ((ep->num) << 22 ) | (USB_OTG_DIEPCTL_SD0PID_SEVNFRM) | (USB_OTG_DIEPCTL_USBAEP)); + } + + + debug |= ((ep->maxpacket & USB_OTG_DIEPCTL_MPSIZ ) | (ep->type << 18 ) |\ + ((ep->num) << 22 ) | (USB_OTG_DIEPCTL_SD0PID_SEVNFRM) | (USB_OTG_DIEPCTL_USBAEP)); + + USBx_DEVICE->DEACHMSK |= USB_OTG_DAINTMSK_IEPM & ((1 << (ep->num))); + } + else + { + if (((USBx_OUTEP(ep->num)->DOEPCTL) & USB_OTG_DOEPCTL_USBAEP) == 0) + { + USBx_OUTEP(ep->num)->DOEPCTL |= ((ep->maxpacket & USB_OTG_DOEPCTL_MPSIZ ) | (ep->type << 18 ) |\ + ((ep->num) << 22 ) | (USB_OTG_DOEPCTL_USBAEP)); + + debug = (uint32_t)(((uint32_t )USBx) + USB_OTG_OUT_ENDPOINT_BASE + (0)*USB_OTG_EP_REG_SIZE); + debug = (uint32_t )&USBx_OUTEP(ep->num)->DOEPCTL; + debug |= ((ep->maxpacket & USB_OTG_DOEPCTL_MPSIZ ) | (ep->type << 18 ) |\ + ((ep->num) << 22 ) | (USB_OTG_DOEPCTL_USBAEP)); + } + + USBx_DEVICE->DEACHMSK |= USB_OTG_DAINTMSK_OEPM & ((1 << (ep->num)) << 16); + } + + return HAL_OK; +} +/** + * @brief De-activate and de-initialize an endpoint + * @param USBx: Selected device + * @param ep: pointer to endpoint structure + * @retval HAL status + */ +HAL_StatusTypeDef USB_DeactivateEndpoint(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep) +{ + /* Read DEPCTLn register */ + if (ep->is_in == 1) + { + USBx_DEVICE->DEACHMSK &= ~(USB_OTG_DAINTMSK_IEPM & ((1 << (ep->num)))); + USBx_DEVICE->DAINTMSK &= ~(USB_OTG_DAINTMSK_IEPM & ((1 << (ep->num)))); + USBx_INEP(ep->num)->DIEPCTL &= ~ USB_OTG_DIEPCTL_USBAEP; + } + else + { + USBx_DEVICE->DEACHMSK &= ~(USB_OTG_DAINTMSK_OEPM & ((1 << (ep->num)) << 16)); + USBx_DEVICE->DAINTMSK &= ~(USB_OTG_DAINTMSK_OEPM & ((1 << (ep->num)) << 16)); + USBx_OUTEP(ep->num)->DOEPCTL &= ~USB_OTG_DOEPCTL_USBAEP; + } + return HAL_OK; +} + +/** + * @brief De-activate and de-initialize a dedicated endpoint + * @param USBx: Selected device + * @param ep: pointer to endpoint structure + * @retval HAL status + */ +HAL_StatusTypeDef USB_DeactivateDedicatedEndpoint(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep) +{ + /* Read DEPCTLn register */ + if (ep->is_in == 1) + { + USBx_INEP(ep->num)->DIEPCTL &= ~ USB_OTG_DIEPCTL_USBAEP; + USBx_DEVICE->DAINTMSK &= ~(USB_OTG_DAINTMSK_IEPM & ((1 << (ep->num)))); + } + else + { + USBx_OUTEP(ep->num)->DOEPCTL &= ~USB_OTG_DOEPCTL_USBAEP; + USBx_DEVICE->DAINTMSK &= ~(USB_OTG_DAINTMSK_OEPM & ((1 << (ep->num)) << 16)); + } + return HAL_OK; +} + +/** + * @brief USB_EPStartXfer : setup and starts a transfer over an EP + * @param USBx: Selected device + * @param ep: pointer to endpoint structure + * @param dma: USB dma enabled or disabled + * This parameter can be one of these values: + * 0 : DMA feature not used + * 1 : DMA feature used + * @retval HAL status + */ +HAL_StatusTypeDef USB_EPStartXfer(USB_OTG_GlobalTypeDef *USBx , USB_OTG_EPTypeDef *ep, uint8_t dma) +{ + uint16_t pktcnt = 0; + + /* IN endpoint */ + if (ep->is_in == 1) + { + /* Zero Length Packet? */ + if (ep->xfer_len == 0) + { + USBx_INEP(ep->num)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_PKTCNT); + USBx_INEP(ep->num)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_PKTCNT & (1 << 19)) ; + USBx_INEP(ep->num)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_XFRSIZ); + } + else + { + /* Program the transfer size and packet count + * as follows: xfersize = N * maxpacket + + * short_packet pktcnt = N + (short_packet + * exist ? 1 : 0) + */ + USBx_INEP(ep->num)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_XFRSIZ); + USBx_INEP(ep->num)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_PKTCNT); + USBx_INEP(ep->num)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_PKTCNT & (((ep->xfer_len + ep->maxpacket -1)/ ep->maxpacket) << 19)) ; + USBx_INEP(ep->num)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_XFRSIZ & ep->xfer_len); + + if (ep->type == EP_TYPE_ISOC) + { + USBx_INEP(ep->num)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_MULCNT); + USBx_INEP(ep->num)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_MULCNT & (1 << 29)); + } + } + if (ep->type != EP_TYPE_ISOC) + { + /* Enable the Tx FIFO Empty Interrupt for this EP */ + if (ep->xfer_len > 0) + { + USBx_DEVICE->DIEPEMPMSK |= 1 << ep->num; + } + } + + if (ep->type == EP_TYPE_ISOC) + { + if ((USBx_DEVICE->DSTS & ( 1 << 8 )) == 0) + { + USBx_INEP(ep->num)->DIEPCTL |= USB_OTG_DIEPCTL_SODDFRM; + } + else + { + USBx_INEP(ep->num)->DIEPCTL |= USB_OTG_DIEPCTL_SD0PID_SEVNFRM; + } + } + + /* EP enable, IN data in FIFO */ + USBx_INEP(ep->num)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA); + + if (ep->type == EP_TYPE_ISOC) + { + USB_WritePacket(USBx, ep->xfer_buff, ep->num, ep->xfer_len, dma); + } + } + else /* OUT endpoint */ + { + /* Program the transfer size and packet count as follows: + * pktcnt = N + * xfersize = N * maxpacket + */ + USBx_OUTEP(ep->num)->DOEPTSIZ &= ~(USB_OTG_DOEPTSIZ_XFRSIZ); + USBx_OUTEP(ep->num)->DOEPTSIZ &= ~(USB_OTG_DOEPTSIZ_PKTCNT); + + if (ep->xfer_len == 0) + { + USBx_OUTEP(ep->num)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_XFRSIZ & ep->maxpacket); + USBx_OUTEP(ep->num)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_PKTCNT & (1 << 19)) ; + } + else + { + pktcnt = (ep->xfer_len + ep->maxpacket -1)/ ep->maxpacket; + USBx_OUTEP(ep->num)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_PKTCNT & (pktcnt << 19)); ; + USBx_OUTEP(ep->num)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_XFRSIZ & (ep->maxpacket * pktcnt)); + } + + if (ep->type == EP_TYPE_ISOC) + { + if ((USBx_DEVICE->DSTS & ( 1 << 8 )) == 0) + { + USBx_OUTEP(ep->num)->DOEPCTL |= USB_OTG_DOEPCTL_SODDFRM; + } + else + { + USBx_OUTEP(ep->num)->DOEPCTL |= USB_OTG_DOEPCTL_SD0PID_SEVNFRM; + } + } + /* EP enable */ + USBx_OUTEP(ep->num)->DOEPCTL |= (USB_OTG_DOEPCTL_CNAK | USB_OTG_DOEPCTL_EPENA); + } + return HAL_OK; +} + +/** + * @brief USB_EP0StartXfer : setup and starts a transfer over the EP 0 + * @param USBx: Selected device + * @param ep: pointer to endpoint structure + * @param dma: USB dma enabled or disabled + * This parameter can be one of these values: + * 0 : DMA feature not used + * 1 : DMA feature used + * @retval HAL status + */ +HAL_StatusTypeDef USB_EP0StartXfer(USB_OTG_GlobalTypeDef *USBx , USB_OTG_EPTypeDef *ep, uint8_t dma) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(USBx); + UNUSED(dma); + + /* IN endpoint */ + if (ep->is_in == 1) + { + /* Zero Length Packet? */ + if (ep->xfer_len == 0) + { + USBx_INEP(ep->num)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_PKTCNT); + USBx_INEP(ep->num)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_PKTCNT & (1 << 19)) ; + USBx_INEP(ep->num)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_XFRSIZ); + } + else + { + /* Program the transfer size and packet count + * as follows: xfersize = N * maxpacket + + * short_packet pktcnt = N + (short_packet + * exist ? 1 : 0) + */ + USBx_INEP(ep->num)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_XFRSIZ); + USBx_INEP(ep->num)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_PKTCNT); + + if(ep->xfer_len > ep->maxpacket) + { + ep->xfer_len = ep->maxpacket; + } + USBx_INEP(ep->num)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_PKTCNT & (1 << 19)) ; + USBx_INEP(ep->num)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_XFRSIZ & ep->xfer_len); + + } + + /* Enable the Tx FIFO Empty Interrupt for this EP */ + if (ep->xfer_len > 0) + { + USBx_DEVICE->DIEPEMPMSK |= 1 << (ep->num); + } + + /* EP enable, IN data in FIFO */ + USBx_INEP(ep->num)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA); + } + else /* OUT endpoint */ + { + /* Program the transfer size and packet count as follows: + * pktcnt = N + * xfersize = N * maxpacket + */ + USBx_OUTEP(ep->num)->DOEPTSIZ &= ~(USB_OTG_DOEPTSIZ_XFRSIZ); + USBx_OUTEP(ep->num)->DOEPTSIZ &= ~(USB_OTG_DOEPTSIZ_PKTCNT); + + if (ep->xfer_len > 0) + { + ep->xfer_len = ep->maxpacket; + } + + USBx_OUTEP(ep->num)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_PKTCNT & (1 << 19)); + USBx_OUTEP(ep->num)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_XFRSIZ & (ep->maxpacket)); + + /* EP enable */ + USBx_OUTEP(ep->num)->DOEPCTL |= (USB_OTG_DOEPCTL_CNAK | USB_OTG_DOEPCTL_EPENA); + } + return HAL_OK; +} + +/** + * @brief USB_WritePacket : Writes a packet into the Tx FIFO associated + * with the EP/channel + * @param USBx: Selected device + * @param src: pointer to source buffer + * @param ch_ep_num: endpoint or host channel number + * @param len: Number of bytes to write + * @param dma: USB dma enabled or disabled + * This parameter can be one of these values: + * 0 : DMA feature not used + * 1 : DMA feature used + * @retval HAL status + */ +HAL_StatusTypeDef USB_WritePacket(USB_OTG_GlobalTypeDef *USBx, uint8_t *src, uint8_t ch_ep_num, uint16_t len, uint8_t dma) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(USBx); + UNUSED(dma); + + uint32_t count32b= 0 , index= 0; + count32b = (len + 3) / 4; + for (index = 0; index < count32b; index++, src += 4) + { + USBx_DFIFO(ch_ep_num) = *((__packed uint32_t *)src); + } + return HAL_OK; +} + +/** + * @brief USB_ReadPacket : read a packet from the Tx FIFO associated + * with the EP/channel + * @param USBx: Selected device + * @param src: source pointer + * @param ch_ep_num: endpoint or host channel number + * @param len: Number of bytes to read + * @param dma: USB dma enabled or disabled + * This parameter can be one of these values: + * 0 : DMA feature not used + * 1 : DMA feature used + * @retval pointer to destination buffer + */ +void *USB_ReadPacket(USB_OTG_GlobalTypeDef *USBx, uint8_t *dest, uint16_t len) +{ + uint32_t index=0; + uint32_t count32b = (len + 3) / 4; + + for ( index = 0; index < count32b; index++, dest += 4 ) + { + *(__packed uint32_t *)dest = USBx_DFIFO(0); + + } + return ((void *)dest); +} + +/** + * @brief USB_EPSetStall : set a stall condition over an EP + * @param USBx: Selected device + * @param ep: pointer to endpoint structure + * @retval HAL status + */ +HAL_StatusTypeDef USB_EPSetStall(USB_OTG_GlobalTypeDef *USBx , USB_OTG_EPTypeDef *ep) +{ + if (ep->is_in == 1) + { + if (((USBx_INEP(ep->num)->DIEPCTL) & USB_OTG_DIEPCTL_EPENA) == 0) + { + USBx_INEP(ep->num)->DIEPCTL &= ~(USB_OTG_DIEPCTL_EPDIS); + } + USBx_INEP(ep->num)->DIEPCTL |= USB_OTG_DIEPCTL_STALL; + } + else + { + if (((USBx_OUTEP(ep->num)->DOEPCTL) & USB_OTG_DOEPCTL_EPENA) == 0) + { + USBx_OUTEP(ep->num)->DOEPCTL &= ~(USB_OTG_DOEPCTL_EPDIS); + } + USBx_OUTEP(ep->num)->DOEPCTL |= USB_OTG_DOEPCTL_STALL; + } + return HAL_OK; +} + + +/** + * @brief USB_EPClearStall : Clear a stall condition over an EP + * @param USBx: Selected device + * @param ep: pointer to endpoint structure + * @retval HAL status + */ +HAL_StatusTypeDef USB_EPClearStall(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep) +{ + if (ep->is_in == 1) + { + USBx_INEP(ep->num)->DIEPCTL &= ~USB_OTG_DIEPCTL_STALL; + if (ep->type == EP_TYPE_INTR || ep->type == EP_TYPE_BULK) + { + USBx_INEP(ep->num)->DIEPCTL |= USB_OTG_DIEPCTL_SD0PID_SEVNFRM; /* DATA0 */ + } + } + else + { + USBx_OUTEP(ep->num)->DOEPCTL &= ~USB_OTG_DOEPCTL_STALL; + if (ep->type == EP_TYPE_INTR || ep->type == EP_TYPE_BULK) + { + USBx_OUTEP(ep->num)->DOEPCTL |= USB_OTG_DOEPCTL_SD0PID_SEVNFRM; /* DATA0 */ + } + } + return HAL_OK; +} + +/** + * @brief USB_StopDevice : Stop the USB device mode + * @param USBx: Selected device + * @retval HAL status + */ +HAL_StatusTypeDef USB_StopDevice(USB_OTG_GlobalTypeDef *USBx) +{ + uint32_t index; + + /* Clear Pending interrupt */ + for (index = 0; index < 15 ; index++) + { + USBx_INEP(index)->DIEPINT = 0xFF; + USBx_OUTEP(index)->DOEPINT = 0xFF; + } + USBx_DEVICE->DAINT = 0xFFFFFFFF; + + /* Clear interrupt masks */ + USBx_DEVICE->DIEPMSK = 0; + USBx_DEVICE->DOEPMSK = 0; + USBx_DEVICE->DAINTMSK = 0; + + /* Flush the FIFO */ + USB_FlushRxFifo(USBx); + USB_FlushTxFifo(USBx , 0x10 ); + + return HAL_OK; +} + +/** + * @brief USB_SetDevAddress : Stop the USB device mode + * @param USBx: Selected device + * @param address: new device address to be assigned + * This parameter can be a value from 0 to 255 + * @retval HAL status + */ +HAL_StatusTypeDef USB_SetDevAddress (USB_OTG_GlobalTypeDef *USBx, uint8_t address) +{ + USBx_DEVICE->DCFG &= ~ (USB_OTG_DCFG_DAD); + USBx_DEVICE->DCFG |= (address << 4) & USB_OTG_DCFG_DAD ; + + return HAL_OK; +} + +/** + * @brief USB_DevConnect : Connect the USB device by enabling the pull-up/pull-down + * @param USBx: Selected device + * @retval HAL status + */ +HAL_StatusTypeDef USB_DevConnect (USB_OTG_GlobalTypeDef *USBx) +{ + USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_SDIS ; + HAL_Delay(3); + + return HAL_OK; +} + +/** + * @brief USB_DevDisconnect : Disconnect the USB device by disabling the pull-up/pull-down + * @param USBx: Selected device + * @retval HAL status + */ +HAL_StatusTypeDef USB_DevDisconnect (USB_OTG_GlobalTypeDef *USBx) +{ + USBx_DEVICE->DCTL |= USB_OTG_DCTL_SDIS ; + HAL_Delay(3); + + return HAL_OK; +} + +/** + * @brief USB_ReadInterrupts: return the global USB interrupt status + * @param USBx: Selected device + * @retval HAL status + */ +uint32_t USB_ReadInterrupts (USB_OTG_GlobalTypeDef *USBx) +{ + uint32_t tmpreg = 0; + + tmpreg = USBx->GINTSTS; + tmpreg &= USBx->GINTMSK; + return tmpreg; +} + +/** + * @brief USB_ReadDevAllOutEpInterrupt: return the USB device OUT endpoints interrupt status + * @param USBx: Selected device + * @retval HAL status + */ +uint32_t USB_ReadDevAllOutEpInterrupt (USB_OTG_GlobalTypeDef *USBx) +{ + uint32_t tmpreg; + tmpreg = USBx_DEVICE->DAINT; + tmpreg &= USBx_DEVICE->DAINTMSK; + return ((tmpreg & 0xffff0000) >> 16); +} + +/** + * @brief USB_ReadDevAllInEpInterrupt: return the USB device IN endpoints interrupt status + * @param USBx: Selected device + * @retval HAL status + */ +uint32_t USB_ReadDevAllInEpInterrupt (USB_OTG_GlobalTypeDef *USBx) +{ + uint32_t tmpreg; + tmpreg = USBx_DEVICE->DAINT; + tmpreg &= USBx_DEVICE->DAINTMSK; + return ((tmpreg & 0xFFFF)); +} + +/** + * @brief Returns Device OUT EP Interrupt register + * @param USBx: Selected device + * @param epnum: endpoint number + * This parameter can be a value from 0 to 15 + * @retval Device OUT EP Interrupt register + */ +uint32_t USB_ReadDevOutEPInterrupt (USB_OTG_GlobalTypeDef *USBx , uint8_t epnum) +{ + uint32_t tmpreg; + tmpreg = USBx_OUTEP(epnum)->DOEPINT; + tmpreg &= USBx_DEVICE->DOEPMSK; + return tmpreg; +} + +/** + * @brief Returns Device IN EP Interrupt register + * @param USBx: Selected device + * @param epnum: endpoint number + * This parameter can be a value from 0 to 15 + * @retval Device IN EP Interrupt register + */ +uint32_t USB_ReadDevInEPInterrupt (USB_OTG_GlobalTypeDef *USBx , uint8_t epnum) +{ + uint32_t tmpreg = 0, msk = 0, emp = 0; + + msk = USBx_DEVICE->DIEPMSK; + emp = USBx_DEVICE->DIEPEMPMSK; + msk |= ((emp >> epnum) & 0x1) << 7; + tmpreg = USBx_INEP(epnum)->DIEPINT & msk; + return tmpreg; +} + +/** + * @brief USB_ClearInterrupts: clear a USB interrupt + * @param USBx: Selected device + * @param interrupt: interrupt flag + * @retval None + */ +void USB_ClearInterrupts (USB_OTG_GlobalTypeDef *USBx, uint32_t interrupt) +{ + USBx->GINTSTS |= interrupt; +} + +/** + * @brief Returns USB core mode + * @param USBx: Selected device + * @retval return core mode : Host or Device + * This parameter can be one of these values: + * 0 : Host + * 1 : Device + */ +uint32_t USB_GetMode(USB_OTG_GlobalTypeDef *USBx) +{ + return ((USBx->GINTSTS ) & 0x1); +} + + +/** + * @brief Activate EP0 for Setup transactions + * @param USBx: Selected device + * @retval HAL status + */ +HAL_StatusTypeDef USB_ActivateSetup (USB_OTG_GlobalTypeDef *USBx) +{ + /* Set the MPS of the IN EP based on the enumeration speed */ + USBx_INEP(0)->DIEPCTL &= ~USB_OTG_DIEPCTL_MPSIZ; + + if((USBx_DEVICE->DSTS & USB_OTG_DSTS_ENUMSPD) == DSTS_ENUMSPD_LS_PHY_6MHZ) + { + USBx_INEP(0)->DIEPCTL |= 3; + } + USBx_DEVICE->DCTL |= USB_OTG_DCTL_CGINAK; + + return HAL_OK; +} + + +/** + * @brief Prepare the EP0 to start the first control setup + * @param USBx: Selected device + * @param dma: USB dma enabled or disabled + * This parameter can be one of these values: + * 0 : DMA feature not used + * 1 : DMA feature used + * @param psetup: pointer to setup packet + * @retval HAL status + */ +HAL_StatusTypeDef USB_EP0_OutStart(USB_OTG_GlobalTypeDef *USBx, uint8_t dma, uint8_t *psetup) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(psetup); + + USBx_OUTEP(0)->DOEPTSIZ = 0; + USBx_OUTEP(0)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_PKTCNT & (1 << 19)) ; + USBx_OUTEP(0)->DOEPTSIZ |= (3 * 8); + USBx_OUTEP(0)->DOEPTSIZ |= USB_OTG_DOEPTSIZ_STUPCNT; + + return HAL_OK; +} + +/** + * @brief USB_HostInit : Initializes the USB OTG controller registers + * for Host mode + * @param USBx: Selected device + * @param cfg: pointer to a USB_OTG_CfgTypeDef structure that contains + * the configuration information for the specified USBx peripheral. + * @retval HAL status + */ +HAL_StatusTypeDef USB_HostInit (USB_OTG_GlobalTypeDef *USBx, USB_OTG_CfgTypeDef cfg) +{ + uint32_t index = 0; + + /* Restart the Phy Clock */ + USBx_PCGCCTL = 0; + + /* Disable the FS/LS support mode only */ + if((cfg.speed == USB_OTG_SPEED_FULL)&& + (USBx != USB_OTG_FS)) + { + USBx_HOST->HCFG |= USB_OTG_HCFG_FSLSS; + } + else + { + USBx_HOST->HCFG &= ~(USB_OTG_HCFG_FSLSS); + } + + /* Make sure the FIFOs are flushed. */ + USB_FlushTxFifo(USBx, 0x10 ); /* all Tx FIFOs */ + USB_FlushRxFifo(USBx); + + /* Clear all pending HC Interrupts */ + for (index = 0; index < cfg.Host_channels; index++) + { + USBx_HC(index)->HCINT = 0xFFFFFFFF; + USBx_HC(index)->HCINTMSK = 0; + } + + /* Enable VBUS driving */ + USB_DriveVbus(USBx, 1); + + HAL_Delay(200); + + /* Disable all interrupts. */ + USBx->GINTMSK = 0; + + /* Clear any pending interrupts */ + USBx->GINTSTS = 0xFFFFFFFF; + + /* set Rx FIFO size */ + USBx->GRXFSIZ = (uint32_t )0x80; + USBx->DIEPTXF0_HNPTXFSIZ = (uint32_t )(((0x60 << 16)& USB_OTG_NPTXFD) | 0x80); + USBx->HPTXFSIZ = (uint32_t )(((0x40 << 16)& USB_OTG_HPTXFSIZ_PTXFD) | 0xE0); + + /* Enable the common interrupts */ + if (cfg.dma_enable == DISABLE) + { + USBx->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM; + } + + /* Enable interrupts matching to the Host mode ONLY */ + USBx->GINTMSK |= (USB_OTG_GINTMSK_PRTIM | USB_OTG_GINTMSK_HCIM |\ + USB_OTG_GINTMSK_SOFM |USB_OTG_GINTSTS_DISCINT|\ + USB_OTG_GINTMSK_PXFRM_IISOOXFRM | USB_OTG_GINTMSK_WUIM); + + return HAL_OK; +} + +/** + * @brief USB_InitFSLSPClkSel : Initializes the FSLSPClkSel field of the + * HCFG register on the PHY type and set the right frame interval + * @param USBx: Selected device + * @param freq: clock frequency + * This parameter can be one of these values: + * HCFG_48_MHZ : Full Speed 48 MHz Clock + * HCFG_6_MHZ : Low Speed 6 MHz Clock + * @retval HAL status + */ +HAL_StatusTypeDef USB_InitFSLSPClkSel(USB_OTG_GlobalTypeDef *USBx , uint8_t freq) +{ + USBx_HOST->HCFG &= ~(USB_OTG_HCFG_FSLSPCS); + USBx_HOST->HCFG |= (freq & USB_OTG_HCFG_FSLSPCS); + + if (freq == HCFG_48_MHZ) + { + USBx_HOST->HFIR = (uint32_t)48000; + } + else if (freq == HCFG_6_MHZ) + { + USBx_HOST->HFIR = (uint32_t)6000; + } + return HAL_OK; +} + +/** +* @brief USB_OTG_ResetPort : Reset Host Port + * @param USBx: Selected device + * @retval HAL status + * @note (1)The application must wait at least 10 ms + * before clearing the reset bit. + */ +HAL_StatusTypeDef USB_ResetPort(USB_OTG_GlobalTypeDef *USBx) +{ + __IO uint32_t hprt0 = 0; + + hprt0 = USBx_HPRT0; + + hprt0 &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |\ + USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG ); + + USBx_HPRT0 = (USB_OTG_HPRT_PRST | hprt0); + HAL_Delay (10); /* See Note #1 */ + USBx_HPRT0 = ((~USB_OTG_HPRT_PRST) & hprt0); + return HAL_OK; +} + +/** + * @brief USB_DriveVbus : activate or de-activate vbus + * @param state: VBUS state + * This parameter can be one of these values: + * 0 : VBUS Active + * 1 : VBUS Inactive + * @retval HAL status +*/ +HAL_StatusTypeDef USB_DriveVbus (USB_OTG_GlobalTypeDef *USBx, uint8_t state) +{ + __IO uint32_t hprt0 = 0; + + hprt0 = USBx_HPRT0; + hprt0 &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |\ + USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG ); + + if (((hprt0 & USB_OTG_HPRT_PPWR) == 0 ) && (state == 1 )) + { + USBx_HPRT0 = (USB_OTG_HPRT_PPWR | hprt0); + } + if (((hprt0 & USB_OTG_HPRT_PPWR) == USB_OTG_HPRT_PPWR) && (state == 0 )) + { + USBx_HPRT0 = ((~USB_OTG_HPRT_PPWR) & hprt0); + } + return HAL_OK; +} + +/** + * @brief Return Host Core speed + * @param USBx: Selected device + * @retval speed : Host speed + * This parameter can be one of these values: + * @arg USB_OTG_SPEED_HIGH: High speed mode + * @arg USB_OTG_SPEED_FULL: Full speed mode + * @arg USB_OTG_SPEED_LOW: Low speed mode + */ +uint32_t USB_GetHostSpeed (USB_OTG_GlobalTypeDef *USBx) +{ + __IO uint32_t hprt0 = 0; + + hprt0 = USBx_HPRT0; + return ((hprt0 & USB_OTG_HPRT_PSPD) >> 17); +} + +/** + * @brief Return Host Current Frame number + * @param USBx: Selected device + * @retval current frame number +*/ +uint32_t USB_GetCurrentFrame (USB_OTG_GlobalTypeDef *USBx) +{ + return (USBx_HOST->HFNUM & USB_OTG_HFNUM_FRNUM); +} + +/** + * @brief Initialize a host channel + * @param USBx: Selected device + * @param ch_num : Channel number + * This parameter can be a value from 1 to 15 + * @param epnum: Endpoint number + * This parameter can be a value from 1 to 15 + * @param dev_address: Current device address + * This parameter can be a value from 0 to 255 + * @param speed: Current device speed + * This parameter can be one of these values: + * @arg USB_OTG_SPEED_HIGH: High speed mode + * @arg USB_OTG_SPEED_FULL: Full speed mode + * @arg USB_OTG_SPEED_LOW: Low speed mode + * @param ep_type: Endpoint Type + * This parameter can be one of these values: + * @arg EP_TYPE_CTRL: Control type + * @arg EP_TYPE_ISOC: Isochronous type + * @arg EP_TYPE_BULK: Bulk type + * @arg EP_TYPE_INTR: Interrupt type + * @param mps: Max Packet Size + * This parameter can be a value from 0 to32K + * @retval HAL state + */ +HAL_StatusTypeDef USB_HC_Init(USB_OTG_GlobalTypeDef *USBx, + uint8_t ch_num, + uint8_t epnum, + uint8_t dev_address, + uint8_t speed, + uint8_t ep_type, + uint16_t mps) +{ + + /* Clear old interrupt conditions for this host channel. */ + USBx_HC(ch_num)->HCINT = 0xFFFFFFFF; + + /* Enable channel interrupts required for this transfer. */ + switch (ep_type) + { + case EP_TYPE_CTRL: + case EP_TYPE_BULK: + + USBx_HC(ch_num)->HCINTMSK = USB_OTG_HCINTMSK_XFRCM |\ + USB_OTG_HCINTMSK_STALLM |\ + USB_OTG_HCINTMSK_TXERRM |\ + USB_OTG_HCINTMSK_DTERRM |\ + USB_OTG_HCINTMSK_AHBERR |\ + USB_OTG_HCINTMSK_NAKM ; + + if (epnum & 0x80) + { + USBx_HC(ch_num)->HCINTMSK |= USB_OTG_HCINTMSK_BBERRM; + } + break; + + case EP_TYPE_INTR: + + USBx_HC(ch_num)->HCINTMSK = USB_OTG_HCINTMSK_XFRCM |\ + USB_OTG_HCINTMSK_STALLM |\ + USB_OTG_HCINTMSK_TXERRM |\ + USB_OTG_HCINTMSK_DTERRM |\ + USB_OTG_HCINTMSK_NAKM |\ + USB_OTG_HCINTMSK_AHBERR |\ + USB_OTG_HCINTMSK_FRMORM ; + + if (epnum & 0x80) + { + USBx_HC(ch_num)->HCINTMSK |= USB_OTG_HCINTMSK_BBERRM; + } + + break; + case EP_TYPE_ISOC: + + USBx_HC(ch_num)->HCINTMSK = USB_OTG_HCINTMSK_XFRCM |\ + USB_OTG_HCINTMSK_ACKM |\ + USB_OTG_HCINTMSK_AHBERR |\ + USB_OTG_HCINTMSK_FRMORM ; + + if (epnum & 0x80) + { + USBx_HC(ch_num)->HCINTMSK |= (USB_OTG_HCINTMSK_TXERRM | USB_OTG_HCINTMSK_BBERRM); + } + break; + } + + /* Enable the top level host channel interrupt. */ + USBx_HOST->HAINTMSK |= (1 << ch_num); + + /* Make sure host channel interrupts are enabled. */ + USBx->GINTMSK |= USB_OTG_GINTMSK_HCIM; + + /* Program the HCCHAR register */ + USBx_HC(ch_num)->HCCHAR = (((dev_address << 22) & USB_OTG_HCCHAR_DAD) |\ + (((epnum & 0x7F)<< 11) & USB_OTG_HCCHAR_EPNUM)|\ + ((((epnum & 0x80) == 0x80)<< 15) & USB_OTG_HCCHAR_EPDIR)|\ + (((speed == HPRT0_PRTSPD_LOW_SPEED)<< 17) & USB_OTG_HCCHAR_LSDEV)|\ + ((ep_type << 18) & USB_OTG_HCCHAR_EPTYP)|\ + (mps & USB_OTG_HCCHAR_MPSIZ)); + + if (ep_type == EP_TYPE_INTR) + { + USBx_HC(ch_num)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM ; + } + + return HAL_OK; +} + +/** + * @brief Start a transfer over a host channel + * @param USBx: Selected device + * @param hc: pointer to host channel structure + * @param dma: USB dma enabled or disabled + * This parameter can be one of these values: + * 0 : DMA feature not used + * 1 : DMA feature used + * @retval HAL state + */ +#if defined (__CC_ARM) /*!< ARM Compiler */ +#pragma O0 +#elif defined (__GNUC__) /*!< GNU Compiler */ +#pragma GCC optimize ("O0") +#endif /* __CC_ARM */ +HAL_StatusTypeDef USB_HC_StartXfer(USB_OTG_GlobalTypeDef *USBx, USB_OTG_HCTypeDef *hc, uint8_t dma) +{ + uint8_t is_oddframe = 0; + uint16_t len_words = 0; + uint16_t num_packets = 0; + uint16_t max_hc_pkt_count = 256; + uint32_t tmpreg = 0; + + /* Compute the expected number of packets associated to the transfer */ + if (hc->xfer_len > 0) + { + num_packets = (hc->xfer_len + hc->max_packet - 1) / hc->max_packet; + + if (num_packets > max_hc_pkt_count) + { + num_packets = max_hc_pkt_count; + hc->xfer_len = num_packets * hc->max_packet; + } + } + else + { + num_packets = 1; + } + if (hc->ep_is_in) + { + hc->xfer_len = num_packets * hc->max_packet; + } + + /* Initialize the HCTSIZn register */ + USBx_HC(hc->ch_num)->HCTSIZ = (((hc->xfer_len) & USB_OTG_HCTSIZ_XFRSIZ)) |\ + ((num_packets << 19) & USB_OTG_HCTSIZ_PKTCNT) |\ + (((hc->data_pid) << 29) & USB_OTG_HCTSIZ_DPID); + + if (dma) + { + /* xfer_buff MUST be 32-bits aligned */ + USBx_HC(hc->ch_num)->HCDMA = (uint32_t)hc->xfer_buff; + } + + is_oddframe = (USBx_HOST->HFNUM & 0x01) ? 0 : 1; + USBx_HC(hc->ch_num)->HCCHAR &= ~USB_OTG_HCCHAR_ODDFRM; + USBx_HC(hc->ch_num)->HCCHAR |= (is_oddframe << 29); + + /* Set host channel enable */ + tmpreg = USBx_HC(hc->ch_num)->HCCHAR; + tmpreg &= ~USB_OTG_HCCHAR_CHDIS; + tmpreg |= USB_OTG_HCCHAR_CHENA; + USBx_HC(hc->ch_num)->HCCHAR = tmpreg; + + if (dma == 0) /* Slave mode */ + { + if((hc->ep_is_in == 0) && (hc->xfer_len > 0)) + { + switch(hc->ep_type) + { + /* Non periodic transfer */ + case EP_TYPE_CTRL: + case EP_TYPE_BULK: + + len_words = (hc->xfer_len + 3) / 4; + + /* check if there is enough space in FIFO space */ + if(len_words > (USBx->HNPTXSTS & 0xFFFF)) + { + /* need to process data in nptxfempty interrupt */ + USBx->GINTMSK |= USB_OTG_GINTMSK_NPTXFEM; + } + break; + /* Periodic transfer */ + case EP_TYPE_INTR: + case EP_TYPE_ISOC: + len_words = (hc->xfer_len + 3) / 4; + /* check if there is enough space in FIFO space */ + if(len_words > (USBx_HOST->HPTXSTS & 0xFFFF)) /* split the transfer */ + { + /* need to process data in ptxfempty interrupt */ + USBx->GINTMSK |= USB_OTG_GINTMSK_PTXFEM; + } + break; + + default: + break; + } + + /* Write packet into the Tx FIFO. */ + USB_WritePacket(USBx, hc->xfer_buff, hc->ch_num, hc->xfer_len, 0); + } + } + + return HAL_OK; +} + +/** + * @brief Read all host channel interrupts status + * @param USBx: Selected device + * @retval HAL state + */ +uint32_t USB_HC_ReadInterrupt (USB_OTG_GlobalTypeDef *USBx) +{ + return ((USBx_HOST->HAINT) & 0xFFFF); +} + +/** + * @brief Halt a host channel + * @param USBx: Selected device + * @param hc_num: Host Channel number + * This parameter can be a value from 1 to 15 + * @retval HAL state + */ +HAL_StatusTypeDef USB_HC_Halt(USB_OTG_GlobalTypeDef *USBx , uint8_t hc_num) +{ + uint32_t count = 0; + + /* Check for space in the request queue to issue the halt. */ + if (((USBx_HC(hc_num)->HCCHAR) & (HCCHAR_CTRL << 18)) || ((USBx_HC(hc_num)->HCCHAR) & (HCCHAR_BULK << 18))) + { + USBx_HC(hc_num)->HCCHAR |= USB_OTG_HCCHAR_CHDIS; + + if ((USBx->HNPTXSTS & 0xFFFF) == 0) + { + USBx_HC(hc_num)->HCCHAR &= ~USB_OTG_HCCHAR_CHENA; + USBx_HC(hc_num)->HCCHAR |= USB_OTG_HCCHAR_CHENA; + USBx_HC(hc_num)->HCCHAR &= ~USB_OTG_HCCHAR_EPDIR; + do + { + if (++count > 1000) + { + break; + } + } + while ((USBx_HC(hc_num)->HCCHAR & USB_OTG_HCCHAR_CHENA) == USB_OTG_HCCHAR_CHENA); + } + else + { + USBx_HC(hc_num)->HCCHAR |= USB_OTG_HCCHAR_CHENA; + } + } + else + { + USBx_HC(hc_num)->HCCHAR |= USB_OTG_HCCHAR_CHDIS; + + if ((USBx_HOST->HPTXSTS & 0xFFFF) == 0) + { + USBx_HC(hc_num)->HCCHAR &= ~USB_OTG_HCCHAR_CHENA; + USBx_HC(hc_num)->HCCHAR |= USB_OTG_HCCHAR_CHENA; + USBx_HC(hc_num)->HCCHAR &= ~USB_OTG_HCCHAR_EPDIR; + do + { + if (++count > 1000) + { + break; + } + } + while ((USBx_HC(hc_num)->HCCHAR & USB_OTG_HCCHAR_CHENA) == USB_OTG_HCCHAR_CHENA); + } + else + { + USBx_HC(hc_num)->HCCHAR |= USB_OTG_HCCHAR_CHENA; + } + } + + return HAL_OK; +} + +/** + * @brief Initiate Do Ping protocol + * @param USBx: Selected device + * @param hc_num: Host Channel number + * This parameter can be a value from 1 to 15 + * @retval HAL state + */ +HAL_StatusTypeDef USB_DoPing(USB_OTG_GlobalTypeDef *USBx , uint8_t ch_num) +{ + uint8_t num_packets = 1; + uint32_t tmpreg = 0; + + USBx_HC(ch_num)->HCTSIZ = ((num_packets << 19) & USB_OTG_HCTSIZ_PKTCNT) |\ + USB_OTG_HCTSIZ_DOPING; + + /* Set host channel enable */ + tmpreg = USBx_HC(ch_num)->HCCHAR; + tmpreg &= ~USB_OTG_HCCHAR_CHDIS; + tmpreg |= USB_OTG_HCCHAR_CHENA; + USBx_HC(ch_num)->HCCHAR = tmpreg; + + return HAL_OK; +} + +/** + * @brief Stop Host Core + * @param USBx: Selected device + * @retval HAL state + */ +HAL_StatusTypeDef USB_StopHost(USB_OTG_GlobalTypeDef *USBx) +{ + uint8_t index; + uint32_t count = 0; + uint32_t value = 0; + + USB_DisableGlobalInt(USBx); + + /* Flush FIFO */ + USB_FlushTxFifo(USBx, 0x10); + USB_FlushRxFifo(USBx); + + /* Flush out any leftover queued requests. */ + for (index = 0; index <= 15; index++) + { + value = USBx_HC(index)->HCCHAR; + value |= USB_OTG_HCCHAR_CHDIS; + value &= ~USB_OTG_HCCHAR_CHENA; + value &= ~USB_OTG_HCCHAR_EPDIR; + USBx_HC(index)->HCCHAR = value; + } + + /* Halt all channels to put them into a known state. */ + for (index = 0; index <= 15; index++) + { + value = USBx_HC(index)->HCCHAR ; + value |= USB_OTG_HCCHAR_CHDIS; + value |= USB_OTG_HCCHAR_CHENA; + value &= ~USB_OTG_HCCHAR_EPDIR; + USBx_HC(index)->HCCHAR = value; + + USBx_HC(index)->HCCHAR = value; + do + { + if (++count > 1000) + { + break; + } + } + while ((USBx_HC(index)->HCCHAR & USB_OTG_HCCHAR_CHENA) == USB_OTG_HCCHAR_CHENA); + } + + /* Clear any pending Host interrupts */ + USBx_HOST->HAINT = 0xFFFFFFFF; + USBx->GINTSTS = 0xFFFFFFFF; + USB_EnableGlobalInt(USBx); + return HAL_OK; +} + +/** + * @brief USB_ActivateRemoteWakeup : active remote wakeup signalling + * @param USBx : Selected device + * @retval HAL status + */ +HAL_StatusTypeDef USB_ActivateRemoteWakeup(USB_OTG_GlobalTypeDef *USBx) +{ + if((USBx_DEVICE->DSTS & USB_OTG_DSTS_SUSPSTS) == USB_OTG_DSTS_SUSPSTS) + { + /* active Remote wakeup signalling */ + USBx_DEVICE->DCTL |= USB_OTG_DCTL_RWUSIG; + } + return HAL_OK; +} + +/** + * @brief USB_DeActivateRemoteWakeup : de-active remote wakeup signalling + * @param USBx : Selected device + * @retval HAL status + */ +HAL_StatusTypeDef USB_DeActivateRemoteWakeup(USB_OTG_GlobalTypeDef *USBx) +{ + /* active Remote wakeup signalling */ + USBx_DEVICE->DCTL &= ~(USB_OTG_DCTL_RWUSIG); + return HAL_OK; +} + +#endif /* USB_OTG_FS */ + +/*============================================================================== + USB Device FS peripheral available on STM32L432xx, STM32L433xx, STM32L442xx) + and STM32L443xx devices +==============================================================================*/ +#if defined (USB) +/** + * @brief Initializes the USB Core + * @param USBx: USB Instance + * @param cfg : pointer to a USB_CfgTypeDef structure that contains + * the configuration information for the specified USBx peripheral. + * @retval HAL status + */ +HAL_StatusTypeDef USB_CoreInit(USB_TypeDef *USBx, USB_CfgTypeDef cfg) +{ + /* NOTE : - This function is not required by USB Device FS peripheral, it is used + only by USB OTG FS peripheral. + - This function is added to ensure compatibility across platforms. + */ + + /* Prevent unused argument(s) compilation warning */ + UNUSED(USBx); + UNUSED(cfg); + + return HAL_OK; +} + +/** + * @brief USB_EnableGlobalInt + * Enables the controller's Global Int in the AHB Config reg + * @param USBx : Selected device + * @retval HAL status + */ +HAL_StatusTypeDef USB_EnableGlobalInt(USB_TypeDef *USBx) +{ + uint32_t winterruptmask = 0; + + /* Set winterruptmask variable */ + winterruptmask = USB_CNTR_CTRM | USB_CNTR_WKUPM | USB_CNTR_SUSPM | USB_CNTR_ERRM \ + | USB_CNTR_ESOFM | USB_CNTR_RESETM; + + /* Set interrupt mask */ + USBx->CNTR |= winterruptmask; + + return HAL_OK; +} + +/** + * @brief USB_DisableGlobalInt + * Disable the controller's Global Int in the AHB Config reg + * @param USBx : Selected device + * @retval HAL status +*/ +HAL_StatusTypeDef USB_DisableGlobalInt(USB_TypeDef *USBx) +{ + uint32_t winterruptmask = 0; + + /* Set winterruptmask variable */ + winterruptmask = USB_CNTR_CTRM | USB_CNTR_WKUPM | USB_CNTR_SUSPM | USB_CNTR_ERRM \ + | USB_CNTR_ESOFM | USB_CNTR_RESETM; + + /* Clear interrupt mask */ + USBx->CNTR &= ~winterruptmask; + + return HAL_OK; +} + +/** + * @brief USB_SetCurrentMode : Set functional mode + * @param USBx : Selected device + * @param mode : current core mode + * This parameter can be one of the these values: + * @arg USB_DEVICE_MODE: Peripheral mode mode + * @retval HAL status + */ +HAL_StatusTypeDef USB_SetCurrentMode(USB_TypeDef *USBx , USB_ModeTypeDef mode) +{ + /* NOTE : - This function is not required by USB Device FS peripheral, it is used + only by USB OTG FS peripheral. + - This function is added to ensure compatibility across platforms. + */ + + /* Prevent unused argument(s) compilation warning */ + UNUSED(USBx); + UNUSED(mode); + + return HAL_OK; +} + +/** + * @brief USB_DevInit : Initializes the USB controller registers + * for device mode + * @param USBx : Selected device + * @param cfg : pointer to a USB_CfgTypeDef structure that contains + * the configuration information for the specified USBx peripheral. + * @retval HAL status + */ +HAL_StatusTypeDef USB_DevInit (USB_TypeDef *USBx, USB_CfgTypeDef cfg) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(cfg); + + /* Init Device */ + /*CNTR_FRES = 1*/ + USBx->CNTR = USB_CNTR_FRES; + + /*CNTR_FRES = 0*/ + USBx->CNTR = 0; + + /*Clear pending interrupts*/ + USBx->ISTR = 0; + + /*Set Btable Address*/ + USBx->BTABLE = BTABLE_ADDRESS; + + return HAL_OK; +} + +/** + * @brief USB_FlushTxFifo : Flush a Tx FIFO + * @param USBx : Selected device + * @param num : FIFO number + * This parameter can be a value from 1 to 15 + 15 means Flush all Tx FIFOs + * @retval HAL status + */ +HAL_StatusTypeDef USB_FlushTxFifo (USB_TypeDef *USBx, uint32_t num ) +{ + /* NOTE : - This function is not required by USB Device FS peripheral, it is used + only by USB OTG FS peripheral. + - This function is added to ensure compatibility across platforms. + */ + + /* Prevent unused argument(s) compilation warning */ + UNUSED(USBx); + UNUSED(num); + + return HAL_OK; +} + +/** + * @brief USB_FlushRxFifo : Flush Rx FIFO + * @param USBx : Selected device + * @retval HAL status + */ +HAL_StatusTypeDef USB_FlushRxFifo(USB_TypeDef *USBx) +{ + /* NOTE : - This function is not required by USB Device FS peripheral, it is used + only by USB OTG FS peripheral. + - This function is added to ensure compatibility across platforms. + */ + + /* Prevent unused argument(s) compilation warning */ + UNUSED(USBx); + + return HAL_OK; +} + +/** + * @brief Activate and configure an endpoint + * @param USBx : Selected device + * @param ep: pointer to endpoint structure + * @retval HAL status + */ +HAL_StatusTypeDef USB_ActivateEndpoint(USB_TypeDef *USBx, USB_EPTypeDef *ep) +{ + /* initialize Endpoint */ + switch (ep->type) + { + case EP_TYPE_CTRL: + PCD_SET_EPTYPE(USBx, ep->num, USB_EP_CONTROL); + break; + case EP_TYPE_BULK: + PCD_SET_EPTYPE(USBx, ep->num, USB_EP_BULK); + break; + case EP_TYPE_INTR: + PCD_SET_EPTYPE(USBx, ep->num, USB_EP_INTERRUPT); + break; + case EP_TYPE_ISOC: + PCD_SET_EPTYPE(USBx, ep->num, USB_EP_ISOCHRONOUS); + break; + default: + break; + } + + PCD_SET_EP_ADDRESS(USBx, ep->num, ep->num); + + if (ep->doublebuffer == 0) + { + if (ep->is_in) + { + /*Set the endpoint Transmit buffer address */ + PCD_SET_EP_TX_ADDRESS(USBx, ep->num, ep->pmaadress); + PCD_CLEAR_TX_DTOG(USBx, ep->num); + /* Configure NAK status for the Endpoint*/ + PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK); + } + else + { + /*Set the endpoint Receive buffer address */ + PCD_SET_EP_RX_ADDRESS(USBx, ep->num, ep->pmaadress); + /*Set the endpoint Receive buffer counter*/ + PCD_SET_EP_RX_CNT(USBx, ep->num, ep->maxpacket); + PCD_CLEAR_RX_DTOG(USBx, ep->num); + /* Configure VALID status for the Endpoint*/ + PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID); + } + } + /*Double Buffer*/ + else + { + /*Set the endpoint as double buffered*/ + PCD_SET_EP_DBUF(USBx, ep->num); + /*Set buffer address for double buffered mode*/ + PCD_SET_EP_DBUF_ADDR(USBx, ep->num,ep->pmaaddr0, ep->pmaaddr1); + + if (ep->is_in==0) + { + /* Clear the data toggle bits for the endpoint IN/OUT*/ + PCD_CLEAR_RX_DTOG(USBx, ep->num); + PCD_CLEAR_TX_DTOG(USBx, ep->num); + + /* Reset value of the data toggle bits for the endpoint out*/ + PCD_TX_DTOG(USBx, ep->num); + + PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID); + PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS); + } + else + { + /* Clear the data toggle bits for the endpoint IN/OUT*/ + PCD_CLEAR_RX_DTOG(USBx, ep->num); + PCD_CLEAR_TX_DTOG(USBx, ep->num); + PCD_RX_DTOG(USBx, ep->num); + /* Configure DISABLE status for the Endpoint*/ + PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS); + PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS); + } + } + + return HAL_OK; +} + +/** + * @brief De-activate and de-initialize an endpoint + * @param USBx : Selected device + * @param ep: pointer to endpoint structure + * @retval HAL status + */ +HAL_StatusTypeDef USB_DeactivateEndpoint(USB_TypeDef *USBx, USB_EPTypeDef *ep) +{ + if (ep->doublebuffer == 0) + { + if (ep->is_in) + { + PCD_CLEAR_TX_DTOG(USBx, ep->num); + /* Configure DISABLE status for the Endpoint*/ + PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS); + } + else + { + PCD_CLEAR_RX_DTOG(USBx, ep->num); + /* Configure DISABLE status for the Endpoint*/ + PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS); + } + } + /*Double Buffer*/ + else + { + if (ep->is_in==0) + { + /* Clear the data toggle bits for the endpoint IN/OUT*/ + PCD_CLEAR_RX_DTOG(USBx, ep->num); + PCD_CLEAR_TX_DTOG(USBx, ep->num); + + /* Reset value of the data toggle bits for the endpoint out*/ + PCD_TX_DTOG(USBx, ep->num); + + PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS); + PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS); + } + else + { + /* Clear the data toggle bits for the endpoint IN/OUT*/ + PCD_CLEAR_RX_DTOG(USBx, ep->num); + PCD_CLEAR_TX_DTOG(USBx, ep->num); + PCD_RX_DTOG(USBx, ep->num); + /* Configure DISABLE status for the Endpoint*/ + PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS); + PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS); + } + } + + return HAL_OK; +} + +/** + * @brief USB_EPStartXfer : setup and starts a transfer over an EP + * @param USBx : Selected device + * @param ep: pointer to endpoint structure + * @retval HAL status + */ +HAL_StatusTypeDef USB_EPStartXfer(USB_TypeDef *USBx , USB_EPTypeDef *ep, uint8_t dma) +{ + uint16_t pmabuffer = 0; + uint32_t len = ep->xfer_len; + + /* IN endpoint */ + if (ep->is_in == 1) + { + /*Multi packet transfer*/ + if (ep->xfer_len > ep->maxpacket) + { + len=ep->maxpacket; + ep->xfer_len-=len; + } + else + { + len=ep->xfer_len; + ep->xfer_len =0; + } + + /* configure and validate Tx endpoint */ + if (ep->doublebuffer == 0) + { + USB_WritePMA(USBx, ep->xfer_buff, ep->pmaadress, len); + PCD_SET_EP_TX_CNT(USBx, ep->num, len); + } + else + { + /* Write the data to the USB endpoint */ + if (PCD_GET_ENDPOINT(USBx, ep->num)& USB_EP_DTOG_TX) + { + /* Set the Double buffer counter for pmabuffer1 */ + PCD_SET_EP_DBUF1_CNT(USBx, ep->num, ep->is_in, len); + pmabuffer = ep->pmaaddr1; + } + else + { + /* Set the Double buffer counter for pmabuffer0 */ + PCD_SET_EP_DBUF0_CNT(USBx, ep->num, ep->is_in, len); + pmabuffer = ep->pmaaddr0; + } + USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, len); + PCD_FreeUserBuffer(USBx, ep->num, ep->is_in); + } + + PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_VALID); + } + else /* OUT endpoint */ + { + /* Multi packet transfer*/ + if (ep->xfer_len > ep->maxpacket) + { + len=ep->maxpacket; + ep->xfer_len-=len; + } + else + { + len=ep->xfer_len; + ep->xfer_len =0; + } + + /* configure and validate Rx endpoint */ + if (ep->doublebuffer == 0) + { + /*Set RX buffer count*/ + PCD_SET_EP_RX_CNT(USBx, ep->num, len); + } + else + { + /*Set the Double buffer counter*/ + PCD_SET_EP_DBUF1_CNT(USBx, ep->num, ep->is_in, len); + } + + PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID); + } + + return HAL_OK; +} + +/** + * @brief USB_WritePacket : Writes a packet into the Tx FIFO associated + * with the EP/channel + * @param USBx : Selected device + * @param src : pointer to source buffer + * @param ch_ep_num : endpoint or host channel number + * @param len : Number of bytes to write + * @retval HAL status + */ +HAL_StatusTypeDef USB_WritePacket(USB_TypeDef *USBx, uint8_t *src, uint8_t ch_ep_num, uint16_t len) +{ + /* NOTE : - This function is not required by USB Device FS peripheral, it is used + only by USB OTG FS peripheral. + - This function is added to ensure compatibility across platforms. + */ + + /* Prevent unused argument(s) compilation warning */ + UNUSED(USBx); + UNUSED(src); + UNUSED(ch_ep_num); + UNUSED(len); + + return HAL_OK; +} + +/** + * @brief USB_ReadPacket : read a packet from the Tx FIFO associated + * with the EP/channel + * @param USBx : Selected device + * @param dest : destination pointer + * @param len : Number of bytes to read + * @retval pointer to destination buffer + */ +void *USB_ReadPacket(USB_TypeDef *USBx, uint8_t *dest, uint16_t len) +{ + /* NOTE : - This function is not required by USB Device FS peripheral, it is used + only by USB OTG FS peripheral. + - This function is added to ensure compatibility across platforms. + */ + + /* Prevent unused argument(s) compilation warning */ + UNUSED(USBx); + UNUSED(dest); + UNUSED(len); + + return ((void *)NULL); +} + +/** + * @brief USB_EPSetStall : set a stall condition over an EP + * @param USBx : Selected device + * @param ep: pointer to endpoint structure + * @retval HAL status + */ +HAL_StatusTypeDef USB_EPSetStall(USB_TypeDef *USBx , USB_EPTypeDef *ep) +{ + if (ep->num == 0) + { + /* This macro sets STALL status for RX & TX*/ + PCD_SET_EP_TXRX_STATUS(USBx, ep->num, USB_EP_RX_STALL, USB_EP_TX_STALL); + } + else + { + if (ep->is_in) + { + PCD_SET_EP_TX_STATUS(USBx, ep->num , USB_EP_TX_STALL); + } + else + { + PCD_SET_EP_RX_STATUS(USBx, ep->num , USB_EP_RX_STALL); + } + } + return HAL_OK; +} + +/** + * @brief USB_EPClearStall : Clear a stall condition over an EP + * @param USBx : Selected device + * @param ep: pointer to endpoint structure + * @retval HAL status + */ +HAL_StatusTypeDef USB_EPClearStall(USB_TypeDef *USBx, USB_EPTypeDef *ep) +{ + if (ep->is_in) + { + PCD_CLEAR_TX_DTOG(USBx, ep->num); + PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_VALID); + } + else + { + PCD_CLEAR_RX_DTOG(USBx, ep->num); + PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID); + } + return HAL_OK; +} + +/** + * @brief USB_StopDevice : Stop the usb device mode + * @param USBx : Selected device + * @retval HAL status + */ +HAL_StatusTypeDef USB_StopDevice(USB_TypeDef *USBx) +{ + /* disable all interrupts and force USB reset */ + USBx->CNTR = USB_CNTR_FRES; + + /* clear interrupt status register */ + USBx->ISTR = 0; + + /* switch-off device */ + USBx->CNTR = (USB_CNTR_FRES | USB_CNTR_PDWN); + + return HAL_OK; +} + +/** + * @brief USB_SetDevAddress : Stop the usb device mode + * @param USBx : Selected device + * @param address : new device address to be assigned + * This parameter can be a value from 0 to 255 + * @retval HAL status + */ +HAL_StatusTypeDef USB_SetDevAddress (USB_TypeDef *USBx, uint8_t address) +{ + if(address == 0) + { + /* set device address and enable function */ + USBx->DADDR = USB_DADDR_EF; + } + + return HAL_OK; +} + +/** + * @brief USB_DevConnect : Connect the USB device by enabling the pull-up/pull-down + * @param USBx : Selected device + * @retval HAL status + */ +HAL_StatusTypeDef USB_DevConnect (USB_TypeDef *USBx) +{ + /* Enabling DP Pull-Down bit to Connect internal pull-up on USB DP line */ + USB->BCDR |= USB_BCDR_DPPU; + + return HAL_OK; +} + +/** + * @brief USB_DevDisconnect : Disconnect the USB device by disabling the pull-up/pull-down + * @param USBx : Selected device + * @retval HAL status + */ +HAL_StatusTypeDef USB_DevDisconnect (USB_TypeDef *USBx) +{ + /* Disable DP Pull-Down bit*/ + USB->BCDR &= ~(USB_BCDR_DPPU); + + return HAL_OK; +} + +/** + * @brief USB_ReadInterrupts: return the global USB interrupt status + * @param USBx : Selected device + * @retval HAL status + */ +uint32_t USB_ReadInterrupts (USB_TypeDef *USBx) +{ + uint32_t tmpreg = 0; + + tmpreg = USBx->ISTR; + return tmpreg; +} + +/** + * @brief USB_ReadDevAllOutEpInterrupt: return the USB device OUT endpoints interrupt status + * @param USBx : Selected device + * @retval HAL status + */ +uint32_t USB_ReadDevAllOutEpInterrupt (USB_TypeDef *USBx) +{ + /* NOTE : - This function is not required by USB Device FS peripheral, it is used + only by USB OTG FS peripheral. + - This function is added to ensure compatibility across platforms. + */ + + /* Prevent unused argument(s) compilation warning */ + UNUSED(USBx); + + return (0); +} + +/** + * @brief USB_ReadDevAllInEpInterrupt: return the USB device IN endpoints interrupt status + * @param USBx : Selected device + * @retval HAL status + */ +uint32_t USB_ReadDevAllInEpInterrupt (USB_TypeDef *USBx) +{ + /* NOTE : - This function is not required by USB Device FS peripheral, it is used + only by USB OTG FS peripheral. + - This function is added to ensure compatibility across platforms. + */ + + /* Prevent unused argument(s) compilation warning */ + UNUSED(USBx); + + return (0); +} + +/** + * @brief Returns Device OUT EP Interrupt register + * @param USBx : Selected device + * @param epnum : endpoint number + * This parameter can be a value from 0 to 15 + * @retval Device OUT EP Interrupt register + */ +uint32_t USB_ReadDevOutEPInterrupt (USB_TypeDef *USBx , uint8_t epnum) +{ + /* NOTE : - This function is not required by USB Device FS peripheral, it is used + only by USB OTG FS peripheral. + - This function is added to ensure compatibility across platforms. + */ + + /* Prevent unused argument(s) compilation warning */ + UNUSED(USBx); + UNUSED(epnum); + + return (0); +} + +/** + * @brief Returns Device IN EP Interrupt register + * @param USBx : Selected device + * @param epnum : endpoint number + * This parameter can be a value from 0 to 15 + * @retval Device IN EP Interrupt register + */ +uint32_t USB_ReadDevInEPInterrupt (USB_TypeDef *USBx , uint8_t epnum) +{ + /* NOTE : - This function is not required by USB Device FS peripheral, it is used + only by USB OTG FS peripheral. + - This function is added to ensure compatibility across platforms. + */ + + /* Prevent unused argument(s) compilation warning */ + UNUSED(USBx); + UNUSED(epnum); + + return (0); +} + +/** + * @brief USB_ClearInterrupts: clear a USB interrupt + * @param USBx : Selected device + * @param interrupt : interrupt flag + * @retval None + */ +void USB_ClearInterrupts (USB_TypeDef *USBx, uint32_t interrupt) +{ + /* NOTE : - This function is not required by USB Device FS peripheral, it is used + only by USB OTG FS peripheral. + - This function is added to ensure compatibility across platforms. + */ + + /* Prevent unused argument(s) compilation warning */ + UNUSED(USBx); + UNUSED(interrupt); +} + +/** + * @brief Prepare the EP0 to start the first control setup + * @param USBx : Selected device + * @param psetup : pointer to setup packet + * @retval HAL status + */ +HAL_StatusTypeDef USB_EP0_OutStart(USB_TypeDef *USBx, uint8_t dma ,uint8_t *psetup) +{ + /* NOTE : - This function is not required by USB Device FS peripheral, it is used + only by USB OTG FS peripheral. + - This function is added to ensure compatibility across platforms. + */ + + /* Prevent unused argument(s) compilation warning */ + UNUSED(USBx); + UNUSED(psetup); + UNUSED(dma); + + return HAL_OK; +} + +/** + * @brief USB_ActivateRemoteWakeup : active remote wakeup signalling + * @param USBx : Selected device + * @retval HAL status + */ +HAL_StatusTypeDef USB_ActivateRemoteWakeup(USB_TypeDef *USBx) +{ + USBx->CNTR |= USB_CNTR_RESUME; + + return HAL_OK; +} + +/** + * @brief USB_DeActivateRemoteWakeup : de-active remote wakeup signalling + * @param USBx : Selected device + * @retval HAL status + */ +HAL_StatusTypeDef USB_DeActivateRemoteWakeup(USB_TypeDef *USBx) +{ + USBx->CNTR &= ~(USB_CNTR_RESUME); + return HAL_OK; +} + +/** + * @brief Copy a buffer from user memory area to packet memory area (PMA) + * @param USBx : pointer to USB register. + * @param pbUsrBuf : pointer to user memory area. + * @param wPMABufAddr : address into PMA. + * @param wNBytes : number of bytes to be copied. + * @retval None + */ +void USB_WritePMA(USB_TypeDef *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes) +{ + uint32_t n = (wNBytes + 1) >> 1; + uint32_t i; + uint16_t temp1, temp2; + uint16_t *pdwVal; + pdwVal = (uint16_t *)(wPMABufAddr + (uint32_t)USBx + 0x400); + + for (i = n; i != 0; i--) + { + temp1 = (uint16_t) * pbUsrBuf; + pbUsrBuf++; + temp2 = temp1 | (uint16_t) * pbUsrBuf << 8; + *pdwVal++ = temp2; + pbUsrBuf++; + } +} + +/** + * @brief Copy a buffer from user memory area to packet memory area (PMA) + * @param USBx : pointer to USB register. +* @param pbUsrBuf : pointer to user memory area. + * @param wPMABufAddr : address into PMA. + * @param wNBytes : number of bytes to be copied. + * @retval None + */ +void USB_ReadPMA(USB_TypeDef *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes) +{ + uint32_t n = (wNBytes + 1) >> 1; + uint32_t i; + uint16_t *pdwVal; + pdwVal = (uint16_t *)(wPMABufAddr + (uint32_t)USBx + 0x400); + for (i = n; i != 0; i--) + { + *(uint16_t*)pbUsrBuf++ = *pdwVal++; + pbUsrBuf++; + } +} +#endif /* USB */ +/** + * @} + */ +/** + * @} + */ + +#if defined (USB_OTG_FS) +/** @addtogroup USB_LL_Private_Functions + * @{ + */ +/** + * @brief Reset the USB Core (needed after USB clock settings change) + * @param USBx : Selected device + * @retval HAL status + */ +static HAL_StatusTypeDef USB_CoreReset(USB_OTG_GlobalTypeDef *USBx) +{ + uint32_t count = 0; + + /* Wait for AHB master IDLE state. */ + do + { + if (++count > 200000) + { + return HAL_TIMEOUT; + } + } + while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0); + + /* Core Soft Reset */ + count = 0; + USBx->GRSTCTL |= USB_OTG_GRSTCTL_CSRST; + + do + { + if (++count > 200000) + { + return HAL_TIMEOUT; + } + } + while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_CSRST) == USB_OTG_GRSTCTL_CSRST); + + return HAL_OK; +} +/** + * @} + */ +#endif /* USB_OTG_FS */ + +#endif /* STM32L432xx || STM32L433xx || STM32L442xx || STM32L443xx || */ + /* STM32L452xx || STM32L462xx || */ + /* STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || */ + /* STM32L496xx || STM32L4A6xx || */ + /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +#endif /* defined (HAL_PCD_MODULE_ENABLED) || defined (HAL_HCD_MODULE_ENABLED) */ +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/main.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/main.h new file mode 100644 index 0000000..61fc455 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/main.h @@ -0,0 +1,90 @@ +/** + ****************************************************************************** + * @file : main.h + * @brief : Header for main.c file. + * This file contains the common defines of the application. + ****************************************************************************** + * This notice applies to any and all portions of this file + * that are not between comment pairs USER CODE BEGIN and + * USER CODE END. Other portions of this file, whether + * inserted by the user or by software development tools + * are owned by their respective copyright owners. + * + * Copyright (c) 2018 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. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (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 to prevent recursive inclusion -------------------------------------*/ +#ifndef __MAIN_H__ +#define __MAIN_H__ + +/* Includes ------------------------------------------------------------------*/ + +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* Private define ------------------------------------------------------------*/ + +#define B1_Pin GPIO_PIN_13 +#define B1_GPIO_Port GPIOC +#define LD2_Pin GPIO_PIN_5 +#define LD2_GPIO_Port GPIOA + +/* ########################## Assert Selection ############################## */ +/** + * @brief Uncomment the line below to expanse the "assert_param" macro in the + * HAL drivers code + */ +/* #define USE_FULL_ASSERT 1U */ + +/* USER CODE BEGIN Private defines */ + +/* USER CODE END Private defines */ + +#ifdef __cplusplus + extern "C" { +#endif +void _Error_Handler(char *, int); + +#define Error_Handler() _Error_Handler(__FILE__, __LINE__) +#ifdef __cplusplus +} +#endif + +#endif /* __MAIN_H__ */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/stm32l4xx_hal_conf.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/stm32l4xx_hal_conf.h new file mode 100644 index 0000000..4871624 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/stm32l4xx_hal_conf.h @@ -0,0 +1,430 @@ +/** + ****************************************************************************** + * @file stm32l4xx_hal_conf.h + * @brief HAL configuration file. + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2018 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_HAL_CONF_H +#define __STM32L4xx_HAL_CONF_H + +#ifdef __cplusplus + extern "C" { +#endif + +#include "main.h" +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* ########################## Module Selection ############################## */ +/** + * @brief This is the list of modules to be used in the HAL driver + */ + +#define HAL_MODULE_ENABLED +/*#define HAL_ADC_MODULE_ENABLED */ +/*#define HAL_CRYP_MODULE_ENABLED */ +/*#define HAL_CAN_MODULE_ENABLED */ +/*#define HAL_COMP_MODULE_ENABLED */ +/*#define HAL_CRC_MODULE_ENABLED */ +/*#define HAL_CRYP_MODULE_ENABLED */ +/*#define HAL_DAC_MODULE_ENABLED */ +/*#define HAL_DCMI_MODULE_ENABLED */ +/*#define HAL_DMA2D_MODULE_ENABLED */ +/*#define HAL_DFSDM_MODULE_ENABLED */ +/*#define HAL_DSI_MODULE_ENABLED */ +/*#define HAL_FIREWALL_MODULE_ENABLED */ +/*#define HAL_GFXMMU_MODULE_ENABLED */ +/*#define HAL_HCD_MODULE_ENABLED */ +/*#define HAL_HASH_MODULE_ENABLED */ +/*#define HAL_I2S_MODULE_ENABLED */ +/*#define HAL_IRDA_MODULE_ENABLED */ +/*#define HAL_IWDG_MODULE_ENABLED */ +/*#define HAL_LTDC_MODULE_ENABLED */ +/*#define HAL_LCD_MODULE_ENABLED */ +/*#define HAL_LPTIM_MODULE_ENABLED */ +/*#define HAL_NAND_MODULE_ENABLED */ +/*#define HAL_NOR_MODULE_ENABLED */ +/*#define HAL_OPAMP_MODULE_ENABLED */ +/*#define HAL_OSPI_MODULE_ENABLED */ +/*#define HAL_OSPI_MODULE_ENABLED */ +#define HAL_PCD_MODULE_ENABLED +/*#define HAL_QSPI_MODULE_ENABLED */ +/*#define HAL_QSPI_MODULE_ENABLED */ +#define HAL_RNG_MODULE_ENABLED +#define HAL_RTC_MODULE_ENABLED +/*#define HAL_SAI_MODULE_ENABLED */ +/*#define HAL_SD_MODULE_ENABLED */ +/*#define HAL_SMBUS_MODULE_ENABLED */ +/*#define HAL_SMARTCARD_MODULE_ENABLED */ +/*#define HAL_SPI_MODULE_ENABLED */ +/*#define HAL_SRAM_MODULE_ENABLED */ +/*#define HAL_SWPMI_MODULE_ENABLED */ +/*#define HAL_TIM_MODULE_ENABLED */ +/*#define HAL_TSC_MODULE_ENABLED */ +#define HAL_UART_MODULE_ENABLED +/*#define HAL_USART_MODULE_ENABLED */ +/*#define HAL_WWDG_MODULE_ENABLED */ +#define HAL_GPIO_MODULE_ENABLED +#define HAL_I2C_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED + +/* ########################## Oscillator Values adaptation ####################*/ +/** + * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSE is used as system clock source, directly or through the PLL). + */ +#if !defined (HSE_VALUE) + #define HSE_VALUE ((uint32_t)8000000U) /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSE_STARTUP_TIMEOUT) + #define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief Internal Multiple Speed oscillator (MSI) default value. + * This value is the default MSI range value after Reset. + */ +#if !defined (MSI_VALUE) + #define MSI_VALUE ((uint32_t)4000000U) /*!< Value of the Internal oscillator in Hz*/ +#endif /* MSI_VALUE */ +/** + * @brief Internal High Speed oscillator (HSI) value. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSI is used as system clock source, directly or through the PLL). + */ +#if !defined (HSI_VALUE) + #define HSI_VALUE ((uint32_t)16000000U) /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @brief Internal High Speed oscillator (HSI48) value for USB FS, SDMMC and RNG. + * This internal oscillator is mainly dedicated to provide a high precision clock to + * the USB peripheral by means of a special Clock Recovery System (CRS) circuitry. + * When the CRS is not used, the HSI48 RC oscillator runs on it default frequency + * which is subject to manufacturing process variations. + */ +#if !defined (HSI48_VALUE) + #define HSI48_VALUE ((uint32_t)48000000U) /*!< Value of the Internal High Speed oscillator for USB FS/SDMMC/RNG in Hz. + The real value my vary depending on manufacturing process variations.*/ +#endif /* HSI48_VALUE */ + +/** + * @brief Internal Low Speed oscillator (LSI) value. + */ +#if !defined (LSI_VALUE) + #define LSI_VALUE ((uint32_t)32000U) /*!< LSI Typical Value in Hz*/ +#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz + The real value may vary depending on the variations + in voltage and temperature.*/ + +/** + * @brief External Low Speed oscillator (LSE) value. + * This value is used by the UART, RTC HAL module to compute the system frequency + */ +#if !defined (LSE_VALUE) + #define LSE_VALUE ((uint32_t)32768U) /*!< Value of the External oscillator in Hz*/ +#endif /* LSE_VALUE */ + +#if !defined (LSE_STARTUP_TIMEOUT) + #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief External clock source for SAI1 peripheral + * This value is used by the RCC HAL module to compute the SAI1 & SAI2 clock source + * frequency. + */ +#if !defined (EXTERNAL_SAI1_CLOCK_VALUE) + #define EXTERNAL_SAI1_CLOCK_VALUE ((uint32_t)2097000U) /*!< Value of the SAI1 External clock source in Hz*/ +#endif /* EXTERNAL_SAI1_CLOCK_VALUE */ + +/** + * @brief External clock source for SAI2 peripheral + * This value is used by the RCC HAL module to compute the SAI1 & SAI2 clock source + * frequency. + */ +#if !defined (EXTERNAL_SAI2_CLOCK_VALUE) + #define EXTERNAL_SAI2_CLOCK_VALUE ((uint32_t)2097000U) /*!< Value of the SAI2 External clock source in Hz*/ +#endif /* EXTERNAL_SAI2_CLOCK_VALUE */ + +/* Tip: To avoid modifying this file each time you need to use different HSE, + === you can define the HSE value in your toolchain compiler preprocessor. */ + +/* ########################### System Configuration ######################### */ +/** + * @brief This is the HAL system configuration section + */ + +#define VDD_VALUE ((uint32_t)3300U) /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY ((uint32_t)0U) /*!< tick interrupt priority */ +#define USE_RTOS 0U +#define PREFETCH_ENABLE 0U +#define INSTRUCTION_CACHE_ENABLE 1U +#define DATA_CACHE_ENABLE 1U + +/* ########################## Assert Selection ############################## */ +/** + * @brief Uncomment the line below to expanse the "assert_param" macro in the + * HAL drivers code + */ +/* #define USE_FULL_ASSERT 1U */ + +/* ################## SPI peripheral configuration ########################## */ + +/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver + * Activated: CRC code is present inside driver + * Deactivated: CRC code cleaned from driver + */ + +#define USE_SPI_CRC 0U + +/* Includes ------------------------------------------------------------------*/ +/** + * @brief Include module's header file + */ + +#ifdef HAL_RCC_MODULE_ENABLED + #include "stm32l4xx_hal_rcc.h" + #include "stm32l4xx_hal_rcc_ex.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED + #include "stm32l4xx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_DMA_MODULE_ENABLED + #include "stm32l4xx_hal_dma.h" + #include "stm32l4xx_hal_dma_ex.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_DFSDM_MODULE_ENABLED + #include "stm32l4xx_hal_dfsdm.h" +#endif /* HAL_DFSDM_MODULE_ENABLED */ + +#ifdef HAL_CORTEX_MODULE_ENABLED + #include "stm32l4xx_hal_cortex.h" +#endif /* HAL_CORTEX_MODULE_ENABLED */ + +#ifdef HAL_ADC_MODULE_ENABLED + #include "stm32l4xx_hal_adc.h" +#endif /* HAL_ADC_MODULE_ENABLED */ + +#ifdef HAL_CAN_MODULE_ENABLED + #include "stm32l4xx_hal_can.h" +#endif /* HAL_CAN_MODULE_ENABLED */ + +#ifdef HAL_COMP_MODULE_ENABLED + #include "stm32l4xx_hal_comp.h" +#endif /* HAL_COMP_MODULE_ENABLED */ + +#ifdef HAL_CRC_MODULE_ENABLED + #include "stm32l4xx_hal_crc.h" +#endif /* HAL_CRC_MODULE_ENABLED */ + +#ifdef HAL_CRYP_MODULE_ENABLED + #include "stm32l4xx_hal_cryp.h" +#endif /* HAL_CRYP_MODULE_ENABLED */ + +#ifdef HAL_DAC_MODULE_ENABLED + #include "stm32l4xx_hal_dac.h" +#endif /* HAL_DAC_MODULE_ENABLED */ + +#ifdef HAL_DCMI_MODULE_ENABLED + #include "stm32l4xx_hal_dcmi.h" +#endif /* HAL_DCMI_MODULE_ENABLED */ + +#ifdef HAL_DMA2D_MODULE_ENABLED + #include "stm32l4xx_hal_dma2d.h" +#endif /* HAL_DMA2D_MODULE_ENABLED */ + +#ifdef HAL_DSI_MODULE_ENABLED + #include "stm32l4xx_hal_dsi.h" +#endif /* HAL_DSI_MODULE_ENABLED */ + +#ifdef HAL_FIREWALL_MODULE_ENABLED + #include "stm32l4xx_hal_firewall.h" +#endif /* HAL_FIREWALL_MODULE_ENABLED */ + +#ifdef HAL_FLASH_MODULE_ENABLED + #include "stm32l4xx_hal_flash.h" +#endif /* HAL_FLASH_MODULE_ENABLED */ + +#ifdef HAL_HASH_MODULE_ENABLED + #include "stm32l4xx_hal_hash.h" +#endif /* HAL_HASH_MODULE_ENABLED */ + +#ifdef HAL_SRAM_MODULE_ENABLED + #include "stm32l4xx_hal_sram.h" +#endif /* HAL_SRAM_MODULE_ENABLED */ + +#ifdef HAL_NOR_MODULE_ENABLED + #include "stm32l4xx_hal_nor.h" +#endif /* HAL_NOR_MODULE_ENABLED */ + +#ifdef HAL_NAND_MODULE_ENABLED + #include "stm32l4xx_hal_nand.h" +#endif /* HAL_NAND_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED + #include "stm32l4xx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED + #include "stm32l4xx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_LCD_MODULE_ENABLED + #include "stm32l4xx_hal_lcd.h" +#endif /* HAL_LCD_MODULE_ENABLED */ + +#ifdef HAL_LPTIM_MODULE_ENABLED + #include "stm32l4xx_hal_lptim.h" +#endif /* HAL_LPTIM_MODULE_ENABLED */ + +#ifdef HAL_LTDC_MODULE_ENABLED + #include "stm32l4xx_hal_ltdc.h" +#endif /* HAL_LTDC_MODULE_ENABLED */ + +#ifdef HAL_OPAMP_MODULE_ENABLED + #include "stm32l4xx_hal_opamp.h" +#endif /* HAL_OPAMP_MODULE_ENABLED */ + +#ifdef HAL_OSPI_MODULE_ENABLED + #include "stm32l4xx_hal_ospi.h" +#endif /* HAL_OSPI_MODULE_ENABLED */ + +#ifdef HAL_PWR_MODULE_ENABLED + #include "stm32l4xx_hal_pwr.h" +#endif /* HAL_PWR_MODULE_ENABLED */ + +#ifdef HAL_QSPI_MODULE_ENABLED + #include "stm32l4xx_hal_qspi.h" +#endif /* HAL_QSPI_MODULE_ENABLED */ + +#ifdef HAL_RNG_MODULE_ENABLED + #include "stm32l4xx_hal_rng.h" +#endif /* HAL_RNG_MODULE_ENABLED */ + +#ifdef HAL_RTC_MODULE_ENABLED + #include "stm32l4xx_hal_rtc.h" +#endif /* HAL_RTC_MODULE_ENABLED */ + +#ifdef HAL_SAI_MODULE_ENABLED + #include "stm32l4xx_hal_sai.h" +#endif /* HAL_SAI_MODULE_ENABLED */ + +#ifdef HAL_SD_MODULE_ENABLED + #include "stm32l4xx_hal_sd.h" +#endif /* HAL_SD_MODULE_ENABLED */ + +#ifdef HAL_SMBUS_MODULE_ENABLED + #include "stm32l4xx_hal_smbus.h" +#endif /* HAL_SMBUS_MODULE_ENABLED */ + +#ifdef HAL_SPI_MODULE_ENABLED + #include "stm32l4xx_hal_spi.h" +#endif /* HAL_SPI_MODULE_ENABLED */ + +#ifdef HAL_SWPMI_MODULE_ENABLED + #include "stm32l4xx_hal_swpmi.h" +#endif /* HAL_SWPMI_MODULE_ENABLED */ + +#ifdef HAL_TIM_MODULE_ENABLED + #include "stm32l4xx_hal_tim.h" +#endif /* HAL_TIM_MODULE_ENABLED */ + +#ifdef HAL_TSC_MODULE_ENABLED + #include "stm32l4xx_hal_tsc.h" +#endif /* HAL_TSC_MODULE_ENABLED */ + +#ifdef HAL_UART_MODULE_ENABLED + #include "stm32l4xx_hal_uart.h" +#endif /* HAL_UART_MODULE_ENABLED */ + +#ifdef HAL_USART_MODULE_ENABLED + #include "stm32l4xx_hal_usart.h" +#endif /* HAL_USART_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED + #include "stm32l4xx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_SMARTCARD_MODULE_ENABLED + #include "stm32l4xx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + +#ifdef HAL_WWDG_MODULE_ENABLED + #include "stm32l4xx_hal_wwdg.h" +#endif /* HAL_WWDG_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED + #include "stm32l4xx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +#ifdef HAL_HCD_MODULE_ENABLED + #include "stm32l4xx_hal_hcd.h" +#endif /* HAL_HCD_MODULE_ENABLED */ + +#ifdef HAL_GFXMMU_MODULE_ENABLED + #include "stm32l4xx_hal_gfxmmu.h" +#endif /* HAL_GFXMMU_MODULE_ENABLED */ + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr: If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ + #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ + void assert_failed(uint8_t* file, uint32_t line); +#else + #define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_HAL_CONF_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/stm32l4xx_it.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/stm32l4xx_it.h new file mode 100644 index 0000000..2c63e68 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/stm32l4xx_it.h @@ -0,0 +1,67 @@ +/** + ****************************************************************************** + * @file stm32l4xx_it.h + * @brief This file contains the headers of the interrupt handlers. + ****************************************************************************** + * + * COPYRIGHT(c) 2018 STMicroelectronics + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_IT_H +#define __STM32L4xx_IT_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" +#include "main.h" +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ + +void NMI_Handler(void); +void HardFault_Handler(void); +void MemManage_Handler(void); +void BusFault_Handler(void); +void UsageFault_Handler(void); +void SVC_Handler(void); +void DebugMon_Handler(void); +void PendSV_Handler(void); +void SysTick_Handler(void); +void OTG_FS_IRQHandler(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_IT_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/usb_device.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/usb_device.h new file mode 100644 index 0000000..9b2d33e --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/usb_device.h @@ -0,0 +1,114 @@ +/** + ****************************************************************************** + * @file : usb_device.h + * @version : v2.0_Cube + * @brief : Header for usb_device.c file. + ****************************************************************************** + * This notice applies to any and all portions of this file + * that are not between comment pairs USER CODE BEGIN and + * USER CODE END. Other portions of this file, whether + * inserted by the user or by software development tools + * are owned by their respective copyright owners. + * + * Copyright (c) 2018 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. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (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 to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_DEVICE__H__ +#define __USB_DEVICE__H__ + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx.h" +#include "stm32l4xx_hal.h" +#include "usbd_def.h" + +/* USER CODE BEGIN INCLUDE */ +void MX_USB_DEVICE_DeInit(void); +/* USER CODE END INCLUDE */ + +/** @addtogroup USBD_OTG_DRIVER + * @{ + */ + +/** @defgroup USBD_DEVICE USBD_DEVICE + * @brief Device file for Usb otg low level driver. + * @{ + */ + +/** @defgroup USBD_DEVICE_Exported_Variables USBD_DEVICE_Exported_Variables + * @brief Public variables. + * @{ + */ + +/** USB device core handle. */ +extern USBD_HandleTypeDef hUsbDeviceFS; + +/** + * @} + */ + +/** @defgroup USBD_DEVICE_Exported_FunctionsPrototype USBD_DEVICE_Exported_FunctionsPrototype + * @brief Declaration of public functions for Usb device. + * @{ + */ + +/** USB Device initialization function. */ +void MX_USB_DEVICE_Init(void); + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USB_DEVICE__H__ */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/usbd_cdc_if.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/usbd_cdc_if.h new file mode 100644 index 0000000..605b778 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/usbd_cdc_if.h @@ -0,0 +1,158 @@ +/** + ****************************************************************************** + * @file : usbd_cdc_if.h + * @version : v2.0_Cube + * @brief : Header for usbd_cdc_if.c file. + ****************************************************************************** + * This notice applies to any and all portions of this file + * that are not between comment pairs USER CODE BEGIN and + * USER CODE END. Other portions of this file, whether + * inserted by the user or by software development tools + * are owned by their respective copyright owners. + * + * Copyright (c) 2018 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. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (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 to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_CDC_IF_H__ +#define __USBD_CDC_IF_H__ + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_cdc.h" + +/* USER CODE BEGIN INCLUDE */ + +/* USER CODE END INCLUDE */ + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY + * @brief For Usb device. + * @{ + */ + +/** @defgroup USBD_CDC_IF USBD_CDC_IF + * @brief Usb VCP device module + * @{ + */ + +/** @defgroup USBD_CDC_IF_Exported_Defines USBD_CDC_IF_Exported_Defines + * @brief Defines. + * @{ + */ +/* USER CODE BEGIN EXPORTED_DEFINES */ + +/* USER CODE END EXPORTED_DEFINES */ + +/** + * @} + */ + +/** @defgroup USBD_CDC_IF_Exported_Types USBD_CDC_IF_Exported_Types + * @brief Types. + * @{ + */ + +/* USER CODE BEGIN EXPORTED_TYPES */ + +/* USER CODE END EXPORTED_TYPES */ + +/** + * @} + */ + +/** @defgroup USBD_CDC_IF_Exported_Macros USBD_CDC_IF_Exported_Macros + * @brief Aliases. + * @{ + */ + +/* USER CODE BEGIN EXPORTED_MACRO */ + +/* USER CODE END EXPORTED_MACRO */ + +/** + * @} + */ + +/** @defgroup USBD_CDC_IF_Exported_Variables USBD_CDC_IF_Exported_Variables + * @brief Public variables. + * @{ + */ + +/** CDC Interface callback. */ +extern USBD_CDC_ItfTypeDef USBD_Interface_fops_FS; + +/* USER CODE BEGIN EXPORTED_VARIABLES */ + +/* USER CODE END EXPORTED_VARIABLES */ + +/** + * @} + */ + +/** @defgroup USBD_CDC_IF_Exported_FunctionsPrototype USBD_CDC_IF_Exported_FunctionsPrototype + * @brief Public functions declaration. + * @{ + */ + +uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len); + +/* USER CODE BEGIN EXPORTED_FUNCTIONS */ + +/* USER CODE END EXPORTED_FUNCTIONS */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBD_CDC_IF_H__ */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/usbd_conf.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/usbd_conf.h new file mode 100644 index 0000000..df2e31c --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/usbd_conf.h @@ -0,0 +1,204 @@ +/** + ****************************************************************************** + * @file : usbd_conf.h + * @version : v2.0_Cube + * @brief : Header for usbd_conf.c file. + ****************************************************************************** + * This notice applies to any and all portions of this file + * that are not between comment pairs USER CODE BEGIN and + * USER CODE END. Other portions of this file, whether + * inserted by the user or by software development tools + * are owned by their respective copyright owners. + * + * Copyright (c) 2018 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. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (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 to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_CONF__H__ +#define __USBD_CONF__H__ + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include +#include +#include +#include "stm32l4xx.h" +#include "stm32l4xx_hal.h" + +/* USER CODE BEGIN INCLUDE */ + +/* USER CODE END INCLUDE */ + +/** @addtogroup USBD_OTG_DRIVER + * @brief Driver for Usb device. + * @{ + */ + +/** @defgroup USBD_CONF USBD_CONF + * @brief Configuration file for Usb otg low level driver. + * @{ + */ + +/** @defgroup USBD_CONF_Exported_Variables USBD_CONF_Exported_Variables + * @brief Public variables. + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_CONF_Exported_Defines USBD_CONF_Exported_Defines + * @brief Defines for configuration of the Usb device. + * @{ + */ + +/*---------- -----------*/ +#define USBD_MAX_NUM_INTERFACES 1 +/*---------- -----------*/ +#define USBD_MAX_NUM_CONFIGURATION 1 +/*---------- -----------*/ +#define USBD_MAX_STR_DESC_SIZ 512 +/*---------- -----------*/ +#define USBD_SUPPORT_USER_STRING 0 +/*---------- -----------*/ +#define USBD_DEBUG_LEVEL 0 +/*---------- -----------*/ +#define USBD_LPM_ENABLED 1 +/*---------- -----------*/ +#define USBD_SELF_POWERED 1 + +/****************************************/ +/* #define for FS and HS identification */ +#define DEVICE_FS 0 + +/** + * @} + */ + +/** @defgroup USBD_CONF_Exported_Macros USBD_CONF_Exported_Macros + * @brief Aliases. + * @{ + */ + +/* Memory management macros */ + +/** Alias for memory allocation. */ +#define USBD_malloc (uint32_t *)USBD_static_malloc + +/** Alias for memory release. */ +#define USBD_free USBD_static_free + +/** Alias for memory set. */ +#define USBD_memset /* Not used */ + +/** Alias for memory copy. */ +#define USBD_memcpy /* Not used */ + +/** Alias for delay. */ +#define USBD_Delay HAL_Delay + +/* DEBUG macros */ + +#if (USBD_DEBUG_LEVEL > 0) +#define USBD_UsrLog(...) printf(__VA_ARGS__);\ + printf("\n"); +#else +#define USBD_UsrLog(...) +#endif + +#if (USBD_DEBUG_LEVEL > 1) + +#define USBD_ErrLog(...) printf("ERROR: ") ;\ + printf(__VA_ARGS__);\ + printf("\n"); +#else +#define USBD_ErrLog(...) +#endif + +#if (USBD_DEBUG_LEVEL > 2) +#define USBD_DbgLog(...) printf("DEBUG : ") ;\ + printf(__VA_ARGS__);\ + printf("\n"); +#else +#define USBD_DbgLog(...) +#endif + +/** + * @} + */ + +/** @defgroup USBD_CONF_Exported_Types USBD_CONF_Exported_Types + * @brief Types. + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_CONF_Exported_FunctionsPrototype USBD_CONF_Exported_FunctionsPrototype + * @brief Declaration of public functions for Usb device. + * @{ + */ + +/* Exported functions -------------------------------------------------------*/ +void *USBD_static_malloc(uint32_t size); +void USBD_static_free(void *p); + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBD_CONF__H__ */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/usbd_desc.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/usbd_desc.h new file mode 100644 index 0000000..98fd79d --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Inc/usbd_desc.h @@ -0,0 +1,156 @@ +/** + ****************************************************************************** + * @file : usbd_desc.h + * @version : v2.0_Cube + * @brief : Header for usbd_desc.c file. + ****************************************************************************** + * This notice applies to any and all portions of this file + * that are not between comment pairs USER CODE BEGIN and + * USER CODE END. Other portions of this file, whether + * inserted by the user or by software development tools + * are owned by their respective copyright owners. + * + * Copyright (c) 2018 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. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (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 to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_DESC__H__ +#define __USBD_DESC__H__ + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_def.h" + +/* USER CODE BEGIN INCLUDE */ + +/* USER CODE END INCLUDE */ + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USBD_DESC USBD_DESC + * @brief Usb device descriptors module. + * @{ + */ + +/** @defgroup USBD_DESC_Exported_Defines USBD_DESC_Exported_Defines + * @brief Defines. + * @{ + */ + +/* USER CODE BEGIN EXPORTED_DEFINES */ + +/* USER CODE END EXPORTED_DEFINES */ + +/** + * @} + */ + +/** @defgroup USBD_DESC_Exported_TypesDefinitions USBD_DESC_Exported_TypesDefinitions + * @brief Types. + * @{ + */ + +/* USER CODE BEGIN EXPORTED_TYPES */ + +/* USER CODE END EXPORTED_TYPES */ + +/** + * @} + */ + +/** @defgroup USBD_DESC_Exported_Macros USBD_DESC_Exported_Macros + * @brief Aliases. + * @{ + */ + +/* USER CODE BEGIN EXPORTED_MACRO */ + +/* USER CODE END EXPORTED_MACRO */ + +/** + * @} + */ + +/** @defgroup USBD_DESC_Exported_Variables USBD_DESC_Exported_Variables + * @brief Public variables. + * @{ + */ + +/** Descriptor for the Usb device. */ +extern USBD_DescriptorsTypeDef FS_Desc; + +/* USER CODE BEGIN EXPORTED_VARIABLES */ + +/* USER CODE END EXPORTED_VARIABLES */ + +/** + * @} + */ + +/** @defgroup USBD_DESC_Exported_FunctionsPrototype USBD_DESC_Exported_FunctionsPrototype + * @brief Public functions declaration. + * @{ + */ + +/* USER CODE BEGIN EXPORTED_FUNCTIONS */ + +/* USER CODE END EXPORTED_FUNCTIONS */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBD_DESC__H__ */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc/usbd_cdc.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc/usbd_cdc.h new file mode 100644 index 0000000..36badcd --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc/usbd_cdc.h @@ -0,0 +1,179 @@ +/** + ****************************************************************************** + * @file usbd_cdc.h + * @author MCD Application Team + * @version V2.4.2 + * @date 11-December-2015 + * @brief header file for the usbd_cdc.c file. + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT 2015 STMicroelectronics

    + * + * Licensed under MCD-ST Liberty SW License Agreement V2, (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.st.com/software_license_agreement_liberty_v2 + * + * 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_CDC_H +#define __USB_CDC_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_ioreq.h" + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup usbd_cdc + * @brief This file is the Header file for usbd_cdc.c + * @{ + */ + + +/** @defgroup usbd_cdc_Exported_Defines + * @{ + */ +#define CDC_IN_EP 0x81 /* EP1 for data IN */ +#define CDC_OUT_EP 0x01 /* EP1 for data OUT */ +#define CDC_CMD_EP 0x82 /* EP2 for CDC commands */ + +/* CDC Endpoints parameters: you can fine tune these values depending on the needed baudrates and performance. */ +#define CDC_DATA_HS_MAX_PACKET_SIZE 512 /* Endpoint IN & OUT Packet size */ +#define CDC_DATA_FS_MAX_PACKET_SIZE 64 /* Endpoint IN & OUT Packet size */ +#define CDC_CMD_PACKET_SIZE 8 /* Control Endpoint Packet size */ + +#define USB_CDC_CONFIG_DESC_SIZ 67 +#define CDC_DATA_HS_IN_PACKET_SIZE CDC_DATA_HS_MAX_PACKET_SIZE +#define CDC_DATA_HS_OUT_PACKET_SIZE CDC_DATA_HS_MAX_PACKET_SIZE + +#define CDC_DATA_FS_IN_PACKET_SIZE CDC_DATA_FS_MAX_PACKET_SIZE +#define CDC_DATA_FS_OUT_PACKET_SIZE CDC_DATA_FS_MAX_PACKET_SIZE + +/*---------------------------------------------------------------------*/ +/* CDC definitions */ +/*---------------------------------------------------------------------*/ +#define CDC_SEND_ENCAPSULATED_COMMAND 0x00 +#define CDC_GET_ENCAPSULATED_RESPONSE 0x01 +#define CDC_SET_COMM_FEATURE 0x02 +#define CDC_GET_COMM_FEATURE 0x03 +#define CDC_CLEAR_COMM_FEATURE 0x04 +#define CDC_SET_LINE_CODING 0x20 +#define CDC_GET_LINE_CODING 0x21 +#define CDC_SET_CONTROL_LINE_STATE 0x22 +#define CDC_SEND_BREAK 0x23 + +/** + * @} + */ + + +/** @defgroup USBD_CORE_Exported_TypesDefinitions + * @{ + */ + +/** + * @} + */ +typedef struct +{ + uint32_t bitrate; + uint8_t format; + uint8_t paritytype; + uint8_t datatype; +}USBD_CDC_LineCodingTypeDef; + +typedef struct _USBD_CDC_Itf +{ + int8_t (* Init) (void); + int8_t (* DeInit) (void); + int8_t (* Control) (uint8_t, uint8_t * , uint16_t); + int8_t (* Receive) (uint8_t *, uint32_t *); + +}USBD_CDC_ItfTypeDef; + + +typedef struct +{ + uint32_t data[CDC_DATA_HS_MAX_PACKET_SIZE/4]; /* Force 32bits alignment */ + uint8_t CmdOpCode; + uint8_t CmdLength; + uint8_t *RxBuffer; + uint8_t *TxBuffer; + uint32_t RxLength; + uint32_t TxLength; + + __IO uint32_t TxState; + __IO uint32_t RxState; +} +USBD_CDC_HandleTypeDef; + + + +/** @defgroup USBD_CORE_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_CORE_Exported_Variables + * @{ + */ + +extern USBD_ClassTypeDef USBD_CDC; +#define USBD_CDC_CLASS &USBD_CDC +/** + * @} + */ + +/** @defgroup USB_CORE_Exported_Functions + * @{ + */ +uint8_t USBD_CDC_RegisterInterface (USBD_HandleTypeDef *pdev, + USBD_CDC_ItfTypeDef *fops); + +uint8_t USBD_CDC_SetTxBuffer (USBD_HandleTypeDef *pdev, + uint8_t *pbuff, + uint16_t length); + +uint8_t USBD_CDC_SetRxBuffer (USBD_HandleTypeDef *pdev, + uint8_t *pbuff); + +uint8_t USBD_CDC_ReceivePacket (USBD_HandleTypeDef *pdev); + +uint8_t USBD_CDC_TransmitPacket (USBD_HandleTypeDef *pdev); +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USB_CDC_H */ +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c new file mode 100644 index 0000000..cb77a71 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c @@ -0,0 +1,925 @@ +/** + ****************************************************************************** + * @file usbd_cdc.c + * @author MCD Application Team + * @version V2.4.2 + * @date 11-December-2015 + * @brief This file provides the high layer firmware functions to manage the + * following functionalities of the USB CDC Class: + * - Initialization and Configuration of high and low layer + * - Enumeration as CDC Device (and enumeration for each implemented memory interface) + * - OUT/IN data transfer + * - Command IN transfer (class requests management) + * - Error management + * + * @verbatim + * + * =================================================================== + * CDC Class Driver Description + * =================================================================== + * This driver manages the "Universal Serial Bus Class Definitions for Communications Devices + * Revision 1.2 November 16, 2007" and the sub-protocol specification of "Universal Serial Bus + * Communications Class Subclass Specification for PSTN Devices Revision 1.2 February 9, 2007" + * This driver implements the following aspects of the specification: + * - Device descriptor management + * - Configuration descriptor management + * - Enumeration as CDC device with 2 data endpoints (IN and OUT) and 1 command endpoint (IN) + * - Requests management (as described in section 6.2 in specification) + * - Abstract Control Model compliant + * - Union Functional collection (using 1 IN endpoint for control) + * - Data interface class + * + * These aspects may be enriched or modified for a specific user application. + * + * This driver doesn't implement the following aspects of the specification + * (but it is possible to manage these features with some modifications on this driver): + * - Any class-specific aspect relative to communication classes should be managed by user application. + * - All communication classes other than PSTN are not managed + * + * @endverbatim + * + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT 2015 STMicroelectronics

    + * + * Licensed under MCD-ST Liberty SW License Agreement V2, (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.st.com/software_license_agreement_liberty_v2 + * + * 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_cdc.h" +#include "usbd_desc.h" +#include "usbd_ctlreq.h" + + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + + +/** @defgroup USBD_CDC + * @brief usbd core module + * @{ + */ + +/** @defgroup USBD_CDC_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_CDC_Private_Defines + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_CDC_Private_Macros + * @{ + */ + +/** + * @} + */ + + +/** @defgroup USBD_CDC_Private_FunctionPrototypes + * @{ + */ + + +static uint8_t USBD_CDC_Init (USBD_HandleTypeDef *pdev, + uint8_t cfgidx); + +static uint8_t USBD_CDC_DeInit (USBD_HandleTypeDef *pdev, + uint8_t cfgidx); + +static uint8_t USBD_CDC_Setup (USBD_HandleTypeDef *pdev, + USBD_SetupReqTypedef *req); + +static uint8_t USBD_CDC_DataIn (USBD_HandleTypeDef *pdev, + uint8_t epnum); + +static uint8_t USBD_CDC_DataOut (USBD_HandleTypeDef *pdev, + uint8_t epnum); + +static uint8_t USBD_CDC_EP0_RxReady (USBD_HandleTypeDef *pdev); + +static uint8_t *USBD_CDC_GetFSCfgDesc (uint16_t *length); + +static uint8_t *USBD_CDC_GetHSCfgDesc (uint16_t *length); + +static uint8_t *USBD_CDC_GetOtherSpeedCfgDesc (uint16_t *length); + +static uint8_t *USBD_CDC_GetOtherSpeedCfgDesc (uint16_t *length); + +uint8_t *USBD_CDC_GetDeviceQualifierDescriptor (uint16_t *length); + +/* USB Standard Device Descriptor */ +__ALIGN_BEGIN static uint8_t USBD_CDC_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END = +{ + USB_LEN_DEV_QUALIFIER_DESC, + USB_DESC_TYPE_DEVICE_QUALIFIER, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x40, + 0x01, + 0x00, +}; + +/** + * @} + */ + +/** @defgroup USBD_CDC_Private_Variables + * @{ + */ + + +/* CDC interface class callbacks structure */ +USBD_ClassTypeDef USBD_CDC = +{ + USBD_CDC_Init, + USBD_CDC_DeInit, + USBD_CDC_Setup, + NULL, /* EP0_TxSent, */ + USBD_CDC_EP0_RxReady, + USBD_CDC_DataIn, + USBD_CDC_DataOut, + NULL, + NULL, + NULL, + USBD_CDC_GetHSCfgDesc, + USBD_CDC_GetFSCfgDesc, + USBD_CDC_GetOtherSpeedCfgDesc, + USBD_CDC_GetDeviceQualifierDescriptor, +}; + +/* USB CDC device Configuration Descriptor */ +__ALIGN_BEGIN uint8_t USBD_CDC_CfgHSDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END = +{ + /*Configuration Descriptor*/ + 0x09, /* bLength: Configuration Descriptor size */ + USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ + USB_CDC_CONFIG_DESC_SIZ, /* wTotalLength:no of returned bytes */ + 0x00, + 0x02, /* bNumInterfaces: 2 interface */ + 0x01, /* bConfigurationValue: Configuration value */ + 0x00, /* iConfiguration: Index of string descriptor describing the configuration */ + 0xC0, /* bmAttributes: self powered */ + 0x32, /* MaxPower 0 mA */ + + /*---------------------------------------------------------------------------*/ + + /*Interface Descriptor */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */ + /* Interface descriptor type */ + 0x00, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x01, /* bNumEndpoints: One endpoints used */ + 0x02, /* bInterfaceClass: Communication Interface Class */ + 0x02, /* bInterfaceSubClass: Abstract Control Model */ + 0x01, /* bInterfaceProtocol: Common AT commands */ + 0x00, /* iInterface: */ + + /*Header Functional Descriptor*/ + 0x05, /* bLength: Endpoint Descriptor size */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x00, /* bDescriptorSubtype: Header Func Desc */ + 0x10, /* bcdCDC: spec release number */ + 0x01, + + /*Call Management Functional Descriptor*/ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x01, /* bDescriptorSubtype: Call Management Func Desc */ + 0x00, /* bmCapabilities: D0+D1 */ + 0x01, /* bDataInterface: 1 */ + + /*ACM Functional Descriptor*/ + 0x04, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x02, /* bDescriptorSubtype: Abstract Control Management desc */ + 0x02, /* bmCapabilities */ + + /*Union Functional Descriptor*/ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x06, /* bDescriptorSubtype: Union func desc */ + 0x00, /* bMasterInterface: Communication class interface */ + 0x01, /* bSlaveInterface0: Data Class Interface */ + + /*Endpoint 2 Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + CDC_CMD_EP, /* bEndpointAddress */ + 0x03, /* bmAttributes: Interrupt */ + LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_CMD_PACKET_SIZE), + 0x10, /* bInterval: */ + /*---------------------------------------------------------------------------*/ + + /*Data class interface descriptor*/ + 0x09, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */ + 0x01, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints: Two endpoints used */ + 0x0A, /* bInterfaceClass: CDC */ + 0x00, /* bInterfaceSubClass: */ + 0x00, /* bInterfaceProtocol: */ + 0x00, /* iInterface: */ + + /*Endpoint OUT Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + CDC_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), + 0x00, /* bInterval: ignore for Bulk transfer */ + + /*Endpoint IN Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + CDC_IN_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), + 0x00 /* bInterval: ignore for Bulk transfer */ +} ; + + +/* USB CDC device Configuration Descriptor */ +__ALIGN_BEGIN uint8_t USBD_CDC_CfgFSDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END = +{ + /*Configuration Descriptor*/ + 0x09, /* bLength: Configuration Descriptor size */ + USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ + USB_CDC_CONFIG_DESC_SIZ, /* wTotalLength:no of returned bytes */ + 0x00, + 0x02, /* bNumInterfaces: 2 interface */ + 0x01, /* bConfigurationValue: Configuration value */ + 0x00, /* iConfiguration: Index of string descriptor describing the configuration */ + 0xC0, /* bmAttributes: self powered */ + 0x32, /* MaxPower 0 mA */ + + /*---------------------------------------------------------------------------*/ + + /*Interface Descriptor */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */ + /* Interface descriptor type */ + 0x00, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x01, /* bNumEndpoints: One endpoints used */ + 0x02, /* bInterfaceClass: Communication Interface Class */ + 0x02, /* bInterfaceSubClass: Abstract Control Model */ + 0x01, /* bInterfaceProtocol: Common AT commands */ + 0x00, /* iInterface: */ + + /*Header Functional Descriptor*/ + 0x05, /* bLength: Endpoint Descriptor size */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x00, /* bDescriptorSubtype: Header Func Desc */ + 0x10, /* bcdCDC: spec release number */ + 0x01, + + /*Call Management Functional Descriptor*/ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x01, /* bDescriptorSubtype: Call Management Func Desc */ + 0x00, /* bmCapabilities: D0+D1 */ + 0x01, /* bDataInterface: 1 */ + + /*ACM Functional Descriptor*/ + 0x04, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x02, /* bDescriptorSubtype: Abstract Control Management desc */ + 0x02, /* bmCapabilities */ + + /*Union Functional Descriptor*/ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x06, /* bDescriptorSubtype: Union func desc */ + 0x00, /* bMasterInterface: Communication class interface */ + 0x01, /* bSlaveInterface0: Data Class Interface */ + + /*Endpoint 2 Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + CDC_CMD_EP, /* bEndpointAddress */ + 0x03, /* bmAttributes: Interrupt */ + LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_CMD_PACKET_SIZE), + 0x10, /* bInterval: */ + /*---------------------------------------------------------------------------*/ + + /*Data class interface descriptor*/ + 0x09, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */ + 0x01, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints: Two endpoints used */ + 0x0A, /* bInterfaceClass: CDC */ + 0x00, /* bInterfaceSubClass: */ + 0x00, /* bInterfaceProtocol: */ + 0x00, /* iInterface: */ + + /*Endpoint OUT Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + CDC_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), + 0x00, /* bInterval: ignore for Bulk transfer */ + + /*Endpoint IN Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + CDC_IN_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), + 0x00 /* bInterval: ignore for Bulk transfer */ +} ; + +__ALIGN_BEGIN uint8_t USBD_CDC_OtherSpeedCfgDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END = +{ + 0x09, /* bLength: Configuation Descriptor size */ + USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION, + USB_CDC_CONFIG_DESC_SIZ, + 0x00, + 0x02, /* bNumInterfaces: 2 interfaces */ + 0x01, /* bConfigurationValue: */ + 0x04, /* iConfiguration: */ + 0xC0, /* bmAttributes: */ + 0x32, /* MaxPower 100 mA */ + + /*Interface Descriptor */ + 0x09, /* bLength: Interface Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */ + /* Interface descriptor type */ + 0x00, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x01, /* bNumEndpoints: One endpoints used */ + 0x02, /* bInterfaceClass: Communication Interface Class */ + 0x02, /* bInterfaceSubClass: Abstract Control Model */ + 0x01, /* bInterfaceProtocol: Common AT commands */ + 0x00, /* iInterface: */ + + /*Header Functional Descriptor*/ + 0x05, /* bLength: Endpoint Descriptor size */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x00, /* bDescriptorSubtype: Header Func Desc */ + 0x10, /* bcdCDC: spec release number */ + 0x01, + + /*Call Management Functional Descriptor*/ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x01, /* bDescriptorSubtype: Call Management Func Desc */ + 0x00, /* bmCapabilities: D0+D1 */ + 0x01, /* bDataInterface: 1 */ + + /*ACM Functional Descriptor*/ + 0x04, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x02, /* bDescriptorSubtype: Abstract Control Management desc */ + 0x02, /* bmCapabilities */ + + /*Union Functional Descriptor*/ + 0x05, /* bFunctionLength */ + 0x24, /* bDescriptorType: CS_INTERFACE */ + 0x06, /* bDescriptorSubtype: Union func desc */ + 0x00, /* bMasterInterface: Communication class interface */ + 0x01, /* bSlaveInterface0: Data Class Interface */ + + /*Endpoint 2 Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT , /* bDescriptorType: Endpoint */ + CDC_CMD_EP, /* bEndpointAddress */ + 0x03, /* bmAttributes: Interrupt */ + LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */ + HIBYTE(CDC_CMD_PACKET_SIZE), + 0xFF, /* bInterval: */ + + /*---------------------------------------------------------------------------*/ + + /*Data class interface descriptor*/ + 0x09, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */ + 0x01, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints: Two endpoints used */ + 0x0A, /* bInterfaceClass: CDC */ + 0x00, /* bInterfaceSubClass: */ + 0x00, /* bInterfaceProtocol: */ + 0x00, /* iInterface: */ + + /*Endpoint OUT Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + CDC_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + 0x40, /* wMaxPacketSize: */ + 0x00, + 0x00, /* bInterval: ignore for Bulk transfer */ + + /*Endpoint IN Descriptor*/ + 0x07, /* bLength: Endpoint Descriptor size */ + USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ + CDC_IN_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes: Bulk */ + 0x40, /* wMaxPacketSize: */ + 0x00, + 0x00 /* bInterval */ +}; + +/** + * @} + */ + +/** @defgroup USBD_CDC_Private_Functions + * @{ + */ + +/** + * @brief USBD_CDC_Init + * Initialize the CDC interface + * @param pdev: device instance + * @param cfgidx: Configuration index + * @retval status + */ +static uint8_t USBD_CDC_Init (USBD_HandleTypeDef *pdev, + uint8_t cfgidx) +{ + uint8_t ret = 0; + USBD_CDC_HandleTypeDef *hcdc; + + if(pdev->dev_speed == USBD_SPEED_HIGH ) + { + /* Open EP IN */ + USBD_LL_OpenEP(pdev, + CDC_IN_EP, + USBD_EP_TYPE_BULK, + CDC_DATA_HS_IN_PACKET_SIZE); + + /* Open EP OUT */ + USBD_LL_OpenEP(pdev, + CDC_OUT_EP, + USBD_EP_TYPE_BULK, + CDC_DATA_HS_OUT_PACKET_SIZE); + + } + else + { + /* Open EP IN */ + USBD_LL_OpenEP(pdev, + CDC_IN_EP, + USBD_EP_TYPE_BULK, + CDC_DATA_FS_IN_PACKET_SIZE); + + /* Open EP OUT */ + USBD_LL_OpenEP(pdev, + CDC_OUT_EP, + USBD_EP_TYPE_BULK, + CDC_DATA_FS_OUT_PACKET_SIZE); + } + /* Open Command IN EP */ + USBD_LL_OpenEP(pdev, + CDC_CMD_EP, + USBD_EP_TYPE_INTR, + CDC_CMD_PACKET_SIZE); + + + pdev->pClassData = USBD_malloc(sizeof (USBD_CDC_HandleTypeDef)); + + if(pdev->pClassData == NULL) + { + ret = 1; + } + else + { + hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData; + + /* Init physical Interface components */ + ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Init(); + + /* Init Xfer states */ + hcdc->TxState =0; + hcdc->RxState =0; + + if(pdev->dev_speed == USBD_SPEED_HIGH ) + { + /* Prepare Out endpoint to receive next packet */ + USBD_LL_PrepareReceive(pdev, + CDC_OUT_EP, + hcdc->RxBuffer, + CDC_DATA_HS_OUT_PACKET_SIZE); + } + else + { + /* Prepare Out endpoint to receive next packet */ + USBD_LL_PrepareReceive(pdev, + CDC_OUT_EP, + hcdc->RxBuffer, + CDC_DATA_FS_OUT_PACKET_SIZE); + } + + + } + return ret; +} + +/** + * @brief USBD_CDC_Init + * DeInitialize the CDC layer + * @param pdev: device instance + * @param cfgidx: Configuration index + * @retval status + */ +static uint8_t USBD_CDC_DeInit (USBD_HandleTypeDef *pdev, + uint8_t cfgidx) +{ + uint8_t ret = 0; + + /* Open EP IN */ + USBD_LL_CloseEP(pdev, + CDC_IN_EP); + + /* Open EP OUT */ + USBD_LL_CloseEP(pdev, + CDC_OUT_EP); + + /* Open Command IN EP */ + USBD_LL_CloseEP(pdev, + CDC_CMD_EP); + + + /* DeInit physical Interface components */ + if(pdev->pClassData != NULL) + { + ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->DeInit(); + USBD_free(pdev->pClassData); + pdev->pClassData = NULL; + } + + return ret; +} + +/** + * @brief USBD_CDC_Setup + * Handle the CDC specific requests + * @param pdev: instance + * @param req: usb requests + * @retval status + */ +static uint8_t USBD_CDC_Setup (USBD_HandleTypeDef *pdev, + USBD_SetupReqTypedef *req) +{ + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData; + static uint8_t ifalt = 0; + + switch (req->bmRequest & USB_REQ_TYPE_MASK) + { + case USB_REQ_TYPE_CLASS : + if (req->wLength) + { + if (req->bmRequest & 0x80) + { + ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Control(req->bRequest, + (uint8_t *)hcdc->data, + req->wLength); + USBD_CtlSendData (pdev, + (uint8_t *)hcdc->data, + req->wLength); + } + else + { + hcdc->CmdOpCode = req->bRequest; + hcdc->CmdLength = req->wLength; + + USBD_CtlPrepareRx (pdev, + (uint8_t *)hcdc->data, + req->wLength); + } + + } + else + { + ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Control(req->bRequest, + (uint8_t*)req, + 0); + } + break; + + case USB_REQ_TYPE_STANDARD: + switch (req->bRequest) + { + case USB_REQ_GET_INTERFACE : + USBD_CtlSendData (pdev, + &ifalt, + 1); + break; + + case USB_REQ_SET_INTERFACE : + break; + } + + default: + break; + } + return USBD_OK; +} + +/** + * @brief USBD_CDC_DataIn + * Data sent on non-control IN endpoint + * @param pdev: device instance + * @param epnum: endpoint number + * @retval status + */ +static uint8_t USBD_CDC_DataIn (USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData; + + if(pdev->pClassData != NULL) + { + + hcdc->TxState = 0; + + return USBD_OK; + } + else + { + return USBD_FAIL; + } +} + +/** + * @brief USBD_CDC_DataOut + * Data received on non-control Out endpoint + * @param pdev: device instance + * @param epnum: endpoint number + * @retval status + */ +static uint8_t USBD_CDC_DataOut (USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData; + + /* Get the received data length */ + hcdc->RxLength = USBD_LL_GetRxDataSize (pdev, epnum); + + /* USB data will be immediately processed, this allow next USB traffic being + NAKed till the end of the application Xfer */ + if(pdev->pClassData != NULL) + { + ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Receive(hcdc->RxBuffer, &hcdc->RxLength); + + return USBD_OK; + } + else + { + return USBD_FAIL; + } +} + + + +/** + * @brief USBD_CDC_DataOut + * Data received on non-control Out endpoint + * @param pdev: device instance + * @param epnum: endpoint number + * @retval status + */ +static uint8_t USBD_CDC_EP0_RxReady (USBD_HandleTypeDef *pdev) +{ + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData; + + if((pdev->pUserData != NULL) && (hcdc->CmdOpCode != 0xFF)) + { + ((USBD_CDC_ItfTypeDef *)pdev->pUserData)->Control(hcdc->CmdOpCode, + (uint8_t *)hcdc->data, + hcdc->CmdLength); + hcdc->CmdOpCode = 0xFF; + + } + return USBD_OK; +} + +/** + * @brief USBD_CDC_GetFSCfgDesc + * Return configuration descriptor + * @param speed : current device speed + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_CDC_GetFSCfgDesc (uint16_t *length) +{ + *length = sizeof (USBD_CDC_CfgFSDesc); + return USBD_CDC_CfgFSDesc; +} + +/** + * @brief USBD_CDC_GetHSCfgDesc + * Return configuration descriptor + * @param speed : current device speed + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_CDC_GetHSCfgDesc (uint16_t *length) +{ + *length = sizeof (USBD_CDC_CfgHSDesc); + return USBD_CDC_CfgHSDesc; +} + +/** + * @brief USBD_CDC_GetCfgDesc + * Return configuration descriptor + * @param speed : current device speed + * @param length : pointer data length + * @retval pointer to descriptor buffer + */ +static uint8_t *USBD_CDC_GetOtherSpeedCfgDesc (uint16_t *length) +{ + *length = sizeof (USBD_CDC_OtherSpeedCfgDesc); + return USBD_CDC_OtherSpeedCfgDesc; +} + +/** +* @brief DeviceQualifierDescriptor +* return Device Qualifier descriptor +* @param length : pointer data length +* @retval pointer to descriptor buffer +*/ +uint8_t *USBD_CDC_GetDeviceQualifierDescriptor (uint16_t *length) +{ + *length = sizeof (USBD_CDC_DeviceQualifierDesc); + return USBD_CDC_DeviceQualifierDesc; +} + +/** +* @brief USBD_CDC_RegisterInterface + * @param pdev: device instance + * @param fops: CD Interface callback + * @retval status + */ +uint8_t USBD_CDC_RegisterInterface (USBD_HandleTypeDef *pdev, + USBD_CDC_ItfTypeDef *fops) +{ + uint8_t ret = USBD_FAIL; + + if(fops != NULL) + { + pdev->pUserData= fops; + ret = USBD_OK; + } + + return ret; +} + +/** + * @brief USBD_CDC_SetTxBuffer + * @param pdev: device instance + * @param pbuff: Tx Buffer + * @retval status + */ +uint8_t USBD_CDC_SetTxBuffer (USBD_HandleTypeDef *pdev, + uint8_t *pbuff, + uint16_t length) +{ + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData; + + hcdc->TxBuffer = pbuff; + hcdc->TxLength = length; + + return USBD_OK; +} + + +/** + * @brief USBD_CDC_SetRxBuffer + * @param pdev: device instance + * @param pbuff: Rx Buffer + * @retval status + */ +uint8_t USBD_CDC_SetRxBuffer (USBD_HandleTypeDef *pdev, + uint8_t *pbuff) +{ + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData; + + hcdc->RxBuffer = pbuff; + + return USBD_OK; +} + +/** + * @brief USBD_CDC_DataOut + * Data received on non-control Out endpoint + * @param pdev: device instance + * @param epnum: endpoint number + * @retval status + */ +uint8_t USBD_CDC_TransmitPacket(USBD_HandleTypeDef *pdev) +{ + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData; + + if(pdev->pClassData != NULL) + { + if(hcdc->TxState == 0) + { + /* Tx Transfer in progress */ + hcdc->TxState = 1; + + /* Transmit next packet */ + USBD_LL_Transmit(pdev, + CDC_IN_EP, + hcdc->TxBuffer, + hcdc->TxLength); + + return USBD_OK; + } + else + { + return USBD_BUSY; + } + } + else + { + return USBD_FAIL; + } +} + + +/** + * @brief USBD_CDC_ReceivePacket + * prepare OUT Endpoint for reception + * @param pdev: device instance + * @retval status + */ +uint8_t USBD_CDC_ReceivePacket(USBD_HandleTypeDef *pdev) +{ + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*) pdev->pClassData; + + /* Suspend or Resume USB Out process */ + if(pdev->pClassData != NULL) + { + if(pdev->dev_speed == USBD_SPEED_HIGH ) + { + /* Prepare Out endpoint to receive next packet */ + USBD_LL_PrepareReceive(pdev, + CDC_OUT_EP, + hcdc->RxBuffer, + CDC_DATA_HS_OUT_PACKET_SIZE); + } + else + { + /* Prepare Out endpoint to receive next packet */ + USBD_LL_PrepareReceive(pdev, + CDC_OUT_EP, + hcdc->RxBuffer, + CDC_DATA_FS_OUT_PACKET_SIZE); + } + return USBD_OK; + } + else + { + return USBD_FAIL; + } +} +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_core.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_core.h new file mode 100644 index 0000000..fcfffa1 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_core.h @@ -0,0 +1,167 @@ +/** + ****************************************************************************** + * @file usbd_core.h + * @author MCD Application Team + * @version V2.4.2 + * @date 11-December-2015 + * @brief Header file for usbd_core.c file + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT 2015 STMicroelectronics

    + * + * Licensed under MCD-ST Liberty SW License Agreement V2, (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.st.com/software_license_agreement_liberty_v2 + * + * 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_CORE_H +#define __USBD_CORE_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_conf.h" +#include "usbd_def.h" +#include "usbd_ioreq.h" +#include "usbd_ctlreq.h" + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USBD_CORE + * @brief This file is the Header file for usbd_core.c file + * @{ + */ + + +/** @defgroup USBD_CORE_Exported_Defines + * @{ + */ + +/** + * @} + */ + + +/** @defgroup USBD_CORE_Exported_TypesDefinitions + * @{ + */ + + +/** + * @} + */ + + + +/** @defgroup USBD_CORE_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_CORE_Exported_Variables + * @{ + */ +#define USBD_SOF USBD_LL_SOF +/** + * @} + */ + +/** @defgroup USBD_CORE_Exported_FunctionsPrototype + * @{ + */ +USBD_StatusTypeDef USBD_Init(USBD_HandleTypeDef *pdev, USBD_DescriptorsTypeDef *pdesc, uint8_t id); +USBD_StatusTypeDef USBD_DeInit(USBD_HandleTypeDef *pdev); +USBD_StatusTypeDef USBD_Start (USBD_HandleTypeDef *pdev); +USBD_StatusTypeDef USBD_Stop (USBD_HandleTypeDef *pdev); +USBD_StatusTypeDef USBD_RegisterClass(USBD_HandleTypeDef *pdev, USBD_ClassTypeDef *pclass); + +USBD_StatusTypeDef USBD_RunTestMode (USBD_HandleTypeDef *pdev); +USBD_StatusTypeDef USBD_SetClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx); +USBD_StatusTypeDef USBD_ClrClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx); + +USBD_StatusTypeDef USBD_LL_SetupStage(USBD_HandleTypeDef *pdev, uint8_t *psetup); +USBD_StatusTypeDef USBD_LL_DataOutStage(USBD_HandleTypeDef *pdev , uint8_t epnum, uint8_t *pdata); +USBD_StatusTypeDef USBD_LL_DataInStage(USBD_HandleTypeDef *pdev , uint8_t epnum, uint8_t *pdata); + +USBD_StatusTypeDef USBD_LL_Reset(USBD_HandleTypeDef *pdev); +USBD_StatusTypeDef USBD_LL_SetSpeed(USBD_HandleTypeDef *pdev, USBD_SpeedTypeDef speed); +USBD_StatusTypeDef USBD_LL_Suspend(USBD_HandleTypeDef *pdev); +USBD_StatusTypeDef USBD_LL_Resume(USBD_HandleTypeDef *pdev); + +USBD_StatusTypeDef USBD_LL_SOF(USBD_HandleTypeDef *pdev); +USBD_StatusTypeDef USBD_LL_IsoINIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum); +USBD_StatusTypeDef USBD_LL_IsoOUTIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum); + +USBD_StatusTypeDef USBD_LL_DevConnected(USBD_HandleTypeDef *pdev); +USBD_StatusTypeDef USBD_LL_DevDisconnected(USBD_HandleTypeDef *pdev); + +/* USBD Low Level Driver */ +USBD_StatusTypeDef USBD_LL_Init (USBD_HandleTypeDef *pdev); +USBD_StatusTypeDef USBD_LL_DeInit (USBD_HandleTypeDef *pdev); +USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev); +USBD_StatusTypeDef USBD_LL_Stop (USBD_HandleTypeDef *pdev); +USBD_StatusTypeDef USBD_LL_OpenEP (USBD_HandleTypeDef *pdev, + uint8_t ep_addr, + uint8_t ep_type, + uint16_t ep_mps); + +USBD_StatusTypeDef USBD_LL_CloseEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr); +USBD_StatusTypeDef USBD_LL_FlushEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr); +USBD_StatusTypeDef USBD_LL_StallEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr); +USBD_StatusTypeDef USBD_LL_ClearStallEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr); +uint8_t USBD_LL_IsStallEP (USBD_HandleTypeDef *pdev, uint8_t ep_addr); +USBD_StatusTypeDef USBD_LL_SetUSBAddress (USBD_HandleTypeDef *pdev, uint8_t dev_addr); +USBD_StatusTypeDef USBD_LL_Transmit (USBD_HandleTypeDef *pdev, + uint8_t ep_addr, + uint8_t *pbuf, + uint16_t size); + +USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev, + uint8_t ep_addr, + uint8_t *pbuf, + uint16_t size); + +uint32_t USBD_LL_GetRxDataSize (USBD_HandleTypeDef *pdev, uint8_t ep_addr); +void USBD_LL_Delay (uint32_t Delay); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBD_CORE_H */ + +/** + * @} + */ + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + + + diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ctlreq.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ctlreq.h new file mode 100644 index 0000000..f4ddfb2 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ctlreq.h @@ -0,0 +1,113 @@ +/** + ****************************************************************************** + * @file usbd_req.h + * @author MCD Application Team + * @version V2.4.2 + * @date 11-December-2015 + * @brief Header file for the usbd_req.c file + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT 2015 STMicroelectronics

    + * + * Licensed under MCD-ST Liberty SW License Agreement V2, (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.st.com/software_license_agreement_liberty_v2 + * + * 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_REQUEST_H +#define __USB_REQUEST_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_def.h" + + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USBD_REQ + * @brief header file for the usbd_req.c file + * @{ + */ + +/** @defgroup USBD_REQ_Exported_Defines + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_REQ_Exported_Types + * @{ + */ +/** + * @} + */ + + + +/** @defgroup USBD_REQ_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USBD_REQ_Exported_Variables + * @{ + */ +/** + * @} + */ + +/** @defgroup USBD_REQ_Exported_FunctionsPrototype + * @{ + */ + +USBD_StatusTypeDef USBD_StdDevReq (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); +USBD_StatusTypeDef USBD_StdItfReq (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); +USBD_StatusTypeDef USBD_StdEPReq (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); + + +void USBD_CtlError (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req); + +void USBD_ParseSetupRequest (USBD_SetupReqTypedef *req, uint8_t *pdata); + +void USBD_GetString (uint8_t *desc, uint8_t *unicode, uint16_t *len); +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USB_REQUEST_H */ + +/** + * @} + */ + +/** +* @} +*/ + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_def.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_def.h new file mode 100644 index 0000000..34a4220 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_def.h @@ -0,0 +1,330 @@ +/** + ****************************************************************************** + * @file usbd_def.h + * @author MCD Application Team + * @version V2.4.2 + * @date 11-December-2015 + * @brief General defines for the usb device library + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT 2015 STMicroelectronics

    + * + * Licensed under MCD-ST Liberty SW License Agreement V2, (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.st.com/software_license_agreement_liberty_v2 + * + * 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_DEF_H +#define __USBD_DEF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_conf.h" + +/** @addtogroup STM32_USBD_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USB_DEF + * @brief general defines for the usb device library file + * @{ + */ + +/** @defgroup USB_DEF_Exported_Defines + * @{ + */ + +#ifndef NULL +#define NULL 0 +#endif + + +#define USB_LEN_DEV_QUALIFIER_DESC 0x0A +#define USB_LEN_DEV_DESC 0x12 +#define USB_LEN_CFG_DESC 0x09 +#define USB_LEN_IF_DESC 0x09 +#define USB_LEN_EP_DESC 0x07 +#define USB_LEN_OTG_DESC 0x03 +#define USB_LEN_LANGID_STR_DESC 0x04 +#define USB_LEN_OTHER_SPEED_DESC_SIZ 0x09 + +#define USBD_IDX_LANGID_STR 0x00 +#define USBD_IDX_MFC_STR 0x01 +#define USBD_IDX_PRODUCT_STR 0x02 +#define USBD_IDX_SERIAL_STR 0x03 +#define USBD_IDX_CONFIG_STR 0x04 +#define USBD_IDX_INTERFACE_STR 0x05 + +#define USB_REQ_TYPE_STANDARD 0x00 +#define USB_REQ_TYPE_CLASS 0x20 +#define USB_REQ_TYPE_VENDOR 0x40 +#define USB_REQ_TYPE_MASK 0x60 + +#define USB_REQ_RECIPIENT_DEVICE 0x00 +#define USB_REQ_RECIPIENT_INTERFACE 0x01 +#define USB_REQ_RECIPIENT_ENDPOINT 0x02 +#define USB_REQ_RECIPIENT_MASK 0x03 + +#define USB_REQ_GET_STATUS 0x00 +#define USB_REQ_CLEAR_FEATURE 0x01 +#define USB_REQ_SET_FEATURE 0x03 +#define USB_REQ_SET_ADDRESS 0x05 +#define USB_REQ_GET_DESCRIPTOR 0x06 +#define USB_REQ_SET_DESCRIPTOR 0x07 +#define USB_REQ_GET_CONFIGURATION 0x08 +#define USB_REQ_SET_CONFIGURATION 0x09 +#define USB_REQ_GET_INTERFACE 0x0A +#define USB_REQ_SET_INTERFACE 0x0B +#define USB_REQ_SYNCH_FRAME 0x0C + +#define USB_DESC_TYPE_DEVICE 1 +#define USB_DESC_TYPE_CONFIGURATION 2 +#define USB_DESC_TYPE_STRING 3 +#define USB_DESC_TYPE_INTERFACE 4 +#define USB_DESC_TYPE_ENDPOINT 5 +#define USB_DESC_TYPE_DEVICE_QUALIFIER 6 +#define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION 7 +#define USB_DESC_TYPE_BOS 0x0F + +#define USB_CONFIG_REMOTE_WAKEUP 2 +#define USB_CONFIG_SELF_POWERED 1 + +#define USB_FEATURE_EP_HALT 0 +#define USB_FEATURE_REMOTE_WAKEUP 1 +#define USB_FEATURE_TEST_MODE 2 + +#define USB_DEVICE_CAPABITY_TYPE 0x10 + +#define USB_HS_MAX_PACKET_SIZE 512 +#define USB_FS_MAX_PACKET_SIZE 64 +#define USB_MAX_EP0_SIZE 64 + +/* Device Status */ +#define USBD_STATE_DEFAULT 1 +#define USBD_STATE_ADDRESSED 2 +#define USBD_STATE_CONFIGURED 3 +#define USBD_STATE_SUSPENDED 4 + + +/* EP0 State */ +#define USBD_EP0_IDLE 0 +#define USBD_EP0_SETUP 1 +#define USBD_EP0_DATA_IN 2 +#define USBD_EP0_DATA_OUT 3 +#define USBD_EP0_STATUS_IN 4 +#define USBD_EP0_STATUS_OUT 5 +#define USBD_EP0_STALL 6 + +#define USBD_EP_TYPE_CTRL 0 +#define USBD_EP_TYPE_ISOC 1 +#define USBD_EP_TYPE_BULK 2 +#define USBD_EP_TYPE_INTR 3 + + +/** + * @} + */ + + +/** @defgroup USBD_DEF_Exported_TypesDefinitions + * @{ + */ + +typedef struct usb_setup_req +{ + + uint8_t bmRequest; + uint8_t bRequest; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; +}USBD_SetupReqTypedef; + +struct _USBD_HandleTypeDef; + +typedef struct _Device_cb +{ + uint8_t (*Init) (struct _USBD_HandleTypeDef *pdev , uint8_t cfgidx); + uint8_t (*DeInit) (struct _USBD_HandleTypeDef *pdev , uint8_t cfgidx); + /* Control Endpoints*/ + uint8_t (*Setup) (struct _USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req); + uint8_t (*EP0_TxSent) (struct _USBD_HandleTypeDef *pdev ); + uint8_t (*EP0_RxReady) (struct _USBD_HandleTypeDef *pdev ); + /* Class Specific Endpoints*/ + uint8_t (*DataIn) (struct _USBD_HandleTypeDef *pdev , uint8_t epnum); + uint8_t (*DataOut) (struct _USBD_HandleTypeDef *pdev , uint8_t epnum); + uint8_t (*SOF) (struct _USBD_HandleTypeDef *pdev); + uint8_t (*IsoINIncomplete) (struct _USBD_HandleTypeDef *pdev , uint8_t epnum); + uint8_t (*IsoOUTIncomplete) (struct _USBD_HandleTypeDef *pdev , uint8_t epnum); + + uint8_t *(*GetHSConfigDescriptor)(uint16_t *length); + uint8_t *(*GetFSConfigDescriptor)(uint16_t *length); + uint8_t *(*GetOtherSpeedConfigDescriptor)(uint16_t *length); + uint8_t *(*GetDeviceQualifierDescriptor)(uint16_t *length); +#if (USBD_SUPPORT_USER_STRING == 1) + uint8_t *(*GetUsrStrDescriptor)(struct _USBD_HandleTypeDef *pdev ,uint8_t index, uint16_t *length); +#endif + +} USBD_ClassTypeDef; + +/* Following USB Device Speed */ +typedef enum +{ + USBD_SPEED_HIGH = 0, + USBD_SPEED_FULL = 1, + USBD_SPEED_LOW = 2, +}USBD_SpeedTypeDef; + +/* Following USB Device status */ +typedef enum { + USBD_OK = 0, + USBD_BUSY, + USBD_FAIL, +}USBD_StatusTypeDef; + +/* USB Device descriptors structure */ +typedef struct +{ + uint8_t *(*GetDeviceDescriptor)( USBD_SpeedTypeDef speed , uint16_t *length); + uint8_t *(*GetLangIDStrDescriptor)( USBD_SpeedTypeDef speed , uint16_t *length); + uint8_t *(*GetManufacturerStrDescriptor)( USBD_SpeedTypeDef speed , uint16_t *length); + uint8_t *(*GetProductStrDescriptor)( USBD_SpeedTypeDef speed , uint16_t *length); + uint8_t *(*GetSerialStrDescriptor)( USBD_SpeedTypeDef speed , uint16_t *length); + uint8_t *(*GetConfigurationStrDescriptor)( USBD_SpeedTypeDef speed , uint16_t *length); + uint8_t *(*GetInterfaceStrDescriptor)( USBD_SpeedTypeDef speed , uint16_t *length); +#if (USBD_LPM_ENABLED == 1) + uint8_t *(*GetBOSDescriptor)( USBD_SpeedTypeDef speed , uint16_t *length); +#endif +} USBD_DescriptorsTypeDef; + +/* USB Device handle structure */ +typedef struct +{ + uint32_t status; + uint32_t total_length; + uint32_t rem_length; + uint32_t maxpacket; +} USBD_EndpointTypeDef; + +/* USB Device handle structure */ +typedef struct _USBD_HandleTypeDef +{ + uint8_t id; + uint32_t dev_config; + uint32_t dev_default_config; + uint32_t dev_config_status; + USBD_SpeedTypeDef dev_speed; + USBD_EndpointTypeDef ep_in[15]; + USBD_EndpointTypeDef ep_out[15]; + uint32_t ep0_state; + uint32_t ep0_data_len; + uint8_t dev_state; + uint8_t dev_old_state; + uint8_t dev_address; + uint8_t dev_connection_status; + uint8_t dev_test_mode; + uint32_t dev_remote_wakeup; + + USBD_SetupReqTypedef request; + USBD_DescriptorsTypeDef *pDesc; + USBD_ClassTypeDef *pClass; + void *pClassData; + void *pUserData; + void *pData; +} USBD_HandleTypeDef; + +/** + * @} + */ + + + +/** @defgroup USBD_DEF_Exported_Macros + * @{ + */ +#define SWAPBYTE(addr) (((uint16_t)(*((uint8_t *)(addr)))) + \ + (((uint16_t)(*(((uint8_t *)(addr)) + 1))) << 8)) + +#define LOBYTE(x) ((uint8_t)(x & 0x00FF)) +#define HIBYTE(x) ((uint8_t)((x & 0xFF00) >>8)) +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) + + +#if defined ( __GNUC__ ) + #ifndef __weak + #define __weak __attribute__((weak)) + #endif /* __weak */ + #ifndef __packed + #define __packed __attribute__((__packed__)) + #endif /* __packed */ +#endif /* __GNUC__ */ + + +/* In HS mode and when the DMA is used, all variables and data structures dealing + with the DMA during the transaction process should be 4-bytes aligned */ + +#if defined (__GNUC__) /* GNU Compiler */ + #define __ALIGN_END __attribute__ ((aligned (4))) + #define __ALIGN_BEGIN +#else + #define __ALIGN_END + #if defined (__CC_ARM) /* ARM Compiler */ + #define __ALIGN_BEGIN __align(4) + #elif defined (__ICCARM__) /* IAR Compiler */ + #define __ALIGN_BEGIN + #elif defined (__TASKING__) /* TASKING Compiler */ + #define __ALIGN_BEGIN __align(4) + #endif /* __CC_ARM */ +#endif /* __GNUC__ */ + + +/** + * @} + */ + +/** @defgroup USBD_DEF_Exported_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_DEF_Exported_FunctionsPrototype + * @{ + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBD_DEF_H */ + +/** + * @} + */ + +/** +* @} +*/ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ioreq.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ioreq.h new file mode 100644 index 0000000..bb5d85c --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Inc/usbd_ioreq.h @@ -0,0 +1,128 @@ +/** + ****************************************************************************** + * @file usbd_ioreq.h + * @author MCD Application Team + * @version V2.4.2 + * @date 11-December-2015 + * @brief Header file for the usbd_ioreq.c file + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT 2015 STMicroelectronics

    + * + * Licensed under MCD-ST Liberty SW License Agreement V2, (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.st.com/software_license_agreement_liberty_v2 + * + * 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USBD_IOREQ_H +#define __USBD_IOREQ_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_def.h" +#include "usbd_core.h" + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + +/** @defgroup USBD_IOREQ + * @brief header file for the usbd_ioreq.c file + * @{ + */ + +/** @defgroup USBD_IOREQ_Exported_Defines + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_IOREQ_Exported_Types + * @{ + */ + + +/** + * @} + */ + + + +/** @defgroup USBD_IOREQ_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_IOREQ_Exported_Variables + * @{ + */ + +/** + * @} + */ + +/** @defgroup USBD_IOREQ_Exported_FunctionsPrototype + * @{ + */ + +USBD_StatusTypeDef USBD_CtlSendData (USBD_HandleTypeDef *pdev, + uint8_t *buf, + uint16_t len); + +USBD_StatusTypeDef USBD_CtlContinueSendData (USBD_HandleTypeDef *pdev, + uint8_t *pbuf, + uint16_t len); + +USBD_StatusTypeDef USBD_CtlPrepareRx (USBD_HandleTypeDef *pdev, + uint8_t *pbuf, + uint16_t len); + +USBD_StatusTypeDef USBD_CtlContinueRx (USBD_HandleTypeDef *pdev, + uint8_t *pbuf, + uint16_t len); + +USBD_StatusTypeDef USBD_CtlSendStatus (USBD_HandleTypeDef *pdev); + +USBD_StatusTypeDef USBD_CtlReceiveStatus (USBD_HandleTypeDef *pdev); + +uint16_t USBD_GetRxCount (USBD_HandleTypeDef *pdev , + uint8_t epnum); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBD_IOREQ_H */ + +/** + * @} + */ + +/** +* @} +*/ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c new file mode 100644 index 0000000..ff3ed44 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c @@ -0,0 +1,565 @@ +/** + ****************************************************************************** + * @file usbd_core.c + * @author MCD Application Team + * @version V2.4.2 + * @date 11-December-2015 + * @brief This file provides all the USBD core functions. + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT 2015 STMicroelectronics

    + * + * Licensed under MCD-ST Liberty SW License Agreement V2, (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.st.com/software_license_agreement_liberty_v2 + * + * 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_core.h" + +/** @addtogroup STM32_USBD_DEVICE_LIBRARY +* @{ +*/ + + +/** @defgroup USBD_CORE +* @brief usbd core module +* @{ +*/ + +/** @defgroup USBD_CORE_Private_TypesDefinitions +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USBD_CORE_Private_Defines +* @{ +*/ + +/** +* @} +*/ + + +/** @defgroup USBD_CORE_Private_Macros +* @{ +*/ +/** +* @} +*/ + + + + +/** @defgroup USBD_CORE_Private_FunctionPrototypes +* @{ +*/ + +/** +* @} +*/ + +/** @defgroup USBD_CORE_Private_Variables +* @{ +*/ + +/** +* @} +*/ + +/** @defgroup USBD_CORE_Private_Functions +* @{ +*/ + +/** +* @brief USBD_Init +* Initializes the device stack and load the class driver +* @param pdev: device instance +* @param pdesc: Descriptor structure address +* @param id: Low level core index +* @retval None +*/ +USBD_StatusTypeDef USBD_Init(USBD_HandleTypeDef *pdev, USBD_DescriptorsTypeDef *pdesc, uint8_t id) +{ + /* Check whether the USB Host handle is valid */ + if(pdev == NULL) + { + USBD_ErrLog("Invalid Device handle"); + return USBD_FAIL; + } + + /* Unlink previous class*/ + if(pdev->pClass != NULL) + { + pdev->pClass = NULL; + } + + /* Assign USBD Descriptors */ + if(pdesc != NULL) + { + pdev->pDesc = pdesc; + } + + /* Set Device initial State */ + pdev->dev_state = USBD_STATE_DEFAULT; + pdev->id = id; + /* Initialize low level driver */ + USBD_LL_Init(pdev); + + return USBD_OK; +} + +/** +* @brief USBD_DeInit +* Re-Initialize th device library +* @param pdev: device instance +* @retval status: status +*/ +USBD_StatusTypeDef USBD_DeInit(USBD_HandleTypeDef *pdev) +{ + /* Set Default State */ + pdev->dev_state = USBD_STATE_DEFAULT; + + /* Free Class Resources */ + pdev->pClass->DeInit(pdev, pdev->dev_config); + + /* Stop the low level driver */ + USBD_LL_Stop(pdev); + + /* Initialize low level driver */ + USBD_LL_DeInit(pdev); + + return USBD_OK; +} + + +/** + * @brief USBD_RegisterClass + * Link class driver to Device Core. + * @param pDevice : Device Handle + * @param pclass: Class handle + * @retval USBD Status + */ +USBD_StatusTypeDef USBD_RegisterClass(USBD_HandleTypeDef *pdev, USBD_ClassTypeDef *pclass) +{ + USBD_StatusTypeDef status = USBD_OK; + if(pclass != 0) + { + /* link the class to the USB Device handle */ + pdev->pClass = pclass; + status = USBD_OK; + } + else + { + USBD_ErrLog("Invalid Class handle"); + status = USBD_FAIL; + } + + return status; +} + +/** + * @brief USBD_Start + * Start the USB Device Core. + * @param pdev: Device Handle + * @retval USBD Status + */ +USBD_StatusTypeDef USBD_Start (USBD_HandleTypeDef *pdev) +{ + + /* Start the low level driver */ + USBD_LL_Start(pdev); + + return USBD_OK; +} + +/** + * @brief USBD_Stop + * Stop the USB Device Core. + * @param pdev: Device Handle + * @retval USBD Status + */ +USBD_StatusTypeDef USBD_Stop (USBD_HandleTypeDef *pdev) +{ + /* Free Class Resources */ + pdev->pClass->DeInit(pdev, pdev->dev_config); + + /* Stop the low level driver */ + USBD_LL_Stop(pdev); + + return USBD_OK; +} + +/** +* @brief USBD_RunTestMode +* Launch test mode process +* @param pdev: device instance +* @retval status +*/ +USBD_StatusTypeDef USBD_RunTestMode (USBD_HandleTypeDef *pdev) +{ + return USBD_OK; +} + + +/** +* @brief USBD_SetClassConfig +* Configure device and start the interface +* @param pdev: device instance +* @param cfgidx: configuration index +* @retval status +*/ + +USBD_StatusTypeDef USBD_SetClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx) +{ + USBD_StatusTypeDef ret = USBD_FAIL; + + if(pdev->pClass != NULL) + { + /* Set configuration and Start the Class*/ + if(pdev->pClass->Init(pdev, cfgidx) == 0) + { + ret = USBD_OK; + } + } + return ret; +} + +/** +* @brief USBD_ClrClassConfig +* Clear current configuration +* @param pdev: device instance +* @param cfgidx: configuration index +* @retval status: USBD_StatusTypeDef +*/ +USBD_StatusTypeDef USBD_ClrClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx) +{ + /* Clear configuration and De-initialize the Class process*/ + pdev->pClass->DeInit(pdev, cfgidx); + return USBD_OK; +} + + +/** +* @brief USBD_SetupStage +* Handle the setup stage +* @param pdev: device instance +* @retval status +*/ +USBD_StatusTypeDef USBD_LL_SetupStage(USBD_HandleTypeDef *pdev, uint8_t *psetup) +{ + + USBD_ParseSetupRequest(&pdev->request, psetup); + + pdev->ep0_state = USBD_EP0_SETUP; + pdev->ep0_data_len = pdev->request.wLength; + + switch (pdev->request.bmRequest & 0x1F) + { + case USB_REQ_RECIPIENT_DEVICE: + USBD_StdDevReq (pdev, &pdev->request); + break; + + case USB_REQ_RECIPIENT_INTERFACE: + USBD_StdItfReq(pdev, &pdev->request); + break; + + case USB_REQ_RECIPIENT_ENDPOINT: + USBD_StdEPReq(pdev, &pdev->request); + break; + + default: + USBD_LL_StallEP(pdev , pdev->request.bmRequest & 0x80); + break; + } + return USBD_OK; +} + +/** +* @brief USBD_DataOutStage +* Handle data OUT stage +* @param pdev: device instance +* @param epnum: endpoint index +* @retval status +*/ +USBD_StatusTypeDef USBD_LL_DataOutStage(USBD_HandleTypeDef *pdev , uint8_t epnum, uint8_t *pdata) +{ + USBD_EndpointTypeDef *pep; + + if(epnum == 0) + { + pep = &pdev->ep_out[0]; + + if ( pdev->ep0_state == USBD_EP0_DATA_OUT) + { + if(pep->rem_length > pep->maxpacket) + { + pep->rem_length -= pep->maxpacket; + + USBD_CtlContinueRx (pdev, + pdata, + MIN(pep->rem_length ,pep->maxpacket)); + } + else + { + if((pdev->pClass->EP0_RxReady != NULL)&& + (pdev->dev_state == USBD_STATE_CONFIGURED)) + { + pdev->pClass->EP0_RxReady(pdev); + } + USBD_CtlSendStatus(pdev); + } + } + } + else if((pdev->pClass->DataOut != NULL)&& + (pdev->dev_state == USBD_STATE_CONFIGURED)) + { + pdev->pClass->DataOut(pdev, epnum); + } + return USBD_OK; +} + +/** +* @brief USBD_DataInStage +* Handle data in stage +* @param pdev: device instance +* @param epnum: endpoint index +* @retval status +*/ +USBD_StatusTypeDef USBD_LL_DataInStage(USBD_HandleTypeDef *pdev ,uint8_t epnum, uint8_t *pdata) +{ + USBD_EndpointTypeDef *pep; + + if(epnum == 0) + { + pep = &pdev->ep_in[0]; + + if ( pdev->ep0_state == USBD_EP0_DATA_IN) + { + if(pep->rem_length > pep->maxpacket) + { + pep->rem_length -= pep->maxpacket; + + USBD_CtlContinueSendData (pdev, + pdata, + pep->rem_length); + + /* Prepare endpoint for premature end of transfer */ + USBD_LL_PrepareReceive (pdev, + 0, + NULL, + 0); + } + else + { /* last packet is MPS multiple, so send ZLP packet */ + if((pep->total_length % pep->maxpacket == 0) && + (pep->total_length >= pep->maxpacket) && + (pep->total_length < pdev->ep0_data_len )) + { + + USBD_CtlContinueSendData(pdev , NULL, 0); + pdev->ep0_data_len = 0; + + /* Prepare endpoint for premature end of transfer */ + USBD_LL_PrepareReceive (pdev, + 0, + NULL, + 0); + } + else + { + if((pdev->pClass->EP0_TxSent != NULL)&& + (pdev->dev_state == USBD_STATE_CONFIGURED)) + { + pdev->pClass->EP0_TxSent(pdev); + } + USBD_CtlReceiveStatus(pdev); + } + } + } + if (pdev->dev_test_mode == 1) + { + USBD_RunTestMode(pdev); + pdev->dev_test_mode = 0; + } + } + else if((pdev->pClass->DataIn != NULL)&& + (pdev->dev_state == USBD_STATE_CONFIGURED)) + { + pdev->pClass->DataIn(pdev, epnum); + } + return USBD_OK; +} + +/** +* @brief USBD_LL_Reset +* Handle Reset event +* @param pdev: device instance +* @retval status +*/ + +USBD_StatusTypeDef USBD_LL_Reset(USBD_HandleTypeDef *pdev) +{ + /* Open EP0 OUT */ + USBD_LL_OpenEP(pdev, + 0x00, + USBD_EP_TYPE_CTRL, + USB_MAX_EP0_SIZE); + + pdev->ep_out[0].maxpacket = USB_MAX_EP0_SIZE; + + /* Open EP0 IN */ + USBD_LL_OpenEP(pdev, + 0x80, + USBD_EP_TYPE_CTRL, + USB_MAX_EP0_SIZE); + + pdev->ep_in[0].maxpacket = USB_MAX_EP0_SIZE; + /* Upon Reset call user call back */ + pdev->dev_state = USBD_STATE_DEFAULT; + + if (pdev->pClassData) + pdev->pClass->DeInit(pdev, pdev->dev_config); + + + return USBD_OK; +} + + + + +/** +* @brief USBD_LL_Reset +* Handle Reset event +* @param pdev: device instance +* @retval status +*/ +USBD_StatusTypeDef USBD_LL_SetSpeed(USBD_HandleTypeDef *pdev, USBD_SpeedTypeDef speed) +{ + pdev->dev_speed = speed; + return USBD_OK; +} + +/** +* @brief USBD_Suspend +* Handle Suspend event +* @param pdev: device instance +* @retval status +*/ + +USBD_StatusTypeDef USBD_LL_Suspend(USBD_HandleTypeDef *pdev) +{ + pdev->dev_old_state = pdev->dev_state; + pdev->dev_state = USBD_STATE_SUSPENDED; + return USBD_OK; +} + +/** +* @brief USBD_Resume +* Handle Resume event +* @param pdev: device instance +* @retval status +*/ + +USBD_StatusTypeDef USBD_LL_Resume(USBD_HandleTypeDef *pdev) +{ + pdev->dev_state = pdev->dev_old_state; + return USBD_OK; +} + +/** +* @brief USBD_SOF +* Handle SOF event +* @param pdev: device instance +* @retval status +*/ + +USBD_StatusTypeDef USBD_LL_SOF(USBD_HandleTypeDef *pdev) +{ + if(pdev->dev_state == USBD_STATE_CONFIGURED) + { + if(pdev->pClass->SOF != NULL) + { + pdev->pClass->SOF(pdev); + } + } + return USBD_OK; +} + +/** +* @brief USBD_IsoINIncomplete +* Handle iso in incomplete event +* @param pdev: device instance +* @retval status +*/ +USBD_StatusTypeDef USBD_LL_IsoINIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + return USBD_OK; +} + +/** +* @brief USBD_IsoOUTIncomplete +* Handle iso out incomplete event +* @param pdev: device instance +* @retval status +*/ +USBD_StatusTypeDef USBD_LL_IsoOUTIncomplete(USBD_HandleTypeDef *pdev, uint8_t epnum) +{ + return USBD_OK; +} + +/** +* @brief USBD_DevConnected +* Handle device connection event +* @param pdev: device instance +* @retval status +*/ +USBD_StatusTypeDef USBD_LL_DevConnected(USBD_HandleTypeDef *pdev) +{ + return USBD_OK; +} + +/** +* @brief USBD_DevDisconnected +* Handle device disconnection event +* @param pdev: device instance +* @retval status +*/ +USBD_StatusTypeDef USBD_LL_DevDisconnected(USBD_HandleTypeDef *pdev) +{ + /* Free Class Resources */ + pdev->dev_state = USBD_STATE_DEFAULT; + pdev->pClass->DeInit(pdev, pdev->dev_config); + + return USBD_OK; +} +/** +* @} +*/ + + +/** +* @} +*/ + + +/** +* @} +*/ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c new file mode 100644 index 0000000..22f815d --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c @@ -0,0 +1,782 @@ +/** + ****************************************************************************** + * @file usbd_req.c + * @author MCD Application Team + * @version V2.4.2 + * @date 11-December-2015 + * @brief This file provides the standard USB requests following chapter 9. + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT 2015 STMicroelectronics

    + * + * Licensed under MCD-ST Liberty SW License Agreement V2, (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.st.com/software_license_agreement_liberty_v2 + * + * 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_ctlreq.h" +#include "usbd_ioreq.h" + + +/** @addtogroup STM32_USBD_STATE_DEVICE_LIBRARY + * @{ + */ + + +/** @defgroup USBD_REQ + * @brief USB standard requests module + * @{ + */ + +/** @defgroup USBD_REQ_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_REQ_Private_Defines + * @{ + */ + +/** + * @} + */ + + +/** @defgroup USBD_REQ_Private_Macros + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_REQ_Private_Variables + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_REQ_Private_FunctionPrototypes + * @{ + */ +static void USBD_GetDescriptor(USBD_HandleTypeDef *pdev , + USBD_SetupReqTypedef *req); + +static void USBD_SetAddress(USBD_HandleTypeDef *pdev , + USBD_SetupReqTypedef *req); + +static void USBD_SetConfig(USBD_HandleTypeDef *pdev , + USBD_SetupReqTypedef *req); + +static void USBD_GetConfig(USBD_HandleTypeDef *pdev , + USBD_SetupReqTypedef *req); + +static void USBD_GetStatus(USBD_HandleTypeDef *pdev , + USBD_SetupReqTypedef *req); + +static void USBD_SetFeature(USBD_HandleTypeDef *pdev , + USBD_SetupReqTypedef *req); + +static void USBD_ClrFeature(USBD_HandleTypeDef *pdev , + USBD_SetupReqTypedef *req); + +static uint8_t USBD_GetLen(uint8_t *buf); + +/** + * @} + */ + + +/** @defgroup USBD_REQ_Private_Functions + * @{ + */ + + +/** +* @brief USBD_StdDevReq +* Handle standard usb device requests +* @param pdev: device instance +* @param req: usb request +* @retval status +*/ +USBD_StatusTypeDef USBD_StdDevReq (USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req) +{ + USBD_StatusTypeDef ret = USBD_OK; + + switch (req->bRequest) + { + case USB_REQ_GET_DESCRIPTOR: + + USBD_GetDescriptor (pdev, req) ; + break; + + case USB_REQ_SET_ADDRESS: + USBD_SetAddress(pdev, req); + break; + + case USB_REQ_SET_CONFIGURATION: + USBD_SetConfig (pdev , req); + break; + + case USB_REQ_GET_CONFIGURATION: + USBD_GetConfig (pdev , req); + break; + + case USB_REQ_GET_STATUS: + USBD_GetStatus (pdev , req); + break; + + + case USB_REQ_SET_FEATURE: + USBD_SetFeature (pdev , req); + break; + + case USB_REQ_CLEAR_FEATURE: + USBD_ClrFeature (pdev , req); + break; + + default: + USBD_CtlError(pdev , req); + break; + } + + return ret; +} + +/** +* @brief USBD_StdItfReq +* Handle standard usb interface requests +* @param pdev: device instance +* @param req: usb request +* @retval status +*/ +USBD_StatusTypeDef USBD_StdItfReq (USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req) +{ + USBD_StatusTypeDef ret = USBD_OK; + + switch (pdev->dev_state) + { + case USBD_STATE_CONFIGURED: + + if (LOBYTE(req->wIndex) <= USBD_MAX_NUM_INTERFACES) + { + pdev->pClass->Setup (pdev, req); + + if((req->wLength == 0)&& (ret == USBD_OK)) + { + USBD_CtlSendStatus(pdev); + } + } + else + { + USBD_CtlError(pdev , req); + } + break; + + default: + USBD_CtlError(pdev , req); + break; + } + return USBD_OK; +} + +/** +* @brief USBD_StdEPReq +* Handle standard usb endpoint requests +* @param pdev: device instance +* @param req: usb request +* @retval status +*/ +USBD_StatusTypeDef USBD_StdEPReq (USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req) +{ + + uint8_t ep_addr; + USBD_StatusTypeDef ret = USBD_OK; + USBD_EndpointTypeDef *pep; + ep_addr = LOBYTE(req->wIndex); + + /* Check if it is a class request */ + if ((req->bmRequest & 0x60) == 0x20) + { + pdev->pClass->Setup (pdev, req); + + return USBD_OK; + } + + switch (req->bRequest) + { + + case USB_REQ_SET_FEATURE : + + switch (pdev->dev_state) + { + case USBD_STATE_ADDRESSED: + if ((ep_addr != 0x00) && (ep_addr != 0x80)) + { + USBD_LL_StallEP(pdev , ep_addr); + } + break; + + case USBD_STATE_CONFIGURED: + if (req->wValue == USB_FEATURE_EP_HALT) + { + if ((ep_addr != 0x00) && (ep_addr != 0x80)) + { + USBD_LL_StallEP(pdev , ep_addr); + + } + } + pdev->pClass->Setup (pdev, req); + USBD_CtlSendStatus(pdev); + + break; + + default: + USBD_CtlError(pdev , req); + break; + } + break; + + case USB_REQ_CLEAR_FEATURE : + + switch (pdev->dev_state) + { + case USBD_STATE_ADDRESSED: + if ((ep_addr != 0x00) && (ep_addr != 0x80)) + { + USBD_LL_StallEP(pdev , ep_addr); + } + break; + + case USBD_STATE_CONFIGURED: + if (req->wValue == USB_FEATURE_EP_HALT) + { + if ((ep_addr & 0x7F) != 0x00) + { + USBD_LL_ClearStallEP(pdev , ep_addr); + pdev->pClass->Setup (pdev, req); + } + USBD_CtlSendStatus(pdev); + } + break; + + default: + USBD_CtlError(pdev , req); + break; + } + break; + + case USB_REQ_GET_STATUS: + switch (pdev->dev_state) + { + case USBD_STATE_ADDRESSED: + if ((ep_addr & 0x7F) != 0x00) + { + USBD_LL_StallEP(pdev , ep_addr); + } + break; + + case USBD_STATE_CONFIGURED: + pep = ((ep_addr & 0x80) == 0x80) ? &pdev->ep_in[ep_addr & 0x7F]:\ + &pdev->ep_out[ep_addr & 0x7F]; + if(USBD_LL_IsStallEP(pdev, ep_addr)) + { + pep->status = 0x0001; + } + else + { + pep->status = 0x0000; + } + + USBD_CtlSendData (pdev, + (uint8_t *)&pep->status, + 2); + break; + + default: + USBD_CtlError(pdev , req); + break; + } + break; + + default: + break; + } + return ret; +} +/** +* @brief USBD_GetDescriptor +* Handle Get Descriptor requests +* @param pdev: device instance +* @param req: usb request +* @retval status +*/ +static void USBD_GetDescriptor(USBD_HandleTypeDef *pdev , + USBD_SetupReqTypedef *req) +{ + uint16_t len; + uint8_t *pbuf; + + + switch (req->wValue >> 8) + { +#if (USBD_LPM_ENABLED == 1) + case USB_DESC_TYPE_BOS: + pbuf = pdev->pDesc->GetBOSDescriptor(pdev->dev_speed, &len); + break; +#endif + case USB_DESC_TYPE_DEVICE: + pbuf = pdev->pDesc->GetDeviceDescriptor(pdev->dev_speed, &len); + break; + + case USB_DESC_TYPE_CONFIGURATION: + if(pdev->dev_speed == USBD_SPEED_HIGH ) + { + pbuf = (uint8_t *)pdev->pClass->GetHSConfigDescriptor(&len); + pbuf[1] = USB_DESC_TYPE_CONFIGURATION; + } + else + { + pbuf = (uint8_t *)pdev->pClass->GetFSConfigDescriptor(&len); + pbuf[1] = USB_DESC_TYPE_CONFIGURATION; + } + break; + + case USB_DESC_TYPE_STRING: + switch ((uint8_t)(req->wValue)) + { + case USBD_IDX_LANGID_STR: + pbuf = pdev->pDesc->GetLangIDStrDescriptor(pdev->dev_speed, &len); + break; + + case USBD_IDX_MFC_STR: + pbuf = pdev->pDesc->GetManufacturerStrDescriptor(pdev->dev_speed, &len); + break; + + case USBD_IDX_PRODUCT_STR: + pbuf = pdev->pDesc->GetProductStrDescriptor(pdev->dev_speed, &len); + break; + + case USBD_IDX_SERIAL_STR: + pbuf = pdev->pDesc->GetSerialStrDescriptor(pdev->dev_speed, &len); + break; + + case USBD_IDX_CONFIG_STR: + pbuf = pdev->pDesc->GetConfigurationStrDescriptor(pdev->dev_speed, &len); + break; + + case USBD_IDX_INTERFACE_STR: + pbuf = pdev->pDesc->GetInterfaceStrDescriptor(pdev->dev_speed, &len); + break; + + default: +#if (USBD_SUPPORT_USER_STRING == 1) + pbuf = pdev->pClass->GetUsrStrDescriptor(pdev, (req->wValue) , &len); + break; +#else + USBD_CtlError(pdev , req); + return; +#endif + } + break; + case USB_DESC_TYPE_DEVICE_QUALIFIER: + + if(pdev->dev_speed == USBD_SPEED_HIGH ) + { + pbuf = (uint8_t *)pdev->pClass->GetDeviceQualifierDescriptor(&len); + break; + } + else + { + USBD_CtlError(pdev , req); + return; + } + + case USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION: + if(pdev->dev_speed == USBD_SPEED_HIGH ) + { + pbuf = (uint8_t *)pdev->pClass->GetOtherSpeedConfigDescriptor(&len); + pbuf[1] = USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION; + break; + } + else + { + USBD_CtlError(pdev , req); + return; + } + + default: + USBD_CtlError(pdev , req); + return; + } + + if((len != 0)&& (req->wLength != 0)) + { + + len = MIN(len , req->wLength); + + USBD_CtlSendData (pdev, + pbuf, + len); + } + +} + +/** +* @brief USBD_SetAddress +* Set device address +* @param pdev: device instance +* @param req: usb request +* @retval status +*/ +static void USBD_SetAddress(USBD_HandleTypeDef *pdev , + USBD_SetupReqTypedef *req) +{ + uint8_t dev_addr; + + if ((req->wIndex == 0) && (req->wLength == 0)) + { + dev_addr = (uint8_t)(req->wValue) & 0x7F; + + if (pdev->dev_state == USBD_STATE_CONFIGURED) + { + USBD_CtlError(pdev , req); + } + else + { + pdev->dev_address = dev_addr; + USBD_LL_SetUSBAddress(pdev, dev_addr); + USBD_CtlSendStatus(pdev); + + if (dev_addr != 0) + { + pdev->dev_state = USBD_STATE_ADDRESSED; + } + else + { + pdev->dev_state = USBD_STATE_DEFAULT; + } + } + } + else + { + USBD_CtlError(pdev , req); + } +} + +/** +* @brief USBD_SetConfig +* Handle Set device configuration request +* @param pdev: device instance +* @param req: usb request +* @retval status +*/ +static void USBD_SetConfig(USBD_HandleTypeDef *pdev , + USBD_SetupReqTypedef *req) +{ + + static uint8_t cfgidx; + + cfgidx = (uint8_t)(req->wValue); + + if (cfgidx > USBD_MAX_NUM_CONFIGURATION ) + { + USBD_CtlError(pdev , req); + } + else + { + switch (pdev->dev_state) + { + case USBD_STATE_ADDRESSED: + if (cfgidx) + { + pdev->dev_config = cfgidx; + pdev->dev_state = USBD_STATE_CONFIGURED; + if(USBD_SetClassConfig(pdev , cfgidx) == USBD_FAIL) + { + USBD_CtlError(pdev , req); + return; + } + USBD_CtlSendStatus(pdev); + } + else + { + USBD_CtlSendStatus(pdev); + } + break; + + case USBD_STATE_CONFIGURED: + if (cfgidx == 0) + { + pdev->dev_state = USBD_STATE_ADDRESSED; + pdev->dev_config = cfgidx; + USBD_ClrClassConfig(pdev , cfgidx); + USBD_CtlSendStatus(pdev); + + } + else if (cfgidx != pdev->dev_config) + { + /* Clear old configuration */ + USBD_ClrClassConfig(pdev , pdev->dev_config); + + /* set new configuration */ + pdev->dev_config = cfgidx; + if(USBD_SetClassConfig(pdev , cfgidx) == USBD_FAIL) + { + USBD_CtlError(pdev , req); + return; + } + USBD_CtlSendStatus(pdev); + } + else + { + USBD_CtlSendStatus(pdev); + } + break; + + default: + USBD_CtlError(pdev , req); + break; + } + } +} + +/** +* @brief USBD_GetConfig +* Handle Get device configuration request +* @param pdev: device instance +* @param req: usb request +* @retval status +*/ +static void USBD_GetConfig(USBD_HandleTypeDef *pdev , + USBD_SetupReqTypedef *req) +{ + + if (req->wLength != 1) + { + USBD_CtlError(pdev , req); + } + else + { + switch (pdev->dev_state ) + { + case USBD_STATE_ADDRESSED: + pdev->dev_default_config = 0; + USBD_CtlSendData (pdev, + (uint8_t *)&pdev->dev_default_config, + 1); + break; + + case USBD_STATE_CONFIGURED: + + USBD_CtlSendData (pdev, + (uint8_t *)&pdev->dev_config, + 1); + break; + + default: + USBD_CtlError(pdev , req); + break; + } + } +} + +/** +* @brief USBD_GetStatus +* Handle Get Status request +* @param pdev: device instance +* @param req: usb request +* @retval status +*/ +static void USBD_GetStatus(USBD_HandleTypeDef *pdev , + USBD_SetupReqTypedef *req) +{ + + + switch (pdev->dev_state) + { + case USBD_STATE_ADDRESSED: + case USBD_STATE_CONFIGURED: + +#if ( USBD_SELF_POWERED == 1) + pdev->dev_config_status = USB_CONFIG_SELF_POWERED; +#else + pdev->dev_config_status = 0; +#endif + + if (pdev->dev_remote_wakeup) + { + pdev->dev_config_status |= USB_CONFIG_REMOTE_WAKEUP; + } + + USBD_CtlSendData (pdev, + (uint8_t *)& pdev->dev_config_status, + 2); + break; + + default : + USBD_CtlError(pdev , req); + break; + } +} + + +/** +* @brief USBD_SetFeature +* Handle Set device feature request +* @param pdev: device instance +* @param req: usb request +* @retval status +*/ +static void USBD_SetFeature(USBD_HandleTypeDef *pdev , + USBD_SetupReqTypedef *req) +{ + + if (req->wValue == USB_FEATURE_REMOTE_WAKEUP) + { + pdev->dev_remote_wakeup = 1; + pdev->pClass->Setup (pdev, req); + USBD_CtlSendStatus(pdev); + } + +} + + +/** +* @brief USBD_ClrFeature +* Handle clear device feature request +* @param pdev: device instance +* @param req: usb request +* @retval status +*/ +static void USBD_ClrFeature(USBD_HandleTypeDef *pdev , + USBD_SetupReqTypedef *req) +{ + switch (pdev->dev_state) + { + case USBD_STATE_ADDRESSED: + case USBD_STATE_CONFIGURED: + if (req->wValue == USB_FEATURE_REMOTE_WAKEUP) + { + pdev->dev_remote_wakeup = 0; + pdev->pClass->Setup (pdev, req); + USBD_CtlSendStatus(pdev); + } + break; + + default : + USBD_CtlError(pdev , req); + break; + } +} + +/** +* @brief USBD_ParseSetupRequest +* Copy buffer into setup structure +* @param pdev: device instance +* @param req: usb request +* @retval None +*/ + +void USBD_ParseSetupRequest(USBD_SetupReqTypedef *req, uint8_t *pdata) +{ + req->bmRequest = *(uint8_t *) (pdata); + req->bRequest = *(uint8_t *) (pdata + 1); + req->wValue = SWAPBYTE (pdata + 2); + req->wIndex = SWAPBYTE (pdata + 4); + req->wLength = SWAPBYTE (pdata + 6); + +} + +/** +* @brief USBD_CtlError +* Handle USB low level Error +* @param pdev: device instance +* @param req: usb request +* @retval None +*/ + +void USBD_CtlError( USBD_HandleTypeDef *pdev , + USBD_SetupReqTypedef *req) +{ + USBD_LL_StallEP(pdev , 0x80); + USBD_LL_StallEP(pdev , 0); +} + + +/** + * @brief USBD_GetString + * Convert Ascii string into unicode one + * @param desc : descriptor buffer + * @param unicode : Formatted string buffer (unicode) + * @param len : descriptor length + * @retval None + */ +void USBD_GetString(uint8_t *desc, uint8_t *unicode, uint16_t *len) +{ + uint8_t idx = 0; + + if (desc != NULL) + { + *len = USBD_GetLen(desc) * 2 + 2; + unicode[idx++] = *len; + unicode[idx++] = USB_DESC_TYPE_STRING; + + while (*desc != '\0') + { + unicode[idx++] = *desc++; + unicode[idx++] = 0x00; + } + } +} + +/** + * @brief USBD_GetLen + * return the string length + * @param buf : pointer to the ascii string buffer + * @retval string length + */ +static uint8_t USBD_GetLen(uint8_t *buf) +{ + uint8_t len = 0; + + while (*buf != '\0') + { + len++; + buf++; + } + + return len; +} +/** + * @} + */ + + +/** + * @} + */ + + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c new file mode 100644 index 0000000..e1b9c75 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c @@ -0,0 +1,236 @@ +/** + ****************************************************************************** + * @file usbd_ioreq.c + * @author MCD Application Team + * @version V2.4.2 + * @date 11-December-2015 + * @brief This file provides the IO requests APIs for control endpoints. + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT 2015 STMicroelectronics

    + * + * Licensed under MCD-ST Liberty SW License Agreement V2, (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.st.com/software_license_agreement_liberty_v2 + * + * 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_ioreq.h" + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + + +/** @defgroup USBD_IOREQ + * @brief control I/O requests module + * @{ + */ + +/** @defgroup USBD_IOREQ_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_IOREQ_Private_Defines + * @{ + */ + +/** + * @} + */ + + +/** @defgroup USBD_IOREQ_Private_Macros + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_IOREQ_Private_Variables + * @{ + */ + +/** + * @} + */ + + +/** @defgroup USBD_IOREQ_Private_FunctionPrototypes + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBD_IOREQ_Private_Functions + * @{ + */ + +/** +* @brief USBD_CtlSendData +* send data on the ctl pipe +* @param pdev: device instance +* @param buff: pointer to data buffer +* @param len: length of data to be sent +* @retval status +*/ +USBD_StatusTypeDef USBD_CtlSendData (USBD_HandleTypeDef *pdev, + uint8_t *pbuf, + uint16_t len) +{ + /* Set EP0 State */ + pdev->ep0_state = USBD_EP0_DATA_IN; + pdev->ep_in[0].total_length = len; + pdev->ep_in[0].rem_length = len; + /* Start the transfer */ + USBD_LL_Transmit (pdev, 0x00, pbuf, len); + + return USBD_OK; +} + +/** +* @brief USBD_CtlContinueSendData +* continue sending data on the ctl pipe +* @param pdev: device instance +* @param buff: pointer to data buffer +* @param len: length of data to be sent +* @retval status +*/ +USBD_StatusTypeDef USBD_CtlContinueSendData (USBD_HandleTypeDef *pdev, + uint8_t *pbuf, + uint16_t len) +{ + /* Start the next transfer */ + USBD_LL_Transmit (pdev, 0x00, pbuf, len); + + return USBD_OK; +} + +/** +* @brief USBD_CtlPrepareRx +* receive data on the ctl pipe +* @param pdev: device instance +* @param buff: pointer to data buffer +* @param len: length of data to be received +* @retval status +*/ +USBD_StatusTypeDef USBD_CtlPrepareRx (USBD_HandleTypeDef *pdev, + uint8_t *pbuf, + uint16_t len) +{ + /* Set EP0 State */ + pdev->ep0_state = USBD_EP0_DATA_OUT; + pdev->ep_out[0].total_length = len; + pdev->ep_out[0].rem_length = len; + /* Start the transfer */ + USBD_LL_PrepareReceive (pdev, + 0, + pbuf, + len); + + return USBD_OK; +} + +/** +* @brief USBD_CtlContinueRx +* continue receive data on the ctl pipe +* @param pdev: device instance +* @param buff: pointer to data buffer +* @param len: length of data to be received +* @retval status +*/ +USBD_StatusTypeDef USBD_CtlContinueRx (USBD_HandleTypeDef *pdev, + uint8_t *pbuf, + uint16_t len) +{ + + USBD_LL_PrepareReceive (pdev, + 0, + pbuf, + len); + return USBD_OK; +} +/** +* @brief USBD_CtlSendStatus +* send zero lzngth packet on the ctl pipe +* @param pdev: device instance +* @retval status +*/ +USBD_StatusTypeDef USBD_CtlSendStatus (USBD_HandleTypeDef *pdev) +{ + + /* Set EP0 State */ + pdev->ep0_state = USBD_EP0_STATUS_IN; + + /* Start the transfer */ + USBD_LL_Transmit (pdev, 0x00, NULL, 0); + + return USBD_OK; +} + +/** +* @brief USBD_CtlReceiveStatus +* receive zero lzngth packet on the ctl pipe +* @param pdev: device instance +* @retval status +*/ +USBD_StatusTypeDef USBD_CtlReceiveStatus (USBD_HandleTypeDef *pdev) +{ + /* Set EP0 State */ + pdev->ep0_state = USBD_EP0_STATUS_OUT; + + /* Start the transfer */ + USBD_LL_PrepareReceive ( pdev, + 0, + NULL, + 0); + + return USBD_OK; +} + + +/** +* @brief USBD_GetRxCount +* returns the received data length +* @param pdev: device instance +* @param ep_addr: endpoint address +* @retval Rx Data blength +*/ +uint16_t USBD_GetRxCount (USBD_HandleTypeDef *pdev , uint8_t ep_addr) +{ + return USBD_LL_GetRxDataSize(pdev, ep_addr); +} + +/** + * @} + */ + + +/** + * @} + */ + + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Nucleo-L4A6RG.elf.launch b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Nucleo-L4A6RG.elf.launch new file mode 100644 index 0000000..8f4f1ae --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Nucleo-L4A6RG.elf.launch @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Nucleo-L4A6RG.ioc b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Nucleo-L4A6RG.ioc new file mode 100644 index 0000000..482a7ac --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Nucleo-L4A6RG.ioc @@ -0,0 +1,192 @@ +#MicroXplorer Configuration settings - do not modify +File.Version=6 +KeepUserPlacement=false +Mcu.Family=STM32L4 +Mcu.IP0=NVIC +Mcu.IP1=RCC +Mcu.IP2=RNG +Mcu.IP3=RTC +Mcu.IP4=SYS +Mcu.IP5=USART2 +Mcu.IP6=USB_DEVICE +Mcu.IP7=USB_OTG_FS +Mcu.IPNb=8 +Mcu.Name=STM32L4A6RGTx +Mcu.Package=LQFP64 +Mcu.Pin0=PC13 +Mcu.Pin1=PC14-OSC32_IN (PC14) +Mcu.Pin10=PB3 (JTDO/TRACESWO) +Mcu.Pin11=VP_RNG_VS_RNG +Mcu.Pin12=VP_RTC_VS_RTC_Activate +Mcu.Pin13=VP_RTC_VS_RTC_Calendar +Mcu.Pin14=VP_SYS_VS_Systick +Mcu.Pin15=VP_USB_DEVICE_VS_USB_DEVICE_CDC_FS +Mcu.Pin2=PC15-OSC32_OUT (PC15) +Mcu.Pin3=PA2 +Mcu.Pin4=PA3 +Mcu.Pin5=PA5 +Mcu.Pin6=PA11 +Mcu.Pin7=PA12 +Mcu.Pin8=PA13 (JTMS/SWDIO) +Mcu.Pin9=PA14 (JTCK/SWCLK) +Mcu.PinsNb=16 +Mcu.ThirdPartyNb=0 +Mcu.UserConstants= +Mcu.UserName=STM32L4A6RGTx +MxCube.Version=4.25.0 +MxDb.Version=DB.4.0.250 +NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false +NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false +NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false +NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false +NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false +NVIC.OTG_FS_IRQn=true\:0\:0\:false\:false\:true\:false +NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false +NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4 +NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false +NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false +NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false +PA11.Mode=Device_Only +PA11.Signal=USB_OTG_FS_DM +PA12.Mode=Device_Only +PA12.Signal=USB_OTG_FS_DP +PA13\ (JTMS/SWDIO).Mode=Trace_Asynchronous_SW +PA13\ (JTMS/SWDIO).Signal=SYS_JTMS-SWDIO +PA14\ (JTCK/SWCLK).Mode=Trace_Asynchronous_SW +PA14\ (JTCK/SWCLK).Signal=SYS_JTCK-SWCLK +PA2.Mode=Asynchronous +PA2.Signal=USART2_TX +PA3.Mode=Asynchronous +PA3.Signal=USART2_RX +PA5.GPIOParameters=GPIO_Label +PA5.GPIO_Label=LD2 [green Led] +PA5.Locked=true +PA5.Signal=GPIO_Output +PB3\ (JTDO/TRACESWO).Mode=Trace_Asynchronous_SW +PB3\ (JTDO/TRACESWO).Signal=SYS_JTDO-SWO +PC13.GPIOParameters=GPIO_Label +PC13.GPIO_Label=B1 [Blue PushButton] +PC13.Locked=true +PC13.Signal=GPXTI13 +PC14-OSC32_IN\ (PC14).Mode=LSE-External-Oscillator +PC14-OSC32_IN\ (PC14).Signal=RCC_OSC32_IN +PC15-OSC32_OUT\ (PC15).Mode=LSE-External-Oscillator +PC15-OSC32_OUT\ (PC15).Signal=RCC_OSC32_OUT +PCC.Checker=true +PCC.Line=STM32L4x6 +PCC.MCU=STM32L4A6RGTx +PCC.PartNumber=STM32L4A6RGTx +PCC.Seq0=0 +PCC.Series=STM32L4 +PCC.Temperature=25 +PCC.Vdd=null +PinOutPanel.RotationAngle=0 +ProjectManager.AskForMigrate=true +ProjectManager.BackupPrevious=false +ProjectManager.CompilerOptimize=3 +ProjectManager.ComputerToolchain=false +ProjectManager.CoupleFile=false +ProjectManager.CustomerFirmwarePackage=C\:/Users/Stefanth/STM32Cube/Repository/STM32Cube_FW_L4_V1.11.0 +ProjectManager.DefaultFWLocation=true +ProjectManager.DeletePrevious=true +ProjectManager.DeviceId=STM32L4A6RGTx +ProjectManager.FirmwarePackage=STM32Cube FW_L4 V1.11.0 +ProjectManager.FreePins=false +ProjectManager.HalAssertFull=false +ProjectManager.HeapSize=0x200 +ProjectManager.KeepUserCode=true +ProjectManager.LastFirmware=true +ProjectManager.LibraryCopy=1 +ProjectManager.MainLocation=Src +ProjectManager.PreviousToolchain=TrueSTUDIO +ProjectManager.ProjectBuild=false +ProjectManager.ProjectFileName=Nucleo-L4A6RG.ioc +ProjectManager.ProjectName=Nucleo-L4A6RG +ProjectManager.StackSize=0x10000 +ProjectManager.TargetToolchain=TrueSTUDIO +ProjectManager.ToolChainLocation= +ProjectManager.UnderRoot=true +ProjectManager.functionlistsort=1-MX_GPIO_Init-GPIO-false-HAL-true,2-SystemClock_Config-RCC-false-HAL-false,3-MX_USART2_UART_Init-USART2-false-HAL-true,4-MX_RTC_Init-RTC-false-HAL-true,5-MX_USB_DEVICE_Init-USB_DEVICE-false-HAL-true,6-MX_RNG_Init-RNG-false-HAL-true +RCC.ADCFreq_Value=64000000 +RCC.AHBFreq_Value=80000000 +RCC.APB1Freq_Value=80000000 +RCC.APB1TimFreq_Value=80000000 +RCC.APB2Freq_Value=80000000 +RCC.APB2TimFreq_Value=80000000 +RCC.CK48CLockSelection=RCC_USBCLKSOURCE_HSI48 +RCC.CortexFreq_Value=80000000 +RCC.DFSDMFreq_Value=80000000 +RCC.FCLKCortexFreq_Value=80000000 +RCC.FamilyName=M +RCC.HCLKFreq_Value=80000000 +RCC.HSE_VALUE=8000000 +RCC.HSI48_VALUE=48000000 +RCC.HSI_VALUE=16000000 +RCC.I2C1Freq_Value=80000000 +RCC.I2C2Freq_Value=80000000 +RCC.I2C3Freq_Value=80000000 +RCC.I2C4Freq_Value=80000000 +RCC.IPParameters=ADCFreq_Value,AHBFreq_Value,APB1Freq_Value,APB1TimFreq_Value,APB2Freq_Value,APB2TimFreq_Value,CK48CLockSelection,CortexFreq_Value,DFSDMFreq_Value,FCLKCortexFreq_Value,FamilyName,HCLKFreq_Value,HSE_VALUE,HSI48_VALUE,HSI_VALUE,I2C1Freq_Value,I2C2Freq_Value,I2C3Freq_Value,I2C4Freq_Value,LCDFreq_Value,LPTIM1Freq_Value,LPTIM2Freq_Value,LPUART1Freq_Value,LSCOPinFreq_Value,LSI_VALUE,MCO1PinFreq_Value,MSI_VALUE,PLLN,PLLPoutputFreq_Value,PLLQoutputFreq_Value,PLLRCLKFreq_Value,PLLSAI1PoutputFreq_Value,PLLSAI1QoutputFreq_Value,PLLSAI1RoutputFreq_Value,PLLSAI2PoutputFreq_Value,PLLSAI2RoutputFreq_Value,PLLSourceVirtual,PWRFreq_Value,RNGFreq_Value,RTCClockSelection,RTCFreq_Value,SAI1Freq_Value,SAI2Freq_Value,SDMMCFreq_Value,SWPMI1Freq_Value,SYSCLKFreq_VALUE,SYSCLKSource,UART4Freq_Value,UART5Freq_Value,USART1Freq_Value,USART2Freq_Value,USART3Freq_Value,USBFreq_Value,VCOInputFreq_Value,VCOOutputFreq_Value,VCOSAI1OutputFreq_Value,VCOSAI2OutputFreq_Value +RCC.LCDFreq_Value=32768 +RCC.LPTIM1Freq_Value=80000000 +RCC.LPTIM2Freq_Value=80000000 +RCC.LPUART1Freq_Value=80000000 +RCC.LSCOPinFreq_Value=32000 +RCC.LSI_VALUE=32000 +RCC.MCO1PinFreq_Value=80000000 +RCC.MSI_VALUE=4000000 +RCC.PLLN=10 +RCC.PLLPoutputFreq_Value=80000000 +RCC.PLLQoutputFreq_Value=80000000 +RCC.PLLRCLKFreq_Value=80000000 +RCC.PLLSAI1PoutputFreq_Value=64000000 +RCC.PLLSAI1QoutputFreq_Value=64000000 +RCC.PLLSAI1RoutputFreq_Value=64000000 +RCC.PLLSAI2PoutputFreq_Value=64000000 +RCC.PLLSAI2RoutputFreq_Value=64000000 +RCC.PLLSourceVirtual=RCC_PLLSOURCE_HSI +RCC.PWRFreq_Value=80000000 +RCC.RNGFreq_Value=48000000 +RCC.RTCClockSelection=RCC_RTCCLKSOURCE_LSE +RCC.RTCFreq_Value=32768 +RCC.SAI1Freq_Value=64000000 +RCC.SAI2Freq_Value=64000000 +RCC.SDMMCFreq_Value=48000000 +RCC.SWPMI1Freq_Value=80000000 +RCC.SYSCLKFreq_VALUE=80000000 +RCC.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK +RCC.UART4Freq_Value=80000000 +RCC.UART5Freq_Value=80000000 +RCC.USART1Freq_Value=80000000 +RCC.USART2Freq_Value=80000000 +RCC.USART3Freq_Value=80000000 +RCC.USBFreq_Value=48000000 +RCC.VCOInputFreq_Value=16000000 +RCC.VCOOutputFreq_Value=160000000 +RCC.VCOSAI1OutputFreq_Value=128000000 +RCC.VCOSAI2OutputFreq_Value=128000000 +RTC.Format=RTC_FORMAT_BIN +RTC.IPParameters=Format +SH.GPXTI13.0=GPIO_EXTI13 +SH.GPXTI13.ConfNb=1 +USART2.IPParameters=VirtualMode-Asynchronous,Mode,WordLength +USART2.Mode=MODE_TX +USART2.VirtualMode-Asynchronous=VM_ASYNC +USART2.WordLength=WORDLENGTH_8B +USB_DEVICE.CLASS_NAME_FS=CDC +USB_DEVICE.IPParameters=VirtualMode,VirtualModeFS,CLASS_NAME_FS +USB_DEVICE.VirtualMode=Cdc +USB_DEVICE.VirtualModeFS=Cdc_FS +USB_OTG_FS.IPParameters=VirtualMode +USB_OTG_FS.VirtualMode=Device_Only +VP_RNG_VS_RNG.Mode=RNG_Activate +VP_RNG_VS_RNG.Signal=RNG_VS_RNG +VP_RTC_VS_RTC_Activate.Mode=RTC_Enabled +VP_RTC_VS_RTC_Activate.Signal=RTC_VS_RTC_Activate +VP_RTC_VS_RTC_Calendar.Mode=RTC_Calendar +VP_RTC_VS_RTC_Calendar.Signal=RTC_VS_RTC_Calendar +VP_SYS_VS_Systick.Mode=SysTick +VP_SYS_VS_Systick.Signal=SYS_VS_Systick +VP_USB_DEVICE_VS_USB_DEVICE_CDC_FS.Mode=CDC_FS +VP_USB_DEVICE_VS_USB_DEVICE_CDC_FS.Signal=USB_DEVICE_VS_USB_DEVICE_CDC_FS +board=Nucleo-L4A6RG diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Nucleo-L4A6RG.pdf b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Nucleo-L4A6RG.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b4e6fcaef4e7bbc9f6998d5ae7af7394050ad881 GIT binary patch literal 253594 zcmeFYbyOYOmM>fc4ess|2<}dR5Ind$!GgOJJh(%E;10oq2Pe1$x8QEUH%^eRl5_9v zdrtTL#(VvG^yoi&?@_RKRjpOOxu(y#HjUyd2_`mXPDGmZjnPR&PI6XqJ0nYSK|vM? z3u|XnM-~a|H_oQ7OpWbKOj%x=+P-x*C+Ff}d-1}_+0pck4WfH`hMJsH8Y_0o8N>3p zkRJ^N%=rv&6pL$b)!ysM?j*eld`zR5v$N7lig!|^$)~GOhYQ}NMI`Q5th$0QkcLbz z3&L0EG%%eXL|^7?FH2-Qp@m&U1QSF7MNiSK4PoOrU5!#DKBbxUaH0g+rs7y#uI64; zEj(i_%cWLT!xx_s6{mCc`fQ}l{YE~OWRi3H1+GA$#gsRrYuQ|L!c3QK`eMRWg$xx8 zqkkS=7-LwPMjm<6hM5qz-{zueaQva*%Xq)SRpSdz?+(AGCSG>cgJ{HUrYy@aL%u86 zlv>+JO)cH!*72AgAtF}qBVjxD6i-iEytfkDvxUEVqLwy!t}P@?aAVWpKjS2i${8r5 zzv@}j-6_hYe>1#NGH>rpGEpwaXPGHo){M1fS&7cJ6!={}yFO@jOuJ==Y@x|LL2lkq z2kFAI&NUdCir?a}#9&1*tuajH!eKtEX}inVXVWsRWCY!%4uhPtir%@fOhI1llJi|0 zS3^`YeWjZ#7PbqF#JssGU89llh%B>w=JBd>`olXi_cvei)*;mcNfap=SvL@#(6Lug zgoKv)n(jSgt*jjOaj~e=TTg;i(&e9a4t(~aqFBy~j`U|z$w0sxjdZPn?h6rSP7XD2>-5ySC@SH@8qM%R5>wg|lj~!MBIV-TFJO0vdxE zU$FjI1p%E5-DuxieY6C>&gk%=_ro1{8a{)z{kNm9-_<-o5x<9(L^QQE`I{7hpFpWY zWdB3@K;aX!vvoGLb#@~EC6LN2svh>HEQ)X5nzAUHI@!568k;(SHz_*W8LOB&lk2d6 zLQKx0YU=Jx&LV9C-uCiu|Hc0HUs{hv0-W)eRI`z@{hm^Sot)#>hZo=roZ1n58adbR zD{`hL7H?kKx$CfkU%B|W$ay*0^6C*n<`BOBTG|bXBG_$6Hv8&-S^VM z*-6pVQOwT9-p=+HEZ)B>9w#ps2j@Rj@A3QNDu6B{AuRzwJplkH@C`gJ0Ac_F92`6x zECM_{{L`lhh{)I|$Vf=Y1ejQ8*d&Bxq$GsI#N^b>wB(eGRK&z|JkJ?f**G~l$!Ph6 zc-aM+IXKyWO#=1w=~HARWPB79e0B>Sfhe9Ody7Y7QgEfTxJKc=!Z_G|y=1p3`%3ar5x<@r%6@mync_mQhhv zQ`gYc(l$0RHG6ArVd>=T;_Bw^;TiZoC^#fEEIdBpLt;|$$CT9Ey!?W~qEE#o)it$s z^$lMdn>xF?dwTo&2L>l5r>19Szt7FDt#52@ZSU;v{Wyi3onKsDUEkdPq6-Ru{(~&= z?;nKyg)R(`t|u@s&@k}7=z@CU1|HBDFt8MCaG0V>@NXQjDB1lHuwTaIRDFF)#i4wH zW8^rFh)d16Msxa$wBMBdpAi=DpQ7v^g#8;`^8hk56v#Yi3_uvTx~0qYL;T<4f7jrD zW#E5h;J;D^=#$DFtJL1~Sy-xHvYT^gsAe7Y=vfJC8wA@UT4~E7Z+L zgwS)Av9o`|Z``zR6}MJ*Z5d3Z8RF{MYC0r{A6z)Z^pER^F+LgEydV}oUGjwB4&CJnW|58 zBpmS_-fNLN=|)w|<#o=dcp<1YrJBQp%l%_Cg&$Axk`E@4IXI8~KR5m?O6(Q4bq^S* zLqXl1X3G8IhN#ZRti5Q$O7T9ttbZt~!+#1jLy}^xTz*LLl#|uKz_MXJFG{Yz9red$LAtJr&2=F=olNtL9o4Rn=G3n4NcAD;)Lz>~b_6#VI(=b}8A(S6O z9q-bkQ}(8;)#Q|Q5S*Kfxg`8F5f%=~%=?mSh=WIAycFR{3b@|uKdVcr-K$WS9XMce zVQAj@lEO?Sjhv?RRWmkplOU?G16I-&(kP7jgWu%#{k&(%%edhk3-0Q@32pp0=(#*e z)KTnWoQ(|WjD9B2;rnzzZuozAKvQ-1uKa{EKe8^fGftH<#J%bcHE~N+5_>~-{n2}4eqqQs5}>s99&xEOrFQWev+8FELIjVZzVbJPttTfB;FX<>Ls z9c-t5+qpP zCm(@${1$r1qQ2x?LVc}>5gk@3`!hZ@jp7?G(wMHD?&Jf=}c+XUr86be`uB}Y3FBPwdpoSly{i? z)Kin77t!rX+l_9KWA-+Ba$t(u@x8=1DFq6(d#%{Oi~(Ay|^8_%7u1-TegGrE)N zJJ-J>eH;vg33l&xjDG}}F)ph{B(P6B)wvTseYfI&$h2*-%CT&~ErV!l?KM*|QAB-c zM&p(+!pQRXW0!`921r`5l|*3wCm+VwsS}VZ3H0xxFtaaz%)G)1P~sjXB0xY5ss{{g z*D}8B@Cx9-ZXLG1XW;slscXY%9~j^W;eAEySwnYc4h?&BaZd`FkkdYU-85nuevu-6jw1hAA1_nzHsZg}Ids^cBmibowDjB$NP`ihHWAJ6H8Q7aYM%LyZZ z@pH7P2ym(Wm+Vbg*TI|OL<*%8_Yjk0^eTe5vhz26@h*c>&Iwix5P=V{$~-y0CApq3 zZXj%46mw&Oj53w-%X0M5Hw&KT_ytf~TU(pZk#NuKL>R@}p-EBI==A7Bcs%p#c(#H# z62*)j_~igu1ey<;c)iA&`QoOI0qKf|viI`RoN!RqFaq|AG$CK;Jhg-|;S-Y3`<*2f zKY)M!zcR}EKb?z#LH!gpBX?0}VVS5fb&X^_dVa(zm_A4hlS+d8$^Jl}lIkO{#x>!) zv!e3|e8o9_1PF_r!pA@J6Eb8P5bpMB8oNwWoE1nZ?MyJQ%N>2i#x)O!tbrOJvE&u> z$XU|qbFfYA{ygZv5if*!nm831fDi$Lu^jC_e}zQCgfr^fX_fy7jJ7pA0s#yw4_r!Q zWY_NKnKq9=s@_;9XLBC?2hF+aO#M|Ll_Q?jEmE-vuLim>x3ThCfm8VC$0Kk}-SP-* zs8(Gci+ZfRuP-2yqkkF2o#;Yn=ZctJBLNJd^HG&6lF;A`iJc;K&7w;RqLj!Yhm%mt z5uPS~_ys3c(lg-!YZ&ckQ~SeH7UAn@z`0g~^#%F0^C6PZPbt00K|SW(endv=IZ@KT z!9Z4NUlSaA1e!}9fz|l4M<7ZOURK=6;r|zeI9fLgnyx7E33o9gJDqbJr&X`IGCKk# zvna_fbn(9@Y5WwvtH@mIc>d*4rt+Sfgou){*&xCd05hH*7x=}(=mVE5S@bzxCcdntQtd=O-K2$vQsI?h2@Ab1$q)`O97u4$Nkv5QKj}(vDO;`^P@~+ z6q}t55v%u-U!i*iZcR8UEhRkf6~?NX8`rhFV-iLHrQ%}e0r9B)dPy^6T{xJTQZnEO zVslIh6Cu~=Hi$4}3ghMXMDvD)6~(;TPR~&)Ruml^!ls@o5~8O=?{u&1iuVJQph@9NCkPcJCSM<0XDx>D%S?X za{?F)Jo4xZ+B@1*vMU$gJ4}7w(-L6Myu$FE=*iwZuGeL3bJ2$;z42IVP(%ZSI-oe; zQX3xO7yT7LHW++uZ=5a%oOM05k>O5N4I;Fm|G~L@fFo)a36(_dD5)Jz7OGGBC4g_$ zMp@HDagWk`HnJ?=1pSq6fWR2Minx=(Nv65)()1&6BJJ@A^cLr>qlL(i)vVM8EeRG( z97X!&_6~o*I0ByL@lnCs_W;i48eEUS)9sM^C4)x*COPZQGD(r-A*ZW2E8S!XOQ2cODX z;k&gB!fa@oCMrnHb3SxYxKoFg2C4VXDtfYKX6!4M3nZml?$YIk!(l6l1OHuzlXli! z%q`1(0BEqzZ3?W_Ulct8R1Xo4fMN3^a8G0*?XivldsnaSsrOL82@u6pBXo93^~2`7 zz=rNvZu*Imo4nmQ!*2+6J+MLvz0-OG$RiAXBJQo+YN62jKLVQ~CoA^>hrZ{^)80;s z4by^LZ#>MmauU=gs~TlKQ(mI02KJK&AP5E^6blk?D!vmsSs135D3Yrc8R>X3Oh_N? z6)ytaNcq{~UXSHicmS<n?sTXC_b^ryD;JQ{tPD2(?-Etfo+6;B#2{(js)x)tI_2{nI$I!1hh4G2sIuyGI~* zroI%ubF#~7l?2l(%s3eTe8|;<+OQ;VP+wXQN?ZN5KEutP>97t-tBCFCd!=t>y&RD* zphhO+M&-?+(xbYZRk2yETG|a8oO|9|zs&_reZoiX!wEGuO96_=z)Mg(Dw4Bqsa{t!YO)6_ zBgVx_is?rG3BMoz?cglvbtd{AI-7hS61z0OAdmB>Sz~Kc@H}kqo>?qq+@86nLNpNdhcN_x;iIJQ}a&@9n34Hmv4cGTd5j=Kp5ww)h=8#)c&iwV#P zy|PH0{dYuEYvuYw4^v7MBti=SNNk9CnVYfj#gu+*7t))J6SaG$b*a+}YLjQkJxGO*3HVPMz?;WiV_r&6A@;5>}*sR>7KYe!B;n@?6fr?@bdfL{TrbHcoLa%4_J~Hv|wl zVg$R9j1pm@5xes3fPI-m-v=Q^-vb6vK=*XH@cx9cL>gMhT%EP8@HT$iaV1tl+y`@g3`UIr#@ks=dpQZEA)fRimhA*UzvDHKeU{(4`e(e?}-j zc}`_quDR%Iw%bIm;j&QlO;#U^$mbx2nN?&9%v$a;8abDQA7pS=?w!HlYn;#&aJdL8 z(brzt({`E8_{PJ1T(b9*Ca5dV2tsZz2_GwNGlOy$Kag*+?Nw@3oUBnLnKXw;VcHgo zj$LCIz$&3Ye!eF{s+0Q&^do^#D$PMQV`xj;3C7B@i&2T=3ihedsL(>w)?4w2KLWA1 zpfc)@gNj30XQXQ76=0aMsaQrrgoNJ@^Z9E(AK=KU;CVxEXSeO+t)^dAxs(}p68Io8 zzjGg?@Q@&?AExj2=kEqe!4Jqnc$?n6X!rA3*BYCkld^UW`ftpmiD&-eopiSj3#)j- zxMHp)j#-TF&+WY1))8{CJlOn-o95MNhcpKUkj{`vzwBNJ-;kXf{DfTrmt#R@Q&1A8 zyeQ1Bu%TV2w0Mp>O{S);EqIlTNmT&pt?!!JW;buI&TMzjBhXT}X+aV(SiirjCwu_W zdvWMEUC84lILSc=p42w2sL?yR&8@~^QxGNVcU9< z{V72om*C~;f;;VNsoI}uz?P`it;*>@8DB>2n;|KcWU@q`v|l>0xz55EIOyG2=($~?9W6?mR{Sn z1ZmnbYd>%4S942_1ip3If5o`prhNw1NB+qHP9GyLl@BjPXL33S6{N>Fz!h6hdPqoU zz`Zns_HdwrR5Ht&WL}8-ZWbB*a!T#@v=jTK&<`ia3m4CH2>44&u9J@NF^|lP+8Zo# z!{^y27W)Wgs;HwV4-J@bqPKc^-c&nihg~XMOVqAZc?`i{P8U*r1jZUJ-+SeCtio7l zL;GPHX4Z{Z&1!S%Gq$8cF6S5e+Z&>FoQg+bjz+O9E`t{6OM;}IWW{bNK{}f}s3s{- zEE?A8A#a z2!l6|Ky9x;Rjx7ycW>4;Y8B+CuRDYsWfm7^C)5AzWv2wM?y#RKTEcNXoHc>X`n6bI z-DnaOx2I=Fyjhr$(Ku{ub)q3gs4c?JR&lX4thGiLGzu;Os|=ZuBQYRCElFy}EXGSF zPOx%>#$I8#-zgPn|Fc&t=7RPuxDFy+kg00YlR5EV5jvxgPMWL!`HHFGIe|X@PBfgH z*ED0mgX)-p^iQZ1X4L07E@EgU~Qd3eh``YP<1L=C^$Inxp)YUa_ zjg_0fqg4|xQsa@`ywZE%X8n4zO4!+$_fXZQrRt=)>zL)^OR+-!d?|u_7k8O#82>X? zq<9g6QOog0E8H>Xn!=^~im@N{q`E5>R#7W^Rd25%zv;kJ75B2uSHG@5eMd1qzcYl9 zCL|;_!11bz%{-uAOXf2|HxG>Wa;_iK9$u>ZbT%$`Q&O6pV09-I1#Imkxy|W&*l_m5 z*!UbVY{3Qs+dstvpWI(v+vZ&!i= z8AP$-5!f%-c?g}PgBH;B!0O(r?Q(o8CraEq6UOPdbe~M5nqo|T1H-oHdY1>!2d_Lw zu7GG^w6tmOk|vQbED~9rA&MNXYR|eA3`K4n;F;;G-!z_kYPva_TtBlce&6D_kRk6* z>*}7TP|G~0rb;h`eHTI>lY}!lK$?OVQu{Ukb;2Bp{=kIl7mg6Kw#de1X+}5Pfq@-P zsB}Lt(El`+q8G2$FsV;c^%O~p6f>f>I@BB+_15=`Kf#lj6`4Ej(CM2guKe%Q1@*d-aB4}8`^^il$$id>)x`R7`(>@6KopByDQ52@DH5!Qtxxr9n?@wP?sClWs) zX64=B+q|g2`zr7-To^PLXegF!l%v=omhPv3lrVO_Yt@Hn!|Q=G8eg|r_QJOU39la>!{ zT%m`8Gu5d?0-@-#+nT*m=o<4F`KtQt;ga%*r>cTTj{wE-PYYi#$T*+xdr}^1HB?zV zoWx*EsBx|T@M+h?VnKa|e4=*uXnF}{uc?VOJ9$tSWFy&jFk4KWYmsxVI$OI zm9Zp8O;7X&^_9&T>Jo9>UYxtvYr=VHLskb zlcx!$DRL}IruSGqK%ya7t=*&L`ygXbt`@ap9z4u*!CsFIKcqhgY4xex{^eHlEmxi> zkyotJB((_&nEfW*maD6g$WMV$l}J)-HMu`Yt*Lv6`ov`S6_b~Tu{l!(c}*%!YyAAS zvwg@n#&~8W!R5&E&UPwJs2YSC0~AfkH)ct$r~5Ofq3By`$;u)N-Vt!*&VV1A;(P?p zwOXF2uUT@^EUr5DC{q2{yHO^nQKf*6O-Hu4VRJq1^m(|%`}oUI!=}v4&uL~Tq_CS} zh?2zU;$~tVD9N32^s=Fc`UIRmdC3laf2c}P#W+0z)jTE;UJ^-dU@TeU1MI#+4K zk-7caH1U%3toAPxzP-)lt@^VY$VSwsYC0*?F08bFAPmu*W<2apZVceq$}PNLG$Hq% zoQ5U_&_o!t$|N$@hS|Ss>U=lWsP?VVkur&9pB=Bqj^*9q?SSSbhSJQWopJVxGFl(i zCPYrEPiCF3t2ZZ#E{-FplTEL{DyYrg@T%B>-C=6tHDTwE3B=pz)i6%K2o$tkIDk$QPzB(Pih

    slD z(^~3aH5xr|`BD1_4v(Iq;0_V`@m+s^YRU5Q8a?f`cLvU!-M-H`Lx|K{FWnZe3=>1s zznOMC6Oi!2Dr3PdXM8OF6?r9{N(b5~g4D;Yv3FvFy4v47&t?ruwW7?`X1GQ-!a+*U7N`Ax1LWLtqS=ToM zCvvdx8Dbb;TD+E_vFXd!z%XL>#T8S@RmW~_7_a|{#*5GlO^%qzdkID~1^yg3Nu+R( z52Ly+A70k`nOZq`h?r&>yDG~X8ApCLkiElCW5YSDymbpGt7x|E)jb6!*n!^C@;+_O zo*tbU8XAwyeLunSUyU@a*^qiwl(h8QwoObIS+RLO8nCi53BwkYeUQP#q!uNk7iXWd zR26W@8NvHtvbx|Tlvn(lVdOs9POQ7INfyfK85zbz-gk8iB4he<9yJwA^D_6ZnrYx)*xT zopr|)bS@G3Hz^C-xN5hqzahn6H{vLoxy1!P&>MR=3qCs&&2TG9%9VzA^20z*UuU|O zqG~T)H^}E7Oqf80=rgwC?h${;*IbLhNeI}Wn$Cm1!5m&KulH{2qkObK+$}r^I7e^_ zJUC|Z__TO_uqjqJWA0+H_pYis)XjHj94Y;CUIMc_{=@NUnWw)qMGJ z3rLTchX1BgBntjDL(2a(L$dsf@@V9gLP!rl&O6cJQvrQN z#sHfsQl48<;J8K8Aj7jrpl;rB$KwD@7;bMLO=K%;N@?7SJSrB#ZXR?#$( zXGRqolEaC{Bevo!v22EPo{Gq+CLZ0!OMD(TgW$JgMU`>_U3_%)lf-ju7}P%&mj(FyP?ok}sfnp#l)MZdA+pI&K>vR$FZ$KQ~sq9ITogqjMFK1Y6d4Irh`%_qpB5C3-M{7YXI<(~{75o%Dx zQzaF;bn7FAtB)Is%XcrQZNFS@N_{KDy%4(rFfh@BoA4jWhMsb|B(ZXIWAwD62EurD zJyg5AK18i(@*ut1Ff|R}y?@zT>V^hE0emZGgcJb&1?8@_|AxfXd`JX<3q%9@ml_Bl zN4R|O5C30!9PZ61kl<+ihD1j(0RT>rMIh6N1eB!7fY^>2aLK^|=mY?3R7<|1N=m!v z7DWtI!`&AutS_g_11`1|a`QqTa@K_;?aue7H6M#~^c8Aq^)W+bohN2Wr$!`*`W$|> zj`{ogpMRFl`WrN*@%%rNSE4w7CvQh#2Xw#@VYPq+F(2TM4kt5>xAfuoP|(gPkeSn^5p?#orgZKu%AP2%m9gS#lht{Ft>*azzW;-FWO7)UwEv4W?Xm9@-4aNK1GTu z%6>MUm)6a{+uA*vPsV)%=`Q;EZ%H>1$ql`L^UXD&(7a%*2Y5GCNSjJFWT>eaV9Y-> zBe+GW-WTa#oCWlk!cZ?#e~rMBNs6=8feO;Eq%IZ^}sl zc&sGA(TZF(BQT4AqfW5@#~FV3S+1xe%cHSoc6~GYB1(Ne;Cl8o%OwxmTDB!a)kw4r zF2s7YUaG0A*kIu@^o4&@<_hW%ccp8ZQ@o6qhlFzda3%ZpA{zn*Hy@96fG!wnfCCb; zqT7d#bEOcpQl-9sk9|8(0X3V1S7jiKm<{wgJTFO$zt*p@J)gqYI@VLF zD%Y}dK$DN;M*y|P4Wxsl>Hq12Outhg-qlW=FVC9SH;oO)@nX&F(`#%A>RKm?ClJS8 zeFjfTu$|3_Jf9UR0SGOucIQLVX@f`3g_#;roCn!LewxKyjkuD z?uqE`#p#hE&Z2?Jbw2a^z)ggoc9^$S0t27hw@rtM*@J~^+dd*=^&sCgGn3acX=xr* zqBCXb)je0&)b+-}5R_v)a|bN|cX!KI0I6ByDyG_c^JJ`;rZQ-oA2GO^5lMjF2MI9p zbc79a6#u*{pu<4i4k1u`e+WkN%wsS*XUx2M2cL;lAnRX?P#^qQdSCyJ=o|w6J{v%W zZS+Gf8)JS=SJ5aro=B^US{~!b|4_J7;HwO!Kn$H%3mIc_+g)r_3pxVtZOS8L@Vh0~@J`9s5?GddXq&4PqDTAvy zW+~YK=TRDyX*iC1i^+(0lI^esO675n}3H4`76@TZxfOxhgg9yw~o+3{k*a*s>WX3#y&M!Iu1?0 z4O##QnQ)orodgJT?l)kWZOno|GxV>JzF{;B;X#J}_B4I>hNex@?{k@i>!2yR5`-XlqO8*MB>ZsTWh;gG8~4AB0r;%UILDAEDn| zZKeDU#o`0cwNLr&%_bzE8JK>A$u(cxUgRFfiXdmARku}z9N_6Yjk@1oufvZ$U0JPFL?qX4pwNfI;c4@X^J-#8 z_(i{>mUbU}e(jw-g&&z(8(%B4jf+s2@aFNIl&^qV`*aL+_*emu3v+f*AMa%SjsgEJ z27dF`^Ypux_)kCVlV6AVyA=4pn3CVs#Q*R7|C{rVo^m5vd-Rlw(6#grG+s{$XacVc;H_Znc>;o|t`{G7Q>|Y4)Cx042^40o}bP32aYJhYJ$TP@nzg%pirxxZIVq%h5n9$twf*Dr&7JEDc7jq`s6Aknl=`ypq4`soz$- z^YA>_0r#FvkzRkAE(#%?ICe$;T7Cb+6$bG}r*eBZ9GzmhZbl9lz?|#Ly+=d_oS#O` zN<3mKc|vzzU=`kSOr9!kES?+&uz~oY@}rM z0mziDSWL-oV0?Y2_2n&qH_SQfO$hNW zZXU2j^&MzLE?3{78PT~cs}Tk2=I$QoCOQp~7#_xkM2kNK6x_Y{WFK;`twK@hKBDW- z3mW02`;1kqC`e`67aAo9h?!SKvUIQZ z3zsfat0##mwU8K(pn~^r&O&=&B%7!cS|EMJ5F%x+r>!G~ys$%S*XrFaiswN&y zfo;a~1@UZ4@~4~B5_ImtO$fmw1)MEAGaG%qS&yJeOUX0RbbL{hCE3tESD~9A8;I@Z9}D+>d$(XYVZBlH9vXDs|uteEfUz)P^dj$WXDD^ua-B~F-`Nuw=%}q!k;6J z6n`g|9ofMB=IJC9Q0u5V9ZvIjB#}Xu%6kqy@ zQP66QDej0ZS9J$3)gA&^N8lbS8(PIPS?=a!BKK2KX&V#*qS7uK+bLE576jG%&k0OU zvW)QtB=#6FH=WTeRJVDuIgF-c2jk;s^F$-N6)Xe9ljH5#bC*pbXA@2bZrC!A@c#oXFIlD=%uf=gntn1A;?#z3*Ay>9x$rI_-ym2?w zaN0NepbOkn{u)o(FDJL=%C)1#j6gAYXvT|qe5_O_Ney@Vy61L-qW3slR-npIwQ<%P zOEll{a^d9scTn|1g@;dLqa;;@jItHQeR}zrU1=tQ7f?4zj=9QVvrj{vtYzCj2uTew zKX7@nf^O!uHL_dVJr6 zJAbBm`HW01jCE)_@Ogf8#e66%QWfP5;29Pm?ZUi#4;r+GS-`gjG%Qa$4UTe5%6AJMXJ+!r8F+uxAV zMhjJKTCwX0{pdnvdNEQZA@`#Gm~q6SA|lq{_$o zu6ciFVHUIWWS6~Ej=l~W8Ukctd32Q7;fc00{+b37Yx*0K_@r5AAyHCeQ49QK6zSI) z_kiN6*Rd4OXbk7`z@F$SuO_Xy$v+J6@Kf&7N%_BquSI5>&?wMEbENHG*XTxM(-Hwl z;?IgizzX*dT_djkP7S2xhKFPChS#nMEw0^J5p=MHE~Ukw#S6$hL=>_Z5JhbIya?wXTmb8J0#@qWVk*aRksNzO_Lxo&zM z84M}Bsh1h+ipvr=q5h7)u|8AHPj_+yKD+X*{NAMc`uZ%kU9!KWJBKQ*P^DRn&O7Ky z#?;0q~1Hky(cV$jcOBZ;3p zZeYF7^2lT0Q3z3sde4-?T$jD}i;(qVLWaHCaV5=I?XGWE(NkvH7Cd7G*nFl|4Xegz zQmARk8#$DMVP?MBA&7;g-pYPf{vu17%3~vZ`TCH0aW3=3JA@Bv%lJu=61`seN|oJc zC^l6I{ob+T*vT8o4s{@q%UjGo{B^uIo@lirdHIAL!lI*1zO*bi2 zK83hC;{c^)sz19Wj+|=8%1!HEkLcWd7b%zDW4Rr=3G)luXs)~gP{0?}2vtA@aS!y% zmPo$H5wKRKBMeTzI6*G3ntL`)i#}ZIcR)^9AZsr`hv`4R-!4C(zPSflr`Ga+56G_i z|IXoAZ^QuUgM}9O$}ji~RCzGX2#Zyys}D!=011fXD-YxgLfqJ`zj&A=jXGba05*<< zO1kSy|BVXO{{dNM?8NmnhX7EvhtlN1Wxjgn(_Qx`TYOqJ>SB^i*(h) z)44C+^wnc;$c*d8SI5>H!tQ)&D|^|eN|EvUDuOrUpDRrlLwMi@ z#|`7;W$&hA(GQ%uTnar5+qF&VW{O9*%EmQnJ2{~SM1%@n{0Es>KES|mMKg7-W{vy zScG^QZ;H~Eb}D!jn)4<8eq$=ZSY;6*ZacE%#wxPCu7;2Lz>^aczai{ zvQCHMb+wEO`5@#pmpZmEbZW_^Tft&HKHK*s>D`s!PL7FA&+@av&cg93IB73xs_9o* zHc1=1ClKfy0`id^1kjuOp}bvjXKrEHhWX+=sgT>Ws;a7ZH%29ksNRZNu?m9jr}jNW znZ_$Sl!pC!veLXFn1*Br-?f>EmFa${5m#nP^Qc)y4AT zPd>+E-foRsMV1GwPsUab75tZCVbV|E%+5$g(s-|H#zf+%@~Pi>O_7o!EJrY*GY0<+ z>6t!s0U@c;UQ7mLG-~NOUF+ug^&d=OXQyh!?EHT2O&Ee7SC?!A-V136e>ehZR*txf zF;8nH>zS#u-^=@@!emm_+2KdCc|c zU`dH~5O;UYLomTmnp8U@lSXE*1sF5jt#abjjRm zein;u3q0Z@$)$r(y5eY)SpNUGMz#>SGe!Kn| z0pymhrm*f8Ga$vgbAPW$;x9fUZDKh>3-@yuw$E88$56FEwv9DxK@n1C_jPw(>TkZk z1((f(Y1O@mD- z713q6VwWdSswg9p^^t$Td^yWMeLF&@lTO>WB68n#w}?Rh=>{ncb$9WSw&F$e%Ok49 z{;UPMs6bi<;!9oZovGiDUM1)qzKL9xlb=6V4U-AM-_`Vq5g&Bz1{G@8jP7y`&~+NV zM=Qg8yi9lh#(YZ@e?qo@p=k^zo}S}?>G;9avEGtC7E&?$5}u9`9#?6bl9J`R$>Cw!sb3I0#|+=- zaP!P0+Qn}*4GTrlA%4FQI_0s5TlXBEd~4s;i1g@@YLqBSl!6)NJq~GClFyj) zX)}t^cjP~e?MpO@97JA$6;PA8=-yEXRM4JOZYc42(c!Nml&#l7#&5r#! zV8@OX4?>^=d1a>(0QH3X0+MB;5daPm0EY2zcI>a+*?}`Mg#X1E|6U(9>ccM=`UpQc zpn?qr5XUd)119n7r|kF_vZ|x|Czm&}nNKwo8`zW)G_6|Fe7!=)T5#P9e2YhwW2bxM zvT*w2rKq-jj1W6Ru!UVVO@#Oz-0WA|mE>{dV^(amYGB%svU~@|lJhI)0;Qt)OZoO5 z>+<~m=g;a$)L2?xOiQ*3+fS|Btut*aNZ%J`GgdAzI3mNJy|83oX|xXTmi>57ddS1% zWzMUlPZn+AaTj-zWd`NJA6?j3FbnpC49&q5XW;j|F%T>FmTyn&Nb#FZXCm&3o#{Gi zC+EN%*Gg=>ML%eV_Ak#VkDtsm0FQ;H>Yl&OUvy3r5r_txpnG)v_OsXNfLRJADjlZ18Wh%K3e>< zHlDTnxDA5%yKX^&%86>LL7~#U)0`}SZoc<-esu5e3K##P%jXCA{*S)Q|NKS0ataVH zb;OZb9z|n{CF7X{%(uz&NB1M#BJR35W{h~!Us!871n4EmEO=4&Oh<1erxaRV_={E^ zF~mCTbVa@e6V3GVF{1MgNTpwByc~{TOUY_|fO}~wxdA$)jTXfNZs4DN$$yBRssHHL zB+0U(zZ8y$3VF7GavF#D+*T_G=rS`dk{rIWetRCE4kn%5OU%WQl_DN%)Oi2h`HnCy z+4c^K;$ci|W?tp$Ij`sIkZ|FsGFQ&JJ46XA^8nC~x;FiUFD2aO*kH0_WxVDi#Bt$i;RE{p-)MmdE-OC#{$%cK!` zKBm#>)856BB2*H-N3PLJ@R`F^YtVU@yv}ezNR71V(bhrkZOqBut0$lex-sITNp|`o zJOT}WHqMI0m^(S3c8rGu>xjv^hbv~(uou_vO^PX=i=IR47JT~AP|6)~>BGAz+4}Pf zv;FjIv*%;;ZF;NtEyjpli9Rc&$Y!KOC{Golp?NV0xBqGZfmDayK?&+0dDc#qkPEv_ z>n;8UUJ3nF%7R9RF*j)EhKISQLq&CjmJ;XyZ7!AlGY4u(9noyXOxX(74 zT{6LiC8Mv^p4H=V3t1Sf*D4Dt4}Z8=ipt%3jGItRfg4w>J%8x$Z!N@a;0SiiX?0_$ zi(S)ZQNfvv3@+i1gmbuTdF`lWpY9-DHbYMU$Jg8DKrWX0{9qkRbNTq?X|3!a!Ho9- zOzp%-YofyTqrngYQw^tld&@%bm`+90tA5H+4zlOu-(0RC zfD8&b%)d;B9YE)5u@BCH6zzI2!lheGGb?#Tt)!|lOf8Vjr17KFb0Zv{h>Z(*n<>5x z($>7liyaveRso7?CndVr2wkB37>4X%Y=Ue^-FYt7!zk!aG_>7>GH%KJ;eI%7W!a-i z^+UgEDz!v&^Hr}Bfj9~r!jSh_Xd<}2&vkSH3@5@y&=U2zORk6IO<2!sW;H_~xVc${ zjxz}K%fQngC2^6{;dq;V``g3j4_#|3B%{`;E3z)sJdgPXRk1>%N7GU|Jt-=g*|=|+ z2?k2t`+K0QA8k0?mOihH_!rvYyR+aWOm!8|RmTffR3AqnTOGhODIoGmGb5_g;$f^Me@d5B4+<-9_qnt|SWAOHpI% z)CrK$!lP*=A4fgqwC1;vN&I+MYHmGY%$oh;u?_&xAL7JQKQQGbhH5-Bce5zbHr(UL zoV5V3x+bwU1a|^S7*`;7aIoQrcXbZxk-A0cXBF_ohA=O&tqFmRDBGZx;3fAq453>y z;@UEA*nP&Z_IJ#!45u7f$Lj<(IQOpKj@S9O2hU0ARY5bL2H|Q|&xK3`324}&q&q6! zy#J075mxU-h8+bigqkBL0i|At0B32%~=EK6{``{l5>O*owkpWtVTFqicb zD|ctK*n|SJ@~vZ$Bmrx#OwZExePzG5q1+KHO1+EBZ;EL%3>o*Y&JDzDCF} zqu|VTR(i5@4&1HuV3tsNC4i9BiM926@E$b2Z(M|OT31hj{?l?7Q^ig_EnZ0T06%JP z)LiMgn<3KMdqE3J9onx;W;aRH-PE?ha@iG!TRU-fikII}u&R4p_}A)=yxDgE6MX>B zpoXpiI-K#kqnOWj;By{jt?h@x13eY-SCe~2#PDj2dmqJ6BQWP8G;M>n%)R2;;xn`v zB9|P)Fn1^6g2DM0hHy1yUV^vzulC{f#jIoNbSups3bK$l`iBzZf5NGMHT(Mm$NH16 ze=_^23}Um$@FxerI+x}N#_P1d+eYy&8=xb41R?khX-Wok5;b3yPa+N|_nHGCyL2g6 zGS)h($Xz?y>&4kF$sazvGpUN5C#4B^Nh)FgDB7@;V)ycy$1?$Y)dwojw6Za7$`{wF z0yb5?S+yl$V`%4idmPgBC7!w%{^vD=EX8sPa>oxHu$v^1Gj!hfBPZHdM{wAlawngO z5JjDlLq`f=``Bqrg9&lr)^dgAw3MYU0CH&O5WV>H7V;(o_O#k>LESuIt0-QuHYiCJ$U$E3x zM86#CSneBO{RAg7!JFoA4Rb3uaAh1HlNk-XWnsnWy`h()Opo8Do54b-^_25EL#$#Yq*zTT*+;qLq~q``m?CmZ z+kqJK(d>@-+jm$V(rRS+3qPZ%U@y0z^xNY1w_DAJR6xJSUkc1WHcF@lt5n7t1wNG9 zmsT7R*a$hL9e!9XiuM-?AArilk2ifj~RO)-!!xt+DiLZNI7o2cJRo zk18o&sLd+DIn!oT&Qry#`|g2Q%9kAZmsSG#Zx5wXi+F_DHOG9Tww$zM8W+8vWJd8; znoHj6z9ahG2w9x>sswXLrAt5$lPzK!1TKr8aoi23{?g;#!PkymU?Wl^GEw+Sb%nfh zVZHv0XlhSfv9@Z0)zWfr(w2_k`%XPJoXhZjGUxGmw|u45DExlUdE0brI}@pq$R{eX zJZBJ`YYGC58AAA@$vD2H|Ew!cE9Q`XM{Qr26oPklQ>xqfkW1aMDXpJlMqiSq#=1_d zPX@7ddM0#h8$a?Z+weDq_5V8SKyfH#j~S#!kBRzGdee@dYB?kA;}f7av(|4&PC#cg zKy?JP#QTrZ$T$CIe`TK8I-4B5EM+->X|U4rqElsD-OF9Jz9e>}zFJ)9t2AfnSb#s> z2A#Gx#{eA-{@e#m6{=kApdnFXY!D$)@d^JoB=@oAibsgGAq2_~vD7f?SS!(YT+|*a zUUDr3TOhkGefpgAIscQ+vN8UrGN}7>YyK#HJ&URfFg&2qF(3y-&iI{(81}!816^P< z0#*hZWP<_{Q(s?j%<0C;ni@yQ&>2iIDI`RCi_uaF;`YVIMo57Y0|P~@>>vT&5JjfL z0m_aS(!IGk!|BZD?qv zm)L#GNz7=wtpUD8(@e`9PjI$)g|9=)x9R5k?zQsU&`hE88SiJFdQ+=7E*mM@^{DtW zQfnRcDz+9z5t#gZCsY&kgs(DI3mI)fXepHe#P{2`Kj?>`-;2SKe%eM!t~o@c-yy+;v!db5e>0h$P5gDw@qZ_GN+gDUiR;6RhZ1vZzXTA^&d9#p%# z0{DQg;OFMBZunQTY4O>P#%B-4vZ{7%n)9;8l2R_>p+#}HyWzmkG7OL~pDzHlboie( ze-*??{n{QjyFUaV67?@11L6XS0RW~*Nx2jRfW@CiX!`T}UzI0-L+sCf4g9t#$H1CO zr+*V*ZvffYKme-l@1QavDFEnDK&Y$$4KY}6Ksi5n0<(vHm1jd`*3;C}>Y#>t1)5tB zGwA2TJ13Mky&-Riq5U-#}#`gZSo_CEVO z_uPHY51wbetg2d4^{#i$F~=OEZnkV{QcF_y@J?oTTso0WLDY5A=3jKG{93g|_+8z> zE`<;XY5&$7^tT5!adkL&O)nhYgm=yEa11VxyA-u2itTO!(4U%+{sZ7O5`k|vn)@;)iolhX+k1lp7i~r`BQLKV z{)&eeYx1oGhb!|~@Yc_o@t!caC6<4wgd`axa3esuW_7{{yQ_JAd^G-Jvv#}*{a zTF2A?h}L7%N^nKxXg_~U`yxZ&dgoe}@Hd}#QSbTmC3w3eHvHgvN8r*3a4SzChO_L% z!Fm-W9;V*4$H(M7#Wfewf~tKSL+x;mlc}8=;4m+?a3~wL)4RViR(Vlznjk{C9w-<8 zpq#>%)bm5`#x}IB@580OC{EygOrF*4li4R1y7u+9rx$?b3ghBDP*vnD@77C*Ac_E} zo?^rBI!<`7`Fx4(enx!_#7AcX$bl>>Qn141g$oyt!pxfI0pe*(Z!^$%{?k=unRpyr zZx7&W(SIU(+<t5b2sr;l`=}DEFRj2wEP$b@7rSXu>6JL!;=xb8vmsz>O7?%w;J@cR zcsEx5yz}PyPV{!JqCansUcXB=FXo|e%9CYPOz#g$#|#(>-i;j+49UUW;hezCl6b^y?giz#bsU7 zni5)b%re4gqBuO&AE;Z>HZf0}?xsM{Ih?CGM;FaQK~XqHJ`Y)XNe_zDy)?eAa^VxK zMk~R98Q5wINH&!NP`0%YVI?4|@@qxq=k|YLRRv4upQ(SS)c^A~HPFZ}EAOAHa8c=V zaL*55shL87s}#!X&UEIf51Mhkco~uD_c0fBBuo?}Cu$h_;O`zl+3?l?IM`9}4m0}B z^ykyz*YU60|Ji*H7UF@lbppw zu8r(*!8IHcKx_Fqp!b9m;b19r6?bdHUz)&dxn|&No!Z!Jb;wG~bz5`oegM>9*r_Kg zuOKcCarIx#pNovsG}*1AB9~8_grq>6%GgN+l~X%mqW29PmIfBs`Sg-D{Y-|lm-1r5 zU89r!_Orx?BUKMdQh`Q4fG?-B0r(V#sutp6P|~L}3_5!F<;JZCZI6l%wR>SAOW*rG zxr6V3uSjUGMo@}zVtyHq{<8hwejjq;z0|mL^{vc#pH^$l>v)Qm-t9pdYkQ0ddiI9$ z{^#h0U9H|XSlZx_1_FT}Y3#{43FJy^|2aT7+Z)>9Z>%&VUU(PQv+7&m1CE z<}UEU!D2SZAwdvOwxR}_kPmOTuPOcduSP8}GzmRF!d#KlU>U1qgtL?6`Pqlm(v9O@C zQ+@J2SG8uMm|@lE1S^$7r%7nNg*LQPJlo#FdKX|L&yQ?@r+{b`@sOi3mDt5u>$|9t z$8Bi6&dU^-I?f6z@?@3@dfGX8!q^ylF|S@ZXPpX6NAo%yKbCKwAr}?toPb0e6=I`{ zc0^jcTzLC99^QeG{H3ZyNj_n9pXNJ@7j?)(Y^>-X+-D`xEijJabhEhFx*{j3v4ufL z0!WRk7>$!1=GHj=5bq|eP;PhXE)ZP04L9o7!!zSd=%{;-a<|aNN^O}lM=m^sW`Hk` zIqsXp!8K?Bo1>X8a>gnuh+t)*Xjd?Da0}TWsFwCvpr=><)rB-VsKytVOuef=Gq+THHvjT`nu4?U;U`?sGaNk%DuFwn-rB< zTzU^^f6JYsIaZ(NUc<#d@hN5EQzz+q9spV39#lZ-*tX`yQ0fA?Np7PC6e66l&ARj2 z#L^erb}S9^WvvA%27lYb+T)0z>z< zXZg<6cSk?-6lY)#=}0~HE$U_V-YCZsp$(LeCLc%^Y(NpFp9t^izW6NsYZ+(Ftre?XrtFGD+cuigqZgY*MBI!Eo7zkDR;FWb!-(tOYt(t%bw{n5c+ z`Kp9xY$5jNhy=rYsxkUpCz73K>|egEWQDoAgNGld-l2kzGXJ(!;vW?CuXcdisuphi z@}CYpsDGx3E05AeB5{dR|BuMge{!tGTypi}7I#(IJ1rTu&}l`^tRcg4C}4uwlSOxp zmrrtiw!KqyW0~CzyPK~5T!Mx42Z)(y#HwYtd(ldq5BhEH`Q_w@Blp@AgsN2B(w+gA zV~mA?{zWot;3YYEu-6JZO(4R<`EHM(>7)C}^@CvK&fAttOf6df2Wl zJJD??cL0@Gv+JqZO>rajkCl766RUZvWv43MnU(YSy_DQFf^%5pB3P@LJ;L%f^lovYBMszIsww;D-l3J7KrE)J-Rb#=XWv7H= zW?~Qca6>@ieYKk*$?c@~vgsM3dAj1P%?BaRw6sNpDNPem36MVcpzB)wBa7~FwJE`_@QD4Dvmal-8Hqq<$EQm%BYRL*AU5g)fJ(l(F5iC>7IV0cIRcyLURE&4ojopcXip3Jup2@_Tw_np?P(u)v3(du}{_*Gc~>gx7rUDJnB70L#IhxZufgy zH@78j_`gKRJZ{nC-jG~Fp51Vqt=!~>Bi}Vu0!&Sn8^jat)F&>5iW3cQFXCiSXA-pX zBE?eKh~6vW$iHxU$@~h90@U>+`})J&FtVF771}vodvbpZ7%Am&wU-OT7K*05U7f zDKh5kp-wqn0TqQV9z`h3i4ZbBWYk2xb+kCEp`$f7t1Vlwpj;um!E_++`tj|4jR6r( zd5slJxU-nP3wqNx3ki#JfAbC3Da>6>U7pz5SR-ha*B?8UNLFZ-hvmvzCU%F{i)lF$ zOX;5Q!c@fzpD2bHmE1NKY0~k?DJWZA)Jgk!lUQ?7L(3|q>g#wl5Qw-8(d*?oyy@*5 z097{Fo_gAyCr!z=L4+Qt%$7bL&sQ&jl-JWLKloffkIeYJUzDGoTCc0ajHZgiBwq+6-snt zCE=oypWavf;!hh|ygphoQ3s9*eeRA-8GJ~t*e|tfdx^^4c-Gl1xFkv^bV42{Q*IC? zeqA!EhD5#iT26u%>3f`F(};@7_lYAQr$P0YKSL6yv0k$)>RJE#8-#DZ?GLaq?Zp=Q z+bH!}jE556{no5Kdc*)JwP)O*AG%P8yL9li!zgyDk%fiJeij)+g~U=hwcSI-bQ{}P zZqy*C9)_6&WydqTpk*sX)tbnxXRnYj8md-f%uj6W zK#1H*Q(T2FSEDpnXCBo1 z!}P5(MtGwOu}!zY{Z8?vUuCk`kj@Y9DeC5qsg}k4ClYBw zw##S2w#XC3Y|yDEXfZLuw(Tz|T!x^aB~0NZ)lkK82FVry^a36nXkITm1Gt&y=`4e{w^0 zwk_~}aQ^X;s~=lea=Wqd`bO2@icBbCE}ro~#|kMu@-UaKNuQ?grH7cT+$)4u zs&ux+xYYA|51^=m2uFLgTNk2>Gy#c+_cBfv;jy$++g7~e$yo`*E~iijc^>z0qavw# z#;wM_P^pbtRQtj;lV^tI=W8l6X2@3DhbasFXa^!#sWTkeQxZ#+)VF6(+B)v3#KiP3DA5%sGOpj>%mngP_D#2)YxK+R{*mQc zve(+W0AT)3@`TUdQgVs0rsJk~oC3dVEayFTH<9Ndghdb8G@2?s>>4ZnJA-D-fIg?m zD{n)hr<*a_FI!f<-~FX8^YK7;>Izd_mhK=*wvE<6%?qj~y1N>u988jL%?vI=gZpE3 z$y6$YoryX$*_{nqGX|`C175Z@mIhsR+^wrQ%qrAJIT0re!8ilYUJl(_^rjmxp)-pk z2lR1qlenxwvx|#3RC}$h5-H#BYe$FKFQml2g|1B~h*JF8a6puR8QWgQHhv16>5+O)(9J&TNLG5Z1xy;w^|J=v1`uz%IH1H|vT3uLDUg4aN@ zPAzC4cnuT>PxRm-|88T@mTBf}JN$F^pUjvw-|1nvr{G;25Xo{M?t_0;8H)kItA_xk zwyw!nVoI8)2tQo7gw|Bh!O=h z?lypk4!Yp!Z9Y%}a!6ej2fng3^u_aqC-;Ogg+Gn$faP}hAQvb>je$eSejEM8`0oGg z|3CNVKl%HZ;w^URmmVp3U3^$lw3M(gY6WQ1WQUfZEuQ4@oeQzBUe>9!CFShnI3cfQ zh$xxB&e7fOE8fFhOF3$<#KC!2Ik)oBN*vHJSzV5Wu|9Ew=n**k?7NlfR6QQ^&Ro&T z2L?6G%yT^)sEot{8Ve1pPRo~CW8r95Wmn&=hr-g@Dy~)Ca$&~dTq`0cQ`XJ2DfHt0 z1sQA5p!vG!fdF+g@C@NXqWNp4gK{JL+u3~1+Uuo5CBLRo+L~L&U_A{vdRZ!e5si;d z+_nJ}QnCGxNYC6R3&XDoKMC&kZ32t|pHj#Ng`mg3JCg#Y7@-$X-lR~ zyUa%tpy!w2?B;*Zc;C6z%+pg!7baSIDj|QV7A{s2(8}1qUcBv)M}do~OrUXip%~3G zNJ*6|`RqKQN{Lzbe097TSZPggA3HSp#qt@J(JO|m=oI0%a)O%sXUTdhla+aElWdX> zGkjY%B&`^?o%@rXU*u6P|2<`@e<_uv3J%^(m}=uGf}S+66xUnEpb@clt%$!uRcwzy zpo-MBOBl%MF;K5n!jHS9?U`6l;Vlej_Y{fw%K3@~g_yL2*{=t;qD)$1?%aCs3fv5= zQ{F5;>)Iym_qVBcXwg8)x=>jjS?|}KX4khbk>jiSU-=BEFYzMuZl)Eg1S6mCQK~PG z(bj~>F;Pnz$S?9bF+72QELC6Bh+j1OH}3((hZ{*-#Xmr1J9=jb0NuCw2oO(q++5&3 z<_u!wQ%DmxO6#Evv*t$hrikg2B+$<10(!Z$M^Fn56(Thl^LIcIZ1hq59$P>m{-l_8 zg)?}l*4BtL#Zgov*&~u{$cq_&t^wVlcM#+T&vaz3w7DkYlzh>qBMGuJ7{S_BhR=il z0P!<6ANGTf9f_wn@tkm<&1*C!4RQ`Xt}EAztPguh_du^2PzxNEw!S@Cywf4GY6dji zVizyho3HA6Tn$q@Y+It<1i|KjD;F}hhp_H?l>(A`t*#y(M$QHd$B^$8VWtM^RTWVK zx%P$!w@vM{jUqZq@v$1$`;*I8W`wiOf!&t}$ zZ@Cyg4}%&EP3>LAfC^D`zB#oyh9Lo_NwBhZJ}i` zV~(XbKiEEPSf+P-chETnySBDr>U=i1|3yWOW7TV`A>#CD_pm3Wt2*jtTwPhQ+u;3C z?s6=}Zq$yKRkMF4Ch%4*BT5WaiYmBh-1*Lrft`A+9Kc{7=H82+FW#X8e43v; zj=zu8-ieZF6)&EU{dryz(}S5;rJ{c9I#L_-se%L2i9Wk0IpV}_aGyHZhKDdi#8qzl z*gLE79)a<%qdu|MsCGh^#fSywLIBK*vI`LO+keJ}9}U+D?c5DqLeqvLxHQI8HPU6QfasXy|I zUf8l{``V;g!6HV24ZjNC%XDbZ;(t6_etJcWR5xRTWF3-@4%4iTo(zRv3}qjYHsn=7a{`x`s)<< zb%Nm-FZNUIBshLkWU+Ee(a8$w^2NWwHN06GL1~^X1>CQ*tM9L^;Y{JbPPh-cx_a+c z_E|1cz=vze^A6;S&8D~vo5SE#xmsGa^%Ip;k(vdwy# zVe?n+Z)>U|^q1oloW)4L5Pc$CNLCl)ux&oScSS3l4(oE?m3umv(_hq-PN>OO8_V_O z>&$zU=>k?Ci6xu%QqA5`_T5I4w-(9oRO`kLD5`xOY&x-GE(>D5p@?HN9H=~Eo-lBJ zY{rI`c`GoCbfw@qG`lowC;n{)l^!14+Jj0pmQy!YdiXJnzWJfcN0-&`K9ShtBuYb) zG$Jb$W!pV|dQsIlm02yOxb3QpAGM8HpKDAnQeonpO^VmuAd=}#UYFq#u3_0%`}P-^ zdgWDNuyLW0;{8>8iHwOXQH3o~RZG6-B;aR=xCOLqvj5Cub`xYzEHOU)KYoW3A+s6f z0>8g^>v!M3G>kg>=li;JK#nK?!1KNu;A_%w2w<1!bt4GJ07~;~ZlM29eMnJ|wy&=9 z>b-O)M+&}K6cpO~<#@${@vS5^D*uCP`Uv;a>j_=V$tLpoYZJwB3io#*{f@VR%sU{| zb6rzJ8}-2=mr_l?a~&xdy){+8w1rRb=?gjH8_%2)aNEm2Kng$Q@(~4ZCK5RB!bty( z;*e3YbH1Y#6`~W9`IFTU7K$&+q^P-|m&kqi+XC~C%gw3vbMtEG0^dn7(;D7m;A8%}cqI3`jgk%O5RWgVqSPUnG1HTLDu(-m*J%3N?C!*uca*8;WK-ZH);~bS%7Y;= z!JspBC6$SikF}?F9kn$~&94k?yGys|i~pf9&*E*PWN(-3&KThOrIBp@=8JL$qyfz4 zz@`@49DW!OGT4)_3&&cY@c*u~hp}cr1V~1j&Q#w!Jtw+x$}#h#JO&u3flSX}H}G}F z^ZG)w{e@OsD7^@V|MQ34Lzr_IYbmRZHhR(kl}B)pq*&|b9I%O-G%Y1N0tfM_;mguLY}wD8Y`RL08Cq9O&_nqYp8I@xDn#sqmhE16_1uQv4cmLD2R^CcG+eYkE#I9`OA$U6u!zi?d$&BBTL$sp zhps;Ju0y{o>7pP!fC<44gj>j+!j-R5KWCfKe|B8%^jpBIla_o@oTQF4T-3G+A8MFz*f|yVTwB`G+NBixQ)h_neF7~klh01F<-mgQu!}He zZ2@N@r&^1MC>}mW1!-bs8%Z=vVhF+!5~SnmN55Q21bS0Cq;(pASuwU%$`ice0T&@N z9a)hMo@UG~S3mUa+T}~c8~p6sPk!EF{b`c7nP`VcE*v_xGefv>vjBq;i8dLS5$BkB z8!!z#P(dZ)eD2qciV4e}pWPrK+Rxu%Q)2`KlI4nafn0DS{yvcnVSy{h)ngmWkd6$6 z=4~!PpTxbWJwU}SY+YJ>YEk8uG_ojDbRR{jE){#6wF`O}@+ibha+SJz9L>U7@KpNz z$?j3@4z^m%j_&JYKF#dK?|O1!{0~kXt6cEl0u+z>Qz5G>!X0?}O5KtUC=}{4rul9R}h!>G`OKw*^#PzCLrMB6m;%Qv&r7H(fo22HC+{pu4j z9&?P$@HrwG0>?YIB@IsnL^su=K8{p{^2 zyvu~xT%6)cONP>mUM=&yUM{5Q?rh_3@N%!w7?q5@qRHfBLdRo(2R+OB4B1QiY3M zeM_b>E_t$;)zTriO^DG}6IQU)s3ilD!US z|2f2pT+Uxq3YJm)dhVx#&dZ_~)hn}!>l5!eK0T!eicSNCm zxoIVVdV8HQqd~X~1b9xYy-1jD8$a;7pP&bY-Af zKKnRXXBa8YX3VXi^F&2I0{jT{8At7wr5)~J*?b7Z2YzI~%KAN+{Lk-H83zRVXMp6m zVey7J?^l69rEYASE~-GBrw%Ikh(~FtV;>Yph0wgWStw6>n;mYxj%Dq!E)M(gmFW06BBv7BIt#dU{1zo=MtRx}Vk z4%WA3h$6P)XtJn6t%$NgT@Ko6@1sv(kvXL|+ezKh*Jbgj2-f7?-J05wzHiP1k7xow zzyqZ_Q~2U&^A;m8vAkcx*=6YkF@_y4Oe=SBqY3aUiR3^>vo^91xrS`as3AuKl!pUl z<5PQH04Or5w%*eNC$-;CXf~0$sBC_~y#u=pbiM_P0oep30FIPBI{N|9E{+TkO2JHrtMsW9ywxrs zqOts}buTXVESxoVfAL8A3|+xn6vw;#xn|30(f%U>WlKzDE5vbjEfq0Kejh64Cj@Qz zvtN}V|!B9R;>ETK7uCC{(*^>eyj`moIDiIf*WvSG?&Lu5HlKHJFUlzG42Mo-AVYfeBjThU z?ye_==(Y*_bR|LTlUy@^jf81kA}>Cyvf5^cqXHIa#N0^*spCM(v_m(Tu%iC_D*Ic) zH%{iaVbyltg7KR}Jy`*=VmNh%Ud%1*V+tY`**JJa0EzRi`xRq<2z#|MRszNmTrgi=6N87eJRd{9Wn!k9#w{_i@>sL>8Yj6Uht6;+t?&5d%+iD}{H( zcuYoQy9dZpQXF>hdg6AMC?&UJ>e#*vl3PQC7|XP!<^HGk-Y1xu1c&vxbCCJ8_zQmq zVbPs0#Fhf9>4nP56ZvS=nMBAu_Q4I=HbA-WIZ*TarzKH@NBLbsT-+OR4}$0rW6PU= zlplwG^_+4>Zu$fC!}8P+tsX0Bl{O`#3S50=ee+lyyd(t`oHAZcZ(%cZ2`I+j7LF+%e)d&1O1%8`nzf1u-cndI}p9AyR zs~3(#w)Y2U;qLK0AVj-DHhaT)k6a{pL?hT0{@dL8Wdi;_x8TF~hb@BO^{d|wUSu(Q z%X^4_<-QkZqy6bt_VAU^tv!C1jmwsW$*)sWIl_$4vZ$ZEDcKCY@KTpcMcrx1TkX-e zm-AhhKXiCym%RjXq+BdB1^nxt=}Q(nBy?h>42%J!M6xM+d)388_<4 z1k5C$QU+H%T59y{7B#}s2~s5y{N$}NIy43w!8^l+_1%c)^aWHwl7B6#;qtkNza&zK zMnsvsl;IJk3y#%rI}c_GsA80D_Cp1lm;V@ByO)p^>H;X@iLQ*ff)GC8lrI~f zq6{Pd!+mS~z(?AWWx0pKO3mwnx~P1r-XmweA=|37XvE;-gH$KhZ@S6YC#VKvrK4gk zMx6c*sErBdmHg}_o2nYQ9FcJmZ`x5l8TxQ>@4TFX6OWv$csr61$u_9t8B(rHQe%}8 zGcDP0k?_;Y27!DQ`o;$OEQ|HM`dYJ?#qeA~bhIS0ATps>$))~h^e^vjW$JBL?x!~(Moeuao}H4a|J0}3TG zGNl)|@fUVM{$v&6WqBW44Dee%N|0tHK!G-Hvm4ULtbVpSt2iSg>P?nLNS&DB?q!g7 zN^WVfYV{E`6{#-loReef^0C83+@n%#yAY!YoSt6!ZtByX&QA(LI96=4k9*%&bEuB@ zd^COB|E!$3df|QKr7SlIhNx}&Hl8hm8jniIXpx`^8cp3BEJKp-R0r$ItGS54eG|e* zZLQ;(Q)h?N&A>EdtrXkF=vKTpx{$&OY8iO#L%eKk=skhS_#0399}=v;$^QP&2`zuz z`b}Wdy!;>9W&hTL`%@f&K$i-TvtR{6Cc!gv)nX%;aJbMQfNucN-DtjMB|_k`-Zc^s z)#?KT{CoP?JeRn(OW07rw^@Z-A8KYcR z0&^y@61$8ow)Oxgknh<;E`iDk z;wn98t2=RW^%qAnOqT@cX*)E*1LnXZW!6Si*h}e1scLtPC9tXKPOs{FineW4#|MJz$}Sb1t zX-0qnV$7zeuwPQ<9*y)HEOyyb(UW(w;N}UByPK>)xe^h#drHxXl7S% z+HV?nJjbAM&9QwpTS~L41dr#810^3#brSa<-$E$5_6mF_?50Z=TkB|sywekjdiDiI zH+v3ktp;R94N^H|TCk{`3CIn6Ll8z3fbR9F)q8OJqs6HupuO=o2GPGO+F@eRe1g~r zgbs|F?8!j6tmn}syp|BOy4ZCSq`k=COsF#cj(A6g8&npSG+S z1@d8qO)8S1ZNC`;M8oLWj9=oqUvEe%`{PII^!2u5og#*}sA(6-$IVoqHS(kVs5jEE zx)aaoH=ddzRO#Tv!)ohCu8gcS`i==uC~f~jp`>a4dSK0`&6}LS0=_&dqH#dJaX`!A-y;dF@fct!}COcvKJ1<^s`s0rS@S0f}usf{(hNZY3i~5=cos(6XXKdtEyh-Oh-6*w>c*F{v{+@C{jYCUAg|q@v zpd0kr##Qx@o-oB`SE(wgH@iM^pc}$*pl}!IvkL#IiZ-$UG;;q3+=+g=7SX@f8sBUV zLI8;|ms=Loi%v@PI3k6Z}bKZp(OMW5u3n>|o%jgKhcSgBzAL)j^zGDDB`t^|aqxG`q9LftPG3QQY7A zR*Yjg<(a6_{2pQ|6F)ym>4wNYNzt7S{Pd&`vViI@QC85s67e7KhtW~(ETk+{=xSSJNn95J_sKs zNr>|3D~tMS8a6^M&}ZvOc6~Ad$YTLHN;Z7a7w!QOyaN&rx)^%WQ|C^gx9(*|9_EPZbIW3?IpnXwT&~0{%_paizsR)y0 zE=p^TDEf>}Xf;uw;2Q#Jk6c9Vk`g~iOJVNjUKXzLEJML#W&^K1RN54uVpRsh2GtC8 zP3U#s@asXG!n)K2<|S`mfP7)y3RqHUroutJaBPG^fCljEKYknh|8TD@fIk<(n0%(H zIGibsV({)?jfuQP+l&q~5BC$G%l&GFTm%z^$+WO&QN%KzchldDpp=y-svqk@9`Dq} zRH`nB$Hq<}<88c8;Xb>U0kDTJO7Kje#R3I%P;8yt@Pp;7z_G;Ol zNR!D7&E-G=Q9nK-qp2gY!pD+lcSFCCBz_wd0lE1C%}66|LQGfs$MV^-1PlM9z&k{K+Jc$P9)xeb5U+>9Q~oIc6gqygx{R za>n98Er|Lpov7xpT3@wv?bUGcpD_2NVf4`_R~|P9oD*aQ%T8F9;?F@UeYjVZo`X7~ zO8PoHLPOJkgoJoWl%odUu{s=QH-9|~Oprv9C|~I6OgdBWUrTB8awAe!H9f}sYIRVI zQl6WbC}PH>e=B9}r*_C1vM$uq%m1o_C&q7pRR(##vRufPKC7UgtdD4e{P-lobx$~R z;IXnAJ6ULDVX_mntM8!iV8}w_z_7`GUze*P!z;f_TztrmIoz#@Pht6DoJf)I;QJ?> zyB`irt0%sHfSf&TQ$LLY*xu9!_Pi2j+2gRp&-r?=URyJ3Vmt*ct@l&(!BtT-kxmZ1 z?KTM9T^4e((6eM6n$N7t6^-h$G#pcCPaoXlbOA_7TV>VA9((XDK}O|- zwM=8W-l$r_!QsSD3;LY>P#XbS3X2*RF>NDKz+|ra7L?EmvUL zhLBb=I>4KYg|{3hRH@+%qkHGlw?wx!drj@cuNf{Cscp$Poks9enkkl6kMqkaXG!-X!4ZeJNjhnha}R}rcIEp&DOc;Rm{VCba)g}H~I zdAEV=hMgWjb;JQh24i3$I0A1?6l;Q(qs3FzM=e)>0%TUB;ftDR~xNZp!P*3cw<@DUT^LDYid5{v;0LRk#J7>nsws!Gg@ zqjBtyL0Y5pVd8Jvw?-FPCRHgb3fZS{^e)tr%%ADg+9RT_o5!8MJ;Cv*a^CNfDw*3v z#TgZ6Q+jEdB@T*=`4j?mH=9}q5l*&H)%Y`kk6|Y=&szl8!?kPct0u@~!lVPNx#u1% zm6LzdeNuv9!hKo~Yl#Wh_KR_B6p8{pZIk40x;K$@{aiSESTUMjQ|7_KKRFyV7M33Q zmXqWmb^exl?fC1Q3h3Fk^)?AYakef#U78 zuI@ycW^CzS$Rj2#ZEqe`}w<5h6Ms3zy2r}IWGz=1T(2wY|!}zd$ zLUU1@zoWWGI3}^|!;N>)*W2*Jcg|zke$i566#H?bkuoUb>;r-qE0PF2E49mu<3AdY z{TY*e6`61xM(!@KV4WGp>GYYSfi(UQ%Nz1;`Z&h1XM*Uh(`c8Vb{Eyi32%K0-pWpU z46Nv|$scTPPWc8nIrhZP9Isi)&*om}@^h`k?KS-*b#wuw4xfDRHD#4oCnM-%u-bUe7fo+zAX9%{XD{5xXxOZurkHr>B@Ku~Z z(8ZEEimQjT!Kv!+!SHyAmGSE}&37B`+hae7n4Mew0XhitOg4AtMXoZ5Uo$JA2Jsco zVR~V{{>bD%7|vG{o5@1bw>TqY(J_qx$^;5w_P9b7G<%D-d_Kc>*Jq{F=;q9 z*jODr99n&Uqj!|{SovS?Lj>~va1&q#pMtl#3YB|S!tgt6DKjvGGC`i$H-BsL{`nK3 z%d;v;uc(aOS-yDpEY7Kw3vt?B#RPh`Yity|YQbRkVm?F?)20SwCrN_JhLA35B3ZJ1 zG@aOM6vZWyqOph+blb>*Gk>FCU$TASGuO*n4SU*)7xTEcRtPEe8|fQSkm;y~olAgB z$gD5*;YADvS{PLA*#p*A6>hFg5>ZW_nC}y6a<^}Zs@}ro*L_0lKJ#4uyfo=~sc|`G z#*PqDMG@N!wy-tyq*p$&yvGXayBrCjbFmi-X3Sj`xQ4H|jkQ0VJbY#M5F0o-9Mv{B zqZk3TpN=ZG?(+tOz9iCsTx z(Ss$=;S*Mbn~iJQLw3ej!)lOQ#``)sl%+1tEs1R{`_JnqCchReCZe|qEhh%qyOPb=iZ4?nRK8!VMFI%=2h+tfG$5U8F$6l^cax=X z7}niqn3A9ArT0Hn^_#G?sGcgU0b6e^p5gv{)i*(;1PjfTlgLZ z5!{=D>aE3wR!Q{lj7G($!`@IHt=r;7c675zCoG>FR_6A{(|iyUc&Xh{(kJP z#^xVQ$Ke4@z0Sy8!<7doSx>5&LrhS^{Hwsfyk8O}G6y#B185|Ul&Xatw-vO9*a#K+ zNnszXy3dp(E9vDw_cNQ3g4TU@<4v--d*fZSV7(6rx^Sf5XT7fOUq`zsOR92sl-$hQ$1DWw| z?WQN;m5KdwJVnB=YFW_A!jP8fdezunCM!1*fA^u>pX%4UTAojiiUF0Cg&XO6#aX4A zMlgqab9tpw-+gd-jQyMEox}aSeCjkAihee^8U=G?|fN$2sG{n zhzVF8DqOm6QVEdxy&&PX6sxkUa#Bt2ED>B?FnDp;e5cXH>)2Z=o)I+$-L`HQayz`Y z01upgZ^HR1vuB|COlyz?rgh!R+iQK{)%q2{(qks;#n8I7Pj%2!(11v2`BClBWYL=$ zVSCg#hS&%O_f%6-eT7z9MDE?OI!(H&Sd#PRfo1mB0aI?vk>{4i^I7f$d#7glYaxO$ z{;iQe!s#RA$XC7S^a3sm^Fu9eji+vntYVi930-lgpI&n@yT%W(I9sC%%&9qxl1;6G z2UOurs(k03gmPqog4LN&ea;Z4e(YG@;sw?RBD?F?zGl2E1QIR0vddbY&yKR-gg@#a ziOTMIG_bOk3XsTBAa$5ti-UkrJ7YQ?yL=JbDeU1 zW=kdZr}%^J-3^Q2Q}fUjY)D(|eZW`oU7Tripyex|aeOl&_rCDxY_WLPrBu%KslN#LDXYjA^atexP7ipW zHjs+5F`lDV0Zp6xgR+au=TL|ZG-|QklC8bp8%n9>Bp|b1kA63ItAfGW$JAB&Sh z_bIG48^xUqJh&R&1793t1~)B_skxjxzO5jKRZwW4bkBCJw_|xpKJeOd)cj~}+p=9S zXu{VDm$dw78WV?Dz{-JXCvZHB8W!VJ%gEZXfILR-V#%kH6-jmIoT{!dKMOK!h+-uL z5vPC(n~##O1mXUTPyPU*ya75nlo6~uz$YlyH;1V3P^rnH--BW=W4j`N#OzDOALPPP(U zaRm;goesog+tqa(abTWd*PNL-sb(k1G&TJ*Y9-(qw#NPQCHin{HNuFe5jaBfAYu@& z3O^oP(6RL9UhkgPzoc0zGXvbc0l<5Dg#efIXauDbTaA9zIng)}UBR5S2SAQT_rEgpBMCxqu7D*V;D2uI&9IMrN4VP3+1eX4o;4GzIQxP{;vG`PD%)9aObUs$F~k@t0msXlNN(ubE1Lh)h?Aw^V`UYy0$)1ky0a+oTZ>D?Y7d zs`yS;A8LMX&}ryqq`f`&_M*LJQ`jr>F%=>WQyk}0W zHg&wJT|0f)7M_Cao%L!duciU$UpR{)HB!~Gxnlq-XY1>3mfrwf3Z&|oZrLAdu}i;# z`3KY{8@LUI%jB4;>t!>KSrrv&21z6xVc6rakhuyaODNv#CS_ix2#mvd7*4(9B1*d8 zt$z$*$s&3FDJb3H?)GItOakqFO<5Ofy1%E%!aN}wo_wizCuUQLa8yOoQ|4fA?}bivyp~2=ZyK+_ zC7RF1AV;);^i9x98}O~8*scC5ibgNRw<}ym%pFjqVAFvI?cA-B`04Sj>Xf#86&q0J zECs4y8LRgQ6^tWi1h5YRRgXSETQ`Ter31Mg9UyGH6e+&$_*=oIZEl_5gGVa{CR?qy z>+zD%?i>4BoYEsp6L#E~AwarB*gk)X`^Z{tvVyEl*yl-KubsY?jig%AOazD1fWO0t zzux^b^+ox%Z`Cyh2F*wQnPzZ3Ru)*zU$InTDnE-9mlYl|tU50* zVzu@|)E0iT3YTaEgr)ky+gC1S2v<7w;kq-Hb&2%BUGz3I)Xobue0(&Xzo}!{AIwex zYo)Msm%N{Lb81w=%gd*%KMr#vK4eJekh251ctY0bBV#PE`h#2M9^X~LBf@Ii1Os-Q z8l{sf(q>n#S4YjpNZp=xzx3f_@DchIv{1vH>8CbP?ytrYo9X$6Db%A~<5?tD0+#An z6CBM3X`G3i#cW$QQL6R>W^S0ZFi<$*?)8>g=Z)YllHEByY;>{4aI@hF0%R9R-__3m z7{!5@jz>4+Em4BMK=qCtJCooCIP^9O^2hej%<;;ATyqu$dY5M}mJdlN_ye}))sgs( z^n`g+qpYK)o@uQ1=O|ctmjWn1X-pZVgOGxZ;JRWCb}s?YCdd8)Vaxn&PpdfRIb@;H z_+k$W$WI_JDJ1O-IYK|(?%L9qwJ)V*iTYQ4zY`Z`CwVX_QX6P9@qXg@I8ZDcvFRJq zCw%-|U&0L+M^>Saswc2=l_S2%3?$r4y^4!4HH#HNViI$fSvmktb`{9(1!FJV?$61@ z_2^(P3^#6mq*kEd8`9QcWKUWpb(L|bu-9z+#3+|zr&>8{%)YWzOkVW1VB>VG-jJ-o zTI&rD_}ZZAxCi(JKqQAF^V6}T73&cOfhpO{V$W2eL_n%LCj8f>I+GfIUJNd_3SRX4 zy0tbebU10)CtTSX%(q|rRUQAn0KX4c*ffH=f*)?7w`sX$_NfAIYMl@oL(8)!{lWrv zey|Xt*ch6ilQ%=eqLWYIMa6FvTpUUQJ{QF@SnD)MOD$5+yh88Y#1q=d;=@h$`39IL zh3rqKiUY|V5Q+$`0Y#i}fTmK2y^M8d{qJAWuoS$=WBhZ~@j@lJ)oQuu9c;sDrM0$S zVB)A~393^x|86heyEma9sbQ%sDfZbVc`{$IQ=zQ(Gh@#QdOmfPWyhYh%9g$av!G38 ze(FL0xGKE%SNt*>X?3`kHYw_W0#qWyb(ked0mZ2-{G?up8wiV1fN*yefWG!ly)~4x zBXg_I931R=7^p5`b)>GZPg&Q9SQkGG01s+hlO78Bx1eYs+wzZ~&?O3CAy_XgM}NOh=_h-h#xDXpX)$Eo^7Ip(ip5LIj}md(GUlj!?S4$yUN8|vxQfaGnbr(?Ap!z1v;52`U^x@C3uF_4+D6aRGUJbUG^!!JF>KGk1R>tB~rh5mWRKK8I)6SCa6SN0tcD3CeroHc0I$ z;72Z1$j%wD9>y*45(-{Ddd6j!V*z5%!t`@ngvdu7FL<@cgpra`ur$k?kp2o8Ba6tv zFg`-LXv=Pt+ujfqx@ZL}&U~;>5Ag!=;=Hg_6-$Vqre68FumC+0W0VvpSUT*}lUl!-rE==YcOq(@=$g~8lClgyK zJbQ73YynPX4d_1(&+?fHuzNIkzLu#qP&#D)XoXv2&$}1%jd%tOSx%gb8#NW*#WJ}2 zNG%7gFKTJ3OLGv=>!Eok;iz*yg*hlK`ztp4)xkcSw+G8C$!C@$@)6p2$j_15Zt6SH zU#~$~9I_iiZqv;k>D$rOr`yF?H;O61>NGK5#dn6)TZO$x&Yjp##;WFMF5Up>!12+z zh2S(AyF$_M(-8Lb8wJ9EHPpBQNJB3)PAFpcJ~F%3Rr6@;Mqm(K)5jIV4xSF^f19P5 zpzWBbbpQF}z`rJ$vSVUKkxqemZJ{ID@NUH2L~@ zO{J__QgqU|DpGOj`EtYwWrJ=(!se4mLsMMyq(s4lDY|liM1}j$zyEB1)n;X6txz|^ z?ak`J#Aj)w{owAZT-w9SK`thee7FFHg~Aj7tRO%?omB8$sLWucUEAJHzN{XK>6XD$ z5?7w}5&;Sg?>|WX?f_-~8?GO)Ig!ePj+?9eqdI*<(z@pWP}BOet!*q4vR#&w2MGJw z#|)?SMG9#jYloN^K7!z?K^yEPM4;n`Ww;55k9!Z0)0o}b+0+(_JJc6i$~fKu#>d}J z3t6L@fb6mZ)8}ufv+vcH4i8u6e0Fg0v zf9;u>>Mw*Wr2rgDceb}1&De4;;w@-CEyr~xjJ>HBb{pd^u_nNE*BE+5_vOn&C`uu2 zc%k=Bi>0@FnQbi|MO>p%tnj-DI(z*ZA)aEcp=<0AsJAkv&x2y~qnrLEC^mPz3_bX@ zOofE4wSzfo*z5`e71>K}Gzg`}geZ|My4(K!NA(ELK6kr|GV83!CjYxPo405rbx8 zxg+tgwbY~$i#rjUKPa?X)&}XXQ%KsOvhuCBlrkX2w?A;NH9S4XlP%KIbH#jY2Bc<3 z>UI|LXDYZd9e?N>tF(}NTjsn)a>f4iiGx*yaxFBAICOAz- zn%5!=bY~msm}m$RH(`_9d6ne^7j>fLL%=OSImp zgZy}A#Epv(<9aA${e=R;WP4-rD4DXlZU@0e?*goJR_`<_p_^Wl9fu@7e}VE@N{tLH z*YAm2pxDVeHcR=}!^U@a;qV7M(Vx3pu#pL$Ea-y&n9#|EfVHPvw13lHEPE{D?81*Z zk56?Zcr9sk@tlWfb~b? zyT3VvhYHe5+qJ%`n-owp2Y+V@cqaB~Jn$qu7Cz>- zVAXAqz`CM0i27YxNv$jS_B4(Pk#GYHei$3TcYhXz={d~uo4ak}gqlD@OG%)2=x?BN zd>z+z4UB~yu+S68L5A@Ix1s4^xwSyn#7gh%+-n&U>M`Q43FprN?Y-i9aINutd(|SP zRD7|k?AuB)%YMJ;xc(|M@A6DCCpVjQuKH-88Z1A{3?K62s1uwO+ghqqB$8#6phkQx zD(t6uU1e$gHs#DHOp@@aeG(J6jGq~bqtjd^6S72x83Z!+3cLTij{yBI5IgkH0+q2FEh@$j4 zWBMQu-1MgM13?o0yhJ$%6EDu;6q_#ko0yeAuHw>;KbdlW^4mo5|KGg$+`-AAv}aQc z*B~cJ@CEBTi_5ahKgqrzHKjz!D4s+a%@_nLD?T(7btUY<#QqxT{oPKEnv7s9XB&j+ z-=#xMRl_d#=aFV4i`%J`4o2{jl5dLO|5budGbWOELJBwJ!nj#pJ5k8M=La@W<_{m zv6qz;G#N?~LH5*ly?OWK?Y2#9p_gz>)z6uVo|QJ!QRR*8<0oTCM8c?i+j&Mh0`B8_ z`-pyhZ6ChN74_6v#$)spYh-z!$QVEk!X@mr0c8HaA|0)tCNZPysE%8@C6HuODS^>@ z>dzK_ag9w)dMZB>1G3&$a)y!z0*E8Gq*ms$d|`yJ5?lPd*U@6qzcUsaA`td z^#am}ORln@SxH(0s**lHzyKY3wGXIL5vx9}|1YRle^ze)ciW^zVI7+mbI^mTEAE-O zS8G*wMBD%c{ZYxo{XcFj!m#%ZTnbQ2JXnJ!X+10p>|bqZ=?X=@g=LOVF1PaUH5Pq? zqUCO^-Vtm7t=Lewl2Th3KQ~F@Sw3mbkSa9D27$Frn6mvrxIHr`+MLZJAs_ark2iY_<^ z_(vJ$BxkEmgvH-RP+(_q@H^aqG_1P~@Z&iHqJabXnnk+Lg3!OwBsKo2z)n= zLvnI<*U!UbKlX$pfzV-FTN|f zFMsp6u>*)DPMwUzZMBeR&BJ~EI zAyV0|fz=L+(K}m&q*r|8^|%XK$$fR6=aPzQ{bs6UVJ`wv2l)?~(jU0M7yXcjO|@$q z$WAo$W-wPX(Mu_u#r+sQocdcX|A$roQ z&*he>BnD_ixM3R6i7KR?CH|b~uC{U1mHI5okMTRXyc$@WO2(-&HJ|XD>KIe3EMvE2 zd+_=B(K^WkY>-4&by}KdHiN9AI}=MQho2b=eAFIGBQe_%zIQRW%6v>VcM>!zNqdRv z`P_|4rW1)4$)O)~v{02_R%~JNU0Muj1Dhsz5LC%B3`#CB_x@7ifwQ zdhJ`it-`R1%cy$EdP~3i+6KY6P;COTaib4BPr$=J@nWW${u3b{<9Fxpz9Cv%K>7OL z!!=1Rgz7&+|KCf-Q+urEHy*QRW;YT-ZKx4(E=LXu zF$tK(iWO-Obyw{-59Z?gUW@{k&&D+iE$lk5za)xM)cll>d(4E6gr~j=7r)8A8fAOT zs$4HI0HV}47w~3a>Z+Zzq`EDNDnXNDnSF7^yO|ABGC7dk zjU_ioG~ybv7F-cRfaeuR zE^rhYpm(rz_#NO}n_4GYJUEW0qXD3(Y&s5VpaKgpWos~R ze*@W#C$OCW^~n4AlZ#Wrtx$Owqf=9G1z+h0PdGw%vhgPi ztClL%&g*;fRXSM~eIN4CXYVdm@xQY|-kZmFbfX%go7j>GAfmFlitS_k$cAZYe?2`; zE;I;8SFV2`YcgBWYKtS@yy8=TYFFjCdesg9Q`+k2X5~Bq_zb-5ikkt5F;4$G3V^I- zDdXRiAA|R2STukjn{P0%?o$Q-S-Q~0<@I9mE)u7__1ikz z_eE(;4xS9+lJzk>dws7MR<3k|YI~Dwp2M3sVh&v*It$Jh(gu0OC|k%|UlH;>Q!_iB zhb!C}pH=VS>ZIAfW1nUA*DA0*BNN9E5f&HZ-%3|VSosUY(3fc_^Ob?ZIiq^XxwLI| z%3p7t$lv^}qmzYz)M%}XIZ3$-iM5vWLKM%lS=EDJ-NRq;vQ(j!tFx=yL3)`GyJYEd+ap! z4(M}EZhl*JZ|pgO2vPli;0Yx*Z;+;itXY33I>S#Oi;g(w$+kspZfVYpp8S5$dW@ae z1m{@F3XHW;&~8Q8)zpbyxgG19@V4%~=-~=IIzEo6IBgJbnCRXl92>4ndXMBhv@`%= z@uPi-JOC^lwdNN0uAUy=mqz=K~yf3f`qvXC^`pv8!31Z#BfgjLO2IqqQ>jQFau+)DGWc=|l-~~_c#Uqf) zKy_d?h*{P4cpG<|qDdk4?5MjW+uzMYR%$514io^xZ@dB=y@IGOS4R~R-z&DRUe%rJ zf|Q?CY&ADF&zPRmM;U#U%Zw!fbNFiAgSMT_TBrTV9Md8J^9&v$MeTl#uCX!Vb1|fZ z6J5mNfaQ;k_gMGD6_aJRCYR+7-3kPt3*SYA}R8(VGmzBFEu~m8i+K1gGDZKJxk|)o3Q&1E! zf4O4vSALIzR1L#I?&04qaC%2+PB-JiUexwlE;Wg~xmu3*b;;N+UfG+Qy8Wh*&SAP} z5mC#L`5xb-ll(I%3~3r|Z!?BACO-jh!&xgiOaf^dThgUKt=uIqj{&VTAA~TEhLqdA z2k4t1FHjkD&u$Yrxn3;RmcD|pO6wHwjqRw^2dIDVQK^@icE~LHT;yG@kXMv8z&Ag@ zvY3G|baQNz|CP}99b}DZrY-JDL{r33z-N{BpwSVEwp5(c5IjS~@+%h4inW^y?KyeD zM!Uj4z#G~GG2GAFnYsjKb4@8@j~7PuOr3KZzN(9LA%lC>lWLkKTdP~8d@8Hf!MG~L zMtU|n*du&XZ>?m5LJ8XvA)nMT99Gm^kt|#$OH=^l=H;*wr}A`tLWv4gh;u|Fo%BXK zq5COp0Fi@tR7>IsHO5hzlgdHu*OU&xlw2pT%}w(R-sn|$`)+$wN&cBdbz6Y=O8*KH z#~4Vpv;4a=k|Pa5D@vi`uwRv7M{v|_mJQI=oU)wK?Q@)9*Ckdu`%Fb+QGC!ZfS|lO zw+a`79*kewF$K+W3)@ZgYikob*4=pN5V+LZs&!#UJ*NOA%4IuV(QKA1A<%%ZxbxSA zRa8aT#$gcq;!F;b-J;LO`7y+L=%y~X?@TOFwwYZE*1QMk5@%PSb649WWDa=S;M1g4 zZ)oqrM|C^4%51vt3#0*&(d3~u!2f%;pZPu4yS3%DZFGKn-PCdR(M^7Zss&}7sV#e__71HZ7X+0fRg>Dp76HR{3$ye>TH?K^T(4xe*p=GxoJ9>KngaiffeX|YGGbP}On+TOPid#JRjoDiPQtSzX90Ff7)qg9 z%XG@5M`TV*{MXUl9BZ{J3TL}3T!fGJhqBIZuW&AFe;|5eVD|Nf9_(nw}|8pq0LB&Jt`6gN*ZMe(5j z`sC@aON&d#zo*}JPrkSBv{2h5GfC>Nb^`35o04-WK_&Id9zTi(IxWZ;2N`A<`Ndng43Xsh2+{1m2leOT5AZm~l z#goOPEG+-ae!i;;;^;0M#ab>|OSQl)X_*c6e=B#PNd0*swf=MVYY%co9o&oZusT@R zKD{pfio!`ECu#Ot!ExRt+AU)oSwK>)vZx|~IG9Zn5w!70PW%IUbpyUyQF%n4R%9mm zE%5X;N47HM@b2W=8bJmaywITiOcjsoqL_!R3$)Y=izQ7HoTeRI5M;@z(Cp}wo}N!5 zYBet3D6sW7_^l|Gw7CQ0KymXpetm%8$q@W-a z<>u2&+~Kk$X{P69oC*~ioUXn&2h;7%q=#T8<~@UlL8@1y2X=(n-H=AmjeX#$b&$Wq zmpaG$p(&I7@kH7&7}9ZEmHsuOA{wYamRBGYrbKCrQK!%rZ2^PLmUGI`h?XEBCBsju zOW7$LTptz~fV?zdGbLre#*mQ{ryfD+$G|vd!8qdaOG72b$C1*UYravHgL^F_jF7Q1 z#f(0dUpA|?LFn?bS47(2P~o>b(`fDIcdD4$)1*67K4kAg;wtQ@N^`VSbI?HoXh8W= z?QeKP!banB!9C+^j5Z+QO_{M)-`W7e2H>(#e@h0ClZ#`IL=M_ja2QlV3oBx@s@r-! zTH{Qbsb=R%nAz{GS4+&CxMtZ=>{8vmmTr0&!o9>Z<6++w0?j_qk`a(L-b7TiX%Rv; zIej5}K>1sku0Me`gj4^i1w-FbGR?~(myIZHl8&!?jl5zCg!$HJPZeJ9fg|&%nHdKi z3Y;*LWJ;-gT(G>X3Efs$M`!r04A~rWnM69%vw29l;=oKVMgbs@`e8~43 zL<2-$>;yvZ8sh|51|RpK!#3^El`_tX9}ScJ4T)Rh#l!S2@GHG(Kqzg6?fx)(w1h5! zBXPX8NQLWWjzu_s;cL`u>}B1A)SWFF=zW=Tsnl=GZQT7D0X&ozP%=QfI3eHH&^x#{ zV>wLOr(#X0*o^0@@hJvH5_|~nm-z@Y4LY_Tx5;(PHrbu%z7>EQWcmVJ6&E-5#)NtX zi_8K8`yd`X#6(GB*0Va37daQxH=1hV6EtK7Xl2FFftr6P#+ClDGybHMA@AQ6Sz^7Z znuBFospL$P<>g4Dh>T>rkjYW0>w!L#SsaSDsRQ|hKYzh)cJzduHaOR&9V3Mf*&Z2P=DZQf@twqNuNM&m!YCo

    nV|?GAW^!F z3TQ1&jz8fn*!wc-$62(HZV+ab2B!6t|KZw~N=TE{e4w>;IvXN<*O4wcWzkOUv_L+A z{%Nt1Bw}oNW3LZTGQzEJ4`BW7o;9UZ+xVFh|A0o7k)xL%6_u3Xa!<$RAGhcGM90RC zF0cv%1>?Mp3jM$D=V0jn$9?>_|K&_^gu6VA9E&5+2HlMOswB!Dq+mY%$xOy%vRwQ} zyunOajadga4bLcm>CJb#^N0*RM+OQ>;L{9mH+V4Q4iPBr)ZJ%M!vltot)Tk3u!9pB z2`RVLKVOf#RTkn0MB%`&AYjtQk(oXN%z}*FuqssH9yh-!-zWd+4KR9gAP&j_#CMW_ zSv-H=JMQj=tvP(Q7%K2EF+QQE?-X&FX|`2y$O_xjdY*i~{LU~aOY{n_OiwxE*PT^4 zY{Zmr>g?{ZsT|0liJsHpF^Z-#L`U}Rl;$C=!r05s1pSP>DwE&dkWjn8`0ZGXhxhU$y zhDiacRy_6NQY{2VnIAIp#r^7@QBA`2%u@Nb&TmKt-52?eKeT>Me1fTWN_dRKFDR|z zk0sA?38-BP+8os_@~O{!KAPpjlVtw6q>6B!l$7ByRO&^}ILT63(3ogD6bWmlRglZV zg&xRc>p>m@CHh zkF!CAW8OaqmlUi?WOdyIBSxiBwzRKUn3QLZLcbLiEv$-`lS;Xvea~&NMn@f^&-Qir zQf(UGMO)bZy?$DarlwO&C(_W;tAt2B028YoqUjkY*XC|k{*_-F1^Go$S}Fk<@$)Mt z`fx7Vy2J^0BYua17&C9F(zh1KU)9-z5om&@XeJfbG7;^W{9d^W^C&2o>7$ZQawOnP zmu@`2)u8li7a$zsFj|OzHmVN{V(L@tXdzmhc7$&y z&dRy7aLCk2DR|n;4uxuNiIe*0kc*Nrdbrbi76D_K9Uh>^7Oq28o5+{>D%C+XzQ^TOzeH+&E=l=m+}K zC6V1j0Zn7OX|uX4rVp*RZ0~`TOh8oQ1k}eLFya*+gHzXs8ZY^T&nw}U{>$z%~a5&Kn6 zE5UuMILB@LRf`5W$6TTun+v`3$TGcf;xVtr9Prm zLQi@D2r2l_9l)E4lpxMuxWeuYk-dSz!G}G43o0B^S-_bLWDeFZ`c;K`+aY^C0&g>| z1E23g0tUVqgu<96onO6XKy3I7u!qVZ_rJ35QOmT_&3#A(0_xPIT*;`kOs{SEDA4}` zVd%og!yi&1w-~=?9#QKNLe#5xn$K1Yn4XSii{2a28*%dOTF^R5_|_O4>33m# z;xQNN2GEuy2ByY979F;ANr*#~WY#tv$AY9HXPb|9at~5n^x2(f#mNyWv>6Cq11F(p zT*J0PN8;;Ra^i&fs&9A{SJp5>T>g$-UrM@MS z#2>Eu1C(>Ucp1aXvY2vX4A}!efT>-Raxk>K&6cnk(EZ?LEqFJ&l6laSS9%}Rxi_a{ zZ5XAHUKVjg)6pCD)IRYPu?)jK|}eljc`!!p$r!}Dr)Gxixh zjgE{IZ5~qgY3R+O`_PSXK&9+);gbc?kw%xr40mMrew0Fs6`>Dn%i8Ds7GdWOGQ)|w z^ZB7K->YRcEy5lT8cI*~3>H;fxER!q35A->!%WyStN{neOq+v8A80((`18Q((*CLO z*mYT?nMnB7-r0ArieFUU>5f**;f}dQKBUMABdlKsf(~ol3Y))2!?Hy8_ zxeCuZwa0f*fC9M%mm$8XF}AsXS4)%PR7|^Ri(PkE*-5y#?I@opI|dH3uPL3l za$_V&K~&UptCu4jUE1Iic1f%KTaf*Gg7`me`D&N#o*BwobB@MPAcro-0zkye@+tsA zJJhpNL9#o*cFXFselsp5I2PGXbI0;z-X8XKc< zY07P0;LL%{3jV>{>YI2@X3#5|5jw4k1$)v6nXNNWuJN+=6ZEv=r|B(7y3_Uy2f|_K z%fCSLa*)f!m4;%(s%y(|*zF>8wGaS{Kx&yGJN=9BN48t7-_DBv)7R1nDI3M(dlO3d zDRCLb*3|z~3YDnfM&9m4R$nVPgsz(qMs4V{?{~G!fA3M&;OiX(yUQ4JmnOD?%R}D# zz4Iw+8v3sx7w86mb_<&WGKVg?l@H)D0Zj0&#_W5Jh02wH&3oeFV=0yQg;DG(eT0=| z8JkSGW1NhRmFJnNCTS`_H?`6(J)B8hD@WpzAr)e7|w%Q2tjunrgXm zcI*n5`Dqrqv9{_f&*|bsdENE4ft=d&sqGN-I{qjnS zpLGuNA|>6=_~{7=`XP?l+#8;8S!pFwle`jj*2SJD=hPB1sWIFQo}64?5L~TW_@3p5 z&LB7O0gt&E^okD|CmJbjdu73aUb86~%`UEZ;YTU~evKHq%lAY6pES+S0|f|#RcPjf zS9k8n4*tM!K9i>1yK%c|iOtHZgVu5Z9z*{SkihF=+$YYN zNa1OieA19995ZbEiIsy;R75M*->v?u9N&U#Thvi`rTZ`miJxrMFZQmNy@lKAvT8v| z2Ym+Gw1NdHkDpBe0WO}^n>{EXJMgD8#lM;kf9q<<_WUW`&A2x!yT51cSYAXC@$m(e zQRUCRMOpDr!BX0-R!&k7t-2g+7jfhtwE-fLS78Qms0XS*XP-HRGfz57?{oB95XggO zj^5#m+*-SOH{5|$P*5ki);fQ2*o~C_J5$^HXwqs5a6HyWSNm~$G6$F>Vd@N54VEa^ z9twPpyItTI+qofHU8gZ&NS>w2pVPtI!^sy&x@3!8Sc+!EY&cb^A{Y-8xwesVEGuP$B_{j!eQ zOIz(V02yg0U@T?wh(p*!+CE54yrWPGfRZ&seqN|hc(f`S3>IX-kA^Ksua6EiNR`U# zA7F`7#}9R6af(5X%$KX^7;1lA%szs{E4q0Mw)SIiF zv9c(Q$_0X7e2u>kCfL(`L-Dn_`gAnhUdS`Zv_m?L30V4i(GrR9bh3Y8?PXk6UXjtp zSi~ex1X^11Ba^=;-pOb#Sap{F-cMU`(e*Z!U4CxCExP~_haib%O^mj$ zMz+hpj&B&LUv6V1P{57}2may&Xc~?;0tMq==*GXZ$8c|RcxXHLFA&J=_o9Pj&t+9D z6XFk4mBqIcfPjeo_p;VavKDtwz!e8W_yDAVIT+=$DiK0brfX#kC)_wxo#zpaRL2X- zKGajOGhi6yH-N>J>n00?YlI!QY5iyPJplxI)lm!m-+L6|<;jW~Yel!5UGoVK(m=a) z?NIqybF3ocE@#wHY`EzanUv~jHVn|XI%I*shc&stVQ}(stJrlWucj7pv=Ko^iu=IV zC|f!(AdF=1cz6!rvuoz0Aiu`8?mlV4nMI%p;}cSNqmGuV-XG+qoX97S&(zmg(vI@c zest4P;CG_5f>1Q(iL1Ztd$!aUEjSQM5V}U!be{>l=A%sLv=r&Z9B6kXUJa~r@(^ro zRWh@V-Cxl%RfxjKp<2DGN z^*P!sEXQ^fRlqZ*+G{t=M;vGbyFg)TR3(-a(b!#A<@US82mOsayP`hs(o!r_bmIKw zt*gkZV{67}dsX=9@7&)@wbZmGq%3Sk$Xg2%!U{GmvDS*S)3^8q z#XuhAdN3j=eUCjBRzSlm?&lCHtwiw^10i*kXIZ*zByPc?T?2MwEvL$5{x_*}3-3~0 zd_0Pu_eBXSudf~!n(0pDXHqX21j{Y}?qAI-sqj{47q9UgP!|EMwA_ZSl~IXI__%?O zrFyozf8D92ylPRTKZaXUZ}+q7FZ4G$01E=<3;_f3Wx4Ca5Nkg75V^3{gO+r^y8#bRhJB`WJ8J>X}MD2Gm%j z%$UbV2feKPDfT9P!T{+Ze@WXRyhowWkFC)tuwjKfP7!cC{g(C8TAQBc%ksp<>Ujy! zv^xbKSO~K{dKnk~+~x5N{gz+YRs54ZYh@iT?Pb2LhiO9Ke7{U3V?%hw;=wGN3$jM% znc}I6lXH$7dX%$PAdN5iGvpUymG}dl`k`6XYs14wY!b~O($!%&T&@D6lX*{U`QCp< z4D_U18>7!KFF18*?-{8)z*$tWODnufL8Xr#poqaXNB{1lzWChaBA8Qi65tcUeFF~e zm(p9A08-hz>^X^&yr@^`KvCzPVoOXJ)BardfCwY&&bKrc5qnva#D$mnWAo?inDQ?P zFj2mDX1OgivgX)-QnVNP3O?zJ>A67GqAd7Ps`Fs1DzZ6{{fJnJM~mVeGNU`JBxqb) zmn~lxrj_*YDX$B9_~%Lt+PnVJzi#&kBd#XFYZFjcR2a#|?#c zCy}tFJs1Kj&EJ;nb)oQ47bsC#9F*I!TmjksZ4{2|XH4bl;s!rX86Y>*uI~NLy2o^b zBlkJjuN4cY0$#bGmDxU0;5iJ>==)KsH;9n0Dy+ODQMczuXiCAM2ve%uG z3poUka9k&`CuC;Z`BbpAdc;AYNqEq`otf*6f6^mByP;CKJo;{o&LMss0Z?y+eCo60 zzYq@Y->z84E;48t;I63itfn?xF>-u`zjj`%wKad$NgXUKT3$hKNKi%gnEV*?LkGu4 zdV7{PlGxCKrkbBt4hbP>)S3N2qCX34BqQHm+uVZhygY(&NZ^WSrl(Db9V;%fyO0y? zJtXppAO7^T#Wsb_(y6$sc*qSPMUV95vN)lMFHWOSqyLyEB#Uc&%{le<3b!e~i}90V z>WSp?Kxy_m`Nmn_n-S9kyCQ`wafr{$lbC@ggzgmA+zn4TMW6rKdy8VizEaqpbf`3o zk&vTij%_%39gWxtW>MZq1pPY8m~lF4ZDvy^bj-DZeOekKPv>g=fRA$AI26-PvN{Zn_9xU8vtnV;Hu*?%Wm9?ybb{*{+yHD%XApLr3EZt2~m*yE9fHznJKdQK}sm87fPka4v7+`(ZuuHt_X1{xHJ;D3)(0Y9TM~ z^`1H1hG_7%Pf@~H+P3(6OafQrO|O1VHHEb@e#OK#XYMH_(lTe0C*!Ou2nR6w4&TM! zLJ9K34#^|AP4?-ZD#>+L+bJ1VB~ti1I|&EmJN^}7AbiLLGGOE0j_a2yk2H-HrG4Xo zCJWoT@xwEEc%s4V%s+dn|5KR^vt{VuNg;He=K?UwGSCj4zf0Y<7x^>os#->`dBo84 zqVmJLo`_nzI>B7FC+A3$tvlez8=aRaF|?4g>(~&N4G0!fH6Z0SX zlLo`#KJ<_0ugs;Rg&df^e?LZ#eY#Bsq`(K-SdoX=tEiq2y=@jA}+g`r<=D>T6+@ZA}<8 z%Fr#~VCWDZyc+uqoJ<*a4n)~mKw-;2N+<%llL%dV7b{o|=yB;rq zd#%0!Zvvj0TsiFnCWX4R(d%vglVc~{K9Xmw_^&%HZyy&J28i~ud}k}fOjT9 zJ04ZirZ6~CrN}D(#3N;w*cIK=(8iB5_jq#t`RIoNG8@(>J(Uc_^hUs2DJaX?b>P6D z&K)yX%LD87TIK!(3m&as|L4vhzyOQeFSZUa>IxO)INa)a<=x#rJzeSE7c$~Z9~-`< zip?<7&#)fXRnYn9(&#tj(KvKdCyrXU)Mc0|kiJlUYVYe#CfiJ3<+z?y-!>-JM~Jsm zeH%P_A^A0I!)VcgY%{V{31j;wh2hXvB$@K=$C~2hpD)`8~NOK`}HE$md1V&oK67z`0n?ds5-PBK&cnLK;u2V zRusD;9U9<9VH9$agMmOSLp(stNQKT=+zIkTto;kLZC4GP`QIefCv@b@^r$V}O_PCq z#WzH6^@1Cy>jQu$z$FW?xBb^s|DO|!*}vr(AiF=`szYn$aYVkOA?psVmvRYU>6W`5 zoZ2#D?;0yQFmk}FXIvTKT2Bi&x#zM}PZd<+Njq|y;mm^1oq-?GR_|2fU<`k318!1f zi#_mwfxkd>z&sOq%?Y4R;{F2B0z1ln55~RFOD5=+IOH_{kL}8^DB(89&Jy(82`(!f z4R{v=VdW6?4(EUIDRE9%cQ;@dpjDKJWe&N!1u*NzaLMhu`Fi^*yoMrZ;bRn~nM3D; zxLnE#N#n+1y?dRSns!y4?ZWJo$}KNzGQ=va9k{L(fY%MR=>LjfTguxqoBU;|$04BP zr~Vk^zPKn;tzZYtKu@2=SJu1UtmL?=Y2nbzV6$nou+ z2~Ji~w7oQTMg_f7r_xWu-PnAy;#eo(GPjx&>0s2ooZra+x$T8$nV#W?yP0!e5|3uH zWT4;}(oS-@WM6+G#muj;P{}E2o!iWsT;HDDe(_Zdw-jrXlOc{7F~y`{Gdj!eqxK4A z(&0_2c4KO_o>8QE-8Xy7W@mFtW^_qO`IIMO6px45t@`~jJXIsNRR_a`?-vEi$jlX{ z$A!c4tvw5HTAs~{1v;ysRC7Pg_p|0nc1&k?3#Jka3 z0;LaUbx1tMZ`k&8;`G$mai-Y`e7ENo3YHHMo2(ap-ZST^bNV?&i4U^yA=hTv49&y@ zixT?2xSuo2$4t{CZws0{m%T~g1#gS}jt!3iKZM+=`pvp8WK_3l^WcXaA4=8;d=_e2 z*XU%O=NrWYA)k7GktkV~^1`buF>9z%l<%R@@TnF=$ZU-&!3b1Fi~jX%?v?lf^cp>Jf0mRH_VniNuM-LtzwQfE#AKAWCbP1><(!%8R`-jvSR`JNO$>n&_i=>qH;^ z10zR<9CWQSXjo=LQAAyeNbv8$UaKQq2Gcn`PO6YFbEIyI(!F`i8@2dIIrJ+qpmt!( zXxU9*C#WtP`{4Dyz^60~bTjVvBGW=iNwF%%`k?pT=`wRCb%0ygZ6)Cwb_PsBtlE*8 z|A)G_j*F___r(WkBoqN@P(YFHPLY;|A%^bmRv1E2x&)*_y1T)lk?tJ2LqNL6-*WHg z+1qEIbM`&wzJ9O!y7v#A6~nAGYu5UHKk*JF?h$bm%?H`z)X^#SNI@?HN079}E$4ir zoxVuqX^Y#Y+u42`xd$EH+J@DHz3vk<(`{`sdt*Z!LH43)b{iVu5Y zkMn=a5`NDZ{=3WnVn)-TgaiH73m9xn8|>N?{ew-13+aI!vjQWB!TsB$Mo-w}^P4XX zk-ru2cUFIb)YA__{sScESGR!pU+6}2#d>&%mk40sDUX5f(6!k8PsodZd+%QvDwgwZ zIzxc?NA!{$@R4>~h_KocvIsc@*IEPTOyG|%2?XFCKA^UPP2WWoPJEFe9zuU>+0#PJ zu_W`UpN6^JZ)h;^Az$zCMavFs_7QY=47wBx*c^gu2pUx09&I|4C$&%tfIIyjinQzhLM~hGwv9MXXMkLPs1eq!Ttqm1`rUulGx>W9>0dmRn zyKB)~4I5uBlf?*i7B3RKtk>Ip_OaM(P*><>VNIcv1J#|o(w3&vp?ZzdRjk=|5$HSGO=Bjf6|R zR6>ZAB(c#Wlaw|~k)w`PSElw(WTPJ+GsLBqR^?n3nPkt{M%Qu3mnin-jS^-W2F^MP z7v**l6O3DFBZXavJjLMI@z(ZT-c?1qx*}Y^MuQy@+36oJ(o-IwHbfaan+E%u^n7kp z6mAj3y1>S|#}Ebrof7!1+-itqToXmig{eT~t^?@$+FlrzS36_kI%u><*CR;UIs;a82chI2OT#^P`#Put9eBj^BR>qtZ-^ILN6q1)R?0Pro#Lv0Lmv$i zR7UZB@GupOAx0FnBmnmxVVPh-FOT{rToIChFfXFIJ_h=$Bg;j#=OeRoIW5gLeT@GXU!*DXQuBcXfW?3yDD{sEd_jUj9>9p)?!*0$G9PhAj9OAlv604b5_@RP0o4xx zG&g|^AP!qa5iNgRbLCRm2fC}zS371W5zsckyPFPr1_Hdh@qme2`u7#ZNg;#W9o`Ef z7rM?E_?)cAlVBv}N9Jly)D9xXDXyUPD2$P%kfZ1s5ZV-hztwQp_JM;I+9Q4 z{3vH<-?HXZ5K3Kvc^W>jHWJu>|D=fL96qj0)DV^5;M^7OVJ1ITLFrq^!+ zQk^I{O($#F7)fbQQW{)`^m5`Yxy^+@C@)v*xa{nE490-e!z%V`bu&5)LQP7FXo&2MO0p6rnk0KT{aM=5`=*sq$-M4lD$`MU8i{- zu(&#P(5*r~qKk?Xz){K*gH^umG7}g;kF5GH2qX;q%y>&INyia>1h$YuWR{!kn|&}Y1?W?+|aSf1`%Uz62o&0T#-o1I_gd-#+9eS+XQWn{XJFN{kwR@*B6pv>dE z-oi{RmcXgr-TV}VWpuA;Pe;kd;Z0sPud<{NQ=qGJhMABDTB1eXtko!Su^sci@pC%r zFzVqEEKorSkl#@P1jQs^c5^_80nEjL|007owNa(zZDfiO_`iu9`&C0v^SCwA)UKK&xWT-9?x9odrhRP^BQ&Dqb6=MDm z+$n~gm7IMPl>SUGw6DL`m}P3+)u|-+)!{z)I_9XP_~}kibNtNn?Y_wQ{Z9ubj!tJ3 z`N))bBpq&8gAQNz)Lt#Qt<_-X)uC_$*)OKSof!AhEi%B>9$f|k{bJGmJVcoFwoPqS zmSS;6W|fV{$oiKe^*oY>gV-4WEe8}W^U;6+&kqWqVE(eUZIhrxJ||-i+*L$Q&l7Aj zB$KN)iH8$zh7+*!M9kYk&nvq1ry}OlL%Gh~?0lhZj{yA^&7UA;91oy&4V0Bmp?_ID zE6KHH+nuxJEoTae2|Siz`_>xO*D>)x{92>YcP#SQmq~x9>;!=hlz)Ev7L$WCdLOis zb_r^lYUAM+pA*>MIV96M#qL~(OqNnA;qRnT90fJHJ!=#foRcP#FymUTc#S$>*@`a% zqExcZ`JRV4$7AIIIJG}Ik4kZ1%)RmAy{70Qq-fr8aUeemz9*A8AxlOB^4ie4mp9`l zsgbT(Q9Efk{w&>Yqf=FZ;0^J?tM0WZHuicq;l1dchB5sw4P8e|A567K$$Gc6Ga-J4 zRcU(B6;HI!GmqQaZZ5a2kB(TPgkEtWdx}=~IUK*O1x#Y?yBB6i;3;b<#(=q2srOP3 zB~{}DtZJnxW!`J7wV^6eWjzdkyHw4Ft!)|Kb2U_n%u=(!_ejArdS`ps{bc9jL9w71 zE&evz_XqB0Z98IK6gY%&S(l-&r}b9_Npd*g`y5@u)loA3LF(V5HOj^K_}bbET`tFE ztLi504{^F$A`%^I#}=w3qu2RRm07fw%T?X|({)LO{B0^mMzs?3Sw@P>OsmtCRk+-l z^Vzf(KFm%Rt>42N=RYq3Umqm9d0AQE4DB53`_A6`ZuFHre<6lV_q3&pP~YPzW!h5 ziSlRM^Y32&3Xp(#kI_Qbf^&?zC->A@V83b46zOGa@X_KG* zp0^C!pPO{2c1#6OO*bTN{( zuL(WHNk?20mTj`;18)I7EyA3BE{YXP+X9V_?Ux1Iu|KmFWq73hU`&Qu{6RHP)d&9@>8-;1$OaFR< zxU>C1JYUzlf?&crd_mG}4q?e>(lspRBCi-ubBbHus3*&eDJ-;9>JFF(5wFImk;cbJ zhM5IafQW`A#wt&Lf*#Ae3GbJ5r$x=rN^lN5tv`9>YKl_`ml8*D7NcG_2?+%M;%4Fy6_x^4qcEHjdr{bi}{U96LMb@V7>`vEbsPwl9 z7JKQzypq+*pxo+|0mCYz6(#?@pt&|hTs-unQe$C@PLFArMXhUyrJY6X3npv>McTj~~THi#_JL-ODR3_ylu~-V_}a^`%n{7}b#c zjEF^6v`g(LAr2yZQ{Ugqq96I6+oE0U>7-j9iQXZdLT^d?fywf;NRiWbx2~^Uwrp<# zz9U-?e$jX&!aw@w{e7vSQ{5;=o0>wB=0+OJtTv4mOcyrL`=Qjg`EuHcd21 zw{)MF@te~~j`bkxY1tV%z~!@!4P8ebcBeE?mY=tk16rfLWbf9I&WO1gGzr3yO- z^J--|%G+fuJu?=6m*+{SxS9J%yKL`_3ONgOmPHeRtcrI5YUwsvm-U-k4`>(nwhc+f)6$=)n};#(0Dy`~UF-(xHI5S#2S z|5^IWmine2gQ?%w`yGFv+k$w>y>VZ(umau4ZMu?R#ota)64&1jS#EULJ6Ch@ve6d; zvM9?S9PamlIxTNa!XakyHeOWU!d28MN{%y;JsBepsT!d;c$adoIriUhOjQgq>#MMs zE>*d^o8*1eRho=?Q(-gb#({OT7C#99hJ)WP=cC{P{0qZE}Rhu zQXJeH{q@RX-AKdS3p2X1Zbqn`6+L8q{^!!HpFzSRw%A8tdgQPlP(OJ4vf$q1I%YtV zM&taY=(5n(o{m0nuY6v*d!Gl~9)Pil4qV}gCD{dfjy9%qKe>TLI?a@cmof$0^*FqSemTxZrLqZ^z0t+^iDv#On^v@^)~!v$E>!ZsHeciBI|(wDPtN?Bk4h8 z7+jG?UKT@lQGv2d{x$4k?czfnV(%v8VuX7-+}>`)?|3^b1d{vuor|`|S4>!X`&Yto zeP*899gI*nGY=Z(n%)PWhTPe&WWV)MwbyYi@M;4iL3oXxMzQGH2%KRq0dZ*?)v>oU z)=0|E(-`70>ihU7h^=FBu*S|{)p7bO)&z_1hUK-F&4b4JxsV^mH2rsFAR~1X!EyFTz0rLMZv(+(+YGt zed7T`Hznrs%QvgS?9|PWezFpYI}S4c^Td+C9-%Zt*EoVoK0^-B7Oh3d+@!05G1dF2 zDPC2Pyuumg<`V*DM%`)-rZ9p!CK**UujhpGDpGw5C70+Bpyi*UaTu7;DZ=PuzbPHj z?ju5+rNKiuo)R`a zeDbg2rP$MCtAZ5vt84mpJX$nC3d|3RYn3=(&m?b1X%irS`@SH(Ho4Hj^uso2V}FVN z*!z8;)@;K!0Xxu{E%_!m{DTd}SHt9n_jf{M)?fLNB@D(CGRH91cA#Y= z7aq?4EaCxn48uKus%r{x4}m^SXVML#WgQ4l6r7+Bnz>7@7fFfYJuY~wxZA1dd+@`s zk7ZQCG$@eU)0oG&Y_jtAHtgbm#Z9dzo^zh_OCH;tx*HUe-93YLVcL_b=kz%p8iLHD;d5Z`iJUF?4jaZnp%} zvk|RPUZ|$uC1n65i*-CNpyxPfr;G+Yr%M2;mVb9tl|E-qxB#N4)66tk#nyZXI(BnQfZ_mJo9%(HAzeZH!?Oopt4u6NR0tx1iX8@}(^0(!NULgr5 zx?-OA1dsMz`9yqK+G_1*?@g$9RJo~dJF)$j<}#X(crv+jlbP_`$ZDE5cNsm`SZKpQ z&a~(t@}p_A&@UX92FNmu{rHSp3t&dZ7tzxL*8Ae+1>1K=Y0T#v;G{=BMmk6 zrbdCy^jry7JDPe~TB|tqCc^HA9`^*-e|Qom+?6@yT3=XRDCDO`Nm6cMB+p6fJF;aP z-V@s&iy`Cvb^ZU-OAOW(d7icjt?bC_Ij_H6;x}!8lYX2*uBlC(9nQGul2{pZhNLQP zy*3;ZP!Nh_s*KVQYA<~7zyq%n=~}r4J+smk!qWf8&!ukB(ddFNHxJy}&rSN9qhIXB6(cwKQ$Dl)blhuNR*Z!r{C!0j)V?xR8ha9!zt;EE8 z2m)qk>GJ8*BTav!sZ(%eWxNcX6=B_=6H^FC=r-pgw^|4EK3B;-%Y*g$hQ?-ni9`0n zyL%}J(`gB#vfekv{kcBzT=7dDY3<7o(8=77;)lF;>R`6}qhl-UE{o{E6d}+7==yJW zmj*R3Gb$YEN9J}I+0QXb61gX0=QPls_z7EY{W=RzSxVy08NixKS)Cf^dEE5Kc=aQ>)N_4 z1Fy2WvH7wCu4+5p8yeZ5Zv*D8^J8+F_7~;=8^PaP$i3)n_#acA^q=Q4fhfDXyjwm0 z30iNWX40c|uJPxoOCT$43r6{PT|{pS{oB1vkd$K?`a! z<4^ipYniKUQJ@d5eQTToaxm*?Pr+5YIghU&zG#dMPi>Vlh!%nY79eb zi`S@mu%JX!eC-wTa=-{lM)1Rp{IG7w^bzIz!uiWUz~0o~g1M`t`n&{nz63um)@q(a zB|==hn;$*DG&f|mHva5Zv40P`C($3-5w1Un!$Bb+4}riTHa6x{%!gY+dLP?Tbx`$U z3f6H3_-KR~I&OuhNenber*D;DHKNs1IQ{1et=};W`cB-hM4#)v(aavz@Nu~FxI^8z za~E2ZyYwm8(YgCtnLt!E(3mrE3|9~ee-L02brg_I+b0ad#zeU&4OJNB#$kUe&rp)u zITyaSpwq)x{+c*iENY)`1J@CcaBNi8vbYIy48S`V0I2#;P-4#|r}#8i|DBS`5tdee z!BS;)oqL_)^7|DUtvR}x5WI`eF|yAp@jh_lD0S#;eZXgZx+!e2FU#F&8?Eq2@j0s2 zJ>oS6v2AHSz*jAz4pFCciW`q;^36-L7R9A|oPd)vFTF0Gt*?z&BO@P7H%CLxI&Br?0v!6M-n#Zff`L|t3;oxO({x=F}m9wLEqT~B4xfr#3O(nR5D<# z_RCUk^WmlO-s>M!)t-^90+Fjqg_RBqG-Gznu}5O}!2CEx23Fs1HQE0mgS9EXRgFmmvG@ z9ST(eyE}PWTbtbS+WHd52mF$%9Uzw|_9ep1zo}-}l8~c;(WwJR#?BGqXBxL%c-3tH z4{7a}ZZ4l5WbN*)!Np9`sp>gG;<_$Th2@DmR;<*3H>fq~vl@%<9qi6k^!mP9myM!s z-zN8yUdCsf`{3P9uA_T=)b*<=tbYge< zwp0VDP(Ji1FqA?tL&t#N%h#A?itV@jUZk95}32>!QX@$@i|uMUT$V z?{0y#p$-U;hv%s-et?Au8g4_*(UhXY=0^s+lb z?Fn0R#7**4<6N1O4{C9RBn^Lz+PhcbDe0;&1N}HSl#sa&OS}y?yH#qWl~P>Dty@wH@ooJ5kFT;dT+KI1b8pY;413mJnf?T6hKD_L zW}l7@Kq9NqhbwpqXFCU_fpT9_bu{ty?#xVv$Sc6gb~_jVOD~DL{`6ZkpdlQbb@LLZ z4g$l6(@;II;|YU5#=$ZTqAW}MBY79mZur(0SAEg~C~ z5(XbCjgHzeFNjT=YUz5F)sx6Q3IB}K^a-DDZ>%my956P$9>48eh#R^NIav_ZsEM&7 zh7Z3;5uOQHaBHxLIE&-pk@+q(ISeYlQuJXYQ=Q^=t!>l;L;BHfysSu1REVOn;rD1{ zsofca+SG-3oguV#ZNfM+IDLM8Hmd_cV;;pT$QdIcqJ*&%lzF z8XFjU?F#2)N?hDTouA!{jc{4aCiRJGdTcy2uj}v6`>Cn5TjZQ`JfzYa%rs5vKVAB? z4!G&z63?TSK^t?*zP6@R(N6F(idNL^(^MWJW}l^d?N( zm~-A`!jU-=xY4*?VF5Y%;BT5eypyNaRF6=Gx2Q9pvn+3o;W7kr{+^ z|6Z}@KU4Af`!>R!U7f*Zfm&GZ;Oc!no=tg~!Lm6P!nd&K3xNU}|F9TgMmg67sWIg8 zFU@IN+JQF$lTVvN1fBBVB`tdvZj_jzVPY86P^HRHVxlm zww$0miXT=LHnopr$&EI_QT|kk4o}g0d-}A+gr#Yw{Fr)-EU-E&bi_&9k}}&uf4G4#RwB=sz_4Hp9_AiZ^VK5_DiO$U^$+cfMI}=_+q+^ zmxB*psttz%(Q4DkIzBEgo;Qf4c;Dg6Lp`{J6R}``Jh3C-aW2JG!f#|L`944R6Akry z_c(OwhY^XiYm0@uFFht~SAsTWcxl7q*714PXzJIG4prg1OjXP^#~2n4^=l%!=?7^& zcd^4$ezZQ%6=D|Ysg$ZMjcI#G-pgf*1QHXRjen0ZO|;$btcW*t!Vk##dW24H0V~n^ zmXm?;z8Y(+vV+(PHWih{+AZRs&$n6hH9A*jlyhe)Y$RVR*k4vm0CmkzxNx5UNk>?q z?|JxIRh@LGQ+PZbDzDFXr|vh`lS%({qyKjum;Y?v|AP^hk$!iKCtMD3Ji@M1j|nZ_x)I`w#B z<5~w19#h;wwwsIqJ|$i9l(jGy7oZP2JOI1s1Ef^VJOkBWV_YjPwsZ~7H*)*iY>J)| zJM;NlrH=PqY2$jeKJuFKcFwV6mT1oquhw$5YiGYNqkAvGLD<(9TJImj?nnG61$>sm z0hxifF$KudgsY@bD|cc)@^2l^aj{u_7h&Y!I_)@r|DmUJe3KH&C%wLsdXOTC`tloc zyY6vW()xx3Y$OtOfbeYn?yNlRDb_R>0t($@8x zS<{5d7L1Xw^%a#vvj2wE%nhO#Dlq+!-PIyZdd3+E3(Zm5=upFT=@Kys^u_m~r>`_> z`1p!Av1$kwR;95pqPlZFYMP;bu2_jw^%7Nk-Mn-zOT^|;KF0<~&Zc+p7XkJtsspda z!YXWWT84aHNTtC}j(8D*2*S`T#?*&p_erK74%PbVrL``jlEFcECV@i&PD(XlU3TQ= z++q3Mlg6#SwAfRA;|T~~0F2fHZEt8RgWs>fj&Dp)Xdx_B>t)Y~0f#&le=@Y%u%gJp zsrG%tIZmr3JS2EbtSigt#0>{N5B@whj_`f{>(4KfJkI5y!@!lgJOsG(^0O5;T8XMG z{o0RdZ$HF%AL%^SdHdBT3NhBQ>B#wMEf6s%=jxd%SJQb(gMI+`-Ex~BB1D*=d&^K7 zpp2fMLpxU?l4?6ucR_!lHXlnM{kBV%97c}RWi|PnQzBoM0WQxVB$JV;5^#U3fbvWF zc>`>l$^{6}fgrtW$~>pAYqC1IsO2SDk?h;LhgW7_M~<$bY)}03sbGEcl#CMlF3=H? zEyQ)?Pf%#qUsg&wzGdZFR$9%aoZQt~WyTPSRqih|xl}yI;=E|w5=uEQ2`T!^(MJEW zHbQCkdjR*>ofDe)O3uN=6{(_c$cW4%LFg!_#@<*UfWe`Rq@5rzCZ69C2G;c8?7@G% zimFPeTdo^#G?C@2k*5_8I~Lr9o#RviGGqx{NWA9*fciel1mNWL8Mxw&qP0K>p7AUX zpc?f2x&S2rJ>{+nXpM1;-fW5@SOSX&(4ZAHthoR#@Un3#>u?!CC}@uAGA~_gWgBTgi=c~O+kGq^>LxS^x_S{ zhiTPF{d?ZG7XskWH>jzDVJFrvP;5MirlewC&|qthJVyUfCNlNbF3&2BJzdcO526Qw z>k>a}N~zKpL=JL`<=1!d6IEQSS(PWQAsVxLHq`4tjGu?9G`mS12;hH&yNq=`MPzHT zC-TO)AVsItp;xqVm^4{jAUkuQUWV81$8+kHGq|5}Ts>^!Y={rjR1MjSoqz9$c_7Yp z(i2h){iAc1S*2MQyw9XGSDFNVQ?$_ zpvJ|#D2#$AJ^oN?2&-wd$uj;zVifZF{TwLFZbQb_6#7^{5!vglxZ!Y>TleAhSptwQ zWY*lE4i7pVuZeC~0?!PWYq?v4`)Fspa=oUqvg5XTgkWF*!#f(07Zaj;eQ=;@m{#w0 z*<<8Tx~OF^GY}=gD3$OqFb1hxt`=|ON)up3PI*r?c)c-s5x?-gq_*N^!`0Szt2%eu z;$o{Moeq&+S_cN1AyqR$ZO&~U;YQK`xEdQr*V}DzLDdbsZ;Sr0MySNhNr=z)L99WJ ze3pp(1`;fcA!v?ffO%7$MJnNEflNW^p<+kzv$JeYTk^3fa0IrR0fdn~h(ukg*rl96 zRqVW1$h}18AFRaxF2?xJ_mz2GSfK&ogq5?1b`E=~NG9Y8Y&?JYIl4(^?B#X1DggSb zJ*$)Tqep(cuMeOLGo+$_f&#UnSCp~)zs9W$kw4e#=vy=J_%4GBFDv^yj3E#kh^)vc zu{JX|Cgn@7HHR1^s>l_MYGKWuX&vFw$?6%L%(}Pz&TkW)s!#mz*2Qia$3tH1BK4H0 zPx>LczXFg&FVWLSVkAk#_%`0vu^@}c-Vmm<2gH*>!l8*GO+JN6`1x9=vsqL-Rz6tm z(yAnWQ9eSy`UOpCleE{bG;L7Zm4s`?qzLVqXBhYQ0;44G%uzJNt>Zm1!!C46a|u2U z9KagU!&cN8koW4IFXe!=rus_5-D1PK#kLBB87;}Dd}>o~j$Axf-}qm6wo4%aC|=u`@92 zo+2J~3_o81OXk$U6vfoF_h(aWHWsRjcT{@m^m})QN1t+=V4>lH4$XM!ceruWdc(a= zc}R!}JYX~$LG|P+g8P6K6kb2ITBo#?k}^H+%MestBqkh2-lTYAycvzUQ2nT6POSK( zIdnr#*XVPabI~~0VA4t?LWJuM@l^sSm`Id8uUGoWxK^T29h91Na>bBiH;gRAPjkHK zCv3lkkcg)`>vOn^$!>T!-~EHTplXtPsiZe?5aw{6<3)7z~*Odg|Y$&0$wj3mi;)QI* zAtS|k989ldhYPNxr%CclMvacpW`ZW;7t$p4k=e}Jddi+B{a@qXmKS=b3T>qSyR*%| z7-Ji6|HWL`y24fT>i%T{q8(_aWXGTVlS=WwGHUsA|6gS?CmJ(Et*H+1Hm&{wJSw=3 z`lZ$jY`2j!co^sKE;EE(5s+zFALi*st6IsKTmyV44L zAviUma;2Q@H8goY#jOi)gOJrmZmQ{CjU~8M3Guj(!4Q!Q2rJCN?tB0%+>o->d@I<| z9S|T*&jA3Uj|J>mGHP9#k5$(FX!&SOUv-)~O%trRQC$F&2#gg$h^um7oypR15bs`< zY8P@pkPIUKr}##Bs&V(R*hzl{Ra z6nawyT>?gDEETWE*-IB20OBySK8b$NmAR~iPea@X?~jeC=a<4jqy@u65VFYEPngZr zGPEq+zMX+iw<4sH+{l1nuMe~yd;jQK4FEptf>~ zT%B%N7uN595ihBk_^>t;JP+4ewi7xp)??J3YKDI+wYS$N{%(;r1$d+dS=}qgI!M;E z+GVeC2Jvk+_7~8^OIV*XyFQ@JHo^)ZjuT}k4``r#hn44(XLX&^$xHenD61(6?@U!! z0wtV^|4P*x6r?nwnW=^zz#e5#b9aPCNJf(Q$r-h9zz>vCkeflZ2*yZB! z++c3Bj}uX$ndjNN54;a(?B4Z#RN+BIKJ?j~_r8;GBfFDxxRl|>xD|6Ij!5;HuRIMKVOIuKU|QmGthM{0ZZDNB1cF`%jtaqRHHEVSG2xJMsN{psQ5AH{E_2^0b>L4 zmk@g7^bc*`C<33Z{l~MC4y>>vX_xrt6+O}Y!6mJf^sqIAZVBv^e@~|}18A=0DFZ(T zqr)ApH>iP2@^d8{wiE_qRL8vfQ~V~6xF?DlD(?9r^+gIQFgZ{`4z%YSh)nfje@QZ1 zgY|)Dh3YyFAe!6})fD`Lwe{yv@;`o6oAkG%JX6PijSHecsAQQF zR>W)qV4O}vtVRyo$*z*B^|$|6=0a84*Av{wLx=Cb-3Gue z&IbnhLy`h(%9Yi)_AL7=n10=|_x6WhuOFq5_Ept1J}$GTZi-Zdat?%SxA&fq-zH=F z%0Ay*L%C76$yR!9MT)K3XpKP$g%frC zf#UcCC3{H0IpdYBMI{8&wtqpIqn{v}Fx=zG6R#mL^h>8M3W>}Tt_u0m*^lee^s$WZ z4c*gY1Gl}3V%o@3J0C3cRj5K4dMhG4SzY(MmbH?IH(zI>nj%{a@zYv-^&0X%6BrvN z{CVM-I!=NX4-8e8B50s7GufNC_DEades`Dk4xDQWINw5pt)>)aBYgB%OH7Y$%c zuHEp+XDk2?AIBA9BdB0-x^IB^I{g#$N>aj%Rw=Ka{M?2~u~O>$_lOTq{Efv?+z8D+ zGsGL;^N&%o4w}A`hfV|fZ=A|D4~AW`=OOSSl4tjriclGf#msw8QPSJ%&6+Bu-pxkWiv9XdQhDY*;R2V<7SM6-_oT%#iG{=tYdLmrtEWcsKEgK~3%wTJsOY zDIvHbK?Mt*WgWS1IJocV-+#uJTz`vA<(*n$SUE;lR~JSr`^XS4v-f#}u&l6+)ZeQM z^$4j_L5}B*wBy{26sp&|J|gFH$8;fF9FV?BdfSF>aiQf1;XUx*WTPSfkd0rl@!8brVN$tzeWHVz zEjdrj#ai#BicQWd>`jhEv{x>iSYlSDy-PZXNU*1~vW+H{#aiW=*K^EkKqaPZJxU2c zOLduJeaGZVVZWtZ5x*_XUF~?^i^VKX&87*Tw}Du&8-z^EchlWSDuBH3USmRZZB}%z zS@fFSdh)lGUp~En3ZF3$0DU_IS|c+&!+?H+?$qSJZW%$Ffg;Wr@rPTR@V4~`{O=f9T=#k0n9pUb^5f}VHPKd?6;8cF6k=ynNAg?pc8UEji%L$47qWbY-_nufY~ z*XS5NS$vW#%Me4;bv6`7@j~X+a4uT=pq0+|_n=vg=-6!%FAR}Lj7HLGn7iT@i?SAH zm#!Xgw^u%o>S}*MjxVE|vQ@sCKW}xta28&Z({6Rd#CpFrmAyK z#8()YvLwweLlpE(Db$cl>xOkFV{PQBZv}U9EQf2|K)tqPg(oRk8c~8TG;+ z!k)`uR|H{$cB%f9bG(^cOWjWs@g~S9gErI_$4kMh*P~+ zS9mrgXk|D{lif*zT_sp$k~h$q-ob_R(nnsUw*Ea!8kuDuqfokOj5=*>bc+^B4>EJx zkWaztg?ic?WY42Y-qZq)9nJ1sC_`Ish_swyCz5!mY0m|RG;~&7eU}nZs+OVQI}?K| ztum0fDu`(7ONEHH)HT}(g_7|Wh{0ut`Fr%OgoElB=JzV$wJAY-7y9D$_!t__%GhcB zCzLIo$gyfV4wQ6X@j0sQf~K7`<}jB;966k>l7`1hZy5_1;aZE*&Kmk?K{g-Uu^h4X zU7|!(uADT#uW2>Qz9A)Is3j`A&u-#(a`rs-a#9dKoF_j$hp{^HNd$9)O1$~DDDD|~ znyuukCK9b>jxfWU5DDrr7?8OFWwufP_4Z||hLKes=#<~70q(DeP@M^Y&dN|Sm1Smp z#Jn)UMiTrmn4D!*5F1d8e}Rk!3cwHwU=$eY98nUuX1&xPBaI!z7YRc15qU9Lal=;NuvThhz6Im6rG<`?a#eHZq6Hf744a+9NyOn@q+#AL>HBD&ugI}@pboaV+ zvjdL6et->}D4d59BD-~4s5^iodaoKg6c$LJTnrbmyDLayq3U+Hn=X4Yn zqI`lplh|g4I0VMtSaN^;60SJVPwVT6L;lp`8#Ts|<1EnlcRND+JZECf=&Vp!FZFA{ zi~_;K7kcc^!bLySKqgWY=t>&ugUB?GP0gRu(KevuUqv{gu^-C5S%GXpW|$9AYA<}{ zD^hC(8rgO##6bDT)6{BvcTmWEz#+=K<1+HKyevzS_B$1RS*6*W0aNVT{yN4s@@Tce zq8YeVo^pL$MlFSodAjwA*YSr0R>#E09VjUUG~+ZW78I7i7i`GkzAI_*|C;0$F+=S_y)I0; z4C*>qt`&FM9Hb6oY(0wWtGXxQ=X9JVWzD!i^d=pr!>|stAVy;vBOb@{?g1`nEzC8) z^z_a^t)V&wS}|AB{Jtlau?ZM}*9%YLb@5CF@jQ%}!>g0D8ZsfCRp%{9cbUtQF(nP@G0@OIdV^8{xXVc zVMj*|4?M9>bt5)4Nq`h)|Mr#f@HseP6Y6mz_uAK2`m~HGp-V)l?x?%K%Ea#c^Ozw{ zAyIvZ2)Z;wj`YS-$ay8Fg4QHwjaYAQ>#iko+SoyjP1Ayif^j<;V-2ljBogx=NJh&h4dV?3y3#KH;AN_U|A$l;PJ**i7NNzXj zH@iT;B=Yx_bPG3%{cMkiL0D@Cc7et-8c%X!o&{*75^8;bf8+0Y z32n6QGS#=PP0}xV(qyGBOCXm+?S({_f^-}h;L>_1MtZ7d5^WYttK6n_5BY`KW#G4K z(jfUgO9z^2FLt4iV^8;m3fGD38AUsZ}@hG_~u(pm|~T1EQ=5Mp{%jj!wf6rTL$UInG{?kqCZ z2c0BlsWGdSAbuCxA6G}=d7Fy-I|qDwzwEv}yu;iz!6Sp@nJiTO+J0n&H!rrR)8>s! z|ATVJ|JWPq4}~_u0ndLrL~ANNzRvy$a#cqDy^Qi_8{uDN(*CtR`VR=lpHPnf)hoOG z?~KdB!He6sco)(q+&aH2r|NG31kJhOh4Gj|($i~zsdTa`#_79x_r z=~#bRG5TCQ$P}2rClLic69)kHo=RsW#;B&2mjby!$<$y6sM?OG+UDRN&aC!Qf8&r9 zG&AJz5;Bjh=(^j19i9LLG3~V$WCCq>Tq_Sop9t1N1;BYK{niF#Qz1yaU!4lR*1$f9 zufmHF{+{32`xGzPiW)n`Z9gqy-^_-8Y9^zez5HXt6AzQHwOX6>mQgoh4xYvz`<*XU z?8rGFO6bX(A1_ruc-y_j7cmxZKV2WQa%bT184P`Bl0PfqVMjZR{f&aS|7i-9vZDC8 z&}4df+aB*7a0W+(bA;tp0A#I`_rdqDdkJ*di3eJlj4{rNxcntgWV`OAG{p_2+P4;A z$_PC$_l4@X{i>G&kGa!rxHci`l<&A%Lzb`9(ACVXB|mGTQS)+*BJf z=_9+lqb5xovd_ykX_lq?(eaF_VIWu3nU^(rcY#IPqikdnE3hz(QL*4Il2Q^l?`g$B%x}R$_YKS#Im_Czyy~f&taL}NN$FUO9 z_WsJ9E-T-{J|;L*5|l#YP*ZJ(&!6m(7+$Egwcbr|k|YoD0=@>I&fCJe?&b?%=x%Qy z&}9ke5g~c+8^`=eKt&{)ygc#qiWaXz;8+=uSN^wiOG16b-gg1F!NozuD}`tCYwk#V z!}f9McEy9wvTGmnMECFuecoiru$$*+!1WX|bO#iMXTDVAO*fZtEFSi~7uq4=6hi1) zg&hx9uko!#kR(eEdu(Yo|1sOYo*buxspSK@a6YnPNPqpLMJ;J;&F5&Q z5rHe`@G(=<^#}LXc7c{;!x2*5v|;4_iYJhwC5N;Dy$IhG7R8I)7> z78b8!1-U6k7`~P?hdq@^19f0P-dpkje)M_ueix@aBL~c+8C({ztJu3AqNh(T{l!Qp z)M(tIk&Dp4zqC(Yoc^s|1b%+|bk1{K*BY3a_?m!HeoY-<@C0pV1d5=;-9W`GFcgLm z6#voUkA6o3Uf&AWKLp$ezzf6~c(h}__q*$yb*+;=<>*K`VdHi#ryX>r1DwDU*@{rb zX$NK_FFl%y+O{OA=&!eTz0c|@v>l<}#`B@madn6f!XOAfbMqJp?nG1&&I~zH;Lcd0 z6NheL&wX^V$;5;V&{o+BnDUG7C!}ZxBf76aXIB=zKx~lukwO(9T4EO_NXS4=FFHG^SU_S1MrfYyHuo z$#u&4806uFcqe620LY;0lDGB3mqgO)Y_BO2;g~lVuK&K?j zBL}^_%ym<6Az+8NTYmMZi)Ds(s0Sx9QJCS52su6ZRf`Cg0Eaw5!ZSR^w-Ig9BK6Nf zj(q!bS(DW*1}Y(o6OzVE=VfzQHxi6}(mxK4hx;#0Z!~2kDeTd(b$pBR7MB!^<2mS7 zwAr~zb01?7L=YV6qlxUxJDB*U(Kk#`Fn=9nV#I)RJ|>f;UbE*PetmQZ;ZjE9>|oNT z_rg{j)zkhsCHYc=ggAwrf`csV8vI%WH=dcH?+JrXDalhS5toe>T_VPA=a)b{1^9JnlS4ZL$^_~l%^@4D#IW}~`gchW+ElEk2)zyR5?ll$CD)EhPyUguU zCVIu{jHdSUPIoK4q$e21MbbB9T)8O747VR9kP;3sI~9+} z#B{DPY`6JScB=cWn^(RM?JjUJT_p*@*>yIFja;ROtl!%E|HymmsHpn=e{>M(MnD>* zySs*v7U__XZfTHa00jl$iS? zu$awk_TCfw{dvbLblCX`>mW2*Tt)~ha>`{igTLr7uAB5s*q0(o>sHK@#aL|`dSmJoLKbcMjnw`Q}^fWe4oT@kA- zx^1m97Qgii3-3htLYl;Gm%y)5JmeNhAcXG|lQT`KKnm+m`vZgwz(bD3sce6;s% z$Fn1BJ8%eKVqyZGtZFJ|u;NatQxqT@KePuHFWSk}9XR9BcytF^X$kvys|Sg_s5j}l z#5-?U)=YJvs211w=a9Wrh0O(LL7^}sEs8aDnA4+oPrB`_Ux19+FXj2mG#97(G4tqw z24z{SJ6|O^spp`rqlZ~{>3A$~rO5I0CViffCNg=Z*)T#SpD{Z&aap@ezw%+Z~x>(0i9XTa1RrFPp#!T zk3oKna#4VYqj$JBkzFi4W;OQ;_w{=0TSfbdN+l4s+Zmy+_Gmf%*q#Rl)q~Yg<_FvZ zYX~?|t_Yj*j{^8BWLa%ZcHE+GgTWPXDgOAk&}HKHuNP(AXe7pkP0SJPqw0F7@{|^c z$Iz=cTd8J@pIz%k)AkHF-+$i!efszeTJ7Pk*;0#`_z5VRGx7+($B~dfRiW)T=9VIV zb-+Zs=CUiiYE{k7#`#RHn2uq7t-hXDn&P#ggL){n%g|}Ry}Ga0m*ohM8)cw zwWs+1M>xm0>!y{{cT{-w?{+(LnTtS8b5<0(sx?(!lkDI^dTi&J!IQes=E0C8Drz07 z;Pgo6eAhDBO_}nL95>6{95&~oeF|u%Yz@C7F!Bl?_Ny;5Z#r?(a&XEt>q%NV`Ye&I zGY1uos)0AYgU<*|W^T=_<%Kr;(={ZBq{$`YH%+AW#d|B|*3i`qCKDm!;$=uKS&V^a zJk`GIYFAHgG>rlLBati;G)2Dd?+@0B}e_%fc^yzL0z@ zOKZSZG4$al+n7sv_H?GpdNM`!_!DfG@GaZ?ypHjAt)*pr<%E$r5!)HmfCOal56~7L zVQp%AkkctlRmWr0qAq-U%PMjui5nV^k1K=gmH^IU(0b13pd`6p?3l}1x!Nt~?6S3| z2+I?^xn_jH0RJ{kIqQXiPyrrcCI$M(D^PNEx;F%>wB#(o&`nlG4TWiqXtRy;gvFEH z%nRUc0&F~NfjUhBXdOda2ip9cSRBRPg!2GSwIveM z+@?jR!BM5rsshx+H~`tM=S`N^?b=1u)WJwfqsWBW-&h!n zTM&})?JcL##zeWckqlfs9^TjvxQY`6vft(iI_%{)QCH=#7l07csbxQa%lmB`WcSp7 zelPvJk_e5@fsAk)fmrBfJ0X?6C>O(`KmQW5uhlY&zlRoux{yM=SX%peH%Y+fTxhNJfa1f<3kS> z&OZ3X`Lnk-O+c4V@}5dATGFM;+0gxPyu*8|AoI0L-)O^Yv(y0*%O3rgy%XvrsW?m}!8%_5}@7kcY>Dul5;c~)qN54I#pxwmU70smb?*1^VJ z90wZzh5E0Ntx+s{W>2QhgPhD9gH_4rSJQAS+M;!v0wS zCMM?raDO-uD*nXt{7b*?|C$;0JJbfGK=3&>3^SWR;WM+JtK-@gsYcb7nk&45s(G@YS%k$(1Q%)AB}!!xYnu>D0cw}wfcmdqZBTw z2L6JoRT?!DIzxqb@yM0xQAjpLmja{om}w#U=Xjo0aJq+NFp~ zjXNsbM7+&HJ=nhy{noR$&q*}Ur5GJgu%Pht#r{5GP|#dZr+!OgZR3!WWle@~j=-^L zj>+en{E@mJAd(v)i3d?%S;=M#n(E(ty%4;(2jaeA8IXgp#6SA(k^kLXxiLeux2FuL zao>rrEAlv_Apfo}`4Ec!#RGP&mK*dcAJW6o?HD_cB6P~V-VM?Sdns*lC( zp0K}63Nn;{qR+-y6eC2v>tbdv)nU4+yNJ=_Z7iExi2;e7W!({-t~%E{=!qlWGsqJ0 zaYD==b2%-2Ho;L15YX&fz-zIkG2Fj&gAv%Lk-b)W_maa&Ppp1R?foWa^g0U12ZWVfa5BHSbS8~6%(S! zKdXWgK36%_cxtuB&nx#4x4Mfi5;NY8hYcG-qamxt(eRf0m;CNWkRsI!S&+yt1o}IF zKF0i;-n0(KtG`(*{+a~-H;)mCe(epH&*3ZpO*y-eNnks- zD@fIsp1K`|jwS?hRq=*FBRp6gq=i~$^VSt;8iNP)!s;5ISjDip;I71kr|&wd^3{vr zWGc^^n-9K%`{ct;nWH8~%>821Ayur!Ifwb(0LR=lUIi~$l3rRV9n?P3fHC;}I}kL> zgKi=XZdmdTZv37=ZkxMAmG_c)IXi##ZZ9ggu}JSr=6%=~L`Kl9x^1o z0lx&YhSw$iZ?rWIRH|Cy1nVMGVsN=>nW$qFOi<^9$jQTvD}hW(3M2ED3_}zB>qa0w z(Gh#^91?8jeU5-C3mUaK{4PW!sR$P5bcJdNsAqEnnHYipZ(9gmHp>MC&$!v*5xwIUI$tc1`}G*qOV3Z57h zRadVywS{SOe=UteRv?y0K(GogXNSFO{#c*7kGjNoM>hs(@PlHfu;bpl2kv!Yaptez z3eh~~J-#}`Q39pL6Y8jFs=n-_Z>^4K3u3ZO@b=zn%-}sxhUJ?ugj3ZTcz&@od$A`;$boXBEkJd)22A_1+jQ3>=?q0!apXvf?o%D}0a)dq_7gS$tn-!G`)>qH z6oH+ZK%|KcUV%5818eX?S*=o@J#cp;L18|?U7pfFvu@QayJ{XJpw4rSyg$jCZEip5nd)Q)?G^y!SrCIMAzWlxl= z0am7I8qE`mzCPDJf5iixpJ2rQ<}Ux2eMbwC{hQ1{VX3P>||^=#Ym{MqEg+Mt}OiSHMHkE?5;Is0h#TMEJ(va zS&h>ZQ=t1~hL$%nAOBvTsrSAx_>pJ7EOx0USJaH?Yr4iHqre_(x;ymfdP$LKZU7Qk z5*$?O`6;MxSEl$eC^k+`!)5d?dGwcJh}jlg=An7)g%E^$BQ_UP=&rD6sCcy7jwD{2 z8-z0JJUP;VftshdlZ?R|F-C8t)eXiHL0ZxPeO1nZ8j0sXVk8jLB}1v$CdMgdU2eEi zazUg|nI^_FZ&=+_DXit~l&i_Sv=j#jU4oq5J{NMbu`P`_eyEYmd!|pwvVn9b9dS@- zS5+)iQ~CtiR^|tYau`wvPJB?X;_0;lpleVYQyQ?vMTZ_$@Ps|*srYP3+;%~LAY*Xr z{jhQC{h-&dcoTF0-bpDf`UjUtW~A_`ovkHH*ZGAjJ}+Q6E-8_V-VA*2YMODOSCl#3 zgG3rsTk_{O;FC2Vzgfa;{iZ*rhOB#j%9xjwD>NvefwN_Z@;ZQZ-sUMw9Q2y2*NRr| zj@|+ZkGwcAW!Ea19OA3@07mg2gOw*h-UE$qO-#(inGneojtHL8G<|G{`g%M@Y$@t! z#++F{bV|Era41FCfyUQOXH6F9cx&vSHXk`N{(1oH0Zi02In$oynIF$^cVjE<-8g$? zAy=YuB=HSEHQLwSRu zH`J~6-(9T!@sa*Dul>LK-Pr(yq<>mB6xX^!(Xi;k!@YWOk?j(HT~h58?`neRBMq@7 zO;c^BG<4;xXG_5w+knCexGTD51|a(a`X`V`<7=e+n`>EsUWqQzW(!op!;r;0<>|fC z2@>DPvMJN`YrTRlXYS@!k;$JY1s3JM-h(6HJ&1C-{^g`7--pjcy$@0-^Q4V8KyqGUEALQH(AlqUXp2BNRi z**_ca!z`&ze{p zo;b|oxkbd~BJ^9-Wcphd%x+`dGk&BOrZcTWoy9Qz*>j_?Xa1%*;E7nle770Fy$}+{ zO%(k;_(I^(IlJ;vW&8~jqJ$9VebwOmqt(Rw?0HsE2Hxx^Cq%1GuBdHL+Gh6gsA_MD zrZTg8GaVE%SqzGTj$JaK(wAzFQ7@x}irbA}1_yK&x&Q_M8jui9AjZHAt2uA(0LQ%} zY%yk%sg|_(IB`LS_;qqLN(4TF%jnRG1kl&?t)NlHy!XZ?rxtm5hJEyz6&=11CicWq zppWN@=Cuz#c%@eZ$P<~tUz!%6EA(IOMxQKh;qb8Sk&=0^G9a4xMUJh^siEYl0!#Aa zOz2HLkkV{A>%7sSXg=O1-A{3k8ANZ69PAOZB=ZbC%ikPR`KNu9srKDPth(7t8a&L zm)Dx?^`QFY5Q@C4C6Kc!17GT^j05_tPzV2szKB z$D1%e>>%Q0-1+mbuXETo{B95yN+DkqZ%=9e*C``*7AQ_0=If5!d=@yke&h}P;5HIS zS>tAh5|DMLJ-xI*n6h)wZEti(-!5AcF;G;;>4q*92Zmg=c!TltoGQPblMtB5qj9_d zQp#pv2oHRSKy&S7vh?lb6sUHB6ybabg|fiJ*Bo%+CE zTXN$n@G)2uVwVxgV{lYE)KF}-a_Sr3ipn}5NbUz#t=_8+-yp-uv)o+ZKZG~+P(;@B{f22oMY> z7Qf>z-pJ~|4`hM5xSUr9dzqKi zM~{5kJ@f7Lr&X}BYH1!z;5wN%)4mkMOMIN}%%v)BgP8aJWBw5;GIS!X^P=4Wo1bE2=6_psK&d`bPlzy@(K zYiXnZRM0_L}O_NsXjx@=*;;HGyz2_V3qNH8%t3K>?GLUl;(RORM61-PXK?sq_r6gM^pql>BF#UOBitP9g?cT z83Os3N`8R$ia8H}*cv!;>$>gm1mXkvL)a?|3;kbC{1iCa&x-)*jO{O1jqg%wct=@k z1JH3%F3`Rgj77>?BCE5!tJiPML2BUJ50DBDr&A%gMpB{bX4#W+>8(g0?=14xO^i-U9 zVMd0&BUsj$LxC;=R~5`{h^Xx+ex&?x(lTm#WO?N1J08z{O#c)}0Rh5zn}@H96G4x? zBhf=_gt})-5kEk#xxb^JavlNsxppSZ8PH?WE&>(*hsaUp!-?N?qJpUt%U8^qNctu! zvaXEoGC(GTkxD?8Qfl4)Z}ZLH4yA1BdA`H6FZPK{K!(AsI*2;rVwKXaAEf>J<>b}Y zrR>v(+QgFJ84|>Nq)wvv4BvZFX5WE7Kf9Qllw3KR>}#V(Lwko({_f3JZ;IAZkb9Lb z*moI?Z#KoDWx&zAN~JkZ+1dND{LGGYg(Z}E*5Rc%NWwW


    IyGjpk%obN zyK;J-pP%yX7_POnmPx$HSEl`F%R$3qc&QwQH^(vXc5q=p7=)uw)H?YtXwx%6mkicg zxU4nJjZyN()TKr|7|ezBc3^j<1lS3^YV7$0R7zHD*okh;U758<5?=+q(for;zj2Y>Ku5mw-+ih7HX;4r#XXMx*P_C~ zLWljA?NWwPPZy+_Tn$2vz$Ju9h9Yj)=MS|~gBt}-s^80D9{kO#`!$5azb?%wa~4{8lFFP}jkJicEGJ{f~c zN1Hx?*&)LS0X6UF%kA60CsW=2J^5n{{L?+h@UHuAK>J1JQUg}xbh!x}X{sBd7gix_ z@g}9U1=#)i;o>3;iPMs%xk*Kdl~0xP0-)kM*Ck&s=27;%s+Nl+lvHKBh?IBpIX}vY zZFMU$IT~9|re)T8H2S{KPUPK(==|!vorcd5MSgV|a%_Esl3GY%bU}fl%nE zA)H_haAwmYLg{g~bN3aHk)&ZDhACU6E5txvmku5`5$SmYstmS8zeL zYVYnqgGc)_OA<5ZOn01>>y|URr%WRZUu$u!s62d~-z5&2JnnyROP07+{~k=d}|Qriay+N}Mz zo|?>WNx0x2CJGN z?|=RXDz974t{Xj|I}&fn3Uizoo)u#wl_pQ3-XK%h6}`AQL3vdzdg+v=eN9u{-)JC9 z-_$4D2r9IZjD8G6Uuvc>6$YTYpBq2_M9ocv){cDsBhpT{{#!JT?$E ziBfN;rDes=Dh5eih4*V6p;q8w_%kV!OQ}bceKj;+?`jK*NOzk}HNsG;s~p{b(5!cJ zIoC8Q&+W#_wN@`Xy9wH4ZmGfj^gUlGbU|@KF)tD^X87|p-3;0T!@!q^zUQUxCYxm< zTz9SNqjw!_yj-fd&k<2Wz8OSwxAQE8e0BJek+OR6K``XNKuhqBvO9wdQIr+UoaUs6itB{%$s|(LKZ|4UHX||5}h=FL^ z_6ZO)V?|RZ2V6j&n!)HoXTNjp0flFJ!DVH8y}0+5zMG9F@At=8?B-R$UVYwrZ!aON z!3ry4E8-#<&6|kY9?Fbk_-)o$u1DTq1M$&)Hu86LSrb|g-!#Qz2q(zXrw>_K(Z3Lw z&k4GaR1Vz$1@^W(t=nn(8G7qfa#m3^@c z)7u+x>E6n)>nA|av#p`&p2lExvGZwL;~1#Fu7f_ciB|m-JiPayI+WEL0gGIL@Ua}u zoswZmLblUQ2kM%LbbGMI1lBEyXGcx7lbi(4D5z<~!`rjFRpvZa$KPN`nOY@%v1LF@7i;t+PY3W7h^Ixy zQ$UCsa?%7^H$XDI%mnYs1Pbp=*claoJeRy*b^w^@y{t{}RkPNw*$#)#DH2N}yFSL%aeQ@neBIulvN|aO z>v4L}YhY0G0L;A8SU!0tP#jwr2k_1Na50s85{N9CD%eo>BnQg%ZhKgaJtYiX_R^Kia{azZ44p7**dD)K#0-SN3qeeh{YI zXp)YwD_jtoZ)F(=7DJB06J5o zC}W7sEyqsJ(dKiL?J5%WzC;D$;AG;IAKz1}J*ThDBzbYyg6f&or|MDx-&4KN%nwFg zG?vJFuWhC-H1O(fqA6^XMF@_+n_=-gzL=YRJtEqs~oXQm!%I48v**&o1|3#bK~fl|Ks%$ML5*1=J-D4qq4oPBJpv>15cdAqxs`; zUUJ4wWf7^H38{aJoXVS)>*4XsAt85n>IxL8Y7IM6bU!R#hvN4=MxNuQ4iF<%{`Yjf zdf!ZRV-;`0K6Tr}j$pB=SLPUdo@TkbTPJsfx_sSB-xn@ zRZhHA=A9*yN~9n8A5Yx9{PV@eu*MeYLlc7do|^OI-~5m zy@p8GgF+jtoVTfO_2z!^hpDz_sBPR?NGNFIrXZq?HqF%j(QWtMmD;ViAT^0Go|6?R)*S?3TxgF0|K^J5e^4S9g zlT;dKOe^Ep=v;GtLJw$AvxthYfMOFtccAs)g)F4hF9XZVqG6@fNnY^Pa$>8eH~2iv zjwKG9IeG`|CUvsH7<{ImC7Q-g)$Xbr7<}G6k|KY$glr*+1~NfBrC?z??L|$T5M{N{ zl_5h4leDCZ%a2N7jP?O6fn_N2s#M72o$&c=*Rr)hMG$u%Y!u3|^H9bVdYjn12;3+w z{Q8|2vqJem6s8+pj@Jmk5qrZTH_TH=W}!Jij5l@69rYpinlP(2YH|1DC3j2@Rgyp< z3U$zs$?fG(nN`i`?ta|k@$T?8M>=`8cwpVCpC|b0bR*cNG%Kp-gHfEaEh%kfMvkZt z>Dc=~5(4!$bQ%1YkpwISx0%Z6zs^+tH=LDp{5~rw;LlD2lI1e<%hZft00|StI~^q@ zy={0F0oA2cuQxi1zjOsKe<|?~1T;SvzaM;8KL>hC;Cqmj)^A3}`ma)Y&RE_JqvoT> z?}AT{ZgoisTFrid^21t>77z2z-g-xxY!0B3aZO}NDO-bmk)Gu{K~&;z&`B212W;4s)vOh>PiujZQ353-+@s^BjZU)JtrqVqpAC) zHl1G~oUjmBTA@{tGr%SrU2#`Jm!ii{G0)ImgmbFYQKFx@E?AwbOO393HKG`6N;4uD zkZ#qh{BErIag5T4ug$0S`G}0S3&h<#q46VZ2@Ov(5HurzjpXitS~r%bNNG}tX>m6( z#v*x8S{z9kmWgw*5BX_zQ@`6<&TpQ_8&fybB;}c>C&iKY0qSjw6O*hnv)6}NTrKBD zj;@E#qjq#0)m*Cl&Ht&_8d5b8CeFlQP&#$~#XC5xSD>GW*k@X2f^B6*c9eo_3kB=Ig2BF(;v(pSCQhWbW< zg4Y&FCYp(q_!zKF5s ztbmXsdc%mqt`2c~;|Kv*@YVHM5VFUuNfCoq9T@Ws z0ZAIdG^c`jGH7+=^#~C`3WLKGC z?wX&~^mjyP`dz6@!0%`zg z+L*3mQF9;SRG+c1J#Ahms}p5!b`vPMDzuXEHtUYcQ-wJ8EA7psCx9Z$Jet*|vbBU2 zcc4#d>)l8;mII70&=OZdwpOFu=-NRjhVY>2mO+i0 zf7}2QYTz^C4m@ugi8t}l1A(^6oNGG9vrCSbG4_U3 z4mFZc{(XcdzQf0k>?dSqgH@DJhFS-6c{`&;?H<-B* zi8EO%nE^SO>h36$-Sh81nvIoNPHudR(+MTayl{0eUNFULs<^BW-k=b{=d`^yXQ;2_ zn5#&yxE4{#FdSlrjI5epm~Dqt&lrUttcZshSuKbwNLfdj|Kd{Xh4>DYQLt!QDJe;g zu3Yo8Vw@|_)XavRM{7;J#auqHEiA$;SkgJZvl=aCTAQ+p-5WA2hYyzzdoxP4#y?tnJ&ws$#T z+i<*f@8>t`YW1H@d`$4?A_Royu1$d@*|wD*SZ@k`d0gb5etmz>be=pql2c<=ex#+p z;C0Dd#eIA`9)sL)8c{b9{LW9o2;F|<=lqkl$6_-MC6(Td3xMf}uKjAz#Vhk|reBWs z>yZnORgH+7bNR-J?C)PcH-x>}eRXXtbS?0>4>G7S1$em}OxEyr+Q2>nt%$0{RG@U$ z@-Nr`TPB0GZ?Ey(Z5M2hy=j%jU=b*J1m#R=R|pyNE1km29QagXF~Lb~D=}@7W*Nuk zA3Her9GHTX9@K&(ZJMI_V&KaU(XYeITIXpiE{bM2Z@hYd;>{C$CA{-KK|d;=-kXuN zRN)&oZWzgv_L_A-p=i!kvIn|uQZcEg9y_$1tu2FhFY?5i}Dl)O&?xE*M11?Wja=)-WkYkEXFMg$!S;?Vd9&% z2hR6%)vE&>c!YlSuN$E1Tctp~nqS4&0kGL`+k6P+eB6WgI{EDBG?;be4MS0aQN?A= z0nh^lF#W&J7kz^OTyfYfJMkVI_W%b18?Vxq06M}5r&T12v)5h?rrHt>47ejg3!hJ4f7my}@ohywR3gPaPnbgm|Slxf&- z9Far_RlYZbFgJu)Mq-gcFO3$FWG3n?2R0rl+&X6O`s5)77Gp)1UB_uK!&ECZiDhbWOfY1MG~)~p^#a#zve#U8vNkl$gM%K(ZO zyT+95*}}7E2m&h&0EIzpF;D`O|IB<&u;iDW!m18P7i^EVG!#*tX+NdlcDFJu5vP3G z8L+P(;aBcA&>!7s9x3D73g~ndtA9&=bLh%FxQ+yJnyakYjIgJkJ$XgVM0r`VnYy9E zeTlX)ogRd*KxTa%356X)5W86VPqA3~(LZAEm(>f+fx5t@QVve^O$;QcCzP@dfg3g` zbeZK!pt0)4&~rRCoO&NhF0G5Zlv0$T`6bP)R8Heu;I&G~W_793{}>_n7lN+bE7?`* z4f9f{L;HH_J(iWa&z2jD{Hg4IDvj@q6`7B-)A zwQ*9&=^e#S<=34DK^)vlHHo@sPo@Au58NN%h8mt1ai=)FeM2#95c}f!4-l_lCGtQ( zezdtH=D5XuT*ds)n8_L+?rf(JM`2)Z6W38Q~|73a;kqvI0( zk9QF5bMCyd)&XA{#)VE}Rk)RUppjcR=;Ir5B^^F34Q1RMP@JpkvUicp!x4doNEYa` zOh5m35{@@V{oGCBxgsGBB6C4gc~pl{o7VymYlFSh=}wTo0W1CMhe4dCh#hU4)(0C}S zx0L#@MZ4=JzKKH@B}!`}-JSIee(zH_w^2D@r5cr*?my95XnP;W>3K{Kfew?tnJ1pB zcK4j5nsyCdO!0sa$x2a3M2y@jW@WI;Y0*W4KxRR^H`e^eB+>4dnuX>k1p_Egx$BOF zi^IcT7v!MlfYj0^R%}J}9;t^1Fm;N?n^h?ipdW*$q#>IV;FKbK2VsU&UAVH34gCBzppLPPEQWK6RU8RD{1~O`hnbDMq zvV&0B#5#h9Eq}ddgi=Jv(6?k-63R2373opO3Cq-330JuY?P&$PxSpzDfke6(Ih-}M ziNe&*Vmmu@=dDNNn3_atI-dc_H!R&-%7z>2y4O7Ia6gCE10XL6q5AcCKqBqGf0AWu zLScK$+OZ^``gH;>gyoYg=$2eW_~w?-&{F&ZWHJkek+>OX|LqTwWLm&(fANqk>~I$% zUB7Nm%nr!bW-yq2lP0ox&DbI#w~3`!HQH1t+uxVrKY??A`uWkh`cyzm?)cR&1D@Cv zb&~nuqKG6$5PGRYq25#T-P)Sb)g^C@Vz-Eu7hAX5S*~_7?kc1`1^PM49i|`DjMD*) ziz8)*!u)oR^CwPw8Y^&bzOPi1AKWCdL%&R56gryMgfS+=EW)#RVXB(9vu9f%v;AY4 z8@_%>#d(l(8PhFc`ZdC`B|XZ2her|L34d!uZhLb=kp9VIDYB(iQqXWB;iP?m>86|= z9_honNJ5nN5n6kH=zIT82>kzC;9IvfsLXxm?LD%!uvoWIIy@bwEX=p3J!Og5@3mt= z7|&iYL!S#>M%Sv^jjIPK|MP?R;{#D_2;^EG^FZTR56U36y1YsAcAztw5;HTJHK5H* zaLF`RxN1HX3OYG^aZjG|b29&@e5qD0Jq-S-t_>Rv-P8PvZYs(n9tht-@>t)?I&stZCG_ku2 z=qt7ZiW^Z~Z?F3MYf||8J6uv8G%8S-%9%)6q97KEr3a8}*AACZm|+maR@trtq&;HK; zQATNmi3PW^-J5W$YI|Nasx3s=FznXKA`bc#DxD5`=UtzYM zT>ucAoQ0~RCo?STUyT2Vzz0ez%F>7V;UQ%XiQ&~9k}rZWqL{9Y%5PvYfCN*xuFRTc z&|^ZqTc?4+KJdk%X2@Ro%}x6)z@PPf!V??KS4u^ke=-)Bzg+!6E@%zTtI~f|#Zr@Z z%cQv#Z-TqOhY!L7mH;9_aN5tF_0O_PhTVp@OYnl!DKxjfraogvwaTE&vi7AiO>y7r zS+!zEhZ1Lj3|}3A#FCw-4y(F?f}EJoc?a$3=PTR!g7lC)Rf?<5h-d0SJ=7 z&3z2d9FnbLMnE!_s-QqA!)TY(e1Gd~yJXxsJ5n)EHz|0La-?vs&E?=%C4Ax2GJEjg zF$}wEJT|h(XlF3jRJ8q5-_fMY2Vg{hZ5orE9gvwRD=?wTSU(vdQruc z>NxNx$=WlpvWC$i_Z;qXhk`lj91N*Uw{D%LA;y!rxqIgC>eIADbaK|d2g96NtLVc! zX+!5zrBQl_F!fmHGEhNrpYPbARy)`klg!P?`}#B2Hit4+DL*)uLJJm%jaYapgKS0Z zow6ygG%+^A7*a;#m4CRGUeVO$DL>+g9CPN1?h2hOwVCZTwIMf{QABmc@P7Wd@wHlx z(9^G3{ve7%d1d3?Q!-#=4em@O&^F#fh13IInm^E`Hd6Ic_sZ7MF$}tM=$2gNL{k5| z^0fL%!*1$JA5(bWjAP0e6I=G{K~Yb?#)^#UJhi!**#&9ShG6DpMtXY5-puSQY$a77 zp4nsN<;@>9#H~M!Q)DMn%+`bUCqycMxe=*7&kJ)V$~h<7kLBIy8x0>F&Uernw}dO- zAyFhRuSIUqV`JM>O7m5Cz|=?pB{t-63yPZFASAODvF~H>ml)2&w!k*kXp53~wo;Cm zX@|>`Sh}|2Rdn^$Hnw!7HcBDZe72UYJw8rx1sL=IUpUVI`gj%P^~!KE?YG3k7+;lf zRR>UKxTieC?bZ2aQ4g?|pBS(Y_wceQk#CguM~uvGP3T@rOj|p-eG>KCOg!Hx;}Obv zkG;WbUTS2pU}(S^Dd)Z4q1M>H1`WDXK^-`S5(lE#p3e+h9S0HBC>7B}uG=~a0OapW zxzR>qu~n-YW2MpDmtW3_O7C%*MWQFtVIoF&AcpIXve9`N?K-4nfgbkb#}iZBIf8zZ z88^6^0+)AuIecErQD{-KTe3bwd^4RFa~ZYEd!aDEee>{SR@|Ov#du;=X?#`Q%q+v0 zVfA5MnEGoLuQsqJ$wvH^QGx)`^W&0_Gg1WM8Tt)!1TW$Hl3RPq=d7A{WBgO87&P=1 zZYrvKwiOOiDa)3sxZ^t<9f_v&L*w_9?TC8=72ovDUwEBDSN1e*QcvtPAHR7P%U*}U ze9}(E%Sa6pekyT6a=PT7qEE;kVO|DU)5ejJDSHzsIG99^-!+Zn zLX{eJ74=nnz>li4qMC6(R55X=FiHR+ZBr2utf|*;TV%B5$;{k;Lt^g5K(y;D zQk&po46;a}Efr^r*eOFa+T&R_e3D8}M{)?-Dz;1a5PWU~p>6z`tEhiAxGQESRUUlA zS9t~~X}<)>B$SQ8!*kGh)iEcX&d%Hz{=9m*P|t{xK1>Vd8R(j*s>ED`v%ArZD!y&m zQPs1F`*bhBY7*}?p*n2rV43H@sm zVtiC)|p~* zHPI|~;k$cg^M&;~bkeXM7)DTHBg>)gG9mc&{s+0t zVl6c!y?qXeiI1w7ip?bLba@Sg#B1^wMdOxsUo=^&1n~{JlSYNSzQni5M8Czm((%tI z2Pmbsn0=Fz4RN8Az9mYn49h%)qfy9c8$VIo;sy4+hF%OtPx}`poEZC_64u0clLw>j z46w9(@+_E>oCrSmU$~WVxnDb18}jsxxzElKIi#$KFB&2qWrx zBg$+GOmUpT6RZZ@G+kwqR?lhKM3*>8&dOXDjVGyONAqH*_>%ERIQ;TDUhm(xeq?=M zO&*9+iebDn@cC5qD{CZtaqNiY+1ro_*^hOzlxT2J-0>O1_)1E&tP_<_U2jd3v6oR>_q4jSF_Li{}-=+Cl7SvN!3i0EpWXqHXqSVRD!4P8NOeCAnfZbg+VO_L*f<;QLlpI~NjwTTVE zqU~hoO&_`~H#SudK4!6)4vKCIx^K@j+%{RTz*^(U>Q%v4x_Y@$Yh%6mISs{F5$%Y! zZDKC_tXZ!VM%j;6Z6{()+aqIGzJ)q_QOK!E06Gkjd8hUiYbEzl^B-762%$`-I+ea` zAh*b%9cLJIKdVl%Y9xZ#y?bBHb6|df8=_eyfFtI2hCePh#6~JihoBf_5LjyDee|P`VMgYaHL~v9AN3NDH56IA zw&J`la>~!vku{r-j#Qcp#x{tK4fxyT!te}>nP$))?FoyY9BAqu^tQc(x;w)Z0cI#F9Br`638fEtl%>(lhjktu$$KH6@82 z+ih~a%VzHckz;**|DdDNw$N`vUB>PcBIyHfMKiR^HZnO;?EF$|y&YYhi)5m&E9x1( z6$Bh7-Y!d$B?{C62&;i8K3ip{JFKwGXP;{8r{A@>D_y%yl8|fu`(^3=*~JTZ%L?gW z$FW@?h5@}cp4t;qgAq?Lv`ka`~>A z{qa+6qGjj^YOdDt_y|`nkss#3SNinfa|Y(MW5%b^CRwExMX-s zBvxh6x;fW;8RN^eGf?X?yz}U()&FAet)t@Dw!P8D2^t6*Adoi@g1fs1cX!FFWbf>goqf+4=bm@p825YQ`=eoW*Q!<3Rn=>)IppHRpNX@3Mar1m6`TH=Vp3zfys!p$*QaJaCUdbjr9hfGSt1vwbXHQd{Z0BC)<4lA5 z3StQhEa9kN+o--yEbrT<$W~A1A52bbbe4&j!&~K&qeXfPV+2Re zOc%<-C^4S6TZ)Uht~3Z|!0nuW6coTB3OOw}kw@gYFl!rqmZH>jw^v|?xkdqSf!-Ol z^c>yXzIxO+U8Qz&(>u%b(yCLKPMtkC#X_V^(0Gp9zHGH&3I~4wb6%a-|UhLvdeJ zVb4mnVt8H?qg~(OZuxQ&5&#q%L1K?^|HXrqEBgB9&aq_kRnH&b!QDQx@=YyHABxdc z4TM=HQgvQ#Tvn>kxkTPbIlWo9l4IA7r(OkI-yiaGTM?!r8|cxGuaMp8qe+X5Mi&IyKrqlW!*g?LfScFsfNdyzE1hVtCk5J|E-bkKm&;wD0C5Ju zWWJ%8rn*I-_u60lMh}WSqzY%7djNi3S=Q`M7Wt|RY$M4hxp5__(j9M@g?2;|5VN*tCgWh5cZ+sm?^)plOq4A9mK%Uz6@!EJ&B#)rO z0_YHV6g3_^ZoCNkt8608nEjAT%zC`Z>+--XwKut=nhut2wp2Yw#LqY{%czeqS#^F^ zcn<%$Ck@obDm4k))%R0ngse%0_u!2i$&OV_U`u{J75awO0b4p&(SXjN#Z14q@E`V& z&dvJlwaK7+^S2b`4ba)T8R2Fug8N6DRBJCgcW=KD6Kk#)?t`;udo0iF?Mc#wttefE zYvyN!lu`Zp2IkK4_V@SbZ^R5O%HCB$rcFsCiOY7I2P$PKo2JsM)p#ZHWwJN7&FT7_ z=-onp zLAY_hlGAlvHpcK`&V1>A4{Lj z0`-ZXE*uu*91^Nr$huv(sv9Nc(ua{IL@mMfpczj7L8Y z=bojWzqE-|xPX3VD#e|X-9d?7cuG{8maS7t} zWC_pUk8y1d&x_dWXtyWIE3aSH;vveFNj-ili;NvJ>ALLChnXdQ_jq_jIzjP4*V96l z_gd*bU;-vfV3<`so<-AL2Mkp)ek&5m)zVaJGtVi=oY4hj(D=Rzuu(6j$r`MxR9MSnv4DQ-jP?=<@Z-f8P+eG7#JHkFYY5Q6pGJM+v zttoe^vWYcFZw`^4zE}}(CCuM49aWNo(6(kidIx2b{7#9pzDO~9v6KQw%L98 zX3}&{wtm+XFbu_55J_Zbid5R9InM60G`N|oqvwq58s?}0dMPd}O^YefV)flR(hv42N#lLjU1LAjrZDw?&Vy_ZSKx{v*+el z#tvyC-iwK3di00HV8QRcgG!_Z-d{mI1b}eo+m}Ov_irHpMzaSQknsSYNeZlo=$tp@ zZKPs6^CWO_lhIyRtPhjUGmh?At(gvvN(2cMS!5+u{1$MsK~ENhtkS-2VN0e=%1h#B zrJ~$%6RPfY>jHGQVIz;wp++9jg*RJ;Ry26Wm(RsJB^BpHlh>)t)pgFUw?(xnh*Q4t zI#zykT5>2n-j@z2qxP^Dk(L2$pn-2EqvTL>aW@Lg=6{r;f7_`9py{6hkr5Tlz_+RWmUqo4A3U{ zFX;Kda*ou~^ZzB({vOM3ql+q_JRf;L+q#z9q1Ge%EYF-hsUEr+TFNV>U^@Z|L6O|u z;~)Pxz$RBp2%9P97Q?j~er`4f5~7dEJWC(fP&KFm!JxLIfVgc(f=Ul^HA(v4awuk~;xKu)76w#sb>OIflc+2=%tA(`y z9FBd>Wv+s9c?2-qMdoOFBj%It$nqEY;!`-s{_sw`A^LfF{B0)m%T?EO{4WexBvwQ7 zg*wR`2-x{>V2~z@IAX5pcwQviK2mLdv+jI7wLhLGvvkX~7*A_LUS=9=0GSpK*vZN5 zpZBkzPDK>Mu@R1FO(PdW$>#=fqj>xRgj2F|bf@J>v*ZmcyI&~jH>Jc(hNsI^Lw5S4 zL`7yiWTLk4V~_n4^)58qdge%gE7j`X4MFPV#+vuukY=dSLmMFKqUxL>8Nc_C-CB6b z$#;fuyG?dFCY^@07l&8ekOC{3001dIB6eK+=m#yZwxoZDYIL?YP-z_L>-QRr02?7k zVQh2SVOBUzndU&3`F>_*!0?`Ah+TP*CJv1%u4Z`jiqoQRvY_{j&)xW%v(Gb;7XihG z5h7$(32#?O_4~l~+|$#2Hj6QVs1e)|h-RVn_+LRYjE=k%M#_q-thAqx4 zc-$c`@gz-S^W?bfX5Slwp{a>P>R_)!cZ4lcq# zJo=2a%&(N8S&vd2J<#y&7*4`eW~z;eA2jni_JaPTBbwWb>;Uh3zDv`Ekpx>Q)jeC=0BdHKP{!LlWhbGhOh#B}k z+TX(*^#sJ@)jNVtuU`GDG1cGY;{moBARj*tC{MvLY7JW4h-D|B9<0sQ)*w$(A(6++ zP_?-6`+Xzp2w87!)i_<1uH1dor~6eCzS-Q}+8XDXqm>F9^1UjHMKmwZ%)fFYQ&E*e zc)6@{p6qR~c;#}vm6smVhVLA?PmWN08y-z>35aeCOb9flS`8~VDX)Mx-1;BbWEa34^b zLDny?49qau{URR9TTbJRE4LRe)U-UE?khdAYxVHUeET$E0#9Zbt_s&S1kr2`2S!nb z{~0@VNlRy0rsV^g$VxHZrMD#E6q zsU?Sm^TWI`d{X|7=Z5KaF~1X+alQkXFfX;Ve$fv7Q#Xyc>TlAZ_K$#vI?_|%>OyDb z57#LiAhZIE&3<_?I|y8&Uc}yg1_M@2&{IIKj`YUwM*1sAkK!w6SlVqGu!3B!m-xc> zO1gUD$;XirD+oH5QIIOHcjcaFjnOd)_&VPP&S7&a#d7@d#G;4zx|09rFOthu=1LXj zMzh{9WQMFrjCC=Wp8I4*ez|+4KH3$?``T zlZE20WW>5?(9XdF&x*V)?zZU#%~>$~Q2qEejVQSRcA0-bDjL4kplBn9n**g^@w}He zA1;7ol^qW{rWL^5hMsfx9?RKMI1OsQh@9_${rs7$n_O5QraKj>cixU)(__)RY`Dm( z$SU1D{DDj!-9fCXQ5XW!-p%2qNsh^Y-GZy@DPBHMn>k{l34?aAKtf zqNx&Pp2+K=lLG%WM}F)|>NWwK*OfH`znf+SIisSr5#)RcQLy>Y`yKLvk4o5=CEnjl z73a)sfnH6>b&`44Eq8eV41OfvFqhIeuXAE>`xw@&&lCYF6EGA4gWm%+|8rrD>RnQ8 zf1W(eOdBw-Dfx%j?`R_KT}FrT1TECX6z$|Bk-I+RocjD^&xp(zgpqmmitG(lo}A|a zQNZJotdZTcS}$_<-ffEFYmCDWt8cqhu4nC@*%j>Yo2u0%k^X!ziJ#x7t7hO_>Q8cI z&GvEg%4Vs5d4uJ9?sXBL@-192`5rD*1?A;=b^H#TrG5H=a(?xURm6*;z?>rY@QE*> zf)8rcX!t%#)ULhPApiQ^6)-Rc7d(M};FkKQws?SY(`~W!6%w!_{LU11@c8+iqgl`| zZg-=vu;uIm2}+X$+==jv!a+#zC$HU58vkv)47Ow>InM`Wc`((7!qr2(aI#BwBBzdw z@kqkV89~B@gGiI>GcS{wy^{sWJMy6nP7kR`QfJ((svwR*M6HfMw)c;Xx&1x~Ltx$* zOgzYVV>rb4o-z%sk|NR7_dHkNKI_%1%&z+ost^cZtQYRKUTzKR;x1xKU*yBPxZa;~ z9-i{r%@YTPt*TV6*tCkHzbq5_{E-G+b8iI9)o7HC2+2@jZ?Do)CbmA(l$+wbC}}H{ zIXw0jWgQ;l9T<@YOcz-HSQX!BhwM@-`1(nis zJPzle&uioNT0qE9rYX>h<4IR4S^-boT5XwJrS_W=8aa~BV%25df=}^@jW1-Z##B#c zkV6mw{w0%f7cF);BcIb@yGQ=G38=6j{PJO;z#j?~#WOk@+K=5e0*nPE>2corOIXqP z_2{>8d;P&2l1Gd>1Ke;i$z!Lmt!-HBY>-ArP&*6pOg`f+NmU8~sl)}Pp^9~i2C_rHj}Jwhg>MxY93bNd=6E|^y=qw}7O_?-8N zt-7dDfu_#n^oxkud5spj6kCcI<%B9wvI%VdMYy=V-)K?bnXS~PCqr{V#TizTTX16^ z9WAg_XImdYDuy(TFB4HftM#uANo5XZoytU3 zbzIBd&yl}J6bftLO7H2o!VF|9=(IF)DGn`9sg6Ubn&ZP1xg5_f$=Kj$4w_=H(y#SL zWXW&lY~Hc=9Zq(*C3-PvRaD+-`B1|?VD@vXG;zz9H z2LET!b1LtP2}zZ{Gswqv`z3o-oLOql`>=d9p=NlD^aO(C3JjJE+Vg z+yJVzfZF3BRdogVP5{eUN9v=z&6CZOq9$h5>4}@SdzW89Q1Qy#pR_pdwSkN|KH^VV zt_97zCNE7r3FPpnFcxt2-pFZS+Zy)B+1bpRuTN)(2o~Y*wP1s|Y@?2n#t$T z+(Wrt;Gjy?9~hV+u8)lFt(V|}4nB1)Me~KUb3z183K-dnhdWky+J}y9xSC+!p>1qr zunjMA%!XVUd9ynHp4h(nme|&WBG2xT`R^$QMO`YBXr}C|cNw<~aU9Uc1gTC7 zu{WeMIr`9Jtdgss*F6?hMdH16O&@8WM;O_&va(2xpLWk)u%+WB>1ONe>WRct1>DEu z7qc5bR;rlpEe0yL8q~iPe9eL%H33ho93)Mhz0lr%Je_BbaFJAfIN>Am`3q0zAP*Sp zuC=DuYHGIUx)`9tNNA?07Z@)C=AuNJT9ec0d~x7p6E>oNK!q;4&sZIv=8(b#EU(Uw z-_{n13s*2%yy;lMv8;nO12j@n45%+RfVD(D`R3oWM1R#5&DZoQB9*FAvf81jc`q4j z_nBkaOrKOew~ocA*nddD%K)Gu2oZ%3hwlV7ZjjqvsU&XnL_&t-0k!+SA6w$SZ}IYD za3Bte5Blwz63`T%^-NikzKvqMg|`xrJILwx1$F{@1M1^IZzDI*WE)@Q{ z2{_Qt-9dwb|LjiUOmyJ{tNNCDU8u9mWG(%!E8&kWZlj)mJC4+w4K6|kn&eD@p)bFK zY`y;I?4@i-|Eu1Hq%l;OkY4&Mi&r73R$#ZWx(@Z^5)jtt z;?ySfY=>Rs4CKpN?iiN)>~~cLXv*U0UT95T#=XZ^Oc&;kI!aX8KO2u}G(L+--k0OE zzu6?x9F||I;CagL??^iC&0=L;zER9>RP!nJ^?M=F27_tIMKq?VsFOz(3Szr$y-YKj znsZW68y3wL=j#~DeW=%aYb1i}LRlV_o2$K8co}jtjzn17_1uAN&C0;TS1syw$SXA* zicuk&9wR5V9qU2&N$7zbo5~Lvb#+Fy2U?<6cPX~0g{2jt{lmXKZgd3^-(L@?terCYaG(T|Tp-lA92G($j6yyLTrrMc-LT zDU)u$-J+{^++LLf9+SA=Jtp9O#vp z8onSY&L%Khq-XUy;IoIkW#rj0%kStyUymhK?1AKBu8M5+#Q3i)EXzej$V22p12tyP^ER6ZJ;IcF2FZI zyfuBLKKwrBVNx7CQrq(WDe5`NbjO{S9lpqjWteQAH?%-}Nm>A|Hf86PLypgY~ zwIiX;nMVClPmQXCFOmL8DX~7+dK7-(8?Ou(OUq1%L9JTmQDUzwAIL7BmT0AWb6P%^J;X?$42a(=AvyLa{eVY@^Npht zdaH3rSlr%0svp`I=&y0R2gIL>V@=%t0hsQOu6L}mj8T<%a;C;;rs&CXu z>OCWn4s11HNbC(js8TG8&^CwN0;x}tncOTa8PVmSxS#NbJ$pTp)zGs5`vJhghg(k3 z17rh0Yg2+$eOwF~HWx;)39jP5wEcknb(Z)S?=fDs=p3<_H=a&h#cyr@#Rl$Ave9b2 z`>z&nwC@l1Z-Nhj+3WLH5M^;P<0<%VBNgeJiNY^0n7`_zmr%)F+yY|Qv>snUS&9>d zCf`;Fj6YTgU8_N76N+Q{Q4-@|?xf`ciL6=fvWnJ_OqMkG`$C<3+r!;k!ng?ul}R27 zE5>X&iazo(bte-U6xq^iu5zmgES5ZQiD+j76_nR0S8&@Y7gRvDWZA(Qppm5V1Alzn zOYWX)AGZ#gFYCDRo9Z5t9`D}ve#sd;4Wwsinex2cTZKONUtvWb@*C(Y$K~}MTuvo^ zWr-5)!>*f}?=5^n>~xm7VE@g(68Hmuu5)7*dMTyWk~0-uik9(O z<@nC~;g1GhX7gTya6m$_5eg{7J9)EH7dGx{3|xWCbk2_!fRS$Kwg6Zb2%<~e-Dv<7 z*=f*dp@$UFa?zBWF-kSwNb4|+2grtLM@nCG?7 z<8{X)h)2(MQWcpU**n3&G$Nqs1~ci7Qm5uM9h-8(xb?>_e?MS)*;i17wZMkXkMEIP zS>l!&xpXUejZ_6x*gDH$ioo%0+-n)(m$;5z*Vm>13vJu)urd7f7U|W8YmOB5L^&dS zpA+FPFOyT-cf|QKia>5fMpKj1GB^-vbGVvh&5z>u1nR9$LzftVMEQySwMff^3MqqV zuXy_n5&G4`4F_Nn_+eBI68K0bu--m%cguL8a2p3GR`7EyoNs!4E>aN0_4+5w-cuaS)Lz;yTDH#SkyO5&pz!T?GERxM9bc#C zWu2#i8vK%6bipy1D%_^s?m0~4fI^#yJ7N6pYehJ|!fw_PiY!A-7tb{rQt^ss=5`j! zqT|QRSkmuiCQLV632|WRT-~kptc+`-40QcAz!Zrf&`Q(>O=0|A3VL8YRE_){cs1!j zvZQWAPirAdk(;>jAXvlnr3AuuI}UdbZF>%q0Ij#GzBdLpN)D3$DcG(1_~nJ{pQ@WdIj-OXEYIoVz5!H>+%kj z*K{8W$t`*{Eh&6MtJnEhI~qs?8yM1X+@hU$C|tEUV&Vj69)_{Zp7Wv^H>k*AnKBw$ zJ5}j6+fw^ePEIknv@=IujLM;vx}>cz^N2Ybk*nd}Q!;pM)9TP^#k#4+biu7!UO@dW z@2uJ&F!ORC*3U+@gs=-G;|`Wu+iM&ENR(7>cvV{PRz?k6s;uv1?pUAJw9hB!lt@AE z4ouG!wb&lKhz#xh;H`?W4j;07Tumg=~|c6B&z4=+`n0_t`2VGFtc(b zXGrJesL}AQx@oiOcoQp!fFB1u!GL1x>Dfjt@H=h6%o`P>v;Q0=+Pv(DR>*zd?V*SK zkj2VKxil@8B#Q`2#_xLD?i*5*KjZ2iZj_<1_&<7Ql!5mFBccP)J`0Mk+0~va#d_vr?=w!bLEszFqUs9;DnyD*2^q5@U$_j zw>ha(r$%&&(!h8!``8Z0k-l>fz}%?HksbLGCS*;u|K2KUFXapGgq+f;^(CB+*F=5F z)xFf$f-<#;)4gH&vO^F6!f^tdM3G`Toga3e$;e2nrnwXJ$Za&jtD{_J4|7#06|K+u zPVhYCw0C?=Z+oUa@Qpm8*Rx80PWa`CL{DWJO&9N6#%$BKb#HS!CGG-J(cNencORbL z!Z|G55CA2+c9Y}Ng)79(g$ux@`Nrt`fGMB_tbDD2_2OG#ZTMd{(EipS;jaxE|64tL zKg2IR{5S`6?fJbgGTa*Mp~>?ro%8y-px2SC`#oVa<}zHm(F5dh#j3j9%c&;{H{_E_ z{7!Yics}?1D+mr4-$RDhw=?eaYOU{(fEj`?64}ebcSeZ_`s$*KgPrx^IU@1S3^&v^~YCdx-8sw)~OBvHv!XW$EZzc*qPH#9}4yh zDKO`wG2@>(-M<2ccX}`{4=aHQO!^MT%ShF0AhhcCO6QKncKWM?sul%;92|b3xfGi_RV#WTnUz_0%Hw^&L~{aB!mr0STG>+sQ7`De;#_( zMs!T4DYKq*5eY*&?kk{w{6MGHMEWFIj^MPYwsp+n=_unnTb5^myGA@+q%@r?XWN2A z%$;Se5Nh2*7?|k18=(~sbP@X9`sdIy2sm&Ljv&_bvN9yu4WnTj>0cSNe`rW}HDbLp zJTF%kC?dgD^vKy85m^NYca0Ab<1AgyqGY$}tOC}%>;g21gx**Z4%jPp6sk%+dB!jL zv7+`(Xm4<0SaL^lOf>Iv`uRLBdoL~x^PIPR8-sb=zh55>o` zkr|)XhfdAdvm$H z63<*f7m((=dU-;Nnt+Zt|9MB40$_kT$f`1(uAq5P@4+$#Sn&7Y_Vyl#u&p6$i+vG+ zurMb+YhGE-;J({w8 zWwgu^;&n3Lk@*DICE7sp(brW;D4K1swB75j26nx@f?M`8jaeijS2wcBJe^PLJ!n{d;x}Ct2mlDc3^9htou2w0flt4!4C79Y%jrC-_!b z`vu|fpSh#z)Yd0=Z-G@LAk;fI&6Y=g^ohn!v*81eMqw(%bfrt?gefrfFgD;Sn((Ps zQ6y$B`Stygl0HRmR?I*FIacV0a!AYf zU=|$4!KZ(uVWSWMgT}SrL2;Iw&^khK)IMz z{7zaid3AXxrSCqSJs#2;oR5;1`*1MOwfQgM$w8zRii;I2l@b;IK_Ym4!Fh)eaY9VJI6yo`bH9D&j<7F_8H}CC;S1E|>6c52)d2h)U2jqzrsKo>0-(m+_iO z+p$J2L|w*L{e_olHdqdXR>@d^<6Zclz*j+B*}6>qJK;)!i~A|dn%N15IxWssWz(9n z;}8jQ@kcKRW&k!RYq++pR>>5gSF-*NK9t$fi4`c$CTBw5M?kN{PCIn{>PkfSl(LafkX zXrstEN)rOMvVA*TaW@4bWqYe}{oB5$5)6UIhAdOl(r;<`(8ePsO|OYUuPdUlXe4Y& zAw=;x-$`AVoBWDDiwgd~7Zngm`uY|R9g8xZttto1j>>snB1C(0&D0TJo#95;w&$2R z66)1)C*nC-40jLZw=*E|$mbG*90@s>6DJfXQw-^c=fI{`=O`S7eFO|hshk7$m!nS8 z{Bg!i@e{J;KJv_;sBtw&<)1ka#$nI1XVs@1L`ojXAv-FEq17zj?UP}+*(Ybj#|nR{ zjUT?y>^zpSE&`ea$(~2Sy3<6 zdq7h*3go}!R6Ek^n_pA@MAHUN0^cqt|!8m_b`J{pn9Nv^!t@sSSK6yJ}f2uOg zlXWZOoG5=4*eJe($85{Nu?hC8o`XhMyLwWXr?N z@w6hSo5|rrFsi?VZy&;(J;$D#6tShVZ9hu&i0oMdVag@I@p?sxR^olsl5l)lE@%5N z222R(mK0-}K~Y^S^;9jF!U$sbGR<%$22mjX$S-Ww#+}C_+9>Si1jDFeX@)@(`$QF{ z-{R!*9f9?$nY+7^i=o>bAchtgUpPPYYX2TX|7Y89@Yd$nm4E9@e&*Cn>BMRArfc)n z#@_*Wzt%FJRM%9M2lv$^bL#g$?_3i1%+5!5mIM~;Md5ewR2O5LeSG!?0w-Q+W z_RCF0X`HDQxJ9t=I(Q726zT_(7VL`!c&aBe9FS){r$qcG|;U%Y}2+H(?kf?U*_(Ps(q=OVXs+n?9cx z-@iUq5jTlOoY>g2diaEHMU zrHLe-(6%oY(4zSxPQDUYQ(%jtS&;8OBb&z4C8U??&41}f=^pJBlhr2qj7l0Er zH4m6^QkP}z}#hb8A73Yw%fzBvI22Ado-4H zMk{1Z(m17er2iNqKxe6lAq1D&oK2aaN3v8eO>0=oMQIo)l6ZPq8t)<4Q&Uq{cSsj+ zro$dBKV8_=9-ytL>f>o6J`~oHx2-nLJvP>`+E!LQYMi_yhFU+b>2jYI8yVf(l?-OS z*1Ung`zy$JhHiJy$=Esx`_t@cy9Ca}aQWtArUt(P(O!ZK;Vdv5XqiOt3*_$8f!D;W zzS>2yj696FL4G>*yb*L+Pi7@N+LEW#w_n^e8Do5Pj1D>%lQ<(nn!r{@$~@=qxk=bA z5RmL{Tx9hrPLKTazP?2t2$s?$`hC*|K9H$&_%G!r1c@!%8;i1I3Od7D+ju|8bOzdD zXWUmh^zqzd9iSSn{HG!m8Un8?n7~L=X-9@nGsAm`G?O#KE^|}BBL+3sBAaJL{LE|R zG#UgQn#MUeWL|5=8?_5(bFHcB5(E{OS|QDyQ4zx4T$*0^fM!K#cL{oER(&u9#|QB( zAEqt>c(RQel7{>?kdf(hD8v*Ra1Pz-L4iffN9KHVYJ4r*a_3dlxW5HRm8t{y#;+jL zNw0y^s@q$g!;JrUWA1K_|MJTk7eg?P$o;1TO#M2;C4aX8_-9tj|6O|k<%Hl|?5h`> zPQ%>+rG$yzy;&mqd&yjz@kKvbD@z0QGSYK_eX6@)bp7(`@y zq*U{Z_EJXW)&krlZ;$(px=8D}2KtWd2Y5%7?^lQP>s|UT^QM7r?-2<2flT@H4Y)iw z=E68`hSx*ZN$p2b{G}62iyyflH^bW`egC3P+)k9iX}Q>C`7jk#0hL;bdWbGgMTE|*6$^{Af9PYFPmXkf%ig0U zHuI-R{p*pci28{uNpZZ#@^BHz>E6$aiY)fXs~R;p$rD>qB*_&w2n@U@&jpfH%PWEa zR|^wyZ05JgIio3duDK@zmk4S=sT3Y4|B0ysAZi+-g!hHJSv5&#BG_yY4%Q06E`b=3 z;divupS4i4n$QP|ZyozoxXA1LDo_{CvdzKz*f8ezdCR;p^gS^!d$gE2*+AvLgiZe* zC=o1(`j=HMrK!p9=!B4=co204o6(=;^CvIeM$MGj=1k;70}QDC3ghL(6c95Ke8 zw+hqdjM5*_49{j>Q&4|A$U(*6?B^ZxtJje<5$OU zJ*=HGl`$)&6bEuhVJ5KU52GhSvwEx!Jd(FKTwxSD$l&~RCyB2ge$1L1a5blh#p)mq zWQ&Xm4Th-**b*F&6B6Ep2J^n8;jVwNmtbfEV-H>C z#XY2xd4azi5ZRNx(t5o%{7gUeb+owm=CLGZXAY&9ZbsC6#=}op&e?sg7UMPn23RcI zgw9N4%-z*ZUCWck4LVwn<}yv!AYSEQ|CrQjD1}oK;Up=XH=mh*Qof6^qU$c5HT_gG z78vm;G@298lvpMhc!N=$W`U56T@r9I#FNo;MwHYWp!DDqhIdqW?|6noVO@vPA$@R^ zH=Pw&;DD26={enVWW)vG3+o<&TN9Yw;XHMqe9$a#>jtDe(;Czyu+c)!3HXEnB*s5h z%7cg%-#p=PB{V`;2OW`@#hu+vah1iTv2#EuE!@)6;w83v*ps~7Ba>6lB0)cKCOh)OWgR;7GmS&DH?LdnuZg~jhhc0ewsMi|V zwH!2$p#+(oTB*qG^Gg2h5{HhP5g4%;l{_>#j(O@+bASf-XD(wElXEy9oLnwGB!-OS znmkKlupugfBLWhJpX72iZ%|)DpyA=uXxV%~uumw)9}w*8%szQ7yD>#VU6>Thtv3g9 z50>ZhuGAJdzqiE~zO?yjw|KGcoizO0(ZdmVQejN8>xUv#=^<6cL?0;}UNU5+5k93_5$zcWy|gy`(%yk%6U0pN(8-%2jX377_;Oe0GaZqOYGcB)sYhoA?MuL zqI!f@PkmT%xfhGJr@0LKJNqZ7QxO%ZS390 zF66kFj0Gr!N|XnK2(9T^$D4;1>bviTB?w$&GRY*?G&#b^92sV*ecIy zZCxK5L!A7W&}^+=3$?>gAw__R6P04+x1G%~wmtY>u+Y87$GrZGSv(N!cz1pgoXVda zIBF@H&Bzo7|4BhUGieejm4r!%Ds^A3qQ2_WZ~YZ$c#UCvnHh(Ez`=`U* zufyLzd;j03{%6$y3CQb|Z??i>MO6P_?eK4LiJhzn@zCNvhEnQ!ijfGOr6QXpNH|$# zMp;lGJi*qysdpyW^SJV?a*_rLd=moaOMohMCmB&XS6^M2^0r70Q&ef5(s6@-)cTKV=Ldu13j9`6FPv?u8eH4Jsu6ywdc zCQ#4*4IspE{B#^|ZW7izAr-IFW`PqdmHf)Y!g#}U?ifQq7WMtuf4exFfvNao*}H3;|-clq%^pjZ$2+&GO&Dn|LyhI0C^hm zcw#b9X*6hL%NuiVtBUp}Gkc?7N97Q?iHIFur{sza>1rInAbWkL&G8y&FZl}c4Q{;S zk+^wM>wI%#PI|!wln<6GzC#RuZ&C_0N%+4_{?}X=GoVz>`InmnJhScJ?$VDN>Gl0a z{X6!=Sp3U;qy5y3Xm!kv|%A$?&8S zY-RX5cRz+;wHgHChDdI3ttIH;?0c~93|-P37Mct zeoClvSq^=HiC^G^8#K~qIP29p2Bf64UkO|hIBl}^;)3$k7Zk5+;sj%xI;vT zbX~E<6g;py$GW@rz!6w@-pM+7TyPr$R`Ioolt(%}p-hC{T@+`8h06pncT>hTLwyk; zy}ncn(^OP9 zk7X^oJUVTqgAZUFj-^Dn2=@@I%~$4(z-$qID+d^n0kPgF5bpeE^1CSKP+J|LmEPn0 zJ@og+E(zqfnPkf|> z{dcPPalsF&_&7l2{e020bhSOr`LVRF9{eJ=t=N$$@IH0Fr{aq7K|Z&03%WqdmF3vT z!n~YQ<(@Q!KgD%U$g?iem)em*Sp|m~I;2<5z;rFd27=0xKh<2UR#9}nN!35OH9ap5 zDIn0*u+blw17IjOjSv0Z>)hQrRrDG%<*~`?;`+H^})iUg-qa<57TPRd&|kt$ zNYx-69UW_mmmb=YkhWo~g0nTj2IS({yevXA5UxuDg_M!Q64|Cg^Kg`nD)pYNDh@0; zm+pd3I`2V91W0cM37tGCM{cC~gZaD@Y33`J=;*4yfu?H+1l|_W_Edz3_Mu1}F~(gt zN2H#Blxh>rVy7Rb`zg3JftZl4c*kD53pPCq;*uxMb)tDSLtX(=Vrp?G<`S3hHVE-O z7HwLL;RB#&+{x{0ON{8DUDzBg6!wfn(f65JN>>~fuO0FfpXAtE!lS2BFG-~49|9p& z3;wNJ@BD2rX>)wAtFmGEOL&+yjV<2b~TwckO&O&|;~zmGRn z`p3)(hYJgtm9j44CvtTAK4Kp82`GEF&qmBSnE2xBi)GfYd?I;%TjmoavmM~eg}ud1 z!Klg^aHA)WtN+p;TuY^Fq*IR@FfF;BmNRd5rovkIKyuAV_zQKqtB%RCE%H6M*+KYM z(*{*;eift6GMF(qkxa@xEH%P5_RW__oP2V!6;{*Zw34kh;#jOHcJ2`O6gOYlG0O@O zuF828JY~8Tn6k9Dk0$jda2?;%K>0v@m@-Z3G?ghHcv(5k?kKe#EJ*T;ut=Y1GF*bC zq@@e8>tKn%ym?{m-IcZ>`c%owVV|O5^2DBea74=?3kgyOQRgxm#uGhTsS56klaCI+ z?jT0#lreL$m|rthT+*|l3Z+}|5mn^mAqm_LbJGVXstsa#a(QMP6Zf-5S}Y00jH7lS zQtu#k&kI2B7Y(bq1}b>9x1wgGJ*>`5EkdsKAe0QsVE9-x5buM~oDseaH#5{%`o_4i zwm)0yDZ3{*X&8+}bP$?%K8F=TDVBnXn)1}2C;{1-nZku*Z+;e6@%o^-XQ&D5+&pNo ze4L|OlX*&XlJ_vfGuk^3Q1I@!%lqbq@GX`x`=8O)S8{&PVQxv^+E+;(QCE4d36A1W z5L@B9Sc|l@d!C^e%~Fisvj;VHEo2Dta^%wmRe=r_RbgJ-`ov-Sij~8aq@2@&+C+R| z=pb_iC4ovhza0+4Y_+xUK2dX5q@FF=S^$maJpy3k^kM-GU{){hky8mm%9 z_U`z#Du^C^8fyP?9~-GA6?Q--2=Lj-N-%lJmWfa1v<$-31r?;)DwXf5%qSh-_0<>B z<*WI_8H&L2eP}7B*=ACvbAyS0l;B;iY{`E`FD>VDhU*w+fRWY&kNHMf{17i18v9Dd z37!Mu`jR9x#$uVEU5>AV#Df}6F-S~zi%?dG5U2bP{)O@UcCBmzw~$x9n)-`H774!3 zM9_+K;7t0Z2%8+T?fm>iE(cg@0P zF`(jH-0N5hZwIus3XKnO6vC6+52X-UG3V}9o`Im3ms^-U$ z#MOP7PUkv7Br17|+`0i|HKeAn{h|6j*wPj);`U-ek32%aFJO;n%;ZK*kGD+Bn)st+ zAujgwkn%Xodi1X#MhcJJ2G4R}&@sqv#K|3&FmyT;ugkW%j~s3zWC7vXg;&0?%1Cxi z4`If#L<7}dcU8A;h)89$p@4lS4P;uZ^TG;S5#!o ztyDE6h<858^Jx|j#08v#>`x2u@$e7K%gj_zEt!%Lf+TYyGp3awC?8aoqaxp)7R6J; zMJ2Sjy*uVTN7c8}-p~YF?0kME;BbF^m5%_MlMU)gP+tL=?X7g4c^t%aT!&ai1LoHO zEWGF3&?Yn@#YiVMNGG=J`3VkA*8+JeMrLLa-(nfU?}u9}kuq>N@7Rw%s?fGZ>f%Vq zP5Xb?d+V^O_IBTU(jX-zAYFoVcOxYtA>EzQT~1m+x>TgQ8zw0r-3`)6hjiEU44zf4 z_3ZULd+)Q~bG_HO&L3Vn<`_)JoQ&}scYN>9H$iw(Fpd+O6S~IOA zF@eN zN-pLC(Or;CX`BQd7u1`n`OPA^PK|(uIO7(XJnBnfclJ!T9U~F7^M?S6M03~I&Q~Ae zt|w;!d`V#5OJbii^&g-%As~K#oQ`_&*tBGRMYHLgii~!a8Y|f|-6rn{54V9djj@bM zk{n}hkt=12+fLbck5+J##G|m~Fn)U#s(bbZyo2cmC|e7OS{`Y1T5=ZH6&|P$I)?^->QbUY;IRjZB9^M#DK=KAc^eS zoxI1zTPR1jr_o#Gv0P1U|EWT4+G%6&_OsF}TkL}lex0MY$mjTsa2Zlvm;C-PWDy|C zL3-(k?lMtC*;{%RF6wWxXacO{P^p}^pFZ~cEQ^xuuiiSze}?Oic)Ns6r{8e`Fa+qg z!9X1P2XcL|GhbJ8ry)!%OJDzK3`*?6GK@lE6B)ZC-!+<(8W_Tbd5z~1^~>nM7MyKZ z2XuZyWJ`5Qf`KuTmlFyU|Z|jbl?JO=)JIJ z5=!`s(E?Rl7eM#Nhi&23Ay>FqGgM^cxL zzQcf{IQ7+CS=apKObmWf5kJnzF*3ZJtlJWg3N#JT%6q*qw!*70nTRmf^xAh3>l8w_c*f_ipnw zCTT08x^+L>|cYL8vr_zJ3R z)J|TGGf{I-4H^q7Y_zjEs;c;lS{!1&fQwPH6%@u-@Sh!fQMs5iU-@E*GmzJe7OvnL zMmt_rUpvl*(OB1VI`%RV^|FJ^OwQa7A|tUL!Utz7fN{6`gbYdUQG)5i1mS747|t|c zjVeXOTjirr0k=xJoGNRf?>P15TE$+53C#5rCr!!xvF?SnRV)tDJs zmZwc7iXY7y3IZ-g3RKe71=M&3CEc`CaJ$-^ib%9P!DlEN9{Z2F)|yA^VrOOomEUYp z4EK4mQrlZH-m-aE)6{=_eNZcbYq;r(ZmSaO{TV}=s^OHd6vCGowR?)Wd&ZZB=I(j& zEM<0kZy!!Hq|)E58&Zh*o=D)FZwFJWj3;32ll+8YUz$~_Y?4UwmAfmAoI|p&cHTvl z)^2{r4)VHod&ArFv=5JlKcY26|Y zO$h|wFn$UcTwk_*dC8ZK;UCs_qXz*70p8i&Vu;*Il34@lpDipvn&{X40|bmcXfgO5 zokLd8IodH@5Sm<-8Ats%)rAcSg}A>H4yqigzY{brdL0RrX--OR7Rlxvb_3dh>j&hf zHVAgIM1%TNUWJrFdW^%vR}Uus#ICbUJAMExex)dY!YZsr6wezdRsV#)`^!?KIv`QD zG%O&RxuB=%Dz1eDBX!J?veZl@GM zIt=np|0^VRbc!&4A@cuL1-soTPxHhu5J~!rSWM+hIn=#7> z1b4z4r+I?LGwTI@fUp!RD#obbSPDSKw6tIM_Fq)Capxu8%1 zUXiQ0L5!x}#7I~7Jl5W02!)_qNqxGbW!p36hH=>199P+iERKAk(ScIA2|eqc$s^}C zGO8gm`<~2Zth5D8lA7@$qIxSM%O)qGZZjp1JZ{3dWapnk)pbEGAccMcTqC;Rg3{7@ z1$1yvZz=HX)Zei#`n~Fjq21kb%mQ4v`lz=_CA#v4=e>fv+6AUq$U4P!;@OB@3(Ic1 z;gkBn$WBiS*_}7bv6Xh(nyXdN>>!GUfF~|t*8sr?)Fm9Xwh0Vj*9c1A~?+L5=GY^P-0 zC=x`PdL@b;A) zMl?!4+$}9HV(hA1<3}zU{OGc|hm;%hDai(#o15X+#*0auyz7nHpJrYRly_r2V|mOb z-c957uziD=+ab#Hp-@X1%OzFWf$g_R8z!5qFww()j<-FGSXl(GM#z#=oyLjHxopRv zM4bkK#UT#VFIl&Iy3e+(Ql><{JuPSQMTi&$dO>dl0}kxIqS+2;3@S zbC3!Te?&^nnJz)q-y1k3n(Ac7T$TWk zdmX?>WV8X_cnAj~TFA!TD_=sE-2;@)-bv-L!PgRyg@e z8(;p5z+9l3t4}%wC{}i-e#ZiK9Z&sx9C$>06M7W|JZ`go-T>@7Mmev{6U}|Ao)fUL zb1!``h^}v?b_0=lR#}=O#0#rDXmfi+lU&6nBx@u~yJMMV0x+KNMJ@)wz;pbke}e#E z^<6B$nYvdPumPibxITZ{0?mw?P8ddXsg|rO3yHCfQ;!zYRM*y6Xd2aY$5g6IMZpoX zQZzVB<%W&qw0_(-`^`^U0$M4yiy4EuIZ)zYOS+t_4QRtHZZ%;CylA(aypC}FKwyfLA#5F90rSIU_%k!_ zGum=t6>*a4L}t!Yn{mx{iq}f*b(1X;$8;CFC3P<3k4N503zc5w&_C#KA~?bHM(@re zK56ZliIW@OXt+_S@>L-uZ_FM=-!dDf zzFiKjetViAn=I!m(CgUNL@NK60wAHnp$v|>ZOAKW-=i=4^(3uNK4E+^w6mx6@0#WF z55%T^UW|(d6U}b`6J;f@4HcbUIs>$${uZ#s{DD&zEwj9Atnj*YU&7BFZbbkVbwWPD zL*zBmmBP2GkWg-XvvBV)jxK>o1ljM@PsX^9hX-t^snYZrH$gYf*NzrI7F}ZLg}ze} zS}*ZdioirT(6#7~$Ag*+v?UAhkm3(6GB#&mUYC0p7!k4^jY4d1EfxL%bYH&c2BH{V$C>8)sz*7Etmj!wDDO?39dfsS11wOupW3S^(Xt z8qlf56LN6+DpxPN6cVn-aSU|5vIZx}@;7sw!zy*kKG3jb++>LMlIC%}cgWMUgm~hr zsg=)lv1r(Y!u|mDH!UU<5T}`jOHv9?e$!N`m9~usjp-71QlPo+tHBYH07`>q)hMVG zfUeyI&i9nFi1EePRnGIm(n+L(;aArWN`6HZ0`1f-OVP&@K!1r{#yB2^lEK#z4sH2* zy!Jc?s0nQUDTG$ZERQ9Kr90RcrwmdGxrEC*dWZ4C%wl5dkwj#rBRyd3;_3x=t=NiA_39vPdOKy?Uw=fb3VL%nqR5D1w*1Bk^H zx<7BhPMXV`BkbqU>qs{n%g`vrvi9wZtuE&M>8Ph8T37773<`{;JB4z4%V?|VWQ&|I z2vhI!7Ip7(-BIO&&_fAT&y!2nkm04%u|mOW9+zN}Zg!Q3eW2S=y%2V zUiBPTb&Zq;{(hFsu-_IBPIrw;<;XWkH3X6pxNXUnII)}&?o>@o_6Zbo$DkGl%5ciu zzKF6vnLDr!l8iqvtfS~V6*RbhWydMRf0t_=LYQQeYN)B}_PSRu(76{_-{2T6fQ6Z@ zCZ&{QZx1h=wcgxjug%QWNZVhOq)IFPpY`PbRo%EU!13+A8@}oN0m__;`zcKR{3@1Qeb{BG=1l*T_Yx z>cDJpv})R&y}}*5Y9WX|xXPRc8UZ$cw8ZXZNh#kA$C!&clxBF8gcK$03+oW!UMLSIZ5S!j#~Yn5e0U4FWZgMNAX4+J+vlu+dB zL*VAz2cG(VW8esub2O2Yn*u=7;GDLqRjr7q{__jcKX3fMy?^>PY&(t3NJO91^#~e* znLim*Kzw!jIgRWRYLQd?{hQ9HVQ7;W?0?=dr- z_D5GNM4aIv_TBadFuc4(3bt0LOkRr7mg?$Ht!!L)=wdobJ`?-*CsGG58ywOBf^OZm zE#PW0Xa{D>8q%OhvQSR&Pa9lv>Qe`tcdvRW1*};^)HbXwX=F)05y?G;5pY3Fg)&z} zP{-`;cTmu{uYYYcJ02c{Yz%K8T3}L6|NKe+bP*`&xTg*+By-}wRCb1RI2_P?MI;Zw~%to0y(wtjx}vU8SkEu}!hN0L)wH z4)~IU78tGjG>P!i-o~dx$pm$&ngbhHyexA*PVhz5cK0RTo zyM|uZ*wRK$&1#2!daXp^_8P|*QFf(J+iFT(xmc-ZMUCc}qxccz#W4XaqQJ%dj3NG_ z-od3bmpHh7L)#os^cbII>l)o9gdR@iXFDUx>4BdXeox9tb{(C!bCuO7L|$<-qvHFL zPg}94U?V<>PBX)JdmU_Mdv5bI zbc`pu-1>b?mKrggnNG`O$nKuDimI*@l!X1u%K4^!Fg!b-Qk*Z}iZ9bYER=rNGpcxs zgq_NJaO7FB_I>RQubn1S6&x>(x>bGb@dK3i3o~`hDs-Fmq^~Ec;uX;+z=Z&}7hBFJ zC!1ZWgINP4Cd97@&#(Uz5#973tt{Ya^s9Yv{C~Hk0;6}vyg2{vX-4pyVa_L#WQPy? zz*0aszCf~tSYPvUzyX80xJD3I;>fjv}OY{*ER)h4q4ho){lx9U$Lh0xxm5kFv7lnRqrrOa-{lsi8v`x*kl)8 zYL+r)eiys-&56G{;R%Od?+)9pZs`t(I3g47$71<2*SEzDhat z?u|Et6pFw-($9b*DNuwT^C*%mqEc+|-`^EaT(nq^C?hE9YV#vA|CE8}>G3JrX=1sK^qR`u02Ws?EfvmF8E;|9%eo?}je! zU;nQUUi?ZcEj9irM!DbZBlD1I5?KBD3_VVrgYFvdJ0n^>BMSv9W{$L%V(}> z`$o=v5--q?BWZ0 zHu(f6cj({*Zcty|XzPUN>aOFkXAk8Mv7O)|Sqfq}NY)1B&dld@JX+Ti>S8r9leuvD zn!TrU1Ea->jid$2aLLkGd}&q}DNS8qa*{07>1hfx>xq$>Axtt>#l~F^7^y#v>GS;o z0$XjOroC2+kIl9i+AsVE8(U4OzJB7en#s;O)fV|Go9sJA`(4&0MzAl5P3Crt$o`6% z`=(~7$HG?`d{FFw0$@9U$2j}wlY`(`zpch#8k=Aj@>)ba9mbf$5@F#rSFzgr*=+mV zNe&9Y(D=$aRzdkqO%;$~F_KqBtcK>9+9D^e$U2cQYO&GD99 z|0#eTWe(6?1)z0IR=;a?5p)4fw{sEDKYg2oA0g)q?~iEBcKWW-y3woO5@Efs;zVm- zpAkS7A$D{V3N=o34t~+n?iKWxdPYb|mn3zICq{dS2jm+lG?9~bR4VPnn3oCj(3Zv( zUk2t+`C#*IYo>(c)E7ZnF)Zt$!E#OsQS|l>z8<}qHkgX_!7Ln#44e;Pu;5wE7aBJi zv!frR_q6d+Po`bUzV>d0N)<#Yd@o9d>gieHcT8ave?eD=D|P;q4yGdG1XXG8^fR3% z_FI*(MfDqVz=8NNf=8I=pqC|DbZ`t%tP~umpX<^^ zYw?|NTZ39g_QFh?u{B!NGbNL!7qSPsOt>(ck1^ZsaOB+An-i^P6xYx`jF2hfZl0Bv zu5iBVxOQy=rZ#cW4ngj0owjQ7L-#f4;oB=+@V!rAjuU)oCt+5!ziW83Lu49&Y&-ad z9M<;bJv?llQ%sMlUiQ(o64!|wTWy6HXZt}tZzRh_l+$;J-Rl()A(K-%CXV3mC=@&~j6Fy#8**hyf=WJ{dQ!`jno5@_E|79{`gWy4CJ zp4TL8?`zC6mNsg1I#C<=vhu3I37!?~NA&o9QVGrZPGeMbY3D?|D=%4(!I+s8gFb?GHs?F>*p_#RKSTYt4zz07vY z0YKugL?71|dO~jf%35|8fy8_|_4awwk#2MC2j?@a7q%~j+Zn^ZbDvUKtdv;bTyE%M z96+&Ay;LFG!@<#eY5S@DF;~kYNUoLHuA{cRec>Q>1=9FXb{QFEN0A^uq+`xRokXS! z|8%nbJ+f)e-2sH3R6QIuEmv@h;AswR)px)sXbs#ZP+&#{_s)Y5@Vh)}@`~tAueTzw_s7-qMF< z3e#sjEZ8cQwP8%byp&fT){@r_8AkHcF_@>nXek8kJDZMY*zbAHt;LED042JUH*kk= zIWCVbu-afHI6`I+=OG}!kpNW}Bav$7U*{y#gpNE0OJY&-$lO!0MJ}Ss$~Syb8|#b{ zXk95lY(rj3(6OKmL z(d1Ra;qfrP(`KPf*~PAzT&ej=0+q_-P4ZRp%_Lw_@vqbR|D!s6n3aOXrFQEY3_bIk z=se~nvF(GgQqqKAT<{llPlw^JB|yd0Z&(y|R>unef!#;P7TzEanLCcVle1;x9E)nZ z*PjLksf`a1;mAG1Ux``dvIj91XJ}wFIg1qJ^|H(wvq?q5p>eP$fZTRP@xJp;)Ub+d z7J|2GO3)|cP?8sR07wX1Xj8{mlcD)5>uJ38&+JhvDv`UqZdKno2ll9z$oQ@wgU+L8 za*E}-xWM0cbrejHVm}NpD=d(_v8t)k1d4O#WEX&W{AD3%wAd_7v99X#qoF}gH&c8A z(JyQe3ODb@ie%fB;@4B)&E~gvS70b}fm}wfV5J;a?mOyOp9?R>#Ov7kQ(PGNvV--y z+FHmbHCI%Y2_g&v_R>SXji}^VDXoBfXsz>$c zDygI@`f@#&ZC4%>ixN-CSzb(eMtn{m z@Z#f zmR-2rS>))FepOV(&@AEAO?uR3IJ8E26)IIC0&TiC8m9jq_pGeE&kvwYYnb^G)hG)U zvS!u1ssW(W{;SYtppZY3TH3O}6@8@FU)FmrP*>7ZBR}`;gyTe5B*e&<{{aJ+&Dm@8 z*?9QtyEwqUAt;lU<_z0L_db2H~Zh`@Dksvx1j_TI$NyjWCd>iV=t$0v(&G zbo2)dBHyp`?%;t6aO2&boEH##fS_j(aOpzl&{* z@gqcne*Nb>pW~ka{dw z+JqP*`7qpiDmVv#@CS=z^{935Igqn)9N3n8KSO@fkV;4Sum`p8o4P>OzSUsKUdgGM zoZJUnDkMt_6AYNsp2F#^vH6e@)1)yMxQW<==<7FmkAgC_i`@`xM%DIFt^J7KVl5j& zV0;(e*jm74CApVmSmq^Ah9YV%_~&28DWbnp;5IwdpZ%oh`mt&KD`xKZl}g%iJ7({v z)|UCwP7ba)go8~zGyp3JZRsgh`1Oej{`2V?{MxXKKAEgU?EvbdtoKlY$tiB7x~H_{ zt2rPS9IHoa2iOW8b~uC30zFmbAE5oUlL_ZcA*n9w+Ul_Lh5c6o8Ja3}-8!XCI-Q?W zirVhp!cRHA0A%B8DSE7rnR1lMwS@r53SzOer58^qd93aez@uB*)wk=2WdCY`>h=mQ zt`+`dI7c|$8C!3z(*rN7H*{UiMKt@iXd;#uE@m2cv_RtnWwPGf2UDMz9va=!1y&4u z1*EV+N6I7TcNC!cuR#H{2Y6`kdw^~n9b7YgAX2k4O)`h<%n&WG`QgJvt z%dUYowE@Z`hZ&#RaZ9@ziE7!kxD7O?PMP?ZdY9$=0t+z;p71M+2YQq-rO8}Whe24kw)J+$Rk`1 zlFQ1E>Egq3=S-$eqE&8+miJ7Ac4Opz?bqYNz?x7sNc`GCGQDVZsAdK+`5h@5heZvsD%F9|zdoA5i_%0l>Si zs)vf2}EED?9Cpq{7jPFA3}D29zaa~I31-1on1(D z?opCPIQB=C4trU;9;r8xo=$4yHNjJO!N^m*)4qjlD!|!`{Brj9Kb3Vue*z6gmxJB` zCw^22n#indx&L^EzkNL5fQw%b00a9c?@|1}fByS-$Q6$BZuMIclE*CUwn>|M3~F)k zv9>VA=fRTL;O;mfX5Kg@+_AE63znvATJ26npE@hyADSIkX`awfNR-Qfr8Y*|=#$Dj z6L}6J^-H4N&DjAKvq`eDwmXA#WSQB|D< znoUFMIUD=B2y2@CRr104Oj}H?fASvx=p0=b{MY7rY8v0f|Os03a zW0I&(ba93fG()Lzj(ufrgE^$nE|JbIQ-o?Jo7X6kq}OBD_pUUc;Ax*lO~ANTf3ykst7#J3&VtaNgvHZ zbKTWc*wYb4Sm)DEsa=QA9o(Qq6EiL@;Y6X#Mv#sfRd)W~`XQ86xLltg&8D#$3uZ1& z1MSA?RNhB~-lsv8JZmXIyoAIKX=~1KIX6D#69}P>%+Ec-iUSdqrjZDEd$z0w9ou9- zkG#ezeSAEbWI5R3w=Q#@K+{9*-4PCqbCRZ`?McCmKrpB&YIp|ihztyupmsSLc^ z2P`NOskKG8Ko!ads6ufsT@#kz4n}BkL3NqY#A87D4^LcIi(qf#eSgA$(>wbx zMBQExOe~VaL>Q<=Qc+iS;C!SvZ{gX={>=tQmEA@8W?8M(-9LTopTCBms*6)U6&-*7 z83`xH#KdC-^5{&o7+iU(HxJU|E+6y(HP0diz=*>~A8@If2H#rMR>+0@L%HgH9|%~^1l!(E0@X-1ArUmT~! zAr;j_Ou~q(AtB((IQzn(`PeP!)P`R3N!9prqz6IcfVvZqF${Rz@+%@BOsq_t>9QX$ zm`6}o)+ud18!aD5Tux@)+Z}6QL$fAreOEP(_uh%X4(Dr;BYMP$$i+OKN308xnge7a zSNml6G#xqX%KK~gg7j?53%EN6)jjZy55$#MqQJju{-gqd;0KE?Yms|k@cW~z9;ZK8G!GHkoCd@xt)U{9VS>XC!Na9M zA=wWbe1v<&Vw^xyq3jCR4tNKJojfc^c=4#(Yf%7B*%$&qJ&ei?D{(c`8uJvfjXuwu1#o1Nhd9jZl52KzGo17%+nmu_7v33f%cV@hKf=H`3!`|2S6FL1&Gps_H-o)32E(lMm^gr4`wsmYUmm&WNC z#Fn-#I&l>{kBUZf-b|j>2-n05OQ1F>=#qxu?)<9@fkTu~j}Z9o%wGamHmX+5kh`1a z*tf&8K*t?5OG@#KggiyDQ!1{!KT+N-;Kaj*p$mX)ZHob@lK7zjA|hL$%X*3jq#vz; zK;#P=$*lSTf;fY(AAALrV&dQkvbovcnb5vZCRR0_`#&tKOS<f?Xjey71p-t-DgFHx*(L1lK=kf`la>F$7H86!F1*$YcPS{ z#O;de81rGI=<{kjHb+3Xy(CR)Ug6@-MZH&bFb)>7KMbx{7TU9*&)z0KK$yIxu{P{q zHr8#;D{2#+yJqxg%m~&DVv^#uMN1eM*@8daSw3LDHQqQ|jkM54dKFwZ&Gk->Hh5!a zA6@SC%blav(I89M{fKx{wp1b^tIoxmVll@l?rA-*_WWX04ylg`FHFz55!o?d$RF(B zOOC~&kjt|V8bA4G3#yipcJI z#Z-(<7|-}=70I0h<_tD*c5JGPg??(0$o(WGhFmF4=K;S4e{vvX`hpb0N4KU{(+m=G z8#0L}HoHXskjK9cdUTU_2sG3Kv)h@ctC*~bS0>l7H{@@4%+2_{Hka^9oo$$M|B0GU z_g8BEMMY||A`(-9d+a(B=iqaV7mo(%2P+qysALHvh6q4xBc4%j7^KxF?bN@>=4)5G zPP2aq`|$NSu7F<~khyGY0nX5`8MT;%M+s_=)$rgUR6_j69v57c+vl^f@8Sp#X zuH-L;LO|lsNjAL#pNNmGs{s`5{!GnR4U7Db0QtX_U;eXyGqCFlpX^=mJi1WpC;38O z?W9e}2lDH2=oVsAJ9v_~h{?_%Tl$Ij_!}M3?n!0TR29C~1S-gzrHJl~ef9`g1-D>} z++R7EWn<|7l**Bc8X0m%iZ zPet-pRh;cYJflLKKjr5go(*&FqYu{Ija(_vy0VJkh>}L3!q^c2p6OtE@h|DM5w`dj z0d#&UEJpSi3T0X@9awXPz1V?7{*`6oDBTKOzE7=zXaxwJ0l7{QJ|O#y=2{Xt?wRW0 z`;GfX2b)_!Gohv1KSR(t5`Lv;2;=6u+r6n1xJc1bE&`fH*M zB3g|zN*67R>Vh(oI1_0JOkB_iyaH6mpO0tNa2FU_)viN61kyi*l(K~%(%rMux%_gi zFzg--8WP+0^0WO|x`Hx-^knsns0UjG86W zvqz)z+Fhf}TgM7$$U>s<0pna{J|198mkg=*VwrXE(%f5J7gq$ERDR>>aJ#cLdE>>U z-ow?JbAW9F*+8haJqbt5kbsJ#e0?`V}^mVjSgcnhQ zT4whHS?pCv0^pa;Bf1F)k;YMPFVqd=EaufqIi~Tnbje<%az)zkk3AC~C_H@nK!Ms<`pszr+F(?Nqik_! z&RrxMr=JP>xt|}F&StI~xGKtf1+r6iZsSY-j^TAEeEOAKdnAwZ?txliAdq;H|0}K4 z-|hRK(O@;Ww@lLBWcrf)2W>UPzecRPI1<2p)e;K+PMvlwYp3n}x7prb{HXtNoEo{^ zWg#FE=$a$Dm_LJPyt{{C0kd?+>vljCI4p|aAKiv0SHH#o#`!E(rspK3I`w2o8}(K|%*dM69io;s z3lU(nmr=nMAZY?L9D9vq2S7r9pNn$BxO!yO`fViCc7DQgt=%w5^2xRk<^m*$Y?M`@d1|sJ*70a zQ(hi~>+xMQ`i%1nU5aeVpakRj)pZfC>Dfj(NBQb!;Uoc64zC?{JVag%l7M1=Q$hUo z?*K_$74tjAu%|MFgN%Ke?31NrEKLwSVA00|44Zh=xrq~LEWVR>&OSfy}&P6km}w8MP3plajqe<83_Kx z@5ub#@2K%NzoV!g6uz#}F5&vp#V}A?QXhfKp787(x6)!?+Q<}u%e=gk{bn6x(m%i)_(_O%meGbD%5N(14Q#n?Qvqcb8xPv zpCK|GW;z7phDa6;fZgBn#5#+ zFehu#qKbjRj1I@XVuZYS;ubCiWlW_JwW(+b75KAh$^Iw{>vz1}tMcVzWzO{*Nr=Jv z)tnKGjxw!q^&cP9j{BV$gd5jw@`1iW>caMC1wx1gmFY|jN20Vczy%7{g)_6A)|=Vo z{fwWqF*4AM*GVv!?&x(%7gvU5A+-$}ffdZ{>wKoX2eC-U`L@!xs=tev6$eR41Y>K#_K(QS_W<%H^_;my!yY2%kQ6ObOJ(yU|V`Y$*M-fpkv z-()p|ERxWQK@;useN#L&-?};qS4)qGO?174axbE zk)!Fa6K-xs6omEk1htgGA|F$l8_aLxl$cKAx``hlSIU5}pD*pKthN-KlSR@`CIq^6 z=9pR9k{t}(DU_d*e(`0HHe@zlS4bBt)i((aNz|TvO!6u^3ir)e-i=&csnM)pG1eIl_O6bHC_py(O+o*823}%D zZqt$FsAh9@IHBOSCYrQ`j=|GKVMWg<1<%}B^!4?W=7gmfV%F#T)WK$qt#7;gR4`C6 zP{>cxoJP>|T?F_x!U#4IEfsrWq9t&Vh{`>>GY)1;ro`uVBJ#f~*e3=`;A9WPmQz;{ z7Xp1J6Jqmvl1i5?I0lV|##$d?0TBkD&fbWo5qlL$s@2Gkbci0nFmwgb_Z5slEs}H$ zU_xExJtNJUSM||`iu04*y@5dE2Gv*?R~kjB;n|amittQ?(<9?yoQX#@<$Q!w=eV#R z6MI7p?M0T2FW)o^C*+nilE#B}{(m80{y+KfWVs#WSvp&{1s`4QT2)BjM%-@!p$_oi zd`yl=U;ud6@zZ5R31Hz&Tfk;o!W#PzEZ|AW=4F31sC;%5*SZi+)`0^khNN#_)F@o< zq+K&veXjWCL!^szBmL6fybC_iu=^I-NsSTn_QlyR2Utt_(p%QDStdTz6eW;=MIK@6 zZQTZtL`f!MJ*8Yw$755X?i<0AOONA<1Hr=`TI_iK_R&_to2AyrXQZfq@(TJ^M?I+2XU>-XeK9qjvE{M2OX7`1>RFi5>{1kk10H4jZm)I zh@=EC@=8EfI+o{QPz585Qv>i=|ms(yFxiJ<`S@T&QN5R6OLCy1~-rL08u%Iq~vAK(jSH0s#ml z@L-^h@aSdQuXt`;7{Ln)9+K_HPv@H3_=J5Q_^XDU(?mKDSF{X7))PlU(<7_?k`_XA;ta47zF4w6rx;slqsYz7g~c@tcGjc#gnTH-^4fY#3jU?kktXEnx6jA+DSC zai}WuhSI846oc2yC&0TyzcjTh{Y~s_W42`!^gN+{Pr{-Fo$VsVRkbxG-<; zYVuuxij2PcwMT8*?VG5*5{UqS;r+Sn^u$Kw^3LWWCmq9DY5I(gv%es&-Lu#>Mu35k zNk$o;JZ%Y_td8_eA?$iF{b)|lLRqgj8Nd1kFVHMUD{F!GVVE`xq77Y%k)SG2do@pr zoWI9t^V&dziD|{3W|>+B7qe9n(e!kXYsin`*3m!OBUuSuFxdh zgmrz6ivS9-El|Ok5>Top!GX4D{{YEu6qr?^!4hO8;I2zlD7S>{iK6*Sx`Y?T5a(+f zZdxKC9d4voOBfcmS=)AK_2WR|J&;vOxvw!4NQBtb|G}IF%yRxwTL$K5JiDQFgMd0g z5wZE+uIGQ_&wq8qT3rGEI{OF6S)J`CD=u9@{hheGQBjQl;F^H@HLVi)HLY@q%A$~0 z??6*nn!su~)`GcX&;!;)2L2(2ckdWH07WJ`wbdFz6d{$!LOS|m`m&iPfCevU`0j)Z z2tTC%v?cl|zp&*e2FQPf2LgzN^K4D!wwGhSZKy_&$OXY;>yY|_o&OhmZvj=;mSqiJ z9D=(Cg1fs*@DSWdg1fr}4G>%d1Si4W9YP51?(P=c?dChY_o^zd`c-vxRrUAx_m9p< z25|Sehm5`NSu)pLbEyqH)?5d=OP8B1u4@T>c}{`nAT$#tIdtm>sP^awXm=j`0AT*u zQkRQAKo9&r%RsuYmJgNvxuNv{0BCMq0K6aYT%Ae}bv{2pFPE_+AdybIJ2ncro}DJ@k>?1UxCGX(Q?j7ODsY95T?RGtpg!DEQ9?JpZvM3Fbj&?-wmF-j(Yj#-81p5438Wwy+J*3X$ z#|n}(kZQ%c>Ll+EP(trxXM9yn6!EpI_(Gz`2YI$*{r6W<881-Y?`w07W>3!*+l2Ov zkyV!Wkajh|Hh5XCO1-ZU8Ma2;JxdqY$w(C1bGxq)Ar6Yq?=CV=m_9Db)<6%zenaRh z5Wda{a}Y5&RRCSSs9+TWRU`u+9xKNLfl{*Lfifv2d+ZWnm@}_EoU5tZkEQ?Av_?$V zZ(_r_DC0PMhvXb;+~*iW7#K9uAJ8-!`WrD(IRSqx(Q-D1Xkq3-31dx~k0vq7L z37jb?TYX3KOV5IA=}%mDzHbjmS?T>!(c3oG8k>B$zmIxlnWyNTaXBqU+8-nj3E_|U z>>&JhOKr2l;QT^tRXq?3C{v*OkMjRNdQDXWr}irPqm5puTNEXwNS_ZBkUC;fj&dZ` zx;MW1kb*^aSSMa1CBn1fsj@xhG@mF{KYl>zHbKV`U4#vliBI$dP-bBL6tX3wO<`^b zO&$+j>alV;L`T@d2h`*LYFr|=Nhm1)Ry~b^3b(w*Ea@GVnQ8&49+6=_k@6o7Jgkb5 zlr)2cw_-Th)Y7l^r^ObiaSEqJcv$copG*9%o{K3LJ{VcE}(JngM4-M(0r0hr!B?%O&%L;1yHJK zuG{Bzt%}+Y-Q;~*s_ftWrO@9E52;DN=H14E@UAQs-Y_2rghl$c0p^8&NokhZXgldg ztE41D19)g(nOnQOvK&SBZbzW>VityFNnebS<9OG@+jelj1Ep5TuFNSp0g+)0Ks1tB zfNNC;_!<`#x@(=@VA?NS-0A?_|4GO8>|jp!{%jr3x!Xqh+!EN#IfN`Sf`9*_P%KGg~$mzY?U4rXSM?_m{U&YLpOS{QBU3j7;eY%_pDkF zc=-L@mGCttPz(ah&s*VTpd|h^N%*=D&|^~jn~R&wWrvvR6WB~SNQnL+{J4=UMG36u zBCyi-y*(G4BRk3=);0nSOPR&0cB7|AJg`SyNr7TAioUF zx)UNfS^%E17a8|z+Mj)CvdNZJLeRJ9j(eotwYo%KI8#qd?)6TQVG1GkrC6KjjmnOe zlYSy9fUP8*$Qu_B{M@)eM>wgTeh8L|NBej-q-jWD#|DE7Rr0xk(NwLW{+RPi=D?*x z-*F-0$e_{<2h%F;Nn6h1rE34u-;sz1KTNDqO?po>^piH~1+NjH3eMQVw-VnmhC<`e%isXutlay);S zXas-u+kE(`YAi01-in8k9se!;Fyo8&e8@ngmyrgft(|O;> z?l9DV-dg*ZI5YEl4+TCm$AzD@?!z*SW=+qVN~@{6$OQBT1Ia>~b!a~r&1(j|BR@k|0Ju4R!E+Ze=DaErO z$n9-)^B&?H#Z9)+aeKpp?B}v>BRqFc_njcX`x$t$s;Ozbl;M*)!e(hNH%giRfp1Gn zczXKY?VHE@Gj7bq9UNR-UUnHs_PB-hvh}HIi{z>b+C^QU0weynpx3{= zoWvh8}18?SYal3r0z-d-vYVngq`=|vdd=eKxI4`0e z?187tsAzDk(zYbKVX7F1zTrSqiuLRnyuz{lSrO`(FL!=%>-VDJTRcvHpbEflUHRZX z!24x_fv5OaqA2K9@*biiUb@>F8`lKNR~w;sg7Pm=EQh?Gxk>3vRp0S2*p@NRD8vzg z#mJCIQs_dx8o}7MZA&O8I6;Qi;vKQg^ik(LUFY4oTN|jEB!M7jbuRnCym>i_I?5$V z6JhhXSdrlqwW#mcKCO;Gshkb)<$o>m=~J}|ei#Nr1HKlB0y0pq4tgE z5d!^!=S5JmLKFK=H-T@z!Gfh?7h$p1@dXSX1wQ#vf4=k24`05M3`L?;ojdVD+We~< zhLp%Lg}0?Bo>PIpfAn9}M)giGk!gI$3BVpi40K<%fu5hlG;u(1xHMLYceYQ zC4nN@Rlhk&xBDhVI3)>(+w>OaoIR>8RB|JF)I_Y!bjy;#>hA`NA{R(r=3f|^Jmo%8 z-dP#ot;Q@3ED09%d14vgb(i&nIo{+Gt6^^^@|A!yyvS~@{OJu6538g*n{&|%#P|Jm z*C$j$Eh-0XO)B@;UkOE57DRsUB2P-aKS;ob;@NQ{2C5`w^}=QQM}n}SYibu+`IbsK z6R~u367=pL(ZD;bPQ z*B)|7lcX-G)kk(iM&EcJ)}ndvhL;5S)dZO+3zn30pC`vmHM8e04>}rBB$y6Xc{Q zl*4x3qY+=;L&xO#LfgEoWsdK&Qt;YrsLSHva;VpGS>IF(3_AK*_m$HTa+o0B4! z)Y}Q(DV5lW}Kb#Cxn7WKK+-SPsWx~I{+*+1ujdSR=w``{GY371ejb@z* zUnk!4J7H++cZW9!g*%(3U`ez809TH`v0i^(5?qX?C1-2*e97LB7Ru&eIZ_Ib*i$uD zbFOdJ4ZRW%O$v#Su#%5x#W@pc_mDG;CO$W|%Ooj*0s%8KV%8Trw%ZP0c##@vIt(X~ zJIseNeqWS6xTAo9^#e4f|C0o(r+nL~=j$I{!6~R3vG$WyT0!cB5YhAqGi~v^L*??J z%BD}htgU3@pxfN&+NF%oc8q-Ih+)UO&a-hl0!LG)G503O@C3cFzCPik#D=;y5{tk8 zMk!tq*8AwC#}rlkiP+_(m%-jEGDmAuJl1)!rflfA{sX=&<%s@ z0o^;AUz&7?0tjleIKPIJZbsPTK=MA36wCW4xpT~eH&-8*ntomSUaCG}UoKQDRUpZj z36}f7ps9X6)ig@m=kj&>^OYIxwUsUXjk2Scj%W76LNz8lV>DAdqe@sXYD&JK?=Xm# zP)qCiK=0&Mv&0(I>TF&kc&Mdi0R6tU;&495Tl4biMfbJN+UtTfVeE(aVl_tSmrKt{ zIFj(X07b+E`Y~0^M{=ny8PH&moj)x(KCVRIuO*V`i+vUkGC)<7-WP$pOl>_!1PbzB zRDb}b)ByGRD(s={zNoI0jfM#aOU2RwUJ>;Wm_G@LI7`4UMPpC?HUxaaLsF3Mj6hXe zfeh`7ZKSMeLxBNt?{!lYt1V9(UQ;vOGw+KgOig@!m7U(PkSTM1V=Ur;BWI$Y(V+;H zpT~en7pNoW3;GHPw|<^;3T$|WPR8Bw4?r&xdtj&Ooe}oI!mUAWK!(svwCGvZIvARU z>oft$nhAjzHTvE=o&oKpO$osJEd^mdqxkj}glC$n2#Xr#O}((=Sd&xx-kGQcdOBYT zwbAeD{TjXJw=a}mCf{;e`Z(t;403!55pvLRhkaIMLSumjwHcV!pq)_|{hD|Zl zx6adHtjVT@Mo6p3{HmLJOamD`WjcKC=gbbILQ%ljlsq4+;m6cS;TJ8=u*ddwihcHV zut;OZFBvwjYOziFQAgvun&Qh1t@(&580h;m$2I{CDa|afWXjR)DUkb)Y-b{FJ(pPM zhRWfiU3Zz|h82XORrcXCA|)Jex;BInX3yBYnW)P++1tMUVC=JWa61B{gL;Etk#R8z zC=gFYn3&&y$0rpYxL)`y*A#FPziyX)H#EUaS{qdn|8;nL`ZyEuT-9!%sw4Ij46!)v z1zhqL(|K4}nuc<{9FGbnoK98-?+3BW&k@Z9yd<8}q4E**X|J#cW*1|e&D0S)gbi?3 z)B6;0UPLy$hHF?~Dv-A};wUM~T8vOrxvC74V$!(|iALfPIH%?%vhUQ4tNPsFS;n`o z9($}k%#>^xERU$u*zAiBx2T`+M4HmRr)~Sw9-Qny5HS5p!KK-^Z*D~SL}WH}WKC9> z-)o?{0-?FAp5|(6 z&A>opHIW%L?=bu)`rcArDF44MoY7+A=Lb$7g|HPV|1RL6#7H2$zD?1 zj^G1)5zd?+MoG;Yyp87D=1mF!+5u9kK?ES-L0Z1pB>@MW&#z-u@X2q&i_X0W)uEn2 zal6Q7mnIsU!otQt|#aT zJx>q|?Oyb+Ac-k%t#Qi$``$`{k%6pj!-E0JraI-Fu_HVrZ1yUXq&rEiC z&k({k)^$k@u+P?mIXy}5l1yD9;xBz)PAcQsrx)!W$y}BJ=5d5X8W@ zHj1Z?N9Nw+4=uTft@HGsWGBR^U;h(RQz@{I1jq*GHUacg{mjK3A+H0$+$NmJfpPg|pE92PZ&Q zl{wXXnRu2g6>k_xt+4p=giA)5SB#BEa9=VXn6-gp!d$hhk$893^nDP1Hr)A)*kila z!zB|bdzAT8&=`$6O->L+L}~1)gzbl`aHd(-A?~MJHRn4_q<0E)IF!r$(&;)0HwrH{ zkVuB|e}HT(@PRB;Llb}ie+8xo#f4Al_DQZTffI=u0p#qvt}{ArTcUz$5Q}V4_Y$f) z5scE7M&nTno?4ooat^wQuW1Bd1W9inpC=ZKZq*RFJUF;)pI|}kXqWwE9Cc~+LcH{n zSTk|`*LxZ4jDjk`%K+JUs*@0vNa4|~wQ4Ki_$T2`Xxf3!zU7NdScbwI5*GbQ={9Vo zlZPh5?)!>g5-oPUrHIyceB_&OAMIjbs;Tfrm+eEWFQ*ysw7z)6||-YgJUcmpsOB*4&J%l{eWQP2Mu zm*MqlLKhdu-AzFlr|hXn>jgr&xxWZq|7d zy%vZOiJnV(9&#CV?pM|NLDfzn>uHUFwae{L$EziCvkhBtptMXsy$o+uf@vwMX@j%^!_dKEc<9_l~jNDPQ~gIBW_$=G9_zhoCC7{FWXl= znAhPt9wY`HBXANDChcXrRh4AAEG}_<@F#p+2TkRopr{X~)S)5GN}mCxvSqTA0F7X_ z@}**zcjFV@#5+*0L;K#K@7jd!a|{sq;o*$MQHk=3)-kZ4l9PwZOT7vm7bPgkHaO&> zL3g!UZ1BGzk8EKDG>A0>1a!a-q%y4)pu!_5v{NsO^1$nxynaMMjX1t z+Y{nQJ}K6)gQ@U~_VQ{RfsHT-_xYyc754+g^w|4#QDE+jd{OMmf@79V7+r}?;j!Xt z$pAEm`E=jc&-?5+j=-GZy>*6mGUg#mjd|OaE)^Y_0%)>>vY{aoc%TY6c5*@$E*!`K zA%odWq-$&NsB2Lt(Bifs+Q>E6eq}jwS;lih@(uB>DaqzLXA;w^hWWRhsdu&{EA->V z!W)zYfPCJsjb$7V5yqc`i&tcrY{iQ$@DTI9k~%IG{{R_w0(zmYKxZu$U@Ek+6k%O2 z1>T%p0L^QDwqTCdS#+P_$ty67@by$67DU=Z6z=`Q8=n;wpgq@&?m(o08VaA93UD=# ze*GW$7wQuK%q563RzyhEWDenWWv!}ns$4NHXFlk=(Dd}l?4z)(itgU3P^YI|$ru3uND)_6Q&ys+Li7&C>gv&tf)Jc-fn-~nA zofn>{j@KsHRpl{ELX)o4N%sDQxB=l$`-CBSH-N#t2Ml^u;l=d+-Hxohrb5{lRK-B4 z?{5>Z{*kqR%f#M4l~jS;@(-S;j*;J~`7Iil`JCdOFh2wU)<%YL-{#MavA;X6!G_U} z+x!WGmd4tQUbGDQe$sq{MSKNEZB<2B_G_EDtra;hdq+1MUb5#O^PiNpBNh6)t;d?9 zz9&x@nOoT7zCsKBCRxcB#o!OGrzXnqBpfqiVhR|QF4ip@*|+7Ho9>yCop%G{MQIOo0F4@)MIMqv8SNw`>ebE3t0v|m z%os-+P|zeV1udU<*9WQ7tcR})c%bh-ciFJ(gnXA)kvpQ$Dlh`gMRJNc2}J#Zz==zg zyiO3sz;#uV*i4E9VW*h|mR%TY7*Rck@WofzEF%{HYEZ4K+o2a+?uOGkD#66xmRwF- zL2&&*_#}v{UN6Jp!^eM38q&uSzkM1rO}Zk@`>H)WN_#MLO^f5s+$zVdBQ8bK(CG@k zE$X&svB3aU%znWo`*`bp{yfkO7i4XySQ|sCW~Rp26Ye)+!sf$fsd7gJ$R-d!>M8)T z326ASx{S3=o0Ma(<(erJb3cQPe3(FHjzOUC1Ypo&jcW2`Cr6opB`&$@Y@=Dkc#t}n zbkr0cPB4gtcRTIqd&*Dp69BsZ*h2U2v4svOtKVA$z#2~#Z0!x5EFO*_*}IRoafuoA z01BYlzW9DU-4l_SPHTXsgYB=96=8rJg|=Cal4^wkEFzK7-N_%)6aI*{0$@cZL4EFw zYiA~^l;q%(ZpcbZ?Q}x!hGf-xOR~hCFbYx8VvTsk+5LyN+@2=K{f3E7il%W)p;U%2( zePPG8K(sxV&g?96kn^R^lcQGBtGpKzmoD31E(r7#p=*3M{la7YMNLzx9Cvz$;l|x_ zfA%O<S+*9Nla~!gtPFBz_>2u}#UVD)DEK+bf+6LMm zTlWJLb>)3`*=x|o)PjD81%bWuG z_%V}GMMTPY)4QtQg*Vs%9)vESM=`rM>g=>ojOXz#xhM|^`YjcKWYG?g+&hOT`q>Vv z+Hw@>?Du=71ot;T*$GwX6UU||Z>4FmxWEF9WI?9=PX1Ima_dm<0J|Cnsu6NL`sEaT zs+G_O2$#^Jtv7(=dQBY|n){JAk_7x8gr=6S(U$Ke90E@$`OU91QQ9u~Xel2~d|2T?4Auf{4bJ_&cox|_84V^jQ3kU8mJ z&1f&f2M*BFgxq%^k8r^cZzyc5LjppFSk=GFqW=*e^+(tIf8n=we&@IT)@EgnK;m?& zG*9T)%mlCx+)H5~Re2M?Z&=H0YDt#Mt*92Ed_o{&M8aU<7>>GT!{>A%7-nsqRn35I zl)mbFX2ip^tn!saG%5$g#m{StZ#p4c+qIC;<4Ewd1K@Z)xSbR4It6xRm3j~YCH*ls zi+g2yj2wJj#~NVz$;Dpe2mAc}fb%;GfaW8>0a2nT=M=p#KVNQemhePM)Gsc%Z{l9( zv)LKEtur2mLEGCL{tW6FVAAD5PUpl_9ZnsqI0Z~F+czV1Xv0inuoHmN3-oL!^CRZf z1q&bfMOnsEph3LdCcS{ld0m%sfHNu&%;=bSW=Q^8Q~T4GjZZ-c@7$K8g8^K2;V*U z%qN%l04B>0xEYm4H)D>TJP16`(dj@k@mu2wPA7;4FDJJM!>eEdq@*=BQKz^&TNy27 zH`W#0DN0n1$9u7>rL@Oa`gs~d`zEIAr0Yby0!QLi2QOj$f}MRj4;I9@lBT*V`=GN? zhE?;;Yt?lAfG~SwkgqHg&+u{b;!i4%e;?j~x3S5rs`Csh$nuBpdab2Pmw!QVOivHS zL`AAwJi&=pc+H#zWXnZ1(V-w9(+TKq=K;uC2skm3Nq1I0_i7}^AFoXTs3ssx`s>l< z%%dFO9Avno2%hrwaJvj*&ll1$9Wx3DPZH|!5{FynE@6~CS(vRm+#y8FEvbyF#CsSI ztkDoMw;>T@I_U%5uCU{)_GDTN2?Hi3_6)x5tB4H!5pPIePKLwG<|*y9In`u*Msiv* zE>XhePeqq|rNi`~H=Z=q<#2f5)(F)QHRl^O5s?Z(aXq4ZG1?ayS7BqyAdcR zHN$i&5s2t`J^tgDJ_=KXGenje55kj=X~tx1xX#8pa@pYZl2y@8+ zCx4vH^b;+-0{XUY3Mb$Lw~9Y1yn_o^=eJKb-zpq;^>+}&XOGAc2R2KqO9YW>_3{Gk z3H+Wq^OiF>mU6*)Aq}XQL2xHni^5>R3~&?Ri?RqR-g2*`5q@iT4p8RU(9cZ}8}LDS zcZ^*Fc%Hw^BZesitTPMs33E*TtGS0Hysz+2s2)~%bZuU>(#3v-?Y&jc&2YPlk=qul zkVnd;MStV5p?7S@#v-M!x^;X}(=pZ@w}9m^Q~~>{q6rE2HG4(@scFvZ%1RxYSJ0KR zhg&ifafE46j=pdra3H5oKCd(TIRJd~pPDROLi>*mF!QC|BbY~hB3HaS&qj8pW-8|K zR1_5H5!sriF?nIF@uEsDbLvG7xmtKf=b^D-UncVDNx0YEWTJFMiY$Slh{Q+5bY*^K zs9MqC{XtRg_fGR6E9uYc&oUL5XmJkJjNjzjP8Ve5V~;CNaw6_uTM6|-YE^cJ1(=!> z=~-xVgE`^Y8vP7VaS(A0GsB>-cO{Bd%k_B$IIY)7m!7az%~w>{z~x#>sJ+Je(;EFt6A< zgdnp%(*fO0JI6LSp%!z=2tAH#hUX+ZBW%s)Enk%L$Wu4Y#LmDqa1UNxB=?jmThig= zgRc~|-d(zLxqE)wXkA=9liuaO6cbQ^@O&<^jnNtAisFT7!xHepAWM1PCWsf8ARN@%|I$L&ciH z9em!SX8oq2*-7w)yqBM_;4R>VzM8?Emv~Kp_GsC)rv8ABqX-+1t?@HCjpX;JDdgn8 zxGXyh%@^1qd-~xtOYf=VTZ}h?GUwQi9H468X*Mhst^*oB!-ekz*$#O(YiQ9-=;`sX zJyIW*$FkqtpaQ(XX*{1xkJ?d+09I(0bvoIM0Yw;3iX`$n8OJSHleRrf;vXO)H61zW zBOA^;_ba@OX2p43zzjyYd4>~A2T?@vYZPq6#rhCrYG^64@dv8){F8* z=npN8Sb8ikj_L!}BbxPG*HgC|aV28#iHtSTr1A@EJ)B%dN#m@>3JcxCo1+`%+o+=v zwp&1ks2Kgo;br#d>?O$qU*xMxQ+lj6!dHx?l=;upw#~O`QJMt1V z#Ah$I@N^EdWud6>Azn$#d&rnL#CoR7i=K+u=B$^VUHr0}CdB44R(!LHi%sj}k)ndy z{&nbd!?<;6sbPKG5Ju)40np0Ho=Ti;YMympkl@f0px4GcL)Yu8PVsqYZ6lys$d zMno8Po`%%9p5s2{#R9eJG7A;zXHT~zW2A?;8m#*#&dCcdig0SVE|oa!o)M-vvNyOG z?g65W=S1ngif{xa`MY0m-gTf`;7+@`N=~_#xQOAn#`TG1q5BKzLcE*t+{To-4qQWQ zS~QX2&@#4^o{-W*A_D^N}FOB-luD*EysxB-ok3|Y|1J@&ewrA~QsW5XEJ5qv$(=aH{rXdqx9cZ`g1 znya?yy+2UJ+4uL^Axp!qRuqWBqKTlli7xcjyv_(f8ht2#89`ypZ-)0cu8e4wxIUQJ&#oj4m(4%mx5nVVxU zQ>rth=;>3~zShX587cu1+FzMpd6a?Gt`RN?Cyec--2kahe@8(@1b=xx`TfI_#@2_2 zYM_R7?qg#?a{lL1`_v*9#IX6a<7>S*5JSR z4mY)2nGXpmbp-lcU1=J#r=bByLvjkn!4y`otUOwT@XD0*0ld`dYmEM(4%6Dc{q{lh;v+)^mw#+E3-(LgNjju~~d+Ol*@m5`CjFXJ) zO~veuy>AijWkh$P-#BdqAeCw|wX9Wj_BKTaVyhwMYH8pHh;=`r&;Fc95!TbK(tI`M z;OR&VE8=EBJv~WcJ&vl?Mmho!^GlCu6iL`%3awU9xO7#yM+A6lN)NtQYY!TuU5uw8*d^ zeeiMXH~JPfx5F~$hLsqPoUmwx3dad=fJ3sf-oZ|C>kLE(VjdNZT1f#qYN{($kPcpf z$|2C&^W6<8*4c(k4hjPg@;X6g2klby(1c<1Pa%4T-*ow+hX=3mifz8{>mLCV7k+sR zBmfr4?KUcSSe-K7hBB;wlbkZ_k{Vji^pMu4-A@Y1y)8I{&0ehA{b29#+r+DMGsTta6&-^=DHTz+YjDl;J9`TSNu(> znZ95dm>>k6ZiS91>kqb^ORYqX0u0lk(7_PK!lv(IqNTQIpp@745H*u6L$ZP>@l9j= zeFb|96BXsWFI^M3?LI{@6`$a%O(qg2`J}n~go5$hf^KD)N-h#7x?JIHQj2`P`nRR-(f8_c z6ATs#cpBj0QeadOE>`2QvSaJmZ%Jaw%(uLCQh~ebtq6lf6YaB_Q`LI5@v@4;;J;$tC)XdSUMc z=XmITs|c;xFwrC2TvJ8L4h?2_Nf*Q_Kft3(w@nU9|VaajSgb;VuhZR_ZaiS7MKg4 zqE8F&{}MAf%{jKw>uR!Phr0?ef=k7Z9>x!a(JUCzP48ZoFkGIBm^7)Yy>);_XA&ir zRE_%P%LP;&wEu&eDFllk?JoxBzs5TG9sS{-sJZ=5egD6vga#7*0a8G`Pfidf+I`|n zB1{SaE(7o*5n>7KL7#8VSsn{M%dOxRlH)Y9r8<(UqhHn-|1E3O_te_LCEX8qfQ1@? zlb3LO^V2Vp0m?B;5&J-l?+pYI=RjddcN(~!`?u>yf#s>6md8f_f3iIG)24%*W(KKX ze%TiAZ+kEG_x9{@@lP8x0w?z$H*_lMcN;o3=ujKih;y<2n@q82&#QbWZGnC}Ojp zjm%%{$R8NypDiz7n13-8zZqtL?f)0A0dlI=;QYO%{+)UI-_`%!tDing|NGhaIi~qH z?gsnso%{Q44`Ewj@B>h?+kq5D_UY*@1=6rLdzM9|{NHeCT}v#k&`tZ}+nJ;cmmh!C2q=@jF`sizlq?q%5SsH>3gr%#!9-PR0(*l2-ao#?OrnZHBOac~I<{q{z;RBOe4n|CZ|&3E)$(kMJYk1f&sxqU$)#Rcl~4pNL@MA?aD zW-b)joZIrbw6wI@3lSdgV1p4DkI&hsGE!d-?Y^wITOmo~8;|#A)`%2-%+|7pgZc2p zc}Vd>v(BsiWUZW>pDo%Hvt%F!UP)1lZ1af{=l6D(<5l zl~!Haw_PljM%v@bKeDdfi}?1(P;auYj%FecjfyNsBFRNr=qa%K#d^D5?bS9!ytmwE znwhud?n+APHrbapm18`eeHBo$H?oSCvP(oTWMKC6tNeB$`+ylEm`8{W5CvfOT49bi zG|2mdon!rV=YWk9x3zIHwsCSK{be_mnN{8GjF}bnO^unAjU8>B9Sn^ffvXf9YzEo|aW|m|leLN{;At7c> z1p^CX!^c%~Yg1sI?bp|V6-9jq;J-o2`O7=xjg8Fp#cbVlSb!fnc{xdWH~_VEp+6ry z7x40bdho2Q-0VM{d`n`#@;V<{(3SfW#&-X3n=ciH81SmBD!le6RlSlkvd2W-CU2j0 z&PTls!Q`*Z5t*cY5?nI1oZ($lGL(Uyil-+mmU*o;Bn1l{^bX{VHoq{8` zM0`9nb~G47oUHyapljr`OVQnM$K8;o`I+_-T0HmjVZzVHu$J!c)Ry!FZOgwA=5Hda zx0ooiy;b3^qm*S-B!6+W*xvwgzsF68bh%Nnv;-LL` zb;o5k)U(UY=A$ByxjqtoD}{WhQYH6`gV!Va<#XX(h_#z578jlzT%oPg&ZG?AN;}Wj zG~O~`@YY{Li{^;Fa9sO{(V5YJdwP8vvXtD*K{yt!6eh_+jR0M^al#yr8`O|_lPap2 z*Kzb;Z%{baq(&{B6bnqa_X3~tVkImlc%~12^&~Qp*evZH-Y;_G^q;ecWY3hM+Q?tw zF(nAd4}O}(A?Hw5yhwZY`i2*sbKc_Jb60dvga+m;3#a_CJc)1I0%xz=uHIIy_VUJs z%xS-SQAK(XXc6!tM~yw9LMV!%it$V*Fioi8$mhTDUBh0 z1Out5%rTP(?Qf;g-?xwB+H|X%r%rZF}q7B_4D$YD>GtdZ9uP4$V-t+451M2O{H;HtMtB9vV-I z?~-hyCb@+sdiBkzuN=K)sO!SKyrFC)G>(}faa(=%OhF-7cFsygv#`Z?^4vq1QCGd^ z3OG8rH{VrSXl{f(M|q>3{~+=%f$~D5^1I`it@s|+V*06?HV~BXG!xh9Q{ArAMhlfa z)^@@5Qs={p;BlbW(W&A2=SVF5{jkM+PxJ+e5?ZcsaOt@X6#Spe>aLWJWynlMupi3$pC@t|v5f;WhULum26jy%IzKw$hhUfgw3dI-{ zv95OJ*20ne$Mm6qL>SCnq-fvfg&(8M|RkJ zsmgmLHAFf5)VLavGWFGGSyZ?Nmi4@q09^&Lkh#BwuZjvsJ#cmD>J{>i$gW6szL?SF7+#b==$m17TYk&kU~LNOd-^P)c6oa$nEm7;a3W-QS#eR;qRUykLKurFSkpeJIrp`>fP25{e`_kg;~I<079`#t##*7?srP}v$JBrY{c z$%yTrv$cye z7{4yJ8w@rRY&U5MIMhX8AAN|&GI!~ryi#_gX#mF4poy=qG*AV-r(tq{P-H3eOno`Z z!(xbm$tt(TE3*2&v3nOQLR@cPEy#A%tJ-aFG{E+=n|&bHTP^qx&6yevYQe+Hp$uh;$#rh>(d)uHDo z=(VM#^BtB#GpCyVaD;a?gh0FjRtU}*GeewFT&UQ6wg0ZT*(;@GvPSX)0je^_b{Qyq z+f~3rAG~V+tPDRo*ZDMjH$MOZkHnS1Lthsy>*6@#(_35t7#7G@L;Kr`r8D?sg706Z z6)&<4c_SAsbipLCQ}D+7cB{y{Xp?vc({V>}56l-@JvIp~^60~X&8oSy83-JGwI|;> z<=3)%Mm8QkD%@3j5DJ~W$P8%?Gg*5gUpvc@{2=hsZir9NEbYfj$#q&G;{w!PU5vxB z3R}Npf9&w0byX+@fld0DFf94!>HUNpO>B)R^O2V666_OhrX>3UrS7a!hR0a`UfrYY zJ03F-3L=K$!6&6J#&{cXPaqpV(TscD&S!#NNx27k>pnlR(i)iDmy^WVoF~ax@!kn| zoy~TuNAK|6*h7{(mU`bIiR8P~*E`G|smLI~WLq}@%rkHy(tZj{wL7Do6J}0j%ljs1 z-2K-NousyvJUSA*9^r{PZg<8HT*Usi-#i!c*#|ZDbBgJGBYB9+z}H%vHOq^Kel;f0 zg!E#k44p$LdpymN8a{Wp#`o?B>bvQf7YF<6>c`E}FmFv`=3?A)og+g9MECY&qs~!9 zyZ664*S_>K{G1GqO8<-(VKizJ(A>>s5CV=gE-|u0f1kbX#bvyYMNmbUAsLdEx$ebe zydUt&FkusU%W!+X~SxbISS$UWxk;ywaoL|DWoW*dFtS|2#q9VB`MDE4BQ^ zD_yaANl%^nY%}`me}oWYHR9(_1D=Zs#+eB&`KAnSN+cH}M5n}oL!(%K=eOtMF-|#P zGxQbV-CSeym5<-6wjnD>b4r}$-pR{(makl7Cts!%`WD>AhuJhr`5p33TP0T}qaI1s zv2ys!O14Ae5r|G@SLhOpk{42N==x@&8)Fd6w~fHl;Ui<}nL#H7bcq=o7F1T)&1!~P zA*pf&(Gfx=Mttg#lrqjLsvNbS-3hhgP~}RdBScP&a1kUNZ#VksPH=G%`LUxs`Bu+? z8%Y`)7FAZ*&&~{5CAZ)g&z>`omZr{*%#@i|U6ra#J9AREugmK`e{t2Aq&r73{t8h- zeOjis9$rR0QMQLj*Tgw3bwJeg@dpMY6C5gb#Ehhzfq~~HCI)QmCrL?t15QRJd{pej z8A+uB;iT;39|z!t*va~fXPNaUZ?vtS6~8vP-shtg#(j3PuZ)0SltxpT{PJZNB42DV z72~~7tvAam{n3bv{&eMwFrS&qt#QM=w}+_&*Zc>wyYaJyIs1q2cH0Dbz3;NR8z=Q^ zZ5HLfAqS#X*_QCX|Is3hz{%8PT6Xs4GRE~=Zk*Rx<}r)aU0W4pU1ztOCKiO?zK8ZsrlPIe*j!0>I@ z>*HGa?*lx}msBZ65+tAGd?e)>-6HE+nOhj{O5+8dQ_vAm=@T59y;OlWOP4yK@>Ff4 z*U%`>bGj(yoaDEvv#ZuO51&&4OI;4ZY;_lTVRZ7|@jdZrqtNxv<24#xK2M_`;`;Q! zpQrp~F1Bf?dzz6&EV*kH2NqK=rMlOI;4`HOcd?OGPE5go&Bx|%Lhd=SeEJQa`v-Y) zVoJgbiMJTCm&@-7atUjVQdA?KB`>~EBjDYO{(Q~p$Ym!Tv!nridHbn40Y$_iM|+vX#Dj_)edCIY+Z?$0>0s0Nlpd`_Lk~( zDr)MDjh`h5ztC0*yl|ABD&JDWG@=~JPg)w%(88bkVW-ENh*DhogKg*f$JW<9t9FKW zuVclS^#Z@6^Yz-e2H)JSPk&sacqevob4V$B28HPQ?T}0N=BAx-JLQZd)z*bqq~x_< zr5Qqw>*kFK<&6K$tKzA`qtQmwPkvi3!mS9$V>{M|@7+ zhbIafP#*Q`Ly6zU*%((puL@*Rt)C+g$K*0yaFVJDU*y`@iDwT5F&XY-&p@{y=HzG`VJ)oH#WR6p%a?NlwWSs(BfVDl=UT#qYUMqblMp1W_N6aabNX; z=*qMts>BCWu^+PZ2absMKRTjcZ2kXONAw%e_V*!5ZXULu{7`)SE62|)SV2cO*bUYE zS^uZGFAs-*tVi>)SuW={fiEIdt9T$F{&g*xtML9-_UKfvv zc<8l%m#Y)pq}=*;(YI^E#r=s0_q_B**^k3Zx@k{kwL~mqvo%FO4qNJ`9TWwAGbpq+ z$gno3wl;W$=_W(x*uBM!t!k8iEV6+}OUicWJOGHnG>i`>j2vM~iP?V4Zwz zK?U2l$E>HTmTwdmabEh~a3+a|zBJVA%K1j6;H&M!1p-VX{^L<%U!?sA7kW0~+M3*j z!|*YD+OSiD`MabaC2-0LOUu5|YpQ4U^sp>G5TG47S*WUh4ZhEbHL~jh8dltP&j{l* z)ARkQQj>!`ihX1Iuz^qgun@Oyvv=%HsK`jPRW3mp_?u%sf~s?$3^gBo?ql)g{4_gp z^MZs2pF*UMi2Ks$D6vt ztTJ35;ms@@$sT#-K_N+}w{nb1De)A}yd8Orex_5fDG@HwJRj=FQjKbS^7($lfScmY zx?USjSM_^Q6+L3au#7|_Q~2Q+QD#l*C~lxh`J|L+wcmZuZI-J z-UU<$NADlY+QigTnyk640##k}#3NDF9C1G6qUJ>Kzg|xX=8**t-7z-WY+e?Bx9C$cH1K zD5}t}yl(54Zt-JUvpr^NHn2!4roVO3W%+ z>>AH1Rci_V7(Z$i;nY@iJoDmAVf(#z1KXp|C-OB_+;-?VfHB}Mz5X~>&^=GNn$P~@ zT^&Jn2kkSe27AJ8W+m=?=o-+-(z!M4PFcJ_V0ucj#(|Jg8-D?TQ>F(Wopbdi=(`5d zoAw`IGBLT7_i9JlIoEXhll=z0My7SFH7{E=V#2&|(m{<-z2K0$A2l^a~Qjty&R+Bg*kpMIbHFI2$Cmyvd+oBH3 zJGNElTyFi@@`XY=#!Vs>T~UIyhpWxPIs0t2BOi;J)9XC0jNQqtv9QCtXzDZ*A~28r zjji@!-U(UZz-(IvuKV|M$20GTNE+Z#FUSlH$H7D%CDX{v^mm0G}Ke)1fbcc3r?ux7H{;)(`+7 zEw);j0)S@_2*BWEN{Yqk4UNFi<&;}qMz^Rj?|2$vJ=Au{q~AkS==iiR(h6UyoWt2UXTe|v?PGu~}S8rzMqkDQ=J!g?lRhZMw zr!3)v)-$f%er5^$mMz^ifl{$TI@!@(&GC1$udz(mYZuHZcwx%TP|Yl%Z#5>*&QHFk zM@Z}qJvVRS6Rmw#Qt7h&o#`{`k)2!K&3&4hdTrNevQ$(G{MGOB2~unAY0pGfLX)KO z(cW9`*Csy9c)7mrpX}<@bLvpAcNf(dgD3Sg6@EL>Co3s$oU?Gx?=Xj#Nm|y)EYXR$ znd+P0Tf6F>e#kmyG?GxH?GYb%fGA@X*D;KTFno!Mr_--TLPcGnX>kbdTtB3fGz_nB zaNpLz)=tUEV?UYIj~1sD?!}qqqQ8er9y@sJjA2Bya;tIw&oWc=lSfUEZIYrfSH9sC zc=`DCne|8gTkphB_FH9JyGK9nz=TwKN6?8A?C=lYV*!l?`SQ9}4|4 z=25>v*v%Uw>Un-RIAAGSj`^MS^x-K4ZqTSindfHpeZ{gR4}?kU(g(&p>>C~ZMEUpo zNwI9)ajW@ujtRf1PndDmrQ~JQS9VwERPL>ep;<;Rm0a=tp2Yg%6NYu@?6CJqNxWkG zImHLfl+SpyWr&3)8o7VjrBgnq?EGwac_|~adYX5H|H<9AXZn_$6@x~SZ(ILxv`VhI z?knE9G@kn|*eYgnmeH^5wCqU65XbwB5^uvNFKZyT4nBRo$3tGJ^0-0b$!vS8(+gGs z(3^(z8jmu~C4>TU%1$o%q^YTYoxe;FZ?))G@a@Btw=P#{EApUOMj3qFJbnoNc+O(A zhkoKkT;K;+h31SLulBv6+o~2@;ob2E7tdr&V(eeU1;iXtlIM^M_BlT)Hg8?HxNm;Z zYxaFpXxQ`b=cI4Sits%2XIgGeIVfSbDMaC}W1!5F6OM-m|Jh(IHgJScWu!jzG>mSr zfv%?iqRY~o&6l9fCpWNtnEQO-rLn;f7i$nlp>FaIgQx;7wg)qX<(~!z+pN00yq(nk zL5-=FYnoK|sxl=kUT5o-+Gt-G$bqkl@z`l3rlaaR2PKumI$<9^>1}6gkDRd``J|`4 zurSRz<>ocNb;`}jhvdO6AXSwP`S{NbJcW*1CQ;KVXW+bB3LUB9@v|7v@@Z|nzJFW*&Y3SMrQJnz$7Yb zvta%;MEA||?@F>VysEq%BU*K}77c>2lRu9f+b5Ae>4@XhH zFpFAmjVQA=K9;LxCeN4`m)&MaBact3ySL6FeoR?O2V-m%_W6kA&kE)TOVz*nn&&S! z-aoM?)04_z}m zT7IWn*rfG^L>2S+-1N|p#awJh#jGvnMx;p~yO+9$pYMWFmB4rjzOdgv^83SCVr;Y5 zHLZ~mtM82qDPMZICTbV!KQ=!1r@P&o$Mc73Z{>)`nre?+S^b|~@crG<1QeS3XhM2? zuXCaXd+^&?lkwEvOqlo33ryo>-e<^6i)Ny=obRKZQQE9JtU6*pedA1J2J=F9bA`VT z^;=9TQutCSZ^tuma4zz&eSyk`4Gg8PnJ^?&WCAT z(v8L^SH|w})l|b04-r@6RpU|EB1)f^Zp`@hcM)Ons%H_wE_FOL_a3KkykPId)|EJug?ZHRm?z@u zgg&rZ?O@J{xRckAVk;jEwK?|@=+b4y+|TAr4{9l$jMx_I{F-T$Hx_m>7@F-WK6XNG zoG{BgLFq-p1y|mBoI+9p{>%Mi?=!rt?KztuWDtt^;RH|3t;YiVu;4x`=J`vwz~cd` z`_d%tIX2miux{PK+FrRqFI0@47Wb{2^THMrw*>$*W_%QLu z@|T(A9Ve1a8XZf1ioV)E+$^9Ul014Qi$jjfxxQQG<)he)5$06JjT-MS zIRLzuwx>o&ZaUfToYoDpC#w_ItQT&IiSZ$kKMHe9eqIWB9_F$;PV9i1>HP& z)gy+lUbJhv|9eELu-=eq^lb|^4r}?i(ySv*W$9Mf&3Bub>8x+pUflUa=zPF{z^NY! zoL~5Ohn6%8!k)|N7=0DG+&-PV=$x%5U7!6-&Ed5Kx>3+luajPR*ZvZ&EAPKdoeE}l zeADnOgSUsjAPqab!zd@~dZ6p|!a(KME*23;ET`|I!S^T0o-kvh+c zHiZZShew=zJRwlWt+{6ut1G?cmgwSG(tK{c-()Mz*E^%3o#l|i<0# zSm4Z1d9}%RaSrR*RGX2I>3x!X%lq~eaf;k}$UR*q9rs{PhR>yDW0nGGQHHHP*1Oy(~O6ppKC^Ddj>CUoHA)M2*+SP9GaiM9KxC#db67tD)dB> zw`8HH!tYchUC!52`)W-WTC7g;T-zYpvK`f{JFXP}Gpyg=btsq1b<1bheJysS^^UXJ z9s9a`CUfH^4@cX#4>gwG94fJP^2^lp>63;Rj&P1-cXK>rp7mLrLPE=(9IrB0$aq<0 zNXyWV#>p;KqnczkW)~I?VWVz%w>^A_n+_CL6uQv+%quLa&LX}Z z_U#&LBV8=Exw!iTtB?Z=#t zlvHsw23{p;zM(_x~S}uN8reli+C+LcKT^A#_oM=-$EAfew z4jK+0H>_M(GM%Nv_6u0YOyGV*D+&g`_|{k)la}MmQN5hi*eP=Uo3?2&=a<@cqa64Xx)eYc$58iRGd9MheN<0*b6wQuH5%UOX}b+Y$&zpxFDE8g?$ zeVtk|cKR;NIaXapT_)>9NWqaqdrxQ8?&DAGG5Of(R&&~0x%m|mbBc2*O*3VmRQ=22 zlAFI^F{TT7^evU63HwU2qpf;%H!1-|OW@*a=iqQ;7W{sviJ zz6E#5l%E%WcHL_`Nnu+$KI0D^Pw6noy{mk8JAb(Po!xSIDJKbV z`Kblf!Px2A$ZUVSP_T)=$%lU`F%H!adcWVvIs0VVs@-A7{K>4-i9hL-wc=0wAq4*L zZ8U{t|I?a~`eYQG{56E3?0-3>iukL&e;5=)z4`y@sA+gAn%#HAr0+qiVx7fy(e?+Q zTiR^WyWQm4GbII#bq9s*7_1mR*?jBjGE=+kxY76CZTg!1-{!aV5}7r zJ=YY@n-&Mne0_C^%arbO*KFp&I9?^~Ns|cH%9@D5of;0ZVNDk<_@c^uyiDVGt94#y zPkkyi+-or(q`6cu#9TeKx!SHJ-mE|<_tT!bjJfnEjc8`*r!-Oy|q zj=^Tn$)fL?xzx$ZD>lo@J(dNuifE)yjs*cWy3dIS+zHsm9tW*`?8ZDndgHz&IvBrQ zK0IW1L}{jOl}80u(JcO-mig%G(RT0IR3cw5^qEvUd=B#3*xi%3pJVS<{zB557O`nK zMoY@kIa0QI@aX+0R?lGNYnu-T)}^sX_~WGZHH?H0JbON~NuhXY?@70i-Zb$V2s4}Z z!q;x;+^+W@+Br>|Z9S}Zko3YD@Rdd9hlWT4X(y7zjcqv&2VJk%nm8CUFb91<_BqF< zJM$i&qt2zAE&3(9h0GAowr@+jH}=GrL*aSV~|N1Haesy>4;qwjLVGxBOdiqXOp;nvZ{dAi& zy*B)o)}LEnV9MO zc!Wj2ZjY!pca|>`o9T9wW^8V3@9ld7TdVqfJI`{wY*!oL);k~=$os>3;(U7dq`R3P zs!Afhl`WGubed6Y8~b-cdB=WJsh_b!Qnn20l^1q*ey+z7tzzsh?QZ6VX`5%n5Wk@y z4}wj$e)nIR<*EtAR`>)K6XhC3uPh&Q-gN&9HgTW%htb$vE`_{=>mBd>VP@yU1vQgz z9D5!2Dc{FF^joED+?}J{pEHG2T;9c(oqSWVDHo{mOSYdav0SVi&e{I6j9o9+Hl4e# zLo3qb)ApvT%iH&K#wpQoodS@ln-SKBK zY>OJAA){Iq797{y!fft&y5GK*g^I>u$edbQ}P`~(a(HF$+z1Dj9d1y8*dql zWq3@eG)cc78bX33yYhH+#FS5OGrHO}g>gP%D`ywx(VaiaQft>dwv6v;y3?%mZDb*z z*Ow>h@&ZePSml@LpDzL}Mw~@|a4j==T)2O1eR4#soP42PFjErI|Fz`!cXu~nNUCo~ z>Txj*s0y_>Om@b@pLx0Rg^fN5$3XP1+ds~o^R92YGJ1`0Qo zJw(1Ef*{Y;0QHD2b_8*l3`_cJ4a7U)?FqnTA_#Ed z#f9i#?JW0O3v%VY$}eM)G#F4zhC?x{k`ez^G7SvK)sqgO%^;8zn-MtNs${a&|Ji2B zLA_NpP%CB0uW^Hc#SDlB0`$hii%)$e;c zk+R_t_oEjrb3Wf1snk+oi$;D0!JG33r$Hw zfE&LYqiCW671Xto9Z(?c!K4HR6bLG%oyupj3TlJEoIn8;L#FsI7Jbz82YfXkI*?pl0GGkQUK?pEsww?1KOPbMi)&$QN&PT3i~x@li5KID2i)HuoVOon3GiPNEWt` zBTfXu->9V6zX~Qr7`4h@qwq`RN>V|r6i(F41ZF9117`@{!4jfJw6wG%xC8g6|FaD% zvlmDfaP|VB0}~9TebqQhR-!VFI^$9B0F6U}wt?~dJLy1-Je^$#_J3m!3ZxKd4~Q;k z4-Hrp4b=8fWe6&JR!9$q=88SQY-T`m2l5cWKxbF`bL30}QN`O?xB_nrAUQ#t2CT*hz`mQ&ct88QwjeK!QadN3$d#!oWB=KFsobP!5NK)}od0oR%k7$puM;3^10IUQ>V0fQ9+rw{|E1%AEL;n(=U zpud*iXiE20+$d{*YW1Lakj@YUg-L%9i1;^o6!}#0C>BA$9fm*1fdR)Nek~`_t8)#- z0ad&U-i~A~`-^LkUsDJ077Awwts`hMSfFA(lBF8(S`cwHIXD!Cg(6@$7z~C+;iRD$ zF(_0_LRJ-cs|YzM{O6~D*tB%DAUKH=DX+hP%Rpt&kW=F3o)9~dJKmZ|kg*`ypOTP} z1*k#Z;t*dm;jLsDh&4Fp1Jy0i(ddXC0x+f1Yr~?~V*t>P)@CFIyIvj^OD;s#V1UHnuIoH`?cb+=N-@ z8w?-FLASH + + /* The program code and other data goes into FLASH */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >FLASH + + /* Constant data goes into FLASH */ + .rodata : + { + . = ALIGN(4); + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(4); + } >FLASH + + .integrity (NOLOAD): + { + . = ALIGN(4); + *(.integrity) /* .integrity internal integrity protection of NVFile */ + *(.integrity*) /* .integrity* internal integrity protection of NVFile */ + . = ALIGN(4); + } >INTEGRITY + + .nvfile (NOLOAD): + { + . = ALIGN(4); + *(.nvfile) /* .nvfile persisted NV storage for the TPM */ + *(.nvfile*) /* .nvfile* persisted NV storage for the TPM */ + . = ALIGN(4); + } >NVFILE + + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH + .ARM : { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } >FLASH + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH + + /* used by the startup to initialize data */ + _sidata = LOADADDR(.data); + + /* Initialized data sections goes into RAM, load LMA copy after code */ + .data : + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + } >RAM AT> FLASH + + + /* Uninitialized data section */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >RAM + + /* User_heap_stack section, used to check that there is enough RAM left */ + ._user_heap_stack : + { + . = ALIGN(4); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(4); + } >RAM + + + + /* Remove information from the standard libraries */ + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} + + diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/main.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/main.c new file mode 100644 index 0000000..980807a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/main.c @@ -0,0 +1,401 @@ + +/** + ****************************************************************************** + * @file : main.c + * @brief : Main program body + ****************************************************************************** + * This notice applies to any and all portions of this file + * that are not between comment pairs USER CODE BEGIN and + * USER CODE END. Other portions of this file, whether + * inserted by the user or by software development tools + * are owned by their respective copyright owners. + * + * Copyright (c) 2018 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. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ +/* Includes ------------------------------------------------------------------*/ +#include "main.h" +#include "stm32l4xx_hal.h" +#include "usb_device.h" + +/* USER CODE BEGIN Includes */ +#include +#include +#include +#include "TpmDevice.h" +#include "StmUtil.h" + +/* USER CODE END Includes */ + +/* Private variables ---------------------------------------------------------*/ +RNG_HandleTypeDef hrng; + +RTC_HandleTypeDef hrtc; + +UART_HandleTypeDef huart2; + +/* USER CODE BEGIN PV */ +/* Private variables ---------------------------------------------------------*/ + +/* USER CODE END PV */ + +/* Private function prototypes -----------------------------------------------*/ +void SystemClock_Config(void); +static void MX_GPIO_Init(void); +static void MX_USART2_UART_Init(void); +static void MX_RTC_Init(void); +static void MX_RNG_Init(void); + +/* USER CODE BEGIN PFP */ +/* Private function prototypes -----------------------------------------------*/ + +/* USER CODE END PFP */ + +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/** + * @brief The application entry point. + * + * @retval None + */ +int main(void) +{ + /* USER CODE BEGIN 1 */ + + /* USER CODE END 1 */ + + /* MCU Configuration----------------------------------------------------------*/ + + /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ + HAL_Init(); + + /* USER CODE BEGIN Init */ + + /* USER CODE END Init */ + + /* Configure the system clock */ + SystemClock_Config(); + + /* USER CODE BEGIN SysInit */ + + /* USER CODE END SysInit */ + + /* Initialize all configured peripherals */ + MX_GPIO_Init(); + MX_USART2_UART_Init(); + MX_RTC_Init(); + MX_USB_DEVICE_Init(); + MX_RNG_Init(); + /* USER CODE BEGIN 2 */ + InitializeITM(); + fprintf(stderr, "\r\n\r\n=========================\r\n" + "= Nucleo-L476RG TPM 2.0 =\r\n" + "=========================\r\n"); + printf("Nucleo-L476RG TPM 2.0\r\n"); + + if(!TpmInitializeDevice()) + { + _Error_Handler(__FILE__, __LINE__); + } + + /* USER CODE END 2 */ + + /* Infinite loop */ + /* USER CODE BEGIN WHILE */ + while (1) + { + + /* USER CODE END WHILE */ + + /* USER CODE BEGIN 3 */ + if(!TpmOperationsLoop()) + { + _Error_Handler(__FILE__, __LINE__); + } + + } + /* USER CODE END 3 */ + +} + +/** + * @brief System Clock Configuration + * @retval None + */ +void SystemClock_Config(void) +{ + + RCC_OscInitTypeDef RCC_OscInitStruct; + RCC_ClkInitTypeDef RCC_ClkInitStruct; + RCC_PeriphCLKInitTypeDef PeriphClkInit; + + /**Configure LSE Drive Capability + */ + HAL_PWR_EnableBkUpAccess(); + + __HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW); + + /**Initializes the CPU, AHB and APB busses clocks + */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48|RCC_OSCILLATORTYPE_HSI + |RCC_OSCILLATORTYPE_LSE; + RCC_OscInitStruct.LSEState = RCC_LSE_ON; + RCC_OscInitStruct.HSIState = RCC_HSI_ON; + RCC_OscInitStruct.HSI48State = RCC_HSI48_ON; + RCC_OscInitStruct.HSICalibrationValue = 64; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; + RCC_OscInitStruct.PLL.PLLM = 1; // <-- This one gets dropped by V1.11.0 add me manually back in when CubeMX ran + RCC_OscInitStruct.PLL.PLLN = 10; + RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; + RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2; + RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2; + if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) + { + _Error_Handler(__FILE__, __LINE__); + } + + /**Initializes the CPU, AHB and APB busses clocks + */ + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK + |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; + + if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) + { + _Error_Handler(__FILE__, __LINE__); + } + + PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC|RCC_PERIPHCLK_USART2 + |RCC_PERIPHCLK_USB|RCC_PERIPHCLK_RNG; + PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_PCLK1; + PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE; + PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_HSI48; + PeriphClkInit.RngClockSelection = RCC_RNGCLKSOURCE_HSI48; + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) + { + _Error_Handler(__FILE__, __LINE__); + } + + /**Configure the main internal regulator output voltage + */ + if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK) + { + _Error_Handler(__FILE__, __LINE__); + } + + /**Configure the Systick interrupt time + */ + HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000); + + /**Configure the Systick + */ + HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); + + /* SysTick_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0); +} + +/* RNG init function */ +static void MX_RNG_Init(void) +{ + + hrng.Instance = RNG; + if (HAL_RNG_Init(&hrng) != HAL_OK) + { + _Error_Handler(__FILE__, __LINE__); + } + +} + +/* RTC init function */ +static void MX_RTC_Init(void) +{ + + RTC_TimeTypeDef sTime; + RTC_DateTypeDef sDate; + + /**Initialize RTC Only + */ + hrtc.Instance = RTC; +if(HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR0) != 0x32F2){ + hrtc.Init.HourFormat = RTC_HOURFORMAT_24; + hrtc.Init.AsynchPrediv = 127; + hrtc.Init.SynchPrediv = 255; + hrtc.Init.OutPut = RTC_OUTPUT_DISABLE; + hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE; + hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH; + hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN; + if (HAL_RTC_Init(&hrtc) != HAL_OK) + { + _Error_Handler(__FILE__, __LINE__); + } + + /**Initialize RTC and set the Time and Date + */ + sTime.Hours = 0; + sTime.Minutes = 0; + sTime.Seconds = 0; + sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE; + sTime.StoreOperation = RTC_STOREOPERATION_RESET; + if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN) != HAL_OK) + { + _Error_Handler(__FILE__, __LINE__); + } + + sDate.WeekDay = RTC_WEEKDAY_MONDAY; + sDate.Month = RTC_MONTH_JANUARY; + sDate.Date = 1; + sDate.Year = 0; + + if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN) != HAL_OK) + { + _Error_Handler(__FILE__, __LINE__); + } + + HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR0,0x32F2); + } + +} + +/* USART2 init function */ +static void MX_USART2_UART_Init(void) +{ + + huart2.Instance = USART2; + huart2.Init.BaudRate = 115200; + huart2.Init.WordLength = UART_WORDLENGTH_8B; + huart2.Init.StopBits = UART_STOPBITS_1; + huart2.Init.Parity = UART_PARITY_NONE; + huart2.Init.Mode = UART_MODE_TX; + huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE; + huart2.Init.OverSampling = UART_OVERSAMPLING_16; + huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE; + huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT; + if (HAL_UART_Init(&huart2) != HAL_OK) + { + _Error_Handler(__FILE__, __LINE__); + } + +} + +/** Configure pins as + * Analog + * Input + * Output + * EVENT_OUT + * EXTI +*/ +static void MX_GPIO_Init(void) +{ + + GPIO_InitTypeDef GPIO_InitStruct; + + /* GPIO Ports Clock Enable */ + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + + /*Configure GPIO pin Output Level */ + HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET); + + /*Configure GPIO pin : B1_Pin */ + GPIO_InitStruct.Pin = B1_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(B1_GPIO_Port, &GPIO_InitStruct); + + /*Configure GPIO pin : LD2_Pin */ + GPIO_InitStruct.Pin = LD2_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(LD2_GPIO_Port, &GPIO_InitStruct); + +} + +/* USER CODE BEGIN 4 */ + +/* USER CODE END 4 */ + +/** + * @brief This function is executed in case of error occurrence. + * @param file: The file name as string. + * @param line: The line in file as a number. + * @retval None + */ +void _Error_Handler(char *file, int line) +{ + /* USER CODE BEGIN Error_Handler_Debug */ + dbgPrint("PANIC: EXECUTION HALTED %s@%d\r\n", file, line); + /* User can add his own implementation to report the HAL error return state */ + while(1) + { + } + /* USER CODE END Error_Handler_Debug */ +} + +#ifdef USE_FULL_ASSERT +/** + * @brief Reports the name of the source file and the source line number + * where the assert_param error has occurred. + * @param file: pointer to the source file name + * @param line: assert_param error line source number + * @retval None + */ +void assert_failed(uint8_t* file, uint32_t line) +{ + /* USER CODE BEGIN 6 */ + /* User can add his own implementation to report the file name and line number, + tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ + /* USER CODE END 6 */ +} +#endif /* USE_FULL_ASSERT */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/stm32l4xx_hal_msp.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/stm32l4xx_hal_msp.c new file mode 100644 index 0000000..5d5eb49 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/stm32l4xx_hal_msp.c @@ -0,0 +1,225 @@ +/** + ****************************************************************************** + * File Name : stm32l4xx_hal_msp.c + * Description : This file provides code for the MSP Initialization + * and de-Initialization codes. + ****************************************************************************** + * This notice applies to any and all portions of this file + * that are not between comment pairs USER CODE BEGIN and + * USER CODE END. Other portions of this file, whether + * inserted by the user or by software development tools + * are owned by their respective copyright owners. + * + * Copyright (c) 2018 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. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" + +extern void _Error_Handler(char *, int); +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ +/** + * Initializes the Global MSP. + */ +void HAL_MspInit(void) +{ + /* USER CODE BEGIN MspInit 0 */ + + /* USER CODE END MspInit 0 */ + + __HAL_RCC_SYSCFG_CLK_ENABLE(); + __HAL_RCC_PWR_CLK_ENABLE(); + + HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4); + + /* System interrupt init*/ + /* MemoryManagement_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(MemoryManagement_IRQn, 0, 0); + /* BusFault_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(BusFault_IRQn, 0, 0); + /* UsageFault_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(UsageFault_IRQn, 0, 0); + /* SVCall_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(SVCall_IRQn, 0, 0); + /* DebugMonitor_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(DebugMonitor_IRQn, 0, 0); + /* PendSV_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(PendSV_IRQn, 0, 0); + /* SysTick_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0); + + /* USER CODE BEGIN MspInit 1 */ + + /* USER CODE END MspInit 1 */ +} + +void HAL_RNG_MspInit(RNG_HandleTypeDef* hrng) +{ + + if(hrng->Instance==RNG) + { + /* USER CODE BEGIN RNG_MspInit 0 */ + + /* USER CODE END RNG_MspInit 0 */ + /* Peripheral clock enable */ + __HAL_RCC_RNG_CLK_ENABLE(); + /* USER CODE BEGIN RNG_MspInit 1 */ + + /* USER CODE END RNG_MspInit 1 */ + } + +} + +void HAL_RNG_MspDeInit(RNG_HandleTypeDef* hrng) +{ + + if(hrng->Instance==RNG) + { + /* USER CODE BEGIN RNG_MspDeInit 0 */ + + /* USER CODE END RNG_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_RNG_CLK_DISABLE(); + /* USER CODE BEGIN RNG_MspDeInit 1 */ + + /* USER CODE END RNG_MspDeInit 1 */ + } + +} + +void HAL_RTC_MspInit(RTC_HandleTypeDef* hrtc) +{ + + if(hrtc->Instance==RTC) + { + /* USER CODE BEGIN RTC_MspInit 0 */ + + /* USER CODE END RTC_MspInit 0 */ + /* Peripheral clock enable */ + __HAL_RCC_RTC_ENABLE(); + /* USER CODE BEGIN RTC_MspInit 1 */ + + /* USER CODE END RTC_MspInit 1 */ + } + +} + +void HAL_RTC_MspDeInit(RTC_HandleTypeDef* hrtc) +{ + + if(hrtc->Instance==RTC) + { + /* USER CODE BEGIN RTC_MspDeInit 0 */ + + /* USER CODE END RTC_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_RTC_DISABLE(); + /* USER CODE BEGIN RTC_MspDeInit 1 */ + + /* USER CODE END RTC_MspDeInit 1 */ + } + +} + +void HAL_UART_MspInit(UART_HandleTypeDef* huart) +{ + + GPIO_InitTypeDef GPIO_InitStruct; + if(huart->Instance==USART2) + { + /* USER CODE BEGIN USART2_MspInit 0 */ + + /* USER CODE END USART2_MspInit 0 */ + /* Peripheral clock enable */ + __HAL_RCC_USART2_CLK_ENABLE(); + + /**USART2 GPIO Configuration + PA2 ------> USART2_TX + PA3 ------> USART2_RX + */ + GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF7_USART2; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* USER CODE BEGIN USART2_MspInit 1 */ + + /* USER CODE END USART2_MspInit 1 */ + } + +} + +void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) +{ + + if(huart->Instance==USART2) + { + /* USER CODE BEGIN USART2_MspDeInit 0 */ + + /* USER CODE END USART2_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_USART2_CLK_DISABLE(); + + /**USART2 GPIO Configuration + PA2 ------> USART2_TX + PA3 ------> USART2_RX + */ + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3); + + /* USER CODE BEGIN USART2_MspDeInit 1 */ + + /* USER CODE END USART2_MspDeInit 1 */ + } + +} + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/stm32l4xx_it.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/stm32l4xx_it.c new file mode 100644 index 0000000..75e12e7 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/stm32l4xx_it.c @@ -0,0 +1,212 @@ +/** + ****************************************************************************** + * @file stm32l4xx_it.c + * @brief Interrupt Service Routines. + ****************************************************************************** + * + * COPYRIGHT(c) 2018 STMicroelectronics + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx_hal.h" +#include "stm32l4xx.h" +#include "stm32l4xx_it.h" + +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/* External variables --------------------------------------------------------*/ +extern PCD_HandleTypeDef hpcd_USB_OTG_FS; + +/******************************************************************************/ +/* Cortex-M4 Processor Interruption and Exception Handlers */ +/******************************************************************************/ + +/** +* @brief This function handles Non maskable interrupt. +*/ +void NMI_Handler(void) +{ + /* USER CODE BEGIN NonMaskableInt_IRQn 0 */ + + /* USER CODE END NonMaskableInt_IRQn 0 */ + /* USER CODE BEGIN NonMaskableInt_IRQn 1 */ + + /* USER CODE END NonMaskableInt_IRQn 1 */ +} + +/** +* @brief This function handles Hard fault interrupt. +*/ +void HardFault_Handler(void) +{ + /* USER CODE BEGIN HardFault_IRQn 0 */ + + /* USER CODE END HardFault_IRQn 0 */ + while (1) + { + /* USER CODE BEGIN W1_HardFault_IRQn 0 */ + /* USER CODE END W1_HardFault_IRQn 0 */ + } + /* USER CODE BEGIN HardFault_IRQn 1 */ + + /* USER CODE END HardFault_IRQn 1 */ +} + +/** +* @brief This function handles Memory management fault. +*/ +void MemManage_Handler(void) +{ + /* USER CODE BEGIN MemoryManagement_IRQn 0 */ + + /* USER CODE END MemoryManagement_IRQn 0 */ + while (1) + { + /* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */ + /* USER CODE END W1_MemoryManagement_IRQn 0 */ + } + /* USER CODE BEGIN MemoryManagement_IRQn 1 */ + + /* USER CODE END MemoryManagement_IRQn 1 */ +} + +/** +* @brief This function handles Prefetch fault, memory access fault. +*/ +void BusFault_Handler(void) +{ + /* USER CODE BEGIN BusFault_IRQn 0 */ + + /* USER CODE END BusFault_IRQn 0 */ + while (1) + { + /* USER CODE BEGIN W1_BusFault_IRQn 0 */ + /* USER CODE END W1_BusFault_IRQn 0 */ + } + /* USER CODE BEGIN BusFault_IRQn 1 */ + + /* USER CODE END BusFault_IRQn 1 */ +} + +/** +* @brief This function handles Undefined instruction or illegal state. +*/ +void UsageFault_Handler(void) +{ + /* USER CODE BEGIN UsageFault_IRQn 0 */ + + /* USER CODE END UsageFault_IRQn 0 */ + while (1) + { + /* USER CODE BEGIN W1_UsageFault_IRQn 0 */ + /* USER CODE END W1_UsageFault_IRQn 0 */ + } + /* USER CODE BEGIN UsageFault_IRQn 1 */ + + /* USER CODE END UsageFault_IRQn 1 */ +} + +/** +* @brief This function handles System service call via SWI instruction. +*/ +void SVC_Handler(void) +{ + /* USER CODE BEGIN SVCall_IRQn 0 */ + + /* USER CODE END SVCall_IRQn 0 */ + /* USER CODE BEGIN SVCall_IRQn 1 */ + + /* USER CODE END SVCall_IRQn 1 */ +} + +/** +* @brief This function handles Debug monitor. +*/ +void DebugMon_Handler(void) +{ + /* USER CODE BEGIN DebugMonitor_IRQn 0 */ + + /* USER CODE END DebugMonitor_IRQn 0 */ + /* USER CODE BEGIN DebugMonitor_IRQn 1 */ + + /* USER CODE END DebugMonitor_IRQn 1 */ +} + +/** +* @brief This function handles Pendable request for system service. +*/ +void PendSV_Handler(void) +{ + /* USER CODE BEGIN PendSV_IRQn 0 */ + + /* USER CODE END PendSV_IRQn 0 */ + /* USER CODE BEGIN PendSV_IRQn 1 */ + + /* USER CODE END PendSV_IRQn 1 */ +} + +/** +* @brief This function handles System tick timer. +*/ +void SysTick_Handler(void) +{ + /* USER CODE BEGIN SysTick_IRQn 0 */ + + /* USER CODE END SysTick_IRQn 0 */ + HAL_IncTick(); + HAL_SYSTICK_IRQHandler(); + /* USER CODE BEGIN SysTick_IRQn 1 */ + + /* USER CODE END SysTick_IRQn 1 */ +} + +/******************************************************************************/ +/* STM32L4xx Peripheral Interrupt Handlers */ +/* Add here the Interrupt Handlers for the used peripherals. */ +/* For the available peripheral interrupt handler names, */ +/* please refer to the startup file (startup_stm32l4xx.s). */ +/******************************************************************************/ + +/** +* @brief This function handles USB OTG FS global interrupt. +*/ +void OTG_FS_IRQHandler(void) +{ + /* USER CODE BEGIN OTG_FS_IRQn 0 */ + + /* USER CODE END OTG_FS_IRQn 0 */ + HAL_PCD_IRQHandler(&hpcd_USB_OTG_FS); + /* USER CODE BEGIN OTG_FS_IRQn 1 */ + + /* USER CODE END OTG_FS_IRQn 1 */ +} + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/system_stm32l4xx.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/system_stm32l4xx.c new file mode 100644 index 0000000..c76fe45 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/system_stm32l4xx.c @@ -0,0 +1,353 @@ +/** + ****************************************************************************** + * @file system_stm32l4xx.c + * @author MCD Application Team + * @brief CMSIS Cortex-M4 Device Peripheral Access Layer System Source File + * + * This file provides two functions and one global variable to be called from + * user application: + * - SystemInit(): This function is called at startup just after reset and + * before branch to main program. This call is made inside + * the "startup_stm32l4xx.s" file. + * + * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used + * by the user application to setup the SysTick + * timer or configure other parameters. + * + * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must + * be called whenever the core clock is changed + * during program execution. + * + * After each device reset the MSI (4 MHz) is used as system clock source. + * Then SystemInit() function is called, in "startup_stm32l4xx.s" file, to + * configure the system clock before to branch to main program. + * + * This file configures the system clock as follows: + *============================================================================= + *----------------------------------------------------------------------------- + * System Clock source | MSI + *----------------------------------------------------------------------------- + * SYSCLK(Hz) | 4000000 + *----------------------------------------------------------------------------- + * HCLK(Hz) | 4000000 + *----------------------------------------------------------------------------- + * AHB Prescaler | 1 + *----------------------------------------------------------------------------- + * APB1 Prescaler | 1 + *----------------------------------------------------------------------------- + * APB2 Prescaler | 1 + *----------------------------------------------------------------------------- + * PLL_M | 1 + *----------------------------------------------------------------------------- + * PLL_N | 8 + *----------------------------------------------------------------------------- + * PLL_P | 7 + *----------------------------------------------------------------------------- + * PLL_Q | 2 + *----------------------------------------------------------------------------- + * PLL_R | 2 + *----------------------------------------------------------------------------- + * PLLSAI1_P | NA + *----------------------------------------------------------------------------- + * PLLSAI1_Q | NA + *----------------------------------------------------------------------------- + * PLLSAI1_R | NA + *----------------------------------------------------------------------------- + * PLLSAI2_P | NA + *----------------------------------------------------------------------------- + * PLLSAI2_Q | NA + *----------------------------------------------------------------------------- + * PLLSAI2_R | NA + *----------------------------------------------------------------------------- + * Require 48MHz for USB OTG FS, | Disabled + * SDIO and RNG clock | + *----------------------------------------------------------------------------- + *============================================================================= + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32l4xx_system + * @{ + */ + +/** @addtogroup STM32L4xx_System_Private_Includes + * @{ + */ + +#include "stm32l4xx.h" + +#if !defined (HSE_VALUE) + #define HSE_VALUE 8000000U /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (MSI_VALUE) + #define MSI_VALUE 4000000U /*!< Value of the Internal oscillator in Hz*/ +#endif /* MSI_VALUE */ + +#if !defined (HSI_VALUE) + #define HSI_VALUE 16000000U /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @} + */ + +/** @addtogroup STM32L4xx_System_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32L4xx_System_Private_Defines + * @{ + */ + +/************************* Miscellaneous Configuration ************************/ +/*!< Uncomment the following line if you need to relocate your vector Table in + Internal SRAM. */ +/* #define VECT_TAB_SRAM */ +#define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field. + This value must be a multiple of 0x200. */ +/******************************************************************************/ +/** + * @} + */ + +/** @addtogroup STM32L4xx_System_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32L4xx_System_Private_Variables + * @{ + */ + /* The SystemCoreClock variable is updated in three ways: + 1) by calling CMSIS function SystemCoreClockUpdate() + 2) by calling HAL API function HAL_RCC_GetHCLKFreq() + 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency + Note: If you use this function to configure the system clock; then there + is no need to call the 2 first functions listed above, since SystemCoreClock + variable is updated automatically. + */ + uint32_t SystemCoreClock = 4000000U; + + const uint8_t AHBPrescTable[16] = {0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 1U, 2U, 3U, 4U, 6U, 7U, 8U, 9U}; + const uint8_t APBPrescTable[8] = {0U, 0U, 0U, 0U, 1U, 2U, 3U, 4U}; + const uint32_t MSIRangeTable[12] = {100000U, 200000U, 400000U, 800000U, 1000000U, 2000000U, \ + 4000000U, 8000000U, 16000000U, 24000000U, 32000000U, 48000000U}; +/** + * @} + */ + +/** @addtogroup STM32L4xx_System_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32L4xx_System_Private_Functions + * @{ + */ + +/** + * @brief Setup the microcontroller system. + * @param None + * @retval None + */ + +void SystemInit(void) +{ + /* FPU settings ------------------------------------------------------------*/ + #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */ + #endif + + /* Reset the RCC clock configuration to the default reset state ------------*/ + /* Set MSION bit */ + RCC->CR |= RCC_CR_MSION; + + /* Reset CFGR register */ + RCC->CFGR = 0x00000000U; + + /* Reset HSEON, CSSON , HSION, and PLLON bits */ + RCC->CR &= 0xEAF6FFFFU; + + /* Reset PLLCFGR register */ + RCC->PLLCFGR = 0x00001000U; + + /* Reset HSEBYP bit */ + RCC->CR &= 0xFFFBFFFFU; + + /* Disable all interrupts */ + RCC->CIER = 0x00000000U; + + /* Configure the Vector Table location add offset address ------------------*/ +#ifdef VECT_TAB_SRAM + SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */ +#else + SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */ +#endif +} + +/** + * @brief Update SystemCoreClock variable according to Clock Register Values. + * The SystemCoreClock variable contains the core clock (HCLK), it can + * be used by the user application to setup the SysTick timer or configure + * other parameters. + * + * @note Each time the core clock (HCLK) changes, this function must be called + * to update SystemCoreClock variable value. Otherwise, any configuration + * based on this variable will be incorrect. + * + * @note - The system frequency computed by this function is not the real + * frequency in the chip. It is calculated based on the predefined + * constant and the selected clock source: + * + * - If SYSCLK source is MSI, SystemCoreClock will contain the MSI_VALUE(*) + * + * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(**) + * + * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(***) + * + * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(***) + * or HSI_VALUE(*) or MSI_VALUE(*) multiplied/divided by the PLL factors. + * + * (*) MSI_VALUE is a constant defined in stm32l4xx_hal.h file (default value + * 4 MHz) but the real value may vary depending on the variations + * in voltage and temperature. + * + * (**) HSI_VALUE is a constant defined in stm32l4xx_hal.h file (default value + * 16 MHz) but the real value may vary depending on the variations + * in voltage and temperature. + * + * (***) HSE_VALUE is a constant defined in stm32l4xx_hal.h file (default value + * 8 MHz), user has to ensure that HSE_VALUE is same as the real + * frequency of the crystal used. Otherwise, this function may + * have wrong result. + * + * - The result of this function could be not correct when using fractional + * value for HSE crystal. + * + * @param None + * @retval None + */ +void SystemCoreClockUpdate(void) +{ + uint32_t tmp = 0U, msirange = 0U, pllvco = 0U, pllr = 2U, pllsource = 0U, pllm = 2U; + + /* Get MSI Range frequency--------------------------------------------------*/ + if((RCC->CR & RCC_CR_MSIRGSEL) == RESET) + { /* MSISRANGE from RCC_CSR applies */ + msirange = (RCC->CSR & RCC_CSR_MSISRANGE) >> 8U; + } + else + { /* MSIRANGE from RCC_CR applies */ + msirange = (RCC->CR & RCC_CR_MSIRANGE) >> 4U; + } + /*MSI frequency range in HZ*/ + msirange = MSIRangeTable[msirange]; + + /* Get SYSCLK source -------------------------------------------------------*/ + switch (RCC->CFGR & RCC_CFGR_SWS) + { + case 0x00: /* MSI used as system clock source */ + SystemCoreClock = msirange; + break; + + case 0x04: /* HSI used as system clock source */ + SystemCoreClock = HSI_VALUE; + break; + + case 0x08: /* HSE used as system clock source */ + SystemCoreClock = HSE_VALUE; + break; + + case 0x0C: /* PLL used as system clock source */ + /* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLN + SYSCLK = PLL_VCO / PLLR + */ + pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC); + pllm = ((RCC->PLLCFGR & RCC_PLLCFGR_PLLM) >> 4U) + 1U ; + + switch (pllsource) + { + case 0x02: /* HSI used as PLL clock source */ + pllvco = (HSI_VALUE / pllm); + break; + + case 0x03: /* HSE used as PLL clock source */ + pllvco = (HSE_VALUE / pllm); + break; + + default: /* MSI used as PLL clock source */ + pllvco = (msirange / pllm); + break; + } + pllvco = pllvco * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 8U); + pllr = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> 25U) + 1U) * 2U; + SystemCoreClock = pllvco/pllr; + break; + + default: + SystemCoreClock = msirange; + break; + } + /* Compute HCLK clock frequency --------------------------------------------*/ + /* Get HCLK prescaler */ + tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4U)]; + /* HCLK clock frequency */ + SystemCoreClock >>= tmp; +} + + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/usb_device.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/usb_device.c new file mode 100644 index 0000000..75e5d8d --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/usb_device.c @@ -0,0 +1,173 @@ +/** + ****************************************************************************** + * @file : usb_device.c + * @version : v2.0_Cube + * @brief : This file implements the USB Device + ****************************************************************************** + * This notice applies to any and all portions of this file + * that are not between comment pairs USER CODE BEGIN and + * USER CODE END. Other portions of this file, whether + * inserted by the user or by software development tools + * are owned by their respective copyright owners. + * + * Copyright (c) 2018 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. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ + +#include "usb_device.h" +#include "usbd_core.h" +#include "usbd_desc.h" +#include "usbd_cdc.h" +#include "usbd_cdc_if.h" + +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* USER CODE BEGIN PV */ +/* Private variables ---------------------------------------------------------*/ + +/* USER CODE END PV */ + +/* USER CODE BEGIN PFP */ +/* Private function prototypes -----------------------------------------------*/ + +/* USER CODE END PFP */ + +/* Return USBD_OK if the Battery Charging Detection mode (BCD) is used, else USBD_FAIL. */ +extern USBD_StatusTypeDef USBD_LL_BatteryCharging(USBD_HandleTypeDef *pdev); + +/* USB Device Core handle declaration. */ +USBD_HandleTypeDef hUsbDeviceFS; + +/* + * -- Insert your variables declaration here -- + */ +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/* + * -- Insert your external function declaration here -- + */ +/* USER CODE BEGIN 1 */ +void MX_USB_DEVICE_DeInit(void) +{ + USBD_DeInit(&hUsbDeviceFS); +} + +/* USER CODE END 1 */ + +/** + * Init USB device Library, add supported class and start the library + * @retval None + */ +void MX_USB_DEVICE_Init(void) +{ + /* USER CODE BEGIN USB_DEVICE_Init_PreTreatment */ + + /* USER CODE END USB_DEVICE_Init_PreTreatment */ + + /* Init Device Library, add supported class and start the library. */ + USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS); + USBD_RegisterClass(&hUsbDeviceFS, &USBD_CDC); + USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops_FS); + /* Verify if the Battery Charging Detection mode (BCD) is used : */ + /* If yes, the USB device is started in the HAL_PCDEx_BCD_Callback */ + /* upon reception of PCD_BCD_DISCOVERY_COMPLETED message. */ + /* If no, the USB device is started now. */ + if (USBD_LL_BatteryCharging(&hUsbDeviceFS) != USBD_OK) { + USBD_Start(&hUsbDeviceFS); + } + /* USER CODE BEGIN USB_DEVICE_Init_PostTreatment */ + + /* USER CODE END USB_DEVICE_Init_PostTreatment */ +} + +/** + * @brief Send BCD message to user layer + * @param hpcd: PCD handle + * @param msg: LPM message + * @retval None + */ +void HAL_PCDEx_BCD_Callback(PCD_HandleTypeDef *hpcd, PCD_BCD_MsgTypeDef msg) +{ + USBD_HandleTypeDef usbdHandle = hUsbDeviceFS; + + /* USER CODE BEGIN 7 */ + if (hpcd->battery_charging_active == ENABLE) + { + switch(msg) + { + case PCD_BCD_CONTACT_DETECTION: + + break; + + case PCD_BCD_STD_DOWNSTREAM_PORT: + + break; + + case PCD_BCD_CHARGING_DOWNSTREAM_PORT: + + break; + + case PCD_BCD_DEDICATED_CHARGING_PORT: + + break; + + case PCD_BCD_DISCOVERY_COMPLETED: + USBD_Start(&usbdHandle); + break; + + case PCD_BCD_ERROR: + default: + break; + } + } + /* USER CODE END 7 */ +} + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/usbd_cdc_if.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/usbd_cdc_if.c new file mode 100644 index 0000000..f5490fe --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/usbd_cdc_if.c @@ -0,0 +1,392 @@ +/** + ****************************************************************************** + * @file : usbd_cdc_if.c + * @version : v2.0_Cube + * @brief : Usb device for Virtual Com Port. + ****************************************************************************** + * This notice applies to any and all portions of this file + * that are not between comment pairs USER CODE BEGIN and + * USER CODE END. Other portions of this file, whether + * inserted by the user or by software development tools + * are owned by their respective copyright owners. + * + * Copyright (c) 2018 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. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_cdc_if.h" + +/* USER CODE BEGIN INCLUDE */ +#include +#include +#include "StmUtil.h" +#include "stm32l4xx_hal.h" + +/* USER CODE END INCLUDE */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ + +/* USER CODE BEGIN PV */ +/* Private variables ---------------------------------------------------------*/ + +/* USER CODE END PV */ + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY + * @brief Usb device library. + * @{ + */ + +/** @addtogroup USBD_CDC_IF + * @{ + */ + +/** @defgroup USBD_CDC_IF_Private_TypesDefinitions USBD_CDC_IF_Private_TypesDefinitions + * @brief Private types. + * @{ + */ + +/* USER CODE BEGIN PRIVATE_TYPES */ +#define CDC_RTS_MASK 0x0002 +#define CDC_DTR_MASK 0x0001 +void TpmConnectionReset(void); +int TpmSignalEvent(uint8_t* Buf, uint32_t *Len); + +/* USER CODE END PRIVATE_TYPES */ + +/** + * @} + */ + +/** @defgroup USBD_CDC_IF_Private_Defines USBD_CDC_IF_Private_Defines + * @brief Private defines. + * @{ + */ + +/* USER CODE BEGIN PRIVATE_DEFINES */ +/* Define size for the receive and transmit buffer over CDC */ +/* It's up to user to redefine and/or remove those define */ +#define APP_RX_DATA_SIZE 2048 +#define APP_TX_DATA_SIZE 2048 +typedef struct +{ + uint8_t bReqType; + uint8_t bRequest; + uint16_t wVal; + uint16_t wIndex; + uint16_t wLength; +} USBD_SETUP_PKT, *PUSBD_SETUP_PKT; +extern RTC_HandleTypeDef hrtc; +/* USER CODE END PRIVATE_DEFINES */ + +/** + * @} + */ + +/** @defgroup USBD_CDC_IF_Private_Macros USBD_CDC_IF_Private_Macros + * @brief Private macros. + * @{ + */ + +/* USER CODE BEGIN PRIVATE_MACRO */ + +/* USER CODE END PRIVATE_MACRO */ + +/** + * @} + */ + +/** @defgroup USBD_CDC_IF_Private_Variables USBD_CDC_IF_Private_Variables + * @brief Private variables. + * @{ + */ +/* Create buffer for reception and transmission */ +/* It's up to user to redefine and/or remove those define */ +/** Received data over USB are stored in this buffer */ +uint8_t UserRxBufferFS[APP_RX_DATA_SIZE]; + +/** Data to send over USB CDC are stored in this buffer */ +uint8_t UserTxBufferFS[APP_TX_DATA_SIZE]; + +/* USER CODE BEGIN PRIVATE_VARIABLES */ + +/* USER CODE END PRIVATE_VARIABLES */ + +/** + * @} + */ + +/** @defgroup USBD_CDC_IF_Exported_Variables USBD_CDC_IF_Exported_Variables + * @brief Public variables. + * @{ + */ + +extern USBD_HandleTypeDef hUsbDeviceFS; + +/* USER CODE BEGIN EXPORTED_VARIABLES */ +USBD_CDC_LineCodingTypeDef LineCoding = +{ + 115200, /* baud rate*/ + 0x00, /* stop bits-1*/ + 0x00, /* parity - none*/ + 0x08 /* nb. of bits 8*/ +}; +volatile uint8_t CDC_RTS = 0; // RequestToSend +volatile uint8_t CDC_DTR = 0; // DataTerminalReady + +/* USER CODE END EXPORTED_VARIABLES */ + +/** + * @} + */ + +/** @defgroup USBD_CDC_IF_Private_FunctionPrototypes USBD_CDC_IF_Private_FunctionPrototypes + * @brief Private functions declaration. + * @{ + */ + +static int8_t CDC_Init_FS(void); +static int8_t CDC_DeInit_FS(void); +static int8_t CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t length); +static int8_t CDC_Receive_FS(uint8_t* pbuf, uint32_t *Len); + +/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */ + +/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */ + +/** + * @} + */ + +USBD_CDC_ItfTypeDef USBD_Interface_fops_FS = +{ + CDC_Init_FS, + CDC_DeInit_FS, + CDC_Control_FS, + CDC_Receive_FS +}; + +/* Private functions ---------------------------------------------------------*/ +/** + * @brief Initializes the CDC media low layer over the FS USB IP + * @retval USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CDC_Init_FS(void) +{ + /* USER CODE BEGIN 3 */ + /* Set Application Buffers */ + USBD_CDC_SetTxBuffer(&hUsbDeviceFS, UserTxBufferFS, 0); + USBD_CDC_SetRxBuffer(&hUsbDeviceFS, UserRxBufferFS); + return (USBD_OK); + /* USER CODE END 3 */ +} + +/** + * @brief DeInitializes the CDC media low layer + * @retval USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CDC_DeInit_FS(void) +{ + /* USER CODE BEGIN 4 */ + return (USBD_OK); + /* USER CODE END 4 */ +} + +/** + * @brief Manage the CDC class requests + * @param cmd: Command code + * @param pbuf: Buffer containing command data (request parameters) + * @param length: Number of data to be sent (in bytes) + * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t length) +{ + /* USER CODE BEGIN 5 */ + char parity[] = {'N', 'O', 'E', 'M', 'S'}; + uint8_t stop[] = {1, 15, 2}; + switch (cmd) + { + case CDC_SEND_ENCAPSULATED_COMMAND: + + break; + + case CDC_GET_ENCAPSULATED_RESPONSE: + + break; + + case CDC_SET_COMM_FEATURE: + + break; + + case CDC_GET_COMM_FEATURE: + + break; + + case CDC_CLEAR_COMM_FEATURE: + + break; + + /*******************************************************************************/ + /* Line Coding Structure */ + /*-----------------------------------------------------------------------------*/ + /* Offset | Field | Size | Value | Description */ + /* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/ + /* 4 | bCharFormat | 1 | Number | Stop bits */ + /* 0 - 1 Stop bit */ + /* 1 - 1.5 Stop bits */ + /* 2 - 2 Stop bits */ + /* 5 | bParityType | 1 | Number | Parity */ + /* 0 - None */ + /* 1 - Odd */ + /* 2 - Even */ + /* 3 - Mark */ + /* 4 - Space */ + /* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */ + /*******************************************************************************/ + case CDC_SET_LINE_CODING: + { + LineCoding.bitrate = pbuf[0] | (pbuf[1] << 8) | (pbuf[2] << 16) | (pbuf[3] << 24); + LineCoding.format = pbuf[4]; + LineCoding.paritytype = pbuf[5]; + LineCoding.datatype = pbuf[6]; + dbgPrint("CDC_SET_LINE_CODING: %lu-%d%c%d\r\n", LineCoding.bitrate, LineCoding.datatype, parity[LineCoding.paritytype], stop[LineCoding.format]); + break; + } + + case CDC_GET_LINE_CODING: + { + pbuf[0] = (uint8_t)(LineCoding.bitrate); + pbuf[1] = (uint8_t)(LineCoding.bitrate >> 8); + pbuf[2] = (uint8_t)(LineCoding.bitrate >> 16); + pbuf[3] = (uint8_t)(LineCoding.bitrate >> 24); + pbuf[4] = LineCoding.format; + pbuf[5] = LineCoding.paritytype; + pbuf[6] = LineCoding.datatype; + dbgPrint("CDC_GET_LINE_CODING: %lu-%d%c%d\r\n", LineCoding.bitrate, LineCoding.datatype, parity[LineCoding.paritytype], stop[LineCoding.format]); + break; + } + + case CDC_SET_CONTROL_LINE_STATE: + { + PUSBD_SETUP_PKT setupPkt = (PUSBD_SETUP_PKT)pbuf; + CDC_RTS = ((setupPkt->wVal & CDC_RTS_MASK) != 0); + CDC_DTR = ((setupPkt->wVal & CDC_DTR_MASK) != 0); + dbgPrint("CDC_SET_CONTROL_LINE_STATE: RTS=%d, DTR=%d\r\n", CDC_RTS, CDC_DTR); + // Reset any ongoing cmd transfers + TpmConnectionReset(); + break; + } + + case CDC_SEND_BREAK: + + break; + + default: + break; + } + + return (USBD_OK); + /* USER CODE END 5 */ +} + +/** + * @brief Data received over USB OUT endpoint are sent over CDC interface + * through this function. + * + * @note + * This function will block any OUT packet reception on USB endpoint + * untill exiting this function. If you exit this function before transfer + * is complete on CDC interface (ie. using DMA controller) it will result + * in receiving more data while previous ones are still not sent. + * + * @param Buf: Buffer of data to be received + * @param Len: Number of data received (in bytes) + * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len) +{ + /* USER CODE BEGIN 6 */ + if(!TpmSignalEvent(Buf, Len)) + { + return(USBD_FAIL); + } + + USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]); + USBD_CDC_ReceivePacket(&hUsbDeviceFS); + return (USBD_OK); + /* USER CODE END 6 */ +} + +/** + * @brief CDC_Transmit_FS + * Data to send over USB IN endpoint are sent over CDC interface + * through this function. + * @note + * + * + * @param Buf: Buffer of data to be sent + * @param Len: Number of data to be sent (in bytes) + * @retval USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY + */ +uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len) +{ + uint8_t result = USBD_OK; + /* USER CODE BEGIN 7 */ + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData; + if (hcdc->TxState != 0){ + return USBD_BUSY; + } + USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len); + result = USBD_CDC_TransmitPacket(&hUsbDeviceFS); + /* USER CODE END 7 */ + return result; +} + +/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */ + +/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/usbd_conf.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/usbd_conf.c new file mode 100644 index 0000000..1b9075f --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/usbd_conf.c @@ -0,0 +1,894 @@ +/** + ****************************************************************************** + * @file : usbd_conf.c + * @version : v2.0_Cube + * @brief : This file implements the board support package for the USB device library + ****************************************************************************** + * This notice applies to any and all portions of this file + * that are not between comment pairs USER CODE BEGIN and + * USER CODE END. Other portions of this file, whether + * inserted by the user or by software development tools + * are owned by their respective copyright owners. + * + * Copyright (c) 2018 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. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx.h" +#include "stm32l4xx_hal.h" +#include "usbd_def.h" +#include "usbd_core.h" +#include "usbd_cdc.h" + +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ + +/* USER CODE BEGIN PV */ +/* Private variables ---------------------------------------------------------*/ + +/* USER CODE END PV */ + +PCD_HandleTypeDef hpcd_USB_OTG_FS; +void _Error_Handler(char * file, int line); + +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/* Exported function prototypes ----------------------------------------------*/ +extern USBD_StatusTypeDef USBD_LL_BatteryCharging(USBD_HandleTypeDef *pdev); + +/* USER CODE BEGIN PFP */ +/* Private function prototypes -----------------------------------------------*/ + +/* USER CODE END PFP */ + +/* Private functions ---------------------------------------------------------*/ + +/* USER CODE BEGIN 1 */ +static void SystemClockConfig_Resume(void); + +/* USER CODE END 1 */ + +void HAL_PCDEx_SetConnectionState(PCD_HandleTypeDef *hpcd, uint8_t state); +extern void SystemClock_Config(void); + +/******************************************************************************* + LL Driver Callbacks (PCD -> USB Device Library) +*******************************************************************************/ +/* MSP Init */ + +void HAL_PCD_MspInit(PCD_HandleTypeDef* pcdHandle) +{ + GPIO_InitTypeDef GPIO_InitStruct; + if(pcdHandle->Instance==USB_OTG_FS) + { + /* USER CODE BEGIN USB_OTG_FS_MspInit 0 */ + + /* USER CODE END USB_OTG_FS_MspInit 0 */ + + /**USB_OTG_FS GPIO Configuration + PA11 ------> USB_OTG_FS_DM + PA12 ------> USB_OTG_FS_DP + */ + GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* Peripheral clock enable */ + __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); + + /* Enable VDDUSB */ + if(__HAL_RCC_PWR_IS_CLK_DISABLED()) + { + __HAL_RCC_PWR_CLK_ENABLE(); + HAL_PWREx_EnableVddUSB(); + __HAL_RCC_PWR_CLK_DISABLE(); + } + else + { + HAL_PWREx_EnableVddUSB(); + } + + /* Peripheral interrupt init */ + HAL_NVIC_SetPriority(OTG_FS_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(OTG_FS_IRQn); + /* USER CODE BEGIN USB_OTG_FS_MspInit 1 */ + + /* USER CODE END USB_OTG_FS_MspInit 1 */ + } +} + +void HAL_PCD_MspDeInit(PCD_HandleTypeDef* pcdHandle) +{ + if(pcdHandle->Instance==USB_OTG_FS) + { + /* USER CODE BEGIN USB_OTG_FS_MspDeInit 0 */ + + /* USER CODE END USB_OTG_FS_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_USB_OTG_FS_CLK_DISABLE(); + + /**USB_OTG_FS GPIO Configuration + PA11 ------> USB_OTG_FS_DM + PA12 ------> USB_OTG_FS_DP + */ + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11|GPIO_PIN_12); + + /* Disable VDDUSB */ + if(__HAL_RCC_PWR_IS_CLK_DISABLED()) + { + __HAL_RCC_PWR_CLK_ENABLE(); + HAL_PWREx_DisableVddUSB(); + __HAL_RCC_PWR_CLK_DISABLE(); + } + else + { + HAL_PWREx_DisableVddUSB(); + } + + /* Peripheral interrupt Deinit*/ + HAL_NVIC_DisableIRQ(OTG_FS_IRQn); + + /* USER CODE BEGIN USB_OTG_FS_MspDeInit 1 */ + + /* USER CODE END USB_OTG_FS_MspDeInit 1 */ + } +} + +/** + * @brief Setup stage callback + * @param hpcd: PCD handle + * @retval None + */ +void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd) +{ + USBD_LL_SetupStage((USBD_HandleTypeDef*)hpcd->pData, (uint8_t *)hpcd->Setup); +} + +/** + * @brief Data Out stage callback. + * @param hpcd: PCD handle + * @param epnum: Endpoint number + * @retval None + */ +void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) +{ + USBD_LL_DataOutStage((USBD_HandleTypeDef*)hpcd->pData, epnum, hpcd->OUT_ep[epnum].xfer_buff); +} + +/** + * @brief Data In stage callback. + * @param hpcd: PCD handle + * @param epnum: Endpoint number + * @retval None + */ +void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) +{ + USBD_LL_DataInStage((USBD_HandleTypeDef*)hpcd->pData, epnum, hpcd->IN_ep[epnum].xfer_buff); +} + +/** + * @brief SOF callback. + * @param hpcd: PCD handle + * @retval None + */ +void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) +{ + USBD_LL_SOF((USBD_HandleTypeDef*)hpcd->pData); +} + +/** + * @brief Reset callback. + * @param hpcd: PCD handle + * @retval None + */ +void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd) +{ + USBD_SpeedTypeDef speed = USBD_SPEED_FULL; + + /* Set USB current speed. */ + switch (hpcd->Init.speed) + { + case PCD_SPEED_FULL: + speed = USBD_SPEED_FULL; + break; + + default: + speed = USBD_SPEED_FULL; + break; + } + USBD_LL_SetSpeed((USBD_HandleTypeDef*)hpcd->pData, speed); + + /* Reset Device. */ + USBD_LL_Reset((USBD_HandleTypeDef*)hpcd->pData); +} + +/** + * @brief Suspend callback. + * When Low power mode is enabled the debug cannot be used (IAR, Keil doesn't support it) + * @param hpcd: PCD handle + * @retval None + */ +void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd) +{ + __HAL_PCD_GATE_PHYCLOCK(hpcd); + /* Inform USB library that core enters in suspend Mode. */ + USBD_LL_Suspend((USBD_HandleTypeDef*)hpcd->pData); + /* Enter in STOP mode. */ + /* USER CODE BEGIN 2 */ + if (hpcd->Init.low_power_enable) + { + /* Set SLEEPDEEP bit and SleepOnExit of Cortex System Control Register. */ + SCB->SCR |= (uint32_t)((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk)); + } + /* USER CODE END 2 */ +} + +/** + * @brief Resume callback. + * When Low power mode is enabled the debug cannot be used (IAR, Keil doesn't support it) + * @param hpcd: PCD handle + * @retval None + */ +void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd) +{ + __HAL_PCD_UNGATE_PHYCLOCK(hpcd); + + /* USER CODE BEGIN 3 */ + if (hpcd->Init.low_power_enable) + { + /* Reset SLEEPDEEP bit of Cortex System Control Register. */ + SCB->SCR &= (uint32_t)~((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk)); + SystemClockConfig_Resume(); + } + /* USER CODE END 3 */ + USBD_LL_Resume((USBD_HandleTypeDef*)hpcd->pData); +} + +/** + * @brief ISOOUTIncomplete callback. + * @param hpcd: PCD handle + * @param epnum: Endpoint number + * @retval None + */ +void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) +{ + USBD_LL_IsoOUTIncomplete((USBD_HandleTypeDef*)hpcd->pData, epnum); +} + +/** + * @brief ISOINIncomplete callback. + * @param hpcd: PCD handle + * @param epnum: Endpoint number + * @retval None + */ +void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) +{ + USBD_LL_IsoINIncomplete((USBD_HandleTypeDef*)hpcd->pData, epnum); +} + +/** + * @brief Connect callback. + * @param hpcd: PCD handle + * @retval None + */ +void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd) +{ + USBD_LL_DevConnected((USBD_HandleTypeDef*)hpcd->pData); +} + +/** + * @brief Disconnect callback. + * @param hpcd: PCD handle + * @retval None + */ +void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd) +{ + USBD_LL_DevDisconnected((USBD_HandleTypeDef*)hpcd->pData); +} + +/******************************************************************************* + LL Driver Interface (USB Device Library --> PCD) +*******************************************************************************/ + +/** + * @brief Initializes the low level portion of the device driver. + * @param pdev: Device handle + * @retval USBD status + */ +USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev) +{ + /* Init USB Ip. */ + if (pdev->id == DEVICE_FS) { + /* Enable USB power on Pwrctrl CR2 register. */ + /* Link the driver to the stack. */ + hpcd_USB_OTG_FS.pData = pdev; + pdev->pData = &hpcd_USB_OTG_FS; + + hpcd_USB_OTG_FS.Instance = USB_OTG_FS; + hpcd_USB_OTG_FS.Init.dev_endpoints = 6; + hpcd_USB_OTG_FS.Init.speed = PCD_SPEED_FULL; + hpcd_USB_OTG_FS.Init.ep0_mps = DEP0CTL_MPS_64; + hpcd_USB_OTG_FS.Init.phy_itface = PCD_PHY_EMBEDDED; + hpcd_USB_OTG_FS.Init.Sof_enable = DISABLE; + hpcd_USB_OTG_FS.Init.low_power_enable = DISABLE; + hpcd_USB_OTG_FS.Init.lpm_enable = DISABLE; + hpcd_USB_OTG_FS.Init.battery_charging_enable = DISABLE; + hpcd_USB_OTG_FS.Init.use_dedicated_ep1 = DISABLE; + hpcd_USB_OTG_FS.Init.vbus_sensing_enable = DISABLE; + if (HAL_PCD_Init(&hpcd_USB_OTG_FS) != HAL_OK) + { + _Error_Handler(__FILE__, __LINE__); + } + + HAL_PCDEx_SetRxFiFo(&hpcd_USB_OTG_FS, 0x80); + HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 0, 0x40); + HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 1, 0x80); + } + return USBD_OK; +} + +/** + * @brief De-Initializes the low level portion of the device driver. + * @param pdev: Device handle + * @retval USBD status + */ +USBD_StatusTypeDef USBD_LL_DeInit(USBD_HandleTypeDef *pdev) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBD_StatusTypeDef usb_status = USBD_OK; + + hal_status = HAL_PCD_DeInit(pdev->pData); + + switch (hal_status) { + case HAL_OK : + usb_status = USBD_OK; + break; + case HAL_ERROR : + usb_status = USBD_FAIL; + break; + case HAL_BUSY : + usb_status = USBD_BUSY; + break; + case HAL_TIMEOUT : + usb_status = USBD_FAIL; + break; + default : + usb_status = USBD_FAIL; + break; + } + return usb_status; +} + +/** + * @brief Starts the low level portion of the device driver. + * @param pdev: Device handle + * @retval USBD status + */ +USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBD_StatusTypeDef usb_status = USBD_OK; + + hal_status = HAL_PCD_Start(pdev->pData); + + switch (hal_status) { + case HAL_OK : + usb_status = USBD_OK; + break; + case HAL_ERROR : + usb_status = USBD_FAIL; + break; + case HAL_BUSY : + usb_status = USBD_BUSY; + break; + case HAL_TIMEOUT : + usb_status = USBD_FAIL; + break; + default : + usb_status = USBD_FAIL; + break; + } + return usb_status; +} + +/** + * @brief Stops the low level portion of the device driver. + * @param pdev: Device handle + * @retval USBD status + */ +USBD_StatusTypeDef USBD_LL_Stop(USBD_HandleTypeDef *pdev) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBD_StatusTypeDef usb_status = USBD_OK; + + hal_status = HAL_PCD_Stop(pdev->pData); + + switch (hal_status) { + case HAL_OK : + usb_status = USBD_OK; + break; + case HAL_ERROR : + usb_status = USBD_FAIL; + break; + case HAL_BUSY : + usb_status = USBD_BUSY; + break; + case HAL_TIMEOUT : + usb_status = USBD_FAIL; + break; + default : + usb_status = USBD_FAIL; + break; + } + return usb_status; +} + +/** + * @brief Opens an endpoint of the low level driver. + * @param pdev: Device handle + * @param ep_addr: Endpoint number + * @param ep_type: Endpoint type + * @param ep_mps: Endpoint max packet size + * @retval USBD status + */ +USBD_StatusTypeDef USBD_LL_OpenEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t ep_type, uint16_t ep_mps) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBD_StatusTypeDef usb_status = USBD_OK; + + hal_status = HAL_PCD_EP_Open(pdev->pData, ep_addr, ep_mps, ep_type); + + switch (hal_status) { + case HAL_OK : + usb_status = USBD_OK; + break; + case HAL_ERROR : + usb_status = USBD_FAIL; + break; + case HAL_BUSY : + usb_status = USBD_BUSY; + break; + case HAL_TIMEOUT : + usb_status = USBD_FAIL; + break; + default : + usb_status = USBD_FAIL; + break; + } + return usb_status; +} + +/** + * @brief Closes an endpoint of the low level driver. + * @param pdev: Device handle + * @param ep_addr: Endpoint number + * @retval USBD status + */ +USBD_StatusTypeDef USBD_LL_CloseEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBD_StatusTypeDef usb_status = USBD_OK; + + hal_status = HAL_PCD_EP_Close(pdev->pData, ep_addr); + + switch (hal_status) { + case HAL_OK : + usb_status = USBD_OK; + break; + case HAL_ERROR : + usb_status = USBD_FAIL; + break; + case HAL_BUSY : + usb_status = USBD_BUSY; + break; + case HAL_TIMEOUT : + usb_status = USBD_FAIL; + break; + default : + usb_status = USBD_FAIL; + break; + } + return usb_status; +} + +/** + * @brief Flushes an endpoint of the Low Level Driver. + * @param pdev: Device handle + * @param ep_addr: Endpoint number + * @retval USBD status + */ +USBD_StatusTypeDef USBD_LL_FlushEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBD_StatusTypeDef usb_status = USBD_OK; + + hal_status = HAL_PCD_EP_Flush(pdev->pData, ep_addr); + + switch (hal_status) { + case HAL_OK : + usb_status = USBD_OK; + break; + case HAL_ERROR : + usb_status = USBD_FAIL; + break; + case HAL_BUSY : + usb_status = USBD_BUSY; + break; + case HAL_TIMEOUT : + usb_status = USBD_FAIL; + break; + default : + usb_status = USBD_FAIL; + break; + } + return usb_status; +} + +/** + * @brief Sets a Stall condition on an endpoint of the Low Level Driver. + * @param pdev: Device handle + * @param ep_addr: Endpoint number + * @retval USBD status + */ +USBD_StatusTypeDef USBD_LL_StallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBD_StatusTypeDef usb_status = USBD_OK; + + hal_status = HAL_PCD_EP_SetStall(pdev->pData, ep_addr); + + switch (hal_status) { + case HAL_OK : + usb_status = USBD_OK; + break; + case HAL_ERROR : + usb_status = USBD_FAIL; + break; + case HAL_BUSY : + usb_status = USBD_BUSY; + break; + case HAL_TIMEOUT : + usb_status = USBD_FAIL; + break; + default : + usb_status = USBD_FAIL; + break; + } + return usb_status; +} + +/** + * @brief Clears a Stall condition on an endpoint of the Low Level Driver. + * @param pdev: Device handle + * @param ep_addr: Endpoint number + * @retval USBD status + */ +USBD_StatusTypeDef USBD_LL_ClearStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBD_StatusTypeDef usb_status = USBD_OK; + + hal_status = HAL_PCD_EP_ClrStall(pdev->pData, ep_addr); + + switch (hal_status) { + case HAL_OK : + usb_status = USBD_OK; + break; + case HAL_ERROR : + usb_status = USBD_FAIL; + break; + case HAL_BUSY : + usb_status = USBD_BUSY; + break; + case HAL_TIMEOUT : + usb_status = USBD_FAIL; + break; + default : + usb_status = USBD_FAIL; + break; + } + return usb_status; +} + +/** + * @brief Returns Stall condition. + * @param pdev: Device handle + * @param ep_addr: Endpoint number + * @retval Stall (1: Yes, 0: No) + */ +uint8_t USBD_LL_IsStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) +{ + PCD_HandleTypeDef *hpcd = (PCD_HandleTypeDef*) pdev->pData; + + if((ep_addr & 0x80) == 0x80) + { + return hpcd->IN_ep[ep_addr & 0x7F].is_stall; + } + else + { + return hpcd->OUT_ep[ep_addr & 0x7F].is_stall; + } +} + +/** + * @brief Assigns a USB address to the device. + * @param pdev: Device handle + * @param dev_addr: Device address + * @retval USBD status + */ +USBD_StatusTypeDef USBD_LL_SetUSBAddress(USBD_HandleTypeDef *pdev, uint8_t dev_addr) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBD_StatusTypeDef usb_status = USBD_OK; + + hal_status = HAL_PCD_SetAddress(pdev->pData, dev_addr); + + switch (hal_status) { + case HAL_OK : + usb_status = USBD_OK; + break; + case HAL_ERROR : + usb_status = USBD_FAIL; + break; + case HAL_BUSY : + usb_status = USBD_BUSY; + break; + case HAL_TIMEOUT : + usb_status = USBD_FAIL; + break; + default : + usb_status = USBD_FAIL; + break; + } + return usb_status; +} + +/** + * @brief Transmits data over an endpoint. + * @param pdev: Device handle + * @param ep_addr: Endpoint number + * @param pbuf: Pointer to data to be sent + * @param size: Data size + * @retval USBD status + */ +USBD_StatusTypeDef USBD_LL_Transmit(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t *pbuf, uint16_t size) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBD_StatusTypeDef usb_status = USBD_OK; + + hal_status = HAL_PCD_EP_Transmit(pdev->pData, ep_addr, pbuf, size); + + switch (hal_status) { + case HAL_OK : + usb_status = USBD_OK; + break; + case HAL_ERROR : + usb_status = USBD_FAIL; + break; + case HAL_BUSY : + usb_status = USBD_BUSY; + break; + case HAL_TIMEOUT : + usb_status = USBD_FAIL; + break; + default : + usb_status = USBD_FAIL; + break; + } + return usb_status; +} + +/** + * @brief Prepares an endpoint for reception. + * @param pdev: Device handle + * @param ep_addr: Endpoint number + * @param pbuf: Pointer to data to be received + * @param size: Data size + * @retval USBD status + */ +USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t *pbuf, uint16_t size) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBD_StatusTypeDef usb_status = USBD_OK; + + hal_status = HAL_PCD_EP_Receive(pdev->pData, ep_addr, pbuf, size); + + switch (hal_status) { + case HAL_OK : + usb_status = USBD_OK; + break; + case HAL_ERROR : + usb_status = USBD_FAIL; + break; + case HAL_BUSY : + usb_status = USBD_BUSY; + break; + case HAL_TIMEOUT : + usb_status = USBD_FAIL; + break; + default : + usb_status = USBD_FAIL; + break; + } + return usb_status; +} + +/** + * @brief Returns the last transfered packet size. + * @param pdev: Device handle + * @param ep_addr: Endpoint number + * @retval Recived Data Size + */ +uint32_t USBD_LL_GetRxDataSize(USBD_HandleTypeDef *pdev, uint8_t ep_addr) +{ + return HAL_PCD_EP_GetRxCount((PCD_HandleTypeDef*) pdev->pData, ep_addr); +} + +#if (USBD_LPM_ENABLED == 1) +/** + * @brief Send LPM message to user layer + * @param hpcd: PCD handle + * @param msg: LPM message + * @retval None + */ +void HAL_PCDEx_LPM_Callback(PCD_HandleTypeDef *hpcd, PCD_LPM_MsgTypeDef msg) +{ + switch (msg) + { + case PCD_LPM_L0_ACTIVE: + if (hpcd->Init.low_power_enable) + { + SystemClock_Config(); + + /* Reset SLEEPDEEP bit of Cortex System Control Register. */ + SCB->SCR &= (uint32_t)~((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk)); + } + __HAL_PCD_UNGATE_PHYCLOCK(hpcd); + USBD_LL_Resume(hpcd->pData); + break; + + case PCD_LPM_L1_ACTIVE: + __HAL_PCD_GATE_PHYCLOCK(hpcd); + USBD_LL_Suspend(hpcd->pData); + + /* Enter in STOP mode. */ + if (hpcd->Init.low_power_enable) + { + /* Set SLEEPDEEP bit and SleepOnExit of Cortex System Control Register. */ + SCB->SCR |= (uint32_t)((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk)); + } + break; + } +} +#endif /* (USBD_LPM_ENABLED == 1) */ + +/** + * @brief Delays routine for the USB Device Library. + * @param Delay: Delay in ms + * @retval None + */ +void USBD_LL_Delay(uint32_t Delay) +{ + HAL_Delay(Delay); +} + +/** + * @brief Static single allocation. + * @param size: Size of allocated memory + * @retval None + */ +void *USBD_static_malloc(uint32_t size) +{ + static uint32_t mem[(sizeof(USBD_CDC_HandleTypeDef)/4)+1];/* On 32-bit boundary */ + return mem; +} + +/** + * @brief Dummy memory free + * @param p: Pointer to allocated memory address + * @retval None + */ +void USBD_static_free(void *p) +{ + +} + +/* USER CODE BEGIN 5 */ +/** + * @brief Configures system clock after wake-up from USB resume callBack: + * enable HSI, PLL and select PLL as system clock source. + * @retval None + */ +static void SystemClockConfig_Resume(void) +{ + SystemClock_Config(); +} +/* USER CODE END 5 */ + +/** + * @brief Software device connection + * @param hpcd: PCD handle + * @param state: Connection state (0: disconnected / 1: connected) + * @retval None + */ +void HAL_PCDEx_SetConnectionState(PCD_HandleTypeDef *hpcd, uint8_t state) +{ + /* USER CODE BEGIN 6 */ + if (state == 1) + { + /* Configure Low connection state. */ + + } + else + { + /* Configure High connection state. */ + + } + /* USER CODE END 6 */ +} + +/** + * @brief Verify if the Battery Charging Detection mode (BCD) is used : + * return USBD_OK if true + * else return USBD_FAIL if false + * @param pdev: Device handle + * @retval USBD status + */ +USBD_StatusTypeDef USBD_LL_BatteryCharging(USBD_HandleTypeDef *pdev) +{ + PCD_HandleTypeDef *hpcd = (PCD_HandleTypeDef*)pdev->pData; + if (hpcd->Init.battery_charging_enable == ENABLE) + { + return USBD_OK; + } + else + { + return USBD_FAIL; + } +} + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/usbd_desc.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/usbd_desc.c new file mode 100644 index 0000000..2e3a7e1 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/Src/usbd_desc.c @@ -0,0 +1,405 @@ +/** + ****************************************************************************** + * @file : usbd_desc.c + * @version : v2.0_Cube + * @brief : This file implements the USB device descriptors. + ****************************************************************************** + * This notice applies to any and all portions of this file + * that are not between comment pairs USER CODE BEGIN and + * USER CODE END. Other portions of this file, whether + * inserted by the user or by software development tools + * are owned by their respective copyright owners. + * + * Copyright (c) 2018 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. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_core.h" +#include "usbd_desc.h" +#include "usbd_conf.h" + +/* USER CODE BEGIN INCLUDE */ + +/* USER CODE END INCLUDE */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ + +/* USER CODE BEGIN PV */ +/* Private variables ---------------------------------------------------------*/ + +/* USER CODE END PV */ + +/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY + * @{ + */ + +/** @addtogroup USBD_DESC + * @{ + */ + +/** @defgroup USBD_DESC_Private_TypesDefinitions USBD_DESC_Private_TypesDefinitions + * @brief Private types. + * @{ + */ + +/* USER CODE BEGIN PRIVATE_TYPES */ + +/* USER CODE END PRIVATE_TYPES */ + +/** + * @} + */ + +/** @defgroup USBD_DESC_Private_Defines USBD_DESC_Private_Defines + * @brief Private defines. + * @{ + */ + +#define USBD_VID 1155 +#define USBD_LANGID_STRING 1033 +#define USBD_MANUFACTURER_STRING "STMicroelectronics" +#define USBD_PID_FS 22336 +#define USBD_PRODUCT_STRING_FS "STM32 Virtual ComPort" +#define USBD_SERIALNUMBER_STRING_FS "00000000001A" +#define USBD_CONFIGURATION_STRING_FS "CDC Config" +#define USBD_INTERFACE_STRING_FS "CDC Interface" + +#define USB_SIZ_BOS_DESC 0x0C + +/* USER CODE BEGIN PRIVATE_DEFINES */ + +/* USER CODE END PRIVATE_DEFINES */ + +/** + * @} + */ + +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/** @defgroup USBD_DESC_Private_Macros USBD_DESC_Private_Macros + * @brief Private macros. + * @{ + */ + +/* USER CODE BEGIN PRIVATE_MACRO */ + +/* USER CODE END PRIVATE_MACRO */ + +/** + * @} + */ + +/** @defgroup USBD_DESC_Private_FunctionPrototypes USBD_DESC_Private_FunctionPrototypes + * @brief Private functions declaration. + * @{ + */ + +uint8_t * USBD_FS_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +uint8_t * USBD_FS_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +uint8_t * USBD_FS_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +uint8_t * USBD_FS_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +uint8_t * USBD_FS_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +uint8_t * USBD_FS_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +uint8_t * USBD_FS_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); + +#ifdef USB_SUPPORT_USER_STRING_DESC +uint8_t * USBD_FS_USRStringDesc(USBD_SpeedTypeDef speed, uint8_t idx, uint16_t *length); +#endif /* USB_SUPPORT_USER_STRING_DESC */ + +#if (USBD_LPM_ENABLED == 1) +uint8_t * USBD_FS_USR_BOSDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +#endif /* (USBD_LPM_ENABLED == 1) */ + +/** + * @} + */ + +/** @defgroup USBD_DESC_Private_Variables USBD_DESC_Private_Variables + * @brief Private variables. + * @{ + */ + +USBD_DescriptorsTypeDef FS_Desc = +{ + USBD_FS_DeviceDescriptor +, USBD_FS_LangIDStrDescriptor +, USBD_FS_ManufacturerStrDescriptor +, USBD_FS_ProductStrDescriptor +, USBD_FS_SerialStrDescriptor +, USBD_FS_ConfigStrDescriptor +, USBD_FS_InterfaceStrDescriptor +#if (USBD_LPM_ENABLED == 1) +, USBD_FS_USR_BOSDescriptor +#endif /* (USBD_LPM_ENABLED == 1) */ +}; + +#if defined ( __ICCARM__ ) /* IAR Compiler */ + #pragma data_alignment=4 +#endif /* defined ( __ICCARM__ ) */ +/** USB standard device descriptor. */ +__ALIGN_BEGIN uint8_t USBD_FS_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END = +{ + 0x12, /*bLength */ + USB_DESC_TYPE_DEVICE, /*bDescriptorType*/ +#if (USBD_LPM_ENABLED == 1) + 0x01, /*bcdUSB */ /* changed to USB version 2.01 + in order to support LPM L1 suspend + resume test of USBCV3.0*/ +#else + 0x00, /*bcdUSB */ +#endif /* (USBD_LPM_ENABLED == 1) */ + 0x02, + 0x02, /*bDeviceClass*/ + 0x02, /*bDeviceSubClass*/ + 0x00, /*bDeviceProtocol*/ + USB_MAX_EP0_SIZE, /*bMaxPacketSize*/ + LOBYTE(USBD_VID), /*idVendor*/ + HIBYTE(USBD_VID), /*idVendor*/ + LOBYTE(USBD_PID_FS), /*idProduct*/ + HIBYTE(USBD_PID_FS), /*idProduct*/ + 0x00, /*bcdDevice rel. 2.00*/ + 0x02, + USBD_IDX_MFC_STR, /*Index of manufacturer string*/ + USBD_IDX_PRODUCT_STR, /*Index of product string*/ + USBD_IDX_SERIAL_STR, /*Index of serial number string*/ + USBD_MAX_NUM_CONFIGURATION /*bNumConfigurations*/ +}; + +/* USB_DeviceDescriptor */ +/** BOS descriptor. */ +#if (USBD_LPM_ENABLED == 1) +#if defined ( __ICCARM__ ) /* IAR Compiler */ + #pragma data_alignment=4 +#endif /* defined ( __ICCARM__ ) */ +__ALIGN_BEGIN uint8_t USBD_FS_BOSDesc[USB_SIZ_BOS_DESC] __ALIGN_END = +{ + 0x5, + USB_DESC_TYPE_BOS, + 0xC, + 0x0, + 0x1, /* 1 device capability*/ + /* device capability*/ + 0x7, + USB_DEVICE_CAPABITY_TYPE, + 0x2, + 0x2, /* LPM capability bit set*/ + 0x0, + 0x0, + 0x0 +}; +#endif /* (USBD_LPM_ENABLED == 1) */ + +/** + * @} + */ + +/** @defgroup USBD_DESC_Private_Variables USBD_DESC_Private_Variables + * @brief Private variables. + * @{ + */ + +#if defined ( __ICCARM__ ) /* IAR Compiler */ + #pragma data_alignment=4 +#endif /* defined ( __ICCARM__ ) */ + +/** USB lang indentifier descriptor. */ +__ALIGN_BEGIN uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC] __ALIGN_END = +{ + USB_LEN_LANGID_STR_DESC, + USB_DESC_TYPE_STRING, + LOBYTE(USBD_LANGID_STRING), + HIBYTE(USBD_LANGID_STRING) +}; + +#if defined ( __ICCARM__ ) /* IAR Compiler */ + #pragma data_alignment=4 +#endif /* defined ( __ICCARM__ ) */ +/* Internal string descriptor. */ +__ALIGN_BEGIN uint8_t USBD_StrDesc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END; + +/** + * @} + */ + +/** @defgroup USBD_DESC_Private_Functions USBD_DESC_Private_Functions + * @brief Private functions. + * @{ + */ + +/** + * @brief Return the device descriptor + * @param speed : Current device speed + * @param length : Pointer to data length variable + * @retval Pointer to descriptor buffer + */ +uint8_t * USBD_FS_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) +{ + *length = sizeof(USBD_FS_DeviceDesc); + return USBD_FS_DeviceDesc; +} + +/** + * @brief Return the LangID string descriptor + * @param speed : Current device speed + * @param length : Pointer to data length variable + * @retval Pointer to descriptor buffer + */ +uint8_t * USBD_FS_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) +{ + *length = sizeof(USBD_LangIDDesc); + return USBD_LangIDDesc; +} + +/** + * @brief Return the product string descriptor + * @param speed : Current device speed + * @param length : Pointer to data length variable + * @retval Pointer to descriptor buffer + */ +uint8_t * USBD_FS_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) +{ + if(speed == 0) + { + USBD_GetString((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length); + } + else + { + USBD_GetString((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length); + } + return USBD_StrDesc; +} + +/** + * @brief Return the manufacturer string descriptor + * @param speed : Current device speed + * @param length : Pointer to data length variable + * @retval Pointer to descriptor buffer + */ +uint8_t * USBD_FS_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) +{ + USBD_GetString((uint8_t *)USBD_MANUFACTURER_STRING, USBD_StrDesc, length); + return USBD_StrDesc; +} + +/** + * @brief Return the serial number string descriptor + * @param speed : Current device speed + * @param length : Pointer to data length variable + * @retval Pointer to descriptor buffer + */ +uint8_t * USBD_FS_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) +{ + if(speed == USBD_SPEED_HIGH) + { + USBD_GetString((uint8_t *)USBD_SERIALNUMBER_STRING_FS, USBD_StrDesc, length); + } + else + { + USBD_GetString((uint8_t *)USBD_SERIALNUMBER_STRING_FS, USBD_StrDesc, length); + } + return USBD_StrDesc; +} + +/** + * @brief Return the configuration string descriptor + * @param speed : Current device speed + * @param length : Pointer to data length variable + * @retval Pointer to descriptor buffer + */ +uint8_t * USBD_FS_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) +{ + if(speed == USBD_SPEED_HIGH) + { + USBD_GetString((uint8_t *)USBD_CONFIGURATION_STRING_FS, USBD_StrDesc, length); + } + else + { + USBD_GetString((uint8_t *)USBD_CONFIGURATION_STRING_FS, USBD_StrDesc, length); + } + return USBD_StrDesc; +} + +/** + * @brief Return the interface string descriptor + * @param speed : Current device speed + * @param length : Pointer to data length variable + * @retval Pointer to descriptor buffer + */ +uint8_t * USBD_FS_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) +{ + if(speed == 0) + { + USBD_GetString((uint8_t *)USBD_INTERFACE_STRING_FS, USBD_StrDesc, length); + } + else + { + USBD_GetString((uint8_t *)USBD_INTERFACE_STRING_FS, USBD_StrDesc, length); + } + return USBD_StrDesc; +} + +#if (USBD_LPM_ENABLED == 1) +/** + * @brief Return the BOS descriptor + * @param speed : Current device speed + * @param length : Pointer to data length variable + * @retval Pointer to descriptor buffer + */ +uint8_t * USBD_FS_USR_BOSDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) +{ + *length = sizeof(USBD_FS_BOSDesc); + return (uint8_t*)USBD_FS_BOSDesc; +} +#endif /* (USBD_LPM_ENABLED == 1) */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/mx.scratch b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/mx.scratch new file mode 100644 index 0000000..a4d6e0b --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/mx.scratch @@ -0,0 +1,91 @@ + + +D:\VS\brianTPM\Samples\Nucleo-TPM\L4A6RG\\Nucleo-L4A6RG +C +..\Drivers\CMSIS +C:\Users\Stefanth\STM32Cube\Repository\STM32Cube_FW_L4_V1.11.0\Drivers\CMSIS +TrueSTUDIO +0 + + + + + + + + + + + + + + + + + Nucleo-L4A6RG + STM32L4A6RGTx + 0x200 + 0x10000 + + custom + + true + swd + + 1 + + + + + + + + + + + + __weak=__attribute__((weak)) + __packed=__attribute__((__packed__)) + + + + + + + USE_FULL_LL_DRIVER + MBEDTLS_CONFIG_FILE="mbedtls_config.h" + + + + + ..\Inc + ..\Drivers\STM32L4xx_HAL_Driver\Inc + ..\Drivers\STM32L4xx_HAL_Driver\Inc\Legacy + ..\Middlewares\ST\STM32_USB_Device_Library\Core\Inc + ..\Middlewares\ST\STM32_USB_Device_Library\Class\CDC\Inc + ..\Drivers\CMSIS\Device\ST\STM32L4xx\Include + ..\Drivers\CMSIS\Include + + + + + + true + false + + + + Inc + + + Src + + + Drivers + + + Middlewares + + + + diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/startup/startup_stm32l4a6xx.s b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/startup/startup_stm32l4a6xx.s new file mode 100644 index 0000000..15a7f5a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/L4A6RG/startup/startup_stm32l4a6xx.s @@ -0,0 +1,563 @@ +/** + ****************************************************************************** + * @file startup_stm32l4a6xx.s + * @author MCD Application Team + * @brief STM32L4A6xx devices vector table GCC toolchain. + * This module performs: + * - Set the initial SP + * - Set the initial PC == Reset_Handler, + * - Set the vector table entries with the exceptions ISR address, + * - Configure the clock system + * - Branches to main in the C library (which eventually + * calls main()). + * After Reset the Cortex-M4 processor is in Thread mode, + * priority is Privileged, and the Stack is set to Main. + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics

    + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its 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. + * + ****************************************************************************** + */ + + .syntax unified + .cpu cortex-m4 + .fpu softvfp + .thumb + +.global g_pfnVectors +.global Default_Handler + +/* start address for the initialization values of the .data section. +defined in linker script */ +.word _sidata +/* start address for the .data section. defined in linker script */ +.word _sdata +/* end address for the .data section. defined in linker script */ +.word _edata +/* start address for the .bss section. defined in linker script */ +.word _sbss +/* end address for the .bss section. defined in linker script */ +.word _ebss + +.equ BootRAM, 0xF1E0F85F +/** + * @brief This is the code that gets called when the processor first + * starts execution following a reset event. Only the absolutely + * necessary set is performed, after which the application + * supplied main() routine is called. + * @param None + * @retval : None +*/ + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + ldr sp, =_estack /* Atollic update: set stack pointer */ + +/* Copy the data segment initializers from flash to SRAM */ + movs r1, #0 + b LoopCopyDataInit + +CopyDataInit: + ldr r3, =_sidata + ldr r3, [r3, r1] + str r3, [r0, r1] + adds r1, r1, #4 + +LoopCopyDataInit: + ldr r0, =_sdata + ldr r3, =_edata + adds r2, r0, r1 + cmp r2, r3 + bcc CopyDataInit + ldr r2, =_sbss + b LoopFillZerobss +/* Zero fill the bss segment. */ +FillZerobss: + movs r3, #0 + str r3, [r2], #4 + +LoopFillZerobss: + ldr r3, = _ebss + cmp r2, r3 + bcc FillZerobss + +/* Call the clock system intitialization function.*/ + bl SystemInit +/* Call static constructors */ + bl __libc_init_array +/* Call the application's entry point.*/ + bl main + +LoopForever: + b LoopForever + +.size Reset_Handler, .-Reset_Handler + +/** + * @brief This is the code that gets called when the processor receives an + * unexpected interrupt. This simply enters an infinite loop, preserving + * the system state for examination by a debugger. + * + * @param None + * @retval : None +*/ + .section .text.Default_Handler,"ax",%progbits +Default_Handler: +Infinite_Loop: + b Infinite_Loop + .size Default_Handler, .-Default_Handler +/****************************************************************************** +* +* The minimal vector table for a Cortex-M4. Note that the proper constructs +* must be placed on this to ensure that it ends up at physical address +* 0x0000.0000. +* +******************************************************************************/ + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + .size g_pfnVectors, .-g_pfnVectors + + +g_pfnVectors: + .word _estack + .word Reset_Handler + .word NMI_Handler + .word HardFault_Handler + .word MemManage_Handler + .word BusFault_Handler + .word UsageFault_Handler + .word 0 + .word 0 + .word 0 + .word 0 + .word SVC_Handler + .word DebugMon_Handler + .word 0 + .word PendSV_Handler + .word SysTick_Handler + .word WWDG_IRQHandler + .word PVD_PVM_IRQHandler + .word TAMP_STAMP_IRQHandler + .word RTC_WKUP_IRQHandler + .word FLASH_IRQHandler + .word RCC_IRQHandler + .word EXTI0_IRQHandler + .word EXTI1_IRQHandler + .word EXTI2_IRQHandler + .word EXTI3_IRQHandler + .word EXTI4_IRQHandler + .word DMA1_Channel1_IRQHandler + .word DMA1_Channel2_IRQHandler + .word DMA1_Channel3_IRQHandler + .word DMA1_Channel4_IRQHandler + .word DMA1_Channel5_IRQHandler + .word DMA1_Channel6_IRQHandler + .word DMA1_Channel7_IRQHandler + .word ADC1_2_IRQHandler + .word CAN1_TX_IRQHandler + .word CAN1_RX0_IRQHandler + .word CAN1_RX1_IRQHandler + .word CAN1_SCE_IRQHandler + .word EXTI9_5_IRQHandler + .word TIM1_BRK_TIM15_IRQHandler + .word TIM1_UP_TIM16_IRQHandler + .word TIM1_TRG_COM_TIM17_IRQHandler + .word TIM1_CC_IRQHandler + .word TIM2_IRQHandler + .word TIM3_IRQHandler + .word TIM4_IRQHandler + .word I2C1_EV_IRQHandler + .word I2C1_ER_IRQHandler + .word I2C2_EV_IRQHandler + .word I2C2_ER_IRQHandler + .word SPI1_IRQHandler + .word SPI2_IRQHandler + .word USART1_IRQHandler + .word USART2_IRQHandler + .word USART3_IRQHandler + .word EXTI15_10_IRQHandler + .word RTC_Alarm_IRQHandler + .word DFSDM1_FLT3_IRQHandler + .word TIM8_BRK_IRQHandler + .word TIM8_UP_IRQHandler + .word TIM8_TRG_COM_IRQHandler + .word TIM8_CC_IRQHandler + .word ADC3_IRQHandler + .word FMC_IRQHandler + .word SDMMC1_IRQHandler + .word TIM5_IRQHandler + .word SPI3_IRQHandler + .word UART4_IRQHandler + .word UART5_IRQHandler + .word TIM6_DAC_IRQHandler + .word TIM7_IRQHandler + .word DMA2_Channel1_IRQHandler + .word DMA2_Channel2_IRQHandler + .word DMA2_Channel3_IRQHandler + .word DMA2_Channel4_IRQHandler + .word DMA2_Channel5_IRQHandler + .word DFSDM1_FLT0_IRQHandler + .word DFSDM1_FLT1_IRQHandler + .word DFSDM1_FLT2_IRQHandler + .word COMP_IRQHandler + .word LPTIM1_IRQHandler + .word LPTIM2_IRQHandler + .word OTG_FS_IRQHandler + .word DMA2_Channel6_IRQHandler + .word DMA2_Channel7_IRQHandler + .word LPUART1_IRQHandler + .word QUADSPI_IRQHandler + .word I2C3_EV_IRQHandler + .word I2C3_ER_IRQHandler + .word SAI1_IRQHandler + .word SAI2_IRQHandler + .word SWPMI1_IRQHandler + .word TSC_IRQHandler + .word LCD_IRQHandler + .word AES_IRQHandler + .word HASH_RNG_IRQHandler + .word FPU_IRQHandler + .word CRS_IRQHandler + .word I2C4_EV_IRQHandler + .word I2C4_ER_IRQHandler + .word DCMI_IRQHandler + .word CAN2_TX_IRQHandler + .word CAN2_RX0_IRQHandler + .word CAN2_RX1_IRQHandler + .word CAN2_SCE_IRQHandler + .word DMA2D_IRQHandler + + +/******************************************************************************* +* +* Provide weak aliases for each Exception handler to the Default_Handler. +* As they are weak aliases, any function with the same name will override +* this definition. +* +*******************************************************************************/ + + .weak NMI_Handler + .thumb_set NMI_Handler,Default_Handler + + .weak HardFault_Handler + .thumb_set HardFault_Handler,Default_Handler + + .weak MemManage_Handler + .thumb_set MemManage_Handler,Default_Handler + + .weak BusFault_Handler + .thumb_set BusFault_Handler,Default_Handler + + .weak UsageFault_Handler + .thumb_set UsageFault_Handler,Default_Handler + + .weak SVC_Handler + .thumb_set SVC_Handler,Default_Handler + + .weak DebugMon_Handler + .thumb_set DebugMon_Handler,Default_Handler + + .weak PendSV_Handler + .thumb_set PendSV_Handler,Default_Handler + + .weak SysTick_Handler + .thumb_set SysTick_Handler,Default_Handler + + .weak WWDG_IRQHandler + .thumb_set WWDG_IRQHandler,Default_Handler + + .weak PVD_PVM_IRQHandler + .thumb_set PVD_PVM_IRQHandler,Default_Handler + + .weak TAMP_STAMP_IRQHandler + .thumb_set TAMP_STAMP_IRQHandler,Default_Handler + + .weak RTC_WKUP_IRQHandler + .thumb_set RTC_WKUP_IRQHandler,Default_Handler + + .weak FLASH_IRQHandler + .thumb_set FLASH_IRQHandler,Default_Handler + + .weak RCC_IRQHandler + .thumb_set RCC_IRQHandler,Default_Handler + + .weak EXTI0_IRQHandler + .thumb_set EXTI0_IRQHandler,Default_Handler + + .weak EXTI1_IRQHandler + .thumb_set EXTI1_IRQHandler,Default_Handler + + .weak EXTI2_IRQHandler + .thumb_set EXTI2_IRQHandler,Default_Handler + + .weak EXTI3_IRQHandler + .thumb_set EXTI3_IRQHandler,Default_Handler + + .weak EXTI4_IRQHandler + .thumb_set EXTI4_IRQHandler,Default_Handler + + .weak DMA1_Channel1_IRQHandler + .thumb_set DMA1_Channel1_IRQHandler,Default_Handler + + .weak DMA1_Channel2_IRQHandler + .thumb_set DMA1_Channel2_IRQHandler,Default_Handler + + .weak DMA1_Channel3_IRQHandler + .thumb_set DMA1_Channel3_IRQHandler,Default_Handler + + .weak DMA1_Channel4_IRQHandler + .thumb_set DMA1_Channel4_IRQHandler,Default_Handler + + .weak DMA1_Channel5_IRQHandler + .thumb_set DMA1_Channel5_IRQHandler,Default_Handler + + .weak DMA1_Channel6_IRQHandler + .thumb_set DMA1_Channel6_IRQHandler,Default_Handler + + .weak DMA1_Channel7_IRQHandler + .thumb_set DMA1_Channel7_IRQHandler,Default_Handler + + .weak ADC1_2_IRQHandler + .thumb_set ADC1_2_IRQHandler,Default_Handler + + .weak CAN1_TX_IRQHandler + .thumb_set CAN1_TX_IRQHandler,Default_Handler + + .weak CAN1_RX0_IRQHandler + .thumb_set CAN1_RX0_IRQHandler,Default_Handler + + .weak CAN1_RX1_IRQHandler + .thumb_set CAN1_RX1_IRQHandler,Default_Handler + + .weak CAN1_SCE_IRQHandler + .thumb_set CAN1_SCE_IRQHandler,Default_Handler + + .weak EXTI9_5_IRQHandler + .thumb_set EXTI9_5_IRQHandler,Default_Handler + + .weak TIM1_BRK_TIM15_IRQHandler + .thumb_set TIM1_BRK_TIM15_IRQHandler,Default_Handler + + .weak TIM1_UP_TIM16_IRQHandler + .thumb_set TIM1_UP_TIM16_IRQHandler,Default_Handler + + .weak TIM1_TRG_COM_TIM17_IRQHandler + .thumb_set TIM1_TRG_COM_TIM17_IRQHandler,Default_Handler + + .weak TIM1_CC_IRQHandler + .thumb_set TIM1_CC_IRQHandler,Default_Handler + + .weak TIM2_IRQHandler + .thumb_set TIM2_IRQHandler,Default_Handler + + .weak TIM3_IRQHandler + .thumb_set TIM3_IRQHandler,Default_Handler + + .weak TIM4_IRQHandler + .thumb_set TIM4_IRQHandler,Default_Handler + + .weak I2C1_EV_IRQHandler + .thumb_set I2C1_EV_IRQHandler,Default_Handler + + .weak I2C1_ER_IRQHandler + .thumb_set I2C1_ER_IRQHandler,Default_Handler + + .weak I2C2_EV_IRQHandler + .thumb_set I2C2_EV_IRQHandler,Default_Handler + + .weak I2C2_ER_IRQHandler + .thumb_set I2C2_ER_IRQHandler,Default_Handler + + .weak SPI1_IRQHandler + .thumb_set SPI1_IRQHandler,Default_Handler + + .weak SPI2_IRQHandler + .thumb_set SPI2_IRQHandler,Default_Handler + + .weak USART1_IRQHandler + .thumb_set USART1_IRQHandler,Default_Handler + + .weak USART2_IRQHandler + .thumb_set USART2_IRQHandler,Default_Handler + + .weak USART3_IRQHandler + .thumb_set USART3_IRQHandler,Default_Handler + + .weak EXTI15_10_IRQHandler + .thumb_set EXTI15_10_IRQHandler,Default_Handler + + .weak RTC_Alarm_IRQHandler + .thumb_set RTC_Alarm_IRQHandler,Default_Handler + + .weak DFSDM1_FLT3_IRQHandler + .thumb_set DFSDM1_FLT3_IRQHandler,Default_Handler + + .weak TIM8_BRK_IRQHandler + .thumb_set TIM8_BRK_IRQHandler,Default_Handler + + .weak TIM8_UP_IRQHandler + .thumb_set TIM8_UP_IRQHandler,Default_Handler + + .weak TIM8_TRG_COM_IRQHandler + .thumb_set TIM8_TRG_COM_IRQHandler,Default_Handler + + .weak TIM8_CC_IRQHandler + .thumb_set TIM8_CC_IRQHandler,Default_Handler + + .weak ADC3_IRQHandler + .thumb_set ADC3_IRQHandler,Default_Handler + + .weak FMC_IRQHandler + .thumb_set FMC_IRQHandler,Default_Handler + + .weak SDMMC1_IRQHandler + .thumb_set SDMMC1_IRQHandler,Default_Handler + + .weak TIM5_IRQHandler + .thumb_set TIM5_IRQHandler,Default_Handler + + .weak SPI3_IRQHandler + .thumb_set SPI3_IRQHandler,Default_Handler + + .weak UART4_IRQHandler + .thumb_set UART4_IRQHandler,Default_Handler + + .weak UART5_IRQHandler + .thumb_set UART5_IRQHandler,Default_Handler + + .weak TIM6_DAC_IRQHandler + .thumb_set TIM6_DAC_IRQHandler,Default_Handler + + .weak TIM7_IRQHandler + .thumb_set TIM7_IRQHandler,Default_Handler + + .weak DMA2_Channel1_IRQHandler + .thumb_set DMA2_Channel1_IRQHandler,Default_Handler + + .weak DMA2_Channel2_IRQHandler + .thumb_set DMA2_Channel2_IRQHandler,Default_Handler + + .weak DMA2_Channel3_IRQHandler + .thumb_set DMA2_Channel3_IRQHandler,Default_Handler + + .weak DMA2_Channel4_IRQHandler + .thumb_set DMA2_Channel4_IRQHandler,Default_Handler + + .weak DMA2_Channel5_IRQHandler + .thumb_set DMA2_Channel5_IRQHandler,Default_Handler + + .weak DFSDM1_FLT0_IRQHandler + .thumb_set DFSDM1_FLT0_IRQHandler,Default_Handler + + .weak DFSDM1_FLT1_IRQHandler + .thumb_set DFSDM1_FLT1_IRQHandler,Default_Handler + + .weak DFSDM1_FLT2_IRQHandler + .thumb_set DFSDM1_FLT2_IRQHandler,Default_Handler + + .weak COMP_IRQHandler + .thumb_set COMP_IRQHandler,Default_Handler + + .weak LPTIM1_IRQHandler + .thumb_set LPTIM1_IRQHandler,Default_Handler + + .weak LPTIM2_IRQHandler + .thumb_set LPTIM2_IRQHandler,Default_Handler + + .weak OTG_FS_IRQHandler + .thumb_set OTG_FS_IRQHandler,Default_Handler + + .weak DMA2_Channel6_IRQHandler + .thumb_set DMA2_Channel6_IRQHandler,Default_Handler + + .weak DMA2_Channel7_IRQHandler + .thumb_set DMA2_Channel7_IRQHandler,Default_Handler + + .weak LPUART1_IRQHandler + .thumb_set LPUART1_IRQHandler,Default_Handler + + .weak QUADSPI_IRQHandler + .thumb_set QUADSPI_IRQHandler,Default_Handler + + .weak I2C3_EV_IRQHandler + .thumb_set I2C3_EV_IRQHandler,Default_Handler + + .weak I2C3_ER_IRQHandler + .thumb_set I2C3_ER_IRQHandler,Default_Handler + + .weak SAI1_IRQHandler + .thumb_set SAI1_IRQHandler,Default_Handler + + .weak SAI2_IRQHandler + .thumb_set SAI2_IRQHandler,Default_Handler + + .weak SWPMI1_IRQHandler + .thumb_set SWPMI1_IRQHandler,Default_Handler + + .weak TSC_IRQHandler + .thumb_set TSC_IRQHandler,Default_Handler + + .weak LCD_IRQHandler + .thumb_set LCD_IRQHandler,Default_Handler + + .weak AES_IRQHandler + .thumb_set AES_IRQHandler,Default_Handler + + .weak HASH_RNG_IRQHandler + .thumb_set HASH_RNG_IRQHandler,Default_Handler + + .weak FPU_IRQHandler + .thumb_set FPU_IRQHandler,Default_Handler + + .weak CRS_IRQHandler + .thumb_set CRS_IRQHandler,Default_Handler + + .weak I2C4_EV_IRQHandler + .thumb_set I2C4_EV_IRQHandler,Default_Handler + + .weak I2C4_ER_IRQHandler + .thumb_set I2C4_ER_IRQHandler,Default_Handler + + .weak DCMI_IRQHandler + .thumb_set DCMI_IRQHandler,Default_Handler + + .weak CAN2_TX_IRQHandler + .thumb_set CAN2_TX_IRQHandler,Default_Handler + + .weak CAN2_RX0_IRQHandler + .thumb_set CAN2_RX0_IRQHandler,Default_Handler + + .weak CAN2_RX1_IRQHandler + .thumb_set CAN2_RX1_IRQHandler,Default_Handler + + .weak CAN2_SCE_IRQHandler + .thumb_set CAN2_SCE_IRQHandler,Default_Handler + + .weak DMA2D_IRQHandler + .thumb_set DMA2D_IRQHandler,Default_Handler +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/include/PlatformData.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/include/PlatformData.h new file mode 100644 index 0000000..045e844 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/include/PlatformData.h @@ -0,0 +1,126 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 contains the instance data for the Platform module. It is collected +// in this file so that the state of the module is easier to manage. + +#ifndef _PLATFORM_DATA_H_ +#define _PLATFORM_DATA_H_ + + +#include "Implementation.h" + +// From Cancel.c +// Cancel flag. It is initialized as FALSE, which indicate the command is not +// being canceled +extern int s_isCanceled; + +#include + +#ifndef HARDWARE_CLOCK +// This is the value returned the last time that the system clock was read. This +// is only relevant for a simulator or virtual TPM. +extern clock_t s_realTimePrevious; +// This is the rate adjusted value that is the equivalent of what would be read from +// a hardware register that produced rate adjusted time. +extern clock_t s_tpmTime; +#endif // HARDWARE_CLOCK + +// This value indicates that the timer was reset +extern BOOL s_timerReset; +// This value indicates that the timer was stopped. It causes a clock discontinuity. +extern BOOL s_timerStopped; + +// CLOCK_NOMINAL is the number of hardware ticks per mS. A value of 300000 means +// that the nominal clock rate used to drive the hardware clock is 30 MHz. The +// adjustment rates are used to determine the conversion of the hardware ticks to +// internal hardware clock value. In practice, we would expect that there woudl be +// a hardware register will accumulated mS. It would be incremented by the output +// of a pre-scaler. The pre-scaler would divide the ticks from the clock by some +// value that would compensate for the difference between clock time and real time. +// The code in Clock does the emulation of this function. +#define CLOCK_NOMINAL 30000 +// A 1% change in rate is 300 counts +#define CLOCK_ADJUST_COARSE 300 +// A 0.1% change in rate is 30 counts +#define CLOCK_ADJUST_MEDIUM 30 +// A minimum change in rate is 1 count +#define CLOCK_ADJUST_FINE 1 +// The clock tolerance is +/-15% (4500 counts) +// Allow some guard band (16.7%) +#define CLOCK_ADJUST_LIMIT 5000 + +// This variable records the time when _plat__TimerReset is called. This mechanism +// allow us to subtract the time when TPM is power off from the total +// time reported by clock() function +extern uint64_t s_initClock; + +// This variable records the timer adjustment factor. +extern unsigned int s_adjustRate; + +// From LocalityPlat.c +// Locality of current command +extern unsigned char s_locality; + +// From NVMem.c +// Choose if the NV memory should be backed by RAM or by file. +// If this macro is defined, then a file is used as NV. If it is not defined, +// then RAM is used to back NV memory. Comment out to use RAM. +#define FILE_BACKED_NV +#if defined FILE_BACKED_NV +#include +// A file to emulate NV storage +extern FILE* s_NVFile; +#endif +extern unsigned char s_NV[NV_MEMORY_SIZE]; +extern BOOL s_NvIsAvailable; +extern BOOL s_NV_unrecoverable; +extern BOOL s_NV_recoverable; + + +// From PPPlat.c +// Physical presence. It is initialized to FALSE +extern BOOL s_physicalPresence; + +// From Power +extern BOOL s_powerLost; + +// From Entropy.c +extern uint32_t lastEntropy; + +extern int firstValue; + + +#endif // _PLATFORM_DATA_H_ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/include/prototypes/Platform_fp.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/include/prototypes/Platform_fp.h new file mode 100644 index 0000000..8fa93ab --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/include/prototypes/Platform_fp.h @@ -0,0 +1,443 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*(Auto) + Automatically Generated by TpmPrototypes version 2.2 February 10, 2016 + Date: Mar 23, 2017 Time: 03:31:52 PM +*/ + +#ifndef _PLATFORM_FP_H_ +#define _PLATFORM_FP_H_ + +//** From Cancel.c + + + +//***_plat__IsCanceled() +// Check if the cancel flag is set +// return type: BOOL +// TRUE(1) if cancel flag is set +// FALSE(0) if cancel flag is not set +LIB_EXPORT int +_plat__IsCanceled( + void + ); + +// Set cancel flag. +LIB_EXPORT void +_plat__SetCancel( + void + ); + +//***_plat__ClearCancel() +// Clear cancel flag +LIB_EXPORT void +_plat__ClearCancel( + void + ); + + +//** From Clock.c + + + +//***_plat__TimerReset() +// This function sets current system clock time as t0 for counting TPM time. +// This function is called at a power on event to reset the clock. When the clock +// is reset, the indication that the clock was stopped is also set. +LIB_EXPORT void +_plat__TimerReset( + void + ); + +//*** _plat__TimerRestart() +// This function should be called in order to simulate the restart of the timer +// should it be stopped while power is still applied. +LIB_EXPORT void +_plat__TimerRestart( + void + ); + +//***_plat__TimerRead() +// This function provides access to the tick timer of the platform. The TPM code +// uses this value to drive the TPM Clock. +// +// The tick timer is supposed to run when power is applied to the device. This timer +// should not be reset by time events including _TPM_Init. It should only be reset +// when TPM power is re-applied. +// +// If the TPM is run in a protected environment, that environment may provide the +// tick time to the TPM as long as the time provided by the environment is not +// allowed to go backwards. If the time provided by the system can go backwards +// during a power discontinuity, then the _plat__Signal_PowerOn should call +// _plat__TimerReset(). +// +// The code in this function should be replaced by a read of a hardware tick timer. +LIB_EXPORT uint64_t +_plat__TimerRead( + void + ); + +//*** _plat__TimerWasReset() +// This function is used to interrogate the flag indicating if the tick timer has +// been reset. +// +// If the resetFlag parameter is SET, then the flag will be CLEAR before the +// function returns. +LIB_EXPORT BOOL +_plat__TimerWasReset( + void + ); + +//*** _plat__TimerWasStopped() +// This function is used to interrogate the flag indicating if the tick timer has +// been stopped. If so, this is typically a reason to roll the nonce. +// +// This function will CLEAR the s_timerStopped flag before returning. This provides +// functionality that is similar to status register that is cleared when read. This +// is the model used here because it is the one that has the most impact on the TPM +// code as the flag can only be accessed by one entity in the TPM. Any other +// implementation of the hardware can be made to look like a read-once register. +LIB_EXPORT BOOL +_plat__TimerWasStopped( + void + ); + +//***_plat__ClockAdjustRate() +// Adjust the clock rate +LIB_EXPORT void +_plat__ClockAdjustRate( + int adjust // IN: the adjust number. It could be positive + // or negative + ); + + +//** From Entropy.c + + +// return type: int32_t +// < 0 hardware failure of the entropy generator, this is sticky +// >= 0 the returned amount of entropy (bytes) +// +LIB_EXPORT int32_t +_plat__GetEntropy( + unsigned char *entropy, // output buffer + uint32_t amount // amount requested + ); + + +//** From LocalityPlat.c + + + +//***_plat__LocalityGet() +// Get the most recent command locality in locality value form. +// This is an integer value for locality and not a locality structure +// The locality can be 0-4 or 32-255. 5-31 is not allowed. +LIB_EXPORT unsigned char +_plat__LocalityGet( + void + ); + +//***_plat__LocalitySet() +// Set the most recent command locality in locality value form +LIB_EXPORT void +_plat__LocalitySet( + unsigned char locality + ); + + +//** From NVMem.c + + + +//*** _plat__NvErrors() +// This function is used by the simulator to set the error flags in the NV +// subsystem to simulate an error in the NV loading process +LIB_EXPORT void +_plat__NvErrors( + int recoverable, + int unrecoverable + ); + +//***_plat__NVEnable() +// Enable NV memory. +// +// This version just pulls in data from a file. In a real TPM, with NV on chip, +// this function would verify the integrity of the saved context. If the NV +// memory was not on chip but was in something like RPMB, the NV state would be +// read in, decrypted and integrity checked. +// +// The recovery from an integrity failure depends on where the error occurred. It +// it was in the state that is discarded by TPM Reset, then the error is +// recoverable if the TPM is reset. Otherwise, the TPM must go into failure mode. +// return type: int +// 0 if success +// > 0 if receive recoverable error +// <0 if unrecoverable error +LIB_EXPORT int +_plat__NVEnable( + void *platParameter // IN: platform specific parameters + ); + +//***_plat__NVDisable() +// Disable NV memory +LIB_EXPORT void +_plat__NVDisable( + void + ); + +//***_plat__IsNvAvailable() +// Check if NV is available +// return type: int +// 0 NV is available +// 1 NV is not available due to write failure +// 2 NV is not available due to rate limit +LIB_EXPORT int +_plat__IsNvAvailable( + void + ); + +//***_plat__NvMemoryRead() +// Function: Read a chunk of NV memory +LIB_EXPORT void +_plat__NvMemoryRead( + unsigned int startOffset, // IN: read start + unsigned int size, // IN: size of bytes to read + void *data // OUT: data buffer + ); + +//*** _plat__NvIsDifferent() +// This function checks to see if the NV is different from the test value. This is +// so that NV will not be written if it has not changed. +// return value: int +// TRUE(1) the NV location is different from the test value +// FALSE(0) the NV location is the same as the test value +LIB_EXPORT int +_plat__NvIsDifferent( + unsigned int startOffset, // IN: read start + unsigned int size, // IN: size of bytes to read + void *data // IN: data buffer + ); + +//***_plat__NvMemoryWrite() +// This function is used to update NV memory. The "write" is to a memory copy of +// NV. At the end of the current command, any changes are written to +// the actual NV memory. +// NOTE: A useful optimization would be for this code to compare the current +// contents of NV with the local copy and note the blocks that have changed. Then +// only write those blocks when _plat__NvCommit() is called. +LIB_EXPORT void +_plat__NvMemoryWrite( + unsigned int startOffset, // IN: write start + unsigned int size, // IN: size of bytes to write + void *data // OUT: data buffer + ); + +//***_plat__NvMemoryClear() +// Function is used to set a range of NV memory bytes to an implementation-dependent +// value. The value represents the erase state of the memory. +LIB_EXPORT void +_plat__NvMemoryClear( + unsigned int start, // IN: clear start + unsigned int size // IN: number of bytes to clear + ); + +//***_plat__NvMemoryMove() +// Function: Move a chunk of NV memory from source to destination +// This function should ensure that if there overlap, the original data is +// copied before it is written +LIB_EXPORT void +_plat__NvMemoryMove( + unsigned int sourceOffset, // IN: source offset + unsigned int destOffset, // IN: destination offset + unsigned int size // IN: size of data being moved + ); + +//***_plat__NvCommit() +// Update NV chip +// return type: int +// 0 NV write success +// non-0 NV write fail +LIB_EXPORT int +_plat__NvCommit( + void + ); + +//***_plat__SetNvAvail() +// Set the current NV state to available. This function is for testing purpose +// only. It is not part of the platform NV logic +LIB_EXPORT void +_plat__SetNvAvail( + void + ); + +//***_plat__ClearNvAvail() +// Set the current NV state to unavailable. This function is for testing purpose +// only. It is not part of the platform NV logic +LIB_EXPORT void +_plat__ClearNvAvail( + void + ); + + +//** From PlatformData.c + + + + +//** From PowerPlat.c + + + +//***_plat__Signal_PowerOn() +// Signal platform power on +LIB_EXPORT int +_plat__Signal_PowerOn( + void + ); + +//*** _plat__WasPowerLost() +// Test whether power was lost before a _TPM_Init. +// +// This function will clear the "hardware" indication of power loss before return. +// This means that there can only be one spot in the TPM code where this value +// gets read. This method is used here as it is the most difficult to manage in the +// TPM code and, if the hardware actually works this way, it is hard to make it +// look like anything else. So, the burden is placed on the TPM code rather than the +// platform code +// return type: int +// TRUE(1) power was lost +// FALSE(0) power was not lost +LIB_EXPORT int +_plat__WasPowerLost( + void + ); + +//*** _plat_Signal_Reset() +// This a TPM reset without a power loss. +LIB_EXPORT int +_plat__Signal_Reset( + void + ); + +//***_plat__Signal_PowerOff() +// Signal platform power off +LIB_EXPORT void +_plat__Signal_PowerOff( + void + ); + + +//** From PPPlat.c + + + +//***_plat__PhysicalPresenceAsserted() +// Check if physical presence is signaled +// return type: int +// TRUE(1) if physical presence is signaled +// FALSE(0) if physical presence is not signaled +LIB_EXPORT int +_plat__PhysicalPresenceAsserted( + void + ); + +//***_plat__Signal_PhysicalPresenceOn() +// Signal physical presence on +LIB_EXPORT void +_plat__Signal_PhysicalPresenceOn( + void + ); + +//***_plat__Signal_PhysicalPresenceOff() +// Signal physical presence off +LIB_EXPORT void +_plat__Signal_PhysicalPresenceOff( + void + ); + + +//** From RunCommand.c + + + +//***_plat__RunCommand() +// This version of RunCommand will set up a jum_buf and call ExecuteCommand(). If +// the command executes without failing, it will return and RunCommand will return. +// If there is a failure in the command, then _plat__Fail() is called and it will +// longjump back to RunCommand which will call ExecuteCommand again. However, this +// time, the TPM will be in failure mode so ExecuteCommand will simply build +// a failure response and return. +LIB_EXPORT void +_plat__RunCommand( + unsigned int requestSize, // IN: command buffer size + unsigned char *request, // IN: command buffer + unsigned int *responseSize, // IN/OUT: response buffer size + unsigned char **response // IN/OUT: response buffer + ); + +//***_plat__Fail() +// This is the platform depended failure exit for the TPM. +LIB_EXPORT NORETURN void +_plat__FailDetailed( + char * file, + int line, + const char * func + ); +#define _plat__Fail() _plat__FailDetailed(__FILE__, __LINE__, __FUNCTION__) + + +//** From Unique.c + + + +//** _plat__GetUnique() +// This function is used to access the platform-specific unique value. +// This function places the unique value in the provided buffer ('b') +// and returns the number of bytes transferred. The function will not +// copy more data than 'bSize'. +// NOTE: If a platform unique value has unequal distribution of uniqueness +// and 'bSize' is smaller than the size of the unique value, the 'bSize' +// portion with the most uniqueness should be returned. +LIB_EXPORT uint32_t +_plat__GetUnique( + uint32_t which, // authorities (0) or details + uint32_t bSize, // size of the buffer + unsigned char *b // output buffer + ); + + +#endif // _PLATFORM_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/Cancel.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/Cancel.c new file mode 100644 index 0000000..fb5d7e3 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/Cancel.c @@ -0,0 +1,81 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//**Introduction +/* + This module simulates the cancel pins on the TPM. +*/ +//** Includes, Typedefs, Structures, and Defines +#include "PlatformData.h" +#include "Platform_fp.h" + +//** Functions + +//***_plat__IsCanceled() +// Check if the cancel flag is set +// return type: BOOL +// TRUE(1) if cancel flag is set +// FALSE(0) if cancel flag is not set +LIB_EXPORT int +_plat__IsCanceled( + void + ) +{ + // return cancel flag + return s_isCanceled; +} + +//***_plat__SetCancel() + +// Set cancel flag. +LIB_EXPORT void +_plat__SetCancel( + void + ) +{ + s_isCanceled = TRUE; + return; +} + +//***_plat__ClearCancel() +// Clear cancel flag +LIB_EXPORT void +_plat__ClearCancel( + void + ) +{ + s_isCanceled = FALSE; + return; +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/Clock.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/Clock.c new file mode 100644 index 0000000..e0c6b0a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/Clock.c @@ -0,0 +1,246 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//** Introduction +// This file contains the routines that are used by the simulator to mimic +// a hardware clock on a TPM. + +// In this implementation, all the time values are measured in millisecond. +// However, the precision of the clock functions may be implementation dependent. + +//** Includes and Data Definitions +#include "PlatformData.h" +#include "Platform_fp.h" +#include "TpmFail_fp.h" +#include + +//** Simulator Functions +//*** Introduction +// This set of functions is intended to be called by the simulator environment in +// order to simulate hardware events. + +//***_plat__TimerReset() +// This function sets current system clock time as t0 for counting TPM time. +// This function is called at a power on event to reset the clock. When the clock +// is reset, the indication that the clock was stopped is also set. +LIB_EXPORT void +_plat__TimerReset( + void + ) +{ + s_realTimePrevious = clock(); + s_tpmTime = 0; + s_adjustRate = CLOCK_NOMINAL; + s_timerReset = TRUE; + s_timerStopped = TRUE; + return; +} + +//*** _plat__TimerRestart() +// This function should be called in order to simulate the restart of the timer +// should it be stopped while power is still applied. +LIB_EXPORT void +_plat__TimerRestart( + void + ) +{ + s_timerStopped = TRUE; + return; +} + + +//** Functions Used by TPM +//*** Introduction +// These functions are called by the TPM code. They should be replaced by +// appropriated hardware functions. + +//***_plat__TimerRead() +// This function provides access to the tick timer of the platform. The TPM code +// uses this value to drive the TPM Clock. +// +// The tick timer is supposed to run when power is applied to the device. This timer +// should not be reset by time events including _TPM_Init. It should only be reset +// when TPM power is re-applied. +// +// If the TPM is run in a protected environment, that environment may provide the +// tick time to the TPM as long as the time provided by the environment is not +// allowed to go backwards. If the time provided by the system can go backwards +// during a power discontinuity, then the _plat__Signal_PowerOn should call +// _plat__TimerReset(). +// +// The code in this function should be replaced by a read of a hardware tick timer. +LIB_EXPORT uint64_t +_plat__TimerRead( + void + ) +{ +#ifdef HARDWARE_CLOCK +#error "need a defintion for reading the hardware clock" + return HARDWARE_CLOCK +#else +#define BILLION 1000000000 +#define MILLION 1000000 +#define THOUSAND 1000 + clock_t timeDiff; + uint64_t adjusted; + + // Save the value previously read from the system clock + timeDiff = s_realTimePrevious; + // update with the current value of the system clock + s_realTimePrevious = clock(); + // In the place below when we "put back" the unused part of the timeDiff + // it is possible that we can put back more than we take out. That is, we could + // take out 1000 mSec, rate adjust it and put back 1001 mS. This means that + // on a subsequent call, time may not have caught up. Rather than trying + // to rate adjust this, just stop time. This only occurs in a simulation so + // time for more than one command being the same should not be an issue. + if(timeDiff >= s_realTimePrevious) + { + s_realTimePrevious = timeDiff; + return s_tpmTime; + } + // Compute the amount of time since the last call to the system clock + timeDiff = s_realTimePrevious - timeDiff; + + // Do the time rate adjustment and conversion from CLOCKS_PER_SEC to mSec + adjusted = (((uint64_t)timeDiff * (THOUSAND * CLOCK_NOMINAL)) + / ((uint64_t)s_adjustRate * CLOCKS_PER_SEC)); + + s_tpmTime += (clock_t)adjusted; + + // Might have some rounding error that would loose CLOCKS. See what is not + // being used. As mentioned above, this could result in putting back more than + // is taken out + adjusted = (adjusted * ((uint64_t)s_adjustRate * CLOCKS_PER_SEC)) + / (THOUSAND * CLOCK_NOMINAL); + + // If adjusted is not the same as timeDiff, then there is some rounding + // error that needs to be pushed back into the previous sample. + // NOTE: the following is so that the fact that everything is signed will not + // matter. + s_realTimePrevious = (clock_t)((int64_t)s_realTimePrevious - adjusted); + s_realTimePrevious += timeDiff; + +#ifdef DEBUGGING_TIME + // Put this in so that TPM time will pass much faster than real time when + // doing debug. + // A value of 1000 for DEBUG_TIME_MULTIPLER will make each ms into a second + // A good value might be 100 + return (s_tpmTime * DEBUG_TIME_MULTIPLIER); +#endif + return s_tpmTime; +#endif +} + + + +//*** _plat__TimerWasReset() +// This function is used to interrogate the flag indicating if the tick timer has +// been reset. +// +// If the resetFlag parameter is SET, then the flag will be CLEAR before the +// function returns. +LIB_EXPORT BOOL +_plat__TimerWasReset( + void + ) +{ + BOOL retVal = s_timerReset; + s_timerReset = FALSE; + return retVal; +} + +//*** _plat__TimerWasStopped() +// This function is used to interrogate the flag indicating if the tick timer has +// been stopped. If so, this is typically a reason to roll the nonce. +// +// This function will CLEAR the s_timerStopped flag before returning. This provides +// functionality that is similar to status register that is cleared when read. This +// is the model used here because it is the one that has the most impact on the TPM +// code as the flag can only be accessed by one entity in the TPM. Any other +// implementation of the hardware can be made to look like a read-once register. +LIB_EXPORT BOOL +_plat__TimerWasStopped( + void + ) +{ + BOOL retVal = s_timerStopped; + s_timerStopped = FALSE; + return retVal; +} + +//***_plat__ClockAdjustRate() +// Adjust the clock rate +LIB_EXPORT void +_plat__ClockAdjustRate( + int adjust // IN: the adjust number. It could be positive + // or negative + ) +{ + // We expect the caller should only use a fixed set of constant values to + // adjust the rate + switch(adjust) + { + case CLOCK_ADJUST_COARSE: + s_adjustRate += CLOCK_ADJUST_COARSE; + break; + case -CLOCK_ADJUST_COARSE: + s_adjustRate -= CLOCK_ADJUST_COARSE; + break; + case CLOCK_ADJUST_MEDIUM: + s_adjustRate += CLOCK_ADJUST_MEDIUM; + break; + case -CLOCK_ADJUST_MEDIUM: + s_adjustRate -= CLOCK_ADJUST_MEDIUM; + break; + case CLOCK_ADJUST_FINE: + s_adjustRate += CLOCK_ADJUST_FINE; + break; + case -CLOCK_ADJUST_FINE: + s_adjustRate -= CLOCK_ADJUST_FINE; + break; + default: + // ignore any other values; + break; + } + + if(s_adjustRate > (CLOCK_NOMINAL + CLOCK_ADJUST_LIMIT)) + s_adjustRate = CLOCK_NOMINAL + CLOCK_ADJUST_LIMIT; + if(s_adjustRate < (CLOCK_NOMINAL - CLOCK_ADJUST_LIMIT)) + s_adjustRate = CLOCK_NOMINAL - CLOCK_ADJUST_LIMIT; + + return; +} + diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/Entropy.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/Entropy.c new file mode 100644 index 0000000..75c72b8 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/Entropy.c @@ -0,0 +1,104 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//** Includes +#include "stm32l4xx_hal.h" +#include +#include +#include "PlatformData.h" +#include "Platform_fp.h" + +#define MIN(a,b) ((a) < (b) ? (a) : (b)) + +extern RNG_HandleTypeDef hrng; + +//** Local values +// This is the last 32-bits of hardware entropy produced. We have to check to +// see that two consecutive 32-bit values are not the same because +// (according to FIPS 140-2, annex C +// +// 1. If each call to a RNG produces blocks of n bits (where n > 15), the first +// n-bit block generated after power-up, initialization, or reset shall not be +// used, but shall be saved for comparison with the next n-bit block to be +// generated. Each subsequent generation of an n-bit block shall be compared with +// the previously generated block. The test shall fail if any two compared n-bit +// blocks are equal. +extern uint32_t lastEntropy; + +extern int firstValue; + +//** _plat__GetEntropy() +// This function is used to get available hardware entropy. In a hardware +// implementation of this function, there would be no call to the system +// to get entropy. +// If the caller does not ask for any entropy, then this is a startup indication +// and 'firstValue' should be reset. + +// return type: int32_t +// < 0 hardware failure of the entropy generator, this is sticky +// >= 0 the returned amount of entropy (bytes) +// +LIB_EXPORT int32_t +_plat__GetEntropy( + unsigned char *entropy, // output buffer + uint32_t amount // amount requested + ) +{ + uint32_t random32bit; + + if(amount == 0) + { + firstValue = 1; + return 0; + } + + if(firstValue) + { + firstValue = 0; + } + + for(uint32_t n = 0; n < amount; n += sizeof(random32bit)) + { + if((HAL_RNG_GenerateRandomNumber(&hrng, &random32bit) != HAL_OK) || + (~firstValue && (lastEntropy == random32bit))) + { + return -1; + } + memcpy(&entropy[n], &random32bit, MIN(sizeof(random32bit), amount - n)); + lastEntropy = random32bit; + } + + return (int32_t)amount; +} diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/LocalityPlat.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/LocalityPlat.c new file mode 100644 index 0000000..a38bbb3 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/LocalityPlat.c @@ -0,0 +1,66 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//** Includes +#include "PlatformData.h" +#include "Platform_fp.h" + +//** Functions + +//***_plat__LocalityGet() +// Get the most recent command locality in locality value form. +// This is an integer value for locality and not a locality structure +// The locality can be 0-4 or 32-255. 5-31 is not allowed. +LIB_EXPORT unsigned char +_plat__LocalityGet( + void + ) +{ + return s_locality; + +} + +//***_plat__LocalitySet() +// Set the most recent command locality in locality value form +LIB_EXPORT void +_plat__LocalitySet( + unsigned char locality + ) +{ + if(locality > 4 && locality < 32) + locality = 0; + s_locality = locality; + return; +} diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/NVMem.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/NVMem.c new file mode 100644 index 0000000..28fb865 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/NVMem.c @@ -0,0 +1,558 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//**Introduction +/* + This file contains the NV read and write access methods. This implementation + uses RAM/file and does not manage the RAM/file as NV blocks. + The implementation may become more sophisticated over time. +*/ + +//** Includes +#include +#include +#include +#include +#include +#include "StmUtil.h" +#undef INLINE +#include "stm32l4xx_hal.h" +#include "PlatformData.h" +#include "Platform_fp.h" + +#define NVINTEGRITYMAGIC (0x44494E54) // TNID - TPM NV Integrity Data +typedef union +{ + struct + { + struct + { + uint32_t magic; + time_t created; + time_t lastWrite; + uint32_t writeCount; + uint8_t nvDigest[WC_SHA512_DIGEST_SIZE]; + } sig; + uint8_t nvSignature[WC_SHA512_DIGEST_SIZE]; + } s; + unsigned char b[0x800]; + unsigned int w[0x200]; +} IntegrityData_t, *pIntegrityData_t; + +__attribute__((section(".integrity"))) const IntegrityData_t nvIntegrity; +__attribute__((section(".nvfile"))) const uint8_t nvFile[NV_MEMORY_SIZE]; + +//**Functions +static BOOL NvHash2Data(uint8_t* data1, uint32_t data1Size, uint8_t* data2, uint32_t data2Size, uint8_t* digest) +{ + wc_Sha512 hash; + if(wc_InitSha512(&hash)) + { + dbgPrint("ERROR wc_InitSha512() failed.\r\n"); + return FALSE; + } + else if(data1 && (data1Size > 0) && wc_Sha512Update(&hash, data1, data1Size)) + { + dbgPrint("ERROR wc_Sha512Update() failed.\r\n"); + return FALSE; + } + else if(data2 && (data2Size > 0) && wc_Sha512Update(&hash, data2, data2Size)) + { + dbgPrint("ERROR wc_Sha512Update() failed.\r\n"); + return FALSE; + } + else if(wc_Sha512Final(&hash, (byte*)digest)) + { + dbgPrint("ERROR wc_Sha512Final failed.\r\n"); + return FALSE; + } + wc_Sha512Free(&hash); + return TRUE; +} + +static BOOL NvErasePages(void* dest, uint32_t size) +{ + BOOL result = TRUE; + uint32_t pageError = 0; + FLASH_EraseInitTypeDef eraseInfo = {FLASH_TYPEERASE_PAGES, + FLASH_BANK_1, + ((uint32_t)dest - 0x08000000) / 0x800, + (size + 0x7ff) / 0x800}; + + // Open the memory protection + for(uint32_t m = 0; m < 10; m++) + { + if((result = (HAL_FLASH_Unlock() == HAL_OK)) != FALSE) + { + break; + } + dbgPrint("WARNING HAL_FLASH_Unlock() retry %u.\r\n", (unsigned int)m); + // Bring the flash subsystem into a defined state. + HAL_FLASH_Lock(); + HAL_Delay(1); + } + if(!result) + { + dbgPrint("ERROR HAL_FLASH_Unlock() failed.\r\n"); + goto Cleanup; + } + + // Erase the necessary pages + for(uint32_t m = 0; m < 10; m++) + { + if((result = ((HAL_FLASHEx_Erase(&eraseInfo, &pageError) == HAL_OK) && (pageError == 0xffffffff)))) + { + break; + } + dbgPrint("WARNING HAL_FLASHEx_Erase() retry %u.\r\n", (unsigned int)m); + } + if(!result) + { + dbgPrint("ERROR HAL_FLASHEx_Erase() failed.\r\n"); + goto Cleanup; + } + +Cleanup: + HAL_FLASH_Lock(); + return result; +} + +static BOOL NvFlashPages(void* dest, void* src, uint32_t size) +{ + BOOL result = TRUE; + + // Parameter check + if(!(result = ((((uint32_t)src % sizeof(uint32_t)) == 0)))) + { + goto Cleanup; + } + + // Erase the required area + if(!(result = NvErasePages(dest, size))) + { + goto Cleanup; + } + + // Open the memory protection + if(!(result = (HAL_FLASH_Unlock() == HAL_OK))) + { + goto Cleanup; + } + + // Flash the src buffer 8 byte at a time and verify + for(uint32_t n = 0; n < ((size + sizeof(uint64_t) - 1) / sizeof(uint64_t)); n++) + { + result = FALSE; + for(uint32_t m = 0; m < 10; m++) + { + uint32_t progPtr = (uint32_t)&(((uint64_t*)dest)[n]); + uint64_t progData = ((uint64_t*)src)[n]; + if((progData == *((uint64_t*)progPtr)) || + ((result = (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, progPtr, progData) == HAL_OK)) && + (progData == *((uint64_t*)progPtr)))) + { + result = TRUE; + break; + } + dbgPrint("WARNING HAL_FLASH_Program() retry %u.\r\n", (unsigned int)m); + } + if(result == FALSE) + { + dbgPrint("ERROR HAL_FLASH_Program() failed.\r\n"); + goto Cleanup; + } + } + +Cleanup: + HAL_FLASH_Lock(); + return result; +} + +char* NvMakeTimeStamp(time_t time, char* nvTimeStamp, uint32_t size) +{ + struct tm* timeInfo = NULL; + timeInfo = gmtime(&time); + snprintf(nvTimeStamp, size, "%04d.%02d.%02d-%02d:%02d:%02dGMT", + timeInfo->tm_year + 1900, + timeInfo->tm_mon + 1, + timeInfo->tm_mday, + timeInfo->tm_hour, + timeInfo->tm_min, + timeInfo->tm_sec); + return nvTimeStamp; +} +//*** _plat__NvErrors() +// This function is used by the simulator to set the error flags in the NV +// subsystem to simulate an error in the NV loading process +//LIB_EXPORT void +//_plat__NvErrors( +// int recoverable, +// int unrecoverable +// ) +//{ +// s_NV_unrecoverable = unrecoverable; +// s_NV_recoverable = recoverable; +//} + +//***_plat__NVEnable() +// Enable NV memory. +// +// This version just pulls in data from a file. In a real TPM, with NV on chip, +// this function would verify the integrity of the saved context. If the NV +// memory was not on chip but was in something like RPMB, the NV state would be +// read in, decrypted and integrity checked. +// +// The recovery from an integrity failure depends on where the error occurred. It +// it was in the state that is discarded by TPM Reset, then the error is +// recoverable if the TPM is reset. Otherwise, the TPM must go into failure mode. +// return type: int +// 0 if success +// > 0 if receive recoverable error +// <0 if unrecoverable error +LIB_EXPORT int +_plat__NVEnable( + void *platParameter // IN: platform specific parameters + ) +{ + BOOL result = TRUE; + uint8_t tpmUnique[WC_SHA512_DIGEST_SIZE]; + uint8_t tpmUniqueSize = 0; + tpmUniqueSize = _plat__GetUnique(0, sizeof(tpmUnique), tpmUnique); + + // Start assuming everything is OK + s_NV_unrecoverable = FALSE; + s_NV_recoverable = FALSE; + memcpy(s_NV, nvFile, sizeof(s_NV)); + + // Perform integrity verification + if((nvIntegrity.s.sig.magic != NVINTEGRITYMAGIC) || (platParameter)) + { + // Initialize NV + IntegrityData_t newIntegrity = {0}; + + if((result = NvErasePages((uint8_t*)&nvIntegrity, sizeof(nvIntegrity))) == FALSE) + { + dbgPrint("ERROR NvErasePages(nvIntegrity) failed.\r\n"); + s_NV_unrecoverable = TRUE; + goto Cleanup; + } + if((result = NvErasePages((uint8_t*)nvFile, sizeof(nvFile))) == FALSE) + { + dbgPrint("ERROR NvErasePages(nvFile) failed.\r\n"); + s_NV_unrecoverable = TRUE; + goto Cleanup; + } + + newIntegrity.s.sig.magic = NVINTEGRITYMAGIC; + newIntegrity.s.sig.created = time(NULL); + if((result = NvHash2Data((uint8_t*)nvFile, sizeof(nvFile), NULL, 0, newIntegrity.s.sig.nvDigest)) == FALSE) + { + dbgPrint("WARNING NvHash2Data(nvFile) failed.\r\n"); + s_NV_unrecoverable = TRUE; + goto Cleanup; + } + if((result = NvHash2Data(tpmUnique, tpmUniqueSize, (uint8_t*)&newIntegrity.s.sig, sizeof(newIntegrity.s.sig), newIntegrity.s.nvSignature)) == FALSE) + { + dbgPrint("WARNING NvHash2Data(tpmUnique, newIntegrity) failed.\r\n"); + s_NV_unrecoverable = TRUE; + goto Cleanup; + } + if((result = NvFlashPages((uint8_t*)&nvIntegrity, (uint8_t*)&newIntegrity, sizeof(newIntegrity))) == FALSE) + { + dbgPrint("ERROR NvFlashPages(nvIntegrity) failed.\r\n"); + s_NV_unrecoverable = TRUE; + goto Cleanup; + } + dbgPrint("Initialized %dkb NVFile.\r\n", sizeof(nvFile)/1024); + memcpy(s_NV, nvFile, sizeof(s_NV)); + s_NV_recoverable = TRUE; + } + else + { + uint8_t nvDigest[WC_SHA512_DIGEST_SIZE]; + if((result = NvHash2Data(tpmUnique, tpmUniqueSize, (uint8_t*)&nvIntegrity.s.sig, sizeof(nvIntegrity.s.sig), nvDigest)) == FALSE) + { + dbgPrint("WARNING NvHash2Data(tpmUnique, nvIntegrity) failed.\r\n"); + s_NV_unrecoverable = TRUE; + goto Cleanup; + } + if(memcmp(nvDigest, nvIntegrity.s.nvSignature, sizeof(nvDigest))) + { + dbgPrint("WARNING NV signature invalid.\r\n"); + s_NV_unrecoverable = TRUE; + goto Cleanup; + } + if((result = NvHash2Data((uint8_t*)nvFile, sizeof(nvFile), NULL, 0, nvDigest)) == FALSE) + { + dbgPrint("WARNING NvHash2Data(nvFile) filed.\r\n"); + s_NV_unrecoverable = TRUE; + goto Cleanup; + } + if(memcmp(nvDigest, nvIntegrity.s.sig.nvDigest, sizeof(nvDigest))) + { + dbgPrint("WARNING NV integrity measurement invalid.\r\n"); + s_NV_unrecoverable = TRUE; + goto Cleanup; + } + } + char created[50]; + char written[50]; + dbgPrint("NVFile loaded (%dkb, %s created, %d writes, %s last)\r\n", + sizeof(nvFile)/1024, + NvMakeTimeStamp(nvIntegrity.s.sig.created, created, sizeof(created)), + (int)nvIntegrity.s.sig.writeCount, + (nvIntegrity.s.sig.lastWrite) ? NvMakeTimeStamp(nvIntegrity.s.sig.lastWrite, written, sizeof(written)) : "NEVER"); + +Cleanup: + HAL_FLASH_Lock(); + if(s_NV_unrecoverable) + return -1; + return s_NV_recoverable; +} + +//***_plat__NVDisable() +// Disable NV memory +LIB_EXPORT void +_plat__NVDisable( + void + ) +{ + return; +} + +//***_plat__IsNvAvailable() +// Check if NV is available +// return type: int +// 0 NV is available +// 1 NV is not available due to write failure +// 2 NV is not available due to rate limit +LIB_EXPORT int +_plat__IsNvAvailable( + void + ) +{ + // NV is not available if the TPM is in failure mode + if(!s_NvIsAvailable) + return 1; + + return 0; +} + +//***_plat__NvMemoryRead() +// Function: Read a chunk of NV memory +LIB_EXPORT void +_plat__NvMemoryRead( + unsigned int startOffset, // IN: read start + unsigned int size, // IN: size of bytes to read + void *data // OUT: data buffer + ) +{ + assert(startOffset + size <= NV_MEMORY_SIZE); + + // Copy data from RAM + memcpy(data, &s_NV[startOffset], size); + return; +} + +//*** _plat__NvIsDifferent() +// This function checks to see if the NV is different from the test value. This is +// so that NV will not be written if it has not changed. +// return value: int +// TRUE(1) the NV location is different from the test value +// FALSE(0) the NV location is the same as the test value +LIB_EXPORT int +_plat__NvIsDifferent( + unsigned int startOffset, // IN: read start + unsigned int size, // IN: size of bytes to read + void *data // IN: data buffer + ) +{ + return (memcmp(&s_NV[startOffset], data, size) != 0); +} + +//***_plat__NvMemoryWrite() +// This function is used to update NV memory. The "write" is to a memory copy of +// NV. At the end of the current command, any changes are written to +// the actual NV memory. +// NOTE: A useful optimization would be for this code to compare the current +// contents of NV with the local copy and note the blocks that have changed. Then +// only write those blocks when _plat__NvCommit() is called. +LIB_EXPORT void +_plat__NvMemoryWrite( + unsigned int startOffset, // IN: write start + unsigned int size, // IN: size of bytes to write + void *data // OUT: data buffer + ) +{ + assert(startOffset + size <= NV_MEMORY_SIZE); + + // Copy the data to the NV image + memcpy(&s_NV[startOffset], data, size); +} + +//***_plat__NvMemoryClear() +// Function is used to set a range of NV memory bytes to an implementation-dependent +// value. The value represents the erase state of the memory. +LIB_EXPORT void +_plat__NvMemoryClear( + unsigned int start, // IN: clear start + unsigned int size // IN: number of bytes to clear + ) +{ + assert(start + size <= NV_MEMORY_SIZE); + + // In this implementation, assume that the errase value for NV is all 1s + memset(&s_NV[start], 0xff, size); +} + +//***_plat__NvMemoryMove() +// Function: Move a chunk of NV memory from source to destination +// This function should ensure that if there overlap, the original data is +// copied before it is written +LIB_EXPORT void +_plat__NvMemoryMove( + unsigned int sourceOffset, // IN: source offset + unsigned int destOffset, // IN: destination offset + unsigned int size // IN: size of data being moved + ) +{ + assert(sourceOffset + size <= NV_MEMORY_SIZE); + assert(destOffset + size <= NV_MEMORY_SIZE); + + // Move data in RAM + memmove(&s_NV[destOffset], &s_NV[sourceOffset], size); + + return; +} + +//***_plat__NvCommit() +// Update NV chip +// return type: int +// 0 NV write success +// non-0 NV write fail +LIB_EXPORT int +_plat__NvCommit( + void + ) +{ + BOOL result = TRUE; + char created[50]; + char written[50]; + IntegrityData_t newIntegrity = {0}; + uint8_t tpmUnique[WC_SHA512_DIGEST_SIZE]; + uint8_t tpmUniqueSize = 0; + + tpmUniqueSize = _plat__GetUnique(0, sizeof(tpmUnique), tpmUnique); + memcpy(&newIntegrity, &nvIntegrity, sizeof(newIntegrity)); + + if((result = NvHash2Data(s_NV, sizeof(s_NV), NULL, 0, newIntegrity.s.sig.nvDigest)) == FALSE) + { + dbgPrint("WARNING NvHash2Data(s_NV) failed.\r\n"); + result = FALSE; + goto Cleanup; + } + if((result = NvHash2Data(tpmUnique, tpmUniqueSize, (uint8_t*)&nvIntegrity.s.sig, sizeof(nvIntegrity.s.sig), newIntegrity.s.nvSignature)) == FALSE) + { + dbgPrint("WARNING NvHash2Data(tpmUnique, nvIntegrity) failed.\r\n"); + result = FALSE; + goto Cleanup; + } + + if((memcmp(newIntegrity.s.sig.nvDigest, nvIntegrity.s.sig.nvDigest, sizeof(newIntegrity.s.sig.nvDigest))) || + (memcmp(newIntegrity.s.nvSignature, nvIntegrity.s.nvSignature, sizeof(newIntegrity.s.nvSignature)))) + { + newIntegrity.s.sig.lastWrite = time(NULL); + newIntegrity.s.sig.writeCount++; + if((result = NvHash2Data(tpmUnique, tpmUniqueSize, (uint8_t*)&newIntegrity.s.sig, sizeof(newIntegrity.s.sig), newIntegrity.s.nvSignature)) == FALSE) + { + dbgPrint("WARNING NvHash2Data(tpmUnique, newIntegrity) failed.\r\n"); + result = FALSE; + goto Cleanup; + } + if((result = NvFlashPages((uint8_t*)nvFile, s_NV, sizeof(s_NV))) == FALSE) + { + dbgPrint("ERROR NvFlashPages(nvFile) failed.\r\n"); + result = FALSE; + goto Cleanup; + } + if((result = NvFlashPages((uint8_t*)&nvIntegrity, (uint8_t*)&newIntegrity, sizeof(newIntegrity))) == FALSE) + { + dbgPrint("ERROR NvFlashPages(nvIntegrity) failed.\r\n"); + result = FALSE; + goto Cleanup; + } + dbgPrint("NVFile written (%dkb, %s created, %d writes, %s last)\r\n", + sizeof(nvFile)/1024, + NvMakeTimeStamp(nvIntegrity.s.sig.created, created, sizeof(created)), + (int)nvIntegrity.s.sig.writeCount, + (nvIntegrity.s.sig.lastWrite) ? NvMakeTimeStamp(nvIntegrity.s.sig.lastWrite, written, sizeof(written)) : "NEVER"); + } + else + { + dbgPrint("NVFile unchanged (%dkb, %s created, %d writes, %s last)\r\n", + sizeof(nvFile)/1024, + NvMakeTimeStamp(nvIntegrity.s.sig.created, created, sizeof(created)), + (int)nvIntegrity.s.sig.writeCount, + (nvIntegrity.s.sig.lastWrite) ? NvMakeTimeStamp(nvIntegrity.s.sig.lastWrite, written, sizeof(written)) : "NEVER"); + } + + +Cleanup: + return (result != TRUE); +} + +//***_plat__SetNvAvail() +// Set the current NV state to available. This function is for testing purpose +// only. It is not part of the platform NV logic +LIB_EXPORT void +_plat__SetNvAvail( + void + ) +{ + s_NvIsAvailable = TRUE; + return; +} + +//***_plat__ClearNvAvail() +// Set the current NV state to unavailable. This function is for testing purpose +// only. It is not part of the platform NV logic +LIB_EXPORT void +_plat__ClearNvAvail( + void + ) +{ + s_NvIsAvailable = FALSE; + return; +} diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/PPPlat.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/PPPlat.c new file mode 100644 index 0000000..8e0b8a8 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/PPPlat.c @@ -0,0 +1,81 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//** Description + +// This module simulates the physical present interface pins on the TPM. + +//** Includes +#include "PlatformData.h" +#include "Platform_fp.h" + +//** Functions + +//***_plat__PhysicalPresenceAsserted() +// Check if physical presence is signaled +// return type: int +// TRUE(1) if physical presence is signaled +// FALSE(0) if physical presence is not signaled +LIB_EXPORT int +_plat__PhysicalPresenceAsserted( + void + ) +{ + // Do not know how to check physical presence without real hardware. + // so always return TRUE; + return s_physicalPresence; +} + +//***_plat__Signal_PhysicalPresenceOn() +// Signal physical presence on +LIB_EXPORT void +_plat__Signal_PhysicalPresenceOn( + void + ) +{ + s_physicalPresence = TRUE; + return; +} + +//***_plat__Signal_PhysicalPresenceOff() +// Signal physical presence off +LIB_EXPORT void +_plat__Signal_PhysicalPresenceOff( + void + ) +{ + s_physicalPresence = FALSE; + return; +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/PlatformData.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/PlatformData.c new file mode 100644 index 0000000..e6092e6 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/PlatformData.c @@ -0,0 +1,76 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//** Description +// This file will instance the TPM variables that are not stack allocated. The +// descriptions for these variables are in Global.h for this project. + +//** Includes +#include "Implementation.h" +#include "PlatformData.h" + +// From Cancel.c +BOOL s_isCanceled; + +// From Clock.c +unsigned int s_adjustRate; +BOOL s_timerReset; +BOOL s_timerStopped; + +#ifndef HARDWARE_CLOCK +#include +clock_t s_realTimePrevious; +clock_t s_tpmTime; +#endif + + +// From LocalityPlat.c +unsigned char s_locality; + +// From Power.c +BOOL s_powerLost; + +// From Entropy.c +uint32_t lastEntropy; +int firstValue; + +// From NVMem.c +unsigned char s_NV[NV_MEMORY_SIZE]; +BOOL s_NvIsAvailable; +BOOL s_NV_unrecoverable; +BOOL s_NV_recoverable; + +// From PPPlat.c +BOOL s_physicalPresence; diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/PowerPlat.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/PowerPlat.c new file mode 100644 index 0000000..8d250cd --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/PowerPlat.c @@ -0,0 +1,114 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//** Includes and Function Prototypes + +#include "PlatformData.h" +#include "Platform_fp.h" +#include "_TPM_Init_fp.h" + +//** Functions + +//***_plat__Signal_PowerOn() +// Signal platform power on +LIB_EXPORT int +_plat__Signal_PowerOn( + void + ) +{ + // Reset the timer + _plat__TimerReset(); + + // Need to indicate that we lost power + s_powerLost = TRUE; + + return 0; +} + +//*** _plat__WasPowerLost() +// Test whether power was lost before a _TPM_Init. +// +// This function will clear the "hardware" indication of power loss before return. +// This means that there can only be one spot in the TPM code where this value +// gets read. This method is used here as it is the most difficult to manage in the +// TPM code and, if the hardware actually works this way, it is hard to make it +// look like anything else. So, the burden is placed on the TPM code rather than the +// platform code +// return type: int +// TRUE(1) power was lost +// FALSE(0) power was not lost +LIB_EXPORT int +_plat__WasPowerLost( + void + ) +{ + BOOL retVal = s_powerLost; + s_powerLost = FALSE; + return retVal; +} + +//*** _plat_Signal_Reset() +// This a TPM reset without a power loss. +LIB_EXPORT int +_plat__Signal_Reset( + void + ) +{ + // Initialize locality + s_locality = 0; + + // Command cancel + s_isCanceled = FALSE; + + _TPM_Init(); + + // if we are doing reset but did not have a power failure, then we should + // not need to reload NV ... + + return 0; +} + +//***_plat__Signal_PowerOff() +// Signal platform power off +LIB_EXPORT void +_plat__Signal_PowerOff( + void + ) +{ + // Prepare NV memory for power off + _plat__NVDisable(); + + return; +} diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/RunCommand.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/RunCommand.c new file mode 100644 index 0000000..aa97235 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/RunCommand.c @@ -0,0 +1,91 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//**Introduction +// This module provides the platform specific entry and fail processing. The +// _plat__RunCommand() function is used to call to ExecuteCommand() in the TPM code. +// This function does whatever processing is necessary to set up the platform +// in anticipation of the call to the TPM including settup for error processing. +// +// The _plat__Fail() function is called when there is a failure in the TPM. The TPM +// code will have set the flag to indicate that the TPM is in failure mode. +// This call will then recursively call ExecuteCommand in order to build the +// failure mode response. When ExecuteCommand() returns to _plat__Fail(), the +// platform will do some platform specif operation to return to the environment in +// which the TPM is executing. For a simulator, setjmp/longjmp is used. For an OS, +// a system exit to the OS would be appropriate. + +//** Includes and locals +#include "PlatformData.h" +#include "Platform_fp.h" +#include +#include "ExecCommand_fp.h" +#include "StmUtil.h" + +jmp_buf s_jumpBuffer; + +//** Functions + +//***_plat__RunCommand() +// This version of RunCommand will set up a jum_buf and call ExecuteCommand(). If +// the command executes without failing, it will return and RunCommand will return. +// If there is a failure in the command, then _plat__Fail() is called and it will +// longjump back to RunCommand which will call ExecuteCommand again. However, this +// time, the TPM will be in failure mode so ExecuteCommand will simply build +// a failure response and return. +LIB_EXPORT void +_plat__RunCommand( + unsigned int requestSize, // IN: command buffer size + unsigned char *request, // IN: command buffer + unsigned int *responseSize, // IN/OUT: response buffer size + unsigned char **response // IN/OUT: response buffer + ) +{ + setjmp(s_jumpBuffer); + ExecuteCommand((uint32_t)requestSize, request, (uint32_t*)responseSize, response); +} + +//***_plat__Fail() +// This is the platform depended failure exit for the TPM. +LIB_EXPORT NORETURN void +_plat__FailDetailed( + char * file, + int line, + const char * func + ) +{ + dbgPrint("TPMFAIL: %s (%s@%d)\r\n", func, file, line); + longjmp(&s_jumpBuffer[0], 1); +} diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/Unique.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/Unique.c new file mode 100644 index 0000000..0e3b88d --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/Platform/src/Unique.c @@ -0,0 +1,85 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//** Introduction +// In some implementations of the TPM, the hardware can provide a secret +// value to the TPM. This secret value is statistically unique to the +// instance of the TPM. Typical uses of this value are to provide +// personalization to the random number generation and as a shared secret +// between the TPM and the manufacturer. + +//** Includes +#include "PlatformData.h" +#include "Platform_fp.h" +#include + +char tpmUnique[WC_SHA512_DIGEST_SIZE] = {0}; + +//** _plat__GetUnique() +// This function is used to access the platform-specific unique value. +// This function places the unique value in the provided buffer ('b') +// and returns the number of bytes transferred. The function will not +// copy more data than 'bSize'. +// NOTE: If a platform unique value has unequal distribution of uniqueness +// and 'bSize' is smaller than the size of the unique value, the 'bSize' +// portion with the most uniqueness should be returned. +LIB_EXPORT uint32_t +_plat__GetUnique( + uint32_t which, // authorities (0) or details + uint32_t bSize, // size of the buffer + unsigned char *b // output buffer + ) +{ + const char *from = tpmUnique; + uint32_t retVal = 0; + + if(which == 0) // the authorities value + { + for(retVal = 0; retVal < bSize; retVal++) + { + *b++ = *from++; + } + } + else + { +#define uSize sizeof(tpmUnique) + b = &b[((bSize < uSize) ? bSize : uSize) - 1]; + for(retVal = 0; retVal < bSize; retVal++) + { + *b-- = *from++; + } + } + return retVal; +} diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/TPMDevice/include/StmUtil.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/TPMDevice/include/StmUtil.h new file mode 100644 index 0000000..6a5735e --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/TPMDevice/include/StmUtil.h @@ -0,0 +1,35 @@ +#include + +#define ITMSTDERR (0) +#define ITMSIGNAL (1) +#define ITMCMDRSP (2) +#define ITMCHANNELS (3) +#ifndef NDEBUG +#define dbgPrint(fmt, ...) fprintf(stderr, "%s: " fmt, GetLogStamp(), ##__VA_ARGS__); +#define dbgPrintAppend(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__); +#define itmPrint(__channel, fmt, ...) fprintf(g_itm[__channel], "%s: " fmt, GetLogStamp(), ##__VA_ARGS__); +#define itmPrintAppend(__channel, fmt, ...) fprintf(g_itm[__channel], fmt, ##__VA_ARGS__); +#else +#define dbgPrint(fmt, ...) ((void)0) +#define dbgPrintAppend(fmt, ...) ((void)0) +#define itmPrintAppend(__channel, fmt, ...) ((void)0) +#define itmPrint(__channel, fmt, ...) ((void)0) +#endif +#define logError(fmt, ...) dbgPrint("[ERROR] %s (%s@%u) - " fmt, __func__, __FILE__, __LINE__, ##__VA_ARGS__); +#define logWarning(fmt, ...) dbgPrint("[WARNING] %s (%s@%u) - " fmt, __func__, __FILE__, __LINE__, ##__VA_ARGS__); +#define logInfo(fmt, ...) dbgPrint("[Info] %s (%s@%u) - " fmt, __func__, __FILE__, __LINE__, ##__VA_ARGS__); +extern char logStampStr[40]; +extern void* g_itm[ITMCHANNELS]; + +#define ITMFILENO (4) +#define ITMCHANNELNO (32) +void ITM_Out(uint32_t port, uint8_t ch); + +char* GetLogStamp(void); +int BlueButtonTransitionDetected(void); +void SetDutyCycleIndicator(bool on); +void KillUSBLink(void); +void SetRealTimeClock(time_t tm); +void ReadMcuInfo(unsigned char* serial, uint16_t *flashSize, uint16_t *mcuType, uint16_t *mcuRev); +void PerformSystemReset(void); +void InitializeITM(); diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/TPMDevice/include/TpmDevice.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/TPMDevice/include/TpmDevice.h new file mode 100644 index 0000000..e683570 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/TPMDevice/include/TpmDevice.h @@ -0,0 +1,78 @@ +#define SIGNALMAGIC (0x326d7054) //Tpm2 +#define MAX_TPM_MESSAGE_SIZE (sizeof(unsigned int) + 2048) + +typedef enum +{ + SignalNothing = 0, + SignalShutdown, + SignalReset, + SignalSetClock, + // IN {UINT32 time} + SignalCancelOn, + SignalCancelOff, + SignalCommand, + // IN {BYTE Locality, UINT32 InBufferSize, BYTE[InBufferSize] InBuffer} + // OUT {UINT32 OutBufferSize, BYTE[OutBufferSize] OutBuffer} + SignalResponse, + // OUT {UINT32 OutBufferSize, BYTE[OutBufferSize] OutBuffer} +} signalCode_t; + +typedef struct +{ + unsigned int magic; + signalCode_t signal; + unsigned int dataSize; +} signalHdr_t; + +typedef union +{ + struct + { + unsigned int time; + } SignalSetClockPayload; + struct + { + unsigned int locality; + unsigned int cmdSize; + unsigned char cmd[1]; + } SignalCommandPayload; +} signalPayload_t, *pSignalPayload_t; + +typedef union +{ + signalHdr_t s; + unsigned char b[sizeof(signalHdr_t)]; +} signalWrapper_t, *pSignalWrapper_t; + +typedef struct tpmOperationsFlags_t +{ + unsigned char resetRequested : 1; + unsigned char powerOffRequested : 1; + unsigned char executionRequested : 1; + unsigned char responseRequested : 1; +} tpmOperationsFlags_t; + +typedef struct tpmOperation_t +{ + tpmOperationsFlags_t flags; + int cmdSize; + int receivingCmd; + int rspSize; + unsigned char msgBuf[MAX_TPM_MESSAGE_SIZE]; +} tpmOperation_t; + +extern volatile tpmOperation_t tpmOp; + +int BlueButtonTransitionDetected(void); +void SetDutyCycleIndicator(bool on); +void KillUSBLink(void); +void SetRealTimeClock(time_t tm); +void ReadMcuInfo(unsigned char* serial, uint16_t *flashSize, uint16_t *mcuType, uint16_t *mcuRev); +void PerformSystemReset(void); +void HAL_Delay(uint32_t Delay); +uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len); + +bool TpmInitializeDevice(void); +bool TpmOperationsLoop(void); +void TpmConnectionReset(void); +bool TpmSignalEvent(uint8_t* Buf, uint32_t *Len); diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/TPMDevice/include/user_settings.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/TPMDevice/include/user_settings.h new file mode 100644 index 0000000..a4d7e9c --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/TPMDevice/include/user_settings.h @@ -0,0 +1,54 @@ +/* settings.h + * + * Copyright (C) 2006-2017 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL 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. + * + * wolfSSL 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-1335, USA + */ + + +/* Place OS specific preprocessor flags, defines, includes here, will be + included into every file because types.h includes it */ + + +#ifndef WOLF_CRYPT_USER_SETTINGS_H +#define WOLF_CRYPT_USER_SETTINGS_H + +#ifdef __cplusplus + extern "C" { +#endif + +#define SINGLE_THREADED +#define NO_FILESYSTEM +#define NO_OLD_WC_NAMES +#define WC_NO_HARDEN +#define WOLFSSL_SHA384 +#define WOLFSSL_SHA512 +#define WOLFSSL_AES_DIRECT +#define WOLFSSL_DES_ECB +#define WOLFSSL_KEY_GEN +#define HAVE_ECC +#define ECC_SHAMIR +#define USE_FAST_MATH +#define WOLFSSL_PUBLIC_ECC_ADD_DBL +#define LIBRARY_COMPATIBILITY_CHECK +#define WOLFSSL_USER_IO + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/TPMDevice/src/StmUtil.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/TPMDevice/src/StmUtil.c new file mode 100644 index 0000000..5d2889e --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/TPMDevice/src/StmUtil.c @@ -0,0 +1,141 @@ +#include +#include +#include +#include +#include "stm32l4xx_hal.h" +#include "usb_device.h" +#include "StmUtil.h" + +// RTC initialized by MX_RTC_Init +extern RTC_HandleTypeDef hrtc; + +typedef unsigned char DEVICE_UNIQUE_ID_T[12]; +#define DEVICE_UNIQUE_ID (*(DEVICE_UNIQUE_ID_T*)(UID_BASE)) +#define DEVICE_FLASH_SIZE (*(uint16_t *)(FLASHSIZE_BASE)) +#define DEVICE_TYPE ((uint16_t) ((DBGMCU->IDCODE & DBGMCU_IDCODE_DEV_ID_Msk) >> DBGMCU_IDCODE_DEV_ID_Pos)) +#define DEVICE_REV ((uint16_t) ((DBGMCU->IDCODE & DBGMCU_IDCODE_REV_ID_Msk) >> DBGMCU_IDCODE_REV_ID_Pos)) +char __attribute__((section (".ram2"))) logStampStr[40] = {0}; +void* __attribute__((section (".ram2"))) g_itm[ITMCHANNELS] = {0}; + +GPIO_PinState BlueButtonLast = GPIO_PIN_SET; +int BlueButtonTransitionDetected(void) +{ + GPIO_PinState PPButton = HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin); + if((PPButton == GPIO_PIN_RESET) && (BlueButtonLast == GPIO_PIN_SET)) + { + // Now pressed + BlueButtonLast = PPButton; + return 1; + } + else if((PPButton == GPIO_PIN_SET) && (BlueButtonLast == GPIO_PIN_RESET)) + { + // Now released + BlueButtonLast = PPButton; + return -1; + } + // No change + return 0; +} + +#ifndef NDEBUG +#define ITM_PORT_BITS (0xffffffff) +void InitializeITM() +{ +// CoreDebug->DEMCR = CoreDebug_DEMCR_TRCENA_Msk; /* enable trace in core debug */ +// ITM->TCR = ITM_TCR_TraceBusID_Msk | ITM_TCR_SWOENA_Msk | ITM_TCR_SYNCENA_Msk | ITM_TCR_ITMENA_Msk; /* ITM Trace Control Register */ +// ITM->TPR = ITM_TPR_PRIVMASK_Msk; /* ITM Trace Privilege Register */ +// ITM->TER = ITM_PORT_BITS; /* ITM Trace Enable Register. Enabled tracing on stimulus ports. One bit per stimulus port. */ +// *((volatile unsigned *)(ITM_BASE + 0x01000)) = 0x400003FE; /* DWT_CTRL */ +// *((volatile unsigned *)(ITM_BASE + 0x40304)) = 0x00000100; /* Formatter and Flush Control Register */ + + for(uint32_t n = 0; n < ITMCHANNELS; n++) + { + char fileName[10]; + sprintf(fileName, "ITM[%02u]", (unsigned int)n); + g_itm[n] = (void*)fopen(fileName, "wb"); + } +} + +void ITM_Out(uint32_t port, uint8_t ch) +{ + while(ITM->PORT[port].u32 == 0); + ITM->PORT[port].u8 = ch; +} +#else +void InitializeITM() +{ + +} +#endif + +void SetDutyCycleIndicator(bool on) +{ + HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, on ? GPIO_PIN_SET : GPIO_PIN_RESET); +} + +char* GetLogStamp(void) +{ + RTC_TimeTypeDef time = {0}; + RTC_DateTypeDef date = {0}; + HAL_RTC_GetTime(&hrtc, &time, RTC_FORMAT_BIN); + HAL_RTC_GetDate(&hrtc, &date, RTC_FORMAT_BIN); + + sprintf(logStampStr, "%04d.%02d.%02d-%02d:%02d:%02d.%03dGMT", + date.Year + 2000, + date.Month, + date.Date, + time.Hours, + time.Minutes, + time.Seconds, + (int)((1000 / time.SecondFraction) * (time.SecondFraction - time.SubSeconds))); + return logStampStr; +} + +void KillUSBLink(void) +{ + dbgPrint("USB de-initialization...\r\n"); + MX_USB_DEVICE_DeInit(); +} + +void SetRealTimeClock(time_t tm) +{ + struct tm* local = localtime((time_t*)&tm); + RTC_TimeTypeDef time = {0}; + RTC_DateTypeDef date = {0}; + date.Year = local->tm_year - 100; + date.Month = local->tm_mon + 1; + date.Date = local->tm_mday; + date.WeekDay = local->tm_wday + 1; + time.Hours = local->tm_hour; + time.Minutes = local->tm_min; + time.Seconds = local->tm_sec; + HAL_RTC_SetTime(&hrtc, &time, RTC_FORMAT_BIN); + HAL_RTC_SetDate(&hrtc, &date, RTC_FORMAT_BIN); +} + +void ReadMcuInfo(unsigned char* serial, uint16_t *flashSize, uint16_t *mcuType, uint16_t *mcuRev) +{ + if(serial) + { + memcpy(serial, DEVICE_UNIQUE_ID, sizeof(DEVICE_UNIQUE_ID)); + } + if(flashSize) + { + *flashSize = DEVICE_FLASH_SIZE; + } + if(mcuType) + { + *mcuType = DEVICE_TYPE; + } + if(mcuRev) + { + *mcuRev = DEVICE_REV; + } +} + +void PerformSystemReset(void) +{ + dbgPrint("Executing NVIC_SystemReset()...\r\n"); + HAL_Delay(1); + NVIC_SystemReset(); +} diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/TPMDevice/src/TpmDevice.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/TPMDevice/src/TpmDevice.c new file mode 100644 index 0000000..07b1aa8 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/TPMDevice/src/TpmDevice.c @@ -0,0 +1,964 @@ +#include +#include +#include +#include +#include "StmUtil.h" +#include +#undef INLINE +#include "Tpm.h" +#include "TpmDevice.h" + +volatile tpmOperation_t tpmOp = { 0 }; +extern char tpmUnique[WC_SHA512_DIGEST_SIZE]; + +uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len); + +#ifndef NDEBUG +#define TPM_RC_MAX_FM1 (TPM_RC)(RC_FMT1 + 0x03F) + +typedef struct +{ + uint32_t index; + char* str; +} lookup_t; + +const lookup_t tpm_cc_table[] = +{ +#if CC_NV_UndefineSpaceSpecial == YES + {TPM_CC_NV_UndefineSpaceSpecial, "TPM_CC_NV_UndefineSpaceSpecial"}, +#endif +#if CC_EvictControl == YES + {TPM_CC_EvictControl, "TPM_CC_EvictControl"}, +#endif +#if CC_HierarchyControl == YES + {TPM_CC_HierarchyControl, "TPM_CC_HierarchyControl"}, +#endif +#if CC_NV_UndefineSpace == YES + {TPM_CC_NV_UndefineSpace, "TPM_CC_NV_UndefineSpace"}, +#endif +#if CC_ChangeEPS == YES + {TPM_CC_ChangeEPS, "TPM_CC_ChangeEPS"}, +#endif +#if CC_ChangePPS == YES + {TPM_CC_ChangePPS, "TPM_CC_ChangePPS"}, +#endif +#if CC_Clear == YES + {TPM_CC_Clear, "TPM_CC_Clear"}, +#endif +#if CC_ClearControl == YES + {TPM_CC_ClearControl, "TPM_CC_ClearControl"}, +#endif +#if CC_ClockSet == YES + {TPM_CC_ClockSet, "TPM_CC_ClockSet"}, +#endif +#if CC_HierarchyChangeAuth == YES + {TPM_CC_HierarchyChangeAuth, "TPM_CC_HierarchyChangeAuth"}, +#endif +#if CC_NV_DefineSpace == YES + {TPM_CC_NV_DefineSpace, "TPM_CC_NV_DefineSpace"}, +#endif +#if CC_PCR_Allocate == YES + {TPM_CC_PCR_Allocate, "TPM_CC_PCR_Allocate"}, +#endif +#if CC_PCR_SetAuthPolicy == YES + {TPM_CC_PCR_SetAuthPolicy, "TPM_CC_PCR_SetAuthPolicy"}, +#endif +#if CC_PP_Commands == YES + {TPM_CC_PP_Commands, "TPM_CC_PP_Commands"}, +#endif +#if CC_SetPrimaryPolicy == YES + {TPM_CC_SetPrimaryPolicy, "TPM_CC_SetPrimaryPolicy"}, +#endif +#if CC_FieldUpgradeStart == YES + {TPM_CC_FieldUpgradeStart, "TPM_CC_FieldUpgradeStart"}, +#endif +#if CC_ClockRateAdjust == YES + {TPM_CC_ClockRateAdjust, "TPM_CC_ClockRateAdjust"}, +#endif +#if CC_CreatePrimary == YES + {TPM_CC_CreatePrimary, "TPM_CC_CreatePrimary"}, +#endif +#if CC_NV_GlobalWriteLock == YES + {TPM_CC_NV_GlobalWriteLock, "TPM_CC_NV_GlobalWriteLock"}, +#endif +#if CC_GetCommandAuditDigest == YES + {TPM_CC_GetCommandAuditDigest, ""}, +#endif +#if CC_NV_Increment == YES + {TPM_CC_NV_Increment, "TPM_CC_NV_Increment"}, +#endif +#if CC_NV_SetBits == YES + {TPM_CC_NV_SetBits, "TPM_CC_NV_SetBits"}, +#endif +#if CC_NV_Extend == YES + {TPM_CC_NV_Extend, "TPM_CC_NV_Extend"}, +#endif +#if CC_NV_Write == YES + {TPM_CC_NV_Write, "TPM_CC_NV_Write"}, +#endif +#if CC_NV_WriteLock == YES + {TPM_CC_NV_WriteLock, "TPM_CC_NV_WriteLock"}, +#endif +#if CC_DictionaryAttackLockReset == YES + {TPM_CC_DictionaryAttackLockReset, "TPM_CC_DictionaryAttackLockReset"}, +#endif +#if CC_DictionaryAttackParameters == YES + {TPM_CC_DictionaryAttackParameters, "TPM_CC_DictionaryAttackParameters"}, +#endif +#if CC_NV_ChangeAuth == YES + {TPM_CC_NV_ChangeAuth, "TPM_CC_NV_ChangeAuth"}, +#endif +#if CC_PCR_Event == YES + {TPM_CC_PCR_Event, "TPM_CC_PCR_Event"}, +#endif +#if CC_PCR_Reset == YES + {TPM_CC_PCR_Reset, "TPM_CC_PCR_Reset"}, +#endif +#if CC_SequenceComplete == YES + {TPM_CC_SequenceComplete, "TPM_CC_SequenceComplete"}, +#endif +#if CC_SetAlgorithmSet == YES + {TPM_CC_SetAlgorithmSet, "TPM_CC_SetAlgorithmSet"}, +#endif +#if CC_SetCommandCodeAuditStatus == YES + {TPM_CC_SetCommandCodeAuditStatus, "TPM_CC_SetCommandCodeAuditStatus"}, +#endif +#if CC_FieldUpgradeData == YES + {TPM_CC_FieldUpgradeData, "TPM_CC_FieldUpgradeData"}, +#endif +#if CC_IncrementalSelfTest == YES + {TPM_CC_IncrementalSelfTest, "TPM_CC_FieldUpgradeData"}, +#endif +#if CC_SelfTest == YES + {TPM_CC_SelfTest, "TPM_CC_SelfTest"}, +#endif +#if CC_Startup == YES + {TPM_CC_Startup, "TPM_CC_Startup"}, +#endif +#if CC_Shutdown == YES + {TPM_CC_Shutdown, "TPM_CC_Shutdown"}, +#endif +#if CC_StirRandom == YES + {TPM_CC_StirRandom, ""}, +#endif +#if CC_ActivateCredential == YES + {TPM_CC_ActivateCredential, "TPM_CC_ActivateCredential"}, +#endif +#if CC_Certify == YES + {TPM_CC_Certify, "TPM_CC_Certify"}, +#endif +#if CC_PolicyNV == YES + {TPM_CC_PolicyNV, "TPM_CC_PolicyNV"}, +#endif +#if CC_CertifyCreation == YES + {TPM_CC_CertifyCreation, "TPM_CC_CertifyCreation"}, +#endif +#if CC_Duplicate == YES + {TPM_CC_Duplicate, "TPM_CC_Duplicate"}, +#endif +#if CC_GetTime == YES + {TPM_CC_GetTime, "TPM_CC_GetTime"}, +#endif +#if CC_GetSessionAuditDigest == YES + {TPM_CC_GetSessionAuditDigest, "TPM_CC_GetSessionAuditDigest"}, +#endif +#if CC_NV_Read == YES + {TPM_CC_NV_Read, "TPM_CC_NV_Read"}, +#endif +#if CC_NV_ReadLock == YES + {TPM_CC_NV_ReadLock, "TPM_CC_NV_ReadLock"}, +#endif +#if CC_ObjectChangeAuth == YES + {TPM_CC_ObjectChangeAuth, "TPM_CC_ObjectChangeAuth"}, +#endif +#if CC_PolicySecret == YES + {TPM_CC_PolicySecret, "TPM_CC_PolicySecret"}, +#endif +#if CC_Rewrap == YES + {TPM_CC_Rewrap, "TPM_CC_Rewrap"}, +#endif +#if CC_Create == YES + {TPM_CC_Create, "TPM_CC_Create"}, +#endif +#if CC_ECDH_ZGen == YES + {TPM_CC_ECDH_ZGen, "TPM_CC_ECDH_ZGen"}, +#endif +#if CC_HMAC == YES + {TPM_CC_HMAC, "TPM_CC_HMAC"}, +#endif +#if CC_MAC == YES + {TPM_CC_MAC, "TPM_CC_HMAC"}, +#endif +#if CC_Import == YES + {TPM_CC_Import, "TPM_CC_Import"}, +#endif +#if CC_Load == YES + {TPM_CC_Load, "TPM_CC_Load"}, +#endif +#if CC_Quote == YES + {TPM_CC_Quote, "TPM_CC_Quote"}, +#endif +#if CC_RSA_Decrypt == YES + {TPM_CC_RSA_Decrypt, "TPM_CC_RSA_Decrypt"}, +#endif +#if CC_HMAC_Start == YES + {TPM_CC_HMAC_Start, "TPM_CC_HMAC_Start"}, +#endif +#if CC_MAC_Start == YES + {TPM_CC_MAC_Start, "TPM_CC_HMAC_Start"}, +#endif +#if CC_SequenceUpdate == YES + {TPM_CC_SequenceUpdate, "TPM_CC_SequenceUpdate"}, +#endif +#if CC_Sign == YES + {TPM_CC_Sign, "TPM_CC_Sign"}, +#endif +#if CC_Unseal == YES + {TPM_CC_Unseal, "TPM_CC_Sign"}, +#endif +#if CC_PolicySigned == YES + {TPM_CC_PolicySigned, "TPM_CC_PolicySigned"}, +#endif +#if CC_ContextLoad == YES + {TPM_CC_ContextLoad, "TPM_CC_ContextLoad"}, +#endif +#if CC_ContextSave == YES + {TPM_CC_ContextSave, "TPM_CC_ContextSave"}, +#endif +#if CC_ECDH_KeyGen == YES + {TPM_CC_ECDH_KeyGen, "TPM_CC_ECDH_KeyGen"}, +#endif +#if CC_EncryptDecrypt == YES + {TPM_CC_EncryptDecrypt, "TPM_CC_EncryptDecrypt"}, +#endif +#if CC_FlushContext == YES + {TPM_CC_FlushContext, "TPM_CC_FlushContext"}, +#endif +#if CC_LoadExternal == YES + {TPM_CC_LoadExternal, ""}, +#endif +#if CC_MakeCredential == YES + {TPM_CC_MakeCredential, "TPM_CC_MakeCredential"}, +#endif +#if CC_NV_ReadPublic == YES + {TPM_CC_NV_ReadPublic, "TPM_CC_NV_ReadPublic"}, +#endif +#if CC_PolicyAuthorize == YES + {TPM_CC_PolicyAuthorize, "TPM_CC_PolicyAuthorize"}, +#endif +#if CC_PolicyAuthValue == YES + {TPM_CC_PolicyAuthValue, "TPM_CC_PolicyAuthValue"}, +#endif +#if CC_PolicyCommandCode == YES + {TPM_CC_PolicyCommandCode, "TPM_CC_PolicyCommandCode"}, +#endif +#if CC_PolicyCounterTimer == YES + {TPM_CC_PolicyCounterTimer, "TPM_CC_PolicyCounterTimer"}, +#endif +#if CC_PolicyCpHash == YES + {TPM_CC_PolicyCpHash, "TPM_CC_PolicyCounterTimer"}, +#endif +#if CC_PolicyLocality == YES + {TPM_CC_PolicyLocality, "TPM_CC_PolicyLocality"}, +#endif +#if CC_PolicyNameHash == YES + {TPM_CC_PolicyNameHash, "TPM_CC_PolicyNameHash"}, +#endif +#if CC_PolicyOR == YES + {TPM_CC_PolicyOR, "TPM_CC_PolicyOR"}, +#endif +#if CC_PolicyTicket == YES + {TPM_CC_PolicyTicket, "TPM_CC_PolicyTicket"}, +#endif +#if CC_ReadPublic == YES + {TPM_CC_ReadPublic, "TPM_CC_ReadPublic"}, +#endif +#if CC_RSA_Encrypt == YES + {TPM_CC_RSA_Encrypt, "TPM_CC_RSA_Encrypt"}, +#endif +#if CC_StartAuthSession == YES + {TPM_CC_StartAuthSession, "TPM_CC_StartAuthSession"}, +#endif +#if CC_VerifySignature == YES + {TPM_CC_VerifySignature, "TPM_CC_VerifySignature"}, +#endif +#if CC_ECC_Parameters == YES + {TPM_CC_ECC_Parameters, "TPM_CC_VerifySignature"}, +#endif +#if CC_FirmwareRead == YES + {TPM_CC_FirmwareRead, "TPM_CC_FirmwareRead"}, +#endif +#if CC_GetCapability == YES + {TPM_CC_GetCapability, "TPM_CC_GetCapability"}, +#endif +#if CC_GetRandom == YES + {TPM_CC_GetRandom, "TPM_CC_GetRandom"}, +#endif +#if CC_GetTestResult == YES + {TPM_CC_GetTestResult, "TPM_CC_GetTestResult"}, +#endif +#if CC_Hash == YES + {TPM_CC_Hash, "TPM_CC_Hash"}, +#endif +#if CC_PCR_Read == YES + {TPM_CC_PCR_Read, "TPM_CC_Hash"}, +#endif +#if CC_PolicyPCR == YES + {TPM_CC_PolicyPCR, "TPM_CC_PolicyPCR"}, +#endif +#if CC_PolicyRestart == YES + {TPM_CC_PolicyRestart, "TPM_CC_PolicyRestart"}, +#endif +#if CC_ReadClock == YES + {TPM_CC_ReadClock, "TPM_CC_ReadClock"}, +#endif +#if CC_PCR_Extend == YES + {TPM_CC_PCR_Extend, "TPM_CC_PCR_Extend"}, +#endif +#if CC_PCR_SetAuthValue == YES + {TPM_CC_PCR_SetAuthValue, "TPM_CC_PCR_SetAuthValue"}, +#endif +#if CC_NV_Certify == YES + {TPM_CC_NV_Certify, "TPM_CC_NV_Certify"}, +#endif +#if CC_EventSequenceComplete == YES + {TPM_CC_EventSequenceComplete, "TPM_CC_EventSequenceComplete"}, +#endif +#if CC_HashSequenceStart == YES + {TPM_CC_HashSequenceStart, "TPM_CC_EventSequenceComplete"}, +#endif +#if CC_PolicyPhysicalPresence == YES + {TPM_CC_PolicyPhysicalPresence, ""}, +#endif +#if CC_PolicyDuplicationSelect == YES + {TPM_CC_PolicyDuplicationSelect, "TPM_CC_PolicyDuplicationSelect"}, +#endif +#if CC_PolicyGetDigest == YES + {TPM_CC_PolicyGetDigest, "TPM_CC_PolicyGetDigest"}, +#endif +#if CC_TestParms == YES + {TPM_CC_TestParms, "TPM_CC_TestParms"}, +#endif +#if CC_Commit == YES + {TPM_CC_Commit, "TPM_CC_Commit"}, +#endif +#if CC_PolicyPassword == YES + {TPM_CC_PolicyPassword, "TPM_CC_PolicyPassword"}, +#endif +#if CC_ZGen_2Phase == YES + {TPM_CC_ZGen_2Phase, "TPM_CC_ZGen_2Phase"}, +#endif +#if CC_EC_Ephemeral == YES + {TPM_CC_EC_Ephemeral, "TPM_CC_EC_Ephemeral"}, +#endif +#if CC_PolicyNvWritten == YES + {TPM_CC_PolicyNvWritten, "TPM_CC_PolicyNvWritten"}, +#endif +#if CC_PolicyTemplate == YES + {TPM_CC_PolicyTemplate, "TPM_CC_PolicyTemplate"}, +#endif +#if CC_CreateLoaded == YES + {TPM_CC_CreateLoaded, ""}, +#endif +#if CC_PolicyAuthorizeNV == YES + {TPM_CC_PolicyAuthorizeNV, "TPM_CC_PolicyAuthorizeNV"}, +#endif +#if CC_EncryptDecrypt2 == YES + {TPM_CC_EncryptDecrypt2, "TPM_CC_EncryptDecrypt2"}, +#endif +#if CC_AC_GetCapability == YES + {TPM_CC_AC_GetCapability, "TPM_CC_AC_GetCapability"}, +#endif +#if CC_AC_Send == YES + {TPM_CC_AC_Send, "TPM_CC_AC_Send"}, +#endif +#if CC_Policy_AC_SendSelect == YES + {TPM_CC_Policy_AC_SendSelect, "TPM_CC_Policy_AC_SendSelect"}, +#endif + {(uint32_t)-1, NULL} +}; + +const lookup_t tpm_rc_globalCodes[] = { + {TPM_RC_SUCCESS, "TPM_RC_SUCCESS"}, + {TPM_RC_BAD_TAG, "TPM_RC_BAD_TAG"}, + {(uint32_t)-1, NULL} +}; + +const lookup_t tpm_rc_formatZeroCodes[] = { + {TPM_RC_INITIALIZE, "TPM_RC_INITIALIZE"}, + {TPM_RC_FAILURE, "TPM_RC_FAILURE"}, + {TPM_RC_SEQUENCE, "TPM_RC_SEQUENCE"}, + {TPM_RC_PRIVATE, "TPM_RC_PRIVATE"}, + {TPM_RC_HMAC, "TPM_RC_HMAC"}, + {TPM_RC_DISABLED, "TPM_RC_DISABLED"}, + {TPM_RC_EXCLUSIVE, "TPM_RC_EXCLUSIVE"}, + {TPM_RC_AUTH_TYPE, "TPM_RC_AUTH_TYPE"}, + {TPM_RC_AUTH_MISSING, "TPM_RC_AUTH_MISSING"}, + {TPM_RC_POLICY, "TPM_RC_POLICY"}, + {TPM_RC_PCR, "TPM_RC_PCR"}, + {TPM_RC_PCR_CHANGED, "TPM_RC_PCR_CHANGED"}, + {TPM_RC_UPGRADE, "TPM_RC_UPGRADE"}, + {TPM_RC_TOO_MANY_CONTEXTS, "TPM_RC_TOO_MANY_CONTEXTS"}, + {TPM_RC_AUTH_UNAVAILABLE, "TPM_RC_AUTH_UNAVAILABLE"}, + {TPM_RC_REBOOT, "TPM_RC_REBOOT"}, + {TPM_RC_UNBALANCED, "TPM_RC_UNBALANCED"}, + {TPM_RC_COMMAND_SIZE, "TPM_RC_COMMAND_SIZE"}, + {TPM_RC_COMMAND_CODE, "TPM_RC_COMMAND_CODE"}, + {TPM_RC_AUTHSIZE, "TPM_RC_AUTHSIZE"}, + {TPM_RC_AUTH_CONTEXT, "TPM_RC_AUTH_CONTEXT"}, + {TPM_RC_NV_RANGE, "TPM_RC_NV_RANGE"}, + {TPM_RC_NV_SIZE, "TPM_RC_NV_SIZE"}, + {TPM_RC_NV_LOCKED, "TPM_RC_NV_LOCKED"}, + {TPM_RC_NV_AUTHORIZATION, "TPM_RC_NV_AUTHORIZATION"}, + {TPM_RC_NV_UNINITIALIZED, "TPM_RC_NV_UNINITIALIZED"}, + {TPM_RC_NV_SPACE, "TPM_RC_NV_SPACE"}, + {TPM_RC_NV_DEFINED, "TPM_RC_NV_DEFINED"}, + {TPM_RC_BAD_CONTEXT, "TPM_RC_BAD_CONTEXT"}, + {TPM_RC_CPHASH, "TPM_RC_CPHASH"}, + {TPM_RC_PARENT, "TPM_RC_PARENT"}, + {TPM_RC_NEEDS_TEST, "TPM_RC_NEEDS_TEST"}, + {TPM_RC_NO_RESULT, "TPM_RC_NO_RESULT"}, + {TPM_RC_SENSITIVE, "TPM_RC_SENSITIVE"}, + {(uint32_t)-1, NULL} +}; + +const lookup_t tpm_rc_warningCodes[] = { + {TPM_RC_CONTEXT_GAP, "TPM_RC_CONTEXT_GAP"}, + {TPM_RC_CONTEXT_GAP, "TPM_RC_CONTEXT_GAP"}, + {TPM_RC_OBJECT_MEMORY, "TPM_RC_OBJECT_MEMORY"}, + {TPM_RC_SESSION_MEMORY, "TPM_RC_SESSION_MEMORY"}, + {TPM_RC_MEMORY, "TPM_RC_MEMORY"}, + {TPM_RC_SESSION_HANDLES, "TPM_RC_SESSION_HANDLES"}, + {TPM_RC_OBJECT_HANDLES, "TPM_RC_OBJECT_HANDLES"}, + {TPM_RC_LOCALITY, "TPM_RC_LOCALITY"}, + {TPM_RC_YIELDED, "TPM_RC_YIELDED"}, + {TPM_RC_CANCELED, "TPM_RC_CANCELED"}, + {TPM_RC_TESTING, "TPM_RC_TESTING"}, + {TPM_RC_REFERENCE_H0, "TPM_RC_REFERENCE_H0"}, + {TPM_RC_REFERENCE_H1, "TPM_RC_REFERENCE_H1"}, + {TPM_RC_REFERENCE_H2, "TPM_RC_REFERENCE_H2"}, + {TPM_RC_REFERENCE_H3, "TPM_RC_REFERENCE_H3"}, + {TPM_RC_REFERENCE_H4, "TPM_RC_REFERENCE_H4"}, + {TPM_RC_REFERENCE_H5, "TPM_RC_REFERENCE_H5"}, + {TPM_RC_REFERENCE_H6, "TPM_RC_REFERENCE_H6"}, + {TPM_RC_REFERENCE_S0, "TPM_RC_REFERENCE_S0"}, + {TPM_RC_REFERENCE_S1, "TPM_RC_REFERENCE_S1"}, + {TPM_RC_REFERENCE_S2, "TPM_RC_REFERENCE_S2"}, + {TPM_RC_REFERENCE_S3, "TPM_RC_REFERENCE_S3"}, + {TPM_RC_REFERENCE_S4, "TPM_RC_REFERENCE_S4"}, + {TPM_RC_REFERENCE_S5, "TPM_RC_REFERENCE_S5"}, + {TPM_RC_REFERENCE_S6, "TPM_RC_REFERENCE_S6"}, + {TPM_RC_NV_RATE, "TPM_RC_NV_RATE"}, + {TPM_RC_LOCKOUT, "TPM_RC_LOCKOUT"}, + {TPM_RC_RETRY, "TPM_RC_RETRY"}, + {TPM_RC_NV_UNAVAILABLE, "TPM_RC_NV_UNAVAILABLE"}, + {(uint32_t)-1, NULL} +}; + +const lookup_t tpm_rc_formatCodes[] = { + {TPM_RCS_ASYMMETRIC, "TPM_RCS_ASYMMETRIC"}, + {TPM_RC_ATTRIBUTES, "TPM_RC_ATTRIBUTES"}, + {TPM_RCS_ATTRIBUTES, "TPM_RCS_ATTRIBUTES"}, + {TPM_RC_HASH, "TPM_RC_HASH"}, + {TPM_RCS_HASH, "TPM_RCS_HASH"}, + {TPM_RC_VALUE, "TPM_RC_VALUE"}, + {TPM_RCS_VALUE, "TPM_RCS_VALUE"}, + {TPM_RC_HIERARCHY, "TPM_RC_HIERARCHY"}, + {TPM_RCS_HIERARCHY, "TPM_RCS_HIERARCHY"}, + {TPM_RC_KEY_SIZE, "TPM_RC_KEY_SIZE"}, + {TPM_RCS_KEY_SIZE, "TPM_RCS_KEY_SIZE"}, + {TPM_RC_MGF, "TPM_RC_MGF"}, + {TPM_RCS_MGF, "TPM_RCS_MGF"}, + {TPM_RC_MODE, "TPM_RC_MODE"}, + {TPM_RCS_MODE, "TPM_RCS_MODE"}, + {TPM_RC_TYPE, "TPM_RC_TYPE"}, + {TPM_RCS_TYPE, "TPM_RCS_TYPE"}, + {TPM_RC_HANDLE, "TPM_RC_HANDLE"}, + {TPM_RCS_HANDLE, "TPM_RCS_HANDLE"}, + {TPM_RC_KDF, "TPM_RC_KDF"}, + {TPM_RCS_KDF, "TPM_RCS_KDF"}, + {TPM_RC_RANGE, "TPM_RC_RANGE"}, + {TPM_RCS_RANGE, "TPM_RCS_RANGE"}, + {TPM_RC_AUTH_FAIL, "TPM_RC_AUTH_FAIL"}, + {TPM_RCS_AUTH_FAIL, "TPM_RCS_AUTH_FAIL"}, + {TPM_RC_NONCE, "TPM_RC_NONCE"}, + {TPM_RCS_NONCE, "TPM_RCS_NONCE"}, + {TPM_RC_PP, "TPM_RC_PP"}, + {TPM_RCS_PP, "TPM_RCS_PP"}, + {TPM_RC_SCHEME, "TPM_RC_SCHEME"}, + {TPM_RCS_SCHEME, "TPM_RCS_SCHEME"}, + {TPM_RC_SIZE, "TPM_RC_SIZE"}, + {TPM_RCS_SIZE, "TPM_RCS_SIZE"}, + {TPM_RC_SYMMETRIC, "TPM_RC_SYMMETRIC"}, + {TPM_RCS_SYMMETRIC, "TPM_RCS_SYMMETRIC"}, + {TPM_RC_TAG, "TPM_RC_TAG"}, + {TPM_RCS_TAG, "TPM_RCS_TAG"}, + {TPM_RC_SELECTOR, "TPM_RC_SELECTOR"}, + {TPM_RCS_SELECTOR, "TPM_RCS_SELECTOR"}, + {TPM_RC_INSUFFICIENT, "TPM_RC_INSUFFICIENT"}, + {TPM_RCS_INSUFFICIENT, "TPM_RCS_INSUFFICIENT"}, + {TPM_RC_SIGNATURE, "TPM_RC_SIGNATURE"}, + {TPM_RCS_SIGNATURE, "TPM_RCS_SIGNATURE"}, + {TPM_RC_KEY, "TPM_RC_KEY"}, + {TPM_RCS_KEY, "TPM_RCS_KEY"}, + {TPM_RC_POLICY_FAIL, "TPM_RC_POLICY_FAIL"}, + {TPM_RCS_POLICY_FAIL, "TPM_RCS_POLICY_FAIL"}, + {TPM_RC_INTEGRITY, "TPM_RC_INTEGRITY"}, + {TPM_RCS_INTEGRITY, "TPM_RCS_INTEGRITY"}, + {TPM_RC_TICKET, "TPM_RC_TICKET"}, + {TPM_RCS_TICKET, "TPM_RCS_TICKET"}, + {TPM_RC_RESERVED_BITS, "TPM_RC_RESERVED_BITS"}, + {TPM_RCS_RESERVED_BITS, "TPM_RCS_RESERVED_BITS"}, + {TPM_RC_BAD_AUTH, "TPM_RC_BAD_AUTH"}, + {TPM_RCS_BAD_AUTH, "TPM_RCS_BAD_AUTH"}, + {TPM_RC_EXPIRED, "TPM_RC_EXPIRED"}, + {TPM_RCS_EXPIRED, "TPM_RCS_EXPIRED"}, + {TPM_RC_POLICY_CC, "TPM_RC_POLICY_CC"}, + {TPM_RCS_POLICY_CC, "TPM_RCS_POLICY_CC"}, + {TPM_RC_BINDING, "TPM_RC_BINDING"}, + {TPM_RCS_BINDING, "TPM_RCS_BINDING"}, + {TPM_RC_CURVE, "TPM_RC_CURVE"}, + {TPM_RCS_CURVE, "TPM_RCS_CURVE"}, + {TPM_RC_ECC_POINT, "TPM_RC_ECC_POINT"}, + {TPM_RCS_ECC_POINT, "TPM_RCS_ECC_POINT"}, + {(uint32_t)-1, NULL} +}; + +char decodeBuf[100]; +#else +char decodeBuf[6]; +#endif + +static char* TpmDecodeTPM_CC(uint8_t* in) +{ + TPM_CC cc = BYTE_ARRAY_TO_UINT32(in); +#ifndef NDEBUG + uint32_t n; + for(n = 0; ((tpm_cc_table[n].index != (uint32_t)-1) && (tpm_cc_table[n].index != cc)) ; n++ ); + if(tpm_cc_table[n].index != (uint32_t)-1) + { + sprintf(decodeBuf, "%s()", tpm_cc_table[n].str); + } + else + { +#endif + sprintf(decodeBuf, "0x%03x", (unsigned int)cc); +#ifndef NDEBUG + } +#endif + return decodeBuf; +} + +static char* TpmDecodeTPM_RC(uint8_t* in) +{ + TPM_RC rc = BYTE_ARRAY_TO_UINT32(in); +#ifndef NDEBUG + uint32_t n; + uint32_t cursor = 0; + + for(n = 0; ((tpm_rc_globalCodes[n].index != (uint32_t)-1) && (tpm_rc_globalCodes[n].index != rc)) ; n++ ); + if(tpm_rc_globalCodes[n].index != (uint32_t)-1) + { + cursor = sprintf(decodeBuf, "{%s}", tpm_rc_globalCodes[n].str); + } + else if((rc & RC_FMT1) == RC_FMT1) + { + if(rc & TPM_RC_P) + { + cursor = sprintf(decodeBuf, "{RC_FMT1 | TPM_RC_P | TPM_RC_%X | ", (unsigned int)((rc & 0x00000f00) >> 8)); + } + else if(rc & TPM_RC_S) + { + cursor = sprintf(decodeBuf, "{RC_FMT1 | TPM_RC_S | TPM_RC_%X | ", (unsigned int)((rc & 0x00000700) >> 8)); + } + else + { + cursor = sprintf(decodeBuf, "{RC_FMT1 | TPM_RC_H | TPM_RC_%X | ", (unsigned int)((rc & 0x00000700) >> 8)); + } + + for(n = 0; ((tpm_rc_formatCodes[n].index != (uint32_t)-1) && (tpm_rc_formatCodes[n].index != (rc & TPM_RC_MAX_FM1))) ; n++ ); + if(tpm_rc_formatCodes[n].index != (uint32_t)-1) + { + cursor = sprintf(&decodeBuf[cursor], "%s}", tpm_rc_formatCodes[n].str); + } + else + { + cursor = 0; + } + } + else if((rc & RC_WARN) == RC_WARN) + { + for(n = 0; ((tpm_rc_warningCodes[n].index != (uint32_t)-1) && (tpm_rc_warningCodes[n].index != rc)) ; n++ ); + if(tpm_rc_warningCodes[n].index != (uint32_t)-1) + { + cursor = sprintf(decodeBuf, "{RC_VER1 | RC_WARN | %s}", tpm_rc_warningCodes[n].str); + } + } + else if((rc & RC_VER1) == RC_VER1) + { + for(n = 0; ((tpm_rc_formatZeroCodes[n].index != (uint32_t)-1) && (tpm_rc_formatZeroCodes[n].index != rc)) ; n++ ); + if(tpm_rc_formatZeroCodes[n].index != (uint32_t)-1) + { + cursor = sprintf(decodeBuf, "{RC_VER1 | %s}", tpm_rc_formatZeroCodes[n].str); + } + } + + if(cursor == 0) + { +#endif + sprintf(decodeBuf, "0x%03x", (unsigned int)rc); + return decodeBuf; +#ifndef NDEBUG + } +#endif + return decodeBuf; +} + +static bool TpmGenerateUnique(void) +{ + wc_Sha512 hash; + struct + { + uint16_t mcuType; + uint16_t mcuRev; + uint16_t flashSize; + unsigned char serial[12]; + } mcuInfo; + + ReadMcuInfo(mcuInfo.serial, &mcuInfo.flashSize, &mcuInfo.mcuType, &mcuInfo.mcuRev); + + if((wc_InitSha512(&hash)) || + (wc_Sha512Update(&hash, (const byte*)&mcuInfo, sizeof(mcuInfo))) || + (wc_Sha512Final(&hash, (byte*)tpmUnique))) + { + logError("Sha512 failed\r\n"); + return false; + } + wc_Sha512Free(&hash); + +#ifndef NDEBUG + uint8_t unique[WC_SHA512_DIGEST_SIZE] = {0}; + _plat__GetUnique(0, sizeof(unique), unique); + dbgPrint("Generated tpmUnique"); + for(uint32_t n = 0; n < sizeof(unique); n++) + { + if(!(n % 16)) dbgPrintAppend("\r\n "); + dbgPrintAppend("%02x", ((unsigned int)(unique[n]))); + } + dbgPrintAppend("\r\n"); +#endif + return true; +} + +bool TpmInitializeDevice(void) +{ + int retVal = 0; + + tpmOp.receivingCmd = -1; + TpmGenerateUnique(); + + SetDutyCycleIndicator(FALSE); + + // Factory reset requested? + if(BlueButtonTransitionDetected()) + { + dbgPrint("Factory reset requested.\r\n"); + if((retVal = _plat__NVEnable((void*)1)) < 0) + { + logError("_plat__NVEnable(1) failed unrecoverable.") + } + dbgPrint("Waiting for the button to be released...\r\n"); + while(BlueButtonTransitionDetected() == 0); + } + else + { + if((retVal = _plat__NVEnable((void*)0)) < 0) + { + logError("_plat__NVEnable(0) failed unrecoverable.") + } + } + + + if(retVal > 0) + { + dbgPrint("TPM_Manufacture(1) requested.\r\n"); + if((retVal = TPM_Manufacture(1)) != 0) + { + logError("TPM_Manufacture(1) failed.\r\n"); + } + } + + dbgPrint("_plat__SetNvAvail().\r\n"); + _plat__SetNvAvail(); + dbgPrint("_plat__Signal_PowerOn().\r\n"); + if((retVal =_plat__Signal_PowerOn()) != 0) + { + logError("_plat__Signal_PowerOn() failed.\r\n"); + } + dbgPrint("_plat__Signal_Reset().\r\n"); + if((retVal =_plat__Signal_Reset()) != 0) + { + logError("_plat__Signal_Reset() failed.\r\n"); + } + return (retVal == 0); +} + +bool TpmOperationsLoop(void) +{ + // Device reset + if(tpmOp.flags.resetRequested == 1) + { + tpmOp.flags.resetRequested = 0; + + HAL_Delay(1); + dbgPrint("Executing _plat__Signal_PowerOff()\r\n"); + _plat__Signal_PowerOff(); + PerformSystemReset(); + return false; + } + + if(tpmOp.flags.powerOffRequested == 1) + { + tpmOp.flags.powerOffRequested = 0; + dbgPrint("Executing _plat__Signal_PowerOff()\r\n"); + _plat__Signal_PowerOff(); + KillUSBLink(); + return false; + } + + // Physical presence button (blue button on the Nucleo) + int ppButton = BlueButtonTransitionDetected(); + if(ppButton > 0) + { + dbgPrint("Executing _plat__Signal_PhysicalPresenceOn().\r\n"); + _plat__Signal_PhysicalPresenceOn(); + } + else if (ppButton < 0) + { + dbgPrint("Executing _plat__Signal_PhysicalPresenceOff().\r\n"); + _plat__Signal_PhysicalPresenceOff(); + } + + // Command processing + if(tpmOp.flags.executionRequested == 1) + { + tpmOp.flags.executionRequested = 0; + unsigned int rspLenTPM = sizeof(tpmOp.msgBuf) - sizeof(rspLenTPM); + unsigned char* rspTPM = (unsigned char*)&tpmOp.msgBuf[sizeof(rspLenTPM)]; + + itmPrintAppend(ITMCMDRSP, "//%s\r\nunsigned char CmdBuf[%d] = {", GetLogStamp(), tpmOp.cmdSize); + for(uint32_t n = 0; n < tpmOp.cmdSize; n++) + { + if(n > 0) itmPrintAppend(ITMCMDRSP, ", "); + if(!(n % 16)) itmPrintAppend(ITMCMDRSP, "\r\n"); + itmPrintAppend(ITMCMDRSP, "0x%02x", tpmOp.msgBuf[n]); + } + itmPrintAppend(ITMCMDRSP, "\r\n};\r\n"); + + SetDutyCycleIndicator(TRUE); + dbgPrint("Executing command %s\r\n", TpmDecodeTPM_CC((uint8_t*)&tpmOp.msgBuf[6])); + time_t execStart = time(NULL); + _plat__RunCommand((unsigned int)tpmOp.cmdSize, (unsigned char*)tpmOp.msgBuf, &rspLenTPM, &rspTPM); + *((unsigned int*)tpmOp.msgBuf) = rspLenTPM; + time_t execEnd = time(NULL); + dbgPrint("Completion time %u'%u\" with ReturnCode %s\r\n", (unsigned int)(execEnd - execStart) / 60, (unsigned int)(execEnd - execStart) % 60, TpmDecodeTPM_RC(&rspTPM[6])); + SetDutyCycleIndicator(FALSE); + + itmPrintAppend(ITMCMDRSP, "//%s\r\nunsigned char RspBuf[%d] = {", GetLogStamp(), tpmOp.cmdSize); + for(uint32_t n = 0; n < rspLenTPM; n++) + { + if(n > 0) itmPrintAppend(ITMCMDRSP, ", "); + if(!(n % 16)) itmPrintAppend(ITMCMDRSP, "\r\n"); + itmPrintAppend(ITMCMDRSP, "0x%02x", rspTPM[n]); + } + itmPrintAppend(ITMCMDRSP, "\r\n};\r\n"); + + tpmOp.rspSize = sizeof(rspLenTPM) + rspLenTPM; + tpmOp.cmdSize = 0; + tpmOp.flags.responseRequested = 1; + } + + if(tpmOp.flags.responseRequested == 1) + { + tpmOp.flags.responseRequested = 0; + if(tpmOp.rspSize > 0) + { + uint32_t chunk = 0; + while(CDC_Transmit_FS((unsigned char*)&tpmOp.msgBuf, 0) != 0); // Wake up the link + while(CDC_Transmit_FS((unsigned char*)&tpmOp.msgBuf, 14) != 0); // Send the header which is the minimum size + for(uint32_t n = 14; n < tpmOp.rspSize; n += chunk) // Send the rest in 16 byte increments + { + chunk = MIN(16, tpmOp.rspSize - n); + while(CDC_Transmit_FS((unsigned char*)&tpmOp.msgBuf[n], chunk) != 0); +// dbgPrint("Sent(%u)\r\n", (unsigned int)(n + chunk)); + } + itmPrint(ITMSIGNAL, "Response(%d)\r\n", tpmOp.rspSize); + } + } + + return true; +} + +void TpmConnectionReset(void) +{ + tpmOp.receivingCmd = -1; + tpmOp.cmdSize = 0; + tpmOp.rspSize = 0; + memset((void*)tpmOp.msgBuf, 0x00, sizeof(tpmOp.msgBuf)); +} + +bool TpmSignalEvent(uint8_t* Buf, uint32_t *Len) +{ + // Pending inbound transfer + if(tpmOp.receivingCmd > 0) + { + memcpy((void*)&tpmOp.msgBuf[tpmOp.cmdSize], (void*)Buf, *Len); + tpmOp.cmdSize += *Len; +// itmPrint(ITMSIGNAL, "Received(%d)\r\n", tpmOp.cmdSize); + if(tpmOp.cmdSize >= tpmOp.receivingCmd) + { + itmPrint(ITMSIGNAL, "Received(%d)\r\n", tpmOp.cmdSize); + tpmOp.receivingCmd = -1; + tpmOp.flags.executionRequested = 1; + } + } + else if(sizeof(signalWrapper_t) > *Len) + { + itmPrint(ITMSIGNAL, "Invalid frame received.\r\n"); + return false; + } + else + { + pSignalWrapper_t sig = (pSignalWrapper_t)Buf; + if(sig->s.magic == SIGNALMAGIC) + { + pSignalPayload_t payload; + switch(sig->s.signal) + { + case SignalNothing: + if((sig->s.dataSize != 0) || (*Len != sizeof(signalWrapper_t))) + { + itmPrint(ITMSIGNAL, "Invalid data size %u for SignalNothing(%u).\r\n", (unsigned int)*Len, (unsigned int)sig->s.dataSize); + return false; + } + itmPrint(ITMSIGNAL, "SignalNothing\r\n"); + break; + + case SignalShutdown: + if((sig->s.dataSize != 0) || (*Len != sizeof(signalWrapper_t))) + { + itmPrint(ITMSIGNAL, "Invalid data size %u for SignalShutdown(%u).\r\n", (unsigned int)*Len, (unsigned int)sig->s.dataSize); + return false; + } + itmPrint(ITMSIGNAL, "SignalShutdown\r\n"); + tpmOp.flags.powerOffRequested = 1; + break; + + case SignalReset: + if((sig->s.dataSize != 0) || (*Len != sizeof(signalWrapper_t))) + { + itmPrint(ITMSIGNAL, "Invalid data size %u for SignalReset(%u).\r\n", (unsigned int)*Len, (unsigned int)sig->s.dataSize); + return false; + } + itmPrint(ITMSIGNAL, "SignalReset\r\n"); + tpmOp.flags.resetRequested = 1; + break; + + case SignalSetClock: + if((sig->s.dataSize != sizeof(unsigned int)) || (*Len != sizeof(signalWrapper_t) + sizeof(unsigned int))) + { + itmPrint(ITMSIGNAL, "Invalid data size %u for SignalSetClock(%u).\r\n", (unsigned int)*Len, (unsigned int)sig->s.dataSize); + return false; + } + payload = (pSignalPayload_t)&Buf[sizeof(signalWrapper_t)]; + SetRealTimeClock(payload->SignalSetClockPayload.time); + itmPrint(ITMSIGNAL, "SignalSetClock(0x%08x)\r\n", payload->SignalSetClockPayload.time); + break; + + case SignalCancelOn: + if((sig->s.dataSize != 0) || (*Len != sizeof(signalWrapper_t))) + { + itmPrint(ITMSIGNAL, "Invalid data size %u for SignalCancelOn(%u).\r\n", (unsigned int)*Len, (unsigned int)sig->s.dataSize); + return false; + } + itmPrint(ITMSIGNAL, "SignalCancelOn\r\n"); + _plat__SetCancel(); + break; + + case SignalCancelOff: + if((sig->s.dataSize != 0) || (*Len != sizeof(signalWrapper_t))) + { + itmPrint(ITMSIGNAL, "Invalid data size %u for SignalCancelOff(%u).\r\n", (unsigned int)*Len, (unsigned int)sig->s.dataSize); + return false; + } + itmPrint(ITMSIGNAL, "SignalCancelOff\r\n"); + _plat__ClearCancel(); + break; + + case SignalCommand: + if((sig->s.dataSize == 0) || + (*Len == sizeof(signalWrapper_t))) + { + itmPrint(ITMSIGNAL, "Invalid data size %u for SignalCommand(%u).\r\n", (unsigned int)*Len, (unsigned int)sig->s.dataSize); + return false; + } + payload = (pSignalPayload_t)&Buf[sizeof(signalWrapper_t)]; + unsigned int expected = sizeof(signalWrapper_t) + sizeof(unsigned int) * 2 + payload->SignalCommandPayload.cmdSize; + unsigned int maxAllowed = sizeof(tpmOp.msgBuf); + memset((unsigned char*)tpmOp.msgBuf, 0x00, sizeof(tpmOp.msgBuf)); + tpmOp.rspSize = 0; + itmPrint(ITMSIGNAL, "SignalCommand(%d)\r\n", payload->SignalCommandPayload.cmdSize); + + // Set the locality for the command + if(_plat__LocalityGet() != payload->SignalCommandPayload.locality) + { + _plat__LocalitySet(payload->SignalCommandPayload.locality); + itmPrint(ITMSIGNAL, "SetLocality(%d)\r\n", payload->SignalCommandPayload.locality); + } + + if((*Len == expected) && + (payload->SignalCommandPayload.cmdSize <= maxAllowed)) + { + memcpy((void*)tpmOp.msgBuf, (void*)payload->SignalCommandPayload.cmd, payload->SignalCommandPayload.cmdSize); + tpmOp.cmdSize = payload->SignalCommandPayload.cmdSize; + tpmOp.flags.executionRequested = 1; +// itmPrint(ITMSIGNAL, "Received(%d)\r\n", tpmOp.cmdSize); + } + else if((*Len < expected) && + (payload->SignalCommandPayload.cmdSize <= maxAllowed)) + { + unsigned int dataSnip = *Len - (sizeof(signalWrapper_t) + sizeof(unsigned int) * 2); + memcpy((void*)tpmOp.msgBuf, (void*)payload->SignalCommandPayload.cmd, dataSnip); + tpmOp.receivingCmd = payload->SignalCommandPayload.cmdSize; + tpmOp.cmdSize = dataSnip; +// itmPrint(ITMSIGNAL, "Received(%d)\r\n", tpmOp.cmdSize); + } + else + { + logError("Invalid command size.\r\n"); + return false; + } + break; + + case SignalResponse: + if((sig->s.dataSize != 0) || (*Len != sizeof(signalWrapper_t))) + { + itmPrint(ITMSIGNAL, "Invalid data size %u for SignalResponse(%u).\r\n", (unsigned int)*Len, (unsigned int)sig->s.dataSize); + return false; + } + itmPrint(ITMSIGNAL, "SignalResponse\r\n"); + if(tpmOp.rspSize > 0) + { + tpmOp.flags.responseRequested = 1; + } + break; + + default: + itmPrint(ITMSIGNAL, "Unknown Signal %u received.\r\n", sig->s.signal); + return false; + break; + } + } + } + return true; +} diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/syscalls.c b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/syscalls.c new file mode 100644 index 0000000..35a949c --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/Shared/syscalls.c @@ -0,0 +1,296 @@ +/* +****************************************************************************** +File: syscalls.c +Info: Generated by Atollic TrueSTUDIO(R) 8.0.0 2017-10-17 + +The MIT License (MIT) +Copyright (c) 2009-2017 Atollic AB + +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. + +****************************************************************************** +*/ + +/* Includes */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "stm32l4xx_hal.h" +#include "StmUtil.h" + +extern RTC_HandleTypeDef hrtc; +extern UART_HandleTypeDef huart2; + +/* Variables */ +#undef errno +extern int32_t errno; + +uint8_t *__env[1] = { 0 }; +uint8_t **environ = __env; + +/* Functions */ +void initialise_monitor_handles() +{ +} + +int _getpid(void) +{ + errno = ENOSYS; + return -1; +} + +int _gettimeofday(struct timeval *ptimeval, void *ptimezone) +{ + if(ptimezone) + { + struct timezone* tz = ptimezone; + tz->tz_minuteswest = _timezone / 60; + tz->tz_dsttime = _daylight; + } + + if(ptimeval) + { + RTC_TimeTypeDef time = {0}; + RTC_DateTypeDef date = {0}; + + if((HAL_RTC_GetTime(&hrtc, &time, RTC_FORMAT_BIN) != HAL_OK) || + (HAL_RTC_GetDate(&hrtc, &date, RTC_FORMAT_BIN) != HAL_OK)) + { + errno = ENOSYS; + return -1; + } + + struct tm local = {0}; + local.tm_year = date.Year + 100; + local.tm_mon = date.Month - 1; + local.tm_mday = date.Date; + local.tm_wday = date.WeekDay - 1; + local.tm_hour = time.Hours; + local.tm_min = time.Minutes; + local.tm_sec = time.Seconds; + ptimeval->tv_sec = mktime(&local); + ptimeval->tv_usec = (time.SecondFraction * 1000 * 1000 / time.SubSeconds); + } + + return 0; +} + +int _kill(int32_t pid, int32_t sig) +{ + errno = ENOSYS; + return -1; +} + +void _exit(int32_t status) +{ + while (1) {} /* Make sure we hang here */ +} + +int _write(int32_t file, uint8_t *ptr, int32_t len) +{ +#ifndef NDEBUG + if (file == 1) //STDOUT + { + HAL_UART_Transmit(&huart2, ptr, len, HAL_MAX_DELAY); + } + else if (file == 2) //STDERR + { + for(uint32_t n = 0; n < len; n++) + { + ITM_SendChar(ptr[n]); + } + return len; + } + else if ((file >= ITMFILENO) && (file < ITMFILENO + ITMCHANNELNO)) + { + for(uint32_t n = 0; n < len; n++) + { + ITM_Out(file - ITMFILENO, ptr[n]); + } + return len; + } +#endif + errno = ENOSYS; + return -1; +} + +void * _sbrk(int32_t incr) +{ + extern char end; /* Set by linker. */ + static char * heap_end; + char * prev_heap_end; + + if (heap_end == 0) { + heap_end = & end; + } + + prev_heap_end = heap_end; + heap_end += incr; + + return (void *) prev_heap_end; +} + +int _close(int32_t file) +{ + if ((file >= ITMFILENO) && (file < ITMFILENO + ITMCHANNELNO)) + { + return 0; + } + errno = ENOSYS; + return -1; +} + + +int _fstat(int32_t file, struct stat *st) +{ + if ((file >= ITMFILENO) && (file < ITMFILENO + ITMCHANNELNO)) + { + st->st_mode = S_IFCHR; + st->st_size = 0; + return 0; + } + errno = ENOSYS; + return -1; +} + +int _isatty(int32_t file) +{ + if ((file >= ITMFILENO) && (file < ITMFILENO + ITMCHANNELNO)) + { + return 1; + } + errno = ENOSYS; + return 0; +} + +int _lseek(int32_t file, int32_t ptr, int32_t dir) +{ + if ((file >= ITMFILENO) && (file < ITMFILENO + ITMCHANNELNO)) + { + return 0; + } + errno = ENOSYS; + return -1; +} + +int _read(int32_t file, uint8_t *ptr, int32_t len) +{ + errno = ENOSYS; + return -1; +} + +int _readlink(const char *path, char *buf, size_t bufsize) +{ + errno = ENOSYS; + return -1; +} + +int _open(const uint8_t *path, int32_t flags, int32_t mode) +{ + unsigned int channel = 0; + if((strlen((char*)path) == 7 ) && + !strncmp((char*)path, "ITM[", 4) && + !strcmp((char*)&path[6], "]") && + (sscanf((char*)&path[4],"%02u", &channel) == 1) && + (channel < ITMCHANNELNO) && + ((flags == 0x601) || (flags == 0x10601))) + { + return ITMFILENO + channel; + } + errno = ENOSYS; + return -1; +} + +int _wait(int32_t *status) +{ + errno = ENOSYS; + return -1; +} + +int _unlink(const uint8_t *name) +{ + errno = ENOSYS; + return -1; +} + +int _times(struct tms *buf) +{ + RTC_TimeTypeDef time = {0}; + RTC_DateTypeDef date = {0}; + + if((HAL_RTC_GetTime(&hrtc, &time, RTC_FORMAT_BIN) != HAL_OK) || + (HAL_RTC_GetDate(&hrtc, &date, RTC_FORMAT_BIN) != HAL_OK)) + { + errno = ENOSYS; + return -1; + } + + struct tm local = {0}; + local.tm_year = date.Year + 100; + local.tm_mon = date.Month - 1; + local.tm_mday = date.Date; + local.tm_wday = date.WeekDay - 1; + local.tm_hour = time.Hours; + local.tm_min = time.Minutes; + local.tm_sec = time.Seconds; + + buf->tms_utime = mktime(&local); /* user time */ + buf->tms_stime = 0; /* system time */ + buf->tms_cutime = 0; /* user time, children */ + buf->tms_cstime = 0; /* system time, children */ + return 0; +} + +int _stat(const uint8_t *file, struct stat *st) +{ + errno = ENOSYS; + return -1; +} + +int _symlink(const char *path1, const char *path2) +{ + errno = ENOSYS; + return -1; +} + +int _link(const uint8_t *old, const uint8_t *new) +{ + errno = ENOSYS; + return -1; +} + +int _fork(void) +{ + errno = ENOSYS; + return -1; +} + +int _execve(const uint8_t *name, uint8_t * const *argv, uint8_t * const *env) +{ + errno = ENOSYS; + return -1; +} + diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/USB_Hookup.jpg b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/USB_Hookup.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c207456be8b93d52b8ca9c48e30845eb3f190dd5 GIT binary patch literal 838421 zcmbSyXFyX~*X{{+5FHB^P*Gt}snUXqf{m((lz@O3l_DTXR3wp>SO!!S5s(@kRB956 z(gFm?D1u6eg(jpB0TUEWB18x=g}ZUynfLqg{kZoYIGn{kyO&j-wa!fc%tz=qS4S5| z2nK^e&fo`{8CrP4;Zk@g1i86Eh7bfTgft;tXda+o;3mVCLTcbSAKX>2-+s|c09_B$ z{x?rMOy^(v4Qwkk2fT;P=7gF5%D)W!-v_h!MXv<(=j-9n++TShNO9x$f9Uxi3oU-t z1Kus1TWI+!KWKNMexcPb+8EHYJ)FH3gB!N*+_}gQDEw#`1|71|X5-Pw=&0FuU{t^Q z{_A<}R5<#gDLUlhMk~|prWWQ9WU<|R$FA)byDZE%n%nF$x87x84M7{O=KV7UwTP<^ z{-rP6*!^LeK)x&fM)57Up;7{4+MS*t>K8rSGJ{{>}qan**i8Aoaid zrS>>o?ce&z>2v-~uS%c$FWs2F;6H7Fl}KOoANn^ytN&Z}dHTv<>0rLpI@053+nNjJ zMXf76?N=Y>Zr@=IrKkUwe)vzH&9`rV2>VZ+V3i-L{j&xOK0ciD4?XYm;nuKs|*zH1<%=an7u%quvG92Ucj3-x{x%_;@AGz81C)`UVz=b66E-&AB(`O zfO2Z4;MH8v)7d)0AZU&S82vwaU|^>Ip(nrz_=g?`x&NVI;JnPPE7ngO>eTr{6)@=b)$ml${5y`jx&Oq<@B1|Cf-k8?#t958<-W$9A*mJ3e$(_!er1i^cDI9em+7f zXeCSwwhOic1_wEo!WO|6!dTE7r~_(;UO)_}2U-hT1KSI;2YD=Ed}svfgIpmvWDD&9 zKX#BOc)t$j2y=k#0c{Atdlpmx6&6M~v>0%-02l()um>gvCBH$ly%+{#<3LdN~Q0q@f49d1cZO{kM`T%Hu9SjX}1i+5KDd&?3HcW=1K5pr)aj8CDGh{hkOi zrTwQ{D*(N5ySbIaK5MwS$v!K%jfs_wIoxE&KF6IVaPxzX2e-p5Ev(^i2-+8NOD-${khi1!a{+nkI%*L;D@7eTa z|E3GT8UAnjnt#(p(E4BL8lcXp*&^UF1NUs(27f<)17Zpa26yb=|NmM|@Lps4-|4}i zKM?mi~ZuU7V z_2>OB5_jY2Q$c4p21lQY+!%BU6>{O!MoZJ3J5i{Op=Rc$JD?dhbO2I=!DfH|bIqAI zXZD&uckY~d3+69aFncdtq_Jq>LiL3U7N~2gt7|L<*Mdb$mTE3uGE2`^GFyDM6!=}d zaKXaa9RF|E%wN#5g$q8;`#cA>8B$vYo3jiy^8&C-2%N`X7Z~8L>z}>9NL>SDs09lN zn=?lZbavicAZlR=v*LX2vU$rlneUsw!sFC}&F5EITuFPhP;dX!XIh@`zw29`zHoJs z`l{7y)@uK5ux0BuLn~{z&5oVB4jgoFbaHla_3}pe_#X4~4+;(mJrfol5p^*di@OvP zd+m?Jr0X|sCZ}iI%goBo$<2FQP*_x4Qc5CMRoB$kQR^ETpSQkfYk&Fbbw^isPjBCc z{sGp|@W>~=VD$5svGEDXkI5K7aW>j|HdBuh?vHW#P*GX^);hTcl^{`CaSuh4<>K^sR<|ADvKhj`hXWsp6joPL~av|WAc<6D+LHC2>sht53VXhhSbDtZ1R zS#1YnU%y#hfY4p}Wd>sTYjqkMoO|UeGpUQb?94iXkNiP7%3YcpAWjfxPm^`(RlK=r zqG$_)x1EGP@AoZxuj8;GNWST7>{QYB3g>vY;u+{n#470rW8YEU_89+tdaLwTos{j+ z4{f$^kbJZYh;NltnosW=Kjho1vYF0*=Km=+y7uLD)X1M7UM<-$#{I7K8p}9|`m|)p z$0KLE(Iy?Q8v@Rn98M|d3HIG^A%$nO^qx47)^g9}@$0CD>_6!?;|bedn?1TST z4#vKV!ya)p&4yJ@k|kO%N11La(s!)rt9aUbKlcDS1^eg68Axk)AjLG;ak0pR zh+0$9kTLbv1n-DI4*MMMeE|Pyt*KMdiy1}|f0WHY)lG3%*bNcKd@m*+K!vC#=NC7v z-tMmF7=YffRC<7r=-qsCbG<~v=p{|i8sFitzfuxx%2ULqJ8n1>f>qQ86gWJjYUlWk zq+#Ds29$foTBxOMG4WOYm09HGwQ+L9wqkQ;E1K;QBX2p$m{9Z{e>iDCqoZ7RNXfFa z+m>eIaU&nTAi!V)snJ_%^-Z6vse({>@9v_gRX!u%P#p?hj2|Hr(Ug8Dr7C|& zh8>^iNmGf@p9ab7T)&n{?ZoCL3!{L;U3xQ+Mgm{2uf~75Z*F`Wl6cm{u>+48=FqvM zm@DM9!A6$xJhSiRR%LTF9@Oi$O2b%d&oLxs+>(<*<_?0ElXWiY`1LZv;0zR-Hv^f? zBL(?z*mVjgu@J$#D%SD zd2Bf^autimEt0@r^~jvr!v$BxDE6l z+PJkVlkt&CE}OtDb}njEFsNe0&6cAbN4UKjHsX~V!s<2F#UNNT-x+8_u|-mdEuJt` z5+qQG{e!y*ON307(AB`AeqehQq1Me|usll^P78P=YYD9BFEq>WUd~-^T~EX?rTCB; zD726(?+A|EUn!-=_k7V|pnV0%;fIv#Iz8QJt^CfHgUH-)pG`eBojv3iMybs-)z62< z`_x6Ff)LEK)}E+$HcS`-b6JDOF`f4*+vr}#WAQV8Toc6WrEsCAEX$UPo!oG9xsfqSA}rcr6vKSKpSJCJ6ENB zF#-{=KAp@Cdl>kJA@i;+TW)7zCzf0B|8Sx4(cyHtjWo<}ZX98NInU8&SwUEEJ1;xW#hfoR zs=I5()s4nWnTJ(hEdk3Ne^?p*?pD5~*vJ!&;AXN_U0uS7P>vmDs4xf|(LQ;trzO9x z;8BJ&7eiE%YuDw+VR_QJpS|vu7`@sfJPQRqws7vTm-qYSG(u7VGWVW#T0z)@C}~1o z4x5N$O!OsX>(sP!2(kBXcks+!tArce6&giG&K;fCm7=X0bK=>D;(4uZgv|3aCCjZX zn6s?~$xLU5!DxB#(*Y&l`(oKOHtF``_Do4!->v)|X3SbLJT*9%J<)S|Ue%+OgS!354gqV7I(J#!iMT^Vn?23200piUbzcMg3yQuk-oda}Ee1g9A3%K70P zkFt}Y*x{Y#N?u;NV{lqFRyhM%Z{Z%#&n0DS_h}cfz}i_=s5vRSCDw2)WIdbKRXNx$ zR<&QI!=2=G8!pomXRu#n7mC1(zxSXfl;X@8sK~ZcL)U(=0Np!?4?#8``C#y2x!FCT zPhr|0#O!IGeA+0N%8v-nNeP(7DQf(moz+;%Fc8uLFia0JbYLn+(K`)!i4TB2hlvf$;GL*%dkcdC$;idvVdjfb{)?0p}+b;WnsHOjD2P z9y@S`Uy_oGa&O2E5ms~kbNxesDg#+qwPuZ00gJs~(IhPLnBe=KML+Vc zQnbuK-?~SRer}NS`Z6=N-L%r{9JE6Y%|MsD>XdymP)k@E4(_Cs98TpQ7XjW}*n4x4 z<+@a5Ux`sXGph*0L&F-eg$VhJ8A#I^y)%f_=`>EjW@LRbV7WcFQ=5VQ!g*R+{6LX; zHgcdlH3YW zf%G;{7wLs;}XYJ+D_G(|f_@w1n2u4Z@ zmepNTjz!dQ`(^I(8o_Z>iPZjw;ezrq^ULkLsk$yp6h=8e2}Q?=j#BDB#nXk>o~!S+ zgbpUt%?6P}5q80mO0jZ5-fB$)0!@Oy_~%J34a0qOxv!m*DI=9MSFMtf#;=w!sp6w*Rq;1fz56T`%p{d=Ub%A# zV+O)L40~sEA0^qPTDiz*Sv&2Hnvm@&*2&4w46kQP%*MT>R~cYCHt#DpCpHNiWLPCD zf`471UUU~GK|L!*83)+6NsflCVK+GPn%(^rO#1Vtaj}Op&(vMcrp9_@A-R=|272=4 z^_$pzNkJ1Me72OXjmiC5i%VbyIm2h5T7|vv^sO8kZ{L{=obC%cwjd=ni$RU*&b?-l zrkd14A!K-o2cyTjr2sBVenb?6g3S>Ae0_PwM5TS3l$3AjoFnrK5O5#Vm(+>Pru~52 zT3-_P`FP=b?Wca0wRLp_7N$Mj`E}|!)LRA8#7%pZ@%k1o7sCp%NT?Dw@0ildy;{*5 zNXM-dzKj)Na`6&NuUyyaAihs&zc52Rxr32PoF@OleeNhK!c`8IF3z_Qh02K2VH1k< z1>dRPm0PjiY3j-k@?MMIxMdx#3MTDGq3+jesZaJfzcq@^WWvWouAMl`d2;$736}00 zn}x}iQyTxQc6>JkxVO}g{JR$oE6xlz2tjaZd|$3=ay>-VHzx-xC^YPzFXSyPk`_FwsWV>dE3oGxgP1AaY+kVKh1fvRg32g^{_d1v2012y0?gl*F5u-H8!fL%ZPi-`DfNa!+MqXw+${ zx2ri-*HFn*HSfGo6$NGu+8N4jNaZ5fM?%ARCJOt}L-GvqoK2&955a0nSDxPT6#EN1oYcpix>F)IEzYY z^O(t_dJ~#5F9ScoK8yCx-+b}2k(0cApw{<6{)-+@w23KKo-IZ_uC}z_zx8plQnUKg z^W<$6T*{V>>)o(Ix5ou6h?e41-$la~_bo5|3Gss(|7126xHr3(ad@8T^QrA#kc%LYRF>gmgo<39Z{S>I@N3VO`h%?P{D5ymJ_@UlGWb)E^+?Dt^zTrF}r z+X*wrJOpDVVArFE%lE^{qx=n%`4#=Sp920Ec90PUBHlP1#Mvb@O<(zFo6pXBd9>-wfvl_DhYpd$E(WnjZJ5T%ij#?#B%oE zDLQ74Sa5ZRy?^%8>Xf|GYj*c=%H?f}F?brfToujgXb!JBL?7MOaQ(5+KE=r@jT^8l z{xwbBoB6})c3h^Zb?6{@j9ERMmnFb@)TiE)mYSd!2kw8B-}d!zBf($~J$BWeZ3fX^ z$pNccCbqrl?jsM5)eUK{nt=koc4O%El)JB&-Na^WR`$(1=R0Qqydi&CKgZ?Jy% z%T6m>-Xxj!NYKW@d& z&SM*}U$W1}(_4=qR+ujkC9ujD6A^dtlg2hT&)Tk_2~@w!=;lX=R%r)3J*L_RBxX{w z&as0g5@9rEh&1UwJ?-Pfsmz*zCVS4;4cK8Cdmn8+?wH*99*u~MFIQN}*Nh||rhL0N ziZXXjt6L9LSlci;4NjE@h8Laty{X=>!cu((YHFGE%~GwW%s>yjsDrP7ArNhHAKgu5 z(ByRC(ca6b5zF(mC`8QqTpf9D=-De9KA9`%gR0-HeL^Kcp~$A1du8pJ?Xossk&t^h zRS>E&p)_Qr@Zi|4=ZEd>2O}zwvBUSSc)ymUW<3sFOn*UXEGFU*2yjr#eK@Y4%Dvv1 zy2qS8HL%&D2_?m&XCT){db&H`eoqy9ce#u@K16fMY2&4bLdgdoI}oGJOZ~zyx!6RX zK%R*sLqD$@LmdgZi(ZwY+I~Q zHR+_co|!1;VXxfa!G+Bc*1%YfaCpO`fwd1$Hyf0dnrD6TjA!1Pf!>j{Tz|0GKzH!0 z<9sx+u-+jfe6(7whZh|*raU23E5n*(xy~|dcW;tFPt>g+w1u&E*<)G8Mw7a1#)JUV z$P;?D)8Teg9Iq@(tA5=Wpz*z%d%Gnd2rHf{W!Jvxm0gne^l{hSUW-SHk5)x~=6%X>v|T@sHf>X!b=py8zSq`Pi)4qF6l6%(?4s&~=|K9*8|+3BQ8^b{dD zh`MS5&x*+|Iy?hqxEZA^jx;l-;eldOWg}9F8J@2%b8LVP@US~@AL8w}wdOI*zCTY0 z>8%ZCli$ZUC!@__TvJTwALy+ zrNzIn%+p89gG!k4zWvxy&UWV(`mIG=mU%0B26WE&$bmvxWBWtbBH%`cRx7SxrBPd+q=mF#z&6LG5tQV#MQxmGaPl5; zW4`$4(|B5o4_C>8;Ke;arpIPrKTl<{=&?zGw5zF8^m09OKMTT5a<`>^xDErE9U)YP z6O#r5MBUh=$Qfv_v8yK$@H=Re9um1s)54?W2LxrDXwNUQ4G z1DuUCf$aP?w?;InAnRI+!9q44T9+~k?~(IjFQY$Iws!@Hy>_yAHVjwx;as+=GTH6f zw8}8>pnjT|o!ZE=VIDY)KaCH;WJjA0eGq%Dr{&C(1&H4Fl-|uWY3Fuw*OE;Jk%kQb zf+-Bchin-|ih=IWU{NITJ)md-$zyQi+ame~+AEyFb#31b_Ej@2Pq9yrFbf0 z@6NymWMGZ*S@z2OIJBK~++-&q=B-k)_u`t4PUZwya2^YR5TX%)T~2#Nb>7YSU=87RJo)*`Y` z41?JLi?;g6kl$WRR;~fhe4i|no_xPGLP5vn50$L{%k9}E?jgZi{dlnLi>{LMiBSnG z?E?+R%$TZf50k$vR!?IUJ?UGyY2Yw-fu1eli>F-P2Iy&dX*RIP+^G+oS*g~=EfX`|C*E7>C5pKgfo>Eow zq@`Q!dtYCZ`pRpZBxnZOp(v0YMMW71oAFX9erinPHrmKWG%XAG=^b}Rghw%{0IqQl zo#!o7X$P5OrU;GY`(h8e@yy&a@qtXmZm;YJroynSrZ3}l;3FK`Kad?8&rnz`+lD-) zmUUb=TOml@UK2s2qGT;1mX7FS!q}PnomHkYP%a)A=X)17(krESp?(BK2cR)+2lD}@ zF{EqJ9sgGcudNzjVUH-OCdRh24HDPOlI5RsxFKzd? z>@c=cEROG?WA{A5QoQsK>{PiRn~%01P#K=*tRrf%U#q@)2N2)9;dYGhjXWzE8^q02 zk*L_1h`3t8swljvx1nA}V3o#5*0x9pKv&RQetL)WK^Gd6cXOqcG0$Y1rfVy8&8L&V z(z#jM)P`v1va5f3DOzh=zFH`G?T;nvvDYSMplGt=r~XN91AYXps_DBeWK+>%qP)i_ zCZ!%Fqkps|jnUc<#M6}#rU;hv%|erxT$S*^=$d*xz*2>z!cf^h6nnJ*GgNG>K&u+iTT_j-J=%J=8&!aF=WYTgXgN4mSBLJJ3u#}z`#hLeDg-XvF>r+>M?_Ml(?;%RkFl&CViYaEl9 zMo*+SJNO{j1`~FZTDiGDH!H*0q*N)%=$oN;wO!y+&bCS^X)6g)0~K<%t^HE_)=>1( zXkDHwx&vPB)MxudU$XT~>Gztko5NO10DjB%>KwRAk_gmSvh`dgpRJ&)WAeroWsJ>KX^WTZ{*pHo zYV;XqkaM|H#ubm(@9)^ec^DZ#O5%?6QQYh^q`@Qda+US{l#RDEE;idF@Q4DkP4`V- zu?6)JS-QH*>3m(tV5O3GuNUQX^v({IR|8#dy649(Qdf_J$Lf=Nchf__T)P#rIe`&b zKlgOjscBd@rti#Lw7B%e;t}l99bc~xX(Ib=h70YrW}slg0G$-VPYY|>`{qrx#Y^o++y5s@*dC%9LK4QS* z=BE}Mi!3(H7I#sQjkxC!7KF({wD*nC9~@Xu5uRpBjKF|GNZQM&x^n9+M(g9LI+}g$ zp1vjHCbq&ip^;VOS*HMt6rG^mD#hA!0|6>QZFEc(xC0GPYhh`&I5cOXaz$(fuNe`a zi`HWSR865y;yJ$mmS=q?b=r@RR9$J1O+L(^i%}TYLl^G4*v_S02^xfmkdy**ib!P^aWxdE4y_a2`lpOSd?UJb44b-6 z9gd2ZABd-gA@=xAhoL&R<9(3RnmY@^fIrN~zgM&B(vZ*f&H-Q&-OM5l9!G_s0JvE4 z($e%}d5!&`|J9*e7C^U|yKAQwanlD}2x*F%Ua^{w6!iscVW!hEk;H$!zxq5wUL7#f_8~h*!&36nP?N5p3$jpQ67yn))i4ry6BBS z*01Kjt?YYjo0+ii(i|KR)3mmi=Ui-tMe+ByZy zX}4F)8^0?0dHSvIrM`v@vKIeE`bgpf291>-q8uEOW@T|-pdQdKd3G|?N3p^mu;sI; zm!-+3P(MrBG|5Kl?^Z%W)p{Bp=yQAjiK?7DR1eHl-ZvnB9IJ5lt&StqBxEkxMPIcJ z?ekJfvVebr^M?FG@gce~gj*=%+wf93@7udMxkq?XLi5+desu~SPEJn*2>NAYW{U(Z zt1pyOu1UjSewl@D73%jpwXJoh$9gP60`h6n`jTxEKyJ#%$PUhN+f!mxQf{dfo$)(i z;IYdpxXLW=t|+WOg+BO5Z5{o&n`7szOUO)88M}brA|5Q{?5?vVOq0`{Y#7hvoehQI z_RT>4eYWEAEK$W(vin&w^5c$M`gis+W})QJ#OJRk>iDCAV&hTtg6}gB&-*!3my3~- z%RJu^FP+fBmRmR)GZY6zLTOQ8SwDstZIhUGIk0Bsq*joo>aE<0+?>xZ(%`?$PsV^5dfb@u6ad6|v#H1()r zHuw|QB?9v_96!<3I$>!E7ZYb~g2J>v&tx|oKyxP)HGPP?-`0Uuzue8{9~W|XLN6V3 zzof?UD2ygJsUs-N$u|>;eqdC!TTEzxf2gz_Wxk+}X75~=RGcxHhb7VkkzJ;6AW-)g zhK6Et$rXs_j@%7%P;Kk|62jQhJKNq5(UUIM^O}JTC@Koo-Oiq%j;lKta4z75dRwX3 zIcN0<*vn6@@2K=MERaoH2u*LfAxN5!%R=R+ zGBysVEZ8)2nxJIcnf=QhYkKwi^jD03b(Bq7r>ntBULN5U}tuJB(;lnYVC7n7n{rcxSJU5{L$;=c&zy zbCV@BEXTy4;`p(2$54I?MoLf4zTOcv-!Sg!%M7xOP4K{0nH$4eBn=ppS84O)84lsdg8)mzJD~*7o z^1oHR>%H14UAxw=1)Ldm1wGULJc}ZYk`QV=jN;4O6$`!>d3|*WC|%fjY^!dY!aJ8m zyUzR*-ql`!28w!k)z;K7IY5@PuA?t&KB!meN?U|FcZ6&eFipdTQ4Q>g_!{6H#0&z4 zw0FzTHd%{UN)p<1(C{JtDcMf~DXtBHU!|)>y$9!=F`-6*4Ii3#yaI=2y9nkZr&sZ$ zrE+G6sBJmyxf_tOz{`HQJHC0s62(@sY@}b0q%>fr$a~!$A+E4^Lc+zaAU+ELyo=iQ z+q}PpswQ`oavs+8l5Z@!jd}?p33`b5DeY{WVjeD@axg#P>4cCBPjuf1Vk?)j|(w)16o3M3Udgi>g zv{mW@dsa*nlGD6_>hM>M1C^_Jm(eCh`C!GXdLYdXPM3uoNX%&?lf$*T(5=A1m8#3n!Arq?{OAFGV0)&){ z8Gg9Xclx|E!hU=8c7%-1qRfjQsGAS`iD$lexNMi*OAz*2z-R<4xmAE6%4;=Rg#B{H zME8hNZuUKsxkddr3NS9hWa$lc^4fa|y`#~~ol0SS64VM zLmc@MtZob0Okc@omDU0oERxf47rFxkp=)FSgqr-UX7c<{LOI`}I-Z7~=rM19C(>qC9m0G{+Z8@ z-5SDcS6(=IIBD-5r12_P*Cl-F`jh-t8I4 zrp<)IZGC%KVOKW<&fm0#u5uoVLdEa%L zJ<5`Gbh2?OTelmqEev3emw!DDGz<7`D}9%_FJV;F*xJG6rk8%3BtB)^jLXqok-3md^FkD63u=qXX7LOJiC%KwJ0>e zmt`mBawt-KZFc-ylV_-oW;;Y=xeIwWW9h5GGxcM1{{qdP>?JS0zgETdq1_+#9{IEA z^@!xIBeP~nsvmW{@%6;33X0+YpK^m7fXSue9QJHWKbW}Y)j$d%#ST?`>vc7m85tCK zT+c{+U8q3~N61{0WrX3;Z(<ew*5cPqiGMT$&BH6R`P1EU>$>J5H|vV>kF-~lF9sG8`HpG_ zsB<4s>ObOlBOGW0d4A0Ulk2lzd^I_6|^)m zo8EI!n8tF6?=`|RbG*s%_%q6T#%$lFs$T0o8)8gCvii)I$7~edlE$x@J|472cFCYQ z+yA@imp;{7<%Y0*A;Box^>a?m%YCd;tm<~Zz9 z78@aM6(t67H}q!Qv2V_+yy)qGAo4LoA+qp$naL@oI`E4(iI{P-?}Ad^3FFSPr;#Wc z9!Z-dnVB$~?kj+L-hf9vf1KhUp6S%WipySos;+8n<#M>pzoxb}$=!HkzpvPoRS=Di z6gZmHW?r{%JJKU=dDrP$ZseEe=xcPLjG^#eCo?V()mo$>RemCFW6i1Me)=H@o&>0K z-jlvz(!`+%Ynkr@GLIYa=lYWeLf_RG4t)MPA>1(e`){26At?`hr(@XOp*gSEsa#4L zN9(v5!`oEP{I!xdT(0*>Gr2nEO7*Oq>+$_9wV5jLk5x%hL6m`d#+xud*UB7vbXGaC zG}&b0RiRxUSL$D8@)w%Ul|_VS2BX;U#!5ybsaoqR5OLerQ604I2{EGXyn`7G`)E1{ zF?w?-ftAiNW9HLbcn_DayR)q&R4_V?53EV%J-792TXtgUxL3+wkrB9aJZqoE(@cdi zy>*gQjM;)?BKERr0vWjoU-+nu?Fzi)htpa@Iws#Tjs$Zz4`qf|s})_BlCKr4X{y#8 z27ZBlApTaH)DV`x7tH(kZUx81qFgz)gPY&Tl#kU1_K&r{Yw*w8aYNLpSO77V z!h#ql18bJH(`K3U;`6 zx`NPDLtNzgi5GW8f>uph0}OGp$UZKq(08yNxYusZNsLUL)^updL%kH)#KwgL==cgi zyv130gU-dc?qdGK1*XBA{j|;9xd##i#S$7n6gh;PN;Knr1VbQcZGwx&=(y>;T-Kgc{Aj>L{mpvm!+v3D4(Ll4mEO0+%kd|ew zZet_&uCjRmf`^BSLN)}=q4L3|-ZFT6!&caCrhK1DJ3fwx6)UjBbs=^6O#mytX&`vp zS;mVA+j1}VrG)Tj4Tzn~=7*NVB!Zygz5=u$@_mU%(Wx6eS_oV9)pIv7M$V+lypkUb z*kZfAZ!3k&BcHwcZxSwbB3k?d8MRk9+V?xONR~;M+)QkKR=&mOIR$qq3Csb1XO-U? z6h>^y^FK3)*aTcd#63D^JvvYS(8>{c?wNr;TDceuIt}`Vj?|u`o9KSESqc!?uBRS) z$SlX-8;~^TPT&ubN=buAu%@vEL%}Br$~;_xnt46@c6-_UK5XIBMw?|%4PVy+EBr{W zRm{Y9-wVJvJWNeA0oo%E%p*x~YHNQ6=Cz8c-^%dzlAuXiR4@O1N`5GrHs;)iG$9Pw zW7F+(p8!9k7g3#kgh!)^6Iht6pve5(0A*#~W&O1H>IWT6=d!8`b`ghe?#}5E$*7(c ze%U5KZ+@o+;1K^LM|0tpyo`v%-6H?s)CTWl>(Ac)W5BVrCV@9x?D!}EFJv~}?^@o# zs_8$)zh%QX*A`gA|lp8WpYy3V!P z(bg>z;nbr-Lwei9a8h7r*pse$dQ1zzP_Z{YaW%kJ)$qbg%or23yWkpnAviM!fGOQN zet@3h%&yCPfICO@BLTJNi56j?v_e1ZgY;|zQO;}i>X=ic@62nX=>Vt$E<1-u^$0FJ z!zs%8OG8mrLDN}xj)K;G#b~hIVZ)g@KPF2*o$d+}iB!4~CvZX2KIA^N(2&5(Ho$9) z%yp6Z=AAuBSi+?b7K_a+GF^G{aRC}=HT39-5DTsdB7oF8+(fj;H$+d;0H1x@yRp1=LIyuG~}c)n6BqiT|! zI%s4^8Sxy512;gi32&`d?nziJ2$7M}M&F$F1;%_tHe(q&1l7T7JtRHF;h8a&V~bz) z;)4z87F4Cg-Dl#{X`Y2>%)+m_N1N-j7KDbDht%#VPmV0lWELcV*tO`46CyD3TjBSfr zU}PZKmk|Z5nBv#94JyNw^Ex9Kd$HF*(`%df8e+ZXP%sBCbTY7u1hMty?wCRN(nqC@ zqD^(cf^*$#(rWSYD&r~PfpJ9HZzwr~rYtUYlfRNocNb)w-Dn@z?CU0_RcCVtVVu zXtXD6?e*MrUThJ91q|n=+Le(uX!SB$_}EZg67a0xP|i!!txpit?>MkJ!4BbWnEsoSrmz8mAh!)7}zT#G*ZCEPdQ|{N>=wCjyOM2A#My)TZK(>YZahq z0l?{ToAJc3f=7&Y;@=nu0E`PmFSqS9NNU5x?$LDt>&CShoY z%6es#)orE}U@qjq7D$f?(9%h)_sVbN4F=Y# z_1}tF^HOh%+(cz z8LeKE^Rp@awN&>Kau}J`D38`U(Hju8ic|iQ>AyPb_x&}lz-`YP^grDuZ|;Bl)o-A> z;y$7yyGx5T&>Rc^7o|4LiQ=V7M8r54*#QzfCTuD#sp; zuW-JG{Ejav8at|d{L;H7tIONRu(KlZ$ih$2UjuG!r5-mF1@f?u`^u9Zm3(}VqOb=M z#J07iiquZz^p>dtn{OofdEM)ce-_1*r1%?AE(y`O^J;qz#D9+;S=@Cw2bSc*y)*d} zgWdfVcWj#18|T}ePbGZYRx*~CJKb8s`f6im{QbU>6{Y0#5W4I=x5$9=@%3g(-Qt)X zBMWXPERq}G-~F@~F8i+GJZ_gwP!?&uz4G6Yv>~}WI2skSo&s-U z)273GmH~HrR!NV5O7jjINO$9%s~lxIU3#noH>R;u=-+xUq=O&Q%?6~VTn3`J>1=6l zK*S_@{J14J@n$MphZiAr858AON|yy{r971qKzw)BhmOx*C1%WK!-^tW#2g6-RvaR~ zf0}ZSf_fAYR#22;By@Ie2|!_yjdE<2GUAVXV6R5FH*W#oO5`tDb$A3w!aw zdZ7ydZmQ|n@AYyVQE5_fV5KZuUVBKum6-M+haPEd>OMhpEPM>&C`;R(v9C>3%B=(( zcC|EMI-IC&?IkU}GlKhU-)ZZMUI3HO4 z>Xc7nOHf1jSDRB3pq)G|m6uGn2%Y#(zDN)b9OJA{8RlvCdc)V)tQ6O*Vl5ry9U5BJ*f(*I2E#7ECEwr^@?>2Kwhdk5HVd7ocVKvYmLu@gB9eQQ~j zrcSqn0`2VVevfq>IJCTs*Xr@g<~;SRiHku%I9o!{vhI#TY0~+mkY!cEwQ}BfL-*~n ze4BCLkCtYCD&cGmEQWLFKQ%q{BWXmPx=Pg^4_RDnouGs|4lo0=pKn%+k1o3vr=}Xm z^Ys*6+iiWa9CXgp1f?S!J0BV0hR3JnxBRa@2^^RWA=h?DvK}N-6L?uEB~ici3~V2J z2)@OLSs~c0NO?Jk$xF+Rzdg_Jsn08!yUO;!w)EY)*(gZk9(SVK-`epshzptMrp_Ou zfjH}vX*fa*_T3!QHIQwV-)Rw6T}5fLe|B$^~k*Z)?FeQ;QKL`jtgbD z_?~NF=rCCDQN2hd>(pJxCNqX>z`4?aE=$ zw(vzYpZnwMk!dadYCfM2m#xN(TN3=wp7NvLvX7JZOr{{}RYLQt)U97xR~@T_$5C8v zLd5n?yGfUhx&!e&?I*q}qJ5wGK5;CGwnzINi!TRGkv8ifd4V$TTxvw+xRFQax)(Vj z!{0HvbPyTfgW@Cz0cO7$FuSLPy?^v3iPmt|)`?0igt-B;VHka06Pm!E((@s(i4xB^ zqIYBRBoBPRGEgW(P57kg|L$&(A@6ql7} zH+0hkY@kL6ZXGi@S7P+>KlN#KzLv?B_F;aNP@@NBq-F2KZFvFOm*FuywLz z;%S{PmX+>SA6Q;XXFYCzpgvCGfEaYI_-bthPo${b{G#L7Do)R9efAchaKE5`duRHG z+m-ip=MrA0ieKGz6hNLwO~u_N=rfe5uX0wWc+!#Vf~1@D{S z@+tt*FX-fS0jD}$iO^M4zvZaRveJkbDwzszXa?GD!=MUEhuW1_z;`z6Fs@1h7v~jC z#5d=+?p^rw0ozqM=91KZ4g})O2FnnYq2eimxWI#R5`YeBArVkYK;+I44uB>mJ=25h z#928!Tq+RpE4wqIXb#V86;t)E$HF-CXhMqoh5SZS-m z#JTmHhx3c2jF()l$A!+0*-uJxG*x}9n*~5=g;ou^bIDanrp!c;sRUoIwG|Jl1y z?=HE;ok3NS(frWU+qxmYV^K7*cf_OY@IV?F9e&s+2hEleK3Z?)Yn`WFP;R3&y&dM( z-5+S*MUH0^#YeT~rFC}>;Q_W^gs1~}O4U2NpgimxxZ&ea%jqg#0cQBI!?Kr3AuslU zK`&Q<&{Ar7@WITtZf*DpqF-tF(yT(jWTEATWw+T{tg_EO z4n()zI%f;~5#hd4REL=B{B#7zka$+*6YX2U5!ox!Gwpq;V$|jpsD9Utz5k-RPQa|&#K$gX#SPh-UIj5W68bb!E1LTq~2+a2tNa4iINg~CcX z7)&k!at-}uKmF*Mf#=sIgmR{v#O}SeqK2Id7loi0^^~J!lo~S-xIn<>dT6zTKc#{1 zW28}@#wSg2rhFvL!=l=v1o)%=WFs=2xCoWO!-t{fLS1R^vR9@6-YqT8xOfSe*~V_Q z=aqdcS8NW+cpZvtu1gCL@xi{R8mwIvAT*(gfY(9qwp7k8-D;}OeQ)>GJMvjTzBDuZ z!*cK)SZmvUTArg0KIGy0Z-)d{=}xtEl!P&#)Ts5$1`wWiv`TgX&gU={R(v9w1A@E` zDM(RkZ|b4aZX5@(5h*QS*i=PWT2ni6sF-XyDW|m{MZkvBG0NLt6f!zZ|9ISMBxr+p z*h^y5m)E_>&SwOTk2pLxZ~JP#%J?GSlm=SyPu|uNqt%P8M!WLpro+C#S%#O6c&b$! zQ8osa1CYEYbxV5Z{9e`ME}Lb-3v!|ocs;9E**@uk(zi=27!y?>K(gFAC?GnT(^0PK z-P1B9rX6N!{U4srJ1*(%@&C5(P0d?fEl1H!)6&#jSUG69Q*(eR8kHj#P?}gS8dobv zrsl59+_-Y0qEecggUp>Ek^{PFfFlKD^gDgNkH_!tOyRuW@AE$AHJ%4_mw-GcG?bDk z7|D>_u&c!!ts!Id8^w6aDy&yznAjP*n}=TpHae0Q-v<-t1Xfe(u)z9vfJ=)^$gPa& zH`L%AqfYE(!#;kX z7sEiVwbcdM3enPGO4b*4CbcABiiq;qoI*P3jc9DoMftb!1hBJ9PER?nGlm7;k^i5_ z*WcBslhVK2LrQ0rL<6Kk$?epOrh}xFa+jQ|wa^&wl>fQMxni$Fa8VTw1*J(Ife_XwG&s_`sm~ITD#ONJKS=mi@_0c`_`kY+l_bfQ3llp{){3L^ z-IcF{#Rj%zG}kB*{gz%qH}}Pga4G3Nh;t;+a}fu;x_Iehh5Q(KS_sTSo06RjO%4dJ z1s*9Y(e9lSQ%j{+oqJ9<`)$gd5cc!oh!zl*2JcLUdU^ltVViUbWcEKsk;CJ_my|7G zDwRonC1!HVuGoJ(35|4$n6X?zw>28owr!qN=Ykn$g|Ok1=0Ot}?=|d8_!m1XS~T|y zEXxtjCDpLdxOK_%UL6m$;Fx9nB;oCpbThODmC30Qj;Srz+c!bYy+|1e#J6*@wzZ4w zEzw;*;GWnR4?g{JsSP_-HSW!G3w&EnM4;8$ufcaR=>LuOKe4YY-#-B=Y$oua(I5Zr zIU8DGSxJOVU(w{?n)yZY64N}2J4jRmJPT%Lc!9juMfwm{;12>(&&Wjj_JcUX2wdi?nJO= zrw8F=WclM9`^I6<3wD~drI*fkCqJ`+MV4%3+yD1@p87=`pXO+z3Ou{t(aNg)K&Teh z7X@|>;qv`ad-&fAC7<(l{zUEfx6}NdL$95>ki?r&+uV24QPbh{gvDLcv@kT#IX`Jq zl}a0{J{DXjv$geuI;vN-H1Yo#zAf{m0x8rEIM1$Ry~$qb<1YUU_AT-pM_pIGcs5Q| z-n|JPhP#M-kjr|RwCb7^q^4IcFYb>X_qhCp@LbqO4kO1Cj#zr_mI=nyl#g#j+6UIo zF@=?lggA3=NG7X%`e4&RpI)-J@e-JN)%xNU)ee86--~AO7mroY;$#N;fNMZQG;H;4 zPeHQapsagQ3x7A`-%D?&wtFhjz&vM3+cg5j{cH^iiRl_>SC*XlwlZLk&v|twmRAN( z!0)2MpWR0H0XZUB?`#-Nr0r^RESL>U$&1)&n|h$JG^q6a7zu`PwfA_T!yujFg@K(T zC*r=RgFf;8Zbm2QG}gsz*mt#KX9AN7gk9-iwefo7z_+_dB#vI6DjIqK9oA1Oj}_J{ z2x7nq>4TG7D;lm{I#!IP{d~O>G;1YWcx6ee zI$#NjKuW9btni)!Wwb22^;iHZYeE;tpaF|iaw`;ic7)@0W|da zrFCax-c7pi;}Dl5hOu_W)6{a?p}4dhODt%i@ccgqc2udN$s6)!Sx1E=cuoP1N;aOB zD1cppi1DEU*5+_wO|?m)O%4wO(a_y6{RXxB;m0IOUKO;**tYn?p2i9nt5GfGPUW1h zcv*V`D6^wnW7*YvcU@E!X_-fe&zMVZZJY{tmt^6FqbPtar zm0q^W`XbQ`ie~q)JZ|gj_MPJ_+B|Z$zM1k3!(`>GXx$=lotkW#t>~rm4uibLo-BU!~Z7)8+hUMGA& zy1TLkT>fPbH8|9qC4|?E1Wt&YG<39^^rLv^0*$!gyf-J6FxFXE2{j=9*#B% z@}a&%xP8K1qMa2m+RwoYKB}Y3m+nuQG;(1!<+EMvy+5jNt^BrdBXIsvTGgr-b!N zk!RJf(F1CFS)M@R->YrS2v=nVUN2iUMhh9A?vXP7eRXB@TexU@?h4mw72{j-u~zNq zd-7MK-B`U)kxAp{i@6cWQ|`5}uZB#4a$cKL71OK!=cS5wqKXC^&lF{uJ}?{}mUNBf zD6p@geHI6v{KA#2G^o7RBZt0~6~@|V&_Qu0?=L#Ii+x@rZ7#=6kT^Ek$O3B0k}T>@qdcUNv1l^*n(})4KV|_Ht5Bk_L$b|jCKJa<&*XgG z`s&&OWjt41zF81Jv+9H6+D?T($!_=RzNb2c6Op@k4KY= zCm=d3LFpzpEy$<(E^*&7&!aHMY$zY}oDKRf&tY>VTh7Q%5kOc*^#qlV(;WS>juz4y zhxSpR!@2&OEwIzZlof(_AsBB=mq56eDh{J_!!ZT7QjI!*;^qRzTdmGw4)C5E*moLY6M*Dd}B;8N;N9Es<9H`$lmjTP< z|L&q6JpvvRIWV@DLn`w~Etxm5X}IygKmFa6Ye&O(bD9v^yi69IeL+FuQHA7u9^QSk zlY8mXr1|1*kv6ZCPD%lI7oYx{r)W9JH)$_PNMZfU4OwLA+OwAgI0#KRe|(R-!NuEN z|0PwB%3jsNGhDedE+ioS?G#&R-BuE$La&p<+C47MJ7$MtZb;U&bl5W>V1p-F53y^OP?M`swpSV9x) zm|s%#_kF8QY(Gx`CXr|&pD8{!0n6nc+qjA?Y)Jq_{B@K~f|JQDZ*~&;VtoBdG$qRk zQD6-{zhz!L(=m#49FPXDaNG-szK$DOuPQUtn;S8DPq(knd~G+O96HmCKH`75$FynT~O;zt@6e(pq0E-d0-S=HRdN|c<Jg}}w$8lsy) zfZhKcTE*pjNg|@@4FscHwi5@U&jC!1zRqxn=I70t+}J0A%$ucO3~azlf89t^G*H4} zV`l@C;G(=~oeBDei$e#dQ!zQ~_q*4B#k~*|RmIE_Ppby^Tqf87>ijqP1O?s-fgc*K z!(AFeMP>mNok4$*BT_;&`pmh8tY>&p&2fdRykjV8+sTnQ>Q3c)LEn}rQh*z(1hHof@LCw zqa??S57BfGjm$3NNhjz2N7m#7`lO_1Tk&GBoH6U|`jX{v-G1wGVPhxS54dHks@^xWvUg=(01moj?AZd>y}KTJ`w8JU-f@UwJ^e0i?db_&U=wL zQ0D6@=MSmJb3+f4bVb{83X(&$bm?eDBq(RO2Cr?A8Ay%zC6y9SlK*KhxV7BVkqQ+1lw`a2CWxKsm>0a5n{JZo^ll9l*XtonICk8^%gS}wSTZNK+ zlpIkWhG3mWsVkSI6huG$C8a~B1!|RJ>-1~8hsZp9Y+3nFXwtgHW4e!p4B6PPY_n#3 zaTQ&zkIZMw8dzz5J)TQ`grinQyi{pX(2+^$#=WR^i60OmzGsF)$I3VjxAy2z2Ksp* zR-sg2^o>f?R|h7+T$t@2<$F;MZ`rA^^jxlA_N~a>w7m3eaLtTV(oD|3B&G3l2$i$t z!6}FfSiZFGaKeAVp8n@gv$M^yAVB4l?R=n)*b8o>@aZ}{u2w6G2G%9W%ZMDtmQX7m zS@WNIHew*{|s%syKUS z<7(n7IeE5iIY|ach#*L+US~k7K?uu1BA_yU(!?Y)s2q}qU%G%w*!N3nN7Rj3#|P#| zg%_MJ+Z|tbG}TFx>AoPh`{S0>%MW7GH(a8NDvV{S8vuwTdVvpHm$cT2v)9OScSbrS z(yvf|2U6=(>5BnTha0?7IGbIMys-YDJ5XNF4rbQmRkiPo3K)@`6dm}y_64Ib$Ihtf z)tSP?T{^K`qvDIaxdFF{e&elWqMV?X;bL&%mz0EnOdvOU-c5{8A_g4~B8FLLX3;|Q z!9>(f*xuxqdz=)GXBe3*1Zdl_v(WDHJj>r+PW_!Y%bmv6Jdb?$7c$WcQ6sx(L{}qk zbL8%+qwX|_u2B2Cop(bn3!OOjcb||5X?5e`BVJ-xjb$4$nI(JP^cFkUouD;0O#uhW z^(lZs6-^BdFd~_RoY;4%GjKO)5z3>a=FG610gjvTQhidr7;Sz9*uX%4wc(H1-8^tO zkMo(N_ke^a*(hf~K2+MO(RrCn$5}!HXzEiA6Uu&K(+SE2YUqq45P+8$3bK8YAxoMm zVaIX?f2^QWjfAE>-|!FME@KH9uouzq#)HG`Y8RifSz2S%mt=0yt0 zb9OAvo;ZO&{D3)JBHw?hrixxc1GE0-ZCQ0!s|AK@SHaR1p|A>8bWFh`LwV(}ZC6u$ zK+)57SV2hU#{7Lkxv4l2$v*NNKgZ~MaJ&7XV&bt@5e<;2V67N)u90sc1PTSS{dJn4 ze+BKaop~#%qY4;O3Cdsr1XyuCkGuKWE%|9(3sNV@UQhAwp)O1zJxcu|9D`)-V*(Ybx0x74Lu3{35*i+G!1^5e1UBh$c=rM0e$dXUCzU0v>Mm7NR)%})`+KGfzcT$8wf83>x&mQS$0JIF1I?BD^T6={m#c@_hI|`FFGS(I`mN) zN4)|+NF+;8<|mOd_XUl~?n&5^5(2C53kwgY2rg|M0CAWYzhc{tQ~Kt9MN{T3D~;Us zfQsT%AT|R8QukJIQQ1jq$v3Kj1IWfCJBdz0aQBo+OlLBbn^ADBxegStoQ*%WMlW11 zLv%*b{@X+-Vu-0P@whL*%1CH4atpqL5R?r}-#{?&q%+dI$$QvLAbY>|lbMt#x!<28 z;t*L)D||tAj92BEtprsf;BF+elm@KWg+X}&CwyG>2|tV9F*Lsv`D?K7z;^%5SWy^w z^JA#Z*xc~d()5Q~n;DuT*|?q*P=AW?kP4~J7?6%$urD}HYR5|2tds=N`1pq_jsEJ$ zd}J~Y|5M2)g-s)^7QfXtkZTjUvZsA$_C}b3@c%S2>#zgB2Ay{zW9fdcMZn#WXj*m} z0}|o1$AK2bKCvaZP@;MrHJZql;&5&CC`^C&c;sCOE@d-7eWim+N8qWf3UqSIX#1@z z3C*CYkjZipp*Cctl*4<#FVi0F4rX^Rc=gpR^Kw$!U3)>XP)Z}ap-u$rvIa=DfT5~+ zPrTf8F;o!hlnAhb?y z2AHDBE}K#hP30rfrgR6IX^wN!_WqLJ=&4IvBnwsJ#RLx3k)B^Dz$LfYuR?n=BoI*b z+i`2fa?eEt+IRSbNmlffku9T@`ksg`?p+~6IsnFD^K4yIW!`E|a37e`;xb=7;uEN~bC79)DMA zuZ#9Okg|>ixV-6~l{c?Z;o-*9h46u(`*Qo>Uf}vHDBbW%AcC=H zxNfVm*`?U*)z7`ybe(uvmKZKxy^tzrke43AK7VV4ehf12@^mI>Z*6jx_XyWD#LxFS z>`8lI)Q8&=g^p1xg~eFlTjH{IWR;VY({sUlWiDA)So)=ub(ONhMl&LETWypc3EJe_ zJrvEJr1>O$cv{X2fFs|C^34%6-mRad<72*IS1W~?E=pd#+t=uLw^)1j|skR@xV(Fi&8sy^&qdwRsNWU)u z?tZkzT@fYtW~9lF%U%vzJSVjnWOZLr`;}--Kj+*#0=#8KS4&XbZ-qJtqd96!?uHC7xCbzcYHRBeRx}7}CmdVTIE^a)#Eb5syw;<=yDB_{^ zYy@^%OA8+fcD8jT+wPiv?5nNr`?9z(hNRRTLkr#Uv4s6cCNr^o5-TO&vBzP^LuKFHtzYbY%M)iy=!f8(1Rm2=dIA=V1K5oXHID;o$q+Bv&W5)0F zdX+WD_d~7e+4x(xdu8&mj;guCZt8_A$DZSu}XD zukY3V)oMC6@Xe#%FcwytcalcRC{+V-z;0|x`#LqGhZS`{90TYS`dRZnKGadUd`oLe zTPLA$9wmxMM}G1IusPQ{_v{T_dg+)IKAkY@>acgcl)vwW&^l_%^1gpL+U#lcxlb2} z;a-(8q+Jt;PWh`5f9=xxD#usDvYlqJ_sR9@ZA(_Od;1Np=-HoQPLFs@b&W%BP;s>@ zuOAM|Z$t;FkE0pk{PNW;66y0olc}g9{G`{S8%u@u-nSI0RfxntraJXsYtF089gjB{ zVPV$Vl#Tm*ouQ-Rv#F!hPeXMeKY<&&`*-Isnpb&T+(QDjhH>m=^YeO}oL#(f{yFkK?Sb743FQgKcB;Au#iD4uKVMm)UMlYy!Le06Nok^XcXyKH$@`H9qGQHr+JuBkd;Bsf8 z#ST^>Oar{g0y6`q-rPHs9gbIE*E3c7LClX@X8y^&PRuNZj`=E+CtvS4B%VAX@fy_^ z|IlH8!AnxzwCc_BEot90-+iS=5?oVnG{%?#NKtq)p$bw}B z)6YLkeLI5^O@p;W)4!va7lUd$V}&y@y;Qp$ z{=fC0b#s9ELgnE`Hs6Z`6nOiy%aY~GXb_Hp8$1NXL&gsgJej@MbYCDwp!52Hx9eRvY!akr8u?B)bT(Fb<$1;w!H8Zs(FGIgC$)E zIrv+02sn@cY$U%NH>tRDt-ADLK~D)UKn;=9j>^PKOfG(j)SWJQJEFE4$1F;gCh>C$ z=9rtp@sVMtjeAT$qOsp~{xIfiROMo03ZQknNj6F+n5Eiy64_Ilnr+d)DXkf$~1qq{e_MM*h;I8C3^O-Zqq);oq!E*corJ;_t zPx;qMJalf#?d0W?o{q5&Y61ReCx732^MBe$!sIrKocHAfzw-KU^UGyBX5+0fEKF(g z>Y_2mMYqyf;=O2*);N8NzE*IPHpolRa_fC4k>0YjetUIa2Y!#OH%vSBbwVW~Tk=Y6Q9^;J zXX2OC!rYV_*G2I`?K4_-`P_5x-=;(-no=H#4(IKaJJmZ})bX7fxF0~%4H%>Vloknu9S-WtiK8N3Qg zYUd`&B$V1T{{6MqZT^HCOO79YUJuzc^5ZRj1ylG->Jgd0%iSBrKP%CAdn+9_x&Hru z&AxHK$sZZj;>i?UC5K><|GD;oa)F z15xtJ&+duEa=bCGOy~tBgZEyoJ0Wsk$xoiGSdQ1!f#o>%|1MKOe37VUEU?>p$(+k;e{Q3y zs{vw?yz==n{MVX;n;M_wO8z20c^~>74D>Il`4%wAK6uZUA%OAw1NDJrIgkI)4i+$} zr5ovZrmrbnmt|fP946b6(-f54N?=5^J7D?8jqjyyBE5(0J@aYP>1c3Y9dXThB$6+G zkMk!lpBFiZzka+{GN~`QzVPT_H8%FahauvJXithHMa-^$@eu%%eTi;;dieLArhCGSBZ;&972B3DW$VABmJq+BwoG44fINsfilKeF zE&PWDSzU8n0AD%%(f_W#E2cK2l1Gj$Tl@!18;-Np&uNmKl&>VbLHPZ44czx)595^< zBWEmMi+5jJF{O3i^4W8u4+r!=<4p+WB`AT-#+c5x@gL+n7&jU~mRD!j%l#heSTLp^ zL}n?*x)0mcwREdq`oY#03iBk=(o2$2hyi$lLtYzfDw$k@Eoml~jZ2)O12aPxPr>d0 zygRKuurlmP)oxpY?ppQpncr7OWcF%%O4N~M1Kz*#*dM}+a-tjp54Cie@dyzrp9UU% z9;S0|iN{}#z;j*$_eNjW8UZyB?OWeHxEfVy!-`tiJ{~B*^hkCJmV}oqX)}-~7D(nV zsb}cwUs7tLBj9dwYu%y}Up|9+95|p~@I&GC+;VflLf9{<=S2yH?L$8oN>L;p(e?93 zRbN=g*vbO_J-qdgjG_8h^8DC?lCwe5SInE5tDTn~u@8hVE6;>|OEfiEnwZ_*RullP zL*Ofu{lQmeT-0tUdu?_+u+6Sx%)=1kQMi7igrc$kH>WBd-6x++X>OeOm?usCS`U$p z(H4adn?sO%)U0K~ti8kX?WLT??4aOheFJ~*=;}W)|1{pQAv$6hq8l#SSzBp&`$usF z{Pf$rcbvlo=+3A-D0jV#o75~*E}7D%aaCmrP_Fjl4AzjM_W76&lBmh9{D+tD157z@<`hnNRy~iLAb0O~oxr+#f+b`Cs zAqy~f4EhD`5)O;L@_C;;nsjyLyoT+FCnq?Gt<4 z0|1vYwOn2lKH`n<%4Dc`PUM=~_!Dqa+w9G3k88=&!tw7i3VK&l%zxfaXt9`bV9%!SKw04;<8~AQ#Ewqhd%|;%S!ZOI zcCWjLv{qfhK{Xf^U5hHdI&9>S~G?QkYS7?{WfJkMhG&$4BaF_CCkr4 znuTMC*#$dzpE?ip!e-y7ck?*o2ZkD%7+d3kz#D|wwozO+ToXO=atVUMSB?6rd| z(9;=Hw9Hy8XA@-`LM8pKvbWXJFynNQ(UsuF8ItemF|X_W#{G>CotY#>bFTrAleA;X zg51>k1Mg!mNB?%V#pOX-+XYDC@}+H0_WjUGp8=VC_MkF0me{VP-~e3rVd< zt0eBk0FAJmuA8aROJNK{Zhwy|g#I$DZ$-d(T zoNH+vnvHS}LF;xFqldNbx$arG;4>TrpbWisTp9_7mh*Y}y z_`4HxsbT{J0 zjF-%Io(+;|X^4zWJZ*@U46|7Un)Dq@<4NmvM$n3ac3hvk8%9iP6>Ta)$++X&^|-X;L{#L)I6Dg%?~ zT|nk;wy&1R4n!nfocr7QXy-VaVz}dR=r)B4%{uF5A?P}4Da*BtUHCg>7y}6h$3;wh zq9QTOH;%0||Cz=b>OlEfTYGt+u)x@^Akd_Y;|NJ*<%;gg;q(%le*&Ol=4+MQ!>#-rJwMn=vtqcw8Jd{TxS7XEmURpF{yk0A2qKM+w-&^f8@{I{9{PHq*Q&|tCKd~6C9mkOg-%dQAV(|ij*jrkU$vgSefR-*YQuKf)L;ko@gFDH#_ zIe@=k7DX9gfYZL9QSD$A>wQKGb(Ula$nfZ*V2osCSQEXtGSbd-Y~%SKeZ(5nZV0rN zpmGX)fxM6#&TIEbIg_{ofc{(30@@l>Vx0Qh_fFshd%SKWroJJ%F zhlO~vRGC)-k6;E!Kq8Mwzg!+HWU$e{sT&9$u%MpVNoNK(4OgbZj%7IEC>tzHosb?A_<6Z%r9*7QO*9uc& zg7aoyZw1UhUM6QW)OcDouy%yEjoQNpT*d60{+o}`iCitMs8MF(%vp5#IqzC_k+A6A z?;PqTpA}yk2{@msl+DETG`T zGuTh1KOd*+p*w-YRYq&@r}|jXxfh>0K+^@l_xzJtcVJa#gcx+GgnN~llS67{Gdk+^ zXHnIZGp?XJKv{7`#&ZTKt1-{XEB(hwzpcHS^ya#=S*%Y}uPOmS27cFAzlO#OM3-Pe z&(a9L8AnOk3SUN#^>o8F_WYQ){>;O-p5 zf6~`{NeXCO2RMzGRlG+UhIzHWV`yF}DGBbz^!t4RmkN6d$*GFup6BtVu@muik?HU~8<>u(2-KT?J?M6fG+=eifvq5n!#;>kDr^t{Vuk795 zgZLDpw^q{S$cNTR;Ec{*ZCfPiz$1I=K&~!6r>Pm#0g|ldM-SWDZcLbU?WfL#t;4b-{8Z2B71xxy+)c_5)-nwOf67a@SzS z4=d63iaW|32ltTqJ^2fgW3<~XfGeFt5nKqZ(8^G!Y9U;i0E1m@kyKcE}t=dZ4trDw#SMX@5-G8;7|Bb*$t-o3Bet08) zYVjas9IaDXANldC9W9eWXgY zr4Ifir1PU*U8E17PD~7m{<;m>;~C^KWpkwURt9qa)2$!oZ(6CoQ2ALE{^6IDBHPrY z=*Yd{s)pRjO?#y8=N)#Kd%9~o?DUV@-cwB0RrK1UhnO!r=hVHjuA9}p5C^tqxaF8! zAf^fw>W=xOTIX13{HIx*w%px&wZ{GSq_oFdp~H8@t><4zZBDs7ttHNH(A_iGGCXpT z7&q0Dp2|$`TkqMD+&P|CbDnjYecAqoKjqJcYrHopx8A*z>>aH1OY(MZseSsDB9$CI zxGys<9#Gr=_kiKY z%S_Yx!}>Az=JO&}59rPfJsl3HkM>yM*ae)qgMnvlqc%B_R5+jRe2-^~6qiv>%bX&m zplOvQ&VMUI`_+znvQKXPcIfszk8-f<_AYOW2IR+z`Bz$WbL+W7Vmhhq9_&++18cd9 zM7edtpXk~BH)e;JGe?u}TFm?V_>b#p!k|vb4eBo`D-nbhhCMKOU5j*iApAc zi0b_R%nyxfv+;LB)dp9OncdtxC*{3Xwywv41>({cCoXvj@aTX7`hz{t)x#SPy)JCL zDQe55gEI_@o`2;;MdD*arvDa~+$L4x9fu83e*|V`Mm#TI@Aa}RJKWuTeD6&~!(UPf zO7%HCPmHt!$EtEBERK$UKIia#e}3OzC%bJ|Odh&775;#8%V_^8RlcgcwGKNSq*zr* zS3yf}zjn`L`Kg={socL&vgbaiD<#X!*xDVH+B>0I1>0Dgd$pOrO1MnJf9U(PFuQVB z+DbRQ?R8Q*uJl06mAkxZt?}-%>L`l<^_EdfTGFy%sh5wLrIVwhch|u#v-8;y4}Q?a zwC-n97QSHz*dM$@&+QEkY&I>2fKxi}-biTIMDks_jiKQoy~^${OmD{ZnrCBRn(x4F zt_Q!zA9@(3Gvk*y7h$FH2QDoy{rN^RcD(w|Gegip!3HXsjSi#UOlzK6Rs14hzunA! zf9T-Lq}^|-o3DKSVX8QbhV|?&M=o%&vhP@@3e-CJ4-9h3qVI<9i`Oyaqm85s>)xji zY}M2)HS4--`SK0Q!^>#CrYA`IWe>%VmQv+XcIus!_knE@Jss7Fnd~B)_2Q(Q6KAy4 z71J~VQxYK;b4o0Y<@`O`mbDYE^pwyRtgl!&yIUgEduMvQ0c^hD!?f1ukDo~HvGyU^ zgkyLAjr7Kxq8beDXVs}LJuNi)9_2ZGpl2&yD2{Y!acl^v@E#bJ?X!k- zIOshvaf_aTQITgxM8-kbDx(H^M~!{WYgy<`N9Mw@(+4g^o+k`P*%VCiYrXXLIbjd$ z>bqU9T-j_jQL3?ARcFD>r`s3$2UbXSE8#{Ye7UI}GT#4~G01b%kP%C?9wrdx7+eY9K*h}j@ll^zzjN4S+ zUTqVi90lk9)i>s?U~XUNpZZV$x0&p=~Aet%;v z`JA7;@zr6w{vYhi?T7fi_@byYlIhchBbTQRf4tV%=J!wIJ$giltlL;8)l-N?EW?|} zS&!^%>sy12d|&(sR+VztVb%moLNqPA>iOTALVawB%H48J+fM7|E{E+_r`D@8CHrGW z7YR1E4x}!SgR<&Vy8j6HgVw9I6mhU&+#laKb#U)!#>9ue7ToeM_pJ1DFIB4CIJxO8 zvson(e|qqX`L)mjp!heNdKpe+Dz%kNBF?oQ^6oJ+3HvYTd-4~%59VrPQTC8WqJPk3 zfqxQC{F1V6%=;+ZQ!?=B66B@zk5h}Nts03xGx={04OOn$+)n70R@)PRsXclK^S=MU z)W*b*WYO;PU)xiPk^H?^MuJ(7>o+Rjr!p0NrI{A{_g_7!Xhzx?-~ZycPA;^>y(pg| zp)uYPJ56AUqGQYT`z&DzO4!Hsi@B5R*%jw?U2|PMFGr32*9|_|M>Nm}GQ;-_nte#^ z|3}|2RnITwN$+(>wX{$6ktOWqC2tFU61sTtVhVC$dT&dd@RRhaL;Ljyk0zc){GT>~As#Mbnz)B^v3<2M&vl4S87qe5qhPgq{t0(%ay)!WqCVH3x%qm4@Pb z!foH9wk6i_MZSubW`n~J6aV*c6xX>*!Bk-?8LYuwl=Zca3Gf|-p3&LiI$VxKeqc6u z-Z)eqPNfB`Sex^}NxafKYXnGeyp}&zB_qH5ud&CczWYs~B7=Yl(Y0a$P?ICF zYBJFI`yi2F|Lhh-=4z6;&UbGNd<$~PJ=%)ji!SsZ2+`%`JUk<;1vBv3BE-%UpCeh51#Iva{f*E~07NbNE^k}=jfD`DGB=wQ6|SRl z(VJm9j-(ahY7tIaoh8u~vR>4oVc{VSvX{44MCYCU2j^`ie*s=wUT`wgqY|EPQr^iGS7~gVQg4LRmdBGL*N4O0{ zu-@Z&90;jRdt~eQNY_J|2h7}73Z6$1)$SP;RpLoxk!Gla7<>X7fTG`SPCo1`jXpB zh6+A1q~U0$_G4ArH$5L;j|UrcZ}dloww=1$El3!-jaRy=m=+YZC>gsHpF5eSNy5{M zWOmkOP#Hz1?eItLpc`Z&H)>w1$#mf#g;ZXyuSv=Ml+*|m^|>*X5HwhE%A5H`hFwo; zxI$2`{j^(J9O|lmaNIth`Dt~ zalZ1`Z%M4y#*sCIkG`YkwXBTO$J5LiMqj zm^H^kg1CWckFS-+cYVL*&6GLi4hU&vV3r4@7hz{Ax7~zmH*qG3tZ%H+Vl=33m*v>k za8NDeX+oX;$4SZBX2pL5D?p{eW?n0}H^uQSOw*aFqDo;HxyfMe4Ni<2$e0?P%x)dn zE+m6vDBf7YI%v5ff6WV_QSWU~Ik8juZ^-~7W2b6>k!^4X`+V$DqZ>=Iw)JU}IpT2Y z#WfR9y7cqab)P9GPL{4bFH6v?`Vy&)8X4{FD5xVVfo05>5X^^%*`; zzB0n1H`sVFgt{~ELhwx?*@y>iLyLfBgag7Ryob^dt}8H73Bgczib_G}u^C}c?f_X8 z+yh_CL*m{BaJCFmITJfTj>sun4Yef$B#?ySn)vyJ4lv`QIHmK>J!0syN~|FCLTUv$3|DD@eLe}(p++#Ax+gxTdy84N9KTYk z84cL-vn7VPAT9MdKT0Om$hx|J@nU;kO)2giaVJKOAi_vlUw>k0YFTfny5FYP5bC=o>T zccX!L769MG3>fxJ#mJ~@1bhG)*Fzzd3rFf0_zXt zyoyE*Q(*TlWHjl@nFEjchlyBUh?=@wWK_^^W%)in)`7AbpoSzCc^OLZUaluK5z@*$ z;rd9lRO*3Rn(exkfYZ6=zLEvtMbC2ud(Uat%7~}N*>_#eBQZfe-zz?WMrE@N1Egn- zG7^E4(NSr%l5*F0tBOg=2(@|G&*{Cp*B7@+;ZUR>>*i}Rt$0w9RC$qD&>=3z+5)5W zWKnWlSEIELwHUmGJlDS9^&KlZ$h42#29r~e*mbL*BSFecAf&m{6@~`M1(nF_{0FCS zX$HSyyZ~ltZKN_g4X9LIE=~Z^&AuLHq4)^ncm*OPyGY&H^(Ki3M_SfY81YTJlqIW* z(6SE%Qh-bO5lg`=Q9ro~Amq@J0oB0QlVvewF{N)=-Vc1>b|+z*w*Es(nuwF^ts8Rw zEK*=anWKJ^wy&H`3u}{{8aNf+Gf`5L=0o#%RWG;>?rtHz#Z`mVZ|0yU`f^JR z$dEJWkxuUgm0u;i58tR64oo)y!u-HonI9OJNN?TcVdwVbEo{L4%d0UJmkAGmk*AGf z(aovdw|=kiZhN7_7o~d0=rt zNwW^4vc~l7|F{m8D5%pq`w%1hAbBNF)as{6fOa?W^3wb5(7c z8{usU`R+llBo^WWglLAW6M~$>Z@)xNK?Led!_4UY^L(+Fe((D1JiY(N0^908?b*E~ zUfUUS_In=Rq2{pE5!FJ?Gk5H;q?HN4Lgr=wsBBhHh}Rt_lZP_nBTyX(>=`e*RUP$WZbOS=*eCi zo5s7Vh*!taqo4&Zw&3pyZDr)WVBW$z!tRA%%OcwLawhI+%p4n4f#@*fSf|(p&&H@r zojyYMCzp@mHdNk!ekXEhI(SK)Imx^+h0e>J3EtlcA8Xt%d%dNU9gTpHFgq{H-Sbbg zj4m^KADqLC+(|eT-Mm__8kys^p}ws$wW0f6EMQKgE_+X@v3FiT`754N@P~eF$L6J~ zn*E9iB!@rPAU)ZSPVnUy&aOH+lDD_|?SG7u_$i-a&bhl{t|umJI`3avnc7;p-y%={ zxO>s2DX{EVVbx^M&AxNQ#TYI>&d(b&Psi$1!?K;u4Oc!Be~6!gEBL9tJfro{-0PV% z3zl0F{S1rcH6U5Uj7=-*YGis#E~fZ3aB;6N#Z3_%hV`>%;kO zM(h=&r?TL3#??DPmSP637k{67b>SV)lE^wKPYZe2RU`H(+)vuUyb#%DdLiL#y;lg5 zl2;gs-pN=EV5-tz&L50sV+-ik&w`yz>%Wuv6#9}wLo#Pj*SN|cGbtphDN2A9z7be3 z4-v7e&z=d>T1eDVnqz#S>ODT&%FUzu=tX=`e`GGKX(^f`pzl^Ru`HavQxB^U*w+y4 zlryd&)$CmKT|55}J&AMJXG3$&wdCAy=wXk3S@Cx7{(TR*toGkQnWYUoAX>%3fuWHA zi{y_J(ziBz!O{PAh4;Bpw;Z{93H4~lCYNdOyPo+VAk6!fo22HokQKYOoiBr{vkY{F zgR|r%*-wuz*xPvY>`Koah0@Pr-YTkx!Ecl7sl>1CGDeK(>|<&@y8)E(uhKy4BCIQo zfJb0Bf{MqcEqrUG&b3I%JnMNeV3w<}W(0wwj^gpB7DrYWw3w}jT3HIhw4FL?M@eZ> zd&{{*jfA#x`5BF?M|y(GJzaHe!lS{rb-(jQ$0uh_DvJKtv&&6PHfq}XS<)w`J(8TJ zj$y=1wCX}K!v`1q|spQU|56sqoR_HUm z=uWcp?HYvGfO~(;t~69jzL`tU64B-s{6rhkzAMc8 zI|j9KBB;T?x0+fE%8>mCdL^y@bc%aWHHE)2`S^1#m7e78Z>L952NA7;k!OOR+H(e> z$K9(LZ#O?p^@>Rxl0S}&=pxlC$2`$;^w%k!iS`2o*K^K!QCx9Ebup&mTYS+7EHgmF$*+Xsr- z9d$mPcx6EQh87L=g`4v9V`_4RH-%H0m5G3{C9bzP6%^y4NuQsC&&gdw;W{71f_vUZ*4~*j&-8QL5Yk9)*ex%kH z!*(3?I!?sAv_EwE+%F~B2Kc7-WrDF>j*IGn$dqoTl|E0NUB#Vp|IDOh`gSEYKhbxY z7QZ&U=G}IsVy8<>gi$cJPM1n-gcmG7b(r?3y_N%4&h$}J`}MsMvnf4a)yCr=*S#c<9_yUZANWpqQkNKVQ5iYb5$;hRS^kLJ&KblC`CoAKSK#@;+Q_tJv{!p9-n0hRQ7P=pGZftB5 zZ>lkeXZKFsDdJP(@U2 zuTs4T&rh?>cYclrUtK{RO}=Q+v5qaKILbTOO;_)YsX}83*PF!^1_%=xAlJ?k$ zd4}h@NauPO)ET~0)VDWWf@+ps5}ZEnP~DU$Qut1!AmvhDkc6+f*}*GIS!^J1jDiM3 zIs86{=t|Qf>2qTw)0ShiwAxyelhSyc0P7sJX%6qGtDPxE8|Ljj?!dp9Jj~igP5IDe z{#xK!Qq&*i?NxPGBfj0)B-lLblG)0d{Q>JQyC$*%LF)hq$$(S#V@j5hv|ggsn{@V zdKxGFk!qgaJ{cE3$E1?sZ?T>T(#?#%E$PQ^IRn5P&^$aGUm2oFK~oPx@U=TO8{^Mi z?>qVMd-!)g`B~s)`{oTiXQ`$yId%AXh!7RW60_Lgn3~MyC$;de@ce@1@sAutl@R)F zcU9d9$G-lyDwU-!r?b|$PWZc#(HnFTYY!4m=^OLs37o@7kg>4$&+g~7YEYhe7KH?M zoqa`Ej(2{Cm3(g~w96bXLmygZ^>}_RZl>1m6{$Xmb>i*J`09MYR7iTDKxYv0 z^*OB=lN@8EZO&hfOPN-?4iahGhAiRF9y)yB{aQ&+^C>jA_z6=x>?LhaHcLT_cQ6Of$k2oFt_8t&KzJ#?7q(yu__sje$cxL8Y(|9PU&{dB+;;wq$8ID_dH*#oV^MTaYINLym)t<=sR zwtOCbmG-V=(?hS^1a)FAXX#q)Bge)sxj$^T{RpnWfjX?XGUsr_%mt+Neth&;*|qsS zQLduV?asO!2fw6`LOb%a);Fe*Ea(r5xb{*rE9V0}U+Txlm{XVjI(#nI(q6~?4u=9c zZa7%x*)UwSM$#co|*f8;jx-h{vL#)%Vz9ux6Hfu385|yIg}&Q=RBAK z;P}^-SrEy$V)HxMK67s7Xx(VVKlh!zKVMXAtS1q?Ny<9jo$4K&;h!yv|8c#1uPZsZ z!b`sYC&eSG%ed#0iDqLwA2ax|VIyjcQe^MWIc?qJ$!B(i-?ZDY9)-K@GB+$ZrZmi z5(@>M)x}=Au3Ib!v1rOV$SrUk>jXD0(UhqSG$h)D#!Y%y2f^W_o)23gslFpZ7yDJ1 zAfEY$g|}EF2+_%ei8b0{Wo>x+CJC5DnDGgW*wZ@~K`jCa%?Ko0Y=r~H&FkGn!Hb?R zw>~jR%KceMeY`-@m9ee}!qz}SQ3x=86c;k=ndJmrOz9)cqBH9@2u{jUXZV9Q&Rn6> z6B{PssTq9QKMBjS+9TO3yN(5(pS$+%4-vpea+jMZ05av;E`#>pJZW z$OX!Xg(Bz=NqrstkQ(^Ur=8o>C3}A|(uIi*od0PwkS(t;L*p(O)fV{=R5ETnUp7+lMfKng~aGnq{o}rEw8nXD1eEBegHS| zdxalMUEfC*6DbDMMl_=V(YQ0sC8GZ}O?@H4NG7>prltnS;bA|%6N)gIr*qh=3K7et zLs$M_fMlzD%ODBevJ9>Sk4E6d&S#j@5sLui-BreuZ2>w&$Hqzv;)N{5*tw$$YNm~j zz&KF0beZbdaPK23$qXO
    -*AVer)j~r;Zz}E};W)K!iiT5RIa|p^}$O zHpDx!J?D8P=BygfQL19y${!q`(lR^{Ks}6SLqyT57aZGcRNr*+uYI1{o z+r~lMDe$5lm|SXyQg8pqMY!78$q}g^m2B0_;P2gE9bP6{O9{J4>EsH>Htj~~2mDGx zJLH;$IH}_Fb|O0@HOV$pX^*N0!5#CHtm*7PO7Fa*YZnD$t~W6C6U)47C_ZT;^Y7ZK zxqYS4LH7)hokW5|y{Ca!<>*+u%FPzB4(Kn- zeXvahO)Xw^!%S&OR$$tD%rrF9okyrqQsJ(aH?MLxCUDfwbN&-?b0li=rHggkV9x{7 zy;3gtK0|7pD@iTRu@g6K_jb_<@dk(gSelR=#v&<7K-t^oKAHEu=RWjq`2(MvK{+Gm zz`y<+%WyMoE=3k!33=m@kOtj>C9Cqc*v$Xq9LS+q2RtYol=rfy0(jhQ$}V_*?9U?= zNp*klIDJQ~fx<|O^r7=A4U&|p7+Tpc&IVu+(aOYh0Q~|8`Py@% zqil_Y?h88A_@FBC2`rARG8|xD$10%%jai(_RJkFQ zy}aLAWz8EB8)qhBzX&Jo^4{(xhXW`qpr!ek1K=gkV}n+XXpE=IV!C9T%^V|?HCbF2 z@voQ2IUyvTnSbm72pA(1?`;k#-hRh`eG4b4AC>rX0;KY9g^vj6*L8x&!hm1}ay)je z^PBtldMzjyaiA6C`r^;X8{e-++84s-909m#d+}?%{gt!FY-Z(6WcE5zLtvECJ{Tnw7iA zS@MN(Mc)re{1gdY!%X+f5-TSd_C*k~sxQd9ES=nt7Tm1*$gM#Fugjpd!OGsB{SzD- zby(-SFE0-%OwmsC=+DI`J{g?dPla1YfF%?7!ERzCsfu;vfy{w^Fe)458ae=eOub8D zuK|qP!j#5Y245Yx`V&S5SnT@>U7vIUjd*8SjjKA)@Wt7(i#Xc?y!9+yB8fKUz9;)Z z8hAtHXBFNFf$0HheCfPP>Ps3RBlLg(C>RFB6o4cmYwe5#l4fW^hF3yTrcLq_Jc-D_ z+|zZ1lcKq#wcsS;?I#~L$0g-*pq2_z8YG*Vsyd$Dyd z*tHu9az~$7_A~$}mCtv81i*6k;?$KQAhGnok+6D08ZZ$D&SLVj>F#^%$^Wdi0>fu5 zEC1tK8>SPslsw`KfC>{vG(e8rpCihefJ`Sm0*ftBvkd9%YXgpmz%*N0LOMr$Q~-0+ z#ruU!wtpus__s)UdTiJy!&RBmC%HMt=MfT4LaM9`RuRrs|(o5%SBbE&r_GujD z^}7{~^=k|e5Aemh)%ugeNd_W1JPc#d1Lx>@y+T-v}`cLjdVr?`CP7EBDZ-HOQpd*;VoDNA$2}`ioW+RlPNq3tid|+Aa{0ULtK@~a3^m@5&W?dS8 z-NTo+l$@IUPQ|HzUNQ)A8**%owYLFULY83eX5$D8{9nt~bB-^)wYf1v7an z`^S0Z?8V5Pu!lQ;QJ>!zfTx@wam!<5!Nwds4bQ_VLgY`gl7b-`w0ziBc8~7~6Ee?^ zoX)syx!#VWz@lk|ld<26#kxIt(kopvY=ungPJ$Y;IQkJ}_*cq@C1I@B~3}5G*#(&1#j?G2VdKn+t{Cu+|krtC)Ct zUN%(BpXs=^H)s40?FZlMtLEQGhi`lgj>L>XJ^*Sb*nE1#|X! zsBPIKn?&V7BuWbX#YJ(Bn;&xztbf;kT8apty;}jxnSb$3cXZPU{RE#jY@%Y>XX1N> zj1>>=uOONF1xWY%Neiq^UNojvdRAQA8^}qUvu!spqZGK$F5A1&5Z|1 z^6nGF?$6q1EoLR;NZ*LARVy1T)vgr-@KRKs7~NvxW=Dq_>BpYkF0<3n$!O-kZ5bT?oe^y*$$O5VO-|_`M~?h$Ex5A`ugv&UPJlVauct-HwWJXbQOfcCp5m z&*xYA-R;~<2WW=3;qNRBtSGx<=%NN0I0$AqGA$Sj^g=JVt1Fhk)jLORsqmW(8%=(Y zW?geCa0m4%QiRS3*LOY1u`7>HT0cUyaIH1OV2WpL>J$SJyu_#))y~d7vA@VqmMRE# z)z@e!1k2f@Nuhza(#|gkOpE~8&KVIVM`o8q(w+fxyEZK^xbWdOLLCB2dyU3pZB5ig*aR0I3?j3U7 zPE{xf2$PkY7+vMekLz5cPLJDBZ-I>cDN{e0DC2dd#Vwh)C0);VK})I6U7e46W&9wS z6!7-Iv159lH!l@1+h=k@e)%;pe>?Wm$ z6a0t0%&r2@vrTgr4H)+D=vpRip;u>@Vmt_jX^N5icPlI`{1X9hid*h@208|cwq+Fi1IHkJO? zhpcE(p0*86L!3mpL#IC|_w5WHtVk*>U@0uV3tWq+_!>(~h_Ghr9c-aL`T_@0wbH(a zLBK{>=n;m?BM;33jBIwLZNGCR9+PjM*8&we-}1QGtEU2t<3dx6&C>~>!lFfP-*=Rl zbCmL&l~^$eaek5S%Xs3uS|A?6k2~|wdCK+Rz(Jfg>VjYKk=g6=taGuaNApOuVaZSu>^wXPX*szi$ z*w>L|EUW6uUNQHA*T=fAoZgl!f}#=Mj1Vx%$<7W0-@1&w^@dG`V&T22sroJcCXqvH z0{RA>5onU34{yA}3BOL!AA?fS7W5;jYvrjl++_KW$GNv#hUCZ48J_$GQPH}FD1>(Y zTU=EM>jbo&L^YHh*X3dPQYGV#rFkF}*Rs{442G}U?`fAZFj~R{ij9uli0Y?d9!2KR zc|qGMY@>uS&$Of)w&A!rA}cl!K6t<$%{U#s%I}pM_-L;V4V4&S9cNnNYOwVw8TNK1 z9br07(d{h-lg>-tQ)jW!E_Wk*zs04R4N?A@od1Z95wpMFA#nb#)L9)W_ujgS_#zGR zALhV-39UL!=b90-JXBdRa%)SOb2OECfpwi)(uv#48OlHUw-OY00&;tDM%kjl3mX=!Lmid6>|r z{@&WJE&3*W>YDQYXxh*cI7q9uu1dHiox+4T(y?>nvCh;;B+^q;@HZYh*~benT7BDf ztTJd#k(|@O)5gtpTwz+v4DpgVl5unq1yQX<1g#B^#;i9H?g1F3dcWmuOaI%`hPNIM z)dq?ETvVWCefR)20P;vo9+n!J_n;nJsg?s96wb4!O%( z_<5_^xMvoz=W=oFLhd04$&U$vpy2Pxs-Yz9@h4zFns`^|Q?NPT-k;Fmqoi>za_7qD z7_tU0EiEW~y6!Ib*M0hBwBrhU4V{<0RyaY@AT>36m#BBYcz?B)pQVJg zYc6}>_3Zj&%$*8AqyRZVw`7vY(DYi))E(_qPq?JUSTSLx-+NO2pOe|a=~a)S!e`db z_2NYr7vf(93%C`-V9_qgVuQDNW4^}$qX_sRvm^bL*{Nh3j_}`4*xzm<8fc}uXxkWI ztpjyC%8E14nAvvki}Gwkbmqxk#GE4tuXZ#pa23-mE2@vLNN>46Y3of|M+hlIGFoWF zQsmT~M#ARSCR+A)y2b^t0k~&z;g)b8QNvei`VVefe>*!cSk8mxk6&?b_)VL-%AjAdzc4cJi> z4#N7;A3!hU`9CIbAxOw1x|9|sXOkU~|KeMOsr56?V7I+5t1rb>AcFLjR)!HYdNi@V zi9S9Rk!KEsA=9Pn%KQ5_!z+MW_oLRAuF>YNK%K)rm{x3z;mR{-LT2yWhgQgfZhB~5 z#pWiq{PUfn$DSrd(czgH{+dMXNQza%=D2Ud1CPF`89-%F=SdNEmFDcTQ;q39OB~J0 zSig5~9OU>G#Wsq@L01P(%w*d+Ah5& zmjkVtl3PEUswFOSG&zUAK|*0D#AY54Gm<+)U>lg83FL(zKZyJ11DrR5IEM$A_A3ag zIVs5&dZ^{B9nqu735_^yvs~j!GSAF^cwY5JqL;ElN60!9X&N9=;C7mdStIKQxNy$2 zsWU*0asUXJqCy;4c2w=)rM4A;6({lMwer=5St{vb*H0;8$EoY~`BXy)p^YPYbhbQL zupOgXlGrSpVn3zWPAF_j)Y4d3NV%OTl6Wxa*yOb|E0`f(@uxe6yJw(5tjFD#Sx;G^ zm8agqX^6Byu{OBHd|Gk~ZL9Rb?U;cL+smdc!UhjsUSJZ+ew7M=}nOm>HO)iVHaj0LX3mMi)W&$f| ztrcn{!#k=?2HvIw;vdKG$To0cKy%;F1*rL`@{d4H(Q6qCtXL$>w8%PXBLZ(a^*Axo zRT2p0xUl{pGuPnWpz?oQUo!I5{(daJJFtABx(rdNJCTxWx~2jH7R4j@BInAZ-hcAV1LM3@l9+imM^V_)LSHC}@Z!#QJi5qi6X6<}_HX;npPp7yT<*E%O72>!J)emqu<$DHty1 zA!0r+`7kdVwLW;di57e5_m7?1XnS&99s?ZCL+NHhPeEiC4`LOmW!>B%85Tq=BOj2F zH#qs8(c*~B9;=x5lwD+iE?k*VX7(d+$+Kle@38R|F}a5(2{?dfB8FD zFa|=W5laj{Lp}^vuQ8H9s}Ghf3&`=J2hsOkcn)eraiVcr#IVTgk#d*{H>7eGa+< zMERI}8Vq`|s}k^O;YV5aAfR~ev-IunM&E$IXT>%e{{`Jq0#w292I0R(jA@}E*GNHk`<9F#65h&wxGfmX( zI*jn=qm5@04g8-oUL3lpYmsQ6wOvW#iR{)D8Pm}!o;Hn`L#Zy~wQ>wAP3wg3nyH39 zb(Etx1aW@mDO2jf9{sn8V^G_FTp8c&6e8y8kB66V8j&~So{q4UkG5wP?~5*tFz3Hw z_toe(o)&VUXF6vnb=zx;M0bWBnaQW{3Hyz6x9cE&L}Oy-nuht|Ak@h_=SNt-v9H@Q!uNZvkzvT!A*YTH}6MuJ-)}HvzBuQ zRxiv9%YQ(zoRTSb^_H=TzM7|3PYb4SKfK=EVP4yT4dNmM4%Z0z+ho)_CV0>j+W&HR z0>Dmh<{4>n%U}p>H14md8zfE&3n@#f9WU4?=OdSho&*Tb*k%9(6I;pXEg_1}vlpDa;|`T@@0I{jjv9=iIL zUjft{T97zNs%id#-*(=#ZoA3p=;iookI$P^vZ*LjDqjaq;CHB1 zhFuyt|LnI03$oc%Y6{nH73eSS9}6DOP`r$X^2HTLHG7le`FB$k7)xw4M>+&jhj{xr zMJz(&Nn_Tu$6WjqRp8>?8fPg?at6LPRS^G7Yv|R5Q>Y_&Aa%E+)y7Lli;>@v%7X!NJHyeWbv9=o!eC7HV zZhWqUns88jfbJCe>oLOYmbgHNr}(2MOAYyrF#xSO`zXiw`+=hW}>F&{NeuLQ+d&?;%fMo1yDvn5v}s;I1j!f9+9dWxj&1F z-S6c2T@bA>AK0V$GWn+(#gHW^%{iQeiX7@K1mh5XflbLH9$R9il}gBZLtpDIN#!zW z9p4*5yQv$7a}r5Zwbn7b(i>0Def9=t(e-ck9)0%v827%Mjr%sOvu7$lORnsIG1CnJ zX7UU|81W=27I*k>TJ`X@vVdv$rLvRwGwqJP_WTkdI<|2RoSr<%blYT9Kx}eS->o;} z9JXyGtO?zLEjJAaxSTq5yB&)a*4iC4=6WYi2)?pln{n}g@cI+W`MzD!Iyk~Y2BZcT zJ14opsN}0mMpy}DhcE#Y;{0U#%6)hNWaaD<81JB*nv>#{R8|$FD1rMJW9pZzgwroO zgyj?1b5MVs&*qb;8!9nOgR&TrHXR2ri3ek?tH1qj1`=T}|Hyzs#|358oLm)BdCktW zs+v)|UD;A#^2syl>H6-WjHx80COTh1=YL$vcKP!c5iC=;0V>4sD8Q21y;gj8I9=x% zWOWRrU~(@0*5zr^*e$Lux$h9-Qt#j(<26lpDEW%KLI-Q# zM%eYLjf0I({g57>;v;jxlV8SZZyS?DKy_goGCS}lO9B_RVkNXezMRe??x)~+5}lOGG7gN(195<`Y;Y4xSNBW#@R33`DorlxkIK1scu zfRHI0xHX{;X@;ZfiEO0)ikZ@Wh(YZ<%qo5*zgXpV)F&H(PW z6j*O~z6rwj)}RO+l%*sEhHL67>^PRP4r2581~+Fv2xsZ=94fMLj%GF@k7{vU*F56a zOC6_!VZ758>3<7OW*7$+CC{Irx7fQI!lPQeJFjaXo4lc@DBNSjUV5=m2Xf9OKY@gc zB}>xCmBj0{vR5|@V_7#KG3#kGjZrP`YYNsGvjwONe2L({Je)C=XtI+EUK9{Iq;p!Z z0sAXJ(O)q{Dk#oaHkSPGN*8|=LITb3+~C^@9pMPj**cIi`x@fm@Ha{_-wn@ew?yOz zKNF8opkZe_+s}s^dRJ%aK5ldw;B_)&21K@AHKdr&ihOxSpQ+jqd^EOv<#~#MLvs2l zEihr(yriI?KAVNR09hf2*SDLj8O{vEe{QCFBjxZYWO%QE!a_7cRlk!b%w{}_l|IFK&(FnKD>TIWAL>%wR&0lGXS zFl=l5^j}na`Uc-?9nJZYhUO;h@S1Y{0QdWso-^|@r=Rm(Q`p@LuCrP2cje=p0UY1h zpG=>^!E-rl&RcwSHOYVHYRl3eofyXsB38(eqb=3S4FwyToWqkdsQq;RrMqwMZdlJ& zXSzM{e0`$oroG6fnOeNt!RDT&+0K_w>N6h=vn)2hpSX=Qf2h4!qx&^kHLFLHs|iCpg}WeU$0*M|8Ku?VLuJ z`7!xw;y6WZzo}WyEJt+y{k&t7tgxw+Hwl?E}GmzcorY`v(+!CLwLN zDE8}u8h!&ib?7tf6desc@0N|L6v@BB@5f6GK4n8z!Hm>HQl&x?cxe($ii8Fsb7%bI z*at_zpJy&2ndj&}u>ZJ9f^#E&A{8%lx;bJ;CV(}<1p?0Lt6{p04|eOGZ0yqo45#;I zkpyT)^Y42D`M<}%^zZm#R%~qha|Z&fN0JGCdgC>e%43&Gc9|R z1=&!~AfxWNGW=-Pk?{Vz8kF+ykPP78z2?5-x2itJEdXWj{JWAGlHk3_1up)&pdSl@ zA0jtG5)rlOv9rprcF9GaAt+;YWOed>JixD+8CvUz(p(UA-o#DS#|=JsIAX4Yo)6g~ z`!V9)3@0fJ(&)B{4N+f0UKZJkSaeu>6zAk-J&p4u$Aq7vLyCf>z7Jc~HjEZFHVqGH z+GlsBpE)I+TOQ0UuR=+7dV!9IbuL2xJjmmQYPL2(m^ODguhHd%0stCV9!oY>ObSm({tU0vkW$L z6;82nhEkZEZn6(>p+~NrFJ|X^$}fR?e-gxK3tfG&y^s>#LkI+TGgp&!bO4;t0?j7> zS+`o~3)cjwP#SgU7NLr78n)Hw^~}UFLVQus)YD48K7W>Yy9Q23n)|#f z)I0S6M`Yl>n(*|M_w+Uf=GJ9r1Px%}YCktgz)cx*_ ztZ`OslI7Cd^I_@Z(ePgLID;%5_A*NBaWu0J5tog-KA2g^sHI`P;C36i7X* z&&jk|jI^_{1p8h408Q`bs|F`w?DY&FrMib(Tl>^vSvTg4RRq$QvEIjaUOp<_xpn2j z8dJTE_MF|~T5oTUAkAL(=tqHS#cgykx?t)))E+sSFr=zuiJIn7fyM#B?p;YBYXiTU z;_%sq^iMM;VHG|+M5p!txD2xl633q_l_6Lpmupm>R$H(VDG9 z=hj`kckRgMi(eW@JOydVCJK*U{PuG^6zm&wPII^e?dNTn>f^%}N3Io%uzdoidJb^8FK^* z+XI>Oo0I4Nf%;M!Ez9E|X~-47s2#hRd#cw{)lbqP3B6TYQ0f&MG{i&zWzQ{fAum#`mL zbrnf~>v5}}`2#x3MBj>cV+2x|y+DKMqff-r%icCV0HGJ4Lr823QdrlIn$LV-e_{$~ zgz|v`ZDd_-oLsPE5T6!wTs=otNpK0$Z)YaBCd1)Sm2L+FV!s|#)lMs0{7o_*% zQ_P~BO>D3EoMSI(ZMYzo49(17qGf*ND}pyR4Mf(>`!Jz_Z%(KpLdt%9cTPG0)JLEv z$SYws+Qq=VB{PCQ9vZvW|AJhSl3idW2$hPaoWGA_7M?0#x)+B{ZO(RmU!X%>sdzn3vxYQ0zTFlPcez zkEN_z)I`q!x9{!#M&C%bzTETx=jC<&+CWJ)WyV|{sW~ZsZRDQ!mfFpptH5u)2QY^~ z1%-?GOu)Do60tEp?}sXmk=m~F_q9Bklq3Rd*c0vWpJM(ao0|Qsi`66cH@mUk#8HdO zW_*Hc;cHlVuSJl}hNg%&;!GVl7xs3=?TIo^V31ar5osag@`odIQ zyLXj6eZrZtni`1cB;v>YKSw$18>;1Ng)XWZAU8jhRgROdLCe55t6YfJ`D>z?Bn`ZI zS`b1=r=!I?aua>NCr4w9aGk%x+ZHSntXcGRBH%dC%7P81B4O4xPh6ROBYVV@*J~ne zVE1>{9)q+~kBu4>r0wTeu~c+2_#~|Z&EIF@);j{|f?C6wQEMg22CE|-j>t~Xe+_(o zlKvjS2N>$VA;gj{lKec_@)k>G+Oo5_^t)W{flCoySWEwGm)0}EUfF!G-=$Yr*mJOf;?X`O*}1;l*ao+U|i2`d}(_GHPfpe9EL zJs!L-f4_S^(f-g?#JKtw^PMkO*f}gGH9$j^Los_D-P+c|4}X41i)`hC?DWHQNnOk% zq|MvE{^P2O!|i&%LDi{MG3>#d=jI~}A^-sfR29rmTj4#Vg?pGovojIva}~Neu>Qr) zpF}K19ux&jpiEA$VA&($aIm{w$RcqRXKe964e`a8b+fjZCgRg88bdOKZ&{%-i-I|ny33I~o4gT4ECN?%II$qeDy-mQA+ z9LjE<=ZZ32j&C)!BytoX4*%4n(6YXpndNk6G zb%_2%w-wgn*klOz5r{vpZFplij-mHp%$sFcW*QP9Z5*H=@B{1bxtxSgzYO6K`QXhz z#dF&E3#jdthg$U1(mKW%exxmwY+b(g<%>qs*7q73EIpLGF?`=kO)rQmhy*DLOx^L@ z%u~2ZUAygzeY|>jeW;u`GLz*}N0?eOzh3Z}PI?rurL; zDHiznMAiO*;z<&9A1JIp>oUVJ3rTVbeNSI(t8X?t@ixD1V#jURllNV!S&ETJqhUG} zkMJEwwBB0%)C^TY%u2c?Nf+$(a}3AvE`*^8-Uk}IxWAoF9oS-f4s^QtwxSOQ7#790 zHkF$X(j_}3M4B3?oTzGhN26ba6VHq$k~cfYPwk*g*iky-<$oY`=`Tank=xA|v}{6- zmp%;g8<>Tf(!*v4c8Y6DI~Sq`ap{HizM9UA^Q?-ZVU{Ey2XuTb_$f`+UamA))8miw;kkF&HnZ8}!)Q%{*m@RfDU#%X3 zSKrl~%a7d+-|_2r$98oic8tDg418PBjPpL5c+TYwPu!_}T^)QJ9a3)i2tDg%t~Ro8 z;MWzX@_XM8qtmIZU(}>l1UJk!pT900Q}s2e7yBlYmCnW6nsnvV0staM>WIlcOww++ zF|t&Jdi{|8bm!;;87uwo3lE)7p=z7=`Mo_AGSCe*Nh4QvKqvn~ARUjcMb&B(WP6aF zcq1#Wkz&}2j+OKB$ z-0?=&+~=qne)R%z1P8n}jafFu| z{yJcMN+1N z8~;|ZE`QRzv&!+JN?X9}N{)khRC0~+VM1b~bn!I>s%C5F-4X9O41U@v|E%BQm+#AA z6y2673oYIML)N#)Gu_62>wJ)OphB!WN)bY+lvQr0gd9eWtA?C5Q4GyiMCH&zb6O=i zpA$0-tArSlGcyaBl8q7D+Ts3P{hrtJ$MbsrY%g2e_j`S>>+^Yk-Ur0Bh08Vbsirqk zs^-`71s5+YBy62Q7gbk*!i}#MHyuEg7VSNi&VuT<%Fg;&e3qGsIlT}9e>7sEU0>IX z)YjU*FLl~ZZ`X`AH-$d^wC70CXYkvDD3B(jp;6_gwm|lbyU(E)^)Mhr7o4BQ0VrC~QNPLj^FIS}0DKurL6Ei;=j&?8zNpZ!g?TkQr3(cM!n8~m1d+EJmdyoJ7g=s0z& z|8}qlzXVF=vb4e^Q3SLb=mG7_*PWQxUqeW?1Fa^+CWa-r7=tWj{Oz zpp|{KEchfMShW2`_&H1~Xk+;Wg11Dd;r>8<*$iNT)sLJgS{wjgJ7i#fB^uhtroZhG z&)+&Q<}~|w95%9OZ)&N4UDh<>VFQkBSdd|A08GxORAIYdOqy(P10DYXPUKYRO*uoT z4Q@?i%Dd+O?K+z-B<)+wF3`p6B-0~{GguNW=3k9Ue&0*)y-3MEI7pS;H6bS;^6LgL z?|OJ>WQlwN+mRAgA?4zukp)Bt)k5aIU@k064mpea26I78=7g1Am1dz(pdvOh6gg;= z$u?gu?ivFe{HlTg#uHM9PS0=#Z9;E<7$i)WJe%*MH30a`OarZnvTNqh1$H6I*Q08( zL}}Iw8xW+MrS?$-SW?ZGTohe2$44o)-95{=9|kuv0#8E1U+Qa75S&5ePfGaWR8g0S zy|aO@prqoEml4v<)+m}?Vc!IzBuEZcN7-*u&1pI`FzL&EL<9aeHzNL;-h3dhr(**= zKQzkph)yL?(WjD0Xox84zG@naE;=;~aw#h8e0NM>28VB!k%Pgz@mDuEm{wb32E`xp zrZZzXu{>P-^J89w+HmRWPiq0*sllhEfsjMs4h1)8Fl$9Vy?A4CyadbEc@Y(dtPq{j zU)Rn|&t@L}j-fdoo7g;YMHhtT?UDSv_UP}FwZMPpumr*xFglgk!6+jUV%DI>xNoGK zw{D^fd_)DteyM!K8GEeX$DPKH7nm^iNNp(b$n28oNSd4dc0C&$?cWlqP!me+ze-uS< zaoIVgQc!>#$9>D)XQH#z*8IstcBpcn(|D0@2Zpv^UETMbJZA4ZJ*1`em&vT@k-Bc}2o6*7{VJ)L;{{0|jRgrwLw3Q|~3g9PP zeD3mE83HJ-B8l}3UP%kQhZa4*r@?dUn6(Z=5O7A7UK{VYJVeAZxT3HfDK!{6fhepM z{5$#3RC*+Q-V4W|+oqVBfws#=UHWNKZT4Faa{*CE4>)?2ez8a&Gb(3ZkWa&OQQK_) z>A6wzm>7r}A3POXBwlIE&(K{m3Gn%tbX?f;Z*2NUJ$#0ALp@^!cr2dmNu`FqDm|Mc z3QxH`AtD_zfb-)ZCl7#Nj?cM1Qk)4UuV-s3Yq1d^0G2L6kutoJ3CwHowEK5l=YUfg{29VY$r2)2a9cl;@C=4>b-;QuP5zV0LbZ<4U+k z!og3wjA#VoQZqpYFd~^O{FefA!tLjkxUcSvTv-smiCs07qNwP}_#K!0fP z^Oq;I*p%mll_-!6fj-u6Jv7S|3jjg@N`H_n((G$}a`d#vQ*hxRTQ)!{IHRE^M>scI zq$v;H>)`%oCV1w;RS>7v4Dt`8K6?jgaOgb$R9!mQ+fo%wd`*}CGVF4*TEYcc+4mJX zvR(r7ILW@^d}J?B44+!_rKiK_ywdZnG$Gi;4^VZCTXrE00g9z3m{?i(@P_xo{L$E?euz2n!SfnHwbq*^@9D8<6L;9 z&}7T-eFfHL4-N>CM}n^(ycS@PoDry3IV`NLt{c{ypLx771zRKoCIQc7I*XWW(!0z%a&oPiPJDfwX=ox+hVQdPo zus&ey)PL#-F((UrL|@+%1f2p9Af-TUlSOWHfF}drLl$Ryf19nVDw?~neGI-fBF>J@ z%4+c}11It*`#rKYrDMfAdWbV9g)~dPAgJqq_pS<}vF7GwWavH{JZISr3x^O{j0-#P zsD*S8G`Go$g8GIw5-eUw(u`iDUZ$W!yO}dqlx>vtm9zG|5=2TyxJy78rdEeD))HXz z(ZtmqFs0CY(_^J&>Q9~U!NP=t*HKs9QS{(vTUdaK6F1hd zlbIo&Hy4njhTLY|W|RW&P(VZwPWC*1yu#rGj`C%ZA`Up!sv|8~-S^h*BXR-vNYHPk ziuxd+w!dU;r5h9fHl=I^kdm8yoPpuHjH2xIH#u*R2uk){r)sk)Shh>Hoeqmm2EFIC zEj!AC_9M;O7r*3BAzGsu1ysdE&c}QV-8lw9QLfhvxjZHarDSkKLrV2NGyIUtN_X^S zfj`@WtJbk<%iYLlSm(l1Cf*S;q>_DC$dcI0-KBsSw=Kl)Zi>M8!ual%;Edtd!q0DV zP7(8bpeKt7SC9!?l)}J?zV;T%eTvlvC*Nj(?W8wWNvWzoIAt$_+>HHC%B&(Zhm^t; z8b#EIiF;U*HuMXv7GpR=bgR73&Od0#S&i3n>@DGf`4^VK%91(vwm)ELq=i;+6Dp z6Tx4(C^_QyjL0VPTtuo}GYJ~sj9!as@;i5=tQ;3H@sES?ZOwr$9De!MW*-qG`+VZ` z=By(l_wN=XRyKB`gXFhVF6r~vi=BpS!!S>Bt+a7PEV7^Dje}pDyb?jowmU#rm~23|Ycsg1Jwc>hBfR4YBZB(dOX| zXSQ%Vrr>6vrOn8l#?dn7BS#*JwAX&FJr>z*#9j$aT3^Uf{A2P~i;S zh4CCl6}lJKGEBxNJXPcqPvyr!FAxM-g#k=DR@MJE`>i-PL96y@=-Ab*9T?%rk44em zMb{SbbE+@HwAFBTBO{{F4(e2&YH<3Btd{C~MuY9btIWd*L-MC5(th7rE8{=Nr(?8J zfrnb>sWe%w4YN;H|J;GAcNQ0`-Cg@#=_m~UW&g~8@hR;s^waEp5lA=$PDGwBac;{# z4x9ySXW7m}?Pu7qudk_w}xfLe42W4I|0+8yqP25xM#>TFd z?yAPS>b~+_6z-JNJ~ast0*5wo{>9P=ghzeq>F*g|p6IozAIOv4@9a^2BqSm&(Gir@8k9^#Bw3l;&%%e;A9MUsO?7#93i=4nrUe-?k@I3xr>eu z&(uzyLYiMgtfMLUZa;l+?iak8r?R)E=|Jk_W;mzzI=(BH_+g*UmUQHl?%lDsNKx5` z?t1gn^PLSrcnj(5%MTCUtX$+n5=_zr77v@OkI1%& zmp(6hwZ1+uUvu_j_v^V~sz)AQe~KTg_cL6xf%oFyvp^Vye^_3wD!r*Zqze8Vkpq`B z-C^%35rrEl7n?veJSM7IHMveNu1pj61+XVFZjv16ntaAAITRleX}i+-NJ>O z0P$(hJx3t(8C=%$AJr+65}d}L;Dz6{4J(u5p7`z@{w*EF12o(XFCE(!(s!sb^?L6U z=3bM3BJ8d{YDG&I@xy;|@}pa|2<^HfMJrWfb_>`oZt_a6|8Ar~XihcN0ultTjU0L%7{t<2y#(w7`AGJUC=vn4% zt|pGJ>Y*>A$MQv*Uw>yXf)RmAx6W+)f+f|SGe)(cO%D>IP#)9G9%YYm?<3n?8fK?! z6mITuuxLMtQRLdZAlhbxhVwS4E|n!NReegq6Rqpvr6XgsB2|Pm`$I{ZMZz_S-%4ys zXBE;urL!9!w`wijyYovm)AUGtz<)X>8A|IeN0C_MX4i!+Tpq za;Wo~({mqQx;O~Evk8yl@6wxXSsy?8L{>Q+yYTvY(t6=j9HkAb6X7^B^eS^8PA>&Wx5P;!l~S5IS4QqNJ5 z!DC)CYq$7$h4YGDk3vEUL_H^6iD(3mcqlfdmxR1*>sDh{{n-rY{I;3o9c_p#u|iMWR+=!3gv>EkmHAFdt~cn=;PFA&{3oxJpkT|+w|JUpV+Ev{EyPL9qQvRGX`)cUwe0 z=6&VMkk0dV1a$-M@9yrd-0+beU&tQ8t9JO3?(${1W0K{;z`L%`0i684*msXcC6fT+ z>{OF1lupvAoRL>i$33zYc0{{`owfX0m+qy+a^@B9^WAf72gno*xMRhN9tNX&VeN+G zM`gM`G*s|U%Tm{tMG-iU-urxzn?>{uT%O)zcA_AhIw_H7Tg&DOT!{hfwIZYs>>sqF zf@{NxvJp<-(0w&yG^AoM4|q8%4gDS}7d?@vPkBL} zJWx`yRP*z+k;H-z`6IUePs;j9f5h=MzP_aovb1g&CXno@GzC zbsd}&e{f5+;$b~dMap={Nq|VcD0q4u9u(iVF)Y z8JR-|0Nk*yX!9~3=s;AhgxyF1j=M16P2|Loto)=Zvdxh_;zhp9S;OrO#w7}bj5xZR z*^dpX5WSo=e5O$rhNW@4KR#ZT_aj<>Fb4S%8| z!+KP{xYMMcVx5zfKPoqzhMxSH(%ACUT(T%Jwr98}mYq>eL8~ReGJzlXJ9izeMjlu#HU zW6@>imPk&x7T6?ygbT1ypScy=zdWuS=4^8!R2S+k z=u96S|Ll_JI*2{yFTx1{b5lMhB%Z@@C*79rA;He{5R+07Rh;2T-g-p zDkEq{Ja^%cwDxSrWaSy<-S``Dna@HRuOwB24O+vIiZhuyOCple$sbs@mGciHka4E8 zqp3pA{GU6?gSY1!1b*tD??wo$1kauJnhdl-IZ467vBH{7Ui%lF;}P;3EZfMa!f)nH z;S2I?XTo*4N$&{_Dx1CQbm)VAPWX zrIp8Dg%5v#1G^5@eJQu828Z7|`)D<|rQG+|Gr~p1qh@ANzb^RgwGxsp31O59GdW}5 zk0QVgE9wEtv3t14mvr}VcJ1c8tZ>fX<#6Suf)fZzuF+TSQi8M!2KMWgvhcbquA9HE zK&Fb^+rjt}S@@z85Wc8vrxXrMvUvGiS5lf=qI&m4G`m*kPn|R`9Vm1FTE87=?c95U zIaS=N$K79#9q8y30Qr@D@k$yr42>BSsM5(SpsC{dEw8lz__np~!LbSR=&}bulX~8E zWs4&ze8Bq=Er=~}Ba&&(l3zd?bV{ZzS8}s*hEid{iVP}u4|O;}bf5Jc%weM$7gFn2 zkv;V$L&4dZ{ML2AD9(xkb`q$ze{x78vYg`1cZ-=(I_Z3}1|`Vg<0$rQdOaWt;@$^X zodoQH(xb?(F*qTEUo3CaVZm!zWCW!7I|Ch+(}~u<@Mvf^Eac)H7bUeE{iq84NMB(s zrblz10PP5@Pk=-ub{CPCb4+jm?UtM?efTZ1n+Y_DcM~ve3W5@O+hJ&A@w!x`Os}xX zu_={)scyo7vzq_(d`~RT4cM8RInIK{0+=fWgtohcn*{jw_asyG1^^HgoWUwRX7j1k z=&$zZmkphlh>OZm=Zqlq7H~vvAu!$t5{Lba;<|^qG{RrptsMkLz5@i1D2-Uyd9lv2wuqB65$UM@oB!%J;)H_x4;#;}-{~L)R4V@6HIH5P`%=G#3epJm$Nj z3)gH-VTDUmGyx6!YhZkmYTEW0A$2%@)&$Tw`UzSl6JkbrvZN1r27Ogr$r=nY9v4^n|Mg@{BO|5a6u5K7u+0q9W9kDLfVDT%vmLiCEym6yrS_o zxM}d6`=}A1LisMQ4oOIXv0eYZQ{dusCTmI3W~>K47O8@dY7@-p;3t&yB22ro0edNZoZHnR;O8Fll(?&U^*9&j4_ z+--Z^vtdzUFq0~B9ceo5mwclA=d}&Op-ogm1a@?2iqRXEx|$DA=&~+hdOiFhbHDra zk%{3dRCVW$8=VR)N<8xY4ChtIPgqa1Wx$sL22T;HJNK$xZ)HO7W8us$*ndo#d|c@8ZhZ=~#pCu{-!6 z{O4>PlYehUS9|eH_sTEe{do6Sxe@tr0&?Y*FfPy|mUR!&pSfSU4-3;xWUNOT=bfGG zaz34U{!O8wMiD-{V)J#Z7vXSQ!ySv7_4v^{wl>Cx%TLoUK~;VuU+)4xD#^*WSLT-s zY}=xh+C8PEHzO0<<2z2}+~{2@gVmim^*oe$wZZemdx+ll+wUBrj}KUO_P-#$_}aC> z?3w52@1FCA>B@H7UpN*hIWCnvfB9YjT=&%|cXM{WlH85`Ex(*YoX!4IBiXKvo3@`~ z{$Z;x%P$9p2KH1k^$nl4{osu1xTP2v+Bv!kTRd)|E`Io3wHp``TnfZ)=RR+=&AKIh z!f#vnuP?ZdHES=*9P(6dA(+|*dl+(JId4g{rn)^>&X7~4*4N(q%;@x)HG`FnaDZve zq$$~yTKR8l=WakQvb~Cyq)jD*+!fQ1#-FO>i5*mODoUo(~SXjKNw zcKg!K`B8mHa8g(1)mR0UPFuUf1@Z1i6H-cm=xnuz*Czxed8=ON<2@9{~30D6=T zl+`r!UIzZsN5nw@D%1m0CzqnSF3ZpT=GG?p^8 z))kNK_f8}S;_k78wfs@km$rZ>)W@I~Yw-t?DSCS8A=j)mw*4|2xEm(DLL6P30zzLR zDcfA4VWkGu0PX{`P8$SPvO@R%WgfU7ZN=wu3Bg=MeBn@T%;%MR)LnSDL;5Aa~+)9ieeK z)*q}9!?xxFTqmYB2{bYJP+b9j!mW?d7-YmKr*7_MEm>fzpu5Ry*ZK$y@U4H0>Nt`Djt!nlvg;Wy$a<)o3nw@y zzA#m|lJ*W9hK{^_Da4<339qi2)KA2w2WMyN9EKhjb}>0aw(`~X9+)ODREEv{8szkS z_5TMSt`xq2A;JB8k<=ySq047vdzRVx{tE7_U<%JIUL6(Jds0K(!xU=S?D$$XOZ+?R zU0-T)n~?)xbB)i+)nZo3Zq&C9BRisaJi(AI>E+t*5{#K@?a^k83jEebs3~2O0q?$2 zK^g@={Aw~Wc!J(l?HP#iXsGk(oBb?YzKdHOI-X8#A}Ol2N9;2L)9|KQ}Taji9q?E`!*3*5F&jr zAd%M+;Gw~WM&cH;&#(2@K6oS?vY*&W-sCGe^4ikq4w+T39ILXQUp%hcg&DNIeSjW? zr&y5#W?jNA)8e{-V8YS&di8e^$&G$tQ==!*8#n>F22i}kOhU;%gzBwDWRXSE%8LD> z)U2-$JcCtK9tqs6OAic|uwI7UMv#!ysON6=dutzL1cIavaHUIvSMJ2 znrSlhDu|+fS{5KEA6!aAqBFoA2_>eWmbx&(<$d$*q!2Z5U<18$Tp2 ztdi^&xpAQ%;JZ9MP6UUkt<_Z>1qM&vAG^&j25q|X?fQ+(ln+%yY=_gVn$+WmUGq|~ z-ocF@sRy9nDw*3X7L0|y5$e-(4}XtVAXo1RbhHo0$c+V_Lmg z4npfs)QkG!`f)#TaZ}Q%q+GzJCRx3!=$MqSL%`Q;vxX+;Y`F{F?N8Q>yoK}GA?&xA zFXzTwKz&nw?}7}A8xQPFolQ$Ti%=WUJCtJ41zbQuF+2!mY%a*Y!iL=Amm1n-JqK4BzC^f_(b$P0mNzJ(^D_j zde;rRX@wNsRHhn+f8~*Hv5HWhOtfTUZ88sim=o~Ier5Mkvx%E?tDdN(_7wIe@Rh8Z zTrE0rNCV&a_Xm94^=znp(w*go8ce~h1*EZlinLZ7F;w+8;`uk`YyrRuEZWj*9Ydsqh ze~$ol@%r36dM{5?$Af#QpYH_Z7P-G10=nkHdwDJFjoCyD>9bEz70ouz_FDQlNrnBD z4a^R}QZ+H8w=<`~nA~di<%IV5%__uyQltF>B2mdCz-p`c6t1^GN=NIjvPK>fekGnk z5e~-n+EBv9<44uO^jS|lzy0a-ginL80@y@5UH%Xml@g_it63g&06eLyuuErhmB{fv zleO)zi2^bv(Xt=-#*&=l;mv=wD+g~;(#W%Kj(v!G0D!pu8l;CTu%vmtk@0v`nNmD)R?HrJq}0FwVShIM_pYw*R5F~Q zAax0_=P$eelWKKf%aFAst44mHflZb&XEp^B!GaOiYT$`bjjFENRGprb6%ja-tduk+ z5aP7fsDaC~rXkp5l7I3tc?Zy>6|hVw*Z>n`(^bYt2g-rcOJ$I0iOx^^+Izm8;R0%W zfsc>C6a_B-I=YR&ksiQJ;f$hPk2~dRGa-7F$IE*t>GZ~e-ElzAWytx4+YdTO&4lll zE9zg;>%b*7Ufi(>w5$H%@gB0xynv(01Q!rXE{e)IDR=2-;S=xjF`*HN0@l7sTABV5pP}yXs7Q;M1P9 z;vO>OUcdn1VbJU7#i>Fo=~D@<%rL1_C0YQVz~e4w(B@QGbgSA*kcCzg83jG51 zF&56Lvim0b8UgvEq_AZDQEF!tN|)!vvCV&KC})riGkU+=h~0p7=>lg;9o7p z%!{<^zRN?`swM@v@xmGmb5b;KGkJ4~bTFA`s>2XgSZI#A^d%jKPmS*vS7m41hV=qQ zwP&t(2Y?!Y+%?TFc{C*~3_#Td*jJuF+k3HHllV;;^B_x z@2bpuzuo11qYn5suP?5I|0m^4>Xr<(LO^p%k$rm*$Fv5Vc0M^m)&jxH{s>mX=Ro^4 ziN(mxJs2$u$wzR${A@f5$N;mNlnQkdUs>8ER9wi4BY3E~IMCs8euJ4-e4}KA4`L`8 z!k2B-geULHmH{omQppc^=i1Am_lN)B<$z17T#y#NYK%UjdRgU!Y-25G%wuUz#DoFl zxE)Po95{~iEx9wLh4AgCg(j0)61_CV10=G`TWoL8*9d)QpZ0z8Iw#Xsc7=GQ!$i0g z7Axny;8hzp>NJ8MwynX~J{YNd`IUUrYD+rZ6I5EEn(!J#+rz*t*gfIXv_Bw zJ1UZ{-#Vb#gR{)pfa0Uw_i=-`ACqM!HEkuUD()T-L}V3c!qRk7sh4+#r*! zqxRA+^8(B(ma`$H1M2pFnpYKR$p)w|^c!9=W}Yc^%Fu5r9`;V}&8MyF^=2=ek?3Sp z^|$2l3w+65@=Y=g8C{1!41CKKfZ`temHubs{f60E2M>!w3HE#UU32k6=BJIk;Qsw= z=CnU!O7jC%;W0s#Du1AA%Ca5bj{gjyhX$*+4IGg0GF{ZdJLOl_sP9-u99(X<-OFIN zI71KWnXEK?vCEwpT0u2OtGWEBekuC)edP1MtKQ+b^=t=bhfxy5->_`?DIhSoRGmDn zl38_>FS|tq+n*Xj?c87zd$c+5MrHj%h;?Z5$7PfF7Ep`FTze5=4TNh8JtzzD$`Oob z=p*?xoM;b4{Sw#d7Dq5VfqU-*u*Ki+m@`>+h=oKHRA1C%Rp+kGy84C< zOW@2mCGesYYBcEZ9IG=HTqx@cNvCf+A403YP?b-(m8 zyXeA}NdC;Z6p=Z_8LHj(!GuI}M+Crk_waA_vpzBi`AOzQgmtmo~Whv zag^`G%TG1>zA48P8516Fj2fwv^sGduO`D9)Tw8NBF7xJgjT}UuJ<{-JNO)X*{M1{2|JU9Vnzt)9cdA0$lfvIZWA}QH7hV`)&c(fLSlPMt_jqAr zZ?fCNvqr7T0i5aMM@gi2>HhX-eAn4Z{mK4wMRw_HtK&3u12j0=K{npxFjvjcDBQ@w z^p5r`t?q!9i_g+s_ijj%pFgj;sw3GtaQ7W%Q~ym`FB-F=wyTQM~B<}Y(9$X!t2c@-aXeSicokz(R53pSN;#cEH~a6sQ5?xvbHYXVZdTa zY&cQGyR@yk*Q)`V46}O@C7TOQ^Mh}6`FowS{ta;3=ODK#1+|BtD8F4=4KZA#!0kk+ z0afx6^Rafz*GBUv)4Mk;CvDq_%b11hYHDyiDXD@+?$X{eM&;OAUS{ty-$gGkb>fy4&TBM5C&ROK( zCd={n5^AK2VDQEzI!NT~u{;cPgKTi9uFp?3{Z3s1cHOVLpAcCvH~}Egh6JAt{C9&a zv=0p_c#fhk;{)~sXN5)BzZ=I5DLDDVmBT^cXg!gF=Tx!;bt|S;!Zsx^KY&T~PG8aK zVlKqz`@rb&0$jq2?kr#|1|+xIN+@?QgOridUknA(M*gaGKpu?-BC_v+ljy3IdM4de z^De{T1ify-v(&_cBxN$S0oODH+S1y`-u&IumGtsn$wSR1{~g5p<1}$#j5wcX^qwl` zb8WY;m8i|eE-uIF|7kbVK5T+c?d*?Um|}pUQY)xDj=XNg;AVunF5mjHAcIx=Ncul1 zDYvnerh1y;5cr#?LuQ^T=GUtd{&xZzHFe`AC5I*UFKBANisj5_xn>bAgBz1oYT((m zus^g6l1+3zJ^nVS-8ZBz0mVHP0j^wgUBV@kT6cV{PB#%82P&n@2la6^w!s;Bm?1^+ zS}!-6F~sV8S?3>Mkg>Si=8=u!Lps(cxY_Xp0?i`?aMBEF^^esHOmWJVkG+?ERBxw` zfsauxCb;Li{RsAjAAe{wXFiG?$_Uy1@)M?Z9V}PtvuA~aDZ$wV7AD!3$MQN}W;hEb zG@Fy!n{drnTh!`5mmGb@>FE0S24f&)d`A+jS> zbac_KocZ;)g9!RScq~wPk#~KwFOp6KZ2}X7a`x+yfnFMR58v#tUdR?u6Ea?o=3g5D zC5dlZFyo&Vw&MLYsFprzl4`IHEz0BcQzzdntjjF(@nbZ+qw4fn(t(1N1-;7#?je7E ztW#0|j%M9TF+k`UV4ebva~D?($tAO(P+*MZ_ABs^rr>K;m;C>#+1~!0jJJ5np5jj# zyPN<>__~5csT}QD;}+-qY^@2DuUm#xrR-8)y)%qX!ZpK`R@Wb6^K^ItmebOmAgG`; zOnpG108jb?=bAlC^n+Hx7+FKWkhK9MVMdhOIi2g7gOlA^XpRK0YG^Wid%7 zRojyRWfiR9oO-?QIz2XTqhwOAr!4<1>1*JsxDW1B5HL3$yXMK=SnXam->6K1kM-7< zb<8Gz_ulaA(%W;lly!$&8q%Ofv|pf%l)swIK&eLf#`(sZX>iYq-tGJ*4*2PGJ3Cdc zME-Pr&I{a9@FLrdxl~1>#x<7rh)bq^b*c;x&us7eXsaNX-ns4QRMHOAH1#s-fYnhK zf~bt^KJAiVl1>={d zz85KYUU4UVzMLv)yrs?l}~D#`QW}LJBcZcN+*H7nIZ>{g(V6 z2Vy3oS#HpWf3r_&EX%#Ul*AJi2g{BN=Rva~bs|8G(crikX?0U$cVvy{rnPrgL% zA!XlJ6%hYM`?T=nn3*Vvj(AfkPKPCM#lq8bv%qd9yEH)h@I1`sNSIA4=UuUoS#kE` zxR&9dc^=xc2h5*nhQP_cOg+8S zM&(vF1>`XW_t=Ch`5XV%Fit$u4*Wd9cT*`e;%*Q*4I|6yMT2`qm*TK_&rzQr?O?V^ zdd|4I;?~?UXmpA+Ww!WZDy3znr`yheCgsKr2IYF}xZrn<*{p-RiPrD8v2ocR*fNPqfa_3#4==&zYYkteEp;5(R zzoS=da`dXWPWSE%06j>F%9Tp&s@d%VG72hAcDkgxYxBfTkgt;eh~*)kg$dGg$DIrz zEN9RQ&&cs-jq3$yn4Csy!#fD4uSeLsMr}4<%)n>i65jYm9?WT~m0B(e7LpWGsVAMr zht!S1yth4f!U#im1z;*69Kj3lNlB>LM+d8n3ENIygpPsHA5wcp6#!$?bhD4smP~+1 z8vD79$=kOCFXan~xbcFQYYV+gUvJl=l$b?lOeh$XB~fYcdb9;d?WHWMvF z0x=!=&ykJ|X{`J-$Z;P*%W~hw(9_ZRY_JqFyS#%?bjqS*CT31p2KeHcN58p)Q}Xo& z|CeY1yFi7PuS1jN4ofvF$b`}srIj^%cU+iaJXL6Gz+A8Vl0Pl92Z(5h~ z&2#_aj!|Gn^JcgKGTxvF9qVoD;ClhsdcP2O4&GOi97D><1D~s{(BE!@(bSYxK)L=- z$oo&~hCJ>!V=sd64Fi5*Duzjpx8!t5%g`fm>S_5low5ewD{#o^Q~76P`bX5NTjEnWmd zXY7})_$klOefHIJ4^={#3Cl8+N0J!o<$3Jx2#NCkPcGTV>tXfH?vW|mzKb|O$o*78 znD@bT2=sdZMiaYYlFPL=$cZ^I1OU^attt4WW6z9!LkPH2(7GV4BFVt3W7c6$m;J&b zy^{$70;XNyes0$m#4mV1GpSP2v9vsCQ>JNS(D-a-*7)T`2}v|48SO>vXS+|!k|R?r zHdnGdAIoN1t315DWqnJm1g>M+hJXK62x#LQ&$c80uHcU3TL-u8`|giOI3Kgku+k}K z`uxg3worBYcJD)uOYqVzsD{8;vbAj5`ux4MkZTM3WHp8_?&E)^9dl9*H(pt-D#hw} zoUgiHm7j$9r6g|>pX9RSjj))p_@2WqI$ZQ*QPt1E94T~fth2$Or;p37#a>hm@?*xn z2$x@VVK*0d26A`a?6&lyJv$#+l_v7vGoRt>^JQVjv&bHd|4-VTeyZ91M)WPDOg)yZl&v}Nwsi)>!o;|HGhqjTxAXIdOrv^km!c>a-R z-hCLSIevZ}ef1M{1`e6H^hqMWrX$+B*;fU^{r489e0bLUEasg{K{{v(KIX2;P-P@v zY@uhZYyN>~9iehML|Z}MYBu!#n#7C5rXluhi}Z4lNl0Gj7Ww|*fWmv*rlF4OaxVtl zv{*5M*Osl#S7me~@Aik2<<@R?Wcw@OFH7Crt129PpzxfNtGXK!b;r`ibYkn&Bi2uc z97eWfKK;nv(<#du@Ab<4+qMQI8Mgm)R3r9CUCBAVWAgdfAK#Y>E1MNlL(fq=x&+gqjT__EsE66~oXGJX_gIrM3obS>GYA3uHI zOchrAd=a?{RWa&mJagjOo_nF1tZHbc61wYa%!Spe*Hpy%vS~jx1Uanykw1Lprw4a* z(mm%br26+eqgIlOXL0!@9O>f<7=hODd&)k%7M&caLe&xP87p`{Gh$rd{ZyBEUK1$K zeU#yBFNpAj#+C57?v&~gb<~ytDT%=twhs#zX+U-_C>D=l@{ke_w-4 z<;9TOu^X_XXT7nS{IX)dM&-Cq0SkW>oCiII!`%zN8SSiQtXN7=p}-37fevNY&{s1A;7bSPM_Io#=ej zq2XXcPkS$c$oKyzj*zJ%98!Dg`c_F?mHwg|7E0BfeqnW($l=n(IoWxs-;9)S-wf0< z4HuPh6q{#H_8-CVOJ6G`R|i8iQ4+bo4iqRV9L9x&$&^lA?EH<#jeA%e4ibURKM%|E=to`$nB_0NHj) z83DeirR`uz+}-&Uum;yEb`UdE7wzkf%mpROYwHZ-eUH>R=0lB`g@Wjx?z0|of)=1u zdl9s*7fetk>`MbkP~!RKu;hafXrWU=3tDy7H}CeI$)QSE3?RmW3FVmsxIN-|JFN=e zE&!Qc}s1UTiXi3#TLCTO!+_Nex&$F9UcA1r%!XZn|6 zdfj7m6+{!zu968JYyobv1TFhds^L$)GLkrp{m_W3e<%Z>n!8#+^-K*q^f zjITGpN+X8@Lz4ZVMyH6!1AWb1;2Fr%rL z{@@-!%T&TKid`?FKshcElqtr&_&Qb|15E+(4yONr5huVG1MVNJkq6VcMqnCF1fTxi zKT((-q|sj~FNc#|Eq!v33?bj~2CoO4QQN(2;_H@n+f^=_1?o1_5Rwa85(^tVa~G-$ z{WdKdVrg!4|uR+-^5I*EX!H*BXiN9Z6rVgNA>NnYcA- zRHXcCR)=pSJMFDF?55~51?eeC-etfNehghLLZgRRAK|zb~!RXLXItutU|3( za^+d_D$K^e2+#{y;*ZTN$v(GolSPnHX+Jujp1lLLfJO>ybtb?S0VXj@m{B0)bwd8) zm0q=Cha|_td8LLQ>!6FJm`vpB0VAZZ02}c7xx=XCC%`e-;40_WrlTe^T`o zXTn($NP7A?b-N7VWbL~<%P(oa3sKvd8shnz%FAqD21~Dswk#p+|I;>w)*Fc7q#Z%) zEcMq!o_G%c!1uWL`&(~}k7@jp44nnQRth&zx*hhH^nt&+ zQ)^?6=676p+G1zURDg5+wK3R8h(sO`ziy$%w;il!q^%eL5_i1>GF8lras(Ws2S7Lf zV^HrcFoi-dYFX$d18?*K#weg{jvFC8sjcHN4Wq+C+N)aD%_ea19!s1%E=OKv_-#4* zS>b{)^r2|zVCS-!NpZ9};Q6;1wKzN@q=)xe?Re#Wx#F;<5rbiy83&WFb<*YUkU_DG zZZ`i~h6LR}%=2tzJP>Ktw*S`riwrep)h$uAbY02E#wku$ciN;@8gh9Viw=u2wPI%a z{rX?a{ahZtyLQ_arE3@<4uJz|A_$rsbN2bGun*7LuNnaE+b`Ro&lGDE4BmXvgRG#6 z`d-y*gCI3iDdyjr-ID2KaQPPc%*(wXD8+29h-m;#pU8CyT-TWAOMm9Rc=Nu(a_P5_ zy38&me|T1al^!jI`rXmwcfh0Bapo7m!nG-H#x9CiZR2e!0RP4&CCdd*Z~@)9!GW&N z!WOR_qe)irYl{`NPJk*bf34j*6pN%=e~$~oPs54)lHC^ROzn9o!>TT8-2SEhTAU%w zJ(%lI#Q;u!3U!2!9L9FeKw zR|1T5>*TK@Du7@d{`EhpG)p(D+*jZBtd2==59VRrZel7@sX9WSBM0~Qk9`LYh=bie z1a2camF#9qIKzN9d$2<+A8?FIkbn%N2TOj8ID9 zY`_~;ysJ{iiXJMgLCVAloL?#ma&$pc49=!A)VsIA=^)kH)Sy|HYLhUb(*@edwEv;% z&Euhb!?%B}%GxHosVGH~Jz1vBR!R1drm|$8kewOjg9sBsh^ffFZ-c?uWiM-tG4{2Y zF@zbj^t<|gpXc?we*Y$8=AQeyuj@R{<9r`}Dc|#Q;vZcBYk7NRzbZT_Dx0v20Qatb zFE)vu(nM@Dz*0_vd#sii}jw$B@AluLdpt01D}8A)p8^&yi_m zbR^|V+8UFyuHn#E(3bfRvM1;IfmMWnPYieb_lj`<383~bLML#uhku&eupgh%2w_(L zGuE!l>N5XdW3uwD5%(~z*I2%{c6g%6QPj84RQxV$tWf*9aZRfsrV@$nOlKN0f%1@F zf=}`y{(C++n}=N?;nQ9ZiriWq~E%UVt69Ne$Y1P%L7Tegt?rK>Oy;L4iJ-N4L}x}tGT_GsomJkN32MklPg1lzFJEL0zj;Pbe=%RD&!W^`TYgRGjO zb3c(zxKr2rRY~_uGLGLyXWXPmK_XmNzA?>L{5@&>V<_60>HM5ESY^IT-UQ^uHXyhD&ixrfd*9#(YVye#o{+!LJ}* za#(aNjy3JkrbQt8ZM(;NqHk$M$ZEnic$}C{%s^HZNvfVY+7|NrmRAV9H0^NM)sNr1 zTrlEVg=_H12#0!V(wO~YMYWzFpQQ%*heKhH>27$tYg{+h6krzuy{1N3$$!3&cLly- z_96QAX@fAf7iDKGGuVAkAa|&lpDjIBNM?3Timv#QKm5vMWBg`G-Yu%$Wws?<@?uRMxgf4OjXWPS+S~7j<~Rz@vGl&MzZ&D zXHM6cgde$*2GD4^T6>)46tjWKk9yPlLbbHQE!=N-cLpsr=8#M5ou-~NARn8%trd_)|KOcmE@VuAFN~Fls1gxNGI9r5kBl932l8CWx>^ zOIL5L&DpgfQgi#7r(GA1QcQHb>!FQ%me=d!=Ewi!+gLa};a@c$I86DZx;Zj0Q?RVg zbj`S4spd^L^LD}dRw@PB30%4HN)EB6tv?UXFYpto{^2HdmAsoM@ImEe!&Z0mclGSV zcG&~Z(7dZS`0BkSt3u~|mxJsb(T7S*`T8PTmy~^GZ6Y26M=sP+=Z?!lrccx|+TRFL z^FNQ>l)=~UXyp?UcCX*lGV+_2{PFtNXq5eyUB9=T+3^}hoLYZ#;aJ+(EGBQq+Vc3; zGV>Il*4~5v@LqQ+?0`pib3#dtKg>7(2}p-&0apC zpe4#QTx`5JSfB>;v-J0Xs?z71aZ}?NLf8y>?`@l%`wmDhgR}T$H#H@!SYQrM4Xu*5oPUP8{~}gqDX-KBhfz&#uag=F@w6n16lGQjhV>`R5wC zayja3e6Bvbrz7)<)eVpU{VO!2aP_6^uG36075y4oC6VQsM?+ebJI&T6XbesT3|QFM zR+K+O*9Yyi^dq`KRISg!Q8uSd(Pcy2j%qq1;qVEgGZD{Fj{!UEgtoFvzjPe)&d}|U zLZp+C*Sl*s#f!W+>0G5oPr?qSv66w@pu1w~MC9>+ju#iMh&(bOCB^pf=tEv}3Ycr3 zU$N>%Oka;E7VI=UOf;-Ly|b=TG4&cXt!r;PkAC>8NcCCuhbxQLKtDgkUxuxsVPg~1s~fZ1|JZNMs{5DGWD*sY& z@&(DIyjw$hZ|z~gZ%KU!(#8TbOqbwuw$;t-Ay2y*%V;6+C7_h(WC7xLJZNq-?xxkE zCY>#yp_vz8d*08XlrR6cQvM+HeNt2PlW@MMSpbb>@Alv6D=!Sj){MHY zuejNnkWMNsFTfF(RO~_nzcb2k*MUgWWbw65m-?UYUZRbTB0ah>-FNDzK7aM@Y4{GZ zSiN$@-MwmXmVvcl6+DnkM1wBimff#Eob=FwWeU>wQ-xb_^z$;ur$| z%V-}KQE|@>u9lan6%gF`WTq?g`_Oct%H@v^0Hmtq3H#T7t~9ApW#Z&uS3-61@1BAZ z67+;w86b&VK0^W-<&3?HfvPz4jJ4z%i!N!JkR9np)1UJKt}%!t6MYbfG_w6G$ssRp z+4s=#xd&DtKhMb=Kd>gC|3rJsj4rTrWu}M-EMB?*?t*~Lel-wIt*rL__hxN)Tj(JC zEuzLUeAQ5gH34cz?ocfFk-+U;^QfhoBN0E#U(-Rm&PDBG5iW?9KNLbC5Bu{c*<#DL z9zINE)Vbq+57$JAvI=w~`zG6fk6e$SqCf~Gbzb)q4_Bl3oWl87s@%A)I(UkPq-2aj zcxo9{@1#?(r#^Wc!c{BcD-KV_;Cu?zQ{Vvqq&(y?PbTGAy(>Y0b8Oz-X8sFHuvzn5 zDc50&JG-j$iH&TvMG|5MIFM@-FFktsY!gKuv6J!AUN>dKl~|ul)n9;fZC-l^EjB0i zcJuXY38PP&H`ZPwcJw9Vr=D)XP|%HgFd@ASZZ=oTTq$q2*VxY9C~3Pu#^KrXt*EF@ zg^{ZR3Q6-ZmLyS`$5wp_7bqW?IG^;mQCcsRVFY`P+psAnEA1y8<#w@1b= zaM%f-jT$uRbFGw*PEm&0UA~j%iSgcf@zA7%kwV5$&E*)$r30<5Lbi}T+jm>YpqSmI z{0frGY}9bi^yl{^_Ic%mryfvWFic0Yj&SDMbctGYvQsN16vyC_;{~ z6xLXtOJ|JN_dJ|ZFkq?~4}e+|%zq`vdooq7%wi$3j-T!?T=)TohO=iaU)tjHrYu2T zys0SrAl@ZP#wAd^B>QJoIXOXfsu)8a?daKIAHyX93iK%gQH@b0Al{PB1lKRo6O?i6 z1193-CHgt;u?Sn>X`HV*h&gPGN^%y!ymB%B1CTbppH!C!H`VxOXPpy+i{B7cmWtp(={n$mAb({mCC%7MkVd10j)qbW~e`J|307`?UI09Lpl%sE^bog7X zW1P{9J$tuN@2o9OhV1zH$neeu>qr>tjEf52Q`is-jzSU9`?LA+P*O0@_HuPzB77 zge~He+;Kqwxn+{y)%)PlXboWPnDNTSZcZAun~JE~;&GIm{88V{)9L3T<~^pdd7Prh z-3LM5RQfqG1Fbq4Zv&U6;Uco^>ip@x)%!(y5YJekNA`L0oEvDNr4?UxsG~Q*cQ77# z7YJMXaXz)5^E&5K7;WHvttiW|w@`Cz3L%fZ$^bAs{@whR8VsZAgk*5v1S2QCPcwu_ z9{NsHI%#M@giKEr-Z&tiJXN#iK>_%qt@8$p^aeCdKu3w^D#SNb%KTr!=L_DJ19Xp9 zhmX|9?SVHTACG`sS+E`12T|}s0M@<6?`78$SeHwJ6r|tF+-^1UE~vkMyL^4@KBD=x ze4b)z-@46~5rH=XHgV4P>?`w3XnVD8G-1D{kF`&&ZHb?Qb6y9Hy-WCF<%yd6Y<$vl z(-Q;6C@$JIY6J6sI^U8xu*<<8Vr>}sJf$^AJLr`D&X<0O^}<@DydBrTm|7Sq_%lW_ z_IQb(%gYkq*X4NF_Hj-FCG4{MZY6f<-@uII4IJrV>4?Byj0IPbZA~ft6!7_4x?(n1 zmuz^1kktlK>A8czCrVT%c}~ttv4|ST3A%H1&yamEaT-{m>Y89ckonVnwV)%f`puZ& zOAAvh61JP1WZB24<28om#mIw!{GE zJ{&;LIaRlgi%j5SL3CObaTb;W_EXKDTx7R@5GhBr2#J8Muhz`ojPI5LU~b&Ib-h8p zHjG!AfthmjEfQPC+ugwgAV4X_4|P?~JMi`tkY@A6BNlmgF=j4!1K6wsBtx#fr9=SK z!F)uJ=33n&HXYssBaiTOMAKcd#p>xYxZfe9kpx*;kRr-HYy=%+ zRg%NOE2Ft;a<4(q9zGxI4|@1(oJ*2dZHe;z_ZAr-bnu%4^var`%O(O8w!0*I4pxSy zExK{%@c&Y)_AfSYe?{-T3{^6`~HfBeX&B^Hi5YlNbEm)pgJxhGKm5 zDE!&G(pqd|=SxEy%y}jk6jB|3Y#)iu%o5@8cyRgR3G+mtyB3XRmyGDExXdLsKOn=vwaSow4;LyGxc?5U0t6^>3++iFfqLO%1))v2=eCcivf7bcMxnCTzRZ`0 z19I7TsE`UQ6jq_ujuLUY2WM5!qWB4G77*8%?jvc}x=nhHeCOm8E)g0|fmQ}hcexc@ zd4Nc+Tk|a4{U_8`+xq>U&+YQ0a(5^yarAz(;^E(;c*4ZNg}MNBL7qZPK!GzWg6T7V zdYIU*Hf~un&hG$U(2-8^mU8m75B1F(xT;l1f={3fw;FEF6(-@6D=OdeF%8t&)vFGF zrW7705FT$;9?hSvOR<6IyY8Aev-e>V1bAkeuLfSd{F$A^9AHlhTIWWA<%T}xu{rz5 z=aSIApT|D=FnN*pGNo!0ppk(=m!B;-Rv&_ePP{ruT^+-HLgOP_lP8g+d-JkEHs~r+ zoo~|5=%UZ6cTqb{Zk{CA4UmTe`PZOE;il+Bf$s+aMe8Y%l&$k)nhEq%*^R>s&KI>>TvHs>Yk6+pDmbO#l6` z$lVpZZ`BKRvLfeZkte!YDT^veMed-eH*2YQJ&8dDdC4dg<1$Thv*d;Ona2TfdB^po zUXv`ewYy}PcSkO4wswwFKS;*697I&Vn{QJo&U@5DN{aAuU3TucW}C4^i^J_GCY7?4 z{oe)0^dy&u3(f5BhZ%OisP*g*o?!5HEi<1|_mfRpTQz6=ct*GH;oZKML?icKTZ8(y zT}MoNT2J#+$@v>=)DmTEqDOyhn=o(8Jbl+@^tPD70^8M{nXwdkxESy78g zg=84J+R+7F^WvQ(Cb8G%$|uO>Pa-oOcIwc1E9<0+`kF<~xNXE(NJkF}!YW11OpO;CYnv5A)~g6^lE^DsxPp!V}^TM=aSTCA;6H3&$<znEeZUO8 zD_a0GS*ub=y;QZ?CUiFO(Ryf?XMUUWWu${{tLpD93=WdyacUaJ3ZxISxzy*6Xp1pV z4_BurnZlh*tc4BMP9=Y>D)742vi>};Bj{cu${aYhW`Op1^0J+St&37(v+7EA5NmP^ zIPKVz>}%r=2?m-5!IiRbzqolPiC;pHZ^6CNB-pGtLbcY`=kx`24&4c8_%rEF3ja!e zfRAUso_O(KpKuoRYH7Gh-Mr@nUd5i-{zKLt3@Mf zH@z!k>{QYP-YkUA|u=_Ywa4%PPAE zEv68hbP-za&Nr+ou}bglEZu-1S9m2TWR@kHA|R@}I7CCKV5)*nZJoZan=3Rp4&2SQ zYN5fm*5t%((~PP$ksHUa{M@sY&F?xtI;q2bh16Wj`MJ9!eb#;Rrr*=oW&oFBYcBw~ zUX%;TE4?DJ2A3NgNB`;;!MBdBFOs?=e(vzkoSjG?KajU}Y^CO;?Grv8y%^EuyMh>yr+Dpj`#@2<%nHEY$`%u~e@ zVYO?E?J9i>i6lF<89~yaS^i1C**Nq(|ABRj`rSyM{Xe@rJ%lCHV2xsLn>9Te93CC` zey!!;PJ%;H=p^XS6!zmBkrOs8xC*^DJ`i3Sw^5@04|uhDwVl&AzhaAWL39guLW_dP ztiiQX5vmbWV172G4Km5-gmGzFfg?f$a`xzOXI97@_Y#VsRmpSm$f$Wt_}dKg8zz18 zP6y*NVfM=x@^Xg82RfUElVvA0l-Ba*9UiNJxjR+;PVZgUEocXB!#lD~OQUnsY8A@I zbSUsgsQV(Fv_?*E>3^Q7zu{*uq0h6X-+3$H2BUY!j+LVcVc0Ow3^%yX6yI30mdLhN zlzP{jIc7dPn*@EM^Zk4G!DBbiym6^HU46daMD78aevTDqq5{}6-IKjaP@rA>6lucX4@+JIrsst2HeYs+# z^;s{w%b^PI-)c0bTUdaOh>=&}U zkb#XGE$u?lq?Y5V{)c?D@whZLkc|p}=dE6Ee{#0292>b5y>xhFM&WyIeFf>vo(Str z!tHbUP};UTD(8!_j;vG6hPPLkJJCYX;FP=Ru3yO7n>n2=g)P;^`E?TmQKb;3oTB=H z$J&CvgN(J>2Vb7QuOQ2O@7+y)YosCC4Ck2f&XV{!~6EKS`QupW2`ll&cBG*)>2*diT7SyRfs=%mVH_} zjLe7R+SXsNoq(mg^7oXnFWSb z^Kp+GjCi6x;~0%&XfZX0*t|58>2=dla~0Sz=7vp{$L74yfZmpt(s1J`VYHhAmNk~` z-b3`cTe_R?2aeGW&ePWYTZie%4XNToLipf@(*9eR=l?)N5ScJw1fpMXR`ioKF?NgB zo!Z)U7PwnuB+FFB97{iK0t8#EJ^&|?hZp=n)9TR##21vEP5Cb^GjLbdyyi;@Y?AYF z4WGjr7&EsfbYLb?{;n=CI=n^(R=Nq)AD{R5&BP)bZ{HC;WJ59Wn6goZByCmuj=le7 zm!j^*TFbn+vu*BDR9yeypY7_CdAYf3SZu4)Pn)wY!ivSah+VdZiE?_%()JfX&N8OAWuHT7ycav0RrCP~I9Dc_VAzcBVUCcpygleH z&92b?uKxPeu2d7jR&!rlVqmBQsgnz6p#>LMbJemJH@7gpleRtmoy3&I&-=yuArK{G zu1x6_a$v^hQ$QEDpYy~S^^YM z?+0wsQb%rHIBk@^K-i3qO$|i)qE*M>K%7y4UgWONcA1xQc=a!^P30tl5{usrAyi+Y z*E6wAB*pvTgBxRS#`fZi5H?SP3w0^!qDTsQHkZV`i;PZz_rB@F=E>L`7ss`Z)Y2<@ zV@GySy$*E5&Lw;Ig3q7^I4mW@@QuY$Oi1F$=qSYz;CsHyk)X;2NMphnudJ6qaa;Um zf$z2e&3FXtBeVDhk2xK4XmaG+Efo1jpYWn; z$b_f7x_mo?$XNT9_UeRTj*e*RBQsMa-5yRtF5p0Pv9=8}Qu-EMVmg&1u=(Gy0Z>1t zvz4Db)CWP*LfE!53z^FM4#rn_u$O^wq~tVJSp80owQZrA>=tcLRC+;6ely?yqf{D0 zu(p$RXW&zjGn!`6UkyH%QcZ$?b|+wg_YMd=D&B^HF_XTP^8F8GGJsIkgljF{s*ZxE zeQ^+n_L`n@@Jx`EDc!9F8%oBOy93m3Z|G}AAGA^bXA&J@0jE4X@ymsa>9#%4NQ#P@=avwlUy+ADA{Y!TNL<_OJ@k|)r|2O2 z4niKii|b|YEagt>7fbSkXHBMy`l*X^Ed|ve7hn8i6mELlhI-0sxV^l-<>WujgSY|Nim1uEioUlDrfu`B+~RqI3oM zZs|)l{@iSndG@rRIz5kWtpgkpX&kTmcl?2o;ZL65X@~brFcPD5U${)$9ZkqvcnA{m zwnR8yxm{0kFT5EetKas0QR;tzA$CHJ+FlCCMA-i32$2E6_XNEfl}-|lWPB#k_K?M7oqHdc zSArAhI7$-XzLoaIuYS;{G5sj3pG&iN`yV`nlf>xqpcs*V6z&3zFgZ@O0F{J{PS91z zo5Z_>i{gzdR9A(71nQDTt(l6LEWSnBQvCOrwJnavvJdS#ow|;S7wvX0tV1>$n#(~T zim0^2C67yX&wqmQE12=nN#$cFad|P%Dm6vg+pOTe#{}?)6&u@=o(+RZ^BX+zK-d%P z>96^kri5YCGH^r12Jj_auwF-n|3I$%h+Eqq#Fz9whq$@j=Xqz*N zw@j0Xh*nWokaBWQYV*6}dBpaWpV$M;v?n6>A!)I*_U6zHksn{MzBSt9H68jqe2!qS z6cEWuVpOS`dm*Dkg^KJE2=gyi7SDGv|EW?)lj)*t(< zyeya4B&h&%H)LRx6!hXGPL4x*ijIqFvKGd&M&}oEB1rmRfq*?JRO|w4xexnDZP(94 z`M=&R)zL2xi0OXQU(D1XzsdQx?zV=^vIo{Y$g_UnZhRmZibY1{`N9-{V$86JL?OFFR%2v_rAXzmu6WX*_ncWIYuJZaIgX4LMnyLEgZm? z3XW%^tTc}+7viR;37Se$72jJ-&P$xBKmRe4Ph%dK9;8JVN?VT>NK^t4l-y zvUYBI$ly|IaKX*92I?~x2h6i%oigyNUmo@RjFpxswvsoU#?5>n3N+|2)R8SbRTPnx zrsE?G0fo*cYnFi?;m>VfG@0giALp(XFU#%ou0GldDfS0p0^kqFfW8=N=Q(vb+y^(| z*TFtD6nyjR)FWG0L0v}Auw6V?RdG|lAQxYNgT(e;B14+VQOyFI95_ZFWNMbBlaA3W z??v|*P*GKeu|vIa_=Oj4zJ$jRrht++*f7=EN+Fb#R=+mLPT$y{@>7{-G2GLZ4=8m> zcU1&VeJFOQPO;luXCFm_cVa>N#*jsP-;)mumSRrcVWB>OwYq}LH7`MD0jD-_aU0emxeQdI<98d)QzTdFU;}wPQC9(E!+NC8}_f$ zxix6(F{oXwUUV)oX)MhOa?542ni8tKBwjvwxzYu-G@ak`QP}tv8z2l) zNc>*sXtsq)2(r=H8nmt!G}(0v!aj0&yVP_t#;pyuQU6zZv>bEdTah(@N$ zOU;W%Lanz44+ldw06ylIfHL9An6R1mr5i&K+VSpEiCDp&l2;?e60TWbCd&>zvGrs_ zI=UKu!qsBl2xWqKH2*q%Ni6XbLW?C!EH$;mAd%K1=!JRlMkT9VPy6Mu`a1V71B)Sd zJ#amh9^>l8&d*!f0=MQwBI~}y`Up6VF$)HT#FCr zm8Y1vtGr5G_^8;1>zn3~1O^X*nI<7nr#+bTf8OD~G>#bR32eC5ybK*`Vl@t%<2}u# z0;BswB(8c^BRu$qX~(o;Lj-0S97rekmx_hR_6D$t zJ5D#Ao9s73f8Yy4J&Rs$9=NMyxfX&E@76Rw{g-38ANoDrF!T^}li$wrjz6RW?c&}L zbffU7#0~(gj(^5zpN*-MyRO#L8y2T$4Vt2py*n>3tbBl!oJ}uWt=eYXx0F>jhCemS z?26l7r*_^2M#%it=LsQ;CQ~u{7b8u2?IJWpI>C}CE`p;wTLWsPoF7llMLB2ruw}G3MQy}CYsLG)TVdDH*l>r zbL$=oWe|)4S#leKksy^+IY?A_y4RKKmT-z_Yu@Aejc*l0^A?ORW$oVhM4L&6`gRU3 z!PO^KcCzGPb4q>|{PdjcgCX%ona1ohX+xMu@j}-l2^TTuAD?x(fJh3LcBg%X=gG%! z$H)El?^=gxBZiO_hl}Tlq6Au2+wSqk#i>iDk`v{3xsQj@#(x^;Y)g(6-x882rjM9s z7nE2W%bO#k`htiNY^e=+tcYRI18jN1r7`hvZL6@W^fo&oh#I}a=gH}f29Ut;r%uY; zB5iJVSUXk;G9tp_r1C}PtdAX*(;b*xyKuZy4-Z@|1~1|5P<6lLxDD&!u@cHi=wK-nYv*+G9VDe?|Pb2lw2_dJ;!=cr)gD zNiwNsVWyO@cM=9=ccFzYGdaKL*p=#Nr<`xNp>!A9t+59ZmCP;bFg4x87o2JZGiu2l=e9x9H<4+|aiYiuZbLDC!>P`OkPP z#x)an2ezVFun{n_Q(U?e7oGg|L1?4e5~XK<8S`>7G%|nH*#bVM$1?3kmok`Qu463gHnTGA#|%gEn8hIThIhYc&zA4Yk=9ewB~7k52;wO)RvCjL121R?$) z$;jcFwBIOXl*+aEYuS9MQnCi`jeV*kE)uqo?kZE<>zjn zO9%^X>z9mqnbl+%EKF6~@z@w7S^nkV6r!cHu&-h=x7s!hdACQ4yaJG}4DDFBV*79P zUwxsfQzx=RZ!R@~4s4kF{1$WuZ5`*&J;$JoO%FA|XS8 zg`uCmOuhidpL}muU(_%}jLEf;i((&jf$_tY^tvV{>o2MZtOQU)8KS;PT;` z!=lCNuj`8L)5Zud^byYCBbLGS$ka!}G(X7TBL zI=oww9xhC9!U%iOgBD`{z`o=E(xfa4R_V%$w#lQ^||a%`ppwav>=J@d&6z(-|gYqpO`5nWBB1 zDj4~v*tE?r`7ejP`}HM)^;D;zOZem9a6N+To7#iNZj|=$PZB$SAle}tFC!wU((U(H z=vnB=^TmBBaj^?saBVazT{-*pV9L3wn8QW~;%=0VP~JhR;BU0Kg3qHn+0xVtiMjq3 z)5l+8NH2@Uze~!Lk)(S1nKG$znfnSmy}gDO@JTk~rG1~&hwEbu4;T?R`bS-r(92NyYfu1C-$H{PpE(QI;=ueuLpSc zl9Qd0ZgrRnoH&_a;gCIo! zN`J5j@N;|lY67<3K&^AGPb$`{05|QzQMwfJC4Is15qlLRtvee855CsE*uCl)@JC(D z(r4%OIVE(%Uk;g?$yuE98QjK~;QN43*jHmPK-Rew%>QH01FW!kHYXbgd=^7aMJ~UIig|d zyzIxRkS?Z5_&l%XT3Yarlug?oIe$6m%QoeO-Kv9(rTjHj+5Fqe&r+=_>&7XURy#m| zYnR>Ou2!}d^|79s^~;ao73~e^)Ub>JZPEqsw31S z>(W6zb1QGmDCspUIb)GD!B-x4esFrS2FoD*i z7)ty-eDA0zYYj1nBf1=YEA^}nzgevN`?^PNRU}+AfW3V+7}WQsvV>DAA1fAui>lI_ zU^~trux;yK1ZVKDZ@C2>SY$ug@Yx*2QXmu)xF|9_IZD#O4e1+qTB~r&y&%Tz!f$Tj z_;iTRr5K{WVsP(nT4whqka7YnBIte&zQf6_OXn7|W}9HM*4mrpw)iCE42bYlMUW9B zsq~r+ytxyq_2Hr&hUe1Hl0{RdEFgctXTi}b`2tW3*do!P`l^*)Rh~Fd@6GiZ(!tr# zH~OhYFV_@u#SHf^+2nC4BnTw8>B&s6xqci<7yW=r`_hJH)jFrysR z<04gA4S@v2|B(ldaSn}Qemwb>-yQI3*%D2Tgdtu{l-AJ zzJy%u_j~zwVWaQ$JX>5)u7Ht~#WUa$wmkf4pi8ItGZ7mTT$LfkzFPIL0GWM|ZUeGfcpOA4PA4+5+%;>)z~xUwlgThU$Qw!vbXoJt?J8|Ak^obmyI_Nwz{fKnFjwoEgAs_HT{apJ$B&CTdL zO~+wxo~wwM(vjW(s7ve{Fl@V&{;Knl`5R`>2uCN2qB~hNAqZ!fbvnLxmnk-=yM2jR zo%|;2^p4b)_9lt$+%G*)3ur4F%uxx__acPtNaAS=6P)6Y6NVmuw}eVfPE}nYJOU9k z`S^EwJ*+k1cU`*(3otB{{ZmXva}oL&xxJElw>txG$=>^1!2H%kl1~tJl2IHtc7$P3 zspbfm(ld*QoyC0fidqX;Ldy5ch3FKYeLW>Ndi+8rg~Pm=a;&vfOYlH+ZL32VC1D=k zPiy)Q;n`{C0novn(=WilS9&*Vn!jgc^kG91pl7WeJ(FscF3FsWvsM9x56#7glIG?~ zcl*l$+;nOiKMp=In8LLeZka{<*68gzYwyf5%?iHMyszSjnPA|Zi*Q%0@>PS|k=1wm zG@B6C97gq@kVKUeWRi(Icq9^4tjxoJmbRPrCQB4me9;LoweIyPmaTJ*NJE^%53 z5J*Y9n<$E$+1j|Bjvt7KeYq8FLH3y?+og9)64hb<*(&Qc}>ON!}i;$r8dFQI3`7T2)} z(k1HZlS)n%$|Qkl^m-5l@|eV^T76TnFl?9T?KS~^-MDP!m&}49bEM*#aO50BGPy7qgmKdobfK-qcSU#K z{R7B`1O5^~Y^wf;KI97q?ZC6_ZsC@F38^t3kC8TfV zjlV5ccDbSlJLVdIcsgwGT{3LI6J{PRY8H!6XCHdt0Fh_Ff>v!zi?4evg;i=Re!JH1 z)o%;Q6oD{Br5W0*m`hTVlnyzA+Xoh=)^=QCIG@{9=`Q~YgIObbkY#?Y$X{&+nZ((_ zuve_ZLD`!W`H9S>J(4%pb?~e+7kT;V*_$he0x8ogfIXo3Q=|r@5N#`{6v#d>%)0I$ z_|We^^Y(NKu!oy_{Q15ud&!-AF3#2YN0*e>Mf-UD78Cx1$29OUzBl1<)rP1GCnrbp;xi*;^IcayZrN_ zjY)f%ub<5p!jCxb?1dD^T(>Q*KO8YB1YSE%?M)sB$5r>X1Dw7=NB@prjQY3{!qDxw`Qg@t#$Kpv`%i#Owr3(472baLv+RM&oCKQT!GuE2R|?QMpQCxf51MrnPij}u`& zEbFgoqLn;47YNp4m-s&~O!mgSGfY%d&lR4hvJekimQ0NEr!|W{iDa9Y!o+`PT4#UIQ09OjTGjS_R~{* zhXcJIJ*Zy+UfI#serN;%EhnCFG=X`HD)d;bUCy(q2@Za_Xrk$ee`x+7sybpX z3K%aOWPXA7$4Q0!|6lFF+TJmK0-UjkYppyVDIFd{Y-{NZ+zXL?TThcO={)k61^(ZX(79>EL@SUW_lsU++fD7*!cQyWU4Azl$kIs&Ek%Z@t zv+&0hRy!I4uiV0|Kb8(u8s_xn=jXJ-BgKZPyY9F9|vssBPP| z)TKH4boQd|1DF2BxAXU(h#rs2*)SK-FL;SkG?ebi_!F3=dr48p=5_PA@-GbsH%5KA zi!jrr269FT*2TPee2YvMLXnHngY8t;mmCbBAkFa4m3%7`d3i@XJb>6Ngq)iVzSX%T zo9EFiEWMk^unggCjU4#B)AgiC!)G;fdwB~nnD&}_I3H;@x88r*CB@{i;%zr-VzQgp zd0|FpZTW|#Md4u^h;!?s81A;YjYn$*=&BeK#MY$cgygTR*Cvki6s`yS1nJBfz?Ure z!&7T9h1>lB!eppec<8j0Jslyr{%#Pij3l|#*=-zX@AE}RS#P3@z;TkgMqC$4DfmW< z7efKb_sa)MRvUT^^{QOqgGtf)A!Gf6k(DprrQ#L}Xo+kZc$g%}cr%n}Ri(@%qZ3G?5?En6(4yzp ze<1ylPZyAXlu+z_Q1+dj_~#feceyQJF=Xs*>nv5KCQz}T<)LF))83fJJ{Q2JgWCZp%cJ0Lo$oc& zp1?_EJlCkA_j)l9klYA!s@rQdQ^T{E_N1&zVA z!UYh65MGfzqo`@A(KPetWt_l=lO z+omh}#&N%POIM&f4~Fe3Xbz{|`nFxja4d-FT99?if?OS(yS9Y;WOT?GbCotJs-?OX zpuA%KEP3%I)~h%3fUMZljcSGuLmSaOtw@Ep;zfTU6lrNgmoCc@o}1O0b3H%kxf8#> zXR_BRnK^)ZFsqqzJ|<+U=YMVr{fu4G@tm$}X{$-z%3gQV1Ah7P(V4ExjR;rnkp0wZ zi%MI$ulDt7-|ie%6?)2OvdtDd=C59Y1zSa>TCAp|4=;r&M?CpN1(1^XKZXDIRC^!8 zcpW3o|6?4*9@>k12bmF!8rtogmc&&uj-QyEn!dk!b?Vwv`!lFKmAScs0pkbR0d5)f zQ+rp$XB!FyVza_>Q8A50vw}_!)>FUbVqMqAdh0g3x}Y?*ru@?NOnK_Jj89)?hvjpk zx%JM3MFnT`&Bxtv;JkKbd_}Pg*2t9GB_1V>d$3xa= zC{qF~Q8yar42p!DgT(Cd4q)KL{_l*~z3%6&3CiggeVc0|q@rwZoTi4Vz1Myg^OXOK zAmyn%*T_3as>r;nhdVLwLtdOF9qmW4FwMV&?VcLC8e{%d6+UeM42%4K@{*53s2;ZX z0$awn?|G?>+OV|GU+j#l?8r4Xo7t06C=i)3M6GTunJnhp=E_m^v7lSwB0|rL+Q&)) zQcrX(dh&??YDO)phFa6d4iK2S>|j4YV5HT;Chu3F4``a*dsPYTGf8P?@#oA8(jha* z^=*096={Q+0ZoB#vuemM;34!`&MAOcM*tYgFEjN0G$kNBmkL=f{^js=*;4&w2`4;P z^I$^)OWsm}09k+r^T}O>?u*umy~n;YV3goK+;a7G6?`ibpFiaX%cw0>H>B{;rsvxx zMXe^Q^b;K3$%F^T6C#x@wJ>iYX?aC`g9QS&$Pn7L*1tdU!u?LIMmd|L^$26sQ~TUc z-&@z$&Ue!My?B=&!B~Id2|t(&wJrMphaVQp}AILS^5#Suiq{En8&Gj4^hF*@&5GmVQ^?=l2}Xe;tmFSwC}quIqfC z=j;4RhzTNNuB6d4sgU1NjFH^M{qbDNbXnmYTt+F)P_Tlzp6mQ*iP&yf9!2VA#u1b2 z3;?IjQq~N@-}wS-_%pq2LQfi z@k!O^57rJzgYY1QP2K+zh#2%~B$7KyKc^uZju9SpEA-#s>2!V}hL2>RvhpwxwRAo) zdk>}Tr|iSz9Jlsb{>Dw3{KQhZ6gfiq?}>3w?*n6Ro#f0_)=yZ{1~zv&$iJ-ehy4}B zU(o2(B2`KRT)|u)851V^q{h@oO=pMf4LYr6x7jT!}09*|E8<#Lgo=$f>b%`gRFNUXgmA0ZN3xAD-Ao&Nz->NJ z57i3g%Is8oqNm(MvRo|qfM-XKUhe|iNBX)D z53t7)yw|sC`_V~-5fWN*SIq#BmFmUqvm#b}=i(8;TYy$!pWN*0-A)<1eh(IH*s z)C>qc77aqE_EXxP4{(gp>+hTzNDgHO%U6(zP&LgWc|R9J`=raCvM;Rw=hglbrV0^i zEvb(A#%^PZuc;eBW!X7}O%lLU2HI=``4nDw!Q$+#KSErc22FSsVtwdZ z@;526Yv$BwRKR^%r09KnEx{E;tE{X>UjB#6C2|zNEzPD;~bsIK#mq8!eh0blU;cFud$~G0j&ooSs`SSNc8!MUSlnS`(^&DwO5x zZP>U0r(fJb@^nq$PUO`Ga=N$?}7|z6?%zL+tQ9 zH6b%48b~NjI%lJOglV)kfs4DVV6SL^NilZVCloTfl>ad*iVUD-sE5ECCd>cUlG{A?3S7-}RvG8j zIwkrI=yAellx;VT?MG!MSIf+Um-N_98igbPHL|9<_ph$>Xpf$m*ns(@*H>x}Pp83T zL!B5JTQ?KicTrsZJkajbLxUU~iG)rw<^zhF`f$b7B{z(XvVtOU#4~(pF87r51A>Yj zmNUQ-tc=|K1#RDe9Wi*Vnxt=A-8J^Pw$I9ezhpLmO-T3GV8(UTQME7Fj;SD5camdVgR<-~qBUbJF=l$o4 zNIKWd_?tJeV?Xeq7$DwN3~x0H!)Z~A#jn_2PxlG#rL^CG*Ml~pV3uDiI?4(U)K?1y zz3_r;+%7kaY3be14S&PY&ac07BH|WHK6e&EKy`eSK};fY#ZFd)O6+;H>0ILCpB`?`!~R zqORdnC@g=2qv%M8f(F?cbeVzc&?_gwy?Y7xc*&o~WqLuYaiu$qd%MP1>L)?DhWelz z$Wm^m(K)l>H7n~BlBmEUAwTAiP|$bek8d`1vpy3cV!T(88oxP^{!R1m`Vie{!WvmA z8(#6b535LA>1MxXqJ|tZl%{K)`T60WW|JMPs)nQ5ADy33R~hbeq_>%UTnc7EwJAaH zAn2?xD(Fk8ue7BmahHi_LEuAH?Xv#X(AYvSQM(J}vlSDGnEsey*l<<r$Ff)6n- zyvZ;gN1d{Cko9<E<;SPN7ei(XtmW3WZXbwQbOue<4Rse1irK1YeEE{xm-EE&udz;I8l< zmDE+V=XSz*@47K{T`x@HS1dLg=H*^}RQ2P$ag(s|7~O*b;8o8fC_A75wYyh`EsyB6 z1l8_Dy<;-F0Dj6B&*1=eCYaJxFpK#*SBA^3b#GDaIQ8z40%MoAXLS?0nViy zU-hu(-OlCOeFPt@`qd1a*lAv|%aSYdqj~L{V4j8`je@5SCC$8X)O;WK(fTl_PGv3q zfd0Ns3Awi8`&tX5y|D$Khs}*|;eXqQMjrTWN|tZb+ZFmFK-!dY#n?ME;+TR{gz}Ti zj2njIVO_X?_H$b&oQPZkki6~PdP8m|K|(AcR`+$T$3stvE}bIUQ--QZS5Xz)7F65$;Dw*i?)YV?ON#JbCghpaE@(F=~_VP6N2uy z&EB~J@c+x!)oj+uANWJimCjo)99r!J)zK59iCab^L~Bm;x%tO8fVKGC2n*RavFNzw zFHTcCYz#+_1wH#)wG}Pzum;%-@Gv*y9-AzRy7Z9x^QB!OKb1N!ub#`0i*e|Ev!)T+ zyg_a&5AQdItsF4UD1?{0pNNOSj!ik@3np!MKjGmF2BTvT{We{)0oR*0CGIb~9GaI> z4=R05TEV^G{evnAFu6Vv{EGLbEcD}`|0Wyi{joy!VWL3TPGgNx-*k6?orK`H1V+6v zR&1RvyO~Cot*c}P=zl@1P~{GZIsb|Ye!L&@PY;CL?TiUyggtY3xtmwtOFie0IpcC0 zZ$zUwHGK^iVBW#2ZVdFE`90wn#lWuE$%?5PYsR}%lK)}fzb~3x)kN=fquh0gFkoYx z5_ydtAMI;vTu;wYBHC2Kt#?jcHvYk@&{z{KD>!z`YqQ!uFTTImU2ZH$5kK{f+Kq`> z{)|Uq*wH3=rAG59pIaT|b!TEz*Y3O5GxDjbI=Gi#K#EX#&(<=>A$7_id!v9SX{D1} z@QC%z-*#>N;a0xf_RgY1Z-q&^9N}W#4cu6eQAW%6TYHMTYz^-1JNw4dPd?5-;xBf%Sd&jFVv1_Ob)T-d5XJnI|6m&&iAtmlu6%i}T6P zU@h%Zsh0bWT{KFce(x75S+o{ymS`mHS+1Kro)>pwQ2u+)EzeM_)KrMrIi(Z~Ul`FR zb0q@0;}%-$`@8j<{2o8@-l*&!~ zisGI$uVv_4wjpYl2ftwd*^1VZ)2oV$VI*Hc0*Vq^XPliTw0{ z2u7&*EdF1sJFn~Yi?_WMe zP}6>?2q)dQIKIvS;~T3hfpv|C2pWuu1oq*r+zBHW@QnyDmp?aGKg?iI;(6Mo0g_qb zoyS}KYUDGlcRK8-fm=;Z`k9jfn-_YpI2Z}X9g|hcR)BL7r)$OeU~A-; z7c&p~(vqj;#;SF4V;~8FQ>ZH=$A-@wa+>ws5nrOZCcPeAW|Kl*CA|td_deu)_#Npp zD(_^p7iZw4CTb~-bnF{A2a)+JK|>WCHB`c~P8A;JT=Wk1Lb(z!hiv-uUHi}UB^2x> zK&MMBHm-vx#EZvrB!mrq$zu+1ce2+>`$+yVolb>!t8v^a%#Lfl0Fz22;dFJyi|>nv zX9TxW#+$5(jskO^B%tbNneaLz?5-k)3b|`gpXr#PU^LWui%_i)E!oZCtk>Jo4>S6IGt{1KuWdV93+>Q38&&h zdG@&x@FFk4$s$)?v;UdL3PFH^Q^ua6II5(AFI5IfOmv; z3dZd3eLrNlGd-Ll=*r8VUn1F59(Y$iaEkKz8SUePik`k$bT=1x7iAuNDZURHDQtsC zJ@B!Mx{X6NO+!@%e=~_jgD@_o(}MC&OMX)z1yAfYTIbF8$?;#p<0BNW`}u2Ga1Kql#%>F`m6=LTFrHHiwr zV(BWpN)Q4cbCTZJHySL2iXi{M=loAk&P5Qzp^cPweBbV1HJWbnHQ^lxO+)n0JVd^E zJb3hXY_Cf2))2o9tueXUu0O;t92hemRG1_c?%x1|WtHZmkQf1{HVNtFF{$54VcbNa ztmdIdNv_UpcMGeI>&%3d^&_#Wx8>$9d_BjjY)LrQM;!aUT<%P~@~f7uP`h@gEFfRq zBk7nHwkakn=^pM-`y$Opd581q|Xf{zOCfA!>>)v64z`%`s!oOYK1hzbdt5zPo+YAF$y&WtUI<#ix6aOO$`t_6f!$n?~xI_BD%|_n|}A zX+_@R4K;MUwF7?+OyGmTLpyht7XIVaJG?-%v%oC}#;r(+uJcz!wuJM(L(dlFir$!t zzWaI@e$}weSw#L{GVba6f_+SOA$S*Q79wf=2yf@R*bQ`}1{0iqN#!OUwTo8VcBLdI z1rkISJK~1zPG|YKsXb@4q+%r+abU7i7^2doPGObz6ZBb`xiSf^?-N7#U zQFp^;acYWC`~r{UN9A_GIAEoq+i92S_eg)G3r@XWU8q2{jIO@J`JTC1xic5K7{AMt z98OaJnsWI2RD{EQmg%t&r`PaeZ)3aDoQT-svhAlQCG}(@bfH1xHhBNxD1ZDj4?I{n zY%RE;#w)CByFrn+w+K6CWZnaOH*@6$*119cL3-s5Z+9>7=TAd^?>}pTH3hc=!_@o# zRkvjMf@b2SCxwlYKV_`&;Bxy|q32dr7%_mhPdiI&XZ!DRYtWNgoO@#G;N>WS>qS@Q zXBT;|3+$}CgqGQ5Lvg$MZdN_8SZHARu3q+@t5C4Gkg^^ zg|9H}{qj+RCkj8=HI{A8fg$miamZPL@(vR{r+R$A$rDrnl0*2XU2!si=xQ&KSrIBX zw+Fcmtkb66XBsI393NN;NOuRPNkAcp<_(pr@SqDr!ie<+9%ulTH0`t1NemV0tp>9( z+p|PR?&z-fJsV)Q+g4t^zJV_lT(DHwHNzj{5Y7jYE4vnf%k6-J9_5%P0?JT!I+}e} z7L?yELewm*UIOyJo`l`v+g&|^J|zAswPMmEyUp3uBfCeSfoIzXRgo;X)qJ8**4odd zSQ0E31Tb{v{9^~V%D;7gc!Q?X9#Z_+Xhn z1Q>dgx#8hFd{f195Gsv?PILUKND)C?bOUq%)lx;!)og=({3B#gp`2G+CUDS!#P|O&|$`5*tu9 ztv6OSi3p}E|Mg_qD4)3eE<$WJIHzdQi9qbUS{0#5tRO@zZkBe52B{KGSDcQG`|Ek5 zM5lRgNF#z?nXRiMlM<#B2N^@cdKK?eH|(Sgo8hBd;Pi{2YWEv9>>`f}g>LAx%A1ub zRDdGK9MaZ@vNHdSyg@T8GQ`sLk0?&eIB@AEy4}&{v&iX>1*ld!G;+z z&S{3n<~lTcb=xC%ghTCZeu0ALjA$44+l%>hU`M;gBq4J{p!!y0s}$kQ*K0<5$CFQV z>k3MK;6D^To2brQby+|}<@lK_p(2^_eWY09*QB1sM(1k>^9L3+A({J;h6NZw!$air z=@Xdj>sj?veX60#cg%YfP<92wgtx&dIbf`IupwFAGsRpz^fWX?)ZhmF;{=$}9G;Eb z9F+5y5`>bqC671CJ*oMqzep;M(`i%5KY|cmHjE1kiZv;!%Gy0~@X6Y$&Oz0|ssmm-8v0PLuYIZM`3TX%&bm9!L-x2wdUPNjIv#j3H*-DPurToD z1G5|VJHtHo87XK7OpI8SUy_T^G{U9!z75JPKg;|i`&>ZVJ=by|luno|73@vEUlXg( zn9i-S+BcEo)`ZSD;9yy1qBp69Og3|6T$JDNu;pp8pUzT}##Q2qR}WI!Pu;Iacy-_G z8-)lk2*Z^&*=9!Gx|@k0)pKW?BrH8<+oMZgJ_f~wruZA8p0}xuEC*0U+(&irWmJ>; zx~!hlQi_?~wpR^|$50KdnveYN-&(ax`i^qQO+B1Opru?2n61`*CwySKD5annaguj{ zPiRwcjodEL#7-_l2JUgCHD?-VAM6?>UW9kh7MSd%GIqOQFOKPAHR_Fi+AUMv#t?TU z{sa3b;p){(Gn-&7e2Df{9VCk)_k-3|Pi|`{=21oB?wF_n9W0 zdbUn0kRy^^zvoUD)%o3dxvS@&SIhhKEixbHzdcmvObvC1Jwm3iT2oXR9 z71?QH;A}6)MgFd2It&W-b~0m}zXhGbFt3N?$tY&>7aC<17hWpKvsqPqZNc6i=962K zp3H|6j_KFl1~w-DgR}dp<(T=2ojlIXnTg+J8 z`k?#SEiM20w<^TPM^Xmzac4F@Jv`umSjeX4vK2g#9>WNV!gUJJ9mAX^k}rQ5cIv9cmv_sb4|N?=Ac#Y>f)j__>Y2|IB6Y3@~;?3b7M}D@sMoKtz|%gy4Zpl?60T( z5i%ZQr-p(PA%x8>cXN|h>PT}l6@4UWu3)x&oQcCioe981v{RVP3@e@-2%8Jw%H}R) zjDL47ynRMUj!KKLp&s{8fcoas$SFt6*1+a_@4?SgTBf*KB%`*&%~7xy#vJZ8&z>FM zw0vG@Ykunp{C001$IuEV90qpofgHD_^Rvd+cy+)?i@?iWR#h%LjY|9p?F;-^f|(fFg% z*)z!@liqhLpfhIM+k*L}(4YaxtXZP2CG>#1+7@Q-!IC5Db#3P}MM`x!1!B|}Op&>l zBQE3s=Z^QLF;T|fjM7gl7>3~6ml{rUYt>3Jgi zXt(gW?%5mxig3?hzF_MCgP5QoI9b1Gp!WFD7;lLUL+8ml4S9b%-rO2udU)zRc<(0m?I| z*NP2dg)*F0uc~J3DA#>wm_z8l4-bWIp{sKJJo22Wr-s|8NWx%xs)q6hfSR z!_No(eCl<9VbXT%X}U9n@e?}PPDg%z$H)|8aKQ4`>0ogaOQ(4(J@Cv!R*f!Q;|*5Q zcqr#!RQ^uC!^YcRG>yg=$97sm&2yj_*zHx5KRur&R)<$k%);Pm9x-)-c<>g=R9$~<(N z5B;bX@R$sED1cyjtFbcJ1*ccBF)1BH(3-1Lz@X8Sa!CTM+PU%h3BKeAm^)O(Wk8ob zz+$Xm?FU^%0{5==YFQR5@Kc+Y06lA{>4H78%$qn~ zo=<0q_XR5a{BJ(d7kn_0v9{9PR2Sy$+8b~i+%7UO- zofj_4#@rnYxPU23xu5#!^HNFi`Pf>@|K9VDbJpSx($fcSmMn}p!xiUpV^=M)nc(0{ zi_4xVhA!C57h#U%G?yAIY$Uzg0i+ zj&9z(&ZxezpM`P`qV|Dfw6KjL2lO=f*U-d3$5nH7cmuWYHmOrcslFIaLbjqqM#pax z=pZj9A?_mU$gO7iNvDj1z!bY2h6T<&!KO~H%j0!w(foa-JJkiR^#^#mvSzpnT%WC8 zgeM(|v1z1vi}G~3`&CY(3R-}nRDB+N4zE4ogy~XVH9AS;;km2Q%_Zo74PX%R<6a%_ z?jIcs{!lRIEK)Y8%CQoFmh4U0C$$i5TOR=P0cU&g)(U0?XzAqC%j%};vi_NWgtq*K zDlJY_(548{sWm%dQuM(yH(uN)6ya=vF<-mm$qG=hWp<{dL$VdWsh*y7qb$PIMwH$T z#L~I8$WK>W#Tb$Xh0SAXVWOMMYYyvsN=So)-NHwIn4iKX8(0xfD=B6SzSSLkCV76} zeznfU7UW@-FA_*+FzVU@!?7o2z6fELf_-df({W5+{NDdAe&S)3gcaowA_ZM-woD)D zC1!wN?|!DVj&)-6jbcw9t=PfO-7@8$B0QVTV64H5DnARpI|}wd0MpXl<4~+=J!V|j z-XrbIt^SJc9dcMGaUqnXJ1KLvm~I~tm*RBIZdfTE(GOq&)-RB7jbmo>glBf{Er#`q;~Dk7*&>U*;p6 zKa~8e``Hqx$M{^|zL$E%bZ>?6lhS0Td%;-}gU*e)>uY{Da*~F^KUQ1$WxJqS(A67Z z00Eu~YrymdD!vS-LG`&F?Kb-4K}NNCAM5cHfm{~OiG_2JlW+Z8VZYp!%>_RJuxd5V zU%nXoc)i-Nhtzbysr=WGjMoIcH6*x_-u=CjtX&)CX~WkGYnd>!yC<8E6zG8^=+Mvr zKA8eq5v#hqL4<}~-fD?oB4b~@D3NtEs#)~+jBN-hPy%r!Yt`CoR)z1}&{u|@Z^&iu zS#KDLKy1J*@SzU|z+K878P!~I%H_b6@g1HeY@umiRY4SiNld${OwlKM%$AXYUlU^Z zIs2x+Se0*hE|vt51{tHn<`tD0TuM8PcxgzvVmN#Srb#{iQviOHTIOaVpolE5FBC@` z?pd#dY=P{WM2jSS=x$>KoaCGyJODy*MW`k62As5Ei>x%@qCa_*pCUhdpPJhTQxNoJid(JMiC20whxWU!yuBxr-ivpRL)8cC?>$rjIUc^4s2f^5``w6)H z({};M-(%4R4^Pi1rHWS?D$@XCsrus&z%V+~^>x0<>&su4$bH{Q{WyyAKmEPtkiXDA z@DmWdS3@2>sF=1Bc9Woc0()Ma_@8-$Sni^L>IkpI_-=P-GIk&L=8g^;7U0)0W~cu4 z?p3c>fI)#`@15rCGQla1pG~g@D;KW&3a7w!3@6@us^?gcliLdSWMN12=2uuRWY9tz?5H$5xzwg?;eNAe3xR7Sbv_u2iEWxdi3nZR| zJOy|#AVIJl3ij91^>Jhs&=g)7CWEt;=nsTtJ)rUZrHlA;sFq3xI#yNn9hQR(2OE{B zu#KHlc;E0J2gst574UoBiZ+he=u&wb+>XV_uKo7}vGV8h9fMAd@eDHhdk{-fK zpnMj(QvhM=ORPNL$S0O%h`%xKzvsXyOSaDH?!zsTty5bu9&_*Y)kNh< zFo&`r@w zdtKOV)bj?S7J$i4=rrv-`JiKX=Pbfu(<8c8d#87w-3!U|lLU4}!iH-9r;H3j!Ye1u z2Dxe+zkoJ!>V&~zs6I1p<>8s;tVNi^-}j{cjQj|r7XQ8WI2iGrDbRVk6Ppx1ocmlL zXMdgK^qNn+sCb`qtvD-!<+oONx)jjCEYV*c7~c^LXk@imwe+Ia!khk{+v8?uuXO+?6tLj+<5hN^Hn?Vj<9IlZF}$wU_;AC0(C9$pmoG zO9*NEH)_*B9@Z2O(dK8LCPo}I2Dioe(H}1Kpef+B9I!ia@4UoGZ~=yA>Uxt4=8Ax^ zr^RK7<2QZVi&OUO%DvPoP&~oUDNHv6os8ACL0WJx(BA>bZl>NuW7c%V=~Ds)7O;;| z1sh1r4KKAOREx2{{})A92wtGGZJB`a;pI|ZKoj{p+dS9@Ybrmg{1H0ho)mqy{wWS#xeg-<8)6FrXJI24@K`dUO1DzFfow4RT>R1?uyx3cX!G zlZTNnX)3x(a2$g%Q6AKUkG!)ZU_XAT@2_Myb}x`Bu?WR5>=f@6?}M4*%En-F!BHa^!=wu#0ay^!@%7&RDa>M3Wy_go_M~4% z`Bx1c-{am@ySZE$Le4r8SE3h4YO`ba9!bp^-+lRC_egPc6r7LELp|!RUW=nGXZ(aR z+-egD($YpM^DklscltYOx_&24Jvxat%alx9zKih4dv*KehKCelSP~nK6vyn$eHa{| zi8X(J``fk3b=nsJv*-6+f{78Br|!7H7Uf=?yv1%{U2@PQT_9B_3r@6TB+PWzUe-=A zbZntM9t0 zhetUPU5zXG;;lGrYs=`{Tx(CcOaJlnVSxv$wuuNU{Rfp>!jm0(r%6_~W>cWlJ*uzJ zjOKL@gQ=pkB0FyTkgB5#UH~HS?sza2SU4bS3?lp&MBzF(=MxNq#l_lTW<;5dBr#TAnxyL{0hLz z_d@Oc`mb8?yJ~YL+hil^bfz z@@&`m1N37wBx5JZ<&Gs_lyJ zMFqM0Z+^+Ed}}=kiT^c7jOlXU&n$VjC0o0fVvZ%g(fa|X88w(R-V>iQt!f&u?K@nD<=X-*WIdd?LzopS8iKqg`jAd$}QkFCM!#ef9M_%!_cxGn7|k z-yk1V5);?BjQ0VNnXBDf4T?x*!s~o*A)y1iF3w|o)gQ(d&QPRR&axBcKd)_tV_W*I zkM{l%s>~AJC&myQts0b$Rcy8L{|dkCdna=&Uq=?F2`^ld6MvdN*A@>>%_=hxNyInc zWJMff2fID(kaE`=b^q!&9~c)e5pjDa=p;&7Bx#giMDT$~MHzT%*+VH4%`R! zrc>8nJze@ZXfie7RmR)N#7q}#?~#9X=(I`p(Z(-kj=@`~(h}u`g6**uezKx2VScjo zr|St9zHAket{9|tv%`I9cQ&Y0Dk~(lvg?v<^un&*w}-rxt$9 zcnWGJ*}vaR){oKpZS$lS48QRv`o2pzLYk?Rm{+^AEla z)-oVY$~xb?+B;Q0TmHRW^MMD^n?Qw>S!)fQlXc-=?pm3!PJ_AJmwMeV<-77glUE_H z-7fRwE6(DSL*Vm5-(E8u2}l(cE!NLH_JxVXBNP}%h`G9iL>}BT>LKfz1y|!gsl69P z=s_z{bB%dcHt)}+mY7vd;&QNhs|sndcNCW?#f}Y(>NhNLl111)wT%;6acjuL`r12* z0*S$`dwRHhRaCEg_LIw@99XU)G`=N@5-_)$H)P#Ee&gdpbpGZ$b@O#ArCF<#ccqz! z&0;QOpET-NFj%<=$n_~11<>{vPGf4zX>%89A7hfLkT)W0&Br#82{}6kPeeX-@X$v5 z5jr)NV14xCai+U2*Ouq@jVJZ~yXg!Yb0PZo>Y*tsh1c_@21jp)T;hawoln|+zF~{N zxbpMbhSN&K^;?NKdfB;OUq0B@v*4rK70|Xjt@o#{ib0Tsci;Yw+ALh!k%t$eeou_H zonxQTZzoKud=%)^`v&W3Nchfe&a`+#d>(X~yGMCs5gr75q&r zx+t`3MQhiCxae`MirU`5`+6P+9$G&iu~>FBkzWvN^GPsM(LC-+Sg#4~KtVNJXr#2b5rZOSHUoz~1r_9pJU7y4LZ|$Yjj9uv_;Yo`0c<3XeFS zvMaJD2%6zM)FwfWJmi7~=;IpaGY;l8M=~9hlxj^zQXP%X%(=ywK2eDYfAV#DOz7rE z#E-^9w+?CN$N4S`zrwP$!%9}RZvK<0snex!=5CcX&j{5T$yX`$m@IS{-@M>2i!#>5 zWWV)z9b~4o`vdgZHjblLSWV;$$5GWa7yJ6O@x#kz;UV9Z+V1C#Wx<(;JNC>QKC^RZ ziM@8Kx56y<_@awQjm4_%LT#lGj-SW#o3&CmTy@hkL}5-RD5Y;JRz4~>v(K|s{=SD3 zq6fmT`{1&5e0XgQaePV?wIAGclsn-^VQG3EXXgNxFG#`QOV@?fB_LuVm=7bw#GY3# z-P_32)$FOC>A4^ry$nr`yD$Tk#)JYcJTmtZv-^4LrI=!Ngyo}Km~!{1lm9+*d5Qg- zp}yP9lz3w--gSl$$r9U#m}YrkrJjwU2PEN;_QqRNZo=BT(n8?mEaNb z-CvVkA`0H^p-qd0TKKSa2+RLVTG`BiJ#CVb1@zbAUn|`=2jhE5$VAxyjnDfAW|Ac= zL&ig>e}o7D&Z`&%oe9iDj*8(1q5ppmWH%?t=~8gE!@HRT9eB@ODX=U3SUwP+2v*gA zh!5H?O}n!mZy=-FuCmYL2{R3pqs*~b5rA#@FbvC&qkB4=m+G^a0EM?1xr?mDlNU#^apDW+_GGyMs*9y>ZVZA>WCM9$=E1@X&~ z{`9TZm_2`ldUR_Vx3K)T0=-Dc+zx~k+kg>g1dnXFyecKLR9mi=kg?70lqvdhr_t)u z#d~F`;d>O+9!<)jc!zt!5o1V<&x5uLi7Cr`@qiWUBau%n8TyHs{h`inn30EMEi$c! zMpG1T4?eWLf35qG(2gZ^wF>M*?R#FT&K%iL3GT5p2ozUO4HByhDbZ%MTCf|T$%DR_ zrF8IBu3J42jWHZ;tsf2SF;z`TSve{tClYdX_P?7+^;`?VFch7f*ijv0!iF-mt(m*B zW($K7ohLS*t<8_So6m>4nCF<|RPTJzlGbdN^E@uxiTKolDCT-1NcnpF(vlH%^x$@E zijnNh75uYqPRjSamx0kC3h3v^{N+;-+VW+!E%u)B?-q#(eNT zHtus;v?!Kq>YiGc)Vd(<IXM`1&F_qogSn8M#uvxZ|Z(#p|90?K8?ZOO{XN zy@D^-+PB?}2ii)r{rr|c5A0|YpP+jHhzWvDq-s<|4$sdHehy9~W+n2J z=3*!ZWb;fsV*GL}ACzXC`)V_9AS|skj0It_S2CIPjFEYLstDr-JjP+7RiDx5jz)^L zl^WzP5s6Hn&~5*1!q#8?5)L)^NPav+VOY_V{|L#p$@n3Ut{Kb3?t3~Ho_L?Be=C39 z4kDX&SXpIAr6&7AnlFn{F@z^T|uG}+NJ{e-Z=0`!-gYBrqTx+Nx0r~46 zYqt2DwG^8)>z!WCUj1Ch*65V7()=*=ezb5j%ev!h{bM7fLgq7tybq$O#P|H-lOi+F zB)tB2uxpzC+`2-tT&~}8l?bM;iSZG|e}sxVe#Rc*w*FI;*0(+h4j|h(l4w@!igfrg zZ5;Y^Tk!6mPV-@}pbSWAfb&?UX<#g=jkaP@=^M#;3KoLO;H9jk&(^bsfb=u%0*6Lt zTJ??j#Um4g#s!<_s&BaL7^1DRTtI~Bea7ors75cP`iSKNR9PU;#3xQ+N6s|NBR9J4 z9#8h&vH7GXmiSdXs}c!-r!}B_4ob~p6xia7k1{)#ihTkT;?h4MLt(0g<{5Drfbz^zf`RUcc3~tzxqKSY1?7aytN~fD$6I6$|bI$a$03S5g0Iy$A5&x(R?BjWn_%o zmpd+6Sq9wM2byf#S0_sSR}}bYW4Qov7k*+Vao?ccP^HAe0~N_15!)|9Ts;ZZKB^aB zh1V~%8s@)K*ck|igB)utCHnIa=rVJ0t#`VLDQPi=xv3WhnaL;nn#^0BSkX(9{ZSO} z7?EQfV>f1P?(I;!4sV129RGVsWn#4Rc$f9o7qUV#feSBi3 zVcD^N|NkvCVEl=Sho*#I(P7s(5$ z!C&EsbQCad(Vr6cFZMzXHkiS)rs^}jyU!hKrlN|Y#FC*iE$)X~+gb$eb>m?{`HmUh zRGe{h*B+kfLz8XpBx$27h6RP+y3%gctJH9e>HWt3Uzm_&9qIwU6KR645G8&<>tma^ z=bN>?5P3i@MX2!1nI}*pk?KFi9ebbGD5O7FJ{P_sRa*l+--ThjaBm7mr;l6q6|l{X z^l)n2NvGsDs`vjR*{2xOG}9^7{)}+PSMhSDTV_94ohVW|7-H_Cj>nmGgiE%$=6bN6 z(Yj^pcE#xd51gfkA`i^?o=is~sZva~iPZ!~Wgz*8Dt5W=ZqFn3)eD0rn-vAS!5SSe zla-=djuCr?I5%3GoqXx)n02z5i>d<5t2{?^XNzf08*9^c6BIwnm@TcpUAjCxCog zQ*}FWE9aKleDVTOXlIi0lgK|pN;x#8rVZ&!@cv2e)I;EV8HGkX0v_%za_JJs((!O> z9!dXSv)KMVOx9viwm!eBh}8R-1;j_Wm?*)?Qnkds+hjaF_Ir_oD2wnFlx%22K6XPOb&`1NqD;2jlqpLGCE{Cm|EO)Om#NUKZaldDxX0;Y0*FJDn!qC z!}ex_P^@wUVEG5k(^< zi3zaaToS(`U1lgPW!f@T*f6;z>96_ zfT#0Y-W!KUdPjS&cC#G{VTWt?Y}il2n@XbMv*^ezd)Hl6{?!}$1AJnPxhDr3M_ILk zd8O6?^d10g@rmj_H z0Wc&-LiV8XZBo6pgX}9UDoj9CeIXlCjme^Gu*&4#PtRw1!MX)cZ#GJL%i=VG>2_=z zmLCClyDw=aKe5hwx?vw0TS4jEuw(7-x3sq^&_+-)z^gc|=+oZ{CtEb}M_4X`-=*j~ z+0Q((=&|Td{_@w;XG}lbteAFDv(yWxiDDet6%waR2N@t6Y^BLPpG?Ymv>da$537;8 zRZ%?jTMR&^JpOg977-dla&h z8d6#11HnsY|ArJqxl3G%)`)shYTHk5(naxpe2Etc#95pb+ClEOQy>!xd4&{X1{Dz> zB(kA+;3D=6Ob(CtB3XN6An1Q*C3ZCmhfUH5Mq!c+MR*_UhtLKVJInJ>CpzTzxuUX@ zHQyP&Lhc<#Wj#U*O&a^*l=?Q}h^dajF!FV`K11yXcz@Hope+7(uh6S{Zy0$)`H#?> z5tpR}aA{YIcJ?w`N@feE5LSH~xivPcE-;}YiaE@1MmsJW2$IXL?@ zq-9L>szk#%Ir}$S>tG_7Q{>x`c3We>wAVSKMq%D}s}ws<;<-33!AHAnh0ky@ka+8T zdQ=!Ei(?zq6?A-9B}h0ETrIJ6%o>D)#|LXuPACh^03?)EEVS~#s8Lt_($Ot(gd13T z57C_Ot~oWkksLXr6A=9TqBl$scI38(2#q?Ra%5!XkoF#FT#$gy)jg7QFE}%Q&8b0l zv7|@ZJ)(iS2;S3)YxPyiuN%lys^~4*Wv}DGDlMtfr=YxERwtOZy3Am_SC_sStGHs5X&Mt(4Ex zqYYPObi1cXz>e_3RqesS%e4?a;;mZ^SQomD4Aom8SxiKD3uM%8W8wiI64D89wg%T@ z3DYG(hOleAep0zUcu9|jc9epY0e9(Ly5TF}XkIZIs7_~v=OD;rV+XIdyYyhU#IjxJ zc1D9_Cd)6j)9IW5^1)`ELe~`vfnZGF{Cp!f!Ps*!N{bIWwo62C(Cr9IPZI=`YaF*q z+zJ}IUx)rV;vQdV?k8Z%!rk$AY>FImLpg|M4EsYl_n*L zs1Q)#u>lHV1f)hmq&HDogaAe49v6n#J39;{#eH1+u11v$bZ8o3`00yt(kDNIQX03W zZ2HZ7`K}k+(A$-mnca>>1dY10w?JpO0V;S)nyo)77LMb7Ud%60bd1%&4fTJuja*G_ zf|LvuJ5&D*d=R7F@Zyi)4Ye^H{DAAo@2i^(Z@s=cU94ZjoaCcZ``p=EIj?f#ho3p{H`o?%jo}4@NA~O>z76{>J&Q{!o%@r&cRs zb36G&J(8)V9$#;e_RzmeIRP|Qv2Bb4!1ezyI$nG^DD%?5MR~=t)D9~{won- z%T$*=p-6+@A@#HszXS#g0F3%Wl5+ui5N&Hf^auY`Y856b9uh3$7Ix?Mx;*(rv&K&) z=+ee1zRKnIo?F*Ow1?aV2GxLZQ-XuG80pE?y0-@dm0K$Z&TBrTrJpNRc3Htr)}piPV>Slcq{aN7%E0d z+S@S3Ll)EFkc+$p6oW%a17aIFUYf2q%9%K(KMxwa8`*8#4F7X&vZLuP4TeSVHeuYGT5;GmR zL6JT?PZ1QXZ#f06TDtj*^6Ry1I5!*f0IuQR|L#32;A-8_2aL?QE9tM(b9rI|_7hhn~;3ORJ8b4a{-2v*CnjBh^> z=Im=c$gD`PXMEU!Tyzxt^|4_XDWZ;gMY)DGIV6#fwU0qxR1V=CCMhNAGWu?3vpRE7 z8I;tdOZ_Fm$t4%#tcqXh4dZLOQj=Sv!DKZ;dyt;rAN;i^zoH)@hWXb~*#lW0wX1%T zxG~?QO23lOJyAn7P>`Sh{!@t8UgN?+!Sb_rCpR4>5|`Agp3MAEPdTSllACIsgh2w7 zw4a zKLsL~3XRbExwITEV?cZWUo ztU2ij18==M%(FLyJx-L^JKellIo5M_|j|N zvIl$L4@Te9(|n^kt@}#zhyIWDItpvJSsYk~KnvOZ0%-6d)mnTh6oa|Uef^m?yC=cb zid$bCyAnrbjVggHtjhN}Q{#I?*Bxs@uw8PmiH?C|65}s#yT#7CPptdREP36Lm!B4j z3~yWx{)o>$1?THLRVI1)K|LSIaKeANks)V5fz+^YLfo|BxWzUfS**1~e zXr|L$gUhabQXuJ(8to$v@eGeovu@m+$0K`KKbmuA$-XkY2J*%sY-QLdOu0p4$x;cv z9xmPyVeXrK*!P_QwR=A{8ar?9+gk1DDcjxND(hawTHBLH_PBeFwG;_?N6-Aw#zc3s zImUtAorNtcN7&Mo&aB*xR<)|hI4}JN42+Tfh9Gi1x+fwv)lX;-ezLy) zyz3TTlYRW6ouS_Fk^1L5HTEqCQOMloI~18_1}HnQdOCaJ1TG4*NInnyWPqf)?f!0_ zR@3w!TD&^ClT(_*{5nndlRGmL`nD)Gl4>#mp>;4nHsz2Op9E2g!^6hQ)@i$3TuP*U ze<~SlIh1Pp+!}0Md*fo+ZaG;pAT(+I;(%FUHm_l#`B20g{%>9CO@Yqu)B2CDE81wO zWWYC%rKSCn^q@#P4h}E@{TQ}WqA_Sq!EV&~oYk%=OnO^vd-n6!-a}ZHPR=T)^| zBz6RHll(NQ?FD+z9MrvK$tr|(2tKw3^Vvl zJzOnRe@n1E+i|kD!GD^%CzE!1xb?&v@+wloi-z?#WAV0Hd^QbTAm2TFq3x#J{?yxJ zM{~P55qFyIU+8evm)!SI3_jst`#hdwrW4PEED#!!jorhZ(LG|$2WkqiOvNZD+di~@ zO<0(H&uar<%#ShmKB`!0*o4eVez)Q9=c| z)2hOi=2!!MPfbYY`ppJgd0%^;zj_wa@WI0bkWfC`wUcLF5>v1{tXh~NTcp-?1|4dgh3$8@d<= z^r|+cy&)#;@+JrSC+-REr`RHTaWLmDqyG+0Y0B3nCiO&7oFzTX_I_IRVc zCpYV2S0=>$5}%=%;?mgo%w>7<0ijr~L7K?53%7_2IXt*e5AaCL&U=>&Oho0FT+OjF zfsm(O_@#igZCd@U!_k$p=`Gl6!wC$X?c%nu++Z)CnDT`?D;IdL54c+49_mcRY04o5 zx^ODw^aNe=k90MizO~Pk%Xp5lrD@3?OD^quGxS{h2_UuAWT%2o{22O-ZhCK6pRL=? zIa?L8%5D9vs{R18v?-ZZ>0;_0X&uj;Iou|mMfIwSed_4Atp^(#{lb3lK_LX9;cpJa zDTiL399@E|G9!e7<$`#3z8 z)~{DB4r`EpU{+>2T$E^05q9QSNvY~NdU}j{+IB_F)hCsuE~KcQWeR*S7mQjA!New_4R9lC`8V* z1=sh;5b!>484#4GNIqYexrX&P_)WI;%OnF9q%?h1`nF#m43Va!-g-EqYR{m?{cn;B zQ=S1!qh@seC+jNMH~3aJr&YTmovHCkzT>!t z6{wC)g<`#i5*WM;*;${qMYM_GhGHgV$CeIxh2O2;dk=gFUW>~ZCe`gkd(h1t=!YH^ zU{+|W3iQ5!C7tma9((igM`Ku%h40Gu++d&QHSoS+?8TQB5>#ei`qwhYVk=`0P3s2W zFuU;!P?p)Im~|N5akcpGj<4c=p`-O2Py2?SwzsFjFDSE^zEgd8@%f}HlMn*--$&Nh zSov@6VZ7D8%dLj;nQ&)pSEal#cJlV*1652n9f8@usX=C5eK|Ip_X@qR^p?s0qH zr-iP%fAxF1v*Py{i^T6G%*Ml;`0?6+!1u-RwAw#At!q}DAF^uzk^IW3Pgmhs_y>fR z_|T3Ghh%j@A$*Q=5$&(#DY;-=xQJ?^wScFlLV(|AKw7zKBB-x#e6(a)ryWx`w-i)=V^wa zJ?3sz2V_N^Q@}&wHH>O`KWaUS`vM4F3k6!!$Y-_Pm=FmLuQ@54hiD6^N zwS*ikf5;T+Dkt!c(^~x!q22`8;`zhpFu^ATwer08B>Iuh{59+oiXmci8``$@`4Y!9 zX6IDJ`E*P|exB*U*g#mqLX?WN<5W9Hvk|#QKln$wf=HCQ@LpzTtkyPGi zK4~>pa8hG4dwXp*r+bWT1TCwO&N-`CnXFV_%fNxul+9^@gJeB!7S2BsFuyi5>u_mM z4!`&9x+6no_(k*-Ms!b>gYNsM6(>n-)}atkzK+fG^rNJB2NUUz7$eK5Q?EECf#adW zpxbgM(EIKZRi_3iplewa;*>_6KwPj7dZ4&Tq~t2L zxa@#I^o66pS^$;gy{wg12%OqxO`3DUu2y$h--UidguXxAgAGmdK8wU8ZQ8I;qA3q94!X#8?fuJF zM7m15sLbA9X8T7>jzX(Ewr|Xw$D%;m&Ztfd0>d>HTX`IPw!P2MRRu3va)E$ie#~R- zy^1dO$>FS+(sCt1&E+r;68*UR*y5bB3;XEgQ^EJC{&Ks8Sz|lzdj)pm2lM1y9oF^Y zrK~!esw73hg?AwztLe@+R-AH5;w#udwxR!IxL^b_Nr5TG>fe>C!o(vsB}~0`==M<3 zeVYQr5daan7!zJ!Ko6bC88RW;sbOvmLFcfS%>uifCnJ&f-LOmsm!@RN1=z2%!EktaTL4G50- zggn0$FTSZcyE3aPe`3{s4q<{rOS87@um zZY7%y(G(@cSI#;`4;mi#n;f4sE+tCsW(KLT+J^#?#^q|Vw#jy5H&PP6Lg%eCooBQ8 zdO{hmGJ@&n^_VG6x(pz8r@5sgT!*~xc>UYJUAVl2ISeIcM)%{p_q-C%;-aBxZK`7} z62$5AQO9ZVq>kvk6Q`4Of!5;a*Ya^A_ntA4;f`#IR(c=nI9+_-5jb@27Mq~th~L-V8Q7wS4tl#g+aIKIq`Zn zNt`aGA<)~7^(iC%!C_}DkD-_<3e=LO$-=XIlIFua|>2~4~6Y*&WF@AFbiAJQ=$~G!8h#+CmTDsIZtjj4dJ>fk=uk| z3tj|n@QZit^jIL~ddbY^vn99LzAZREgW?IM^*M%UJw%D0pCwoX8IGCaVqV3A&z*&5 z7vu)^XlRfZ%F4Sh(2oGgX1+1c4_*TYCRbkI2NKOl)Sfg=X&9f^wQj)v2F#@32s#Zd z6YCan*D&_J#6Zf1a*|=_4nk4yjg7vD<1cy6bQZO=pU3I}qtj{Y>cRw4l8kXJwaDFT z8~1Q-@XatmTXjkmeJdAzwCHNA9GG!s<$O136kw~uJ*6+@R!1*!^i;OKj`wGaD@!|` zNh1Q~jFHsm3~hISO4+>};mV5W`8SHUYETlqAJ1i^x1C_ix;FbC`|7=x(zd^AMkQXk zO+(pOkYW!~>l>iZQUR?H-cgP2=xXOBj-x8OAmTv`iDSHj&ws$h*bJh2fsI-(NMeVa z!*ACRiD9ngjL8m6aM+ZgKf7EHmfz1m2}U+s4;oM&r6)=1oJ~J+w(E+Fej`<@iVvMKNZ++y!BH&COW)b!e%A3j zTNI|IX;6U`9AUBqrw-AE>v;~c&R>$*+0;v<1fQlMF-0T)WuAR=3yTpEPPy{JgGHY? zIcMuIib+Ajy<_DqtS|gZ0hH(tGV3e3vI)CESH8w4Amo5AiIcT!#f*?()nZ-gR_@hCO&Kx>A&zciuF zl};n(JU$3ITZ+^eV5ZllDL7RB-1l@MuBP+7watU(%Zd0}tC)i{c8`ok%-0z1(Gb{K z_?oHA+2qRdxJ)(*7V}J5b@PG>O_7ZCZi)fd$>%(X58i}z1Y?wHZ0YGgAv=+=BsE>x zEc!O`9RZUm>16zT^~Bv;smg*&r7gvGwD zH$2Y)U71*D`=FVUjMUmgqXfhF;7k4wAX1&|azdg5gY(^6eF0e{Uy`zk5OZWC!0`T| zjolxaR&iDwV;hs&0Oo)-1AZ>&Tl`Xv-A67EE>Ll`RoH#x4YMNaIq*8SPwN3JxW!}Y;KV6yT zY!1J($#{+|!pFFYua*}}g{B}UIEp(K z4Qc7DVs!=P%gVbRYM)&GusED(=6rF8GSH~sM@o$67sw$befs=dFZmoXQxNb2BB(jC z&KP|r+72JK-ARM2LAE=k#j~XmjwFNg?D2X3eZuhya$VN7e`!V%4!Z5ww^4udA*cp3 z*x9J6IB%unLTS=(klwr&d%CoQ338B?5uR>}QP2L;otR)B5AC^RHFvEmG+#tb>m9^9 z;HcsC?QC89#wUYvhVL9(i`;XF$)IdBe`W9#j<( zKMOd)ny0c)H(U`rU3}Ht%F+8oXG915b8Xg-NnS2Q$T!-NiUWE(V&V=m<=U00F;&6& zn`y4B$TpN`AA78f;M%!@w_$OYeU_|iX-f!dEH74!`UMjj_?^Cs)~DAB0QYcj-M$Wz ztkZZHc%8`;?S%_1iR_co+pQ-#+8FwQUkg})>4T`2=?imJ4l17bRLDIl3grkh>@ysG z;o75uY^CKTiH-ppQ4<_pGkAU8bINa_Qz`Q6?KiY5HHLAs$!B$yDn`HdsosN3<9^OH z>Z`2-@FJOKBdhXL49m*n&gIM_pt{92ILn!eJxFkQXg5A7KuM$FV6!B@4=)2Yz5NWm z9iyD93x+SwHL@L+cedp+Q6Wj9V)?Q>>b0V4mWK_y?FqC2&T`SOFxpkp$^nAjKc*9V zK{7SRQ0v`SFBaNi2S=tx23%!NLl^Qzn&<}R!KQWsvrO0c_j+Orh*jYx^aRxXp+<;=rm%Om$r6XehVIx6Y|ACcZQ&3++a=G6$?y z5B3cnXO-XE8qck-5PcP-_f&X9`IUB8|rnB3TgXL9)}dV&1w;f z2pR|QR7L77^F={_e9P*(({(rNB+GiDLbtl?%r4d|TdCa;1l51+js`NbVZo6@Nf3@o z6Y@Wo#C=nt*P6FFSQ2_GbRK9Z5`R90pw8hN1~QT@as@{a>K$)sr{IXaWA=DRlekak z9(L%*%9kV;nLZ{;sgiu^ZM}n~6^0*lUMbT_;yPy~*SeZ~srPxB?2XHCu9wdXHa)<^ zgd9Q_g9zlkd4}d+mC?xx!@%xKvyRmy{E6s;Kwx`NtU@EVvV5YpRm8gW=JG4dzY<m7qQKJom5u%o8!-4E{r}J~oED*R??F;R^dvy|su#KLZ@_6K#}%4C)nk z+U#}O9edYlr@8=9bDEqt@If%0Bv8xnr;++{np)Ly>}N)&tM&VUuIL*QQ6rm!5!AwG*@y8|?LDupJ>li3*VNwp z>F9^YkK(T7dTGG!5uSrc;h9k?WmdSFxiYR{;rNG#2E>dRZq)L>5M%>nB$74XnB zxu*^7!d{98{K-Xyz$eX-ohF|7908$PAckKExo2x_(rWp+^H3M2gj)!acQ%ar6!qvj zeO`;iqP_-DboVl^%s3Y5;Pt@T=wZA~FG4x>#iCQgBG1c%_rZOp5dS@pR(vC44fe_a zW=V;nQA55RiU19Ra-BI7N#S9nnJAjXu>fST$17A5{ScM)b$;nng(}db(Tig{0_`*Y8+9bFa?!(>C2`;WR7%c7!mkx>cV+0Y z8P{Uol*vtesxX0eL4TV^V%n)b9Z5~D%7DJI7v|?GNY(2{q53+RX3HlEF9q$*B%t=A z$1PEdLyEKflXNy(|>{zZa(xy21oUwq-0Qx5gwJChKlNe*&(M8 zozm~2UGTW3%IMycX5;@mf=f`@ApaNnDYMnK=`%}=uSjie8`IV2^wce%C~5ms$>y&i z_H3SH0af)5kvdMoTTh{@P8F)cNge;|q$Z|aOw*Mx!1nGOuP>J4C*h3bP}JpT9>&6I zP{PCTGf}WRxnp(+~k z9qAK^Aucf~$N)@eAETT#tkCXq(E+j8m<*RNK~liKrZa0e|Cx>*swF8GJ`B+uaAi!d zgvm4xmP8-Qy(8EE_nJE8NKY@2ItuKr-!`6GS_0nua$U^qM8=ZNqoWLY`Q#TNx$#*u zx&x=oKbtADDw7u&4l<%wVC7L^YuGGwD+yH_H8@mh`JC%O;9Tc_ddicrQp44|UL>gv zB!2sk1JJ{(g*bmzm2XN@Z&uu4$+vIZDJf-$c0l98=!q=Oz}d%~?bZX*I=&z^;j&Ym zYq=B?cxHU|yv=v3)`vH5t^HGp>)@w1bVi+L{8ch%@M$mhD+Rry zwN1Tc%Inia(#rFrUO{_(^)ocOa-Ju+6t?-4*cU!evI<@=2$$Ok9aL4k3soabv0E75 zE-W`3wZ!VZxn;h0utYz~Oh-Erw%Ha^oDxIQ#B)}FMNv_m1-szB zE6pqR!QkV)Z#(hdzLEuI3D+4j*MiRp9UE`|>&N?%uU0SR`OS^^)qxmEmRz4ATMX-w z!xR1X24CHocBQE(%z-_r;8f2V4mi@k`9LY~ujU>b2iS%&C zuRa7+?T7EZWnqAX+*BG;C1cS}4zT~%ISFhM>&$d+1lB_%vx|^}y_De!&lF(0D+UKi| zs!#k;Rz_)inDeyt_0@j2w2D7C%cj`J@e?PgNTD;U2k)v+)!B8FYkv3Wj$5IQ-e%vU zMu67h>T>yf;r@ByWsr2L3%}Z@3McQ5zPSghYCOXM^G|0RkiaH;t+~HdJ2KyG$H0!y zd1EJZ8`4iV{loiuM_eC)ad;$jPnLl0i!AFIzzMLvZGvdGvaEnN*^ z?TxnmxO+(?PIYE6>u=35d<7({c7K~z!ua%3z4jG+M zJLZHcht@4=_ZRN5wy@i#1ZZmd(fa#ZAR>G8FSMGpX^whYI!b)o@n zyArjg?QLbx3A=NlJ!IY2uH}8#X@GhK;uo_s#GW>bK1xJiC+{g=W40u%vde62DS@Tv zS=#6z4I^~MK=y=wqW5wpsV{>%JPc8zc>_`rk&Ukz1y3nBr3VSAo3<{Jmo}XXTiGa~ zLc=&1F09a#?IAUV1tk;h!BqQFPNTzI#Xyu_OvQv5Z;!i-bDNkIzqA0(p5mI4C!1C0 zvsuR3<{`~DR{J=?&-UomfX9y@b;(`ot>>zWsS|Lk&dEac)?Oq%g4rB6xNFhZ-5p}; zk7F$ifYr-=wzdfO&rc@Ch)$Ie&mtfvhVHW>$+)=}*1Z@IY0eQlP&onuWYWFO&LBgb zQLIQ=r@7<$a5k9lcsVDD3{2$tmJftkGy zJ#Y8=Qf!Ktj9kkSVT}(T8cvWgCe~f`VKZv?pSj{rB(R|1Xv&~M0{(0mfk{`4s?kFV zA50w$e=D+1?EFGWpXJmF2DG`%PQSHPLq7PxZBJwE-Q@KmIVb|O7H*SiLw{gLRui{g z-ewu6PnESPMmN5(bbCKSkk+|&@;LQ4MZx`iW#B7P>}b;@ymO^{U)9=Q7SdbN+BqdF zPNi^J^jgeLvzQZG{lYlFk*#J8m1?MNM(n{{E<`x^z#JEZYC`40n=fW%=jR8~8U}r` zbDQ?27)D^0?0pQ&A>w2a9Ty2~F$aBS*1q!+?gV<6ZQ@7{USP}OvL|^Sd0&P{y7M$w zPiu(9D|t5WDboe`DZ)o~4q@pxRGC>0}&7cYcCtZA%}Jl^@+yIznbYeGVc82}o@eMSxR2_1L(BP8KuP z#XK@EC}5@JX=$!I$P9mGj?+q~5={8dXY*3xHe-uk4*2=NTX(bW5}VkZSz0G^%GDI$ zWa>!ujK8QE*mJq^cbu-0v9at89P!ur?pB=fQ%9F|GiiOO8fs@b&lp#`fBE;OZz_{m zXVb>mWFn#b{!l*HVc99-z72ueq1{iLj@6gm_{uuEjcElb_a`l#-!z8n4dmr&mI+yS z{dtnQsr{^j{h?jE|3E!t93!LB!g{_(c4tof^7AG%)#_r)^x5BeXLlk`n5`o8M?Zx{ZwqO!UNP z6+G{jrrucFY*klIwN65(Hpf(xYUq{n&e(UK-_y9#yg5RC%SsT}to;!`hmH$y+08w_ z?uE&$(=zn>D0U>wvvk_k8Omm88y(*KTY?4KUYgIFENNwEpL$<$enfz%*s9(68VHp? z&=GsNbtte~))#FZdz-MTL2Rht$VRi2Lg?^1D?7Ta^_$i>wB6ZLNape%g_^`+d$1wz zGu~&M9u@hu(CY{lOIbA^)T3UGtd<_*<7+Jwj%!s4z|R|<^J%<@dW{UT4^~dgSX4Nd zW!A6m7#fst(DKR`$&NDCx`#z3KF~mNTwJi_W9l%}d1GJFC1IpNmJRW3tC?74Z=Y|z@*l;Po;@wI z^@AjF+z#C;T-1%ev%`=JVLzSUvo=X(vO>2sA-1$7kI^UVj253k)cfQYdxCW6_TVHp z2Fo01a<`As3vt75MJxeOx6gSc(YH7+M#}nUs}^7MWsa3NFT9%S%w-Z+yI?|-FtIGU z3HRxoj4}1EE{0xfd0hFwIhuSzdyxu@Ht^zP61wl0o#Bq20?7TReq+Tjbe$$Q9H25C zaDB2us|TJA%#flkJ?zmNBN!z)LMGTG9^eYXk?gnFR!y=j6>c<>}|fzau&F1O%-@a5V~a# zR-Y*fMAsz|BVyw(=*X&+<#q-&ZDkT*NS^!n#YWU6-N0PLPR3|1n ziCXk9Taj&649yUT`T`Sh?8cKSF_2vt$jF>S#pwwKd>mVTLSM)0e076ME?hj^(<%T8 zRZNpZn8%7m=SpzbCv#{_O{K1_?9VW>>Klu(QUv5lL^j-K1w#O3Vas3Ov?`XPKY|HN za1`-wAIYoEt(T!jzX=YNhY7Ad)@E+ouEvxm!5!Q zKU=W`zRR6;o|DDL+KIUFPpe-vA^OicFNg6i?}Zjn6Q2`Xb!IJd181hTfU!+{aqA&7 zduUFRs1KYlM5U3 zTf<-j_*kNH30E$ADN!DzBp^fYM$j3xK7$-POf{$Rj6QEK3snlr9UdCD$d%R47OsF; z=)Z+4oBoA1{cV7YuY_oHbw%!QOi=?FWjbyAc|B5B@0G4$qxmi)}XYfJ)+EQOSH! zzd}=D{q48e-(0avmUNKi67c(Yko4am^9!5PE>!M;cCl|cJmswxZIc~e#K?C1BV&O$ zztp%}Mkm|;{%+{Lp+^!?ARF0zlAhFxX^`8U{G|(dBeA7nbT2VP<)SkomgtsmT6?840r13(jCMfe9Mk z&c3Qt(3H({SPB}q$1aHIJ=7L|fGeaY95)sWWUuLY3MH(sC7RmCj{Lz)Z)M`9C%av$ zFxN8dwYRpHudpm70EnbeF=}o@$6OEC+Qqu9;L-DBtzV^;o$nTwBlKn=5YMibzSxuR z!vBt)fY_>F3w~D+s>T-C-SF$_1#{a*1{z7B4W_j~Rm^yzy~9(M4i*_uxPPsfx+Tmx zHfh)~M+XUxY;9|Xvc`_H^9asM?$#Ws!d!>$pDeeuXmQw-IkSqkn|a{-wT`3LiRor(ZKx(^hNn0@}~r?pFz&kBRfo82%%Sr(xdR zfMtr2bx3PE&o+9Y#x0)DD!=*gs3Zqy$&2Myl@U$j39|C<_k$mYcA--{*9&>>jau&( zj;b94=Fj7=N=4|8r@H=Xj9NK9FpEu#fw1$C*hP_gt)#EHwfKPX5pqiP2_#aIn);F- z65iWcRPed~Iai*qX3m+uxQ=#!DNb<;-9ZmUqM;R5=UnrR&g=YwyG=*vWH&Bee(hOM z3j{?*I>{_c57xF-M;4)id0c>s(R8EYi2{kTjpk~g=d70;GjP^t(l}F`8Zs$ES_sBV7{I-ge zde4JZ9yLFiCEthJ`?L(dc;z;?$x`r-Mypz`5gh(<5xwO_2jyKF1^gxsRdCWMEDJGc z``DTunD{#q(vC^-9&PE}xMOTlFNY12z8QlV=ll4@mJu=Rd=0HI2Y4u-D_}9AaL1_+(ql zS9D!WlFv|J&*DzEvns7-&?6mXDxl)76QImiwr=)(u9iB*Ed0EI-rE1X$HK30p2*1j z-8xguKyFhex0yK`@ss~J*>$1dU6^ad$|H%B=N%C-bFmkA%5Sk{UiZ~$bTqz?j7u(l)KGh^vRhNpe5I5POhLGn26~>rgzgrDoF#*es>x++RSp89ud)WMMSiG#j%#sfU)Y-S15lu zqkng_e0O_B5@z<*rKG9fmM(z$I;ObWmvPU9rc zCt^d(E3FoKm}^~vwpO#|`7j66&X|)B0dSkSMkjmKq>P?t)_sH}jKF(q^v30#63LnL zgvw8Ik7P1WvB-oxrrO23t}UFm6*{qeS31Ie=0`X{Beu*P4xlh&Z`1mi+M(Vrxw~$Q z0$9~g4CGZPZ^e0gi$1peNA5ZQjSK@hvpUoBmxpu)y)r2xQjz`idDj_4O{G`&e46uv zLJ@Mk4=}pLlmW12Xz<0hM2nphFE%H$Gy(;+M;2O47QAGMLPw(p4{dBu@B86kOpz>s z5XNG6i`pY%-zyfBwC5~gTX3~PSWpRS&X;UJda`7=$L|844@(oX{C=WZKpCqsJS4E$ z1`*<{1=?9*JzU!?12oX$@441lSyMBRsDfKq6wP+$K(vfS7%niPf%9 z=XZvLeqsg6JLhO(`*z2^F9+%Z!<(-Oh45}BwHCLO5od3P`MmAKwHJF#6hL;Pb18x) zcg5|!+${1JBT+Zj(puB!Ngxglu!BZ;+iHVY5ppf=FyLT$9#7|*i;Qn@w7Ab?+dVG? zmN2bErsV_hSOJ!R8^ky8V4xo`NQkKXy2UJbNWA>v0Hma3~?WH?jD3EgmwtAb{ zhL|M9=#q7-uA&>BB?V8SUcJQ@2G4O3iG%y-=3QA`Z@WHdPv4rT7>O}cmP8-z_*LeR z8S3M9OLvsY(!BptDQxR2w(1+qn%%s)EprAb%B-TDn=fqbP~IJM(l~C};td9Szq|-0 z65(D8n_A)Fex5e$eBufFV?HyeWaUjr<9XF5>}YuMk(0ZYUa^LL#dXWY;uHI16R{BY>XcBmv-YvC8k&$7dX|Goy}J8|N< zf2TL0Lsa5$ug-xb$2TZ?_Sl~ZX({hA>V}sC1GrQzjWJNw`+-budxX?$2tywr19}s= z=n|IP8v&h(HyC+a->N1PZvtvG+I~Ju%80o8$PjQV1=GHC+4~T$dt(v*_cdj+Uvn%P zZWeNQ81c4Dm(i5mw?gu|*vc7yp?rMdkOgF`P!RckzQ_8l;k%FHRq)%Ni7y z-a<6=-^tMK)b0Eg#0cp1=@KoH@Tug`(CYoOrI>mKR&kIe_w7RY9Ee*2Q~f8OumV4~ z0NoMpi_S49A^zXOY={4Ud{AbL8`wEf0^a##C2WfQ1gU9Zyk=wHY!UX{U)$tl;J7)Y z{HVy{VG*m2hx4pKAs9I$#Qao=gfhi7y!_tx$sohQpI-j3#>j*N2RmkEwn|cMhm~*X zTm9i0;z5&qDb)K;qE|RPsnIsH8UK>rhZ#%LL~lZRU1EJ4zQgoM$QEJn<8;aK8tpW= zuC++zU>{TGvoBQyOLFBc^4}Fngi@vOdMiwNu~#@5 zYpZzFJkw!ur%s>LEZ>r*HrDxr0K(V~v8ees@hgB(#z1uqMCi-TBEh(^oNa%fN)a%C zPRo&c*8!U`;7_RJNji{$6_T3oBd{tU)sSl)LONl$!zU<>(?nC30g_y;68Gd<&cN2*5J0GSdy?qTi7-2vAmn*a z$=@s>34UaF2x=Y5Slmx#k`Nr^9qYkKnmndX4SG#nkeF+k*u=|-P*7{>r^u86U@Y@n z39d$c?clY6|4yYS==fkil%@107^t#_+uqWZzNM=P%WeUBa;AHYRZFZbz8Fz_=AX!sAweaj`~t@DCP>Kh~fb!xd%`(w`) zoM4~rs5ezxw5{#mi;@gSZRb}+zAYOhJ<`saZV~#)854;?F2n1+Ea9wBmdIyiQZz~7 zwII6T0CStK#Jb;8a4`Q%;%bBU9b0Vy#?bevYlVXD{b+`*>P43Sz0LO z!5U7aB>|Qq_~rzyF=q`Nx3YQ&Y%b0I)CIuBbr!=a;~@%YfTigqhrkU>C+KjrMo7X? zPVwx)>6dgY|5IuIe>W>_mE=VOYW`7q2z?WS8oiT~KbdWImjCvJ>Hx&s{PNCu8~xVa*0?pnJ7IGF<#MQIIyT6y(eppZ z2pcdB`a*!AtPVOy_}3V}2iXpGCSxWNg3d+!>tC+%TRO5QsaN^bU`K7ix}8$wejn>Xb`JGwPsyj)2oh^ ze_vSuoGi+13|7a$H@S<_XSce8TF+R$1}nEeyGDwPt^qqpYjHv6GWef91P;k7|2i@1 zGe7SA&jksa>^1oE7qcA`A7{OT??zo@P%lPEIXJ=3czzLklJoXU*>2-4S62C9pN{-? z_k*g>bZGrylKfgtL!$>WP!OVZkjH+;7DB_f+KQM;lECbCSi{L^$`HMQxN916l5*8VuN9*0$wIS(_uJ)O+v1U-FV{q?~WbmDpXn-y9?hb-nK z8#;kmJ?sAe=PQ2TzPN`l#j}z&xZGR7SXbV0>P6k_`5Q|_JA~r5<$BorvB&zQ!vcG^ zp=etNH~S(J(DRppX2z%8A70SFpH*^Tc}WW}St@#58OFFs0r8o2!b=)A3!jiQ3?cN~ zg5i}hZ|Ybk%zB-J)3PzXz=-&SH-i{ z3dc_ecAB~g_9=BmU|VW*w=F5Sm_libk>mtF$y=`Xi6gL~rJ3=}O9^Lqy^I-^jbuJ+ zl~V8l_Yp4e6**NxEWh^V2)QrEc)rhKNJiQPD@k6nX(U~=%ivfoOp z!GO=TcsR4vdy$`lT^@&RW$1O~ylZ7NLPHXcT{Nn;;ih|U>ypwA(c}cn$vaxU2g04K zUhE}CfREd&_XZki^t^cf3mCkul8R}21BEM+K1HDa!)3v9qa-eYNy|18b|_M>hqT?6 zLd*S zNgMjSP(eR%t}VFib-n`B&l$BgN7}d{boZlh_H}wKM)@I!hvFm9@o0!4QDe^Vk zh0_ilHGNZY3Fy|PicV#mRZAxupi&?ulznAaz`~9x#dR+gWM`w2P`Mf``*YlQ9V0%6|E8kEL z=btmEYR!2}Vz7k%^U@EcQBor#1u+%=?vFmf**c0@oR%J0&HrOvLb?alioSP&W{#Sy zbE8VFReK114B52SdZyyB^IGS(AhUG;@N-Kj>|GV&tQ7KBY?)1tcrb}X_iTSwe~sk_ zkC^>vn_G{KWRD*%RfMxpsQp!Z@a0s51dmu`#S~{KB2p?DZqfW3o2xtBa62t!3~M7Z zqnHX77+3KVh8g3VKJp2`$vTsE-hmJiUfy}YZd0x^0MUzf1)K_S zyrUUV)h*P@Q`K>mf&R3%+XABYN4c79utykCmlpae0SjaAx?Vv~D-cJwS)@G>7doLyRuZdpz zJE;=5O~Z?^Mv6|yH$m`10CysraNblNLiu4SZ{xE{%MuaZa(-x z<#Ovu4Ms2Q+@u-V&-hnN`pyF}!Ey8c4A+_#qf!VXvB9~ywCCK)vr{oE@73blpMtrHFe8J8>YefKFQBgyCvjzNX zIz4XB0t~kUYO=XJjKGs)^}K#t`9?bI}3*kG_(c5`*HZTGNZn5+?raKnJrQVsQTU%Ew3aiI*-Zv!@MYo zx3{BDvtMZsEj>|NX%eAu#nx7ix*|W|$K8esqhu2Ns3_4JF4?*aIIT)H9j4+2+9s)`>(@W$<#^ z_if2LjV@#7xkNz`HKkd@)jNPY%_9fT>e-$fD#8n3`MT0kIi_9Mbj37P6R<++Z9r&) zm13+<=*ixJWs#?MP%m}}UhG|nNN-PZZD%T|>To}jh(qeb%6PZgU@4wwI?6UvL8y`* z>rY!jXqb0IriWo5o)?VjRhJR>=&6>Xj5)4@)C0SvoqGXaWCvpHN zCl)jx8)Nb@1)E$5h}lO>#|nlTiRko@?`}cFOVtEw9Th)?yI;sq)MvONI)6cO=h)76 zYQPpas8$SQ7<>`~(;mFCdKv3naj1M3NIH5XNC%{p<_xNdx_R3QzWyrVGTeeQb3n2L zv+upy+jIkXzV5FV1BTop{;7?CAjVyA{(k$=7z;xY2hluVl}PH`kELaN^n@8SQ!9Cqq7xSpN462}7g~b}V)Hf#_Jl ztAiBQ@CrC(%KCOi-pF1CHE1>?ZW)xzrCf)sk0j19)HIsklxt(mMe(B5z#)FoE7ty2 zSg3>0iM(QlmwK+uOnj5|fgHrqz8@~<*^q$A8LTK(X8a1OO|PhBXYr_FexmS`Jvm%o z1R4`Zy+ZcQIL*YNj0@lJ)RfxBgpOS}r$b5yrYiVt!MM?uEfH9)*kyfaL*bakS|SCa zBg@EF4Xhs67VKET*IL#-YTe!00l%korsBlnGv|4Ps(~Q>mlRWC>L|}OxZJhsO1m*! zAU-o#UaERAwbq=zwp4=VH^S6M#M-#lYYKC+loZx+cKZ``$Mm}K3)_{HE==BTE9nuP z8>`KfJ`ixN7&%;S99aO`g$zTghA*&mFbLn>0v!nSG_{4?Hhv-~>EZdx zq(1j8x!^otq~4+EZgT{yvf9Ua#PW3xF5O-kuqH+B_F+21mCahXYApx0!va;uun*~u?-9K6 zy9fT3HPihVK=dg zHWxzbaWo>=gaXCLZAQli6{S&G#hM|?w|5>gx4SD?Ea*qm+x;}&@v255AY`BC4wfBe z4A)st$*v2!nPDk>Or$tBLx z?8UdK4@Lg^hOt`n(~UU)bma71&A|QDjkX8|VpguUD~O5Ga6Pu;LbcYT_fOZ0#p~K3|cUZ#=zR&W+^(>g&y2G`9 zpzvAgp%Q&jDV@|{p|<_7APC85060NfW38J2a{XHqd5 zL1uXRU-DbSacxm` zm%HPY^s|_8Q7P%2jBO)U_06P$5?Su!w$>py`xB5k;a8Gdh#m^eTC{|hRhFShdI9aK zN8MMh3ACK&%j2m4g-jU?<=4Y!CQMxO$Zg;^o}16hEaj4e`mQ_9YS-P!!Kql;KYE{x zcBSU}YPjwnmek;aO4uI*!l?(%X@*3o<8);cb?e}39)mD4IJXIZN!&^x4zD#7P)>g7 z;SygVOkE4g9*ZaFP+X#@ptB-UAakG4yY)2vaHkv_S_ldENX@j@^Cvr&v#lq4iybpv zK%liUWUQb-SSI!>dZYBiAa`VDTgol%TpLdmWS(1{@+On$($zZ5D1E?7hM zqN_>LZEeswFX4O9k4Q6RzXPFn- z@$J{eT5F+uvLtNDEavc-Z14&m_8Ucb_OEC!ec;nHl5_LB3o^R~ZpLg3S*u+~U zf|mG$h;N%1MBlqyhnK_bVE@qDQ(t36k!F@)pHYnn>CQf|C{kzHKfccks2WCoH_r(7 z%U&j%a!aAottNIxK#yyJmxh`mjR>?Vc3I`OoL3?EN?#2v z(ak~RpYFWOilA;L^dO{&4OHJ48`4XgwPRST(Ybum_zUhiTXVBPj=47jyr)wn$b0s2 z-6+x;<=ww-VZ1#oc(TIjoyekoAXIv|-Om@_LEpRb&A*dDgfgiKpAzO0nEdkM=TmB9 zk$*f>qOgI1Yx@3D6VQ(dLH;M}v-Qt!XECuV4*HrTv<^b$G``c0jI0$X8%{~f9D;M2sJDLIg&l2_sxW)4(}02y~> z5lT+TXE5!O3D%12*$RLAL>EV=X$Mz?waRYZ%|x`4iI`;U6WQF;7oxSMWrs-*OTf2Y zx3-)2w{~6l2g@ij>d<`HPg*eOpvQka7UQYHqD#E1vR)5>@?lg?l&pO?fFD)X*BQkf zYMZPxe^ZA_<-jCPzF5g4$0);JmfsrVL_)Q4T+z9%g!Y@gt?L9|+QuJEm>c)UP~)&cL^Sz?@$uyUl{o z@U1g7lMXeMwNjzCP0o7>h>b12Z$^A}JkOIQn+kGi_IK8T@j}<62a)~4y3_N;W@VBe z855UT;plwklbZdlclVTtGR7)T59MXT8dJBfLar|a?v*~hvDp=wLKbgJk%tCo3bKWz zH+C0LahgWRH8as&r)D9bl=hY0DTb;(uxjFvXJNoBSa^YEk-e+k{LxC>ccM^^Sk58` zOMNgOaSKHtL7S~OGgQgR=eT_oBVV#JVM^YWn|+&Y>rE0}dOu5e*8t15RMOohd^@Ly zkDq@dE8Q8F#8z}#b$``LJGFL$)jy}~uM!fJ6|9Giq1;M=<>ng(2h7WZVCO0HE(*3L z=!;YwcfSRau1S!Yw}?%m<2)DUxmU~T`L%BdwR6X+`J-G&h=DHM!}Re@<_sqC)$pxC z(Vi3WBOod&9?~OA`O5lULPf?FAqGKWi|tpOm#_bzyc^F=T)SL+C$x+y85@g0tSO65 zW%;ixc@dQspwnkXC^rM_o%xU=uX5oWuk5iArjha4!ZPg-H?!WMhI$qY3X(*7=Xz>hxv=3K6RT4d44ZuV|%b?3zf&(NA) zS8}p=?}debxllOvr^Iq^L@cL9h=rXo>26~fAA&hVrEhEy9duNKE4{~z zo{s&%mUUia13|$ zf^PcAlmuH=)F1`iF}Sac=*A4 zE34;+pAkaI=(5<$pM<%TAN{M{-c^wmDtq*vQ>9O2FDb7MRqk@k4zM)*7i^;5CZT)- zB;2Q07;X=9URaP|tXcN+@kQZ z^7bQ=`Z6B62A-)*qd9@Zg5{oeLZ&bER(G~R1Az7L2Qc#LPj>S=xR3M|L{ha!`d&t+ z*4#O$_oJy)LtRs2)juv_Y(D%cgYc0YoCj$hah~J_vxP3m&j%qybI_pp&_bb-eoa%F z=(OMx-J-E~>5b9_AM(Hq0wfUwC3GOWzViqrRKP)2* zw~X0D!3_Pt*jxRX+}q5j!K+8e!H?$n3ippb{1M&XuB(;6M%>pCA;TTOJiBo8RQ`)^ zE^{vJf@etUKkZVQo#p~Y>k4>Eqf-G|SAXQpO5k+d-`Sf4brfb}s)u#JL!pt*LH4^xO0L0U1y9AU8R+3{`&@ z^3Ih0hX66Pu&~Qfwby2lct;WKb!}VoU)+rho6qJKcHx_~od{JC+$M?Ib@x0sFh9Mr zImGSQukI6HrEX4@>KxhZ)wr%vdbA5Xzem+>W=Ultu-xA7?oZqpVv8#wEPD&mB3_f4 zeOXwHK22#pyeN#<#(~vnD1Qj50gA)ICK?ObQ=reZ)jMH(R%+o5!(VuEA#($e++;LY zAB3D47KSUD>nKv%^$Rv~5FyRX_mxIsQZ6Wt;wt{w{)m5o@-Jj8JKr&y9?fd;hQ5zH z!44Heev!5y<i#Kx9w(n|zk^Ael6ww+Rh;8Wi!!c(2jj&4zprtt26niRsJ65V}{re(ohtNyac!s@lNV|m_)wrwDhrGllYP& z8xwMCvC^aqTThxjO3l4m+~2zDY=q8fx`lTu;)0uKPluC4I_e*Ie_0~;0BO#TBZ({k zFb6~5ma|Nad~v{)d48}d13h0btb{=z;keqTAKNAo^N&O^u{*D{o?^|0ACnZ#k}>$7 z8L}Sns*8|KL9<$DkgbtUmb!M_Rnz({c6=7Zw1^K~(D}{>?_DUZ!Dca*#>&<%I&iAx zD;6pB&OAzDG}iY9%-&JA3kVtP{l<>BU$>k^#ucT@@0Pd?xvko1zetTPn;ITk!G6qX^Y5>@z*B!c?8 zZ^u9LD%<$MBid=i1q;NKNirAF9A?uUJOaqVBELb5+B zqJ9LxHm>@-d!Ez|=gL#ShEQ`2iUP~Mx~Q#{Wg@<|f5$1q9FU@DxWSfL9y9(02FteC z8T74t1PMDD?zJg9BA_bt*q``|WJU-mD4C-g$`Gv{poeWKrZ41zUK@2&;wJz((oay@&&d;6M#F%|in|ZH4fIRSWjQ?|*ri+E*IRzsfDRqjhl54Bo=PI4T{I8ap z4{G)9?`w#mNF=2$%MN!CNd;oBwcUGY3&ajBE2f96h6jJzav$m?hur0rd6~}_OCf`5rTQE;EA#B4|zzFumu&|*EgjR zEt8w~^1Yn9_@P*V7zDms$k)szT=(B)9v&mAzI$I}v|fMY4!>(m`1VNM)qVQ8y6nzI zc2WVW>tvi}pgcpAp<;Mhg+S;`$Og~@&}Ds=1_{|lab=-g9zpEytQjML#$?_`|8YxJ z!Au2>(eF!WCkvVm(5h8Pd;4shm~90oS^bq&k+C~foeG*GeMi)Kimin)PKj|B5NEUQ z@(85}bzfdXUPEhYbbUXU?kw2$$r{wPipCPH;$rbFcpNuo{Z+a2#32tWCw*e4+{YVC zbbDIFekZ0_LLM*;&#QAc?!*efNbqg@+Yj#{R{;?f214u@w+_0oIgp14eyK}ln08u! z-nnkE3YH6-2$EXBuh==kR&Xp$-X*4nP{wLkZx~!+{v@&p{|5^${$Oj6hDJy!ml?Z! zMO{;#o|O+arYN#Isr!G`tlqN^2zaau&Q?qM1I(TveO)ueNr53}VVF z_A2mdyklWXza$zw&LRJ3>FPyf%p-r^FY?7hi{KR>23by7I_bqmXcJ9i3^2(4&c^YnbF+N;hQGl4j zDa(JkW^0$C(E8tu8v3a2JQlXhbdQ-J_K~7|UC0^D=*P?0GJpRz{P~W~M%v-`;je@0 zwzyZ4{TKYW8uX~fDA%t%)K5Q?%jq;ey;Cb8;<6&5SVA=Rt1M6NN1o$FW4X@b$AEWC_5?`M@{d%_Veh+}`T7`1 zg~dpH~Z<}jHh|0SDllhGdH-6FW8JaUcKozU!l&x?e!UmC&}Fg*BteRYu`Z~>X?4qXq_GoF<*PH! zTp&G3VN;(wJb4U=LvW& z)-m*qJ6id?ygP*d9#?yJguX>kV#67k+=BQ3mB5ONGN)gaRe^D|Z+5b?Z5XW9tuD3B zPQh8(nc%*kHiSjkS|Tp_6iuE0qU}!aL)}oFCz=^m-KtiC81Uz--ohYWfQaXAi#~`GogstFeZzHicne zdq4|Ys*^`0y_;FDua$%7>LJNRo0s;bz&1)9EG3k>F8!mO?4Mh7D00g%=qwylvjJsj z0^;JTrsO?mcE#u)0gSY#)1P3WAXt2aAQ!4;)m%zKfu{7C(R|Wz8J$vCFuS5-mtOZJ zi-=1I;2gsK6Qh7+%A7bW|Cwh}XQcX>{?EM9&v`>{8g$=D@G_^&=h~ik-+;ZirLWzc z>e&2>=&owCA;TT4cOF6xd+DSlQ!f0W$S%kZp^>(Y{7-+J`^UduKxe{|*~&ry=-1X3 zwu(Sw$ZC45UcJd_`8zO(|7RCm<{w2r^>!c#n8*L&+X@+E;tT<%Q&zMy9{uec=8ymJ z3Vud*$sV7739LkX&BX6_|DgHrDakxnh7FtG`Oaoz^{mf3Wj;MwOWh9{uaQZ{X=H!0 zAZ|Rlil7_0*+E~Zo!$&7S^(#HnHS{cv`Odt@UIZWEU+h*_K2rdebe8UdG%kpTk6($@UPeGORZ7Zu1gDj=NgmeoViVb3wn_1jKFYnAOMjIB0RDJKU&1A5<39|9+eR>fqR2&7-%hhy%SO53h z-_?DH8dBf9n-ItNtyUPEy%57x`P|IR&@S|{`qx>U(Er}vm1I9Bg?e#L4;Bye2Y*NU z!B#2QqZ3Y4=31~+b)@{7iQ}W2DL*DboKDl zpnjv_IcI7>#F?HWA6;1yXDoLVn|jPpu48pySUCmt@p*nNn1in`>}W+M=89r3Uy#wg zsqmrMUc^IT+l5mg62sgHwrs01KIu!~ z8Z;vlb1HrFyR>5a92}Rd7=Cc*(1}=Vj};v72JPdJeVp39j8r>l*s-1oPGqlDdUxyW zamb#e$6`1wH52a7opjW-8C%msu`DWNbKc*)>qGS#dI7+%hG)~sp`|tF%Vr_|SGwO21eQ-q(X$a6V`dQ$&~5kNnf+}fJ$JeaOE{b;~Sicct*bNrMqGEIBr?|8i>6eRW6e!i<2WGu6S=nB5iW%i;3#9a5p%tKOF} zS_d5<9P{-W>QL6i{!TUyw$^RK!5-Sy0+SaNN?LQrRYEEY+&P<9eW+=0eRLguW|yo9 z8n5DZ)jJqqn~$Xt=sWOPl0G)9vY-QP}qD zBAzDv712iB*+}+xlIC1K4n|G-q9GQh(*1QIkftxpVy;ASueM zBOqp;NdiQXwkR}mx6mCDBruUtHc@JO1cxP3rR?o*y6s#7W&)J<;%uKCg($?2ls#5n ze$0Z4Y=^M%73!ONhK2hw7nu#L^#j+5Z`2lwaG9&fHVvXAT@)9f@U`@2SwnQoU&pJ& zf|qoSVEkz9wp=5mdT|~{e#W}JmUTUg6(B0wTXP`Gd*dkGJ>4ZELk6tgD=dc-Fa2^X z;hF{IGm>8{?$-N}62@<^Jg~XIY~Nh;xL3z>BPlr7+%h!&T55dw@u5cL=6* z!bPTQM8Ibfab>6PxVF4g-6KQ3v>{n_PQ{Brp6s)-qx$4o;Om@o<*0y&u@A(`qeeHb z`_u>)Qz^@k>gnq^L5O$9`Zn}CEJ)S-{eC^5?HTaBPTH%uU3tOf5r_yC^h0M>SyU^` z%A(4molgnV$-$6QBh5U|%1cbPZyF&=N*a!@yKi(ER8F@0^`QDS9HRFiBnceaa;hc^ zRib)SZYg8(?=R%=o+)XT51dbSdW0$g1HIjWpg=+6z8(C(8@Y6uynyAZb}K5I@=Usq zI|Sk$W2=Fma6y7^??evO_fryvz|VOweI?`#v(BXf93l5MIb}yBhlN5|PpXZ*yQwjv z<0(n-t+z$$NDeC=T2p~n6H?klN&*b!aewa1HUxPvamsT*ds@w?W3!H>A80%;h`Xg9 zuB>Owb1^jzjGypPH5l2zqlNMJASEF$LsCQf&rY|nC=5FS40lm+1R&HPUfHz}yD1#; z1DbccO%q*Ybi9(O?h~ekAc?}U7-vS4GkDvYy<8M`fWWLU*s~}t5#}tn6IxWe1Y?@U zw9=13jIXkWKG0%gT+x~NxsZcDT3EE~7pEZhi>6H9i@BC{?7@Jj8@o=(q?Wwjxh zN_JCiYjVrz-1nas#86O%i_W3n4nb}u^TVI1J6wS&&GNKJ;5Sx$V_(wn`@a0@{HPSp zaYFac_#D#RE$!`s5=7LwA#jzL2VUXG09nLB2s=vwn$};?#j=R0YwOncAaaV4?VW;w>!_2<5b7n8 z{*{HlKc+(nN&_|w=`e9xoaT!p=J!c0QOw0*;F-}|^{X7hSW<_JBRe>tI08NDWR=pW zgDc>}fyKCL$P3lt$anxOUljqk^jqJ6g&%- znTG!spbb35yOk>&sH@Kuwn(d+LoQjNJ%0MEA_srp8pYB!G9qd}r1;_#+TUnNO>--U z9kSl)%P0+UX=FBXR zL6E1{&MF_ts#U0;(h;4nmEjrArdam#T882THniAp*#S@q)ApLg;wabE79G2NkYn4_ z*3t*VArNEnC07hm#cHdmfNceJ#Dwhu_!)Zva5H{BJW=YSkF5BR)s!DgUQ)hPY%H`Z zu<{jR&Ll67fS>n9g`r64G3)T?N$q0aGrQr@h^__m#~S311wFpwy^p4+*`G3tAgNW4 z@}0lhBa=+|Za#_(|HI=cevKN=g^g$Hk$+#T`kMG_D8QeZQeXU2${MTwUu(7)wuCAZ zelJ+IYp0{uW!C72=IB53j^60GgiKw0PK^cK)b&&;>8AhrR%ixM5}69R@|RD!#iF9~1K>87HCJHh3!0@KsnQ)r7GCju!HdKCnrfBkT0&%Oj_z^RPeYV0 zyDw`H9hkMM4@moYzqAnqv%gHN^lMO({XI+fz~bB%ZsG;eI#<>;NXQt2Ysp~1-h?ZN z#UO4|o{G92+Cm)*w1-n>zXn$uLQk_*^!&ej2A<=d!)EayT@&W z2oY2z=hp>X2+fAK|4Es>peQCR63_EM^J|%tz4IrEh!)4@f-kzm^_MkJE-QPg=bY|a z_~_F50Gv~(_O}Nf+4+LYKfK9`Jr3OqT-7GtXb)Qm8>=(rbFzYSe9lTO&n=)_78P}H zKa|mcR65T)GeUTz8qVCYn!Rr%ndD{JD$x-Guav%@F=sLBu6P%a&#Ko<6qyK)uXR4F zEYK<|P)8vrW;5>|>}O^0Ac<6Fo~vtrID|zj+5B=Ckct%RL?h^!40(Ua^S< zRAML40Q-ya8M7^zz|6oz;4{i^?dfRmKeDOghpr#O*@J&-e~q=SOI9V%fFK6d<;V=| zbyxY*t7EZj;J+wSTbC&)Qxi9QqlE-<@JNOFCCXcEr{7^`H83XWi{9$>(u!ZVI~}$! zIjp6{OrD{L@BQ!Os^3F5P@@?L>4q{%o%>AuT)8an&bG+TD|F};PiuB2abDnfU))BR zRsyYgajrVc^P52OZqLgIRaf>W+6}7%{`-Iw@eB+C)#^xv|G_+m4*+D8zEgI5dOU^V zL|wQQAl*@K-m89L5?LlhmutJ2H~|%}2>18MOzoi6u8g?3o?~c+l&JfEdja_(edx#< zqh`4kdD?X|H8vnxUD?v7-~QuYIN)ADo@7tO`EH^us|&XNZ3Zy@EZNT?evn3^>eJD1 zDoew<04gNV5A!bBeX-vpRD;glnQp%K_`$akqBychHy(6bgF7FrffD&`Dd~;*@mgo^*_{dXY z*%a%7^>CTx%jL-n|5J-X6&>s-G$Ke<6WNy6yc$S72%{L7qin4`vhvs83rt!u$v~xl zIhC6z?t&@v$Wjv-=e%LTNLg*C+|2E9|K)hk*rbz4>MVgdT!Ef4Ny(||zyDJTE0V_& z@uWu@huF_M)fJo=!!tz|j~P2oxXL$F()as@1pT$6$@!ZhK>&;8#*agiAdaG<0QdLv zLHrEipLsvN1Q^7G2fXz;UuFkqJoF5efiQDUBU+A&Omq9k5j<*>WW2R2GY zg85u+@rj;~WDLi!v6F1<8x-8Nv6z5D3 zq;|5L!aDL8!D$4?)7sGGK-VdtXe9`!=6F)jyoRILmN=#=V<8H2UF}W8!T`Jkex&}p2 z#m*^--@b8347d6wUEE$}HV}fV8U~884S}jJlQ;#df`91l`|S-HJ(!?f7t`PR+2^X_ z^SOQzz;qb;+ z@G*?__d>P~v86r*vMv=1nUv?dnqV}(Eh2@X?R2$&$}J((SWot&E&9}O>K;x?!KcYa z@4XOC{BE20T1ku-jF#Ej)NBQO0~2YR6_g+R!?VMn5wFR+va4Xb-9+o}2HtZg(Qwh&8Co6)nYAZ8)ElE5T3LmWR$iI4AR!^lj%aH3@E^vEz#RN-rwk7g?@7^)|r(6#}?*reD_m zM-8soDzUcTjpal#XDi5Cxn9?rc6&Qo6Wm_Pr5Mn!v_{Lk6M4fGC%>n}`*#vShCC>GBEw$yVC-Z046)bz~ z*pLZ#VRffQw5F#qaNux6TmnodUdn{b4{BDpX^!cn0U5gK>QfrIDu9>kT(&kB+6kTt zVkjk>GNd8E*}Ce!JQ+Y)9nF^Xx!WA5%O(4Q{Xyx{@#7aiWGsuw(Z==mGi}n@F|@~x zvcc;eh5-7}aXv!=>&f0nyI)R~4+);LD*Tbu2nQja8gr1TYwW;v?gRfPnIh?4-*tZ` zs54D*$k^GCrlxDSCnO84W`dIX{UcJHA{Qy=U}3@)(HRw?Uaw^udBadet3w-QZSMe> zZ$`@aJ>vDqPJx^P|0Ld(kf8jNqUT~7c2>#s!4lH3K>`~^Fl+Xm$yp9E2HAY5VBfBD zu1roaxVtA#d|EyPBAN#@B_NBBonT+3m|vu@hT5rQ{|$~fH`frT{y~DlBkNuXVJ>P~ z&nMzF_8l}p4nE+gyo`L-BAu*TUwvP(?SQQQ2%WN)Yl6?7PmsKwsH(BWn#r-4%u@d5 zdgbn%dW1fl~Zk%kw0afT3`e=Fd+?PrgTs8vG_BA+l^%lAH4VZ7^^XS*Ee2mKRkHil8WJ;c1)^(Pj_@}&iyt^@_XD;TXT-|9)a^Cvk^ItV zvlH&ZfGtpzaCD>D%@o0N@D~^4J_L^;w4NBfJeGq)-qchdxfLqwCs>1#}XQr2x7@en92=WObhsa)1`mUFjV02}mKc6>~uiOOw0@P>x3e$q%Er2)kN zv72k3?KUVH7x6>qq+J|s@4SMm8@KL+z(Hlwm)&}+jh3Dhvv9nv6zgqh3jS04txZ5D z{r|aorkTR-WISHm+F-=BnX)1;oGnc35u9q%?zUj`Reov+^Fhbxy(V}69uNSo6`xd= z@R4~@ujv06O&(1eKb$<4PK<{?1YFwR4v!ndxPn+V%kSRLXF!~1eR#gFcK3ggIE0k; z0|2Q}^yavl40x>kr{J3Kjs-gVR~l{xWb5ccCPR1ly^|x*>Y;tV#-*_dK(@OFvNZu# z(u~=>r09p+SS=DrxC%V(clCSC#Wh#!VWP(*c5x1~9X_H49%YRmvfz1+uZO#3+?DAF zfy>ia28)j1xZ|NVF}M6i;l_!G!weYs^g(DT#+^N%aZXOS;!=iRNJs%ycZlEH?7Ib5g% z@q(`opQt`E@0Q2triwo!q8Ut0DF%I#!u1acxg2)Y)FF~NspcGi7^+;1hlf8@ zd+l6zHfJivn$YE6qbUl@8{tOat^UO}FQ)#8H@BV*H`bjIUjKw|UhSqoWl+5-;)3B~ zv$eu;)dYL;w{nhQDYu0H!J)I?mGr|O!>9L7Wv)2Yhdj5#gnY)+rY2qpI8aXK4tBU< zVvS7OX(ecG{MG3lFK?=};hgDPe*W*F0kYjbUoWOx4|5?M-dvC~N}sr>S_Ln29M4_t zDSO}XP_B;?UChC$bCP>aHAPn9Gb!&-nE|33veZ;u|M<$+zJ$Sbrxf)yOZ6xl8)(Ca zGtL`X#KYxIS$Ob#t!njj#rHj@*ylJY`+`qfwosmw2^FtP->41@?`Lh)YY1Z7z7#mP zFiT=Xq4lbR!^U&^k=c4qqmONEZ7D6RZ28G^KNwEWrYrLKZ1JMidsStb7eyyrI$}c3I>kfFP3nJ^=WmZI+dLjP3-3RFO>2wY~H(q~ZERytYhwqP5^v=@MGlC~dGCr3o z)SwxyuOEr*I0eVfAd9);#!mEoFV(R)rF;pOw;x6?#?w`T3A{a0<6XRNS*+ z=3%w^G0Eog_fJ~;7n-7r$vi&_a58TnL{x&0K5D z3pWl;2*3~DU~W4*w2@*S_DJP|aje{TM}qQiIY(;`PDnNzNWty4Y6}X zB{r^`#mjjC5;cHk1@=f(X_MY`)6KBBH54QJqc{J`GrUxo!oJ#9Ei)~7GCNfnczAgK ztBw7tYSpW*>R)$O{la%1_$_Y_o3D&jUvNtwp;mKbVl*#N{VKS>VrI)%`^))HC>!cx zTU^Pl?R3Tcw`$F=-^;Pu-!bQhw&U~JH~f+umKoE zXn#|tp&yD}STynd$IDxJ-{5oY-6%|#8fU+7lXg7rOa{cNbg9SmTq&SyNV?4fHAD|H( z9aC?us~q^|^=n~6B#9xfe*fw8C&w{*f=UJbd-F9~JS{z0C*QNDc=ka(v0f4j_K{8hjYDn*RFzq|6d zfP@+N#NTEcnJP7htmfl^(cl>`thZ5Da^&Pc`jQ^FuCc&|syJE(`)N|dGLHvazM?MY z$EUV7pB%+Em1_nceg(xO-9oh&Blmlq?t+&+Jd^3$ijF2I>i24 z>=hKa`*vjlsgEZo6>19-khI>3Kfj_J^M@!K>muUs$KN|AkXo3b)jxc&Q)B+OrY5IM zBGlH3OA4d64F;vlD@=lIizpD7UykdW#Vu%UIW49VIWm}AzMjtRub^y=$CO>@Hl3ZK zO`sz~P86O|GOgdzr)QA)d)Y>H2KAMbybijos&!ELXQ1)^v`j1Z*CoR-yw~E)2cs)( znC$`q&7c!O11) z&5v~>A)4XdWhB6{TJmS@0(h^MOGe$R1hLeu{J3>a^rK3+aDT69xju8d&#HDhDI&P$ z%|`uB=jDvA&vxmpQ(x@Q8yWDGTT(^tY~!J)@3D zWAaDdPf1bJnBew}!)0>YrXKAs%zIxi<2_APvUbMCf#aV8cG|BkoT8)iTpYx!EVirO zNqJX0&#&wpXG(HWKoO9o@``?UT9uw}v_^CqvHJU(_>%>)>&yyu+u1Fxj8m0i3o#uZ z4rQ70ht3M^@h?CswDu7eZ{l@e&Fkt${TzOLSDYlfKCjEl3Q)E<&% zNxEP14Gy~35O@AN(J9kQFg9F)W9qCjOLrb(LA2Jr%;)YUwJG%nhn|S}H}q4>?DexI zvp5!572S{|*str+|Ak`avGVw|W7h0owF@G5#UTGTO73q#ESG+dHDgnyxb_~?~duc{H8+PxkCFENt1XA+@OJ) z#u`Ztr|i&czC3{t;)~9(hl^<$2A@=_fJXv1T(TAkWEMf^LgU^}krKzFJc0 zWuH=%d%hEzBHGHzf4u)!dz|S2mhB)KY?zjMDox)*m5nWP%1ThSnfko z-G=r5xm0&U^Ya=Uzr88>`#85GW2}^kdrKRL-Y>9=*mjwa>i#rIey4AvAi7HE+|K-e z*n01%CbPKvml;PLMP<}MMcRy@CczM}>sr{msjPVC~Z^7EbQT3*zOInKNMs^3O z>o>*b>8Wa zKowRl7&t>Ee7Sa2NEzXh=7{R`nyeXaWuMg3@Y_OC70IZD2jxgjg0nEu-SAo=UgI5i zN9{SU2CdVNqfgOT9Rxlwq+Z<1Y>M#?W2l@PCd)e1Iev2HM)OgFhufd)_2GnjD2A|2 z7D}{qZ89!yl*279I4h)^z{e*ay$Eay(^ZG5S#=h|!PtA~MdZMjrbff$$$>D~f`Ww( zr#iX#kD!ez6ZzG|{Qf?$JB7Y1f4tB5fTN)C<`^ROxx?mb0~@G8nn56fplQgevF6w4 zOn+6+PlR6zjc3zPh?4Vb$n-n&kzIvG%w5F1RO^uwNboHPP2w$PGAoQEe9XNA;!Y3M zeD{=@glfUfw@DBpBm?zbDN3Om7cy{19F-huO$hix&zkc#i=;Xzudz~#d@w)#O*KIq z`Q{z2mHBQ92U#jQ#SJ#TDSq@PJjkOOMr7*JHFrtyi1}x>E&H4iaQ#3%*ZvyY+Ilv} zFP>6Wf&8F+$%St?O>OHbKJsD2he54W5$Q9`><`!@gnxgy$sr}r zkl&k~$KBraF1)331T63Y>m3!^4eCivxsFkCyq z*uR2sIJaqknx34@VY>m^7HG5RZ<}hxa7G_Ncn?r)ArVmiMMR*&E|Okh7IIV+-yZ3F z6wfmikp%Bsaxo?t!Cu&5^_O@d%>OL-l)Z}Wo9Cr4MwD#vE3<-#S zDY-kE8N_TWwSqEUl+AS?n))8;#E3(UAgbbU36sWevLeq(`ueu3)hdk@dNS3+I}Xcf z%+ol1IBT=@l2q$naaTZUG~Ay~R?16d?6i~npEsvTexpSrvL!HveYCm_!-UX5R1SJN z{r71JVoLSh2}dN9cCU-v0cC4rEOKlc^X)VFd?eSO z+45@7Ih7yMT6@l3@CzfO0SA-NBunN0gF(*E1~A_*aC)n%FV4)B=~b$qR!=2Sma=Hu zuUT2gvZJ=)nvy1>tu<5)r<1xhl5?tpW^NY;WEj~1CKMT;X}oCiWuxufCm&bLM8V?{ z)S&xpM2w4UpgQ_qguhqAz{U4xIoCbokRzziYY&dRJpy;m()zJBU@(tYtmce-(dMWr zv%1F~@N$c8$Hc@;KYtwUv%J>vwlunCa63hj7z;5qGw(=>%^$d$zV>LesF5-0w9KIU zdG)-Hmvb+4SYN633cdF{?q%UfsY8~njd#|@JZ`T!mc zJFqh*HaSL_U}|ZH*QhsT;pL#xm@CTs$K+QzrC~6uXtddjOLYtIco z@VeL&?JE6;4ncA?=1hN-{!@MUh+bSRC@mr)%8V;rgF{{u@s6uzs?vjNWg&4NZG4*_ zXPyzw=)C{9JL}=Ia`@ z)UDK-`59qd9QmVP+IA9R4cmVZ);?2AfD}uWOBBVQHUd%u1b=sEV!=#aax}#=d7WeZ zbHicbRtSxiCvkSi1nMK2JYL1cPwd2N;NmNWP=i7zUCdg*CCJGhP7@|gh8ok8PRR;| z&B4j_-^KTKMN`cWO+%xQ9XwW@$DCLG_sJhb?Dn;bOHSO_{or5Q$)({mYY6$6!dJhH zsZAC?nTcA8FQoctkVPeT$Mt%bK&EV*Ur0@&np(d5UA0h9~0F`?+i;WLXOft zXL8S*XPCsrHK%4|vV?HLxZZN;yo}#i>KPqj&LvoRH-b6`4zRz^SGzyqal{wTb#=B? z(=*K;4Q}N6KuR}cm(mvp9MjjH#AH47PfAC!5jlR{S5&KI#n!)HMi((d9Wt$efns?8 zo*&Yee3K>%17PRLb9wXC)@Pn8YQo6J}xhU1p23tj7BcDhxgpN77UJ+c)o*M;vdxYP_T1GFM=Z;6;h7wcLTG zUKLSQi`T~Ua54+YEmY^QJEOCk5w(#+q_3r~`AW9F;k$s@-tEzy1(4c#Zb7@SV}#n7 z-`V&~I?A33Ow;OB=Sw>8CqNnUSzNqQLHk0H5XMem5)?hctwbrN$*WEuzARtvgg8Ww zxU8kzZrV-{(WJu^4ZpUi&22ASa0yr!`G)J+?$XwOn?x3Rgqw!vt}MA_ya6wr8K*v~ zAf9_J`G*au&56`T&!poc%9Z5eW@n-3>t&x6O}(s(0&5tk!OYRc`ue_PmR=G1z@F0s zv1zKbThxp+I}a?p0}938 zPsQqaYnDYaOifn4ApW?UMw_I4T!Bq|grCI3`W5V0@Gepo($tuE_@b!rtJ&}xQLiaA zS^~ao{X1mzxeaKy#m&bU9!G@j>AvPXA5>6qpdruTm_WfL0T>Ua%LBYV3xpUD{@JY( zASide=|XT9vIGo8HVG-@gpG4QE&RYxJ|L> zofmoScx{mfj1c=RmY<{rGph|^`fHXv$~t}`vG-&J!R8C4cHL)W2i0|R&q8t=w-irU#QPl zChu~UyHdgPpZSa{NqTGyoRtyouBsA7YMfX7)zq=sck}lbDbqhQFj)f+&!lYd|CNxq z+7YD2Pc5M1>9L43Gx(p(X)mLPtiXpq9xL7IQ+42K2d+u2$H50p17x0m!SQzJjy>WO zmw~NsM$>NAec#`?MLVTVbs(%}(sFOtY~0Tpz8b}~v;g#d^Wy|73hB&Iz0#74!Apik_@%1tN;K!vpD4!7YiL)u$5nE5j>zwbPrM|v6w6lOW=ILYSxkm zP>t7Ty!zR{ADNmS5Q#oY`eCoL@_VKiD^=L-cC1&ulpT!o^bLo*AG|H*7OAu-G5*&k@2+^Y@P zsbwwzIj}MDU8-uVmnMqS1lrN%UZhB^Db)sYN_@C zCqLl<@kw7b8&(QfFa%%}yh)H%LdzfHWvMdD8qWqukGfkqq~{YV|0%1wW#aOI&d+CM z#Es0fU+i76q(rSME}U&0YWLk=hyB+#3nA(UNP z=f5Kc1>O{-X-rV}nUFcSGv5cvYjs3_eDyBXnJWf<7BF%l=lVrzU73K9xVTBQ%84%l zFbY`pEbh$$1W(QpgN}|SC;MI@4%9EEmVyx!v$8>Y8o%_RBm^mf5EsE~Po1-9TzcVy zO9=QYA4yX|zxuy8p%Mx*D!CRJ4mHqBtI6snWUY8I&|&oLKxWkd{+@(FensCrfpQ`+ zqjh+#i^?7h`J!vXxlBkiAVzOiW6;}*Lu++an55;5P3u30or6ZKDHs%wdQXJMP{&W?dmJ0f1PO!*SN9qIsP9HFF^6qrEW5cbWsv#Y;e6zH9mwSY&XYt9(@xugE)%gO670R ziHWQ)8R4)a`wBb@KelyIH#ISXmkp1GMAX$MF!Ag79flh-?U%-39~@l}E4r)Op3bGo zQ=aqde|odRxsBC_P2#XEzcKA) zg~RuezVCOXp*ud`tcWKnK89Lr*S#t;+e{95bdke z^m4T&=e4|tmO!3CeJmyoJM{*ybaYhKuIRGp>nh<6P1luPTn+{0F9EEMHxkWG{?jqa zoeYz5OtFu(~d_rkY9UXs?B>Ze8eOtv%UU;>QQON>CmQ9cw z;0TYH0MjE3+#avj$_8`b37(an7YcPoQ@A+RVtYlknmwX_!fm87^99Cy4|vh%}T^R9%dU$rqeb8f=0dH&I;qNejl z8b6oIY60aOD_GqSK;gw6ce6A6a_DgG^(xiV(AUq2MAMZ8c=w908)AeNkdmx@5}bXddA$CZoxwZu(` ztPnVJ-6&X_c0w&^!reFvjK$P+=eu^xnA>>6?c%V)R+~a;<+EZa^XXbQ0c@9twl~?| z`K&YXI}^|4`e0Nc2rKwc^7aD8RXKvu|c^Z@NmuC3|v5v)Es zoOGeAN&i|v(=#KZ9;$ExougclNHtv8VnG&0K7nosU(0@G=yf-jj``E^(V62a?UmS* zFojPi(~N|}sFK)3MBdn5(ZyN+k1&A|T(aA6^3d``7d1_zk6zy>Lyso~`>Y#MM2tauhd&9)(p!ZL%-Hk&8`Hy?1|%l%7Fb;UlpMa`qLv-J zr^M)pt|hbOF6WWW>tw^6tXmOSiI0YZ)7etb3qrf*Wl!GrXnn%)9;H`1ItfQi)UCtWu9wl%~q9j0ifX4&GwRoh0V|E6N8&r$J(Lzpe-HkatS zUB^d^dS$ty&tPkFH^s@g^58z(ooufh)RLZrX?DJ>_S%`KZL&M-bwL{4V-{{~tY&bS z+t%zdF=zczDwwAiqMF=IilH_%D`XA|My<;(^jv|aZP2J~^%%ez3h;W-jaN%P@u~mK zk&pHI$Hg2W3dYK=9Q%WlnlUuz1CV0l8}ssk{cc%`(dafpYk0qwA>ZzK{7qL|oWaLR zE~7rY|NMMn(P{Ok?s!a{8(uXhiz`$+QktgPq)7z!o)))v$%SDuaGT3N7Hr!uKl3(8NMmNlQIa-!^SOl%DV!@MSs@%zbX-z* zwR38;p)Z2L6;oQ6DL!4b-E5H-K7hC8F$bUjYqTP0-@d8(`ZG_f5=ox`RhN;NtURz2 z?ga|K+M6Q>%og~DF4~8=&C+9iMiwO(K4W6)-P{cqNWDAXL{&@PC>;5G^}e1n2UT>AXb z>j#$QPzhLl^_MZhbmeTY1`^t1M;zXqQpdmO{q0lSXX3#*FFK(hZz%hWp%%`pvO`Q? zn@^Vfs2u#LmJ%GldUK4;aHx>iUhU8(>bSWZcu^SohG&(HH=I8W`d3zE24DRl$i`DM z;AfQ%C(5T8Yp?`Iz7qZE&2paihDRf0L#}kT2scLp7*#Sq%yyqdu2}oF5wzL;3V8qc zp1;1IAP@GN+2kr1HjtY@&f-as|LXkY+a_D}^c_m}s$!O*?GN)2bgx~7f+`zE`niNV zH1n=C)zY-XQ2r1ECc)=CFSmI4SdhmBUG34oo4gKzdGeO<_w#S6c>DhHs7SPK@q+|F zJvTpdcvprXoFYqTfb&N@Rd|0n(tcR`6UHrrh{zy4LZF&#T{9^QcxzS7F~w`TeG|0E z^gKasuJS*Vq2p=T8Y8&qocM4QLszL!`KVWKi`!WAlFM8N3_3pHn|yw4!9grf z8LhXG$HlL*o=oLMJ}SuHY5<$bJrGa90DU5U(s+B`u-&bhmdgf^RL86k9W5XjTs2jM5ZhYuk2mJQ5V~4rmt@I*1t4Ju$i-Dcql5rGV^^asIvN-(SsV-t$_i56a9BJE9Dim zP#s{Z6TTgKmER5VJuF@Af{7oMqqyl#XWV?WSK@%gGC4MRy?S3ACi=*j&hE~xQF|&r zVj0Fr??2Cj(7wJd{2R&jqGL`hpIyjp(ZuwOtZ}T+8F%9+rtZueC=Zj@MqWyKvLO@F zo*!m{D;M{sa9NS)_hUR6GwZk!lDfTW=2Pt4ISE;CXI3y~;NI!zhh!1p;0a0EoGF-C z!z$*$W}sfZ(r=>Yd8^**0Jv3hvmvn8*@{6wF9J=|DaPB0CQkJU5PFj*TZ%|8+fpVk ztAP64elUU?;4|&{Lp4e7-s2|EXY!EKE$O_tM+I_mU)ZXr#LV-#OCcNxRJ!2*QO*$< zGQ!A+Ll*jktpSYRJ^8T$=ju7Z!8;@!5HLdO2NsqF+jm?`woadeT=4XPwnhZa@b| z^^V-N$P4cThqMgG!w3+9t~WS2nbgVU6#2tA4fk}ukSDBcdxT}~J%@VXpLqfPUW*?# zB;96wO@$n|j+#$~VGXNrHb7%eW9Uo+ygB7=()EZ;QP$io#;?Dxt(NuSe?{iR3ICuH z5CeE5*CW|kyz`g{t}^3i!}rI%UG_fp=Srtb%1(k>K!CsAGEG^JbbP)hzTv9)!kNj- zMer1!9-hokZZ-`(Q}bI=;Gba)ze}S;$-J+0uGxYq^>ZDfFdBLDNV#cY*lqQ+vv%78 zy!!TwlLpjhqu(z$HW-W$eMNC>6R#}9}&>H8{pGQ6e>QDDieLvdYa&YF)z-2NP3 zdvG@CPmcYhN0?!9Y-H|$_)8c)Jsd`UW;k_2b)d;k>AB$2kQO)$u|=q<-m{47wB(XI z$5In3i}bbNOo0yf&!|37n;U*NqEg<=_ai|^oo3rBlzdAINP3kiI!kZ4td|xMPugi$ zE*&}Chizh=WPR#$oiX+a9?0w&%<;Q7H%U_C_do4sPlo5Im~+g(61&wlN3MDVuQbYK zfLAijX2xH(g&uiYYB2Ml;74!M{-d8hxIO$xcVRE*r9a|1J$hp{##Q{6zJ_imaKFa% zy9^IO9GC&3)JJ;tPZpz9Vu4}C1)^uzEALCQcz&G0&fZWlHqh#UeZ5Z9#mqtdPm-Ib zBFx%DY(pOpy3VHESVrHaM_>sk=6tDKlWu-<&({ojw_ZI~B{$s)d6<_! zSbP>D0>j$?1$jHN2Q>MQBt@MOZc@6y@cazF3`c*4(Q5Ho&$&#ZF1jRVl<2)ZeN$}N z<*kJur5*JRo(F`LJ|C z!H5H84o`*Mo6e>TQu+>tL@ZVdqGlAXk7l^Jk5K{y3a%2&Bi$`SHIbKad%wh~@_B8y zZ}jvk7MEZuHz#G(O5!gDl+z-<;t6q7JUC?Y$2#tn;a8&mJq5E){dn3Z>p`!`K_LGF zm!g^;T<*cs;bA7*PSV$(uGO>d;|B95CYmzP?kSwDZue8>R67XVFI2;cQonoKxR#TnElaR{i0E~2+U~%pA2xgS9SkNy8VeRwpcG| zO=z^BIA503%zp_({J+KFMc>r}rGGHhb(tY&J^qvVyZW~1tNiz~I3Bp6t#`5}nZSR$gl_ofi52-FXv(;bhtcXlD#21( z*8(diO_pFZ0UK+%TINIw&);IoVzdq4SwUE<{$2(H=5p2Ve|x{B(~;(g&7HuFew_7v zM7rNonKh0_`?Q^~L;QcJqXt=h|Edz2h`iNOn2Lu5AdoLP@Fz;Z4&FyROwLd>H{9gq zgj}ChYXPdWf(6h?lU9IhQN1q>2N>CjqPKXi5t_w0qd zcyJgyCJK47S(+929xWd}+Ox7bY59{q>IqC`Y7)6kRLOrbC7%}J_8wzxyRC>nE&kIY zdL3n14I_Fl>wrF(#oq5%F0C6`-xRv{DYJwhM~n6oEWo_A`hQ0P*g4QMzo1~9B!WZY z1&>04lzOSp@MjEUd3ZelhE0)bR(5M1YenRMC~;7^pZ5H5@K#dIOiXriC2%gSbCWioI&R>>Ln907K$5WOwoxp8vV=yV19*q6=Wh^IBeG+CezR%^ z$Wp;bF(~e0O08sP;qhIfEQzGi5E4#^GJd7|i=l+z5oLf{+W`W6q6&i>dtYe+#WQN3 zCa4Auah!M{B2AR~<@cS~QGaY{a}f$Uves`;`g|{Jr-IzaWAv2sPIc`<@e=oot-_*t zaJr1jiL^K@b?aUua`$&I8NBKVlWJ3Q51$t77hG#zv<8jV8q~pG-kL;fp?B-^K(hf5 z@tsraCi*y3tzYJD#F08KkggrBZoHWR0rBgUpRFl2fGu%*`y?AV^y{&{hJ6I&bY7KW z;bpgjVv-?m!5+fwo(z_;r@LsZSD>HO3E*#Bf*pnSXKH@M$)nfY|6viX0mo*%lRnH- zl^4Hg-|0q#fk5N32I>($66mpCU}p9f2?1V>>^{!GWU%qG@X+3|V)34=aFDb&_rZ)3 zU00&U=%$V_dfiPbP6W3^{B~uz?IrQorz>8Z3+-S}yaOixra1g`5Y0Y#$u}mou}tc| z4QN5=ja80+E-uD(#?b!rK(mzdGkmngSLN-Sw2P-i894lk9+zhRwovI&hyU%UCVX>AT%BneP)ambc5~KQ_1rL0X@=h>>mP?<3BjP}lvVp@fz3yK z$s&juAV_!veLWaW0SUI1>df`2p&mBrDu3J z%ROw}mIU*FK2*D=gSwYh{Xqy&1IdKK@}g^+RuqB@8w!!`ko$S@oS*;hHKCaEf!T67 z-uTb|Wd5=_1oM|3^B1j2m9Ebwo<+VC<7&m#qQf$e!kz@}q#xwLMI^^du@6mRB6LAK zhYbUI;VXRV+xk;`+^g)Hf>!{cz%mJD@=ub|aF+w}V7Dc4O#C8kJVD52wc zz#TaRTF2$JS|E{4jzr#6unF}gR<#u?u@}HM=&>RZmHhXcBMLj? z0`}?51&Gjqa8>K%QESZPgU8t-_HB@)MS(THTL8N&)b;*!2WwYU+4aRrxKI6s1^ac* z!G*4`qM@eu2^$Qp6ZVxPCe4?={-b;*)gsXl;_%gWBHBua6mHx+>&GE-WE9# z1Oc4|EkP}ujyZQ3ePBR}(=^18@y@K1iPb_3kiXBqU7S`ZqVMNK0gIdneXQ(;TH4LS zSR)|!;?Z)`?G=-eo*s4liM35;rRw+9&P%RVJ^ubl$b34+H;`UeW>YjPOYn`Oc5~GVg&Wr9 z3)>^AyN>^=RZjae*^-};&W4c*e634H+pMn?oim#B|AcWE%$vr9EAVH{?X+sC_*YU- zCtF3jb(Z~Sj+D!35xN`0HMI5_d~~PQTVyD%$M}4%JfXH*-#5aLNjmq+f1tVNNKuj> ztY|*RW&Lh^(aQXvtB9j+S+hQ0WedsM(vlJ`1}es!rQ<^+gfaB=WkKQ>kM5id$7pbl zkN5{XiQ#TTOoP0FKn80Qpg@~DJ+;=J8)T#hj97HEkPPPKZO5+~{heBzuoMQyFJA46 zAbFC00fLEL4iusMr9k{$D;6J{jR$o#9KydZz!WWt;QX?O@QUM)igytxpT4@l)qxWC z;&-7SNuUbC13dsl^efa(6T3pY{v9@I?Ea_L(1-|Qcdphee)V$!r4;0|l9dNpR}=jCN}$WNjW ztpo^$jd*heqcZB>*GC^)&x)uJuD#xYKqL_hANvT2uq3Ix`{d#YZAUjq08%{ZJ@n&b z6WqrB!$d>GaTDSVM(iIkl`FK5U&@m*+)z;Oq-Epj(tjMz$c7P0eAf3&&1kHab2!og zMa>#EIt#4Wd$w=cmRI#xD5X#{4%?2DDyWvId7eo-m1I;aL`erN+{69)j1J+Jb|pKa z0^ZXoj-;!a+86d&jMQ{V49vu0!Lkl?_Or4ALKWE7V@t9!~pD20aHdUsC>G2m2ycm$l+AIuo#MZ^18I$eyaKJ(DnRI1^m?Va^^ z3O><&)Mj&DIcI%DVIbmnq5a)NMPCge(QC3>-t=ycYwPk2mX=-uw0Bi$$XzeD(GO;Y zo@U}}%gXV&S*SmF@UqoQ-0cgyrTi|O^7(@UVe1N-28@1Oe&BqN?!aK95_%qQF4 zv_61mn4@z5)FXqL@}>CULe0rkQ~;k2Oq2LuhRgr}8S;2G^#zIy0)7Lg38gg#@FI?{ z7k19JQI{;JrHrp0!Fs~H_ackX(R1{4Mih2`DC{Y+NM8=ag{uoWklHifznF+H=^3K- zSmdT=#s~VF$mJ!aq{Bwp6hJ^>zW=T#hrV2Wlr%mvz;krr!MzCgg-T8fYbCW$FlPw+ z*P{_WukHy(t35prY*H>K4Mn2L{t{NvnrF2BuzuUbCNAKQp!cxpyu3u4P=8t;oFzm* zk1oBJm}|I~adVc|PtxOKQut-|>Y4n%bz6LnLdJN=*<|UfqqkaW`oe2@irP)|dBF3) zqgKx(ei(1Nhq~F6bD7)SJe@z=pkHse3f(P;W9+f{OFT4%m+tGKP>dvWGtu^?&f^(> zzdaolY!3CwV#5d{gqQJ}+XM>fI|-^hE{sv|NhQOqwe#2;J_pcZTfEEiW|FsFj6XtE zi?MG{P3a?(#sgJLTnwJEo7ZQb`Q=z|bb67Sa9j@6vaClfJsh+qjlJccSDQ?`Kv#^^ z0~?5-IC{M0$x$rg*RF#hrxf!s0n;(Y$|vrp^&S}~%0rD{R7spl3=g8RTpaq2ds|Vp zvjug_L}dzsYja(e;Ap@xIw^`V+h!eir(C`b6Jw6(2!b_F1-83ox0Vc1jex#wxLKP4 z-)787zqVQLX0TPD=7JYN@aO~Q@={`--4ttlhfn^B8x=RN?zWz|VpzUK43czp|Sr!94t~pKP9Sbqe!z_PrnMgHHsP zv0Wq8J*!$dB`pyHK}x6@V$!|8R*%)w77db!FhCXepAfdpf3HY&Jd&C`PE+nnN)l%q zsn3%Z?453=zVPz8l4m$sw&kyt!pr++fd5&XS6@^fHC$nz2F&u@~X2`FqK2bou- zbM-SP_u0Q+E(o`*JAXwccozJ!I#6=aSB)B0iOI;ZMPwsq-tckTrf2pVR!h-ULusS7ZZLpFK>-%am~%V|Gg%*H6;V& z_#Dc4i83~R`A|y+p;#n^u9|+2uMlVWS}J1ZbcIMGq1CSzxytW0qU|oKM)z;(zwA zI4z_an%wohjjyUE$hOpD943v;&N(W7NImQycxmd`e=<1{-CN4yu5C4L`Xw-IZ85D^ zEe@a&DtV@XX78~VM$e*A1Scz)*n>S4b}n2rG)H_skVD>Nwd3ce!uw;W=Yv^+wu%vj z7(`T@hQ?njd4s=I2iNt8rGTR>s2LH(ES?}2m z<1$H+b1>~JQHyDmw{%!$e*9gjxs)lsu0`JW`o>D$HJq3pq1R2A_aZlNSALXF8kgqe znb=@Zi_0kI8&UJdrL-QmVk>lx#S`x4q%HWm_5nl6nQ&48Nrwkyr>Tgm*6rr~BbmmE z0h{Ac2uy4h;b8is1m7wSG}5H6J$}xfXe@A0dl+`2-Wngy)NIU={;?zoAC8b~l2LzA z4_CzX;*pb(S9qD1cl$N%FP{%F>JcC0!RQV5Pn`>Qv?43@J;qtJh*{>0U0Vj?hFww% z^+O}z<3*bVc?Io@e$I9W3}Jx;ssJ)U^dcD!78&=fp22N+W-f&(XU+RVnPN_f)VE+$ z(=yfVroM^Rlos5nHoeza=}u83!&W~bAaEe^Pj*}t(?vj(^)kVX{uk^KS>u?-c z6`@&a@1suh88VPNTtawI=!v2G@w?qxeHy(&EupR>c*Cj1*Sq$}wL4{oAepdsVb=`z zl+Vdu(!wTxL@;Deb^Q4NQsnin8LcKsX_kEwVt^Z7m&phNGV{=@gpUDwlrM4giK|`WK0>qViM2AFo0fN? zTtq}+Z=>#(rGnuF?GF8|scp^U9Jo3i|A5!~h6w#wOYY)f<~(=J?_P{Q(R6cn(gjgv zw9c}YzU~eE;joC?^;Y%P0;^6B*%o3{O3Q5IRm~;EUkg0*bSVJKWvrpR+x}$1)lU<3 zbR>uM(c?j%*y&foaY4>UNln=tl!*`j0j%V`VX1ucOFrwev3nY;=s7u#C{O%PqIbR7 z;;~}}IbP9~GoT59U~Q@tEi8JyJzK5CHenR_`=7u^KPI0G&l|eg>UO#6Wj*#LBnK3e zsaVIR*e63DyV1$C4;~0|_w}(C)3p}^ILE%w6|#8eIEd^YJu@Xo-yI+-FAlk{_jN(& zbNb5=a9#Stm-1Xj4)71Sjv>g6z?j(TLP5zkonEi}h!hniJ5l*hX1K}u;;}Ee@iW#T zN;jj!EC%Ff0_X)ekMCK)64r_0k*^}!ACk139eWfX3AE4o%N~*YS}PwK+kueeHHqjJS_rwQ=&nAi8(Gq< z{pH`!JZMuc{*{1PzBaRteh}h_@&RDR5Umd<@E=;uw=vhkB&_dS4N9^2`z(Xw%Q41T zVye%Ioxs-(*V6$Y)OTV;PXU0}0+|_f8LLe9h_YToGJqzPn=_ZTq7*78tf<#nFigR~ zbT0R_c+owAhcLUf{vh2GH~ykjcrppBY)p4o&&@d(dqC)^$9bp%FqTt;`SJl4;XfJW z*E`e@q|AQa^a3!bR+y4#9Usf!to1bJ|8&Y~T4`dXBQb@~x>z*Q#~4s0^wYcg|EIiO z!nt{@k69R8lz602TPlJ6^%MqZP!P@?A$?q<< zQwYq5Ry*B3^AB2p82J~TN|KDQS|78AG zvuu$nS%``!8HB4gGQ54>r-07dWxH^R#i^PVQ~+QSEpO7MfYkC<4p3M?csKq<66^cl z5R1ood58a#`HKF3462CVW~6__E5Ss$eX6w^b?&4npi;+;T0BYze0Dst9;|=7)e!fU zcVC}?D--;5IY!};k2@AU2atjFY1ot;z){Vt+a3x~^r9e>42&$FTav7M4AfHtHk-z1 z`84v|K71xilP5g@+{uYhaSI@km%p|iQo>t^4K&82TdlWj7Ovga%4!)e31>+w6_XlS z;w4p%Q_mZsCq(82;~h}apC|v|oz%5NWVP$Rq@Y%Sq4d6@2K9aE5zaRNwjlX?mb7a!|1pMKUBp@ga2E)ogSwzvCd7**LuXySJrE&Cy;c{H%u+$^W{oy}~nNrR# zbG!fY`c%s-1!t}4R}JwDIm}P8bGD?pYD(o6T!ay`K9P`bQ&DS1nk!CWkgKBrmzdMf zR>Y0ow`rzXYU#(l2F0%|AX6i!nP6rGifArG4_b+0CBx(gY|eHbI_kD0<^}V_F@7-v z$w7R5!zvGM{Cm#+{U+;ciN6;K_(K}mH-LJg%LF_iYXUj={2k#wv(L6KSvss%;xMx# zVqW^&3BMcE#{m#Pkn#W-uV1jy-*(hI#2HR)GFhEg9Bd!B*j~2{GXpx{?zdr8jZK=L z$Va%LH6wrx%~c7w0QW`(*VO+(P7x$Jzic>e(E(9hJ$T)sE15N3A4+eJbs?W?&?&6) z{Giv+2=|E2n$wA$SIgaq?7D*LR)63T0fObxXKQmzFR@mxd7c)7O>k6Jhz=@aiEW}{ zcyq9%G3H(otOvyJNR-3DH$B*{Bk1Sw>$P=dA`12~0+Y|uk#1kg4L$X|`hx=SOtd!t z_+h~5_NCrS;k!l883LaH*qT4KBIL3HI85}v=By=Kwsx!NG13#gUp>L_Ca-@;biK40 zGSLn=Cwd@RzF>>}W8|?oI=w~S2q@|3i&yY3E-2u1#$YTRN77}tuZknj<4E_SSC|B&g)#*0~?OR??EAS_)8?mV0uFo~O)hN7; zXHC-o@|UC-9F#o*=i`lp5lJcCk1odEU+Oh-e-q?J7cT7mZ*rurlhEG*|o*(401HMTRGV(65+E zDm+`N$xW4EvO+W#K5%TK_CC3tidVZy{D$bweEQWqFuR&)AjRi`;8edc|* zU&r{SgIl(?Bw->$fy|DC0rBi;XKP2hTeKBfm=g`ON`qkA49wOHuLzg92?E}#QvZr6 zo24@5Gfl@M&@K#BMmv#TysAfDSFWHFj|Bb7IB2`8dEc2t7E|Pr5>VEC#}qd} z#k0koZVp3ldLFJC;0DTE>J<|x9a za&2Sq?>{Ic^B-W>dFhRVpi|vQ_Q2q*;t?f=eTaJQV_$!tukoFVV2mM-uUGTWCZG?ppwidZDJcTYdI{-cHNRH! z+gi~Lb zg^A7_fI+;ahT5H=Q&tjA_F=Nvke6V4PQy-mAHW2FMveAYo7RW0S(*IavUgt9`1P!P znw$3$`|sVTd)u=F1}aDg4BsG}bS>4O3W%SoTyO~1;gnfSddJ3&WYShZ03ccw82U&L z=H4{5CG?LPObFuHBAn6sb(()``kd7`D{3NIcj!naTi&oy|CC8ve)pUhD^eLbvs;)j z2bC&MSatI|O~?mdKD~zPyeWXoZKwo$)iLZFHtn!5CIRv7Zs*na(B>xX#&c&*VkM4G z<~P}MDW^N9AIFnbS9GZxDkHb1EgFjUjv;yZmvPq3GutY=g9Wy2r9hC5j-InVThV+# zM_r&8X2}GnS;U;2{GV%cCI=YRU?aF+r+@S5qS>O&&HXTEkS6D2;hsRvEMMIQ!CwMR zKJiS-^@R^pg9jBtN=2u*PuMhKKT)zO?^m(60>W%UR@PG5HXikBro9h!bB!ZLNGOXg ze9ds^O@t2Xw*MWUcGCRJkXr7@nN1V)$^u0V9jQgEDeZ(7S8V zT+53H#mx$VMvf|zR;BDR4u0l6*Zz4;EY9NV&-PHyu@i1Vt_dT_-z9OUW~8 zgnXamDpcx(I-X%r_+t_ zUT>EBY_f_DoVtTsVNMM9 zkBKOO(Im|UX`&Q<&2}FZG@~;Lqa&nws0{5PdH-Z%1()>%4&lk0ZEuq;Z|84;`8knE zCqAs29sh;s$+`7np+#{WkCveCbuNB{&d0@f>e)~_FSO!?t=RZI@f89ingx=x-Ok2 zQUS21(0M6HRy!$qVtcCde%LJK2-NGjP*JN{w{E)Do2veDsR{ZOHLNxH;E+9e$Dcu3mdMB+Lkgz=-=MR=JwLPm2S1`ohq4 zF~u=EUF3{K99|*Z0-0bRO5(PXTS26|^?&)NdT=>jRV2^h(+d?LYNvC6>|7;^QE7fV z{S|s8At2?k=-uM@Lcywk%|3(kKpG&@iNeU2L5k`A^63<)%B`YsfhqbK7(X}!C$S>I z*fhv|c_X(=|Hq%tK7&M_8jKepDQstAm2#3kpFhKrS}!vo~lJQErLcEt%^- z6m}2E@88}an)l+#iA@yl&lgOT+TIbq0O0(ZgONtrhxQPsG3rT5&*A0*JcZs~AFvlO%7L*tEoi5UDTsC0MR?CjzE*c7{O#^5RnEB1ODHq`upM?@xD%R4O^ z7dQWtial8^fc-FkL)g^(L^-^21f7u+tp%gCGX};wrQ%FmT6k7+$$X`*IaS8&8;%i1ar$u#asYaaD|r9CQVIE z&84hdGH^*vQBf()7144{0Vx&C1yD#4LFT>Z_s{!0$MO7IM;#dS<-R}H=Q>Z)Xo`fX zsk42Dl16pbT34XDipDz;TGD@bB>8hwooA_cdcCJYZm8&K)Z$eB=L+L0JjpKvNDmZ7 z<{CmZE^2C7g{03R{XlX5;o_j_T&ew#?u3UCPJ0v!1($k@n-8EfEt!j9es`Gb@uQ-G z&~9g@>|ZSY*H7SnFGnV^5i&R9*!g~De)|^o%<2E_cO4v9$5C6;oUXKLETI>pNhQ+V z`gK(-QOs<$(TxF{Cvfxh?58@LwAiSgpcKaz?NEwZ9MPAjcLmT$*6~+nFB%&*^oGIl zO#SAhDW)-9&||TzsU9fjv3O{K6bc4r?vG4BnyYD3=J~e^wH|U9m5Ze>n<|1nWL2da zq7n2bQv?VvvxXh_xQwo#*V`=5!dsf1B~Ix;8+&cw z>>8ePd)!Ug!=XOoQguJH?z3NHrTL=wcps-Jwzftz`skZq+KW*of_|OvETS9Wgxj2% z7IQ{tU^Myeqxz8EBm||t?QFN|V|GfamQEKuE-~XAC*G`jMR8{PD>?#IlB%rklkMF$ zJ$n+KL zQ$I;PUW1?mDwvt(pSRWPJ&m4WG&>cskem3+U>eFe?tLD{HfE*nn4$?A1fy~6l&B1$W*g^+0*c8> zixU*On7x0}qcA&J%*H*L-B=@>F3%ZNlq?h(&w0~{Th%Z>U;c(H)p=XTM&Di{V*;&D zeiL>YPdk}MR;4KZLtEoa2yJ&|ikm_7n=C(RSN z6yKf1%a?hCnPlpTN^ZzvP9o3riXO%$8H)jX zyDb|BG;E0m#KL~@tP6+4Ui>h7^;hhzv~T(eoYEqsTXo+bdt-gHj|ad-xoGZ>uUohN z8g|8N0^TwpK#LFg}2bUaz$*NrQajlpyS?b z{qDba>fkIxpKv?`PT{cJ!_oJ*ECivO<2;k#j32fLw*US4GV zo1W0glzO3IdJ1lbSOVLX4TzbrZ!7sS50)YjH>u*raTQ~w0u{YkOc_m67C;bZljWL? z8Il)!jkF2z6?_OYYrR-w!nZITgF|vMLcgiQ<5)a-c zdicbq009Q<;)VJ`OPwO$?zEvXzd!|;`gNn!rVd(F^561H!`Mk_-e&Sf$ zjdqJr-A3<2S8bo^6OXzdacsI_JlQAP=3@|OQH0G#suu_m8W-B&a(P&%mhd1sV*Rj5 zdIVBe5Kp=kU!1-6)@|Vr#;-NrR8~x!FRiJ72gWWBIM;fQ!QfD+{~+V`y))m>?&-ol zr9GQX%mZj`V(*vHGe;Do7M=Y0p1gRvZr{fy=d6!H!VeQeH(+C1Togr4dVMEmaLPwWXt&gPPynW?fYZ$I z+RM>z0usk03a&c?WMhdK+`_br)!G86&!!iAQ%SDt6(5r-wRQ$v`)-x>05^-f2YOc{ z#v?7qH|wA6DvQkCaV6ZqgIgD5vz z^iVwdzbIGk@#9}4VluB{IG5!Qa0sylN0b9Jr5p(Qdnyy1*QNCg-o0YrVql=dTtCdZ z!XKp8V}-)NA(rnhVg%sk+yCb0!d#Ltg`->Ux2<|JJL+3c3bw{SWFsLi2%0hkCu{#( zKjsz?J1)kJ=SM$xk{F>9&(28Ia^rCy5@RE?exuzH<+pTy0zD`>@9$m`(tA%bI1b-& z{m+5(?i*QH=(PD@+WO~6x?>jmCX*o^v8CmzvVbp3E7_Nko+~DA#s=G?YcxSBS{Zy` zX5jEz?iunH2{ea}{p7TuS-yPXh0lXXtkvpM^9bqmxUSf74|7Yrqm-H{2^(}xW zt2zMp?!w7(SBNM%~Hax%GY1)wxL8c?lqEBo@Xi{9n!47TJGgj-%7;tbbeuDO%g1`ddDx zMJzbYed@O?>B-h(?%@Rgy#V(RGFE@9z2UpW8bbL$tFs)EZ?6cr+k`pKj|_aN&%-5W z;1Z0XVAv*WWk~=&?)4lCm&w70|dJTf;z~c zQ>xQ>B5G6MHFvX-Hk#M)vv_OmkN|+9)n~xJ-e;K!I0{%agN(VQFs)SJ!W`QDyuuU6 z2DdzoWL!2C-Sug`Ql=_rI`8sJt)!wm$_PxhK9OSq*4{cM@WoK+ISA3_*SR88^+QKw6eCqMktOi<1~={|&}8=lRaokCCL<__VGmo_)l{G| zRfgD{v*wPZ64|1LI@fUf!(0hPh?7@pK3MrVcn`>Ib%9Ov@he#e@knx)Eh;xCJ$Lz) z@lO@u=&>|D#e9o>MQkDsq`hzAr{F`(4*pP#e}jZ99Ch^#HL!3$?X7N;#nqR-sOLAl zij3M56#RGUE%a?te0xF72UDcxg0;dW^2MkO%n4vTX!9N`gN{}04%XmA)VF*jJ{aGV z-q%VmGc)Muf1U@MHWu5?(bLFK#(Hu(B@2m(ujFqCB=c)a@aJ`W@=DYd@{K(nd@G;t z{$5J~>A~3DCe^o36sX&v+U&6ct6_;Y`KQH@gE}SAC&!wqVBJ@8-&mj+gVWSy>{j!s zuKa7dI=@I~&Zo78{A&7X9^_DPanvDiHx_Ezo0dKrWW?AV<0=A!sE3U8s8a9{d4z?E zE3A0d4`nsaEs#3E{ZVidzyYq^thr&K_4p$c+9u=~L#*z-6(0IAgj69hK$SIjRqhxU&{nREAmdk8b^XZRp?vQh3uyG%tV3=oQeoi&O zmtQ>v7Ft!D9fNW8=h^L)*Xu2s6?NG|#ndSM&f<~?1uO4bTad$_hS>hoUvWB;XkIY2xw zSWF`9J6R8hrZ&_{rfze6#PbGMH(%&JEpA}8+epl(Gu^gKg{B$x;qjZ?axgFq%CzC% zf{Dx5Z&C$OLXW?D`YU#E7|&_g8`z{A6@3%5C>d|X1{p>>SRvQ{M+y@aDyjh%S|ojXYJHwf5?Z!uh?%4ZJBP!^q| zwjX#6S^oYX)cE`o$=z8YGF9l-f0CIoUBy76UEFCXv3Y}d7F}NX)u_D(NC1VokF3vA zWlUd*TzgU#Q#XI~LD(j5MAiYbs`2Db0G`naf}!-n!MgT3kPHg&{M(kK=U)HH>@xI6 z1KMzI`oLXT_}6}Do)q={=EsC(`sc~}+}lJ`pS;OKw((WWpC`7w; z=rX)%Ytrp^HE12O6%*N5Z(4S~KAyaMtV{FUw6&3k4V@xvL+{tMdN#Y0VB9PBQX$i6 zEkXe@*LA8cP`9)@H{k~p(oe#zuwMSonPs#WncNb^qF;q?bJdQRIex3yy;ydq@T(PNs*5KG;;9DyGS{wed*KH zALuZ8(0)&vTIN4QCw@Hj^DnKjP)qBsL-MQS{1>R)_mXP)ORU0-#lpBTR2K&#zV@N{ zE-`Q>e{6dkEM*q`H1ddrA_%4Lg}IZraXfss(2UpxVZQMqcaP|`x<6xQo$)zk>6xyQ zf&2>s^-a3gTO#sDfrxLB!K8{Pm9Oe`}(K~_+aCJ50_Sbo7V^9&e zQCCxb{uOxXwl7KNyz$r1U}=?4&_wurf&?8YiM#BhRTLw2DFg_Tt~(_euDv>=-gtt5 zbKzN4Bh`%vyvh+p!s?OH_;7gK`n?_ z?J2itoPk0`YEC3F3x0wg8VLW}F|fh-C)9glbFax8JH(n1qd{AezylYlq#4=29tFPX z4Lgyi7N_cJF837jJp&dgmXn8wCWvnt#6OxW_4k5w!9jbR;_v1|B8Ay@fA6%~u*u7i z%R82?VxYrK&~KTp(rFKCf{i=M%MN#{fkL((6hVvm`SER4rHk>^TYj0=yi>LzYieOs z16O#n|32LI1f`fYi=S_AHS>L;I#pokPf8{dcchnI!~9xty}r&}_0u~^Z33syT1SIq z_gA%^ftdj=+H7Wcdk%VEcg?7G8=u=}%{D3bYu-t^UuRn>2_`WMUF5X%wYr5k9D0nw zk6=FNyg>Yu#)SK1fY|U$wnYC_2Kx{k23Q(NJ~N9We~v1#K0D~u8p2U|Lc}6%N3u*V zN99gqpsZ&vuBG~s_3qU-US8Y8HQaRcsECO8aO79zpq8L9ab5Vv! zV-FN2-z(z>T%QqOkmlrvm~W#-Z5W4Bs3-AY84#{Yj~k*xXf3T|2HQ{t!2#rYuSQB;9RY#Mb{`L~vE-Y%{z>cJ9rxO?x)CW=F<3UT_*`Io zbCHboHtV9M$(YQ{J90wPX7&4X!jCe@81XS6C;Lfses320zX>pgyKMevV5C&8G{;Ef zs>^d5rbm{HlpxMR^E}a?E1QT~&qdqcl=h9kaquNFkU zlg?H#21uh3!*48{)#)7E47lJa&VBw|`&+b5MNtR;ssBbs=ay=hXryufXAV7GDCddW zdhg@UvW1;ccV9Yy1)>`1dlwyc_kHfEK0%e3kMnLusYP7%K5sZikhdRLdI{leMJmPY zcya2@ZI8=XrjBukE+sv?nAW&DoBYB->D6sFjXtw-q*EjNWqn-^Bh=fS1|T>%Js9l! zVU`}iXyo=wkDJVACzX4wf?&9LJs5^X-;?k&EGuwN4SPx;N?sc zZ_IlHAkQEgf0!sLuNJ6vM6hJ@tWbF^t+dz&G)WL$xHrI{wqcn<%ARW6YJIO9;W?0U zGu318DXbn7=qWmYyXIeyz+7JvCUxL+T zMfNs-**>jWPpR+;j>v8<3>pPG!`@iQ!TcE{1VYKKa}sb{Y#Oa zf1<@Ff$TUiZ*A~n6i3{~+m+OB7vwc0(Ik$IGq2|F!NBrRdJ;q6FgVq>`c2t<8qaV% zu@=|o?tT7WnL|oo9oY0uu)g2V<8`?M|H{~Z?P12TMJ9>~r-V;R#unMAiAG(<&)M1P zR;}>k?ZvnrJm^+M%KeCAX9f?R@Wb91gR7WH3YD8U`7U(T8r?NN>GopsAW=%{~C5uQ_nDq?ti*7adgH zO9Yow1h@pO*H1Z3=Fkf=`V4`D>Z4t^W-M||UuL|UsGhW#Fs@ZsKu)LfBYWoyN6mX! z%>|J)wZN&PS-B6qz((#OQ87z9`@ydO%yJAROGHdnjVX3BYKPq!#) zaM=FwT_N#g98bB#NGq4Ro0ctW(WS-Ivz7jsc{5ZZ);gTS)0)>rAZVU!`i{QeyG;i# zCQZ{jL%$FZU|Gri!SeG6(uw&qd-9E%8sX7UUphpy3wJjnvsGX}Ccw8>(2D(kYgO{J zD11?`7Jiy2QoBC>i@K=6*rE4CLl_LHJ!C%yiNejmaM@VjyZRs>zWnT9zJp&w-g)j+ zXM-j#`rB@mAoN$Y#PO-Otq(4 z9g`9x5ME34QY=rYaUcl(#B-vyyD7&hui0v<10W|x%Q2qwCu=mi<=>sd)3Ce~M}_Kl zHSi@7`j=}txB@O`UJ#`;Pdvn)Hd1hx4CWDUHARr#R60fCTX?XH8X}7(1O-&t-6=Yw zPZ1cXcGGy%H@|A!MVSXK&($7;XjF+W8FvXk^jJDNm9`W2B)QtsB<`sVFOT#p1{hMJ z__G+FTsVi>)p%olvG7Z9^t<*inutJo!>LN4z33UoP)1z(rv&)Op>C*_miTTH9<(j^ zAEjI9&FP1r?iIhG9P2uCUQ3JFzC>z6W#w3k0}iH=D8csx`qfkZ1Kf^mPP!r2}^$gWUw0VY|*c|(fYxnjIgbK+4i;?sWaLy;K&Q
    zKA=Ltz;2>c;A8 zjkC%>WgH9$HVW!2pVlUft}tD-aLDm=i|d8-I0t|s#Y|Z}Y&=*|$wr{^MlU4{kuWb# z+sRE@?~DZAju}T9urV=vMRuxB?#Lt=2Iklg2Z3i&G$DYSwpZ>gSN6~$_+&bl=NJVu^XsxD}wO-UDO+j4zpzDr*Do>H?YA^NoX(HYEHuuW3tk*QtC{+$! z1p&&7xp+wYhAX<_F-?I5Yv=mpqE-~Qj@|vM5gPTC+5|mA|B^ImwPNbw*v;A3DX)j| z9v}$txuyeq>kp5i{-W3`+&1OP^>y~owHI4q6yir*I#sIaG>(iHZbD)=LYaM(q=C0H?#ZTP6QLAv4=Bb+O} z=6<1JiI%PG$c&o}X_}o4y>dz(E|5Rd=Bx4FOwBdn^A?Xhxjtj1?Q;8Ysn0mj+ieaf zf*wOE&qhJMvRzMpsqF)V`YQ*0tFJg(J7qeVJ}?Fj%$i$*-;MuPN{G!rmgo_gX#@A` zW}vd2u02TzQh1lybbQ)m)<<_P^*$H0jasm`c+Pn__G?e+c;oPoqn8Scuulm&Nsg3* zaWtMW%$`!zvvS_9Vaiss<{Eo9)0@!uCGPb^@%KxKJ_kI?cm{ridPu_1l^xsLN|vSb zhK-XK{ARes<#Ec3ZRyJT?*b1;0jeYGrubZ%rF1pH;U!(6ASwU>*a<{NwSuu_NcDHW zx{G}zC`R+z#qA*~K#!`G!W1)&)WVWze9$gNRx5jc{mE+DT>$$_A-tcttO1qMhSuYA))jM}c3;+9N`J&%{{@;n=Ld)+*t^W8T)M0^L`wi`2 zTL&v!sjSyn!2N$^W-or}Vz&D3m8N)n&fibzd+}GuJSgrHSV%NB{S}AfZZf9W zIksZZ_hT~3MUxW5srD6>gF;-To$9tMbF8hH>@n*3YGn=x-*LS=R@^pYiojnE{q~W)e!$M> zyIAqWf0T&uqW3&5@aetWDy&FX2Ey|1bO|4n=)!K~UD z7KqjfKwf?x*M4v17K6W;k(LlXO=4dyu%`(mqaUQhL2m&~*8Mwh%>O+0|02ew|9ZD= z=TJBe_xaV}rr2Yw!QZ{slZE1Is(uLa{FrZ+Egri%1Cr!nT78o!JFwfgyWe^W|F2B4 zPl5WRl|NJzI2QKL3}bU?_!_u>_>ecp-s%`Antqv^N=bP{(Sv1 z(E1(*;nOO>yiW7{n`o5^C>EM8$VTSK2?%c2we0iZhgnq#X3zcfPtw{O7Gz0?H)dQU zcGb4B!Pcb$PvCC``GzV8(^a%pb$tc6nfH}~y=#Ff%|?@MQTx@+-(|S_&v36n+u+oT zdc?#8st~X41=;0twQ^uaV%Rl!jue=A*_WN)1n&{u`NbANP2b#}#T5V;$mXb+iOzH^ z_^}@*PbIAfk-D24#6|0?m#K@F{S}@8j4uzr-R=))u9!LX)=$Axj&b=~J$Wq%CIa2E z?(!{8Q(_YM*#cv>ibv?r{*{?nl&;DcPuoCy0MZjDf3F}M^qd0_mqMp*&q%jzPCnY~ z8hyDfHNHXQ$^D{kklt!Pv@JwJcd0|pth@au>HBR~)JOy07BizNxvdc-B=h?lqW1G= zuUs_~m_FI%TMD4i6y3g&r8@l$?GuIA#cJ>ZV2PX4-zsIygG70|`1M*@d&ou?$Rz)E zNo7&NRHm)cI4h`}3tu~Jf!O76dmR*tFm6<=Ry{xJZSn6-kV8w0(xc-;MSmVgEn)QH zD+na^M(j8>mi4i1q%827uPTQ@WT9@@nO4VX#wuIgu0QI&BUfAoY{wAf<{p*fJq7>D z{M06I1|?SZ`?LT#%UhNgwfG2!t5Fv-nX$`QA7O4pK$X76-!|_xY7wG>bqwf$ zmURS+`?p=+fKapPxSXKz!s9S&2z8VB+--T$*+F^!V6iCVnSVD>9Lc2l)7~QxOm5N* z%Wk8CSq{k4w376k$ws)(hmnfTEHtshz#k^I3o7w=p(tce`N+O2_zPZRJ7)JuK!(6m6Z=qpCw0DY2Go0 z|7P=7IaFjZ=EO6IDFCR?ONyzpoZktTo z4(zMCjI0<0@r$wb)?}IbU$tsPsHR*LlzvYl4t@5-k2}Ap=bz*r*&LjP-RZXgUxp?|7S0Ly!)ON#UQ*%KKhJF? zm{xWHy=>w*OLV;$Yxls3*jRMQJV2B|W)=I(MMytS-_@>Mu~*uSy}hBM@YCqf=*~pw ztyHNuDOuSvRlBbxwBm~v@%K%(_oArUR?UEkrkB69eLj|#F@s>n zaXFLLQ;Pepd25JH_CL2yxsxl304=&Ek)LPGJ}lIIrvY|Hau$1XQ1#S=Af6e6+c$D` zYy3yGI1K87sLf$3WRp+7=T_W!V7|?#uZA=Ec*5?QYHB^ z^eVe0eKkWre-53V9^&hVbxx?oXa0+A|gsPaX<+L4@z zs8ldls~};$nJp^M=48)N$516w%#tc3dBPMi&+36mk;_WpVeAw-7u*YuF%s6MUpeQR&v4M%F3NJoOe zu8#xTGrXBIJAxK&4eC$~R-y7aeGt}AK`7Pm+1E-iO_~BK!so%H0dM@&?RXmWfo|J* zXzH)d~FRp@o^ ztmS5HzVRmEWI68l6zpa@I%>J%zSNCd zggJ!1hDXxsJ>S?#HJCzGtW_ZS2p?QXaxVLCZak?YzO%j zT`m<}PT3{ENX`&tO#ai?{uJram5~QcLb@g2TNRIfW5d5JtLH2QT-# z*OA~#p2{zO7Q6gC*;8Am!@5zK4ev&pl$|SEur{U5en&SyWUO`z@LM?S^Za67hC*=s z)Q#`ly+>Z#?$<|ogN$jKWWA>&IoO_fSi!x4b)Vx@gsGuAf-)sv7W0}&9gUGh8*cx* zAk*P6Mv)Y7yg?r92tZkc}MEj&|B&5qvJN7h;IBOLfzyD}WLn<^~E zb*2~<<{vB1(_@g<& z=~)rvX9aCARMDLu26WdjhVc?uZ>w=?Wh7u+_iJIi0K>=BhgromP+q*&)#ep5)lX{k zM->Tpo$6Iy{UJ!c-6yx`i?&;=O#=i@e-DnO$@VsgDIL-jrpdPPccje$I1ttpY$vm=uQFa z&ohJ5KlJx#bR4k%2+g+>NGKnXEosb;EWi#n_mg5n z&9K?}`ITttcwG`2T!dhxAtiUj5h>MdGs2H((7fhj!ekedwrjOJ)m!=j$X=WgM-nN z;_e5$^MT6=MUg2#XnE+Las4`Nzk5djkpaLP2rUD`o?NE zu~C&i`0Qj0sBle-5-VA7naPjis)c0o)r=avNYrLK^rU&Qx zY%0{aD6dU;mM)))Qud5b0A&NO;)ve0H~Zmd4^wuL49hEu+23hua~b1r4%T$ZTP~Mj z;=!pGb>iNW1bkreUSt}T6oG{LuYU7OPT-54^w)5qmvwKGb^n#Q@%~ZXHhjTv-VNc^ zO+P&53vFBYSm|d(n^q)@!AvC343LP@kB8`WG^dx+$amEDy zOGz?ExrdQa;=|h^?rw{jzuFP`F6ox=>Y>Rd80x#+j>j9WM4$PK1D^0M@CSJTGJe%Y zzvk|&HM~dyQBrVxAI&ySNR@GnDpw!%rYPuG!ChKT&Z&hJj-c_wSboA#OtLKI*4kXA z{^^JfSJ)cDD5cy!JFlS*$)}l861WBqY=f9v!@vnsOUN}*td=_hM%xG)vPWtQ76gb$ zM)%Q;ovlXYnKsd2)_AV3@+srqz46C$rTb{?k5%gFvHU(V?%s#_!J(3tCkUcw4SBT! zpmV>?9o@*!lRaSSD^PQByUp88)!6)8eB!S-b_vn7(XAgLm|=g<#)L;OP2SKUykZ-F zsVq5sh$s0mDaz3n_qVyFoect68oFJ=JpLBjq-rspOUXZS z)c`WsG#ZU)GTF-Fo!NH-euqYJBt_J_C51>{#?u3ar|`Yfhx)%19dE#f6ibR9uk{+m zI;3{32Ed`WesrSK2PYc!vlR{eAS>vX+k4t>VzMI6x3~Qe#ue5I z%Q-V*n*!@)Gp_g7C{g-cp-U~kC#4nY$wG*1DatKjh0v5A((avy{r$zgd>-BG54%_y zMB7M4o==38ceW==ta@}LlsJJg*C*IYkRrF8W`$v6Wks8Zj58EMtfQp2h^#dWHlemW zAn~xZMj4MpG=cY6{?Jg1FmTk@0!xoOE51BrNG?Nkk8Vze7i*{3W8oo^mj6yuR~aA5 zy2@)c9TbpWwN;G5nyrOlg|6d=Y8`@xHT54Hn{2V(dN0$I>bPWFb@s0hbnyW;s)!we zo;0z5=j_);<#~GoNhl4y{J`QJFF)s!FS743*zbGD=t%f7a8^i2fvXasspI{k+l)S> z+U)9#;c#P9>{Ge?`6p)0Rh=+;TfkB73DqaKQr!vaNXV8+x`ZIm$el3(?P&MrW*BjR zIt++^;{m!KSkVKgK8wPQ*Pu4^@XCi?Tj~KG_kQKbTeWsa&L3ZyVQAV@xav+5Q@L`U zj{E?`Af8^78_3|RWBDtEqxa;sQV;Gan%agSe>xaYjG@{Dk#FVS?q3?@3$L^kb={Tw z<^9c{LX zM*Sab;GyIF3xK3T7H)S^uD^lOrDVu8)SXU8(Z$_iA1vTidQHx%**9zzWWBTY5btDF zYlWMZ%`eHXmhA=T-4JmPY5hmcyh{Zk2>+#uu>eTZl{w%3w3F+!36(n>iU7E4q*7>0 zl;Uju`%HCBnBARsmYrQc@~xjy_E-0QMkp#b8QuPVvFH8;{-pI9n&T?R>GnXhgxf`@ zvQYMG1pV7KSBt}Ds=@Q{_1_N2fhCf>t#swao3L+Rj+SeBJW>NpA1D}kV_ORMJ#e9Y zhh{(!HdrkmosB3NkOda{}_XQ;ccshj~+pbZQQ!S zYD%^nYvv_bX1|EZsp0OX$rc(M>I*GCBAgwb?3`&vaGGUN+0I0SOssP32nG51!z(um zqh1cXc*@#fw~==J$(mPPRJ^CnPF;#d*_<~+sJIX0uQuNsT`c7-AJYoh%+00ozI?BA zRNOAx$HNxIK^mO+x}P&?*{i6;nN#1zq34l)Dw?s$d;{cMWlmpDUC%e2@4~l`1H#;3 zT&v3;)j1-(X#tq%^0?#a+T7U7wmv%WKCYMBR`Hc5WSJJ1S2$J=KphvLCSQ=R_aK<@rmCSz@vl^cU&))EmS5jBqQV7#e00blI~i0 zLTWZLE~fu0)9UhT{QH#jRuH;g@fUv;-T7P6zvDmb=(%1oYsdQA?$G0coxL}Lr~L)i z!79I}lSsBCF_X7*Rl9H41eMc5?mSP~tcX8px48ugqNroe*H-PmhWdyHPDnqlsB8q; zl{+SeB+?}2xJ{^nZvTYTnsjkECS5$3iw^Yo(~oY&35k#SC>>5ozkB24oYZUZ207Zz z=38jTM-Qj++K2zjoRJ;G4%2Yo&qf2SIe^((Z~R%6{?R#m8Tn*Fgzelby<1;I6RF(t zlsb4=uk8alp5qsze5Y)C@A`J>aL6E_SM1?`ulO$|Z$jlg+nc*i{^P&jF?af~_W*#% zCNXs-zd>Es-Mc@M`PLu)l^I{~+3>nj{PB$S{r5$AxreUee$-bQB_29w%M)T?xchxY z+wQcjodyVr`brz;6Mb^H_584}D}ud3JQ;}B+AX$g5$bVCZ!+A1?$U%3=F+f5EkOb{ z_?F^)&&jIJ^95sh-LITo?Ha*SGRfw8e*b$dXY4HiOu!1y{}=^Z>^#yH`l%W{M_O*s zCg;5_b(lrlT$nNI6v#D|&t^sVfq?S8L($W{U3pp^T$S9-Nf{(4-*T=pF`&WxO9^xj zh)0=*l}C_w_NV^suK>svv9I8$XAp*T^~&$4&HUHd_6uZPvEfctz(7*va>}~M0K$7k zT$W1_m)%c7XiPBp^?JVi0rck5=0b*BFoen<_S-zUrGnIUYjZN?FWEDqXpu)5jadEP z$EskqicSFQ7dM#Co>L^6mn1%#@fBorD$O%d1bYDv%FvfvDV9#cpi^ePEY$b63heo- zy~^xs#9*APjE$=7ya0T<+wi7G5Z~K^GIEi;H5)s9+#zP}#?@as#El|Rxi+BJ7IMF1 zG+pW&5zN@TvL#@*m%<;0VlO95nnJ~lKqjRAmx~{)eAf3;E~C6@9wj#VdVd*%$h`it zKSN5vB^p*)enK@|dKO*n z$}e#U7UvzTV)?Yt)TBwz`IQ~|k{1EX*{23;egqxya1nb$v)y=_JG?ec3}Zg}O%Q{1 z8UDA)>+>%&FLm=riy5TNGEw73TF_sOlPy)NHqt|TNy`=^wTL9RR)zyXn##wp<*Q z(&9Pg>R`T|$8HfAZwE}u7GGbxxX|QHJ(>|FS#a#SgG1w| zJmV>(-Q)*RC5^+gHR;srl22f}Fb5ANgG`5kQ^FhGeFV)Ar{-Q#>|04pr(xB$OaI(3 zJ-Fm*E9F0hZzw-2Rw%w|%uU5?$7Oq3bN-U2E7CMb!GP=*lfs4N&tIkbC310+Z-Kt(YL&($z-6WPqB{5*3 z#pNsgH{>D9q1q}e{OY18Ehs8uCdA+ZuyrA!WSytAwyG$D+jZ7c@bmzw1$peQVn5Qj z*1(F+`TCK3n(=nItJZ@^t(}c0ko0PcSXYr?N!kD@)h3PqoRc-w%eAu#=m&3y1AjAg zWQ)?L%$`aGL(fq(50|w>`p0VPaAj9oG4$!=}Qwv!B{(6wvXd}hk{X9Q^ z&@0ANKPv*MZ_t!)jKc2?Z=JrUvwd#WH{nnHt{8Z{=Cp*vmw=1`>s#;Al#%mYwXwlZ zgk59mxhB||5KdMGggq5ua50ZjB4s_B(P5*GR0Zj|E8amtUlq6ezGLy?_`&l?)x5h5F!uU@md0PxQMHA`1nyRA z>~yYFleTy@`-3)8-hM?fsFH;0XMVvmvOfiPaMA*R%9xQh^;B%)`%G0OM~Tc3KInRlZEfG78EH)2NYr2{OrQ*>n2~h*D8luhtAt(gYb5A) zP-KfkGjHz=+Ied8tzUt!@#q|KU5M-!Um9L1^S*-c4RDh)na)CYr4Zsgv(wSzS!^-QbNChK%mJ@+Bv@#{c#=P=;A`Yt zIrn1PE@P&U$d&BTb4LseExfobA=S28cB?%1PGd%#+PAr+sYNy;jwAYDg3ZzPlcy}^=oR>D z$hbeFUlC;Gyc~*SR0V&`YfHIYB{!l8I~(DY*;n9++BBp`FS!aXWbLt9&^w+$*ECEa zhANkYIT$7_!1cNYdT5^Oqxa^@*8sxr^;E~91IN{`&Cw4BHGuQ*&iwISzGr+KR0@NO z6jqLB`1%)6L=Su;kUl=X)W6zjG4g*d3|aRR8jDYFKvc37Kk@Z1l|wU>4!PM4Fmq#L z!{c1dQ!A2T#;B*7h?|t|a*GkrvXvr#(j*qeVNhLpf9COGeMQ{?QtpastKx_0FS66z z)Lmv3|1kAAdT|+PPk*f05jENIr0hKOs!%!maQ^t8wH!JiEL)!4UNTZSHrRU=|Mmm} ziYU0dW&z!QnN;E+ZxdMTuSIH0_^KE=XZYkFu9~aQG)UZdGUg8))Y|RcRnvnt6WF3? zzykLiuSegc>h*F zoMH++Ep}%NUdfg%gnw^&BbE?_vCAe_PrbYnQtMRX7X>;j&Bi}=SegxA{!3w7haDe} zMEex6fbX~^e2*Cebcf~QI}z2AU3|en+^A_K9O`~J{C&}sH?5|3)}=#^&!nX0%>otc zgDQvKK4Pqkl0K(<`O!WPOOh3jI;h41U&0ha7dt^+hO zu@J7&A2$QHNrTyTtpSAo;a}(4B8CWH|Jgr6DnNX9F zk>R-obJ~CI1%WC1$Ezr{pfc_LQ~_i~_k@y&YNq)quq2~FLdcn#^0~3y>GH_<{=G|U zc~*X2n=E?E?mz6}hk`m>nsU|r;m&(|Xhi+G5IS%;wB8WwuwdEHwHa+;Ya&x0%Cg+!{Vtbn)J-ZC;*G|4si}VyvXq zbd?$?=S?4YY5DW4>uX|8(e(-R#@av-$#E@}e{tz?h4lpEUL#*)>P6)m21-xvx8kwS z?r4QJ7K9)lDLSgY^QMX$fE|ld7>PIdEAhq!pXcrq7=)Mg9^Oxa%EAmzmrdVw3-^z& zViNDleFKGKhI`<8d%Qfl>L;8?PThSN!?a9N($!u^k$CU=BnCx>{#s-tm$z z2Y)VII}mojLE%ypIgZ%Rcwh73n>g0BzosLUv|ruTo2laq$|^EzCoD$rm467G@>FxV zE62ad?6`84sxOHAT;Wu2g=+c#sCx5oDBJM=U-h&rPm8SageXGUWtmF05MoBQrm`s2m?G;~vP5Q#vCRlEjF=g-^u3?Y=lK1O@Aq$qgX6xh`?~Mz zJkR&*Rj5U7dwY|9XVwj$A`wZ7q_Uj>7cd70_`K*j)>p6S93!;fTA$y`V=imdqbrl- z*dKyVY@4`w%pe~Yyj&=l1cpX^GPKB|DuWK;HFpID#^4LS-MT6z$!?~MwiZt?g8oEJ zC_H1~r;$8^bl$$cp+@KCc#@jcbrS~t8a@DGnA~_t^6#)=ANO&jt4ReX1C%}$GCK_y zVw9db^{_~3^D z5C-hS3Q0>7NIQurQcAw??gm7tGigz`U-Q4Lj1foQvaGTJJ+!St&u)gZ%5QjGY_n54 zj-NH^86w~^s4bE}Voz7X|Es#%%w?OZFH=FAM-S&cAIskjlA`1i$Sr(CW`@pTpt@b< zdaK@4@*`8`ng>}lxNq*XsqSyh8%A;`BuVK_S70~x-2Kqidtu|jtsCY6xfgPPu+iSSXm=9 zLYg>^PS#mUFn03+g=jihTQpRnXgk}%&qLx0Qc7sc4eNB{I2;S{O*82+?%dFUJE!$6 z>wI)PpMywuTpF1nL@hR+uck=7dtkNHnHo&Wm;uJZbtIEmrT3|BUMVS*Fxb#5u#L{j zaL|pv2jktIjKO%sPo(b>RMGRH<=i;|Vm`1n`8u-s`@9}>qjrGQxk%HO+R-QJFKufT0|$W6 z;%jaNuU-V0{`>TZzY{}pIM)$B=O=YH@Yr@9*zAY71ef$3C>K>!w`2woub!|7c$)F6 zL3?A#zkY))QTQ&f%`?NS3mBV&fQKhJgwLOsf+j2E%o2+&Ldm&-aJL3O7%=xGDRq6P zGSwtwTQwge4q|%`ICvkB+v-sVt5i*zi`}9#NCTdbnaZU5&%)Lq`b$aYhjURjRjb`% z$iPteb=Z)D`Yp)nmB}yfI_T=9L)Z}VOsdd>^z$?oEk*1A+l!4=%$R!;rXO6cdHjQ4 z=oe3RJur0ZU-$XT1NFFC!9s7f;@TOYq(mVlzx&(RTHQY!dduo!?5lF)ko9)A=9BSf zgcbJ*2<6tG756H;>doboC2MlQnJ=N)pZuse=b(!_6%93$z&q`eM}o@Ho+xXly?E0! z!uUKu@36)CMRs5oX|TY8Cg|3=>37S^%g8meL9IF<8XlS!_M=hhicjY{8z0ZA>~2|m zDqh8Tf(qtK@A|#umDwnKmKH`&W&aPFq52>A!6(p0ZW!RwYEsUdmgXIS1RI|D*{sbs zWl8VxEdB^sycuT+@ox{EZ(XkgDxt>JJ}#{~Z=Zny&{Q2xQF2feb;@(jjS5 zNE5ctC>}s6ae8uQ2~7Ofs?|)k$rqV2>a7NJgC)Yc6{8ecnTn^|$tMp#5D}ydyj}Pu zzbIa=1k{ml)v9jUH5OvfF+xE_WPpgbUwHLMkrpwu_UhKd)2PV@!XpFtA6PG7wDRmn z?2xqEm--IbGk*jgvXXh4vg2*-gjBqyT%5Rm)H*(5&3YU3%JVyPp{&E_5NczR#3O$% z-x?<0mEO(0De~F+>_chRHXKhsw$gU`WvG&w8`G)tKULV29>>}kJ9juv2b$5xuL4wN z`hI@|jzE&9J9>}1A$jUfBkSDcny*4b5YVkz$&{HgAC>$tOncQ z?$pq#3J>);e9qBk#=HaV?VrSEX;J@kmW1R1rTZ@4>i@{*R%b2qfchwF$1&9hF7Lvv zz-tj-nmGx(VH|j?sk&P0pGi27x}8q%@L!4fGdwDkZflupq%~7RZsRuE93H*bL@TLC z`~h(ij@Q;`gHusE0r|FPqMOwKO$YZ-ZX=hXLT8q*q%ZRiw5Aex+!tzqMZ{VSzhTx(@2bB45#VVB=uck;ht8L2unByg;1hWFi9>zw7f=SLe6 z4gps!dzs9{q8l&mlaL4$#uLkkHzl+{bM^oSw-e{%a2h`F?SSA5Q2Vx>eX_cA_#1#V z>y$%ks-fi4_=*DhO%M)6DT)Y$n@2br)e0HYK(g4$+%Wi_p$7nNcy>;wlSedpSvO2A z(vtXuU$V!&EWFIAH2yje=oACjhVd0WS~p@z(80|hu-}T;p2^*O$zjsPzN%JbHqUJ8`fp2k( ziWNMt@XYyI4ZRpJxD$xE5!epHNWbO2CB5slo9icbn6*WGdG*@ZjmX-LxDampaKKRH z7r)Ta84bJZ*g=%n1NQR9R7*xFOi1?XA%RiXWiLGqnkZ|{sbttA9tD`S_J+2w?6`9wD{*5zI9z$qi$=A8VBTD zXhrJd1!E!c3^Jo>Objhter1XYuNpLjQIrsX>CLw-3kq~GIsy~-z8%b#JtHsX$cK^A zZ|9+}Su$+h$P!KT1y_pd(su}B#qFt&v~MXHm{4KW`aW*@>3Gk_73jnM2-w;A_qe*E z@jz(?`VH6;U26p1D0Y7HF5SbkcLzuiD+B9t=<8TY@GSnh zQ)Gghi(V9EL+d;DfOup=<#BT?0gPzLPg@~U|}af4c*jVsJP!G_W1Vn ze{@G%y!>3;E34*g4`37z0vi~sS;xoimU9$~OW4P0VW6(|iJlpr&cBC9 zgW^}CgJiH|2nD;Tso5cX|4ObfzO`GT(5>4BAvDt^Q=Uy@W8ogNKz}2^t_l`wt&SR* z-_|}El?;jzu>6!8@{r`1jfH#fHW?PjJsmrB{6Ld2FwqxPyh+RD0C0^^cl!|6L4te_ z_oj|a-uUr|kl8}LsC59YQ?^$tT9W>`-0z=O@KK4PQl|6ZjNz+1dwST}Z*AAiI=na_ zg`eLYtP>%Ys)N;lQU1R*U1RE>0zZk9U^RV0k5}tyei9=&Gf{zTe@a+(9D1=!rs{Zd zLw!|Qw=M!lLlqbHRGA+KDnS_ZE5EaduTqLH8Bq;>zq1WpNp}DoMz<#FU)PRoqRylU zY$UOq7M2(OsHF^{+A(q!%p(E9%0nY1LZTnQ`Pt$y22iX7Mwcqak>+La;}SK4FxZzr z0w&96Kc_s>+IFv5r_8!mrfsyBF{a)1as#o9Y-7=DmGsJ9K%(*bz*^4G5T0ZBB zg@(Bp8Zv$XxCEy;Q$gAF)1n0s=mIzmsq^z@S%+U(h6V)U!8GNeT)^~9KVfJqsbdpm zSe$1wb<1D~zXaU}`P>YH>zhVB`bcUkI+(HGhG=#^qFDX47@%0;bE(uB>QqbtFUE@HI=F;}i;7+$|3S z_TIi)@m>Pwwk2L)ub*gfSynQ**0{s_H_JWac7_FdewLIuA-MCUwim&Y|0B>tNS?q3}*2X~ePr5{e< zi!N)DUUzXWJNgHWR*#e~8w&H9^bar8O1iL|ttP8BG@X5xFcG08XTm%|>0b^v!w*7P zEgZ{G?YReaZl!B{*-v8|wcnjo8?~p||J0o*ICMRtKxtch_p-;q{2#CDr5b;Og;Onh3t7u7m)dL@_1hrsK+QqQ?HF#b9#REx)wC(mj zet4Virz|vXaM-1OOW~Ej<`L(0rQrR;wN&2RqSC-tLZCs@B&a(%K1bxs$Y1^CtazJv z>#^@4n6Ip-33bF4gYcZMyeua@^mD$beX4`QnE$l)a-{DCV|!3%=y}uMwGw{>UVMh$ zL~#D0yazj~l!8qoxumOReWFY0J=V;+9NMlSvq3Z6B=g!j`Z!7>6uD>;tx1W&__;nF zlDm2o2LG$@iD0bVx9x7|7V;}hd!CkfvFH88_6B)z(+um2Pom8A{Fb0BS(P__+Mn~C zOj3%sH485Yzn2hm(t!QyqVX9VnA0Yn6u(%~!m&V&W}t=i4I-INu9#mT>!-DTz*P#2 zPHo@+orrSrdcT(EiP&oPwmXczX)#%(pt9r!!w+p{PoYBEd7ql-n@z5FdW*wZ4S{})+g*czzh zWSa--$~|(BYJ2XC-!y5l1cH^4|6FhXs-0=Bv`Na2+t(}&FWlIJsCDw!N6Kxh$QIHr zGrBP;9z@{K5RS|I;qD-^6|s0IaWlCy&^KpjZ2E`uy!br-DMW$#S1`5dx$B2fcBW-Q zofdVby0LUF!hwL^gsk70?cFunI+$DZA?MZGxB4xN?i_>>gSxfiK4q1k?KZ(-6bSib(vV{9V#mq}80zup%K*01oT zoV{Zt{*m!{=fs=Y!LcnsI!aCdk+v#XRuGs$`%9{F7UygC{-{p-;3LI))9+|OzP`7# zSex2jPc)iW4Z{r}t!KmFI>fmdMKU^utCcT$P7~4C%t+%2{ z>PddoKG0k$N}zdD+-E$hPP6tBmc)V$&It=9s0pkO2hB_k0ILJp4L!y0L}Q#oq4sSZ zuF_5|NyDq1K=mqPj8D@mZWa_iAtrjkF=Scat$209x4XjH-b;MEqjXI&CB1b9hffu8Dg3V&1ji8uTmX&1QHs zjf#xe5vFbHP3OCmubLx*C88!tGTiF#5(X^&fCr`v$;9zaY~kM$oeh3Du%t@gQBvc* zx)^TnKV@FhDvRlhy0tdV?^c?A4dCAUHwk0m%rCY5g~SJYLc-`THXkx(y$wgSH2BR_n5AV#1c11!<|0fv-@aOj&SU8 zW!#lFjX+hZVW9jmeErIeb2zJ9Wp zdi!qCix#FxCp2+Zm^E}_nJb&qUGQPow`vHX=2BFd_m3P}L@>aqKxJz;Z7w(d{zk2= zxyn0i`m&7va~%c22q~rQT>g<9$N~M=!LVA|+Y7IK1Y6ht?BNgsmT>KLVYPl!y4$XTl&) z%oY2wVJ0E60s%Owj`Z)6%3=m`UhDGdBU93cS$n-b84T-^84|@vh@5dW)qR94_RnU} z@Cnle#2KI26K|w#TjQiNgHSBlhsdsot?tN?KLUR(v%)I42Y4wo+@$+`krswD#5WrU3;?RH0L$obJL+TLjU(O|@ioYHdD?e(|}C30k>o@`h!NGhKJO z#lA+p@p0Y#;E~Gu%im$H#lOR)iQ}KK1^-}1(O8XX)i#Q(SDviLV{NIMU02Ts6ojt1 z4pmKd{4+YaG3%Ln?h%G0)W0&o>_!EkMhiFZu=s*prM4}pv|1M^#iv}7?svsQ{^9UG z**v)I@L^DOxCr+&fY-oo9XFoT*RD1j3ZAFMJ#Eb~^-(E8{&@acfp)8T54IRLRw8vw ze}depDL4IFyE~aA@&$S{@}_)B*&1Y*$;pg-@Fdmp^ez6+`Ies0pGt)Y()N6H-Y6TT z_-#^j%8MH%fim^KI=8&ZRhpx-F2@$0Yv2U?W=z>xAYcgP^gO%unN`7nRCD@2Dqr^{ zaEm$$N6~X{9|(Wfc$Z`41XQ%xcQ~@igRs8y497sxGtZNIKiWU}ZGW~RSb=CC=p%hI zQl0m)?c&yp`A1`#1igO87uxhg+?4j`is8>^0_YE7g5juM$uV?!3Q~4+tzY2jlGF~6 zc;#3{o|wWvq9ja;$0k=ifRT0y&R=J16RBdN(wTz?>O>6!5*$|WUnt3hEsI^`SQ|97 z!wS=rDPKki5KZns@`_;c^e=c{&kepx^uNPRC*(d_{q#9Tmh+4BXRXX9zi74UrZrSL z{UClUZ=PZ92kH6zcr83^p^+!})F8B0^cDZuo6XkAZY=AC@@To2wY>ed*3Pjms@fSW zNg~NO^8V-=uv$h)r!CAkRH}cw8qn_N7RvVwX!jAXwSP!SmfUZdt@EX}QQrz!g7qw* zzIG%Llc1%YGVA!+mM%Vr=^nqT8wT#MjK+!{ptOT64MZI+0;4{f)@?wKb*OqvpKEl6 z8Cl_DSBa|^Q?%;MvB--@Z<#$xaPZk3!8qYFX{Cb>)Q4QDLpOi=F^=ydw$8P1H26Oz z!)16ydN3nfao27<@x0r;5zJlF0XY|UDYO$0S>NWorn4O4nV1{cP_s_jpLB=WSG9H4 z-gU~(%pPH4C6o0%66@&+5E^@2JILy`v(9Yo!B>9j4}lhJ5-rXn^|FNRnvvkn`gViiW4hp#)RBQ-8*&gWWrQxPh64L#UXSJ3(kS(7XOfL#ZN zNgWXK$jvYGyB)--)B1%WARx7Z?fBmRfRrnNNU zah$@4qzErz+nH>C)7@gZ(A&su(e;`4Qwq=NV^vlf@iaMAMu}qwEHNqiLfx?Mk;rD| z;2CB-qoRJD({|GM?xd&L^sKpD@&P((D^yIEo;P9oxPTg=`##qE5D#$F&6I#z)dItV zOQH&#WBSl-&&3J_@z?sr4%b|k%QAx3oi$GK*Y2ZeSu0$?EqrXwQem=fMFbND>@w!O zB)xI5O5S(Mfj&0PxH`&95P!>YPJNy!e8}k!^y}JwbPyzcSOt5O?bIR}0X*Iz?xS>vRf8({pif7PNEKInH1 zVzBm#vo5(7kyS|aQ$Zit?<4l2%;hn)m!%R9zV{!9nTOf zxE`I8{42l>ku_RB??B^p^W7L&jAdMMAa;7*wZ|h}d!1N=!=BUC_1OLB?M{}hY`8K& zQPR$;#6M4&(kXGZQh6_LTSz6SP#GkJ=LO`;o;G#0xy<6nq-><>0fAJ-JEzH^k1H89 zjz9wBhQQnott2~j*c+T5veoWPC7$&Hf*KQApVZCj;6EypcUcD%bjA8hoGWTNZS961 zF;OOumlf#9ZhOnslP^}yOUN=B1MAoz?kX!UX1v8u0Mh=%gU0+k?;Dc(hT*b%0yq?;#K{ zl|akBSkX&U;;trC3~m7&Bgu3+M5UNxF!fHKOh_DTCeFAoiANvyHNnebhk0)PbtAfq zIz`5}Qx^x4rjNqPWniupE%NLlV0K4HSe>zwz~(o0P}Bnf6B!CZkJG#?ZUF`RUFWRfRy2nz$sCKmAcL?7d6-$u}t((x_`^cO5QO6<;4(;F=ILt zIWPmd60|dX89NC)`K%lWIa^Cb%%O-kKKmgBVwHBjqOFOHSCte@nN5L0*ZIP5Uk)wOjIYoCs z)AP0G%$=Y5cBh}YwDu`tYqE-bsX0~C!*e|aA!&{67%@>zZF?qOZ%XHwPi5Po!~ z_i)}~T(Vyk%9o3q+F%rhZuMF&Jd?u??cmdu8ZB2*C^_)SaBA4__3;`xp9?8zG&9B! zc6l`<>4ZZPlMo%$THMf}K)|3|@mJ}PlD8H0v25X2#kB*v`ax5Z&qTjfH%$g%-8{em zq$^rrZmYjs+!&I0=j&@ALDaM!EFC(Rq}a~fOTP_EXoe8Kv~qi+%}Y8z5hF>C6cCc? zaRq&4A$>nxJre&d^zm@ z;MbEx2Eimo?Uq9(>q9ihG1TEeO=4JKChxtSL5KGq{}@n$1)xGd3}t~}hS`oXEj?z-zitg_}YDsKly;v$s2BcmZYs>F!GXNH%ge=j)$T`A%5PzBm1Jg#yZ z&}0JF^jr&+=)b`_ypXmX;Atw|y?tyAB@KM#cb_UQZ2iB|Adb)&Z{V*QLwVY_zvT`( zo?Y+6ve#Td>o<_x{aZ$Ee3$?3POA%d2-Adv0XL`+wDqvfrloi96!7wo?5rs595y@& z8QBE=ujsUN((VM*;MI77|CCydKp~v6pkogP0tF3BARh)ok zpa1{Y?5n6C;8_2GChFA|0n28(ujs@TwDy)3eb+YxHXg7Iv$b42ZA=~o5K0S0>Gzdj zB<9bm&wJ-{l{(jb5!sBT+Sy{n1_QODUVs^?wW~Huw{Kc7q%*z2yk(BFkG3#CwK`#d z)RqqOEz%S8uK+%ovk2ST7z=8Q3sA83EJ9=k{1H&TUGPjZ^Kc=~%HvAQaU4tu&c2Dr z$T>spce>d8S12d~K&TgGA268)RIC=(0BHLIr%Lfg;(H>nwC-s{{dCFy!Rg5xgS%F9 z?FD*ZiG}T4jcK_7E`C$dJ+VN9MzTb7;P4zpVDFm|S}2>k*7uoP%|E*ng}ceAw$Ala zWtQz1>+o2nl5Hv@DSIb$ljxZ&r|iKy_-_7p0o5&ZM6ezryd}5a})p zCOB!;s+yUL03s_Amw`6j2?4!fVs&yZ{Bnoqc0LJ=j!pSAl05GV=d~*qx14ED3R*B; zaQ=zhm*(4AxUkHq&DlAze`Zza8jqxRj=#V&P+GBm{jKEvd-5Sp#mDSyBuv14YqldW z&B-Ktcrry>I@_5BJXp>jBeId7N0cNyWOOr+;eYboRDo>FnsCLsq(i|Y?+xMIgVI;i zfNC|w@Y}_-K*PyJmL-f2)KsRo!PNeOJtZ$z=G zMn%8;((y((r*a$CTSt4Jh#Kg-rC50t{xjfLI5>OPMQCA$GHXLAqdk*Nv@raF4WZNh z$t>}ka(;~#5(?1yOVhiLj7;QQ{C$K`h&GAeaGzAG<#QJd0l?Y-+^|{SMxdgau|8Ar z5pX*J)<%ug8wC$ou{7(B3W|C}3>?*{j#|DDqRnx9fGWz+%JC+h!11UjoA-A9J+i;2 z`bCNocC+EEry;p4=k%AXuB9e=X88KvdBVLb$pKQ7b}S1B1?(Ld(##5r5aUPTI<`!> ztu_Zim(~LTV@t=zyuwoW_uL~8uR$Lgdg`*!YAx@weggtN{H>{*uK*>`oT54~(y3)m z^UfTS(fS^(H%@NJ|Rt+1!9LQRhSY*+EkDvK7lVNb0$q z+YneWE%*eB>Qinw7h?$Y0o_dil9h9UoijC=piJfBK?82ULb|svF(db>1x;bgaQ@t#7XD+sZ{{roxwJAn0Fc^)&ijb>-o*!m4ki_{`ZKAiYzw! z4L}LN21%gu#Dkorlid0@vjf@6VlRZ=`x zxehPeqX@mWQ4r>fZ5)@VjVf$%>lAW+}u1nOtxD3WUR}S)SY4@2_ycv$`Iw2 zPPGJSPG9&q*(}CkGicZRV z;$soe`$#rBN4|%x#jV0&Yofl;a(-pn)~4d*p>36nCJ@;-xa+uXwnZ2T--g568mS3U zk~INwG%~AgZ)5rFlC5ytkfdLWVel}SP?xzSX{#|H>mzP3#I;;?4cY+WGZ_ssJ@uy2 zL(C??UdhrvTP53^7T(nBNq#kek_@;NenxrJyn_&|5e6Gm7%Z!YLra8oD*vAD7A$Oz zN@iw5ZY55A%X^$1noLt~3@~rx(UK!B?%6=)QrL+?Gtkzm^Ugr0H_z5M7^}s9 ztXDSEot__3&zDUeF7~q-za%&=!=-3RBNueL%{9j`Q+pWG6WBJdLbsmF@C(kar98I| z&?_(N;Kj3_uR!F*qG7U@DLiAA67Je zJ6J(=(jtmbA38Afzsq>k9USXvT3rsT|Iea1%TrTY7-1=cyT4Kzl2V%(YD#`rtEzBf zAz3qux~n2cSstZ23I`L*4h#VpS!A5<-qYGx^jzcA>7V$9o(vrL!M1ZuNTY{q2;xzn zp4snVzv2^H#p0u_Eev?|=8LI&y!c4b2ix%bC*8ibcBv(NM&{H${Q;OW1<^qizS z@y_$!^7U?Rt?fFDdcD}PgEV4XuQQY>`hhi(3xNU2g|fU1XxA6eBk0TOtqA_nkp;3` zdwU~tJpi6;(EK#!B`P3w~t$*sPt(FVwHZ5AIT0TSMXCLJ;o9QuGotNpBbULNW&G_OGn=o9;ffvaoqB)sHhF*YT%sq!d8w9N(sz}huYmCTtKJ?Ba{t*t^ zz^90uvKDNBl19SzS6XUs+<3Gcb|Ctjm%*z?uBF^_PJKRwqWW^5X2Rk!4pAOc9pmo) zLb^@lB|wtzyb&{axP*Fv8f07nH85XhyEPMu#zpeK;Gdr#IAr(j)r`R(0jI4$0xTuD z5C`dcsdBZ7-XOu#5^UJEg$oj79z_!?yO83qr06VV3RH2%T74m1a>s9oHX-Q@ z3hgptmOJ=ER5E!CF9({dp?Ht~5%BYKHJ@j^&l#INk^vYBI^~Gw0!s(o*+G+dm)SF3 z$GUMm=P2OOiFmO+;>!iF4lhQ{{VGsnIR@pi_K082-$_gMp62JD_bufacxB>ef4X{e zN`Fp$IUfM;IL<-^XMeDWKOPb$LG_Wlb|LeLtN=TvxrShkOG2pWPG=a8%q9!hB8$)OW> zEc$XL>+ANu%%kOdt&_-YG2XThqpEC|lqNpudx7Si93YRXxj*H2v*f{=kJ?_PvT?NE zkko~qtFk#JPft42qc*}$3H8Y*2T6` z33IibWaqEqiDSfGKQE;lXb+;)*3niVdkPZe#>FjrO9q|l1q`N`r@f-g) zU!yQ6E^s+NITtjS5H22C*(;^gfP+;_Hbtb|@1-dsOPjW)0B$*{p#PjjtB*W>M)OZ5@#y6w-1^R zst3Se{Mo{$q24%6f{$}&t6eVT7pa6I_{1dlLiB+bLn@Q-uN(61e*EL-w^DwCUbP}# zHUdpn`sq6!VUWfC2%U#(`S{R*;Q`&B)$0%Pf$mBdOA#f^A8bM>ZZvNlKfVi|#uy2F zZaTD1y0!o4Lc@zEACb5pKC=*DFClWkt((@rY8PR5hp0_$*m0+e!EO>-e97gOf3SRm z92W5909~{e;wp?qMlB|WGlsjbNJ$7ax?YQ_ptsHKYzq;_b2t|KV;5@iz_ho!w79=n zjvnD61~$}U->>hJ=T#<={1JsfeMUD_qQ;=Ya^sr1H4ATllAD zyu(jKzCnK6FCUHU35I`s&lF~Ig_Y*D;}dCxRs8{eKIM8hI-;_3h~8N+)4v3xho6{A zVSZ8e|CZjb9pg5sF9s`ic3O4JaE_NhmMLX@Vv5z!bJ!3A%y+Ll0+)ok3Bhb4AZa(o zfS2!1wc*T+Ghu+FM(Sa7Y)5bZeO0JtW-1B&=40#o3Uxb)&|-4%@SPsw(Zul2N3gsk8IP{O3;eq>-+Y0J!Z0M_ra}N zZiCM~4X)f__`bcVkH8lGMTdXYsMyT8IwOOOHKuvDv3I%sZ1;G2Q3Sk> zqs`UX!hTI=nU#$GBH43prkDDaS`9|;+f5blXDAV;%%iQ6BtpO66a6Mrdb!tbJb{M4 zpnr2Keo>_Bk3gc6Lk!n$A*&f3I=Ng^Sf7Yyb^(_DQ@&WwN7~Z)}7NKDXXgjSh zZ@`Lf=Z_gRnTx{pwIju;Uq=I)u$o;143$RzNzSa6M~IGR*Sg$ZQaIQfjig-#ieT3e z?YJLL!bZlb`eq#yO$PuowSUP*7ob5t=k4wZL8L=zu=i8cwN%|{AxBAglSi-NqN+uflX)o1m)q6stA?)$);ID)qz=$eQ9ru1& zJ|A8(+xsv$)!4eN$}VFU&MM9!AIMmAw+#^Qqo@H+)Mi+B@_F51MIGpIb)#(PmW6PLrely}~)4_QZAQm5Zu^LX9`AMJ@4-8?dj6 ziDd>Z0+FPpq|miHbq!Ya-i~}*{s4ETz%(3@Ni(ezb_rm7$nDqyI(UHxz}+1^eyGYoP4xp>eaRA*)QX!=OUKRW(s!P>51!GrOYbz&ACglODzfiY>Qhj z&fumv(Ff9j+~5NH3b4JKd9t&Vo~AwTABm)u9dS%-OVEaK%C}W|Iun}iY~_uS%o1gQ zn3tyw{`xCY^Abb1@9bK&^3&ZkSeMe!4%=e;g@pb>{)sBT8EZNNi-@(iyN^dtu3SScJ!E zt+Pnk4(}AV*eUmjkiG?ZfDtJjx+DcGDYH`#0HX2`)|XqTw!YH86kyXc>bw$Aw++@M zG3BZ3FXw}j@1)thbZ(G?ZC{UpaB?lAQR>faSI-4-ft@WlzGjD0yivxEn9K>@FF$e4 zA|zEQs#b>AjmWK69U!k(CFR&X0vAV-99v9m3QK~V7*;1L-lx&-ioi$Z$T^kNz_Bk77+hPSn>&?w&+a zE=%P2=f9-XbKFO(6MN}kEc-pmV;U=2;Lz?0zFHxN0~j|T{5VbbaNf4<%p-7)!yBaA z1{DWQ$zE_W_nX#coUM-`4hBYNB)Ct*lG$O$C_!2CLNp z+vlSgb&2PW@ZDk6H~{**KCWA?#Y+-4;SgS;X@REU>5iV*WWAIu6&mD3+$m}sR%(k;GhAraTu0ZCY&R~Q=GA>S`dZ)yG-Rs)8hkD=22j&esfmMGnoYBvmpoJg zM*N?TrT4^*IrA#y5p5(RB`xXHfT@}Q@LZF#u}_f|(4+;zZs?~^BAAuLH09c1yAU9I zcY^5$DJsu|T@JYlt#{7JV2ZO2Bv>Rgk<6)p4 zEyE)NH1o^B{t=)7ql)S895!rJnd6)`M*J22EHVEP<3|l`KHd=MJ`O=jLhsHr&uL?w_98m#6@gx*Po1L?3_35osRc235%7F5*1 zK@qf)syBc6Z%nMnvomQN{Q9vEH30*VQ<*f^cr21&nUW69q-*mHth^ApS193WsVyWd zjnl|B-_1YVAWY7%nzhh0QN@`h4a(FVGfb|c~6`0pa)37w}9Hv2`bf9suZhb%^@2oNov@9%mCE*8OF%x+*4%alU)9wH1vEeF@(h~;&a0j@A);NK^6ZM1NHsL9gaZB-7w`$n%~jLU>& zSLqOcgkZfb1PqDTY7d6_3b;ikcQ(LED$MLuy25?@^v3TQ=uDQE)xKD(xaW0dwMHER?+UAJ&e)YX|}J#RdEcH0=`@ zr)(U8d#F&00`P)Fw(LZh{#|sN1DTT7_~H_Jfg*JD;zX`9{Gb6iWSgsD@T{s2oXf(K zOVA?KmJ}r~B!NFqBy`aX9QG#jTK65NmREcUDd$jrO~f6CD+6RYxq$RE>G0P*zp_o1 zb+^!iy)GnBtk5_B(kdS`xE;Chgp`5gBx(z4cfIdZW-(UA9H6Nm^GdF7c zahnDeM`t;tpY>x!)<>A>Yw;ZDUFkXM?w0@$to_tcg1vZXS2HnJ8m^;ytL9oL?FP z&gVvCZaXDg$C{UXA+AVosg7VNlQ|CZ_x=xE@BPr!_HKLQc5mHQEEE+4H=rn0ia}~@ zG?8wCNQqLVB%uhQM@1}15fG3r(z}!-K!6BHO9)6WAw;^A1V|7FDZXoe&w0;1_lNrz z%&e8UW_iXl#;5ueJFvXFUkCxL`XG7^=|DEo5~#fT!#RER)b$2`8-`*8)w2vwx{sVm z3Vpie8GXGs^{$3oDH=1+=qf@yK`gNBqrLnWKEpN^RyazA4x|z~g{UJ*@dCP|@q9UPIMg^?qGFbYNvLXHA z@*iUFsofIGV3lgyi3^K->3nZ73@HhiKgAswz9v4lFpN> zoMD#1k=>gXD|Sz}TOqOe0MJ&BW*>KX9|@6YRG#fwwSx+dCOn^y5L%=h|M7-M?wXz? z@16?_hFIcJoK41D6=dELS$0;ehbEt=Of~w34_C{+v1jpD5CjOoWNHCa*f8w&yl=GK z>NloeU=2tQj^B>oNyQjnO681<(=jc~N^2DM+^6)v6-PdVWjhPD6rOLH5O;c}T#o+v z^LFri7E9szSWeY710cpI&HeeTLj%;5A_l(QDQ8<5+vIg79WgmBYIHGBvY}s|$GH2}n9{mF@a^xfRs;uf?y5&eqbYk~?V0ygC>8A*6JvYF0MXexWBr`-DiNvao{^TtKb%otK8pLLc3Y4?j215(I*E*C$)JD-}IDe;kav) z*>mh1@Z)CE0=FzGs+HUK4(mgWf+`dMV&gI;{`a8UTEq z@IV%WG?^Re{k|C9M`GfL=dbUauQqSYSfeip!*aj@SU6Wu*wVY#v)!{4M@8e=33sB- zKB%3q>+3=A?W(Ah*WAOHFd%y2uTPCNueVWHyLtdOwbxu)bl+eK7C5hKpcP_6$#(XJ zirKmE@Zt6Jgg*HN*sh$$SK6tF@8CmEDW-?p=B(z#jv4RJz)Y z684)dIs_P|09M;1Dc&MLHGb^8==Bi1=WSKz?mh77;;d712t#6}1w%Fa3_&zzLau09 zf8RCdAKE#*o3~A`9r-6T7RRE(xV!M0M=f`^E@<4_(l(m^kE1XXmtnYznNbFlUHD|y zjz*7oQks3eE}zjSXomT>X3FHHg?Y_LPKLHOW*2;#w)0qC{Kl$Ti#stOo~lR1FTukb zIOvE@5OCbmXj@fr7B`-S|C1gnA2m*Uavb!rfXW3weW4}Xf35l69oiNVxuEAiCK2k9G82Zm20_Fm9XAags+^pJFFpMt*?(VL(>bq8#;Q?d= z?Y}s8BAiWevacP5UT7TM2%M`DX7;z!&PIICsg`SrbT62)e-OMBkVP*~{kswz@alrI zN1wIFD(>v^!-r$7>#;QKQfwVz_wLgY@29`s1Pkda6Ya@k5EalovYIPgZ=(PBe$>Hv6R9VQmGzaCsm;|e*6 z>DpE*`~wexYwXlqEcH&jRkrx55Bw~4%H5;;$JmO-TK|R!_&MR&)8^w7Cv(4G;$#Eb zgA*klBwh{Hy}pcX0S-|w;(>Xv&ese|F+Ufi*MSIFje<76>(gdr@GQa_zD}M}*!Nw@ z^UAPU8GhhpNnLWIr1P@gh1b^A#uwdQc?fBhl|U_m_N4{&v#Q8~yK;t|;noj$1$E8R zH^(qfoCgQ5)jy~@jQiOCl2~M5A?BfZJ!$aEQ=rlo~EV?3p{xw&qoo>PZs&~xpZDkc=zekS_&gL)2M?eV6l)G<={$3bn6x}NJ z>lK#w0X~!H71-clH9I2OJI;B2)VTj(Y`rY*k2=DS6564#+ne$~yhA|mil$&a7w1ov zcChHy{TGg_L`lcbJlq|dL8NkSb7eQUdS^Elb1FTyYwjZSI`@LySTZvW0V_sx*;#VA zJ#soYBZ$b&bGX&$1RVvNzJ0o> zVo^Cog*Sb(|K1pJFEy6n+5ab7qqeKkjxydVnX$BtpKEhHQEzcmZz(Zwv01(YCKw?d z<^ueUKD&u%k%<)>z7k>d9&`a7(Jw{mlJP6K@@$Hy`BRPTF0S=5Psz2xzR$!N=z@H4 zW%4F+0|t$AxAqM$>#e*FqZ$gixJVqL?!G6%o|pA_DAnL;nLpR)V|BN z9=}F2ICMHJ4R9gRM9^&+yvi!|&J_ z^Q;7B1CUu&!fxOi9Udc5H#d3NB&J8{z$BBA(j^MY+}5{sSYNKpA9U zHB{PBRYchCWo&_H=Q_o2%;Y7 zW4CCgYWJYjU-ooe8wpI8G3PK>wK2^$Ot!F{upVqe=$*@)U!tu#ej}a#7Q2vlTU<`m zOR3W-FUQkdnVxu+%JSvv6%E@+)_FOb-S?#lqTOLfxEC=Eu%jN(b6zwVO9zt!kix%F zu92s^&x7T-Uw22OS0y*@FL=FGgeQcVxW%m%9I(3Kue6T85aS*v|EmuKo?t|CxEeg9iDU~w2XY$ zt6S;R@;{vU%!L;CIQk~pCF~*Zt)6<2*h~wi%(F%6$ri; zOOmMKj)+elS_-0*3Xex@vvkHLUa@nA#r+O0I0kTFL2iM(>@a)mp%#&$jHh=i$+CA2 zJ?{Z3j|Do`el{Ve<~A@}?y za40wzl*d6C57%+LUOrEvW2+9|d!(fL_nZ%HNRL;>h!^qjBhRo?&OBT`dW?H>BIBWY;LIOkSCA$RkuKL)-;Z^gtU9!LF%BPd4H za`lGbb%aBdTU84c6`7u;t1JVbt4EIiK*vUS@`=C&YduCspYzm%e`%BpE`3nYnWxL8 z2LO#64byQzbMlQ+*De7+-}-01u;N(6r6!kn?@$0b)ne!Swcp802l9Z~sj}wvx^T3d ziKb|ORpZ{_edM|pbR0!VdJg4>$4aKv7apd6Ra``zJ+s&X)cIfNc##UYk2bU8pW=@A z2W;D6U`fc-lL_X;E^VCfnXdDjutKX_V@G7}m9eUby@XJtW`Cs@OL~sB=C!$h+jy5P z8N)pU=anGU`U6heb?zJyM>xXdd@~dGIdbX!mJc7TbaYxE$O%>=$^GBW-<=zI^=@PR zVateZ-WMYoyH`-=1nM8zO#z$5G481<{l-lV`r8W6l(&i6O9KR zUEg0trd<0T=Ey5*QRNR#pEdt`eAmrEsq2Bu3%-2N^eR1O-f#Yu+}FKFbJ2U~?UTHi zMP6!zVAJGFpv~zJs2(`q4#QpBDjIG$8MQ0jl+!q!6oZo}Eb#R4z}G6-5tlk7aUXJk zSN$T&{^Oz>>zc`#q|orG;KPwmmUMixePN}05-+y*#8rC4@0M_?uGo29zUOyyJt3OA z%&P|jF2b`xlY*nWG&sy!fH zNB)p#*mVBNKa*-a#K0KVHZ{I@AcYCWzRlZbzpn?G6mwjA>=U|Gv#!|$P!ns-QfB~X z&$1uIGhGhTLMgL8TxXp8(tS4vSff`_6&J5_E=sg^4}IVLEx1ydH+lZ1n2dd z){sv9*g_-J#|iv8kfD<1oHAqM5=h7UD~%#&91Z^jlDrd*U0)5%C*$(weB|+r$i%F6Qr?RSsw{;>=f@@n$I{Ct&<93#hf zn}kkIb_ok31lLS$>28{)3n$+B=2=QKCl=~tGnGj%Dmwk1G`iF}Ffy>%ktuw=WtTinuWqy!`K59vIq}{d0O}?r znfCnPVt@UoLmGzesuUb!$g>ilcNWgL8Y>NR^uD@L6`KBO`RZ# zw-3WPc)~(9H8S_S<~4+yY2RSWFZ1M&+?CegR_V;eG-fFy-cKHGa0kAC^79i6sgDdv zARopImd9eSQByYZiK+%R&8knhB;gEnAFcfxfG`u->67dAbgpLy=4mY?*NQ1I1ON+R zDefrYabTk4w3=E?4TBP&Y_Kq=xqMF_zUoJO9^tT%3?Vdvn1a?1D{$uV&S51IdTzw< z;hwWUgUdM%7t^n$7yt@oAn(`LdCtMPk;hzm)TY+rIFz9>a{sfxNu+b4Kr;+sQf0kje!qD;hn=y}e$ey=lu1-s7%YAmb z6lj%UB=)wOVd^qjtNx~PkXW%$2Aa7v6x*N48jG&JHa4lat;`tNtPdZxTGEN6312Yl zrFkPY{E?lbGb1Lf9trBo6)~Q~EoXQxPPObHCFjFY$%jt3q`FT0L~;f|G>LBnX6{yz z!YiX;HM9slCYS%?mm_=me)QYFrhFa?1%LUB9i8|ms^w<9eL!g-2)j)eH_G@P7PE#A z?p$05T^hxf)5GxhUl~p@h=4~B-oSp-x^DVP=#W(BO2$~qq;tTu&%XXJ$e+UZ*Bc>w8AqLegYn?;zTkqk;I?NMbZ zF=B33u@s;&0#nNG$^env{21PBYv*D1;D_KXUn@wbZCiC)B4Uyj9AZ>z7hin6?467k zXutBbGUmaSWu1#g*dE00mAT5L2^8@^1d!Q6%D5x40s#3*&g;NZa)&-v+x*loyUOd!LN zsB74K^L$kr^QG%+ABVEHdh5NxI+3}c{FDb&%T@1||%Vft-DfSw7_x3?O{xE{sX zTR(wNck0h9!>)SZjE}zcBjKI71m#{zkibdW zrIxIXquwoIxJ0*9R04cKN^+H9Vyd?&Rg&ty=|W^A6sQvx(ly_8f2cjVG~ z<3d@h?$aa5QyS>6H~{cv@dE5l6GETk#l$c;P0?Edw15^SZqw!n$Lb1LK<7UC^_n3N zG%0*dPb6IVz;6M-;<^8~0IUSP?5idC=dtWVgAuNj?K5a#bSUQYKuzyUyfTReQQjW| zq`X{2$&I)E7Wh0`H_vXYBAIDR=so8Dvf)~BCj^iBh@!|Wx0Gv~F64A!nP4iax57$; zNJA}{X{D>(`(TC$v=CQ*p!9&K{TRE&LLbU= zKqH%*cc6vTVdCS>x(;$IvT_7;EO!WV-SHW`83)-Hd4Q0qX4nJ7U7i8BXJg773u(b; z(^sah+e!Zx$UVHGb24SaEe`0Y{L~Iy8JJ`*FpjC$ezNHB0MJ7nP1r-ctt>s8y2vhz z;uRC-pYIljf5#dkIk2mhoA*Hrl}EO-tbYp}<;{K~y}%k)asK1wR5}Kb*Z2qjo4ghv z@fSNxG@tSB-vY?`G)x6dK|MOR#SJ;jKi9o+@1BlmUKk0t29#<6$k&@ZIXpW0e?_>~ zn1nvv7q{T{@XPlcwabLiyYKe;@>;atH-N6X3v#`Y__K zXFE*L!`o9Gp&_aO{W&vc12!53% z?qu+|@tG8bxfqLYkhcQX^`Zr~Cx{(lv0r9C^2oge6ezHgiub%h=(v{vpo>lAqq=QP z5R%kF97moRKT{G`%Mx)I5l@IhfPZKgd$vBVXII}Nen75YGis0o#{V8sS8<6>M8EoM z^+mYPHkhxRo*@lSh$GXcOD@4u_hB*mveb6aNa?;i8G&?m;E-)o2hi8g9qw%FiJvW) zda$&c{_HeSfznT`%XSpw(58!`CdZM@w|)TC^c%+>@R75C4K-B~OfBF`0^)O4-M&+} z>AzZ->E381ATstd5c+Tu_SZmu~%ZC&K%G@oJ3Fd+)>3a)H-@wRN<|+7!G*C+tj^^iwmVwx0{7q zU`_q6pK}}Cq zup$hy#Ix<-(9Q)aRg|@C*&eWDR9(5O#qG`A>qa=kd8^*Hw4JtDwiTCbW9F3Yp{EpXE{V3HF7 zuZZGiL<>}ii`B!|a@xpzsdvSLn!+amARQH0wQiGD+1Q#h6Uh;*%E9uY^KWL0X$q;L zhYOAEc)RUYW76pY4M$I2V-~{`HK>yv8vE9Q%5okV!ELwcK+p>{Py=RZ3$5JV$=I&~ z2=3+6^?Ky)3LtAn7ypcgUYv@tBsgBKKMA`vmf;dRvc0qjTSzSK)p<>I`HhDwET41zKQK>H+Psy@Q(QK)!vQT z3l2m&%jpKiuyV9)jLfXnmSeC{s%x%Xn;3|COfNCILM9Y<009XH@?e7x;SwC>qvG`W zBE6w+e+zVZD&BRE=lR2r@D?a|y_igE+lO;+C=vY`p51!LQmpEgv$ihX`W!+VMeID9 zx-|Ig6wNfz4VgS2i*9}kcC0T^fX@xhO-RtoDXCrv%9ahCZe()D22shU4!<=Z$51d?yPx z^-*m6FaM<2t?c(TMFq`wjye+5lu7I=&sR)iWq26I&GjCR^j7rO;xj3{{~{b-%H{SJ zf?)TulM4y}XYA*?3gi-;olHf+>8;l3?X{Rhq~>c9>j1!a2=y5W?6=Gw(J2Uji{liW z4G&(vA%gKz{a!RdAsaZ5F_Cnx)@-e}ZMs`bWv44Uuo@7#T1@ThQ+wmCy$8y=4tYSw zf)s8Ydyqr;R<;P|*XNt7$rNwxi4_S@Q1_+=Yu>`$jYmROmB|rHRD|J0$XAuHutFZK4 zyF%yJ00ko1jncYu7l+V>*j@q%XA+CB8Sf%V%MQzr_sA7$MmC5J$p9R%SajTmmxzU8 z-@XD)J#Uk-zw}Exp+W$F`fVmUzkO^ZkqHV}K8 z$c`p_EXmp45xga+V|BT%bfX7j=j=yr2t;&MUN5`bW&#yesF9no3wu2BY;`CBaw#os zxcr^8_Mh+u$1HH1+zE}fXyL8R^a=&H2uvMSykd0@TTz-t5mr{F|)y>&w z<-Huyh~EMk{z`pCxsPv%x?mjcUc*s7PP|%RX_RNNq3c$LMTI#${5|+s7)L7df{lrIW2B;hR)_>vP_~dM6qTLKse?3e)sQ?N$646a|JAi4g@Xw zRCxENqa3s*rs|6H{nt;%mu0Ev%@%YyhwEt?S>iFo8f6j&tMRGGp2EIbUUo!P3*j)1 z=GW($)F(VnfLxpgKogHvzJ^MC@PDFYEpN3!&Ti%>Tx-U6SJtqr{ zVU(^NNSst@$V$5d(|Qg4+Arg$GFhki_|>#z2GJ(qSf^#i*oDpe82K|>yxOZ%IVgWa z%*X7Ixa*}>-|b6hjz%I=cWn7?Q?yXsAid#IBJSkp&eC-j%KTCIbz$4Wlw}JUxGJHy zst$bcS4jo3i4?#b3yY)4l^r9;Z$FHC>?i*=T&#QAsj&_KP&J`L#U<0im&bhADR4wJ zo7ku4_ARqWC$d`_*K8zxf>Q3JgFrq-Xll|;0gr|1t<{||o^w^$FXB!~Qutv@qax%? zmS$6v9V6|d8i$hwSq5Zt_lj0HXc; zo>gy|RQHQn#Wg&ZL0N?V@OfghqN>~Ky{*bH)`QqMP<*rif=GU%dLzawSS$o|&_m0A zXf)6DXhNB>2%QiDOJXpC#jS!9$%u?JAZWv3BNk}ls%ySXyCG-$^U~Qg!&J;hq?NyH9y$eQcZ?nDk3GjlEA+GO)6Xw9p&^8^x2I2a`-R~N}>t%M-udJ;+~*a_ryy#eH%-HCw6rH*HVjI z?66n3STDKZ{N1v;P|56l#2ulZbeH&EC%%(B0$$N*|(%v6^QptpX>|58aj(=rb;`6yT&&fuBkg%PqOoJ0z#B0C)^( z4DPpi>$%44C)VC@Oh$6R@dllokk6V%&XjN;vXm;ffj_5$h)A0)YOD{|FvSNhDiBwh z+^#2@=a=D+V{_f(3=9%X=upbov#ZpVzuh?JhogHIYS4mv&0j;d`#eC`PK`~9XbKrh z{F<^0{IQzQX%Kv%ba@*z=`DBCrq@jji`4+|GR?YSq_^0bno9#adGwg1bfZZK=1~vp z0EhG%s<;;1ciC+AgSUp&3(dSVYJ>|r^{K0^Nobr}G|5y4)|RyH_GIU7vkWCC^@ZjE zOv}hZdF(lcp%op21xowhH+L;4-V+akJ^0MEpStyARU`PKSCF%jLxOWSQN)zQ6lCB+ zl3h63vLAu!j4&aRMmSqohlijFe?i4i#c2QT#m`N#h3Pt#>(@}F`5Cy=D}tIGcaq6h zQUd-=T5IuACK5pmSjM6rfJyu7t6g_kk1!rLeai2;1Uo+#YSIO`8DdZYvGqUPG5Wq& z6LNt2<2I1a|49%sr}?>~@L>}1Rfn{pt0^T7OGl>iQsy*EYc5k3Ql{v!aho40IUhOh zLI&mE*-{1%c8;yl7nOA~Q3nd*G}6bsO&j=3I=pvcE-%#TtXen8ZO{mBvkOV}51R@& zziDsyZT%D|s_co)p=)iE7}6oDgKnzNuI^X1@*f|weoAXf*ani=r>WH&2M(I4*^hk_ zbC!G?c9p!O4u)%M#B7{MBC;~aKx!Eiq0M89@z@Q9`o-*72L|B7P%M3 z_4V8R)zwiUo(!v5u_czsyR3el-&}<(?q=m1Rg%3*)Kuw5y{UFGdsSyU0>7p z@Ikx@eda0QW0zMcyzgeHD!ZQ)^Q%v@sADtI^cH#m6O<}_Skb=n;Qk9c>4{A~9oTD1ge&pLjpxfb_XgHhfx|TbVnF|Ry^RB&<9lNfUr3p6;eTv1 z-mEb;`O%1!y$a-n&T}(Rm9GDE+QAM}Ws|FH&|b|OBT0o*egX`^urU}GJZ-G*o$)}5 zVL`cdyuopvMb>*VpV;4{51jkY0%A(U<_}i7ZWek8Kw5K86DB8HwXAEuLX*p{3f<)Y9t@4Chw-CE&>ID4W@Ki=ZfoI> zauqLuKYU({q#0-d1=0~?z01qk>W_I2_q5h5+D7Icaxw z^VmJyl~j!HPKK|hBg)rGxr3}Dqc3VbRZiwmq~&5_Klzj45zJZem6MP$RXXdaH@?Mk z%}j18^<+DOWmK);gCjQwR-O=0wP|^h{6F&oxETNMiJ<}RAWNAUv_LDgrL_eydb`cr!*|Uw_D|&9Ni-V0k51c1=uCl>N3$&cj#6GSMT8iAY%z2R}o_ zJz7d$N;3RE16^_BD*YB%bO4T-hedx2T-Gc@N2fa^#6oHJ_Of$~EYMnH`> zoRfau0(>OtQMWm{ehC@!GtX_R(D>|J0_1!`Bwg{ZOi=X?%+TDI}8q zzec*gIHe4fI9GCZEePzJB=V-eS;PD8?<*M@*Qrl>n>G$s-SybT6j3^={~6|6*DFsr zyg2&EXS%TQim=E`egJbG3Rb%UnY`|3c(!ll+;X0)U#u_d7-iU~^n}ZnCSWeMEP}De z_(0k8&x`+=>cIE=pQ$dFBm8vt?E#8KciXxMqvCl__fJ1hv8s0>f!`4)V0vrvXBBOY z|D2zXpX~}+g^%!8F6k_YwZJJROarl&WBz&<(rv3M;R8@0DhrbDESX{^(5>S>nEHR- zA()Oh15_Qu&AFFh+)uYR&CMH<3s0^*Z-M8o^+s!i<;hn1nqhbG9-d72J1YqPd|ka#&(Q|)I#aaSKKo&EJkBUrO3 z#k9QQ5}+Yal?*MYo0g^;3@Vm8P!izK3D&pY*0KD*)}*88?=AneBs~ImiXF*{T-z(` zxY$su*nhL%el|_AqeAb1*gqqpUQ2(BbWduZ2w%-joXMp~cj6&9U^=BTI3=s;>C<=W zqw=(qAvWum1MI`PbeSRluTlJpW+RfsPbrW8`kVClNJUxM39(>6u|&6xRD)LTh2$pO z|3vd##rytp++B9i&1|Ei%C6dqE?Q8MaoJIJEpo<{`{i{GVa}RSX|mv_?*FfM79T(B zm~}-vcZ9_f=cQ%3f1+m&$8O#>ej)te(};$e(i)`!_8~-qU0FtVGy!cnkfR(nc|RgY z0I4cNy|!I2k<<*6RJ)vDv-|c}KQnLQfA%H8|7!-!744=vnJA}5W2H^*i(o0h)e-&Uo_6@wIx#O9$iQ^E64ZjMtOqvNS!6Z;>PI+XzSMXlpMy`YY!Ax(3xZY8vOH*|IAgZV84h_{@EM#LtHD+HorTy*$*s%_J}>$ zDS7Z34>aBX&2q}oPRJm~H1T?CH>Wp9c4Dt@;#2I(qYM^#?o$x2xz|jdRP_tW}m)HG&z`xtkmGK0P1X|bigO{&yR8X+JtvrR+SpA84Ja8nBaUX8(tN$0BS+-hl^fZ zGprAO7fY#s$N~!`g1umeH;43_*7@J7tj6^o=@~$&jyAI+0B}!2Sg{^4pbXyn$I=@4 z-*S!b|Hw7^E-bAIaSW3RPgwmWJQ^f?D@fV^PB~)>NEe?+ zi|E|=>I&umWqcd+(81W#sgB_sbKn5~%<*!+r3?CF<-c7nyCU*0ctxH4&-CQh`7aFt zHR1{6{;q9DYajc6q?)JGN2kJ0=R5CuKmIK+;Pr5H6}O1o6@;bKa8J$eDjW4vIY%Y; z6ulmvag}xb>KU!D_NS@IZ+P8J@UEQNH#gkPVT-r6=)WwBl55jam_dtV7;PI20{yQas zua;0Gp2s_8GMJj@yT0RjBOxPjt-^rqS^x-XpN3@GEv|SU{a04Hc63ME=FGx4i+NA@&<=syvb_^Wc8X*D$Y#vGHOUN5 z-U30UzP}U0)$WzmO_6euGNF1bkygy%LQv@aTX; z#SWTUY?~IhUxO%TEA*64H^g~j!O_po4MwczB$vc=6FTr-Xe~dWQfr$GiEu4NiLBwX z#Qc#w`6sU@+|@R7?`0qR$e3VC;^~7ePcc!-72Cv?M?he#7T-C2PkI(JysdYvKFO&E zV>SX6D_crV*DfHbNh_0ChC3}UZE91vvhO}JZf;+nOGv+RX|ll~1E-`HYoRTzI_HT; zhhC-u?L^Qg<7@5^;0N5Unu9pkYZ(17WXW#i9pD`cDM~zLc#7^9jsGaG7FMx)(s;hJ z#@S0%qZc26<~OV41<18HE^$bs;3`Ks+g!a{OrrwrnNbsi7ghBU^cqm9qD^mPckxN=GfO|Wn0Ql@FWI3VGB^0jA~H$bin z{3EuFm*C-A+Qu6d9+0w?oU0 zv&?X`W1Y_bN-orC8*scZYG1#TG_!wFqZSb4!^rhK&j8B?C=gzelk7ucU$be7GZy{` zH{bc7Jj`&!xRJw14vFw2k^^N-aM;IBGyhLNjrDWNY>%Dl`oi`8IFIsd7%kojN8T|) zWT6yq^FCE~&I7g45-}7KviGX>b0@oECnx&xKTJ$;UVi9&^OgG)|+FSjHbrrtDT&v4nBC>@33D4@OO#Xr({k9CbLoX+NiCKRxL^r6yQgiq&(NwhR3Qq-M$} z2FPAj7$}6e0r(eEo{H>D(@-$UvZTG2Z#W>d*pm7y_%s zt9~4@lsv|3XFvUPfcN>qQk)7aICf|IEhM5D0JKU`BlvAJ)lv{`pn19HpVuCV=lgO3 zvQY4TAJRRyREt;}Zc^n2o&w?Es{e@%5}`>#F5wmjv9T-r@ps)|FGVQgpp! zi_;3)g8g7)dAb=GNJ~o=;v*2`0TM-}IC~%GfAD+mbe%j(kB-AfxcwHe#SLfg7WT9l zabH3ma+HSQ6vBFGLSDixBE-s+5YXZPr1E%#S^+>jm8o7bS344@*?Ybh&czwc{A-uv z5W>%+w;vXNf2Wy@tBWZYTXLjXJ`7~3$CAQFIVC(uX~e5r^p+n4PQ)W zD`^N*nSfdLtti*?!=NI6F@6W0MUXyU0o=_z)7e(j9VSW>!YyvDl-8Z|rAGpSHNpT< z;n=uOJA348T;du218NwSL!2r@zq(RQ>4N)wQ*Fdi-5kj5D(~Ux$4q;J3IZbq_%9|* z4H0d_AnQfgETx)YrgG!&!9!_~v{WRqtnOaL+RgdHaUv4#U_5MFwF0meUfgEq-AceN zu+y?o2!NG$E(EjCl$gcI-Fhsy=X@~pe)r&cqx@Psu~!X8%eaaScQtgie4&rAcEwia z44~V)a$(OUu+aQ8%yz*6cZE`|=P>^3AjYKdVLrG~QXw|0m6=0|ft-D}fEh-#1_Bx> zN^noY_kNnyX$;K2CyQb`k|FzjGkT!8#Z+$~KWMyY3hH{Se&KR0T&Qa}}Fy zCFT`Y&!2tOGK#F45ADjj;~W6#x<7E@3NWLAi8qV|0sTyo=8iZyBniw)ff zDtPUD?+qn66};vb>f#&yhd#VS{fbnry;e2(BsL zGERw3c*DCqIf_eo8Jj;z3lQ^C>A!U@ZBaKGJ37_R0}{-Ax2|uMXq^>q>=I`DLE;k` z#~bz}JbRN2)%&WBFHC_-jcbd${;4ljeSj_SNdz+{d}yi+=vI%TuQgdLg8n%$L2SVd zdWzoVRFtsy-RS2GXizJPtx3UOrrnE^Yf5NhUU8p#7oV2ux4BgoUx;aLYciw2#0XJ@ z^`tJL)FYykf!GnKbp!U}jzqIfeCIQT2NT$$BQql-dhvL@uJpp*AyD_?TVV?Ll4ax8 zKT-A=f8oKf@=aA?2NEGLXhl;p_DEs-QSX6>O^37yk3Tb?sl5-LEqHF_k%d$2H}<29rhAG*Wpxgm80VI$ z&e-^U+;Q2F`+Iq?_{h-`zaBaHmNn!Q1{H%}*yf>H~H$JMvaMW=hDUlHw%jd+Z)O?3uEWLo;D zbAPVqQbhMU;gpDNIyFcq1`6rGPdgZj$DWc}XmL|X={o>a5``9m(u7KD)xyZlsJuY& zID;z&x$+3Hho%j#ZtSrOzD%6XIi>xhqnekl5;;1Aw6l5RWZZM&re%0$*M%w0&Shwz zrR-St=L}>eJj!g8hF@GotZ60Q+$mE$OcqR&4u(qsxh9YrvyiGkp2>Adbv^x_8cybo zPE{lgzuGSB@s*-FY20Ujo@zHdv#_m-e0+I z9g|G(n-EV}wo&>351P-itR|5)_)LM)U0tf*3|;c&OW|w(C3xhIUdweW`NyHRtO3Y}3!IKj=nN`R$d8+` z@1&%Cs44y8o71Q&c5nmukuC}1#}*>s1b@cnK>g<*E=K(U2nLaZT6aUHMOco-g^XaR z;zrN6i%2^z$6NA$uyQ=pLA<#`BThg}SK3`fmu`K@Vl29LyXSD4#sN4DJiY#5n+_4W z_r@8cQuCRcsEUMTkf`;nv6wl`wa2H_@X9GdIq5)%v(9mwn1PF%=`&ViVeQSv+xe~^zO682$+aj%WaRx^ zrt|&GOQTRKMl}P=&+;gGlsqBTrbr*L+>uwI4U8>p>-;LFPr&EGqf41^Do(yWA<>7r zO!nkkrKPw+`O>jXOf#Fz*)0511-$Ddfyy4sah@*J*H?NeuSRYj1p)1dN)ozR;az7t zjFGa$LDd>yCsbO`$$sX7%5`(~c%ejp2H-J3+kY-Ks|s@zBwT7#YXRU!1f$PCVfq6~ z9IJ37SP{|Gyt>dmB?k%-G+0ls3PxaSjYN=&yEZGC|B*U4Wu5gYnr?2$4{~rzDJJT4 zLSMLNQJUhg-x)iS4R6)Sl-uxi2G6lnY||E*sb-zDExhjr0}|zx9_+>K7DPFA>a=Bh zhsG_sohS}<>kpj4Q7l-x-cb8G`@Hhr4(zvp0mjUJUnUPQC=f%(=9(;{}p=zs#x3} zxUklek0Prwg@(@p9hoU;xmw^j1rFjYzWWTn@M_AA!ZwkrTsmCNHUKi;d&J$|y2zEN zsr9ZEd1!A-c{uZ*PvTNzQC7t=KV(o)39a4Ha7^6gaf z=5*GvcJeu$7>XTOy0jZ0FLf_nu=w7&+0wmTQ~lJT6J$lZd<^QAVO~aB* z+^}z(YMQCcX)!Z3r!*@`&0TY=F}KQG!4!?keF0JvG*N0Mtz1*X4a>?Mw_H(CD9a5* z%Uu!41zdsD6cJ>ed;ZV+et5omcpTioy>Ok^dH&AjPJ7n@ce#g05s`xmIl%qX*jVLF z!~LZbm0WLyvu+rz9yJLp{WoM#j#U1*1tP;jzs{Bd>H~%fGq_TCIDvs6uH!`E5_e59P6JTUX>%(VgX|sFC_=|=;b;0{j>%JMCb1f zs-jQ(Oiu|3wV>|G{f#WV-@G&44)FbbGT(Ug`C-;6?_#zm2y{LziXDG>_{8{B$H0YS zy6h2+u19=~lqDK)ds(?FI9yeU>Q_*1C5db2rG6m~>y0`b>~#@f{ax00Q>~$Y%NUoE zheEi5r>>EVV9^5&z;+ua2E!+p8?w;naI;3mHj&@PNnGFcOC)z-57F~|J$Cz}@=r~QyHZ;M z>q1&4ax5Y>M55!l<0hLzo zY=roEjfq=%2L*-1+rzEZ8z$OoJVtxcPlWJi;lv0z+!Vg{VX_wpFXgwkt=nzBKxAoA zUjqw1wW;uY&zYA8(`7WLpTyLv#|gvU%xwd!bm~Yn!kuWb3Y51PDVAVdv8X`ja}alh z@DOj(#mEzgtumx$x;*jn%ES8%W9yGXn_IfMgQW#ci-tA+FLKBzc%E&m6k*@$ZrF8< zcIpcGK-~+8yX?NT>KtGdZ}=QahgZmji)m{~8+XEUw{50VC-h|wxYN#c5Bv$Qd`;Ev z(&um}yB65Bb(aI60)G(&%`UNd19a|O3~m5hY6;3tdbQ>w+hCWYos>V@bx~Vg$eXkL zb?3hpY7OKf&QxbZ0nUx=-h&|qGZuV;XG_u!2gcjs1)kJa-W3}p-`a*pW9w;G{^+c1 zu3Oh!!X(g$fX0VOa(6WVNIWlMmtEw-ZQaSf4uE#M?6_M#7EZ#slQ$I1`E(NeAlY9> zr&7IS`>)h#&luKBS(=lwz%7|&xEej6^X5OO(|m5Uimo@WL;(1}4~-3B^M+noa(+#F z4sm#;5%nyg8#Xc8j{PEMMVgoF0S&42!WYH*Y>74y4siH=Uh+5#yZuM$e~2}&Pt>g> zhn;_BEPf89I!>Yi)DtVJOa+%~j!nRU(HNE{f3u8!f`OBq969&p4OZl6qWqW)0yJOq z|Ai-pBG2Zu9xg~O2cC-m3CYd*6IhKO2Rfk57WYj7O)@Ux)New};Q~Nn%|D_0uT<>+ zq~;I6Sg%^CEc&hdU#a4S+||w{V=q$qp^&yBD|=^?bg|Z_FNH;O$LO?@(UpN0|6g6F=tG$Kw1JmPdy2%8(KA z`X1af8$r!2QER4Xs6RV~HC+;wZ+NksSZPq9U3)=zUCazDwg7SlTN}ogC|nKclvj^m zxKZfqE7*)(dZk!h3Y*_|3u0ggjW z7%xK;Lj#S$A(d)|5fFwg#n6j;MP}X5kiM?#8hejxJuTsjT=9u;A#m=KH$2}OXTwDl zeQSC{9f{3YcfsA7Jn7J)EjId35SIeUw1JD$8f%0>C~q<0cXJ3E?RYcAa;9hqC6OTq zqAyqM#mS;|4|8D#U7_=qBpyPTMbOFEcKZf9S$QKsYfVg&neq@0OfA3z29%b8<|Up) z`VP-stlL31*E1`$>|^0Yy`)Fz?wL%JNCrof#T0&6+?dTpaPy-8ewE#3{zz9+q(oe3->{Mo=&>Uv}U2FY@jQWU>S zFDCCiL&1NYMt18t)cgdC=?5DH-NJJZ1G?!5SVXymi)~tVT3p^dd)Eaiy4WF) zExPX3>q#Zap{I~7WTA&tL1>HJ36M@LcK?TE$+F8_n*Ezm`*b*y6nKj~%Ps?&n%$Tp zdZmCeqP0xdb}#S+7B*dg-586rf1Dh0$0P!G51#xJIUJ};cF+p2o}h3MU<*sSy(*CP z;xoAtr6QTd4y!1Ym}DSb!N))Phqx;1w%d4eoEcRLR3?2lsauIGOndDX=~u3i?;U;{AyF5J7wc%OdOr@b}`uaNKk>Fuv{j5pDV_-KdAKy$mAI2E_+<(x4I zgK)_lzIo$wc!DkWGd%qo1h9E?&$F`m&N1=&$qDVf46=ZQ>_OG zskGQC#a!Nr81tQ^oFDq>n4n`FB$pL}flD{LZgUZV$D(e;MfgEPtp(Ac1Aq>%Q&Xo) z-7)uv=~g$Dj!TeQ(Yi7%tSGl1`a!eNA!l)3K!Fcb`3}w(e(fbM4cu7G3b`x^rb{_O z>kh&dYy@lN0TxdCkVxxq7v;|$-V@szJMt^dDBK;umUct7v?!zrOwO)oyA|P zRj&w^5R5InD!auOTAnKVCpLMbf3(Kl8J82KD`)5Xaj$oioUU`nSW&P1B@lLHLmD+)+AcAc@D@C}r=c6vx-9twU4#z(`)=)mP`eqr>Fo|B!|2?ZEZYa6r8 zCWt(!nNJJ}0pe+gI;FSGt{TASTof(>DXwRM)`HCraD|<<-y|&_I4EfVomXN>>UBSE z9Tz!C0G@PL5ks~1M{T!!rz&E_{zy(+S*8>5wQ73L{Ari9m<{LX?U@Xex^{ChgOf^& z8&(AgC`07SGC?KY^NZ|1b26`m?68%!hBJ$w!OL9s!@)>CVs=p4QQ?X7py_$i>(nWj z2F3iTD>1A&q^GzkRpTUZqepXONbB>m2fWM@-nqhAD~9x+r%5j0`$PEX#*v$ii@<(l z;l?d|ujnrmwFL$r{^i9J?nvHWZ#~bit?I&4komzEtapqEjg2Dc)2x+caWp!7<4!1~ zsxa6Db*ZP#g$-sBQw1LQ;IgAZPc{Jx`LeIP-Ev-NLct|s%56anl1UU@-Q0;Dtf)@6 zQ#)Ln>A5qaPIVwONCzwS$`cWju_&*9rQ+R+uF+48AAm;!$pUvYkDKao%TQCN=Hz5s zD;0Q9%p)d?`Q8%^bGOCaOa(Ru?gm4IxtWQEL6G=$tDJk*f#6L-Ikx=N5^JD<2np_n zk2q)rNmij3NEFqBF6`Q4z9{?9hm@dur#69BYEN4Lgapa89`PTC(u#9s zEh5Ogj=Lgq^PDqu(q^t(j>@E}SApA%Wp>n!&4bZ8RU5#nfwD+l-x_in!!@`iIOv#l zk`}VGWV#-QWXJex#Gch_Rh{9Wf8PU8dPf`kNPE2|~}M*ff9)vrfjr z%g=BpYGoNIQIO)E2zEuly%)uj<7>UqZN_)@$zE}7ZPl?n0jI0+{UBl)Gj%UD2Q~Ka zUwnzy)Uio3!2`3lAhjmwVh!jz*+q#oJJrNDjS!U9VxaQCjIlKdj6vz>3h z()GH*SzAxb**_Plt0V7*OlhwfE`7;aTjUt#c1mDsQ019FZI~nu7@p8oeY&ZrDIM^; zX=$ptn|t+DD;Q#1^ZXtwCN^a`j?(EQa9OO{5!gQS6`Uf`SfEgbggc`&ZzQRaCrab;5ve;Z9Un{Je zk%fsSqWZ3OmqC=(lo|(+_Zckj-wmZKTEr>Qj;DOg?*|IP%-X-KGQ>0x244rbTYLBr zH-mK>6%##EU;Lrgut#AR)YeeyW^Jwb)fO`{EZcQH_K?kq61&X0hv^I|#GXq3-K(Sd zJCGi@zvLvc9&arLwDhTJ1#INT=^Zomp9zf2YZKID5{LCWg2fxWIGy3xa7FH3NaLu} znbnVd#N>huT|PJUnDni<8}*3Z7zey6E@D1-I|W=+C%kD9#(rX ze4DydN#uuj-y1rF^XS0ge5HY(nw8)PZK9E*-ER5KatrUMN|xWEY-~(vJLIK5B5FRR z34mOfM8`b=#))-Q0o<$nBQ3rCdAUq;HqASudseSI);CZ!O`yYNXid>hHQx!_tG9AaA%6BO>G4Xk zpb-RT0!sgENzjW-v!2sJRqtj?tt`?9)oS^&0%CC7T}rEsUxe?Mgo3x<*JK*N8Fuk& zwwMF1Y#KhzTKsUAa`h;r& z`WV6;)_O0}449P9ZP%mcRZ>3=E2+t)3>Rh^phFrtsn{v=g0|CHTE#j&o8G$WKvOan zO;e^Bl~%Qm-LvOatgzJBjKRlYZHvIDq^tKsf3R2Rdq>`EAN8~GCf$B65$qrN?UVs9 zS(!2$H;fkZhOgzwYHB$7b&gE2zBI)iL-R)x4H)~cu+RZs1jc3Ymub?FVB{UnC)bQO z=G8CwV0;b))LYkhH^^e6;^AXJI;^?l$Zu(Ochl&> z2vvi8jpnWxD=paycFMftr@e4DRwiR%)5;+9wk!Q4W2(T8_z)W{ac`7k6^A=J?fs&q zF~cbAU6yRJ+f!r1b1M&?g?iWDB#>gQ&(kxSU$}JghTkck>w`q%IqiJkshXtBxs)A( zLJXnr{$zy^w(++Wyi5Lbcy6JZ%^AXb)1Dd}QQd;dGHhAR14k96wa%wFsN`fO#hP#DFobu@p&ah_$9Erbqi98@rYf$erf}2-FcFc0_b9)A&0$@r0OGjEfEM zG9>V%N1v>{v5{3dGpy-h5*I^Qt;3KCOlrFVKHd55roAeQ3Z9a6JZUz{`#5Kpq_%6L z=Tjx4`mmM$EVU6B4{o3*+q``lAB`5%gZIt&jU|c1PQFxr(@xb2??_ETDs`U|3q`PLqa$2K2^tKss-|7&ozz>w-vT z!r#Lg&dH8?Bm4?EnK%dv5)ZNFk+i87Yjc4^XmNc~9Ip27eU0Dv=~LG1x(!D^ha&=nn^k8m^+70Rf3LKN`JOjsfgbEi?Lab z{BP|Ro*qy;j_6IAf+BX|Q6rA6Z(98-J!6-{bamSaa`Q=-Yj&#wdpu);1Ul&--Fso9o6hT=b&v1^P12T&}Pu9l_RL1!56Nxn)QdSk#La*E^_{ zyNnx(QkK!qZVS8lC;BmS#cZ%fbC$)j42>%2x?caasDorbuS4(;O0vzn=XzLB_a>Wg z^y1;(8D(Zmqd>GuR6c*|*+k)+DGTG8=HXCLS8CY#tDM8lF`}>hp{A6l9msQ2;I&E6 z`IqIG)|Zy6d4t?B;mz8X0?=L|*;<$qrIIvLI5<{G7N%7x;e*vbG)<@6x;hu?s)5`) z=xG013 z4nDCEJzr!Qto&NP{ftJrmdR_B7Hu#Mpp~TSH~1y^`?*e3u03M_#G8PWLfX}l)wszj zi>NlRm(PXzU733xp3}cGBd_YaZm8B90)e&kFS%9AzVrQ^JZDR-6u9GKne#2g1}9sF zbxSy$G=G03$~x8J{H8Je0!a3_xvaEKOV!x$4N&Nrsz~`Ry&3{zQrpev8WMMO3zhQJ zuuYvuJ?#sz*_rlbwx_I^+22rsPo~7Fm@tMPR$37RG zw5u*kanP1Su_qX{t<7Cifalr;j;!laL;$1LiXn6A(Y>~~o8Kxfirjosn;UmV9F63; z`Pbju!r>E~DStPl#xa1#cYn40pOo<2iz^J;7yk1>UUd#JPJYg?%`P}tsWOr6>$Cos zMQ#x^D7oumKKId3dV9J~MLEc(?zi5ub5q8Drcl@czgVc9ZjrrRU_DVm?NEy9*^n>w zBZ9#P6LrI=17cR>D)r5w3#TVM?W#^kK6uQ9i2ju_aEiV4YqZbc z_3uPAXnd>lTAfY-+)1$I^n`C`Kr;Z__zJVaRN&vk!W39VHahqd9&W+{o8Q-~sqdoZ zs*MH3mJbl`Cwf{8x(e|(6!Qd&4zJw4W_v{?6@-JTEEe(MJ^dj=cc7ED6$@YaG`O#_ z!7VAOphF+I@0!olxP^++&L$&gJLha^c8! zqK&A_sLONaId3ntT)RO;)$kk>p_!I zfAkihhG_)eM6-AO1Li91x){_T(uxb26*2Bw!KP=Gmiy@Dy9Yjs{coInJ=CiCmDcjQ zo+qlOMBIimC3K8%S=w)B{(zuN&ioG0vyeUgU`$BCosqEdyV=;*A=xALpWNo*^_@xe zSf;RaqRH9(-p<6!3w|QXIZ2$0iY=q;sOE@7AV5{B{*&KY+1xA<91|*phYBDC7P^M3 z>J4_<*Jss)Ij^uXbO$hXXA(Hw>giQe zZ4l%T)H2WzfDn@D&_ZA5F|QPXLQHa0LrG}*+Gyrh?HNi#{?kzt%8XrgzS_V<5=>u-Dl_AL9If#JCFdynCZFO=v=a zuT;>lAd$sZ<$uxrYi8If*}+Jq_AQWI=P*6VB6^hO(GU2YtG_^Zzy-+d|4)SWS9p~_ zZN^bL=@@ndo`tCTz_(RF?C1XqK)ylX^jAVO22X};52kdbW@FpH z|4JRB7~E2m`ES5$Frj-dgU5t!#w(E+v4>aBOxP*V{?Imns! zkIivNK`dAQ758o|*BDBi5(Wa^yvUSxAldMuEBuXp|-An-c5ICsG7r61b#d_z$#0-M(2W}{e2iq)zC{dz;zjlqj z7B!clj|&45zG~bzNX`VGDG13($OeJL^_{c_LsqvfjkWrwh6V*$ydgYM%fhh8nsq_g z2xLrM_juNYk)T^;<+zM|LEuUWYQ4EM#85OOMQ1&Pi-z!4pFRS_ffv|HL;gdFa@+Na zPo=vUv3vogQpJEXkECB8kS@>1;n~H87N46TWtV<^wncQgb67w#7?vC_pzUXAa_cK5 zXGOzKX*#%6vP;s8TZ z#=4Qdp9wB71H~2t;#}p;w13o}`8jOjWr%BlW4$XgS%D9h%rnKwQVwQSZM6wi}V5hL>1 z?P&mbA=iopSRcz&8rD@j5$=GVTA^g2LRY=i6Wrp!R6z*I&iOk*Ih?};VAi2bc~RT8 zK=gn;(AKi!27Wfod|U!{!7J!?fyjK6c`-VCJ)bEtiF3m{pG;JT`@0Isu>7Bhpvc(G zA#4^O&bF|w_=tO-5HKt#2LN2GpC)mxDO1+M`%zFN&^NICBdSbOF63ed3d3-{%$;3o zb(Z=0d>o?hD_JkYc7eJ}f*+Ub3PT*IpSPSECGj{P9Ky9VSTG9{NtES9~oUY z_Z8;kplW9)Bg!xf;@5AyI@uCg_;Tty4nEWm&cLWM@El=S(%7b{GQfN&-=jsNnOW_XC*?@9itXuCiy!by_~J0XREs>Jhlu#^~)Y zGrqa2x6f4dPeZhcGcvNO+C^0}@&ypsjPMbfx>2S96$B9|>cBwP$ff)f?wA-)#7BZ1 zHqpnBv8|4KOQ$6Ro`v`vb9nE2tL^zxSr=O7l(mM6&JM8EB1TV_wzNW;rXfuHmizS| z*oiwAJ}_FN3*m!jcBax}Vpgvle;0??Z_dP%kvv0-A{%{5mU`n@V*vsJwCwyiJy8T* z;KV`pGR}xeVDbXb7BMU{aTZ8wdP9j9D;Trb&&JN@cloe%Lo9gZF&ka$9V(Wpd387O z7A=h7ItdL`EW@nL0w!hbi&fJ49qn83{vvB`@1h{b%Tn~f`ZvP!V+{cwqxS&WQ2BDr ztv3b5(jJWgv(L^(F~!&2kO1GMSmcz#3gRIsYFySkuIu-t3f>efi^2hWmMlbec%amr znqz~X!GWb&PuG-_+Si!vgpy`XR*nIoOz1?^nH>X!*~9JpGj%$RY=39U){j|PUF(`^ zyc(axJtOhX1D^|v3Zd3|2!oqqMkQJs@U8g-hY#7qUPr_J^FyxWj#-HHV~RRvSyk$VH_?8*k1(0xx~e21HtM?J z7C8GaVZy@t{6;m%^a{X4W@(v=frw{#`gX6->qks z4DW<@s|ZI$g!fkSLlGVRU1Wo>nlBVCNLD;d=#AD?%}Ib;d9Uk;=>U+;BdNAaxwp2q z4lBbqiC(wFwQGM^HkK}R8%H+Bf@6ve=WDu@f}n9J@QMWjJ-Kh0w0@7Ve6t~A<-;t; z4>CytR-=yL6YruD%B#1VUz5Qh#Vh%+7OOLfsOAg~4ClgLSz@JnI(y#n^!WTBjq9!| zB86|4qhzm7`NsP~Q}qqR^yXWW*jC)TlEO!?w9aLZ9;dBUZ5{=AkG>w-^;h2vy9%cX zv|2heakCjIU5YX48*^bE6@J!2_rI&QB&&+~Ingef1u$*ZL_tsmr9;q`(BRryBZv1z z!*oL-U~h%+ucsy*_YB+|P51Yk`B&=mm&C3UW{VXB_F1qOSCDC1H3j(JufH8Qo{XkU z_HhFG>5G{j4JAts4=N89y*^CTWTqoJ56P_Vy0ZV9&=6|C{r;$nbZT}A=nV_|#T7wWK9R??g;$?NzHp1(I&qsuW4~4r}KFD&3 zGMO-hFeG)}{!PA!VTdhi63G<9B3^a&I#d~%I@)$5^Pu~}tN8gG)+e)1iyij+woekr zC2%p^{UH2Yv1RB_!dlQ9pZtsY=a{~cpFya(>N6Gibe1~kG6)WDN`vke{U?FD1o%OV z;N&|a((BckEG_5jt1ex70%_G+0v8jrV2SAIp=s%9v@`FV{|Ci!tQH@fqJSQ#+iA=t zzq(1j#m{-v$<6pL(Sb-S96uP=V)3I&32NRfjK5HOv$7cnER)9}V_e3|$ryE&174cf zqY_roNG}HI0c}vJjB;+A3Fav|5e+!&a%`nfoX4syE=W}!IB_!D*Uv?vao=Ayim1}c z;fC{mxmQ@xw4IfEf?e_V_pf&arJLN29eQ(v|Ili({Ir$#P=-S2KuL1uOh`dRm|do@ zKwFqITRM9t@tHXt>=0LmH7c_x-1l%I*e_HS|r22`Gk(Z*9Ey)#sGOelKU^ zrvZ$U95Yc)j%D?g%PCjipAd5b-o;GaF<80V`!U+^Pfp6+3q6D$|A$|yM*Sv8S;6;W zuCF@x`VLWMXHg?vy-jJMLm4U9{SRv@Tj`2U1lw*|MyNGH_^ID~s1kXy0#1xpB=(Y_ z+K6x*Z?EE8w}G)Px!jY}!(?P@be>Q7LnE#;kOVy2S;VObYoFZN>b=A@1^YG!7vwJ6{s4iZ9fB<5i0h0sdl!jo=w(vjn68 z$R_=gQNTY9)IHx2k)m3GpG?b#qhQQBv^PM6tt7i1o%|TScz|ERE@359vh^TWaNg~%94~fvjMEm9gRs1P9bIIn~gNueZ5+H63qufLxdFgwuBk= zsTU3RZ$1s_z_eA8f;Bfi9~j@^0L4s+2XDR`-(+tVK11%_%|=LuUq|Q#N1R!41?FRr zfwv!{AEA3?--MD|_aWLk0+Cw(XHT~&r|RrFJYGe$yumH{TBq5#vC6*WF}@@7cHzk4 zvBfr4P`S=CcC%@<@h`=HGds#JA}BiIib{^*IVBn6xBHj%>O4LB5|*4&slaD5`=oo; zXeO_`&rALr9yOo(s8rEgMJ=S&>2+&cr%+h;M4sHV{An3~xgqx3&cY?qx&d7J{Oj<*6@1a+fW zT6|YK!GA~A5e_?ArIHBy@qVJ6-XdgP7q47(ehW99-~Fx%tnq(+)HlJG zq4}D@*m@mdvcVmTETl^uJ9-#YY$yj)F(0}|;vCUD78^zPf+X0Ez*+u3CyS5Y1^oN+ zbln~u>;8x2JA9mb0fW@cHrWZTvfYZTCBD8$gn1tgxpTPDV0fjAADWxR9vI(Ly@O)1 zbY8*xLWe?0vWLcfAbW94GH=C}Vk}-y8CJ1Txb?;}`t>Vf&uMGk+Yrpbp_6-vzs{J} z@*G-8L*^?Fq*U?-s|o|A*DQ&dDdmmEhCd2a{{Xs9n+9DRCf44US5q0UiodpQ&Kehg z_T#WH5~Q!NMvckRHddUMwRO1Ps(bNA>3D+#Eb5nW$!PK^)3YN_dq>HF@fQhHD8QWu ztjYy`B1H`qy9YHb7{-aqjgrUDKJD4BQFSIohgY@4H0&(2b}!W>>w@JB(?0Tr2sX&^@PwWpFOk5qYU<$N}d87G`VpM%@v< zx6-*7O-V$s)s>(qnb@lxPO46e)0y^c^eT~k{$DAJ{{Z?o^am}^lH^1LhWlvmT#}~k zyuR*rHFDIS;F~-+fq_cmDjF)O2UgC=9VRs%x5zQPkoxpyn9ZJyD}Q)-BzDKT`a|wA zGJFyn_Wh-hm*HA58vwBtV2`{fbh}jdj_>s}}DOiHmnUhAL>gmCVXZ{rca z4)0T(H#@&pAb0Zvc@)B|>pf4EYX2Lk48NXf^~4*^Dz;ZR5Y^aogv{{)XM|rk7xZ`X&}iw=(fZS1%PU8qd*-vD=oL$w|}%RPFT0 zC3B}Y;vs|8o(HW=ofSAqPFd4o+67I6(XO}x)&1n@>Dx&(E6 z`@vy+$U)MG0ayq{hUCSUH#RQbuX;8YFv^LF^$SV(+c9X5$hLlnodK`QqEG!R z)iL<45JzoR`WbGIoD(MC$25njhJ8`}_d~%LiW&;p(oM>uCn4t9@;*y3>Jv=a|}SVWWy3}@i6QSQ~IL(+W4RFa+(g2M%=Oncd?ydHcEKJ z?O~;C5T-Bh{HD;sd}y|5?_6R8DKn;W@EPo7=x82?oUoj_cC`Qn3BE_o%9nwJHcz&}|=ob7rVatiF@XHQ=!_#iI-M@J&R;0u(~3~@pAyvZR- zbSA9LPQ@31Q3H9wdVG{~EI4Ge@6AVBmgZMHeyc2rG@6Tv^qYiAwnalb~K0%05_e*>O{B!dn|Tc|KdgOoH_w?Cv76bZ7=9BoY9J7Na(6QI;GNU<%oB9 z4iXSJ_Xo|R&<34eq`+4ucUQ=ObZzbD$BqPgRDV!3mmr_5@pyjBgvNt2x349WkiGT7 zY`sLWdZkz|!+OA$L52xDUKkKcl{F`a8t%Wpp?ELHR)_}Z>y(bCz~to>X(Rba%=^#a z{3zH~9@{n;5tW)~F~@5?M=aSqI}bqFjm^vhwt2v|H|h&^%v|MPDSO)uwIrUm7$g~` zTOL8ZZf1y~WeObsyCmG|4K~rCwZY3FmD6IRJdqYEvWP5uOl?RLo8R-2`}?l)kEe?Y zc=qv2*oB6w@XdU%aveX>Tp*58#IkO9X+7}<(Ci>v6^^(6K0s0o8A%1m>$OC2dOddK zOtl36J}4?!aE0lq%)MeL0U#mgB$)rzW5*aWC(Zd16VH8IbBkGJF?fexbEIpOBMUY^ z9`+y@0KSQ3c4CWw%j(M#=J!*qy^DJc#Z8|jg6)P%$j)r_s&WfO-#1c0<9nrYSSiR` zh9a)>7)4LE>hMHE|M{$MZ4oFlS)2}JRwyzvM~&^OS5tJXw8C$aK3I`OGsj~CvJoCGOB(kqMOJ6!!Jow5R=px^hZtdfF+?P3! zJ$6Ti?$Xocko!KQb{$X+-u`Oc0aa#7xR(u>Vv|P$80xsP*0Cg(!9Hr`mEU|1PC6gg zu2XJnNvl~CQv`IiK@w0=T`$$iRMCv}8p^A-Mu-AM2ke|0!5?CM-~PG|n4A;OO)+p*eR%BDCQHf-+(?U zUy1tHJ+5G|GCJa55mW`ps_$C9Wl3sveeQh@O*Cz8f}P= zei#=YB$*D2-ZfV97;jo1RzKVt_Zz(oRnEE(DDXKq45T)z^NVwG@TVZd_Zfh%*9d{# zFZh7nHO*0$SItQc=R#ncv0kj_CHjPV^>01R?&Rgt2=Vq1s^T=TJX9zAE47cd{jh|X zNuvP36?iWRnfi;b9 zKU{XXbGu6~h<<2vn(WIUnXT3DP5AJkDef`Ki}IPYt-N?kZjVhnfw-S?!CGMcYGZK5 z53Fn?Y8BHYdRfv+34}ci;uadU@!4_r+|!1-<0fbfwYPxX-!kI18D%3p<;99318Voq zBT8TcEYzMb4liHBZV*5t(D(>jz)#ypse&Z${>vhhfl@$mr~vVyY+|UJ_w2Qx5kVyo zyC-*yiecAoo_~iMj$M1Ov%NhGlwCFK(H2+M|Aga1R|1CgH9etS$GX?lTXr~;q`_4X z{f|bDb7}w1u=OEI8VAoVWMoFH!FGx+kd!_tx;p=*5o`Ud7dGt&(~fPv6YvW-yPC=Z zG~;kk|JT)9slKgY7EBXtqBdnT<-&*3l%tIX5wIC%o16K&=5hn-y-AxX#X2jhz}KJ zTFgX#e&9gZeEZw!));D>yN5+=+A@Q6YtK0DgOuCw>GN{(dNRD6A@hZahxZKL0Hw^BQ)>SBA(^*(d94 zf}LzU>9r^T1HHc);2;0=utY^nfyZrXtW~6Vk?7b)P{kkj0-RhqZY-5Nr(-wkhg84; zgS~5M*mU<8^usB+ff;g?im{~=rpn`7<>K0w{j@kWgdo) z)|%SJaj%mQay~R2uCi|End(8snRmxjK^zlP1ho}t>0qVJyoIF8zfR;LH%AftFQINK zIN)|wVDVac6~2w$w@=m@rUU05U5P2mk!>voAl2Hgdq&o2x;4IT5TH+d^btIcE`I zP4s;@#%h<`ODzdG^;_6oSfeC}&Y*x6KJgGdjfGkgy}$+yPFJf4Jp- zL;Y83ZFSG5O;fP3eCOE!_|5c~5dq_c+)qwH8#I3S-R-nYrXylpjni|^0u-JEFJIOR zHaHkmK@*Ilh~~2iU?#gqSG<%cHcIn0yPOj0bm7={s=$#1T}ccgPEGWB`$=92-`y~h z_*@~yiZrM4xmrQ#H#N!)v&TH)uE>7%9m1u~8PS>J;qr$v5%LnMpGhb=V(4STyAR3tW&mp}-l zh+S@eWhAU_-?-X3u_7iW`hJ!^RrzF(4&gG-M+nXryx2;q??`(G|AfO)o}Ab;`;3wW z-BfW+N4_x-f{T(?T*i*%&3?^I;AkuHz9u)+2=INLkNo*}zwQleY-s2CCRbTB0V&0K zV$h(M*`K}uvZuk>`RhQ*i|>~6YFO)r6t41$LiEJ zMGP;C?J41V{@dHbL#NYk7~ZWsQ|zLE=~JjCtLIMI1bS~qSo=gsWahvG_S8sD*vbnP ztfK#h4|k)uyBeu$a=A57Kn!Ve=u(_XfyiCB*|-Eu4>9jhv}}R*K4qpj=tRh0J)4DI zE9J!CuC=O1bJfV}BLhCxIaYPo`sfWA&zLLTn4y#4>Ezko;MnHw;7}nL-}4lGLZLYAW#ecn z;5v3&C*08gGE&X9n2aog$p`AbCklM9WYFDt~RUFdc>PY^h_8H@o5dXiA zi~3J(+>ey%e*K%7ItUf0ie_#mMvk(XA}+(`-CXz;>7)bDWRCv&;aJoJeEjh|QNFZF z)!i)|q{E${U5qB8Rcl>FeY8J35$I)4mK#ikXW+0`Ctf3JR15@@wOZ6kM%|I{Axz2Y z+r7arj?=xb?3i5;kp14B%T|SH zh3nk7{LEeZqe;P>a{D_!5Ti(RJ<@)aa>r&}!OZq;UU?1>Z>Off>BcRKv z>kjVh#<#Tfi$UE>79*XiH#byqbB8C=e?O&`@=XQaM~77Aq-6F zwu>a+fKoA#x!U?~LK~*=Nx6Lk{MZY_s2753cnKiCAg*o}+<6SLHf>BBcDc`k;I1PM zd}YTh8TqN{9T8R~C(|0#tof23r6-vovsTH&r;s>_SR$ z)-FW+hBo0_d9ic~6Iks!HpV4hfv9cV>T|^S$(W9e+Eg9|^R3zuvH%_!F@BdDs0!1i zU&I$olARy!%%JJ^L1a|s3$+o{T~bqy@%)=4X_uP1KRjbHVK3G93gvo24%r!<=pU%0 zmrTT@$ff&%nay5x!)=32$A(*8^i)1q1K7nOj2bA%2Z>kRn3x(y1lTvsq173vG9>Q0 zZfO0{v5|+-RVtCQ@TFcl>4oeo>9_Nx=EKN6O6F0JWg6CQwbk z&>J7dxaUBopW?J9&B-o=TO~$)t%qWUeTC2mX(vwIei_wWejIcJkhbnk{1a{9J!w06 zE0!13#%;gdv&O?}8}cJqv^Vdv$QKU&9sL5Xwgxc*F!&Jb36^2liHNSCc$v#4LQURj z-_%Td8oO~H)mYJ=^0Soj#nICXT5&4mjUSZ#C2_&rr7x0h_HGUFMuTzOP&j;|gsJ!= zOgC4mAtETY{il|A|2YlW%S!jmZ zx1<&0adl|ROrh$d?ba@>dVhNrYRc~x{@kmZ3Oh4;S^7UMI5(WZI7@}1lRxd$J# zz7UXkThTQ=f0kg|>+iW2uFc(M`2YBs=1Nq$%z5nRTy7wo_q@se$NL?jWD~lOuR0V$jg6&QvKpNtnv6Omi?I1gc$rvTjmfR%u!-nwDbxocdne>mSUU2Me0flEW0Dm(L; zvbVV7aXEQE=l>onZ>bNpLoD>P_&F^aYW44p+Vg*idiQvy7YF`dr%s)8@u`kVZiOh< z+!JxSxFyMD?w5*@%jUj?*}72)J7}0|a^GBX9p+NRFeCTNHX}x1lP$D%>H9vv-{brE z{>=k>+xxQD<@q|Qnp$W$r(v()40G1}Ep|yw{{Ca32s44OmZW_4fd8vXR15VY15X#0 ziXEm?b_A>H6sFapX$Sbw`7MyRY5;E?i zVmP65)hj~oW24oxpsAcg#-+y~mS7D|bKes4uWOsO#(NIDQchg?V!<`g{6cj%(?)uW z@nR@9f=h8E8J`$CGUq*{D8|Ilh~m*wmjaSnbe`kGA$_c36(xCh$Pb-?qrLt!Nv3PB zPH9GjSsMM3-}Xd5*E~@1CWZO#g2h~~6hWpi+XUy^Y(mD;OGnv$a{cdsp1#-+& zo;GM@6LW*1%L3qy{UvSLb=Efps5bYYt{L|$JR-n@8!P1<|?ab6KW@$(lAb4?smwnQEb?Pl&<_MG# zV3D;vR|Gs`wX!9Q{>Xs;fnx1*Q_>ayJUt&`NY}SKCvCcF-|!HQx~sfB-!60Ee9Zb- zmHVQvU&;e7at8tRKY7(;!`L%Z^J^5vS0H~&abkn~p#hn&2wNkuk@HJ|VkuZ`H^h2h zVPwX~RildbP0W3>_1qv+;a0OJJLDPQ5j6jrzDtdUj(Zp!%YDHi%aYzK^ZnDg4sYCt zl34uSd7=lBwYv8|>ia+O6FSre?ez1`zRIf(L^z^Yy>)dgXWrxXm<2@#k092mWWE1W zo)reOVSYhm#LEX^3v3 zuF`k?crNm)&rbZB-1GNPXV8FdJufDT>jGmedOKc?b5Lze9v)G{T>??LH76$I?%2Ay ze&O7G`NcM+$*V#7l6^+Tc=bsf{!CTUU}cjjn46`+)mHE9xbVlJ*T78PMSioVQbkJL zL}B(aV3Pz_8@MSauI}3Rw}xV2EG^RcM=G)xo4;erTGI_Ng!oB+uH=pIeq^iza%DE} z=DeF{^Cw?9dhuSSiA;`|(!?p7x)>-DMjOK6SHmt#kxU9O4;bVLtQ5AGGaVcfn)M`e z5TJ~th|l{2(I}hx#$4mdqk|$8*@48eg1k1S)S55Jq(&1FTWb3X8hCH*^7t?Bff+1 z-y3SHPAc?&r^TeJ+ZSJQ_J0w4FQ25|5p*yL0B0xMtIdQk+I{kNH^&}Jhu!F-G!?t> zDMRYL!$u>r7e{M3= z(r$q3Z<;5RP_9v3?thq&DM=?~er#@528kPu+!**8B+;zj$>8}@pQGa7Mzjd&sj7K( zpDVyg@;K{l72ulvx43qJ0<02w( z$5%41(g-RmcYb{PJ3iAOt(gs3Z)&F$rGEa)bwQ53g_!TFDg!6 z;?|akq#9A*Ur~>7%06_(!SCpfR3qq7HOWlrm4w$i#fYEss!Wfm&eWfl!OWkgq*%nj zaX~fUYj}Hu1-fHok#5OHMoO2~JoQe38|pQTk&`duyTWsR8Bw*)0YtV#E+bYu2f~}~ zFt8V;Qt7?O-Q7UflQdKIoRw3^Y6Sb;`E!!D27njxxe^|elD6BqGZ$3hJTeb(8)EIn z(d{0v%`fgnG~189p0!(!w|4mW7HIj^R{EPzKoh#YTQPN=no1vJj6I>H6@h4{f(>$gF*k}Xj z7>w%;c~QLLjYrx5-t9r?Z?S)VqJ{d3lSOD51Tb_7Ov2qjQ0&w(#?|JCp}El1{SBzB6f$!`e1)aF*F0S7+8%Pt`=Pdbz(IMTJc zttHe{v0r#NA~<)&>^roM@E=n@i|AaB_#dKc-`D#t%;3`m6tIbEc%Q4yr(ZRq zT;6yzo8GKi`?Hi+m!g7IgwS_!z#;(wE;uxwSBGr|$TRbmXY^+VPYIF&j_qR*(d^B4 zuR1}!08KlpP*+atJrM_(s)GGk0-q5F zpRf90?n2M>!ZBEmxk4X+WOCCtQvM57P$5N606ey>yL(y*;L1Gfk38pu5JQ>YVkwH6 zE6yS7q&CXvKvJe@tM_G{h7&S)@ouX|)ze<($rJkJI5Q!@UIN z+kI)NQ-C5-7XK)8Cy<&-1ElNDAms-zfZ@_8#vp1KSYunvV0l#JE~U)?_*!N4?zFt> zm_y5vv>WWb00|&4P%;jPs~=vRt+QZ}N%Li5gSxwc=O2yilP=a?J_P#C zkx4^j5k>kAEu*Q6X!+0SA?kaBvEO2N2r+Q5UN7moa4lF@w=gHCsp^B}U7B$1GSmQg z4MEu)fa72IT@_r_YqQ@XG&f>0@bgiLrRNc-ZsRb^+@?-j@@^KVc5h1p{330*D~>-{ zyk=BeguH6I<8zn>q1Eb{+hd-xuHsiKHkJs(zVqZ=w`_dCMA}rxMyJb@g%zJqGPqMr zUM?KSFZ=Y5>4mep^}-3er!LHHuO``!@j_CGk{&;^P-{k|4;hEAgI)Ml(mbwr+6t|l zJ4@5W3A$K_u2l1f9<+l+JVHI7G#5>CWhOlwoFVw5eSC(lWN81E^;IH?Yb~v2xMko{ zJN8&}pu8sxH_+5vOSgUjcvE|zDAiZ~KFuZ%lam>JtzIp^wm|n&CL2_30EzRE4lk*E z%?J-$xIql6M@16=+_#u{^rfcURWO8M2)F_EPBlsyPS9hREVZUBh1$;8spnIlbrK`0 z4aT}O?Yp}16sSUmF-%K7)@%acb}R+H^SNL!84Aq3bUmp&_vYoS8>Yl(=N2HoOD2?v zFTx?i%rADL4lCRl^FtgK511x}tqL=N>|V02F|My#$cC-bW6J2Ry@!W_xfS472n zgx5#%yC1(MZl!d67|*%PmOc=nHBTcGL%%fc5%=5=Nd`K@p=n9AW*bcggL+LF=W~Gq zE9_0^P`Ir}LVElQcy^bX;ZdAve$a$=?VJHgV8(&~uTx{9FCLfccFHUUj(k`2)PHWP zbJdAN_t6bqh{5aBW+|i(CKvV+f{}Tkxa9t!5rNt+CUUyd`SEe<=adX(5fL`9zJbEH z5E5;o?`v(v+XG9HdcpE!ekS0HH@%X4^kePf>oeW0Phh%rp_pctK)OjxDKq5rd*@l= zijV&7Tx4lbbPN9~PNN4Xad95_{aWBU)ij;+eN<`smEH;VcgRK8$zQ~O-{@?h0bntW z);ESry<(Q3X8}TongS5!Pr4#H(rZ*=o-iv_3?3Aa>v9>2Ng6dbbwjb>bbUU#(Ufuh z+N$K8B?s%80zDrMIMl1v=kw=%Tf8wu0w$L~TtwxbzPwYpl-*aAj9Vk`0uwhXtXiquSw#T!2 zTS_5hrD0%5Dzq>Z*%5@^T=cioWrBDxfgt{fPY&4QQTMxgeEhCM0!s37uRhi#5HfB_ zgt3YyEv{N#F54SroYjWKc=>+gurD>{x5*uOD9l%fDjlWzq@MSx-ag#^prTP*H}oka z7YV8On3a|aYV8G#$FS1s*((t6AjIz~@0d{2$N>^1>D_d$u_A3jm@U*fBZw z&qVY;|2^94tVmt?jj`h$Uby83(J)f;h>!LoOIp^HmyO7vYS5Io8T zjz@#E+J>7VYEvt_MQ(lg!XLqpK#1-noFRg4-xe#UeLKxIf6T}(E0MNNsIBy#$gJYr z{s@QoWHBL(V*B$SQrCSI)wH%WeWA$q2W9^lhrp}378^K5R0W`tZ#!{(kXsMHoF!-8 z8D;r9AflrNb8bv46R%Li8t-#~#UjXQNg+wn;h56+Li(qH5BO}5N~qa%OVP8Ww;JBo=RYNZOwE1TXRTN@6I6lI!aN5;>zr!`k3Fhs}ggVh^; z=9oz!iQx}q^EtnMjVq*TWm?U-p!q4U6FzLO!Y=GF!EWp(n!m~t79SE7Ufeg1Js<1> z_oD0qvjDZ@5j(}9*;Q$}imR~64CbmZi{+??@q|kZe`282`B-yU(EWf{zyKC%wERvZpD1H99i;G<_VE`D4ZJN%emMa!!Hb5n_B6T)^?apl~$&q_>65PlWb$^i+ z`4Z?{LYUq4+VSu2=C1|#BPYeN^1B`e*#ziDWbeM2y0^2h@doz_d_5&HO2{K36VoQg zYk_Cx!3S5=;wSlJ60XBzqRQF8x)>euQet?`g>ZfJ$BrKLk#8y`f8I^X18AG{Gkm`M z@mN-$2z4EGJ7bqdxR}uCO)^2##c;4>xUk0N1Uc`J`qICv?u=LLfs|Kxs9gH9N2%nyz7EodKNqgOi#m1IBS^|6V zz^=K%`!W$V2kuO)Cvu`MthP71X=Fp3A9gqRKFRVyV$0|7L7CM|m3(o-El3MZY?Joj z@!4m$Bbgr+c)E%R>KiI?&&btQmR%bG?lW(>0&vgtd?O{`-hm8oj2=))dxe#==$nxa zMJ!@ERHcr`YieoC<^-C8L)EE7`3O@-mU+#ead9r3*^#Z)%|2y|flXrClW{Le;IA=Hx=zs}U_E z*^B-Ums+AStuV7lmym8&LE*-#>;!Cz*BJ{Shw~jK8tg^nsoMAqD+A{Ma*2L zjx-eB7~%1r2X+jhq(*WC9VqdJHfw20JkduK+tcA%V67p47M&~UY+&~Ch!NYZ7yVxcY7Ny74Q|@dk{Y;?0~~JLici z|G6sa8>oxD!3N^fjvnKEukV9VMPA4-tPKDMwB*Uugp+Q)n@#nDr91PG&gnYD*YZxM z4@jOrF4}=?p4>EYiP-qJ<_oFP&3LIvsoq*8{g|_qk-y!xCjE&Ddv&hK-TWjak{EF% zA2-wD!$$8ssgj!T3M%lz-5z|^y3pc;B9slR5aaQt5 zZhZ7kT#QC@V{%Q^5Pk*K_$kViG4{3rJrKYxo+CH81jlH$E*Cr+HU7FD*RbmYWSAVe-;e7m*b zF~sY71!rrJ{*39Dv{&|cclCPUVtZI+=!)tA9ty@VVoL*ba}5qDd|&RUy@wW`L1$h5 zaJCk8E7=p8Y4Mr@VY{_AA6GuGH*wYMmeS0)$#HqD$V3YZZNq+D!40Vq_w=NllN|Rs zQpmSfP;+tp3y`?(L?lsPVXi78B=dI3Bd8hm%@@Fe_8ck8#G(`R;C&_68P_lzD1@(b$;ZvJc5F<>iFI($G;=0r{fc0zVv zirfsCdkoX{`nckrfxZ|@KzF^R;wMAvR)Vf#$ei8KBdBiDSa9{{o|Sr{kTO=YLXNOf zV@P5vy{rg_Ka)hQM^|XdcDYQMFd*8D4J^q#>5-B&W|=j&&TKfjaIcn}2iKS1Df!%U z{kwl-+~+cyDva3o}0nQx-Tyv>puQf=@*d9S^| za^Gt8?UZv9HkH`M877$Cb~ow4eJxq*bFHE#($66&gx4Z0MB)cWTC7&dFHcT4*(E^9 z|68#x)a!K-Ln{`V85z${_en@8ziSKCVGP1R)aSONZ&r=b!};qKKhrZyl~|XOtO<}XTm=K( zx=5US8NpCgEoSkD%9P3BKUDs3^oR3h~uhPpyIm2>_ozukW8;8SE>WG(o(r-v3NReQ> zKkKZNbS!=XgY9l_%EoBGGsu_1n97@s3xNnq!mRysGFSGkZ%sJGd?o%}uk(?*`Z`EO zpXsT`f0+d6W9#&nZsK>D$SPvC_3k5*%(I-NVI$MeuZf4`CZe5r?@j#&36X-zDOh;Z z3KVWiuY*3?(R6|uUF@?i*BJ;uoNcF_k0|q2o|Df*#a#v-A3y&Y_mrbs>6*sik7oO< zZo~pi5&|&nrb(~DLN*VAR}-YXfApmwR*z}+&)O(d6~h003xO_kF6yg22?#xW-Qbm? zpBF#b_PMN%j*dG{Ir@-p&vATJmtNpRxK8u%%zECqi<7*Pw|h4g1F~;!c4gmhYN1$$ z2X!dZz9yZB!f&<+*3r3w98_k`M0Vm58T7LGa*JoH_?`oKOI<<5I*hsJ)LD>k^n;Dz zG6S;g+vBbKmZlmul|B05R#o4mPgy+r^s;Eb*n{@f&l8_XkTL@1z#w(r5|mwx=u%Co z?E@~fMF9|*ka63(w9NehDdSL6-%OvZ!ok;`71%?SS8LfA_>FGef94-ltbM>cC+9T6 zV6Xmc`;=uU?Pjqg4IYj;ko={(C-ks$y`>Hm1gxaK13L(o)P{k8!DW}|_H@n3hxO!o zTmH4hYe$BW82iuX)iCT@m3DA;j5b+X%7ubvqR*a{&S=HK|7|2IB@aT&fDpLE-5sSsVTNA3Phut)TL@tdiyTj3Y)c z=N(S%P_m)+)`hnsIiPL+a^rjCrUn&Us3OgTaa|Mpu(zgeBaLt+TfQ2N$@y+RG!Zm7LL z^>J+flmYvd0x9gPB+^%!Iczt-bh(s3U)}_J2?(1mLO0(h>FqK}=rF8j&9Vhq6(5uQ zHXq*;IsUz}dhrRgy(M>}E5Hj!0ZyvJ_nwhdzP~*b5o-H^kX=XEx)6Q0qr*;LroM6P z^dG;)aNQf+{gWyyMvlXQ85Ztfu4FOiJF(PJw8e~FDM`CIxEidZ=@BQ|a_U+iFTI`g z$~{JIGKV4b`t*u(g?UDY^!fXv$`opKH`C3eNu$kmhx<9Avq{?f+CH6=t@E$5Y^%G- zq{02;BYJox8)o+M3_gV#DJ>{gFv`h0%1^S1Mgp4VH-{o z3855}pA}&WreBAKy{g0Jic{3%JknhS1EgC8^Sm;;((5*T2QuNf0{gPms$x<_hC;_O zxb`%n6>?V--5ZGL6oY@z5A-Vy&Bf?^W~OKxlT@iUyR2Ium}HMQNER1}pS1NeTiSBPN`LDvgOL|88faDLMy?a80k! zty8*UVB^iAt;DrRHFcCKo9<(*IEU`;gJ^IQzF>#)kt}s;iC5R|q`t3OBkIVpiwFfl zU40s-$>QI{Vm6@SwfReh= zByHIQvH_3^L4PP>;Fm~S2t3!JAtnN%K}hmNvKK)v%yO%}I%q(+jD7s?bLc9J-Z&3O zHQ3MhkMbD z(w3FaPXG&ZA6C1g!2pu;SJ1Y`#p^${gsUfhi{1PGrF#f9*iYCiQuXOj-dq%&EUO)2 zz=M8^bvVfIg5U^hC(FIdaoNbuOjv z{tdc~p5^yG;+OUFQU86*ZTtd6_QhadpM34FrV2hvaYM~gr0s6DbIb(@?T_kBy7}>P zBMs+8O&^gHP_xB0KMQa&g4|Fptf-1rx~E4I5*)HUV@~uVDpn13+K5A$zq%k_$&Wos5h5bfPg7J zMn`j=_X{-k{}N)1>J)0f18AUZJ_9)F9|8}l1CWEClFF0EHu#h~B#CQEUW`jVMDydi zy4q^Q&|Oqg(!Ti9Gu|oIfb7b1N8bk~DL!|hsw49sN>2k+of5fnb}jIi1ffyvF{{$7 zJ)NOns`?CJvDLZ{{i#A`(VK>Q2qFp)M-_nzMv$IZhzdOv$Oxm)SU@U8(?3e6Km^~h z)$19I1z1$yM=OrW0!!|(M*&m$(+TjDoWxdAN<5EVBufmo@(BKk{{E}Ln+b-Apk;=NRC7{3g#4Sp zv!jS8hR{iWvmT0-qWlNGS7#{kjz}wu8OmLEI#3`80p(tY`Om)>P+_Y-YX68ItzhPxB36L^5!L59+2r?t@HxA+DFs=I!gj<+o!$LAAoV|vzSe%&SSs$ZnDI8 zT_g_Y&KZa^40m0)->fJ*WY~V=l=gTgW4y4vNxzfa6eV7f+qs64SO~0_tP3$vz5at~L|_ZCqQWvO4EC?zX-D|R8S9_fa zK8+UF-vKil|4}XQ(ocVjRiS->@CUAwCu2YKRJ#RttLMqC%TH&!uYt-`V6zO+qmBKj z1T$~d9@mmlz$~EwgU-8vFq;~bJbn^V2gEu-SPvNE!|0Hyg~69zMaV~k#^7CS*ABSM z@(djyI{_5Nunf-CK$CvfETR!;bo&agIOvbjqV2HKD|ERjzzKTcj(^o#L^yRAem!|` z@M9hEm%f5v9E^1g-Hk{o?0M!maPC1X4}*H;WKAlscD|hPD4}^Fo}*qm)iRhy%vzxm|GRK_@SHwxSb0Q-M3J>zd4kLO zCoCm<6nfk2a^dq_GkJGHfOxdo$HEpW>Jsh2Q!6FzV*E!9M&y5!BS<{O)kELk*@;S6 z0XrYpnm&-{xRk0tUoAHv+38&;Dt>kY!k0F3wzT^aEx|iBe6`}xUqmF=nyW=OA7rtB zAwzI?Q#)EwP)&fY452E%6hRz}iU!rpL^nb5cRB(!Rt(r5b02gK;i?>em>~a-bk*xD zna

    +G9UE3-kkdlU)lp@<72A?o)P}X4q3qAWNiWO3DLOO1g(oV>$R=P2-%UW-e$v1yV+XLj5r=B%H9y}u z=}#L2DmL#RYaMNdW*8@+=r}|^oScf9z4%M+B7XZ&&T-e$URz|JsQLi5UI=(Wu#d{5m`%o^O zeR0=KWB#8tH)-gkkSc@`PQNqzkusc$S21UBWTMwD_bOVrTWEV~QW();>%YYi1?Hwx zYp(v(Q(3|(D#sL=@=r4hVb%PpQl-~i2sjjg_pbt^n4HBZ ze!`yyM8pvFHe_Hat=BH5yradTx>b6Gw%&o#|JW;L9z+Bkx^Y~KfB3&6?$pe&ng+7b zbWTF_>^3vb@r<^T`sbIERR+3oMV>+rT zB@61YdUvfWiJRoQtfPkJ1;`Il{pPzKL&I%ztQFHh-WqGvuGmtywkKSz)4#@nk>=cC z@3leME3v8J{~T@#*?hQsGsQ*JN{}NRN_sW|A@eE2L&yMh@FkgTZ&iO+Kj*^~Vi-SJ z7C_GX?cm1#Of?7FrdtY(lhx<3`&fM!_Ar7n{T&Q-0K<#Vbo?2alp|faZwA6pEo@=L z$-acnPoA)r?HFq)HkhJ!6wkG9O`7E!I;Dgf$S=|f&{2g|hRl=AfBx*~`Nl5^QXiGoem;QL`A z&k{(bu9M23M>`~De^>X6^J+nbl_2P%zfIXWSwFw-wvt?+;Z{9-QA2>q`P&Aic_VYK zdb#=PUr_B^iwc1?;5Okx>e8}^Q!+R!`omIj-8QhigsYootta%;=j zh(O?*lGIdOn$|9MI;a^n=N@;b9>S?nNb_LMW$kIp<4SX%%)M=MNisKg z6>PRsu`GJSnl$s<*wf6!H{|oowhJl#=$~#&so%JtL&WS=9SQkce<-R8)>Bf{A$o8r$Y@2&`iGJ5l*VRwhDX(_zjLt-#E`<6 zSTVAS-P?-d95W5XbO0|`h%i&nPjtH~5qTT?9Hyh&SARp`({7CkyF%EC{`Sw!r^X)$ z;zT!pV8EIIn~xQa3M!{_-V{V!9Sd~^SfnrD3*KgTW=jdJ)(VycJL9;RkO38qVJmP( z>Q&>3$Usqa&)Za`T<9u2TYly1QJq%Vii5|!b%d3!HeTP!Z7VV(9M4Kj)CW^4CT zyP}oZ&t!^I&BWDzU^PO*qxGsjGk0zkUlz#@=SzeaSXH=#+nT^`Qj;QQ+B>VAS{0Se zyH@LumNHy@&wT2~a~iC6hClAVvJ_}!ax^hFS|&rUz)y>5APFksVcVA5oZ8g;^k*T; zlL!Qkp?f?cBK@cYuh-S)qe^z^7mq}dflE_{O2UZr!M&wo0X6(M{T!)MY|V*?;*b{4 z42ELZQfXiyS7L+q4}Migx9;h6;$xnL!yVD&{w5QbYyKI7X^K69&xN@%hub1~lSH@W zoYNly-5J8NQ>q{L45MDk?7V$*H_h3&=}ndGcxXYr$L+xm4q&_3PSm_>Y4J~|LyKFw z1zT+YwNEc@|1aJc)ZspV=yjB8u3xBzr1OK^7fMV&83UB|Pte5;K?`|^yrKh!S2iQ> z9H1|xQLjF{P^^O0Pfi>&LJa)fR-gJM1D&>;q4l zIYPKq6ZNAradD+3)582HZfnzrT}dl6i2VGZiW*7)gWTNbC0AEYs6VlEsO}Hh0WKbQ z=oWO1ru>h4g|f3~in{;F4>IZGzKtIh?U+mfyj<^wC)wdfa+EVa)m8;D<8WG``yj5_mh#P%MHBN%tzV5Zr4H0=^RrcbmbA(*&cf}AhHSHAY`*qAnlVz}yg9R7Qdr8H@YqRshS}u;XRGtaF zV)Jm(mMpy=mSnr0F!H@+*j6F2N4zJDLsy;z5`c0H;xJrA>em>}>uT?(e|2tcSruVs zZzjD>`LuH{zLM){Eq7F9ZyDFpF`jU8*wapnx0ahZc%!n=iIjd?p1V}}&B#&JhJ zpyENm$2Bbnjl3gSwoNVVgo4xOQc6H~*Z*kVhIH(7A$D*tkK-i8{UJkDQiL0=VZ}zY z4xkgfhF3e$PXr-9Clf(AdM$GYX(ZWe6(J4c1A9OoZ+Nnf1{cIg2MsF410V0BM75BAddH#XSo?)}vA&dEf5=L#JJXGze&+ z{3yJdQr5|8W7~!m<6G}rob5jVxxq7MD9)VA4(1Q3E0AQDhxP+=Lay7J^An%dtmRgs zou%E18N^T{TKlRVuW?5-;sgrJaX!Q$kutoKBPzjZq8Ozn_X8~C6orTm{5S`gK2 z(7dy&@%PIOSmvzZ;4?GNm5KqS3=iHho=pT!N>Ii_Mz+4M1?mS?`YYw(hm_<^f{uCl zQu}NS)o2pkwHDZ zyhsPi*~06Jiin-f*87V{&{5opjAU-1dr94f>yQ<-mCl9oNf}MVFHP>0k`x<@p=yqR zOw3$;dPOE0=aM#DH4v&J7=lAmltCkV8F~>}0TU-VbAZm3z+?c=tF=eJAnix42V;L` zBYvs1&YtcQ1uiLeb zqqhzDE~EN(JAny0*m z0X7Y=GA`|r$9K5}H`UD?O0|{_9&Da>$8FL^G5#OsOu2jyX<@~M zh?Od8(0-$wa|(TVhU9Z8?+dW~1A5yJ=Qf4sJrGHM>yl{97Vu^gMosbpT{4Q8GR01- z*?gl`!>S%pVIsGEnb>r5ujFdts-qm8ap7BE_&Vs6ovx;DAn>6B*ecCyU5H(ktf*?< zSsNTm<4{4(KNgNuGxUUSFMPe*-VXHk@+AeCYg?PnpxZ|s^H!(Q=f7C30Bp`1-Gc0l zWIsXqzk$&f9IufN!7I}$6Nb1SQVb{PNBXrQ;)D4usC8Xr>0)^mXr#Ci;C^-bf$~?fg>io z$nn^V4vB^)5R~D`fcXKSH-lqWbU8qgfg8n zBHr(PcpCb`v@qX+&_WGc8#&${%7j9;x(3JrKkeL0*f!4k*wWdfBpRk~OI)F7|2a_@lJP&P`56vHtum!pk!g>)tnzpD17b-)jF<2I4zRt>g=_tT zd7QX0^=CF z*%JO&tW&Ho(4m8T@E6ohcI_nU$D_epc;!uu=_BguRW9jPoiJzKCT85zupgkg^RJWI z7yO~y{}W>qZEV5aUB#C zGy9fTjlSii+uCPZ8p9Rp%ZIzo?-r{lW(?>%+BKz4tzDWAYJ@alF^hA5`~4QHk9bsh zF4cv5sIMLnR~sx_i!~!6$kSVRbWz?5XuL&laq4Me{H#G^2rUmEcIWEF!dbgu|D;pF z96+udf;=|8V4PSM=V)c3b`HSHqCn&=t;J{QyPDgOZ8dmD;Q~GA9dO9(Id<+;^Rny$8mA#lXrlyLChSA)d z?J~*-b;ut@>i&%e6dBWd7U0|et+wih-tURL>ls)z^!(j*9J$qHSAzpaA7C1p{gTx5 zz2kVX`qQ}e2`WD1-q7$n^W;6lR;wAkJ|3>3;b#xtm7QA7K+#jD9kr_7-DRoNhm zw5N^fBqm^y0VA(FmCA(B95=H^{k_fK`8UFhWR_$v&MzyxW87-@5V1|&+#=;QVaci2 zmP##g*Q-}An_B}*H>1A}OJHNUR8w2IM^?;`klGM3YlhN{7(J$aNLgWt* z^%;ENrCQ#wdmF7*pIZUD4g6Y`3$0T3f_+B1(XvP(-De4XF>LaZ-;P+&?rG#PApeqL)j1Cg&eC3v%Y4p)I8I1viJ8#G^ z(Fhm>0v&0E3+J!i;!k|;_D$=yZuK4Rb<=H8seoSjWqLT6v+0(jhJXC}U*-s}u5%R(}$=K%Iltdx4hOAkj@)=%GFEr^j5CFh5k&u)%P+9J(#y zjo7osDtQq;c1o(_CSlAT-Gh>-gt*mj){M6iU#&wCqXf3%D>t`7rmutwQ%Y9X$6O%q zSJn+wE_HB>}BaV+oL^0w5q+RdJld}rSlDyL9-X~`j*TDe`86vN`q&FO*IXK0PTsS zkEBp6Sj6|loa~{KhO@V&9&))r+Sc~0)hHfF@x{Irc@4pJYIiHlc@3>yza~~5j9s*# z0(o{h+)JjPc0DI+2-PMW z=`UnC>fUhcdW7rJi1A4V&+^@Vf?nDG7CRn1BK*q*&!T_uY(T-<8+y&OSka4SS#W_h z^yhzae^M@DbjMRlv<0Xh?-7=woU}EcXcsfh&BgLaA|E$VpH9i|QgpDG0UoG7<3^HU zU&ByM@`BvWq_}5(fM)ST{F}*NDZj=3G6m+wS$Sr^G=g)46*0m>gd2e^dYq*Idosoia~^*j4}?(i~9u^MAO??+s|+XDy?i{1&U7==#x;Z~0gO{2hvJ z?c7dQZ~4KQYRyrQo_Kk{%8vg{*g^Zj$mEtHSa!{ptD@Pg8aLTvDgRClvIpye9^_Z=cCxO%VFTIz zq%K`VS8U1K(2iY#qm&sugTn&;oq>F~VmLvV z22+bJ(H8SWWKdKJf7pz8o931UjF(E@Vx8|~saekmCJJD`#TNM!$sb$Y#X<_<3UBFL zL-H=p`e2&2K#x9%n+X#0U%+)|JmlH!2Ex!<#z=P%zgje@cEtD~Ghw;O1&apQlnssz zk}0THIq$H~B0=|pdQ94(BU|xnAwlnJ{tz&FIl{Gw-(vq0ZEiWfm#X~hRk-+Xv6G8A zcmA{1j3R-+brzq|d#i`MK$z!uX^2^nxfew8n~qawiMGb~@6C8k5DAhzSlj2l#a=X^ z6VYMQh?rpLl9$yCHXN7xhA$j4>POB7^4j zOC|j_B5&mdY{{Ab7CTH03_iLZQ*(}*UhxwdPErb}Rn86OUo9&NZ4O2^SQA$K?hX_d zt$Ww$nc|7U{7H#SP}i(zGj{%R+bgK$}UKrmlt7KLwVNdm9cU=x0e-BB$U=m=m} z-k^_gXcmLgA?q!*pV4C-;Sh3^50Nvv6M0Ctnd!6p@Ykf}glVl^9rFm^sQ28wW{n0F z#wvYwUcW2A1Kf0P`gkLn!v?M$rjM6haP_YMR=hCfhWdOPA;GVISg|-Mr!7)9Za(j;!=}Q$4ILnKVcrEy`yFbtuj=5V354| z>?0+1jxb1tHKL}9JtFH;H!~Z4O?orqy|bKRY-=~Da)r85TB6y#@sk`xtD?Y?X;IDB z|FG8J%J7Uy5uB)D3bt~#t#t_pLIwL1lN%q+0WB7?LmdddB0u>p$}(MIws{Wh5=?#x zMWLZmr{o_08rJ}>e?NWGd|TTBF_BH9FrC%TD=s)sPs^Q`zCM^jriiO=H8tFDNn;lY zqPuLbbqtjzl+SRaM`kga%7=DXz_=UloV0A4{Hn9Q#O&r!x_(2O{n62m^JpaPC`oFW zKV9*cPoxC4B6V_c7O?&Bu4^6Lm)+yhDgcPCI`%YB~bO^@X0#mRGh z>`L82XZ!Z2+%$9`DWb?1xAa1gE&ama2|=r*TeH6DdG%HRziPLRiNgw=4QDtoVZm~` zxkX#jY%{t*YtiUOs5i#jZ1xSQ!pgsmE?qa*KkxAiwjk1HiC2s^Kwd`(S(LVhIcsXSV2uJHhE+P6p?eHTey) zpAe!p8@GNsPVc}oDY>Uka@CCH)}<0}!@iLwT;7`p6JaZYi&?i$0baJ`g(ZBnpYT@3 z=kJ^H0x47Z(Rq$xK&qblmPs7-$xLc6C1)!~&qs?a-lfAnii`hPThR^*KayFfUC5kC zz!pkB`ZYZi`&^mx<%?r$x}}a_y~9PNmOR(dF6(jy9*~h#R^-rMsWf&Ys#+Ri*U=La z`bkdPB}eL{USM;va1#qd;^**Q9@)OLC+Z3Fz_vmdY8LrVnS1}4^Ex_JWFf6)>F1VL zfRV;_=j3_nkZ4_J6C`j7kaRa0!e>(tQ!@tty&|&Zf)etsQ*U=*lTj)}o9k_+#t{bZ3jnMKmF0(Ct zKp}3dVGqc!iJY}H|mSr!*ld?@-{ z(V)tHfU6jhMp`D@13jbwc3?3b2x0IM&7S<)eNG}buBj`wyLR4Lg76(c>>Je>>Z)mF z_7^j0_Spr?a@zm=)j-G=Mcmo~{8ZH!pdbA9i80-3U?ZWj1sDdSACOmzFgM<)tJ3Ol zHsn*8j%R8G2k&TaS85qw+w5+Mdy^>oOdI2Wad1REc1gXvNa;2u;EKp0oZZ^Zt3Wl!G-`g2u>Yv~H zbyxZ;%=_3+o2o}dyHsn1U{~OkIZvwr8xgDfqN>%*W@~=gV2fK?`FdKrZhkt-@dkv; zwGY1wiJlL4SSJ}8qsSG5A8XnU)s?9cRlq&7!}|y#9&Fz$*DG`0)TV#S7(F`;YNFX! zF;o5)d^?vStS^672;8=_d>XuqW%E!E`06PD37M(vUBbS1$s(BAIcPR@ipGGIrAqnw z4MKt_zUy$kU)B1bzuTZ^NA4C-!jokfZtn>M6&6wFn! zbovhLd6UvIQmTlg!12L{isxw7XHqJ|vwg0*o=m>S9Z%Y|uBX;<*gOI#ntrecG1%2> zIlV5irZ->p9l#L!(}V9O8n${E!$Gt)zOwCnZq`cQ)r%ph0JHyj-CmDsUPEKtfTd)) z1OM13hO>T6w~+rUl2zLsz5VDgF|(Y19jCY!g+74Z37=5kRyinh+)`S$_U}G=&egpA z$%2wq0Qct;TPMH4#nB+GslTQcci4U{&-*CrT$R1lC!5~1EgtYxsi7XcETl8cd~(n% zar%MnTh1oukbkbt3HhFMt=W>Bhn8P7hdN;VV=w?}m+Y)Mvcf4Y^XqmyY{<#sw% z?A!~P$lkcQJ~&jI_+qyrV};sE(07Uy|G2GcU~<6o=bu%xRS~YFfUqHk-YZ3F|J$R_ z#jXu3@g`r_&UT7c`sU)|UdLhlQc9DyV5YI}=bshC{$X0y(NSb(irf@EyT#C{k&c9v zam6=G%dNh9pk_%9IbiE04_BoB4Cnk%WT=tRQkde~ReAVW$+%g7&;J5rdxsuO&0k)o zt!;UQx*1dIM=$FlmWVlNe(=zxVk(9>4G3z}Vik`+i;5^}NX1s}O^qrd5al;cpka z_cMs`A*X&UUBnd&kqwXe=Rz=Ja=|2*gn>q zv+bgrp>)(+;4)<0EDhWvCy$K$Fn!JM=B;#9E=M)|(Yay7Z8mi*eh)8cUqcJe^bK2p zgOAfWd#k!lGTH{aXAHNhkkkKi+1F#^cKGQ~VIf`AaU|5{kC8aF%XwW$oV6=EA8lgm zZl+BD`>=_taB z%=Xo+P`K!bi1p}dj>yk^9z<%d<+bH~!NkXB6RX3VTWLU-628e#`{gsA5H0zspQh;W zKTD_yR(_HK&Ha1-xIWQ1_s36b-R-lp)iWpBd_(|DH)K%u5-*&(^9syyq=mh>pksHa zX55qN0fx@W)PBiUC{UqF2*8Zli7N>8>Y)Q5wT$oH$-T-_Zm_1=6Q8f5OEcRuNt z?8a4Nl!uk4SK<%$oFU@F=N@&ULAaNM@p%eET9dOMRsV51vwch)E;D0S^expVq0z@v z*}#9aEdiu;YQ}T!$jk5N!i90WDhiR6OCG`80h~{82>zBj^t32S$w)GFw}jfEmTKfi z=1=qfrQ8G^UbC=Aq2u^xvqN)=7MybhVHRl4vuXO;(}_fViryao0)yAgtcTL+rhm3y zGucgpZce5-m^?4_V3Tgac3ndpjtF|^)B;GEdsdB@9krUaF(Xfcmzf&Z-*@5v$=zGfIZ(*Huo`&*dYi~~$qx~YSc8WYb;i5|Yc<2yM zADc0LVb_R~UajWmeA59$sQn6_5wQn)0y0{(gP7*wBkbIww4esJ+dGf(AcE1b#$MTv zLR)ex_8n9r#Bs2LTF+4aOXEH*pI3iroIsSQlAm$~if!E%DFORw9k&ewWH;hA{nHcb z8iQ-a2GsU{Mm4x)C3$BSyEc=}K4OR++FzdEv3?cw#7Cg$n_RPQTP04yRL6`n8Dv4G z7)d~&0xn<}$~C!nKU~W1xvB3XX(K=3x{pY~j-InPSXMRH!eaPPv=1HX-m)WZn+w+8 zefheM$Pf|aR$qJSpkK43`Of^ovzq;R54rxX3#WH0=CLW+K{#n8Wwl@5sHP{+98LG? zK2rIS=`%kTZ7~L!su>p3RzR9>YImC{yuk)^28ySS@o-YL*P-bkZ(UWn)Yb6*EN^V zJJ;s1mb7Evb~XZdirBO@rqSiDD9K3IWp#SEACuxPmpB}?IXXKzOG<-0@Q3WkgDTU; z>Aw4t9+2W%S~jamDPI#XcOJx`mw`0|So`MdLgdBqj+1K<+I5*{ZE5{WFn5!!{?t?a z^Fqg->ajG}%2mL)&7 z)|{vJEmC!FPq>-PZ@PMXVZJ-3zhQJ#_3B`FE8lFSE&S(4e5fdSS6K*lCD-V_(I2e= z&ejgfO3Tnm4sV?lyWkV|9HJ8qX@LX)+FDGao4qi&b0$AaXZXeQrpf17|8nI6bD`he zdLWyFv*q?(tO~IXAJHJG!@PhOfp?T-?wpEv4bT$O*cqpW9ivdH`trQ8?Ou5gO>7y$74*Z6j{0 z5!QDkZe#P>ME>ZGd{3|h*tS-H2eR1qTp}=_<=d}}X}4O8ew6RlEqTCQK3!`yH$m<2 z)VIKu@}0vjgsSYab3@Kngr-vb^%W@e1qv(IMBmg6U^KL@Cq_W>UnfsXdxjW%R zlTyym;hSOJi3PK+ok}`k=Gm$NvF~@CBO^=S|34@KJ{lg!#JAGAOw|vmwn|^eeue$c zZ>+62mEwv;yZd7{loA;MIYO_y&9Ur{yD~P@^KFeSS-QEGY~alSFF?1BAuXJi(e!!8 ziF4o6t!Apbvjc(2XxL$i!HFjo^XFNbGYt*H0hjI?2}&z5D+k(AQeK_b25N4Kzau=` z?-jQs!7Y+q9s}BCXt)i^q0R$ZMm45-u9ip$VbEA>>q>X%`k9ZdZi(LF7B)Pa;7qLsPrtfE3 zZ>lPOXwo>3TjGeej&tyq$cnM`Fg6fngcD{w82a^}z~Jt0F~xt)Ye*GT2F4I0dh?&Z zkA^L_ZdmJ+$nTg9HD8$#qIP@TnfIF)VS8CAZk|vOXd96OM)-h#=#&}P&)dCOCr86T zxhE#7N2MqboA*58jA~sO!eF@4J8>lJsl9+iUXW9lxNJftlho^XaQLRu3sPm%~%)bU}Tb4)mX#q1J>@5liz2 zE^yh=o(^M$XNuo*tg)4`o`G2BO;zQ=B&Z&g$|m^tnyk-`Bm!K3 zyK(-vR$BC*XeEqKIycZKOMFwPzM>wERXY&AQ&^2>N}3$h`q+Jep)Mt$jA`COHwpoHib-m5r9^Y&O~MhCtAL2-0#CBnd${TnRm+HGjDeUBjVEB^S=VK zpheSJAvw_Z?JC6d(xFD?HSbhahMMtZUfAF8oYzN{e#q&b4ecet!B9^ZOhl{ZGq>YO zJgRFcO(_6LCJ2Ex$&OSO&0d@&MS#*%^K}4rkE8(^{?%`W6`DuY7Y5 zjVANH#;vOoo=@8FO1Gtw!L8e4S$p-ZRuo$3CTQD2jqd3^6$GtJQYu_ksIpiOt1VzD z`^qRIo9z0b8$$^RX7lsMwC~Nm1$GYE|1?@9t+=3q-kI)O);PK?3%nX@0-H_5 z+J|J?!%&j!66EuU1nc@nr7jc;S1DZGu)(6q-I|x~DA)}PHb?^Q6sOWr8G9$2@PK9b zUW$ZUViDJQd}dWLhY0Z!%{;MS%_9i{nrbp&EMpGuD$VPXQ94JV=Im)Cp?7Pd+7VpS zyBlUl6frJ6`lGd#c5{93jM6`rBuV{Yi5+F9H$Q1Spt#>3URgWVw~!k(1M;-j0QV#9 zI)ujdO({}5ss?7UQ05&Rr(}JHve+9Af6phFk0mh`b&~0{ez`YqS z86Xz;vNC%#KXhY$v}|V@(8AE>(fI_DUNp(aVRBKeC(Ie;o!q>he{hEWAHwFPW0m0- z8MmyoZOPexVAi!*ODE%T%}52p z8g7x(#N>~fE^S^65scZVR-$8FvXSXOm~eD>#(N1W%kkg|d_%<;5GiQ)+l}08<<(hL zPWE%($iPobjMfUBqG|iF4^29}Sr^VC=<4|_?*H}O7LRZ?1v~6KzYo4Xa)y`mllK8S zx+-W8oTk~aYrDgJf@Ri=oL=jGq~qB90C-q}&a7%(DC7J^W^&~&Mp#~`!ICX*-r*gX|M{Uce?W;ZPqkM%6}{(Fu)>m5C%ex{}*RiYvUrf zT`Zh!uKV!}uoJND_G=J#ZV%MWaOiGF+CbFclnyeslO6Y;ico(gQA!Z8SsCzSJBVi= zXaqoHU&DgkZ)29IjOYz-Kw{pcmQY*usYmK1JFKdZ(m>~XAfD_+>O<8=oR5{KF17H* zlFqv%?W%O>ZTo|u?sH`a*-%=0YY~|N0{Vu<4IX#|%($%MfeS)VG@muTmvDsj)h9r5 ztC~|DIN8y^!f<-gG}vB+O=8W?2Gu0t>auU_r<2<`?9D|J$onHryBt11fhxd&W*n>7 zr0=JuQSg)$X|2m4a)~uB{UY0?h4PmHW=Hk}YdoJN$0fOBtEfL(lXm2Mu&a(!Yss@iXuX&d|DUD{q& zJBQdkU=SclPpo$o%y)D0xH+O}tT4zKJ)(Uqb+`{Lf++wtd0G^}Dm={9`LaDBYVm!R zU4S-@j0+c;c}V5dj92uQ2AN{n1$7F|Di_&V9z*|feR!0hgI=u=|NXuLU<=EF=ip%sXwj_tjgu%o7Lt~2!U zod6G3Gun@^VC89U2FHx-A2tB*OsEy4~I9ZJ@mcoTD|B>{k1xlF7py%43V)zBUN&8Y^DPCE~n?AUJcRm17Xk z@LRJ`ac*bw>TDXYBgQ(u3kJI_I~Hx+Apxi3=)aeGW;5{iw}!5d40F-`Z6P{Q0D+Xl zU}o%42ye)fr^xfLOO^j}37Ln#Y-fkp$@{4$X~|D8G1681zzw5kt=5zNO8{*9d|;3P zV*hT72{Gn2W*Y1cB>ZNHlEe^B1b7)?j z((gJGO5%ft#%zX;EjinXT*&L^o?QLyRjNS084eSfrdzG5a?}ChxH1KFC4Xy@?|D@? zyfS$Qi%4N7MOf#rsQH9@7NlD1vxrSPv^C55MsLroTZk|q<@5D!q>l1|W$zybl~QXH zc^TUBjJ>MykW(X&;N9jF4zLfJ;$KVlolIjHn;d^H%*pz%AiM^htTS^LC8b^`+t#S0 zq}qbA)T~elxr@IV1sy*!Ds68lsZKFL z`M^<``e8q}=?>O=uWjkJ_WcI1jHpQUJ@Eu^cG$H2sfPY~&STFT1TRk=~2vDtr*i3+dJ&}hf z1*H}9XRc~*I^lk0YcNgV4Qx#4qLF9i$WbFs#%*KH1pks*|EQVX{Lr=;hxoG}jo(aP zJumh)ov)Q*Ck(umOtYz}O$GJJ?-x|$*s!? zsp`6kAoFDXBe6yZwIu^_j9ozFQfzAx3Kyi ztRw?<9FX{*YC}YJZI`sg>D8NU2xQ0)Vh!VYfNn&@nc=Ovmm$KU<}{TUI}Cx$5FJ}` zNU+um@M>NQsy3I7rmspkX~sDP7~FEGI^Sv2H}G~~c;~2rf4Y6E7kXQSr?GF$|D7b~ z{91kZ8be-RI4A{uR2U4mL^thcco!$iV&u5aG)^{9i z2Lss49+#zGkDZ9|j{x^=;?XK$o;Dl8;`axtu7~zK+Nm4Tu58LMe<-fM)j;QfkZ$gX zrksoSSI>;9n9FsQF9()qDjr1rIJ&+1E`@v`H6PdblNA|xrTO*x2&S*0-snn%OOnQJ z?Wib8dh~F%ZB4U$A;ol9^}bZI&80ihemyG8PZJW@cnyJhd>RKFG-Xb+1wg2lCa-?knp(}`t9~dIY zi_fQmZd14?%T|LUuSG}H1^oaV4kf`8ej%7R`-}_%!|aEi#Lc_sG`N=6Ovdp(bXB)5 zvXgDo`+vFQ+|Huks1Ky-3eB~_8OCvkyx!AAK6mQSZ43T+F}6C-bkO-~8GG6V_Avyd z2F2J9kyTOHBH;gUPxdIw{|84KUh9Aj)f5S ze^Qe)EKp*|@{x65^F#|G7qLI_1xb(~UG^L2m%sFj8KjMT4mz0U&6lFz;3lQ@eNLYh zl>?Bsz4di+e*NzCJMJcZqfnacP2taqgFVl~SF*}NmY5JR=#HBiI^ScoSyR!XEz)bv zcF-;sNXBkLOl%48>-=pvbp zu>Hd1ObvGlp1=LRH8HJBlJz92hYB3ce;Q4(Mh1s;ujSjtR!{I#>^t3oaE^uV(N7nQ zM?~;$q0KezzdBmXMCy6ypg$Xof{JF!v#!$@m5de_=JSGj$F6|rx67t`1@D#3IO?yp zpx`j4fPs3^H#K3@r4so9$-dOv*QOs=?x!$)yEa~Uyw_>-DqqU3v^N2fPBalF>l@g+ zNzf}^OTShPe4Wipe(1EAy9i)mNnQ?c zLzGd7JC%bMeoed`I(u83oVBAVY$r1q8FtMN(bPQYW!s1ixiOcPlSdn9h%#DMtAVKi zOymm3%3&z6y;oM_e)I)pa*3#U$prV5w0s$w#2FcYBC|^e1N>LvgV3+jhV!VQ0Nc@+ zk@N-wp~=rwNAd3VG~eRnqk}G)zk-}hf-&cXKquGeB99X>#No}m(i>r0N}BGL#xNC9 z6!G{JpD1IZBuTRy(w2i__F@87z`NIEb#T^2+Dp15@q2MslWc2s#*_PXKTOikMtx)| zefjeVH2l!~$5G5E>?$8ibwQC(g6Ti)KCAqy>w54i;>=d0;5&D~W!N!-z7MrcqT~^U zJ_#W?l4Z6x>#+}fcm*;v`3TKQUa_*Lrc=n1B_6*YalTiL?`|IWK(yTv2N@J22-ZJc zR%g!i?y)@01u)Tm@9n6Z-49Zglla5-G`2&05Ju3RU)OH?VG6y*Y01Wa0%&kR%-4ep!8?ZV;EGY{AZdpwkWx(asv)`!HtZ7t%bYYJ31S2QhwH zdLR)`2Ta$?*Lp`wfoIZrNlkNrq3%%Z)1Ef?SO1jYpMBO@+kFhsX76SZ!&rKlKjw}1 z%_5G1>2F$|@yZ{WrOp1*fKockZGm+c8WHM1xMIl!}Oo9XHTibuG5%%9Ck7d{Bjz0H#h{9aYMvTtCL ztSsACg>%1rIwS3ctOH0hNuriZIlTp&-t^Gbi<#Ismhvfii!B^3L zm*1#Q)tJ@Hgyx3I=x$6KA1ZCx@UXdSER9lBK}X9$Mo;hdNHgz==x zdg?=%c)vSKIL605pcx>O-Kkbfqi0FPX4qh}=3qCW^4CHrcyA=D=z{@6>8iGU)3)!n{*dl&Q3I$r+QqsFW1 z{OPZDYYUKX&4NMq5GOG0Im!FZI)oOYB z<`U`a!!7TlD&;RHojk>S9g#GCFl#e?9g`9&QQ{<#wgh=CbrHYq^|^45PnuuOX;OW# zb5z+kYb?XQ>pOYFs`lmfDy9t)gMxM=Ou#`dp@JH5|j!zKC=YoJP%tNG)mY zv~7@g#{vQ~wIMbkb6H0OQ-MM>9o>v@eaeGDlaNtt1`kD25-?{w~(+rqC z(02XFF=lZB0*7M)9V5Oyp!5e;OfdiB`dEJc^F!-nvi@_89vEw~m@y{U0Oo$*-aB z9l~n92RF*8R4iP_Sgwy$(~Cxyeoa$ zYu{#D6Q~A|EAco7oS30Nj9JpLg;zW!dXfdtt4H4P!tYq!?x229kP@~`a~K)?1#v5w zmkIW20z~hovfSwFEu(c;A-~41m0c`bOt~?(AxTc8{>51T7R)<~3C$36 z@!Tn*=I739cEtQFd#-yXOCQTE&NHsJX za4Xw?Vz)y#g4caqLud1QIuaRq8ct=r=Q27cX*WV)6qZ@4^M|Oa7te!!*S>SPt@Eav z9atAM>B+8CA=}$_jFi#3BnfqS1y=Vjs7sqFMf(8tb>nwPy-R9o!Jq5;TO|#^;&o9| zNj3wxl&%JusO->i|H^j#sbP&m<6=(_C0I0>H=Pf;8PyA{=jVZ`gGxkU3=RzVbXW!_ zT2pVyd1P7-vaq&Flw`}4@8IlV(nSdUsIP_terw!38`Vy57F1q~-!9)2QKd-`+mjn= zN7R0X0T8Ne{y|r(=f8+HUSOH22W5qp4(}b*a22 z;PZ<&u;;paboL~`vJp_d6^mVI8FygFG3?mPF2oqL%V`k@MF)0H(d5Y7LNCpIots>p z?Qy^u$~8O23d?Fa&ZX3{=A;|`9Os#?25CD=0p(y>MO^z;>FX&QuT-pUGGPDZpx%x7 z3Av|DzIj~|{dx_2w{Zfh>tm3T9fSIh&(mNi?B4tRU#`1lFqWx9SM+nJ%Cyt)zBf+d ztc1V5>Alqx;cdneO7|N%iv^t>o2bATSCEuIHQWAM%Gq#XJKJmef)OVBZ-tX0EDjST znx)oIB81&1mtsa}zc`TeykSuk&V7fU7NE}0HCOWsfj*h^-n5Y zxI2}M@YWuOH7vR(>VT2Y(_(-A`KEwq>{mi=iZ7Xff7W*=_+tg%c159`&59?g4W^{a zTGqy5Mv;EvDkL`u{4@tCMdJOOseK`0JHhfIXY}pV#Sde44?-OKmyf5o!+v%}TBpbC ztyls(G%I}gJZTX7TlOP!d!~wd2a7Rs^Ymc#i_a~?w#p@NJr!p^{XMJ>EP!#4av26oxN9e`%8dS~nu_wpri>>uhxBBPveRq6H z?STZ{KM5Pva9r)K`Lefw(-JC^>ImT=6f{vbcWb}CP{U|t`5k*wdE3p4vTM9aG7C9H zQu&Oc#MtQD7YB~P8%A@@lnDJLX%X^5i2Rgr1F9rseI-TfaB z2wM&F%TU1u9RU6wALfZ}wON$Lr7hD$sq$fi1z-Ds?Uwc5hl~0VT`?o1*N!(>C)!qa z8Y}z6Q$q9d6_1sPPbOOIeP~IYb$Qj}2a}gfcWyFT#5jKPQfIaYIk_`bw-}EI{enS@Eb$W0j1T=PnHsdhEk;it(z7)h}SHupV)>fMx1r*WW-hiT7~MOt(GLVbnQ) zI7*8dKT%`mKDGhSM)(-+XR7&1`MoMuvKW4Yh=!)&R?8$_+47ntSr>h7?zA+c(+r4{ z-1hyE%0i{61pK#Yt3D03^!%$rbiD$vwcBXZzg#4IrZuxW}ETwyFKYJ-G0Ryl~plXjC00 z*kv!jRcSD(z0&CdYSXnSz5+cA#<43d)Ejyx)0R(DyUb>Yfx=Q1Z9DCZ^nC1A5Sqwf7Ix{no$}sX9@V z^@LCDi+bhNVe>|IfrwGEgAYT>gm~rUlzRVWRve7vIw$xR?qedRyDggyPYvT&Kb*?x z89wLzbziwhf5lSfwi|M`Z^cX*l46Spd!O#Mq_HN z(@-(rIF|2W^6OWp#pS8w1W5YA?#~fmu>CekI(pa=n0-bfWgS;c&eVdmE}aBR<>?2F zW(Kf~jH8twWkoQ3_Tj|(7WJJeQ=q8gWEt|so~&P31`f;9w$_Ua6_@|vOyipevC_kt98 zdKCkrYsV}ca*uV)osMc2m9TOA8fdB)k+tvq3QGKWU@Rj88fF|-<67uWaODdHf<-uP zJ9Bu-bTwX$2hnbj#v;-xZOmH)Me;>giJ=qHNLPyGP>(cykL_U#ROHBM`J6Z&Mf2ulCqX{Ygqf3@Ee zrkDXEVm2)w<1i4Ww=GB+0+br;Ph48Wo^MVIRYAvkoT~&Zc9xR>um1~>#X(#IWQdLq zJNNp;0WzYm?2>!m1V%=5j%v!p{FI>=d?tUUDUDhEt$vPdSDu{)A&YYj5Om*!5&_*2 zOXgf#>(pDK1RMXCX{v~-Q3J%KMa~_>!C>9#Kt=YO@cjt(tnK*9DqeX#Oo2Ur`TwKV z#$O5J9${w6PJmPH!7^am7ExX34@bQXfb6997;1)DtdWlj)qBaVIEnD0T?Og01ct}N zT8EG6Y##sh1M;#OkON=F(EU*C@-)##+IyYV*RDW1$2n3)0S5xi>e1@p%iT_l|+r8_|xo%Uwb%Rj$Z!`_c#9U=sVV{uFwK&5f zvS~uumxt>Jw@^$+g1Qckd?1JzUUfcnFfIEcbReV85pMpkDZM7vV*fn?XT#wJ*4L-3 z;t?x7=V^4{y}8)B|C#{QNaYhz;Qta$ZZTjI&)|_Wpp%sWE4KNj#9T@gO^p-*2-85C zWw$ht)M-d|_Yze`{Iaxg9}L1QT2UEhwppSNWM5*U@SEm9bR0IQ7rnV@ew*Z{R3v!p znB*)jkWEVRm#!Ni`>f-)gvTcxtGc4_bn{iStJF3&ZMFnB4)e4KR6U!9Bc=6gegr5C z2jC97Oz58wa*L0kApU(MA|kII1ti?M&7oHFf}viU=6{|R*GBo^>Xgm z&1f~%{i$nrTuon|w#+D9*0hO2D`;})N)KeG$$y{cVW`o`*6b`RGxj3WXU16RU#<&) zatIx5`@k&c@(>KvjSaO349ed`&{S5qsRJ8VvSa*Z=vJI->6ZGA?aIfZM3V{)r}e6MvX@Gd?x>4~`&=~{;3m*Oj1tFzBPexv>-(`5aL*)cuGo8s zLWgB6vBq(2!x@~z@}maA7o`p7&B*VX4g#+ry5E`-I1c{gj(zHGv3HjYw{zAfKR3aa zvkXY(yUXtuXidDG{pa4{7DHILX2!Z-Pa#>7ma!+DxcM!1ecmvku;&G1qGeV-o3~$y;%L~p8WyUN(H+ivZQV!z;fgZN9Ql?6nD~N{ zofz0m^dc-X6TWd|z?(T|JX^MM`LVPA^9o26qXAjx5V=>|SM}@pZ~4`%?xfV}Q3q1b z&{tmDwsg|SQgOp{qTDo~N!~f%% zXf2;1;hXzG(*AH1P)W+vi9pH$`bK7L~QdqIX{5y z+cxRq22??NlJ`S7MOmpce~x?_B02eHAA4^kEoKJZ75#-E_EU@%f_ZIp2{7 z3A7C&9vZO)z#?OnZhD7Gq=ajBtTu)thLe21xJaF;j>kvBC64Y1jV%O)!y5M+q@!us zh>YLdOf$lXXtfEqR3k?Yq5g=RYedox{J`@2H65f)u&^(sr_wLfU}{e-Ov!D(o;!i> z#J@SLty7&!V`unInGU|4Haj`L-(fNA{OCa8XI&>P0fCV$03{&5`3)ccmAhB zk0t()!ATuc?L87^x3+oA>XIYPM?>(uzEgQT=&9Ojk+1WNnrb(Vq}yT^sfL;c+`17> zhdDLDA`?=cG5J&n15fgTrWQVXzY2rg&xn6xHPJp@6gCLiZaz;@#| z#MvXhLSH+cx3wzvZ}4%$(K(Tb;6R%rrbDxJirG;N`!gC5hi~M>rSo`&%xg!QzJxfs z?JOjD{_W8ss1`>8c?3+fpFexSp!xCPvPm0fRR52dO=7)-s9Gc)_>Q-dolT-P2p3 zw;%x3$ImXDB_pP%?H7OauJrkWv02oZ5H=aXr$|3C5FM>T|MpY(AW+Ov*nRcTjDBQ8 zH0I7kAGHYNvnt7m?a8^6`}YgnJv}^E$=S=K=ukObx;eT!?^(LH#R0f&ak+y>O z;<#O_LLgx2>xc`|#ucCkHRwzo1`HX<@%uXm)?(G;bB&=Hg$;+`;z8`4NJ~;_zZxn8 zYb{S`6^nXk(v3buzCOs$$OT9aL(rC9V^ryX<#Y`pv~{s4721?4kr}#Z~I%Y zEaUMViSFcd20Q}@6sKXBsy-nPv9V|LwBmu3oQoKzZLYv?Q&Ow(LG=%g=*{-KbthBY zLnvpPvO6}j`5|qHaLouyo5G$64=?f_U@1pQ0LE44gvc}fSafVH=Bh{V{IYc{S!h{& zQLK4=+`(Y6kH|tZTOU_Zc9(hcnssqej|bQt5L^(Y>iI)QTrxTGv{wL6@)k}>8E`pN zVZG{RoC2(`9g)d})rmn@oI|eOQ~MsBonxgvX6(hYc}XI~6@WQknEkO35Z~^1PC06r z)#Jf5))$59lAHoeZ0vSbYeIT3DVN9trYzUwQVODBT6DCiwZpbftwGud3#DemVF#DC zo3p(xSbG9lUe3u&(rln+=~DkW&=Xu}&c9qCDG44Ol}B!)*@<0QUAx9gjZhC1*d9Lh z?d_K>o#18OW4Cm1i9r8PzAHhJ{M(9I&m2>zD;x`T7!)Iw4SutfqS=l#CoOf0Dh?D9&%ceSYU>WB~o|OAe04 z0hl2V9|3sn(c}8GUfG;^Ro+^1$is(>v~&;Smr_#;fu}@1mbAs*a1Vv5K|R9;p6inJ z5~3d(g$Tj702)Cj;7ap#5X*NQWSrnwmV7>MA7;m=NM>hdY}_Smb!aZyFLrC+U@07S zd+(JqXLRL0hqHdcQ-*>}Fs+eGBmq?RCM5apGS)rnl47?hesy}@GqK1KXV#Y27Fc`# z;sf~Yznt|Y$Us?E-+0uN@sjk*FN0DDNu|N9W3!c(9VXSa6?L~AqvZ)Ob&X^cm3LehIoO= zLY)s6mB{H&vSIw9n_y$j^17ldH4mdA&K0lN)@@YUqWGqpP^9IzNpV$~wJKa>fLvSS z{XW;QHtfd5*XQwTPdE8@Pkus=Uv+HeJZ@%ncsxvYfShG7WGo2)LS8<*fSsm9?!U0; zAl?2=*Xx&Nn-_oo&pfo76Z*YlO4K*V=Q0AL(m{p`^p|bmmkX4bD~1x9CX6E5LS35V z_sV)$v**T_IA*~5c>_fQjC;yBu}LD0qPM`9I+2DPW|Xaj5G|h&Q1DX ze&Dv9v+NZ)sKiW+p0t`9H;SL1)h_)a(vDp?BLIRKxJcK0^9fGG#r8iH5)x78SgxRD z{9@z$9%7R`d?ZlMur%QwuCpIY1dhYG;^VfRZ1JNVL-}5;xK(9AwV{)CvM++hILEq; zqP?{I8A=Wgv-8sre5S;f=_zBRlp1aYM zEWB^;I&7)ydHJs^TAzUy*TC&0!?Lch=7MKvgXw)ci4+MB*+63hg{VlDW#}1VaAR}@ zWJ3dy>oie(A%LN98+###ed5^Z40!(1=}dAu$<4SJ(tAu>=r534evNT}a@DQ+Yyeb0 z&;X$(opeo(-Z)q>LWoY=3FvKlM$@z_Jd)jS4eI3uhV_+hv|uOp36l&va`UoxrhLby zROoiqF#wqXkSJ11-hAL~%dloTFW0k* z^F;C3Wq7xyq+W$7euNp8Dpvj3-D0FpeT`%-<+Vn=boe-_UG3pm-`;q%oTP6-0Kjs) zo&conT>pIAKUGz*nUdz}6o;N_ikDAUT(55%={3!{GP^Z_|66xsicrq&a%}%DIy=Vl0Wdt`L3;+Y(~BePisYxpmbtyV17P4Y?pZHjO(h^ z9{rlpLW4t<|IGJnFUS0_&BwPTI9KdQy3-5cS8Y-F_z>g7PdkS0Ow6;VgY5Vjz5Yd_ zIFvn(Jlm{4&#F)Yxz*UDUO~E-G#e?sp{#B-1AXWHI~%<vSg0k&^vZ3SSm_?;mH{JO;YXZ`vn+`F`x03YL7c_d|vn+14YBAcs1hTAg!w z*z^N4byZW{DO{|z*j~?;aFadw*Fg=ycXQi6 zA}Dd(L60v(@~UKbZl>dWB-|>f3HTFS{aRM2RC1#m^za|$a3}wFjX|;|d$G*ci&t_s zdVR}6D!ZN##>8>;jV&F_ogy{_}c%XPjD*s=MP`EX$gSE53?B$5lleVcJCYbbT@ zVWtit&-MO{#o2JJ1;@6u#lAm=qLm-^px)TiF)0!m^uH?W20QNLC`g^lanGt}?bXk- zZwTn`fsIkjBvYPqf+7>=5}>Ll@27}Cz)Y<{FN*0>XMToc4b`r_lWZj6$LgUn?*FRa zR6pT(5;VVEtkjW?xeB@@2=-!m+BV>6a9!+Boze;ZFFB?-&gykh*D4x&eY0O%K#gRs8M2` z!tnxyyeuuk@?x+XCOF3aj`MwN|8R}kJl)#<+yz1<%hoK_gLzWjYC$bxf4>ajiLR0^ z`DWINrBo;;)Qc)V6G~XF5qp1e#ZO$B!mMDN2jt9b@g?;FMRb z->5$pwvHCgw1i~CW+?R3Irr0oZ5{%ldG{Nho2UttrBV&a3Ra%vrEo+i*H>y5m&e2? znNk$DL((4JsYv{okJ9HEFtMGGe^*Z=Hnhq>X^S7opS@n?GQgbPz4x(Xv`gaq%3|_9 zM99UtBVsOxT(egsP4^d9GTd$yZTm5NeBwdod6rK~D%HZ@w|--$aF#ET`1(a)Q2av7 z^?}rbqRzsr9+#XIrBknhZyL_pJP&Y;{x)jTtZ<M`(DY?fbk73#&gi9YVhumm>JW zAnv&(89yh`+&Hy92H80Y<$=GzsinCicSv6c$$BV&S~ z2SW0iUOH`HnLZaRWdC$KP#!x_(D7@n1@T^ILM6TCdDR)Z_r$+kiyykx&GL}r3ydV` zihszRqfzx33bUd5+fGD4)~`{LsGuOt+?xW(*;kbP8G_4X{><=&7lO$FMprzbnGlOX zs(>fhO=QmWyBcONE746!nkdLjGsKHYZ!R{RJj1eVh187uEon_z$j`06yPk68kC!ic zHKax>B?etu;|i1-2jvo5E0>pcj+#kDqTxJJ+C<3`rEJT~`ePz|ehRrwe_&bhHg@{0 zj~jZjznQ-6x$4^Dwu2D>613GO^-vI@p$I?NGEdTp`T8Lx$4tyH!<<5n!YcxGu#J6! zn{X0k%6fg`RLp;DKQHk|Zl(V?J*F!u6|yJ1_m$R#mEP2Dux~ZKEQke@{hF_u zV6hG&rg}ht^#?nR2#&Fpd=Es2KC%&l<&hujdD;Ax7_=dI2_2-44 zm*B_JysBp_+>rzf7NylAx8n&ik9m3qBhYQ$hDk(~!frch9Ss%Ak@a?$16+ zLoxSTAXQQyD?dTb+|%e+6~?2WgM#Gh$d59rxVvh6>HPi)lW`uNW6ms9N3fHM8E)Uz zG@zx!L-XZujrXr+m)|+AvyRCMgV!@dHGuW4MsNH5s%uq!yck^c5&^~#%0bP;r3s;D z17J%T*c~uNT+3ymG1mEGQ2rz03if;l<2U+Q%>u51LFvBHMO zDZ)02RfIF3~g|Cfti!g^}UA?lu@IsTZ+LVd%#jnz!QCpY!Ag%{m;(cj^lJU`bWLGUiC^=`ZCU7R!e_0%^oX2hHgAq(#wb$F6Xym&p zC;MK3@KV_B0oHI(_#0fKcg5UiKZQ^!maXtP{Xv?ajN+FQ_DQI1P#2yo-c7rt>q_JI z3tBbiNoc!yd|*Gtj;SEDGrWVmA61n2qi?sb9RD-(U#{lRw;eKmGZMf!`kkuexPr=V z(&|unz+I-hSoj04G+e+5%ltN*35(7lvp^v~ndyA*k_qGP7i!|m+*mZcHy0@a|Vl)myzv^(m(Z^37-7C$0o4%5W3m@9hISRZr zoc{6nqkKC}!=Q-1H3hKs3>>+Lv*HE#NMS|(jl!f z&C}vIx7d{%Z6+lSYpvFABt}FS16cU<^GQWT(jB+#aQ>BK({PQt&rQ=3q<#fzEWA7( zrs{S|gHjumN>$7nDABQQDfS@L-mJmK&HMG#H+;5A`A~Q2w0NMKuBwggaUJ)|&{UO9 zrPlYcj)0U4lu)Hu9`)Tw)Y|+VU5(qTPekR*-V;6zP$VlHq<&Bf8cEiec3KL028Qyv^%gY!E3p3nR9zAot;@KnE- zLc&yZWoR*UhJ4N94KK+WSsb^(ar;(^tJKG`gB`h>;N|CO`>Av;Plxo&T++_NCnB!B>aIg6yKX`k{;|E+5+ohoozMcX z>n^L7ysp-)ervHhrep&}K{TPCO9@4%k6qm*9-x^|0+YHNs^wz*hwJU2fu$V`YXrQ! z{p+Gcd-*4>w&lbRNFhg_i9aFgqWos-pW zTDYCoP}M@fA9;Ll?^4*)-pV-0Y&N=H_dTHK35@Azy)|A@ceZHqED@RNl=EP@$qDws+cI;gU!tqXf&{3_1{G5!6?Rc4zrp_c^Hbo}0`gn6A<;q;^lbe3dRgzz| z%Bx%BEzAN5n)DjqqC`h_4D!~X$GtO*Smb#nNsglpc}t|>at0%FA(c*^b9luP94~W1 z*99i^B|fV*2;!M^6IB;pI&srvJG*hW1hQ!iB0xH+LRwd-b_Wq#m6Mc%YAKsYriT6% zlT_v+#&;-?;5%7h=Iqf^rxa?8+H`|$SLa?&ftCF_5I)1c)D`S&#u_gd$cl|F$1W#0 zqVQmSApu6=-jAb#W|P^R_X3dDsQ*&tyNUxN9lq~$2sz*h2K3BtV$$QL#0nn%Tqmcl z34cOgE=FH_&=v!!F4ft2C_+L2Lor=bJ@+!XuP=S;zJz9~sP)399Y4`mMhia*rA;GA zcc;S(!mH!9qmm8&?srL1Sf?q12`9U^86jHc=B!_{{n4*%5zDQ<_5n`idb|25VNQu2X3Oz zX}5s_W3eOf&YD~#o4sI9Hcv|-8z#2ehy5`EPnbJ2_X8FqGxvgftPOHWlqt!le$upr z7(}9m#E-)mP&mzw8l1vQ2I?z(`!5sgYfyC$^j?b+rlsmy_xr}b7%0Ty6`!U@Oti1F zgsH(v2y}8PlAJfu%@ycK7|ce`R7!67-a4w(xPkR`eb6j|{~a z{==vh*7j6r?fR2biw-S2mN{YLE7-k|Eqhgms`@ZEgU4Kp*LxFjn6L@?^EZ{1dbw)z zwCkos)Dg7`2m!xN)~1JTBAV+`XL--g#(|a=)^4Nu&@vvDzNl{I_(Ih@?ZQz>FA;a-C5GQM`1hG)N41+lcSVE^SOZ-w&V^U1hpp3UCr$1(eSnuQS<>Co|B5uWv4V z!IyKx|JVVc>beDljt*|jE;RJJl&oC=i3qnFnBiVxNh_-$DE*;J#qOP#dWcR7>py2K z2GO5XDxOT+5btU&RNH{5#%i z!$^1e-+kKVEbU zwa852j5kEsOe-R-5`icWJi_UFi|A%uKO&Fb4#iKlCjEyG2)r^pZ{^s%SP!mbHkZmR zcmD72cCme@ZNFXo((4h~wMnZ+k1C^N*u5Qr_MU zU(yFH*~Kl@>+R1@y5<@-P%!xoKZ$WUcJ){EdD%v8Knx5 z^^H9_D>UVqs(8mnBX_T8Q}EF6s6l$y$tXtn8}>d%!+Y*$gZc$S)aN}$V3&u%obiv+ z1WwkFmfEIlUP}FTpq+Lr6Q@tdZ`kw^#|OVR3}(zqc+Q?B!ja`+F6t+biE8O-B_Hx=MT$Ky+F z6-}Yn9W@h*fomlnBje5i<5|tVou^-8;y~#Z`tRG11HwRXM|o!B5UivudlzK43de(Q0j(N-0-6AA)<7A1e((`Oz?p3 z;ZNy(>0nq%C#!Icj&mLGI>Ub>3G>*)ovNEmd$C4*%KVK>D9Wp8dJWIe2{KPzdKmS; ze2FAbgAgUMm;sYOJhB8m!Sp_oim=~l92tC}5@BW82T~|SQM>;NMBnYBHZ#&8xNR6j zyVI^A9h#oGATHnx_Zz=1PHblwE#$tcjsX^|D4K*)t(b%~GEk zcEHK(rq(z_$;fyvwKifVGRV9j^^jxNtHGtgm7z=Nh4_AoMGeMIWrh7r zVM!c-=IJ4GsGlT>h^ExNf+X&;(#1|1SH$%^S4l7L@9GIQfAB=X_S_EoCbDbHh|5Yj zE5CfL%G%K{$Jc#lc~XtumO=Y6yFESl3U@WoVb_T2NX z-+@m#K!J&^p5S{|W3i$A8N4j&X(*imy)k$Iikf}3wwW|?UQ#P z^v12ib|k1eYcXJ-7nws$`8MNL>Y)Hj82U~r3cTv5;e!tkVL!Z_a}RfbWP%Rh!%rii zLG^;+`i_K>>O20|B8yfpXxm!75Bb#n5L{cehWF&vh=)YFV_AI@VLEyX`lo)o5^>F* zpZ9mm#)^gASM}zt%>&gB5&-~$3x9DrIo*b&2NY40p-an0DJ=8lEZ&>_Ux{|^XT4?V zJvgk|Vau>NtL}@dAFR8FxB%SG4`POWE~w@;5rv|O6TubhFW{j~0s^39{=Ir?rteL- zJYbSs<2xfEKiGO6uQFKW#6j}Tsyr;YbqzDMzZ06Rj7Ue3fV9r`i1c(r`awz~$EYZ( zf9DL3?hbc~cU}tYv|Th__6H*KM(b2h_qP(vxU76#k(l|p-^-!ovM=pN*1C_1MuP^1 zC?3EI5C=A`L@V-BsFVn^LngN-4YuTOK^n!b+v&5UIZu~1g^ur7Z}=sn@GZ11VYE_j zzQ@VI(*&8usN{*X=O%!DLfbshMZXd(C4;M^?3lIpC!lc#%BA}7FF8vA%zoyQ{Sl|& zPEpFFetO0&9#lQESVF~@>`;DHIeR5H@|0#@?|vrD_VVyROUcPrgo=B`ue~F3yVLXE z2`%Qe*q108MziuzW_gYIW__y;L;zrHj+8Vj46H64PW|Ye5~@Ybmn+5g)3obG(l(|6 z8H1(?%Tu7(6@l|@qQh{hVUCCb%UH7yGp#gz6}{3d=10R8g)_H?2y9j7$HALTL||<8 zt*>kgd$diJr5c*vLx2bud(X;lBny}a5_9%))x9@NNdeuhPHxPF$&o`Mf?^guf zaqc+zmu05=Of-T)hl`vD{F1a@F)7~~+JTXO47Gq(O3W))S##GIYskUNbTz7-^%kNf zc9hF|2BqJ};61s-+baSAazq)Q$ZjGzKl_V7$s-ks$(IrsiG|m#{G5Xg%ki4UuWVO5 zXgWLEGVNbeEd2RS&&;}*F}|rI3kQWRyLrD48xhAX`^vQCz*U!=7*!eZTN#wOJgb>6 z4wSB>J^nA9$4wRv#?#b@^^pcPr`NmuZ{ZR=E>J*{BZic zC&l@X3o9NiDgA=YM_M)c3ge8tx>iQ;Ba0nbeFAq>7o=)~1B(9}_}M&owimINHUTcx zY-lhCHo-1mrLY$|lxyjq`aDp)BeAgEd4q6SYUXRw`Pkk6Fjokg_wv+5x5olj9Jd39 z*r*`(?DWH;405V2#!aj#@!7K;s`#*^f=_?MU)Sx=9I?6dv;0O=5byLWM1`HC_yk?{d6D)teF1~=?*WYW0T^_Y*rJnn_mUaD z{#1_G@bL#2y+R*&h+A5A=EtQAMZ-&Xxi#*=|1OoH%ackUN;75aciv{@++OekZHl;0 z<_L5Ykb~s>>s5A4Fthp%Y(wk^v3yI+^0ie8pa&y1h+>9KR{ipWR5ABy{N=wtOSyh9hLMJ2PW3 z->VzhM+-9!7_tuTvOV*z9=@FO4nZIKFLlkTvqIgaVEUD1^treSVY>&=OPIMURYNwn zUTbx*C#3!tB>{yN^Z7lgmYpr?n#glm*nf2x{;iR};3Uk~Ec3@D2FJjPS9r33d|(3r@gq| zMmUxs^kzoG^(bRJ;h{(WKzIr?z#-LF*B{iU!u8{Mhm+%P!dtcQpmMrj^8G2^t?F+~ z;u`eTl|3R(vs$v{Plik-p~A$;Epsu5-qouj^r=~B{dl2pkTQJI95eY+z{7%}v-oDV zsS1%65$!$BndSaw_3 z&~OG{cz>7A<6zf}l=Dimy|O3D5rVvA?nJUI+mMyYPKKz8mNkG8`;Aup%(ki9JJbw>X- zv1-M{nyfRWSHCS;hl3xD2?m(rZwfjr4Tbm>%gJW1PKfBCI^(cmtSbffrzU<>acR3w z<>Wse7#SF`m6EuEE@?3M=xo+20zLd*Grptu^&OD{LVh|&HhVE!heDUgO zLg%!KBUF}=13pUedUp9f`EL>)vAr>{%J4`_0ly>*`ihEA{`|)#$3c3d`$RI&N4IeG zVuw?X5EiO zeZ)E7A|HFb`YyVvdV&-+y))Q8_i-U8I+Hta8GJvOzI_hhZ7ODuPs7DCMm>VWT-|uW z5Y>78B0g){$MCAN84*KwW~T%$sq~Ao{s7h9YN~uYzR&4+@D7&h@Gm>;S_>2$TP6cD~4+AoO=HQoJD$TV1mbOi5Y;Uh%7s zXYlZuMfB-3z7|iHU<7ok^x+!VbPnOfA;=@Y7*?WCU#9)SxzeRHs5^k8T^b4=LqR@M zSL}J}UfIHfglak)Wknfbwy%QD|Bes+ZAo`{p24Go4GCmfzLdCK>wHfPmh?tnX#SO8 zK!LFA{4M&-%(RsH%|uJYfLCwNoidNW^}5pw0Szh6q|44Yz}zbmX7T+5XPx5{<^z>S zJXph3t$>7nlI`L)Ue@jq>LuITovuhuTo84I^x*+4yv1<5w1Ya(62c`aeCS9^H74C z-T;zLTiz{2Mo$Kmi*{82^EnxNP$q5md2ZKZ^$Fg7#W@ij5>m1#{mQZM*_}^QCR^rb zZ9IY~SKVxci?65$(5L~Y*iN7tdw-iUGvpKYAu5|ups;e6V2@lSrlX3&Rq z7g$fTDEm^QsN1r#&fMp^CPKNCVV@%4$4gm!rF()o&i7QXH)~OcVOGuB2pbK1qR_mY zQDGVsRXDCcKLCys)tvCH^J7(wgjO~%R@ zdVvf6%b$`g#KtC^FgF*Yr|9RZlC96(D3}koq7RQ|Sa4^JY^ogca-7$G(z>aY zBr|xZCh1V~sIRAI41D%K-2teZXTa{V@*d(HK6G>6VDx#s7&P;CMM}*n!VSZBKeDXN zw}u~Ql`d`^NbAHDLk}R|o66)Vw$m>&K4M4;(72pdCN6)aVXbZbWay2}<@v7UdAT=I z^O?&jg6dF-aXY^LhV2)6$E+fTGY1wld!;9)DkZVL{3y?D2qAYC5y9eQ^=Uy69B#j# zdk1ER&a<|N?s`#g^6N1^R2BGV%bpx|zj}a;%i=>B%a>S@Y>o0Mc{Q5VhZx)?X4Q^! zz+tzT2wCc<C>D5Pb4w&)8svKosiuix$8~bpPr4aJIV~;V+b*UL>9-L zO}dRsWN1ra#)^PpiFmX=2RkaIXO`=fikE6{!om+NmHMOBf(Z?|Ipm~reO>fWpY^rd z#A!z2J8daE2-$GeGVbu~RzdE(98q+xWR;K02ta=QV{=p(suWe~rHOg3KhakYGuPCu z3})gw&~*igrL3P*tYes=?MbF?$I(}`&GN>*1)BYt&Y%gfZ1$d7h@I)Yx@ICaRdCruGAiAA=#)A0#aE`b z^#^)Q`PdUsMvow5cb(wy6NVr(%nHn9Y6`A`|;3ykh*lTdhVupi0xMt>c4tMTJWjAO}*Bk$>Ej9L^j>C^v;@ z%Kq92t?J$j9p#c&I0UwzCl_uAevF<>`0-#*>+_~oCIT_5Zk{Y2!7sD#sn3B;{dWId zoWDENLb7m>u^#sqS{jmDXb!W3%W($pj&Q%P>uOK!BHRS8bbVVBjAa zP9p4{2~BmBL#wTm%kLqG%2N)yI~w0zu`%vO0^K+L#Xj8o5EK%BW?{u9=S&!P$Cfth zOg{|aD`dFGd)c9FFm1+#`5^Yy;z{&fG{&!>x64nYFGWVm-xg5*N_f9?@ps8g`!vfJkVYXoohmzn& zbjGlW%wzCN4%%KKpIVX2++c%Rb_5>DK4=3{n?d)%1ah}4a275J5M z5n6kjIMaEm^F{Y(7Z*$QM)d^jPm5igDZi)=Hm*LEG2K2e6sQWnAY7UP%?#qN$8xRm znF3+euJdWWqZdVv)bSU!te^EfE>Z8K<+Y~ex~B~$=f@)S10IaE%LR`CN|HGLh)h z!-XwDGpU>Lhq!~n+y`$D@KJb5Ucyo)^9UVTCk>JO#@c78n;uO#VnOY7JCUvOsp^1& zE+FIE8-PikdQfcnkL^C|4_NQ8t9u{4wNdV3)ZGnAnPCne-AoL?lFf%%>iUam3>lzL zvQS&T1BXbKOw{>&{UdNip`I^}Dx-qjZ*@4}(aa1O*>~sX+y4Y}w&D7wzpA&%AVn}* z_viG!t&^GFQVsOyoTD=yC7Yt_n~&pG_O1ZkS)9!h+Ff6f zsTEi=Qid+7sA+T97X3y2v%t=Zu^FZxCe)VyV-u?bF;AENV=MTTfopYW8ay=rU%mO} z3{&%THaiGvh*{ST}?tml)RgaNr;Es9HMbCX?9eQg~B6l4&+1pZVBF5XPfLQ&|BbFfV;SIgg!=%ztwQvS&kD7nI zVm|i(5ElH;7y0J(H{xp+=(k~p($l1UDDdN)S}EBj7`~%E$%~GoF#>)b5A<(i@#Haa zzV)B_aYqDWDdZN++?~w>)qF&V=?mM~t}_<9L1RBCE-B!h3%j7BNC9ujmo<~dWeAg_O07Vb>$uS|^L}Wkq??^+=$0J(7LN8+94Jz5ceb~CoMio0O z|KFc5e%$DKfwsg1>(8U|CY|B_ro`N{`zfykmr@cWiN$#LqyX??>GlypVwYU^GU5_Q zFumr`+(hykv(v5<>VC8uu$bgcZpu`^lgW)4MfbcWePAG!&BJjWvc3j>FQsXFw*?pG z^6Pv3rqmA@KX>Uz2ELgp751WKY%jv`C}pjWn1#yU9#=W>H`p?!%)2b?i8%!yQiA>6 z87lD~rPpfH_d;x8(A8GEvbCNZWPl(*D;-zR+tyvGga^wD@Y+tO_+HExTZ#Nuoj3FAn`Dh^-N!BfZ=4P&T8qOPtV%$I z^y#RJ6Q4*cll^U-D4=ZN89KR51ZjUSPk#KqQyZG?5yTWfP&YfM%~r`YXkt+;7_QLn zK=i~~n{7N1FVMJEv-f-xK|eF6y6eETQcbbxR(srP-qjuVVeu01`1)HqQgLk?sT6~C z-T!zL99qQhPltdew9>)TIfr&;C5M{{MfN#tZo#f?f5;lyl2KFYDDarHhg^6+}n&2ZnVCarIp^Zk1Di;f9BuC~9B*sUt^gzU2Jgw8KZ1o@8dR`_} z3xFBB(zd<5MV461n=akxboVp4;pLQ<5<8*~Swi|_LKlOIn(lcdG^M*bTf{j!vGz<_ zyyT5CG=FNuA*7^X`UgA5 zc~#hI{U3*dphEu3H%XbMSZs56^3)A@OevY=KUv75y;lm-uX>*cjbFt!eov6BzEuRi`Q%81e~mDf5`_@ z_62yBRM}SH8h#EDO+625zEQCPlgM%Az74G|F@&MM@i(`nH5a;v^v0KRE8?o*EhX)1n0!3|XBDdK(jlFuk6}e^3 zc^uJp8oRNoM{bTTiDoy3sN^WDESl^IlrzkoA@8|Or@sh|Dh*1O>EkvOyRpA_WNd1x zXH3Ni`ZC``8zc3oA9o zGX{THCc$^|vE=>KG&^I~TN9G4F2Y+-CHcA>WoNwl$e{3gg>08U`?{i1EI%*;e=dj+ zR*WdYeu#mF6Z+4>&+ptyK+bDDwUAv9@rAhrLOF0w`pLdS-rtWClk~k6y81E!k&I+s zrn%L=3kNek%4WH=Qq+ENamE$EM{?f1!JC2A zSSr$2FyQ&v9ibOlu6gA8EwB1*7>txstfZK&quZT5fP==oPQm21z8a)0~+l14)w06_y*vR!pHC;)GgRsx$Il zl}U5m_l0EOKDcTLec=4$x9qrG-%zX14%IKn)3oM{mT7fU<(BA~3_*>8IB zx?tSkcB!H!u8Vw%1Jy8WL`~KWqIKcY;rxM&tOqe0DfZqQcTc-Sx9_|-9F^;@bGnVi z_fcUf?sa&>XM^x6{oCIX(X)@1RZG=8<9~-I&IltF z9(p-0WBa<{nnnK&&)EEZ;H%IiYmF>Q55q+QTM`0;w79RZN`ZQFE~iBASf|p%>Az<6 z-^ycdZO>!vi0RG)=!3sPphClu@}QK>+^Dyy4e}?@xFnYjScTy&>FiMN0Dg>R4Cm*B%JJj?FL7@f#Vxg#Rxp^i*!HBV8&hOq~w-opN- z6b%ZMx^MNQa_PhA%&9n8$7gpa_KI1B_3qA6C%fCL-H_4mCs#*hhb1L2X!mWIMXZCoBnjrtD#rS4RH-!bM#du6tD4O$*WtaNw|%( zE8nANy`n*X9z5sx*)=xVGiw^M z{^@CMLp*axF*Mg*p}KA~f7a7?N5MCC`;5?&6Id>7kVPu1Dq}*AW@6q50tDxyHG_5^~PtLReE=qMaF$d0gdWLJm0Be$TwQn7^~4GpF`P4haE)5nCF5D zZ}mfjN-1o7Em70YstjGo4T}-_L3=_u?w`vD!kq(E zFI8bbpYP|epW*|Y(6Jtpr z*5A8rH@(s*{zsDy5~r`+WT$&B)w9*5o#=|aRj1nr3BAOYy=u(Vcv_pIAZXSAAV3~k zT#~jl5Z^U^5Z<5OFulk#MnfuSjN70J#eDSlB?2XFGZABW_~JICR-Vnhdn0*glT z5>lKjLR=k*UWin!^pYxtb9rmPSF;K|0t1OW}t_BSe zcNCFs(n+B`&C?DZ=QbQ^ogc&(;@?ufG^MZ0W=LSS=NbqlBerK$5KGvHV9t%ZXIPhQ zOr?IQT#%MQ2xY1q66sDZzOO&gG^hV)nm2ro(xHX^X%4$OHfj-Xp5#s3mz|=`at`O@ zo5w4RN#668hL>;WS)K?TiGPtAyXYrm-tsJ_OGZiIXnSS3%iQW_8)JU>&M)+%O7RAm zrZc(@P{G&hq#D#+zEJ@R3oG0y^xjU9@CbBC>T8%$>F1N&t86?4y|KQ216f5j-w-_m z-`npSY|$Osii|T5?p}^vCwHlFx`*;)2;R}iD#4x;^@BzN2P}DcgYNWr)nV?Kg6<{K z5Rd7?OJ}!=sxeLGxe18}Q_uI1iBz{z#M!#hYHa^y@uAT`A$d+tO?7j< z*|(la_XL5nw@+CYxEu&9*pf{4(W*h5 zmT^^Cs)thCx0^_-^+4aGl-P~)(eaax9)-;ycee^SKM&WfY|X}g@b!<$!(&P_8|*XI zix{)S)T0n+3s!9Qg0j|AiCZ?bPm|(q85F)~!OZZW%ZqvvOhfb?;wuc>_g7_raXH#e zYk=-q8nK-!U*ovMZ^1Bd9g7~p%-anY^LUiMx4Ds`)I_*DeY;0niYu&v+<8_kNxK%> zsX$g^tvK=BEERB?6Yn^q5FAU3vAR=XF}B-KJF^%9)K={Jh(C^p zdtz;s&Y0wnva>p}0jYOh@Ou%frbg5A37v={F{3>{=V#TOuA*J5-850pbi3)_7Kpt6 zbem2W1EmSGp@K8qjl_-{f>m@qj)P35*4!6T$p|lz`;9Z~@SN0aM7LIQsz(VJQ}y+0 z`?fq9Fi25vO5QGf6PBDS6hY2*#aN4mQl+|NdAvAc6%J>HHCH9D0zce1dZol`_#u8h z%r|k}OJTk_+qdcs9bdG>{Rkku9lnt+pjc8<>vFqOVTLnn+r670H~@{QtVK~J=_X#$ zXH#Z3+h!|_6d%@PsM|#t1kxTC?$v|d>_Db9 zebMd8PAsaiZCN>k;MUZvs6ya1P9H-KH9FQl&(-uk7?EjLzf5sZ%6R9-QNrlQ`3yLE zV$81UE@+sg>{Sy6Bj`vRMLqhC`9*iosj*@crjdq*npgPC@?pG`yj}er-9oX4^ zo86b~-uawz-yE)3q}I*Nz7oAw*bb(u5zhbkc6qFjf5n^aSwbzmYzYf<(9(>gsUE-8 z8kHHO;ClRAc(}b0wlW*jwFuDRK=LbZq*D3wAsL4w`y#;3ch3s?e~avYUlfmr zmdwDf#nKtv8?Y`g0WTTrCzDaqONq1 z4g*M(d}DBdTVi&D5%%9&p_o&git%+VGh04Chqm@RA?FVHH={kYN2)bgwnc zjkG!Hvmrrs-8+AGD`f$CEbG9s)K-@>Y5{VA9GZ`meCW5?3jIvHdi<*YGS4!4)5=IA zFloo)GrN=&`ys!+Xt>g5JvXxOW(Be_{1L|V=ilG$EXk@Zi-?StvPlGdu;m(C=n>vrKhexC;+H1f#nx9GDy^>Xi;g!BS1m0<@1VFoQ{8>L*dA5*kmRkwY zwK()e_f|zxrB?BoM5oJIG`;k+#H*)&^uIzXqB=gf2Ukc`^%L*Qj-nw~7b;h*sh1$`a>ouux30Sp)*EwQVy_>Un^~6)uN}M4 z)S#V>SGjR~sWMsX9BZIe>?j%V=gRSW5L|Nh&=D)o{U-6P%#d4Wx7mvBSu5h$--ZKe z%^l`R*091$J|HTioJ`pCc?QCE?yIFHTBM#X)hY~3AGmnvzxCa zG&X}4hB;A&RS8c7z%4W)+1k11=KR>3mrV({(yPVlBeX3q4)`(Yh_zWU=d+^@w#le>- znG3{zuTxJOc)}lPG?mARN`1k*TOUFk6 zkaSte`12CnqDsHFi&n#&mmwxk^fMz6@-~RnCF0dYv&OC~DubWQc64OL?p>}9!mPQz z9FS>j{J!>>-6p*jYkgvQ5EdU0R26kO;Uj7!X(-sVY1OhS=YcnxSL@2J96k-vpwGY6 zf=N~bo$039XQf|r+~OB=a<1w`4SN4$JCQsp7VZfsZe9fTXWpZlQDJ3&4x zT{Ert_-N~ohSB*kPl^LDm~K}nd$X`E^3(%0L#AfCB@%KaU;DcQBPWlVp=}3g}c0Lf(>a44la zo6yE|n4!+e=FG(j(4dR;ZiV{RSjdLcf)93TC1V#lsC7pocA#%)#?LLxF2D83S&1Oc zrm=FEBVja31&UD5Tx>Gb(OPD|icwuZf8io!_M5*tNG%Y_Ix{vWclHofe-P(Z>~2tM zv#PKvpOUpxQUS+cR-dtS3;PW>W7FEQkQI~Tl z;CalYHuXr&-=u;Fxte~qbdw}^NwFM7^re$di`gM&YO>kzf@gNmcXE6bOWRqFBFDZH z0yk_V={9rHO7&GcuHVrIH$>t#ffV9$VCoNnh~foJ-{(;En5fpDDIqM|4) ziIIwEz=jSDM1R+^;N!rZ(vu8Y9PhIwr1xdU$DNq;)(vb-@Jy_jMB0_tp6`}!t$X}i zB)~#FuAHxD0RQr#tnUuba-p!=Q-T|8KhOI|{OaX^1wq~Bod)nd)nb`Hr@v&tR=89? z4mMf!!G`q{RL&TIi3N=<+}yv zzZ=B%HB&(tvr9B5At#Yf(Uh?@3+pUwztYQ&rBuF)T^IdHcNST9iq>SpobUHn-Ntbl z^@=>+V>tZXxeG@{m7u?iqofcOwlk!_$gU?VJGXD4vk)*LYohDoC)OjVUI-JZZgOJv(Lsvtq1qw!%(6y0k zgKO6d#R!X_Y79?Yn90uZH)sA7ZOF=0$SPQv%_O9ct992pVa%3K6=*l+?1eKQF+$20 z5(ERP;y&K&?a{bs>|S?%+nA#aaN`}~)z*kOj8EZ}PBjDNasFm(OrNJ*FYsv1NyC)W zAC+<&vK~**Y!8%vbf)MDfps5Uw1w?PS1Udm*!sF|*N_+%rtTYS*%US$9Jv?yW?|bg znxd5WmDmsFUT6u7O>yZ&>SbDMg^m{4XL0I!PPL#;G9?crc%ra+(I|2`-uE)b_m48L zB>vqs3@SLO`?4eqNPK`UcA-wV`8HK5l$Muxp%2H}XDTVsZQ+E{ZF*&f=2HK-gS5OU znquSU&N*-CYx)4Mu)LnHKIEW|*l%?o@WI}D6xR(=sMA#;4?7%X++j_n3Qfi>LJ2UTWQ9p=^Lh#zNhhWmE2({}-;LJt4yz&bw z4A&^4Ms;wca+|!V9E1U_8)kxYMd~gtx_-UN4!~ps6l_9_Jf0f<9|ha#9me7CMJx>W zf62Im)G2%Bc}(wD=@eV|3iy6?+Yb$(g}+qXvE2UitBWQ z0Ir+1rs#BUY?s3lSwrpy>u?CAk6p_O8C<~gq!b05Hk+Oo|FT90Zj$R6LZinL2U2dh ze8dkJuM-US2Z1KOPP0Ql0d_2~YBb0l14It(?-!EVnLGabJR}r5B^HX#08wdmD`=v= zeitL8|1H`u)-CZ|%%#w0PL#6?Y{|ZJiw>w6B9s*wjATzy+OoV(KTirJx^D##VBlaH z&C%t17U%r)o#!#!-`KxE=b+#5NoANwleIR_Dx`&N}2B!B9zM%1$Ga?MGk*6)5-}iJU-)TqWd(hX?%zJU|{U zC0tF{ch=d?)KrVJ7%vDgU~``M_6Hvyo*Fb1mMiUhjd2Z08l61TnNZ>?PO@7-_GSX^ z6hb6GDz0NR?{Zi8k}1`oRh2Xw?vr@QYX&JPizbSu$F%E{F79$HWKT~9Mk`oJiV-<{ z>z}V)x3^vQwQH$Q*>g?(PndHt?nt|zIo$b($ATDz(M#ZV)uYrneh2e>KqS1G=MsOx zne;yV{C>aPXIw9%%d;UoU3@D+&>z;Nwe4Acs8gLRx#2*n6s?-6;)_ix7~yprK~T!c zo51?xMqRX4IrQie;0*-#u>;gt<`){bm+m7 z{M@-N|NV!r#$fs|2vmS5b`(IRe^dr6;e>xQH`=vVLRpsA93~|G?hY)dz%H#DegwVk zSIr6V9gs^Er&DgcCzphmLyC!qIKUS1ALTR`R#XJfQR8WA#XZZ%6x<;>0NpourL5;w*;IM_Em|Iu)g zAzmxs$kv%6JGWVm#D!nKD;Y_>x32tp%(PGUPzIa<*c!Vaox(bk;yL_>XM4_uO2$PI zI;g}#8vn!xDTzMdd~~Dr_XTh_#a%DpEo`WGQAPdtPRWp0xH9Hz%JwpnUb5D&%u2Vz zP^rYxs@%U+GBl{BWbjY7b4x|8M(pQRR{`(>a13X4;U|KHRQ|*D-}UZM;ISp103RPe5+jsO!2S)fkNz(->)lXbL1q5HxH4y5$W`w9L-B*B0wHC^2r~QRnsIh_wn`6Gpz*cw(haxg1-jan3a6SD%6y4Xk-=#99u6B#O-T=0?I;TW71=HP}Y7Kj?e;o#>VFVKJOS*k!W_ z1t*%MS+;fgdKuA5v=@-XfST5B3M@4>XI&6mf9?9(V2w1^(Rm3tka>H^5$l>`R?*_0 z9Ip7$9aD^-hx%%j4(wU>P{ts zRirpq-9ETHoCP!X$Ofr@@G+L7bq$YyoE`J} zJgbx}a7cwBjOoqN;Yj1n4E}Fvd$o~^L*eLlv5kbhmFbu`S(%{0!PsGS+-FCTMK68x zg_Iika0z4v_j^H|td0zhLqXZzx)|)U3qf$H!O}jN{@S&wMbp#4-lhVP5qxQAM{A9o z*5-2 zRgL;L z?-w|-+Z_LKwnrrEe(A?UsJJMOS@lMd1)*k3g)Ht0Xs2ZcAn!OA{7NSKL-TSSyl|mZ z>*2DiV&733CmnBD zzd8BG;aDUTPBMng3tVf6lUj@KSXCse!Tr?QG`&PoeJl@S8d<%R&~pN7qhk4S{5~Q= z2o1w;$!ztnJVd_KlJ{aBc!)c3-CepALJ!%RuLO_e?1(u!oC0z?6>@vBw5L}lnSda6 z97R&E92{YKX80A4{Azw0T-pU0S`^mzIcCaTpg7{9ZvUzbGUT-J+P0FyrXFGXVX8z5 z@T|P2GPhXC8K%WAW`a5RI6^Dvi(VFxf zVUpO{P%UP7_tV`R=|WH!vNj!CgkeTqIBA~x)`@IJ99C5)iJzQV?rtf6ra7(b$?jLY z;3W_ceU^>^^}909BUTr4gpR~B3zZ=aM;2?NtX}flmhV)Hsl1nj{$BX{dMZ!!MX%42 z<*|gBm0J${_Nu*ATbj=E82ncDHtL)w^NWUQr_76v$*XAqsU8qjyzjqBMyJc29v#wA z=^59g;?Rf&lQW6FDyNm~#|$4K@~ip@Uzb=m68F0nKrZXCqJ)}phL|r0f{A-ec<96k zr-uyRkce8_-@lbRH;L z?>}FEkF8o3)Hubz77~FAaGw{yt!bHi06ZKNmyuX6O8Jwk-mUfQR>@Zc|4Z^_jDBx! z)KX+~TbHsKi_-lan_S{7U@Zz^Qj)x7d(<$5ptv1HrKVRu$)gk4x^aWSb|NUOnwxzo z^>t$RP)-o&)Ij}njKhgpfpmqKGWbb&Y;Ggm(gS)Fx9{SgHARnf3(vZr3j=na0g()!rP z69Nq=M0$j=nfgSz*XXNLhMae>)E7FvU!U=>-LWTO0Y`qb+7-W3uN+!~pbO}SwfiPI zR6FtJj2rwxzAE84=)wB)v(jeY8d{@K!zK9=K-Q_gV3n@#Mqwjng<@@z(;*&(Gwep+S?A~yP3LeLKFJDxK zajZn#`d$0Pm6{?NA!X>{qUDfuUfgZ*(j7_TI#1rA>*5^z?UZF8(;>mK)-}c=3N{*+ zZaXZQhY9;qczX7?*TH4vP8{h8)2>C7z$V@po9*v~m$lC`ij6%Y7!;`=6=m*dXX?7M z3#3WObMDK>p0~;oM7jrE#B4vj{_FSL4*MS-W`c2mT3gc#&%smhH{Qw3xBdg3yEmlz zW?N&s=j|weaF;Rh)JAu-VcOY96+x_T{?z!xA5?-LKuow0EwNwJ_;zBtYBh891d-|q z$v~+8=CU7547nN~{E{|AO}CLDs1UAf4{`!Ezw*qmy>b5KeqSK37Y+}~Yqc0sVpqx! z0Mb&Q3tQ72JrNPi`BI))oKBlP^{E!ytZhfPASjPbrQ`Bd(Ge*QB(*zM$+f4ORLBB- ztoUWnfr-k`gm*vFpS00!UeHLT(e@CT_ZPa`RPS+jcZeWHFW zoP`wLqcJP&-DSJ)B)F&xv=Q?)?NkdNi&_W$vQYZ1j{}ChAt3>I5W6Y)5f9($ zaV7K(L-!Y#V&@bmS^Gtaf9e4u!momCABij75MG@jp<+OovGe zh;eIHNIn(-nfNVO{-YUt`$Ag#x!rOD*0-M5r8J9s)&Em|tK=8=7k{dm_An(ya^`C4 z+xgLomHTV~b^G#FDL)vSKaZ8*O0NI(>x&;LIjvh9f==9=6X{)lu+MpJka{RT*|(gP z_N}?qHArJzQj)C+I^f}T@-gl;geNb3b3h}2cT#Ss*x(ZD-rn&e;R^(#Z zIv368#@Q>mN^eX35Rrvql3`!mR%z=CC3g@LGq1ozsnE;zaP}0Z1!KpiHf%oBSPJ`UDB{+{Z8vo{QP*x!;{_V ziR7&dNs)AX4^SPhmf*e--|r*JPxxQmwy4@o!i8-BB5#Q+N}N=z!;;J7ssH90Tcau3 zAN6b41$AjW1M-U}YMn(Ry08<^p!RdTDbEclQ#{qa0rS@Vm8g)X^tabsIP|<8o0YlZ z2e@OLSI0?5WlWWhus%28Zi)_G0Y7HV`u3`%QEr|ruS{YrOeGgQa+ zC~HcN^$?V?{|bt+>ojdLF2pyZ#bZ0HoLO=IQ18s8?(?Tv_8dpNIv30IG{jSEvoq%k>tZ}*+N!z!p>dcU#76r(?elj)vh<9U5CeM92R$k=gKt|F$Q z$T3cOhrn)Ye+qjTee^X-$yQN>C(g`btiE2fy*gR?uR)WLl!tskcBaYTu9!&2^P7FW_7XkA;?!*~eC2Er}=VU~lh# zG<6GjC0hEZ!6tvpOD$gCK;cVyQjZXVfj7@A`Dw=Mb7`FLF96Cs|EBue)p!Htjr@;- z-3JSh<%b0#i~?L5shXa{qebha*9s5BEwb&}jA@6iae4k&1zP0+auPWxMQbkhWsa89 zl)+@3r5IkskTA$!O{VwZpiQ%Dc#_z2)GUR!e+c@GE+Kqw$K{=7bNCLMJVZ=N0;j(z zBJy@2;eFEU&fn?L6NN5=!&dCV@>L&rJlQ%8b$S0@DsIOMn`BHEHW_4C43QqM2Gfd- z`V8zipGXUNp`O|~3obQgF1@cARNxi*x~1Y14?Cujx^6Kn6o2o_H+@{s#^Jl#o)TzI zh;g7$Gj80`F(fDvT3+Uv^<`_rqg`=j=3{jZPHU3W%*@K@fX9pzG5qji>MtH2^k#n* zXu1mi=@*J^xU>^IjO;$&?lgJy?UKGP;`yhtS~ES^jvaMp6?|r7hlp4CvuI$F@= z!rSWWB@s((RFl*xlrBEUKlP4ouh>(neR5$)imSB8D-okc|5k4%<>}k@BJ+kAm+q4z zY*Huqe)pWxg>{e5nePoF7)1|0q(KfEtuPOYr^e1DCe6+YJd;?J0Y6A}=U;4^HvRHE z_T?KJi_Ou{Z5~LQxc6!0@Tz|`$gMQ3(gulpkspQ`_Q)FP z)Loo!c`>cq5y%-eCi1ruRb{^S0>_{>(q0!-o4V2YD*USxn`>}mmTJ@9pLh%Zsb=u! zYuCMgDOE3o8bszk*+?LY&18w^)>Te2i{70yi5vmp1^pAY9(|{I1;KB6r>wm`~=9F2?KoxU!1-Q0E)?Qgr%M|sg(7X@nKvGY?YLTN5Nr+d6MCPei zz0b`O?%?)Qat4>hOwXORVGw&h#nb^H0Neo0`p0v4AtKNFw}EKO{1^iPU63R3CzV>P{^)DJHnrESH|0;Fj$Hp7PmkQ+@76@Df#2WE1~E*a|N zzm+gtQ@Z^Khl=a<97KJ(iQ~!4b;jDb7xT8)sdpbC`oh;I!1A{EEc)g}-Nu9a+AlVI+#28u%;&`+nW9JCu7lXVUYWj@%1e++x6 zcQsc+2P0Pxc#{NYsmjpcBadFJ!PE9bY{DmQi%>Z$*zg2hPjc8)+PTM4Ulbi3yKb`F z3v@cEB!-b>$U3uo)LYKM#kF=qm_3$x^R^&|fphE*3m-7eqXxkf4>ky$+u9D!+7BPR+ViHY~ayRD7%m@cStU4!8-cxw`nD^`rK>_4rLxXO@8pN3dtD+KEB z{W)c<>KRZQs}qQTf=H&+xlD9lD7=SY&3D+B{$?ilIY(kdNccBRmb;_649yKg=yyI~ zuWiKjz5z$pp^u(fH{X;NY3cOjv=A!2USOXt#QHW5M9yJe+dG)f+oHv7($y?Bjb=LC zDM)p>z=GBI$Rdlt07K-Y`6&-J{kpUz#NC0@v>%8 zLT#VdaV4A`DmO_L-hQyKGb2xsFW*RYzlBd%qZ|I3Fxry;IY9k=B%W8Df$yr;ZQdg* zS&G4EEy)i0GUP&{6;{vknRqPvRo7ZtM0&8<5J-Q3ER-AzlY`9vsk983+4- zeXL-8a7G*Fi#eS2PUsdZ`=F%9B@Yt8f+EFAgi?*wm`)(EPBG!5FMyeZdu#Lf;IA3a z#U>GFA7?B4rc_XGgP3Ygff~(#EmW?IIwQa$_2$|LM#6CC2B~s{M>*O1#YzidecX#= zLVnSTFoE;9`rIxfO^6)^u3um7{8LMbh4EySF$8MpCUN+dA%{PvOMT=?{T{fj-%9z^ z$v=0{(sVfTLFG$puQ<%RyKGK6dtPExS7bjvJU-YNdg~v}b(u($T%-Rzfd_UZQ}PRh zqYl}x=5bAICFnd`H;`L(?)j943p`4JwLl@}cr$QHlJJHvXo>KS@3f{30>BF35dp*1 zRL=T%4_Rqx86=HEM86P_cSPH(Uk)1-V8GySCUggzYtWbH*n4o<{dRYA;_EeNh*|jW z;0lpVrW)NMT?m23lApVOX1LnD))-;}PoFk7vsMP}Xg%s8@J^30Qy0)T+C@rHi)O^h z*EXzP9pU*@hlnUj5Tlj0j~@Z&Ar>jzBJ#oiV2B;MT>zA7pOZmM zxr}LuRW!3pd2GcNs^LW8YQ-qe)nCDg!{Zaq8fRh%-~tyvl>go|)4G@0^eN?TR8e~^ z$YO zdm|Qu>DAu5Y6X2cp!b|kZy4GwZc~vXR2fWFJu$FS#|$R3$5l;(LdrB>&L_ohtWf3f z2iP%^JM%n$KX9@@j`@-~=C$rdsz_&on;2d+ZGpjO>gpRp&5c7i`39;F#y4rbd|)u% zD3mhnn6~U1qcs2J2p9f4mMK>XV=eWc)t*vxi}DS*D$qIE&{hGO_?F51w<2&x=b_R- zhAvB3THnK7=ZGGJ@x47*&`;hAnGRoqKwpi*cUt+Qk%yKHZM*XQ?@B(V!Z*^sImSQu z{eb1_^_(9GRoq}QJ7K{2cH5!fba{St-}hD?jHtI>X?LQ}?@+bf6(DjUQ$t!V>J<#v z#CCGl2<-YcZ0xeK%)1hMjvntPDZR?atohm|5 zfVDL5x*h*#xYO@HpH7ZdazoAFUG96&Wn_q~Cib}LCX1bCN8KPLA*C+9UTF=YBwvGc zkTh9iDox>>VW6BQB3s*JbohPFa?bIgI(Fi5kylMyK+Es5 zfto_S3`pvcubp|HPE6;9?r0pE&y6E20tHR@?KPXMm!DRSE^)S!f7mt2JO>jc9I_y; z8s~QhNddA(Xz|}=f?Pshv15}nonpj*!$fI64Sd^s!=i<|vXz z2RpATmOw~LUt{h}ftEvPO7sY#e1_V!A3_ym6Wvz#=uQ!zDKQ;PiELh0Cz5$5O#Q zY1y{)RiAOkPF#E*ZJ~x}UBAEx;hDzZ144w>mE(#9@R==gaBwJYL^-O7pd_jp*y)sK z6GPhFX3HA#1-G^&c<@BsJk$(H0DSc&UHL@Gd4o*;)xtEeygs&NF=z2ye0aP28f0dN zZ{8RbFo4HOhLmCBr+1MwW;LoZo62e-|^3^Ds#Ul3|N)CYnE3)edt3_Lj1BEkr{vs zF9u41sQoRiIp7Ap^?vE^FVDYkm!}a?Y`P!!?}th;j9Pd(IOvsUtWeRO%2+ zr4LijC2{RoOH8k(;eT?A>bgLj5`_${4x>*saKrTn3+irO{pLqw%saV_3D~gJwlTgy zk3N%NzN#Vj`iT`&?97{7NqFGLS1&l z-aRLOC`B4BkSCT$9O1}XSp%lIMLkzn56`^xAx_o&2*)JtJCRDqmB1L3+%uEI3CyZ3 z8BF>wwdkn;9XDpuYyDeT$_{ahdZnM_?1~m>mkKQj%rPLA%38#w)6bu#CZH|fdF8(9 zTI=jNb!-GNwgjRq*~*lC)}4%%%C!EZEnXf>bJ*y#YTTeo^poYbKIj7amzyf1@Ri3M zk2x00B;+$BG5&Aosizf!)*i09!{ zKcM(ni=|LXb>Q>(-b#(FpEUvp5`H=7`^mSI6|GP1!~Zl^&i3Qf2a)9DDfr&)8fsQP zL^}r^Kx%UxgS#a6oCF`4uXeh!^s7B+2?l+0UqqQS3oLw-rjGH8TT)Q}uOR~TDS~8X z3ascKP0`PtcKR=e@-dWgJ363YUF~XKkvK@VR5?adLVme$k9r)-fQQe@RT;+xNFKBS zG9;t;{)8{^4nW6r11T>Q%|SfrJjhIHAr0Yx3~=XwRI8a~*Fm9d$9 zp+TodqD4K+xpHLFZof!}*#^D2MD#EIN5j6>a3D@D3|-K8pG#zE#858 z_Rit%ec`{{}4UO9sozE_17c30;K%8vc31Thl(Koc+ zcySL0Hj(o1m0I)9AOTL8z`~Ojvzj%(g6VW{+)u2SUtqYY_$<8{uSV#-<$4hgoGRzmng5g-L%po$LHx#4?H zcn`7m$vazcO%o9mnS{44A=w2Az6N%Z61&0f+1%|5Y01BDLl%%bbZ=xvRX}~fR$L!U zyh|4jW2X))*Sv><$`}5eEl2tJu{=`!6z9o2e3_T`LNosxAcvNYIJs-PjC4$U7z_^?5bdzZ7@%NsnfCVEatjAp^5gxDrvE z{EU(hgi>hcEal8l&DfX0LY3lo(t|{QhVIc~lz8gFg_eM@6K0O-Z`w>*?$_ebS&Wxc z`65c5#z$iDq`*fccA~I^Nhm+Yq}loBb&HB1XPN7h@WZ1~PuD-csCc-4yTQp6CE6E^ zVqGOK$QOC}*$5w~Gkm%~aO0eSm*^0(s4=1<&(Fkz&rp>~W9ptR<(s{xdgZtE++wjH zV5)mW}}fb1uzwPa#2leB=94o5B1kq+g>b zFj5@r%JFCMSKkk)LCeUXF6|hze0fn`NhmqwwxvWZgKxIDF41<_Z{$NsH3U$ z*Z^00u|SzoE$?NQ<%>{(m5b-;fW4d6(LWmUwKb{p+PvPxv+ZR!WyDEfR>~Cb%F*su z|30w~?ZBni8u9RIV&5tAYOMar@M2EO?Pcx~FKhzC$uJ^yFzGsRD zvAKtann#2W?!K56QjAHfVH^6Te#Pe>r=PuL2%nD^r%#c021mT^q1p%~sSt|gUu-mm zjgk-K#hKRtTZPDgvyUZFl~UCb`N{s_7DgVMZm}tNr?;F-Q?pwyl0KWAukMYTXUh&h zRHNB*{Ue=vBljK=`Dxnw-s>VtbQO=v0djZ`#sGcZOa!g{oLc+-eTwTw&HMp|q>0p6 z))Z7!J>JE3oiS7CuOG1hWebBOrK{dvZpiNHuVhqYrrI^u~f_v>d&W}+dBZFC6R zFrIx`vZFE%7uc@PB4Kmv@S~W2Gzsw6>`1g2E6*2zl?Ps|MtQs1z zRqP30tJqYxUbdwWtw287i{~v)qus(3JeTcCmQQ08R-@JT6eU;ziF8Q7WVHK+gB>%l z)^;H2k&mLWif8c|;r*LBmC?D~6STM=*sw9RP}gy!BRXzY-~!n)v$s0^gi;~;RN=CJ zI_J((@a$Ku;-!rD&j!(wGgcL2d4%Jd*OXK$^AgmSSY%U>kfWsTY%cz5yiZ9aho+zF z*rQ0_AgpeitlbX#K?j~ymvpt3oiWGh-&tvfXoZv&W-4~Yz6)E#{t!{SfBuB+Xe*}X z=9FsC+LaZ*<|fE9_^lTEx3M+hH_pA&F0Cm9P$0~oz}HltHo=*oVk;D*ZW!Ho%3zv` zibbx9`Df2QLv>uTBA=QM_`!hVnc8AvV?$E_JGOQum!Qw}x8HoFt6wk6xZX9(u8JtL z_LeM$iBov#+nl^S#69v4iPa$H7QLKAu6zzot=H%4|74pm3dGr_-AR2Cz@!qN zL1P489S`{E*(uqWEO%;f#xu}%_)GA(Mk*~v<9VD1^Fm`XkarZr0`Icw9P<;3>>}t& zKfq;3eURYXlZh}n!;(b-^>lcH8QR5jQExR{H|-8;L*^;$r4s+!uHD7xp(%}(6y=Ui zbbVm?%%&PDQx5T53$3$SjDTJ9SRh->KUW;QgIW z2;+RyXFCP^_#><0D)Bt&L97hkezG&Or&gUmAf^E$a~&Eg81`dR+3?4XNuoE0*_5DWY5s>#{s z_OhGcl=l~BaFT2N?=D~T#bheIP1vCd9E3pE{iT8bv-IVu&~KtL&k8P)^}T4js|_^n zz0vu*Zm2+Jo774n=&u4V0&Jb&+i#OX>Gs#5K2!KG>i|DsK1Lj=_DtYCvWqlF9_yNVvzA{Ad}Kuo!|roqOcAw7zhNh)4#uZ#8;>r+oMz&m zojZmzpXnVrg#sc++P8;$@o~%_p}LOf9u|EMFYc`{T-!cb)Jg<6uT_+lF5^}N^p%_a zXXvlmzVdH&x1fC&&;GLgU?vKsM@vE0Thf1;(6Z*r2_`#WiapyRToi#dJY8M5K7-qU z<*oE%Uh(J(F)aAa5B^|7uL8)`T^k}@I*?gHa$P;>RTIQ;gjf1i$xjzFwScomVuhlE zzkdFOQC(SU;C>(*TiZ}4Ug<9eBf0z?<6Udco!?s3A&MNHptLQrk5F9=h%u&lvmq9` zrJGw9RA;^Jtf%d!kiqDem7S#7vsu-GIkJGXuV8d$50u0I?;p+T#}%ujPndR`yTqEa zu`Q|XGmtKf{z^|SCxS@&&cL3^06Tpo12B8eni@+6d}q9yBClxGC(&O}WUOUc<9Tp+ z&Mhn+SG;1kj@|+;C|STLD1*ZsQ_~C9?G;J!5(hceoMxYEwb|3^L8NO0!4vO-- zywIa}9e)#yQiTXu3UWjQ80UlhwGP0eZ1?z zK-GQ`WjjL1!K!?O6R20dF+!B!s>E0g?C>Pbaoa}VHs}`$hNaq+%r9&U?}%A2ysSli zZn(FZ>V4yD>_<*6hkeFSY|%o~d)rb1<4M{>)JE(NRD!n_2v_p~{vGt+13qVZn-Z6z zJ82$dT&VEpo7sTuhkcEE(w-b~B_4bg2V$WQgF@^{k3A^V-exs$-d(aC>TjhN*y(pG zw`H<`@-l}4JE>oCcz09&$||AH=kHn(!cr=gcjUG@Y|q)dA}OI2Ex#PhlN@A!b-k5l?nG|T!#4bjZ=lIFs^zC%{{mUJ zIiLc7dthR6v>J8U8S?f1qJxq9YyS5B)a_TrrG#{*IIoi$f|+Ep4E47+40FJ3cO-sU7f;dBPf+ z$4b1NB&l#-X;3G?PIbi?g>|`X_Tf;X{_xLejobK&o%m69EVJ7Y_I1sA=&K}iwZUfN zAdGHO$X2k;_fSCVN~33CY*7>kokMw2rZ`wEWcUl~bW;VtUqA*YuV(f+#M`_2X8`o& zGZmkm@eKn20AOdW+<%)bHG{*S{gD?T{*vKyd1e=fj^Si&SqI|`j*v?5pZ&J_*aC7P zukXn7cgWDf#>~8Cy@)u_h)McThUxV_YvEC5_rKG?-%R7z<6s{53OSrV?xw=C=t>V> zQ^#CAnk9E#i?mQ%{da0o!j=;E1l1J#8!asQn&Zs%-WCS_kd~Va&AWd|FYVL*g=Xq& z9r_BsR>!-!151bvtw8%@m9*#8(t-UXU|;pR<^JsT>l3T1a{AIqBm$N4j{hE0AKiEI z1H+31ek1u=tyaw#e*$iwMK$(nyEaS-gIp^8OA4&H<-_wVe+dCG1Ju5Q5AZ@?JUlNM zbjYtcOm4nzK}2zJxW$imv^6d7ZR1vQ=pGTAXRWmw#s@qRm%o=T;`=1i8SpH_AMS&n zT}th1T$jf}Ahg3T+aA0&c0?pSqKyYi>{1dxx&-%=os+tM?>?J#JuzcDFJr)*Hq@45 z{~=YQ_x)*R(?Wv@g5mApfXhD`KjV*s(6L`h!l&PZX_&RF8I2NNC-XgC<1wq+Gur^F zzow9-C%ktTHWIgp+SSW-ji_5 z8GXC_I(nOfe%U3a*H}R1(p^-iTPfG}_QS|W`6!D;!7ge%S!6^gZMdB2#k#H0oE^Tz z()qBbq!QO)QVq5p6Ng!^VML^^^c#SGMkn*A{Vuqz$E}lRa#vFIXDm`fdNjaO`6`80 z3&H4A*RA54?% z;v?R^(Av|IRbDda9P}G{?I;&Zuxy`4fE5P|Jy}{(T&OY8B@uc@xYda3Sg8G zU(Ihc_TfRtOo5|5#}(!c34A??vmCk%mou^pS~Y(x{={!y zQ9K~h)8w~`S}bZw@ryx5SvTUaIWH7gb6Z~+@GtE!z$JHI)<*SojO{$q{pZ7*24Y?XQy@;@R!UN;* zWz61$jaDzuom&CHZ^BY{jdoJxQ+a0*7Vha|i(ISANXhGV=X7`Qv>DYH65$RlGA#hymf6&Ob?;MysXs0nZN0pfR3oVZ!gbc53ed-xtM5Z zkm8T7QZfNldhYTKs3w^wCyt3NqGc`K#m||L`@g5drCX8{`$IX>f%=ql%c502N&9O> z$KiX|#MjuZ(klJnosc4j$*jGd(ZQjM;Y*paJdbI!HXO&SAD#x5gBVnOR5#@_j61a* z^gi3>-sQn4;bqV{qTT&MY0fy0Ih2XSkTkTtmVR-6Y--}}s9*e;k*R%PdqZdz8PVjp zpupM!d+dV_GqSwV8V8%pb=G`?ydBk)20c82qP}-HXEvqCIO7;)2IHN%OpL=1yLa^V z?Quma3U;NusHj4QP?eWx_s9k$P8cr_ zZD#3@7zOkqG0A99Vn zYR@J%inAQ$YH$4M&n(dSYbGVW4)m=@K#^BkR&fEeT#A0D2D1sllGRP!s%dH4N#{2T zIj)Qe+1rHmt-wd2$Zljq|9e&Az+2yEBw*uypXWs~N=Aed@b_Qcy{yCM=?&*T;Fj@l zq7*5Mhsf`tx$r`gp6_IXxGq$&^h`(o%(S_xe~&C7>+vVJZkO8yvB1XtG|0dAmV;x! zLY^Ujsu!;7oM)Sq);ehdtjeh=`vXqG*RI{aGXIrwuG*p(+@KHvm024CGg0!_^ldlh zlUNqP`}F?8Xemh{2`pJ+#8+MNh$-n1tw(Y!f{riD*Sbc8+oSHsy4xG4rwuId@RFkW zlqy6x0%~(-ZthQ|rfq)gln@Tw1ZT?^6Jn+1S$!Z$N@LXzOSf91UEhw!SPrA{``xQI zlvM3hBIv*q?I!{YK(erpt(t}2$3n{F3+$aNhZZ|LZ0|n!AB~ltHOEmz+}e=ujBnNf zVt(X$;GGcPx9f|~7*n41ryk56R^5rHy1eZ5_Vv+?at(joOosc(y0rCfi@ohd%{T&_ z{#`;?&ateQR{fF?PGNp_(@|4?4|VCWSiJi26TWWC&@ZRSx*O!-fw~RPs92j$n=wnD zOq2FENT;yrr7vRr7jvC}U3Sk`r`gPI$t?q^3{{xL6U3$?s-9w+^!h@}_o2~HgDPzg z-t>t)7CqtP(tN($rMjkAJP zlcG}LA80^H`vzcho?7V`K0k#N-vb^^?zXhKSeulMQ>`0EulUr}9-nA7J7~o{son^* z3cs3IiInu&?bUa67n&-(vO&q=P?@=RG3w^ifpY>9Uypm)-Aq(IB)E8l=C<1L?~zB| zExI4~O4_zu!|EFCc}7HPh$NzFMV3z!hShB*b5eg0k5vz@6Kzc7CGOw_76lrLzl8 zHg-KXO?XSaiNBpqhfFLRZlW=gv2&z}RA2`6IoQqi%t;ASjEw!=Q}|O!O(a-Q`dfVs-)9 z;x}ftQqpz`vN@J|5}JOG3;bELRoYZ{hxz7yHS?MWcKmSm1b*Z&6ISJFZ8aUc#_*|< zONxw4@zSzFi(TltxPRRH+(w}&rY?kkw92(;|4w_OriHPyomk6DC!Unpgm3(**0d>m z2R?VY7w`1!nLO7Y!iSNcTtF6ip)XO@0d-&a;a)(_|4{Ya;cT{V*gCZ+ueSDjTUxDI zyJotqDq6K?6{R9#&yX&(W>FMHTYJ|^5PQW|n?&qQ5Frv7@Av$U@1O6>ANenNj^lpr z`?{~|I?wAo1txa)rPsq^r*=s|(z+Zc;3dWqyknQrCDMXh-KE6HYyz#j>Rg{dba;JH zpwS>elnk+gj6XOW60KM_%iK#o{4|5x4mx&IY!IbB))q+tXzNtZbWbdbif$g5MXl zTu&Y9Fe;7Z-o@v~x8L#TPl(nu^_-a5(r1+s*PR4x&Z!<1`B(lUlf~vea4W02;+kLS zDuPF5uChP8pe$G+IK3X(uXEleJ?Tl?>Ot_uCSB4nFz-f&gKsqrxr)U@rffn#3cN9q zkB#-3ja3;#bdHkhOx3@?E~WAtUua%&X5wRdGpSl8c}^tz>z6>YD|@vi`jhw!{z0cch}upYlVo zu$|5I)`muSH6CePtMa3i-{*O?&>Zsd>GT-9baZw?%ZC0YdFo#4Fna!KP>f-9ef))% zKS&hPn|nHQ7yqx3r4X9A(mnGz!7MJLC)x07X?3o85#?EwH|1|Oj({$QT@h1@%;!kk zu-6D!=|4<8c=jia@?FtK@aSk*B0rY6DPJ2fI^ZZSg>nvZeokWw#`vh2RtOlRsP&$yd`ITh9qN07rXI3iRN#<4eO0EYrZOIQ*KZr1B^`eP5W+W}; zj;AAfD|QEWEBPYQpy$M3g&D*-l!*4nA;OH6uj6*z=15`_z*0PqHV}xaAEiAQ5J?eh zb@k^_H}kIbGhaP*6+S*x!FN;DcHrlZB?UB}8mJe{ij_UdWrcs;41Rn2W*Q6g#q zdVd_)NR|#!ka~Ylyl7Bt@*gkUa@xtpN-hN%sL_5(NY35g5JRV z|N3!=xG^}P5vRhx$_*8#^_Nw7^Vc%I_sNv`zCSE_5wGGMP4PFAUVXt*6Aaf{w}t$R z9~tU9Z&3xbC7oi!XBeE28U;$)rOmh#i(YtEO}i~OEnxa@{gx9kUtKxgm=rsiH_4C! zPsa(*f@%w0UBBW~uBNDluZ-2d1qFIVL=Bx}1`gF$K7K!QYVj+4{ADie4MC-kBoM3w zF0jNn-u^q5oP%5Q-aJ#Ol`s^CxPU2X0eg0o?5$|kA93aRncphc@zgda=C}_rD%UR8 zX6qQ|-(0se)kV6>lvUCC3*+_i_(!E-X@d!VNjLZGVo;vLt4I&i*zOj8EGj3ZdbgP( z63C}{x4i9CUz|x9h(@tGT_Q9w5_AX}p%Rbi{QG*quA9 zOnp2s0$sb^K(8GDym`IZ0=VD$HzeBW`|K9-sq&8CtSRwIW)TQU{hKhLD>Aqs`)^XH zMI8gZa8W~-@SAFe{99g*TgsNL)7R+qxbZ&R*b&VY)LZy)jzo6g_*9ubo}Z8=trCjD z7Q$cdXF8DY%63xktmunQrw0ivSKVt08-6Uuto4yt2!KHsB*{T+*-se%n)%-k81L6w z*Pu`R8*A}J7dR#hjX&52V+#i*map06K|5LF85&C58BrLYHhk z;GuCFEERtALxC0Y$r*%S)P1fJNUXp3##gz%`)wn*zRIubz%d98IvvVgfV%PpVAH-s z>~f_7WpqF+yS4u@k;OQ=@D9dS9t)jmNs!^0IyanraL=A<` z*gvg}?gbiJt@D)v^aQx8K;$~`uHMNW9zU~T{WOhvwD}A!nMmPpwoao z35PZlm0)Z3X5zda;g91ApK@)mupb!CQbbq*1j#EyQ+8<~%Gr-73VG5(f~IOFHniI> z#?8fNhII!ybS01_3OlKApxyrbAp3LnzY}%%mqs>{4mXEw;4+VSFAV(I%Ib_wooiM_ z17xRmNM0=L?m>U+U~#wu^uU$9=>#ni;xyIlO0uA5!g$0#`Gr|&s4N{#-mdvz1r;!O zpX2@H-w&qQnW59I5nbbjk+%ICQP!DRHljq)o*Y&fWXWMhSzu@2@{vJUs0EMV_5YX@ z%A8$bla48?vM+v2Z>8;CE5KSZhQc|%WHKDNOOe@xv%1@pz(hY zN$TC9k(LIRCYb5#*I%(6=rfMZfGq=~d5kJSXQw-d{DTW-=iZtxDP1Qj2j5hDFm~@q z)8{_=p~YRQrSFrC=c_5{TP-)~2@IjF5O{P&?Fh$=rMvL$50(`h!D6P64Y5QNFX?Qn zTDSmX9E03-a9rWIv?a`!)?-*OKOkitpC#J-BUs>Z4g1-wbmrC}yRGVY6205HnEYoGevm5$F51PKv=WmTHpR-6 z9Idl*zOhoS?}E6g!^_E`YQ{;YrD;)zSw{b{6WG(7Pwgm8hW@_~s)N$61+$^KSK&^s-lgiV_14{z@;h zY~4LxZi-J82b{dDcbeD&gG96eY^aBW&Rv&-rHDA#F!bG(0aL8#)>F?fe^99a0!J!% z@gEc0@$y1bIq52V7Mc!jHJ`&q4It_{FjD5V7veiI)>mjJ^Kc?wz zhf`alnl=}UHjK>rmJ9O$z+;#$2N&Wz0QxAGGntFHXej++m{uL^~qJZp-u(vg$mpq&%z&l3_$E$&P#3Ev_+;Q`-=vQuvMsCc1}rq5W0&^VW$ z=YSO`P&xRJBTJn)p#9ic4X!17o*8&pq15^o$~3c+GYin- z57sJv)qB>Yp5Dq_-%7z{hk9FUn>t)!=mc0y?9h~!G{xKOIcxsbstbh4>W}};Z!T~A zr1x+abb7qe$_sM-kLesOfN(LPBq-qt<8Ra7In7eV;TS%4k^AS_RxJv{s;7v?@#|yT z^V@tpK8^QW9FMtxO!o4H1kwi^fudA>ONqkoDsq}kLPTxM{OVTNMLV|u6@GV2bFJZ7 z@zkP$2Cs{96pN9007?Jwl6HxlxI9oEXhwz?w3LT|Fyaj#-a;_?m;1z>&h!C>S3=&< z>(X^OZ{S}_MV^!6mgwxznh;qLbJjC&aA^gh4}vE;>68Nw=c-tJI;{yl=quD3Wk7N z9@T-2cTvWkAeG{hs>MD@>h=SEU=AzKplS5-g#&&aEXtd@usbHdXRozCPbs;mp{IsC zDb})U0CgIAAcu&M_2hjSm9WWzh`W{qIOc8k<@2AT2TlSI0dyZ#uH{r8K2gkIJI^{L zZ$9RTIpahYqcyLuh2}F(%=GpAT4?m+h_=(`54n0*is6EZAqH%#I|rOp77naY^MWk9 zL((*^ktQZ?IegH%nKZxR@x@i5Bo`i{!hECVt1dIZ8GI5gC;Tf+G<*-Ymi)SaE98Jl zb-5J^obgZrJq8E)!@2;tFn-!FE2i{foKeTafL=-AM;~y=z%7R;ZYfW(27e6JH5n{B zSU<1FrxC7nJgYTGnG5|}BdVq!VQ#!vU9r%a4dVYht>Irv&V4xU7lSunKJC=)pT$1y z9-G$qrzItI(8BjA*2+|7l7ig=0#1QcXP?6zh#54~7ec=fnrJQT5fvPoJV*pBvb6`S z%mftWL92HmSkBf)6jyUYaV`ed&eA`oG7mwS`Gjz5FqCX%Gq}X;s9Fwb>oj@y3cXS> z_ZI8cAv!)k-4`opF?1WJeF&sg7PqzS=HVBHnqH%5 zg=?xV7pB-eVc+*1gS)&$K*pKpb5whawc07S1ckq(t$wBYho6xwO#wpPpBC_UpXhKY!k;mrLCifxe#Cu zRVX^%NqBnTn?U9^KYT zjBOPhjlVqD#cbMFd4Ji3+8RARrc=MHngW>MHNd)Qp?|MlGe&02gM_L zB)VrpQX}!%v>bBYu0wBHL-5?lk~x0W+1zs76nnU9#R6X`N3T7t=7~}_gU6i2prEwN zZjdzAPT2vPhJI~A(T=WCzks(3TTJzX{{B`4`EP(@T4p~|? zwTPL`?;zJ+m-ild-n}2;eY2!AtoyKEp1SG<&*!=QkTfE%-Dzvc@8n(@oE4U!*i#=p z9c21y=fq4w;Lgs8%}1le^c6?>fwf9pK&;jR`6}_btvmal@7N(MW8gBEuBSkTZC8x^ z!?nB`#@aa9E*whTlD}K&DI;^eVk6EbaPYUb11vr`FMfKk-aJ}w#f5^%i{!CAY6BoW zlQM-)KP+PpkIf3ei!#@zKS=GR5}i&iEnz4`7q(TX-1;f**-Gf9SqYPu>aTH zBuP(g9ri5s+>hPC7Wi9KNx*Ti5PQ2a|s`Gkp5-DJ+oZ&EC;(mX!o@gErq zl^4XDMU>m!aBTGdYJU@;*NlsAt9@)QBf}h}(O+)Y1X_v4!9%YoZneJ|8o3YTRge42vFF> zL!=$!hh!j-!?B}!%MSi%*uXqqoj# zY>N4%29cy(e0b!0j2=SjNqDon2+={B3RRG--qtEosU=Ddz^oWf?f-Vmo);JzCGwgl zCOtPY{;46{(af*6*MUAKj}3NLmM`s?JBIIN{2f0&KLIh73cP%KA;)u|E8(2jTCgAq z|J*XYe6KZRw>SNbY3AC-q!^mF%tcjmNc7wQ5ZIkHS)dpe^fFIYsqQi>SnlE$aCtxO zyw>>0(YA&wfLCl~O?;~Pg>yvN3OA}CPHS(gr8E7P=dj^%gKE~%J)1uwCwyW~GT^!P`tal_! zo&oG(eu%*P|L3(Le}7DfAQk5^kbu*ci_4rO_1^Od zis1DfW)__=4a{(VOQ2*T4C}s?m5_#b&oS*kuKf_=`hLsIpY;nOH#qIub!RkyJGGs9_oLWSsvOf7c_n9ZBPMla-nHk15Z#FtOR%%pfneiV5KM2m?7@E?B6NWE=k` zRW}a#yYzC3m+zpwZ>JyH*t(@^U|lNdG1rfPZL92UPz~bxN$OS8NKhcCzqC_+s8-*z zT+mIq2_=)_OZ-tS^dHj$ILp}=RRSs)X<8yeD>k}XAaEzw@84X>?uo$b-l z{omue>&f_R1Dju2CU?&dW92@%<*Uxwc=2k4OkS=f6uDc*58DJw3AK*N-jF=eGNT_o z`Ir=L5-Lw7?t!Xd0b?d7;UioxY4HgW`=Ici~Po@y**V>^XJ2v&5&~w6Cq)l_SQPi zah^zJw01pav<6VL=JPUo*oHRxo(H*&HAKa&MdF;PIqC*)4w5_2$lI#CBr!qZi+9e_ z#srEOqs;+W*ydmd;hxULr&%l5%BhmaeoCy`RIve{L)X>1uXAvw0j2LX z+tkK|ces!5X{w4lHgSKj9cippLl6Z69zLq*b|JgVY|NOI>qWeUFP3Vo#Jxnr1~7r%6~8X$`6 z2Do6-1ZaP9Jv*;|r>_UTN+1Q}b(-3pUyAe&-MJ#Q&50;HqcLN7X#5C%!`vStTu{A1Rcd_^!mO#OkRlrw^?*6vS-Z*_> zFnxwbL^p&xC8xjM2pFZDT^$k>-_jJB$ zF4$_tt9nlI-_NL`dNVekwx^$zcR8LGzpj+tNaNXCucribD|8aCC9ynxy4N$GRnmin zsy+Hj2{e&Z$>=AQ<*hxS=$o|pi9Nr7n7A=1jl0=U-w-jGZa)9eD|+bgJ>r@2gN z`p6#00df|X=A_irgG+y*{Jw4&H@n|9G1^bXgq|}H&83s+uGX!9l~l;;3ib@xJ4eWU9tT;9 z8uT}ol^N`J48XNL=sQdmrhufGbPKjemR$}{5Y!)~CB12v>khx0!8qSf7jhMX#R3Ah zffk2<-CXAHuUN|ai+{6Ce+cW^pE=gtR!J7l=uRG70A(jN0i(dXkTcezUmts_YS3_! zkL^PXqWbF_h?#y~;Y$%+5dPbi=abim!wKzuKiMEwjx}{T!*<(;5f)Tcg#RVhd*%tO zeUkOdEpk&$3NFh~%m+J=Nu0j{U_=zp`Z=qqdoXWq@MgM@y{frF-wvi_02rS7IlvF0 zz`kVjKvt8Uwhq*D7=c%s*}?vFBy7@>-|(e*a$mH6(!8!I znLnK_wg+b`k+TkL9yT1r=TrOmO|yR2GX}t)f5+hyuj@ViP|cRaq2&->Hyn<;BDC?L zHaM=XD}ZR<=grkAVR&n*ckqRnjX(%udC;ngd{k*pPdftbI=oBe=1x;St@{CLd|YVQ z;K_Z@uIl=XKlEO`2m4ckT}p{kX_KNF;u)3zFFQcB+(}CHn4Ray z3GFhZunk2)zMtc*@79!lR-twLfIGs&sU8aAkp0}MhzEDQENiWbg*9zTjn`6m? zt9W=;-k7dTZ}pJ0oO)Y!VvmOUk-#$9tqT|PDCjo z=V~4kRwib z5(-WCMyzvy2`=rq)R2NK($1IK(zlL!zmZ?_;5UP7Za!3z@Yxn%a^CAUauGNGRFFA( zENqUGdgfMNZg!+ef^dVw9$fZRCLf zn{s@eX7}i1y7m1P#C+@B!+DI3jPWC_=iZbPrL%nsD*f0brMITlfPBnh5qp#>+M1$y ztkwBKYVVWE_jn!Wu!Zfsdo^bcOSr-n7XD87+H|`X8{X=d0(+r&LcTkAIQ^~`u|JlQ zSDGBVWA5ezmo~ph6n*t&MrBZSxftMNb^BL9k^_6&VMX7uHE_-|miUp%awZ3=TJXJU z1xe9MNY86P?JeNLzJxY$?>?Rg8Jk43y_~7mz=cvn@AE!2 zeMC?H!`bxVi+n!v%;nZ~M5mfyCj|KO8wfV*afR+V_NdBcKztKS9g%7*c{GT6(UkJ4 ziS2INF!&q!Qz{_{-9ZiC4S8=K;2@P%nxrBtl5i0v5Hvm_f~_xF`Tp3o-!pNhH%?;L z7TNz(!mG1r7lchmWHGP$*h3~JQU(ML-;ask`x>EFNn;l}9 z>8uX)YZVn+H4z(}M&owUZ2{ys#5?bL9QIx5rUjrNZ!j^E=Tvl8^-*rUidZ5yT;o(u5g(VV#OeCIy`@71s9sj|myrrYX9ZK)Y7T;2gSAr!QTLqQ0HC`TY7# z<3+>ovg~sMBjzs?>#zN=xOR}nxV*yAJu*9PFi}DCUmmCba%`FJ^W@w${p}(;bMLw9 zny5y|n?{#gcW{~)z;0l8yTt9*Dl(YBnWQTEhYAj6pZB;c7b(T-bVsg9s8FkXy6z>= z{S6?Cx7$lKlD`xOQT%WgT_@IG>fTJ0F~(we2kz6C=6JKP1>(OqfL_6jF6nbCS$8Q% zkbHKlX~>}6O97K#_F;;TM{IzT{h~9jHvOK>l~{spRNKO=E<=E^()AzHKQ#SPL{wN< zkalx+re`A7>z?mdouFNLWASoreQOIn*px0HW^}%@E_#GiLe6qoipns){MeTidaDL1 zKkYjQdCrz|SE5-@6^pFoI_a227o-w7UrhGXQ22$*ZM@=qeLD_k86B;h6^wI?aqE$G z6h#q*0$<8+LNrEqYi#8|Q2yYAP5zkbX|wiR&0@as&95sfQZ~0Jh>G3Kah)Ogx+g7GImA!)_1N2H!9!YaJ(0qTvp zL(0n`qx5YKU*r##F47@e)_Tz9tBG&HjWt_vgpGn?K$;{%KH&Et*Fml)i=K}SC{FBN zr_-UKH_+?wjT^u{U& z(llAcVS$zZ(5o}?IqbWu5l!oe`Xp1g4E66TVje(Z{Msn!Uw*QuLtOT~`oK4Yz-Vse z*Lc8d=x(kZ?o6A<8>E&Hxz(J&^Z9m+=|tr*t4+|<3(awTwP**aTjaB#7_$O^rD#fB~$8^Y9bR4~fFxD6-uI)qYB{c6c&=YeH74_;y#ke*f9n^24Nu z+iDhLW(l`%ZXx$-C`fjC{uPtz0JZ%Xk!!o*Oyn5-14LBrR%Jf6opoCtXBo34Q;>f6 zD{H1f;Avtq+Vg&;3ca+27ZY@D`DS0fTIUs-14d5!diLu_MasK(Z-)RzgI6HovoElf zJyw-d8y?fj1f!e=KZAfLm)=`?>5In8Wkiu$##_+KvOxdLt#^AX58JgPb#v*40KfU% z_5C@o=6c0fYr)#h$4Y3Oqr5c3XE`%NpWxgwBJ9gzN=!8+%DexEV2VgY z$O14uN0!iu=U!gu3g^jr8sH>hYtu{ge)o&zBX)h2gngfJK>i@TT)P{d(=I5K?sS+_ zzI07o{w(r70`bjq z_HPdsNL@gLI;%G(%e{q=tMQmEeoPAHdF`n|U+<&VZN1o@YV1_QI?$`6Nx8KqwSUwA#(U6?t1vE=;pH&w9Gly~fU3@mZXyLNIDYE^R~Ao`dTkipGr@n^K2g znwRdOeo0yxf~uC5av~C5afz@;F~$3SJfcf3wvwgI z64FE>J*Sjh%~CnYCzzc-8)6?!;}>7?@3nyzMBBQxOFTC=va+{CBlW^f6E@yp9NaXn zc9Fz?RwOLJyCs1ru)tZnaMi8lNk(>RSufHm>Hh53Uje57E*5VkMsHZXbf;vdty5AM zP+5(r8$qI&6jMsJflM#%BT9=)D_q{#)?!jvU=F#g>Aqq+DJxUiR8-+P4~%*73~0-& z)qG4wW;5rz;^~+c9I6FMYH^&X!W%8DOY)`-2Km-k4s{TcjNRpUoqYzHGu=z&0uluG zMGNLgKZj3Vb4Vk;Cn9h2%@RdJx_t+Q*?zM&uyBh3rv z$cFkXSutxRXkpwS!+yT$s{U#;7$@sA8~#r?E?kX#`CxduBgC%qlgts=BGv78>uA^D zkSO2fF!Xs(4K_28xEzFTOt@B1_&nNl48~J{?V`^5#jyi29`}4K*09+|OzTZ0cahJ! zoruB>zv?e zm7z)1eMl5n67)z`NSJT(-dGPl-~K4}$kRI`UpPlAbs(;2=#Vz(B*F7z)%%0{k#f0G zsi@2b3^t5P2^36vN{ptcJ|HzT?{G?p$>+&nwVp3XUSDf@?KS5l6cGyD-6{NYfE&!T zaZXOd*23BjE}<(V(Rp=mMcMYoB=3eL0({PFX67FjwTxlBLXepbuBxo;3$?jbf`8wY4vmF>SEi8DsXaRI&rJ%2L9O~ta#C-()vcMv{YKB;W5#<^OtAQm#A11Ik1{fWv_ zaR7JdQF+l+>4m*(67B{sHx_0AOVE|Yk=g0CKrJBzqJBcO-UL}akHiQQa`w5!KghM& zzGDBVF`Ys)1-8(wO)as>eenZymoX>#X$KuS;CMdVS)T1xE^HAI?$BAJL`umz@}AQ$ zklA3|Vn}2xHAM_)P2vDUmKVn*{T9Y1X7}|yf-H7F0vQeQz<4)mX|nF`QtI}pzH|06 z%>#s%X6t8rR22Mla!pIZHhg-X zQyl=Kx{?6@tw&t3DQQC@F75FB`#DtRF8EflZ~=BU{RA>MgPE9miHd|KA|)nTU7uju zGra&v-oHSeHb?6y(e3Xd{>Ow#G^Qym#0W^I0xXt)DoWerDB+jJtXg*79ssIX6*i>8 z6;d$4!jW`sdRwyWfNx)IMFlNTTrAiys~5>~?^MFH9jh{S2}ACuvzl3BPJg9|X& z0_3rBMS)+sf)1AfV?X-{{ymR`X8Ta88N9EF{6_+qSNj4`uii`B0oHpO0{@?E7VXk6 z80YVJU?Lb;WbN{|CHT2>u)5?$Hh2efZrCKW3Ru72QwUMVh8iPvVJ%0-u?5Y9Hd9Eq z#$yrtvt6XO@s!*}3*CJ;(Bh%lKu_{Ks29<%@QK3X17=m-wSUw_{kNMFYiA-~^g z(itQW%Ahv&IcU*zp2tg(d@zT1UrYQeGf&QS!^JIxd>l*Gs48YkY-%}Y3W;3H$a6m9 zWB$Eg1ztnnW->$t#MS<#S|ywmTgC5%yQ@fgQd-P@Uc#yeIiRL81`R@A&OW74!;h7G zi7;Ha9m?(OZOFjM+sw!QO0psV&|9GB7y>9{#nnuPA5N%n?~8d__#nnlnj@?*@c9Cq zULv+3kYdKZUm)S!MvDTrFg6HeL@4a$IKw)CDh*Aqyj2I6*co_Z#r{`EKHR<#abF|R z7LGRr_UFJD$eH6KLWC1`VYyOZcK+=av{-(il-t7#)^*?9e4uzSmVL4cAXGL@)`_sw z{0@{$UGnN^=F^5(fA{dMCW>996{6mo>RhR#6-#?tJl=eF*_A@(*q)5sTF z5N~4d$(d{C_jc-woN~;Mwz@aC z`^0mvB@9`Tjl%O-JMeH7K7sF?`%7*MH+*Grgx`1 zss3Y(>zh8$c38C1pk9Hr=wHh^G_{G>C69inZecC{mdHW%MY2H$#-M~8ZjEbHg&>px z>LBN{QXI5Xj?d#}bEM_`mi~F2f>)PWv+srY@$pvvfVoiZVa{Yc^<|KO0ReCz_s@wk zpK5F}yb#mpEie~;^klz2<%-CaShg!eK;2SXg=sH+>tn#$EvEjoCYKpUj;4(OFEI{y z7gR@>oSTz5u}-=<>-%NVNB3r#1o5gXtYh^><|f&teqeL0y(oZBi74#Z+5ZHuiEOBN zOB(C*cXiG-DZ|1LGiPJtgEZJ&Z?`IjvjAYM2F#f14HKVgxlKkbM|E*ei`6HwI@HGf3C7oYt2^Mof3N9_TyFARPez z+iS%^=pJE@aA|^KxonCgPiT-0vlKdMgeWL%>J>Z`_8rNgB1>Obs*v)HE%kk{-BIw9 zHJt}akd|M5$Yz5>l&fjq>lr%nW{eCuh{D^SwL)VOW;QyMt7o<#rC|O~C8=I&-w*@P zwV8k5@9T}==Q28e+%kcEKCYfaAVAjyr7r|4?0nu+M%P!;SpAikmmDL$%L7fFz`&sl znl~W6)7;9HV`%EYLVmH%YwkpPSN5Qp2av zXw#Ab_QfFVF<~{mScI`No$?;aacp=eK9Ma!*@M3sO zJ<)-6rUQm_!SeTaXM)c=crk5o9Z@v-bY#;-QoWVchmN z*!Gyh6i%n$Z4U9)$oA&f-oLQ3wU|#A7e*RmOECLwy`s$V4XRv6;t>oXatsMV&!oAQ zY?DaHQF3I5aZUNBsOJGP_X=M2m&8#hjTb%Bxi(EpR-`%7BJT97Xx&9NQlCg!44L_3 zn_Q1Z+*6zq-0zqtX0A~vw2SxA4MmVudCy?wiv1s5rwIvxqr-@?Mhl>e92?@!#5Na7@%Ql zvE~&2E*s8|*SbVzHV14&u@Ef`cW8nC7c(aX8D@_oCicR7Refz=t@r1#Ysx^q?F5wE zI}2xzp`Wcoto~zqwW+Y%_|_TZmi#Zgg!x0Rg#Hd4mObWDA7_cuo0A>HPH&zCWU3y~ z><9+Njr4EfcY@?Z$AK1ac(PEF;Z;hEzn2l~ho~R_%$=5yxG1>af4IFrBTD5XASImF zsq9V1TedSWi@ImK<=WbLp**{xp0~-=r6>ghj`R|n_BvkC$LUOqK0z9X?2;tLfI-@gE3%e)9Q!!Ahah1L$HxY~F!GSDZ5G5=Or~|7xyOxRd8&l;Gh*ftoE;c^F=V z#--Ao@dOX$h^+nIlp}LquTm_|DUO*%-ur`*F+Aju=+^I}@29o%@xIEv;o{)}_NkZ} zRMkmXb9p~9tvN-2TAv6va)(#-35_0R`XvH83FR4<(ZXC0oSL$rmK{HzAm~G+3qv_c zdqY#@+%UYas2mQ+04l~Cjt2$mG-y*&?BDW*XEwgK2TiV@inul17)dP#W)jZoE^t08 z8Dt9ujQZr`7$R{z0-}ej$$>*zsOi1awQm;fX$}Xb`#i`Yo+!UevqWUI^vYmU0A}O; z&cb{l5_o(O7!2mXXvn(P=;q90w>hp>to)GpYC#+lF)yAOA{zppWb1I zfc?g?*Gm?M?L8og$ipege2a+RhGjM$CZ43t`IgCpZZwTc-K4>S*d*fW)l|LL5@cmD z?!)FffzOX(ur!oecM2*qIR03U#(3nIs7U^cHk>hku@LWe+BCIUN&ZCHIFzMbhNqK` zY&d)W_+L7C;NV1?ly5#gm4+i9x0^OgIf$& z+yGx=#)GdlG*tTibPG+jMdFLcp5+1(H99*dT)d@D^r>E2=~5qju~LottXk#c(d=3M zW*aN$dm^`%%!vp<`FObC8YTY9Lw~SFXu>O|HuoM*(RMFZvEY~W1`3DX>Cc9+_ zzGy%jX)HS&MND|!EBW$8nM5s9pMd0lUiJ4&5o2suMO01yTAc2>2i&_hN~L^P!Eoj+ zfOc}xrM^)fvLYyd=JcbrF%VQETAH;ZMb2R`nO`h?3yM4u6~Wq8JR0$r#i;(*!|V%I z4LW`t-==3^DTySd?&hWemJ$BFI7G$q%pCC~IU4C-kSpa;G{Rq4n+fM6zHV^%0KZzh zA1lJXOVf7ZNWRsNum2!TsFlBVa*yVR&0#eAojk9YoI`R`>$N;?@p;cZ{Zvc?t0KV) z#AiBJ3xvyxrp&+jxeX9>3Wd{t&D(ZNvylEONMQaXBAr+Q?)6a+2a-fqk^w#I7@+E} zoFqhy#47DyY5%#cFx>asJ*neQMAl!5 zc3~f#^-U!D;~jwJT-82ax+HuUkd<$_iT+J?G9d(#dh+Z*)iM{R(|B^45<5A5;F+1e z3h-5w-5kaG#@Ed3OT8ha(XLICrvB3I1~1EA17}|&D4J-WZ;V@MOA=8N|1I->9rExYKsP1gvajLXf-S9p5V zRJtJs-7UNj?H7v^>HAmbxhRhZYg)pCRqk*eQ391h((rXuNB2hYUF>gn25+mKq$RiWSf9xuK6eNUb@Z?SI;kM`d^Q>Hn4%fxPo zBP(1ke6W?jg$edA^z%5)p75M-E2|Z|e{`JThlo_Yc*62mC{_=24|82;M#ExOkpMeKAqZ5&^ zF-mWzM{Jbk`U;}d&wJ#37z5&Us?%Pi33v-S6SWAUDTwS&FYU9~+F&XgJd zt@;clsB-M9t$^Mwr``z1H)bvv8%2IQ(ezyQr@jsj%|#}x9hR?(+(Dm+^#t#NQcP@o z1>`azDA_^26ug7j3A%6St;1WSIVn`k3@RPDZYA0nr{m-MvEJExWbIk}_JV1K_Lmby zrvR)K%kiR%*tYs|6VB*E9zw3CT&B<2xVgn4(=%vUj|$wxl`r)LL&_5SuFfkuBIWZE z=XEdHpZRx*u&Z!VJpC1mDH%ZR5+R^a?s-jFmsqh)T$A z^6h3)e)C~@%D|!?tcbMxkEuTWWYu@jIOX3{c6#?4EWRqiZ%9fOxf*PWsSRdmpi{K! zN^kubcav8fSMWd&qGY)qYV18GItfJ4i7#f*lKRb8aVt+ivOjLXgwGu2F>&G_u-`VW zK}%0$PHD96RJR=9lc`WsSZB`kN9X?Y2030s42JQ zn#6E7BsA)srYRnnxLCg9(oz+vmt=0^YT=qH=T(}JIXKspxTzUx+RKXYYQMGeq-<&j zxo6XR(D*@K-<+a1!Yia%-0BF?;98ZFl%K%=Lq(+V#;B}r2d%eWdaBJm8)mHX5tccvLbFR_HSAr%F` zZwr?&|MS^-e9*l;XBR2(ryt1y#){wBcq@(oHBY5`yH7Pn3cv3sMRy?l1bd|Nki^n-!;EJoKHev=^Di&0Ul^3KN5x0R-%Qm4-@o4Glx z>lMr=mY_ednfL^6#6R4hDsi`9Hi%bBF#1yA=tG>d)j6nje89y08UISZS4?DSW%Ne8 zRqM*~)Lm($sDc5%gOoF@Yt3jWJ6BX|Lis{b)AMYb@??6Xj*Cu^Skh$8WMayfNBY>< zfPDk60SQR+o0-p`(4c$~8Pk=acdJRD(~WY|alAAJ_epBBl6Uq-SYG{NH%Kh8o-O;F zmzpWYpd!aRNG$HfY>SyrDC_4=tzM)v#rX$e-_*^hYR;V-FR$6zRxQ*|mAxw5f0;RG zBC*0{|{4V;nvh2{(Te`1q4M9keCvp zv>+W*5fBj(=@u!;(H#~bEki&?sdSDWIV1;+kcN$r&H)1%n+t#E`+KhId7i(3>wLz! z&pG$~y5FySzKYpRH8qB(E@r999N~7A8!(s50Qp`=&UpUcFV5~BfA}yN;U7R7kub22 z8`rNFiflPbU-c<@2&6}4XDWn%N=slzi@H(JP`Si3`G(#eCwa49-kGm&I@GKNM5GD- zfw~$BKCfNEV#Qrr(Yn2u3me?$z+d$>o-q^sxc)3W-B^6H@?>oKP8tP$>9&CM1oO4( znW2_BnDt+A@Ed>#wRnuVw0fN4bS_t9!Sv!jf<9+oaNn$2RQkp^5&So;VElff z9AYTTJRg~)FS~X%ZRBuv-iK~AP)(}tbM9bHu&osSW${BMp-io+1TBz+WZsKdD zgS=zC1UMI(9Wfu6xYK2P=C<@tOLv{co)xVZHa9vljwECllnMqgW=ks`jNU(^?SX`i zSyrMg`kS;e(DD&p&!Cw=1XM(xMKd8-Qhct;#BA=z#l`oGY4MT<#@h?Bbw*TPxi1-+59km>RrLJBu#c2`Z#ElaM}ESO zFZ?y;{#=`gzC76Lxh;xwS(P8@^y!u5#^|Ww<5E1HV%jISCAwM~T2yNad&~mQM-va{ zZraOnROoFg>j)~>T`s@wF$dHCS~S2SbLND0BCmAQB@k3EKq_o}3J2KnFP8_>M%$ky z-i?#6cDL{kMSt3Gf(QWAU(G>y`9~kFSH7r+i#dENm<5?yU6v{AQN#vdv!pX6=}7cx z^PdEoO%_2N100()$wT zZY}ruQpjhv=|$^6z0aCnHN(pNRp~y$L#{mQR@!$>82G%$k>bRt<;ZI;k@eGsrCYhz zo0_auOmlTZ<4wZV;2eTvxhCU`ORd9LK|h(WZbc<{<2n>`{GuhvKOK_i`*i2FxjZwS zP{O`pZnztmtUR)^@VyD@pEb+_mB?Va`M|7bPU#$5Ym)ELNfm`f-poZw2o_?Vt+>bR zZScaQTxFj4hoVMI#AEx?-B#2@x0f5UA5=<|P8ht77vE;Dh6;9H7bYa+K7?1OiY+e@ zwJ0L?KOplR_DO?&$86*gp@Yu{hOJ6F&(G|OJs-cgJZUFyst1u9dgy3rF5D0tpVRY- z(u{KT|0Av8H&_3s)~=P$Nt;S15?nh0faa&QqhlW;*D1YIR znkz22p0OqEjMRXuzR25*R}^mMeLe0CX`7bOF1hO#Dd9lMvzP0TeEtBJ&EiU^ba5-! z-k3*ia`X7gYH@sBeSJpU>?U=r72d&)&n(#0NKL!7?9=}uuU-#1b7$CZ!j)wVpmGna z2dkfL5kYs(-UVBf3b$QZR7G49wscz4lAf-aeD!u8=cOZ- zInq0Zs^@wRnC|;N!|u18UoDH6-M+K;a8YZH<;<`-7A6DkMh4;p$ zn`w};A@0h&34ub4BbFOYO~F%H{@os!#7)n6FFI|tnDKhm9=Bxa$R9&{#>Q#5g4d+| zV$TP=FLhWk`SxBlPpbB?bAkKVqa@SpO?b$#?e~I8k0-b6-288u#QQdrUK=t!DU;53 zTYgBr8!>Wgs$ewjMuBBuqX%U;-bVYMv%@Y#6+s+ zQo&@H-tuFklxMJyAGtPMCil2FR! znX>d@`9(Yln-d?5zfah;G@Cdb%~dBH^%(}J`_LD2^ZhmMUv;@pimzHyJ6PVTEXcvjomitS}Q0Wr1h!P*ZFT~VCrrXVJ z!>Y1v1e-M+^au>T!#I}9liTigL7(;O!4-W$E6Y0PfMu^C&TRjMnQ1_Y5f_^}qp=xD z6rGMK3CbckyQ$si+kG)v)u8(X#-!+=bNjv8`h@G|P5E)uTlo_>57Clr8)oyLr|U5Q z0w0Q*PZiZom_FAzxQ~tZci|*P4Cwh!c3^l)~NYOc#T!o$; zSj>@6y`0!RA{eK`_xwOz8{uew^lq}s8)vC;Wu@6YuQabt{T4MD=$$TcZMSeHwdt&4 z3jtm*4~20vmrC*Hp!PO>StEU~Bk$pq1~42CMGC!b=_7#234wmHVf5Ut4Lx4I8A2^^ ztZkXF7p_vElzr`d$%PZ7KM0xGa`(pU_w4jno?7Q0bHp9eIc)iaOyKr2G>&uaMP+My zmfF~)K=@#`+FuX~eN;8Ale*5Wn&f*@x_@EU z&p6fB;qhPv&jIgeb z=CkrE|1!3SK``s8V>&D2_FWKcwB|eKy(+Ko($B-GMuurShkkc9Cw$5ND63#vO7&bnK%!VVaF+vLcMMEyDyiU zt?0|I2YrI{40iMY*%f&fhhVJFawUZmBIG%Jq|>sXS_+=Z82p{TDFoMl`bVabR(Gv` zRMy@48OIaja*^wet!^7(GryOv>L322>w}rJ8CMmJSDo+Ck!VUW&OYRxTx(p6fpy?D zR*X@-a6X%$BvZEwZXf&!MsM~7V;n;1{5%WtT2ZH=GitIL?j_T;qSjp%ZJ^EYJiB>?4K7R;k@j2?GplS}I8Ufqub|Al z7XItX<8#n0FP+y-z#_MeXOdg=OK85wYzeXXxzBJDkg+Ul%a^Cq&EYspZSBsLAF9nh zTNndfZw+u>hbJR11!etIV8)=L{d45Gd0h4VorT`?4&1yz@8o?zkubjjP72fiy*>5^ zXK7QNH1$Dq&H717=@tunn%v*kpj1~Aw;1a5wusq}EFZ1sMxNS)HB;f0^JTxfhVLr{IFZX9?xtcf?fDwiQi}76{@cHt0EcvD>u*}aewH}G z^m6`yw;J_NrpSwC-ReWX;f^xJ0c-~O9&NB1KvWQCqCT9){bA4!4l3gre+?~awMUp0!0 zujPsis1o+5m`61SNiUOZR@z_6H_|M zg>uyq(#o{Xtd%|TB=;Oc^AXbxb?)zu2G-1jKchClgSghs2o|p8(7;|lei@?eihhhd zq1NrM1T7ttz#k5?hC|1-g3aYYU$wNKt*WPOb=2f_W!YX2dltzalqgVl82H`;Xl@@^ z1YC`ejm4fj=ll7{<5tM$h8^2O0|>VcUPR-Nzt#hHx&w1*3qX7nT`q`tR-to~#XDCl z*DMOB22&tJ9NarH@*WoQ04=7blhm!h{ZaCqBG^){_Q^HjXJWryoqyI(@Tv3AJ{r8l zBb4o(+BXj)R`vWCZRX3t9XE7LhfjQd9%?$aRLy|Ok@_9ozQR#F`GMfO{?k%ar=76^rdwR7A;Oz#`9(jn!Nqay+)Y@gC+8?e;cE2B>oRft-} zq|-q78v@H6{_Bk^7u0tk{GR&&A!=u6syj8%kaWpTFvfs+{_I8!ciIG0Loe|y|?Fi1dvRhA& zzR^x-&Rc(8WFpvF1F9{2E#R2zKyEeo)S?4i53sh9ebLp;Er(K{_Jy1m8gIv%NGtpM zJdbeygL2IU6Qx9=Rwvm^4neVP>94V2{d|8TXC5xLxi~hZ5%hJuw7lKO^5K8x5<6Nc zazMPF2pCBIKsIzo04Pa4BBsMdKgJ^R(;trkNaPhiQ|m%Aul{gGw1-vW^aSw242zPi>tDnF--j#Ft}_FbHlTC*}iMBr3hM76@It1-Vv?zca{;fGZ^U` z72q6m;J;qVT3shEgshnzpbpKOGy4+$}LD@-}^fw=@RGt9;#ioC8v z*uo_>72i0@3N?c!7UqCB3?GRB)_9el*LW0+4125X#K2s#H($T+S7dn0qGx=+p#6vL z1_zwmM?M^23(l=m%hm4?QN0#3AH%#$G)rBP{AQFn<2ce-f}|O1s+X{qDLp7B{FpJb z!Y+dra(QWS*YTM3tYI?8^92AG$SlCH`4Pva5q2ZF@%KPv{r}4aE0?`L95vsny-?tCwvI0^ zAesbhyg252F3e)eDbE^S&XN@CMmt|GN zxzZ=HK_65%6GsXdj&(=0GVZFf6A!iGzJ*oVoo!rNredaT-PXd>ASB@}U`a;Pma6c0 za`QX6Jh76x^E=YjyACjfI)_jH7cIuIC0P#4xB|&jKq#3a_;7?KNvHu-HBs08O9)%~ z{}RITf9`Pp{HrJ;LEw_srutgUSowh!$i^wZHL<@FxlYN}v_IBFU0QLii~lATfvceyy=XQ&RFJaMJgffEk>?Z1 zBJJxwz<)>njKC>HIBhgL_+3t3-#vbbShQU!_GF~U-OKV^rD8r`wcK#0Oio*O>{kk9 zdK8nF6c!6j<|7xrrE3jZdaAo}q(vBLFFLBsMJ^QNw1OxB@1tyAE`@wWH#CtepEK}T zddP;w_Ig6kFjWcW)C8MC$t2(zs6w5cWPpjzzx&qLTBZ}J0DM_d9Z zA9j!Rl(kZR>5YZSCFsQP@eb|&U}vS)bJzEMtVS^GXNDAL4NYv!n*wC;QVnE z?;qa0Q@0Z~KKUix2^>!1d)y)hBOG_<$BWV%B|qs{elnX%tVn%`;KT>CyOr#~grlgq zR0twBNTa=Z#HS$XvOeOJ`ePREv=^*^!{OhAU8QE90A7G8aGg74+B6HT<(MpbW+YgU zE^r}^G6U32kBI4xv$Pw;ax45&&w?&4SF)qs#UlVaZ!7od=Dv6KhtI?{HhFv;HJbSS zFs3{2dYkfJ{ZD^%`Rw&Fy@lJ?Tl9FC?au)xl@6HhV}8zY8v#Iis(|Fr%Gc@!qx8Rg z7R21uMZa82n3x>Bs^#N?`u>ZC2AIjyZZM|RtZgFfDqOzC+s#$7c*#v%H2S0yPw_$;EDSNn=3ZGdnSaNTZPOET^5(A{b$OfBm zt?UE7BuwDC6*gra9FA)!2dcfh)NC^Fz-SbCKcO>|yK+5>g0(EkI-RZ!DZQCove7_XtWIVZkfOANTcFo#r zsK$0ATxE3+zl&R103CtvsNV)2$L#f^42!K6#E~OS`-9WN*rj6RmcHLTBEPiX8|a3n979tpHl zBn8R~3KsT*rYPE@`6^niSM~g5B4|e1rxz z;=cJ~N6Bia&7>>=y;hLaP{5vb>!sZ!FGP>gAr#^9;B(+Eq%cwYaI>$LxcPLdB20}x z$J^1HS}-p2EWn=eV- zU>?t3@$c6@{@mo9Fg#5>meoo=HCAhNpqUq2&OLOkWPgD(9+}==D$>6Xl}@qrIdFia zWo+0M7Y2HKN4f3jF`|T2RQoe$lCvbyxKtYyS(r9G-BAaQlVjRFxcrZ$?&Zj10s|u_ulm?0q&~16T|bCAX*y zhv44Ps0bNqR)nxChP7MAFUvC2Y#PA&GpsT^3#yjeny{(-mPN9}naz_Sd4$FKF~+hn zt$2R^eq;JppMG5rN0zR3*Z}czq z*`l>4^J7mNrwxFAP}Z9P3{&NV<1TsWZFx~AAlaiSYcn!yNOP2jUP|!*b|mYfIBZ7t z=ast-cMAu^Y{9cA1a*fS?0Y*e-$sxpuL(%0x$#hAMx<9v))OPNGf2RdzxUaVvx;6McT`9jQ_b_>w*jLm%0$Jjs(DY$##vrSaNJyvipK1xeuq zE(SqigArb$6=J_7X}QawJ?(z`zI~L7q!_pXSNXNA#Xb4z!4bZd%8Yvv+_!cvo2B?H zay7;S{`GN$y~wFUw`92SUmCkhNN3bnZuLN(=P+6Eqs>O*AsulP_U=x|1h`j&0ne?!WPOmCU!f!_>l~f zouV>e%&uEYyqr4PIl6%zWfDu>E3$(Vi7Bxpx zB$)5P>Sfz+h{ov-$DnjjU0vAT*ptH+D#tthkv6m@H7AVwFwYEn+!gZjO~&czWq&^$ z4+?#guKd=`bW$zr`eMtS$#p$m|GOtD=xrp*S$G`^pTqsC_r87G@h9pcNl@)ARqQym z^Y1~7Iy>-)G*s0qvvEya-es~32rYIysH5ik(urR|YKY}DCv2XtNjQ@{*3POAo;@;~ z2VyPkL+c}6myGBPQkL?b;^F*}ol3Op6jS26@Cw&l9=GygV+uCDL{4YUC>4!!=2}g# zPkuU{Bp~fENN_TYcikds(->XIMnS%W*oH$?ci!2ZMx-=y`gZh=WxTP(?Yw*0US0PZ zUv|6PJgYTL2?b-0SDebp*J!=SYlkDL5P!Q0EA#j}RX29-LPyN=y~WFZlioj!x!9x< zD5=kJ64+%sr@tK2b(h~-q3iGS*h*|$rL(s)gy2$1>AA}G`0ZM~{R~KfK2--_NANv_ z^x^oqRP~md8cO!6m>UoLdD9PA`%Q<;UkfUou5N5wXti;qHy(3}HRDJ3I9Y$f=azmF zLI^dhtc=5}MVgav2=>K$XT)OGkn8PR=<5<~cZAaR#P(S~0A4Xw75s;8C~zjz_3ifh zDML)5j`xz(`V|zBtmplyO=E6cRM?a?Bkx*dOC^So9|89d+UAdSAplS1Ako1 zwwT|8O;vnP9kG=#S7<@=uO|mCsJq)NS>zXWb0ELP&9K$}*e7=_`vftNX9>He0RZW< z-k0ZyJ@(WLeceI6HCp`Cc@|eCl@izHSpibGLTToO@~f`#&(UvNnLvCEwMIao)f%vL4To4e91Y}!CYc_w;`atRg7;=iQ6#mX|C@5mbS2l?qD!# zLwH;=SP0+5GEXypIeOiF7c@7g0AWn^aAdd%P7^s7*cZuYNta;}Y86KFZz*uKJSDVF z%b@5_e^KUFf8~XYWj!^Sz?hi;3o7Qq0Xl*(#VKiq!6mTJW>T7#ix47b=rc7h)YJB^ zUJLxYaD+`qOoKITG>H_}JXVnG<>+E8bVQBtQ|eSpUe}gpu4}O@@1L6Tn0TXk^c9}* zRwh8_v+verd5EljCeVnLUzD?J4E9(&|B|HAU1WqO87?>Ji=dx)3h4%5@PZQKkE|S2 z#FmqJBJ!j-cwryCP$`IriAJH%UFg=gVWsL?{c9`>Q7MzzwCi%UvUsrsT5vRW>G1%90g7G2>CI!*_ z?KP)9y64l>R2#%M?#9(QC$NXTFRtFk6fm}|%C&t?aSKXjagj# zq1iZ2F4`n3_ualg)G=|LLxM5Vr_@0fEF ztVC4LnqPFM?ge)H8fth$MFOB20zK{^3e#S&U!6SPE zc3H@!W`#Li!h4h$^dr=W`5MY15x3C*ReGh;#sKV2NYOJ=iETm;T)w2hi#q$--SH}GOnY-_V5;tyG=x2j` z9PFd}BeXz%y53O6U67(xwF(J0NuC7UMjo;S<3F^zPXj7IKpWyroV!EnR^*M*=A;>u zCMv~euGjN}$5d~rsoAgd7mvF?>!<=bk!jx{CEAd3;f75t2K(m2a0VKgbR}OkB{Nv% zfy8))5_CSp2tn(HKES-6MGPX{WM})EFIus&OwWfVNzV@3?_S^ax8n+Uf`y<}3575j z;^@KawKZnvlX60xF64fS)x4lkktyGkx2@{D%`%rGIsF@N5dX^RpWG z#)S1t2{k)1ug}8$j#U*}gT?z;)hbOkVlOCvmV*p?sd z=_V`LOZxPW&9iAOlP;_@+*k-xkQspZQenWdM{w=DT6TQvsSDSLy-?DH&_C?hYD|r# zNlVjA<#IHqV~Z)ZYgE7%b)$yynwLslGC-;?=ma{4GfR6K`+J}v-tCPgUB#)A^!Fed z$sy5BN%Fb{Pb$Y30)-ILX^>RLD`;*(Z~MtO=-_bH%rTxT;g>bT3xh+t7Z(aq{bXaz{nUYrO;<_PYq_Dhk>76& z_>~<9_YCd{kQ{UqXGw7!kgvRfyGG~g9^J|`&qF)fUE5E9g9`w;=`8E?HOU`~Zh!AAr4 zy)^_p{f~{X3a3{UB#jWf*B)GMfO6lT?V8sO+T$i@)^0|t7&G>3c&SWY7ndNwGdXHo zagIs$oi@L=OoW?vua-QO4IV;e0{LWYkjN0S%XkZQ+vVvyX#M%en@r)xKP*W zSD27d!OA#no#-HVtf)nT+;C=f)r*hi&e_`&Sc?Xe#C_OxYb@L2rjr+E5ksuLFXvs~ z!J(5lYcdj$gn2HB4ANLZe5D^w-ng9G41~g* zl)_bK1qz^3sBs+o@go)GtN@P>z8(&W zBEmjF9INW8)F!`CMj~uif6`s*K=M9mwK{$K7NP_3Rf(-dsJc45OJsAsA3G}0UZf_k z3s$5LDD<-yIXpp=IYlI&2^@x(V81UbA2+EceL)q^x8+g4?A$3%aNayi!vbRX09VJ zAIk6R$mp?tJtp0~k)P%sg}t>!=fr)xJ??q~%rOp_XUMzgmRCT{+Qz>1oo%K+@baO9 zX96?ve{?bOG;R+m>-wbS$|7@#@u14pmS{W3^?o)f5jKrzW?eSlhFafu)+X`4sgbMN zKf%mqv&2#pt_AlKo_L;RnVt6w3hZVDn3abjUszS6JcD}!On&~#7PR2s@f_`6|DFVA zOwBj&RV;_g*5E~OmwphPSA2qe{>sDLV&rYzfy$<{-e=>WvjQw$eYtnjw>LmOw z`&Qx1I>II9F9arLCnhW>u*0SNmTVh!2&O(dh|HNENYlgP24qM(kt0yav)7rn+KnUskd+I6`}iWo7) z4j=lEHd7OPtFbA-&Hrd|WECBAH>psj_QF7aKRl5p?}mZ*D#>+lSxNMj7g}5ExH)Yz zbL!j=Ncj?XFXmcb;057o1^=}a+o!bNT_G_2A6+rsa+Tenm7~lGIG<{tsmu_w?5kMz zoT>+#@aJy%JQ*+ZKN_3%`ighlue9V51v{ZicQ~OEZHa+GwK_*VNA=*~h-14Sn}W?N z`NpY64ae7)i(GghUlMLx-TS#*t;JcX%L@sl26I4KK~=oSr zdvPn3%N86IWvbZE7w+n*Vx?Q+2wQOQPuoa&FEt328ctXAznO4m^l8k{n=r(Z*AU4m zk?UF8VZKWzZ-`Ot0~37(Um>VtT94DBRtoY3y`<3R}gy#-cecWZ&k z(^2Ub&$?mK$#5JE^q=-q{mehQl*!25MZte`20J-gB{S>By}xhEFr? zZ@H(79h{(;xVo#xIZK3I%_IU&CG&%rmgw&anadqF%=-4w96cs3_kFbTFGgQasa`DL z4Qn`>iT*iy4N6< z;@GM-FyF@z;g;u#!nwmW56raRV^=3#(nSz(Z??d~RN6@+AT=3$t+Z27`iJ>Wsk zMs-tugx6V9HhnAC^(yc!jq=r_N?ZV)3}+_}1Lq`7wEG>&u2(o(=B8X!TGXtYT(`Zk zGc7-`z?H-8gFbryKyZEr2odR2hX@^Z0EGx&*NbroOurFMwld#>Vrxa6(c*pV8Se)f z@1`>3W+$nz5{30UZ7&7Y{a&nrFKiP+HV~!ORu8=;R%n=tC7(b^a-Ey@cJ%O139S=vyi#w}G*LQ05NqL( z*m%DZls;$)%>n?)hPe!rF%xsxiV`Bj_RF&-Rp34NK?$%kF_Ac^A!KqYb=7GoniI|U z%?@d`3X2WXar9cW@_h`oT&K*f9+C9Z>=zXW!rNe*(B>&1jxm=m@wSrL&HBlEV_>o#$Ha zRw{SWTG@tH*heT^&I`pAj&f_0PG2V(7Vr2+e)0GN)njbk_bAV)Y7NLxr1uNQF9IUc zrAFB5@=5(BRbUabg`6?)NulIgTrfEH(Px-$PiZKBbCCHuW}w-&4Y)~De2+?QCC#Uf zw+RwfqU;Xa>+6aLmi=R}puu|4Z;cA5q~h;Ydkw%CM`Q9xHcalxvPjS$^;gl5J+hL- z50geGEPDr1#n{Nx!6Ee~G$a&P@WvrJ)Qtl{z7Ms#5xfk=qMb>!fB`EU_5*EvD!!NB zGAmimz2HH4v*vi;_>~^%5lYH0f|}c61joG2VI;vIl6^ZpptQnmX5C}G=@rhkl~Pi} zJ~yC5pfW^ChPq|>-#B!M`Ea$fo{Eq8wB@)Q+nG{l7E6uF7-$!Rh zO*8>2*IS__Bfk(+^5K04b91V?!EVJae`lii_{w(&3Xb*#uRW>3@q3a??bnIi zj=$IZhQs2?Ji~zsJ>_dM!D9{Y98FUs`4-PfYeew|x23al0j8F9EDE;Gd7;NMI zy~atN2uJ$_=fW_^RqNNtC*%>}IpQc^Gk@kND6sop19E}KBl&#BF#Res_RT9PKY> zPem+{Qh!kQS(QjleQqtpIkIk0DDce?{;azG zkO9MygN;1gC$*CdDECVyzFf_5@g3aqeKxN76>&fGgZw|btl4ZSu0oIL+S;^P0A*>i z`kOM)$-b0^@T3mP>}x^h;lmTfu8FmQ;`b<78uew!Y*1!LjNC8yBx)}2B_R14I5gFy zW=?d{M5fvtf4G_|7~1T>3$|8%yRtc-3g>F%iQYRkERHCcF(>;3eONAP0LY?g3zLQw zrua%Jop`dmU{PY7Wevj+%r1)id@Q{prui&V3PH*YfaeHB%1{>V!?HIg_@{mawXQUl zuU4w)elUVgrRu)5nEN4>vEHZbAZ2h;Wo~CbI^u_7BL#EEXUmd2j>0z){B`}GF7adysqpR>LMFczqg{uCs!0Ui#q#c9CkP%~tp~u(` zxsyB!+x4Rr)Jjb3`3f|1gl6kVM{9}$qZM<^8Y-tF5V@%7m;^PlPNHP+88ReB-%iH| zs*sb3w~Kq?1GSoHeVSPtTDso_JZxkvRNukULB!ke9_t}{kMpaM8E!TgFv^>gtYM}L zNKjK~D3{^ElR-{jr=`3$6etihSf!CwgchaDd5o7@w{~Ej&%$AZaqZm~cv}?=enKz# z?JeL*1qpkI^r&78^2Q#>$SrGaPD*pp{AYtiXqV354N=pVeO+#UV3uxX9$(~|d%LC0 z`;Sf;kOHHlwIma2WcKHqGA*mso8b1;yo2~R3fHIcWmpVya;G&JQR%yKFYOjj&u%xd zFz306C)k^WSvu5=j63CdmO5j`p;3Vpiio5t|DHQrusPacoZB$W=L21X8K$>qGTy28O-jWjLn1Qy#(VZMIE1fUZ<_Ji zvAHvD=@k&`c`l_<#i7beo6jwu^;3+LgqH8~gfGoMf^Z$U^Q#~XdL^(I$KTx}vm3!` zDfX#CV*1HiViSpR^-MKKTmnFlm2Ol$+_H3=4F@+Gc=|l~w#gi;xx_+Q@GAz>~q^v^?O_X@m*()N~(j z7HsA=(DwS(japk~!1=%kk)n z1V9`%mHEh}M@>8K?FNK4u7lVffYMV3zI61SoXB}#Ed!Pa7J1zBbF}Lv(`rk-&5;Ym z#}h=;e{}q1>W@Uukd1h0qv~RpyCvd1{?Q@RTSnOm=bFxgyP+t zldJQn7fnrnORBQwhXF6#{L-O7lA&A$ZKi_kJ)*a#2%SXYkaFRmD zb(W4T;49|4L2p)S(s^0Q|01(@Fo9jA?AO&*$1rpls=OY^Az$pG$ z1TUv8Kpi_p7#F@e;ugr{5vXg^Ss51l+2XdN+%Q#{nA5VKZeDa%0A4EYb^c9ovocDzp%x6llzBnxIVPy@|ny`FvxQ{5m1D6`9$$%n#gB2Rx={?w=L6de9;b4k+`NSI?Ymu(E;#vBLL6{Eq-qo{SX+fBKhUoi zfBId$Z!l^$WfB^&IafYaoKdQqZk?=bh84>{(d}7k-0VEKxXW6+ldFDMl^4$A9wag? zF}13mpy0qyR4Xq(l(Jsl9BZ+y_8(t5oZ|&$d?(Oz^(-|g{8Z^63PW(0mu;^Qd5os*#{4g# zEA(ZD#`aP--hRGU-)H2TdhEda2V=&lKycZ8t&Wg~3xEH6fM;5b0gCuAh$6&)=a--2 zoO$CS@EVG%gVMcL0NI)6u|~SVqn55n!O%K*RP+f`pU00o@E^{fR~6~x^_O830GxYY zX}+BYtfOg{J{kY9lX10E`FU}LgyL)S0gt9#Ed33-K#_>CI#io({zin|kKPf3 zH>zmOB@0V?M~VA3@g}whtQkc*j~hIHIoVOE3)_AZQ7}8eQs`ONQ#Nqg@$|jsoCqz- zmMgLofKyy>wkwFAt)oo48RI*gi(D<~3#!w>1xH4|*-&acUc0u=R$=4!Kmlz#f2cXy z&knw;zq!k7f+=Gh6LK9tT#{oPEKkgn(_O2Rx`mJ z0v`c(NOOSGH`azMusw*ptoV8K1`+4R(Yq#g)PRyWvdiKY%qGCa+s%G!Ym)wB zy!QPGs;0r@hg&joe*#~7VDnsYG+u&`Z`^UFFK@6o){ux`SS{8V4%fOyd_$rbS(c3E z0x^w?ybV)8s$8sRu5QrG^E8-|0q7R%%Lpq6UzC~{UhrWKtk*be$Wa&+>gmagC8b0my68Te;Xng^EsX zXZva*TQUdXq@+q{TiS7x%1@W!H3N6o>L%+U|GxHsb+Spz!t&SPv0Hs6pA~y6uzx}g zj`}M>=g2VUbKjE>M1d^L7};`Z>Br|kHuY=p#Rk9Y>Hj6G)J?-pffpV`DqBQ$ond`o zOmM{s)=tJ+>5Z9cYh8}S;;X&VA)t{~^NDEr`yJc)%R_-qU7Xow33JSA_*UZ<@CBx5 z*<|^?zh=9lVw~n`Zw2rg!<;^^j8@CPm4O+ypCUx>z92hu@`Ilya|5ubQd=_!#L2o zH&cq9PqJlP2Z{rA8@_Tayne_TC-sZkvQSsUI#CKb&Gix5;?ItFafTX{=Pg>+v#381 zn5T$0>*9U!ms*!G$bCIt*1!Pm_O?H0gN1o!-MksuiK4=pP1_AtJCy_JWjZQ3siVzj zDm3Tq1j`+nhjV5~5=fA#xh8b7+J$%wCT*W-h;16OxK2tuomS+Oj zCR$!5;Y&He#5&veR5}5vi^9B=Fl;x7qfa+Q$OhdGYd!nbbjmdz=dU&DLf{QvO_r{t zP&bvDmR?xSUOkZ+P@#m{+GL9M*fu7pn27X+#ni{7gap}m?_pVQLRjh;34xUD=BSR=Rp&!dYpNR7f-SZ6_ zlzUVUnc8=isrl=S;kSltPruo2ms_)YQ-xf=xPxcm@mCjpy6Rt!lrPf6S~ZWDm)0h% zmdOv`ZchB-C8*()H_g+Qlj8g{`Fqz)n4teo*K&qd*~ZyJ-}>)l3P4;m84iV`E5HBM z)%jiaSS&jYPs$9C2qWmZrF-M9A1Fkca1YO)`1W%;E{rFr9LSz8gYNixos|~OO$t$Y zcgR@b(yeI`4ju<$;=t+2%y+hMXe@3BL8i0>8(q`UBQh*|MRx+|BdlM77F}G%t!s%*tQg(h!TXKW8mi7Y$M>EqDA;}; z0T;_8J0aoj?V>y2Y`VlUtm{;-n4dU7n_u{X{o2#@aR2tZ|BPgBs3<65wEgO>@i|${ z3=)dFdVr8pZgCDUZ zwKoMS7vo{+I&WV;PRv|t<~F_D{Ch2GLmrQ>M4m)7fYCYVRSQi@DxOZ3tac`S(cQ*& zUfk}fAJ0J-=RB5Q_s5U3>|^tvIx4KYCoZ{h%P;CUmVe>;>cUNggg!{0QG`GeCbe%4wVl01 z-0df8_B)W1xP3<_+KfnSz;!Eszw%dDtYuhCZHR|WQ#8mqmoUDIP{?z+Y%JpgIwT(6 z(qDXULrtVv3@tiy3F~;)Cg28GX4YfSyagoZA?3Ax!5Hzi2&ejv=&JC zmVvI=8Sz>dVGFDCdr7)=Sp;Q6;3e%yb!BQ>&Wf*yu&uIdlB4v!nhK}3ENz-R1SXz- zX4XQA%CKEw?Pq^N_b~8cH?-~mxqSvaV|xoppU5%TZ3)!j+$Q}X5GEkOgTW>F=;$@} zft(d8#wSjF%FP@L?F(O?u9fWbo@9|)_Xo}^a%biZ*i21{GQJ@9YOQds7hn9ZuswU$ zZ$MGNTJ8T_g;yFIyDJkgc#gESoJD-`+E^WfHH$Mq=*3Oh$Yp__UQVN)oto8R$C&=Y zy8iu_XDia&H|ja~V(TtC!S`TY`0(`^vn?$E6&c6|M~xrR<2aMtvbR2Q9?@aInk&B zdD`qvD7#RV&tm8>?&j*uys-HLLhed_)3Cl>Uw(sQT|(4W;GEg27|zp7RX?rOTc^1p zCGTJo>!hE(X53_c>Ziaf&p(0C$Y5B}97?G;F_*Yhy}K+ZxIUls%hYZ5JHnmGe2Sn) z#8;Q5*{U$lE~|K2P?VK5cp&afLG_zhh8J?BA~t;S&|$`*pdI|ow=vW*f*`|sFx~vq zZ>HL^eQ*}pI6WM+tlU^sfmD=!RNvU30Yxd5LR`(>QMlpQJxbP_)^ zndjugHh$fu+yJ|HpG2v9JQ!*hpQE_fSCb=r+7pZ(iIgS$lpfQ)XQlPNwRwt`K&_twsG`uw7I7$K>9c`XF0oR01EA zYl|>T*s;8o7cJ1Lp*4E2FlPYf-D4Tc47hh5=(Cn1*WvKjTqjgoE1anGilK}hHD2>We8Kip3 zozpSWla)6uKM-5mTddG^pZdK}B4L~#bSE{aMsU1$Nc3@WbD|Oje=3CSJNb3ArA5zw zFaZk6Io&yOt~1!%x6{#;P@Es;>0=mwN- zVeQihCGB;c`T>(4kfhoW((JU4#XUashr^?qId3_+16=s{)j1tWn~og32h2dmQr>!F$Xc zG}L00r~as85I{Z-mX+Q88#Ef~oszbzrYq)f>`8;y=+B66)P$1MW(pe`KFF%S86kWB z)U>c;!)vN@A=^_oePh2RtCwh;nA^L_S&M+^=7QyB6&&VnhS2Gb;dhuMCFZ=)`Ev=? zbDCQ#~Ahqsp656>@vcvdR0TbD=ke>_X%!#OeGoC&*3f_7R5g|9^#{y7JCM;U za1igb$%JNK|4XaisPx0To$b?%+J!hpT$l$VjKa{WUXg z9q88skga8`VjxUb%i2o?>swotwdwF5mATrzLFx_xNy53eepD}K99x28Lqayam{za8 zSQFjgBW%Y&t}0=pNBrxXsafzP4D9vAi!z$sVEWHh4@>IaKlkpl4-{$S78ZIfZtc#j z`!*wel2;_CxW!a)%U`_8R2qaG4VYWMF;UPo7KK_9b3043M+$VkRiwHkbtea`j8P{P zOCY(E(!CbbEagOS-aLD0%t?e!@BUrTqK^5Vq$GdJ3?!SS`$o-Rvqp!7PO#b`jekEE z&p3D%nv|#t?3p|ztUIyc^I6*VO8j~d4M{Hq$N__x)_4>eC@C%)AE^BPjm-AlonC*g zsmEENQp94vxCGfq*7f!ln6g-iwI4=F4ync3omR~iUP5xdVwFYicQ3oFOE8}dl>fWBcwU$tO z)4=wp4@j)>^RyNdLq5jTF6^$VDJ`#-)O}%3u6-(wYDEpTy~KQ+jXm+g`}D|PGE>-e zLx9CQF#<_`-W+m0LCauym{O9Qc)px!+@Z`_iQveDhavw z8PaP|afxFy0|#xeb*^&{#3EiXT`D|VaJkaEV+K7cE55}$0~BOV;nn-SQYFTCec@s9 zHtP?vPab&4zcsy&1TjE_|cL zX;`XWKch&=CAL-YsH#i}^*IFF1~GD;1{BMu_xVN7cfngdCdbrSW2&xIO$Y_nC2%!7 zE;va+;HLl86YVIf8<=>;RxJ3Wa(liS(j#NKCCaL`;NZDkd~Iijba!qeerHodp-y0e z-_Dm)>o2A+-Gq(DC0(x6E9pjf*Pf4iW){)F0SO%xE!RuY@^YAo4$?&|*5ocfC>VTo z#T9Ru7=$iN^ZzwUhIy=cs@PGdis-$|jb2+T_mVegYD`Jzj4#46evP+E4gYgXlg{Yh zX!&BQVbqd_cA#0HiFOb=?MprQGS|W_#nb#|=bAdi;^b*;es}d=&0&n9p=>72J^rzH zOenJZu`Nqwlta~dZN5g*u(@C6Z9d5N z*QfI?F-zu4%+kG_*!2(eGr#;1(Ujrjw?L8=QkfJ6x}<8@^NrwM(t9akfSVvn#*!{`z^w%-UZ` zY4_{;)rSv`Eyaf;PIj_&euwh>^$#%J5*+VYfL52MPcnh7DOC#?y?B#1giq&pQ@R;c zfjO~DsAHU72a9`)cUh~gRg>M`#2@PI_T|fw`V7A(v8yyy^4m_kV2~`b+IP_)Z}HZ; zLk4RN#6N9F%=PxRtVdsa1>z!_VaJl%gc8N(Y!A)kpQ9E#WDy8}suT0*pr;+8N zdmmJ!h_D@9-z9vE%AW%D;{K=Bq8e`y>M-`$yPYLW!hP#WzSt1zvcS;MUXJT>lfo=V z5evWVCSMO&ErjEMIN_q*DJgsJ*|+<+dl+C`*1cS)HnHGA*x-r z(=B`Du-Dopt2HllpK0ohUT*yORc`nC#}&%-mJRNVmExe!Mo~=ddW8w{E`dA?*qQdd z(b1F(qEh|0I@K=f82{vD{GQHzH6dW#hUv> zh~|CIV%1Bd8T_fTQJ47B-YQh@QKNn>pExFch_SCR*2QcYORJw%nXl=P zN*YoPxv+S$;8&SlmsEHlGB?W)UIVT59X^Z!oXllc$OCjb^1R_CvX|4Bbr0>)=}X`? zQw_&V0SW)`(s}6}UbR>+l!u#3;K+YeCBgAQkhGl{kQdd!s&Ay1dl#S#3rfAyn8`-U zz0KEm3rcOR@>*>x+1=haR$7}i!(}x)p<48@e2P@$3jHrm-o&=3GIHcX%6R%5cQ?ep zwMOTTm#6%kkZPpL*>H1>UzB2u_~}PyFzw)d+ssr4_^$}v(PfUF<`-qFHT9FR40$|D zl%LbW_~fSx<4h*m!-=bo&K9gr__{IOL7orB3JYQXwvfcFL7`Z*1Q9EP6+EnU7d%XR z^zlaVo4|9A1`qQ;Uqre~8mpnv{a!6phEJATy^+j9<`nP6`YiU?p3ql)tJYQ`KGf=8 z0pZQK)l~Z;WpXX4ZvX581h5&E0R3>(V^lu6n!BuTz^}moBm09_$g$xoRI@Hhyz54I zUB+n(lhvqIyoXXUIarPS=>|K$3dO`PB}1p7-t)Kx%-~k=Z)U_FnGah$JT_z*6FkH)C5)6Ee-Ta&2+dA z4RZC@KTLL56^KCl_A6AXnHl6G6hd_1i~-fo=C8>>r@V~8OL(;-Hhy&U^Z`CS(P zxbHNH^iU}LSU-WcX1L%R$+_1WV$s+fC0Wz)h+OsHgxaxpg40ak^%9!5vzyBy^bmJe&3-dg)4b+qE6KucpbRvv2K0e_$xgKswpXSS}wi zqf`0ag|%;2+pP~C)CMcWW@P94k%hR?TrcF(uL#G$r2E%bS6ekA>MBN zlIB$XQgXDhPZ-q&!)Dk`)rA7E(~|z}Dfe8Vx|&?T0g|D2D7G`>#wXp1*0}WbgV~L6 z)S;gZO2K*vZxx%^N={1=ulHfbcy2) zo`%e7q3o;s675xBoKcS+VKG#bQ>M4@8}*9(WD6%}$Hs(3*G@|5`;2?JWMz-UwsRE- zC(ACXJGq4+G7BGMs*w!t+`lrhUMUMOXp}n^e&>u`ZM+wKjp)%MFwcwTGfuGA!OQTr zUIxsmzAY*Q5|}#wnEZF-d2w-@SHB8S?PU|D;-*{9F%d0W+Yfu&K)Ai501fNimhOn&{XwV{{1KBsaMKcA7b5mQ@5y)9zpSdkYt- z!d91-hE^@Wc>QHQJ$Ym$k}iP!BC(iK>%VA<9y}=|Is72O7RT!gzHi9+OGBF6T zp@M&QfN`KDSLGbTvKvNo@faY4uZ13hiTY8pFlLf1s4?M3bDY!AyFlX(u*D~VbcI*% zyfAfvhMno#fAFYQbb7gorDm`jKm9a$3atEevXmlz{+;myoY5N~#oW9-csPT`DP{5M zCqZ{%_M@PjU%6)Yz8>$`x+QfEpcFxQ?G9uI$zII_58O_W)zKa=2@l}PQM%2e6v=P1 zfx-G&$4~>WpVf~9Ug8@N?2Uk|eQsNHb>}(j=;?D}>8#ww+SsN$n~iW(kZ_u|L;31NE%-=TO1c+Rej*@u6RQcml=)SV|7jjNTtvq^vv`*>flDH zwZL74O;rL)dRD1;6h7y-J9Ox2>@lv#DXtiLIe~5|3bmhM)i5dZX?s`TFccDe%yzZv z;S6<_awX0nF>PDre;SEAi+M{-At|+sEz9HiK)Wk2ojV5d27bw(nZiAx%{m0+7Id#k z*d-VVq%p9ucU`0Hk2hl~-$zcox8bXmuQd8Z9EG{ECrjdF1Xh0RGS%j;*I~&tzY~9g zw-rZfGP3OXgN~vG9opQ@}RNocFOvs!dWAXYnYzkEv|fIgC4XjNcY>0N~FB><{)l+~>Ixu2U` z>9~vYez!e&bB7)tb>lYIbtr!-g`e9ac0Xwcuo856PBMG=zbisS(L%PQnm!+s7q4PA z!Tl?f>}PL6$Fq`lE-&QpjGB%v)urmEgG2wYECd3&*lf+E<-lt+c51yANlFfIZZ?k6 z^)<_Syy=@(9CL599kfUQ2rYF)Ut>Dl2x35-PIUx4dFFRIciShFOG=gcv9?YYr@(5)&pSH(DaC35_c|J$}5*?Jo12 zaQ3=77^`bmM)ag1E`@s}U*+|>czAajt;1HMnUI%U8D9;bHT;WD8VCIUZyXxf=FIx!eBqK@$^BgIqfHaGzTuSz4g9Sthx9P z&$S1;SB6Fu=Y2uC*;PZcbO#S8dA_Q}n{V1X-7YK=qAW7Ug83YI7)$N~<-BGcwyYE% zBC{)j<@cVfc69gdpNAiwIKVQ32fC?wLde@Upzv4c85G}r34NjN=Iixgy{Ux{5})OL zeJS0z7r#DJFc$Iq&vRWH3~f7_ATTpffmu15vPWfxwJOdNJCJAE>MjkCO>XHIn~&$w73mf)HSWqK%KlFUiMCIQm&2CMK?0S`(}H zQkq%*=6i8PV0{1#CLH^ws!si=S=kleoxDwG(H8Bw?`OZ>+;;UYN?S29al9~Y^+IC5 zUghsr?_=|8^RBLIjB8>+PNv=28Q<9HzM&wBk+40bN6RZRza+9E~ZrQcw|}zm^nHfEhNs1zgcdN!l_@We06jfnIN|ZJ1vQP5qAi0u}tlE zQy`nT!K=%g+{x1~*IU^ozEveX-W|>648uF03p;+?1#)zP{T_@qPzS*0Wnb3#(}UmM zACtW*)8f*YGj3wGcEM5NQDLsjjqY5Nlvu6TIE2n>{S{pcBZ*E_RRn6ESYQ0vzi6#+ zm4CHqO4OFfzMlx@w+D0fUQ4`#xGGfmMoX2I6n4T&s`K7=#`L~p>jiu^v(0X0C2Drc zt3$CP)M&n&n!no#>%h$s!tmb24kv7WNW5F=qM~he9uPgym<0C`%LcSa=kAKVTH|T? zCQfJbk7n~K`Pv_=I);%RPR1y4pUINy54&f2B8OWS#zYbV^TiK=2+-{nt>M65R1|dL zaS!GGc}^%G_vv`Cvq$kRg&U98g6p(nOtDbsGzSyC$e)ZEY=mof-Y8P{*q%W23GeQn zd$&jX9=GTt@ULc}g)tMV=z)330_nxPTC`S{6DW08RGxsNVIc!rBieIP6_IYywg<-w zmnN!y@~Vscvx@9%Zf;HoC7SQY$Lezi_zpi(d_5^%Kw3VDJkLjmEKO6`i7&T6KmW+G z)=dY=@5$3&+h>y7eHZ_xENk#g)!M1Z7i@2tID|^wXJP4^-ozaF_qd zHC1ato$Wl__b6NgzPQa!6t34|1CqDEPs~Z#Q%o`Mj zQpi39ECt^Ud{<7MFwW$(FLP5Y5-{hNqp=qUlO_wS4htdd0X{M$)g#M)WE#~eoCh<8a@DA0|0@?qW%pg)f9Kl& zQEA7F2QobXfuI2xdC-Dz>5A>8zw>hQM|XiIoQQKMoIfq; zau^uOyBIeDdTlY%@^j8-0Ofo(20H5ti(cz8W|l!nSIoDygw2(lklnvSR&7LvMa^C2 z2sH5d;Pc&w1*;Jb^J_mM)c@)h!A=8=0)m3U7aab3ho^2VAL{4YPshEpn8Mh8j0XM< zi_K~I6MD@5_|Y%u;Ir$qaw`wUFL<-Ex_o_F(n?6|ePoML1r`5A%kV3U7wdzu3E4j9 zbNJ9>Rj-|K&euD<0RgA3)OXW2+uvn2-nW@2lw@j4&|N4S?7+U(NQ|GgxKgvNS|QP6 zl7LPG+TNp8&Ivnff0uJwzq~qUa*I7l(#tfZ?ZlrlNYU1_k~E!bPCe_c-z>8lcJ#TI z>D%HVIcSCHKEJ8#(dEkzI!XFmIR6+%7m>A*y}G_T&dUVJ6q|mveY0I|CZn)G1+%Q* z0qCSu%Z zck(6LVX1}*DM~vn4T$oqIGqO}s%e32+YM*XK+Y4v^KunF%o6JPg#ynx3Oaz#aE3iz z)3~Z|#O1KM*8`(y64(B>9M0!OXxT!NcGtTj748wBOtTeT7Z?CqJA5FO_DN#frNqK}WMBZl>_36JxJK$)MCImJL#C#*oXoTp91|S$GcNyo z!z}3g)hAGP@?sRZZ^?L_;ze>`jBMkw*vb_k-pupz94{DgY=}}|f4u1o$TBT=FrngF||SaZdnu&cFP|2%ceHg6PaaTf}WqnI4h zQJ92I^cw+fl8fv(Tn#3m!bfyqIQt}F_oy}ZSts<#y%i}1p1HD3i|^!YQfAw6p!tUI zB$OwYL*fzmbI^>1+4|hUZe?`)LgDtfjB#n`Bi*XU!9Ca~HRL62qN*g|vPA`i+k3bfR z3;=uSQs|vXv!-#l7V$qSZ)e@X#OdC!%GQu;y-s^JM#q`nLRV}qI>Hv{I#mRKwXFvd zpMP{V08<^_d9TUdZZ0>dqXTpHY@A(nA%C7(ytB6Q+a?3Yo^$R{JI#546F+apvaJaP z$btGGNfFx*%|DrV7acEfSZ(hHOMMGpcb20974aHb86)?>^RyOI=r@~L`v`sV)}y3j zstV<&W_g-{{uSxbw4|C3Mm68s_i0v<3G@4}Bst;Qq~H*@(uxQ_Sc&DJJ26NQUf0n_ zd;9%=RGXEb#1<1LR3(RuHG#_QYmG;PZ+X)GX`eyDI-bHM_lp)zT2c6|tQBc>JF#T# zcU8?nQx^wRQh24@mC3dGR6ZNfDZHO0mR#QEAjhcpi%~r>?a0C?E^YKWZ9c z3a17J8+cV`olj}`9i^G|J@ zKmu^sdAC6cQ@q1%-+-OrNBY32f7gRUxv+#aJ8Vh(!Lr^@m-9iH^2b$Lil2!cTnT71 z9tC-A^&$pQo$>wo?fMJm-+ntri)Ow0JNkDl@^Qr*6U1!SDMxbbgXAj*m?8T00G*{a z)lmSWSvyk~dE$dwl^p8ka#+K#089?->>(*)f%`NLt+wpp2ABWgW(l1*D~m}{+7JNg zW-3T)-Xwfw8XPn0IhB4;P-+W+X)>wS;JTcKUG`tUY^eBZI?Cj19tY=~ZUa6^ej}0# z@iA!ZXw7`rbC<@;btt~|=d&H0Q1Pbdb_*{_IH^bcreMRN3}?PoY59q&Ym(bhKW;7T z8rk7QnPgi;(IG7^&Pn_`*zBErg-#@xS={E3#uNtqqJzo)lPUwk-_XKWEa$r|kK(sl zpeNXP-_f_)$x^?Mah8iig1Y+is!sc(PZqa%So0spy8ATOjc=C+qQmx$V6k#L_t|oJ z6Kusw>s3V%Qm3{`#zGg@0*ET$`wt162`LeBgKP=;G$eY)-={3QK4BdX(SkA}4&$=e z(nombL@)2r-QC_GoRvv7Q2I^x{_Rn+-1iD=u)xb$roYd(?(<4@F}CDJR48U0wxVug zHV&5BXr_PLlBgH_fkKlj3hLiPfUnsV{V=2f>)F+6z ztfphv@VQTByWejE35=Y3fT#2$YFusncxAIiUcj?l^U7U*NuDBs(^7!U?GU2K%cA3D zakue0<^E)1UMGf|fp0za_eB~~`DSm}7BBUntv&D^(U*O34Mk+Hyu$#!VF2;(PSjYY z^;GcsdeU)P#yY=m${Um1kX|2pCu#7tLHdN&^s`NQ(SsZBRskzfKv#xo6SCX#@a4em znX3yaCan<6>Fc2yS;xtybG7>dBmO8V}5ZD_0lOaE>~KJVfN*#M_rD(KBd<@p!T zALeS8gmt{S;NLV9Mr!Y42Q<&do$4g``~R}D>mQf!1N*%Mt~0u8uHmtGYT_Tp7r2te zGJD6tqy8CpxN7(KX2ASDc|9@lI}J5A8U24;OvH>n8fH3_7cyq1wqX!qdmhE~s!o%1<;B{sPj|+)%T>`W0|Q zO#B>({pRb=~Yd-&b6L6^}7PLV*I@o{PM9b0P$VvE|5OJ^tk`=6eUyJm^`j@LoN z7!5{FtJo;DB3vTo@2V`d#u)<3r9rZvAC?M?GfmV#-fduAwvT^9(;eMj$y6!4 z_hwk|c~05BvU?odh1@q~{PZuh;BMn6Tr#YvhEjU6i-2QtDmkw+Z>lM8wI^NBTP(_@ z1^|lodrhXHj(m=zWX&y}$(b#$UfJc6Yu!l|BDk)0+Kn(qIGaP!Msu)uYwSn$r%@0;?ug?5 ziOMdHp+O1Wo@EWrtFvuJf_>H)1#-A-#5*L8RAP|M=kpE4&?5Bbtq5sk2%A52sHm>orJDN^X4H4|dT3_b15xh!E4!d}*9?wysV z(E{%y_ab7?T_z^S9wL_d0IseYEIP8%g{oA40AG!&2NvT zZ(>V!{1}Ctnh17X`E0d){~0aQKmzj7YaR{%*Odd?Nl)w7CwQwbqR(Ci2K1)yleW5T zc!_i$d4#9iFfgtR*6Pm>6TkoA4!0W>I;dp+9k!68%H+p5lZ0u`w~=Thg)Qb-9yp#k zC5#pvj|p&HP0LP(Aj$)o{1(hwfx!N2nfrN5X=~Z}e`k6|+$W{81I2{?xMXJDVI9yZ zZW0Szzq@4v*#~}4H+cW_B%BC)uOb_mMIdl0e#nwJHT6czRcT$kLsx$k>+asXva4cc zU!PRlvij(+Z#%VL80$qh5c~Lwn{83AWl2}NJC}>-_ruz9)`q}ayYXXVbm+6sfYT+_ zY&S2?23fjZK>$Jl_I0i6zo{hP7>`UStPVYSk?Bbp>bmo(zkhy(g5iDWOjqdffcKVF z==A))kvLs9feCTtH=JGcsqIEpL9GbubNE#JLX(HW}-K~BtPYzBUk?B75214&_-`(&>wonv<*=XlTn{# zi7u4en2sGGV65j1>|NGx&wfSpuO1X1t6$n+mAz!D*g??NnwO)eaX(#Zn;6}ueRxQh zng2p87D3M+ugWF%^=N0xzfzH{K+k4|d(8jtgp)~O#*S{y8eYuK(Nuwbp4S#rAnm%? z+~DHUe6VadfHz!qc+#t{N9~iP@@gEOaiY-$L>Hv9^rQ#)*ojuQnGlz@uiSuF0XX zkWf4#h2qUjrDjUDB-Smq=tofS1?V&qZ2n#K)H~t^}7MUPm_Gx6BP+ z3ILSusN|vNo1uZx_JN&ri}m=&j{lU@0}d%7CO{#UbeZUO4D$44Mr@1Py=_lF>IJzNmj|ea2!lormGIq%9iM08Wd1UO6KU$9{825wrS=w4uXd zuDq|;g+ZaP{NA7KseWsbu0K*14?5463}30?p5IyDJv0Qlr#n>?nxm%8d|LME1LuYx zr;#}mL1C7$tkK3P4hgWi`?~l5!2uBZu!}OkULY{ZW93@f?&1+Lv_XsGc<6-`$fHXr zV*f?1+ISW_$>!mQ0@FurFwM+bD;;#5#Q6yh&@!@upR5pn!5qvWhHSTfX!ulHCT03R zYHLXHy5j%yraaHL>m%pim6C^%E{!@3dr)kRX5M!~#C3XQFy%?HK*Dm0U?ZLv@g6>D zE9Lz)wN0vpigDQp`ZID@7Fawv$jhi9){#> zuOxz$;9aLsq!qHW!ku-$t`$8o61r*(b#y&utjXkJJ0p34c;+R!jGw;P^DdQYXqYN4 z?d2hFj#L=b!ff`!KV*K|s-GQIg09WCCc@^LAy(A6`UGIX-Z z>xY1HuHRxX6 zk+}-civc_%J!$rX8wkY|qpmlTS@0<35ixg`6ChnHI!vu@|NLf1DW}J$qgKNw_KmJy zX>vi3ctv%1%z^3vK1px-8$Fw8x!EO+Bv;%J;`+*&3s0T%!N8>coOiH`M^QhlUML-6TT@;7`uZT-z_bue(r&C* z2?MyO*MdV6-aUdAew)5^+LWRd`tBN)mZQ{%Ig5RT1LjmnL#S)}Q>4-&N3(`KJ8lI5bv~k+_?a~BWBVy^_fMN`PgMPZH`QD-- z<>BS9puSljMw*hHS93bh6=!SggH@OaK^M@1rmSjD3XQhEOEny^8xaFAZr{-p5U>T%D?=2IDteFwPhFfL) zCHlgSv$2j!-@#4%Jm;KLuZ{R4p_b1^&E2+#`Y%CK_5H3tFLx-t{b61u3`rZ_D%d() z5{No!iOI9VF`;Apt~)N8uzB(F1}3%#qr?xocvc`o)e0}72=-_7-m70$Y1R(qLuMB$ z30o!-vL11MjZO`tc2VR0b>qFqPBFJcin4ipEZSq5z5ZSMIl*sOlT6T@jE&7V2!a-hi(| z{>){LUv95_=dj^_@~B$#phj-YQ5&_zn>pN>>WikCR95shLG7&kru0NQ)@NxZN0|nj z&ghNnaOH6YsD_t*;*hs2!hbi7u^4AZ7r`VppOCIq9Ufk&qU<&;*z}0aHKkwD3G}Ls zDr=Z!fsri+8P5a}Z7%=v*EvOoZ93kkPAa@Su#yXQkAw|Q(LEfPE z!(7b2`+`cTt7ZoCYMm{_N4G2PS(l#R+Nq~#PPJ&t-k!})q@&99gY$bW=PFpf{Mu7) zyWm=(7JJf5XNo!XaZ5SRdsX)ZB#!Dvyr@4Y_=xe4`M7#rp7#jnwuNj>Ov_{(C=u4L zZh>dphP13u-qW)`pWbzoeMA2sgy4f+m+gi4%n2U3gGFx9L@ih9$veo(N3Yzf8)Qp= zR%-8S&Wvl`xoF0Bet6E~ zLj#FinIRplS1KrDC7igBsF+TWgnCKl^%@%-V zG?H+(N6w7{+vy78HeklSl2$dHaL!cZV$T(6ftu{$(SY4XbfOEij7D&hp!mXGh#bz2 zv)g+SVAK&faq{y8_IlAkEPdO+p=S8SwpjiH-?0yLt;S;#f*#QUsX%Rv@u35=ST^%V z>8`_@LH+$lsLL+ddIvwUccg~?P^YB z$PMB3&f~ZSYdUp-BxJFb-7=5+|Pk2Kxf z_|V+*7_St+va5@Lhlf9nz+rV7a`M_{nG~(t9HiTzD=BT8m;Ek3^%I|LaL;?b(~6m? zordo0)X@cHfsA7i8|Lfo-#{WDuCHNrI5mB=Tj*H*gqi4d@kk&RzFBV1`;PYx!%Cn3 z`R*WQ?zFV+9zuVcR|zt!bK&(jGml9$$b~nQ@2*{gPuNT)Eh*>BQK)PFj(aXgl6HoP zuF8R;P;;zn1*?nJ(BxIV`R7;OJtA4w;f>RVb)26@aVU+iI^qHnCzggc zBGh56&teD~a?tSW<+P>#lvZ3=Hp+a$b7lv%a=vq#8EKq;cl}V_r%zBlt@HF~Ws-4` z_tRvq1WBZMJRu5?Qr80$ItipHbgI@0I`Hcq!zyT(kNGZ!)*+HacV;Zv3%jf9jXy@%@J!F;Xu?BbdUZ>@wQM_f zfC2;dDq1hKYpb+;1S>M&{iYfO^TOY@k&|S93>}I`-kjrb00<$r@Uyui!w=KzT-tQ09XxBR7e4?{cpwzndIxqdRZS zZyXnc`X${czfmk*hPymERRb2t`~~^IM`rU{6Qd(2Z;iuEh&3;x7ZWBEYilniem2#4 z49cd3_D<4-eU8Az-G5H$mfET>weaW5O-*e34wC6KZTWa)%io09xZiB0E;eE<6IjI#XCkWND@w{CI_?hDR(4vd5s%# zmpiMsm}YIXX>T_CAqb?X^J>7-HSqUr3Ag*^YEygOMgMA_anK_Dsjzm#d3!jNfT}n; z2@CT0yF$o^<}O{~NWUZnk*VWSRGPgoC}|4FAwhJfSlyYw_ZD=Yq4Q6=Ap`f}!> zCR{B-U%&LyS!RQrn-jG^tu>B)M5H&E*IVUB_ES>{NEh2sXqt<+jPm7GT`k17EgkC8 z(1Rd1-g{IEI^j=GizQ_Rv%xM-_|+!I^uW-Qjyi8Kt9V`m8<;E(l-|?oVVX63==ca# zqZBzK3i*&AT`WSECfvF3@Aj#?qP3}Lu|TYI3=5}yP1y`OR(go#^K!)4J|oJRFeD3n z2(^Oa(p}6m4Pmu;w49$f6BqY#-L;?&X9`hI!j_k>_GR$A>@(lJM=woHGm4_}45>ox zsJS?Ut5~-Z5MtT5`!>>7f6dUV<`}fhR5c)w?opa9PBD2+8W$|o`a@DXCUv?h^o80n zIeCfBV#QTooM-3x!he14!xYJW7ewWYt|_A{YZQ63E}W;HP%kTN%>q)rD>WJIBY-np>@2yTRDN& zG>g5ytkixHa@U!Pxkb4wj<_j4ABz@oFu{9=`tT1hr}5{#eNtiNP$&7nzF-2cM-J$s zb@D%|Q5L-@z@d?=tcpcwH2TBR3gT6k^scZ!04i-u&P}UP3A6~?B|J-M1v(Bx&WrG=CNN#$xy}q0 z+esprs68bOk0KJLGgoF`$L(RAo8O=eVt&YwFKaO)X$1z z3lsKb&u@cHj(fR{mG{px+dcGYFGh2@5zA_+rkV|3XK<_q?)S4MUQlN;Xm&^7t_LcY zO<2kw%qR#nH-fB_n(dwz`+l`+vjgIsGN2IX6_$^A2@3bpmQ{|n zqVO^Sx67-F#G5|rl&kzDXB^3LLd_i!!h%V@$TWeO`8ldGBTM4_M3aPZ$Vc7Hzf)@G zt7KoKB_c9w+)tRR#!BWP-pqski5lWf(C|BxU`SZiOum6+X8p6$3m3$|-PQM|%QE%N zkv&}^bLC(joM>>TZRJpxj}JXJR*tjD(IhaW-(Fpt z->o@Pu^K&u6_$IBbTygWHeApuWgNnfsJ95!@z-{9&v~(Ne*`&bCtAhBoX9mv&HqQ!Tlh8Azw!Tg1EKZ!NF&^ebWCzIlA}RVHefUo14fL&#_r$w{J!7sAF#(xywCew=el06 z*VEWIt$Z_BgH*>O5;14fS2}T?xbXUcPH|`f{wB3MIsApZ_jtSBdc67S5lA{7QXM<_ zEofCp4xHjwBZv3nKjfl!S=f9R?wJaMB^y;97?kn$qEWj-M{WTaJEv zhV`4F8tg3vPMbGbNv+4E6e4jdU zyK{ca$rmPwlx*cyoy}v2LAQSs?2{MzGheP=+FsYRtTl1=k~`uN| zCoJi_*=ypAJY9OO%S1#aAsp(m4wnm`V+rOqBoN*6TOTd zpMmc#!{3E-kw4ij0HD904GC>v-0f$x;rd;^6GcUCTcSAUtDCl=Bb+CtZ$caAa2cV6 zftOJn7d_U|m{x%$RX)E&OR8_l9dv=$rcOt4nHv zk{f$(G%Yt&>^V5mo}Ig@Zq3}#~i}FQX}K# z{&!nPy{PlI+injEo4vS)r1303l;cCSy;r!_Uy`JCBsV6dow(+>MN-H?qeTUQR9C4? zCkqw<&ndXv&!B!j^`^6~<)}F251_@b_^Y*HZ$_3ig5aVpKVy&M_eB0(c$$GNczrtg zJsAI%wNd&aw@uAkC(EZk)gvBA7V?*5&=Q_32LI%#uEn}4w}tH;7L|<0N$lRO zez%x$z?DOvmt7Z>6c>*R8`bakaS6>6&NcLEwt%+H38GXs&#@;6ve-s%zve~qpF2Lr4UQU<+&i7nc)$A==Y#bD5<7Ej3?DG5!yy7Ys{6_&Wc&&N zVmu*Q7r8^2wpv&@i9@fiUfsI%!h0B&fUbt+MzaoHJ}=U@Pv1rD!O?@JJKF%6SL&ew zq-0;hrf>>8A5=wN%|Y>=%Nga-uH=1MJqYEhQiws@&tK;B_dSW?Vsq<&11W1UPIZG?~&4$uk|aRA||1z!Ec`H+IGIuX!BR;)#F-OFhuUgOnYvs#Zs;@1$3q=+R zh|?5>45hW*AA4C&doof}t>>FVz$IaL^Tr#!Z|zgtXc+C=q0B?6YS3xjLOh})Gyr*o zh_0!r*VIR)zDQiX#n+QHiN!`5`h9(Q=^ zZurOWK}20NpgD4rjjCS|99wNNv;w{D_ZCPOmX}>fcqjbNl?K=7WxbD4iRyQO^L#Y56Hd3Od2LLS zgN!zr0#yrE#|G3StB9JYr}1BM76rUKvZARLs?(9^)FJ2CbBRZV)` z_Ph}_SqtY8vwp@OG`Vv94htJ5UTgc&L|n#Fj{25crr26nxW60$I_%lw2TGIjs?6N29c*Fc@e_QRvMPoLyfm$?58i&@5h z3^s2|uh=GGpJ(%5uo|Hjs?{3GYU>5G}BjXfd;LbL_x|XK8iS@R(RhgEr z|LN4aH+R#kZ*+dICj`6$10kraU%`so=Xx_fB;t8U!+w z9_>NDW2H|g%k48z3(%!w)DQqkyFUSFK#a-a(Q)efOS5fL`PeQY#c`tzk*+r?I$VfB z`The$l;n|NXRy(FR!^FHbOH@liAxPn-B?LBzgm7PJF3V4MBHnp5rSmng)RT1bI-d3 z9MIK6B>5W3JkbKSb8(%vyLB+i{S{w#5-}+LAKhoZB@CiPa;U8OSa)F`O6e7&br1#4 z+;mF`p4%tIP6O0$;nr~k#@Y84F9GsxsSaE<(01?{c`KTpVqs6?-sp+olZp#>0Glsb z_U|jj0ZNs@F9K)M?kVS`pw)#It5Ir04gzmz8}JUeHkWi_mBY6Gr_P)#2%;iU#sAT* zu;>3jd8pCP@>zIV3x!k|hOe24L!PVTonLkz6SmFsb=#%j(tT!fX_LDf03g`qRXcG7 zSG2%x5)h}VqJik7G11zA(f9bWU+$&s0W#wIN^AW8j>6V=Z5KP(RIPp~wvF+3xCN~K zz7mL#H9c^?5Fn2pssIB4>-P}^b5M`$aLii5EDO%nER+yMnZ+3l1S6X!8bg&eb8<`0&C;P7MwmQvfPCF2+nGQ7R!v}@(Q9QtZ4w2VqbS3AgKIU;H2UXQ zZa_8lZd^a1UGk-uAO(;`UBKxJ)~fkZp=5&4z0>Od=;Wtmk!?aQ_^Y9^LFMk8M5{lW z`wEB68$P}HBKxX$URLb9uT3i)8rwCWZT5S*@TOkr9D5qYMwW`++3*_MAs75xjy$Lh zada|yuG&f5%Od4{Y_CoKs0j*$`3YQc$J({J&CW}I!I4&wna{a>abE1L&ounX5|ZNG zO5eg>h~Q7ZOWgm6n6P3u?3a-r+SrM! zKqe>5<>B+PwGFrVS&Ua%O3KOmipVjK@}n<5(KU7G8nm&*y*nRudEHblmHtb|^e;Q; zle+D9vaWtetKo~9s`>=OmXx8-Kiu*~W;5Q=@g^GuDgo#WM%(jTKM=eAcMMVTaYK_; zPgB!_^E_{r|LCkAnT~pS9~@V>j+f3fWy*U)YW@B3)zB^;ft&heNP4o9k--{Tqx&q> zR}V8;`yT1IM^#)1gm(n%MiHpZteVp!e7PnC<>FUhBi_!%x$)p|hG%m5$3Ezn06kT8;VqPj>}wE^ zK5Fk+*x`x$MIUbdc;ugxO7|rwVQL?_67_FdE;n%|`dG5wb`Z{p*~@P1Ov;)h?h(BA z_m)P!ku>1FcHHB;d|Faq>yIy+oxjoLtSl7GPGg5cC-*86DFNyHO4MN^3qS!I3CYhC`v+qdX5v*HDJ=h~IF zjPD=)M<@LV*5Q5VN&BL_K&iEo9t>tRXPsF4kM4cgR@ByE|LH%wPTLmT;WoRJIuj!L z?I|M0E&r9lMjY+;@9qifgz`gAwf2BUGydKd&*e!&A)VO4W-|Enbs4rz<55Kj%Lvh9 z{=^#4oD`$(H#I~OsGCVY5$C{Tqg763{;VqBZ3MB3l| z%?VG~H`{C;uK~h_d8xi6vR7p`Ce!Ho29GWOL*v!8% zUUrJ#G_bm@&m%EBh~{ghL%B&Es#f-|@;gY_hVKEcA6yk~JhKsf&j<%uJ8iQ#rvE3^ zfu(c^FB#g*BhdHqpvIAXMfVg!v)aXQant<34VLihz1^M`i1cd7;H#=dxKWLkey|p+aE$?l&Fm?icl}&>uYDwFbfm0qOT5_) zy)I=RZ3obPtrs}{qcaaFG4^WVU2&JQ2`Gn+lox_B!&fAg7W6jXQ#bE6SgsuAx$1V- z!rry5(C3(q)%r>z2H9~`$(sF*(@76kp4QPIpco3=tlomw>PEp}w+s?~SC zxutZgGlaH+f4JF(0N849?*Nnih#WKqwEx_=)+T(yjvr~90$aAd^c_)?ooM55k)9m5 z_D%(b9kg_8ny~s|T(h!zDH(2aVS+6=OvC-x2>Ut``VTgu%F4mQ5$Uu}<8V9;KANjj z@Cj?I9yhE5yOsX*vs0mO)#a7b5|nRG8*1;$z)kRfNtdfw5fXx#!Lx%&oAIba6vxY| zxl+v^K6(KU*qyPsa0@K{nKHXN&feTxbWO#=$t2+jXaVUQcrp!}KRr0{ydicld`;m% zW=h*1+Ek@H&mRdnoy-z@z0(7u_On}YuD>FlF9dtqY3o%#kjREBJw>V|W!MOwvG99q zmmBl%&DHvNf`a1J&zuXS(n?5?K`RYLW#|pt?Ic_<;(@MWgbo-I4T*BTu0w_C2}>R? zHBd{2y|AHwV13nyo0Yvb6cjr!UmTaybl1t7?;glUA+j=ue+>*DO0weyxFOgi6ow zWKLol{7=&p>!fiuO1Yipcq%0G=|JOla?6-(NSSEblKnKlSyE{4;~VuGkzX$Kb)0&+ zCcJr_sN3jxstH@LTQK%ORk{gC|FE!JIfYOv)+ILL89iNUphCfnPaOp$PNTS0j+i76 zxBVMVv$nKJ&^p0Eh5%L`<)Q44eT^&iJX8sN8P=BgZ&u+ivfsc{y)pCQ;uEfK)DW3z z3qbEW$ZYrJ3{MJ5QKb8c%V)juzHBWu7^k?v1o_?BZ+9leUR_%B+jSkw*)L(#&h6X= zAqn6k`FNtxr49I?POE6NnhBqv9hg}VZaY3j3d$2KVq(hyV?xcHjabW-XhU-|_<}NU z6?8RR?-Ndea_&p)hB zKieHpH{ev^qj(mF-wPkIV<&Ga$dhY2n>>HiSJWD6<|enOCDK_fc7GIjmgBcv+jcX2 z5`VQ#+DMB31`!?QM*y(x*iGzb!@RtA91AeiUEGWt@zi1?zD+(5vc#AcYFaT%Hm@{q z8^NY-kX$p0=m(rT(dv1R`?)Ga9)22;N1945<^9TIp~~;KV4>0KpnO*)$siI^qW8Lj zyWl%{i^t907!5t?jP8MrH)e?LsDszDqdZ?+KZ{a;Vj>&slOapZ8f;qQKth5{#}(@y#>SdNyl=8W?W2-8 zNX`e}=_U@R$<+8!i625f3RQ7^D@UqG>6FuR$svV2EM>{Db!svnW5%PCx9|B+!jy4Sg~(9wuZmz8hM%P@c?)&5xk`)why=u47D;koW54@g}oekW-9aC_=WsJs`ZSu;c!7=onf~pr!N3gWD*u1 z$Q3UO^7i^2lWO(yLyh{IZO@e%pQT2D^kBcXWI||lTp(IrAnP*vd&$bVS%jEc6XM}$ z!LZ=W6KR86`?TEjn|jj=0VBC#nT{4d{>v`(|3E6Aho1b$P02wU$j6WLvJMt-M%elVSiYqA!M_djb-K`Gj}6V7sjs4riPLLOAej4p z4o={@EG6%jB(y|#!mne@@Jn3Zj79nSf>r(%Wl5cMaX{i*$+hqLw)yREKUWzk$jQj~ z0|`B=*YlXO5+4onucKR+)mR#;AfKjw=wRFBYar1!?F09T|M;GMR$VUNY%)~L`UILF zytbt|KxBoGE|@E`zN1B|a}otT69zU>cDS#t^fy2D-IsyXU?Ni667fO6a89&P?)v{IR3YsFemYx5`>e0=-@GpA8N=EuS z_Q`juLPu}Q3y<<>QJ%CE6#S9n_gz&04N`!gnu5BztfZ zr>|$du<#Tr_dU(hWT_$mDGbZH*^p*Bll-muc77pl=)_{z(HvlAd;qcwd#{DIOXaHy zJ2x_Y8`i7AYWXqmLKN#>loKx3Q63i4g%YU=jjdi6cbRVWzi+EbUb4^9TX~gT6mKhx z=pAjmdN{#NXe#Jt6-^{Ki7FmA{b5fNRoY7#3`M1iRP{deTurRYR&XT^Mt;>Cs48}H zM*sQUFZ$rHTdC^U)BDiZ+IvoSwItFi;1Tz~02x$G>xkbh!ydD$nHm8v*AAi|bo3>; za)d<6+@~#Mj<9mTopELnM)x%=2B#Srd++KQ(aQPwNIMxFB?+6I2fIE)o&AuQP!4{QzCv% z+XgC_5@|My=N^Sl7gsb(ce^v@pl?|2&XcT^VSnxmDV@+Wc}pj^URlg_)4vOOy>7&7 zG0fwMmu@tcQFz4gCa|XAfp5x~5*=6B0^gWJ)$h4x{Jai;nqKFOf!|0NitP@{0Lkc& zs=0kp!P4PsN-g&3ytnPnb0>FDS;SM% zZ+(4-OIrqsP*lmbS-HY2j5bON3{6d8*6fcHcGB(VH=9dJd_bEBF;l)tht{4qF&eK9 zGSPoEaN$o<=&x^myFL%b>~D?#yj|@sfaPd=(?yDo68EpsWj|7Cfmu$qPqQTYs1mY9 zCyrezne!!OCKLQcemj~yK4CD)l{dC0Po_Y%M9SqgaxA>_FNvjvgblCtX1rX-%&cDt zxIS87g^q%lH<;Ja#_P4OYfdGuK@!$f2jh>vHD9=;^m8*fI&BP#3&IN$@E-X43;pMv z`dfH{v!XS|u(_$GiDD)VmoGku2b45>$+;f9pE=1*&aT3-$vsv_wdi*?mMvp^B+>x~ zT;BQgeQYSTVJ~m_)qM%c?GR~EVi7;=>twEjO>I3~$mhFEn-$5PY_k4O*p(5;T0`E@ zskwoC8S_U+&^3#%ubZ zkop5%jor1lbYIYQc_T`dA%4YQ&ZvzdHN)&VVd!)BgPI7Oe5&VV_~p*K4b`=n(E^2C zM!t*7Iy1s`Uq$N8y*d7TOY0(B&^a;MKDZB(ffOxlDEig9&niIPL40dVe`-wL+bSIo z?GuSc4gLy61PC8mZHu(F#`eGz+8i-`1L-$(;#wBJ#o9I6J;*Dtq409}6MQ|ZAk7=+ zA^I>O7J?;t;N~vk%Bu&4=#aR$vPMtT9zT9)mcg>YMv3#4Y1E?&Bab&5d`)cvW9&1( zf7Yg~;XYOJbGoc>nazp`1VNJC@49JNPwO}}Po6$1Fmj(tL< zG`0JDz$@47^*iAzCT>NM1k_h|*bN)SahRouxxM_Zz=Oh>)2N5$+DHFLYrTjwtjPlV zy9d5H1h0jtR>tdjid^b@a{Xh6I{l%;A(YYew$Vn9BQZTT7i;@u*;wfyfFj;-_@lAG z_osTG+?Ti#jP~Ymm?OnH@B=I7BH^rayrQ?9=z3k-*^4wPWYd3Gh`Gyoa_>~^14kQ_ z>`Qc8={OTbvnIy87D2~+Z!n*POYKVWA85iX<{i=JgRs*+`(E=?;LF|q-tW}sJLF1H zudjio2uB+d;*aw(pugz`eFOwUetsg8X?y+y+hL^jNC(k-cf{px$fjM-xc2M%*eY?Y z{Sv&gjfFOD{HhYglFpgsf8^@HalrG|&+NcqU~#ZEieXoBy8b^pdjQa)6i1YVRJ8y) z?w>7am-Mg}u%!HEpS|9=rI$TUs50&(ABQH>TR|TVY`C-aa!N7H1x@Nd?$Bef4s@ zq$pkrbE!Xt=`I9|qVC>O6V119$^*AmqW9x}+O1@b zo}*^xBe;^T^5zqVq3|=-C?MV|W<8&Q^#Irr*3B_FY_utZG4Xg7trUML=?NfOj#)E}f$1#)EL;DU0D)d0{1nj-74EBZ#yq{WZw1HEI%> zi#NQPgW0o#?}H7Mq1DJ(1#;n(;yu61_8$VJj-`qCOI7NXF#&7kB9_(F5fNzeVan)b zL=6JhH;tzB<_(_Rpmm0`))N&T?qKVhTC>$HlIJzr)6!Wo8*)JpH8&6VjYWbg;nolo zefZ2xBe(jKaW`<4q@kKFg0FMFFB3bUrSnwx0&+;{XXOluo5)x<;hrW5d+m}tecyD;^MpFDgr4P{DuWd$=vfqj61g`_bHz#q$ZW|8h7cG*Z#W#Ad)mT5^ z%D1|nxXdZyW2{odtv^#TjF$ZilMK1y4~+avjtjq4*towq^%CjM^>?(q@uuSb%gBr3 zUKa%3l{Q_Kri}^Lqs^TzBXj3*o`!GLf@$pe{K-Gdxb0h$T7J7X7A6ucpQ>WiIv9M6 z#XQ|4ZKZU!J)K-d{joGHz~m^`f9fEHwkB8bW9DsVZ6J|ZTPowA1x=;Bz%JqJ#OM4{ zK1@s7Pk%wJ%RpIsLWn9~9{PjgOL}+SAC;v~*Pn%<^5DWRTL!`p`rXF$plYr;w`YyLeA40PYU%vxNyTInn=r^{y$f5AHc6tt%(b*6yLxuOxv~n2Z3j6 zGQtz#gY4z#Ycd$FM+Z)h_Pj94h>BD1LyLqHj4Tf%eBO?Yh=^6cP!_7(K2v!yC8Syv zN*KI%fOtD|=UxXcM{X(b2vz*@dqe0Sv&0Lh^Q(v@d*>+~^b{hCBZz zQ3J{lvid?Nd@y^Gs@Z+kMX^;($BdH2;SuW6?mx=kbn zqgFozm9#H@=fq+<5IEnZA|NiZ0Uc(_A!pd6Vxea*%587Ov=B1<^9hZ~@+|yIC& zQ7K&i(U}o7FNW~?u^(*2sLRTv0Ad2)@k-$+%hk4A<TbLSYi7)KJe*j-l8W^bkxA9w^jge-q`BF z5&qUAPkxc%EL?A2%IRaX&km29`KQiA-k`jlNihKu^5>hc7pnc~nt0dSRoj@!-w&75 zsq8g9O@$fL0oSqEQ3s^6SWYaj@Ey-DD-v4HykU#-a(QEe`WMqZ*F*B8GwTVd32kHf z^_nL7yWTb#Www?RY(HykbiH}>;!!Lx^lJCu0h`u{uQ_gq6cV8C&ZBebEpSiDK^+tP~tuQnb-dAyXd~+otU! z=PuLsc#r07h%;J$t9jeFc3|q#`o-cJc&)#H>RDWoOID9+3QID%Az{+3cpN>h+}H}=076-FLb68GgNAp!whw#yQThxAz*dlyq)P9*q zG7v^JFNKyH1|hg~&EgjNPS`QSVON^-L7`EB1+~45jlATi z90zjbyJ-Sxv}D5Y_0#jLi}4Fqjf_HDS38f z^*emy^{Dyka$71nX_*;?%&Y!76RU2xCR6f#P||uQL0|+g_N92q3xQ1h$nOnRn8kRz zyY*sSUh7%a=RXrZm}1iOF!2}LrTk6-%@1h8&z_9bm1jXvTN~xH{x)q?Pl123sG%jZ zK>ZW${Oj+d5A#(!)GtJQo;u!w@>yByz}h9c`x-J;S5xp@sF66fPu8eT%Ez|xb%=&J zhe~}doMqO&70nOk^|p&y1XgE#<5I>-M0YM{%`^a+SAO|yQwYB3%y5w|9MTaK<^JW|naQbg3RM}6lXv5{ZAp4Mcv!h3yKp-4`}2H5>4YA=YLdUav%7o- zX@`p&!<(DBtjP`RD+!?wiDq$dr2@ov%vJx&0=JVZzu3%~=yGR=gZH9B{gy^Qas2FG zLR@nRE_W$_>@+1msO)I$*HOI_!V)qw8lr^OP!C{UZ&0;v<(5@*@!Yz}ScMl-$h9t2 z&T0cJaQb%Mo6u{B4o7u!KFkN|U3>QNex5;ZzlWz?9BU~q{#^65s5SD;>@1fa@5giBqDZQv!^ zxqw=1(LGZ)1I&hvTm6WT?YM`9Ls;wNzJ7SIcChX*Joa!Iw6phP-j&8avlwmIk$rD>w8l z;Tj$&c8LvC(5k-3N+!&~z6I!&9W>SNc+CHyApA3MRsoVVeev{g*ziHF7ZZ=0DL14* z(`k6c6W=_Olt^*aukHVO@(}qE#6vZufVNL=7k%_|tqo{hd?f{yIc+mCNOIIQ;>;eLBBSQLmA1`*Tvdmf{{1 zH#(rAzFZ5$ll)#!8JsIYubaK8Naf;H_Ly?#39!|CpfPB)T1gl^Ed9t!9gJt0tg1~T z?(g(9*hmJ&B^J>g#-3VvguIke2=^&*#O_5pInM3|@xE!TA%&r1`J`8`7P{uGpGJ7& zxCn` zVc>KS5Za8cQ+#Qk8mCjy6!)n+0ofEsg&OdzOCp=_lo=bGh*PJ!Fs!2OCju}`>oi|t>51b;A?*_l~AzFqdD>HxW4_-B~$ z$W`iUwNzZARk-8puw*>fu@hw7hEgg5>nGM+`0)fK0np3J>GF&XN$|**TqK& zaH<>m6&n|BWl7B-*GJF47T?klentIw?Sguaeb!kN1zdw}Ik>$nniPHniI6{kw4SDj zZk+4ercFqOVZBrJ)BrQYU4xw4HR^dJ#Q7&0U-*zFdjmjZFHo#iHf~$m_&hAq(W~j? zku3L%`xn(HXtWne7G~=}C15|EoLFm2rx)AIg?+d3KnWZD%E{=IbD1)xNXX&Xk8gk1 zbzbNGZaYgEXPjd)9hQ>hn-p|ezoFH~!n4NUS7u(?b7+en8lH%=saKCCIiE*U87bnM zaOWi>X^)jGQ}v35=3%i%wm7LCU3&EkW8f-XF0?r`8|Kq?m%OxyXRMz$>^_saAtoy4 zj|7sf--%0~fh9qNh^2XRYWvmA@Owmi=POvd6rsDCYox`H<%VsG_0-j4%^K;&mTh)p z?9zU!Dk!t3ICP!Be&}3M4r`o6tQ8%iq=>#iC@C~hO9QOc@*mw;q+**S^*ND$>Nicm z`Y%!LR7SDF2w|Cj+5=3=KT+=znY!C+1EOJmsGF|AN+sR}HZ9=WikV5UWd_g3>x;=4 zGV+hg3yCuoAv$S0B)G~cXnBnF7cY|YK+eIe)Vge5c zsG^;J0iLB9#p1P4Y+LlysOrEyuX*vM`&V9)j&GQkK8Jyv4GzxnRnNBuh7~Gm8aHGY z^Wxg>*|^!s1GRdzeac>8QXx+S(rDt^;}doyk%weG32$L4*B6MPLY6Cn4RvFu7Y<*T z)j7Sceb3#QczNs3h$Jq*&uK8UeZEB4!pTF1P%6=y6_N*vCNcx|xJVmeSJRiS2c2I8 zzkVf%>qx*fzHWs0J)nx%%cL&xJzQAwH-@|3GLdaaHSa$m4W-P2$o7rc*uHkt5j+C6b&md zpEvl!+!Z=?M@v`^eb#LOB;vHW31Q1V+LjqR;hr6wyoEKFsfG;ECq}x2RxhDQ`I0bkB5V3%g@tA@<~mh1Sbzx-=RQQd#(xyJ-tNSwWj+(iSxAmBN#3%643>!K zSdJ~3+~tv(VpvIhzH6ind={-uRccK|6MYCnZm50)ooprFE$lg6>_(k_CKaKY=um;lXdbl1n8`FL5{_LCEV!lVd2L_T%@PC{! z{MU&mUH8D9XzTEb8-t8FiD?HC@jJ5cmjwu~xZ`(RnTHYB*UO6vzi^&n zel&b>8sB3PY}L>(wUG>oOUw9Y!$pcynEJ0h7b;g%Q43I%{znHWJG;EuGF!{{!1jE@ z+;3InlM>sZ*5@zJ^QB-87n+vZya$uFaNObdTxJ9p>p z8{(te*v|o@AM|=ChrU^yQB7>tQkr(cR3_mkEfFqQ~J@!1BjoS$;VU!C1xem@*ap|JdK4Tnlo zj6#`+Y~9G1E-Qc7a7gGac;9Pm`$zB$1M@Xk~LZw28* zjgd3U_vwT9K?a7EnNvTM9B_w2sL$J)&m(u<#xbRj%&YU@c)qBNbn|`MOd0dtwA87c z5|foHeQB<#g;-1gaU+&2sc(oyo!P?%TN}m`j_H(#k}*uXkJ7oG9geNWBRF)uq4^+5 zrN#I%DpWDt5YZt*1+f4Lg=`$m+fX@z9b5u}%*^*#354$nWarZA&Sn82{sUdKPldOW zeu%bA1>Ya>@Vzeuw2Bh~rCph#Qu1w5dc(pg$rQd{r?mWlq=chN1kOWqfrKIRJsf43 zbEgiVP$@?sYK|xs#zSe4k|nG5w~_CSPzT5*;duV8R_~?10~Okrup7S}g0wwGIeA5R zZ1DkwS$W@CrKH_{C_GCr%VN{WAz<6Ppi!oXj#q7<(-7Ub^6OJN^I0CQgehISDOL=X z<0k1N`lD@q~ii1sBNKMgU&1EevbJGNf@| z2O&FB0&L8T+~m4f(1EG9?MtV*L!p@Z3o4qOt?`-{y%Uf!?GZt>8{xr-|NZHfELno1 z)C1uNq`E%&iR*9c!=bVdQE8`QB6>o?_g0a;?d(U{VbecLPBXJi*CX`DVfmHn-b*y|L*vL$P1>EQ z6{P#zu44i?U_p54h2Xh2^l3QmrZsH@aYbEnzZc_IUr~-tfLNuUcn#%)gxT^I*qU?R zo`Op%8!6BI`gTHdgxH+@LwoqzQyxf#WCpNXBt13g4i3PyYH~ocWgFWg&9x+hedbk5 zfA)!H4@TA#Xc|Q)(PJr8$^=&N)Mp`J5WQwQG#73@Kj>I8jJSIM7-`Y+_4stwLr>BX z7wXY@4zQ7HgplHiJ#7(7^3Ko=jiIxwe#BP}mv;n& z(~q|S;Q}9=$w{@q-o~i}=0FR~2KRia2ZO7W(@1gyk)gkn<$mU@5+mIPY74lOZ(1u% z7FNCrHT&PQI!gvERic+=8AG4#w94TX8I zapS?R{b*9_%VeD`p|={kT$@l^H^3XX7n}R0uJ_xI{ObC3BMs?!w0FN9+nSw|<8zY| zm%IWmXmkVhkX3^0sx3??t2#6Iq2(F9w>v12?+Gwss^?2Ki*UP8@=0Wnxoz)!Ti*OO zG~1#bK+(jWb#}S?mbi>moZPmRQFfxQ-$5jpH3OG4Ce*B^$sJDClbR1;o7aek-(IQb z0;e7uWDCIlqq_!G#{Hki`e<-xZAnY!?-HeX%@*f7x?sFv=vRbUE9h+dOEx0DaWo0O zfXpT;o+gMiW+H-{ zf)XZ6m%<&@DH|p0MO$?o@h1Bal}(kfJt}g%*z;+2XjvvCU~o+;Px8Xd8p6~Va;pv* zlro4Qp)tqwb>Uu!uHiN@If|sMi?86lm!x5-XT!CKAg@0H(9UcDD!ah)wB|75$cLDp zn7Z<(Im%+uV*3Tht{+1=NBq~Lfl*N3xga`)V1yn518LS8L$fhFT1oh4#W8cH;1q|M$eirWMo@7999JyH8Vmh2zNb$=+rypbdn} z{kh+@5|AsM+L+(HzA4yt)&J<0*6_F1;R-h7Fb5i^k;0Sh_lew=SMwqtZqTl{6Sc7_ z)KTX0`^C)d`Zq#y>I3{XMALyk``-dlrMdk7H*2$&Y#>#>l?=zW%b`P$)$e27MC$x) zX>WGnsn(V!@~gzC`0%>Z3T5i8?d75AO|B^g4gl_3pPN$2Q_0>hq}iJQqFo6h8a|u+ z=Fl<*dtLAEbf9nuZ&1O8Bu)H#Cy`tl==!I(C?cpE-1C2~rMAddOy;4QUIJCbWK9TD z#PbvJFqY%Sv+bMZ66NgQW8X9f_MZy0k2k_Uw6hDWFm;7Vb_eX&3 z$uh{Xj&5R`{y5Oa5^`160?j|{+1PyFXb@r@9dE?C>x4sMyNuba&D>DI(nVYGNOr@3 zZ{-2sl_EI>?47icpSCE?m3O0m%T53sm z=n;IR|0aL!6vKY(0nBcF zM3)>vKdjUy90S^a36t%%s37sNEvJ6y@MBCZuCK4kB2s_cOJV0Fni+oo z*}9dcTKHJ{sA5HqI6?%I=Q(->BMiQA_x`|(N6Jde0k3@q9{s8iF|sz@)z;t???H5^ zAl?Aqz=*n3RJYbLjANOgP~ilvvU5f2o_Hl&J*nCCzrktRuvXP@gB46XiFN{x-I6w+ zdke_;2Sa9r_BC5bhxpCw`a+)XSD!XKsiv)=U+Z}!w=X<%YBi)?swwO#{EN6rC`^=n zK=BdI^*{6s$K1}$2>lC6_^?Yz9gzfz%>}x1>Tt?N zud=ym+KrrllenftJ?MokT%U=GhpiGv*;kD973$Sq?Z%~{!8iWQS!4X*g0oHe+U{P$ zAuk%&l0BarGsx@}7jB+O{8`ZG$O4iM8O>ZpYLYdmRm>5*(LBMlH~(fEW&J$`>!CdU zI9a_mJa5hu`_lEncLrTxJ-!-?CtQE5P*u?s`q_H!GKV~wnGzGN%H)0F9euphhgdK+ zayUMLRGWrXf^Cgs4s{@_S8JYn=?mDHXDk6$m>&Y0_rK?5oPx(n=;D?q%+M*$vz?;rk}Qi+Qn<%-N1iR_Uk7jRrdlW`nFmO;mX9R|VNLJp^8~6R zv$G)oA4O*!*3{dFaZHpDe<&rTq_i|hi8P2H-6&lf9h1RO1SBUQUD6E_V>Bw=U86fk zGd4Hod)~iyU1vMjIeX4??(cnnZconc&YoFn4G=ir74rG~5Qs+I#YM1&R5Y|&%AdIg z25cb{RL+;s+x$OMI3FKo`ab3P^$VAJLs2E84<(@zJ-WaKY^2)WdDNr~+~kbj9(25Y z+3CBU=307R!W<{EU~X1|>gPt~$Na$gb*(521p>@Aal-;_%4}z7iJ5G}Hd3OjOgJa) zZfD}b^?o`o0mQJ3zjALCY3t$<^C-dfYuMm^EkZ7D&?|fjQRzrp1~Q3(<-6_#yuu(a^X+s!FlLTLngARSj7s z1a{>_w|MV!ru^6f+tB`E=Y)Qnv3`C&d!O;3J%diL@WQp2%9 zH7)Ma!h-+9-;jh@LY!QLON_O}{0grMCeUQV=z2mdzMlbK9_FDNy0~-er`XjkTNR(_ z$_>A`=V04&)}SfjWr(y4oojc0-)4Lt<$z^WM=kT z5${DK(D2kp{KdY99(4~s6;p!`&6 zpt5kJg9&|^K-+{gPU?Q`yKD4{&*_1gadN|7XrjfiySqDQi(B#@=rtrN^`@|x(l=|T z3xbMLseAewH>*=RbGd8Hv>^4O(2(aZu-81d817YktH|=BaQY*MpYb2ErDR(ImPb@J zhCNRpQ^4ll}-L__^4R2Kb?S2sUz2RT5C0r z14Yd-y5ZgY>rFsC?KWt^zs>da7FBY0>uX8oPSCnvtFH3KcF?|OU1NkwaYS+8cH$5! zJ7v3PprbKm0H<=({rN5}6yZO94Q>A}xPzF&~}QI!RsFx@_~}l_*R9tIeOk z7qSDVGy04e!~DaS#Srd1TfhdQ@#TG+gXE({+aJ5U$))$hyM#5s3F7x!FjgFaanRaV zREhg4VimWwY?5c>Uxo7-EY%nZVA@S>8+&eWJ_w9gM!Ekr{%eUmesrZF!~bvQ z3cvl8wA^$Cv7l<^i5AI0nzr6S2Jb7`(m-415ml`gsR`Y&`r^9_;;iXeC^$^9XMGmiUC}? zW{5b4c6BT^363Z1bC74_WY2i*Zqr%2P8u2yA;Tq9B29Ax{rhoQ4;1{dM2EaH?LSLW z_Rjf#w%3&SG`OGL>K!E~SXZjKVwyOd>hW0#FCkR!k28#3jSkQ|^hq(_V`c~`IlPD$ zT^!`#b2+S-XzTKt?`LXS!*B zHJB7=YwJppq-Yp9Tu94Lp5ElX5>{)Ie@!BrJfc}eDoz=qx&o>*2ObU@4(BY-6O=PN zr4?CbJK+{Fp37zXM#v{th4*7;hkOC|xiAt!`@;Bx>5E+NmN~S3`b5Bos2=C4HPRoKV$|NixlsrY(&!5g^Mi{hN-t~VIeI%6JeoK+oH85p$1UQc;y-O@D7 zGHTm~_QUWT*aU@`#DEN~X#o%@8MAU7C>J|Z&_wsB2z&RBB=}Bd$O44l%D9h5&-Q8`g&iBs{Iy4syR&9?}zS(Q=3n7Vl{TT}T%mhxcT_D#i*-<}D=rV90rhf9?NQ*4cQ znRE3A_d86N=e;=M z#5V2a-#@;R9rq|f*>d=27%9^t|Kt3XIK;n(5=n?X_=HSU!zB5dF9?109{72dd+E?N zxy@HSx6_T(wt;G`JG4$z%*-qYmd*s&wW@NhZ;Ls}Tc>QtXmgSKqOEe);bAYZiK~K@ zYjXc(=mGe}P_oGz0pZvoKK!oYt@!xFgqDC}*`78n@3wYj{Q-}u zM1z?aoPyGI9Pw#@g27bo1VTqZNWea6b+S5CeEVVdV{>kc5_lkVNoP1T{X%E{9|=aT z7OP)T)Ka=~-J*v~GJFE4Mrk&YqMnjo3vch{-!_4I?E_#GnI=<}+&3`1E6Y6Y? z3q?%ci|092ygfPIEagGI6r!TX);vEV;}bx=-Zv9(T&ZpBnHde&(B!Rd73U@~rI4$- zxCqpoXTsXyVfi~!U z(8x+`&IJ!%bq1v!)#A-1s)gN?UJ*%NF$YeeeJ0H76ZtgU*}pHz2BvF=lDJ1_Gd3Mq zxeL_Gfn8%F)^CaBIMVvnsSX$detsR9!GY&zMN*^+OTYfk2o_cfw9RleAT^$SxC?Ns z=IRGpvO*TZR*yJVZ|%GK9q4?@O;F!(jZFGNQSxWYj!g3BZ`>!+4n3FfTz~gc^P!&$ z)hJ5}z3vuU;ou&gfK}Mxvw;y~ z2e*zBi+m97^^I?x%)rysHNBj2laI4Lq1TsOBgLuVI%_T_5B)UhU{cP7nCtLF1uvV^ zV*DKK$ub+SFa7EiFuoT9lZ_|rj9&`IIonI6Cqb2#$r8pg$tWFxg4i3J66!j^jpEy^ z_1n=wWmwIgStV!osp{l)KFM&{A!hL`Mqk=BU#`k4{5A|I(%<;Jy)B@20|R) zSzjD=5L3$nRtS$$FbXpOb*kg`!K@W;$t z`N$hz*C^QMJSL8_)+vPffFx$M;5{fNqvX6%G#o@$@-=PT%mV&`b=`~)rQmcQPC%D_lt z2f5L0Wdw69j4r}Xt(MYWu+SG%C+5Z?kJSz@(u<)me|PV@uc3 z5-WfFyu%wO>)X_Qq7~SF(ZD|HFh&CuTl~!4%s#qxPZk-btk+WBb9N7JFK^ZM*RaqI zB<_&Zx=S=^x2NOn%KSc%^=qSv$*`A3oJB7vUEblkTEVeRzqg}~LZ0-*9?>dlV*cCF z-M!HyujdQ(i8cV%9YbF;(W7zS$5^V=GK%0nb(9i0E! ze-xYQo+5obQH(;AYNpHbVHmDMGcY3`1=Nh@2O zRR5-eiiGJ*zFt$!ah8v>AZFn>;;(j8uBC#O^M8X~qYlYv;I;0`m~?@y)fF>!5|>j< zke=L0kP_I8yMR;+H2Qpbx~S+Bew=zG_h6+mFc0XD{?k{z)lE*7LkoM!38Zj+Zm5JVEqf{swEkbltA~41Am*X9%AMZOe2m2!Qmi7Bmc)q*| zzBJF)z`0(0taqM%D^44+>2qLEDEQG`zZqMJS1OKem2v&y+{~4cyPFO@(_(JHMJp1I zh`(fd^>0kkGOd<`GicVkoJzt3iqwC$G3>K1JSkQ>UaTowKOIlAKUId?m(xD}(sBRd zI98q?#An#lXzqYW*pnahVGr2ypKIxwAK36CwffTxOxA!o+cA2>^n!{8fV`jcnJsr> zXu~;4>A!F3$UaEY#~8<%5Cv7d__wBV5uZ&BL<%Q5>)niP9<1JCk%_|VqjhLA!mR;{ zFUxd>*Ouz`fPxfe80!Aez_V*NxOZ)o&H=jrT~!9@r+*5i)ihEDiPs#tzMS0madWk=`lsw!>cQ%K4Z#cYG6H_}gtHH+81 zw>G#qJ5v}{w8jxww_vw`N0@GG*2yrmg_X|r(LxIU4DyVz&-|7HS%2mODUwe~Ric== z>k{#txOSRxI_pUvrz1DnQQrLl2AWL@ky}SLE&fa=cjc3=dSet;vxy|9-U{<#EyGMl zhJJO8lK-u#32kY#d=Bbev!({L?pGc5o_J}ekGjzYK^oOeErs13iCgI3{fg7-OJjHz zNL2;@WJ!hBsWq*~k#mZnZsDLADzGi+-C1Tp0*!66xbGr#1`wA{6vEqV*Wibgr{?P& zVf9(&o$d5^hm6XSl?bNnFi3x%sf(k<_ZT#Qv6@S5Hm<6+;8OwfxF+HjyCK zLPm%gs=3~>gS(R!3lO9)ij_Qf)V>(5d>cMX2~K_L*IVgk%jx6OaWD85whkyLVxEaz zW2V)%IU8W-Kdj~OT#;#ZkoXs<6(;aP`t_lRka$A^kb zRm0LW<2IzL!PikBbUR1zNbpN+P+sdh>;!S0Z_3o+Kg8y{)i1_Y@$l65SMian2{P{R zl?RvA^P?Evap<%4JwZnEDRB*V8n$?@@R7Sz4Nrf4Q&sh#GIIN51)DJ|?HlP^n57kga0-Z`^;QDhI_}f`gH_gO@zPlp1h6Hle;R(@aFcN(mXqRj z&Jj`xzGr4rwI{>O@RquWkB&l|2BI;~TGenGE#sq?ZMDb;9^zjb)k&doVCE4j7}_6* zJ?9%}N!gaWVdWWx1-9&~#VIBW?rR2QjK$9ObdT$BUf2GArAT&tI` zWP`3Rq_y9nSBiu~DvA%fp&d0P4Ql%xr{w25|40N=h<8}e`1_%7(W};I(1rp^N0n}wasn#x;lWAU^z~t_avaIh*>mGnpT14+ z;g4c4aw1niMy&0+*poM)bMc1QqP+NvB%-I4Pr*zwEM=Qt?M^HIb+%({u1e*sOsP(3$x6M2+ zr^Pl*k1XyL(=Dr9JS~<{V@m$s?#qI|Mj3*+kPqa8J~O+Mq)wgG^f5b$RD zt?Kk{J6<#%@mn@NLFcIvRcP=N=&S28g8#aJ(rYYYy*!ZKJxaYnvKrj*C7az;{{1T^ z=190%4n{wG9eA(&j%{j~9ZA^Z49K@ouaivswS(_Edui_~x~6j|ihr~0EZP49n{cp( zE??5(HOGD8XmkvIYfHMtzEVwMn|`sOnzvloMs1xnB6OL^olD$ER>94b>gD5q?EWUK z&c+`%yC14-z;6#y_kyy-pU}CTLObFwzmGa- z@{=Q6s|E%i=@W<(crq-w9XH*#fS3X=U3q3^Ch$GNC}8_f-}bK4eGPs>cstA4F;kCm zh_rUtduF#6#w@MJn9WF$sf9VuM8{)>@|3ZfIyHCSagRrccf|3Dap? z=*WNDF&Gv&jl_L{s*LP)V5EB=bnFek^vNOKxmVg@%th!Pzf>mxk+M59#DVb*JXh#i zg2DWP*dWC*JsCM)&|!lH2gT}N<9)hNn=>doxEy)386p}*SOSJ=?@{|X)beZrgFXH_ z;?pCArS#0%%FA6LXPI$7=-%~^{-_@RNAh4Ui(5mT3lvv= z2zGpmu-DV6DA*)o76bv%|0I5){cJV~i;y7BErigu ze5Dr*@roVecj^ecpjJ3tv$XznvP?ey7+QvcGRr{`g{<(+AYXSJrxQTdRI$F6RGwKv zWbid-u;}jitsG7CRYM5Z;L}sWr=I0V;tjTO9c|~jB0O|{e+*M$G>>tNTe#r;YjlUe;~N)} zZH!3D-mQf<4vbAiUdC-%V}>#DoSfwN6esIrSlipBmdqfOEzeRsP$e#LW%ubLqqiwjsJm(m%<%OICF6sXt#?5 zd~0MSt(0V`+t>>rK>`e7LrV13A$o(VM#UWw)2pb;?Ywna_NB?L!0~x0_oGvH3;?$M4B)kfI_g@pAH&x=;t(Li;sk4X zzDJzRNBDw}mk&}$uVVdSHOGfn8~;d9b(r)SdEo;hk_)l~FGU+J=>z=h^-C}&-h7)5WnR4h5w`?2<$9hdLAJkzQ zSoX_vSY&0^;5T-gG39w?ivrX5L7NZSB_6%}eqX0(cS>ccG_QS5sX8s`y2tv`li@}C zav%DqB6OaGs) z#J(QwTxN%TH496@Xm@wacUQKxh|oXL#Uq(m3_yLdoxqm_eh@eU_74fl(TVVMg>}-^2BJ* zv^T#r-Im$ml{1#L_Xzq&@-F>X?^!JoopKEO2t*WmQnV#X8eVGla$b(;2dbU@q4Mr^ z`MREwB3)hcRf0TWqW1_RXNMcD4_6N0Jx(*1q5QW zu#VLMRK4jsUk?dNZWDr;b$i8bUQ9{w&^80)Da~)nZ|dTBa=`x;Q4`=bT-Q`(2O7Z# zpB61aX-Q-v*U%64Pl@_+Jvp}%d=7^Si1oW0kJ$&seUwX z5mfh-C90u%gOty1R`+{?x`yicV_6Y<@(ubhEH5FA-aU{{T6?i|FLmAaiZfVkO}E< zwUj(0icHE+Gl7{|xP{Ued_34}$Yk1oeF~YnE(ak{j=sLiuBTS7S9r;HRZGEEN z@gnF>;|1J2(_3Dn*6c~kj#f+9Yv%|>NqWtDGXS%GnMZ!|jYDb36d3ZIJ5~zo2)S^w4eyppO$9X<7`f zkr9#z22w4*6+1pC+$Atz$*Wz`l|Lq~%%L*A(xKlD{8oE5-gqmnx0(i*0WNa-;6(hu zO}J5Wl%HEY56AL3)JR0*U$~~I4P?((qVC%)?C?h^TD<5vr1R;Kx!e%PPC7nV@MUdN zhP5E?)lz)ShW(wsG-U^8xHp|xsHEG}OeejuSS$q1U$7qDT5W87cY2_R@Li5yM0E1? zNDOb0tiIp8B!_=IKVBg3RodW2t87sHm%1A7E)>uxiU)6CTV;6-$tTzLdyN-*EX zHhrCz$Q2nS7UIXv9#uBf;e;o;<8{tOSv#XJ`8vznvJ8f`>dC4i5~fHP)fMWEUpHe` z+B-udE}Xxp+uqcBze3apTowVSF)j{K3QXf6seeCRA+=<8wBR zC<$-M>--yFl|lNzRmaE5YUg9?I*t4#{MtEAX|p)P(`O$+TqYj>y0b#|;`RGSBS#{x zTj7R@H_W%KlQNtae+6b=a>f;khfVamdwYzmbZ@gPcNX#Se!nh&Xgh1Gp|dv$@VSJYy{H{-1k7LhLX!Pxj4MbJd8HW6#W-3>L)6Qfvz(QJ@wb=O|;^ z;T2Qi9U?93cn~!;E2~`|5C!_%gRF9i?s7t=OsGedNqixxdHS55Wsz(+HpBboiZH%K z-Vh9IqwLiv592G%28{gn10@fwPYUJvpdJ(TuHhi$TRNY2;lZTr+zm3T@2}9-#VicK z;^07#N}pz^td<|=9x6-!QZ^tQde-g*(3&vU#GA*v9Wt6sjJg zd)9T!%qB--DZIlX<=?G&T8HN@N#g;d&UVt1?1&jVX^j1+g0-;9=S6=-x5I(sm=h!s zt%<`8(<~_MvS@*+Z|%mVRIH_#ZVh0mzKz6!#31HD_Wo4y=DLvo;$UCl8E4`b1-xd; z%GPPdt{``T=8H~GJtZ=M4gUDDm)AQ1goXoVXJHs6AnwLRg^*fC6aMM6#I;#y<&mv6^x5#S6Qy5Q4>gKC{ zBKqJfo0Oyfkpw;PG!U$GG%|{u&ov}Rcye=JCyqP^ya~O;mYw+715sq@xhPPs5X`LR zn`CL)a5CuW^TDWp=c?vGP-!+BaI$&?spd4thQzM%TAsz|QqJMl1ji;6EB!|3aW)WT zpHW_7V+W_n8>!lod;eN%?AE9SW(*K-3ZtLJry@Alz1YECD=+7BK(P%tkoj2gru}?d z28QKa>Escxi$P&O`EuDJ5C0ZT^)kPkRfs1zy8$Z-u$#PSLXI@oDb*{NU4=^{gZw~* zSEGPTQljL~hHJM*wIX}! ztxi!+NEQ#glD|IKofqOiqA?>+j#FREkF6vZd_cHQ;-JT^YI_xsdK>Ki0oP<#KyEaQen72CW=g${nsEpWE94`z&q49{rj1vw~(Y%Chs?Zxpu61%sR$_7bR(YpGMMeJNdx(4ytK{ktl9uWnH^ za+9Xl0R-vWvslj`OXdS^mua*Tto%9ql2z=4>W~E#CFG3NueqIKdN57eI zD=5_Ru@aUJFUvh&l_32C*#?1rkCV}}{_x6RTa`D>=Eg?pCfT*>3A{6h0!ve+P)m@@ zHwh{%NH#a8l)n=T?M%cM>AujBQ5%pUYpTRjbqe=8dI$a3UAE8EqG=`S%%_jMxOcRxI-BU8omK5kNJ-r8eJ=m?twXz`AUwS(4SeoDG#Tn1v9)-=n}Oq zJadvT>yAcQnW%VvVB>$pfoVw`9MKGi*WC)u7Vbre5+BC0tZ0E`)F*7}fQazX`?}9t z�!}vnA`1-=ty{H}JG>*xl<(!HVHJ;R2W_Dz2yc>NL2d>9f+sn1-ga}`UV|i21zPVVu+SnzCbnQ5lQ~N3%QG(Pm)${lxF3b}c zp18>YT{f$;54qW)1ROM+NH;$3P&eiSQqT>XpY}NjKogQagwSxjRXqCf>0IKDl_j0d zNepcFWPZM<5tR%)7i7bEo zXwZ9a!=JlKMDe0{VIe3&@0@!5G33#p!JCDSREPp!Y=!4+^_rm|(n6#~bzr=BknfM6 z?9UzU9eC!Gj^Y*aaubkE+`641fB)l1ukyy#hjF+3`otX|&4lbwK#Afi1 z2W57$)v*ZkTRgh#zbs|c#rq^YGX)Vxy4U>-n#16)6mR)y9868mAi`&)*}}z`jv74vd1714pg*Fzi#ahIoFgile@^jfhSwxQqi*TF{)Fwo1cDOO!WL&bZa!Ugv zQ+??Y%Ke{uL1toTX!hlutY)(%_39=LA5=`OT;|xZuWejS=0;-7HK0{S==e=6tFDMg ziR6j>?1pUBoxQH5l6vrB{@0*mdif_$mze|Z#LZH7-ho%kZ;wciib&$)f_U@94z)as z2F1KJNBZFZ*=wvV;fL|YZYMY2>i(2{wDQz|#d<*iw4N|yqy-(QDrf%tTL078&*l5v zKRKYCYzcIsT1a1qD6X(}z&c|x%tAtP^H*Kxdi%0jcRVw&e+6=*1)bVwRq@bSd<&Q+HAx=04&?d))RL#_|j^5&CUj5`6J&B zG|Ca$cxp@>6-3z7-fgynla(Tbs9*Gs5#|)$8S~pAo1HlujI3+dFx^*E$N>d!5%hcS zzL7hx?cz;3`ETA%_+u2WA1F87=wwUE`$Om6=FiO?{#!hMRUr9;(78ZA<*D}U-|V;G)9NK=#GP)H(Epij9R_f!RDWa>T^gGceo_Jzecmw){m;% zIz1URWnST7KFEWF-z$F{>GAFGt?Dc;PA6Esu(cU4n7d=~daT~%5n!anzheE)EL`%HBcpr0T*5I5_A(hd{=HI4#!N#WIoZc2RPrZJISpk>aPmzk5r{uFSNjrze>uwuv$h zmhE~XmY@e7@ATd^3NE+CJosD*`Oleuq}@g13Ho{pPSq!M@4t2ij%V)cV=d zRcWxgY2KaSU5o4mh}aU+sNqaZ&%DLrS>z9Z;HZZ0ypnDD#bH}*K{Zk3|CUG}!S@j!zX+5d5) ze_j~QA-VCx-HP^PHR`$H2Zv?AcY}UL?`{Z0c)Yst83Syx>bmthblJo7wHgBoKhK~f zQIVT`^NT#}-XRLpFRqwhIz}0pfElUtMQYK;&0%YPLVz=-Yb>N-E%>DWlC6A@jWAX` zf5h%EH_n!#J`|R6m*IQxvGZ?fDax@aKzVLK3Gvnf@uGf0OxL z`j%0EKvelE24bDz-obtBP?^@65y?Kel)v;`hm9{}KbM65KTSD*M~1ED zY4h@Tz6imBWU&YrT-^dLP}x>SvirBi)l>bB+O0tUE@-nPl+Onl`z3Nt;eMx-J-c3w7oF8RYBJAl5je3 z6s+@7Fn$$OyhE>ZIG%$ zw1DA!!Rcc-+fhSo#(<8*636vs1f%S3yW0(dvWGNxx?M`bl7%d7f{Me@C)IuyaU*|) zmNQ32Ph@d*p%T;h!gZcA%X2$pp|+{{x`$-X7jL|=YoH`y8}_PIYEWrS*fyGftj9TV z>6FA^LVD}jPc^)f_(zb!VIew7*`i73A}}Im?d6Zi9^n>`zK!K*lLw^%DaRik^*Su; zX~}+=|6=iJySwl1+b@83xmWBm0i-Lq<(zXQxzwaOI@BMI3t=fLdc_52dLmnQzaUco z%9WVZK5ue+MbPx_B9)c=k?1>#4EZLpNd#b5=sT!g7ZwAx^__LqP%gaMUCwZ6eV$_7 z?ku^uIJzmq$LI?>9xDi?Cwn_~-5hl%XduPtqY^<7&&N5u>#{dK&~=6&U#!o0lu z9+|wS?~PWaBb&pKkUw35zg7S&;N3+o-{67=hr2|*>ue?W#;5pjI;oz2Bu5+a^~e-T zcQPGMj@sAJTYQ7}GDb`QX(I;w3)dufy|2a0j3{UHeiW1|sQGIgL}%r2!#}3?=|Bus z+qKh;3H4-<$g6lznysjGJ~^9xi%L z`+TgHxwuG@MINn}grMT`v}TbPvlv&4(FL zQN$`MtUmy!I@MpJNU!&B8sDF}*Wg{)<+UfGEdndBxSRdZfcJBOFpBDw1+y!QwC($WSf`%tL z8SBE9+tuGa+aMJI>jt$JW4^c7oJvN?vaZAGB+9P~KRE9!4q^faWwsDH5ToARa1sAmyN^|7+VoxJ{MQ(e3QTDC>akgDz&nP$+$UVr=zRyDTj(8s! zXiyBGta7&~C(V1>)&7do_}!CcWW6PQvHEukQ`1(F!`C%1RKq8dAsL^s?G}0#dO_H` znf1C`f2gq$G>{`Gm=D%^f%_Vq=~#_0;pd9Ki-CPdCf#0WlD$#;HsbN*BV#@b$fV_> zwD#_y`8M2d+qRx$Z}(;T&?#$3rR*EbnTwVuhu@i~O07>i!&es5*P$6_<{z9GMJJ}xXaGTnq|{e3emSu}psJ1SCD)S`Bp zc|Q0<^x1i1PK+pYF_y#p1-cV(~F;CRc}qIJTW$ z&>1qNK^mRPOEU0FM)c9h%bSu!O5)5idvtembp(-3sleRYRQ*>h*XGFBcP2%F`ZfE= zy8ibjnH2F>(ttb^i9}8ksRLTNo_wD`wQs48rvpQ%5t^Z=?+M{W81Y49ld+efN)K zp|jk!Sb-*O0C)_`5QrT8AVt+lPOsR zG0fO#<(wA(i{Zy%W-8CU>ED}FsgDlMw8vck2$q!mqwu-8H;#RhILlf2t<^++6m!2I zL9Z;b>Hez$X0OHTWyFaPT6CS2-UWuVLgr!}&8GO@xBhg^kkRHIZVK0E?GUE3`^B4V zWwLsQY1SWTKTA$IwZ-tBDz~#Y;T^w<-2)3CvZVT(mrs)-zSaK9kHv1rkaV&$s+VB` z!X7WOb8ezw-bREs*Ae$^F7l%)BZA8GW7P>eZ#`3%)Gt>kh(NeAvf~3V>xiBRuv$8< z1V&&IBbW{JL!8IxCcoAT)B%so+gH795Xo==mZLz|{tT)Bf+=A+eI>%LSnVOJtqEK7 z${AbAuNit2^(MRzUD?%UeJuTn_XkT{jEy9-8BQuE5n)GJh2I1p7vSt8R~WmJEnH;N(>9^Y!x{c$n^OoP&sGiihJ8$5BLCbEb>Uhu6;Lcawzx<8p1Xu^Y zSJ4+jb*2G2x}t?cTy~A=(^jGguFtAWxDc=VzvRMQk1B<_J_i5zDVL2Xwv<s{K$JaAO(#mSCj1YLnzOkc4W}@H;CC2Uzte%?pq{bKA1Uf zXLGV%ptfj7796EgR|<6LfdzV3BER+#u3h_JuE!6Z|E7dYxRMXb>B*R)HtdWaTIZF0 z4$%xr#zg}4XIsPmTV-=4f3y93Q`SpYT{L}AlVy(mn1{dJAFw4XFXh|pBgsIUplE`M z*O$aAode4|)tz`WSS;1tinBG?Oni7cEqz%uYq)Lg_SsufSek3j^^baN(k$ji`sqiX69jG?;>6$C*ec7vlqG4>ZVWsFUElC@p6OA z_c(!_;NA@rUj_}HqBudk)(i_{#$ekcqd3%K#;lZ~IB8B${;(;DZSN9OPK#-5fX~m- z+p$dXby@_^_Gz4A6601+Fgi#YuMT}XO`rmNq0;3-n5xpU+_tvBuM=xx*we4yzMdil z1`;p#tVK|k{9`}hUaBoNa}zsRP-BEDLf5m?nx)YW*3>i~#@yx~CPB%VTo8dK=m3(c9@r-YFbJLap?rP@dMy72c zR2%<%_(9I;X9i{)trUchNitApH}TMPK>BHk?vfO~sC~fvs}P+>TDyZ_yPE^;yDMXF zE`uoS5dd6)SVb&)WSakh&IgaEr7v~22FBO%EIhS;ccuCchYI4EeOLqs=kYYW!Q!Jp z3uGc*@<$U+>8Brzw9k6MIozX>?Ylc1-Z2-)T9~}?0>H#3Qes)QkmTLp2cAP)OU+-( zX%64^k1y+Q@?SG8hWlIT@GYEF$8@aL8S9%7#7|l!-_!-=?K@9@`MUhZB}{5`h}~_c z*a}x&m%YxFrlG^@Fq9+l!C}!aChm((`~Ro+<4(KFH^$t9@z+h2{t%~;ntOGFp+gXX z5H(W&Nx!svvw-sc(*0;Zb#{zWLBcj@w z_tJZE3S3cfIUm+<--m%7@p~@w=6q+m`T9MEoqf;RTrWq=Eg-%mxd28js~EIF^~5DT zX~Qj1w>1G`3iGO%kRH87G>w}MBjc`mqBcas7M6|?)5=w@G?LbQa zL#Xauodz4uB^qH8w7s}596A}>R32ks%q#l6DXR-V-e8WVBnPReibyg6_9n3k7L{|- z^r$&i)kIq;F$DJD<2cuWky`X|_40Bj*n5gM#%LN|~lrP#UbQ)+K2HF0< zoEZ@FKSQyf&pR z=g7pxrOs&5Ix4FEuf=cH>NuAS6+Ybl)m4^{-6W1>yCDA29|PZS?qgvDMhy zO)B>dPL@24$zDk-fvwHZ;YD57OTfl{J?a&h_AwD_x7av^dD+=H*!=b~y&fbl=xa;i zLY?1u;<=DZW2d^?LW8^U>ShF~)<I3a?q`$%iC8>#t(#OjKq%8mLg7B z>(P0@sc!T6k?Ih*@4!4-a{MM0T`Hh9 zTuuGom0*`@mUi=t&-?z-v0(8>*=OIzjD6HcU)S2`EqnPTwDM0BFjF4j z*rxR<=rFv{vFdsV8sa&f4(s|yhtTOXWH=u=1=FT=Z(NJ4-OU^%K8j^>KpqM8F$z5Y zdB4af5@(e!FdSE2NHTzk?=xb%|YIL@zD_zl&@FMr22fM9&i zXpVo5HUGqGG({ES#0WbKPa%vkYX9ZrIeK%d`gQZ>gA(dZntiLe z0K-`}R7T;bec()Q3gG&wQC6qjXxq2s(sETu@83{!jLRVI2?bGo0+0C#WyYhlNnx&F z=fbVyW0mkY{maNV&{7tUhc{R~&9wyQ9hGEQ>5zJHvUUSB|~Sop*!1ceLJOGV!c(Vm&d4 zfFq+?^_Bvn7YYNJW~6k#j`W?Ba=$0Km(68M4BZ_Lp-j*<&6hD9ogWF=n)Ujn+7I{}1eOO|O;NKYeXWD@oPOcB zB|V;J<+)A&=mOty4V+Ie6eR`ung=|7Km!5{v;9&hk_b0S5fZJD*5|RS^6diQ|;$p3Y?- zfsk`uSNB8jJZV%b>CVT$fkc@vaZ0xfZk-F86Vxj<26ppZ)8H^!mJoVwK}BDknyQrU ze0C@+MLsw@V1zF?W<*~<-KKVUNpVB@YSVx~&a(LmEPoYeyL8+~2#TrSl6m95;9Qk9 z=nNZvQNa6~9Q%XcC%=n{(t6HRL>Sj2#Z$ycq5tR%oWtVHh@+E=|LDreN{YU(7Q=`z zQ`(SwKHYj1>)N7Ll<;cnP*dB9gj@MSrDu)NtiPA|w5fsfJJE$`+$VH*c=v6%kDbOp zy3TD)*8qZZPli%LCH3#78;6CYYg7Ek$9z4NztyingD5`12gWUD(J&5@mRDNAWb)YJ zk%-O6oxcpW+I!7h9RxdF66BoG5?_lxep)l?iDWL^UcB2rX3)8v+!GtFFi}JPO8(_^ z|8v!7FLS-0u_Qmwn~k!i-s;L%UK1lVNFf6K3sTz39N4(?w6dzSc;P7@!5Y}hZ)r&{ z^UUXSr~t@Hfow8O+pos!pxz0x(FQ{K(dTzYp*~=#gskcJHi{2sRDUvDiyU4zx|sjv zy5+}VgYa*P!jLpmQ&g+1jVagAkKIuD`K(vKw6)j$zgSP)g%bO0<`7bP4gxMKy0=55 zy8~rT%2gM5e=N*Le$YjQ1rbb?;u^QBPlA*vlg^c^QS9NA)U~|@fR6)0Q1NIcwiyOV zi`X~iYOF9c-mFf*e76n$bm?VPOhM3#&AhLt<}787n-1su+j(bA)jDTiC0CP)j~%1^ zD<8O+#A&Qh3D&m*VNMX9I#r+MH|>yagK$L-nOR}zo>1n5Cz<)2=|Fxuzs{vOu$sMP z{t0+>@f(LWrBjx*#G=tS4n1)qvB@@mt8!|Y&q{OdYzALM_+B5MWL9#eg?xT&pC)LGc;srV zu4L9Bm>%UWfDEymyXGJo9~&8uwYx&XOrup;WWQ92=-+x<6Vc;yS84)V{f`bfW%2QW zZ{1KjM?s>T+EZ}<9?^ImLI#~EA8Sm^D%Nqr7j>5`l~~aU>K?p-0IX5AF??{aOkZhp z%V>{jup1#Ky)ZK#9FoGz-cDCHdSY`XWiVIL-_cA3yg+bpO`@ zI&>SxLFFK5c30m5Zng7|1{mI00OU3{zK(LI+xAwbpT{c9(Y!5c3_qfrvIQ9dtDsCr z6d?_n@yJsCQIC|KhFVE#js2ayLYA2ihIP*RZPxqo@tpyuhn+h&{MHSP z-A1z#A1%OtKeXDOKF-6pb-5!vYb9V5kka1BKz-n0^{ks`A>~>b0>h&_4jQ2Cc*W-s zN8eqbN)Tnv8Kakn7>v#ek*Ys1JJacb=kNjh5WX-`2`XLUmv@0!wdoyd&?wk7?{pC$ zOsPcd4&C+2E6=BSPt!ln*k^OC&d_RdGfr|zR`B%F0$0}Ek|}-|!VaRX0zNCmq|8QY z@@;4+yJt+y zk94LyZ=5v!Ts(hx8JLi^0dG*4h{Ypl9)4%vB#Xf)^}6~<7QjI%(^t9D;iqI!Im6YK zQIx+AHWeG4J?Sc%hC(qu>;?fG9KKodb&0T_o2ZE- zfPyF_{eC)gpH%zsZKrPtd&H%@Hi;;Z@{~)|s$!FVAdxL7QrL8MlD>O{%6wG)gv5xC zY?lLNOnL8Myi#gKOv5PufdVD+gc`CEnP;>tT~oXJ3)PFy4CDy(wV7*~}Q4e`EXv z+O`rD@qRv~+h4FTqXR6oydR?`K~v&4BsJ(?4zV3xeulVJmwNxlZs$NR8JM6tov?jl zWYeoT-eG3Z7-A@bED(b2KnSkno#^ByT)t)gt4RUub zgPd_r}PDT%3K{pOwEx}qW+-LqgK%?^V@uhpW*fO zxKKzU0;NYT-VOJ3AE>eJ7taZVAfDT6>2l4#friD46(~X`+BEzvtR-Q9O(I$qQVU_q+5>qZ6}g z$^M~u(rg`b)4Tn{hFx}6B}4`(m1wI2)`)*}jbfd47<$`q)@KBljPPnn_!bWkEpCnJb(*>5|NK&7YBJ*- z)#5kWl<OnBf(kl6DFFL@CJt6!^|(Z zhw`I7+V-DNGewG9%be~rCo3GY*;hcpDe?xg4fj&!8-5~Kua8U$`lw-IJ2W43`I zdvGjZ3@O2n#ZXq<_vFQsy3th&<;WxO`N3G`5{o$axJ!S&xt!Kz@>?OD?bP2VgHZ@!hgm z!kZYfS(6U5NYC*J9s1GHrXLK`S3_onn-HnrUyMF+Bo|uuB|mz{enG4;6G zrgtj%W(!4gy??L7^7AP{;;E8!|EGqM8sb3Hu%Eyb_UO3UyJ6~XJ1{JgnZNakbaG&H zKubBav@y6Yd6ueV-bWMDEoZ?lPH8%wJvYQJMO0|6h}Vp}Ways{BRPVkpxQG*0}tgM z%3d36(;&u~(=>CJy77Vu=hvy1AJO;~FOMqIN-(8YcN>SJ!DkNZU!8;f_pG zh3l&v)6%7lo0|w^*!FDOai7uRs_rvf(0m3!K>05Wx``6aT?wOE5DzEZhjv?V?w(wB zN|a_i8_eYP+N^rKTCtrj8=mIagg`c6K5VA*Qvl=y0Rh(OqBn^K!J5JC;NhiJfDlqk zn5KB7Cz}fwf?rD6H;wHJgEG}Jvo~V>T`;|zrQ3#ub_ z5TCfA)BVQBid3^WDgy3;jvr52zLBl^^RP+xm?f^T051IY`uFcCIJ3qbaR3DDBS_Ka zFCzb4E*&YMn9PE^(R+e^J-yzLk#rj`XmeBJV zm)kmaL$P>W{U?goO>-8l@)te61JF1f9__-svmPLJ!C%YcbmZd%CAReU{F0 z?$cdz<{dT^E9K2jvOKWScP&?$={#nwMfCoZo9W}Sm1X~BoPta2sFnnQYA(t4{ORU1 zP@im$UAyDuBWYor9MZ!uIPdT-iNCu%q(4bk_Iad#%-?yi{lU%kp%L|~mp&^V-nOjx zIY{IM0o~apjnZu{&rluAPYkxz;9xo6hE}JMWPt#4CarnNVDp?8)@(`hfOi z-F3t*eUF-oxMWK}ntjgw+54M9)opshc~}F=C66($2I7*xE}k4WyW&ka7}-#rFeue+ zwZ$0VF+XhvVpGjtHH|2XRU5x*8edjQ)XZhi8EpvxG~fzfm&UO;1JzGiTMZ}VGopkO z08$&t3sYinG2gO0i^4w%e#E#uhM}ylLZhC07(?+6-9i`V7#hkbtFaR8bn_*n=ZE*^ zno$y2lkFP8hMnj4Yy|eZP6aZ`OXs9))Hc#C0fW@eb^1VVD-q#t zFWwB)dfb@He8ns1(~naPqvJuTE9jH!1!FK%1;t2A_)){;Iu6NUepAJrsQmCn5^zB# zLp*IE$0^c9=+Xt-M)Qmc4+1~+@uK8t`X zYY}vaVi~+W(zQefjdh+3ZRo3oByVO#lNlrsh zGn@5u#YXVhdcROzx6*^j}0Bk}8^=vv@riT-Uf+7pU5qhF?J(F5) z?T$G|>rvZIO4FM66KG(jwS?9!k^atzVI#x*l&zF}J^!rkszirxSj2%;K8Re?R*tTD z{A4TDS*%pezN|ggqlH#U?+Hb(TRNv1k%g@H?b|g1Ki_84VP6?&RbRm`U7}^;c^+3S z3|xwu#X1Dlg6-?0wtadRhG@+o;!njltD!=0%wYBPDZf#X#1FqV$4Xidx?q=17_Fx} zl{wYxa8ggg&v}Pzy<3WWhDhh}N*I5cQD;CeUwSzwYFKOGzt z-@|{@N~508qxfK^kfB6F(|fb+<4x2du~|#Q`8Nm9FC%_E9#6_E-79}Qclg=ozguN~ zzh=I>L3=We55jbH`G^e6DlfI#el!FDU+d}4ghtQaneWfN)t{2XvHaFmefzli;*bYH zzk%OYYHR?~P{YP{YxtvYQG%}yK~dsbC2X|ZVM}B}Ej?k#GF^2iyb$8#`EK>mfo~Y@ z`0F)`L-_7ob)C)2A9Me`9NMq|Y=mzJ(ghDHG791`=M~8JE0UN~nVoGP$~IG$41Tat`@rz?ee@!h_HQlb z)p~Gr0HmF@DH@XiNB#VVy=$JgM6a`lC6Ok1BiOrSCHti6r(;dv_AHXGP0jmKO{uw7lF+R(^5gCB8oP205zl3LT5L4|-vvB>9o5Btl=RyVX9( zkVj?pQL76ngt_&be2eW_sNkIvOxo<56kqGk4;gnVKKTB)`c?2Gxb&v&zE+IeAAN}Z z2HDn(Y`QCK(RW}S^5ZI+dy`(ZHgvL0gO*$-`AM?-yVOM-o2WJJs%Y#by4GgukP)7W zFgHUy94wob&W08(frLV$|4S3;FC&L5Z-RU<4Z<}7F01h@vH6Q+h$rzjnO&($NG(Ar zfA9D!6MiPw(r))S$QT?5?vu4H5T}+!yyAYMP97QRlecjr8bGeKA4i(mR9>_WkuzAo zIG8Qc+hZsans8(b@?#kh>F@7@Xr|(%nw_%lBRF|i`{KOTG&GsO+2LgiTn0V?Uc_v> z2gRJ94g?hnFeLAbc_^GQ@z#NcGi?(h!fkU9j~g25?$UI31O-6WMoJncM5tRezVAA& zOlUcT;ncEbn(%v{2(8DiV@UmQpHkgZShjp4UZ1;(mYyBtZ!x=U_wZ_?v@_<4vhehG zYA{KGp-25%MT69{)lnyR9?{y&l_rS%E)n_Z&(|({*jsIwR|B?%b=N$EHLgl*3i^~* zCSRq>2>*QXxv$82$uoX6l1Ja+Zlb*^!u!>p%4b*!W8Al0A?{WSvZopSt)tBT9IwI( zKU6KOk19vtk&;%8H`~VQwmRvG>hGvOzX$>aUow7%xS2M9yIVVFF4o|BJ_NsR++)j2 ziug7!J+sg5c|LM^^VneWPs8N}o(EBX*syMr-i!-*@7oZ|BfAZn@7AUZnkHx$fCkn@ zbq1`rSby*I5>C~2{s6jvO-vHzh~P`fYQ-BK`(>}NgjU9EFU3)M^E2*10w!8cg!k6{bxP z$wP%nMF%d=)hu-AiK9slMvA+U_jFDqPs}y*;y9D4V!6qkcc+?|TMKv}%&>7%j-eSCE^eHj4qwyho<1#lPgdL( zsnf5z`LdeZS#>2=HELxVrDk3QRVM*UNDR-S4Ms7dvuW^}K_`ky61YxDWEG92-lsv8^0wp83a%iNeB#NBNGMNwiDbrs_rm9b)t z4`l8t`fdONlV^ebz)!eAm~Yn=oor4zufK+NdgPg{Z-++ly<;mYQ6TV+LTi)h`vjIH+9R=LIsUynJ4WF-^OAnCpz{C1Kg*RBO{gYV ztg+@e7VB;lM~O7qbZDDp-ygW09mMgNzCWY*vQ>~6joJ*h5lxzPKHCVa`*F4ceaB(4 z6|rZ!m7I-ca1(@12{)RtteO!}^!|M5RMi3`Mc0vgea&318%f*D36 z!&M0h-PH*mu*z2Y@RnA0!>G?ig%suj*kXxkzq(Mz=>IAuKI1^yYx z-KWgs^ZbG#Tr$e}TG+a{WVCqEGg>2-JG(0}*DePCtwasLpJ3A~S5Xn6$JyU4xBpzu z2edR%fP?#Dir7K3u3++i@x8oJp{{bav=;>eeL=8`LCRre*r?COj`le)OXz^mO8>tt z;f226fWZ5C@`ewgxYl*MXMn!L)HHInU&0%RLt<=o{Z2JW;y91+eO_kf($x%3JGW?G zOC(T^`O#*%>&d&lUiOWpdh`FJ;WWVHIg$CDLM5dz2W^u_QR9ln&VJa2>%O6Buh zlrFj5`oQkZ0<2SI=ma-ZM137?QfJ8gm!NZ{&q^PZ9R&=pep^)6}0YN1BTp!oorl*4?GO9n+jJg^6hhX>3B6&yf!GmYqSu^sx-yDXGte zR#xn*?W?&c9;l(;2xdKYp}Wser8v#~{k-d3Yz*}_o5pe6^hiIA`X*nuAY?Tt+-UAj zENy&U!OO=%=QnZ>N%@Vc(Zp#kYeoeL@QuPAxVLDeKs=@%S*ox77+_l?>lI&T9AJH< zcktWOrMN-2f9K0sF86nJ+Imi#jlXXNuvb=Ry07pC#ke~;Wg5;d&)g0P``Keowm4X- z46h8rk7!MMX5*}+ax2GgKe^{yVe`&qCE=hu_+(d=av2CipMuXT%RL%lcL}Z^-$uyD zSS{ev2NQFb-FeWciZRJ#-(KdNKtr^mIkjLK~l6*_=ngKSw|L}1fzO|xo|vw9f& zHU{zja0!>GFml5^y_Rjv-Rubf90!&a-we$||1a+{jQ1nfY$iJixM>2B8(@0$KEW?% zQVL+UNPvg0_YVH3XvNLKKYmE5&-bzR`Q0H+K!)?$MJ+`f&jx*Ju2g#g!ltR|NVFc; zZ}r1TkI)zy>Q!pmgqonY*FM|y%W3Id+}Z=ia1CvH0l#$Y`s0mKL?mRx+2YUuko$Aa zY*>2-{j9lqMua9q)o#%@Z#I>z9blzFILgZz&!ZlHUtOt|T63RuLPSgEdETQ{xLjly z4G#-Fy8F=`=(mGfl?ODQm$L_j*+G6$!!@qATk^k3g!4+d1TSSXRw6y?l)=~$!T^n;_vRGnlDL5Jt3=_k>7PI}>5%{%6w&u6lv z+LQ33%+M2ar4RjSF3FRXYdJ(4pV}uTZ(WN5-q3*N$6qXEJFtzp9u{eJ&{MK*yfEb)f))Mp;~#3 zha-P;siT(Frt>^*d~e)8`qMEa5nd*k&4tPHtjW2V-vVkO-6hPKk|e@@*t#p0`y&)r zhcssIwot@N2D@Q%cNGr0zCc_plvDBq`-%1x_ps&-MJYTcZ|`je2z!0wB>h0KIYG0a)ty_@p}8maR6b5+w`9t ze@iss)g`J3oK&`R1EUd_h*g<7Yw`HTlcd;>(?Nq>KgqxLWaVhH1wNGJNvqJQd54Q->+nm1<8?uB z+b@8nMH<^}=#A@-M-(>N#qh7nmltgHZJz6+YML7TqS6;u77+2<^G-e!eCE-+j#8PY z-FB=bKY8;3AHLc!%M$W7tj>z8^yaL%Z)(Nfs6R z9~??{L@fA8CTUTcIkY}&+axF(bBpLOB!=PzS)c&~bfi>aq5*-UhCl0FH6%a@1E&6b zI@@S4@8r*}bNubB0{VskSustFKH6w#M${mc@FTZ$51qVW|mO3%IKF3OfWpH#qQvFj^|_>&Uy z9CZItyH5Y_b(sZq^Yn9`L%Rr6tx^{&Moh15LQS;@)0pXW{@iZSMg(c3dfoBa?zeZE z!Eq7II##EpCICOd=pMC^Gy#YZoOM7x3E?cO)bH1$`QJ&At&OmY+j#2i?$SfL>wz1s z`SCPV+Ueb%vXh$kO1g`SD6_gM#aV{ zOzZ8s`|676=X_%`n0b&@VW6TJPGS6~#dj^amtBM!Q@_uKc3W2Npm{5V(~DXAhJ0ue zqQ4b^6U(E+?HF;$%H$~a&@%~pKW zk8={!lzAO${sxaamLWwGvO5Sn7|{%u7Mrf(t5q^G1vUB~rf+0=JK1(sg*K3t zw6oh1WkbFrA~S=)0pwgEObGUUSm^Ww91ocDYp{?!vy7-)YtBr1e-Us*WH?gK{uG>WkKa#BG(0t;R_r6!B&T;GecG34- zE!V%3;2CMUh~6)?DQeB|+-ta?fVO!l^(nq*UyTmNs?%52yT29J)@Y5E!JvekJ zhEPH%xI&8~&7iUa&6`GP_7P|9-;!6^Tk`HJz4#rj+t>TJ7dHe2(WXZ3XWy&TWUz)D zBtc_T6R5AqM*kJ%#Ta1Y$+L2F+ZTMv1|17@Wcusz{kQyj0y76?4wEYFL-}P7O05*D zkJ+0Mpz766PAuohga(%bliJbQ_=WY#3ZHLji}(LSpL8#C@0M>Uhj?9mN+mm9cnHWuv)>B&RiK-dO2VW>_72@a)w3~> zk3Fx+wN@ChwgL7OHZE9$L+>gPcstsaNPeq=9CLFE)}CPH*}c23Go=%-QAVxaT(?dV zLLCp6j==Zh-csAt3Z61oe5@=S%wd=2_heDo94V-}bq4olrv^#w@ey--*q98Tc{6~dg zdw-o&2qYFjD=L5C6DcbE%OfZ4_QuALERD|h|L7Kd{=a#o)l1nQlvY$Lph+BOM=L@F z3hrs{%PBBlb?3^@pn8lXefkBPd>*uWvf8n9uo?t(5@=4EV3jDp9|A+nwV!mBG zA6}F^C(h)bF@mb_x4iJ$2~5ACBXf+3Bgh<>xfbD8r7`KrqyRq5Tn zFd9YmxBBYYcc~O~7Obe`>{~L|GI*$U-E&ijM)K~R=+U+rX?ZWiX-)#e%30fVB!pV- zoTdLU+jkE$=rfa$igStBu7D}PMo_GW@Q-#4I^8?hWYtfhQwPGFuYoOPy?W9ny>j`v zEeUP1D&)mBf-1%FIA9XVSvoJ7cMp&Hcu@*TGtbR@o)h0hHVHi1eq{F+_6v1oUsBU^ zB*v_zF&pj>G)PcuBzk5k1y4ZNz>l{d8m`#UI?LxMXV%+P<+FyWfLtNHX$8USq%1p) zz?elHJB2HZ5^Rr{U`C8+sp-maGr^mBklDUN4Tma$!tnL^LqSXjzY#Ay!dG?|5f*%} z!QGF`9_N)Qr zqRByX)QzEDQ;PO4g(y_Bid15|?miHXso8sM{(IY8=q$ZjGx41Hauuxtya=W;a(2>I zm-*n+;XePSs`MU!RKb_zn7z27ME=_ez=$MEhX-YNJyw?h`+Y5p&UWH&I0pDjv;M_t zGD)H*sjWdS=j>9= zurzWxjc)d(b$U@$eG)5HLXerHZvtk_56b2iVJPJ48tjb3CAG4+$@`wgE)BdkH1N z%=eZfN4QQ+l3|PaTxN##nsIx%Sc9SVMKPC!aZPDo)leqN9F|sVLsnQLsoIM=Q5*55 z(6smfMhA7j?F+~1pbQ8}geK=}?S6eKwF*QhwuPwlC7y1Vkcptlf|##kKJf|Mq=*hZ zvtT=Fve>2|PJv<#eL*V4pS&J}YOOK`7)X;p=zHON29Ef=?0!YqDbCcGX~C0c36qUg zs#v~d^S>w5+u6sDNMU%vW$A{>zdSZ$*0`I%%BgQ6UA`~$=$8W5RdxH;j<7M*`SDJG z3)h|*Mg!amJlbfFeNbQ8Zo5f?u|HZC+a(T8LL2kzA{)%~f%{J3eH3Yu8uaa1%=taq zSobFStPRfAKk7wXZ!x8JvtEmX(jxW{n0hEZMR^Bax3sHDcy2=IiA3PC0tZwX_ZTpB z@%e6#Zk@1`8OYNg&IdGE0%Sg71PXjs5_vrGcnOj3BgZQ}tJLywq71_F75(OaF8rbnXG|xgG$M1ip(*S)C3i0`&bBD!soiCYAd_3jH z_r#2Nt-e60Qc1ZyXtP`n-ni(f)X4d>JkO!d)AS#mP7=Irz5MMlzt&Se=U^B2+aC^8 z!7iuRyh&j<(L@i_8L`#0byI3s0+X6My4qttu>-qCHKuvd(qf0b@QXF2ZaDwqMN7{O z#j1h7&b{E~xj#hEUz$%VJT`!ptLMm z`Do2q$vI=@GGt+1t?~ShV(TJyAaTG?xJ`pVPYS(>P?xBvBbk@N=JIO|qYm@0dGOel zt_spGMmCK@L=z1I8oYJGceNc^e14zrX@lOMwJ7Y9Of@f1x$)ozu;PKm_!7k!_ySd>nyyRbCH$wF~iDcWVWgRynSwa1pa!& zkP{Yj>MJ-GwmSG3d6U#=jz|#{oyiT}dbfjKu~nkgbp#TmnEHxDF8G_346F}L;mXWg zePNlJAmn15w&oL&bFyz&tdx&`iHc0ZAd-rf%IZ9|L7Povo$;itk$cT`+}aA^>wd?q z*MrN21|AxhWR7m8goc%F9caiy<_55rGu>7RmAJUx2<~qQ^3HFlm%tdE372x(Yp>L; zKk#4HKf3O*vw{m#D^l2mSFA64$`kwBCy=zykt0F48A0wO0$boIh>t*VX>cj{`U=sYepA@-Tnxa2}e1eJ0J=C78SVbUS zBq_eV%O?Ftt`9wE2unK(ucqD-TCpkDqyoGICUe00v3J2G;8I-n#H2Z~ixnh~ZQknJz_6fjq0CSJJt!G6_$}D!^CQ#_ zH3n#Ia&S+W47ztv|DlheGNh>TaLA)$RysFh&FO$`%aNfl%!#)(fWLJrBwX3Jvq$cL zI-Jvk^l;!SSTlj#_ON9bUqg+%G>soIE6hPuItaZLudcERUIH)l{VLu2M+ec2vm*XL z63j6{Ue0#A6v#qEk8BL3q6M!0NL?qyT8DYcx&-q8Z-KW}@ zt(T4RoON;!B;0cAr~R-X&ACo2TltfAnWmOV?a7FOPgCstsj~P7G^l1FpPkmTNUPfM z+F17VnS%8VL&*qbPkVvJAi5r(_nFtIYK5P>F1y4^1D z_jI7BDqry%h^L|X3tD#QX9%jr{+(Pa*T^*+A@_fDvw^!VfjZ9TBEiR-iAW^hL}TO6 zt(vl}{q?T$b#d{+&pnKPe>{2n2<>S?iO&YCwIK7u`ai{i6P6?heN>4Nh%uhUx^%d{ z1mIh|kl~n0Dq^xEagg)Z5RHiRm6E1J9J3cY>&V6(=_{ewoUrM2#BKpzPcUAv&aS7L z$?9HT`1L{r2ZSNR=UzRl@Tjo9*kH%=X8ns-=aEO%6Z;>h9_XBy}F{`oGSgO^IB`;;e5lE z{r3GzLzTuKYWX=$wc*@Dk&gsO+8*XfSkw@6(454O91!Qy8hgZJ=b zfl7*n`)S)WZVoS^Id-=pnVF&CQx>x$W8S8_Ztg?k8hC&Y#~Wt;4mPQIIRNq>yuqyU zJJ4$3`AX}Mu7}xiqjw9YLqs*nah|^KB$NB&C4b6Sp3{_brVn^dtEO?P2!XRB%jC^= z-c2-y?W!}7DYAc$-TM*y;SeZVpcUYaVpVMrcX0&$FQ&i=?$cg96+Nh7ep6v(` zSwp<~zJckvuPw`c!OMHlP;8&4125POxlYylvnP$@uC@rywi$r{MPJgnbw~Qq)hBBYje>&M zH>L{)LUi}y_5X&oA)~tO^DNVOqiiUaPK}wCq@IT+IbI_^I6%3!2D+`W1BnX(>jy5A zYYvuB@;l0z0gQz%O^apFq6nG=i1(Gghga1Jhb11LtMcK(GQxJAvj<8kw20|<7tr_{ zp-zs3D$bg(1ImSY-BPOyvKg_#C;JL<&dgK#PV(Xol83{GBBhPw zW}=>=swc+1czfd=5iX5xu0>DIUM3a{U9_*LUw=`i4<1_Ez1uDP3gbO0mIcAqDQzk)}V?p+g5v;iE4C`sHy zLz8g)<{spnl$76^a>g!58;+fmjQqC~cXR3iw-m}N9M|pAe#fohb$MYBJ@Btb2SJzH z+6HuZcw=LYH>AfzJPjF4#rC~9_nC6v1=In+0W9|S{O9k%Yld3;gxB)Lu?%_tT{Pgx zf?_}hHM=;MrnjiDUB3suvL<{5e7?SnMM<`xU~DAM$}{Q!EvFLH8j*+<;y3gSKCR4w3g5t1zqe!U(QE`T0^VF{#B-P{HuEEcDH_^@-_Q2Cj{6rdcwI>ao{hS{FgS zPZ#n^guRS=BvuWhHFy)d^ZAj_U8V%x>k#ix?|*M1HptYTW!-Cv_RVAjeMl$%qeISY zv@a)+>y-=H&b}{5EoA#W7+*_}|Mgmlo-d+s4`$rb{+h&#-#5jhaDdXbr6?~c|HF_w z`9^Iu2Ru_k?IGtQ0icg_(8MUoqMuDz#OPXD!7FwVY4qS`y_lIlmOb2Z{m(X!OXBiv zeE8Z}2S&PJjrKwCp$r74hKyeY?~R&0bHY?z{iRCY%*(*`WcWE!lt?^(DnH4!3!^LNgU0;PN=4( zImQ1w-49{RKtm#f*9P5b(77T>temQMmUY;?y9?AKTu=0vHsi6$8PjegYVO^<7qhR% zH8S}4_g_ETdD<9`v2WJKjn)z!2e@|>2{+XIMb!=Tu^Ie%&@e+B^ZRmoTrDP;-XXtjRw@M?|8vSx z{;*W#XXj{at?kjsSI4^X!&!}9*nn`t96xxECCnmzkmJD>E*2u(+GO-ExTN}2tJRA9 z=_Fmw0iPkX#@7AWS0#t1c&hOrM2X|ig1BxZv@ugUd0u~f&1VDr+g9biNAi*t=rJ_b z8985@8w*mJS^IV2=EawavMH^9LS5RyV85-F`Q{&wCcYt?{L^1V@_J1sY->c^xDw0y zAtz-5x^T^y=PPo|%!0!-VPWuP`U#_NMGf{&#n&3%Va7{2O}MUl#P&JS`o#?p$BH zwQsb;@jx--cJIDI*Az;UgQ(*Np$xv|a^;QrLK+bai+DXVI|m%h;H6EF`7=4Bj^VCn zi{0^0$y}kEiP^>XKVECdtP)K&OMbw@DH7ufy~NhRgh#rjq@4^YswT?vrntq$^IS?7 z&K|bz)unqX&FggqFrrrqy1w&6ukScSG0jO^Q6`dXa_KYsTVVT>k*UIKv1T?vEnsd2 zBW23e%mf)(L;PxHm_4BGHxVRH;eTeMX_Um~octK>!_(E_oZ>ccH^%JLn4o9vT%bC8SZ+c+gf;3I~KP;VfSd;G?_AyZr5$POC zDJcz7UxN|>rD240j?pk;vj8Qf8$`M#M~==hP?`-kV1&fz9^m`@-uL}?$Bykd?&sd_ z>%Ok@{G9J?{d@LQ*?2z+hS3sFnmJkwUfteioYHcfl-7i$`c@ADDwrg;6z}Qhl$GQe z1q1s(*JY@LF=e`HUI`JNiT1ICk0{R1P=tA-Wc@L9g+QMRZ?o9|t>#y*hJ9|ROrAYU zyOM?U{@AvM1~k7fZ+12@%BIB$y%qk_eyHT*1BvYK(X#xJ`{6v-o8m@_EzHCVQ)`AG znEEvt{=wKt>IL{(|LV4vO3Pk3k+%imi2W)2%^jTZ;>`;=Rf^d_pHmGf-g9YEFz+lr z0Gx-?uk>(}9$4mk0s9qsgWm~FL4(nv?Fr6pNq4KrX-oiD=c)mkRO%5H_Gi669t%fC zp(DpXm=x8FPF|r&I)7C%xoy8b1-QcZ4;sN z+GtL*jgvRy{~qfWzvS|bC@u&MMp>MM{zpYXqT_Yy;z@KcN3w|9+uRO1W~|ndKxp_o zAX#H|rwBfBBWs3p?q!V(paOT{qgz%VxaPzeiI`a|;eC}^ff}EZP@Q7B&9|LsB0`(! zSrTG)?L&Y~tCm|5_Kj%aa|zYW4bJg+H0;ZNHCO0A6r1-It>S;|Q(;lMf+1l`&^qw9 zmIY?fssf!9ku6VzKoxtO^ZhRRC!!fRYYU`i<0kUR!=GJ^$cG?3ABHZU0K$s86YW8#p4J4UsrEHT2;6i)jLgJF_J={M2T# zkHkhqTe6$|HB~-)<0540(^~efr%27mOE5JRG_2o1q3Yf+xNO8DdJReWIg3wQ>~DoT zvFdkckG9_g?&bOguYpZ4Hn_|$5~cgPej6geB%ey9w#R<&WZ-g_fz9#qO)`^Ewlnz! zN0xKm*PiJ1=G=!T)&5; zsUsRnRdHU(*a6Th+$2sg^(CJo4!X$LqraGv_Nl zH;~u?2_6r5Sm;EGD5eJO^((+OSiwI%;}PT}9! zo6OmNxXm4cNz`fArbc z{~A^M+B>19JXRgQsyqn+-N-cTGl|BA$vArhq2fmsb0eU5ehkh#$YX<0F0Da5QTkfO zT#e71L0Suh-h0g4bvNL$ZqM^_6ff5hN;Dcf0PEK`YAhmsOh~q|DW^}v9(=wn;QJlE zMzYx7(OHZ?f4j3eC2HkkKZyj{HIN}~v8%9K3curDCQz+xbpV0wg%#)g9!XiSHXQ!#9N8wwtyuw(!2H)*@uTyg4IYZLLl z(|P#FVe$)R`zxVL8PPPYunQf{979K|_yJfKx0|v;iGi(y{0nHrhyQ>k0Ic8?_~m;v ziijlI*&7-%QSlKH^(uBh6F^Z~l1_!|==#M;21KfnQ@#D|y$ZjeR{s$Owm0=nUt-_H z<_cui%)YD{y1oDOL9cQ)D4<+IhVr-XXNc#oQ-nu_9aYnl`sVAWsn>PAB6mE}y#JtK zB~M==Yf{Hn5-T_{OL$K`YH|y4SBf1QGMiLiDJXT|B06)-hfYABcVB(Fe)UiRK`q>~ z=>@L+jTRmsX+FMhM)hTN`Q1{#C#sQ|erRyB*n@p^fZoyxYr;Ylm|50`#j@K5>}#?+ z5(01}C9qW{y}96ZmiCU>djZFVrWnpt$)pY5rl4hx_~3LaN^a`Ci>>*^{4ky9-rc+; zt&$?zEMs2@hZVqqbo-cl_eW7=+}Z+y*C6#o)i_TccA7#T-@stHqMm1RSG&~x#2%3~ zvt%!OJ5=893cmKCi4;WIZoeXR;@*f1y3s@?<4WRb1L$>SVfoMU&itOv=Ag3reYd|) zub9YDN{LHGAMu6Q1j0nGsc>^M&H)&M5awGP_q?(W2J(=XXoB|?lakFBOF_HQqIZq) zE*$f#Cyf;#;&C_siNuayw`o?=(eCUtw)wxQvLh(BYWk3az2TcGizn?>X%iQWY5jejkHM}xR=sh_yH9RiFyx|DdA^8K^db%Z4ADt9 zkEUi-cZJL+?JfEy*~MnwriEE{)iMl=#pCPzUuVqb1v=*Y#vsr8C$j89Drl7sYI^z1 z9xp*(W~@%7X(_*T*AyhZ3(d7V!Vm)VYxKt)6OJctMLPD@b7;MR(cJOZ zSWoeCOfX+^1e6Wej%NRgzQ&(oEtcIfL({A6!lIV|5<*Jr>F7U$N;6|wP=UU0)8}4w zN=$?rQI9l~D7P3If7&)2Ij_a1dR=EqM_`W=(}DR^(iecpEz7fTS{+eRWoK zWePpr<&C6m5&SMAZL08jM0@-Ma^4%8n2$)|!*kHz1A8LnFfv2_HpVK$1L;(?>Na*F z0g3La9-{z{NCglop4lcD+u0h2Z`sj_j$ACZ9IRP9Cp%~?oj=h{&vTr89a+vM@Q(t` zdoONJO##Br=`zjxMG#hfxxYzjRX7mq*vobe-)qCY?p=L*B6pPI4CGMA(6)}( zbR890eY>BX?J#u3-Yk$*sRl6r{bPz(>@Bxy4wRmQKjzMAUDy8AikiU5vpJm7`I_sX z(ZE>C82{2ebl1cdSC_W_G+SbM_|%FN9a`$-hRzvyAfeuTovnqmv5#7`(|}v`y#YA` zT;@X>T9^B4SkZzyNd(b zZuH;D=T|LN(aMA-OKcM|DfYa1<->Oy{=#!gsYJI*k2|p|<+bwG5E92YLfV$MX8#uX z%Gn?AP^;G+Q{p9X9oZ!eVD@f3QZnU z3DzyeziFPx0@VtH$?BTi^d;t803qKqhK>a%tfJA4k|+ zNG>v=cpVAP>fS=P!>1^wkYQN?n%5`8kAOu#1?BD(l1mST>iW*LL=^HH_K051Ubg|? z0edkEE^8v$XQ5TlFt&W@SGXNC_Gi$~U+Y~i%N_^iprn<#B)>$EyZNZqu^+$Sc(97; zKJ`k{AKa{)(eR|1x;P#)e5*30HT7_OLp$r2FG8a4@*%uWnfl!7Ck06fPAQSxk^sk(=CWEm1Fsok95;AYuy?qykE zbiadhEmb)f4KcY3`5+znxr1Rh`6Ih7M?W6z}N~JZhDBAPk~=; zsEgb6ULA)TUOY;v+`iWQ*w*5WYZuo6Nc5$pkecV1+UoPY()aa8cV>6Goc~eKlm|1B z#n%zcaH{hMsNLi)$ZNLNn|q63b3M&$t>{Z;iw9z2(JD}3bvyHpkMh5~qLqFkyKI2w zC%zGD?idjEO?f`)j5DWFqL^O!u@)7>BM_MB2rHenb#itDIorJJa$4^eu4?W@%s~5F?=EIYA zvifpteyT;qt!CDA2Ac}EZ%B78>fpIC&%k47EML@od{_VHvaP)~oeg(&ZNwgF*1Tcq zz39#qf~t4XYWAJc*L@R+9evCsg886yCXNqG zx;IQZ|9aH49l2U*lRaS6s!4{c2hr>h77(Ea&BgEzn}vR36*^4`T>p>xqwAz~^|i5Z z05kO|%bDpoo8CL20n8f>qM3Px(qzfoYblEqQD53|aX4!EBV`%MdF>>y@&rB!-f$^@ zFv;g)0OOQXsODwU<7XlAlNGx5p-1!j1$_K%#w>5lq-udcmnAh*sB| z6o>chH>jFJS(Ih+_1orf4ux^SCie7r5&ZDk8OUr67)|MK(+QWDwuN|uL!wY>NooYv zkH5ulD8dFXrof~kcQI7CVF!R)IT}W7^P~c_2d@#tXsr#fQYN#;YxM;iy-9D)7^vjp zHN8(`FbN%8yS*BH3q8QlHw>)fUNl1FGq68Rm8^QSbkJcqtn}l(QS`Ek8{*YipZf#D zI7{#F4PX*suq*y>W`X10Tw6#^Q=DSsk=*rQ7nhE<9TOEq(!qiSs$t zw_$mqtW-yhJb&;l&wh@mQzsCUNFu4Br#UJ-VVl(6h z7nEI@FM2L(q1J#W+;8beL^0`XXML!Wy@1!PG^HYJimm;nrueC}wMn`^K1nA<0wD7RWjkp(XM186o2=K~c%YH52! zfFXkx+M_x6W*jv9ABAT?AcSF4s0~*(q*%!Ft?B;0=>Os`Eq6ZL{K{B zULBcZ!{jU$3F`7Jzork?{%aso9eA?!ena;l9pNbUF`13pw?8ALiR#*{>^e=3$Qjd zgzo!cg$fc`P^uS8&p&RdD~^!O!e@b14qP{4?IZON(XB7o)1L#89~j}^Bs!gYbT%Op^jv1z+uUn) zAFm@n5bhun-S=yF-XkOUrpxc*$1Ylmrm}y{o&TIAU=_l=;RaidVO7SZ`zW<5>I(A z@8QzD^4RusmEdJyXy#|C)5XCz3=WNjxGo?q@k}~#Pw&m{N0u55FBUgx@CBwg4+e6E zvLNdxW*^6@8}uHYmZ;2Dl`sN<-mlw4xq+#Bof*Fw@)l8`440UG;xc&tUh{J5lBNSo zn3l;tyI*N!D4&wH2W31b)cvFQ;xR?O1L&JxFl1^OVL$+Nbz3%@OxcZCE9R`^G*t2( zJ0W~W*XP*XNC+YX6dqfq)z-ztD3FiJly{@?LgcpHMZ^JbMQQsh(T}yt>D&LGPHBlP z{&110VA3}<$^X9(pY*?t^uP8B1T!4GNp3s9{9lo3Cm>R-{eL3WpUy$(dopfwFM~%Z zhkyrtB{vCi!a%#6orp8d_gb=+6%-8WM{CD$yg09&Ym-*PI~%+heG1%19i4k9pxMg4 zxed#yVdT2U|0sC?0#@oAsdNI)Uh( zVmb33(@-Dt{I;;usRxG7ZVG{oK)#>yoAf4tVBEQUtKlafZw;9JqhJC8=>yUTqLwXn zB7_C1cQrIA2qt`~-`{Hten6=2PxtI1`Uk2 zHr}}SZ{=X;#zo1s)%Gfuz-9<2an9nY-q}j_@bktQ&d3ClS`PAMATL!)IkCdk+fh~# zfPPlU3h`DT!e4t(zL@uE56UtzHTN#z&0-7pLd-eC%LScY`H6)9extgA0(4T446pGk*tZkUS<*Z<88*kNk*KF`>p<w96_r=#q*=RSgS1Y|HKey z`9zd=>~$C4>kk)xH%3Y>8N7E630+Ku?~leSOO-HRU>-z(;_OqT+GRT_)0G_#*t;?F zfy%W0Mh110wczEs8_R7&aqOOQ9XE8Y(|&g`bYk-)o|MX&J8?Va9ll($GY1rEmUBN& zod>n&>gYY1G_qTpR|=8TA4(e$5#+i|jI@pYckyCFaw!tRpQ4aC+~x;-q4PK809+~x zx~&J)oVvXw57Ay7a3yE0V*fujq0%#~ThJ5h8x znh8Uv8NK+a7jvj`kHXDI>uVrr{~C8`F-LFbt*fPGlE`?;WEmMFDn1sx$v2qT){N^N zKF&Ak2C2v(Oyj2#a^&0W=9p6GDzIT0Z_5q*RV*Fb$XV%^E(<3(XtlC{w_sVPipqC_ z&<`$8N@kVur=H{(Yns>4lp6R>{fgab{W5Ncqu4gtHJ!%Ua(29)Bg?&48{UipQpd~=FyU1K}>eiIZ1L&PsPjQGT+Q0tbp^ zZ42YB?!w*j6-*bsj@=Qb(JFf6SJfVDW#5j$Hg0p#IB=|yi15(;6$4u>g7mW3R-aCa zhyEme9HYl-5CN8bFDlz(|IY3(Ndz3%^J6q@u!-bwr7?ibFJF{a#*Na0JnX_g zetNd&WK-urW6= zhcvo$Wz%qS4@1*KEjHA4K27!vYCeicG;h7BhB-Mb2+pj{VlZKtJ}>5v zoAs!1vD1dv+NG)PGY!0NmU(sxiOz#+D|069J4`zL4vOIoUnckx06=3lc*0J6Duaxoq8z4@-Ov z_Z#igm~+q&>U~_zl>ruVp>iUCo+V8xlnT}(h>MB?@zat)M2-#FXz=y&i)^2zwlho) zT;q-mW*ia}$vTp*S(9#jDv2|;3DKSaTUNEa-;EI$`+T^PO@uO;`15x(g?$y}v8@_~ zEM*0!v>3m*+P&HFy-43$o!uxKKHOHj8iH`Dq{cgEF*doB21~D5H;_eB-69&VL_SV= z%oRUOWAW_pZzOnvSz=7Ndb7YVYjJpvRY5e(hKbVxpW<_)c_$#oIe0kV^>=v-q@`;$6mqOi)`SyX}f+o!Fo3>IaJCnRoE^XzfMIqA2S(RYa3KDp7mGW@IWfK^-JXy z4^RC{77WZBPM!x-%NW;<3%N?-s5KrXJ^)LRsk^OV3Nv(W?G0XNx`ERBGZBHL4bb$8 zq1S$|Rd8R-VO1piS=x@yH_IJ8z{iHTdHKl9AKLw_K0n{m1eY2#UKJQ|>zJJjO|j}3 z>RQBICAV044irY8z65cf3=jpu$}}fks_FWT8P9K&Xn9%hxlufNH1v_j!R;x{uY5}y}*l9Q zjJlhqzDlKQv2|}NoI!fy*=BM5^v}9kZ!`HDc8Rr9i2oX?yygSkbV5%a=3v;9Op&-r zDYl-ZbU%p9En|u|aLt=;x31fG`7*rgmb_e0(EO z49ReSE$pfv5WJk9@TZmz7RB>|pR9n_RNY)ozdv|ub-%|ti2o!f=Nypy{5(Md;g)~T zYVS+}n%x?lR3pC#!_U)Sx8Cc#sqhLPLyk?J&E-YUCFWSh5B3bI#YbQ1^4|D7*6KAV zA~ND-=k{rxcEEb*sN5~;&NgJye$vi9_=n(+>F(&frQ^l2H9sv$0k;Qy$a;iiZT+r= zq@7-7b+63b^O>dWR+V&cUlDJU#7l|Q#)xD#_WY$+B&O6D9pRcw}Ryx0SE4Lt^The44C%~I){;}H%Br&Vq=)A~#jZ$H5 zqgqhUdN0it)gE0zIfbQ|?>DFOuY6VXh&@g#nY`w*c~tN5k0P%!ne_)EYi=wwxb)j1 zr6O$mSnFkx2DC)&wj*RIbl7}X{&9=??s)g~y?g#VOED=1UO>r*W8-u&@E;c}=|3uG zclsdx3-@dd z7zg=w9+B6eG8byQXLo%+Bj92-&{l<^#^NQy4&vhA!^+^G64&bzyh_eM)PGgPc`&-hV4{lkl00jEe&X$Fm3A7vpkstaktB& zdcqxRHS~!gX0Ty;@7lh4r%;ITbR4XFZM0}CLC*E_Pi@bn6`2u;?BTLU9z>|B@;-enlh9FB^P!B>dMpuRZmMJ2aP z!EYz6ySbfhSKU}4){BBL+5+|1Brr?Gb*Ci8zeLv`NET+0%=M%09RkU3!FW4ab3$t+ z;?W348Img5(U(>I) zrgZdMyaBKk#cM{`@Bf!{%moWUSIKKr81jdIUGQKqlC<6wNDXDoXf&I+B+edw0~^nH zPnJ9XSvFKN-eP=ubK!Z{P-cNXQr3ICepg$G*f;1AI@tra0@zFs?#3R%WM^c>^ z$3Kd59@<>Vr;&X_uc0h4 zEqSV3vx%kH1#jc%YVYpWgICT zm$H^bPy0;S^V!VgLxfS{{}u=Q*w=Q4;+q(|BLk>E}c0iRc`5t6Ut?xvp6;V-O5f zj|mkNbNzA;)AJ244!gw%iZy&VN5p>YLsXjkRvNBKWzE_+>i5aXVKr7Na6(9#xB2nn z{R55lZ<22(2VLJ=Vf$jd%0*=Rz;2-L^e}DFIE@zu!uS{@OW1&i23?k?70x^=A*#0Ku0gka%PqpglRiyx@T2LQx?ddTuvk^ zPky_?Aigt*7+f1YhaaBonrAKf0#j9JN(j+kg}tA(Vzl>q_CwvdGdd*wtJ?r0mHOxlvZ+Pg#Th@aN1XGyEH^cpf!(Qz>Y*>9S^n5={iLrrTd5#;I1|Fr^9%o{ ze?LMQj}iV72|gZSptyYL>Wz=Nh`5IJ| zEhbjI>dSn1>aq6v@$d2?@qxQB^fF9_gP1BM&6A_bE3#LrvMz$xk25*Smpn|TOS>Z; zAb!q54fk@iyVrDi6nZYda!o}OBNB$Z;5+TIU5K|ywKsh-N_B;*-h z?vU5}@hJD>h?N-_Cwr1Wfb3gEcO|ddZzFFlP0R!pRkRkLK91<$)qLGuHZ~of!b!x`?LS;(J_H zP5nVqkEZ$a7;tK{7J3vEBp1C&7uwveKpE%TNkg7SDdcGp);nXGp52AC|0HVnW*%UC zpgh0(JUm?U69j%WM7;?5Nb#Oo1a|%I#g;SJfYG;C(g!lcrSi#!jT9}u6+@rPJlk+X zW5i2;p`jskOC1OqkDL3#30W?IlWpNnSB*o1T1XvMQ+|57B&XVB+Gev;!r$t`0q>H^ z{pzP44I+4nKD?=jt{;CxlV$|-n__yI2a>+!N7DqIxEHH|A&*03Bi%hd|ITu*ugZME zINy^?Dpe+mC;gQSGJpt;E5>b)O%}WRx`n!cC&Wn?TxAoGZr6&EjKXH=d4`Y9_ z>5Ipnbw9jj#vqKNo*I z=j4|b6wV;L#gM=)S#ngPK6J`0xM$<`o5rlvA^eoB=X*1JTGtr@b-BzetvxD5xU9VN zw)>7#VajyVRK2?O=w+`_F>_^w6tvFCy{R4VRZ{b_!#%b(z0I3jOzUF^ka9ygl^=vC zeo0+P%G);w8^3gG$}wnYh|`jCyOF2zKveSDO@b7C*%zx+kLI-FYSCzT*sup>ht9eB zVGQmPujR6^mBi%|^%~>jWN7fwrUhJ7E}Z!=vMi#JGIjir*N9TKTy$n?A-J%c=EIqC zn2%;sTV0)FS*6fKh2%x&>?sK%DSqQ())S%^&BF$(03WUF`c!^X02R#OTHC&|LSD;O z@RNnSq`KX6k{mC`DCSs0aSij=#zB@U7g08-^rPT0m5J8wDbsMbS4poLT|RpWHr``9 zj$l>QcZ-iJX?1aK+p22wJIy#T_hJ#{UbTGS7~mUEHdD-xQ_02QoS(irDs~Zx_X_46 z`bQy2CDnYLR*l6>j9ajeJME0PSQv7k9G<3?k(QNsbYf^yY5K%hi(}tv!EE4~?G3%y zVb9rY%LJ65g{fm(J<}kP$%yG0ki|Jn+?={=dCYjU!q#)U?p8l{D0N4BWiDJM$gt)j zTY>vtQIkTA+A5l%$xLuM6zuL#^PoD!{?7gSYi<@31$MrFi||L>PnNZtGt2$F22o-` z&Z8)r6AAE+Y7ECkPwQE5*rwC6CHB;b^B={NpAGUqV?26|s1tSXx#V4Z3lao{1<`qc zjw&)eyoz9s1MjD#Yt(9Q=Y9N<0<#)}v*cd$omj1Kalx*BQFa#n(6rJVoR7n8xVJyT zm6-H-j>4RdLSsmb1e8G^dPQ2S@j3ex4f&S;m_aDST2Wayu@?6=cC}73uPvHo<@*n< zYU)8l`i|Ai5)G-mvK_hzEy=^iC`E}|uZ3mn@?%PEMrF)|ehvL@9ZdX|#uSp8LF9Bb z3nsi93Ggywi|}g@_V8#Es1)Hdxf9gD2Dkc5C};Hh4qkIzS)VXD7WgkYbl8dI=EM!2 zQ;HFI7(VkNM!3v*ZvgsrS%2Sx4%#GnBLfzjS-5g3bj4DTZj)CqDtefp6SbM7Q(H60 zWfyMsXrN~G{i6g2isLQcF~~tG=cGD6`B`h{*Z6*d4Yvfx(9@a!{sWycJt~Nn17AE+ zU$%>FDR781%Vk2-i=_DPJY$U>Udx+X;?`P~c#VNRjb#QU>eRN&E%zoB ziwli*xwzpN3@m1jdb8I%vlHfz|2p67nMf;YFi2C?-#3-1hie~QATAueQ?H&T}leEu#*f~y_9!NsFFj^dAK~ z>c-4Qme>yADDmJ~)HukI>`R!qTR{xyJH6sVMDyI^h6oML7|>9 z^A#ElpA7q|@V;%Vr5wB;K?PSnF`5^y8~L)S#4+cOut1W5*f1CHAd-r=U%;BqO>c#S z8=13A&M=%kpNyMcPL|OF8lm$EfbT!KFS|N;C4yJzS@DBH=3JIQ#)!S03X zVVB!AcHhc$gqMKc3E$~gH5@TC~$W^kf2*hS!EM33jhse1<1&WxmglNB7Xv2=v@BA67Y zcSZVu7Lp_`_#Q?Cg$`sWZ}&62fnmAh0edzzdej{hh;v+rB^=xd`4dS-ipD!S;w${m9FmRGa%sZ z`q^Hy%)-VS{{^HFM(Kfy*Kzq%M*nPgd%-QEqBMyo=)KsZdEtWIXqc<&Q>P zSG9t+fqv0lfPEVCm2h|S(WrSvd70bw>b370JYH{x?{OqnMIu|8M z9I&r6QId@0p%{iGBaObnoGy02lf18~2Yj)X&;UK^?k>AMBX$&snjFr^qI~!|BP(SC z3nbfL3iy1l3<-K!uOJ8{p7^}=nA1O&U2Ws=uc$2TY9uG0znG2sM=_*FUWBJ3NgO-9 zi#m!y4h!RPDgpx+Mc->&-z>yV)1>S)Y;0Iqk#&NccM#p%p+`rioQ(_Qjg4>CK2C0t z(AzvU$&TqxW_LYr4dYKLLx?AGi?(+$3kX`7rUa(0up19a28xo(3A&5Q$43jjGH-pya4B}FMD@wZyq_vhe`w% zb)$598v3?&47&WQ@y~Wp>7-NELVX;^-utevU*TDqnBZtgIel~8Uj(1sGi$cZ%t)GO z6xS{x^zt_DM5h~|CtLXZwr|Ut@9~h~Gt@|5x$%6Kl3Q7nc@Y(ut`qY%luii4xh&kY zNU&eyIFqabgq2UF=d%Yh3soYuZ()1oj9E&!y4beS=l=#XVe~UN#xvc294CVvdJ#LunmM43HkwWg0FLw8 z-Z4TQWq;s%np`0Ju1`4tg=vU(!H8>qi;edRu}@MYr(On8S}tIXvJ&_B&lzytx7unh zDNnj=4=P&dP0M0pdh{}$)Jek4dt@@UhIYY%O42`11)3X( zm#I_cJJ6#KyHlHorRG}mZFK7voDe;bBiMkh3-)XNLG+!clqXf$0ZXKD7>2#10vBG; zvoE_Ymc3928|}wMz#wd{1`@u||73A#XJnOfo%9uVKN%(dAlqHFUJk26QF{L{-Cf2a zCY#pHUacH$_wa^yAmMfjBRNSI_n=;1^~6j`sST)$;8f6%aR0x9yS7LS+bMop1jY?VAewGxXq3jXoRLyRxx6odnNpBNybw(Gq z2#;iuKe00&y#n2n8~mB)Q{`YJH`hJ&-hffzE@r@}tjLmx@H=k$peT^er@9)Y z#CwvvXmB8-#4}YX6_M^}I4sljUB0AJAR=a=#|`M07AhcilzM*b0Ed;<&0Y;ZsTK=x zXMS_ZVEG3fGrtOYGuUGcyOMq+K|;{gpriMu&dYbTfBNKMv8AORjYjaX@%LHy+D4o4 zqJi=#D5L)|c(=FFt9bo*-yCnQfdUtxQ98P}iIk{kzKf`EpkjGFfINyug?cwMMI9`E z#NUt*uf)>!3n(wAPB)KOSw1cAi1)0Y%l304k)MM)QCW2dQ|Axfg z$2zj2d|#r-r*qHUsNQ89;m~Tz_I0H;X4MvkbXA;5?kkMSKgoXxUQROK9{hsl;58 zr1*elXkuH_cv(K|-cZ{aL(m$jCxXYNnSaILlGSg{=M)jKoa;=li`I?|o@?_d`6xePX#AJd8`|@rg*WsOjaZaie9YC2DisGmmt&LK`qji3L zRe?eukfIqlLSg5piW`Wx6XlW|!rP)-!X!wnpF&MPw+iR-*Q?dFgm65=M7;`RQHN$0 z!zayS`sLm!KgE5vPg?pmGF6fJpjvlUolU(RbeEC>l)(vp_fL7yD-!=%z{`5a<5hP` zS&HSbYx&@lMlvse6Px@D%|B`Gnq=*%tLWG&7x=wF*b4exJQ?`MPQCB*GKT{MIgWTA=utuOXZ6atwcEC-m=D%ew*% zK96OrSX0oMHP^JV=|Js8Oc1x1Z;eZw3tpf>FIJ?o7%evP=XFf`XY;90CDxO`4uM>a z-`<%rPUOkSVm46emH3miW=ys~(GChkEC$~vt3J&ICFHFSoUc{B?19T&{(c9*(4H>} za>#UE3YjZGl(fz==fY-4-0ibZjhCzc<9PO~((MG^cX>aGDH8OnZ6h!bb{S?->FYOmps=~vY?BN!5IYEErKqhIBN$|Mj zw(xoHyXLKlP{5yosN2^^_`X5VAsF0yrJr5Dzr`$EpD}p553@Ih^d!if9u)k~%#rH+ zA;!sZT_y&qj4$>K_*{p;=Tvj+20Q;`5|H+-zd7-b;&<_%bHbBTXTz|eRcBJ};B1-W zcVp}Q4#?o#V_K4Z?~45;<0Y%aB}VkD-f~;?u=q-xc=eLZT%P@D<0Y#Gb8lHQ+_L%d zP~v-O%)$@K3sO6RIB{>WtgWj)yLtI}9SYj^DjVirdO=A0@F+I$f>e6G)*L2>ZEoAe z2ELb(H(D;J4Mf^3pE~DVGYJE19di|;L>bI{^D2nj^+{b-UBk9{VRDm{)wyzynM|KO z<0ValfXqM@%5vM|wS1+n16xn-4rK>iq;W@-l)5;=_*cWj9R-@=ZQ1`}6q}G&$Wvp( z1$nQrIbDfF%vV@Eu01K=Vd}Ktt8EECn>;(3T<2F2s8(IuLs25Ka{!S*i_VeNMYdXx zC`*uQRfA zsamy>DuMFTGYYjUMvawq-b7uGxW6&UVN&u1!3<=W|4%4q5HE1Wyb%KLD0=Q9)Xe8^ z(B@4M^?{3+ID)KveYV{T+R*?mFJ0uveZYl}`oy9W@7jzh(}Jo?!!LCb*tIQJs!lKXN9al?m(`s9oa>;wKR z{6)iGBq(!wg!=;xrdL~VT{_0Aa;Ng*&&>NFJY7TD z8jL^W?X}(}Pv9gi%)$##;Lf`OuXWQsO|x2M^V!s_-XR6f38Hg_>LpdRkpPBk_Z{YG zC`XS00_%JZ43s{#!14bm=#-eweMZlf7cwo#olUwk1A+rCDfly0S%r+^JI%i28aiw# zRhZ9upllsNVolbIt2D!U@y{@^ zjCyBcvvk5O_@*Nj@)KiQYA$yuF6{xq!yWMM5Kht~NO#u||9*OuyWscD7j~Xvd;1wv z%awx=y`$5U=3=d;?M41@w4;Hbx?T@DJ!IYuEq<<79 z(1%Xa%T@b!YFsuT8U8xBCmi#SqM9ih;WTo;AZkJJ-aiTh^PFWL#|2IQ0gC?aU!9RV z&$8O5^5Nszb(B$XVSm0A4yZ-bgzz@2s1(0#*w8K2YmjyUB{PJc8Pg_lm%B%aY4=7Q zDq@k^K?7V&4EGs>^3?6;_AgZ@4pW#JjlG8z{q~(bw~TD?EqIq2tX&)LtMh^eTYBWA zGh?$DlKpue)rOjQFeo2!?Em6X|BU<<#Se?kpc&ld?J=TGw60QdV4<_APH0eQHd+5g zHSGUTbk<=_y=@#v1rryvW-wDu^FhPUV$1k*CCGYH-r?RTt!hM3rT`&Dvn~%SbJ$1-~hQDAqRSKY;yIsty=eS9R zYOTfJKR3uQICiWo71}PhU+DmfZ(_(s!ygUGaivrvTOr{DC|QT*n$=5I8jHC`>EsP3 zkif1G5?muULc2RlX>mSz!7p9yZM&`;885U6H?a9DpjfH2(Y&sS;v-JcyoY5YOj-!! zHkL9LeNTw-S)Ut&L;`-wL~LHDfHo3iY-rYxgcHlP;9B)sp1y%qFJzs}>_$l*_`ge@ zjq|nyV6^dUlX$7Vwb&a1QnpL*s5Y(|xi@nA$fo{RkK7`EEBfKR|A^)+Ldh{OLD-+G zsPGOFw~SnlnQMuswI#>_Cz1+e@6e97@KX%=<;~hAoROE7P#WoZr5KpMyZqotrWZrg zPsjFx;FN6|EDp7W?7UupbXrg<{elzx zOrY00IxIp8O^bY8cw!0mBaTP^(@zjvDTT5_Q_rR^vL0ipgL}*)2OLl{Y4>Dn zMZ^pCjDFt$KSN~(b^=7Ir^}z#x+C(hFf0QlW25c95=(OwWT(1D4#v0SRmI>b8;Z$Iw>B5-cRPd6Y%jEaxN27i zRQ9KPY8L!WrgLa<#vu3n6`n`eC!W5ilVg}z?gWkcw1-K$fm7BFc}5zUBgVYhdi3l2 z?j1`_U&|a(R301l#}}F-N9wI5Ab6qKbk~t@@xM$*kx?oAn|?dAS88InyGxC2e{NNJ zXLJgn6}qM62R2UtYos^%Fw*_(v+rwGynR$3%7p_Z|sC9(*%MbTmrr!3;wy~zT|}UO2h#n4#MTRZjH>& zNiSihZxX7I`o7dAZOcm&xK*}tir8aA^`x7Mx%q$sm-jf1)E(FdrLMpDUc}34UkzW5 z3~KRc`^&jp)=_p@qvb4un1Og=?;pPg(H`6CDY}l?M}$#JYxO+MrwQQ|BtpgAeL;L6*GQ1E5MGl6a?Cx%-JgvG0F}< zZG$Cb)Kv{Go2N)2Cz5YUlqntcb2~3pkVaw z!o%t7qxy(1!`k`p+=?&{{OFev(zj1t&rJ|V8a8Z74PX~3?oT6&?H&Bq_e62enZxZV z*A={ng8q4g_Q?u3AB5Z?JQPOXWGE6Q!^!dG0V^hTGrl%Y_7~txKHA>o-clW0MK#YO z^`_E7bHs^&+k<+WrWpYuT3t7Zp{td8NarA(;sWPf$=AarZ_11Nn3m;KnC@CxOC~dZ zBIG@~dumHUSJPyYFH+B59aZ^Z1gD*ktdI?zEy2!PftC!vh+7y0{XNgKyI?n^?u`Uq zG1=wOx$g9))mg!O@5X`WXxr?zF25A6x9l;F+HT}}kyox78|am(irkWGWG8{XCOj0 z8DfJ&FS=7iJ#^MzIZl3n%{JYn!5GYt#VgkWHh2FX?2Sz-e@@4`bFt}BX)%4-?PM;W7euzZ7*=@`zyPYM2BL__R$F6{Mrz28M%HD&7(1t_~T z;uWmq=G-t#Zkz9gxf5jFjlQ*O4CL^}iuG_WSY1yOkg=@8+|6!wUA4m3S&A3VC_}M7WkBltfm4wC;2fII(%kJmi zR2rIu3r%+mE*0wji%buI{@p-|-qoeF*5%sSwcP1OkmZHvk^TEl@d!WqrBNZYq3Wk4 zBb+!+SbB0&N$25?XLXAYt_U^6Gz0>ZyV0gGY02f^OL_X@`>4NZ&kvd15Jwb zj0|1TKnn%~$?vA4Z5qd;L{&0g^0`fHIgh)-B>kAc2rO6Z2!TqTZDy|3g==O!k;AT# z|LLwYO+PzldN*Bx77!2jOP_srj8%*X2<*9+KB%N^QfJPjD?W2hh^{r*sY7EP64?R? z8fLCIJAaE@{n#?d%qCvbw>kN_Sb?I~Vq3%a7{x!4(-dajxqho;{wWP1=}tf4X6x@! z#c@{ZCqDgOaK1aTyeP@-$n|+m2J1HsA)5)LY|65Ly&`6vke2g(W6q{1ttJikLNg26 zhpjlFG3aK5&!uPlBIZ28xQb+-^{ly)qymO9;!OkbW^L_|cXM6ZCHJtZ*Okd=k_&!T ztpkO>s05KV=XmFSVv%&>m)nD#sikd_{}C#PX3ud= z?C7fw`Li&Ogo=xE0=1dlZJzHRoTycVZ5rh~!ck2;WIH_y?en!Ey`3X<5sDQ@?X5Tj zx)+{c1^*;AY1d(LMw4|s@Nj6ylZWFW$}0XkRVHW3HqnBeUvn4!BO*W`VueE29AS$F z0kCx!$Lah|_!M`{JRU>wv&zNSBU#m}`1A1dwUG^y>}CYmCR~~Qh%K+s(z&u^*HEKm zBp4Xl=zI>?6&8Q~u{`3ddi$8$XN7s)aQhAja*uU>Do|`s+m#SxZwk|c<3#Mq4S3^7 zMQv|+6bk=}3QUKt{upT{a1)>kA@=i!>GXz*Y{vh*-_^^~9Sx>0+!JC8^fO+?oJsAf z)t6ewnanG)+hUwQaGkgA02*m$Z+UNWU~GHm8HCY`@Oa5HTo34ZqaDxuQ+nxQ~s5_qvMB|s~p77gyQl* z7;jy0B$)C*4^{sPy3blweVYtOgLvG{Ot`71Weo|G+Cenree|)RhrUli^}|it43}MI z6e}7ui-x(*Dad*ry}8?=O}FlGH+dk)=|F#j8A1=0pTAacDX0u}L=Fqh1lk#xM{FiW zC%xC)j6kvree(+3?wDEC{fHrClHPSSH-kbb_7*Vy2UjYJpii;E&O(^OSA>;5vCW&> zl*z(kf<~uSR$9=!!08v4N_U2eB%j(u!5&>GsLuf!8#{S=`>fyKR=-#GkCR(lSQP1N zK{Cud;T)USW1wvtirp*!7=o3_C#OF~m(qOC0H~;E71A}Y0F)foQ0&LQiqVQE%<*oO z$klpX0PtLk*QCd<1Jat>0~Vi1?W;nRzfMJeU`~E3mZ0VLzRE(U)V~Re|Br|)lAReg zWy;3rOZSfVfz?&-vjgZR9sViQ zaCOH&|2o7GHL{kKnTm=z-?uV&RMPgHXBjB2O553o(rJGf@gPl<%uoU`}UN{ zx{}npck@7D{qUDroR5UfO4f#1=0Ys+V;#CpNK|iKk>9=oau_W6g_=AfowHu!iyU{< zv5f5-=LOVMyUhMn^V27 z$8uQQI3JYl%-3FuTB&%;_s&abQfb!@oY3f9ee?G6_1k!Yagy`*}J1(0VKS0|?g&3g zKI9BGHTaLH?P0^KZ^AR@t+#Bd;*6zj4WT^RnCBTQPkXne0ls!rZ|{MJZX>ke@Xs4Y zZGI@%J(P?^U2{k>Q90w|aDLLE{L7#jqS3cD9`scvWtipRve6fMq|g#oEc9dG@B6Xa|}h zOO`-t6dX--K>)L~$-Q1cnL|aoQRL@3>sLXpmtZ zY5o{o__g4NUrgQ7`gK-dOY>=)GVj|de(`zruAuGj0IPlXE(2tbs5**a`S0&BvBtWg z2f2SFtt}$wo|&iftQhT^H{;f52dvPk`S@5mB;RZbA|GQn%&3EIw zh3MB-HH?$#<=Z{&pH5Cf<&ELNC4OHVQf{>eKE!N*H2zRMf0}dga?^+1;?J>rLKpMw z-666|@wYGs)4J5*FVg&CTV#i5f0j^67Oy)xgR8D|piK#DU{O`YaQ%t&$*Y%{kZ(jw zWG4iIqR1k)gaFldbX23OgxsS|uw}Ug+4`9Cf@fpL>L5$=w*pWHH?9ctvELz`|BhZnqeRrO@aUoxPKsS9*HNr6V< z{3!GoinaiEz?EFY9piLk{l@m^%WGBXeYf!t51^Yru=%E71(FFofBQKAcBmjtiZ9Cj zx7#FuiU#jAoaA7H1hlB%#iicMOb76L_r}>%C9dzQ&V6HIodE&`^-D*-oOFK6wV<%O z$7X%cpIv0BqHWI@Q-&(W8}ZwIZ+axhfGTKsG;lNh#4vfAGShb-nmqt zmsw3#xSEK&<{DAn&y)VM*(2TodEDD9j?yJ|LKuMl#*Ry(g%<^dc}}`N2@4C&Kx4!Y zOU&BJM&BPv7>Cv!`hF3wLu&`@!(G=;q+A~MipqN2{U>*iWplxVomO7w-%^6030(rW z*Ssk(mt+-j!RsCdDVIEFswrmHq|*H0C~uUp3`+W~pe8M83p;#>Z;_+LHv2VW0=?U{ zO=f^&&e?lZ`0=oj&)nJMqDJ?KPWr*a73b8JTJHOIB_3niNG_Sy3}4iR=P-MyGjPyc z?b*0sK<>smfyV8QXe#A6u@~X?Sa<$jbZq9I_3vzpSOyt0)=)C^1(Gw zgHSrHD$s(dfag6f5lR2~an_&9KR@U>8dCt-%!$7*a%CSXY9B4UJzfagoT@<@B^s#0 z+dj{)106E4I7sMU+0BP8?{(S?wGsfTf$f=3%_E zRd&fGI7K|*r&3S$YvNbyR^fuSA1~E{PixJO5_?d9hZoAX%z+|YY1hN=TRKk;+154e zNXfMYU%mYl!FW&B9n^-S$7@y#ZCg!#--UPxAysu#@A7$+KAyC6EKF5ztb_c^GNW*E?lf*c@$YHk`L9G3T;5H=o!y!H`{`gst0Dh z_%H1QbB&4s%ex%IfOsD!wmNX7%TLrFP1^p9$3F#WlEfP`x-T&Jb$6dLuLN zcGACOAdvIrb948qjaG1tmz{YkwXo7FwvKt--tQFHo~!M$-%2wsrU%vnKG_Oo*S(5K zwDvda5rh(Q?SkS7T%|zS$*#&qEjtJ;--aEjXzOer=D2+0I(6NOO}#-@E8P_LyT_jm z(*csx*0iEg@9{ZF*ooj-I*)i|mmfIV>s>#1vKZXYY)~2;nh~kgf^S@uY;1aiBal?H z>K;ro!UG#{KUdgCyAM6{EKBaPbd3YJ=u!S4(z#ycg>Gu=XSI7?jrjZB+wk2o}e zi_O8CqQhcdep~FE&jJV`sCl_#DT12!Tm6zew7s~m5+XbJ?^z4$V>flr`{j}|$m0HB zt3?xmqLxH5=`ym5_v&!i^(>BVZX`t=L{T=Q#Wu;EIB`4-Zuxp?TJ5s?w%?jGWv~RA#2z^Ie?UW6cAAB zVJtRuTeO>Cr63)UJk(;fi$xhH@IbQsFfq2`0svVt4KE5l`)r28qA&hj3GH1b(qk*V zPXw;pD<*PlJ-eJ#9pkf&R$?RK?3|f1wkMT>=7Nn|aJd?eCgCDqM`_f(Dk>xrg{@Vb z+D?>Q2|bswYlEZjh=eYdizrpHpPe@y%`otRc!4k{C;8D&x#86lrNp-5WT-0r2#8E|+Eos#FjVrTzP# zMorgT`K$I|>$|TD_*V->qVJOr zSgR!Hz7C`TA5p0U^EL~MZFSgk#l_Txle8>b-Dv*MyN}G zuk|k=$M;O;yQl+dCi|{TTHOrxCIU8+jarwsSgHs}^E7b9%ROB=d@kze>2FwdNYC4#+n(9(`{Dp2&3dSdx9seQsw$Vm^7&oroJh5L>hW29MsVT|^ z+7gB-YDVdNj7T2i%deI-L<$XwnJl-GDCVfvMw{Gaw%C*LCa>#nL(leib>>G;PlD)%gb$OEshvDhlZiVyt0*?8O1rho{r*;{>*G0>Q%CKEyuh}-v!!K6^xyL*UzoX8S$8LO z(zXE2lDv8s@-H1*TI$;9-?kgya(kbmKSTi@bW!ABZ*s?X7I^OtItOg z31WG@9foIroNK#S#^TA}{zj{J?u0kKdrHq^Znr6{2EcwZ^#k7GC=DmaD>PU4K))|g zW75)s%{aGK-vps}PPH4YpSg@`(}<;=qgs^+QVmzp^GRgCuRP z#M^qSmeUU(v2J(O8RBdDUv@hhglSv79l-6lwRZbd%F z|2>WOUDGX8`$t{tf2Uc#_ca;K4d1Kd-+WMY^zvdTL(@Z4^wqxdsi%{2`AjtKDZA`% z``8fQGXD*w?cxABw>7n4Tf)2s&UR)TO+J{VEu}fnsZd>+7F|@{l73mc(K()oUw>?< z>gecV*9oT=b4qFn7<@Sib!-(`OwPt{&_;|mdRn@<_+1*1(t6{IN!as5@&>z*CmS7gN$latYTM>;lN z*hqk18u85RG#1^H^+4w6tTERI6SiI~PD-MoWXA})07}avp-t(w?Zk4Idb`6(*CmY! z9kt~MUEox?`1xnj+H33hCkBE#!i9a3TeO6P~C*SVVPr)w0$6LvXyx9)g7 zx|2A>dTh-iMy<6xds8Svplg&mukV)E)H>a&Z(={eBm)Z9atm1(q7+rC{+^Q!q;a(P zCcKMB>?P^riC{Lf0@|**FG%dZk#OrPZ2z+cVD8pOM4b@(gwf#KZ;41?4e*-5wwt~$@qJ&Hu{eV}6>jdj>0Kn)N8!gnR zMEz(SXwl;NRF4ZHAxvqr6c*jR^<|Z!sqVORb-VNE!H|Ko^)r)ZM1xga*+@C=@qVN4 z$uDfo9>VcIA|!Bd1oWi?pqqXogjf?-`04kK=T9O#S~ulqHxvtw7R78 zadqdwY1@*>;wJueFFPl5=AAt3`){V|M>1!3F4B%?dZOxe0D!WMpIfx>?z8sPJ_o_41ST5TOfI3`R7j7yED3SJ$MURG^j^6zlEd z)s_~i@7g4xDLPesLXY&c-=6ou?p%ca*r!qTUXN#g6Z2SqY!H+a*nF3�|TYXnEZ_ z`SyhU&%*jy<&ntxz+hb=a2Gx!l$Yj7JA|bfUQYZdajhPA%37z-_twmRymj$Y_iX>h zv#7#j%_7+FvU7b83&0uj-9&16v^`1OV;H5h7r+RwG45#Yt;f&^&@7-$`w0Oi60KuN zY4Yd4B^ex(89iyV7^D1uxYekak4qBr4n`dY?p!X4d~28YVcOFgwd|0N2=CK<8#zHG z?a6uDHJzZPS3qdBXQ*e_$$v!r>CC<-7bZ*X zTdvo|Gl10=LNd$E%{FqQ4@TeSpqsUYOWvM5PHiEAWwOl$6Ka>AC$6oJOX{1iM8dBX zl=?$E`MOL<#2;{fBkD*9!dbJvt8e^(ni7$iD_u(uHhKG9-amDbw-yZt7%ck10ltXN z*F#&^eOs56+lWQ%E!mxFsQFP|MhL-f+q$rhOhN8S2n{rfgNd<8-+0V+AhrYkUI97l z=dtQnlu=NLH8b5~S5r)&DBF)W(mQ_^zHZl!wx7rzv$1VwnzuMom%c{f-zLTWN7OBX zVILvi0IXJ8yan0R%{OFqPa5>IdpD$m%$Unj!oCmH0&&k}UWNfG2SagTRONCNza78i!t8GI?fELij0{%V>!jrgvU-LNw3 zzWwrz(DPNU@C3gN;?#j)na>C(2t8~pv_3E9I%Gp2{`F*kE=QAd%JUU4kc1H2FqIvZ z5S`F8ChZwn$bkwSO-4chAFRC9=M|0D@FDJ3=BHdu!DZPXuOhd*tljDF|0l5hn`_*HEY%7g7Vxi?A9{|!2YZJ`^zj{ z(-uqBAF`3l6EvP70qhSdx9+{){4`UdU^*Du#E#)UZcsl~3!_X>RH$*jax4#I@n|mR zIsM@9!Xe(26z(4QXaOKC3fir`;0hgllt*<YMc+HW`du1Y_e@IV^00Z4YYXE|OIPuC`u7Pc5R_N}2Fvm5%o1&GQUY5CBFj_GeA z85IEp`MXZ}YjK-%s!~&I)(2)0Cq%d^Qe z&B`2>&pkx4n|HfZv=A2JZ)MK^h_p3MGym|fA!09FjBmjR2?4_*Jw)HRtCTJ7J{|?) z+SwRT(|3?4EA9eHk3)l!Vc?Yk15Lv8oyrKD*8dKWe>5=* z6m_vxxMUNceC#%7y(_eJlHs>B{&OQY?6~ItNXo$M94;~RU~vW(T2qWDXGMN?PZPajBE<#={j1z_@QLf_FuVLG+)(5q*5|}#o;aOfs0#XCV0~& zT*1*7kM_Zi`x}l`yoT=oUQ4Hzh)*2BqBhRtj!hH0NCLD5tXXH=Ynrg+-Fbf@?)$!6 zKp9b@gbIHTHO(bU%0$F!DLWNR8cOx^!qDL;YRFVsdainXT6@D{WQC6*Q2Kf5H?XWM zdq64@@u5jbdHEO-O!h1OTIdD@&^oG4$dI{`YU-@0U0P%?xgL_TK`M?ee*qXZbeOLa z0^Ep2I)c|v|0W9z_T6^@Lp7^)&adJqqw=;dyD*P< z7cUgbtA*_@5iu>?`Xi=FWI+OEpHKZozOMM+RNz8m5p^qlE66*xY?4Pyxo~npb86?o zIWFG`all=HS>|mBR#@34{fihccQYXotW*)0?XPZ3ZfrrbQ^-rdzV~ z@FAWB&VFr<)#S%F*#SiX=7r`Da$3X$er@`58#y%*l0E7sF#tvvQ(bQX{*ju4sdPu8 z(_1XtHsUQ{75)g!ez3xmf45$KS>UlU3lJ(;kSVA*u2yOlcm zC*5U@$?HpZLe-gFZQ?!|svyq88x%(nJ?UtP1>UA0{erJ@x@^YmG7^unz$gMzXXvDl zb+ht8TI=*r@~P&nSMvFXT2v?p!zxvI(b^E;NDFE`@4uM*?1vkLU4y zM4i_qRDSlhp}PIeUhm$Hm;URAENNP&B)#}_D)1js17^lId{)@r>ycy}&BsCpu2Us} zNuIeHUs8IEL?9t96FiMi;geU*?zf0ML-g2?dB<( zLM6#e6e;-I4>0VO}scIXZ<^GJ+u84v%c zg|Vlf!h#QAp=3u5E>gzk|C9^4C&ez_Qlzt071Y-IDT)E!heo9D4T?Nm{FP7@dls!# zNth)D2T`F|wqtEBc-i{|g3YW&NG;IvV(3XuG}rP_lA6*_5Sr1188ZV^b>C83c^2Qb z`k=(`HjQ`D-ps#HA(RZ8xKKVqvD~y3teHEq{%sKwO<1^u@$#c_tuv|%^P5r@$~7xt z0u4<<)qQ%9i?fC*hsaNMy90Zca+7#XdNk8h@5;tD1@;*&J1fvxph3Ai@s?Bm1Y0eA ztgR}VoEdB4 zJHh30jqSg$FetYMOI2@9#um_0bs{zY%O+s5JTk4N>Ulr*dJV5Yt@Gql>B{T)|*N^x8rFUh%)T z_jf;)Obr~B{sR%V*zwzndF9O({TAZo(aA0x5%Z; zRc#7ECyHXB??b~8cF1L_8G|?GG7`f|?VD#T2ftXw<#F2Zn@_hiixq?!lZS4G1zVxh zw2So3_wr8(g2K|4DltupS-(_&_O?{)oof=CD1~?o=IGEVztO|MSbjvsP zZ6x@VcaZ-PRR<2eBSf=~cyFB|6aTQUk&QVtABA)XV%gDIhqjmMd`*9nb2nLTr7DYV z2LNRMIt}KphI%b5<%>J=*V9GBS*!C7-LFHG6 z&jd^d<(<2lsDzd8zJ}$a6mRTalq)pg{LlOe2o(_FTNe|Jjwrvt81}Nan$yb010kV5 zkZ3FJ*@WmX)RuKrIbQk+fl2P}vI9X64z!O72l5)DFkykm3jr z^s?-~(9#iE9wOV3x(Y1f7zQQf)wUx{bNX&9$jn~N2*Q^;uR3HjgqGXQ{*4#(pFc`v zY5UNC1K-c&jUZ<^kI67!v~^bR_E7rz_sP_joQzIv_K;(cgd_|r-xQBZDdaUhT9%^ zPLzI|@ec(lBqxcUr)zqlYsyw#mElc1jp80u`-IO?rMe%ijjtMG&9^ex18a74*u*Picg2DI%9=ccEj&Z`B zIB+IG*B(W`fp5XbAZccXPO^!@fruFg?c-G=jEf~T>C~l=YC!T;AZ`qXHo5n3F zzfxnoT|G6LK%T@ig74rdf^HRfJNmbUay|SqlwK~)^5jVekyF>F$>9bCt`CPF$qnD< zQx|~O8b8#MHJ8Gf`~JZcFndtRlyy2CBp?Mq)c}%>}vQ5DY!cI>E>P5iNjcm7$q!O=ellAT6P? zkbHHQf&*PSxuGAW7dGp(3Du9M7d!jExQ!wH!XM(()SeP2k%y(p5eNAexhS^#^0Am4 zV~}_xA;Eho?w9=az3u~9hNW?y!@EMWsc$QW&vF9%ipo!{)gyZN>LNFi#PVjO=yHlD zdCHdGtSoAYN0?P@2m2)kqV)^X-eS5Z?(qIGjvWnTR&UBRb3k#rL8PF+P6E3FJUkN~ z`6=y+NDXwPNPb4HGqUlSPxEoMMW{Tkhz@rr>vP`E%PQ09cF^QV*o_~r*^g>*Pzwh9 zY->>dl?t`9We-kG#W~j0?sMdr!bJ5jX&Sq`U8qoFg3Vy+oX1E>^emL04Q@@iN1f0M45AD62We5z>7 z>mjTZ<{FC=uvGa9&wartGA#w@{Q5KrvgtYDc@lHczFOKB;-q;~(4?)4XS*>S(0lsKQcr`JzCDok%?HI0pZ!DEI2&WU8k}`&$Vu7H_bVZ0{)LnCXKQ zbyjcl>VkgXl2)zY#7k#X^>)JgqQ~9nH1_jMY}zi)+dA?Qvpku8BGN<=4ZAO!K>?}9 z+HC;{(hZkmnK0OMS2oe3Yqti4@A{=6bMT?yVaG49ZDS|G^vLhE;?wDjHr{|lksl7(Qz5w2952O z3~jves71+Nx?V7v=($-sv^8R{T| z7(y!>Tc2|BRQu(X;{ZLOY}XcT7iqSopdib-zYI6LHf51PFCE zChqWFmt0;rg4kCp6!~G_e6A62FqfiLt}+P;Ea38|PtEM8bo#>T5F?vbxBa+C#x5?z z8wRIO=X-+uS;O%uo8go@?w#NF%8$3!%IBQ-I<=g9;;U@5-0B;}YUY6E(jFh5b3_tY z<|gWTVu!l0P|O#B6IE3u!Fa^ab+nact5^G;e%*|SeH}r>eBJK6<+9q6GOH2Kw9Xyx z5SvE`Ke1Xh(J{%}Bs9(T9(xBItCLUB z{mFHxN*Z`5Y#4Nl9YtRsK7&Clv#TGEch1JV$;hCp80r+x$90`g^o@VK%h|n^cyGR= zl;>P&!l+3VWU0bEP!wJ6Q%TL)BY{%hesK`{^vBR=`Q+62B?ZeF_k5RzFMRsGh| z2n-@%=l#p$_$sj#-sLLwlIBiMW;56o*68!P!rz6!-b8+zywM>=@;iDV`GT9-8W!_U zQ^{g!lo06^(iLu*BuHHrPpk&XoX}=+2R_H#ekKqiwMI|Yt~Q4}hW3gF4iBF{t+&+l z?3x~AuEZ<&J#m8%tgF|_h!Wb~Av(HJJXL*K^HtN3dV(dUt)Mm?jI@11-YuyzDn_St zq~L9I$O-%l9k%NT@cT-D2ZhTwXn5&qxj)4W!IW@@9K3nw*%6JwVDO=PN32lYyQ5zX z2!ftkb`cKo(8Qx-goTRm@4!NhdN=u8I4H^x#GBdA&$G!a1}~SBLm_{(!3n7Dxq0Tq zteEG(v5eS^XQrE;9WO2u4vDPL#|D%<%ZE3#UE`kaW976}DJndiH`8I{BTt9gFEWU( zTX>>BE?G<*u4tJ6gUf~Nym3+;{x;qpbA9YQ68)hx=M^2vJs|hy*zNXVK~4T1k5rLg zGEWzIIcNrhZkE$NfCbfk!ELI|X3+M~MnD#bQ!U!TM|_Yh6RC3k^TG1|yZJ(g*`$y} zESH{yq}Z}L53VIq8bG)k%q^@pdmpueU7k5MeKJ|hb0ui!9r51|Iii>!KAKPq+@CI) z7j&3C;Ny4$;7$qcScgpe?)0| zD*T6L-HLug-WDeQ9~2ll;LQzi$g>=Ka&T6%h-qa7QCZx9#^nUaVg8e?)eUk8m0Z&0Pi>DFSYz3?o{38MzvA<&7ba4uZ&- zBk|&dDnM;ZxY`LZ8|eBdzJMdBu6M^T$nX^8EnZZXoi<*TYawvyxuP~b-tqPE6O$)p z3~0}5#cZNdPmpweX*=YL6ltdF$z?jVhUFn&*jHI=iHRT+&!g#G8U5k1J`tp_zoc&2 z;NBR*lhge91FFO|S%CFvIRPR%u=zVD&<3iS_9KfC+KZFN}Q&T=w9@kn#2%u&~M^VkCA$} zm}R7+RaFMr8I6G4j^L|zBs>1R3r}w>G!N5}hTyYcUl-P`Tn5ybExsj5mrjj{g(fAW zoHN1ve2BJsU~XmvRiGIrxp*@jsrjq_J$b^4fSnRwTqQ|Q9o-3vBm>0Xm=58HV_(AH z!=3UOexb&RwAcvX%xt=@HzDoTlC5fg!V|)R)>m9GH=IYmJnZ}a-Q`38)lC;KLHQSdXuzdD-0xmcUpwT*n5$i z>oFP|9eMU*cB2p`FhZDf7-D&I!qA3PM{H+|GHg*IA;H&!8SDt6J3S%ePb72y9 z+PLBdM1S4#jBFg9%GJhpc#;L^o*`4Uat`R0bsC7t7N|9gs%Je=*pr4t0hbIHY9GOt zNvT77vDk8+=^$VAs5}`aj|SJ1zX!b0%FTg=d!LUz4q)_)?W8 z+^$hlIwjKeWVVtdou29T(S1&9M6Fj;793+Lnla}6rF|8=gSW4Vl6n_7$@R;)rY)-o z0Vz8*h9*6~>ElCqG{A?-zNHjkwD|xBEcRLuqI7z=gI81{@?A@}P4 zJsHthpO!)!MT-jDE|{$3J5pP{ZCUae{RZb2h&Qn*S-}as6+hFF7+l>bEv-e&VOmVi z&vc0EcrS~?82_AJ@Tnzzm&f(pMt2Zugzah5)KCf_@jOLmc>PE5&j7=AdmZPVd=TEA z6-lGn#WTCN8GW;%0WLGN=mz3Y?W35N`GSsjN&SCx=E{E*p&_^SrPw7s z;u(2KZgg2vAeXOfZ;~Pg``>!~bPyywJRF2wP2*LEuu_@bZ|IE?33{+(321)8P}1w| zq4uNk9JNIk3quykF3lp|hVe0~=qff_$K&G=*`$;8wFH~8fV%wZif&2S%)(jipQWP6 zqcvKEiy82H8yH*?G507faH!5gjc4U%$ZQceRa2R3OChYjG22!v;=TZH-|UC%FDfLf zY~qM9yup!0OXesw_4VD!F0j?hw;O$8Me#tT32i#faulv;!M<9L^gGUi?EkP3(H-q5 zgLdFrjW03LT~bkQHbb@N2@pOI@vd&4?-{uilcK}b&*M>69&hZ`y#XEdT~@Tc-ybsj zJ09HPewHrC2Zb*uiQI2of9V>MTkQ6N(~Kgt@;-zU8e(q%ZYc=gTWI`n4GwJ$%xNvv z+VQX0=NvIgvQFeelx>J2kAY1G)qVjQbZBlGGPhwyxZ8{dwy*0;&2 zI~e?1BSt)IC~4$smSp^KQ$a#m8&|Yr#;j>9wCFNcY}&V>6%&c6=HjM~YZ>)uX#3zX zl@vW(W9zb22+PRSkadF{e^msCoe$x9SRgpORx60r0zzsEs_jY^fME^jySz@6oW}dP zEqH2GP>Sj2hJ5j>O2yeSDRA}~33iD9X4egSYPT$78^ID-Q1LTHi%Kt|p-W684Ds^s zgu>IXj}7B@k|QC5;%uKK=a{ft zphski%RlYTbSVBVKV|MiP*fX-)BE{Ry?=Rrpoh`7Uogk;J@!<3uA+G{MyN#q-VTS5 zhuV#Micv+DTK{*cIzk7pQ9{x@d8iTtE{ywf4|OEGiunbM_fdCQ z7kpbYvFaSxYizti^68-yqjyf&jQIht4A9_wN%HSsZtoSOqxRRRpVg5W8<}ozkecvX zAKLWSRq;%|t12EF^2oy~ki?5xyqZ`#d?$Jzsz2^ciacx$%^jLan>iuwC!~im+FsXi zACkTQxBM-wpzO*)_d>htK};?O!liuc(_6HQlk4uP<04*Yf9~wPT8_hz?GX-88CxEI z0_)N}QW!LeGN?Hl>s*RSCR-5cRze<`n4vKv6{f-f;|3Nbf!?RMg@1b2mc8QuPCIk# z7t;SS=ukWL0+zib#RU7_B5*bTurM-FAvpc-`*OeRoFN_Wmt9@1Se-+0(gnAwb@ue#eCY0kRj5Y{d$RgulG z7zB8=;@u*as~T1pf1mG&T_#OqvbDLU9M z<=KLzfl0}39m&q$95>gWMam9b84X)rib}(4HC{poAUulCCnV*%wd$+aHrL$w#_O z#eDBw_y>;i1O(FtMiL9BU22x=L2C}zlA?mS z*P+B;kB+TgEe8niR8XmL@`l_|OVNTy7c@_$N2z5l{XdFsS2Az(@g8H2*tnZ%-$APv zn9l&r+O1xnbIzupPM9W|O3!8R$3c|`${$>E$tPuTiX&e~o~{<9nezl{MR>V{w2T34 zR)%ye%uL2hSm1Q*Y6j|f*HLnZziAhwu2aL4{=6_zRX8F!c(tc3F*Iy(PMgT z89e?Ew5BN=4Zs{w{l_h|Zpw`y6 zJoooqMFevq7Il-Ps+}?#itlFHQWBCXO>`q0e%m`ykSKwb!*vU(sh0mu~T%ILv_@28uefv{lux8GYLXsSjg!)c&M2POrTQqLXDr7uVWgei-Q#RTr z2{*iQukNR5+Z!q!uBFmGg`{4A+fMNzyJJPY5PXcLhWYOP1pAl}1k4RVsysdV(Qz=f zKezBqBt5X$?0k&lwDH^zVLcJUcC9I3YizRZ6=3a%Z>4KpNxd4rH1%{zo#ytsDg*Neh!>~XCyNr}A`Djj5>BxWX~M!LBhLM>t5WI52K(@Al~xXFA{ zoEK*#eav8EcR4rICyPr7J@Wv`1#wD8Vl8Pjx8)vrp}C6fS8YM75UB46G!=Nvy3G*C zH>O_GJWQJc9r&8w`LT9ug(|H>X7X7Q5!XHga-fm0Mx@!Q1Zf^&g4UN~jgjq##<%k$ z3D$Ldqo%NJ%^2?-^Pu!=9XAq&8OAnT@~FrLI*ur+jmU0vaNSQhR{={K3;Lu-h6q>Y4f}=4h3_seHt9=-zaqP}T`pNgzI{$tL@* zn0oq--nH=bO})r*4qVdwOcjGa&I(WXbrDfhY6-HCypa>I#$iJRz#?s=Pm_vD9m1Hm zZ2pQ8`C@c9x?naUA&BzrS=E&umCTkH7e z%!7|F2zgyr!qa4`VvT@b&Sq)p(mgacx=qEy5wLSJ#au+iVzI?rGe?xJ^ad#1ZAt!n zyhqFL>qbdoEw-a(CMIh_^L8Ln-*q&pFILv#L7zZVrk0^@b1&1geVe1@wRj~}Es1)a zwH8;Cqq3$jiLg7Ep@I++9T{pw7JMl6jVZuyzCFCI@G?_L>i#tFo~i zYhZhMmB8^k=UP30&Fuy5>F->lX;JB?6|3>r1Lj-0>1j%%M|GJh^SVMB{Ca>?q6PF8 z%Atpj!D&{eWc|fI+jKm>+f>)o#HiStjb&@VrmSj}FdJoAr(i`81ExJes={ja3g0%q z1ddlre(5hF>#m{5@mA1_z(f?M>&=aQ#G;spE(Sw=d>SShI7H4xhuU-Shn9%WxWz8^l}D+KeI( zvc#clWM(Ky$T3h~MgJYmF;)#h(L2Zu$Pp=rHS^rq%+mD27OFnhyvm7bA2=6)5P3zi zTuGIRPNn8mG{;-N=jIOhUXVXC%#eXu#FuAID)*ke*;lkH>kL>wKl;J_#c^8pxx}xO zcrW6|wpdtVcXi%*h{)d0JTg{J(YPG?&wIDIM>H(uDPp>*FB=~faW#4PN0s`;D2N4f zd0gK%N4GbHBpr2!blxP(a@z%S`G@(+N=U~FWU$Loaz;46Xw|f zJ3?cFb{UEY=9yday<{cALUQU$L}vSzNE--do3j5X#CO#bBnMhZ4n*$$|0ryi79Ksn zOorack1fWuniZY%M_6pag%YhzJQ5-`TT(km(QJ)lUOeX6{`su7O2^ ztkht@GHFJ<_<0O^2YpU72fom;9PC#^c#bTW(yg7xslVW{&)lpcsVW89yZ@sIyAbW# zQ(l~UU0q#WUuT)fi+IBDLcW6|75g^Npfy>s`TO_MKs6{ZPQ6htmb0@Wdu>XpSE+UoHK7nyLKiX~p2P8n|#LuQfN?lmq!qZu~1!kM;3A;sMBt5u^`o3fo8&dF06bIo(t1AZ8tbmgZ#ez~#Y%FMn#v^MMwcnTS(yj|g3 zlM*h?Bq?ugEjv6m3^;q}fP&M0DV{^*Fb*-?3?4a8>txYE(xrDV!-n6EH(@U^cXj|L zc2(xF$qtC-gD)7V2%{0WB;t;_*&JXrIVurt*jZ%?qO1viEk_{zRUPQQ#lObwZ-6M* zj=R3Nq&^RAV))^s&LsxMdHHRLg1^E-1MaQfWjK%T*cY^K&ruk1SuG? zz~#`7;5DPD<$gvl5>;4Nlpf)m$d8;$Ko}qHfq*OZMu=-dq?v9%jZOa&1N4PQ(5g$+ zg8m*O#53*pPx9v*a!-8sxaHXH-nsOdX?yhltoMDXmOYWh?XFc(fk0mnW;p-Dm%P}I zh@l-IV*gNIuUW%^pa~yQmQ=~g*8`!fp>k&($ABlr3 zP1Guv`Mr{R>+dIC(sN-lNx_5q{P`x5$A_7Ew#>iAh!b_zxn0&^{1U+gItvf@QFL3O zi_omR6N>wHuIDM_6smrenY81KhK2Yzm3GuNsH|g0)cIIsAXz|i;aqeKZ_Uw1M%EuJ z3~iR}fkY?8-W23D-~GHRGjUFl*r(YH60BT>w4r<|&o3LV!*Oyl-jLyx93 zxY6!5d&>sS&3wH$-`TQVM$4^GyB+aIq54tINmis9q(zfrzdmx^?AHVLI5;FNwarey z#W#3Q(syQT5v^I#lHHPOU=X5#U%H2h`F>JkC3b1gAPeTza$rbz4-A%3gDmUo$a+(IZ6u(| zuI|hLz!wF4Lqyc7KlFv4%;w|x}mT~Q_ z4Np6i+{ConQbiP0?*gthvJ_Dwo$-@ZSpIgMc7=VlI-8{Sf*i`=ruA7A1+M9@ASN#~ zZ`Ycy!69A9(AcnSH)sdXO-Me>?NW*S6d8RAjN#|Bs$U4U43hbO_v;hy&OIP;0NVYl zHnuAiFkQL2+dN(A=6xc8B$P?I)`}cSL@&w6jSXMxm#Z4dMWx_;TPi|2CCS|R*Ih>R zdz3B1Mkg7vh89VF%%1)R?~{^!iz%-sXdUCl4D*R&*WsjTo#{$tf!&vjmz z(TR<_ukSmcns@&|M{d;+^?n<_( z#gq|~aN8K0OMv(M^G#=pNsqCN$8yx4)it-etep&EHe1QDH4LR{R{Q-sW&^O<#xt>J zBM^xQbx?E1i8Nh0X)L30E-SdlFZ26SEoZ2?abV#LPqnF?OG26&&6yVElwf`6-=R+_ zR#_6{(vUIfbE6$HU^8H_OxFkh z&-ScAvp+adGmeqRkgD<7pTz8=?SHP}#or&oj#7sv#s`$Ky8T00|WyG~YKLUpop;y(j?Aa$uVC zig`of)(6K$l3o-NcA@+?Z%n?Ab>oVSv^>`Vs@>cT#6eJDJvr(TP?dmUb?Q=#g(wo@ zoF7u2X7u<5Czc`wWSKl7q_pJKG5l0kZ&vY-;xIZ7RdyDK_%aNDjJl} zj3s=>6h9_wa2-Dg-eQ3uhS8?F&)wzvZutF2K^bCS#dI}}0`he^C(VwOnX!ecCf&*s z0Zi=p%*D(4cH1cuD{-fLku^&%T0|T$07!-#_ixi56ZzPSrz?fUP0Y0U#Y+P=1AwBp}d`US2;zV7eo%5}?lw)S@K^@prg^~i z7(mnV6dY8dbI?CmA1oHsXjHRp(8CF9{_mlk258ICMf#7w-Eb2=7@C3cNs_hvGgVHJJ%XGd*~5;?P2dH+(q ziqC5`hlf}4gr{)j zE*&@ru&CPZ6XOo~Hv5`yMnP7Zq%_pg!9!yoFTOj<2D~xZwajm%oirgG2K&R{rsaC8 z_Gu0wsR(q)X>1U0LcBtSAEB9=e4Kc77sBPq*BLMQEJ))NNh|H@n4R50#nuSJXx;$3te^!s?j?&4L~ zBrJL2yFbPiZM>7M6K5m0rJm)PpL@NmmU`dy&Cuxf9mOtXT0{7@crR4tp-WWEk&4<1 zi=lEEKSPiP!%tLoYUU~Hp1$! zIoZW_!*e`RnU)RBgEaCdP`CkjlhIh}naKUR4oc*CB*Ss?{KdD4(#0A9OVf(!9Qz&b z3=@HU2Uv)80vv!akJvY>!W+`w*n(TuW1A}#APGfEBRapg$G4}RWd*zk36-W$fzm^d zRNe+AjQ$43*nSHY`&=5S(XK}RR@yYfRIG26UXWe5T4QJbrmM#Z@5>C#>9UGrVYXN6 zGPzm!oxe|gSWV2vhOrI6PQcR~#%{KtIb3uNZB~oZBCwgN2m!^F z4N8+5>#e=33aNH6kKSK^QEF;RO=o2>^6RWWg5~D84|h{6B_u9$fIAF@aGhs*-z@&+ z_Lac7OAmmUs`^T3ZrI4Q#!G^nJZr7Y8ly#7#qBI9p8)!$Nzgv+v*o!NWeG%r&LOrJ z)twc?6eH2=eRv*vP1*Q+zmt$JfVcOR%p?+1F2XR`6q?cZv5GTB=!wljy{YtB^= z0)N;zWIB9iI%BXn#XMICZdi(pwZpr58G>DdUXT>8mU3x;a!IRU3M%X6b6FvIUCY#0 zz>U&tH{v6E9wmHKW|LuztOxx0pJZ{MT)MN_{b|boi;^bOAFOa%u5fdCvU?P1{N5Kt z#xrR7O@D@Cs=cR&o2o>hY`UR$=(|ge%j_oJu|jgFiTi)N{x7e%Jvp)Ghug9yh4N$XR0AhAmA09H6Q36#tEFkNF3XjjV;$M6!{i{P8vf+0^&+fS(F zdL|_DS^spRnE#`gO-NS>`aD=(G8L8ClL$irklW z`dAHfnTb|_C>w1>Y0T$?yV+tJm2Mw|I3J+%Iyq}9e;4FFbZS2F<9H(3nrUh>2I2bt z@3-*zTZBZ@A4eVFCjrbozy)Y+$xT2ILsoWLsF5Le7oBR)31$tcu`J((S$>(6clRF$ znBFn?;=4a^9S;%>=`>R0UnA=iAJCjMHkUJwTqX|XI%cc|Iticgr$4>jFnVf#o-h)@ z|7%vtsfm>5nJ!Y)v<*5m1HK89R_3J|t1*M%&r8>vnUc`1(7w9Y>NncIA8Ro zO+jBd*e+*(UGbr%?!PHbt6A#jmT+^NG1;f?la+lz=4u_Kqaw>?8EXli9J04gf~(Vb zV6Z7dTC9%Lz3-NB%xt#*6z$j1VrhRLZoW#eF$K!WtdEYrvQGj7(jNRf|DHEg_S>+! zli;Yrg^jbuQ9Y>Dr4X79>~Y;FB8$FliCMsWu1bJ$0);cV$kKTo16GrWm3l*F!eMlzD-V`;shN zJKgRi8pl}sx7o$q$vD}p6LOi$QJ7S_G@N7}=36^}T>6w449aMp`zsPt(0zEp{Hy*8 zK)avmEq`y;=c(h|s+0T8d%jf=fk`B5otEr=J6fgg$CmA*9 z6>gM^LU=$Nj+J@J z=^|w5+*Kss=DLoM=hptO>}ZJ>dXf{>>MKSf_2>2NydwE&_OOp_uGLZ8aqp~sNA8iD zFrEPf2BnI%DySK1%Z&vaeQtDS^|7zy^UGeb(aBGH?17uoxzG^^-)a1q?_OL(eofLh zisq-BPpksu`eeP-#np0BBnQ3!thiO~rA|X*(_NVPJ)S2-QpDe8?nL(r=b|!EOdE0F zN*-`*TE$v`rzSb&Zbv1yh`*$t!kZyAAhlr_xuHhb;3KKR9ZY$+pE$tQL>8ZMTFmBT z1@ID*lerHX>wLj6T%dkVa;?dnN*nb~0-V%WMA0{dO1td#j`YKc_`9jWYP&=L65<<5sp#H=31Rea8B8`g4h)R z=*4PYVl?(iQP1_usIGX%pHUl=A|R1ZEP(8?lDjb1&G-s;Ivci1Be<7iqXF@_-tIWL z?`mgE(#F%2j$`^0OBb#CRbAP{O@One)<>{oA z^F6_eoOIcRN*kvlaf%Z6f22N&r@7*f-Jcnca@H3`dXqrWD8tA|+!gX@IbL|nIVC85 zdw-cz*r5R=*2j(VTzKpTnA37$jqN_GI_6y>Tf#@EEic_QGYyUkFstGh)GaRB&|%&t zMfO%8ub_5FY^v)=jN0L3;A{sZIAMb+YQS zdY-cB_coacohHUwn#@@>@)>4>^^LS&aIn(cvOm(sFv|50 z-_o8-2IS@gAdjD{RIT-w%<5BOhVH&Gt>F#cz+QJ8aT^~Cx89Vb3`ge_NsnHk7nvKz zp`y!|d`O+@n(>UZp&N!dy*3Vs7Q@kmW%M`Gn@ouw)3jgJr^RYZcDK~DEEi{G;_YG$ z&UZ9Lb?D8qdsJXW;llHDyFsSjq=1jr@U)?Ag{%LdQouo+`hCzu%M!HnE0>g|8jmVrdf~nioT#TxODW3Bs@Tavh`nqL*}R zeAvq!kd2M?CRGnxRN1sh}|XD%^u*L@GJdON`N& z7T&1)L#heV691zzawTLhZbc<3M#&!q3{`hi%g#=?@Cm?e2RaP6a!w zfIJ1T?zOHqF|dki4SZ^^t&@`+*p-3RxM==lfflE_u9q7-ntZ)u($B z`L02OxuUnBM>ge&xn;7JjYrc@fx`961q-@WDl~JE^P>mO^wK9Z?&!qk%WSpZ)XZ!G zTzPcTAE`%;nb>t?jhoZ9M=x+{Z6u|mUM^JCPfNzvF&|!B@4f*YYlTq?&K5p@K4&C@ zE=-*eFMxAZ{VaelpUT2X&}TiyC7})@S=qBI$-XyLTDy#OpVo=N-bI9y+}?vrtt4Z%l04;vBJ8jec|R#Fbof z?=IzeFp(gZLjGXY+vM_7^XyHSxvV{RTV&z3iS%U$gMBEdOk*>c zFbj*GnG~%PRBEborLgn9o9B>5dyrMMC@+=kjF_ocs$%b%z`Pdrv+7FWW@bx{J-lJf zQpJoT1}Oc#Yst9oO*mS~1T_krb2dY2TBw2+P1RV%ymC_Wq*vNtPL+?4rn1nZz7Nn` z>~)F4hazt!V{^aH#8kYngTaGxos89j(st9u&I68;B_HMm#FG0JLmu&EiKKf-s=1nt z2y3gF(TVTc+OXMvBfKfNYZotZi_<&hIl~%EE5;}JHM}`u(a>`4U4Kx^(2I%lpx@21 zi=*4-QH*`Eb&-3I-nXbaPpFDDsdgM&vM@*Z61H`R8;tr!xBK205t#1hzl%S6cbPqJ z%n9ZLzgPUFNGhg1-jBtEmL19jltc#qi zauRY2!^~r)yK0dQkCWKV<6@Yj4HqANilu8E9Ff4Q#x7boIoHY#L_M5D4IpowCnbGO zKpxB86{ACrXn&5l=rTdAuLUktOa|pDIzgjr3ZZ|V)Bk%+`$8dVFFIzd9tJxyQVUG; zf%*Tk=Bk1G1Uz#clqJk^B_cxTcX1rHw)TDN&6cqX3O|`Yjtx<xWtVd2hxpgMVfb!oXZ~EE=fVDlXAABsz;&`}+r07o;D0d&@0SkFbpLhl&s?ranJ3V=BXrL;F z?ZkM}dY0e*qu|$&EN6#_P5z30*f+B=FUv$|N5XPE5-R8^jU0VD-770fOzK`|Z8pS{ z{1Vx#nVIqz`ESgAYn`}F)8{mLDhkgRo%`-O{``P(*5*G7YVu3`Y(*(X zCj`t_dMvU4Z5asmSpS#Rpc-}al|$vEt{Fk%r=5_JxZHVsuRE0-S%C>pR;)0#rpEWo)Dw1YwjAWSM=Ox|gpM4B*^GVe_L&R^p|l;Si0gjp1K0Ph z^~;S9gw$B8pdME3h37e}HKZGLy$<$K45{V!23+kO$K4#GWBIOa)q5}hG***kerbSH zi`xrq`5E8~GLp75Yiu!6)*%+p>0d1{PFlPw-$ogHYHiDUu*Z_p*NCT{gWa!md-zX4 ziW3vYk6s+~lI%!~QTZIqp`2$U1!MVAZ?r>@SJvQ%1HbQx;Ad{6dCCG?Kn<{)Bzxdo zROm6=#);cWe>!%7EljO}MeQG`)fvMm%Jmx&w^p(kitt*?Ju2+=>680;@TMByWSbI@#REZp+_1D`Yo+-!R>sA{GbvV!i zC*PuX@U&BUqaenecWI{3Z{QzzFq>m>(MUqr(U$<})5XX#M`K_I$1cdl2jW`sk3v5~ zM=~n}8{i~dLn`h5M{Vc$Bcc*eL`lmeg@OpJJ$onF0CQoV>q++U;t7HSKiMdjuu6fm zbDg3KpjSldN>IU1REiEXjj+4-q$U$bYw!KU{qyBSXD2mrb|FF{+{b^g%r)MkiZZGT zxfDI;o3UdS9LDP8qQKkpZLtsg0(4eV@j%_hgJ7O^ekRBz{?=ldCi&#C zU(w~Sk>b(usmqIWy&2`{T2%qbYR{oEE{i+?=&ujZj!pboRkrf4 zl42?M;goXE{$nuu*sOi<=ra?vH6*6so^b7=x}-Uh%l38M7-x2avB(Smb1J1VW{6qZ z;sf5*t`yA)bUUzQxHDe!sS$E%*L(O}HVtk9M_%cT_|4kWAI%@xWOtXZ2r>7_14~}K#uPcO(;f!X6|D<4o zD#~?^V5zQna>ZFi?i#xUZI{<#mQO)ez=IK8aRar|qy83melNbY&QXQ`D4x|g$F1+G zrQdBcn&%VbR1xPeXf?-pMMo^oTbd16Yx%q3MmI2ovE!cCLweozc^njUe(7 zey*i|ToG!t9(69(q5bRc7PjxJOAgY^ba9F6J{7qmau0mxWAN><0*wIw8ncSt9u-Be z1EW;Gpo!1aPj+%nmHreU?$%cH4oT#jzt>x5sDW?tyKllbC*wb?E1nU4Rg*Y7EkEfH z+`CZTNcX8SbWz%4Uw2Ip_{C})Fm?H&OQt?_=n?(;sj;cjUrTMaDoZcxt?_id-2M}j zixrFPEBm<*Jyn#6ULb$}sqVafj@z?Rw?%lX6U?hK2RG~Bx22Rl8F+5LxYn2(qHX-+ zYH+DGIEf@kR%rrswxEy-^kAS85Y{LaD6?eOF>u4p92^}^?NwoG=(42@i1`} zXWje29>TQ{ThIeKI&;*P*)#JIhyx^lfUlu06WUYr?Pqd+jZH^~Qosl_fkZ>5zWn9= zAH~<5GN=Nc|7*P^f3H69Hf@#Nd-P(w)Xnum5*;7dk|M}$BbPNQ_VU0aPc+=i-%Q61 zM2lAHfe;evVhU4+ZhRJg;BX*&9RP|39v-Y9IH`k~{|2*7DbCbQNTGv7sLa1MX~_Jt z$HYZk&&DJwpJ}4x`kBm2#sr|FyX3>mM1)es)mVE&dJN(Q?uYAML;Hg*Nz+1fLY?}? zvUZ#PlYd^?tkb%yYsU)$o~AF#Tg{4}&U$Rz(+*0VVE;@Y(C@i~AWu4vgU>R)LmA}y zmHexmh|macS_#$kxbL{}^G%D&#J! z`SU?&XVs0%cIBHy817Nm{Q4ob&N*=lrsE@AI?R{!Stlm+XAQIKwUp?yAZ1-XX?33f z?w4p;ChQk--edf1K0NEpiLGXD{VXJ1(I zC{uJHeO0w1$@&oVE&ph~S3nig3VV#a>mbh&mKpi(G8Y75_RCRL}h4kpoV`1eGkFV??P#?sO;L4RnVD($fa8i zB(Nrcqd43z;7E6%4yeVN)X$W$M|DTwB`2l0Eo@kB4kp+g7dD~D;H3?Ym&jxq07M+KR`&vm_x)%$MN zJd5IF8N6fpYTb;SE=-|j@I#_b9vh)?^JVB1=kBpp(lY05VyW)eXN^sNu%ZN;F)k}~ zezLhmKwKAO0QHgm8}5AW=U{+H!HwSG=n>X3Db|(v%>%~QYKau9V$U92jrelj3YK#O1sFIUyxqwg7>b~b;d-90K*x(HtIQF2)x z8d*(PsOp;_CbN<%==*|__$qSi%4^hO-zf$Ro##YiavF~FXKOFhv`nrhB>IqU>xwNu z=2Myy*WB*ofbi#&kZ()%o8N#K1xVf?fre8(!`LSxt?ENEo7;zh+eTLM{1pKe1ZhW` zv=t~!O}J@~@CH3PF8gak(OX(hNU`Lpyw7akLOfTtp(6ke@X^uK5$SE97EIVhlbBe% z{rQsR^MptSTx~Zo!3gn|#-9Nn=N zeZLQzM`*IdodG|NXVA9O?W^0DP0DO!&CEVIX<#LAb?cw<2P0>8ejN#}pYQ$h;lUqs z{E$BC|JJ^o8TeOpcsXq;sTBZ7Z0 z0bGu}xBFi8w)7Iw}gPx;0`4YTaCi>o8J6fd-to?_sa zm6sIVPRziEdPHWxbvw4#Rg@p8L)zF?!5kp|vx$zcZITtK+y#ZgLCAkaKp_d znT`L!8A{@a>0Rf`VqQIyr3Fl7J59&Aht&@>kIc!xGaAD;6MugyVRx1np0Qo@<3A*q zs`z2m$1i5n!=bDtM6`M16hb9`TXxPk<(A&!DE(Nvf_r{g5+~{IE$g9S=)gj{v-bxy0uk>{#g=L7 z96Y+yYB~+AXn~}uTPbWbA4G$$Ndu~Ypa z$*$(~9#ICTPb!gnXWN-yx30hEo1c{Ew?5C`nd2dp#HLn_bL%YjLF10yXlhmUn+$!+ zq4+U(m%j-_KGwS6>4_Ghadcs}q{_k?r@+B=+v>+9;3mqgBr6Sk-LhK|NriX;eqbDE z9)mOlDVtmF-39l(Og9{OeA;hznoH!f%S|G^bxqAMJXuKANsLJlhW0$Z_S3q}0>={~ zB>wiq7FRQ&Vdf-xn)0H-v`kKLfAqZ^3E zwe?rS8*6+udsC}Wc@&M7cT?UW8LgkLiEVQjr#ISLqJ7T;)n9~-ugwieV%GhpjUwz} z4snKQigiNToS}Ws-CQQx9Rg+G@OEs25q3sd)ehy6OzVGuLTos0#EVtNmLUZ9-yvCW zJU6XA%>^EUdJpmkJwB8igX4`slAnrgIw_7V;Khqs3e}$s)awQIP@(9PlHij_&P8gC zBJ^b`L!!vKD|E>$v9EEr+i!#nl7_YmCj{C`DDI)JyxwMUucI4^BVL2&AsKC_&m4ya zJeNcchzuOBCMvWqZ46+Ci@Cfrr#<(~`;WDRj;_axZx6qr2$mj!?Oj`rQK^f9nyw72 zH3b#NmA+`xKIz&YYoA24U)>3>uy6{g<%~*O+%`9Wzxk7$0_3Z`dAQG?*aolq3NRmt ze7d0_&U6b`Xw$Sgg9+)FzZvQ8Yp3(kY%x!|e`GygqkZ1rD4uy*?JqYSS)by#-1Cu* z*D<$3u-I(-U4El6BTNi7()N^6^smb!D`LY+5S@`F*QUkf%1l1GailWQLS{eGNuH}+ z0?;ROpUuUD*oVaC$P$BA=~%6Htk@4vdlJArXML-@mLx+X&;DeY8f|ic$NXG$@GRq^ zJaG&^^&TIbIrYlUp-i~6RY60lKjZb;L@VG=JtB5Da zv3?uu!-b9^L6YQ~mqk$Pa;QZ8RmWlYW|RmEWA8-L$NHoeiN@WwTm9D^sEQ!Kn#S@U zm3sa--ERn4x}LE+{xKR6OYh=wTF<~gB2e;LLUvy(1P3;SZoku@$f2lwQy>rTh5c<` zNjgxb?wd63H^_TM_9;0QHF+^wboC~Z&2Yz;Ui7t>Y8d@AC z)V6W0VA@e*)Zu0FZ?oTcy)D-}TgDx}yj^j6i8~T5jXhlYl;iH$G$; zd+rxx9!WQw$g~|?-qITg&9`n!eMDaU(p0IsaT9%cKyWOuM^*l_hdy)sMfZDYUs^mP z-;TA^^dWTSfy~SbEQG-$`;H7Ne6JsQtQWK&Y*)B{4SprS+~&&oi^{#?ID|n=HUln$ zZQs)?x2`!3snZ-{Xd|ruy4APWt{^O3_+jDPEKS=Dl$Mt)ew5VsnYn8p++tP`ciYOT zW<87gEuebqTBeZV+$n5h?Q$L9;!GjhMcsv8XC(NIG=FAPWi_CJoCWVW_{X?r zx-NCKXhAFVF*-caNZ7hjsciDOjHjE}W?~`9qG7g81Zp!2^`preRBFqj`q2`# z&tbXvj@#Gw_)P8jh__0^qg^C!i8-Y6xgvFye_-cD;qL;cvqYhbgcLU4!@kLz;K>@R zdpCK!b|qZ)feDMA)768_H{eC5yyxE#jjL)jfw?H!hj~mK7KdfoLk>9Iy>onecg};$ zY6R!Xd|`Xj6#2o87Oaymp%B9RZrP54`iX$#mrr%xOCxkBYQoiFZhsX@z4L+)3JCEJ z9aEhA-k(=Hr-j%V#qnTUH64^5!B|7?T-06N?j=1W=2~5rE9&9}SNXqIo#eZO5WnmC z+)CKHR&f6A+PJ`;a+48Nl`;&l0X)0Rwk0MV@|)Bj&W5!ZK}5`Xs~dE#KK-;^cDT+s zSov+kV8v1LQP}s?vAoj+dUc%cS6>+6STQE3un!=e`efvYY4p$eO%+)Qt{f0~Rp$ul zdwBdyy|Sa%<1)R1!)|4{SxHG4p9_G4Uh_5qN3Akn)!iHtC)KL2IVb!l?dF$LT@*8P z?q3tzq<&p6yowJv5^pFCey$sYmRvO|T2;C0e4(6P#*<(dBEzw`a|R!(R$}s$+v;^E zy(xGvT<+s3vpUvz^>{n!KMH${nMi?ygO_(4eSIxg&`SLtMoo7Fok@4z4y!|tqnjk%|1@pF(-*|k-_kSFnhd*2Y+s3u3sG_R&tWlfVv(i?rs;a$dYYSrUQEly2RBWnN z?VT7AYHzJAu}9Ph5yS}jKKVWWKu%ugb#n5#@9TPBSDnMqnm@aLooVaMrV~)OCJ1_v zj(@ssSx|t)K15NTvx0zrvR&BlI&4~ zBae>HcCQW>*yYFS&U0Y<8<_{wYk)+$W>rB9A#;N&0#*^^nkHPYNQAsOs){LNjVf1O z|GR=SjAItVWj{*#W@s%|nTK8d3#X+;s%>Pz$5$DyjYfVkn9B;Woq7;60#r|MeHVq_ zTQfIo6FK!dI$N~u{Fo0Z`@?7IuIWS8stZrv!o<<%&}Z@P*Xn%#>s0xyk8I6dFZ^1f zo>)8Epf#%jSR9C8J$Kn*_QTOmt;R0$&Y1yv1UA$M(SFAdH{E+fpU>BNn9DUi>usvM zV&n)s+ts%UpSPuZ97S?G(Bj33M)GI1*L{FalS1ocuY!(saJ(1Rpbe@7Wl#)(p~0LP zX7HObs+c@-I{6vJV2ih@Z39=Ymb?BDjH_r8=X-;~8>zebz_MmIGxn$Zr@n)RJdKV4 zF(6O{aF-qn#AROm-UKCZK603cnO3?&+D$mb4#gAeE69%y?4Sz%TR!JiOvIeAfg0Mr z@rQFGcmqf@uqy2MMUW^^=CjdnholS&E_v#CzcAvmjLiAs1Ll0au1Cw`TC8|Cm@ml_ z9KvIgS|U0q@tf~D5{@IG8kEHf9IS589@xer^fTa-_XG3+1qVzX929m-k-IbVosmhq z*1Q;1#R*Is*!kE@DSU!jOf+-5XeHvewrm1%ALWMDuX9}W1AcH!6&YgSwS7!6pnTi1 z;zGLiU=1bW?)U_s+nbK>y%1~P1Q=?ZX-JIs*r#KtWY6zb|)s(3-4*W zs9o$c-bh)9nq9$2lCLf?_59(4)u$y>_kWW*5EznDuQJpb^D7>; z`7X7YEn+3C5d5A-FK1A!dyB4nvnDXJ7a5DRfk?I=LNjc~K^aD$l^72s5uKBSdz8nF z2(AP;L(agC&P>Vlsg9{_(>N|gEbB-avaKml=9Ao62~h9Gu}u+y2sDm52dP8sMNti*+oV|9Bu+Dpc?MtB@liuhTzM2brs zY}IA#I z(TLxcUCwcEk?_A$flfN^j1l);yew^QeiCiQ_VD(nA4-A-$DWgukV3b2Z9<)m%#wpN zix$zv%;p7l_@@_}eE?e6t8-TW3i0m~r9YjEkWYNRK)K`qnYO_=5hC`pamV#oJ_)8# ziOk42%AZ#}CGI*Z0hrhSkwhyo_0=T>&|Q4)Sv9U_Gyp+clQm3ip00oY{DV_r-?o%h z;(!*@;yaTHqc4$ZdK>{>7B>_P#4o;=JhBSC*5=_6di@vCH9_7pjUpB=(6X5cq#2@S9iyla&kn1x6wUr4jja z3Fp$0EuXS7*z%i8kolRyZVoYy0pWvl!ASG~Zov>-(P;FUb!i6L%WH?}5)ha0srVZ? z$l_phUwwnS#$7LaQ{n;99-(WK#4ayd%9!5l>yK6Sgr}CJ3KYmDYfcbTDs7)~BjjXk z#g*v`fOcw8r-284mN!o}EvDx5l|=^Zqjz~!Qe^M7e+ryfPwUiEiz>S`ImitN1Iu5+ z;*vTb6P^#>N*2IdPUX9~;tR-TRoV6n=#NXpICFmqCxk52jMwyhdy{NDgJuiasql!A zy}B#sQ?A`wHg5z4Bzo3Iy-kJ-t@JC-V7GM3Rr1G3 zF@;s^bzfv+fs}eEF<=MxYaP67&Z^<09l)k2PRcGwdKlXFyFZNVSbozq@|p<`*tem^ zyeZ&5X84aJPVS~yf2K$yS!eMX~*Rly$3i^YbbObz0@kA8Gh ziURg9!3DIPAFab@Rv*-|d}uwMkC$L_oP9ORx$a5CuvN2piHn~IBJ)JGyCQxORqA|| zQEkfVHpYmh_>bgo=DWBD9i$!GzaPKYEtoxvy@?|*?t&XKFg7vXjog`jbKu;Wu2<$C z2X3cCRMcf{2w^u&rT#@|1}YDjI~rz;L`xCJ<%}cyD=}Gs(jifx?utc}CeAew<>i-1 ztL+u?*)mG7N>a6_-ZZ9C2md+{JLp5p7ML@q(Q~M?69v~#bO7FEooz1sHaxh`d%3L)OefmT0gx!l**JoVK0)5m5nl7R48!jbF^dYXap5uhyS0Sge zZEJ;y@{K1k8&yH;#{->SP`V)6&~rM-=9v4VPR*9EUD|_?wb(q z3G`rbZ5>aXlQg^5AHX4neVIz7GbT!Jp#jnnuIBw-EYXkCkmM54+z&KGBK!4@r*S@i z2`Ul4jamvRTv_{XS{f0*IcEEqa#7|V>uKiJ647kYEU}X-1GKXHwve6Q|B-O$;z6Ne z$A!@_k%)~DHo5rOuEup~U9QEF75y55KJzH_h$_fwdz7@_vx{Cu;Mj1D>-v!te&7nw zbMzpv=XVa9ua0uyX-7y|&Lk=&^u?FPCTR9!0e&;d)6>T?2gsQo{q1KlYZ2FUM5%}T z7?N2#zA?$_YRYPbQ8usX?;KC+6^+ax*GyDQ{Pk|>OLT2I?(>B_#uV3goPmlAx`~lb zwtLq!>EwIm(FV+`REIb$m;z6KbNQxNpswYKM-dVtgupjfU$|Ik1E1bny$v(*R<7`A z(L~7o!p=mDz76mbTWOU@il8O%hmUnZ&W`$tFM>caIJdJ!OJyGpqThK6UVpFkN~)Ze zX}rnpi-2U~;nq$zG$Lphdqc7rE_Y3SL8OxI)E=8;ZUD#w)B9NGzt;LOf5dYf%rl8l zzG!)$^@Lk8^uj#cu;2@~NyPP|F9y(y@nhvRw~4C~RnEDCS?-gwSLwqi_ECpvk13=- zb@jUy9b0rY$Mi=eaX|}WN-o6b*C9~Mk#;K#uUZ^bJ%o!3+m4j@{@9I#Atk%j z{<`Xf#&sTDN-Snu)q!0|lShVYghm`8GdZ=n4)Qm?S8zEfv{H3asm*R}%?un1r7YA%m0Zjf7T8YuMx^7p>3 zXxD~q1KP||7b@s(OQY)e4wdVHdxf7=xsSQ}Xk+Ap3zJj;648FPE2Z->8!)^Pq>Ss* zepG?`ke7ul^73tPWWQ-P+(jFp=IRdc6XBwb_{}7S>|5o8i#|J>!65msY;0-t5fmx5L2LMTfA0y@mkjSi?+@gqmIlI6fo|?mk*%j%7dG=&3ca(9IC+)`mH(% zBr$JS2-t5=z9Kb(2+xR2i zB*d>>tNX5D+T8zU=CkM(MLxDfpy;jd7{HtpDSoD%2w+)k&&R8WXQcl_`nNuLs-@3;SpMhBn~uFQ_mveQ=hWlCooBpg~eFQa4HBXVWTQ zaJ7HQ2J_>%?`&~A!jtVDa8&0(0nEkV7g8IkQ>dK3UTRUp@3Pj4|K8De52=peYvb4AdvvCPi znSK@$JK{}LAmRjlDKuv>5+@Ik$%i!5zVN3|3{Cbrhy3q$_z#5G&6MT`paW1Q$9nS0 zewX&J2>dL;gWOagYIX26wyop>EkJ|;08Oqr#_&vXoO);9m3v8?>-6^o#&fye31^eV zg-fi^hnAQ!xzHd?$^d`~##?ql)U&bwkr+*D{1|osZ2=|6tos<}_A+mo^`=M`sGWy9 z?vH!x`WU_SV}NBZvUqFERLJwS*TFX7O5wx%n1O+v{&woE`o({-PA*Oj;DOyww^syf zJj5Pji4ANz(htHN9o^`y0bk(!d#Xw|+1Fln8*KaIYPx?p6>5&eMF(ow6F`r=TiU=R z>`0k@%^Yony!{sIDB;gV%Z45aGEfZmtdXJpiw>7v)`FE->G$W&K!%C;cxf#onM)G% z2Si7WJkA7$;X0V#puVH+-h zp)~q#)z%DsWv54}l;&N^qQTxFJ9FH%2*CM4E`~V-MFZRs@XITz-vs&&%xd(3`*N+QBeW@g&aw5Yh)iahFum8NvaT(58;??3f-Q@7^gM4a<7vC?(2qBXdP$4SxJGPAc zJS4aP+1hWMHXu7!%YrF&$Lziwu(~$qTZorkB<4jM7^N&6`q*_hUcK zJfss8EEbm6WSm+`4DH;lUxBGwaXRH8*<2Armd-D*KjJ_9DSUf#Y(sgkpP3#*&23n!5DQNIx6RM~PVFF_k{kZQIB}0e@V0rD{ zBw;dBE!#j_3|*FH`#3-w$Mmg|(v~cGz>3qJ+#}$&2DJ$+nxKGNCI&yaGon>6tuCx~ z=`7$SJ7*gz-;tZW>|3RNyh|1>rR@@V9fm_K??+LJEmwg zp<@B^1yc*lBA`I9=mR_M&Ci1c%Z;N|6=zh6rJt2?pr)Z=k)QzFC3pX$ASx8a;F!<9 zW!IIM8ov7j6x(U;D~9U8KnBmabCtMg4YT@@JSUJWHxrhs)TOK`<6JOyRIK(C$pzRi zV#kJ`_%7=YM+AX~4(8QLA+EYP0M9uJId2mG#AwkA_m}~Kn)m%R8=bR4te z0)Udji`#%FR^oq_Ut_|pa(*zqi$-n8OIxaku?d&wdQoJ{^-xlx`lNd~%b(=i)w;(F zC5ek0Gn-E`5Oo!}{CE4%r#6fGCqfJ!lMZ?Qf2``#kY9Ch(IH&QEx4*=v!8+;ckF?O(0Q+8jf4aX)V1D$f-MN7J7()|l;Cin*60pqYkSKI+7@ zq}u1ae5FBb27hj&tw?zM2G-*KL}%Dvhdn&x)xKEW;<9DLw^Z_!t%1#6PA%lwFSKKr znnz!2_IZ=#O-6B>b{2KQ1I=5<-}>yh`qM2u_tFEM-h==hpkN(fP4(P~w%bY2`{+-D zJZMSq@{qFL=!D?yNfYOeR5iM7G;;QDoG{7YIya%$2%p8jacgwLW{YPA zKbcMJ7iS|&@CGRPb>@NhAdPAa9U^!18i#RCsrvFVjsgZHPKkB47CdC`rh2U@diKuz zX)E%{{NN2b-$owl1Jb^LT3QVS#a$zN{V*v$9WOt*W00r`HmoYhl-nxOiZE?zG^YKya^R?ftcNXGfm&uo8^L*|FN z7{mDjlK}``W4A!gErwya3sEx`=1t+{w<3SKw~v_Q z?@TpzuBP^8*%d{_sAOEH)Ob8@g+ZNwT+NlQc`|B6r>^8EGkuo|rO+G~gXJxs=R zu?}HrK0DO_c6lOqSs6Z)6E@frCNjtxof0^ww3B_ie>-72`AFj4bH~Kn#X_l1q@y>V zv{yNte6qlUuH@&|x!JIw-Ypy`crxiE&Ujr_P)5Y2X!ljIg|^{d&qE z6QAQSlf>KDINIdX!|RB}gA%5jIN=#sng+bFb>Q?SDz;q=2fJe3)88EimRtsBX7T9O zFfDq#97eI|iG9<;m*hF^7P1A#53bvOS%=SVnWrI+-MEHY2@@_QZXX3{r2aUmK$}tQtYMBh6 zut57o-&Nk4s-VOY_}|!ak{wX}W&i^gfab@W+Xim-=lBxn+PnT97&HFehPB{{dHb~j z3%?qBtTZ7{yI{|toWT96X9oKgQ`7I3ak17qO-=l#;TAuP-VFsf!GmuOgXaSC?*G$} zs=&3gu1m89=A=c*V$P1d56;10d2LY%hFrcHY%SiTl_J;pX}DGT(l502_!0F2pv;fEcWZUlL!xbxC>dH}RnbgKuX3;qB+`Jtpfa-H*@_2i9vQ1H3rn0?q z#$QLVX4>zM<0fsx$xLT?E#vYNg?P#=o`4k@%x?O1k9|RErY6p)RC|gk;rcH?xAvqA z`opv3{N<}ZWD(-el;3?7U9k|k9$SPs3Q8w;XbTkmbG5Xzbaa8wR5vP96iy}%tSYX& z2y8eBIo7^E2I+D#GD`CA8-4V<&8{=uzHKXnHFPSdp$E6$HG$u!XLDil>SlJUc(24t z?gbK88GpQ!x(y7H=czhqLolOBxsUG9+&r&@Tz!IOmsoCF27RmT%MDms3r&k)3=_5v zc^A)8c0ZNR8J~%!yA&Xu=J`1{q|eb-ef@Tp$_#62mfk4Bk8V<1|X-p0uIm zkRO!`)3*DCE(Gi0yf{g*EAhDAXVBF?6FhgKc^3suQ{ zBnA`QKe--D7cJqH&ukrpepc9z-vX?atwJMG2qf3eDZRF|#Iq<{NFdql)bFzIu%u|s zOeK!Ja;~Sm_tb<2U+-NdZX2d4U1qhXZmTZkTFgr1^jugj*5q|{g70KmT`Iq@PG%=x zVr|))$u?mNu|0KB(6p5vUArFdv|lTHja^-YZZZ}h<8fYpuPr7;maHuYT^sjII!v@v z0by9NPH*S<&cSm-UrKe85 zJ;Rt11D%iwoAcK)(Q#`WI=!4MO*7&iP*)sd5^ra<+P12{qw^-R&HvUpTtB@a{16Vc zmd)UFE(&a*hc)E-efzc4*LYnnP_&yfQ7TVf6T{@)7jnIw{0ym|!EgNS&C?%E4wk8C zz4ot`O=RuP7V66#UNK&Fc?=#j&DP&umXs{Wi-ynxFNrQT+V+mv%izqZ%WEeuJc@Cf#;lfU@|k@!7IEQ_f=T;IT!J%wh4Yr$r{prbp8&U?V}PWTBQ zWToTvVc@xV_}=Fssk_SaxA2BR5twoiGt$aR)T3rwgnvxx4#3-Nm0+G0;$z(wf$w|v zmVNLB5uSK4{9V&;YgzM=KQh%`#Orf9*bgk0=W@d-hH>ee6`NsHcyxgc7sH)%4C&9*~o($ z+m|%x-9qlyv}_JAC0nY@BlHpD{Ou}K?YfZxT0I+p+3Y;shE54KV&xN+d z*G^4~Wj%(1S!7EV8e5|Lo%TC*9dh@bTrSYbX=}+GN&FA)083NVu4W}BQ;b`*pYYk+ ziXjxt#E&GO=oY7uAKR%mgP|{V{H+fXT6u$XJ5b^MmJp?!%c{jfTb9@2$A3;4qtzM>Ey@lilxo&oA3*HwpJ%ROnWPhIcs?hCHk3=y;8UfMf6WTydQY zh;*N>3QzX2T0LweLf`c_i}Et>Ung~QXfqr}VDvi}V>bP^_OLhkVr#2Ou_LUKJq6km z3JTXEyB|AGwk|uTXi4k(xR6MjKc~t%NcnyqES^Uyf+y7spLAC~s66m+qK{Ey*`u|O-C@NWkfd+lq zY7~0Wq_4@*RSp%fG&wpNpzphE2$S+PRC!Y`=4u>O`cuY)@!aI< z7+N3oCfk(pI0@Nk*1(tE))^Hvk~gbrmVcbt*dhFUc=?!KRZ?b&r&P zzjoN~Z?skXN3vCoB`Qvze_YId=*t1bZ2Fv#e?dPOPM>_YaCLlI1GrC=Ppt@ifgU)N zPMAbbV|AAtzREP9d(FG1fEb>$(lP!2*UG5W8tmtM+?r%|h^-a-i=iPO`I8JEWS9yS zBYwI);n5p_ILz?0v-ZC(-d*14M#`VSo8DI_a z9|_}K)aUtLxuY)c5)+TT1?GhS!1AO3vuX?rgKWw*z(!&6%O{muqS_= zPD}wJ+$NiVWjE8R@`1@%PF`L-{d&!*@UpmU?!^Iab57ihaJQ+;Nn&C1#Z5kuR6JOw z(J5=ueudQ$t)89~R~q_{Wbi5WGjnXbPa!cU4Eh{@Cg^(L!Bp4n38L&Mi$+D-xxm2Hjy1BI^EocDKEj{$y=J}{Z zX(%tIX^@NatnjV{B2?u9=ntpMI)s?{8E#E5f8+AFxES8bOHH>eCKf0g0%hB8QbKhf zx5h6PYeAYS942$fv9hQxjCMYQ@9N^}3q5fYZP?DuX4t_aHdxy&)Fs*LLSrs z>c)t8!CmgzYaMyWwMSULv4F;eOb%zyH48rBRqK z_$>-?`}=Pf3Pl0Y7s%+dldfBu>tRkf^(&LR8w@oynYU;;FkIr%VBw3)`)Pl+p<7N`i|D%uAwG*<7tc0Q zXnSSPV?cmrvdY6&o&6-j2fds(T7B=+23;6-*IhrXbNZ&8YL4!(tbnqHtHYm^I^A53 z*ycJMUGNt64~Obva^_#9yGq13q|MGciZ9$@;7jxN+@E|ML!eTW0W5@5x}X+=p}9Zt z`0q}NRMY7LdU~aSrq}d!>V-Jln?@CTv{LnL;9d z+lv>?z_`|^vOWB@=I@ zwcz_r1Z8_6#(&~M6zNYj@G8|czYdq1-Fu2A^t#@dPDL~&jsr0}x?m&3B=F()e}BJy zG9B;2Sd4p*g>qm{=`F3a{cei!ar)L^S?AS2h0Qz(+n&~nky)DfKcVfMXgvQg2ejwr z!R6Q_PS70w5#PW(Jj{1u^QVc0;q?u%OXcSK>4_a?QjN`D6DODVgoFfm56qO4gxAf*%1BpR=Uc$);}k~TmiZ%|7@ zBgH7fe%RhiReKZnQNlQ1x88Eo4r;mMC`@SYce_$$Rp`uwceh8e=LxO*>QvT4QP=VF zu7nF0q{hLQ4%9D#^&agC0WH2N;E9A@zBAx+^H?%P;cIU8-r9jOw->b<@)svpern-{ z^H)XW$Dh9fivQaJtb)#S;{Df%v9UYBf`V6caL@&{WLJ!g$MWR43l%lYRHcJW!;~z= z`v%>$QYLk{JI$`)3oecon`biTzXRh51X5EH(c>$%yp?fBbuRLKUAQ?MWb zN{pYISFq7P@khJ*&pHk*w?!P~*r&;7b&0R8FF$`UET8#5kG$j06yLbQ_SK$oJr_AB zKoNOud_U)_+_&Zv$k1#={3nKQS{-Z`mCb*mtExXr=2F|aAQg+ddk*80%! zb}zf{CbvC=Ty~zF!<5sHgT^(ZDBNVS$wV$ZBIah#8(9^KQpmm8u9Lo4#G4W$xAb~) zCzepG?KGgTJ1A=x$8l8;?BYQDNZSGw{?&Cz_ zaDEMhu37t!B&CpEMSTrTkH+q;Fu6mq%`P}cj$3iP9Gj}ENxHeFv6t;yM1n=($$F7F z{gFFD?s%%m(yYiCAvnvRdN_+TSh3Qm9J6%&d5we{+g9w_kR1aF_dZ~n*6IeSXk*%I zi-RII++Ul0jGxy@LF-a}L)*%eZ;J-gbV=nDSfrUmZx4c%q*wVa&EKwe>W_0TpGT}2 zyJ<7@CrS%TRsSVNtOofk;N#22m_DsaoC5`$=c0@4LCr*Gw2KQE^7Gl)s^3n&?Yowg}Qsv4t?2HH=%B(wcED}(SDRBhqA5%JGj*z;C`>g9}t8sYl}Aa zB+rMsZ^P#WGcf-yt9{+y zHMDD_^2c=r7Akw(Z0;--NUCq8xxV>3a#1qXs40XZz5ZmZtgmKjqFlKzZ{!Z z+ZI)|hMwoY3U{(8uN9e#>*WD74c^_b^pRhtiZxX&M_$f!IRzs9mpj5i?W&+YqD3%$ z+c9Rx;r-YMyr8sguv9Uh*Bu`^=!mZ!(3pIIBzZUXVJ6#AjEAVyRE2h&NIPNHXs5Cs z^-2pvS4XAghlg<-#1NNVVJQy+<2PZ*v&=k$%1hTFrqQIBm34-u$btNzLWS6ol(0G~iqjkJl!(~7Rm-S%F3wl1$spmCbJP?$JZMnB)3-y*%bO?}D`R3cKA@);%#f=s$+c63DYXfTA z*7!uI2hS;aT9-D#Pc-`RBDy0eqW1vJn!QVMN0}&F>4NftABN$7QV-R$Q(G?|zF57< zM8A`2#s`$#t2hyXIoK9zkUwg4RG(P1#8;2-nOwKkaUVU0JDaA?@tL}Jv?aCfqHSdH zUY5h9q5L6>>F67KY{ByE(=4w2V(wpL7sIH|{1PV1k6cn-=X}b6`&g(e(Xxk3TdM0d zS0Pd>YOPqQCW@QB^Z8Na>u#%;sr{&)*t&Kq%bx{aYhLu83hbLTMh)-r4sCw;Hw(UC zvympyKNGV_s^pG_)2cT^kcM96Q6BGup`L9vl3OVoB%EEP;pM|^7k?k61&tBMxoWX< zeMqh&Q4}xr?y>;u6oJZX|9Oa~X;3tdx~2=%4UGhR8K5ke$nb*5wmCqI5g7CFt)XuA zJkd60@*19AT156wW9PpCB1)ajiF(#09IyaD>8ou2b3NS~uq8o!C4>F`JiytIp1*@H z7MZ-+_w~Ue0fqla&Tb~4QEvKn&c&}Lc2Yv6o*vu{RH%#jkHo=@^JLRF5^P&Ik~w0U zB>wQDMnB>&_J@-fpgb6#;np`N@&Ip0EL&-G@O@wWv+DhqrOlJN&l{FE4#8Yyp4Fza z`S|Q6Yq=kbso{>7<_(15 z;@az-aF21*wv1bVhx2#`Qdmtg)Sc$SFZ zlCZh^da_&H;Ud9piKQ5~+poKi(+7|Jevpgs$-gG8 z7DhK%LlGTz$u-!W)6$&z;S>6>>i99ao61$7b~AmXsMQ%k;?Iox{X&;$uIyRQj)!Yn ziI05g0Ngi1O?(NQ7RqMJxg!W7C@AkOx9RA$+DT&7(2@xh$Yg7*i1XLT)L)-?eOJL# z0k`cMHJ9%G z$JFXz>im5XPXFm^-SFuoXGT$2G1A(_WByyq;L?}#^Ll+VBe-E znn(eG>%Aq1-j201+x*H01o9Ae)5LIH0V(a*_5}0Nzo8BvHYD!uwr?>)_d%8B>V6hrc+3#V=CfY0-rK|Zdf*^68?G9zRu&t7d<0Ufd{sBD0b-uCoA%P3z zE)#spWAHVDQa=j#Q36%W8ddt98I3;Tt7a;BkR4swnK)Kmla^ zkT=`dxYR^vX!9&lyYf>*gR!$c#{`uY01k}u4vozhbYu~YNFWla#M zW6S06aY#Tq$CoFMDg-Ll{K~B~Rp!}>bP|3k7=K=l+DV79JpT$(R5=Co`RKc}`o9Ba#xH*^A_g*`a$L{V%VCt;^f~xHD_#!x0kebr#eZ^xUDCO z9?(07f7b+w_2>72N2au)2Lz*sVU;TY$-$uyt(Oq=GoMdNG?H(Pfh=GnJ+YDzcd(+^ zmWkb`+!+Rd;GSxRvPMq97Dbgi>*3AS>(H8pY$urlJaxNX_e`p$sbE<{G%4=H-KD~Cvy7C!!KlPMa19wB!;ls%incujpnFx zOMH)L)C`4N@N5McY#(=g?iF}8;M%^6+1&@-A$DwMB0Y$q+g==lV*y!X2DiU@FTU6A z_2a00;zzOBBCp>x8sy~#-07!(p(5$Zcw80Q2O`mWbUMsOipYLa=&@p(={u(sHNgF< zF>9EkD{Ipk>%qk4HCd+QU&S)40%X-#?u(i8wi>1 z4i-gpqQ~AXAj@zr2h;DMi9!#mnO~sZr_bE>>d2cN$Sb?FYb%5pZETB}{hh6eXu8(s z+t?6cp3TnqapJr9_&*Y`HVdeAB-s8qzm=h-A~4*{_pAeMi7#pL0^tUs+F;o@QpuAd z(sMVx6~M9wSt!0T;`d9K0Ej(x7s6C^Kj7|g_@LCA@%wa+@7z7=O`h;a2LXhyk&(59 z8$?9I0b|(1YEmTjwMnx&tl;x~y z&$PGtX@6aVuiM!o>?>~y(Tw=wCL}Na)ujgk__;2V&hE2z_fji|NTFq9g^u5LwMhdy ztcqUSZLijo2g`3om;5!EoVl`q?0D^>2s5a6%->%#kP8gDJ?VPYlDswEd->ww#)8V{ zr(J!IJ~4T@IdKBl3X!*0H=rpJGDux|tF(!JRGfq;g4$q?A>~}VMeAXZI8sYN>?8zJ zu@2N8wp{lQFY_7Hk59~l^ZN$B?uO(vXKH`=;L!zhaRATko=ZmE;z{wfvrp)_$mI&s zI-gD%ho}1%I_Dr{ljU5{1{)N{fZ%^D8t8Ji##QutN0{=UEd&}xpx>KkbwhM_X(U9G?;}=QQC_(?$$(DG37Zl9 z$DeU4k@+j4RYINMBbR8BN(pRoBc9za)Jm z^i-7R-cxP9PfN7gEp?|ga@&ihXdxkcB=7Et_-4z4>f#UYy841~3=TC~zz5;={&@-lwXv&7mJ>~Gwd0MqUEzKWw zL1a~Gvdf)yi2N@>jSGYK3#_#3X_feYTb&B1$iJ@hgfjW7TE0X?HEKV4*mv9?+Hi2Q z%R(AxgN$1{?bqZ;FzXp*S~PG!Ml`8RS-|h29y30FS0^l05|UFV+cEAtcV6Et#*<(g zvIZilrhEp$PQ=M;N2BH;J$vvx-4&bM#_ zO4jXZs|N?F;o9=jRKd?jG+KSAR7l>~~u*<7*LCkB;-Cq`j^tdl4ri_KVF*Dx^ z#(Gwz8*+2E*tcevB)d4anccTBV!Bm)xmv6)jI)WU|0k?)UDnc`Llxv+vJ^V!2=3W< z-jQmzLx<+bN+~smrRj_+2hBRTkBfE~+rgqtRSh)mQLk%ArxIJxew|UtBl%4JjPjIJ z7pP}+XWLUq84iE1lEl63d=+~lty zuThYf58KB0MxX(f{j>F-EfC2j%QM_@j;Q;S=oedq+gS^ijeIHP!{EzoN>I8pd0j-7 zV`;%Wnl-qoq_zuYY`%{8)07t!?)FTxIJ|lLhoOk3Oiqb1ow(T6o1dbF)Y(2gD)jf? zOQ;df83ORnU9O_~poW%+=A;fE4L26g(C>-$mrtd!>GRtgRf83J5xm))d;37*OqX!F zE?4Pv^Pc3SKyQVmGEJ_$tU25$zN<5dg{M`+oZ;@;efrOm`9IMAGY3Q;I(t}~Hxccb zQelnb4s;%^E%Y8nZ@#ZSn2`4Y?;OzxHB`@=c$KzHTlH*?ETc4it6IU%EVk$IB%1;F z)^aMp2H2~N8vTq67IT|^gefQR2jVsf`7sT?5vXi2-3JCZXQ+KN4bJ_a5E9t1qJ9Kb9c7 zmK=IFti~7DvMn-&XOw#^f#qs}j4RrYfpG?Ml6*Sc#4yCCylj#0Z|x-ebmV}Ui4{Ij zN{M`!M25rDD3qXlyYOoY?gGkFkCx}=?Zzg=DCjzfikFBE2p4N^cpk-R%wk;wy>pI! z)0BGThJN!b$fj37(Oj^whT?etDchQgffv?as?G*9fl?=*f%>#OpdAJ$N7lU zwbXz{GC9~XY#;m4Kwg0Nj^8t4B*jH)gck^J&TC=5xGX!q-I=$G(yT-@XG%vqf0h1x zTqx)zXoa6gFd;0gZNqA1uqZR?t|JReF6ps|wr`=ZPpUY|$>58+%_v-E31J=)UFx?T zdS2+Z{0nhYIp_R#G|-OT{Eb7(p`?@~vqN3TV}lIsevxG^>AtkY4{r_pn^X6=AdR_o zQF2qS5~xozV-6~SemLc9s$xXHN0p$+Nl?DgeTtLRx#kFmXHVu0F65m`_UD3uNSA;l z*Ay>D(L)w@jXNHg>m;7hRu<;O{6*sSI0A1S{#TXtIP>$VHLpfTE396JxRrgA^K+28 z`V~d|>(D>+{u>25|( zx`au?MvssfY#?K>G2i{(KVZj>=Q*DHzOVbb&hvBH@w&gW5Qum4NwqvkI&m7*mPTKe z!5g<=t*vz}`8rd&#nbOwofnIkB~evhTVU%qlc}o7MeM;07#3YX&fp`lM&) z1&U2Ij)FC?8^v5*^TIQZ?^py*nM4f-QY@tz!M^4ot1w=PXbx)k$pi8!2e7_N%xR!PM z)x!k(F)1ClEyt_F<~(cne&cH^75U3lKp@i)UvL!k#O@ zY`)RP#-Y1uyIgjif30Y=x=%?|1nS*nW;hXh#;;I6pw=LC8@M?2)G{+S%>>nuE=N_# z*ipaw_dD&l*sQSr*fQM3{+);+IQRQQ_8pFamyXlsX5{tag-q)w&#wInuo5#QyX{P6 zv;WHa{AtYGH}23lEu{M{)pg1RDlfDAP}r9E+S7MlUxls8eAT{?%EL2P+5P9m?CXhw zhlyMZi{XRyON#aVM-LL+_9~NCJA7dB=!E7c%j)jJeZPKHRd;dBqTM?FQ9*zi{7Ct7`M&oQC%7)j>w-6=HU-fxGLlhr* z^rxa?h|_t!cP5uW@>nD-$89IG)hEB|7nlA~-I>)WIY}4G59HuIhuz=Rs<32n)SQ#i z{uVuFLh8Qj#GA4;B84ER&27kSb}a2n#G^7OAnK6*hg@QEN1B3Z&rG(IB{VK{dXDbC zLq>GPj5|oZ>-Jet^y++P5xKifO-TvAN*MqvLERIn$q498zgQhs&{*jnUD>jhyFJo! zeCQj`4R9yUiScXIl_bQdkM(yh)*>!!1?i;&15!q_WJRL7b8>hwAdh$SEd)EEeyk*j z1`>FIJ=RwUC+mplA{;ZtzPiBy(w?u$H8;}bo$XZMj-_;ojTUSduDU{;H5L@XEWUdzl4c zhhf4fzJA>qMkS<$f1`A`U}XK(GSh0AuYGh)cNpH@)u{dYkIFWGu@Y?^*L_>NGC+MW9~-l){3y3p zSRMbCS=$RPfcQW(^8@mGpme+}4faJ!>8FD^DLjpJ^jLqB+bBF0qFXlrbK2nMzbyLaXZY3)qo@_`FuRQWfg)?T z@n0@W6d7<%>($#y-w8i@k9V_#ziQEq?n!o?DGGRhr?-bbCs0%`){IX8#y!tZ-c~8= z@ZZiWy1TG@yi-;k&#=xA-^~I_wgg!*%=uPI!^CvFf<5pp``ht_A|0tT(@IKSSt!~Y zYE5R~Sx&C|AGjEF#{>=gHqMJ#S~8^k8l;6z`P(B7DRU!@EKdp1B%^H^3FS%7MP(Zn zD|CKG%ppaF^+k-NN9ZbEdHNE&m)5rgIbLVQY$Pu; zyLR;lpWPT7P~lN|?6cBUiub{R!%31@m_g%Qv!$14Z3*$}ePo3zr)5R_5o09PxjF1k zCb4t=Pr$s~Z|?}AOB=~6EdH7816Nd`yjWc;dYq`*&7@Vm|9VL z^Xo+5BGRR3Sp0zlz;3;btLvqNBw2G^#2IEaUgdtm5u_iTXx+{n=>L^XSo}u!ceWOlZVhBkGJG3~b!zcp- zG2TcPww3BMu|vFUrQO{dqKU!D#bi?s#Cjra1c@PT0xRvsVk*oFQhLr+h<{!O@;5c! zLe;~DP6UCvZAu+8N#|9o?Up^M7~~HJ3v4%myDKCDdqTdIVOMJ27*N^+*76e4ZaH~9 z6E4X4F*}f%D}~H-kWUY#VCo{^_uLB-fcHcqeD$G8HK?wf`oY3f%?w|syiZVWFw==d z>C-=ml3yV}gqX2kSxbh=9-L;j(5MlnvDh;F&1mrqVzuD8Yb^}zF;F$N zxxtcKywYv8;mt%l>g~UYzZBfIoc9b~s{360^y51_4l zg1~%~L+54A+|?m`{Z zAHovd`{|V(JcX-=713=MF*7*kSZQk}%fR-Ug1~YMfvcJxJd&C$*6nn%LgGJ1HX6{a z@imzkxDP}2aRnuJiZ)zUmR7kLppj1eal-5iy4)a}as+(-2A_!&PAv8Z<6(L zSMxAmnRiWn%)6?z9*ox)PRu$iROYF3r{qs1WtJ$r3D(<8;H|Sq=*5$Dc!!93k(cx+o|nRUeQ3ik2RMV-9C}IY+Xxc zpp_cb^(3~Xg^a^R@V&k2k4RlUyRX9pvpEHDXVHodo}MmM`^;zQ{?9nNvX(7b*(P|o z1Rn7p?ht}*jZHg-vL-v{c29crOcK;Sf0{9HgNw{r#*~6bQHEgeJHekwyO5cNYw6O* zv&t8krO_KhkT$8`@@!;2+;$@+kGo|rD`LBt0yWQ8Oyr57`gxw8GQ{-;e?;J87p{QJ z8M(m!YmQmz4a`62V6Pw*U8ld{;E%j9sID6>xKrCS#L-I;j0rj^z~`hw8!7rPiky&_ zlvo6rO+G zKh%zn4oahcQ-qes-U}D3ZoC7Pq}{emU3lzSOzUN!^q+rJjjrRoTQhI#13xqzB8QH| z5U-R35k~wjExDsh9!tgkpGLLH|J&6WKke#vhBCbNW_>pXD6E-rpdtKgoW zrvp$`RbL{%=r!MeRm-{QN9Ls*wz*xXZO^pwPN$gjZ0F$7LARj(EYHIlp{*o%clB}e zb0s}cIkS8BfFr7-W^XE4IvLmwKQaJCocoh1)pg&@0sNdiD@?kox07w+U zH}z+j-oNCEa0t*@&-;WWj|=+>b0W0s6CVp>=Eo8gbJh($To1n0vEg~&#ftW~ho7+R z#k|h+!S6Apf&N~(b={eIIjUQ0P1Y!tbQ0E zRtpe%MFw5y;6bkIA@b-WMswGo!Pt`3WwWOy{CUe9>ph53jp3RvI+N~y6~GCzAS@81Q1V zv<6IlHK_ymRl3M!wz=w8+xlc~Xa4n&XI>j>b49;>n`gn2%^S$UMyUibMCRsIFm(rtOJU6SG&?U83z z%cL`4b!{@l%ai?icbZMPI-Q4VD@>C~b1g?qio!`6Ov2IWn2&RkSN}`&G7R9k6Q8hF z{)9qpipm2Jtex1&ytwP}1$~lS!beAiFjJY+9&gD+*Rf>x-L@(>ba2*loydbG4I>4R zUxL)RuJK_R$CvL+4hEGn%8s5Lm&kFfPX7@dNiE#*w;zVz>^1V&95`vb=jb?VDVd8; zO%B=7Z8oawg4EKRNih>c8hQhKzy(DPJK*J#3QUThyzwR(f3#6fT@3byMrNM{(&-4W z2I7fLngA%BFqJrj!o=c!<^c{Fe@EtM68%*HF{1)FBY{U*x&T=$g+^Lth+Gt?ZqI97 zZiO-st#hxvR$(K-m(9S*MsE)(WKhce=9z5hQlmRX0vj@&&p{&!B`{rST@~+sFGE_z zvORT?eMrWhmwgWz>c%fAW5nT~^SiXpz_(sZ*(pFUJ|h-L4pq)nhW6EiDTzZe7lBFC z6JII$vI8uz-qI|c-Le-fX1#Hqo_UrD4ncLhQY9YNp85ZyViLhDE1v<%#n0+Hw#mL# zJwYT?8TFe=4~1?s+cfJ`7|}rUL_*(uo6-^c$Z;qj>z=x$*9Z6pZG7v9tdhZ?UP=g# zXSNxl<`3sQWA9_~IFg|8AI6R^jIu+9(va|jSF$*X5Fr){wXRy#<5xLF7o4}9M@AOThwxZJZY5|HtFuZ?c(X^uAZw%3=dP;7FXIb8 zbyiTPgbfCzAA;1$H;s$-tn2?#Vf=~+GMcr4k`B5a6EXBGa7;}rL+w=oD+TgHBEvhbM!(pDRy*P_s0(YiQrKs;_<=`<(bFkdT!u#rq~_(+(w zD|zhY1DIauex&BD#^m4&>T_^y`;oLG?yMJJY3z;uZ~8|rlHPr3GJK&&>CPU3NWQ7h z(UpkN#Q6$d7BCt)XFa>OZX^Ll=Yj9s7zo%iDt-G^Pwm(0-rCXd3L3|hBv{4%?Qk<)3zTrR~4~HhrUCn=% zv~Z1uv%};#u(lAoM!9)5VM?RAWt|~c<`4a}nfqE`bb-Oo%M$=mshFo7FD0SD91kis z?YBD%H;ggW*xJE=Q~=1sd>Sk3+K3Qtr4Gc^7Eg~+#up}A4fbnw9GZK<#t_plx}TDl zGdK9o6PMkU_a`PXkiDZYOZbE9**pSE6e6kUdW{o4h)`Y-;!iLyCFJ+bGaIuhU0`5= z7^~$)M9R5>GLGk?!&|7dTUDS4Qu3y4BnWJgt~yn`N@phPU=|1*V^~#`kJ2XVF>^) zT3Q}3C5rm!Q(vd5j$@YkG!}73M{Xe0NK$v|%;{hVwINU;bLf8#qx6v3v?7}#S5z}+ zb5m>P+~J$^Ckd-f&^R_7`A)A5=~fhM9JH$sZrS3dISMua=QqI;vd=*1e5R|O>lF9e zYqwMGJV9h>lICUcG4Mskr&H*k$H0_-RFe2Uv{Fwq?h^{KEAv`*bWzn&`Ab0!(5N{J z@IbfS(f=Gw8f`tZCU-$(Q6vcNlSdR`+A1{PFIz9;`(GY%n(Znj-XJ}Bu?g4Gb!Qe? z152)~l}FQZ#Rot5pjfZFt=QguYbG^2-Vdr43@0%IUUtrs8Ij9P`OXOw#{f%&SQ`LZtI&l<~l@(dgjgxe|`6B4f`Cu(hRo;MrDyRaDwX7!lzoq+rpktTx=ul z+&O-(&?1`R(Rq>GpG5T{Xgzk;6)lrGOQi#DCF{8e>kg2oxEe3vJzPjZ1MItuGS{qd zmwm=gSki!7N6wXrD}HfKRDQKC(?A>Or=Cbx@;hv z{8#WwDc8WK(|r@JmYs!W22^GLe7)7{v0F%?BiNRnosL+tniySk5Uf9u1u_o2r)aaT zpk&j0#I=fa5qFt4HuLL4E$$Xm_ZU*Y{=%pDgpeg$m)ZXx{Kf&9dEQ_`@S(&A8nq@ob8;zcOklEA4s=Lii3_$*8C0?) zT0zD^L}`+*&h^E8x==rNm#eV1*p^ulV5izt;qCBFyH)9IEO0}nzG&abKg;rxB-8k= zaqIyj*S7*LNlsdhM6)vn!c%-Xa}3b^HoHaj=XlQ|Q?ql`=%jD)#HG;bu^QS^v(0L= zDpyoNmt3!|q#}^WOj5v#_H{8(;QDCy;Jz~}0oX}XJhxV}rl{ig4;~IHRac$1IldI| z$DHI-wlRIK25795f;q!o)eU!sfpit!=^7Z1WZ>(~z)6u0GMFJn(h$veq7MEq7T&7_ z?66ZkPrN-t}JJfOQG>VnU4Jpn8TYcu}48Yv#LW~AdL9&C4 z*C{k`+5G z<15u6s2}L5RmMk9^>aScSK*x=V82Nd_zP7;|8AZY`5@S9D2Q}4t*jK#yDZi%G5rZ~y@c%JD*_cyYm@=<+s(&wlrk9|2(xd0D{3Ja(i0j` zTLyIiUZG^Y0I!|u+zl|+Aun{#q)DYY*DyY4j?YnStQdWvr)+rXWgVPl%lj@il_M9i zdC(A3Zm6d5^Rh*mk#bAB6~eJDEU6BKSy)sGRz0l$HOE3T#(tJB+_P!4jE#(#NG87OFV)j{(4(@@-+ zlk*t$(27z3Q1ILf>Qq6O4*wG97{DY_@Qq${bnGO8gJ@(bl~YEXI5N*Q-Q=c!7c)A1 zD!O=!NET@>&mV2c+(-||wUarL`0?RE`Oh(Loqtqj-3P6m_ET=i4TaeBfEJ813B`SY>_Xlk{M8bxpcQ3##cMb3(i?^R|#$)#)67w$x;7d*75}h|BRIA4#7ms%RqaRxgmluo-=3i{$@s6%FCru884FC>EdW z7t6BkDGig^I<}YKSCaEkdnO{RcdTlZEa(V5RsDvPye7x8dYqFNsxXhfoFDXLw$`MB z#fH3y_ZXPX&`a|=Mnksb5pJhtN6NARB`!3H%!F_U2QHzkrelG83x)eb%>mYi89t|? zgm5M!LfZd6VH@B&mxL=zYx~M*M6#(n{tz`2{hwXJIT}}-q7AB6;$!CWj192-ZMzG| z`6@R|!=e-qQ8pvlp03N(>X zc)XWC6*gTlJh3jn@RQLeCex-U?a(F$YgH{EQGQysdpUg?VWKG^ps3s7kZJq1^c&UB zQO(uAe=FeKphN*30Y=PmM<3qbfuo_&q3ud10%2S3=Pf={NZw(*AMB|Xv0kVR~2S2Zt{BN1rW3GE|Gq+5C7p7Yhug=`*i<78)8)QuMLr7?VZSTcdPSWHlixz|Un;0v7Idmq1`u^{ z53B8JT{Gb>M>8X(D+=Uo7CU5BQpI3?kl2AveYGfo-*Zq9fmFcj%r^mTU1)M60XRUWSu}UwRR*?3#_AZfBiway7KZ ztnaM4?X}d0BsC^}O;s@FiA$iIr4(b})n$Uh1{6uRCOVkNSd;|{fNfYFw41wL#OEZT zR9LPD7mc@Xi+LAG#5qb|wTn4Uq$b&>tQ{TD;yTt3Oa01~%P(u%+3yO^cn$t?xGnVR z8H*giE)>If=#j}XOw7kKOosr8a*#n~CgDJvQmJ&^G2z((-1J5kXpz&7#pPY^D=ce+ zPR2aD!Ca!?_Mxxm{nX2RsD0v1azDJ$s+=M2P%1ln>xr-$dH%r1bXBlT@P74ZAx7iX z2_NmRq3fL|Mzv)98mG%_$7l~))qzT?T85|KJ$&S;G`1)P~9n| zQ3#sJy7PSwHtyV!#2OAyd(7z=RA4+jLUPsGZ%*ED3=Wnyv>iR^#Ur-Gf4&$wPFB+3 z-`W!#OBix^iBv9*y{=_ml8M%<_Vkp{Y*N77u*uFXtx=<;hek#4~qe@kc8Cm6wu1Tey_trkx=#Qw-)5c2XsNka{LBaOH9V|;VR+!{4B zmG>w5=sW)&&6PbvmES3L{4*InJrb#QthiV;#?Fx0D8wzN6#WxHBUQJ1GQzoU)S6-& zm6YN@^2)q%U83gd$9p|?VJE_}BjGad8&tR5P$ILzMkgkld{Z))%Uu$XQ)Y0|2)DWb za)@uLV+)3yVt2o}-G^uiR3d!;?U&=DLayF$DRcxA6%ii$t)ERg%jIkagVs1!W1IK& z3wo26mQX)5wg4E`=47#t?ANW+dK9|-f1YPlYXcM??mrp%5bZ&{XR3z-xP}f2(NX82 zg^`)1Vy&$%m^^+kv|ejV!@trVnEoXD5m(3X=EVi$?{A}9!umSF`{wEP&PK0IctNrE zxGPe+3QueSAC*yAgbBZ&a@l}9-zLvIK>8!(J8j&?9<|Euf8lZ9P9 z9VrdUf(2{55regac~_dxJ7OH+k+;v(n4jsw%u&$sB(Vna-!3MoYCk zJV0v4JrCXVS*+bf7eh~T1oFPb8Bbc@AxoH;kwktM;8eGBf9wY(hvvGG zCwV`wc+k(^Yr22CL!WY7Xr8MFoqCzvv=L|jTMas!-ws$%oMPz&Hdf^!yE2APbddLZ z+QEJKi#sa6*IMglYpaW!r#Lq1!!P;14tscn*QrR zLxJ7qm6i(cGI`=7HVah0hub?k&q=n5dykqw#)X+tx*Enm%~>Gq>Nr}Jb`!H>!`z+r z#^l8!*^?rhYrP-4DdYch8lPlPC&dW7t1J~ljk~gccdXLv57x@XpID`O+Wb?4lpP@Z zBBG9^j1e=zT+6hK$tq@D!Dw2n<+8kKDz9c1tRI6+P#S@cv9$+iG+nk!)q(VFL5%*0 z!voJ^i>J;5RpJ<$F#&tJJdN|VDz3%ab*qBViv6#u#es8kBM+0dSCC{(%hkZ|=9MpD zqY`%NIw2v1MUvuT-)JSOU^w5Z-YxAEUly~_3N$~E`6QZ}hA}WYf)3EB$O9B&oKHa~maZ9=s0xt~V%|*p)J*kL(=6o8$7M{z4N+*5~SHPldU( zf@7ie9+zL~kbQQ5lkbZHX zxG=Z|$H+pc%4@h2hV+vAG0=t{rjF3`S4s6WA@xzkw6{#w?rILMsJmg*9!$GoUK`Ul z4(A!{Kag0^6bJK^Y;u}Xx$o4j)FyBL2_4c(SL~`EuCIdK`XkHR8SS^3$*|Pl`o6$F zITR3vtoUNgb?dJ%Bj|*WF||&tDLQQ+ z=PmGY=8qV<(z?KKQu%%LM+@r0k*7#nCVw4Wnj;1jo*uxD6kGJB~QdI2; z#I{GWx-qo?nZ(j1mn2CF9ZDV+JDP&g{LCH)M0`~7hQ2AwoZ$-GcDa}l^i9%qx9#OS z!K^Hw++9~(n7`@)48Z9NJ;B|xH6MZn+Nt};i*gUjj%FA3)zSc>Sd{7lW9Btu261-g zM|@hJ&5ff)I2Y~ZB_#qSZg<`(vPXAmjMgt%P}4tz=@+{DeO??Fho(3Z2t@eM{7Tuc z$U*0A*teU-NhQQ?gX~E&^$p1fg&!N30Rq)E8DzGR{W#B%uhBG8(LXIX9}-7nwXi( zJ2r>5?2YgkPd17Rq1oSFms>Kh+d6c0{^kB*4&wXY(g-=Gj$5g+QEbJoFTRa#$w^6a zK*pWL_3pA@5yf9B!97v3q9dVFuj?2kQNvvLKBpq9ce{6_jIL5P{igD?RNRW2u4d!d zoi|kud_w>VNTDkx@(46#{6B`MaKlSlu>OAb-33cdT`C>ERdt( z(fek2Zj}ntf%j!DKP#xxIEl{yuob7xKsWngJaOaD%k0A{fYoLJ_BNZ0=-QL7mq6{w*R<139)8c&+rBa&n+wC|nhnrTaC7V*X~@uoZu%6n(nR(@2&d111h^d!PE zdlXdm8e$Pg)>Gq4EaN655|so#c7cQDneVvGmL#tiJEz}lX&N~G0Tgf(eRrvhzs8q0 zah9wq<)sdAyyi*3XMTnr|FS!?_c;6@@MD<{U|M4}Pt;>M6L5zykCr_C`E%?NJws2b zo+`q|L}5I?Us+L*3OMMDebzZ>`XCT-Uqy_Eo{3d&==R)4*3j=m3g=)@mwdDb|7XdN z^6mD(x{IJ3daO2EC}mveMG-c+ttxF=>78pmEU@i%gZp@K+J2^n1}61Ms}>IV*|Enn z_E++#Z^fwBwVv>JU%3iRP2!TD@R_RGo7ws?V|uW!m1-UK?Gh=n~-k>Ww;Z^+xd zuy8{bB5qG6IHP?}ST|sqXTz1pH%R5}cC}+4gN>639e88PHL26Vufoa&CsHg?A&FYH zaG^LQymm$}Q8#qPVcSETgj$PC%bLQ76|`PF(|fQVvqtfKIi8Tdyq#iw!{AVx!UX3M zW6x(lV4d+9+ki~Pa*fCJL#)!XYE8Su-|j)|e!Kc*ZLU0*IueursO+t;?p|y)pEv_u zePaY=ExnhPdMBAB6`?L4uP|IneRZnm@v_ROFdMm(%`R4@ueJv<4@^ErN_(c+vG#o| zht;8De374(?Nb&gZe+%CP<*v;?l14*Ej=0QQ^ywtYKNMFS>}~%^EX2Sog^h`PR8ym z{}6AY!ls(GR-wsm`AyIlz zl-dlZ%Gb|{7SI6W5@$(OzkvGZLjL$aUp>{tDUwu%lr*BccvKl7- zPNnEgnyS`;TC^~&s2s4?g7!Y{Y&HFLj5q12<Zzw%Qr< zZCB#`&>>{_;KwI??CA(P%#q%BwV8#Lif~R$$80h3052iPm1Jjor*~xs{-ii^1^8U^ z&^|^jqQ%osjrd6@QUk%SG_L(7P2Qc~?{}3Fo2&Z(&qa#Rz1{|>Q>SjBmjDj}K#I=I z<~i3CUh+Eg2FV>cn*mB-o>@{x>CBNDV`gQpq1U)D^ZQ=9d60IT=)*s0V!(`~U zLJ{zFnuN5}N~OU99{;)Hs(66MO<d!9ZMd@W3Z)XS!g9cOa*|NJ5K0Te_nx4BRVX z7@Pm}NvHku7WoOeJ#BTqhiafe&eyBW{&kuD-v@8W%8zS^Fe-c&6J1ya#-KwBNuNAq zX_}IQkDn=zjtBg3BpzQ|_2S9|*vK{n*5|R{`92E1V)DBlEsQ~Jo3JLkJcb@|Ez2X{ zK|6Bhs*-9K=AO<827i7()-LJsYl;)%b(|?CxoHMn{IPbP z5>gPdaE9IS8XH==^}DZJsUK<=Ul@DfifHy9cpSgbHs+yz?z0>2^WV}>-|nPcz$ z?ed6kFlssxwWD``{~RgLg1T6XR?}_zM_Botm-D}Iy{UJ7WT^cKba=iZ7#`C@doB5e zvfE$Gf0>o>lVLcTbpl0X=Le!2%yh5aNay++HMPt1*5QNyh4}C=KdzSlG68DeN?ETA z^n?_Rx_OaikdmE2!ny1Sdp6uRyYIEZT@(xr6bJZBb@g6oY-f+1$P67)0ZiaE}S8%8nB^qQIUYAPXkE-T><(wAk*%rz1GQ65sN zM0?qUI<TJ#NkX&s|?= zGQR5NA03ZR?8Y7q(o;tYzdh4BfuWp4$?zWNvW#E|0am3U-BN`HuDvmwy-|8t5|dH;!vh?7p#ic zwhr5QLWgPQTZPz@5uFUVUF`&gKyJ-jl4_d`RTVrIiD};Y+nlo&$IamavZCtjS%Ma? zev_tUv&w$CEjJ$5TGUPzJEKhtlC|990SBlL9p;;-4wyf|Gf=zWO6ZekyxE?^W#jmW zUV74qh&eT!EgZQas9+G+p(#HV#(ZDUzo-u7w8EZ-kC!}tdxiv|{g z_bJ)MVoW}o-JbmRpa=Ql?y--SPjDyP_`g*|jAqulJs>;yp(+KUwS4^XS5By;(WYl+ zCOjlM|65rm#47VBZq|e6K;i=JU*Ppr%cLl2Vv7O<1-$ug%LX^AFN%l5;uP3my*pMRXU z>faPT>Tb+iht10P4s8nUW(B<3LJlF8i^xU@eFn3(`@$Ptd^*yEyanV&fYysxV)t2&pH9SU6d_sA( z-HXS{FCPN79^s`gf`F{4<|(qCl-QT{(vR-G{+TsW+R~d2U&gdj<6y&O;M*u~Oe6-` z)&Ue5nuzNNIjHvtw~Z?+^hzA{5bx-AQOzDIlkyol7Ibq;S3((HH>Kl;2bl*)J2o3~ zb$)UEiAuHLQ8<4Jj3r-vuCE(IFpR+P%8m=i=SM2vZ^ZErGPr?G{28Zv z)nxj4l(o>u1>Je+1ITmA{nIr-bl}4|nJc4Tnaj}#*xkzfTafwOt49t$f?nx_t(j#f z#%J+NzAYOObaNKDXSEuz@SSJqYY@Br$0g%sHbvKVw?Jf`xjXdSaqq4#dJ8BE#aE&U zNv$&x9bDA`q5Z50mTFqGrbCt)md|TS`yir}KeZrCznQY{{C!$YYXvj*i{VSclsM?- zJa`|-|B+e|gRoL`8q9B;kMCyRlYChj;A9Y=*;ycAo*tj@d*`bChvyf@dkO1Xjg5^0 zEr?vORN!W~F;}jB>-1WCq=vm=602pJ>F41N!rw(&oMvd-OEp<$+y|HYAf!iTB0ICUDzS1bAw-C1v}3<32Xu)c$@KVm;L@MS08! z$YA$v0ub9kG^A8R%~I#pTj4jJw6+FE%_OCd>?pL;-@WEz@1=5Zv?#y1U(AYZYck^wjUcDb{=OwMhMK6bzuK4| zT`+Z80yB?n3_rAf1_!%NCDT=h7Hswh_zCXx`RmvdV@N?4(`^Hera@0oGu0g6JR8cL* z-Pap<8@iUedJn=IA~qdjUZ}ZlP(RDsSyn6UT(u%rL|>m%19pPZY>iA@`vBzvI)#Gq zez>9_ooJpZGu#h`mfn3#QZFEFtcH4d=1!|aZH1x@c3yLyOhe+Uo9_($P7qn)xU0k1 z)v>BcpYmbFwe;SgdErC!f{(TI|I`IF9YiTYv2U08f3aruot%*T(5uYc_-J4I)=J8ruc1svtF%>bUAA8`mwZkFL zuT1GOHx9QPuKE>@UM{&056dgPtf^c(!ccD@7FR7&tgxY5UAYtEDS?#aQy$PIu9K4# z-nrerby!(F5d=A@_uQC2Ky2iPJy-rx28zDwS#2u(2Nq$uGHYV*DMBR@bXPLbY?^S7 z_=J#wo=fDbQQGQ{OSTx*%6R=k z%L%IV@o%lNNv0axAy_TWA~6Z-%(eJsfby6g^_=+|f*_;DHpBEe{M?>=_2Co9)e2*I zdJyINTuYZw0THdt$J%Uy-TC%+Ty60`$)XU<0WEcczC-NxCq`DEXU@fnOZt10=C8>s2z<~Gn!FEJd(cp zxFKbM;+qIIJZaN~L@rpcS8f!1DaC0naj3p|(N>7~oio_AzE zYssp5f}^TuJEAmE+-H6}u2z|_(d}vyl&Ft?1G(!YY$*rNJln~{bBuQ-<-V!#5O3d^ z;e2i!N|dQ%&Pdj37U5_K!D0NUaGzGC&%^#vF-Q=SK%VRZNQ>BqGIW)`Z5PLZmjUIz zlx%YTemK2kbC&a5vdn|dhaF&_l&{1=$hRtx4gb@HgTi%AubV!~)^IX4QEe4WZF&a% z>8jH}KH~S5?SjZt7}nQv3A-Tw2B=E_M7vcVu9>*air^uFD|IQJEEkB3<`d?bCLm9} zFu=u2?ESkJ6S7{YtYe4dIoCgbGa^kJ7YE6u`*<3`YwoD0Tc+Od_>fA6JYOWf^uQlou}18K*DjChvb(?)>y~&@1e6X?`}DRFyA-nMKc(tcz%Rgm5~1to&3h zq-1y`nz>GK9&J;0ph!)ezEz+CH;m!FqOxtJP}IvO-PbNtp=%T!3q8=KHoSf>Xt|}@ zvtlK12$SBP8dDGZws%9P<8nGKRPZk?`PO5{_AdvY(AS`8g^erm9j@hfo}ku7XGeemnMvSg0-6Wiw2lSif*DJO?6VSr!l|)kVUZ5=o!|U=7M6qM|c7i)! zc?|)wehP2WVO)CYC7@Ao6G=tSTxt<>*a;wV5fazG^iuRri2iHlh==<@7H9XH0y|?? zpXCJBh6zPPzLVn;xg9Wc;Dbe=YvV(1hRXIOMj1gEu|!J^xSjJ5(lCX3*!NW**o~qy zpJi+>>0Mx5@m-O7_*56LuQj*rAqU&TpE&y5oyz0mv8 ziDB?&$NIHeE@#1iR5y*Py|`t5OoyBSUfuoZ1RsBN2==jtl2L4x&^{JI2lIXN%H66e zvW@n4n{fLeG}F!;aU$JU zceRD#>Dl(;0wWz^&uHXpeJ;!3E{V6uzu@#9e%ANKnP#VJ_HWDc7`AqP#a`JdRZLkB zG?ub)`Qxsy!F>{bv=*{j&wv?UM?t9xUyNY&bN4CP4M!hN9!71|?FG1@A7Rde%4tjY z;Jx_|v}yw+nA^&Pezz!vYgD&= zp!|6CNDsbJgdm!?kUBu=Z~w&AaNDQ@2Q*f}mk0W-R{B}ZpvSEN1Lfoq29{kmO)U%X@BlI2MF7p`0@&&&@Gi=5|_;DXSf-41U5(e5xu z!|km(_g1mG47UiQt9`P@R)BL_#~*bIpABz@|00 zB&x2T+$E)RK{#2-YD8lpc&!Q=-Oo92L2L zNRz9JSNpL%_l{aot5mq3r@I~d*1l$ohl?G)*~->gCCDVwAd?g2l~2JgW;G3VBn;Na zMkh~X4^VdKrxf)clmQix&`Tcb7h9CjqQ@0Uh_f!-Dx>!K?LRoZZ}pP0d1qW^D+Xg> zXxe^vt%2tpgVBX6@48jA?##@v7WrQT(hqPx#T6n3XzBX=b;~OWA+gz!ZEslQs0RfmWrl)X_@I`#aloEKd@K9=sbjW zJzbrM@+A!Y1+Ht)0M~MW*EfxPDC?(pUuHG6B%AFY)tj>cL&WMb8S}Ej@_NKiBNWWz zDCkdoQ2e1k)O{O3q#$_L-V(kHa@E88v}H}&>nZO?OGTz?z=&^pE$R8OnDL`f!LW9U zdIPY>oS^ghuhebLnX!MlyP(lq@;P49oVp)lhAHJ9q9^V|7nLe>Q z{0p7&iMbG9Ob!Ptva8>9d{d}ft8lKFpT3GUsr>|@C-AQ+F#_)pjJ2A(v#bdhF+dU3 z<*%~o{NC|7)DuDUj@^2fUpK?KV%T^Gw#KX5s}B^ij20@ce%w~G`*{8NUt%-fn#3%z z>nBRHd;GIrX}qO~$zLpG%#cNd=5lp|onfPPLPInMW!U{#`tJtKT6dw$4$wz9&dQNt;vlqUtYEd8L4M6K)aU)w0{NUQySP>~Y?0qNhz;T&YtX(E3 z<+xGIY!_{p7j|o_YS5H_1di%!Q@a)LBq+G#?DZwJ_GTXhb(2DOzQk4CJ5 zD2(TFY?4*0n%oOq<@LCWtW1=ls+l%RQ8>+(f5mbNyWZz`Pree^I(e$sj#ob7H|#Uw zx_9Hed0XmiZbu!`ybiDq@VRHV^wO@U>Y+&$0-Mpb=9=aNs&)XW#SzwqS2D0t<<2M@fSyoc_ z4gOPO>Iwih5kf}u)18Uf=cLZHSljdh5Ae(kZqwtmc-b^d-8ySjta&f0vbn^LcA5Xo zCnLbh`^LxBMAgEWpGzzhorkU#NFs3S@YZLQ8n%lXtxIR-D>dDXGyd8v?rM7d`M1^e zc;=A?L)$(gu%?sTh~=UPuToF8?pi}!dZa@uW-R{&?BCpY2Rfj4w&-|wc`zkg-oJc8 z55}2wzf`)XSK`5=nA6x$>yj^hXQiPCPPXml58kLMwe;dC2Y}lEsg7w+QXz*rku=`$ z46~AJETA4?;-4)OFXQi^DCMoF>AJ+t>0JgblOAaQvRnPaZhfu)N}%eXSU~XK9x1*bLxXoleQ@bm znv zY5Dm*u3xjg4EIiceg6A%O#;)J3o5e;pi}`3V5P+#fI%}-#j29e zQiC3F4QiSW1D{8Avz^Pkdd&T#awegIk^c;ob7P`kbYjq zt^6?7i2ifFa2+rB)!;_N*58_@M#lE(kx66!01RcAd!9^;Se;%(s zx{`krh%;*5HeOVEm=en(2xXQFJ z@-y;i<##8a&y6=5{u@8oAFc|a9dxGW<20QtR`2XJ5-<#1VZJ)6IVwF2usN)%#*BV* z;#L+&A^AUO~se38&G|jNXl|qSxiknKI!>+DXG|2Gv z=V%P0p~LNL@r$*5a+uKk!)b)M2s%j`{XH%4C_P=29L&}K<`Ky}U1Whw z3#gD8o3!~KT}84wcXUwsdOyfOpXM4PYjxqLe)jUp#G$%J=s+pz;L!GL*&fg(wa*a3w(h5N^ykx1<%bA< zp}9SHk^f1%7cx&cGU&H9>SG@c80~dTqJ{j@w88gXJd6s)fK$My17}9ocf3E!9)svF z#q<^SRRXFb6KLPTg*uF+4o6+ynhMxTFrQW2n~16q2MmKZ_Tk#DM)h)+wB>ym7YDie zCr~Xfk!YvLUjsPHA9(4i4f?G*#N%#&~t?lfr zH5Uosw{;WSf)lqDmcApnKpniBTZ2Kni!Tf?$F_o9@XUv#d(Z2~u-5l*(ZqURKsfC4 zyyj?F|M~5YBx6EJXO1?<+0@#dIF`ios36|cI>jbq%a=#;U5-NU?xhfI_&UU^Uoh5` z=9t8o);3$1K7!aOraq8nGsJ1s$_|f(Is2WOvP&k8`iv^4-<8X-j5k20#Qnb9H2*?X ztY+!*kH)~+59Y;bzh)*kK3Yt@)KktKPQREPE+t03ye6grs@Z!v(4`U;aK9Ytg1ZvS zX=$DqVs_Kl^cDHUa>M3)FU0kcxOiR?3=)KY4Ys(g?^AetslrH@sPh}?Xv8CHZBpi+ zcxjMZC^Djd)4oFY+efPf7$jp)-lkp_s5}@3locCAh9uIj;@gNp64bofpfw!pm<8oXkhJ=2<44a#|npwdPf8AH_FCotZ(&LHQQAR<-Jta8cXM$CR- zWix&-N6FG+?NJIctuL7WFW+X5Qiq%EcaIEZ@{)~S*TGY<;iVEE;oR*S$d@y)l~>SP zKtws#g@`H48Pne(dS{CH^gA~Etb%Qi`XeCIALarena;{;`uf{ay|qWU}kb_?c!Ml{r>n*PT-BH2}Jd->sV6|ITo#E4yd zKPD0T)UOp9=eR^aU@x46a64@e>vz7CU*H9+*NJc@J+MW+*fRKRXw1kWW&k zsdu*iM`t{_xh$lK$#Jr%|7y4=bUw-*A6~oOA;u@+DVMHVrt6o_`a<#Es#JE}`f?q# zyUo12gXyp#pA`q#F}}_eEG?sOmR`$%6^nyNwFjE%IvKt2Z4yp?807_BAf2w2y!(S& zW~LSBx4pELBy2KxB8(s$zYpB6kI)-%y-In|>ChH7SL(&gJKG-4=mqvo9O{r?7{Hxf z^P|-J$lYWd=i6P}s)Q&RN4Rm|f_Z3Ar&vo1(}y(NmC&Yo@)I#_<;j-zHf!9)8;DP3 z3w(xJJ)2QSbRofM{)A&NI(q79Y3m9-M4?y($?LOJ|dR>iW@h_?FX?vh zAom*S!Z*J03T_9AzKxCh;a~ziNrn*EMqu0J3lGfH#mF`(4 zxjg2*j6YNr+v(XL6i#ulNIhFeHJL5LMQDL?+ z!_VHmx`G$z7Cn*v7Cv;+5$r5>nq!k1T#Y0dTzvhT&v-`N?s1f@YmD7hiXIz^(4USd zdJYaZGY$kr!+~~pc{$Q07pKK zF%vCr@9O)Fn3Ue!XJ|HCJS1poaC6{BR8Zhe#=h0;=50k6lTMMcJdM~y@p5#icm9(( zD_oP z_L+~oWn-1uo=pJfEnIyc@xBIS)kTW(T_B(Co*VLYevy*;aFn#G4RrC|T`9E|ss5%z%ep!%nuP3mg(dlLpT`Tl|8IVJ0jg>gcrkD?}p9$=`O_l3xu{~AQe?GpX~2Dap+%1u;I zF2s%6CLG)C+H^8^c=z1fpfF3ryGGf%zWE-Ft;B=VWn3Kl%Y4Ok+c)aJUI(byPkB3| z8!m~IKl9tL-?D!%jS7rI`TDbmIc)d&65)*?5&f>m zNB9fB$4TlT!kG9~*HpIV3e?KIB%@STAy4a`&0v3A(J$>@HCJ;nI?^ZI;vHQ69DE zCgHj(D+1x>Rp2EePfrGRZI|XGQD0MRD@Xw~9)eLb{u z{K>EfQ|bYauGr9vMNDG;P;pa>ykQ@9tgCO0=&=2&kJQOz^0}{5j_|g>SpWROXeY($s4xsJ3DB@k!L{I; zj8ZpwAhv7RWo1qIxx=;M$FAfk;?VkjZ6AE|*<>9m(Bgv9H(A0DjP%huwTmZL7uLBy zRknVKe~>U5kbKB-a`PEmq005E%CA|{L&`8sTS+?gT_>{fmhX}h8d95GO+_8$ILlPa z{zf>_%hjSCM$;_=!W=tVp5DlMyz~)0JXv_-LZ;`|qEQRCv@~Kf$4}_0VW$X(X6nky zrTmk4bg3d_+(&(pc2yApemCpC@yI z_Z4@}Vd;F?Vd*ET+MzimWVOD0KlaV4o>cp&AN3)Fe*Cbu^@n2P`8x9XAj?~#sp?^z zXtl)DeKL5a1pNr<>*CDT#jpiC{c15$ZsM8N&tva>B4W0i`KWJF^VH=XtswmpVW7J1t~;h^JRy4ADih{-oIL{%_ZHJbvHjPiC8&R4)rnP=pQ{- z#pM#_!)6{HDs^vo$~JDuIf=L>+UwMP!wk3e12~N(ch1c`ph%>_2utwBoj&+PB<>zmGm*@^06&awGwCOusf~4 z3(MWgHo^YOSMN#cdhf!toaJpx_|V@IwNPvbvF^2=vO|W`sKe9AMIhPdKLCo2OV?cA zh=M?A)`)0|>2AW3Lq|1bRQNJ|WE88-+M|N5iJ zc%|4wIU!^vKSewmbLvncR^>lO3h*IR30LPOiz`;>-Z`G$zixXL*JckfcnGqAL5rF&yGW_Czm<2Xt8}f$5D0!3p8`Ny-p>` z$4EG6V6ut$E%A!r+?IIgpT#twROBzK+A}EWJrX?uk^EC8*p$4QJw`Lvj?^dk!v}m{ zr>;mJ6j>KI&!MPTBX)SFEgvLfX%QkAS6y8>qV0amfcVoDWp&vt4Kl0l>$$tSqc@Rg zm5Lu{NvydWK&FoMr~lT{I?E>j3}zL>_`)d4CQ}PVh_NB}*(JqT$p)ZnlW-On(OGN< z+a^Ym`9Dw#V^MY0kKKud{wj~X%SG#z*%7@zBZ$KSUraNF6Q*ll!qBxej90yM4yk5g z&dlUV$utcC?k#2nLU*8(g(%xPguIQsy)-fLD0)XIg?Ruw*PF2FMS|DkZHzT)Z5<8d zu}A5wFZKNHXMDaCt#8PLpv4b;DVr`b<8a)p1VvY=S-Q_8=C?OClYpOuqTT&*U#&+d z3TEMRN~Q1?9oZYd@-cKj2gZk*6)i3Qx^JYrddT8z0i4F~x%yZ}xDf9n1DFiJ-|)|+ z+821A?e8OzxRG+q6(M!w+k5??`FgP|(jkS`Ne&rOr?oj^u1SUa9f*hg z*DahX{0d_=3Py=6_}mWS`FiKe3IZR6d}Z$dPUTu7rZ~U+)ap3pr@noKh;UW2m;)Rs zXv?kf5k}tG+Jf4XY{z_p-qh2rtb|URJB)g{?i3hFCB zXM0r?BX%rZZJG48`uHqZQuNP|CvM;OOfadti-in+x|r8w5C4i<=M9!z-aki{2ltyi zP)oY(6@dDRLy#A36UEmjFhlHEVXu!(hgg1SoG9KvPB#5|s2bd-3@X`s8XvpPW{~X~ zmvfpXUNb1TI6mSFAM?>_)rpcpM61<%)nrMgxrBS6wzjR77|CheB z5$pIZy+B;EGLG!sI;QG>l$`fFVOoR-!Tf)`ptHC&=!cH_qfd(COrB^vt*T4{OlNCq2tUxjOrL3Nb_5pb@*ymGFi! z9aa6yhMsr=)TfPq zA6=5DB~GO+?6J|L6jle@`Cv*X0pg$^p}b!?Qg>*OwMJ)fFGaSQ(qDJA3BGXJ18jsI zC?4lwj0(>6e;p~1Wwgfc+%2kV$h>_=1t!5|JM)B_Zad%&btLM>xdF@m|L6$A{hU_H z|Cr9o`@$U5##UXB%}w?fMG0AS<^mZOmrd1eZmO1cyaD2}Sr(R8Ja<@*mwO@wDa^ea zWiY6dBTt+N&%3bi)XMS$2D;;lf$HCVN`ZFvW0TE?0=3#S#|7{cLW{uJ4UF@_mL&LF zWCT}#@9n^G^W6(``?Pu`?lco}={nwjM4N|(J&M=9t?iy>~-3UM*TO*ZPG(CqFlapq!-fDs+&IJm}_Grz^TGU)ZF=+{!H; z=9WEX@p`kaO8bL=K{)3{HC2Xomi|DWnG;g}StoNVE&Mn_m2Xbh2DKG<)1do;KJE{z;&r7akKS8Lmhh z&BdJiPH{;p%1GKaBz6b(2Q6-HDMBS<#rxg4#1u(ZRZx*XlM+UxoM7JpgkiwzTo!~@ zWLAwjD_5Dj{~r-_i$P*ew%1yDKi2BvRHe z6w+7pqjRnq9n@*MPQ zXZhcpBB7PkbQZNXe$_J@`aawN8d3@@5NWZiOfiyu4O)mR_{pV#U?~cGeOS@`qV(iM zntSxYs;6ZhV_{m``bKz3h399_%sF{)96!l4pA+zyY^AwEKXq1T)u4Iv$bR<6R6|44 z>{bxKB7XLb&(N(KJ(gtpz~!$iPUVB&6L@;9-Lsd2zTj3V^0iM!!V1WKh%?2daOSgb zT6b+ce--DKIeNByd9`4-DEVlVWaYNFahv<*6DkdV@AzM2o>^hR)wQ(9FoCyI#U++H z1zy0W9)fb0He2|kI#eocxZ50ahbl|7#qPO&)ZVi`JX{go zARPfs+@-36p(IO!KlOg>uBNdS#%1#0F9*drg%)mSSGXX42hw>kr+6Y#J?uajLfF~{ zR*&N`;&E^p5Aq8@E~(o7rg%W}^g+Sz09URDzg}&$SAfdTB%qwa=e`O$sUm5T%=tM*jvM*@VO^r z55|W}?N=@vXlk}tkHSm|_b~AK zRh|~JzZZJkAhFZbg&Z{MWA7m{>M|f z^H!XvFd~MI9n$eZVKD-s$JFR-x~PQjTPozAA-1tpw^t$+e(pd>^Ax5!_;a?g z`Lvc0wNGs}Zbh5P%aI*!MNs~T(F5^RR7$jug~UGhPPzP;CR2CtTKiFaJq}ivKQ7T7 zk0hWie}${M&pn%m*2n4;F$$;sIXIhpe|CG_Es4tI&UrWJJL$UfGW5zkTsU?; z5Z3hHrjM6cucOQ~23Bem76A)@DU5Gn>PK9|Yd4UmgMX>%T7xHkkH&s@_Bnm~kZnk+ zFgO=)C8hKkX+B}UT5?^aGM-TG!ZLh{sn>tPwVp<{%+fU9bm;~MF3wdy-j8?)C!VJk z&tkbFU$;B5n92GwdxRBaW?=KJA{R4hm;UvV)x3`xbvT(1`&l?&@d~x@9*`6qw4BoG zugzK&u1DA-37iE5tyD0Z+rYbLnY}`w&g~$Z@msf0`o?rWong6hbA#F2J+xKs>@h6U zh27e}r7l6Q%cdud7*DOI_yu)?H@~hou9zk|J~}gp!Tf0Ht+)5I_yOsQ0qj*%WH3Ux zKBnOxeX>M$uvgwhkIm^(@+3_~bXleg4ze&6>p{&Hhb1VdY-Eqfw_e&oBkugsPNG3! z6OOBw*GdkU+`caxmjP@|pc3l1diiRf1#d#bA3j5MuaAVFUMXn5U5vvXHodPXeCV$2 zA(tT@Hl_~x#%oQ>n$n!9qWuj4w#BK!uJzf%%RFFs$dfcQLVtzj$x`l4sac=|)2G}= ztQ96$qeX4qgGF^JEnoh8*5=(Vc`uO!5c?)Vy{^$!t3!z}8fIwjAQDwAl%JV)Ez z_Q1-jJJ5bpva5k;d-icV0-&eMGgQ~tI)QlN(`rG-!mU!}MGHRzNyfKow=4%WuU2e| z*g;(*b4+_A$r1*)#xtW zYVBv5W$fc`=EiST*%iKCeuOjVktCVD3RpP#(0_hwZgpf1&Z~8wP`phJY@9*O{9{3G z2vmFNXrBqXb$^{;ARWb5bKi#W6GfPpRc#D}h@=`cDDf%gz#2;OG?n+F@r_wdy*e{o zK0()i{ppx{zIo(;(4)vw`y=@-GQvf(_1}?-K8VP*8ViQdR7+um+FY$+!B+q9xx_2- z63FeahSD)GNdtk>#_-{DyoH+*$ZeQScKWW`3=jA)SnT}H4?eSTk}d%}n=jW-Qnz#q zc%4{2c?F7*^%W=z{vX{ro9n8gOtjkdLb<|>J%t-du`WH;Q7`>~p20CsY6*cUu#(-t zKs1T-A<9Ntkha9E8DD#kYDs(A-$x3Zg@J|dYNZ$NSWyy$tpazhONXdf(%nE{tS#@( z77c|oK0up)UHcy$SW0?wkK{#&!2@&yXtig*l{GxHk8U9RhVMNY06QjS}ZcmNPCS-#KuA6eJ906-MGn7tSyfZSbChT$ehXzI#a)vA~pRB~6 zw1G(aXV3~D0M9~y_Dns&1$SE-4kadTz?;wa3Rn_f#=M_71gS}z{W?E5(_Rz1Xwrrj zoxy*cMFOBVe^;F>D%LDy*?##pxIL2oZtTg5_;#_xfi_OUD0`WtO#rt*EC8bEc?E28 zA2xFNS$M6H!O+#%kE_=J``O^C`kF<<0@fevB|}ZTR*kcnUX`|kUSUx7naa4vwN%-G zpT|!aG(E*Zyj$5;`d@Y)^k+5`(C4>B9H9%_Pg%t>c8Nj(z%Pb|Vp`2LUpl;5u-(S> z7qv%!O$F>d9q%9a$4b*ej4Cs@4q1JCE+z1o3dX67FV@U1vaF7MSdGw9cTnn+U{Z

    |q1$C+BQsOIeezqWEh4`lyrpMB zE86EAGy-um&34p{)%v(r*g69dLcLoWQ(1?H^e^532s}1ui;O)BvO^O1KSBc_ls8%Q zwBDLiNO6$n@Inf7kMbJ_HXdihKt-|--c6at*|83GeQtg=>~l>(K5PyED#7hMBKwF= zyHYw9`DcdXtFEVF*po^-du=o7O_2r08Gt zl;cd9{ztd)N{F78Caymvle*kBObvaxOmh=8G?6pjhBB!?v=FZ>?>PG_>F1;;wyITz62^&Ny6)HtG9z2)gdRy zi`{X;dk@j*-y`LC)Iobp5&t)|md-`7_DTbl^&*ohFBSvA2(4+~TE<+qFjkq+7+pQS z6K4&poR1jSPnG+nM&0dUTF)PR|K& zAOlqq(Y`k0qilHVksz!!RVl-s9wD(@k~!i3V{*1XMN-dFY$Gx{@|OTgEJoY)C^l$G zo`%T4ihQWSqPv+!PMpI_%fF@Cq|>8EQy&lVy6tPz`f;w~<%5Z$-H!QetE!U0B3ba< zZo-yCVhtWd^9fy}9@(AaX+3jvaGEXQW zcFkSt?2kO5GL9DJFR+m2O)qzE4T7p{C106p@r;4kw1rs_23&lB8=<F!@DFGeN3- zjq@We_5YT6fBve3wz~5V(p)$&<zDWLh|@f}p#{hP zX#b$sMv-7d0Ow9e`DMX2&5E7h{dj{>s{)6iU9m0GbI$8CP>o057W?HzI&iaBffScSVu_dqor84djI7x*>h(ZES81O~~d&`VS7Hbt%$C8wb1o7SRBa#LMT+)qn zZ{(u1y!c+cXv{`xSb_|rg0%v@{m@6S-NkpM!c7iKpux7BP28|XOnVre#1vKKoN-c1 zfI1U8_wG-XmDPlQ&ZpO5xH7FN*!2eY5m$-#csV?sZ16p&wtRz&WSXjO;t~ESQu?fg zVnHhm;1Osl3Wd)VUgUrtq}F7jPvRghaqk-(30{rCz4o3hQBZl>tRxX@R{NkcD9J4nMN@< zWze*=3cFNQx2~M@a!NLkH5dj}aroe9>3tO4;dn!mgx41 z2RE54a7tDC=31ey^<_QK>5mwQuiF!1wX|i zL9W|3es}oP;b{)sJi~E@+(CP%32m8y(fX4kds8Y03Le(h0~TB6eG8-f(3icm4USA{ z{1fP*Ag43oD9@5U-8I^Zce{6;oI7>a-}Rk7=bV z;{;4v$!3=1U}vb*99(}T9t=;9@EosSedX6;@G(4OjP6EmE~z50g1xt4AT{JGFw5$R z=r6U@ngQ+_Rdv4V55P^i4Rowm_E#;SZJCGsh23e%a{8d-dM71;Gg=uwcvyPVv124Cq3PN zpVQDCp%qF+%#B@a2`9AW+oXzGdND8MVYGGKCMXXomZu*ac-U{oBhZZC;DJ?*soyXpuE?z8()y zOj^VH1;P$f@LR?0Cx?-9<(`LI*k53nz07^1sEyY@6a zl|Bw8Jx%_6-qB)gC5!xzx~nYU=$=X(+F2;JbjS}tXztzPb#auRQdAff#)dsjeMUeJ z4c}%$s2$$~>@8zsT}}iW+riR1&WL4yNRBN+p6B%maiBzCvcxvWA|Z5CGUZ}Z-y#PR zy!vrOdtA}7YF1^2<}o>1aY`Ck_Z(ctO_m0?+QsM|k9`jluN(z?j$gSsY1h{C%}LnS z>9;XEcjv!X{5=*Ecfl-q3So|x*!9i$r%hJs=)haEWvQG}?|w`dDmj4jjE{y7&?3T=9o8fBmp%sQkXQ23JJ zYg~{sn-_vsseJZII}0M25K2f9GhI?+sk45PoUA57k{A`euY?BhjYU{1UlQ20WM~AH zH0HQWW%}<}Elgz#c*`@BP4c@&1)K$M(C}yjnsAK=s4MPfd1*s{l{ra1=9b0AQ?3u-D?8)38H@9f>s} zQ+KIGMPF)@7QXz{Xbk5)`9w%uYm*>doOyi8s^R$O0Kq~fQapQ+BjI09qYJS!;3BD>;!8?yYgZ9bS#xrP= z3D>#61=@{ZzV<9%{Ut%a^q)6piX&rjDz^)#T%Xlrwa7g=H!;Yg_&yu|H1FS}xQ2*n zq){1woYMMy67tmbgS7RQ3fV!{SIxD$F{!Jcl;w=+h*kMoX?1#ehv)1u(SGvxn ze%~-swN`Aegk@M*(+qZL*^eEYg-qMz7V7 z&KeqW{}rpLGJ?7(XAB)kO&(X&zwt?GEyX>=U%Lpq=^>mXBa`yYGTF_nvdjnU{Pkk- zz4p+HtNMD+pYPsmO#Nr9l;hGnlJ+QIxqj!4+a(4aElh;x45qirIr?goi$~PvhrYhF z*D6UrGV4I|e{rK$)1pd9K;85Hyu``AS6^l57!p}?PZfsaG892V4vxC={kJRDh>8-! z_r$ixA$ivCEba^iVMDShoU_CO`=8YlZMmtk4!z3KoXPK+_%FPkIAs&ZII`7?lWg?b z*B;4*z|%Gvowhgm02f6YTNTew6x6Gh*4Uk~OL}v|qQpp3aeJa#+Vg0(%#`gRYvyK$ zAY3bm?y?^;Ff3)R@#=>?2bBv}~zXO& zin$a2CGX5##}#sZT3k>re{4iZiUXS1QPL#c+#ZSntu9Rf}|8wLu{c?`Yd2md+CqzsP={Jt6ea{-oQfv4qaK{NM{f?U1 zZV@=DLArfx^iHZxyWpo0!oHJ`6X0zyb8Fd(g#ePa&bbGVcf6frp@cSpU{l^Xu01N1 zYC=7B)Yg)`^&I{gzYV>Ni6Q-NZy|h)^*50nEPFnuywxQU#xo#o_4xPc?Y=inTEVcp zHAk>1_kn>LU50409{oJ?7@mZUu9oTKApsnHXCToQZz9^}#ymokIFR<9c94PD7or)L zG`Jm>faeWA`Ae#d*I2Nr%iUB)B;mc%-BD6bRS0U9YOYtR>pCjYQzt7~|DQNlG{Xz| z6h~0;x#yX|&9vej*p5|Agx?#|!@m;hAqqjZhxr3aYY(q|i0?iv*;o(cxiY6qdG689 zM^OIB69F)6Z-kp3pA1Un<f^j>JnWTto(}}8lh-`!msrr7A zs)><9pk_r^2dgCYL9o`g-9!T=AwuhEMi?NtCVKRK&vRq$SbOoU$ID7O8N2;u>ljXo zW9Qm<{G1kN+S3+`DK`$kCGCGVe)U7SJ=Vd^<|yD7+4UR!Vu{DvNH~1$7`h*|CW%AU zmHbZ9%HK5RwVTQQ^z8(Te}8>TZmc;a?xzb@e@s?;CGVe2J3*;-7*xNuduJ*gJm(GG zHX>#HV6_kbCL9J@Pu29|-mEQo(P#wbW1TTp%rlxO;@hl*S5=F)U?$Dh3=a`Y`nP1T zLbs)PQ$fo&X;Nb?!{T5?g5MV4o6Tm6EoM1OlvYj-&I`@YzagG{mZg^+wVp0Orev&w zsr|43R@c`xZc0Z@b=$N&%}cb^%Jx{5^;lEsT`V63cAi(f2AvKJjzO+tSa;uY;DU*9g{`j=f-xNta$$Lm+P-Tj0fhLSwE#E$Yb z<{z7>>}uZ)$nL-2Sjou=2NQn|(s)7M;RjsS_McX&r3y`@r&6tM!cb^g$Uneoy^N(CkN{t zCUq_Y*3Z>8I}&DK@y=OS!+$OY75&irNl?y-s7cfUO^h((yVApgWu zt(SEtoA7OyppzS6YwN}9tuxkQMKTM^CXGK+SKDV$IKbHBlZH^b^Rt#VdZyA`lQV>U`#; z^4B;l?Q%nuO5BflHy78e!3Rz`nw%X4=I!p5JyD*<32`pqiuO)2nN91(2UW94|D>@$;1M zvGUR#L04;YH?e`sR|Zt15b`GK?+lFF9dz7UtuQUY=i`e~{aAJ%r7Jf0LxG;)^&>y? z-)y=?{iHy2#*$KifpJK@M*O?^k}um3V^}k+f7`6vRWQpD5QQmn43P@o#Ktv!&(?Y} zxPrPGbUohPYIk`+z4(OP>CIL|N#J@KKhHJ;WHo>2D+{3T)0bM!5ykf1VTK+?wW z4Z(+7ppGq1^%)N-R}gP&&V_XjOV-^oGW(Uf+{6B;enrVNgHoMQ$SJ?`;MPH7(?cTi z;N_c4-h++XQ(L7n&qG6xP)*JjKCPRhNJ)3u+c6Dw5V>G->180wz`qg{R*Z^eo(M6c z!8==@Uuqm9h#p2&g}))hSk+H;c#EK$aZE+MNf=^h2#H1R+Dm)9V65x>r1J3CVfi;- zy@<4OT(AE`e~|E`aLP5lqK{!9p4^byTEVuxFNE#=;csUry^rt?HYl`T6y$XP;`i>W z+C1uO)+}3>>v!Vhu9HZA0iMvS@m%mEF-+h2#?38_KQ$f~X&TBRHJvI`FDd3gdtr3xTzn?; z4O6l78~QfKTd!^bmv~c^U#~b7{fcrKr*}VPEc0l2v6o<-YE$(ZgJA#gR`xqZv)fx9 zEOl}VhHDJ0sxl}tL=nYtRSir~Q~*Ui1XiQdy(y-MlHq<~F(YnlylkGpm^mFQxF(@# zR$oUnJx~m}8bdJ!e8;5w@5o4!igKQmX*>elSI(4bsOA|tG36E#%<<5aSd8+7Utii2 zKrU{jmni1rglzb2!CPSrSuYdf)`-P{A4mIN01)!nhHw}~^~`k5Exuqjph~e(qI4zt z8e#|2lUTXsyJqvOHYe8^!N7IDHH;?~d3-SPvJ3r6f%(oWC7FqIs!5KpdOfGlUN5^m zSL3s}(;#+@YGZ7lNfvZ8Iq@bijERC6f?6Juy`QG z8{XDjpKZ=V_D0rvTK#%|UnJ3lhaA0XI4FE0*#c4WOY;Bc zNBuXd+1(AQ@IYUU7>2r37<*m+l6Ze>N#|8DA3baKpPE=2ou@(OeV`Y#!~^Anf$6zz zVWQl!ALl{y$gCuV8ZW z3$qv0=t@AtC||eO&}gQG5i{nim^;2&Y2#AL_^RoYm4^^8b1b6pFu*toN44b1WKO{r z+sqU^ZNy}lbVQ0eH(6bKlv=4wkI-j+ngz2KoME*N!In*=SKq<4Ug70%zTzg7NVVjZ z9o&Xwy9P9MDg8f+&N{Bi?|tL&MMVWcP>@EYq@|mwNQsDmbg6V~NH;SG$q5KZPNgI# zIbtyB25H!U(MXJDY;5fFdw&0Juh*XK*?G>n&$+JqeVrOa^)8C|Cc=6zvfpl1Yx!5C zg~*Ca@QZUpAAV>;3WPVEbZhEOnK|WUsN}uaa*o16q~2*darE(u3z)cP+YEMjLUDpg zO^SW|?v9D+;Wr;`JwLKm477Zk=BJ0-xzVDyc;zw4NJGukG0IM-*Q-{SY3o0l$hNnA zx4{lsSC&U#oD7TXo-uG?>$?Vq*BiD_-C$IM8TGZF8OMCqvtHnQ_uv(CZ7=z5aEItx zGFw~x)%ym&43WA2R!p9c9j4T-%|8S~)bR3xy$tE~p90}flpzr1#6O_+Ai9kqr?Jt5fDqYC(sr+)09I7>h zrBzU#{(;gG82-m0Ce$Hz_mrW0$4*RCJ#HU7u2S5O`LO<(W~ktOms7Mcrlr(;y=1^w zVc!;Lx$_X;f!&}Ew<%`~vlYU0ngicU=iT@tx_sYyW?cP{*wd`3VT$Nt(loQ*L$mCl5?^)KT6niEPG+z6L>~ z#b0-Xxb?EXc)toUn~B}MMZMllV7}hDVL2~2h>%Drs*%Wl9G3e{2IE82Mz*#1h}ZlyUhyy033(VPh{9Vwd zPxpQ&n0kx1ox~@~G~37hnejUxX~gq{^G$N6p&o``%E|e|ddB2zYrApNXMi}CAN4wH zW*Ay)M7g!8MKoUNJ%oNnX;%=jJr+hhtlO%IK8D`%Ph>V|qJ!vCx(Z33JZ8oTitAvT zp=^sl$D`hRSmEO@*OhnGX4vl+Iu{1+`J385HGNVmH$YAcy)m?NhRk*JeSM&I9)ys* zsMh4&Mzd+&6v{~FotiqIr`KbN2C4?ymx&yEG<=UKJ5zi051bkUZ#_z43ev7$P5J$> zpm^TQGeLf`xaVR3-i!sTsQ#>x&iMS(sGug?hh8Ikd*ygf%R1`n(J647_diRQ+F2u_ z0-PI>jWQa|!(2aqlmA?K(~eJO_K*g-g5olOU_(H~lm09jbNIiN(YLj~MfUl>pk!OBBO`?UV(NMZT#Dz(FWC zlwPUb74k}5@!H*6Gs)s7~tZrHrk;}pgIG8BSeZ2lckxTCH4@7QmYy}GfYxq;8$(OnzyhuAh6xb{&r zD_@(P`pSe2i%#R4V*;^s2k_Any{m#hX*JKFK&28vT#PLx9~@Jsw`WAID@hLo|68Ds zOdke|L)8&}P=Bmud={sUEq6P7W{qlOC zNp;zE2cNYd#JFJDvl~xljzOscePyMio;#3OR5;7w<+CnWR3u=8h$@BD4{8W;f;T74 z1TEK-xT909x~Od9D#NkYb?c$yW~eOlsqoTE`7i#X$@-vk7yg`ZiqJX~!RxO`a|FLI zV%FzNZ3a*1?A@&<)9Kz-aT;=>`|>Vy=9@Nmt$ZaDajc;N`H(com>g`lGorV4%XTi3 z%fG2eP54|gIk%JZdUe#B%I4O7=_*joNlrq{0^w_1p5~|kR-X~p@sT@5J%E3)teF{~ zb9n1dGcN0*4ih^&TP8$N!A4?prr9}k@?OF9^4~nchD~M|YE&u8>fX04i@y9s zR)z5~xImz!D6HrIWhp!{Y$ZoGUwQu|EbgJwtR2VHvt-{IdVAiCBrIn(LDwJ2*;Y8xC;JhIl@A(jCpP)&(^;vM0Rz&99}VGR*JSZs1uD7%=g z7Yd%!|Hsf%Bn!QM#Lp8s@E^@h^~>rwkAt?N03I)Bm?KAP^jDuoj(*6+q{Yau@r>R* z&^GR}OUg#aq;VQvJd*K3`7g!!M{qU{&t+a(yv?}NdLP-G0V{NC@#RJx{3)|Lalafg(dW3yG=I7xR z4?`z`IYBdcu#2A_QP(ocYU{8ClN}hdmGQS2J!JmzRs+-U<8fKMg{IMGb+KSu-sd{( z&8hK_k(nBcf8ltAU&$+;AxbvIM?dn~{zXQj@r?5G>Q#JjT_g6I6Knxkv+p0#``QEmazRv+-U@w{0Vc+vbadDf3oKm5y zzX2D^e>9pj1K-te{o$(*4Y=CfptX4~s|dE?L<&R>9j5Omf0H+S$erqpZCNKZV&`uq zPXSXNk$wgCQBhTpdVj*k$j)~GlHyDzke1>eaq`2?%DtDFcl}mIllZPj_~U{-J5{-i z2$qO|VXa+p`S1VH3@SJaYqxJJkMim~NY|6JdX}40y}^y@qtx>C6_7H2*2GZd=Hr3j zQ(y4avw~Qg;NP0;1p^7ct-(yUpcQSviYdoN|gWarmrU}PdJ~#76 z2>nUj^+&xMpB?Uhju_ek2mE>i*Jqqq};mbWI{fAya7l*g=fvI*iIL^2t#bDw$O;sAI1zWJAw)+794Z)%Ac)jMG9W z&UJ53y}_N*k#EUNaoEj|rP4XvkL&>o9sW)z#+49W-*(89*dO6PQND@WTjt(0!t0$$m!1dqjV>Yvp`SGQQ5U%Z`-%B9;}qSC zmgVT$uh?>#CT+FxkSI|rgwhjur2L`HkdZ`Z` zzB+mjCZ1ekWwzd>4i;ysL3$;sk9T2{{4^AkgUzl=UVz+WK4XT2rrR$*^>_StRUxd4 zPijJ)xnO?Vx_-@EH6oi6B9z`x=%Kncvj*RFJ(w}O$bv#(>_q-2(+Y!d=8g&VhNI0v z^Q4~MH@QsQh)elC!(mGJkg{2 zgia|bHW+Mah~4b{p6^agB6Kv@i4)Xo%s#S_BbvO~E0`Ul#wIJP6?X=S*x`4~8or8D zwQ>>ab*qYSe+OpbfDJ>^mC-+{W>qIoQ>M?4L}+gRxs=K2b#z4>Hd|ydH;=`H<@RFW zH>e_RpgZ!?co4IP`FV8mnRbToWy{j`-oMi$3lqL*>1RZ4>eT{-y+iob2CK@wdv5!# zAyzYkfx;$@0{_&G&n*^f^aPVWLRW_^&Eum;#`P+GI?Ln3w2sdVj^6nUg0sU_&W2SadA8?uK}x z`&AQ7Ywc6)S){d}?uInK)bxKeZNJR9bN1i3U8%VLTN1uUsarQYRx!s+_PlOEw_I$i zFLSL?29fL3)BmyMY&aLLLV)%x+^dVZg>>NQ&*=rqc^LS+hZ1)qrHNc;+K^XKux>3D zlCY++;teeOw1642QeIK__PPnyCUAe>LOuhj2w**B7B03!8#a0u3l}K&bL!H)6mft- z-Qq!t4R`Drw33H@b%V;~`t2cFi3~~?M}o1xJpSAxIlx*BF*YU3295sw9k>H72k9Wn z^)EO3Ikq)DxE>B3@0pkM@7BS6EaYi#DP;mljdhMgTa;I%+e$CoTRxsr`B9aR7|E4& z^(Ke9gWrdbqz6hiJQ}fCX};603Bsuw!f&`jlIkew3B*sO#0j!nF?i=!S^EeT64~_}=G+Zsw*&_CeVd_K6Rs<5uVV^V*mvAOf!%!~P-P_-aM*E6Vze zo<)f7A`+*O)kJ=im~pj)gsdMaEU&%uzWt!P#ZHMHLd1&Uy&tQzsO;zAD$dg-%Y+M&N7$RN$(k0uBm)ciP8t2v7A3` zs%=E?6;RAp;ewXfU`0g^M1XZk@4DFgM+-eK0*|ie@>ijkfd3dc(n-){qF5fDC5DIm zw6)sKK9av_6!I=pN$J^m?4nPL+slXa^c(wjo0Qu*1Y>~o8!qbUeZ#79qsdjQwSxKc z)aTbm!zWv5@w*v{%nLR=zMTV<-oFla>fKO}52mW{f@HJSNj|SzhympF!*vJbB}LC= z1W~{+0nz0h|0PZxE_|fzbTmNevAva+stWyQe|jq2;lM~N(7O0?5+T>sY-&yXiD^#_ z^UuL^e{+&nxqEAt?!(cC{NqZf2_``LMr0{`=C+soB#|;clPW@6Gml}4M4NE z8-Seuqv66*>}!c>%U@Ab3O9Jo+PZ*K=%{KL?XwVCgWONBV$VT}RS|U@bnuFwGZ@+# z3h&H;(GnxumorT!y#++QWpo&Yz@&G|q_>}saRS-+4*byOk0iGRY^Lc+FHkjQ{8*Kq zvuF{XsQA?NoX~!U9+zAD47Jf2?P7=3R1#u6Q>}JJiEtdXgFrS}sI+4E)NMJG|tP zg+-dAhn(MnjUJR6Qzxj>$Rp<_0GQ)@c(HIc(X*59`|#1|55%HA$PpB)bQ7Jk1ZQa2 zKaa*XjGc&|Pem9Il!z|V5*gGh2ZQ$!`vzNwkhGom;t7RIN^x$y5x6Ei!u{zc>V(m=*MPI2b}32 zfFd84*iGLzzqXPTgg1Y|M7yWOYNSF~LD3NurX}j&iPjQlNMq}t_D>hVUG1#uJhkvg zSN7^pW)((bnkb~6tYP&*rP9O#Cd+|ohx@U3gu?nJ{?jVFepqS?L02~VE(bl8{G|6U zUzzIpv3&`dn`o$clOlKM-5sGbE$#_r#MErbIh1uEExg(9Kq!z-)ekdRVN@-lc&ZZR zPJSDVp-!KV98J{=8Ccq37f^3`OHLR);~l7t!HDOL)01F7WVl^{)gh z*|J!_%JJ2r4h5D86e-7NJ`>5=DG(W$*7~vrB)lY~bUrx28Z|AQ545_NPdR%g#93>} z=?n07Wq1K#l$=3u-v|}5G2b@_?MhB(^r+FP*5*6x*h@#MNBOV4yKKZ5BNGdiDIRFp zQY=9ZsBmoAjXjg8Q7#eQo7?8Ebx2SMBu4+(f_tN44H_rkntvKPa{QJy*~@QlL^A_a z_U%vW*bip#Q)M>2%z5iu)2wBMV!7%xcLKNPG>n!pC?vrX6~i2tZLnaAoyE7tO|5sm zqf{~Jdly^>+G;&VZ@XiV_@an%E063KwQm=n6?Mlr?Dc%R3>%P1{v@EVx#Bj6@q4;m zqSn(pPE|dCb}o486N7$HLYgz59zG3ZUl|zH8X7lrgTJ%ojU6;mRwx({hBhowxph zeRlIxWc9-^^u&Un-6iO<;tTVz8IKM+@%7uFFPaYl$N z@+qRgC8{Gg+?DvAq~HCJG&dX?fB@nvNRr>+?Av{V(attocZTfq{`7S{OZ{QM!TfkaP^jnGb|eJasTGV48eEkOVY?lkP;UEV zs4dp>^3F+7Gx2aGfj`@uo%ms+G0qf9D6Cqvj979~^vRDH*g!w4L(J(eFC>$8DI&{6 z0;Md$^_JKsqHk$cbJCD3M$tI7);aKw6;7#Lf7T!h8R$iG@B|8S9aF2>P)232_&IUh zmH%kyjM+=|<=zeRo<4s`jy z4`)v$`spIa$31_2cZ$EA_Kq{e;4rV`I&(>VXo#WP;H}%~^_u)$nwkTLBqkAts7~Jz zW1LodrMKqDuxd>O>#V?*B_W_tDnJ2 zRZ^!IV|4qLpo4dRybA$E2Uo!>4U6mGZ%~a$&##Jm4YgiYY%rO0Ab7`Tgjqw?rL|yr zzY9d`>A>jFsi}~<-Qm=zWNwjhfReuU$C%@;;~;tdq&uR`k)ttO${OBJ0^1m^7*7Pv z?@(nu2{=xWvki>T!KyOvB6@QU>^y#3LgG7E>p|MbitZMt@b5kjlAV%OX#y3jAtSpi z&UOd=B7U9WEnzOLNJ1QO><6$q^TjPmUQzLux4UI>yeCz4$3H0lrSCVHl%w_8wB*2< zWUX5cUIr0^3{p5T(Wrs0Q(BHa2H1=IRuA81rgZ5Lg&=?UQ_doT8S~l+Kk=UY2h9ih z@yFd|^Hz%@89CE(x2pXzj*6li&A3A^wpVjj9TL{2*#i$_S_7)Diw~A*^bY9E`*tOR zxXw)p+QgtA;ZKMuKH$<>OIykMQvWz~;Lu(mEcJ=;SE;>ED$a;po4{hOrJ!bijCa$m)NiX7VPP2K6m;xFV zflD@nTRQopPC&xoHjlw#to{8jenG?RP)v^E&j`K4+@q7;%mWOwFs zyKI1dg5#g^3Mw|iVIVR``i^Yi{wcs~Plac48Fe$W;H+w)9r~g9_Aj{3%~K!IpM6?` z{YPUL#9s^RWd@2T^YKjW>H1+)lcwgRw@ACkdnS)?qDI0xcR%H?CKo2UptTi1bLi#M z9l^9<-Hshu%~Pj|?t-32y#r&*(0vrl16@E70SFB-rZ&XumS| zpVLjgDW;m#8r>_7D-9N(J6}Yr^VJxI*&Ha@=<~5P1|;nM8ms9VzU>V`GW}8_J?r|Y z6zXHDf6w#PF_(0m9yTj~zH0tlKHO&#PVlI?$PbGGxuqk+(SkTPy}?lNyv{{90KY7C zhE&dt1xfYas9p2#sBRyPT%1aRwL8nNVdfHNs)TFn)50??#8TLwespTq=Xm$OQng0) zlpdu3L=sgH$kk~Rau4k$X8h~?;<;Pg zRPUUsF9}{tk!uML3+ACz$BhTkBtUaA zn&6ol^N`(e8>#cYb(}z;yJ%2Azo)Xy6ih_25@9{V2+yE9`(ZzAZ7Y0`=QBtXvjWT~ zAHVkz`b!q$`GP4R$mm>#!Dw8zW+}jleg*f{4xlD&Kq9KII+W5{Y%mt`kvPiv51zqe zFq`kGw}~~QT@B|M+2y6fVqIs~NAG?61Q)0lvk)oqag)eq*{KGQ1@;&~BYBgJ`p<^F9_aQhm+3b1;GZCk5Sd)qV*AeAc#gC`-I6V@6^ zFEcRO$W*4+^%8-fHrS;cjj2r^r2qP2nDI)7Go5H!)8%C%2x0Hh_T2h8*Kl6N@3~%2 zru!Fz2eN?R<8pL3I@kys=T>iRT{|r>B8# z_}h#FZx$Hc>y5cUnKd7cIPj*4WkrUjA6{*>&Z*YA6RJ`SB?7n5PUdIac^{pY-+tK) z;%zzm#lEN_NPc>_-!ywaD9#?EV@LkXv%4_pv`WkouCUeNVh4}U>&o_`edE$N`!StN z%G*Y#WlCI=K{Fj3iz`!FoS-om+~j*reIpJ6_3YVkGw;oLn*`8_Mc!1Q9r?cg8>V?m z0n@j3ensfQjscIX#!q>lLI3_tGyTgQzaRe<=h-`t^iNaDjF8QVN(*D3kN28;c|zwS z-Xe18fVs%t=1TUcSE@HOL-M#2{h=Q-meQv&{54)rQ6Z{|`UY1_!z_f@s6>sIPNUnqF1Ppw8)xkrfrDRj#VuqkQuu{F&E3 zIs{GH{7Qxw&Q`)tzE)6tT@2V=&8IX)LR6g&w_eeK5db7@?IImuZW)%TbqYnz(T9Kj zt~l-+@`gI2;ht&kx_fLOTl0MO0g@Ap9Z{4R^Evu3bF98mr#b5qBda8)CWcHA`8Hs= zdRb7VkFK;V<$0Y(XBDlJ1;%e zLW({z1Otz7-owPgM-NCJSe1m{`LyKMAA!21lNS{am7@0Qzz#-WX@e^2SUXd`&3|N}^QmA()3y@O-(%P4u&6K$JJ4-3E{h zD7s(nT;W0INyC%InDAQN@KpM=k>Ey6r{HV#aRNl2+?mRZ718ms+!+d8&(J|_C4-J( zh*Zfinw}~YJhOa}m!GsuzMQQV%f2seIp`>-H%f@B9PSE9)USKp@_P9<^WB-B;d(GF zV#_j=c^h|I;mUY`XeC5*1mWQldvV`FJHej@nVZ087T3>{8ba3$95@J+0y}I2|8o?` zaZYIX~X`;Fj?r;5VssPyUT_e=(FJoY9UDcx29T z2D!?iFC4_fs(k7CNtw%S=g(t8o9FpnzUS4Q$_6hj8u!%4Ms%!p623&cIoN zqB@HN#n~anX|J^OcU*>DHGA#mdo-nhFo3?c6)AX;9pKHpSie4}aBh3<^-?#zxd@bs&&vzfan3jngz7~2AdSZ%u+MFzED zK0L{7>8G)~4$cI`r)DsPpv0ihe0i$uL>FA-U&4 zr5TXBA+F2AQt?E=t^blYCu0}nMy~58m1)K3=dwwn_J%u0jIokkrroOPrnY4R8@oZQ zkMEPjuVV#nTS_{SrXRF3aOj7wCHEpixpsCdc?*P4qNqo|s#|mV0am@G^iz?1Jz!&( zUx#Smm6nr0zHE_fuJ5{kXbG+KNmrZURqrI30wr#SOl5s9#(X(E?(N5AL5!1hd%Vfj z4r;DN-_9iYb&T9En~EBnIzOG3x9+Q~V*Bb{!cnfut3gIB!-4=|6vG}8M;*_}2^_L5 z+a;Mj)L90i$%M)}Jq2Yyug7Q~-*-68kZQclc0KKPez1suhFG~xaSrcP7XfK_qv~x4 zuxS9^ih9luThsOq4ljxDllMMM{a(jWJ-N> zHzrE!woI|4amJn6ZG)OCFI2WI10?3tvP)cWZdU39RHKquwQM(+Z85imqxf0x!b>BM zEH4YPg7uyB4Hrzm_d8?DmgSd)y>xDy8X9UZFNv45q7-W?5`R_eH&_MQR`~YcGi4p* zU{r*y^iJk`EdD6fsLJyR;K{BZ7vFt~d=n18e~IODvYozKvPFxM!sT4&0`pXDq-%&~ zAW}6vzU=zdIC5eTW6ZxGQBF2bOP6XNwoW-!^>?HrZ2H3bItHYAS7lQ$H&UL~!2p@9 zX1V)4<;_vPU_kvhz%?xE==7DPPg%M5U@5*xF`p25H%8o?WW(a!n6zvCgBb?~NdP}S`>aeq3ct!o{B*?Abs|Fuwa&DZU*LSYDz%E!DXavpt|*Z;Pn+Du4o&Ix*V zIat{`e2SPt&n;M+SoZMYXdd!F=<`rW1>XEh z!IYuxq3WSFlM0iF9~@0RiVZwB3(|Ud#Ta&ec!pPtcU671%3z2^LNnL(D5Xpb3uiu~ zG%qi=41NeHYNisLp)xnjWGwOY@y~g#JHMi&f zS6FUJGP8Yg>dH1d>bPOoAaEADs)$$0$hs^0+BbMucGQ3?y@mVpdXlmE1Hneiy<5!3 z&EBTyA-+Od;+W^x!oQU*0bMNhE&Z+c)7!$XsdSCrtYz-U%k>U`HVz}>7?vJ zlsW?>KNhfEba!HFFB^WkmpneVN+p%9iyCIs^YS>@+1P z=Ik478Wzl`ELo6$sDsv=ZD@a|q=@_WT|ZfFC)sFl_*FeBMnlW_3{!QF$?Aw-5pZ2+@HC>kMcrn1 z!)|}$_v*St1a$G2v^48s1|fKkYfg()(_8N-MK!rU$hk&dEuP5E&~IDd{=iz7T(XAz z){OT~r;XS8(u?+P#S~V{Y&B0p631#vzWf#7c1dwGY~j?$gzPEro49Ez+f^)o>tF9k z9BFywAV1c7w7axtzA&N_xj+4LoFJcS^*H2~NOlAGHbCx2b7zCZUW6~cdJR3@PERf% z7(P*pFq5!-TK;udF0%A zE18<(Mw{TxJDRgjGDq4V!5A+W@Mhx(PKiIs4wWiy6Fn((9E4e4aZQxdiCjq*3=dj4Uy0^O-T+OR$YCW+(VLF39d|CNM}pcf-IWo z$X?%cf4iW!x?zlYFJX9Zs&c9@bt`|WqitX6NO?7m;Wd=2Ki{u^;BY$4s5cchb0D;96E51tE%*&Kztz&ViFKupw|x(w=Cwg3(5JB&WV;D_85J% z!1nA38La4D(fQL(Z$&$9IZWwd8S{zwwLhs*V|2Psx-fov*|h~c)|sK(7$y7bak9N; zs%r_fr%h}c#e68Tgo~N!QVojBFyK|XlS;C#t6VR?`}mfPo#W8g0V3(~X2Typ)cHU*_hkKZl}^jOvAYw>61*9-boWcUizU@NhtdeczBKK=FtK%2yYw)acKSQdY>F0rM9iFWc$LCVu>*)eU=~ZA@L?bFp zt*0@2@quHsRl~f?+-yYG<*)dK{3zB>DK?h2l;5X1CrI_;7z&m8l%PMmPLCceTh<3nDT;$q=3PhOvBuA=>$I&tuYuVdJbk!qfV+A*iTJQs=W# z&e-+G?SeO2gV|)2@=EmutM|ZVZC=0k7U17DUadKfXEkH?wj6IXFMky$ncfB@v>_`V zHj%${+PP}k?w5P|1^awwUi*0y??SyYT1?V#(TMb&dY_wvosjiTefU&=#D-%Q8)z#>{Gx3j}*2` z-I&&=AzgW)c((Gnr{imt5Xu*4gHjy8eA2Wtv(#^7&J?oQ;JBTgo>x|1Uo$U}c`fPh zqaLN#@I~`gM2Ynp)J=Q?2p<9l)nXjF79ub%RZ`#F=#Zfz@L_>DJN68`0lseYF}OQi zjjXT*tt-K69k{IaSVOxL;v@tobBsQYZ;zmDId#mn${R4>> z-M9lIeyl;)4B&E6H#|7&#d$OxvcYl*GlUwB)wZkuDsNXCMVVaLy1mQE^S0?f8n$pR zVl~+}@~^!FaJ1D4vH*!0Yp~zk4*BL3b;H?PEU}zQG1&bUmxl zBX`%$NpU-gO~|>reS9pu^oavQIW0ssC?3|_*xz`=tHd4jR?}VfDz+z#zo(7n0ESmM zbR?);l-3ztq8K0EK*Q8ER@{ChkPVDq1s-9!)199PcKKc5*;MnTSLTabtu!U{<@8t= z=HF;OurFVZcw!#LVCC2lQLU%Xg2cQJ=)kv&(7e0x{Pzf7>wA@qdPShVtyLve#IEal*+#5RyxZjXC2=Zbvw2ynN-!V|ntoqaCvv;E7YK%p z3>Yn{8VtId6^+7XgCw&O!guN|Pw2#Zd=|6I1=IdN!%7nFvT1x@sy)}qFZZmZ&R0v| zD>%NjJtBS2EojysGE>v{;oK6VLIbCm@DxK8fkS!BS8VKb-qNnhL)Tx!yl& zp)xCIV-tOQL!pgG-F+2n(S}#aDgrq-pYO=sC9xV-{4`p+cb>}q36m%9?tNe1Qx=Po zuyNdAPkex(V>wC4oO5-c+wvd{Gj{PQ z-M~aOojaR%>mpYd+qMoysyE#adP9c=WWg{OVY5ZQ<0~pXATgrna-vJ`iq6L*uG)y7 z3KsGDk{i)^q)W`{H5y?G5$h#ez~4XncU}WMGUw!Ou}7fuM?{m*pbc@tnTJXINDEt<^wZR7TB>Kx5`2dsf9qL zaNnMn(Z37>*k^)XyA22IW=R%~RruBy`kg-GZ7$D-$U>qv3x8Ju6Nc{NLqcYfjn??7 zD-vAYx=;~x!@Ff4>;>WEJ3SJ?e|Ia z9nf|1w6m&4M>_+hHhl2t>$cAzlV9ZatETZ-g8q~rAx2;NuC{aH^WRIk8O|e% zx{;KCszga$yz#oN?;BzZL?X%WmdJlCde*$3l_0nqH?`fWT`Mx4 zD;NSf!#^P%c-kba{~c6LHKY}nP6lv}8%e%FnlKMRF>0^Ekkd$@gTp&%hEM&l?u(_I za9WYlEFL`fyqr;#TyziiNLK)W!L%|EWMZjoqq`G_cX|wbygf_pT@B+Mq=y<~1dq-) zlPVk%VateYigB4?RdBpMER(BW96~}uMg!>*LrslQL+j$YCP|(5`;gc7_Rt|*hPy4n zTU&M_okmHEf<%T&+wFYbNy%Mrsrya~8Yo|}wU~d8X>uI}kZi+Mntw~{(}S4NNBF+> z5w%dWke{!T`jfJ?Ns(S&eM@V|gO&O)&K`4jxC?MQA8QJ2Ls{EyQB<1S44}w`;85{| zgs7+|NrJzwo&FhpoU9fGB7hIn(e)O)o^O6wFIW@blG`%@!MLl}2Ashab3_sa9Xdub z|F93PawVXeKRUce-%!sqYc^tf0#~#uz`UWHSXq&y+wU4L#X zrCua~UCrDI70E`lviRA(C4PcC_RMRyW3q_HSv9>rY3igc&*&EzaEYOB$ii;GuHXYNKCAXP}uogWnwfyC9ML&r|q7&x@J zYU_FV=GK;siQZa%Ny&@!ooo>0mT9|8;c!GixvhW{+gsE_lvgnQC6@OZVKZ+ITBz5I z4m!K7qX@^_Z4cZPVWQSsESWssg2Ff6sD6Emcrd>WV>vL5T)zY-8nGD>C15>qw;@yV z^^rm9*5QvWY5#Q6C1wvd18Pe{xcw9*O|jf5^~q3B(J#aAi9Yz`DS|QZmH_3!H~0yh zr5SmsS=59+VKK%*+gUW(C>x93H@#iBpJF})&m7S3Pd5t1|AF4CtKDPS(fyA`ND3If z@=%DRBLQ~6OUPS!iu>hu6y-Uav)*W-!u?+4lK&qXNAJ+{jiGA-FZqX_9YH?=krex% zfZiAlVK;dL1`Vl2{pU3(<0vcM-wZ80X@CCo|3TP|7k@M`3$}97C0C$jXQHhie#OT0 zu7@lbtv zpD%=qR8LUZN-N@o=u_m>FT>e&vpZo{Lo`VJsb4uMNb`oH2 zD~@z~jh)6Xw7tJ}!?+H;iGmyX&}G9d-)@h72KmaSOppG!c_*e-`YQ2>j+HzyK0Ly2 z{m>E;+IN)4OucqoMG?8kqlABpfiXbvL=#r26o zGwfN-JJ3bs6e;5We_*>lN}Mc3bUD_VIsx4RY{YA|sD^hjNxr^H@`*GYOYc>W?HX;h zt^Wp9_r@3W?E+x2SwxSf>_raRQ&f|e^62jh*}U`^fYl(s&De1>?nb)x%@2O~5_*bg zLwk#}p)QgrZ`j~pD>8fraxz1ITiwj1@{%pOaI||0Agm{01h(>uOS95-Swrf6hEebc zBK;AK;Ef8EkvkunLeyvGa1Fvge3s#}XWhy8OZm?4k+a)2?_B9V4o~r@D7Xm9k^#!;UlTC!28O(uS&x6 zEWTEHn0l&D?E?=!hn=}XFg_>P=B8oC#?wExa;E8R|HxBZ)eFba<~n@*;8~PGDgri=5f~2ZX5~+5$4*L&EzU;;#_gWv2%)OKr0q`UIZZ93tL!+!>lMJ9* zV<9*0(YASCT*=%kXT`cFPzf6zp%;r5fSH($g)Inz!KR0haSFG$?vcL1T9F$+OTHr9 z!a9C~OZX-A(09o#VhV{!vQ4Bl^t`o%2yL+?H2uB*#^xS$ap47d9?>fDE%NOhPm==_ zJ9)7#r}1i;lIsQ--EA-kxefRKI}c?DpL}md?|nd-{LCD&qk9;EJKon4o$p--+B&|{ zOp~%|DGnWV3H#3mBHx+uhpa8N?Mk`3b!|1&SsZ$C$UeL_|8f}5gc0VGYc`5$G8Z7{;r%OtvpA2UB zV*3b<$s~*%=xFNX?E#C`ziXAE-6PLr=0_@0 zEnG`4zD69NRWG)^Qt;R#>0yeE=P~>-Fd-5>Rcp0YxM3fg*U=wcUROI*cK)n;oi6L0 z#!@YkR~AfqFTx3WL`U07J`6--r$I$7O@}*f&u5SbuQ7y z-T1pxA+IanDX}Dp{NXO_kGVx6z(zf1`b4(0440}OI~CumG7G=Z7EXGDyu4uZ04H;| zgoEdN+N6CdVcpZD;B!>{^K(r@#l<6SIm9=MDJ`ff+S7ZTy7ypOp1S?OesSsmiU-!N z%L4~z?dT-T%zJP+b5(HKtFec*tua=#fL?6Hy{ou_4IRRAPHR9 zzUhzVShL!g?M1y}WaFd5XNkOm^j{wH>WG>th2sLu8@<7tbN&SGBMN$fikCGUo@&Dz z;1VbOlrjM|=kKrIc%K@b%6`DT&KdM%+ajqXaKA|7)hS5M%+STV7ONKt&4R`PrX< z7J1Lq9K-lq&ff0^_o4+UY#!JjN2?bY=q>Qo%2SQt3(tKRQF0OpJzFLU87aE79-EzU z5Hjdv=CAfB)9~+e5pP)ba|$cKJTK2Txqe}i)n8&fx0qcIeW^R@2>qE+gd9&VbgmErpkOxbFClk}V0 zx1S;zWyS2ZnthVY$uN}zS+^jy1sS48@}{5*i}+HSMogQ6ltxt`!c0$U=c z%&?8;sq^o}^wW!BVGZkKY^LOfPTiYRRU#od3Vd zJyJEbZxuFOjBU`K9r`z*6oQuh&D*$Ss{Wq z_%WO($-j|15W=0AdHg?u@|K=Y`sf&rct2ulGGFkJL2~>*nqD|Y)9O=;EN?v1vU5!lLUy@5GHhwzu2k%8o-gal}x?;5vFkx$N9PVX8$}dY=`vlCA~eHy#cNoZP)S z>Qv+kk=#=cX|M!VT*(uCK`A?;=Wg*myaQrDPk(QMHL`vx=_;lNMWW765UJb&A zjvdljouLQ%gh@bgdCljNDqq67NS@rhT;#Tqw%}zt>bNI!c=C32U(KFF= zeo4}>yoUk!DM>RxKmFqYjmDGBFCJj2r6;$g&$ZZ&at6L=u3ikodgv=%?QUmp>o_4( zEY{|?9U-dk`+MlC#PF3BnIEz;tSZNz)yjk1Y-u=SOgH}U9ujA^jRGTeITpMme2Q~g zopg_-Gzsfr?y^Sn)IChv?%}pXrRIh?xD3HDH%hBi%!KnZ^S=m{d~zq1JJ8%H-5j$7 zHch70SLx9JsX{TS>}LKBGBpXvh?c_<6_QVWaTIGD9_WUs2t1~kG~M7Mdpf0XzV)tC z>igdZfaUo8cz?QWD#pN5`L9h*zik{7l~Rx{rKP2Nic$h1NY|8xF-Az2 zqM)>ZbcujSj2;^;odfCEXc!VBhQP+go_D|Z@7+6&JHK&V=lMBnsgitN<~Ui&R1a44 znf(}+b^N}FcKr9NIC0b2p|#@;wD|>=dMT*p)`f1WMDL^=h)KWMH=6Iw3Vv@UAZP7> zMWTsVxJ5AA$Sr(!?xB}qZicRJX=1j3-Cl?`NWOI*)PlkGI~4YixIdug%>bhuvty z4a?CCl-gY~`j(oxVM(&s{5G2u7;N%1Mt$Zj9SIeQ4 zS{JCvci2}Ui>lVSFVY?UoPwMbX>&>-j`H0G z&$}?W{#+c%*j|;`nelsU{E%t-au<1QzGtK0cw;(MxBs2{TVnCod-i<600lp!IsU_O zyb&I96li&zh;3_dxAsb1jDPCPXE5~~e|t-yFOa*s$^y{++odf4fEVG7mMdI10K{d^ zvYKBAb~ikAeKQ0JmeXD5-eFSG=F=v;_uPP6XT8ofuaimb*haWz>Wljz`D|65o$ysT zY^8tW(Jb&~Fi|GXW2$TpAxc=yc37deN7owrhq~Tq+5uiZ zdRy=`jcsTJcV%ejw4ywwk{Ri+VM4dKU3?%rsM=A~b!-c|QeZMy;2~XT=;SD}&8-z4l%cz`Oj*DU}V=zqQyYv}FPJ zJXO_QC2quRnY75C1%xJPwSWRZ&L_odR&TzlY?KcVjeDVIfN;H^gjAigpv~M(aKcfm zm-26FeziyP>Zj1YeGQwMe9u9(rIBs0!1mU=P2ShWR_;gkw;#soe|io^nXl??rTu;g z%qeix?9q0?IR}`!jCf{nuk0ttxmHIG{yLDrq^iCZ+Ifg@S5${iTRg6Nc7F9^8?QYe zy7{NU#7ElOK}|RXh5c--Q`UoRH^{fVqfj%kSpF&bDs)y!j$xfw=qnBlU(FF#cI9pI z4U-#(3`qHo!e9_rnt-hSram)lAa(Tq0l(*`t2$wU>m_Y)j!+ps0+=tXe&lwN^9jR~ zq5ggPb`P7HM#DQ}lk(k)gCi^>C3ct80Hp`sM%VUCA9g6JMCshF=TvoUz=LZYU43}L%>q>@%RZVX`Lr5Pkr{a{0qwg074~f={JjgbeXYZfe zvI+DVZ`TUOp=C#Bedj%o_KRHmNtw9@yZ*?A!%rG6XA@u-#;S#PZUmt8Owz6 z%_R4d8#d;-o{0=Ya)qHz1ux1S^i*xOmUeZKE-QB7pUpwd``F2gow2zLS&w>F!d>yY zyR@IDH!m0A73%1(*hZ~v$#0}e89SX562fjpL6@ZAaaTCAb@B>v%*QnWIzi%KeD2@xh?T|GTBW?;^jE^=ZTpk8ANW2KQJ`ioUM z2e{pvk#b!8{vh#%^Ypflz}4P^?a2xxZJ~2*1A&7%>9(;KjUg{2Mc^See+X2^H@nzg)2^>;j@JDD4jxNKr!) zx5?tR$z3bK{OPa2Vnb>1iAUyx&I!`WRBuCbmVcVXmeIR%)4F5kt(M*+GfxkV<)>9j3sDXyUM^cdfD)2LX##xF8M1jNc}X2G zxj>T@_k+42*w3f{oZQ~HV2+{`t?pX{iuhZ3zd1Q!CR_t4haeA+)-@&!H?%=K=M!aK z$&j+g{XW?H>;yB}xz|7QKBGj9q)Vij-QzeYWQ{WZ8oF&A=n=)6(Oa<=# z@yVjd7bBgQj$)z%{$3RyJqEf~S^M}AOo=M1GG*K1w%$+Xg5z!a289RG?!|Uqn*o~LEZE2d?INwm8QiD4kkiNa!9h z;p8N<{Xt(|G~B}pgl-HDp6(?XJ_gS;W|!u}1XIdVoXso`-ntbVNG_EH2{x-Sq2iqL zz6!2edo5rz`YeT{+j0S)L2qQ8&epSjDmft#?dVj^P8WA)_~Xuu&W<;!{Q(E(O1z;3 zjj44e=|ghFFPQ(Rp1@O@7F&vgnQr*I^yo8*f6pVKKM>-a0@jz$oTJ=|-5-lJh-b(K zC)uv)UM_s4`d(=7am(NEnPo%vd2j|!1cnndYcm*KeIv8}1QmKjRr%V(d~RZZu5B2u zTRn24s=(n5@1rX*M(Z0p6hfpfs-J%-$2}L5K8Gy0dwFwOD?>)Z%W^a7C5FUajcT0z zTSWeoGF)?B+_A*?aPUgf(E{q@(D;2Kq+x!DZ>%ZcoKb0+QBPa|aZe~fM51;Gv5{De z!Tgw!ST>Z0NJ^lbCI?)vjkBXieYY8Z8$A#fSatT+6aISZ9k=ch=y=C`1j5;STm@ww zNS%n`@hj5fylDtU5$7vc-1OD$pT{x7UE;@=|Fl;vI~Kea?U#LU#W!R-NyUsaeqg5R zyd?3VCA%H#NLylj$3z$5L)RHwr35TZ;oOdO%TiK$9{7zemAAd{h2i^_(fCR|f3*?O z7K}|`2HKD-M&#^PZ(V*@?6z8AyB^5PacW+7&LD22MI>9&MC+QLwmC5Cv6_=FgU@VA z)g)(voxP)sa@dsqn2{>>-K*4IOcJr_Uj(X%`CO7l^98Itlv|V^nDUU zK(lsk7|`yOG_zFR_*P)u{n1zJG2CUDM5=ezXD}#SuWV9Sr{MZzo@cV&)AtdDHN#v4 z2qL-bN{nwF4GjSvZIsI3+)wE=+`$JdTK?eV`>_!Tojy-ApWS@0xlsnSiaDhl$mG<* zXm-n+W_6En&{M@dJ8#$_99!jISHVs(xhCGZ0_b)?x!Z8=^3yI`5UdwRBQP z+2SsMEB{mKJ$Zx)#8%?$K5x3$qOZNVIQ(^P;J55W(2s2KxF-=DH;G@Ff zNhm1d-7?up>+;f}k zrol{+q6o89Qdh$`*Q}|peBPgV9p5_CkEVW`vP6ac4=7*#f$X#oNu5%1S41fSIWKmv z5}o|lmwa*v1K~06y%XwjgDJ;6Lb8|5;dhe)*Svblh`=zWc{cvSPokwJQw`;n-d2w5R43nocb?u0wiF+l z1DpjKjCsyZYC<(VYWqumn)EE}_ck0FmO^v^+E|j_*4D?#M;a1=4=+Wlew z^eMr);p0@AJ?Bx(fbp@#e(O3)T|)9_vrVPdlHA@QOh@jujNA`5VYVcUQom-@ZJNT6 zT@95mk3X5Kb{&}%@2khO)M^xU6nWW3xp?{Mo5>$+q{*Ao4C;PyiEWpJfKTudx zT`+2tl~-m6lPAflY>kP0+b)SBvpQuC7rHj5BFzJhWM&R%>jg%W1nholy+T}Lr^#6c zhu(pk2PnIjUwR~qwKSiVo#`c-t7}Od6pK`hs0v=_vTeb=t~4YmUo8)>&|T}$*K6zl ztZH(*ZHi|D_Hw9oa{YR|(hvUC#3z+4>t&yKB%hSHtLly_R`#DQyG(ScdG4V~0Y=Ft$*jMo9-MJ6SEas%`N?8kP6=1 z%EZ|6T2m$M%4gdvScZVS_QL^Z;} zFw5}^&E*Fcrf>Na){U0lrr-*~wR8}6cHmpJgB4b0Y~7<8e+f2mCD+ZH>TT_8Uw)a= z-j6sNN`2BPvR$!3$|>cI!9v5H`p#BBX=*KSKUFQi|8G8WnvlJa1=v*RD?k^-P~n0XdN)`N(qICJmNib&h4>Y_sFzHE5iM{Tl?{q!fcY3mx<_6gF**)RY7_Q*w}NsHfk=R7SH_aue(RQQACd~J^U+jo1#RF* zkF@{xb(Ql1@jaBJ$qr$Pmn^Bd=&z#nQk8KPtA+W`Wei{?)>NQE!=&tMXaQ-?ZbOR2 zI!yg&3|h5okm%|PlAnV014nN~o3bVg&|)|JfMOAgKv-E)8}D&iSHx|6aD^Ky2o=9%E z=cS6D-f4UB=g{#4EDituM2G#n;^M5m6tCS^Bfq36p)ezz=%W(*knk!$VQ+Zzi0!=6 zyyfGN_i_DV_p;ZFrQ{t_g$g(_0LA5>HdW5sH}LG$Qp9rM?JDf_Q>dMx(5%1P!&IIU5yMnkrzrGh_(}-A)AlljEVLtz z(^|bWxx6$`Bt4skIt7t9D{O7V_Lmdy$CdcR^yG2P>C}Dp zJJ&s;rjaY0jl{VXV|nqAn&{)vM20U-YK480nSMMo##6pgB@{KeP=h!wOkyB*j%_aCi5A7 zNAd(&Sn9z5v>+ArMo%?V{4er2$KmxWok~MvO2VAY)p_blqIFwpq>~Q_>kOdvyE+YA z0`yR84@}wEQuNd1mXu-56eQ|x`58=g~LmGJc?oB^_l zr4mWE-ACUV-l&NX8;h7|*$%5-X{PA21uVPY7tsiZ{nLP<$>W{3G5F>xgA-_vyNV41 zd~Ay56Yef`(5R9WM#1t?zp8&tdtX2O$Fp2ZvUE?VR;+Oetn=SE=rS+jp?%N@rO%c8 zN$NLm zPaa7L#(kCT_tsTsD0NJqFnm!xw=+MW3`GhWg-Re-KB?3tuiuQRvz3!ZEwe{hF=~HG zPI*>RMm_KMucmE(BM}0fxM$%ACIq7DE0O{qZR`N^bNZ^lKhXxs5vevBe>*mjY|n>O zGq=Zrsd*E5Zd}61f?upmDOJHWhl%+30!lD7eG z)WueHc*FcBi@Or6c+Y?80HE(B5i#PD+5$0Zfr>^uFAa@I$U8C0W=1zDSV}SauZCWV zZ9r~OgbBtjF!rWYn4hDsQ9(*LHN8y<#+(6 zAQuWcS4%U_W+Uql8m$}>EeH14PH48b@6hXnoR3q|fLg_pg-*t#!rU+x%^b2_fd4h?wz0%fGa?JN`;Ur`wB(1~(YsUW zMc>-A0h0Q)hbWl;IrHh1t1crk#m1wO)G0aJLr+OnzE$ENDY3CQ!dGUuq8f5{dAh?A zg<;nAAFen+qeF-xuS*<;OD#M-Q8s?yrPczU>DOPX-ByBnOxmWf&}x4hB7T2b+}O^R zodqqaMD@@1-PM{f4SeVN%Exo2$ZpwnuwT#kyM=cRZ9$GHv4i66xBmUB4)?kq2A*$I zIABFl&ig{=q(QZ4i6UzpCV=03%jtq*C635jArUhu6 zF#5{cXHxi4J5oMGYqt~eL<}VaP_$-j;gzz((<|Ca+trK5&M_`A`cV~im24d@k_*NN zC;E>CV(8A*e4mWV3ORp@IL^-xBGa)Y1$%K*nPx(dZD_|9@#&jD%AC%+?Z6)9WBMQL zdu=AsXz;M3XJIztua3O$-Lg=<6Y%TvjU~7+w|RL`;H#51mHKoiD-9QChb0P-wp}y` zqSl$F%gaDY*;mzJHs6x-b8`PV|@-CBgMLUL@S2SV(XcIKG>7B(b(bPWGxZx1#N zvebfEkv-q!RleI>MBL6A;Rr5Nl|r_6ob!}|CN!=MT3>%8#7QLctEHCvIh;~V z?zjFIByEkBI(&mjP^neVwu!6xK>|#+$qFR@TtF>W!iT?#B(na!f5n>RIK!M%Q9jtB z&j^KDOa8s&3zq7O5UHDl-9ne8uz1<&?sAUMH72bcX}P~-N^4|tkxh-8J_YSr!o-B( zZB6iIc-odzhV+Qp)YSKbKTp) z|AX?stO(G{4o$S*epX6So*=36X1ar576%oVGbC!}pDke)cdPtt`uG%whlklCt$Xm$ zMj)|jLzU(s0$rBRBUfRZxIi4~~G7X{qv=8D>OJA7DYNVazb zY^{KjOd9ngjNw=tCin?(SB}l@WHY?n8E#8UZ}n9~?Ogt#fazE}d&5rNORkb=gSU#D zMGbOu@_aI9b~B4=HJ2+>8d-a^fVUqWHvxTun<88UvrQ>H5%U;qy%#_dQ^|U-q6QF> zQ`!3Q97LZfcf)=I<6P>Du8250JebOnXrnAi9$Rp}CuCmcP?-tZa5haIETVL_^;%^f zskUp@&SMOJ@ul{C6Qa1S7O_Pwt7GZ{Vs_q{wk zE3bD^_)W<4r;@~0{SIF_G{K_CyHjevD?fWg9{D`Evtai#jze?exH(|r2@lqzBu1!| zrZw>BfZ#qcutlL{ue*_X53tpK6_0C??d07_*_$Y={=*aY4@Bst$O2CKd(pG|z=KKg zg14BQhTyPBW}!Zcwg{HRV6iw%$1nZ%^6+3%3P}NlGjm3ma|ZmmX8ndpvG>eRdzQi@ z=?vHoAena>bDzm1cFI#}H9l($-vVyy&ha?P@{;@9k#I_7(52WMl9l|wE0_rwTa2wo zemD>GX-T)3!gn6#+y{FFhVN#3UJqov1zt)cmf9TE3{!NLP2X3T0d7V&@%HO;5xG9W z5Pwyp2bRp~q=KhoK>@-EM6S8r{?ZoJ0D_{|@B#S%g!@dsGsM*b!3wUb_L(~yKIaeX z6naUo=*WG~S0!;d{jYP2gVd(aM$P_slbSzK#*Hk8XLVftLP2?f)Fo9_6&B;__LDvG z6R0-+(1xo}%qorWeT(npLEhSxWUNiEh5Z9~o1UWhZbIE4G2%%I?P~4L)FH3+DG*hB z_L`TwF(1&++5tGenFcD|v609a`&%M@6DV*kAqBxScd)H=wL=>J%*TISYCdp1K`Pw8 zBI4Y^$X_-CSN~o~SgHG_5-&Dnt~n;5tVZ#5Z?8OvkD`j3+mI|G%Hc-`n=pKdzVN_bn+<5>W72`ewmZ*g&Eb z+K*l)vi649LAO!=a)-RW=krHCj%!WhOQm<@J{}nEX%Z{AOzV)>Cu&8^MNl8hPxkrv z(dW#b-}90I$FVxxT{4eyKKED_rXm~8x4$W^L%k^PwgMN#A6#oGZu@6=zV_nDt z`}~y8wJ|8(70K}%)$}$~=?TR{d$)M*q~- zJVmqNu=!1keCz+HETdG5T(#yeM$RawKAzC&1h}zmCy9!ga?l30pHsc^`!Fr_;&h0Q zSRAkfTL&DyG!)wC`H!mZ@B{XMbvyJ%0P4io@4^C()>RbY6`eymq?&DcZNr{g=Y`)| zi0~AHESbr>vl@OzrmsIo-`xJnw|Pd%N#rQru?|b^S5$fAv~+HHR@2jof0Q{e9%~(l zRfo>+U0hzmq6?9wHlAIVclao3#>cMlj^Ba>{YqrpRn+_XR~6}7JokD#k4hGf64-_a<4-n&k`;4;cmyckzfv7h)=;OX&puKITq|| z0}Frg7kr8%pG!u3_~u#|R+y2`+bk9X*?VaC$$ND zn<@UHPmyq4zxq~sm4U6h?PZ2|d~mJoyMRS2EvLR; zKXkR~KdQg{z-RN3tIe;Vn9Q{Rcu;{>yKAgj8^+mG)c1Dx#{v?mGLDdTW<`0@!T9sD zUqGxXrwvUceQ`RXvvZnXD?x~TJhfACiTIt~&@Zx)rTG^=&h0?5MzV%|8$9mAU+?G= z)b(3gBX7=*$gyYLRC)}0R!a<@M9FtI2xo5fQ>8lrNLt=CpqVP$@3O#icw)t zL93B>gEo4Hju|n_V!1W7HeF|Q@}*s|?3=cow)EQi{yVm(1F=w&A~77a*n_S{aeFCS zT=KeRHh#Yn|0eIsoZ8uX`#A72F3j*4c$V{dojY;v^BRTBqsE%HYr*l|B1y!1rTzNB z->g^PSHahq{U0;mXKG#-y-%nL6F#n7<0(3#UZ*^|Xn&o!i`{V$p`wOg20`1JOvS}B z6Rn8kr_LSIW804({g28j`Ap{x=q~^-Cb+&5v1p-d9vz=aJaqK z+R40X9p1fjOp0$YI+XR)9xvasPv=N7{gx~P`?gs3j{>kG-ouCX18$rGzjQLTx%#hm z-aw%xs%SuWBxZ}e19&Bvzon#$U!lsYWcqY{8qi3+|GEedT;t+V!w1)RSkHd+i)7A@ zH-;s8y|uW0o98VYA9ci9EGavSV7Rf%dzaDyyxnN@Ima}UqXYo9skDo z7o1THAvo`xMe9?LYf7*5BLRa+3v4!f)RVfyt4rCD41U{TCkkmn z-sp+RdUV4!VI%3|<+9j>M1)e%dp#ey0{)p)ZL)lee=g654?FfRRpQGnvSrVz>5iJJ zA(=W{mA_6Di*@!v9tyL5$lE{}_xnF*av_WsllI}?sRE}@XibzYnmZNJdx|df2wXi* zc)XL`jhJP|`t7ksnc3sh&m+444gyIwP%;?WD~;87-S~Fq!^WZ15^r?a6fwjtZKs2M zatn7LDb5l8A5}}Dq;YMMhO@xiK%Ne0Ul=z-e=?Jv4E9*NaUa?oxT0Ih#^tT}CY-9e zut!6w{kS(xtJ1?FryeEK*KrcIB6@X6M^&eWZD{}+()^M&la(41#v9ASHa&zB#UFZ= z4ma8P>zKJf%LX%=j4%efOqZ?;6!OR$hZLX2uodGype}`3+re;|4RBqe?o%26ysxIU zVZ^vxSo^fX^0I)tCi7cU_w%n`dfwDt!`Q3Njh?}Kwh)O@lGbZcd|3TY4g*C?CpTzT z1jx*1QgI!^3wVYz!=sF%;5AgZjY;-q{Ul@1q!QL@1pCnDJr(a|2$6QZq^lxJ` zY3ggYjGyn{Rv;#54*T}_S~rkUjr9lU!YkQzZ7CR+y0~)@xhUaPe7%pw`O1rah9@Bb z+Kq@9_y zn97LhWFfANDsL0p=EkhU#w!dyn6nyw$Q}QT)ZP}nl8m`_SqqWn5aAX3l*C+)h)MMI?QbD4t+9f_N45_?=O$KXcEiR()MiQN$$ro z9(M#)RH9y=HgVGv zUmZv7Ud50N6`VwdvkDdhXx}^{w&8TQ)%Qvp{%jLfMLT)}aOo!C>Lt{c`ul%110Z00 z&c681Ir~}uln8CJj&!s4+ZZQE7DL3${X)v;85%S|W;C=`ND+w5K7C{t@c4Q(XZ;oa z9ecUjn&u0GHirDpWs9Z%&8{(NMk*fC()9+E;41>Wd*61|SE*lRIxqv`&(WYN^X!{{ zP~WsCHO=RQgZ|)gjZ^%&V!uRypj*)~eJSV3iBP%Jy8&~r$0)X%mzQZ8DnZ41_~N3{ zf{JtTxnurk692la?+sbJ8Mqfk$&=qJ@DS8bw=2+aUA?pw;t5Kw(!%{bgYQOUcaL@0 z8fy?uU!_)=P+ufg`z6o*unAQST`F3)`Ux&S#}-O_{7q@tmSc+TWH3u6${0{qz`@B1 z>zz?_e*LfO1Ale7Oh?CN$tDV0T9G-AQnd!2DAaA5D*`xDLE7HHM(TLpHApvrDJbd0 z|C5U0H~3v6pWAM}Hz%@JM?^QbN_eHY2aIt5(mmj+PFS>Yj5j20SL zy8o0-yTHqdP?BO>OQ>xtfc-niepqW*ms&{fYw=_?*})3szQc`W8hPw-JR!L%Jx-1A zetByzhY(1<-MSWT(_dH{0WWdqSpTayx7avazl>VUOr7)e?!XIbD*Ya!bnnF`yY{s5 zEDIC)XD9)3SC%LV*1wNddczg%r@~ahMI(2Xt-EN@c6JJO^Xn%3uTb;Kgjm|q;I5h& zfamz<4nBM|F(jyodv>S%nHRh%V1ELoI}sn=Ef(Y;F!)4!gg5I{ez!vbj!!v~qNEL2 zta00{Cx0Osf!5vEG7iJnY=YKLx?8kAz-1a8G2%A^rI~A13567&L=-G2>Zv#Uxx0x~ z?^zRuGNyhokrF_>7Ltwn{f79#&NMhUfSi5{4B?M z%Tde555l2!D<&*rKcSN8gy}@mFI8>Xh#oday7zKZ&T|N?gyW$3QX*a+#5-#GEylQc zUfC8tQV@fH+#URns)2&N)BuEu&du873tQKw{zs+n{2DwWoJZGED>|R@A5{=@6d60X z9k*LkwK?6nnk3;5$f^7}%)9a_l$)kqLB=UQ4NGKqe#{Aj3|GD){h-8~-a|hUu?~(E#@^g)SZe zU)Cw=gE+;v&-rex4pNQ|r9*#+yMU8#A3FLo>{}fDM`Z-dA#2$^7(SR3?AElmxO0#9 zD`NZ36JA9>pg2hw7Ek8YTBjM&LLfeO2b}a;k4;-QN^pOF5{tQ4xU6w|l^gAY^d%a) z@|t{;*ZJGN)q)mXM79t?(S#Yv;$+AkTNE{jFiRKEF33_YAmu7Nc6Td7y<%Hwt-eHn+$McrK2`9auykDXT_)BL3MFHi-S%LR3Xr$u($>smLIb!AHRnpyPNLfmL;$qul{4>xyNY2I+Mr)Or~ z*iZ``s@U`ViWaZ$*_Ih*R;affz|mJwk8;l8D|~{^;1fO9Dy#|7=hj1ljfssscbXR? z9LJPM6%v}uTC?DUF7FZaBNR3R9hJ^W+7*SiR7 z$Da1sf{rs(MhAhoHEf-;Y&_-Gf@ueY8?s27I=xzB&5>-(Cz)*Ev9r@{3E^M#&;n&_E z21mHKlCo-E(`c4Bb0k@`O#L~kLwp%#EJ=q7`jz5!HiBW0h3x?qsn`sl?2GzVidGxD z(QF=f9mf|d82u4CY#VuxhrpM-K)-wTzXPqEmzKyyB|W(SS^XTor%PI}W?%QYjgZNcz1yRaJ`sT= zJJ0Q(Z|q@To3x~OK{w;9oTvJ~56>wF096>4GjL}R7uENkX$e<;@-2_&ds2c`$IsjH zYY0r_ZV;#()FIHA%2pIv`^;tMYWqic;iC-8PbQ=&yI-w!UCBu?i2taPW}A4fTvis^ z#PLSV3(I->OlHAcUK)`oOk28 z^0#nr5+yc;o{A*0H72Yiq3>)(D0ws$@Lg7xG)=*c&TK~H3dDjt8zdDL6FXf#kG|zJ za1njVK91aZ9dPW69R`<8udQSe6CoT#y(D+W<9)*AKK$NF^}}cVzD|r@yHB<;6^r&n z>_kbtkJn#5Bfhl>bM1!(07*@s2dMGa$uBYuVM%U|ur}SA6^{kAdd#w6WpXDJnsMxqaOnwSxGt)^4{N^LNMF^>=63d5CC|dkz&E?UF83WM`YIa;bz4!`sYCVjx=@dy|MjMjl7wl%}A;7sW#M? zv#|2}Js4AhHidqcRq);MU^>&{Q> zezky7ki9$D1--S#no)~FqgIAmq{NU2V0w;;{`DLd>d`yil>D2{*tlJn>8ed*e=+E~ z+6%_FVHLMUuO9T=9PsdZj=Q_8I~j4xVs3sSXr8atP#t0R#6onEuH8m}1iM+}diKj6 zbD$byY1$&&gHgEqj*fk7-DBG40Okfwf%i0<2xjpU+;YvXO9p>yni$~u`MoWLV{ZTL z{wzkpG+k}S(s?DSuy;+6_j<3E|ZIK>9oYk$8Q-^eBH6?%_kJNdFp(03N4HF=z4olXLAZO{QPrT(-pDwv9BRi0Up(LkeS};Gojg0suVk@&uQO(&+Ws=c z*JHMz>A3Oni_wg;$@uW52DU&^osYz93O@+W#bq*3hWxR-jinPvd-8y@SYhfBBtL0W zFl^L+;2Ox!G=Fr9^B!z1wPysL7NSeh#ZxsWQc5_THxU`i(A9};r&H)ElWlL_5DrthoP~aFEopueBeLX zP?BK>CPckF$YQTFm$)A94;Jj3GQ5Kg|5G|C=kqYX_9j-` zTH^7Ki)=uvHzxc_!r}mfPH5A6J1cRch$*ik4ZG1$8+Rjxb$}pdS??P1Q@V`kDS*PM zrC5dm)>g$wL|B~GHt^|v`li6X39FUR$YM0*866LtBYy6{^~)A&74{&$%TATV0a%JY z)%!@l(SaIX30V_RD^&2{*+|O*{C9o5ZTI&z?OWS{r2w5e3;4SXoRkE`-;=(EaOXE( zasg&&E(-l3YfMOtn!}f!GKkjxwP`~+vSMGU(-nE% zB#3csA9|~pfF=fh+1ntQ^u3bC#UA}frR9H1;rl_1!M|~$F!V0ku-b;OBR`ksRS#HV z9g6P$zQ2|XB<|(B%lL_Gs!9=;mFXS1AAMGlIPlJdUSMf}oy_C$;*mlo@7br=fZ^P1 zV~$<*R!yNxj3olCJ7%=?GTOrS^Zq%&4Wa$?le0}PVa#%?;|;~}vEWgn;eht$vxCA& zKSKi@wgrz?9;NZ-TPE>Ju7idcg{&T=K^EbaItWh_4n7S}9`)THu9DI5q5d#umL{wK zvU%Zq7O|pG^64CR=R-3u{&@YC6EoJ4H9*qB+4nAi*yA z<}9%6DR#w3+G_*`U=TH5c(477j5kOuFP%=Btw;5V5-g-^^8TZe%N4ls39;ebb*&5< z&|ojCSxZq@i#I!)CM>ok9GDn7++s+el0@X z$&OuYSJ>05kG8)hzQ1PfY;p2dp{n~af&!=7q&Qd^a^kr)PE28xbV>63uPvaTU^g~7 zb1dS`0vCOArJv<^#qX~R@1#EZ#Xy36 zL?4;?*rix-W}l8L@DXfgT1GBeIlENquK9_yxAH}32z3u{bO^A!=El#$GRp=XS%W7~&6|lgMBUm}Z~)T9TN5ST0bRdmZkCMwLKj*$Z!7g$kaCD<`8F81((mYbxvnoYQaD)#$5HYynmHgDa^dsYY}-Cc{37$~-;+H9 zjqZCveHua?G@%c@a#IjHJC;C0x@P;)jCEy!%T+X`B4~$N1U!y#Y~&u4kru6A*5?$S zhudpU9=ce48c|ruJm}=V?tN2qefJU9816^CtgQHpPUnC{g^$hJ%MAZfRs5K8bQf~v z41>Mt+_@W@qs1%BxHqW$*U-R;G5Sk}V$9mqJFRM4{wfnTn_G(cyXdP7Z)Yp@?xwDl zI4|%Q5r-WET-6FR>>uaN=ATyBi-WvIN1^TWx&l`0$;xztzbkMCaaKG=saoJp*RNh* zag{g#@8^(gnT^_^nvNL=_h7kyxRI-dzihTRcNo!TrtM15Y(l?Cz0R)2 zo8?ECZiymL2(+fLiZaCzWKG^Z*%@tg^5B$#tY`_*T<@nbYtCNhDBaN2=i6I6uo8o~ zCSrmFhaPOxJJ+~?SGsOU$xEqhDELg><36t|u(1~y+V4n+U2LmiR?L>0-K8O*;L=V` z*-k^hyYr;`6hP4~mMi;zkB^{C!4dD=Ze0U$(eiZvqFwp2e5Dp2z1j}a?l4Q`HlMZ3 zv3jc?J&<8~FX^d?uj*VTc_^|zF?qjc6_wBWVp?9}Ekr78!8$ZLRbh~N>$AhBosa$D zdTMh`$dbVcf=Hd`JQJmyuj3B*f>WYSf~C011!lM%>{lR3mMIZ_$!&QF^d(0k3Aq#3 ze`xeCb4%)HKTHI>wAoc1HK2z0oA;u8zN!S)WCGkNL7FQu9kM|L67c7qJ^#^4oTP9@ z@ZtKf+)4|s$(i#!Sk z)!%2_qD-ZAQ&a!m6!SEBYNgIAooHr-5A(1Wn)QUfYag5q0r%>kMd2W-8UDUi(g-os zO3qnK^ky`N;N?b5`UwWm{&!@#QoDv$oSlS0BU@vch~J(3a_lFTv2k*foIn27;vt6c zIH~&L{twKVqcM7qalbrCt?#*?uvaR;O(cK)aIMSef%aR*LO- z%U6Avl@#HbY#n2#sUPnzx(h`dXgR{*TvTSQ>$!Z5iy<$az{gwUpflV{s^Rm2kl32I z!yI=FyREd6-1mRg{c@_|qB8nEi2`5&?>5k#{uMv6I*JBWi*(aF13xtuf?F8IgIfIA z&4??(p~P9cndz;?`{355N&tP!TS-m4@jMvWs(O#TvQiE4429o{-oDjlBkBB`Lx_z$@zxFQvDB0G^TsRsV(5lay7srZGzx5EYdM4k&fS-8W zJJiC|>9{7?6gRfxfP#1(S9CRJp#VcebYqhPb(A1>{>vgYt0N6itlU7ulJ`U<3>#-F zX}j$>oTaYfRJdjPyf*7V04`p2t^~;dBTw@3DLDJSpY-(#b+Fm%|OAmNjfP_*SM)*oT%udEmul5>LL!Vou#qT%ReFq!Wmq!-s;Le}(Bz zR-N*mDjG4j?TNdv5?1^^J1MDgU7I?p2|LyyF{S;Ecx-vF@6vg6iJaukc%(7KV!6tq zwlNJJ=wx2wy?p>^h0s3%i)t!x_@;`UlhheOso53lzlpm%V3M64(@nrM1N8hVaGn*HSHa^10TgV4DcQq7%{m=x*?AGTTAu=yboOB z*6f$pG#Rw*O6t&5wi{dH*2je$WF%P`@6SszXw)B!3~_|iZ%rU5DYxpNQ_&fdwOnj+ zhx}qCW}p+jS+is2)dt}1RlH&rG48D|~K(u^#=rwsM#Wam2#PwF)m*y zo}i8Zg5XWW(H0?{zjN}S*=~Q*23fE{p}?I&rQ$kaI!Q3zPv;zzyZr?wVWW$9mD(57 zz1H-LDr^9AZP#e2W~!4h?A}pLyg<;Y1cPC=7w4gzV8AMvU7O%XDdR(l0TF$aY^AqH zMwT=0dO^2o`s*N8JPHoN(Z+3ryhi%s1e{^u7wqM`zhOf#$ z5@-jo*wY;XJ>TCuTCtsg9>637-|5@P5jBX>CMgfMsJcJGKTfBUJXWx!M*|kgXLfl1 zP^i6JPL#WYSaf<*qnCru)hEh-SyMw!+5eBC^YEwo|D(84DMFDXs}N3%$HriJfQh-EFQ{>r?) zBqNq`ugckaH!F4^jb!WNa&s;K7~^=V`$c^F@0=+bt671G3dk`T9OiI6iI;gs6?=>o zYK^_8w)d`tlu2d?Y+k~B_INrusU)-v#Ad)?fL!u?sV!K%Gfwe=n?*Qvn{h(){Wa+A zi_r{3x0W*khLmn+-1KUU0sEyS@+Iof{3yNzlZxwUJs~<*&nPkP%l4{B&+M{m{e@^2 ztGgD=xd_@_OeR=+`F*>I@5OpVY>w-qnRSs9ARxEU+97dy4)HU?7%9mzZ}no~16O7& zXfMlH7L_=*V_;LS0wqn6L8K(2R~s-7|N2>(_%ZK1Z-hwqH3Lm}-ka8D`k<6kYB-=B z5RE+la9$y8m|`ExKFHqe=WlyoboG&z_y%VL{YMq#d3{_$)*kxM*n zj$6mFAcwfGrnScJ;sESb-}w!D8UL-3HY*}+`CLq!Th?KZ(1gkrVDUVMnz?4zpef3s zvMJ-+OLhAX=b7=EJ}|#mzu;5ivOxc^c0{udm#t+t+>BT}{RCK~&i5#Bm_E#KST=ME#(3g#t?hfktiHi1 zENZ;{zV!tyj_|$cgX}jejl)LJU;N*EAkp{TL{+ygz;U?>CiQZsqPlWk^FxnYWEmgW zW=Sa|^?G3813@D8lSjNuvChK;bs%=|6LjD_yCr)Ilia>&$S^*5ATtHtuoi;-5r=u? z-hxgpFiwfIsJc3wphY?`=Vc3^hegKEe%JV7NBKNMu7;ROo=SO=Q%N6<CUj^F??-=-0co?TP-R!~hP{`DfCL@4jB&!1JU^vkW~O(JibCM-vD zdT=?t%KN~A3`d|NzC5pcDgx`MXT3$DHgv8RW__zN+c%JO-RAd~9*q(7sSh!O&{Mn! zLZer@rZ3!UoD_)L;o5|Yoxwx3xj&usoh-+DUtn%=u_~9&%j>`nQgs6h&Bk4x&$rB%)>6Y2!A`+@_+tXo=n7~D(5KoAIOT?{GIb3Vw)^qvru4ptTDkVLyNWoela(l< z6C2@JJcf3>%}l0)r^>!p@HxeG7`YddK(Zz(>(Xq;?r-IAPn&BwRkEQqY}oACjcX{K zIW#UrMhqKo648kyd*4Fn<^7k3L0`bBYY#8Y?7ja0JNHu=Ry9c*#{D?9W`X^Yx?qRc zo@Xpzboa425oMU!kh~jsla67*-qtV7i7&bL9D$zs!~caE&BVAe#%fJN1Y+@_xrZ)2%#<)|3TROnsk3MhaAOQ$iCh0H9~EPK}acV#aantTvP zVGhuaySPu+GvlRH35O0~pkU$B2Ob`$r{55u+p>b*UldE!1PjbSI>{}ACTQK3#i#0P z=W8I+@ymifhY8#Bjr5BXESx?C(};p02WEzQhAobdnBKs}FCKxH3LOqkKGau8KgM=K z+PhPJrR}=o{9ucQW>If35zkLj_w-MpwzB&OvUD^~jP3x*lYrtyQoml74i2zAU&rcV z4+z@m1#2=+BKW=x)Z#|K^zC*x!n%!I^MLg#%b))YgY`U#5mbnHjH z=2U+n71!+SE1bX+&RHNwZeKWc9++FCO!nUc7;a^D)Jm=SPWik0=6fM%3p^UOD57nh z{$uw-Y^n4T`BizRANz~{s94GEW^R$T7P){AG@}u;gTFX7_>@F4_mg{Ke;SD|@*ci8 zA?VkyS=4%9^e;=swVrQ<*4Ww80V4K~MM=Uf9z`6Ld#w!ygYSig@?`W`eMCfOQr87s z{-X*YmD)YZ6a+S6Z0&nRd5ToE9km!GSP=Vp8EN~1_9^)Wz`#_6fRf%$D3w4o3v)p_ z&JKxkW*%RlV?n)CE0yzvB239G3H#mHoJAVPoAXKG(vW8T^YiD5L~Z%D}c zjQQfm#Z>ByILT&<`^GG8sNVRnpDC#Ccg!|2_W3AvDQCn}vewh4KFq2ra0AlNZ*H>0 zw3w?LWam>dG6J`%nzdaFswNBV&bZ^+_(%fe=Mehy+7{InZfX*jNRUS*HD&>o?Cvh5 zd2gO}S2#$R;TesGD{>sRmGB~XoC(5+E9!K6TU)mtm z&^*KM<8$4N(UAn5Df>9`!2N8=lms8();1qh7}UPbs&{_)l3Isp{o(#agzHiW14gGh z98mnqC0@};wRvnn{Yj2f!C+j%@+a_Ys0$3nw2Kkmv8AqWkOJHhk5qG_-N#~0^tV_w zS^d{AB;$w6jGr!83Cz-|X3Alc0~c=EB27|iA>XexowA-lgajw)fh)5P8r}t!n=M&6v?~>|2Iq-T?oL`IDD(cZMkK5Erp&-L zX=nK3rLNfCa0F6N-1>OWfB;O%$<+77)4DncY2$ zSx6{*R&cP_;u8%!{4#7VbqU`kuS@S-Dnm^D_>yb$n#%fkf#60wE6W!5-KRp?T0JvN z7K+Kn=#sG=ds=aMt9E_Yoa*!ss04clNAOo=)i_lle6pb-WewE0?qG@QE*`UYMx}2?9eKnAEBoX0?<1R`Me zy0^u?P@ETW*GQP|auIW*8N}y#XW|#CQ`Jj;e7=he8}SmWDv!^9RJ1#q%Mds>x?vGe zo^&z8w$UOSo0w>Ujb_q-9Kn=~7)7+*?Zy=8r2}%_P zpy|>5xYCV-N?56taU*IvNM8f6tgQ(AZe~PxE`z>a@NVXa?pH?SW1Rh~1H+E#%@o-l z(t6w3c}vPfUwt<-J2MPJMf76C(7ME=hNdy}0+@m1cP*j7LX{0yqRzdL9mU};(o#v) zht}vv@H9<|BH;$HyRK1bQxSbbmUh1vv$DL%9qEBzZh(cV0+)) zexf$5at>5TN)*;HNFe&S2T_dKT6ptpw<%UA%tlg%<-I=u!I4SGZXsBE!#a5=(hW`? z?Mw7y=#|}pZIAfo_ZwHJ?!;o{IgI-OJ-ixwurBE(L?^xn*A~c$#Y63B6%tkc4N@BA z1*Y4GW0dY%dn4B$^XBWF`PBI7wgBm<82^N0Q!Bri!U(-WBh4V0IO!yy>w-xsX)pdq z#o+EByhD5(+jVrBPhDvAA65ACefEVXah)H{Ukx@USF9xPS?_v%ra~CSvbzRlr!Qmc zE;iX+9sdOzX2L-=Lv-%5gGi`;Irc2_Fl43GaW0htq(od?`HyPoK>q*9@5W4$aWwx9 zWN`<1$QWDOndJ8{9oKG%t6}b<8Q0RB9P!4h4`AP;@KavIL30!L#O0-oWi{1M{a4QS-rHMzW-*Yt z&gnmcNVMMeYFzS?agVM@nT#>3aYbTOz%30K&Mla5%l3o*1@Q`TPAWU9_a8HexzrRh zKvt!D*%?Su{d$J%$#wS?s7)D{ZY0aa%HDhU?0uu$KXok2Qrl|`x1gg@kcw{NOS*nk z_9w1u%E6NuNIOn;@ZhVx(~vvAPdumGz2niRXQBdh_shn~XY&+Sy6Eg1J}<`?tQ-*( zU((x_Otqy(qg3}-?>#seVgTy$jRSwxeh4^b1=eq@!qb#fy%$S$ltqr zV>{#Vhn3e#)nv*L!LZN@a(Hy0aRQnXTVeQ&63|ZKK+aZz+!i z8)*wx6Gq#Mn}N2e+WM1p+N4>ax|%9IGEXaTmo+pg;en0(-V8EGc8Apov?ST`j%bUN>s9dq@P z;g`kp4ZDM6f^05&|D$4bXh0>m@Gj-nYhaB0YPF0H=~gMf{5LqfU_0fIPRM4;{RqLYepn8ovs5ns@)c^S&{TH&N0! zpk7xctpX7aqos)KPamvX(mWqO(iBV1a~v004x4Sf(u@2-DLCd%_Pt#O0J9HwESn3h z#Sj8F+n*F`JIok0>Sp`1p#Oen75F464&#_SXbXQ@>t=6qU;yXO%@o9HTv+sg6SXn^ zSs2vMH=&`&rL065r@BVL zfnDy}gSG2JZpBmyo1`fpmEs>eb!rTaOOpiI@XCtHwkhdHkZ`S#)LScicMb|iUfR-6 z&TKe-`9P{A(@>tz{QL_M@>_=8+)7ogSk~mL1GG=>@4UT1?`OZPlJ-Xo|?iI=R5T;Lcem2?gtQI1UJyW zL4|Gi@KV%Z+zmi6prwKm%uF+~t9uq|IkJ=f@zV`1bFO6K)JE75o?9bK#1@H6U$Y!` z^yP&;0jOe@pd#+M<`2Hmx;9b4vEms@=IPG>Bt-_3UajSNts z2EM+Ci*6_%sc>1BaXW|l?{14~iOFj>F}yFPbUoqippMK7lHSjh`R-bB_q|1<+%B;% zP+k~`Uo>g4b`h(O>&7(&j4x+s%dE2%H}e+H|4_0IfXfm*Rvfwgo<_^weOnhlujI9{ zo+6zz*w@1XlwghUkM2z`i(4X3XsgcGG_PbnMwpJQpCz+P)P#O*8o-$x)s0`!TGF52n$-wfK^SS$dbK?z_?|W zF5?^}g8izN9~5=lB@TR@$C+oIQXcp4eA6N~`Pm9$B4M+d1O>~8)pp9B75dtO*ZP7^ z)nszL12tok{D!jPr8nR@ zOK{|0({y%^*&-%)k(uik*kB4)koodvS&pwuqAb?o9o<@lUT18!wi3KfN)fVozG(nB zc~Zlz)SzJUR>eTq!F;iwXZ=}W*&j!+Yg#rgGN&@{06tO*@5xb=o{6u!XRuD5_ zxaR6PP@c~r9TJ2|>OUgoP2+Ek!bW zjg4~mFiB&Rr8E!zqvBsa!!oftgqhn4RyA6`tCJlP9N$5jXcuHgI|WF;Ask#pQXDy* zQv&{&F6_F;G~2x<{6__62<%kPnP)zmN@)Yjrw$IN6}zefp7SaW`kw%oDDkmb@)MKN z63dsIll-recjf(zWAJmCifU|f0xIohA>A!0Uh`U#@N!{8l=?ape{K1>Zl?TpMi^xe zuPblt8}n5a+47|BasMgb?|$WH6eqG?#+`t$4+$LZ$$Y`4sX zjp%vi9QK*%G7D!SiZwFvJV!PI_QZ54I3T(&X!h^tE79$Uca~F9Wy5e&z6!gbgueaF zr$Vh@|6?T>v7E$S8c6NhV-qIhw5Ge0K*hnZ|-Z-_=YjrUu>aY35aW{0dC;9dYc3?gH;#+ zddDB>X|nTO@O)fuff~E(x@J~QwJ5l`h}~b-z&`UkxEL>I76}tN1Pe6w!*30VtdKct zErb;Dsdl+erv-edL5b1yFY_B{xFu+>!XsnZ+;PQKFf(8<(YsJb_Whwz_tA_Qhpb}D z2BT1FGIVTQDDfLh{Hi$T*|b|8eNB0;OW4T}rf_b9-7!8lSr5+n`Gw*}g)R|R+qt0; zInG-PJy)B5Aa}Y9g5l&(GxEaE>>K>+Vu~~ZME|jg@}l#9sy}QQI^I4mGU-TZs%T+n zhq&UuM&N>Y*7zy`pR3qIxUEw^rA%$I($vn?HSGLI74@pydgIYE35`qip*b)H zL6&$6lhg4*=GtZ{>8ciQv9#BsGZAs(48?>}k=;iP zepzC@Hr-Z9mJL73HM!QJ=}uHj?3E7Yfz@CYPa_MO9oXa!B|SB^WTu2TKjcqlJV9^G z480K&9(5Gh;}(9lrZleHG?~HVTpa~xy;Zp5yyj+-9JW5eyV{Su@Olszt4ljiYwAb6 zAv`8rzsH@1d0@-1Aal8o5|p;Nhc2E%UO&p*tX#I1bPZ3=bG8**%WY5z{B~LuqI+E8 za8Pu<7!I6To)wK@liq6IlO}hWJkAJvhRh0|gT&2n7FAk?;rF7Oi;crA)UvKT36s35 zOd`U4UJ~I3Wc}CEyOB{F9sGtHKDPz47aXxfc9*d3=Al~k;{L;)Wsx!M>ePUtInBU% zYTrLaSZ6|)JLObloSb|*g|`EX<2exh>+c=68doCu?({FUG&D_^Env~MGWM29H-tOUjG4vWW#5XU$<%24`P5UK3R?E+@Da>>394j{jQBSPLgvQFiEa(i(a*u*cth?arH1S zV~u9`&Zs-T<%vX~J$r!dmP>Y)C)#ZO-csbqO0b1&I`>>b`uBq$sc-8BdoMLAxouV@MvRMQivYo8X6JrghOZcy{XBMIYfm>wW%N*b zo%Jm>=U|v%@1u`guG@4`_Tj_PRRir#eumB~htz`f>)L~T4}kfs+>8#KN3#V^ zqUHk)hhGz~=LO7ChwJ&EsFnh^%|Wacw!qNCy$x1pj!Mc`Rnj_~?Uz})|H?|hA}9?_ zn{{)y*X4kF4ht;n!`h@Tu)w0_6^3(~47f1R;F{n5uM;~%*Kg=tJ`#o}3mV%8I}eAir2F-gJHY~jjjMIJlj+^YU_$*Vn3 z!pbj%>iKu5r0e~j($c_pT};9=3KqBWKy#}Td!kf>x_qS<>rAft)>}i_)#R?bj$b!mhK9dTTM&#CB9em#ZJ88BaCK8?XyBB!8H+T<<T3P*`at;fw1t0B5l z7TWiFSaRfT4vj~?ilvznzpNLj;APGnP%)+~MPW6#!~ODG?{8CH=Jr(74N8XO?`+j5 zrk=9lvy-n)4Tw|uu5fUtl&ZU>R9AHJD!|1C1%H53*TLzq)YqiGorII%Eq&zm!L?5A zH2Al4p3FgVzK=cMF5`ztlt)!&Ki4a}pgSSh{o1=5=Ro!dn`nMZQ*Wv#&e?Kn^uC2~ z^hTxnPy>sfiRprae1>blJo!PAkBl5Q??=BvrUE9D%x|mdR@Mt1vlEs0-rZ8+?9j4= z4mg-+2p)7_PSr8mLdb1{x8V=PWfv*!e=@_=>0PS^M;bfV23@|n`sE-8;2x+rXPmKv zCGIEj3E7+)it{y3GeHWfPO$>_X8^Ss14JBwIP0p8PKtGp%#pIc$IP;mT zCn+ZTxE$U+HDD-XP=+<@3#R7>{e6_s=3a(*WYmvt5cH;5(&tOm4%|k$@NyqB(U^X9 z{&IkN@a62}=k)+Jl$v51q{~P!arB;pd#j4?Ns&U=K;-SBxNo_xHxk;v#Wsg>ZYk@t zWax^rfBV4`=J(xd?(pQ>pVN?rg3Om-QEa|-Qf~SrB2CwQd!Du=N#vWK)^?OT*II>{ zX|A(+3G+&l-~RSxZO^EpOL(GGCxUdZQ}4Q!SCj@0v=k-c^)5WiL5j`SYr9~cJ2Ra5ot!UfsZQa+2ykLLtfebq7 zU3Y&aa@%e}vIcabrb`pK(!QA6_5d8(j^yqd4P&Jf8}yv`4R>MTm%)mExmi(HI;sz! zE`g4s+p_oLE@;_TDww-aAKjxfjz{{$rrHMG9|SO8zm#;zJbC*Z`*Xd9=%w!+Io&;x zglcX42fcn?tRev&0kKQ}pXJEL-g$PM8zqAbuXUx>k%g5A8xTSi3G{OUcz`B>?-%A2`1E=c)j271(Fvq5?9&yYl4?F(>(!R7&$gt*# zH`A`d?}S=lGBa;^WL84M-^HtHJM-0;o|X)aWVRX1Ns4oe(xM)meKbx{C%ZxTW3jyV z$NT;cwnAn-+#Nb%S`AqExUEz+E38Q#Vqdx2l9kLw>ao>)#!YU!wO6TC|I@g` z{i;Dr4!OVuBhe{Sp9KH9a+K+|ht>9bd0=qse761u!JZ0^EQ65u=M_pc%cBhQrvI$?s+!uH zO;fOU6~93`^vY69Z>z)JD;le@K#2kjis3%51A_*9`IEEv?m`*^%g>NqVbHNe>FDpC zc}p@YF5!DQ+uF$adS}i|2;qFnLEW+>SLO(+kV_IfWN zc~|#h&|Kvv!9Mrvad+FKueq}K(@(GBt$IWs8hNt^vpiU}jdMAF-rtkF(i*pM+M7{P zgs+HH;Uj@70(C}TH?&nBEKMaoMdbu80P5oTb-n+n#N4QHYu$RW{dO@quf8WIr*oMQ zcZEHv70xal%(P$3aw%jk%XR=lnk}2|Uu2^!dz0iZ>g!T?`74JMbJ!wJ8>AX3pZ0Q1 zHl;h;GFtQx4SU3!jY7w;?$=0B=W9~eOQzSNn#TTJ+y#<@z7D=_vTt(GI-Z5s*rRhF z-(b=s|Lw$>nopK`Fy|a&c1Gv7w}s7<~nNZ{+b8Gq(7c41k@06 z=ANDeMA!hLIn1y^Q(aW^MKI6q37cFuq@5YYq!O{<8G>aqZ&a>mjH#)t5IC`X6O7_o z^%^g3LXzJFIj9~?4OXsUN5thhpQMz>r?(9aVcP877qV``{g2>!9sDt}L0Y`~!$a;r zRyUB4WbM(q`04ClVaeF~N>=ZS!`-tlBSL>*i+QOjA5(XFD}oY*rOfln-v))a+3EoC{xQSSKY`kkk@sPgGyHTnqnx$2cTu{v;n-@Bar zQ$v7r8O8lho+3;MZDVE9^r3Ch!>1vJ?`>wq40RTdx5b^eR`LfafutTadyEU$L;~oR zCn%1DvCAKQtQD<36r>m02eI^_hxpOP(Hy>4eBoxfk;lq5)9mK0FD{nlCSN7!dhQI+ zJh+|ce|D3AZtE~OMJkB~xbptX4U30(lQj3iolUu&6<`yBY($IpWku)e7othp4K^>; z3|4#E10yUh?YI`7*DG0;1K1W|(fFvs`t+<$hW(h&l=|Yl-?njdIGPKDH9O5+YVYM{ zr94R7Vx$XuYZpJ=ZXe>unr}*bF>NJw1RFnCC5d) z*Q&2M=tQm-EZKg@3W7-VdLvg@xy<_4!%y3Gv6x0H&u4fuE_Q-L?P7CLuIdz0n`P}o z>y8*-y|Wyj$L#M#$H;{OkH)uOUHEoKi$TtN5$)_sru-G9Sdx}m?fydUEvKJRHqK`d z!BBJBavh0&xh-sjM!|mEHx*@QPaC7cwM@UV`F|=NnO;}RzVk(wM|dpGe^P%Cfc=A@ zs|7g8AE)=6#lBOXdnek@{v?IiK z8hQ5r-cE8BYHTL-x*79y)*%&mzr~FHf;ll>o~Ll0XG7SQ%*lIVT}J-imR7TX*WI3J z?KgPow*WA9udvc4KOkM}UEb&&q!%P=P1ZLeQ%p@wm3ppAE+TljB9LBC2~q+gaQ$HU z#H78ct+5fd(AxbcQBx-LlbYti`PGkrSb0hdI-PO`fFxodwMV%tw&2z?ir{b@g$Y>SF zvtR1jC#`FwN4vFtns2eiQO&eE3CT|wMvPKd+q?gnQhz2fNjq1Y0c7C`_zxZ|Gs4Cv_W>=We5lDC4*D)FaT+<2+|9_wh>Ws2s~cCdfO z^2NxjP$sZ|Z!-fflZFEzK|!scBe42I;1?@ER4W77mu18K2F?4xYYuPHU@KjCH4brBXoi z&$ts6Px4aLy)5DpP`ES!9BxOlDCH^PrVMLhNXm6nB0BY8_75HXhQ~AEG^)_-`2fVU zBI5F<@r2rp|J@T4_koEXZV$!i6Rx@x=%tDLSUYn?SZ!aSjQf0xry!T}Bl}0yev+g^ zW!(V`h$P7WYh{lb8z}VWf||fNb==*EY-kEm(af27K)=O1f9)f;lu+EqGvkXJa588M zSj9q^Qc=Vj%of+fTzqQe7ARoknZV{Kg|@9BZV4LpsLSIlq*>Y(wHs#PsFF>dE=u}| zaaOcNe%aZ_oKIROds(EF2h7v>5&m)--!I1rCZ8rdW8ReGD2766va)2*$rO8vJRqp^FL4jwlT^9}Nb9Vd zUsvr~0IIfgL`sr#mrjndQFyMs(qnpjJMWKTU6Tm!8 z#^Lp@Bubd3u49`rdELQ#u%J?<;dyO0X1q*a4W5{0p68}SdRKM6eTEOwg*jkQ>!&Hno`a(UlNJArPktnb zrJ0}xEou}(J&Ut3&Vv+dY(XL@bIpBH$ip4^K)rVe6z1|&k3Ha|bcdYD-L1vLVsQ>! z;H2cT%=vOX)V=`Mo(tsi?g=AayH*1m_@85!@P{JGKKx_N0q>-cwGj_G9+jzHypOFr^{>|*mE$_(ZkNjv$b^`DRk-nM#}b=v5&pR z?arg$?la=E$?pS=RY|5iq`c*he?nMObP6h5A~eM(?7^*Gc}(obsmb4ewUX7>ZSiHw z9wA9&GuWT^N@8R|%B%W){B%_Lc9b7ggYywS2C4h9e=p8uQJR}1m$`%@{_q-J1nz@6 z-I}Zx2e*{}rU2LRaRIJY_p`9OZQ`D0Ra+wx6)TVv_;%Xnd-Nia+{O5svPLRg3IP#! z&fBEhBdl&Ct5Ex+;cGF-ZH$n#VdfxgA#p%K)ab!=ZkeS~uuQb)p}QP@a>u8<99jh7 zCRN)KFiRfams=&L4?0FIP^@oX236a|=vIz*ZjL@}AsP0bxKu_IqXS_tYbSh3Mhl(V zpB01s3~6~|sPyE1N=2&Ep;`C z`r@<i#rgIWu<_L)|_210!@+*$U;gg!DMbM=&8&243jW2#4VNk7@H zVgNEjxWA~q64h@zU)@4B_HhHJ#=-=Dw|!qhCBDFL)}q$uHs}2+b9-al7I-q)Z-}hF z@*XMmjH}lvR?6ZA4>Yc)iwau~cKs{U-7V4{p7qqN2yy3p5SLvMQ89#ja{7O{e^W*f zd#6;>z~NKMQ0z|J`pcM4_JN8TZXWAxjIobD#7PbdW7@+qIdbiLSx!z{`4`Rcir(=4D+laFfh>P0Qs`S;WG8alD_%c>Y^Y8H!NQ`Lb>u|oN z7H_F_#U@nht=X;1l;MM<(3x$?v%g_ihal5}(O5@zlT&rKgO}APHSS#mT{BJ~>z$l4 z$RFOSawv57P|?ou7~ybU-fq__wqz6ov;ZuDQs$FL1U)H~0+(*pI}s8PVAx`L#z|w{ zJX*T72V2a53Ieg(6U$=XawIZv>J1Yj+T9hOEglWl!5)e(OFrYW#!`{%5 z`>o1NcDe&fX7w)iQ)M^TyX=3`8Z);m*==Np4y*k?ZK!43(0=x9-pi_I@K)68DRCqlW({gP%ir*Z4j zxnjfke>BgHJ|w5t0Nc*61Khl+a_!`$vzfUX*dJLa6XhXLEd+PA-%@!Pn1SoH;;&(~ zwi#ck*P@qhGkWMH2{=uHb9~uh#!(?=Izx~@A)Xh|V!2x`lDs{h9jH4ve%$dCfJ4gub`Qz`2?uk=?p| zbgfrA7OfQszWdN~@E~uUTU_j?lI;N^eHgUBwzqb)vGeZrn%K_7(~c$(8b})6+uaQT zs(j6>t1xjjEU=}#T;D@nf*V=hT}OlJH0k()>xHCY0&lV;iI=M?cBapccX^UVj4${; z2ynI%tYGg@bA~Xxrty$khgl+iWZixizd5RdJSe8zVOCAm9y^+IK)QbO5G@P{_^MHU z``Yi3FAoDi7mC)#&KI^C)i252Xs9YU{nP5cDi;HM_mQ~TTCdI%cZXQQ z;hn!i{b44Fx&lM;=vy?u@9hRp2=8=vCG-mmZwg(7sYv!qc$BtY@1fcXLimqC6(MqU z`x%=+yJ}AFY7qFjplrbw`$jzBl`bE37VL#KH0oQ0pbH^pw7<$X-w^r4WIrmn+unWq zj?iIKP}%-zsHVj=t2z47m+wvwhVKM{<@pAl7;3UqPZ=QOkDngV;OFv4T1&BUOCdt9 z$K9l}ZH>O^mTVH4?gZlXg}c&yKHZGC5^!+tx*;N?Sy}YqzDP~T^ywSnE}{_!b?njp zF{g=OoYv8f5ijG8tAeaf??ijmn?%d)8Kw@Lv!BUgNG(IOcOTOmj;kCA=dN2(F;(+Y zs2>fd^@r>-3JigW6xe&t+Q1~U#*C-IekcR;@UPlU>hTYv6)1zD4M{yPW@`gsT#!wy zc}m=4IO`tUrIB&x9Dxj`r=N2Px_pL~O1Nl#|^f*1I7{ev+tDoDk$8irbj<+tfJ zQ40Q}${M$H@*X`g^@kz3(X6pwynRUHt+62rY$&rIG7|F^mYR38@Bc?N`qKUP11hb{ zElJjr5Er0GK?Sldjdn-uw@1{q`t)Xmr^-hXd@)bc-B+KnRk-y?TvS{EpD;-L4)D#VW6uFO|u1{XQDsU-#BrjDk?8&miYf zW|cU%jQS|}OTKuOq*CE`+Kt|psE0OGoliD+OYg0h;$VNYS{VPMqDyGGRO)o`*wRe# z@cj(2#{4|l9uoB2CK;7B0<=yOJS_{`7dHTK!*jBuI)PhjI2Qdgw69bay1a|I-T{KiSvnyKAmFVd_ihVe``d|8$@-od8YRQ;y)cIK6hJ$a5V z+tD+Y3KFG?uhvV2xXY~XwaJ-6N80I+_gGwIWSLEz2qC`~HQvbTU)F!zk#vBUR9MaV z;>GrxX0!#MHebCmCJp!l|EN5Yjquy7Q_oTrDMNQZ8gAp8g?)@>wUrrTi&d`e4odAs zd^ZF2#E~AUlvd6Q%o=ISh=}q<>A4o860u8c2iL(*-?T`7-Q|`T|AYnBRbkBzJO2 zj=PKAE845Y;0o*xEPFJjDB1a# zJV^9eQcr+Q12>@VrAO}VgzO*b=9yTuR(@gUtC`KO$QYq5d-d;Es6AA7p;Jb4+gcFz zN6Gh?1RP9PuaQC*D-;f}b=d;=YE`fYqEzryC+3cZJzGLJ6uf-NJRy2=Kzhx$iA6`> z`u3Tn7X*J_RTOsw5v+ZQa^lEMry9}ym|Ve^!%E|0t~R({vuqa^AUFE1+cWe2SxT~@y4I01i-TOVt zhiV^wYkE5Du>%LUW;zV|<52mxk-hIoW7k}kwH~kEK6PVVH~nyUS0!4*@6RX@FZN`s z9L~$DC0S<yU}7iDDzAL3rvB7@ zz@08BIk1O87qMnIEzedl4XS^WP(M9av-I%oze=foimDbPTAJKFKeh)>PUe?5n6ID3 zA@+}kooq#VToN^dJmTYII5DOhQTF2{ZcR^ncNMlUl9o(c|?tXoz?7Oa2G z&L3{R!<)0+bx^Ihx7n)TPF+h~S$hHqtgTYCe86ih)ir{U!8QqL7gnWkivwK`jr>v- z)u769U-MFgs0XyyyTl6nwxB-Y1$~*fniOV28Qyd81Uh5J`1xtv4(4vE;k1ay<#}C^ z=8C3JwtzXM*N}de`X^L3A-%|t;I4K~fpEyxig}UVRIX%d3yXWdKL1CxllOSR$cz5B zVAqk7U9j(jW4rR+DQ)bng2j!u6d09bPGV(3jLnQ zvNx*OX%0}znh`J6@ygdMm;=UMbTBt{nv#1EtxzEolr-^+vjb^an9drpL0X-v>li&CYDsy&m4Zz zO;>wyq%?if0ql7@x$lauBfsxTSG;y;2sUBM`Lk*O=BN6s-)C=o63^9oEfAq_9tHvZ zbQyESxx{!BIY^zF#b$C2nD=ybdhE~VNqsk8XONgkh&*iP4)l3V(j^<3JE46n)C)Gx zlC!qZ(x1sYRWCB<9%|M;OdY{C*j;KQ_1#(d)G^}s_>VHn#IECcVRV>6V0ynaHp8lT z{^OCYCJrn)cprn0@+IJdI9VTcm8duf`0G#&%5uE3s}F{A%d=J9PI+pt3*=xsvd4OA zU1qKPNZ;aPDE&0{%vr?IK5kS0Ra-Kf0BNn12cIy=7ueN-2ZEjWs z$KWwZbr8antJOFfmILp3vXf#D5qT`&9N&2n!{5)zMz|AUQ+;ZHhsxScoR`%?;H#%I z5+ddO6p1JGOV=*lJJl3GAPV^ghMWAf<9Ep;d275ku&-n0_|Bon+>Xh1vH zt5XpRHg}(&w52asKQ1hF2FC354YJlQ2kTDLMmdsw4eYb!)r-5wqufFP@LO2rqXl19 zR(+38QanKc;*^cOvMO9Nn9~{kxm=>RX=_0?lMcYE;TuQYD24U0**;C_r8oFNUUhMK8SxyqSab2Xir zBlpToEoTnIjT^VQQ=BN80~K+gjQ4xKe}MxI9`5Jny07azf9D41 zO=Z${0pS$^U?ER^MYrPagcfntM0^qbl91)^`B~RnyB{K&yD+KVf$I5r^=nE2t|f!y zoml3guW5jb+LrafqRb|ukk9l@gMD50`bQ0#=ynT#bX60AytNCBerIT{))9~V=KYgO z21`-7AQ_XZNpR6Y4%HiIg|eyNgL~H2Hu8TR_a$bejMq=h33m007v3u0Jj}Z`5HjY* zXQqUdKF%G=$lf;R)9SI0JUr}nQ6M#D*ICv=cz?^2U_;{ zOFt-i5;ta(;H+AmlFK&=8*BRl>Y(iz>ob9bUA2Ub$le!!HqcvU3Q+}&0e`fo-ZO*2 zJbQ$rT!_J3oY^l+P9L8 zzs#IJ>UM}ck4VmK{yo_rb9>zLSxz&IKeb_DXkn68`#c#{9g$Jr^N{8iFr`{_#o9A2 z4do?OTpi{X zHU4(>SAAW;il@%!z9a7+e1ADF+BbUmDM|XkrV^xTP(uq34AZb)U5OXdw=gzKu_6<% z=z3koNsxB^os+$i0b9JCK)|s=p1r{DNc@bTCt2#?C2mm)9vC6a+be)nCYsmcHcU-Z zT?&GoTt}~lHr0ihhH1?mwQGI~a<$IT>)x$ZAB2uJ*$4&ZAOfV!SqMgQ-Q$h8&|c71om|2@OZVVzsfmx{B&uGT*v6CNDN=j%JCj`@G*@Z)KsH za{p}Vx;SRwer*g)_~yENw<(VeH1s)?h_O{%%LxT#kDLqso_J^BC$nIwTs91dSB_XU z@h9mQ^_GA`Yj$!Hg{Z0ot=|vr(5I$Phx2U>Uhr*o{fo|UZ|=u5>wiDFz}2I*gm^_Z zE#7`=UgXc`$Zg~``{uMf>@Iw@F`sM-$vrNqmdTy7ar zh_0D^RT0<2WxB$1kBkvoNnl#Zes!zJ$UVaS#}v3wJLCPy7o6&qP?mvlR7lqUD^6Fb zX1~HR#pxF}`oX;!2fr8WaSyZ?{W!MSA@=~ zsn|Zir9IRBeJ4<Qz?(t>DL$xgRZPde7#?B`@`w{H?)aal1bX7>q3fW_@ZXD z%e@xa8JwGGkebLUzw;53dgQu3HGi!oWTea-b@s=4dGH8LChxt+ z&h4f&-5Sh^Is7Q8cgRZwo^iwCt?r0*?2QAy?i;B{Az7@rV9{Fmp#II{4`0a}u$QYs-&uP>1yh5rI zWF0|G5+yv$Otco6X`UlQW!+(>BD~>uXM@hSosw*{J7MpFlsZk5#vh?-%#-^q zcZ!YOeF6me`kWwNmX5BoEYx*5UvuQ%*cE>Bc1As5SSlityYu%S zp{ke7c#CRYi6&JGWfhuQURi!y;BsO(s167Sl(?s2Pc7k(ZFQ=Kc;V>T?ICiHoxdR4 zN7=XkoHQPmjv;<77!NOgJozH~>-oBn&-7I3PBeacu+9b3ME$8K=OK{NvSFs3Xbh5w zKdVRNjaZdT72-MxD7JfA9(dcylzc;L_Hyzd`D(7t?829UIIu@Tt;Elx)P)X_d$q~6 zOy%P=e9qe*fo(ymNs?n?4qOm=;+3*$Uw&0rKE=`);6j%s~v zzN!2JfxbDJ@JykR*k4^5=y}VQX?BMHhJSum;40j*u6QtdbjO;5Wv~?m-u^#TLN!3c z&zCO+pdg*ZpIKLUCGzNpHva?9E~Tk0@7MyLI;ww1$TnAjV;^0d44lz{^yGmqP_1;2 zeyGo*(Pmx#%rE|=XBwH(EAs-~y>HkrhNJeuwZ;2i@@fYBBsIqGPNG_ zI-H3K;=LLd8QqO=KpYo!^DZeYt$Y&z42ssfM=dqJI{Vlp<;lds{cUQB77u#eWR_j=+!wEVaJ(^FP^#%V94cs=hrR7W#k7=sCu{ z5O1Kb`Uz{xMtQfuI^}1e6(IEnJyZgD`dQ%9&h(j&#n**G7j(8DUopI`?6b5W3Zx{! z{NTbtMp9XvQ1t@t#0AOm7&Lm4|K`a zJPA#`y{mS}ehy`HinP7TtA;(z7!6)Z(~&y8t`$Tnz>A=~@aIVOJ(&Q)m7XI) z2K6PX?XAlHI4gHWn=fi5`GB*#@=^#3{a35lLV%AY(#%l6!m9R_4Y&-+_cYyaM(W|* z*VRi6?1J9fhDP)XO?v~Lqk7b+U~8g>$nSL})+6gDUS17tciHc~5`Ftel+fObZy1>s zWU!)(Xiih|BbQwnA|#fNA(r2(CCdpVJu$28JYTMz1bfLLMr;cB+EEP-^dRo&Nzl!0x&QqZN5~e z^=4p-#|Crvx|*}XrIx0lHGS2R#$}}kN6cO)X|3*g#x?ApbJ%{B8wS)eR>+SLGcdeV zUa5Ks<;{iz`b*n(@+0#7ZRUEqrkc;o0jdn`rBjkL<*DB@zt`oM{)qHkEm?|Mkom?` zKHDa@_@yp{i?-=W#?zSkW6>YVWpqtL{a`p_1Z{cM3zmXb;^*MY95r#F2WiMTy^6N& z0jcI?0@9A^%C0SUv-OY zLmb#{6XVWzteuw?(2)LS&-5+1@LVBxMWYRf9oJL#3y0+kO!hR)G?YwFPUWcVdAMP; z$=!e3g%Ce~eA|(1rtka)%ifSi=q2K=0nFqro+~A_eclefi&1H7{S`Y)@01GxRbc6j zx+D0>^e}GCW21pDcD=YfEJwgKuh$fnl?oSjYn^{M;H+XGE=+G~OD z@0`FN#I;>e7HBoC%#&E-u9IcjFGGIL2uOyjW(A=&pPQTG^FGf;w&ZUFUFx2mmGCY6 z*Rr;Xp50Tt=I{m>9A*-P65L)jWZ)ea8K{*-vdZ7V<~^m?r)J7}QeXHj$QK{~RIS{4 zEFPzKNo-!~TrRj4BKJ(N2bVFd^g*U=Bf4}6SoMH&VB$N{kaVdNR}!J=_LaZL3Xl&-fBV z8y(R6C?B_V`CHuXxzDkGP7jU%#1})Oa!HeN7xqrgC`OR$UOx98 zhA^UCRsnet*PO{2MTBx)2HfB?&2slv!X+MkS%s>!9Vo0m*ximJsdjREdMSmY3?470 zQMGbFI3DI%S@7b{bbtL=S|XLGmi(b6W`I-S0#yUj{x=L6;EdP))Eo+H(wUH-e`N_L zq8r%;a#?sQK|m+^(>xb|{(9OC4oQ9ltr*?WX?v^lMww}aDR0-jU1o8!m3^{6TqOV7 z!c+Z{9d~EjuX}$)bAbK6Ey6Wm@hF_+c-&d8uh%?PA-yg2Qt;W^#g1a2>ajAhcKVLY zz;m*if!K|&e(bvU_+AT~Ca>X{Wba(A(B-vb`bG7bZ-M*Gzss7R>PM&w=MM(_eD}F5 zY?qJ4?!=YGcjbD;r~IMaqVSZ5gpooS02$oVvz+)%Zp6=b!Js8GIYHRN+4ZC zOfsy)R)i9|H`HwESP@{}Gb>s8ZO$-XSF&@qfsIXv*O-m9C)9tPx3btYKUnUBu)Ha0 z$h$BOu12S|f|B7n!%n$E>mzG9##Dp zBfR^>$upYDFT&$F5vkQQgJmj)eTzpC{?F)%cQZ&feKMMQ(+hi{G(#!>qF+g8v#lKXD22mf81drLF{he8`|E^I$H#9_sVpvXt zl0IsHe!l_7=@tZ9t|cBlxe0U z*e0Zu&{yMsd4^%o-WZNt9(g`p6Y`iIPIFuW{Zof2-fZP3^`yOi4+Cqpl5=}Z+5?JW zn3hAep)bUhmeAXtc*8i2%Z<}h|1mw<3;PiNCYo&BsHht#+W*{5u}Vy?(^uHytXpV{ zs`aeA(0t+=#KkmGdu|T1Q{mIAPTH{j|KBySJ_&bJH+m6g?|Q50!>ut7OWAa0uO;SO zxrK(^S-~SClIZsMPs@tRBXzw_qtAx0Qr9uQEX$hCv+LK}HxlF~oEkYPqCwhzR125? zm`Eh0WJljERJa`1^>&sI7+)&UYPfd1XjVWOXgwb>cS@ok>ge+FV-_RNn?V3 zqdpCopZHgj(40*T$KB2p|0(_Qo0E2?3j^emHTB|M{tq$>#Wm(m2|7T>o{bP1igi0- zi&;>o*y>tf-tVHgvxP|&E5VPtplAGRoqgJc6Sd+%?-h|s? zCw&vF7+7R8M1DJ1YOL@hF}+l3irN%*7&3?SCjOOkal+B=);?`WJ`-jIsXCG9Qk-(L z56KB5hoDsd-qbSef<@gB?EtaNyD!{nq+UpN>a7_eH0RpxU%PVcYHXe!$qcxqOT$L+ zr+f&C1vh&`9W>Z-(*D?^$Rv!b95|J+QI%-2&M~QY1Eg^B)2!C*Se;u}$FpBMpG*TW zRf|A^QSr)jTcEU>;c{?r7PV4i0sP%wpwl7Y{@hZ00evpfwupsYuS{hfk+_a0UHwR8 zKDenl%iMPQsiP^6$I9KmF*3^ea=m*g;EEFq?>h-R=hq`g%-omMXRvkefea^Z+zWAK z6tjyE6_*v)v*Y@ek1L0eAL2r(id&%T&8o||)JZjU7<4Qq&>_hH(>$v?ywKZ%`J}M* zAJZ>H8|F-i6GhPLCnc->)bO){q~7Lo2yVbjK7r`ntYq58&)L(oV5}uJ?JVy#DQ$mX zytE6sD2ycX{}4dXNd|x~97{Q`qpnefNUUxbF$y zngtw|k+2G5`Rmc>-rBV-xw zu#$_Kqp{O7{5X*yzGl;s5dFPwT9CfJ^q+4SRIo{7lCJLJgbWavvv6uA+cs)+oP~-D zL%-@Y7{M_90gNHQT+O9i%6*YFAlabR!kMZHZf=*7dq3P69v`$K&^R4<1lI*LW*7=F z>?tMYC=^s}PP^9M9RdpVf)y^P>8m%hZ6{)d>|#A$_(UoG!crAZTL6KsZR?bprl$Z7 zmUxFRecARgi;?&+*3Mo}x6`S@_jma{?7|#w#ea;CzWL0cw1d9eq6-=x%4_+L2_W|0 zx8|yldpqZ_N?$9KY{0ZU$G<=H~B$Ej&R z^7Kg>1rzx}+o$27m9A`4JhADAqiP_e#Q?~?9@s}OSTQ;D8_A!sY?-FGX`&47(P?DF9%q#!}tHLGu?pH?s zQ3|V_TcOmA>8eH@U?v6R->Oc|eL5cRMcM=6hFO@Y;{b7;*buC6Yo^NA_!oVEQH@Ov-8`aQWo+2ThqGo4kb+Bon^m%5kzV zRtwp~IfFi8i8;d2E1LtCV_JadHvLh%z@3{mvW7LiGhZ&s4DU3r=LQFbMblV-9l|O^ zm>xlsQ@}>ZXT|Av-OU1nCyJDmV)niNtyBZY>pvY3Ql_k(*~JAc4BG)%?G*1OhYQJ@<7!o)wJ4`V}|WaJHJ=b4DZMm7*wa! zrp^MKPD$*Y8p0GiL5h=m%fisV{3#d8(rmrLfjL(Z? zfW{oCp?y?IV%I3DdGyP30z^Xg3DkJl-F9YNPcYV}O{~OcDM}{Og@ywpN;U4^*Z&Pr(r&@Y*X-uWCpaq3L!KV#NW1nhSWU#JN z@1eH|RF!~WZ47-FbrHP#hTOaw??m{J*u!aiJ^)p0@G?!hYsBaaXea{{>v2_elQtM)2x_%QQt}0%3i7fwSXC*&)N)c^Tyq|exdfc-3PD%H zL@gPUwnBNf^(2AT$muHx2Sc$YoVMEz6I&P8OC7=m4ojb5@#6=Z^HTYLhW63G<`UFk zcrE1WSct2<=T9(rP8dDJ{T~wq0qJSFAMoS%&kZNdNYm(m=mcXkR0eH-F2tI2 zPW4hz{!hi33xx0??bj-+4rkS$@qj=fwxge+3I;~X6FHyB)`C(y0i9mi3=zy%O^PGp z!eFn%sK@F)8D(|tM0YC|IWqNiO4A9#*0UuPBobFGFa96Xtv^ck70PDotYAu))H}z4#>2B9-VYuyrjjb+l zGkEzrnW}p;%iyNJGW@FcV7invssm+Qch4qeh*4O$Au+9cRch;!Fz`=Yyz`?SS}at@ zqCi~Svw(5@J-ykmL(Zf%3wH?s0O0!DGZ&=P~8xEj+7uiDOie?!duw~@=fW=OY zOC%*^GW@dwUleAn;M3X@Zj(}}zddi2&uTMH6o_`4O1jDgdm49#Htfj{(q~^0jOy}) zkOK5(jr#$J&LBuQgO~F7^im*AuyMs`GRaOz?#0TvyG8@;b3xg@L)v@OJvR!cw@XQq zJC#z>61%m#V*btbs@E@GytVEk>cZR-2CONe%NPR?pRYNB4(`MTK)^9!wy0*6|9%`79 zV_uF-^G%;MP}kaBp5L!rpn(%u3f(Q{gpvfspy~FzA-F2+i#AhbM!>7@2w7boAE|lb zZFNKbGx|aZ4^xAzaerb{-Oi~!3)f#s4qn|w1dU76hoD#DeWD%V>mbU%PBRTz*PFdLczJubyGDL z|6?k6KYfeXPl}l3ut-ov04VFWUo=&E+@TK8Ju2;Bu#-k&bMF>U?(XDHZIo+EBq|Rk zp4s33>NTBhzrK5g(YdiV{tA`)9}`|FoMwP1SwJetXN7xtiL4LwiEGR^r(&%c3WO=> z_gQ!Q-v!dXo0<-w@UZ*zpRGcW5G_(2N)i*{s|_yq>ADdQx4zcCpOVEZmhTgP&GU$B z9Z^?IWG`ln<<&;!<0ZMdk)20X+C>{bB_h_6{t4h{3n}oL^BTF>AT&J%LVaqR2~($- zciuezyY+4ez~OzT#^=n9v-Eq2{P9A2M2+#X^It>Wm0h^dbPq(J^-}vD5BAUQ4I!GRxO8eZ~6i$YN?*BCUxaUPQBQ3 zA{x8)(+YpNF}3JuL8Nc4*p$OQZU=QxSr0OTh_o0pSmpL0?XB_@p9+MVOD44HhqaCN zHJ+Qax6?<_l zE-Nq1z-7*VtIIHA#S!I^YhPgSV#E_N>?OUR8M0b8!sVXW(vefr_>n|p`3)`EplVUd z?fV0=jG~`*>{1;HDZBL`MoU=M2BOCN-BUrK|7772-BrTcVvzW&y&Y84!&7syUsk>=Mea~}m*Lh8$3l#bI3F1kcZwmTa9`76Y$(d3R5Yz?eEjM-J72iK6ML5T{8MK_h;I zE}70cg%Dbm0RTP!hx>)x!H)tIRjViYI7w-s;Y-gLbmfDx@~%;*+rGG<#+nxz&chzD zbZ6z9*~C)8d9Lc;*qr`?JTr%_MQ#)%f^037_`}*&Noo3~@rzi`?@3G?7v9{~>0Rea zfl>7X(6EgEm{_%bAdf+VttrhTh%e!pr@=?66!v9IG>`eXn}3jhsX~l4cTc_HgJ&8kPr@0QcKx6*j@j5(#c6wSW)dc3*m9kwfZ@Sfu>9%Y5yc6JyvFOK*Za4 zV0_VRQvrUuZDS;?IuLc65LT!`eJx= zOJP_)gDIYnYIvUFSYXCh$`xxQ=n3*!KXe7lkc?Z+TUw0okF!8~=ibeq%}%Zii95uf;;fel5>qqH*o5zYm-ADhxnq zja9t*p5h#1pzqp>`0_PVfn|r3y}nRndS?U zTZCHT-^X|!JlBo?@V!n3R~=W%`E0HsV()^^b!Cy#>X<^4NGB5{VYWmBlJHuT|AXqJ z@{Z149@MFTb zc6#{zCGUAvc;!FzXqsp#EdY3NFfIVvX*JQT6bj07ymqRNhZ>Q0_h%(`acFP!plo@9 z;Vn9nB)8lQxvB;VEu5pLDj(hzLc>!sXC31q32|FF#jdanZ*6GG$<`he3y|kI@dm+9 zU=fWY@gaAnW2XQm<4wm2#r?pnmy#XcFGeGk+cod2yQ4XGpLO&0n~4X&x^8Mvc&Kg^ z(e^X|H{1LO|9SU5`W1M{ztzI-PB#>YJh|@~lT2o6rIdpr8O&qNfHdyB93?GZ&C4xQ zZzIfe+;*N@=LxuTt?i21J!8Qix8g5suTH|wh6qu*NpeSB07DhS8=wddm2|p~+nBl% z+H#=kaxv>pmeb=ZXTm;MqKn){#5ihx)Q}p}T>2Jve+p&Dv6=edW}(E?qNmPEP2FH0 ze~*wZ$H_x}?)997j~t)-ga^@^_5&jHmGwAxtktIu&5xQqtyi|pFI^hWteSJJ`-@Xc zIKEu_jR%t5b+oL5?T7pHtxqw4rI-&KQ$#|9Ql}b|%3^NJSw9N7p{kfm=;-NP_cHHT zid~|bA}Qi5+gX(X1$ab6i0P7mxXILEoJn0)iPgreOT0mxNUz$=JDjMh{Q!SSMcA$Z zW>#)lDasE*5z&kcQJ{xcSO=8qrgCZwPxYuj+8*@I`Q;>+m@q?TdefBkb*=8Fm89hR zXT{$%lIaOM&3QAB_R|;xm`BwHtLD!4B%ax*S}pk78P!(kCpbX%MO53wf&c^OQfZh- zCTE>SR(|&wF5d;j6T55yn;@pDzSABHO~d4(%QU|cz8_4O$>oDphDdll2q8CX=z zQ*^GQ{;1oXIL- zBuFtIk?_WS?|Y}AWj@-+b>CsQ3N7 z14(xKb-O9%{_Dt{omJYvRGC<9Fd^y~TjRedBXvb~rsvE_!?g`bPv4g5%XI^VFZ-&s z(Jq#suiyGmjC_e;i(j^j*Rj%h6Zy=TJiuz!cFsPClzbY3a<%UAY?gT<+!nvN=vmDP zq+RA(VnGt`oJA{?OQ!oX-8v;0Msw#)JqPVvCaz%5z4bO!*&v%7k114S@w;CvC)Cd^ zSlI}@_W4afY8r{L^I1p=cS6Ymk%VUpiNJkdWaQIJoc&bzZWZV(RkC$@?ZLV@{emw==$*Qn82^4fxhtlF7gBxjdM0f_uQ!GOv}eGulr|t)lIx)A>)RkWiqnI)G={ zCX>Xr%=d=#ykO47^9JhKmBlfuXtd67`}!?Oag{LpTkji!>=kwh3SV4?!(EjY?bmDi zWseRvwInMAMZ0eD!hq^|<$P<}kF7KwO}l{I8<(VX*<*xF#O0B@Fqhfm4SB$ zmpaxrhrf(5F_5~Z;hS&wg@-HW^N4~b~}WZRt~@fdsDeW8}Z zKW(%qpIW;>INUm1b?@Jc=NmbT%jMXC3c#mOvE1GVf5zAuq z%JMfKxE;rKYUv7@q3Qw!QqSfGN@w$B`?bBVzpvjbP~iCxc8&Ii0x6zz&4g}&!I9|H zWr^K_=19enyn7ZRMmNlja8oigOSOyBUx7J!x?j#!{Kqg2QVk9V8I)4ER&5pxPT$$F z=@{rg34^6Hy+4NA&(`?eeVM&QmNZStGkXx=@#0RLn#AiV^fc;F(~ zl&%YWr6Xm0oOk!kKXV)^g7273DVDytll%|3Uh2Y2bn<{p$62NH)urs6C9nO10{t5O z-5XC-t;+6JDQwmrVKzIMuRYc0xpezYadtLzNIy^iR}WG!1#cCqTsrgA@Ra78do zcPTs>$3+^SoChHc-K8?QfHt%M2S|#c82@xOdY8SU`tHe0SLuFo|2leMM6X66s(#!) zQwI?!8@guF7%97>Blh=qtB7ufA%Zw`&s zmLuSWwV&JoZ4}oRoP5Z(rIK{N1w-M&#~_Us#X|nnJ#Z=ZpCnjfl9Q>*Q?F~;tB1f` z&g};!dQ)HEg=qZ3T__*4J7y5=Z^EC%*{ciXbW0)+qif^M6OFeQ6*nZu94$s!h13u- z13n|_KdaTIXZ5!OZ3)v}+>geZHk`rT@Oq3}g!oMyuAR zN)TF)i`BO@@Ixqe)j%umed9GV7smKNPQ&@IH(vGG{#)ienjZCuP(_ic28XETI!o&n z#Fzh=#Q8b$c3+!#m6`3Ujbe{X4908v%VGP)eES#Xl7f7{Udp+!$qtd48dLq57OY># z{?XxOfg9$_is+g;i+ZUTewr$3m1qDkMLjy*pN>FD)geQ-SXM>V8_j@9{KpfRi}7|< zZAry0R0@9Q!;o0DcbVaFW01EvM~~)#t|YwFTA~TcEyAPEn|RF2Hjvz_&UxJU>gBM2 zfmS@BKxfCvvZ&!<(ujlxc+EJ6x{MuUS@mDbDBM8%Ky;dBH|6Q4b;~{@^TzaTDx$?S zY>xUpN6^CF(h?80IU?TFc;?ObA+*uC@KI=>I`VVf37q>U`vuGOj|IP;_9c7!2_1|O zjITb{&8Q7^Tb3NH6il3~xH9}VY_&_{BofLhIcY-PGDdw$Dl6Nb50h# z`(nP?mpV78ANs(od2SzS21JX5SO>mu5cT)wV3{f>8rJE8GMeB+)Su^~ag=l4!*f-z z%_yveU9jwOG1jPu;^Db)a_D05HKIZ${#w)fu&G|$yA@LyAw&I(oqmmTL!=fy^wu?~^=XOOf(Go&al(Fj-K_Ph$GyAD?M zbclX*r*0%8&po6wG1l*>fO=kYTJ;(K)CkHv3vr(_yiZO)2$XkzPrwcKR^&o%InPZlJa7lko#MEQ~%krD&d~) z<<)~NBTnJQmdZ%V+QL?pNtb^Uj4=-?4nqA zSJ_cQi6N6u?SW;`#t-_k6y~SqE!p`Tmo{u&Q-ekCT>82Td9r2d+hPQgoJq`Cc{5P` zGz0v)BO&(Db#*VZbjg-Adq>xzm*oTqvJ7{CM+>R`iax7L_>XG4a z%ki`0$-5yHUx`{LrgO_pC1h>6+j1=Jvuw9DOoZh%QU*Ku}m)83W+X31!tA^k$B zR<-49Zw+|+Y}l`-t>5 zZUvFz=%O$3uVbrkFaPO8LZddna7MA&3Ao?09~a8iu=Tt?&_i+z>`T@R5)4SScNc`+ zsyfrEb;~E7YE>cD)o(7`ywLdI(M{rZN!ib+0?*atSX$@Vd{n$yqfWT~YBkS^h_y_ z`Tn*J1O%Yv!_#KL@Pu2$aC9Zg;O&A(EJk|A>uMk=g)FOdr7UA(^R1YwS*qi#;&Ub53^E@3069l~$4Hk1k#_ z<-kY}{t?VR9oOrC;^m{71~^J^A8LHq>r|A9mSd0WybF4hn)>3(04#eTRdyxY6a!#q z&3APpY-0I<8rk6(Yvth~>GWo(>eV17c)$tUfA*-a=uQAEs|me(y}D>wiRpFlgt@Ui z!Wj&=IPUw8Nup?`{#M@!m{Rk{I6uPbS*D+}qbEil;R`&NmR~&g*iUCBq@}l{)u^>E zF(#xdb~RE!WnKP^)rPI|iuvqNN0U;`xVZ6&?j%LQf3I_6}~!<=4;qsYN1pA zYIoSj%n9rs`g_M_%#N?$p6{oo%yRw6*w2k>t_=3TCS@}x8^$UD$jg}0O??_+Ie(m& zc10|8C4XJH1fAexU3?@5wGEAH_@a1h)bfI5u-TbQ;=yn9$5dCay&UaNXxl}Obd`KK zs=05UHq_AS8QZRZKMp$G=8WvwiD#&v0oTWh5oHNtT{Q)GYXc^jPN z2hJy0s}Ogt$%(9$x$^xTkB%9rZtu!1BLateWLDr2!7;^h`Yj{{E$*D05LgC^YV_dG2?AYvogMw0q9%#;t zcPG2{z8Q0L2rX?j)BlWf8Q58U@Jn45byT?8o~9V(4trbj1Lwo1OEbuwDeC>b7ky{Sc8X9oFIIY zv6J8!esa7rm(v1BN&&J=?I+$e7k!`9d{8MZJLraA%_in=5*j@Dg{)oYA~&bR2jJ04 zF1WnLZUN-O>k7}D*}%P|#%KF=Q=Uzh(Wi+Ux<8&1y%;q?P~0(mhfPxh#g#42=XsF< zOzz=?L($u%!{(boRX?T@Y1^+z&Oq65iE_#lZZqaPZ^kRruq&}r?-3t%V$>GOxeO6w z%z>&#KF~Dxw5_J)RTajd<#pR&%e-x3LvN?x6(+38_4djNsq)oNArTt7JZn(nRCN;3 zmJ8^dF(rPbXB-wHhp3}9m8n9O7if0Ky^DD*Ti|6NX*h9SU%AKV+eS$>Ayg{Ng?5|% zU7_+r>lKnzguA=*;I>DFM1aIv*&(% z0b!ri+qXJ}#!81HZv3B5R<^moHRVb4FftgG{*q_^*~$7}e&S0dfd$mT6|4PRPK9K} z|CnB5W}iUnDbvnN196r`dzr4&G3T=^zbTpueD39|hkCoWAzYr3TSeS1n3_0!=_+=0 zK7m{p%6`)Xp@`D3j2l>O6Fvtj*Y41OT6n+c&1`@5t~i(!cQ?A(E~4<;$hE7*~QV z4mQ?XlAZ=Ds0^P~I&SC#b=txO<}!o%>Ye_K(lBzKPCcxTS@!U)AL&TIG-pm(CY|wv zNQo1#jOcqlBLaetw5azdp28!0JIX@-xTG_sW#wn@(VRo6!dW8`fIixb#QxF|!Wj_r z!bVAdyePTX{pS;+Guxl}e?=oVwYJ}$59Ew)Rddf3+Z#?^5)WpDN|rm`w|wHrnxr44 zEBquWkT>j75CmHpxp=)*)GbbEfpwa@(=h5=4LZu6s-CUNs;Nk@X3{*f%~ZZPBYG4_ za{9E#v4ZD`Xjb>abKY<>9ylvek|dSo_Wj~J3u)!PVZ^5mTPr>BjGXD?*u2>{GJD5I zUVF&*hpHnex2gL&$8|dkZ#rz0&b4jx)&q+^`egAajCB6^LzuAT<^xIm>>T!7Rx<@& z7S8N_?O0(lZ1g5OC43o-oose5-ZWz^dGR|CZKPH1b&Ky0Q`w@FlDD#e*r)AJ%U}>+ z*ysZdWH7(Jdq}c4G*c%)P>A=c&}-?>!YU>sXF6D|Pn(?Zk)JfPG#~c;GcKCgS${tMPfAr{Nbheez-(xjYUK+E zw+bLsO$dMLAI46I&NlpA%ICe)uxa)!Wey5|g&*dG4gkWfBx$ln0FuGhN%H24t&G~m z!=zz-{D$?ptFkK#Nk9PS2q{tj9?7JsNhh^Rs}y-`p1jaH63+N%Xs?d`)|dJ{uGI_> z=tp!a31CNPo5W(;<;rDf-rax$z-NRQC_|@Rk%$e-wO$#IHP0~?_yF18-cGynwk0cq zla>N}{)bl#T&pm>P>rk9f>JRH9*7g!+TL@M=nU!q%g6cd%&k=316=0m)JX_x9_>FD zI!hk;pjpEi!C(&X7m({r^>VGN+Zm~rAbMgYCz4(SXYQ`fjaDcj;PhqN^G?M^Br|P- zCBZ|%+M#4waNxp$b`)@Ro@DG`93b4+(-3KF{R0hLrjPo3l1F|!5L!_uBh>p8rK2R$ zr_MhIBWEc!PsT%}eblPEVhe~eNF`UkF5$H4+cmiS%27kgUHNH$OtoP&re=F#bNOq$ zh+$0zTDhU*i zb^zv4T5SnZ9`fgV*obD0bX-NqBR~32yrh^ahn>Nd7puT(-x%p1g;5aNkt;kQ7Y zYUVR}bxOpn<-D2Q<&ST1+8l-WOGcarce!2xZgn2sa~yopC+5qLh!AJ$i?FdIn&~7> z74aP>+b5Zmz5l>EF#4?2lYPOq-d?8DH_gV~kXoRnd4n;|!;l~$IyL_d_=aCVNcGPz zHz2pY1&Kyy3(mxP)q1P2WKVkk94H(-e5FxFkNc0wDep3+3C}gs1>>2w)+qm>tmt1| zGkCQ5B8;SwrKQql%|>1C2om2=Y{)c}1*CP;ZIGHu8W-4-q}?^d`Dmi`A_e)RrnPZj zG?xHVI?E4zL@X*aYGKZttn7W6wSY+gf3VcIxNXd+3 zrVTEmu3}_YLE%?PIr7N;<9t(02WVGp9DMBUy(o@YsXemk@2UwUPE47Se`#zXE}i`s zQTiIOTjCEeraW;!6B#?e=n@MLG9n2{APzuoOkwlYh=9tyalXq)yi;MkmZRNqW5^`` z3|W?sadzU2Smi(jq=o!)(2N@hFQ(nAR4>Ee0n1e0uY_*>5=1ZgwH5-w$l zRyuYSd|ib=9fv`({8XV+SW|`=lck_6xK0C-)yl&c zdQz9OsPHED(`#bAX$KMa9FjpoNBmSdd9RvUFkh3G2HzVqVvhwn{|3sxoa~w?VML)s z45EoKB=^3JI`qVhovq%i?Zj2l6M7@Uz5y+@OV3PWSke}y7WeNlA=pE3Kg*+d9|0-k zu0zL&1%{ZdC7csD?KpisHyac>RcOxMBwm;JMM-^wR~LCc?2zeV$BR5T#jTl?GeBQF zDgh`<+JhyNF(l@0&|dUk9v;y(mx*mBn>i{{kJ-`3CSM#)1*F7CV}}SSUad)|ImKzh z5eg`T>M4a@Byv~lKYN%?I%jv1D>@DayQVMpyy{1vgw?YbO!n;qzWgLxG!?+HwA%?y zYY0n!)DR93Zssj@tK_o~x?(6O_6s{)eI@YrucZ}%rfJ{m(@}GkFw~19?fEN?0rO-@ zvv}SxARZfruZ;PR3C2kgchIacN6IgrrzmxzZRG)jUE&DL?wYqkbw?Lo%cZ)D78hYV zm&(LX%40_?mE~R20EIjpKUj=`aD3aFk4H-_*7@83$1>BNYxncQLx6Y>rnS#Y?%wms zhv^NLAO!Z}%Nk~Z*5ebj>`o~=2Krb`JaoPk<^E|((*?r%SA!YZ^`Hn{;994|jmO`E zNq?)0cYLk4JpXQ;-^W&;dJFiXI`WmX19*X8WEaLDT~{8SGIoJnY)vx*M2I$iD%GdQ-(F9~h(@ zyZxEHn%zWW!Yw7H&<9fq9h2FC-)dQmGX0(ZUg`$k$#J%1ap6bU)@x(=9JlfAn*yi_ zNs)LL=o`yd-(LUipZoC7wkz@02_mvV=#ZfFVQeJ>E}PfFAj&$D`3R8zCw6C@GB`8nYl{Amk^j$aN`&8dqKMpI>sdAGmSo+t2-^7zSeo?W45 zh7oykv=`F=Rq12((X3>Rtj18YY-NQHtu&6&M>Xh*U6iPn+D)nR#0pRUPD%W82R*E`mS@ZDbY3mN*1MKk}ZtivqTkLmlZ>~d(F2>Myt_wq!^!bPb1wThn*KxsGP^=p7nx9zGL? zV|Mu@wS5C|`M8FRRwoZ~cJ7DLl9r?2m1OB5GT|6x&CyZhdfR3Uy$hnGc;i}FetpkD ziW?P=b{P??O;k4gzlB79ARvZosM@jsTqVr&9!)wF1R$FaRMeWrZ z)!KWHE_>D9)Gn#LD=3OmgeXdk)~LNlf=Fs_YKA2Csu4tL2LCtjH%M|_dCob{J$^!e zTCRu?V&&03&z}nupZfGG`>|wDwz=2Jv2rYBT*Qe`Zw-wy;)dPaT za`wb3dY^yeKYvjA1A<3=8?1-FCJ#mIQT0ml+)ueT)K@lTO{p=E=O$8M1EG#y z#BvI*{YQq`cJzGJJs7{Y%iaJTL%I=KfN-%jcYb_r9jiE12o?kNbTwOqhs)Qds(P1Q zkC$(^Z1X6|iZ+<&Bv)bdx6q(Dj#iR4|G?)zGUB9?2rqPc!+#5+7;7zm>rbzbt6uWa z{%Kd+k@7%kqcB{&>i*EA$eZ`c9)v?DdeGn#l9EsY@vE6>*nGkcP=K%Zg>sJ=SG#A57>^KydLKl z?qCycW%FAOy1!Hn941ACu4cKR@R?%o#+HM&14t;Vde>)ln`p8H%q3uZu(l{WYcx15 z68(1QM_3AgpnLuwS&QT`g0sEzO|q{yL7}JOKQjKIUn&&d27P%xBclZnzcLK5W2p6? zO9}Sr)ZA+V|EVc-|Kvt%#ls~wnMlcf=qa0%{~Y-uJd|@YfpH(cR9_hifkxh}3-tQ^ zj*#Qo(Ty3HDDrkk*k|fNUi>BVqLErqIrCsj7JRkK3cYNy??@424lZ|Y4uwbveh`r< ztP3!_BxstO$&b?lKE^>-1r=TDVXe?$jM6r9>___3tn#sm95+(=TKW5GFLXo>8jOAB zmH~%a9O)ZBj>)AW1t|j>G@i~1q3$EQ8}up%*EYOJX6m0rAtv)QP-E4zZ1gxwe3BqZjkem^RiLHvvD=5d$|LzP|828oY6cctrHp2KrKeZ5REg%b z>^J4TGP+5Rx7n;iP$wFiEShDOtR(4$(mr`x(%mw?Le2xW4OMQ(lcpkRPXbCN>HwMI zdlbE%q-dc>4L7N9-0z_K*|~(=^MVp@w&tICX&8ea$dhpR^JY^ffa2@=ldQq}yV&FF zz@HpB+ZP|6v0CybvmH3DFa!9JO z*&H*pNuNbliefl6Hk_ zs*MM@-DNJcQ?I##O!igd1E?!FvT(-?zh}rKN|)j4^jI`ERT4AVLelFE&|BRFjU6Xn z?=FrK1@ydDOgS`L6h+BYtt#EBiyTX;Q_Ipaq4D$H8SIicn! zU8rxXViCc7b4z&pz<2>&vY!7@WX49I%IKcVvJ;yD&url&uBMrqku8SOYE&Y@*3B3o z<+q|DBUx5*e}6pV;Bq!hoqY#p^) zF}1Yz=tF+AhzQ*JwZ8T=b9JULMXuP)cKf>8dQ6S?-;)%7-N|(fdm3hNqoU(g&96?dxlXA3840Y&tZ$1R2~|!_t0uJ z_gxcM@KN|^v}8kRYGm$~xdyl+bCC4T_f(7b^jGztZ2R&e_OA*f6MchCmla98rj)-2 zygr^VKpZj6zuf1G0Y#A{AsmTIT^s05<)CnwWYX7}! z0-xgBIqv-th>n?f^v_z-wNi{=?(can{uIl(v&PR~SH530lg$*I?&}@X>hFbL-~SNP zIsW5vmuGdWhmwm#NRKz3R+(-yg$US6T3?m!)vwGKyBXwWdKTs1*{F$Jw#VHr0lK%q zGTAtcW^kFjF#D#L{#3%^;RVkXQ=HhhN_7K9`(m|>x3vHEm3a7+l?~44B`tEr+fB{c zziJR}m*lNMDn+=lD}~5E_P?0vZH{}t7~=UKSx}N4-v|9P(!9a>=Vz?tb6?d-sm62B zW_9DOZEWlmu6AuOTCOgsFCRE&T>&`udLD>X_^A7O9Gt-Z1aKvo=Re9{TpNq~H-A;J ztxH=oFi5yH5nUPp2V!X;f=T8Y(}3pD;h$p!T_rp4^f3c0PBFIG4B8TcT2H*!(ohk8 zkapeC2+GV{mD{hOTQoRMzSOOy)PUa+g#l}$Fwjvu4Ls#Z?gWs2wQowAjl)sCYLXA0 zQKYlpOb6WayPFne+rbnw?Q30)w?e%>^XE^B$E-~{HxNyc^CwC}PoF&eQu4&|i+rb& ziOy|1fqliliE$3E{CqxlY?S|1aH+7jMBI9Nm0TQBk~wX2l{N!1Yt|bl`d=G>n1NxYZ9&Gv*zl+&6nB`>!_e=Nvz3f$$s^1G4 zM!JEfgQU63;O=z1fV_IIKy{|)_fn4qLbuTseZ%Y?e=0RL_Jaab`-nD_=H}YG;K=dqih!bGLD`14%XJO zw;7d(ST5%-Gi{6bPC?(+p_7$Y-_E_9(<`VE9$#aJ^LoH=yq;h}I}MRi7%m}LF;K5w zU2iwjVW*oEZBR;f$H8=Sy11>)cFNN>Hs`sg;jF|FiQS}589tRup zo@9=?_rzOr{61t2T~V~@Mg{jXs4FifI88Y}Yp9e6pAWL}6fqdj*kb-mqpi=URtm!~ z8!bBDlulTGUEk7N*=IYrlyUwsLcUBS(dFUAv`_r(?00&7A5v@*i7gH zdTk_4mc%-xQBHH!z<^Ta&6Fj_1Zw`)G6ajx=PW6rAZ|&|)>9+QZsjY6PmPMY>K14A z1XDknov4u1Jshg}G6yrA9|X#d=AKlFFYqGWQq-Z)R*OtNbT3Q7Ia;r}Q>D8xs3LW~ z;p_YLG|0wXzI^3sf5?+x zcx0M%ZDQmZWU?%7zB}%4G2>bvA|j)im{O%;HbMpW=I4o4ZZl4LotrYd^L~XWjM(PM zP6u-F7Wi)xw6(4#6{yn8d0_7?&AcYQNB|HSP&<5P7I`A*fucqHWW@^b z57PIsZThFKOy%C_Q!tA?{s#e@>cnGOFrKw-+tIPOHgz?5m&KOx6*#iN^(Tn@ zu#5^oHKp4qB>Y&In0!(*vUTI^T#NkJD(A3j79~*)2h04y*ojN|F@;yW<{uGLxDMp2 zZeLJO*WiW+;X0PJK7V~|GRMwCh(eKf&?ZM4wYNU_;nGHu5WGAmnWx)zg!4Dk-**+r z-w=@a$cdEJ;^d8!#*U3tRJDH|eyp#vR>rcLP4x%87sp)KNT_dh9Bmw+-*f`CN9FsP z{_D^mH*0%8v8n~}+RT?^hvaT;1gx=zITctH>M)8AZfM44GNeI06PFR2{@@MXzv7sq zN0`dkj(XU4fhI^c3J{(>SMh;F-*})p_S{RU+|zE$UqMo;Y?LM!OnX#GD(KXm+$1Vo zmZ8KNz49KXIlJ8JJZDRlBwfVFObEARRNuqWvIhGORA`|dRAAm$5w?r)nMw&%W-WWw z5?l>C+^{0i@5`g~iQ*B)+7D%Hef86H@kwi%9cD8!cbQW><_~LGOD&a`bDDE{(7GFF zIEca{nnSKnz}ZCac6KdG28T>TCgu^wvLPs%_E3y$OjV$EQv?^S35PXcW@Vx2cg4hB zqSeFQRc8EoLOrijQ|rSM3pXqt|3+)b9UKtMh4E}_chU}1Ru>o7JcqI6>d{?C^2PSg zn6l9<77rf}}LK5H#v!5nI-BRyi$?TdpKSts*mcI@UcsjsB?5^HvA||MEfFo|c#2z!nyR`Y? z9~1YQK?$5Jpp|w&gRSJYHT5L61D>xtad0;!{e@QF$BPtLFF=UneY>{MW{N`0nQKZ4 z2f;@7`8C_vreXv-Yauu zJ@#@_uz1A&RQIWVyGg7!nEv1Bw0OfYo` z84Ar_#|ij^@34*D9lhU^bgjQ!RVS8hewHFjx7c58Z(V8qaAF=;57q=hHgtEE%@nsr|)uLCJ-%V5gS!@gtf*a!b6H}M|1!Fc~p1#Jd&FovxrTm1JBpYJS*OpFGv~GuvJ*%U2&w;p~ zjwh5iwJuJQ}>tV%2$#pGvQu5?-yUSTiP^KB?c{1JupYk!p38- zFimsMG&Q@kcs+*rT^5%!`=25_JLTnh7Ap)IdYxWP z#+hN7EpVPOFqLEFoT`xqiEDz_;$fp3*ncX@Y+y$|5+%Td9Vyx*efp%21-^-z&PRJo z&X9Si?C_;^n=@<5#e_5TLo9Ya%YSQ=KZ+nMvna+kV&b0R|MxFOV^cs~g7RSW^;6 zUlmM49;#pEa1KK1uI4&o!Ec5&TP_%Jz9*q|2&YDo1@Jxk&5NT40zE+_oj&EoNY!Yj z=|W@hJNZ?FLi$M|{#QYzV4e;x6W>&U^k`PcK2p-jd{N9WrqM>oQC+D}3U_mD`2+A< zdfmPc_p#yaH1=o2BHXwP?O$`U)vV@Pskqu0e@@DAFK`&btv5({vI$;RP3--Z2xSi} zF%M|pDs~<_625*z!s2wG-G`b#4gKS zn)A~2?IRNm3B~qo&Tt88b+*-|+ARC^n1;G62j^e0hMZ+Ztu zkQ5^hpXH_*SNZ9V5*kC335pKa`0cYu0WAgx+un=}lIQxKhU4N7JgKVPaUodf!T=Wcpml3{!X`#qF%PCU5=?I9amS{nM>are`HUH)1t@KQh_ z`o^E0tFJ>o@9lJka%mrqV|Io-bxs0j566<~1w0o{6T;^@w}0=VTMAK4=1+?~Dg2MT zyRTJdl_+X#$5(JpmXlUHwvAUQ7uGJ{-EMOMsLFVv0Ux>0I{nlDUx4bDW}UJPThJq@ z(Lfei?jz3;b!EJbj#c$+eb^&^(eGoX)?NqSjvl4|CZEmb&8_5U&|;%$>km?(jlw98 zhTEpC5Oi9@uIY4kl`WeEwQ8E$%Z|PZ!^hbnky`}=>P(#fMy)N{QKEG2!8VF3whPhc zpHBG8I}c1Q#~T|5#@l4ywp(wkN8acs6oc5Z8D`Q@9=L0s+`X-T(!YKIyXW5oQ+1z? zK2;$d1^i`Ob;s2Q_b+Ym6rc7MsRfPN>ccT4I&NT=U{vz&Br1Oks!AUa=ja$R5J3=A zrYPlXVo`C9L^j7=ErtF0NnWS?w;?ROVs8JK2JPR6?)XZH3$sLEs|vQQJ~s;9*=4bv zLx)|QR(v$?A7=}RxR95+3N~+vWp2athVxa4?{7JN!M-EEFz4E&49$iD+oS&@^GCi? zets#jXYOJ)R7CFj>bkD3105zryvPw`i`SZ>e2Zpl`Uj zjsobLlrLCJWCMs~8T3(x@Cpsk`n&~rIp zI|^qP&MZ5@VrhASTZ-vlu|@5nsQ#SgT$`Xz7L9t_5Bzh}K)W^}1yPWd$S+l4RFQvO zj1L5ZJQ^vb79wnCgwl$WQ!9@qSc_Gk5l8I>1+f>>o8mw1kUemt8m7`==$ZSZi+S*A z1>;hn$c!f`B2n{ng4efX1D-ZeF|bPz6deYYn0ekATKJ~sQGvVEZja0`!f%13YCm7! zL!yo`f2*Xbm1VI8O)V3ta^$?Z`D6^slq7vG`iyQeRCsmJaHb`4KxVBbT>F9YnBcEG z)<*M0?>~Jd+J+JMe|A3ul13??{=+n9AQKyT4^uJ%B{XMgC4DN7l4k}&yiY0)xsnj< ziy{5$sOrE`&QWU|wPTmo6TwTWj+e?E8a#2Is z<=xDy{78>+@`y<^RTk%?*(?*HB8{@jdggjcN_8ApMj%3kRGM%&-j$Uz+gxTnzui*L zVrS;Lph%`rpq*e`&f?deqh2CYOD}oNP!r2AIg;a9p;_QN|5~<`^LWBy`w-n9YiGVs zYUPt2zkGgHzEYdaNe@LSDVK}cG0+fHrlG5-R}lZ%@Tw-Efql$$QQoNk^JWDjYgp^4j;m2y|eH?z=5_E zNLhS1I<2LjAiF>kQE8j~mKI99As)~neDu+oyBniIo+-05ey1Wj;!=+Q$J}tqwE0K2}gCB8A0GvpxZ za4I-3egwnkxv|Cu-GQ$2qnM`eC>zX9WAj*T1;o&>MoNlTzXz}KT$iz=98#sH& z83N}M$yM?nSt8@M`aup4lsE)HEVL&hKf(-BhFQ;Kb~Mc1uO@sgT{wTiOQMsiOddao z-{88WH+XxvM4Drs_8cBoy_*o%s?#(b-wJ!~c22*I0*_@VGlz=3F6s%<8)!3eEgiAQ z$<}-p8b~_ZZlB~&VEUE6Is8n{eC1OGAE=re9i<6888`-)=+#mV0*m{Q=cv!Bh+ zE*0rnf3$`R+4FwyZzr{l|B-neoIP{RBQl*m z9XnE%4(xb!jrTOWliHUS!}1~P#;3n9X5N2m)qblb@}_p+lWeZa-;dn8Nk2Nk^R^ zB)puyhipYJT4~>VJt)VrhT5owiAFqojpsS>sK*OWi*FxPZx?Q_CTfJN3FRehv0R|~ z?GM$5f6C%G@B$7`dy-vkzqCVL1K8{T-jO?9Fjg8?%toGrgFSZ)S%|{%q8%u6u}wd*86qYn>HkdsA`IOd<33x z$W+g^!Es4EC+Dy4->|2;UO?8{e^PZ}G48vjVC1|r^*&mhAYsRh-svGFEb4N9#P7}d*ixI?&a$+lNZB|!pMZ68mf zQzjd)#v*ZstCZDtOEzKF*--ZgQ#isPy^cC@=+PmRU)m+Bl<~%d!ioNVP^Q zq_pE_X+M2c!^H#_74F*VVP!oa1=`=n99|2Ipb+9A_Ihzz$QABC7%y{xy+&*O95oh2 z*p=y6(-qXrIVybysoK1nCl4CI{aYt`Nf9IILvr3jZ_k=TSF?+8k}3Mul`kIJ=gCRvW#U#Gm7dAn4{B4}o+53J6kM}btErpvCiPku zbVRnn28!g$=87cuau^Js`O~dRUQ6U>n)+-2!Rhkmzmwv&v$Sf9?l0Cx@j&}s(tJ!F z91I@@jdfT!cs02dn0L0h+pb2E3MC^+hihv)IPzhL!d=q%mKqnTeCT<}o;MQqF2ly{ za6o!J|K?RHkdO4)KFe@QoK;qMWM+QEe3x1f)k?n-AaFQ4ML&A5o9f$?ugS1w&vL9j z4Oat{FN8vm1Y2eV4qCq-pC|lP2Sl!@#zgQ$pzR+u)zVlk+V5n}R&G`qj~E+Ft+Kt= z#;7xqJtME=fZai4QL?;>)++dfXEdj}<7RxfKvr;RJ=s2)t6rB?zj-C}nqxGw`aME8 z7yUcS_)g$AP^z=QhVL$@ef$-m19U=vW={Hha=KsN#xs3^>y?L0YDU{C=O%C@j&%z} z1=Zg#O#(}VOIq5uK>L$%~!b|M5yvDt=v}E!hgfRD8jeAS%sA(FLUU*pm;F4X&OvI#>S@Vww zQk@X#S8jQR18Rkb^G&xLYFY``1V4MBx{)ulru-2l>EQDR%bS$kcp!3+7Ln_pcw8>C z3{gTSPP$D-l0`b&Q*cEe0oBjySA})n9QLj^SZ)UeMYh6cp5D6A^vHXmOi1$p%1@rN zg#?himfgsE5v=Z!58)iEg2~=pRx@V}&CU7JglY@5)}+RFfjm*4BD})!5v;HA8Yc)m ze?0I;p-f2yX8!tQtm`($3BaXJ0zTgS6w069%^PLcNc7bC`S+t}bi|D_S*u2TX88*7 zq`*FNa$#MqBjARU<;%I9R>!%qJHLGldqbN&^ch6MY7p@*0zN)+_H#5R4DhQu>0}+V znf;PUAWvcGL21mjiWjd_Z1TMU&QhLI54`smP8Jf;NE6khnUSL`Xp}!{yH0g+ z+9bP;!nBoY7tZUR*=P|Qma^jJ5`xyNU%TIPScC}sSKH1z;hew7LW{b39{k*rHfuN4 zAM}w_bCq|^=V8Zk=sAig2=sMo?$QzPpi>9mNQwFR|7IsHB{dGnZ^UEdTszdW4J_-~ z&5XS}&e^=~v>m2B+H(c@3>2=+-uTm}u%ooV+R?0PyYksiv(t<56;e?^m!(5xTmELI zPRx6fI-#DlWBX`u9iEnS^eC-Q!|wQ;TDBh-HUfQrOtP4Wv&)VL@(3)4v2W!!)nEUK zc#Pro0|X!4LzvpPXcK*R*wdqMHj$>`mdA#N>ec)8f~4DJbVQFpPo*~xg2Z-*cn@_* zEQ#SR%t@!%+u<%6%sIT%PD9?f|5Pv*@4mBZ= zyH!hn4>7%Wx8C1cX>3X#4dCoXu@vla0Y?`X-R)9@LjBMCpZqG3*PG{s zhSShoH7HRQy;soq47dDcZ9Q)jQb<U2-!g_3Y%DMf zw0|r0UU50CZYUqJ2-rN99DCj;_p1=BKdz5(o93#cZrh>vsOx4E&BUClJ?-uKZ2FQi z>_|Vfw%FVPbk|Y=HqSYP{Hh8| z!bzLUliAa1cCUmjzW$-|jktyOPdBW#0;xGqjleQfKZ!b8&-GF@dF{xlZWLHu)<8)s zK)nZ(O0O%`YkITaO_xBom^o;qhC!fw9)!h6KL2bmH|YF}_Q>xbSBl&)yq&=edM6xp z`BLBn^$>Az#=lDw@7mZ{ugTpCb+1tk>GY>m_swJmI>%sr0IzoS6h0PdNon!qwHK&L za<*H9nXelIKjJxhQmR+=3{mbxbj%Pu|1+Jx-2{>D5{S2J#T#o+2nTj(JI}E5^;X(3 zYVjyJC)|5$LKV{|gWon5&=bTG{0r^@-iaCahJ_$Z!-DHC?uC@TO@8C&o$UX2hqN)0 zFJ#n|6_A-umbnCb5j!G`m$pr6MSdoy*o}?&D&)@6YJ9h?lNJPk*$Jw4Q$65q4opaGe7JjR5jajN$wz3D{)Mt<5Ta*`dCSTZDL=9biA%GM}Iq_TDfZmu-NRIXSpb$s#d*Z0fu@Q*eFHcqMp7iF{3z5irr*_j8rn5HYW` z<6!piXZH0nv#Z-WAsQZBtNQHranLxWWt*U4O)q6k4fS*UPbjMAVfnnmf_||7kj#pFq6!&z$>&(pF@a4 zBE_5k$TD-o_a1~F0lW+VDiNJHcGI+rE4Qlfc+I-FCI4-&%3GW!aT;-VQ(Yw*A{lYr zj|*x%EZ40EXsb3&%}9otL%2(;a>)23#K|MGjk-!wPxuJ)lB1#twC8%rKyA#-1u59-pH!Fby_C8V8~*wc2Vq*;?!VBPiDo8rKRE$--22!QSgg+ z7piic?xHTk@auh0&5Sza-jPOi&u zNFK>GRv&Mt@7odjH>4sV@5S|GWQ&RjxP1QALR$w%aT7qe7Lv|b)uOM>V80S8wm|GFt4NK*kXJKsc|`; zbKmFoJD+>wO8FUlxes=U12eWRl*Dq?=@fY7$NW2zedzLV zZ?7!IVJVM<`xTNpoPFm$qnY|N%Hv#C;2p)V&2+_+{^nqnr)mpRLh{>M@98rB$;?JTAeKBOgo9~=QPjaYAga~}wiVp{6kCzApK40YyL{fRK zp8X^`J^fK0Djgrc&j)j{jsmvSTlMUK8(OiZoAa^bc&BO;{GAfc7^187ORpA26r;ju z9{l9QQ@9p9VzlZlZIhNY_JHPg$H#!Bx`OU7*rm>@VCCl&c_|oAgIfnEc>c2cq`Z5W z^5MwKgjR}_=5ck@RK%Q-mLg^(-J{Eb!#T#NIR!8;bDqQopq^m--DkWpz_7PC!*6iz z7$P2XB38MmMuR?Ls|KtM&0F+4D9_B~en>otbO@6dDG`X>0&T!Pc=6_@R*!4{y_8%l z`*oFesr6&5WtTtR$SqoM*f7%DjppI&q&ndF*hsERgx!lOBq-neQu-AM{ckn<(t!8K6q+R+SQMtsb`qy z?h%G562rNU&86;>r4;L9fkgP5or_xd3FwR;x0QEzVARkK#@AGNJDEg@Bu&is)!(yd z&>A1-sqaeKXm>;;)VF1O25YzT5r<5Z6m7>OUM}aFe~IV{dbUX2CW}(Y%46Sr&WNwx zcS_O1lNx9wEMv%%#D^}-TlIKenR`gh62DeH9pnbF-yB-!^#2o3`*qCwxYdRTPf>!& zi9TWMv09RQIE12X3v^#O7amYFiPtY>`?N3XnryVgW?h=VX?(xzC~eNBI80p!9J+oY ze<>jEs%{=~pfcXvB1Ef+Z>xAv-5z~!Pi|D=g4wkh6WF5oeMq)M+Du#dQvQ*?S^87{F^*%4`L>f%f*R`aN<}6eFZR zDn_1x`&su9q?yUBdSQ_1a_-+h!ozdO;lXCH)tDl6C{cD;a>v@&)&%M*_ZMDqo_e= zvl>5!)kkK^*Kh~MS!^sQli~>CrJ}8&MC{ea`|9->-kE$BPn)}n8f+-PpVGFOJ%5g6 z$|dvv$6$8kAOX!sSmR7xZ7|4@U~%^4l(VhG_V5T1B~{jpto>|5x3|RLT;~RVsP{|M z{^pmVRdBu2+o%r#VGis;_(6h=mp!&!3jSOfGz=xXW=I17XD^C0*3W&8Fs1gw=59mm z3I***6bb4#xvKlaBx@M7WxseY>#o>?dkaZ~L^UX24n=cI@+phy(}(Q>mm@*)oh(XG z=*rA>Hrl>kRyoXAY+co&1x#(8z%;PMas}YAfXmWu`72GnVE`|_7^>P*Jkg4N!O_81 z@(?RMlha2~qikeM$dUA#_s`9Ion&IQfw!>JvL3NET_TX;R9oxDtq)$vuW^)}yn79} zUj-6_S)2feFo@xH{vq>DzK$06 z4d!&P1*dOH-;Z<~Lg1ZuyC-oAq8Z*#mloxJrw{q4i?@?j5@nmISSzfgMD$`}mudb?G7?>X^fTl;PHvZ!)14G0vc%2#TJQ4)0yZMsFnZv>>FlJ^+7{o(2O3=5Y zX}?$I0VusKzM;D<@KF2QttY8lH;cgTwZ)cIi~OeVlJZ^mtv5dip7c{7N6i9h7UHz3 zuSX?n^S`u0fwGj)dgk(PRVGe;=tb$-EogQ&uog0qj$_;{_;%ZDi+T60mPexoCxhiF zV^HF2N>9VsF61qGQeJ7sUP8{ zpg4(+bigXjqKuh)o*4c%>%n8KxCsy`rq;UQYOA8CLe46ES$v> z`OhR*YNIh0Gt!j5>;>csi5fW#dV+NN{V~h~SbcReJ6{|7JLrZ-YWQOLsv;MS`;iXKe6XHEPnV3ln~I5w5hqe~ zag98fvw07B>yq64@N^}D)UE4u5=wV>Bh(6OeGYl}OaOm4udKD(j;{hZ@l)}Yo-`?l z%_#)dlL(0ld1f)bQkm^fNs9|hNPzJjbrbem8e8(qtJUb8FPK~93{7M0roqgXpe4nZ zYo#{EUI8aLsNwGt+`y`@2{QkY(RTAIQ&{ByV4KbAP_w{!*$kEGfU)4)A4fO{;nx z5K6CDn2;pU9>Pq0w1r|Ye~ZX;9qsv0&TLAsQign5&l}ub{3N7z&+{o=)i`UtUcJ`o zr$Kq+>8)xtH>$LA@AaOlq2LI@@cUuT--r6o3p|3RE@84#LhV84jw>du>(MG+8unwq z8lm*u$ZSCgFV8fY<35>kbhmP7A&O(bb()SPJ5eYZw!g&LXQX1<&3|T+W%ZV5bY6G< zmF;HDT((Ks*vsAAYiVxF-qHb_K<|T1G(@6`RANQlr}c03YbEmm50)5QxUb>zY)O?r zV@juh)F=afL6{amfRbw)Q~HW=vc+=1qm*`1l?-nsYWH&rNewawd8511XD(CWlJ%wBbsVEh6D?pR3S(gMg z!VB%Iy9DPm7ib^Yhuui+dSl~EXpb^Mx+k+=>XP2#*&)GQ`Hz#mq*R~qM=w|he5j?( zDA<%6beO6gP70_|T|xGdbOg8S`)Z{-5%*@R52RGtUwk-z?m4UDOi;HO3clTw$YWPT z;eP`qJsp9Xg{rn_;Itf;!v(sQG-lw+^hy{12%%sh-r}-l>-}|a8>%g#BEgui-;67R z>x;b#{YiioRP^}X0TBRHo>970Fy9ywJF_oT_3J1oM)0>LH1!tMFzi!^5S;4x>h6?t z>+F-1^OlkN6>A{(!rZfUa16_6g#TIAZ^YB9m`HbnduO%1(1OD{pm>FSm0r0HSDrs5 zRb1pE$8~_yCglK+xBMzn15V)!2rjDZKGNXPxO~dw*c~ab@PI~pwYRrYC3fZbPuANy zqA9{kI-7L$<2B?SU_R0$i7b0F*^e|>g^?pQRZDH@!Td=$so~uOUYArs?uN)mVJwZm z*L`gYdJVq#U5XzHpESFBq3GQ4Qb>h(-Ll_2Dl4j|fCpk*sFh_GGF!{90L!2yI~OQE;YSW_?DVpK)4& zC`PsV1rmw^W#?*C)Jzd1_V2c;?zN~>{HV@gvAA+9h&e9;$tndBR9`B=Sk+!6KfS!# zQxyseyWe?MOI5jSYo_RudA>Mn9zFK_&h{7G2Q>P6Kw*DkNXU*m>#DLDZ<-kKdaP{E z#3>q9Ng9SNTS-a|8}lB)yMYeC;Ya1daQzX5Bh7_QmR&2uqGzM3k|2r00*Rk-d0rvJ z@(v<*CT!cg+U8BNppfLbenWW+_|>OO=Ix_=`A$Xu6hI?sr%Tn1AMT@nEj-$rpW*H0 zk{_J34nJrplWtj1MjW0r8&oXDGmQ5F0^7K<*|OCp|rmWxZ1Z@q!x}Q$VXBf zra(#ma+&7R9+#t17*X5yMh3gs01x{+&`RwC_>{}ke$MD+>CygumA(+G7oUDxBlRm|*<^W7A` z)1H1y*@PYC%(#rQ=E)$o^n=yEnec1zEn*mftmRH?)S@5KL@z$vYcmt8`Yh*28Nl3c zY#$0#ZH9p-8MAPlLF3uBpL3yyjGWO3vg+jBf1YmSkv(*n%e_{Ulk|$wodnP0(OVAuya4CMl*|O+( z4wj`M@bGxq$&pj!H!X=5r=<$ij0pTkc4v<&A8!7eX$cBV5%olk&InJOikuRKba9QF z?6J(9kA@@9o@w-02f_Gl+=cgLz15o&UD8#?m_1^@gzPyPUCa9dKoE!?;K_baCS@OZTkcw44E zgE^$_ne|FD$@v=AeJwUQaXlWUlICOTY1w*r=f&Ee=ZvLrT&#EJ40%M70 zb6qeya@y1$ItqqjfI;3<-SRG!igOxN1HS(OSdd7FN!-4sz2rx!NQDe3Q*>um`Vh)P zHzB7!nBGrXL1d{ELw6{iwtj&MdYfT$MP_Z=>n|yg`p1hv>a&UROZw|YTNO%6wjLRz zV<;vv+nY6SiN~2Nbe}qKNKddRGq1KBMS=`d;ALW#J6>BgqLidpzx=yYK1QTV4)T>N zi8-FVeTZY(#n~yYAgOoqmGGQdKejVRWm?N^NP!(btxzt%ve$Dye%2F!9h&)m9D?kO z1Y%&?m4Py%MLImBFt_qR7tU2$6hk}a{A^!3t5l=>Eic*HrV)I4_pu(DOY>-5x|PTf z45Rtmmn`-W8qDsfuMVv=O9Ft+!Vius)`upd=_soy-qak7%|+>CK;E+7MdRO zM&*Ad*lO&NJ5EK+u-;9P_LZVt&5QN~hTsqS;6Q zVm-5GB*6x%AdmC@W!c2$0+P|1)-#a$0sbFmJy9o6pwL^~#%=gK$|iV=*yJxiIgPm& z6^IY`YrLr6kK>9ZMVe=~!vHj3Qv70`Es{Sf|4OhdM{XmzNMjKzfjbW+XOFSZL)+t8 z*C5o&N;s=k&6TTuw5gFibA^k#$&ILd2?djhh{XuyoTcIGY1sE9;P{5pclN7Q$#c~B zP}2US>i;M@%ebcgHjJYpD1s*+3z{t7q+4KIqIG=NN_PgV{zL!_R`-p;^tn}5G1SzO>J%Pjr*|2w3yTdbx=N zoTB2?Z!Ilq-C+>z3!~^yBF6MCgpDX1DODo67`B4_^?GRWV?=5s2A z2^Nqx>KvtV?xej17@>!u*&NmOe~w-Lj^)`sYFSMmXd`M5B5`8KPtK_&m1rd8(lM@> zzQyV_?2=SEN}b<-90u12_R5sMEDfN^O$6=uW#L($P*H$^7Ip^;3)>CG-m-$IJoUJ1ZJI@%&hI-mrQE1FBukz=J-G2zW6m{&X5OsKTm?foeu8 z&-j(*lN1Y?3~GGEYzWdhzy}Y@$@r1A8jEyT2x@az64(p)y@!~VFpP#_t(8VGhRLDe zFE3tDXPxrXjt{ZBbnqPGaR;?T>$+AcbE*=ObxCPG>4#nOnYAR9s4#Q1NzEgij6(Dd z)hxgwWz<9(ptcW)9vxurg#~vBwbgr^i2Y-bGA&|p{k-{B{%WA^O43m+ntoE8&BX|w zB@aNl9wa~8|9<5pZi>Tzw)c<)f9aC>Oth)S{B^SMQh5G}BDGF*pFPo5D#)-SdhRs; z3B;`62mj}QV?M37U7OVInknRo{sH>}rBcK-J*Yu2sa!oB@DT}6Q9|0npgM#Q^8_W4 zvDoFzQ>L90=l!E1hk=gtR*dT_!B!Ei1@#}AlDqAJSoh~KZnbpl)AHxjbd_E~rm=qv zqc>31u-5#dVzcQjCl{l#CC!qvnB#EXmTvGJ-0ROawn^FvmX=R7O^afhLTI+z^ zy-70Hn&da?jS2PZY_7ZKt7(S=xw@6MW=e)EVxxzgAh=RYYjzwReCh0q!#rw?ue;tL zy$6{qg26Y)XwNKw{BxTw5bbo_P(hJ+_sVI^DcOQUzbfWA|DL&TR7>bThVa<1r4phG zU0f~l+!rG$*d81IMp;W)4lzg`H*BF``#9lQ#VL4$2am*k`JS*#^GU8Nndg{ ze{~#vwF)kdq!zY&<|7C(AR1oHE@hr?iM9J|Z=Y-))s%JCOdxrpJGnn1I_Y=FK5i}| z*P)Du>IogyGt^OWDC`;j$}Knh*wF8cYhl2>XNxLq#3{}l!^Y@s2DJ=T63ElY8&3aI z{%q?z=?VWa0ErQx{q~>3Y#<$%j_S)^c z2gWZ(>8z+jBRK5dw>-}0++n-X(4wHJX@?lBge)XnI+u^us;C17i(iCfQ`(_ zQQ(SgZcq1WL-7TlTkzYn_6=+k)f}-LBh8dZ(o3 zL&Rb*)NK?61 z48zJSp-=0KW~BLe=#5m5W!t?qG0462AL%Lzs!lhfw36m~Vi)p)V_V@LdO2#xMp}A$ zY71juV1Ks{(ASH52)_@GcV^e8W9u~Zv486B#}Qm!_15<>+!cJtNL8Po&yl~J+vR{A zI0Wt8ALYFhyO)RHD$8;h`Sfb3e3PE$sC^=JATt271zbB*#?7Jo=M<`&@ga&IQh#uK z$+kpXvIkh!GPO`MW4-;*qtD^{duap>@s;k&w%sV9WxIsjLfMBS@qs3G8qPn^7Z4?cU+e?w5$)v|yLj3pRUW<3fv>wRk;>1nM1f z@-(YMcPQ#fDV%S1=GxRgHx|UQ=}#5Q;7DO|e(lfJU(a)P6e}$5#&z9L{)t;xTspGbDQn3acWd*@F6?}8TGJZT>Y3j$>jVkihJ@6?9%R1noOe!zpBa9OkiPi- zDLRxu{8wjM4l}8zT@Fy2*T>z3-XfB|!P@ok@_S{$ zhJp^!&7FKiNU8?=ckNYg@+JJN)EXqH#HS@LzxMV!z|U40z9S0E@98Pcv8R6D}^kymSQ@%-SC zWS*gVeR-Qvp+^k+=V;u>r)Tptj@0J{*|6g)Wquv#dYW70MoaCF-e)27XeTYx>t?#( z_GWT>@grN>a17rW^J*>owrzR3#+|i4mNa0a$K1A?{1f&GSMfJ|{0UCA0sz<9F2*x$ zZR(feRiWIq;>(^|7vQGwQQ!IVY9cP%92lP4u`LXLL%H_*U%wxXIh9n<980nbQaQST zdAv=wW`V$Y*smyWIP`M9p+M`ctz;4lfHqdYcDubylXANGfgb-DIK$I^dJ^cC-+u1r zBVC5ZtdFi=y~=xUFeb*Qs6{~U_j*RN%$_KkxVEu1$ar*NW@^x{6{L)J)N-ZWCr__s z4f`$Xb%D{{o8PFiuUWRs33{IrpAt5goS0&SYTw1avMU7i2+8jw-&4SADwZ=%lIT@< zu?yqfB(Y=;X@X`PCQ2G_-Dlgrrrmo_kyPh)RwtQ4u(uCri>H2FsbPeqa^{*B`a6zOVkj#`^1?3 z_S3`P4HR=r;g8#?;-*tBi||8OwSOn#5d*|8pAVgtM^ZR}oxvgx)=oYgh&5F>*dX1( z6~;{YCzp^pb0eF+e02qB)~EM>ueSK9p_cTWLqJ(LQjFUx&A-k|`PbsPb?*r2AZ8A) zNIzP8gPx!J@baaJ{U7sw6aNkOEh`EK|8i{t#caRadQM4G)9-sL=uOn`S8eun+J)}} z8t7J!Xt~-SQn9W;rX`2yZ_&&KSz-I%?-u^hGDoPdmBXUw5&*_$@#?W}|1J{c+aq=! z^#9uR`Ir=1K!J|@C7^#_jTvsiC?R-%SURq z7Q2ttSA-pFMs)@3wAtV^{ntrF&2<;jDSi6UPNbwP^)>n16ul4X2%}ITOGtY28E>_( zIgmPL`sL5KKn54+?UIV6CQm#c!_~eEr1?=`(`jEc&r0b=YJ94<`wK{#!?y;DxH`bM zBDrGfMJS=Wj{1%J5U}ag-m1H#hM>Fg$Pu0mi{aCzX~0~Eo8rH}xn_A{i7D|HX8u}r z_MKXPkDBLk`#h%WAOVtiYG};wyZQc4!=qQDVjFI;d#-#2w?1A{{hRmK1i8xmMoS?a zU@%RIuJE3F-B~<(0+lqAH{dV0@%(%C&*MPNosCXq<*p8WpN>kNa0}})ww9tEm7Q_> zEL&P{SG=bvS+hS$YvK=r+xNH0p!ihR8lNuL(aw5|@%w&@ulvVT^`dsNRn)6VEivtt zJ+^Rp)GD%1i^EN)BgZB8_^R@GrXVM&!IWD#J{oXAzbSkp|SoVE)AiRChl*)v(CYydL-un2D0lFDLER5MY2MJh9o!$FE z8={-}Z#P&EzCCgw<(3}$ylRa%8DZwTAgD)n@SdR8aK*0&y1st%sz-HHB%kKp?-N>! zyY#gMdD?FEYu^06${0R?zDj5;Hw_qwx*9?|6*->Zn~-bq>AFz~`efyT(mC&02Xl^{|)$~CA`p57~ z=Z|*MPoPs#Thg4)!b8wQUothCH%L2%{OafUVKkGM~9`k(yA2l9tSK}FtvJwPUk`hMFgDR`XeXK#)B z;`D+ZW70?oOOl;*iAI4y*37(}yH|6~PhI03%2PD|KJ#18I(m5P(4>BbFx^`=iu%3N z>v(LB05wE`ZDU4CZIn>>+{xehq5aP#;JU707*hOP`=rq4W;_mZsJwZ#%Go!jfYY+e zCbvLAzIOERmFs%wUf%5{P6>P{$i8_t-|L9B6Hr`wvtcatTlI$*@H}pV3(Xj;@-c^u z$(LHSTBP5Z1ah}<%?UuaB2Tn0$Ffn&JdPHEw`c>30W_RUZftODI587{=t5nz`tx47 z%V)H8H8o}pIFUN2alKb@G(Jsrp~fbU`Da6;@Z&E91+x5a27g)3xUEQ*+(Q|f_jkKu z<4&eBXBrV0IrcQ>)1WtbRE7iA%7@PxR$(Km z+m`@;x%Av$5mMC&&+k-oAs@L-cjBD|vHl8S; zsih*Ax;rWMqLJMxvZOc1@||4|9I2Q_V!p zhZhqmT3)L;rw{J^(H1HV*)&L3Lg`q5EICDE%9#uDT*6EhTluZVNN}CoCU$8FT@TEi zKRP<-x`Ql#$GD}`I+h29ttDlu_9xYYsY`n;W1@7zcdc3_uC?4Q=PS6XKSC$h#l_PC zu>ibFf@qMZ^MlPQrJA_ll7@-d%_+-kxSi?BGFwdlyiqg0n^(so%N?`R_rhK2!V@>t zw8WsiG&0vHYEv}F{B1;4XJXUu?yfwLwUtj+&8)}w#TH-vyVQRSwjn=D{6IQsuE?<@ zFt&)vB%mwXqE}?XAy;HnQt{<{5wl3aDin5*KjxCr952-*dNub#&72xj+Dp}|4NYml zJM%%+zBaZY*bV#|#Id~S0d>319~Qo7eD6M)-}y3E#Hg$3En1V~W#Oq=Zo#U=CXk(M z{hN7_GK12L@fn!t_(naY9TVDYO&{~9|1}$vek_TOj07$wHV^kHTu$-h2dds(I2V1J4I-=2cPdWY z`DT;5ceaDL_Jo2kB<2r3T!kW zyuKGJC}wFB_2YrqitTXn7FJLadL^wgt`dK*Ky|l^cO+&aj3i`A7Nsc6cJWj0Dd!b7 z+Q!s{;1(T3Sx<;}3s#={8>9>gU!D$d%w6rMVt?1x4{V$rOw5~5J&KljPM_mV`j?6{ zrCyi%s++6A;iP7k#;$bi(22}-za=A+*$S>24$N44lX04$k@RlYzmJygJ9mIcs#AZ0 z;CARJ_}T;9T?6)w2M;P%mrE47RMXoi*QxbX_4X&E(LpR*l<5H{-DVf1$5yz$#4|~# z2Kn98ml1&{o$E3xX&YMjREJ<+LW-Y<(dJ^A{AeP!3)>Iaib}E zf)(IntafkTOxQ%STKzICMb&2AY`mhF0_Aj&L>wfs=+ku)j06vz`TfQaUaC$FP!qgPNu#xD8~b31ItRcBn1* za|e6JN3L3De)q@Hgp>3n$@MpH_wb2qY&lM}dVhFs>Gp(VQ~qqbT{ps2;}CD0Zz>Na zD{9$$kh7gX0&}Y54yzN2UY{#of!^F`+mg2%6bR4`5isi+sRHMV$hT+z38Rm>(nD%h zxISdRPOFB;25i6dKPWMNo;FmoBi-oB%>#E$7zJTB7KKwbhOIV>3b)t2rP}I(tsQ0* zzm@U`Rmh1fL&)Cn6fYd5$&W{R1 zgPZ1jkh=?+(Ox}@PhL-oabtvVJ$ zp7*Wp>j`Ztc{Y-6y2UfQ5D#!wMj~M7p`7Gxg!;<}pp;dUWE~!50LEo)_^HSi7Z>CR zT!&95sU-)r)NSjo1*LWciS=85uCEKqApyjBucRDR>*2L0*FRTNp%#|?acNAxkt-WD|OBeSm)m!y&sc-oBn;tjC-fDS|!{z7k5-*`w zEB8C5Z)FkLH1)E5rbsQ6H2068b7^N|zi?EX-{6=6bu+YCC*AQA;|--ClRqDx<`T<8 z+B^$F>rj-{P{v4|_GYVKt+b*B;SNP6Z$14I{g(LlpuR?j_9>vQap# zEfDw<*%{iP@p8U6x65_Y<3jfZutVGQ`fOvPt|zGD+n=p^ojxH|-_SL9sqX0y?URH= z#TgqU|o0h^Igu>2%N#5H*-(O7w{nwzWy>(%L5qWGR zj>S}{$ree|oc$W&onuDqy{%&z(=D>kq}4c8C!dY*GW4HBeg2vae{wSvGMal+Ph;id zrmto=xvAV);FLQY+v#js7=yeOQ!KH+h_C*<7Ht5xm#`b==L>Di4}GQuB7MT&Du&tR z{-`X5;LxpgV!sOZM<*1JN_1>w1ngB?p3ZgHz|S9+Nn*;#_ePuI8zNz(af!kE@`D1< zHn&7jF2qliP6%KlITk^}zaP+h}y$GHpL8)tR3$@B><~c&8ytofM z*L)&DvwEXE1Y3pEe3tORntP(2DiT$V#U9CF6Qz8HTBw zoEi-E1eD2jmoVZS!jj+O%G)bOPhdYmy?dO6juZ$Vs28y(fBayrC{g~J| zE%wY!yQU9bkPq`ZnTi?CGVdR;PNv0}9foYQ&6j#*+6fCwDCmtwr3hMyc>IKWCwms{c9isiOg}qH z=lJ%w@HdV8(K=T63~j+Fsm{ho(8>qeL6=M4vOpAC*L%l-TeU-FrBKDl;1e}%NmAK@ zUOToUYTSo0av$ir9M*zAt@J@I03< z$H-q*c>Cbc{&%%e)qoD36Mi`^m2bq8;MkHX;+oxDjlQz$Du-%f?xc6fdP6osHl;yYtZp-yKDElgbr4VJ9)oGfE%rSDZ`M$jOrA?R?pfqig=!N z%k}(;-pSC@ZhOA1wKQi44N0^LR>rqB!#`KawS43+n6e|ayT~*_2sLvktlW_=yI_?d zlvRR|%C8*Spw~XS6x-2pM3In8PTh`Ut*MuLQT5X$C75{z#5o=S=dR?MHfYWADRY1V zvU^FoEc?bbnZUZy7O{;Ll?Ma|=&*W1)J%}R$PA;dj+P0Jm-5`t%>ot2@YVc~YYGu2 zP=Sm}7YBs$XyI6(s@Q*Gd0Tt<*{8HE5GdQ)D7j<3Kxsho+hywXIHh;Z_&*J6$hG6vTDd$$pgB-Oy9b!qU0Kv-X z-j9+!7ypRLuW`q0N{q&*pOtZ>*`QH@^bIrg5QO`8b`J2Pq(t+0e?iu}0o5wWTd6sk zAD-4s^KX#fs!}AHh5zQ}l_oFR3=2HPdVJ(^sOGbV2MTrFqJB`MI%!k8wZy$tY<(-s z1_jLRAHuJ9<}EU|UVrijz_O_2AG9sGcezG)BRhXgHsfj{6X% zAnQ0Sk#XpEE?!TmT2i$P^6ZnZe|KX-x(r2Rf3W{%$Mr=`T)yj_pO@-0^_`6uET2UT z5#)9TqUd%h#_=(j(2&`P1WZGQiQ29s{oN$6>@v^Jme4>5%nxWI)OcBh6t zDa%zw>8g5(^j!J$9JL8{K}n$TFYpn%QfO(xQXL}SR;}gq8FL}C)8l!Et-^+bX%cX` zGL|`*zB>GMW{7a)o0Rf#YnU6KIqmk4e!;`9C zF?TQ?kiQ9UqHM|&idGk*KCd}*$Z0I!PePk4$nskKNvm6_(0Ei*TDYrxnnUwy*SYU0 zzoEvS=KqM|F-_rlHMiw`VqLUg6FShur*ffPU4UzCnyd7_c2Z;ZuR=u(5{X19tXUS* zca|InR_~&emigIiiG9XxWF0DXuIQ!Rvoq}NY!!yDdPW>i_t~G48+slKEck#4O>C8b9yw`*xL;R zupx)`f~E z_a9Etw_Qh(1^_c5*@?A_ysLN0a}UMnkCbt5Uo=qf#)(R%d{lkCSElZG%KCqcF@W8f z2M`KpdoPNu-2shWa+In{NUV`5LXWv_;#_(Ju9|2y9ohd%eXjCqmrMh>lKvJPECyH? zDaIRg0II6h;rS8D--a6|M6Z?LdM1p6&9ed>%T&{(C)`cUppGU|>O1RE3L(6-sR+Tm zNE^Y9@>r}dpTw7p35%GJ?bv#!ei(lbO?jp|#0~3L^8`G1z#lA8M{Kq1yC)vzMf6Ut zESVGZrH76$shJ=#B(ON7g_VmG$Zoz=(lWK?4f?D!(4V#q!~F=!5`c@8Ngma@R82k0 znbSM$>wn6d@LU~36QAzB8XS9-a`_;%3F;7@Y%r6Hw_WO$vY9eW$;5Zx(yeBuFWTaw zFl%755YrouP8V}{x;`~1P+%fzn)ClX+%xjtY5n@U!QMWa-uDdS?&lA$dH#7=HDxbT zaPWCftEL9FLHbR4hze(nX;QTpuk$tD?&D9*_8{I};11^J>N;R+Dnu;c3B}$DvKcP+ z*EmzIBVV7=Ex&JL&*Yr7y#;5cWX6e(^tj-RL$+%DlhqE>pHiFQ(@zh%9F^Kq=nk%d z+-K`$8-F6*y4LqotMhV-{ZwNy^{H6dtjwU4W8T`r)d($*M&zW1I#O;S%B%X0-j$}v zkYD@lz%y~v_urciZ_cfhI;})ja*l}?4PH2(eijCN*U=0ap81Z+0Y#+E?OwY<|B=q% zx<36{cXI=eH#HCm>Ys!EcuIdG;+Eo2T+T$i9084B_H81{=ePc~Z$YZ%oFzu@k`gSa zZ=!CO);KrK(C5*Yytf?unQxsBlpF$j#x6+qb+Mi))Y40xMcXAi6$s;Vg>Q>4N4GYC z14x`V0X?L%PN~89wReU|hKUGw)Sm3_W4b!YGH3BCWklcmt2~#W=~&qq5w-PzX+g;n zHuKX&fwQ#xThOk+hK@a>0P#p z2ys=CxAw{BeZTHc2E(8v%JbH(zvXRz{@7?8c7N8vgV35&2E}(zW)R zg##fyA=@>YKIN9#&8niyqRQi_@D4&{y0FapagqDH{A4H zH4X5G#&KZU7s=*FR$jE}4W4Jeikb4g^`Gw5*F{~&YvW|Sv-*|XTBX9L-Vs?oKcr@o zH$(6CXPOFi7Y6)o?6Ysl)6<7h5R$}N|3GH?T2yd-);mt}0MU&TI)k|J& zbhQFYuE_SK9oo22$*^&M@BwG4$ILs=@)8I3U%)H0-q@>j9J=ASkPX*KqY-@mTDySj zJ2tfb(OOc23Vk2nBV&>~*}uI|mjT>mi4VV=(QZrrO0` z4g9=oi%!l8bW}|kXAe`CE4KCY=&W01>q9Y(5qUj}c6nzXpa0r3j1^W`HJ{ZHnRvwZ zQ7gWad3le*30O)0kcU&pFfHjVwJST=gEQp@@2)RzhACl&25jD`jC3o{Irc4DRmP0h z8wOMx?GH^ohBn~9qeWf0H3Gq9mCCsbajVs+?=T6X_iPbeHL-6H``%bQpZz@^ga)=H z89XMh^B}yH2Wgkt_M7>Yn{Tqt%h7!&5ygQy8p|p4*jCA%bvFbsIpi9gE{lgNMQzSW z`i(`(t{ROEJE` zzT6tpYNS|-l}5B>3t}r*=q#RbX?hS1px!BER|@Rfk!dG8 zDf%o|=&>j-gA5SjMf5wn!;~KKg(5fw+k@3eVeaHMoAT+UklxFl`|%raZ;N8=HFrISCQam2gPI@fZ3>`oo_V?^UCtENq+aP1mfP4);CUeG@4miY zKOf!;u%$*kn&cXTc0gXsOgBW@B7>)UPE29SKV^Wt{ zt5?#W1KVNZH>fXLyT{_}mtVAvAR<*Vt-64&ftbrPu(|HT=P*jFrKvyr$KXD|N>2f? za>Wp-+l@Kx`Q#?c?L{b<)J(uM*XJPW7U>C?`d^~3yVK)?BWNp})1EY{RsieaQ#eZ7 z8#O1r!=VqQw=LT)bsDImT2NuJY?4tO?0F^6!hGqQ-rqAxgYB`MI@KJn)7)M*a?^8H zyb47w^Wf;|O*1|v^zpwk_N2?!m~3|;j5cba|Fz4=7o%UDU+g|Mf(_d-8Lco}syh~dj8zn|1 z<;TLf&JQ2T!iMR&=s4U-wR{t>oNN9uJ6{ih4_{{?t5@2wfinH5`eaaAu8ENN($A;#? zb`B+`m{3(*vC9_tMVDw4gHvZunL>omSNe64d*-vv6vQ{zD=qZp8eOOq@lBVE-M<;e z(hB^`rQ&aiz~(~s%tcb5F3sDyPkUeK3Xb62XvZ(2^bZ8-d`Q6xFDuTcmEd!s#7_+e ze=hnqV)9x5sM{Ug3Gk;d_=K(w=G6ZYuuOfDPi&T)r4|V*&ZE(Hhi|*0LeJ_B$d3ES zJ}ldo%Ev7g&g$!4%H4{xw|k{~2gMJO?&g{taJDX9$YtwPJ*{ty7`+rl0{raB1-!~Np znx{{+0#V*4|4q|hv>zI(J>A9gxa-ywMInNg5m|=7gJo^}r+hUooy3X0eFO{>;rm;; z^3~VGF~3N|+t@n@FN4mavET#t6INY|`)cD*;uJB!b(uN7802~`4FB@Q?xQ}L@g|E+ z!hZ{|7?k?MnQ1Ip2k9$Lsftj)WT6|AB~wjTO5twsboYh+%#fw(K04oyb7;#kg8ubv zPWsU9#r7I$fNHiq;8wPvj+{ClXCg`e_Atc+35#x}M@jbmHN_i$(JS+USmikss9XtY z8+pWDe^P z3l}cXY0W5a+U3~&`8B{#mIA7vV-(yovF%J78TX}S}*Wgvo?a_t|3_H+k7 z`C*h{{j^9@pJ@Z=?WK;@&GYsz!#MOo0>`wQ$c3pBj)2AKyr>=RqXvtawaMM3P;k55 z8FV!^1+Z`ZK|`Eu>)CxpLt&*|)7v~P{M$^8v~))cKCI=|Iere)oWP*8aIP)DzPTT2 z1bO0o#$MsXoP_(U&w}c&zme%_b0RDa>@Z=A(WQ+88IHT-fj6~y&-(i1pXP0*A5X>x zoUcID8A>l(7yR%EdY2XNc;xz<>-p7?t|zN?N%9t}v5(B{qrWNU6G$KU{Z0cFk`nf$ z^$sjX+F{O?v>PB)x5N<*#4n4dD6LnZ4h}WFLvD@_vcXG5Vynq?%^SuN?0m>am)iC~ zAqVq_Sf(hoE<>r9Ts7v^)?5qx5cJKcSe8#TL^SR5ow_14bQLx(zC?0% zMK^VUvH$&%+y$Q9FR^i;(4mqGzTJ(Y)Z_jiqP-i>U5Hj2k9DU=2A5@?6j=767s88 z_YU>OpA9#IED}ODNKWr*(Q!J0gIVv|$3kh_guS6*e9~z*3UH!2)ge`N7JAqdh8mxb zr#$=mg6wi@-1ql7AJV?)ZKud8ayNmjMq$rwWOEt>Uh~zk@h%%sgn9dB*+n3)2eiDv z4{v%*FfDo4^9~uHTLBYJEzH9h2tSx-C zB6x^m?B8~OKGP!~Zri!W*pi_a%EH7H85063@#HDaQ6cfX!f&CAuoKO4-H)J6Hu2-z z-60Ud(biEJ0xJPQO>{4g7W`wlZ#5OmL}zFUo_G511b970Y{zyY`Rh(*z5@r+n7H0C zEBgFV*8R(AT(=XPvo}-RIZraF>HnYf(95%wZLRa&9dq>QBA0!v`x8h5bEY9g)%d%_ zf3p6)b*UYBn?(|z98$Gv&7dW{@Q92$`gci%RWBYfgq9=DS{~h0#(}FH-qPFgooMf! zbZ*+u;w!W(-nKIDI=ok5uMbx(;a)%)j0_=(v8u4Dn8ZC2Oj`jNUMt&8Jdsu}uE6f=pmXuGt4_9b z^tr}7)5?Mvap5uIUFss3IgD@TxVE7Lo{VRWLU{7;DNwp|B-emvB0x$$t=e*PINrN7 zIY<$VyZC$Y{G*<8^+3Q=vhYB?LruBY}i%3cVfAINhbn#|dl9z}z z-#2SGVWFs7zIIw*hCe&|u|gE=Gz+(dW^VSft8G9n-cqpyH-#}qWbl0oW4$U@bcBCO z#F{3Y&dX_liT@aC^h|P>(`J8$M6z^`D2b4@POi2WUulZ5^f_VJ_ofHR_WnPCHR3O# z*gH6%FLb0EI6lK9@L%LAe3xS2GlFjJ2>8cv!<-o;{-swdTPojf`&oOhaEbVSb+26! z(>aZIw&s<0>G4C&+~3zc>3=aINKtB0)E&W3AEH#;<_K@abm=)xAhZ9Hdv8UuKn%|$ zSEL?rr?Cmm&DvN>WjxLgtx$bfbBST|qbz$&_L9BlmKQ>;=9>Xz!__bQv$IBIfNp04BD>RV=wRt6h4RxkwadiTFRv^nNaUyxnV(FzNCT~Dr;A92u zA#m~!hRcIvdS)#`jd;W5?)VxR!Hs=dDtUQitXWRv?n^j}*&{y3%R5-LnmI$YJu$0B zvN~EgVX5BNXA=;7GWa^tS8B@h{q#e4Qo9+q>77qk6&jBj4>Ay*de=cAZXxo&VU;u{ z)Avz;@^Iz5_+6KW8%>wqEMzNG7M-saEyARJgN%JqjHV1s)cKfN! zSJM3Y(hfYZsMN+(WN{V-)XrQ*;5KG+c%MC}nG|1AT@zTFYp4t*EHr6oOx3@6s*~#C znJht|Nwq6y^=xiEhB_MH+N5X5DcBB2%|V#8gBJFA9f(6xG7A0tVfB}=-eX0QSluLe zVvCE*EIYIr;ZSn_(ZnTu9@5;eYBusoxm$boJZ|qWeM$QDKD*Y^EL*iCzw$y@8+>We z*{9g(z_!7IsMKW_7?Di8_iTG0KHL?#22wobnX9TZxPcC8ANu&I{)xVNP3gxlf*=R$k_&l$u6wg_3I&B#S z#(})me9Pi2fyHjKPAwP}xuNA{UmSF7Ff;;-=Oe%J0Mr-9ft%Pl7PhTyqX#IKm$?gu z_E>8KTd(S>n#3-_V*iU3R4hhaSn)c87=}jrDP?5O4-*$KJ?U@tK11RDoBRz$-s|0G zQkZrd3j4IP3n*{r`I}d6AIFy53`olE@_500Sq##s_Uw++fH#(zPNIv_Xq}N+iMU0h zKXninZp`}US3Ysp@>+ho4967NgKREE|B>${&j)9g7^zSVg|&2)y6ryKCzWg1GkVJM zwv96@Z~x;eos9;U%RBYeYqT=r-U&75kuSQVCG4e%!tH$j7pl+4V*b!o z%ge<;cHm0cKL&61q+$*YGq$eMXy;(C5C1dw*36kk!iDO|ms-C*>Q1hQ9P*|^ps8Hr zdp=f5vl&O?y>u?F`@0yW@cO>Kxi-hr(rv2|D5K*mdCXHHAj6TTEiA~}TjpTzs) zDgN~(V*eO&b3n3ifuMIO^9ZLV_g(E(U>bn4;~p$rSvAx6PHvMV6k6_qf93h?iLgE` z@b^`NTPey4s4jGZaiS%^clg|m73C)b8K8%Nkajw!6M6lnCpkVNE#74;Sws=-5StLV zXMZ)QC9HDJGX_~_<)y_38N-f--6CG%Qp}6)>=?({4dB3NctE(QJUqgo_@X_d8htQfEuWMh|S9OJo zxP{s`uYc4}hIc){eQE1xg6HvOcMJ;|r`IKcnKPeey!B!Ozfw;N1RA|O|d=Ar`Z5g*}X;FFBm?%u}YniG{{hYPkIm8vHjv$s~ zuGoOA8)Sxs?+RSV-opxdmKl`<@>i^}{;HXAeT9`LfqMiB{7pQ4MeIIUjX6xf>OeCO zUh2uTngkW;#!49O;9;!FuFmk#O=rL5s|IWnp7nN#H|6;4s)(b9yf(>1!wZN2{cp9O zcig_lkZ(IwFTJW1uVkC>5_OW8Q_@Xbr>l^^6CLV$hMZGQS8E-0fg9D4S$pNh6zwl} zAl*|9csEWTj~uJt2xU^H3o3V=?jed~`GwFXNZAfJXRIWT!e5NzY9YUl-OPuF*MPe- z^PCY1kEMm(EWx$pZn?k+HOZkKs+W|Kxpu1u-OiuNXlLmR5YGvE($j}aVY%&ZT3y!t!;i`$#=$B%Tn;v; z-{>*y?adPmFHgN9E6dv4@+=lp(B@GuyFk2rlH=UUZ&$g~N3(x9yDg}soXh&SxT$$h z$zNjo`lwP8QX1{C4)KooMIUxqkn&{!WrWLgIpvd4k(g7ThR3^Fewk0e*d^NSH&acb z4TgW5BZ|abSU&tvKzENH%K2lZBk-AewlK{q0}&qA;IzlXouR&hJVD}og6U*M@xW64 zYrhe{hRA}J1~&}2Mb+yj!z2TapgHhSp&7U5+gRm4W9n~NiF(XM*_IwCO~_@@^qcTc z$qy1aSrpJk9W$?^tMf~OaNh_lWN9s%OQbYV8>>L%REEVUm|v;lu#6OL85u`@yr!OZ z;;3hGc@I@NF6m%5EGpINW{lm@7BQY#uHkQ`NF2UGVOM#1tE{8RuL=328w5r)T`pXM$OMKyPyk*`hAk#fI zH&YZFa&`FgEyj(t9udvUYro7FN^_L@7WFH7?Yu>kMmj$BQ2L5ZykKnu?%lXlbhw`N z_e?&Kj8^r@zc0Xu2Qxu7snDFLeCQ4|Lu}pPhD1kImiSl%FNdD{|{mk08ca3t_>$=yMf$%7Ih()o8@}% zmrE!NRRy-_SVI+K4-`{$Cw1GCwJ1MFe*|QGyd-*H+|`iz@Z-=(YRkO{=f&}?mW`~l zfT?PmM(;|A-kWXB!hXUoA#N{o7Ha~T;Z9GJt>HMf^O#sP1)QK*^ANmbrHIC zaig}dJy>FQr!MYipz@ohR+KvXY1MZv`#^O@S5g#g@#omJzbY4l5Uo(i4{Hk zPKDoTO>B+oHF-C5bXT+v;@SwB;li--`lW#!)7-F&?nSbT>;;rjibhz4kEP^>N1uF& z*o?zZ*B8_ui}=AUV_6BTr?b9`LI^pCCV zl_qd%m)0xlOz|Rr`cNNXv!&{<1Can1dfJ%M9TCJ&8PseMnOD-PV_C9>4xYfqo3vcX zPXoi`T_aem-s-Pb{%JmCi%_hudOZ{R);=w#nQj@mtfHH|0p{SgHXwaw3=E&Z zlDEsrtY*;al*%BLk*aF&lKkccW0W)*0xD9^U1iV%Ju4@QNb>&O^1;dUVC|WHBG97w|aIHmctHn z|L&5uPyfhQ-BsC`z{|@;0TyL$4W#d;4b`!dB%9PvcZb)?HOUr%`cK$yxgCm`!DB~8 zc!?@972gM=ub?6?Hnlt==ki>a$-b?dQn!eeOznKI)?jtvz-~=9VL!|=fow_M-3z$x z(LK4YL&Cl)JDc}h3lKdLnE#>|uxZ==d2_K&0UGgY!&!=$_F$O~qpHQvS1VyZG=8#E z|KK<{(P9XtlMbpxuQUv0t*d1kWzAnnI+9=1khFSMxEnz#lL+@wfL?JLJ1(QvXz;du zlFiRaZJc*2vTVpC{@+4o^+E1d^J1|{_MbeNM8*GmsT?&O5kyHckKeu0X%`;J?cX+Z zQn_4<)p(Z-wdm+Bjb&j+cB{F~>cj2&w>F`OlZF?J5p8U#Exu|ZXKiyTyZ;ytu2}8I z_F@GV?DZntgUV6)$)KVe89qz+pQMlDm&J@~?bAOU4ZO~lN69CLhwcUSe=V?jKNDct zVD;-SJHknj4zK4=yxlQ(^qU|x>uAl0;QwHhzz|`irt14}Lei^OT;(5wU1?O)KF`lCz(K)-=DO9+QMSfiv};S+_5@e(^?Rt;=-Z2S z=%&|z-M)Q?DE77Y?bA)Lo2SM`Xe9XiHV1m#kK=s*2e)%Btb>~u2u0!52WsG({=QNe z{+EYI$6f=0HCA-y!Cn~35QVu%jOt24_78tl5z^C`UdM#^egHuNDKu?gkaVPEP>T5; zpGe&K4*de@t-!SEP4VpIOieFGvE0~s`5K2X>GhOg^9-cYGFE%b#&C=~OYfG$Fh93L zwR4E7L`Sfq{CBTf;i{J>P($`{B2nM<^tf^!H&Yne=q+T^ESnX_H^EM_ki`2|5YQ>0>>6M3<>O9_PN*d>!Q>|Kt6Ay>@3xK{;< z_0fgR1hfQxo$_TPXy)}y#iTZo$D#62d4m<&=w5-(V;FB~<8HVMLZQ<~u;Nz`0mqeV z)8o^6ICVRcDtVONx`%gJHQ$|qJIagrI^8*61!dOJH0Z@uX*&n7%@;Cu*{75)ID^v$ zKJf2{3#WZ?p%|T&e2tRXAD^hJ#Ta^j|9vZhzzuBFyL!q}4v6Hdm7~}FRzHIx$mut1 zNS=pK`408Rsb5b<7(|PDX1e#E!ITKyF2w>9FVo!Yn6ghd0QVX^FNTvb>0HaPb?LjK z%gAJGy?a6kn`z%`pLtX!vWt$q&C|V&G1@*``m&uIPjtje zcdF3M1Dn0?A_Vu3vUz6uInss zC|oeu*48c8Dr7jWO$Ry`zTR9Z?l(<|VQrd~Av9Va8CGIX-?|=NBmIw}^MGda|H8OV zEp7ce)Rxw)TD3QAwPscAP3_f)O$ceL+L|ef+Evslu_AWVicM`|&l*8ug^d2+|2dB1 z9OsbayzhO#_ul9EJa%q3>FCd@QE#nt+8P09{^CLeO%Qe|;RqPvD;5mY7Q=dkXFeo8 zCN6P;9yeVQMCgpa-sGFe*QuGuPA@Rhq=NlcOd|q{+}M9?O~{_Qq+CA8HN0xFRB?(` z3Y^qv82_2$FnPdtnumhBiwG?`$742O#1Zj)yx(~ zy81WoB5L!t2(hO+$MKV{e*l|zxJa-k_767n`$9R&p0~!%jX2L$6}G_#17bhp?>#xy78Eg~m*<77sP-!3 zRU)!x{+@0BhI2P55majba`RM7+~w4NXf@AUwdnm!{}Z;H-g2SIGqgBS#)RWe*w9=} zrgOZaS?fYAymgM{SYe`xZDoOxpO!3mTu@>+{R>x?KV@kDKtYf{Y27Gc_FR1U&c3I$ zhb>D*V_GusWQksCDo%Vn@9>E;;DTrI@88G8#d;b-SVwd1=DtVWPM_8hdlIKvp-Ed0 zcQY7HV}Hsfw4CAF4;Mqnxf;EQcB`{?rHy-|Yo>=}Cp zAG+2er_aLi0JJ_eD?9I3GshlmrJekM6}k zzJuek6n$cHa}6S;CT$+@X8#dKPMPySama~eiezbnwrur=qa<~=Jpr(u++tqe_xfJ7 zn-S0yTiTB7{(vatY4}XT-iBWH@!I3S&((B|I1Y2m%OtM|TiKD+kKFZ>eWNZ$iLm_F z9plrr&Olg}NFwqW95nFpf7^5Sd`R^R=dPe;o|FMkI zQ~BicRZMQ!ywMWSAlAP2LoVguBI}iNi=2}K zK2O6pa*vhoX2eo;Q^bbb`NXnaD0pWZz&KT?@>#mthG}O(lw)^^jXA~(D;Uu#y*5+1 z5;SYy=(__kU4<)J@Y+1_V@cnuk(J%u-c`8-i-=L3hBCLb|2OjouL(2+LX(Hc{||EB zEB273w{Ie9q_f{ZQ1Tw=4?b`7N zr|CjYc_1h4g}8U)>TmkVa^W}1b~SP2A0E%^YQyC`4DXH!KxHZAW>wJ6t8}mZPRA~v z@+KPtS^}w05A!DP`E737EVQY;1)vCOTnpxIhUS`{p0{W1=I7;7!3+=D&(CH}Z({53 zImO2;gLagb#V=A6S_rmD$Y8%NOYW3q;VA!)Dem`Gw`;sr?J}qZDhkMw$Stp{|O~=nD~gKky2!|E5o{-s{4=OGmeg-?XyaO0`riW*)n;>GN|I5*gtHbtOfd zR}=kNV-z!$X5?v<8b-3Hz_F}C76FiN2u+5)pEtuvuioV}+}dAxMX+!pi-XO{g`rBM z7gKoAX=0;oDAE$!1!0b3(Xz5~Pq`bEveN&kt4JeAG9vZ@w#+C=XQzwBxAJY(bKW=3 zvwK85O<;&s<)eywlB8BI5!#pp#9q!tyuSh(Y(`)gDhAQHq`P|^+#H0wV7{gRaZNO$UvchnBr0b+Ygl=8m$GU%8EkrQIir3PgN*(qJs8E%mm)1d>f&Mc<)r z+afgBa{V8j8E|s!e=|_4my!3Te3vCqp)*ts;EJkXYIaj{nu)8ZEV&Z=%nc^nyaa5S z?*g})OBUofEJwEv(=-|o$6|@n#zPMAd)LzVpw8c}W!`8)G!6s+3umQwOnC91dp3hpOyG?+MD6^f9;f4~e9J~_f_mM~skJ2&?_UBPb{-cv_L92;}ljf~^KXF&LC z+>ksTtG;KVtW+Y}oGAg0S=B4SY>{kLGtVYcM*7Q3$+h$q_!CwkuMA6)=^y4dsypGQ#G7LuA1 z#jetaA!k%AB)=3jRr^{y2Z(@PV+LDnI`igFu+YW^*e?v}h*!JO+olmi*n;_F)iIuU zu(3Y2!0mY{p^Xo$42TQr7nV1=23U^aq)_;>-G3ZIJLEgpXwL*(R~NmT{?TQ7Zith@ z%zlH8&}dcO>Nw-wxq^>y@~VOgoEk6R4ns}MrjHS+ecCoxUvH3eeKoG) z5ISdew5xyt4nz-oNlga35W-{fZ0!boyqQrP!OW{Bj#;tceu!_GL?xdH8>7~dn1+}A zOSIu^>@21liI3R-M|b?QGJWrNI8XJ&t?^pxXC;3IAoo`Dc;EU;+1Pce#iZN)2A$io z6_^+?896+h$FcZnN&Nvnv{Og&RSJJC$&>6K+yJ?_V5|PUJMnRE728eqzWQ^{t*4sz zzUT!32T$ZQ8r$I7#--aane(5F{%wn?dNOy0l2$?+=w4R@-?g<$T;+0Q_T3znWSXm! z&-J#AziPh$Z(TSiX>*Yb4%H?dr6k$PF5xDu4qh_2Yf@8 zg==cn5I1uiwCE8!2XGR9Q=;6?cJ7=aswn{%8Jx2x4EN)D49bF?5P<1p_BlJ8U&l$# zolB7|$qoY-uT4OFGrq2A%*wuGbV@MCGBUaM?z$gEJrDxf!X5x+z7Qr)8X)j+T~Kep zcxJ4cM&R$d$Rr^4UFGRH$!34N=R{ZCAO2kRX;GpaPyij>L$GTj9@Ka;`0H|k#%QvwfuK3ar!d=^w}-+ z;}OE4e9#AlPrLMfqk*L$rrGepbyQ&at`)J|?@2Tcj@UJrj-Tsa=+xx}&jfkVjwD)$ zksfpjT05AKMA^Y5iY|34(j*_T4*2EmLh=C=qfHa?r05)4N5Ce}w`!^GIqI_#iR@E_S;tm!1HczGjMXq5>|b*-(Ou<`Gpf zfE_U6(K_MktG8M^4J*;Y1@WVe!8}#ey>GCwze9yICBq9Rci#Xj;++z4@ip>7NOnIj z+bP@j{|m-i6E0e&9#{1| z{C&qYq>uN#wqv|Rm++2gs4i`y@=J;na2{EhZ&ucj8S_l|>toPf^mnM=Zc1z^90Zg# z17)ki0nl{#+(zelFe2O=#JUrj={Mg3l*IRMX>(_4J620JGD|4b1PX8Xs`&MRqQGco zVoxH|cbO%-+Cs|hjSgE$!q;qB5*&IrV)^sb%SIMgTmdM^?;0436a;wp`}DM{a)gML zPgp%r*Fp^_{+A4n>3WSXZnJjybSMmw(U*|M{B)HvE5)5w2F*1c`C2RW%JW%RnOt-s z2|#>LZ|}L(1}TuCVHOjQiP~gcnDI^UDSurU4(-M0eU5VZ zNamz4URly*UvDs@5IJpcWmk>M*J0^n$S|Y3A%VNFkIcj@0;+|Ih0kg(@F{MtZ#6_u z69JP2>w3(5r-GI9_3JQ2vt6&^B^9;46qnKEv}5LWEG8&~6mwhxeEvb6b|8#9(?wGB z?;0FfyzQiNUfE1fU^D;Lc{&rrYo3wvd>2M@WpEMw_gRU0Z+s?O>s5oB^(!#W@Mz1S z&V~1i;f>|Nf!pnJlNQgbn&w9}+4l?3Z=qa-Av^mSwX-3bKo*B|pwC{?$v2Mi@Li8b z3v%` zBxvMbU;7=Z1Xu!BiQlrKzFe^>rSM<^0)+33fhlO3h?&YS81KkYJ+C`>LYsGJ{?zJV z+iFQ7yA4Ju&T(v0epZ!EELkiFn9QXdl@}~8NKEcD94u%OYw@ZZFxLt-0Sy)TGZS$< z6PpLi&FamwmEATa*&LtxPqyBLGE^qHHk*4rP1DHob%RFL`Yum7Ym!}|`n6cmA7Q;F zfo&O%Ln;!s`F?TWZbU9&qt&kuzx94ynpVQqQv>wHt=wSdpv1^6%Q=<>_B730$F#GnM{RIH~=KtVcxC`pBbDKwHKxKzBh2IaKUbrc}z+^E1Ewg1mf5#gF5K%Cx{{mvHY7;lj6u%dER6)Z=@J7<8}EAJTddNe zsX{nd-iY8>Mnq6RxeL=nr3Y!)Lq{_PT_BlBfj5$(10i_^selZ9s)tb=YjU4bJ53k<$47z(p|kbw<2A zM`=1jN>S5eL3v7V;J`~1tFLpo6mHeS?Nm09yOqO)59g&#WGe&ssyBjTsG>JFwmIk> zY8zm>?Sno~06=X(lbpwZq?M-!UURn`ddZ2*}bHuyYy`Ob{DjXpVFCW7A4*#6PAVW_c2?emujsgV@HR6muV(JHv=& z?b&A`V@m4H0SGst-mentm%omq>v2aMMQg&=c#~&uyzA{+^e0t-c3hN!&I% zP7L9W6tWaV(MGxNkc9GR!wtvpmgQlZ%lh1&`nMOhCW1iDsNq#*^@}$_*^haq*CqJ< zhF#wg;CQzEKH41&_PU>DeWGqh>D1WvDos<#wuS!>q7Yg+0BH5575{c5{M~6X2y5f909(K*et<~gUC54A*wLRipwgSF%E9j;N9l8; zrH}Me2)I710w*BCN~cORP-9_CCDs}vf6v%|IKmhU^I^#Q^nDTLXB#_ei*_|?8B6%f z@)pS%H2%#--b~>KZ1flk1L6(l>!0A_1YMfF-C}rvE?Fx$nlY^1c3g~IhL}VXxJASJ zC1xgI!<*ej|IxWK-8x0AZJQ-fFv8`zB4NQ>92BbXp`_Z>#_!slA;5aI`|&USgndw` zj9S4!Hc6qzg@eRS)s}9LSZa2yzrSPG@aS@z1cK-hRz)*_cf9NdO4g&HeKkcVY98$I z=r7OZ>lQFf!vK``5^K*YsGUow@c0wqjxRK#!%Y9aUi5-n(urd+ofp>b$)4ShNl@ib zd&aYW2bY~@elJp zN6+(%->zbAVWZJ+NK(QH{K)?7dt-?jH1S%U#+U%UyVzwnyBS8S>2=lW68;V_@fZ7t zTH5T6eNGqV8SYq;vO+ zELmNsV4U&81{>`L)m2}=*vY?6@Jh}0BLAG6wieEV{O6{Q4n+jYY4?morjNc_CH$=u zqK_LiGH0Vnfw>=_TxtGz<&`GqYfy-4CH=4+fmt3-duKO`7!qnx^3<(;P7ugXlAHH$ zN|fD*_4b^DzedET&*u`Va4$VGsD>=>ExeLfp?Rn{BW{-`eAkyfq z{Ft^7nRKP<-S=~Bk1Fv7mG8FWJ&X65+U%}Vcs&t2DuTKrUSbIj$vgPY#;SO4Ep8er zvqYd))i0{)X%FEW+i<%*b-f9rUYd}?A-Wa2lOrsC)@7X?axmb$DJku%`~{O#Zxy(( zbp7|K6-N40x*pac@I0ZMh4huSN4uy}GGb9>h2CScI5*Rz=;VL0Ist2N3+K)sFNY}r zO<;MX3rT$G69?~h*?(nFgtj%HHQ->NXm2M`bRen zu4z;PD#wv0d&lQ&qfg{E_2#b|L329*HJrjcx>Vjw@ciAvTsiEYLABhPG_`P!9#^mN z{^jfC&9R%+>4zqiudImg;KVzCzon_SKaS7(pqTtI;*No?vRIt!BfTBt^UMW;-aYc7 zee8!t6R|@1gYHJYNv=bHiCqju_Jf(#&E3)~w-^deHPDi|RBe&1U@{30E60dQD*BgW zXjgJvwo74J=rP01d{l$gr>Ipe8yBgD^A0bN-@;*Q6@|VGBE#rNGt130O*c2ZqxK^?5D6w z<+s&3w>tbEC(k!CbUGytIH$}dauqE!Bk&yR-@{H>Uq6;#y~h0mBk5R2 zSfJeTJVpXu9UvkaafPBn3a`|`2dtOQ-hsScSfEq zJiW+W07eC9??*|Rve|lOL~0=alMJmTfW+++=sjW zmy_XyaRDC&IDSYX5>{?`(I=8qvol|>Y?@k5=yo5}r&)=kIN7sJfE-2_H=vg6BW*WaH4Ra=F@x`L^e_t6yeU zCqAy($Zq}!h+lT0c6B|%&$efBtL{C~krYl@RZN1;TMjflHxaET@W|3W{G(%e`IUT} z;7=u3{pudToPcC^uAMhIz37lzH?aDp&xb<^*-!J>0Y={6*F4rb;@my?BGym{v7PM= zsfY1U&W({$Z?sSjFH?;=rzhZ@E!h@kwbV-!c^PiKfe3-gJ@-nprIeidMT`zVvapaKTb?a7kx{-aDUSX}x z=lOZ!!Ofp8eY@5#N~gT&6YzNBU72%^f{9h|U#Dqz^%_3}51KS@>5H*?<@=p*kO~lv zvYp%YVN7MF>>OJYMC;O7s1JU&ugZ-O*RS2RbUJeGOk{YA+lfWAR$nHNCAO>TnwOw3 z79{?U&bG|Ms0Yde%YiZ!X0SOq4m%-vqq`Hwn9x%=GcRl>irh^* zxf_ri*Qj-qadBhqEKpkAt9H25D`nde{Etq{X5QsbqOQ0y`};wOVrgI2@^p88Wlce==IQe^l%;Hou~m^5np}p}M4x z_N6KAJNKevp-vfNMh`c*QLfU-v|ntFZZ@tJYfl@{de(OS7C1+neCciG-7;(7OO4m%!{ z0c-R*fnJNekEidRcShqOZj1XxVOh*Rq?f{Aw_) z$IKrA;ft&Gh=`57(8#v8ZJ-A^j`{2*X4J1`tCnKkF8t>7o79czUAG5=m8j?OZUqN+ zC(EKyyj{dgs~ni}V2u)`ntK>)CpVKmfyJ%BH~dHSmeWj|0c~ z=D-KDbt^4lLVX^aj>%S02`nDFU#xkd_EiNOU*v8q%x#;Ni`kp6xbvCQ3^Q!>0EuPZ z&nrVA@mt#EB3{5@E|gs(H)!@LOMlP&W1qo=kUU97m3bXW#r*g-(FCckX-L{T(-k^@ z-c7xlDMFLyQ zXga$@Lj-qWC2V{v7k4Rv!*oS|7NoZsWl)%JMMJDo*t2){<+T_ zPC3Gt){-0#(8@kT&DMznj%jbEO-yVI(oKS=YvcME#aV~KlXJoxrIV~5<1%_o%+ccC zep#>n)Z~pnq}%*pcKi^172WSpTp24`KQw#TbxFzJr>ja)r!lB1tUz-BaIK8dzXV=+ zazhI4R)7Dm4d49t&#`kCuH%|52zLTc*du!0^c@ETMDsnDC7Zm0y$f+vs%O1JM|Cx3 z2d_1G#U7J2#%H<0pX4Ad!}2s`*7tG8C9VJHHt7R5`W{VDUSG!qsdZY&0rpo99dh8? z()D6ns}zpZnS86eY3zCffG3#trL=MF!X!8CtM62?&U#koc%$XI_`~t(j6Dr|Smn%R zv$em9fS_*Xy4(zlua%I?eD3(uYv<~r3d-YFO8%enN*>D2McsEfg-?6s$uJE-iowq2 zjtNht${hn~0-!l;^TniT>;}Xpap1;q>>meb1PO6{P>Iv;#BFq!Cqr+BkLblA(g!Gk zPhj7{Z(?s6^l^IcJ^n{W>|2{}G!pZv4mnzBemp87LIfoz00sn>E8nk|WY-N9&?(-H z3J|!jobsYX{87VO+5Hf|y`!?2;FXVqT5TmzdA*UMG~;_c=Tg^KPw)q(oP8p0^?GrP z5Ao69*$1;vOgE66M#~L2hyI?`>Lr$6zCvF5l>^3)Clj|^Q0Q2`mjzE-dXzg6{admX zgA()AyET!hxqIMJp44X=5=W<+y}>d*1uky=5&oVjX2}}kJF3nbgr5U^M!HfoYHn>W z{)M%OJ-rHab-4BYW>Xp`RFu)`evDu7^H&k%_HsQ~B^d_2<&n)=molB=WE!!7((Sfy zKONk-sA~1Fu)^{TF_@4_wX*6an*?f^#qPca{@(!tKeyDl@LzDu(8s5Ej-w}IbVdp^i z(lNoV^o9?9%zp%CPUxI$H`(7|=UPp-snYs9GEFTOS$amy!%1?@W&`b}yFT*_r~?J;T8(P0o!@|@Vn2Zgl4 zBfMe86Ech{_5~GIOkx6ou^9P-m(we=g(^(IO5N-@%*G68sj;P8=T~0UeVm`L5Giy@ zRMDAHQ*Ijcp7JiwLqDAJys(rL-K0&H4{m%_+b{xIHhYY8iQ#X+4M@=UGX!b)=5hZn zEg-QhsTg(GF_$arh5fKG$8yZu{i7?e`ev!%1?v5LTKwhI%z^%%m*Yr7rHuI1dQ|VE zdd8(EB{j2-d&S}Olh-n8tsj@J?MhbhhK)m#wat#U4ZPsBy7i{A);waP9AJZ_q~U`X zf7Zzwi4i;f2~|vqrUy;UO*!9uHQXoAaYdJAdgB;Ax0ue?J2vL|jkG)<<6@xD+g8{O zEQ<8Fzwvl)HPJBh4{gK$VRzrvJ=$P*g%%t)4FY3!L#PuB-(A=cl7Ul}r(7Af=Ouyk=q=Tg!WkJA2`8j>#<6&qY?nA?fKR(07xmD`z&JB*Wl?!8L3vkXn zE98fk2aighj%@l-$9XiSZ)Z#V9x8lcwsEo}N49rUyA0zh+YCv`SynMKOft--{-~~I zQ4@Y^`68nEF_xE=%QHjY`sVuq@c%*z^5Sqs&XY%5e`(%{n^Y*PtNdSsZx!pyz8Vr)!YSobXqY z%g7dJ-xTb?y5vl@`4GS9HB|ffbFBVe6yG)Hw`wmO8X+XUc!VTv=%gpG#coC>?HHM2 zc494SLPl1w(j#ToFsSm3Wv1zz9YNKD23f7X~B!%0UaDmTYeShLqa42Tl_D;1JRJI7fuivn{*W z&wb|`TO7NthYc)-U4k(c%xoUFm`&rSO#+1?%^w)F4oakN{Mx&dP@ptBoWUq1B)K!o z0=ZH4u7{2&oJHzchAOk{qbBXzIkYtn9KTZ%|=j$hLE2xR3B&LPaqdbM%4e z-9D0Q?l37$j!~+E^@VZ-nIJ>B~}`iNLggu%<^|F6|3nrR0RDH_uuhjLEpxb|mv4wa(7g)oZS(xO~{Zclb6ZCfYIux*@& zyS|#D(4J%uVcsx!WJ({+8|7E{m(0eL!A10e~=)bnBQG zlhdKi*Sw$^0#q0mn|Sez7?!eKLBl;g@}s~N2#-Kr7f_l8?~Ui1xI~8*gOVucpLw-!NzFHL3w#Y5^uprj z88$357`H()HK$|gwNW#ZEgSFK$w8#u8BLRkz2j=HsaR&k6OjHvv@x}w;=Uo%uXvp6 z?#C@#V{S9GnRpJFYeu`;xM-sTk^mpM{RxsRu~UBc7RVJ=SeeMPBMAz=TTg;aBY9`E zRZR|y8@c?rHv{EWi}V1bGnYunB3nC;@ca8+1unzIaA9AOzzXzz7QSqy9LwVp zrDmp$pgZ}qfhw1QAPA;0AcIduCWi&yrc{VK9h_(gs83wiaJS?0{_QQ_XZDFUl5;)) z^Ip!hN+1`440g2ojQUu7QP8==b=?@e2u^|svT=W`Eu?-$%{eaFMy-g`VT(vVaF*}I z@w&Rf>I1G)TvguzYYow}fLid&3g}QSQP`G*$=yH4rL*J)>Z-M`eVkVxY=hD*u2h`* z%w%yKxVaiFsd~;NKJ5B6QVnN0LErec^E_aIK3vHLb~VE|7!3BhZCOp`!saAPV28iX zXmD&NSUYO-MPq~ZcpXX`8Gg|%`V59`PyM5F1ijrRlwv2%BxlNV!AoQ~DlGd2G-!0^ z)Iotuj@U2N`A0XCaV$Qfwsg~Z47Eppn!^4w?oI?= zm`9EERcP@dq4E1hG_k}GVjS`+N%LFy80h*@PDF$1*9y`n+HL*wTXwQZeuGm%=XIb? zH`%%epJ0b4vtU;V*H1o$Kd@Xdx3RI9=eyRU{DOJhtcZ><+8lO?(D%HN~vFcglYnY0Kw>!!KWOa+Fd2j`YS5zA^--UjBwb zA!An%g0|ynT&l)ozpm1xv4o+QX#y>XKWYx}i+1iU{+3}KqvE}#0gvkRzY*zp-$l<> zQzKNl=PggcxvgkXVrfBp3DQ2&K_e{8bECjg*zZi79@`|pS^h?~mS&zKh{iuzZY&Kj zBi#5kSW1+e$qzId-8;{uQf-I}pU(NuADV!tSOErF^{=M7n>SNy<&_bRoniK_z>@A{ zpELGH*yTwl$=yJxpr-S#WLbPOIk5cG5|VNoaMKl(-WGd{{<2F<&UWPO*N1JO!;^=M zm|s35YUb+4*9A0c{=e*CDMN@tYGXL>ZysJ!X@`q?WZRY@Po*+2*EpY>alAl^ggVfI zJ_oFy2Iip-$&)RTtl&E?$jz{QS&(_-a%zzyoe-toG_{|IV(7ywFLvk&)BK=t3 zHXw^GRigk%`+8uM!IjlB3H$k$mWBk23RUNF%|!skLcIWd{{%k73$#si&CJ{@N_ZNz zpz`0j9HaP`D-(@eIbwmx0gBAhSWW(n+Jiv}>C)v5(+>&`^Pf*oXbd*4x5Ila_v_tK z?mq5D-q-8k?zlN9#~Fl+Cg~o#QWL`^DHZF=Q&!qU+XD+e^PbK1c%S&D z|LY(24TjDEx|G{$&T9WzxZNEn_DJdGf8WC^&i{x063fD+IOqoD7P+kf^O1IK%5pm$ z+?4}o=&t_l-^eYM`8wjz0N9He760S9Dd_E+v9VGf&<*x3UwJpAWbmmIG zevBMJ;-r>VASd$$Ruw36NPil$BG|Pz{ppDv!zNJC zP@d>?cV~2SgT=75P>-P3#}3^@e0CU2*{JHd{?w!?A!r9e25;Fh9Cgqp zhIg|~-XFYi>*EQVH1wI44J+*U5Yrd3|uV1$AhL@7W(RAtjLcw$laT zAW(QoTS9NjF<}o{`$dcH1gmcDApCr+d7x-CG5^m7W?wH1=-Zc`ZAz4c?>Tyzf_Lj- zH0cHafr?z3?0`h47slj|^ANm>z47a~`B_aruKLyg9N5^%vuNIfG6+dh5np-yr8OiS=M447#~acJ2!zKLg^ zt+HBcL`lw}#p$!`;zy;k*u{OtK;|={B~dQ_EHN3oWP_(Wfc^-<=E*O*6YvV-$zJ6o ztJ#Oy)U6ZS%OH8EbZHpMmUJ!56_5uK>dK%!=6|_Mcui>saF(N=vMg^h0`WFAKr*CF z&n5s(YqWCNdMy&&pElc!u{1*ykDW2c9_CJBCh!@YkzDT-xsL|@er5F(1L%8Q$>Z0i zXBLtz5_DzvQrEHbKdmiekpo2J{M`2Ao49US{HYm5h)_B6JCIUF9FDVh&Dk%I z^fEPuG(Nsr6YkXil+wQtlrBWkh}PM?^NN1B?*L3=H=%JN2cG40z@t;1*|Z`uf=)cM zUu?y`k@K+)g7uxaC4&14$u)6;sT4a=DR1ZBw1?JRDfN>5Rv(L;z*SDLQrZAt+~|6K zLIgmF7oP_>H-=x*D`G$cS-2Ts$O|x)aK$@1-BYK5MlUy+qi7Gmm~M%!-P{Q3@6(%Y z)~6onV8l7XA>^$LkqCz`3sUgFcQ4Rx$^*JO%e!k2|=e$uFvTy zox6oMX%E|qOUp<&kee$G-@Yb34{0`s-)hnWcKV2qyJEb~rc(ord;S;y(JAU{T%YFf z1_oEb*>%b8lWfS#rgZ*}p^Ge*FrB{h+GfN}-ASI~uNQcMSp zXXMaIi7XN7HEDJgl*RV6wOoJTPn~s6Dr*n(N=^laa>pJ3jSNN2i`lTxPpDn~D^80H zSW8Yn)ju}~rOWwt&lC)))7yfZrQ!nW}H1oij5^f+80P7K^;RNk92Surj@F5 z27Yqk*=wt;r1Mhi+>M%l!)?0W!5^IeEV(-X+)--6N(tRxRU-SiJ^`ID9^$h zt2I*>LhQu-J^rr@M!g#USaUBS#^=Pe)FW_@KdvJYR`l6wtu(_RC5axs+)v%I3N##$twh|iHTLaD+*og>QG z4_cllIK}Zlh{dSUONXTde)Dpt2y}sTHSw%tIZluM~Ltbe|5tXZUQrYgslfP&$rSDmKtEpKok{PMn^r zw~NFPOT$!}H~V<|IQAgPI7rV)mD2gp(9vf*F)_=YYiTJ;JvM3YckR-AL(k9Auf0-- zN^akr?~&5;VZ5xjiRHTe{SG56BNS0b4?ePyjf`@nY=aItb$m7k)GQ+s{ zhC##VGS8V$pOYikI!ZmodxwQtSFo&lc|}7qmJ_VC_;}eUi`vtuWIOvI9VdBB!jeHZqbyWNvTFK7D(%hwrdSU;?QfeeW*Ho!pr&wVjhv^ zV%LCU2^`(rHkh8{&x9*dhO#hn1K2n0{*qqY_5dhuckQ(Pu+uw>bLJ{U`b+K9${cZr zc05bwKC;wLMmJ?!m4*%A6!#w$7MBvWhH*Xerp~lYNUDlFR)&bdXAu0%hhZi^I~~IU zTzU&;9`Mco%3HG*Qrq*}w)rN)+c9pO&>r68eJ-@UG&F_}m{n55^#613k4>L127A{a{kbLoEB^^Q$7r!-);hM2|3U+<;W-YF3D|1Q zKsP6c{YEnX0Fd~*!6{n%jTW`wi;=8DZ0ju-Q&+H2M{Wi#m?kH*%QSgN!Jdiu!IX0~ z{%Sr1!Of2{k!>hAYZ682*svvdOH_MqWS&rpTke)l=&s%&wIz|6*2Bm_Z&D34Ib%yO z(B#z7M9GJ2WfSw98ow6WO1>p|>2D0cPRSt8bWF^zz1>|%xtRD}gWJ4Pg-KsH-p=0g z8x&sPJrG?#@G>yT;|PbRdWChuj-_t=9rwr8A5JM7dybf}7@EXQo1{78*mDx#9|AA3 zCjdGqJE;@Mi3#*N?M|hQdN8IjE$=x^;1#tYWHj%yl(SV(N^bbcamHmlgD+&!>xFs0oE(7I|bg_M^|$(=S)2g2Yv z^eA8G#D`v4K1o>FTF+WT`PxGqTd31}3B7okIP>bNQ@B)hSLn4P&RZS|0>V6s_yD`q zwbx{y1uhS+r$lY$=v{#SHiZk^$h~(|9FU#15mvkLFs}g*Kl&Ai{xQo&s`|Q66+4#(y$Of!mOiZVFSyarpw9ds#SYM6- zikKNm4{0sF3wz>`s*mEwpb$HRcWqg{xX-)Z`P5zEAJVHmNeK17jbWCPx+6=`^J>+6 zp2RZDuEkTb|9b9NjTPvY`=-du8#_3x49YaXUT%>odF_1IzC@#pQG2-b2*rMhH2}}E zHEBGOF2v=GN)vN5c{V%6)}vB6(Nx;5wr`++DL7(zgK|GaW#aqHc)LvY9{-BDtK{pW z!Qe$EQ%a_L&ra-Y-q>-B-F2Ks&lP)s;g@7s#e5io*N@rv=H*W0nZ&MSwCPr*sNg6i$yk)mr$rElJ53Q4f1oiA4$zZbzPBlwy!@ihE8kVVdk5O?&s_EA z^u>oCSPt3a*?Ft-U~cRrGiRAsOp?u2<-fbUzPBuxS@Ny8jQ#29Gea4oRVoLL5uzq6 zyH&N=)6g&T)Z$6TwQ7wxS|u8`jrLN^j2{EyF5h@7`|i;MmW>T(leVJ`xg2exjS z$i#rEx40d6HHHo@CBLwWK2+eU2F8S!0DLp_D({ON=(v?HC4z6Ms0EEWsBKx8{ccm# z#nr)ifQuzQ46JU~uwXl(lr?T_UFA#OV55XO{Afz!Lz6{3D^1`Z^?LjD4LK4HzcVBt zXV~Q=PIaXq2i#I9bkHnjqHGT0cKhl<<6VFx!}#vRF5Ya@B=c2{h%{;rqXV{@snVxq^Gg;9K|GC;RaGylG@6eCKstpC zHN)RE&$&UAC5LJ)`GhV80B^Lk21yMTgyIPI;9_r!2xvMi@_`FEO@`Kk1 z_BaQ~tM6Oq`^I6s>ifvO0ro|s%+sa68y8d}*NaoQR~mRNOgL^o2hYCGt`vyU_#ems8-1v=&S3!6rYCPJGA(k6;y zTf(F6XSc2TEvb3VHc9tPr~XILS;sZiws9OE6%++5kVd7Xk(7Q6N<;+dRO#48H%vr8 zNdajDm6DvqHjptSMPynr4q*Gk?n`fe&WrK8RSv$RsA3D2Xs3<#?t8Q4tgbm}alofGGcZskB^<-U5 zmb+yF69}Kgn3eX{E>VRBYVY(>vvAkMuHGwj76t%*GZr$(!w|R_B@aO{RT-5Ja)y&v zU=B7PYj2q>Ag($(Wx3!Eb%szcqv5tHkj8nV`ck8`Y%zxnkqjNM_RAX_Wmfkzfqql! zq9NbtY^{I1m}PP=2|_rZ^M>i9QY>BOu}tHLaZiX5wZ|v2WZf}3;i$?V>>X!8$=5x! z@+l6pS`(5AT(yY%2|?i0jH13i+eJ{bnEgJg9N~^ia@AO;{d(NXhP@#I6Oqd|`#&14 zU+55*5*KFi?Gq`^&U5!>>nR-P;arUr??=z&{^-BVm&|I}e3&^(9XIGu)r`nP@)P_? z^7n^TiPysX)fEko<3U@^=^{dbzG2))duATM>XDEk?z-W?13g(4$u*hxI`1wB3H(r` zjC&xH!XSRU%J>OwRyCy2=A`L?!UYis=>6|HUwlFHuSIKn!n)-ujHo_ITG z9tEw2$mFuyT+lSbYX(^NSqjONc0U0)e7G=bK_*&lblcp`qrdV|>7UKpmSM8o!jiP4 z7LoyW@olw}eN;=4xkrY(SzlvyCygypfn|Hx9A!0myK7$Q!=UWi%}ey(g#ml{ZKB<# zPrvE3@KQ{Dz+wdjn3>f_2C56ip_JHv(Fl#5LSdtpdfTMpaSo#XIh^QXT!3JRvsy+7t(i zg4cCo_IIhd+l7C>`>Y$dcw`-;JnFT3sqNieER^w&TwqNd5v|LY`8)OPTKTd2tT}tyxI~nWUiT3!9Db6&Oc#g=!Txev})`wXq28pSl*Ao)T3@F7mA0SuATk@}Hm1!cNA!>tqNs=OMKVR!>1+h_graqUUyFAZzb#aajg zU=Zv#mJSWATYA6mh6r{v`B$8~{=0b3ij4qCu~m(+v9d&YD}!*Z5dr>**VkVMyS5VU zS64g>2!0EqT$kvSJcOf0VvQzV=bv&?wc1eAHL6B(ry7_hu$H!?$+Ibl83>{6Fz>VI z#+g?lx3))Va8U3|J?fAn>MUt!Wk7wT=-)9A=^qB1GT4XydpB^;exp|1&nCOI>TqoH zI>IXIzPg9q$ZmKjn|`8cS90r}NTI|ze+`R)6zk3VN-wL;aymqMkoA{-KKkilT8b?| zty1EDKPf!cVtm30Fi&(HRN?Go8ff*Bk9)Y39~31dU+U!YlH-^vF)%jy4^ z6iV)D$)fd;b3=%$<)boLDvdh3_;t#MfrIDeQ?3_V*9Kt)9{?P#2Eg`jnr_hd{N#XZ z7=$B`nz9dwj{r}sdYv&sOOSM%>2bx=^j;}}lre4_+Z%!|)vP+SzZ@r8=7mf7M)C1% z4{m8huHr})yK|5H4F&F*(&KO;1Fh*#6m^DYGPC(72yvw;F6jj)-bk@j`XBra$~fx~8hp9mXMK_)snv<*UX|(2|gaKXMKd79Xk228^0#9a&i3 zN=i8p#q;jSw2E<_mhbpuCT;}%L-W6w|2PV#dgcUqn1YEN(RlF+O_~u7o*tmJ=s7Gz z)tlm;&LoaY?O9=lwp;g#S_JCN9%)UXG9;Buc%`8Jx_|iv{j4T0@7?fJS-d?ltonf_wQqRKxE5_<&e(?My{C58M2NC;6*6bZ9%ZHG;?H1@ApK zWNngc4=Olg2VSfY2VzPy!pp0H2T(7HL%Y0jRYxAO=-KoRi|s~jBumNWY4=1_>hvPX zcx1ds=;O{XDPe#herd$}`+@3*roD?~ZR+#Mbq^VzI|{8e(ZRo;{q|)KPF|&gl~-&r z#O3|Yg*>qX-Fy&eQ2LVat~pCeSr~r=m3Ohwg>mC)zFkpC1=(%JxH%#QVaRjRXe5-o zb2F7YAo(!X_L?Um$8tv`Zjnd624zsZDDE9x;}qY1Ra5HVks%eD5UE?@{k+bCf$`-b zV9%;7PcpFwX|a(zt}Dh4&??r=W- zSroTi%w`vAHNxfbqcnNAL6l^Xgf?Ui<=KvT;k_s@LDS`huQgfm1&|P?CEU2F2*Cs` zFJu=qMUac!^Q}MVi#OJ>s;{ijc3xzZcaIc9O6C72s`{I^5)h0`9m_Ak5rub0AK5%R z2zDOZc^L{_9?2}ltaX6vaS$8pFkpWR$b8Fm>w5oi;C0)ilv=?lmrftOg;sIRvqXD1 ztS9Xvh5#e$>nz_M$90=rEv9M=%?a!2g;Wa3Js8*sR_m1tSJR$j9q8+$4pxKNTmH!F z!`+=9j`y~EEVQn>o#_4L9_7^Pfo0TepOi387G9#?Sui&%=)Qv#sVtBXyG3uNw2(SJ zfG4XZL)3C^*QD(JuDNA-%3##bDT{(&?%S^p|6^+M!za3;?(E`S6cuIna>2V%XO7D; z>tVsW#1@L%e5>8M_(y%X2}Hz9v6{Z?VDn=TbM~CM@*bxIo5w4=5A1t*kVdq#&@*NY zOOEb~A_-kcHer>?n7kbD-u*k*{uSn~ODPV_kfbfz5<%@fF_~|?GY^h_nk-X)Sz4tU z1?%Z%4*DQPDm7h#YJUu#R8Njn?3ewCl&Cchs`Sddz*Bck-<{t5cG=~!QQ_H<$j%PkpiKR1ni7ct&8`qAr_7(Hg2S;VpSE-yA4`r8X*Hn6cQBoD>L&^^0I(MM}b`4A#@W<5iy9;vktb&D`-I8A^@->!m@y$Y*X{EIAMG?=I(&s8>Y>CvSQca&4Z#u zy!2ww4(R6Ky7asI=1i#pMdj$j{jEXgG7&Qnwnl|wOhSx}oB@_9^hQ*1-U&(wZt@~n z*V6Leq5hNT-NhmT+H=@#!d{XEJg~siW^CHn43R-Qq?|;lAO0P-@vgARH?CQT2DOJ4 zsi%@*AM=i@{m=$B@-TRT&d%=WGY&sT8KA1bG#L^-jJ{3C7`L=kUP@X>g;XA z5zN=SEd5g?&Ir7-IM3d~xr9f4DxPa^9DQ#l>ZX4cHh|OYgDN|9- zvCeQrBcGuB*dqv+<@EPc-XKJGv0c@)Zz=WYhN_gXthOa}um$a=CC^eD6>eCYR=n;x zCt&r4AxF+!uKOCjC^)SwBLn+g`a?J9PS-8X7`Oq@!VjmCymFFIVNnFBik3+M^n@>U z&DA+C?Ww;ZK@gsbWF3R`!xr%}UZvSi-P9&?nha z_Y*L9dflsTp*x7@SYT@-K2o zBsEok`rAvKed7-9ME}4*zg(RkdbEl3H~0DL?p+fZcp&s%Bwa2DWVY`9;=0tL_MEWa z$-N2EO3MNthPNVKIgMznaC-OzZGi=B*?)RykMZ2U+i{`qhz0JdROF&@OgpF>Ceog$ zo!z<{#_4#Emy)C^6yb%~^&9nj(zjrU(+fO3>8{o9zHaEJ5qToC?KGr=a>ba}_m+kgMO#)1?&gk<^FT1pk!oaAHsBJO7J$S;uudDpMotm~#UyL-HsY zAF(=LgWvN-qqCe$;E%gErf zvSWvV4y|ZNG+Rh<<9w0Thw>!%zIF{o*~O!c#6=?wz1Ct#BY1S%F`cSai&Bp}1mpe0 zR3m#L>t~l{@)E~0wKS#ZTUrfn3zAusbO!N(m`zUfw9|B-kDi>wKclA+5rItjbG zu;Nc}t*_207N1myswQ);h7|)$&Z1A`Srz>5ZpFOen(E-89R28pfHJ%HpBGnh=4eWG ze}2?Z32~;4Ct1O806r{$R`)0dI?QiY513m->SsF%YZiRDOCOni75rj~Dm-BMe2hye z`$gOqM>2A~T+z;PiPkmFp$DlOLub|I?+*u!bxnPT-3S=)O=?PO$X-ahZ3Q{8ZGfkp zpY=8_z;OoK?|{(oHB0FJ^E9T=*rm@KX_{)Gi+9F%UYyk1>>u>WKLxderTGod;CfxwZ*@8e zYrm?0F9#FWoQ&aX_(pwV$3FfTv5&{1q^jLWLfH`#Gp@rexA+wfldmVo#?Iz%MJq@8 z{MKfo>7Wld-phiP8|$BQa=Bc$SL8qUuR*_#vVLQs>%fYMlI>6TCy0Aps<~CIsn7)4 zdfsh<$hT^+2tR^VE*yN%X|W2mQ-bwL>m%pFUfe=B$nw< z6q3a+!_Lt20J8p<#cTAhXfba=fr+K;#SOy&RAWC^|NE#G@k{XDu*D`gCfx*Htwv*4$=WRHWWU&T z{TLDruY5nU3J;j(1%K{VG0Eo_7(}iyPLy8w4$boAK^G|BE7#BdN#4!-(Js5i9R`X4 z+SNoANLvaH;BM)@Xr)(eWMf`}v8c%QJ+r7iGMmPpA!AtC<&bZ8ce@4Y_k@r0Y6?f5 z5ViKC5J0an9y<-s9g_Y_gic@0-fuI!}(Z_JcFU z@Md*=uR^_(?d2qLPXtmwLge<1h)t*$u5{L43 z_N#4AAQBvu!Lk)|Uf=zhfBU7GriSw;9^lD$Mv`6uHT9K^o|KzL$SkEcZRi~lpXi;7 z!Cwg6+QgUfaa%^vSK-VC61w5U5AC?Q1LnZM z5|dQst`@cWvWM2?q9{Cx3lSklJanExh?tIP3sEkh+#i0Ua@42WTvfnw`5SW&hyOY(0`N|rSd*0J3$ zCQJ38Qzg9+xEH=MpMGlmh5Q!Z zldpyT>T+P{?f<6xAhQ3~QQxp}^KO?_D&v=W>Cc>)6h1q#rg`|c z7Rm`I6aT1+^|X)M=mZWIN@$~}$O+U)ng|(Q&X{0`OhJ^4?JPn5L>M9al8sxcJpQh( zb0I(b4PO@Fe-It7mK`fZ%A9vXO%gWUf&hw|`8BJVN~&-LV;X-+j?-3$FElC|vVzjB zaulamNAowya-^WN(-Ed2i+7~1&Sc^QP6emPdT0)E{p&$w=b{uhccg0@yWaWGxI=I5!?2DO$ipHxVyF-&sKZy310Zf+mSrA zgd4qLUzYQ}$@~4npsp%bcupleOER3pZ_m77MLZtM6;SJ0m)x3_v83LQ;g<9!C73lG zz~bhnsa@K)Ca}63Kci&VG>0)BOE5Lf%SToDaVPHssbR>?aCp=FT}Z zGn&t~MRD>d$6LBDMLx>vI+Hiq`OtnI7Vw=sOuYdNT;V^Ucxr6OnfBVu2f}?bm!v?b zIDIwy?|fE(`Ed(Dz^V&BJGvy-lg9n1=uhboBdiJWerR4+N4d<@t z3*@;vk7#!E&nZovvH{Ra+vgC}_}9BjYD*~{E&rY&+K*o1Z7N0wkcdvj!Qo$s(_bdC ztpktw+9T)Dd;tc-hw{HR^T*?@Yxg+ww8!Xc)DNQ&Mq9XPlIc|8wQ2oUnhZT1CGNTp z?pk5#Ve_^h52RcEc~H8EFuSmdey%3dyDT)YAnyklM?NPnQ*Yx!!PL&v;`Y=Lly-fx zO8+1v4GjqptcV#oAK^s2c<|_PH9aXVPSAzC=*|{u$e;aSL1= zlU-xs|IV{Y^!X%yb`AEv=wdV3=|Iu?w_LehQVQ3fjxM%|yJ}Xf>da>CIyt9326SxPkNKjR^oFg`_Qf?do9^&mN%|4-v^n~phBHjIKbWd3+pk7)!|W=;|S%|;0D8Z z*VT-C3`^(M3a^~ergzj~g|L_GGnA|*!Dy4bbg?X61$EjlKu}xc-QP3rUxm~0SZ=>0 zn(I1QAC1q+bDVD9ivB5^-&)}Pc$;;{&F1QHhJxP3m5lojaT|0&#Q{l?7(4A;@grCt zAX)cFi3&M41s1SDf(}I~CM_(PyI!31ugYa9*r+F)LgZt6BjoH-;Yy3cr68?6axAbc zzod0BE}kxjxhuC#Z>m;B;VJ90$F%U7UOY13A^zqUU8qdSzlpHJCO=pS`-9hZ%xKGT z;D^}4z(B-_l)b(9)o!3UE7Xxz1fTXqS_$4lf*!6j?2AQs`{nx6_W3fARvrRgPbG1?Dk{E_Td#ZBSM0i6i!ZHUjfZNUs#YF zpZ$f%IaHgvo8{rTBrumk6|;YMmXM>=&b<-Sl9DZ`>Pu(dEQ_(j(GRjyDAP)A8SE%s zMK_V-==HR+j^C601$997l{$HxUXsvv32yOl&-G9fb;RSyIC^;6=gGJ`DKj?-$SxQ7 zoEGkFv6~Fc?oCd(v}Gs<0%T9wUr8;E_6+q7{9c+%p0oj{ceGZe z!9~fH?DUI?H@m34QSoHB;P}UZcayhYos+$k1O>eye3*8U67837iWUprh1&Sa#oaF) z6fH@zFb|vBiLUFf(1&;}hWGG3Y|TRuvG;c+#U|$3L--&m+Ll4|rQ{-C1K5Bw)hx7f zX9|jhUA1^33H2}{(XE0x2$n#>#0$^aTa(bOok}+k{G=`#5?+IZ2$NC=?kvb#a_;9uGG&u-7{+r7^3cq(QwLtOc&Ws zYh?KX7B$fSZgCgB)wnuZ7BRXbbB39+exUW2>r`qxW9>>**`MFv*o!?`S)gJ9sq} zfKjXdHctT`sP~S$_X?79RkLE(7UCTCUZE(<)lEBbSSxGU<%|Eyqu=wDyY)5~t9l`8eSM3mRF zkw?+!n1>Aa+s7Pp9;_q38}o@3`>AgZ2SJ2I{59Eb-~LM3U;XaN%|wdWSOe@@IfC}$ z!u8*w#TNTzn!@W4GX++!%TOi~l0#pzwZTG6f%E92zdE!VQjf-TT<~)tfEe}?O%~>? zd^Cd<_qf;($(?$~$Il&gRr+N> zLjPD{_58Q2U9MOmmDBf4j!pK#In)cAri*{FLsV~`+Aa=$U-bNQ!gZ*wIX)uZ>nf?e za_yhE=l+Vt=jkQdccGoXfd?H$eiAwnD38b5I6}IVd}2BxnT16YuNN8bNG#&t5s3((@f#%AyY{6d zuVa<=Yr<(s8c`M}-ze$54I&wjZWQJ1ayG_b(Q9Z=mwaUs&YwW{+Qsc!2Wua7B#)P+ zCYnCudYthuVrytZmiVP^zIP$){vUm~c|Ijy8I{Uq!;{w@-ujH=?Cx=oNhBgf ze~@UeJ-@G@C83g6>*#Z~HVwz642VVP05cvN7 zT3Dvd01h1tEeJV9^lQ&M3(>>vs!P%7c5c)5jf$`G>VHvk;G%2G$o%_QfKbNpcc^vSu&bk*_?InFv+|W%hes zTrK1^0CnlF^$oOs1i1smlI;6_zd53tGM>UDA6B=`p{8fYhKg1GJz-*>oTyhw>9cs3 z8J1DE1{%KB@X1yDjlYH|FAS^MS%B2u%L@TxeD&{FKUs7svIkvLkjToi^9HTDvmhS5 zm_m28R1x(+udl?f-u8hfe}jlTM6!WpbMOjZkrqohxp?KA(LwBS z?o?AQu^_n1E9tDEcYyEs8R@#MXN!e`YC@l*N(i7Qc;o%Hzd#bU_SI9=Bjj7P|LUg= zkLTSpUC_q8p3kaXjC)g&x;0HmGpCN=0}z0#fvEf3d2)4RNAh^|$q707b79r7(}zQQ z!xwoE6N6i69Jcg0%`iW|W&9Nzd#&zt%7!V@`+aaz4C3EZmB=sWpXF{G*4W0&)N5G%D3( z7nisw?U#OaPWU`eX0db#5&LCdJ4Y~q>LJsV#z`Z2ZC{@^f*gmHn+thn=z2VX39yH1 z^-AH6pD0&Y)uypp6nuS_wcFDEPciZ0l7r4NzI#|ysr>D9FXh%DXs1pSnf@{1Q?3ge z`~ePs4yFaz3rC8=bXQC+ZmLQtnL)iC%VsR+?2JEk;Wi6i_AiM|-Tn*9YzP0jT%C|TZ z+kcjSCbqz+fbAJ1qKKgz`g*HVLm;`JBn1ikd>GkEz^{Xr_+d)_G0F0Xr8o`ep)GJ+ z0@i7{$yd`SZZtYv2s;0gq$_gCY}0Fv6b8C zT8NlxQmsyIcizGYf$Qxh;YiQ@OE|J90kl(P8ZpPCylU)kkXUj~oum|H}> z74?|y9p^xW>d1y|U_bXXJ2^&GjXx3^nUL%dAIOwC)Bmg>XPcqSUd)Qc4hzniwk)j4 zgNEqZmcnJKL%P9v6W}$emP0-Rle6bFmcu7^%9ma8U0hQd8}DbnTY3r8iWu`_gG+$x zV%I21=qdT87(FJIGJO##C26Fb^v7LmE-Qzc4s8f3S5t7kMt|c`S#1lXNdHXa2USX9 zyW(ZRgvrV9OvT<>UP;97cB!z)%s-)hoNiixIOVI}TfLxk&D!~=HTLu&!2m>IYu5Dr z>-6BY`Gzo`*=4=yUn8EGPw~?4@f!DD{nRN)`@}YgM|chfAqc8h2M!tq+U3)uohmdM z7gOyxCF}$2aM)hFhil3dLUC8V@di(?KF?@)Hr0fxRpYj-+2?dsQAyh$v6q|DRg6In zTC7b(=5cac_;8C`it=nf&*R$&9IIB`4T^zcD} zvaIMePoi+`gp~8Z2X2kX4Uf(~{RgAtWfMNmuBp0oY%gZbH6r9?EYp?HZ5u8mw)ZQm zz-xnL^ct_6T)6De-xb9^%eS6MPDddI zPb&%ctITXr*W`xR)f?{~nwKm`TL7W*yWi*YRHda~Lkq$dt{IY+BEP(9^Bn5~L2i?1 z)gcH-UQ68M-NAqK2mB-c_DCa$8kMz*V7C~hOF`eU?N6q~}93KAmcwQGd~7XJzJGlQkWZOhy%wsU|X$L5_9Fm}TgGzVqo~W$Fp9%VDcX0Ir=~BUuQJ8f9Ixdq0dCqnKWK z+{!-Pb@}YXWjMj9p+?nF5`K`uAfm@!oln5Z0d%w(S=ZdB&bLtr4F3k7H#SumJ5k*9 zXY{<8c~$50tyE_qZ+=75sPjDSUc7?_T{rtdnzAG6VS?#<5-!g07>chvvsU$jjywLH zHs6@+?E}H2s;DZHJ9_RvbG7%HuBqL7d4{AihD^)Zwl97Qq>r<;f9bE+85Bs#q|7?? z?A%iqWU9>v9w}MtH|>GfG4`ug`O$+&EA$!qxANbCI2hbc`UKI?Bl-*BDV*GF_PFBJ zc?7Xz#O|LWg{kHHopyJ8!PZ_M1Jb&8qB`6+9Bknu3qN|xqW9B%0o>t7#qp#d(yBes zj^oT3qF9mB2E0E194*;oJWgrfAfbJ}oz@TR>smLP`f=p7I~&GPaz-pDsfY zD6fpYi|hV?u*nH52#!9C>0C4M znRrFAbkWmwwHF4_@t69Kd%a4{5xPdTKNgi-k87lFf|n(iE*D4grmB4|`IU|U{9JUf zYMO#mJ~-suu2=@ATRKAQXf1@FWQCA${t@v(RRk(7gG_L2=0EB&6txcS5^koV8Y=D~ zHQB>ommOZxYkf=KL(PG3`c=onhTk6^?_}QbNqdi|4t|i?v19zG6kj^HrcQ~-m0hLd z0{TaNEFR0fesP zgrAA^xW`C*FI(-BMi*byYIhPTy7`-}m$r9dNbg{T4*3OI#Iw}GX$RLsDwoVcxZ%Eed(i zi3{m0<`Q9Tkn+e$uI7Jjk|(nYZJt+H_1F0h8{V7!j8^nQUus9}pFb|}{)&c48*^?E zJ=SuWU$;x#QFwT=G!uNu8W|B*2uG?HC#ZAK6!wTz)!0bIFr^})=^Y+fz@|ZCFg<;Z zPhY6@66vGA@2nbkMRYGf_fb74S;^@J@mc;R1|`|?^)@%Sxu+WWPGp_AfEkRzG>)~%FIHguk-p>5Gk@jO~xk#^Znz&!J zwTHT3>Y!}tO#WLt(Paq5t@*xBpkVR6VRy^?tO7{|M8bziu7i;G${e`CuAlK=W-eB4 z4J&sNGnCvC&4cxy(wcvbOw6ovAJL8A6KiOs-3L`&rQ(hz%!%H8jL>+y8qJkp!W^p4 zU_HMq6TV?P@oJym_QtY3>E@L#k>`Ei&pb_z`W2<^v(j!DDWpCh8YK#Ehog~!AJU1d ziy60{FV#g{F+Z@+Z57Km)HSW{;GzD>1W%- zEG=Ap)3o0_$d!)!$;H|(w&N?$VLJd4T(jw}+iyUuxti5t#Loo}N9tEb;~iD%^J;*~ zRhAEN19!vdvYANe_FKKMy{8EbRsn($UqUF{jrtX-3*qYN7fDHO)~0Yayi1#?B%9HbuH_>8KIaKxo?x_lC033RjWXzF^gz^dghSeuOe4uQ5G~4Ua|h z0_VfqccHylU2g{~pUit%d9{R;>__<99LnI0<}b{Qa|w~s!xGO6*Y3^<7f*gA(TpR9sv$}W4Ya(JAF*d4KBvIlR7Wh!b%sTY zgrr`;KyV+ruI@t!8A;t@s-ss}!wzYOxGYT(EDVS|SJB`fgDBfoq6|W87*m+cf z3(Z_nX?s2Ly94mAmwH?-(3<*;!+4ghFu>`XRqfs9>!};0T7JnQna+w3XnKGN`O>o7 z`)u{{oNrqk1-U8l9(qL!*QI1fuw-WyTQPK4ew zsV&$gpgpnCoASbJLgp`yF4TR{qlBod5q?^3>cGRU*lT@7C#e#auldT`&%M^c+R~eudrH-m2d@yUJLSjHMM)^H_ebVe)EM5a?f+sSB=d94@uz5p4caBGYomj~xoP|~GR-XRw2+BPD+8FWG zO<}m5Fut9eHMb-!?3oB%%J+l^cE2NigyLr zAG&W38~w+`Mj(8bp{3W_`&hE~Qxl#Zaa-E&M{TdRCFfC{Xb+`FYgW(@TH5c=4|}=X zL9Ju;hYhFxzWU+&5FEDKDSGJiBu8akFX45GaB0f=KfZkFw;V93e#CrAkqNE~V+5B$ zJqWr~4W5I`qJjE-X`bmPm@MYw+PSm{FF8&D~37{33^ZY-$Wd3CyuA6 z@|1^Ba^mJvZ(dR-71}25MsDvHENQnNP ztAhbl2-V6^spZtKD{VU6w)%-Rfz>HFPA}8Pz6xBxn)Am?jp#4d1uTzZlJE(~(RU_5 z&Nj6)Lxfc7_non8=H=t;|1PDzvudN=+aKQOfXCu5 zf^lfph8OSqA**`+*K%X8323esh7BNy)1*1B8ecQ?^Df60-Mt$3|n@d6QDZ*oJ zT}NFnWPdhYXZ&M&=Z4R0>rF4B<)w*Ydn=3m5<+~%zWi*pt5_ZL*Bq0pj~LG-!uo%S6Y6ught-VDnfyjgwOn%Gsa+JFK=K9+j zjg5U}91vY-I479V%W55o*{;Zjj7?PxGVAUaS+#T53r}T&oe-R#r(>6dI6{LX)WCtY zDx(ANDbA7zkii}Id-7WCtox&HPmf05F+^<^JWqt&qvArkd+xtxKeO{-d)w{_I8cO^ z;v1?1N{YMCs-~2NlVfh;O{ocE@-4 zrybWF=uRd{^RCyv^3QWpkg9F{l+1rMwFHP}(~c1b_TCM~0p{tJ3iyM+#AbJa;mDmz zqp#Gbnj*c*P;Wk=vg{vCzLX5wqO(Bq*yq~6!q_&xQ31@I6hy^uJIDWcZ|-03nOY5qVZdlbkLt%3aY~>ke*guw8V} zW4LxZv+RB3{9)wGALHZ_Hn=V&4)}$6cUKxu6vY0Cj>ubbjqTRdBnHh=x)`i&W#yGr zL2``UuvLOf)d0?JO?l-%ruu~c*Vsc3kDbQ99DsAYp|AX0OtCBTl0SI*#krRbi+Tba zhXI-DOSb~RhBoiEcY@LTkUNCk%-9US7<%wbM{y&Pc6}5B7-C;6*;3KDqCCjKu^0x% zdMWMXtqNs^rrq-86VTv2mRG*^HS9?r1@#&noVsyy|67l?;GcHhR}->eStYJl4Pu!g zIXRIo5*O3sR)b;R0Bz4_#$7VBI(m2uEr!}(DH|O2mUJBc2Zf1vo1E;gcYn#Pl_N#y z$6_p1lhKQoZupSDwfybcqT}c%?@E82D_SgnVNCQ7!1v@uGto;Jyj`$G?aEhGl0zvn zZObX88vAt$7y7jEU5jl7)9(l+nv@rXj@Sa79~_;X&Q90<2wgrh;T2C&{_KUFBUm&vgBGnd?}`>=D86~P!P(2` zX52ck+9{)Yc^9(~?XD<-&-t`n!GghWjvLfiH3keiO-4=P04ih7VdzaHAXWbt^l zkczkMEHvLjc$$?Yvzd@ZhE#c>L_@-TS$xzQqOTxium$-sRIr^Y6OHm{*Un^L873vt zEa(8q!W(o6Kzk59tGq~mehyEyCk5So*%+a$XB3LR1(DVt{+!$Et9mfr?uHVt?635c zpXVfvKejT5w7r!oRw*Y~I0Q<`<|wOfc~lWI&*X&@`6~B>aslho?2`1ieaSp%$a00W zw>Y)6z0J{ZQ{U2XEiUbh!{|QoI}n`2Ve!NlC+B^j9MmcP%nPf1PQap@F5UYr+MJYS zp9Roz9c1_JSv({zoO}mr1%CfAMZL)CBsyb@+6?c6G8hXuRp`yd9<|^qI^a9%m0ohF zdY96Ub;?giyLQrAp>5m$vdyc@EkHK)7cF05j0cV6+5Tga(LPxy@8bSY06Bm&8D3(J zvxZ)R%1)Z~cFXAmL0gA8HNQmtGe)b*Wdb5Ap{k|7yJL+Ih%_A}%{)$XGsrqInVxzg+E;-iJ6vjA=Y#MC>rJdbV z)}gyQ<>++1a63N7_qJ~0q)M&yUY*{01#+M@#K&!P;X47^mW`utNl!2JcDKgfq~cG8 zl?w(5ki`n6MVDM%D!P3nJ(rS{b^Ikmt6fEZAcdx+Iy7_^RH?J1qqM1I70VeWqLIs0Vg)!g^YwG7(GCgVZyEB@*h*O zqsT!rZ&Tf(xTm9?c$~^ZM~B(V7oB68UJ_=o=$vU_*CTq{Ttx%n0CNI(FDE#fC^u{C zI zKG3&1`v%4D+pnV4JQ$MX?Sn^V2k{BZbBr<9(y)mpe^q-S`K(k;;!o&! z-y1J2Si@yg?A9t*2Yvrz3iE0j;(btDK(=k+cih=BwQLZz3;YSH!*?Me`_sxNZ~jt~ z%0A)jno_bT1UBTnyK>{DGqNlT6|#Guh~~CNkG%Z-=4LwzmPc}e6cy|w!Bm`YYrEv& zfp`~PcBEIID)5u&fGd)x{wwfv=9TbTGqrtZrGaJ`Sv=POv9!QiBEQjBykAR-mZoLW zg1+>8_r58+XkIT(thab1%OaT7hYw{jfv1!q4YFneRC7{>F!_5ZR}wj6No*~_&%)|t zn{1^T*fo-e^Hv1p8tb@OjxVs%uVC{~xFRoY+Du0hx>PU7m&V|lc}H}1OEpSU4>P@a zQ9eY&DOI7lC)^|<`WjisjGhz-JO8JhQ(BXSj{0`keXYAL(@Qtn;^Du1=FTjWvWlrD zfE!|myYj`R;uKr9RXdAvAo+P&oBq+a;&Unc1xmCfMh%ux8yQroTvP1TGUU~MM{anu zJW6WYx5?qj1&Y0;DAh^=9IoGEGMCd?e4b|W_0OUJIlYv;wRLKG96!-SN^z@9>27p6 zQ*>`6e7)6#EMbz0Qe5F+qp9szBpk``nI$}c+qJ@e7z1o=(m%WkipUhyMtbWHSb@yZ zrE2~B&{dZ(g(7c*kRRLi{}Q*c)%{s+w{4KfAtH&v`3J-LDHGxxZ-KK7;*id=3URTd zM2IhAbZi^T=lZK1MdV=vB%a{U`c5{XJg?<2*TMxtN9A)pL_AXr;}`6fZhxcl$PI#lE z?IZP@$thnp8P{iI*((E)R_V9}+a;EJ--=O&falk*)+373F>pl*&4*rrGOi)Jxn}BT ztY}C{^;kK<&pkGghy3AAy}x->r|38%i+b?-hr`g~lZM7Sa*I-93gL(5MCbG74K*G^ zl_cbF`k1`d_p*fNIf|@VyS2_o9E^)P`>MtV`a7EhGn zpfjp`^mAaK^@SIaK}y@iFQT1<%0jMh{!q)7ykY)I6(Tm)Gao&w&EA}Da?D=PV&_k6 zGz$K^;ladE`(`pn?cze(Z`uaj0a<6;ahH+~{@~P3#FepOI2BrJUIBeCI{s_MCS$Vl zB-&|-61?%ZPGD|<4o}%MrSB}S((?oPk}PbRqGWaFL%OHy0XvT3045&Ak%$vmrjBPc8WOQs?3i`Z!DS%EUa)oNAO0x-nb&@ zDm@i!fxM^ZfVw)OXB@t_gFJYRS=y}+QYlfitvU9$qg0iNQd;f@uHK`B!6a-{I`^bh zrk^Lpv)6BAc5GM|~=VtzJ-tDbg%?Ti}-v3~lqx3k>HUEDc zoqIgf{rkstt5lRul5<6rV>zF7cW_83IiFTJo6Y$=Rtn`9LXJzw`Ft40mc(KXIUjby z9CFx``aHpl)x^V(bES(Q+o{ z5kdEJcR=2l;N^9piYmC4lEG5Ln>B;uIkqjon2_P-mRbYL?;8f;vv;43c)JgWY3K}p z(R0SU4(Cm2is;+L37s`6@U6)@&;H%}T3ALbOF@!K!jV7f1XK1N(Vt$Da1t3ogpe6K z(?V^a z>79aU&eVnNwxsDV_fx#xzjEiklrBzjdoGGGuwy=0~BsXr@r8Qx`s7F{Eshba`=tcr?^ zHz(k9^iNMf=EJ_ldCJnX>q2Fw3eX39JNsQaa)F>XM;DSkeB^2hM;E{eVf3RXB^=l5 zz9fbRui{k*_A~hDMiRtkc?k*CyXBMh5v*%y@R_W-L~IMW9S7A)&$CJ`n>{TfhR|zH zd8=)}0{T{6PuO}sC-b#J&F25wYk|1KB%58#a%}ZN?<<9&oVUlKt(S)sb^8wT>Acd!2N7n}p?A>@`+!wNB+9x1#D49Q>_bBX0ux8B6^D`TcKA0#FcsBMBv) zv&UN_V~qxC<4DKM&y<=X)TFMe5P^iz_N|m|_{=ipdobzjR%|0hPI_pKo2wa_W(Wy6 zeZx4v%Q#g?i;pwfQiCHE^yTcl5bs7NGM*3AbeHf8Z~ulMs+(Vtg!pl&tK+5hGnu53 zdPOn|x4k@zP!-538x|jJ{yULbxKV(83oMKrppWD~-wQa*w+vd&B>&XC(dwwbH$^>Z z(A>{+x)Gb5Y{Ns9^K)6 zvZiEDiZseTY9mlW)Xyo%NaOL!!&hIcK5SkWjLea_k5h_fl`vb9>}tRe$pNZ%)6{w|3^i_@`Hv&HMIda>9WC84_P`qe zM=_*Z7WE0_YwJyW!)E(o700d&4}(-U_b1o0$g(ddf?3ILm5K6`B4bdZB9sSZKj4J= zFdJbhr(l<+nnJY?Zai)QC(>w<_12m5ZnoS|eOEo1TTrtH8Ps^uu7S*@)ABXYtN;n4 zlxb79+A``t@Oubo2lZ%f_xMy5 zdwk0Rm(A82ie>5%p%XrfsU4V%oJVIn%Jp9ncAf5;*$ihk=ne7$DGlMsm(d!%o>+4i z5;pc|g5Rzu<;S79j-*g*Yuju5*B*%$f1i)gX>g&M&U3GLm4%&yJ*bh zPAgzo=^$Q4p3gWOzxy>s-oiUZ(TBnz7A3PLXEFhqJ&U(8m}c1+HtLuE3F{4CD66zz zrB|u0wX92Co8hPJAv&f-5p3(pPQk0~pUNYy?yiOH-U(crwER}P2z#?-JVz=5gx&)s8za@Oo;5s*rPDO7S^3ho zX~dcY_L%7z`YD2$Ky9t=FkjElB-N?xi40o`a{|FB-CfFevizH5xfdy9Q#-F2rC7xD zzj40UFOPFrjB4$wJ?k|zwYnZKlxb}0S=l^gnyIV1RmzqSYj*z$=FV0|)KB-u+Q^IY z*QKqI^oWu-t?uSs#HP^xTF>nL<=HUFr_xQ43UF&w%cICs$b=LJ7~bI zPL{yP7%rvzvnzqZuhuK~(4VH~;W6)9forg&q`x-xD?smdi((6J2RUnFcBo4;`MJ=A zl2B8l;}K)>N@_&6)K;rm)I@^6Z}^rK1hUxbdC9-YZyw})nP8uGPp?{6-8q)xX_&G2 zTpCs)knj)JfI8P@!^(`J+#%$QD0MIsl5}uRXfzuP5lzEq4H7o+_TV1_=c&wq?Zdfl zWqg7^%095-$kUQgIMVX^glR0qo)WSMK@xlc3It2u9yG6XkTfD(?Z(EA~cfs*s=h9OJuA+~b^H@&;y&Se%^| z(Gazi{TbMKLt21m_t8Xyky~TmcFV$gXOxx9b{S8>p^0GNg~#Be#yfG#q$98*tfJzr zS5mckMfGGE3s#%)?g?fs)_KhE>L# z49@hgeKr|^Rh0A^9>XMvz)4@Y_l*^sULv&)Cx~%NDNn6G`jHQFN`prmjoR?eE3`X- zE3fZFc~#853x_ZUERhU_{%@)d?6)GwGpNHt;o;a1pG*5Xr)cl?otR%vVuN_@FbyjT z>^FF-p5=P1yzLD*0#@-dff?-f=nMumGnJ;;acR@&46Gt?V{M2pwO;Wq)KqE6b4zK&SYk)BA5a$Jl+%0{$6Z2zIZRqqZNE>*GeFqplbW|qD&gn~`X&VWAW)d~>J zs}SDFmt-DS4e{B3xU{UHp%d^X{$oAgSY*mjOnyeLP_AcEkt{3OkP@u*cf?Q8aQIH} z_H!*eO9Fvil(G3R>!RUQ0(8WvGkYQpf`1@VBu!lX3roc+y@!4pN4|JIWaPZ$glQO8-b%^y<{U$bG(|ExJ30)$*1t&8;A#V&L=lyF zPjVqc6P6hd6oC+BTWpZ2b3e0tWzN-<*EDYo^YOf5XY~(eV#Q{D z^?(8+zevIl@pvTr86SGB3N8(xgmg`h{n}qO3Iaosyo<1kG$^Ec<|M~;RQebxw;Ip| z9)J8*E$mf>xE(XiA%G0lQ#14OB%FcxHbOoWGx;w-tjKt|k74Dqa@c86)okk!)*~@_ ze??x-Ps9BW`6uBxs$bx?L}tL&zWcUu?R-1&IS`=X%#}&yNKW!T7J% z8h)SQK1QRRHLw`xEliK*eisUUa^}EoRq#=qkz<3V(WiS1u4vciu^>|=tj=HZ8-M|} zt0OiKkLSm+xZVfZNNkJj&-Ouu=Pyi)w0_^v>+L*RH$kG?k*zbG&unBHdL_Kou1Xz$ z%~5%#E2N@PvoUglg|bezm@2eZ_D_+$kp)*8>|PR1X5>@9ZtI%T)p}FT!_H30Lx8E* zHA6Qe`HN@m2A3m(la($%#2x#O!)o;0>A55Q>Zo6E-c9s1nE8Jk@8ahbW_u@oD4F*8 zr$31cc#By%qvgB`GEX@>LvpBE_3`mhguKbNc1CWs1av(f8?geofYSzU=?;Z18PyN{ zp#i@XziM@YA%VAMt2QcLfUuM(c`^5^F9JN*M4*CR`WmISnu z@8-a!6#N9SXBwq7tp8BAS)zUx60E5UrGt&!+btwBi5I_5%oKxhu*cMTey>f(?({sr zpZ5%XRe6YJu*z6IP-$yxjjia9)r}aIwu$UY(ep}H zwozJEO!+H zgI`pug_G{2${(te8^lnZB|jy4%dUVFaMn4{*MDTqF;NX z@#a_?U7=_5k{1~n*XwhxCT9N7PK@Wz{#Mi4K;j-Vz3gms|M%N3PR|Nd)3ml?4)aH_mAG_0gcJ8l!ZO^f`En;a9 z<|*PFNQVna9mx}ajp}a;%muWIcZeUMl z@ADC*(mS*dcsvwn6xWlwTAIS}01TS9Uqd*gCOkuUUpcigPb8g=wHS5SED?g zhmKL#pF#wb$J3irxF_`h1&(u~*}YR$jazuY_N!W&x0Q36{@Cg>0?>VD^WG@j4&o)r zC^D^wMzF1UFZ_m)kM}X^4)(Pf`*DNY?5Z|(F(+w5sCG8rO=fV*5|R3Q(c-r5%J_ps z#`{N)tTPMThh|IJmyq8F-4O0$u8ixiYJPh?ul>x$83%1!PnM3Y1~e}wz4UEUSk2MU zl$v1p;a4f}2TExFS=M;1gR}M`T>5YH{A0yZ(xaCsuQ)t`()ogYAE_pK7GuG%j;wm? zZNgaU5{$1m2$DzQj&+lx3H4ZYs#c~vQ_uk}BUGn$oJ?$^F>l>(iW zW~T&}0^6?TzL{J zgr#l8c#GuII%cei!5EDS0}y}%2lPT7%jM)c2vkY4wrQB z0Y*P^7g-csAfE0}hiNm+Zu%p)yiHnA)I8xWm3>HqcaqSNTP59KyPhTL4{9qAl(ju< z9U#u6F~oaOjkE{bv_3qA+r{gA>=QrfYQ@}_e4aUXo>ySE=ybG2 z@#22{NIX_^aF z?#L3f=vlkq*Kg&q>t^YZz zxN1c*DX}eDLRE(Q#UC8GwIhlR5*rIzKSXY9$r>!Smp;I~XMg-@!cFo$--D&_mC{v5G3q5cKSi=yzH%Yb*~nHF z^0a@=N8F|PgV{q%XkpkNrFD?T0UT>L)eRCLnv{5DS#3KQOR>X=h97*Z59ft$Nd#&f zQ3KTwP4M^4VC&d5mU*g3Fz(XY#VWN61*fKk#GaARDbsDnpASA*J=-_4IZU&{b_2pv z)HSf0i8R=HZPqbeImR0I6Y5(eoZiK*?9zsmM;1AJL~O$Fx|ZI5-7(cyj?_`j)~dsP zJ`knN%!#X2T5&-F>+yXZ9|y~nOTClSaBY`&Sl#KQ_S?^m2>n4CA0(_80{LG(7O{jQ z@!y9s1icpu(YLqk7otka9c*USg3+SQ3W$j?Q$Zb+VRma|3zmRt;RKAvh{!5A3#>T z=;USncM`!}-Pw_qS(fvOSERH2#3zZz#CunFrAW=PM*?e@rm2m$K;Y~t?3I%8P$R*! z&rOZr&v%&5@C3I#-<~(qdEl4c1DnTQbPovfj*fSA*d*oR={#o1&&yBve5U6Y5(|H38&T8o<=56KZ ze4_|Ub&pBxpPSeX_#CbfdW}xY*`hJ6H@*odjir?eM@*pL)1_T^o4jB;#SIE{oLkaz z_);t{z#ym#g*?%{j68$ihgGd_Gjl_S&MFjKw;=8dEji9u0S6;98yXq%7n|+LVn%Lk z<3PY%_xC-y82V8377brtcu7jTK%!49KfJU{Y=-N*U{BR#^}ND4zDLpboQr=gGmSs+kpb2w1tt$dv&*b@i|1A_ zTZUj6wZ_|y=-Cf>l|BHlg|d!LfVAuRvba--ZBXVMRpjjI^Q2=?IT+Cdi4gUjtY(}V$ z(^l37w%W5ma1^T2d4KDn5BT!SS;PIsRNCDFy}uKHf^nQkhgQysMTeW_*LWgxpv7fY zHqb1W`0j58UVk6kOwQe?vvNe0^Bc!1$h)SjSRILF<+P4_A;hN_%T3jmwVn4E2N4Tm zV!))F54J9sqoG}X}Zu3>oKvGsV=~m1bcj#vFj+* zZM9zEReja9nZW}I>^voMOndR9x)zuq7dUO@BYVG6luA~p_6!4~O8X9H%dI{kw3L%> zmCcB09({+O3F3{#oCq|L`Kfx=xx#L?qJyU^Q+Rhsow&a0RI)Jq`Y-5x&axjAnK%Nk zfJrZ2{I~axsoC+x_>I}2o7sz}$_BSvt`yYu36`fEz~{8BwbzW$F8zCc;7sgF+(s6Q z=KwiZOVwCNGO+j!Z)EFL6S)&C7)5~L?j`i3kx3z5ic|az=*z5pX1i0C@Gbm=^+6WI zChgz7ss_~^W(b5eQ#es`@&V8Ybziletd*|Kc~E3}C+Xwr9n=FDQI-0wFD51%?Mh_p z?i{U!01s{2SADHq;O_GJIaAN~m?jn!>Pj>i=svq$v!({M8Xh21%@2uHIN;b4{c=C- zrfnP%v}xhwHu-|wW9BA1z|~KxUNvFWm$S&-_s$yyuFZf_ga6~`G!G-oJ|W9IKe8lo z5q&z31|JE-J6L#24~|sK3}JlvV?~*(C2@O1)l!uPBriP)kKEMvng4RSqc>UY7>}~+Y!!7kS0nUrEcP8?un>P9BMYNl>lu2H}LSc41c}8Z?%J{B_Q*u?3#ZKEny!` zRiy~o0!v{eHPEU@7mR;|Qy66H1-}*&*0onU3H^^l#jq;4WzCIJ07sdo$aQ_;Qt0mh zlD@ahDFYD9QoZ2}gI_EN6Cc}8?fZ`d?Q#18(|P$BLwejtj7T8MnY3AZQQfSL6iV)< zOjzK_x;@HM=Ym#X&)R6dEeT9o}_E(i^ z&1OzV)?QP6`qKlMnuo)eZ{N)OGun@T_Vg!Hs(kgK?2>z3X%N3N!*~t^%%AVo92P@6 z9tF+KG-7i6V=rx-|#M_y4#=Uno zy2Abb@`D!Gw`t;KDyL8z3%fKIRLcpR8xBW!J)lN$L&QaCB7s=}Z)JUSCy|q>_-j8t zo7p>YvyDgJZ@=y&c<@MwZP9+%tmh*K?nU#D*6PjkkC_|4%PTj`yn64s%*D%Rv7Tq5 zyjwKZLH62wsz*ZNT^XJw#VMVbxdIS!B}vaSB|%qXw8LmgH>-$fdK0&cSKz~@* zo@p(Klitac`!E;LmJ9O(E1VR~9sCO!QLQ z@1}@BDYH>pkt;ZcfK2+Xke6SfPd~=7La(uYlhV}Oq-ulf4%m6S2jp-?SFGwaB)={E z^Vj5^lk`Etf=f~$RmGyp`|2k})NQftvDZcEsIs0g%n$N`jC)Fl)RxlY-@0-KTE_H2 zbY+ZHW3qmZ4mq%1etjx^D&;ZVhu1^Xy=U`4#`^6n>rh2GS0>C(>f_Poi?9r?tE?WI zH{-q$Q(pi%$*pOJPD`J+$4kWX9nHi+C(n%RYH*IlT*Xd)Q@1nPZjD2hAvFH_ocI|I z1c?N24U7EXvO3z+4=`y-Qd3eJ1TgtEYI`qRHA^>eb0}nMYikb0^aIJ(g*19m3G*k! zCBpjEIx3x^66)WO9{(re^2WsU5=hR5kC}s5$`%KHxgL`n6FMS8nCd^cBBt0KbXA*%sUa zd_-4X#N#JItPxli3?`92u+4TaCMbhDJIZw}MHlD9VD2KT1+s_D=&RlHEkMQdu3O(F z_f%p!*P2eHUEoS&l2qoxC+}6%UnOjZC->}n)&&|vg3N&PI(@DJ2C`<`ZdC!Y?)PL( z`0lz|4_T~3s0y6L52t_htZFpg#w|n49*L>mwJbVlp6l!AF}vugq*-r*@p|Z;a_?u9 zbNpW~Kd7p~@MPasmd^~JaUOGDg0rur+q9w&%I6QBL^&2r+B9_G{dv^yhbzb&&~|H6 zW&=GeyEmhrW#?)I;8RK>BY+od?3QFMWjNkRD9&j7#)RF3tr*~7*Q(Sipd?0)r0G2# zrt@z==u`7t-*xzV5Ld+PJ0{sLb*XCl4QQ4i^UNL7i5vHec#NUk`9+X?H`7=avYZNrkxu@W-@TjC1YVNwiGcfxkT4Ab?V7tBaFwO%Kbg z9}s^vBB6a2U0f3&Mq1-_#ytyB$wShMaXy-X##Nn za;|}R*skRsnmLgL6tny821 z35~o;xTR&hkoyRH?w=2zm~z5WP;z@8b=+lYR17$UUI9;(1M4|-E(H{iERddA;O=c6 zX(C=Qzw%K^ma5z;YJ05lmxLP51|V#dZdii>#Ku#4=l)x__Hkv5py6*@I|4x{;r$Br z>f9?`OMm}Jqbk=A-w@KO$s)~xp$}lA^3(xbj8E>?cPyjCP3vhU0iO}Pg{)D>YV6lm z?ru)MouBH~6SfcKcG%K;zr6J`v!03EqY8)H4c~xToIYyAfig}HnGFO?!+IzwCx~ph zgM9dWV&m#)>aFUm7t9&r1Cxr>LU9!-mBM#wKVs%m+CKsB$m664R7!?|fZn9I?8^(9 z=Xj;6Ba?#4J#!0`Dr_RZ@)PUjivS%qsd!~Qp6T6Xv>-9EIajyq3Jh@l`i9aC!J~jX z{m5Zl*FCc&1&2AXKHC&-kr_^nnfkm%m?_d?a<{t}Sn0IsL^b8aOmw1WT-utGRY94c zJDO@EpK|62e=@Hix9gpQSz4!NGVBksHlsMEeqvgFlpTD4=IYw&C3wc+IG3+EN3W>t z9imG-TBu46vxCq!P}&Rjn=}qCjoSAZs9O>&5+ZBtBRGUv`}$ce4QONprupA<+TEn@ zvu1Sz;ys40p4PxV=-Jol%r*Q&IQ)UbcuEQ1SxmR2v;vX>YtrM$%91%@H0L)Zu~Qiy z`L4ZWp&ME+kvPw1TcC7R!;cATc>fk$+d;~Z~QV) zMT1W~p#yJ)omn%I=*fE2*6KW$d~^X+-#tOS|a zKJdl98|4h!$J${UdUu%qekn^%`7C>wSp9)}*`J(@>dsz7=|S40UgHefG4QZV;5TR1 z(Br&<+|SmZrw3Rqy#r-!J{|nfa2GXmFigkQ>Ws&aW&v|VW5LQKV6IQ#262&1meu}h zA58a)yp-qo{*vMHX1FAhUn%T&p&wx=ot;PHjmhNz2eyGC0_hnVl6(@He`FQ69pO7Nam9%`50nJ9CLrC zK1~e29H~I}@nlB0c)|wP*;;k$*lMM0G{yUmE+{vo_GHZC(xh&ux28D+rAn-edMvn#wYMCq4LaUXt8T137yXm z@+0;%E>AWOVn4fNq?zp@Rdu>5@BYf{FVl4;qWqTx>U0jz>Oh@~>>ic=KB&G7in`e0acI&dgE9e@_{?Kc3e06c@QtQb^CUk($$ zrqu9HsLnkB^))3Y72uDG#+>82bcLGJOe!O*vB>b09p6-~G{1q|6zA8vPBOpIDllF; zI+t~!xg#8sr}vV+s8w2^KD7}dYW`&ViiDm-ozQ!1_I8aQ;(n64zs#=2+GB@3-7-4p zz4EZ2M{sy-I^0JkX`x5v@qoAo`zH_Q_Py(m(=?NJmnQXER=TMX3p)iT8qw{!HgV?Q zlkxU&LQ~n2qNKS+xy~s`w9jEI++#f@7DG1!35UiTQ|k_#xYrXLw*`cTJl=VJ4F5QK z8|1oIn~vuG6TT1JIezrbg&0B>Pdlkvf-Z|%PQRc&P>V{`wfE6wk0qV8dpXc9)-q~S z1iBo9#PSq8hkP`wurAll`#Y7*wmK~CkfCQSoJ^T_G&Tnv7^^U>F~H(qelj znBxljDV&|w2P5TRC#eIyFxNSVGfT~Wvg6ZRi`Hi?ca|hWvR=F>g)XT(sRb@zG-1!? z;8#N<_Skf}+LR7M^tH)m?#d7bvAEUng(vLG>6LU)5dcdEUOLE+&o_YZPJr!| zS<-{zii9U6Ekob^sUapbBNb{nZ-%WJwX3>m)rjg~WW>d5Ia{^o#2)J>#x8iu z*{MyVia}Z78*b7%23P-1*vuc|A1O78-y&mH2;r%zL$?zhYxpwV@Iu~>{m+9nv;`x_ zUm5WSC>g1-ZVK(poyq;UYjr(&=ypx!!}Nh5=S2nb6Qo$+9_O2!KrhIoJCQ$I(iXmi z7^4r`Fd@NB2!9nhhWzFWMU9?^_$%`>_KO5Q>rJ{Qo$w~dGkU~EzeDxT_0&wam;3fh z1OpudXA`6+G=1RqUf`^*Rr(MCyE|k40PGW{x@?6pu=@8YCI775*YePWDx- z(Pbva4R9z0YxXty8fbLsC8>hVb~bu9-ebgJU4Ss0(jSKPDoa%-fR(NGj)KN~TxXM( zYiLG&OA&q!pdQ{7r>h5WaT~G&Q^`TrJK>6?#|+`vwu>qe^+BhyuD&tS%jdRQ5a$kbh+ekNiqK_oKOk?BBJ={Yt)$xTQ95!_%>G zbBr&BWu%azdmTKR(fnz04=u1Q-s~Z(aH3_xIU4~ku&CK!Btoe@3c#>OQv~-+$SF!& z9hxZTREmOW9b}Zi?lEL{a49V&JkOMvkLAU!G8DgSipHNj_Xtc>MqbjAA19oneuhlX z!AhH9K%)0?Mr%uo$<}dv2QK%6bACGR4klaj#=n<%qR|dvQk=g72P5x>UCrbpH57Xk z!BEDu(|rOWAJ)JK5u>LSt3Bj_RooWurAL;TOJc4;27MxpdBlar}?KZ!M3aYdk!idCTOWEM0q8g5MV=yf1QlCVCLOPVJkgy(1EP`ro$dS=ah&CHz1MK`^E*|$FFS5bwDo! zOKZU@Kh5&T=rWaa+HR&0*FOFdx3$LI-xx8JH2b&NOuV3#vS|ex-YYSr#H%J*+NO5o zk9@P|5Ix=Jl_nr$<{suWKavL_6nVW9p3f>UT2WC(;(~npt0nv@DjI4e2@Wf-!&WD= zZa>R-Z?~o)9_v}?W+hHrR%Pa0idH<0wM$!@-;{%m2R}4OJ#r;g&H&p5YnNob5%6T> z30W89h3xOlIuklfqCR0%^SNBqe#SlmL!EgEA}HY;6Pr=RRvaiB4a(HPtI2T9UdjU; z9Mvk`B+64u-b>QAj9^tiX7ui=iyvRet};+b$#hEz)QaB3FW*>MmhwlK*^S1T7*5p4 z&4Oc6)r>FJrK#{@iQ*dH*=5gKADi&eAUvt~6OTe#KivqcrxJ#2t$Fgd^b5f^o4ci< zSNeO9;$gUE{bResaMoJ2Ejb|q8*1%kzics0vMV!vcblU3II2ACc<`TXy}u9R`43G8 zzli*#aSBLGY)=pNHLBr+U@?UL0e*iZ?oFRMbSLe}px+s(emw7B6P9szy&$IEJnX(( zw_JAvyFU>%sk73ewNP!}fNe0$#sn9DrC|i#Pr_>9nHOe0K?~(1(s274!9>xeVWJpd z`MBa0p{G(!?k9}YMv2&acyCQ<9C}S8E)G zd8B3N9#umgB*V6$95E{-evR$S;Gd-_Xgr630)mIkBt8;X>6OZ7#%{Jt$cRgS-U~}4 z{PTF%$86tIzP5z*yzipS1K*N;was>R5ohiEQ*79AHN$#Lf0fv)yN>u!Rw)2G^70(~ z-Q4*iWx!S60y5b7pys?^n#NGLB{+)cGhYk!SjA}9DI4Z+4@d(l@QgEwLw+mg@$uX&%LM5H}l zex$k0mJ113N2!(l`zF&#H$%z3=Ud-rJNuMRE#oiPx4sif^H%aKZFOz=oSE7~Wi$F8 z734mKuCJOv4NZ>T*RUpS_ERvT)M=p)68?9ec?}*G3N~2-{J@`l84`rHDF1)|_?g(A z*w*`uyZ8&EKv&L9HWNqRwo|XB{>KsA(9n1VvL<5R!0s++cDxsi5Og4DXW84@>)k%Y ztGN!3H9r|um{~N>&E!8-1(1246+8wc%qPi1Msl`aeX{X1UsiNbf5E>e5zyaNcPk*a z`6vJ5_=Igme5Oa1Gi*-U+w}Pf;lvdi<$q22rrP`AI1BW(taT`6@lIj~juL+BYU|*z zD9(ScEYwOe>O_iP9Ak(!kA~rt*HN^hDjOcMyjmcRz9qJ~v7G5<_G2k3LOmvy$Z z42e{y`yW;`AEyN}kvu#RlT#b^l)h$&F2e}bj7*}AQLi*G6^83HVuvD(YETN=I?~i~GSkHFdcfCx=JQhh-^yAYtoA6# z!Q#45&B_FSR(hYaNFy6}=>$Z+<=%Ru(E zeJYh$Dcmc+_T0CkCbcTD3O}opNSJd;*0fHJhbwF)ZW5PA1jcSY_$naXTVq?$`R;4LyB7N zoffZSSx;L=t&D0U@I1E$HWHt|Gr?~9;j6>E$t~_bz`1-Zwd6p=-Ersx;WAvom;BF^ zLTb*&k&=;0?GL^4CTEz#XW!wiEE%c#KL#__tUbJ0)<58MGt6sU{=;Hz?uGK8B-KgQ zM#y&0$>lo)`{Ekjtl{G?7DbD`sEp|6xeE3F$02^(gyE0y^?;ub+$TFrZ6_Vkp=9+ zYw%N^KA{By6LPbGbr~grF^Lb$j;jhh{IH*V@9f)kON_I^yC~6vwykt*j(Y;6u)|T! znx|T`b9m-gDkBlr3OzX57g+~6o9>6yUo3ZbiJYO6DJk!wX2w(UqP;6nz&CfJs_}+eEoH^0=)&obDw~&g}h0b8*OGe ze7!4{gi6A;j)`q!vR0YPU6fHh+GTz(b5DDxd|6E97D4exzd*j&rZbd?>YSRb*OhWQ zc@Pm*cr%+_Zoil^KzYe|b@9luElf~l@h3Y489dx-5hw!YUEsNa{eg@H2XDh-BUz?P zr<5{erb@sDwzbbSS1bH?bT6QjN5#%N^z!3Emu_Z~=4f#*SZfXcoTKy!9PK}@^c_II z%s{*L4ih(6WF@|h&~@wDq8u>uda9cA9Rk52Op9^-+OBpGO{VBTeD12QI7~mzv^{NJ zR`9fIE7-OJ`IPWaVRz6?|GT4@r-`3#-)`D7pfr42vF!S-1aU$K4-e<2(+H(DR_}DxMv&RY{?g?Oefc&_9BgPV`JM+)>$_Q#I77#-2%aQbEFc!A+vq{>rRTY1x&n8BzucClt zvA-4%ClVChc$lp7k zQ&!$Lt46PpAB{CNE0Nc%&zR4i7xOTosHes~+1lQ%iCaK!xJLpV<@xe0gIM;nk^|Dv zM8B6&>HUz^gRbMdeH*4+^pAG}K-SbR2pMf&*V_i!qIxS~>8?kV!zIu>wM*yF!*Nt0 zLk!nuI_cAa4}X(yI+-*tr)T5qP1-HaUN#W8SfPK~QYslP zX4ic{q)XWxB4E#aO2E(U2+FB)J=H{%SR?5n!RP&XA>B64aX(X)IkL3)OrO_~j&&eJ zSZ^H|K(}wjwr)Oes$BM&9jM;V(6w9{(^*r82b|k%|25=vV@@i_~Q z;1zWiaSgbNW@3kX(Z_r)AE0_tL)A>$;WxUhhN%~w_?X728M7T~+G*C`WW*psSIYYL zw5v?^N?elQFf>NGZtX5jhNL%_S9w^%GS%N!q{W$Jg0k}k>b440_eH`eeBDRCfe8i4 zW|pRtr*#_1Ze8$XvzJuEIMwXOOK9lER)(a^viU!94VI< z0vU#|r0?4(UjqT+WMi$&sP}BX+HikVv&TNdn@-KM2W$&x1~8f}8k9~Q+i&T8w;6ie zhoq?H^m*b717~lMJye++!x}nATE~j4M-74PD??I6Z8I1H-jez{N?pHtU>#M%{>p1N zq0eIZ-l_h_ksAPEm4pPZsn^;Av#Ch?L4AMfp8L}e4BqUx@a=rLDVx+nWHwY(b+$}m zcJ#c~?MRz;74iqu)@%5etA=UBf!@6)0UhpzlnVZvlPBX)+*`n zmrh>%IIpiWWVY%A*e6dwoJ)^-+pD(pN43*?I4gpZ?BT=Am?Ot^pxNXq!vCXvWh18e zKMpAN<;}z#W1Szvg7S0UqYbfA+JC1S-*k`V>w3x*=*nC&SJ8Mz&GBJh4)_i_ujh7X z+Gyd{WgA@IFtBupS0VmlL?AdiU1!uJFdydh|qlf^(w* zVeTWRd&)ZK23zU?kn>I|dt76q@$6YeC3^?~AOz#dxD*Ue#bC5dc z!+SK;q84>+szb(`K741}2YLf=iqZ&$%vO<;8cYL?o)D~DX=e>aJk6%RdeeDbY{q?W zkM2&5na{$|F|*Y)2*QZPrNs}FuSYjSa1sds)=POSE*1i9f}akJ$%ef6fHs^)(-k|;BkpkU zE?`T7$aHgsX*aX8Y`$@Au+Kv6B`@R$UnIb8LyEe{3Td_6;yivXx^?~KOTm^uK_j(N zrW>rOIUg$Dx2O@Za~teOrS`_9Sl>4}w|xgi!(Ea!YK0EJVdg3dt{!Hy1COo(dM(^` zi~l|UqHBXiD1~s$`a9t#Bf6DKB?eff>gWZZ8J|b-9(#RzmbM|PlP}*yM-_SQRz)i8 z8PUlb*e&o+U6n1~4;!Q8pK6K{7fDf6=W|N~E=VrI8;6R-%hc=rO-yJqYY)IrMCXPo z?0wrhS@=~s{2KtVP!py0_>kl$eX^sx@|~^36c5Sl@JeOK zK6VSv+kEn0QT|~2kfXQeikVKpS<(4SnaU^w?IWL`Kmq29xA5kB7gbj!f3cc~r2_at^k9{ zXLUZYt919)jBWtn)1eurmk=(tevCL(E2a{VziQJaaYMz5fEO%s!~bGtR4N&y*}tE) z6w zC@yjtZ<=N@fC=&}zwUw^Y(x8?9wseAj^xPwub1nHc;s`-H~5sHEU{4F(APJX8W`um zrQ{Yxk~^KWSRS^`!(Af5kB9)}STbl9pZl2*1zQGEw1oV1x2JfwaNpJ77tmtl)!=kl zMW=2Fo&nSz?JC!0ii}oWT8Be8;uC^yK%N%*j%fOO@B=RDSy@fAaaxva?VSLrc?uce zqQj2E!(P{pYyy^BfFY_xw_^NDN5_5p^Vj>M@{^X}EqtZ?DUIo4QiQaKDL`2|zIqtz zb{NlATeu!sBi~jQ8gGO5pDC8{5xh8kJOFoP_+FHgk`s0-;zx*+G95CBfT*QSow8;O zKi*w;E;X+(7C#vcc{&i;{fyBYwAt}x4nIK?R=(gO_|A8M+Iqb?1iVgeY9k_&!o7az z%zDN)xD}edv8?*eM@qzR%;#TrW$IxSW-hP2ma4;g7z*zZw}+@sbu)e*Jui37_0CP! zALTuZ9nje2E768;wiUmk2bcDzWOqop`_WU5&REV9%@>$2k0u&YpajKw4f8t&VhYb! zhwp)_fPdn9D1#O7h~Arf8GLi7u>4+TLy>+}v4(R#F~pgZODqG3OPT=IZDm|nwI#Pa z)W^#4(oZ|>yVX^6JM?<&qh7&#{)!=@2&d%^%pOp+MQa`W$I%NHR)+JleYX79XU$?= zjl7lL7X>pU?+X|=!chMFz790}WJ{)EI;_{Pd)zKi?>@$zCR4xGj4f@?yD?psvAx#j~F`Rbiy$)^jVjVOfE7n!+P0n^{A+8&E4cI4o@ zkvg;|73D|w!Ae7xy?2BOI-RGg;pp0 z3ghSVe;l2AIFtYX$8}UGDmkAjq8xLYa!hhg3UfY`GqcV4%sQdu5JCvac{6jGVOYrd zRE{xo-XzU2Y;E@W-QVB;yRQ4b?(5$Be!riu=kxI_;(H0To)|1Ok{(+=;lFTEvkX=7r8EShynUNB`X8GB_0N*rBK(R$&HMhAg|Mv16y^5_ zX*4>Tn>H8#66=VS3rmitK$O>~udeK37T$@)&uSMEJYE~sfhcrC%l@h@-tg0dgFY*b z;8{E$nH3%6oT<4SJw-PBIrweuKel^2I)wo*ma zu_Bo|=)y@W+RUTr)RX^iBn8lHHWrd%Mb@X7LB#3k5QcBG(QZ0iN`LH2^45OT)Ge=)Sx)8VzQvP%H#e|v zJ72C$=qy$PxguKsQutHr+y#sLcB?12RnaHM3XdtqEyZFhL)2dH!)L?{X?7({1Kf5p zmiZ+n(zZw;sPZ>`Ecj8;M{rMI#hzC7qqrl7gQo4g z=v8XY>E&Kg$J*DZ#t9=>@{C*yxILc`#+5X|tTjqW00rtp!=Y((tUdD^&H z^ET;d?I6SC@JD}0Kv*m8{bj{NV`-swwR7~5y~Wh$u@`80UE8`Vqcqbhc^EtK=}T@X zx#zBqw43N^E)Y4rz|;Y(Fgm=DFtx%``PtQ^yQhwm+%$9~Pa)#s9p9J!ZyHX~^%H1*4rm9*-uOHxpL zyGuR}D)5VK-MRZtQ-@@#x_Pcy@lPGE7*hk<@QzYPtT-*>Td3&ev4v3L-BVo#hS%?W ziRt_N*9}KQ{dN(v>qW(Wcj4TZgoLJdHNsQUAT?b9_`%jC?`{DJFI8) zm9|Lj_Cf9ccs%b+VzS{;x9d}WD-WKQ7I+skr`RE)B~w95-dX8Hob%jff5E(4Ww1)2I`!kHU?G3wkvoc)pubXbVT0BYg>N}O7j8f1x}+O9?>>xv zak*O{+2NXi;poCC-ChCf?m(UG$8rjP5RGbY+!g=iF3UK)MT7%A!k6FQ(>(u=GxP6D zrpz`jRmW#tTNQ%1s3M})8R~P2ytc)$pt5ZM`dZoW@+|Pkj>v4-=op4E(>Zmew|De% zc=bHwV0>%yrR@#MWtaN$fw$P86u_@-kGu$-xmu|T9krox?a0^y=g#NRC=EtjGM{S) zFWBbfCy%>Z89+?hmgzj*nr#^n{)g~wL*kR#lZ?>~7cipZMlA2I_Nzw)@RFwSztb%Y z3*Vde z0&S#@X2}N|bn}>SY?f)X)H0!u*^{txfP;0x-@sRhN5r+%FwA`!bK@QT>7?Qe%eFlj z=Sst%)JLs1Te(M<^A5tct4l^@TjaCVcI1h+OCg%)x0|Hq+aDh_v`UqSOD*51;sx#4 z6_*d7L>Cm`(5^}hW)M5ZM#NeS;A} za!V~~S$FvZ2l3uI;j3QhcQ6&29?M(_?b5Wcr7f=61t;%=#u`~m`x!GvbJ_c638T$P z$eFKOv7s(8gi)Ju z`0-_sc*t7$fci_w>v--6v5$6*^+4-yt0R}?(Qn{g^l9h)zK_!2IyGk+0&nqZ&ss{< z!pp?j_70#V@42NFq63SPWbrI(eR^1Q+v%X*$jz=9i^Rm*j<pr`HRhh zu|bQbT3aId<*jqtHmBaX@0xiUGaSO>?}FspVr%PC<*e6#)GzSgp|ocmrL#EK2|TT8 z2oTPL=O5}!X0@DaOT4O|B72xd>Mxm}Dufxnj&TE`iU>#~ktia!GBbUG{A?l=GZJ*y zfkzv*w!e0KXa32{{+rKGk16R6zoNONs2-RFy)}^_8?)pFM5$4AN$7xZ@ctK_S^T$Q z$wzImm12W?E&^&|PVLyk#!7}DP1@_}yx8~Eg*a$qtP4pjdSB=*Q>!8aXtp&usV2yo zpj!6;SpzB*QgILL{={ZmF#oF5A6e_fRhRu%Kq#fjizar$lwlv9PIn_==0T%N4EMs@ zT06{*UtB+R4qooCC$)>~l?c%`i_%OUjnS(bmr^f#eb#!ui4Z&_(A>pN%^9C7PiSzD zyNKMZPxPc0hVB~88I7=OUigCNO3*p;SK;-KIR{#pIc_|5jIjo|=%W8z_*|o9-WWi& zlunD04R_S-wF4Jx4U+v8#nlg*S>AEd2 zHd3m}V*J_nwpWLA4Pg8Fh`Xb|x7goD_N^#T)J0nQ7Fc#iTgj)in656fP zufD_r1G+jyd@N76wOBo{oK0SXloOt*cK2rG&4&i0)P2cFOM2+EkJkb^2q5IE0%-P#?xhwuwnCtL8;A(fFtuHc0XR}%7-YyQyFvP6$ zI<+t18W_=sjTn)XUqjh}*?v5;t5r`CmmJyjW6XBy4{X2hE5xfKfBGDtLqeVbRz$5& zeuEP9C)d2cYFOSqQ9b}r2OiZW=P3o$NglmoLZ9uNII!HVnj$=f46B(rXiPe7sD#<} zcu2jp3oY2+W2a)-55xdbVo7V;Ap)Ryp5*)kolG>XJzrgg2o(xF!^WI@l?WX07t?`7 z@zwTWw=?@>aZ7RoYO3|cyjFWCsFT<)@brw+$K|H2SxfzAIDE4q=F(@U zb_aT(QM!OfpwLZJ#vg4;C4F|bhg&otqYAp`Vg2`|D z6Tf&e`kRjCr$Sw+_*K7~y*dM5+DQ@T(*S+e?SklhYk`d@+T5C>QZ^5_)hWF>_i?2{ zs}hD&hUpWPmt5fe{nS^zk1{VG&#%Y+B|gC!)J6|Cs4I(Ve+HN-nxmP^-ndM9sM>Ja z?u%F7EpvOJD<(G6=LfNQHNsDn=!vD-!M;ShJgz3TZ>f$}&*?xGbroJXQbuL26U-Nu`g>0ZPEDoIG1jyF(=G7$8pBu))qY%l?p=3#* zYbG^g_r-b=_(9m!T>W@{X8vF;*MJa0>c#ZuN{cySZ>w>0PUEIE5qF}Di+@<@-#1@w z$@R=k#9P7}PQ|9s!!H^kDZ@{V)nsnF_ z!8K_*W=-=A`v^X};P#m{9_Ksv>tr2pM#Rv~E=8&G@hglTTb7UIA%3QP$L#a@lcNu# z#_%mXDTrmMcak*3_L|icn%9~keEvsFPP*Y9SO3Mw-vTJ==|R22Bar3)*k%g9*}FWC zmGI3iYgR#~M`TqV#H?SZ2gHA6rwN+JaxO#G&56p^neAM|rL(2q1`#1w9=;P!p}pbz z>Rod`izDOTbY3hl<*P5qUN(a3{BSeHE9sh0ruo3xO|>8wy{xHn zL#|uq)dgNdlm_4F?#|o4+6@&L;v2JJ39+{g-RmPFW6_NZQ9WRBg=;xq-G4PbD&N6G z9iim-SUe(s1f5Wh*x?W9n6!5vyvf&2cR#@knM;kYyJ*ukzN#&pk5#tAB*=O=)m3Ey zuazZN_Kk1AF8*Xd(y?h`C}e@)>shd|1jB+zhrEqt*RDMN7#0!m$LdXQQuStFWU5Kk z!^)Pwzop9Fjo$Zf_}$B4@gWPjmXGLAqpqZD!5;sJxFsV`)F`63-u(LT!GCOOS$4!v zA((P`aYZ6MHVn9A5ZSfBZX;FCMGeuR%{+mk8T5XO^sFp(vTq2x2&Dh59u{8ZHpWiG zjBS4Yv~SJx*IY(ta{)G`BfXSOSt(+LP&{|dxurx>O>aE9V_OLaK$<;MYVVN*efo5m zZ0K`=DA%I&rA+~GIG*2Y?qeEQ_v<T>8xgk(%?s*Z+^3*iZf2140wa=m!aM}*j?OGj zAPEp$>MdNj5H5N{!0l7y-?9fgpwH7{pb2`Wn%IY@`A@lr}8I9MucsHxE>!u?Q)FR<2KpUx*AFkWE9&8c4WfJsSmw}tRd~5UxP#zbmmmr z^$Oh%`H6}1bnF>!S|td(pZk%MAvbP#PN3b&1MHq?ww@lQOoi$8@>ft=mFvEMdOUr= zyn3S4-eY~5UdQtz%BuXU^1@{MJPble)6c^=|IU0oN*#{N$>a-)?qL1u@sAMROMI{7 zi4TW~6o6cA9H2lp{+1mBJN>8^?UNw^Y|xPbf=oq-WAadpE|1jDA81j97C_IYTF>B5 z1l-Z|`UwuLXFQnZ?n`c!-`5HFh+|s~7|XDcGwJ@glzwN%)gvrKZnyESROJQgum%vS zan0j#PjkxGW!J z6|u&$cE#atoCDe(mZB8TehE=prR0S64`nlPn6<^g2tI=GnQZ7=_mC0gQZM7sBGVAz z9+CmC(J<$MHvG&|*>iW1yldDumiS(usc8E zySn%F5ZUq?A}&)e-IoL25HhlTu2m=fEjQtxWxx7SQ5ei=KpR?_+NyQr>uz<=NeE&M z_Q;ueL&Uo+g>P+*wLd!|R9W0%s!w0+R%-iUR!96`C;mXGDPnrF+GH^d*!nVb{w5oP zWJiXRhr2M9>|^cGz~1lWFI)?o_5T@9m&E)fmV=8SdOZUOI?S?>_EDjsKp)k&Q!kx zN}JTdGa6SAFsFG`DvCaDWBm`M&#fy>e=9XpcMsYm6EF8_f{L-wX@1>SYz;43j+!L1 zoB5`#iJsc&{9T~5b7K<&bkg!!qc3Bak#wTA>+|ypPF)2WQ-yyZ%P55lOrsX=esX_> zE)SBvvFB(s;{2qU-S1X^FV9T)%7N}!u$JU+Gmw^Xb;(;oc*}Ey@~d0PU(y1Swz({K z4>4LtX-pyb3g%6!775$kc98jYF<(4=cr|UXJX?M%tyb(F+rLRGltGzbbZSw)x@yt8 zaw?zYpLJfytF`Eq(dHaGJ!CwiSj0ffXJ@D&Y)jiSWEPo>ixasWzF}P6_Y9J%m5H7V z-SS`%4cO+?&riBEC>!?8@m*3ICbXNkMJGXns5j&;MGAaLnetw{B;Clp=9DyZ*Dr0| zF38bj?3tTavV-sDVB5?~;e8 zeN?+s*ij(11BuplIt}NV{jF58PVNo~fZt5xyaF=4^|)9QFs0rdj{U$i`?1_kgD;<{ z7IU5RnSKmg3f+7$;V#N0)fW8<;n#=r`akHZBY{;2t8^%@Eq^M965R!|%X3kCcxjZ4_yaXN8`5?hbyJ)E$p8^`zgEgW1F z|6}_xGZKxp7DiQgcxXJ|Sa9bfMc7Zi>dR4gWMpgI`awY%M4to27VuVY2Bt za`SZj2RCb_+!iwzx5d0sBEGvtzEUa;IWOH;x@^mPCv;Pb>6g+&}hi7$>lq;v-U@9Nlsbc=WmSU?%hkK-wytLsE^6Iub64a zpC!_F7hN%;l#2^WRalqp)Aw$brzN)N<~F6AO}Lg`WcJ?A1Z_SE)c zv~g1!V&{^ooPiKscI@n>tW%ej($BqY>gdJz*>JddNxrIZbP$U3L6>{b#dpI_ow7pW zFp*T&nf@Z5|JW{GtKBh?t1b+8kaeE6&ApXrVHCuD zp;W*&-I%?oZ^K28hFGdjW9X0^!{5{5KwhL_kgrB{K*H-^>+W}bm&%EJ&bz*ow~)b_cxDlnXv9_8ktZZya#YAQcV1^P*U6n$6lS ztoj*=d2QSAWz;_}Y;*%^JcesQXF7%72LTW-R%-!{CPl>bpl2tvR1}8YsN}I7L5{=W zw@)O6X+g4RrGWlfY(D$Mr?vkTo6b>_saW7qW}D1ENEx^@RKQSrw@I zGHJRBr9lwsV(+{AAKQja7T}Dn<9Zb<#^jjVR6(DX(V)J0|0t)~yZ^2{`j&*h(B1Xf z#1L0XGtg!BDFDGa)nQd`5LYs8`k*C3>{PToZ5YYCgPl^rJJtPam(8?3I8(%>@~Y?( z_xH7G_37{SVsWtcW2|A;)z+QUl|1Of6#KJ(REz_sInHgnvmJYTMmVLzMin4dbZBay zEKk+cTQ;*^Fvm{qV=l;Cke^z1-<=IC`u0((Vnicl9|5e9iaQ=|gy~j~XRy@rFQZav zF?^dg{GFfuR=o=DQk{n(&AzE$tt=w_oR7-1FKvh_(Zm)B7sG}0Tc#SO#$D^ftF91c zJe`eabDq7zYsWd1LSum&;;9eO0ddB8t%C8Njt2(9S@DWRF`ZMQz0 zR#TV%1cfyYQ&fU#=lz3{UPi3ZDlN_PZNb{yWT?Dn8ebHPI^h8}94>52nHdHEo1C%N zH$+c3Y;asKZaC7h-(4omE^LVFOCFrXn;1`B!k8)j5d5;eGb(~8EqKs}>MeBly%yAT?(vA_WsIebQEw)FEl`FLBh zD!<(G!^)g`A2D@}BU5vc6O=Z6tt~ksMSiolXt=D5@7pkhb=l?T^w&$j6-3BmcA4Oi zd77d4R^$t3o^3VTrtPh7H)rR`pCNC~n@NMFM*d^dO?eIq=-Y7aV(2^B1Elwb*UYQg zyoZ9-@5&7_uvITsJcDo482Xz_>}$y=u+C1GuD9Pl`ds~G@-Oj%#WX`@ljuPx}`#kCX$Y%#I!;O;ugnB{Zr^y~y^ZwuF-cdd0O18fsZ% z_64g85eRG`zF>zq^mpXUx=Rp|H5z;6J9Uh|RimgEg7Yo0t|dJBkL|WpSbLD}QFgRc zh~&-^l~XNRS)Et{TX>Qb;G(_8Q>PPCx(qVPY)8?>0J~0?5yVC$grk&o3MlLgTN$tR zxpwqXr)gMUY9*)1uV_5SvV63k4&Ew=bSm=)(ZmEn0|AjRAbKvWZ^{XC?31+kd z%|b?*(Y526sumds@20D(dG(ManI7#!IsEo;?00)spZ4hlue_x;Ngp1Z%u$vqy`HtH zqd8F*JE(mzWyuY}G}qu)DAjO)lEmfLs_a|)lc*07 zB!jOfU0)#{Z{eTlY?5n(d_&7eG?zjOKYD&dhU{EMKhi`#I?xUQPJlJO>!qyTmapMZ zO3HG0TCVk-)Jpafm3=FkHeCyKTg=M`Ys=HGsL=+6m!hBMI-}uhrX|E-a#un4v52pO zF|qOgYesmP6)m;H-h-KefPVyYoDGpVY>KzS86Q_Z8NDyn7z9Qv7P5{_Y6~(sey9wG zPB~m~9htcI>nPS)DIjeOzunaPC_y$%^ISs&a^69di(wqwr*89SkHN7qRUpvVlHwf; zNyxfK^%r8xF=g!aGQ>;67yhXI&xo_lN9Eg&9R*KY9ECJzfeXSFM0q{;#5nnGgbNwo z)5v8^A5duUD(3y8T&7;RcPL@jK5oLnVqxek#jW7%)e{9dnCIGOelK9fzA{d4mnAQX zfaWLpH=9~*OFS&rirHEBDERGg)cE0iIj{HypD5J*g+DLnZ~m`e43-REiZ4RQ0Y8qw!1xETP z1L2C`@83Z^-dRg2&={mXIT2j|n_RuD6Vb;JccO;lMRyc}y3WvoAb52=wH%DLNewM! z$lvHI7p^`sEb~`R$*DqFCm~5f<7F!x%F3*>sTKNVtf7C}|FN}BJu4^eDJ^>Gysut( zGOf+cnw=HJE*VTzMeB>^0;M?|CwtUz8SI;l$5`8&O6_0jbe=A}R$u7Sc^L`IS&s5- z1gMPXcGTuy`*GB)U_?4FnXy3ICb0X_aVwk!mV8_XN&|5@JnWmiSHVC8?r5b`)9$`W zJ=r8Z)>PAO-c1RlnNh9j=dNGy5ubqGGr0d;qktJ%>j_KN!z zxU+xjHe`Ri1NSasaYG;}k@DdD0#!H^GfJ2t9=Oro?Vt``j>leSy42Kg(JXeY>dGG(&6q5mTc{3|*PtYcjY4&K*HpQH@OSD70 zjqxrs8ogdGzd+;R(H#Hf8FPiGE|!CguY|1W;V2&PT(rt-1m{5V$HGHILdY}m@vN?A zSO-Y>3df%GxWGA-Rq|D54iJS!RRcKkvCst)9T~|{B>ZvqbK?|zb3B7)zKxYPRk#3f z3@zQdL`m7;D zV>#870d@}0bva2ZHiOC-w?cv)es)zoZ|)s>oMI>*_UO|zjx|cyw&LOsM=XQap0jS2 zq9FE&q3Mg&y)94GQPm@O!U2RrXB(kQci=eCJsNV-35m_UJ;j~=-f)$qXpOzwx4Vf2fGVT zvXsLWI_598*WjSO;H-5Ab8h2ndnRWF)sFe|FGY;Tp7PlDsod@Ng_>XD;q;7YUVSCH zi(&zMfPpgag?>l1!Cn$Z_~Yh$_AY$VEoU+Xf>Uj@EpJbeKVV9s13u7h=YYJuZ zepU>qnXF9(DGaB!E_AoNU)}eO?xz?ngd_0A1C=aZn2Zp~NyOOJ*f`byKemI)K;#Um z*$1pSir>XBCaTcb+Cy(yw`aERhmezb%M{zc0;ZrTYdT_9C(fH5mnY=lJB3IT_wfr$ zm~H)!tp!`E@b;3WZ9N&o55w(93@TC6KH?GB^{Kj$H+nuw`eF+qaz~Rr>M=4dJvJvS zr>mtrJ)FqeaNYIXj!Epv_#W@WXkzFVYyB?<`8rZeMj`Ui+A4v`%Wd7H!>!`rVVnIY zu+E{*z^?ebF_h3XjftddFhVzte&qgM_B79?KuJ+g5!#viS}j5}{^jp+yP>)pfYFpn z#nv;0_h@6jv)HXSd`FVdfhrL4=-1aj&B$aGIsb}F1s+bw0elNkFTrZ4=f-jz?K=^o z$SzOW1*!*c)b?G+WMILXy$pOljwN;!ndsLW(xL{>5F#Y_{1t85ubkEZPp=vuWBha> zKY?oL9z*zLIN zk(9-|p^pcU;^!`2H2$5l-t+rkozZB1yCG?pi8`D_{M+9JtmrHKh58As%K`&?tWgq! zkaa7qGHJ_`o<|FZ5>nB&jY)ILH|Gdc7_kA7to^SS+71Q->uFoUUNx`x8}z~bCa&h} z%}v(DyE@6yPZ$VkQnWobMG9vN=36t*tkd;825=ttF}0f|kauC{fs}*( zelo3R%VZKT5>V7~N4a6v*=yjhJ&)9J^VG*gRPQ-DY#4_`#Wrb~mx6Qkyn>P1#%f## z0zp85)~~cw%iVs^`(HC<$>NN>TGssh5q%V^ASU}vKwvuTF!Jyko?%&%mTNYytgOVW zTA0`BcV4b4&*3TCW#pRYQ66use+n7>jH3K8~sqxL+HXG<}ZpFzmK78r1WmAd} z>J#AEqy|X#aN!OMw-tI*_7@jwqB!8^=U#xOnhS&U8!+eCRz+8{v?n(YliZtTaFC$p zoKRK_YEO9Gfk%A*Pcl&9tM^@yhLVO6C4cPtlcL^72wRr;*xq!iMg7MnX5coSW<~vT zf9^J5<%NfxpZ}C*e+l<#;6#lTe2Jb-#Hf-*$HKm+o5uO1;R4Z26PwQmTTe&>Rrp5S zP#1+U*z1`4pviXC`$;2i2X?S!0kwvr_oyshIwDheS}J$;O0I`X-VnWnCAQ_hPbo{j z-?uU}zqKcg5yBsjdLrx!DN~XplRva1fd3U>#i7JE)4&!rIBT*y32{sVzB5(=Hn5 zzvSFn9`gI_e`ozjCTH8_+c4Kk=&PgVrFU7aWA33YdFQ{s_Ty3$uGBKb_)T-~a36f9 zg>2(`QkSTf_9Ubsxw~#Mnp$;q=|dn_4f~cn#JdN6Ura&ohx_(#``(suzwv4NDcBb2D{wqnZIm(*koN6&qJIpBA*bHf9H|hf*bfi7wxWNhwpK$1lB)6e%zD z2(Nb-WAZJ@~wo_TZ49O!J@OmtxqtogyF?vHe_FVP*e`^^?%V5)RCqw4x zp|ivYtg%o1#tC;WMR~ZvBUcx~V^{oyc z{TO(G#H3@rB0fpOu&Z@E|QrSk^FNlU<4tZWhx+O z)G>>ns3zeZGRFN6N<8<_n%~TR|Hmfl;DDH4DLSY+vbbyQ;hpoUKTEdC##{JU$|vUB zU0fmaut3deF0CM6y7%X-sY~6a zjT8ECdNZExFAy2fqi-tw4hT-mFJx@VkLG<^;a44`Wh@^iFu5?Y>XU!1;Ww(X6>kmW zjVd$Ga4^wX{D09a0{!-9$dwkCVj16Oo4!wxGFM#`-9AJ(1YE!W1oT{alpvPxP@8_{ z@62V0cS)Y_mrZz%p#`YW{+;2pY^zWC(U&Rx=6ch3?A+j?(>-}LsR6?~qYpQ$Fv8LI zezc0gh5t2vZuA~2ZBgLk95a1i>`ia~<@V|6sbS%Ic-HKPxhoOXXi~1aBf`s5@qXh5 zU<``g3ethyVfs#lmU=zzL;mifc${zLTn(WB(C}!h?X5%%uZWmEuJygLa`%;cU`R_of4?sP52m-QhaZaL2kH;=|vYcmdsG28z=v#E2xE=wo=A zEgaf0b-VcUR=Ur>*AR($D+1n@%`8oR68t3pxv2W2&y`-da1^gvC z)8b`5bw(M^N}cIFZ$L;HIGAI9U-h2S=G<&g?EqS^7;qqyKOFm+(mL_DXV<94q^|co z6c@Ryzuxrz?5LI&vU_BMM<>KuRb!Q`SyL=G{p#^=%Z4;!aqE*!CnDLhMQe?X9F=yD zJ7Ux;oMKj$h;J<4-nzqnfjU*>@h)giA(KOGco&m3zDYl`sooQT{9=TT-g{r>t3xBMMSY z@L`7EP*i5S=g*Ew(*h%r$jC{`$l)H?EhBYFvE5u^rBt#=Et~TjNnCBHYGdQ8L?T-y zL@ir#iFubnkcm9;%5boV1WOBr!8bD?r@+`BNpqk+e7yS7Ab7s=Z4 zzsGj4VTMhUTM5pL_2G|B?}>e??Mlq5GU9q)n>9;(+1P(VK}=Z$J?cDZ^|0P(g&a38 zUJvmL@ze?!FZEI?7RoA1w;m6r?q$bQuaifg6om6|uC~VQ?8z?^ZOF2GKN%CDvOkFZ zd+^Y}UnBU)3#h(wdxI*sc;0z*oaeFuv^Aqwys+nm2}rgJ_MT*VEiSsrO1fSl8*q%= z6+J=(7y?h2{Ii?^07e+xBGG`Ye-bJQS zEg{)&tGmc^QnS3g3zu8o^2r>UYbJpavLNh@&b~^H3k=I!Yfqp0ha+PpX=zKNC+GA; zn-LJ#y=&gNA&7ZDfu{nxC#p|J7My~f>2Fimm2|94UV}tr?n6(Hbr)Tvo8)C))(H7Y zkkT{=|LyNfBFs$YgvkafB@^9toy~d!M&@Ns>m)mK=6-uPJDFG9zbawU30M5cD{*Y^ z6x-AEJDS!9uPW^}vZz`OgKD$dAv0I$neCfAZ77&=@A9L0PsK`Orjq&h`pN~};7UsG zT0|nz+O|s^ab`6L92~+1=8D?7Jty3g1X0W8!nCliur#6*M9@*5 zAm8uKyZa14G%XNJCbzfVs$lqRyHxX6ZO#(<=ka2pKbo8Mi1W4icW(?eN-HIRR_l6x zbk;Blt(i|U9o#?>nxfK)#D+1=!p=g__-;M#zesRp*)BN8+IqG(NIJoK&i{_)+Let6 z{nnH&iW9N%i1hXRvBcqq`S>wwUJ-49sza0Z5WM2ixFIF5IOS6++G2aN@CeX^p^Pa{ zdMtE~>tm8yn-4vq|LuL0j8~9)ChYFjOJHV>y9Z-LCm~eCwst*j^!Pi+ytMuZc_Xum zDuUz|sqyS;WN^ibOM`PvX~wF)j`A&fs=mM##-NM3jw(;y;OGE)cctu%iqGOtdKx(+ zY;d>MyhTg>3FKHL>A|2Vb>8AxtOwWk;5%z~w;mftYc?7`1H&$5Ns{oIY1qoffCeQ) zZkT&E2fzg}A2L|7tV0=*!_@nKgoikO3fZ`K$x+esF;MnMnO%^QdagWPYA8D>MI!DZ zxU0!4F9s&xUh|$ZxE$d(%)D@Db)F5}b|iCm$wBq;NJVO#CnLF_Br>Ed^J~^JD92uD zLA>HE?%DL6wO7Ng;qb2qu{=#p={*`6r!vAe<=lAtvo-Qo*=|W}N*v1eG+@#8a$Lsg zzv)c8hP%?BCLvI@$96UH)arCDDfVaK1*(_#c=zn}DnG=eB!*%4waX zYi+4fUCpuU$rDYp{)YVGi3yzq!B*v+%PWG~wa<`Pe5QMSj{M0$?uO%5Ko6dHl3VWV zPIh8L>akzzmA>la{M4+{e6J>>*e74vjFZyCS5&nRy1lVVK&?!I!SW; zSeT)?zmXJL-MM>o+^bsUU3*{!k(nIw! z50I!mmHjYNt}#gsx$x=warBY6;TrB3Qz z2M1w9JZw`j&BD9j^@XLM--Z}O%4mO6vHT8@*Fe)vAJPWcu|u)ed(W%b(tzTG(iU~?Z?WYst)Ebng#)|oc@V126o z*y}1CjoCzIdh~zoaOOf=rP-U7Gm!7sHVq{7*+SSclEshZ_RZd)1Tmw6--xll?p$+7 z;x>7vA7|mc9RC2G(^{7owD*Z;aZPjThxOf3$wQS^4fw$ppO5t~G(}>&`d7&X@=_Py zE)=+~)D$*&t) z(no#FH{(3!Y!<|?w;Hm}T@#)LZq2!5-nFGm)`shHCz-g`qo?pCYjGbF2-Kf{-3$g$ zV#F2z0UU15yrSfha1bzgT%~aD9y~s*CM%&eB9?LHycl)^&*JsYwNiaZEM3DugW> z=)Nv_kQXRccD+moKMrI!@8KkNlPgBI}g;g&hX`A6`xtO{Hm z4eCx?xkHCgyZihrfU}bht<1~wPPtkd-8b3#Yjj{?zPB86g|?l2(dZqZU}?%>vzxB& zv#TH%Le20tThZ@mm$~+e@&@U85s3@m2x?bXFKwkXxD*x2B{K@&%oa4)Gb}vY(?DP9 zYvsSjME%Px@>7L$&NzUDgOmDxS%rx1Z;EZ3op)f3 zWw-)(f=_mK?$UGWZot4u^VM_6T7>+4W{2IO2kttR(Hh`l04URPGd2ewo08N%?%MKz z-^SDVh76<%I6?A;&dbdk`cYDDUlLn?{3|Z$S6Z*B`cXC1WbN6d9J!dXA2h^x@DX6w zFy-)}G0BGIJ#aZDi6|1ZTWy)KPAoMOozV^@Ww8#2(6mH4a7+o7#992Pa$5}^S)hC2 z$I+3PKU=PcHaKMg?FSxa=;Rp@Bh0O2=cNw{qNXv6#LVaG)8D6&tkLlJWU6@%9cfryjm|40mgtQ1+Y>^;c?LXOd0L5>(e7nmNJI}~sF z?m}T<$a6eu^*=VE4(lAcnANAl%^s(qsTC2nbyvm{VkAW}w(J)jVGaT9{*MIAnS8l$r@vV`waOs@OhSjhV; zX+|SK>#6p1_)0I6Cz9CJu8H3+@4}pQp%Ja>12bCB^95Mw@y{4La(>!B7=e7r7tA=c zn2@%PYp#w7fR~qkx_RAh6Z5^3B>jfi~%VO?Sl|%mv9Le>i(zI`%2RY zUoffQes;}GAT^`#wn(o??^qSn4)`4om{9>D#qb@pC&_=dq#fF4S4UQ$mL7fGkfB|r8WaL;{!x}frN->02x zzU;$Gja01eL3Z*NKQ6++9&tQ0f@fdqPY@$KT<>6N`<3%AIl25vWR;Dz%|q>Rh@_HU z7#bU>ax&cF)4r{@{51cTpUt&X-nS{RFEi$81MLoBGU zy(x9;2mUz?%1}TR;$m1u^utiiIO(I`5_y4S1peNcfgwBxV!_HXlsVYk?$V~u7IW^5 zGibBuLqAZo$AO5?R2pHptq)U@KTdTA{$(cE{wWJgOs$@A+5-^ar^&A(U~|h{r_=XUzH;HO0HaeBjgMr=e~V?U6te* zF)Vk?%#oX|5^^qt+?C{<<=BQ{xpU_n=00=HMwm9fzt8Va*xv8Y`}KOiUytYW34FS_ z1b>Ie?6xA{Y*ZZeWE$Of9GFj1G}9b7YVl5n1T3I~LB-2;rfr0BBR{R9dpS6H^ zW9Pgt#XP&2K5#V|~_1j|ubcHfHc(26zS(f&)}5R&77-?tmrYIic*o zK(|o~fEo!G*Y+RVB#>%ys@h2Z(f~Y)Wj#FniKp&6z=iKVX|))7xD1l53S3BOh+syZ zQpDvL@rz;-);OBLyWYgoIr}F4;2Yni3RF!HSzp)rH&HZ$!YT7sl2DzwfVaNFh|fW@ zCE4Oi2U);*T3zO@`&)4?-_;kOP}`q~F6GyLp|%TyW$uf)B6`xZ@M)=66IV@^d*R>T zu#p^GT5^R`O70Wn?1`{RTIu3VoBa9gV@Kwh)45D&HK_yfCbK%!ykkx^XWb@8%26?- z=f>v-rS-FyT%)6NR*`zhX*kmzIW~8GOp;br`*HrseC1=kEl{=}2Gq;B!1g!Ne?B!O zg9@S<>_#^RSJNLX1$yIykM`_(pJolY^!;^Z=ewvYo2C;<$@o5Kp`?I2LV_Z{h{5Ok z&U>1fBHv?ExnVW=(ZPtAMi_7)8WAjB2}BET9c9dC`8)<%zMkkXC} z;6Uhx;j0;-vInre{^{WF<5|0EM&}~`51J^pz|aZMD@p|UhesT1%--Q_fIZSBC-%?Y zs@Mqp@yfdr0(#&%)lmHqJUAWlUWp))3sd=Qrva=u@$?w0swg%xJ|p#P*>Rg9$jD{D zdXUn{*+MSlpNw)iAA}CB)Xu0&yo#^(FqKr${KKEZQF#9si9am)(~N>|-Tz~} zcGCI;i68i}^OGUVB9SP%M?=xitW$;21FjErC&=uL@5B~|KUd9#PI+HChT7k*&@r3* zJtxpZYe@F8?6h7ng+@4>fB-KSGa7QM--E8&mdTiJnXukEnL+2$cCCXD4B7wK+H?lQ z7Yg}0MW0ntiV3M9yrTvFg_)%5wucss#V^~YP25Wp9`N!v)egQ6d}-_wLpZB(kb7Y= zy$*?Z8EKul@16>d)=ivQP`Q5jgbnMR$#JP=H?>K;8T=m$SYGmm~#1!^1jg;IX`^1~X_jz31k>}yem5GaDO>58wUyall4qrcG&UP(q zQAv>DouSsd(PtiTWm~sfg;)eP9}V-Kjux`*=&~v!&+dgKbFtSY zt#CI`dX{w>s>n-)+Z@g`j>88edM0K`M1n80;t2Y)(QG&Ze#c~)H@|2NPOLFMd(E#_?le6K}Y7_j3GrYCzxp(zqH-nMWk(8u?0l!A*pvOdvIKR=t*=Z;Ub`%a|q+T z-&YOk_58<5iO0D|j5v{6CY`!u{Te*AcUVAlejF@^*9SXR6uO|StO&V&bM{ed&N$mO zL|erat8ZUpLvUp=QAtm0*LG)DVDMBVn;g*2QcRxw^_yI>=2!c(@Z9Nlr?U(cQ{xGP zxdf&*1eU_46Q6iZ8)mdYOog0;rvkG%X0;X~d(S_DWif`CwInykKP7=c&a(csLH7+Jnn1%XG>^uy3^S7|+Fsa~Dq&H3q6*nZ&cNyv*-- z3rb9ZO@n-~Z^GlEDXqv`wEK`rhO%LTJoK^yq>7SghnC9hx$!V5nlc&f1twEU-{R(-AFW&Kem;66m9gX7k@b z$pG>iJ&zgn3Y4eJsupHy{{2(qg}x8}Su)^mSe?}-_TX`@HDij7aB3Why^H zRF1+rDi11R9={qXBxZKgz7B>-=p%p33o7Y@BA?Si$x1_0MdJw0sm|5UTw;x^uV2n+ zxqJ-lSq~C|dhIyQy|lc&GI;_F6knNcW=@beRx~vag9(CyXTaiaF{e*8gLIRQcIH~z z5u(rFYCJoN>P@8CNU}+vWcVLE(j?*2KUj~6P_8u9-}nwh9P{kasRrHq&2)sUItAb|(J=I%dJ&yHAf$OUcWI ztUl?rdN7(-u7()dv2scLKemYmus{Tqe!(R(1Lzu0J-5WG%e@M32~NOP|6?0{s*(9q zdm%5}wsW2!lcCwMB|NbtpZr5jwMbGfX~)S*OV@uOlFrk`Z7Ib1l4}vS0t!olNsvR# zeLV1y@)gp}F8f)K#Q2*!vlIkZbm}CzIZe7+mPPL5;hC^__dswbta2h|SLIW3NElJr zK-uU>hJ2T+GwMR4#H$wGpN(QkjgBeRSeS*XH(GJnrglC~*nAf*zv0C7tg^;Ecim$A zI0bJwfaG=W2-7CWi@V8+X~Q@0I6!$PZY$S27^+JP73EyY=?;_{1O%8Zt2RL3qSkT5 zZ`-O<$}ql|eq-oKOmTgjQ@rnoWX6-lt}~P2qGYtGDyrgA8F3BX06yp$iVUv!HkSUW zSn?8Fw$dOOU50Xz;Dxj=h_vk~z{T1q9hI#tT-Opr=6bcB9zX0SMp`Axr8gbY-?#rh z^B!^Sr-_W#A+`^3CDOEo2A^%x2ub#kf~uzvPR`#Rd^EFfmVLT( z7x+K6_~@NqD{jaj+EkrGwd%9ePYZ=yFxNfryY=H1YqlmQHh2^JMXSMh$J_mt6evYM z!xsipn(%s^DCMs*FSp#cT&8eWlzxEii8(1!$LD$;VwR0X&L1N_Q@(ZW?+5SfT1}n) zxK=le53&n3-2=+{O5&R5n6E@{)0AcE0g8S>{wBs9brY!TCw7E=-@p8HF%|oSeu+K~ zVtABnOs2`oMcj&mueD2w40Yui3(yn9=8zRu{?;`J?Io!xPjkuT`G4>EkL@nD2=HA4 z)kzbUhT;WtbaRR)%1WB^2!ua%3tVn3DAfDBy(f46!eWJ%RWMQa(pGyo7$y-eH~l!7^hC zFr;RG;swbAMGs2n6uu^p2!>q|jGDP}=CRfWzHx{l&q;AW_BF1Km6N&Pgn&Mw=lj?0 zUHwMJ&0c`bd1j{%-ux|#7nYU&^Oa#XY6;7)U5EEE zyA2{Ewl;s&f88%~98%iQ-^32oU-locfA&z-K>TM$a16ZC;{8FFw$!530tGvjI#*`)Tw)l;pnso!OY_`H+gzT~;b^Q9}TkcsNgTmf&)_@d9y9>Bd?<)6m zQT}7Y{`;f3bGgfEhqG5xM`_;D$QWn+cb1vukBWbX)j)j!hwC|dK2tcK5Z#}q*-K1- z4+#z3_wjbV;KD>7q0s4+iL^OBMC4%NUTxIu{I}>IN9AXH)jyWB`>S_-hkpzth727U zaYz>6fEx8+mC-{Vg=i3xZ(?5MYp$Lwb)Tyde0TOP;0nD;n#N*Ug3>0ItAgE-w#CQGnIQvrZ=anik7sp`o@6(_9!CxXhf>^gWI~|71xj=+Yz_t zI~T`cANN>>w%J_?2TZi%$t%|LYR3Kj_JlsJ>H4YaB)Cxh+Xlyy*y}vajOSSGF_sB-|5+Z$oS3_%OOn3(sqGc!Wq;Av z^+1=pPA4IPY`2}HsBV!J=eyObpqUo|T}Lqf*Scvu#F3YRm2*K$0K>?(dJ}4EJ!8^7`joUA<2x zENAw35XG7UZy}^~Lcl5|q_?jyBLJ1b=2T1ZUo&g8lgPFUL4b#P@A`(7TglrE)XB>g zWlWQ#$1TQE^1YW$uc}>?1XctBV{O)peP0(=ce2a>(ypdj4$K}z(tBidnUBx%orlGE zY2K*f=qG6o0JDCVO8b7@H55sFDEHJ}E=yO!=~emnkz5D#d#a8VRRh|>Bc=mJtM$dC zI=i{~u=;Q<7B2#H9-n1~_@-&tICd_95mee`5gZsdIt?2jb0!d9vHGq2pm}*I;|fXD z+gEDkSmnJHq#5SY$DH2}`d$-eYt*A*3T8yF5Z%Q_`fr=^*@tdslE$U-3KKg=i88sd zfXP_<53pTU|Cok+Wb|bsGOGSKFq&1i!+igaI!&$WBdmCIb4IB=Y}zYIjU+W~@)MM( zf3Hx*Y7Iz_<85F@r_=8%wrg!Ti4fPwBB_Ogo|4GSEn(XXVgH7fW&Cp5Js_~kx5ux# zYoK9%SB}L>PeZ;Vr}_qisDvBYd@vuM^cQ|nL~D}~$;?AN7vW;~NRWr8BeV9~QRltG zKgp(YJA1BYG$bSIEznErv|>o?h^wbtd}J3W;v|(UIaeq~9Pq9+8Mv`y?Y=l#wPcLK z$Wk?{`P(vL?oDIrN2Zs%m+jej5o1OTs}ndx?=-L?3v= zlUkbJ+^c+;s!9KVf3>CrFu`9$S^&l};IV>esqt$fP+2t%@*GJPP6-v-O~^nlzo|(i~j7I?tpYZ{5Y7(p8kEQBrLng5XbzSSQbd9me>}aGGjVhz->koN?iguC z(fVywe>0#i>muB5xFW2;KAEB))Rt6maUgP@>7_6aA1RK71-W^=#LwskJQNBmxqx)I z6cG9iTdY(`UdwLr`rNhCx5w(1Nrm1|r0%rU0sWi`gB(&u-k7aq;ae&yR%h zlbln@Eu0vK93E8owk-H4HTemfYf#dV{ul0PTzT+@RsyMgR%H`DIK6L++ zmyUi(BByWC#(l+#PrL2&Q~$Bq(nI2_Af0Am{_6_fm~#{4!4O?{2LX}5F@HNyjd{Gx z$f=%w79z~|cT{K7k0JK&hocX>tl|ukbBiwSq;5G;=v&{kkCK`c2u@;SHz2Wuw0VzV zRY&2Mi*^^Tqn!*x5!>jc3J?eDQEcy?`sqlESB8^3x~cUN?2K{i6;I%rB{&pUAp^&6 z|NE&Z;d4>c5j6^avo&p;)lOPdsN5>Nt<0WkuqO1_bYI>%#EKdh=PR)^B!IKq zbu{L)m>V%iqUf>`1Mgh7qzcmpjzNSpAMBvB!VM=GiI3RqD^!rD|m z1%i6Sc2Kzmc`5a##2dvPNfAanJUznjsa;qr;D>5UXlu2A=RQ5k%R4HsrgSUl+j+P{ ze|r(jHewGet`+aqDe}6{A6etUSt0eiW`JyQ1Qbdk0e2U@t01RykA=kVw4^AX+f02} zo~u9=&OinCx7ht1t$QU9jfs>1Ze2%=TZ^RlId1ydxxYqy)Nv!Md;ac?hk~h#@&7n; z$t$Vl9budGr9#b`Oo36`pGE}n2PdzB{#`PB`c{h*+(^~+XKn3A9CG9?6{o~48PXzi z%<=-g)9ibX67h!lCJK3F7AXzac}Mjsz9i+>-NwKG>wWHDOzafml=Et&{HHnJ;UK9r z8G@JosBg6?Z~l!H-?r2gBU^;iJK%Mmym*MF6PArTdV(CaCpMg$1ZeX8{P1bd^zcPS z-?`p`B7*&4;Y(wj<{rEfw`$UV!N&e{- zMp2hUU3W(X=t3yLns%7waq6>~CX)F+{=$ntk^7fgL<%%7?dNQP@7!+5$wl!s-9Q0@ zQ--Wy^ct;JBiFV30Z*aFzR3n>jgY&sPhJK3{S`k=|8Ll!lkyfWM*6bgj>@9!di5A- z@eCf9tW*raYDvnk-4DpE3H-|<&o(AB(Sb~IM@{z`qXg7KUv-^6Nt?GR44>&1;U#&0 zXM@fOS|wozTDO5FfZqA81+b?(j1r(fKe42edvT48NwK($W8vw`etK$l*3HMsMdj6W z&7F7}b@b4kkxJWjqJ>P}!B|qPW4S00EiTn=$=Hr+(}sBWRBQ3~2#eGs!2R~%^Y|T+ zh@wV;#=n^mmE*7l00zCQeoUknDXbk zoNQN7|2_~uaNz0dJW+_PchV2e$lU1hhYg4MFJS>rWtIf%NsH;t35sS)aw!&XO zBXfJg_L(PrK1Xus=mqo-hw)Pd|#gui%({oOusB@ z5NE39-+dW*BDYW#PM$B|8l7HlyZx8BTF+xrBUI;wo~<6>@yyz9NrOb7WXq~LP9BaSS&lfVSLJ9xyQd*Z3?@w9jfPD+}`b}NaDpen?ZA~<_++0hy0h!YZ zqqjU&$~R1v9MwT4BIfmkRNKC(mC{)jByiBLtrGK|H*5r++_LX$Sr{>jL;7j%*e%OH zndC;;ITmWHHR;$A*tPg=5Yz1)<<$*j^(=QLiGDlvKQ<$oB&KaIQ%j;6)$v!?c6sM- zhZC8`5voRAGF++iIAdDx`)sT*td)e=+9B0uVh}Zun20w^Gf64Ksc9xddPedqWgyr* zU)yreIPO{S3CsIRiJs}g(NAq#WjbsbPg=(QF=G%?>fi{uQBlW7$i=-}NuEjJk+P`| z53qW;zYpb7sdrGIU#^7n2X>#bpAG;MG;v+iDua`co<%D|WdYfT@5D6a#m9h7+O zOZ1&N5$K;9xgQv>HtbIX*G%?8-<>=6mE*BaFt*gUPJp4qRN8zS8Un7RBjRv< zHn(TXmtR~sRGGPWYlxlE_#7J?kmFUDyf>!-vs&MML8<`({w~iH@0HY6lZNj^MBGA% zKpJtW3aH?iRDQJOdWss$_=Eb|bXTrMOqs6Wy@#pQM$cN@diOZj`G2jm_^?Y|IGJww zUGBaL2hBL&=Q?HfBvapEDnc`pLZl0IWBnZ^+7a$5Xr!F#i}4cyp}yY`1W9N&gRB@T_qIPeMr@hx7mURk4>xQuapvqB`doMv0TjDk zM1aJ;^-248-H&~ge{r5;4F(m`n**v)9gG;DV)iZ1&xq%Ie4w_OM!4Ohb1w8>G{Wjy zFv<0>z3udR?P=#dvD3o!J4Al_MgCld5r0Zx=QGH>y#w?PJj$c0FzjKE1bf~q6CrHx z7AQG9=9QF+qnZ?a5BuI6d-jTHg&*r#V-6^1X?YEmFM!A}U0G1U=4XoA4j0xNw@FXD zN4K9|{GH)nYVfJXWOS-VJ9%*5=zFiZ6u;J%Q#y@fN#LdHo#BBpui!nitQqp~&hlos z3rR$&Mb$}RDB1GKkxbvXHuKjPV|v2g;G($vVVL0BTtCuk^TLgW&4tyQ9)p#j7`ZF9 zSO#Ek6S}J}&u}%Ye?ko!P?t(yHUCvQE<&H(HG?M3iN+rD9t>OqskGR@e!kaSF~zo7 z(T6Na=svIF`hA{xyPF|aKQBt{{}bsxR#!jP>W}On*t^lA8}a_|EYJwvXll&Xb~Lvv ziLG1o+(84H;#a>Pw%)PyZLd&xnekFs2y|ciUF|ZJ{GCL50PHI~b73yCMb6PuCpgpQ z>jP}gvjv~493V|V8)Yu>_V;kEPvJHhZ6lh#3R3B(VR_!u&6+!AXA478v-(&a>|_c1lmAQg5<~X@AMYA; zys}xJL0HhAuP(FFezh}b+NHJDB!9?5e~!GtFsDPl zWx2>Y@u!_m+(Oz_OS!)XKq(KCJ^xWU{}#a7NwEI}1o$LRk^lo{le4K4!JJBi{?*j* zQGw%n@G^qDhW!Vp&NaF88vCqZm`*voOoMjsPOJUPNGxH*-?M! z4j5R#5pm(3v8;O)Gn3we|2XC(PaF)2@@8~}%J~^Xy*DEzs|fL+g)ccV_)iqK*xn~% zS?l{R?nUoEm(d-!D!lo{Q!~ir1if=EjP81R(R+emt9ixS22b}Q)8&2LRo*se{l4{^ z%v+{lL!v!wR+!P4s!}>z+F!EPUJrEl6?{31C@(Yb^+Pb7+_8JXX-4@F@kU91-g`@= z$wzdTLr8S_*~SZS3yu;>gKW;z9*{218t)t6wXDLAeTXY>CEfu$_239|)$;yHkL5)7 z9O!FGE&_w>*B22qJ$w%_i`PVnunP^1MngqTds>9QGJwJJxjXbP=*20l!mnn-FaO5t zTR-XSvc4_4!q!y444iA}KY2lw96`BD@R)|E9{X=p*OA()Pq!sjr(3j6(w_6tc}_VU zm$r7)SrkXTlDW;!bZG}Sl}-Qp1yp#`v1th?`={}<--YG&+VP4bmPC8=-AGDk1-F{~ zZFPaP@|-)emHlsCg6{i_NTC2$%Hve-xOPH}2#X|j9@#R-NC`w6x z3&mw!^AKsp(s}iReX0p}3|WO{t$i`Y8`_+T2ji)~2%Nf^-E>VF?w-Ikb#^L-%{1(K z7Y`tU4=xg>q#of}q#cVpiITF%qwlCOa?D__ zb{#pth}gAs)Eq1c=_R!rwklsYQq^r-K?o!cxr7ePCjHiB0!NGyIxGg;Aj1WNqstOp3~a^&!tya+k#~dv%XWe2s?{s)+Bry_0i{P)R>3A?{15 z_7fUvQu9z`1muFcu!+ySmWe5!*&_e3xf$^vn{xkmW~s)@J#?-(u?9AADjDiwel0W@ zt|h(aw94sAX|OJcOPJml&wTt)yBa{6XjAEeso*0Z5(z<67NA@dMg zBi^uti8#Fy^}v2i7wkvoqcr&!Cs$hj3cVCc zY}M4Zrq@l7HBSF2XEpgugXHMwN##Rs{K;FE>C&t-E;0E&;_3s^_h*(u+pSTPXN(so zTGFy}gJ&rr%Cz6s{zget3Z=QEl;ZJ>%4Dq@bH$z68s#y^!8tD>A-(5ktX$na;1xvQ zXJ9UARPTiBM~@^ku3P_y`zk_>&C=Il?m_OrNGtDP38M_u_U>|*76)&^)88LP@^Yr$ zXSSUCic2##Ijl6Z1>u)7`Alx+;pL zx(;cYb*tMZod1=Yq)}oGb&39gr$V9@bW7Fkv zO6U?@9ec%5V<3LL21|clnH$7?bujmxaXt_`*Rw6Z^=#B4p?c9p#VWAIbA`a--#3P! zlIBFJV?M>|Miwd$TxVbZCM1gJ)*YYKG^Fu#V_%<&jfgnmXh0E*y}6e?G0u-*mjU?) z+!LvnxqcG(2&ioo2X3{cxR|vRqZE%!J23&X1WJno{5O0Z+dqj#yV2cOJ4qSrC;4`q zYK9peLl%YMzqiF?v@aa{fMM1?M`%j!G9iwIKrE2r=6J`bIEjml8SP*19?5 z`p#vw)el^C^t7pUwy{QuL`4M1jr1o2ZU=$1Jng~7rC)*#K2SO1$00@EcO7X7L;Lv4 z#UWILl!JZq_0+6@cV=6gsXCu6z`3pm>L)&`0wz=akn|+ka&ZPMAU7h;YvxfBj(?5s! zL$d(d3+8AS)GXLWco4M2?IbPFGiajn@4Z&tuTq!wq2b5gAQA82!=1C5Y6gVWIZQ*A zo}bRO#0PZ#!9+>znftl4s`-%l(sk(uWO-i0)ThcZpQv`GOQhcLsh*=(V{kS-@g5CW znn*Pd{57NG)%YtDdM{MI{ngaft#I$|vR=g!Ry5RT{u@%Ket1Wn2>lachwmcdl0FAq z(PkUBG`|9M^u6d`4b{|Y6EIZVaX2%ohPI`;0nUW=oTA7n?6&ouS=#6hLZ;h zY4?d?x;jj~8C_Bn(~#WX0_~GvvZ0;-V?*0c^!X`OjsO`nN`~CWhX(_ZU3$viL&dEg zLT@ZBlIDBzKCyUcyLt1TBbdd#kQ+5^ycwoHFKh3U%ZkY@oX^5DbBcE`ZZPP<{Rukt z_46)p*a@r(hYOzRGIA^rQP$%)C_@fk>8_I=D3pgEN9`X}oo_6{YvENvd-Rj_ObF{d zjp=au8=$NpmxlW|P2P)r{k9KPK~6hKj5bLw?r8{ zs#?de9ZJQMqM24lu3}`yW3F$vp$tmlRBnCD-F(r0pY<|oqYkJ?xPjU2-OvOQ}m;z^nNYG zE!$n?z7y)ouK~kr)MUrh>})(RO8=!Lx~^AYGHku{DM`*Y2=XrV7teMa^X^a7pG`6- zRN2PiHB4`hq;KX-QCleZ`2C+9%hv-yR!-mNt9M@?C`zk@eE6Am<0}ObRMLri^>RPc zB5i7x%p8Bo{6oD%U!>`!6gassLTP6{=zKs)ekaJ+2L-D@jV;eKku-) z@suo=j2Ow(mn*Ez4|#=F=*-5<^!{XEQ-CQa)ci->DxfG0NbtCm2CJ!n_1h+uWL3zY z=L$2J0+&ulQJ#((dXy(6H;@B>lc{#*sC@KJZV2j+26xB#2vN`Tg;79_%+3b{Q3iJ+ z!Y>8!^Ev1kk>nar#sP1N^#Ytu0eqZ_&PFYi&Iyk-*)cUX?H^@(9&S~X#0-O>sPD%+ zt@5Gbm4v`GuO|4z0Zs{z6^6JXe zdSVTIiKVn44vDnqHS z)es2jn2H$#ga~Qs)4pBk zRk!coY6E1TWimf}b@^aXOXdV!7zsUBvmHG3!!1}0mGSI*pK6WH{hxh=_2VPg!jZb5 zo8QxAQNAB_KUL{R|+(v=*HGzFlSyULX^J z5V^0Q7c4%SL}!-0aolrCzAZq8Rthrpq)<2${m04ZcQ5oEo&vP_`;kcP%*qi8QL(cx z)6M2mjewl?wNbc$-hGX_vA^sTL&DNNRiguC+tMd@bWAvsc0Pei1g>s$7A+StZc2Qk zAh?l(+MY@3Xzm$EDE{}}&Zqjuq|c*}#BaWb2ULhy- zuv%j-KlF~Ha(3vTZFqUPZ_x33*=~!8&-E$NIGmwPL}F5fq^#SJOmyC_!>TaTp4nU@ z-SQ4RJ~>Equb|6Nd z8L#y_<4~(~2$I7ev?ZO1-nBmKVTj9?iYkA5G7&`iCSEj`?XNoPEi%-f@DU7IgW9x; zt`)AtD=x>oO*OnWBOJNMS!(SjxJ}!kEzp-MR!jOTTcC=&qj$?Pb7I%ikkfP0P1Oto z>9{Z5{((VDUW;ETd>qG)O=Kb6^}gg-As7#(StlbDPE0A>4I@SHeAo2Sos~_ z=$e1`y!8kR;X>zYi+6F(d8R{^W9(1oQ2z9xL|wrkn#l5MEye4|Vk5XJ6;g-a(^aWd z`7pKi;W*KBW_;}%Wt49K)?IpbVk$zoVz5jydoxvmT9m@UA5~8wVUDfqKfx#mEGU^sAhyI zlaF&xzVReC9LNip2`~=NbT?Jlg9HP*yn5}fC(CDpHcab!MAMYU(h&J}?~0t8qs(m5 zG-8~L;n;@p5apv#VaW#dwhZ*&k+f{gQCDwDJrh&??lRkTy4e#~ro_-uMutYsHieMc zBj)v6jEEtM#LW>~z#j8;X9|p~yg{mNXlHPWrYj3#s}vBx1NDAtGhW3#(K$093JOB* ztv0Ttgj*@Nc_drd2B;yJ6#RP3_dDJKE%(d*h0oOb9@|B*MFdXgM#)f*KK1royomeS zx3?EytoQ7X2ocoR{NijoB(zX=^3kKf*0nSvo0uc25j1;>tn)yuVV^ z-sXUryx5ZI^5a6HN$O`SU?f|Y_D6aFk7xqtzm_vm)kr(tj!7y>i9rtG)C}shNcoo# zvuwotOg&j2*!vw#R>xNQ;9A^(0kR`F%lAjqrPOZwFMyw$#Aq0@WZV8#b{v; z0?uRte)$;UQtEtED-v16uCQ1BtoQ*He>0|!+Aj{C#8M#>FV z!X^b@)3>JqX)*TUbktaM&ikt)%fV=K9<&NMYN`3XW zR`GXz6(28oDbE=m=Xyv`Q(BtFRLZ-9fLE7s=50DUi*U3(ZWY&*O!ThR=mhsh4cEWr5E|mQpBS4iCw}iA%9xqMQuWI3-)R}T zlb0EGG`~^JBZx1=rlw45gva{ZUF;ib3wv~$fA_` z-G^iRS3Gf-Yi8(c}&Nik&LPx!KCrKLP^YyapX9FL`c5ffbUm+roV^@vl zi0{`wZlAL!xTm=9t;DY+2NR_tH2HeE^mIn;7psJ)%}IUA^nlQ_yk^i3`HdMXO{!`N z3S~*PYVN`f)AH+3%7|;Z!6KfioPQJ7K~2F|?U`8K{&btZ*KGII_$KUU55~P9O26e%<6LwqrQCA{D(A?QyBPXj+akZ_uKf;;gf{@taOUj@Y1^UQzQBTvH=q28z zxEG1R87N&v1=W|{nLjg0nK4!;y-N#h769FJn=#c@I`7rgdbcj4%A+Pbuxo#6W-4~U z6al*gCk{R)S`g#~w7PiIktSzF?yFXiXjIwL7iUKK9es}et?@nC^JQ)|`2TQ@yFNbo zSC|;mfpC;TptZc%lkeOJoN1miw@G%M><8>5$DtoK>O%$;?q-0c&;gCxdSX!~C6I5m zYGwbiy+m=4qdV0P2OkG-4y#b=(*&3w zHC3q_Ju99$uXLLIfY$X(-EA_Zd?w)^~yiT{n}jJgOX|t#LxBWv`1}{}K^| zO$RNcHI6+fVhrji_HlWS^j1fnxJ|uiZOnVFerQv?IC+51Mb0LGGis8GQ&dvB{Oypu zj1c%@vndsx<>IUK{cv%d=o-SIwcAsXc;o)smk%S;ZL3y2luSgHEB%}J>m1hilN{1B zE{Q4P;RpJPHZ>jVfLZ%AG1!OLr@XltVEq;xBJnOsR6OH%R=vV^=h+qP_kK*X^~*HQ z>aCn*b!>E_@f+Ml>4Lc#QyJ4G^!8AuPOg-n>4BE|=bODUB87Y`h%iM`tJ)EXc9<><;;{rj$K0~t8+y`Ef^7g<;s?_E1}QF z3r|E}h_%IQUaAV!ss0JuUZfEo)HbDr!r_asr@@+;`HWWg6{e@Urwy$tcd7aO1IQbf zdV&q8G4oD+9H&kNk5jn+blF&h`bS;7zR*dPzU&j^H17sdl=dYH73EUs*<3&7d*>+m z`SIUc@lyuM^pouc>T+>ZH4{WZbFoxLp2G^&v&?H>&GJ+F_u4)z>+)?3d4F6aMTZ;5 z0?qWj+S=M=f4<^M7k=N6Kl_qIPe9kUcAnqe`HwB?l6RVEyT&Z0=Rov%rMEtu_p_@@ zKS|y}wNlwO(E_2Zo|PhQ6L)FH8JEm^V7QppVjUHHz8s^Q}a&lH?j zZkzTiu6S2yZHo4Q?Tqmn2klw~OOA)t3mK7V7eo`*4oU~J zmSC+o+nq~Ke9=A6j#~UvTbGKa8Nt?`(+?thr6`3NNcZ*gB+D3eS=m0A#NY@<795y3 zvHhF)jfA_xs8~>rzg)cZ;BKVBjUN8y%5vwNyI-#g?Wss_6NEt>cd;33&z2k0K|iS& zK-Aj@=PHN^>@w33i5;b;ew>wf31LQ7N4b;HPZnv` zKkALe3MZIDcWeq+oF!*OWk$7@T+9=c8>NP5%EdD)M|fYZeaSQL+Hrx*ti%UD0r!MfxwLk(&iRk4wuRNo?e*iI z(%ZFRlI!bx4<8kM_$y0151^6wSi0!vDxtyceH2_smxtl?AP%h)*o+$(RwB{pX->o? z;5o=iU<(n-9@ExWkeabIWHDyjvu{`U35BsMw>jKn&L0L9QlQjF>k6a02NFK5*nvhQsxy>mv{dNEckm13U^*X zyC@G30tlCyPI3D~tgGpdqj(Pe8{>Aw9YQpDi91Y^l0W(M9K?B**%7#OH&La`tgF~d zoeU|=m#86pGm|)c$B0-;mN6@s7+Q+W4mvlNfd~xa&vE)Yj?ailFQ|lYfaKO!2O>P% zfcNs>aoZ%OLTH~6BVNizJ1)_e|IXHh&nX+VqOMmWKflaWPBV*y-yF*^Pf${_G^)+f zd9_K?9Q=G_b;|!^3(AjBF9z4A*-3S+WqelZZ!g<4ztK`)z1u*q!9>)KlAIlt~4;?{eYGV#dX$m77*D@&q|V#DXl>Ul>vVBsalAM^{6Pbji0aCVAJ$`vk!$S*t(& zyYw2#xYJ$`hpsT4U`n@*Ie=|BYIY0qhP8+`)z_OWx)4#%U(z%s-WQm*``y)|JNK3% za%fq9(8Xc7ve70y`yjsLyNQq&n1ES8+T)$K@I2k=4E-3TD z@9%E9ZFkl@AGXQR`|E72S)eZ`!h<>a(+FgbEn$ot8E5A!xifVl2hN(+W>PP%i{rlk z)c7Ao=N(Vg|HpBC>zhg_MZ+pYnc17hH#0=tYlZBLd#^n&DjCTLAv;;wnHQIPvp3nf z7Z=yaxbD5ib+3D`e&_dhf21DHIiJt#{d_-PyNRWi0&nS$7`!v6v)IkjXVVH0h(9RB zuED}qWZ=f*ei8nk_?*i&Fvb;E-I#7W0YwSJ_m)*fKju5K9lkH}3agG42olUcE(GmC z3>KEt9A3N75OPFp;`tk!J)t!Wu61p7N-U~=xGoq2)%LH=3>Ylc$T#}=c0}@#d+O6l zP5sap_(JW+eu8h+PD@Hj#}q>CkP=qk>O&X6NrGq?HUeIiI*4(pTs<><7CUq!k%utE={D}hkh(D$0`l$Jx&k=ioL7a5DA zIDgKdyypf@xV zV9JIngO3lWr?b>#3Vh(K|^6K+)Tu7&R z$@Xt~OaRf$UzSL+8=B()%Wu}>*j$fDoCcfVje;aFo)8O{G#{7 zOzL_+ytzua1(3^)skoLJTTvDGc0*i#C#00zYr$21s+z;Z};(`}=;ATk!J$exL))k-~#AD4!+| zEH&=V!2GWCx4P}Jw*|dSyOXZ0GT`|}RkFR#BO!)znVPi1`J1x~%~3!_LF!SgtRxu&PTLEIQgp)l&b z&A8T>w4fwsvKHat8OQa`T>xl&4o>SFdDo2l%aS-@^S}u#%cz=YF;3{mvLONo0R@zS zqxSuK47P0%A}%bLfS8NFaG|@u z&KL^wIAizro4&m!%fo0P5chfo=YUe?q3O%JdZfGmGz?qbS2i`KSC%VPNWjqscTfM( zBkx6Fkr3JJ0Zaw4#oY`o$3R9PpSob?w0CDUGXD&!T_Ux+Z40b#P~C1I~ zIItxYt^@nXjY%sbXQdt+1q9I23~C0g^Kdm*l6foX<$XQ*Ky?wOut%E*?uI8`q!MkX z8f~m~KUbRBz7%eAP{zI;^}0XzbGz@yDtf8>FAE|jF`VmULf|Yla7pm8VeyvL=i0H* zGZ*3~9_)fnjRvg7sH$iOvT}FA`DdzuR|-`^tAcwh!=r?nGHAIrU&y?x5^#p2mNAYO zC~x;2TJw~`qe`Em{Wab^(-O!h}!eZRe znESg3w-W3doHt-rp&a!o(g1hgnQ7n$X@);#e$&#lo(n>DXRv?W%Ja3FGlAWNsL~!_ z=R$K1){$dW>A;>paBcei&2ZKU;*4QFmmx=18O)E%IqKOzN~MzLp733SFBYBN%m1Kt zsgHgY2N#-hXoMYHjkYlyj1tn9HcYoiejoKZr2*OQ<7u_*D=Ru~+hMZt zVg%5VcI@I^GEeGCn6f@eGn;1;xa)lYt9xZ<&eI@ci=+618fj)$ga;>6*#4{JN7euMw{!L5!S)`u)8r_BZw{*B!2@^6~%Px-So}{kk?--Jn)D zLNKMsbf^n*y#~bS2Pzuoeu$IXdfJm>7M)ON%-cTCS@V{B_qwSR&!id>bD^O(+Y`R) z;!ayY3Vds<>`41uy@q8NK5b6Ud?5k)7|io}R$G}g8xMcQY(rgVaFLBhV=6t6{uLU* zq$kk5;NU;!PqWZLy*V32&s|-3Pg!4)Hn{8)u6IZ(HW%yyDQ*W#D>Nm9JNv6=KzAiN z4uH)Napg|ygS~8Ub3(rO&iJmy17gP}2<{Jj9OS94--7(()iC{IY3vQvyP9sqJoLek6DV(gOJs3xO8pnS44p=u`n@@ixL}97t*#>o1&K-M)fbys11>Yu*ipI;mv>4dw$?+>}EH!b zb;`G<1zgv`&!Zx`pI3i*LJMx~gt%;{%kX5zA5=sLP;W+X*hy!63t9%9j7i2;xRmn7 zYQEtQ({kTlr}B~yJToyn3H35TWKLjnsp zwbDgUSJ-{MZM&xo6=qsEANAVO*?gd&+NjJUV^OG`E|6R3Hf#H6t~)2w1=8P>&Hf92 z@#{Z6y65Q@!2Hvs6KTg8l;4%$?NLBYX2Z;liDYncuJmb821IL*yMt*)%=bCL$*Xk^ zs#-1<5oAD+b(lX(6L;Jqz=Q#IjsvV;sCmTR2Z|Q-@QSZP$NWvxP z+VysemcP5a{dSY2rrZY&bnZX`R8}s_ldxLwzSUDrwh1Z%ZIKkJ&?mek_-iL=ZT306R(c+aD?e(*Y-c?Ui zCB?C3CKSZsu71&k8Ji{&#ZZAE8&O4x+7}KZ<^-1)V!DZOSL}k`3IXTP(8neXhLqU9 zEWX~iZwtl#I1w^lQYUQApjH~44RT7QW7c2XZLNO>h)esS)o0{_g+0m{!{s>nfPt~S zvPueOUZiTT0n%a~&`XO*N<2v$KbcT_sb)uDUwP;Tql9WVgs&_(p8L^zS@un{puu`U zlHUhjNOHE|{lP=kfwAJ3;^N65;d*nqG-YGs9E5S-Ebd3xuVzyC*S&9lS&CksLqO*D zUY!*=_Gfr3u72+AuR?l+ldXv|r88|}6z=B99fphuM6vbd)3tG%CWWZP(;k~#YL6N0&L zkEbdAQvO_N)kQa5EmMiIm;@qDsQUlK2&-V{6C#P+7w%qpzq_*T2H^Xop=`Cs48p4V zuvK~9g1f)cXzi@w;&|TFyG9ZX20s{B)OOfHIWBbmv>8r^OMw@p(L=M|MW7WgUXERM zQ#Ke=CXt5nv@gm2=OHx}&q`w8LMIcWE7E(_k$jxJ#H5=MJH(|q#Sutmm1X+flV^j& zeeSEPugt#$8J=7SBMs8c5c)NWcW0K3#a=%y(dB!Gt;HpVwNwkAu<=)n*^|J1MuN_B zVWC&*3`#@AQD?7vX+gbl#eRaECoHeSZ!zQjW}2HO!RpL2@+RIMTspNPym`yT&u+^0 z`sOg&MoP$>!t}+OuI7(koB3w;<$i+4(fGdMK<%N5E4dMC9;ruo_(z5<%2RF&&9sEDs*@&frgk`#&_#(E4$6-NgysdZtjtU3p z9W6A#^%Lvh?|#LjY3Af$ZQ6-;S^%T6Lr3lAS`~+-TWzDNs)Vd#nqz|XdTM9{SIm-s z2f-+Ay3plGa;SK@@?cS(u0l_P@+E>@TIw1s!)14)SlB9f;)zJUQm3<-Lk#T>$w*|WM-XcVtbfb;BfChQ$kvnjz3#txc{Mcnz?gwl~cMDPCP%&8oEO| zd$TlJsU=!99E?k!9|TzdYhm*s!vs@|lDZ|Zj+e1vtAf9J>fh!{dzR7xQ|;Ia5tXcc4w_G{;T=&s~idpef$O?oQ3aYzEQ6@&XI< zc!7qiAGCu-XP>xnDa`@1@AM6Hqb5vVBr2e8#|46xxdma72rR0q1W@)#Vt zA#olNxyAFiAfW@l&cqPkoL^4^#dH#{;|GENOL}=TWiuyhg<(k!)uF=RKemqIQNCZU z9o?Dr<~=TbbS=-L+}aJQ?JJ3O#DqIT2K&mEW_z@+DH3#7h<#Fq#y>)Xuunc@48C4% z4E~bii@fX9u|$$xY}Y`XCv3RZuCIR~Ry^8tpQC8MXFRmWk7%v@Wie`wGdu%&;`d2w zE{EA!niI9LX}Z0rFy6+gI56!mp((BMASflYgLhbtJD||fTQWRt75(EcOG0$Z51O6&>GA!b`gzlT*}+l|I6$FzG_RT57-AMeu4fzV6{nHc1;hrmOf}|M z?DtX!4^#+XXhGhJ%36@M3lo{m+1zwrPIVOLPTlTKN0Weg;_Cz%-Cx!4hGZ$BG>7J} z@>x0I=2xo;iY`Ccmy?q;>jWvt}- zOFO$Xi0tR#(p)e&xoW~7(6gnvDI>$fg8+jU)(H@x3yLo%5;sxxv{r8pM04~)W(Inl zH4)CzTTawZ0Vl1;u(hC^TxJMW`5~nlAVF0&7E94%ka(~fw@JXM`{2Z#~G6_ zKarHzkHsOc;!y)zyvJZar62txe2K`l&Ru$fK(NNaCRjQvxH?Ne)rX7>05+SCC)*Gn zu4!73KLO>+3uAoIUoX-Jcm|!{K$64v8qiAfB)KPQqa>+`LZ}`MmT?qUpnHQg&%_`h z*|F6!Md`~e?a*_$yFUjuXG*hrRqXABJ?En4w~xG(`I3*H{rd&tnB{T_34JLX!AaMR z?7cTTvw8E!K43L?3}gq%DBpN;&tsT;`3NFl#%2h~d6X2+h)X{vo10|fpMd>omLjy~ z<-oIqyw5B{o3{}bQ%cNA%Ru;0A4`fR0Qxrs8s4%L(9R48L$(2!hSPIWWDmpZb|WqK zN50$+?32?*ll=1sy?FXyvL4AW3sYfxUiJvD$4c3evU0SrVmaFRRXwNu;WTtP6gE3M)P`K))H_ueX{tqV%}g)A(NyXpuEXI-x7|C>(d*cRE$)$ln7+erSWQo#abf-B>@#1`cN4WFd zHpZ}zx+75FM=NnrzcCk%SGw^cKLerCb4#@Ki_VBpNuSI7_OR#N5?6>rg^_&lP}*;6 zseSlXL5L6FkP&g25*dT#rgL935s)|ZuJa|$l=sDA6zStlSJr8L zf=a$KC5a}uOMfcA7p_|>HN9}kEp2+846+hT^=-Nl@t)DA*}SQHzeQizjmPb()*%Kh z-n8b>?aFe%%~5diimkqaqJRgJ>9QtbwE69-QW45`o9?6TVcEC#ce}Z zq;c(D02H`wrXiZHa&(96ZayDzXn{KSkMQp?(5_$_2(_`W-Cs1mv%1eWI-*1p)`8`Q zJEr&fnu|8G%iRK5^73Zy62>%6_Zc@j`k5)=IeP7~>Fvg6&r!B@3Rcx-rPg@^vGNQ6 zUxm16Hft@ov+)K$>7J-7FOT57i<2qXoGD2v20j$3fe74Jaz)>EcHp%LKcRjAZZ`k%#A;dfQ(mT7(nUm58_h{8Mr9%C-%tdgRfx zbYz9K1or|0_T@^M&gE`VztOCJj1gk$)DT7ay z#5sRaXW%bfxbi71QDV(58c0t3wLb{Rp^@Y#iDl3U=M=;Kk$Q#1<%b+!{!Q0v#%ub5 zQ2#LWrZfb}-}ZX%Rf|p%i<_V5&dK%H!t`P#_9eXkvJ`~O`1|zlDc^8MC?rDenBLP3 zblm;|8HZhqSU8bFi!EHo*REG8kH~dzufx#`^YcEzwo4#3%UsY6I4(Jjckok~1@9BGbPUy|308?0(~p`l)?ttFYfTq!_J2{k5oC7_hl zo1CpnSXjvU+h%fU^*U_ra|l3Z>-}>zu$*M4SQKBGotY0?ME9 z-6E%WXc@Xhy+8vSx{KJkFj?YrT5=|jA}u?LW*u^z$EjK_lDIPM2(|<{J~665O3bFF zv~Ld)wLOT@q;kxBP~7OqG9=?lLy|Y250`F68vlb`Io7AEmoyFbmJI41@qn6}A9Eox zR~tO%Sk~UYOf1xJt>LDP(Rtzg6XA;Cb{9{ig3SBCM}nk;ZH#fT5Q1nnN|h(5fQF5IQzEQ1{K@iN ze_2=$eiPdsN5D$EL{N`3b~e}V(`xsQfQ2VbxOP1=DFW!?*`unWMoPB=$2pQAfzUK-9_Uxhufi)6?~`{yN@X4MvOf{#5v#Fw@E- zK=*w7ePW8v_A^|20wo%x!~fi{#d<`GoO!F+nMlmU;H|#u)&$hkC?~?5D>CKI1@EWgMuQvkI zs*TxxOs$0}Rr-PI>q(uM1{9D0Z>B5E&sXb-?Djq7ILxnYYtet++5$v+(HarUxEpTU z-ru%bp#^+CU+%mvl345iGI)7XRWYA@rO!&RldjY}>(9onHKTJ0+6;;R|HBw8!a=P8 zw)>WnLwZJANV+ePNJLx8BHlXvZs`I&?ZPG0Lv8qmhHsMN%OrwLr5(eCS$kl2c76b9 z(zMt1(IR6A+Xlz(>C4^U3UMsu)*4!@54pXsIevK5Wf#B5Mr}sB{(?WYkMO=3oqo53 zOTlx`v*UTR@NUlA-mPssg3fW6K&ho=dq9@F01l5fK=*-5Wl%K9xHsWqL2A4S((0id z+?`LL+mLlpFJ4x+ec{DYkt^64^ka=HE8}F|PKm0y-IKAFIHk9iZR^+{%3@_3&134w z7o*~8-4jxWk^_PnUQsD`FkQZKJD#UfCllQe*Dh6tIwyi@;Wk5PH)va8$g?^_xh8(| z0B-BR8nMWO(#|S*xhSj{9cd@&Jq0$J|JJ6g1JShD#U6#fRF^is7CE91ll1CeSEhY) zK!-ZQ+x)Z+LuU2;!FN;Yg&|;xbtranoo_?ov5PcYY<76x-YTezps9Cj-;DUHxhIoC zNBwu9AQ|NXuU_0(7ifIE;#>v<7vHw9O4$CYMmPc4%kf~9mf+xLBqgggO=n%vkIt6_r6?d~OX(Ws=V}K7Dh4R;~?6K0dGbc-K|y{V z^>JAab#n6X?}dS6!q{-I;Og@#D9RkG{3VBA)X~-izqqs?Z$5srv?Jma<28w+LOa?I z$rS9l$&P%fHueSYKpb6pUm5AHG>HwgPqtHe2=%O~7Cwix5BObm@~QkG=6+Xd));GC zg2�nykf*XKn+f;k`%i0`$pjx>w+}171k8d+haPg5qf^!bD%YAga4!lD@^Njx!i@ zgG{e0oDNx??N~f*cA_!3{|(=M>Zk;9LCnN?!roFi?nXW|U|nel z;BHy9ruX?w+e~Vg4#kX1#kbT6CU?4A*Uv|t9Eqh8O;Swc1BbDJPz+jnp4=N$YWMnx z2bpIWoUQ=NZENoc>{v8t0uH%n4eGVUbOg`Bf z(VF(=ZDmZ>g2A{hpL0d~2x$X?-U$TR9<zEBAUNK-d4WfKK|x6-?5POoJFR z2+x#)OP8B3&x)0{yTRRcwamoz8JBtU^P}d#`y?4T zfhtk_R&}L|VwMhEmJtsr{S_@~;gAZ%*N$Gd%Fe~*A8|u~p=K|6QZOnM0Jj|3thG5_ zAJ-(b*~6A~W>>6-g1B%5Ha_E1U`b=#7rwkMbjZ?)7Myhk?P|vhBsT8Yl4!lC>8cex zq}zHh<|Wrz@BT4v?<$_1c;@?W)jqa%gZ;!7ON1EN%S&f`Gpl+8>2Y>%A>73d*~Kv} zw7d8FtevbJdf`t<60A4`u-DT89Z%=cl%nA_0pw@H`WQ2Nbop`nNyL|P^~tI6zQ;33 zM*RtkvHMER!t2<^Y{`+MkdPO77Wx7r+ONT5BV!NbF63|6;>Z#d)kz5I>O#;qpc;jQ z{x?xQGig@eo;1+*9x>?r_=kiJ$As>gvv`f!^K?1JwKiakCbOA$wUOqSDz`YY{;x;S zv*ldhUZ26U5$(Tb!Y3ra2fXj6D!uca=}+*&5SkZGW^CXF{*T8WAh_Nc3!^{U;_4F^ z$T#Xc3W)y1j^}%u#~vI(;3o-~%n?@-3kn_`nOR#hVrQS`dFHIDu)TT6YwR(NUP`BU z05e-UXzEUDeN!~Qf-(`RH9Bl%I+*g{r!afoP8<08hkIsFb$$zfG1DiuC%RicJE{L6 zYzPc(am3KizQC;(@s*YeVfL^36Bt0d+z|Trz7Jm=XpBz8r9b_#gLOpITX@?W zT^-^~vutv^IzN?9;I{ED=dR}HlMOGL+ll1@l0H3R$*?7*7yL7tCr)C-;*=RtQb#h& zNJYbwYe$jQjqJ%(MAwJ44GF0O(`r^PeU{nL!7IiynnAy+BHl9l?1j=c00mJ=f2oHn zHDbxS+#@(;t4B22FgPt{QHP_FQ?m^IV;GCw1%v?K(g%0on7#TQv}Xk7>&XE60} zv(`ODc*mmn(>K{(@8mI+n)E_olsXesJ!?o0>+6(qK5*k5vF^XQTwp2-;V>S{QtRkfdvgOo z<#>g4bb{0SL~o#WSt9b+?AVD0@YB@;16~24sasSSY0Jie|H??--WDh{b+znPx?aw$ z4#9h8R%IS%QID4MYF$aQKqlHluzqS-0b%Xtimd|uE){)-hmI7!?Ku5MN2R7QVk!BA zwP6~?Qu0metIO1#l;vV<<0^A~dSQNvL!#t`TNlpz*AUjgN@{e70+>qP)wtmr5pj(& z?AsVMs$tJf&qv_K`JD{Y$Y^h5+AYFhKG6mBhPps5)T1hsD0JJYT=3!<7qHu9P*I1t zs&KWs`DkE1VExeUjA%?{SddN--ldIn!A7^sR__rV58Ajl`1^b14{Ah#zw0yHGk;|^ zsR1}hS>43otTs&*du!ILGqM&zXMS7^V!8X0Oq~^*T2^aH>|Mk>OE}KM)6W7v@yFko zb&6F`rE$Ri^ISiFXKUz|->2j}WBkc%DchE}ovA*@-1XggbO>5HVkw4lzLZ+uM@fe6 z&Azay#D%@}xu*4HGZC#AUZi{dweWL-NPPnYDk7OmFMQ{j2S_%!O{z2n2vCI0DwmweHVQw_Vg@_ z$~9^EpO-8Ezv#s~&07M06zZ>7sD1y0=j$gZAU!?=(Wj+at5-dNi^>0y7qhS_vyuGe z?}e#MS?v!Q>tETVyj+r#n1|06A(*0?A?8*Z*4GubSYD^!gy)U;NPYc}s_azFFk0&B zIx!8reL?`d9%q*(A{v?Z>h1!hR0O7Uq&D{6UgO1r^cJT;rT@IA@_^4He;Ie6_$OST zwxasbMO;^-oA59ML6o640$vZ-jHK*>Gc|iN2u;v21uXd}6S#S8RD{C))mnpFR2p$41k4I&^M+qrtX^hc; z&<_}riF0RRyaj%<=3W}o)fqt~*Cfe&zh6kV32eo6%(Ahi)8g3&k51YS`d(7VHJ@33c2;Q||^cu8bKno7;F{Ul$i% zTK3MGzEqrUyL)u${Wii2@3llXH=-+@^fUo*>kbaGlyL1uTZ`Ur)inpf{ta+aYonzmCyz(5#QNZC`;=Zzt5m zYYBN|tx&N&wt_}bv$3-|L5n#w8QrmC=d2p&jcFG3*wQo~c?9 zbcPr&DR}p5?PNcCXR!QeSBxKETG4g|McGpu$5lE9zo~YV&Q>zeIYKvqOOup7cwAM> z%}e!=FkC~eH#ci*RO3}XTy*by+aLpXX*I!YP-K|j;1Wxs>JLZ~1jN2AAt2DkuHPwl=pvyZgQsnWO${vaYLlouS92-=_6G zyVnzB5hCovy2YW_2v6vm`H6z8he_;D_}k>%KPjAJKoY*Z;yP#lcD5u;bv^Cr#J%r5 ztke88!mHYB4A1O7JCXtK2h@TD;B$CNiIC?>(U#UY_xmm(=b~#uX|)I7$B2voxiHfX zA0eBXzKvW7!^z*`A@-jEA9bRsqE%y^f^+%S)L_mJGKZq%fAmp-3A{VV$%|JmWU}n1 z$YU4V?I`TbXu$06kRKKCn-X$(^8F|gDjFI)ep>Irb&%=a_dXwe^$!}e?4C~is?s|L zcgNwI2b$|!nl-K8aK>4WhS7`I{TKG$$TgZ(TLw>)dYr9v3hcI1 z#(`OJ+P~uIkv_-JII7N(7WWeyVH14PHUGr?UisFf{(|*$Qj50zSP~COfqiKxN&WN( zm@uyieeUPj?CEwh*l$;S_ES{gyWJGMsp{S-;fRQ~>owa4H4B=LJ1MR2`#Fc!s;B1L z%hL;%kRBGcI?-ZVgVUQ`s^v#|bQx;g^=zB*82pLrQVQb~H5(@M=;V4^qK@EJ`X)E! z_>;-$U&qsyC!7r3{cIDh8`B7=WLc}yOAh@}l2)nW@g(_*Vf|Dib^FZP z&CL-X!>^XzWA~#h?dan%U`hw~_GGt#sgX!KrxM~L_X@^O=wzR)P5DNmAV_%IiPfnC z+zz&kKU1jL9`&Hz_|hlc63&@Sy6TnyUv@7KW;SU@vFf>D!Ub%{ncfknPe~bP-WWtq z{iD?gv|?HkcyLD4+U3j}X;~+hhCQsiC!^IIN~;{@s=}=&iq9XnQa#8+04*BrXY||x z#=5mAK!a1O;Oi;3vJG6np70E;qdv0xKQ!oDX?vKZ(RIHp-g|AmDYv0E2Do!@p-`>O zq==6VZZ)?_i)HS93rcK3r1bL0Q!h>@CpV{V&Ci<9Pg7Gn(CmKxSz9y9;i7huzbtI$ z0l}5$(Kqok@447q11w{1e{nrq8!me?na9;i-gpNWTkcK=o^KROo@zt`RJL^wUwA23 zqZYZH*EsW<0u=N$;6AdEWz5LV)79A*D(g09NHLkk4?iWd$nIZGESwciwN_F5msda{ z#VTJY{Fg1y6hn}V@18kcnAp0xFoL(W9W9TooXGtd#p0;C8P{3wglN`fLwZ2zXz>$& zB)NX&YCaE2J}9Fn(lY?lvpV|>YWl?+ z_M^CuKC4*dQTS)L53{5}ChFt{DI&7%^2&`ywwm+R+Y2stpR_6zrO#bb9a!`6wzYXZ z?XNlQTPTf%eivG#Hb*aEE$1y$P_SB8S`9PU(|HtzGgpCKX?^;4h?+^jbR;?4R| zY$|{yUFpu+UV>;aZMvaS{Ch3QV|*8&Ff zy@F3KqTT~v$VXJ;*^{dY$8ECu{=R;%(&oY;%{sRP^v?Wc`J*vAlYwK~aY^#E#L~Ps zR{a;}4?DJxXFq&|fFSwJUO*GjRj)4>f&w2g%KO$O^E74-=>2WjFc)oEO9%7XH10_M zpAsVv7FDJT69jjTzhNuFD2=(G+Ky3HQ=;AXOAO7r=0qK*56bXtTUjCTxACtwW>QSv zAKSM!1wmGHqaLY0xo)>mt;gcG{gQE_+t3Dhz5-(y5lez!AovmcY961~&-Yxg4o-^+ zc^jXULj-^d`H92x{uMmU$<-n*Vd!=noV<^hi3l)Duq(2P>9ApYk%(vhGa{NLlpvE5 zH`Kg}KaH~1@ZEPo=`d>>kbuUxZt?CoSi(uJ(&)(C8=IUcpKQCXYsz$2(pDrtPPn_? zqVZ#D(+61^@pxcn#&G+6Q{-Skatt{nhqF8H9cl@|%piUG$I@e@oQZ}a4dntSW}8m`|98eW!! zc%fxs-Vegf>J`K0g05kMV}L~MFH2LHMUj`&zVO;Lx?xI?QKbN6k&SouU@;95ktLQJwnCuw5(&zmU;`c zJl}E1nHc8>w68_DpfAjOI*ltdF9_Xhgg814z%ws=(%JFOH(=~5v~~|N$F}p%;oE9h zlYezgciBFRGuo`lq>Tffp_{|^Yt?#=8wSIjQ0a;`i^%I2Ltn&D-poKVLbnihi)mTQ zbJzJU;x)|wD3#IWsAjzD76(S6s-nUC#c`two;epkvGBp0`%i8beh(iDxtKk)siyF$ zuo|as@?q`^CyHZ!LvfvMBD^^pJEsl~vKwL~y)R-GHCAm^RolL-5l7ard8r+0te~Qp z?@r`A7S*V+3LCA>sL2VTBR0ttIi2Q(JfBnjFa6fqCFbzV&v11X61GMGR*!|lTWeu zj?=*}Tw61nz*2k#!%k*N^(s9O_9@-9>CeK)j<4;M0$9%4jE1H?_w-2DZX3E4X|dYUn!9S6FdlX4;km1)`c^zf zfUv`E4h)MItjkNSunkJ>X(|ij?xmlDDp~7%w~-tC%HQTApE?;IcMQ}nKUoGa?`z>B zDAC$?f(__7%d9gFHKJqLr>9)M6K%Qa@+Y%aM;)*?O{g0Y(IM$&6kgv}zs6>rFDcG6 zT>RbBEEmJ(Q$n|ICgS8(bvCr={M0T>stIdi_!W$W!t7@80i1fs*MJIb%(9*yB z=dqLjj|_x4%KqKxjNrMO(orpSn5=G4xvAKl^0hCl`Q?2Unf+>A${ng59`-@-66y~8 z1z9u=RsejZO<_{)MZEA{Q}w9ZFV@}_={KZ2gv^sX)G2P{A~eYa2dt<}DiUPOrrNa2 z$25C#r_)eJU;bP35jwfVL2PGEYpRxgCJMZ``)3GniZ%-2NESwCE%9kpZQr>@?tIcq zf#^$hunAbOV?T_kzC1SnQ&M~b@p>7zp&)(>1YWF2wB|oPta+pDpdEd3pZOK-NqCNz zt}Ph)N)4FxuTG^51vX~U0=(?a&Wp-bwLWgN_Wf7&3};*0rqrr#*oeIHBKD}h?~J*$ zsG(kUj1hP7!0IQd-oU!137iCEgYVVN!0ffUweY_zgUE1`R`t;J?7b>CT8v^3&x_cpRGiS?)6stZD#8WjwHR8sHEe!2UkjH_ z6bRclhl;Ry%RgL$1}wCgLw62^HOVisV2w8Fo(t0_#KEGAEa!+1u0e=8Q;&v6=bS;1 z96!FBQU`~Lu9guAO%>tb?D37q$*dwkA3^RY13YE*+Iag4t)juglMqq!8Qw?;UT*T-A(9Q=PEV?ly9WK%0g&+~9dIjB>OO-yK1B2lKg9 z4P1;Pck){g!7@RS(VEue@_ijA@a5KWR5%EhE%g&Wd(|WKbYgU1H+zT-2V8MRCi6(I zspRgpo%N03l&9Yk%0`W?F{mfZY=(Y`#kPRl49q2KjGz=~c=fU@te*DetjH;Rbk4N8ip8osFI9NDtKWR>z5log#IYN-#p#M8w@LX+6rM#R#mkT_fN>U&^P0G z#h~cWz?$q?{p@8 z(`MDvB|mgUNjeQaw($5U7A8-;oP0pA^V$pun9X-?uJ?G~_&QxgXRz+Qtv>iqAhafl zVN+>Be+-8rQ1z40l-{nvNKbN_9vDk>o}|V{#ctH#?OwV0YNak?)q@e5gVudqL>jeM zUu>4UFK6&zsiD19pjw|zwRv%N%LWRZv#lF9WSMWEzCNk1PW@Jsm(*=9%UvuV&&Bykok$0=$y)@p{6YbC8 z?e2;BNlikANZ34P*nC|h#n%LZ2>s|9U^6;=IZ%30Ek$obxbf+Wz9wySd-%RRicG{6 z|NCF?0{`UsGX{IkvjL_pDyxZVAfzSF%9D=){ga^*YP52!?u|Z`G5oVR>uP4Nj>`tM zshailt)miM*y@NVaCCoF4{zr%_9h~(vR5SAx>XdPtYbZNs%wJ{Gl1Yqy@l!C*zKdQ z%*jPCL(5-vkqo5(^iyWmvPQStY0hk)UGTz|Zlm0F9?cZpy~jcspyjj{%vnwauIXqv zrK#D)+?jR~F`%QnX)0PJq4Ni)p|@;l$Bu-lsBBz)Y0+Tbzq?gityC(GlhKGI>K9`p zk;C-iu7JZiq?nk9ch3vGPbs>J>jms+vK$lxMBAzZX9ORbBKC3L>?FkP6K%k1e z-(`-lMxEWQok^#X9ko3#RsQySl%V>0%+92^;PR{ayMG=MvMw#OrZ*0G7taevgA?)t zhmo`AWREhMOt@nd^D#0x>hOxanh|u_d>A>d9;S>bz)X0Ct=!oH*cU?FyFKL?cml8V z^ogX>jE2t;R^ZU|PUA0q5v&Um${PaE%tJ$Yr@(}`tl+}9si&6Qxud@`1C*}K2aLR+ zJIq^GoN=+i$qe&*sq|ILKks6D+Rr+KIES=`8Jn;+{&TrdrnFv~n7`)Yj6?7xZ%3L+ z2TEUq4BoP-5M8sGXU=G)Ic&}M{??XWWp6|WHrHA%!6v?e)MO`QC1th)D)DGlSlims<~7Hb+b$az`$Pr6Hhwnw%;l`gc~d z-VfXFrR#J;=S?%j#1g-JJ+};N4EuJ6z3~TcVYS67USq0G=T$;c0!V9Ls3L^VixYaV z9Ry!%<{&>7c^$B8)0W3N+#Xi;tJe`UKRj4&?rYyHkW0>Dan8Zse6(98ws5lX5ZkE6 zTe?Rv!0IdkjCG37d}4S5m4H2xw#VfAr&+JtPc7XH+06)kF(~gGa6&*qRR|Mr?zv}q zroPnp#2^C;h4=jrmi#wOzgGp*jl>?flCkw`-HX6Yp3hU3|M0?nvNZgJ7a&9idQ_>+E*-PZqg! z9bsP=G(xi$S3qEJkWHGf!z28fm<*2jRW{Y`d6Afh^uktEWA0~d7FUGgz6oL3)jy2m zBY#59?8kj!+C_d+$3pGp?VqcO-c#nKse`|Z_cbav?as?=m#asd?)i6iXWSK5Y270t zRTRuolZ%WExMM4iRNW?S+k)tvTaTYm3%*;|4~c|CRY-1MeYfm0@vklCEj-cb;IPso zA|b=7uagQ_=YLnloJMu;r5l8vBQxAY#g7W6iNhZt2g`~otSsSr3l{a=#qqDJS zSB`DIy8+8nPCWB{kz-brV33M2`|j*w(BShj6(cF3gug5pdHf;b-QiqAE)V25vR;VB zbsd9q{7ehvY)_snjW8GjR>oX!fR9ZsZ<8tm&GfX!HYz`eIR2YC{RuDW)G@}`uenJg zCfI6!IA6)jGwn!!h^@N}kAE=l^aP$0Im;K>ih4(tr<-@IK+L-IAp$cPbzr1w2NOxA zIe!o-*Lsm0J<54hE<5FJS~z6l+Dua1obBERZ35EK;=&0>JK1W{gaFiz{(xp|$EY|l z{Zq9v5j+F|)52KU^_%80MojL3pSA+EQ2DKL=I`85U!Aa-*W7#Qp=wK^iHCb0j@wN3 zyN=N_I%4hzAgC$I?j?C9H|)YotCK@e<_~n>`Viltz_js5W-d2x$PRC&6Z`DCh5)mC zq%FA@YjCnpWVGlE;0y3V)#{g}1`%fZ?g_%Q%6MF`tkC{XftDg>m-Olh4-I5dV@!p{ zD28mpu_gPw!{D%?R_(THZ~KWafCBo270|xYQXP{RQDtR*2YG2hT-U2&UuhT^VJdB; z?ieW@UuU#6t%Y^1J4+q4&$b(0)N&wT8;fX^3a{e!q!5?l3)s5rIA5)Zxy_%H^2QI) zHIH>WDU4Ve&R)D$CTH+L=dy{&D!>!@(lxelTnac$#Y)szSAs$3=$>KO%{_^kOU!!D z>a&;ANI&E8!vEH0G4-06BkkQ2@G>Ye6QenQ>!Pu)YRx+|P`>Lrjdmw~_FH$wd{rxQBi{UFakk@v8&C`E@q!-$d1}fxQO3V{ z?*AYKvIajFlyi;u-rMuGeT8dajXES^eXXV$&nu-G8xtyxnawOF(aeh!NPAJUcy~ia}U$!{W4=)}(IMFts%~E)oSqIv&`D~8UZ8po+ z?BKm)%8Et)vqtswbAMULBM6!O7X_B>}bT+I8q22dZlDVgcEnB`*L9H7>w`_uoqVOgEWsS)=8LX* zn%gUA?9mc`{tj`47=5Bfs)=%l9(pn@+}MnG`*eIB!lYg-H{3Wit%q;&9SN%^U+JFM z2Ifb9Sz>wJhi9`cPLyVR_TPUcDOcyiF_{=#Rwkjq^NW^!a-NsZkc6;~f#T}717DYK zxBCje?QMQOk0c2F61IHJFWAHs2QN89TV;+rqmX2ATCj_LOE(OQ{;CDf5DY7)pA2<1)LF@ zxV>e70fMU4n5p?#TR=HWLBhK%kG(e>7#gpe85dOwH5Ip0m8JM<1#8kq_DTriNd1)G zP26Mt_DJfb(DZp9?6>i6JuV*8(u-cyX?)GQPD?rvwc=k;_3d1dA-{6v%hUXP zZ~e*MpN*E$XY2Yt)<*wdp@1T0Dh;zu{nhe6DJ{gg!S|mAdHv34d*9&AH1}q`37oLt z3(dA4&9DVE(0=`$931#AZs3qc-x5PLH=P@;E>5K)!Ff~tl5qX%1j7+UR;n;xK;|7$ zKe*>BO1a>BE05;w(u7niV(Caby;i6dI`~5plboU&B2hcCpm-(r1}iyA46X1i?JS;#FVoV~z1iEB;+N5HDjg-V!K)&ihelgqEK-KPXaMlv*3 z_ecQsMZ%-;v3ze#U_hS0o80^T`S1W8%-8DEu4(JO$ml9LxZ|M6?dd63?IX{XaK%zp zvdJ5x=i&%WrHm!!H!&%2}#C6GT0X8NN%DLn@*Gd22Z@(@8U?9 z203FXcBya$iXuZorkC*FDdsP3dhrtBl5KZBBVmnbkN)LAdi?U0|74H#(U0ctt+Ye4 z=76RPN2#!CEW~I>Z~PYy^mE{x+7XQyCQ@;?`9BZ}dL8RLebxtGvx$p=@N(LY4rYknZ6 z^HSC3p_&Hox7vuk^`Hq#fg$HbhsOCyc6mEA(AuPCOgl7(=s+p~$~NM&C2z(y`Qk)A zA6kzcWL1=fDVB^aY|o@fskm7u+utd*1S%&<2vqf=xBM4(fx&U)e}g{knj|!Kcm-M< zBq2=VjHlIn`m5lNHJ%Z-_7mhY*o|xV#iSLZTP-|s7Ym{AXGbJxWZE44#kb6ecWJDb z;3>1_WUmg1^MBv8b}WX^fF7OCj61WK8Cqlne&xhXE^+5vM4zt&@e}^Igc|}JO|D#I zZ!vZQMFJe~=cIt0j9Um(g2xdxn$~LDCq2GzRD&!M-|og!5?382I?6B!keLg$;X3#2 z{}TOQlnyHwN{YLU%jjkqAMwMd@>`Ninj2Jp)U@AZv94gw2mez%+#td^dvja;{ojEx>54#`%Zs>_MTI| zRn8GozBIq~5bh6qT9_%!ff<1OL7El^qG&cd(2d83{@8g3of4zw-wq$}FB8xgs;MSM z5+7T}M_f9Z&Q04OeZ~lL{5ykjrK+!pprXbdq|6;aKEzX=jXO3Vp0FjczBZ>+CD=9 z3~b^Ahus}E6CuC+uPpAL@R41iE-my6&dYpYtK`^BWB2J{d$m~i1}jSa!|BH(S!pU^ z&Hp>*S(;Wga;A6My+;6#vOZ6tLYdZacMeJ;<_K}ux7|t(_&n9E>J>|NO0yT;^elNe zzy4c)H^Fsh)nUJOrpVUPJbkmQAE%o{1^gS}7TzfjYdeQ2*^%VId*jOE-bQd_>^Qe}CVR+BFEB8T0*( z;sO*r1;+LHew8-6j>JMnV%w#kx*2&h*V``UxG(v;f^UIU+=t57ZNX;&$L@DwKrq(! z|M{AT?MQ19XCco3YRJ?MYLn|4Oe=kPE|e!IG25Knwt4W`sxAvy!RppJKA5Mr?~K5y zNe7huFT+x63zhn zw4X)^k@weB*Z5#v)01flmjpS?#h8OP%Zuu{^8w;8iWP2b?LIovV9hgDY4E1s zBgNKMKw4^}dGQ!%ze8?qg!|Ay1R|q11l_AE=Yv8?bacoL_Kft={I{B|14wrvt6M`N z-Oc9fyti`Mb;0DFo*n5Nz{oRZ_pVBXa>4Oq3BLPV&%@*&7XDd^oEvTJ z$c4X_1W+tWQ|hg#i$@>XW_cb&DJ#fNyUw70+HYI;7^eDk7Iw^sqCDa3i)fp0_>`N7 zlNR-oO;x<{8pW@qG_-z2ZJ!X0Jm|e3w(GdA$ZD{~bXW4Os_+*+f%N_xv-+1rjA$S_fZT0I+RuVxGeJNc*^D2exz&;- z!lkfOlW&Itkf;X%&akd@f@ zPRxgI%8TkV$Ic&Lb+QW_nd`3ss!ab1i1???<vM-rn83pP!knu|oW`a8=)`=0lRu zsNG-GBXqM82kbd>;V8G-RPgS$cqKZU5pBieU#KV2k){}QcC|}1?&DtB6vX!Ac$R1H zwVEYn4e;EQeFV>DpnWTb_>~M2dN@yFyrNU&V`fX_J#w+&63TA7ZqK zldMwmonM6xLCLaep3k`-U-`1X zoUTr{A8%k}SV$(2af&EcvIVZcrDi={bk?;fz{GOwp!r=NM%1nVhPiQ|#{1k`=QM=Uih!W6zh^FPhD9wwClvq#!&)&h&HWfGCGNhfabK zXsOw$fe^wduvLH1Np@rV+$^S-?@~!d7bXudTkczE9`CMAX_^Sk7#LVo207RI`i=Ye zpFx?i2DL_AED8c@+W7~f5kD#jPiIxF3L%jFG!R(x-=xH|K&R2szA5|*Km^nK@O_*a z1eX2N_s=E^%L%bi4qL}Bc}g*BJ{Pf?Xiu)XKzs2pGNozzRsm{a7yu9cwotEC_z z7}nZb@kA|UOj1A@Yc!hG5ADoV4DG4WC;Y#Ow>4gU+!un@fi!1)9JM2pgD$5uJ zz=eR4V^gk{EdI@^v29qkTE}`GulS?VqNt*;EwQa9ymz-DL!5um%?3?MoIXNzUe-3y zu{T}}nKxCksRvb321P^4TZ-FUEG4-!!VG4X8)Z^@h{jvxt)h>fR)U|N_lRoi#=+@D zSJem)>vPlN@S(yD@2KpxwK+qlhc{ zg$n(yw(wko_0Gsb{>Hf-tri;c{!V7@JXX%C?o7?@VF0f4>$|s#DN}Q8sghGdNeFe|l_R#*n85#h@*m(JDTknrS8t=kb^kSh z7X|iqnh8#p3L#f;)}aL_?ldclE4Q6I+sTdN^=Cm*!x9yQ=mwoawtM|Bd@m^XqS48+ zDN?{(Vxk~j^VPoWd`au#a=!i*)2d>{KM3TQlS2emKt&d}EmrMz=Y3b7I*3?|wX1GVhq8Kd zn>=r_4I}@i>ALOg$+^tm%tp{8t*B#>hgR}gx;ylMLU{V2Rax7OC4ejvHP;JGP4|Tz zX^!iryV1NX_)`g=*wqKBoJ%VZ<6W>EaQVSK7MZsWS4>CkviSKQ9JP7Jw!PO~;gV=; zW3gR9jcD(@daa<4;EmolsEnQVP(TSd+48llU5WR1K@oo7fYg}u8zm@?uPckz9jz&j z%ptO6i*G$QJXpC?R@#exi^=Fj|C>CsTD9F3y<2L{D#`w}Kx!1UP9W>|Ja$TFvsLiJabyA#_YZXFkZ3jpGNTJA*v1OI@8WXU3AVYxyC2y-_^6{s!5{sZ)v zV$HI??*}Jn->f`IouYmJ6gTwsZ4h*aLufN4a;KMa)V3x~Bo~#G7YC&S zJ$#KoH64S*Idl9>#GKgZNqetLUA?USp1KaOcKHH9?LcbeVtM+K)0TDb0yt(cgeO;y zH*K`lqo=2+L6%MM%k%_&EV%<#3EfIAQ967eO&yj}sCy06cllC@!?%f8wpz2oz^9Fv zb?l$t%c@7qt(-NE{|=Zsr0TSt^|}azZ5!fuBU-+CCbK>87?pIePdgV#f&_(#ER$*0 ztrXme4zP$_C*P)f&n63hPs0TW=9Gn81-kbP`gaUi-!NCJokiqSIJBd(#zACMnntdz z)HFW%(a~0~1}Di%%byGwd_$I@_%L1jE}V88OY#vCo7q|@nGfuBn9Qgt0o>^tJ&FEG zk)-rm(X?<#&VMh!8eK|3#~5OD#%RZjm3+GG|AObgvA8W_Oi)nyumSKsLV z|ICCeb_@hthJ;7LgdGXWN3(B&--bYc%kXcV@2Py1-$ziM00xO|v!gWddw>1FaaUV} z;_{7+{@*fxx%sz-xs-GA7p<9SrC>G%$Rh`*9(L$)mdyTm6;(VcK_JKsL|#Q~m-ULi zGadaj$}ic+^jc9_5AZvcL=fhWPtE?M0-~@M{f^|ib=>T#6Z=@jVU_?pW=z2XPI;lb zyhcJnCyQ^*LqgN7J<(^``10{erKI-OW9d)fy}MMlujRk-0X$95hfDA&z_%B>-mbWm zn$pK~ksveGCAJHk)0ggE{6^Rbr4o)jKL>S@xL{A(Yk)&1*H_>bB#j3XS$$(OKP=s4 zOW&1Zm{VFF*q6Q4gBls>a)W~_XSGnHY(^+p57x~ae(rYQsBbSum>6f}^ z4@$&L=ESp#gNBQlzK`<1x+QFu{G9ufkomkC2#$@9dAu}fskUcd`*z@+xY zZ)tPLAXX4ko#8tl9V@-bSzCiZySCinD-Y^?{((uk#}6p$tYr(-U&?Lby|wPpHu_ZDYIma8S? zB!dPhEd=%Ft%S$bJiyX)L7GgmM)W3mB~CuW{%6B(rPnzn1>nB7yVc0QHywV|rK=Am z1prxE=Xd6>Wos&pL?O6kX1cePm;da}cz$)@a%?VxEO70ZX*e?#C|1*{`1}a(_ zYg$*_1Z#RBOvRZ2fHsFvq~JGo)?!cl;jirZ`2kg;@GTfnqZZNRsgnmH_BQFk@pN_c z#db$roROr9GIZuXb&kPmd#{y-l{zJd{UKzzi?Slq8!^ZyA{QSG9t1EEs#D}TMCigK z##4b!5(%Bt?zGafd~x)yT@7Q}zBWvjb6op4uY&Fn&;)kJGRK+PZh@{0eS3--E^2Ob||ep)!p{kuPPf zilwRV^K!3F0NS``rdrxuD%qCf=CJcE&Xc_Ifx6$X?o-sawy*+Cko|bV55_D39xlf2 zU}p^RqrF~3^ruvm=?`58@u~T$eIDaG&aSVRk|OCoY{HC;WTUm}Xq{%Ft}TE+iIF(T z5H#B+F9Jp($mIlQiI+^2+vDYhJfqSm$ZgeFNyTNyzM|ghis^q0*SsCF!Z=DEy3%91 z%}{?}&@=|gb|uIet}LB!54gLM>z|gf7=SE7rsud%w%gu+S2eq@u_o*3+i3(GxzFX} zX2^;{F#u(&zxo-nSsx5GHU(X#@ms?-FA}1s_Y3A?L7V!(o^W~-Z~v~Awr-a21pmqs zu254-@3hj*&U{}EqFs-34TpsB)*B4=(?#S%8LLmK%QlI?IzXj5earp3RFs~pt!Pfq z-#&z9&C%~SceIagS|;f2{zzYTb5d3`|EeVQZD;(gOn7^#g0(yaskqcyd{Rhb^MdE8 zk0lu4vag#z?3X9;>50vIg`1_(cAYTlA~W6y{*p7c0U9G(cN!FG=YuR$xE( z+V8ni)nZawubi)K81%}icTN7)ST*k#Ig@n1+{UbH0AFj~Efq3GE*h%DWFVlHkMmw|(GG)m|k)K21P$m(St0c7gh!u48@$*v%_s zXc)&WNazb_u;EP|4|TYvYH}#&b5>H$gYpcN+aQ+|Dk-_mC~ycf6C@w7*}6&Enh;M) ztx$3}4zEjuXx`Sdwg`*L2jZz|VF*v*gyw5<*X9sl^5=aG$-UxYR=Sl1At*`L3BTsU z^TbSvYKBLo($zsvynzVIl6e{bbbecO&BxLTg%H^f{7zt0sJey@`PhYJ99!5F1 z+eJ0`f^3<-U!k6UwBpXZvfshYU48#gSiBKhVX@@2AOM|eMy@=`OhG>; zgugB+dF53)p*K}6vb4CVt?sGu;me2a1do6&f*itix;WEJl9+A(wtOQJwU$-av$*r; zpa3rEkqtcH4O7sP4qc<)LaR~muWktvI<_b%K24_&uj!+8$BxYMQb8nWOH+UH*?GavKZ&yQ-Oy~RW6aTzP#|u zg{1U>4W~Py1o=8B>tR%5`0<}6pQbF&!2*}atUTEs!7`pT&pXie*!f$gMa3Bea_0~6 z=PV2v;Xc8^j9yDz&wbcn^~4F{M_*hGX&zSKD0}A6h|ai$2<`bxv9c zeK8kuCwG}KPHIr*96cVP5`q)st$qOnRIE~FZJbk{Hbjw2anPA|k)%UW%Hvf9TNN8a_ zY8hb8esp0elC8*@`jc_RjUsRb+KpNFLba*al@E$vgXlFX?cNZXp8gZ>Us+6lRvCOS z7(D!ZSZSt_-3JcX3&SpYzuwL_g6cGl!Ejo+im~!HFc)Y8!nf)MQOtEat0tbx%0$o3 zmHYjTmZZLmxV!qn5>Lm=0@K@q-9J+8mJinCJnWtnWx6MC*v#GKY1XYqm^5LWMxHNU zvBl!}4Q^4V1%I3e8dEtZAN!=oE?$gzT7@`aiHm$;`Am;#X>WdKGew>BJ9-AC|$hCb~& z`)W3h3E-qcFpA`dgiw^_)EBo-8ItOlclC8EW>UZ=JSp9KJ)Uy8yt3*>QEweUwrU>p z3Hd6(Bt;!#`Ydn-3taVn-^R=aaAfv#r)BAl8KSoCAoVMkYM4Z9}IhU&=2Vx7o16%uEF%LxU%0`i5WBd6I2^|XEpA|U=Iak#`R$)^*{|* z+e6iNRiL?nS}?sDdDlJ$pBEe|@uDsjZIId`!xlc@(Efwfg%jjFB zx;xBZtD_S6PDtod2er4(UNqCHfzXy!W7b-BhLP~UV~<9W4{Ihs*d^mak-qru>5DiG zt~J@x!%LFI6WSuL=W9&t@g8}vS|1K~((XGA>-{xch?+9vO&7UzzNg}TarKjecp>lV zd!+_*6za`cbfow-N3GVGtG~uzF{ZK#4Vd!@7by5IH>EBZb`Im3{zEEqPg8*Y||NuOR1&&hx>3Ka^$sPwoE=l$%?i&X*HJ9(kp5$VtqD? z>=HA)E-q5Nb2*lO10w4^v3Q#<^C4yoe4PE{kM6BNG|Re`elGOoU^yv#caeMfgy^mR z_7>vJ0|^U);V7ZWeh|LMZmLMHF@<`%!a42_2y{k=fh`&Nb?G&MmnvE7>T3THxxrTu znzKWHd%}Bb7>62IhaK#|Y!;a2R;Ix2gXQ zhrUKD%3bz8n1he$Mzg$jQCAwe$ox(A2#z%CcffzFA^CUK%kcC7Y6$@$z7SUxZwlm9 ze{O=o1f6vSgYR3FdW&=MC`-WYlJVFKDZJ7oWA~NKTPXFY2Md>;aJ^8Te1+P5g3DQK2ILGS#pzJxGl&Mxs*Mx%ym=6|m+?dp8|(DL5hO`ttf zr&GsMLd9i)a)$9%NYUbx%EiqH(q3})%c9WKdI zi2anP4?PvPJtJg2FCF(HjcljY#nG#sWPoqXg`e*J-!bW?qwN_5Kz-vvh@W{DRMaNOdcfWGB{W~ zYcX`<)T$7rPPt{HUs!sH%r+JaT4asZY}Ca6z`We*siDjbmgnsDsmInKV1vClh%f0{ zy7W{InRcxdDypFvXkZiK)ik$*hk-_cjA`=yO{6xuo)&D*7b`Rm1*Vve>UV}=?~(* zi=Wm#k`p&-VC8+T8OOQt;FcCIeM98;QJU_f11bJB1&2|GQSR^hNC8TLhz{#ap;4*& zs`z-=lboVDr(5E@54vO$)9eTT1>C#R=+rMomA6qzUyG2-AKAZvVU49B#MXcPustdk z|NJ^n9nhxwTt_xIeqiQ<6HyG+yS6ohvaJfj{I zkAOXbxjHsrmSqD2nCVGPRz2*j*37#S<5dErw2HvpT@M!(&4w(*8^^{|GmVUrpqvEv zR|r~;t0I=NxHx+VsCE#%3utlL<_1S1S0l#_XQmKP1;sDJra#138oZdU7RO2v?N)cY zRpUFBUK&7WoKPynrq94<@uYqli5g!bEp;WE{{;F!M&zS%VjC7j0Bh2ESt``cD$Grf z$+RXmb_$7)?Q^sF9*-LWJji~S&Ejr$^@#Swv(KH&x8Gdm(=6Qimng`V_WP5x zh{_>O1$lQSO8sS*ELE8KL|L>QAW~E3?oX3kV$OkL`qCVGdMs{L+ z(IHC%OF;V#WD@OeFO=<;w%{uj#joqwct@=@h9jaQ&%0y3&Ub4Ctaf);w(GZLmXzEr z(j%5oJPx#MS(X~D`_8`bym!^@(k+I-SY9PFfojF{3@NE7!la`1t#DR}vAw%1faq=6 z=RR64n%-oJCxoF7M;Tsya`EE)Bv$o25ZA&{6$&`O6Ua?ztI>2U#Y!PA<|k>#MfLc8 zgEj+mcOwJ?yxYKJ-~3P>48@#X8xaZIBfA*aC!8z3{&My72`Cd|@q2|>pB+(r!?&%& zChAR!oNh{jig0By48Cre6Jw;jWja9F*d#eA{zY$_M;H9>7>vhyE+9YGhB#?cDf^hj zUKQbj-7;(*FyPWk$#vsQNo-q$41Of=$s@1Nf_ZCj^AXQpzsQos3!USBa(Zx^&N=Y5 zH#ljo`!s9)mTnWq4E}`~BEljCj7Wbhqc|lKG_;j~HSk*oX4`(jDrpWLqkAU$VdX?F zW`q8(YP8hV>7uU3G!ex)9G7?=K~FXGq_><)c3QC8ls?^SIP$Q3{=%|sRRH##i1(C`{IIOj)dTE zL*dStL|{Bn#j=)N=x8EG_WvnXYT|#?3fNr?+m*e*LBXy=ScqISN9 zQquSH7UR&37N&cm{Pj>$&DSY6AYa8OwEbE}COxt?Tv*u(T|4HOTg&uF(7_)k;n_E{ z)}>gK;0zq(HX!bYKKW-y(%IVOHZv{$4YoCOE%A*bmaQ5y`M2sg@60ME)MHvG2%hST zhibp49*yV8{&KtCLy4u$$6qQY8$L46!RmI(NBR47It7)zrEv+dW-;FXiJvy{(r|fXZ=~I z*TRDzwN*+VY|~rIn*Mjp77tt-CwlaKZ(f*1cAn`nj@C&?cWzxE-<)HD@;&Zj|7!H3yim<3WhbB; zigPw}{?*v~sZyNw&_g=S3p)HSi$?Ok(!3~O?qmV{!DocooV2oy;yLt%Nrv)@DV!f7 zxR&`e$hZ6aizKPmZwp|hK24nHe2l4PlB{0mufIffvpVuBc-urG!Uq{Rg8I)h;4sls zT*4#85Ep)ENTnWx4pq721vVcpdOL}uo1ZsncmUo(U3CxeDU<|0u(&<8=mGzzfH8&# z?|w~5m5txE_U_tksdb6qpF}r50MGt-erucex6>K6M)?@f->*MKMiXhVE0 zUPD^nP3zNC1pkfpv9CuZ?$=L*W^JoCgSU%OCm1HJ@3d=%{c065)M3QlE7K~8nF!yk z;rdsfLDQvU1wR_1En=m@T@%O?OK+M#@V->$ks5jP9bT51Tv4~)(E}1un=h(UsAOUH z%8oOtfpbls;l7RONbpFRpr=@mm%OaCxjHW(X3!tox%!+ke^TKGSxS!8`2e>TSk?t6 zhH%bg?fA9<=2`#Pr>)ziB{*w7oGLA6gv_o;`OtjQ@Zr}l;aQ)pGzJ`b;;x6-DvdUlk zJ0-<~@6dcDho&hTgF52ixabtB_MX=K*3NvpusfTpsssJ zT+xQkr6R#^CeC;b_sZjql?Ket?Qhv|PBB8ZvuDx2LnZ8XK#A}LxL{xg$+cv}%T)K4 zH=T>?XyM!9=H8Vum80wi87zal?NAFq?2aewO3E8)zsvOE;}*KZ#j}saOyxh>&d7=u zv1cUxbXq4$-C=2;QB7XG+T~1pW4ulAqmAT2R^JSaT4H|RN#}ZSChb}49C;q=?zi=m zy5ehg5PtO4uTijL=486wuV}Loq_d|G)I5WzTt@R6?ETRA20c?+ybzwXZ9NC8^PP*{ z;wI~G!cNwkyh({0=-Ua`vi4p%Y1ApS9t9k;9&kQKqaFL-GrDOWSe~67Aj0y4mvvWvB@|?vBA2+UsNv&!3GwN9VB0Vq&C{RD4JOZqMC-6QVC% zxL`W3kDRmHlGGsC3y!uWK(k+vZYr!M*efA9N}-bune^?}t+vFnlUhK_9Ep^rm3-;? zvbY(Zh`F*(Q*`SA%YxWqu_JHHa<*EO>0ezRB$v9GgvIHnF996BWsa!t^Pg2ELn}R+ zSr6E%3|;_AHPLLtw%$24;B;x7nA_2>qz~ydT)@=%$K(Z02Wj)$^&jODT+>4(S^=kZ zgGhb}Xy(QjyWDI;{zZ3r3sv)p_us#*?39`uAjYfUmjl67xRCRX7(HS!gwG-LvnooPOyow)Q*g?CII z{K>u2!<`T~c;L&h-UfG$Q+W4#c}$+{@HCc~7O(TooCu$>wMK7x$GjEu?i9Q57_wp( zH6u3CaBkQ|u>$!W4_BIw**NF<5 z_}=P2Ux>9^Hsx&#_*J8e7}*4^OjFBb_yyLqB=FmV5rOhBTN6Re=~82=2P#9o6Mpu= z+0IjSc}-}%U-}o;hYyc23xZ*GYR>aILSojw^0@b)Ct5U23*q)a`TXfuw1K3eM+AQ{ z=+bn~`Gg0GTRo{4>dNeiwIO2Wj?=|*c3pjSD|b4)w;UYO{)Ra1oO=Tr#?zTi zB4YxE6ILUyYDskg(>z$reO@~z*Fj4f$!f4B-gzk1=WXUb+g zhp6Rc482s7xMm=cftT;4*Kz^OvJt@EaC)#A%*AlDZxuj{c-Bz8wF&N|WrRqDa*!J- zYxAHi4eA8llh2aW;%%g-XPFZlDNl}a_qC{CyDLYK**i+#nT-|ka<+TTd%a8aLeXtbPiD@fA!rF`F% zSH_{-{hzxsi~EDo1<1t_di?2Ej!_$+7=gS#igA zJ_;FotwsfjkxE|<&R9(gz1kD9fb8a?Ju>u-zMNa00T3Np@adv^B4=^1mJGp8xpghX z#Tkcd+2QaR{=X>LM{ka4&}PhFVaf+z3JJJlnT?A{8^W;cE~zN@c+7M>?|<&&1*Db< zQz@VNoSse}7_ldK_QPMzD0Y4|W2``J_{*pgQJ-nc8MR)5O>%!93_g5tz{N-^W{h;C zq4qz`5~RDf0szh! z_D5GKJ{34JM`=7^Z8E?261#X8N3T6l<7+`cSp~Ij9C38A?6XpoSuYfmLYOVH{zR#O zmAgo!A9N?5)Q_xT|9pn%-Z;G;=UY>kHDz#s*xmxFPynY-E84}`8||OZ-_VeJmz0AD z;8xg;Eqd~5PcADMxEsH(a(GOrj6E7B54G%UTA5$#Z+a-|l6PzX(%y8L&BKV^894~q zE+R1o+XRGBIA=){_~mrxaP0&~7t(TQb?W|0}wZw}ZmC$L8J1wjAEP zUO&WEf#|d+z-}`WQf{>cUx=6}oyOShp&8dBHU=ePn$CAGVEA$~s|x}ntZM6D!!CDU zZ#(^|uA7z9Bl>MYt8$RvX&$kWn2+iM1KW(42Bq(6OYH~6kQK^|*6HQZvpkdk#mK)1 zZ;5%K?l>g__^)P@gFix9*Hbh+UiOOX-% z8(qT(In=UUX5>+Bwt^D&UbNC8X;~i2cbmDL8otq zS+bg#dsvY`(w4wW7EZZ>U3VZ!Oyy+%9j5D-T^aOJ+dXc6@h7$Z|=iU+>GJ2rssr@}de%`&+1N z^bJe>_}qY09E^>@2U<>$7ilAd6*F);2>xawg=-gljUzzo;F)+=1x2r1FRrams>( z!WaMDwNq4Gv4p!U)7FN3Vr8c3ypxFbI2On#2NXC_Nl*sXEFW3~IKlS=9vVrlaLlWYf`P5^2Br_p~eXuGmpHWMk6b zuv#v}{dOgG)NmayGFp4y$NIf~h_!Sm*08FoeD#&)eQ&sZd`bUnw;`tI#-uA0pph<0 z+`GT*F@}D3rM_(1O%jt|eVzadH!!V`1$23izZdfR;XyvkvB!l(a}FpDxYymhmA1_r z7`{$VcPK{2=JyvR=J@I+A6}h(W z<5ER0ct-V2MBjGGxXL1ZQU3K@x6#xP$LF>Cn?g9-19Z=9HSc{tBe1$D;?AygP#kw8 z2WiIzKLhzHET*@@;?qN9afcPHOI_M=8kgg%YBt)gZTW*+o+d9O?iI%dalTbtwx;P? zlO=j4uLyPKdbp3i`uu76KBy8VUtFtibEES=)|mZrlt_4(Bd+FR>I5V>Q_lhC(U5Pe zyXLIBdGy;SPS?SAnDM3s9)CekF!NEYvh>#VN$B(s98_a{HO>2Sw5hOt zW!~1lryy)NcFmV0RPYLy22CdfV(1Oi{x08MS**@>Ir1JZ-X(+tP&@B5ALJR_re*b! zXh7I7JNWo&+E4vy75O=H*8r=*-Uz47xQ5whH9J8nPLTH^?Rs>9J> z9Zji!7h}FZpPwkwP+1S1G=NDY4(OnT3;7}!YI{1c;(zHUpi}z$IyVy>)E0e_1ljj^ z`<3-SuY6-HZ51&IKaivG>Y&j?*nHrz@Y&&3Z_x@PNdsXA&1C2h(~G2kOv)P*oDh{V ztUpvpmP0mMyZke0{`NF%l#%VRuh552&?#y(uYbkz&r`sk6FASp)tce)`7&u4!fHz> zH%n6GmQUv&){_(TVb%C+h9#tlB{CfaKZvL{b4gBL4DA-TM7>z6WqPki6<+@xH}+LU z_1gyN3-Ru6(HQ@Ny#o_Br`y)SWi#->0{ZuJlz`n?o}wa>AiTG0aXYa6fm?fCAUO$C zL)ioYEQQNcifJYvS?jcuRN2zt{pGyfag%&+`WQmFl)nka-4ob;^0x5pH=@*6dcD$1 zJT!4`$(oxb#lnR?Jww1=bcOmibXBV6_KbUoavAygQxCC5&C%FTi$H++<(y-hPEU5B z#$`SO-B(j#%&~wYYPxUt?9Q_vab`dP9x}FHd?b0H;6Tmib+Rc-WPqGOXe-Vt(~-Rj zTd!XNbwnObfuNmSA3CM}oT&Mv-G1C2HcV7N@e*W&KG^cF3mYMG~&IxHN+rGWu&QBwdn?!jR}dS*Dq#bMTbh~2(r42 zJL?_C%1nUdR#4>f^2k!FQ9K#RiyPBDR`#h6>h4o-69`7Sz*V#+3m?5VTm#RXszJX3 zi+duT3ytr62$JhR2xutRn|f2cjEt6lR3}v^aZ56m66W7@B6G%RD(?=eqh^TgF$}}u zm@Y95uE#BrbDtIuGdda;4zB)rf#2yUujh~5pvLt_IeRQTsJh&7dGjTSpm_j}Jo{~Y zh?5^TzdD-VMfGz<`Y^)g^U7JEViEhFz4fO)yc%cRizz^-U$67pAytPEHbTz-Lh=nS zq}ndWUFE8jYw4HX-M9-oBSm`-XNA138RzhB?};P{o0MgwP2*>;eyOjZb@uSGrdHGT zoF*sw(htzX=~QUbmDH)^d)HL7OZA`8+Ct>A#9qH}mP$Ul5W}n7`Irv@@VQ7p3IK%h ztULk&&+w;lr;DvXK1OGmP7Taxr=ZJGM?`4bIQn;pAbQh+}+crjbkd9%7*-wmK=CefXXq=LwD7#IkyJWKGM^3G{wz^ zOuai%_q_AEgU%Kim5+rVh({zgZ(~0-cSPe<-dU9?Y9|rZ)l)P2 zvcNKN8NQY;!quj)S-I+g+pO~eQ$bbax5!dOoIxEH!T{xO_oBqBjwe6$9&5!tFtj_1rr`2&3 z*NgKh*Y8CfzH`dRx>3(K;>nOPvnp78>5 zsB3&}V54NMm|nLai3nzQkE>=0dphChaaq47K!>OwFDQ+a3aNODySL-0_}43?GZ3US zPPzEUFpAuCrV`*jp=Sp#2mZr9w1q8Optzri8|o62)H0IU5_mcQM5fu7AG9a14a>Kc z-g$AL)=!ep6}s9=VFDhew_eray6M)spi}=wp2+Fdm1AIbE}88ZVAMRS9UqtkF4+k5 z8NsDq(_G)bJ^r+7p=h~5tAiq5#iM>e#8^+PB<+QqV(EPQbsxrW;++5%_+45bIy9(o zaT?uxQ}?Q8rVyiUhwHc9mnf=xpexSSrU#$qB>TicJm;h&?VyytKyM{nMw%RzV<}IE z*jrpAd)()(YYz8&zHgkryr^PSyC8}vJ3GSB_Rzfq%sxdPx^mmDEFOuDbNt_m1rNnn zpI<$G9}{*mS5GqF-gGq`LFL&ge!x)wnb%m@3YYB4Rq$GJQVhXHCLhZ`wy6`094)p_ zPcMA7^oIe|v9B@g^Vz2f+u$gq%!TwHYoFK5e;*uFh^3sprO&vM#eChdsX`fV+TDik z5m&&Kp&mDdCDL&t`L@@Yx^ zSG4<&A`;)C99wCk*2GM~YKRkW=cT4@P_k?ElBN8cQ{#i4D{V%#*+0|BiH@Mvub>Hi z7Cy!2(B)c*4Y35hMp=GTL2dP;0z{P`)h_X%aHh>B%>0XzSnaw4rqk@-=M2PL92Wih zAR^%kh+Vz~ZM4}LfFuXw#qM}M#u|>qQ76|GrOCybMI}&i0f(+@q>hEp(|*fXll;^v z+ni^ZH&$+|$vVn9#kBkqgJI9x<+_cH?&?{5iqEpI%KER$DI z>s!`J^X>MLrKQ(xBP~J=$CtUP<0#0^G-hR*uI?i zlA~nBbu1paLXkjUUtC6d8C^sb2zd+E<13PnoOv^GKn41h>osA zD_&r@uhiS7Z6_IZH3~06E5TSVVc_OM4@^~rg8}HL`@55m&0dp(7SPB7mRi;%Bs|Ru zj|f2y@9bT)G5Qo}mv8S)JIMd-xrqcoJOT9x2U2@jL|10j^N$gQ10$Z3`LH??U{V%h3@d|2+9gb&%^+MldNDx)|ZyKAj7bcVhpl+@x z&HIjvu43{RUkB}1yGQDKpG9ZxvAXVdIJ##M-icZJg&i7cwvdi`nf&#D^o}h~FW2~1 z+SezIi}d z12R%zTb%Us$QsbJ{A!~=(&ppNYC=@P!KB(&JXzKIqCm#^tK(z7Ibe}@Gi5U-2C>Xl zhsW^=qx!k)?LzN<4PvSy!H9+hE-!aL6DOpge`}#7z`EfNT((f#WOh(ebz#AV_npG= zH*XuYjRvdWFF2pn3l6j8>bCaZ?DkcKw+m^-S~Q@V-f`;88y+!(t{wK!Quso0(=&b zyfcswwB4(oX75)JpJHN9yh$xe>F#r3uUuP;yzy^m)#DXI5l*811t3CH@=QqGg2wU( zM3sH~cZDybHuJ8BQ;VdK=47&QySdanEpA-jXyHU+fLY4@X?K($g?=*skd6p( zO7y@K7FTdAQ2AfR!&yAh$3|1ork-AD6{_gEl$ZF!mp_*(n{aj`Wa~d30%%SY4!~u; zP3HaRS&4}SmPZ~=`D(MLb^`j&a3gIJU!G{9RhDk*C12E2^pVhCjk{u!0RdQqCG9<= z2`3Mrm%$9ww{`rt(g=UoFN{E;A)i2!|1z}a#IM#%+x|PdNG)fQ{>#F5ws2}K-Z!*khnu>O6shIU*yfmCkFf) z3n9H7s*-YEO^7B|Z9M&!bW@A(c3jbOiGb<4>=qxET8M4CE zVl-R&OdCh-qa)B?HD!zP$rq{t24+`Q4lYKtlr7^T56zxz$5=M9l)Oz_Glp&Gx3!DsFwi@#SXoruUYCx8advmu>0^jyt)sFM zTGu*5X{`j{6?N=Fin^hzi6qg^tU0tt_V_VEv`g6OT@>_reUMuy+}}Q0LBrTx)@RSi zYscurtZ>ut{H+D^BSOz-t3onpX@fy%;oV|1BX8bE52@q~GXwZTRm_ZWUA3z4xf_to z5eC}+&dEo=%9X}#7DTi{p~G!tZ3B#Tt#?@Ghpcb)6Hk-w&yxOb8~;45sx1*wu_6u| zyqztsbNuLyBb_a*qFWOL4y9=0HW) zFEj{#nYjLXYDllimYiT4d8ws7=|QE&P;I?tZ#|lS`OxH%TRmk}8i=!f@cPZEwMmO2 z*vARAhY>$C1%-Dw^7+*g);2FSi{|r>p5_v{e3S$3WWmXuM!bB1@bjKtLU7fHs>&{3 z!+{k_8Bd=7bfZEx@h8w`Y1R7~OQuC%iqv2v!(7Scw@Cw0?H4cQgo{@?M6~ZwK7GHu z`5#ZRa@LdNHp6Ra{eA>n^9F*9p16`Bt}1j$_8V$N@9I4DR0S(MqML?}-R(0HU_?sX z?ppGt_^S4-CRQ;m>jAS2;NgQ$_5nUKQzCySP~FB?x|)B@@%!G-)XodFzCL~-$JTTa zX^=;n@J>LGqA_nOp5|{P*ZtH+=)CUPOx1YQ5TL-Cs~3{=@%+@zxQ zS?pn8Y(g+9xFSY-%_9l5rocp&`1HIGcxHHzoDh)Qtb&+D;*93%gwD3Jq}R@w?N5YE z3$gl3gN-ue$+&pZ;mHotCV=blvTqIB%m)sgD7JMheDv+XKKWAa*`Ji%p^^wCN98?V zmz93kISwXOcYxm^)&=;|3ZIvb16TocN;)x!O1Nk;G@85w;v_*`8UIVf5ZxN5lN?Fa znR>GM11q7!Sv;U?DcxemKaf{A@sZbMyJ&=H->eKl+{ofgL1+>FXaEV1DVXB3gv8=D z9}kKD)lDl7K5vF{F1~B?y!6+l(-yQ(b3qR49rt^QF9Mz}6UJDK?S! zSCu(->)pWwXV`g)AhSEdT_7O`!q<@Rrq`PhsO{0|c*m{nax(YGL)OT(RHi0W;V&LM+jn2cjZh53Jc=XDTa6p}3fm=a13nF#F0x?-ip(-jC{&YPv~U*Mb9v z%$5h$0y##VoVA$yHpFyTdJKvB$8HG?C0Lqx+!qEUGp*mV)qTCM0Zd418MvMz8O$30 z`XwibI>Z_?-v6PcrXdzrhX7PEr=&v_is7iNEF+_9-btYJA7V5_-TreHvQw&_Hist# z2izduJedSj^|*{?|6F<$31bHb-T-Gj^ksV4Mcd5a`dysd9J6^Ho3(Pdu?+gQfZUJ&C}?pDPfu27{rM~%;g!L<;279EJWBoXd0_VHa}XnAL!^zG5Oed2y~Ml zbZ0y4A>q%loQ;?rImQ~FIDKwCNNLz0U5b(-TvZ!PGDf) zS4T8sD;+Qvf#y2cp+HRpwm0iZOYNfl~uWVq&sLqGMAlkgH7aw@}l07ujh)6 zQilKyl@E<^WiW?j4}XN-sxDg?I^z|#m;IJx5o=+Ws%@Q{n|h*VrLp^kt48Z8Zu1uA zJFL!sOTH`hj*RHMTb6*Ea5vG(b2N8yHFiiWG;!aSQT{8@Bh3potK5$=a;h%s8~A#* zy*+zPR&g_V9uHS!zzP|WdNJ9gd$lnG5})Kvmb%V|@+RcEu_jpm@c>@B*JG0@wG^vu zB!~XU7!xeNk7xl(HR~FcURRcU%EPe~Z~2!vYA$b225=@IEmjY{+NVcSX&I@v=yDv| zUb(wiriiJoj1_7#F}*Sa@NmG2hB^&)z^QAEPLvx3m5Nx*7mqTndB+&;RZyo7Q zd$vJpal73I{&zaD7wQWyt@Kj)8@5~mJ+IjTEt`BB zE64vQPWs%G4H6FtItsQw>*z|ATTeCNIej{OYjPDLiJx_LoR+H`DNewJI#Q$X*g9ST zx#KH+WNGrFgB)@!%$m5Zc(lq~uNGhB(c3MSg$ci=eCO6BCr9QV;Hqkxz0 zPhWo4-%nb}?kYJV8)WT&F6liBWH%fs%znW5Q*c(_m@HoyXN8-md_lp1Z#3lj$<8g{fV@xk!a!0zfOQW4K(^64?~*vb^~d6jOZKf z3?G)GLI;*#`SQO6@QPM{2*i%9Invz0={J|zjp*B!OJDRKje;m4en~#jD&V8q_Sraw zg0hC|sXPeDXzej;^L^&oeTXl zN{lvUWOLHDbga0YdZbfIMbUMpgUau>k?A<~7!%18+f?E{E>G%#W}Re)I+e!n2b5znQ2$7U2CPt5){}&vc5`Qr#daA&Uha*(_s_ zt3PYB4Gj!n4h-_%LGlLfg2KY-I^Wpf9zuQHxo(}6%R!Shz+i;E%fw#mw8{U+^d$^B zbh;*iQ!AJPPXBB)uuWaT%|q@yH@w1#*g7sD&plUhqL@4MzS0+`^e5yn3Bg+R|6APEos$75$D-E?DMMLh@5V4u(=PSN66y$yk2`#Sn@jS>^0#6Cr0D*(jE zT6j)Tj}J<|GmP+e%L$I89R0JRzazm!>f`qbWU(NB;QFLL=AYHvbH>zh=@%OZoX~y7 zD9so|PVg*|kUg8H-6nUf7i>_>%pN;X+f!uN7Bk}8!#*`76+Bf)l$lxqq;?}heqvbI z?SJNMYw+Abt_W5&>KmTj8^qlE%T9{b?&*FZx`cSDr>z)yk)-1jG3%;UsJW`kQyldN zo|x>gSCOosx&g&8)>Q!OqQLWk#5GTkfqiSMuY z*b#-qQ(qQugQ~34_PjPbTiT;XUggcu3O2~_gl>Orsp{~!9pxKYKS+VNX)X%VKLg|` z1HF0#41X9MJ+o(2zr~Tm0n={Q%08qH7QKwJ(u&>D45W*=$ZM0cy(C}Tf8yi8lzXKQ!k`@V; zn*qGgG#O&wc2tj1pL%s@lJ0YOH}K-TyJ=BE22FPzjGEQ40{e6ahn2v^Q^pSi^>=n1 zD2Qi}Bcu=?Kx)w+mR?z}7AoGlCQx)dqGf$jgCfX(&c3Ai16G9;o}9yHaLTT3bQDx) z_w3%?dsBTFpO*ohuSP5W^ghxj1NbMfTg*AKgg~lhe@{xzf=QExv#6~C;FxU@IuJF9 zNhR~A%-Z+&@n(G*;~71J!12qu`#S8bm_KPr<3R95VH3T%2Y(N=SI;{6tkLK^`*Iz& zAyfn$`R7-`Po`4F)c-?^ui4T}W=`!&?fbe^86 zxB$8?b>cPr=aC%gQ=OP?AEMD*p{|&BL9Nk;k%`&0l}F9@>d-MKY#Tz+c^#*|Z19|< z>i>gUZ@QS~Q@px4ZGXE0CVB*#-x3CH@wt=i6q{uj4zESZBS}t~UVyeLZWZ9HH)C_sPZv zlE#`g0(k=$XQ;f=5;O~zxxBaq%J#ofUa0N^#EK|e9F`V&mBDG*r18(v=hCKZ! zKt$QX_8k=`FE~Gx!h`oTY1AaPpYcQmq-S`>XnNAS9tefOB=H^nT#qUAI7OGr%d;&t z8howLE!xCR+^&O@I)5Hw?tX`-`PoR|WLhgpKpi&yyCT$~%`-kYw^?3uq`Wdz8eBhi zZep_6bE>~2lfm%i7B9S(TRUF0^bTz6gcczV^6XJS4X7Klp*5HnaLrk<=Z~k7!yuZ1 z*;@C4oIA0QriP0#g(zpN9}&Hb@5RZ775F}<^Zqt^fjom~yR|vWJ(&7-j8Mi-_^^8ql+MRT!%yB^$2$`7Tn2 zj-y(B0zo8-LRI_W9nVA+VjoNs@6^QPWo zK#)twzL@F8kry&f&wWGX#3IjqVr#mS}e zF>R(?01fYxp_;HOOeZdE17XZ)^xeNs*{s`0!|Il8hm~`igBC{dhp@f3AB$U z6}W_z^FN+O%#%5Kr-FhlJYn{wJk@y$hH2FiaDOqLE|t8@ zm0?D`THJj8&xv@EtD`F5AQNJ=p7t9$+Lw;L9Qur4rdr`^Bf*Cg2>tBa;j>MrM|AnNt9R8nBSpYz0Z@Qxr!^FP(uu3R zqkaRPRF15BSrIYUyrUtMxwn+2=i&ZzA8S6XpKo9ww?Fl4JBZy2u;4Tp#EJ$U4^r(E zek^@eaaN&{Xd`~uVi;Ug^x!KqMpFOf)4R&aQ3e&d&WI-2Ik_$$EfPJ1%?D{JdOgp1htRDRVse;l)<#8)Y$j3+gtuHc-sV+|xWOvt_9< zL}!GTlbZ29IGN?M%|)qaFs!Ws7qt`=3b5qDSH7x3o4{$_*Esk(W&huYlUJ;M#%Q~q zqSKg~98O7+KQp*Y-A(9B4?c{%bRSyTj}iG`psKxU`LnyQkPV3Zy+Y?uSHZba*|D? z@BrXe@6s;D68B{F;6t+!%ghFsnSi%mf^O0FTu3?qTm+Z$;&c1g%1f7>+i6M@R%6@O zcv6}%?~H=I-{Gq;eSB%ZzRM&G{8OYfFzxR0_|uJUi`ck~wMk#*(IsfhWLO!jR72ns z;j5){eOC$AhKL@Gn$);fc9;MqThBDC!1@|(d3l$`bH~t`j#co)9Pme9u=85O%KAi6 zsB$d z0S9VGdo=7T+P3;Nx-`$-F_>`T##F=gg3qtJWfN>i2|yaJkJ+{og%DLv)xNl!xuAS{ zdcC(!@cA;DnL>sZygHk3@n4r)_pDD?eKHF8gf0VxlW@W8diTn&FOs4RCBF+*OKj^!;|JG9V} zg%$hj^VC&(qIdKT3QNmeN}-=S?kZ)Fd~qD@RocDx??U2Lu$ximvT{Fj2&u!CudjcS z?f(uMF=(n2R;r=XyEnxI0>h)1HwSYr$L@a|voVefDG8Y9()qJ@bj;6NJNCWvy==j4f6)pR7Os0VZFf2A83AiA6i}G% z?u0z`dv0v2)kZ_leVe;3ABNUBY^9*zGHUuB@J=&<%z+;NB1>J^fg+$+b)s6QoT)-#ro|^kM}a12|?(x zUl&RQ4So30KQc7kPoaY}%e59P_`^P=X95>sMjQcavrSSQ-Kp49HR|tcL~|s)VC!+! zHR%mAI8`bj)THuB@V9{E?_GCFlFX`I!)Qt5WKvUF7lQ{(LbcL-aLab%xacV5zTf-n zpyxIkVqE7+5qn2hcyqpPAO%eON>`lhhh*WJu|Vm{`h%`hN|9o(eN4%R*@>`_aBH@ z{ikZNSK1uw3SA0f0nd^*p??DU-TN%*0$odUY4+=+a;xFjnz8+=>%Y67xnFeUUkEAz zfK=Kq-H8gAj|QhRKTp1@**?icwaMK9$wBVaSaJHf zJ)-o3aqak}F4rfW@AZKMIdID6hzqlF{Qr%D(u+jqQt1e!u`iDcfO z^5*+@1%p|}=Ry@5H%V-P6MN6o+QRswn(gN$H0@E4Q)?;reCti!wyizfWzO&qEJr_1 zGV~3b^U&^st)eEqde#9QvSa5NMqj(8Zb_}Gu_}K` zmh|>s!iyf+k0A$D0TV{2cXGsnx5;)?0W3o5M%|G^w(_H;j7c+}lMc|TmU>DGp}Zrf zMK?FaZh$U&Dmr`CymDh0a|D*Nr88jYBdpxqXA&8*e7iuacN&H$QG=xtocE~*S`bj% zw}(}OkFoZK?o8aFUzP4(UoDO5vuVAaaWF+255S$G@P-Nw zG^AbEC@S!}VzX9}-K=9LH`y-(<8p40hgl@jD%MDWJm_{^D(p!hT!l3aw1gheoeH{s zUmb=EMfi&+@`gSnqyxD|p6LAwxbl|ejZS~TCx6XNf9B^+Z(5e&S-=Y3OYu1ON{_E4 zjJ8p*z<-({>ol$*;k|s#S0-xXvFzvIt_J4dgz!oYUsWhz>fO@#UGPFrxPtm<2B~)} z;p5BjxO|=DUfOn74eMh~!^I&h2OAGA1~npowP5IkDeJ@))Y> zv4;miD987yN)5Bi&Qpgk%|$X4cD1>`g4Hu}ySyL6Zt3Pt`Q5YoO{wb2z>fjcbg&#% z$C-UHW^U_IhL@;`lsoC7eO7H^H;-G`*wY{7skOL%yGpAHB~PF1NZ#6HJI0%*5*^<4 ztJiEk*s0bVKGMVnq=xagVZQd~%e z*Q^R^(-KL>t_iSdQhV*4jA3;h$zV2W^jVshZ^K8WjkA;49`T#9?HPUpFu~+!`L0y3 zqg|Fz{?X&9d|^9gcem3mh?OKDfjB>ZTz0zsVFC_O(8AW<7uX)W#u}m|1hd(QaD5tx zAv;gh6*=Q&6I9lWrYep|s^lNL#B(|TVhG^a=G;?^aC1(+| zN{YISYA>Oj9eO`dllpC8nX*hUJkI&dJs+Y>Mz`V4hFJW^V^cSRm9_7My)sL@f9q7` zu#9krq_*_y>AABQ{WmT(Uj;bnfZv-F-g-c-EA|o1{D3?;sWSaQ+U(NpL&E<1MOQSW z59%U($T(dyv96{%Se?_IYY{zP;kAaA27W#^>zxDNAG{6X>=f95rPh4bO70&N$W?d+ zMM#xJc8T(Lo`_I}F#H#WPES48O|LYmuy=6^wbgww)lp)doTKe)5Miv52y}_ijklyH zniQiKh>i@8i4%6!`faOCm#l$DbBh`aL>{W0^xeUH>mRAqi=z-5tpn$H8EzxqF47U+ z1Rvi-si&B48(|S@V2ix0+;Vz_$e)^|GuUU9AJUm&ZUMWU;joRIx&L_nf!l5J$2ZF& zNnTB|an=5YQHWP<0)3ZdRHpPjV{uPpX;>FoYQ3i+5<2j{os|ot1vypW20! zN6uR6iXYfa!0u@Gc27$3^R=gtEqqYXG~+y=ZB zrDl_4B4~IGfcj$Kcjj3dbz{&#`2_v8e-NQ(9tA7$8+3;;kCQuWn@|-TWFP%Opigr(%N{QHfQ6FnQ?+!FYv)rqy+Pf166rN5$po+t%hO`GXjbg$gb3$v?5lbtp5anxA2S!NSb*XcpqtjD^ zUA@9pE*@92ggh3AAn}O*C0ih31cPnpkQqk;ijFvcN6b(6$s3pF6)VOl$0ZNqc0Hx^ zuMghHJ>2LjOn+*xo|eAHk&nGdF{wlIzOP(^8@u67zamlijr!0wu!CngIDN2*;kng9 zx6T$^|4PtQ+a^dVZoQh!Sp{A}g@Eb%1jMiy-$*MTSKPYrV#n^qQ|k|c8X(qsT!Ft= zP<9T-bIX^Br5G=9w_*o4YnHY)+DjhHEINsOp<>T}66b}Oo;5$wt|eHrX5y!GPX5Dj zV-@i;4=e)`2@waA8Z52Io~Hav){X8tq+t6K3e0W7s^YdxVpdvI%;7UQW#6DZbP5|LJKk=wGj3>+=9>shUI0HpyXSr)T}3F zevWD0vUu{o`1j*NQbBx%u@f!l_m%-l#+@bAwIt z_cz()UL|nW+!|A?1!tPoA_cmp|0w-x@!toMB1$QW%~VT5`E|5nTOvsY5W)OYcDdul zlrsT1ce$@q3h82p>e)C&t$q%Eu1@uT2l9SgNqv>cS;ME7>)9k?*&(-n|J;Zr z*vdnI`dnrrFn1H+-CRkURW^tuB~d+zs}^>A)y1pPT>2U6&%)Phg5#-yWN{RZgDM52Yw*{$vI=Tj9x&%D+E+xnbEtwII{ zm*}`#oN_l8-Nzlc)l1<`UydPOSwskN^=_V1gL>d`@)4xH=ieR#Roep(s5JnP(JKe5 zj+_G8V>AP81t)XH0r)Xc`X!V^hhw4xbR>quqJKO8$D`(p#|0GuFaHbt&7^ivzC>jM zV70drxE%n9{KGOT&&}8j&LX0iBk+NtehhYhrzBK`V7xgREEjV*SZlV}L}sqy4S*@W zlJ|8=&MLq9v8PciJs6Sp*qrXHJOrd+m`nMlNzo8N+5HVGO9VQ6jFi(qBL+logllDC z1bJirXIt_U;SK;NW@5BP7zzEqQ$FHXB&Amu?$d_&Xm3vA#C4 z#(%?KjtT;#P;k5wN%0GG=`*G6EfJgkczk-}VRa$iNDSdwkR*wc1PV;7Ivo(PTzMbO zy#vMZj`B2OMBW7jmZiq=MoHyM=h=!o$gf782tplM767nWc3zMZSjDx+-X;NpOX+G? z>L0m!UGg=O?e7-nm>Asvu5$JNcwop_L=7n!2<>o@hPqEWjF*^cS5^fxW$JT7mmW*RemI%znqkgaRdD@|aha{}U;{Y<~ zt?Gbe0&eaL>D=ymmj0^5GWtU)gj8Nxa#L8i^~`)!z<&5L&dg9dau9ot^R;TDJ05OO zyq$$>MP-zRwG%U(QTEHW}Q0HeNXpg>N3b`k)Ls`n=QcGNjmAPe+szt<~<5H zU&#fM#cG6E z$AXzyJ=4o=N2lq2NA;3)kU!x5EG@PU1F`ULyz8Dc&nvHCL0MLPO#nykv%rpRT*=rwn|X=pK%aEb zALGN4T7669uML}nE6#gpN&(&(>~08HQAE2c*+cZ#gG?9^k10btLJ7+$U|S9{^8(9W zYQ_+_v*0MYaVLl&C)BPS{U6UcZCjzx4x zp1I%@lFu|%e_od!&-u#mw-35OsY^fp!@~-_M67SF>m;EkUu$seS5zTg?=g=BNiPz+ zEgbozcU#NmIrWATK%s68)L~mJ9h7%*tbQiH!w+%%z|DmoNVplms~mzdTnU5u(;<^?akr=tEWK;(?iy@W>1Ck8eyasjL&0k&hU6 z<|U(y1e%{T-A~!Xm?zzTKcv2Y9-iTUh&Aakq-U(3+}mVWNjQXonm?U#P{iA7G45pxjw0WQP zX*lxe8svE*b~NynA=tUR<~6@d))1LtJGF2}7KjI~1#SbM`2vOvKhWF2;GY*5p4in3 z_lf=V!Wf!-nv$izl~xybK(ON!>x;=0@K5c=2c-ti)M$N1CR@Epj>N9SF=t*u>ODu6 zm@b+q0o_-{lc~C1NWoe6yUx9;xY^Z*Ha_1Vv%UbgBTx-8W-QI?y*G+L+7~D8gL8t% zw$>etHnGhDV#Y8|l}{6>xrZc|>zOxIEmIkYa3$C8sj{;E+Uiwlw?*>{D|e2@)k*+nH)|H3BJd0oonGUhVgT7PU8YFn)1~;vk#X) z3^k=1+ys`y3W|@b)E%2hpP1I(X6G!rr`m(cEv8<~?kpy3N2U~&lI3z|Ka>UROx3hK zAV}|>1HBUuj});7kDS6M?M}0XTbbd0YROyGqQVI|7qt4iX!EOs=0R3SiWhxfd+FY2 zSzk+XjnR`vsU}7+5J?CW5)%m%=3m@$cNRB~ghv@SV(&pR*>s2=w=+_uZUoLB2vbOL zMD>6Dl3{ZKlboCXj{mj~(QQj6Mf{o(N_{uTnP4+7=4Wv17jhsV5XcbQdl=7e8FJ0^ z2144Ud%EvuK`>1TpSHnuZ>py{0`u|7XSEAk9tG+cL*i3uJrjH#|Gf4}fkR8tIv(1Q z<2j~21&(yT-*6XNlp4me%?Lkn48oM0v2X=P7v1BKkpmp>qc*6No8T!@XeI-v8?)Xi zsP{T)jp!>4{XV1$?Fw5lOji&79dY{aV%)qCP2r&=p+54ba34Py#z#N)m3U&qTkKZR+c$s}|i~Iu-Q!w%@ zh|$WI#-f`V(RGiPD^0cJ>Rv;ZrC!T-{C|L*^(Nx|w?vO06EBEZ)=xvX&=r6X=JnF> zhrON5n6^ zvic(+d{36ofbRS`%-?^ktvEY9WyiCvAQ3Cfs4A>ljxW0xAXb{a(SMfGNK1RodY3qRwbB5_|TM!BEZ-gLsv93wva0qtGv9SqmXVokBbEUJ1N6iOmNU8r$f!SvFoNy= zv$;@r!?n$6qea_-$Sz%P?nnX9MFctT^IL#}Lakp#RXF^XR(Tf;`q-$=bL98pO0a2` zW&D1Ar)~lZH%Ft~n8PJZ(2a|I1nayXkQ6J7uQvCcx!FPS=Pb0Qbob6|4Mk4WIjmwb zefMBF-kg!yg6PQ5)y!j?{M_Rv^ND((?W(H4pC5d`p!-7od#Mf@r_x0Z9Ru?DZ*)dR znJ-+9C@CR7D9DbL#TFK zmJlpAj@Yi#t<@v@Kv}JiPW1Qwf4MrO*$?z6VqHev&P&v}(QO8|DX`16j=z+z(%-;D zAKCw_a{;j2kIFD3t?w$4v;tZea%B6|%53i0oI)AyUmVv`bSygsRJ1;|eI_qJ+;5QN zggL^EYc*i$Vm=XJ`9E=6yHe*8$}7;DYhl4fkKQYdvo?NXV6$LiH>5<6&o}Dw*zF1t z5%hy@*k(P5CsISq;h0kPON?{CK6ZP~zh}QpVUlwhj>`k15lzOtB4vxogH4x7&#Dbq z`lykm>i^VlAivev7sY__IcPPl0knA9`eP;u)9L|mifGR?Qa+=!8yJgM)c&`S+GF?Z z4wAiFPbjUIIvk7Ia3U}D$avchtzVWIw zyLYmega0jlLo6p&y1u`TkH;-yoUF0t9>Vt_$MNbIT}|QF(?U!g1#~#1kkIL1(466m zKH*m&Pd!;4hQo$i8*QT0%_2-Hm&c)&OTx+@>tsLIY7v=sQMpI8caVadIQA2+^rku6 z1Miqq+~iYi>x@%hluNb6^^G)B7ZxC*k;8bhb5m7<+EAe3YD)T(7^5rKPwVvd*q$H( z!bbOGyy>aGN!LAanCQDG&#}HO$M(cB8KRH*?8wFk(K}-1Q9sY-o(74NHHJ}bziaG+ z)s#u@!oDk|EpWUWK;sN|z1Lq&Y@1pw0rduZb1$!dY)csK5JA^QbGgJKX>MRwP~!86+55fB z53t03lG4UYkhn(y%%dOc3LjF{vaWaO+fp< zHcUVD`TRqiVJBAxl9pd!aee)nD@l&J4NjUM#H2mn+b>V*=<}~%R|xVIQLWeys;B%i z_KR4{{Jeh#oiX(n7cBN+aknBBNQ7_n)uhY}VEos@z+yIm=)~J<`pIY@7pfzdH)`~s zsu%K3L0^|$l*nSh#1szepPq}rd*r*OdxbkLx`ouK_GMURkdA&_&R@YA*$gSpAABVt7ywq*?(>Je(CRY7!~z2P93VTp z>i6DWsSC`wGzCSS20cR^C)U2jJ^JRtG?0 z@{Y|>%fxM}&B@9OVHd;3ZroYy>0PVo7JEVZS>ZpZyRu2V785S&T59C@66M$clWjzFX?3$s=pC*@piqbpFGIw^jlzy?H5t>R zRCeXB2<%Uu0fXk%bhKHmJ{uR|$jkQDc2yWSFEdW2qLI>1hF{=Ta}CGwfXJo1bvw-Z z;ZPvfnX*(AxvCxLOsc*y`&y>%>B-b9?1VmQWl54@-gPBu%@KKKcoCSjhDrBtU9>bg z8GPpF`~P_Kv^LTGU;K{pd;1ob`3{JHH!zutzB&fl>W9RkSt>${?%a!^Ya!|sxw+b= zp7Ml5lxEHS-;}6sQ|~S}mM(<_h{yIb4T~*Jq=Sd43jH%2QeN0x;PSV7cQe3>VmBb^ zb^BNw7h;6mF-3SoB=zt3?OF<{wUj`K5tIQfOlhKtCnhhkM)3lv0t#y%+TbKv7tqA} zckv(;bm1PUjtZ~BAZ0I&hlkAKHIEbQ9T|}}PCI)V^3D;3;&s0FdXas3#hYqLV+6tH zj#mlZ?6vatC7vgNyBas6Y!VEx_5xtXpyfyXm=HsZ9GyLKSLvEn5%1(-q^^1fM_i-OrqlD-~NtmevyCVVm!Q1-lHwE$CXths(KchA#Vy zl&4W$vrM*prL%=td&v!NdMSw%OiM46}KEEjZ(I2*~-$#hIn6o`F@hqV;zUz_mF(K=YhC*90ndDQN zUN1Dv^m@oo>Nxr9FRSmY8DJ)`fESk0#S==K2#w-;oj` zyCvJdVIFnz@^F&U%(t0MgL1u)hlDpky@`EfRKt~OuRSC8kyI&6&Yo0inm#o>tu3wIDjG=&pRurMEdA6TeMEr}=}vyrUFG?5L-oE&g&G_4nN13wdZ{=5 znKE7kHpiSlfq5R$%cm`syZj|vwN8%83Ju zeCZ)n{C(y3A_kxW68=kED}4B#rr6oC=#FRxJHnpmE{2aAygXPQ$WXrOcHfVwSmJEHR z9toA~P$roD;__|@mX$)hC07q#Y~Q<@gYT_<@M!K#&+)BE(z;7@=$8)1p?J!_1T%Ib zrk;-v>oZ4ti{*y_7|O4khF83_f+|8?i>VEX&bQSbq`t4cNy;sknoAiCZh>xCJui4p30OnE z!~N9E+3Idr_0B#SAK{UC?(PUvhFAmxQFD(vNv>P6ZvrbbEJ`<`YVv~y><6d$2I?Lv zb*Xr|`@weD4l)t=wlu^UB=;iQY-^>B@^Tw&cA_ZU2d4k)qL&E!8@@PT|H9@?W@eO2 z#n$<`i&YCC{7ARWSW#V0n~lHFduJ!8b59PICaf2?Z85_IE5$t&08(}!Kwp|UKmo=_ zUTYY6MX@2$oHKjS4V?bW6F+L?kWu+!t1fAQo*E_HpBxl7+I^HBH!d!UGS2ViZcc3? zDE^y+>$g!Ecnb1T{9`llzazJ|Vb4s-DS})dnzQCSvU0u=s9bz^x_kiV8zM5K)9Goc zsh*G{=`S{8k|tVLZM*zUGuy;E+ zfsh)ghVwH;J`fy3)Q7QZPhU85Xnj2)Y;x^!rlR^1D!FSZ)Y=OcAmdZyFPkMwOEg@g z&h|~64(&9Yg((e1PhsjQCvBtm40kDzpZl#GwRuDgTwWt5^!FZr{;G8?k%yNzWj&oT z>MP%M*+wp2d9d;;82x_~orhmi`ya-=w{BLh+b}a%rDZwGz0%uomH8XQ>0TqRE;nv)WfZ`s2BL!siJHLN`7aYzx-|zSHJkR^#w!!xu7xx;iy;Q#z zFSxT`tYDwd-C>^uJKJ_!AK{4zZu4ZX4}-Hzk2Q-)P5j= zNQR?q?sqpP@^3a@KUfE)yRP~rQYs2tiJ_wWd`3tf-n0z3GsguWLnZz0wwX|^7YAkvQOLn8no*C~eEyHL*R%ki)uX~^G8!>$!e9EM zy4@j}Xi(05ux8(K;CKQfn{&D)STgD#EBA8Tp#8yL}=Hnf8aPB28kTS4Z^RhFwf5 zH7(iqj=OQ+Puw6Yr5<2ke zJEA4%xK}vauWRv*%$^+^VTTkc9#5XR%qt!t5iv_=GZoeyAOK*KB=jnn&z>dW?=K&- zlFyXN){1&POs=XpW-zm)1N8s=CQQlRUt{M*6n9BAzp#&mhP^~V0XoYD;d67Eb@7AB zVM@*;bNxsf&{67{`Wkv8!-6xki%cy5-z8bwG{z*!%{Ui^O0NR#jr{Nd&NPfmMF23K zVr>t_MJI#hZF@+QQ9!gu=}vbW-bjk;mZ2|9(CbqC`uj{_eW$&VTdcuqcsLJo6=05e zlhoYs?N+>)ZBmAhQXda`C3OXq7uqcG@L*)NbipDHEwd4UjE}MkFPm8}5b-~cIJ7)T zQ7CciJ>B&$7x!-IO?%;c@{PTrv9@ztlGr`uu1sMk+$brj-+X2|)5ap(i<}CXYR3VJ zRsEv&{{=pl1s!m@eb@*I1-VW%Ra^L&iNu|DGdz~opMGj%7|3quo@3|g3P;_ddoH#+ zV&h5jK9;*SZJ{p^cK6OVS_WqN2Fbj0CF@^?a zE^kaLouVA3uV^FSZH}|9c$(;ESZg$DI*l_$Y@CNR61!6CX66CxYwo*yqz-$xvu3=0 z>i>Y7d$~h3Hm2GwIHy1)vQVdQnMin~?!HG8!K@8X%jDq#rEcv?JZ~Kw~r% zn4wUdF|c+_^YT(VAS=h<7f(7Yq@H^bC)L>cvS*dqKC4@`$pt6ftt1kgE_gul9hQ6) z!Zqe($2mNlF#^|4!K=PN5?S7UMUMG>{(R)Ww-fev{R6&}(ui;S{eP9^l`6Ir8aW%e zf!g=R!EPS!Qc1Np^A6|f&Jd3zg39Q!NXm*mQY+QT^?LPBrf<}>^gH$R5d%DXGA|Mt zwcrU4Q!3WjaGiT1=L|1VZ2q0)jM+v-;VNX~^J&j=3MugWi^MZt1huho%duK{$hP0D zUnY=SX^y+Xf9>J+VX?_KXf2H@}GW?F4YG${U<+*QbQhlGb;TbqSJvA%j& ze96Z>DXzjCnH9`J?*C1ebYE&*>$|y$kRxbI@w|%Ng`Img0P4~|9e;NtgXSa6;ql`2 zVqPM~*@i~Wn3`e~rbMuyqCZ@tz>bD4t=m%m|1uDSCol%~rb9@!>Gl6rw`Um_$oEa3 zHqypM`8gcPiJ!O}5%_C1+5UuXz0|bn z(19dC{zV5SGo4^R&D*SYh@_9u6ZGhB8xhk93Lg~uq|zac{pKtENeZX;?v4;PWjn8r zk;Y&PHR6}m6l#c1ePTgP7xtyXmI6oaChh4}-(_+EUy#R>{ceiziFRbPAi&Q59F)L-dileRN3b352|T#)Ea=I;E%CBnM)j6bo~LY)0@c)sIs zb9wQ@O<5`LF#kR=gRqfxz;_V5rFbz6DrRWWf^3C1JNL<`tvrP`*A~LS)EVv$;K~@h zE%9p2UoHAJRPs>zO{6nw;!Pm!BVdctEwUT6t73`l@M3tPB)_j$`X9dkjSH)uq`|6A zz7B{UmL2HU3b2dcczl>WvHcBs2H0TWSeqA;4uSidT<);6>ds6eMii%?5%pa)8zhFb z;pW$6&FYu?Jb+mCUMV(98@*;KzTC;B9Yu!HS-_;Qhz z8u&`)RWE3f5 z=vRY^1vF+(la(7IOnwi!_ccu#WlTfUSSRxK{pQsu-|TgIClO@emh{49A_dw8oKX2w z&4tS95){@%`Yq=lvanriRF9J0?xrvjJdd-%#8yn*(46;Y&w0=D5$TkH8ERklNO*$9iopZ4hc#nx0(^db6<@LtpAYDLms%sJALeqU6j&YqmswhxU$MQ>z?BJM{G*?epJcc_U?u`Nj+xK6^s7F4)a zI@Q#{j8H2nh@u~io+~_?Cjzwvh;@|^pp$0w_-6kM4n?)Q!o26@zgc+dz$aY9)fjRW zV$1k=>vGy}!Kr7@)`_aFtb03y=vzC{tA(NkCe9CjL6}3a$3>whN=!0|gX7sb%6p-l zlfg_~;IZ`VN=?}Jj!?+1V7~=?CtUU`h4Q|@eK zv4I5N!h0==PKo#|wCXPLJ)9~`k2B6h|Cl~{ovShZ^i<{z?%vQdROENr`sZ~+Hy^st z{8s&oZKTh~19<71AJGEzl?7r=~Vs_^d zBCDH&JFnN4p~>Y3`sAu-&i=1fhAs;zAA;jxj;t5w20eah?dd4+c*B(Z#+jN|z(|CYkx!C0| zYDZIEP0W(ltd>jHft4~S4U`Ild$IuZKeT)|uj^7_+?8?2Z?k)QCduje^BIG#pI?4E zlTqjmAa+ynWF`)6Q<3pvXMT>PZwtJ)SZ%pD0hgeXArT4v&Nf5Pjf$;D@Hs>o%Uoi| zR3gPrhzBrCIA2%adkf}F=-m)|J!4?;g>$GiaSPZzDswdZ?hJ@YnB|0!o#$T7%^qHU zd18APg!HF}OolA#k|@5c`AKI-lQ+XcZn3v2;>OxfYvzYcZbw_USzt@5HKIpYBONBx znQRg=<{usrxEg<-TnJ?WLcQ&4}#FR#~4dw zQ9JpUg>FxC^Yc&AsUHQ}!i5Li5(+t||JsfFNxYy^_}9A21z;Q3K)3DCphQhQNOtd= ze{Az9-C!&bw^zM*VN9nr-FAYpIXu#bvSaiPgJ zK46Cc&0gg5*lkk}|4PhzUsJs#fO^?u^q6%&l>3$Aoq7k@d5l-;=`a8^)B(M)|+xpN@Z6WT`Es#2NtWZ#B35#_O?CzNi zYK9zsyHIcBX5@Mo4nR52#YiI}o<6mCcGIEc=pPf6v`xLn&sxJRi}dNcEmJF867HLO=bK zV&BHXp}Eqpw|%!=V^yEv1ChS2MN8jhcqC$u9?r|fN@O}hM_PKtUTO>lFhP>IKV0vD zV~@EI0s71oEswt(E$y@~3A_1W4o&YPkLbm`2!olmj*{Jw6VKWj+mt@OsFA$+gXY&B zUOQGxw`#R5s*p-|ti*~y5{I1ot3Rh322y;M3vrdk&H|)=s$PCApK(U8XNBkUmm~Qn z$!@BO3CJ`CHD1)8U7j((xBby?s&Zlv#5)^}>YBP$DdPdOUWb+oOYdxep0S|xQ4BY( z(|>)#^V$$6n@6XivmH@3^Os-F$Q@XFcU0ilc~x`?{yxxhvdz$nwD=kXfiab`5@H{kC%{`P6P4N60g&nj#6$Hv9FvGK}mi zzw)fz&^DyUz*yeNiP*vs8yr9Z0m^NkN^bMV-#(@|Jt&r`c{$U$YY`8Z)nJub?p_Iz ztAw=Mr*cITuw!3snY#J*Z zr%;OM|8Xs(yaM9(ukDa7Q9|P!n?3TVKeHrBVSzvTj?aSf!xWA3TIHjRH(^Y^H+}1i zrS}dUX)IyJK=5v&{T@L&!_p_3DH5c_*-n|?r$bd>9aEE;Y0d{8&LuYX?$&*4MYUsz zwQr6@(;fT7lFsyrn&zdSH^Zfn%(fth3AhHWES1pF~BoZAEt5*KyD*mZC7c|w~j$X;G3(%!&6IDlqqfB35NP*(1 z9_gx`7VYxOZa?NBFB$UnN74w7PQzCzLdL zLhU9bcB}*d3)gu)4>2G8U-Az7wv*RhpHV-)FKK^FUApvGt>6@=2Yn1hhcH#>CI%B= zTjHbfpp^t0-$uVsLKmRb`(sN5r_H}62_joY926{Db))HU=1t(t)eyQZK*DPq$CAJX zOf%Ww;I3@-bX3uu+cBpvy1wGR69F8Mc1)P>{V=ZiCwLyru8h3gZ%~rG?WOCKf(eDV zOm6EnNxxd4$L##!dNi&8hE8PfD1|#FoYK9=EqPHQIVzN?L(d>_Z{M4XjYadc?%HPi zE6(YS&Xmf2_#2@VCb|IQ1CuourgKI-1J?`ViA{wuQOdigbgl)pe%)-iIX7wu4@@ez zbxkQQGUZXFN+ z!mp4_yAU!ewOxOuLD>lCW<=ZI_YRg4O8h-v&P|NTrA(3cWhnC%TD-RTHBx!p0Ts7c zaZ`1Eb0UTTPgX9FTc9A44M&v!=C6i%HRAVGP+my*_aX24c^SkXE)>d-+?2(LjQYMF z%0gw+0}GbWH=kT@RH^*v?@h+4HzcldC#Eo+BxOC0s@B zP&@NoZ8Eb6A{zGj1xlO6!q4w5FCh_|bkreu_j-QGd>9}Y*thw3DO7zAVmufgo9~0? z-(8PF3owV~&@t>r9h-319pKz0FP}vMdlfg@;I6L_FV8R3zAUOgI0Tb6HxbG$%F?&qD@uFMXy7NE@TUc6B^=3pe_0&&d6}kbp;2o2{p$Izt!Fq` zf=rw-9Ud)em&n)NVJ2U}h{e0z`1@Xnr&osbWr+^>5<8osW47yKGeK1~%IXFU%?tn- zUy*pZHqQ`3@j-V$7GT7q>WZ@>##Y9D=e_?OM!D)-e>?c`r4ymr?T!doV#x~!`dcS@ z=&l2sAi}6dDt+x55;6767?z7XTbybdEjxCY5Ma*d-TL`usZ0>V+t9~-yYWhLE1UDFNWw;%O|i&iC}IGYVeY?)5SLS^}u z%uk9;fKjA7G0>NFG2FvuB^yF;9lf-(48JpB!rPr85uO8pHc&G*k?Y-ELzkVIj&#SB z=V&Y;-}4Wbco{Q~nl*0+!Bf+WCBt8?QI!|e2U?yKm>IG9t(=Xob$JUt2MoKdM0Ken z|Hrtwd5|H`cRXr93q$bT(TcQ2Iu^s5v;C$|J9;Ar_Frn~X7Z=rHmkktoEI8}Q6RTP z-w;q5F7at~pQ&0ORF`4(&xm<ue6t3Gp}odvO%)mBP+_|? z%`VU#lgafsJW-~ibg_>qAT!mC`ZM5Pn-FXc7ROITq671;UTKmZ75)zo&q%g?{^;>Iq zY8@Xg;y3ZL>!3hL(&K`*J;ZI>#@p`uQjpeWFur-@;a5Yv)AL{vT|3Lcp}m@jztW67 zaK$-}k#dDHzk?Ytm#<%*xVE)DNm)z2-I9s$!}@u58mZu(P5~FI z8ac}UPW*TN5g*XBJSO+}-XAVmNc%wYnH)$qZ~LtieEKgFJ(VPspQ{P2JWu)}(2@d3il&k+w%6qb zu1_%>U14XJ0}m=_=Zsgk-RF`p3dF$APuJj%>3VQ8_{vO!tDoJfW%zQnwpXs|^FpmC zRN>m;dHzE;wFY4Yx0eakKu};WcbYFsVdJ8aYv$nzst;9G-K zi~|rmU$bZTxrjfJI%&VZXukKgud#u82HEn=P6j9+lwZ1#E{3aL!R$PP(&`UO=kS+f z&GPJpR`4s7l~mJ&nlV2c?VJ$A3M2G)iTrEr1{;qQPr?9PnN~c9znzp|E^G~@d5of< zhx37{4t_;JLd$l0#F#luxc~Iqsrb5T5xG17>lGfdXQ6tBCu?bY*-QQpR~QQVw4xu^ z;<_GQ3(P|ozCQF_8htw7KeRS-EwHSTrTj*_ae;9i&sgF+1jLbT;O+HL{lDc>Wwf23rrg5Pb2ryL`16vqN zc$-h8^L<-*0UzN>8hGycJ+Zz4zIH>6`I%a9|M?aMsz9emhN2UXQkYs#0?oK|&6|;g zFU(yFeo`1^ub&zYY1I;aRVw~DVp^|w7M;g*R7q~t6tZq*MAapfue4sVHAgiL8=fC| z(>k4?`!{{S8m?uwGFibWmv7@+z5kJTUa4lm9FGHuVY$&-u(x`As*1u#3dU67fsZ;C80ThU-bI&n;Ixazk~$wtFz|w0@lHtvm;YsD_Dt zh*(p-o>A28!vju3st*oUqx_;%;g8_^QEkZKd7yEJO<71e2pHa}40p6g-VC;7bQ}uq zsoCicTl%IiV12F{mBZ~*$QZ>s-H&NFxg_%c17%7qRBL2vM3CB|op&F~CwdY*uh?iE z;C!te-4kqHs6Ou(UXdA}+$(SE-kj{l$fM6f!7a-LUSmd5UT3nQSOBc#Vj(5~H(o(W zYB*PILTQ-hZ?B8e7x9mCiaFQ7>=Vk2iJp~*U3LHh0R!}1cYoqgx!&B&s>{mgi|)_i z*?*RuVtlY=rAV>4uSB*5=vK5}TZFHz$Z%mbwJ9bM56R0NyB=`nD?WJTA4Vo72C1kA z@=o!%kp0ku5qjI*87GqVdc<@M{-m`<9aUoEPR!cIhaF97N2~i1UV1s`Ld|fofQ^n( zA?5e2`cjK*qbH5C#g#K6whzjU0Cf`2MFH;qH}ArToPXKipq4CKpYo^R4JnHOUNw;b z#IM%`j7g20;V0ZT_YfQW{&|;h)-FhpGYD)@qV6sdaZHk0N!fd1ZKX#FiN4Z`jCIMc? zk|e?SHtdi`)3FN0iSEho?WNvp&vScOaWCI|O_>j_AjqTXc{>tILUCxhb%J1G*PKAo z_66BW$8g}_Xj z$!I(pC(L|U!)`EKeO+hVv~p2m@#n?bu~eQ;FaO0EKi}DcIY=(wpp?gdx-ND)h1uVI z76nq0NfJ0f=jTJRu4KE2jk5s6;X->ePHO(Q$YJvA0_Vlt?fip_Oo!vzn}~mdca>A zT)#y>AJ+7EoKq8^@&M>Vs^>IOP{eFiu2Ag{mxiF52fjz`)m;vJq-HIIzv;zPvT^0N zLkiT}m}%^NA!4N~waUeyHVa17>yO|U0&=@I?GC?A*31d(At?EItJYat5j`+nt(yP= z0#McWJ3@ti5izm9Ax)Ct=ZFo7PuwBLR;2H2zJoPdyg7)!=p5#FKmAsbU~Z3U2p47L z!?6$HCkmUKQ|HR*uRq?<*U?4n=?dl@CQU52dZH%%GDBTg+T{DTeo8G&wyQ67Idfn3U9#S%Tw#WAYQWi^4{X|1R(Dix(VJUy2{PHorL3OqHpAQ~t0(!d|~7 z|M8x0fa*l@&3#8t8n9%cj&Zq(7I@*lCKqQG_Raqk@rejNuHJ4tZtXBwK~(&>qOLwb zi*)m!ZnwCG$&q?)V}I@?VE3p|PUqL$0DZ?AMWrrf`-Maz$*ScF)jQcg)%H65`6je{ zZ&ikm$=q1XEA78~tXaw~rgi|K%J}G+1wx^|%xmqs)bD1HVl$U4{-%S2>@pQpn0L>w z57FEM1V0or`HPv8%i7B^IZN&-`b^Bv9}5Bx*M5$#ln!iyQ_4zJZyf4F&Nx;dW^L+B zys+*^TlwuB^8Ph*000r~6n%EBtl#-|FVzsKCZ7c?c597y#4v}YsVc!QR^5#|DDJ#7 z5AdlULsbt$V>yBwNQ7G7we|}8o;Ol&`;7mNl~DSyusak*J!_Hm%`S}@`p(HYuD@=w ze5z<c zJC(l!mot*s>q3orhnhL_hQZSZyrH9#JC~UAg2103B?gV!RCd46F#dp50Hji z)NbCh@H!xh!#cJPT_Qp2&~7G>a^q{AFy4SlnZqAX^&T$ks)rFRF*}LuiaQU9t}#S^ z-uDerad+y0sj*n?WcB?;^K5mAh&x5L*R3;!UTpNQ0W$`GEAfxf&ch8@BfG9KmY}-N zLhj{xjQ!j>P2*nKpxe?T;wOwH`$u#hbdYwGJ9}b2XJV=aMkHc5^2qUEo=ADuN0V1Z zSDS4op2EQ_Pu_cL+;2gSQ4tyUMq#e)d{A+a32cXA66;tF5n^ATBBx%p!pWnGE=PS4 zectAC2;PCbLTj>4O|)H!taw4--DOuVwvWTb^rP~e?@60pOzJ;%JgSA4i&>>PtQ`wJ zwxGD3R~e<;HVwqpDt#Q1vT0T`(4(P1_L{;pJ7FQxWdCwqn!_6IG($b9o;7 zUF*4%1uqU$KfGjimgq1}fg9JZwYDSn)%yI7osEB`iI2fL`8hG8Cd-JrB`;~W8>9EC zQ5<{9S_*v#{BUDm`Sg(d`%oo=ltN_#q7s{kVhb!eiVN(TMkuuV2;vXe=*++yJ`;`4 z)58tR&Ho$Lo_a`*3rYj?ZrW$U;&lEE+;SNLdN@Ff)b5dETP`Pe&C9>j?YivFRj+1O z1N8e){6ZI~qE^Bp7x9?_S1xVY<|vG*h^d|;pM_d})?Yg=iMs)Fq&3UNgqvW8&WJvUHzr8qBClGKDB#fFt&zOzEP3e2 z{=~Y!=ua{M{kw_2+(sa}4|GBrJ#LlO-z+F}k@X~<3zI#>&@GBK)e5xgc6#8&v)%4x zv!EVl>oQ!XZ2pgf%+Bdo)Uy&I-UwMBF;Q(B&42h0PGYu~ z_ur+@B;O+@S%p&%0U-_bLHNpB~_ zXQ+;ot(`NJ0slg4?EN!t34J;XBS$Q6WC(KbOas*QC+TbRPMe;) zO@YJ`lk2>qDr2tF(a`$V2wE)ZIVXl*##cW$JP=dTu_7B z7k{|8q1Qq7z4B2aONy<|;_~84fu7}dHf#H}Z3)r)jXOnLh@-*|^F>?dxb$(?U6w2@VygooWQqni z@eZ+E9Q;_jrVxRd9<)6o9_a6~dvO%#;?x+g*N}pt$6Fyjp4ANj{$^{I>@KJS^GXp+ z8t_s%j6!i8}e2N3eb+; z_yUi|kz_dZ`VL=pK{Z6a&2L}DnD*xUKd*VMciD4H2ta8^1q2e04RPD!WvpxL9ALbEf}ZaSsX1qU!Okd&Fd9 zg$Uv|Tg8jMHuQZb4;6m_Jl@l}4F2-RNia>~;>{Qmd;!VU+#Fj%= zxu$-@{QB4p?x2Luq#Emm1CeIRos2`+ZV9%l_U(~*J51DedalVNXjCDjL)7iBf(SuX z24IE((WNmxz&AZc@{C)hkB~|xRqpUx`JayngxKdT|D$Ac{Mnm;mqv`{jap(>nl{_! zc~dy@L@HEO`(`-WBF}sJRLl8nGv12Q|C12BgVF_Vxl)k$vZeV3KRspG=ke*=6pjSR z;nZDmkr+Uv#Vp>dd-NlkJi~x~G(-*K|8S*@4sS`G`Gp3|=0T&6$R)tGi_p|3sr^ZU z0*rEpB#msrfRDzKdQ_ zIr>qlFut?Vc#JZbqgZ|QL0TI0DN%u%O-KAP&s59$2TEfMo&SrX=e{=^%O+B-Lc@KF zkk+NbzHBOGf8W|{kIV;%!8Q8OIB(3|#iZonNeADwZhdsaLu-_|5ae>i)+K= z1k%c*h8hF+D9lQu8JXfh&rm|CK_yax0LjUHb!ki(_|43ud+l~l&CnRi?P z;4VE-JK4RX#>Z{oK87{0)V-23ye|1%IF&guTm4{Ql^choS_$@3ujPqa`r(^l5#RND z%ufDF{q%=xyS?1?gI@=WxN`}T73!wQKDd7qpvKBtr{)}-Ac}tSV1%&e%)XnOfB`u+ z)oLl#I}1Kc1IE}jxyRezAWJd=E znDUQ`eKt)inOWLBGFqGl~3VYTDr&5pIo5 z!(%H4f_q|X+ss{Q;}nvxjxb5pePnpF0MFi{B|uKw8?Kp3+Gb?V&oClI#j%8zNQrk^ zS`{jY+gcr+-VLcvYm(KG7o$3?7yHA5Z*5w((9?pMs!^t6cC>;MyGo6SDLqdD@itaF zkiMEPy*;vf+t!%-70aMMNuBYin7mZWYrIs8bYKIv#CNBAF8twoQ2*qpwigKZY#9-G zgD_21Uq@WA`?9j&xz40rA_2*n%y!i)$F|Tt1%61pr|Dly{Xvjq>Pcuj9^Tod&P>2| zilJAY0No})LuKv*MxIBZRGvY!^%)||hi0&~NJ)$iMw5nbqW?oV+(xE8 zO5rkft_ps0{}i~1vX^(#%G-V2U|@-~qC+fqMmqBEGXqUp$5$O=_R?)` zH@b3T4r=S0@DEMs^OQZ>GX&ffM~4zEevQpZJ(<#Js9>+^mQEq$LU6Mci}oS;ILt_O zc&7A-f@?$mk_i94@OK6jT)D4maT;^fP9#Tf7K^?yV9;cuH=718sWM=RjESxq&q%>< z6Q$1=g&*7LDM!Kg1jv0Q^IPI-b-6d(o2}zZqU*Bf?#}71v%+iZRBsliNP*h-FS!5V zy0i*U<*}z{Tl&N{#(xK6l+`9Xerp`muufbXt*DS38GN~QPXCwTTInq08+>1KoRaz( zXXoolk7)TV{7ucS;sRcts)J>&OX}Ue10bHJYe&UQ7W4Bb2)^a#^D=z=9<{?xyTSN_ zdQyEH=9-)^M`;-8l&|PG_H!@X2L|lm8Ksmi@mF}D!uXx4oyyzpwn;||{u{)e2Q@n-hmn_;|t3kV;(e!Czd()!4vQ%q*q5D)en)3gKV zvaU6Trjd`D)2hQy0nDsxjX8j|F(fnGwFobZ>#tOfs@Xz@5X=K->_*dX`-Lh1tLz^x z@2}&(n^l5Ajh*LV3e?Pdvgf8t&nvw~t;`RWpvh5aEmXDrM6^ZykI_RFn`@)>V&i5n zafmt)YCj^<#!IKyqn}M|XA?UT9b?no=TK=-5H(0peYk?CwgPN4UfbQAGCT}!&Jo5V zl~VT$A0`}m?w`FwMA_{A?ETVcH5Nfc*%d!B?6T4BIu z%T}$LUvsv={mjF1`Ne;~M&;R~Js3#860f9ekq`zrwVnNiA=e`r>Xo;`k?8zvmHhs>YD>D%F>eZp zba*taSP`Wc>l5cCNmPl4=TXSKf!)Ep-yhh>vm{H)f0sx7JdDO6f$r`@vaw0MfkNRo zY{|xLTz8AQrpJ77XzAk=IBA;0WAlQ)L{8vR-%#N8#3;I~zU|Y16(}J+VV8zvtSq&09l8)29c7B|3^g zbOcRRe0$XR7x9QYwJi)|=k@7n;gL%T;@_gT@b*ke*nb|u0 zH-m5T%C}psBt!T9Z~+x?H6@-e+(HZ(*>afe4_chy6KgMQBwjq3xIW2Mc6zqt5gf-p@(x75_5)Cu?<>v!T(h$?%L}HfTl6DDQ*=_)#|>NiR+$p$j_Y@RoS+6 zT?qhIo?-tcFrxsdHl9*4>R+4`#4Kos27YGC7~LN_ZGZ{pViMS1^+F~=_xIEl;nDQt z3Bz{y`bzn;CvBF9l8E0Ka;Q37>VL2+2IDXLlkyOVRouQGS0r=1xe>kyeU7C@wR1yy zGSUG~z;=Z$2>NZc?9D$mIk|V*{E(5xQa@1rK+Jh^1M3%YSmp|<=PcUiIAhvraaP?= z&eVR!eVa>L3{@W(&qxX>#g#SN-iGex>8TS|Fh}#&AMM~VzRUYoLwIQ#$AE!(n02&g zR{n|BLvFE;ZWg<_Z!rDnn>zwQA}a2Nh)O)HEWZ%*K_+StA8v*-q)*PPuA4*$FAs?e z(L)aJ=+$`Xyj9xP16m3gh=XO$M~tU^HBDK&cLs!_rMi6mhRktX%~|n;EHVd1j^(;- z(gYVTpr2UJr)#>~JV!+amrMxjj^dzHAeAm*?ydPe;&M>uX5%&;51!bGimY04PewE)!jH6$XjOl>5UO1TPNr3q(p7wYxCVA*2$T-)Z7?N9uGm6Q z!`$BPB^B70;~#;(51XY`?6J4{2cjV@B6aX=HfUGkFciF0R+ME1NXS{HvWmQI0pSPb z3KM;GZ9d|}v=CMsf1oL{G16Yj1CoiOPfw4gdMlQh_$2h-1IE>9uo$#cp(`O@d?0vs z4~tbQCfGh!&ShV*j-86Y# z+~T6C>v4q>;ykdo4arN1t*(f_;>oNk1Ugbsh(itPkQ#x=zVaD4&#;0F{a6y6s653c z=}!0wg^;V0mXjWfy>U$IsH*FW_4M^+WJ3uDSv&oRZRWIVEe#pHl=O6}V$elLqJ3m= z0GV}UbLSV{u|iT-N)9lb)oA^-HT5werY}gx3&_`l2)>O`xCsBGpzkVIH6}9W254vy zw%WwU55aj(u_F{Y2J)d<;@sht4H)6rZ>3-s)#$Dt!}x6LUYE#FMH;K ztE<4GBd8UN9GE!wiF7Y@lZ)2#{kXgUR)qkUsMS)^07UKj+&b>#%Xvj)>A@GXd6Qnw zuQ%oO#lS5V>Pjf{c5sTwOprosUG4da4i-Ru-tnU(CnM*VFV%(@HW{Ej z`&b|ae2Z@JT!oU)v#1nL&c83y&CYxGH^?gKn4ktc$W7DtzpP{R8*OA)dMiN8e2rtf z)!GC8s0iH^QzRb0trhs##fabvlp6TcU~$I^1RQ=nbneV<(A+>@obeG#j8qVy5OUx0__ws8+{ZLb ze5k_8+Uwrp{C1IR%k-c!KyC{yPL(${et!?w z+u$t`7QCp4$NgCToYL-9>AylfJ-F3TGsRh7UKs5MqI9y#H*9%v_9ma%H@MOlj4u^S zLO^Y(x3xnP9A__~zYW|N$eZAb?uZ=?mDK?m3ShKa1*6-7k1TtK_&4r_zc1{-=$Uic zU;KR{8A1NXK0~h)`SRF=|5Q53tj%oB}M>po^UKGv-5&f%4 z!gLCrUp~HMOiD5EI!8yl|6H)~$uzr85R1n|f*Fo0PW)jiCu_yCfWiSe)FK4ca^LUR z1|dWL*VECZ7ti%U%2YC#RZyB+aEIfnhDYhzy4Ynck1-%{WYl0Khh~*p$g3?+ zORi!9OMBp#zT&61g8p#DC6+dM==;PVJIcbJPwyf;mk z6v#osLU)c`Z4pRyc%89`ZfXQNEbCww#2g`)&rrf@fItxPG!yMilvS`R1zv@XszWDm zT^9l!2%U$C_SwGgw@`y4(z#5#2vnt7#s{De<#~awAA@R#FS&{pH=lh&=M? zx|$W-)!L!iltjKQ-#VmQ8n4N@8)>@FPxk68M~uT3jn~zX4~0w` zk#nVMMu*C-uTFAo4hnI*$c`u=V{LA>Pl>V;o1W7fd+d=G3Omcl*WjWZT`CC=J}!gg zxmqdf`=V29p7(=Id*pNUDw1yaRentQ$?P@+(AVbZ$G+PUsueq60*z|EU^iQajeD#n zf+j8HsiJTh)O&W(5Ryd4F3JVWu^e{jK8^z+KJRStya?)Mfd3nft-|W)#ZvqYcq()? zt$tr!2kD#evymR?${Vk8vc65uCWO^)Au8cbFbTF=c~vRBtBzkZ;2JT9lU6?wtB1^| zbl=__fR>odmOG8+dLUzZorztjmxRu0L(u}qWra!KsETgKlu1$Tk3hJsK*JWdA4EHE zcyV7HOc*3~?gx_-_S{9pvG-WobB6ywL7C8CO2k5{H$$0odZ--c8TA)7O<}f%2QjF` zD*I2oEdyZo*-c$&jBdccW-?O;`qgz#5A0^gf}+5^7&<=YsY?ARDH@=)9BAGQ@F1DJmV_VK+3s0B)w8Jhg`Q zu^_uQye~Kt>`C%+{6xkN!S@`)BPTf{S5o!q31veF;<;@a`jm)v98hCYHC zI^<{X|LgziHckcR6@KdJv;kBO@M>~M(}R18xkft;RAk1ASm3yZwOiWJLHT~ib(Z7XFf@x((d+lQ?0G)rH<R9z0`6lu$T* zG(E1jV}wGL(CbNtk=i9p=juF3cK&RLRLk>|9C4rDksTNwUlrkx8;843=D|0He3%G# z&-uGz(|7dkk#v*q>qqG>GqW>Ki2JS9aHIUh&jr@}?OO#1&0&QbWuq&hS~+@SzOGj= zVSSTOsD-(Jcif;)n4Mge9k9bVENw~}Wf7xwX#;d#iH8>2kil~ivVzf-sM4vn#tMb) z%C&1fMCIitxZ3gg$Y~UGcu(<=_ZK%{?+PU_XT@YY(EYAy{zzcw#t8-Di+aZIQx)aic}%?6rOVs zwMaRmCioE$-OKH>3}l&oaLCJ=p>aSM(#?MYg@?X+`b+7<_xh|sN81c+Ay|M$POx3c7{fdZEP`X z$M^U7{Q8BauLH65LD1Dg&+tmRjD*qN&PlwOaTTWyVo|x?UK=1$N+StD-#8FfDz^Sr z!L_D0W8$O#&UVyuY=$d_j>qcS$E!+2sd^bcswoBGLe8l`(8vF8BrVr$|M7WS=qM)& z6)lEA1{^>()i+VhGzgYmEW?8Ck^&w8xTH+7nsVD=WCP z;oS!!1xOONY)xv9bFFrE0j58MO!5!%`QdAn7@|OldKU)0!E7>$+pFC0`RdbCANHm9 z$xyBUb5qD-unS)>81#|}Iac+5p9Ci5p8E7z{o-56;KM6EqCs8Mi>^GPaPx}mVQln) z0AN%OpU8a>(fa{N-wmqz143MaJ_zVk&AU3$9c2Ybz!nIYhJnU>%}$_=U180%X)>eX zWth}l1`vg9rJoLIYMKgA#1(WA@z#j@Gcc+wxsWX$iMTmM^i?7Xhl|5LT8!N!2Xkv7y<#s={e zd@yU*MfRCpW%BID09zGf6Ut}+RH_JW4dGzjXFI9YX&*tL(jB+g)5KyszJ%-wv_(DS zM7+D1#jfcU4EYjZr7nqwPXfb(ilyzJ8>ZI!y=vJkHQU@?$|cv++ml^eFiBXoy!z>l zeY8_8P*Atj#0tv@l4Ha*w+c`5Kh85-Jj&Jkk`Qr+IC`*e!VjTUad)4kWQh~_@si4_ zO*Hhpkq2O>*>b)Y=+AtJy${+nvCE;6#3dCzvl26Uf&pefJ95K z`EON`)S5<@l#p+H>Y})|kj&_+*{2P<_fX8#RsUX*-fc1*oRpW1li+|aWe|I3i7QD( z*df=`$>QsO2x>?sZ5S4y=R7MBB4nXv&mw_b_r=+`Pn$yj1X%l(pLO(MWP~DMei*dF zuoo(p-MwfVI<(`M2W>Dq3`4w0rArNq$cYi&gWMe_w$S7uW zuKUe@C#70yTcy=d%;T=##PVAI%lXzD^(@TAe)yTL+9OIm%%&IrciuClMn{Fpxt~=d zDW=l{Bk66zJJ0i}!7SW=s|I|Bktu!QrciB4Z`h zj_z8vb{14jamsBXK9A5kY;)&>+8x1-PHis$Iny|oSV>CnJD7D9{u_`8jf={w&UM4e z9l74eSJp$m{y^BVJkZ)+o{@K@5TV|eN0oNH*44%loY?!yI;wwianlCaa!CPEB_1af z`Mis3&abIX7_+y9c~ zB+vd6SQjVz4SBfn{jR0g!^<---gyzNl;efpRX$fd!tlBu)pIqX3~K$fn=r4Zir$bC ze@9=}I*~uFZ9;kULqA)|eoo|z3Of;H{Hx@g{_mv;e3WRIspZ^`dvN?FZJrT;9Be-o zalZEP7%|fOi2;)c0J2hre>Gz1)9F0}WA)F)Daqa-GXJEyWlhQE z=nc1FBc!Xs46;X~=QgFF zCfQ$KDE~F+sNK>zNPQk~58D#RvMqj6a=AWa{p*sZlECB@!eZdX70+=+hL2BsYR?E4 z1t$rafdbq^=jwZtM#CfQH2PR{l9oVHbX7Gt{nmk440qo;O^ z-z=P9jYxjgDi(^7>-9zjhpFhIIc`U+;_y={AU)kO!sG4=I}~=3WiJoy`)6hPndY`) z`yy0#&rxtBO=ctBiXJ|&|0`t^FXoH4kIMSW#rP+r>vfICSKnit`P3gL*_}#K*r-2y zn+f-ilZ7tMY}n?5_i{TZjqox4RO6|>XViT%kTpnn^cO*>W0Xr9 zsIRAn)^C{s-k6^6vK^xhYQ7<(U4JwOX#(8g$NPi?`&8iFZ~a)kY1Z}I%Htaf)9UE0 zc_w$V7`b5&^tIaUI^*w-e)7Ns0|RkLGfX#@xwSQsZ)kcj*1cg#likKL(r`$d*sa_d z<~^jmP81?EYQ_!?@$RC%ds{%o>%J%tSI%7sself;xQXna0AF=DNp0ppjDz$ms$}RH zcHpPjpOr8F7?sZWCqWNfK|)<}laxl%+%BplTWEA`Aq*38ll8WU+VtYo$ukqaN$=AW zICrR*ECG@3#N_;Au~1G;L7uc5WLP_T)aVyW?*>}zgCFPnx$Z0>XT@^cuhw&`aDv>; zDlT2>J{M;7;kJhdqO%PPgIsJ&9{>D70%z5$=Huesmj5*#As&)^aC*i+h>0cxS*KFi zJL4Mudp2fotb*b%;P5|?r|yJ$>D?5Lu0+W&tbuDs@k<7$KULgUoKuzv6ZxSIcl}!B zp0^Yf{zS-pLvM=<6WA%(uH2hK5_A)dnL#z12zhRPi+q1~l$p#2$@}3RY2nzAhn)fz zrteGlXYXa3n;Q)qfvmx{H&-GMq%b&J#mAK(dj8RCr5gzY%pGnq*c9=tb%s}vH<9mY z)g(=oIO$K#TCnoq{Lc^;liZwjh5yU#&QewQl$HY{=%NiDIePmGF}E z`T6=V@M>GkmTS)7@#6807hGhMsd!wR>rs4euY)d<=!L;bUTOTdDli@*akTYBimQ7< z{`SbUIz*XFXjSinytpf^kOTR}Sh3;5uLXAc8K3R=CX}FnaS;%2EO~5-6b1DzsCZL& z$>;&^3IT+x68TUC=ZN15(!!Aed7VHGhBwX<|DcvewaF5x_g86VHn~O{O!<-b7XVe` zyYI59z1pxlh`dJ;Bn30GQYyS*d@s~dYC{H+csP+E!m##>XV^X>^@AOZgFU;rjeLv5 zsozWXd0YKps!2Eo3xuP@uf7)E2bGxDP zCVtw*QU+RRmPI~M@h?|rU(E?>?eO@@;oH+L(KF2i%K{!7M1 zisabEla}u%IF=5k_*AB%~b+z(wVA_y)q>-x_TZjesOc9Mr4uZRo)m zUcpC2?2F$rl$|E>V3Pqd+3pRqX9%tGbgDV=hliXL`0$g^>F^7-lOG#*kN4|G$zoYB zjnPn&=S5We=KiYoDxScY9%3;iM8VQr*88-)ux-v^6z6ViRJ9*oBGR8Ksvv!P{cI;A z=bkF>)AzuAZln#Ooonw&&1rZkIBrX`;)kDo-&4#}nNZQW{^t?>bQo99*23nkZY%up zDYVtT?1I~LTYIL`d2Tc{XW1$&%LqBdvYS=5ohmLm0x>^FD*+1($rRYwt952#>v;%o zEJ4I#vQr<{DO)3HKm-oZjpRVmZVLXXv4BJ6*n7;uZ&G(Ny&T&|DO2iQLGr`_Z4I5j@pS^}OQ=s8 zDl=rOs&BX0PzW{Yn<~&J1)_kkpYhUn8q#(yzS>4VHyt6+S zsZCTrXw)ZI7vjm9vI6vSd}8qWS;qq-(`fNHi&Dv+aR3l~=L`)=JP4bNSd|zWaID$P zP6#9$m~wtiN-Mk@xH=crCTXM5#NQLnCFG7SRuQJ8yLFKwx+xmIGHZA@WVhjj%Y+Av%uYKyonrx*Qrjjwr5RI-jy5*m zz%B5B|1tuC#u}E(GVbPZDSiO@c}ngT^-Ju!$NQ4kq(@?b95=9>$2xHN zMn_M5cKzE;?}%9=IG~+L4T1M|g6ewJgZ(mE z$i*)Ej|3SZ{xbYjO9hLuxr5olGh1?I;3ku{NFtYk7e(-1HvKEg+Y2)B(u9ZOZ^s)jLem^wjWE!EH#yF0a*4tF`pQ2c*q z!a18~PWSP8cVR(y_}uTC?n&`>w{tG|k+(HS6Gbm`d*fd3$A3t)bc5e@!A7cv|GK+` z7i#qC2bkl{m3Ud4v}>Qok&)5OHN?gZ!v#OC<4K!I5px4A=Qp>d=a4swajC zmhYYFPQO+oRCLSHi$7bteO|zlt+hIRl3CoLsIIB1lU_#WZfDwmzvxGOBxUoe_?DyA zt_C9s)=cR-E@#n00CCD+ZQe{HBPB(#r{YFnzcTjWryPkPl!-=>qIW3X^}Zmm)Fbz~ z+R8+hy0m=i0e%~UeB%P^zg0)!bAu1R0vo`gom~b(>icieaIRu7JRE)JPvJMdc|D!H zuUM;d`!k0%=qs1W>lYKJ6m!`F@L&0h4Ow&uhajWCr|Z2xt9ye;7m;InsuA{F-;CET zp^=k0k;_q1=GBEtHahN6`o`Xjf7A(>D9p3njbV{W@}UC1mY`tD2vZHN8ub$wBBISG%^Qrg1HsVV+((}Hl99Ak9*=JU?Hd*`YcZ7xc zRDQ#6FR?hxt}qJw$lu}hDDgnU!svUO zC%ZRCZSMX`nWhUf-kWE}c6m>sEfTIZ0|GbOcL#Q+D$x0KjhgZgJrbySg@FnCD4-g^ zHeIty|)p9}%Y!*w8vI zjra1G)gnl_^YHgA*m2C*^8WaXO-+MKe%mM3CQlssXl@yAclXY#bpyWH&paQG+Fw=o zs4Xcgse3W98>1WBTki@5DW3&%Mle97Vg>x(i!)O|a*IfvK#h$M|hhcAsP;g>vi=Bhfo z2mM)4@!N)aoTiE)kFDbBn+4gWthmN&kfymN9D%mAAPQ1pyA~BKjzLe z7P&Ufu$?$y==g$Nyx#w0*~l+)h8>T?@!_27pH_R7U{?aSAYkm zWoAiM9`g7?7sc-zAaHG~DZVN-ZzZ-DaxoA1WDY*lXDIgA)9-MyX3DR3z6_G=0O1~{v8ibS#6qibH+eCBy zw?4kU$}TTgV8Z(g@!u-HlLW!_hCYO$6ItMqUg`F$+r?a@kzR7P;S;S*gF#M1!p4@Z z<}i(%L95K#(XGv)jY1MP&#zUdKa5@ngV$azsI4QY5ffQ)i)vBWH@nr&e-FYTUtBh@nm!ytL8F;&C-Vr`RJpu4ZcR?i#PBb*0FetB$`&x`PG|j^5c75^M<; zrPL?`G}|%mZjL~#9glEkD;NFyqAg(3&Z{P;!PF)t?}wyXG_tPXVnr2;W38~ay5aE$ z{;+sY20uOwUWwmK<&~nux<({~too$`pBFGuJ-hl#nyEnUQ-b?d=|pjEV@n2gjoFTi zH!{B9gGlC|SMP#Ibug*fFNEI!<|6$X#8yh0;;LBTxrRODJc@^cKI8Z-=Plg!J`HF$ z&MREiO{)9>#qdF*fMW+i;6zgAK=SQzYR zk!MZ;gEsi`D@M`tgTN1dhlOctS~%{DNdzLbR3rP7cK#vWR}V52Rv92Ha>zutUCxAo zMGP{dyTD;~($*L}5hP#7Z59M&%Ms&pYNxBOslbCP!w}Bv-yRji*s@@w7j4U*>hyyr zbHESeI8{k#_zQLh)%sUWoI&=w!p7{jLI>`^^bMY0Z2TDvPC*%3yEJrJw!_lA*nCe6yq^CH3U` z#rQA#lT7;ZkiE|cQY!-im!=%vnX8>5t)WCEv?6dT)t9!nRqNw$C0IrCC92*w5&&9J z6;_8m07esSBbC{>&}k7BaGN9lP5O6Sp#b#yN{F%b#)GP<=y0NV=4yyW; zGp2JvrV`6-f8?~+Ip>zpL%n3aOC|mDzg4EJ3{Mm&7CZIkr1_o$)Zf~xu2=^wdnDZg z<_K}Gq5Cy4+Agxz^?={x)!HsjFGA5QXxFIK0z3-6p@+{N_CPF$ATujhLMm_lMH!sz z2p7sdrvmazTfUALcrr441T6A%q}Y2K-n<@$msRWd_R@_K_*{9-^OCcXm91&_5W0bV zX(FNGO~Iizb@K=7#8^@0k{R&vVE`4NEO(E37I=AkM_p>UW^j20W+Kvl{}Hd^w!Btl z?H`IS&|U_HQlVkV+YN!Uoe;D6l+eb(<*!=MY%J)>?Vu^`AP)}pNQL7Ywh!au`R%p|WUTHBkN2M- zUgwllUe(6<=Q3+&Eg#5S1Ab9MUc6-7Q zad`?r+`4mBv;M<`;&R0vcAx~XBn3g2G0meN3d%@n^COL7$W1=n<2qv=Ei(5^pSBzR z9jF(~()z&GocrkBKz!@ORZ@??&_DkYbz=W|w|CmoO65+)vdNHru$Cq(ly$)fjDJH5 zdRWf;R3;8hwg?~O($>MnRL+YYq= zfH6_Zc$Ut$D}mMEB1=yXm#3#1uRcWmk^NFzUt@Hx`6odq_kDjz(>Q1h`!S!|Y^~fm z_#tlArn6K1a_^Gc9_~KfYmR6CId**Dwl{CviZ@_xxDI5#lCnB%;n=;H$4b!D`RTEV z5uc|!?nI6qK1AATGhz3F3B`1s_;1y1eky1UCY+o!l3-iQ30}5tVzFnhy*U9*+oJi8 z?qK%7HO`$*%#8&^I$)wNu_t;o02ibg6V&1ICUhi7)S%;@HBKL;_uEr|c#`n<;{R)0z}$(9F-_zRDWd@yD!Xzv*vieJ4np_#anX}^r`ULK@Ommaw&O5dPdU&#_iw~#!8 zY%@Q1qKjs2#mP1fWuKeI*rZ$;`g%w9)2wcFI=oXi_5kjGt4B2RWTwA_OT8#UHMJXHVFxyo% zhAC*{0E$Q%kmvVsfq->yZzl!$B&?O>+n;40=wt#Ol*q!%@x_VZJ5oE4r*bCFTb|Hp zwAMw#e+dd*nyS>MXg^*huVQGP?}D43=i4ZSUnsK5&+gXwVVmd;6o{Nyzc88l>v>-D zDRGK}Q^a1w=_okdQ}C-Sm=3$cj}kzZ=gxB2RB|tkYIZjF%0Ymp#-hDOCB{zFOime+ z#HL_Fu^->UjO#lzTiV~x&DfhCfF%LIJ&hWokda!0vR;sWCDi04gAJ)>bn;5WjQnf< z`<%~&O`&)_1dw7y5%C_EOkYcS^70s~Pa+E9lG-e5GxpbM!Z2j@%z))^M*iCE=J+VG zdhK9I`L=I*4V$_s&`q`Ud>B<24+@PcY7qGmMg`$@95)uXPX7j>1t`%v$@~6rZp~t5 zzp=Lf%1_LbE!Qlr-o4y27;Z@RNrv%@jIGzti+A&4?VxHCGPPuro zb5d)bGPd^HBqDn?X8APJ_t8(M=3U{yuCJNUb_%upY903okUy3D0`L+XoxCEu;1*_QNyYKl}q2nR7B6!y`O# ztrt{-?S~D#jTCa5w@_4}Tl+QzGiuloMRXF0hR7l0eNO3wf^T_Z?U_?T7?aE zyb^I-Va~vY1_nF5UJ8iP2F_kL>1xdl;jrCBY$@Q~(P%*Y-P(~3{2UW=z@Qy=J1%0W zqUgymO?Iqhh;S6CVgnJ)tpSytmze5;0}}XiOSOQ+nOWAulLwD;N{N}g79#tOTA zT7#7>_iN~S33Sy&yu$69Po9WyH@gVZK}@jTOv;_Pnk+|hY}X;xpmFZQhXW%I^>Z$f z3yM%8zgG6cK|aATrm>l@??!m$MHUmdiN(!P>yI9KnUr@AgGGI!rg(?{3k?uk5J%Wb zFW`Z2^R^E2iGk!1O{bvp*wD9uTYITMt;kdV{quP0$)|!NoTE)eT%Ty_f??f=|M2ab zI@`|x>uqJz(oOu!v@1A|EpgCROxS}s25mA!*QdWO{?L`87$7os%-4@TDWW(Kp}95?20`=D~R zKu&r9D!+m<9MQuGlJ|_EFHS}!be>c{Sbo;LA3Yh)`4-eywFDTU9$e&*-A(!AzG?eB zJ#Qr+6AB29!s4`gG9S&FkH)3hR7TC%lhpSsY9+=uG8p?qQEZa+2_ z#T##T-QRwxmgkQ;7LZ5X(N+2?dY3IEbNrc}Ic0a$ZKA9v^iuOLP8R?Ul;KeR-^w%6 zjK2kWLjGG7-6n+mxK2w43`izq@eLh&)+W3A3M!b772n#V5l+KvR3Y--5=ch9{zE?( z^)Fq;0S+Uv+5RZL)!y1h#5VA-uTcU!CQy84#|QJ4501uYsDLd)nVlLw61YA#puN`1 zQw*D473Fb*W6ZbXvR#-mA9i;4MFc3dsY8hx6ccbC?S=ZcA};8Ml2` zkb->$!4F=cnoNRbZ=|;~oK6 zM4uF+v2-dm2W-9VC7j({&rF^JtUML4dnsWsCy=J(cX0h5AQV%?-1hPx{UPn3jsHAA9eieH{&PQ-1|I$+Nm?0nKKN5=)GM z0IqUbS2J>moL1G7-BSa}-l1E7jg$_!LJH5eczI#%%^SfYO2KkY`wYozGgJ@t)htzl6pK4ra-sqp?X&vFcV(3*x}lzW@^p4Mupt#QBZUFd+z{XF$6 zK!Y2T>Tq+%gO>;dr9pH`o%gd4F)v+Xy>%e!Z~+i(qCuh$?%#~`*IKZuPripZc!JoT zguqU5Y)2iJ?|%k|^%633ziwKp`Ywn3h@EO!@Vpi?naKhjt{4rt-ECv`&+lkT$=>-i z2Dj61G|Dvb#GL=52E4W6iVQ`s&0!@Iim|#8E5BAi;5GGT!k%|TQ|h{unpVXe{-0?co(+)<$Q4<1HO_wKFD?81d(Vp3;`wXj~*l52YaK@n?OyLa zHXmtsaK*ZO*2g;x(+nGrGvyD;hYDTZ?>BNL-Sikasy7|lE}k1DL~p+Tf4hpT+S5eM z1l_FW+$i1B3%a*}aBLc?h?&2WRDeprH(>tm2JkslC(7MeV;H;d@4OBwPLHZR{HX`Y z!KAHFo?jy8ok8HD|NjC0{hF`S5DR>#c2akD$2CAT!?HnJS=9rF5D`l6Ac|9Hz;__&j53*aof_vZC zQ_JENovwl3s%bReU#Y)!!>zLIMiT0>o(fO-3)5xo(+%2m3bioZ?U~n=4T!F6+O zZTMI~WMhTk@3)R1)7am?tmIgQo|-6zMeA-8$Me|BSjZ#9JR6dHA;=@rNmp_WEsE{qes(Wea00EFE8ey; zv#7zp`8gW)cZSJkxEvH_vTd1J zu`342({62ibf(dFLsxXP)XBpRD%!YyYO-*VzhX$5zX+UEk}$+1Uj4Ysrddz5_Tt5% zy{UHCuy)(1XM^i5jjrAkRn#VbzTG*|LJ=4O^h4}+D=il8WhMZ~_0i?HYh%$yMi8@o zU8{`RwGTRc+FblD&NC<+a?-*4@l`?c_Rz&(Id1vY%Iig!iQV%9 z=W@-+ayzURxp;x$m**a+bL!;-W^6&`>G%T|5!qu8yIAF8Bb*qIp5TNwlQ#(zA)^%O z*y(8YB(QKsXS)ftTarv5wI1*;DnaI)ZiLxeV>$zDg_SJ>QDYzbTNeCUIy;K5lOVZM z**A`nvnV!0V2bwO>zRA-N_AV(6ww%UB#29fIqk!A2zCPX*5ojn04h+8Misw2*rAK0ZCh}n(%K)>R}CrWpqV24tb--pG~@IYzJ3Ko1|R?B2#=_fX$c zZnDpK?X?MYI1*!Ct&zeHl5g1Dl)oZTzobDaRQkFbj=~h8bnm_bs%bi*@pdnBmc*z?5KTL9lbLh z?2jlq(K7C9xOSbseSC#jwAgc0U!Iqxl3qX^2{SSZ6b+dWPwsx2B z=98N2w26W941>)6Ca$d|P=l7Mbtr%#p-FmuHOk`BM{63@#O5RxsR4*v#htE9gON!A ziyfRzMU{ww>u4UXuWFvPv3+db078k>JHZAi!HAXJi|FQ0qkX*M+M^H*l7vd#CtEj3p%USmZ=4d01cpasLH&xHY4knjdcb{>w97UnoM z7QEO_#ug0?=r>)pPUt-P#fbDtH?&?Qy#|GN`0;@dX4R}srtLGZPL$GK=z1+zFbUYJ z6wQ!JhuVZU&QT(X%k1{j|5oMWdKpxqTg5Xu?4gVT8wM$xr$sd?mXwppbNzY=LvEw; zDn9Y8HQRjTgFc%F7ToUUh8L(c-Z+)L=+g~cK`-6&y>vGhIXo%wz}rE+vSj(MW;sH6 z)gRm9ho3x?$FQho3W(N=FQo}=PZT%Q`9tI+Y?T)WjSvaTap4I@Fo3#oWXd>AJq!d( zkpB2@)yL27u%Yza!?HXSCJrY^g4)LthjPID=kCT`v0Pb*)%|uKEeNZ&hCo&f>)rct zj*U|m-VvJh3!BL#i`&?pZI7SlSZNv{RebN*+{mV#Fg9^$^IzMKg5qILQ}@dfXWuxA zdKY1Udmj+V!fJrKLXClhyr`H5$`dd+7>GN@DVS$=V>P?vo*`90_4gK$7m{WDf>Xz1 zG-u)^NdaUv6B=xENjIn2^5F_wiis=aQ#`nmSAYiktB#!?8A%9+p2Q#-yTvzP8)}hi z%YO6?pU}=rtvInYjn7pZhN?8qwd29-nT6Uk;Q;q_DeIdWBt}~fv@_0$*zWa1+gs%o zx(yjXuCjW`o)K{PZ<0mgaFuh<%yF`4XzrkKEa=1BRs2n#6Wmc#G8)mTgqXj-3!HF~ zgQt49S!!A?N?f`&&*PugslS(#Y3R2oH7iJ$EhZa&+30ErZz_iEjHGPP6cmT8{`6qd;3tmAJp&``B|hq;7mK9TFW z!&93A?U{9xI!YS{^;;EeG_<0Y!A?tHQ0E7=MM+TB{k^4#0%8`>BFG#fwCMTq!Lv!8 z{n-x{_%rRBZuXDpiRyWkW@4Sos$rmKSxu{LXaGc4D=4=>KVYMfo=NVx;*?8P)lXD= zoIfa))XPG&9o%8uw%~B#og*#p@Pv@XSr2%IG=XZqT#L|HS?~OHX>BVQPqAMDY@(fW z(IlXe4X_s6zpwld`E`7_ZV!!|D~73!hr&X!+nP6}{b&>_ZQMt9=*IME z$|!!kr2{1|MoV1svB!&2+wGHJr%o|Gvui4CJ%ib~La)NN_7HRW zLs>PrPFN{`0xpeX^4)G`@6npgU*P$dZcAil%t2Yo(8!OpDPQR83=ArptZ1en0ickl zVtB)g?trsj4V&&E|5P?dkd3LLuSQSHZs^`|s{>-p9WTF;@0vX6@qxqxfJ@m|qwIVN zvG=9B?QPw3t_cD<$tzV`d_n<(dmb*z0$#zv;C+q2th`c_gX3uN!jN%SvKC!>-HP*c zCuuFol$9)XRs^M8u!F=k*J!^?oZxfI5x8K@_WyfnPjDpEr=YcWa4v;YUr!VYJnzrR z8b)~?c<(Qw<`-UYLQqBlMUl|4nmrfb&h>suag%z27FWMJwt{yFi+`c~2*7!iwXdRj zC;f{-dq&B6Dcc^q@SaNPS55T*gpV~{C0bgi4gHu!MlGGt9*kkX6Mk1PYrZxzx^W4y zz75|uJy`XiMj8W1h~|lsL-;=OG!)X$t$dg@(it=I*r(XCifOxtR>Nh>Vhk5hu=+9We(rlU4`^1V$l?%t-fFr!#HHL^}v`fB~$$Sc1s z6SiP3B0_>`^vSGTJ?Ge*3Ti62woBrbW~66EBR6&|RZV(k-+ca!pdO79d)EGnohrC> z^!_}ae5V@fKfTy}r78wJtDPBZ0xu=HYe}oc?|z_4*%#3Le(8OLE0$1Cd2Av+v*-_| zw**=9j8;QMscNGN^B&;1=T409#>!Gc?qT7=*KvP{LcV&@h>C;B9@)n-ls-;B3ejI4 z92&%4fXGSX6lnq(x8iit;3cEUIiutljE$C^w$HQE)g-6YH>DxH^3E%1p5lF4z3CGr zm~vi7QUcp65DJhVu8s7*7Q3+itTe5{n^)6H3U*J)?Ne6opWQRg)h#t0Vz&@U%*P{j zMBD?S*yz0BLGTF1Eb@C~Wa!0)twbbEeGiZdv@6_})8bR~=7XA{_IY{vE*(Hh{Xksd zMRR%1L7}_foQn6NKh#GMbJs&Mw(FSAmWxsPQ{8wzSyn zx**Zjg`pWbWet^6#V@1hz7;0K6po|k!+?3O` zE^>cv0l>@+tmf1~W7Kw|IxbxY)>~c5a%_zUw*+mzF@7^#H#cl8i)t#GCY(JqT42)% z%(?{fYf~m}BI_Lec(1~%2|Ryc+y8rNBFk7p^xC|RQ4a-GhyI;eiT`WsPmk{m0 zpSgds`qWd1SMo^6F+esPZJ&2-#CjLX-#uS~H-aI!&wrZ7KX^0g*!pO|Y+u!Y)Kp+H zIwL$sifjw|vU5D}uU6YU(zKBbb&t&|*-sISL-L{|D(<)MH@rTXlGZvzhc}ul+2qx8 z9(q}V+tP3kHW!k*WM8xwwZ(G?uYY9&S0KJ1_e3!VU#g=w^Ioen&jI~R5~^+b^>lft zS1oG0!=G@E_y4Wxh$!r*3{K~aI38GU`@5#Nn%eyD_Ya9bdTfq4%br zwQ+BNmu=jT$JM!n!EOUVkXj3uJ5#*0Gu?}12{QnwH7UrL@2aE5&p99T-Z!=b93M|{ zV5aR-Mb6KV8*59rOtUWRWL#Z(eMDy)Y$9+xM)s|6GRCLc={N|XJ@)etxG3OdhhOb~)Q z(oayHMHvPDbE0<4WE$G~loHJHs{wKlDl11V5w9Y@wM_3yw&J$z*g&TEvC$>{6{Hrn zmKpuORs54yJG|x3%I<(Y#?da=2=Pc|=E=XKb#n+*9jK^SuDmXP+ug2G*g4gp#n1TS36 zUlqz2k=c01KHS}3u%1S>FpcfC8;a5oFbXumw9ZK?dC(<9xkpgG{c&uV(Q%ITI^PF7 z1%+YvnafbjGvbsVKDQUXvD+Va71L1r8s$JWg89u-US`E@Opi8<4Q+CikVK;)YVFC9 z!Uo|TbnqmE)lGeJATG5j?A~Fv&YE!A3<(ajBHg;r$22*W_id2hWs{&^J8}n0Ld~YO zXO`Z5BJ{K^!2V=M-7u+V6Q&@*{_|l?X zM7jMNEH5z_xYFmQT)HBM9C`ob&zM)npYHm7sT<({Od8JO(#(}suO5X@Xu66Iglnri zz1lNxl1^rNUXY_KgNRkX;|uYK&D|59-kc`;9!y~4hSJf`kH%&n8T+Y^V$`I%g~4`q63ox1zCwpfukD#{o5X`M8BY>WuVuDxjeW)oUD!|XkAqVeR#5bc4 zuDa_k4GYVo(LCy4u}~f!5Lt>cAJ=<#f>NeO>hkyKsiX=2vXLsD%jwObG3UEv2M)Gh zIq~In7MiO-)zj<=@t#lA``N)n{Pu$sMgrfvhj`S@(RrUyaqV}tu5yP;Q1`k@Ie1VQ zj1?U{oLjs!m*1Xnza~qhq*`;|Ri3|--yqzm7G9%)8%fIbzeiI7wjCumeJee;?ep0K z-_#;LPJE-Uh#yTsh<>Y%e!U&@8&<(omtR5@wlZtB8LbW91!Z4bkK`n=T^YT|ajB7s zy%_V;a_zBkEHEmb07^oF>N{|um-ZN0GtV87T3f&%gjJDEMh2cnN=VQfkhLryFBQ-M zrl9Z#tOIBW3~lV0Xo?N{0OQI?ZU6!X;M1RcfjuhgnH|5LF#lvsEjI)iTiL9H0^dHs$Ylk9;%(~qc|I$hv(A(&K&yWb z2o>$9rw^m6IHvrG%BI-Re!kUT{{r5mHa~K8@hz`{^MD2Wp*!xesTdbJsbXc0qpl`V z2g==3^%_ZveVJ^T9%c*B9r1oi6pUj)1oK^gO)3cn`I-wHW5cs>mGmGO~TyIWS*afyG&Gh zT}UunbZ2M?14$_L>8pO9C8dV7C|9Fgqeny`@Xr3DOv1VZ2H2TJo8n3L0CoCuHRQ2F z*A9`%wTGWGkhQH)?vz_W9<*Pq?kUg@DtMfbp_&aiB98|H4@>C7-rEee=ie0J;lU{m zA1t1zAcDUq@P*gMvY%u4mKyq($zBu~2at$`g4tUpmlQ3Qd}A88Zlvn2YbP}Y!907; zxWrT}HnC1ZANARRc*mh9vt=GHsO0ZTs@0#!*~|C>9l+Mm%`Uv-t5>hKCB9%7@Lp2_ zCX_WrnW*FZHcvsoa@DRP%?wFzvq;fXCi!5DK_OYSP}>4PD)l6_?-}3l^Yunw^x|8x zm*P{}>c>;1Xc$&PSp*`w5!&rqtSi z8tIMKrkDAZzXGtLCb;*S;U3{u02+iv!6m?wofRgDrmx$XdDgeaV<*fz3YlIL#!r8Ny>{~a;NZ>wFswt7omj5ru ze}>%9i=I=EfN_W#e)~`8d$LaDxVLs(*3@byAoTB|(;-?zQiV(rZt8fhSy0?u!9^Ee)$GZNHhotfRMi&Yam| zp`E*>hSstp3ha4@q;Q}4Q=Z z@;|uxUJ(fG<5Bc$_qLMk7tEGJHJ`3YZ{yH_Ks;`>jukm^ez?lr@jWmhmMsk5^z!mi z)wG4vz8+P}=#cGqw>$o~Dq%RbOoNOQ5&UAem8_*8mP5;jZkHwEWzzwTk-Ai6uZ6V&_%Be3?%UQ#XiPkw78YAv@bu*col{j z93l6@qqBPJphgmLx!2WWb-MQ}YVyMYe2(brf_|^Ot6IO9o2HuL0wmtcg9mG>)#8Q0 zSm<^8@0QE3S|CHIuqtn>mqt%zs1Vp7$idQeKobO-p=gJdhwKi`paPI!*E3(yQh{GB zaQ8mZr*2b#+Lv!BNCz^FNjGBS-E)A`Sk)hj$M8eM7Grzs1rghsEpr6O$mb30U~`hs zYY6|2h5~=$UW_U*01F`s!d0L838Pkv>r`OZy0=obN^1Ah9{k(EQ-TH*r$GBhqLMkr$|M}y;5{_DU!?Pepb1}*j8iKX%4QbYDz!~pnYGLLz5V{_j~ zSs|H3VO4h?Arn+_Tm2F(WlMvr*elpiYNM{gTuPtPkp>v^zlJZ-B9_~!IjPF0^|W7) z@tf?-f<>7t7XQ<%$vvvS@Mj-&3N)E`{?L0(gDQ zPN^%&YS;YHO5&xr-TL+45fIg!f#J%DrbAoa8rdL~W%ZNLsTlE(rx+b90hiZWXtmDPqAC_~1Sa@!uM=rz|7y=dXmQBMKN z{r-gm-!8!aT|v#(QFGeGf-~YT-Y4fZ12KnoW%IzqB4~G9Oj+>Lw+#kVDZ|dS=^7p* z;Q5NGCad4x`W!!wTQOQ&hz{&A0OW!n`U{8Xa0`KKF&A=nLoV>IS$s<|D~;kr4$V`x znS~>v3yP=(so3)Jj@Qs9K&R}m{^df&ZeK{jpPzCtz8jHvNC-Y%xN%)0-JhwNW5y?{c`71aT?ciI? znZAsPK@&7k&J%p@wWy~DfIP=Tk&7mYsCQo%?w4VbF}fi!xl8<(Ew5;q z*G_FetJiW5Lt`yotIG|OD$Lu6%I5L&Jm@|D5`Ve2_nok!_C^2lP-`2mB^b`hmHFCb zrUv~@sZ{?Pe9*#(*NW8q>1_JdfAIkS72ITKz)32$D;YPT#>SPcrXF&H-LZ#KC0m;^ zn2@z{S0)eyj7~dcHzn3Y=5ZV7mzi{(_w&quRDNG}aatjY0B_NpLz`9En&DY-*Oo6y z><8gZv@AvkY4hyYpnYJK&Stuvy@=Q(^2}(%T>F(iCFN|dqMKU)0bDbGoD4Kr(cdn$ zZ$oCx(>zDRauBudbR}6@Z=26w`$JJVxsYWII97iCR6C0veknMvG5uP>!wcT}KOGBS z6C8$TQDEtUZsS76!2?38d9`g@`-~n&&#TNwjhY@TLsHgF<02+mnYb3Vx)>7Qo~gK; zIUQ7w@@@P3bVZ%w6X-{i%zqF2{@~yKWp~@rXNm_bmx8)% z7lnP=B-v9sbe(#G@!w0^_H(?Ks$Rqaa;P1rMO?5Rhhtk@yMAr!lh}7lEsqeh? z8=ylhx`J(<_eI+H_UFAHVGCDMe!q&_F|j}TkCuCPc;A?r6#=6fy)SuJ8++D01ytW)Y;P<-x0qPFK5*XcvJ7KG3({CQV%diP}^@fqqCFV1Kjpjd3N=CZ0WW?Z` zq~pH?L@}t{^zVheuPvpi*5y;H<>AV$7HK|$jIn2=+t)uzsiCu0#4 zN9fnnhT2Jt-G~Ox)_PV8$>gD1hlyk%YGE|=%Um^gF$sEW zqBfYSs^!~(sHHw7qsJ@wA2TfAE>wK;v(;0AWV_*8Zm);|_ys?tc1uPIztabZQ?0;d z40l$96*KHb6wPo=UaE_|HYl7%+$c-qmKLK&F4C6C@oBmKctc0O_fP42xwjY?@u=>V zN&LWA%_Br#M6aBrb00j!o99=Ag|dq2{var<23>q74E*0^CHtv!j##9qVKwWRsmwr3 z1ZC}|zsy<-smC@VC-=B z%_0!RKlRjcB~6h_v#%C{aB!Yqye?dDHgJ{=UA`fK&Mh3`R= zZg*4m2rz^aKT3fx1g~S2BUko*cVHd+!xph;kdcf*E22lN6!=a$;$Yo`fjJ28L`_v0 zZG5!OGo+d}tiPQvviw>7pVnC2IxNMhJ?1_G zmNU`G?e*eBSf|Q%vwOJ!#Fg0#HF9Ty2RH9ra2(}i)$3=RM)7Ph1*)$TXs}Ucx61V@ zkjQG@F+I3Kn|-haj4xFbxvWOtE;C2vx03do+(PPnM^Ju{*AqZEVebSD3fmhw`*hfS zg^Tjp_AY2u-C1h{@CV5;K8=q-M6`z@|BACk)Uxo*c!VKFJ*R(QV1UuBo_la`q3M78 zq&z*0%X?6+FaBKlG~lCQluxjb>s=dZ7cn^iI(a$+OQC~67?D@bx(P${jkcBd8v#N> z{N)=+RkJ{NFZ0aXOdErR5!2#Y@FP}*#2m=BGo7kss{CAc$_{FDNTVJ`v8yKeQyR;p z-VCSS@XmqN^D*=jn`tO3$=Jm`nP4oI-0KML4r zB1`rRRIkTUWWE6r0VRbb!{)U{oH7eO_<;6G$DhX0>n+ALhVATrll2CB!EnWD(R(q1 zFCJ-HLo@JF3l^#78UsCx*Vd)x@g4h*GdL-goDxIgj#oD9ddbN~24)8N> zU{O)$5B<&``|)*z1{Exk)J*IUD!O0`__QjXKvj}}zoRCl65$QzO{yr&-0x}^o9(UK zwi=3&8A#~_T~()-%$|f*7G?Q)8Z46+ww3RsSiuU>Hff-xj)tVy5Atp7c9BnB`4nS1 zOSW@sAiI>?3rkm%^(=JG(3qzWPoFij5Q1)Xb7$!ehITbKQ(VWFM`dr4djT68itgk3 z7t~uGRd~{DJ3YI#9J7m-{TJsjO&)ErwSUJj9Rf!%Eai-h1Xp9{4gn4Ebmz_nalmM@ z8UC~1YwCkT9rMI;CBW61S1sXAHmfy;bU(N8haL=GD4!?sn0(t$puhKR5{P%kYm$aZ zELx0dlf#roq;>Kd-vTG{)P5VmOyR_42tD}rf}oaGQ&JW%{5^eVTj?L-#!^e>E7hMk zhLXz(0Xgyv8J4Byqis7z4PzSy-FRvV*rV@i^r%hR zT&^n%sPW`#B(^!zc!XK4t$^r$}2t>oDS%=6L-puTH4T*pPvf?7VB)Y3r=Hem2HqBEOC zs3|Nx@fUk{+@(VWVgU|X&TBC+b1mRc@w{#RGh=x z0Ff;#I@&9o9E*MeMLGejha|gXe+gqB4EB!BvP-o&iNxnTsd_E|hbY4gG%Jj_ZRsk| zgV87|6MItciy^i>sVRL@@YZfg!v;@dG zk}~%?p-L}LG%RG6R84K>Cf4jMIuIs=+GfDY6xQZfspmOCZaulIRfC0rwBd%Sji?>tqr zJY@uj2Y+{yJAK(M2UZLI4rtbQ5OF_`Ug_&-Mr18JtJYDUkowXMz3 zCAs;6@(o5n81VDy3GAy?G|SBu=fr`~8iE-imUbGr;H$IH)q57ZM8EOmKpT@hk_v|G zr0|oKEr0QPZEuz-{NsSS=+`I)LD+0Bk@#-8#FV9sSM9%DXCUCo;o&H_TW+ur~Pd>#1tkIm8 zSG^L-Yo!g;FST6(l*~nd+&8KP8j&3inL$HnnYsDc4Uk6Msiy^9KkbOu(hb0))0L9| zOvmGCY?rOPDk3xiU6szC`*_WGjIw2y;2$l(r9bgh9+z!4EV`j*nwNS)MV5F%qK)E= z75)NvUH}8MsZKw>UU%Vxy_b33&#j{>V8ILtG=1>MY1y9)Yc@gXHs~}b*67FP)eX{v zg{4ngcYvxQ?9{`&+5i6n)Ui~;9T*X#arC&(Wel*FEx#S9Tyj}iDm~a=@1j|9461?? zK--_nOh@dv+t&+s_4d$$>J6wX#vK9GDg7{?$?Plb&Sd zGtYzcW=;)&O8lj?sjBV$Yjp)a6sfqH_z4+^gVEJf`(*CYkD#JrQVSSMWemQ9ee}5t z>a>#0<9R7<)m(?=e2lU=)|<8-TpDi6{Hp#!g3!n!1Lp&w%@vqyUtQkPOBOfEqZ*2j zzI5dPCcBrB@uT{B^wy1e6*CZ+18%2FfrM$iCb89k%pGg z>Elnb`7wLVT5_X|Mz1nnE-IqIKv+Y2PPY5%F=Go6JsNVR4ue3^A%9qR#H}@XGw!vh z9Vo>(1MI)I2Jv1TtLhf3*dMBdJE>&+nJ2HzuR|^|Y<%riER_da8QS=|RS^vks#JwD zN6B7!(@zW}kU^73R6e+?Yqq%XZpt%N>+)jBR))!-5Vl?EVzZfW(-{rma=(`#c(R6j zKV6}KM75|tTB^qsQF|Zk2BNKG=Xq0m2`XpNSyB{79qZ*m%Avf~A};=i{)Sf&bHn}I zqH^g_0X;azH%!@T-UcnUcL0NJzn@=mw)ISUFOk^QLTQA(TZ5tVLx6SklQL910XikUOg(O zvg0Ev1sI!I#GjKMv9Zatr6Q)1+m@)nPgOrMlwikpkueca_%Zqhh;*VsUPCAtYfwvy z$`3_v#wSaB2Fafg=5);bu>T43ib#b<3M$XxuP6HWJY|V|%vAh0#+2d^{Wt!Dv)$^e zlkS@vo4~}g5n>K)ji4fuX*o|C*^djm%0!kno>t^6qc;AhWtvpa%u`_euGAMyaOF67 zF2;>vJ-pJR3axD`mTlfRtw}IW#}1rx3Zvf8`^~X1^Sj@?MsgKUVImiXbr@Q*5N)rP zs8<)EH~H_5lsQ2{c}}QK&xm!*7K|^1THGywRM`?AoDe~)khd7#*)|B)Cc0@oi%K*m z2AFT)K2hM)?=Gyx{DDC*RV)v~mpxsPHBZiyOT=ms>#Jw^<&SgwO}{Fh{zU*E`1 z;|r2d7EN7r@1c5x2=>__NIw)fZlFY?B&x7x?ErK|%jbI_%3T6qbY^eWqRE2Iy?)eL?2 zWn`>C?0Oa)xh#00TJ@>HNX31TgG!PO-iswp)Vua^|_i z{^owYR?@7*$87+p7J^J}CqDK)Bx^JP2(;E;1)d<39X%RO2n;MPME|IA5Pyu^e7_2m z%4RC3=2dm4w<3uc@LPNk(uH~+Ky#qS+uS2X8kXg+x9TzAyB17%A^(^x#?dym-VP_#tHeT-$@Sk?$6;rOsQjk z`^F$=9#dMb=!(@G_k7`b5?|zt24;KFs*tQO=|^w%+?rog{(>^h<7z%eP)$R)Kq8@V ztr$xQQ2+yR0?b<1XZ8Y=#1eSq+Gwjo`8_`>``aR)!-!EDzfHUL9T?dN&e_k9HF;sQ z3;caGy7BJCbZQF6vkYiTIk(&xtp*Z6)gsvvN944;sQ9YB8<&QiGm3|gShKNF#xMlfzawzw))0+~|Nf1u|e&idLZ(Z`HJPV&7@A`@i3Pb7! zYPLVUVJI(mwq*6VjN0CRr5Y&d*4PTNPxI4Wk`YkbCaVYpBYCk4)_F`DV!mTN!oNlz zWpb3C(x%z*vW!z=nx^oVAb(cPH_R#-JTkIJw(i~fUE)kooKy>6(Qhhf_`|!i{6MK8 zN#SI?;nL%gkzc75^amgB6;jEWbSc^QRoI*7sN7%)U_ug!j0uf|1d1KLO?^`VsUvt<@a+LX5*8dhj{Pbe z`u^LMCM#54xm5L{4GLtgkbm&>Q~!n&8vNrOrnnx1xsRwHz{L{rI&h(6S|f7EofQu= zEQUc?vsRG~r;SHf&lz9b;HzY)-I@@Q?Yw zJuI`qo%K^Fj=^%HBOHdH>HTGXH#G*UosZaMNoQ0KfzVJpg&Rj9$1 z_jco3V6YSb zf|agmzJvB+oyj&!K+y5u=fdIKL3Iiq0RtHQ_vdp#zrS|^ZLhM~#^Q<&Vb`1ilf(c=;AnpBYF zUi0t|WI`78yHqW99Hq=ey$zs_KMB(|5+iCsbBiS?TPFF|OL)iVvh8P)VRW@M(0^)y27)=L9G)_^rSm5rTEz~Tbs4$n#+*VHUDYV zM8ec-rXJISj*RMuZMX~Rf>w$*5KSE9p>kjbEwZ`sDckUZ_5$Gi+9e5EeKzV68tzDu) zPA_=5r%O+#hV2pr13Yz*35Z%B#L;yi8)y!@CoZBZNGt4sR{@xD4A-+)47dUvVNG!1 zR{VPNlY-*=_UcI$@AGod{Uip9Y4H2|d^3Nh=qlNt{h5%+AiR=+zM=nC^ij=MugfYR zo0cr<>@VPDcI-XKZRrAtP;^{E)U0+f3sSe)#>%kgEDa3CD0F{CK!^W6SQ5J4=9w8QHb< zKdlAZer{|`s-oxym|GDrxK2gZuqe)4PFXSgGA!v#m6tIr$kK6 z$OuXFg&yxP*xX^0BAHe;BQ~@dCXsf#mhOK6;6Pvb7ET~eBCYlpWXWW}hkAC~Yxe@f ze8g|N+m56bUeN)`%wMmBhmL^H)8b9-C;~UJ;nYDg1Ous3nY=r65r`J zZa|fLK53M)G<(=mbM%z^UCDk#?;zO|t4M^&gUWN%qVC0L%GPWX2!h^5+IzEcWIr5$ z;=&r^fj%ZZu3ojK=yE=-nBlzWLlt~N&uQsE05%TkT96Pc*2~=9qvTzW#uRM;D_)qx zJQ@N1r!LUp&fn*f&CKGsc|}u1;M$O#-($9-PE2vDb*vM@@`Y6{ z-BlV#x51}JO6bQP{8=x0DHqzURyB(M+ zyET&lj9O$5KZAT)gr8Zvxi6kdq{Rbs-TY{gUE)^!Y;%UDfx+7xvbwR*Xc8=kDk@;X z`japOJJ|fw*&49#DZYVelc4Ucezukt?_dC;j5m{>n!G@80i8TpZc3s_T&<_W>T|xHRFADCpDk-YZFk-!&=JPF- zp9r`x^&BLWJfulIEq2`(?9-Z6nnISg*qoglmhyY#)Uk=p_#NX=jXqpNK!av1d)8p3 z8RH)y2RheBIFnatwxg4{81>);tE7E$_&nWZ3|4e&Drg!U88h6o%?X#eGJV}ooU~lY6=9OVB zPxCz=3hgR6nvC8A>-mO?ze^ z7u1a-0AVC8T}4EW0j(MR#OqEBa*1h(Kd)fP{*WF0V-gXG>ZqmT;Mx{$jRyC&<2g$H z>?uYYUV`PqfBP6!*2~j?V_adZ2(s=-5tJ653M@oZgC&0TJ3bEsLBi>i1}Ve-h$D^` z)3i7+%KBK*GvM8d(pYwSM_?Qc^HBrN^s`rYDxD29@+pmY-?Kpj%n<#On8Q?6|L;A! z>4K>kHB*(y4MXL}+aSQzlaorwobrCyR(g>4U9)RDX`v+G(OD`) zdM^L|0q`H@$0Ww~FpL{N=9)#@Pz@ZB4Fxu zcXBXZ#Q5`rfx+g-`hs^{9^@w#y#?7ZG$3 zZ7}tZcdH%XPmvepI;f?PU*+PgTg)+dF?3)Cl%GDzca56478c_C`zX-@h|} zn>_4eB%?Hro=~%~T)DZyYVxJm0tx4CWhCUDd*CH*v8@ftnF~sbAS5bs zgAGN#;RU2=5XRNn{v=`pegajL?S2CS`ph4u7kDq41R@>?8me>{XhYG}rY@-bs5wC2 zAs;!oAed)@H<{lKu|aBs3(YS$FkFB`@O#d!+g!7mjuRVTph|W#_2~%bA2a-VEZYLQ zdyk5MNR#S$-VpxIhK}yMznasI;fY|@RE+s~ornO&!uSh8pKiB24}23;F(WMp@G++{a<*yBzUG8V|&WP2|efCIe6 zt;xt{qj>l|w`D;^QQ29eo)~?+Dl~H#RN_R33Ip4~exa5TXdV~@ge!e3HN(;ab1^BB zB%?j-wO|TPY}J$!)ao8xFs8hQwI@tYI#ekI{U}O2re$;S5x}oU%N`;xP+IGm5R))^ zg1h!}&MS-YQfgfYbT@8c8X)36M;yy88K77Y=tY{do%{9~g{f0yB-}k9ulB4!915Ob zP?9RW3^X&j6ObIk>nR*Uxq8-+p>l-3@3`Z&CvUJD)U-)8reXw%FM*_G1=$TC00Y0R zBsnt||FV3v57=d?p!=1O?z;<}034{m!7VHfP@0rWAJp01g>KO72IcDN@P<0UCFitM zm{pqwh)R;~&YG>)UTTSS4tvz+odHklxVNeJRl0*k(BlayTPIRcoo!BFo`A zKHnI>w7q^0LxJy-oL~@e?dj*=AlQBbbuG|kdqOAM3@wIKNtIDt!B8Ln)!4QHqX?L^ z%FzUQU(k)_4)Nf|vG%UY<~sroo_^LKWdxrg z9zG~G?OT$5g4IF4@7UO>8FOQ*U`bE2t>|$nk{Lzy_HX@qxwJ4~&z>_n&&-iSi<}mm z>0Sgh0DaVRD+&%qDHQ%dl?=}m_XD_*t1a8|RUWM?vDuhgy$NFky^MAQuXWQI?m`p5 zMikIuqg9z#G+UO0*Reh2V5}D7&eYA-0>|SBzS7RjT6Bplv+*;}%*Ba0xxvf`nB@G5 ziFDFG;EE{;3RO~XfzBjSVga)$s0Ci!G4{dD2nUkku9EJL1uu>Y2-EVNe`ZGQ(Bb)_GvUx-JX^FTzh3 znC&yj$IQ9|-Iq2UE}i<(v!rqb6dGl@PgJs-PVjmeKC$K@p@IuG@;#e9hOZ`+?1maH zO-;hSs(jz&KhV1vltmQu3VaajUnom><%Q^SQ|I&?jL9jSo0y;U_$^6BN6D)ZbbobG zR$;?Zk#x_mZ=OVgX5|L$p5%t&ggfX`mgR5`&zEr#kF)KV}Kh{=~s(Byuv3D zZ{f;x-*zY`4aDGHeONo8Kf6914k9pLEG-48ZW1&&ry9tP7rRh04*8MA_-y&ZPZIE^ zqw}wFSTaiuD}4(;IYpuwxVLjZ16)dDA?5CqF$qJ142icb&Lh@k97b1+)W(vYH(8Gi z^nRNIM6$;9Xpel1(-&lPygVhc|C*`XK*=*oK zKB)(E!GNcEJGnjqm5)*S6*c(p%67JJF?_|Qr>P7(-LIN_(V+qNCh$iik=p^(=(Ym2 z-&HO1fbeKB;5*UzQ$JJ!c?50W=qy1t4Ea zaiRHtTJOjH7&HRee`q1^905%;mlHKBJk6ydUP(TH4dM5CI?rZHRuCsW@C zq=Lb#81T2=eq*2;ut4L5(%M2maC5RAW1rO6U6^#gGf#23k$7FRQ%*BK16>E5P*&Ve<-KVyxNxd$wtPTvn#Xd4 z)4+&iulLMovC1AE~G+}vm@RM`nX`reVrV*wF^*xT z%q2ZTrZ|bT${nII;sCmlS47f94YIs0PY$4wk)UMt#FCyFn&E?%KPO_lFxt($!I6DD z`M$=G_~ttPG(7%Fhdqx14!Be;Z3B0@xfJ=uQ?}ts+#oj^_qHuS1XHhmQshNk6OaGa ztmSbQsG8QfO@N*SI8%R(9{Ssr)n1WG%VXl7M=d|(1jcPIOg%~;cw1)>Z|;7zAPLWh z@v2WK@aUTk7sJ}E-MWR5s3PLkLSh^sJyol7FgaIC7M9L6_f}T#0KLZHQqVKEe}o9W zjUUF>x+Vkx>uj$;(67=3XVSjh=39VSPCe~+ncf>7xJ3B)BPE^ZvbsV5zu=ryC@hd~ zS2Eh+I$b?5x zyZf?F@9YY}vK{81DX1-uF)nY`D9NYvATJa|iM^2Y?dV&{NuNUl$S#0pk3Oe^2mj>R%r0i%t|9|f?x{qbIF8E4G zYW_^c0~bOlBeh_}l`!~4W>n9l{ThWjAKtb_kqeSpz8IB21Lx18KIsNiWNoql(Aj=UycsdWIE$d#lV8*O@4 z7n~3-4NT+BG3><{eCpvtE5Ly5di9U7!?#`f^Rfa|&A!4{S#=B0D2-TBl#Yqm!MBoUws0qxG(4T-^`DWtg=By46$fpimS1yzhNTadnjf%enwmzQ2jJ= zYjjXD7DfK9t4a*PBBF^7tWj~xcC7~E#5q1jm45kmW@cd`uchnzX1muwV3YjIHw?kd z0>|oew76229pe_97YcHw-QH(`7ZIEpzmRflcv4;pcMPy+;g^68^Rr$nq-(C$`{P4W{PUVfrMsBTvYa|z`P~s z!3|q?IjDrTK#OX(99fN^E3+Z2FkKKm@XX&b!|43x%_J8Qyoi68mx_DVVq`DiRB?jx1~zRy=5>Swu5N*k<$>9_Lg zOZlIUdqB_Kp6gfW+}XlND{l^K%fRw~{k|{qrR4P(r^RZ|qb;GJ=v{AjYLIsl-$X4G zf=0H-tvh}nG~&z?hd7rbV2^v>sKQJI5$u~E+g$avCD5ILwsGYlT;yy1qHc?O3kZl; z1QirK6l+t9g{!`R5RjtE1(OBc!h?q0ULiCW(EY26Vy|CD(WxaMDy_xSk>E&((AF@K zO2$-;Kd`bmFi%D-+#rLcXgcZQuop_{wfBu)qz>#;q>ghGOR=^nIf=`W{EAc7R0ksx9x6EKZ zScp;zpJabcd?`}kKOFI!B&N$&@tP!~H?8eKI^C+Sh*h}DH8h9fo0^{oza9MMsmuQh zAmB1vQxRviaE>076&}HPdN=$i?(hG!EWi6aEH`z47$!#NV7p`ROwd|6iVWXL{Nh}2 zP;)>y{jtlv0j=WVc~2bNNP1mf)3BLJQM3ujfghvor zSQ4)XUuYKrl;twaWFp{Nq4Y%O9vRNIoa{CiED(7{F9*hwCkv{wIMtZ9>24^`cwl*Z zBW(%eyCmV>QjwBHPtP{t?o!c<3JoR3 z{Yr`tVlojyuQoaLHP3I7PP5w|Yn;^}6~V^K2*i&H#snNcIq4*&I!P$L#@7haRzr)q z+P1&FfN;>uIK#jK7m05N#Qr9$2;lTeD*tVQh?)w@GKfV;>n5@6ac`OgOOZzhZIbI0 z;yY=;o~5}!@Y`4ztS)jw<)Wz^xA{RJY*&%n3EYwupyZ!z-n26;v@yQDD_Bi&{_xZq z_Xe-~WPUQ~Tz++MML|0zx_I};xI3jopJ09`rL|8c0uO-~vI6IUf8pD4GQJk~UY9B+ zifVs+J$umM1o2|5?&Vc3=T64|i(dwFf4QiCy%yF;s;kBFb;9PR5Bxoz)6{-+))U0} zwZnZq3!9Hx9Q2Q|UoaiH{Mc;c@j3026fm~Za%zTGd(FTxiaQvn8c)=V!<{JKc1=04 zZJ{@4(c1Afg52fL%>!XOQ&yv2IE8i}Gm;C$dKWcwb^LalzN2w5KVUz-RxVUMQMAu) zNSbo}yrE>?KZacGui3|iSp{ZTyD0l>u`IW>*7qZ#P%OLeb1U3HZjLvJe_k?;JMj5uU9*neN#O%7z4T_Tr20^zM>ns+|sZ zkGNN#4y)o0Jfk}zA}_xgUQ^QzLEXeRV{YT4V;q@7Yv()@f6qU7YZhyAwC-5!a+i&( zlJpOq9>i>`Jp{a{)*}cj;NH6r)c@^Fw_fnpXrCHj?(pK(tnO{#nk-kb&J5VwJ3*>D zrVUy2c>Frbl@dee=%L>}7-?PSR2EI%|DqK((|vw<7;3;@P+hK^ z#16C==j?ZOq>jO6G@>gdYXR_-xk45DJ+0;G^~)i&amybE^MZ$(1lb3Mnz8R+C|dv8 zp}p)Qx|W|TfL8Db<-p}>iF`!S)6VjYI>)Ee6IQ;qk3EPe1@|>q`lCwskD4_C9q$US2lr)99pZ6&tCZT8`W&PeaZLfNW_ARm1r z!rh!)00U2uPAkIK03(KlAVfVEo2?BRD9fpuz4-*b#K*F)&7cdFkJxIy3v^_JDj}zK zkRczk)v{!DrCg6Ou_eEac@cc3m&VQ~Zn)jXeZW zP5C(s(nV)&vd4c~|2yJLyW-+P{Bz%r*Usm<#tQf}+RG?Ohd3L>K*RN6zq1T%lnS_GSgnd;K+`Tzu&$l%!V!Q^?$L5p)Y?4?A0`vOd*#($ZNj#*GJh|HMFw50gq%O z$6bGk9&}gNLNn!h0h+na;R<>it9V=x|H<$@@m;h zV_eX;;&4Lw#^#!n&1oxjUKmc*2oRq==FAJfysasCrX*9#xuEc&tDMK%7<$-%d3iT~ z9r)~V@>i%nGCjk=pP9K1LXn)XiOtlDg%K=^N*t?s`<;pxCHZ8fO(ILLtv8OB4 z!L21C@N$G@a~r4Q_jB%_O?$gb?&+_2y>aEl;y>L%*>mkj7qB&uK!aO;X;7^iFcQvj zS$#_fBL|Fl_a3Z5&oJ!y^m73(C++cfKzt!~GEI?}_B^#oKt^!e?|!En5H*S_67VS_ z$nId3H-T)*#h>oYXd~22D1VRAuLoi%@ok&pGVX}kaSl_?$!ZS9DVfcaap+)#!(DRPF=JKv(^-UdAW z`1Gd{)*hvnOqFMQvC6giduiKo!OxLw?CkY6JF zNtd^(dKvfBL)ttEv|?=EKS^ba5Ju;@Y>&oj1^(BM{_W6MlmfGHx^#_2@D&c%Rn~JT zn0Y62am!rH#qj5FG;cCAo069|l0*tx zd^>U5WhBO8d;s(YS)Q$rUOK_rfo6=$YVj8+*=r8GR?nyaG4r+BB+LkK?I?*~la1|! zHh^^stqTpDF$kxd$xnf>9bMZ=OX0)O_I>3k`~{L-&Ntc8Q#_tC$OXO#ziYb3a-wn! zs8mVknc6L|PMIasGy7zd5vT?dplSETu^=_;H)zw?E5J}XUk_mSYRiSMHRcSY6KNKb z+^A(=l`TFDXVlBb!!s#g_w+Gk=2qe6z27b6@aGYJpM;YP2c_*YNZ9}An>8ji{#H~2 z$rWy1L2VKeqOr`y{WMIVY1cC4_*A_9>IuDz2e3$Pd+|0R$dDRj{93DH;3=KX-vF#j zwnFV;(2GV#{b8L7#qli!k<~c)AkeBd&^SgBOX@-#9D9FfrsEaRM0B^`FwWM=0`?kR z1jEj*X~zeqw9dZ8@d}vqvyle_K`lv1z&v$n%LTr*nxl9B{x{bOJI3`vy#*1_x>(v~ z2(h2=Q>Z-BFRh%D0;+-FGgHlp>up5>_6pyb?sB)GKXi_%GM7g?AdX;3V@78_zU^H| zgF=*S-z{JAV(}R9Ti*e*9j_VIG+rnJgRnoeZr(Y=_WlGQ4KlrL#F@*`rtfTy9gUG-jZj2$nZx|><@2cGwgQrRa*0$Ryn{DP^36}$Z{7z+oWQX*dOLmmV^YQx@bJSa zOh=lFQ+OzNoXrGz0bUn0)Ia@V45udPftpAaJaB6woK8f2$Lp-WqfTF$u@_hC+U1soLU)?4+6G~9vVWz4zZ`(caf4&`FYjodwFGxm|_)zTurQ7o7 z>+q}xDj=2OA;Q9^~ zi7mS2Hqj-XL$J*qO$m8tk{o<^f4uFGj!bhwq zFcmLZtBNcxn*=}<*YR?a+sDWwmIG~(zaR%O%ZAj_7AH|{D=POtt%qRq^=?)2%}>*X z3h?`@ja#J)si<5$#d%PH(Lu1a@;9({K&Yb^vrj{The(t(%t%&(XbJ6{Rx#ic9#J<_ zcSlGU0ce{4{b{81W$_^SKdmR;yVe?%6qOd8;NC^$135}Jfl}?BrvQjEi1b0LD8Qfs z>DNfU`|Kxzbe|uU4#?Dki;)0{R@d!QW z=_d?0c~51p)oXeuX5%hwYizOxjc?_tzR+Hv0e40h>zUKVnKP9Z;UDqO;VE?DMMU%N zIMoxkwSW z1PHnXm16Z01^IqhdouAn^A;V?D}UfjTmw|P06xjH=gAkr*gQ@JGNWky?oUrmY4akG zJ90a*q`RF+Up$G3RI;DV94(U|hFCuLd!==Q3T%Xeq24s``Blk zXs~8U=a5!>?^MisEaQ4TlUl_3Dnpj1?$A-sBFurdldZeyw@l}&M9F#WfMi4@l6`+F zeBfjXUp%bGuVSi9o8M1b%;TUD8q<|V`*?ITNOkhs7J*T5w>*U?$uzW3QB=-rD?p?) z|5~=Ec;R~J0uZD4f3NRnESi}#xA%%dZPWktdLR4L|8EGSz!J-WQ(`v;I z{X6Bb?-uGiUa_gd&EZW?#;-{}4C`(sNi^M*3>#f=|7=A8LZJ9SyE z31!VqhHG?`%NB>slGlGi7Bo7IWk9XHZw;k*<9Jtj?eGa?@xc& z-h01a@7M7>9uE>~x`%J%+nMF3W@Lj|tV7WCXi(XK7_59p31Zqc{#nu8`D;aZQt*5S zVve6nR2*QdkPm2LQcAz=1{<1ZZ-1oFV0ebts+pouKR}QC6+&YEW)gki_B^FCTZ0IwmTp%eGt{&wit z0i^{$<8~$KId{DVu)yt!o@@|)32Agsz@7Z9rK$$=7#!C3J?G}3^ik`>?j@^MXI*f( zcOiQkvq8MA<7tCUEWH|J8D~iDxGr zR06)v2^Q-T#awZ)UA0N8d8kGF-_zltbC~zq;#c{~wGj4eF^*|hT~&g)2f4)%FJYl@ z0#3MgLf2sZRA|KH)Ev}_luJ+0j7=#2%}Cc+fNa1#lq*11mm)Z8r(1a;r|op7`bntk<$Kw-jAPIElu9?2T208IH9N608JUArjHlPmMJ1H+8n$nC`HvVZ=`B>iTIh?9~S&yGL znIp_Csn);>3p;6iZIL$FyH)RsY_>3XTQVsPF>RQKZQLJcz9{B|GxJ>M6&wgUZJHs9 z8mHH^TpU|Vu0C;471c?Ez2|@R3e1ZecVLpU!8o({V@4y2S&QRJPqv07pMx!QT$Qk@ zkF?xXm?PATd0wwgUxFC+CwkebZ#h2DC7%(%Kk zR%vQ}T5ym-SK(2iu3*@Q#p?n{n{L==Mh6y_kh@_~9c^4joL;pCo4YozVo-x*1Wl)+ znw||Lee``9eCo_D5ftyB)&@`bHRUAkDCOy9hnH{Z^{zMSqVt+%X%LmCH@A|$?O9bNAe0sRA9b8 z6x~krX{H~j`rnaOdy}8TQo5Z=PonMxoF$!bxl>d4;S9q z9rNGz;qRB0x;Qg)W_ELvK$qSaV60`KJsRnPgo2-LFRnr1DTXpf5XM@3zJ30a39Z(i z$tITfpVRd+n6OPrLuT`QX+XTh3RP1~P(lv2ATSnKY3g@eHs?P+o!fNv+)N`Ymo|gyaQhF+pSHSm^GXkoa3X@$SF}E9y8f4vU`^rsDukL1D9}LmuC&k%- zzSs?OuQ2S;w7`PBZI5EQMR54iStA@L`NW*?_RxU6#`KLiGtR zt=J!(<&I9C7n?nltS{!>#$WF>o!awK@=OCQ9!$h0Oe36R^Vs?EOp~8>$x0evl99c* zizn2+TkvDb-%Z$QREO#x--T+XtZ-NGB1+lx?(YXixrA-;J8AD~ST@?MjL-Yb2HNFf z@Zbl)m|Cuz2j^AZwi>>0KQSpqgt^9_A&bL_7r$uk+VdvoaA=N~;lWkIEA*i?0^2`W zj$Sd@prmytumL~1kN|z{rXTilE*a{dQvYJ@u!0T!e_V8{5?f=cvb!yy)>xV%(xS|g z74PAf=D+@XyQKY^P<6+Dd`!j0tiq>tC|6suOiZ-bNsL*&26kZS=$HAZN7qzi>Nc|; zj-fn-nF^_cuR^>rqIxHr*rysR#e+E?sHx+d$(L(C9@)3H z!TFuWtxlFkFCI*vPYVw0IWy5Q^L69OwtG@SQ+09GIp|a`dzc6BBehJfKscg0^pIiP zY2H9!xbld1I3Xl&m0qUPB@X{S<0de(i*Hw(nc2LfZ{}Y^-hsqLAsb+e37CU>S+_Pd zw>W6lr}sNmbPHTgBgT#U)Ji)g zQ)z{`xLVNY4c7TcGi(oNNJ%o78hf#xmbFwLn?3t*28o|7B=}7lv@;$!Jt+jR<@iFR5 zW(qWYo6GU6Q!o@{y>d#u#UWr2S3AmfSQ2JpUc$`<01=j*YJa^f@?Gt#+^oDF-7!69 zV@Xw^Ukp@R{TXeJ*Ul#_Y+(h_Jp$n~^# zs;!wJj4qR#o2bm;ACYd>)`xS0f(V#X^xw>hNcSjUpE7k~)6s{8TYdkn zmv&jZ`lrDn0XuzObBWXdB8*~fC_SkSgOgyN!a3p4Q6cj1Diy(BpiF1ww=Y(kPG5iH zhR>V$-)(nst7%D<-bzLdjK52mTNEngkc8UxH&wS5`vPZ;-m=Tk5Xi9chf6{;tKm|h zwfZK!X2`>^%(;-P*7^O9&$B`27RN2+Z!uA8$(6JL1jX)K*g4)GH?rrUnDFZ!gi zsv!t`DU9%xQ5`DC>tbsw3;G*5xxOXL97$o!&&hXAB25W2{^hSZ9zQEOy?k?6dtBVW ze#!Pfz9$fIqyaO2J~uj7cs=tpqLcR7#Op+^Tk<2nJ+W8Ct;Nl6&Zk-huE@=)a70ba zHxQAF!#w3+EenathL2&i%E!sGD+9Ne?p}zwafH@Q9iDTKAu^0Qy4NPagzm>t+m!0A zp4RH32=Wx3h9(#1miJE}bV+GmHb?qPYsO_#3+6$@^OAu zrO+gO=CYFlS@(OrpW*oz)X6~!4Uo60go=AT$**Y8 zWz$XnU1_iu{Vg|(qgJs>7fTB*TF#anJm#_JADhYSD zxc@g@T&7-IDh?*D4tu3{4DJqVVV{0&b{c!F2fyqeAr)P%wF%6=<#X$u*?X%3RKy%8 zYNXh=m1~thnvz~!z4T7A{P6tSp30C(j;NcFGPqqwx;HB(l|m47r)j4;>9ms^e!9jQ84 zTR55Y-hglMds0qUyFg8KI%=+va^x{Ho9z@V+^!e!W8(9-y||(iHiM!!{dB(vmIpu= zWqgU)b>>C6HHA60%CrF-W;#NJSL@1uCOgdP%S{)?8y}PxHTM%Y(|IMO96C3SzIegf zkcdC3cPTh%9^c8%J?<$HQE}~h{qDsfkH~Mk*iB~_m#M#rtx=X>fT5A6zH@-=4pEJI z>flL&>h&D_CUart;>=;q_?1143X8e?97h}zaBlWEG=0w0Z^doo{I+v-q(v%t)mpjM zrTlpRBVcW>2Y633QIBClNJpk5Vj)-bmvsw+RCR%U?IEhr;B)!0-7hbfZ0!_GcL~(H zlX!~UHk>F@XVdRzCgp8@%~(#m=cVIcsLlJyV~5-&%^Yox&Qq8QQ5`BrgZoaOS%i+& z2PJQrXtcCNY9#u_y}qS(*?P@4VTC`FX-02k`XS+9%b@(7b3DkWGQT3tS1Hrc+qF)! zSGS>i|I*1_ACc&5HjUs4tsu_1f=ns;O;hLFBb9&3tM?6wtl6ab7OE<$UNv3}u@boQ zVd&QV!!to;^k+AzPD5ZeeT{Xr)moEYI3SI)X&kp7hyQpLIUUQ}+%MOtO?`NreGGiA zLAVre5LP?%<~i5Ti>0ym4Sc)}9W6nQD?HYfVJMe_?}}N_FpDE%x>cCxTZdO|;zLmR z71n{6d-*1jqA9Pj(b{r-_r!D;tGvK5?6nK83&^q~*y_K+&rhneuOrx=mz1Tbq6=m! zVT*n8)Ay9M4qqGZOZNO)RzFmScgGVK+aV3^Q8Wz|0k1TMr5%ny5P&JKcGccE+ITby(r>a8wqd42K)pt7 zm=DE1JU%?JaQ)aFFVfXxCx?}$91E|WrXPyM@#ZA zkw6!fRYcg+qm9%dj!tQ^8?g|S)Y(Ui1qm?2saNK?L{O#-X}h5>Ah-$&z8oJJ$CENZ z>5>P}L8GOHCrfIuPqjfnf`S<3Cb<9Yob?dZc=UVQ;@)7*lFj;)EVO-A+I%CmXW$;j zCjQwv)(h2+b`H-YJTY>3{=pSs?`W4~%&}#4XYDXP@bWF5dIjZa(t8>l-(|H+GW=Hp znWDAv*K$(fS`r5Z0?Y;#<$d7gc_kPfR1ax|XMrT-uNwzfM6(F4)@JjCg3#=74Cn{N z(gL032vVDtjfqOnNT9I%JHK1Xx2Rm~Bv`Q?uwu}0Vm|9>xl7bvjIdFklRh^b{%rsi z?^S}jgr2VeM`lS|wnLbhqvuwZ1 zlr1xA7dlg;TxP)`> zN89*U0}8R=y9s#h6?l0=aEbd;FON=4aMcS^08bh@F5`FUArw#i``xJa($=I@2b6Z2 zIDf+_7TD0bEY!2opB4LTjq91w(|_L(O3GTE$@O1$8b43<2&#jNoJ!w2zTFJE7VvkI zuQJp?%KfKq(5HRfB#C?ATjl@tYV*`#^l=@5 z3>v_KdwdJo{}sd8R{)wfB3ZsIA1lNiKta=PhveGCj>y^)Iay3GZ79N96KY`7f{MU#HBn?B6orPe6y8_p`S)ORQJ`8!mFfW-Tu?g;Wh$ zJdkH8tz4A!ghG8lndWSn)|mntm3$B2;9POAO|)DZF-c9tF=D0?NPS}rQW#39ED~*O zxEC7C3PRRbN)4oJ3-cQIo%;NdeOVd6^apTE@TAX>rR;0gJy5BAJ!VVx27W8?d z`9{$XC7I|OKD)oAGz0P3;_@RTdhC~0fPnuCVl>W2pue2EO3FJnlToWJ6;i_+SNPVb zhg!-7RQQH7-zz~D0{nJAQEO}PtJkgl6l;9Gz~ebe+4Yl6u1%{Eqfayl*QmlhjYhp4xfIaCA(;gU2nW_JA29@B8%bF-eZd7!rR)9$*~}J2A9-w$ zrATuR1JrolONyZiF~S+Md8qh|bQ%ptNB@r;oi63>#tPD!B~#5SDphG@-YS=j+i|Mi z(_adSDG{_bEiOuu^Rsp%C(Z*VPpTo?3BC6nOB?VzDvipwUFt3&GC%&yY&e2WL;`oB z$aCF6z)RCH|2D5wCeb8?u;(7>fu$&KD zA}j1a$*Lh&A&Ox*2BS=N*WJYRC#9ZbW0@2`%)l?+fI+j{;5ybs{f#GwB5(EZQIx+A zo6>pnF8RQlkiK@5*yaO_*Q3VO2w9~wbMh#~UOZvB3{+;*UyjIwvz`}lCL)7&d+^{S zo25K_6f-l)nIv}*WVWD=_``T{Sn^5s^H?eJuA7ZZZ7l~_E4m?Iy5d?auC*9ftTM*VPysp z&i9BTW|bv_W`FEl{Zoypg3Ki}##Idm=Wv}Y84js>o4RT3{3MZFU+`6tY@yMX;Fzt2 zI|fdb`=`?w-F`ZO1zaD(Uku|IQ%B9-uey~1VM_Na$gN?K{UnT+n1#11fXF6Fed?_) zpBQjPWB~V#56hR>dYdlB+Hu=#LOCN zM%@Ej5ZD7(-nD6ed-BQoW9yTtcm3fNc0l+L2G*d`e%h?PW>rkWD)jrb z?yp}Y={@f%8)|0I^lA-bnB_>AR3?7o9%ZTzIxV|HTes% zX3D-~7yb>DhU4DM{Va4S0|Vy@O*!p)e1HOOISHGlSD5nqK{ydsm%%O2+rRqoWMn|Z zdLuQvK4)I$qD%{w(QF}zj>9cPHfEc#Ki7%OPDn~ zzdZde?&Iah31)k7ukp7~?x!zQ<6R)TrcJjTwIaMNpyX|TkCWQJVRFn)-T})6p)k7f zu-?h)7~C*jNWa0gCGC36mjV3Imocix!;Toqc_r{?eb?A?&pmFQU$n&3y zqNaI4`xo~g78v=ss&KOV@Cuk`ImaYc%_8v|7VA>MD9eC`))u&>DNG}hb-^UJURL-* zY)=Cy4*!$LysFj}jhIJ8*$by(R2^4G8b+v+RA_$Ec{v&3%v)1eA*-YkaVq5L5L4Et zY(bc4!V{Hyt!wH#@8q+(<5NXD`#&9;)%5$B!y{Jkp%Nd3A)X4VLxuz0Bp7>9gSv^u z4GU8%@yB?74VxpcCYyGM>|dl{W-Fa7lxSWb-UUry4IM)Z?4-e zhVdVF_BfjWjWlE2T!~@(&*Lf!NW5;`nQ_^1CGg;$iyt>c-6o^ zR7W6qVV?jE>AAJB!E#nDO<_}OdD8)6G^ks`mEQKNPMue~504Lti);sdp)lnrU2Qt; zkd5fo+#@Qa&ZGEmLRHN1S8uH$fucozo~E2 zH#+wIFmJv5?NFr0u^Y8WrZ%FjR}l9D?4Ms>n6aA$-+$`d=en4VGYdNHzhn~nD+7Nz z6Ou2V)H!u%CD3@+l|NFP zLFcE@jMFxGdmT3Z9;d5tU$5i%c%!hRx?wL$?Z{ej>&kMrXXDVsiey&dZX0Pi1Yd3y zfOWo(Ms+}T%t!)XbNF)z4sdzM!Bs+t?9}c0*d*+pH<5ys312a~e!|`@@s?he%P6Ki z@RmDgEk>>VS{Q&TOPZ!BT-T&4Ts6$7`H}GG&fpEHEA89+7eh`h+z4XRp=j>QYB2ckfKD3ktY$) ze{)GWvv>FqJ;;~si3S|66_{vv`+t0rNRK%@^G-wJTT4o?n}Juzf?ck&LsA_4B&RMW z-9l-1ENJ6<b?9bH>BsYx+KhTsTZsMTYH2OSwP&hdceq!p?K8s1V%{Lw6mDpD zVH?faLA@f}k=ITSMSPKBD&o7zqN{Kns+eg|z@xsA*4)-K(d4rOal7z&r&8NBb|{<^ zv0W3hN4YWKXHA1EYkwOho##?Anm@iS;Kzu|eO_+G(!qZ0b)4PFr#d6c3(k~F)@`3=R2M#1nT8o}K-NG?OsG{e zwqWW%K9_;V2o(;}_`thUy(TOEqKfy!FnosuS5R{w@ip0uHII$(|M)sH6ENJi3t;?* zoxs_}LmlIGm&C=l89pq@Y)L(S%ce1^3nx1a#m}`KB@Lagp2iW-4kb$cfrqQ!oZ5YJ z2n_s@BBp=&X<^>Mnt;Qlxvq&{ExtVx`LV@W|8u7aqc9aY{pKT$)w~ZEwF%=K$JlSm zaZWhjVSXht{%ZbPcF!EbtLfAI56a%q{y`JxrD{<(!CK7BTC_<(LKam7V3?>@_fIn+ zAS@FrKe@|@sM*nU#5+|4M{dZR^5;|+9q z#KWAIe2`ssW2KcY9+H)IMZp7JfL>_jrCK|Oq%e03L)bslRlruhm{{H;d$OtvFzL`M z@_&!N7V&Kk2W_+;bRJcW^CS%5HJoxR0-UpIs7mF*fbstYhRBMAw8r$wB%euURl)lR@t-AD^*!m@Qx#MKF zm+g*lRA{}8g35H2V##Z3v(y5c=rR2KN6<~@l`j?Mg%WW^n%BHAnIEhv>1xihs?8b5 z@NI#ps%CYE#r+7QR+bXdjN76=I(}M6TuS+BEoZ!G@F_@hrzP7p8o!iv!0A3paru)| zO?4VO(1-DxRI*)-Q^C)@#2;;dd;XnoeNfb$K3Z3PJtIWKSoc%_qX*__`2$P{Vd3X* zyGqN&dW)xcDW*)-!q5I;8DE7Ig~uA|b!;gNSuV=Eo-C1FJU)k*54ePJXFH$-W2t8x zRnF(Hvnxn#p~9hTCWtJyQjP=}NOfC_9qoYa_BB6iwn*ZbMZI@?gw!AN)%#_u)m77L{z0! zP~6$t#?smyXJ78>)ywI|LzSzD1?uwFm>XIynn11wTnYW~={i9WyNH{@q5!)`*P zeM*W861)p^Pn>ZT10pIi4U$nC4k|u_Rhxg_$gnyf_C$1-)ZX{W zSGGR>^?xV^KIk0ywceh1DV)3q zJg@v-3D;o0VB2$ShkbO_$~+%9dIYUa)DqmEDJ^E)UUF#{oLYaApgDO5?&7l0pU6CG z6R&&oKfVJ|3D1qm_}a{gOHLQ!6u9}9_6QF>;&V)dRfY+3#Gd?}keZqxPLtDqHDrYm z0&H)W>)yH*{^amz{8Y!DKfm6+P~aV4utlcB`@)ao%<-F=rzp@)v-{WQBm2dVU12r#Ri7{ZoptNI zQ^U1&rYxGIvSzYDH*xA?NZh+mSVjt3lgX@^IZOyIOSAJfvt8UDD zUA%Q5tH5smW7;!n&za^$0kDI3?eVK}UTVswlOVEGx%1K98*@MjXD5DFw`9-UM`R~t zZ2~MwI`ptflt%SLjTU+^4)te1+DsLMei37nQ4-k1+|n{hb%udZHTlDYOqUXQgo+$q9d+sSCkKg-)?p)GO&vfczwrDVBQH+{2 z2YG9+G??Y=HSbVl2hEdunqS3bDyBYp5UHu z2Ce0??;}GuW>e>363i&$lsk|cGIfM{ z-k|1EcuF{Iyo)IasRWX-nMOIm^T>#vTapRa^)Gamw0uQLxEZh2lzjCie6ihNXHcH+T8RF>M4LBVm#0b*nAQ%L?hhwhrzibfPxw z5PQfEjp@%#-l}6zit@`wYWw9z{i{cC4Pfl$d8S$8KUc?GNCiCpo6@7MAi_EvjdP?v z+12BngY^O!!;5lXU`#vMhPA2iZQcl68Gh@aH3n~lT){NOsHtXGzBB7>UOY+a3KfWl zJW3=A&|hZu+}x~=hX)MpnHpl3xi+!Y<3)L=ZoS>*DsWQQxx^WI$*%C*lJ|D`^)rl4 z{DuKU)rgjnms*6{8R$k1H%D7SC9h zP|vaD$jlPDP7CwJywO};h|=O~nKTb+D1YP9AzwytPXio`&2WL=l)9lcOdiwbtJqP! z^1_0fI(G)Y$!W7p{6crmzPK15(zW(*r4!s#y!%T5|>E7@;9q3UEjyyN;~ zr)M#Hx?F0*7$s%L^rvqylL}T<4ut;m-P^U}$YTL>zN)4Ce3nE92Xm zSv2q?Jq?dqzC!J7=WPV?UtPv6ax%P>-MWcRUktu9PLS_; zeWv0y^;Sm|;14|>ze7&5`^KhaB{PC7?|*r3Iph6~M#lQl3b!>I1-RQ5&uYq)nmt>; z^VpCtlpwf8&;{b(W2&jpyj;(fK%#5+azr#MRnIfRMKACcKx^7RGL!q;Ff`EYS+ofH znIO#KGPn-}`SnE?2vesvs$H4hhJV^$082eg$w)6U+DsMf!qK5+@I}cw&{P_Nip)^| zqKD1S!0qhvde;cW(U#rvjSnghZ=r`}?J`i&=`k_-*PkA=bqLV0Mg7!!AG_5U$ia6S zARD|JK`7TPO;bUVpQE%j{Nlj7xTyXa2(~e)Kr;QGtZ(|M8?4nj}_p{6hjqeOfo*l#nZCZTO zoJyDK+Sbr;pq29E??k6QgtSnKuIVa>Sg;fb7BS6hO*k$`vZ#^I$9VTOHb z&9c@ef+rDODA*ci!RjdX(}S%8rl#UlvYwt3+9u#ZQ~R7Iz^+9&B;V=-^hl^oO^D1a z4sb>_7DdW&!=tk+_RH5(&(apE+|xf zRN8QB>|dtPjb753be2fb8@+MN_@F@_CCnc=Hk1V{G1kC<|LPeDQ-v0{&{Ea^BdcIy~SE3y#fC?z9d!)N7(5kF-t#Vh1gs)_Zby4bHmP|ZlA0PP3V9+!eFGq&W}ykF!JbZh z-pTM80q%~ehuFVXRLh`eUu#P^`?AisT1(=IV3eiolI=;xx_JAPVnp2t$OUh{CtOKO8DOON^uHS5z z!!o-b=T4}vTIV%fX&sn>Ll?3oMcfXNNb9H|Vi7j;;*|fDANz_`8334ZmOJy2yS`w5 z5T1lv=j@A^avo5g{Mt|`g6<&>aspvobSd>y7}>B4)bTp;9jy5`oYGO&f&w6fF`gM_gOP+$MV zWb=x=aPZcJ(MD)OO+Lhi-8?Grtznl-xInbxz^=RzErMJt106eMb(hUMgJyWA>$`7N z;)4cS3X<+5U(w^Bj+^s8PU)Zdje*;4--~5n0EB{oN)P-e@Aj}(+J@`9LU}tT7t#u> ziCCO9>953#QK2cp|M-+OM@14->S+IxwGX6yepFG%_4yseA=3)?y09h>KLRArV0Qe0)yO&4kj57g9*`o%n{tfy`uE3zwpa!Tn% z^vI%@FGw`sKXyPejSTt}(`jQ5gV+id%9?dR4|71M2@_*FZExhDQqNr~(~Q&>+N!0Y zy|Dd(unZ_J3vI0OO@i9-PndKn?prTUW&W?_*(SG#Vu6%}GMWAuiq>q;z>On@+dj&a z4N;y-k;*aUC7!%&V*d*KXchTW^`_-dz5msG6%RqQS^A#x6d-^RaG^ck7;L?4zVtL{ z(mhMptO8HA%?pkmj+K}}3DZ>>4=sN8XJf0GkJ^uKE>W@a7pjoth#Y}ESIyW=bc151jWu<+r z35c@6qgWgxcbk6Vjstz${ZPTf6FPx)AOh9stn1<*6mxpxuVka0;cKg^KV8EljV-JExBe^@D`dE|Q7N`0GIRY zj(k5TEA`+h_1Cj1P8F)!71NG;JrK$?8k~joQ-IEP>}kamIVM_d+lMDb8xbX?I8Y;O z_mRwRw_zTKyA6>`77-hqdNjHm`%i+ldn{R9-wCf)hq@b|w_W&7)yHhzf-2YqYo#*E zY!s&eOa|y|&F@<8=Q)A@fX$cwh^womIsv_SVLJn~!Fdd0)?Xn)1uqRCB&xa+X^Ws< zA#EcTFi9In`a6oB5I}2p!MYaPYM1l}l7~DVKk4+YCY3nW;UEW;mQg(V|Z@O7kaAzCZ7BcHB`e*)zr7vM}7JWXqfGiPQh{{ zVO!(M`+oy|=6ik(dngg)A)n}cOE~Fxo`awGWF4>sgzXKI`)06#qjrSntg@HAll@Lr zSPZJpn459}{uQYw|Dv3SS#<{&2Yu1dOWkZ0}P+cWXVLV)zpd0jyJ}f0@M_eoIXE z@!0$lUr&YCcgIhdfj&PrM8SOT2fBI&sd6{LbJU>mto}up((Yal*+FBYc+Y-#i=uJ zZj8{6{EEb1grzgfZL+fcCqf&lq9|M=>x6Dp)?*UntQ(JEBsXKmKsWIU?l6z)FjZA&qzb}VthPH{}-_x z(X#e$#$T+TfIh0gYi*1rRZX81!f#wCwCyzPqvhW*d0b~-V35Ji!?$fMqX&y2^H36( zSl95tRu$|*c>`yRQrl1w_JvJr&=f|t-p)YVwOnM`%mv7vH@#emXfs&_uPHuY0z=GSt5bq53N${S3|_t0Ed`F z?lb*%r-A$1ae#3GikM3KI(-rTi-`&Njr%WP3ovTeCywKrud%1AQiAq&dX#&vt%(X> zh}^gVoM2{?pZ>1g8(A0y4!VpQMo@$8vL?Wy(JHSLcw`)2Pm7XeoUjTNtf=d6Z(OK{ zb5~BR%Pm8l@EcN|sFWYHP9Gu5&we#EU8g+1%7aNhi#F!Ieu=bIy@`50R{Pk-3p|9r z{CQ{h8E|RE7}35jA#Vnjo@P2rUy@Q`k4-~@Nl_fZ1c&9nApH3>ZK>Pd)~rpA0X|9S zn9d46d(05CbdaOXDkEf1vq?ZOa;MyBCg$pNRyN6oi+-LFA8zl@KgvZ*E+sv~PNORK zmOnqA!a$;gHy_l|UX!eI`t;l&%Hsek{-N_ch64TMEX^eWi5M2zq!U=ZX`w#rKEME2 zQIBNfZB&pyN<_U%OqQtm7zFzmPGFfn_B>d=P7liz*PWro~v2N8d)dV zi{43XB0R7 z%JbIhtM7I~cjW?Xf|Zfdm(P#?AwxOpq{I)4KGg9u>ngNj&}g9WxNwnKx?A702E0*0 zaGS*vCrV$oIuKX0Jo-CP|J1H+H?lrYz|m7IaKjFhNo81^Yfs+@a%}J%OeK)o9|+p8 ze~|*Iu(qx5Cf4H51`f}2mrFAwosZ0>%GCVNsS}j(2WIjcfcYEAd%izG*QiRXYSmaq z)nScyz9Tci*&6z9Czfpb!|)wmbDm|+|2n%emDHGI_aq4iqMuI6Kay(oTv43R2%W-k zJ%B=dd9;zvu4H5uB;7We0y|4fdi~|nKq%-3N3yLHV@UoDHtXhmgtudLK5k3a+08E2 z0<`Mc62tRr-<$}hPYK4`NW98y{+!0MI!!$|p(RUmUg8}|jEfGOuZgJ!7!2)Vb~w0t+$_!~fdGH3Fq6uhdl-l?t zj8{|`P}FoWYxc=vAZ4C>^TCsWMm-QajV>}4)iBrlJsu(xBJ219xMv-Dr88=_!8S)o z?4YMz{2PZRA>PQaxzX~h);YW38Zb7F4I3(TDGhliYrqSb>C1T-`5$#!MaI(Lc7aL4 zEo-a4PjdyqhJFn_8g$N;NV)}v)3!yuHz^P>EQutOvw}0+Rjsrchh=LRQ{?nP2}*!5 zZ++H2K|51V69F1rs2$mw+zD1V6`TtSFl11lqH&rpKHLuAH3=NqcRp_Ihy_-v^~c(f zgf4)h1cL;TeqE9_{5?az?ahEH{2&&7i{w8EE~dv5o@XPl%tEWEfWKVvMG8~7?lUkQ zPaydjKNN=HuD4|(M+&`T41krG;qg&#K`)Re;W1O3d-D#e^^x8-*v64emOy&4p0cu0 z=!Mh_LXI&>9&V7(4~v1lKc0~8YnB$5R8hLK&$Bw0SPqDR+u>B3~9T@`=7g~CphmfPAs>!WCu3>cr!5Yxfgi-9VXTTbp?9>?SbmCra&3A^Wknz5_m@@)Koatp6oY zp*Cu(^3j$Dx`LP6wDktH$&j=4-mjROL z{#3lf(hQ*BLhZXhf9{U^Cb=6Q#v1djB4f*br!KB*$i&tmHq|bFGIbkb zM(CN!2ZdRsk@_@MfUPKbJf^1}%p~+O z4POmkQ8T4x_Q0*?ZJa9$(%Nt$e%Um44whE5lpe{-0*kW90o!ArLBM@l;oliAt_ze| zqObDo^yqf@BBPN5E-ajzTd}J4fy59{$*?QW#ZG_#PEwXWg>Hy+5aqZj^rf>Y)zj3` z)DesI_Tp0L_{j1ZtqTE$2hT)9GjNt1NT(IFLen_S1o#US#x8@IAVwu{D>?}4uB(ntb_!%~_zx=L) zpo3_^W2{t|9|v#mc?&!d-UKm7(2D9*zt{kDk%0erbV|BLD%sw^9ZXv-4fYEL*81RN z90a%9-rck8!yX&R%LwuTTDD7qw`D9FKA_t163$nw&FDD$=T}@EmN~qgP_^@T3M1B-H_q|Us2}9}QP=WxrtRTfpK?tv; z&u|D_Mr?jM(EOy?iFB!4T9qo9wah9z$I41$IY1UoggRw`#14`Al+Wc#EwF$5$Cohr zg*EtQT}>IhrS7L!E7UY61$@YzCzw+`YL820Z;UExiAw>Fdi&NS1eAkQ|Qr{-SXD1eBGT+Ss@Rf>ae^L9?u<>XKUuYFZ%aE?9ZA`!*;Sj6~?X*;@OzjuQ1B zCzJ3k^?Y&tMGnjs%iE_1(%54$L0USgs7<2LI7V|FJiKtvL#qdx6m<-NZK}*h39DF% zIWa9G`0p&m@HiI{{sa>HZ#(_^iLtERdm1UX&8QLsPKp!_Ax1iwcni`JxfJXTqtM6D z8?3a{ng)M>BrS`XeNwOw>;p^%2juqR*88w+7iF~6lV4C$?X#9>)*$0IHJTcTP5~v% zg4AC_`a7_RFz8uBlJ;+=h2Da`Bs{_3eJF8#AZ7V zjSoqSAFMNQScbAnC1PFUDbE4@m{Fz~tyRh&dqdx)U|yJUryJ2 z?W^7f^yxO^Wzm`X*qjOysKRW!OZj>`)Z9!#qECe61yDvFnlz%Pu^0hx_YvzB`_9-` z&ysdN?J=+D69oHBeB0e}1|8E^X>v->UmmEN+6>bqK#iFapZ0qe5;?YEl;n}SHJZp? zj!Yq>K*&;qZ$2d(kiUSlnPNpzDq%Ym6k%{%a)sVDkI;ryIT)0DmoKcWU-C?P3%ipDLp zguy@6a>I>7C~Tb<988@rJNvC5A!WlnRt>`g?@rPT0tD(^Y<^{dO;lhZyiy_(j`fHW z&iDdWeG`m-t=24z6ZrC&$8PkSZOha*#%WGi&-$=TS4kYeDXm)#*H{DKlKS3nRgyuw zg2F}%y2mZB*7>%5SRs<;s7sdL6?Xr?P1Ts=+@M`JXhA=_lZl!wbgb5azULA}ZqX#c zR`jR(9_PnEg-WDc16);3nYD;d_-ey3gZ@g60*KdIu(IrIe8596E{`vdl|~YBTVwxP zDPmJ!=~zdmLem4O<-DOvp*q?cXc^fl^Z9}C{a9_rfR?fE`CW!EsRlKPPXE+*cG5%u zhv{nhcsHSwCI;@xPpeod!g#o+XRnA&P=Ec;aF3IT%)_hs=f=TNXCc0IqXn_mq#xo0=1uF z`F(09P&`YeCEwmw4tMnwdhdP4XNm;q?v>}_s6cEeOk*I+!7G0)z!crdgv2tNKOr&4 zeZd)f^^w$9hhJtX2fuJ9N~Ir+amPPtd+Ql%?l_Tf_OI>q+(2}jU};pc#5>(!vAC4+ zmhyibU3py6_y4zAwGP)hw5gRV%}P`Af;CH9&8sx?z%#Q_DM+B~8_ZJZm{yuOHN2Q< z-hxM|fJ(}iWhv01XvHBjgPH}DR7f2Az5M;}1L1SLU$58m^*o@6m?1rLFKMH0Y4S@< z?=m<|JSbNCGCJRWQ644}zBIb)_Z0gTzS9e|QFSpSf3VJ#5{hX{k7+56@3G8IPyRyb zS@XT_o6*x!%4Hy3k9I83QA1YqUi06mTt8?HzScSZXOa(d(k2(#XB0(}-DJPCfhOWtpZ`_9r_X-B zLR+_VLRtK5f>y5Lq|DW{bJzEsj?elO`v1(3fXX@&+ihuzckeN=*GShY)8l9QI^CPo z5YZ+bEJmKV@?@3e_3RgSl(vo^S*0&I+81R7$bu6INlT+q`)}#^?>xD^Y6BZ_pH}wll4)B z)ejFLneF3+1ihFI;5$n-;ToGZ$-1iSjo4^n`DweY-Qt?4V$IiSJx5x5R&#_eEFx|x95{ zzE2s@opfmR(M(WBp~7FzS<36aZ3~y*e3P_bp%m9(nztvIy~4%jKeOk1)97`5I9Y$} z`E+rQ5^cH>^dsuAkyc*zpV?N}%0F%5q%q{}2JU#`<5usLTVhvaHU?-YE8rIOhTxjJ zeVz9>++x4RF}k@NP2{!ZtltS#@|US$@5Sy<6StRSXL5nb7Ba*kvH937KLpZiz@Yt0 zlN6EChb7s%c@9}YiSDC&9c@4Jgcp*6F1RjnUR=HVA?%uP$2L`MNhr`|2i+z)w(<7% zqyOPP&=Q61Zu*)L)BKQpEZY~UJ)YC!u=o9O$wzSF;&S$j;=IwdLtGb;4kD0j8lQJHARkGq*T`w_x47spS+WIo>KyMD~V0< zfH03H5dmV644$4xy^^$$&4-DpEw`~ID{r@SV}|nV(jaG6IGWj3o*s0GioMS~Vy`2$8)|am z(=BoTw5qkosn>X>CrdP$Q)wpUZ?LdaeSP-*6qj5*DvjhAY< zFB>O~utRN^JuXu0u+Ym8@@o6y^#o@w$E0-kkFEWi@TIs0y_TC@Y2#WdyDveRJLUT? z0sUB9`3PALKkMSua(fz$EY~waCnDrF7vZF(A1&YFv=Yv@C*zHG`bLl3m*MUJ_&P;}ob5VU%9K{%*--T^=i2a3V7$MYxU2&5wAM60@bPVb{CRt03 zs>$1jI|30kJ406x(CZOTLz-Q`GWD`^;A-l$Kw3$Y*CUAZd`{2J%5%Qbs_K~M6vINj za57Jf{prOWMQxFq@)syW??1xJ3ZPL5LdBNibr@tuvyaC1mB~72+tVZxm>YI)aFMoT zK@5nM+ea<5$70`^8oNydE%1))MS{P8l z1DvbZ2!2FAQgXjWSme;##uGWAQcb1+&Iv;#ZEnP-53pQ4aR!0bfySxlmL$#}qQ*p4 zxxv>3BPLzk;h%#bc##d0#OF0@ADX__2l9s@8`laIT`UpI1}n_#WrsUu$PlBo$0^qU z6IFvBw)i9$F=giPM~8d<^znR!s0L7)v4Y5qniO56HR2;HP235N-pt2n!7_( z?iMX^0uWypRi$=xMNpsrCh(3{2gz(87-nAX?r)q7-tepTF~@ceH49-0#piBZvOenM z&v4>?bJg=QKRlO7eixDSpILN;>};V|N;oKv^}?oguL8j2(=4xy)#`&v>}8enk(Q3l zT#`zdyG`>GcvUh(dI&C|-Q95)Yw$I`M8iU1@Weh~c z4L@IZQR(Yr{bxaY>tdtqU3l}6T!b3Fg@dL4LojR<#@!$K;xxE!?BPc*H*)MMOFj3! zaQaBnVErBq9@3@LIL8;^-4EMu*K=WLn5fx+`2mJwUy{5!xSgK=N-un7hug(HO%%=j zl@{CW>uAgQ+^D#Og~HJE&bq<7k6<9y6o$I>X{CuX=5wQ_eAYNl0+zgDbam`D5~XAR z^_1{ilB_L2a@f(tKqUU`YCf%POpT_SI6t(6k)8N@7ROk!CXIL*#U(%=)R5Q4fg z%1TaeH|Ih`Tj38wDil6qhNc>cPc2H)ch0aGj@K)R7nV@xASsi~HF=sOm5NYY;emwi zA1ie330j4p-G6?Qs|k8I#M9DIn|Mcn3$BiIV-2p&#i!^nJdJ-X{77lld04GC+azdh(ww0HM&`)yDz)ODJQ);&yyjdxZWh>YF z{40se4%1l2T2SK`X`6iB{*`cxp0l9ezY8!>4Ec)$0g35lHm(wLW^si!0Aj!AL>uGH zxgG}?3MVv;qd3?$t`~CO*`>T?gt(^%zFtqt0K>vY@zQQ{(`N`xfcgp3u4yMEnQpjp zPl@&>N7W7irUVtZhA=d0_%p#_}l^hp^%Y#JO4~}V@@g$1OYn6<1 z&hK?E%;ZBRjLe5UDry~VD*Z0P=bQLo2GJS=s-pRDKoa$TU=4s5iReCI#gtKsi_ zgz^Xv7a!#w=O*;gctQv>%puxNv@u_i*aIH0*mPaZi~&=rDI}m1QhG2 z*dHdRzpUU;xtDua&eu`

    D1}_2k~k-`;T{P^vd%S{uwgCr_ODZi}AU<1(t}5(^>) zHktA!g~Q(d)u+%4r6uy}(7TW#Qu!eCMI7$$KG>hV*N>iwj>o;Ia`@||gq(aNt9ZGjn>_W@ik(uTLX3S4w@k@nBLxth6XdX9Ov0g?g}Rai zY$9w52%O+7ZvJUy;>S7(@^D6PG!97|GksB0qsq^o|Ca>}L%Ebg_%O^IP;XmCb#zLx zBa)L7OBA1*EcQSD0m6Kwp^e|1fZ$fBa=`@`1w2Ps=wgRex@g~@TRcuUC1;MAv>!&H zHMkzae~rTlgErU}0q9*{v-PwSPKW6Tv_{`k5_en-jQC}+ikmAA4=5|6c8SA6s0S?|b_uvvn6=mXPZlvK z9a`*;D-Wfjme8!Z14HD`0iEsbm7M6O3tIoRdj!v>_QR)!4>Z_s7&pu0ZQ8yB<}%UJ zo#ccUkf8arXb|n&E6{Yj?=ew`O@o|F%RJNs_)8+MjgmwGn*_I+OQiYlt zwQe0pC{uI{TqnGfV$%)I2vPQCzh)ty6McI45&TY;s(w&E*qu1Bhnbz{b|>mf_m z@m_KY;9oNsE7tXRob3Z`=H|J6x-Q!@^cP3OYv;zx!Q$k+m;k@{d3nFho)gFwD8GV7Tm6ent60sVgsi1>`M- zEhMdb=go5f$Fzg>`-<-lV=2rT~zD7CF!}GnctcwOV7|h%44B(HQ&1P z2ezQ6`XBbj*oCEkL*I(A_AlV}FxR9OFjfed+?)c9yUO{YY3F{YU(T#~kpjdH%A~Nj z9U|C|PEd0*)xEmKG1F7BagzmoZL6JA@X)fM7Srfb-l9~Oss9bNSYOb%3s<Sbr^qo!Ynug2Mw$i0c`#8+{@9?9qK`c5zPNvT6g*F7^tj&R=CDH88? zHvf&ig1H6u8*gzJ7=7gZOve2_`X zl$CsJJQBt^;k*-e+2H+V5}3IbXFQnC9cRodeh_YaU9{cTWvY^Y-|;~oy2>S39NP`_ zwvqUy0%qT5RQ8??cL=ZaodG{a1HZ89sigyEL1YJDFZ-jm(q&t8EbvHfu(Pt+$oVUnWL*W#sb|iG$sQgG?j64#8tN+_V_qL z9AXv>RK*M@@&}w=Xlxc-(%^A2YH-b|`}PN9ZaT2D=+aSKrP2c`_YmU)lSPyDPGDrg z?h3c4Yv%Rhp(Oyyu5cA-=@v(1a_MwSpy1|zW^hgsbLU@;Y?adbuvcrmyL3&_z*d0_ z-p7Iw(m0$2Ppz-ZW2ulYD&2cWh1Qj^GXxyRqgY(gV)2g3B?=KV6%PeeLxhwcBZ z+BXWwx5A+c0^_2RY^C72U=%G%xSBDL@>mMSAbv$$qo$|y1!~ZSovCaIChY0Cm~k=4 za%VSg2t=QKo!se>O%Q7f311tE43P}Z8(p;G;kd5LbB+td573O|A=Unb3GuHvtLw+2 zz;lP!P3=R!I&T-ggImx`aU_(n36Eu7!CkuS*$lEz^?}v?BC=ZBxMj(Z()WJnn55-y zWp9`S`SoWgFuC%&{1g4zQRpf`d{dGsW`GY?2rGu&vr}>U&KJ@A{5dQ~qlhw|GM@!6 z8nNz%lZ*UsfSH;&&q;7z_F;D1rT;O`*e^MfvYv#e&#|eQw+DB9=L0tW-mu%^W*=Z! zd>Tmfz-H@(bL=u;;)higI=`1y`J-RHt@MFgG-;s%xIT{*d|HqW1+bt!zGZf9Eul`3 z6NDTRetx5k;;jdMEXo7}io7dn-BUWftKq#-bOB)7=pHmmGA>;1g0Icalvq?FwnE?> zfnyq7e$N`AW8-wiSp~^Z9fjZPbDov04FDa`6!F;_**P_3h0xa{@UrT29icdsqk*+L zXV-;x&ebzgl`vp^LNizOOrA9;;v%(;`kEXwLWzFB{3W*{W?xE5Vj1n2H1RB2R&vth z`X;c&RXUs4WnmU#x8V`#l*v;mbJ-1DXNhVwP)SN~`7Gt=M*n8{R7$HBFcu`}sTg8& zDkq){$JPOJewV8j+~-4M?+voyLnei0|CxClPlaQ~K`FR2+l_e^ux%e0r~IYNM(ezX ztYkfpiHY8Pt$*fJu<5O|JL)DqnP6OS!JI%X+m|79D#mXq+!9OqC@Zf+8OH*C@gckPsFqN=`Y^b7S^I5e~xGr{9g$LAHAZ3EJP|a~zDHUJL;Chpvgus5_Q;x6*kZ z&%?b{%6$+PJnZ-y9_UVBy;~KdH*(eVvgBok_;_P^UTH=xWrYfxc4vB8=4BT6A|=V- zyoWWa+iigO#gpRNaGw;B?_Qg&k#LiVPtE#?GMYR%^3)@Hw5Vm8X_vu$4+*q3H8Bsh z+(Vsa|F$h0N|Z~OiG1I58eUPayZpGn?IXDp#wtwX+)ygGB=W-ki6ZG;*aY&rjJDtIe-ww6Hh_ibY^S=s0U8hhz)m4D#SB;+LsBkaufL? z>8;PyOsL_5O!^V&$?BcbR?hM!Q1uX$R(io%KV+Ol@y@dCY^0I1) z&#?+?h%R9dF;`V0OZVWVA=$1ngpEAzz~8kL8ur=Awd;tDV)n6dLd%NHFXbwcY+M`` z-xLmkq39<2Bl>=A85!GHYY)AGA+&Louf)ePmc5}#5LFXp!LkK66KQh zj$&%x=MYZnZ$P9MPOf|Lg@6vwvGgPO`u?%y4)YjWM z=mfI3`5I47FP0jB$ipunLJu%jdgoC)f{aeoD=w^5>3=Om$f(hHc*RpINt?ydwq8Gb zrCaY3mykX>ueQQf&e9i`Mn3vB_FB$gMtG^tKeN9ysDHOkCf}!+Z*K%}Z@2hrZDb~= zQa^s<*M&}2HHl>;B%is^-M_ZI!wJ_U@{IWcKd!|jKpsz+MHUUdr1GjCo@S%X4Iym9 zs~U;VC{)0|uo$;Blyo1hVR01-MOz;m`)-?X2PTb?sAog3^ETcmaNgjWxmv-JitZhNLp*E( z!<|#8j5aO#i_e#-tQ!!L1dq+32AcE0s9s99G;JWqWd`5^lk=!Ab67xnpTMRjhuE4= zw~fb@2RmnNxEXzfP#(KO18V7W^2xGa^hR~C! zY4IF3uE|dS64oa_CUGh`yYHY6%M2kWhY&lD5AMt=-2Z^A9@o(wBz$1_0QMo;Cdq$Q zOQ4<7&n{aFuRM1K@In?z-|YZXG<}7S@>g;B{^ez-wAhoJ)wXB2A4Pc`HW{tbu`ARS zUPS~01lHXosKn;eswVqHFN!FU6Qb}6(^6hmdl!1u2C>e|lqeLg-NOWb;`7 zLV%`@2}2OI`uf^Ij|~QTB`~eeuRP&|Pt=kV&*u2K4RXlpk{NnP z!|T~Cd4$Ui<>6S6oSN?@uJ<-a`)1${T@#mIb>QJ39(OhN0(fY#GdlZD0#gVu=uWT0 z*#0pBH5W0uYS117CTeMrQ9}32Pg6O<1MDhA*`6aFkAC|Tbu5Jc7sY&g%o&sIyL~^} zkTRuQXSe;MNz1J@g6wx?^e|$Ul=d1ZZdUyfF9cmG_x;E~As6 z9yoMkmG3E0ZKZ)o2fBSvigeobW2Dk9uv^0XW}6ZU1@gc*ro(t5>%NZSm^Kmbn5zL7 zuHG=u2Ys^-!Y!DS0fsK(13n`chpA#qHW3VqOP@WoI}9}&UH(j$DlU;%-3VGbXpddU z7uMJi0ekhc&M$FfdiXOyALxtJ@B3w!K%Vh;Ssyl;(pLnuyUOy*H2%L@Ur}w(eIhjS zDeO$O>gn8|4b6WV-g9S^dvCScNn(k0(b?`T#Q?M`WyAG(WOP4HYVcg~dyMIet-My; zkyC^bU(z^^pe`sbW{D85T@?g`1nmvN}1#o^Iev|NroJ)mK94n!Z64`yKP;@kq0E%fp5sytppp?jYFiRPXJPM4(&&!QY35Mx zX#1325D6?}V&18l+^?T#J#FKr&t@K&7!yh_^V%NI7aM$?5fOU9HCca10r}aw<*e2z zv(x@<>yRp4A2vp4hg&=wKe;5lzriC&^K(1SH!hWyLpM%2pWH~`^y9=K^ZjWLyOt>e3F|j0GnEPAiMkC0pIMd za3NoM#|F#5V=1M>-cCk&)!fiM17i*Go1-*qeN>nuI&}0ING|{EgO0UNEWw!}PMjaf zl$CKmP93y_fGNWGE#I*W;e#kC4kOR>gTfFIuJ43uh?538=c? zs!nuG{D@9s6J`20o-GxOykhAGfG$d$6f?zP3G1WZWB~aq|{0fIA@L5Jm!lQhw+6{ zY~gmR-}GX-k0ruaEAVf}r2;V;F39}mht0IwlhFWx9?X>BrO(fJJU(d1gR9)hTr-5| zSe&`&`upS)-Jo+!;-}8;BTPSI#t&HpnH=*v*p6Jsk=}yc0vp_;#InA)^G!CZ+Qw}W zvVSAm1nUqg={`0VLZoU=I(cp$Iozr)0ZvNfGgZt_35=dzZs%hb>p|XdP$`Oq+4C&j{(is^JrAaV8FT+<6}eQY zX*4)`@n2qUx7O|dM~ux`f0Z39{6df_Z65?@{oXvO=gyw`AGN5)IkCT|uKJ8cNsuJ* zv@o@<-lQ5I-Q)`i*YLUL=l^sN4rXt@+o!n8{5SK7J+pFA<_culD6l@Qoli0!X%`$5 zPfs+pZzgCd>T=@KmWNVL*(;FHzpNfx5<}!St{S+EJ?x@DOEnRb#@9I0=j|oV`Cmfz zCfD!cY0{9m21Hycq>_tj31wGTNgvb2C=!LKK^<&80-m+wAeplvF_uk0Ze7s2_}Bji zV~W4knFBY~(uU2;-=u1#I3^cv8X{3<-;4(5zi5@<`mlN{Et)hAw0JX4E^sDaB8VH8!sB2KYVq4DzZV-#5Si}vGMgE#A)JK%3bc+ z^FQX1qvo@5;5QR^hc)I1JlBf8p%+rl>Bt<}-FwPO1&%v(-a;k&Ctayh3nVaAyEOIY53$NblZz9b;D90p*81SB5{SDIp~pl`1= zIqRcxm-CJy!f*crDiDg}=^)k)B`V6~7*y)%I1dMvN0>J~0On`B9n95MbKCesK7dBW z+(#~S0*U_tadOFKLGN=#L;uNk5I}>9uj1>-s*_<~ z_WWbxq#myLOgxFVSBVcg>LuQ!_kD0c;HD{t<|&;ua#x;rGM=a|z9nh*ug#P`i0!*E z()FEGHwZHMFBKq#RgWRyo;=0!P8f2yBnSAaftq#KyKQ~t)+ zc(Q5=K-8v-Y?&^e8FDJu>u9p1K`u5N941c9Pxr7nLbA|H%WE_=(lX|ux_oo|H6BxI zTU@PUyJt5M-+psPHT^QSht2y`cWrAy`vQqf8QyPj^htsA*O&FoQg(sJw<{hKW%$=@ zAYc1<8T78IXLgG$fNUB1%7j{9nsu0r)-z0kUBf^s7Q;im?m^@(SZO@r$er>B>hpfZ z@l;U>qiasQaZ%`4AaX9kkG=p_ND6(bvwD>M6GIPhp`O3I{zd z3Y)Vv<1fP$@9WdKd{d~MX+G-pAG(`IT?|N`!OOR}#d0o7VN$vlFo~BFT8!$wb6>9v zc@xMXtE617-TmHA#_Ed^k|CccaQd}?8PwK&mKKCvFq$(QB!76%2;0(}Oi=C(XGke8 z_1)DM)@kHr)W})o%`xWoBK&(;YSCp>x6E_OI_M8Xahih_PvURnE2hWFyWSa~F0vnU zW(U5!wIMk_qC-ow{o)F4Y#VZs3KdLm_A+4Q3<)0*2fHj&q*^R%&XE^l6QKkzE59-^ zJ!AX9I_p$VC=D+vgx41U!Oy9|e|*uQ;KJ-~Oip;lAc!>?;u3Xak-KtedURQ-y~J14 zbfbCETPMibL?{RxlxXKLo}i6>7qRuCkIxhn`5OIDkl)))$!;hg$Y2YTmU;ZhaMjCP zrmhE4NSCJDnL&v7H+tEdRb!Xma zi3dLianLeD2C`@L*OQX}@zG_0FRn25*?3YOXhBm%-@?7@+#T;*S_`D(pCd?bw;%et zvct;iRLI@MjLN$_R9(TBRvWx}LdvSnp47ffkyNT9IiJ_dnp}P@bmjFFdVgQC^t9GQ zD6d?n020!hX=N}_kB|SQW2ZEI+pbx*aTf~Cm0Kys$IFSWO5WZM+k$;~kqpV(cXD87 zR`f{%^aJLRd#~I~V17m*{OZ7xc99`15XIY_cYqRXD`MOik z5lwUifjjxAlq-iU8f`-iGJ=esFMN7$#m=A2mQ-RXaHd-C2q>7puUx$O%>)OS!eWVPjNcZm-wZLqeb{6 zsz%t$T#r}Xq6G{s9FNP`uFIC~ja{93j;Kr-m`cTI4uc;3JMZhqpA+=nO(-(@7Y&{u z-(RGq?PkelkxX;{;dCGtg-;d{3 z=ij-;@7~Hu*LN1}M$lVDF~s{V2IsxQ3-WDB(nc&R77kSJw_+)qqLT>oh-0s+FJv1s z8kJmiWbU?nRV&1Gl#flOwUQQKb5y%{7dSx5 zqHjEQJ=ij#CFsW`4xxP6J>mS;z&jOue;G$h;e_w8zA`cc&qD>!M%|Xc@wofn@IBu> zh~O$xbl^Etabqu(S=Zyh^>G|A^l!2~gDJ#`s-R4<4+LL`aoU2TSJ#}Vr;(rpOx54L zQ2VGp{UK3Z@$W&2CT@N!e$7@y`#k z#~X=P_P$X__s7n|+s#1ZLOp+jrHGx2hbN~H_pD=^sHs1aa{RaW%ev^V!#cirkGnzm zSC9`*?1QGfB2283Umir+uyLj{4$>ip!8uIBEJ4q%=r-oT!}r$nVWM+9EXtvMp~drH z4G)SxPo+6ro7Ll03zU+6Uq|+M9OdQE!y7ux&>LdFEN4G-2NH^F#?yI8e&ECKjue-5 z*gfzc*iyvg?fslsUcpxTwtcE9+xq~;F6aZZ18D7sTBa*Y@Y2eP__7XL+lL1{H|AuB z^MOpY7Z-CYPvdTYP~`~qu^DWPLc*W#XqpbT1*w?b&%cuo{cAyfM`1>lD5f~9SJiso z5*HG_$ss(zoEblJ+{4Na@t)o~)?~S>+lJ(5XbDR{M^k4=hN1Uisb{_u%?o=ku04oH zMa_!GN4CA}a*;m7%g$c7BKeDM=u~?vj{1C#46(C!*PL*X^$f`#959YN*k|W~pyV3q zS*3>l87?P$&18x5U?R0i@FT2+%gAwUHXgxneWjX=QBQF!E1w43VXJ(F|7rHp>Y6;- zAf(e8mBO1rk4d1}DZO)8wG+ z@8~I8Q}VTB+v;L#jkMFEDzPA)>QTtaI*km!@XNKR~Z-j`IJU012Ve# z-h^Mf4oq)NN~?BJ3SEa@EaRSWtHe@my^XSarR}(XwTb%9$u1=>$fe|T5^1PX+Q?EJ z@`*dE_(_-{E-xfdV=qL3Qla>D=Xj(4QNY*Wtfk3|FE50O2HrN;z0e}ENmdLjv9jH4 zDWTW+K7x9A=xc#);HQrj{Lz(&(T5*KULd1@Ml0}RvRd|6D_Ga8avm{QbvO5HsL7Nv z69;iGouLnP@<`|J$q=Sr_8Rp0lm~5kgx0bw1hx><#wqrlnuBX$ZQ7`HSR2rMG3W(y zc5PTa$vZ&GoMhDn4t0D#o)?DGSWzw$Ogm9&wF85;YIk2wchmL0gQYrpjIe`3Ea*d> z^f?BFxS{kW?whclU?9iXG})MMs8kt6r;#O0c82T$V0q>aQm*TV(Svn#yE1CG$(6I4 z-m%`dUlUm)*9A!7E#7-Q$S~N>bp(|}S^>n*;##y#dKNvekL!i-N52ktA%1{8;c>gN zstMFd4uCVn!l05g>U-{kJsB;Rj1z&Nhp&5MoLb2Dy3_rqW9xfYUa-E`=biAjJQiT2 z7h7=yK+_k_&q|RF>KQ@ZRFDhy`@b4C%1lEA&-wC4g)E0`bupds`_1H2#0Qkw1}Q+d6|zL7;Vpd+H&8T9FQuI{gEd5V@4o z0k$KdXvq*VQ#(RdO0A9|H>!W4qQEKnDaRJydz z70U?J${fy|&Zvk~Th=_E;Rl^6a+?Z1w!kgNqV=Kd0f6^u9=o)my<2 z<<>~@&7b}=OV@1rpn6wc(Lz$~R%#%6*~y}NNg&*!_w2Eo?N(N-Ho^Y#jrqr&I5TXD zg@@uqCQlpBId?!Qbh-CxSI35Ym4OFu?^tY@1t~-36+qbF`k@2)(JSUMawP&_c12wD zzQauI!UF&w9L(n&2%+Xx&itky-FiB`$cJ(n!UJ#;qdc+KPj$68&+}MoQeTq6o8&qf zJ_udH{bwgR$sqDJeFST<>i&19_J!Rd8qkXqE8eYd7G>$<#(Xx7}hnB4J zNsvvTNFMHhP_nSrcg$nD3CL0oS>st`Z`L^U{jVX4Rll9IJ@>O_(Lwu_LGV7Hg&Ktfq-?W~iU||2*^wPk)Wi-mFEOr#8 z4{sK=n6ym4#kjIsw5~)R=XVW1m~gFkHR)aOf`kBl*A>xlrfjSlV~OBV&ej*HS}pp} zwI`x(hFnq*RC*XCbh+71;1$)W6nCLOUnw?X&HsW7Y#HrDn0-nzu7NmJHpl*i!iADk z=!db_)7Tl1a&Kj|_d+)n=sa{j*3xS!A2jNo8&6suUN4U=$qaBnu{|>?XKjKlE^KEgR0 z*d^bQP46ROFB)O#_D0`bPj5H9&y>gE?q2jRph}u5wa3>!4AKi;Lp%ibTgmQbG5Pa8 z`-PG4{k1~c=Ew0?L4rifdi$< zVN6`nSukLS>nBRNb*^7oaCF^$i9dVanNz9i2&c2g;}s3AL#;6Ba-AFjD*8wvwJguO zFTDb|QPdD$CavGLmW+dz5(fu33?NFE!qq^kG&Rc*P832iD^4Cj=x+YH~JkVn(;1MbDTg*?`+0ut^C+zw}TlvPBPq**w? zHja}trsp3Il({#&NX}ygQx>=J!hVw4AjUg&2(~wi{qaB=eH)lETIhOEKfNfk7%gLE zB~k%bJRO>fdj#D5AWb@!&gd{!7MC}VtikEhYXiZp;<2o}DqmXx)*+mA)(B_zDHs%o zYo>!w-7(iVM{M~cV2h+5Snvg>?Qs>1Sxus287+tOax9cak~VD$`~Fnrgvs&5QM81N zN~EI5ac2!Q%15be=$Z;`a^X5ho?BJozu}S1apwxz_^o)w(bWK6PjXJLVow{zol-%h6t*qgm<8oSeKXrEo6jTULKN<(6QkmsO{Hy%i{x8H}@ALm_^!OUwB ziHb>FU-HHVMgHvi=dhD4C#>BZ&~g+U$$_PVh)~0Vy35NM;9P}T{Kzf};ubQeGAM4k z%Cxo*LfIYX!sd%VP1}<6s6(%g^6OA!!o;oH?ORZ~?F~)@k(i8i&ivcy`oWG2nUhzL z&Ch?@77?@%-)4bdZQf0j>&Qx9x%h%9ozBc*UJT0hpje7_aNQ^(y)e%TCs9V#N!fU~ zjpwa~*xHkTmWpH~ldkR!Nzc<_7(e1EpEfqVsJQ4Qb|5RG?nu{tcrWOt^HO@8y(Yc6 zA{4zl+SbnX&l)wTp6Opls`L5Bwt@~0R*vgpBS{lr+u{3iG)b>d*xYr{&nQWE>ZTbq zyMZrg2gRu-&D|j8{^Pv+cJArQi9`@2Hg+Af_J!r7uxNA6jt=E9Ec(?44fxp%Gh9ov zo?~HBXk^}dzT&5sx6%Y`<5XG|Dm6o>vyaNp?+s2_Dh7JQkmcfAAG@lj%MK=3Fi-v9kCU#$x|mhKmkbM z^puOsJ}@9sBdDz0-#b0-ncLnNL%g92jl`VUd+HmZC+L+kMnLCT%8O?Tobf&52o_oiMx& zmgye(9{Ceh3kNtw^S~vh$*!QR9Z|t`od|2boMw2T!@RRChP|g*K`fAo#SqmH!wK<< zzmv-R**{Pb#(|TRG;26^l-1g#g_n((@5;*y_y`cij_{83OdFVYz$!*wKhML}`}kb` zHdRzuH#AnOrA?NrA*oawAlP@z3Z2R}et!4sFhK`8%((5TbN!)1SV`$P(1HKQl?VIo zLeC?+62#n`Z2n-LIO_a5NZSMjVxn6lxb#@MGnnyboSYnA8^nP1ExOTCRT!X+^7Lb-$o6oLIo@qGE+8Dds)53oO#^yJtS>Xadg3Mf&7s` zJvyl4=~$7`*6-K9Vrt~JS5+FL#q@@ z8uE0A!`{{hvy+xMn&iX;Nr}y3{t-C}WdQ+6O+!Nu?r5A4Q#mPU_G3AGo69%^!t$e1 zFTbOq5YIal9@#YK_zK5s8KCHoIMw6#WQZ5;FRn>^g*8j7c8zV$z=4$=+6+~R|lB3|fmZGdUiZ1)S@>FHt6nN)Jd zXlyqh622}848uKh~jjzu@aq!k!fw=@-~uBis*eO(34=)!?fw6U#!!oo90w zht}=ZaY#s>CR5r8ik`3G_!nfg01B@#rSA|W*QBE}&!^^f-&i2ZE6-v(xf|iRwT>#g z`(QmK7cV-L9PJ{Gs^5h?H4UV`_SVq^e&^GnW=^ymI64BowCX>zyUZVv)B<9gAYyCQ zok~#tF4+Rp1LbAYuND89iF5!=-(Hrl1->5=G<%OoUiaQ)A5;;BX@;$PB6EL;{bByB z$CD};l>NaxE%&Q%jQ79Ud$(6vq;3N>Eh6^z_Nb)r{ZGR3Yz5i6664hWPISG_9BnL% zSJ)X|Ro-`N8wYg}{c4cY+m$XaS(W9CCb7o~`VbXU>tEzejW&Iy3znVHw?wY^Hd(?e z)}ctw?kk>v;ml)M-S!)q#lG;?pLRk-x>|zw!HuqZneF^{34SV#B_Bkal$*@gQF3Q7+gYWhT^>za$96J~ z#ubOOd(7p6;x*(S|H=p580%l;N)exXrs@8vWDlqGpbiD7b^i@1yDq^eme;;$cdt#I zVi>$^i^XnKaU?27vjtNk7d2_i8xGhUH}8(tcfN~{uzvIyq#{_0D8%2O9qQ@r-Mmuq z_UG+$JF<0A#ePBC<=hr2<*-^fnxSwQ3T8xH*Z9>Bp9WWoR(^#BT;B+{%@a z1%C{?`MQGjuq^~aLKxew0o~2y9hnMUISu`YBXm)SqQQ{5l7pHDt`gYj3a%6C*RpS0 zN=E~<+{@}nQppnFhEc&{NE1;fUQ=c>i(9Xy4?A`~9_%F@ZET7YEya`v3IU9JkKyE( z4#KpRR~)sgg+nrG_InrmEmXA|r^;4-9|;{c2h5heoZQp#%OHNR^BO04kYG4ljb4YI zl_&kr#N82IVePsRbp|CDwVvG7fzY82yqPo%5t z2gA!(O$Bzic-}#C?m3{cl!dC7@i?AO>^)CRGaOk;Ci3fpiDUnbjY| z_t?ICNh2Bs9K|PP#L)b#f*e51Cb|84?cIZ8e4Zy3S6`3fSwbt@VxM-TWQIF#V(v*T zKK?79w3M^AFnv!2?YWFgn|#Ob8AW+DIC_6RP5$-3k0~Plez`8o`;_+;7*70$1`D)Z z(%l2%va%BStT~*ySz!D8GSE7a6Cu6?r3)j1vfDkR8^?7m(>C2aX?{T)t$O-RUY?+m zW}3gZ2AGtZ)4IsL6SWC4Vu>KJqVJva{9j{tbhA}BTC^G!iwyXVlAk};9HI%z<9ckC zhJ`R=D@j8)Rv}Wvoho26xQ>-}#Y%V6+y66L5tI2{Dwlk!JHnoUb-gC|V7tp|f}W|^ z>A5r7X60bk8x>u6stG-4>l|SJkN}=spy#}-p!9KxS5&aIGUg!Y;P1!R$FeD_c_F~p z&DBt3PJ5dzQ@mNgFPaqYJJ}t=!pY0%emdwIIg#gnJ$DBlLf!$H2T&z!n(mh^L+Nh+ zCJw_n*;L3jfz~2lQKZh`kO{?Qr>0p?=?pFX?%&_VBK>6~EKmwDz*aZs7%L}gG2fJI z-K|Q1zr-fFs=M`nB7t==OivhG`^GYHW|{GGuyk6ZoE|X&a-ebcA3600r~LQT3I2oA zDsPe_5`Jv%VwvM4k&Go7Sohk7WL}Qq%91U9@6nT)*_joi>GhqsHAx?vp5xz})_of6 z!}w_7;O2yQQy*pH041!)auGnW^uGQcPxwMVbAS$L`z!kJX0!=9iAmw38>u^^v6CdJ z$=1~CQ91*@-}hVgb}!*&2>TAHK)I)F{4s&fJx9uKi9D%gB#wAzhhBr zmw+8{{Uf9k@Sa=Dolog6GUol7gBC&ZYF&!hVVM-I7xsnnUrONSJc!s3cbne8hI-Xx z-Da*WF8233Xggs7!%g0Hlk2Nnb6@z2Ikpej(5(Uvw#)QI#@Wr_)92Ea;O#cv6fe&z zB8;0Xn>O7#^nDJ;e=P2%n+Eo}lgvZM4Ub|nN6*G2O@DdsP3dXTVylO8w+2|@UJ|Gn zo8{9!;D}g2#%zA}@u5Z6>s1gN9Uc7Z5lme}CU#??Dkh(m`u|Ml3Q+)AVLhIPWm zU6x{UXew}DN4Gf#(AxX1Og0$$x^~c72K;pvlw4utxws#`%-0ctK=O{hxggoYWwk0NIR}s_l~~Ja zo32mKiaxGGaY4);73%VaXO0yre+?0V0?*-2RXvo(1q#nAxSh`xEbBP~7M1rUe_sB@(T-ZcXiw8KD$Hl+O+}pFknabd)_@iTUVgU$F z{873KP)Lu@g`?ORcz#s8E49Q|3U9~qfrQ($%SLQPSI6O}`)uEkKV~bNxo0rQtVD3{ z(|4Zw^J@mf@D{y#Ir{@^YLWeQH@5Hpb#(UeOz!_5SDiZNP{*lrBvek3PHqyy>FA_e zH$`qYxjQN>#59$zMbrG&-6sm((FN&kIEDQ;eLvG=4&De}yWvzQzP@!kn*8$? zwFY6=z?qgb;H$;3F{o}_ph}okm3Lq>$RZX>VjSx3^OMVpzC+3v*#7LfJ#tDXR8mir zC=Q13&gXqc+T^M&KR>}j0S(K^Tp)iERu`XqtuTRTr(1w-hKf_*nDkGFL_LC6@b zCF&*Led@h%4i(W#D5(TnnkYZ1t5FagQF`%v^L-}U7GaTBxM%fC;BVPMaMl6n-{s-5 zjwBm-+9X)kofWYm$LTjfs2~9(6&yP_ob*p~i!1-q7U;*JKWtCe?^69!sp-aHb6mluG7YeW3?8RCcN~(&X zBw0Nbq~NT^Pa}~htdo_&97z!2b2*7PS=z&TEaF6z(p)ZBpDxyYgTw9~Y&o8aaIjZq zHI}B42l%Y8+(8r3$^R}=%DO9@ubZLkjmh-tL1@= z#bGK0I1r|5qpo@8K|_-|p6*u9Yj+nAko^FLOs~=Y;m4lFD2Xkp49Wf{yE_N?1>_JN z5>NJ4H9EbdZ&C&Dq4p~3CbDEpuk_1BuKm!mnQJ>sOuN;Ce^jh$!vTcCeZBwAm##26 z?8SzI`nHyU$fVlOUg_68#!!j>=|}<-4n`8b5JzcukGdl2y6wfOHTW@Y!7uyTQTGQB zAmETCyi0Ni+jrh;{~4gOrE1|vrq>y+3X%arzAya8V-&ZzRgX1HbST2{w9lrix6c8` zk(kYQ`*z-Wx?)R{dAzY}TYU$d0I_DK=k$Se!hQ=)YW!j zjL5@-Y51PEZeglE;5>}d7n%LnN0`r>{K#;4N|ZUOv8`VVW}I!DoTdg2OQY{$Y(RCo z+TwuG|H`&q;Sj&*$tWSYXWFyS5wF2?XPx=m1o^A;pmNNpAAK-RZhxU=^47p0=;Y?U zq;1>eXJ)lgIGpJ(beelzVP<0WSG@`06DWE^48?!CcCwSq!1VJWwRJ4|*eFGJ$d}G0 zZfj;swTkI`VeBR3kSibJJgQO$O%;^P^wp=Iza@Oq?#%vTen_mxW*?dR46OE zl@*I?F;3!M1FgzVMdNlKMWb@L6E)tsZNE-7W`g>2A7OK!!zLBH-+(dNt0yYR<#r;X z8fxO^1Yr+Emsd_Aw=`p_)Mf;u5xI|Cm%nV@dIK7XuUe{#m0Q!@3(=SAoI~-LC zTEte;Afo+xceey1cy~1R+kO*33382fvTn9GK|37;w!RlPEZa>uCytmUKm9vjL_j=f zMr5gkd8g!0%$_5-h)!*ypNA;2Kd{-&=osavz<~Xc@y?$B$o8Fi+sb}geWT_*jH&mA zCdeOTbugoGG=@5my~gRyCh`~8E7gY{JDcU>#a$ZVYwhQQO4#$q0>F}NrQUv0!%xIqk2y9I#>)m<^6Yyjmc`eP5+%8WQrpyCA z+IctiFIduYa2)|v5%xln>O(gDfJZP<&CtBR4xPu|J&P=ZrRw)tKlX{}`chkH*WWQh zJj~2g!h7yc6PqSY2rAd~t`GsJ9`9yW3e`ZM>ROq0Aji$$9Y6l%xn+h%vv2QMRaE zrv<{{tl!_lOJ_66$jC^CXC>{uURKTkL+&I*0)8=Rvv0bFN7ag{=S6H=l`F9(a|7>! zjJEyN*f)G~KSMDFB4;H^XWa5nKXGA|B0C%5v1Q7?BlyN7t#w9wc-^M-H|EF{20R`^( zCr{~$!rWQQ`bZe$4?ZZ0&AzD_j|a~57McAv`~Czz8CO5H-X0Q-Ly5kOJw zBpCZCb$HJh)Fn#V|6V`0+V+tKLol>nJ5h?R%6k?1@=iV$dWBgpcAKY>lV^LZV}iSV zK@N;IHQTPeq2>Ry;jD`XN}q_#s@B(aPF?>_c;ke_h3< zNoy-}h{wwQ=FXLtx+#lHQ-I8bJB0AiU36R6+_`*rN|3MO+5(E#w+7C%^Y^mZ>TWn4 zFm#W{Mn$H{*u3^NL0h2Cgp{NZ}oI~?^{3x zo5h+(W`k=G{?>Hs1E=XG<((gy);4dQ1*$QFTU&X5^E)}vvz?ob%HKk49{Og!SM>Oi zdJ%`{=YFf%YB^37OJ%$Fn7=Sh)Cj5A|8#!W@#Z8(YG}8Ecb8SA%^@tB+dX0%92%5P zPy{wWN`ixpj-FBUQw{f%v9p7`i9+%YcIqvEt(E){<&mu7bLXG$T}d^8@uP6Mk|$Wi z00?UCCSPlZ92{lU4D|X3tDYF{=*tDiW=-;?x642YaPL^}AWS#L17xCeDz2knkijw5 za6gTqATqY*nZS%~^i3};QzK^XBs6d1?_HJG*LIR8qEk}DA?CON*9>SsdJa7fA(U_c z8DAN_Y9kP$st-OXF?{+)&GVru&>vR_;E1E^f3-@!Q@~DT_~eGn9BbBmR8Nl%H+f{; zgpAhrCmY5wt7JJdTFDW%%|(Pt;4Sz&oJyccrdl7`%nDRpDo6kcu*^U~5#^4plv0Q_ z*-g*pDTXt9zyFf(La&L%R+Qe$x4fkuXk8nhCaC8UD+`@vV@Fbj(-q&JJ2qAXbYz;s ze>v>WwNEF@qGYpsUFRC5qd`_*GX3|Y@%BEr7L5sf*1wo4D|#Idi>OKL+5VxM(cyz0 ztj05DYtxWgL%$EYcUv6r1S#F0p4tXuDRM~UelFT1OXVcgeiIVagBAWyAB z@9(d&e9*}AG={2>O87LylP%V8Lw1oj8V|h#r zJB|tm#K154#Me9~i9#%KutBUG)Pp@c>?tWks16Js{B-68K~N2|!h4hqj%0_oYVaPZ zVKUBJl*;YdvdkvApO?KTDmh;nd)2;4YutF>@;+FJRbv+8$}=Eo|A*w@;DAFD3d?u8 zaOA0UKPPd{Twp!JVi@YaB_TQ|`;ZzHLI%d8>$wUwy?-du<}?ry`ConesrO-n_Mr9K z8^F9;Tp%5$v*QdvI~-e&;ur9>5^FnUE?o+Wn7tiYySsS3S{Kh>cKI5LtGA(MiF0!S z=>7bwY8toy;`e3*+XBp~T#h6-H=k977ct=aL8pB5nl}s zuCa1nLXNHqZ(`}vhL+9ZuJy5#JWW#D^}H_DnVz^K*FQ$B-WqB&$gTh@Q~u6%dfCs&p6+2IxNlBgX`?6Mc4VZkbt4xREX zi84uKmQcmm^K2em5U*=H<{)|)rk*L!EhdU=5E66gHN0cBOtB*g{c4-`toT~|nHNOY z%#zK@`Z~5Kf|_)AfL8y#5}kfC-f0~uVrij?6ht;sl3KE7PObZwY}gJYPNV&g$wXS? zr=fl8#7@h^0^jYW(!8L1kic{DEk6-fv!?TFT`M0UyU5Ojk+} z>CjrEQx^ZcWDBtQ19GFw*u3en6FGo^0*pP7H-~6KLB)4#9dpQr=bOi_ruMcG5W~4Uz<3?>PaJ(&;e~3mG)d8o6Jy^4bESux06B=ij(W zQ8dyl#mq?pwNw)K_o{}iCfPCt-i34)Op4<<*oMW> zDgOqeqJ<#oa2Qzv6j+IZ?bomCvC7M^6oq5<2A{tXA}%aCG32_(7kZ=^OS*|_ zQQP=r-z+a9&uKm%#IHHz+NzhSLQtU2sq5N5jI&}cPA`~XvP|KG*N;-K!%j^mp_!v` zJT~z?epcbbV=u%!u_*&6SD9rhqj&o53%xM>2=hMO2W4_b1J_9oVxd1Bg1%u3Yi-Tv zL-i)BC4z^lL1_G)H!#Wz9ys%k+OS2d+9?^d9rvhW72{CXYtP~!9g3mmvwPkinBO_N z%$(~ALh9e!{`-!>wad!qtK;>zcB+YEpc9DuJIpdX$3O$X7 z@fr7gS-pNj=Oco}L%^#qCf8MFG}EEB)L>`)-#k-plRa>WPtZ-qbgc9)G|35>)X@(0_GC&^y)}~MHpnKa(Itj?X zwY5YRNJ&$>wafN%eS_Xx!o;{k)q1~rt~hPHYKnN@>Zoi2b()vmRos*6(SHD^2e_K+ z7StFOt)urWmogW)F%dFBm9#Cz1kiFWP02V3Mv!|f_Us`fxn;e5GfoqmTNiyCJTg?$ z!f1zm0~s98KfEFRcwyt754M9xFDu4V*c3WwCa627!>C14_9v!Un9Bj?@9@>910~_+ z#n`2%4U4MXf9T<<`&;R%&YHPGW$bV&{UY3-BZs@%7grWPt* zIGQ``blHKh)ChJLweQpx7)KT6?KQZWCKyz7{)lZ!xQe6!anD9%<;v5b&cPgL`=!O>oB6LbPKd5zoi&d{SbAblJBNYdz5{YU`chgk;BbdvRRJ(_kx}OqNFKR`LWS`2dQkfQ#{$4Sz zO~v{5-6px2Z>Xq3cgE+bK5QnyHxs$b*W_pAI$JjoX)@grtV~EuUmLrlzlSZkd#6o_ z`ow3c2U%CX7ymIv9SAcmA*Hr9Z_7OgO6tNL2xa2k!M{*9rAn%!n3p)dS@wml52}@@ zbFsT3LT=pe#=8*3CG7i3PDH2wQhlP<6006e2WAh<1V6}F?gK*U@ODyw|NW3zi()np zyp!{R-q*R^{$78NofanKfd=%dbYv{QNzcs%ga*c%x?|hLK=!Zmisa37x?Z^}JK$hC z6RnA1mIQ4;2Bt}PSn8)x=#dJbXv})HI=c|7g^HLjHn4wacr^BR;1i@*5E7SqU;a5l zI%K|qgEDni?d)6nq~0hEO+{~^uYS_aJ6@i0S|A&C|6U+AeXwYz1dqM6@zbz%X7nt4 z?&nKa@Aitqd@I5dM~{t}fKZ;c*41(rH2i~}VjNiaW?R4NjOXy)^)Gf;B!dtfC!(KA z`ijcLpm2k5$smfBKuk$>TbH_yEgf;F-TaswY$^tgrh1jkh zo`4+xpTM6s^h#Dv0g`8YJqtAAWtH1_sl21tcSH$fY#<`W_9ndfX#V^8W@uxJ=5P=y z8;>el0``^ItEW$(mCmrq?xh_tlXyW_1}bplE$z2oE036NBG1jIj8bBjiB(U9Hpg-y zeL9u-r%z{_K1@_MR_$`@4)NySFF#*dvcGUk?1xR!CluiGpv$+1Ty%G<5n~9QAb+Tl ztm(`C_bJ(52ut02F$xELL^ibN(iJ1u%Or@Y9q5M!pP`jbM!6z6F@mE!{NT<8^R@K| z=ga#7{8D#0cuMBq=bTCtY(opQAJT-Ka#ZOLX#VE6kOdn==r{s;o3A5iQw!%M+^aAs z?)`~9*zTj+sk0ypDxXo-qGGAZQ=PGl2aXtGcn$mkMpqw!X&Prctu@y1H2kRYnI=a1 zwO$4`T^*+AX>^zRZ|>pjk~@NIuJe3~UtC6m=lbZP6dDvU@BZA+e}W-jw!8GLWRx*vn#snU+crF&>-hgIPyt36YW2a_108#x9Pzqh$uatI zOZDJ`@^dxB&ji(5>1gP6#iY<_TR%~XLZK?Y4IPm09{^!PZWIchsDu&o-n<%;kNSLR zy|Z0}>itFBnIeCq4wg+PrE$1iRG)wYeXu5WFe6?A2m+tU7p|5pSG&E#O_u8B9ahW; z5sZvWNRa)kV*a!W6!#<1)d5T*;%k2>Vi##`L}|^sn3v@sWA$s_52R0dKvjNxKg>&+ zk5oa0AM(EuNrv;E+{pJ*Z~F}k1(#=6~T6exqqppUa& z>)P4A_yAXU7zDX~aGjqt+uUH;$AoN4_4!hUr;S^Htbn6rN&mSY>)5hykS5pYAhvO#zJvh3S{LUYPO*9=!Cw#JHB#h)4xTWW(Y6rVg$U zDdac0LRqv>n_Fxo>QLz9p+arr~QDKTIm5R@YM8u$bKmA8*jQh>ar=}j~sXh4=IPK7meYb&E#-lN|J?W>Tk;8=CQ(zd~XhEpWw*TgxE|^ z*W?>QN2j%<>|#p!JqJa(1B9?IysM~)HFoN+0riJgav6Vs%!Uxe{x32v9!0U zfie3fMh9<6v`~-J*nH5_}{z56AcNe(%V^4BFlQEdt_EYI9Z=n>s!0=>K$ngQRw%C>;FsN^Hk~L7R%{^y+y7`9B>;)H-lM=N2h_R~<{l%f8f1 zLzIFeH=!Fzn?xTUfT4Wb6u(yX)IQXOa^=FRSZDht6+_lIemCF71VBl#!?wJ9Sie`} z)XwJM)eU0=94%J=Qr5&|s0 z^{1;^+TyZGCWy`ADrJ^$5VlrO=T<>!a{ zvNoM2M{7+PJ0Fep6Yr3p$+v&8CV$>b`>Vct&URX$v5dJ%6Lr3TxA{ogGd|5UWiplNFGLRlqoEzHCmsCe|eZSzNo(> z;Y1NJ=w4OW^NlE?DK&cYDW1QOLixl9C0e}L5<`v#4Y>Nx&$=BsW>VD?A+g?zCu%w* zl;ffaGd%}3MhOAJJ=4y)*?#FJKoV&ENYEU4=i`$jzk*#YeUzbZ#Y6=y)NQ?H7s*b< z!G9V#`ljF9>X%qn8B#+2Y~`t9Ze744VKxt1sm{)VaQX*-+HEZ#hyrWxD-F-apI^*T z$5a%q-da@l9@Ih$*l^)lHq6yACE^ufnMx8ogu6#;Y6FedUmo~{(s{(}7Pv@Mtqu6c*vfAbeHWC4_>3L~}Vmw#K@CU4sx&ht_4A-mbp`yAW1X?pO-N zP!SW(dhc&OSq~xTpDVs&NXshSEqN_2r1R&8AqxI&MCYK{4!J$CK?shJLsrNtcuP9? zF-wM{%hsojJ%w-;qXV#*h4MrF?o%@m;T|}`(ml}otg-h6&YZGGr+{hN8!-n2{leU1 zy=FKcSnNZ{v%?OXjEJ|sQXK6_>N`1Ljhn)^2WLjAo{R;D=9F+ybyW`p>^LY!wPR?x zt~7yPP#lOkV3r)2=m2)A6rGyBa|53WRloM@ z&&gT(+1IR9p-?;gJeD7ClRdywkXr+opN-}c+=96i5haE6!Cz3AQ!lyaYw{w+pyosU z`F`pwYcU0GnzbGZ=QIZj;#@)JYTR(2_Um z4$8yWJj_~O06_AuXvW~zPWs(*_aKCGJQ5xrxxczOGrL6wm9cQA)F?0q@f+wLY~=!* z^6WW*f<;ezzxlIXdPI?FnR7uzCp(d1nfszp#drX#Ql6U&{Yc)+-M9ao1xRk>`iPV{ z$|}dI$qCbL1#O${%JLL3QM;w$vei#WvdR5H2rc?Uqd#wR;LF_>nto|@{FFWLQsE3~ z+`BF8Y=0_K$r@W1DKN{K6|h1wI&RWT6 zEa3yNeAMrD0px;UgB@EcwMB+zddCM0X?=wiI{5CGZzlVlvsT4>UNVtt;CWu zJP`CYqA*>=saz)(7DjY}raZ7bMz#Al&~ARN9zae2`6anC77{_*UAr~!Ne-|>+$`}j zoeNAn=`lg+^ohMlKf$J~+FT24gc9zg5{us^wd|HtNJ$nwm`Fuo`G$v>SsX#3cxS^UTcO1ysi-?;0ZsFa}&Hv64UL{(1f9H$PxJ_YvB0amGE5RYP0qBhWmAJ zTyCs0=Q~)j)hp7spjLNlB*H~+*o%c*5H%o4Wv(oVkjlN|pY-1eBEWW~T%42BG3fWC z+5k-{O8Px6y*X+tPcxZSB{xXmrqwR}e#wLPeAd7J=|nv@mQ3n@8Y=)JpQ{xluUxr4 zaj?i+o?5dI(h6p4s;(1z8fzZDSoP^I(sxSJcSx*c@Y{3hBEz3=b8&|(LSq_zbHQSW zdbZGM#aOh~7>$yH^Q&UGZo?NTfJ0&O%WvmkB4%hW*wfyxw+=Q@u6{t9t3W6vEUgoS zFdq&6k}nR!1xWU;9d}ZeFQ910jyY`OvsGjMVi<2vm!Sz*Kt#()3*li zfbXr{qjD$GBhflGp@DJ8vB^n zTMEs<1F<2=;W53v#5t9#IbS$^a-0U?vHQ%7s=}(@V9(^Ar5bRbRD3_dhEqEl7USpo9F7FCy<30z2>2lLpVYS_E^>Gt|pCO5W(&3e@FTIxiVk6@!#TT}mxOyF7J2=DMF>CFi4u2D@B?ux0UGZa6 z*M$o}9cY z8+I}4|6)8IhmEL97I{IYkeX18X)sk<*~z^;UtyE*wGN}=1HfRFU2_K>lss^|`#lkM z_`!qg8yFPTiJbe*&;y<08)-`jfumbhj^_3=tz`77m^Vp(A7Zqb; zg$qMYoE&V0iX?4Y&2bwCJd9#_3Q}N#H4^!fe}2)|7L|whSug~ng3pG(Q8R#=IzU=t zBF<(nrjg`tcxmt(P6*NS3LpyXG$TU$LYS%A&-RZlR>lJuRtYkUN*ghLF^fAz`nn>l z9(znJ>^{=Y2|z%VyZ7Vmo?5ZM3^rM2Zc$L~!adkp_~Gq-t|hp^c#1mSW;Gbji!=?t z{)ApvkDvk;fR!`)h0iu6kzmARGPfG6v*X1R{Jem-xYqAVUL@?&1|63L z%D=`*9dUZ6xeov7tgb@4{%T!MKip4zn?M`-=2{P{76&y$f@a2V%7ec{9|Wh813NtJ zpsQs5k|RQ7XsMkYiKmh7ZulXDDbM@?Mot5 z$dwsl1By6Ox_?T)Q)6j#3#S@){J}dYlCJ6&@X1+4K_NGN-K8~&fJU3e$uA=$DC5qbTem0 ziNz48Z!jno()s@8HG_gZhv*S8CV`6<&t->a-$cCDWw0UX-bU^;NLRmW@-V#w5+>fk zVM@o~UdNL$U-&f19UtD~ab?|Aga;N9@37vswG{^@*dEXoPs0awF717!_vTNvG_F*f z8;VVRS`UNym|Zs?w?74I6E>HMe^wHFHNZ)l9q9BvY2>>xUC^-x9`GCXg2Zy^`Ad?^ z1eG@&hah4rE{Aagrnc&awdLQ5YU@#clmGgb>XihufV0B-JQO@oH}4w9}kvul7mbL)Jam7J2XChYrN5i=0|QIvy?zw*PZ99~mS z-J@?0sGd?f%SJWGiIWIKGSeaM6I6-4Si%ms_090*Yd`z`_;`1ZuQ2UqXPDk5H>ZCEIYl@t z_lz?zQltQkg3#*r4A$2B;vYZM%*o#!YFJK0^Lcn1?HIVOCqXW5MM;kRV5D2ZXV#f) zB*Fhx%S=D1u78+X%LP$~=`ABZevZm8FNxg~>qJizfTB98+li7z{$M+eUHKTd#%d}2 zh&38f&8Lp7@O#H10md__gEWMjRZBGO;!2ro+Y+YEl8(rA{?oA^YRf(S41r~&pZ70$ z(NhRc;OMFUe!zJN#Tw^j{EQi9MP*^$ys=9X4 zV!8GC##$j*929ltHzZSlE0swrR@j3eY4LHZz^qmy=dgKkm8O;mtC6Q2M7Q0beS*ac zNV#>aNhS>&NU61uL*^|4UTcw5yHlKPhE@{c4efDvng@;SE7u;>W?$MjXT;v{c9KNZ zE#DiS#vvgERUWhZ)G)$aivC=S!!L8V?34f1|7bT>l>K-E@0}WDIh7ozc5%Hz@7r-q z1{*PBLUAf*4+fjsCEDQnRb<7E3*45GduuCD(C7WVH^uImTZkOaOiS6IxSwPvB*fxHCoGB0eh$B;H35URT58_d@6Cdu@?8X}V1hv>%2dpIpTOCI=P5 zDE=*X_X!ds2yG?aF5uHfYENj!P+C(;$c0EgzJ@d~!T~B7kgJbx6@3YXn)kOuxs9JLe%yNHJ4~+iv%Bsu{2maY+!oxfRO||>vP5AYdM2Qkz*@ok8)7o}=#TpSWmfI@m zgQ8RPwTy~)CL|Ni&6nEf6CfBtSe2L?pevIA&-}!j7C3iLsTfBJZo0&xXBX;>cMRss z0@m)^_-YRdBpWShLnhc^(Q$XPRN5*xuDx0a+7p|RwYfp?Z5qNk_H*8f02y9M@_qd< z&Mw$c51_7A4r$L`KU3?0US9+`J=t3e0r-M&GnsyA2L=B-9u>VjNHbPv7@73W&jSgv zQnW`%ucd7(Ydh9lOHlk|g2*ZR}KGcK;$d;sQFD*ffQ( z$!8N9E|Mc*<^>#`F&DAic?G1#SeJJSGL?1X(%sKW|9WJicaEQMA0dDCBF^BO8RDOcgZ7@$Cl^*m^Sdv@$5k@unmmOv++f zoPDpwi)b_e{hzu?LE)ZTwUWnv3l96#QQYR1XbyyknB!zkd?w6W%1^C&0P#cM1+Vus zp36B+@F~1EmCA|)H1f_b*Q{a3>wtp-ax5hF`hb1`iVZr8O22guP(B z{3JcLONpu_6clGD>&g=_o7hm)t+L-0^4eY1kK%U9#xwLz51#ESf6zK%(g(ax+`X98 zhujqGuhmLd&g*p3ILwHHM=;BBq`_Psj0(jIJ7uuT|6ukq=;Y#03M#pjTK-6Q{wC{Z zmPwM+hty5V67m;ek->7#Kamj#=!1_@6>-Mdz#JR)TpiTS=4r<7x_m>lIvRZEG`B}H z>Fw&hcD~7~{SEwK(oX>mWPft_AQMaUH;2p7XQtZjMz@Ss-a$v^&Ih{91fL5Z^!MoU zR%J@s(bYT2N8ElQJ=2aYNiZ^39gNqrf>Wm(jbib8jly!Br?57HXI8 zJs9T^g@GtlfN)@oHt)CsB}%vV^$q=ZsB>u}4;b~ET~gn=&IK_0N9ux9yyqd*orgQp zMA#P5TyY&J6sBuS?U4>Hq=?!aAE}tLG0O^U6le{qAJCdXkJl;pmsn|^sUl`PPd{y{ z18H>CQcsoGPr-t3WcwT6{zaLKZ|_-)q^`wlpepYVF3uSQ*at00tHE}RCo6kkiYY#;WS`(U7+lEp zB17fJ(1_|rqz#5~zH9V%upoab&F=@)twvK@SQW^=Dh)W9U7a6GfYIt6kN$sQ)17&t`j04?(6zhwt>4aTjDr7kc2&FYD0Ny+jsOCe ze~13-iuQQNsM1*9Rw|J_z&wGmcUa132k1hrv3JKZL^FAN*Ro!K+PCVutdYo#3PPcR z0Rzz_-DF$z;+iPm<(Q?KY1}KK-NB9O9%2@|^%>!~fP0N+n=M9$2ljJa0O#BNfN`u` z0I6WavN7_3q3q)QG)8Hi7G#~wCUdV?$LrkhhL$bu?*LS z@sCP)@Z7OyJ(&`Cv7YUk9Ls@X!XL9**>tNAt-MP9`3p{6R$pCA-%L-TFcq|<|1~#) zxyB5I#+ddzyhrGGNhmp%+Ir=hzJL$g`@G>%djvNLPLowu*_l3ex0X-QI$9`}7$Z!d zG8bYkEDEY)CW;`1D9hQ&6)+-gjwiiqo+`Pjjj;$PKJ86N!@zKOBv}L^#)-OuBOWxs zSSy1mSLg*-kKUb#4uUVJX4*Vr&T?co*ESI*W~x?N_YZf-SjT-y&1)Pdg;wB1QD4cM zIcP^;i^kF&U*v97YO~F^R<8a zihsF(U{Q{{GT)Njr{GB6NB&7``3Ovu+TGn7KQUTJ14ztLf^`_KOU;u>>YU86LXt>K zcdy-oq|I@-4yGZ6+YWeC(9|Gg^(??|*DuQme+rL4z2~|=7e|r+Dl+trJNs-A07YoD z8SyxPNA(IS{A`}|t1d}YTq}dxS!HDE?{xpN%fHx=XkTbA`L=Vhn9sXMYNjB5{qjrg~HXg%$q7tiiq^P9bHar-Zgds%DO?N9;l=y{a6+%BmZTjTIg{Vw_Ou2J4Z4}Has3R_!FHC` z02|-;!#r?B$4Ut2*w0%UKkY(CNK2hxVtENE)ezfeBGTG^@crv~;a-!(<}$96@Sf+E zzHFA+;v*JouB3`!4}ZWLkIp#}eYW+| z=(^2z_us8!yP?o0{F76HmKTYifrXM`9+^N-0}%V|dj9=TX*r_#=<8=8h7CBABk?hx zJ~^*Ot-rdSVi%7O$*QuW(Hel6w9Nd56)xFOQ$FWto^QY}>qrxfeIv9YSn><$o(@t- zCp!lh*3j~+Su2Z-tmKYnVc(m-6`^XS>n!OTn@&u_a5Eh@MFJk*vFT$|<;As75fpU2;aQA5QL>34p((>d_agur8yIU}|FaZDSTJxm z&ss^nJf9})D!1EiRY#m*dwc|pqsG#aV1MX@jI!#0M$jurM?g)ejvyrko8KQ~ z5@FD(;&ZTN_?6Ta9>oCTefqg(9C$xi4`*5vI0Q4*@0OhRygaZ+#=@?>kxX&^G@Y$R8fI>K+Tgw^)IC zI-t@2ykW-cdh#g^wA(Le^s~k@Ww37qIIl+&{Q#2%4<&fty9S)p2sv6H*=wktW!{9w zR{fg#z{l1U#v=QAnW(r%8>oQJSLa2Qg_>|5z<#qw=SV9}&1k1|jP{&tW}DE=Be!}F vT$PO?myXEP(-FL{0YND`VPyG@0mNhuceg6r4T#-Y@6^FN14Nip|4sZKGU5nw literal 0 HcmV?d00001 diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/VCOM/VCOM-TPM.sln b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/VCOM/VCOM-TPM.sln new file mode 100644 index 0000000..f6be6b9 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/VCOM/VCOM-TPM.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27004.2009 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VCOM-TPM", "VCOM-TPM\VCOM-TPM.vcxproj", "{137D2EE5-E1D6-44E7-B11F-B082EEBD86E3}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {137D2EE5-E1D6-44E7-B11F-B082EEBD86E3}.Debug|x64.ActiveCfg = Debug|x64 + {137D2EE5-E1D6-44E7-B11F-B082EEBD86E3}.Debug|x64.Build.0 = Debug|x64 + {137D2EE5-E1D6-44E7-B11F-B082EEBD86E3}.Debug|x86.ActiveCfg = Debug|Win32 + {137D2EE5-E1D6-44E7-B11F-B082EEBD86E3}.Debug|x86.Build.0 = Debug|Win32 + {137D2EE5-E1D6-44E7-B11F-B082EEBD86E3}.Release|x64.ActiveCfg = Release|x64 + {137D2EE5-E1D6-44E7-B11F-B082EEBD86E3}.Release|x64.Build.0 = Release|x64 + {137D2EE5-E1D6-44E7-B11F-B082EEBD86E3}.Release|x86.ActiveCfg = Release|Win32 + {137D2EE5-E1D6-44E7-B11F-B082EEBD86E3}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {C3149E18-AC8A-49A8-BEE5-BC5854EC0506} + EndGlobalSection +EndGlobal diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/VCOM/VCOM-TPM/VCOM-TPM.cpp b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/VCOM/VCOM-TPM/VCOM-TPM.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fad3053e9ea611a56bab3f7da038a9aa71ed70b2 GIT binary patch literal 13340 zcmeHNYi}FJ6`juo`X8ti5J)$cm8MRE1TA1mwh}1xwqAf%c1xkKZ$zN}K z&RibN+}T}fS<0x<76iG=-I+W0aqeRt|NO^;@E~-;4`DOxh23yJ48uOIYhe^F@acqa z@ZAc>VH{4vIj)!Ze-&Qiu7mG6?x*1c?k~b5wz$Im828hx-3b5B(Q^_`W52^l`xNa* z;Sdx~;`_Dm+wdE3^B`V%|GP+WgkEpLQSA8{s9fRx5M#Utm#@QTH?6-5kHS;%x)UB_ z?AKAINjSs(pYi=3?|wjw9o%h&gOImAn7w(1p5I1#JJ7-=bTPoUkKS*=DQWHFcM1-S z<`C_FM2jxCF#UanyWWh(n<(>1cop?_gg(?D`-<8SPtG9M1oDaIL%hF-?^j`ccJ~GD z_%Y6;moaEjCu6iSn;n4DO-MEf&v4xYZv%X+y|pw8&TrqrNY;neJpza08x1#0v<*(K zz=z2*!2Ka4yMSiiLb?;s=|w8n@wWq>`FR3c&{{)WcX91t#7TIED=l`7FLm(iOmg+w zfff5<8|@FGRcQtOqn!+CZ^2EnQb~u>iI$$hevqw1bvBmJ?n=0aey4}JaYoXfiK5WqiV(Fhlp#G0QN;iCg5AXT;Q}{A^gLy&e z73*l<0}Vzod5T(kUC^Fa(X!`gJ73$@^Vb&0A4IA{VEqgTWPD^KWVA~*G5_vjY(B4x z2tt^(tn(F%FT2o@`N|%2#`r{ZPVhU=W7uLXaz`6|4=#w9DSYz~*c5W|D5Pj39C->u z(4!}meRm<@Dc+nw2aN65a?KZ00*3f!h2#bhgY$b=>d4H*$CiK1Kx} zp6fCqT|^F8KeK<8XL-NIysdrDMGG6-%VzT24}U?+waE7?=x{W%%mCiHjXH(1h+X_{ z)Go;F)Y8K$mf2XYZ#hG@mb`YghE$r&WSKwZn4HJ8LR z_aZ)PkFS@A6CPjXf5}?nAY~8nybrWbQOO?PWY98W?xQ}^ETNBC+Gd<-aOThnzu=p{ zAG-JD=+fv)M4;6bs_M&8t6HLr)u)owa=VWLeD)OF@8HAQwp|AHF{gdjmquT~J6U6N zpefE*SaH39^*u(bmXLOG8Hsd8GD<0|tI{D|%?34gJp%JM$*9WO)qJRokfPHZDW|Z3 zMF-;5Q_1x!N{dwWz8>vh4JFM)N-T-Kw6=0nl{X=36*$j%7oL*e`S-o(WnExr9~nlO zrUws}4(H)Z{MB1TZ>u?OalDCEJKU+Y;ZOf`l{O`z@K;7Uwg0rGtHWb1S+zotT#KMq zbLHC*%DGB^=6y{VRjyGr*g@tvfuDD4u-nUD={9Gp5kMx z`hD8y5SO~%yQ$cG3@i_($tX}!gD#m=zYlP=%$E(gy zw-7luK>Y}Gewrb(+-*_(QRGkSnjKUYoF%l~ne*BD+T|6E!rU`~A0A_W&t@8&%jC1P zQoHJz^R)<99w)v&HNC8%4yT^T$vNT)cTWv*K3-U>l0VVdfIQpVTBBMaMeXQSb zzvLm}dfF$HTav7>^ek9lU6H{ z`&8$8AE4KAr;+23L+-ZrasMc;<#AP^eEWPR$>TUHTaUlWQ=~>|N$&u^KY}8;r$21h zw6}dOn_0K_ndUmVx(h+Q8oF|iA)l)=A14oO{Lsg&_OnCpKX+N5HpfQI-wg-G>k!Cd z%r}kLPIl>;oNYDjR}lZI9Bfu*k!ciuj+T8GJ(ZgEnVkDPHZtG&_@Fm7SISZ3aV0+U zd8D_8)=yIA@U@|xC*YY7W`F_W&QG|~*X#+`b18Y(#o!H~c@OIjwt{3)nC)%1@jZI` zDl@NeE--?p?b~|(m~G~@E-Ck6seE7dHrnmmv$DO2*{|%=RNHz^a`r{JTv(4zdHDC#rjA~~~71Zh*T=p2ns^K|p%vxt;VG`)yttX>v%d6k0Zon?Q; z7sGz;Js$t8(A!rbX;wn1n`~n5@)e(^mR4bvyjS~|Ev%pIwB+@Mq-Hd*`h8xOXRB3w za_uO8*_w78ZBf2NotD8vK(gQe zeY^e)>Zj=2$|9U^^1ePltCCrnWsGW0XAGIY&z#3v(Q99Ob2dCe=0C;!m#6vC{y*rp;>;)tp5V}(q;4j literal 0 HcmV?d00001 diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/VCOM/VCOM-TPM/VCOM-TPM.vcxproj b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/VCOM/VCOM-TPM/VCOM-TPM.vcxproj new file mode 100644 index 0000000..f2d4e7b --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/VCOM/VCOM-TPM/VCOM-TPM.vcxproj @@ -0,0 +1,163 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {137D2EE5-E1D6-44E7-B11F-B082EEBD86E3} + Win32Proj + VCOMTPM + 10.0.16299.0 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + Use + Level3 + Disabled + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(SolutionDir)..\external\Urchin\Inc + + + Console + true + crypt32.lib;bcrypt.lib;tbs.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Use + Level3 + Disabled + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + Use + Level3 + MaxSpeed + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + Use + Level3 + MaxSpeed + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + + + + + Create + Create + Create + Create + + + + + + + \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/VCOM/VCOM-TPM/VCOM-TPM.vcxproj.filters b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/VCOM/VCOM-TPM/VCOM-TPM.vcxproj.filters new file mode 100644 index 0000000..ad33d7c --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/VCOM/VCOM-TPM/VCOM-TPM.vcxproj.filters @@ -0,0 +1,33 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/VCOM/VCOM-TPM/stdafx.cpp b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/VCOM/VCOM-TPM/stdafx.cpp new file mode 100644 index 0000000000000000000000000000000000000000..199d498545fbd6c05c1fd8ba485b0767ded7365f GIT binary patch literal 592 zcmZ`%O>4qH6r8ir|FGz}dhbmtr5CYKDPChf$VyBkMl^q3oq3B%V=3}{yZb(7-n`td zGtA&{M1uqoGF&i4j01lTZx*R=Le007w+tSIof_oKZ}{d>GFmVzVdTh{9nb3MXt`zU z7BNp4HUIxsyLCb(>63`Mw6H7LX@tp`Gk}D4m09Th6-pmE%}`2OV*~{CLF%0_5yQ!U_-?}f2kGr TrizNa!-PQ-Z`*!+6JmV_0)J$h literal 0 HcmV?d00001 diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/VCOM/VCOM-TPM/stdafx.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/VCOM/VCOM-TPM/stdafx.h new file mode 100644 index 0000000000000000000000000000000000000000..b93ac60846963b6bf993a124f00b671367569b10 GIT binary patch literal 3116 zcmc&$?@tp!5S`B^{tp-YQjE$E6%$1hS`kQq5{iNn(j3=osY0)oL#>2=U43u%w(aiy zs2@yBb9dX_*_rp=%+B5KUrVwifm}-}9SNl?KjevAVCE&Rz6>OiOS!>XjQ?HCTxO$0 zM%lg)R@^(nou0<(Etaba57+WY?#n&IW_06g2oH&ThW`j?=xM0qzQ&Czy#?5D0Sw$n zBt&}y53yqE>daTn#K4+@!x-@cImb*ogTwBO)Ym|I*?#I!BKtvUqD475iz)j%qfQj=w9@l;m9t^dCU&hV=&aZh}#Me=&*%@H5&W;vL{whwAU}%lr6S zye3YHdga+S`Ue;dke@5f%B|i5FypU;i4ps) z^>YgT#a3sq^4DBl46-IP;Y-&d5$1k@dg8ZtBVODWd8$;+a&>AVy@&BN`1Cwj0 zZ_h^q7-0`zFuQ*TCX(wXn10Xzj^%*%9q*1^J!h0Q|<< zM?&y$_x>wnrb|uFu^VMRvk3X_cv-N!>@%;6{l*ATCER~1D{|&B^wnY2PPwEy84ZfgM0Kr9PuR5XSlzCsRcf3=37!-7$pn3~=A7H9*TsoiKIdc9 edkBVnYnsY0;+(fK82#_oA$-~Iq69w8Tlo)+w&CFb literal 0 HcmV?d00001 diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/VCOM/VCOM-TPM/targetver.h b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/VCOM/VCOM-TPM/targetver.h new file mode 100644 index 0000000000000000000000000000000000000000..567cd346efccbe2d1f43a4056bdcb58a2b93e1a8 GIT binary patch literal 630 zcmaiyOKZYV5QWcL=zj>fEfw0WxN;+co0fK2Vs4B9U*sm0{`t1wOo&Foy0~*EXI^K{ z&F{}p2USW{Xp2p>*G`#oJ!s%(q!H-M(Ty4fmG}kNtEQTB%)V1m=}BwwfWPvrT#@e@ zH0NG}74Ao{glS)#QXA|NYdIfY7hrMp+Ji@H`t9kzWx_SD6;~Ri;cvXH)6CO{-I1p_IJPQ#X=r zigZeSqQguJz35q;zt9^Q_C^^>*mmuXUCp&pw^fPoGX+dho4RCrySs7j@9_UipWkA5 OQDt4mH~x-^Z~X_?9czaG literal 0 HcmV?d00001 diff --git a/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/microUSB_Hookup.jpg b/optee/samples/ms-tpm-20-ref/Samples/Nucleo-TPM/microUSB_Hookup.jpg new file mode 100644 index 0000000000000000000000000000000000000000..22b5e577eeac5c0b6a771341208c8a2068464c96 GIT binary patch literal 858243 zcmbSyXFyX~*X{{+5FHB^P*Gt}snUXqf{m((lz@O3l_DTXR3wp>SO!!S5s(@kRB956 z(gFm?D1u6eg(jpB0TUEWB18x=g}ZUynfLqg{kZoYIGn{kyO&j-wa!fc%tz=qS4S5| z2nK^e&fo`{8CrP4;Zk@g1i86Eh7bfTgft;tXda+o;3mVCLTcbSAKX>2-+s|c09_B$ z{x?rMOy^(v4Qwkk2fT;P=7gF5%D)W!-v_h!MXv<(=j-9n++TShNO9x$f9Uxi3oU-t z1Kus1TWI+!KWKNMexcPb+8EHYJ)FH3gB!N*+_}gQDEw#`1|71|X5-Pw=&0FuU{t^Q z{_A<}R5<#gDLUlhMk~|prWWQ9WU<|R$FA)byDZE%n%nF$x87x84M7{O=KV7UwTP<^ z{-rP6*!^LeK)x&fM)57Up;7{4+MS*t>K8rSGJ{{>}qan**i8Aoaid zrS>>o?ce&z>2v-~uS%c$FWs2F;6H7Fl}KOoANn^ytN&Z}dHTv<>0rLpI@053+nNjJ zMXf76?N=Y>Zr@=IrKkUwe)vzH&9`rV2>VZ+V3i-L{j&xOK0ciD4?XYm;nuKs|*zH1<%=an7u%quvG92Ucj3-x{x%_;@AGz81C)`UVz=b66E-&AB(`O zfO2Z4;MH8v)7d)0AZU&S82vwaU|^>Ip(nrz_=g?`x&NVI;JnPPE7ngO>eTr{6)@=b)$ml${5y`jx&Oq<@B1|Cf-k8?#t958<-W$9A*mJ3e$(_!er1i^cDI9em+7f zXeCSwwhOic1_wEo!WO|6!dTE7r~_(;UO)_}2U-hT1KSI;2YD=Ed}svfgIpmvWDD&9 zKX#BOc)t$j2y=k#0c{Atdlpmx6&6M~v>0%-02l()um>gvCBH$ly%+{#<3LdN~Q0q@f49d1cZO{kM`T%Hu9SjX}1i+5KDd&?3HcW=1K5pr)aj8CDGh{hkOi zrTwQ{D*(N5ySbIaK5MwS$v!K%jfs_wIoxE&KF6IVaPxzX2e-p5Ev(^i2-+8NOD-${khi1!a{+nkI%*L;D@7eTa z|E3GT8UAnjnt#(p(E4BL8lcXp*&^UF1NUs(27f<)17Zpa26yb=|NmM|@Lps4-|4}i zKM?mi~ZuU7V z_2>OB5_jY2Q$c4p21lQY+!%BU6>{O!MoZJ3J5i{Op=Rc$JD?dhbO2I=!DfH|bIqAI zXZD&uckY~d3+69aFncdtq_Jq>LiL3U7N~2gt7|L<*Mdb$mTE3uGE2`^GFyDM6!=}d zaKXaa9RF|E%wN#5g$q8;`#cA>8B$vYo3jiy^8&C-2%N`X7Z~8L>z}>9NL>SDs09lN zn=?lZbavicAZlR=v*LX2vU$rlneUsw!sFC}&F5EITuFPhP;dX!XIh@`zw29`zHoJs z`l{7y)@uK5ux0BuLn~{z&5oVB4jgoFbaHla_3}pe_#X4~4+;(mJrfol5p^*di@OvP zd+m?Jr0X|sCZ}iI%goBo$<2FQP*_x4Qc5CMRoB$kQR^ETpSQkfYk&Fbbw^isPjBCc z{sGp|@W>~=VD$5svGEDXkI5K7aW>j|HdBuh?vHW#P*GX^);hTcl^{`CaSuh4<>K^sR<|ADvKhj`hXWsp6joPL~av|WAc<6D+LHC2>sht53VXhhSbDtZ1R zS#1YnU%y#hfY4p}Wd>sTYjqkMoO|UeGpUQb?94iXkNiP7%3YcpAWjfxPm^`(RlK=r zqG$_)x1EGP@AoZxuj8;GNWST7>{QYB3g>vY;u+{n#470rW8YEU_89+tdaLwTos{j+ z4{f$^kbJZYh;NltnosW=Kjho1vYF0*=Km=+y7uLD)X1M7UM<-$#{I7K8p}9|`m|)p z$0KLE(Iy?Q8v@Rn98M|d3HIG^A%$nO^qx47)^g9}@$0CD>_6!?;|bedn?1TST z4#vKV!ya)p&4yJ@k|kO%N11La(s!)rt9aUbKlcDS1^eg68Axk)AjLG;ak0pR zh+0$9kTLbv1n-DI4*MMMeE|Pyt*KMdiy1}|f0WHY)lG3%*bNcKd@m*+K!vC#=NC7v z-tMmF7=YffRC<7r=-qsCbG<~v=p{|i8sFitzfuxx%2ULqJ8n1>f>qQ86gWJjYUlWk zq+#Ds29$foTBxOMG4WOYm09HGwQ+L9wqkQ;E1K;QBX2p$m{9Z{e>iDCqoZ7RNXfFa z+m>eIaU&nTAi!V)snJ_%^-Z6vse({>@9v_gRX!u%P#p?hj2|Hr(Ug8Dr7C|& zh8>^iNmGf@p9ab7T)&n{?ZoCL3!{L;U3xQ+Mgm{2uf~75Z*F`Wl6cm{u>+48=FqvM zm@DM9!A6$xJhSiRR%LTF9@Oi$O2b%d&oLxs+>(<*<_?0ElXWiY`1LZv;0zR-Hv^f? zBL(?z*mVjgu@J$#D%SD zd2Bf^autimEt0@r^~jvr!v$BxDE6l z+PJkVlkt&CE}OtDb}njEFsNe0&6cAbN4UKjHsX~V!s<2F#UNNT-x+8_u|-mdEuJt` z5+qQG{e!y*ON307(AB`AeqehQq1Me|usll^P78P=YYD9BFEq>WUd~-^T~EX?rTCB; zD726(?+A|EUn!-=_k7V|pnV0%;fIv#Iz8QJt^CfHgUH-)pG`eBojv3iMybs-)z62< z`_x6Ff)LEK)}E+$HcS`-b6JDOF`f4*+vr}#WAQV8Toc6WrEsCAEX$UPo!oG9xsfqSA}rcr6vKSKpSJCJ6ENB zF#-{=KAp@Cdl>kJA@i;+TW)7zCzf0B|8Sx4(cyHtjWo<}ZX98NInU8&SwUEEJ1;xW#hfoR zs=I5()s4nWnTJ(hEdk3Ne^?p*?pD5~*vJ!&;AXN_U0uS7P>vmDs4xf|(LQ;trzO9x z;8BJ&7eiE%YuDw+VR_QJpS|vu7`@sfJPQRqws7vTm-qYSG(u7VGWVW#T0z)@C}~1o z4x5N$O!OsX>(sP!2(kBXcks+!tArce6&giG&K;fCm7=X0bK=>D;(4uZgv|3aCCjZX zn6s?~$xLU5!DxB#(*Y&l`(oKOHtF``_Do4!->v)|X3SbLJT*9%J<)S|Ue%+OgS!354gqV7I(J#!iMT^Vn?23200piUbzcMg3yQuk-oda}Ee1g9A3%K70P zkFt}Y*x{Y#N?u;NV{lqFRyhM%Z{Z%#&n0DS_h}cfz}i_=s5vRSCDw2)WIdbKRXNx$ zR<&QI!=2=G8!pomXRu#n7mC1(zxSXfl;X@8sK~ZcL)U(=0Np!?4?#8``C#y2x!FCT zPhr|0#O!IGeA+0N%8v-nNeP(7DQf(moz+;%Fc8uLFia0JbYLn+(K`)!i4TB2hlvf$;GL*%dkcdC$;idvVdjfb{)?0p}+b;WnsHOjD2P z9y@S`Uy_oGa&O2E5ms~kbNxesDg#+qwPuZ00gJs~(IhPLnBe=KML+Vc zQnbuK-?~SRer}NS`Z6=N-L%r{9JE6Y%|MsD>XdymP)k@E4(_Cs98TpQ7XjW}*n4x4 z<+@a5Ux`sXGph*0L&F-eg$VhJ8A#I^y)%f_=`>EjW@LRbV7WcFQ=5VQ!g*R+{6LX; zHgcdlH3YW zf%G;{7wLs;}XYJ+D_G(|f_@w1n2u4Z@ zmepNTjz!dQ`(^I(8o_Z>iPZjw;ezrq^ULkLsk$yp6h=8e2}Q?=j#BDB#nXk>o~!S+ zgbpUt%?6P}5q80mO0jZ5-fB$)0!@Oy_~%J34a0qOxv!m*DI=9MSFMtf#;=w!sp6w*Rq;1fz56T`%p{d=Ub%A# zV+O)L40~sEA0^qPTDiz*Sv&2Hnvm@&*2&4w46kQP%*MT>R~cYCHt#DpCpHNiWLPCD zf`471UUU~GK|L!*83)+6NsflCVK+GPn%(^rO#1Vtaj}Op&(vMcrp9_@A-R=|272=4 z^_$pzNkJ1Me72OXjmiC5i%VbyIm2h5T7|vv^sO8kZ{L{=obC%cwjd=ni$RU*&b?-l zrkd14A!K-o2cyTjr2sBVenb?6g3S>Ae0_PwM5TS3l$3AjoFnrK5O5#Vm(+>Pru~52 zT3-_P`FP=b?Wca0wRLp_7N$Mj`E}|!)LRA8#7%pZ@%k1o7sCp%NT?Dw@0ildy;{*5 zNXM-dzKj)Na`6&NuUyyaAihs&zc52Rxr32PoF@OleeNhK!c`8IF3z_Qh02K2VH1k< z1>dRPm0PjiY3j-k@?MMIxMdx#3MTDGq3+jesZaJfzcq@^WWvWouAMl`d2;$736}00 zn}x}iQyTxQc6>JkxVO}g{JR$oE6xlz2tjaZd|$3=ay>-VHzx-xC^YPzFXSyPk`_FwsWV>dE3oGxgP1AaY+kVKh1fvRg32g^{_d1v2012y0?gl*F5u-H8!fL%ZPi-`DfNa!+MqXw+${ zx2ri-*HFn*HSfGo6$NGu+8N4jNaZ5fM?%ARCJOt}L-GvqoK2&955a0nSDxPT6#EN1oYcpix>F)IEzYY z^O(t_dJ~#5F9ScoK8yCx-+b}2k(0cApw{<6{)-+@w23KKo-IZ_uC}z_zx8plQnUKg z^W<$6T*{V>>)o(Ix5ou6h?e41-$la~_bo5|3Gss(|7126xHr3(ad@8T^QrA#kc%LYRF>gmgo<39Z{S>I@N3VO`h%?P{D5ymJ_@UlGWb)E^+?Dt^zTrF}r z+X*wrJOpDVVArFE%lE^{qx=n%`4#=Sp920Ec90PUBHlP1#Mvb@O<(zFo6pXBd9>-wfvl_DhYpd$E(WnjZJ5T%ij#?#B%oE zDLQ74Sa5ZRy?^%8>Xf|GYj*c=%H?f}F?brfToujgXb!JBL?7MOaQ(5+KE=r@jT^8l z{xwbBoB6})c3h^Zb?6{@j9ERMmnFb@)TiE)mYSd!2kw8B-}d!zBf($~J$BWeZ3fX^ z$pNccCbqrl?jsM5)eUK{nt=koc4O%El)JB&-Na^WR`$(1=R0Qqydi&CKgZ?Jy% z%T6m>-Xxj!NYKW@d& z&SM*}U$W1}(_4=qR+ujkC9ujD6A^dtlg2hT&)Tk_2~@w!=;lX=R%r)3J*L_RBxX{w z&as0g5@9rEh&1UwJ?-Pfsmz*zCVS4;4cK8Cdmn8+?wH*99*u~MFIQN}*Nh||rhL0N ziZXXjt6L9LSlci;4NjE@h8Laty{X=>!cu((YHFGE%~GwW%s>yjsDrP7ArNhHAKgu5 z(ByRC(ca6b5zF(mC`8QqTpf9D=-De9KA9`%gR0-HeL^Kcp~$A1du8pJ?Xossk&t^h zRS>E&p)_Qr@Zi|4=ZEd>2O}zwvBUSSc)ymUW<3sFOn*UXEGFU*2yjr#eK@Y4%Dvv1 zy2qS8HL%&D2_?m&XCT){db&H`eoqy9ce#u@K16fMY2&4bLdgdoI}oGJOZ~zyx!6RX zK%R*sLqD$@LmdgZi(ZwY+I~Q zHR+_co|!1;VXxfa!G+Bc*1%YfaCpO`fwd1$Hyf0dnrD6TjA!1Pf!>j{Tz|0GKzH!0 z<9sx+u-+jfe6(7whZh|*raU23E5n*(xy~|dcW;tFPt>g+w1u&E*<)G8Mw7a1#)JUV z$P;?D)8Teg9Iq@(tA5=Wpz*z%d%Gnd2rHf{W!Jvxm0gne^l{hSUW-SHk5)x~=6%X>v|T@sHf>X!b=py8zSq`Pi)4qF6l6%(?4s&~=|K9*8|+3BQ8^b{dD zh`MS5&x*+|Iy?hqxEZA^jx;l-;eldOWg}9F8J@2%b8LVP@US~@AL8w}wdOI*zCTY0 z>8%ZCli$ZUC!@__TvJTwALy+ zrNzIn%+p89gG!k4zWvxy&UWV(`mIG=mU%0B26WE&$bmvxWBWtbBH%`cRx7SxrBPd+q=mF#z&6LG5tQV#MQxmGaPl5; zW4`$4(|B5o4_C>8;Ke;arpIPrKTl<{=&?zGw5zF8^m09OKMTT5a<`>^xDErE9U)YP z6O#r5MBUh=$Qfv_v8yK$@H=Re9um1s)54?W2LxrDXwNUQ4G z1DuUCf$aP?w?;InAnRI+!9q44T9+~k?~(IjFQY$Iws!@Hy>_yAHVjwx;as+=GTH6f zw8}8>pnjT|o!ZE=VIDY)KaCH;WJjA0eGq%Dr{&C(1&H4Fl-|uWY3Fuw*OE;Jk%kQb zf+-Bchin-|ih=IWU{NITJ)md-$zyQi+ame~+AEyFb#31b_Ej@2Pq9yrFbf0 z@6NymWMGZ*S@z2OIJBK~++-&q=B-k)_u`t4PUZwya2^YR5TX%)T~2#Nb>7YSU=87RJo)*`Y` z41?JLi?;g6kl$WRR;~fhe4i|no_xPGLP5vn50$L{%k9}E?jgZi{dlnLi>{LMiBSnG z?E?+R%$TZf50k$vR!?IUJ?UGyY2Yw-fu1eli>F-P2Iy&dX*RIP+^G+oS*g~=EfX`|C*E7>C5pKgfo>Eow zq@`Q!dtYCZ`pRpZBxnZOp(v0YMMW71oAFX9erinPHrmKWG%XAG=^b}Rghw%{0IqQl zo#!o7X$P5OrU;GY`(h8e@yy&a@qtXmZm;YJroynSrZ3}l;3FK`Kad?8&rnz`+lD-) zmUUb=TOml@UK2s2qGT;1mX7FS!q}PnomHkYP%a)A=X)17(krESp?(BK2cR)+2lD}@ zF{EqJ9sgGcudNzjVUH-OCdRh24HDPOlI5RsxFKzd? z>@c=cEROG?WA{A5QoQsK>{PiRn~%01P#K=*tRrf%U#q@)2N2)9;dYGhjXWzE8^q02 zk*L_1h`3t8swljvx1nA}V3o#5*0x9pKv&RQetL)WK^Gd6cXOqcG0$Y1rfVy8&8L&V z(z#jM)P`v1va5f3DOzh=zFH`G?T;nvvDYSMplGt=r~XN91AYXps_DBeWK+>%qP)i_ zCZ!%Fqkps|jnUc<#M6}#rU;hv%|erxT$S*^=$d*xz*2>z!cf^h6nnJ*GgNG>K&u+iTT_j-J=%J=8&!aF=WYTgXgN4mSBLJJ3u#}z`#hLeDg-XvF>r+>M?_Ml(?;%RkFl&CViYaEl9 zMo*+SJNO{j1`~FZTDiGDH!H*0q*N)%=$oN;wO!y+&bCS^X)6g)0~K<%t^HE_)=>1( zXkDHwx&vPB)MxudU$XT~>Gztko5NO10DjB%>KwRAk_gmSvh`dgpRJ&)WAeroWsJ>KX^WTZ{*pHo zYV;XqkaM|H#ubm(@9)^ec^DZ#O5%?6QQYh^q`@Qda+US{l#RDEE;idF@Q4DkP4`V- zu?6)JS-QH*>3m(tV5O3GuNUQX^v({IR|8#dy649(Qdf_J$Lf=Nchf__T)P#rIe`&b zKlgOjscBd@rti#Lw7B%e;t}l99bc~xX(Ib=h70YrW}slg0G$-VPYY|>`{qrx#Y^o++y5s@*dC%9LK4QS* z=BE}Mi!3(H7I#sQjkxC!7KF({wD*nC9~@Xu5uRpBjKF|GNZQM&x^n9+M(g9LI+}g$ zp1vjHCbq&ip^;VOS*HMt6rG^mD#hA!0|6>QZFEc(xC0GPYhh`&I5cOXaz$(fuNe`a zi`HWSR865y;yJ$mmS=q?b=r@RR9$J1O+L(^i%}TYLl^G4*v_S02^xfmkdy**ib!P^aWxdE4y_a2`lpOSd?UJb44b-6 z9gd2ZABd-gA@=xAhoL&R<9(3RnmY@^fIrN~zgM&B(vZ*f&H-Q&-OM5l9!G_s0JvE4 z($e%}d5!&`|J9*e7C^U|yKAQwanlD}2x*F%Ua^{w6!iscVW!hEk;H$!zxq5wUL7#f_8~h*!&36nP?N5p3$jpQ67yn))i4ry6BBS z*01Kjt?YYjo0+ii(i|KR)3mmi=Ui-tMe+ByZy zX}4F)8^0?0dHSvIrM`v@vKIeE`bgpf291>-q8uEOW@T|-pdQdKd3G|?N3p^mu;sI; zm!-+3P(MrBG|5Kl?^Z%W)p{Bp=yQAjiK?7DR1eHl-ZvnB9IJ5lt&StqBxEkxMPIcJ z?ekJfvVebr^M?FG@gce~gj*=%+wf93@7udMxkq?XLi5+desu~SPEJn*2>NAYW{U(Z zt1pyOu1UjSewl@D73%jpwXJoh$9gP60`h6n`jTxEKyJ#%$PUhN+f!mxQf{dfo$)(i z;IYdpxXLW=t|+WOg+BO5Z5{o&n`7szOUO)88M}brA|5Q{?5?vVOq0`{Y#7hvoehQI z_RT>4eYWEAEK$W(vin&w^5c$M`gis+W})QJ#OJRk>iDCAV&hTtg6}gB&-*!3my3~- z%RJu^FP+fBmRmR)GZY6zLTOQ8SwDstZIhUGIk0Bsq*joo>aE<0+?>xZ(%`?$PsV^5dfb@u6ad6|v#H1()r zHuw|QB?9v_96!<3I$>!E7ZYb~g2J>v&tx|oKyxP)HGPP?-`0Uuzue8{9~W|XLN6V3 zzof?UD2ygJsUs-N$u|>;eqdC!TTEzxf2gz_Wxk+}X75~=RGcxHhb7VkkzJ;6AW-)g zhK6Et$rXs_j@%7%P;Kk|62jQhJKNq5(UUIM^O}JTC@Koo-Oiq%j;lKta4z75dRwX3 zIcN0<*vn6@@2K=MERaoH2u*LfAxN5!%R=R+ zGBysVEZ8)2nxJIcnf=QhYkKwi^jD03b(Bq7r>ntBULN5U}tuJB(;lnYVC7n7n{rcxSJU5{L$;=c&zy zbCV@BEXTy4;`p(2$54I?MoLf4zTOcv-!Sg!%M7xOP4K{0nH$4eBn=ppS84O)84lsdg8)mzJD~*7o z^1oHR>%H14UAxw=1)Ldm1wGULJc}ZYk`QV=jN;4O6$`!>d3|*WC|%fjY^!dY!aJ8m zyUzR*-ql`!28w!k)z;K7IY5@PuA?t&KB!meN?U|FcZ6&eFipdTQ4Q>g_!{6H#0&z4 zw0FzTHd%{UN)p<1(C{JtDcMf~DXtBHU!|)>y$9!=F`-6*4Ii3#yaI=2y9nkZr&sZ$ zrE+G6sBJmyxf_tOz{`HQJHC0s62(@sY@}b0q%>fr$a~!$A+E4^Lc+zaAU+ELyo=iQ z+q}PpswQ`oavs+8l5Z@!jd}?p33`b5DeY{WVjeD@axg#P>4cCBPjuf1Vk?)j|(w)16o3M3Udgi>g zv{mW@dsa*nlGD6_>hM>M1C^_Jm(eCh`C!GXdLYdXPM3uoNX%&?lf$*T(5=A1m8#3n!Arq?{OAFGV0)&){ z8Gg9Xclx|E!hU=8c7%-1qRfjQsGAS`iD$lexNMi*OAz*2z-R<4xmAE6%4;=Rg#B{H zME8hNZuUKsxkddr3NS9hWa$lc^4fa|y`#~~ol0SS64VM zLmc@MtZob0Okc@omDU0oERxf47rFxkp=)FSgqr-UX7c<{LOI`}I-Z7~=rM19C(>qC9m0G{+Z8@ z-5SDcS6(=IIBD-5r12_P*Cl-F`jh-t8I4 zrp<)IZGC%KVOKW<&fm0#u5uoVLdEa%L zJ<5`Gbh2?OTelmqEev3emw!DDGz<7`D}9%_FJV;F*xJG6rk8%3BtB)^jLXqok-3md^FkD63u=qXX7LOJiC%KwJ0>e zmt`mBawt-KZFc-ylV_-oW;;Y=xeIwWW9h5GGxcM1{{qdP>?JS0zgETdq1_+#9{IEA z^@!xIBeP~nsvmW{@%6;33X0+YpK^m7fXSue9QJHWKbW}Y)j$d%#ST?`>vc7m85tCK zT+c{+U8q3~N61{0WrX3;Z(<ew*5cPqiGMT$&BH6R`P1EU>$>J5H|vV>kF-~lF9sG8`HpG_ zsB<4s>ObOlBOGW0d4A0Ulk2lzd^I_6|^)m zo8EI!n8tF6?=`|RbG*s%_%q6T#%$lFs$T0o8)8gCvii)I$7~edlE$x@J|472cFCYQ z+yA@imp;{7<%Y0*A;Box^>a?m%YCd;tm<~Zz9 z78@aM6(t67H}q!Qv2V_+yy)qGAo4LoA+qp$naL@oI`E4(iI{P-?}Ad^3FFSPr;#Wc z9!Z-dnVB$~?kj+L-hf9vf1KhUp6S%WipySos;+8n<#M>pzoxb}$=!HkzpvPoRS=Di z6gZmHW?r{%JJKU=dDrP$ZseEe=xcPLjG^#eCo?V()mo$>RemCFW6i1Me)=H@o&>0K z-jlvz(!`+%Ynkr@GLIYa=lYWeLf_RG4t)MPA>1(e`){26At?`hr(@XOp*gSEsa#4L zN9(v5!`oEP{I!xdT(0*>Gr2nEO7*Oq>+$_9wV5jLk5x%hL6m`d#+xud*UB7vbXGaC zG}&b0RiRxUSL$D8@)w%Ul|_VS2BX;U#!5ybsaoqR5OLerQ604I2{EGXyn`7G`)E1{ zF?w?-ftAiNW9HLbcn_DayR)q&R4_V?53EV%J-792TXtgUxL3+wkrB9aJZqoE(@cdi zy>*gQjM;)?BKERr0vWjoU-+nu?Fzi)htpa@Iws#Tjs$Zz4`qf|s})_BlCKr4X{y#8 z27ZBlApTaH)DV`x7tH(kZUx81qFgz)gPY&Tl#kU1_K&r{Yw*w8aYNLpSO77V z!h#ql18bJH(`K3U;`6 zx`NPDLtNzgi5GW8f>uph0}OGp$UZKq(08yNxYusZNsLUL)^updL%kH)#KwgL==cgi zyv130gU-dc?qdGK1*XBA{j|;9xd##i#S$7n6gh;PN;Knr1VbQcZGwx&=(y>;T-Kgc{Aj>L{mpvm!+v3D4(Ll4mEO0+%kd|ew zZet_&uCjRmf`^BSLN)}=q4L3|-ZFT6!&caCrhK1DJ3fwx6)UjBbs=^6O#mytX&`vp zS;mVA+j1}VrG)Tj4Tzn~=7*NVB!Zygz5=u$@_mU%(Wx6eS_oV9)pIv7M$V+lypkUb z*kZfAZ!3k&BcHwcZxSwbB3k?d8MRk9+V?xONR~;M+)QkKR=&mOIR$qq3Csb1XO-U? z6h>^y^FK3)*aTcd#63D^JvvYS(8>{c?wNr;TDceuIt}`Vj?|u`o9KSESqc!?uBRS) z$SlX-8;~^TPT&ubN=buAu%@vEL%}Br$~;_xnt46@c6-_UK5XIBMw?|%4PVy+EBr{W zRm{Y9-wVJvJWNeA0oo%E%p*x~YHNQ6=Cz8c-^%dzlAuXiR4@O1N`5GrHs;)iG$9Pw zW7F+(p8!9k7g3#kgh!)^6Iht6pve5(0A*#~W&O1H>IWT6=d!8`b`ghe?#}5E$*7(c ze%U5KZ+@o+;1K^LM|0tpyo`v%-6H?s)CTWl>(Ac)W5BVrCV@9x?D!}EFJv~}?^@o# zs_8$)zh%QX*A`gA|lp8WpYy3V!P z(bg>z;nbr-Lwei9a8h7r*pse$dQ1zzP_Z{YaW%kJ)$qbg%or23yWkpnAviM!fGOQN zet@3h%&yCPfICO@BLTJNi56j?v_e1ZgY;|zQO;}i>X=ic@62nX=>Vt$E<1-u^$0FJ z!zs%8OG8mrLDN}xj)K;G#b~hIVZ)g@KPF2*o$d+}iB!4~CvZX2KIA^N(2&5(Ho$9) z%yp6Z=AAuBSi+?b7K_a+GF^G{aRC}=HT39-5DTsdB7oF8+(fj;H$+d;0H1x@yRp1=LIyuG~}c)n6BqiT|! zI%s4^8Sxy512;gi32&`d?nziJ2$7M}M&F$F1;%_tHe(q&1l7T7JtRHF;h8a&V~bz) z;)4z87F4Cg-Dl#{X`Y2>%)+m_N1N-j7KDbDht%#VPmV0lWELcV*tO`46CyD3TjBSfr zU}PZKmk|Z5nBv#94JyNw^Ex9Kd$HF*(`%df8e+ZXP%sBCbTY7u1hMty?wCRN(nqC@ zqD^(cf^*$#(rWSYD&r~PfpJ9HZzwr~rYtUYlfRNocNb)w-Dn@z?CU0_RcCVtVVu zXtXD6?e*MrUThJ91q|n=+Le(uX!SB$_}EZg67a0xP|i!!txpit?>MkJ!4BbWnEsoSrmz8mAh!)7}zT#G*ZCEPdQ|{N>=wCjyOM2A#My)TZK(>YZahq z0l?{ToAJc3f=7&Y;@=nu0E`PmFSqS9NNU5x?$LDt>&CShoY z%6es#)orE}U@qjq7D$f?(9%h)_sVbN4F=Y# z_1}tF^HOh%+(cz z8LeKE^Rp@awN&>Kau}J`D38`U(Hju8ic|iQ>AyPb_x&}lz-`YP^grDuZ|;Bl)o-A> z;y$7yyGx5T&>Rc^7o|4LiQ=V7M8r54*#QzfCTuD#sp; zuW-JG{Ejav8at|d{L;H7tIONRu(KlZ$ih$2UjuG!r5-mF1@f?u`^u9Zm3(}VqOb=M z#J07iiquZz^p>dtn{OofdEM)ce-_1*r1%?AE(y`O^J;qz#D9+;S=@Cw2bSc*y)*d} zgWdfVcWj#18|T}ePbGZYRx*~CJKb8s`f6im{QbU>6{Y0#5W4I=x5$9=@%3g(-Qt)X zBMWXPERq}G-~F@~F8i+GJZ_gwP!?&uz4G6Yv>~}WI2skSo&s-U z)273GmH~HrR!NV5O7jjINO$9%s~lxIU3#noH>R;u=-+xUq=O&Q%?6~VTn3`J>1=6l zK*S_@{J14J@n$MphZiAr858AON|yy{r971qKzw)BhmOx*C1%WK!-^tW#2g6-RvaR~ zf0}ZSf_fAYR#22;By@Ie2|!_yjdE<2GUAVXV6R5FH*W#oO5`tDb$A3w!aw zdZ7ydZmQ|n@AYyVQE5_fV5KZuUVBKum6-M+haPEd>OMhpEPM>&C`;R(v9C>3%B=(( zcC|EMI-IC&?IkU}GlKhU-)ZZMUI3HO4 z>Xc7nOHf1jSDRB3pq)G|m6uGn2%Y#(zDN)b9OJA{8RlvCdc)V)tQ6O*Vl5ry9U5BJ*f(*I2E#7ECEwr^@?>2Kwhdk5HVd7ocVKvYmLu@gB9eQQ~j zrcSqn0`2VVevfq>IJCTs*Xr@g<~;SRiHku%I9o!{vhI#TY0~+mkY!cEwQ}BfL-*~n ze4BCLkCtYCD&cGmEQWLFKQ%q{BWXmPx=Pg^4_RDnouGs|4lo0=pKn%+k1o3vr=}Xm z^Ys*6+iiWa9CXgp1f?S!J0BV0hR3JnxBRa@2^^RWA=h?DvK}N-6L?uEB~ici3~V2J z2)@OLSs~c0NO?Jk$xF+Rzdg_Jsn08!yUO;!w)EY)*(gZk9(SVK-`epshzptMrp_Ou zfjH}vX*fa*_T3!QHIQwV-)Rw6T}5fLe|B$^~k*Z)?FeQ;QKL`jtgbD z_?~NF=rCCDQN2hd>(pJxCNqX>z`4?aE=$ zw(vzYpZnwMk!dadYCfM2m#xN(TN3=wp7NvLvX7JZOr{{}RYLQt)U97xR~@T_$5C8v zLd5n?yGfUhx&!e&?I*q}qJ5wGK5;CGwnzINi!TRGkv8ifd4V$TTxvw+xRFQax)(Vj z!{0HvbPyTfgW@Cz0cO7$FuSLPy?^v3iPmt|)`?0igt-B;VHka06Pm!E((@s(i4xB^ zqIYBRBoBPRGEgW(P57kg|L$&(A@6ql7} zH+0hkY@kL6ZXGi@S7P+>KlN#KzLv?B_F;aNP@@NBq-F2KZFvFOm*FuywLz z;%S{PmX+>SA6Q;XXFYCzpgvCGfEaYI_-bthPo${b{G#L7Do)R9efAchaKE5`duRHG z+m-ip=MrA0ieKGz6hNLwO~u_N=rfe5uX0wWc+!#Vf~1@D{S z@+tt*FX-fS0jD}$iO^M4zvZaRveJkbDwzszXa?GD!=MUEhuW1_z;`z6Fs@1h7v~jC z#5d=+?p^rw0ozqM=91KZ4g})O2FnnYq2eimxWI#R5`YeBArVkYK;+I44uB>mJ=25h z#928!Tq+RpE4wqIXb#V86;t)E$HF-CXhMqoh5SZS-m z#JTmHhx3c2jF()l$A!+0*-uJxG*x}9n*~5=g;ou^bIDanrp!c;sRUoIwG|Jl1y z?=HE;ok3NS(frWU+qxmYV^K7*cf_OY@IV?F9e&s+2hEleK3Z?)Yn`WFP;R3&y&dM( z-5+S*MUH0^#YeT~rFC}>;Q_W^gs1~}O4U2NpgimxxZ&ea%jqg#0cQBI!?Kr3AuslU zK`&Q<&{Ar7@WITtZf*DpqF-tF(yT(jWTEATWw+T{tg_EO z4n()zI%f;~5#hd4REL=B{B#7zka$+*6YX2U5!ox!Gwpq;V$|jpsD9Utz5k-RPQa|&#K$gX#SPh-UIj5W68bb!E1LTq~2+a2tNa4iINg~CcX z7)&k!at-}uKmF*Mf#=sIgmR{v#O}SeqK2Id7loi0^^~J!lo~S-xIn<>dT6zTKc#{1 zW28}@#wSg2rhFvL!=l=v1o)%=WFs=2xCoWO!-t{fLS1R^vR9@6-YqT8xOfSe*~V_Q z=aqdcS8NW+cpZvtu1gCL@xi{R8mwIvAT*(gfY(9qwp7k8-D;}OeQ)>GJMvjTzBDuZ z!*cK)SZmvUTArg0KIGy0Z-)d{=}xtEl!P&#)Ts5$1`wWiv`TgX&gU={R(v9w1A@E` zDM(RkZ|b4aZX5@(5h*QS*i=PWT2ni6sF-XyDW|m{MZkvBG0NLt6f!zZ|9ISMBxr+p z*h^y5m)E_>&SwOTk2pLxZ~JP#%J?GSlm=SyPu|uNqt%P8M!WLpro+C#S%#O6c&b$! zQ8osa1CYEYbxV5Z{9e`ME}Lb-3v!|ocs;9E**@uk(zi=27!y?>K(gFAC?GnT(^0PK z-P1B9rX6N!{U4IPJ&@`B|6ixuIl7(d$dPKF6R8NfO{J`xTaxQ0x3kJ6mTi?xa#@!{ zMG~6p5pv&LiZKkU6xpncP^KpBEcM0G*m936; zjonhFKT%#KHG64~ziW`jm81IAwl{iWRw~HTK%)mK(%2|XA+C|zOa$ux2zrUyfz>G* zyX%}Zin3-111lCpj|G!0&0(^u)yrKI{GZMmN69h-hbaaqF)$@;na%1M>PhL)C9`A+ zc0Q=D?ZT{jEAuA7;4zl!!=eADgV4y`jR#t%E|P&}i_`%`JrQWztKu4kT@P`zMSm6- zBC=W0+3AbyM3`BKwLhkGGdj`J(qoW_jBe9&A0Ga6EYc2`ERRSADQM7J0FtQ<`OBxz+|E) zd!jeX2m<;iV>5ZlxJvY7@A3#9tB)~Ddg*2yPJSbrBSp?8@yP%Fc`{B|LrM2Ldzd}C zZBC%@^YiksJJna8auPh@r5L%j!E}ereren{+*%@~+oRsIAp6}577mTCpCNZC$h#J# ziQ?c)Ikq7F<+kZzFe-X_i>I)cck4#bxrn?^Q`< z0fr}_*&ucd71`au-xJme9m9!gQWhl)v!4k*7fsZi!(LD8^oChuDj*Bps&z%CQV_4< zHq};}_fKeeHB00^eY@Ht<`unGac0q&4iHPjohdS*an238QM8D6A4Qc%uHlNg^JCZ5 zXRxdHteEyA{uNAZ6>>GA={n&dyCL&K?V~0#s5mp!pJ6$He5L(rTXy_csn7QeUdlSnJHGP)M zPkIst@5IlM=v~EMyNH5@kx+#{?jDVS!5eoUN9&4&ABQ;CJ?d$Hz6J}M1Nzj^mw#66 zi>WEtsQVJ1vzzi+Ib^fV>cR7lqwk?IF?^&dUxKiOm0A!du5X^N=-Og?!+-w{=_ZUo z{{o}lspfCXoK8?!nwjrfBh=08gcfrjb)Wcv<~w>26R21OJaW?Ale|3_)huf>ma3OJ%VuZ+cS9 z5w200^GrtHo>BN^r!#a;PVU@2|0mi6v&K1u%_d13pIXkEZSFy=OlFf?^HQ{C=PyjY z8+(ps1<|e*dbAD(A9Ocus_{C|n|aF(l~BDv;_>mtd)^yOT8^ii5pZ^M(#nQ19MX&! zj)ln~PLGqgYW7ow_C<;AH|(F0?xvp#g-wEk8H#b^U)ZNTO^@t)?G(Q|Cl(Jl=QC5@ z+M3per{yPD5_9WQj~eA>rsR*d_iDp=0EM~(^X$j68tq@Q&G)b8?9U3%A-|b7!L5S& z_|tG0;xT2Q%PP*0`(>Omwxa22I7uUcN8eCytJthqRvLAabI8i2(WLvdk)H`3xTXoQ zs=k$)>KKa1o1~3xXxk9h&kD8w3Z>VWon~OX@tN>ql4$nx);fOb(g8NG27FA*g7EIF zph+~Cbq|}7<8%M_to~) zPZaPI|Jf_*0Z(Id@=uQ^-NbQRM!D(<1-gyWSL;8-2L+LY^lbIZ%g90N3|fkczDAi0 zGY-?aYk@Amz?p|ZSQtu&qM2k~VBFR=z0c^{U9o!2GnZuE1T(`#mi1s0CEQReLGFcO zRsfAx#)Zp_{dOn9I0QjtMq+Dp!V9)P*o0A!SBw#vM<%ljCl_W$sfP6nW?mXUL3f7? zJxq<323mM;%SU5>kkbm*N+%1$OhJCAub>)KkZsIn)JzaD-(BzuDQt%$!0Ph;m-=Bg z>K0A!p)#2`Ufryxbm97inm@e9Co>Ob6W(fgtCwt6(fccQ&y$-k_~+G{V4x7{F1*Y$bG+O)lZ&goAKWrxPD96{M(o(TPIiNEy-2Qe}-d8Yunr+G3 zL)i2m;G2O*`L1hY`^AkBesL)O_RPQFY~ZL ziXYK7Py2>7|sR%ihcy>|NZM@Q7o%XjePxOeU$eWGa z#INZ;BS(sfc~Ys0-fLL?ToD!cJFS>S$~z5c?Pc4Jd#U?HTCOu^<_uir!yB99gUHO8 zS2y*E1N61OTRt~B4y{Vp0V}yaSVW~$XBpfp3QC5FvqUsjLHVct#aVGcTq3jPs7wAE zt?8*GN#A7PIcrPye(7hot3Ix$vpx{SlZ7*8XP7eYHn(;cVa@v^&lRnig*8LQ$}oIM zZ1;D&_xQ$=*=0*+q|gF7d5NH==q(B}|KCm2k8X*(Sn`pTFj?hBFaYQG59;Hf06&S6 zHC7t;Cwq;fL*npiOX-^=2}|N9+5EJeD6BE|6M_+0v(V)61OW-8(3_B&7L(z>9j981 zGZ~o_03!5sH3u7q{?f>|^BI~(<`Kg}=f$`ock4$1X+ya)gkW>4o5yy6P`@SubsjVw zD2F11onM;|NAp8#IbON|%^P5LOC0yGS<+W}q(1Fy?G^Vna>6OIMB3g}QgbHaG5v}0 z0ca^yer=#yCt}}KMlHqFGr-nL9xeU#hdN(HAIa1N2;0HQSsOH)3?)N16HHXHy-Tw_ z$HINZpU?_CA3B`0ifl{E(+HUOhqeu{D+qY{L|f&3)A6FsKtdoa907!x;Mm)lA%jw@ zPMW7mw`~uaEMvvd8EhK3?+cpG@2}p+MQh|denGia?MT^eQm-%ljFju z`~8!_0P(LjcNN7MP2x_}%I)zg(X)%p+<)%;J@g??y{KqL<}D|LS3hks-tv(3)@~)y zDn{+l`r>fWg-k&}6Y8z4SZP?&<=r3-p?~wLd!VjsaSP5eT*`*W5$G)3Je>%04gZA( zx8sdWJJYhR)QS~zZ<#8^ZL<)JJ0-sh;Vm{4E3a6NX-#QI7d>4XfJ`FBaT6KE)j= zGSO>SM)6(PXj0eCxa$SoA-xxk1SB=fzR27b991Oq@BNanScsn8KdpIS(53{n;&=;zxAa)7dcoI z`HK^A%$_?#)l5Z`?S)!|%&TrAz9^1RekR-Q5gS>i>+gUjq)N z;{VC{xbG%<%Xg8MBpz_4j3Zl$yhW3I@X6iN=R(FQgINnZ@EJl!Mn@)~vg zyi#qhs1Y)=Al@a6b9yJgF!MCOm>Hy^7yn!qRP+5-F%=D>37@AANhf9GLnr>zDbJS3 z&B!7@*|;wgz&~A$li9ho%53BbR&00R(f6JOafFlF?`9T~aS+&$nXWG-dL;NbC@^38Qj{2e@zmK>`;>`2iN5Pbc7Gt za&JjQFa(omO@nS3+;)I=x$jVF-F%5Q3ZZ#BBw?aitd6_7RCaQBM761QIz173==byA zYsMc91$hoEfh(N!FT&cwA8*x=7ZWPGFm%z9&3630l1f94w+BhpbZ*}ORz`02**w6^ z;-2nbE&9HbD~vJ z;hPKwUf4plE0TCi5!O=3Nrs{!esf73rmw{H7 zj9I)E{`5Wah|pt@nLl^;M$QCOfKgQ=t`2r-2`Cc71ZeSb^g0%91>ED76KLO-81qHXeq}j=(C0hS<-M_TkMKW ztWly2Jv%8c>&Fj2iVwb#?Yui2&G6kYp}@w?vbrehPcJ+A4KITE;mtCw9Xc1KJZU2O zfe;I4Uu?OH?htg6Mdm&-`K$Lip_bKS*k{yc$y@9HbUH+F@~V9KhW8;XDNeZnWYdfN&s_~U-b9+O9!$q{HK$Z#?<@fp*}C1)lw`lX1R~+n3s#w zxN0ntmm1-#$jT8Brn1LkDUKNV;>JTaeICXzag7RAZ-vpS73PI|*;Aau9or;qD&uRb z6m`hNRoxl`aC_dQ-m>0MEG49%Xf|HxHA+8`%0Kk_{`P?w{PTX8c^k0Hu4Z1K#bPFR zVNDEcv&xfh{-6$RiX(`J-qV^Zlw5kT-3N~w2 zvdqTC^zF7H)>RU({zCD(jx`obvwBJYHu|Ows4$=MVvxhN(v~x;EVu(41;{GamfL;c zF|191B$$Xj^eb&O_Q*X+Hi}Xtizqmgu##UwDS+?HZe5PUfnsLPY$3J&9W6QwbC5W@ z#BwnGV{~xjfnAaUMI&|NT662r?WWmtADeraP11d$|7&7yv2JDW8H-&rfpzj~xyatHed zjz`ZHevV4q*bz%fP&%tMIQ~Xj2IJJWQ;b+A(|rC}YbZqB z)J1I(McbHhWRac2RFt{9Bp)B3r*NL*a_Hw%optRS6@g^||1M3MN_@4P&+xMgbqrc5 z*b=};SgOoFxreqCP2z71|G`!<5S{)q@`Yle+K4`7T`T z>#r|Q75W+#9*bA8z?u=A<)WzNs^Qzx7gjY%Gh9_1Uv}Cp+oCoUDdjn~gZ{)JNIPF` zX9fqhYk%6ulV<{MHy~kZ^X@Z|a2fCcxDtj8!R#m`$IlE07cEE6YfTXh>pfDMmvn(2 zVQBhG<{3F0j>8?t#nXzKUl!&>pVyj(nJbE*fAtLCgLagxOMJi>7}AL^Nl>vS+$T-@ zQk9YD^^Rz*9>?o`gRqVdRsWZT`OU`~mA2oHLF+*>sycA!1)X*L}s{#@0?XACjn0odidjU3dioiG*r@g0JMv-~$(l z&tyDm075F=5E>xJiVM5eJ8Rxi7NHy>KfqP&H~vp2Hx0#dr&~hCnI7rsg9b4e+-o=N zV~`vr7Ae1-*Tz_K=)Q(aM(!LLV;#Ege`=RT48H6zkA}xtnE+B$N%tg6N2*;oK$?}% zZS!qkwO5=o+{{@!A@j8-K)x1W^&w1b$;?*Lbptoh-Q04!i4kNdk^^^S99>v}h)V(0 zNl<^VX6{i}WHGO1zflb%^7X}lLiM*Z68V?{#w3S8&GK0{unPeDdJ|cP%Rv2Sw{__) zm!;63Bd?=I12?W*Z_fdD7M)p}F1P&J$ekJNr*rzoDn7L|vA&v?wF#0Z*48XxYN+UI z2cF_tW97Mr5nUi&jJDQH&2xT~IA?D4rmf-mlQ}-yQuK*z&S9S*l!b6;si#$W1R`Nl zSsS6%aSR8?WbY{I>sk!aIvf=j$5nbQ7yvm;azxdkM?0+@BPs=szB8?|A5nExJ3%%B z0BJy{rm}ViulfVe<_KtGGQHJ15TuKSOtB9ODa$QC-rfubEFb%)ok>$CYB4>D{Ezdf zl_CwVm`r*DR7QH2oqzOsjIwrM>?B4^X6{|07`;f$1K7JXV(F-MZNQ~b1__hjHZ!X% zNDisryMSuMfZUDrj+&?$_gJJt=}k^;+#caHCqs+K(mRfd!*xggLR81X%}?O96N}>H zHIyr6zlcm<6_EO}!2XmRsB^Y4cVJ1yd=EQ9dECd%dCkNDph4ezvxvfoQZ=wUT2tp9dq^T23tZn} zz}7g!7p10K81vPKxJQo5x1g*CweK2{&SQXL$ zfEFF}Kq5hDP@DFo075_DuXqZ=B77x>y+Q^0;?jkf4H2SuAXikDbcXM?`|DWcemF^Q z{g~a+g*6xN90PTy_PZN`OJC8Y9d=@JKtpv(Q;6Z%FJo#Nr>VajS`Cz-?uQA_(^iZmsndsy8M@bhE7xyU^lByJQ?4S`?>Vj5lq} zS0XG%AQnU!q$yz@iMH8}l}ZCw-CJ%x^R|&a^t{l~5rdsBYeR1qoC~itvBa~!9352)x zo&Yh}GC4@4*0*gdQ1P2vZ%D%py8}b5vYpJ^DaleENgVJ;N#11Xt`!)gxr~sa$rZQt zl*tMe9Z6zLljEkVz&(^1iB(Od7k=B%_{qwf#QumfG_}VoYiTpBfCNEHzRd3SZ~BP$ zFORS4v+h?1LGV}RnXGnYQK12;aY;LaybG7ZKnQU%aBZ{sKPW$;RzMqMlbx41cW$-gm^>L6JMmLI1UMAtq(`f5YG|) zP~k4>t&_&0;&g@b$hQV{)C*$#d!P_M!*6Zxrxw{L3TeNF);y6qhp=Pb8 z)qRaDw=yH$1!%oSA#T?tqom=`*Rhy_BVST#15yW92(caY-U8RYNIzb`ulWN|S*Ji; z-q^SL)5m$}IQy{*^uVdi0@hV{c|*90?(eS4+S*q3-Ky`(Ph=(J9LW*SXhXQqrxWSV zx7(hRlb0Hl-Ytx@Gv5H&^)61f%TbMdom=Q0nc9Kx3Ix&xj}mf zM|QaF1moy3Mw~`|Fnfhf2_;!_;LMD0E8@NH&GA#Kn=i z^JvIr&F2*0ElK%{^Jz>&N)g;E6PcE(nm09*$G9^Ryy!wvr`y`A$}YX`K!ZKkbHXwn z-=ry`&_Q?AWsVrW;>@?2k>T*zWA(tVCx~myu?|EoLp8kV7j6e~9s{M3KQY@WyvX;@ z7%M1G(Mm^Z_~HzRoKf#D*}H*ia8wF<%xHdvk3WvV=|~aWpO^)&a#os}%~IJpKx(|z zBqWNF^6S=oKBfdow)>;+crG(;-1SvFo<$gm;DI)8;iKB%W<02iPf1@M%+Df`S0_n^ zeCEp*q$EDiqOh(Kgdo%4)h|@-4lg&KY4jNW+c~nx=v0^=ig$UTl5$B4?0%9{yqX(* zI>F(~(U2o%3UA}&phk9O_uomT5k5udm1O6-Cmp9!=Md^s1k)jVR!<6+JYMnsO@hN} z59G+hx%>41g8c?-&g$$Wo2E{E?ez}aGtHW&`T8r|^Lcx_{7?A|B{KfkU4S8unVFFj zV6ttlUKqdoDZ8nW{pRz};UI4FR=g^JoI?F`)2QjaFtE$WHVh5_EKD#fFU^Lcckvs) zl^QaIJr=&L`vl@gJGSrDXEfh?(K?M(6ek@?dY?KTz!)bp4|Bb2C4`al{UNpO$zh+A zzUA-s$rHP%_3e>$Ij6Rzb$3NQ86E;)t8xu8!{PVOm>UXHb{#x!U&Dftottt}Ct?VC z6*+VfGXkS~b`S0jE!EIid5FPwTIh^?d28TFvJW3D)P}UGcs&<3@Ts0Rqx4wuoAc9W z08}f8(e3RQGYSmmaGY{2-B2&gKjXHPuT@O@8lJ;zMsUr0-b4=Axco8wQ}f#Q3vLH~ ziN)X)OMoGM_FZ+?ySpQIU%#-WTa`406DD%N=YR{+-1iV$vPHdylYDelc=$1nyirKR z-M!i$J4sxk*uiJ!))<2vu$P$C{eyS5Z!+;x90AfPtn=T8h4F?~lsUU{yLzat@3HC& zl%Qw95H{!698mDnQdl$WLZ(pP`5jsPqh?nBq{=mM{@Fa!9i;dx-b!Wi#j}NW<}e(6&Ho!|?gnUl1xRnEP6>4^*h%_uUL{pV8f=RWxVN*)o(;^DxTfGnb{K)7E8jbo{OF zy_11?Bnf~fq(Zot)%DLJpSA6E!qKJM#g zkWxfc>a9*z=7|ON=uIb1w)Nh^2e%4`-iOC9k|%LD-`TW7rVV7{@Xnp7?@+Ul;;Mc2 zihH8i6bo6GoGd~w%?@wAW)sCV#a z5F@Y~ucC3iudj<&9=GbNs z6J0(53=*Ur=yhWt;%Si9_TuE0mb;rUz!<%&5Gk%|9W+r)#?lmJZ5;W+W#_&;(ad-4 z_d|ofj(-4mP)cj>s4`DO-TgdIlUtg!h-M+6@LTgAdAz|gea!H}IUuQFiA^|3QhFfF zSK*@Fb0A4z4_cv#+mckNNpRTJ!1E8EHLfYGN4ki+w z3j+XVf;=_wjXZ^cypBDyfe|`n{nOYKr0T1k_Z#^;Fy^9j0>jduFVjlg+8LHyMyyrET&Icm64Y5c z2^q8g(pH{cQ|JFh?EHo2Qm{;qOfmEiX5?k_*Oi53c?y$Qq{}@VP}~3twqhhD*iy^g zPi+vWpNZ^r5RxRv&q-6pJxE8HS~sI72CovB8(!}AWC_dvzUacZ7fthFI4z#6Ky8ML z43`%rxO?$`1##px61v!k12R8et>d$RW{tQCIUH`t8ZBM?Kh5YSZOD+d=8J_09$tpg zJbCD3cy((SZv}U+-mvqR5(@dMyf$!sb;)?>;qX21J^D2V6QaMo>6vAC!I+Ty7XvX? z)of<5;%mKK(SRRX*scwXaW)cn<3VDa=3$=N|7S*<>i?e65pbyTaFeL~XyJid+4n~C z@elFLS{ua?p~!q`#drJ=^qL+Wl+>MnCibXUvp;Z1On^R-+mV8AR|cfGj(!63T+(k& z5gCP_FGy7Upt#C_BEmPXIrd4RMKZQ)uM5dxw^!35^#ApPuI*8d zQ}r8LC9@$+K;S+0O>3u*;z1mPwz&evL(vzt5Es&GH$g;<+~xT=BgRSxPFW0xqaZh% z{JKn4)D2oZ>YX>j9!QDyYF_w0NygMlbhfeWr`0G@K6_Izu#jm3j$n(OI|Ip58A!Ku zws~vRNh4Z`@u`^)Qc1Nlhk>%>dUuRBD?o%g>TZFWp1O%N-Of)YG7p~JFb6qAtxpFU zDWcF{Cv|_PrLaobSFMOL#$IicXA8?G#Pj0F39-BE z`y4>g$nkr>k?=OL{&Q;mif7XnqH2^iy>=CtG>;R>y*>_+*sCYVQ!`-+eez#{BHsd>En4g`; z86~ncn3_PZ!I*Y`O(FUg;hAi9+1g7c@A%0w6T;(yE>U~T3`O_abCP(A%`e>_LQdhv8ysgqTISTY zoJoS~tA=3AM{pE{so&Oxo;w=xpN^~c2k%H2F>khsPqlmYg#y_CPf#2@Kp(4K?2IDh}jqlyqdju?{9{6|I#2w40qva81aYiEOq@OyU-cX z(8j>0_{+Q^j&KyI;v_KZP?be{f#%B>#U4$X3K^h6#y|Ox&bg9Kd>OpjU>AM-`qxUd z{?8$r+{I`ae>9bs(TxE$8Q3>U7vZg%)gm*W_>x_hS_9bq4L^Ph7`J85{fUM9D_bx^n{ zU?uCi|72y5m0$R%hm@TIWVb7<}xD(qedL_cB`r-jJgWM&zGkuEG zNa|gWXnxDx!@N3eDy7N{tW6xzXj4p;ATF_{o*}a#>p8y>JeG!PhZiuv&jazmh3ly6 zUIU z(3iin{Mj-OYK)H?gv@EbALNLeKB)R;Ywhu$6ma7fUbuY}W7rCB)g^P6oDUn5K7P_a zm)_RMu7_N2>?RhE*mWTA;_$#(1f)iohP^^UVh|XheN8D5iy=9>p!=f|4V==Md8?&O z8VSqBJL60Btp8+{6ajNWkIc1+AV8(hvPNs?9Ziz@qe(r$Z5S&t#g&Lcx6taB*Gvjw+_`9qtAUyD&!4{;c;g=GV`Bsk+X zd)-HS23UY}TW46k_U97}aUV3fHETb*nFt|f3D-G_?;){csU1%sxf;Kyl0&jiWCCHf zHjizXES*YqxT1Rx1V}v|D$EE5EI<$%v1FCy8-KG$b63GrnIY#XnkX|j9&{d=4Nw?O zh)JrJLvFiU*es!nz5vZBi3+GdJLIHg;GtO@fcaW9SeELHuh58WVi- z@^=3DhX7h#{|>B0_+KO%nz@8UxA2s{|2wrH>B8&q@+`E@u_e{hevkE}C$Wc(RQ+=M zfjWA6qsx1|Su2sL<>;pS;G0ZoL0qxxx$)^K*G)&)S8RW{J|oWA1YenTk0qos zfYE&>VLh&EsSEPlw?lYT9j&>Uyz|t5I$sZy`L6&+Rpyu00 zPYQZA|AUU+@bBv{x#>0gs7L$GEJ)wjk&3|xUzfZ;H7=Spd;P^Me7flEcTq;C74gi9 z8@qSiP0D4>Xcj?6qQPF{CYhk(cjvLTcO8gXqt}w1NfRqB{q#@SO=9F~x4e3pyYP;6 z{icq@`>QVG&|{RZ(XPD}Np}U0^l#KXZ?b48v^!>qgDz?sZNjnFrucvVHB_$8!S`qy zyZoMW0q@CeuqnkgjM3kd%_&zBMWmD)(&yleijL1mS@0I0N*e%{{(@8cS(cs6Jni9#BS=tvda=J+M3oqD?NbQY$lSL-NgzcZXG3r{tI^w({*EPuJO3 zK5u4t8FSG%xB+lSA7-k!N3fzZ8qo*u{@iFUcg#wL?TxDP$N?az_|PwncqL=B;Ixd$ zf-Nn;I~UeQdwL^tl?*~vU&b5NkekWKxIKu*4RNn-_DDCv6$W} zy3v%yHPI9xM14&S;Sl;NL)wxv=-lA5m5Z@+unL+EkzmTV8#f*m6wclWl#s1(-Q zJ<0UeR#oUR=*nP3(Gk59?DDbE)2HcjuW< zQrcBPz z4wF(*oT580YwwL2$R?i;@3?ktJlBg7(U=_Kw4IKFv^5A?m$RXh zM&iG5n+O9;K>IFGj?$u4A_;yjKmelvG+od`M35+9a>Ku3+o^&Y2e#{8h^h&Xi2iJKWzu2t0;`8I2YvyC~&Qk)jHH}A`zd?vV44`CSSczf&nd<70)O$5yZ9H1u| zcbNRl+O(J% z)%pXH0g~n9z#M}380XQ;_iHmU(Ej3xxn)A@B!VDm;}|SG$%#L8X{P>nakqC11ATB& zQ;B(u;(~hUzh%HlrFyaJLi9blw?da%=4ZY!y%-s03@hL8Kw3s zqi7=_6KZ$g7r!NP>mNzA-(edKOp`J{yuGYQQw8~7N8bxLa(wlw%BJ-t=5I1*m#wlG ze$+U?x==2NySD_Y!9>gE0#&7wl`f_lpR$BtHPLv*_#!|r+!ff<%E*wiWN^z}jqB3c z&tY8oPv_(M_CLgn|M@%E~+Lg_ICgQ)M?# zW=AugqON1=57i7b&}Jm1aZP_ktp62yJU<+tlr&jua2axC^JG4*z0MD?%)LczqkFU= zq7SxuGyElLcexK$O@mcK;)z%@Ie7`8^gz&Lj&1h#TL>xGBi&lc!c{Ca+5zIl0x#8{ z+nB1C>YRgXCIHT>{o~W>I0&l9lcm@mal_1q64AVOkL_9!GXyfnGj_V-S#cU_M&2YE zHY&+|%lVVX$^E7KX^4FC@+lmR@GzuCM9STk_}GTr)q1CHd-)^}EOUMbF&YtStSa~f z5@8A2xcWUu>xy7}vvorhv{1l3bGPt*xRL@r_KHf=MsCSFtQ6Erxu1>fjJ84sNC;=_ z;zyU|80S6#@Gf;jG!rR(Sh!)FF%^k&uu`$UA_^~Vj=Gw?LhFF8C@6>l5fRsY^T5B2 z+{3&ww+%E;woSiE((=|8YK2n>4SXzQ$*Si#ox%>}2Qbcf@zJ?dB%BM~)a|CDGJ zUECDK8r(t5BXYIFJD+`goe&N3Axt4PedA9si5nkUuU*fr14HNWgp6~K*$ zVuFERLABqz6Y<0|<3>Wv-0h@e?b`SJFI74)Ax}L1QL?Y9hHcr*5Rm9;5#u%X@k`r* zGESuHjO3jC5R*tBbwvBXxMs=mQKsZc8)RLxzNa13!YTf}qSeoM+tL22AzDi2LWa>C z$J0BI#!kk5t<^_Fgm9RUl<9s=kSaYvWd`9L-4>6jhNusZV^9D_xz-yV$R4sgvG)FA zE5@?+5Gd~646y*z&y?bT0MN9qvF6e@PRIxq8&Q@q;r^N_&uz+oCAgSy{mgfGdWOMG zCoL@LL68oE(}4OgU>_cI%pV}q(<7@@f*4a4P_x^9Gg>4}g}N|ScCTOVTR`f4U@cLJ ziZ|9`g4Jx1-MUg2I{gkD-clDaKrf0?`x58h@3Gua-(NWi*}PObBV!Ol`Ht zeqn(kFqpS$Lluk~>xPXEzgsj5yENn3mvg(pBFyr;0Po@NV*&c@xh>-;;~es6rn zN&rQ?VZZVv1u*}q?3u^5=Jy$m3g9I&vpFDL*YI=$v+cf78(3yWZI34v0!jPxY4o+pQ^_kC&Z0-0!p3bV3*@WvqW%SsS+!WgPzTwM{=NGqF{+l)9PXMh!-qM$S?T()lA%;$CTQ~Cf z>>F<36w&};V|TRWmfP|X&spFdY@(_;@|8etCQE+rSM0?Dy04$Kw|SkpVdL|bAhq1z zX**n`*W0=0gZbLI>TBOcWtm&mF=;VN%FMP5z5P*%9p z{D(B;sVElc+-LtXCo*LOOyw%^{RIh$liP04ys$xa_;y2aZ5Uf>B!!6S?;Ap`@x)>> zkGj$~!A9&)RME>WVSM;O->Th+?;Dr3mSvJLwhJ!hH-43(X=`$=ZQ@_HjsW9Qe$%7A zXwDU)iI!Eo1ytE&oRVZ8|t6- z|3}j4T^St6S*y7tKD5hzpluIr=H!nz^x1UPJnitE_0xOqbkRc2A9=F*iu;vk8g8cz z$GDld@a^%Nlf1|Brwpre|GX4QS*wc&=zN2`q`Ii_tbuOR?^)OKksgXSGQyL zw7>nCF+A*CZS*?yj^Ee^v}%W%F!-NNWaE{eo@ut%*MxO2Fvb4j$oG9a4R$oJo%m{$ zr6K$v+TZk5p25lepm#A!TsPhMI+vGR8*koS{Nw3+=ax>(nZE3vXrJTL6r-3ePYoJJ zihb+?ic}eLa}S)U^{dcBXYm195;yzf!vRql2ErVb%4YC<3=?T?R1@%5w46;#QEg%MAD%%FFE+^jt@Y;Azw(F9&y z{yr>4U*^j&?PtseApn7{e?fW&x(GY7(6bV_{C&}mged>nOR%YlnpLj zJ9s}=)sZ{>Yg7BNni9`KdX5_k92%B;~xu4;jDfznAI1>b7u-|g45|eGi z$Q%dN@UJKHT41}tf`8{yRbrz8y1!}>utjx8k6ST)o^3Q6_<2C1>h3zh<{FBh(Xm9) zm%$k3e28(2{KcH5;F^~1uGjaiFWlXfpSww?+2*ZI(&sDFo)Z1>#$|_I9yraT3>J5z z@5(-Cq$OE)Ev9;=4*P;l{ciY7o;*J`mtsMxITgrlyee7tL@Zcy?^5w#n^$td=UM-3 z96~QKX5xCDO5Yv7;g$A+t>d{HduFzy{`y|G-uL0!4% zG+q68Y|oHMrcY-la_anz?!Syi_w{}Ho3d@ghFtcSca#g+!eZ97-9~Rw^ZN~Pg~Hd@ zzME{SxcNYtmGd#|^!-=vh4ghUSK|NNlWgh%EHL&%N~yVU7q(b z=0;rO9?Iy;)^E}Z7(n{gUZunuZM(_25zW74H8dUMQQLr_hxK`2K8zsAEr=^0Qg@nk zb~FpDF$pJ?j+OIQJS~)d<2r*@;O5M;NNKcGKhdX`Pw6|t3cf-5U)rokt4J@~K3p(A zbjNe@p>LU^A0}?Fmd0MG#`(JPmQ9E+8fH}db7?X&dg=CcSy%dX5EiXL8!(@U{C1(c zfdz3aI>|?5s;0FRFuYhc)>36HzS3PBU=$v9%wXN`?6)(&8r3+`Cw)Iyp-7#+gGPm` zhvNuXmAFkWR`V6}|r2#KWpwz9Q&s zi#figrM1H6SS$E>r!KocW)$33mk5Qv1AMG%U^ufO$_BTzQm<92Jc>TIWi(TfCbIue zr=gH#^<10cUdd}IrvBzgLL|({4h2QTXR z!@?5qOgC8t=$qDS|KN%wNyB_sTFZIC*f*Vze21&B9rot<+O zpd>{aOR+`L;aIbp`;aTnrnw?p-|FKAtqJ_hf}lTs_|$79+jAc!$%>#z_z(1o3Tipm zLcNkBa2Z8s0T|;9UJn17)s%S$8Aup>+5_z5tBU;AFOA$jVPN$6Y{xi4X=?GU;fSJB zkY_QQMBRxRIhHhaF6|Ej!umzm!_uraWizZp&ULr3R}GsC)~5nQp1oH;1z!h4Q_Wh+ zwSvb9VXC3~O%!a=Brfk%{0;|q-`)3HTmTFb6Wit5e;l22u-o3gT$toX9_Goz|A%Jwd4B(cuip6HjOA_jh&qn7U z;=rhMAz~UriVH7p7_cen7^CDrX(rKDquaboJ>kjc@nj764mPPrP0Jx1*R?6JeTjnn zEOMT458h}ptRkA#&k$n^Gpaelc67-f)+II$-QlG*UCt@GPn_&2{5upQ7xB~j;ZJ&? z9+jJUt-^#^hnlD5j_t3b`qyvH0X#S!lfu|G3W{dw3s>7QcO=lO&LjC&%NWD~mPB{$ zp5~JTI0}7aQ~M1m-I9d|Y z!;$Q#Z}3!>-Mq|coN{!y8~h&9dKcpp zcFNWvW^02dvCAv?sRdHw`c$96wRJ#y&LV!-!Coo zh(#EhSs>M{N5dw8FPDjWX@S$?B2&hMwh`1f4BU9J)1h&DDz$Gnj5(-4Dy3BuA{2H7@`s+t)Bpy#f8mpy~Rxt&<@Y-b>nOSm1ofj zDNm$$Q7Pa3^bJTCn&&pkm|EYTA8emrA%SfY^x05Mgn(sl2xu+VT+k#TcFBEt)`QOE zF74~j`_{c)4H-FdYleDJ)_pPHk(J@dnOzN{0-Qs}9MrAfGJhe~+G*JgO*g?cPD$pP%K;{%STx4NdBS?KIi4uhFd2h-T(AAUvmBdeHW#AqH0ea_ zV%Sa!KWtI4p6p$zZX&==G^W$S*3`ui@ZhAAH0bQ;&tp4E4mO*&hwxiLsDn1?9^D}1 zcWv!Y`p`?I$s51E&fPGOJ9U06*p>New%Bn-`%6LG@jpGScjktx+W6ex-P(f&ocqq| z7e<#Z!YpkvJI5ZUmfzcg^Um_lTS#j0AX;Iwa^`h^#w*WP@4(uNF=%2i`da#d_L!MF zLZ?-4K8l;ngaOw!=}*}G{)X~+VDm(WLqQr$^a>NF+e2XoXU2An zdMZXLQa{GyGiYAYQ&oQEGdJ)xqjyF;%_(`BDUUba89ywI7a9rH?`Jd~9`g4}5|}a& zJ${&(Q*q<1$t>hvx-Hk3pVcviqGnQKK6()M$Is~ zSwwBty|@xB6SwXMUC7(sn#V|HT>=f~T8L8HN3# zCELa8&oIA4KOJDBu736k8hA+qSPT|Ly4gd`fJod)H>P1Z0Sxa5zdJ2nynohN*_fbcBAA84=zeXt@mKT!Lo zWI5p+Yo#EnwR`(Z=_dE|qeg#qW-C)(qvA=$?eE3$A9B9umRCM$h*V&#B?$>njTsa} zX}{s+I@Ir{rZayGXznD!w6UO3(_EKG9xuXst5?ULS$EG}pPfZ>d`-6yoLgE&3p z$j+q>zsLRJ;2&#?6C?>+I1%&+Ha8^t03hJWxY~1lP=t%bG!J{&BOn4dwr1ii2xk2L zz8jwskAekSe(~8>a6Lo?xF?B~xfdS>WzDqA&wV?nE{emWtGais7n!@7=OfWa>z7vE zezDOcr0y~K*DAbxN2MS^Bd+O2f0%_$3A)!t^;z7Rm+)SQ{C+4YsnV@CSoUU$NMl@M z!2_&nvg9#&>)%^9{y&b+J)Y_BkK_7wQ7-AGlGwLM<(k`&T)Meb?nZ7&?w3udxo^6l z2qDDE{m$GOhE;MMkvlVU+mzbeV%BEg-|_p`qX+A=?VR`J^?E(wrS03P?*x#~?rOUqMzxdBL9!Nv!=w1t`KYd&7zQmeMsD{$GS21CN3=VhA0R zIjLDikULqW<`xY9fkosvFaXy;ZdZsWvJMJS|I_GftOQ`i)Rx$9<=>8n&=Wtf4F z>d2iRDG^F7=k4Dxt!5+ z{8KqFm!C`m-s&Vo(~n&aGFGW6nhgvRvo!w}e9#M*4q@(=EC82bB~m8+8TJ?hD;4{U z1F_3fNw1iKSs_uZcz!1kCe~XD5_obx=#_%60sgvqN|)g}c=6GF(qICr>F3(-vi+jd z*74<$o)WKr*B>4;y@`li!jVy-z} zpf8Qpa%EI@F*J(aJRiE6nKwW1hAX=I*tcOhl?$p?;z5)2bK394bk17uMYHvSUUbgo ztj51M&rsi>ihk45ofR5uQm=Q60{LAHJzE1O9B*hS3cdyRX&YIeoxS6I>MNv9yfsu{ ztXU^{?w3g8Ay;ly5eOzD3jh30eEerK4TvNwqQ&kR8G3wdJ&gYfK2c9E%YpgKwea~I z&t}E*HtEQ;y)~V!AnqDf9}7NH7e8}((_K~>7-*h~&voy`L!!^Mc>CW5Ok1Z>C<7%9 zxG8z5=0FWO318<;sXP~#FNGAfhJ`VF@Q_tZjbi<#yZeG;LZ;MOecAo~z^!oYN7r!; zj#9EAenj-A*A?e4of++AHIaLIzA-i>b5d`+$uRc(@VFc44*wA(h8)pQYlK$|Txz%_ zjc{Ge3>_KsrCq+LX(u7FXew|HjriZbu6F!a$DusVqqUXDNXqlD{myeT(1>?gR!=kkKGL7LzsUFEhlTd0 zZ-?SCGBx0C;j~Zkih%PqBy*rOJaks!C~3R>^AxH8E*YR7_)n9|?+MXofBs!O5_0Be z`|uLnzO!!HDtgJJJ?nJ{GcwGH_c`jEz2Sd6hu~wZj_G#(%PXR4Zl^z;-usLsygYEI z!9?yQX86MbZoD)-#b zZhE`6H;d&)`CYBfTm9>E@6L&#;7Cx?)USq<;|HyCZQ~)4Ro$X$%>Ug<6};sD=>@S!f|t3;2dkK)fJfP zD{az@WP6U{}z&jj^FWj{cg2_44Pe5H6;8yqN!b&r)yw;)(}5J%(U6V_W7D>cRi z34iGu$_UP-Jt9N|ciBR+E47hjy~_mI_^09U=+wyAz+#{~kz0L;IF56d@8AaZ2uN-4phA=#90W{*rpGu{bp3-et3fTW_9hfk-t?nR8T zN{mH|ID8rOjc{^b9nVTitWXOjB$>D&%Ekv5BfLjr^(5@DR)HsVE9$iYRzJK$&Vg z)GO_IgSSC}00E02urFlV7Ni^R^0D?5PcUv8R*5vhY!YS)aM!O`$+d!*^n0%(K}Nt! zpGmG1*?{+|(@!-4_uUN$%^rA3yoMMXFg<`5JaXVa9-ElB_fO@_{Y9nTm#jCE@PWwE zJ>?`9b8V}lo7~D&t}LhiOs8eBZ;ID#mJ65`C}i6|xYl`byTry^TZnkiz6>s7l6*`V z{C5AJkEzZg(cSF~LSJ37qNng385ucgCu(!WR9RCRcfY>cjry~cma}vKE^7so z@eX5$a=^=`UwkhLI&vF^`Nn?sZuk+oP>Jr7kOtSX)B}bhe1IB6`g^v@#GB7Z4hdLv z;F^93i5$mmx|)aU68CRjq+=_y_~JXniXzC)1WRY{#qwwX#%+6775D9HDTjjmkk{wC zW&5naNmy^(cST{NI1ySJS4yCVPbF{v#B!^3SwKSFuiL%wXnJP{yIx5y9!TGSf?OT& zO*CAul?PfGFdWsh@{y-zs~%kBN~|*q=^G;HyG4R{fd_Y;Q?@>I^WP~dlD^=@9^97* zX7f0}Mk`$HE8_mOH56@Rp<@|;!GjM5QEb_s6ITE6SikY>w_Xnf_;cH$+e&aa5yC80 ztk1WCfCwKRa%XoDnwbWEd+CrfQhOaVFIHO|5(Z$P%6gi>LLR)HXNL`;6$5P)@``cN zY)v!?5-8$DUdA*5>|JsX z8OQxg;#l(C&_4~Q+O4QwO#Oe@3bMdWvF9xqMuRVV#^m(ZoiT^HV^D2p2MV*Fhd#}= z4i#EC8t9heeAVfQB}OsM{0xFCK(=zX3)J}Pgce3MvE+r@Zh7yz*g?t zl!UJmc*w547-}J~ildlomT%e-3wRnEsQLA!Y+W7jHb0S3iCyFg67oB@$*dg?yl6KK zzpVf+Fweaq?wT=Wp0DoOivUHyz1do!8rdMbBAVdf9rtu`ZdwB}mk80vGxk1rc7FTa z7VPs8U6E$6T0OFbY6M;cGVPw))+cH3^5MtXWN$4svSD=_obWV=Z0w!9_tH~0iERgD zeXx1W#E)mS0_j%vJ0MSH@s%N@k09s1)A&A6YHUgyjy1xKgKRn2uKKdE_0T(8>)Wi~ z&y0F|iTEE@xl<+UalQ58dGn&d3tjJ;5O&+PCG8~`8?}plSdQG!n}LJhl;B|_NfM-|ySw)^obDWv|#^A+gH@|%rN7PhEI+9j|J-WS=CP5V~T4kb2u* zO`&?7Yh+)`3Pb_d`OJeum_?Q~5E$wPI3$(@hx(UN{tC+6OGfOumbHcc^1g~-WmLx9 z)Uu{h17Ww)?|dCgyUWK?mS6O326opHKWfF?nVRABrq3XE#!Ey}wojjPpw3k==_bBR zRbi&E2rQ@ZcLh2%+Gy1LkI%<1Y9hg?r}!o!S+vBh(ar4=kiNl=LwB%ob-W6WfM({g!$; zS4|GVwb5kerj-9xgHsaf5|6K0=dWXdo$IGW{QBsEZ%VbTMQm*Iq0Z&5#TCx+tS#Ia z0ElD}#4Fm4hTW)d9)8m5#Z||Sy7aeYDQkZ+b$M}i;(_&>jTwS%#rLDBv&gl9=&=i9Et-4WV2=`1oMoXASL^~S=Vov^v+-zLG)LuB zyXES|*9cb=u^=N!T%+Af&p7 zoIY(|0CYoAgMdD@DBJNr9tQ<&cP3zA)S0!{ao=a)g|Y%7MtXN9ewnm|@0xWDAAlOQwBNNV;06aR*)mUV;I0+(z)#*?$3 zN^VsuZb!1MgWNwGs+g)|U_YHE2_0p8Q^c2m)BZ)q_)acB+jA60u=j@S=(UYaujIOt zq%zghbM<_UwtWIGUHzjY!zDJuvpy>vvYif!>RkHzKw2Z5`AwVX)$w}zACTXXSp*qt zEhi`xsE67T{64?>+N-qq`q%d`z3s#`1K|m2D&hS3 zwwLn!=ufrwaUC;10EWElKx=X5iP4g>vkDou-GAtITM-R|PU~SZb97BZShrotf(=4T z3FK4!%Ghu`&AB<+;`DgP%QkZKSKtQZ65;w_IL|+|Zh$wvaaCYG2d=p%W){Sw-pilK zzM=4sU^^rsBxdWc=d*RL+d?Gw-BPW66qy;a=XUeFNpo4<+OLF=zDFHCBsFD~P<>SA z$1OkQu-b;-Ay12HgE`@&+^4peXzc4EGG}&XLSh2{`MRc-wvOxnbweLVbrZW9V&V3d zR9O)c@Xhl^`ca$c`H=6Aj~Phx^m3Yt6OT&TKwpY4y)eI9pSE3{;X0D@@0OV2%=^PZ zL-uv(uR2$MqV{sEF>`KBTXysPIm=36OB!s^Ka@Y}i$ay-ZyOq?v<_*7U#^|%32f4~ zzp^BOJyJX;?-64;Y~@~p8lu$ggCH7KX>oo6!+kfWt2A!3!frn4`NgtM+Fpj#dFprw zoNIh}?2X=)(2_0H7bRiWGRA(o*S-~jz2Gs1LcC@Or>3~C8ki@m3OcVfIR+B{-CSsW zdZ#9X<|f|XF?n|7i;y_(^~qm%o2Q3usfn+s7CKK8iht{ydRHDbge&zUR?ZGqJ$WLj zbVXyI_}8cXZb3IcrJ{}=9xScz`*cWBf~HNmGjn6_m93vKOGAG}uyaTJUXZ@(Kx$!Oh#cVX{QLKyuH3+QnQN6anAmk_M*2X*#vhe;P~Rl8Rt}2^Q$Lh zx<6mUK1REQhKvCH2&faZdva9A+0ZmW7c@*E2B}uo@n?Qw5h-Y*>_OCwdww? zeD|08s0qB0`^NhT$8=_^2!hw-u&Pnf-q@h`UD9O^`H#lFk3`%(ho1T1ep<1@Z~W|d zAI`B>FteoCFmyiL*=p?oHaM**bAB$J8Zc6O?0!~Bx$iMl_tld{kGhP!F&b4NZJPsw zR_x>235uSW zfrP*K^2|%CKWGKEqr%KqWiMq?VJl^g_qW!X>J#*lyQ zhKwi(24!}2J~&-BszQ9fqC&oNA#=(_NA_71I4*ykS*@K;pDmSsm!*0+OyLj8W7Gcw z@z<5bk^%z;!P3#@IUU5A)F|s`r3EsJpP?+#EuiDq+o6pKHnat2mYwdCh_kWwR#oM? z%@Lwk5Jf%W)Hxi`#&uY%gGlt!ONe2d&Nh==q?fDnez2OsN&qLn7e)%n0ZcsUIS^Ze z#I%NWaK%POlf7L)8*#T$<#kqb9nTKQIt$~CzIx^w6mWBCg{6@o5t7WY^V|VJeB3&o ziOGfrlvhYqT+>vKnX)@lG>}>H9T4>BBm&smWHe?p%6?9-2H^-^ro7aE z4KO`VzZi;}v1M4X?5L!>bu6zyV8^=L`|HNZUm#iZP2VI5&(6(v!24e&K!5L$M?^|g zG&M2o5t)M|KLB1Ykn|!1g58d>PYQrW74u4cy+{Lkst9_a%t<#8EWO?Oa|k-AGg%1y zDN5LVakojGqpoPoQz<%7eeSZF5psBl{1l93trMKKZCm=UKq)Dn0>DJj3KL>;nx6yM zQ<0lf-31z_$_VTcQk6jRE^HKbTv>$}3H(A9OUxktCfnR8Z6Hxz7^#@~bhH7s8^I@n z4#MK7MSA!^9uji6M%dpfnP7VE{yo20We_bN>$kLm7QX5!)Vp8Nd3_wbU(H10fBD-H z5YXtvtykF5y!=Gd;)tMO6wj%yuOZ=JJeS0+4g&TZi9Ns=NeTnwSw)=E;6HFNFr6@V zmG0AtiVy1tUQ#T#GGT`=LgX9GnWKWuQq`X!->u_J+Ug|`9Y8WYNLNkPc0RhUYzbel z_Pt#a2>-<_g~Hq(11uv@;_qp3j$|3hK*txhJ?5OJ$_&M6ac$vbWc}Xw`B@o79aTX( zkVtw;OcMu~Xj|BuCt4y+e+R8i7eHasub&F7Tr-mho8;$6f&J!NV8H+-D_2E8CtBwV zAyg%%7drr`$iTZ-c3=?{Nh-0YjX`I@6Ay*=bu^TPjr}QXVv4bGM zF?%nOd%*~g+Prz5ju3&Nu_jW^j?4h=sBWpvNX@R?xy@sbon`<&0I+Sngx|=fyG{X> z&C!IF z^iuFfBp8M>p9}&a(_!eD>?HLO#*{W)8!FwO;szp-t)?c(1h{@<85AUwZSolGP6kHp zhu!+#WOGUZK<-^NE=yUAAgAd!J;$Bno;mQogOv|H$+yzU15BW6LrdeBDJ54yqBM9+ zpZ&PY$rGz-kmYX(z38EOMr2$Rh6tU>du_2Z}o>%El_2Wo^YpwSP(at)p`qqbEm;vxl)CD(XkiWT-o&kNh0#6vw%B&r!*Zy z?IOc~D_ED*PTXCc|y?bU#3Cc8J1H_5< ziQETke*FE;aukgFPWp8Wm>vy%AmxG7l;y#5ur^oj@_#&6h3^_rItMmPztgVOfQ^+L zH#lFwDcwMTKz3w&uhf-DwEO0=p#~NNguoLPsDb*FfO>Q+jno|TQTOkgQpv=UMRViw4WMAf+hBSC4@ z0^nif)ihd}LC8*ZWHYwWveFNF23k9anv0ho;kEM9KEJHxxF>CY8LQ z;6H;MX`&rmZ<3q{LIg{YKP(Y5Oytuet-Q(xt6*@9^?0ty?iN zd#kJdl=zc}fsJ6R#Fd2W$DGx^iEm3{O#~!1w0oDl1Ji-+|<% zf$<&RSxy~eVJ*vF(OjB?@}syjh@i{Ij?^Ra zqC_(cbB@VdgQ)?@_+FVmK~CoKeP$T88H3YBO7PdCm_#mJ<}!sDXiB+k>#axz1Botg z*J?Sa+WW24jQBKQ)hwi8Tof@|N&X85WjxBfo6cN8{y>j4m zWe0lulF;vsdGxjvg>IC`F}3!+n^xj+G1e*jXZzo(Bqqk1)TBdk2Jvv^l|HjQ@?rFk{^Jrv^RI+ z!MSbs1<{V^cINnvelm$^wQ((?Lw;ch`px)?^7i=ehP0>R)p;cHO%)4-<1C!yea`{n zuG#KpbSB>0OteVOpijaTOm|7(Jdp>B#&)R8n+c;1V;~XeHvf+|5}qRPm;PQ^0q1PzYxrqWqfo06x!O(#O2NbYF8C|Ve*;ps5i;nRLsb=<-M4Kc zi&?kS>32DD8{y092q?Ya!Ktiy?xtjiw_v0l%@@QeK)w)ug9n|q4P3V(crcxd81~h5 zh@wL-7pPk;fk=!3pc-qVE9Ps0@Jq}O?S>0(OTf1$T7i!AY^ennMiIT)yI>4;`^&f> zMIIe{BJQ+9AIcWi)f))Ub=#S*1TKMGJ!K9s^HW(siI&SCb1XZi%K`owvy*|C!>2HF zKl}BSV`C6^zzBPQBe%00nEq?SY@rbh7 zv%t#3YvJBAyEZV|k~2KFn7EGHEV^^+%_N%$_GWS#h38@~_IATE(wUejcKx$8p^k>O zGecIIWxrw%$-kbIyd&_;dVeotzrLx`b@p^XH|xvFyxQyX%)h>Z+j*8PtBh3(Yp-TptX3TJRvqoLs)bC`XtvE_$Bm zDEbzCPR)Ji;g9Q`Mim>%(XjpQs~7Ejk8X#%a=)hT z5B-tYSGaJ_+OMZG@XBJ9q`>~p{ZG7|d0+iGy(y*3|z*SmAcIiamDXhHaolfw%dx$aM;!A>@p=O;mgE53Z@k=+z&`S=aWv=f1Z*&8xta{k#$k#a&+rDAS8TJX-#$lKpUT?)^Upza1*A zn^akrOTR-?HSO@jHyF9`a~zb)L+$d8NN?2&__sKT_Pwrxjcz+_7E_58VASa0Z2vJ}d7YUTy@ z8u6TcPo2E9jLjLn3+iT{wNoA$*lOqk$fUU!b|lH5LKr*F&fip-%(Hs6#K0ZMYngVk z4{Ox;`C$Z^lNAL2>X%T|diS@^m8fs(Tl5E~ibCp{Su-!EsvCrCy}Cgz{LHoaV!Jrk zbrNG!$Nu~I2yHL_-bq-O_^9A!?`^4ZSBIIRN>=}#vA)DB7NFI;ns|!(tEc#w>IC11 z%YTGry(1lq?(kqdTqJnbW@;+1F2f8fj~aEI8=5iSt@q7_b$*mYc}$tu7E`h_ni2wi z2_OV6y4U!ozvbUE#Z1#5#p7znNbMrjNetvcy~3+M>MOD|+&jZXd--w2COz?&R~C zYV<#zBjsUwf?42U(?! z%ZXphZ;PGbpyvjDRTa~`{Wv=0?EQeG2Iwx%Awo>gb+z8cU5!#SZC5xHanxVL z5+FG!vS)J~Q&W+U%OqwA@~HF+=6wVxZON||-;`Don>@iCpMb8l=$!zBB#=F|nsNI} z1Hd?9ojeDlw~=(v9^9H75SCwPBDCTeSk-mXt5T`#{?CD7ZSUY02*9QRKiI^Ne=5kX z=Q5TBK3fN%>rGgJmvustuGP>%l3O*Gj8n+h3WAQ7fmD&(+R!1@b+Q&T9VVOKUK1sZv4HYFs3 z&avL`bKW?tyN*jAMt6`3QU<^ZlB>sizrau!$R% zwma7X6=hG7?oCsklrr*@C6YOgWbPR~cp0$3Zh0OP#XUv=cod{B8_q&UB_l`8QJY%M zU*CZ66xgkOQ=n7_bcX8OT0yclV;S8?+$^jO>oWsRlu@3cMpso)cW(g>(KyMdFP{U# z%QiHDUkn*>p!4_fJ9xWNMqcVH&`)`tyn^jo#qwz2koLo_ouf;aG@p6jyl}h#iXXfn+dxw{afoj0bVo=rug2XPZFAR`bB{7sB zND9u(d*8?Qy-0oF)&wd00IY=p$rVBW@%&I>=#ZVSD^9ynFe-+xMHA*6GZHN;epiye zfz4NjGHx#eyZ`B#iK!CYw%6^wL^B*>dN{1AH=rTKly0gMP0M~%^DYj_=>x$du5MPM zpvh-?g06KAbPv+6v7eGJG=TT0rWCi|>++!dZvd0&94nUG*&1~t{l~MMeV{x`dKau0 zI+mD2zM2f!X6WSi)(|xy;EbhtrU^2^3dQo{-+ktG$x66%yzfk|s%8!4($Yp=YQhp% z;pe@07f+yb#AT$R3JRO~1-wWRaFQL(ajmc}IzTYC-p-3rg5=WEkf3?=4#{sj%I|o@8geezTqpxHQP|Idx%XJ`CHw>veL= zyWjQU>&_?}y9-q;|GG0}D0u`2mK&^Jw|hdw~0tnOC?3`LNL-}!$8|*gbB&z;F~#M zM?xH!@nshC%%vNtCO>&Y_oI|;XHM#{)#i*QsSKSCrdI?Mm{h+|=phz%f>8cagagr>F^xCr$NwF%&|h3X6;jF7 z)IFloX)v*~r3VIBGxcY>8uTwW!K&BUF)20Em!>K|mex@&l@;@^?=15O2X;?#bue(% zyp0rNI^OH{LoC5phGY4I%Z97~8p+^4*cyhZs5e^Bu#q_hR#B=)Umgbx^HxtO#~Ej^ zVv0CayWxbay#m^J(|##(FKS0Cj|_TfkV0pMAmasqx9&i1k*wZO1tBEnj4qLxXhXnn znCU_uB3PhwXUmy(TYu|zXe#4xf%0)EPd(H4s&;mIM`_(ZqRpkuMsVa}T-fO4H^E^D zQvWT2+8W?Ru~nsB{`wc=y9)Z^ki551vta$&(SV_*`r`3$gK}%HkEBtLe*koPV09Rl zFaxG$G39_BB(v+`z$5>#vE~tu$^ikOy)tXU%_qX{hcCnQtOl4n;WAdgjVd%yh`P21 zb8qp*?21#_aC*}tb&BQ)=;6m2hngOY zbxa}Me3OAzvrGVQ6TzxL<8&8rp%o&1%2;aGU7`rJSUIs3ig^@jHv!Il@ zLJ%uY^$NY>wm>Va6$bM{M@~q@nIy3oJ6aJ#5OU%x@ z+4}L8N9@jGrzzr^yN<%%ed9o{wa;Ov@!y>sZISewbBhp zC6BCL2^7d+-?SQZT04;N)cHxw7Sl|{m@s3#4>C9o+(&eqS+X_v5GZi=AFN(ON69hH zt)j4xYYIm-p_;V&O&Xe4x?T)qf0G%`yI?NfYxn2c6ak-AX9sB*Kj@4RMUEUTCWF$j zT;YYz2_Fs!Q)lFF-h3@1Ovj5P*(VVPir z9Fk5gJL$^uv_*74E6IfnYpVkVl;Y85K`U{`H8u8Kj;c^vy&VL)jOinHuCyAha}jnc zrYXHY^m=Uo?cJNjS8W`HATva(KfUV<7`yKWcymyOahaAhv7u$7iN;V}t z+pv&7;bb!7C3&{t=)15+hyKnLpaJQL@=0O8+cX1f!iBons3mI2o>I^ZTw+Ch0g@u< zZT?HVNN_{6dFVmZ!bi=dZrs2-cl)*)FHm{8d-VpfH-TXQsGvr_evF(x9bhDlVvy_p z<6+Ea>_#wLc!*dG6i{>aXB3m7W(|;@Bg#-w|G|AmP}&Whs3=w- zWW~HrqH+z9pQJ1bBp15knryh|Rqz`2Z_3@&*U#86s&CXyjJFO8(++u~RJ_2R{2@cj zdZ9K1i4+$hH`aQ-MeK9e!P}2hgpN&Lmo%3)66l3}A5m)4JNWPF^*@#GwY4}3xNWET ziKvfo;fmz2NP2D@vI}v2PoC-3OWpqp@SNT=)E0ZOqX<&g`d8doJJw_>FR8XV{(hw# zYJfIDx#gT<^0$6TQb%1nTrn|ICMm%>dX^A3ZtPvmxTfY`c+g;fTpf#CC6IL7$ztQJ z;Wfd0>$`jPWtG}5D)wFJHQ`+?&l3KL)K*_DpVBV#drB?2?q(?@uWcfWtTsRW##v-w zsI{r{$879!e5_SX)Vz+;1wAm?BzFIeshq78u@AetX4dGa1ee}86nq4-yfy^elo)R0 z$h_E=S(E>Dqb=>rgMVE-d#J$&?R%af?YaQwl zq1$gItSQ{zMi<@n_NGox*19QNIX0G=9a0&FtT35x@egxdZQV+l=kLtuWbs{<#RzL1 z{3G#PsJMbsemgH~;?7bg=kQMcZ`7rmzFSf8Iyl2;d=dN0JM=979?;Nn#D+vp%bnes z3|*=Z%VA&T_B^<>3hAKVnP2}qVp$HXxbOhWoB_KJ9B0v;CMA8 zi)x^V^ZRiqKY-S)2KW8p30Yx~;wS&fnAIN-v>$GKeXI1q_w5fbxbxQ#bX47V%Sff% z6Oypz0~!q$bwZo5cu6PD_${mKH(BZG_}8rZqR$Q%pLC8$jbzyMTbPU%2Fq2*yLe`d z;QE~Qt!BH-3Ov>-3sD(a>g`+Z>2QEpayK1)4`eS(*Q!{S7i(ZV_bpoEh zYR^Q7UnY`K!JQw)Qe~uIktoNmr@_AAXV>h*GeZMyoID)8^D3o3rPSS7jb9w(UI=^zKh0Bcsl1 z488$pdH3je$nk=c=om_j9OMPF`}k<=xVk^rJ~cT-Heo}o!1#*6vieqq=0Y^*M8K`p zP}T$S>e{KISZvta@x7yR5q#U{SVCwLTr|8E?w(Y@wPSx1t zUZ+>qI+uw{A`+Rbx$iH3_T25~%g?*im?dP-u&Le|9(tKZMCG)loWP0u)F9>(B&ITI z9Nm)p`C{QjWt>21jLVs37`-%buJs)m0v-RoO2N%CD z+|TutBsz8;;N={A(&hIi#CqYkveMD1=7cDnW2y>K+Dg@9b(j*YZ@KF+y&oiFec#T; z4cWHLtI<_u>)~0OP2bZNie6&rPB<7DGT82lCOK|-9d-lO{>qt3@ts#XUTl-8tU1BV zf_2jJph9xsN&UWM4X4dt3F}&^>Rg|M=GG~Kc&C%JQ)#oRRq>9p(5uK0FRa#k`0Y4d zR>M$DO(jHn%l3g9)Q;-AWY7mgLNGM4eP_D_34fst^sUd#5u`@3es1WX1Ro`IWvGHY zU8}Y|g!qE^RMun}zI=bt6#zC$DRTVm2H%Y2#|f$6_!Ocb84Eg#IDO~ zA3#CNEMp;zjoo>vZQKrp+5r_7zk>^VVaC1aZ%rM@{#&1AMmSvDuz$wW2PNl#)21bn(4# zuiMFTz;H8ED_sc*d2VkjCW$g0guVnq%gti#^-D$lQa>h5`lK&dh(3DON!Bl6m1NrK zgZ|;bvW-sgKXD{bLkRP8Bvvf5{eEABT;VEg5&n)$DguMvP{nWy`V`x;9MI0u+Zj2X zP_VrBWq=ZQq0U#sj614NQ*+%NZHN%jpzr6qDVhAJiq-0g;q;eNo|b-1jEcL?vH=NL zf;Y-)Zu4^g7EbO>RU!l<872JUgiv2{e!?+BW<$~H;1K)=MNT~;v5VSpQ;o>?wel2yx*GXp3AoiC)+XGM>$Gn)WK`dU_66dR;qD*H`$t(cdS z2e?|dF%yl;s_zcp;eb3P4EiN#AXI9?u)RCWw^$}*7IJ4&oZa&}qJ8$F$aK2EuL24BwyEFU2deJIo2Y(MT}kn}URyp>p?v1aY0l}AX_H{ zYxu82{st^V$FT)ujMr<5BqIPS3SX*`<+ZVa;J%|x2p<5(ueGT+_u7C)n-KH*jDLev z`yv7~SCRQC1piXez)+e;6ENJr1)c;XiebHiJ|1fN&neP|3>@Z|k&I@b=!$L->6GbyX6;?c ztUzk#GLL@)x!nuLhKa%vWk95Tr)(X_7*3HLTlJHGHM|30!^HAvkIIHwW=8AlB$K{= zju8{+v8!BcL!ZnlcYgqC9$3k)OR9RE@)`gqcjsB)SjK}t|IAY4QR9Wuk-KMK z^(DcdfJtJUL=AL%FM_37=}+R=ZS^vb z6uSnv{nl=K!1s?mvPZt87@Gf`)r}wK+D5W4%hHFf6Xrn5BPb|nAM3ga7yAHt-SW<> z8ExNr->uTiPj2ut`p+?l)YtqGzsZnoaz-(ryvkafgO564t zZRWGvr+Ma{Fu9@44=e&OsISeubSL)JUytAo&9nq}Icj8=j*MRX+~MgDkoQlz$&UIG zXs{j@D`sFjMn5EWiu^UenaHn^Yn0){}kir6DCAxwKMet+c; zvzhyC!_KRx=3eujxXIIQBD2!-1dA0pTXK^$KW@>=cZpTY3M z^;qmCttTN_a9G=Q@4hR?rL}d{iHfs+j%AeEtS&jtt*CAN-0i%3LHP}%atj}!U~}QZ z>-0xrsJZ&B`JFnbyVfb!-fy`kbKvEO=MY9$395$ITrptUw;Y+~zp!F`HvUytRb|v- zIKcn(2m`1S``6fqzEc1;9QXc-4l=*&i73ZWPB7|$Rl3BHrp{&cr}mt>kQGSJ~-xW<%shevAdRr_M8J1h5|=H7p<-_+IjfmYjAa9-neqc3@9 z^Feq?%d3W2)J3eOT);^+X>NM4+fEOEqoPFNRa5Ik34Pk<4;yb#!eZruFS^LIS0A^+ zx*l#85Ra}K*sbR2x*Ddmd}(L8Pr%}!tM?pi64E~;nV1=`Pvj_vm4=(xMpC0DR-#T~ zycSc~rCL*kib{tjcm?i{ zsn2|udlO(`m$}!*#TFm3^DQAw(Ys>D`g^A7bm%V=SN^0#v{pAbwVrJy=iyB{E zG;$@wWxjG1xYODy+sTFf-q8Ft8$*#ec;23K_G@1%cu_3XpJv20b7p>%^#WI4%*Rb! ze3=Ori0(2aK|{;j&3v4nU|p8qb@uGEmF-)5@{2HT?xnwW%>K@mS}9Wo9r zHhPH9hb9hooo44G7=3%J_C)=B+lOs{Ar#m)AHT7x772H*UVXXIsUT%Vn+q&)b6YlC z?hBcHvR8Ocry3+PG;wq;l-bf40*v4IaSxeA0@;yYO$k?0K%~+Mr!Su3N7_RmANCbM|)yi7LWe? z5RhQ|#a#E#pF%u$4d;%09H1NWcNz5?mXMWMvAEW@T$RKML#Y}=XZ(f=AIP{$WSVIu zZ{6RiXfa_c1~rS4Ptx1EBxA;*aomcBI*H86$;wI0RuZVL=^Cp;;}5dTN`+n z>XVxnDu@4WR(=X9Bt2MQpWu#%jQ_4&(;GLhO(`5kh@B_Yx@kLnwONuFAKVmPShA5- z{L@O7mdip*g#;VJuZi8gdtYnZR|Q2yXaZzmG#jK2M$SSYo|NM)V(t~5{=umsFE2}P zBw^k`53PJY%iNLiY`YJ5(q5cY?B!uhk*XU`N59BiIp%}d@X<8nGzTn}1J~e?;7e`- zz3A4vcp8!)4|Wb=W5_1kEAjVa5_Y><(G4|L!x77)hfj-9`%WiW{| z1P$++gTY6Qbh2Mhbx3RG9`!x*b@!sikY4 zbOg2VX{yr(WUdfu=K)aww?jEaI)X%))j@tF1Slg|Xl;)@5CO1f(#r#>gIy&e@ifqS zmQ2&9M|fJKE2u1RGX`VO&68w93AhhXv61R)cR-Z!)V>A3vXm+9W!#ztK$WDph`tB) zIWiX}ON!*lbNY{GeE_s^g|aVbrW7^sze}mb>$Gz$Tk3)!D{^}!(C^@o&!9t6>nr`- z24JlJvI01k2@u9KFw-7*xq2>@8V;0Pbos?RS({)?FbBy#1!9j8#LggifX%|@iE28=a7-fqJ-{Z(i2icAsxG+ zde!rVK|gNA0`==5fZDj9D-F~)rdmU`=~BB1Xi9TXB|3S-Jn)A)sknMx@7qdh#50$N z6d*3!%(0_^$wyLHBcz?nRFT=dOv;x2*wR48g8ybnT2yj?IV&__dJ3$gsPHoIv(|gB z1vNl(UXu$-0F*EL*IEgD13Jfqp`(8qIoHST2Rr?JZ&S!;=G5G|dvC&7?SA;(Sxden zru6@i!B+jpIr%2(H9#cEBTY}Vq_eEYUTb?QGjCe<*IQF(>IH~QKPEcr#q|$m=uo(Z z^DZRDHe({a79Sv|x#Knr-23}`pL;OnzwZuUs_0MoLHNKaCPw9K^%AuRE?o?k54_$- zgHi7Ccu=1RD)&nh6EHieCAjcu@DFDSl_AQgm1auEimssBItd73ReA|Pqzv-#>?4=J z5&{IMclHCNb|{<&z)c&cx(V&gNw;PDIs)NEGEjO43cx(0h=wWf5uO2-8=eqNE8b4@ zf(@icIpXh>$MuGlWA&abDyF4;2`eAz=u2GM20@pLU$S=if89$=vG8J$xua*I-y)WF zS!c5NW)NLa(OV?yk2OPBfw{<@McIk_gF-17?tUZ3%@*9w=H0WzM%PBp0XfRZ8t79|4G%~U$Z1Y{#Oi;xtN77*!{7y|}OrDJq%jL{$+!ZsJ*-}U#mFXr}a z&vWlRpL5>ldq+vn5GU0Nv>M$kuZY3{vw50HcAWRWrn%_BddyCIys86ZSVmmb>!Qg| zI=T(R#kW0N{l^wf%sUU?@Bj>PkLd+(YBD+`+vF&SJ~o26o!Hp0MME`~s;kvkBn?5N zd=GJew1C&^bG(%#Vdp`n_-D-f$=G={F7qL^vY8|oMx!0o#0sRu1un0~0z1hDXq(6o z;2Iw*F;Lt(451QaH_!oI!;d&+Rmp{_|18$G;=1k0OrUWE86hgQC@tEeq5lju%)-~P zb|i2Vx}Puh3~XEf=5>hm{X}hJR}88`G~oZRen^`0K8wd~HE6Jn8_gy$2qY6Mcvhr} z1|uD+%cw}uJ!AuZ0!vUy4kcuflG?w$Ci8kH$pWZdPMnuxtK%J&YvBN8s7uOzjzJoG zl0KwnFcHCaB-i!)%pFT7wq%K}6&SX~LE>+sgBy1O2?pzA1%dVc8-zs}?nF@kBhsa? zKM;VONne#;35f(H$X!9g*=u(cIEU6O!{xa|&h8)z9G{+&e+CDxB(ijRa??wLE&b=y0M+3x~9u|9WidBkb9~KbEN;wPVUZPyiiW;5OpX z!k!Q~K`Kx<#43=P7XWZ`lgd-27N(CRnDQBW-#UM=D0?VV%NP)ExW!$I4oNy+nq`hW zM^9vwm?Ut41LV*+zg4ik<``H=rIw5G2;O@!l5wse_plFj)C9@BVWf~`ZwG9#gW1m} z)`%-0y6_KN z9uFLbY?x@iygb2^N=tZi5tv(25<5@$LT9p^+pg~zNdB;cEvv4Hk&EJOh9#tUC78Op z$#2`@wujwd9Or){U~%(o9*4rUIKbS_wup?%XsAvTmhB~I)*pyZjz>XL(#scF3;A}2 zc_}`_Kck1MS<42lQ+fl3ZHg)D!zg{`;i5KA@oN3xF zUPHOY&C?s@`j-} zBC$S|nHb2!vOhRRtJ7l}SB^8Efpa=8@CxMn##-`J zMnwAA!50|p@WxzyP54nGhvKc87jq{dUl1Y_$hNFEpYj_bvA>tSX1>k3WbJ+1zBwQh zOv0`Yi*;fl0SrtlyBqvOZm<;sh5DH4xf3PxX{^t(8`_G6m95A2;a(&6*VBVWG1E>v9sZ~xJQhh_qP z@MIU9q56LuBMw1;ZMGZzlucGS8GxYI6{(Crqji<)d56!5t|Dx9+F>tks;s)>LcRJHX z8}eeICE7(2X(Y8tM%5Wt*!Jk9_zJw_9Ui3@R<5JBwghH*gHfklBz$HvPA@eIVV^w? zYFxW?W;S2lE>X4fSXmUPOrl8vIMU&5i$Jx$^+20fIiV!D#cJ`;R#oBYg?4VGBV9{M zi!l$6#J?!lr=Ef#$AdN=#+{AMyl-1vGC#Vmx?Nilz0G$i;lf;q$+e|rJ{zr{2ZfJ{ zl$SN3X_BVz{>|TrZ91t<{(GrG&tdLy_uQpTU8*`xMAaRu{$!{w@sV4Z?^uUe17$CU zRm`+u1fhD6{xR=-)}UIr{#nmLU;j>{<2FSx$pVi2CT-#nq@b`a%8~YVeR@7#Dj8dC zGTf#Xwu+7q3NiX<{55+~1)aEyXC7FTJwfDg&lFP5$O3sCv$ck4O1R~@JE)u@%cdgB zZxZyj4wniQ0gmq%-$ma!J<=HRu33SYmW@2m1^2`%cUI5aiyS#9oP|{#ra8D2m&OLR zUguY7sBA*X|ADX8GVE5+2X{HGdND!|AJ)O8mIo{pKl1YZV4vq}Uk##{jz4?l=7Ku$ z>vnU=7-P02ows)LNaTMU)7SbOLRVoT5vj<_qk(QePZ!OG)<8k)eIj-?C^{TMxBpB~uQK10F4{!DUS!Ixog`iJtOm2&W3ytWZKnpViS0 z%?>qInLBRo<(r6_B;2n2g4z^OmYI5~sdwy0nK(uvM&rxKqK|lBBfEz9kbGypp}Y7j8&J*rDp`eaN{>Ef!tdwQ=`o5(!wgaqi)J? z9V$MT{r#bTDF$IZwKz6H^Y{E*A|gKc+3r=465}>|#Gkhf?B8scjK(H?y$#}f_a2jZ z9ELvI&2?rZ7%FkL-@Yig8RRvq#W)aqQM@TK4w_u)x^^&ZgvxcIx)gg_=Pc}#;=xn* zmye2If}%E^_6YE3f1jvtG`R6Frik-si3bd3Z(g!kWB8+|_icL);*(kf?hC9nsrXLb zMoC!Hh<9L__n364{a=c{6SVlpK2y;Nn04G(4gOy7|%iGBX8{f*?Jbt-c2)0X=SW&@ep4EVA*I>oIt~ ztIU-mg+rLy?OEs#&&dMX;FM`?j<1r>@8Si9;A@^ZyXS8<2uP!jSr7Lo^!jQ|p(i6| z)xrup%l>VVc({t2EyfLcV$5<$!8Mh4wR|lVf2EFXveO$A=u<|EUe{mKS*f+Rt2uVz z4;wQa$Pw-aJ$F4wIOwT%+vhMHMMk~T-RL%q50t;8Ub<|#%O}uEGkWrdfVqW-hfs*B zA@4r))D!Mm+cY&NT`!}k25!}F1AK+?`4lNfA0uW4LM^m6>=>(d~WXT{zW1E#~J!H?NR2{WAs*k z)2QCC((~izD%BEyy+s+&jsu1zEa2RqjL`n2O=;prwn?h;H!NJ=sBe*2$0fWbmyxI+ z1sjC~zNu#{VpZb_T}71|wev%Zh=3r8?=-V%0ZN3b$UCipk@F4lHhtQc+iuWfw{#N^PwtXhu)> zUyT~8Bc^v}eeccF?>1X$3@s(m;?yyX<;hYdQkiF3E(?YjL3>pbdB@4VjNHb*V4q>n zrfB}y8K?2KBt9XkH_;KiPdMc(%YQs%cc@M{;V*37&I+Csiy7Gj?o7*^VRVX0aj2@f ze}-u(YqS!~L)uwa#C7b^vy_3HZF)PsdQjxKsAru_d+`B@>+Ki+^2euk0pB9(5h_N& zJQPmo0f6FN*6Py-*!u^BC`cbA(8+)yTotxEgI^ysY5eCi zhku>_F6-x7Y_<^y=pPo1@C}rY*v2hi%V-ToX5u;^lE<$~ENPr8+g#&hj}mlh#20~> z!X?#LVaK3=gG8Bjl~yq~0lU|{Vjn1h2t zYOnZC#b8oORCy$ftiSWN`Ut@wi91CnPV zu&CGiG_G48L{V1gO5L~{^+t1s4Qin@tPu|$0Z7$5_fAAb#`Ja;Y!7JtjDN!x%Tpwb z&U=U}-NFXbW2pK2XcMIBEpS#F3IK8wmq3aFe8#Lr$?i}h1dPf!+#|N<6o@YhY*jZH z&?X~T=Tsn`ocUs+xNSqR>%OFzs5|ex1g_+&sv~#T1CLs*i}Ye5qT_pgS)OOYDfHC zmvL(NAdINr#Z-3b?j%)^JOQX~sCPZBq%I8$zv>M}pC4q-BJMD8jcdo7Br;MGySS?Q z&Q*Zj5sR3m0ICHkQp@V#K*WTuJuTYC+))sy0Y!lM*Is#2CqUS-Et!gkLqEH>a@hHTifkE-5Ct;8S2Hr3p(zeU=t4 zHT#dFJR883rzi082csNS*lY4u)C>T{inoQ~f!c8@kaUkRRBCO~Cf!{U6OS&rmFYa& zI-l2Gw1egbp18t!mxK;0g51P&URPA7@FbCV}j9ddO;*jMb?($iVUjSE2wawFv0kJ6ClA&#{M z{5V_svAbtf)W1vYP=KJPU9Si%{|?GVo`h)SdCgbnsxA-uk!r!`7}lF8xjG5L6Tv+T zbUgWMCck_T2?BPo>;6%Snvr_sRSeaoRsvFoWUYUc>8 zP`{BBzHVwmiIUlhRJMpu^>7}|Ke62eMvqQ3mx1S+2{;7yAJONl6UfP*kFOX|>|$Pi zjcFARHn{}S0+Ln5g%beZz%FdUC}^R*fEGwGKKq?eCN`h|Ry<^i_pKUoEn*E!G%=6> z>hs180pdpuHMQO^VQ5wMHpQZ z!-;F8Pz%59hY8q#FWbyb0Ue&8)kZb*4kYv0(p`lFST2mlE zUphVkJZXH3ZXy>}5-4P^`KYyO3IKeUgE5$&PxROTvImG=#C5|m>{6{3fj(QeDAQuI>NT^((=_;p^zs-Q0v7zWczg;o#_KB2kN2cg!C~N_@BJEJnHV zf0uvG7uh`vJ4c>z-u!0_34on@ALNXMI75>a6+y54+-*njVo!BU_rKu5Rw}ZU4aBhz zFnyEVjYdaPd!oLRilkh}eZ*O2hl&@M7OpTQHM{GLOktgPNe(W)C|{uL zWd>?{#v1BgBFDrBKccyEAQnvBvEbjY3f1+Gy8zN6PFG_}1u0=K3(NWRqAeyqA<27` zP0t^HCvkdPMM>kwiEa{B5m=4z3dh%g;a=BJ{8G%g@qtrbN zBFgVuMOiwM8&IzMH|U_}5Z$0YcHow2XFtx{0jLSFfR10#jrvX6{f}d}Z@+>p)%ALk z;-Nc1s_?o%Hwp!19mb4|+%wzBf_|2eCK#4cz_J`;6j(3pvh@p5YLUu5 zpfkBo)us~}SfVXwRWs3zk=kbsna+G!T!eK6AG%O+`Je%59lAag+sylk0zhffXC$~A z3@XBC41)0idm`aqL3}$feg||SL85|_J_HMaHtb05cb$<6P-I}FW+q}9ux>B1KsQ_$ z(13Z=UOKcxQ&OM(5fJ?;GLHt<6URmku*_po?LaER99hN99D9K^8-AsXz*lB?n#FVp zw6`C*82rq)=Z;-Tkhd5Lo;V7s#xv#XCNwq)#|bCGO=f)P_Ci1Z4iDr{%ZoY~ihFvh z-3C*C3WbQlPea|%oIarb$*5`clS)ZRD^KS8FEZC9Kb_HSx^RKqg8Dph^V5?u3A)(~ zwz)(KJ$8i6$>o;c2HDdKow4d$sZGmF_OPeV5%Saje(o1yO4BOVUm_FrILCoo!ih>ql_HgeWW;t)qiCi^1Er6l8X zJh*KTIlWy}Z*8pW4%3)Ns2!Y^fu>)%zbGS-MKop1#8#I)314n;N&9BvXr@2y2u%(u zsO1zx1`;0LGzH&Ks@R1h54vfJz5KI4tQsP#?x#EWDn%4VUYrGw4v;1y_D>C-8ll%P zx~tH~t^!fbG1k1jUXf92sbp$I9ma1Ia+nWkuI1@DP>4Z&Fu2qN1 zP;8svLvQ6*`%`pr7fGhl-K26VzJXd(NK7w)XZ{}LO~jtxt4>(5Pw>k={VV)Vg58e; zL!&?OSYGCN31gb_EZ4(d>_eNZJYq4Tl~|h1ulIOv^*!vs!AM!z17x?Iw%N8d^w!zE z7@)g8pD8gii_$Y3|Dx`8dfo8ouhzWk2k)XKR&UQ43PUMIzAdS^r3vW{KEep@Vx!l3dKJAbX@;DN_ zc^e&&m`qK;hqU#)sO)wKIy-L*U982Nh$26lL} zMz78r(c}Xzgl}eYcG*P-D-FjdF8ETKq@z&RXht&{L-n%xx^{lz7xbDfc!u`Gf4rlG zr?wKM!%)|0zk;lcDxy0VO+7`UxXKbDwK%>>-&nUFM zPA9}J+I$|R|Fu=tyzafBuPaeot~J`KnsQKKB;EPaYoYemlm6?gnmjwhJGyW^HQAA@ z1kj;FSI0XkKlg@v5I-mK$4|3b@>$FEEy0W0{?XA z{(S3K``7;I$2#_Smenfrerd}ISu(6gc?2v|Opiu;J%etQJ=j9!Q^5~ zFe*m9^x+Jiv+V@Tt-u9)TK1lObJoJasCr>e;hH~-JoGHaV-x`iolA(>m!p_A;a4**JefW9yvEL!S|JK>H}q2MYIbz{ojBTYF(%NgQ*G0P`%St64Y?Wf zaO-?k+58GIj!;-eI&UHHQu@M5P213y{rfoApgg_;d*P#v0$ur19~8$khf0VeGtyHj zGWW$b^Ez+;w)Jn)@Er8+i+8!djKa|3W~pxj`KHY=QC7{ScY@Lecrm7$Zbd(rKfb{U zNB-kn_&1(p)!^M(0<+wauau=Zn*#QPa$D*5AcuGsbGZNc_xz1XkX zJZ|!ESaS!WEgPn|Bl#&!gvZ+|V%syLYpx=3U0yjmr0^z#b7yX8D?NYLV!qi@Nm}^` zjWF^)C{v`sKDV}J^ViBK!t9&9s{EF4S)om`JYT7Wz4Gf9{w#@l+My|xBW;(^)fkeB znAi)x#T%aOLg&shgWZ{0w3x4e_u#&^QN>c|U3Kyn5Oqv{xP%V-zOlIEo}c|v5)yqZ9SvpS)n%h5otVU%hhsA|CjnE^~3rCFp-&QV?T$%FVJ0X z3Qi-R#jV~M)z4%1>*p?UXLorQt)v8o@vfF3M)ur|Uz(pNKhOvJJDTAeFE(t{lQQG> zmRDfzBW~aCPu?*e@x5cd@AL<+aNZ~s@H~+xxMS2sP9(ri53EqmVA5>OqWE4h6m+8w zeLHH`#xMu08W~-OD{tyJJkDrMZN=44S#Eu*vVliZr@?biQo2=*lw#dgEUs;5cNVo- zx()IFZnQnCcFlphEJ0xJXZKl#{^Ab%z7lng|J~(^8%8l?3E}r^KL!7u@|-L;538v) z8cul}VPuf11QmQz=d)r}QPDw7)}Q2w{hBuF>Ph-CYO;lEPRVOg6PR52`&pr!Y*W3! zxUv6sZ!X8)x}VCn+sFPz{-8+)fivD_jxtecv4fA;PsSLe*NcM2F#&VU{S|L& z77?oOo?>TyjhtDV$I3Rmx(QpKy?*dS9Vxmsb^Lesrv7{8x$a4cEdkfj=bB8NS4Q<& z{&H<|906x-3?kFRes)NQ&HgD7(?8`JOCo*hZa!pN+}5{`5X7_jaO!Z$RFIk8*7*{@ zT-xK-5tAhSg0A_Fn}Q!>W6~;=U)1MH6P1`(T}K)@`~Cn-a+!WrKCfa$Szsr#0L&_m zXXW@}jklo5p7}P`wok0%ZVXh#^j`hsZ6mk2eKS5tAI>Uiyi8M@xf<~tx7n;1<$o?` zm(+SWWHtK0p_L5pA-lVyX})GZN7Jv=McF+luRQ2Ct{tsb!131v&9&s^hWve8M8VJN zFaq?|^ylfGjQ?i!yKf#g-Er}?%*0%VH9NlF(2eU5Pp#bV01KNhTxCs5?pSTPbbpD@ z27L2d{pDj2lw0m*@B5NnjxmhyfZWxW4<=^cy!IyO6j_(F{31OX(Ce&i7O~g<>rMMR z+`#YfCP7}?JX&kw9=uek#m}eQD3zMl`ylOT+qA}Fi0O`A6qqTxOZ5y}$PGqgi3HTLy7# zz(7)ciVI?!oUlEq#F;Lt^>%j27rv;G!;mNB@-%MlQa7GoHvT|5c)FcP4x>V%d~DB| zXMa?w-i`cYaaR0aIo}cD!`u6^ghNy*1~y}X#2hY{uKB*5tqc4i%x2_2idJ*(oMP=>8_WbdNfnHn^Cr`f1eVOwy&qlAWb z$X(qrr&1NohJYC6*`2+f)MoFpCN+VsJ?J?XiM=3&1*b*BD9yjsDtB89;+5#5tjrzX z`um>;TLu&C-r8=DctZagvdp^wR9JWB^1B@fM@G=D{Krv^A6!?haIonFsB>oHX9csj zI5Qezpqlp^YdL({BKbSXY8?}JZ0{|0l5Xa)9ECE{vo0)Tt>J0A+M;%Rr0^qMp5le$qI1+y5nTt@z?U3V9Kp7?42 zrU6DUn5U)O%8gWz;pUFkt$>l(YuEqdFvc_F)u~7!5@M+SuCJO5hC`6mPc{7p%F08C zAiy#3SfOB|W5-ZC=5qy;;s;m{f~o`HDA4f4K}JCl2K))#s@|+&P*m{b>`Tdiet~^e z<<@xMMEIJbf74?cpx69N>33v3TwfGP1QKeIPoKnh1pX@DV#-Y-?LBM=TKWAuOli={ zf+W2Cd?BK9Qx$B8T~oUK?L3w>V8L4SWS5hG2JH4At7Zgx3k7!#-B4t5dJTPYs0M`% zPdh}g-S{8F$(EG++jeDJ@|W{%#>lk*bkykW0jv+?0)E+@TZLg3y8=veHkDdvLI+v} zFf*-9sQuyjYcv8$L~Jw|Ye^HTB!JT4(zraZrl!hg5iAl|^lQx$-d(c#D-Izk5!MY3 zoPHZSQWV_dPDLykyvM!*T(Unn2>)of?#=!AlM+%2u_m!SAjOB}p2?>FE9hx#gbgii zHXxW3xg5fbL)hJ9JAeG^P&kA7)2Xh1XGUgpyipFc3}} zK>?rkAvIrau#_|ws_lliA-B*t!(H|WOHy^{=$5!Zhs$RDj*gS3LXzdEzLrItB-e*DJ)3NbgXL4bFwgj&fo zIWyZ01=53`^FBZNCdEHC(H)KS5lBULDvF?a2hw)5#VGao=AmPIhhmeYS^;JaK9ipd zy+vc6C$kAE+2r0yq$cj>V_|Ve z;Di(o-Ji)HY)E*VwlrZIBn8&4nvtkza`v>|#te|iI6%!Gg4Jot+Af`g5%e6*7uumX zT^CjNG*TnrAv`>41E#}`1#8@0X{qRl4MVFUxoCanAy@74IVORcFPm=$-%Tdff<{K1 zuJdTeQ;ICG91(Q3fyW5|FdVElfbf8M;UE#)UOeGWx4?&dx?o}P7Tm3dTJx#<@I*Rb zdzeY=2w!jhbiHvy2tQ6QRFXR2iDe%!^n2&AHOiJ0N#6oj>d|HI_0vFpq9jRS^kce}YXHgD0@3S|FN(wfm z`+?6!!dSe6vG+DCAJ(0F!Dog9MnXHUL+!fUnhI2?eb{>?y z{KM;zpf4G?x^RsyjV7AaMi8p%smSu)dyjS^0|mpk7{KUBK*O!0_-AV?RDyEMI5(|s z3-s3Vj=|DFKlYl=<>LNXB*CDN?%sx2DB$ISFih^9-@YS#sL)UPZtrdct*q~aC6UR?lT4%>9h{Oq{qzSB9 z@+nGbPG-IIh}tolU)>Ko(XHd2r-g#!b+;J<*v?wcogm6y!R@gF8L9Im7BM)N2-GIE zZt=0!jlBY%z;(?|g2vR9h9c{tgLM3dg48EoH`!MhL+MtQgm^f+GhTJa2{FRnRef5w zEbw^S3U+yYq76Bjhvq#OiT6eON63G-Q8`tqFw)5)io{8#m0)3~K#t24x>q0|UP}Vc zm zW|6gHD$l8uRcUb$ErRAT4taQ$4Vo1>lpH0PR*613HL{A}#a|EdQg4izYtKIjK9{u)P|6*z(4Fop%Y zgHag$Ch2~z2N75xhwop@`5yb7Ud~3}(Ezm~aUL6qUKN9U!^xWDf{*GSs@CkV2=Tjs zdxPH;kM}BK4}e$JSg8U3sZLU0gSH633mGQRD^!=kz{z{Sw~;t%>UP!9f;T2Zf-W3_ z&1z1?fADq1EnSzf*aFlFX{zh_p4F7&X#nV(3dXQLj!&a9s0FErbw)8p6vpn^*voff zP$Z4DW6xfjsE6gx*-#Y7ICMzynueOZj25CJc1N1(lJi{Qp{S#L>l(;dN#5|)%aEov zxY#ewD<}SbGQrbm0<1#H^F#u!8??F3vm|0@4L))x9ti=U8jG|NT4Ju2c_f1zIcMFI z_z8TItSn87TgTrp9$2xWwk&zhyCugTqsf3lad`zGhTjt{ z3e+fX`1_ZyHNrFkdp{* zSR+_b-UhJ8;L~e*Z9mweHStviR$YVHF5zKG=@&h|iU_Cek6Uv4qd8snYYoCa8y2YJ z>2#vk?j-HTOqh6x($xh~505WXc0;3`GdCMs13%Gam#&TMl`mTDsve_lY+df1GK+!B ztt{;x!?beW*ekN{lP_Aol=Up==-tx$We2y+TGdVkYBZS7Wa#$uES%1dr&>Rwb_nj9 zhDN&zCeC+PtyG^-!z7%0`TvES+Nd*OQ}X{@_=RYX1YRM+hrhz2V@glKt9?B(Zef& z@0#kmOSu!lemmhLg)F%v;Z&;W86!n2-&ECq53MpL3JuD{yJy{ac1-!O;B3y*A+)`l zfPIjT4z8xWF6`K)N1*Rha87Wq?b*>1ZXqT*(LC`NVaC~X*1CVrIAM9x!LcsvB~l9M zbl~o&Eq@-~nb~vq(b<@Kf2ZaMmXpz@%b-tcM3mv=(fe42T{1#!;)K)f+2}iF1or7o z`1@66fcq%%po}@aQ%H9r)96U4Z2R6_v+sfGtV-tD*)aaeNu4Ogj))G^hWA-F+rF){ zeP%3Unz@gS*;IjN+w9E=5ll5g>5uZSn6{Mp0zExlsk}$7ni{=2;A?+NQ*7eR;B?CX_~58wwf4@l^T_?QdMPruj&tPq_+7>wiXyK?g)q7 z;fAs)>d&#pJIuSdZ4Wt?d@;#=n`|8x4>?#WJCyD#I4amM9-y=S%3Dd@NXL#)f4x|H zrUf&&QJU=-ak^#UmV?C75%{kn8g-h`_Fjs5i+r$o)gwE|g-8u9YZRmrbyXKTtO%-4 z^SEjuH5dP$?g?6%#Qetr(cHrQB0}E%VO>>stTTp7_1yFrFkp&lawMz_zWZXLF2^E& zsB@VNYaxWDU!SL5&OOPqGjhidPhK+5-P$Sl;OW|bb_t#;}~U8SYX zaPyCmh)~<3?y%3Irq%tD^&$uOuD#x`@1>z@uj$aP;<;kUzBBlzOYMxFTtGxb7Z<2E zG!M*$|2S*0`Du2c%qzTZSXdXf9-5PW&VNy?PXFkP^eyARL2ifnI4}$gyG_Hyl6aXvB{y*vs1DJ@k@^u42wKWbeJ+(_#i9Mzw!XqhuN1X&K@6ztc#cXU&@-kX3l>}wxVSAelEq66ZM zeaUPA6d8<91JUBRc5DU+!T3^w%cTBXAA0!NcB``O_C4pS9Pm?ef1P z-ZjE$dBjSR)PEdFH>XD5qlOg>Y052@yb*HaDZPf($xl1Z!t4`d>lFS*3ZvrJ>jXE> zCmHk}h%d`P!=%q;+d?pyi4$?Q^w(#5c=XlsnJXjH%b%iEkGcOr#dvr1xD-5_C%a~( zsL}x1#N7=-O#R8p)%=k}E7FPNWH<;s>H2Z@+MlcWd_VsjJWkc6NSqyhi7VQqOeMDI z+D*Zmg%q1pgxbb8imk5JJqC{blK@J}^Ow$$LJg@xSOsi>wqh3j2aigTgIy6GnjwK7Q}d8Wo|E&f7aF^(ixqEsEZDpp4f3R)4(C zHIh_A51jqPmtc7DY5-BMYNlIVK|!enR$T0jKUvZLN(%BZZ%59$78r_t+<` zIuZpqw@dEG@2I|@1pGUgc%zo40L^+|hM$)iOf;3J1{!b17#7=*jy2G|{M{Oe7b|@S z-NEJ5#;r5K{w+2UDX}9Rg!hj_PF`gnNa08!{{j{4T_L87stoWcPr4YvCmg_J1Q?b0 zG-Om^H6)gc0LTL^I2u;TDy&MNG1$qsN*>KF+SC3>y6Y7>l0QJPyUAnN)vf?qH+1$I z>A4tb9N#;u%NAn`0SDG7tP?~%&{J}SKNAsagnPfE&Dl%Rcv>u?&2vIkC_+JfSXv_k&x8cV$5-Re?nq?j&jxFbat)F|djZ}4VJ=f-#9 zwD_>hHpZ`%t{t?0f{Q|7Fdf)$vIRcdGf9OBuXj%aZabB*^RIsHOSk`VH>pWJFtGOc zXD64xVftH&2s=mnQ~VeU|gdW;L7thgsL(E z)%lz`ddWDPtOc5}L6zGLTqoG3u9U~H`5CbUR8{Grf)TB0Ma*~l!lxaXV|9zo2oP?DK#JSi-?n+>Q{pM0^ zGB^jB(5*IeV%(E|RS$pD;1mOaq%BEl&Nk5UU3S07M~Ip|0ZJja^2Z-kdVn`bF2!TUC5Jj)G~)m(Gyp+bE!i8&`x^Nc_INU5IK$l77x}N0Ei>%kN?^6WntU}=9^ zC&f=Kq?nF+=3Yk5PIZGxP*E$A91ps=T7gY5C0UH`vpBN=+!7hG+{p^-WY)6lW(}L? z>prY_=|(D&u#HjY&tL|u4@FSTLg>Fmnq{QBFsZcseFVq5X$3oqTT;Xi&*@1CXm*3H z2n^tgsgthW;u?i{fSa<9o8k_MPo$wg%+kDCX4LKFKtee{rNZ2FJNmMzxxEmG}(5pb0OK zuQHNODjLVa2EcCjy}k5o}Yxo@pFByCJV1Yx`pTIEX4uXFCu9 zf`ZL28k?M|YzAi@j{iOZNhuUknMhmK|75=d-4&oEWB@OS!D&_a1(a*IPFXRGByksE`5+rwnT*(lHW=xOt*fpR zgOlnO=jr(H_r)CB9u90COD~NE;I~|P;xJ!{f&{Vu9S%^EZk52@OvfvL-( zx_)`Bl98S!TPqE^Jy*3RUHIPNTc0j`*}c(?CEzNL%diETDg*HiGjVKbDE*r<;bz z`h(VOM-m48!PW8km+;c95C<^ja1AMTZo3g4v7^`xOwfYs&zWleNwqG#kS4=*f%5HY zm*$=aFispRMUMx0h+G%d;!EDf+`>=kR_A}p&C4V%>k8-y{}zFDg8RtYx(q(eNjC&X zfN5Po>c-tSnBc?rQe6}wd*~_oOCt0k~@Z5g1(#>m&nW-P%_PVY@Qhj+GTh17i=c}57teqNyC}>+);ag z|A!fprz0G|Z0RI%hAp#%z!Ig2SDc@xpRxeAVVUN|9rPqs+DO4O_8ZUN%u1!J8URo~kgiq1w|hvJCPCy7XPyw_CF zdd+N!lP~F~ez9eX?CIKbEjLZ3zBtA1mT(I$o$)nmlX3q0wmseUYIz-SscFZk`RP+X zZ*~m{`yD*%Z6qyE@+<8e)#9|fA^^#2Km}`LJMdg<;M*RE&}}I(pvN&@u{%bgC+aml zXSftd>?>xUD(`%=>lEGnu?CgtPGU;z$<83(OV;a8cewi~d**8Zfz$iTx}pDKuI6@G zH-*@?hlraBjTTs~P#O6Ul zLyHP0wA}hIl_{CQ$FuRv&JR_&~_sw-bs>-<8wyS#E4H~FWZ)7^y8^JTR{ zC;9aA<-5Xvwbm=~^@lds$u3wy@}azHZfVj+1CBK|jzYIJ&xN0VdhxREkEoS)wQC}g zUh08eTcLZ@0jXD%a!rrM%V~OZv1aY&f}S5)Rw8};^h(n$uF(jgQt8rlDKMPOh5^H& z>ToSXMt8MQfwCvSSP@Kj-|av=2RULUuClr>aupCU4XY zOqB4ljsQW%;Ks?&1yS@(|I@!)f|Rz}9u0!=V@7b%mPnIApJs_m|NAYmXnp9S9Jx>1i=3DCRm;MK$(RXrkew!jR_mB3( zeG2^b81loYME>kIH?z~)+by?liv|sb*TQ5n$yGO(-O_V-`22*<6)8#ID#%+Hs;KT~ zUaRMBH*oU!cBxixZ|N30$kpy8A2x_g-oIB^l3Op+&ng!=*9q!}W00mT%xfHio}3R#n?ejes@%S4m(pWAG5k&5K-2px(6RyuX20Tm zQ}rur;&h%~@q4ft9>7Mok1B4)SwfG~h^;gBpWMWfO_#5cxJCWw)qCXM=@P#;UZ>b+ zocWWgqR^}V?rHzC$og`<%mlLEtoVUb=5vdriP2B&LAA=Z{8E`G!$>( zgF*ILrUs?~H#j$R!#($mwnxQl#z#a@_Oohzy>v{EC2hrW$Q@QSG9;Z-g%SO^@AGQJ zg!Dbvob}YZjO0&`9C{X>>H44BV2W& zi(UM7`<_tz8vM$xMtE80fBYhQVsW4je%!ezz=gl+vc?Na3-$s_T*bS|%fi-uJ4I#U ztH&-`FB0av?$w$7ZB5Y!1bk)19y9YY*(PZca*9GX54oC8yw|@@67V`V3(^!3*NCe( zUI$JTsA4K&Wbj73s+u0b87Cy`6Sk9iUv=(#>Tjk#O?!gmdb9n#)h(r=5+-iGfH94B zw+~k0FteJDD69UR&+x=}1KOc?KWIu&CKf(Su!E(WZ!wqrMX%n`Jp|Grn za6g>vw&E=7%^31(iSJBWM~rQ4K~=-!#YYX%%RLqsQ^Yze(z5v@O?ga%bLy5|LR)H- zGt6iK(@(TR;-6F?o#vwu{)$aw#?tGW^R~R3WqbHUty?78+X=F?zRF>NEuodAm;+4r zO?3F$86B8oulGrVRJXh#pRzNh{I4eS_b!FKuS?-azY#gG5Q#D=cbf`(@E=DZw6p4u z{^_N^VXU5In+$^oZPd+Ul(aCr11S1U-&efsEUrUt9AUM2hIjXQVGK&?+bh<{!s zJT9LxylAGS{ypCLen9ueU7amN@6U9hxV29=kOtgo`kS+O+R5GN3MMD*1H+nD$*|Jx zTd3?eroXhID8_meq<_UqrsDz6H|W?Vyd2%Ez;@F^`gXWZ8MNmRZCY2u;-Ch`Dw z-a7<&_pOG%T}fc<7G-Z4*}>Y zD=0P(;pe;j{fn`~<{nUcUD^F=m3k4IyiLn%TLKS;nfE_)=UCqBZn~QB<;-CfYpIuR z+gk6k$ z%jHwpIbaVs4`r>~V`ul;htwRP;lE`$Bk(M`s?$^#8|kow}rpa;~Bj zNyt%-CApI1nER;YZiH+RTP2h;@37vj}N5{M)*;^C%TEDFi z$G^7M4=l$&@iDsBs2@%r6|Wz%W!W1ong(3*jdcD`paaL?O(_OOYvlWysDL^h_Eie#c|4Ju_Zr4u9NHSYd-OfZX@;qCRnsjr_1nix=wiDi{aBRD?D2AmKn!W8t(I z%5}|5^)�oP1T@26#ZJgsBoqfJEcdRYbw)#iw7KC$W5Pio6XjnzBbn2M&vxvqY|B z^KyuQw+9k!!l^L(vQM709lWKdZvFrzdW+m--g4u)5dRn0PSZ=OXmN?nR7&w>Dw4*| z1hUoj^ER`DnDX%>Z+N8aw8Az?kfC~E);H|vE5a{AhEVCSwqcm?GU6!yszK_`S39h*Bl zX8rIYc_jC)d)QES{oMvO5-q&trJVX}UC}~0c}X@i8)2(in0)_VHI6NB%0;9>8!ZCX zuJz^s>zV%doA_htPbXl?YkyTZL+XwTP?ak0H>KupcvPmMjx88a=^Oxix;Uik;Gfx; zk@}xNa9OS&lb4nLXgw842gaAZ6|V@*fWhJLAcUPjZ81%F!uEQ}aF@Z6-=C5tYGszsI?4 z8na~!M5?6Jn_N(KFz+{`-ZTu029e3b@=Q`9{+4f)x0rb!zSSprUcT3;_n!}BJ@py9 za)hz-TgSqUNzSO`(=0zk>LSSPwRQk|ikHpWxcBs^#`!cEHk)K&3JP8JQJ06*X6*P3 z@^Ab?>5c5xAV73j&`0dPkFV#B?of_Ip|{eCm|H0LsK`)wJ`U1c7ZRJ1D|Tb(5>(|A z1JZG;8Rl_IsSmr)ZymQUS6kt{JG=hd*>1YmW|T7^u7W1Wv-WmE6+pcB0Q25|uN78e z*y?x@1XihP+mC2Y+JavB7PDmKcf6^vatXvJ`w1Iq1w%X{HahaM1bn(2)bE3DZG`3# zpUo==IW;y2aR5K7wU6#Y2LECn`TbtSAJf%|%|L|h(Lzd9+_FF5GXrOX`Mu{&v&{diB{@Y;VYGCjb?(6zbl`UfNb zSr2wu4bw3(o1w9)K`Hr^K{}-lhKtt5_j@&VC8C(-v!IQ3AhwY(Rq8z0i&=xSQ?qhw zcfG#Gu8AiRVqSbO6X#Y+fM}@&J36q84U8TKmy#aXcxa)3L(u{*?dZ9{Zr$*@vk*Pt zpIXlaak~)Lu0f%tQ25aA(~HC*x6^0!xfjd@rzQC!OMo)^iJ(3PNxjFli|YO&y{oyV zdHQSb0|Q9N0|;{C{lTD3*A<=WM2`_Q!Dj1Vc*0E2SIO~V4d7-&frJIHTVEh~%TKiC> z>F~VYGEmi9^lwP)a%5WiO*>wOq^@HTV{azh(yu(^E#;ou+<^I1Vw!G)QC;pGtOn*A z5#R3h-SL!ySLo=v&z9P}^TZ`jDp^bBc z!dgsUMVw;hiI_(mKqY3fgw$jX|0f_yA1Pp>ao6mU9BK1RG$MEqYz*oWu+`gMSXiNQ zj}hBy3n?x?D;Le@6tdIFk^EJel3)F(eu`>1c+@?Ing3K+P3P~UtNhNxML)Y|>;4!9 z(zs+EW9Hh4ll6{rjig`BY|mBKf-9@8`=Iy3cBn47?ETo3Dz4t};tCAiwC88gPxD=~C#J*D536@o`fiS$!WtWmpUsSnvpJaA-v~q@I5yag=KY7jx|Zs4w0%HBxjv zk@2lh?3Y-p4Yc#xPU=PQYg)*Z*+sKujKmSKkAS}@GX3!d{ctL0sVM955wl_giA+0d zD^%~O}P1a6q-VMBy z^2~I{voDEAxxSW^O%d0o&G0-nlqHv)&~`O;%8HDV%WyCOj8LN}%#RpN{@t*C)_ucA zMm3w&r+E2j4>EMFJ7Pmfo#xiz;kCWG|5zSnV+VAY(xNoGm~bJ?>^(b{AM2x7qxa`n7fn16YA6r!bBX4uE|V708^?yyYeO)-!= zX4QVvmmmrWU&4LgxVNeO4d>XPi1lcR%L-qTH6L#5fphzH=^uAo5<5qsED+SVRK8LYru#1i(X6_o!X-jh*I?2G*S zEX1|QL;qpB`_zeuUT%xmTPwZ(GFyupb!MXxneIHkys=8MWU0;*bu7O(e+{BJlQjO~ zONE6c4!%6h4z8U16P(;>(7`1Rbaq+W>Xc5|lTE_%@uGP>{OX|e)1d%4!Db*JwY^yGVU7nnBx z2^icFv=nJ|OT0Ig_?(K<_@XqqriuBZV^KVmf3Tv&#l!I)KKc5Od$j|4{NTjZyv?-FFE5fBA`Abr^!lRS86WuEpRfn|~8r&nxR;cD*mLrY1&bRR{tTQX)Gs8IUSr?7} z1YVZhiSy(@Z`?b*n6Q7lbua_HkG3H^<)?FS?**>#Y>r%q4d!!0nsQJ`qVt!#kk5Ic z>n%_-$Jo?$yKXVgz){rqKTL}bNHSTarS+}Rt`m$S)#}Z!n~mnAY`Ywyr?8lt>y{0E zrqjlbYlC{rnx&XI>v>%}x$1jX%`bl4XJ2RgzWB^zR_inc=%?liD?Z4);YNEMwOq4g zn|RCiWLMbLMs2Xo5bnwNu>vh-DW!c^Qa)%U%iqW*p4P*B9Lh^4*1Y@l9Hl4%#A z&MDc^*Wm@pt5Pq~v^J55jXu$}+f>r6LRoIC`7d;Tjsx9hcwo&K(wvD1qK?PlAW_T9 zMX)T7%%0K+ z9)kx+y-TByx}w*??ge8TrnG;OVzQu=E?=I1UGp-C!1eL^k2%)w|bTyE>> ztzL~U;o%h~#nEpqFZyf9DFCOm4hV& zkE(v){+J#4`@L}YD9vs=Jt_34HIJChxIX6m?4wS|@U775HkLCYq;EnTO? zj)sLlO>{_?sCptIc8=h#^SU57aL><>vi&nQ;gN%H5IC}qPC3)xhmvC;8#G$dyWDB7 zx|No9EKwp1gZmj$yl1m)(8pSPUzMfX+4{?LZPQZwb8AdL8Sr0RSGWm%?eOQ)o^gi} z(M!5Z)0g30`bSSvi))#SOhp$kaq$dQK z8(!8b#&YJI^{LEy!OCU3y^MNlN^HC@jDJ>ibGH_HQaku;>(Qt?MmqTM(Y%#g{*&28 ztjT#ZN1N3%mEuu}`CkMli=Y>haWW?lJra;>&`}tyjw-o*@dG?W=2N71uZb%8veMM? z&-|Uf@p3chj*w=9^72T>-=?BoCSN&gxWRQ2|m^vxJvaosP$S6D@v+rtYf zgU%Po?11y1Wg-vUR{owblQM-xsiWI&Uxqy2(#RD7y3|wnly&^W;j4S#Ztk*Dr3H!+ zRGFf%^i@ajD2ZH6wD89IA9gj^uTI0(1^Mqp8#o;uFOwb94AZe?8k}Rd*cbVXP@Bm8 z%-4AzOTG+7I9#48E_t6eOtDtB)!^3Hwd<+U@-FZSJ2Qq7W@UAE=&Fo( zjA%;)yb?9B4a;(TY=7)| zSg(81&aDiJJUJ7k35^V6bMCX;uCGAokU1UIjwBQRlBwwfT}~>Ur?zD%J$j!ToitqJ zZTT)hd*YU*r42u8`D=;AEIZ%?(lcn2-_Dm{-OJi5ldJGjSTd$9*+AyhbIC(SCljz< z;WN7bga+4l{|T&^nzPRBbdXJh3UR%|PS<7`#NHS=d$)$9EVrdn^D_?I%8_z;Z)s>l zQ7Wn(bVp)cQx?U{oLULBxiz7ke|))|s_35~2sd*v6YG+KB|P-^ee(-Z_ie$!MdBm0 zr)ajYja^C+HLwECgzC$GqUci-00nS-F`f_`ESI?e*|cSRn}qd%(%JhpNo=-Fqz4&` za(8VprmD=SQ!_L;Bc1mvCtX{v9Z^RxTxWgUl-+w=0f{$>2CLyM$-dzh_;Bk4@`4ul zXW3pJ%q`o*v@8j%j3<8=Ft|L*-pW&<-=&ht#zRLzjNT?v3k3(vmOInv+NPqt3VXMr zIa+0)3x)j8ETHMKoz6d-KN;4!14s)e%BgsN#*os=N1wndT_$Km@ZRB;#_8ux2_zWW zZH0{tK*a+()YPoGRP|8@0hseh0##KAkNDoeea{`yU|t1BGC|^6(i&Jl*Nxo+@gyu) ztK4w9^1YP?^!hmMo4m~zvkuk(2L-9PHn+MrIQfL9a6#@7l3;aS`Q4+w>t})7Q&iS>0-l9iT zjaADNTS_1wRKiqRVelWL>rf6Ac4>@lU;~yGPu0-=&ad_F$Ck2hf75k;uh(#{o4YUR zA9o?R6~KHNLSpuT$?Li0N6zOkQt6rf4IzqYpv1QzMez$9A1tG6AO~0bNX!Av7UODu z?Q~#JfN==%SFSM#h^z^Ba609)L9*v#s()7b*l9~CywATMLf#DjqYd;r6aelCUzjn> zZCmhU;8xXkQsyK>wD@mLa_|IZUe>GeA7A0UBiRX#iQuHHcMSxdD2479s6j}e@7#7x z_d{)5h$967C##e1MfwEHb<_K}O3whff=6vh4BcMoQ@~VH_4fG64jXLYO>J)r0G|pw zya1{gl4$lw03;eH^x(W#)3~=T7TsU}>~N-=I|wsMr1%0Y@CiEpNY{6D4F&&x`Rjen z#S5-!&xG>bJRpc{T+l^bCWXH=!~;N;DplT;t5P6{mR&nQgW)cY^8vcs3?{rToQ>qI zTZ*oy*7HTA=dsYJXD5bsCmHHG7`jqC0RV|~ds;R-l2ezyEld3_DfG?`37#iJiQj)K z*<2|eU;hs)uF%8ImPqw_s8S7@ceiYwHA-f}--D^bN9I9dNk4y7K^~Zi!22~$z7{P_ zCxUO`&~zUDR+5CjPz}0iWUk8qcr_f{jMtp}{;y03?fm-qWSvhN-v^f12P1=TBQ!@k zY&i_W?;T=DygNh!_n`5l%J-(k)ND@c+wwMBfFD+rmG^K0ExLb)Dr50p&LaZZ1mqTC zs3)G&3eQ^}2~-VvmEZaR-hYD>hMn#oN6uf{f0{mRzG`jOB(01?_Tqs}VIgy04j8>P zLXy_-sVE--6IC(LV|_wQTs0fUgm-HzaEteFtqZ z*_=_i)mo5uQ1PMy-6iO}yFNfD18+kmp&fbgUjxsmNkcjP0+muGdQa9j6~E1H6a)9@K;gZmKMOyUjH$0&sd>FhgCjY|(fVnJ8Q`MJBQxD4q;@7uYf5W$m z{u8k8UXihct0){HAplD0^3Tiyw)rY|g!Ym4(SPm7S3Y#MQt5>EqV@2?OF}Xu5}Yds zuae_kOzP28HFJv^=bK^$2YUN+1_&YMx6dWCNySM(_Op;(W9N%5Hir0CJIa$PYwooY zkANba1MidYxYf|_E|3+$8D{5x$Sd(e>69~k3pWvU{+;;XyPi8(Wthkx{9^+uzv@)yQn`@14t( zb>nXzIqz5T?~b{}X$ghJ1)ZBBv=hPKTa0^m09@JyS^upv4)ErOm!3VD6t(EziOdTy5*>DEh7H$9Kl=6O-0H4FO*LWYK;cvhQD@$ZV<;L>?T9EgoKZc$V3W zZZT z?YKW9HZ3uVjgIu<^mZcsfLilxNS-^%X$16jKT-!A_5r$AKQ&?cQi&lx)qDkWx+aMb z&C9aOrUA1U%SV3O$*KO{?_Hpv#2X*0sIdSD$>*OjFDL+~SH2~04A>0=o5Pv>7Rd@v zmcljBhklm2J~6jS9a8JrXmpUG!C7&2L0|a$oqW-Ms{@%2_5T{L{Q)rd+Q2fM4G7)a zTK$^oh5Rj|@lXhSjYpj;(-3YJF-2poQ#%!-)_L?gIu!|31@D23$iJ3Vj{>$zX~(bY z+@znvA`s4)H7@lg*8`l*o?S=DpxdmP&qykF3ia1*BJilSs>wAKy?Nc7Yt`d~*GG(m zqZqOtlQrm6lmUOBX;%qd3LHb85Soq{lzML-U!Rt_+Qg3E)}At)(-yvsr|^w9?|l$kuS z_|?Ij5ns1P0=nsKG`=Jgy^hyLA%j?*}Su*yJ(6L$YVX=EQ`_~n~ z<9Dk?!e{t_Ghh{pW$D$GW6#nKl%U2O_Qg3)fOaw>j#hFx@9Hednb5Ir{SH)=)X=r|aSHfK(9d2K=8Teu@xD+~Z+nW-vwzaY9*Op=Mcwgr zS}P-dpYzpO+7}E&EF~+scKFEmsi|+HtRi58gE`YYU$B88MQ_^pM~5zMZl>;6&wdgl z|6z5<#+A)0)tMzYwEI-*r7>}7iM*Okv84|M-|+Puh8wc8`qu7 zgxyN<({;SWwzm1}(A>SiwjFBOF`M_fG|Z@2y|&We^h7)Q5gt8`W1&@V;uPgkLsgyk zel;c25*8DGN*^2zvwgZ?n9$oTk*NQtYE1Z9#jb3L{{Hh~=LZ6owy(P+1^Y_JsycQH zPmZbV>)zWX2p=3@D-Etb)Zv8;Z!(^&c^knz`YWkFj2G4(h=^`##_9aE)9idYRhuxR zE5-8f;5gp-9_)+hI8QT-iBnAoG~vUFLS_dKE-BZ&o(=HdesQ~uK*zUt8_=60iFS_N zUi8Y~-7wj@>MQF9!>>UG3eEH_8sa+qrAFJkblo3n=m`9Bav8-{cp80jPU7!ko2tG0-B&M+6J*e!|s zrx1z$6Wh9;0=D7Yym?FBV1mDDt{>*JNp${$dE~5P$8k%@eomifbX;C@V#Y?I5amhW zYJNkMX~?0q6V_9rA8K^9Gi(+4*c45u!`}#Vmap6DS<0+ZJ(<;oqhA=Cw(_-ZIVLVC4U5%H;uTB zVASjUY4v-8ubc}vFe;OACEXu9@2-G_bq7xgx2F+b9fl)l#9!tw!klc=9V$CXkDU{#%bPATGYr%nFY=$r9 z>{&nV`#4x9Uh8V$xQAyy9e~5FOovOpA&unv-Y=*_z9{%j1ve%>>b`AY+=~mCXBp2= z)xJ@S?79Nd`jOD*)Pf^eyGgEb^5$?)!0AQ5K;@|_J2LxM6z8|8WNh#r{+WAh*!g^4 z1q?B_`LJpFWUG6vB>JheQIlM2%~V(?r=;{xv3}UM;xT7(TiJ(^r1XW}?+ZrIE%Ch5 zEi*lf2wKHqnGu;c{|OwD8L|G}_X#Ygo)@2qA>S$!uV2vI7W!_yCF}%v<@j>1v8ugA z{)`2%{7nMz^sM|#FLLvBSGmu&ifr)3)yl&KVqCfCu9xGkD~mH4v8apG@Vt)DgGJ@W zxA*JsT^nBNra@kdY~*z$Mi6Qfm#a_ti?OmGl22Yx6>0jCDUM(Ce##`un@dUNy)Q?L zKxZlm6X}~*(H-XdCVz%1zKiJB5MBB}+r}w>b?ur_*y1mzwJz(lxAW^BHSJa$OG5tY zcx>+w@y^ zID+f6EzszA3`Q|A^Z34@1~IQQ{|R_W()|M_#upZ9;7ZZKzOh-H$VtqLk$R+J2*cG^c}avKAUwTr(>mLcU9I~l$@8HPf(a+#sOJ-fu*(zP8uDxKH@0Mnb%HE6Fm$1 zC-3fQJ1NcT_MufO6}_63O3hf&>((Lgg17QMD^216SmHB4GDK15q7&-W$FSxnDMeUf z(utk3#|%lB$BV-@MJU?8htf*Yf9Geg=5Mg z(IR2W!Ty(jn7NwOZrS|3M)TDtNKQUY=`oif^xr*Uzc3V|6y^~VZvk!IHt7u_*9lxj z1+0!Qn`T8U!`|*ThwJf4n8LdQ$G@p>ujcO3o5ws+%j z+gBaXZPy8I*%gGt*R%Xz)t&Jgh9#+Y4V`9C^B8X~b<~@WwF-XYnugCnMfHPAC^{H^ z_9NLB3lyhgj~_-EO3xfJ2)zIC@w)ht4qH~*U@epH^|O7hnG@H>2O%rw1X77PucCRIRBn+Xh7eyjQS>JgmWrec z*Y|2r2D!WQIah!N;gKgBWd=C4SCmf!*ROskXrcF?C5BJgIM=EQXZx>w$D*wMwOPwP zM7l8*EW&q`(mTM6&{_|)*3{eN0rh%xw0~&4ogW}Xek;=tp9aH$xYA=OgJkC#)qQpk z5Q%b#CEu`0LT6*ELsB-Mz3>ik3@1KmZFT*{zajE->s#Qk2?wYT-=k|7p!}tW%M`JTsxu~ z@-z_)#+mCOPasd@>r_6KbE%!{@Deyw1LVr~VDJI%q-$Li#5d~2Z;qfjv%fXy0et!` z*m!4tq;`Ugl1*<#SUIWH;eHP;fJ1rv)6Te`Ki+?B`;nTDd~q`pA=U@%9A#7Xp5;)L z$N*B|7IzUKDas#M8-)=EDbCcVtTL(SjEQLyAu}KSl1By;dClmq|MZ$8&2@IO zH0yeQU0693Z+h1A2RbxU*2~e0ue5lr+mGBu#hZctH-h5DgBJDQf% zvKM+d)Xt5fl*N=?tB8&ZSfAQ0Hq37Av;D9|r=l3&J?Kv6I=Eye%uX9=uCI`+z2RVB(am9?>b zK~(c*9FFqP@9&VxC!lO@Oph?Na4XniXk;@ID6Qd6{$3?DC#5Xm$S)5i^buf=*L$r43j z``9x0gI-ln{dWOkxP4}xwS43>bag4Tn#doRdi@CL#+wSQ@yknn^o8+eA#S;gURQBa zD}mYcA?Z^y1aEN*Z=ZwOB;$QvpP6=>g8osOEz#(e*bn?b7KR=E3g**D-l$KeI(Az> zHVSFEj!T^5U?uJbfet5liv-ikOzn}ZrJzHUfrx?zG2%|oDfezl;qrF3J|_tNdYMfd zP&H$^)CVaJ&K*b*hsUQ}->brbX>D~%LX2ImLv7~&C$LpUdE}x__Yo|`8;&lryknE< z=p_meB`qIaM>!5wtVrGzjx%yh4YfH7LSZE; zA-;)o1&FaWP8}Tb1ig6~6dyl?1=Ob#p-+)38>N|XX8$NC^V6eBM|@3-S*V5C){Q1n z5Z*0KI&Tkwf+L+C!HeknoUmhqe)DN6uF+UrL3UcC>dd{h=SzBvJKiaV0R!sJQ!L@| zx&755VK!r@tQ*FvWlinJ%+qGlcUvA>lz4DJ^^JM|NRShRd+hhTH5Dt^WiA|c_M01a zMAoq=C+qxvwMw>*om9hN$$3enPQ{<}O*57foO6{w$d_8_v)NpkcAWe&?qXT;cPJv@ z>kipmlMQl$!nbrrDYZiLKY`bFe=?Oc{2)l=D$KV1Qz>8G@ik5z8kN-uBcg>Kkz4GC ziT9EXZGAxp9yNQl;y^!*?waW>V#ttxpc$9wt3(D+xU_66tY!CAthGX#QYV9z5xrs7qfo!3=8x(4l?tOTXDfdX8phO0=wn+|wMTZjG!TDg* z`@wyZ9gp@tRpNtEQ=?*I>Dt(wI$v}yDvmMtAxjYOkm zlE>D`-e<$I%URdgXI*1{tfbXQu9Jwzvx|IQ1|W~DY|}=u4}R;ImW~th^&a;}r09o; z*S(oPP(XVV8u8nOzUnrM%3F17V-`;nQXWNz=S)>C)@BH&erD*{HvG|)S%eDvq-TlZ z!i#<%Vqfh_p4R=zc5+OWs`}gcqbkZQ# zie>9RAHJK>RNZmAT0+eKSgMBTcdxuR*pAa z2u-bc^`qy_?mNnjPh(c0Q;-?OyiW4=g|W2}{Ud%Vnwu7QE!d=v+;*)piRiv!fb4 zqF!DLEAJl|o;dgWuZ_?Tjj^rDsh98tw><6mFPrR;?s-=!)Z$3+1tC9Jyg{~72H}ZX z*D**y7PiR8q5bQSJ5uvP7mE4EbDbqvBKDhGYzmL zR7D%qVsNZtisE{v?op3UnT<0>vSvoO1fU}F>xcY2>f|N*>_{&kc3+muYcd{O7qQ62 zr=0tV3>D(^+Soaq7oUE3q+PvcGhiBVWuct4)o#I}c8sT6ZSxQJX?^%$wMDN@kXlW% zcM*zquf!dq+#Cnz$qQvF@vIFnxI+4DZ?~RQVflodjXAb1<8EW|*-sC$I9300D)}wa zFfe{JbKS7zsbpwmWo}@eyk0}-jH?*cqY50Q+IkwNrKNlzFMN@U z*?Jqmv>Qg>H!?7$JM2`qh3}*|hEwuxVuO5ehi4Kq4jz=(BJBXF{4~Zc=au55@M;R6 zr(ya>`r8XF(mixDwntucMLgYEFz8darK(uydp_pV3{s>>)--s}JWc1|Ra+pq?k3D+ zP%g7_bTE`g@h7&1N%}4Qv)e68hO`%<%=@j?D@NQSd9&gykKg8r7A<2N`iG^Tv|7j> zFgkD;C1Rr zLZ}?nS8APYG{Gw*z7O<}i9e?()?Unx~bhV_+cyf=#cIO?gbQ{suJ41N+hb;h4*Y9h*_n&}M+dO}# zUfE?=mZD&S;^n-HoDM#ub>#3dqsOrMlm7`EJ}G%5eD^nnK0a7Wn4lEG?j+Aq%n$bz z+D&sY2lGxmJN?encU$x0K}u;{jXHL`v?YEgJ9*^q`gH(wCa~l@pKUz(lY=rtyJWDB zi?;s^`Si8rrSDpm#*UO8DUR)8cPCTQY&B?3v|>)8(~c4BO_?1PXkUCkb71DKrP^==S@#JFyrOnK(wAw0-)!oD$}a!QHL)fh)S?KD_sAc+PZg zHKyl_VS#Dt6X;n1J zCcR7#IyX2B>200iJtO!!3(i5FSL+@NGi$=~dm3MMmXKX_M|PZ8%N)FZwM;G{H+5Cs zM>%hm_&J{uDttzmZ4>=aro_$bm44;5qajR-XB)dg6Yu z+%rj{b|;rPxI;6@pW&~olNXwKn-hG$5Vg<&lMEJ*d{@TvUagQ!M zFqN|UvXurHPFZU2ri>blRR_A=o@sX9;)@JA9$ERu`%_KAs~1EkoVI;Fj~3!z;_9t1 zUv3B=Wcgc;z8?;jX_}*ax5sU2em)bZDeEQ^VTVK?3^Vf5CdSKICa5n4IcoA#H>2ax zUXUn=KwaMQQ&DWhok;a;t^KYl2AX`0o!eN+;Z3$8vx%ewX2A!twxWZbe5pcDmttwvT0OBpciYO-xhTSl z+?;4$^-rYLufN5a=aMA1Yarx5Z`g?KGT(V*k4y~j9WM#(>%4!nj^%l^JA3||o=9@kWM2y<)o+&-qZIPd2wTYl%L>R4! zJzy7qVrB_O^z6%1(;%d0axSjah1FBMMWKordD*OrB-W|byc@iHU5Q`(^DDe|bI-7d zzC^@>y0_a}k4t5maP@XR(yOX6B#$$&C|8HLUuMIlm@@@N)7J}q3~nF%wS3jA_C_I^ z3fm8NiN(V&WWYXi>L?}7#M9yB_{_A}=LdRK-uwBdFBGk9 z>DPr-@TSDlgLbUZi~WT7V@nr~I~%bj?Df&YYen%W7w@D9{282OEuiVTu2ZrQf}S7g z%lHH;&|Xe}{%{#3vV$`S-~cOsR+LNk0%-Liw~vYU1~zgk^p$!Er>mH=#Z||B7-g!| zmc349@$nG>Aj$qt_#bF<;2D zI^dBuzmJGpuq_SyT=9aia<=H?LJgEM&#;o%*SN2jRJyL+3Vh+#l^uaJz=^qWrAiI` zgkkUKRX~Ka<5LOvn?rt1jH&)x>l)_K94eypwQvfj6G1P&XpfFSu4-&~xoth?Zyeic zr00tTO2r^X=j|ecOQmosOcta7)YV1SzXiWevXU`=`G&vR>VMPZn9*lArOt%Y0>~J~ z^Dqyhb?T$pY!EW>i7{fog|u+hWK=%kI8a395fGkYs&KLSIc*5`!+hICHqMfL&utdy zUY~ImYYcR%1%d~(98rU0ch_v73>^Wcrwrr#3;-{_<(`PQ|r74R)(I#ikElra?GX>jsqNxW5tX;>&%{HB5rV zcs4KhoH*`|-2kYoZcOaI5s+aI%SQ6G>uP2nz(_YH*H7^NiH4CL>r(Z+vEOC@E<<(g zygBI(6XFl6hBaG1B|IqsY9%jA@EeHAI6N3u4Fm>xdz|sVqH#^WCvZ(lzrWV|0417^ zps}-$WydKsX!LWfdrqjTqnt5%DiS%}S}2E5+)65(gmT3g$@n=b85ACHq$B;$@H3oHGzc-4&<689@BfIkTxXg9RP zG)jPr9r0}U6xr5~3g(yG2l2QCP;WHwZ36szfkngIv%>|tF1yM2geerg2FOd`lTwQ5 z`zmh&EhOkB5eqBb28)%iPzBA{eYsA3=ZR5y`v_1s%5_z=XxUZBe!g5 zJMKXFv?}b({p61o{GupoGw3t2FP)6@1kjJc%e7y3W>{GC6*&g@r@en+b1DQNMIBp= z7A4Ce&47#ylY$|t=u|}1{ZHsmK)Mo;ja`86$I;-JjSorlq=my^(!V1(sud9ky&70g zIlfp7B4>DD1)0*<;72%}W4tLg!=x3ibpwDD{6Ge@!(^>|b#3&BQ0*t)(jyO;6F}O` zrndSR>O@n@5|+0W?kaVMlL#%h7X1vM<4{EL`-6t$!BtB*8I%yS(vpJKXr;wF%fSL7Lh}} z{E8fBdB;^O1mXYWXSZrtD)kSLN$8kJRQ}=L@e>@(?YoYC(5Q@0yQb~aawNn5agn-h za`VrguA(_{0dig;tRe-7GzQ0w@39m6aU84=t$m8rT)kG!*MdFp>{GR9-mXJMeqi{p zh57s79PbJKAo?Kl!l`Cl!gJ`%U;$K7xyXQA~xFBScOdK_$9bagc1xNh(O-`S8e8i!T8#I?R!tkgUU zirdnhU#nU=@l?sz)-AWl*Zb%YVJ3l46O~`}q!D!vGzQHwT+Sy?n+m5lzAKfjcr3GU zaz1(V@BQT%qNHiP=D1Ha&SwzxGtjkv40{4)b9iFRj#ocAJkEi%fhSBAsd@i!~r z{wxuL#_Tr)rB$mj^?0NxXk@GVspC#whm-2F2p7V_FgKpC;{}Bp7KbYPeD5IzsA@(V z9v&r5U>!h5BQh$M2*BXxFn_y!M&*a1%*F46#HOSS!(NaL(sA611)8+ds)es;Zd_!# zf@w;l*;#5%%~q)s2pX3{CV&}(+n)STQ7hnAjGGDe1cU7*i8zX&2osYm7#@kdEE8F2 zQ)NKvk0A{V^$|Mx{c?UqLMTG22J=Af`3H#)!~95Q2$Hlpx#)4d9A(LH!e#)p+r@vb zn!%$fB`V-O;_%Q%+;FhB!c6O}2`!40T2gn)Hfp-=4WF3;_6j(rm@SQs@^85{@SZB` zsYPIAxm72Fo^GqEDDwNF>y@J5QJi*6EHRkWkeCe!IRL6zgz?R_5MNdsYLNbn}yRT%7R9 z7s7%`apFr@q0^AV6AG8zf=>F$FLpDdhMu@t=5;yTc=%1S756ZLcCLW0`xYH?O``jH z0dkjJJs>E0VNH#T6JW`gX(2yLFyRZwkBg6tI-u1i^Auj?%Uk_O=U!P?qT@LVO0i*z z>eyn3M0)InOA}Wb^tRHaTe`oE_ikF5%~c;@*hJ~*o3k%+N2X!61@nYr9p4Ro*f3_} zxA(p}e~BZQy2ahC(!5%NN9?`0l)1h&D@tGD1-op1?@Yd!Ql>ohy?$pP1m-rZ8`T2QUkST(kw&atbIR!? zh_9`l5SuMo{%zQ|af#LYB;)DLi$B*|Bxc@TypinKEv>t>>(|Cs)eFcAQH}HKj;Daj zZoGVg6>R%~pIWv%vQ9YtPh};%Y&M-*dpkX>BseRqLrNhRNRA%fml5la8)f757DQ#c zs20EnH2VEmg6*Gjhq;NLX_jWe7any*T(J97`J-S&P1kr8`3$S5!qCEN!lo`y2JB&b zyf!j)VF;F}^>aBY&UTk-B$lJqy> zb0LcpwnP`XRkN*lHIuVxmZSu+^>)rSm$V%_&J%M(4Z@dayYA2LS;O>^Vrzo}zjyci z?4R_x`##cY;M?w?+fln-oDvrhEYk`9Rd(1Oq#Ag>KXFKH7vJ|&MkpQcrIz(>%()Vo zW%63ZgTr5cU3){Ga0*2f4YX|(?#;WIH8kM6xHcPOa$@t2Nx=Fwm~! z>FVM-eJ`#QzkJqfPVUh;mb;hknom8-^_-!ygftf&&vr;5l#myC~2nM(FlENTZQJ4@z^{oW?(=b7<`y489@$opxW^Y3dQx1Uu_jkDxhD>H#=I z(w&|X6-eq^o>#z51!?T^?R{-)c-s-}*QOUCa(j)bB0|!-~Ai?mAYZeb+Xh zD-Cc$=COavNk&2=p-!?F#*fq_ocsJ^TQ1?6*0_*Y`;kq|+SXO?Mw7s9s{w6-9(^PK z?enkI6@T(3j5#_M*qw_8Zxvw@n(ztN^Tt^Wwg0(rI=87;jba4+(24+Gcs8# zBWObaWnbk_kGmRMymz&474d&@bzmt;QJgFu?Jx7^p`e_%;@EhCmRk4MZvm>r!0*Z-_7rkd0#y^v{%yBeI<6TxL~FF%l9RR;O?Yz z5)btIf|R!GLecUIeUDVC&8NxYcYk-i-I&bEJKVa*ha%1*KFNwTPQ#5C8#JS2ye4at zyPqe_PqjY#xQ6N!C)L5Xms(FCFA98Kz-miy99VL5XY-^=UO%)Ed=s|Xe<`XoNVuv-soa5eQ}!uj)mHQM}7TzYp@+o-;s z<24@8{1$Vrl+trH%a`Ie{y&<|JDlqOf8&~3@~MonPDKgHCXv%ZlD+3i_Bc++KF(>O zWQ6P_**o*#;8a$b+2c5l(XkH)an5l@zgOSu`u*2c*X2~_{eF%6dEbvaPVcF#xt8t^{$h)+R8Jn|K zHE(1@9{O`qp)@KqzFgq}jgal3Ku0K!mVG#!pitTJ%5|qb=qwWRrfQ+YAxEO)#`1;? zHWV4R^k7PF1}9YEnkxBJ%78xhC6gEu?{PXT@k8^;xLtV~eV%)~bIyaH=jrD^o2fG> zY&|G5t*vcPLa{k4>gBB#-%s)4x_v;4dq$@8Ce0hXEWtY-w5ZfY6yPZT?ZwM~HSEmV#pSpyt z{Cd^#k%<_`(T*UYO`{B-mz_U#&)wE49;jdTU*s=iZjijEPbw^B-FYwUeXb|CNY}EX z*w}iv=;TNHUMdbf)KD+Atjo>|L?1_gEt!vt#8FIyjoUi8-_!_tF6}9Gd|Wsuw_;RP ziVD{ZjRQkIyy)ykn|bVY{~v$wDV=-D`8b#JAMtTN48Azp*2w(<1tQ2lP{v(JSO4)U%K*}*>_xJ=ejVzhAUs- z-^z4J)iVkCnW?nBl0)>QmL0L)1$idnO5AU7(&y!>*U6gwbQo@?DY}qtP4$um|KWLA(Z8x#qo1;8pV_0#b74D@D&B&) zvP-z$dPqk8N&vak&peIGGWv6g1SA;OtpD~G;JSSD#Q^*0{ZBvY?V@pgC7&YKAaaai zFsDn9ZxxpW_c6U#P0yHe979D>601B%6jv)cR4!A$f(r=mR&XVG=w$OBD;9L=Ls@H0 zPI1$CCA>}nf3_LG^UM!_D3LwZS8-?VY#(rFAKK0DJWtmjrQrYQJLEl{ik`Ly@zts;&QsX$%+5XI&ZB1C%x>EV6Utf2`HtRvZYN<|L%M;C@Zyvq4z>0V9i*#SWH7bteIK| zk_R+;hQE;tZ{4~b=s6*aa;If5aD?6LI=Tlp47B;sb2`Y~^-3Hv$G_K+&~pgubFm}D zZ8)NtB~fzTY<>X@v~|RsL2)~VtM1vb7HeS+RG6tK2CSS}uRZ<6{4xIqnoFD7010?T zdc3Y?!2t8%q^t!;s+q^l9z5r?i-W%7Hkk{(2CZh)nw&_FovM+xb7IT_cNn#~&oV7lC!hWo@*d+H6SRxRZF15KVo zB*a{PZ&DocRh}9TZE)|6LiWSHO#!eCltumpHfpFMv7%2KM z2fADhM0~F`=@1{*^u-c7in?e zV{wO)a*#L$|4&Ch!wA)f=_z|d%49ntF_*CQTZS>*@))@7+}%5UI-ekt>hXr^;TQ?K zQgky@eK z-@NpRyTm}>Lp_{PtDsGip%!Ji((B7b9I@~3Po!2d%5>{D7`WEkunfRaYJJd6@`t4W z)z9>PJD8N&(A>|Nr9j(_l~o>p_NwTnV$dPa1Tmg~FuW4q9EkoJFvKscC*n%rIU|)2 zHmyA5j{4I84M}{mwb}S0_<1#J1N+eB@Z zApobMRR9ZMr_F(S$`~G!@aF8UON?pDjHp9BBC1e^;Ud$;MCtnzgn#s2t^S5o8Ojhu zw)C?GYUSVZgpH#XeRPNcnrKMYR^8wg;a{_7T^7;@KqFbeNC8>U26VHTwd|tbxQXPb zSCdp2Q1B3VA8SJP>SSdA7sGS`YaJcA_sd0D^GE|vJ-pZk7;+2ll!--w3NO}*R{g2< z>;FEwmqT_R!Ts`xXk~aDp|ni5lkdhulvCopFFE0X=p<9j!;deOwsB+txHu$0fqu1I zh+Q#=J*lD7|VZjFC9@y>@Pf)=3bwrACHwpY-usI)l^Xb3Og zNQ(LJa~pbG$fMv8A(kX;LA=RPk&kwO(Zs@V-wDA;olU-uG0PDn)crh1`4XZ3e1Wp* z8QPO=LxCW zQ#_J|d&fR1ImfryTHN&LLv&Z>-SCjQjo)9Zl<(}Vu`-D19a|qlX_|M9Nqk9=!`Cy3 zWHi@3kh}U`D=IV1=?fN%Y&>Zb19V!K=XpLB13^Wij9gH_RJKzXkUYuRRkI=PJ)`PU z@XOfzF%w@29;N&UJiGU%FJLF@$j9Q^&4gbk|29T~AgbsBeMcYMe0?}63VgR0Rw05i1+w9iFbAD5g5I-m&v`|AWz6^ z#9CM=O!HEE0<2il76~)*RbjyY+UcQlwggG^2kBdQ%VXBYuA4&W1?7U?xa2e}0@`Y# zbFsJ_$b?)L?wq%ZOLXu>rkyn}3mDLL;6D?BG_zI$rNLoCSG=nfJwc$lnJ?MkZb$VJ zFmPbuR3Xr<6QCJ^y%6$~p}DVp(*9D>MO2bY@w}!%Wtg7p5SUU4jv7a#p_8=8b^7L6HCm-> zCD`>^EzE&zSo5s{LABV~6j9csUVDxcfg0u(sUUG4>{IL!(J#^o*g(Tu3HN!;?l4DY z?GskYWRJf%A^L5?a=|Ca+o zlS3Ni6Rf9rEnRHoW&3NNreh+nX^5<@!o{YYOP@!duH07;?f4S!``cAWXp!T;gXy{Z zH$15LExC=jRhUm?X}XyNwmh8uJ>u8p_DDMow6B~ppLIl_Y0(up% zf7dGeBrNlGMZ^YkYO2m>Edzf!SaVLYJ~jDKJliQWbn7=Hbe8_;@VPS4V=g=UA_<*B zCp|klj6ba~ZkP^+;cp7v^l0h-Xo8Dhu3kzEGSOFo{?`ND z%Qv04MgSi^X@B$+rJ&vOEk6HE9$(Aj1_%6;v)A{=-m!bLs%k69a0;SLAg=@G<1;T6 zeDsB?_>?TaXplOyvn8lPot4%kT~3qQEgw(}_Rjs~FK9C>)JOjEj9c`>fp~ngZ|Bh? z4OWaF)0R=Oy%qi+VVfzl$_A$#Ud!yt0itE17GQ#v4Yw}J&Jx@KFvZOmUQf%h;7K9W8AZ_8$sQ3 z2Cp^5JYoV%Jpw0_TC;HKrHhoGY_pgLW}YQ_TNQ1CO75+e9{r!8GkNF(Nby-|M}y6{ zSG7`n)td?mN~I^xSv97e5qd-wjzQ)sMC||zL3K(ScPv}8JT7m=V)Weyu>@~E%3?)N z5HDiBVhuJQH$gS9>GjhC5i6JDyRU_G&T71h%}R2QOuFH2?1xn-J37o-l#ZXb&b=@* zg)+C_Ihm&T&NimtLjB(GWK-&KNQJec+w-fPU%nO>R#*^@=@nmN2=FVoOgvZjuRwq- zN(ho~b1|ANz0AHyiI%&I_&g;u>AlXq&TBAzcjdvZ(AWzPs)$_!Y{Lg^&|EEQLD<<# znIv4K65*~+q#=iX-4^d@$A7-A>h`-C_mf@@s)Rx+p!_(eihW3rP2sxAIq4gMDSJamk(6W7eX>oC^i9dwncbKdMuoI3HY~l2d|a7$m$eb4HfdbPUrZxD74Eq!^9 zuBug^p*Ae?E*gJlsPq~w)eWy@YE4G-Ra9;-1HWT|_P3d&iiew!waEDmZjWjkOys(^ zdIjC{fK&%6QmLDkGAr{&{i2G;jca*s&At>Nlt2E2nM7C~HOf>Rt99Do;vYm?R0`uZ z2HBOLvsD-C$L4u`eW5WS40Ol5T?*k|Ba|)OK(sesMxVa_#oedp+@vPq>`ja#&2M-N z59VG-7Ow&H#W}-btU=4kQO;L8 zC9fTtt4&Ub_#rVykeS8k=y~DxAk|S3-v^&ZJM)sdWWCe2VQ*1Vt3=+~qKX~(odtK5 zGdvF#yTikHLyxh}|K)h;+j7zxsKqGB6%ny7cDfIT;7=J+LD$BRp`>6!)XS+ODH^>n zXi&xOkxHzB!6%}&o6BSN-Exx2(h=46kd!r8=w|4yqROZS?`A|w-g3zMW&c8}O!?y# zwem5=fj=_FIO4+}srIRjku)wltLFQ(21R4U3XA5%ySv3Dv_?NTk+0+rxhvMJHr`z0 zmcDw=!_49VJB)icix2$`%I2ljsg4?)tj(I_$<1=XCYe1aSElCQtQ!Ls6Oe(!_eY?v z4qv;5RGE+C4}zBq)kn+;hAv$YTRgVE4X>U3IBXRG?gKAcR$<4RZj9NB4l&hG4*CZ* zoK8Q`Ml`jGPk6qg^fQIhX7@c6-Q;hDo*FNI0(&@|-69r3j(1>I)5f-1IA1XXeiD^! ztjkQXX5pIPhCBkt>6=WpKd$n4oAO@*U5S?S0}0-k!vnNcU0|(J*cAUB(xI_5yjHHr zYGqH*X%&K-MCN}fyD=14>SznkAW~BZnWot6GX6UxJT1rX&+&AYD21QNpRyacnUyS~ zggX`FoXZwA&`jIS@xF zp=&YfzqlFh0#&HmubK{}HY;$~OU=Jk9y}RP)O0dgukS@0?xBj{CHSLd-sc;`8`X_D zO=z)_Ee*4FGHsj19@g-PPjA24WIRpfW-JNpY!UP8u6<}w@cJwtW-ECe&nCPVr}~K= zn>xc^CeRyF!q$WIaYmqBD)@r(f7#jEbR#_K7fd3~@5xy2ZiHu55+m0hN6Z7fkW_?V zwAdr=axPT=DzPf1HSRR`pSZ(I?i+B<2?O>WysZ`hTpV1Y`4uX!Uf(Gbi#4>KUN^lN za$lt7FUNsDU9-{J4R5loBXb?DuvU;ny2MX*-be(-7zH*KnPDbUz>Y0*+uaXyrBZ{*GQ(x_QZMy0&rEgC+*`FUgoPgcAwdVb`O>}G50hh^(JdH%l~1@RvQ{&HaQcv_Yr zCav@_9?Ea}mY3!Osn9$2t2^OSuwI4vX7uj9&G*(~A;~YL<6cWU*-cwRC)Rmh+@=eW zSJYI+2b&_>r}vLC51@DL5IVz(MGWa-E)hVS5p#&F|4}i*9SJ*xw3^vCTGmqFx?p#| zSM;@&)6uNiu8$$E1xUZ>q1p{jR*7B$-hAlcXpfv&U;sYHVZBt=v)eK{QrKKqvVADM zB<%NjaL#BAw1@rfAH;>KC$E2SEhp0`FU|P!B7$^JSOTH$}fJI9B~x#jKfj`O{jU~S)*F9G6X z*os}NpE419SGWfk*=<&&a{6waW}+(*)`V--H=~;Z@gW09e~UcI#>zk%`X^V~hDx}r zGD_GXCXNoGvW)14e*sBHM^RVrX`GUX%lIytfm1s858Y zhJrO~r#i8Pi_5SJJ3O4S#KwB4lJb51-)c$bxz1cz65TpJ$BN&bfO&$)j4!+>zkPAt z?7)T;XqeH$$uo=bkqoRyu;Xb7A`>P#sOeqY!04&rkX(1}?`4xu;F`aJ8o2PH_PRPw zLcTn+`}P&o9IhQhq8IVgS`f(}O4WNHjFnVEAQw)`&`=8buL`L^GNvS)EdvZ>S4(do zhi6|*p?Nvv5rh&XHmz7?UjP#uD1Cp$s-8g%UC7rtI*Cmo0m{!oB>ipXKUa%m4zio6 zhzrqT^X4x4GE4p`>My`qmr*?2FWXARy`>ec@mjEm$vKjjoy`FR`alCAk-aqpC{VrI z$YFUhNPz;tjBojfEqHo8-l}{VX^e?m2w;ohO_WjK;XeG?oc`hD`?76O;1Hy{RolG8 z+yTp49l!rQoRsTPgQ@O|iyLq{swU(9bp$mKedC~<#YP{Pp?TCx=-5Jrv)OhfgoHsKMY(G-^pg54p*$t`;vi^tkxjr zMR}k%z|9usIw)rBXBHDfr!%(c-PC|}webCcOByA(CR`Ea?dnY$14Fql>el4ao(t*=tc7n}A?tc!B*m+0bUetT5<8jG(V& z_`l|9KL>|d^dw;e827d)8UW(*AS2f+j8vpLS3c)g=YjYVdrvCk6`V%K)nwN6}!VJi!qnxFwpj=*3M?gmf z3Fzm_1{pEf_rDI1e@}IFx_}1u2L;rGL-gXquRtaNVMl;s{}idu)&i1z3)vJtT!=3$ zyS#ih8TRl0K9{gv=#0<88p%qFp4kF#Q>XiGX_b^C$UO#{5}xvo-AbhC6Pxc~lJN%9 zd5OL|)()^)d@UG;NEwY^jtqn~62If5c}m-Z=_qrS+h?2iVRv2U1l5+$ij8g+Gw~xY z#b*dds6u9)^-)U1W^kXVfW`QtzX8aD7w*+wQUj$kRz^um%}HS`#Z+Fa)IhJ=v2b-d zgPZKbc*;D`V1qavq&(lIwLiRW~zZw2=^ToO->3Y##G5YxJoyZYLwQN;S z@2e@`40a~47AiU$pfh!l8u4dO8L9pi;VS06@NHcmR#vd!9l>Wh@9%RCZ>F!R3;yNc z6uMBk<-ZXbvheX|1D}mlZo`{Yk$SZwduQTOG=|wZ7HbocqZh{R?r3I9`hrTvsI=eo zmt{QcdjoICF!^83@YT8sii0pO z;YFjZO;^mhjd!Lf$BP9kN*k1_+6~LCD#ZdCMr`n#Q$XF2Qx-mKCD$mYBQsr#bfKg;}1e z4l88>4&>RXoug-^96i0+J9iftqkNH@Io~HqQC&)9N&{QP%l?AC*VjDnKm^?RjcVQz zHN_;cO#@WHCC`t!PK~_hGIxrbsATWjI?wId-@jQZMxzi?!wxf zwK~G2(wNF?7ZDlWBt()ywxXs+w*Rldlv-bY)}-Ku1XOakjASjdaqS|&(G}NBhL@`0 zf=a-cCl%hm_#o_Xmctr0LlEVhU*l2I53u<9o~v#nHa%|=X;wD=Hxv$aUUX}L?S@+_ zPn@ps0hNP8e3uX#a2VDElk~ef>@&g0Vu2pnZAiF!6?yi*7v-Z?C|8H44h*h)LK+4x9--;ZIK_Jx_|LfuQ!J5K#RUI1c7Z>sD2Hux?bl5A0yjS$o|N4ubm*$x z?_+P*49ZZ3v{m-8p-tGF_8XocwQqsJ$BuLVvj#k+b%L-b4S z*6&Gha?%dCPI#uUjA8Ft)5Yh$NfeU^6+--xu!=#aGT`vSK4QIEYPo_wrQ|X!7XG%MbFcj!&$s9Xwe5tq|DGsU z@a{>?;*KoapTg*d-RPK}Jd0ZR0m|XSJr%=~A_>+-j+Z=5%#RG{27uG+5wt7%DDwE= zEQZ34b9lUbx^3_qLI`pB7spj2(=(lP^)a8DovB^NyBIROX@3=p(vT##y^koV3_a+`7``X;W?>R9nvD`!}Uky)iA3d*F6(SU)|MbL(U2daK7bVl*#doQh9b~&`V zVfhl|G?8ptwo!}28eujaP-F?OOZDvz#0?dw%2uwyv@*&ZfxS0)ZIscD!|K#FWi_^Y zga~Lqi4WxEWDu#nnit85;TEt}lPA3|sdYo=qA*i*cfMN?P-DuTrwuy zZg@0$ZLVhDmkwiPFwPJt%nUL}&+mq}EA(8&g#yL#^NflMt*!r^*Hzcmq*r7b%at=i+|>BmP%JE$@x*x#g=B8Bg2Dvowi6B?F8!uUnz2RRk$$4MgH67 zSFc#p`HHeYNL}1oj_YRVz2Vw04W&5CDv`%t2dLe#x2Y9&QI9kj7?(LJc`ZbkPLmDp{ z>_T_dX)z2dq^1FHP_nSfH;=CeCF12cHs75L3{8-Vqogo-?%t(oQ|7u2C~+?o88_h$ zr>1Owz9^mXB~GiZ{w&5FM2REyS(PpFmezKw>A5$2^%ft(b)v2t`aRP|KOFm5Xd1py zvmH`htRyNW&5SG407sB->TF@8N+tZRWq8x=prS_IOwHB`eSL07Ch|BV$fM;<3ytXS zIm>mUqf>8a_)f>jEvu}CnRlqqEq$yy4XKrn0u&`&EBfg8igj{Dq4n!@OLWjc!5y0e zs!H2n6_=r10?*Ww)7x!hhBQ>)?fOWy1t!+?(eFnf>J{Fi8 z;Wt_9vgut?x;(mv#Ed1{+}+YV@Sx|-+F>6n@iLtQHNN{b>>FsI!0CPCuAd9h+tIUc5ih`Gu~nkvoc6 zyTmXD_gsM%hz)bOHjHp@Lt?pYd}LbjLMB(jgr&-Wh+n%uexdC)ZaG&xb3 z`d`fNqNO9N@%E;95@t_VySfV;2h9zQKi8^gTmc|Sb+a<=N}5(j=l4c0*CSs#1RkO< z(2ngw$1%I9!#FQts4c}H7JgwQ`{Q_H-+$Nm&z_Hi`Pgey;@C$$=eQmdWSX3dCTKAI zj)l|rPmJ$9g~Wt-r)|c~M6R8_3_IDY@<#o>qnz$l0hiEm|%DE5%O z0+;WnAu-gV@9GRQ?{)Z*NoAQJL@U)^a?I-wUP<0|8qCf@6JZE9)HMoq&4Lou*T-I1 zaf$D4^2zM?kq`=BJA{m+sI(ac>CV-?EY!ahF}dS_Tl<$}L_S0Jvl;5Ro;>e(egng=i-%=yj$MH)I zMkRXUa`_4kzl6@b<2?Iwb-Lx*FE$5_XjB!nvvG_SwW37-IK6iqYZFI(@?CRJex6v1 z1k<~NUpG}EaIT2Ad!v=}aGj?r84o;<8{C*QKlIU(P-Uh+b)-{V*z-^5cgWc$sd>C+ zhV~|3T%i_0y(AZCBFIJ2O)X`&?Od27)xqu8oflkgR?*x*{@MAqw|=W{A& zoUB@Np0)b@`?CV&j1a7jV$Fbmbp!n`2Ur|i1AT+M=dA~yN_7ja8ZGFa2^=`YV%72_$pP zp^s~oAWH3DkHvtFX{e~37_k-?<$Ydq@>L`&_tsg9A(2bq5G&bnT>0&MM<=B#dw%JLIq@ahg%#SKGEh38 zRFUfY@Z|!tgiJinZXZJ47(x&H5w5+I{x z@z3cNn!-5;6Q)8m?sESLipm<|^HSX#(c4Po zU$E2`<(HkHA@Oq%WL7#h!4kEl%0oVi@eV5)DN_uO`gZ4PuVnNo4C(L(c=mvodiQb} z*+EQWkSO<;L*0BtE=e4Fb9~lO(CWXXMzLujJS)>*`6FOfhgH8v^ec@oK}3-Lvzup! zkTw;(u$hm`>%5!;)GOt(%sWHt8U9Uh@dWI>$O6)I6(Z4e)E}x^d$WO-ds(AM24HOXj-s6V^=#>{fs8Dv7E{c3Y&;hq##eRs&+dqQeT`tcQxf{soEKl zDGN^um3{2!9Nb=Sa_q$)Mo?%fVp5fpc`yf+Yw@$%a}pN**}}!jQiz`LuKkTh(rA$9 z_ZAIW^XeD|9n{bW%DJ&{{%EO3I)qht{;M=zgpIiqPmN;`}l!4n?Gfs zAK@B&p zCOrwN(s^;+w$BsV19r~)Z@?sJGP`mEe}=7^G>hy#<1&99^n$~OMBfEuuHF7E+`Y~f zG8+DAg7&xYcdG4=FqOH4Glgwi|4ps z=E~liSefMy7OCURhhtu`hjXMHYo5dCFRe$>f;&Nnog@1Eg}ZnWzvll`@UzeNzdmQ) zV6UWDXIN&;z3w5k=^Xa>eT&#rfr_tsqQ$<3_`ZiNb;H z@1PqAo;Q-3?7MkO?&MjPf2di7Exga8<%iHU&~Lj|7+%$aty3ZX6nSb> zg?(gfURbavWPfHJHXb=Q_Dnb;dj@jqM#W`aDFjA~ zv&b#*Ic;o>H>*wWB#kRQsd$kcq5?#y?8mib6%NgIzj}qbSE2>!7MUg;C#AXx)en!w z(Xx#*n0B}WyFG80Pqo$GFAnN^cxU5Mw@eEk3~2+rSnzeECIx4;EgI(7y7yx9ol|Yf zp1@9ABbGIrzmG>eey~Vy>UEO{A1Wmk+ z-M%F?fs~qW7VHc-?*DmZ5>+H}R2qKcXEkf)q$xv4V0;tCJdK_idrcLz6E*)efgNA* z{Qz+QEAK;#Okl&KXh}m1n)&VdY2kCyd~*t^x%G9rkp?s#_$j6)>UlEjLVZYC@})k= z+)H3_Q^kpHGl#?}c=_gs7+#x0;)A)u_hn@KyL89W?IW|3k9}Z*ezXxwAdmW3Bi3GS zZqIfVyR(%kanYqY%O|T6@5+hv758RQKSVA4DLX!Q`6D0nzn}xgwfJw1gB#?XBit>& zx>aUGfd%J)^rlI;+^A_~%^Xoj7ksY|D(MUE-)d#4AGyzHpE^lN2kz{zlD>MlOMGr6 zfo!s3MQ>JPnK`;@!}dZ#t0Cru{Gs;JcaOeiSAO$>_B&G0tqD@4V6;_y^YE}eH;GhX2Aj#3W6+Tru zOl$%z5bT|sPK3+EdN4$|_-?Ma=P$>0Uyixt2jl9bM8WjTjs<*O@tBxvvLGwTTHu!G zV>E$Y)V= zt=AFau>;`1q0y|9yg_i{9^zegtY=k_PLX!mUt|#DH+YkUBC>`oPMGmd90b z$*(S|@+1)eGkjUM!6KaQUW$KvZPX0R(XW4ce1pBc4`uCYb}0k+<}`Ga>t;Yd0oB~Y zQBtOx38%VoxIHMJD<%?hsGi@vYs$pC<8Y1PiQO4$C^OJh;;Gf$#f1mqODoHYZkGGj z{n7?VC}Viy+?_fL67Uws#Qfz@p0rZN2%@L)ciOP;<3OWfUW8JDi#UnEy0Wjd`?xnG zlvNxtH@p8D3c&322k03-+wjtj|L{MB8xQLB^=|z-wDep4TA()|Pr7$26DI6%(&oSB z+)B-y2@8jz>mzAAjbGSg4w=kG$gU0W=iV)mfd<#D=ikFRk*XUrE(gjIYTdX(xSSE~ zg_B}j=_ukgD7H3(eaNWB*&>hvCQk<|h5@_pH7`9qeS#4Gpa-?|Zw|vf-HPlHB;jv; z*E&7|ytR)}^xBB}0U zz*ZTOvH|Z02J8~=Nnl#0_8x~Iz{l#l(5ujIX>Klp7Ep=+hbZV<$RtwxH%*-01!n}H zzv5E!B1v9oZg#k?s7Qu|2lzS9E=-nT1(TArd+(uF0ZA~c2^Tc<+iqadg#>O!-WwTe zZu>O?{~<8d9=fall-ow)2t_seL6lV9(D_*-tR%!T@{+$yxvW6EjLHd15N*9Rqgrh2*pQ2(drI* zA(1_uf-Pia1U9a5#HZ*=NxnD_RlBdT^WTch`8vnBo)(x#k1j2_@l*0g9(FO%dK-5N z{p|>9-^wUPP%+a=EG>YExozgR6tGFNn20Lw?Y%!xqRrl*jC2axIE#vF2^-N{=Qn7| z#995KV{s>GZ`(p_ffAWgbed!uxabDe*B-4WJF>Yd%<2r*WL}phh*Q@dc<*#ep)8Fy z(pmajeItTyCmg(v4PIYa_V}?^tBlg7y=8N)&?;vGv@w-k|h&tbt?c$jU zec5Sip(f5eEw!6V$sFp;VQMD0hCi?=YiafqxYD6|$nWb)*v-{lGp94ke%oP_F)7^{ z>m_h7SRDxqKs^kPj2dV9)Uw_JITd%HRg7j)r2xu?T6!VOKXZBjyZ|G*&wmCnT zdXoocY|N5>Hkm2>Xcv|di=7im`#IiI!n}SRV$F)&&P)MW{{f1bGJs=hkHMToz6C-B zWYmoqLCb1zr@G+^(JAG&T$NtLdo!<)CTTrongV#b4ajvLADM zT@i)G?vnm@gt zl(nJ!3tOyKczQX>4z)ri>=f_)LC2rkv4YLH&gYi_ZT=do)XTd(8FBbtW$V_1!Dab} zo0~s=EPo{CNmnp=_;*V;55>}uXRcl)V(E(bhyY=QZMpM-YjR{*B|LYsx3;$#mx^mA z<)|!1#lo)*^=uz1!=+kyLX%Z|XvWFP8IwoGR`$I6JEhP7F3>cRehR>PBW+SdjCBj> z9uo(B>R*1?l1Ja|A|f4FwM?A?R%Q*5l%z9!*9P0Xr|bK>$6jU)MX{n|N5vC+wnprN z%<l9=X7e(uPsjX`cnZ<)w|cuUYN9)RUsA1#R(#m~02I<~^o1x}9Y!djy2V#w zAPPzn4nu6ZwWoFmn1ywS|Mxm+k$5o2RZKh1-k=usDlc?wV2$da1iaq%G3K{GLmdf6 z{6cObXz9|6y-S>qc=VoQS};*tEfoaKlti@~>ObpfbdTQr%P~za+%JLA#wd=al3SJJ zb=1jiAWC*0HP5~NYk!V+*72=PJ&^lTjPF3UoC;Jx^Vi-lwMo3~@rj77i=YRwcSN;% zCLr>ITZDje4UaUQJfD^T@;Jzep=#hF)))$g>OKvd2I&*`3r>2izEu^yrglFtyhuqh zdq+ovu%Z$M2sL1AFwuLBDCdXWaCza(*OqWAE(tzzMrXOfh6aF!VfX+?fB-xy9Y^Ec zAN7UgWJy7}xUePpscGd)@I&~m`+4M>-TV!INO)2wcclIQx4Mq}jG1vA7eTn`7bLlQ%nfA&79Thp(HCrU^Xl3dAhp$MkP2Ef1WM3f}N3I71^*x^5n_Ugiw`+yO|_SczPW*}g@w`(773otHI4L-r>YYZ&o8I{pe4?Bhc+wE?c>gZ zKM8*jKUAlYw0leZbUS_Z0&z`x(ny5;oH~WS= zg;u5MseI_7PK(>b-W8>dxmkhX;Gv-J+dWI&qQoc* zg>7wT7Hk68>tQ#gI$A_%qHXrdn>=#M%IV=F!?8!)%-#s?{HVa;JUyilhfv>>)6s9l z+;^O7qr|!wZp)lyV#l7g`oPcFxn2;(9|@>(`}cEy<&oWA3{e>%3nqV&0T& z{3y|f?LU|Qeu9|3tL&OmVZ0DiZs#TttrFm;gYfbGHXncT-2ElZP=g5I63qF_!J~db zpkkL{*MV#GJKYl0Y3tG?1-)c4awcH3bX7|}ws>LKW}&wK!Db5i_$L4E`%Tk;KIxleQOfG=oVtlj$XOQi|l3b)B3+!r#$m-s9`;r*7YnrdG4(LAJJiRjj6Fo z7zW*HqZ_vm?|EAL?C@2BVLe2lXw7q8=fbJJ)=&MsR8@V6$3=cS8ZcqaUqxLVw^b5Y z3ibqw!ftsph4+0(Kz>}Y`zGrvj2h2ITzhf`QG6Y zYpH;q@5JP1)uPlqFIcnjts&u!<%ut7c38kCB^OCiEqyEDBRGB|J(`p7wEvbrE46YkD}T3w_ZEdLFnIi z1RQJ9A$xbDnA~Y?G>cZtxH*T%xK?n|S(X+denJfh=zlSDsU9xtCWAWYcX+73WI6eC0=VdZ_u1vla9!yEYbAeb*zT6g?@xd|M#8 ze;MxnChy!&!L%Rt3Vqx|V}uF~NYlBk^&E%J={xmoe=UO}_JwqFRnB4@te+>R?W5=n zuvjXw&zdrg5t~P$d|O#_#zjWgK71)be^AY%rQx_yf{>Ma_(E8BnK zKYNwPXBqnZA64HS&UX90ty7nJT1Cw~Ev?$M>5xvNR;g7hZ51^lRkb7OLd_IKQPS2P zp|ye_eQNL8Gh$TCAXX9?-}mnCzxO{!4su97_qeX}I*0YS;k9WNULf?i8*?NloQ8S} zV9Z7hu80gXpX)Z{0+6~BXDV7BU4Uqt7;Sh!QYWdGmIFe^FLsp8F_LSJupNW*6xuJE zqQGySuv$UCKm9Lfz8Jw>5d@gSp14*dQvw!e5y1fe-tLt18rZGbTD-H+=qn$It%v`| zvmNLA#n#b0+KW|DSTw)jJzsotF8{)PQJuui^SHaS(PDrp4*L;tqeD-g+(`2`d5CCvH0&@vcdQ6@vmX!HIh(EkY>(u$$k8x2G{(o!5ORvuE}EG;%tr! z6HO{b#RmJ?XvoSc%b?p>*EChb&tGE%6_n82OY4vHMK}l{k~3wVJ+wVtTn|#?O$eR) z>=E5YVnU8Y5-#Y0wQIk6G19rfy|7y{Cpd$)pmLKTDR0p^$NOH<*qLfRsqCv@#NpBC z4yA(Vh(?p~;)z-)@ij+Oyj^M`hci2An;WIlitK zCZ)2N3mvV2RoIdm33Xm&`*xO`Y$~ljzBY;X$01E0PooddR_>Kbtsm`1iT6NX*ES70 znt7HpI%in;afGDMc7hNj|DbgxK2|-tnIxI_WORi!e-L$W1WbU>x5U_Z0!DbjWl~5b zc&}~uwq?(^O+&eCrYrFhv8i9X-A}*&eou;uLVRtz*oh+9Ht6m9z_v9lf{nDB0Po-^ z#m8<&HWmk}nT_Nm*o4j0esHF0mS3-L+cOfefxNZ3TF6kIz4%rn{TD>&+QYnib-0G_ z?M45s?)xNsU^2NhvL#f^H%6g8_hDR2+W4|1d3v6Sy_?+E>4Td0GW(Gd^ve{&IHLn# zss!7;!u6Ttw;>thUb0vw#TXoe4F<*Oy|3-A|Kv=jeE4u#<=@A9G2F^cr6Se?)ByU( z=18q_7~9hgGL<>io;n&LZ6db7<+*G18$DgAHEuOlNt0>BDn09w)~rpuvxr{#9G}Si zUaIM!IGb!r4R0Dua1`_`{pg`iJV4!;`p50;9%|y!OCR&)C9AidLxwFzec5bGQ7P1I z7(!bwDA-L9M|}aCqOE};g0uG(uycSfl{p9iv&(%>jx%Nq1;j5Z!ejXgI;!F!|CBpi zD(&31N}Db45YSjcfvx=}j4etFCzl6q-NU@Rd2yl{cutiec4A)Z9ueA0?ac{!@X8GQ)d79WQ9B>6mU z8s56oJ@&hFtMoar16t=}EFSn47;$^}z=^lcXu%eJ_P$tnS%kyo6a4o*`+kL9D0jG4 zqb7b(Y^787Ca3>_uG*<2(~mWBGQwj;(BDiP%I^sj3`!)wqFmdVNkxlS*LmHqVA)9b zDpm1?i-IIRmj{J%w{o^-7xaVf*H3JZbYjY-5+Vg|*@b9F!m^${Wez2c6iA(6Y;A=OI}UAk7#3xz*cod<o*4kquSXD6=zBZMV)~eJ=c{qG9KpG z57??03vW4Ul+`2h8qPTS{pHC?Ho+Y|pR2nGJX_{KcyK3oNCzFDnn3gg&Jh;(H5Vu5 z5%h+Sv5=H4w10SOYCIr)+vz>&#LSL+d^3LM0+EF((~uQG*akpQ_qauV30VuzcF}#J z!y@kSnd?5TXsau2Cs5dOdM+M_srVH9RCWZS6S&jT^Z8W>Mw-)PxuMwBbxExU&i9Kj zNq98hamj^8o%n$5FZ)e8*?()SV*^smBz!3ePG0L%4@(Jychfzf^)=}fmoJANY9XKu zs$ALHqxK4o+XPQ<1i^IcsMP_^I`I6cekma)Q3pf=h7nUhQL$T4-aXIs(1llEr*2I= zY=94GoqU^mOKEOP9`O3TNhaE1HUMVU5G@(LWshJHHRsF{{U^~u1qqp15^?hi#Nc$% zFa)8J?oG1L>a5V3%8wgHitfKdsOtE$<^ec${}=xQzi#8dy5`~W1CtCy34eOVNQM5{7;N8-ajavx%8(nwEzQEGl_(^OLaMfg zcvrw>G3!^N-8Cs^(v3altx|0UhEp#NVKDWk2{Vr)q-TiRay*gQ@J^yfIdTH;pOdaq zuEHFNIt!Xs(f}oo%6yKZ@@RF9<2D!k3`MCV>@1VWu>@&_HZS_0Pa=W0gjiBKXW8?z z*x&zjQKvu(v(87cyz2A#E!{m~#(m;obi$~|i`KB#Dr)zQQ+Mfs z1;X>wz9xv2Z)pAXD%p`art$V`H&gSC3olErm@#ka>xyLq~ zoLpvlDqe|1CVedu5UPy>%TMgY3!qEM(d)8*cKjZ>k=uQa@KX5sYQ?}gCLJxvw?dfD z@}KV^?>;+qrf+S9ZqF!)A^0b6)n{6DRoHGii=uYT`W@}K6O@fEX>qb_Y} zhy{cWk@UX$=vs5>>Y0rc>ztmcqDnJTZt-ioS21B;@;;jb`r_!5vZyU2h<^jV&D@Us{FXsHc>qRl96mYG6)`bT7m9lz}iga4I!OHo+{*V zIROHf)8kelTTxmPgeoeR3P_gqH`1!Lx@wMBrn3g4nv+nlRFq?dni_!Dv<}6;Vs$={ zwH2r?I`<%h06vlRZ9Hea-mtfOvp;n0xYdc^g%^XdE9`p}a7DsZ^jMx8$R_)J&`Zr5 zr28sNM2C(W2LsaeV2_~X+Lxo6SOOg!m4ZrrgrsaQp-Ger0K!zPp5O?Ke4a!Iy%Sl1 zyX+Ze4es0IFI&f7pg{CZ(Zyjf@IgGc_TnrTNQaFlyX!iDN0w!C+7FTT_R1TBzwvKl z?uEr=$RR0N5*KU|Y|u^k#4|M!>BlvQdakS?ED{F+Q7^!f6tHU0W#9MBgJ?r z`A^#-U&9FfSOCllYI)E1PBEXoH+a?wKi9CMY0_8t2Dnxhh=e>4gIq?`RZmzNbY&FV zQ(!|T0{*vHL)-4%XA|hN}oq;%GxUw^LGqE zrWCRD^pyFW$)}igy>8qL2mr6)(h6=Sb3iop8G&_bu6IJp)vpu)S`qU*}^4q~s=^kreQl2fE7UE>43ez&)1%Fht?-qaY z-({7ym`T<6H&8ib5WI11(DR5mwtn42Go$ZxjJF8+Ae)w?JUR6mht2QjwNn(kjVQ67}MC3Ac7 z(OwkC4eOsL+9=263jTS$Hxh;#1PnkNN@)@1T#cc})5KptHz(K(xiETNnJydU&CN4b zR(`eDjHdai$QD-|rNSKzX6A)MLujNR6b-BiMis z_(OQ{mp>^DHyEuOi4PdpXFFpxxff0HREX}vKZ>D876T+@M{ujoQ&YaLo~yl{9Kk){ zJu>wz(I}Mv;@QZ&_6r5OR_oN}yhRvIilIMU-KgA_a*=-|4z1=O6W4H(ZOh5ZwZ{l} z^yy0m%ozBr)e!4;Z zR#+q`V2s+>+27!A%akQPN-3J$&3YS440L5+xkq{1M*dFozs!YdcS=sKVec&ht*+U_ z4a=XS%fi;v;#8ZfW;0H@S7nk6efuZ3zo&k*47wP)#k$NEs$wVxlo*UBOls!*`NsQ; z>5;yLDVbr~e9tP5uCcwmbC{@^#VNdIC5If(jv=X9=X;i`a_fdB>YSx=fr;>JP^IWSOd&Q#~ zs=GCf+P;beoq|qj7cU2Xovk|H(8wnj>6gKaXh@4<-@`=cia2looR#7o*GS?n$C+(h z#v%XxE?2C%(TI=j9xh#)I>WjaD~%E6_1{F@4_&z>|9(LvcBr-R^FV$h=Yp??>YuL5 zml1_AIsCuwJ)PCX=(s%FdgN1Plrtv+P&lQ-ruDvg?mn06>g*$>#OkUeI(Tz@gN2(A z48u&T{_UD?ES>Q}XQusR+G@$mX#2)g9DH84^sI;TGyev&HZl;M_dyL znx)#WHi&F+c5yz{3JEt-!SO!n2duo#Cw{T; zhR%BR<=J}QyPUkQ1Bz0Wk`k4bRqx;itA9@EpWU{ccy&EoelctN%}i9(;QS@xdJBw& z(4ruB%nk%5CzpJFN+etYWBVQ%F;HLbUKpv&mr8F2@m`K~QFoF>y`?|x=Ra(rDSrS{ zTXJOWYKYCNhW!lv8DG6U>uA>$gRdyk6((Ij=BWWwK6BF`_F9X zZYRw~|Ka(f=VIJL#@3RiTF7p;Rg&{usF)RGaW5k#E=2KHGP^vjE=AJI8PQW8Ij2Fs zEvQ#U$jWF@{QZmgCh!l+@d2I07bC{T z-)?mERqY3r6VANa;;GGjD?+^4j2m)`z#9Br-v}pdX^z7$7XLE0a4566Ev)zBQ~ZSr zMer%nSF)h*6kH*4?P3C$Bv1!vQhbL~>;sKZjQh2Ephq7Z{o&(@4F?(`JXCRNC5@(BDyrhbPeo;!=JE^zrXpZ7uw+ zVd1Dc%TGk8&ehy@-0rB?UC|4nRePk!b*U2=sUucvJBITpOc_8_SPvqxyDR-U%{m_W5y zSxbk-_j0oWD?k2^r)E~hTq(XJyTLqv*Pkc7l%kMQhV|2_ ze`;gjKMSbz_v2radc``-2H1kx!>sD3nysc~Ni%jC`5^f|x164_VN!-Gh> zmVRV)ox1&|H#9ANC~VJ|G8**4)%J+ike)>@cS$zm51HTq@`pCMF*7Af*YC|j2v&P4?W1W}mDQ z2VIprie@J)=FeHCOw%%&0!iX34yujA#p+fRvN z_B7o&W!k`76}xM&^3c4arL9S=G%f8_Vxz5-8Uq0+JMWV{4_AI$+WY4GNb4VYb>I;> z1^XFQDI8V&N1oM!;njA5_7}%mkJE-42826*ds7-B_^~d5Ngh@+^4k>5dKyhVM;u@GLiiovBP(GrdH2v9M?MC1m!}Vq-Y0r`DyEK z*zF2bxF5@E!7qkbcVJ4h(QPciW-3yyi+vceTcCAR6SIq%+QoUg1bP(Gthc$v=vy0P z%xA}>91$DasL;X^H_+hb=F!_rr8XOFf3JgMrn2O#TR@LmFwcnZ#>#FL zBWa@q(E5HL-Ae5n|JethuXU&Xl&HgZyx!hVyjiC|T`$uTjE*mIuey>`LI(O7g+kr* z*Z(jXYe}3sSgR=ouQvv`$B)i-%XdaJjlb0DixUm`7l24nx-U?1-x|Ug z;By?(+`wXDd`b#(CMKbhcQ-3Pr*3zi2Do^w3G%@lAVA5C#3B_N951XQ?|Ri=i`aB) zt<~k7KAT1(3NW;+H>^O5<`=8VGOk`YMY_?a782VSza~GY!anf9YCt5#V(0#SGyq@G z5BgKWxDvFdj!u%za=yXipVtvIi;Qt6!yBBm@0_ozYf{$9E%0JhQIR_!C+xFzb6yMX z@E;{+9-cJN^$yG7)nGJEo5eK9G2G;;B1)F81Q+yvOjvt|4V<`yKIJqvt<1Q@t;x-P z9+;?CHuTNu8p~R9fd7TAi}ULKk*+65!Rcb__^^BYta3Q|&oVlmi9Qu7p`CRgXg=v& z6b3QVyY@GoxqbZ)D(fLYh3^iUtyLPG4i&whx2cVL<}FoY(pTHoQ20U~c;)RwjidS5 z0rPr(x4)6JZ2hD+(VG{I(Tttos-)u9fc=xBB>6jyvI?i?ZG+$NYiv~$vvl{DQ98?y zD$Cw9TKD+~r$a!E-~|6@wX0Ji^fHIDSWWJ$bX!i>?;o-L2c|SO6YjG8l8?P|kv`M# zHXmKwPvzzK!T?+6W^-VD1ZD@PB`=8!+1%c`phQe`t-|SQdk&woGsLZ>FzVWF0G6tc z(}4|vn6i=XkIq?uKsQ)m!aYW2s{G-2e{PTt5GEf`zxspq!wp{zf`B1rn#SH(Z$#`I2gY<hT&TLox!F{PLQg@@HqWiLJ z4k1JI13K6T_V&WevrbT>ZtV<5gyed&?q&?0LoZ|-6T7VLnx9-%?wA}Iu)0TY3`XSu zKS?1?-;g@FR;CR;g>y-0bd|S95V|`8;Z$Su?OlA6!-}4rC+hKV@_pZK-!|B5_Xf`KVrDo$iLb6Pf*Y9_$<(zPtXDIjndV3ta=O>zfbvZ1%U$2uIzK>RJedDfvBwp;w5yIbr zv!P04&T;kTpYTFraHRC+1Zzl4c1sxGs=)`7rARdqQy@gF?5IdMnP9HQj4#Bd_e-n_j3=nfCwVk;v10ScamC-Kye%7;~Q36r|U&l5qq5Jep;! zR>w~eAs3uADe_$~2|YzJB!3yIja0{~{X z%AowtnKXMoW9kF8dQh`JyJ(X`@z7)5Li2ai1CWD73Ed#;PI~Qp)x0#jgRDGvuhF9j z&Kiu}q@I|tLM`{r6HHzYfJEV&`#E2eszOO)9tO0{YCy%m0!w}Poe-<#Kl(|lV^Hu^ zcZ1GlU~0df=20>x5~dLQev6K-H?@XIt^GD=Zaj=2{Ez3$0EUFP=So%;7i8fK7p{4< z&cn&dBvx*;!vP;x2jpOb>wM30Y)Y2`{|3I3aUaKOfyRw1K9Yu|mK#dn?qULuo3vP; zbAMx>T(hmsQlKIJ%ci6o;dkX&QJnF(P4bI{b#G>JuG)c%Xo8V?gd0?Io$Vjy{pvPC za;TSmEa_9Z3e?YC7`g#jGIcr8UGvv}x}o4zx|LPBKZyAXOZ1S1sID>b!4|8V1ILI! zLavHQO7UJ`K16-wNi-z;4|63d#bc|kt#L(72tD!W35)`5uqNt&&*+{yr}C z42MLX+Q}=2JMh<=w@kQpmQW^uJaOp!2WA5zomDZ+Ay2u0ACue#W1?!9_5quD-WFZ_ zQ;2j*!Q?-rDd+D90+)Iw_Uz^$!jVYtzzO@aBXUfCI@L(nt@0G~PH$=$bTw zXV2^LlJZ_m9-1&&AfRcMJiTi3E!5({&_xEEYC3*$rqUjTa*-*Y5^wMJ4dRVb~a_|6{J3k9$2x<_c1to5Hb(1L*=H+e~Wcm=F zOlL@YWP@O1Xdol z1$c9x;V}$fBx}fP&M$DrjsM!641-7P;eW2^Bt-Qx#LvB+yE_DyPk7>dEBCqqt{Po` z$Hk}3aSF!mG+_q#Y*s>6#K3ist2{OD4~7XIkr$jG&=5{q0B5tf@~m{#-FsQ{7M-)zqVqDp6FmPG&XtLe2tZl0cmLYLD-z zUbp<@V5ZK5n*=fecLhsN{W}M!yv6SNkJxjGqW0N-H1c&X$agF#?f{8%Ly`3%e72@a{4^Ul*E<-?y~tEABgfua{uRk&B?Hds+3#V$F;gU*xhEZ z+Od2toIvQ?I)J|Xrq6%1WO_{i$kjF9Ii4ye%!y$Yu~tC8p~Us=${?i%Al2zL_Xl>lMk*!*{5kPT}zpS!hDDccCY zibsdg^2hFY6yj>q-h5NZR;adPFT7X-O9?sfG_)I#Ri9moG6-LVlQ!32 zGuhARhVj5hUMJUG^NkifPu}_M=I;Z}h&nL@`&jZF61Q3U1J#QVx;_J&zw=Yg8R#h_ zjo}~2Qhr%o4@JT$69zq3{#tQeoa-BTf+u;Lcv>ufi7&Py0a-DONEeyJnE;1wDdo{*(A`^|`dA;wJ8R z#uzLIu2->S0;0oOa{ezm%&n(3w9_LvL<)hguXK$vAcyNYiJT37o943n`s9!7)Tgiv z!|9l$(pwDDM!!)iq$$myd#4V)^!?jbkZ9al=i>KS2Wsx~x(K!gdOpAp72kicc81Vt0Mpu(fZZza3}iW*QePnKVRs7Ee%5o zgyth98L=m*$8gO>N#k>GVc)OpzLj7kz9?NkeAYRNLEIhTB#qdn!F})IZA)-1F0uOL z1NEVL_E9l&J026)F#;mDx~;<(yJ!wH4FxNc$STbX@MUs@B<3uK`^s!?Wpf-netD z*!73Ek8RGsElrtqwzzL$?mkx3JT}$azS^^ATWA}F7EE0dU~BzGTsx#3K4Mzwcyji@ zK76cy!GlT2x?2Xxx5u~Jig9z=jA5C18s9(8SyNnnk-w(v>OjN(`nqA$oWa`^KwC-< z@Cjn6oe650zVdooqMo<%8T;OE1n5jMZjBgKvy{F{>$myRjnFSylBv|sBis1Xe*$$i zXF47xTM3E|jt~T0Jdu{zys@Rq;_P1D#J|jE-)&3Xb0FFIgq}Wg$>}3(c zW3|{PL4IRWXuqu;GD!jpQ$9~i;?x`coHMtxV%lu2+liWmEA2$SX+%gDlSvPpI5Wzl zJ6|(}1|gIu$Nv@I=fs>*9%C79%ojtSRL0sro9wFhG@N@jFkvkhs8j!NQ~xc|P0`FY z_0UhDukWW9{N)$5=`I8g}j)CFj|v$W0gT>vhFc+kBJq${Z_lXa}qUrp!H&a3Na7t4T;kJz}PS zL;fj{ZD39$PnR;zdHMnt$D^zc!()9e@`KqU z-`2-9(RJbjvvR?xIgrHDwNS@q?i6k+`HqOVeX`^-8i&jS3QV)XsAjpef{_{?V^OY=w(FATaXUR|C<&+*e@ z)h;&I;Upmv5ou}?VvL@frpteuOw+ht8K-O@5SL(Goz5o}am;0sSxuas<2l2~hn^+OWi_iKV)=f-nBbMvVzxJWE52IMIo!*(( z*2-mDTZ`*MKbBVzr#baMQ?$0J^^+!(2WLKenH$f(6_1Bw-GYegVbx;?+huw)RuSbK z59C?eS$mlGdJ0}+gw%s%4<_N%Vl6y6sgLt7>7n-+;A2|PkUmX;;z7H{vc>9V6~mC; z2*z$p%Vya4Eg3YzBkWO{aMx}UVf}KuLMh8B7W+t6V(KpEgdL9RbC{XZyHsCTp)b;U zTd!k-;Hq`|!rpt%-J;Uy4E9mA+cceuom$r^4DK|`=fU5WVU)|$A?uDepPOn#9ohaw z^cd~zwhKWhX(_7mi{KQ>Emspua|^94O5m3mx1Zm79{-qxU2a6gViXj)C2jK9LUp=i zxk`P0WX;#n zeUfG8?egv)(HaRQo*M*j-g+_e#!QbN-K5Z+3okV5GnFPQokBCW1C$|qLZ=_c#!beN zx-J5efK~5JSntrKAbPmkE77tmxhEIvjQ#9B@N!>A{G;P8c2~JTHC3y*Evej#;Qnhq z{Y>CWG5=}C6~2t2H*A`(JL35-1swqFV3ytIQm!^a!9cKEs5wb&JCyuExqGScu4TuI z_r`Z6T{s%Jt695f9-~kdO{%Fb^am_+1BY=@0q>(6t)N)WkY47bCb^`Z*YBk>Q-|_4 z7s$k~M5FxX2FatlGqRL;uAv8ull#<37=MG+(@#-L9Rj40cm2Jf%K9T>wl3QOY2bN= zX7l%=sAno6Rv#BMa2Y>%62w#8xCYwY{9_@6(eeO?UVN&lw1T-UaUVu)dBakt_!Da` zP+t|gjU*;iza^NITea^i(p~@IAzW{OG%#@72niRvU!peubj?Hs(ax1>NG4KDUG6N> zMdkDP?gbTV7m7laaymT*%6XHsrlW4ZVV2`hpIi%8EZFThgJk{)z}?(9F?sZXUX-zIf^7cllP9z1;OvQ~ed5CsnYn%gY=B`R+$^A)t&lL_+80fx;3V3kK9I z1)pQ@C5yAZf8UdY%Jfs{)1`i|kcEohfnn~Pxm1ZCC*)M^9nm)4D=J7`QVlrci~V46 zvq?hC7Krq2i1)TJP4#FHk;%bal@Vo5x;{F7&n{$uUELAin}R{M{j*)ggH8UgoZODCEqi+kMjg#(5r zdIbjw2Du)2hRR$#D;#-b&+kPR!v~X?-g%6oW2kSDbK*^FkvH4!h3N|#5&FvQ<0{=j z%Abp;pn!z`s2>0hcXIH(%Hc(S6A@AC-Pd*Jd;^v?hd_^r1hA~W6Sx< z$z5{%Zp{xqCBg*{09`(2A7;)-+fd05fp*EgSG->_WiAw^!&igRO#$0ST#jqS>G&?% z$u&)I8~H32>-z<$9=PsRQTFm8Bvg@PV{y}PyA#X{#22q%EmS|M*20AuF#&?`McwS%)(b(uErqR$E!kKAHXo5@k0Gt>+MWi{(Asxt zJO?AXUrU@T5xw$L0-+`RM%Cjtx2DT}(D!}*M^_})hti8Q!bRu@`ADuAH>9vqHt>Kw zi}I{``xYW94X}d-rnD{0HXntMUaI22_J|EqOJQVr0Qrooa>KA95=dB-x{CCE^)FH71*R z8ji+gR>cfbq2~9^938?jj~F*WoH2iLxOD4cq-iQ6UrnIm0J!(oW`exbciE93-;V~= zo-#yrY+7blIzvef5DgwO=n?hdN*6ACKdr1A`5T}Dl#l8lTdU`u*IBxqyr68g_UX?P zUJ0rzm2s(Aw~WULyeQWYoW;VyXpe~;ndis}m7vk*eb$U@ly%oGG3bO+Zg$kT#pZMH<8sqNaJ@xv|;)KxMu#o7v(uxtDD` zt3Uh)!vMB{G=exmuI8V!ry9mqrp+sJZG+JZ10=E}< zxhxa(jt@u!OD4CA3rx)_hxt7cGRgk+_brYx%G*LbR9qd*Nvuvl-@%_o(nJ<|we$-o z?ka4(ax464@519Ht!Hzuc=^qo*8$~#IZU15pdr+T(Lmj>%rVAM-b61^Yk%|l(R1|j z*?!Ly`vem`7kKSNj^L@>3hS)F8J$IJ){(6iMe1k^#VFg_UfF>lwBRfm?2l}TlX?3AP zWyyP=Jaws!HD?2LxXO^Xw039ZFZORh4tR{5Q5g&$ojcQ0aTNn? zkRXL}NLofQ|PFx#NLwqbU5o(SP z#=m$Cq$G7bV7w^`zuuhpC(^1~+brjC)eX4vX!S*&=3;Oh--BkI?sDyCM_=1E`T|st zcss>n<@MKiAniLj*)r(Y7oBox9#78Lcc7)@+vO^m0ujWJ{(B@ovguL?5E3Kh&~6(K z2`-pXPF5j?ePP=-N4CDnc2=~}HY(PZPeAw=MD_25LaP%5u1NW-KVI3-_qnv6x8pas=s8isD~3g??M%9BizRs zddeCm2N&lp1ovov25wv)Q@EoV`jVsJCjNr$E@NZhSTwRwK&iN>Os2dkkr6HWlb`E- z&XQlL#3`U|cHrclgf!xm#1nqHS~Shr0JZ56qX6^^b2n4#)nWRmzi|Pj&{W;n>^z`*q>H%r z5yPJ+l7IT6;VnsoQc$sTJc2hUnzUFAiY+=IeooxHv^3)|~J9 zr?x{xR(eoDgNgOvXq!7`(kHz&seZSFj-GU^$kb=o6K}iZ$ZHPT?#!gZZ$likqtA;- zBwvfOBfp$H@uO4vPZ|t`bI1Z=os}6v)^!W% z%AXquT#>bgy|%|J-qo4XnfD)KjV7$nf~weYwkZSg8&mJU8^B6Z*~Y!sqzaD+dq+n_ zb%puel@E!2P;dyh1JB?0bF3npuE!)paXC(L{APe$t zzFS!Vi%u%({ceBKN2j{KZI;O`yDEeFSX;ij7o6!()KEPw_Zaf!eCZcYBiBD>mGScF zSPQw?{r0ez_;WQupGx-|fQVy@f*B zoAjZq=|inmGo(e(2QSGgRD2v~dM^5{Tk)|r^{Icw9CG}Y3)-o6KHJodc)QxFrmsEW zaiDjndRKM0t>m;W%-np-V^)-yx}vB&`j0M>mntTkE$2$Kbd$m~>-=AR!LW69D_8`W zVLRRZ`qi-n-A1=V-90KKZ@g-ud~AJQ*6xVaEL zVkct0dtX=^l}qxho6Nzb0(r6Olj{}`R+KB6+g1JQmW<^;x|^;RRk0pf4Zx6`59-u&EHc}(R(WZY2K2uaT#4*87Ts4 zBUMb_q&DeOkUxJ=9%R1zB0YmwyDRBL7fSFEL+<@&UFSmS;q>_;$D<8I{rMOm6RB=z?Z^V} zB71SD#gtJ5>O9>NbMZf~0SSS_HEA>L8z(0Q!p2rOHT9`qz01t=#x)Mm?${A76q6Eo zys1AdWwy7 z!8P-;?Ra*11-3Tc634c!QkIyaFur}y{l9bE>$RpqT#ut?ei-k{Q@D2hnj0=oyXF7% zHwEH__Rjv%o!z81BPq6@czmBs)Lf%Smh#_`?V|CYX39b$FvB+g=v-Ywc!w6f?#`@> z3Fr!>F+Vaqf9Av+9kjhMY**qhGzX7Cx|B}KC4N7SH;ftAEgyN^d76Kpu&{oEgNUvr zF%RctRtjdi<%IxtDJDYigVqX&hD@oey+}1a6yKyO&xM**D1pNtWKH~Rbw{4=7E(~V zLK}<0z*zk1#h{HtO{!-42K!Z6?7|1MB(hw?M9C>-`~TvR_svub=R(nLE_sZ+@7hM2 zjCF?|#+Pa@5SQg%A>o;isxwco^Fn~7ipQPFx1@>BJd^|#XCP1 zic5;Kt%Ebp#;$(XrB$Xnw+%7vn7SNs9R19Hq{p=4NPj_8OE8_m7oUz*hgFWG=-+;G z=94B;=K@iDd|81%PF3V7=dH4W0%7E=59coqfe+h|^jf3M-CcJ5vZ_5Fk=Mz_Z=Eb< z&^;hUy3Gsx2Zb!CMs31<>k?vjs&Xi?;!I@$@OP%2*F^S@uE9cjd9PGBmi*ua))KLQ zZ*{qEj;15)H(1RpIFXZzD^aF-$g9JEG96xWtP<-40q13M;*<&#k{f-6=8UtSWWCiQ}0l5}sQ# z6c=*fy((?iMH{5fp77#gajA?-rz1c%@W}OG7TsSt`FlY6KyHXk1C6y|k>y1b{02UD z#S@iH%+>~cDL;PLMr4eiG0g79s7t`ZRldGBUH6CaJZV>O^bv|7)tP?Xv*^zMqutCk zoVtJp^2_N?6R64o%A+_DK-t2bo45omnC&BgfzSWujHGt&G#}4fVCf$**1KJ48H%HV z@FCA$l)QUqzgm}}GxwL_Z@I&sa%ec4iU_F)aTgUFa_Vmh!4ppg3LFV2T**)!Eeo z@H4uL^X*(N7|j^&NdwY&v#tWm9%B+UPe5i){}trV;H2d^X3gr7oUM zCN4);dFS5qoKm@ARu1swkha zR-b+gkwe-HlB@P*8A~PSVju^f%rRE^qW|b-RGi*l2sABwy5@%=IHg)p299Ql>kAJu z+fWmLPPO&xpc=K~L3px$$eK>3Sj=x4empv4%whmd2{^X?(SN;;SjC!)tb~5leA6BC z`or;fs@p6l|4ze3UvEe19q()8-4S-(V~MkLuiGLNK__4MVNiDa4CPdW%zG@jmC8$#VUI3Z2(Sj9 zCREX8%uSw5llJ#-+JxMPy(VAwdl?1NsSHUM3BZ(9W(NFrMR!xXP`hiNbiefGwNv}0 zPq*v9oMJdH7(m-jC{2w{sagLckPNn^>CHCl^^&)mp%%`@bzvu{NU>*<(?r4=Abcvo zvSs6#K5R?O}hRMr9ppGRM(+nl`%ulyL(W?n;hUqqes4`8hxqVK25i;Fz4~ zkJ0D_(i5hAhSH;-c{;Or+am%TUkQE_e4%>fxZ$`!6Z+#gwV3N5%TIg*j2u^1x}qe1 zrmTYi^1k!25nr~jE|usp96j6KHR;fo1EJ<#OQU8D zp8KA23U#XTKiiY1f_BGgx7{c#|LDRZj!}Zyc>ynvAQYI^Vxf@C?<8^9(~VXWmIUxjsYr?mjP%uQFo734}yZC-OOH5F5+sn z&1;_c-SYSr-JZD)DU_Tn@_ZO03;IXr?VB%P&L8gq0>cxROZCiiO|gktD=OFd7aAtf zlxO2AB2>=ydEPr_C7A^}1(TJvPh@3wM{Rvm zM)Ga*^*RsKd6Bw1MwIu*oKz=3NTWu-qhhf~vZBY;!-c1&9OERbS*OkR%((tznjUw{ z0eVk0lnaVTU1&>KFp4StcC6lf*NOloB-#(26nTDA)ST9p#GFg6=6<*SH&Zq<{eF5u zH}BC`StSRt`zvHXgF&{)cT7-pA9@;gIqgBuv-wk|@ut7rRq1xu0PQbA;7Y7`%gdki zbRJ6H`8jXvo&eWIj8P(I2xK8oTB5gqXNzc~7pZ!On8o!gcSJl+e6t(3Q}V2Z_Z&@P zLC{6KGKeuhfi{t1>FpRry>;DZPh#sB4Eo7QK9fi(1QqwC$o|l?8h|ft1R!V28k##{ zYym1lS(Q-@;_G)f0u)tP+bv-ERG?lAyX{XCns14{ElwVSCXDY+rW~H*6keiL5?3!g z!)?*9xk|%EUIEKVxPqT&6r}B<(WGgU+Vx$ZV+gZ9>L_MNj;J6AHdX!wN{p$YW0D60 zjbepFGx4)$#@%5P=%)BVnCj5A;NDyvQ2#w~kr6dfS5u|L=n{cyKjBiWan?lF?KhtF zAvxo!c2dpo`&~VKv$NKx!R@jKBk+x36^6-W)z?Es1WJf8s?i0{pL6`mYNy2_B-1u; z10@W?g^Er&UJ4KRMduC&nJBi~BrE`#$$d2rc{J}qakw~tMJ3L&A0dA0&d7yCUsw|X zn6AEG)L%BpqNP%7DhoRKQ1~m#jl6Zgm(FW*s}h*Qc4Sjv(1Hml9+ynS8Ml|@;cqmB)jggVL6Ds)kTKei_)|!OA5<^7rRKiZuI*&A?h|6S}xyzDfb`!3-1%R zSs<;lw0Ym3YP9Q0dpfX5V4G~cKH6h3gAW-g*Ser`oxQ8atCH^9ySkCL1VJnw)8^oe z@-1p#CdH)hC^H9&mx}vb&qpA{x=>y{6XjfoE5k!|4?Zk|wWV8SYyPNXSK4$!)RD+> zY@M9upxynxM$GKSCgMDo$ckzT&fB;BR9@S2@s;T11mm5j@eXrciQrpcD@ zqZFf--FMHF#fC7XGJ+!rN<{zSF3d}NZPyi}=(-h5rrtevG-5jI%D4}qKOSx*T;Ih- znpsp8mqIR84{u&Rw-<4KO=tBtcmF-R4&X+8WEs*|1zk|?2P8X8G)*a+!r)8;f|QN5 zPD{MdSC8XGfmn!Q74|1K)iSqPRDveK7i~#D;LV!p1}AItZ|#elBYP4!;u~J|lL2Ux z3BJ?|UbL4Jd-RX4&FGykFZNRl>MBipSjBqYnpwMQX!GqZxENnX| zVT{D*+t_!7?h$vbr$T8wppK7{qh#)c9jEg}Hz0SE>!xU3w|xYH2NO>`J&lTkH?vM6 z9lMIgA64UeKWWhui;-I{>~}Z$*UIthocc^zdPQ-2P#zZ{p#3^?^iOR(U$~h8U1_=Ib%(6W)b_ys3W<|{bP}|y|LBsJJVV-0OeF#iJj{bj@CLG`+ugSI zQsLicY2y(gW4sJV`JGG+EKnuF+6{)5YHS^MESubyzLbgoo=4VyfBY>@r2&0Ja2%X2vgGH7u9t#oLI29iK+TUe9+n~+Y%LdKIik$G|RZm%jUMP z0d_|x$qR*g_>+~@rPwW0Ii!i3aUn6h|kbx062; zW#k8RPj4IOTqJ*1?!-hzaJoIm>`qHu5W4@Q#cQ_Ibq_uvK7eX+@c*$3wJqryG z9K`%Ku7LTz*X=wiE!Yyk>}i5eV!swjmn_Ho?ZB*1p~%ZY#-}dRr;(u*?he;3+G-U> z?78o?o}$lqdJ%9Df9+;<_t>hUbw^C;GJEIA)6G7GB~M{;>Bf&8ilVstHj-mLwKvM) zAKi;gTVR-gS-xc4hy?z6|5?z4)L=;Ku`tAU&{}1-$s1VV+Vt@y9Oqu*jWbSN@ z^dyxxcXtK0f`uq&cK_(q$ww7^Ij4!VbFg00ApLha)--sy_0JgsyJW!%pp-{ z3iI)YQjPD&;PsX>j#2SQ%a%A@#~EnjK1gidq}i2hr>Hd_gn;DY*i%y!Qdi)01heMg zEjfoEyJC%>mW?vXOX$rjsR{QZ?Yme1i<17Z*$UUIi1{3DY%-de#NNPkCWEv(t-wp{ zDz~UzZWt6>!dFI!C@avCyi;ZQ&S4y;=i}R%!2~8429keV)am^0d|mpa)FIt1l`2({&BA`h)hV@D28(t#H)$XpZaW_cQkfs=I37BJQ@G^6I=f#|^Y%wsWcKYXBt6ikLQW%S zy1V)<8NA~v^w}i;$d|vqPC%wsaj$ysXJgXbLwB+?#A+g)jv^#~7ps4UT&8LLAB1l$ z)acY$o7)iC;JuyODw6{3kv8(xHmZ5(-?a^fFOb^$)YjbYz(liM_^SOE`+G%Qgc4(; zM1VTX3w%KI{$v!uy2WZs?TWi9_n*Q!E2mNub)`0i{0DC+2*Rfo=64}-Aw$5Kdv@I= zgnn3!p(#9@*nZmrUxx9wgT#8w_=E3lsWK_Oi!!Z6HOc_s(_%Qq0d2F(+amJ0R3%`c zy92X!3cEkbGjrqlkY>$^InOidP>s6qyLQMA{$aZv+KfBIDGYw7_or>P`^)}b6jW{L zHLg&0NFWil$|;R?04`{_76bz6i%6&e%nwiH99l=XvD%>OnQCRQptEm<$7A%D-_*0O zi6)v(`!5Qw5pnL$J>vD%wqIOq&CPAUNF=&dZ@!-ND7fvx-XK&;V<<#9C7`<_6tan- zr!B1(j};Y67lpD~5vlq$s+261#4kTx%vrikeP36D+J!D@d3yB)`kqgkb*`Od{azs@ zM=EM z+U(J&WkNW)#&B&OdZ-V2-#62z-|pz6(_06#!#+hZkJrd@k6Z-koY|5OC*U>#~)y)dn%g_aprZra~rQBU@(X5W9dE&{;1}4@sO* zR=x?7#+gCuVXc68FGE!u$kvna!x^3g%AIumm8vU$XJE@Yd69g|dfcZpEV})^qJEml z>D!S2_z%HcyJ2Y6YN5kIG31PwMB>+I!?75^fc{2-^9g_|5_pLfHYt1cvNlZl=ZkQW zY0tG%PGW_eZk%6TQy z&Ht6Nar~a{ySTu2$AgqCnTOj9&G!|E!a9@+@jb@d4?T3Z$B!#!vM7u{YS__0ts`;1 z7dFuCCA77G5eW$G5`}kfMreFNU=6i*0Yl;PG5g|nnEIX4Qv3txinJ(>ZO2T9B6b$f z|MB_zC%-BSvfUodp_>TfW3uTu;k-xo8Cq&j@yaJ&xFzS4&h5=jPy;qs-+#Vh-_i}f zx6sm+ORvD|f6LE%x&9iHl7G<8$viArp==T=YJyfBjvOrR2kgUCIhr0}ci}j(B`|oj zEsI}2K)L%YYOKKl$OgH!Kzbkit%Loe!iia204ot`4vfj+tVrkKEvP7*rI{*24Wj18 ziJ2&X`3NtwX8ZPEq$yu>^5R(_q~dCbKUJ~Ve$213_x?po{(d@&Uf60O75UQQ*Faqg zlVE*7Re{T#nN&1UwmH7+mt|kP%7L=Ut1EBrumM% z$?nmI1Kfb1TeQBuM|roczcD`Y(?2@hy>F=>1V@ddw$u{(Xuy-C*xzW*D4Or)X)0*+ zTP+@^6}_>=ks<8{|CP0;()+Wn_Dz-B>ZaoY$6fM@;}@%~ld9YvV2E&jvAg-ghEm|T zvPXr*WPN@10;@;V7>>st%H{IzbIwUZj3Q%3P};Z(FnI2dH|UE<4(51GDOR4E;uZ3j znCERZ3JZibYvz#5u}!ICzGf19DVz%Z3Ag$gC0W=)E-Q+3&P5!k16YkRfanekC|K37 z3&naOf5yz>{O{Kqn6NRt*hW8w#k>-nE?>z=dt2W&^H3&fqX$g+v(Eda!3m6|_BnWd zvz6!GFgp^REQA8-xitnAa@KeK4co+iPfGc?1M@-Os^U~|n$`Wd8U^=^&__aoBr9Y3*T;m4jPU6#u9P=izFtz~ds48|QT^h2Ne*)I zkXFDMl)oIaU<7bY-Q27GlzArc3U5H_;{p^`_w9!_;W=oeotuof`B^{TpKoz;y0qtq zt^Tx08GETpuPp+R&T{sJ@eDR}SzeOhS&~y6K7t5NX?Rfe(y7~!X zza``!9l>i~R`dEnx5uUn=Zh~})&o*j+F0!;G0y^$*T>gil!c1{Q?5EyWaQwb^OGdjvo}H0P z>V)vBDUqQ&{WItb=6atIsy<~ei@}NQfQ_7rpJr?`~zZ-*27ag z3%jK4^mfc5y`S=4#Zc-1T!M!FxKvOto=ezTAD2v7SO zzdUUjBi#!wi=D5nrmA$6LdiJ`5(iE|6A`$T71n&uI_F*d`b_eJbhTxuMc)j&+vmx2 zFlb7G?~UOyW8Dh4Z7}}ib#%T}dB@l|BlS-tEIgv2Pw&6CU(R!0P&wmzEpo5AY(Ezx zCY7QK9S2Rrz7-7J~iwb&=;oZIEtt59IF6{WpIz*I)LM4XBOR&tA-1 zdNKZ7ie?eYpB5k;F3uDP`dr+5gC*3w!4zJTe_T+sWl|yVaLhKN!>wFMcMT z>{;d>iR>3nb!3$xS5}lP=W(LsKwDF$Zlz)nK6Pwz>{>Vy+&5xdiPoBwYe~Bg+2_Oa);nqUQFFfc&8+y&adQ> z6KOK9*hy--xMl2!f%R^{r5@21GQnPX?1_S6o0=6v&5z0SXMKz-nzCKYDUULyUes;9 z-RY9sY9AR@R+z8ER!cUsrngb5;Zo`qy3#D%hQ(4Ou3OC_m=nG z!<>;-@C7GP{4FJr3v1r+YpLJ@U5+Z5s#U3rX zCGNrNj)yVUl#Oi8nKXM060tqI?F=OjPU!}OxrY03-Fr*%zfT{Y*Ebtl(7nYgx0+y1 zGSQGKnf>a(n??@2X4=IIwB-Iq3!|kIvMw@zY-Z%C-1Va~8Gx2!*`-JP`(@=s22hON zfy($8J6relR1VvOkb$*=;r8XruQ_{C6TfHxb6Nz|ciNy3X)-8t7-N}q*3F<~(IcMz zV*jK<&$w;(;b-yD&O6cm94nI@3%L-`z^?R(Y-mHuBmcU2RE!GayfTWlA-sf5xix$t zz_tb$aE~C55`KKVbjh=sTb;}F7gF*x4-2^w(ia$3R?vwkhOCz93|Qe35Gz*&Za&}s zMStzv3hZ3d?pRfbghe}0g%g2a-WdlM(u(j;Tq%o#HpzU(8&>a2RE~jn5P{I`+t;M0YkTWOd6n49vaP+YncKCAguY@n|W`YTbg zgH&29B)NO&U<^tsME#vXEu@4TQvJI z+2~g$J3l@Pn3s50^F2pZbpDvJI)};7eRXOaYxYy%5~(iJVyFK<)D0Egxl?tss-3e$ zpAr|-)!XdF0lBBOY*$n!9Rl8-*ZIt8IG}w!jR(7m`h}me$y(@+j10<$$#&jzS^3a+ zOPg$T@4CpdhkayDPw8RooeeI~BOI%n3-rvct1QlE^?^{(y5EnEzZs6zDY8)_DxR&& zrRi57k1ICmdtU@kK@WQ2cgsZ#7#$i`=FRT?=0E`4=qg|8QW z1#)rQ6x78`VkX7xEW@;Xzz_`R;jBc@tkgd`@r2#jN&c;)5r7<%*d3-WX?jyiQ$F!X zYq?8znx~l+MzWQUQ~BJn_mEmQ?B}gn_K&`|+-2)E0M?M(Z=q=M|zuI%U0re!|P604Vw= zH$d(LDxw^awATK2eSRbnRHauOkM(%H#N3plE0D4~4ja)@UlU-exH3#nhH20rZa=xP z6%C8>dwlY_2=pN1aSt&Nxw`$rCp_UczX9(}wJ{cc)J<-`^U5QEIU+I{R`NF=YBH?f zs;^ktzWHH~iqMq{o3XCbY7kPF&WAkCAdXkF8Vg$9SW6sdn^NtzsH{*MLbKu5gyWS92+RYJy^w|i6ofbg<4uJj5+=Q~2h-bp_akt|H{mio8M6BgLY3%yq zyQo+?6#OK~o0u&XoNsM;#K=2^{C$~@4msJmLaYz5KkESKJRjBVw$ZbNgfMcw9r$V_|y>;F^qR8I5o=5vgYD}Q)yjFie0ZnFp+ znKHwrti_s^HW}=@wI;Q%8C~*?!7iuZTI%|bAF^*|%@H%1oH2X;cFpp@DisTUI51%msN~c8eLm0cDk?EFPr^>e)1`^0ASoV z+aSI>h+c#X|yKM^%C8|0R{5sE{ zw|HbrUR=7yQpdH#Bt(fi%_rQWJwMHoIAcXhj>x35(&T=VT=%!pJyV}8?swuH>`_}$ z8O*Hh07?=0WcC8eRXseDL7WYOng8()JRt>EvL$%qg5Y_a$T+o5qt{_$A&1Ob9Qi{C9^^GZyGb=fzCBF~ zk#j~dpGnDoI$T$0gSuUJ9J?K-85=G}XD_nP#%ZX{`-tN*q1){F|-w%-jeY=u7q-u zkmF6Nh=RhDMp(2ebjh7$cWPa(b;Blaa?scZiA2}%yIZ7>z+WQxB6#_Z%5pj0Jiu-~ zlZga@)Dq37emf+b4cz?7Q+@4;5VvIKAH|ZOl;IC)U*D#}-5CAyl8eU7@=X2Dpe5g* zL)$N0`*ANKWk}b)V&6D9T^^ZVZvRHjiWR1Da8N3Wrc4|gaMx1E!+cxaKozr<0ZC0 z`mLj<=Ql!F6TEm019?P}j^`=*sIb6X{8rI8xG1x}s{nH^En!h%)rwrY*$S+NRjiKV z7W$wOT|hSxw?M)*^ysv0{G`lz_laPR8>trl%&i&R)fEGHU0WZNZ-rQ`sNao~k69qm z^7}DozkN%hgikjNx%{pzf8E*t`o};-c}DcabJzUPEu7&rOTdNW*1TpDv~BeItm;^* zTaEjWvfRlcwV)@a&R7llhlc4lI=(K}iZ}Qv`gvEX9cx~~-tBl3y(luBd5Wn*ax8SK zUtNz3{`sdWaLJ7>{9b*O)zhLSIf}4GM?25x-w*N8BJDxE{rhNHO9P_iZD6lDYq67_ zk$?!cBR3ZcxWQEb3ZQOmO;6UD%>;czcSII8vFfaAfvrVyxIkbwi1-YprT$`;_v{wWuIhu?m*7EJYM35&|_j1Jjls=hEWZbWql zH0A)x1=u(0TQuw+I=joS>6Fu-QsdgaGE?uUplY%E>dmMaHHl-52O~UeyKKeZn!O$d zy#0SA&!@_GZ7%5MF|b`ePX2lPcYiYw+uN4qQ|G0R;GfoMNxNYd-=1rCsNLUVT7|?H zHN~(wPf6mA+Dulehy&x5Ax#YzHbWGVrUc9$hmQy^)9*y61NoC%r*2bQv%=mn zfO>Un6Ia2;_g>!*Ce`6Q@pJE{DplkcdYu~m4AdeET~kE5nu8{6blrzMbVz0Ie)qH1 z>ySLNuZ-xDG7Uq9XPHCf{L2k2U)Akkuuk*!YWD^;*jk1UjzQCOtHH2 zyf=`6r_o3r@9T2wpqc?BNp67=bW4}RoQc#}Ll^U8yY7PxyA!}pJ}jOYg0KL1XMyet z)urfV`V&31<+f==>np$sYs89F9^aBJy|$i$2}j*$P2b3iecnBg{Zm;lc9=hAqD1qP zi>tTxP0q}xX9GN!YL1nuO2^VoxT6`!=c0|J+WNBjv#tl-|IIf4X9!H*E%2!njh*Z0 z)_yeRE@&e$AL`{MT3%ir5Ou?$(MC&^*>!cUDnt1MdwBw>lR=Rm1md6< z=%V7ue;Ez{<#GY$v{**wWj+@MXADCYl-GKG;#xfSE7(mhRxeVvY2g9GTCR{|RWQ2V zJM&lw_20Hk^^5$XEeA+~L{v~Xx6ZwH$DmZ+;|KrfJ`e_F#+Aapbqn>xO5d3bI#=W0 zPB>Q@H~{v_D`d`~f7?a;P!RK<-A~pEC&AScelW=X#J3Q-x)HoiE_fX`amtX%wE{@- z{A2gQK<#m{cP9;8ENty2*S&&a7;l@G`?=(CjxJ+GuvR?`IOFyD&mA|dt?4H;m~Bo7 zYqDjDPvcC8LV4B!Hu?&{)mte`W9*Ji{vaH4t%iYW~EW;NA zP1){aH7^gN_;Ji_$s@V6fZ!E0aB4NOo!#zrjma<7t?^U(N9UqDKH|N&4(11h3L-SI zupk$;_M-1FlK80!B$Xa*Q@_5kt}t}Rlsr{bsWW3sJ_DT{VUg4}Q@D9U@&>B7rgjWO zKFV;|5u#WE0GZ$1JhKKno3%tUVx3Y!hxv(eji?l2sQ$rM94A-~Qnzm`|M&N7vtbx3 zWMQUGnwCB}zkmRVj8L%F#C-+zDX00UhC64Mj^mrhD4Vjar)lBm1!fFaeYqRt zm=pmG77c%z29#baz$f-T{vSox9nWUlw&~Iq)rHz^DYa|QCQpaGii$0*O(dcAOjRjr zD~h6O)vg&kYSyYfBlf7B1Q8N>zx(?;$?r~bt@ApM_1Ov!?C4B8spy0SnU__TsV0ku zbc1GsN{&WFd8WJfXb(*fgewfX7q3z!SJQKY?Ou+13yaUl8hF6CD>-bw+Fn~lt8(sl z*gefoHq}Ur{J!mq28&P`2sN+HbHPYGaCf;~NHOZt@TEHkj&+~@s3>^6Z=qriBt(%U zIm2KjG-<85f?qO9&u%#7?2YO#5fAIC%5AMx^_U2( zmEVEyGrs+x<&(}gQc8PUK<(naoMkagvL?e;?zu?{P{eN5?A1xGSAAgP`aA#L{0aR< zm4*XonXk>|vC6{Oie2&jU)YqQ7|^^g$Np0nG3v!44emenKET9D)ON!*`YpXy9n

    9}^Dy2K0Jz*YRXF_YgtgZ2!bJ6!#tTp?%PW+HkhGG3o<4zTPXF$g3Hbx@)p_RixZWbYN0dBNU~ z`2^L1@kx0*-$*;4K*a^euU8>+fc{!R?0dIxY*XlsMD2Pmm?VD0vVO5uvy21yOWIA> z3#(`kPB3%duL;=JNDei7%d5{VF3=8*{4*Q!6K^bpKyd%vs(oNT&y$|sX5r-)aE>cK zN&Pl!13DPev-;U*-HiD}wg|0Qsg6q9uTh|Y#qX}ajrb8dca}{XLL-L`#YL9Wa#D&d zM=B45A3~p0AyXUey)P^qsML?Akul9$0w{%k>`%x%*7d*m_^+tz6RzLo4-SlHPvpVT zsV_wuDZm2`UR{Dyy4|P)S{M`;gB98_9T@SCIB-%b+GF#i77s}}@rBjhVyx`9^x$b2g3g=Nr&1Ql#~x6= zJm#g$@3*qp9u7CJTYvY|=3^h^s%|_zU11?hDnyFYr2UdRI5j%W09MOwnjibFuj!2; zP9?g8yYJ}ww)Sjl@a#0kr$4CA3D5mZyF*x;@Zd;+NL4MALLdLF1f|mm)F=K+gp5in!iu5x$T%Lnz%0E=lfY8;flG|DpGL^YGQCv9RgT~-%E$3BQuz5HBmhy%e9y0yEe724PbR>Sm0H`$*e6uV_W)*yGdx5EO zg0DYxpWRhdCfpj^k>xhczsRUx(GD?a0^)d*_c;UlI^HFe@hCcBGbo7ew)5a)^JJ}xZ|{gEaT zKiG?X9WYN3A_0iZhju?G$%GsQU&fZRn@_WC)4PvvVYythKP4~nPPRLP@g54D$i2s_ z0FOsHj=dj|st9u28`FQfv!jJ^%(-MX*ZXK8`E9T#49RVviq9+SzQgf*?p7bC?IXVAJ&w=Te1K-~@j3#mlPfzndUfKHCCKwTdL?%LoHy<&T?-_)3$EN0HzN_pz1mN@Y z?IcG=L5A}~lRCJa!Keiv;9xf+-g#L)+y1jBZ@Ux+RYrek7k2$!X04&9W;Z)!lC>lL zQF9S$;XKT#;+f>}5~tZM5?zRcy>GN^;XoLWA%0A_cWb#T3sWX)Cklw5ZY7IXKfxB zNz2=B&1n#bevx=kHF5bgb6x0S<&?v5-gU;Wr)4G_O@HO9h;g%PpX?AZU?6GQx6MGY z(0wdq&om%-10ufR^JjR+W{6@Q(iZ^jDCg>=iQpa4#V{K#!o^dFOF-^EL|>n0Lgc;j z4UBJ&@#F%qUSz2zOYyTsUC>*qc5-d;9)%W}pDiyn=%hK*o?Ca>zgNXH(Vw_^*nH@I zKCQSOk>oVA-QSAxTg1@_eA+-uEU!0Rz!CDQ8M=ncDKM!?-X>N<$Ze$awH2@e?&E89Do=^i>h8X^{VI+*ynmt5JH>)N%^1=oUioxcBT zyEUR}jz57+)|=dHE(53VMf zJ!B5ey7GJ zHR)EKem|kcTLsKYQsxa9qaOcN^453+XGs;`3{=Fjkm}}2iM#3dvbEpD4#a&knj7L- z-4Om^ntZ)VAlu-pXYGBK_fqpGh32!Lqxh4|%*P)(zJ7g{GDdohk=25$4iVQqk z%iGGoOnB3_X3Et0W~RIlS@A`vH|YY+(-n`x+s3x5+9{4a_tp~xzA9c<;y;_7WaoO@ z;Di+RID~J=yLoXFpklOk6-R<#ou{lTX$SEW&3rY}EB^kod)}vM7d?bxXo77&&D)6G z+-PxLLx|*p41F)%;q>@n<*?_TRLr^QCzqk6l^@Yf`7+YWnYO4qIvoF$-w*VzxOQj# zhRMB5uaK|&GSr}%72r91A(hMD!a&SQ?Z$4!R6@tzZ(F6+(8Z!wSLp13TnTtKLoQK$ z+E2UGDF*Ru#&_$$Ms)sU^?BvXx3Y;fs*gwgqbWY3a0i|UuINT4K~@v&iJwW@lOrB! zMQY%rr_7M#HzVPcYbMyJl&W^R8z{c1a;O$kz~i@_TytOT!Rv;r+w4DYVR#5RQ}0ta z6HSvI#G*B~4;n2WZ}$sWdG{<2ubQ8*OLtO!rq_$gh=?-G8PMJAsL((VgPLstD)AuT zgA$bEeX8|8I;H%kk@cMYY5@Fq1=mXQTv^*B6a;dgdC4H^9=q8!G&ChW&XD^bU3LWa z{eN_+m;D9X?8%crxq`q;cIJF$Sw^wA1Z>93F-v%|u58uAq_KbAi>lqNs(;jpnD?jK z=P8{7w5;q_L66AnE5J!<&PyEDYHIjkrdpaKp}8XXWJE9Nbst)Q=|hR<&LIo+w$M`6 z7gWvPs#QJ173eL$Qmc$BIUYJ+ZR70#I{jlv3N9)p!S~H77lXBkN76>(?UZnE7t48S%V}KEn8~hLO~eaT~A;rTOvE*!le~8jVt4 zHP!lV{I1-yM^i-l$;1!cqDZN4zy+#M&A)Y;dgp(1ufs@x<5xgwFWrh?NJDB@ot?SC*Kj0xeLL1f3VxOI_@53TK?Mb z!aF5~X^x5}FFPZjs39W=_;s69kbCucRtVS5g2 zl#GYou0_T2;kAQ}ts4w}m1VeDSZT3+pEf`~YVMF(ySd<+?&orC9%PrTM8M2le4T|_ zN}w^l)G;&SiiFc(#qcbPm3L#gHpy4G^cnao{JI}6PwnP7&yA1_m{7lAZG0LYNY;}G zRfqgJD=EE2Cp1R0Z|&0aS$Jn03s(c{k-=~199IXbRw&GViYnyII@Dah5zRO(2xCJw za=kp|I2MZ8?{)_RL|-o0;tXZ^U(U;4je*uz&-6823XtZ1sv4KgqX$oIH6yLpNYEIbpg%KQT)ZFf6Ghc zTYek=QPaxloNTl;<{#O_@e^W12`o+jE&Ev1LQ7TR#zuW?+K@w6AMd_Lc2RUCYsO4_ z_Z-e~p$hTg1()cp)YBWLIcZawocnO1NN0^$$+n%hUGIVovwzWB9@6&#&ej?o#?C{* z9$c**-Q|$RvPg-R`li$+5zU4}#!{?2!^KO?MMBO;2bO7bVH$Q+WAV1@NJIC;_fMok zv$c?@j2|_J8Ms-K+EE&JT+#B7A3>>`FBpE*9(q~Jli>62QA_(~DIJE9%UK5#XL%@kj; zHy-c%`ZinXo(Y|C6TU)313yKZn*^;QYdysjnGk8z^`+<9Jo$e#)st zJQcap&>;2V^8e^&UmCWQt#G|J ziTdaFhgA6m^JbB$d&MAfE_{#bgF?nl$h;hTTF@n9^~WJq6D$C5#RPom6+p2o9Rt=WMMw`hn?LpqL*t#%nI)2RcwIyC|KX0OZ%0=41I(`F= z>s8#EDh+yl{!6Tlh1|5NHeTEOneugSwE^eg^)^#R^G&osL~zMi(%r;A^fguo(O?I; zu{H(Cs9j_&7OZ?U|0uf{VP~l%pz4UiQ|*(G%2eLfz;VJCC3a&dHuB1w?DBqJO)RDRLnH+ zm9GgOr{0yf#+GXT@^@TV{-}D_)T(F9KQ#1yViqp^4ONCr$fv#}BP;#l4sY2VyNjz}CS0FijY~O~4lK`#->Ua^j=cZF zh|M)=4t1W_?p#FysP-vk=x!&0Q%iEsNKZ|`;Nix^7SVFp`{Y-@ycWM@oOT=wyj45h z`d)|O6cwj(nQ5gCXsb@GPfr|~p_aaL>K7NBCk?1g^QtsFKvmD$s0FXp{eEQl7GAkY zmm?h${?EVs;3I(aMu5buhhTT+T`ax~xs!g$JPrHvb3vE>Qb9t0@4@}20ZarNZ_0Ht z>c7eF(`}QSINd=fVjYh>;8PGA6@goBeCc!>J;-fW#Lv1J0>W>k;B!bN^`o^L4e?sz z$D&G;wJw)WX5WM>R6kF4d?A_D?EdGXCm}(&mp=U4w&8~W(W3cbiVnwhFM>>xOS5dN zLBsLCp5(R#hg3N6}w9Nm*t^_(r!Kv3QP(=q;j{IG&pJ z9ah*{nkSQOjo}?k7o>>yaC+tyIWXq+|xcSp2Mt`Clum8&`=x+_$f+x^DvWP>0FkOxhHTP^=2 zB=T`|jxUM(Z%>C8P2OUB7L>>9E}PlKdr!6?<=FwhHLPd$?5Pf%M|sm*#^|=5YTETo zdv)>FRj|b9`{nUgE0fNQF5kH>-{{H?9HUL_%Ce+Pg_d@!(p*TLeE4s(19{5>-=UTsUex@J2Up1@vh~?cX*>yOGy7l zms5UZ`kr;R{z~$_f3y~_U63ms+Xu()?lkQ^GD$ause){O3JL5ReC76$L%__-bJLfA zlF4OcV9mVRs%V&4+285z#W5G z9b}c^nCZlp^;0v=b!w!{u&X)uW>XKQ)vie@?15_bY`Ji@-U~1KR82e4*6(kawe-|ET?ppDDB}?mN}eE;`RWQZV7Wv-F5pv^<2F3`EbapPrpdsL$5fou$_ZCdzD^w+ig*zeSzaN!=$e841SCwy$r;&e;^ zV!N}^gGcwvm!{cV6K`k0|E&C;?QHRGtgo>xcr+@-?pbS`sd)2K`pxw%0I4)c&f8%T zfc|T?0r_M)on9eQgBtsKxnHOLDl8YN+nf_fTH&uZUtQQ87F-o1_nvhq6ZT=C9+h0? z?rL@HhV{Q(beq-w;dO191QlM7xk?xGSV^has5)tI{D&aL*Ns|2jcwfffVy!s)+n9w zdC@uWD=yEcNfStn!CO_Z^yfQmaO|MVO){3t?CUI5;+6SiWqwf0??owp@i>V(qHa~& zsAxTKUWr?A#7WMH55i=fzuxw*ig8kLXHncUmdJdHJG12ANOg$!R4y2Ncjxf7Sx~=* zzJLC!B)7mwJGE$@5)L0!p1i@|&5P^9K`f*aabw>|j{J-%;e7PK%kd6FU(j7}=1mGV zqy;{tdbZ-AN&1%C-SHy zD(iVm#y5rO$OlO2Y5x?IUz!$?Ni-(5otC#z3Q=rI;2{O9lekSKS0zJ1cgR^~mfM`&AL2^WkPHnu!Y8yM1Z&Cu|#B96G$f(5M&>C7$rOnOZI+YL0$JukiPI>F!E+_?TfI{S%Y(W%s8bF)(v zNsSz}ynzoXW-IXgzJ*Sc$s`vw#8W^krw;e+`@ufuuO+U~p9a`fNCMYN=H4ib^H$xD z*hh7P>}kIY{EFY5-26^a<{KS$5a{LwOQI{h6iHQ(myag!~}|~ z4Ifry?!8DT+aQ)tJt53%xDVBttTH9B4QstR^Lbb%qv!a;;E}zSf_6#uqmE_uQDV;5 z0Dwb)5HIIAs^0(Dl4zG9eSoZ+&D@OX*i~n}YQJ>r(0j)e=*t({AU+=~-H?r~ zL7YZXr8te<`0Y;L?K-uhA3*hR>h-m>VlTX{J~Wk!QkEHJ>YyswTUu8RHv z=pV5eit|NZbKBrwlfY?|*5AXc`p<3$n!g!ePTsrTJUV~?+_$8^FClDXax6?JdXt}r zyofcR8TO#J(>Yo1`4fU&GhYZ8p1KG?Md2y7wq-ahee-I$Sv^1+>)+m4B-^kJ5GI21 z-z#S%g*U~m=$Jg2*HQR}QPsMiC?K}V01IlbobY({KRU$I()-acZ)}PKggEzK3w>R+ zqU_!a`NKc^HE;u9ROTDFS<-`D(Ln6DtPehD`=5e{JYb7-$bIpz>kr+qS8!lHB9HmFQquXm69s=Y%dc z4hGm7x^OJu`Z-+-8vfP>r(0hst6M_awR4_rO5o$aZ<-LqasJus0Fch#RyABXm$aO$ zl%yKCPv80N_2bgVVv!FI-(Q#kOCejQ<5EWTU4`fW8a7V*WvH-3gfLIZeTMneWg7g- z-r23kw8o!!B;LHGw9`TT{@!QlI+X&5N3T(h$iT|E#uC@UN}zAKQ?{KEgSYBNX1;EV zx~al~tGIYg|A{80C2)J|htQ_2&pQ5a{0ZxACzx>DL)g?!PIKV_*=pWx_8%{C{ zvknO0Lnex3nBE ziDmEmAo*CBNLq0OI!w)&&nf)(_l_f*J)J4(6t>h)1DHC6UCc5|I50jS9zUJm?{qv$ za4-?HcGLTY1|phT(XZL{Jz`FA1*6%*UKISPv))I#uV&zbVjFTEbM@NaYu2+zibFx? z6cqpj03GFo(}2nKF}_PVyL^@J&b|o@XK33HCwEWCHMDt%PQ*XF<{ty=QEY76miTHo z$iy0JyuUu|jw4tdZwo(_JCrYCOU>VLh45whR-+fv(ZTy5qW4MzcuuALEWVp19DVlm zbB$HsVS8p+ex~B9_QP*Szxgco>(tQzR_e#)7So+pCea-7>WSZ9SFS+c%)wM&6Yma$ z_wJR|L&>0NP?011EoIiX7TE-s^WF`BCs@7MWetV|n&7*~`jEn*vw~q8Z)X@h&O-b) za??n5_P_v2XCo!~85H zJC$^Bo`a|sTv-%FAQZV3&*#4N>L-o>$lm$!t1&o&9$DoRlGHGr}Kmc4% zORs>g9LIS2@d08jTkoWWmrhOb>#wNwR!o$zo%;ID$&e|9{dllE!ShM?QpxhB_BCyB zYp*5{J37|6FOEfA^zq0=m1ai{_}y2vedubaqOOw1BuxB z$1Pg?QxcC%T$0xQY+>$54y9P*e$#pAz#8EYIr#3uVPzJ2aCZEi0>`j{#ksQbI5?pc zrXU2EbNx91&xtzZwDW!P+4B%z^O#NZZHON{yr4$h_vU)fqt-$HekD!JBFtGGT&~4dz#T z==%M){fSUFRHZ8^`kQ|< zUn^NE$HDJ9>pw@Y(>%c@!4&lPhX3??)KVd5TRei`7xn@@#jnP-aP1aH)$taPdq__W zhPI>duNLY23fNSlBxE@heJIFz_`x5c1o`P$sy5KAvxo6=p#5d}?##`LJOqT{HGYo9 zy;sb_g#XNYhW>;7@m`$eTJen#n_EFLxMqZ7BuTN#;Ccy$T6;7GSDE5bAjy9+=Pz{G zi9MCqm6;TT2^%@*#SeGIv-q7Y`Xv5zY5GxpfJJ(-rm5bLu>k{pXqF~XzzZxYy8cw~ z1I{{cKJoohLYF&z4?TFH@`D{_GKjrY9isO_ttB$eWPa*z>oZ_qQUT_4==CuIW{+WI z;NX)*YKnik6?DexyL$98CR~3v5K{ZIVMvQlri=G>8HlY==vt)FN8^A4vU3ntpl8?u z7P&fK`q(FWOMU9;Xa|bLBZuV5xRtuSwI=ebwR8Wq8kZ?glk{)CXgt%c)@D zQ-e32bD4Lp@%7KvWv=6D>-QG&3DNUpJA95M8Mk^h2>iVZ&6%uDtQq3pjgX~u|M`dU za+(d}U%pPjZC^V@{L}t*X@U~q(^%`Q)yzNGHd6X9zOfO7v)W7uTpeo# z&TFj4BlI5p2Satvl z^lFvefzI({xJe=_drKg`C8;W;JH_5X`0$B}x#jc(pX&kb zV)q@_G)9tl()w38jolC{*I|xrop=Y2EqrMdqP9?aynopT3NS+lRv3#-Qtaod9#;6$ zG|;UcwxBD%Z&xN#hP`5g8cckG7ngrdVm?tO>fH`?n=?0-(;ctGabyThHgt~i6udyK#n=(eBjIHeJ*Ud&8>gl)s*z^&+7i9idxdHvyzZx z`(bwRu1sDX!6=2`*?S592^A@}40->@%tdT))<$I!yUrq<x;($G?VW#Cxrx`0!jJ# zcA~{g`~ntm1#HAVflQQtZE{v?Vj$`UY#PWu0d|~_3*;fZ`l>NOA?zsUrmIEDWXCBw zb;aeu+`1p4^t~cqtZz$Uj7h~`=hYIM-hV~E7XdH@T+17sQTee&t8fPrNJUdrL+9>H z+cB+MGUT2e{RBM;nX;if&syvK47_8Ds4)0ze^KVap9R)u0`^Z@)al((V3>$Nbdsr1MS6xDr^`P z+WpM%j)!3uMqKILU@x*?xVV>L19~7X0Yp(BN)k}am*O_xy{}Dj@a4h!zUucOVgfQ2 zr2&coV6#Wp_a)!?LQP;Legfs1@fPjdcY;QV{3@-N9|+!-uUO|Nhn$=^bNVo2BR>#007d>EVx$$e^^-{ z`4uBf!3K-64P7YQ%)b!lE{(kecz#MxN;hpMXom{jA5YR-lq%dm z_0ULV1*D_Ei=s^FZH~RPr_bZlD77`xwG9`&1*crE)qRDF*N$0<)ZdlBO^BpGTkDh5 z=jM%k|5>07OL-N!(u;jk?okHLx6NkI&=g1-av;978I0%D7Y{=}Z`O(eoeUY4vO#(m zkSoRZA1l=zaa1{WYV9heR?X~LT}lWt?Yv~QP1*8*99R<6e9~^}LMiX|-t8TvolqwG zsaAE_hn>V1mqP4xo58Jzy!73#9~}tl#KrQ(@YNu9S=jf`6sX@}Cwo9EE$v6g;k;^- zeU4LN&EtD^Svdb;RnigQSiu62Tx!WW6h^WmEdIKS0%uyJp?p2MSQmk0Ut4=%8}zHo z{v++sGfp(+|6xN~CrI%epkKNSbC8G4;&sqt-lpkdNsLhvg3j62GoFI-iNwSKyA5s+ zD3to&Sfzycts#WX%Qr z=QAW$YCpzPefQ!A#nngEGC5QAU^nFZ02bg{y22h2q=WC!zzwNC|*j-)l0u8_Y}v=l78)$s|i`R36Mf?{Rv6o0)yYe9^b5>CQ#6 zAaw6C#XiV-Jjj@E(4B$ES>BV!<1Dt6p=p8}M(Om=_hOV|Zfhaaz6-X7M~5E>Z^4_t z@%Ct2@bARW*^$1WuG0XO1U@ymdZA;3(up759G14M(G#F^H;eyTwR9tpX&Sg_{Jt8( z`v-J)Cq%jhssbUH>}VsM2GI)iAp{Bk-;b)55mv_=fGkaTb2n$@VD92l1z?gxx8-y4 zWX@m8-;~`(TfGXebbm86p3Ghzh@svYCK)4V2T1Smq<9o1%k>_5p?lN6k9%m~GJgzj z%XI=wKOCyFw8a1 z*4~`J7X~tw-X*Z!FD!@2oUS*J8&|ISaOu4;f>$#SFl5BFd;a-zDIi(`1R}TQ-JEyL z$oD8#xwX-tZaq(kSXH9xq5ebR`)SPS34K3i`_?yIYlVr)(;R#`<?=MOcuyvM4xwu(@GYw2wB2EfH<0fql^H1cNWqIG z&OkrKn8vOU^)@kj`$T*67xZ|z`6*tSWeW;O{cd5Lpf}J_l9idy#*I&wM^o>jlb+^y z728~=cpbBL?eH-KDHU4@pfe;gy=7f**{n>-2j>-9n+nj6wMLu$X;@4+-1cistv~n( z1z2zVgwLc8gyY4iI-M)6Eln*+z+zbWH&_y|cEt`|`HZ?_x3rK)}-w;M1lX6e@g&*;%p&)+1#;E?rOlxkcb@*c7lx!-l; zLR?Oo>sH%cvXfrj`Nzdh-s=QRL=e{sl27p9rmMmoRDlM|V1!sP#CkMl$^BCNIT1G3 zIe|#>&{zsG%pB|8@Rq90>o0(Vw0Ko0enD>lX+XpghJh-B4?p5OBx`v06qE{dXgX%~ zTzyrL7S?dAxRnvVTp1&$Q#ot8Vu`b{vN2zDS$MtY@9y*D-o0mkNAyP+0*IJcXpJOQ zW^St(whCq;XY^3ky{nTQx=;%ejRKMlmAYi(RUU>8a22KtCfb~JR!ar&R8TTHc5}ON$hg(nZ|U@^One^M@Yk4==8-|F>GH*gL%N=={_8a$z1!{C{*^NCt8S&@*V| zb#+m=va+H#oR$O$ZuS?CYox*k%5Yk>Q@y$BHd_-Rf52C$Zz;w>nr-CRRk*7q>iWMp zw8dtm9QS^MaM-%2ytK*lP436oT~VN9gB#4T8=Mz_U6@~VS%``AecH2)*Bdu7XB-l^ ziRXELs=nH=n$7V}tFjCXV+pOM2I4CtR2g%FUID)uO6Mp4SG>M@JCyI$xA<&-YHq~+ zY?FvV+;Vp)G485v@Ir3|Y(yO8g1oE2yQOMU*0+wv!M338p!_zy zfFkN`rzK2SkPCj(iZ(GSi?e&x&=mJrLMZm+^bG=@zO3%E`P65%AUMa9B17gJ){B_0WF9i95yHVkbq&^+OqC5CJ;9Ozse{_zO^v@8X zL4bAY5GG{DZ{IFc)ecsy$n&1Mt%-41r0)|-XAh%_!ugjicS%y%X8P?Xmp#Q^2fRFs zBv&S>54|})MJ1lb7Scv}1!6;xcU>bF7hy%oz9IUa)=m*2LaxwTWmt-V#iX3&Pi%jv zLz9f)4YNH{ff&1l%OT;ed^M6Ez}2)N@JFDF;$>7aY{xArWtVfDSdtt!d1$bgz67i~ zwpBGa%Zr+N>m-@#xleE$-Tc?~_P_f2fzvfflg2&IEEe&-n<2t}p?Nw{ZAQGH*(A(D@YIuQ$R}O z*GPR}ILCEp-SkztL;m84tz5M_&fXb_wEN`ddU|S`344RTDfZ22%TNPGij5UI5J0AR z3diQ-dM~+qEEGgcu0hm;2UijM66}oaYCTuWi+`(M7j?*uS4q(TmGw=xiMwJLHyW(@ zUp0&&kQJ(hS@*D70(9I=UC$E}|B8w%l2QqXMH$-dSVO*jaC)$)fA;_Agc;mLK%L3|(hhJXW#{H%qyT0kvm zVr->85zU=Qd|$-du+er=xs)|JWq1d}L_QJjCn}q1lM()+xUI!ulHvX)c_vrp zv)>uw^CpI6Gya(+h@LFEJbVGDhqdvv*aE9OEsAuK@{r5GQ=dzZY9om5l!uz?=lW~bD z;fcGRsRO%qG1Fi%-$31KUCjM+f47KN2;U`i$cCH6@@9v4wp z?1wl5gZhP!0=wo5HW$}x%@@&#b>vqE%lp~SD10kUoqlbCejtiYBSp+(`;`{rKvb@F zfE)9GYg$ErY*BhG4kvmzy@ZPgtmyf=GDs1NjNUoiWVK2T;Fe#lI`9*|b}0Yd^5a@o z9+St1kT(I-2)>2S(K27kAo#^d)nL3NX%cS`CP@?b3+ukM@D}j{ov|16t3xds7vAai z2FotAK_5)80E%aZ0zWkEx)VY2x!=m9Y|0oFTiDtpmJosdH1uA;&!|x2)iZA9*}js6 zOJps==M|^DsAWu4h&0}<{>)#4SRdD~oKuM<2yNhwA%iHG=JQG8gX^(xP;B%O5RL~p7drFWQf zIiN9JsD4Gka2vOe&q1L3iWe^)BQe{=jMmGa>sEVBwW0Dc2V63M0Q%8=sn9nNC7 z!t1*6+EMOIPQ3*G8v1&DpWaj@6RY!uOjNB?2lDnd2Cs`^BEu*QRt*G5vKVi0R(VW7 z*zDJJl{bS<{10k2=(>Fso(;i`YAq};d^UI)EJS&L^9NUB!j9Q87G~|nZliEo0+Mxi zoMZNvt9^rTH}(}PlK>>R`5uTLsJ$UnJy|}tV1*aaFPnVY7R1-y-}i!q|JojN@BOw9 zZ(qHFWCX&rYE#qjO?=n=kjvH;>F4n)bPE8=sw3XZu|eI=a^*v3`JS@6;2q6Z(gC0PV=DL)SYmJRc$|^b-MKrI=K^S6S|qAi#Ahl zm%qQ-bG#~abm}_R7>V_>jnE0@nQX(_^EHKLsn*1S%<29bSb3OKrpQi4m{SWHu9slH zc8vaf6nAxLE!%T^qxc{nW-YHc#bG(%(b!Vkq}jfiJHQ)~|C&wymxWFQZbOB+|8pz9 zBw(eRznO@wW6`1SqmA0IMyxI^M)GcJxq)!5;tm;sp3*P4PaQ?3mKskrjO0THoN`Y~ zNs{AElUzLkpmcxlq9K%na=xJ+>w0U>oYn`9TLLd+G)qt7fZT}gV3(Dj_or1QQAPbz zgz^sQTJ2%Pww1qisL>!Jiz}HzV@>N~ncZA5nW|jQ0eR0^^nuxKqQ8$QGm0ko&=pM#kNyBLgiI5J$ zf-I+1lFQ-q5+?2Kn%JcN&5>W7PY$g4_8#T-fL*hMB~832ev5i&mwmT>_^q&~T|b<^ zAz{CiRiG9N3f}S1FzJx$uCh}RhH$0QgxJ6|2wXyAFGL--)^Lghx|Q( zz6H)*@8Gv2a|!r@%c$7eqO6e9?A{^M`zi@v-jJc40@34Qf z_Brps1XM;k*`{N7y5HqrQKYXiY2yTVqE4MTfI2JVM#1+1Cx5x$*^^Fn=*gse%jl)B z+sTcE+=#!7GIp(|q;RF>X|Xyzaos6sWQ1Is&Og%8V_JKY8;GNgpdwvfB1;ezvFvm3 zShG~$wuZWd7r5|A$m}nq^n^^_{2yJ12?c7=eMxMf0OxWBlRXPiQMdZsoMu}0+~G^y zn$$&)Wp!7{OH^TUHy&fqFfNOmsz);;#XHOwHT;?2IUu87y7{sd1?Vz6a*V;uX2^9H!Mm;L1kX} znQv;GerCVRk(IFR;9Eb2&dU|DkT6m438)+KM}k$+0qE6*TMgXrH0Z9B;;XmNhc7Op z6Hi)lkwU4XA1@)L`hF|n+E>@N)YBZ(7GxuQ>dXvnVUsRdJieC^!JF ztt7sLHjTR_u*fekSn@7%MOdkCCzLj6NMM~vRsLqc)ADLw9`~6&9kKgUNq{dQX`XlT z(PkFXg}d@$(QF%h%rd{f>c?$OKbl?YW_F;ly?-q|7 z%#8v^TmNw>Gf%L!S(oSg8cUGU+}N-F$yJ|33HKNb2HXgQm~>Z?^y?mG0?wkd5mQmw zxK;bpjQ?2v=m&b0i~8rhidYyanzeH=v0j+B+E=@rVPd~-mUG~BvkGyW^fpS>X& zopHoQTcU5>gbU>u-m#g}R79C20sfUG=Zz;?%Id#*s%yIHoA>5agQC|IE>XOOwLhE@ z1Nm;jiTmP4Y)m!7*EHTlB@3=?Yi;H97Ycq%mT^9t?6AzU(cmw&dXzPC-WM5s$TWZ3 zvZQ!(stCsN$lQE7gdZo`<7WLLX;@JGRaUd#)=6VY>X}!$f8*MG8IUtVZaBR7PJefe zo2A@xF2^kiEaP*Kd17>p6^*~9#h~gLzxkTpy8uf)S+*QBIW!%Pm!i(RT3*?7x0#{s zX*kvI|3-?3jNqGeRJk}LK(8OM_WvJ6XTi`^!-ipeQBhD)l#Yp@D5=C~uxJ4VMu*bj zM)w$sBGS^*QUaqS#^_0oMp`y{Fr-TcV`F~j`v*JQ*@@@5@9P3(DmF68mqK^i`q6sp zZ=85r+T7kQI3i2h@2Jl9DXPo${kh+artlSxLXGAQYg@#To!mGzAKs8yqZb=D)(^!a z+*ewL80(M~q`)gGPHBgaep9Mbm(t=Z^z%1#RyFyS-uPP~=e5FV{=;X4*q?so>&b3? zJU0r*#h39G4jnt*i7UC8J0wC>wJ)c|#{-;L$+mDI3w-PX`N{n=m2Bbgt9>%8sXDuo z8}nLR%K{!rO@*VqlCLb4?7|+8l<;K>iUR<6c zX^GCy2*&A499L^X9qkfC4ano`vG{`YL@m~$_YSY1Qc{?OLp!o}+@l58 ziR;_d(5IIK8)D6v1Oy{J`ApwkW*|~9dJk}JGF=b+|2wNlKqH?}(2!?!EQxf?g9_JL zOSNw!nIkM&Tt{a|q(?A5%|#z|d7>~9Un}_Zq;N%Oqlt98`lR7{KV09fFg0kdl*$x2 zLV#m)TZ6wU1Q(~N!sQ%t=&r1`fk;We^!_|eC}HDZQFvpQ2qtin+v_{u3C4<$j?3V zTHNpCR3H4LZUn4Yd`d@4WHmZD#kpqoIDT4oYG~Q|6Nz@YAftVQ2NcKJ+xIS=rF2f67 zu_F4~*d)QP_6a{;Kz>An^tV)8AZlY0=xHkrpwcIL#@Li01uD6xSB+!sYf%Y~=$QlQ z61)KsOk?%v^%vvG+rAhn;38;*%j9UA>tRa*-CxwlPLU5@g zZYw;+fh=!_^4ReFsr;bc%Tm`@C?|Gx%?sWq4gKL^^r69fsx&g_YR3Avh65l2YLQ)8 zPTIZw1kd1Zc%kg44qpkq)Jix~0P-?kdWn`zfyzkbP~cXLxWZr0k%EQM8n5XpOB}k^QZgC$6?I{Ozhn!d?F)ZZiVykmP`sD?>QWfUD+{7@Ij{C1`!S zadp3cn-6wp+7_fEj#G!?lP_#1y?DO2AnWfw|HwhN14j4rxTNyCGi|tjr+PPuW~N)~ z@g(U0z3=p+_!(newDiVsKOW&s`|~8}P~w?>!^e$;8gg&~1YQ)9B)~?F{hap;?hfSoG><-kS&b=aan8N8uGaN?zqy_Rzj^rda4Zpf~EhUR;dMJ;39p$=O6Yl9)Xy`06@0keKOkINxrh;g8IK6vJ~UOm>4T58Xb+mJ%;iE&o|R{^ z{>Cz(Ue@3tA=DMZD?-;SxyQSfQ2M;9wuT(v6S z8;pI34$i%4P8+64Ox*L&)IONx%=BF*JNJK}V~>}+{r5;D!zZ-1IQriBm+r#;UWy64 zJncsPXxdz_@9Q83w{4xi58_aksreFp?7v?Zy`clMdXaZI8G{-wmYz)_sk@# zYU0T5RfPcgcfs;VIE{P%uf)aX!u6(dNjvX(Gpxr9&)GrIyHij{8|17()h_qKN$6r6 zs?yodt#Hl)`n$eXbq4R9@JU_pT%6aV4>p!o7Jb*qjPOK>!P#QbU;?g1gvNMI;0Z-) zQwNlJT;OCQs#$aOq!YBrsTw?m23E#51e#JkV~W(qArAegmekRcXB160n+x!}%T|n2 zQ^ThtU7BJr&b&i$6PO32f!lLjW@mxk=geXWXz~%noVrK{xZi+?VBmw!c$MS9PUWp@ zf(H>I9E#N&?7yNGF}9&Iv_k^WJs9#+7DKt8s7(ZN1;2==)(SAj*!Cy>VL6!_Xh}0V!IcR&RCD-kT+0!S- zQ)S}fO2B<2k%i3EK!#*JWx1{3=^Oifz;c|Ws%t?JtLSbrpyHnp#=vo0nPIdo6;*J2 z&9#4c)5xVD{_U80_$T5V@mwzlZ|i2;$xX_0S)lrGuW`l2+-jOCNUB~R9|;!xOmg+k zI`6*gov8Y$Wk<15nk4HnR9!$uIO2w4SUxf@b%$K0fN1?y`<=`GZM0dM;O^$6;-c~0 zfU)W({Q*uVcWKr`a~my4Z(?SC-tc6YLei1VWdx$pgk`pG{cU{vY*|gPv|?SMFVhAQ zxM9}nrrY{gCt`muG9G|f;Q`Z1kfm&)pT;DXSqt<2*EOH|ZwjWdBx*+p9!OHT{$k>7 zt^&n$y-6;umYbDgpK@=iIk~f7Nx^b{EC^_S1090?_c;qpjsDi*@(}YPFSbj9DIkc@ z#V0*coO<32B4`Dk)a0c5VeOd&4P3%S^lHsoJ#@J{H}m#<w`KbHM*&aBN6w&I}xVV+^`s8<1><@<#2k>paR$oGur zq`&N`Yf9eJ{5kuC_e8F;&DtEw_1e|o6F6(LtX|K}8~3rt`?Qq@tvs3}uoQ_AnZ zhJ0GcTl6w&~S_RhY$mgi;%{N+zRBe99Lc3yLQtGxrydhAtM_-2AJYWU=X0gcZXa!^o#K zsZ=TJBTryZKXDT5#79ImLATi5Y%J9`H?tB|Qbyqbt0Bw^4&J|5w?AN4qQjh$9bcl4 z@*Zt}Dyil@QK2T%FuPOGoy9ko3i?MUXhVeWgQ%<#%PX>+Ha8c#=B*bJ<#IihdmXT? zcc-bWxr95ZhRdb?ehFf>u_mCMDxubpTn6fm%q8gQ;`*@`HyoJf-(>m(Q;g3gPvZ4Y z1Z+CyR9^0{Z{Pj$k1oy3U0l$N<4CCyTg*|V@LlmdW_4ypTyQB^mJvi220p;~f-^K+ zhoT)IVqCp%RfkUF(w&}JoG|-DPWc4}(f#*CRB9b9b5wCac58-hH&9S(x#vS2K}^(( zds_-l5u(fEQ0QE)y%`Q4XHhDcbu6>c*H~Z)0|0CtEsR5YMa$*!{k8qST^sr!9U7@u z|HK1Shp-5#IYe)p=p%7}?ai8!<|T~$khmt4`>k&v#O*Mb^k&a}`!0bwqIx~&!oFj~ z_Y-SkphG052F{KTHYWR7N22nX6Z)A=e(v5&m&)x>`&`ygr#PIYy$(`juK7gaBa&5$isdhq`ljzl2-jZ zFTD4+PpRxecuS^OZSL28WT#?n+@rXoQwNG`0E}XEmO-^_f=10-$s|d3&CLGv1>QNZ zPZo+0?ub52J*k+&|3_AVohqWr;mU#y5t-GiKj`FnyNjjP+MUfFSLrZ+PSN%sqdD=q z3g6V?3aw#|R(eC>q)p<|I(9i+9=WDAB>}68(+<0)OrFvKUcA}G$Eu$Ks%n8O6kfJd zwRWNN(o%gKuTB?NA?VLb;R3RxpSa{D9$D6dstyd}$p|Uytmy7ZS=kA&)6=SVNVHIt zU-4-;ymj6(VnyS9!k2S@y90`&FwVd{Q|9cu1l0_XV17c}1{h^6G^>>6PH)if6%AbB z1$BB3g7bVUt z#`|3Z>+#6Pzb0c)Z|NKdAX``U4#>}(2-nvx$46%HeJBNl@_Z3aA-*g6%Kfti_&q&@ z4}{PbNUHh;RW*$_LdQ9?ufQdDD3eP>p8kr$px@Szt5+{rb$jcPAvG4#&1fm8Rqnj2 z+Z%`lXlwd%vp@Ss)p^Kw^v=ra|6SQwm#yZMNJk33w7hKXb;uNr>-=p%#PstY-Gb3} z5d>%z8Va1v0;|iooxerPnx_Bg{-{jQoi*Fj_HCBFg9SicLpnS${hhl$WTbp8(O#B% zq2xb^O&TL6n3(sqTnvyIpBUP|twGP>&v5EC`pw5BbPj-x8j=w`}doP<`q1W zRKS?M&~3v`n+H~Vy`hd(d@gNFd+rgi78gQ=nLy5b$Nd#Ihw#X*m{EsFGB;yuqbQv` zL4^(2xtXclhpU{tFJ8y6wehMgHS@x(FmH*{Xby&xukp!}J7hrgac=0w&#BdBq0L8L zH7dZ_!;$BBQ88rq5auvv%#N7-Xk<)jHgTP1E=T-oyZH;w0Q&5!>#jcj7ADr+WiW4} z2IcAhnbO&OZdi`kl16$09O)Mq8&q0X)y+Q{j-UGq{yd)HytCjQ7gcL_3b;;cjv|g60*GLlvXpHLCl#Jym=#@W8nU#I)P@HZr!m(Bqa3 zVGDXFY`Uk&8eR30(YZu@xj&be+k*B$RCX5NR`g)>txV{rw%dC-DHVF97tRO@ovXD= zP78O6`ya#TPJJu*!^`9j)ts*tNpFq(;*Q3qdkml;nAVqPQ$N4EC`=YdDJi;@nCtTV zn(eA7c-}sm(s=&H?{VCd1E7@ZrM21bexV2}x#OT3e1@|hAj31)qVkp z6-Qs@9*8dnPA3TTnV9Rw5ZY^-+`2LF;E!L`F@~|I!tAVRa?~DwutT=sEi;#x*Nn<# zQgJ%Tt^%-1mmRk2EFA4aG6NiJEZ4{;+-FIo%t+2QGkdEAk+=9b#eFMux3f96i{%+t z2vMxD`rg)Q!jRXG4#cmY^}CONK&}6uV3P@~njI1OoLUC_1fwqKdC3M^MxSw|m_NIM9++d(drRxN&mOZ8r*<<4 z_UJTr?&Px>C6sND2auJD>Gbv#0k4azSm6<*hbsHq&n20UJO#kBFbA9Th>24pj}g`$ zqQ>l2yNUa*Y>4EesPwneh-~1`$Xx`m@SA26+2UM^VpBe5f0CLm0g1cq3@D#wBWI-( zIPk))hJ)C383(l3e&7dJaF-c#}bi?~7|UxSuxooD4Di zM;H0GDrrbHZX~ZAIE}7Uf5dv$-D%rhcHj=ZVwC8z*{DSZfSwkUktCVx2ee;#c6eFQ zxmS&Uw@vtC1>@J${X$Qj4pxGr4wl_{djcId)Gr_)1MpZ>YlD&r_8%R3tP2+&k;FVR zCGX&#jTl*bOAdI`Gp0|lc`a?rvEPV>;RY*O15UkdZX*_6o#h&iL&wwuU^ez8Y20S@ z*&`^>4@GYvp+CR$kM6iIz*5V-w0~^`?9W*5bvZ9;aWIp6b#6D@cO^JM-_at#&XhH! z&?+%sQ(V9{fcu$!3Dz*9jCohkF-&s_TEv=p#+j)^S4b_MrPZyAUtv5LSk>|vIFP#U zK;=|4S?6W$3w&j(JcJoIC@{7IF4r|2Gg15RVtWwTAujtJscww~%HS)rTE1m@ezSn# z0GSJM-_Y9C&jd6RMPR0!_q6`I@`WD$)2Tw=txX61_=h^iH}&4Zg4o0bgw$rtOSu6n z=Hk%Boa)(Gt%~O{2Qot~_s3Mk*&_n2fUFy*ywdbIQ_)$Do<$JY!VA3mbBh&YPEMm; zrj)C>2bO6rI6)VD7r+P7vEi3u8qc3=MxRWNC)sF7No4Ha`A1imm-6_SXPTIP2zcn7 zHsQ+tVUb+R3q;>Y2u(lb1^n84ZmhymdZsFP^%eR!IK}(VfKG#M@s9|i{!W?u+!npJ z5q}%_EzN1peFxmL_Jg4{;6QnZMQkn*V`qFQ3!`0ly)pN$eN7r49Dz`h2;8HZ2FxRaeR!91@Y?i%#D9)j(Se_KM;UjHc|6TeiJd*|GlI=U*` zW$ZU#=jjdGtq&Y~#Q0ZeSHdv6KzamVuNjP*&()pDpzb!j91#hGRj*`yf5IU5|0dDk!jesaBCc%#x)f{9TUFL_=e_1cKAq+JRse>;4=8so z8}SOR0LQt?l&w6S2xxA{MGe8GgJA#VG8%9;gSbhlClbt`{brx>B%v}2203xh+ui4+ zkr8W}!_K^_TfG^Q;~4Lu zq2ZwTSy;nbVaiwFzKR)Z!6aW^psjeN*nma1N4<03O{=GZ2LvyF4Pw>Mu*LX%aWhJ% zPwB4}vH@aR$O8S@1J2Q?P%FY)xpIlhUSvaMIIuJgf1h&3+P}$yoheHh)@RiJKx&o| zC6_WFvu(vh>!UA~YIacG3Z$LS+guUVuXYZ+n(buo3{(fQrhYOO@%IOHb40hVM^~)7 zOpV7=v%Goy%p9E+rS<0-4>7%{uU=jNoiqS}E;M~9ka&{hY&XhbtCW!r4OZoZw@{{AzY}4&C+ny){Ut4U|MZJdEUe}!MyUq7+IHP;SK@rm zJ6eih&_^$eZy9V3(6UAXOYjj093rK?zGKqjfQ3UH9UgUaYZAP{cFqS{a@c-vlPyO# zi_(uZ($RHq7ht@%WcAY@>hq4Q8Ko3a)XxW}d~KUZ@~R~CK$;eP{uZ@0uptX8N5p!j zu0R(!eiC*PwRUwa@+2{a>hf&9=>@S#E@TLYCX)UAm)WB&5pXx!?ZtSl`X=Q&Wv`yS z1h*h^<@n6SzRis(biQZmPdRH*hBD>x%4!n%bRvzNzaZ9bmS#>J^pwOlSI>W3ge+JLpWZ{opd6HB6^_3l!45ibxRapPfz4qUY$2qU6nK%uS-w-Q_ z_yb$r2Ia{fJ^eR^b7p0d;=4d~oWYAYN9dcKVfc{yggm9uJ@T1N6>z0rD=rBs^(g}z zH94Xw`ZIQ&wVK1Z@}hVRrKZ4XW70kuhkA;F6^hF6qFNpp=P)9Nxh+M-z@Mi_ zenjuTted6H2?J%BhiPI^? zna@0Lj22^-Cl|Iozx`2VsZx5N+=|VCCJ>{mVruDLVByRMb$8Ljr+b&Sh^@XL(o&fSs*-exNk?PL>w zkv$RXG2(^1gR7eD3}d9!W)Dh!rjM%tukiy(N&T0K6Tdp@(Tt3u!O2qOYO-jvy3Q`>L7#h(3FX1T zY@d)3H++(vDNQl*Zs2l;$xS~HiOnLw-UO0h8*5?PS{Brj&UrppkM2rG*-)vLuTS%L zTr-oj0j{9jVdehC~qrU;ov>spA`(qzyAbM(F%z;Y(3oikDXlfrGUB zBI8{CMqh~!5oMAnft|j()hwDK_fsteSQi|1$YLBwo#1r>S z`E6snCN0DWPprGUSGA}PDoX0+VO^$0SV)B9HiW;{fo-%;K(_z7j#97%aV^k(6N_>d z>pC_@#`VwZ?@pRHOaz9e-6r^fNd)dvIe=et+)GlhNw1$1Y<$`~{GGSC?Jm< zUl2RI?foe+hi>@-s8gZAf%BihZ?8C^xYA~JE5(d8SB-JVUD11UD=@3V ziz+JlRmlP(iqYIMu@kA)RODbuySS_f8#%pS_1hN1(o2ph&hP1trsj_=j=8t3(ue8y z4-y$RP%=wq6_pMafr8My`W9Q~6>*BuC;hLleW@Ed7XD4K_u|w7w(-F~lP0j>wldvkN=c%H0N&N{-q9Ot?JZpQ%;M(1OtzUNNl?P}OreHhIhY%N8smdveRJGCX zMjB6OmceYG0j_nJ=;P?}Dgz`hD6nc`khPp%G(_?xzp8xWIH&OBPH+Fs4+pZhoq#7X zx>Dk$w}??s0g0s8dAI;TiQBel6Tu*}$@O3Yf`3=U?VXw^9 z@EtYR>f&pGxOt~no<$>pciYy{*bc>(;A1+;E=gKls)F+5M1SrkFYQoGQkNSxa{Fcj zU8~#R-+y#?k#_d9FSt&Rz1Gv82_gBM(&VqhgyYZUe%A$*PLEh;+(0Z!QlL)1Y5OLp zv3l;J#^6Au^n&>ty!YNE#T*^+dPYr|DvbIin+@^!GVBfU@+cA;(zoX&WF-5`z*9hc zq~j5m*F#u6bFj%L#nxDjaj33m>$+2nXUuf&EMhE&p(Xr<%I!n3M62d<0((N8$2W08 z_L5g1KxAjN>j>p;5g=4pb6;ie0ym{}cLrLB%`7E8T~NGn<+t3cj`VOAx~uA!U-futBmfv}axq0TEze67!V`O?C5EwrNipz)w@eKzbnaoo!vY}1ZJ!ahK^So1w6b%ytfBVswyV!yTBONb zT}!UHGXS6{n=_R0o_(DXtv4>Si+Rjj-hsx%R=0eARA&#zo@?majVks<(o0JA^xY|D zTKS3>C(DWScur-?bXxT;bIi><*VpW@Urr?mD6K?=RFw1AKjFfn%&j8tP0huYeS{UB zGUlsGdx^$-{TZxrm^4dtcy(-YL7w3#e_+_zkK;sxZ16y~_5!D>hW$cX>$il7aJzS(}ps(;*hK%ah1>nDy%QopBlP_->Y@b{z6XI!DKXs$kp< zt2gC|H8{}z5abCx?13~YKACN~8I>1O8kqI`ppWr^AH@BUyxjQ*+_h1ARo6q?pQ^A0 z=y!94#~w$DZs&B9k`HzSGB1Bo$65xa^U6^-wS9^t!f%N9s)V7@^M&z8!O<|_2H$2L zZ(Wd)2Y7U&+6<7$**Cn#`pxlQvs4ZLR!N*_0DX04LTXE@3g12?Cr{9Iuv(@iwN|)z z5PPLS(7!Tid98=}8eC*_X+p^ciC;H|uH=dBR0>F`k3A$1V_2?TP<0X{n=@6ey~!V9 zLhKIWg^mNG{en-Oc#)^G>Z2{;el?8_X1BI~a`04zR(R$zQ9bkFroZf_s1hY=WiGB` zlCw|1t7I*`S8cCncrV>*1D`Z5*@Oov;o=%A))ma3cZZHuw)Jn<*>5w`s#}w}v{^9s zcT&*`J#X%Id>)4ff7%-qgk0`ZX)NE|w1}4id5awedW8ZDd*6m(kKquERr3SW80{awv(T4&8#$!VwF%EBY0^P37PIe)xXI$GC?&G-qd zU%)YB#@CU|+5Dd-LB@LX?Eb;_!P+hyALiwy(Q1_I5Y-c2bfp6AT8+aqc!X>O%K(`n zhcn__>k{zPxmNsNMZ$#FKe|dIiNeCa=p)Idvzm|*(uZ@n@#}69C*t3sXU^$#2-{%nr$&U1K7;}`MaJ1}D z>s{+a_^hvxKt>oRf6f`VQ!kQr(gH@9Sdn?Pzg(ZWWTm|!WV*w5@gUo@^ALnc@0ROs z6pTzwfc_Q35w;HBz_E^2&4MgKLq{t-kk8w+0iO5iW|^X8&5k=iy}RMQLfdKtT~%Wf zg*3bv!3Bbtbd7DeACM;cUQ;A1-giwpw9_cyba)8*ZECeG!hbGcu|X^BJ1_)>53A(2 zeNvLO>Xxg64>lBE=9C^+=}f`***oLFCSdrHEfA)v)(=jPH_K|kcv-<=APW($7#B`3N8#ZC5Wi_Nfk!(9RlleaN zF?-xxX(e};7>@mPCj3u2DZBhV8cPJPORXZ&^ILK-HGS!@!Eg6V(SVQb)sF%U47ES< zG1S$aeS`1L4~tfqT`$6w0-$I#ilFinQM-R+(f_5 zGs5^D%_vd0qd8hcRFu93F3TZo!ycB1h9 ztsi(e%&0QO`BLNj)L+%Qv^cJ*<*Cpcu4%9OoB1BViW0=n$=%0)jR{_ENJUvx*pluO zZ60MI>*p38tUM5U$50`uC2y=~p9lu|#%=is(ANiNoHh$|64Shnse)-!LA9>NNmefY zuU6SC0(0cS|L8_kzr=_uuV>U(`&U{Ej_ow~cQiL&I6SwdZ}?%pl$`72l#uHK%kx7I z^wQ|#*R=R#B}K{vDkt$&4f&aoKW@4&$PqQ4cQ_+q9mK4s>?{cfn6061S1E1Bc~2Q$ z2annx3qh*qHb8Z2v8Z4+b{wfTq|r=u40YMj`0A8ob9LSE(XP?os`wo6-q~L-m(!gp zDB~kvbkwPisomUg_l<_141X(C2iXp#U}XObv^B)XAj1=f-{2sVZ?99UtYu=T)g8zXkS8*xNu^^ps}61=4Jl?3 zgD>F!nG$&RM}!tw3EpxIvnmvUkZmlHgni-Innb(&kB+O4qVEDMw%}E6QZ-7p`ckh~ z8Basz-594xu9`(=lVE3uI2Qhd%k2%?GYZs5Z}>UHB-r% zw=Y92MQyhfMf=aM$qRs{8unG`WjlbBmMMwjAKkD1;(6n(Nk=x9CTcU%OhAj9-()pk zMicSsIHS$jr17uYpxx8f(8z!yO9}ln_r3AL{>t55BeAv(DHZPGy6<+!UU&G(}wA^4LNU|%d;L>S?7vAImW8Ctc89yN6_4{~qFb%7S#_PD4e zuS6&ElbyzNVef9?fkk&>LD}1XbYGxY%hP0@;4Bke1sTVxTMK!y+R6E6gg>oM*EuuT zbl1^tBB88~T1&jb8}@93V7F9Xn@-6#uu~p`q8Oj-G99Q?p#HS`F zoIzp1L2(+aD_q4?HvPrqM`WF4rh(va+luo|Z)uL|A-Cd~SzmTe!TO}+Aw{htMNleJ zQF~oTdYgVz`GW9-d2yHzRDJ2i6kAobc1<0B`upAS%HU}+iV|%y=i*sW9jCa`g9`Cd zk{@4CNS|0AFR#TFRpCu|2mnu5$_`r4J23nrDL_B z*7uyKB36tdMd{LbqXZQ~%_nz2be3N|zJ!WrY^j=~@ww%m815T(+HffexmN}R8(2LZ zUW)3PH&Z9HaWJkQhb)i~`{mzr4RyJiK%G(`%DM|a>_^F@zZAWJ#1L@VJHri$08lbX z&2OQ9Wcc=*xe?HXpsa-!9AaDM`ypqV-)`CtO3;Phs~rEdriO~T)47TU0qSs;2}Qq3 zrodcT(6%AjW@(Lfio7>{wejb;eKeVKw1fW{Nun}HRofa@xzS$hFI z>7D|p5f$ELwmEv>)BO7}bGHn@?60rVj#wp$4WP#tuA-$i_+-x=hHll>-7|WqDrKTv z>2JQ+>24nDQE|566MKv>w=I+WYlS&Ex>tU$T#kxWo&SEH+(1q{LF%U_d?g61&S^g5 z;xiKJuQ*P}d`i_+pI33TA(f8SuNt_p))%YFQjF+g4}oK6dKI6v3!fr)pyApSCQ#8s;32c! zJE;VtHZ?z`)d7{scGyD&cw2hqGt&G?V*%CmtVK!IZSP={#=^9%T!4-XzTf$bTlC|S zSzv+@+ue8$!nYv}AivTb#JoL9@d((|-GAo#>csC>s!`a~;g&nmo$2rbf1D(izIdP+ zFx-Pas_yBjhUeC(d|wM9p0hxTEU6yYKZpEA zOs6)v<0bC?+L4~2{%u0Xa;bAL+O6st#mzBTvRr@zl-BcM!?=Y9+cr+LxrM!#Ly9DcJ>Be;AlFU6wY-cgzsesga8Ytboc`RX z$3v}ktodrUwimKBhos=KA7eWaFMd{lSxgUN@7|4QvP4Ksp#~_b7tQ)e7N(WiVmt3H zyh~v}_i4NJ(vn+`>S83{jd);v%A>;XoEl3swP+Wb3H3$+c|?|oL=P!!)qstMHT7l0 zvc}e=-LgfA-S~pVxY~I4t+@RjGsT<3Qb$#Bn8nz%r|vk#Wup$=NUp)=8~(7tKk|0J zu6XV?eUH^rkP#5?o{WJ!Uk*y!P5_R4U>x9%#Hs*Jrbyp`3R(TVOa`6%6^j8x#-))g z$1C|#F|zamRdgo(m^}k#9B65+r;5cHaq+~v#04R|f3>niwk>tcN|67Y#@wW7Dk1M^ zJ?f0%giO(gEA5R$v;UmGv(G?6lvO@iy^HJ=jg@S~sn{D_)VGW8Z{s{`4zBCqXHX-kmnqunz*nO`5b9VnMlPVOrm^*Xa zerjCUe8hAWd`T!F(~o#bQhqHi>(J`$Ug|m!l<;e*BHcO(58SsSneA1gLj=+6CaK7= z;qB&Ok%L{Tr**Zo&>-bE{upf%Z=zjuq--AgAIn|tABf!(WA#Qt1$(FLWxfKWOH*ie zcCK?%99t5v2ge7)fR0mw&e$B(glJDT$6N!>m^`lHZl+LNK^MDuYg+>eEd?8+mIcCd zgp!U;>X!@$24$ar3O<(yQRMdu^Fll0rMw^6FqSRd6PRFnJ zk!D>;w0rx~qcEoOs)2*z-)p{a;*a$ih(O#YDo|HW^)sb3K!>g3D7TY#`IJC#kHIOg zMTtN6&u}Y~pWXI}9{&zZk9>wCy3M&=6bm!Gn^LXD1#|o^237h28Rlb8g4oj$Q?Ep; zXLn-D*NNDZ3+vljzWV~^)e+b0i>{qurfEmqNr{v+PhEeFG#z+=W~O0>XKt-d>elvulSYJF5ED(^u?`D=>p~Ui4Krdz4TVeVc*1PQcUy+ z{m`Y!I!WjhLR9F*p1;pKeVgE-^hIR2O==^yG$3l)u<6i!#RQ6kEOYdbFnwGYE>+vF(%Ehuhg3xX0c1W3w~$A@7yo``^8x5~FQlI^4f4qL7o-XRk%Gq%Y(lHav5)5;Z71yPjyP6i(l$2EO%bM z3ms5`_5>YOI(97OHE3~iJIz}y+&Pn5W8E}>wu1vvtc4?mG&)*W+cnh-D<`r0c3tMF zkxS8i_O)YMTmR_11CcK-(L3K?Xntv$umICzkQqTt0eQ;^1PfJqjK&|J*k!`C@DWwE z@8IU98)stS`)mc~H zEfz!_x=v&XTOV76Tlf`Z!l7Xy^Z%JKfIBu4uB2y#Klec5If4?r% zu7@>pNdtboZsVtw->2LnDNuE4uwzgoATfP=jqeCxT`5wvCt9Qy@tGki8_QU?kEuoz zg0X`1ybMnPwi7}nAWBj8J^V>%wLc8+D+t4Xdem?uN7=0xJ4Q;$jHJk3I<8;{QW*W^_&OK*C9rBYTKcehnclM3?q+WAnYIo%(9Eo|GLLyAa3(?~mXvovr zje^Bki#c19IpFql_8AgsJg*Vbvm^^%NC|RidxQV`|C?A|D#>djLnN~-Iz9DX^y-W! zw^X90vCUT~ea6YDYCPYaII!ta>ywnw)eP4}EV^;Af#Ikkm-!^~<-U5ZuWw+f%;1=v zn~rbW+ic{+nV-j1Hh1$0QL*Xdkw_ZXL|=_|!@9A-YJK$7LTQz+C#i%s%bkvREUzaNh_6yTjHFn^jMQ{&bLdW8ojrK?F1P1y5W>--$aj92bvy2{2%BobPViTI2b1XSRdMO$})`c1Uy#R zIoa@$64lq-z7zK*-+Thwh@p3)bfd#BA;Z{?SF#RmG*PRlw!#4ci*(uZulwyB<@(xr zLfj58U3@B2fOJ=uEp3`@-TMLB5!E6ZLnrESj-hfkcdwlFtdOej4r^D^LP|i$s0Z9I z{bMa!%6{OakdkGF)8FX`YmVt50Kc?qrlx(WYIw9=v1=|jcXL=LKE-h0YO_Dxf2iRN zF6EsfL1^(aQfi_>=It+74zH)AzuOvQmOEZ<$t^=oP^wPCAlsGvAq#u@Q=n@@PENL8)VyKimWcf@ zB3leW^x;V#L&M@!_*90^k$R$YqK2Zs3c^v@?+2->_xs7wvSK8!MOQ{a<@hm*Atg}x zk|43QfOPkSyxi)&{5>V#d^0Gy4=JY;ZQLT7s29< z`MNlYv=2v;cJ2PM?Ca%meO_7MS{t1NrbXV*MZds|pru?;vf$it5VaUHR%&ha>?YJW zCB^f2+MRwbD8sirUa)^S$5vbx+PSB{mSDJnkZ{`=mL+}MyNc;%{?ycy1fE7uY?}{< z&TF}D-sE@WpWgYg2{1+>Z~!@a-hE$|WD^Fr$e+_K>;uOK^0u7gPt>}X(D(G*V%FPX zs@;{A={c@iWnu>DSAh^-GPeP`eMrUlHYH_H$M!H?OrbMXG)AF)4(@?iz6A?Z^TgX6 zl6y`4u7vRCua|Qr!AxI56*k(j*>dU2cL%sLbIzv{2>w)7!)1og_0l+#_xX+E`3Gnl z^$H%ubFJ&E@R3Ke?+QU_eBVnDKaX`wWU? z2f)#Xi>YsnO})pF0d`bMHNaL)Oiy6;j4QlCSpqf}hsxQndXq{WvfJzvl?L}d=W7)R zI)tq$d(4F>5lG@EEWq#vW2gH0JCkYEN^Pse_wAO*6^rycv0v!6O0)!E+nx0O3>-?u z-Bs~7;nsWc?EzJY{x-oqQmI(hCZ(=1rem-3*0o50eJ)4&%|lt4n$4MlpMAi|l?fc3 zj+j!eCA_)Xwl+3rd`YSFO8k`@w+9{UX=3@a&ys8nx3wpP_vr=7NNyxxr9}i|1;lT>5@Zo)P%3-97NsTK z9J+m9%gr}c27gFfO>-XRIGfkk4%_KA{~twX8Q0X`#$jv`6cLdIl~Pi=;crkPARr?~ zh%|Gfq{pTxAT8ZYq;rx322ANjS{U6mV(1ub!{ozxc;h4?{18r;@tzohEtaF!qxV)0Ug_p%wNyYpX zFtG| zlsiLlNeR~frEKm9Pdk{XP)~ZVc64xY^R@g%qmXtuRzdXVW_|nBZud9!iQ77-(L&Bu zjv7uMr8~TShV2sgI^!cxi)@-2n|`_HMP%^&dLC25B5U{MYnz5Z)~Z<>QGxmp7oE|j zS*%$wXeZb;4oc`Ulwc=*Ncyg;+N&(AIyLHWVES@Pn1rX?xtI2l z#fymtk`se2q*U+bHyDv7&;p0z5^iA5QU882MckY!wlFCX0#^NjB*>3K{ zWdK0qP;>bTyM6K>v{#1Kr^<2HieomAeu5^i;-%ys)s3%Pwrp7oJ6?^)0o(x|9yU+J zKi9Q-+)J)xd$&E-P6U7PExD0xpm1&$Hpp2pE{`$1rCP{pw8sCvQHKrH;; zH4t5SI3J9HyfwcczvAs; zJ`{|Vn+v|)y8aCL2PM`|+=xrl(q2>^m#-Rj=5}4}DBT-V7W`!^_%ccR9WYD9vX@54 zT{D{F;Lp(Ix0R4TvIck|m^ZI^`j1{Gc0QZB@G|tCX#*G>jMdKG5LsEbuZpls?1oe8 zWPR%=&m06nqMBrs4HyQ5t>%#xFlA%2IdrweJ@MO!@dn zIhKjJ^Lhsa&_D^e`O^AB=Z;N>Jycc>DojBMlkB-jAuiVr%AK9{m!G|!<6i1+GFjJ2 z%N9QN1g2zYXP*_7!^_HemA~ z(Q|{$$(@34x^mC|-Xygt5>^2D(=4vh*VW%Rh%Xg(jw*V8@}%OgR$MP}X$@o0YFRm) zr0ApJheQKnzk-hR|4JlN`G#=KED|?gbF*MMHf~43rm8A=uR6VuE`4#&*YqT9*E>Wy z;6k05c#k}POr)$QCY!;|qPfZ=s%Bj>en{qYQme`z#y_+kkpEd!u=zu>#gN}_;>GtW zfeO#>H9*SbV%8(soWxmVo#v`Hl*Gc>i|hKAzc(jf((21_>p+)kxTnaA`@MIUiqYC- zArCIk^AgJ(srMeiI%6tq;s#t<;XS$WUtrL#I~(h&yi&31NnXDh{Ne|Buw7-W?Qdgz zs|)(1gay6>R+gB@LXGR&j6bIc*PCob=Jj#S-XDaM7NhO`&eV(s?={plI5~oop(6oR z$&?Lu#+LsqQ}psN4Vd8L>(_+V@YPG^ce@@_`WiQGcNN&7U_dR;Uno++Ol9I9-N;1! zb!O$hElR# zmb3jA-_UI}Q5DStpTf-LvTUuX)r9rgGPN=;WS#xmlS8Q)&nb>G&Kd|TVwQ(!^uGg-NqYUG(weHBxlpPC!eoO20h&4~#0%5}RIC375D5mx06&x7&-61x< zhaAPLpDMR1Gl%q&n4$heoYK(KdqbDB1;%W3YAl)!N`G>w4$fi*ewz_unUERf+k9BY zL@+JG(N>Mw8%Bn)xxbMzd1zkTwN}>*sTg*bkv_3ih!>s_pVD}6tzt-O@@v9`Q>>~; z&7K(HcG#VnJcdxjRpEbhk4sw}JbJn`XELLp#J0U_D$=AuFeW2t=eC7}gg`9o)#B>l zTvqLY|E~A2-i_q73lDmN<>{KX&XvOPN!^W=+V*E9rV^Iir4H*q3!LQP>O|LTk*>B% ztKE!6B2nzUD}~#q>s+>ks}AxBx^IUTWWWQ=D`Ng_y?7qTDiS{m0V8=`B9HG>&EhrX zI+&WkkjAS>!DnEvm=G?dZmyUh4kpUz$(eRshvgFIk!^-DItq1F7OF=I2(4}5UC?Wa zWg=WWYi|gss4SHF{4(E+vEzJmd=|)X*Kdiv*?SSk>~FL23X&}k>8VsL3lOeKH@^L( zlezjm2Z9_I(l=K&-mFOqzCyBX82eiWJ($^I4$f7@)oOJqGFP#5oG`3I_faj8#9^{9 zVKUb_pg6!7vDBOi0AShZZyasNk9#*TvJO)Q=UZHW!Jboz@JP;Wm*VB(;=i`J*h2=A z;em6z?WOvvQa832t*<;aNpW%x86bh|xXV)U4O!82&C3nAX}%xIVU5e(hwSy>VD)+W zNu~vco*7-Mj`Lsqmdy6|eyTL=fN}L39h4T64qtWNvDFm5>b(q~h)-`vhv3EVd^Ln^ zOV{N+HOMrAo_u+1X}^u8K6%=`OB7)4Bi1!wj^yvYG+hC7jfqo!E9R432JCu<1ebSq z-{0-nBmGD|$`zNFUB!K0M6La4z2j4oEZ8aL$qvlCo5!CX&oEb5x=Te|nChOgE4 zW4A#=;p`Sc4xReQ;n|4=+b!rBf0#kwjXK#W&q22sSouy3a__fpfA-f)ut2Zivi0Gz zv3F7_dc8dPnf=bteoA#IK9&w-KrWH2B|9`Y#qeMpvoZ9kS07zF=1_BMo?@QvN(A>z z5{3LUS=dc|4<2!?4Ofa(<_3!mW`3SFepI$z8>DcqS0!<(h0Z+V*31h*iyXN(nQs#J z&n0*jl?+=(4sq}k7kVQslJ;mDDI+Or9~QGr)W-=$Cmt{t3ts}Uv#rFt_ab~Y7MHE> z3=`5sN`o9`@%N!S(NL4Ru)rhDN|i5z#R4)iw=K9l=UUaG^WkM-h6g1QwYj8%BfFzJ z@|Ucuq)UvlK29l7-JaD%8OG0;M)C~S$vavA2rI7W#H~&?kkq_(BWYiAHnz{G6#>*u zJT*fHp5FM42a;o~7QQF?jc48ozBrCfrTT7<(GI-XKGc`EApBnY?SyTeu;F}-(E4m2 zkC*>N=0Wos3!A}ug}r08nP{%P(=x`tc@FYDt5xqH>B;x4)1esV6wpkISGpSHXosW$ zfY^}{d>CX0LDXpU-JG$Cg{6xs#nb;wm*6ZBaqQU(Q$x5{AU=Tg-GvT4g%giN`qvZ^ z4r9w#>a`0Hc2wyD+YUok#O%T?wjUXFVG*U>p0Z}g8FA^p^RH65)$Ozd>dgcggLju( z7=?dIKD{6b)Zva<(lKSp1x-%N`={|DaVB)zwbv;bq~S% zhjE>8w=MkJcAg~{eXkoM^iQv8jQ3EI`9!+!KTh#_2B)Uzc&xKpvLadUgv z{p(h-_-=uoH>KA;8l3+8QO~Nn*#+L@I+4^Yv-n|S_4V)~_!j0Tnn!_?bRhT~M03h=xOLh=3dwlTgurFT8LF=>w>;EFxWX+Np8nNShbtzq5`A3Gk4O{J^PyLivp_ zCy`h`9@=o2{b(xp?H504DMw$*GQK``GmV=!D}!vgK{_}bAC>C}EZ4nncTCGR`d!?8 z$rA(x1Pa6K{_XwMGcnuI1S$}EPE2ZSP1QTZcY}M%8JOvEgs-GV3x$C*qtry^XZuz6 zIp*Zg3DDp6F~Xp&CpxxS+I{Z#UYiX_eR_=bu6OcoSmR6P|K)?X$)x}s4p(H`d;_*F z_5rlHgv%%y(@pxE_V%Tjik8aFONfZb;-xSzGkh+!Kr1pwO6&P)h61XlI~4K2MY)vh zv|$W|7=G?wGxQ`SHC+%-^Qh9{t~zi3V_^Tcp%_I7aeLG6cg><-8V)6ih( zl9~xXE{{(9`Mqwakz`@L++bW5a4Vsx@7;<>kcaMHbP_Btpi)TKXJ8awj@wZk@_WR; z|Bz?Ub4{+aKSNF#8a$M>7xSRlAVIICUW_bf+}*`#GkxFo&u^A@<#rZVJv#1eO2rno z63Ix2r(nLg21YR4dp<$Y# zd2PQWzLzfqWcD)GK$pBfe2jxnWp>1Stzqo{py|olEZJkF2LuTa8mU3H|Dy(N?mQBJ z@vUoV%{F^nW>Rx)wb$jpYigZldUpLchnhe7y(G@vo!bVF&MXDz?OE@W%+vAC14`GV zLLR34qdRyR_qm?nVbCxNo`ucFKyLR71!q07HB4nE*a{W*%8(S6gxqR3!sh`?ChdHE z;_g9hH71qsP$qcxm@aO^Mv@Y&EqA=Tg4W~Rmvl)s_2_Fy%rz2z!XWFqIQKYSi%S1;N08% zde{)1(0py_Oq@!8sQqK%Ciu61nIYJrA#S)f-B1gjgQ_o&IA3H1PMK0XAgRiRp;Wa+%IbK2Vtc)jC9QOafmBfy z>d}0e|K4YT8=^XsDCHOFCZUz^UVd0y!0hi64c3h-tYcJuvSB6M_kcbdsuhj}JsVOnz&{7$vPXDFiM zsQw?F^t_x(t5y%)(JbdqQihqfxQeX_8n6sAEkm#T3=FGtuJng=GH;QCc7lbR6ZDMz zUw0mSy*DE>HPh_Zj^LV54Omu_d^{$e0rfU+0IQfkPavwVy$t`pxQh7(mosHrpAz`<4AzG6cw9|wnqb@6 zVZB)8*AQu(JRfE%V>#u%n|MvxbZ5;VaIaySMw`RHb3EN}fPYR-=^Q;Pir)fezciPGVG zghnNE%;h5{n64fvi3{^}&~AW1RgQB+8Ogr#0*mm#Kep2gCW*QeLJReZewUoyLf-`Z zpo$VR41sy`Xg5Hh`4mPKOLNli!+Q(qF#gBSvBGDNW$I3b;XZ%2(y8)KIGqENTh{PnJE|h>!zEe%9d&$0_Lb=&2+T5vF2=vqz|Ry#H51Y=Yb%`VW~A+ zwh@njgO+Zqn@igSgCaBU3~B)UjF40~2(raNwOi&Wq!cf_ zl_bUw`SC(JQ}m4fs_~J-8pEiE&V+W0>TcAM+qXW@lJC{leQdWTitQA#4SzN$_k@ZXntsL zcj0XZL@;Cr|=Pki>p&xiZ&i$hUA_PZ%q+s&7L)3Cy=SrVQcZ^K)a6-qS^_Lm@3oZUGixn|c=y5Z z7@yp2Rl;YvQ#bq@gbdNBT8Jrpl|lixeutzsrQX@a|M%l3r4*;Yv$Fv_@tx7{1W>f# z_k*7^aYAx9njyWcuQAYr?`D)$=aQ{qirgF_RU&TPt9V9RpTa`bunj|EQX`o@T5iGB zd>lr0_0KF(s<->4hA%pBug0{qZrNghe~QC$s>&f-lqB5ePVSNp8-XETAdxozo^|Ht z&7$JdoPbJxl4kRv!mcajjqW1fty;_VRDVjvzI=p4p3-ZDM=RUX!Iy%EDM;%A)NcGT zU(JcJRzL5ClM1VWAFsx}9Ca8Zrw$B?n%yqC;ie5_*M17_U7y zcxeS!`@Ie{oAzC69m=N;+VTLGN$vBxhbUhMj?pO(>nyH5t<+6T1l z11V3$jNSl{T(7$w&VYB$D0SQ93zK`g~8wC(?h7c3qjB~#RN!D+KQYaO?H8~<79Y+H*m_dArG89N@f}l$nWdJ|X1p*Q zl`_p7$isytQsD_i_z*fr9K!^P--`((obhE8YT5fk@t|0>Er)aVl)*aO;mn=?1{%%? zI`mz8$obp`7}r|9@MNkBWt`6Yz9+GCG;PWqxF?^>r}W2RiPZ6^tX0h1*Nd+MQB64C zl%){b%-d-2e(=IR^0auvZ}15E^=ihG!R!U!Mr2gRHF8v&ABZS`q4x-t7oKlt^rpeVNmJmE;m5KQMlI{zZq<3Sx6VAJ7m1kxY+2hd5U56@5ivGrHxKpSyh`% zs^0huk*7PaMyEite13!3_+WCyC5&&3_t9lHuW2C4ilt1{mMX{YcByYyYba~Ln8?ED z&$;C9IjUsysXOX2W)aH~LJt`eBsBczvlwsQxJsB(EdnChWFbQWGoUpy81ccy&5PHC zw*`u~&1&XP55$lPwfC=mHC-v=)mikBJN-xk;?~FDR@)ZL{+sk-D`^SfS?YboJCiPb z2@^g$UYL_dt1LN~75yG?kI4c8GH-Y05JB7YWX}&DY?aS`;;Q_jfSl$+^uo<%y|UiI ze{^sB<8dQzEEr~cIzKvw(Y;iDPk-u%MvFPH$iT6FaA3*;$x!u{}8^D$&PpUI-Vy5&xKQK0 zrXHDoHS)*4-2;YWr;|J#eS--Vv^iV=lKUO&pFips;RN^?i^|V&WWWg!GrQz=V1?i~ zO#MhGzZW?txfU$KPZR}jv%Oddz&KI|j{7}r?Lxl(U+)CZx&JL1@DCpQsfX0j5&*d(Q>P8zc%31y zzh3vR3M$fNq+)!);WJ-WpW%6Fg&Q~CbIOVZMhnh^c`mIs;6&T7rWv=p~ zmsan%V3Wj?e{>$_{_Kh_ef~?ILfZp51*PAvUw7Yp*c3WJ`pzl|liQm55C6yvIT z`QO^k>tfcr`^RGGH?Ncw#4dQ1LT8%c{ZxzNqHf`Yg@!md9)ld#JbnF#b;58q?%}QE zx#8wkMyeV>p6$RWYrI!=Ttd;4@m;Wr5;rqUr@MO3RioSbcLc1?{W(F!q2!kM4$AN( z!HlVnlzGJi?FhMNO^hk^Y+QSw7ptwqNugH0>&@~zoooQSAF>l_l#O+mu8sX6=~m_= z*h$)wEOh0_Tnol>@xDI=X_z%v_Mf)b#UCSgGl5T^_wY)Tx)>P0<9BL+%I|G--vFC0 z1x1IPlUR_K!3fI{oeAJW%j1=90`syy28s~$0!#4Ts11DWc`lS$L#<$Tt?vU>eAoFRY%{WNuP+^-_!SQ6O>NOlK;+OzH`$OJ)0oW zQm@N#J_slfVG}ud+c#1Aat*Y+#c%8}7vZmpOK0Z(@Ek z`Mi8&X!L8$o|aDK;)#wo{JJStgRB6Jy>Z;>9=QA;?{DW0juE{W6vdT>dOVV$bYGtLaq2@J2&Z)n4P2!E6p`PkAQ3t}%r3^NMNq zj*cX+kceZ>4Tps&ZlrXRtYOu&exWhk8VBQ*l0WF6@VzRXlS+v}skG>(SEa9#QZnS{ zhUrI~LON6Q`v(5e&G$(sJidF=^RL{WY*Yu+dAQSodSVfo@^Y&DZ;(bR0R;Nykf5OW zpg>nNbbB>usz2~8G}!;kbbztML2=a!E>E@h?o%0!LUpu{!HlE2q@ak~!Pz6xVsqcK zV+{*}yQHHpD?kaDjoS0I^<~ZSJ=h z88=`G+&MVO3k3oC=_t~k$#LKziq6%wHk0Mrf=sN4p^V&IGgl+tuZMDXaxhu<> z6DttT>p4{<)I*K2d;jRnhE~>;X`>e;R=T;$7VK#8XWUPns^Ttf_8!UTt^e-yX3S2y zA$?gnj?^@j4V>fD|3(EreKz4(7huG;FKZE|)_slnsV8dR7oA&KXzmW6wt;F>_RUOx!iH%d%xU%UhQ(bN_Sx+(PH+uhp>uzB7 z*IR)(`T`5p!|mxAuUnZ9`gCQk6FZBd6ngI-+`P0k#YZs9KN+e7riTc0~VJ$Tb~v}`v!pMw*_pnAKQ4_<}4hTqNY{4TGfFja<<=(GcL-D zk*(^jF;{t(yH>)f6-RyDFr zq0TPPLLVzBzE-#p_qC#Uu+2=%q&B4}0@06S*l%S$8$fUzELU$H1JhhP_xlmi(w1}j zl&wVXRSxNZyF|ZttiZdx%Xi@3$;bF^A%?R%imKvSV7?upY%V@7Js(`HJMT#R>VMSq zhL4+RZ{vd8>A7VNHsd;^py{OM3A5Dw%KaqI@tYcdL}G_J#X*Y3^8#1Dfz0!X__aUR z7fvTfI%H3<>CZFXo=Be2vmA6AAK305Rk|wg#R0yW-ZFhvJx@ljfDy5v+mB4Le`4Nk ztiiI(dUHf*QB?aSKD@~GLi-sPZsMK4PlLPqw6oi-d9^dE;qw8})&(zCu+HcT1jgl5 zzonq1YtvM=&gy^;Z!=-DPv|05R2Pwu| zo=i%$L%d<6QT_m8&BM5LgwB<{8pfmOiRpNPMLxbo3A%?(!}-+O2BD@^VA&QKyRq&Bj+v|LDs zX27H*+q0MB>Lrg(KY~R*$-?k3!QT~j-)(M+9xAQ)P95a1X)##c?`9S7j9_)ZQ(6{0 z({#`FZM;ney$vwpPw=LniBZx$J)vtzMoFig4C#s$T|6=kVu4g4gJny?G%tpJ6iRIwo<1Vcts(t zmmkUqcGKaJzG7YOb)CD-gU1=djnJ#yFrTfi-NE(ayCqr-RedNEZls8(!bPn|ECWL_5Hixo{dW(l*neEG=q%d z<~&`8gk?O7dZ#neS(Tc$u&&ha96h0{?&K;Iz8cSn#2Jkr9*?yun}OJPOc+dNOcXt* z;ZjMotbL*?ilj?+E`uwOjiGWXF155bJA(~PIvj*mBc-%v+>$Yu=7EJ9dzL`d(VQf3zjrYwBix z`9K7*#vpgXH=5WNurZSRYL&{0|-dX!s?6V+;SgIqB50 zdv*zOVS3XTZD+a^zXlVp$YRw|^GfqrwIR1LSEB47I_+~?#sBZ9xjbqDb zUQ_fWhAo-1Ddi+zs+VJvevbIscLnVhoZYfK2ej@)|5WkL&o= z>*##13LLJ(=T&Yj&>OnbEHxJrETfAJZ*N3F^4tANRJ{mC760ghTBiD!R8kD&6L(HP z11UAV#OL!b9uZDZY*HKhGHV9A_OSuH$(im93$E(Vh4AU}c_+qP&Kv7*o_g3*ni(eu zt)|UJs&1n?YsW*w47IUqTI(huxxOoLOM~~k^Q2&TlNGCJv~Owy)~XTeAZIV>USSo_ zu|hR9*|$zndR49$G#Nzp98kf{BcUg^zi5pX;7FF>&-Ohyry{cf z7VTUvB(s_B4_lTaO2B=cu{Wp{PM+PqwGT^43D0M3&PK+KY_At_5!#MWe@4 zmh$SPo{GXg%Mv70rDbCS+V2g`1|A+m47!x|#13(RT@}i-od0O*rb~@@3#qQtL|DTs zOoF^L!AE}gE4=LJ;ml(VON@-2iH77L#`}$auF_I!mUE69fQ&q{?DUb1) zQj9w*`08I^<*DWPuk*3h3KzmpJQt#W&GkiaX9T*X1ieYvdE3t~Q~So{H>MA30hp^x zigQIF)qH=#bil9)cbQOjuBSPlNcrX~HORW^zSx*LaN5vq55>jkzXbi}1)2NJqcwZi z@OejOl%-Qze#1KaVe6swa)wUw-4j2jCDp~rlzjyBX{<*pG&8} zJ$itWw2@dUi=ohbCc@O|h)oiIeF!*l=X!$PvJEt)$1g`zm}Z0MIoYhPm!6LgQFF7b z(w%jfNty}Hkq?O69&F^NJnrKn_ckl-Z za6D!tzhsQfC+r+KCuW=my&N0x2G@Qr6A&?)OX}KYRq*JO3ekVrFh;1m94cIYl&roZ z>*`UJ`g8Ha7pcjn?}|lFij=E*W82C#C7t%*0n39X%W_lgz9VwBH)bu&YryzwwdfSC z^jVF)SYLUKDAnNYW7M?!A{7{w!TAJ-Fp!%QlFXG+0YqJ(YHfMS{qwcQ5PzY6DC)1_FKe z94x*2u|Af#m;T0SrZU%$UsWO(VgKP5W$J!x_`8Df;1)mqK_6N>kSx=X#X_q?m1 zl#e;`?XiVO&RJK~wc2ma@~XU20kNCTamv3XIK}y;Hvgjw2-qUOGGpVKxW-}a@aCuK zr(X6=rs7iJj1`!;v1nnUx6t$pEJ#E2BQctFF{4HRX`kw$-`@uFnZ=qV_}w@uUjL$9 zd^I`}o+U93tq2`fgf$;_%5UFwB4&e>_>Ft8(a= zK(C_epF-MK@T{HvY$-O`G#WZgM^JrN*!w7Kupkj|!UPYsHeX0CnkhSxyq8|dZzWya zj_y-F{hQzIRk0%GEgQ9_&8ak7*=k~^J>RoCIc^6~~&5TeIz7pyA3iOyuEa+ykb)iE4@kLLv>08aeGIDxs4K)dhz@zL=v{+M#p^|Updf`A*0!)oVD^kWqZ8$Q7JgX9|Mz3xZ+QfF;|FK&#R&9hj=^ouH_ zMH7x!7@Iw_Vgn}~H^QO(nS(d?oL;vSn)0vDUto-dn1ej^C2}9kE+Ji+cx{1^YTRcz zfBuG`LHRztPt1-2U%E1@%fBAQ&)QE#o}ka@GY{Mi4l(cl?%yJpwJRIcDSY;E%0|}h z686=t!la?EUpRZh6t5KX;+*F#D>_`PO&v`6q#gOhyt8}O&GPr4b46y!@|gYa8rDnk16Lb* z=rPfZQ1*SRxTv%H+sNuvg6UVPUek!=U#9cq8bc5qgBj zzWt^DM{PZo-_U(=>V$8k`KV)`7a#ZHNAgG!S)#LIbZWOst-6{J(;_DeMnIhN`-1$eePlFQxVv?C$VV) z$&0+n$IkD4BzG5X6hzNM+shxPPkic^&A)V{ME7CVLsTEZH?3W)>&+TdQ9CN5zIjj2 zRtgneUHsBOB`0|MA05d$CL5QIbsxlT{IO9+7wEf{7Dib3O2|k3dgn_NbHS=Z@%3fU zBl*KDUJ-F{dp)nvh*Na~CUThzm0&I${q4n-fgdZhg)Sg>_N+M|=04^y`0roEy@&M} z%@lof9azP;ey-#A?r~*sa!j7^;2;}>_fjyh$lW-&ky|3(A&)ue7RmmlHlFh$dN|?n zlWWl)=ih5s!fJp^rVbeJ;NaLP5T-FkV0K|9#+$V}_h&m}Afj&H5|&FV;Xm;f8)o2H zco=$SbA_Vjw(w}6lF%wg!B_nf(!CVCNlH-vrfQenbxo>6&roJvU*n8^VNqu__TjF( zfWwKS!-POgCP(kN2CBw%v5zEK*zaR4moFBBX>JCaGO<|Ms$tUlhX;D!D{^NALpB?8 zIrCwi)5p}({-eK2D-Fw4s;-QQ{u-v{e(v%_sAi&bmd-ux!4Fv(n?*vaEiXK|t+R%* z@<7d5mVQ$`WT$N@T0T)lmQ<}0U;ylkXQfRa^Jf)PcgFwGIp88J6+Td*CFa|MtqWG4 z@fFMRo2K?_UKL@+2742$Q*0*M<;uViwY%9X8-*p#7)pAuixO9Pi(0fj3%VxD9zmia zcqYJuuXlu$VA?OtwrqM$^K-?^<2J%SCrRDN_rp>RixAwKXFOzc&3xO=dC=U-ASN07(8>A4Qp+m{P4{6wZEDK^}#g1!B%NSsyx`*8r*+WMf^~EaFyof(O~#yHgh6OflFj$)u>u* zQ(iQ9nG2#4Q-hyVpLDXj-_vkcn4Lf8@4hJTK?8}UH(g5uvZ9y%;cUKeSG_^<;7t|;l;Uj6=Gq`~0cB`ym&arJqRe{@(!u2wr?fensrDO;5e zB7DRZ_08We$G)08Vg5Xp&5g8^yX1>JFhJ4kLe}Lf+Mnavj*W%W4Ao*UU*bF1LtY7h zN+y=*V#P|2cq)G1eF%I_O9q1<=JpH>;4>l4YqNfjwtkITYpxBpFw}~4ug%!cVWMx$ zK~^0Vy#F+M=6H)A-l9w&-6)})CqLD*>V_0U&u&hQHZ9)x@8YW27sTj4x@xmHY&i0^7< zpJ0xixZti4fo2#50z6FgJ8Vz2Cw#=^mmD>=B@3con8i05C2{)>zB5DBhQ~-GSD;lN zm)dB1e0w+v?#4gjPjVarcCNP1im`KiOd@@!zA^uz|+L7w4I|>TCT$AWOX+GC0d?0onq{9KT5OzLjb8Ov>mO~cM;iu!v#HCd> zTff2hbyp7L`ve2Ut;n(8eaBA5<@HKL~ zT#l5vl&RgAGL1miy|`+=j2}ZQ?PFM1#n-LeKT8f{-7xdV7kC=?&6;JFTfje>nzlLB z3yQan|?rU?!Rim zJKdS2xI@Qw85@Xl(&UlQ^lNYl+t992gg}lOQhDXCYgnVFY-~LEB-(7vW^t7X*rx{A znZ${uV>>M7_yGn5`2nC3s4E=XLLnvTz7-72QvL!APZ@<^D)Z}_%&T`j%)FK+th#;u#YwB z{W-J;!Ny0{Ty{@JK+9Xg8_>qIOox;e^Yo?o{7^IJ0eq@ju#A=BmcB7mriP)@qE6S+ zbakpsl>p#w5&%|9hM_zk{Y+Us(&u(U=y8u^^dvNndW&o6tvvLtEJvmNEdJS%`kGk4 zPj-#DQ?sd_!D!^2?R)M(G9Ko3GF%Q?NF&*Gq$gP?yMo6T5m(QKl!brbnA-DQ>V50) zJfadV8imfz-Y`U@Z?yRBmPrr*Zr2>%Ad%nmdLs_2Q_62j!Dmz_WzDSyu$SvUKk^Y# z!I=R0g~i+qYalAA;eg}#Z8_5)AW(1jO($1c^^?vcIvb?K#OlJq^Xt4jkI5Pn~ae&T8A=bZNRnC!fEJZjKp?VTwA@bcR+&GdCm+(7!rn>Qx*V{sd-C;b%pv&kF{ zVCyUy{H^!Exy!O6O2weME_+5&!tcsc`ksr2A?kIf#N52OxHKfzqA5J&PjGM{B#JdY zA39KREFD}{8q1$>$Fp(JG9x){*79#5GOOESK*{W7*?eTHnUnsTq%j z5|DqWkWHw*|63ZHx@JrD%{?2AQA?(<-U7g_NSBD}$JI>+yb)L0*XPlrDe?B>_ zuY0p>|LCepSmS^tZeWzTz+dixb{Da-vk7IbTatr-xv6+s8<_q>aRhj6CaM1NJ}sp< z{wX|dt|{I^L47zqxpjXsFTuL}D{Wpx@rWB;vo`?=II>8YzHtnvUtNaRxDx}$q@tuZ|ei1k10Hqm2r%-dMQ zALC{UH{x2Fa>jtQu5Y73Z5`Vza=~`4;KWdPy)XbpK6cX@TGu#b)lus_(>SV6{Md%; z2Y`>i5ZlWMPbmYK`LiTC0yf!K26je}15d4+=3lRS1ytXEl;9hBD7AFBpbsych|^Di z3y){vtr0Go3-nQ&;oLTXt;g|~8zy5Adx37g*^hay~FKMk?|7;CtJGDs%a zRv%MYS2}sc$R$i62w{J%sb}MyOW#6>b2jsGGfLOjmF9+@G!Cty({PJ90M)Kp@Bl*s zURp6^CJaE`ig38!vG~i8un?9^znEiyDB{cZLe@?Z&J~@FFJM67MR18w_~Qby(-H0d zv3|_V%=?~h@&nQkS+bLXl%=pdgDn5eA6D|~G@PFK*v9o2_<+68WG zdayxv-r<@Eft?nM@P4eKaQtZV(HZ^lw`r;|5DiW9FS8yWfmPO)1&F`--MvQq@-&g0 zjk2V812)Oo@oCG`ittw{!M z1Odd3;sd5Ort?Lg;o8e+CNiSSMU~7;JXJ*eYWBV*H76{nb(M97(Ji67;+R}<2dUs~%MZVx z)G}jC7%y95mi<0&E8a7b$V9$(7GC79KzdJ3bu83o4MRDVU1SdE9J<)hwkPnVRB4AQ zhpH*q6CT&O-o^W34$XkO7Q4n`)lGjxQtcSxj=yueZ{TDR_n~Hq z)&D3u&u}*1HjL}kt*zQ4En2l}Z)vM`Q4}>(dqnKLQd*P}MNt%0wMS~kj=e+e5j#SS z7zvR`_`i9-`S2W$onPl`R}AWG z)2!O7eI5iaN{j%sf-Pp1RgM`!)ydkZ%b#vI6Sn~|D!WIp_$&A%IEtwBxu;c2vac( zJpTL^$tN_;{6D%lDK73)wPBN!^rSAn<-KTLY0HX#Np+9_l&nj(rz zmsChyD~sTsnM98@$m6l)b+wjQ5_k9Jj&TJwB!5w)Z%!H_>sky-#!ER0OO7SFp2h{# z_YF@Dc^PCc%AQE#muUpIhmE9&Rpzh?FOQ9~R~ahrB{a9SxSr|QDI-jKEHd?5@x4O` za3~si;jif|^uSELx|u|SN>(pIowX=CvG27$4*nikhYx;=4^4=t=?+Vc9-o%0PCkSx z9@zHvE;Ap8`Pm#^KG%ya{5NA@p*_nvAaleJAM=LkkBa4b638Kf7NiweA6hBIAZymM zypfohm*Q4hatAkrM_#8=Zp0}j^3w-=$DK_rE+?g+nf9Tzz+JC`Knvpo+~$YR1AAx2yMAq*z-y@23+x(l@3X;a+DlrHz2NBpprp)VADXMJ&ZFne zRuU<5)z=KpHzw;|7t(v(iwCy*;MOf7b-PS`Tns4effwyTPau?$*=}~>A5C3rZf8w} z?}#mKO>F5Vv>A)lWkVa&<$jGTh1clv}zSx5MBk15>$Z}!mEFWY436=+a}%ei2~`ADpoBLiQ$sAra@G2Q#s zk9HhE(xXboPn+4ptn*E2csc^FEp1&=EX*4J(c$zH4m~5KAj9Z)&6jC6^6Ar=8E%oY zC>0he^K>nUK5(YT{CKmw!hKSS*c3LdTHpdvxOCOBSolGk9N+y$Hvu+s^V(*o;&LSP zex2AI&^B}Mr>2n7a^epDHLE+Td-jb;MXt`$v`4ygjJuWrKm+8;7lb65%Gp*&qn-y< z-tMZ_#a2fp&~r4*-`SI#*#S9ec(BZ~lHB@VbfmdfjX2dd-kqkH09Qe4)caH zdiZ8l!{v`3F4>2xq!O*ly)1jH(F^9)o`XXYPxivD_X=SNtmwOQN8fKqb3K?;|0DUT z%44xcIottMC|@iqB>2gZY_ZReny6=Rn?!(|>KdNAm!n@r>_!@6I7&_V_=nHLbLrmnwg7Ku>0bus8_ zZIPit_*R0Oh*s}-)VW5E7Db7qttfDpkY~=?KHBW zOR(}UdM@BsG}{UsfhCw!cN@3u_EDY)1w$jc#M(V>Xh`+y0(8`~FP6RVAUei;MYFu8 zV@&)G%lA}vnNRP4-nO(>99li&IO#~uaI;l^)8+o)SENJ><4l{6Re74v(rdU2F`!12P#>h=q(Ur|#H zk%#Nc1ouUR`?RH32guw`moEwDH%Rm7uAY&UeN03vW`_LY-De974E05-k^5fB&>N-G z-ix|7%AqQ#QlwXtyIoR8`y$FT1GY;*&Px)z{{kI=H_)!!k836?Ybjqy<@ZJ8la|;l z6}>s*J%7-mifQK;-MNAbu$I1a>QFRom$(Gx6@sT=YnmefmlMTJ-B(9sos?zd%~(cXKh z5bAqX)Jq9HHhpUu1Wzlg4MtGVc{No_y&$oqtDAb^wj+k@_-hwJXzh# zD*id@?Uy0Pfya~UD-;tbPJ~uoUL`>((#xv(JNl)dokZY}jg1G_ZX6xp zJ9Uo(12}#%O-!4wZ0j zXqWE!G=NEkFYp&fnD%M!zxi32pQApHOI#M{&3<);GRs_+LInIE`$@nz~rx|*7r>W$5JkN^DqDv65y!Mr$7v_T>4QUm9v z=e|+-_*t%P$1^;f~=R*Yj3nB={C@)Z7rRm2v1fZBWnP(ZFHiS8m-}i9%U%UW9OC>_Azua80}`+rk2|YN zs~kbeuinVf3oW-POuWueUzauLWy`ZF9_(pzz@tCN%dPwvUr+jcoOWq^{7?XA-8F!jLQ7B7k(EpS`GR57tZkj~YjU4P94^ zCwbGrOgUEdV*{eoggjcatArq94b)v=JeyvNO;bPHn{$ks4PEB@j7GLnRWB8|YB{F= z?IkGb^)uaj?}VVGCEKpHSrX8EusZXQx5?_FgIkv! z+1#cFudB!mzz7p_1nR?SyPcLVuGXlt8K zt8JSr<=OM=Lwz6AgBkmN7S-qogJT+!3?l2NwU|VG$fI9iD4Q5M^|;i!{@F z>y-2s>ls&N;`|@onhR^fuY>^RFmhD-dkp`>yIN~mVNQGzkCIY3JPq-EjamF&L;MGr zf_F8}Gls^I(td8QmR|L54|j<)TCOv=x1};yc`%h}a6qE5=l&*6h|vD!Zk0W{t);Kp zvO@CFHwf;@4tq>Z@~Sq%WR~eEn*t9>VMg!K1{(TOS7_>;&Q%Y zuxnW**6OEjS?423H5rB$pSyi*yz}qmcAYKI+BhZUDHZVpLPHWShnP3#q(V$nQf8R) zVkOP1mqf-F1$%SMOM^Vz#=emksyHFks24>GqE%jA(i7yrodx#_;uXYw`o#dWSC}*E zBUo1^mUbYBL!<KPpv;--&ixWVcq}Q5T0z&81?K8Z;r7LJ1}q2cz!Iy>NIoIn(r%C`)aUUlt~L4(Z6E1^_)dStv1OmTUIHKDaTm6 zIycjVoSyLWP7$ScRFqAO`4#wgRGUN4p?5{=!84;IZiW^4LYJm$^Dft~Rh?(4T)}#P-5H8G^!hQ@12{~-@a*3WHTYu z<%;GA4eg%E#6N&vPU6T@2brD(<1zWw0G`ZXSkWmx0|P^2H1*5`pG)st(q(g+R)qSH>j!*DtDQg#vM zZ9}q!ze6B?jQpC-^XlJc=XI{8e6g9D?!0D6X^Nrnk>*s-XASlv-XW)Nrvrq*ZG4EP zcLpudbFrx}6T071*BLvM)=FNZoCun^PVdf5@iiPz4O05_LWsrdUq7=yM{T^$cmIzr z^_%#*JIFu_cFIyqyb1RFcp@Rn0}_0hz-HIjX37!l*XLMCzlP{dU|89!U?5hU%q^|) zj6w7JzYyAbbPp>hde^l6$-|$+Fe7yV;-ihWPA2%C!Cnh2r(Xvb7z;wf-+__$T%Ohk z+-*(F_DnZ9i8*_#$>Nm6-|xeh!C%S3^v|Io(4;a?ah5=M{q|ti$%Gl1v7<||3>5c! zY9lMc;ZliGs&IOY{r~V7{I2Z_NTW)&(3lkHzRUTOgO=ddgmqJ*=#r66VZW&9)Sqe^ zr`*mHo)rqBDE~8{GSy7mOhA0$cU2uOSK|_Jj_ub7z8oB$3*H)se&rr>v|W%HP8*c} z*d|}y0K<=L>etCKmnjMG%(bGU2#+%Fzs|631PE-!9Sb_tIxrvLmNsKm<>1$g*D4(0 zc}IZwHU*MSr|f;zpo*=k1&h*_KiA`B?`GVg!+-boT!{E#f{X|a`%T&&0hbA+tt~R* zI5K6`;~A1n))I5kH@I?{8Y68fp9$n z&c&=WkpO+y1B$@r(tDX1h#a)mxc9cHvCY09n}euS5GgMsQS#0?v6_sm9HQ|AyobS{Q2sI9l>71s-hv3s&zsuJtn>2^BKRbhWmt(Ez8)C?PQDG&caENZbhs; zMG>-CZ;T!wzZl#sJ}xo%6|*kdY_tIxWHWUhH9$*U$nx?PaePx&hXACu>9NFPc8vOp zvI-N2{SkPtlXUF)VJO_qpv1k!UVWiW`--v2ow(qXkEplNy=xqBh3lb>Y&zAwXs$1J zWmgW=xSkJ?G7dFfl0d6j*><3&v>B~G&j|~{P-hs|9+RF5QPSF$R`|m|Z4gelpVr_f zHccD?{i8Tkao^~)lp{)@D|zPN#qa?Y`5#@J!}Yg?_6Jpr9LH}Qo-}g{wf{$F2bfFm z$Ynv=kKWm4&y7BsgV#OI4VxsENX4r*WlSBmzUcgVVFi9^riMZLj?x6Oztb>z_LR^C zWml436T7+)n58!5cAUUG$CrysGYoCE106+$;qa5*ZCr_opLG>fj9KIQ%gI>wJJ1IU0M@s+E}QL z2b;YWS9jk0l~$W7hu~4dw>Mw@zF*d5LxB0?Dii$5bX9sP`5I$wYK(+RhaW*j82NBY z{_s&6;i7}~OQnVRtQ2H!eyk02(7#j5a=)&%OLOSjyUSxbU)8mB@R2W8zuRRVd!Qwj zF}5TiEmS~_n7|NegIM&s^1}-Sm9F{8C?Cpv!F%o!Jw#&)!-h}AaaE4ypL0{+9n2)= z!%kixtz0`boZH5*EsFLORDZ8FwQ)D>bPCB4YCaauL<-wKJ~QMJ9nla*u;?_&ILfsP zB{L`sZ30PrqUF;2bJJ_|A==F-iy(&c>q5udF0uJVqj`f_jBx1jkDdd0f2CajoZZ*KP>b?yis;U9fvguN&S>{Fgvwu?} zG0Pp*O*q;zv75+TlTI`C$lCDN&z9eQ!TCX;UZK`JvXpml$uZpd&-UEPds(3QP?q8G zo`bN1sc$mGX{6VIvKYftb>m|1sfSK)DN znJG-L|6(u7<01Gm$6o>!W%uDl=`@5x@*4!sgCpZ}{4ujI3Bjd0$ELypz8Dn2U1D>C zkS@GgB!9)!CxVXa=ViN-<^!PinM!J&me#V} zq3hDIDF@o<{;7*hNs>c`JG;I>eYDw)c)A-u;)BQEEh%h`TlAxRI94s}=(R5Tz=Haf z!T%OnR>V3-0f7w0t#x6J^SUyCWt7Nd{lDs;qk}4YVPQ~q^2FQm^$FuVLP16<2#~zj3b69bc=Mp;sOv8`qxQz0@ub&s_U-HmbTCC?d;tnl5aW7p-Zfgd)!mHlOe7 zh1_*QGL$!y$WSjF z5TYZqxmAUb^#2#Q*3wMGPhJLAkH+TL!%!!}Z`_?1xu0_~Ml!%HO=bg;E*vMXCck*O zQQaqhixj`cL&%nJdqUiOy7o;%@ol_@V6oM?(;Z`t%IBLC)6K|F&BCEy`K+ov2+7x1G=rRlYGL~TKTOHHsfoRMY>JzZ`~Fi ze;GF8yb_9(rDzBHfQ)gxY~DGXw)2ha)j_n)Teex2vha-ZJ2*~hRoJaYX4AxkqqWVj zfoW^`2GX8^k!nu^bFJOv(&@~!s-V`qOe}G|Z&90Lgh{=ou8)dj;Avb=fL@aJ_+ZUb zUpFOM8)hg}d~Y11+pv7|YCnGT@apAo3ti_TmMV$D=^|0eL5)qlSpRYdjpBPub(Q|E zA=97bO&hOn_!rcxuV0}cBhf$1WN(%V)w?!OF&dS7qb@OiNr+waYkmEMu<*V}-*=mY zH}QK8^sMxW=0#6Z=i)`Nb{Fj9)Mtkpm$7K7ZqBoiTfq}g?2}U02?6}H%*$r_%Xfj< zA%H}rO}2;XfynY_CE2yx96j~(U^isk$jce#{P^2>L7M^c|LRf?Vu+?w;ZFnoH!Yhc zYmp43;3ZH^Wq$E~l<1RxcGeP}!8tu%)78X-I@CFwRyKa0%W}(-RiCq35Z(2OBSK01 zyCG1QMG;^Kb^xs4VT`Wj0Z#F!X0+eI@gr>{T4%Z>OLSeyQue_)GIF$u3FsjIjB zo$yT47Z2CK_p;PW2$^%q?(W8(S8?Qcp6dZf0-noY=E< z_mmspGRbnw8vv>JKCt_3M9wGfK)Bx74?Bcau$}07Qxd~qY504E@Vc(}=`78?4uR5Q zqP#~7;+*D$tuZW*)STR-Oo1rC`%)q4&=Xk)q~H(pa;N~LnPvd$fM$m_f6-{&hY^@?-p$KJ&-6P8< zbtLHFioj)Gvi{Z9_&dxA+M!dTLEjf%ZH=b!&xA9aRVmS9;GgE<3AJ3_qi@H2iwjbx z1(FIKUk&Isa;{WrxTmfLfDSBjKQ)Et@%f-h`M$yi)Cw6fG1zLRdsrFaWEB+Yr~e6e zn4*2qgX{W7EQQzL0Agv$P4_!SPhPIaGa|TCkC0Rv1F%!&4k?==IFDL8V^MEGX0ELW zxyl>}^_TW3vQjqz;_~bMn5#`i5d|#1*%@7DdCG~6P$v+Yp2pe0>DoyzM^e?C${&}x zHN+a{XD+=MP}iVacWgq&L0P1bkt&yHwRgquvVyIx)_T#6uTH=I|Jv|b_ly3J0%g75FzSF{~AZs=wIkZ+I$^V{&1p$I8RI=eyVFE|BUlP zKVc{(SeqVpo!@{QOc28k7kd-nmOJ7gb1E#!1v{bA{gr_`b%XXh&tF@E7Qvi%kG^TNYmUckzT=N)+>{MTxeMgO?5 zZa*eqaO%)$*QtnlfmDa_z=_d`MMLW#)#V3fXE40@@{M+xYdd}Vt`s#X(k^bCHQkkm zCO;pqHF&+nT%VU!5EvM+`lyPnxkqFAEb48%GD5gwJT~>B;-@b5Pqt~jd& z1lDrnBNMGg1uW#(a5ZNjd8wR?+a+je2t8j{GfQ-#Sp#3+O+`qkUR>wMYdF|^qW%-l{orjg!$Cu*JwC9*Kitm^Ib|-sjd}S6f zvyXw2U4dT|oe|_z4Vnt;;CdaNDPR9v#eX?H;DDgtU#QbS9rXW?F6Wy8FU@duwomns zdzGs?@MLi|-+d1lo$k*844`q73lYN$)Vh&i&VgO|^m^J;Np=oNUnFH{e??Q4cM(JN z*|ive%=Y!Ks27Vc z94O1r$R%UB`c(hl^n1dyw2wIV)*3W)(sr!;U0sskUMT5KD^{6aBc3y)p`+)UT>{B5 zONBw<_DRW;x}K1kN5-WeQf=l-3lOFkD5@6Zr7KNVyXaqjpmgu`kBJAB*vgw>%d~XP zLF)Uz8;3NF+U+O#chZe>zPk)7{+W#0+LRjx-d{ASUT4uz+iVtMDvd%JM7v`z31vw& zH8)uBEwc+p(+B|=U@jCi!4S3l2h=q>C$_qm=d^-km~{y-6?eoObc1v*yI~vkJRM z!UN}{$kyP%cyRFy@87lj7=y9g@5nz^om3!gbNdyD(9Z-`pEZxhT}E?LS5(AjPvkaR z!)ROMl?!LhN6=YBXA`&!46Xpr|IRb)*znaYl7F1S2Y3$dL_+jQ{G*>+954b(kb`r) z2z}4JKiU4GqX=!4y$x1$qP2ciC18btdfx*>-^T#U1STMzfn4vv_1qlJSi}S*kB~zF z$fom32u2N%8yuA-%?U3n3IyC7e@=gnw>>{A8KJ3IKG9NZ<@Sr7 zngcr^4rs??+gXh1-^md@@Q9i6W2!+^;m6nBgPu-2lQ)2Q zO?q{7a0}2MxDXX zbYWCckL0dUOk()n@gWP&m}be}n{ES!k8@u?Wcuh*KM#u9w`&Qk%+#IGiT0?h{^AhSS_qR~ z)$yRiD`Ilmx@w`vxl~;R8RuQhGXMTF+0wIxNt-s0mWt+m(=Ucvs6j>U0>$FrCjx1nfr&-rb(C1N4-VI!o`_u;SOgT0PQLG#=alcKy%6UTjvpZp;z7@s>Wt9sy5 zZjVn*FH(YPKvu)~{$W1x)9#H2NWEw_R*P4ZZ>6{>nZBH0+g8m@c61WJPmD>R09pn| zo?oC6bk}YhKgndSZ%KB>mnS%h{u>FxIP)gvJ+KZW7)Hy`Cg`QU7SES)#%*6eZkOAi zMp}nz9mJ^D97g{>sTT(g&?G>%?AK7qfd2Bb{U{ZVrY6(I35fmsj+2(Bqj*mhn}JL9 z;Mt;B2arN+fS z7gZiy8sM!9;-^aNN1tCK)oAI4^ezDor{c#G>s*?AVOe(cK!tdK*kK3U^FV($YXupD zyf3E0=Zd`Ba_=VR0aQ|t6lI}jyKgkq^$YDd-q}1 ze1|3}MYQ8Q*qSx!$`Q)zBTU)WSz(4VZVjRgx>PU==C6_Kno zV3DOdr2?3zYMfOl1+C^@o7FD?znSHlmbudd@g=3l{J>yg(i|`NQyQNS-DQ|;dvd6r z$lvV|P1{zLp2F8+Tf~B^cN7vb+lI=JQq6sLFV|eY@?TRSXGy_F?6WkuY`wn8BK##4nf;rNb}Zy46eUesq#IQA#h%QVDvQ}pwb7mnqgb*&7Y%}*8ZcLmt0M!3P54(8;L%A>9IGj zyJ2(GlQs~(CVC8X{?bJLgtjaHkQ_i~2U2FM1hA#i!H= zmc=DZZ<-#MuB8ygUyYR5p7jS+K!)K)v8vCKVYci%E220-W*pLgD+A_DpZFLVZW-x~Yzb^^M5bt5! zXpww7_aqvcz>bAYDio~MLPe*W{M@*+|D!weJEaw?x6)VqtDKEA5Cp!_j3&8_#FQU& zro7`BP82@UlbMkaD8rTj?=z>sa*T1xU#9ngTve83jNC~oG3Pw>Ix{zD?M8wi5Y{x+ zMn=~AU0ZUPM-lrR5{q7Q;$6l=0}n4R??^WnnY_;x!64FM-ty-f(x-NQ6jl=8Z9_uA z*pc+BUJ{GGCfWKWL;BUK#IJ`Bm?_b%rIu1)EI;-2EWa-`PB5EJ+x}{BV;c3{NCd2G4!7F4JC>bfX*EW*2le+o!!=;p&dO>-l zEr@PeJwYt`NQQQe1j|i5NZ;+h zQUjQ`HAQHY3S=!aqGmYE>8;LZH1?hJb;w!cY!@&gJQlI*aImT4@>_*v!qCy*@l_Nb z!g7U21oIP0`P3sN>b{#Z7Tl#DME3{!NQXXYG%}dRvecytw(7!^IB=TR{ zjua5*&hz34A{f_cYf-}YI(XCH#}I+Ly(XrZ;CfhJZ0y^V;v3e#zR3pv+fM^fCdRzk z0s^B#^tagM z>P4Y`0u3Egs5Bg@new=5h5#>yu6_w;UjnCSv3xoLO9ePBUTKoBv767gyEMZ&W3&SJ z)W$(lp8?DU>!tr*u;S?vnnQmHaNu0|s(c2Pf2->jy2%(Am4bODnHSwfK?Q}!nDPqC zSWL0ashEI{;~SNZH#3LE?VZv70Vj*oamxC`FJoBa9p7hX%TLxHnp>a`H# z-!=9Kk0pufOLc+1{agD3LHMkwY70!N2q2UoKawPpj^FB-t?E&F;i?;Ya)ot>JdOR3Kfu0j$Xv8?LS?N`8ltw~Ty_vkr5f6Y*0N zXfCTrV5`holX)AnS5KVnRondFd6cYvSc4eio?bkOfBo}L%YmM2clzxh&+XXtuF<9L zthb?g_{N>-pAFHPINr#sE=)`T;e_DI>jR3X>{zVSBg9wfE?$`)2XgkzAzx~ddxoP! ztW18f<6^A5GJ_IKAOSE3Ibp0!$wX_H zg7>WB!0$bbo6wAUabryU*99k7s**p1kHJeUwXq5>6|R3ng>2I!UD17a*X*&MnWp_>;xGibkgIUA4({p)fg48Xea}*B~FU zR2@2cl7YEZ{=m~)enP{hT92w%*1)5* zHJJcV26bwd*7trfI5iZ@K0d8QKLqBsnwuGMH0H$1j~1A$x*Mse1DvDfrfCDT#?vOx zYO^HX{h&6Eavzc0;}#`a6hlYTLwC+=0{A!de!Q)(`i~C$JVQNY#DQS6UuM4p9Kb9^nA&J>&0IE z$M&=#3xb4jR=~BxA7vqvIhM~BH8=NU4|TYEAzx;^PXXrTQnFJO>y4%jcnrER-F^(i z@jWG>i}3r>ky+lPQopE$TaN3l7+Zop>w=ysOa*k_YCc(%jDJN|!87U8+S`3U2dp)i zl6XG5HFbv_RZrI6Xu=0VC|pNXXp97W`5 z({Uwl$zLT_{T(M)Sh4!NDf)FSCT$j=Maezk9U%_?uRJUrqeDl#&e4mIJd;I{>0b2t z*X9;fK3|%3p!Ag=c81RD;#N}Q+9g%?_eF1Fzqqf{MK)Op?eAgRU-8|l=|Uq% z1gz^U6Q*UZv&C*z9=|N9@XbYrVV@y9wMdmseYnc8$M+}(YZ9=q^eQ*-Ax3byP;m-S zRgsPP)%+moWtk3Jw7RgwT*th|67SExO>>%#-lQuOzVZ51@gSec`4c{vx*(tmRjjeW zAgDWMjDJGu8Ijl6&Ce^x@@ke{m*hZw!B%uC?A{hutWVoD3u@;QK-||V7Efh2W3h2? zoRgsDKE0JVa&6s?P-L+vozVTa#jF2-oLsrZy`;tAI7QFKO7AbZJpC(k8OL&W!LsQ4 z*A}R7RkX<*;h7^>&B9-UY&+L4oMSp0$o+1M`x*)BHwSJdL?Bdt0MauPyGl>kA^i;r z2%&QAeYU9IOM2eVd!HXw+$>&cLYSH~Ea0kAq2u!2dJKnj^lV3HlSd7xGFB^lYqK;O zfYr|k9C3_#`+A!RE;6oL&5GWuQQPQi4c;|q^y&*eHAog^|Iu}ie9>Z8sk}#vcq|{U%-IlGHi|JChJnGy5gk4GBCNB zs|D3}W+KXKyZls79eO&&bd*3`JeaSkg$<$}Ea@+h-%4opUSA~PeqJ!hZ*!Su27{sE z207vql7bL}+!mGq`H~Ei>8TsQjOM#C11csrho1Cpx(8x%gBu@b_DRfDmzFl=OO+nh zKsdfLTZ`wM38|d+x;$x!K*%PSR=I=3-!%@rhG}s9yD)JLzH98x=<&VB$d1**C%17c z{)YcQOoF{{s{g({MLRL;+^qOcwz}e!ke^8XATxI4>aQ-#L}PSi$}cy-p`(1I2|dLLJtKlvf+pcWep0{k3j2MiaHF8T1DWDBmScs zzk?f1v#BDrbA<0fiMR`avQu*vD zw#qOSrTC@Hzi!ytxU5EYDZZ0zS9=RS^w;lq6tb4xqgHgi-VoKQTKb9gk~iKvsI=aH zi$UYUFDvRAG)ov+CK?bk1Zgfre++xXEzR*p88cPy9>`)>b8ih7Ip z%qlRDD1MQANenfxkKQPkPkT4!oyE>hY`Z$w(P+>J)poZn%(Z zmsuPEe>{l-d$4L|Ye$782Ymr#OhRma*tI$>y4(aeJx80UiGGf^+rcM(J8;El507PB z{Wl{F7fdLd4ILWA=w@mbra7HaR3WMJ-y7a_-U%iQ$(0 zK39dQOm=G(x@>h;N^wA{**@uBK@G*w ztTPs?QE#uLpZ1;y5rl=|WzvGtN*!g@rczt37Pe@k}Co`xc6x#kXFd`NN96 z|9;#^o~kU0{rqd^?H8=SCVrX5zQ4LcDk*nm4(`%EJY;%FlHAR;3Gw>-dCAfJCW^3OOajZyGZPiHUd3a8AS z+Y(yra!a0H@DBBan?mB9xi7^HP=1@QJFSgPgZC4$WDTnwv{Yw@iMcHU@&&LpA9v6KxfR2?D= z6OroSK1sLH;vz+^7ZOgwrU!3&@pCe57HB|9TU#gH$8~B_u%djFe7Y4v{Pd>)om=A) zWX-aZ`VAHgmi}*CWs_#i8zY|Ppzl`0&CTxoLh~P#oQUU57KyVneOG5tlvn=SyCpT= zyGelIS?ax<{7P9)PTRKUXK_-Xgf>1BBiLc(%%kfR5VIcA9Af5Slj_bg>?5QJ``jL% zPIoDF@nal?o_L1PRV3;k8bmH;Y}7F0T0^mm!vC`RLEo>KQqx;~pa(h}A-Q+Xdz(0o z)Td8|M0z?B5Pb+=Je@H|1c&JOv#TL94(x{siXtOHYK@%0PT*`C!w2Bi&>(o=mv?sLrUxxK44lWy`)LbTQpV?^3!{AM@Q77%%^c(~cgWxh}QRo;^xz5VYb9dX_7 z_ZC`ac<6)Eg;`G7pX}*`-z;J&9@(W?yW+&<#`VMsU2hAm#}Kifg05NGA}$RirZJx zeZ5_03~_ja6oC(NBYVwFrUD13f=S>?`Fyu{=Mb^^I@kDOu3N-C*4*X$nyf=~;oo~` zRy-{(Zilnn{bXDyvKB0f0|~?T8r;fGK<}S1Sc8Y4U@O^fKn)OAQ9#v>9yM${Am)8* z4U}CB^2bFra4_x_TL&o}GZ`d%rw)9xs)U`K-@JVbu}n`DZL?~wc1=iiUN>17OS=R7 zNOwnLX^=8A0lnyFvj&Pe4O>sv@g6tR0FDCshx_Rs!e8W$w+WNThh{)`U2ta;f8?@B z(>M-}NjqP%@L})c_K%%JvfWF&5)j%K&rZo|KfOT$=+KfOL*X^(>e5}K8-L#9NBppp z9yMDM;MERj%#&euG<2A25MAQ3xRiWh-Bj@~r5hh8w(4G2Y}Q}qc-UjFH+bU9%T@Fb_5+-0)&W8`&;C-heu)!a0ER>3xD z8s}2C)Yr}!zHkmiO!@#~;TW}CoPk(>j)nJyE9wmNtn%EyvP1r_r;!pRH!#-88@gRS zWN{X&)@w;`*-sgJY4PWPOWX7DGhncv6IXXZvXD?=lz+qrf0^gPah~_<4EIOIK-I6 zY-_i5DEzwh%{@qYi~R*ucm}-sB*gNZxBTbfZRN(?jS!75?E0U8HLx!~TjIpT9_aWc zJ=5YC{yJzhWS4WnP(Q2zo^vde6jW@bUEa^)!#XI_DnHNM-b{?5_i=(aU9;rKkrd zhCqJO<&$lQSHqz+HCbp+!vUr~YTZD8`2d_tilw{{ME5M;@e^S&IlMA;p6lff9kYHvz-ENR zVjdo%nT{4{gfQS0a**?e3*)^~rSZ~dqe^9dC(1h`NHBa>_Qe6Hz195W73_Z$oo76o zZ5xO6(N;@UTSe^_rA6&MyR51zwS&~2Ns8LR(}CJWQ53Dc)riEqgOf6n^MDugrD zNZS7aZG3;PJ0gjUXRf3fe8=>-`MIr>nM2+3-e&NIh)e769rY{j<(;RG?*}ePCnyTu zcs@fGkkS8MH(p&xTF|k-Jl8I`$Crz?_oK4F8M9ZJV%rQVl~T{@#XdT+ce(}}ZYRt? zWvpjxAn8UhPoMqJU^xK4Z0ne!Jy}k8HvGesZn0)XbbvmVGSCRrLJ-XYLj*^5?;AAj zgs=h;5Q1eu1Yd}kmK2Z%7if$;%&B_2?RR%5exgHv`TdeldJWrIk=FU`i1W}YXQRh> z`~67jl}c5M%0nua>^9cJ^NTb4ex#I*o|);Dz+`{phR_ zS9O<%z;4ajtRdCV3i*!Caw6YlNlrE@_fUgn`?#iXv$jR&d?cOg>~kQkBGi=E$3{xJ z;Ijx3^91W6SGx2blwWo(cDv&$EuiIuU8!_`VPR1e;dZQ^q%H20^y7X*yz;D2Q*Vj^ zN8%n%x5qMo!|L3x)o;|Gk_DbeSzkSu9s@|*W zUM(Q`^b|`?y<>RP#`0dLHgC|vsq3V-BKpFl_XD@&s)hY%Y}-X{6($BCNPHIo%z33_ zB3uCiX1Meur%if!{(-Z{^n>sTl96ymS1FO)thf#q(Bh$40{71{F#eC+0L-yu=eX90 zE5qx?m79-2OpF0Rr9pQjFHy5;h993W2hVl12u9uhENb>zx>!IH556G;|v}vY4 zlC16~eXlCa?ZuyMH}BTcr*ft0k%^aR*5zS2>`)D2oM^Ddb-+V&$|@V-1?KJ(c+p-V zrv@)O-bk<%D-+JmkuwSt%n$!fztk}a|IhAn*P3AEU%S>da}kFITXg6Ab}0q=zEnJ6T;HoZ-NE-Vo$q9>6iDGRJos?vR3!I zEbfqABm!4@5P#?~(T=Sfd?E^L(-~Tb+MR>l!4f1idiB2MQbwU?61m0V-^|yN9_R7D z*$zkqPMy0+lsrLWY5+~|{ZqXI%TGhmERj=%I*!5g;|oueiKqi+QV(tK+V(JssOPmw zu7Nwt(6;|}&C)M}_5*Oe3aOnfZ&RcPhp4kP)GG5Mpm{FcWf8x-pTy_s44P5XLzRI7}V|N<>N0u zM7)uIec-QScY9cvzfk>aINCO;6F}onnSifXF`ElUkyQzZhDRnsk?b8Iw;8oc_;UKH z0@Sr^iQw!LukJDrgNAUEZ;l?8JtI|@e0$ojAMVj^wv33LeL*byj!R0uOSXTU{Ymqa z@HeOmpvT+K*cqjY&|FRu_UXMF-Kd*T1#LEU`KpgE>-1|=Cx`h~`GaeKLTjlY_n&FH zX!v0G?YglC*{0JEJ{w+0(X}_szsfA#!NPMmdUBT>=^w#LG!_-zNhEMFb^gNgGSx$r#_?8aaf}$PB3@J*dudb(T#{Am& z&XOy8GCLemYfNJ=(LF0_V{%&I_8+~zNk(so{6Rh$SgeWs^~>S!2-`3bTm)`(>jv&g zpTPCnaSAy~)73TA0H5XmPZ;H!iugsDkV9~8UVTKbaRR>n>iZ6kNji(?EKFen4GVo+ z|Gnu|%8SK+FKJbs1lH)We#*Fu(KtN`Dshg@tF5kD*_*>3W2QPdwqwq!eqc2!F09Xu zr$41u>#MG7egFHnrYU0S`&fhhZSOV99cc`mLad<&R z=~(bJ1&pRRiNLJmT)u^txOqNJm64e@2MfqaQJB=_+=>I?V}n@*BOV;kn=y|RPJ2LH z#T`O!e?GUD81?hFMO;~Ewn@odgM!hBrL6ythr41XoXpN}y^EC?tS^P;@qY;_xVz>P zoTTHI_l@z9Ewk?ccdiAnTsD&zRLiD> zTal^L!}Gb(BGTXo2Y`=@2jH9{7C!velG~5?2&A2#fNgS0{C_5e{PeY=ReY1H?UQIo zY|G_R`;rwmgP-{^IPna7)oC?whw4VXO~>K@yi+jDEC23kIob`1xo+|JkKFgS0~=x` zFC>n*mUj_ipEP*AMDW|!Ib47s4kgtyuS4XLVAp>Pyx|Li4gPt*NBM(v+T@*FlM4f& zJ@A2Rkj^WCN8FuDZ+9gAzUs13+f=jlM2Y7|&I8zyfZWV8(A?IK@EJwte($7=h>46h zc6jCesnGcNLWp?+s@0I3E$m}+m{L2YX{K9swoaGce(o(buS5jsJs=jcHFXkDrUf(( zPXQv}O!?-}@P--~VFw+tGxf9Iwj4O~8;fCSwd4%i;lt|#hY|JkQF1wVJpv_OFO&|! zOAjZtKW{>CgR=>Mu72iUVdQ5BhE#L%YSjtxo=5=^ihV>z9+%fpwU?hcFIJY~1O63u zrwx3Kq-1vNDZDyKxS6(i?>pO%jCBl6p@OCg&Wh3g1Q3Rjp8zq1(%$Z@M&|UbIp|8; zE+u1kTm+M8O!nY0mOkmQaa}@xpqVu%Jn(h-ie!D+k8$p&Se|7W@Rkf42wwyo@!)nq zb5nFj(ScJtTOEl2I=p~S3HfR+ExDGoQ=Bs)!A>*3T{UGlC_J*4nV#Jol1JT23%6II z;mOlV))#y3bhy%q|L`|S$a*IFA7}C+<4wPrR7Naf!*Mg-Se?- z5)I!CPPM-b9EmmI<0wuot)S5^)K%}lIl&5sF}atd8cx#E&ui-HOKKYP`937>0FN?_ z!>|{9V55DJX1jm78Infr9nehZm_}T=B-JM=V%lAvtL6Q-Cq#RG+Oay(z)|S07A0}y zewu+DhJIv|$dNFkNCCM5&c2O4Vg^uOIUHz5h0E&g7cAkTVJpUbb~-m}-cnp94V`nw zLn0RpU|%lZd>>Tp*NNIUsY&>c;h%6J_kcX^2XB=p0hps!u{^&eH=E@{^47UMqJe{J zhP-2fyC#peep@PE9ylvoLCdvQ0turr#U2{Rfpl6;@q>b1Uia&Lon6ZHJ-6aChlXS&ic z5L6HmlK#eez=yEgFM?u7;c8+$;O5@PN2B(w_F{6irWG)thLa=cLnj%F|ZWFbtmA9D8rKqOzMiz{>3Mubv3{&v{^nf^Zv z?D?aD)%}q$=jv{i#S{@|$QvU3X1%40NX1js zds7u>pBD#D)2AWa&Gd(n07E<)X2_r@kJ2K3pSQt2$#w*m4Bu{@vZx?Q6=4{vXMr>^%Rf{>>H zNCi*&JQA@fdfjr%)?Cn?fKFl};yCD*eTv(NlS@c^I{sx-6rnIO8=e=uGD^rZwn;Ug zs`l?OYiaT-OyV{1T}*m3DRA^^Bt@Tw0B5I}(?#iD@Ca5kB5;=ySP#G1gxcPL z%y6@`#5Gq;{o&F%46ZO{IN>*hXUBt=U}2XX)~;V#0J~e?>WgAQ5-d(bLnqVq(v@*| ziAH?to^!zYV{&oKJQvsRS+u-lU`ng}g+-Ly+VO=Jw!!aFB$pZC_7vBw70xT!a|1}G zFN_*&CNG1b6Yy3bf213ZkLEMEg88wS*KThKV>zU+wA}WDwGd{?TddMNWct>~cm;N_(yAjz03?d>!yR7Wa6Ca_=N)=EH z;#R#f+^iC?RuY)q4qnZY$48hK-HR7eD$jd?>&a4)u}_UL${FCP_e33 z@XcL1=KygS9tNPWkVt>Q`8}J=*$|w4A14sytlgIU{&8IbCVcNzlK0x|%)!D}rHsV^ zn)(}j6e~Q@iRK!1k?WazE+{HFn*|9&H)nYHV1#n~{0Vvl+7QaWQHoeHIa5&IVyHs* zr{t-J!?F|S6#h6bYIGyL!m#K=zs=ZXHPwb2IFCD!+P+r8{28(NSaYi(PXZRKfwZ7z zH~KF*7{9VyOa6gOc~gl#o4`wj_#}D}A~4D;>$TrcDvV-#Pq&8C3>#h=v|H;9Hkn4? zHfCC7tn^~a%Y>u(jO>7 z6WiR|lbPI#?WPOMJ~t>_DPkF0?=Fj9-s@AqpV-^qtxr_hQv^}dY>9YbOoPkF`niH% zBJbWClWGDqWX-pSlCm>ynKu565dM2nT{RQsk9-@41kixC&2;TUQ~6ZdBA30%X5CmlTBn`l-Wh7r$Fh;-%ep zY>7IE2$a{2qdosYeS1`*cg=OMaqq$7v%TN@USGFJPfeZBFVTq9vmA`Uc0V8-a1t5p zDK-bMnBxh#ACf{sx+Nd1*Zr=dN#Z4>!oQgY_gIo+TiMqwFs-m+eR9?1FW&mj6c9QU z?Qb_|-Y9oGaNaSS&x@zl&4omFbBjOb-ck{n@_lac)PG?MB|X@AyxO5Qr53rCBEhj( z_Xb_tNF06qX!{krs`n=Zs}kAx#-L_``PwQ;Kh^o(^7e! zh7n$Z^Q(-J>S@U9i^~SoMa!oi1F2#H(c=N9i0X`@ZjQDHSN&N6C}OcL@_2LjNtt`2 zmdNCUb;Dc-onk{0%u=+iS8={|p1R}|;8_wy^C&v$?vmMF(3!3-D^f63Lwm{D_Lj#q z|CCP&b*c)sjEY#w&t*Pf>KQ$G{5Q1f5uzf>OA}|<`*Xy(bNk!DFM%qG%4F(1ce7p@ zk+XxhF(GyE&}K#vOE{3z9SNta{aqbFhcTivoFyz3MDUUPj4wNxN@;Q{=WU$Nn;s7Dpy-mIaU$PA>xxhYdu zU+i7yC{(pFO%;(Zp)*BRzZE_$^wV6&xCQ++yV&5bMplYS&!qgo`q?tQR&Vd}h=F)m z1=}wzrAeB<7yo)f`NCEfDTw1?Tt@O`THkD(Jo1sqGL;;&}X{-w*iA28BPJLC)g?3Hg zJ#&ImW}%Dzs{Ca@#O2&l5CKm!`dwPoEH-IU7O~PPa8;~$m^TSq?c=b=J8%XXoGoo8me4YFr z1r#_sb;CenME>NsM<-a$0CsFO>j>PXuVklv%`H?G-h9X*3~o?>I+4;{@#`9HUeLYf zh$>JEZcLPYBR~>x$Z#?4qWEeiDxO?U(eE_+RBml<)jPivyqfeZv!1yEd7AD|n38}O zs9tGHes~qjw(un%5I%s&x%NB02CS30Q`0Xqc*)+W)ZshPd2POWgEAN0Ex>hkJ01lA zS1?o0D~&}CN5qS&fE7K^uDPy7T9%~2y8c?}pz>?g+h^h!_Sv$c3Wcn~#$5r6EN3p> z4ZHDS6f@A0IR^|hr92Kn?OpXkyE*|bF3y?G386b%T4^shJbpY(fCDt8s8^;q#@P{2t>4Y7=Yk(menE z>C63rwGH-rTqfL8KX{)+C$4p(`Kx~YDi2hWp_ow0T0`T)OdUEIiapyE9y6 zQcEc4;;h-EjrD^)A+tjZhc~T@@4K0<7U|*&a`WqH{s$nSwqlvVQ$c1{Yc6s#BTiK7HH^bHjp`<%9vZh=<2hQ>u$;?Jwe9S|KiBi;{?1KvI3ikb#U+S^wJW z$+wi-2{tpsnaPcNX0WtI-$xcZw@xj2m$erRf6)~>?6eK1IG|ALOj8ohkWEEzMENt< zUdXDZrbI)iY2y~g!lmhTV$ajqUnHPVj$)c9ep~)(BHz8-zii5~c=E3(@+*R>JJ>4v zu&VaCdR;io+g$UR3w;=r6Q80EkJE_Iw)-w$@|KiAzXQ0#htK*?`4r@IJakNBxLgmh+D6o*CN#nYFTXdSFpUrLmGY4sgHB85VH7{)!UG51+L2BFS#!3dew_#}tHF9B#y> z#Yq@*TZ=k=!_kL-HKx@!Iog`o14sX3 zkj!^X9L#CV3yDz<##t}cuzbqQl822EqV%}Q-&rM^+>!&IP>B_5a>7g&!t1ZEHw#45 z8OS65_f;cg1lV0J|oYmu9mFY$lDs#ZkTy!>}7kECi4dJDktiWTjLjwTfU7A zyORc3D2Y{^A_?zVzdQWY)5_Uue!kd~}f!!sG4cp#K;wa3C4Jx@$p29YO20pDVRM2A|RZ17G7ISy>G3mp4;7 zG@fc2Z7@FZxRPWmqias#@>@$rv|q63XrlUQl#Yvx6eYV^MxOBAbY`2)DhsM9eG=W| z!Jck6D8)tnp|XKj3^DwapZPSxSCN!Ihb`b^t=cn^h^hEuv4oWjAal}RCmh$KnGKMy z|L_Mh3ae_2m44pw*UcU=VJw$P<_Z*nKtlraL$AX`BthQ8pZFhtr3X-wYEP4nOOc7V zdthMZ9;nvZM~+ds+^oL(gSM60)Z1OB+w@tyKzXR$gcQV3!Jrm8i9sVXZCpt6R#4aY zl1nldEkC51%I(&tgppb*lzMERH<^%SXH_>}&JTU=AD18ojXQ=VkRxKE*ba+sOD+b5 z8#GwHM6w{)EL;pSALk661Ald!DfQTvOpowg#+v1qH?G-j+`4my`YS$}^fDKR-&tSv ztV0eX(Jr_Uw_+b$`u24UQO_-tG$v7+$t5UWyvBbPoPXOzkF~0Dlv%&S*CmtNUODO3 zOPO#}d0cYUPzEnI9HDy&GYcKNXgs7D=HA@Yj6`L>%?=->R+V?@B*AdEG)SSRliu(F zh2yRY{W;@yMB2BF^8#!f53QR#oSXVBQk_A{YB3yvN1X!Gf_nuCbF^_FlC6Mg;qrnU zt4-5akgepi)|@HY@RtQYgs&cV`D}uZ7cVW>5u-+2>~LHTdv-Wed{;kRbrm_Sfl~Lv z+y-aJ)RiB^3w~M40uc|&bK0*bnTg;uT`QU>UMZmmsQ z=Md>*=|n<9W`^6>R~~-x%S|I{<~NMjBO5)O7jgFCmJV{&bOzySnF!`Vul_xelzR(y zpKIU7fOZf54X9mXx50Y@`hjIPgUrmK%Gv9maGD?72`?^*{m{l$^Y-F-8esp_RaXVg zcw!m{kJkw|#fEFxy5;vfBQXnA>vm+s0e+|l4_EOvwrVA= zy5c+fFQyig+;bzos*3KS`!d81o&c-Q^cFVC1&KpkBe1C9L-w?lA4cVa?1AVEu<{Lv z*uQ~*)8C`YIdSq{E7B#y3jz(Y{jd;)j9qn%DCqOuvJNRAzQ`1gw@~NJm#J&Gr!io0 zGlKF*a5tn(wNoL3^$O4XhXIrUB*7S47qyn6=2$>wY1~T-6#C*CkzFGusan#9j=MqOobA+Vgds`Py*4Pz3Q5&I*d$0}OB&Kfx z#ob|qYF%Pg8pSuhwT0?f(3n}nQD}*)Ny?lJ#B2JhI~GQTRs@Tfx#uca(AVPrsA#Oz zlyc+lO+eb7lvD=BR@S?uxg`0LloIt|RoaFVOZ(V(r7AU1v3uay_rs2Vlnss9%sq7pw4xEe z=X_t{BXSQMFM9n(Bw@OjBU|N+R^k*EFzHsDdW)rOyw6A~yqlOa-K-p7H*0 zb@m%Fqj!q@o@=_c?3^^8%m(+y#Ric{h*Z^_0ZW^lgLP1{cH4^?q7{lYTqwwLB`Ot| zDPBE^)1CQYTXB}SB;VI?5z<}Cz@Y(17@O2jr%p@d9tAjqRAjv5l>(w@Tr`qT0Wie zfRG9*b{ty0ASx!gQFS>hJADOnzxIJl;v6x9B=mc%QzNeKCuy9%A$FeOp;&6xA5jDs zuZ?E;z{k0S)_@m5Obg9k;5Y&Hq(1O|Vno-IBIKuBVeR9<%sSop_&rlC`wwX&JAUyN ze|^L1IMR}n$r%=l{C;DvlRQUyBa0Hk$6Eu3hIbSG$mWWN#)0oz&+h4+?X`4yb3h_%742D7{bJrTpT*KDBi?kXe|d${j?ClkjsFUN`yQ${N1(o%lGh^m(X(X;A+*$RT6TvMk4V*>LRSl}*;R>9puId0Uah zQEJSEuKrsYDoo$r&C)NJv35?2CgH6)>g{qu|ecNyP@ZNuYkK5_PSyH3y`B;nm5pIg(O;RZ`2KqitV z*Rg~zgd|6m5w)52E8GD+S=+WhmC%A;$=4xqLyPtD$}Z4HeSqhvuS;#k&co*&vmWX} zqRE$4hI5mO`)<+e(yN*r9oB8za|_ZLL)Mqxl%4}}IgP?LmZ#JEp6M525LOUUHUU!b zjS+ZU>G!DG@_Rwrp1H+4v6YqYGE;ZYu~nz9UbxScQMCa{zlOMa*M!zX`0gf#}TVN_Wq);SW=E zt1HJJZg^Ov$eb)yUwi`DwqKex6uw7kOvlc*H}U&QbfRGQwd*6?@~#y=8%h)gr!@wD zRDrGh@w0JQ4bCqeuwm-M zpknGsteq)oYk@3l*x@1SYTs^~`Ylkg*YnfZHc}k5d0##q7uOyRElBR<-?|62(6xnE zku&_@Lm{u(Y)=2Cf&{gPChOE{&e6aJV%>I+&)PIAJ#9eX9|o^uw{)T&1~Yno2B!B% z3$K~pb%$ojTj?keoxC7 z+PHoFvwYtxb6V|&6O=flWlrWxs(RYl*z7is+)Y~fob>#y%6|;olhC!&`9CAGRwtV) z+Sd$(?6($*hDM4-E!)ECbXRwsN(eoEEy{_C##g)q7qVQA*3;k>2s--hSXjQ?862*6 zN&sb7dj|D2A_$#WROgp?v?aLzg7X#C(&Oh7M9S9Siu6$@k8uuPB2QpD16=;hMVIQQ+?oOJ`>`IxILU z?{UmF*25scR5UX2gNXSycL#Z(*&2mg4hs|S$n(U{zk%0EO;c-Y(wq2eC#tO*|Bx&L z)+tCSTuv|t$zMtHMALA8@uFS9`k&T7IF81%r|s6PQNwP;Ihq_E;A+>tJ<8FR9*_{I zg?Gi~&9n<2hk}CqS=O-~E6<^nSc+3^XN^2Zk!VPeC3Py)dAP+~;!yZ(;r;V^sk2Jd z?&Mn96Y&a(;&HvN+*T26SS(okzGvv;KAwtuuuStZDWOB{`TrO+?;rexps-lurqn@L z#yXg~RjlU8H#=5*N4oyR9Xak`P3~hZaN83ndJ^dB@VDdIZUDG4u)^wV;8YvgH(0JL z+j;xSlJhE~=8JK#f-;SZcUeQGV#@{`FG=fTxmjz~d$7ts`t_n;lTX%mL3D+Q{k@GZ z%Um9UE)QA-9#`Xc5iVW=EI((ml^ex(n&&WKUW1kY4;B+(IAH2j9~B7lJ!sP@nk(6J ztY2RJ{Q4^<99wyAL--_UI0)dZY-^&upp)9sG^4w1-sWj{60(Jc1l>sSPmWA2sZRP%O73DzQK-cFEq+E3G-nYMT9J)5J8p}!)w}-$FHi< z*}e}|TsCfraWgU1Do)WnPv*bF&z(estq5MT#dNzleixVQ7j1G?x%6*xO1Ni|n+iJZ zcdk3)?MRxpQxr_rJdh6v2B8egzl`NKRccJv977JG&vs_SI`iUfwEL16=e$~kpQR(m zFI(K7l1%Z}-K9Q(KcCT1FX?>HK9ZUi?3VH% z^%~VT+v;1GP8f?wgp}U!AsmIP4#uh*czXDc)vWDWoC9tk2vfZdm1$$z<+AOhY>C!0 zLLo)@9xMZ5V8X@gOeam5*6e*y##TItT9T_nVm)JxaXvH_n&CtJ#QTi$*IF|Iu+uK} zhs+po^L4T9YA0nQT>y5o`Q;c1`K_+>t4K^`BPaA zi0V8vc{Ri|&W)9K2)CP(Az>KTF=q?j_)y-)UFuY9Ng&mH^g-e;EFy>!fh(lq_jv+w zsb^W91MA9I?5rPj<%^QIFpr>|HW{?{ioUz94hqB-nFgF;8)C!3dx}Cj%rbao9Gxeo z045vJN}ql{#1Tvhd?mQ&EKQwa7*YBO{KDUpL-PP}j`n!CO|-kq#-4<^e%bZ1vkiKr zDO3{uw~#ezSmmD~{0?negmRfs4|D@jOXeGS4W?%m%l75j;jZt^Sz6uhUg`~XQ>l4G z$@ak@*Z*VasJGSbV+jCX1gj~J5;(!7946S1?-^a=ln1~F>EHyr6fuuHPCSVTUFCn) zZD2?0ywF1%IfU1}`Iy{Xr}E%kPQ~1;?7^$m=_Fzi)!(CLpA2LqDCF>)L#2gq^wnDDTCIbuONxQSXfb;4(1`UhS-Zx3&@(3Jn2(%p4Y*9mIZphB{ zNvibWRF~Y`YidwS`Cw$^-cINeQPh}qGoU56ssbFRLSHDVT3sF(Vcz)Mv_YNji#5$L zTb;wbH%Z7G2p`Mae;yGX!KJ~*5;W7h3W{LE^tN~|+8NhPzg%PezA8|__g9r;6}7LE z!`Z$3A4AV*9FJ56Oxz;`PJgODcQ$u}_^4M#CgI)OgRlg@Rftm`xIQ7VwW6yr!=^a- zc;4}O`C}W6C1=J_zyLkc0emvPm!4Y`OagOoLh6JyK8-Y6xE}iTzR*`$%FU$|J$v=G zDi2^N++bI-{wMRTpb*D8KZKB1XWy!rSD{9b$C z@&RvW%W+I`P{uN6+0xmKgg~xawz<0Dh-KjC#f9;9YhU?W^nRqvFtg@%j2H}imiADR zd3BQc5}!kbr+oY}k7-PTS5LF>-|R;R7f^8up<#~)R#IjN=VDeUDUY_3v$B1#Q8oN$ z|N0yF1BBJDi=Y}+j9~&EFH|K^4+Q^{cP#-~VZ*(#=CVHF2#$CML; z123bq5}H9d&ONKKa)E#W_epZr4f8p4yo~KrQQ^C{bXE5P8fPM1)=+^swJ@!=k&d@Y*=0b?9x)v>#M-B6Dvy8%keypS|9i9t&&GtMfh*H~TBF ziYrt8ZOqyrxnVPD#~mnf_m_WaqKw%r;cAh`Dww6diW~)hRMHSD`1aIpFgQDLywlz{ zhyk!A1N=J6qH;>gRR=_TGJC%CVaANB00blfB%wRv?#L$q^iHI{}N0=9@Rd^}Lh ziwT!>|Ll>sX)2a^qk$b}%Zk-*xvX+p!&K!!Q$9-w=MQ393d@M^kg`2_e`t0fEa#r} zBKggy!SauklzON4-L;JTzWR)VT5@*AuxilaVqwSY*Om2M+oC&eC#`|ic}q3#>38W1 zdDj%$MezV#JWf+*G?YZ92>$d?`j;@ucdl1P_3j&{kW+CvuPc?KzfPhhq8R1NK7MR& zw%;&0$UeTmFWrq|50ba4KM-w#v##hRS94lmf|(P2n_ntb1L4Phy=pblsM@?=K(#3o ztv7ZAi?ifXOBZ@Cnm94f%K%>^irl02k!n=VnmbfIBCad4T?yjqGL|@T`^8Coo#CUO z?H`9-GZ2>+by|Bb-2fFD`+wv7AmMn^WX1_qFq0zw;iMLhxwNWMHqg;^n|MI1s6Rw z`Q_Ki`@#2L#)alwPDKxG_y%DCrL}YP2vhZ_MDpk6j&eAq8LqURoW1VwZc?%6N-YQ{ zAs1FaMU&Zc@n<1_3pfiZRPI(L1)hMY!a*<4OW5e&Y_U8u&4rt%Rbw9vCcO)<55T|s zf)cv4(^_7yev6O&anODIq;Vfhjy%#nuSox~oW%2D=J?sp^(w+uh9~zapYAk^upN2( z1~bYpL-LX$yplc%2<{g(WMrhP*>EBwxz5-OqVLrR-_WuGJ}fnj8NV?fqZZg#qGH@u z_ZZ>#PyBquVijSGw!vIBUko=u_MTU1eb8&K%j+R>eE)Klbt?9m`o@jtjD56y783n` zpX0LNJDNlO38UG;Yz(4Cz|Q(1`EYZ*VBTtIvpwH#@T%%d`GJM`doP&K;OiRfKKrN@ z*V^yk=SVJ|2jd^2c#B{9R^NPkr6}THXZBBDoCe$e?DAgUHss0gtTiP5)(xC!o)Mx$ zx+tu$r|ur%j`F$pm3<%nZi3IzCoORzu!UDWmI4xyslSyi|FN9Egh09{YSf5ag`=dQ zyk&g3MsAT+((bz)_j`0V1xxVzdfX2zm!8Lt9tU&2+~%AYcAuZV`JK+6xfsL`+OPSk z$nr{I9wzM!Avd|KHa^+}$L3uOm-Dn2*jEUU!P+Yh`KHgM8q}jzZvPWT{b1Li-N4x_ z;$BmVh3Cl&8Hp=6`%~TlJgvrTYFr_~yfJ*dJDk%{23_WOhLV@;P-YCBbXd|NoTLh%O|@BYW|NDz2Ej=D%AUZGVJFf%IZaJZIu za#WLmg04q)NI#6FgLL0bwitBUAjJR~e|vUVh{)n+;8 z^sPWoZ;B56)vG98QLvGB!>%Hzz*Gi=$UF6pyD7NUQ|TGLlD6F94|o;$%ZS2yY@fM2 z%Oi2<_2A$wx%RWI$fM7bG?P+LeHneUMG4j7G{u*fR*Nqy9taij+yr!zo_$ zZa;dnSY>}RXEMks&(;<5n$l(`G;W$v?kz#j-Y4L zC5(1UcBAqd){8{8IcY9Gxi~Vy!m^Dv3jmt@<{wuXuN2-08-04tio<)w!eb7yv`FA{OnZAY;Rk%96MOoPv& znNdl7_^uM32VS{N?c~;2N(O)FJ1#tUH4hBKVfI4hU(D!Z8HCg79l_p85PiBsBEg#N zlRp9_y!TOpnIqf57&99$om)LySxYNJ3GOu8<9crC?*Y16<2=^bYo#Q7o0&w zn45Q<;eM~hCwdm=$$*AGgzkV>y302b{Va8wN!S(tgd9dmBWh!ka2YYrv!Zye|4;^x zXiN_~I2!}HsN@2t1A1KZKAy%|7O^tMo5Cf@BQYGIvJp?kA`=x;NU7#W^e8P`NUr)JcGW4;8dv$${-QEuPT>aSs5nM(^ zJ(t-9<@oa2VIsT5`_3m`;t$kl_4~GDdEbf3NPBrQxsUHY)v7&^FpcX{`|{GzzXY@R zY(*tUIcRS(vHOHFzjWPl9ASm|76w{PFH^| zi0AQ>Cx^=eF9&7Lt&vC3KuD{=HlF!!(q*_&dkVtSHRA`^*9z5PDjDuEdfZ6nWReMo(icDF#-UN8x6t*C@ z-KAY?I~k;T`TLri77JAu{t}=Ze*i@hb^psj@gE0NLtPs_ z%6*>k{mB(w!<%B-U09|^WVh}xR=}$TzU-ldOkhDp{jh{!!bczcW|EH5RvM%9QB@d= zT-3XG0+m{}f}&~HQ9ZK)q9=wc336^NpRRh*h0{C)7C+GAIBwR#KkTc-4Vo&E#IKkOKBYT-K30#rm*HE=MW$<-lna!F@M7oO2Q^Re4}UVNk}eF zNQ>&MTZINfzM?tsO}-jzE_^-?2DBD?(M zh#piHn%g+r15!opb;P3md(};@i5!a7ry=1x|1l`-9YIpUntHWQ{~|37!h{-!E1O+i zyXBqU9ZGu|qPt-VJ`LG9Q?1^xQrn7v;ze0=aLcEv);36=sb8=7zxtq|sT(&BK?FBf z>Sp9xhZ>#ZLCaHzSL>kS9VkXDWrBS`Md33hDhZvO7I=GM6!4TtzFGY)aONSBX>S&3 z8CoA)Ra=m$<^67#fxoQ8(S`SO#bwdMyLN+^th+Av28|ik0`e8X4Z)Gh&@jB*E;ex~ z(Z?dKZ9t=GLB#o$gm~i&rhkOZJF282ESD<)0|g53h}4q1XR_NbPTwaa>#jOByq{2Y z)_;vNcV?SRzpbnha`osy`}d`cRVJcrg@-Igi5NA_c`;>XeYx--YrCnOb`=d@Z8fT1 z??PHf_HyVZPtPdppj)3G27+#ebH5mN(w@1WS%n^H>TB5x7{PXrKD<{;9_YIn!&x~9+=;lq&v=Hki3g$nKG2_M_hOpE!-?xhYXQ zp;l*^aBGg5KJ=z{E^hQGD%a8-$->cQwJIcBr^_rare(E{yz;8sC0syd`qyi`R=9kig9f<;OV^SikTK+6(NzS|YkpF4yo-h2` zFH=bDBIq&k&u)Un!m(rA8g9jXJ}t^w!zCXG?045vjo*pt$$tFwR^xMpw6wV#|s0iuTuj1 zP(zqss`egqTR9^hRJJ_4qES+=!I;Pgtp2hKuc(oQ-8(N z6;fxLk3Q_98ILH7k@YUN-P)=S<7=OBurp%!yxzy>b;S=pN#R}f5D6ThfZ`L2EA0#j zILSC(qjgzGb+P6m#8z%!CgRw}Ff_O=VX{JT2$R!R%qAH2J&?gvf}7h^*}}yk%|I#m zo%XyIjmP3%$`%Z1;Qz*cbNZ$Z;){NK>ABn2``7&TOvLge-}ELAZTo%YHhqYBazp`P z%J?RCW>gjwQwOd2KDq_Sq>JooBxSrCDD`J4E1X=+e=xWxFL5zmzYeM%B+-AXn9&&- zN7WI&>x64<8j_l)yipI>du1;N>aB#(C*rf64$Z{%h0mXB5AjvY$~{$?cX}7-9nITT ze8KA8uP&sb#Vu^XTxmJ={Il`eghIif{czjEQG|Njn~pZBd0~`xPOHz;MY3%8k2bnuhe@6`x;A>FUAg9`mHN{&b`PS*mYDkZ`3uQ(2wSI zbM+Cs{HxPGgq**^>uHL$V?rNtg_S#a{1eZ>_AF7~!rdBbZ+&O+r(|`j^?NuzSSCnw z*eYox+7RT6*GT+_aszhA5$<|RldY`uNYpLCM!_8NBiw>S5gR-BEIt$hfGLj?&c|;H z1%sM0t(vJ{H8vosffAK(#7>FmW@plTZC66oyKj@CnH|>GI|3ZL-$p14-s8+k!OQYSYbU|dE6~LhIdO@ngD2)@u|Jr?x34deV;V5UIO37;Rhlv?m@n`8Q*2)V9 zX9uwUzP6YMyfvA{an@)rXiSd^03%}a4;m}=vA+eSz&#U2snGl-_>NjOs|Vp4qTKke`k?{T3G>8N2S9S zkyOGj%ERuE$%4-dxF-aP#hy1_-jAi!B>jBSmo@TctThBPVjkdvw5`dSOAddOBBwgy zd80=BfLcp{w}JvC{RVUWVi`te6dF@s28$$GSere?L3z=x>b1?G$;hnq3GMp%J?6n$ zN+QSC=WVp_0+ikRHY#lhnYyA;$-(#o>PfWb2_0Q5qODBJy~}?PX&P2O^`?){Lokz2?_fUUs@x6l3sf04bc2e23-urjTED=kXg)9)61l`V${%8`%J<~(f=lFAsZGnk zN2%#H3~3H_;|~L&u#7X;-Xw>(IDR6tml zokYF@zXFxIQjkV14?flXY|@dQ4Gd2^WFu~R`8buGgxuoJ2(`5plEiRi;&%=%UU}n( zIotY60+S1q#DGq)e+K%H?HZhQ90pwUshXZ6BU}8BdASjH4-dj8xS3K|t`EFK$z2WD zeKk`-N29JOUIHYUKUgOg=TE{%Kyg-gn+`RS`Sb+5Ul?ARkGgp-_Q+0(*O-ltu0^kv zYvyK%iy*IO2N#g?Z^s1iS4G`oD(3d;MY&i(+swUI@19}8^1E2r8tnTvK-IQrnXkQ1 zf+2~jBTBOfK0QQ#LP8>uiZku+ z^I{||y}lA^*%CgAx&&9ww|%mr$z?`0%Y7O@>Ms+9cNg(>{KdEiDS!z|&opaap!d~+ zHcxwo&q#Q^Qqb@*Q{C4A7+?JjISbp`bK!r)5}W&L6wWfBHE>3%j?wo`B-pdjdJp0f zYxvH4LXZ1RVa$sz76|6Ux5f*Akhja{W8>4M#h=r+Hw0tmsP9KdS`c12tquv#&X$Fi z0lndEw<6AMLVpu1(@a7-lT>pc_+?t%KTmIx7Q-7cN`TMn966;e#n!&bUlEiK?@eVn zl>Sx@n&qzr3x(D4|Hc4uyTJ*E5)l;u*7LXb{>~4lL;kePxjIS(`QiWJ&Q*mtS!4{m zcfHi6($3iiW8`4&d~x?$Wq*9^V3RI}+QF4djGxvo^N!5`IkdT>iB?up*e>&5+*&7! ze17VB?}Q;hj!Q&?Z;)pBJQ7yFXe1&&EbMKxJ-Dm7R^x5j_nLeIs!x9bf?aKYqq-fN z^6V!uO3#NJ?DE118pQXv$8eo9A@BkfA6$oNOfn~CrM`?L&Wk>s7rYL!*!dv#VJ<7$ z0A-Ld=uaZc*bPt{H&S!w%0JovE`CA?jtI7Xykl`g!Y#FvXimUFl%^@%v%WjPX4JdR zGO0WAFd#FMjOZsvKMk!GTVz}1Me4aK;!Dm(W64H+&_DkUUlltYT zd1R=Kg$%{5KiPzQRko>Yy#tt}yob<->DNzk_9I@l&3b!F7b9oZjz(N6`*wf_-b< zx|dPr;EcHnO@#Y6f)@pyKTlSjd>HO%oi06281B1sp#y30$Tec8wS0@G0(MBzfWQKD zIbVs=+~$af@Y6K+eNQc2^pv6lkjW5~Dkj#e8mAk`yK-%L;isR1=}`>e=mTHU?~wmM zP(^`u^k_@|>DY zsTBQkw~t!!y3r*+IA|+ux3I%eowl$iz;&KhWw|>;Fj>Y@E!O*O3XVT}tN5JE*SfUn z@ciFqxY`|MEvH@9=poQtz5Nudf)Kla{RjGWm^kQ8mifrJYw3J0=OBb$c^8JMXWcptab{6S-u0l#KW0xEf5)-#eX(Ho|U}O5dI7 zx;pszPni#!QxyMt!|A3IhefoyT!bTSJfCK|WchRGm9}t-gCR!cB-XfXZhyeXXX=l( zj!XJ)w2HLqb2lj0Wt!~b&P6X#TxwJR$Nlmv&&Jas5k&Eq16PZ-;?n58Z?Xz8{R*4^ zQXz$X;V|4~ShT0^JJ0y-7~eSEe560EuQU6?Zankq`8L~w-!%p83yd%}G>S*=dZfYk zgr~>T_!zJMA*MT!i8P&n+TDM~5ELXFwthv7*wZBb;Crk6;kDw$I)y+Jak$B6)hKa< zrYh;Xo!`!SPy0Eo)Y#3Nci zc_e>%bC=iTnQX^Zi(0m~8ZANqBfmRvDEDp+w^SI;#j_0XU+rVyUdeDHO{V5wh}3)` zX!llqbXahM_V(u6#hIQVr_$-8|}lY_G#73;tATMGuIDWWxRc zEquAcZ?Du}vRWqd+Rq=0Y2|n%d3((%d5B2~;%g8pz}w-}nZ4NR=!yFBX$co;CA%&` znW*LmB3`6H^1+fkztr@`-8{3ykIX!4nZ?-gdX9XyYa)2tqJq2(g-)7Hy2W>mUh_(Q z-QtHUv~+r!m=P`uB;%E4_Di-WfHKO1YKAsHG*%GmwzAN;C87D!kVBvrb@ z^w}5po$u2bPM&R<9w$?p&QuFtjp`7vOZkY%=%xoVn~0pjVlivz@RfxQ!19C38sP1P zoLGhDz(Ta*4t7rsj2%LRQud|n5hZ1n-h`Qo>t@e7In45r)7k1n^V1^O?vjqAUh7fV zw&H2syOi2Qt=}S1f10^>v!yja$nudDFDj+(-_2Y?d$Hz&QYq{x&SRkA4_D2Np3@lt zSUuO-4y#p#ZDQAne8lNF+*}-YpdltC;YVx(bl&~xU7`1blj*4}!LF{Sc62e@+Nm<( zBr0dx#+|addB$W<7{AgXp7!1*$EE`@M;HBmHzG#nH!&#JWzFsH@_gLE{2Z?4L-SGE z!HyiXKbEsYPap6(IytX)<6c8N;2Eew(aOO^#ie@L1;5?kwIo$}*(oOaA$PccA&^HU zjSu&f7SJnM2jiXJVir9|KxS$0pqw#ZHQ1<|lic|NFr_CHiv0O1AvvCa74;hK8T#ac zT1z-;i5h)iqNe|UIRlp>gh4DmN3<&l?zxAA-(#m%Ie>r3Pr)sAt=fejc7&onRL65$ zuUiSqHMff8KDc|Sx=7=KRc3sX{aSlYJTIPWi}|>K&{<_iOY*i7HlO|>UTl&l^rlt# z3?_``vXC+O76{nN`KTg)MGXMY7w%e5w42T#2EHq*T^E%WDI~%}sU^=7y}Fhv3hL2j zin}>m8tCAiHdVq({3oPvJKXnpRSN-^B<{`0=aw94MT=*b?s$QCb(Dm74216f105aa zf7`$kW^Hf3>ia0+&5`Hf7v}|@-dTvrxup9tVg%~&%Q7zP2i+fuk8EFX^=s;#kBbA5J`6Kh~1n++xor2cNxFZ=RPXWoum1! z23FP7*W$uH%85T~VSD|}H+Gu2IiqvRwr>|akNSWxS(I0uM%Y{?Oj#=-_Tf*C{|Q^m zZn`^xe~r*|+Z#O$iF&xF3M4bgDmV1p9L1>Ij%dQ>^Q+&A=3KPWj@n&qoOYJHQm_17 z0@1NII4@GXD{6_2+uoQ2jU0gHoQfYyj5S*Fvq_$^4jPB9;sK`n0}8UkZ7U@cdWaKpb{Mz}Hi+#i z)Dl4nq~RezB9gzD=w--RpCZ-Y)Df7|b4 z8G-l42tJyV{1EW9SLZ)A`WXY#T_@{#l+FP_19s}2tosA>svfo;bGt@hf>K8gPxF;V$7^AIAIKiAHI4PL%)SquTyxi?U!-(u9B=NXr1o2y z0SRG~A1yKp)!2uaRHc?a_7A}!gv|;{6q7s5*yP!v_TF(^I)<|cl#IpoLOOsPVy*}l z&)(V=KL7qANp6DGw%DCp(@_h0p_FK<(7L7_z1oz)I@dCw1|-iaKA7Z8y}13jizLY| zzI5Ur8S_rp15T67i33uwujr3?BdiXra&App zEF-Ula;-ZaV*s#jt0MClL!YS<1#S$tXnzh$6R-Z3uy?)mIUFC=6q zU#Q+xql$VV8lgLl$EwBG$e(){09lYOx^PL^(YgJNd{0fBsa|NP9Ham^O7D@K%{Pa1 z_&2hZ%>*EK$7`xOOWk~kjX#5*8mozWutofqjy?LwyuXNh4_jXs9 zaW{0coNL>+uPGy7q*|Air5KMbz=q;5>TqXj%|4Oaa<0;n9;CSRm%SO1bj4ykIj&cJ zX3}4mbymN`-jJaY>{c$Y;IMTZpWYg0CFJ`j2*gFZ9o5lSdt;P&KG)t}wPsOITI#WH zjo53hjDe^3HKU~N29*G|Hd*fAGpxQ)=wIW2R~1vrrFF*2M78GA$0SFiX_Q|%IQ^(? zyeHSy;MA^A$q(Cdjep;n8i#3rf+@Xzk8R-`YHtv3u8B}D9`_!}*XI++*){wMQwHK| zk~)1Hni+l21l65XfB3asZD5FV6g-R!mk{pASmCCXGA^+u2)ux;2VwO2_{wlVMk$JC z<7un=p;t`GUh}-Y>!g_wExQa*AZ*z8%7#fVd_^h(}`@}jx0lU6!Vlg^U*Kb8)1 zUhuJD5K-cU;sHVJ*{rUD-vC8cU+h!@pAurO-PC%*j2eUrZA==8D@*D-FLJygXMt!A z)F$U^@Pxwcb5kr)YKex#rJm1t;K-p3=e`;H@=Dc7;aT+#v(6C~g0-)}^>ZWf zjb-g|87V0*1X;G>I}Ik03RhI;mb};!c{tAfWbv>Zit=MWI3hRxV+%@`3c2_1R4(00 zz9B#crS#%Iwz=n1l)5+Ilw_nk5P8n}S8g}=ta3tpY4upMZEVFba>-m3(TJ+~TSOI) zcunWs0X@nys0<+?LAjnUDMzbx&zzS;5%yUx)W6?&IaFl9z}6YHQx1hY&;1Qt>|+Pa z;K_m8Qv*2-<^XLiOcuu&vq87UehfM-PsQ(~1Jkz7xh7N3#-2N$sNtwAF$D^*H2J=G z7}7gFS&;S;p7!-L(E`x!# zGy)F;Hj1_0UfZsEs*|Gg?C29fpUu95>;c>t8x5EER6HFTO-CBBX6L-$H#Yp_yWDl+ zWos9vCR`rv3G9)HN-+en%9ewZG$*%pL;(M+?yCh@YOnue}lydcWEIY%{xg3IO6z^9j0_kYWhGVJ2vAaxpT0 ziG!=X>gY$G0j2QeGOSj|Nm?j`*jB!%E^`+M+39^_FD-X8cV{Wki&UN^pIVoEh+}|5 z>x-8pQl&IjqGIX4{TKD4Pzw^fWdz$iv-7{4p9j!Ym-v zT|>hxZGveJl{G9uHP)orKLHAF-m+bTIuB&3@vno65~jD)d_@`K1r^B=59C&CC-{m- zZM`qIx0!v-{YG=|YYXMTra70%lAWy+vT!-=h!-x*Z4LT=P4*n=@f+5{)V{o9Jl9cFm;%_ zO(?2Pi5y#As;YRW)}AG|;qHokPNHHLf{>upMYE`X4p}krhnfL|2Ar1D;cLx+@;3cG zUn*+4!;O|m*R67$Ei0`?!yhw#P5gRpY$z&8+r0nj>4cm^W3jUh(YYkjo>N;op?Q}x z2O?+;OOP&Kh06=3#jDH(_pR*RY%%HMTr9!tOzxJ$)}ykNuoE6E>HzMi=zXx^gPEc| zFLxDsSswB^u$azTYNAY8%vnO`fKaN)tNkBxmtSlL;)UFNqyOe`GH>o8^BFwrj^~Gw zQr5v-jF87`A8vkhkQj?*mb`zhTGYu^WbYxAqXBHo-(FWdbp@&gyRoHDfaa&wPVCx( znWllzrF|wk&L4c!mbPgDvC$d#|2mF*1kT8L^3Q5w;br}oOZ&BD#)st=Gk@cwbE@Pc zbb!Ig!{J8FJu$<*@$tX8WR6156@h_gf*;+xPiVPh9t;HL>{{dq2YdVy5v2Jqm~m~` zs^)XP^TGvzU!)rfXe^&pcJ+V@h75`YIe}H}fMz9Ld9S;B-%V@c^N!P`^Bdx1ja8CV z|AQ(xJdL=*lpc=bzAZ7^b)ghny&+;FRlePg-aj;Jk3-gYm{cWMHX1mAlUE4n-UF>; z+2dAy#PhWd{c}K)wA2#TL`Sd~3V8L~q#{s3FxT~|z<~gNFaOd5-G|K=m&Qev?Qd4f5NeE1#U_Q?kl?~YpNKOtc7$+XBh>qf$5Y4(q z+mfR%{AHfsDr$qxn&f_}J<3K1``*ae5?1rWt`OZ*$m_p{jxqfoF0gX{L1RSgV?;7BfGy1j>? z{6~$ar0V5A`%kqyAJNW03Wv@ro1#Z1bq6egoD|_2Wr@-Vvwixb&ISlH`c%p>^tuTVV6P4cfZ5EPN#$5Gd&f;&F~EO zA-%gIXE8%k=CPn2xwYl1zL#_5UVc>UQ#trG(mN@*;=yP$wK)o1OAn9z)Wgw1>@KZ3 z_o+5qA#zQlK>7BB8pxUz=pNtac492Y+@`PtjGDWE{>8@OnXsfO2nMz~XTfFWmgM;Q{_Aa=9@PlXrg zKbc$&nPkkwlhlLmc3HHHM%=BeX{Z_~L%HTemAcPbMQ!o8JD{68&%f_k;=7%ly~J$_ zpUPP{_|=bDXgWP@X|mQ`^9XkLw8gp1?3#@sa&_!+T*}-maqj!FMI^BiHq(#qhysJr zA;`iyR;9Zc3v3KH!J$?|9#gm8%?lQ-#x1q|6I3Ek%V2Mn7ixXJ*YcOmm+XLli@XS2 zUD}PlfBrc%`Wf;LV)+jB!2J9mb_%-m(?^)#30L3$t1AYF#u7-{%~SK%xNyJ+&9^>? zY(tt^{f+W?^V&>JCEp>GOFQL=H z@rS9v&!^FlvmAE=cXQhRVgs9b_D#IHbCfHQyYJm8fn6(wCouz=uHi|0n)9Mjuka@a z@~y2sefs>}p=;LHdHR&S&j!AzwZCW=e^}uVm@yy5af9MxrjZb&XzxUI-4_43xoJy% znq?f&P7ZhhdgfNYbtC>ELdSwW3OD-S zkTH=@T^Xp+@m7*I&(_a}9F)pFoYszK2bRW;HE_3ZYmITYWOG0k{{ivXr#_a9AzX-u zeBry|5w9fllb;YQse$<+?onU+RD5P1Fy-JQCecBOLjz(rauwgyrPVoxcd0K$hv)1x zzcTqG0t&<)P5m*@T5Q|^JobNo=y+^%W%hwGL)kJS#p4v!m;x2Pn&Q|6NQlKF)h~=x zOUDxNAvob9U%;wM<7#JZm{~l0#aCpt#n9>&4pK~UMj0wyyd9q$fE$XPff;xNJ^#GjwhTJt^O8-Cjbb3ZM3@cPP^=Al19h@CV|)HU(X& zJ}j|ytPzKb60l_VGey9uAlX077utRR5$meJ_j;x^$F+cV{2C( z3}Sr`!`x@k5%7#YZ+S@!_{lk0S0HEHYP1Y?J#o>KRBrAs?Q&UeNHKUbI$$Mw&c8RUibk45Gk#$9-|394J0M>reKV~#8ucs-V zrC=c@kMSWY$dQ`c((MXj{;DPQmIr`7o}9^G$_hcisRW66N~Z2o!Jl#NT8ek{_>;i z221Mf*}8=C-jM3?EX?S{T9!;o=BO2i zro!rzF`9k;&Wo(sa|vgj@NS~Iyyls3I}BvQ&pE!T)_2gU-i7vAQgECdHtKn$xz9Y; zu1bWNl>)rN^s8>9$|u`y?WIaWY{%Bv0t%+-{tn8Xz7=Y`mWCp#-adD@*wf>9e47oC zmI-|lD|9QM@pBwk`?oTK92#z00HwN?c1f~jE@_8vMry}Du-NDfL9G+}ssJ>r!)P}% z@eH-V-W^^)Am)Rv2`c4Top0SnOoP*XzXnwG~Edq$iGN zB@nv~Vvdy7Jw$itIQ*B%NM|p6ZhlD^YAAPHN1|O9MPc%d96+tOGf% zHF}Qoufe;qW%#fX>RQs1bWe#I>*=({4*In34b?^8*0tARoXIM&_-WL5gQ1cf)%B=P zNnwd?FEa>`?tLnCO&st@T7h;-KofJql@0=(9v8ID z2ic*`59wg(Gij)??Gs6Hq|h-xN0d7OlbL#1`FGJ)ZNi<`iM(3x233qrvLOYHaoow{ zcQSs^LB=tkPoQ`JPDRr_-t82(m+i11Mri|ApU5}NwIw`5#gv@yp5%}18k~8tKFIch zIS#5h^Ov~xwG_SzPJZHDM?b9z;|^jx(8%GqqF|O3h9RBZZlc`dh}+qdy)`82iJahvD z`$4n*loQ=rV|&}R_3ja=2r2NY3+JK^Xr7s0HBx-4O^x?XC!*(pnCdUkW$6o0HtO$C zP$?g?p_>Y`rg{@9Pc5AGjoisG^(q^RuYM?=BRQQFNH49a#4BhxD%I!P=u8VqSSH(K zO5rX`_WSvTuASh%?kruv5Y0NTDXpreIx47VLlsKs+zLAQvFMtR{erw)5LjJWS4Y>E zo(15A1Pl-9M^czlsW=fEsi_BQ82w8Zi}Schw@?nADW5e~OS$W@ooKox02w+raaRMt z0*s;;u+lI_n@LILK9|OzQ6WV6v!S>fK3wVK{(o%a$vrcET>d~+M72^+Qzd4VluAXq zvBXjx3ulWQ^hI#KaAjzvb`&I;5;fS;n<g2E4))3o~vUenYwSkg(( zRs10xK5oqd0X{;A%o7PaBZ(UmB$#M79V9+Ow5zsmrZ2kg8HWN}pO4vZ*&;!JFCeU)_U%_`T)-ogvbnI3Ur2lx}L6C0trz|OoXpL)o3 zapR}qvgS@r;*3U{*iTL0H&dwCu%n3#cz6KZw<`3HEV@!mfI5{0xDyl`xEWO1!^+- z56MFAw?3wvV4?GbuCy{^ZI3>)MCTCqX!-xKo#k!=*Tj~-ch5>(kx1iQV@LhI8rU_` zoG&6+)mUdUGCMo#N<5)h-UVOsUVEEd_ye6^s`4{#K%(wJkF@QF<(ak5ZudCV3!kYp z3b~xZIGOhli!#@+MZTjaeSbV6+QC){L@R%h`Ms7Rt%M6i{HuPtn`N(>5U0MV5k5eP zK*U-)eHvtX(B7(}<0oZZsUV4rPtA-V2N_xSWC!k{^FYxL$nJ>nRz z?}vejt`V1#T^!I@xPqPUpk{+}bwPc~gl-BcsEVuUE9sNafshLjF230^s^1hykG5N- zH$_?pemiGd)A$KCAV3bhnc4@9&7AkZO5Ij~6gefQ1wUXIsr4#`2)QWJ%N-Y0;<(+P z`(cKOD~DQ(MTXRJF|!PJ-W6zLwn6K+^Hm0uDYRswv)uS>LzJZYQl`1k4YM>}f0Gmf zpW<>R+x<0e+uj9RmCFVV%ix5xK*gj^4#&j##}Lspii`{>Cvu)M?ds(Z)9L)Gx#dS) zLA&9zntL%LHmlnAoszr?&-M517jJ|({z%b`tcriB_mX;ww8}nnH~UOCH@JrwqCAW! zRyqy%s#}D{2n04q1l0Xz`i=d5x7+p0il@6u%5$`|taSBZRLr~2wa^A*5B7XSE-)*N zN?+`1ZN6>;Ex=j_cos&>mZRSuFBkx9Gj0ffy+RFLZ62z{y?Yv)m$CZNZ;DtI^g>b7 z@@9M_^i|r3@yiKiy{QI}YDt`rYTRi^@L(dRM1WY3Z?pKm?0A}s_0&&~emBuK*`!$H zD^@qE8X3>H%LLP6{V~=X0|90BAI)FXFdiEGu%f6Yckz3xa-9kRq6-oT=wBBGo2=eL z(bM(2VFFzhG)Uok&;ar}pk`g_f6;RW7u>fue(&T(UKagFtm9*M<3j&=@TXacaXg$W zW>(nYeEYv@9sc2+CC~9RelkV!so<&P*A^{Ts#U_)Vs+=USf}<}QJ#&v2aTilw@ETq zmx(jB2}2U5s%u4^(tjFuI9rk=XiyvSoR{Wxe1ya5YE`0hEG5R<_xx7mM(7&#|Q|}n8R!lHNxb$!8 z0w!{_t(g})icZU|!F}reh?qpIn(Jni10vXf_n}3IgZM;hJ=~;Z^lf$)oYfc7Y>ZnJ0)7-w2AH#gY&a z-ZB(`zpvR(y=5r} zmb`=Xsl|b%cepZE=r(>nI*rdi&x9yS8Sj&UhL`xgyT~GZuqcXu?P7E^MpkPus|L`a z!QZ40=nNM0tv={*_%>DuzQf7RN%Ef*0&&=}&Qcc4*k4i{jkrOqa`iK!kUmzQ6CA)l8PpWTyXn9=FdS##W zyGl6$J5ERp$?yxh{Eby}HSBt#-i2N?W&25?Y|AwfrA@snCyNbxc3g6~;{twsAF5k8 zQVDP{8n9KVC21kO>hq$BzlYz935m8fF^rGiAoz>);Q=?__8gWqmU18bLcS0>)-!+N zH*d`3Tbh>v8DRoZAl7YjzjkA^s6TyPwBb*mBxUm_tPHt)!2XSQR?}zXW{Tuyb0Gd> zyCU7I6ZJ>vSmxrcdC|`*-v&EP5j6nYImz0+pe6`Y7PQ*`ir5VC7c^k^k0NHzaK8MH zE%MZ^mTxhu4+ll>)2obcV8LVR*WS>q8p4Snj8{v8$mZ_7**-_1zG-G z;@)Ep1n3&X^LuFfUS>=$+NN$@*`4?!CLd)f8DW$5eM~OUz?6+{L+QNhqjM0#PR?Q6 zqFF6q0O?RM*fU)_t7-L5n`xE3c=U;Poi?dD&BTUD0`Cd0Z3f`95kPABE7la8Lmu$C zag>R8kceno5c~Kn)qaPA>A)on@z%=Q5KHCmu*o+v&9WWwq+=1M7{{0wlNKdo4=|Vd z@~0rN3txG+uxGyW7&pIO*y}wQG#jbcB}mT8cbeEbSpE9fnOJE}_?|pAtJed$oc*DM z^nfztG12S~;NEdHn8;?O`V6CSIrMUEiW%*oKH>6$9ivV4slgxrBf=lJF0g2qye2Rl z;G@TZJr~2Jqr$$LOy|O4ss{69xf7t-Ns-*d7xF^1jssH_-RV}gweDc{M z?$?pAMQugZ7#X1rStSz8B6+Qh7C!sOa38B%r}{hci+*trUN+e}LWTT3L*C}F9ytgj zi!A-FY;LSb_^L$bb)qOT2LmbAZ<2wF?W8 zmo-Z4Y$`doq4rI(;ijy_A*iBRxD9B8`)E=B)$w&4p zTxrV=ja-t9rdK0}W^Y7Jrx<^t>zKr?2iypG6UOPMzG=Ub^NYi*y`Fj)m+b57usn+v$!dWGyirD;uS}!`;6(86g*(h@Mg>I z{6f~LB@)i%frM#@mSLjq-2=0?x|Lk7RX*9E?b;lLq@qF7)l)bFzQ5Os`A#rHN52y# zZwA5E#`r(q%dUhoH2POV7^JGuE@h_8y zCuksLh*U6pn~DEEVj#bzY-+v7{*W0q_J8XcD$T_=XjSwi&5@L`<2|}ardidN9F2(v z=ziMX?vP9ajD_Tx=bA&DrGm5v$z@)Fhn0-qVXgRc%5zcaGJygJp2LZs3mZ}fNZF?VnyJ+8Y}1nbbiD1T zmP+0XBs602!|cSZ_UeS4933vY#Zm9`2|o zapQl#RG?cPzbI=6vXD!?;Ar0``WwyEl~?gC8rRXU=&{Iz_Xl^8*LJDDbaViroJsy4 z9>opZG$Lj1;2qeb?IS_Z zFVNSi`8VQ}2%Rqn1{Yq%0}Bm$Y2t~qk^w-zuS$T^o?=W0PnU|(IY)}F4&F6q+N{e_ z3J`iTO=wZ|?T%xLAHDi0<@@J(uR#SLyf`I}AO&LzbfK7cEGb$tLwciLEfPKXeBAa< zA7qt}upWBx?(vZB3qFC9wYKX&%Vw=3EVYTvVB3-X$sn^NMvVpfwoag@fVp|4PQcM? z*3}JB4&=E%=~f@S1-hQs)PREd-^plfX8JZvjx-r}1b#A^whR z;|g8h-zHM49+ui)h$ONGN2<_{Ah2?jUZ#`a^%1AQNP0b#Xp(gPyb_|Xffl}gG`0;? z+oVS^L29ht@sCx`Qpqzq8@qk=@oABQD-L6@8FWq>o{-OIuu1h`Y2SOlZ&bxqkDo1S z94KqWM`!ojeC0}RvKz^ux;&%eBVS)jTpzE*-yj2yn|YLG>$GOeLS|_rSN&YrQF^rc ze{3OCY{}3uF;rDu@xXP^)85jCl^@{y9s;?%h33aB>Jselfr6 zD-qS_oKUqYr?ZLT=13+c{l|tFvJl(v>d##T70v24)HT~?_?3?n`q50Vk&CEi5>t6w zeCt642Gv*!=x)3xMfXM*U31PN`8Vn}faJu&=>cDX%&nP(1~%W{oYFN3)=-Bzl@NKd zr;Eh*T`T*K*|#i=HHPz(u|K|l+&6nR^1-He(8+W|u4^^51y8$WMRs5qkbR+diH&{gdJ`rN^FU- zA79MU&Wj6^8B8@=aR9>$Icqx^i;&NEM77Bm+M_GS*$~Pk8u?CF;w4~ zjGn`>Gp`DE0zxCTVBK~RK89>oT%GTs-N&6JJ^MASSDgxD3Dk^{<|{|B0Db3MI@ebI zUQ!nU+mN@Bo;z!AFV1sl{(hg@)6gIO%jeARS=NtA{L39;LEqubQGu4E|M!>Fbkm%C zl3wrR`8v4ZYp{mq^Vs?0#|9VdF(*VlAuqivQX|*a*~v}7jS3n;xe2pB9R8berV+Hq z`>RJ_o#0h$J*9BVEzm-DrSO=(WRQ6@1r>qcwHy=;Hd}O0{)PZ@22&R@!mZAsJ%nPF z!%zdDb z8Sq?RAW632u!dKqkE%FHW!$+Ne(Z(k6yniOe5#XHe7WG}I{trW&wn@oQbbm{vNhjx zqK~#>Rx_XiFn2hRQ;4yLZ?*dbm`$g)2El!OeN{TMt~6HmH06nVpoX@)56e3ygCtkI zc30daxrYvKPnTBoHrxJ`rl{!lDe9H7hKOcW@j<#lEA%vcWFrNDfoi(i@ew*VOq3k< z++&@JxMwHGzRd=c-^As7Ghb=fts6dWN|@H?vM8(be2iO;V;SqFRB4&R#nWY4xp5`i z7~S|o8qH8LZG|>ySo?A^EW`p)qTSP?L;I~cs%67~AQYn7p}xRiCo-l-^%B1X*I1Zk z_4;pyfSGK^t?ALAzaH_yBfK?}a$=-aL;NaBq)EXVkYv^PncDyj(i@>yz&Kz6{;63v zSj~D;P7a`tUmLY?PhCmvCuB$KcsrNs??GCVLZY+9N8AIPGmv8+rbXU-V0Ll;9b267 zj?Y0SEy>MQrm~I?_Ws94la;9O4c~j#zWbHgpj}qs_71zu=kxxrqtza16D(T&XQ(u4 zmYJ)h8n}iNHTw7e@ashrwXU42jcS}pMUP8rN-A}ySwWUT+Fg8%TybP_&b<5-aRJlD z^*U7kla7oIE(A?$3n##0-NFx5_OHIkDtQ#4$Con0tEn#;{cr1(+qts_v>8(ouhRG9 zY5RGjXZfvraI`>17?)Wn<`5%c(l9QDN=7;~QC^$rE`c90-H$#xgFj|p!O>6fGjVL}B%VA13|%Bbs;|wW-vqbC!LqnV;5Y zF%+Q8(C*C9yf@c)VXJhAnJaWqR$%=-P3%pO)|4eFBG&NFX;fB#zvPaXh!wB9h(~JQ z09JJnczd>-x^jEpR^60@4@e>w^0*XA5$_d{pYwBv%crOhS6k2{EN|u-Z zC0X}fG0}Mr71H$jvl~gzb0DUro|{u!dK159)F1d=whkvnUV_{E#`*7ntv2T>*xNCY zNOkNkPu(Kw(!kP3Sr-bNOi=$@ll^F>=*p2t3SR0;X3p2OpY%^%BIg@uc6$J7(f041 z^vsk!Uw-y2g7W8gOig-c*hrzRV&H>hUSYFwFiqTHzkQcyae~({tNc?*%WpL2Jx$f0 z{PPD)O{=NYOC?+M!15ttcdpfGqZbfxC71*vc5p!~ZDw5&Vo=st zG!?a5F8K0qvCIMSJVs%uu1YUxpZ8UFTv?c3=#i(&`O>iP${v4+kT+hY`Nb=E?roL! zx?vev_=>n5PX*(=THDS1p5s``z02RX9J8oB1z7M z{B2TITF?}qZyp7PTK}wuS#mTNz;JQ$;Rsq@`C#vKQ;{8dyrcbzoaKyb{4Kt{wA1Qc z)Jl`^S+T3ddIK<|Q$%YozA@b}NXHctPof(&J5JDt{m?t@0UE_r9;=$fiJOU!pRHDY z3EuZZI_)nniS{;W9%5;_F1v%~!z$8tVX?YqdpFBa9#x3?b;eVrZ|w4!$r{>fcQ6VS zX;f%znz`Rxu-wewZdl#~Ews1n>TraYV!p12_8=Od)${N)b2Vr5!~cftReZVIW`FE; z`)bdL9HW17?v(Ej?7WUvK`)5<%=1l%VaAy@6|NH`!!_g{#wJ-3F8iJBM$G3272>|@ zU}M?Fz|WOWwzf(sN^<1d<;2HG&n#3^_Yvw^K4|{i$Thdi1|=CdRc<6at;z4Mh0L&$ zKQ0L0*FzQF7|%y{jAeXT;5J6!Rp&6ipl>hHHsb;}AJg#@C%vB?CMu1EKCMByFX!RZ8MH5{JS34Ag1pg(fBik3c zgUqyiF;m-Gd1=cs21vsfYM0`bR_vE_A_RPvtv39}zSM1no6qAfdS)vRZ5?n(ux25G z9nqG_U-gFRANbgpUq46|4-nq$D?>pCqX^WFb*=Lr;Q^`@oOu%*SF!)G)p?rtx<1J( zwg|mwf|z4mU=2@-a-in3o7MNOrV^cY8+j*r8kQB+GKbHMUOTv+XVKh821_D%hYoh8 zSxXCZ9p~%h_yd}34d-ow1|)9yrh$X_5ZKvpdZB)vn;fyFlp^qs2zw}IFV|wC z(QFsF-`7IuI)vfSA-7K#`{a5%^*-5=YiTtl_4+iz);o}|Xt^z{JAg+ieclc%8k~T* zkM`oV+*xZd^!eN}Lce#}sDj=7`GpsX6VLxh?rC!0jU$MbOkh0^LFsyKwQ0uCtS9na zC$7CZIGzbztF6~}2jBFiC?m7;{G(I&wa9IJlRZx!AK#uKURe=R8!3#u2s-OJLo;d2 zRr51dZz(qv&q}~KC3I3baQ*=GAI@1~=6HAUM}0j*^G>W<+C?&s#z6l>dwo%LeP^6`ue#d!KIMLVCqMf$XWX>}9v= zFx%qlAN>(4+g^$5sg=Ua%?B*holqV<_2Xx3u=k6HVlw^h+qk~kxX`%H4A=-s^6Rs$ z^=brKGOI3rvobGoVs;R%cKQ-hkNyq-ghjtl;>OKy_|{ImM3b4D1+#rMf&&gSNlCqji?#S@QIST4 zU6x)&bKSmst@SjI%#-1&+7rv&(1xJPVOCBq?*GPSEnti%u@!+Ug8sYe>)^`>*P1$7 z&R&(Jad9~}bYdY9TooC4pLhG2(-YRFSR#tB>4>#?7k2|ur4_Rztfee(yy!8F;$lMc znFhPs%~iQGArt;erkI+Az!=>x`48VDi>ry@jWV9QCb*{uSzAs_uY|bKRXg}**R&O4 zNsvxmK=dGD#`O;V*Qz#p$#it*B+mx!Yyek+&_kW4@UM?X8a(C-q|YBFf<+JyCTpZ2 zx6x#T(z3qSkhSA^Xi1ln&ZJhc!}J;-i5Lww2gV?Wyp`LRy8NBO>usCN0%<{e(nhp5 zt2XPYqTcCzKRouo*z2LC++M%ZzIs6@da~XVCK2dRTq{hxL#$|_n|aaktg~yrP?3zq zv$&8{waZjv267}Q6m`jyu2G&P5Y77jA$N*Cx^*h-OFhr zq^;RXb&Ch*(wP%8ouajxff~x`6?tyHDR?CWUM36+v*fCl1Vp-nwqDaso!?4CB%VJ_ zq}xPPBAtEo&UPqS$3aA821Nb@otne-KOXEiUD3&|$>&T@D7Ck%o;-g8mU7cc+)FgR zUeEsx{b{bxmvreF0>2pcT=b6btw)sqadhtSOuz3R*QW!8bP{q{p_F6JXDX$T7Udi& z=fk#~Ph&-qoI=QP$@v^(a~KObpUPolGv`BLY=p5xzxVg|{~nLMANS+Fulu^L`*l5E zPNb%sx@sZqg@ikJ6R+r}({gEXP{W-J&-kP3dH*=}Cu~u;i~EVx>T%3qSuM8VaW2=B z?ubt;^KCB5uO-Ca*b54Wx!Je0W2a9j8C5LTW~aKs($x;Qo6bBi=z>wiuTr=VavwiVptiK_lq826R_e z0(G5y$JXd-#-=Z&S$6>0tmnd(9p8)avcsh{6*w@p&_AaZtNjiqDuh+-qOW3c$Q2vA zzWEbI?TebKGQ9)=?f{>r{PZi(avFu``>f51UfaXkd1{ng@&|=3kaX}Zrnjw7a`KF> zw2aMLy7L#C_&=~Tv{2mG5o$b^wl;&@9JO~e*(*trw2YoN*@Vpo92jyscH}2+b3v1x z5NXzWKVG(=Y5QP+ax^}co$nRe4*J|5UrNdjjd^x?QPMBxZ#jOOk6h@(8W%>RDN{>J zmyqBrO$E_wF7YS`WPJ(cv?3)D_25@)N1a4Stg>i=ylCAj$CBSityA(3KjPE%DaT|< zS@(Ea{Dk4F9AX85T2Fs=UYQxV?Z|`rR{XHH%(y8 z5smUXc%5|5c1W&SUBYDtyUR4fXx8+{Y}Q%({mR-cP=qe&oBFv2OE14pWHaulx>w7s z1iY7#Hfr)^E=B!Z$g1OBLMWzRO^$G!^H3MbyAL<7_pu|fDK0LqvZQe>jLSicu4nUW zik?bSV~9Mu4ju7?frbtsOFT0R9Z|hS>ay}@Z3-Cu1v+U!k2g~^C&df! zJxwQ)SC5=;?evt0(&GKcaU;n`UvZA{WaS$Vx;AA&J>Ag7)jqj;UL3uc&Z!e0SRK|4 zl-Byx<_C*-7#_dPJP|3^HWIqbs^zg*)jUgdnn^Tx*7K+$&8-vDicgoAX}PK5$h1dXqF`_+HHpOCeaC-GL?DtM^T!p3j-FRd)Vn8v!RXlHDFJU8OgQ*V_YWm(M;$I`O$NZo+_N-G``v4^w zw{H;zY5zXo@|2JPhDB5c4q~s9Ke=!N^q#ERfLC&qi9$yuHOPm-wwEs9f!oKQrU=0a z036ZsaY6$|I;u|)>SO-F=^85f&r=j+y4@x-Ebq|+c7Uz6Vu(uOK+_X_N;Md$sb8Cu6rOAk!7oJCBm@5KBJIVo4ZZCMhmY?+K-g!@!4u z#+bG2$F^chUCevFxa?h+NXEvv+cY{gL>wL-No=f8wtHJ^BZO|Qb#XAu_;yt1sp+e4 z6seViy-oN1@LxI3fg_=1M|k)0A%&Hx&y3K5W|>ohC0yA_Gm9A8?J1o1$XkM%%pOeS zkDgQMbhM^fhVE@`#U2Ba>J-y8#mn(+#N{mhojl=_=*o&!@q~BTGUL@hr}k>z0%fuL&Cc>S=64^X!#ny}6(4 z%YSCiq|F*nR4QzYt%N{UjPPQU{X4tWR*zY=ZTxi0#r`ImZpA}XJr7m6S?2np^qkMf z=_GvH9lB!)a!P@H>K6OV=nPFqx!kV)&kGsjKit5HydRl$Q-WEyKz8{gKQySer9s`+p)12vE90dX!h}#o%rR>X^q-k#mIsM{z}P z^~I#r6>=L68WQi7ACy+CMC=ScOHPf9@DBG%FLV-c&%R?? zQP{X8-aIQU}r1 zSUj^D)umZ!dCwQAB9ky&(PY)M6qlB#k1n=vl$ZdrDc`~SHY1ZiS?vt{X z{!BNyB`B<>;U)YLmY2H6x?`ezV2-EF!pr$H(VlIv{3JIQ@lbtt=~khwViyreSgCF zm}pOmGHWxoAdIyc~IhqcPNfme7`2sFR(xIy%q@sd+fM842<^Cun~Nj)y6!>A8y!-~-V zIx0mSebWy<>5*3>i$e7NqA_vW-U%+mDyCdhu%IC4Olv`pBTvM6o5?lg)Yby8zGZ?9 zWTM#Ldi6Hu#x_M$J62TY2a&v(ViJ;Wc@{mQ?jHC&C#4dblRB~t=6j!Djjk4q*D0;f zESN_gT&kbU&F~NU$ZWy3o!Pv4dr@;esiSR++Wg*M*eZ2Pi+5HYKai8!Q@hf3j#}x9 zi>b2xjp|?6U9y<9W(Rt?+U#1_%>&Bz|QnZ>2thOrWaeX(k zcl1HQdo5s4{o+eRjNk!!vnwq1k2LA6`MpyW(D1tB%OeFrH9#^D`PL4LKt+_IIvXwp z+t^tA`X(%N%x5eRuoC-Q8e1XM&5PPTZ~2a7jZLD@`{ESH-o8aX!#?YGhJ2 zYycq2wC>n%wd3A|mh_CA^@JRsXp1ZH@N~nCS6?WqzpVE&yW29(F_uvou&l9CQ$c<0&x ztB28#>m)^n9sX=7bd=W5@Xf894MFc76{X=@73K*WMPjpoA zm0=5NnHBrlwX5Sng^32Q9>|st?OU|DdIQ3$Dmr6NqmjDR*|K#$IH)U7O!?dB z>b9yNg|ZxN5>9>~Qp!OY_StWlaD0nE@gfu8|IOT>1;vR|q1pcIdy!R0q9j&kJ3~UI zAs8AWS@Y0RkEkYRmbMXMolPSkFa<#?lf(MMYL;LF--Py5|&)Zr?X{o%38`V z7Ih$-T07k`F|2%GFu~Mo&mTKla~0cwSK;*>2fLIJtGgNO?n!M*(Bq+%YI1ukAyFI8%E4nSx5RZ&GOM2_ zAI68eMJ0bY2(igq@)$RsF5r>jf&gUC71F-(CS}~m0mD%F1I1*;FOxQg^UtqN`tbPMYujI<9}$O zDI4MXk}=^KQhAPGBBI|jl6VQRu}W?G$I;cCn>)d(iYD*vZNy2wNz|CWwWwK>3TSmB z7lKWz%uSNG=;az_Z9yi%OBSMiS32Uua*(5~fT19<2h2(cuvthb43YZ4`E>mf(Dy{{ za5Gy7$?SeDg?9lXQ`|;ua$<*xkV<;kyF3;9_BY3p6CZ`_*0>#wDba$DTIs+ouN8Xw z7LZhC>DO0Zw_T1HI?PC5YL=@0V;2)Nken$*;O`NRka-*%4K|je*>U02M)83 zxG!0oW;fG=*RLC)Q07KR+?@)Dc|?QVG)ZrOWcO}Lwc`0XUBR$KoH2#1&K@O7eb+xS z?L}Z)j0gG%*!eeq(3BTMaLjyn8xQF5UchM~=8$@vEsX%h%VUv`he&p3pQCXr5!=th zlWW80T!OFYJ?8**B^j^d<_aCZ4dw~cWlDqbvt16?CSd30p#Z84s?%$&7Ucc-1efS> zAACoLD&*&Sfy1NRsr{PovqYJPtgm{aQ}nn;=nQb;{81J2`7E8keIkAi>I_pvyM>M- zLz(`EsrZkBi;Y@PIHS-z;9N@UY5cF|O;haZ@mHt4xY;M|j{lggn~A&di;}ugUbhLU z>^ypmWjMBOedxH6I**%5S|GfKdo6&@PZio>kI3dAV9a_ebSQ4rH_XEXxQU*a& zJrJT|Iy`7H>{Av}@k}wK$0(#IZMFH^Ku3?TQy=KMtok|a{iU75+5BFpir^BgwSzSa zGaeAWqq3CqC|=jdSdUtP+{dUNbe(!%+0|x0v;|%r)K>?hyQ%A0;OV;ow^hEdqAt85 z8{gw3Kf495hn~Ol0D@E>Y9Yo838w>cm<;FynWHsdfQ)E3CSZ&7YJ==mLbke(2F#3o}f;XN$Vy+X_ub;F#L!N7Ih z6Qhb9tb`fg~Rl^}n z@{Ww9YZ5@4t*=ubXxy;H*70G%1GoCx%5ieS7zOP#M9V`Pb$`;%lfsXfe!F*UimU56 zi2ZjaZp$KYcY2mwhF88ep>4%J{xC(iqGzz;7Ow^L9WI7_SO`l)wJeiNR65*<6$E8Iey1-f+Yde)7%MzTVgj9=BSSA*Fwo+PqZm-GydDjR z^zrH7%+eznAaz3qE)*NI_Y>uXjMUnQYt~0iK3s3Ws4F%y4~77rEVU)TSsApL@fymO zfa~K%Dc7u>TcaNcWd>2EZ=SvZs5D<(4Q|}kzo9>ug!`ucM&DzX_Li+PW@Xp>t##1U zC!xFzI;xhGacrB5y>rB|U`Cvk3zwm~%~h>L&4=@u{`xz0**(*nvWT&KcE<19f8Zv` z{c11v$uS1c5QCo%`*DZy%--)Y?LsYj8TG(&M&;@^uGMt8yw^;uYirWN{@YEg#~i6j zj|jV3eWqqLFKr#)^Qg$~ug0GjpRNQo9RRGzV?HdTj{3q#;_L;eeC5Kp+~PsY}5W+R{NNcfp1`yavFl>N(Ho%b>w)Y;;s(mm-6CpJ* ztFg=y^8vLfb&-TZG2x`oerqzu!2mqR??Klb1)K&_4t_MeI1gf8sOW4i>e}vPRk(fTD+e1h6_yh*Ns`5QSG!vvcLzCGH_o82c)>r3z9 zNEPgpBc*T%MBSV^Q`s!_zCPH=&StJ5oWK(oukw1yc~e)fbtnX}0TgS;f`FY6&(?5f zE6`^bmI?Jpp8k|ckF$o9m4|PYGF%S=m*nS~$e1dKtjo27_{Esg`ri@nB1W1Ywu#aO z=5^IpR56XHQQ5iltL$?h#TTjF`g5w|>W3qXBtWA!gV(-0b*Wq$jw63{*q!g&QI}t> zHMQ~mq~j8ziiv?1pdlIZ?*JMLUu%RUdkTP{bl+or#To>-&6C5PjlwoFtCky{_z1(6 z__9A5K0Vq)ey-6Ku`qi_z6!`-lQTB)62VfBAcK4TTl*x|<^-DW!f$Y{BnwF0WwwQ#EnSM1zTmAN$+X=P<{iYl zjaA?7S$4!-)aR`a*N+(BN_K_}Z6}tb+RVsOc{9?-db}$d0u=_B^p#fWkRJzC{YkYM zu_Np^3kYCeP@|Z4V@jgo_a%zA4ua$>qIMwdn!l$ix1_pFLFsLxGy}3a72!7Uhak8} zts&q9nc8Dj@OyrIQSVNEX;@4G%8*-rf7KNq;}u&iTB zP)%NaO7p!5Rp14sy3ND78+R4B=y4`EyaW!@*gU)`I;-`YD4tLD#d)@lQz=TG$< zGXigxYoo*aLq}VaI{lcl41=2$@yli_Ve+}$hZu^_yc(T0pTOCnE*2CSA%YDotG-*5 zZJl{0*4c87YdbKWM{PQht2(M3fzr#t)o(Lzx6+EU{pMR3Ba~}tTLmd=3tJ(u%aTr; zDNohmQ2w3V)pigEQ<$b6GZ)o^q-Iz@o908eAG<~xi1&?n+O6BCy2TczBd9gsBV?QD z$qGM2)n?m6Ll4lQrz&Ipe6(Iy2wYY)C-3wv7Mt>4H(E=QAj;SyuSZOSb$cjji?K^4 zz>Myax6O--1Ir&zZ5%DVyrgcfeQM`{(?w;u&TH%b&wB@3FlQ&vAL28*!0%I-cJ#gl zg>y5~4Z~HzqvF+e14;DrQbHXR(7npir=I5Gk4QmqoHmrG{PW0Y>jxj7NK-L?q)PVv zZxO?X=?S##1(!(XeVWw!4V|k+Z4|UGcXWK>U7x#*1I7l!8ej?(?ClYUs`@#f5UW~H@B*4h|>e*b3KffO}E5t2y-riAKP)ll*fhW}`0C}?!9ssUW&Ruo<}qMm5o4opPdxjwyB6&2#who|$c#Xn z$6P$*%@dDf=YS<+^dIpAN}^PHE2t+aDNmASk0nq_X359CnG8ze+`wt)Jy%7Jvm2gX zCe__G_ax=jP(cfpwLrDWabOv=&wWY0D^j++`lLp`->eic5?xDgtqGAYUZ71OV(~^A z&;ltWzO5XH_Qp)PU+~)uomnHFl0P*8dqoy$5=2VVi6@9}OvI_fEYKT0kc}j{cxuD3 zdB*x60?7*9R#Z)?ko?8y;if0Q8K~>GwwZ6rvTaq>mz86ydaAvmq%7=8Ah2bU6(ZSS zPO%AjByGeZA>t>7U_A6`x{~n??3buj!`5~zQ)Hf{9`?QchH6ZD=aNpAbj{kTkIsT#~^7@!cg^A2fVvgvei7b5u}fv<-GB}dPm zneD+aFe74H4sR{Ud%c)!4|UMw{@LlKz>8G%0|XuTtnK8}xr2Y!I~;1)nB zJOgTIYyL%nJhv`xsLS5>Grio&hx8K?u0gNp`Z?MpeQFAM(K@m+cw7TBB=z;rN^l0n zl$JtR4C>;B81|ET$NaMuJzOrV?>k9tDIQxfTps~{3OGhM$#ZR6|0W9JdSHPIZWJqF zOaNPP3@(?yZW$=X-I%^M>pv1M*Lfi<(CSoeQkvz%*F6&Yw#x>BHbKnFxb4k@P@dJq zU2;ra5kJ3E)VZbgCZifNj3a*o_$XPoD80z%Wi4jlnE3^GHTT87rL4i!Jv5ES*V{gn z<>Vq}TQyeT)^^ipC|r(ll_@$FArlN`L!kXKyOw8Vp4oN<@OVzXJiQqN`f2se15u|C zRh)o!*YeipM{C*jpsG3hJ4-2!IV-+sX*hXgefanyw%~Zm<4()`AxX?n`ZX|dz_Bf6 zSZk#^TNs!YGETOCK>4KcXZY}eksCp+d_UdU@w|iO~u@GeEUZ39cu*CzyPtZ36<@f@h5Zo~4fjW(BApR-0XvYT9 zDJD5`E9}TLTXhRT?bYLMOyLLfx%ZvAVnKGhFtnpbSxRn9&N&?{d@m4mI^yha$CCw( z80sbxR?I5eAK42$b1*4<`*|qRdy!adA%190ZH!8+^LB82!e_wiVdVaIZ18s>Hp@fI z>kV2JmNE2r`pDXi7fvBQO?JL~8K*kSmQwgs7|{=$w-*`xfVs!OuHL7Kr;V@~@$!&2MWk>gl|M~Wz|@67R#%V%!QHhhcb6AuW;ylXih zr~&mo<&@XrRi{cUOwnAvFjLYFBpl|voOf9OM93L%g=0!nEA`!gcvgOg0FLPJic6AH z$8Ic&y4;hJ5F~Q&ujtpiQI5~?U5prF^HVRziea;2-d1gVjnrJ+o^Q-lUY&09y?;&v zv~>lLuj6QA?fb|E1t$Ob_AIMCy(;y$a0!^l-oX~cL0j}!ru?$}q)bDf^>?;-Bgcos z>_xYY+Wa*~o&bw)V-(x9wGKdf7^X3mZnXXN∾j#lD>2G`}oju8Xjm^P;mUgOg6| zT;SX&nYXEm_)f@zW}$=1Tk!6iwekJnV|5hW^%XvnC*OuX(2M8@n?r8{%uX)RNm9jy zjF&?8*6aRoo8{_OPl7If@N~Z$RE*Qk1@*X;JL* znXNC5^Ql0zKWY=1F({rTyB|v2YJp?6my#uw`j^zqtfVHx2X`y|%^{aqQCloEO{koW zXxa;O?DK8xh+^>ij_;4K)hv|PP4G-PN`_fpu@kVEPkE}6tsN{&2`>+_ z-Ths4!fye5ln|uMk6$pE?F|4uw|tcIONnYCsryq+wNQqa`g4u1E<5}t^1mn0C^gWl zBe7zQWk+^^;nUt({m-K}?T0=E5|u~1eN4CU>z+!_LZB@cwz_?Q_GK0ZA<%9TO~nzj<3Fjz{r8JL4tjlNuX*wC1*X zQ4=O9IMq)XGF^p%ay}GO%yQX%KYq=0Ohy`*6-As8ae77Bx*NDIn)N*eYWW7ZL*|!8w=6&8T3i6i``N#1Ce9;uRf#!$Hs%&Me_B4dPGL$8g zRzNA2^WQHH21u?ZW#3ijrnA?sXI|74rJYfD{pQmiFi%gTWtWuRq7KVX`QU#=7I9XNFFgZRVC7d$qqy2SpHzZUfrrk>PYsD{4a0 z`@cg^jGG(WH!n9Z?v!Tg-MW_QRmvzL-_~5Kl=+=!i6FO;DOL^BG zX^W*B=e(*lp9P?q36-!b77=kf)tlB74yC;=gR7m>N`|w6H%FQj#ml2!UkK>Z(m0mf z`$f7^ZUwcS@cQNjx2RNbTfAX~M9I*lchdtHcaS=;3v73){KnHG?+blcQz4z}!N7V+ zYOAU3>qC}+I%+^|X-80cvtJ2yc(%RFB7y)Ddjh4ZLl5vuJsP`z9>y*}ZddC;%66oo z`ZpK_9EZEbxgFQ5RFJfrkn+CeGHv_2aUfx{53f4Wl3xYzPv;37WN zb-7UyM=%ki$~lJ?UVpAIEGJT(YI-XgyDJin{+2x)HEWHXNVDtn5K3!fugqkJ zW~}B+gbhT!s!aY0Gdwkz0wD_ScKYOE7pml%yd0J8T4g?kxH`5p?((!v*g%}IJ1P9G z4)zvLwaWCbOSF0X82&=v(iw=(3UE|Xm5rY=99Apqoy)4nqzHb7l104!amYEHgA&!9 z`Byb}%kj0jrKK&&cB>XIT9$-{@w>Y3l+96zYR}he9ZwB5C1m^bMQHT$7bst|D^9$i z3@`03@4JvaCb{WGoQ_IVG#d(bbGZwN9~>>0jn*Y49{m_Rd|YeC)Oy}VZPVssfBbq& z4acVFACw{kl+CRyEx&RQ#rhRLx2?I#f7y8`kUFic5Otm^1UcR=# zLCQ^wuzI}KB>ed>QW{)aV5{R8z_uV(p#o1Vyb2!qR!(u-i>;PQ77n&wi&#{I9_d{y zx>jwQ7N^)L=~MTke{;=l+1nRvE=&!pQ~cs1Nul>as|+R6q2T7**?XB|An!Y3V)$RawflUP+HR`wI#C@ z69xF+A+yGYZ1Zm^(+?_B@1EF{bj(>=)rtDxkba3JkX_?o0f)u zb=B-+i!0-cp94{e|z=KmPG&;-q6a`B3Y>dulBK)Bh1+% zR+aB>NlF0Y&gOK>CphT|C^+nJytnjqvl_m#d_Wm>78BUhL7SZ|f_E|y)`dRwfa)tB zT*AI)yI`)@8NPRUwNpcWmiB$?fbeS%@#j*Cw@q%gaCVHNIbRX{07(9h|AMYG{KTss zY-YKimD^5I9vHu=bGAV{Xs^cZ>b{RzD11alYbDr7GH^zySsht7gsq#F39q=z&>oP( z5v`P#a!L0;-z+i&Lt4GM^j(nrMsu#TYx$5~MJ5@jb(=)&Mh&YI% zFE5zte^(CncHdI+w8XhY1~sHfLUjsX^}Q3Dq6~$CH#(_etL!tm#=5qG)m6KeAFf4O z?3@FmoL`e(S@GC$mXRC^5q>Ab3@c|1e(YEDpU#?)7}nuld^e%vvS31X0Q_g=t8A}2 z(sy^z@GcHPhn5(fpep@ILYJk3Fg@8{Ds>?BaiomJ4q*jI>9GaArzfAJCd$;&dN!g8 ze}|fmXL*OF+8dpZpapQS-A+6az9+sYG$&TFyyXzakf5v0_Bfsu3v2O;3!})KZ`Zni zHM>tD11xVpEAdkA^^x83GRuUADhD6~Eq^Zq0WeX%WNK8Fz&U&%iu6;ei?QI{H`Iy` z9b3%Q*_we5t~Xc+!%k^Er{PnTWL%y?C2i3gr1nr$3S)b2>)d~#vjj( z>#b^bY-xyq+Ldr7rrATW0|CJ{xj~|XvrZ7M`QamCfLH;j+5^1|4{bFQ{nnr;pB2sTHxO09sHMQwXBEI z-7TN_uup2Fh(*}ivwcFm+cg9GK{9SB8f^cGqya;&e;mrS#EKor$n7CfgZvoU6U&%; zbe9F8O`YOsV#nf;jor&$F{Kuvv8zv`BFPw6oZ3H*m$^=h`cXRi3wS!bnFlEF$6buZ z20pAU%$SLbT=z~l&o>NV%lc)pZqTy}y27cmKh8eW>uMaU{zC4ckdK!3>WG0u4>;K; zkIrMV=WF8Rr2_1tX(H&&q|+*8 zk0km-9auR3{`(*#pzIlsCx(6$?Cv6*;|T5m9A`B6ceXbEQ0;((P(V*3c*l}j5@*+; zZb^LKkgHQyb~(jJ-MIuLKbZ9MZ_SuYk`jJ`nHFnvW&`r|o;mBiPBKeo2fX(Jcu7=e zXt77d^jao1c8eSETSAp>U4q*$rk}kh4Sw%*Tb3v(@)By2*}Z0F7J6>&483OWHmh7m z-DfdYmU$;n3Q^lts@2*-N=ICOAWD6V%#ccvaINuS72#f>Szp@}gTsC(d0j+M6N%ry zJ+o6x|sxu?)ykSYRbWr52S> z^d&3CL#u1{KF~`R_@+4bQmKgdV!BVBQWf6I6@1vcAvhhLle9}KFZn{ctizXG^Tcus zqJB+VB!gl@<+EYM?!rzoZ&9Ng0=yt4Yc~tgZBG9<3Q#!*o|T$bkNf+Bju1w1x8d9X zq|!u3p=j+mzr*&7OhTUZ0eqbIowLa6)5-^g_SuH}-9fA-$)DI8b5-gN5V4tUwQ(B( zU%T{OiaBY)|iq=)}Cy&`V-K?v0zYriPvZy-n9&+D)sBAWW z!c--~p4a29|tS+kk1y#fkWs= zyKIY=m#gZC1t{ZKFCVQ+O?_#u$vNO1)~exgBk&XdV5OO5r<7p}E5rdk?_>c{E7AC- zQ~L>Yg7wu}z$EcQu#s7kDlep_IdlFod&WU^Y|qXP82Z`!bv-sP#8=j9mh1M`*5gU` zq=R&`W1Xn&yo4oJZ@k3L8^)}{Bf~A2=f1`N{)R3OQiN8))Jlc#V!#d7DL*!oJiHTc z28&JPE{;sm*&LD69R^&(18zMHRX#2J3>$Qc($7 zm+IMrRtD|W)e#dulFNa*ohtu0lqlQ#sqq(f9U4gRqqO1-;J7V_d)mgUZ`%}}laM_n z=_1L0+$So@VY2#S_pmAF<3_alsWH1p1KanPHcy=@vw%75l9*>x?~Ji88#pa|va{D) zxFP3YBf!?R6Mp+XD{??oJuo&=ewP~{>4gMKiDiAiFCj52@NwvANZ#EsGEZwJtOV>iC8Q0CN;&Z(imcauC zV~Zc;pnviomScMVarjY({nm$!ivN7`y0rT)cmGpu!w>hhLCC&*V9puE6ol;|%#;y=Hq*R-GOH{)4_4~{mO-d&58O)M6afu zfFw%GVz$QU4CwrtSv6%=!u#Hc6bE2sW$TSZ?=KJXP zj{{#L%c{jWgHAB@=>k>L9=1G|L8P;nbCrF6rTE(0nm?FR^BZfpu+}x?TLo6uSYV4* zMV38E;5I5wkM-ZyJ4LsrWn0jFyed5cTU>s@ZKSI<&fXF8;JhO)l|S+E;-$4d}@8yBT4;7}X72n;O>K)PX zBerG{d?!G!OAG%_wlW^VCGa{fRQ>jd%T%?vfGUrw;x1R3^$kSbAU3r@sgpA>{1nER z$U^IZrfnmJ5T~Exs}@piYe&1VJEV;iL+ALLBn1b>H(M>^1XZfnJhCh4Bvbkq_BOS~ zZbIkY{MNa97@N9p&DJE7&pAq>8;UtMq~d=uY=cJ$M%28R`QXfIsK31ikqpTmbYFGC z&aDa^+Zmym7bCU4mBXd_iO+__<@Z@6pyWx))(;a!W&L4`Fz?}YPGImCFQs}MMl>vU zAsTRa!VQ7gL8Ou#o^9@tzDlX+@7Z zFH55rFxLz-NaIp;@{=I_4nDZLErHM`KxU62Q8RJsZ{_6z_Z1eR-$yj(~K? zcM*t0wL#dW9T9tSl0mlVLxtEZ0#g!KTk~3C+(CPw5G7r{-bzipKePKER%Q-b>oY(5 z-mIZ@;1=PGVAfMeRW3V9l*4;58Q&VS_o2BS;Jf2a(r?SlZK~P}JW7!AvN_s4_}k=p z;#{85TBxNX^L&lT82km}w*9?|Kj=$EHG3Y&{>B*JiV#{C*6BESWZbf@xo|VUrLlCL z_IJJYsVzjb0Z9?6vNl*oczc46%1@B|Y0Zm?hT*y%POQQP-M%&;Bk)`f(p|)4{>eEz z+O~>er zAC_^BV3_>yPL>I`+SUVPJJBEU)mm!;CQNSjr>&lnXQKv;+v~|2x62)wL&KzKi}gQw zUR!{$!4-F6$n%@YeE129^Fe0O*y8L+L3yOigx-Jb0ljnB^tF(`CY&kDXsK)-U+JXh z-xrHqo}9@SZk(nREL;OixzFPyc8(z2hdih3(+~gb!~59D(g#k(!Jb7@6oDH1XRPVtGKlyU|cUX&;b zn)gY}J#D=i%wdBoI#dT8*`XCZ5qV>(TH@;<)%_aE5Ovmu{*Iwak9qWy zf~arcE=3pNKA#`#(K&aEQ&-uM1AcY_=c)f@k9Xcw_`4RQwOoZ7wZ}A8)wV1HIe(6?D(!)77QDqy; zDj|zz^%B$Wi>_|W^PtCZrmW1r;r}>7Dm%d~D=y!M5m)Tn3aa5!tcH4Bua1N=Yx)OW zKtwru@nk#^IielM6@ZII9Q#XF{;@X%DZLNnUx2l8O$xl|anO!( zlx6}Rn{1tk9{qZJ)gmm)GLS7v-Fp9QMEBDUjM4KpxbAJ5TYs7)vl7fdIPIdgG9eI+w@nK?&|#KOF~%nn zB)x0yS062PMo53tR~j>mQ;OPAn}76=BR#$)u;Pj2KaP7AY=!+&dE&Diq?{vTz~XI! zQW>eqvS`{FGO};iAfb>dHLzXr*p=K}UOXK=UBy~61Y85#tyXNkKL}^QjJ=Gu(Zpk# zY0c38Ndsjb4D}cm%f2g^*0Ta4QdTK^5JJY#vvR-JiXdB-(RKeg&K>@Gn4EXd)gDKc zmJTWTIe2&j?XRzF!D~(!j)4vK&#KybaIrrs!+G+GXH2MmI^rNb;nT!=XNHMdEd?6)(x8TKV+9P9Hx4hWc-u~&|z zskEJ>8DT9kV?zOY-b%9G#{) zJORFO3^;tz!BKlNw3xUWNesr3XR<{;E5TK6Q>WnCg|^d1B#a)TLjQ%Hm3pn&CurJ8 z<%(lACdnnsDc@33#Q=Q^#eCTU)#5u^9)b*7 zcHA$svGa1;{Au0YQF|rRqC&lEu=cl7I;64+xXkJir+)2ltEr(UDgnZ{;ppTRUjwj! z0ba(A=fsO^-3AgMdX^47u*2S2Rps7X(4DUse* zZepL^UgW~giEOSrivFp*sB#t_KYNcf`(N9D!iT+6t0OPjy1d6Hicy))CV={sMDlW@ zYp&7?CmOtF&nO%|B&AtHEEvDuO!-+{a<`p-ETPliVv!aU0QgI=JY1zb1sH2B5&QjZ z-%l&sr<*u^yyqz8Sss$KAEXUq>L2c2m`Ystht6J8N1Pt}t?RS?q&l#orZ?s2{x@9z zSE7LURpRvKB+g%KO4pRb5koU9f(c7MBne@l_k>$-o?KPs&0WH$KA=fusLS9opkYVX zw=AwDhdy85*eZjPGca7||E?ky%(HkK!fGGhmGY9JIljp;EkQ|#YxD|3m zzx!_Fr#&^iaQSlTgz{Lz#4bPw(uOCs0A3wiKmxJ5zN84`(5ZTHd`wB@v{e?eWgj8? zMB<6i%+QWHl}bW@Y-=Gxjjm=*2qGB+XihGL?f$NJs-xm`b_rMS-XvQuRwkZ zWHR%zFX9qlG{m-OrZ;$rfT7>Y6^4;A&XI%v0i4HmM( zN#p`1$_cZmS zM8Zs3Ik9tb5T=@UZMsTfxZ+KGP5`Wxn2)haT+O% z!-l1_cG-ZHWK5U$Rgmg~`Ghfzb>wZUp`Seva3${fgv?xaTAW`9)Mo$2z4&h&&fDrA zm1M}o1=DyCY)gO6F-dg29rt|i;*3z!e~>Cay_Gl*hYLq~b^Bz)E67`deLg5Ce$`Kj z!em&jXpW+#@2^h**T~D5FRC=lr)0Eg!P0#5{^f0rk_V&T9=AAIvGwA6O2o@ZlkXaz z53px8g<3Vm>m^{CpE#eF&UWr7U>v;qbqlxhB{NQqNkEtF=$~qCQ)UWU(rkhtu*{gD z{fxvWmDpFcy*~>eumv(@rjS@kvRfqqy|{lI(wfy^)%qJM{W$f^9V4dxOyByD>7{qc zJ(;buD;5swfyef~YWyHPbT%CrxDjx=VprGGkc2r~LuRj^_(OTR;U@GfUp?A80AeOz z?Y*&*qDrhA;c|V+`7G(t%&tnP?5jUMBwJL-%`bO7Ci_})QU)VnTfT_HiCCK5LUbAx zF~5>u8WGgD!TE4+L)SETGaJZ-4e3^8rZ3Ti!}|A>OOG(Nh$(csrb6Sn z#-qi`xeaC|>Xk;HzV7Ri?opX~pytoF{*R-x3}~`_+c+jFB8t+&R6vxJPMPsgA|m2w zn9{Y495psY0cimNX_3xJZS?#908Az4Ck!^U zeXl*gVMy0{@p zLIA4##y`etvP@)7gp#$jHVcaav`*z!*T0SFjj$`C5=@T;A1nagv5_ps1|vzI)vZE* zcF&Gf$9U&W@cb&S12#0iG7a#D=Q$!dD(z}BeCJ}zWNXt6#-8{#KlW{hNG=Xhru6rO12mTLKajYY44TU%z`^0HxELF!Jw^# zJ?ycCOm)3%2Up+Dc2YC-gYvwR`sfI8rPzM(bLwH#;kXZ}Ygw5gc=B4ukJhodeBdzp zk9Z>5SKrXO68o~w6q?i*JZZi}7##h;y%1m%9^{gX1z|}=J9f0Zjn;{`-&tYxo^`V6 zCC2a>+{OX^<=1Xr`&d)8b`V2{XKp{koOM`~WF#T<3fc=EMz3=% zwME2__(#4qb`gYLT5H^)RAYAhukwE79oK~9BS-Cke$PF8&k6o2oFxhuS3#D6c&yDu z+K;WLhXqFcN=rHpzSu{Thj3XA?sL&9!#pWOOGavqOtD`$&o6aXThMD06-Yi8Mzij6BC3Tc;g26E2bUL3?OpkLsN_qxm znd8MxP0Ic#o#R)g))t*zPfftV>ziz_IjI52bEKSbo2$^W)D->r#a6dQO*ZR5Q5JJx zWlI+ybaAS0l71uY>|=LBnd(j%^!KpO)Bl)&68&dx53LGlupRxEJtpXPqjX4QbAuQTM?D zs{bw8J%bV8W2JQTG22(2q`VJ#>N=RK>t!X$pObV~b8t8CPp8svmK0@svPAX6ng_d< z=Jj%3HT3>I>tM*Zr>yHKX$d*)el%J@dC{L03mOgW>*4X`?^?rqT5%s0&XPH-#8uR* zVSab)9l{?1{UU=67HiJOr!BatS5G

    V$cO)!O`b!FD>AZ}I$Bw&(GtBMp{0)uNf= z3G?>#Kb1_(@f}MHo3alK)G02#U*PRD8ty^R;^tWCV7+ymkBx> zX;bEe+2w(%{UG1_MIwAEd9U@9EHu1-X-ub~5C#9mlzPvys3=>NNzJ=x=wUQT=|CL1 z&TybSSc|VOnA!gCNpD6zfbO?N47=aCnc*J*ibx+5MXr`O`*ipCz1K8HU(6cGcM`;E`DRbo zV|((w0{YMN9NznIe>bClyD!z0!v~^2OLDu$M<{*P%ehoOhC%+$xA@Jp&ijvg6s_g9-a`wu9wLqQm@md8J+C9)TW7eZL~H)*_fT(S6^UQc{<;DA zHGf+DCL4`5)97CyQFh#`5cNJDoy>&lOUasx-?x1S37_pqt?+$zaX)Irg2%%sZl|rj zzUhi04CP1Kxlb?3OH1%dgz9FXk3-+|wY0Zf#!sQ#qAyludWH(@tP4MQD0jGI@hDB$ zj%~^>486C}HeUptl4d@fp^T-v+%xZ35j`1tL=}!a`Hg7DN|<~F+_jOY#$JHLU9?iS zS2fRQEGkI0kL~PbY0$DCn^^7hpU;2MZ>Om!p(j+DM*vCJ=7 zwqwveCQ{{x1?#5S*!U&V`r=?Ze2>pK_ElAsN#|9GM)NE9wn&1XNVFC(>g+dH(-7j_ zy2R&KsBQ%yd$1HkK;rS3_ErJo9{5w1clvQdtQat(elp@VwoiKa>V>DLnc}M1TvrL@ zjfmEI&)e}KD|>r6aet-ag(&sbm6Bv4HTkz;bozz2|0Q%+>t?&VyMZQc>`AFe?|!$- ztOK*puyKf*(FD^_B2}&ZY4@G&v4n|dUC?I<(?Ue7|E&M*Xf1ib!6&U6K>Ga_wp1jg zQ#?@ff{x7?aXt!U6J|S$gvEZ3kMmGE9?q&sIOwpkchDoGUX|&D84OVIy0R=QH?kr1 z9%QNBCFn|X!TT%NtLp^w^!iGkcWJgaI+@3cgt`#$9kwbvPCM7rj_JOeOt<9$A`@ee zQj?qXsY`t-Y0E<;gu-A%hacEel(mQ7#9Ks=RH)-F+}PW-F~E09!KqV7x!`_PM1iOwB@WzNHlAHX=CwwYNDhD|{$hWMENT@Fl1d59+cM%Pl&-(!As2#Ah%?LH`cu9A~sjrbIKv71}o zxGh6@Ycph15K}iMS7V8^jO&tEXklQQaL9z>Su(qmm1KE{i)vTdO;mg%T%D5b=@E); zv{CWUO?G{2cMZ~Q7nL3So{I7l%@)OUxbFC>fjF>EIex%kbx8iAy~N&Lv7z2Vu}n#6 zb@USGT4~LUn_vIKv7HD%{!oU`212XyQF#q9Qws`hnBcuK$Z_#OwC-;h}GF`ogX{c-KD&;oA zf*BV$YZV3Kb}YW88ki#W$n~x_yY^NLI&h8+G+mLdaHPHAu0XiV!^6ZTFQl`WVp3*; z`C{kG>yE?C<-3Bt_cxOktuwv+y?&0J-LDHvd`xJ_X*uZu{P^qM?@9U*edOmF*HSbs zD6Urz_Y-t6be(s!jlMtKEy=ZP*^v1?swLmfD7I(AJO1a^YOT`R*oS*H)_qyVE@*sp z(<^-@hx`}OriuFX*afaMaOvM4mMxHGg=d5%Cz!m%< z-(&5)H9fJ95^WHfD!V2vgPYLSGWP-Il(sGM$Mq92cX#1PIGpAF=CoOdM7*SrVi(gJ zooSs7(V=Ah- zDH^22EEpgCijBiPkJQ$+x7e%ANFSy0u=PzEEq^$}(X|RV=M@nVY+nto)QXA_m$vvB ztcrR6Z9CIqcfjn=R%RO`RpklRuL^wKNu>(@SJ=Lyj#&NVe2~hy_yHWpry}GynAMBs zgUReL(@Sr!$;Sv6P;77M9Y_!(>= z-F@LwC-CKH%ynNb{q5ko=K%tTp&qBhe1+~+GtrNsN0;yYzg4Z_3%5-iU81&(Eti!2TrD9H@<|6)+i&S+a0bQs0l?meCPEQA7z^$TtiUv`czv z7|S1(w>>Tmm=V}cw2za=stUW+JC~OuIn3KPdTZGgs0p?=?<03_WVq>rUj#W}PMR@_ zd@538uH}hSwjOPZD%)!yTYJMgd52&VTz6Q452BHcLFPWr zm3Y_4*1krPw@vaGb{;mJs0y;9<&^D<_Qrnm($oB5 zzM6W&NFJOaABH*o1pY69(VxE8ayEvGvp#Ej4L{E5;1$sV{$`^B^K# zlIz{V38oQ<-ksxX8YXe_b-_B|WWFNIM#hKTu`KKR4$nyDVi%2QQNIWH>qcW5FB?HB zAOKm(4XRo=^)kSn@3ND(aK=z3@k(zEx=B;RH|FHlGi5a6%o=qX+PyAwu37}lEs0p7|ydSKhjwmx5U-U&jQGl@;Nm8QBchPe5v&tY1~ zQ+En`dypDV$UCXe$8#F0{ET)U4&cu*w909pnwJF&iK z;EM&xvLxDz)xRYM8{f)pE$hF`#AYlviJJUl8Vo9ctQ=y|_tAGCpE^Uszo!u^vTz`6Psvk--1~t>}(A12vFAyA9PIJ${9o}MoN0ybqCwV z&7VTa^|5~nRv)iT17}jWv8TEB+ZeP0rHYC!P>ok7UCob~X}o{OBA6OfxzP*NARPM6 zHAOKx)8-XuinKd7OnTv$Xz@+f9jWh;`f9gbEutISJ;%ZiUUh14_+{^F>BQL$zc{?03?F{(jo9%-qN$neGsJ#s0OHZmfUxiAnl_76q>jNvbL|QXe z?94Da3k^EW*k)~8J6xdO2Z?RC;M-BG8F{RSVj+0OX^J#2b3GD zFcq(9}@<3!eOp;`W1Pf?TVGJ|IYS7%MK}b z!8w+ixxP=;vT|{jTLkU2%@- zmYmB8k*XE+$ct>`7Q8KG@w7OeBkSubz5Xv1RbPKpD2Vk2ANZiiAcl*7 zogq)TU^YZoL})i{DMsuC#9Z`^^?6)m)pfJKLlz*S{!TSoH73{esFHCUbePUU|6_za zKkAjL8o^iGRWfd*ODVmKJmW3Mbk_LJ?RlItVKpIjQM=vxVN?EigtH>lgl=E3dDlMX zTK%Eow&X^_|NF_VGG?(zW}+{t(R%bPUWk^2tcFW!}C4>=T8(VzW*iwsDx!~-ujN%s{X|C!PZtN zrF8aU;~z6~)nbrISxMRVz`U`SwjuiiueG?>KD9f5nT^!9y|(3+)&ry@#y!w9dC`vE zTGJ+w<>-0HVtv`>TyZ!pyV(*)F=kKbPZqnObJygEn%o5LiDhKpU_DVBQtV>C=$y2X zhUeo)g^}9xd_I9h9O>YA*p_M@?v<(L%6!P^5!JthCEA`*H~P`Xw*(SqKs*kemGAB< z#Gc5la5)#!$d7X3fRdW6flL3GnjFvEc+nZp_--8SrzYuugM!^SqOm6wL>tjjSnOd8 zf6 zZ)*0G*D>1ghHixKfQ@v#o&{Dv*&L|2{klZmpdPxJbh^s>Oa6U*XCFCWF~_o`?-_+a zzm+B{E#iXm&sj7D`;c<@FBVZFz7h(11-Qg<0h^FqkN}uS#f66{aw89hpM2C3)jwnm zdSOXR>bj_Hx$yS)*5>e4eQ8iCP>TNe$(0Ex@6Xuq&Wzq&sqMFgJ>@KG^nFF>T+NS* zWeUZNktZ9GRt-qnSyn}wrNB}*5u?1A#ou%QW6;XVq$Sd0{J)WFqt#=YtC-Yp^7V?= zC7pxIqa3I&>&lE+660TZ9xJwix`u#*vC-(5Er59nAjM>T!Opk`{hT~i1Z2O}#QYb@ zKmj&OFy>oq!HiHeMx@D!o%g(+hpwrVWHMzCLR_kul5r~!%FamcKpI#qH}iWO9#Bs) zYM||#Eh_4TE;AAj6Sxc-s(lgb8eetPY`>DF-uH`*FoYtZz>3UINNL9m@ezb+&g7bZ zZrM-aurl%1D(6>jy?4|&iM>q7E%YC9B>2({BYh+NO>e7$g1=rJp-SgM$%EL=Z-m(E zXOK1RfeNzxuM(hdtKsA2vj#0MN>y>PJM{HmEP;8xq!AnPClf^8KZ9+I41| zaT+=vmi?EwJDHi~drtgMs|W`@r-coy1zNL~4$qs)aV9?k#!xb|W~gr*znMOq%;N<4 z#img+p=4$+ip^Y7+tR2jWpknOTeDO~d*U-;!dImZCTJtlBKjMuSznF!0EjVeHHWAW zoBC7YP6(Ke92Nfbz;D|}$77>K2B0YybLfqHgO)XyOiTJWsysimN!6DXT}@_N@z34Q zNEhOS1pvNFv}P?Ubu};C=u!*cLLc3MegcFdAlsTfQ>u*kFK=wvov4F?$gCNxL6{hY z5r8-jvDresNgQ8HuA;;iOOfm&uN=YXm&_64fLl#MmQbVQ4L1BCBVhUl-4D%`TxV!J zw48N*)C7Y}9H{iP{$8A3wfV>r3RD=g(XN0np105Gu9dBsYHo3j_FzZ-Bt~jmacey8 zH-eOLi4 zRu>6Z8Z^b~!tQMd=Bv#EC6G_h>)G3_dK2-!eC;KD1kerZn&}!5p^Lyw=lmjMFOYBE z@q~Q#s8C|5_g?WuKd#!})=&74&sdF$U*ieP-F28AVU)v%{#rMVviAhr0F1aH@J-(! zC$Z$u)}u2$Fh;(rclXeSc4gmyf4|?!a-=FDfvNZ#>|Zx6N<@2_I8yWlhCR>?Nd$~riD@Q3Bt{ZmPfKaPxh{(BVuQjV& z6$48{wG=wfq7>-MiM2iBQ#6yOh_q$is!AA^H&>+!yrHcxkxH(;Jy+up9?|lTsRG@a z`59LUjhKT8Xcf93?`x!9+eY`U9TQQiWCdlWTH9m6L@wS8d!|fhb3b5VC$M_i1 z<{>DfvDCrkZuP>UOwWs4X_YmL;zPXtHHs9`DRQn8NUjksVORC*!+A_Y1g~71o{8oN z@dRtVS`Bx~406ACHjzuFFeGo|CnaF>r{HP6`k5(T=Jx+-Ha_b?)m!J*fC~MW7j}6$ znVopL_&l-k9X_6x=yu@5wbmK7^(551gn65S`u%O=4cwqt>d%8I$Jh=*RV{{U!8YUa zX7sE4lUq98m(gl$bEhi0EGXvATPe_(v*<|@S$HCkX@RzII_+*6@6441CbI+D<5Jt%2ZmV2(Gh9@2CdBB zN-y_lWsHRd9`E(1tN(grd}6-`8#K8HSGh2y-=QCFgau#shL{bs99+41$_YueIUmc; z+<)_S_IMSN2)@40#*7U*F`W5^E#I<=xMkFIy9R5C<*XFYk%;>*nTHu$ezBph zT7)8=OnfEnCgB49#dv!F7mnguXU9s>zL?$4H{xIjt}@;(D!p|_qSBlTG&F-xIvyK;`y=$&)K zrq#fDnv3$XqFL2})6C7XF607zBw}XYr|qaCPP3XMEfC0~l{plzWoD&T5s9NRqF0+! z)tmbMu9(RU$XcyJP_kkpr6IW*-f` z>ut)-tAG)zq1krer;*D-2YF?+?@Q!jOHYHu#TC(0H%tTO&+oYGSivHAKcjY!2#`c^J&ME+aC6t&CB*0~Cj(=TZQc&6zmX~#XHcZ_ zenTYwcsDEUp(AimeNkB0m~3gAG2ah+J55ax&s0O6hwpp}bq)~8np z0n0WrCh)FD#zuPn?aPu_F7_8b^%xQtvtT(oKuFKpfQk+m0F-1uNR*n|H7#W!*=X=? z?80S2tfDsb%iOrak8gMZFCYX5y;OO;>iKP~#(vt43Yh;ab--Pd$s|n~4>fQOn%ed% z_LtTwKBT_#U+_VjoThu1vdog(?vJZ^XA_;B})BzmCS1{{8Izs!Z72hm4On{w)|$clsMYuqnC8j>7c-#(nF+` z=g#3C+VT{e4bh#`$S7ygb-&igPJGI@Ro)tT?$@3&S|E-AYB1t4^ywpb6tBf+98ruv z7K&)R(Bz&nFbU-YyrH+L-@}G7{&Wi_Q>ww(Fw;*|m#8+(tEblf{-Wc9W-qOe+Y|0% zlarRE#XtGr|9pMrNdYI4gpT3^X9)GauA97l+D$GZ>E%uD)6#2~0bf=?f~Pt1#VhH# zW7YTdB8wRdLT18BSJ%nfY^7tZwe8@kMzcESSm(lsyL(Y~Us>#Nsq5G3mi%<~y7$SZ z7#t>0bb1VFSu%W?Q+v*)3DlX?`NqUed43HX&qC95fhY`6%sZkLSa--e*pE@mOB4br zzw-2lyi>O8YQ=i|;ycQGG*`?(C0Q4MOi{jK+$8C>k6B6@x!^aVI8+xDrO6(NZkMHWCl#uu~5xy zJXAD#%+`0xmV}xqF&n{vE5Kjgh3I}UT6`Y_(!3gXc~OJf>cM2$NvD?SA2=PcWF4g* zNNnlU54uXBQ#F$e8cg5wR6zTyDnhpw&dvmbv#F zfyA_GtQ>GAnSN*FM0Hzijx!wFb9_H$Y1>!73y4zldA=&9eK>?UKd(y(ZTYxwXv* zv!u3|h!^9Byc*aro1ihU_&xf8UXN+o=FZ?Vfy}n-iNJtuo0$-XQRzHGX&e-A)Lpek zvwYrW^`Ig~w_(ICSupc;;tWMeN9jh6#@0pitN65CE7loCc_5wJiaEJ?F#p>}%H3~H zx2vqI3~Sc)znPewup|;p?6}T$=%!p&n_excF3HI=T52>2xc;(++kpOS zK4kYEk9;nT2RW9=fT%IDz`*QayvUTuR&jNku4tl8#b-hX&0i{=pcXZ{0ANCj`T`l8 zF}8L9mv6QO&8H0))?#Op9MmoM>hhEhx5<=)b^EIwjwdr$`qPvh;Oe&XHmkTJK}f_T zy{p1fJk!xU3hH~$KC)9*lbs8KALfhcQH3}kf5!{APshup#(t-0z9zLYLIL#|cQEm& z-9e<8U#eNk`<6-&NnfJjwO+X`iK>dd)}z!--{d$vpZK@p{@5vlLqMis?X0M`ZAi7! zEMyPGoU)SV?(dg1>oY8e0!P8AZnx)Cs{VYp4S75$O1VNX$(CM=^vch^EXm!ytNC5S zo{IHR3ojN5dB5DrND3(%eMk6sptfz{q2lMND;Jz&3?kr;(%~Dx&>x%siN|ZCN8+*0 zCt0JIt&9GHLK!xqNtTSvGcky(SM$YSEML+xp`N9>Y4i3z$33B_pHp2urRC2Mr7PV` zylA(slKe%Z_(f>p66a&p=mc52phS2hD&vtvc7H-Q)tgHiLNm4rD=C}5Q zSKx)ElGp;e#GsrW4W};%i7y?b}yg1!&fH|3QPb|Q?!xZQH(t`3H+Ul z!HKsD%L<6-jLe_n_y&brHswUdI2U}BOv%kM3j1k~N@56c2l80OWmRF!$wIIMpId|s z>5Oj^BQ4k45C6B11c+cug&XdZsOemb_OyE3N9L@}w`Zqap6iFqxkP;>JX?luW^P1Y z(|XK6s75CBZpY8(VIVMGUGobnuwGhwG>fg&gG+9xF<39E8f=a*8lBxDe}-*HA_@%d z#O6BK@KXNsQQPB}PNAwEfaCS6N2@Kh+B~I_iWu?hG#~V4j*i2V?tU|&j!jK;PS?uR z&7$$=i$~#T*(i>+LxFnQg`*Xlt%T)Jjzq3%_evY?DQWk+9`*WHp8x{3R;;`We7QhJ zh1;u3%b=l6imMTQW7aN_J?-k#^Exta$k+MN%=k~nKwBW6>0cBNdLDzRq4$kit#xVN zr@bMR#I09HGE-|_U0(GU5SySYBYX$d*;>9YXS?hiO zQoB=lgEZ72xVXt;0QtJca<)GorKs!ZYQ#Wpv1bI9gNQ+y1|7iW4QuiVz zGA(xZCfLarO446f_1zdhjQxEFQpuxMYr>4QNK~u$%uoq1?gE@qXIleuH3^!pW{3tu zAf<~R%QC!uC$WIX!_r$ie409)czj^g{c>-_@b&P6?p=su>z7tHCc6dW)HJ0j>Ba@@ zW7iZJ=Qq_qNnc!L1Jf;S^re#|%FTQ2n4?d4VV|h83hUa%HOm>N zqAbP1HP~l2T^Nz*<{KMIw*?vuq4L6}Y8Y_J{1P<@Iy8MvLk2cYbuY%W+3YIt8$149 zUekIMqyTho!3?A>Pv^L$%T6qe_$S01%El8f_%D#b`jBW*Aj( zyE(GOFb*7;>GI{8Tc9^4x9P2j&cam{!(VJzY)$#FkB+-s(GM}nO=&^$U$%lZ1Bnq& z8HZjYP;8S$9;x+HyTq=JJG7_%KoDkcH(ea_4bfWth9)Kl1tHBH2nmpr2Lt1!OePVK z^r4onCJT?UF}nvx2Ju~M-J1sHMJ;GCF~LA`IzvcuvXHQxE1w<5hf+>%=;#=wmE_hg z2#{aEQtx0UKK!@iVae6<~O(L-M4v0m8p(KAT6E5Cyum+oI3zcK{X zuwY9@!crN-{&th~X?Xs$D-I!`0xxD{owD3( z>FS!KCb=N8nHJzbE+1?Vg`qQey9CX(?foQ(uww zaNscXM^U9za)GN6^&&s~gyz1p%uF>T97;bVRue6gU|sm=TgTSPev4Z77~|~`F{tJA z$L?uW`%q*Sd&yYTX|=TRq;h)y; zmc@Yx3ms=&HK}gdfcAme7g*Muj{a_TY9#WICRnD`sIKahGHM^2qA^v_+nR6L7R{jH z7)-;g#e&7Ie5y8gG@5Ex*-i1De(3JN(#w{_e(h<7H zUJv>vE2{Xudxl>9W~eQ&zRxd3?>k|KGR-U!+x}`-RFFP{YIM1<{K!!J;?s)&a6O zifQsET4N`mS@3mJAVCT(XKoZA%^udU7ZtD*MaA$BJ*NF3HEgCqB3q%45Vb9>m%Br8gtt zzae;_KIbhW&(Jq>V-0dBu9A+P+q`Lk4Nuvb?>8AWV<|$0*)|Egcy+x$uGQURLr;_y(<_{s7pE&B%|{t2VBgUc@jE zzmNfm->uj7Mvp_%FMPCJ1N24ad+d~yOxrL|{YY_essU+g(l>3+T^9~<%uY6{4ZTuc@t!VjW$74^!4EO zhJ6f&St&;Hx{Hox_j+*~g|5Yto9?7khJi5$xs63`()}MG8?O9#q~;WO+lpoMUNT6* zbXr!FPDw^oe7xu@v%A@|*vkI7h11Bw zL3tDGkI>#q^^I?)--&{%CDG2WhP8z^-|@Ir>^<$vAUiG{uCpn&>+-X;Ma)p;Qk9lQ zg{l)axm+VuzM3k($>#TXBA6FotjDA3_}*+xk23 zBU;A^s%Uf(g9UF#mXR7CGFtQKRtjJq))5mHw_4|2I@IbbF=PB)lu$Krf4_A*ktN}= z7POiIJd3lngag9H1=O}XvN#UIB}=9{;3j<$mprjyhK176KdxS5EW7bE)f3@utw^9# zOqdb!`Zlz1mLiEinH&{Tl#ph>!F1;zLsLf z&)P#2I^QM&)bUHPLmak`dZH(ljRB8@W}x#Qt=4ED1lP7mht!l!i@|_RA*$sZ#D&-L z1=h+#)41>3qN456vuq{wm2J*iG?FpBsZNZhi`#Esh&m}3ZYovZuZ>m^M2>!C!Zk?d z^MF%7O)!=K^AQgb|AW=7A4|-w9On|z2`=8=JghEaJF-=`XZ-Ce3Ilfev_Lj)Jb95@aXq zPlNtfjsG6D(jp#vw!$eci-9Rhf{wfo6(vU_IcARc2WX&R$Q#$XK!aj$*lpK1F@<*8 zB%}1LK3;7Qqa{VZrF9;es88>bQ@qP;Dk1m^yVrmtg-^W!yfgHNzB`94R_Dg{FAbLQ z_Kz8B?40zQfADCSIhS^@X0deS|EAEuFq$&4S-LQRX2-+oVbjwbbeoSm)fz4$6Fzqx z6HtxE-nWgH_s1!PbALB-B3+F2V351v5(FXYla<}8^V>Nw2XosNq9s%9OMj8ZlZ!=# zdzXAqfmhHr5(A?JM+V7Cg`OSw`^eDKL~pOJQpvZKjA2bh%px1KF>o|y)rw~%+h+$( zNFYT<_u|Spz6>z$92@`U#9^5utBUodW?&xRFmXZpY zraq|S_mkZIYv=rC zNEDI5Rvd8KXd`diw(wfvw=)O8T))~^qPbQ+24q8={O_UcOCDlQg`O?t^}g|XEfAkt zOWZ@foL``3i+wasjVr&p^YgoB84ht-D6b|TCjYVkdNp-9PzZDIkEsTApMedk{#m22 zo^{bj(v1!O*O?V~khcx}EQtNoW|mNq2QMP31$>X|6gII<$B&o#A$0NgOOTnfK<2T2 z8_-akMV&M9t3swb>>fI)vfH5k2(z3v8*FO+=-zG)fiG}rI#>NL-}z()HdWbSRQ`*X zR8g-E!TZ9|(2E|TCFJVRFp!OBnTuraA!_cuAU#r_=K!5>-~qJ$$MofS)Fdckul88q zJ9ir5#5-jfu`5;;5LV}(NSW{=fHCG&ele;!yK8-C8=oqIO=oP zUsbB(`3%Yy#YO*P_DSEt2KCeN;NT5O0qgB@ z&xB54xhE!&J8;|KDCUU^zB)<)!t%yfGALQlI&u)vov^^sFSaspBm!=aa@LPFCh;X1 z)xfSz|MhuOT}0GQ++P1ZbF;GkS{ih&0Wklcv=fef|B?-8=VggOE7VmyG*4*-D_^bB z|Hdh8|K~T?*uFw_==`oAW0i0@68sSQaYErVD>8h=MzbJvGGXUO?l@xhGzlhw^_i27v6`y`hLCT{!_IWeDe#tdWah20@;Vzl-6 zDj%9@CF9|CXE@)JKi;))^U}{^?y_Q6ix=zOg>*5UlBy|FY#)Da0oS9@&KZ|SlG=^@ z+Zf>$3TR|hA;)p}f_3UgrI|fPJ_@pv z5*mE+)ZsKdNc9xh?*tdEZV^-5iWIxO9R3H}R8`aDICYG-RNqOCQ)gB_|5X~CFoxpY zXF0EJU1zUNSOh=Hw7Mh|Z!~)}=q-nmZ|`JmFIB|JqVe6oZNRGHYUpgBTg+#@QfWZw z$<2My`PZQuwz2t@w%&Z{OHr}kGPFfK#~MXu*xDq{b~t6Hz8Rt{q)OGIvk9Fed+kUC zON4EMX(n$@`G$T{k@w-s%b0nN#q<_6$)!inkrswV|CCVZ_NSowYE5HpEuEy^~8?%^Je~CqcVlV963-bC0 zW%;8Bnw~HF+I%)bdz%rB)-db}vvo|ltiCBIl|=o*T&7-q{6C`}=k@~N8p;m9Zk3uC zva@>k{Efiu-rWd+6yl*vg#4ew1u` z-5@4>TJq+k(ptOs5euF1pPSF06B}bF?bMkE>0-zMq{P-(sr(51@UT*->A9chGm~pi zC>>-p-YVGHnXA10ven?@?0M`u{|qjMTxB1&%}^t=JJpSa6n!uSRRb&n-!W zzE4|-%C1HT)8Hq3BM1Z98wM-t+MW*)9A>NmL-fG)vPDa0@1*9vwr)fDmAdo z^oe=t?<>Eee0ANI{m|8R8er_JWfEiSh-rUCVy zUx93P`W>Ml8BckHNo9x96)s9==3i`5JdH=lzTX1SuQ<)?0a`1qOjrCPUWTzF3d$oQ z3*ISro$-5ou-q7!Ogl5Jl|%1Q7l_-i+nFD>aY6;#oK66Hs}Y_wp}!(?4EaTU`}mX# z6;l_W-#8j^|7A^=&B(m_Z~DI9PW&sB?4Rhtec;so6b;5;ZH!j4kfDaF)Auz1ASNodg@kW?y0zqx;7P}M7IbWqjMJ8 zGQRyIp9?>jEB#z{ust{_{L6UP@X`}C3WT@4icAhW+s|3#qB(e1k}SOTk7ZEL}BwAFu^XDyF(xw-+Aav28{}k6k zCgs$@(qC;Rph6;oJCd(#keV_jZpG>BD5+x5MCS+R{&EnP-kq*`zHeGXRqskM8hysF zM!mJ+Bh+M>DgO{)6j%R7E@I~+-E-_G{6acP zSRc`{kai65nr}`pd^vz2&FL(dR(uFc$qj{0pAs7=KbSE*HI`NQ+Nfws=^F(V)I6^J zrEBE_K>P0N^EQY09Y!1fqhSXr-x+1&Xa_+yz^QifBt0|$c?ok+?ReRR(UC(sI63z4HRRkPK;f~E?Re>l=2l;Z+}8S(hu%VC z&n+U>qwp~sNA;38e0@k(iZP`KuAx5fAd4}!a-)WcSnJ3)gPF4Q4&c_S?>O7Xp6zCb zCql=G)djvqvt=S!-+5gZH!%Fx1L9FUC3^oO?KLAW%KQLx)XebF0KZ7e@v&Zh@CoB%7fw0|&9s|{mQSizO|Cj<6&Bj3do1PCk%exWJwz#)_f}mc7 z^G>B@kdt5#)pxQA37QA|0hP^45Ixy8`D}EC@iZ$ zsmE-9XZH%`qIfDy4HQxQy2WCqydD~jx)CxE5X%ll{w!wm8*5EoM^7KY7(V@{i1Xz? zri2oMXL#-uPD6&c4`j3zohs5l*0b76-&9^}Hv=;Yd(7K*M9qlQ>HgDPW%){J2?Wb~ z7oq4_iqoxP6z3+r+IH27t!mi5Cfy+3pJNK=9qfJfdHrcAt{qezbF}SbiOF&HK~*0a zMwi|fm~uDI6h=JR%E+i&h+~0A+uKjCiS#ws^Dd6Jz`=H3?g^`+={8fD(}N|#RoB}j0C#)3FEQBylf7emNx6WW!r&n*pb*$H0B=@PlKWj zi^f%7syaC33G={*M@r;qzv4P*#0($?eECE*N1@SWhEc$->MqKb7KxHBzCz9|1Sz_` zdV0K+&Zujc8eWHXHWvKtsM~n)3Kj8G4lJUEutyjGCzpc-y61X(BT%BuG?j{5_7S4^ zjBNG&{Rx#Wqy!0_ zw%Ns-R}Pcrj+J%~36lym{}GE4l$b6wlc+(!-oEXhqJ1DH*rBLWMkGW)I+d0iy&jt0 z6a!fK`pm|Bpvxm}4tfzD2k31%eDNxrbO`wJtaORqPWbh>!_CJ%=u*V|^2yx{(QPS) z&}*!&V$EMF7@D}&#@q1H2$1&G`pc&vzjxZV5l#C$BS?i23T5gN)IJo}+i317=|2OP z=S-RtOXt+|u1QdwwQSnN8T9LUoPv}+D>Y0DCTO7tZASswC;oNAUKH7R&QAn1n?Clm8BCEvxl$;+`4Nlk-5&2hVUr&p0qe}i)Ei7_LnBVj=6sqEV$ z5ibg$KM8D?;rx5jKC!V56%d*{$mnAmnP0wn&u>~k}Sgcb}4Hq)JT7;(M;W-KI!W@ z**v&-WsM`iELpi}AlJNgVMD|2v!H1FpWEKcXhU5z;?|#i33*+DS=ShDHKBB#cxffF zX!m&B(#4rl8yQ*ucEie_ZSBqJPvICxy;OB0!VYbD&4Sfi%hl7>7PUA}8xY4HvCbaU zp6*Abw_td(6K};nQhon%smc1ZssWhqtJOJWSr(PQQWuz}P|pLgnJB&MW4)+M{q@$? zb7!1@H7eJt4XP_b_u+STSKUX(+sGJODUq1c6ky7&H+}fEhWShj<3C&fN6~rsCDpfa z*y?GQW~I5UT;(jyy|PlXQq$ZcDpwA`2~Kz#YB_VDxihzjTXAA)Zqag)Afn<{oQWXH z^PcxFIDU|G_?`Q{zSnmh`uQ0XAv<_ixzdD3k`~b1xEL(lQ8%Zgq)Sy#YK~i6Rr_C#-L8&Zq-%5IvGFhNmOi2k0EYg>K)rUf?626yo z>GN5XuVQbDEsIWa(S3fgZv>jK0Zr)Wy0Seg(SR)1X!vmpy?f`z=kELSh{D!{HYdv2 zRRHDL)cY;2|GIv9%{1Eccy*)e8%zn$aTU zdIGMtL#2mIibo+{n%W&wR6w*Bd%9k|eqJuJ7u8-Ak6;ag9_a#*^GEQ!S0GexhpZx% z;UpB38;|dE_&eiPrx(T&4%Bf>csT1QTsURR|60&#nEwW@g)@76&Cf`jaBg^~hz0r? zA`qIyhqEw%B`q=$kgPs>g?vxdQER-tW$N_sjj^^jImZnW>W0JrrsaevY5;{Z3Ro7U(gZ372hms-StC>6 z4dTG7o>tldW(H|9|6;@tMLIHS-4l`3XtP>YeS2XP-jZL?uYAFZiFIq-v@CR2*)rKzW8~{I(N}50#D&j5uFW;)PWCJV~VHvlW-7FQJ>;^6RX^Ae#n+D~ zivj>jyB)ADISeJ}2!v|>x|e0n_QbnDp;GqN4H46-$Qu2{>aASg9qyy?AhgzH^R0Is zXy=grosi<<3`6}+g%0m-^yn76U45D${>&U#v?RLT#Zq6Z4n=OebvizMJeChYuP@kSeW0Bj@f^OPSM&cU`OBDULlV$q-J!ZJfLYv6m9*s8a(cOBY`>uXk;3(67n9oy0u%Uh%ythEo_X*%PD#Qxjxc|`i z>OF`xhtP)BhvCWkYNG&8h>N9_#pAR$;8u;Tw@o0$?acB$ON*(s-8*J+c^D%fA!ARE zsIvWQ{8k3f`?5_>tFO=;c9N2sRbqlHKZC&ntLj;)ugP_)3#x9TqbJ&CjmN&*+Xs9R zQ|V%IOvY@`sF+UKF6u2jJk!AXNxri^{F}Dv__7huy#cIer6cJf`1~KIB4x}%j@(THtLbSc z#lvP;jMM39^t655Jj52|XzfOp*$B3Lbmm4R&8+99V*M~#5$!e=Bk-yLTzYLDMqbUR z`N5~XddoS>@_eBR+KY*x@2+Z68_}*a#~WQ8*AbTBwQ#-@r>Be03`Tn@K4w|oV3n<5 z|J62ZRh)Ba8dJ?l<9Seu9mHYYtK)V1F5CB9?yK=TlL6fr;LP`ooRI zP7Nk99#DP~%oL~ccSUbFhq&vwU6OSYRnW`oky`vwQM@OoBiK7(1g5z<8(B$Y-<2eH zx}DAxnG_oJca&7%{8PreTv<4~qaWLLYvse{%ld1g8vfcbJT1eLIMBJeqZT%mn!_6? zzc!=VGvHP~x{)_RbG(Ul2hRsO**NLd;PrNSlNy)g(tj}UnANsRI4O_xa9S3XG}+pU zYO0P#VKpzqqYJ57hd?;LQ+fY{JDnIg>?5*HIR^~E|dv*IlhO;5m&YI;0DX8UK71nyqeJB@vpp&xy6oB z=5Dj{XP?dvj~f0f9$VDtkbIK*N08o@{@j?R-5A$mMwl#8h>k zSsO`mPgECoED@(@)Z8`zI?U2B;^1>FaU_sm=>}+HOVQBRGh9aGU*@cm{bnpm*k|9~ z>6Q?O-duWR4_!BBQ$`x>GKq!CC2EZR)r8x_RJmH=p{4k?w-cA!V<(D7Xd3-ckz=_S|aLKuYM|M zV7)o44*Fb0MmTPlZ(N0}Mdb;7hMw<^-8Uk$hBFrSPM3RvY$iQJdv#pAn$Ys(+(3S@ zxH@CN=H~VLXyJUs^R;YD(!_^*a+$X|Qz5yb&7bdJ+V1>eEUbU^5(L@qqR_#S z3OF^fWpsAx*Wp0DGB}TcdMcvG1@%ZMBMR@-cRlaibX8#*obu~=nS50|D$zlH>8KyE z@A;Z=?v5gt+TUXEn>fM3FRH!k*EV@(d;_(dh*>`TEI)Mp@^g9Gs-|y{aLx0{DISo# zp$pb)W94Q!b!;iq31GPIpAV?lXY!0=!7i!uUf9sMKUbT;9i2)>Qe+FcRzh&M&axIP zzv0gYX6X@ne_sZ?_JcL91)H1R{(fAp`i_+=(|&<}xKPRRva`f|JSRm0m1{ukviCjA z(>n1d{aaNJPtTOgRC}8Bjp`op1FHE|;WZ*1nh2O2G!(1utar+4qQZ>L&6;2Qz8MDMB$>XL=Sf{L9i<5q#eOKIC4 zp22Zkshz*@DAj+cTD8CbCVS0oQ^e3iBT_H%p2(Zxu=rYVY)0jLrpUM_%f3Hy0D4=i zn^-z&nl^M=EXoKVNq$pp#cla7(X5`c;5je9Sv)5WTK)imtaGX+w z0HfQy&4$h_rd^DmT(^>d9qnH1k8OqD9e()dTpeUUXkel5N}m7?_LvTlN{R`F7uIz; zDAnd5Q$Ta`TW4;jx9MpH$n*s|yV}^k;CFTHSMsa19%{qp_gF-Bg6SZQr=Fk5!eGbw zFZr(@y{0Y%*Sv~*Lin9z*W1T0de3N|u5v^Q_6}Q(%grOM#@6;+X@O!F`gPVX`{YbC zZ3UnNN(;(;sFfAmdZQbm1JG^Oiw4FCx7iFZ=k{nndmsdD#j=3gA9H^%c|u>R-0#p) z!wOh_leQ34(=A9n;X?g2yMktjWm6zLDDCx*`sCs*_VQApafnvVMOuZNmHi42mAni7 zC>9jIJaCY`hjz>Daj8Y^-i&p$hDl6m99x@ccKP~t%xXzOs|ZM@v?dx3h+bf;I)>if z=EZu>$=DC1L=T2&M#R$6@8>j{af8T7*u_0zUk`=wgHsjM%~;-P`RtB4u(E=V{XqEB zuk;SiOLsIoPhd0s>T#J#9l?+s*obzF{XEm&Bf{Ypd(G#$JMKgkwjs_Fd0TubSQhc5 zuOTte;lgOpdmnch2fT~oQtVPqW6i}MiPIB&BzR^nEDvHO>lY*9arotoO0tVJa(2q> zh~q?|bkpR$YwB z<-_{Q>YJrOlT*c{Ag!=bnq_`wjp`)gpnlPkDY!7h^}u7$thG~XqfL6D`AMna@ige? zG;=AduufPv(^@!Cd+lN7)9+4LA91<;2M`zXXj1R6@;|WR36ITY-=pdHW;oWa=3Jj7 z{c>nO3GSPT)qOS=oNFKM)Vv648Eo_aD->^6{4T@CbLUPh4%)hd9c+!fXt~tD>nA2d z+xZhZ*sS`>f7qn%+h{Ey8^t+*Ns$f;pwRRvHR7s@CTyLU!P6R~e$lSrl{zI#;NwoH zIw1i9o(qzdvS3*t{J|`&>uL9k!_VkzAW3AqL_l$>;dUm>K81I@0QH7>&{uQpLx9?{ z=Q`$TXVsdh%2D%Gw2TY?Qz0j@n7Qghv8@eKXK>OKN&e@QV*;%c4eQ?E^rIwM^FBi1 zjr9uZ!uyMou(A~S9_qi^XO)==EM>$mUfmivO^@0eK$d#hXph&&WTjA+u$P|9ms~I1 z(7ny4rY*Cl;BEV*v$+qHkY*oTazdQPiJ;u=2|Dc`&+T#9Si7|$(Ilx$bTUU4uJU*$ zY1P;B@zZ1zRUIkD5ys;`4y;s{>DjROhXg>J%gJ!Eh|MZbhG03(txulqn=1a7+pdid zahK6aw>T=k2Z%U5cn@%STl86rm-%MBTPtYY19c9~@XHW>hb_3%FT!N!EF{$}NN9^l z>X`Vk4wci~em~GhAMzN&%sQ%e1z$+PUh49JlpzCT-F-N(!mUJF{!;5+6w^H)1bKzt zWjO%Zx}#dLkwf)aV|n&Lm(FmAPw|xdrohV1zkXM$BS2KvWIMU%3CoF&#EM*FIOQ)B zbUfvA+)g&hVAB@D^|}M4MzhBsb|O#xjlY0re{gei6PS~FYV%WiYU4&KpZWnpnLu3j zA+Znm#>JB&z|Hnat7N* z|8P>j`)-W?_3;U;*q~-TGe}oOT;xN7v8|{lH97uV=~t!?;YQPhu}woiUX$4Ko)Jwy zyCvRKOHlaUPjLrVT%LOJne&uU{~e)hLm?{GlPUg6ZGZ)7=BFV{ycu&c9Xq6ED>Qyd4diQej0E5ufBZ%07+idjMKN7O|M1CIPR z-_oeozSz}8cUAf9xJ6PpA52PnC0pevJXCBZmUGR#?zezohFX4>l&wT;?kz=8b!k1Z zYz^fwg$o@ekVZ?|k%*ke@nW57SxE_b)NIm4n|7dV^`t6fZs9(K7Km@gUa zD|Y+1Ld}ztFjD^P-%Og2!o>m7Gxk&aC)OdwX%=B~a0PLZ$$5B}Kaj#k-1f{lPjnp# zkU={)1i0GdbEY}9OEbkUsq^61%(4`I5YOS04el%{ml3wUoF|Z_J0oDnnXO!L+1=`j{Yww4 zO`ogA|2&azaB8GiOp6KM$A<|QA%3=T1q|0JFMX{2^U{@whu*6+;+#{o`5{|olj~e1yASIEOXL-8vV`8X@aG#=Q{L4w zZPL9zBRjzJ-clkWBf9Nje}(QFP^1r9Un;_X!f<$a{%e-u{fF|}>Hv}?#Rw8vezQf3 zOvQR^#tcT?U*+^WAT;!r5=?achjQSaJYHNCe5K!2u?zI_DFw0&Av>?QB5AQk_YuJD z)>vR@3;S)mTHv-f$Yb5Ty0bhZlsB>65^@dMrUQ~lOdysv%aUVwcC^)y7Yhnj>`Zck zoV1YIWeU)Mx;|l?tys_WKTBHgCUC^gK9QfG49Eh6Kj_GFDTi@e^4o#vIyHccsMW9m z5rdQV5f0Rf!*lhW1N)zre){k_nPT2k^K>tnGrQP1z?-DS{(8lC+T~u5> z-zq)5xFd6~B=J^0D-8EBT#M$w^6?gUPH+Vct8N4(l77BBPI zF)i}NShjwcRtd$A>SDL=R)pwia7^Lc5x{oN^u z`t;jisgo}$b!uh?*x8oZ$~&t@EB01R8+5&UiT?1#Vy{~x{t4iXEF@H5$~RQ<$}Q7$ zHno8+r-|*N{*9QRa`P*E$}Uw6Zz^L)p&93Q-Q&*?) z`&GYU5OpBa?ShSXB@KrGI*gfqCc{l`>dKI|XTmQqS=gjn`vg6lp^6E;h#fV_EqzNQ zuA;@;-d464B`QXKd93-aN9|@4g&{c<&-DqXjz>F0&RD1HYUHy2OfW zP22NCRCA~F&tLdmhzkWPbXjRMY9GXq7(~En++l8M&bzf!h&3lg8pzZDJZR$GjS$fQd6*lfs z5}bejGN-l-rmn88X7u%0p;DMj{etSe^7SJ*9@?Y!6+Sn=%{(f!sa5VQH?&(&g8POkPG4nBb39#x@CTNiY46>;I%*#0+ zWucw}#gI5Cby*h`JiNYnu?68<<|8{C3A5$Gue56+cov;11i*PUr_<*aETznj)=9|8 z%}#H8ldv=%0ZI!^W=6gqRbyLR`PE}mAww8h4q37LZ$N%Fnc#J{Wl-|5$X-0S#HS)G6ZFsP(8E%d~ zwvz+w+rrG5d5Lfti;W?>#N-?$ohJZkQivF0s~&x85u7E7o+jB(wT6$@t+u>ZNmLQy zk=vPZN*E&)u!sNSI6XIt5MHU*D2VFuaf1q@PqKyc`1$5q%fS`bH0??NLlo23<;o@! zzQIOKn)uN@ZfBYoR>0zig#FlO*QgcYqF4j;+$Pr_`pICbalO=oja;!yvt8l3E| zT;Yk$GyKxQ{XP-4ct`QH2lBzcUp*j5^JjvgSYpR$=gKgZxG`11Tga53ecyeak4bPux z{vMX?pkpI?GmQBDOb;GtPTofpVr0TIPWrU{$03~G^lxvO6VtxHH%l;~{u*QxmBFw} z?nb5n2k|5hV($ z##{r9AQ)x8YV9$m=IuAV<~}fW3DgX#C9D@*t(($^JKHgGVQ{@xxmqN)T6KGwc^D z--<|)Gt|?U@wmW67F8kI%!A7uVSvv5T>Yv(3n*Yf@<>-~DpK~x#qR!@Qe$EEOVxGU zb%_N#a2+_rl1&pcuxwdn* zvG=Nt7r|^^JIv68AP&k}Oi_kp;5<(I8VSNd%??G~GR*^^V-%ztMH!IyDt2icE!ztT z!Mg$k4e>xE*;BMD{eoRY`Z{e_8U;$mYPY?twbkyDvy6|{1xk$S45JXTjM1KH{_W}3 z5|5_(_}e!5Ee(c&KcUzYnKQ3z-Vx$o_aWPXen2Rf(4oXpzShO9%^x~9Q=g92-FC{R zpW)%pe>YWnB9qp~>FbTy;FS5u(8M?(h5$(3D$GhIN1kB3EsHIEmp|yf-kUVVB?s$CkwDp}h{b#uP|(A}fdeaY zCYK`8=BgWWAR3O7ogy-#I;~PSyCA$?seC^hVuUzbagfCp&Dl-b#nbD+_xGeEBQ;DR zA|Qu%S}N-*Z}5}IgvJMcNk5LOh|j#+MMA7&X&Vw^e+aI{(9t)tAJ9Lsw18vtZY8LEIx4V+dp6vn@dq@e9YFzrx$cD zhu(;%-^MZYi@Q81%eOByrJ~L~N_0q-?Sz|U&KwUU5#rRn85)QoqYb(=P8#CTGtpM3 z+HFci|3GrLn9a#a{XBpq&4j4P6?XYRFPFh)Rh1fdNI9)pJu5FAS@+lzqV-&~*l%P| zps7P;hVcl5ciO&hwjRrR$enmKx$~q@wyp+Cm)`5Ty}#~>nYJa-jIAGEJKN?Q%lEc@ zNmPb=Wa~pW`Vx*+`h$$9Zp?P;?f0rYmvlV=dc2-d6U53P5Mi!S10k&op zxH}U?p5NL1b@|jWIyzQ;_;KOTpvv)jNr&W{^M?s*vro!(BT79db{yQn0*C#paC!2S z^@kPUt8W4Qh+SDw!T1R3SWf0mRlcKq7%63}vCp|}4L{mi;|r)u$dMLwcbp1wX7l_u zJ#DwT?PmNeNwl_jV8cy`dfp=br}dLh{n?%hgUzt)y)-u;cGQxmk^&htJM3khnnQAG zS0$L61dxZ7t`R3TcQ(|84S`-|j4r)w>%;?6%R@-UcVJZO={6ceUG-d{o*r;olJ;i1 zAZG?Pbd}p?unA3v4qJoqbbn7&25fMh8F=g=j9R=2;)Mj=@I^cVwUDr?!i^P}wiyiQ zaxEwZbhVbRR@+X_QZD&s3wIx@T6N)0f4)%WsX+Ubt)A6>&AC-LhxQ+QH`uK^;*( z7mB<|vxKoqj)v13{|*Nm58)GIGLXRGXkyb2bg4y2v@_>(_Vq1dFG2Awd}mU#mc*uh zxpSX`ZJ8<_&Dn#>@T{~1tp7`K6b#J32%T9S{Y+~y*5YOuAg*vFVM%MIfaSLt7hu|g zjyQM)6p5xWd|1+l>RSpwF6#DxE@hY#6k7B{=-QeFqvb8(HJ{ZL2T2LhDuTJ){P+Kv zkGn#z1lFH9;V_)Ywr-@r9O2>i&1-cv*+%jrqFr%8v_xa4y-&M48LYEvyJCILKYc?7 zD*>pC1^|<~1y7;U^^+=Ie<%w2E-mAiQcIu^t5d~p^{V|WAmL!j{gT-b6uDO7>^b6VHjPs5G!IGI~iF2hT;V?-cXIyv{RiR1*h-u|7L{VGT^Z?ON~1mw|V{9)){!Jl6ON}klD#B`*^Iq)|@Um zS7tYu^U$(eRq}bd^;^_yCN^w>)oh8|Z#Y$eixGdTQW_M!gC#=|9(-cl9U~A_HgtA2 zRSR+b&8G?b5>B=8cPuYX04Ny_G-^`l9FAGtl42MDlKljulGmA zovqZvtE^cRy#SK*(!&hXk!kWP@>!hvNvufZ zEkiHdnF*buwmn(a5k2Jib*RVUTfz8%3(MdKXI!)ACd6akJXY22eDdv{Q_PY&GbGdM zuX~YTO?DY3mqq}IXbEz?gKC*_wtD(~Bj(5LbKeEsxjy(!=GBt$=@-p$bql}=cNI_cAQSLsaWsh}l2^Bh7OLCv9tZ_ct znSv%Qt?f#e*(*-D`4U>$Kif|FbMYd2>#a2+P=#dUdBrttN^M+o^OQZ$^%RZY&{p2tDnQ}$`9xJ773zGB?0Uh|e4+_0! zCcO5``>F_43UdEm&Xx)C<2HLDhZ`pmYPKEv+tXV0Ah)^(+k{oU_5Hp?stClVUOORo z_?V5)kNmBwx&r~0D>Zi?-k}>ceT~tYPj+M=?P|s_m?D7J>~#vtKO8w|DPlW^(>ve8yb>fS-qgophXKD>h2DtI0kuD0cCQw-EZ|4t;(2 zIv1+yi{~bqRfKYqIYdg+n6~d@{FMjngsMlKJbZnv-t93c}(w;hA)QdCE$%GWU$;$PdGs7_VH=&cqn7ZB@NTfD8!Ddc5`F5_S@T+ z5j)1^Q6u8u8esb^H;nWMo^~}lM|1fzNJ6~4Pvo%LG^(2qx5YWfV!d3n8A5S;S111C z(0tm6+tOcN2^adir2g&ehDof@-JWFN)7-c8p^d65cQI<_=&@VV%-7?a{Gm&C6gHlg z&#CU2d{odPSk#Y9Ar@`xduk8+NvQZ2?G;f7c~4?|7bVUvCF>P^yFU7gLh|oEkKMa! zOR(pCAKGV}T7!ciS4cy{PI&xXidFc?c+EQUEaQD=PkLAvJHzK{%9+xrmFra1{6 z_4C6cd4v}Cyg(7pq|#NZUff?u@au$hbz%5GIC)<{YbR)Bq|EW&uH(HV$ptEG9mqEC6$L>ihNVME zzi1ZF=4|zg_xbk|<&pob+!5f$8Rw{gtQq?PgQ|N3*##A}RyQ9NkvgUjvVPgiOF824^`8&j(dxJM%Qw;`y6*&HM%!>-l zi1O=2B_n|dAVwh;y2MY7ikNn@%z)6!np0t-n<7U{9=W}_@*Jh^sIs-4YNK7Bj*W{X z?OVrEM;=0|ioqJ4UU+%fTxzs1zI8!7jzwUCO3Wh4SX(}+wK8ZFeSj3~)yzSeR1 zL%H5J?B!bcF7_8lb02>wyB(igCAG%q9KL~z-YU#y2a*-}Y*WtDyM(wny^rt@eJop0+8^_@r3125`eu)3=vPyT|O_iyvw_jwA zKlnQjC}bYvi;YrT!>=up*u8(XYo0$QDI~`?FUUTj_`$bDJJPL>tIdnL@4%S}-(v@3 zf$@x3JI%Zs?FW@g%(h3LCSqy^<$W?m?wqu=$JA&T3jYYYy6JAc@P>THP_4^8!^Rym zagP`)$b(1}JIVKAEoStOv4j1vyz-lEv_=V-1XKKSM_m+S8P8qoxu54Hh2M?S@mj(d z3+3Q${I)eS9IOU=758bHdi}mxTB|F$G>qus5LGeo$qz-i^sNAP$Cj zhc%7ys_aC6E^x85V2haHKo3VT#-f{ba=+2CKL2rCJLsB$iKTlHE-tkAgf?4yWxwD` zZF^`r_{;b26`uy2&47|(1rYsNR`k~Qo0i$DaO=!|3)7%}LO23brz4J(z>-ns4^cgq#<|%m0n{Q*wIq&1FgJF3;q< z@92r=sC6GI`bqdTbKTDy>7X8k)2o;IVuRa-DvwBm;OU3IPFnFvO*Ek$)5A+0Pg~Vn z$uvVKccjd#b9-La?L>akbz1|w0Ug-QMN?A_#upP%3v~^umj=a*|5$uE^`ha9_9|gL zV_W9MSZ&*-<;vD^{9brzwf$tT)uKM~Zh?Q)i^|@w4phXS-rKs}PSxPd!x zX7|;rQrB5R*8Oc4*_T$4m$h7w@VRJVb8`NGcxpn1tGjT=d*M6hWy5^BgBQ`ECm9LF zfx1-vg_su(#zmB;-cj+@E(vd@6E0aVT2cSwc(7Ntx{xprQ5=W33lX1uH;>!sA>1K- zpOy!#=7;tO)26#UPIwz=y31$6AQRc#*f77-`lFP$Mx#`b*(N5fin@MKd8~#pUQrj8 zm7fGz`U6*7)UjdPb_KTJH$pP&ue&DjpzMS3yP*vM10vatT@S;G^*se<1w*~yUj5i- z9LK1-6ZtMOt})j_YM_A2min%D({cvqX~b`@0vgn)TJud!Cw)vE5104gaOT#$Z9OehG*LYy$zS)|g+bOG7v*d_w zXH8T!0M4#-dwl;Z`D9QI@=u6&Vv|t{dGQoTuYIxn*)Pp|l|hfEZd*bnGTtuhQN<@h zQ}E|Xkm>i3t=Q@Vr|F_yF-4$hUiJJ={obCIh@XX#a93$}S#@c5RE9OoxDXr8`_=Yxoj+gYRYSj} zNU@@RezEi+Hk&eTrPPIOXUwU7V2eynX{km>M>M+L?e6fW?4F|DFf=1!{AIQ2e5T~A1M z6ZN01nZ`*2dn^k^`RY7={g1ZCKd(w0i(PNf&X!I;uJ?GsQTmn z0H(9LE*Hd>+Dy~*HoDTLWU*#1DD~q{K_9pTF|5n_2EW8a;0#5ul z_oB1>X5t#*aA=T3Yd2Qb%(Qu5`s$6)_Xy@t;F3spqbRZ2rj3DTIW6NZHYUMxzzadV zRSK!tKqhuR(fRe*-yRd`u+&!9zYiBf^42yZ+W1?pZTldGzcC^@*mKGkWzC+6znz?) zd|!0IkgR?pcAU@yr3U3qh=AFb_c$VWMTSHZ_?g7DZ^5YrdKKG|?sNv1`> z=Y0EBTcDX>_PqGhx`;)WKYvb06$y<(zP<`la#Gu19Zk40>gE4GXy>D=#?$moB+X1gQ{%q3+O zW>EZGYX>h-#yG|q8(W9qyz*hh$1Bga#oeJ5ru4vaZl`3LbrS6?pV_c($c4lBC+lr) zZIP9s&$lIdNEJ7093?#6Sk z%h}nLX=boVCFOkG(d{j=BZpShL+`2+Gd=`)G5Fh;_$t0Do4#kCVEmpDwnAQ5fgk8b z-4ld01mxW9?xJLMowYqR1}>`K=)8&Zem^w{axmbAbKH;Z-G_DcT@71z>JD z!_bRrd4V}j?W-nPCYEDxV)oOB;lV5Ck2XxDrgOxzT{qL}H^_Ae$3|+*wh8X{h8$cg zWmonsMKdVm{f3&T;t~KUKYF@k*ZaoG#gg2}_Za;rV80@9UI$;A%6PzkvRR3Tsk2if zKjGl5F7&2FfqhQjhi89%08vxEX!Pc-E-aDeb&x57c-@UaZSrn)4=nJ1pC-Y@dc|CN z#KWO>Tc(WL6QA!Mr9;7KIOo^l(ji-l| z&Z!14i{6xB+9Kw;jg}w|C}P4P2_C%N6|DM$GD(NV5Cq70Hu@<3``aA3jqlq`3}jN` z!F4fjv2s(>;1R|s>#hw$b2h9fE>vc&a9btv;$&rus1r*VUxsfezmi$5vSTC$F9>_) zsc$D0xn3YwuT=o~KufUplRhL_L-jtyjM|2`cE09G1@trvVuiZr=>G?{x_RpnLcjMw zf`J{Bj@XKy*pw}aHX^TD=J7I{thPJq+L4I8_QOyH7X~qeQ)T}g#~NQqIFGjP>Lz`{ zqBtAGFHjS*rKxsull-i+`VR9gZKwo_ZwoMXNCMP5NUuPcOq1LuJ>vg|EQt0ibZ35sKCDK0^ zIARJ5+(JZ?g3dyd`y*dj#R%ueow?W@RDOl-!cYhT)@Ptmt=pbEJ(4c18H490wsJc) zmSPr?ff-ClZrM@36=qrWY>5q3XMi5vZ9v+Y#es4Xm3n>=ez$Esoy=y@!^b4zw3Bo) z;x}j)uM2jopU@HjMyW*28LgZeN|*4%2jLs}^)*cH@-(eU^!320=y+&Y1M zjgBsU8sG-Lpz#(uJr$PqwKfkW{_bA`LG8)Fvb&ef^QT}Mm8&M-qgoH+#}+0fKSP>H z41^^#^<7+KcAXqrxy84;48tClX%t!u4HSslmFC3|+oARMb_)aS=pA<;4o z`l(6H>Ada|L z3dY+>EEuM_rKa^DYf5w~Br|$wc4zdkrWwAEPOo9K&dNPFnWbep%jCvEndj^`K%Fp; z)I){M(~cg3V%yNjD+5DT_RDz=oHL2XDzcI#v&w?EbM5})IKhhR(3crzYa1t+Obi1T z|ADob*p(QMGQNhQ*QrCxE^j>JPJS!7Uo`2XLn89VH=vTCKd% zH{;@lf2y9|c;pmA70dPk$r%D$)Us{I@>Du2{-fQ%@`!3W_KR}ogQ|6MXC((ak7pIR zWm~~HT#V?gc?xBh3o;zXEnF-jg-tY3n}5r%(e)YcX7F5e?KmX2N4oKjyWQg;Fygm> zR@4;{8>{OnJTkXFVeHy7wGA7DFFRC_0s|kl!HQU>22_5!$MEgQblJOg? z751V)-&rB5diNdc)43Hnhk$|Pr0X{Pla_w5-WFwctm&tQREGA#Sn0l0pShlFf|}lY z9rLrjFC&$=H#@c849`{o^U!Ew{nu10BG)GgZaZ|9$+O&Ua)#lF_osiw_<%fsV}{rv zmpeN2nDHa~`}pFg5}i-6o_#Dly1DU(koB|T(MTLMH?=;w);=qB{XB5}m!oZ-P#%w$ zz_Bl2D>drgpN|;N#!30S(-)|4X+083cN!mdY`d9ikgx@vrO{hUG%zh^2FpfnqK)2L z_!>IEDl&m;`m|u=$NwWVjH=lq2-Vb+uIn*!v+gYP{kuS!AUOzlNk;%!IJUJmS8z|ehkg+_&PD38 zoIUNPz8k^{ZoJax9mS~Oi57cEK`zdk{xemISbYL;(w)yQ=>1ar0LR`xOyETdSV-oxiVHGy zJIxHG4&ETIDB$n&+Rfm_L|Lo3Eu=alAaOh{Q@=PwX|;4t0(YwbugqJ&{_%Ax0i_}A zZsRG^7{U<|aC=;A&j$ zO?&uu7|}m820}U_dMq>o@(=g^LExc9cBCkCsNI1eTc3j-V0keq!29E-x$35%1j4a4 zBT@eq14xi;otD1pq02rn(oXe z98b%3Q6yV3^kMe&EmuMvPtE5<#b`c@Dc=x5O_OVdww6S+_~Na1-bNsE+LC?EAnHS<4? zz}di#-LWy`mL2qy-L>%0kQowKdQnr`!}EP<%6dYXNBsN8WdPQnnrn zg7`uo5tO^Ou~98L=~D&S7uEB^ZA3R`T&m$BZIR_m?WTY+^ zKXv+vSwG%Vzl2Syg#Ux;2%j?1*z49rv^_LZEg9aki(RSOYNLe*%!v~1>Ddg&8Sv$a zTLGHdk`q>`17Ua{Z$yw|x6ft1@%R&OUo!CiId#M9Al4&>^$+7Y1>wMH!cRNNa9Ljx zsk1f3spZ1qoHE~qNpW6a1>L5v>(a&$9}3?RrAJR7q*n#T7whJPU2orv8=^X=Ox&o< zb6uFaE8qlqEciA430;90O%Kr(0&L(S0#TZQ&g0kLax+MRcYcUp>O4{L?7$B%otFQ? zEQ+gC^QB=g;u>R8HLh(YS@lX-lNBI!NLy#S%84T!0=X;ANNRk;f~F1xK$3BaU5aPP ztcJtEVEuGS7S8p)9OcUy%w{-p%h*2Wqi&53c56rUGHBI!?w_R4O##(Ocp;x8kK(Z< zaW`yhaND{d>*6H4OZOb$Azj~FJ2Kl8ntHa+{r%LJfA5s$Ettj4C&DiWl?(jo)$nzk zTsHg899<5@0&~4S?d> z>Vc>8cH~b{k-g!|?i%2pPvE_QM(A~N(0pB4=o_u(aPh<+$A$+IH3{pT3Tfv{0EVnI z|3J9zXWydaAA(#BBWTl6&B0>XG@Vx`IGeiVLqH%KVve-xc( zT$1hk#(i3*S++Dcm6qkqow*uM&dkc3sAR4baqj_{KQ(u1?$pYaB9a49QE~54xl%;j z<^bG4jOTyZTP7KyB4jgoWERV9dz@6#kY``nZ_b0FH`#k?-i_RWn*OoCN^+5gO*aMb)#z>@~ z$mYAu)Si%N)zDZ+bD`y-5tx>{6F-OdMr355FMtrb@@CxO(PHb1iH&AY!QDl9i&MwG zaZ5`2N>4Ub7aei$N=L&*{%omDqB>bm+H5|5Z*2r1S2NUqU-F!m5**#GJNM|$=-JmS zCw95^jlkux6Lhn#czIxhNBpDh2eAC+oB~(-^sn6ubqb!=fmZz_a|GP+f>)LtN|%O^ z_UZyQF5{?0eih^BYuCA))+EIZsts;7_;~QDYg_L@`{HM_>BCGWEX@{pzx#`mloLR^jYMU+;!Vm7iJH>UNZ~d$v3j9E>n=_+|qV>Y1 zvCA(5^!VwrOMUI2vvl}bu+dI0pt6S65zWq#?kr*jU#_H|GvlVPZ_!torf(o;SSrB3 zfICF8TgBsw!zKIa=HX|F0q#cfwO9Q!23M9^ntxVqhF7lJIe+vV3jtcj$PJG6kBGC2 zFzy%F9rW9UH>E8m8nIf)aY6f`Pl5xQCxXzUr1uUIZ9CL%Q?Gdn5#=S-n)?&9?&Yk# zk`n2kz`Sw+8F(@WUMH7C==k++IG_T zkmDyRclw0?`rD7Oq(ruBS*~zU2-g+_8&^^#9sxx-g>p%xckuTl6xMeBtD`{sq%tVCY z+FVx_3XM4WctZ^TyJo=(@xH$&^GsDAi$HD&Wcv>Eaz`|TtgnqkBr~1dg8-1ROUv`G zRhIoO*7=m`Wvrx_+x6Drl;Xb=o^a?=oXGPLzfi}DU#r1SIdK`Ns_bbV823lAB>&Rk zT~NHv$;b|GrVc4Y+GIyBCg7~Xur)!|wyi19r$=PT`Tm{Xqfd2e_Rz-kXu}q!&Ymfs zR>PfH^uA(~p7EjC|M23Nv(mj;Uzax7sz-s)Qj@+JsRy*CYw?VHfy2;3!O{?BO5gsx zc|r`2g9rI=+k%bJ*6=N70rnOihZ{A`Aq#Z`p~s#28W#_?dsbA$) zDwiMA5>~tS>(dkPe_RPy+W4`1WNInaYOeoVkJQ0N4^SJwo17v#+1qXkIrR-rpF^ho z2qg5CMk)cu`Wv;o266L8OQTaqX4(9-F=(? zHTRh99Y|*=3tUb9y{wzbSaT1I&tw)&YhUOKb>Nr$5{-;)`Eogb9HO#c46ugOavWa= zCLX$fWDP{hdEi=u?g$-K@RR?kA}Y`(z3{EFYF)K=?h5yYpnt&3k6d<2G=^*by2jA$JT?r&qy=UZft z+}PC^>O0auun3?r%6BMlzOB9#U;dSlA=wiiMP4>C66MGw02|b zb_xN5yLA0`cl5XkZr|aQp?%4Nmj2Gy$ada)m$2pkuNdfyzc@4YKaSk<8_{;)t?NOV zHou_pHy)%geHveJLDub3w@r5Ny`+n}*CLGR6-%Zvq(=Z{>FYc=+)$m7^fj3GVa3o% z!wh$+cZ8;eso?GLWh2Bw5gr&$DTB^BlvacwEDFODwUDxr)I0HmE00-M#Yy4J$}oTP z+wU`u*Uv8e z=$n`KD^aahVhvh{TM#aIH{vYIk@)~VGh5zk@AN49!4A24%U+tCMTM&EZ7+0|TzujJ z4v6z;SmX6O4GInY1@2E_=DB*eVySK^r>pIrWTn}k%ab+97`O^fqPoCJ+bjvAciUB| z8bdCFz(XiAh*cC2L>tjq1tadccmw{nMcO~(mu)*;^VCOwPp>kpRc?(w{fBMpmw#dN zqG6k_6`RIGga6s|F?eL*gxO;?keZ0Pk$8=HZRT3_oT1>7YxLk88Ru6`oY~Y5U#d_g zc{B&j;E-%mrlAnmh55G%g!$xeF}Ve`!0_kYKX+BZ8(U(dwSXxGW@$0|+rdm1NDan( zd5z1D0^~iawp(5uEaE2QRzzhYEt`~n=gqO0p30fQZlsEGYU{pC&DQv*<*Bk1(lF^d zc76zENt}-ApuU{l6Gc5AhV<=g!3fh)V^1cEX3z4a7;ne;;guHzJ^ZcyV1fW(xYCegB!i|VTUN-|!> zJWI;qZU3}qAg~UqMQrbv(Tm%IMG9NJ_Q9rb*lRNt|IqWF;{T=Z27ZQmY5V)rVHnon*p(Yt-!&y6js+DV zsIBFT3{l@BJ;@CqFw4QN`0QJ_H@HmbBGjCD)v_KZ@{DlP?M&-qK$?9Xz>1MlMh1C*6Fp05lSvNiHWf(=xan$qkZu63o8?$YT zzqZL}-63DsX&#TCa)!y7E~i`4Q9md|2#AieE;@>(6TKtd%7{0T<1$apEX#aA0qdZA zSNP0@F-UJ)`>(Y~>8^&LeXsD3*pwTj{oSN=vufE?&CHDs_wWE6yL3T+-&XVl2J1B= z>M?SC+me}_?ibl?Zn>b=w(jC$Ifvs=wa;Z1`TEPR$e2VV^h{chid0VoB8E( zPAfaI4BWS9NKr}gE$aPJi?wGaC5?>j!tBnSdO&@WLK?_3rE)r48DV0dmPuZ>M6Is3 zj9ZzoM;fM*?O*R@D{_v4{r^rv->;;5N!*w%g}dGwwx*E*+mnh~XXyK1r$Fkfb12+I zs)zF(xp1k}mDtA$$Szs`dOnFaH;{Y`GR$YVdT1Z$1EeRV{`zWaYnlABEhMe8woNo> z-p6X0Ut_Kmzo<~ecp+x=vgRx4ysoVxf{f=T7~2z%o~}@ z0U47vm10aznVZlryDhl1kI@*06ymI zZ0%zxf`ID2fxx$%T3M}v8s%+I#YS>o#ZgZq*7Ec)t__lNZ^1X!&b2&NF!uw0w%3KA zhWSs0{2nJH^&w`i_9VT*;UPTW_L@HR)sAAPK=^ncXK6Z!YhqSK%JfV&C4Yz8_lrW| zR9~lY-JG&il7n0lsPW?ry+i#2@o-mQeteZEV_2lPtD;B? z)zNZAcA~v2ytVR#n6h5PlrRb3ymXTRHJ+TVRk`H<5gUsYo|=g(-M`RD@?idJEDC+4 zVPID?&>LFeoYWy|BvKi<_So{^?t%nyV`_&nm#P>mtJFvGD&qp=?iJP@k>6 z@uL8G->jG*0duChcW%z-j!2s$yG1Icm-L`Hgr?ToU0GGNgOkzkj_DhG3c)k)JKbz6 zH+(u}kDCNTwQj+=#=M|wMTE}L&A;M;TB4fhD{BUOLRyQ_xYv@?Q3GPj-_T~#nKdSB zp*FwTE<&bX264C(&Y)+$j*_gg35H<9J#mOu@cC`y7Plb(Y0^{+@(45$o4EVv8P+Y! z@bHYK&D8CaovS6hEfNp<<_9*mtO47rr~)Q6W``c6brQ@(M#itoWudc|PnVo@1x#GJ zuGQrWMV$o(iw03@W9K2(D#XYF^ac2+_|)BJ)Y}^xmD+WPmXZN?fQ66N(s}}cYBWl3YRQ@%E`TBJd(WsKuk~6FL>DpE9n=;{A}xrEm#o$0EBlV3vCh{SLQ#$V2@Fl{YEACI z$dfy6N9gG8+0xkbSshe8z<6$(HQolwtK5@OKm4ts+%JkA4$)y+ z_HBgQ_Fg|;f2-qf#Ei8cV9D=Q);JXG5YKrW{$gNF*EDjfnArh{5XIwZ^WTQk4Me+< zYp@O%<~#s-sIN8&y4L(MWzlL4mIE{}VPn$2^I!)`j8NDhGj4bgObtheWeG*}5U^0A zeX`}ENw~zph_L|HS*dL;;yN!&sCz2Ucu#){kZN;kU8q;;gj!#l{F-o{s|BRE`-!xxlet3Kd;{`ET zr9QmzzR;%>f5=H7b{9T|gin$LZ@d$Yzm~ptS3tYzM6k*Tl1@ zYyMUMq4FQjV4D;@bN69auiiz9Jj7x=qTsunqvHbQ++LZk^O(@`Dj?Hz;NS3{*&;Qp zVUYB4YcLclYU5eIVXLCnlA~+22<@1;)1SVA2I~j*&u>iJtTM6=zj4Cmb<|DbNmC>wdiHNd6cAv z{1dX%Fv10qFv}0*&eLzJ9oXKi#7YS5{!+fbYg8kZ;TVuS_25G=H&3D8P;>$ldGs-r zbAc4oCUvK>|L4Z9N)ufeXHR_DM`%nte7XmLrM7G7&5(LXXIX)Z5Z<1%S&5YfP+#w3 zxy6kH=8o{o?9tpSc}%w@>G;xVpmX#e*Ln5HT(qiishQ%ft+jS*7v~l6a_%7yDy$hnwmQ|H5 zoa=NeKDve94nQ4^1R{0}4oyIDVYPDvcHxq^Ed?@9P2RJ+dV~N1rhRv>exSlidnLvxE5l+=IL)Z)@uXxZ#-*g?2JceC^yf>i+jkWfXCbDZMzK zDgjKVLP2#sBDFxzOo2}NQ2Eb^w1Q%ke{0oUhrfB+^=~ZN)`AWK*UL9-;M(+L#i$7W z%FPBmuCeBQZ2+uMXcer9()`%_v(dDFhR_rYJD!51KD9q5+xuocb=0i6fAGeWz^lOEbo0?K3dqVE|FsD zV=L~}!a~;_f7TQg+}BQNQlrk_V@F3^seoFk%+e92b$R;p$xx}ZGJBe`suWq<=kA~R zi2?j;#S>LOqZjROD5Eg;<%v`ul~_X2Lj#b!!kZ&K-|}8NC6VXe{3r~~scE0xNA6h4 zPqd8HyR>O_ZaC=cNGseN6QUbkCaYn_{?2-S)GfbsrUE?jdsnTuXZ9a5M-yF|ehdO&=_{7DeXT*vTgI7hvE;Eh=7iCA8Oz1A`BHn;oV8|MrOk8V;x z&D;!kN+fc0s8~(Ym{2g2Y1n%qnx0LpD2RmW{kCt(3@z^LCZy}fKH9(XQ1e6}H%1*a z3+ zkz_p=2(P^jvTw0f!O(RWE!W^{hXjHq8z^jO|B}tEQTd`O`h&t%1`KdOf=fpUmV3Ht zST;%xcHxKZmThK>cJ&_xsnk{RgmsXbB@ob5GU+AxVs^fQ*+96Y)@M--Ww=pBz z3jCXm*%fNBbvdS}%?wY*OP$4xV7&CNCUi0cBsJY4?#mbUKkU!? z%?|q#mlyilBUMi$bu<6Ukm}50((_nAb{CBlaP zR(2t12mfC2HD`LSct4i3>}oU0)!W^^~^jeJEu2QYoS>s}_)41t`j zAUIu>e3SV=*P2{4fn7K-9@bweQCvnOT?^S{#PrvoV&^5Z8{HsupP@~yw= zI%l}Pwvlke&;2JDR0rBFT0-;E^DTGSYc)%R-vtL-;O@q7>x}5PP252}QXFyUY*xA+ zPYkN8FFE2$<9GTh645EUTqJG>pvmr?{00A+oBsI3g^PCvdzCumqX1Pd7Mgm16+`mqPqQFJw@B#6S1?76GZfBx7 zllE%vWtXxW$3Dsjv8sjfvxGggm@nC$zY8H|vM^$^Ej8hV3b40Xwm0Y>PN)=Rzj`oz zy!w>yucj^E)|a)F#TrC_85Jo@0DK#W|4Ce8e`(QL!XNhto`uA<_y^RG=#UrqoUSv5 z74fhk=Ud!j>#6y7+to-f-Yl0xH^cd6&lW`ke=7dM`=2eICGt7WmKR!2VP{%kJrcIs$((43QaZs*0dw?0NIDa_W&^|vg*@y`d| zG3m*3dyh$$Hs6(gFa2+%mT8O0dr8Bw!OcPVE4b@evC~v7TmbNp+*bqI#35V%j$^>d zY7sg|^ou|bq;82lck17{V2zQ^zasn6`o*|-BKa!HUys8Z>C+t7Lr7dMBN1fDu8mnb ziIV&ub5eH|)Bymo(vIb$QhKG))qQ9CFQsp=*uirTuDVI89h9>!k1fYwdrd=C=@|K& zz)V67<6tXMP4s1bNH5DzWndlcv8K21u{k0vuFurpv@K=cIj{4s1b5Ptt;GR7TZna$OQUX|l$C^}@b=6)^b_fw&^ zR_=+>OmsgNY%9rXvW)*AMSbdN;#c4i^IB>aC{{VNW!sCU%pOe`X?r@uoR;pVr#@Vx z)V<{5a9hF6e;K$p%Db#&71i-BuVd2>pJ%(n${jm|&;j{6AIFN_&1Hrdwm^@ zj*fx#QV)11p8F6H4dDua@NbQIvyqO_%ls>D&Mwc6{Uf!$HQ&l>9dG_+=u%fjT(a@} zFM}k`Z%D0oEK8EfLoa&rv)-_3`d>`S-pPd5=#Od2tEuM6-G5mVB>Htu4Iim?SiLQH z_GXRy^~}k(4I4XV;3#wpAxIY->MInORE2h1VJ1+sQ}#nmLErm~S!3gf*G03Cqg(X& z>b{-5t*++j=)lC@Ky34ex;-A7W6LzRT$-TJ<(74lEEp8IC2s_UlH0h8ZJ zDG46>P*sG+uY=O2H2IY`YPY21HS(UfC*4%fSc6ggwA>Qt*mi`dHVha+E|i%HB*o}z z?7FPS3k`*St5otGy8o5<32?t$w$>D<9_H75qa^eM_yUB~4P>X>~5fOh?~;40ECPVG;_)Eu-=c z^MjQGT#6wq_+*PX)5IfBA!FB=G@=72bry=+ZnBHuS3~MUYDG_bQWc7`M!{#|a-BP_Kgl{n@V<-2eZdH- zx4neO`8vL6+?RXlG0}4FlQ_>qi5-U1Y~O7bL{0gzuEP}y@)UsGFI4XNsJ;eieZnZ7 zJ5KSYU{RsF_eu>8hQ=J&CAmVR^W$`}$ ztllK%#D`(D@`COpVBeqoHld0Lw7|DMYY_E?q#^V5*xr`*M>-smy5=X}Q zXN=X&Pc;+*OO~Yy&hYy9*cAwRH#icfn&{xc@s7|YdhIH{7GH8Bmo+GlHHfOq~K9|W6aVugy&dtlr zk@-g07fJQWNTan;X7f`&Px(uJQy^*3+<;kw8*v34|@sOK|~xrzT%E=(Gi0EvWelNN6mvO z(5FGPNiLn6K`tN}GK5xfg_aLwYaIKJ>+mI1hzPKqO7&mOA^163_b;jzsW<_cERINg z?xKPLk#n;gc}kPe)OL7wUm+NAWbvFUCTT7UI5q3ckFqTOf!oIWj(ZcU(C-VSGP>YA zlM2Oi=(8;;`S2qP9w7l^+K*Aox+dQ*?ut^pgYyo;*;I3~wQ7<8ZD4ehr_yh8_wc_5)l)KeOco9YH#G9lnR0)>I)%#?7bGnECcosC zYj>l(4N>a~K`)p0nf<=96dbcgk6G3+>9Ms$`CWpo9+16Lm5y`SkE)lAcl2BsTFYFO z)otH($4S9!4Wx5#0)0`q_Y!hQ*`QWMhT^@*p)Nr8ksMwi`Re5BDb{f);QQc!yaD`P%WF_gHM6Vtmz# zjeH=|+AG6*2l?3(uD}6zT!+^ujczoby*hjKNJb`(`F>e6{zT;HDZTi3 z8hsEJ##uHE2--V3oXJ{XYb_@*6**^OlpqNXps42-!3AV&xa?b&f=;kML@=@fW_8I3 zL$|Pe)sjXY^@Z4H0Rj(5D}{4SzIEJvG40B#9hzoi;Mj)^Q$XKnPX5@^W(&+Qtp3M! z^D{V#9|!{~I%?b47|>yk>rSqzUmyx2l4}XAr_3Oz;7_J0dq2TLX_+=Jf#&W-G(8V7 zTWaxw0E9r=MUsE(PJ(izT)QHMik662-FkMZ^FgZjAd-gAvpsbrkLY~<4NQo^!~BsN7e=cH9=Zte^`vV^wYYHfL8WJpG4nX0h*H$8k@5(kd)mY=lL zu8Wv2oUgxWyf2UHI(& z7Y&^Qg1s|SH^V@vD>&Ier$c@Y&vDgh#A%1q;2|~>e&|<)`s4p;Cj^Z}%UjquS?+59 z34GxkwOuUh;;~Eoom$^`8-7ctWz+IA{gdFKPJM9bwo#d+lg1!^9-ZBb5H36tHMRt) zRmA?x%(MuxV8A!DCty6*K5$niN!}WA5Nk>(F$DYl0&=_7378Tm444jm2QIiUBRmcM z5;g439EoF3vbL5Ggs*S#i@M`4Vc__$G9&es{ol+MKYe1$lDF0bcN?bmjx3fjVDG2paeLNIRxHq9$k{765C0oI9oVek}?boTcJYURBycqZuOyK2a4 z_-Lx}O<&B-waC2SLkRP`mr+>%dsYS0OCmW@@4$%rFXS7Q9W4q9f`h!w!qk2(L;~f~ z35I3!4!n|f_Tro>4(`HiUpVACBD{SnJ1?B+I$)LycR>S1#6l5M6>(xSX}4;ymSR8r zd?x>`*^hIwq>@uEMrQr!J&wa6qs^CdsB)N;$Q~^EJY(UUYfYizcBrNCNOMKO1; zR}Z)6rMLL3OJne@q$XmCNkIIayt<#(aBA*LA`E!o7_Z6oPpgW8E_pmBnw?San@<|T z1fM%;y`LqlYdN17%V=$^N==3cszRbTXB(#uL$7T6un5;bNRIS_u6n6tIPe1{_xR$r zpVSBN=7{JWOAG8QxzL&-b-T~g@@L|kLGwT1)95LAt^}Xy) z9X-qaQmehS0<%Iw$_CFu;6X*31k2%vuH2j3h+>j_Pkp@T5DxTbyB$vc9wMo!)=A$# z+M|2#toK|IF(tAmC#DE#^P{BEIKPz>bB1G*pPa)d_2mPkpOzy-5S>AA;T`PESHpC1 zQkTR?2Y@pvdao-o3!VB=H8?IeSo!lF#g2Q9dt7^pzXLy8*MXOi_j3F}aj~gV5`CaZ zanA8P(Tw!DFWmsG+09OpYvEtaPli0t69tF7R%DVg3R~e($$$o4`~&~_ci$pXXqzl- zlPgSsdNFbixc29(DWQUQC%-akM<&5LWV`h){&*3yp47ObFiz@G9A+Z3C}30Lw$<(L zuL|#|6dpF$dKo?!D6!yNW;8@iqt&A6$qV=XNatdyRUu~is~ZCy4-rX(1~NyY>)6*{ z7BJWJyVKqy`|3+ozqdM;QDz>yBcdjlHpmii<6B81!Yqc6kyG|_@POZx zJe@r~pe{^ZgdZtP$L&Pyg&+n2Pz2%LHrT%wERsMv&iy z(ne4E!eAkgS_n#OZ)fz8)5R-=-i8dkf5*St3+_{Y&y z&ZIU}txKi3jy2r0tSL5$8{;Ny<$0}I@kH9hQj^{pU}Hs?Rz|*?-Mp>f`q9%O zP0BKDZ1D8xcGQ^hmYP=oHsd8j!*Hx7p*H5Yd&j2##LJ2Glnma8h87#~)@C~uVRbSj z-{TwOT@oDrG0*e%noKouP7-mYY3q5H2y8AHkOrHGLD=KI>r+KiUxNB8=fN<0YD!h4 zfzHX-ur(90A--u|P(W%?K1JP{x%=x26hf>YCCRu!HRi|e8(mHqtkpEi{Fy@ugfZVP z_=Ns_fs{&IeWWow+~#aoe8<5^a~Z{Db~e$@w%VqRZa)-f$*b%?CpK}G$3{X8qC|X% z9jOV{kdEFkC)x{QQiz0s{p*7iNG8@l-2j2Iw40OjgUt{3U^Pao;D5$^9~c{X+%pX7 z?|l3_HOtaFt>%aSui`xQOENL9zZazy1p5@H8`6+Ci()s>J<4ol?w^8w-NUDp$FAv8 zu9lV;)Yon|Vuulm9L$^7EAwR@15(o$s;44{uXvMIK7CpT+^NsOb4tyGGpyk~m0Pf) zkVQXHLMhC>rr7A3o~&V<(>>Nm;VDD5to-}*-C|J7o;8^mN5qnox$omvb$P-2)h@ML5?p`wE-_1mC!gb^nZg zbz+@|#?ZiAh}VQa_igSBsUPGtxFuz%$x6G>0Hcrn$7$vwds5Fob71)k`PsbwPkmr} zht?8ok|HwRs*GPI-5HV64Fep^!K&f8K>;g4H!GJsdJ+)|^Coe?85?5(lDzdGs$*HW zT=B1N#=he4@Pz_^Ot{uAiETCVb$xVuZbZ~k)FY1O#lLDkW6i3nsh;%y=*iG@`mN#3 z8H_p)9#I>Ydrq0J0p-?QXU)9|-k2&7TN7$17@BM|TRhX=u2VM^ixt!u{fW+AsbJ*# zk|)B)J#E?sc#Vf@AZy--1)4gVYKB%fEy0g1otY?15G%iCV5?7O6UA;y7%{Z)t_L;& zt|4RWM7Tx4i(TisC(`|BOppeVIK8S-!Pt5%z>vhr4ZmY zeuSfVfpEU#|7KsPtrVQw9m3I`SbS7;5S^ItAtZ`+zsk3;(n8=;AL@+ArLilp54Wot z=kI2C`)RHh*~&ZG)nfTic$$68C%6(zh0V;z6Z&?!V_|CjE1~0lZ9$ZzdwsYReuqpi zqr#_GsMjg3G_QLgj}BlM1*O>jy-T4yQ~+o1MQBaX7`&rI$ZPh^fUiitmU46SmU=BLH0Xbl;JE zGYY4jTqAB3rali|d)_|w0$Mxn8fW`=xql8nq%V22ZQFqH@|Vt548_;i0|JQKB7t3 zH^;;OvXFJRMpDcg+$)zoj8XeC0c^_PlVm8<8gFn$L?`?d%4^o#E881gYJZ1p^-4rmwv;yhAcLHk37W&!Ypip+`Fn zqp*jjhJ9Yy4iTwMj^dEF!O~i-Tj<#uYAV$0c~NGYXCXIttI9Ui+c$GIX%M_N42uC} z`9FDl`anpr*m{OAWHEz{zjUVW>N|g%S^gMU1jzeFL0%=8I*Sx^w2NHcJ3uk5ZBnL~ zL&=0}zXnZhR45`|&$B4b;nMC6PVP5)Jggc99?X29kt>gqRzGo53sJia`?uDt9KZI{}GpEYj>N=)s4 zn}g$89ywMLh4Nm4LnVZz#PPwmUKom{rIva}+^1Ina>@VNK%9wPd6q4#sA%P}{IFNV z+G+5sy)Ks&p@R+FuS6r<#mA*|GqW8B)cVGE6w)Xr>u$ArwSZo8pK$4vwgzekY06Jm0;>`MonUS|a3*7C}((iaU zfq$-Cxy_gGAD1iu_#4Lk^$UfBjZ{ce1un{lyqFA9fw?@xg+l!Mo?>oc_a*z~Mtau* zIkd*o^oM}wsKsUeHvzl0HNc!ZsF0`1udsjB8%gUa-WvHGxU5eW7OqC!zzf( zqn^<&fw`;{n$|2E(LiOH(%x=ApnbJDh8`xVlLt|M<{iTBUbBUSB zQ#BpJ(LdhXAD~shW?+(!Bzj1hFnm{$lhJC9x2PY5Sd{HGwchYp-L%dKxAxeMg-3YZ z^PkRRyx)$jgnnil8?Gedqimvp<(FC-u?2{AcVeX2pIqk(ozv#@e`@IqfBc_j$AQk) zAFX&kxguGZcPj=PaHM;>`8e_=Ytk`w*9qdsXG@I^54whfo2I|8c!fssZsZ zCG6#) zWI^jGRCB1V!z8<(fTf-bU7mQsxM@?IX8$>aw7QoMRiG?iCTRu0u2bf6<_2-0py8K0 z&B|Yhb7@WdRpTD^};QwK=Z7@!p#<|n~L-&8((Dm*+!V!z2#Kd#_Ir_ zWE7Q>Q)cQVsHTJ+!a*ZQ8u(LHf2wG@5;kiLFa;S&nfsI=Nl>nG!3VRcZEa15KwFCZ zud|ZD8ClPl8QwJGz0ghBX&`Zgpr>F|EgYoNYklD2INK8Xj*%*{#-R-r3;1`LR17J zk6~X3Ex&QHC+)~1P2Kiy08YUPnvIJENSVEf@$LhMaES3iC`Hu_cJqv!$&fxIl<2?g#_O^x;Ni&&HaeFX-fypxU-Hqnn%s{Ctmc~85&YvdiOO!^9VFC^KEuXE&C)HeDRIrRxlyX&b zvz#MMA&rF6UFP!(@H51QHv1odo>hG1IcH7;-AOhxuEBh-aeY~UW&BbQ!W< zL?P)mAo|f7$YrKHkT$$L+%E*eIrGmhXaU=clIM~LtCf();5}&NLIdP~ocP4mfzyKRFc81O94^YlcNXHqDJ=X{Y_|sk zHi)tOUV5#C;;Au=?=c|42w>`qEaG>Cu@?6$Yw^JfQ{GFT739*-16P(^i#LSf+}bL5hNR*l&&*Ndbf@_N+_yy4L}4Ydh2|=Ia7Ua|YePwBbGq z08L=23dg$(=RV7tt3o7BmA(nW>dC4^Ot3o~AJHsyw-kq-%z-jkka_zFu1|`*czM3k z+y-(d=Bx;%pAj5UpAch{P0yzM_$OfgHG3GS!UErvcuB&@d)07{TgQn65V6F9(YEDP zt{U0p4WYepSw$oU0(b`BA0i80%&I}u9_l*f&19|xB9UFG&tAU6#A|Gs4u}CXqLTbS zcVzdh}KO2?zNXqL$v!N#mOw<#LSHmU| zW9(V3D@d4!-c;o6GhQx?hFVrVHMfllTvY_Po|M90sZ*-?kCG-3H5?(2>F4CMWlZKI zc+K+KU9rE@00=&CY!`9X7cVaNcslCvA8eQbR92aMq~r1RP$g@agN`Zjl-X ziR9D;1NTMr$E39v;_Zx-^D^(AM%F@q;ujJTJP~TU=0_#;j*2b8ps;9b($M9LV_xDP zb-JSKHSV|T`T?wLU&yxx{27+s0)l6xmrT#@t-Q<+azqfa{ zj&yc3$QRV&ST{K0-={N7{B~}1;-sA4o#VRdpU3*me#dgg1JO?a6TEu>d9u#lEA(qT zb?rBy_HlVu+1!f z)AwXI`mlegO&fTJ)(F3!oVyWTKj3^UAWqLJQS@c3>^Heg3DKa@e;wQz!7J6vX{#|l zedlDq1HT@N=y=%TxBz+|8MRj!?)yh? z$B_D4uLD%)9k;w27awS<(G9wcS<4C^d9n5K3dqI%4*9YiAym>g$nQzgaPWn?b285p zkxESKQRCB0y#?=gh(${l&rWvSu~1mah7b6j7ZH=C)aWLyOhJUimEsOg$c6ew}RvEeb_+k=pnl zsUS+W6oB#&dwN8O&mf`W)H_qoeGu6&Kh*4{{xmgTs=MMxw*D9v1GEQ8 z0fNh$O5XjS`qx6pZK`bKZ29TQ!Zf>}6i9Zi$jWpTPhfp_))=^Oz51(R;d{qV1f1+H6B^@R7hDw}kP{@c-N)k9WdCULD`2^>^@>-!dv?zU8i6@pfxzyNp!ovo8+Sx=Z zE^8s>)#}k3KRS<4!iN908Gn%X8aM82tg!=H`!*v~sovX@GD>G164u5m7n35qN*y=~ z?_m8ruuAXXL$g4LM3b0M8zepxD3oKc3bF4B=WJ71t(Y$Jtl@Dq-mx$Jgm|1*FM!+Y z=iQ(;8+zL152gg_N3%WGK>&HG;!PF1Voo5NAUBRRjmvcYI3Ax!0{N|oKG>+=43WoX zaZQoEnt#F32%*vtEpuB~lf@ORsnI8et^wPE7x@*3Z)*?EJEpHPF)yaCY>WgW)tnx0 zwbdz?l)_~PuZLYTAYBY>VO5j|_CF07o(Hu?gd5gDQ3sc`Ds5k+VNQm7+qs_fd&uZ( zqyOe6z_m_2ewh}XcmH~dkn{$6b#c9729F>jaK+HoQEX;YgFB7igoY;|M<#N0Bp4T&9@t)0{11-p&*Z;h#Y#mOu<$Q0n*$iJ+Rh z??3lS9#g`LZvzkpeXS6y0!y^RFpT`d-RQHLaju_lChr3qR1WnEk@3LQHjN~zosLKw z{cX5-Kn(65&)coI9ktT(w133|_X=8a$$QDB1&Wao$SN+Utw;90cbx-F$TO*yau zz!Co3(}BlNpN$fZ7w|Vj0R3jmT32`ZkK}+lRgTwswY7(->Xg&%;Qx4k30?$6B3*J^ z+W+ld%u%oeR!=(Q-iCXk(os&dR8_cJA80;A}G8N-y)V*{-fmaG`!wo@fiBrg5o4WdokBh$iF^72Vs-7r&4A$IG zdwp%v$5hWsr)dmoru((sOaE>>SU1Qno%xaAGzm3AC=0cH! zxV|+lSJ%yc9GJ?0s812dOLqE3L7;G^mVQ1qoRG&g{S!Qej4e>qWL0}Ei#wyHL;1Oe z_)|ZR|6Of)XmSNTV28*TqamX|^ZYj4KY&Twp`GhXssQRH2ri#!qR0g z^`=R=uWMkur?eTFu*S?va8?*aK?PLI>j^)1Vx7M4e&SDGm>9ZebO=|@H=nr~^5q&y zp*E(g#4e*6Uo{Y+UEZhk(91Ks{yo;Nb063(R+io_;^{VqfA~t4Zc_OiTl@V`k+XlN z!gSu4qQ>ENtugQKg>_1;g4yV%h?^^$)tVnd;p;)AI*l-0U=urCu=jj_WZ0WwXTLeE z$;Dr|RaPb>75{m+WC%Ltt&4N)KsRCPRlAo|3&t1j@Bh;In0!T~zj@yXh^Sh=(G>Qf zM(U`<+l&RRNj23Q8lR*!Dg5M7kIwTlx2U4%Cn`r4i8x@yLYL`0_(XN!d@?yZCgY05Ek6vcpd~JGg@VyCI={haHj97m(060@~*|pejYFiDOwgg^3Z8y zkP52Bx#ASjmHNCBti?!HJRWxj#<}~QnLKf7TznDc53WvFWzN#hA-ng*qV_vm=k`|~ zDujkAzQ)~KTNQLz5VQQ!y=0@m1Ng%Zzo^ead5Cc_`25IuO4(P#EX4a8qz4DG$72y! z*vsSnb^m|41J)c&iwCSswZ6`xRQoJ9W+58CFt;)qxjc1G%Q?srCmtasF zas4eDG;dT|NHGn}XSO^)G7buU6T}T?apA2TzO(Ub5ic%-e(lBR1pn<+=BMTGOWi3iA_PL z`oEtQtGs>QwnZTF{0|>|wK-rhYf;=eN@kf36~>qiNmm1Ap3#Pg_Jbi84`LrDTl{=) zs8!q_BEoXo5P1dAN~FiPgKCC(YA^E{D~EjG=+Ku{*XG%RA&cJ>Uhg###Ci9|noi7- z*}PDIoWu}Q&V`53$3nJUizv_P9|US=LnkJPo_7Njlf>y zXz|X}Eu&@=5tnpY@$ictR)!P!N2`)KZ5}tx!fO>TStqZ>eL;o#MRbHfcxNKZHB=^O zZ6N&>s4d|~JOCv=9$a;(=_Z*&sn<`no*T0b>ZnsHr)kpAK0xWR z=vj+jX%O7K|M;}1$4hr3wwCQRH*nL69lJhmZXEwrW2`EOy`w5$zQFAxh9?i7om9Rs zww#mdfHI_FOKxSlsmhnA&ZaBj=vE{Np~Xj-Qb)KM-e#>v3dU_(*T;KqR3&~0*n#{A z?36c5DFfqIa8TG&3VI)B|FisAa*dk&Ibb2f!`sy?AyX(BsrQUwlT)Qz;euiGsH}hn zvyxx41Z$3EfaHkgm%1%pZzP~JUG4FEXxz*<`H!D`*H1)W=_Ug*E0z3lx8E*)IjzG= zaFT89*5ytKz46!T+@q2>srw8yA1Xd*j*=V39Z95$X>y*Rthr>u?xE?pV>K=sSA3LE zLsEwBj^*Qz0UV&wbs7kRP}z9mNMz@1#5!}Om{@GC=bRzrI-=BdGs<`Hb01iOs;~-= zod(?X??AIiTuJk=gC_c!QfmzY({SeaS;?{?VZN~OZb)@`)mI=V!^$h~RU)id#nAdc zGC#?>XY2}|EUeoLw)yqD*3omIWSZ2!IQn(rf_cLlsFE40RK73SpHERNM!A4L5wAZ> zF4OOo2w5H*C&YWNw(}M z`q$ zQK4@W_Zbmifla(hN-xmF;X@_=J(;|+(~k(8LH+xp(VUSR7&(IR-j2}Rw|2ME1kjT> z+{)Y6^}U;~bh#(TCoBIXdRemuTs$1UCyobc6~8?HyW*dZtnvq3`$SJqm!YnJcXQJ? zDZ9*}{`}3+$;uuwzM-W{|4n4yuM)rvdp!_R-)9Um_Yy@?PsV4tS^=Uw@6QD1_73AA z1)oB~(ScsK)wjuSX&N(<8v^4@%?4}E`G}=mpW~{b63eh%c}{Ob(}GxK3+|lu@`xql zvYA|JgGEMkUztUN?uW(r)H`$L+V(+Pc0p^DmEG!>+UJ*V2{fX2yE>2|yWp-4#Ng~d zZy7@sdnsjJ+*GLtHE#E74oj%s5FZuJs5tkWsAI5;yW;k=DIzR0(MNi6;WZHnv=6w? z(%vrLI;}KJ(H!Ks*E^Nr8#e)}`FC%+L$_8GRZ5d(1>bRt?)?-h?srwn6E^wYaQYAG zU6B$=ZrSF-)}FTOl?pndq7j^0c}*?h{?Ebh-Iq@Fy@R<^>}+0sth9)~y<39oKdU8h z91r)FQY#<6G^}wquHN0Q^=r>62AwWQq)LSTD2B~#x=+zm z%Y)_X##-aExufCV6jU3yXn#5+Ye6!9rNdlSE7T)^Tp3RR%Vme{Ydn@YL-I|Hv%mRk z?I_T1{U_{+bUn0-&Ouro4#EwNf9YC0UsCM^lDWevzU%`lmZi3@9}s9MjGEJSO)`pC zuMbot=WkBdedN10FS#QltWpq{|D@5H^QOG>aAiKVUt-|sHx>+j^ z9D>d%itfT+qJx7UnrrB&Lwk6Ar8tl2g@ioTmt)KV&&zic?Qj*n_%)z~SI8@uq@>lw zP0}mjwT$|1&W{T}HhnEodd=NadlGlG_Vp|6^D7q1t7(0N=jA()CK}p;c}s-ASok4k zWmTt4OHb^c*@%hikA1L#mxsZK6mNi?aJAY=J^k43IQ_(wmE+Dzzu7`r`ono<$(oy^ z0)irxvJrFqx%%@N?WwNVG_xKtx}Ko1_Y*s7jmHbA`TNX4@=xxNiMLDB0Lu;1*!1nE zZdhQk*r_gzlx9aOUOhb3__5y=>3BqU&55lN2A8b4nA|c~Y#@$Sp;98hf1yneElO!6_bFhTdcB*?vH!hU4YVf5ccs|Z0KtXJhERl7#^;c)~ zi>n{6QaW(Rz*W>~VQozQp1DNFaItyf)KU+7VdF%HnF|YMt%);C4-h!gjah#y`shDC zO;f+gd7RfSYJw&Dlr2+8QmyG1zr*it6PanYF!73V+JxRjW3h%|7#?VLNlRWm9ipqz z5d6d7YM|R{m1SXGgs1^AE)wWi33>uNQMZ|=H>I({r(e9yAc*BScJYNGU4 z;=H6=e6}nj#K$3|BFDHw-Uym+_4H?EOsbs+F3w2{QRqbYk56f2-|B1(!67s}P5n99ioklvFF>(= zO!>a*t{lxObZBPCcB;zvZUz5X@a@{gXb${7nN+QS5@McNSPEUlfZR4+KLJHeJevHf zJ73`TfM;TBe@IqF-8T`s6E##X#`o--d9$QVVasHfQi0W*LUM1X^Rc*7xTzCsCa3Dk zhvJf6YKwau#5g;KD%ASG)pRrTk>(OQ^pcj7(E7V&Ju#^F6%PSZf#(_RGmcI^3I0BA zMqJGK#FsY)jJ3bdd(=mF8F7T)$QSjKoa1QN6EA;NzvV$|))*9ixkNLE1X-(t65PuE zhT9aAncseb^2{$OKGMHF2gh+G(tQ@5$E7iM4ia_s_`kHxC$O&+wVQz-<0?nJ=R>Vd z17q2V^rV{w!lXXSotygJ<4dWXocu)0XwIbFs14J<(`apnlU(MhuRcPAGbO;U%VFDl zcUp+yL|2o`1+QEr$U(z{PEBKMGaok_gMvLg;*1A?c>+f2+$-zXe(VgJ|Gj`a$ zG=$9tXigSAmmul&%d0UeZKJ1B>2uQbyCpF~X? zC*HT8>>)VrI-F5F@bCa7Y@1VTjnmS4T-=+t0rakquH($vr%*Gfv+RcwS_Y$+M)F@X z7_Pd?XP?HcUk7gv$5A|pn23cL@-lYt zdr4`MvKxUV-_S0=pQrJm43~PNkKOcl8A5V=JbX0$Mg>++#cPZJikFK>f+_Zj^px1n z2w-wY2j3_A8XIchWgB6`*I?ywyTQr}+nt8CRao2q_(q9+8E)jLWio(KG4LW?h6!v| zQ7HLWoOON28bI;67n|3aZ4&nT!wezmYcP(>G&!tlK6_koCrIbzNREACkp#JF%+U;Q z9cX1crKi~N$q*Mux>Ud1Z=Y_iR$X(iSaPPUe^@chHQZ+LVIJ2y1kHUms?qN>I_|}& zSHa&T_Tc@wIyJfZ}{DtYbgR(#rrwPaXI-n*Ec7~eFuebpYC1R_+e`6KpM+lTT-(!v0)Y@d#39&xg{Y%pMMN(2#0fhe z`>X4{gWeT#3*x9azw2FO+fu~Pb#65bo>gVdD&0So@Th(a!w9H_10^ga#sI7Ae48rk z?*=4)c~!3rb>&Z$UiBz#=VsF2EadIJ{ENR>V$?P_PR0J$MXq61!JxX9>8`crX>smB z^Ucdm%BG=;KINxF_DTLeomZd3HX2j7lM+V4-&cHM$^Ru>DeHAF7tNNhgw^Ahxc`t*Mfk(yKbYa-cL^gRPY-Z6}LCaY!dS9-EV8(7{h(T z8mi3~5&agbJszcU>}^i4JrB5d_;&F4_cCEfW!sRq9bxoh-!E+QyDyWQv-RCN+RONl z+6o^!?DrCtV-FOJU-8sG#K*h` z!&ho-r_hA;PycZ~wVu(8Z5%7}R>Z&-ZNF{WlX`WD;C6!Y^^6B|G%xeon9oz1@? zPYuY*fH&!4I#~U>NN3ZK0bfy{=zM=#1=i|968wpL%8-q5qVXkMh7s6?%Lb z&dFTe{ejXAsM$Ey?BU-z((Uy>D!F4Tg!w-5Cy}?WZvUQNUUBxp6G9dYk5<(B?Ef1& zNQXMi(modc418Ayd;EuFJd%3@Yc3_zls&_H#rqK^2`#ag{dfsV%}v};W7!M^04EM) zJ(sQGJc4zQ&|EIl5ObJlGZTO1BN!=c^iyZC#zP})oaMe=5v6~I9p0X+F}4HM#f0kr zlFTVmzjrC}ugAqYptY*9!fRYl#U+2Aw5x>zifP#onpAf&ffc$&>;3L+C!%prh0^1) zH?OnD&A5+3;IrdVJh53_rts2k<~u)6&1IJE)sIR(rRQ~99v=l5M1y4};YE3?^SuE8 zkMSPj)Gz@kaqZZau)xOgTjS#YD4>;uN2>q5tw7%7QWb`XGwJ#&HS6Y`dv-o+7{=pp zX_`V;&bbE(grHRI#bQ>OIazn6Jbk@<%WOnXCTJ@9HNqS!%=qY6o1hWDEe<>eAwDM` z>iAg1Y|&oh-tM2idie#SGYQ;SnI5wB>EYQkxZ_RR5-VO)zr0twHraDE$8EjhdmfIj zB8QhyXPT}D=C{6W&pfXDtJ!`-i6)oL@VUNX0^iVW9Se4LY@ANZ+II`CPw;Sby(ayf zs8YD$Qyq0a@2#a%38r1uXOo;C+4(X&sMvL6C-#h*8LX^LJg%Ae>vzHnao3kRT$_O# zv|{cmLh*-R>2uHwGS>?vq6ZczdqZ;^a#p3O83vy1CCw)~SFIbf;@71mCBjYg9A>j@ z;@N`|^{B7bBd#`<|G!AUGYP3AZ zh<2&W{WJHex8ijmT6NP==X=?2m~orlNr^o?Pl&v;SD`Pu>|bl6f9+RdY8}&|!1dW5 zA>ZvHF9?>@cE!coT?QJX=?uV97~s1jROqtP7bB>pj9*Fg#^quDVjjX4cP)0FSpU z;fpsXhKyW;wx(#y&LOShTg#MX1EiGQM4)KEh}Gh)tUt)TSgnAlqIEKGy6M^y#^cS1 z|5LsHS*0`& zekQeWgQWvAC9#6dz_eyP_8XUlP=HG*G%~1lddcV_P!F0bK1JF9SQr}frHcd{(MdVT z{ASj`R=z4h2d|#)$gt4z6cm`2q{FURX#d<`qm-vs|v9_ zEZFDhe|#Qwm#X|LRb6RnE6+vu=`J?)BJhh>~ok*C& zV_bYtbP!XqazG8D@t)O0*x0^i0XbGP9s;zgEELt8!_6;Pk$A^5b_*T}zeNd)JX(u1 zUiT@Ndhub=w|SU`IYOmYZuM5 zurP7}T41e!xO@!X?y{KwGo;f+#gP*uQ#oyy(K+}u^UK7WBIKhBB zDbZ0u6BWxHJ^2xXm!~NR5UF3PdVR=s1xbA$uL16v*B0t8C?ghtD)RbqDQrrgxm#** zTa!UW?|x5UKJ{_;(h_#xm)XB?Z`1A`2dbuuL_Qi7M=Lzlng-x#Yrl3OF~%@j3zo1( zcWHbjDn9MnX8`AT_I%;d*lT~DmnwdyZVpu)$21_VzZ^~^tb>E$8&B+?_G7gorc9(y z%a>0j&@Dcd;E6G>WD;X4Kw(t~i`faD(=2yS2l~Oqlr8-_SN8ay^QSs*i@RfGdnJ)D zT1R85H<^pKL&an^2H!$3xMzX4RRcGMWm{>guA|FPBoGK->&vXbV>3b_AmInkQf`?4*ItoW3TN! zwD(xU?%yQ*R(+~KZM-occjlqo$h8bN8zADe{KUSqU%u9dsM3c=4*=}AZK#i1RB#$iH^V0M-C%VKS9X%Uw}|M-bc=<8wB%-i5c zH23*An>gvH2O6#2s`6de6B_FWi?l0-g>p5w#MUY{tlnPemmQ)tK{C9M4Nk`CS$CwO zqcuhzI?RIFYS|9!G{bdXuz&_3)=eN&_lk9L??>59e$gAm4 zgiHUD5VU3k*zm%DCQT1NrvrATS9MV=`#1CV>tOv0<%`@hV%WFDJ2moqRGO0XTe=mO z#<1+sQdUg~cu)kL6;t?-%B#nzR7~6F&zT=@_5OXGbSCt@r82EKhRVgiiXbj#=Fgo- zknNZxhIK`zm7J;(OPQi@%x#CB{oLulKP3x$PkvIq;45o*Vu4eX-_L1IGdQj>gn{ zKq|Zls@kXDuq+U>3A@6#$p6P-tV&M{+y;*W9YcV>vJ)P|1Q*+g^5#Mm@0|9-hvZ8C zy=hkp-9K?XP(Am?`s&G&>dSQ`iq*Ju5}&yE?tH}%0gP>G#8q3_6`F`5fxt08Hp2ag zyruA9dZ$Te-i{VYXv&~vD}>ylBlk|xr(hlRI;eJY+NEzqw$;Bz?p3fy&@tWmLkF=< zDiQ1XZNzgGge!l-%8Oah2%N=>prDQY%}1{--QIV)E{Y5JL!=y9&pm)yyY=uIXn-+T zeWkY>`@S8%DIY;oQyAtXFRwURw2}OC#)7J9HlTAFgPri$zoZX4M-j1@JHeBuufc0t z_5Yl1I?eAGTy{(f+Og;*OF{Yi{xNo(`=l~C87!q+gTmJ$Bf^JM-*lD7^yAnzobb#g z`|~R!fBk>d5stD8*Ne=41`1fuw*~8%!nfwIW=Z^=tJ!|q-OSvF&;oWU*MuEByPA7u zUE~cDj8$rq^Oaa_EGTU*Kx?$9L_P}Gs;UPE_weK4b)^X$LNPW3-w*_Tvqfv;V>oFd-Q1`;d!3P@6Az?BNUgO zM)dI1%D)z5`KW1T=jK*sK?#hPB#gkKGQ?a7Xw@T4>1Oe6Jp zBj>9Xg`Cy5M3MXrtS4U05eQXmSYhY~?&nOiKiu@+RtjD7MMnsZz!yUQ2V7r>Qju0x zw~1EEhfxlQ>KDl?tbT{(SGl`6qbC33TN&?nkto5VZ@=rXijz6J>R-iEsC4N5Rv&dW zquyyFa&s?K!b|~iqw)o>LCVJH$!6`dhz$oG?NKV}ZopN#O*b7F)c*fS1QP<}Kd{5_s^X;>4L3>`@$yDD_=5&3 zKDTpzw08V@*el z;3+DDxJBJ8!gch1c<2S={QW#r|UmOWR-^BO{jh_A1pqKW%n*_fxZd0enUD!~-0Tcc& z95G2O!$#89ZGw#27<;O)r8g-PlZr=UUA4=V(~f6f9f2Cwc$@&OZsoU0Dfe1~@c-T& zt7=r%mR>OVjkYhATOFQ_4Uaxiu&moa15b8xMC0dP8awU^FFCuYJtM53YWBQ{84UnH z8K}_11xfBK!W&jmu=&4MDBuuM8(bs0(@ykzeS-@vd9Tn_o2-3F>O)|@nk)SA!1Dzi zYfOkn32rl^b#%#gc9T<>_HWjkmyT_@@c-jaZiaH)frK+nZhC4u_4#3uQ?vT>&m7qH z$)4UGANs2Tm$~v-F=t>3$^d7a8;!Hd2%*rzSF8%2NzT}@s(~oM@`I_~fKyq)T*x%9 z#Ht>MLQk9F(--(Zq0&4Zx5NW}auW8Bf0)TJ?L^na?R-o3V6CJD=6rQ5HK~mM{3mqz z4|Zz5op6G%J`PweKJO^ldAo0FzaCLAI?D|oFNaPkN=nz5hMqw@BkY1S1;Z{>c@%v^ zyH~cyypOF)4;uTu7_(etlb7-(ltf}iK{r4@a4h9q*Yuy~!A+&a@`z^WJQ(;9=5g203kk`}_WwI3EEVjRhmCCVmkzfZ4}jJ%VY|zg`!D7_u9TG# z<#wx)xg%Bko7PS}WL26j{v3CY^dI!-?k8Nyfvehbp9|vy(yr{`yKBF+5nB{z|fLz3rj` z-m9FpR_9QDrSY?IZRskEMwMXCBw(zGiTU-Yn(|Ta8U!s^Tu|UTEckAp7~NP`r{WKeFdu>Mm%C8q6*-v5L4W46ahgic3t!y{%mBPNu zU@B4ut1?VgHrA*STw*Tm<@`NnigdqUYnSS`CH9x)4Y%Z z57uaG`WShp-wAJuCLCSVvx)@?wn0zVTrNYYF&tGjj~oeK)cEskW4O?Cg2dEoGCC*> z4fh1_Blaphd172_aM5IMC`>FP>B^;$QM>f+M`gqgo`J;5&vK&MO?{Y!N@VjW7T<%Z z>6@bvg*TER;2-~|4UZ>^c;C~S3civS{K`+hXR=h@7}U=* z+d8t`J@fM)k#nl1-=3DNCi~FgO_a56sd#y?l2lv*)5$J~<>rm8CJjKBPW!)avVSvLbA_cw-8gcZbn!J69=y5yyz!swL^>g#D^BC@JO^}@oen3WyB8JyI8=JYh7Xu7my)h$M2 zZ@&0Bxz30B<2*RWs!Xm}?9N85+CQ8uCQ5P+`ABW#$(jnGvm?v9j0Oaaw0i#tdG8jP ziR*i$Z0t=wq%VlR0lWjdh2iI!(o;P{sywvn+OGCZ|64JB-kE1@V3<$f27H5LswVn` zdeVInf8fZG4EFyaDy&hSDQjh}V;vMhR4JAGeDl?JmnQ;@_7`R4W#piR8{!8Bo1e%C zG&b%J)w?IGm4aB~3wvIkO6%Xh0}*PYDKemvUo*VpN)9NM9kJkI-JR!?j)4Y>JWsyt z6kDWi!nj;h@%c^W;}>1ZmlA7tNIf6Pb{Roxr^8%*hYCFt3=KIo`$HQ)#H~8wMb&HL zT&)s9-7H=3iLZ`=?|=Up>kyf|;A);ue~u2W;)VY-0T4pnk?x!0UL}?AM(y+JUGtjj zUm{ASP(sv|fty!{9I`4hgwgb)E4y{c-M@o&^IWVmCTgy@?M;sf^-3NQ!t$xQ1zCav z39LonNdM?-5`kZR7{oz0ar?JkHrFryGo;vkyoN_qfbBCM@?*6#My<^I@X^ywWktom zA03bi4L*uo8$E_~2u=e8-bZGlnTL&>vZ{NU@~^nW=LiWajh0h41$xNgL3(f5}zzXa5T)pbI-M_6)UvMh5S7jJlCoj0g5t~P5xHf(N z@!^nYU)j8`6phGXgA?XDJ$1~wb1qdcpMb9)h&Ml9QB;=&#Ld%xJCSkxR+N`FS5(@a zC2Gb~-4%cJ!?&b5$@)uD=k@;ecM8!nt|}hzov&PL2D>L@1fb*XD|qtO>-3B~fWjuZ zdAIx*(A8+XpcsB2_Ej4|9ojmz>;zf$Ung3w>-3|-Pu}1CSJBxLm>L^MeI|nZPeu-P zgsUO6evY+vnqX1^Zy(k_e;7^v3-z?Ewr;g+Xm*{ zqCS6gikqF{xAV};Kb29n1rWkd^v~vK8VE5jWq)IBSZXLJU|YWbwv%$K=8Li6wkjZ^9t%+*c-Fn@$ozQ%{DarTk0twJH1)=AK$ZAq5Ut7)KcV zR#eosdM!a5Ct-NEudK`z!NsZcHX|XZuqfU4^YHWl-E_b2Jr%tq1IkE}v)1RThr+4r z_&Nss$(yV96%k_~_%lWC9x>-#LxlTp=%Ilrt3n?D1B}fdI}buxT#H)vwR(bb#J85OcobX1nS7vB_(=WbLUj z`15=wcj&M~cgnpiL?^k2v3pZ@T(>Ob9Qn}*0E?jezC|Ay=-td{CtSFH^f&amW>2}{7#WLOv?X1d<|J8Ec5Az<^3 znz9RpUvK{7S}7}DdegywmdKVDS^XvVZX3iOQq!vAUE@U%8@(Ju^-k&j{k^Z}!9`G3 z|M7fr1Z4+^8NOkU0xH}b|GOOla9OTEwh_xd~XjNG~{cSI0Toj(s)V}z-&EuaS64$B>inse> zIW)o1njPew<+qCh=`d%F3PTcmtBUTq+4TNSEJI2FFAQ^`vx=gC*f(-rpSDwJZcdm3ft}}lcbZHco=M&I zA)q54WH@B!BdQU-TgXFiZF}!5cNg_FN*V-m&$9Vwju4Q*GAvN77Q=eaYk$7T_v~KF zpzqF#T{W^Dd9Bz!Lru&$f;9((n~=? zVLP-*aJ!_$`oo42FP+i8M-(&uiLd6@m~p;aIc3)ep9|Sngn(CRfS ziXWaWD$p{Qr#PgZWYkO0t5I_ki|6aw`QG--O2!TKxyrW4+Hqi9oyYGcS+#MnRrmcU zZ0Hf@bfud&;tLG1D7_7ej4&$#8a0JdVRT@&x4F%|ukMFwb9g_k^)Ta5l<4v&Lqyv; zL59G7o!?_s5HH#aBR5-Kp#r^sL7t7_ns2>|#iSHZG+5#MjLZdAAPOBq(+PRI6oHTJ zkBY!FWzWeI^I`twVN*>U+^?LaIW&Uu4EST5&dWT1m1)k3=b{ zt5Q|bJ1HzJxU-b@VL?6zZ$|*I!#8i1nAb#Qh$8>v1BbJH*Ay1AEq2l5^GptVpA|Zd zUN>)R3{br|RK|D`3a2;}=s(jteTz?=PKW?@R9QT+bygNvuW$_g4C>(ze_48{u*tWY z7k`iP#mzhq5F7}-TzNB}E-t$FCEkV(agH7t?*p$}n#s)WWn0e&I6F13zOeXQs=Of^ zvSdu{hen%DNuf_=xyYDx^ppGR5W?K+JlS;!2_A{Oyq>d<@hC(*tVx+(O26>&jhNln z2iM>0zce{e^Ft~q^kB2g9R;q!e(&Gi*E>{?dt(|ZXPiaLpH+Xlmv-yj!E5tOqq|-v zJMMqSNyvaSt++sUntOfJBW~gyjw_-dY-S8I9-H+j@gD|vS--5rcw~I^e%y|}mG#i- zU*pGnAJsuI=l(hq*XKKOB`SXgD%d7lS2xvfmIq8$eYjr?(tJq?`x_4x0}4dw33Dcx z0EZJDjkxvxvU63Ap^?J@w~7_^yZOJbI3IE=r!EJZWfa;53zPAF-&cO{uXh)WG~N3< zS~o_$VAK|DHnIKJy(C9hP1|bGS}o5-{1T$W?u^3bcGu!c42w3Y)w2H&yJ`j`5@HS^ z3;@IwdNk6jTq5GBBjI31ut>E?@JhGaY{Wqv= z#c0GSwosE^C{p#;vp7Vyx7`fR>UD64P7uqqZL3bC+~8E@`eu5gPHyjMZn=7%^=(T? zlAVsD%;-Zcf*nW~@bJV+(X0iybAC*c;c35~9@;dwcW{W{Y*Dq1a;_LNlFk*Vsmh5< zxo+RoXR4~)-_e+Rv1?JeP1?8b0(nWVAC&~fdnsHPd|PEMmGOB zUW@EuA@5IzRxw~S1;$?+!JAXb9zOi1>_*t}-AM6e;*=yR-KUJU-JyjHDM>=e4BzdJ z4M$}RFsdSFa*c(@ok-l_{eD9r_}f`9T(Q08)9f^ z{T-a6ZbeKb^zO|IWpPIe%FBFv`nS{;iR`O3tMe7eA%JY%lqnMBqvSG@G~+03bNX!j z(;F8*6)cL?ad*n0ET6r^z?&*8mxLB)rKpyv>F%;3>vv{iYI6K1k6uDLQy2`0MZXXL zMNK8nn3;OG|El?iW5dPpti~TU%?tnI*OTo^1}hR>iEJ5EyUJuRYY27Tk!tG{5~P_a zvzZm%b^fFFqqE9JtAY_im@qj;KcKYrZdAP2SGVIiu(dI^FZSh)?cj=QRdBIu4?;`G zwwkNY@}IpO3A0(UoVq{QOTsS*7>=Rox8v}d^Ij!?ZEVKn8@ANW&nz4I4M_>Zp= z)d{!LdV+P_$|Hv5lH9=ES+o#8JzG}`^X{XRemim@C~zx!a26_2!rFfE5QT{wif zx#Sg|DULhR?SJ{ZQbUM4Pa&@6i__b%`86Ld#(c^llv0SZeB$E}DMm2M-#`4=;QeGJ z9(aERv=2xb(lrmkI7oYV1{d4n?)HCG3iAj{VhWqW?2|4dS`AR-GATmaV@UoKSU+9lfhaB6nHn;h?)&7wo_joD>V^9v=vs;q%Rd3YB4yL67Lol-FB z0&d0R@&|2r`d;SS)G2<2et|~Au6-3=&?{;8seUZdnoC^$_23i3u?EH=z%v0IdT?h5 z#|2O4!#8}saY)?Keb%3QzsW>8C-^wsPxtH2i6s2KI~9v$81I)|0fiEy(0aOdzCbGF zoBX@QHQw}&lC4ZVCZ`D~h~FyUWT7*HBbdwgH=ord%zj(5I(cUe-h3~~ti|RKoyuFX zrZj-mEKM&Z`f14nVx;WXEP5jZ4InWxji|E5)B6mK4Bx?C9Gz24)XJ#W0`MCwxLT0) zt0NirOCo7FP}qm_3@1EJYx>(^D@T=GPnVuLelg?@pPW2Rg^RgeFQD1RgD9Qs)FM%* zNP8vlj0PNxg8$A3(vm?jOBVO9hLkW{^-mB9ujg#AuNOG`%$|4g*>jC2(YprzyQN9& zg>Op0Zi#u$iQsUH+O-mi`3j71dD^cz~tDuqL^A>ch0jOgE6)p zNuUVBt1QCS8$k&l1x>B#ayP@}& z&Y@crqEAZ&Rd#xf|b7INZGCge3j_M5GSC~R6Q=|)?s8BgKfsz26$IalFNsf7); z7RQkk&`H&5*akBqxhRD5-dC_UlWhS$gq2xmVCp8Y5pFJ9%F;^bgBA=v=O=)#Th#B} zD2I|D!i1Zs7H#B}kY~JS^Du|b=`$ncQl_Or$-TI(u9LF|^bSOkvk&Tg*A@ow1pl~Y zf<;j+w+S*U&@p3N*A;UFrm`pgw4mTNB z+MYzPA8%50NOI4?`q20yCD~$`!uXhg1)09wqAt+7MFLx%KbCNw5+Vj1daeCnt^r9O ze9r^d1W|s$XzRIrs^r>JlTYQgZw{_$(1TEQBvQh};Cyh@DnWTAZVr0WI%I0&A`aXj z7?fi0PN0T9b23=mAM%tv&w{i4*Z<>d|Ce{aem$qT6E~A}h$Z*tI^let;Ge{+9LvSE z#4e66C0lq)rh0M3qtZ$(uXJ>Do z4G`yiN%r1rU*C-d&#JFC=N7#0m1zARMQ7s3^#8|kefyRU(S_UpY z!bF_|L}HF4QvRL$eB}mSPpnoHdoC{dgSeuJXU+^IAInVm2effGVU2E&}s{uDTL6$CUu5#Up z=Q*ZVKQH#w(*EFk&QdrW+4%BG5J&P)k{s0~*k&I4;4+T}II@UGgV5@jatx>*Z*O(JgwN!MpI@KfZ>Kt~k|0>K&gpP&w$MNT zMAu-b-e&#`bfzS49XQ1kbkU@kvzNuARpO1Etw$ZNb?ZqS`{KB2(efze*^s@2?$Q!W zA>BT$2fT@3ORPPvtz*T=XR2b!Ua}QBX`0r*QKE!P4BbZUdo;J`{DBF7PsW%CJw&j8yxt+|4+xiLcl>G*A7fkHGZd+Z!rD}wIx3&y`;izke z9$_R)AXfxWj2Xg&-Jnrs!LK>TIsJhIRk~GFKBKC2`Z8_{?N5qHAWt+kM^4@}MwA*5 zrp`T=s80I@x$H50Y?!S8Y~Eca86<%s=fo7fWXa`YQKD(>c4yF&6{%NmrKFd7Z+Yx% zii>>Ax2NN%uzCvlfHfdKk$XQW_zR$vUfQI#Gpr|ZX}^f?kf#U=&)L`0e$j&>&1yAAxcwX7*=L3c10rGhtA7y1cuOZP@dg!CJFUE;<%4OaC&UGK z9gH>W&>l+wSq(IaCb=Kz)xf@l%^3fS$) z*<~ltyPM!=!&wehMj{&}s+&dgqt(dSupn90cnZsQ%pVn;NU*%yuTf!V@_d!k-VRxJ z*;n}%ceEX~fxO2k-`mPqHH{jjVr&$Cv%84?#G->^tzm9H^q8ia;z1B2(x`3{p9UF} zEutm`_1AdL^G!Cljb>}ncdJv=%!&7w+S*%v-)!jVKp*QE|~*Y0|>e zp(q=gIw*gO&2iFJLxyq%6uSPyKSc=u%8yN_GLJr#XqvTQ&R(bFF>rfb`41`DMhvaJ zF@!gMT7nf`S1e1Jb})8LJFj~I6(AMzhSP05IohWGp_Dy#=1ocvUS+AzHPL2%3w~y; zA#nGPiK(Zga((2+HXvluwWm<^{&JnbEXPzc*vge9xgr>`wW|FeZ?^Vk+$84hZr>78 zy$(x@qcjhF%~&r0PYx|__;ke-SfqtYybN#jH3*<>07OC{eHf1|&Ai{K4lI36?H^C@ zLqrpmm`eosVKm#(Etes_I&E_m>zS_mK)zHEE}^bfNVE5BJq|d=0uu zbtdG(J8;I*+F`N5db)skF74^(mmI@}gsL=m?agU>jLZbPI{-3;?d4o*b!naJ)pidI z!!;QOCSzPBntb}TF`))y)ubrZ{zCVk#q6#)?~fz{solMD`8|R2#4VlLuWco#^HM6ua9OCi`kL=|F6tlfOx6`uP_f ztk>bITdCs3(|k)8ba8qus8*m*+beuj(_6Hyf!z<&YBf>`r`wgt%O&91miIbw^Vjj# zz-awtaB&>&>tLGh`@?Sp)#u^;Iy^84AC$&7+spOz%v5ktDro6P3XEtvT4xRe+Eh;Md?|%+_nY$cT)-BPVd{$z(uX(xrzN zmcw_v1G7&88HAm41dYQaj)I2-Z@3WK3qP3ehQ(lUp2$ijOte)>+akw%>N>l9w84UN zQilc@ZDzqA5!S_qSljj}nGEu^U^QyoM^|piA8vQK8NujldV1Lhu38V8F8_*QQSd{fU!9+Mc{w4KYuWk(edl~woDufG?p z#6a$a(&0cV?BtpyJub7|^BZTkrhKFI*H%~9$ZRFDqg?wi)_>$MPY1{zB1n%V$+0{= zM~ywLFiD1vCpJ)5e7(6&CwKO3q$uYJZfZpb2<;;qDU(i(NFnr6g5juw>u@3gWEF25 zoO=09)Z{#?^^IggO5J?+A=(u)1Xm=lQ&dM-c?~+J*xN&j7iJ{b7n7TX15t}0+co#| zxCNB1HxmDH<(q7=3qRTupv!MsRZUaf%uAz7 zMLfbbw2Gm&SaXpgP)}1?i>_L%L9X;69a!1au>R%JGw1&+N?`-Pl zoV736pGXd*)R*AniI3!Y$;WjIBdnBFpo#I6S+8s^wufrj7(W07z^G?(}GA3Mvc2p5n>L9OX4(ilALC=c45W8{o=+b;ySc&hQD5s={B*f=w zmQcaE52$Jr~%hkauY4aTJqVZi& ztuZcIa=Lztx51YkaJW=&jb2x?)QI$Mp6 zTYh`vt$eo4_T$o0l~1GxN8f6-hVd7SS7%NKJ}13!vFg$g&JKGDfV0l-pDi+!ZDQolhv7E4oAIl$@M)U6L=3!(_t3!&XN|SI`Te3%YBuz0_X| z7FQyKetcAcxtu;c#OoWe*J7!{1L*p=lYqEc@zeTGiE0#pcQU@iJy_h) z3eDu{mpDZPUSrwAyGe!{>0mgJ@}nveA+#zh7h{#^9pBSOfqO$*wx>}K0wlMkYN49s zQW9L5I%TTfvBQsivXyE2No_L=%g@9@=efdUMQ%!`hljxgp8o+}0oq~|+ zG6Uy_cZyX@*I>f$U4tc{BM?&5U2g9DW47Z~wN%}ndiypt7tS6fz3LaMx>xm2PhVa- z3DvNzbd-x{I|G0EwxIiBWoc-1IZfq-(@}bHz>EdwBpz*yaJC?i|d3LDG~4D+T+g`QvE(cCS38QGbbGU61kIze=| zn*ZvvX%ui&S8)ss>^#%qa&E~T-%c$$n6yB)g#xLr6L_D_OPc<I;(HSt;iOPiKxW#!Wre*uk`Wp_BnM4%4rYcQ)NnI~z1wUu zq)kfN$uI}Q#_tozp}S!v)quvu^3B3dVS4r&0#EAJKOFR4#S`tE8n{ecn}nqFm_lh} z8)MP1d**hAkX-Anef^UC5xDI9n~vP1OB+|*&v61_v#|90Gd$wMWFvEOhH}XST&ZKq zH^lqZKX*yWFO)jE*_zwKH1|o%Mwfs@OCb>t$ji875_kOPk=V|?0Mb4n9NSb3Gt5mg z-25?RlU~On-rN1P*84a*O1{`u^(9fxZ4*)2fIE10-j?ZoNFFGTa3K-jm|{sh@{dui zKOr!jVA+HHf@(P_S(}jy@0o-r^(geYlL9CYQcDccZHftkJ3M(%yhm@S_TsOp#M0QM zbt~&0Ryfvw>aJ5UDd02>qZv1`q8j<%HO4g~%n{4TF0Nl|s~&HTqc4RbDrJjns69F9 zfi!KGwdCgndHPb~j9V4NaYJFYR(D&k(j@2j(p{m_RO7kAYUyI6ng=qO;y&OK<=Y1~(TGqoWW?fuVGnUgF--5enZ% z>VjkJ&Ysv%hz;4xT7t%(v}AW68a6v8o4Ml}wi(vXabML0=wy&`1KuTNpmyh&O;Gt4 zsE*q>CgBab%-w7?4lSLkH1~GeF<9in>zk!{KlO)V7ZBqsRzNyl%+M<$AKNx9?xLT2 zAynXElAdQ+R5k7gqE=b-t2n;4{E?0Q9f2A0kmmRj=2=op9;xuewnjIW*65;L93}Aa%?>Rc-jS_@CNX|( zS%N>^HJlNQHZXIzr?O_em^9rB_S(1|@G>@u^4N?s4jaY}U!gw4THKoo)jMxk{k-ms|(ddjAT-Q9jP z!M1O4+&R|K%8d!X#UyP0T!5F{B9-VDX9h|O2L5J!=JhsE?|pFF#nqC$wE;+@sO{fY zG7>L=CVyt`%Xgg%a361~fnebZY=V@?ZM7X;4gPM;G8TEUuaU z70|I?9J09En~WE>Eq_ zXddGY&@fYu`?Emh=RGKntRN?k7|(0nMpf~N3%e^|5#ZCLIak1JEk@dWf5hbCLUF2~ z{@&>zgd}#^h)>Ip8kY4Tc zG)}l)4Vw5cYWKshv*Qj;hN?bW0rV`B^Rro_5uOSdlEVXm?|@Y%7qBz6q_kfJs6^8^ zNHf@`*$>Qq`VQt4)@^<7QXh^J8V$HIHR5c@-4bOAsJ! z&5kYZ6JK9X7VE^m>|(?Jx93!Rs6tJa_RTk%v0Ul$2bM( z=N|;)^$w?ZlNT))?;Y&*-PrSKy;f|DQ>av>?7m^b>_ijL&$l>zKkLtfssMhPkL%>X za>OxH&An1`oK_Zi@hW(ya4b~Wi-jjZzaDAz{mUhiVaj+GQl-!`y2+!5)r(R)wi+Sw zRs@*7h2TyqUB#r=uf>3Xus_7;_>@oV&YE2T^@ztdLW7V373|DVxfyfd_>^fcqmHwvJie)wG$U-L;O%9fK<>7rO)8&<& zXQta&tmw)T*yQt_%iBW@CNq?iE8(*Amy;g27F*tICL9+;*>@Jbe);Iw*rna_;U9{& z?%kdeaa~)5gVRfo$Mok+mG4l5!$!yrX+K4`qr>W_?NO&I;E>5n<)_!f)+UMWn{N)> zfYyzNVdbg1oxCogHCW_=<2ueQIVMNSpR$g9SZXN%&a!z}0_82iC!Nq7%5k{k)PG)X zc3I!9>K@2;* zAwtV{9t^+sD!DqgaO^?2)p%F`R(!pGInEz-;ki*h30fOXuGot5MoU~e8vAYye5Hlh zl8|%2cfzdbo`tu`+Hay%dk6hHGT)@Ar#OC*1)n}Z_7b}Otbo+`fGYxg)`J^Pwh8n{7Wa6tm0sC7> zN>BAE_g6PyQ>qTMpb0GX)tnDJ9{3`~Qf!?*Ue!ta6m(Z+u>7N_8LsNLzX+=GS{~|v`q1H|$j|$iGH*fUb}XCBQW**rTQSJ4*CO^{n@D7A|0XQ}QQd^Ga@UB$zu%?2J$b7O}Z)P1fN z=|@>-k(IxFjo#nn92ygh`(()VB7U4BJ9y{9z&Tmv=(@#hM`k+6V@nX$ z3n0fvTD*Ypm3$%OM62|uOOjw%w?r3Fb<Gs?Obj ztmmGavVYY1iT~qeF24CE=9S9tL2jQmdC-_qgM>xcoTW~rN1~9>=d6ly*&1eF#_dyx@_RiVK;VY`n;);bpR9nkm-iLt;J~ zOY#>@EECT%u(61SFeQp6l@2U%MafRo(^Y|^%WG8I^S0~~RGKH0h3EUWU@ZcpuQk>L z?scmY^ELxXTlNMrX?@3iAGC)6+uzgprn8tvap~Vn&nc%W?9Twg)FWQ51cyg|4)Q+F zgV{Kw-@TJRK%nz48 z@;#J$n6^>7EuU)Z0=D2`Uj30-ts_axt&_G@T{inBwb%D9JMk~i%`KX=N)ow0&;Kw} zdjj^;{)GF~K@45YpX}&8Dbea+p+>Ev;ih|q>fLiX)Wo`~paJ5wZ6=_1d*cjasZb|+ zb{w8nqPh=d{_6Ljx#;^0wpagrj`w^7_F0j~BPRlx*k{%kG&Y)5bjTi&&4jB%^^m;$ zygUb6%J`Jy_ta^}tJpbZ*)cM2`%-BDNHjodWNsvV8&LQ0?G=pbID_Am%-PF!O>b=( z_g8Wb0%jEuN_Rm+Ko)*3h1W`B@w$1Ba#m1ZHW3MrlD` zd-(Kq3Y2Np;w;~~CMSTdxyEoZ+IT0q*q+dGoX5x}x9mbAeS zdMgi$DLpPxPAAY;yQ>l&%ld8F8grj0bNT&c&gI6dK%4}de{Bx?OD9H{FOs9ic+?~& z=#Z^-kdjpwK^^IAzHDw~I82*Qx))1F0n%rlwNZzg04^aO;>r$zfOlwTP9K~*Z6FoH_jmG@$q!wN!F-~lI@W7>PV_k{?% z22xk=PV{7^6R5%1y5ClrPMt};fF*m;G(jF7Hp0RvlS+Y^I8EsoG#6)tCgwlTCuy^NpIo$%Jk){>C*=yJZze(CknERG4pqRGrl~Yp{Hd)%I zFjCP~zTeebtx2PQ1lR_{dBrXoi$jI&zP!$1ou#>Q_PLUC;;XgDI zG7=asG@%}T+ItpHwuheqq}+$E@;kR^pheiC-c{4UFGaxH{xSQ(sH0wDoU zp!f4Sz0;IYog`C%0(sjj93dB(EzsbB3pt9qnX zgh(e>Go_x7SVI^8a%ruel;Y{>BJTIPx@zlWqVU*7W>J-X$<>80N+vxQoFQu@;-5*_ zzH{W8Qg1CZH?C{L9ADHe6ad>8sK(NvG7D>s;dtRZQ2uMf{ogct`}&Iql7Hk%o0r^C469dLT{9II^_{Yx$#dc^ z`^=*>IbwQ&lCs;vCj0E#UKnsN`=ccImxg!jl`L7u0cm+K5B!YK_M^8sk^ef@afL0F z4-*+yAy3}X4tK;9+eVvOU%G64dm8iAS6{AE=Yf({)q+prFKX=Q+MjS&)YSB7meAsBYE`NNAdztn4_Mh32>!{DDpW1o( zoL(f&(ljbuWKp3TV%8b>1E20N{9qp2>s^_<`i@+$8MWmR1rvf zhRt05k_5`>DmuovVk#Osrog%ZToPyfbw21^P(XOj6VG{0tI&Cq<-*>S?;gGFQ}*kE z>{Gr^8~BKks4K-rP8V?L56r8`Lb?y0nPPbZjH97f^Of5hwdIr?1l zlj&07VAGV~a^Bp!{DlPbdk^kIc1wrc_l=J-eQ!SoUY9FZiQ<5Qwg3M)0EZUyY9H_D z@apDM{$xZfq={U^-H`dxes|VTQbv0OK-T5QOw19X^E7HPwJEH1YJyo;jH^jI_EoWy$I+56FXW=% zJ!;ALK~WGY!PwTDg<_)Kr%@`DT4ATx1kc*PszJiA0a3|R-Tn7pk3WvL7J1?+`SkEh z_;vk((rIy$h=vk7>}tN2-|u(SWN=aV^>mDh#~3XP8?>v3>x{t zswLHh1xeWM->}NG4rGc4fCVZjd{qg+8Sh~m9F}N{tx?XfZQOW?j)$3uzg)hOH<34; zHp`mybsXBcfhnxOvfgimO)^zq&N#Strv9GWT-~UPX1Jq;&>c6K14+TXy+PBs+e9A3!=a7v?wo18!z{NK zH9!Uhza0wr1Ll9B96UirgHWW)UoM7BICd_lP!Bf87X|;cGFrIm5E^PdU3p9@z(piM zX0#4989KidNrye9wZExX%J0o%s5QYwzGsKU`FOY9G?ln65wxX}+R3lOzIb$=?;Szj zUHjFnbD^Q%`%E!QqlCMYYrmJ=l8Vb+#x8=I6mo+Dq|im%BUz|qXz{Y=A&}8T z(;iX!>Xa_7KY=~`hIjA&IPzTf$Keued(CX>hWlrT>ol+ocXf!=q&s}b6wRm_(s2V( zPunuyzzTz!COLn(9$*~L7guN7#n!%5^BE4<>eF8z8$e>XCkc`s*+=Mn?+}Fu6%X2q zu-;o>))(95L*)D$)Tz_lA2O$@R1zctR0@YmO~SqNLC|eIqS`roP@6>HZ0x5Wj1L=p zTs5IDt2sBqhr}<^8UUF)TVbYsMDcd{iGISoS$(V$>Dmk}OP^17XsKN09QO^e;Z2CC zGlr2)W6dJlJt0aKRrXG88IR2-v>R&W+EsWypCW(Q6H?b|MVPXzgRbs3qN-6*Il~w} zs&OXsNuG~4>EJQ^->HSJp>XfD>{gi2RNP85b1-Z_=( zE;)>JyBm<@*Gw;am%o}3QU6K+T-oNj^?d%t%OJpkq$T%z*YpHqvK4DQyLnNrqkZ!R zX=}b5Xdi_4fos|!(T#7N<>zYVurx<|(p!C_jZ5g)S|Y=G+?Y1k#WD@bjR;3Tt)8+a z(7{1CR70T7%UQ}<&X3mxANFocNTeM^B*gAujHGFlkLRQyg%me={Oi8ET0VVRa!=YH z(D(N|D8@6yvqn6bh$8bbU-sdxw?+p}2_A>HO^=RGjJNZ6RN$7OhJ*b!z8yU=kLz5EM!teCa#mw)cW*pLU!uhZt<_8A*j57}v1%h27Lm_5A{~@bnhXCoj(TruiTF+Z zZ(J}bckgQL+yX|AXC@|^XYE}l`9H9%UU&O<;LW|%Mc=9Ex52G8R zwNd((cC!_cbEpd*RzA$9d2?T8HJ9TYdplY$+R62K*wWs>W<#0l*Zkfh@ z1;~`pC308st3CKf#g$z}$^E+EJVEfW9d#*elEx*;q`T>AQr9!FVl7{J>ozUDI07qc zV$DdmaiiO@6qP2Cp35&Tw8K2M53AP0VC?^T8cH$Hvi>bWGX)EHW-Bwk3?N&Uw8VR*JU^g9KpmZL@wKcLU}SQ{M-@*Z7{~D30$G!{7l$HO51XTlA9sq$!$?-{5x)XM?ug@|DO2Y5% zf-&3Cr|;aRk93wgRFEQ(!2LOhc>U! zVIOx&U}rb5o=3#To#WLcU&v_kIQztIlotYEOmRTbbv?Z2-e}BsTg(!=*!Z8T(34C0 zmB*o`Pq-cA(1&pdZa9sy=T1wFE1X0Va`IQYFBVU@PHi?s$q+T?6Q0PGW$9g#gZX7w z+vWKqSai=l3!wjU-W-=`#RVpxX_<`M%dlEqi&BJLgFg&$I(6}8I~Q-rF3>B@r0t(2 zhqvG35s0el&YoR%cD8ysh^P|_-=&Jz??aQ5Db_@E6#zdkvSDltS=w)a;B;O;s}!_{Tj2W{e+}jKUS^fI~QPxb^`o>_1?c)V!k@LYTYtWwiUjMPa%33 zYfJ$D3W+n{q7+lg>m#EOz0G{y&!|T^>G6Kx@1=OBI7z)Yh4K5vMCHNv+%-&2qj4kQRlMb5B?$E2U6k-=a^tm zzD!tWzf|;Mxzu_h=Jx0!C?HiLZE=bsTSg_pB|>7lom~?-EJO)@ajl*I(OlmwrYP4& z3{6_HB-cIjzl7GXGg9SUeCEjHL%$$btHv)>bSaR0*~FF-_FYknA1<{JqDc=?b$#0; zW5lV}67rV|9!Ms+D{SpCO@41O;Yze+t#*X@Ph;N`-RMy&KFuA7!C4I|-cPN(GaQS? zgzvLzFO~SJR8yok6~bZlI(#8UQr50|aVbF@1$4yPr?6FT$HiqMe*_+30fliWym{JB67zPPJmDhw|z@J>zPmnCq2;?oRpj!>=6Pl`-(?rF#1Dw3yC<+Ek@Gy7JLQi@K8Mww=XVc;+`20{C}q9?u%^ zsdsK5vVET9J^t^8p1u8&E7*@U7HVEpX7nPy$Y-MXWzNedxiAJa~it;Bv7;U<@svTT56Sj_x{FJ zm9n1lv~0o4fGCL3-jWfHq2uSTRTCWn|B*XlBxUw`$)zh-uY7j9?0bamxxOZL+dc5c ztE$@roftJh33GzG&(y)k;feR$kAE|uljFOU+EDkJQrvk`%jjNlC8BKHO22EPT`Ixj zWlqwTx{VP0aKvTz!14oD+ZE&|cN4sCw2&QEl$I=ibE~JMTai-V{_W0er$=aEs!)uy z_O=R?nFjw^ygv{Vm2n@xhoxb=TEh|=?)7uD%=XnN3bkbvJmqSV{?=^&wA(LOns0?> zMk4cbJ`PAf8dhutq`LtGsL{^c4=kpZ5HDzgho=T0>nCRX_llrc15Y1Ca@ob25m?&N zjCYuTd4Q9AKDd^y-xJ%ZfG5_ugn}IJ-OJ>T?dm}MLs!cTj?a|V1V?50C z;<&3wWn4q%qU(Y0D@$0WPKfD7*-|%Bmh1brfTg8r`sd0G`_k6hc2UXy9nyLS-a21eyP4!T&czxwfktAPh zf zV&>vhX1Jvlc_@2VVUf6bR+@~)fEa4LxfYH#YPX|fN#SPO$L#=-+S`cmZ`9wf;zm`O z;aeY=zOi`;Q2eJ_+ncA*X4Ut^V&*)^wT%WpqHbqe=(|BBJ0Q-=b{(_)AiyuMu-10N8AEdWGGM*L#3D$6 z@!oo-i&R&C2~{%567T=#Rnj74R!^yF=?L*1G+1)wzTesLD!XEK-=9*!s^SH=HS^mF zQW{vNZsbhU;iePS6oY%flc`#%)Q#^ZcZ;X<+viRd12QT|_ZDDY0{sJbF76fWZ%FfS z+cd!7oP;iZRW3Z-=*|>EEP$Nh6`SkX_ zs#z}H$M5Q5&tUDxt?oA+Vro91J){sqFPP?_bfO?~vVVP#PGYX3MW~_`5>2}Bev@8% zw?;5vVtST5%gOT$8r{QvKznM6)K^?3Rkys?NKO?AiTA0ia3FoY;kOOf41Q=i6?`Gk z9zAf0__HCZHnT-pq59Ekg*KxyMtqCn@2`I3iPqiSGNeIOnA%>AyNJK9Vo|^r(~;kz z+y7x{7ToP?{0-ExfbxroWAxM_5C6>W63cDC1uxPQd4q7>#r{_ozJ{O?&xi2;%XK_l z*uz1YQ6UpmetUQ5r47H;^@&;7EiR?YR(){s`rYrou}-pSgKcLE)O{cJ-rfk)3+dep z4Y+|xw342j_MoX>-tF@+k$bGZ>at3xw{l$cSytr_=2#en??NS|`sE{f|)`B(-J5W+11WY(?2 z=_CJIC^#y}B(YMI1(%wYM3dJ>^TAWaA6zEUm=xsZkFf^50O*#o7X-ae#8K4lc4aP){uw#E|i_6{+UAkBCK3|3FjiR>!}lPiAm zrDNv5NP~u`)JtBfi;y2j8^Y74l4#AnE=>oTmS1-b2yM<78SwZmS7H6Xv7^d>aFx z!ZuPtwGU4SY5QL1sZYknV-92hV*UzJNLy?=$Ol8Ly4}T3Xbli1>kf=V)OXB-R@!{P zg22^bj&wuvdzvu}S~wzu<*?my9(x0UZjrNdS(4lpc>YNr;KG=wN|OzX*(>s|WOq8~yE&StsK)jqaI+Dl?u0AL?Z_m>l7RWo~Rv>_aC*^XX(EQIUbp(o0| zZ(Z!w09rWN+K4*E9!}m%8kXPfj*@s@9|x8Pyl=?QJEFkNTxwoU)hn^DRz^a|8fra7 z3ZuKR9E88c8W;{N)|cOJDE%NJ&-|gh(w}UF4C>tEUFYt45;}4MNRC7uTRVRfN2`gH za(pOvC)Q*A2)X+*_vNiKIrbPD!XOI>IW?+KQKx@DyqGMz(cT>dN*;S_ z)L0S%Ymd6KmW$<#;`Hm0SFAvhmMqqJ>AXLE zl3Ubmur47MeAFKXM2n9EoEDQXuBxwjlM5y?!viq@}fHd*?!iab0t!&$K1z zn0bn(c4dtHy&ntX3!X*77E3k#o1E>y<6Ir;nnPGU5d%4$zFSO$u>qR8@3czO3x6LBkkOzMEwSdCh?z`677mp>-(@tPjh?FtkPS^ z;)gkrLjQ3`tL@xpX3c7*pWkwO82U1Lhi>=4D#X$hBo3qfP!P zm$h@>dwXLbbE9iP?ux;ln8AKY2fXvNN?W&R%s%qnn_uE7{qG98P1A-+VrEY~%+{l) zuVO(|h2h}B-$f~ieDdP@rK1&Vf4N4>9LDDIi%v|$wA&M>)9#9+<{gq}G>}wN@mH$@ zJzdEWQ(Zzoqwo^fH$2xj&#>i&U|x_UiT#PzFt>2x`4z>QXxZijvib8Pql$_76 z1)i~<;wWgs7$y4BHBVsiAi>~XI&5z_bVPKdQp}T#KX5KBT3J$G{|Zm(KtSn)Jmjn( z>sd$&q5U*rPUxI7lQ-0f$k70o*hV&GDMGb(LLZhsE|OIo7)t5W5oWq^P9@Hy0Q>+q zmZRI5de3DhY*Dp0@7)al24D9O4NcpLye4_VU!XxL5 zBohxK*eZ~m)oCeu>(qdD!tC={tHSOjrOCV}C+=!q*U7a0f`BsK_{}E>*gKG+?qvnr z_F05itg~Ew+$#?KvkIR2G}!v>jB5l;0ofxN+#e7MS%M@@9lv&g%MX7#zILi^k6B_y z2zxZU;pEC%1i{%=)o4o0ec7=O8I{AY zvBG4Ro{kl{wn}X!n16lq6<(S`;$68qDKuOq3mBq;E-#NZWC9r+#AZrNHuq@#xw$M0 z6I%JlG8s^>5(q%wZ{iz25-lCHQFkEfWDhq}zX`T|uDdF+qJEHl3x^v)h+N}PEvROA z2VMD(>X&KUQ;nj5yXd%wV~q}CjH5FRf^&8LVSjw-}L4^DU`_D59!Jxc7Fyc%R{br~G;1o7hSD8|Xa+dW z#(5f4MR%K35@T^iW>{HkjW??&bz1xHEIv`PsFXPey!AzCWp&>f&BjDrB1}`K$hP!A zZ2feNPSvMNSK8G{joh@k`X772w2i!?ApFzXimHsYb#F-8`d_Z_n}4|iIH-b#kWFeP z{hc8l`=MTKHcNJE-h9YkOl|$A{fQ=3>jkIIKi;{{$Pf&1CgI?}M7BTu-;=zofS*w^ ze^@`4g}4i~DyFd|0g)Bt)Oqcq_zzb*x2mmiw6vH!EXijUdBGT3DCQETZO!v79)7G% zW%FRDlznRs4GpW|2-1&@wBk}NK{i4u4;L2BCAL4=J#h4ysgD$&$w-)C2_?YDmDWP3L5#mPxvhv=|G+q=&Fy{Az;L6bh!LGTvujcdOI ze7_fJuXC~E90oYN?8k(vPqqxTHn2ZV(^ji(so%V;q<_+F== z7&o`f@dntQ3vIO%7JMnr35$IZRijn^LU<7!`&m%gcq!0~{?Z~4V2%Q#M~Q?uTI8HF z#9eCo41G9BdeItXoD~zo?%`fDn??vSQlxlvW{=a;#wXr(ZRYk31V`pSInh4Pu-@1m zi||rRN043#Wislk$;`Pg(-IYNh$_ehz~N9fu(MQO=XM_HB8H@&FMwQ^LI8u#e~TE_ zbHoTFmjkIabM#Z>WNyt8TQJ=!qvpgB81SJJwDPDO{Vlf1j0i}}b{Z5!UV4?h`S119|6D4XXJPgz?2DkiAUYq_h9trUO^Xbmj?_$CU>7{)A>70wy@y>W`2^jG<^ zL?L$Fn*>kk5US)(IgC60{q@4CmX;Tb=6U@+eB(0nmi?{$q(w}F`Fvl}+LLrQ)|0(g z`|FQV+U-|TfLgb-XtMnxQJw+@=d>Ae?|s5?K(6= z@Wt@nzg(FArseP>{#v?vE=j6YF4;!fZXL}xCx69%Lyh8Lq)pCA>p9bpC;>n{6-D7e z=)z`+=Rqy!XS1@L$jNEP;QSqk7dIpneO4wcgdX`WG}QNbJiqq|Zh%ELJ|sfku_PEW z1|yK2-BFB!xo?b1-9YYB-WC2xA-kf+RW+ZfP#NIZ%^N2~fw_0GLO6HP<(OBgE8py> z@9%aT)!dQw1mqD-M4Blw4$xb2xAgP%(owC(#jip{^XIPbEKOIbb)0f8KGFQ|!c5|} zPv@Njm02QB^Q@ToWZ$Tc^z@~XbApS{e_i6Tj*Nbm`kBn`w~fsotM@dJ)bGL9l<#Nc zq{P76_pQ>s(W)b4Hi$UQ_6RiJMxazj$}afcP|OgrGzCxyh~X6}@fU!525;70=REa) z{HuCFnG>0<(^7r@t)|*(U^|O!ig=OpnnkMEI=r3$&%*!Z63fXN)tCGcHo{r?mP2|3 z6kQGON&4`cI%Hsgo1y=y6c)kEs@W*S2FLc|m*y0%(I zIB4WsF$1yWB5A$KQyr90*mSNJM4co3mn+!4lmv<+6_RRe!o3i~q?2b}86)`t348lA zX`cX2{g}4oRYRssbA+W>_;6Pe8*KYul;l-*Bf*}cM2Gy3qjPa&djJ1;=c~KQ>4GGj zqLgbP&yt~)Fnn) z-Xd9Eyw5#BbZinG*Ci*PU(q~&sG2kk}Td&Zn zjukZirfUHatpt2X^rvEBYW*8o@*N%owK4b!Yk)fx{Y}E;-3&GoqqD?z;OF@)EmC>l zv@akF#t0jKKiL^>-cHxOw&&U>9pG=~jaJ_-hGW{AE_YdD;fn&g=J|yW9u>qJ2P<&^ zW@ePX>j2!(`Vx*RN?PCO>JNy`CL$(5bB_&hSvBi{X%W50ezUR#O9TKfNx~ZE#ciMB z2uj9gxtO`fCFPz)x2_Veyus~t_K*}7K`T+uq}k{jexl-@ins42CgmP4R=Nrx8=@Wh z{-DP52|x7c8mxY(VCAI)0FDKhE9tHr?YMpgsBaN8=G}XrMFFO;ilu#ulbSfTHV++O zi_2pJ8h;?I;!@60@JyrH9D&TQ7_e$T`-oYw>WDrWj3)^YN_m#*t+7DCmehO7|7r!UFnr*O|CSm06VUks z{Bb|33;!4Mctd^u)vH<)-483d9M_(6Em@uB#shR^=3f0{!4oM5h%4$pjYnsA^Y=3p zx^*ISy90=Y`9-EU!4&%x?Noj0$UBQ_RrS`oO|GG7Dn5j3elRTD$v@~xc>K#rZ^hOT zOE>Nn{)_Uix0@@ECq9R6oL}Vz?Bsl^Wt$wG_x6QVp-1r@o+-$sjbS6ZnZo%eRq0Z{ z?IdTOMr;;YQu-dA&gg@}n*@L@@t|~)rug-fx@~A05bzJ?|Z3fLabugyKI^qt$n55)HY)u=_03H~D6T&P(@j z)}hfUJxsvpm)QFXQk~RWbK2cU^)I%xts@d)-{k`hW=1A=*RGfNn;$emRy6!Mr+v~^ z61zLmke1DXhi;#)rP_?{pP?$NfVsiNMPSeiwVJuVA`hsH%g>?HxWAU71Eb4}ZE-Zy z;r`zHp&539`*v$_Ukl?KVhn&i`}sd*Uu^d}!xB=DQM-9xl~d7~4;SXl6T`SJ-s>Z+ zXA`wZ(7N`7PiG5T4jT3aJ%_frm3HEl9B%8*kY_d2q)|8JORK&7F^7W8`uj=2Y9%1^ z*G^~OFDL|L`HW4<5f3n8fK$-k(skPBxx#p(S6oJRca1rPV=;wp95uTF_dajqUVR0I zE|A8iI5PqYq%qsk1hQb#;`-iX4$Da}>HkhI5MW!$a>`%3k8stk%kTGe>U^w0`|tyQ zDp4|QT1h6b$9fNlPs>l<6+G5%jBAYjzQch&3UIVMYek4=Xb{EMh65F48aA{(O&#?; zd5?njfmO!;3SRZtIbu@;aDqU}`nI2u=4*jKT6;$h_ z*#@CSrt-d7pr1qmbmdy;2czsRW8?Dn8HdXT7fG{4QQ}km;7)!UVfoq)>Wv$#njUo*0+p&S7DX2q?xDw_+^v&2XlG z5G^3Y%V3YH5Svivg#_9!HAFtB12zb3H2zoPSe3fA8myy>gL^A2nPp0EjWSfC3CJom zdjk}o$5R`k>&DWv@wa|fBGREbqr}Z`vNEO|s~$O|HW9c+4faE&!4e`8C6mW=fOMX_ z&DU>;8Ro#LcgN+l^qHF!rRd%7A!q9LlFy!b`zB``*-OQ;LmlbpU8@N+Q#y5!fJ)hS z2X+V>pHQi*i4h&V%+CK@9P?*~_P^TTtk*Q;2mL2{l z0}ZI;(@O~}a`*nOfb3Y>IW9Z!g3g23i-D?>4EM!+{pIXEUtTG&`cD8>8en4isf+u?Jy`h?<#UwRw$Wq!N^M1Eb3lJ)FYG0vji9a-an@nQ;WQ+wlz2w8C|3G+ zkH_7SZ~be@94%MO%pc*xm7^oyD$KssmDyHq3OH=bD2G1e7yQ=`CV>L3rsnA#?)i zoQPD;G<&716#t<;%{$AqUagrrXjHeF23)vxqldbBX;pvcAo;g|{QIW48ou08&)~2! zA2dxE!na9)P5R#S1E6UPyXu%xZP@*Wx_EZYsZ5_H|go zmM^-Z9%B`siEk#C%w@_Mz+l5z#_S#*uQb>tXx7 zhbwjUq9YdIBz0D({eWCfCK^_r4Hj?w*IRFo2ye3>#*7fU*!EU5_p}NY<(#I7+Vk{) zTaNSz_1+^g*X1%*Lh}haU+hz6x0w%m37(?P1|1wGntiM^;fpf#I@Y>Lxs!#+E>%6v zw8Ppzt$HF_&_^TiM9g+e`K8*x!!rYn(!4f1wlJB4&eYugndf+wolFU-7d$m`WF*%V zSrK8do(|~znxR>yvxBDOA5Q$7w#~fe)Q!rPz;9W*s{^?v+Uv}kf|4yLj0J2lNIeS?ZmdF<;7CRYC?UdXU^z zn=+l)qGl1Dhkj`G9@x=>{br4IbfxAgo3$VGNFakT%n2+_tb`ePe(i}B&$X8*5A&A| z+zQ`jy8`itz}F@%Ij&T@Vce6=;8bERL4}g$mD9l+tfHgdADbZBfKuj4FXIqHm3_l0 z2lgkf7&1c)9tUdg66Vd2dTN-)5>{#O+_@P|HPtK}?M|sBM2$Ct`Jd+=BmXU+- z;nrIX(bcgVwY5cx6VL})Q_^qa0k!%(u<~MB&HC_0rdg{Ei>Vl1hXs6kYgj&aE+;{> z23y9a91zDjLA5gGVfWT`MC)b=J@0w%^>Xk@L3eD~tQM03ksCPu(ReRbIo|bg z#*vZf8IG0+zp6Qx37g^7^g-EhLEq`G)u4Cn5$4f_IoSx!t%~U4Hms8c*b2DR6!$QR zsp`wplIg!9#(|7Ip?$`O-@LVOdikE;?cj3trfhZ$A=NF5M1=`^W^3^`n;G)4J0=qi zw_2Ux576vE9Hao9dBLxr;b+o(0TS{U6)XC*d1F+M0&yWWEE_9aR~FXI&|8 z&BW?2@|_g-7?$?QWzm9co4#W&&9y)gcB?n?TC&qb#rqsREeI$Us}KKRqOoOL{ggF~ zbSF73W)lUwgxdNYNZSV4~Rc@h$F^wpZwQ%+)U>Z5gg_c8LCPRWVXlCAsVUNpQRQ+`F)Fmjw-R*B0<0*aTbe@6Ip!JND$SWHUBK&iFzExlqk<^;=wI4Y55X&j|*Q#zeUbYTIT z3*u(YJkIXVujOZ~+z>SVp5*(~K~OfLg;z@TxpPmS&UKdROx-AB7H={DnoSIWx;n6G z%~j2;?nyyh^~6%}T!5G~GdBnphK4v`)#%08Gw7gp?!RCgyIa;oV9}O$CvMIV#eg|>Zo0T;;_#Lt}8^1gBOT2 z>71!}k808Pfv-iGK$s5f^Pozuxjy^)?t|Yh{F8po!h%MKL>++Ul?&U(wDu+qaNrIU zP{Q_)r~boPpjm=GbBGcfvAXp+EmvXe1?RYVJQ|%Ziu$(qs632(xZxt^75vA6vW4mk z-Fc5vbcP0}p=|APv&L0D*%O9onT{+GGYLQN6=3gS)sLyzwU;8+MeLi#^Nqi5fzOK; zCj{qh*=IxmvgG;h?%~?VA~GfrXpBk3Y`x$&R|W}+{mgQz1C1R^doy~@CXK0X#1P~D zshCpBwQV;(iRMx^v4bsV*Zqz^G}Qzu2V7B|bX3U8*#qNvU}O5VsP|iULWeJ%OyQf_ zT{DRm_QG(;n5y<#&4JIG^guX2$63TGRdOG{cess_fE^sFspw+}dZIQ8t9`A1P)t4V zL_=P1^!2y=V_)t+_$#t{dRh;b0wTnt*%As;Q7Na95VpK44<=svGsEJaM}P%YO4iPA zC}Bzx5&vKl4tk)Q5?PZ)yOW~#!s1J*d`vTihfmh=)`cO#-k=#iXCn5p*|&PDbU3xi zCiX|vy1Me8T4o>)8YE`1vyl-?rzXA9^)sTdL&r0-*}t(&1(UIXPS|nS7(fT!6y|tL zb4w|F&8I_9UdWtth*&iZB%@gTQ}k0^67KACsMQQ^RB+U#4l7W=sbGMm5MJ+>G8K~q zg!gbLgHayA%`0xer*8ruXbHQxefGqvkgV=lrnirMnJ@Dg1dl(yvF!)N9 zktfYOh7X)SopsUvd`$Q8H~0|U0E^#k{6@ovx;VkMuTX>xz{W(Dy`D2#RAYQ)d|2I0+x&J?=bMrxCSr~*T?$@Z+3QsQr5yLkkzGwHX2{J@^!s{}}HepT##$1Ks^>;{L{BE4aRUoa_cUjmwZ~lX4rje@u?zvf8rRgK^#!2va zO4)DW5z^TU+DFJc%_H)Gl@OG`_<%*hm9;AT;rGFD{nwlV4DbHRQLofp2h+ggl#vwU zzqxf`Uf2xYV{v7YZ|Yra@PeEcjOTvKBxq2-!ScKiFSWiPS4$35dS(R5vs3}Ay*~W+ z@iTf6la`M@c{yU{3c><4J3z_R6`ZC=sq!{w3l8>5#W>fV9Z;<>6ju~r%}-Vf?{`|H zQ-=K&&|Y^;fBPAnZgF{tC3t74);At{QxF@W5^@#Vd{kh%6X4%I(3rQsb#^GF`J=3> z(q9&aKg0VO`N8W-UA#A+@uZBB;XuS@ZC>d=lwj8HCr4vQg=C`lag*~aqupcJs}x*b z;LqkwUZtqumZJQ#P^^3?-Ega1!>cU^OX-RcyS+Z)@*yp+{yh{Y{7m)gwe=O|rZ1xk6ZJzjA zlO%KnJes1O+MJ(Iy|g)RIzn~OXsP6>r8wTUDQktaoGWk4tdFT|CV3>tr+sx#qZ`(e z6H}iX$=h-h^CS=D8qiPTD`vjLY`8dx zzNNspe$6_h`?%0#>K88_Ei>(>dwHBWU)Msm&z<504UV?_Wn2@L(12Law*9`Xg0E}% zQb$+{D-TFBmc4FLrVu@48Wj58-QK=vkQJ_j`83^o3%!w1Aruz8SDci3M_R9Ob*VwK ziA+0xxgvhYZY(={{j}NJ0wn$2#VxR!z!_y%9qH@jG2=X9licCkUx$U3w(x3^qWquG zHMx(+Y8N}$cwW7cbA0UEzVizRahz}!SP;I($1lE8De%=;6Cj!J&K5w3>NGtfwIOw% zEFUbWz*opAyYTcOivi(X(x9%Gyykl5M<@+|QsYD`{I1#aLF$*q9ES#t)Gsl(fa_Ro zfC)yx-?swgA?f*bH}+<&szj(&%+@THk*+y`)OqMtN6OVKRYq|r>>pU;zQHm7^!|0#nO)RqMMaVFU69E zShj6LWcvX$@LT6oEK>cbys{^o`hb<$oO;Ug3|27Ab9=24(QE$t|NE@pqxN7Q>!osF z6kdQ6QTH+#2Vuj@o;(0#cquOCuq4j65Q1s z7`W`AkLD;4zCosa;z*luseR&owksEkJckbB{tS?3Jd_W&#G#R+(S+ACc>&cn!s~}=TQ)5glsd}G$p>2l=cJTq{0`ot z-2=I|q7{{g6lA3nKh^fzFr^Tf{ztvF(BJs(N8S8cyFTve17PVZZyvT^o^n3ZP?ys& zNC-!P{@r8DKxAewnj=4_#l;i{!lBuM$&*j?N7#9%e)~O}G2jC#?c-Q?!GQtIZ>3s2 ztGLBew3s!iY!vN-1Q7&>gaGq0z{wf6NT#zUpnog^mF^1@+iy-!>;q`~b{}-CC`dY& zFjHZ65tK4aXZ0r_C(ABA0*b#@NWkH+4wKCQ86$V+n@Za*hVX)7%ByYk3jS!9J<4#` zC`GdK{4bW(9q(f(2~j(NWg7?LwqZ6d?U@?z6Ba(+G@SEzoQwUAg;?(Df6@Cq2H26p zpZacJeavIDuv#vZ+;dqI{k_TH-#rDb6-=r0X^)}FZ^J)C)~@<4?wakdTXWEeE`?Al zf)u++(zQl&4W37|9d5lFwop`^8G%xrCWfWJyfQ+s0CuJ>9Lx?Omwrd_9d#RU2z60y z9>gb5?xwaidafU<{M=8AZLAWi)z|zSU{sPVi}&4+O+h%gEVOLS@jcM^qozK;Q<&zu zFaf;_VuXFR?XT&cC>fsysH*r1JfSNV@}MaRvdlZ7Po?WH157Je+P+%7w=YrBFt1QF z!DO*w2Iu@fIsh{T;SD;CiY-3O*qlx1xw6XVI8(mvHfL2$fel`Zra)AA40NQFqMmG@ z?RkvbZKV$v5IWT$vHSY1mHF7qFaq^j6y3Tb2X!I;s|A4SqE_ZA=7sD3dQz7;^R9zg z8Wu7C%Jo1)(9foWws|nXq};cJu(v+iMOm*Rp!fpkKdbz(QB7l%rhL*iAK7S*>IfAD z95Oqz@_Q$x8lFRuN7gJd%E7PSml2Eps^1@UqJ{}BQqs|<*45GwtIirRl9*t|-DaJ( z(qSIvFuG{YX1OFqJutcybE#ugJD{%-WqQag^Wm7(EpuP9zM~tE`QF6!+AiLiW^A~0 za&;Svst%(r?__)nzs7lsS$9f3YO5^oA<=y_U~>)9hdrbiI+c+Wh2qwl07+r|sv8Mk z6QSB!cde(XdU4s6H)pbT%(8aS4lOdC!bNbnb|=xp+$e==e47U8E-ADTvpJdZ+s5c0 zGRh_xBX(kvL(pO-E1dR+sKUhfbBtX3#>YnNE<7uNcL-kO;q_$y=)31>K*guFG=dv0 z`p^g^8+W0|1$oV6`Tg=^m`sxXoDEm*(LYgBeddZC$08~LAlED5pG5&~l@B3QU3Zw( z-KPrsdHsD4pD8xo5+B0Nua3r>seFf(wq=Hy%R>I{0TjvM9?Jr#5~x!>L__gs<1hBksvCChee?_44^ zmG2b6$TVqCy-j(0zpyDaz})0$@s6Dx>F@D-!zBf!vzSA`N7+dVA0`KFRp#^TS)%dg zzBiojc7_tQOJn%MLnc{kLxrl6JI+h0ahOGAGC2PSNjz59^w=2VdnF>|d3UR1{Aqqm z5BiP2*t@51<^Y|-!5mu)iLJ~#=@$@gkNc(k7^TF;RMTefF!M8kO)CKcqgB0z$7|U432{fc}0!qwV8mbCeM$8GT{s>B+>pgeO0 zj*87u2yjk;= z7fa|Kp8+DPg?ZwA&BbkX6!?%_W}ZA6+C6^B>nrky76Zy^X5#zHe)^<(ssrF&)K05m z`MG$OyuTO7o4Sb&y`42rhm)vS0l~nGp1j90ILn#b;g$3?2OCTK=ZI6*+81VgrXyTd zKx1U}o`YAmf;=E>OxQ6@{vEy1Yh6~(f%>umH8lJV_rqITMP-12(EwlMH#4$itaIMQ zRJ3|i+5hyY5>l*N@@ERNhDmo!8oOD2 zHozvfmme%Nth_R?WV=~IXKT|y5}$QqtmQw%c0ghV30<>{XG)9v-I=q*)Hwlu*m<$W zq{()$5+|6&Vg}=3b-FUsYXtS^LUEJ6KX}l#Cdo42!^*; zFlv9aQ3Sm}E?yfbN8#>&Ka)QE(;I|ouVjBa z@inteZH>D-akY;ddD>v8I+Yu>X=~LicJeC+I3uxN*0Fl2`l`Z@4vlXGyKEf%Wl=_KxEkRVC**N`H~c z(Vh?SkMC*mOZp~Sywk~~@^Be(TdmUIY(tw zpq}Un7p05saoj^YXMV=U}kw^>?A)V($wfdg;#v08Eg=QilH>zI0B_1rYrIF zd}>o3R$9V?|8y}ED8T{L$d*c(I^u6mKC{Cdte+ zFqV?m;pEY}+_!YE$+Jx-Q3#PmY@n3)Kkq)HgR_aHQqU~c0ToB|NCgh1%LYs$6HBK* zw}D+x3oF`ds5ppf?SegIm;nqUsaftq>c)gq|Cov_IEbz~gom($g2MVfJ7dRzOEcr0 zoMWKhizscWR)2X^$BbD;&>sBSqL32n?@ZhryQ;bYbUQta%1w`N!iIxUKCwH{Jce+^ z#p^f@u($kjUPM4Wnbv0pF5qHt0RMS-vwmrr_VG&Nn}*&hfiA~j7^{#RYP$#^Y#%`PKT&n zlKa&5)U_EH|FOfCR&SiN`Y7E`*)*f}sW(bR)vC~*;B@L6G3qcr-(ddatCJLdbYRl6=4UG`mN!;B2S>UJe zxATe0az6G87`RlS1D{`BnJpb6W(#QT#~RbsBhTezO1~2=^6P=;i^Fh0OpglyZY}4) zLG=H^38WX{f27ZWE&9oWJp|l8r$?8-F7b^D8);Q(NKsxaWCe5jPhFvmN`0EYN8 zX(Jc5d2KlHbUui}OWYJKd=E~*UZEU;D@9?CHsQ*a;)WlD)PrAioyGiB`OJ0aq12%9*dA{xFSU&Oac-~= zF!x**20+--t7{R+ptV zBd?n%MP2wK>7Xzx6Dc(hob#uY3#iMQ3!X|@m8}qV40ZHjQ;{fz2v1`Vq8M1K~31`WJ*%?tKb=%zUWIgz8H?S+gU zYk0l?Rq=9WAq!YkSXEQgU}w#ru9MD0j$HN*8gBQ*()3cw#dfkJ^C3vq57zhLENAOO zo{p_4dQ#rzJa&lk)_~Y|L+3Ig(`1OncfDJ?5lb%`K3`rBIwY_5F&}6UnI6|F_Uju) zs9}yVlD1cqQgj_JI{9xa`07NW9kt)pU-D>=wR3lVDZD9aH&cpG6s@teYqZYDUb&mK z-tntHww21eZwAj1w1?NwxfL7AJL=rv4VhNyF32oproKlFb0h`1kYYLb^k~e2;JEO& zZ{l+?N)1!jAO~w%*IxU!043zeuNjY$D*rmjQjZF@_Q+hq-*G@{T^~i^Zm~s z!8=pKXi3q#aP~|gw}!-8qr${Ws}BZb-_9gY3h_k6AsF9#_RmpjPW zZXH1)VeRU`7tDO@u=l`IuRAXIDaw9ZnAEN%k$M^0W*4&$1Kz(YhU^q{=BB0a)ZnhE z=UnZJ@Pk@s81jjqfrbT&{0r~1oWGiegg!g@{(#91^~~h5G*_gVB@ME9mHcza``$fB zvm@Xf(Duptv2E4>h#t(e^}gPR%CU+Hkwp{vTu6^;?ZDHn!^+?lo0FMqXhgtP-agm} zU2D<eP{oh`G+?f8J8%GOTmH((c zP=n49B@6vyH*C1k>#Pc9c&sWn=(vqaM(jsB-ADa!>ji~aebO~$?=aYXO`P)gEQRXU z4vr9*y-lUrzO?Y5xm7R`*(hUNc=->{)@s7yya_y!)yDb}Q%Xv{c^w9q_DU`WV*bVI z*t5U6$1LY74$~idLiJ^0DbPqjJ}gy`!dp>d7NK~oq=+8MjJqFSK%-7FYc5)$!C^^l zy;lq0rM#s;oc#+2ATMX>UpciV3kPzqr#&3*c)s|K!U8;6xa_I2{xbGOj)vo9-a8=` z$(10z%2{X&_ak3607j2ju_njbL#?ZqQDkhKK~BRb73b6bc%`rOsGY9!aWfv&+O{WC!VU4pp$ynr%#$4?i;-_0aBqrhEi) z*US1*b4x4#ulkR`oc9-9+!hKMEb>gJIc1;#zuEoL<%9z7S!p@5IM1}q5a}G0%o?R( zEf7$yyjx2G6WEKL; z=3%rLBXmdih(TgnkHR~n5Rg{XS-=hgUu`QCy6~sMbq>a~%4)afF-mQN7l#)!`OZ7| z)g`;9fwvg?3e6S5iS*y=)kI8smuSURwC8gRZ5+i42?Ne!qEUghhhL!*)Q2CmT?1$6Wz&ACZZ{3!RdXz1>2BK-1}lE8vZ0 zIRz24?1qI-X&#cV^(#c9!U(4fEoSjf)~AEu$BMIBlRo@9>m{j1uUY}bzr$sguC7I& zD~$}~C=3DPHY)Sa9OFxOfG_-9i>xN&lVZ3o0LrxlRmO)eNzkr8Gy_o{+@twkKn0a( z2Xv$> zBZdeDf@=<>U%-?iwAxNte{z(HnG-XQOCImy@c@I_PK68n#2vxV$_$J?_HInt8}MSQ zW+hc`u8CLe&+~(hQ=8Y;mI1XdE3i&CcIEZ6oaWU0Y!_3EYPNyqve?B^t1@X<`Dly`IjCMq^A(T4u9`fl()Pc8xpB4@9e2OQTvvOe63(wU z1i{dtxp}$@d~IC#-gLb@m9OM#(TbO*fU!^P(R8MUWyaASz8&Iq#T2upwkHctSgSt# z4^zB-bI3?WtX9Z=Dg`X&82vYibr4(7ZXI%VvKq+6Bvu(DeH< zWT_P19UYrH9@BS#hyhh$1&R|-iHEH(UKLFO(pe)TE#UpV%ylwkRz3c;vj7)(OQ2|6 z#?w(}iZ>^wj;J^R?XG0;nUH?w7agFWc_Os`;jpyI7})klXYrz#DYNSpT=Q!IjNvey zRR-K&Qk!$DWb~C8B^7#>4R)bwn>6XXK;Qs`)gCl+ba40gztC1`*$QPK=BYa%1{Ofx zs3py^O63eN$0of?nV%Ggm9@+db`pow2CG}q_V-fnG-GrAeyM`wqqGdJRL8%msE_Ak z@DB!*h<$_fZeZY)3e%eB`i*2*Hu||Lm|?iijFP^9#PjiYQUOK;0uj}^2;B0%qKZ3! zNxU&;xVaFU9df~1N77b?OvRwi+6ZkoN#Tra35|r4J`6sxhR)flE`ilQQV-*o!P2-%rxZ(2oN$81$m&a`OOt5$9#wsNc2 z;(Mdgt7h4$zso&gk1}w4wC5G8SB9*oM#oB@sV~{>T;{Do%Fy2wWg90O{|3XH@4O{S z*x=KwSs*k|!SD~o8@1WOKR0mP^hvY5rClBdb0y`$m6|QztJ&Vk-<6Xy26XaA(~+!4 zc1mFjNlG8ONXY@m69ZOT=bl{IjQ3T+8Wrwb@?}2$0Wc7`raLb>j@yu$$Hp$n)l}c< zVCeMz=5YTh6stJj?%P8@wzNLFc5)rpM+UvO37_NX+$AbbJ@U@eZaMxOhfsZE+7_jq zX#OLYc4^1_zpPcqI=(u;=ifc4we0ilZ3#z=-S2waro9Z>BW*ZZv$AXOqjn8d9-y>t zN0sVQ)cumx=KwSEtEnnH5$TolKbC~Dp_-L+?Ues_H(k~E_v5~u<_+4fH8FmOoy(;! zw?L-;mfC-QGU9hNyOyT_nZ zxgfu#CrbSJ2VD-x(VJm{sy%zeGV8>M!rPNoMCucra+TWj9m1euzcTny_!k#IvECz4B)U*CV*zf>g$u@C;ot6-@yzTBqvOm~o0>wus+m(Nq@739d#lLR0J%fGU zC9x+*<+`jN0?>muI3QSOTQiBCSX<0sLZ3`4~1B>b9@!R8&wMGbUZvuSiL_sY(q-dmo@?zF0O#9HKq?w5W~rM=+# zLh3S6uh7?C=q|+J?eMncGaZEnGcz6Gd`fXF+wMadLW3li?HN8=KvrxZnAbcJ)piJ5Q63& z1ftCm$omhyurOyzM`jH?I8k&vT@EqrS){MVU z*wIe< z!R-bX3*sm*rdToW&K^6xM44}uoAJh&#FS@~eoV}GzS#SC4ISUqQho4=t4HA%*PZ~mu(g60??&9?Sr%PP7b{u>8Zu%L58r}TQ#7MyN$c%=vkGY@CVV2=Y6 z!?V0a0Pm0l^$qGqXEW_Jb7cSbJqqs8Hx)#WhC6a#_Z z;kefI($DYzch6dMZtK2p8Gafw-eMVkNCcaC<7k^b&_N~`^Ug!jey#^JrmGEP@|yuq zMj#TXV%xd)a~isRiOyO#{Aik}T<*;ep4z$b^ZmEIiKkscP&zo6@PG=3{J{@Bs zeE=MV@$}8g6CQ`ELAT&Ax)u#HDy`7ndB+nM2v|w5|9jTd-%iL;m|`2etD4?DTt6h; zjMM7vWKwW`3bDHr=h9Dq&jB?r7-z%RP{I{__b}tKUv3SYn*&qOOa+<_33gFwc_JOto&vplaPh`UL|N{-b-9t69@^&UC@+dbNx(k+&JUOa zWm)jE1>HPu=@+az)ono8s4_BW2QH6L9m_eo$!tL$VG7N=a1s)Q)&H|rNki!xv1f6? zScy`CTgryFznkHwnX`#ad93y8rhbfL4mQ^%)kgl^qs30c9BZ8UeTYEwg;isB8UTs9 zq!CVPUawRS@)#Q4+?;&WdoC3XY!C6mTi-lSg`OO=Z*lZBZfjn}`~Z1W;VU}7=%_pg zR@%DU%4IhyB|<*uv}kfm0y{A_-KF~OyCv|M!pgeHpWhl~YM)%gh9{@ee1M1xN;Lzl z(w;THu(mjfpIZD`c+37{md}x)Dqt&bes%e4`QsNF!&yGS|DPSUygTWBUu4<%T~zrf zoG!%+<#_InyICz}FsK(7m7;fW3n|-s?->{YPI5pvkgatK7*bBN@?bVLGjWk-?>KFq-a zT~EKv?`E+;Rh9zl3yE3E_6RCdEq&ht*=^ zyTU#iho!l;x3eA*)X}POmN!;3kd+Eue^_|OXfe8A?4*e_|K--d09YVfpM|fpk(Y7( zGFVe7UJWHz_7`Q!0qG+MiuOqd(|9^&j)#U3v}ymGJ~fjGmVQ82e++>;r{K%K&s)6# z1j|PR+C!tIj(}^fUbOSDiWV@xdA*PJO!cLA;L8*j;V==)Vm*wkc+h)nlMwDw4;(f| z_AshGx43r1;+hNdSXiubLITbFqK`3F8wkd>D2bx>q}!=cv%JWKxmyaRN3C&T8bn_6 z3mB236=|xbPgQ|`Zf_3KCaz8-oza}pTsMI6?`8$ns{Du!`)~l#yn36;D-`@EB%kiF zsOCm^S@4nNd}qoksqj22o=X_a0R(X(;GMUq;@rxH;x++AJZ<#uo}hrb&MJZyJ%b^Z zUWt@e34$vdQnCKfyrWY|WqmUw3naX9K-${fb~+}y zr~#bZ-n*C`h?a z7!Bt-1K<03$lx#sCh;s{yZp`kfDg0~JvsgF9;#sGtW$U03OV=K*L&Hz`UZX`I<`lS1#WRg5q~&0lfA{3vZS+owQu1_lD*Mo+mu#R~H2kYW zx^3fB(wB?NhBSJt=WL`%{ktB0hH(&nu7F{uOB72ZvP+E4thFos2!tLPq1^^#p2KvY zi2zlTx;FPAXet$=p!!K})&A>dWj|-w^GD75jXs4&GdtUwj;@3-=xf@%buN!?=`BX08=YFNACVwX4U|O!Vf< zht$_SB;1AA#T&)s73WI(O_}%b8a%23a8Ch?*YKTgO#1^_M)9h&tbNdLO^exfqm1#*#pqNB< zBlc1nO6?h4f91d5fPXK0ONKtzkr9qaOpM6STckFI2?GM5ubO4dTd`Od5?Eu1(Brn6 zwS*8%nzlc8HjgB{OobWXlp5lj&8`8P=C3i=8^(Z+4)c=%GU{C4rh=(q(8$cG!BYzg zQYMN8O#r%U@9TBgt0aP#xs+a8Z2Oz`13piO)6Na3HlH>SaiC!FSm8cqhgpo&hC#e{ zvTGCGDB5ZEE6B^s_`cO2zkjt-abCo%SqhwEZU7$#$0nGaj$qG?Ce&(%W6|4o@YbUgGk4DRuRxAA*HV-{%2fDao$_>eWtnc$lrriKhq6k?x_2)LcSH?_S!FA)SCSC6HnP+`RI5pylKWxdToA6ztr@u8Ocp~0V)#%jF4We zaxK>j|GM_KTVJ<$-$b4jJ^`#AQh6lrWW@D9n1-ug!F{J|O92mB;WWm50~;s&ZJ{up zY}!uKSZB7Y2Yc^*?$vVqua#9sdR5Hu>&yS9~IzXAqV zJiPwb9_KK%+sSX_O`mPm3{F>sBzf=8Aszu5e73f!$ zP%WXy&eDA9&ZX36VbFcQ3M8jYOh3<>AZo7d5_Z|`IuYkh;N*j%cYeol z-S^ISCa9VjMsZ=zzkY{PE9=#XG+fT*=$?(@nk3Mb8zkbIY#ORt)~l1g@k1cD`LUE7 zi?!6K6zIXeYhyYp5KQ9YQ3&FxNt3Y|QzhDqjD`bd#10h2F0f#!;dOrC4_sh$q)8FH zQg!(JC&1qm6J7?3Q7^qUHbS)%g-Q+wxv(A(aY%ByA;5GPyyX4wp1ulEWBM$5SWedL z(73kN@x?FL+}nUSU>u?rSbLb_Ze=pP;4PL0a6fmyCC9 zn9oTz!YH1$g{%ZCAao4L8){DQMYKP>3W4#Q+v>;klBx??lXn}Lfv;4YZ^@YdZ+Try zxe1$$iI1skj$el*^bUTxP3WdyqVh>(EUkFtNH+#qN*N)wy!V{$gC3o}N!L)vi^02~ zz|;dX*XH|``QMS3y{i-d9w8Yw1A4G+D#IO46*@&*qhuRwAad0ox=BpAl*{J$)?4sW zf3a*+Bi5z;U50>giErsfSj>@6Wji#pcaAX|EgG}d&@7TJr3;A+MI?|e0DCGg$BW-! zP5Y^)P3-_ilzO@v+@1G-99?@n)BFE-x}GlTR0l=1Q$z?MTOCC=w@R*?+)|0$wnf=e zV_l9eB%xuJB-f3R%Qh@qC6rmYjI!C5YOB;XP0ZTm`+N6$Jo+ctmx!BGCyCMupMib|3jUDnbbIxQ99zAhyn# z2>k}Ihl)vwjP1!kXmh1a!v?8_CGK`aEQ&8yjr@DYIi;*ig$+LIe1v-)QLn&6zF6lq zj;IXXU94K9#^S_!%E@RUUR0hD8$~+j@UzP9Ro-Ul&f+_?^|vzuR2Ov$=KgWp2=5G) zuUPo;cA(F+Ekq-|Dfb^mAbN$h;Ylewh3#+W5`3HnTXKm67Fy0QTAsg-2yGY@jMmjI z4Q^b>N-$a84oQt~;vcq1+UQpn4;LOe#(lEw3gf)q<}xI8S^A7CyMv95tJy(19pTP7 zB!2Q$>n;m)#sOo(8R^4C^4PqaXhKHV`E&N){{|{o@x_V~UurLhMjtfKP`HcK*!1|i zsDOChdF-N?Q*H{Oc59OFiUIMI!v|e_USmP$o@0R&z3iTr=X&1o-zCl)D76AJ><|23 zkNke7_6oz!lcJNhk2h*3nVy5=?yBQ=U*wT6nBlh)1fa9!RUHBA)67EOLO@Ii5wQhs zr@9AKFyWg|yPWilQ4y?20aQv--V7uX{7i2DfLVi*vYKnrLM>RljQVy4$ps7YQ^aVE-O_Wu90yaIA{r`Q~LN1E${5&5tS-#A8vh zUG~=J7F$~+7$1>oSgq5RlGv>R2C~+4uSKBSEWelAnzCUy0Q7+;#5Thl(T?qroy7PJA(EwRtgfVg0C5+# zB`$vc4~A4fL^MDtvN$W1s#+RiQXA0@$sM;;b(??*@X7C#v-6X!4b@TuV zNJsohIYZG{A$j!RF{S&BQ6l0oJ(<}6JgVYLbCj6>UV>RyR-Kl^gy;yC3bE%h8|oj) z{Rd>rrU5dbn=}vbu@D`Sdyb1mVM)#~&VTBX%a3RL%^+#<%^N7+vQWz07c9^hr}KS4+MSBgu&AwrsF$u*Gq6cs0`8&oR|L$tt>* z>l;dB7^{i+v1(i4Qf}*e7f-P>5^@RT`;fyEJee%y$kN7A^Z6>omGf(xO6$FZQJqJl zL{0=v9RMza2%*uZxYG_(^6DNYs1(vGhPMj~tgxD>?!fx%9-o0nV#wxpt$>*_Fvfoo zka#5|Z1^LuUT7v&XT->kiHxRJkg6t^okfP=@RPtUdTI0<3jJXmWG+-AZTgn!z7Mpn z%v;n{)m0baNWfZ&1lrKr(Gh#|xOFD4Vgz&N$qkm!ANeK<9J6zBkGo@|TbZ4Gw5!p1 z{8IjfG-5deeiYL%$gtwKxV)J^mPjhi178-2W_F(+iYc0}2t-B-{Q9`SuW?doUmf+I z)+GLsaNFH3i9Cu_qgY9%zB1`=;~p^8E6lN~c$`e^Fx9A{ta8j^U8{u0zW%;Y9rqCv ziWgRftnsddzNm>nPOrT~@KD05J3;Q!=3*(1;bK1_wa>s*JC*jaFJXW9ucz~J zGQQbDrLjU^(0(G?5J;M>XPC!xop_=)^xASrk@R6=`)X^{GE^kZP)eHR7~jNEX5xcw zcWQuc=8zaVV3PXVRGZu`!LN2(+6^sp;Z`QQ^fgSpRYW&-rXgq*!uajY!Z41RbNa0M z!eYiKi`+q5gR7A?xPMrD`Q#78gHe^E`XBwU8E6CF1O*{f?yPrXKky0Fs=xmsYvju7-BYbPT3y)bnO>|uW;!UP!f$HKOGJ! zz`pLUD`oo4hfpv6pe|zUjt?loIHFoCZnI@Lw!O$eb~K0d*9&&)-{2wM8(&5i%t z{fyInyH72~2+t@2HYV*`Ku_c5ChMkfUBhQlW9XM@uG7=NiLnq&cVK_#n~zyV{!==h z?RsUH&?~7H@;OL+<)y-lep7d!xvn6rFs{E*snmpQ_;-E@?UM|?i2%<~XpVh$vH1$? z_%E5-+2XTe=#9Nlu>a@$@!`rA0&>=4Id$_%vpIUfs~x&WUk=yU->jQPccn|!SlCp4 zitjFBEXmC6gn+J-U&Pzspe9(8s58djTWoHq?=^~cLUPx2yZz7L@RQ-CYI<`|KZt-R zrRE+Gm9;KB8X16y2_m>VIdGNu6^mSXj$Iuv&qy*O5s4-(rbZ&6Uy&lj_27fZdi`<9 z(@&px*{3!o$q3pvrQwQHAbB=ct?+usiR;JP+HNaL%ZMU9nAwpPGi~9)uVuc~bUNPW zG5V%nQYFpXPB#WC#Dy%z)nS64%W^cSj3!;OA>u*B>srGtaK5W)(TYiQFek7YYupR_7N7Less*lMn zLL!-kPJ-MZuh!hNv&e)#)2io>-+@>fkRBc>d=qx{aHCV|X|P6uqb%(Ys~JaIc+a-% zC{{n|6r2M9Tg`afblBuF+q4F%3eW%Uu7gK8?*S57ny^TcgnxSZ{kg!j)sz;)`k|9R zLJXwBrS+(7@+V|F2?D_vGpz?s&wlmj$xUAP;P|e9GHGOAc;hfX6D3LEJhFb?v+pd{ z7X3OzE`P(Ixw)oup4ZuYmS~twPb*vQMxvJ9o*X+Jqh??hkJfuZ`nsg=sEm#}qe=X~ zJLKyd$q4VlRZNcPma;)Xs@bKTH0wN|Tb~J_O_bu?n*(nS@mj#QzrA3bnhDyHk1nO@ zHE*`m-#HnZn=u*_DY&&0Qnmi+2d^{cG7*&)ibd%i_Q^uRzNFt@6h*?SF!HCfl$hFta0sO&sf^DTY@LpKT@4UymClBVT>4L#O2NWJpjxY_s* zKjf`hG-Y+PQhg;9NCLudxled4XLbQV2s@>-iE8N^h6a>|&s~)xdJU38o5Npolh@z| zTbb}8>4cwOL!5Z8q$%;W-SR|cg5@eKj!DT_+G z{YNp?Z+*)CNhnmRw~VY)|0G|G12V0I@G%C6(XrJ@-4B&-Uepnz$-3Mq(!7(+@k;)4 z3KMibH+R?AFa_pUh99(!=#-D~F4&3Ca7FT~_XF{qls}{4@2)V+A*2+2y3MYN@Y=H> zQiOh1@)_V_f#8rv1;4BpfYiEkg`YC+aa=>~P4_a1^df}dYtK&o`86+ptvMi}GL1m* znWzz6J^|bX&)33P=fQ-BJ-dGRyvBLQwnK*mW+?HKcN;r@jS#8w^R3hK97>&55;9^V zrthTJO1)W#o-nXt{H?_A33pO_sGhSeBieox5#5Gb-uA_svtx9E^d0bhn~?p?5UV@m zYqC0_#Q?zw-7n9{K=7F(>AN=mT(fpESUD04_8JQthPAf6RF`P}3+-S}9W5LG=k6J! z*wNR1bf-VZ2*W5Llm4J4>-vw_g2VZ%l&=^lZdIC9jTS_=Epu>2epVgjkZ|%;{O~4^S zbq1Pw<>>WpyJ-Fz9l!J*G6p@ja;9+wYjY6xOq1t-<`1v#Y0?SVFi};3E9)ChES&ij zRQdeJPk}E`$sZrgr?qjlMNx2L~6W7bW! z?|H8Zw9WBiTg&`u_318u>)zO{Nzo_mDSkaZEIhu?)TDNV~cY<6eTwm;@$> zpij5ACpidf`Zaf6CEbn;e{Sq%nNv7vmPVR`e>9|%q9-olzt1#XN=-Z;$(HN()Say8 zqK8N|txYvWFVSp}pjNexm3fGBJ|#eFG=z*5qmk%kKwlet9zs3e)HQoy7I=_V32FAm zyNLK(A#>!jp%?gl;)`X@mx$e4nm5A{sUT~T@#7MYgewGVM7F!hC+~QA3yL&tk?d~2 zSmj75D`DTN=-k8__X3|kZ_hK}@VXd9l(iOcY1hsb|>#h_<*ZD7bf z^&2|%v|UKfbG>`m>23RZ)nUF}8DST z#msVvC;XWFQHW*8LZqNbKi@~vdKW2VApc#fLcIYxby;BDqMWN%<6))q%S~mWXSvM& z8fP1BsaTie|LLOd(<9x{^Z|FYr|eucQ?>VKhbkzgW2FVzOpEyY*b ziwqfZsv{ozOr4RiK*l44I5{KL_-w|G7j0fqS}fAB*thclj@_+>yRMfw<#?FSoXa>H{Y0x4?0D;v zx*YzdST(~z)0&$zDNa33G+*5>z{=F{c#e}TbXGvazkC=`Znpis7I@%m(#}ZKBl>72 z66zv!0;281$<8xyK7|=}^=dr*X%$8WUbyrioP?D4`&Im-wp#b0v7f?z4hTG2eC0Mu zjeZ{I>ps}J9_?=@bU)4L)0K(wNWe%}kmd;NtP-(P6CexOS(Lr+gx{mz2!pHp z+3i7t?bW~rBT!X%3VpW@N2k{1t~^($qc-P zwk_|L1^NRL(D93kzp_rfW&{7nqeuBp^%dwou`FQU?%tNF-r_c4$1P~D6;MM zKZ)sG65%%$c{;*43DQx=)Rla6_4ydU*i?l6VYjch-xZ}!c=GlIeX$VT8Q5j{?yVGf zzb}J)9i8Ia{>CDw1|jEAo8G<3^KF3F`NwKfWKl}v(B<{9ww4>&$`fgbQ!w~v8fGoQtyvxzqAdt z&E_UT6{IS!PqyA5NF-xs4{FhG%;FeQpmhg<1TkAqVlm*%WM6;OR>a|F%qj}+zuttx zzmNLPGg-Z4-MMx`hFr`HbV|f%#_IfQb2HJMI>iL#adR_615X(vR0io3g%pdI7P)#g zW!l>a3loNQD9zoL;l$rZ4%c>hYeE$GkF8%O#0PH*;ZB1l1w|g>8L`^1W`*;R3cPZK~{rp2*v3|b(i^9Lx@@qJxE306xNmV;Gfft9n*12YblhwXdVjp|#FsG%)Wc|@UScIqt? z5DdY_#Xw~vhCiya*k9dIvE_;LnPeDA(%t!(eLl!)DyM#UQyd(4L_g5o-bg55vf&$r zxfde^euBdlkj>xE_)NScT_&t|Gip(%WHCeL?jasWHrs<2FK4;<((f>4heZ4O;-ReV zkEW;v5oqP9Kq?b6K>ZaQB3fnoUsk?nJqbJvqB~*^k%W>&efTxh^Wqf~-#2o6^uVXw z;8Py&FZn{dE3Uglec;!rc~G|{EwL$fk33_ADzB)pNoQqCuq#HcW<@FBmqM|B4qp9o ziu3-RDH0?{X*o>Z#o&srvoMZR8b?3s7RD>3_f*>J#NF^0tD&Q=SUe^-(e2~et6$D| zO>i!RC!MW7Std!s2HTROnfBI@-|Z#@|v6{lcGNk&3$>=(U)(@`Vv zYY(VcIPke%ySOIQ>3d5SG>Vi`D;uUk(F^#(gm7-_A<8q>m&kX&LiP@}a?2*db|PMm zQ)S9QnPmL<>pi!r2PX8STF;xK&_;+TCaw#A$b2e2r?f0@VQWD32eD1&r_mmTON%N* zKB#YAZycovnjMmF>~Sc6b71PTpRip<9U*FkedXb~VKognhv8H-JE@U&%|Wwsm$r_2 zMjgC?>U%`iBPNydM&f^-x^MyGBzO)LkGUPW3+~JuE1@y*y(avE;I9{CCPv75K%~-d zw_fm5u|=xtF4kep!VDG14=~<=kvki1*t3`a1b&%CC9ZJ!W_LiMes?voOWX0jc_h!q^ z7dj`dR-j2!Un6aLCCcz~Fjahgc?WfMqg$igv|>fCOX^gkcgN{7^r#{UP&!p7LYB66 zhWl!E)6YhDG0zIM78&r-#;KF+n>^pLd+Cz#ME82%q<0ce!=w}pdqolzDRMkxQb<`N z&n?u40-*l zGiY;sTCjERXlu}fzG&l}!smP|KFK6S{&mKvQ_||{hY5?20gW%48bT+J55Ma^zf)*3 zfg)A+S_+O8U{xWK z5zb+V_NTU;dP+Gf(=bC*9PfJlGdwXDUhQ>e{XAiq(Q_@QowQMxNY?yI`J4(-zJWZa z9T(N4bmq7WNW~MPQuIGcyHi5O91u27mM#7HP3m)+&KT#=81`aG*4K(&{&p2XB$1uz@kM2Z=he{MmT;y_z)&C?9=V*N zmXWa2wc&Qdl9-BbYrgb;fB$R!2koBbV?*YNYgRJHiXexYYP8P7+djr*8F>IZZ%(}% zVZcfL2{*C^*TBSQ0l|daA$moR;peVW>qg_)rdy>M-_nKbqL~_p%Rgtwa}te5foNMo zo#DWQLcPoC-louf=s64}WR%$j*11i5pLhq_oy@co1J!~HcL6`4YF8Y|ow!rN$o?l2 zUa*Z6A}!b(1-0u8vZR=}`Yjde9;TU|NNq_SdK(JgXCz^`EZ)b)3Q<}}O? z!?IL(#vws;t78-?G1&K?ybHeK?}M`HjvGzaz61~A+~ccW%Kml)ikFc9#?(*h!j@wU zq&k$900NitRQRk14A7+j-a^d^D+=iBn@ucVkar9E7-%AE$ITLrHSCLEZKWt0)L|Z8 z+3T8t6ol)_gY1^xPBH`iQe|HFHlUrG8m{a@%?F|zLz@P@8;0EEfeBzN%uooc?I!@f zPpAvpD!9wZRRr6v{XM8YT-3uPxndginSnCb6+J@z8x{E=-byH#4kE?bgv^EL7ly5V zu{Y$b`^8F8U%MR$;t;#1Q9KH;A~ndC3VatZ4zr6pB0g&hfKz^v7o!$vD$^<+@v>6od0>N z8gwb-aL4{Oy-l>0LY4agU2=JI9N&+aF)NoThbyB&GkXccPmXMchJ&lKLfm=O6SDR1 zlJ)@f!yT?{e$=;s{~6Rp{H+eF%%k_T>1VtwP94U)0UnP1h$S#yJzal3_n!jLNHFFS zJWe&`fOHJjDOuV zYFx>_G#9tEz=s1e%aB~19B&HZXYbP`VK@A8PSRq8y{=*PJ8YVv5NX2FJ0E~bR@Yca zWc0@dvcJn~ko^Anfjbf*R&%vWP^;vTpYSU=-pS0YCe#0taP_S{{@h-VhxvCxG!Co1qTJ>RtI|mPXBPvOiLmtUC=r5!lb_7NiDr z58^^X#l~2etP<`T3O-?J+vrJ)1bAm?(Om7F1JY!zExfwe^WCy`cBl6E&spWiJin=X zX0^*A2*eD~`dl9Iepd(kfkt;C{xa-yQ$-a%io>V0Mb@cmt?nfygyb?ya$swxWK1d9 z)MJ`tMnqJ^*mY)nJIh-!YHxCA5b(ie-+CDl=FFK}!b{^G+sE_uhCaU5_5 z{OzBfEwco3UTqY!^_7PGp|Zqx*sJ|_l36cVgN25is*Al!`vTofp#zf$Q_pqtBlsJu z!==@a`&A@);*P+f5aFXpkgxv1Wn@twy-L8CDaSd z(dm;59N^FNE13skfC$!fd@IIm9RmmG>86*a5!J$4w(#M?*cb`jUQv{~r&3)EA)!V5 z)*LILev9x3F{>*R$%b+Fu7pnmBoA&aU`5U1pI3~V)d-_B5;7IwW%L#omrGy3zhfY| z+bnvHH4Tr4rE#ZmY~Won^kZ_=ZUEz1sevzpj+_cVGdG~%ZTNLN)-{=NE-1_s0a7}_ zBz3V&iVRk(TsGI1K<6u*&v_pRJH>YTe#Y>B2DqU*qbMRPHo*gNeF7Z0y@-UoXhe=T zlDpRs;S^y*Ko@4EJ}*Q>a>0yheQEEW46^_RLp^}ovtHX zv0IY89 zZ*cu9D?-OFF?+-*1ol9aejVXDd?n+2}EMF|F8I`7tZ31UW z{4z%MWS*n3;saPsqq}&eI4uFN_QyUt=-+5|yxLa(AR0*WqFgNc52uTtw2r8YK%&vS zDhM;`NnI;QNARELwem;04hR7#q_g1Tz`^}@&J%!d3J!QbI~#)G8{m@M_MeUvck8*f z&Cba2KF%FPMQk9LHvMwkFH|~+^fLya*r3)?))nV5HDWASg%IeBj5T8*^>!>;B*S;} zJw6!9X|(vCkbM~^pCLIukiPy3NmQq*Gp<+$* zMF{8>Lf|XRJT(-p*y31NE@_zta9(O8UDnId55p7FpmZ3XspH?X=8K=GG1D`(hd#YH z=P2ycQhk^SP(-dHyR+j_>=xEEDgo1MAHD{ushRV&J;{pvMkkuV`VQ$PBOmQ6R5S1& zTR%2A0`-0}C~~nt7xeF{-2XSp)ptpwRh?f21Q5ipR}OFJtGiQ!G<9l*Y(yM{(+Y&(sE^(=zcO=lOV`sQzoU3)?c?&_AXxXbizo7@LXDuXk_>O@` z`I4lz0u%3sP#0c*Q}_;Da%ImAhJv0;AjHE}w}+$o{Z%02A}gxUed1yMF7p_5#_VL^ zGW%s9fPQ$S1YNA{W2;82irT{=P6G>Ys^i90Iez^sg|)=nxsUOkfeSR10L}sxJhlKc z?;x6#0N#19QD_fTH+ga5g1dc!^I6t8FD5`jE-3<~e-zlfq?Qr#^VU*Xis`JK?w?cb zm)R76w|&GQ@A2)%DTRhfJ{{E549B{x>akd>-%{h$0+vk&;Il5TNsb$Kw{_rnuk`|& zfNux?Q{My&WUUXCjyF?-OhZh^P}#r&AFx^G@Ao5}zltdr=v7tV#oef3sZgRg^0)Pl5WX}A)EE*6{mwmS3Ab+B8eCVci(}tyWi-0Zf&yb z{r%gKb<50Fu%QYqruYW~PpF-@@K3Jlx5FxGmPmg4my9Hrix0Q95<%()(g2od*l!eI z0H4@alGl>1V1t8r$!TYwcRJz7Zd(;==770FVR;C+^|Zh)eWL{3 zdDJz3wL@Q3xI`ELdp+K)Wn(o@f}{nKS9(Yh(lG-Ke7|Q0D3!hf|me!X|nYMhA<2%9c3Iug` zOnpPBCO`A*KY&E&2?uV5O;NftVylsA(j1XI%Z$lMRt|wZ_sf)cnyPlmJhBidA8Bpl zVh2#D1GnWc=PMv{M%%^^r`%Nf|Kk3<9cyhiFGJ>7e1x3I2mW-%I-_YNWiU|#_DR(# z2Ljd~212b_{QF>}NNhC)R^3UEb-5jN-qa350sVglUv{j!NeOccWw`iA${aED(du5+ z+3*zVze%X5iKq_`7fp;^(1%^&$TMytNB zmT#5|iqs{=?wQ#*ZqWYn5O<+QKpHI>T00i5uvc`@4ragMOydLz&czrllNhe%eS2}~ zYPw>g{EAW;A|E(xUf_0Slw=0k<)bc=4{B{P&?ULV5q4&Xl$=+&-}{+}NkVH})@;&L zL4Ut!DRuc&{UjCYIfLW|`gfyxB?(EF2qCUSObPx6J}q2QOY|CWGIyxU;?PZXH8c_MrxEyom2{g5E!` z1&Ys>4}+A!Nbx1Tx{`Rr=U!t!8#<1EN_Io^gez$Ox+uqPhy+7~%c#)!eCK3%uc$JQ z5Q=}&>ig&P&gyfYPs0G{Y_M;8i6_KKR{hGfxdmj^eLad6zU;SNcNBEVA#>?*%ObM2 z3!(Bz@x@AkL>9#aFi!oolzgs0R}wW-p{WCw`+1{=qUa`f*pz<$*TYO5RScV=?RbvZ z@~7C&{D|lju64~nr`7jzi;zxf^BR3e%&j9|;Dpxs=?d`fetWnXj-))P9u;=)3Qu_N zAk?%LIP{mp+5Bo5@YwU0wr}p0ysXghR?a+W^#Oh{ zzUWx)31pvG6a`#z=TOU;?Ch_;1u5LiZ0Ml2*79KB$w~;Qj{}sI+j>#YSV4jI(gIg( z5?BN0<*8=S7Ubd2!bEV5NJti8gk1`ke?RQVW1!S+VY&S}=`celY&Bg@eDYF&?qjmw z2cKJxY-gY}%(y%yFn_7Z76o>#0PIirGb!=NsM2}~6DtxPMIiDHSC4}C%hr<>i;+jo z)<&e2!TQ<4gasxDCSzxMsT-I&OtaRfy;HMd+)I5n>%S?|N5@-x#_e0Qt{w*N3U45I z%F3yZUw2DQaKE9A=U8O34Koq^`uNyWeS!?t4;=gAWm8JnZexC9;11D|ODxSf?Ve08 znj73u*(efz^P7n7RpFTkVYbw$!Pr9xB>pV{+*{cB(;t;Rh;g zF}Kx_iD&xeJ2CgE*&=#f{sW)^67}{;49Xc6~RI&OYa>kgY6lDoF6@ncm!ppAxsNT`eFU)b8ng-k%H z#a>POlkW*)7y-ttj!#2K7%(HVh;*qT;|%9;mrdgjK*w;GRD>X2`cn7$H(LWnf3xHw zOsL@;6(}cI--5sLT)sg4MD`yvAx4{PM7`QY#pTD+M^6AoIW{o9ZpOLn!(S7zr^I$X z67{tds;AhgZV_PeZtZ?$cB%mwVd+Gotu^u~C@!4aEi(5m9UpDmD=g25dFL^D8};ze9>uTxjUh2KVcfQJc{XpBI8w zBYci*(FWNLpcPdDoBu>uDO3Me!hb`YyuAYnbXumjP!V*M*572VNqcbS_2NFB=d%zO4{v`#fQ+%jNyF}W;nwgLKG)PwJ zf%71?B9wjMSw;-#omsU?Z4crMl8r^WM5~Lvl+=0K(ynnL@IS)I(>|)BVq(I=XojYL z#Mv{n$UQZDu5;^#1{W5b>nT9QZWFMXbHn2EwY5F=Sl0?{TN{7iX>-HH z+wRLn;_tjaIm<6)qlBsuepT#-h1(&F2PTqglpzy61&Z8q5!+=~rCHE28lD;S&*t%O z=E#o{%{aCu{Kep-CM0!#kEz$VAe5wORhy|2+gUNc@s8?w{}zt-Vl@H^$h?I|l~nff z*ZHUsk4o9NDv~6M5P#XTyo7*zW$_AhJi|~D23-V1tG$%C*wwPY*L8bArb%Ew``60O zU6|Ii>K#4n{;I=KeaF|CEv3}$UG1|r^Iju3p+vR2>9RhW8%)>t7+sVsINaLwN<%vm z9}x``+S2gXE82>+wIOFLHEly$gg-REfD6iEd-MOgNA0llm}nn1!%X$7?l8g};$OyRRN zv^6WOk1YZ;6{6tvYM(A#PJk;???7OM{ZY5F>tYb$YIB()_~cbapQucC@$~H>5XuOi z?XJDqOM5)}7ywNr76F2`l7G=izkxS*^b-fyYS43{Y`cc58J!Y;YbrD-*Pq}9mp}=N5=ir1M->38u4R2u=M)#tz=JV0x z_jQWdT6jnl0T?b4pqZJVIVo*j*kHc>7!M4=iXV=(ZyyzCLuc4&#=lM?~vi})mbR$gdjtd*p^Af*Y+K@j7sb!w#89^B#*8>DG1A=KxYH<0-5w z#h^-px!2%S57#nW;!%YzIRet}XAz(v*|~H=fn7uT@F-$&q%bV+7&fvW;Lk^MZun_2 zdBlTh?wBjqmL8j%3w!%GhhDrgy{?X*2FV8*GB4*vId|a)*VaF~0KulZUPl+rC9G@* zVAKzC`H8wWQ@nett?zzD!cbB^kQ&tNNKkGE?|!_AE*jslwaqZb$*T?AkGX-S?=f%s z+tkGP$&AzU^}niH4BJ5<(}^`GDGCbGjIH4ZeXk1WLp|L@Z#W!7`9-*&jmx(ew*GOl zVjNHq1Mv?+E=c$G|t?l7$c&r3;0M$#fWSfW#Tx*iqHODo{s&MrH8wOUHRlQ@f02~U_ z@F>iXGTqYb@jHR^s$}!Mnh;4sY*Bl;gq;nh@8+%gJ@r)WjuCTiCD^$d=XS0aw zCn|%qcDl(^hBZKnW*oCvqQ(oWKc!_IPM7LULoFiTY2K-8|HwZXRShr(78#ZlJ70pH z?X*4};|dC%36Rk+;A(be$z}7r!%#`&{|rQx<6e+dL}d~s8r{e4_NFolBY+w6ivN79 zjY0@eynWTpIb@|A@ZYG4HOLc!5FLNl_%$FNdFUHK0LXXa6exC?&{NHx|JjfJ{(%vH zqL~zu7AKqr9Ob_YAGbJ=)^Tvu0A!TIbs?*=pv?gQ9l02}TNG&yqvJ1GRS`X)>)~^J zr;ScO)6`7|5sSSkZj-cq$%I%`tI?`&nR&TFVZb;F4aNiE;WnsL&7LdCAwjzLdS^0h zkq8Y{uLy&ol5#uPm%f1_b_+=OmYKd9mJfKBVbAJq&iP1s%ZlQwcW|$dGci!{bCSh1 zPGr3RkVTTc%b-F^9RQ{?b1urq0nczpT0TvZnoBR5xAFVMX`vV`&omIXM&!vU{Q~KI)TW-0j8p@R-662WB&1Iz^{$Jm_RGR8fZM7Sf8;{+pV} zu}|US;_jo<^d7Oj6b$ScGOJ}~kSArLYM-@vyCONiul3#~=IiX+0!1y zJap(IX3|DCvVz-Dq;Pgn2W4f&!@#(m=+F-um`5l2DjEMX_`9{@FT|GvC?=SG#=wzM zTSa7e_pza1zQDCVDzaYOs;e+mh29Y}y^5I83pHYU{#7%qldUZX)>PGPt2Tb6Hxe-C z60=-ehCU4kP^i-zfa}nHR5_Myi#Iff6|%dh@fc7vKhIIFKe{^#M~LY_Fz)ntX&g4 zth(M**_5)OAc>mhs7@QNYtKlyRu}>K@Vh;=Jh<_&liXd!wP`{C<@`Pk&8dr-q8ov$ z9~xGL~8cazR;~&qV&>CrN`>M2MVD=>&PdwpDz)5kjc(Cx>?;XiVM`uwbSAU}gdZ0hgs;S;i{0m}2; zl$S9p)?!NPL+WhhVNgRvcMeBP`>THy!{G-U?>y(lrI)TR6DGtTqgnB2%Q>dg(>8Q> ze)TIy_;V1%bt!d!-`f8fG>cs<3JmJNr1>TI8S~m1j(`c~t0QPaiWvJV__o-7aD>hD z7j8w}78Ks2TZaGH7CUaH|5ZzGe$}THu(R&}Z5?Qh(E;TaRYi_RdQ{OCAwVKgZAAUy zcJM`M-c&Oj3;nwF)mnApb+C;29Ikbw!!Z1zOdpNMR7k?jrM|qp*Yy-51~|?PZRhnT zt1@OBvs=C2=`Gc9(+loA)lDJ-o6oYH!2EZ;ZM@wa%o$-58%0-$krdx|F=i}O{G#A= zS!-HMyME@6#3h&O%ZqT?g=z%JBJ-k_8Ynv^_4G{0uD^Xq_K>(Tc6b0I+Mk{uzH3o*Y$3 zIns-n%s0D2yBSH{hm2^eKctg&0Ytp=0@m{dR9r%-??PoHldkD0v%U?xD z_PxLxE@efZ(+%rqR`no^fm}gv1NLxiBY=x_^$}cn>u*#9ZC8t=)`mMBU=i!t2l^GC zf~}CxB?&?wbj?O&_f95evcpg+Bi3G4K~foe$H5s_|JR)bu1^BFjjS0fZR?|__QQ;_4xabBq+C_}N)DJPFojS} zC8*58hsopcJfQXj_eR!q0dh%4$t#*;&3ITuV?Ke{{AqvJv3zG+R4;I3^E}IotmM=k z>EH2~GE*7Ad^Ehp+s_V815cL%Hv$nB0I-p6CbfGjA94`ILTvpl<(~Dgzhh)zIwvq> zu>crRQvdZ_wsAsh_giW`mhGeG;8%9eGwj1$6|iR$5HbAj5NT{}IK)OLq}ebE``Ds~ zi(8D~i@{Ur*2+{N7Xtj8D>_B_pTR;0Zmyg*Z}M0SJP!lJ3;{1I$~8QhpxrE#yen3? zw~@TK(AdM0XmRFTbRoG?r~HiVV`GXhaOy)9|GnWiBvxww8`u+1H8toV~@Ju zYEhA+gBWN{u=dq;yf6#gzh$%J zW8cp&s#NMDatrf!p0hFp;kO?*g*LnNnEX8g;xDg(dqIXrwt?a1Rx|?Bg%f|Kg=~$a z_WEpkBZ|?>>_5^-(kLD2Z#&kkMyw;O-XHqAAW_=A3))7%l@alxM{(NXcRBTJ>~z(! zG5D3(m?}c<7!PpFras56IxtPIX@i>@Bta@N!rfWA2M*remZKMDe=xx%GR3qfpH7zZ zpS7cz^qVJb&DN;!|KW`w+ftm`;e6U=ZGC$b0kj;LntQC1bxY!uraAR>cUi4cWDCBz zl}a=-moqqCThFa}!Hib3vn4`5B?r0;m#tz1%8yCk{pPU@*H4!{zvC}8XG9VGQQ#e_ z(ZGs9jA+7jCtS}sU}`Gbj3>qRprvv-)!<=~5pmo778z?e=YBE&gYS?n3RpIUm5A~2 ze}7|*cNd9{Pdl#6u-)%IICwMY!?!)?i zxb zfCJ}=c~1cc&pdpu;k4@?gd2bdqB=`LodLZ~GvBE`5SZ|+tzhLuSdM}6hxUL16_%1u z-jog)ah){@k9{Mm^uOK3IpOvV9Il>CV1bB$tPl5eo0aiinY63JfY2VEt6z9D*6yi* z77wygx^RNHB+WF1IlmU{_LW>y8Y}dpCHs z-1}{zhBtF!{8u{v4{y|1l!VRHsU3dkm#(^zD zOk!maQyz4>?Q?u2`#DcKaRJE;2So2u15;=LCj66dh$LP6UP7b~=_*p1`0QVX2X>S} zR{&UcEY6^~P%xeGcV2T^)*;|VovBWFl1oZGybNtu2sA_k3sP{y&grsFYa>EM1XLQ9 z|8e_I(5Ha{pQ+T#=AoYVoLZmn|UnmKaMCKb6u2t|i`jvO;g zTXNs!wwbw=Y=+p@j^FS3{@?N0XV0GJ{k%@}(-FlEi*|H(vG>K3eY!eOG{}4O%3jEg z?6DucuZKempQ(h9WGPG#X2RcIn?=n2yQ^J#_`ZDn4P*nm1Tp()6Ydo}mh?`9Y4b`0 z^L$fx8r~0`h&W8Je-EfwqEr&RHE5~~t2`ub6G?2py_wRR!V)u|I$nMgy-F|e(WpnQ ztv}8^Q}^x&4$;rwk{{BjGB|>cd3M%+wRjQAA-0>JNRq;%h13gDq_c;YOki1vt)g<& z(@QFwN+6D9EXu2O;rhEi{3fD`zR@zWFa-Vd=Oeph z%c;ttUQP#i_wz%kpEp&dy@ADOMynPr$TM8|XQlYrxRZ|K5dOlhr~goyC2^cH>Vc*# z_e^H`ju1s2Debo6EDmtr;V)xDP6z9*!#^pTCF4>;dde_78W?7iEfVlv^`!91QE-JW zQjWQty@}^h!%Gj{C`_`MwetmW$QICZ?$RN0$Wf{81%QE%qTo~D=Pmd&U@s`xhH-wE z1?^8tS2-RU<)VXCajz8-Sn>e?AjGfuLPW(tleNJd_6;4MbyW(3 z%m3PlatKuG?PRxW+jUJLF+f#h5_i$j3o9ewkxtLxD_3aSDTf{;JF1wL1=plxdj@U- zmO1O;u>0i@O;98w!T~egA_|O&=KBfVKa};Kyfzl?+L5^ zm((N-*6Xq5d1ZVfU)(D$yD0_;h2ffgWFU-9jajlP@5#9CyO0oBvZhsPyq2`tD4HDruucLvu7Xqp>m$2MP*0i^mZw6sxIY)J_Jgj&4Q6<)kq zB82P_R&X*bX{SF|kq>ovdq!9sp@CG_ziR)=*lRARy zCFKn5fz6R`(AdU{?6ObRw5du zS-iN>bl2xaGBY0hu;SXF3#+8#c%xcW=jyE0;Eg_;l86;1 z(z@N7=$euL2{blDF8V}L9g0kUOE3BvI*-~1H0J}gV4j({juRIsUxI9xO3pp*0je+4 zBegozX6zZA3G$+I1G}{RGh&+UNFSQCvzSIoN>MXu!! z5K3Yf?Qhi71oGEzaRFQrT^t&-Y{&be2B+wf?SGGD`uV=p`97gKAei_rW?7%VlaT(B zp|x&Dbb~tEu?dQuqu(EXtx$OKG@>IHOw&(CigGnQ!kzpo$Kb2bg278RC!dc<#R8*! zbTjO0JKpY>PVi6M+gf({hQrgGf&ZWZ@_J>hY!xNGWmP31+@ zcG%yo5+FmJ`7-WMINa(#`^OGG+KO7aUWGf6p7|&FIfGdhMZTNf9b{|jO!$MADAh;V zeHvJ?o1ehr%6vI3^_laAb%ozUrIC9~64hy3lU3qs80UsL#|)|4Ft%75KbaPgAnI1% zng1rutXr-kJhCk}JC2Q6Okv4Ui0K@?6;Zi0T*FA=1Sgn2@v7j+stMmP`?2xwfA_ zG!~MTcXT9YLq^qqPY3IEgj3YS?!=RVf3*S<-qJ7I1#U4Gek)lp z7p$F1-=G#==;4lEdp&l6#IC!MD*Cn|D;#`QN9Pe`uV2cReh;lT{L?Fv!}uwFKq@gfFDpUIA}0l7u+#uuBmgxpIv9Z(56gb6eKvY6&qDx~3l6z$&yf8rS>~v5|7Jj47kL0Qf7q}+ zG!lJ#kLqUE?O_9~?w*-C2tXBQdrHP{GE3znD^kIQk8-W_1WweLsz{$AqbdKOpd-SM zy2`EV>e>_|F!|9%#XYopJW@&amc&}n6xrr;8e~cx(L5@LEH5)$@@ z=#E_$xG18E&A9%xeKAibt9%z6BOF~l-7*NPUZ3UP1q-NS%0Kr)*}>pPFmzefP~y+) zbCfKHpnkmCI&vKV+zuti8>ZPkKcA>6&=wgeX`5{RsZg}0}n2iheGL}nT8J%t3Ybv|b zH0Sjk>9jwo&)OqL4J8ZDpIaDwlNoW(?04Wl{q*gBEWPcd>d<9lC>UuA47z0Y|L&J3 zGVWGAXRL*+k45L!5S1XkDNbq&O6-0_yi`*AI~STTCzC|f8Ed(`-y?T!bgN_jV3KS< zE+iZ8@#|XmQr5o;i=fARN(rSrcZAOb zI^Cq!7k^LD1ncv~ym5>v7dv^STiR6C(<;{U;C`iO$k+QlZyH^IJ=T70f|pg1 ze@p7e567o|eAJC#30B;Ycf-LgbLpdp^c+L>Nog*CLuP%6Rd zGcV^mD|OwZmAZ$kr29(W64~UN>eW*-&;#=f#D<=Dm;M8q5(^R45=lIHpmu#<4EF5k z(}-2JRauSh?$U$hJFNE86@z!dyu;8602>YdoPCGZ4mQN#chxT&d;sYV@(S6F!ka3> z&xD@z+K_QUN9KcdK~AqF6vTm&ZPI)B=RjT2`bxUTsxh?9EwmxM!J^+^`BFj)28T;NHHA2HT$}$uMT$46cLwt+6Q|NRG zkUiGa@JK2C=`8SVhk2aa-s1)(Z~86=>0BC^qB~arblCe$uK$G>NMaBWjNx*%@EV|b*3u**fq}dDny~EFE4*=-dwq0!e`bMby)Xr+7jbNd|k4jvvoS!^a%wm}BWro=kboxqzb<6^a_LASWQ z0HwLA^T#v8a`vuP>p-_t4R5J*0j3@Xn=Pv`rs_B@A!a`ee4y$DszW)A{}Bq(m7^|= z1cw-(^B@?TJHm3;xL!~>2E{r7vDnQ~%Uokz@t+SU+VD{guN$P=cR4?=x20h|x{o8S+B$Z&| z?hYi0FH`b~jah3d>aL_7fEnGb;PfStbJy>lbB95ijVr!Z9gzdGj z_jsS5zU80&{6W;@xa(aIg*aX40|ysXud|8Wax!eb3|3iD%zsmr`q?T%pt_UO4{DA1 zTgE?V>G}B_a0R;rL~P^#?xQ9fYf3>_i%suCY{y0oFiqkppNx1*=DtuchbWrK3rP6c0<2LB8&|!CGSqHjiii_OB{l48-ix5%fTI!vH?*t zOM8@eaRCgnzgMmbFu^4YZtf4I0c}`F*}Mp){AZ}ravHe(1+xKm;Wg{juD(!MMnM1H zGC%sRe9od*B-!4NssuvHjJ_`>t1}4>2_YbQl(%`;%zu$4NCga)13G(yu1GG~p(>f9 zkAWAp%EwpWSwzy-M--C@;v}RM{3(D-xZrca=T`3`10beq^Edk!U+QJs{!ifgr< z5bbMPFL8%K(&tZ^SZT+*=_;GL+r$@yS5`jiO!Aa15cyw%>N@21@m)5#W&gPWHG3vcZXA>CD{4DXO-X&ZHgCZiro+ zLI*DKW$8n0#Ry@j_aVJx?-$8By{g-=re5>R)Hi$J<#^&PpKNz3Gbh!3Q}P+7m1R@7 z8zs?C78K5Z>|^x@>4uGuS$l#3 za$$A?ts?>iy8KaPIDT#YzoI>rg~O<@p6IJFaW-llmIc?& z1(~2`g8E9F4w56EU7~vK$Vt?^?(_$#FWaO(N~vUX_Zz?zQ$A=CEwflq&*}!}8E$zm z*LuJ4eefOmrFTK9hfe(ZdMqSI4d6Y`%k0l6>k> z?_erU7}uyjWM7>&X$VuvmsO*7Qff^+^%P(0xaO0D0l4@sl;ASyjXn0+YmJ{1bjJ@JrM=Gko7#Yy&4#%b) zmlt(xTS$*`F!?qR=`94Fpvp^D0PQmm@q2y$lDq1tUrK*dE)LJd-O5=0;f6dee~YTdz@t7`rB@2j>fJ6 z?cW}KhFZLe@8kOFkt&tP%?RxNpP%z?AkGJ9`0cRqoyJZcYgG2@d9eOZf^!=+c2bI$ zg_LzG4^5iBv?Wwk{jCg-gJi<;-ly+s)H4c$GPz>jvwX~)g^1Zto6Wn8W89?NkAh#a z)uUQNWNgRRRK45KGlU^$dwwrLthpx4!Q3ERFUI3yS>*v5o71Da(~LnWXY-2_0R|P-#DdVNm9|93mv2vWq~JiIc6wo-X7k& zEw`a9=~7>9oKY6%3gt%s33vyrh9{zc6Jvl!tKIHkP-#0j`m8&DZZ>Re!IjzwK26U5 zUNqW$j%&?;Dx9wQkZ)NC<)!@1XL%2@E-bfM+-S>^^^N^b3*WY}s&2GA)paWVqV%b9 z7xcc5MV4Bt;gNOKboVjH`W26=MdxSk<}VbTyQN9j(M^_ulafo=M3(@| z#z#Diz5+*u-I#etYer;fc1FO93bs|v7LEI zIMKJm*s>7yoU1*qPn_)h9x|2|=EXlz*W}zM`2{ZOl>Q^%;k)(NFEYvFA#xwDN?(>^ z`M^8)?f?0|x#BbJrMs9f*w#F_UP2FHTMTfg4>-3FH#67I8M=cPB{ z+tnC$$FHs4RXOA&@%+AByTEoh^NOI`ypGJ5l1~N4MQ52q`{E~^-(Yfzu8>5 zOY;JZOZq#(p~@9U%yMP-5Y&-!grD=#WAk?-683tie23pxMm_lPeCf>f_I(&#nF}3> zJ|~B4Ar>fQq|*<>-K;zCkhZ25Hd5Ay&TNAA*2HV4&Pytr3WL%{{2)tNr1k9<^jRGx zaP_G3{!?E=hqNAsiNyHKB%5H7Ti|1qvwo@;`ZH3#J)(c)SXaZQeOxUsnxCqXUtXHp z_tx0(USos7*ZKLZRg>A=wMkv;Vfd<8mdTI4e^1NE=aNlNO{e(^%)eQ#k_jyzmCr1C z_j@%`lR=!*Nm&nUz57Q>dywR#dQ9sMu}!3e=8&^+&cc8n9Q(wWugF61_Y19G|I;bE z2kH4~+DWCA6=4f~W@E8hZ7G}oPiKq9^oIqm^yW(EtJiL1aPSc}zB-RUF)Y}R4Xeu0 zEzX9@4%0AL*QZVEnx;*A$)W>clGpWSkROix-L3*+TzHE#st0mdMSmH`F^OF}iq2jr zN9`87 ztgtml0FYC(+pqa{7~{5V{CWr9DJNs>Qz|5DNh40>w97_i;HKuogZa5pmSSlBej>xS zcTVCv>_}+xzkv&tkUB!IltGgQx$fQzpPdKx>7UrrA4`@PNp_*-PiAc|F)V5JRbCFh zuV~)r;`S4m-F@-Q9WC-@%L*Qxi4!(ev;!PysN=SGwPRBFAJ;S!g3?pxjoX^ZdyV%- zj4xY8J(Y$%2R)MZa9z`%?);wWCNnY7F?HX35ATrN9=VsThrT^^6MHhR^Rq^jD~CjNXQja7vC2R^Nbd#b&~ z+b14+B+FVkYjn%~NA60*LPGs*1es6M^hLq(Kvq7_45Q>AQ|VFf$qqFRImWhhCpyAaF|3*hYEMEb%5`3u%%e@9X{34)Gtc?TdLw0fZDK1#jj84MGkIzR#&~PyaAuwR9z{_xNUaar0%*P38Ou}4Igg7-q6kYqNlby>dtkB>B+6pum~L)DnqRD$-MP*a~7iF zmhP2`H+?_~X_SklbkVsD42(Aq1hIRz@mwH#kCl^T1NA>yCjqCe_x zlPtEm6R-G^o#i|2|NQ=+4Xr%YG1)*9ey*NkUBrFi({8&Ux;K);N{}6CI_3E4V+HxjRT4uuU2gk{6e6RDz^#F%~;Yc~&&80D`xE~+r zPhS7r4Z7~iWen+SS-zKPH}7|+T>tc!mNSeyyd#Sjx6G5)u|>Wf0?O${c-xkKkZ}2<_$LXclComTg`6+*kjVV zbSvbjp)6JF3N@DUFmvpJVZZ#hg#+S#8s!=vp0_HN&;~5O!C1MVGeTog!=!^eLsta8=^zf-03bydI4M)W#jv=JA!=lf!;cKP@nx+cIgP+F{F zslIGgTP+r@?fOYtX^Nlh!T7nDM?cOUJ*56l%gY2@7|S%q+KueJ!kDYM;7J!42-*>j zF6)W?=&G9XmU;gb-FNcC9YeBfTwpjjaU#Wwvo=F~HplX3wBBMY99gaZNt?$$50rqH zL>;nxuqO<`J*xVs1l3O1mA+)jN+l^N@U)JcM+6SaGnG5Oj_8mE3f^z2YM6NhK#mhM zJcv7y@}vP`(6-+0JiXwc6m;LRAmr!+#2l#bwQZrsUJ-Iyd7z3TJi$pEah!DQ_Ltk~ zcmEXJMyB;hio<3VOS$j0Gk9I6ljiL!9X6<|_!_*siLyFtuh=|{VOcd%+zOL~Jbtg~ zIQrDv!0OL~p{0m8UlnfmM~$7qrMvtle~Cc*k9^82x5Bur>hK7Lhs_vRRC^3HBzwRI{e;L; zTyDic4i-4v$)A&dxrnQ^y_pPqy9hOfPL+0@08y~Z+MlBxBztNhw^1rcF9x&4@(_>^ zgeKfI7ZQJ1&bJTlzO-xCyEJPNCZ_c-nx$mhqEvNQ_zb5_rO-*j&8$l9eBzGIk8%bH zQ6erdRnSpvMmW{FuD9L9kc~qA>8^N`CKP$=eAPSU=!LKkG@BJnhv_^vgvz*UIbqwf z4Xa5c5poMjTE=cGL&_AN8a4Ws%7eX{P24 z_Zm*Xr3Vi9*mfH3V>L#utMT{a{2ys0ghkF8jMelsQV!aTyO#7mQRu$V^=Cp5pk&cL z{O<%QRwF})+HR;aR1vg>b28t4+WbEO)1*f>@_PgxSuXxDsf`!$7{qbyIT1)@R><7q zPi^86BbQQxs1YlLm*jvW_>$uTI(ZG1a;-#$tw{8PGwW}z7<6DtJ=V@HWO@fh9P~c9 zD7pKE`@@Qfd6|KI+KhY}oUyDG|R0EZF>%JL1fW(ICXo($_YYJY0G=S?0f^QdF$kRA_$Wq zKN@%6Gye%{5RL7OLVFF0OnE&xG_FD~s*TLbJVbCFO>m8p2?(D*6>Th4O}NY_$%>$# zTv0Y-71{u_}f*lNXW+o&XGVAM?eV6+TzAh0DJh zulJKz|K#|k(bP|!E64VoAIn;;awpa+aF6Yp+l!flt64OEsZFiewnQu`yg$J?mNdEh zrDZW?t|sGH>Vq*8GIa-f=A-N(h^Ly2lg9&@v21Pgr^!%UGft=9uTt~P6v{_7Ya}mf zyio@V-)YdHaTyGW!8{e5Y_r!PUZ*LegcY;rdU>+z z#ISQ-g(&-o^yB#dKFvo)8(m!It;FB{Fvu9j=`6`kw`&-Q>g?;q0pnDu;PwwWI60pc za!(*&BOVQ#&5kPFuW=Y>_Q zoJP^t)@-sO53F1rQub;YUn-L7km)m3SQlT&iCeXFEqslj8wbYva`e92B7-mnawfSCPTTxk;|$KnI- zC&}LS4H-b?Vxnsv=uol_pdg2$BnDJ;GkePOTTPE)^f11_0va;4+F_XqnJb2$beP2f zJ^6>d{R-(KkdP{Ha(&(ugC19DVh9IHQ1)|cB)_NcF-cCXUTNir8UU7Wesq7}rYq*+v) z6XaGHwfnuyhQ1+y*qA?-8%!nSNIbs&a4*)g_i0jN22Nq!>Tvg$a;n-fG3QATsy$m8 z9H%Sj(;2dh%h%dr^9PaMt2%}NiD|}-DL@<9Q?+hAe#>R%K5{VIx^fu?;)caemy=x| zlWo1$?+o^)@@Uu-JxIDO{~x=|bit|_gT`)sNOirxSP6;7OzC02N8u$v=~;Y%r>^Sk zZOUR9GM}b479}mG+uvxo+=nkSA`Pv%lN2wj3SpK5fJ*_DA@5Ijhs^=KXz1Ei;iP)4 zZ1BHY|7XqSdJtE+lSS;au8-JQ<)lRnTCfU?y;;W&>BZ16UqJ452zbLU*x7LimasAK zYY1=52VJ()s5f*T*^N8vCMzH7wWf!@;;M{Xg5jy0k!EEtk!ec1S{5!K1$2~r72bIS z(c)Zj>t|WVD-2d*kxk4vB^OXRI7iu3D-^iexGABB(*Ol$A{ZS>{(O zUjq{gxhWfjzx5)C^VXIs*fZ{mjY5r%9HQ>ABn7&o(k6~l`uTO)`Uait=>W-9Sd!&= z?Zv+V5zM+8pwN%$b(1Xj5Z!y_X$Ag0QSEQBadrJ_F(BE>XPll{Yh{x`0D@NcaW24s ziFnJTXj&_9oO>m^gVZ0d0@FdY#pOkIsm}XE!+*6P|DY{_t8z0{v{`rEI%;Z9x0r>zv z{DN|MIr!Mq;CV7% zEqO{D#0TSgEs_i$Kw{GSe2`Ra#Eo!N3?BxyP@ z5MKYEfV8F>Wr|3H9>5<}H5};Qpd-HGNgwSU+$eb7C66y&MeCs}w0B zCwDFKx2_y*bQEd?tqJ#k-eD;g@50#7jy4;kvpn@HUo^RRL1k(yU z^N!8pw4vqD^4o#QhRkqeda&$&W+Hn@lnomfN!|8x5BMo3_Fop<4%gRJK)=T-0kX|O zzQJt-)uOJFhB0dEm=^ad@53-dY}{QPim>pHI+JP%-`~^8-6G|CdmG?y1g?4 z92a*-o6^kAEh2JPF+x>XBcGlDG4KA_$>Y=1h4XIZ_gW@!^R6>#boDQRpTuXWX zf(;x@sR?R=cpTvC1x(Au>=W+QmB&j1Qr&6H6b!z==O{xQpS0d zk;!9~Lx;xr%2pN%>4N~t4vsd_`7LScMB_6lMKnr-80RlOp^6#evRFDBRXGN0riKCE z_8yCNM=wyF{DxOfMuE~j`cSuEdH*SPF8yai%~F&|RzNf-yB64gQL~c-z$_Z!d2-4` zHD}^S<4!2_~n`OR4!@pP#NecwD~(Dsst|ntf#`*_ai;} z*UGdMsZF-Ym!(5aEbmI5PgWGZ!QT&xj7q$YTAnNnd(sF+mef`UCyMUc)xBbJd;FK| zpI}&|G$&;cGSb&g6JzEdEcd`jit4^2hS{T_^9q|2q$!l z3|!Lr)4IXGreZoyF>)?UC2C*2lHol6fbh0-@zZs&#kN<8c!wjkDr<=g!8DV9l&mcT z{VXHcy>1Z}Mn^MD-r87B2D7tqzGJEd6QG%W_9Wz5D$KSbr-P~iYHcVR^VrbXRW-&w zz9ez>eaCB@21RAGlPr_Zvio#;SF!B5F#c8qY&(tOhetV8fCQt*rya$vd#P*VE8vDbV&Jxs>+aZ+2depSm!bjMQ);lN%jxjIwDzl=m)+Wf zrJ~Y2rJqnh)Izh%_6jfGm*@qHx|09QWkgl0Wb0#1*zj<@@qyEh-Y$($+5@jNLUF-1 zL>oPmO{`7=dFMtmRMF6(`L>*a6l7DnCmud)I@_c!Ltl9Ij{EC#NaRux4}?19H+8Nq z&ql~f$arl!U~AuyYMMT=PrvIHw~q;2^1C{}Sv5qR$lbQ8;iUsDdgQ*ApQgC`o_v=n zXXOZ~72C*uxe(<@Glj8FygK3&O^z}0$VjvL!9PM&I9bnFx?AZKoMpgJcZ_h0JQQ|6 z*bt1>(K$$mCKf=Hch9qo=KPyHvGD7o2=RmcGR=8L{k5khFFkBMktYO$?R$z5nb2u>7W@JmZW7X!x#mg})x(c(5K=4$#Uq&iG2^7E=xf>&>la)isvT$J37 zW3K16PrWuX2>rd?+44Vuy|^g80yHfzkk>%=U%5D={S5sr10{Hje4TYU@us( z^4cT$!swa8X+s9T=#O{UQ&Le5!CQFaRu;tL_DOSz6z>qu=xUWTyTqmpI z>)JS4=v_$CC1H%t+`MBdtM&4WA9@sbN0Ws5na{XQx!)#Rm&H}K+#Q-T|GkMaxwBnIY zBI2tW=Nb=Q@V2oxmK-r#~MQ+g@&s zbTq;7l8^>v7G;h=#s3?1GDZQR=~Z{v;nd{|?~Y2j(teW~L4C{i1>ih~xQR3Flm_`R zt0!;Ntf)@-&o|)?N}Bmc)eckSO%*(NV)wFkFlrI!)Sn9kc7m zOXi_NV-NNZh&WkaN%i*MAjItB9!@c-uO+a4YG;g-kEqQ?3w3=AeUv77a7g}{E1MBO zjd(2<*$t-V-R2Fo&AiWsmu@_IA{K4X7V>P!OeWib_Mn&x)=VmC0pRPJX>HsyiPzMOu`Q_mbf9q_OHS!jI)P| z+`%g%oC)3L+^uawNKQN5`EpGXinTwxX}Y`8_|EhWh|^DSl@dwnz>=|CDv0yF8IK{gJO;{alWAoCntlXipGlj0EP|)_2iwpog$ON?Kx#mI=RX= z;qX-(zZ6ZE?i1hQ-bER@JX<=_v2nQ{^$PiTvfu#=1IANY3BZa9yoJ6QLR^CG<62VlF_$mezLHjUGVof2WQayN`RWo-tp{Y5^H>b zpv-&5*I^B}pc!%AvWJTajK0LN&9+*@4xHR^k~;f|m}-H;9&zB=+dKaYF$?U-{}VW@ z>hAa=?T<}-Kl9PO%>Df9Wmg_vi4F(|3EoLG3KC&48=UbOBUQ5x%sG<$zAGWC`3&RM zR)@ef4`7?$sC)Fl*w=ny#x3s8KmP|<4PL3(UMiFLZ!5_xVydIw(~jH7d$#(Q`U1kR zM<+F@jF3V|syXzPmW;wMNSLyU{I%TUyU^D!D@A$#A+jz=BvdrZagK4X=BzuqjisJ3 z;t(|hFYhtl=c{4)s6Q-(26Udg*S@mw>!i+3{-IHXzQJ5jjkxX6c6B>%!kPa6WsHDo1AmkPq;-%H^5pqDqPN@TrL=GT?T7) zId?Xnbyl`r$gEP#rv`=Y~_rAU>siot_!{@2E{ROKbq|cxy4fxWba0!!Yes|9IX&8%@cJ$Qc*I5Hg z%69LVz5>U^2EbarjCRpmn;4$q{ZAlPTL!@iH?Odo+rEITl`3mIzQw8TQJ) zDop#P)V;{2{)+SWwXGJe-FKO?86X@fGDl=7_+sZQS?4?A*5j~if8pTN)t5xMC#)`s z-;N6Gp3>wgBFNw*Uf1oYI>ADBJUB!|h=dMaYuMzI#i5luQ|sI!N>nx9&Atg}Y*G9< zQPN&v3_cFL*{#SUzxoiS2*w>hd5RD{MzNZaQ`)&In{03WX<2r4`~$j0fwq9yhaB?S8Dn zX4djUzZ($&mj;ynLcSA@)HCipKa}f{+KKRa2DKIZY9Jth+F4tA&!KBb*P-^-dd@fq zDl8dua|7LE>nq8d%%7?-{w@owZSrk(=XhXff(}6cD(qIA58wj3?8V>~XAD;>k?g{@ z4W@$IH6{*Bqj4Wd5J9O1b~2?L^wMM{OMdm_JFGrLtxXr&F*Ue&+`W-*dRM_?;`G!A zpeDn-%v82(o^Mpx+T&Dr)~dknrKwHdXWBGYC5~0E$R67AsI-CAI@w$9F3(pot~y$Z zZoLc?OXD{Ux5xO3J*mKzx799%TsNYxa`wni`^Ti}c`V9|^jHpa|T=?IUTg>(U2|N!YoT4W} z63bQPQV%UTYRaZjt{)EQoSMS`!Ai?l*pX%)mGRcouY;)h*`YZ-a9r}Z+|)A%bop_4 z{+SC44Y?~RYGAijqnH59V~-5OKTme5|4GE5B^TMW;GH5T(t;m~Y-9eNY-kek_Wj6I z`~XU?@-o=E9Kaj3NF!}I>ip4@((8rHS1Lh5&MNkV!R>%Fc7L`GTkY8L+!wzBr5ixpyT9!^;?3%%-({c|AiroxFO`b^Hrz zh*~2XgVIE5uJ5VG74a~UFQ^(NqN;7mI}L>{$h$0F{=3wy#uvN+wzP>+6a;BKggVbP z7=2 zZkYo!j-48@J>5}a)zp0_;FYgPUES^3vW%-$QlZcJM@3HjO2?z!w9BoU%#Yi0Zd&b^ z&HET9u{NPEUU1uFilwWg5BwfJ_0N`jbZuLy zhWCc6fc%J_gJUeV6PSz5-S$TucW;<<5tCQ`gXM4WvbaVZE2PlyU$sLPkA(YUO29Sj z_pQ|$c+&90Q-?L=T{itQ9vE4S>%2UV_X?siETHwUiLBYxOne4i>+SojK5AWR+KzwY z4Q8h(X&^1EN|E={@aRhZPPALTAnU$UL_{v_(BSIE;LZ%Q{R%}_FLlZ&jkvqH0XG~9 zT3XWk3z-0(qp~^-@>tmBW@N&XlF4b!uv}f^n!~MAv*cuhzzz{}@V>WHk-coTN#K+7d|40^JH$T}ag%B2Xhz((FMuge^;jXkGx&}paUASGy!c&jYX+{XQ5 z>3SCTNQ`+z3Q2Bm9cwX0dO5dp&wL4i&POf!$b3E+_-&u^OLD1R+buKGO+u(^!?U>3|+^yf^hc8%+ z&0YVwc75;U#jqB+AERod)@|i=M28w#?i>1Wo#T6*j`8ofTQ!*LhCk1wZoW1>wchaP zU+|XHl`^J6)(yZZ`y?d5{+q~b45e2j?oK&O{;?7Na(1{Jeqy-biN{%9O4hSz!BWYp zYV^zpUD8v?mz3m_VT3_MSYi1Q)tQ=Zr8ftp=%+-Ts%D!SV65|&s}la4d!f2UqxyP* zh|jF~R^2btp18G>OLwz{Wq&Liwp(wvBY)4WO+vQcv9@NvDt#wtuOCW37YDzT?D&$p z9Yb0uuMjo<825W*IYfWc^1bhk=Y&{cMzD0sUhtR-T*t@|sjeI#ki~~+rRuMLXA332 z&^-|z|8I@Ie;yI2w(2;G50i`h+5D^W=cj?cUP1W zCcX~Ff-6p>p)-UpSiNp_F=@#GyVOn!(P)0v+x;h{Q?J$rGLyzPtYs|IX4mCRMjlu< zj6x#zZcp@|aniR+^t(d4bjdJ#>FeMOV%21x8Uw*GUm41IHD#ukhN2zfX-7V#88>WD zI@2U&`~)jUXXY2X{=|3iiXk&^QK~SKplp2p9AkzapO9sWhqOL#@o+wn(aluzVnfeop7sPz=PmYGpnb6Zz~ zUiALu`QnDj(-eI0BE@V8?jyokDwuV#ats&^`^eh{>0oqH0o@$?SKdt#bHi|SfL7O= z)Gu^&QxQ2T*o9nuN!j4neao}l^3Kl<7&Y&3!}*}sEv!gWDE2E(!UlI#$;aKLc8PrT zh%r%7hN!7_D|KE`EFp3gV@2-JeF99RfEW_i@O%*&qNf?TvUB{j4fT@VQAhGB}W20jd*``4+ z@}<;+?kI?EFSE2r@72ESjr=V5siZqI62WV8g=z3=RY<~;mluw5k82%wRIwQyM7;Gh z)NYdrCB||_`u0+|iWjDz^py4E7Af^nGCdozbgYs~A7YNm)jnz}7P?)y`TX_*AOt{o zrhT0$(>>C^etO?@eUuO6-9m>oeZy-2VNjmemB-8fo+dh*uJ~e5nmCvMExsLmkrM9?L z<_hLEPMM@6P*yM|Ld`r{S!QaeNM_{8A+>wYqM>=X-y9xp_gV0IKBFuRbcQ-p-K| zLxl+hGy-BDG?X5s*l)O_?3Dg?J)aB&Rxs{$fhw8n^?FNDE z!jSyU_{Xor;aCSju_lIqWkxu?`rJ27b781DN&kH2fOGU!}JevIXi?;?t7U1c@GvYN!T)%Am%zXLZ6J#LW0Fa|y8B7a5{lS*H{G@Zc!mVuiUrAMtrgp2&tUHNGl zG?;brmKFLNoQrQ4?x`;|IB|N=&Bj&*t!%<)M8Y!PQ^ewwPjQOox)-J~t}!KAuA%FU zASaO~#l5MkNppg)t(fuVot4d1Y-k$`bs={#L$rYLDUlh>3|}0;E6wM6g?_sG4Q-!a z=t<>vF%bfQocDY+d=;`<%SwhP8XTHYIk?LTf7`@Z^Ey;=3qRL8;T2 zX!aR@tznUW)4f>jkJbGzrlGrh(`L1oBL}7uoyB$cm0yun@fZ|fU{+h6!mXjTv|VQ< zrfPW+m=)=k(qwVeOG4>Kt}8RkE2=QD&_nd+JQiuYc~OBbvG<>v-6#3?;qmoF1XE3W zaNYT3=l`28n@HfkcGM;A|J5b|<~%~Is858}37p-DZ)%@qeV=s6byjk&=FKmoCMAT= zQ3ozq6hZCPl%0PP^KmTvRo%z!r4Z%bKNRB{CX$m=uWOr*ZH2^`u%E; z2Z%68T33&`Zs%q^9fA(hbpDxfE054NuVpf9iVd8>D2ipXwvBh`>i`dfnh&6jlO|Nk za3B1}zAb$Y_M+xG;ks$@wttNdze0#Y-x)L-^e=`~&wq`Uzk`vbMVy%(ww6@j0JDmN zdR@yQ87Fi25`qej(h*%8HC1(Zd(g4gkO|utcP-ru%I|ZjJ;1B2dmhuwF6@u<3tnq+}`j(^W(`v4xqz>FDN0+d8862SvdL6n#i(A zkAy2$;(qWbI8K>yA^WJB`scyE62p?fN!-`Eg@G=tVFU?s=h3$83pbnuwD%VKQd#hY z-{SUAPU(CnZ!aCR=w|L4YUo7Ys;Jyt&zsd%D8{6{L9c)Y&Okhd=ZF3y+5SKEo5a*W zG45Sxjww=8B10!_g9TsSdB;CVU10@1$VY^t^*?v`Ysd|L^&fc7+IF<(%1*qzrnUIJ zDsn+VQz<8b0Q&-}NNc-QbZL$lrM*Zk&_%uGBXVYpVyHfTq%YCeF{oZ*o9u|?Z$yba z(wrloXj>2oIVVrAH_Ex^?y}iIFMks<=gu-u|9s>|BKR-%+$$HsFl&m@VI7Rn0#$Ih z!Xm%O%4uR`I@>Z;C`!$<1T_a5v?SzhW0#MqZtT-dpTkcrJ{`xBA~E9kKFQ(=N*uu5 ze18|@8a3IZv=Hm+B#M#gRP)1Zh-NPskOeW>FJ-k@%fqH3!^?9^tB-E(b$Sk%a=BM( z$iN)10^a{?Gz9fptSdx5aAj{uQ;x$=gHR-e*swtnHj2f8~@(fKV-TfigCmLnwG~byxdv)AD^u`;H zIXUvb=q06^OBzxb*ZDK@&+ul;twpKEFr%4PP+R=hSOPms+`cK_B_pA&C%7Oc6oj7# zDa~Hn07MzeWw{5Nlh}%9KXH=-y5eCTOK$s73VS+WC)DKE_Ar7OY4)G` zz8f!3AyfVU#=d3{9ZWr-2cDMz@(Z~P5CE@n9Z&3zkTD9k{<|cJ4wIhIGjGY(@|K9kW z@!9eDsK9~Ldd6QdkS$KPPH6erlKlEWP;*W`MZE7)aWASpAkR&`mz*gTAj%JtA2Qk6 z_T%Wg_mVZ_i~6#i1@`beE^iM$^@_Pgxg%@lkHdR012CDHfgXJ!+rG}E^MEuDq9)6- z&t47w%U{@TU#XQdMFXnk1-*K1NZy7=fbg>7hedx=8EjE^ZrNi37J zJe`Nn>nrCuW##Y8d(>cG52xh3nS3{3wSoNl<~QymuIS3{xz1&m&AbzA6~;Lu$g%NP z4jT`we0_ew#@iK5yT3f4R`=BcXwEH3p+q7b0#cmf0HI9<^D2u2?0h$FLB+|$w)Sod4~7&V-Fi& zB#5{a|A+lgJKlEdhXsI5aE-krnitjvrXnq*RuuCS3LjRk$1K2Ud6dk zCB&=S5S}bk*X84e*3O+)MV5HCs$n0IL|sO5I@g?P_3~ylX`|k|S?Jni%WAbzUc60H zgch(G86*Gp-=df^SiPw{E?&ZF*mZ-*CnZ2NkmQo%kLzLj^#^LVSo}ORj zqEc{yei&iNAq`M^ySUzUs%%5ARuJy$+5c0wU2xKOoQvS#m%A^`D=}zvf3I5qdqF%d zVYD#l7<*jj|EI_L{(9zo9cDv&oc|LE(>r^6*%I$Kdp2fMOP@7SV(3a3v_3{0f*$Ob z<%A#|5ke1*tTA$RoYEt3Q%*rM6qU8|lp|punH+=WYh8>f>m9mj^7ev~Rdm#ZV5q@6 z{c*jCII;WCHUIHKPI1}u;v$)bl-TY606m3DBZ^ASdSV`W{KRtBM#+1VOcQB}(bI0G zeiE<5;w$H0TxD!(dG4i{gGe{AcpslIJ~U)$L+hLrJ^slzrX)<@{~Gy zCEP&1%pekY9d52FgiY5foE?YlWvu?486MPNu}aG=t~MH9SdW|4Lr@o^M;4cj&_t&o znQKGT=M$-D+f(a#x0<3BSYwhQ1a7jbBfAC_smdVRN4~{TO653({L9@`-_sp#_P*L* z|1r8^Rr0(Csbw10vv|;0C~GyY zTw))IDteNrV8FO(i0Xb{znt6K^~c>lS{f0qF+c7vbU@$EddZj#nmyP76stP+^+2~I z8Gv1#%tl)+m$FY<>Z|YGE)d+u?rE(|k{UMOy%v`ncWc}REeibXEZB=h45D!R3j^SB z@eBelDfI^CiR3Hu(m$INdwA`vY_ML+s#C^U9|67F&MNjZg(x7LV+WgG&;4Y#!_1>+ z1}3)ex353#PD}%k0$udy4ve;8RxkAb*C-IzC1~$~WIzjD3&d!a%!T}SLU11Pd+i#w zA5(3}Z4^sjiAbCPHdJ}X^-AWlvSY%vcwsi{T@w$ovqwdH8chVMs9zI#kjT3~y4mMx zM-P4sAU=$BYMfS*>8_~`8efwq(8Fu`OV%TzT<1R08RGNDrGJfne~=}EB92wUGlzfA zeL5BNVlGXgp?_u#^C7ajUtaLIk989h9uk_s&D-Ixy2zVlNy>8c!X`l{&@wX6cb%fM zg78HuvPnYE=zCk^F>3T&s`kohRg!kpZQEN&lxYY@-n%zN>A{7T75ck65r}P0;JssT z-{t0p@Y7J@jasD-G2y6L8L&ay`fgHs6NAX2? zStPj9YVIZe(yU>V+XJmK=eXmBRUtxd26?bD9SEUF%X^-3bjjcl_$V8NIXkUr1U|$s zl{Z_kd7Y4U%V^I#awN~Z&~ph%t*V<&;1D8T+7C>kgV&-YZ%{}4ihIGyrET9_!RHcy z_}m#=8SE9l;z}orZSeLpqeiDs(a`PwZtf$l`M|(#aG&)W;*;8ZLKq^IULNMxD~N zWPNNU?=PrYJ*Xn`1qY9%|G05B&ai0D;}(+=xIxv3gZL7N<+c06GW+5wyV0_avQ7g2 z)k}yMA+Lv82EkrgtF=j~yn4tf;!&C{!q={S%Qwn#@hp3?4)b{h z(J7|q%PuMc@@9KEFUpV>$jy0&T!G^T&Frn$*`btZr5%h;1k~I7O8W8(HklZ?^y7gJ z2cnL75Ja&Ka3E&N>WY6G-+~8(Wx2}DMS}-l=N{>Xci%;Ck>M1hS2i`i)KDOOysc1< zC6GTyG2Mu@bL5;l=Hav=hmsKXX&5A@R~DUi(Y8mRwBBB7lFB0#`*4b2MMd6VtzkI^ z^x}QK0=cAZG#kDUeM6gK4PD4d9Y8CD5{P=Vz884Z*QV|2lle{SEV}*C)%sik?D4I# zCHZ`@nois6s+i!4(GhEMf*_L>e9|QM{-gC3a$?)xM~Bz~jef>9QkL8^qZe*kwI#=e zZP|mUZOwZAh4FP5o1cHH1_iJ*fzHF<1mU|?9KyzNDViRIa;i4a_65?C6njO%lJh0g zem|!7rE^%3$be*_mzO{lu~+5gILjjU7hC3p0ILpSSBxGfB@fJV7dF&ptIC&6q7rz9 zC*EU+QJBUb#GIUMpPR3tdczK0s5y*v^?|VT3(`hFy&>QZ%vR^Z)#+T7Ca%1~o_y{P ze@s1}q-3k)~kiIN2UcQ0tU*F^wF%CxJ$=*ZSH9E|eV z*d1U12tFy`ytRjflFI?_e@X0;sK@@}8YIY>U*uU6;io)K_0gWZic>Uw*q81)z{V@} zw9hpI?bK4e^1~i}66z`M)>hjWwpS^jcu+C`v4#TB?DbaHd-f`_BtCNNkHHE`G^8pf zhZP)lM-NC7fRNSos;baWK+&WQ=5sg%!K|*`lK9dxbcpU3X(93a3Lj#ySOqEb^-PtA zJq9xb!qj0WW%ul}6tA~P6mA;g@~p4sfJ<=2Bw?9!eEtM&%kACFCZA1NU{2l7{(Pn; z$D8J;rms<839!Vc+X|RijKm9m(y009k0%e~^J#?75sh*9m^kdVmLSvlTa;pW?{XdV z(4mxG{HX9?>ozgl_gq077OsdrXiKHDffwj#rRCz!U;pPJP}ChDQt*Ia8SM{EJhGUs4!hnQ0_XKG}>^-#N2 z6VN*$W_t7Ke~s=$#v~vEfcLzK_5MdIFDTJ&4ViWt?3&)0BSr(Bg!NLa`0NGLQSN{*Bj6S~(4l2|OkwLKF zVrd;o6XCXmV z6H#wBp&vurx3TEWj(zm}sL~&ly#(65k^k_?9J8cfqzJ8%>xH#bqAxh8a zX1*m1-RRhLyGA87^_gzi#p=_Bv3+~%7+hy7rx$lh0c@9CEv0#rVgs&cJy+Mc|96Uz zG{-Hso(Ag1af4vLw&k&iLLh&m=aq9vUzVqX+I6t_6=OGM<4iJVh>l?uFcjq zgauU6wM@VCSHwch42Ml@U))0EgQQ(tQxMA2d84Zbcy6n>aE2IRQ`at2H0*t6<*a|9 zAw-tISyik_eJ&S1&`IQB$zLxzT-p3mO;a@Nzo*DEz@F#mx$ddLfOs`_A| zM>FG2*ndpM6;pB8V)jbAR*+itXhg?~1{IN~CdJ;}FP8d|s2J0)GH+B+ELM6z&jNY?Gft!03$rEk2P_HzJ zG{Bk#jU%-%foJM})}8hFPAGR?=b~JATo&3@rGo<2<)(8ewLEhqi7LxGpjT^Ri%wod zQ{df>+)^5s?aj@GMuApv?e1tR2zG6U-T(fDZyK{qj1;%iNh)7;$+wZ@ycocu zi9(B{U_Dm?wWt}g{|UOK zO?nkHL~bRPaD6>OaLq|VAH+1q<(|kCnBw$jdt#3-Q%t8nTf}xR#6pFpX4oe12jIq9 zmDc8c1p_ip7X2rDp}EQD`F8?+-XQ?ec*OI3`D-D0Cz))#M7l5C4dZ*Z10_DFDn3vz zPmb2W6NILZ+lG-pL@fNT+tp#gjUBXM)phh9V@bj zOR&OVapjb1-4YzN2W|)FCU)*rBtl|wT9G9lZ-5AKZNoozIM?F7^TCW`9t(8teSB9J z5MFW9H6fSOMO^{$a6Y4}^Umk}ActK3P3L~lAUzkI_LOkCa&yfumhz)zNNrn~wOCeQ zv5U?=2a?tvfhD<3^2vhyQ)eP=j?QHBU^cF5fEjAx%*!W6~5wj{)iwlpRwkA(E zM7mx!Ctt*A5wQUdaC^k8K0)`~{qVFwu%7sUCHb0i(z0My9vk>Srw0w3UnY2a4&3qj zjlUDtBED=Glhy*Sj<`x_7GRZ$36xT+B7Ec~zuBN12cgF(_uP{^ZUy%C2#g;ihN8|A z=BM}HcY36SktjxW%R=*#)4%ybU~VX9lS!8-RJSyTinWP{GqLf86mftk;^wp(sn}z3J*S;lXvyGXqfzimT9%jw6G z)Pc3S<+P1sSQ1Y0-1N*r%B$y{(~sv*SA2O}8+tFcZtR-45)H@CuGFNzZ-=2)wzK4k z72l$+^N~B)-r{6kj^QZ-UM5qCWQL zekr*-^vQUrx(<2v_-~U5`!}295qo?TGwB1elm7>_4-Xi?Y3&0=#jYngG<`9neW-oF zA!#0N=s_iTN;NxP~?BAo?poqIhm^ zUZTIX7T!OpUib-`b>c5~e_F*o+hK5?(r?x5qY*H-ADbio003_>;@-bTZeFtt%cFb$ ziy44qE?v}D{kzSuayY@W0Uh~@3S~r^$~^Fs<3ib5UI;Uv>f7B_H9Nq^%Mlv#WKI8L z=AW}ohV0N3-P513A|PDbvZ;h^z8U0hbt-=n6{mnVVkP35+r~b}PIi=tO1-8m3jiKp z&r#Nc!A^5ld+_f=%|Hq8gsjS;^CEi7ade)jJLKe_@$aUjEI00bCl%P@BwZ6 zzedU2@-6(|?bSUP-o9XmJ(F={f?jy+YHRQx61igl-7WaY#&=f|kr z%wv8&G>X1cNG5#J&`&bRpd5GVk*Hk0VAsB7Gs)kBxlKEq_~nGUN3B;KLayY1H{f8J907>RT|QsQoZb7H8$lj3QPT%3 zS)-?#lLWzApo%*WGohESi@BTTOO`@L>(AoZVXWqGmdv+L=U#Z^cE1t=4b%4}aN?E& z^usl28eXDr?2Fku{T8|-sj>gI5I5_zWK~Ky657W(5Xnni$);gb9Si}ERBDbr)^gQ?rG&9u$?S+!Q+Lhu z@b8+~a@~pW5=Z+&I7PDR*4l4mBq4ksrMJ1Z?giiF1N=x5s_3L|Z-lOJPs98TOhl3| ze0%I*gIT0P{t(391hKD@VN*oB8fy4+vZ%)kU@*(f{`Xz<90B(0k`wirl$bi`M^Q=p z&Gyv41`zD`t5Z!%tJk9SFKPx1P2N3UY|ukht&s6ZkJ$AnAEG@MSh`{2i41Ng#-kML zfQTU}#dNbHvQsK7oJ+JblkpX&)7zH>hy(YYS~E1{19M#Tr2G@DdJx2)G3*Z~2|E+o zJs$ZS^G3j^^6l~+D++N=$;%;wRark$dDZT1y9QX&za0^8b3`8IXmlb zC(jvsyS5B*`#8OGq7y#!T#ksN0Fd+hXz%R?yOpM0-;tEQPBZ9!;uB=~!vTwQO}% zlgH_A9}W~9yeOLhmb4WAZ1u#k2SKORB)CKL2J9PlF*uQwynWPUgjJuKem6jPfh3c+ zExzp8nof%HC42}MEFGIaAtGOR93l`UbMio&TS-~UF779b#SNpxUl9Eg!)At4%WtsW zQRVB0s$sly<*pmS9r<%B7qw)rYGDQ%o?#@;yzqqJE=jhAjX~ezy17EW?7{)r1lQi{ z(=*$8Hy+}cB?*XZHZGJ2#zgIBFL4cP+;%{n`Wc5rZ19mUTx+)wzRLmhc1ziSctYa1 z1BHXDz*t?}nZm7NXoP;hR#ucxDN#l-LW_IB6Fym&gemkko8Zlkl*saeAE3zjr>W(&2`F7Ige~?CEfe)%D*ys$p6KCDi<%7Y%KD8^r8Zuc8 z2v^%ZStA|oD=KB~E%tV-AC(bV&(CxABG#4>Y3PKdBV|Kkq?yb zg-zdBmL$}jXg*TlMc{WPcB|>+7XiHI$g*Rz1&{YA=2;i5;VkoXOZ^Pc65uE;bS}|l zMuSAVDqG0M>l%V71_iV>%Qv;OF4Yu$8_qyCP%!gtGP~yFcwJk)$PyT`ucO|E&C_Ul z(A&89PVKz9Z{!-hu+`;T*RNj5I2w-M=O{kusLrfh4?R|E6FZ`T#zr&dN zTOnmjF~elDnY2PHmryan@F8;ipxt>2l#7yc%)#y&l;bS&l2XuMerZ7CTZxq2O9(14p{NIXM4Var$`mp9Cy|=C8h=;YF`V_zLp^u zw-dZRjji_LiQWDqg4^frIw}cELfxGr5IG={?h0O!zv;E^2~%Bme*MVOivZE+nH_H3 zn(wHx8+93we%ws3C!3tJHCEZfCgCOU@2B*Cen|p|)H#||0p_G3?x*#UY6#Y10=#q+ zz06a~i{u}q6g5_jPCV|t+Owv{xyPxS51y*1b1Lwbocnp#EmbMIBO5= zHQ)MWjc@kL7~2(Ii&-PUWb9Wu*2tYuj+9pNw4@nH5H9W+Le zmH>;Y{|@RujSnOldC_6tS9-Us1&-)#H!RP20z8gY4m?W$*q*hkD?GTep_340bn90o z4J)4)W$;vE^2T>U?(~5U>;uiYMj`xXyuDlVX5J6W(*mo~aKngExcvR~pv|@ze>sYmTwvlu;7WD%8SlggiPC&F30XBL`<2D|(x_L~?iX)F?f0bp+IwZhZ0H8Xp< zUtOPy$q{pCr#;s6<*PA}i0{8NeM0^87c&SYsCL7Zv*(bv<8mf=;JAR+Ty1?eDGUGz z|L9KeGH;Fbr7mnG|L7$M=YE^80#602D&Nh`{uJvj&91|qbAkwdt6^{RoT)8Hup%o) zGgjqu+G8u0FUh;1pUF>6PWHt&-Cmh699W>T&r(jk51sO4Noe1~xx7Rrk%P8sTX#;! zX$EBG9jBM0#lc=pmL!~Z=5DfHv}}T_jFN~4K8;3f73aL0qyLQT`QK_Hcjhag3I9<} zYHsTIX#emXZ!rihml9-)1C2!(Yu%XrpY~Ewk+nV6QB63B{%?&(vI$fa*Xa|?F@{IN zeTz3=G2)OSbx}I^q1hj2{*#1m#f3nd1M$Dd zL!gI!8g|31X9<0;D87X)zM?wmGo$0Ade)&LgW~Ny*MjH)S5s4XLNVeZv#vau=U{E{ zCdKhY%I~`Op1L8t4v=}rXGL>xF15#*+B;tA6qSn*$f|yMuL8*AN9o3Fg18pr>u^yo zZU}VQ+56Jo;;t*>-ra!NH&WJU9P9Bb@B;jw55rU3_P^~dFFwG$xndNrf%6rAQ&eS` zZP>lYoV_@a0&ie!-Ny~zvzMe5*AD!*peNBVbO!|XM2J~F;jv28EK+&6JSr%4=KBJ$ zHGb#M3gb?icFfM|Mxn$mH=7mWW~2qHocJ~~zSvB)mhkCw7(C|9P?^U7 zxZc-mZw9@y*)`45F>bfcKFT{j07<=JMTyfh%!^mQN*H}liS<|{ORlpy%Itpu{Q~)d z6N@qIRFS&p%fSZe<0>bim-7%_KFNL5cB$8jbbf=ni^$v0?Ald1N3SJ33FLD#Qe*yL zl#8P0*kKD*7ILlR#d8>3N6=p zI_zO3{zYu&At3kg*!nV~Lz)RnnZmY3?A=H5&kzy7KU@wM zD@PZ-O&Mj^%jI#Tu?4hU282OwX1to7!0{rE{TM(vrHW`8;)3C`vYb|< zybn9UZI2B@t#$wu?V==22vlxZO&Lw*P6MCXBM9n0ngw6Q(myFVAF;^OU;)@0{FDzc zJt1?`^|tzcUyd3&e{HKdt2I}7<(z2k=#?#G?Ypxs_n3uVSgk0wbn@ca#hS&14w>m9 zkjk>NQpwVqP>^d)U8qR^Epzl}!c!3Y^1D?hQx+z0I<364?zDYZCB3Z6Yn(&s8z63{ zK_WROePOFF# zf}UahKX;4@D^fWcZyJQNvF<0eX{GCqd>9EDmEYaoqn-rj0|`}NBL1*n;!r`5L5CfG zVNo(+^#_i)?%Ezs3|U;sGcIZ;;gsR(z%@n^XZ2OfR`QN}#Y00}H_xYCJ^u)}PE)$X zCk3&IUCW^TYE%~Be_b)HOBMCRXG6{DEM^o46#?7yy`TT$&;7^J zIF%8kVFFpGZRA6U{9psXWDk5S2;!#l$!I6p3LZY;lDhMC0fs53@^v(@QSCi}ZEY`u6ST zb7(TiHuW>Msqg{~O_R!f2wUI@feZGB?tKE5zm?l@Wdxhg_wC%n4U3)$v>M_SLvT^sNHOBbP}8Ro z>i=#w%0xQ)Rgr0cl7n~_WLuhnVWV5grv5(=+r-^e5-pWa?2FfNKR)Y0y+|yPR)qzh z{rbC%T5@hcg-N{sYJ*+ll{c03IA@%Lw@)%M@&3x#{Igxn+R5XeM$`9pmcT-8^)n+r z-QfYi5*!7+%?I~$j<}1qBC#jUYpCtcpFzOg9J~8^$4+@T8~gOWB-SRpl_zfJcC+rX zBdS?!z91r~SA9|Gsv8TpJ(zv}5j9`(>oyy$=px9ZC$dbxa7)dLa4VMUM*l{w=m0+{ zx~{+`Vc2cu5coNl3)VXfX#Yaix9EmUCeJl&<|;k2ULeG(sK<3zY(z2pi2^mc(phM> z2f?<_nxWxeeF8r{y?bJFMhF*E@+IH$OuxnB2Nks&4GESM5@*{HN$OeWF zKDO`$&N0TkgokkCXu#A%-SiROf(DnQf@5hqK1e_dw}`)9w!v`i8pYhnx^W*xIIGbI zeFi=2eu3?zd=u;BD)Ip%<2w5F|FoK$UiiNRrn|w*iqtQ5afeFy%Y(Hb@ny4r464%- zeAV4sFa3aY3*fpca8&dU$MS-cQAkl_TS~JW{EqS0bw! zulxKPCN@z@PiWv`64jJ)oR_5 z`)<8vN?D7rqKH6s3rIkI0|Z}u_EG*{+_|!;8)@gB7iJpUl;`Rt-KwaNPAd3)tiZQ> zq|>S|Na8uI21#*xZ1bwdI1n#-=usI3YytQ%f*ylhN1;ETN;1e(7asE(T*0^v6rBne zgjl^64x9{hDz)fnj;NC~JDm0R=<=GN{$4Njjx6D2w);(M*J;J*6yC|_19`gL66L8$ z;54kVvpHcanFCVYPKlUhDHTTq^`QSXYUAQ*d~_vzV(UJF&558Q%mS{E!4MroIWRfW ziLnzrF?=!0bsR?3^Zp64iROLWkDEdyr*V96@=Xx?p7Me>n(ZVqZX871=~q_F#R>li z3_01{V~jD(%!`OvAKcXRTz6{4(H{?TDCF+Q!F3%de+|MHeAhbUk0z_+kF=GJga{w!=Zdo}(S zrh#=6?|xv9^~M)Z#2ju8<>W9qgUku`G>5n0GN89oA;b`RLkpa2e>wT%%COjp?`wp3 zCi!oKP3uzR)A?d?&vS4()M^EOYkj`TAw9tx&ZZC6(=uD8uu(Pt68r8}Qa5@989IfwF`!hVw+r&3?VL-v@PV{$2M8N96-u_>K+}+eG#Q$3id*Q;28C|fY6l5A6t8${%>5yd3)TQ!Tz+YnM&sNTkvz>Xn zw-%Zg2926f=>eW{P+)UCteg;NRNnloAPM)i_>T*;AKv$lYL&DX=ki#nnp zw+ElSBsWCyuv&@u_TobSnC+Tza3WCl#s_w^$oDs`NRD#^xn0Dq4zbV)K$D$I+5BCz z{-ZB1n0?&Tc7(l5hNxjK5-c%p!#qw9=x554?HH#xIN&V%J$TI6_M!MK5YZr&5i72E z1AfNGo_0)fdzc^_X|N++kq&Usx*?164xc-3M7dfycB1YM!B;3c|A-KL%!q|~f zz>6vBZe$uuMqdkc{YSErd?pfAPzGBK>L$OL^%ckM7Zx8d@36NW(~yN<++|Ymw= zMjHRMD@!8X-^{4cm(|_*lw49#f}MA9e0c7bag|TV0tOE`_IiK72wNFuy{ghlF7G}|#7gg}m#pPDyYBj%}y97a%*25%pR@UsHkrR^aKpszovbJz6Hbm5e z&@%U7-bzU`?8(|TQS_F%;!;T_0ahpe{Ad9jXc9hy>-w+JndclCXp=QrlRgT`tX&XE z`EK^vA~2SK13-9!SkcQxkGzzeAb)x9brzb`Ge)T4W*t-AgHC5t*>j}Wv|2UIoSQ@2 zq`$k<8j~<;B+L7CCr+#)jyBf?2uR>>-`c!j)+Bb zr_p>faS+Rw*fl>Qv*$6VbhFvL!^ki0FAE|hj-6EQcr6jYT4()jvRM^MFG1IN+28wx zcY9BC?B&dn#p;^43GbzNO*F=OPpi`d2?TVqstU!}pJxBe$b`iid;Xs6Y9O|X%RA5s zox<7C#N&|`kN!3C)fo?0X%f#IL9A8Cap>=Flx_IIvkCA(EwPtbQ_--81H_cxpmLH-p?^D0tZykIuL#wTAlU@lEog)h@n#6F~ z|77?~v!DI!_wv+3KR&cfx#}mWao*9EF=drggazsh`p&;bJ(XWmoLqV;OI%n%+8g~h z2CaYA=ILj`M1)l!3^yFG8X~{;J@?0OvxU>EPYo)^|K7m7Gb}k^bA;ymkQdyMCXADz zmz`*i4Y_a9HD;6U`dQ76B08kO;h%R*IKCWwvYI;MnEV*8px2F(sj3bw*y|c+j^FIm zSi)0IMQ^`>L9O}rM(*FYE7Bn>k7E%eL~Z7#>@rW$b*>w+ zeL;lhw#568SUX&sShf=*?kd5K0YEC?H8Lf<271a)U{ax1PTV`mi9YMEj+Q3y<+JTS zKc3;uwzNi3M;%(fw+ZuslO`N+m$Q#ILif2XLeCEM^ND)>@91z`!d zf=?ECmELRZIeJEEqv?5c(w?2=f3e2a?EMi-rGJ!ggub~{V%BZ8Q%-ZwcRj6=czm=jn>#S|g79rFAFX8|;i7JKBL0F7>ga+^Z`MJH+RiYpUJaumq3ii|=J4qGu%MYBdPcrDCvF zMzUpwFZOo#b0sj?(b{=>mNnDhHN;=2z`YT_k7&EdKf;lUISRcnH)S{k-1H{=wgr}Z zb{2zDhA)yKA_4lQ{}K|jlX6Ps2|Tv4s_cEVwRo9UU|9M`rR7zW@t}s-KkssR;EtJ9 zfb$1(ue*49@2Jzky11_mX4b`z(yEXA1+yWBC|OZjhLF*qiz@m#C2FY%jvuyu@1s_-)Y&u?EW{Wa_xE&xOY=xl^gT}qVq_{p>`u^b3 zz)k!oy{GNw4FP%D#}j(-7|5xSOK{v-Ho9!u4E<=ZGnB`k>#UNGE}untK2+GNIUa%U zJQY^x?gJYw#O5U@6uyrBDs1w~2>G+`lf=@N*0Z3<9atA*eQaeXS6F>h8r})3-YX#H?0&puJ~@iYPgW`EBbVdy)Mfi=mcsQJG)Q?ZeupVuq(Ij zJoGjy2t(0Uc_9{;L?sjT9L6s%pCkxWX@F3)6*KQO8F*2PD#e}Yyv~ba?ZjxheaI;_ z!EPF--A=bT$`FxMM8?>f!#5J~OfD(aJL_&^+8$uzAh;^k*+ zp=G*83$uJx8ZbDvs!#hb-1Uy*K3I8V{1ZN=lz*+Ovbj($^%_Rp6GZSAs7?_2C` zRsv~*$ElZdWKJlqoG^d!v)Dmf#FyNw%m0))YtSJa>6vkWlLggxd|A|-5@hV48_ zw@nsNqztQ{gFDFWk=qXc_zaoo@;kJV@XWT%stJjr=|xS2nv5|fF zP=_WOD~%^g`a+EubzmsyW))h^&Ed{6E=_g3FBP~JG_OJyd#3zrbOok-e~gMG{}7kX zBD(~ymz+6MqkNX${m&MZtLq!u@21hd8O6*4*7A5yv80!S@n1QhY~gkKPSOc8d$|$u zmu(VD&f4IAa$5IJ2^nfWyZGQqdMXu`iVV*$sIa_M8y=8 z@1|mLdk?O-c)hZPq$V4K6D)3yt1L4r6`xJulwfS9 zU0)O7x8C$hgK6`WOU?n0I*r)i7yCw6*C|#JG%2Zz3+>oR&NI(JJ>1bWNf+6-$3%arD%`6|X0;NTe*aMzTWLo*1WYgX?k@u+PmSkI ze(H5!vkh`1>m$bo#8qj&8trHy7B%6MICZCi2Oeld%4U;n_7*Wr27f+U7-T>~cDOu} zphzQf#kJUtzdql+*E9cy$^AAMm|WR&qs8gfSGkavH~LB>g8-VIy7h$h&l@FQ2@wn( z|4-S3WT%$Wn$83iDJlR4pvRj^-!ugXkZix-l_yc;0% zgpbBQw@NanrpMq_>QvkRVGs#z_vDx3=3*&TD>r&MNoyQ;nB?ud>4p(SH1&KRvb^|5xC`BzozF~t`Y8L zwA9`pupB#r!cEn>vZA%nqjlfbz8g|M+C|*{-^6p9XPRter5+NsNC#2 zWDi&6Y{;!8^Lew+%$mKoQc~+De|-i-bwsTu=aA3Lh>fUyH}rt8x2X&7AtOWx|A3bv zki865LP*A<;DUpyYjTP6Qz$*~e*~9d#uq8KR^|I7T4iv%MkSrjjWP1Y?Ilh zFV!k4D<@e)KVL``v51gM`bhF{8_%SW;e{3HWm=s*?qIv2 ze0;CnPC2kf!`|qV&~roByw_5etRbP%wUbXjjW!E9OP3?`Z%ch)axCENce?IjJN*k# zPaB*CV+2f}|5vh8yh0ptuwteLv9fS_dAiv;dj3ODzT zwl=po00o}nwOWL+i{|2IGQMj2fKyx{*FLgrH*|(wb?v`;qNpq)RG1n@DytP^VE^qoaF6{3jVSpXl;H-XMu=Zzy^S|OOD7O1f3T=VSS9gBtF zuc(z9+Y-VSy*QT92^QSrf{kOo`n=_LeQ0sIZPtlzCP0hLKYP2{>@V8#2Xf)qrfKac z?`#0dD)ac{|KsS~874%+9=*u|S)??Oyw> z^AFwy_lk~(^Q$BB9vhNpBb`T0ok?m|s&y0uYOs{CeHVDVoN!BVuPhJA^utYdK(+zr zLbZxvZ!9!zTv{uX_*o3ZcKT-Yz<5nJ=g78Lx1PO7xY>^7Hfgmi3pe8un^Z!(@Tz*e z%4~h!oRK2q!i-Z9%>+l!nyz|`uLVJEae5ps^u7xhx5ZXJI|z5;P@0RYnu%rQ@EgLQ z{zPLGg=wm4#k#nhln)4~&#R;sHpTQdzDPYvh;(gr0@I|Q)a$3Lkmb3L39vbI>B}#b zs{3%B*?E{`$r$f+m_DKTJ2a+|dx@JS6uCoxK<{hj<$2l$sm zyl=}c7U_06`a5iMK?>AOVuDp11R11ji+|bX%_KvhcH4TOZCY5!nnx9A5r1s5&1>RD=BYk&I~qEn*AOJ^B3j%)vH&r znYl`IZlW0j!Ai^QsZg`Dc}9;?MwV>c@nmKZSt8PkUkOPI*szK^6cX#e^3k9s*#Owm%r+Pt?_Ak`W>TXSO{LotAZka$XiZM3IaGgx97AnVL z8>68YBV!XC1Z@#T!0j=8F`DllQjAm<#k6imd%s#rj{W9MLAYEaOi?gA@-RT zys>u*l})Dd#SpcOHcQxiS29hRAk-a>va!WQ6yLWyvGY|B=?h+GdX6)uE|4;a^AGsd z;i=EBV_XacsseazYa1S#0tpLyXX<#wG=}gN`(z#7BpwFroTmExzv86p9>Bz)&5&41 zHA5gje^Jtc#R?OcnXZTU0DhZ#kaZDE+0m@52uL(VD;9{ z09!2ix#gTxJDJR6J)=o6(J+;aAF)5X z?McEE!J4QQXS&LIvnzL=I_)ru0nn-!W`kR*3WhN|E0f}1y{i{e7eF2Nz13kiO=AUV z^_vCiT=g5G-beTyK6x%G;rY^-oidzSLT_s!*MR^9O-b6mb|&U>%m6vz(T$LbDIS8{{`C3Fu8 zgEc`wi;Cql&eNGBF5~M6;yPqrvmC}Ax)1jAPfA8@mb$;;oPv75`1X*8(h;wMTzeav zyk&`|8kP)IIAV_7S_D@07|*}WpB@`*wETL0E(FW%TJ3mc;|dVD za9=7Dy;0HHarIymKWRD1$gC{@DShR12hzyb9Qt5<1|YhDVI5+B zF3iSsbKBqS6nQxEr|dF5@w;ZTI$eTW{fwMSrq#@t(t|!ExRku>7*4V92=mhk%6^AuKd7iC3y}7=fF<7fhU`_0RIViPY6Y{KaQ8X(uS?nLd)5! z$6!jNf+=KcmCBPwLx^;yFD z=||*0ywL7|>x`A-@FX1JZK)^_9O!?WDK643Jh3sO+u~L&DgX?o#D9+Svq8C^E0&L< zg3hUt7WN^PKl0@Y_qzbBxX-fx*--Y=BQ=V6$Syt%KcjnD;r6a@<}5-SS{d-eoq)ER zT6yzsu{+-hh6G2;QMQhoWR11J#$)=QeE7o*vRe~4_MF?Qp|MP9nx;9G1GMZw<=8sO z)r6BntLOJyX1LsScopWv>O9KeJhy~#bstg8tJCs+L5P7+WhcX}yc%<2J0%9Kf^}JA zKwV_`qO7c|hQ3!i%3olm<;3PV5P>~hb!NQS{dK{Lu4tWUHSKZNF{>92H0^A}!E!W` zSQdq#5(epT8fRPQ#Fs3rJ+aORy@;-&>ECs&g}epz$bv3X;Vg=nu3?=G+Y_?wW7l{MRJ_-(wp6HNRhe35##c?9V+j7OWhWLm|E z7cymmbQpbP@;|+QP6Rx0S{~Qp1;~NO_QTT?)I?N1`(kKZFNxAbM?p96tTFN1lyr{wVuaf>{T`S$70_p|t{+9KNPcmt^~M((kBX=S zu+SW#jjL+p?sbNSR|*HWGAQ|F_bkrb?#a6&;jo?yNt<#&De|1|$s%1K3xp z?*v-aM#!Vog=Bl(2A(GCO5qcg^*PaL@R%QD%?RASIQcH?c=&>hd-zlExD&+6t2;kX z|2)iQi3vrl+Z8X1ww26RFJYa-ylWY)9wmLlw&LDzHZ!w}F9ZIe5d;rTB1Ar&N51iF zAuAV#D_<5qZM3z?8oU1-9Q77*3D#lrq#Ix)HT#wrtm;UvrGFjn5NAI*LD=FFF1$oD zc?rsYy+56}_ zeC2Aq(UBPsYmlEUnl_jxqzDV*96vLrLh%ltgW~MhFw0NF7X94LbB5hV)@PDTRst!; z-_6K23g<+Qcvcp&PNaGwA09)R!?ttD?gmg1x4hOpAr@m9XD6^1GqO2lB(6>d#IgP! zTzG)&f=;qCqF`IrTfXjc1xEhWQRf5)65Hz=%rC@OD+rCG)K zFKjpy1og+UTjfHqVJ0^vj4uZjfDQ(Pmv`Lx)Bh>#eyTOmKTfl+|4O&Qghrq=&vEm_@m|EArB;G*A5>zxT>sh2Ln z^4@U@0)>ol@pv_>+hhHdKLYzIb{utvY05_xr&8J3RB?1@kRxkfN#;ax$Pn_+jB|x_ZnI$S)C^s zMvL6jYE<|ngwYk{!*Djoy@GgME>*+8j!+ot63&E+3@+}W7HNExcVz+ zE~b~{<(FqNTv^XY^h8dj(QBJe?hjhaAaLeZao?2`hzLy8>(s1RGljigaBOn((?yrB z*QLoel&Z$Syw##P|IgRbEG|+TVzdv zLTSx6lk}saH_H}k$ZQ3JdqkgywDE!?jtS_fGv#L(V!Ah>#Rd73?;ZM8 z;5k@UwpWc>hL5YF{2dtpW{Im}!EtkzO-V@kF`Q7 z+_=^3d_FKQ@`5X^Q|f?k<~H{y`? zK>;n8J*Yg>VfRcEk|{_5P{lhxDnqM{|2NQ9U?HbTL!C*~0eiGUAW|p`NNRpHTGa?Y6xrT53#FaG_!JP>el13=@>PM*Pi{K|Ujxi%7fqJXrpr#?gVeNUb7~Z31sUwF)Tf!q^n@Y18*F}a5&2`l z?{E7tXnF2A4xe>%h-$l|b&_T8@gyqRePT3d0gJR~i8O1ert6FShppJn0W$lOr4FwU z36GSqV=a~T+4sR5GGbbbyRm2&x^(r5?_Tb!iwP^vt(DiA-?m|0f>VM>ZE_t)no)#- z;?w*>D?uOFHJ7q{nF$0ZhHJ{T)y!sAI}>%Z{u=hZw2p@-IvRXQEmx*!H*SBcFMi`}jF0V#{pw$TRzw zu)qVP+J-3VI1B{e=pbZA!>pbTlD0@qx!r~Ukip(YTXVBISUn2V)~2x;V}@DVpu|Vl zj24InN;+X;|IfSU@#|l(1hk>B)Mf?pCcrLx0(QId82POTvJ!MFHYHPr1;p4t-DBQ} zz}vyc66VsMEkdf6(3b8yvl?-qb)`(MsXW6Dw8Kz)5X{nU4d zy4!#%t>(ufkdA_sMI#UM8z3)!wt8EhhHPwfkf^C7?gw7gz16FY^#6h`iIR5DJ*x0= zNi(|V>IE|@CL1xK1+`$HR|c-`Jjtiq>te zGQ;Jr)_60;4<6h(k(ON$2U62Dle^GMP(@v#`;{AZJYPGQspaikHres=;1)ya$c27q zFEfWxp1}vtZo+3+%!>=#qE1-~m2sRaF<0sx_U5jBDL_@v_;YidL+^OpnIa`O8)Mn) zVYrz>mV7@63o7*{917l!qWMNVuzTRZwJ;Dvg^kV&HXkJ6Kuy$Foj;vGjpws%1Je~y zG7_uje^*B8mgPU_0w2ULjsdr9cG4B6zqCB$p&gyNd^A_?8*=wfslZucVKXDbJwOG? zP)WaTZ@_1ENk>6OI83USB1mdvxBJj{mcgl$OrmCLq&GsCsQi&oAd096Wac=%FlT)> zRL>SMMeq5dDiGIF#i5y%GrLIk-&(e3=87hX(m;Y*T(nug3)TBcGa^&rQX}%ZuqX!7 z(m#Ei+pAuqcA_b~V|YLI%>>j7CNzgX`anf4e`=$`)m+)E5#K3>K>-ilXyO^tBZk=1FF{QO6gmV9I)Rv)K=4H_C9(*r3p{ zJ20mmB#V{j=KtM)q`+4f`Mm6WgEMnC01&bFT|8R1M-aL#bVj)X{mrdS;0_k>J=rZ@ zhV39tNiHdBY=dv+cIENrGbo?M>&oB$7lh2hJmYpNG+jX3%!hGV&(Rf+GZ{o=I$?3z zopW6)VG&b z3D5UJIklAJ#SURycp(n3k}g|}5ba`XyaRSe9S(HmkTjELYPjnQYsu#Xel$sDhz^aV zvM-O4qj?jcIoSRE1}8u9ek6FaKonY@phIuxC zjL3^ch@qqVPw&%+plVY2#5N^)d6e6!*&RL07E-`^G4_U&eVqVoMoILyFyLTKlpY#z#NV|7a4*-( zJSzL~Vb~I1jPG2kktvI6jB%VnXWYojqU{Mu|LK9-ptv%NC=FZd6?+5UJBoUEaNBgt zBQ6|L-!)u*CzprA^x-y5X{{>Q3XUv}aOh#0tpcCI1v;W`+Y_VBS)?y1@YG_j-}+C_ zd?B3G<2e{|8At6xRcikkp$P4~)Mp}O_Igglze_1AVc*GaYgKnp)*5FRWr=*|i~nHR znb*NYK4xQ7UB(%*#KC?t3tU3^JPq5$ zQKt)-ze@9wFSIjj`61-lA;PLfbe}S2=HS1oAk{05r4eBoH?qNFdn6vTq5^(Rm@Vb$ zmDj5n1q>07W#;c)_`*fctKKnDPPec<$L(MUAWQZ#H4d&su695Fgl$91C{_=xX68ZR z)t;+Ov>XEi;g<(2;_VD31yYu44C1Yym>t<1nTr7#P(*%?>tvgn>)W>#(04Ns=q>f( z3^uKO!XlB>D8oX7>&g%^rp94kb|K8gtPAUT%TLl%-Bplz@L;W#>j#I@LS`^Mj zE2yTzeXu&k$fpCEyNFfYZKQ8hSx|QwAr@<8ozu^yA4Q8N1qoi=>B`<`!3ud}3a?)H z(OD{Kwok`pvXfc%fuyCu(+BkXc_T?w%u^L9c~rmeYvAQIY(>g!{O!mrWKy1s=lIft z>%_o{q)hdAy_N(~!YRKmI$SJoe_&9pdsHaYlM@vtxE55U_`CiHt z6FiE>=d-L!7QFQk43C^oEI~w_11Mqy8Y6K{*y0QoKH1H}PTzqoxqGNORh=F{krJ}n zg~U`C%PoN$vy9Nel}j+HFkb3iP!TdrHBEZ50?|ulO~XO#8HB1$yooE(0Syk zGnC3uIxW@mHrvoaJ~aH#xed?b+MUS}Uucs2MVGK=vA+3&ArL%l^*9ELxWu@!vkx_J zaPk#~N}A7{*)x1-Jg%)UZ<6iF2?KTMZm%@k?|y=>Me@nuovwNJOyY)G)^o7gg{-;I zp#7IXRnTnj)&BlQ9KGyZ^TDFxljLyWr?37;AG)Fsvntk9bm4?OM_e6(z7KW~PJ?#0 z$%@lKxr(241)I;9Dwa0*q*|w6`XC7ZDIl64fJgz)HvCdev;Npvw!5kr32ow9z1`Dg zFND*Y*lqut3N~ZlLt^#Ax3*|uP>4Re^$39p7Ao;IGwpn&5=BY-qn2(&X*@|aI`7vU zu?BRWzfQU2V2&wuN+1|rGhmw;QLd8MJ`UpJB362Wq{^+CbP!Oru@?A4TmXSgm#%vA z{UA3L*6jGIhWz-v=!uer?`z(l0-bg=_*{=P+SIQ5x3BH-MaPS>n-_F>#Ll z+EqZ=!Hx6>Tc35tfYL+{`AIUL1t*m(uutV?>Tbl3bNgjjr%b; zuI>@o_#XX$N^nemmhY;#e`D{UkeD54qZRPuj@fi@lJkL#tPwxV9_+hU6P01}SZ7jQ z`CIQe&`dz0;cTd2VsP7vF>1|S4vsL3dQQgX28Fm zWZ;H=grO~f$&&V*ix$YWVpW%N2B^{aB**{3N;a8)xyrpOn#ESWL7>y_Hb_)q>e21c zcU(*62kBO*MmOxrWupxzp;xaN4sE*Y>ZW9Q-oZ5-Yl8hVrSk-?-3b+xGGsON^@^|8 ztp~TznAOVA2Qiu+-$gw)l$Kh~qyr@A>@lYy@S<*9>2BMBScD$g4b(mx0LFX;;S>sf&OcWUY7wx+iZC;p+?#N}xX-mHJ*S5kTAxq}R6179l zs7c}?>*mkUrmGN3kXj(F>Rprlh4KHZL7W1?MkdNqX7Al##t;_tgI2LG3eDhFE+BF0 z9i1qR8he{1^A~D!4(etuF5d6i_k&~>M!l%uUYOrgFIf&F_N!~hBRY?tco*d#eNWV) z;fK(EjDqNalKk>)|E-%!+Uwf7a7>zssyt;elSF~~uIC{-U;@SJ^sF^VkWAKj?0L#~ za?E4|qoVW{5zgn>#OEdqVc*?}HZz2I=GTC&11Q68KWVI$qk%x7Z>AM`1@iN#L}BMi z(Q%XBQ83wVwzVrnLG@}~h(DVtXDB;k=M(iYPF-?I>BId@-Yn9kpB&blXZ0wHI%^soU*^Cxfmst^vaB->WEw;Q?O+0VVKr+xh8<(+!Hy-Y!#N>8wfGs_9nZ(!j^(~?x-P!-Chwq z29Cd5;ZXCwypmj=ka;H(D(P}`bm}@{y^QIb#0OB(RT%8mj%PdL_z9!N`C)N3*|HYe zq-ok@2nE6}S0$dZ(cJh>^6CUOIP3+C3}|LQ`V`z?Tup{v z?Mv@~iKisG^t+iXcIGV=RV{q>Fza9xdKG_u*b$#~+oRt3y_)4Ps=KI1O&0g5QHL6m zoZQty5-u>)Q*xeV1!ABpRsZRof^Y;(sNQB9_I)+wZ#(?C_h)s|;s#t6vIls4{dW~g z24&{qwXF`0Fn45ix)m_N^3P)W99L{jU|GQM>=`uqw><7zp2;-=d*(^S$`>njH$0zY zQDLf4TO}I&q9kJ<)|)=TRpg<@k{V+WY6)eK|-7md|@R1_7^at*O3_k2$Q8?94v zn%wz?l-1C5+)mGE651|e;#~)~9cC%HUbnJstnLq}@=F}0b>nM6@i~e%{1>e_W`qQq!&ZMT+Iw2OWe!} zB3izR)p=yY=O=V4fFh%$<*T)_0`2|gp9Vy|*C@gWL3MqQWKDUpI{*5mErXnzk~|2K z&0;^FfYnnIa1PTYOW^vT9%FJyI?SrLIJu0t%5fejI6z>WRR_2ObV|i z2N9Sp*XOqG?7=%i4b|*lo0{j2x&&3XJ=BA6lRqdBEmm)(XZv>jl0FP7!Q1_<=yKGK zWt90qk*etDTyg11!O_FRDf0jd+%GYa^b}yFI*AP?jEFv`qTW6orJI*PWngyEWTsxo z^oAj!C**IX@J>^eR8LuW(->HqD7QVo30343AV5Ph=Q_MOI#OdFaT;}+yag%-{+5Ie6zKg4kjr)ok%y(_4?rBF5Il6;gzAUo!ezx=EU$}8;+odyab z|eLHIE<-QaLAongk%@`583MnM8lzg$n+kd#`Gr6J}V zNhr1Adim3PCBmu7+Ej*t3Ps6VzQJ`W!j$vUD23O!Ta|2>Ut^k=eNt*5tqbGn7m!|n zWq(A^K|FpeIUOEt*R5pbl)8*p)RuqvK^IzQ(Y*W7;0Djuc0h$loE#ouwpD1f>TofSzgh7_WY+ey6c%!^-$-eP;Yu%T?7HGXlqADAe4FrYh ze=jOOi=2wC$;;44P!ZFmzglzRS904+!|gkIHaK%xB*K@o^_zo7;m~Ma&)L&Y$p7^r zlstXVWZHOaKAG8^*8)jSJ|PaD$(YczSt}cF@Ql3I^48Ydz5q3as=&-uEFVuBtTR4e zG<^>F{&UqtEyj5(pCl+Xw|U|H`U#GmmduZ7|`t5WE z;~Sy)zR?PZ&H^IWJ+>11MsLg{_$Xy+afuN=cL_^SiCa^ z%rCE1X34AHfI9(DEkaUEmHpF0DPj@Hcgg$BysfR3?i}(N20@p4lBXXGxmKMX-FD}Q zV}t@cPw!52h=KT0#5{JZ?QV&Sx)ykJ*tq_Xyz&Wo8c0G^Zd@H3b$qGMWS2;%uVP$z zeK9FRLV*4$G!C-^CYZJqee+z$oQeq8)A@d9_gBnGF zv|{ULp#^3I_3E#Dx4}WMBUyZAJwJ%OGbSi1Fth^EE@oEn0ON||KT(oDk}r9jI_ZcI zNnynJfw>S{w{tX{4h-#zQ?^#09|_7^wR~W|@@4q4dz<2q@>`$|j`XXZWI4JbExe7$ zs=&2;+K*HYj`h45{rJ)jbM=)J*?f(I6lnzm#|HuBsgZDeDr-W5u=NtC2We4ev){3Z zBpmuv^Y&~Bx{os=+ebgQ5L$xRkNin1RL}lCX?&X!W3X09q=6VG;J4IrUJ&Fa!l)<5 zC0Lov45@M40lPF2KhV9FUx1g42>PTY1%%J9?}j-6e(R?|RTv0j>NmFvs^ZR||D-w0 zETRPsiC%^sO?5x~0*h?*Y{nKxIlY_#I9 zfiiV(e>gy#cyEig(OUkVgsB;M&MA1O=<4rN-q(Sw4q!N1s)UmJlIJ z{8>%Xo<|JZ82@h0{XeEUlPiLih9(DJ{nti0~*NH0+3#Re&_`UoxL!{w@=6>x)A=KVIY zA(Z=pz9c^P? zIJI!UPQTJ&j6emeL6i9GV7ItDT44a#MwtHHhGz5J0?q7qp1qphiREN#W^0|Ed_i3A($^=n~GY!|4w}U7}#3B5$*|=s0t7) z9^E;#{u#Y_DXg-&6rOuXkq2~?B(=SbU8NUWKHY`mAUPda;k-qHIpO%WtZ2BUzu`nqM= ziK0y>+I~H^Y=JURQ9S9f?b`r0GC@-*{`lTAJKnS@`oYpBdn&XdlO0>_RA0ak|9*S!DbOh zMO_j-^Pw|&=>)#Zu?uqgGy|ui;x=vMT%|h}wjyn$s@SN2-Csa3ZGHy&#>Syr|D*30 zC>-Lr`R{98L=vrC1tQNpz)oKYmRu9Pp|DbWOus;El<&qI(7zY)b} z6|n^6r=*n?r<;4dt>H8uh1^Q&4oX^i(GA*km&h2@S_XnD`rfmfGf1kM&Gu^l$Kf1+ z`ui956?9(#63M$X446B=zK*l0cOn&aNCi5(d3e_Qq`=GQ&5gkmCEhIQ>rab|hwxkU zUu&{SS?x_@sx$9r;huMQN~Spz=3{eKWCz=Pt#hb7fi}v%ng5sb{4`TkerF?-gS@n8 zm;@ueAY!^aWDUEIt(&vkeYvoovwm+ z4Cg^-B{gm0C$sX%vVZAoI5a*LE=rONQ_Z#YzL2U4AP6eY`MP9i8ju{W!fIh#?h66K z%rB|S^9c<7f@^l6v+pkI?q5}#IA!s+wuRUE)gFvr!E1JM4aisJ-`{?EfGNTQ`*8S< zXkgs^;#{;pd^l4)$dDbUTP{mxeHz~U_p>@V9vY*pz%(~rA)Hv9I=d5zhkNAt&PO5Y zLJ78om0achuFxk&5IC*Ec9dK_Z)gRB{e;Z4CMx5M^PHPas=4Rz*wMjmDHu9}#HX5< z-^ujhaD-Q(5NPz_?a4)a_(N0CrPR)OzLsJPNutt}m78oR>tqm0Ta*XAeHh4v`YEKH zuiNkE3yNb;xm$#g0Ip#=xjaj}Xdjsw-T6Y@?qA2$LXN~$G2L!^U5m?0NPevsUd{)V z&0J-zvlo6D#Q+AxclN@mP%vZuEHy`nbsmf8 z)Y$3eSWV2AbbRV9i(Mz_micq7{$Qu7Zjkd3w#S%oslT0n_-6H~oFCbiN?7WA9O_7A z+~o-KTnB?sJAiL8w&sgYk`U8;Yhv}bv_(jATAp$6n-wHzr>3xHrI<(!65<{%W!>cI zKK|?x@n-=JHuwFc94ML+~SFVh)S>FNeh2~0TgV*3RF!o+8*}-W%Wwsf10l3iI zw{pCaXK4RZ<;shfX^@psA;US8b(G@Eke zEkR?YcWZ}FYgj!;mOep0MX9KloWGou%nFq+1=WllvgWS%fP0cj8jXHr9ivE`TKGt9 zzq_BtVS&ZSBWuq|Y01KzeK7tkOF6onH)C0Dn-m{*nu-{^ z^V=s!wvFvFdBaHNF0j`(Xh0PgY)-kF2#@g*$e^H%QD&N4T~48L;~>&JkN?+brwSDP#>ZxgZvh_%(In(r??CoJch`tlhd@O9tPVbixybvBQV2cmM!&x zzFiY|?T53E8`tMorTG-d@B&o+0p{Jte;3DlahK#XGcp{~>hr7R*^lK4?U)lSI2adC zc}nZ}p?6$e=dX$%tRf18SALE1vAYU`dtw>G_el-X$=-Q7$DOR?GT{ipJ`@AQY(OVj z@;!%-F(R>*EJ4MoywlDY%5;@$SvBlBzW5oL<|8k$ZsL~gLfhlmOoGU7V4e8A7{^4H zXNl2$P$w>_$T`AH;8S>|Ife(ick87$FXl|FAFF)H5lSdTx>T_h%zzb&L-{%-L`19a zh)soR&?9nGu!N2o&Og@H*zNea4i#_nH-oG4UDl<9dB?o{wzIKCUGu^ZC;1wu#S^WM zb}1{NexnRrdTWZ(WK38#{^@B>ah!q@PUhDNw-~3b(h-*V51$XjZ1(_HZP)!(sz30P ztV^t~bIau?3RxeF!!H4x~NuJI{1;{s~W{7<@znwU&i1crsZ$Ry9p zm;wC{h%+)uvnFuKUQJWHh7YKN;1STeq6_O7v8!NfGnHpr{fqPbtlpug>I4Y%b<4+- zWl9?JK#0KtBk;j(4eL^v%6GZ?4QPM`r4ZeL-4_i3Zg9W=8=_^1^;KVQ6_>Gs@^@HG zPA|8aQ4foR+CJ=c1tlrA>ojOZop`u>$nOb^L?G4dDpbRH&r`G zE9rzWmk*(&u?Cq`W0WfzfZtfN+V05{g?>l~$=ur8$L(4M_xL z4Seu)x&!6r=W@kro5$*x$|73SQkz=`;cG1*)fpY-&>S@I6x|uBm$VAn0B)#rl&*#c zXrpi5(+qwZAni_VyYu6-hOBlz%d^#3VRVW%vR2t8gR&BnR=cc2*a*rZ^~i_4acR>q zdJmKtZ8S@s)QaHpFAG?Mbw=AA|8CKsrphniAmAPl+W!(A{joVOKSz*(D*>Q((CNLX zosr+WaX8O4FeGyCBdpehgRQH|CiR`IM|9Be{INR0HgCK zk8d$-0vcY(80@<+KjXrBVFA)g0D)-U2U5x>*dUH#em7=mCUuDd1DWs0XC3A}- zPoHN&Jc{4Wtp}Xr9jB^nchqUcJ$j&(Uo>X_{#cm9hv5rFuwBE)9t?_)=QHr)YsTkP zq|E}xLXG}!4f_clbXfYJ3Q~s85NTQnRSv7lp_i24DL19BmdylCzJow>mc3(aEMhJ2 z=lO;()^o@`Uz$vRF{>BR0bJXf;QGW(PV~SkPK}zGZckzQm z2iM9Os<(Mz%D857boC6wdk{E~3zXCvwHp9J>vR_&pj|S^1n0bbG^x<+f)b1StL&6k zhov0=%d?S{ymZ@Ru|Op8>4Y4GII`#_QQcJgR}oC+FSIfIM1MrJz;~g)blVU!H|CT0e?Zj_O%g^3Ok&5Okf! zMZu>U@ZrsSC+7QW^&8j>@mxjjhNFLL*cxPL>@E5|$x&^IIQ&zvcJ?~z`;ePc5uMDh zfv@+Y*jMY}ea=_^xfw#Iobsruq2&Y4BStu8P~1%1qbckaj)4;+nHC$rN#)lFSQcWl zF;{H6mSyH^bI@4uI1g6`N+y3Pf3WLSUDkZt!$Y)BNQc4WFY_z9;2xh2ZTaL~@A*nI z2mWq;zzeYpo>QF+8iQ<~U} zo=V@Ba2D5u?hL}x9)0om*>biIFXqD^Ro)-C=Z-!yjB_H{K=Np=66^DMl-L?}Db@i` zXlDkERiF-Q8I(pZi!*Y|f5zt)L)5uHoA36qavDXEm7hnLT^|;GbGDo{ZENLHcnFhf ze0-~I4z4eR5P~cDZa)HLP#J^4+;M?&huKng%C*%{+A{mlzqJw4x{|pQ=%V+w?ld+d z5l?tlF8^kXCv*g2wO0=bj}~Ywn0R5g%6I$2etyUu0l&Dk$Rpd=3>xTe&HgXFnCN3l z%B`ZBy40c|qL`4!nyASx_f?rVU54h)-^@JwJ#qA`(85wcgXmROY8R9avOwY-%{V03 zI-EsXU<7PK9u7GMOOf~iBig*qO8Sb48!7i_4uK5xk4L@_6F9lvK^0(#(tqbF(AxJe zSXYZ(&xoTW;VdwO+zuixQdyE(UM(wU|Ma7peqSi@w@HKbEYu;Y;pr&gz+H@k#d~$} zKX%k*DMH2VC1zOU9o7_p^DTBix#P+!xe8g}jxm_iVXL5Ko8$-PtA@pz4~}QsPc^RT zQ)bf|7>2gV^Z<`bO#EVDs-@M5^(RFPvjf$fG*@}Ac+n<()}K+wN z34C&~4X`uKgs42)b4NkxvH{iQMM<48$GjBKj|_dlH%MnM<|I)st5~|o0807K7p4q{R*$&M8tAbskv|bkSy%C59m?pDg);0?5RgDJ zNa%t+kCP5{_Ca`2?~jXc)@^Yf%?-$#vOxb|wmK_063vO9*P-_k<&I~lFxvR4SYzzg+Wg{cuker@+w;^tHPg_Azm>r(ElHE``&$qVvzuSU?si zU6yTWk?d|ToPH^&s{bcQ1e26YtlQ=CA0T$0vB@j&Nfv5wClJf{307OEK4r z{wE2-za-WtHlK2|(DG0z6@`ypuq>9aQ(UdNEOXXX-PaoD*YlUpgMRa)cMEM5W$wxEFYN+m_*%#wBuRt z+nhd`g|pK&ZXdhlAtrnhzNXK^KU|?zPQuT%=Rsl77738cs&5+ZQ`5CP=kUoEQR%lD zmWjh29X3H!#v_ON9CA7n0O}lnj}}Z2VPUPFC(Y=ln%}i(414tDAdb)CsjypZSORhJ zM0VcMdSU00jYzJcVN!8fwwGz`e|na)7vC(2>h~#7H*fS1n~KP4-{l*YT^eQJKIjG> z+Vh(Xr|G7*huq2N2+dXf9SyfEsbZDS=jIsjS37KimE?#!1oFUX4vuwuy)(QZ5nTBx z{=LkH{=_T@B(z7NUCcBkyl3J{FgePU9^5-9@7cf9PWKEQ#bpK-?`Oa9E2#;u!**AQx zWEA1r(m#<>r}5U<{pk^m>T(4a#80#5GJ_Ir@G8pJIg5^-IuvBb{_1M$-sasuGGp?= z!Hkl9WMd(w=qKEE=EF6}Ah32jE6xErNL!tjg8yPj8uB0zIq zcR_4P{OW69XpNy_z_QEra6rc|O7e)g7w{_qd0F_)kuVWO!CmUvZLouc#}I(jx4}I9 za=F6@pyGRq$pU(tGpv0d*O3AFT>vtH1=Cv!?y3rFRTN^d{tN3n&)n__GitjJK zWw&)L^vUxV<#Ggqbvx(a_hFf}uooq5(0&ogCLMJ4D9AzCdX=(%=18b$&Y!DnN!4wO zjJ_<;y@6}JESq(?45n1X0uJAVa*eXSb2+bD7Zc($rGhQ!pNVs*Nyw^e0=S~(qID|t zP~SfW#MxCQA>WAh#O}hqkTh!ZRM>riX}yj%BV%$WC+XtTj7*KEDRiUWcKp2aDE-Bb zWg{wSk9?+YklEGrtcMx{waC|ilTSl20+_}YNTt>9LWq4&TIPhhO#{Z0C7-RpqwuHG zuk>f|G+@)DOC7lg{GuN9po!CC)AM{FU|UH69}wdz`A@GGV((J%NfDFSm zj5AqFhiymCk+$Fw$eBwkNKCFGLWsxpiNooB+;%ruX1QhzK%oowU#!KO7pY_vSilNo z0r@T}5X@SsPx+eET89v6RnRUqDr+PRyt7mWb0)_rBk;@CSvN9_t6uP9zPGLanA!~@ zExWTPmjW7xPopNKJLq>Qm7TO_lS$aWK!BsiZp%0iQXGkg_?y(DEizdOw&FQ^uRwH+ z+_VscW8!r`>5<^S`N!_#<+07vUMx~SD{IYe zIc=CnN#~`V&WVJs5^Hj|1%%u1Fk# zN;0anX0yTJm4mcq{b!O>G)a|RYOCSZuYtBd@|Dy}%QJ%69xs(-sr28T-^{F?3UG%f zW{OsW!gtQRz^_p!36tS)Q%(9?Cc{Dw-RFdmmFyGmw-&pa!Egd`yaDjmC}$k2+w%<~ z`-0*X=m2aZ_ZxQ0M>s;qehytpx;naliy2@T(Os_`s(E!<-Zy!D{jBHuVFU=d2LTK< zNHu)+E^;MknDTGIq#&vI8us~X2?NDHT2hc%rwA}0mv0&cjhCK`^Y5RywYq#}C1%U*9i;)G*GLAH=MpMM$lt%565o5U=3j zh=YWg0E`@;%(Ul6S@tJL#>Eaiw#Jj~uPVy^IT|PIMzKVdWOU`gu8>W(I23l{-aKE+;lB@>F|zgSG(ook^x*?t~Hj+T-Pp`Ze@8oW@Q zAVsQkoBx&hL}M3m#9U(bok?l&45@$71Ar|u&N7vtC-cJ4qu<dc?iyZW{}K(AT9ns zy$#y2h>nr189Zb33ivnnsM$W#mwh^Q!^BGaXDTX+MA_*337JX}U@gvzTK|z2h?nT1 zA6(cyT|!a|i4Ti^HfFaGKZOJO$17a~Bo)@JnC2V#&*{qZYh8AKlg*k?k8a?qd(H|; z(mHb!*U1z6(F1(IXZp$CW1W)0DA#i9fsNH_g#?Vk5Tg$KyD!Qb`Ys&jr6!Clg>0YK zYwK4*;V-nXe*oIL1leM>_3;M_7PuT_{vNydtr|XDwMW)Ofiel6xg#7S74h?^@f%lX z6bT3B$l|&SyHL{%$IqbU)(e(8p883u@`GmX3YDE)CbJS~V!7K~>*Nxs1aIHL%`6IK zpHgnqjz0+ec7{W3)XCW1m<^VH^NG!7?%BOJ77BFB>puGOCciniu4M1O<@eJ@*@z6M zg5d=ks#X4Gfk@F0$~pby9qh*Jga=f~5ObwU9sG$hHwe;$>VVZoKl%Xt{B3#h(V-OK z=e~;F;sgEaAeb0Fed52TTIPgpgdlX<{>s(6mkLvAIDeJ#7PDnieRC8q22=Sm?d&Sg z9_>`(k7$(}+o!czp^pj!0z8G4bL3yB6Oa(0O5pM2(T1R>F@l~#_9lc{*~OQ0ewx&dokf{Xz&|rcyY>L9*uBy z_BVL1vl=WhlHQC3Gg)YTZ4f7%$v{>4cB^T0jkB(KX7jSuz~tv{LsB_111BhyN98(z^LmwLv0f!*D3l=>{V%nIBqS{HwS6#U@()Yh|oa zq1*0V!0~=9$t*hB2$No7kzMbbSamH|873~}{CQ#|>sO)e+Gc;TH~)@=PnHkYNv5Vl z7?29<#Uhp}R<%e6nIX_aU>^p09C}K-3D%6cpAI_Gcd20{QQ7pXca^LG#QI4%<9Pj1 zlHW#;wXM&urZ>`w1)85K0M(yDXZ#~nU7 za+*Y_Tp8G`dr(n#kB*x$#eJ|Hn3~>D38e`3npt#94T$cWy;=up?`2W}zze(`xvy(V zV))&U43(oR`p)Qk;op-6$AM~f{KrhNi!&&5H2tD?@iz4`VEC2ixcbvrJ(>tXsSoBS zk7c&bvsqbt4gkt%Hhu_)yH3KZ!J<-U`9a@628+BU^BzCu5av-t&4{%M%yBpHDspH@ zfilAx4eYY!tvq@f22MD_l{FLF6O;Z(n^d!I)qGTVl`{H;ma-1IU*D={^n46BZe|RZ zq=ezNZG3Rnqa)8cfAUf02CIREj``dY5LRb3?}MLTF5%1T z+@Sam&_rA*9I}zDaE_1#Q3qe5Ey8{ta*#Tv?0=#e>;~-!3FpfF0W@a(h1kLF0gOQR zQW;ucwvRYe*Z0NW?hJMByGrw44?j(&fqDa@E_E2K7<_uiRTa1`lN=3w8n9m~Ep|T= zfG1i>+i$$4>YYF?eb94l>}-Rj0U%t_7<>aZ&o&dOQ%N3QOv%g)6Fkr?AxojPX=SOYc|bBV&)}gw^0C zBloNb$1>+ztS^zmvfg)jGH2A?6#=RY21KMQBjOH;u=48s?ZYlg&YW>MA-M>KDcJPU z&-E&^u@8{*h%C!@ZrIq-MSEHAzy|q!AC&Szh8mpc1zv+h+&hq|N`m3~R>8zoSQcD2xjc)k|zq9L=kN0Rvua`jhutkbGSbL;WacLn$qN(;6CxSrBI zj}5;ur$&MZT2^|Gndj(WP3+~{2}tb$KXnVYO)fgEf|35H&&{SD_@d^`3k~=SU7wv2 zoDw|VCyq|<(qX^}=7O?Ff7~l#fI|2dc5>9+u8^dv%3srbj#g}J+)e-A2jbP+JI7fU zjjg53Qs-BP!;U`$uG^$z?EzDjNywp&e5mq;GON7XKW6ng6@pIk_e}zChp@^~MwT3vL(XO;{*msSM z+uB1-P09z7ulm+JRHEQaUSSMfx|(ERXAS(xo2>^)C`bSxrTDoyJD@66QD7=mRf|mK zXU>maemKa7Hjh@~vO9WN8q}DaA901dunJ>s3Tgjty5TRDqBg#;Hn>?|e1q>1S9sFc zFF87(bPbj=fmi58W~8zpH#FkU+8v4rAFKK(p$Sb$LCB!WJFTuB3!5pQ65Y=qFN+BQ zb+qsN0=>9W0}j*3hZTkJSy4sKTmOGD;QaSMP8pH{WdH= z3Rvhh1%ypI@+FCDMwi zGa5~(F8n{UYH}g+Hw1{d+m2;73<_aX$H_8VR#dQlt|*cTO$1ZrgEYxMx(+*(MU1QV}AAUobQ7 zJE#xPQy1J}UBSRxVe*UQg6jy}kv;~xgnmDGCl>bQ7*|Wsx!Tjqj#Xs798qpa>;=W& zeBP3l^9DNsi{7vyYe1+bN4=~={NX|v*%_oVQ2T}KxK)2NCiA|whO@sdA2)7mQl^St zAeMb!j$E{Dl4N_UXMY^Q5Hg<&>0|B-lB(71#(Qm}u`(fbaVu}<^(4AHNcyOayaTkP zf>Xo0e#r4aYeBBGBjUtLnoYP(mPvW4CV-vnNsg_v^_Iiirvdtd@&pWjVYFLD%;5$u zm%k4OX2L=J3RT3lae)ua7RdNhJhvl{05lRaU58rNQ-V>E7)Am?ChFF)RtyB1py(q( z)MBmtfXnE0hgH#u-LqeA{K(sS&@&3A1gZ)9(Jj5 z@N%TzL=05-+yP{#v~JnO_)XdQ7%9Y^{rEh|XD%tczK}_`>=2zxiMWLq%D_a03bM>e?upIW7LWQP|wz4_AFs-*B zUJC!JYsdLKd#E6)#A|giTQ@Z7tW8cIqy}6#!IkJmoPsNtCiI_g$#c#cZ*GGafAP0H z%G8@m%uNGj`49F&0gUh0Ro9W}Qa&&tY{TppU5nXb(SfAK&W4IHg9W;^kfuyP`#-tu zA|E7JB_#ksY& z1eldMt=evBTX?JMd80+FlN7xH!WW6IMS!0Xp#kLP$tO6#)}gjWkAyT3?mYQ;HA z!Z{$u6^{rytuPf);~N?S;w6ZRNe0oz^P&8P6*HymBKJH7U;wd3w|Vws^M_e?bu31f zR~``=*l04pAlUpphypGqBAjGi2EoWAQq4-$gkcY+2586au>bY9kZpJS+u=m&`iwh9 z!QbJEoXtGL_uMlw69;#vl8pc@!n;=G&8=Gos%`(QZnLUh4@E)P@}}MU7T0soZeJ;|&=HrujYjdkgFmykVD35Buq` z{ZdwDW~r=k)%|Bh#%-xmQJg&3{a#WzoaWpoy~;RRz})~!i*$ct)SbrQ-7(R_u1S}; z4KTQxYO>fkSPllt2;W{6(Fpqa?cst$0y&;xe0Kc?K@8*X`1G-Bew{t9rny_Kx6B@X zCgU&ljX|Js2e=}?pNL~xNaj*d{T$H(+)1O5`)wCdfe4(5`A22qM(sy{=Hh!qP7 z&q|8c^6FpFCnXVErD_=%AM3u}`BK%%Hs72+A)2AqE?s~ibTE~b@?7(($wX=U}yyw7f{1Qr49Lef_J!_j8f5DCt1=4DH?MC^V>8{E5Eq>7)>Idj_>IG?%pJg`K zqeZhQap`!au@PuLBbRB&VQ>gq8iv36RIs=tU6nB6{F8Q;HV#2(KYs)nZ?jN92iQJm znp?@t@JaR(elNZxWS}NYlzggrV~5`3eeKkZrfS%1ge-y>dN!b;u02@wX`@BYe$$W< z>=w-k@vVC|4knFo>!$;_>RdcXKU2W?o>2kp1NJ<1mp~It}+pw$@7;I*l6;lucDH*zc^;tdSBy6Z}?>-KDg{q#huvlg26cvA} jX__)?pLw&IO~)#vUVgTh0M5Pi>2yn6ZNGTvzvur4-EGwh literal 0 HcmV?d00001 diff --git a/optee/samples/ms-tpm-20-ref/Samples/TPMCmd-DeviceID/Platform/src/EPS.c b/optee/samples/ms-tpm-20-ref/Samples/TPMCmd-DeviceID/Platform/src/EPS.c new file mode 100644 index 0000000..b74e04d --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/TPMCmd-DeviceID/Platform/src/EPS.c @@ -0,0 +1,285 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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(_MSC_VER) && defined(USE_PLATFORM_EPS) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Tpm.h" +#include "Platform_fp.h" + +#define DEVICEID_SIZE 48 + +// This extension is needed as TPM2B_STRING only define TPM2B variable when #GLOBAL_C is defined. +#define TPM2B_STRING_EXTENSION(name, value) \ +TPM2B_STRING(name, value); \ +const TPM2B_##name##_ name##_ = STRING_INITIALIZER(value); \ +const TPM2B *name = &name##_.b + +TPM2B_STRING_EXTENSION(EPS_CREATION, "EPS Creation"); + +// Definition for Device ID value. +TPM2B_TYPE(DEVICEID, DEVICEID_SIZE); +const unsigned int MAC_ADDRESS_MAXIMUM_SIZE = 6; + +// This value is used to store device id derived from hardware parameters. +static TPM2B_DEVICEID deviceID = {0}; +static BOOL isDeviceIDSet = FALSE; + +// Read mac address of the device and copy over to the given buffer. +// Returns 0 for success and -1 for error. + +static int GetMacAddress() +{ + struct ifreq interfaceRequest = {0}; + struct ifconf interfaceConfiguration = {0}; + char interfaceConfigurationBuffer[1024] = {0}; + + int inetSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); + if (inetSocket == -1) + { + return -1; + } + + interfaceConfiguration.ifc_len = sizeof(interfaceConfigurationBuffer); + interfaceConfiguration.ifc_buf = interfaceConfigurationBuffer; + if((ioctl(inetSocket, SIOCGIFCONF, &interfaceConfiguration)) == -1) + { + close(inetSocket); + return -1; + } + + struct ifreq* intefaceRequestStart = interfaceConfiguration.ifc_req; + const struct ifreq* const interfaceRequestEnd = intefaceRequestStart + (interfaceConfiguration.ifc_len / sizeof(struct ifreq)); + + int32_t result = -1; + + for (; intefaceRequestStart != interfaceRequestEnd; ++intefaceRequestStart) + { + strcpy(interfaceRequest.ifr_name, intefaceRequestStart->ifr_name); + if (ioctl(inetSocket, SIOCGIFFLAGS, &interfaceRequest) == 0) + { + // don't count loopback + if ((interfaceRequest.ifr_flags & IFF_LOOPBACK) == 0) + { + if (ioctl(inetSocket, SIOCGIFHWADDR, &interfaceRequest) == 0) + { + result = 0; + break; + } + } + } + else + { + break; + } + } + + if (result == 0) + { + unsigned int size = deviceID.t.size <= MAC_ADDRESS_MAXIMUM_SIZE ? deviceID.t.size : MAC_ADDRESS_MAXIMUM_SIZE; + memcpy(deviceID.t.buffer, interfaceRequest.ifr_hwaddr.sa_data, size); + } + + close(inetSocket); + return result; +} + +// Read primary harddisk/emmc disk serial id from device and copy over to the given buffer. +// Returns 0 for success and -1 for error. + +static int GetDiskSerialNumber() +{ + struct udev *ud = NULL; + struct stat statbuf; + struct udev_device *device = NULL; + struct udev_list_entry *entry = NULL; + int result = -1; + + ud = udev_new(); + if (NULL == ud) + { + return result; + } + else + { + + const unsigned int diskDeviceNamesSize = 2; + const char *diskDeviceNames[] = { + "/dev/sda", // primary hard disk. + "/dev/mmcblk0" // primary eMMC disk. + }; + + unsigned int i = 0; + while (i < diskDeviceNamesSize) + { + if (0 == stat(diskDeviceNames[i], &statbuf)) + { + break; + } + i++; + } + + if (i == diskDeviceNamesSize) + { + goto Cleanup; + } + + const char blockDeviceType = 'b'; + device = udev_device_new_from_devnum(ud, blockDeviceType, statbuf.st_rdev); + if (NULL == device) + { + goto Cleanup; + } + else + { + entry = udev_device_get_properties_list_entry(device); + while (NULL != entry) + { + if (0 == strcmp(udev_list_entry_get_name(entry), + "ID_SERIAL")) + { + break; + } + + entry = udev_list_entry_get_next(entry); + } + + if(entry == NULL) + { + goto Cleanup; + } + + const char* serialNumber = udev_list_entry_get_value(entry); + size_t serialNumberLength = strlen(serialNumber); + + size_t dataCopyLength = deviceID.t.size - MAC_ADDRESS_MAXIMUM_SIZE; + if (serialNumberLength < dataCopyLength) + { + dataCopyLength = serialNumberLength; + } + + memcpy(deviceID.t.buffer, serialNumber, dataCopyLength); + + result = 0; + } + +Cleanup: + if(device) + { + udev_device_unref(device); + } + + (void)udev_unref(ud); + return result; + } +} + +#if defined(SIMULATION) && (SIMULATION == YES) +// Get device id from hardware parameters. +// CAUTION: Primary seeds derived from device unique IDs are guaranteed to remain the same as long as the reference +// implementation manufactures its NV state on the same device. Since this implementation of GetDeviceID() relies +// solely on publicly accessible values (storage device serial numbers and networking card MAC address), it can +// only be used for the simulation purposes, as it cannot be used to produce a secret value. +// pre-requisites - assumes that MAC address or disk device (i.e. /dev/sda or /dev/mmcblk0) present on the device. +TPM_RC GetDeviceID() +{ + if(isDeviceIDSet == FALSE) + { + if(GetMacAddress() == 0) + { + isDeviceIDSet = TRUE; + } + + if(GetDiskSerialNumber() == 0) + { + isDeviceIDSet = TRUE; + } + + if(isDeviceIDSet == FALSE) + { + return TPM_RC_FAILURE; + } + } + + return TPM_RC_SUCCESS; +} +#endif + +void GetSeed(UINT16 size, uint8_t *seed, const TPM2B *purpose) +{ + RAND_STATE rand; + + TPM_RC result = GetDeviceID(); + if(result != TPM_RC_SUCCESS) + { + LOG_FAILURE(FATAL_ERROR_INTERNAL); + return; + } + + result = DRBG_InstantiateSeeded(&rand.drbg, &deviceID.b, purpose, NULL, NULL); + if(result != TPM_RC_SUCCESS) + { + LOG_FAILURE(FATAL_ERROR_INTERNAL); + return; + } + + if(DRBG_Generate(&rand, seed, size) == 0) + { + LOG_FAILURE(FATAL_ERROR_INTERNAL); + } + return; +} + +void +_plat__GetEPS( + UINT16 size, + uint8_t *seed + ) +{ + // Ignore GCC warning. + (void)EPS_CREATION_; + GetSeed(size, seed, EPS_CREATION); +} + +#endif \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/Samples/TPMCmd-DeviceID/build-tpmsimulator-deviceid b/optee/samples/ms-tpm-20-ref/Samples/TPMCmd-DeviceID/build-tpmsimulator-deviceid new file mode 100755 index 0000000..56f21c5 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/Samples/TPMCmd-DeviceID/build-tpmsimulator-deviceid @@ -0,0 +1,52 @@ +#!/usr/bin/env sh +# The copyright in this software is being made available under the BSD License, +# included below. This software may be subject to other third party and +# contributor rights, including patent rights, and no such rights are granted +# under this license. +# +# Copyright (c) Intel Corporation +# +# All rights reserved. +# +# BSD License +# +# 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. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Script will build tpm2-simulator by using DeviceID. +# CAUTION: Endorsement seed derived from device unique IDs are guaranteed to remain the same as long as the reference +# implementation manufactures its NV state on the same device. It relies on publicly accessible values +# storage device serial numbers and networking card MAC address), it can only be used for the simulation purposes, +# as it cannot be used to produce a secret value. + +basedir=$1 + +# Copy needed tpm simulator reference implementation source code files. +cp -r -n -v $basedir/TPMCmd/* $basedir/Samples/TPMCmd-DeviceID + +cd $basedir/Samples/TPMCmd-DeviceID + +./bootstrap +./configure --enable-usedeviceid=yes +make -j2 + +cd $basedir + diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/Makefile.am b/optee/samples/ms-tpm-20-ref/TPMCmd/Makefile.am new file mode 100644 index 0000000..1df7a5e --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/Makefile.am @@ -0,0 +1,62 @@ +## The copyright in this software is being made available under the BSD License, +## included below. This software may be subject to other third party and +## contributor rights, including patent rights, and no such rights are granted +## under this license. +## +## Copyright (c) Intel Corporation +## +## All rights reserved. +## +## BSD License +## +## 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. +## +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" +## AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +## DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +## ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +## (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +## LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +## ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +## SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +include src.mk + +PLATFORM_INC = -I $(srcdir)/Platform/include \ + -I $(srcdir)/Platform/include/prototypes +SIMULATOR_INC = -I $(srcdir)/Simulator/include \ + -I $(srcdir)/Simulator/include/prototypes +TPM_INC = -I $(srcdir)/tpm/include \ + -I $(srcdir)/tpm/include/prototypes + +libplatform = Platform/src/libplatform.a +libtpm = tpm/src/libtpm.a +tpm2_simulator = Simulator/src/tpm2-simulator + +bin_PROGRAMS = $(tpm2_simulator) +noinst_LIBRARIES = $(libplatform) $(libtpm) + +Platform_src_libplatform_a_CFLAGS = $(EXTRA_CFLAGS) $(PLATFORM_INC) $(TPM_INC) +Platform_src_libplatform_a_SOURCES = $(PLATFORM_C) $(PLATFORM_H) + +Simulator_src_tpm2_simulator_CFLAGS = $(EXTRA_CFLAGS) $(PLATFORM_INC) \ + $(TPM_INC) $(SIMULATOR_INC) $(LIBCRYPTO_CFLAGS) $(PTHREAD_CFLAGS) +# the weird / duplicate static library is necessary for dealing with the +# circular dependency beetween libplatform and libtpm +Simulator_src_tpm2_simulator_LDADD = $(libplatform) $(libtpm) \ + $(libplatform) $(LIBCRYPTO_LIBS) $(PTHREAD_LIBS) @ADDITIONAL_LIBS@ +Simulator_src_tpm2_simulator_SOURCES = $(SIMULATOR_C) $(SIMULATOR_H) + +tpm_src_libtpm_a_CFLAGS = $(EXTRA_CFLAGS) $(PLATFORM_INC) $(TPM_INC) \ + $(LIBCRYPTO_CFLAGS) +tpm_src_libtpm_a_SOURCES = $(TPM_C) $(TPM_H) $(PLATFORM_H) diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/include/Platform.h b/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/include/Platform.h new file mode 100644 index 0000000..ed1b820 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/include/Platform.h @@ -0,0 +1,51 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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_H_ +#define _PLATFORM_H_ + +#include "TpmBuildSwitches.h" +#include "BaseTypes.h" +#include "TPMB.h" +#include "MinMax.h" + +#include "TpmProfile.h" + +#include "PlatformACT.h" +#include "PlatformClock.h" +#include "PlatformData.h" +#include "Platform_fp.h" + +#endif // _PLATFORM_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/include/PlatformACT.h b/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/include/PlatformACT.h new file mode 100644 index 0000000..a917367 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/include/PlatformACT.h @@ -0,0 +1,181 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 contains the definitions for the ACT macros and data types used in the +// ACT implementation. + +#ifndef _PLATFORM_ACT_H_ +#define _PLATFORM_ACT_H_ + +typedef struct ACT_DATA +{ + uint32_t remaining; + uint32_t newValue; + uint8_t signaled; + uint8_t pending; + uint8_t number; +} ACT_DATA, *P_ACT_DATA; + +#if !(defined RH_ACT_0) || (RH_ACT_0 != YES) +# undef RH_ACT_0 +# define RH_ACT_0 NO +# define IF_ACT_0_IMPLEMENTED(op) +#else +# define IF_ACT_0_IMPLEMENTED(op) op(0) +#endif +#if !(defined RH_ACT_1) || (RH_ACT_1 != YES) +# undef RH_ACT_1 +# define RH_ACT_1 NO +# define IF_ACT_1_IMPLEMENTED(op) +#else +# define IF_ACT_1_IMPLEMENTED(op) op(1) +#endif +#if !(defined RH_ACT_2) || (RH_ACT_2 != YES) +# undef RH_ACT_2 +# define RH_ACT_2 NO +# define IF_ACT_2_IMPLEMENTED(op) +#else +# define IF_ACT_2_IMPLEMENTED(op) op(2) +#endif +#if !(defined RH_ACT_3) || (RH_ACT_3 != YES) +# undef RH_ACT_3 +# define RH_ACT_3 NO +# define IF_ACT_3_IMPLEMENTED(op) +#else +# define IF_ACT_3_IMPLEMENTED(op) op(3) +#endif +#if !(defined RH_ACT_4) || (RH_ACT_4 != YES) +# undef RH_ACT_4 +# define RH_ACT_4 NO +# define IF_ACT_4_IMPLEMENTED(op) +#else +# define IF_ACT_4_IMPLEMENTED(op) op(4) +#endif +#if !(defined RH_ACT_5) || (RH_ACT_5 != YES) +# undef RH_ACT_5 +# define RH_ACT_5 NO +# define IF_ACT_5_IMPLEMENTED(op) +#else +# define IF_ACT_5_IMPLEMENTED(op) op(5) +#endif +#if !(defined RH_ACT_6) || (RH_ACT_6 != YES) +# undef RH_ACT_6 +# define RH_ACT_6 NO +# define IF_ACT_6_IMPLEMENTED(op) +#else +# define IF_ACT_6_IMPLEMENTED(op) op(6) +#endif +#if !(defined RH_ACT_7) || (RH_ACT_7 != YES) +# undef RH_ACT_7 +# define RH_ACT_7 NO +# define IF_ACT_7_IMPLEMENTED(op) +#else +# define IF_ACT_7_IMPLEMENTED(op) op(7) +#endif +#if !(defined RH_ACT_8) || (RH_ACT_8 != YES) +# undef RH_ACT_8 +# define RH_ACT_8 NO +# define IF_ACT_8_IMPLEMENTED(op) +#else +# define IF_ACT_8_IMPLEMENTED(op) op(8) +#endif +#if !(defined RH_ACT_9) || (RH_ACT_9 != YES) +# undef RH_ACT_9 +# define RH_ACT_9 NO +# define IF_ACT_9_IMPLEMENTED(op) +#else +# define IF_ACT_9_IMPLEMENTED(op) op(9) +#endif +#if !(defined RH_ACT_A) || (RH_ACT_A != YES) +# undef RH_ACT_A +# define RH_ACT_A NO +# define IF_ACT_A_IMPLEMENTED(op) +#else +# define IF_ACT_A_IMPLEMENTED(op) op(A) +#endif +#if !(defined RH_ACT_B) || (RH_ACT_B != YES) +# undef RH_ACT_B +# define RH_ACT_B NO +# define IF_ACT_B_IMPLEMENTED(op) +#else +# define IF_ACT_B_IMPLEMENTED(op) op(B) +#endif +#if !(defined RH_ACT_C) || (RH_ACT_C != YES) +# undef RH_ACT_C +# define RH_ACT_C NO +# define IF_ACT_C_IMPLEMENTED(op) +#else +# define IF_ACT_C_IMPLEMENTED(op) op(C) +#endif +#if !(defined RH_ACT_D) || (RH_ACT_D != YES) +# undef RH_ACT_D +# define RH_ACT_D NO +# define IF_ACT_D_IMPLEMENTED(op) +#else +# define IF_ACT_D_IMPLEMENTED(op) op(D) +#endif +#if !(defined RH_ACT_E) || (RH_ACT_E != YES) +# undef RH_ACT_E +# define RH_ACT_E NO +# define IF_ACT_E_IMPLEMENTED(op) +#else +# define IF_ACT_E_IMPLEMENTED(op) op(E) +#endif +#if !(defined RH_ACT_F) || (RH_ACT_F != YES) +# undef RH_ACT_F +# define RH_ACT_F NO +# define IF_ACT_F_IMPLEMENTED(op) +#else +# define IF_ACT_F_IMPLEMENTED(op) op(F) +#endif + +#define FOR_EACH_ACT(op) \ + IF_ACT_0_IMPLEMENTED(op) \ + IF_ACT_1_IMPLEMENTED(op) \ + IF_ACT_2_IMPLEMENTED(op) \ + IF_ACT_3_IMPLEMENTED(op) \ + IF_ACT_4_IMPLEMENTED(op) \ + IF_ACT_5_IMPLEMENTED(op) \ + IF_ACT_6_IMPLEMENTED(op) \ + IF_ACT_7_IMPLEMENTED(op) \ + IF_ACT_8_IMPLEMENTED(op) \ + IF_ACT_9_IMPLEMENTED(op) \ + IF_ACT_A_IMPLEMENTED(op) \ + IF_ACT_B_IMPLEMENTED(op) \ + IF_ACT_C_IMPLEMENTED(op) \ + IF_ACT_D_IMPLEMENTED(op) \ + IF_ACT_E_IMPLEMENTED(op) \ + IF_ACT_F_IMPLEMENTED(op) + +#endif // _PLATFORM_ACT_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/include/PlatformClock.h b/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/include/PlatformClock.h new file mode 100644 index 0000000..d2b1b5d --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/include/PlatformClock.h @@ -0,0 +1,69 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 contains the instance data for the Platform module. It is collected +// in this file so that the state of the module is easier to manage. + +#ifndef _PLATFORM_CLOCK_H_ +#define _PLATFORM_CLOCK_H_ + +#ifndef _ARM_ +# ifdef _MSC_VER +# include +# include +# else +# include +# include +# endif +#endif +// CLOCK_NOMINAL is the number of hardware ticks per mS. A value of 300000 means +// that the nominal clock rate used to drive the hardware clock is 30 MHz. The +// adjustment rates are used to determine the conversion of the hardware ticks to +// internal hardware clock value. In practice, we would expect that there would be +// a hardware register will accumulated mS. It would be incremented by the output +// of a pre-scaler. The pre-scaler would divide the ticks from the clock by some +// value that would compensate for the difference between clock time and real time. +// The code in Clock does the emulation of this function. +#define CLOCK_NOMINAL 30000 +// A 1% change in rate is 300 counts +#define CLOCK_ADJUST_COARSE 300 +// A 0.1% change in rate is 30 counts +#define CLOCK_ADJUST_MEDIUM 30 +// A minimum change in rate is 1 count +#define CLOCK_ADJUST_FINE 1 +// The clock tolerance is +/-15% (4500 counts) +// Allow some guard band (16.7%) +#define CLOCK_ADJUST_LIMIT 5000 + +#endif // _PLATFORM_CLOCK_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/include/PlatformData.h b/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/include/PlatformData.h new file mode 100644 index 0000000..ec4530d --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/include/PlatformData.h @@ -0,0 +1,125 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 contains the instance data for the Platform module. It is collected +// in this file so that the state of the module is easier to manage. + +#ifndef _PLATFORM_DATA_H_ +#define _PLATFORM_DATA_H_ + +#ifdef _PLATFORM_DATA_C_ +# define EXTERN +#else +# define EXTERN extern +#endif + +// From Cancel.c +// Cancel flag. It is initialized as FALSE, which indicate the command is not +// being canceled +EXTERN int s_isCanceled; + +#ifndef HARDWARE_CLOCK +typedef uint64_t clock64_t; +// This is the value returned the last time that the system clock was read. This +// is only relevant for a simulator or virtual TPM. +EXTERN clock64_t s_realTimePrevious; + +// These values are used to try to synthesize a long lived version of clock(). +EXTERN clock64_t s_lastSystemTime; +EXTERN clock64_t s_lastReportedTime; + +// This is the rate adjusted value that is the equivalent of what would be read from +// a hardware register that produced rate adjusted time. +EXTERN clock64_t s_tpmTime; +#endif // HARDWARE_CLOCK + +// This value indicates that the timer was reset +EXTERN int s_timerReset; +// This value indicates that the timer was stopped. It causes a clock discontinuity. +EXTERN int s_timerStopped; + +// This variable records the time when _plat__TimerReset is called. This mechanism +// allow us to subtract the time when TPM is power off from the total +// time reported by clock() function +EXTERN uint64_t s_initClock; + +// This variable records the timer adjustment factor. +EXTERN unsigned int s_adjustRate; + +// For LocalityPlat.c +// Locality of current command +EXTERN unsigned char s_locality; + +// For NVMem.c +// Choose if the NV memory should be backed by RAM or by file. +// If this macro is defined, then a file is used as NV. If it is not defined, +// then RAM is used to back NV memory. Comment out to use RAM. + +#if(!defined VTPM) || ((VTPM != NO) && (VTPM != YES)) +# undef VTPM +# define VTPM YES // Default: Either YES or NO +#endif + +// For a simulation, use a file to back up the NV +#if(!defined FILE_BACKED_NV) || ((FILE_BACKED_NV != NO) && (FILE_BACKED_NV != YES)) +# undef FILE_BACKED_NV +# define FILE_BACKED_NV (VTPM && YES) // Default: Either YES or NO +#endif + +#if SIMULATION +# undef FILE_BACKED_NV +# define FILE_BACKED_NV YES +#endif // SIMULATION + +EXTERN unsigned char s_NV[NV_MEMORY_SIZE]; +EXTERN int s_NvIsAvailable; +EXTERN int s_NV_unrecoverable; +EXTERN int s_NV_recoverable; + +// For PPPlat.c +// Physical presence. It is initialized to FALSE +EXTERN int s_physicalPresence; + +// From Power +EXTERN int s_powerLost; + +// For Entropy.c +EXTERN uint32_t lastEntropy; + +#define DEFINE_ACT(N) EXTERN ACT_DATA ACT_##N; +FOR_EACH_ACT(DEFINE_ACT) + +EXTERN int actTicksAllowed; + +#endif // _PLATFORM_DATA_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/include/prototypes/Platform_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/include/prototypes/Platform_fp.h new file mode 100644 index 0000000..a68ea19 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/include/prototypes/Platform_fp.h @@ -0,0 +1,403 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 6, 2020 Time: 01:50:11PM + */ + +#ifndef _PLATFORM_FP_H_ +#define _PLATFORM_FP_H_ + +//** From Cancel.c + +//***_plat__IsCanceled() +// Check if the cancel flag is set +// Return Type: int +// TRUE(1) if cancel flag is set +// FALSE(0) if cancel flag is not set +LIB_EXPORT int _plat__IsCanceled(void); + +// Set cancel flag. +LIB_EXPORT void _plat__SetCancel(void); + +//***_plat__ClearCancel() +// Clear cancel flag +LIB_EXPORT void _plat__ClearCancel(void); + +//** From Clock.c + +//***_plat__TimerReset() +// This function sets current system clock time as t0 for counting TPM time. +// This function is called at a power on event to reset the clock. When the clock +// is reset, the indication that the clock was stopped is also set. +LIB_EXPORT void _plat__TimerReset(void); + +//*** _plat__TimerRestart() +// This function should be called in order to simulate the restart of the timer +// should it be stopped while power is still applied. +LIB_EXPORT void _plat__TimerRestart(void); + +//*** _plat__RealTime() +// This is another, probably futile, attempt to define a portable function +// that will return a 64-bit clock value that has mSec resolution. +LIB_EXPORT uint64_t _plat__RealTime(void); + +//***_plat__TimerRead() +// This function provides access to the tick timer of the platform. The TPM code +// uses this value to drive the TPM Clock. +// +// The tick timer is supposed to run when power is applied to the device. This timer +// should not be reset by time events including _TPM_Init. It should only be reset +// when TPM power is re-applied. +// +// If the TPM is run in a protected environment, that environment may provide the +// tick time to the TPM as long as the time provided by the environment is not +// allowed to go backwards. If the time provided by the system can go backwards +// during a power discontinuity, then the _plat__Signal_PowerOn should call +// _plat__TimerReset(). +LIB_EXPORT uint64_t _plat__TimerRead(void); + +//*** _plat__TimerWasReset() +// This function is used to interrogate the flag indicating if the tick timer has +// been reset. +// +// If the resetFlag parameter is SET, then the flag will be CLEAR before the +// function returns. +LIB_EXPORT int _plat__TimerWasReset(void); + +//*** _plat__TimerWasStopped() +// This function is used to interrogate the flag indicating if the tick timer has +// been stopped. If so, this is typically a reason to roll the nonce. +// +// This function will CLEAR the s_timerStopped flag before returning. This provides +// functionality that is similar to status register that is cleared when read. This +// is the model used here because it is the one that has the most impact on the TPM +// code as the flag can only be accessed by one entity in the TPM. Any other +// implementation of the hardware can be made to look like a read-once register. +LIB_EXPORT int _plat__TimerWasStopped(void); + +//***_plat__ClockAdjustRate() +// Adjust the clock rate +LIB_EXPORT void _plat__ClockAdjustRate( + int adjust // IN: the adjust number. It could be positive + // or negative +); + +//** From DebugHelpers.c + +#if CERTIFYX509_DEBUG + +//*** DebugFileInit() +// This function opens the file used to hold the debug data. +// Return Type: int +// 0 success +// != 0 error +int DebugFileInit(void); + +//*** DebugDumpBuffer() +void DebugDumpBuffer(int size, unsigned char* buf, const char* identifier); +#endif // CERTIFYX509_DEBUG + +//** From Entropy.c + +//*** _plat__GetEntropy() +// This function is used to get available hardware entropy. In a hardware +// implementation of this function, there would be no call to the system +// to get entropy. +// Return Type: int32_t +// < 0 hardware failure of the entropy generator, this is sticky +// >= 0 the returned amount of entropy (bytes) +// +LIB_EXPORT int32_t _plat__GetEntropy(unsigned char* entropy, // output buffer + uint32_t amount // amount requested +); + +//** From LocalityPlat.c + +//***_plat__LocalityGet() +// Get the most recent command locality in locality value form. +// This is an integer value for locality and not a locality structure +// The locality can be 0-4 or 32-255. 5-31 is not allowed. +LIB_EXPORT unsigned char _plat__LocalityGet(void); + +//***_plat__LocalitySet() +// Set the most recent command locality in locality value form +LIB_EXPORT void _plat__LocalitySet(unsigned char locality); + +//** From NVMem.c + +//*** _plat__NvErrors() +// This function is used by the simulator to set the error flags in the NV +// subsystem to simulate an error in the NV loading process +LIB_EXPORT void _plat__NvErrors(int recoverable, int unrecoverable); + +//***_plat__NVEnable() +// Enable NV memory. +// +// This version just pulls in data from a file. In a real TPM, with NV on chip, +// this function would verify the integrity of the saved context. If the NV +// memory was not on chip but was in something like RPMB, the NV state would be +// read in, decrypted and integrity checked. +// +// The recovery from an integrity failure depends on where the error occurred. It +// it was in the state that is discarded by TPM Reset, then the error is +// recoverable if the TPM is reset. Otherwise, the TPM must go into failure mode. +// Return Type: int +// 0 if success +// > 0 if receive recoverable error +// <0 if unrecoverable error +LIB_EXPORT int _plat__NVEnable( + void* platParameter // IN: platform specific parameters +); + +//***_plat__NVDisable() +// Disable NV memory +LIB_EXPORT void _plat__NVDisable(int delete // IN: If TRUE, delete the NV contents. +); + +//***_plat__IsNvAvailable() +// Check if NV is available +// Return Type: int +// 0 NV is available +// 1 NV is not available due to write failure +// 2 NV is not available due to rate limit +LIB_EXPORT int _plat__IsNvAvailable(void); + +//***_plat__NvMemoryRead() +// Function: Read a chunk of NV memory +LIB_EXPORT void _plat__NvMemoryRead(unsigned int startOffset, // IN: read start + unsigned int size, // IN: size of bytes to read + void* data // OUT: data buffer +); + +//*** _plat__NvIsDifferent() +// This function checks to see if the NV is different from the test value. This is +// so that NV will not be written if it has not changed. +// Return Type: int +// TRUE(1) the NV location is different from the test value +// FALSE(0) the NV location is the same as the test value +LIB_EXPORT int _plat__NvIsDifferent(unsigned int startOffset, // IN: read start + unsigned int size, // IN: size of bytes to read + void* data // IN: data buffer +); + +//***_plat__NvMemoryWrite() +// This function is used to update NV memory. The "write" is to a memory copy of +// NV. At the end of the current command, any changes are written to +// the actual NV memory. +// NOTE: A useful optimization would be for this code to compare the current +// contents of NV with the local copy and note the blocks that have changed. Then +// only write those blocks when _plat__NvCommit() is called. +LIB_EXPORT int _plat__NvMemoryWrite(unsigned int startOffset, // IN: write start + unsigned int size, // IN: size of bytes to write + void* data // OUT: data buffer +); + +//***_plat__NvMemoryClear() +// Function is used to set a range of NV memory bytes to an implementation-dependent +// value. The value represents the erase state of the memory. +LIB_EXPORT void _plat__NvMemoryClear( + unsigned int start, // IN: clear start + unsigned int size // IN: number of bytes to clear +); + +//***_plat__NvMemoryMove() +// Function: Move a chunk of NV memory from source to destination +// This function should ensure that if there overlap, the original data is +// copied before it is written +LIB_EXPORT void _plat__NvMemoryMove( + unsigned int sourceOffset, // IN: source offset + unsigned int destOffset, // IN: destination offset + unsigned int size // IN: size of data being moved +); + +//***_plat__NvCommit() +// This function writes the local copy of NV to NV for permanent store. It will write +// NV_MEMORY_SIZE bytes to NV. If a file is use, the entire file is written. +// Return Type: int +// 0 NV write success +// non-0 NV write fail +LIB_EXPORT int _plat__NvCommit(void); + +//***_plat__SetNvAvail() +// Set the current NV state to available. This function is for testing purpose +// only. It is not part of the platform NV logic +LIB_EXPORT void _plat__SetNvAvail(void); + +//***_plat__ClearNvAvail() +// Set the current NV state to unavailable. This function is for testing purpose +// only. It is not part of the platform NV logic +LIB_EXPORT void _plat__ClearNvAvail(void); + +//*** _plat__NVNeedsManufacture() +// This function is used by the simulator to determine when the TPM's NV state +// needs to be manufactured. +LIB_EXPORT int _plat__NVNeedsManufacture(void); + +//** From PlatformACT.c + +//*** _plat__ACT_GetImplemented() +// This function tests to see if an ACT is implemented. It is a belt and suspenders +// function because the TPM should not be calling to manipulate an ACT that is not +// implemented. However, this could help the simulator code which doesn't necessarily +// know if an ACT is implemented or not. +LIB_EXPORT int _plat__ACT_GetImplemented(uint32_t act); + +//*** _plat__ACT_GetRemaining() +// This function returns the remaining time. If an update is pending, 'newValue' is +// returned. Otherwise, the current counter value is returned. Note that since the +// timers keep running, the returned value can get stale immediately. The actual count +// value will be no greater than the returned value. +LIB_EXPORT uint32_t _plat__ACT_GetRemaining(uint32_t act //IN: the ACT selector +); + +//*** _plat__ACT_GetSignaled() +LIB_EXPORT int _plat__ACT_GetSignaled(uint32_t act //IN: number of ACT to check +); + +//*** _plat__ACT_SetSignaled() +LIB_EXPORT void _plat__ACT_SetSignaled(uint32_t act, int on); + +//*** _plat__ACT_GetPending() +LIB_EXPORT int _plat__ACT_GetPending(uint32_t act //IN: number of ACT to check +); + +//*** _plat__ACT_UpdateCounter() +// This function is used to write the newValue for the counter. If an update is +// pending, then no update occurs and the function returns FALSE. If 'setSignaled' +// is TRUE, then the ACT signaled state is SET and if 'newValue' is 0, nothing +// is posted. +LIB_EXPORT int _plat__ACT_UpdateCounter(uint32_t act, // IN: ACT to update + uint32_t newValue // IN: the value to post +); + +//***_plat__ACT_EnableTicks() +// This enables and disables the processing of the once-per-second ticks. This should +// be turned off ('enable' = FALSE) by _TPM_Init and turned on ('enable' = TRUE) by +// TPM2_Startup() after all the initializations have completed. +LIB_EXPORT void _plat__ACT_EnableTicks(int enable); + +//*** _plat__ACT_Tick() +// This processes the once-per-second clock tick from the hardware. This is set up +// for the simulator to use the control interface to send ticks to the TPM. These +// ticks do not have to be on a per second basis. They can be as slow or as fast as +// desired so that the simulation can be tested. +LIB_EXPORT void _plat__ACT_Tick(void); + +//***_plat__ACT_Initialize() +// This function initializes the ACT hardware and data structures +LIB_EXPORT int _plat__ACT_Initialize(void); + +//** From PowerPlat.c + +//***_plat__Signal_PowerOn() +// Signal platform power on +LIB_EXPORT int _plat__Signal_PowerOn(void); + +//*** _plat__WasPowerLost() +// Test whether power was lost before a _TPM_Init. +// +// This function will clear the "hardware" indication of power loss before return. +// This means that there can only be one spot in the TPM code where this value +// gets read. This method is used here as it is the most difficult to manage in the +// TPM code and, if the hardware actually works this way, it is hard to make it +// look like anything else. So, the burden is placed on the TPM code rather than the +// platform code +// Return Type: int +// TRUE(1) power was lost +// FALSE(0) power was not lost +LIB_EXPORT int _plat__WasPowerLost(void); + +//*** _plat_Signal_Reset() +// This a TPM reset without a power loss. +LIB_EXPORT int _plat__Signal_Reset(void); + +//***_plat__Signal_PowerOff() +// Signal platform power off +LIB_EXPORT void _plat__Signal_PowerOff(void); + +//** From PPPlat.c + +//***_plat__PhysicalPresenceAsserted() +// Check if physical presence is signaled +// Return Type: int +// TRUE(1) if physical presence is signaled +// FALSE(0) if physical presence is not signaled +LIB_EXPORT int _plat__PhysicalPresenceAsserted(void); + +//***_plat__Signal_PhysicalPresenceOn() +// Signal physical presence on +LIB_EXPORT void _plat__Signal_PhysicalPresenceOn(void); + +//***_plat__Signal_PhysicalPresenceOff() +// Signal physical presence off +LIB_EXPORT void _plat__Signal_PhysicalPresenceOff(void); + +//** From RunCommand.c + +//***_plat__RunCommand() +// This version of RunCommand will set up a jum_buf and call ExecuteCommand(). If +// the command executes without failing, it will return and RunCommand will return. +// If there is a failure in the command, then _plat__Fail() is called and it will +// longjump back to RunCommand which will call ExecuteCommand again. However, this +// time, the TPM will be in failure mode so ExecuteCommand will simply build +// a failure response and return. +LIB_EXPORT void _plat__RunCommand( + uint32_t requestSize, // IN: command buffer size + unsigned char* request, // IN: command buffer + uint32_t* responseSize, // IN/OUT: response buffer size + unsigned char** response // IN/OUT: response buffer +); + +//***_plat__Fail() +// This is the platform depended failure exit for the TPM. +LIB_EXPORT NORETURN void _plat__Fail(void); + +//** From Unique.c + +//** _plat__GetUnique() +// This function is used to access the platform-specific unique value. +// This function places the unique value in the provided buffer ('b') +// and returns the number of bytes transferred. The function will not +// copy more data than 'bSize'. +// NOTE: If a platform unique value has unequal distribution of uniqueness +// and 'bSize' is smaller than the size of the unique value, the 'bSize' +// portion with the most uniqueness should be returned. +LIB_EXPORT uint32_t _plat__GetUnique(uint32_t which, // authorities (0) or details + uint32_t bSize, // size of the buffer + unsigned char* b // output buffer +); + +#endif // _PLATFORM_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/platform.vcxproj b/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/platform.vcxproj new file mode 100644 index 0000000..753c885 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/platform.vcxproj @@ -0,0 +1,509 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + Static + Win32 + + + Static + x64 + + + WolfDebug + Win32 + + + WolfDebug + x64 + + + WolfRelease + Win32 + + + WolfRelease + x64 + + + + + + + + + + + + + + + + + + + + + + + + {A9249F05-0DF5-4D06-9873-FBBE61B6768B} + platform + Win32Proj + Platform + $([Microsoft.Build.Utilities.ToolLocationHelper]::GetLatestSDKTargetPlatformVersion('Windows', '10.0')) + + + + StaticLibrary + Unicode + true + v141 + + + StaticLibrary + Unicode + true + v141 + + + StaticLibrary + Unicode + false + v141 + + + StaticLibrary + Unicode + false + v141 + + + StaticLibrary + Unicode + v141 + + + StaticLibrary + Unicode + v141 + + + StaticLibrary + Unicode + v141 + + + StaticLibrary + Unicode + v141 + + + StaticLibrary + Unicode + v141 + + + StaticLibrary + Unicode + v141 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)\$(Configuration)\ + $(SolutionDir)\bin\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)\bin\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)\bin\$(ProjectName)\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)\bin\$(ProjectName)\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)\bin\$(ProjectName)\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)\$(Configuration)\ + $(SolutionDir)\bin\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)\bin\$(ProjectName)\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)\bin\$(ProjectName)\$(PlatformTarget)\$(Configuration)\ + AllRules.ruleset + AllRules.ruleset + AllRules.ruleset + AllRules.ruleset + AllRules.ruleset + AllRules.ruleset + + + + + + + + + + + + + AllRules.ruleset + AllRules.ruleset + AllRules.ruleset + AllRules.ruleset + + + + + + + + + .lib + .lib + .lib + .lib + .lib + .lib + + + true + + + true + + + true + + + false + .lib + + + false + .lib + + + $(SolutionDir)\bin\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)\bin\$(ProjectName)\$(PlatformTarget)\$(Configuration)\ + + + $(SolutionDir)\bin\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)\bin\$(ProjectName)\$(PlatformTarget)\$(Configuration)\ + + + $(SolutionDir)\bin\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)\bin\$(ProjectName)\$(PlatformTarget)\$(Configuration)\ + + + $(SolutionDir)\bin\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)\bin\$(ProjectName)\$(PlatformTarget)\$(Configuration)\ + + + $(SolutionDir)\bin\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)\bin\$(ProjectName)\$(PlatformTarget)\$(Configuration)\ + + + + Disabled + $(ProjectDir)\include;$(ProjectDir)\include\prototypes;$(SolutionDir)\tpm\include;$(SolutionDir)\tpm\include\prototypes + WIN32;DEBUG;_LIB;%(PreprocessorDefinitions) + false + EnableFastChecks + MultiThreadedDebugDLL + NotUsing + EnableAllWarnings + ProgramDatabase + CompileAsC + 4668;4710;4711;4820;5045 + Default + true + true + + + + + true + $(OutDir)$(TargetName)$(TargetExt) + %(AdditionalDependencies) + false + true + $(OutDir)Platform.map + + + $(OutDir)$(TargetName)$(TargetExt) + + + true + + + + + + + + Disabled + $(ProjectDir)\include;$(ProjectDir)\include\prototypes;$(SolutionDir)\tpm\include;$(SolutionDir)\tpm\include\prototypes + WIN32;DEBUG;_LIB;%(PreprocessorDefinitions) + false + EnableFastChecks + MultiThreadedDebugDLL + NotUsing + EnableAllWarnings + ProgramDatabase + CompileAsC + 4668;4710;4711;4820;5045 + Default + true + true + + + + + true + $(OutDir)$(TargetName)$(TargetExt) + %(AdditionalDependencies) + false + true + $(OutDir)Platform.map + + + $(OutDir)$(TargetName)$(TargetExt) + + + true + + + + + + + + + Disabled + $(ProjectDir)\include;$(ProjectDir)\include\prototypes;$(SolutionDir)\tpm\include;$(SolutionDir)\tpm\include\prototypes + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + false + EnableFastChecks + MultiThreadedDebugDLL + NotUsing + EnableAllWarnings + ProgramDatabase + CompileAsC + 4668;4710;4711;4820;5045 + Default + true + + + + + true + $(OutDir)$(TargetName)$(TargetExt) + %(AdditionalDependencies) + + + $(OutDir)$(TargetName)$(TargetExt) + + + + + Disabled + $(ProjectDir)\include;$(ProjectDir)\include\prototypes;$(SolutionDir)\tpm\include;$(SolutionDir)\tpm\include\prototypes + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + + + EnableAllWarnings + ProgramDatabase + CompileAsC + 4668;4710;4711;4820;5045 + Default + true + + + + + true + + + $(OutDir)$(TargetName)$(TargetExt) + + + + + Disabled + $(ProjectDir)\include;$(ProjectDir)\include\prototypes;$(SolutionDir)\tpm\include;$(SolutionDir)\tpm\include\prototypes + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + + + EnableAllWarnings + ProgramDatabase + CompileAsC + 4668;4710;4711;4820;5045 + Default + true + + + true + + + $(OutDir)$(TargetName)$(TargetExt) + + + + + Disabled + $(ProjectDir)\include;$(ProjectDir)\include\prototypes;$(SolutionDir)\tpm\include;$(SolutionDir)\tpm\include\prototypes + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + + + EnableAllWarnings + ProgramDatabase + CompileAsC + 4668;4710;4711;4820;5045 + Default + true + + + + + true + + + $(OutDir)$(TargetName)$(TargetExt) + + + + + MaxSpeed + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + MultiThreadedDLL + true + NotUsing + EnableAllWarnings + ProgramDatabase + $(ProjectDir)\include;$(ProjectDir)\include\prototypes;$(SolutionDir)\tpm\include;$(SolutionDir)\tpm\include\prototypes + true + 4668;4710;4711;4820;5045 + + + + + $(OutDir)$(TargetName)$(TargetExt) + tpm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + MaxSpeed + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + MultiThreadedDLL + true + NotUsing + EnableAllWarnings + ProgramDatabase + $(ProjectDir)\include;$(ProjectDir)\include\prototypes;$(SolutionDir)\tpm\include;$(SolutionDir)\tpm\include\prototypes + true + 4668;4710;4711;4820;5045 + + + + + $(OutDir)$(TargetName)$(TargetExt) + tpm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + MaxSpeed + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + EnableAllWarnings + ProgramDatabase + $(ProjectDir)\include;$(ProjectDir)\include\prototypes;$(SolutionDir)\tpm\include;$(SolutionDir)\tpm\include\prototypes + true + 4668;4710;4711;4820;5045 + + + + + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib + + + + + MaxSpeed + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + EnableAllWarnings + ProgramDatabase + $(ProjectDir)\include;$(ProjectDir)\include\prototypes;$(SolutionDir)\tpm\include;$(SolutionDir)\tpm\include\prototypes + true + 4668;4710;4711;4820;5045 + + + + + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib + + + + + + \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/platform.vcxproj.filters b/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/platform.vcxproj.filters new file mode 100644 index 0000000..bdd7398 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/platform.vcxproj.filters @@ -0,0 +1,66 @@ + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + {4303d7e7-8154-4a7c-9c6b-0df9b7e6447f} + + + {c7765704-4071-4d43-b451-b1dc177da099} + + + {356cc198-cb6e-4dbb-bf4f-b203b6e3fdb0} + + + + + Headers + + + Headers\prototypes + + + Headers + + + Headers + + + \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/Cancel.c b/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/Cancel.c new file mode 100644 index 0000000..9296d8c --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/Cancel.c @@ -0,0 +1,70 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Description +// +// This module simulates the cancel pins on the TPM. +// +//** Includes, Typedefs, Structures, and Defines +#include "Platform.h" + +//** Functions + +//***_plat__IsCanceled() +// Check if the cancel flag is set +// Return Type: int +// TRUE(1) if cancel flag is set +// FALSE(0) if cancel flag is not set +LIB_EXPORT int _plat__IsCanceled(void) +{ + // return cancel flag + return s_isCanceled; +} + +//***_plat__SetCancel() + +// Set cancel flag. +LIB_EXPORT void _plat__SetCancel(void) +{ + s_isCanceled = TRUE; + return; +} + +//***_plat__ClearCancel() +// Clear cancel flag +LIB_EXPORT void _plat__ClearCancel(void) +{ + s_isCanceled = FALSE; + return; +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/Clock.c b/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/Clock.c new file mode 100644 index 0000000..89260f1 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/Clock.c @@ -0,0 +1,258 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Description +// +// This file contains the routines that are used by the simulator to mimic +// a hardware clock on a TPM. +// +// In this implementation, all the time values are measured in millisecond. +// However, the precision of the clock functions may be implementation dependent. + +//** Includes and Data Definitions +#include +#include "Platform.h" +#include "TpmFail_fp.h" + +//** Simulator Functions +//*** Introduction +// This set of functions is intended to be called by the simulator environment in +// order to simulate hardware events. + +//***_plat__TimerReset() +// This function sets current system clock time as t0 for counting TPM time. +// This function is called at a power on event to reset the clock. When the clock +// is reset, the indication that the clock was stopped is also set. +LIB_EXPORT void _plat__TimerReset(void) +{ + s_lastSystemTime = 0; + s_tpmTime = 0; + s_adjustRate = CLOCK_NOMINAL; + s_timerReset = TRUE; + s_timerStopped = TRUE; + return; +} + +//*** _plat__TimerRestart() +// This function should be called in order to simulate the restart of the timer +// should it be stopped while power is still applied. +LIB_EXPORT void _plat__TimerRestart(void) +{ + s_timerStopped = TRUE; + return; +} + +//** Functions Used by TPM +//*** Introduction +// These functions are called by the TPM code. They should be replaced by +// appropriated hardware functions. + +#include +clock_t debugTime; + +//*** _plat__RealTime() +// This is another, probably futile, attempt to define a portable function +// that will return a 64-bit clock value that has mSec resolution. +LIB_EXPORT uint64_t _plat__RealTime(void) +{ + clock64_t time; +#ifdef _MSC_VER + struct _timeb sysTime; + // + _ftime_s(&sysTime); + time = (clock64_t)(sysTime.time) * 1000 + sysTime.millitm; + // set the time back by one hour if daylight savings + if(sysTime.dstflag) + time -= 1000 * 60 * 60; // mSec/sec * sec/min * min/hour = ms/hour +#else + // hopefully, this will work with most UNIX systems + struct timespec systime; + // + clock_gettime(CLOCK_MONOTONIC, &systime); + time = (clock64_t)systime.tv_sec * 1000 + (systime.tv_nsec / 1000000); +#endif + return time; +} + +//***_plat__TimerRead() +// This function provides access to the tick timer of the platform. The TPM code +// uses this value to drive the TPM Clock. +// +// The tick timer is supposed to run when power is applied to the device. This timer +// should not be reset by time events including _TPM_Init. It should only be reset +// when TPM power is re-applied. +// +// If the TPM is run in a protected environment, that environment may provide the +// tick time to the TPM as long as the time provided by the environment is not +// allowed to go backwards. If the time provided by the system can go backwards +// during a power discontinuity, then the _plat__Signal_PowerOn should call +// _plat__TimerReset(). +LIB_EXPORT uint64_t _plat__TimerRead(void) +{ +#ifdef HARDWARE_CLOCK +# error "need a defintion for reading the hardware clock" + return HARDWARE_CLOCK +#else + clock64_t timeDiff; + clock64_t adjustedTimeDiff; + clock64_t timeNow; + clock64_t readjustedTimeDiff; + + // This produces a timeNow that is basically locked to the system clock. + timeNow = _plat__RealTime(); + + // if this hasn't been initialized, initialize it + if(s_lastSystemTime == 0) + { + s_lastSystemTime = timeNow; + debugTime = clock(); + s_lastReportedTime = 0; + s_realTimePrevious = 0; + } + // The system time can bounce around and that's OK as long as we don't allow + // time to go backwards. When the time does appear to go backwards, set + // lastSystemTime to be the new value and then update the reported time. + if(timeNow < s_lastReportedTime) + s_lastSystemTime = timeNow; + s_lastReportedTime = s_lastReportedTime + timeNow - s_lastSystemTime; + s_lastSystemTime = timeNow; + timeNow = s_lastReportedTime; + + // The code above produces a timeNow that is similar to the value returned + // by Clock(). The difference is that timeNow does not max out, and it is + // at a ms. rate rather than at a CLOCKS_PER_SEC rate. The code below + // uses that value and does the rate adjustment on the time value. + // If there is no difference in time, then skip all the computations + if(s_realTimePrevious >= timeNow) + return s_tpmTime; + // Compute the amount of time since the last update of the system clock + timeDiff = timeNow - s_realTimePrevious; + + // Do the time rate adjustment and conversion from CLOCKS_PER_SEC to mSec + adjustedTimeDiff = (timeDiff * CLOCK_NOMINAL) / ((uint64_t)s_adjustRate); + + // update the TPM time with the adjusted timeDiff + s_tpmTime += (clock64_t)adjustedTimeDiff; + + // Might have some rounding error that would loose CLOCKS. See what is not + // being used. As mentioned above, this could result in putting back more than + // is taken out. Here, we are trying to recreate timeDiff. + readjustedTimeDiff = (adjustedTimeDiff * (uint64_t)s_adjustRate) / CLOCK_NOMINAL; + + // adjusted is now converted back to being the amount we should advance the + // previous sampled time. It should always be less than or equal to timeDiff. + // That is, we could not have use more time than we started with. + s_realTimePrevious = s_realTimePrevious + readjustedTimeDiff; + +# ifdef DEBUGGING_TIME + // Put this in so that TPM time will pass much faster than real time when + // doing debug. + // A value of 1000 for DEBUG_TIME_MULTIPLER will make each ms into a second + // A good value might be 100 + return (s_tpmTime * DEBUG_TIME_MULTIPLIER); +# endif + return s_tpmTime; +#endif +} + +//*** _plat__TimerWasReset() +// This function is used to interrogate the flag indicating if the tick timer has +// been reset. +// +// If the resetFlag parameter is SET, then the flag will be CLEAR before the +// function returns. +LIB_EXPORT int _plat__TimerWasReset(void) +{ + int retVal = s_timerReset; + s_timerReset = FALSE; + return retVal; +} + +//*** _plat__TimerWasStopped() +// This function is used to interrogate the flag indicating if the tick timer has +// been stopped. If so, this is typically a reason to roll the nonce. +// +// This function will CLEAR the s_timerStopped flag before returning. This provides +// functionality that is similar to status register that is cleared when read. This +// is the model used here because it is the one that has the most impact on the TPM +// code as the flag can only be accessed by one entity in the TPM. Any other +// implementation of the hardware can be made to look like a read-once register. +LIB_EXPORT int _plat__TimerWasStopped(void) +{ + int retVal = s_timerStopped; + s_timerStopped = FALSE; + return retVal; +} + +//***_plat__ClockAdjustRate() +// Adjust the clock rate +LIB_EXPORT void _plat__ClockAdjustRate( + int adjust // IN: the adjust number. It could be positive + // or negative +) +{ + // We expect the caller should only use a fixed set of constant values to + // adjust the rate + switch(adjust) + { + case CLOCK_ADJUST_COARSE: + s_adjustRate += CLOCK_ADJUST_COARSE; + break; + case -CLOCK_ADJUST_COARSE: + s_adjustRate -= CLOCK_ADJUST_COARSE; + break; + case CLOCK_ADJUST_MEDIUM: + s_adjustRate += CLOCK_ADJUST_MEDIUM; + break; + case -CLOCK_ADJUST_MEDIUM: + s_adjustRate -= CLOCK_ADJUST_MEDIUM; + break; + case CLOCK_ADJUST_FINE: + s_adjustRate += CLOCK_ADJUST_FINE; + break; + case -CLOCK_ADJUST_FINE: + s_adjustRate -= CLOCK_ADJUST_FINE; + break; + default: + // ignore any other values; + break; + } + + if(s_adjustRate > (CLOCK_NOMINAL + CLOCK_ADJUST_LIMIT)) + s_adjustRate = CLOCK_NOMINAL + CLOCK_ADJUST_LIMIT; + if(s_adjustRate < (CLOCK_NOMINAL - CLOCK_ADJUST_LIMIT)) + s_adjustRate = CLOCK_NOMINAL - CLOCK_ADJUST_LIMIT; + + return; +} diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/DebugHelpers.c b/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/DebugHelpers.c new file mode 100644 index 0000000..609e74b --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/DebugHelpers.c @@ -0,0 +1,120 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Description +// +// This file contains the NV read and write access methods. This implementation +// uses RAM/file and does not manage the RAM/file as NV blocks. +// The implementation may become more sophisticated over time. +// + +//** Includes and Local +#include +#include +#include "Platform.h" + +#if CERTIFYX509_DEBUG + +const char* debugFileName = "DebugFile.txt"; + +//*** fileOpen() +// This exists to allow use of the 'safe' version of fopen() with a MS runtime. +static FILE* fileOpen(const char* fn, const char* mode) +{ + FILE* f; +# if defined _MSC_VER + if(fopen_s(&f, fn, mode) != 0) + f = NULL; +# else + f = fopen(fn, mode); +# endif + return f; +} + +//*** DebugFileInit() +// This function initializes the file containing the debug data with the time of the +// file creation. +// Return Type: int +// 0 success +// != 0 error +int DebugFileInit(void) +{ + FILE* f = NULL; + time_t t = time(NULL); +// +// Get current date and time. +# if defined _MSC_VER + char timeString[100]; + ctime_s(timeString, (size_t)sizeof(timeString), &t); +# else + char* timeString; + timeString = ctime(&t); +# endif + // Try to open the debug file + f = fileOpen(debugFileName, "w"); + if(f) + { + // Initialize the contents with the time. + fprintf(f, "%s\n", timeString); + fclose(f); + return 0; + } + return -1; +} + +//*** DebugDumpBuffer() +void DebugDumpBuffer(int size, unsigned char* buf, const char* identifier) +{ + int i; + // + FILE* f = fileOpen(debugFileName, "a"); + if(!f) + return; + if(identifier) + fprintf(f, "%s\n", identifier); + if(buf) + { + for(i = 0; i < size; i++) + { + if(((i % 16) == 0) && (i)) + fprintf(f, "\n"); + fprintf(f, " %02X", buf[i]); + } + if((size % 16) != 0) + fprintf(f, "\n"); + } + fclose(f); +} + +#endif // CERTIFYX509_DEBUG diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/Entropy.c b/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/Entropy.c new file mode 100644 index 0000000..af7a0c4 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/Entropy.c @@ -0,0 +1,149 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Includes and Local Values + +#define _CRT_RAND_S +#include +#include +#include +#include "Platform.h" + +#ifdef _MSC_VER +# include +#else +# include +#endif + +// This is the last 32-bits of hardware entropy produced. We have to check to +// see that two consecutive 32-bit values are not the same because +// according to FIPS 140-2, annex C: +// +// "If each call to an RNG produces blocks of n bits (where n > 15), the first +// n-bit block generated after power-up, initialization, or reset shall not be +// used, but shall be saved for comparison with the next n-bit block to be +// generated. Each subsequent generation of an n-bit block shall be compared with +// the previously generated block. The test shall fail if any two compared n-bit +// blocks are equal." +extern uint32_t lastEntropy; + +//** Functions + +//*** rand32() +// Local function to get a 32-bit random number +static uint32_t rand32(void) +{ + uint32_t rndNum = rand(); +#if RAND_MAX < UINT16_MAX + // If the maximum value of the random number is a 15-bit number, then shift it up + // 15 bits, get 15 more bits, shift that up 2 and then XOR in another value to get + // a full 32 bits. + rndNum = (rndNum << 15) ^ rand(); + rndNum = (rndNum << 2) ^ rand(); +#elif RAND_MAX == UINT16_MAX + // If the maximum size is 16-bits, shift it and add another 16 bits + rndNum = (rndNum << 16) ^ rand(); +#elif RAND_MAX < UINT32_MAX + // If 31 bits, then shift 1 and include another random value to get the extra bit + rndNum = (rndNum << 1) ^ rand(); +#endif + return rndNum; +} + +//*** _plat__GetEntropy() +// This function is used to get available hardware entropy. In a hardware +// implementation of this function, there would be no call to the system +// to get entropy. +// Return Type: int32_t +// < 0 hardware failure of the entropy generator, this is sticky +// >= 0 the returned amount of entropy (bytes) +// +LIB_EXPORT int32_t _plat__GetEntropy(unsigned char* entropy, // output buffer + uint32_t amount // amount requested +) +{ + uint32_t rndNum; + int32_t ret; + // + if(amount == 0) + { + // Seed the platform entropy source if the entropy source is software. There + // is no reason to put a guard macro (#if or #ifdef) around this code because + // this code would not be here if someone was changing it for a system with + // actual hardware. + // + // NOTE 1: The following command does not provide proper cryptographic + // entropy. Its primary purpose to make sure that different instances of the + // simulator, possibly started by a script on the same machine, are seeded + // differently. Vendors of the actual TPMs need to ensure availability of + // proper entropy using their platform-specific means. + // + // NOTE 2: In debug builds by default the reference implementation will seed + // its RNG deterministically (without using any platform provided randomness). + // See the USE_DEBUG_RNG macro and DRBG_GetEntropy() function. +#ifdef _MSC_VER + srand((unsigned)_plat__RealTime() ^ _getpid()); +#else + srand((unsigned)_plat__RealTime() ^ getpid()); +#endif + lastEntropy = rand32(); + ret = 0; + } + else + { + rndNum = rand32(); + if(rndNum == lastEntropy) + { + ret = -1; + } + else + { + lastEntropy = rndNum; + // Each process will have its random number generator initialized + // according to the process id and the initialization time. This is not a + // lot of entropy so, to add a bit more, XOR the current time value into + // the returned entropy value. + // NOTE: the reason for including the time here rather than have it in + // in the value assigned to lastEntropy is that rand() could be broken and + // using the time would in the lastEntropy value would hide this. + rndNum ^= (uint32_t)_plat__RealTime(); + + // Only provide entropy 32 bits at a time to test the ability + // of the caller to deal with partial results. + ret = MIN(amount, sizeof(rndNum)); + memcpy(entropy, &rndNum, ret); + } + } + return ret; +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/LocalityPlat.c b/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/LocalityPlat.c new file mode 100644 index 0000000..9fb2993 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/LocalityPlat.c @@ -0,0 +1,57 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Includes +#include "Platform.h" + +//** Functions + +//***_plat__LocalityGet() +// Get the most recent command locality in locality value form. +// This is an integer value for locality and not a locality structure +// The locality can be 0-4 or 32-255. 5-31 is not allowed. +LIB_EXPORT unsigned char _plat__LocalityGet(void) +{ + return s_locality; +} + +//***_plat__LocalitySet() +// Set the most recent command locality in locality value form +LIB_EXPORT void _plat__LocalitySet(unsigned char locality) +{ + if(locality > 4 && locality < 32) + locality = 0; + s_locality = locality; + return; +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/NVMem.c b/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/NVMem.c new file mode 100644 index 0000000..29d9213 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/NVMem.c @@ -0,0 +1,372 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Description +// +// This file contains the NV read and write access methods. This implementation +// uses RAM/file and does not manage the RAM/file as NV blocks. +// The implementation may become more sophisticated over time. +// + +//** Includes and Local +#include +#include +#include +#include "Platform.h" +#if FILE_BACKED_NV +# include +static FILE* s_NvFile = NULL; +static int s_NeedsManufacture = FALSE; +#endif + +//**Functions + +#if FILE_BACKED_NV + +//*** NvFileOpen() +// This function opens the file used to hold the NV image. +// Return Type: int +// >= 0 success +// -1 error +static int NvFileOpen(const char* mode) +{ +# if defined(NV_FILE_PATH) +# define TO_STRING(s) TO_STRING_IMPL(s) +# define TO_STRING_IMPL(s) #s + const char* s_NvFilePath = TO_STRING(NV_FILE_PATH); +# undef TO_STRING +# undef TO_STRING_IMPL +# else + const char* s_NvFilePath = "NVChip"; +# endif + + // Try to open an exist NVChip file for read/write +# if defined _MSC_VER && 1 + if(fopen_s(&s_NvFile, s_NvFilePath, mode) != 0) + s_NvFile = NULL; +# else + s_NvFile = fopen(s_NvFilePath, mode); +# endif + return (s_NvFile == NULL) ? -1 : 0; +} + +//*** NvFileCommit() +// Write all of the contents of the NV image to a file. +// Return Type: int +// TRUE(1) success +// FALSE(0) failure +static int NvFileCommit(void) +{ + int OK; + // If NV file is not available, return failure + if(s_NvFile == NULL) + return 1; + // Write RAM data to NV + fseek(s_NvFile, 0, SEEK_SET); + OK = (NV_MEMORY_SIZE == fwrite(s_NV, 1, NV_MEMORY_SIZE, s_NvFile)); + OK = OK && (0 == fflush(s_NvFile)); + assert(OK); + return OK; +} + +//*** NvFileSize() +// This function gets the size of the NV file and puts the file pointer where desired +// using the seek method values. SEEK_SET => beginning; SEEK_CUR => current position +// and SEEK_END => to the end of the file. +static long NvFileSize(int leaveAt) +{ + long fileSize; + long filePos = ftell(s_NvFile); + // + assert(NULL != s_NvFile); + + int fseek_result = fseek(s_NvFile, 0, SEEK_END); + NOT_REFERENCED(fseek_result); // Fix compiler warning for NDEBUG + assert(fseek_result == 0); + fileSize = ftell(s_NvFile); + assert(fileSize >= 0); + switch(leaveAt) + { + case SEEK_SET: + filePos = 0; + case SEEK_CUR: + fseek(s_NvFile, filePos, SEEK_SET); + break; + case SEEK_END: + break; + default: + assert(FALSE); + break; + } + return fileSize; +} +#endif + +//*** _plat__NvErrors() +// This function is used by the simulator to set the error flags in the NV +// subsystem to simulate an error in the NV loading process +LIB_EXPORT void _plat__NvErrors(int recoverable, int unrecoverable) +{ + s_NV_unrecoverable = unrecoverable; + s_NV_recoverable = recoverable; +} + +//***_plat__NVEnable() +// Enable NV memory. +// +// This version just pulls in data from a file. In a real TPM, with NV on chip, +// this function would verify the integrity of the saved context. If the NV +// memory was not on chip but was in something like RPMB, the NV state would be +// read in, decrypted and integrity checked. +// +// The recovery from an integrity failure depends on where the error occurred. It +// it was in the state that is discarded by TPM Reset, then the error is +// recoverable if the TPM is reset. Otherwise, the TPM must go into failure mode. +// Return Type: int +// 0 if success +// > 0 if receive recoverable error +// <0 if unrecoverable error +LIB_EXPORT int _plat__NVEnable( + void* platParameter // IN: platform specific parameters +) +{ + NOT_REFERENCED(platParameter); // to keep compiler quiet + // + // Start assuming everything is OK + s_NV_unrecoverable = FALSE; + s_NV_recoverable = FALSE; +#if FILE_BACKED_NV + if(s_NvFile != NULL) + return 0; + // Initialize all the bytes in the ram copy of the NV + _plat__NvMemoryClear(0, NV_MEMORY_SIZE); + + // If the file exists + if(NvFileOpen("r+b") >= 0) + { + long fileSize = NvFileSize(SEEK_SET); // get the file size and leave the + // file pointer at the start + // + // If the size is right, read the data + if(NV_MEMORY_SIZE == fileSize) + { + s_NeedsManufacture = fread(s_NV, 1, NV_MEMORY_SIZE, s_NvFile) + != NV_MEMORY_SIZE; + } + else + { + NvFileCommit(); // for any other size, initialize it + s_NeedsManufacture = TRUE; + } + } + // If NVChip file does not exist, try to create it for read/write. + else if(NvFileOpen("w+b") >= 0) + { + NvFileCommit(); // Initialize the file + s_NeedsManufacture = TRUE; + } + assert(NULL != s_NvFile); // Just in case we are broken for some reason. +#endif + // NV contents have been initialized and the error checks have been performed. For + // simulation purposes, use the signaling interface to indicate if an error is + // to be simulated and the type of the error. + if(s_NV_unrecoverable) + return -1; + return s_NV_recoverable; +} + +//***_plat__NVDisable() +// Disable NV memory +LIB_EXPORT void _plat__NVDisable(int delete // IN: If TRUE, delete the NV contents. +) +{ +#if FILE_BACKED_NV + if(NULL != s_NvFile) + { + fclose(s_NvFile); // Close NV file + // Alternative to deleting the file is to set its size to 0. This will not + // match the NV size so the TPM will need to be remanufactured. + if(delete) + { + // Open for writing at the start. Sets the size to zero. + if(NvFileOpen("w") >= 0) + { + fflush(s_NvFile); + fclose(s_NvFile); + } + } + } + s_NvFile = NULL; // Set file handle to NULL +#endif + return; +} + +//***_plat__IsNvAvailable() +// Check if NV is available +// Return Type: int +// 0 NV is available +// 1 NV is not available due to write failure +// 2 NV is not available due to rate limit +LIB_EXPORT int _plat__IsNvAvailable(void) +{ + int retVal = 0; + // NV is not available if the TPM is in failure mode + if(!s_NvIsAvailable) + retVal = 1; +#if FILE_BACKED_NV + else + retVal = (s_NvFile == NULL); +#endif + return retVal; +} + +//***_plat__NvMemoryRead() +// Function: Read a chunk of NV memory +LIB_EXPORT void _plat__NvMemoryRead(unsigned int startOffset, // IN: read start + unsigned int size, // IN: size of bytes to read + void* data // OUT: data buffer +) +{ + assert(startOffset + size <= NV_MEMORY_SIZE); + memcpy(data, &s_NV[startOffset], size); // Copy data from RAM + return; +} + +//*** _plat__NvIsDifferent() +// This function checks to see if the NV is different from the test value. This is +// so that NV will not be written if it has not changed. +// Return Type: int +// TRUE(1) the NV location is different from the test value +// FALSE(0) the NV location is the same as the test value +LIB_EXPORT int _plat__NvIsDifferent(unsigned int startOffset, // IN: read start + unsigned int size, // IN: size of bytes to read + void* data // IN: data buffer +) +{ + return (memcmp(&s_NV[startOffset], data, size) != 0); +} + +//***_plat__NvMemoryWrite() +// This function is used to update NV memory. The "write" is to a memory copy of +// NV. At the end of the current command, any changes are written to +// the actual NV memory. +// NOTE: A useful optimization would be for this code to compare the current +// contents of NV with the local copy and note the blocks that have changed. Then +// only write those blocks when _plat__NvCommit() is called. +LIB_EXPORT int _plat__NvMemoryWrite(unsigned int startOffset, // IN: write start + unsigned int size, // IN: size of bytes to write + void* data // OUT: data buffer +) +{ + if(startOffset + size <= NV_MEMORY_SIZE) + { + memcpy(&s_NV[startOffset], data, size); // Copy the data to the NV image + return TRUE; + } + return FALSE; +} + +//***_plat__NvMemoryClear() +// Function is used to set a range of NV memory bytes to an implementation-dependent +// value. The value represents the erase state of the memory. +LIB_EXPORT void _plat__NvMemoryClear( + unsigned int start, // IN: clear start + unsigned int size // IN: number of bytes to clear +) +{ + assert(start + size <= NV_MEMORY_SIZE); + // In this implementation, assume that the erase value for NV is all 1s + memset(&s_NV[start], 0xff, size); +} + +//***_plat__NvMemoryMove() +// Function: Move a chunk of NV memory from source to destination +// This function should ensure that if there overlap, the original data is +// copied before it is written +LIB_EXPORT void _plat__NvMemoryMove( + unsigned int sourceOffset, // IN: source offset + unsigned int destOffset, // IN: destination offset + unsigned int size // IN: size of data being moved +) +{ + assert(sourceOffset + size <= NV_MEMORY_SIZE); + assert(destOffset + size <= NV_MEMORY_SIZE); + memmove(&s_NV[destOffset], &s_NV[sourceOffset], size); // Move data in RAM + return; +} + +//***_plat__NvCommit() +// This function writes the local copy of NV to NV for permanent store. It will write +// NV_MEMORY_SIZE bytes to NV. If a file is use, the entire file is written. +// Return Type: int +// 0 NV write success +// non-0 NV write fail +LIB_EXPORT int _plat__NvCommit(void) +{ +#if FILE_BACKED_NV + return (NvFileCommit() ? 0 : 1); +#else + return 0; +#endif +} + +//***_plat__SetNvAvail() +// Set the current NV state to available. This function is for testing purpose +// only. It is not part of the platform NV logic +LIB_EXPORT void _plat__SetNvAvail(void) +{ + s_NvIsAvailable = TRUE; + return; +} + +//***_plat__ClearNvAvail() +// Set the current NV state to unavailable. This function is for testing purpose +// only. It is not part of the platform NV logic +LIB_EXPORT void _plat__ClearNvAvail(void) +{ + s_NvIsAvailable = FALSE; + return; +} + +//*** _plat__NVNeedsManufacture() +// This function is used by the simulator to determine when the TPM's NV state +// needs to be manufactured. +LIB_EXPORT int _plat__NVNeedsManufacture(void) +{ +#if FILE_BACKED_NV + return s_NeedsManufacture; +#else + return FALSE; +#endif +} diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/PPPlat.c b/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/PPPlat.c new file mode 100644 index 0000000..d762538 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/PPPlat.c @@ -0,0 +1,70 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Description + +// This module simulates the physical presence interface pins on the TPM. + +//** Includes +#include "Platform.h" + +//** Functions + +//***_plat__PhysicalPresenceAsserted() +// Check if physical presence is signaled +// Return Type: int +// TRUE(1) if physical presence is signaled +// FALSE(0) if physical presence is not signaled +LIB_EXPORT int _plat__PhysicalPresenceAsserted(void) +{ + // Do not know how to check physical presence without real hardware. + // so always return TRUE; + return s_physicalPresence; +} + +//***_plat__Signal_PhysicalPresenceOn() +// Signal physical presence on +LIB_EXPORT void _plat__Signal_PhysicalPresenceOn(void) +{ + s_physicalPresence = TRUE; + return; +} + +//***_plat__Signal_PhysicalPresenceOff() +// Signal physical presence off +LIB_EXPORT void _plat__Signal_PhysicalPresenceOff(void) +{ + s_physicalPresence = FALSE; + return; +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/PlatformACT.c b/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/PlatformACT.c new file mode 100644 index 0000000..e69f024 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/PlatformACT.c @@ -0,0 +1,302 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Includes +#include "Platform.h" + +//** Functions + +//*** ActSignal() +// Function called when there is an ACT event to signal or unsignal +static void ActSignal(P_ACT_DATA actData, int on) +{ + if(actData == NULL) + return; + // If this is to turn a signal on, don't do anything if it is already on. If this + // is to turn the signal off, do it anyway because this might be for + // initialization. + if(on && (actData->signaled == TRUE)) + return; + actData->signaled = (uint8_t)on; + + // If there is an action, then replace the "Do something" with the correct action. + // It should test 'on' to see if it is turning the signal on or off. + switch(actData->number) + { +#if RH_ACT_0 + case 0: // Do something + return; +#endif +#if RH_ACT_1 + case 1: // Do something + return; +#endif +#if RH_ACT_2 + case 2: // Do something + return; +#endif +#if RH_ACT_3 + case 3: // Do something + return; +#endif +#if RH_ACT_4 + case 4: // Do something + return; +#endif +#if RH_ACT_5 + case 5: // Do something + return; +#endif +#if RH_ACT_6 + case 6: // Do something + return; +#endif +#if RH_ACT_7 + case 7: // Do something + return; +#endif +#if RH_ACT_8 + case 8: // Do something + return; +#endif +#if RH_ACT_9 + case 9: // Do something + return; +#endif +#if RH_ACT_A + case 0xA: // Do something + return; +#endif +#if RH_ACT_B + case 0xB: + // Do something + return; +#endif +#if RH_ACT_C + case 0xC: // Do something + return; +#endif +#if RH_ACT_D + case 0xD: // Do something + return; +#endif +#if RH_ACT_E + case 0xE: // Do something + return; +#endif +#if RH_ACT_F + case 0xF: // Do something + return; +#endif + default: + return; + } +} + +//*** ActGetDataPointer() +static P_ACT_DATA ActGetDataPointer(uint32_t act) +{ + +#define RETURN_ACT_POINTER(N) \ + if(0x##N == act) \ + return &ACT_##N; + + FOR_EACH_ACT(RETURN_ACT_POINTER) + + return (P_ACT_DATA)NULL; +} + +//*** _plat__ACT_GetImplemented() +// This function tests to see if an ACT is implemented. It is a belt and suspenders +// function because the TPM should not be calling to manipulate an ACT that is not +// implemented. However, this could help the simulator code which doesn't necessarily +// know if an ACT is implemented or not. +LIB_EXPORT int _plat__ACT_GetImplemented(uint32_t act) +{ + return (ActGetDataPointer(act) != NULL); +} + +//*** _plat__ACT_GetRemaining() +// This function returns the remaining time. If an update is pending, 'newValue' is +// returned. Otherwise, the current counter value is returned. Note that since the +// timers keep running, the returned value can get stale immediately. The actual count +// value will be no greater than the returned value. +LIB_EXPORT uint32_t _plat__ACT_GetRemaining(uint32_t act //IN: the ACT selector +) +{ + P_ACT_DATA actData = ActGetDataPointer(act); + uint32_t remain; + // + if(actData == NULL) + return 0; + remain = actData->remaining; + if(actData->pending) + remain = actData->newValue; + return remain; +} + +//*** _plat__ACT_GetSignaled() +LIB_EXPORT int _plat__ACT_GetSignaled(uint32_t act //IN: number of ACT to check +) +{ + P_ACT_DATA actData = ActGetDataPointer(act); + // + if(actData == NULL) + return 0; + return (int)actData->signaled; +} + +//*** _plat__ACT_SetSignaled() +LIB_EXPORT void _plat__ACT_SetSignaled(uint32_t act, int on) +{ + ActSignal(ActGetDataPointer(act), on); +} + +//*** _plat__ACT_GetPending() +LIB_EXPORT int _plat__ACT_GetPending(uint32_t act //IN: number of ACT to check +) +{ + P_ACT_DATA actData = ActGetDataPointer(act); + // + if(actData == NULL) + return 0; + return (int)actData->pending; +} + +//*** _plat__ACT_UpdateCounter() +// This function is used to write the newValue for the counter. If an update is +// pending, then no update occurs and the function returns FALSE. If 'setSignaled' +// is TRUE, then the ACT signaled state is SET and if 'newValue' is 0, nothing +// is posted. +LIB_EXPORT int _plat__ACT_UpdateCounter(uint32_t act, // IN: ACT to update + uint32_t newValue // IN: the value to post +) +{ + P_ACT_DATA actData = ActGetDataPointer(act); + // + if(actData == NULL) + // actData doesn't exist but pretend update is pending rather than indicate + // that a retry is necessary. + return TRUE; + // if an update is pending then return FALSE so that there will be a retry + if(actData->pending != 0) + return FALSE; + actData->newValue = newValue; + actData->pending = TRUE; + + return TRUE; +} + +//***_plat__ACT_EnableTicks() +// This enables and disables the processing of the once-per-second ticks. This should +// be turned off ('enable' = FALSE) by _TPM_Init and turned on ('enable' = TRUE) by +// TPM2_Startup() after all the initializations have completed. +LIB_EXPORT void _plat__ACT_EnableTicks(int enable) +{ + actTicksAllowed = enable; +} + +//*** ActDecrement() +// If 'newValue' is non-zero it is copied to 'remaining' and then 'newValue' is +// set to zero. Then 'remaining' is decremented by one if it is not already zero. If +// the value is decremented to zero, then the associated event is signaled. If setting +// 'remaining' causes it to be greater than 1, then the signal associated with the ACT +// is turned off. +static void ActDecrement(P_ACT_DATA actData) +{ + // Check to see if there is an update pending + if(actData->pending) + { + // If this update will cause the count to go from non-zero to zero, set + // the newValue to 1 so that it will timeout when decremented below. + if((actData->newValue == 0) && (actData->remaining != 0)) + actData->newValue = 1; + actData->remaining = actData->newValue; + + // Update processed + actData->pending = 0; + } + // no update so countdown if the count is non-zero but not max + if((actData->remaining != 0) && (actData->remaining != UINT32_MAX)) + { + // If this countdown causes the count to go to zero, then turn the signal for + // the ACT on. + if((actData->remaining -= 1) == 0) + ActSignal(actData, TRUE); + } + // If the current value of the counter is non-zero, then the signal should be + // off. + if(actData->signaled && (actData->remaining > 0)) + ActSignal(actData, FALSE); +} + +//*** _plat__ACT_Tick() +// This processes the once-per-second clock tick from the hardware. This is set up +// for the simulator to use the control interface to send ticks to the TPM. These +// ticks do not have to be on a per second basis. They can be as slow or as fast as +// desired so that the simulation can be tested. +LIB_EXPORT void _plat__ACT_Tick(void) +{ + // Ticks processing is turned off at certain times just to make sure that nothing + // strange is happening before pointers and things are + if(actTicksAllowed) + { + // Handle the update for each counter. +#define DECREMENT_COUNT(N) ActDecrement(&ACT_##N); + + FOR_EACH_ACT(DECREMENT_COUNT) + } +} + +//*** ActZero() +// This function initializes a single ACT +static void ActZero(uint32_t act, P_ACT_DATA actData) +{ + actData->remaining = 0; + actData->newValue = 0; + actData->pending = 0; + actData->number = (uint8_t)act; + ActSignal(actData, FALSE); +} + +//***_plat__ACT_Initialize() +// This function initializes the ACT hardware and data structures +LIB_EXPORT int _plat__ACT_Initialize(void) +{ + actTicksAllowed = 0; +#define ZERO_ACT(N) ActZero(0x##N, &ACT_##N); + FOR_EACH_ACT(ZERO_ACT) + + return TRUE; +} diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/PlatformData.c b/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/PlatformData.c new file mode 100644 index 0000000..4309292 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/PlatformData.c @@ -0,0 +1,41 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Description +// This file will instance the TPM variables that are not stack allocated. The +// descriptions for these variables are in Global.h for this project. + +//** Includes +#define _PLATFORM_DATA_C_ +#include "Platform.h" diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/PowerPlat.c b/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/PowerPlat.c new file mode 100644 index 0000000..5fda66d --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/PowerPlat.c @@ -0,0 +1,103 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Includes and Function Prototypes + +#include "Platform.h" +#include "_TPM_Init_fp.h" + +//** Functions + +//***_plat__Signal_PowerOn() +// Signal platform power on +LIB_EXPORT int _plat__Signal_PowerOn(void) +{ + // Reset the timer + _plat__TimerReset(); + + // Need to indicate that we lost power + s_powerLost = TRUE; + + return 0; +} + +//*** _plat__WasPowerLost() +// Test whether power was lost before a _TPM_Init. +// +// This function will clear the "hardware" indication of power loss before return. +// This means that there can only be one spot in the TPM code where this value +// gets read. This method is used here as it is the most difficult to manage in the +// TPM code and, if the hardware actually works this way, it is hard to make it +// look like anything else. So, the burden is placed on the TPM code rather than the +// platform code +// Return Type: int +// TRUE(1) power was lost +// FALSE(0) power was not lost +LIB_EXPORT int _plat__WasPowerLost(void) +{ + int retVal = s_powerLost; + s_powerLost = FALSE; + return retVal; +} + +//*** _plat_Signal_Reset() +// This a TPM reset without a power loss. +LIB_EXPORT int _plat__Signal_Reset(void) +{ + // Initialize locality + s_locality = 0; + + // Command cancel + s_isCanceled = FALSE; + + _TPM_Init(); + + // if we are doing reset but did not have a power failure, then we should + // not need to reload NV ... + + return 0; +} + +//***_plat__Signal_PowerOff() +// Signal platform power off +LIB_EXPORT void _plat__Signal_PowerOff(void) +{ + // Prepare NV memory for power off + _plat__NVDisable(0); + + // Disable tick ACT tick processing + _plat__ACT_EnableTicks(FALSE); + + return; +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/RunCommand.c b/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/RunCommand.c new file mode 100644 index 0000000..114421e --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/RunCommand.c @@ -0,0 +1,81 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//**Introduction +// This module provides the platform specific entry and fail processing. The +// _plat__RunCommand() function is used to call to ExecuteCommand() in the TPM code. +// This function does whatever processing is necessary to set up the platform +// in anticipation of the call to the TPM including settup for error processing. +// +// The _plat__Fail() function is called when there is a failure in the TPM. The TPM +// code will have set the flag to indicate that the TPM is in failure mode. +// This call will then recursively call ExecuteCommand in order to build the +// failure mode response. When ExecuteCommand() returns to _plat__Fail(), the +// platform will do some platform specif operation to return to the environment in +// which the TPM is executing. For a simulator, setjmp/longjmp is used. For an OS, +// a system exit to the OS would be appropriate. + +//** Includes and locals +#include "Platform.h" +#include +#include "ExecCommand_fp.h" + +jmp_buf s_jumpBuffer; + +//** Functions + +//***_plat__RunCommand() +// This version of RunCommand will set up a jum_buf and call ExecuteCommand(). If +// the command executes without failing, it will return and RunCommand will return. +// If there is a failure in the command, then _plat__Fail() is called and it will +// longjump back to RunCommand which will call ExecuteCommand again. However, this +// time, the TPM will be in failure mode so ExecuteCommand will simply build +// a failure response and return. +LIB_EXPORT void _plat__RunCommand( + uint32_t requestSize, // IN: command buffer size + unsigned char* request, // IN: command buffer + uint32_t* responseSize, // IN/OUT: response buffer size + unsigned char** response // IN/OUT: response buffer +) +{ + setjmp(s_jumpBuffer); + ExecuteCommand(requestSize, request, responseSize, response); +} + +//***_plat__Fail() +// This is the platform depended failure exit for the TPM. +LIB_EXPORT NORETURN void _plat__Fail(void) +{ + longjmp(&s_jumpBuffer[0], 1); +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/Unique.c b/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/Unique.c new file mode 100644 index 0000000..1b8237e --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/Platform/src/Unique.c @@ -0,0 +1,82 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// In some implementations of the TPM, the hardware can provide a secret +// value to the TPM. This secret value is statistically unique to the +// instance of the TPM. Typical uses of this value are to provide +// personalization to the random number generation and as a shared secret +// between the TPM and the manufacturer. + +//** Includes +#include "Platform.h" + +const char notReallyUnique[] = "This is not really a unique value. A real unique " + "value should" + " be generated by the platform."; + +//** _plat__GetUnique() +// This function is used to access the platform-specific unique value. +// This function places the unique value in the provided buffer ('b') +// and returns the number of bytes transferred. The function will not +// copy more data than 'bSize'. +// NOTE: If a platform unique value has unequal distribution of uniqueness +// and 'bSize' is smaller than the size of the unique value, the 'bSize' +// portion with the most uniqueness should be returned. +LIB_EXPORT uint32_t _plat__GetUnique(uint32_t which, // authorities (0) or details + uint32_t bSize, // size of the buffer + unsigned char* b // output buffer +) +{ + const char* from = notReallyUnique; + uint32_t retVal = 0; + + if(which == 0) // the authorities value + { + for(retVal = 0; *from != 0 && retVal < bSize; retVal++) + { + *b++ = *from++; + } + } + else + { +#define uSize sizeof(notReallyUnique) + b = &b[((bSize < uSize) ? bSize : uSize) - 1]; + for(retVal = 0; *from != 0 && retVal < bSize; retVal++) + { + *b-- = *from++; + } + } + return retVal; +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/include/TpmTcpProtocol.h b/optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/include/TpmTcpProtocol.h new file mode 100644 index 0000000..e7b8d7a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/include/TpmTcpProtocol.h @@ -0,0 +1,126 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction + +// TPM commands are communicated as uint8_t streams on a TCP connection. The TPM +// command protocol is enveloped with the interface protocol described in this +// file. The command is indicated by a uint32 with one of the values below. Most +// commands take no parameters return no TPM errors. In these cases the TPM +// interface protocol acknowledges that command processing is completed by returning +// a uint32=0. The command TPM_SIGNAL_HASH_DATA takes a uint32-prepended variable +// length byte array and the interface protocol acknowledges command completion +// with a uint32=0. Most TPM commands are enveloped using the TPM_SEND_COMMAND +// interface command. The parameters are as indicated below. The interface layer +// also appends a UIN32=0 to the TPM response for regularity. + +//** Typedefs and Defines +#ifndef TCP_TPM_PROTOCOL_H +#define TCP_TPM_PROTOCOL_H + +//** TPM Commands. +// All commands acknowledge processing by returning a uint32 == 0 except where noted +#define TPM_SIGNAL_POWER_ON 1 +#define TPM_SIGNAL_POWER_OFF 2 +#define TPM_SIGNAL_PHYS_PRES_ON 3 +#define TPM_SIGNAL_PHYS_PRES_OFF 4 +#define TPM_SIGNAL_HASH_START 5 +#define TPM_SIGNAL_HASH_DATA 6 +// {uint32_t BufferSize, uint8_t[BufferSize] Buffer} +#define TPM_SIGNAL_HASH_END 7 +#define TPM_SEND_COMMAND 8 +// {uint8_t Locality, uint32_t InBufferSize, uint8_t[InBufferSize] InBuffer} -> +// {uint32_t OutBufferSize, uint8_t[OutBufferSize] OutBuffer} + +#define TPM_SIGNAL_CANCEL_ON 9 +#define TPM_SIGNAL_CANCEL_OFF 10 +#define TPM_SIGNAL_NV_ON 11 +#define TPM_SIGNAL_NV_OFF 12 +#define TPM_SIGNAL_KEY_CACHE_ON 13 +#define TPM_SIGNAL_KEY_CACHE_OFF 14 + +#define TPM_REMOTE_HANDSHAKE 15 +#define TPM_SET_ALTERNATIVE_RESULT 16 + +#define TPM_SIGNAL_RESET 17 +#define TPM_SIGNAL_RESTART 18 + +#define TPM_SESSION_END 20 +#define TPM_STOP 21 + +#define TPM_GET_COMMAND_RESPONSE_SIZES 25 + +#define TPM_ACT_GET_SIGNALED 26 + +#define TPM_TEST_FAILURE_MODE 30 + +//** Enumerations and Structures +enum TpmEndPointInfo +{ + tpmPlatformAvailable = 0x01, + tpmUsesTbs = 0x02, + tpmInRawMode = 0x04, + tpmSupportsPP = 0x08 +}; + +#ifdef _MSC_VER +# pragma warning(push, 3) +#endif + +// Existing RPC interface type definitions retained so that the implementation +// can be re-used +typedef struct in_buffer +{ + unsigned long BufferSize; + unsigned char* Buffer; +} _IN_BUFFER; + +typedef unsigned char* _OUTPUT_BUFFER; + +typedef struct out_buffer +{ + uint32_t BufferSize; + _OUTPUT_BUFFER Buffer; +} _OUT_BUFFER; + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + +#ifndef WIN32 +typedef unsigned long DWORD; +typedef void* LPVOID; +#endif + +#endif diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/include/prototypes/Simulator_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/include/prototypes/Simulator_fp.h new file mode 100644 index 0000000..12ad7ed --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/include/prototypes/Simulator_fp.h @@ -0,0 +1,201 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 4, 2020 Time: 02:36:45PM + */ + +#ifndef _SIMULATOR_FP_H_ +#define _SIMULATOR_FP_H_ + +//** From TcpServer.c + +#ifdef _MSC_VER +#elif defined(__unix__) || defined(__APPLE__) +#endif + +//*** PlatformServer() +// This function processes incoming platform requests. +bool PlatformServer(SOCKET s); + +//*** PlatformSvcRoutine() +// This function is called to set up the socket interfaces to listen for +// commands. +DWORD WINAPI PlatformSvcRoutine(LPVOID port); + +//*** PlatformSignalService() +// This function starts a new thread waiting for platform signals. +// Platform signals are processed one at a time in the order in which they are +// received. +int PlatformSignalService(int PortNumber); + +//*** RegularCommandService() +// This function services regular commands. +int RegularCommandService(int PortNumber); + +//*** StartTcpServer() +// This is the main entry-point to the TCP server. The server listens on port +// specified. +// +// Note that there is no way to specify the network interface in this implementation. +int StartTcpServer(int PortNumber); + +//*** ReadBytes() +// This function reads the indicated number of bytes ('NumBytes') into buffer +// from the indicated socket. +bool ReadBytes(SOCKET s, char* buffer, int NumBytes); + +//*** WriteBytes() +// This function will send the indicated number of bytes ('NumBytes') to the +// indicated socket +bool WriteBytes(SOCKET s, char* buffer, int NumBytes); + +//*** WriteUINT32() +// Send 4 byte integer +bool WriteUINT32(SOCKET s, uint32_t val); + +//*** ReadUINT32() +// Function to read 4 byte integer from socket. +bool ReadUINT32(SOCKET s, uint32_t* val); + +//*** ReadVarBytes() +// Get a uint32-length-prepended binary array. Note that the 4-byte length is +// in network byte order (big-endian). +bool ReadVarBytes(SOCKET s, char* buffer, uint32_t* BytesReceived, int MaxLen); + +//*** WriteVarBytes() +// Send a UINT32-length-prepended binary array. Note that the 4-byte length is +// in network byte order (big-endian). +bool WriteVarBytes(SOCKET s, char* buffer, int BytesToSend); + +//*** TpmServer() +// Processing incoming TPM command requests using the protocol / interface +// defined above. +bool TpmServer(SOCKET s); + +//** From TPMCmdp.c + +#ifdef _MSC_VER +#elif defined(__unix__) || defined(__APPLE__) +#endif + +//*** Signal_PowerOn() +// This function processes a power-on indication. Among other things, it +// calls the _TPM_Init() handler. +void _rpc__Signal_PowerOn(bool isReset); + +//*** Signal_Restart() +// This function processes the clock restart indication. All it does is call +// the platform function. +void _rpc__Signal_Restart(void); + +//***Signal_PowerOff() +// This function processes the power off indication. Its primary function is +// to set a flag indicating that the next power on indication should cause +// _TPM_Init() to be called. +void _rpc__Signal_PowerOff(void); + +//*** _rpc__ForceFailureMode() +// This function is used to debug the Failure Mode logic of the TPM. It will set +// a flag in the TPM code such that the next call to TPM2_SelfTest() will result +// in a failure, putting the TPM into Failure Mode. +void _rpc__ForceFailureMode(void); + +//*** _rpc__Signal_PhysicalPresenceOn() +// This function is called to simulate activation of the physical presence "pin". +void _rpc__Signal_PhysicalPresenceOn(void); + +//*** _rpc__Signal_PhysicalPresenceOff() +// This function is called to simulate deactivation of the physical presence "pin". +void _rpc__Signal_PhysicalPresenceOff(void); + +//*** _rpc__Signal_Hash_Start() +// This function is called to simulate a _TPM_Hash_Start event. It will call +// +void _rpc__Signal_Hash_Start(void); + +//*** _rpc__Signal_Hash_Data() +// This function is called to simulate a _TPM_Hash_Data event. +void _rpc__Signal_Hash_Data(_IN_BUFFER input); + +//*** _rpc__Signal_HashEnd() +// This function is called to simulate a _TPM_Hash_End event. +void _rpc__Signal_HashEnd(void); + +//*** _rpc__Send_Command() +// This is the interface to the TPM code. +// Return Type: void +void _rpc__Send_Command( + unsigned char locality, _IN_BUFFER request, _OUT_BUFFER* response); + +//*** _rpc__Signal_CancelOn() +// This function is used to turn on the indication to cancel a command in process. +// An executing command is not interrupted. The command code may periodically check +// this indication to see if it should abort the current command processing and +// returned TPM_RC_CANCELLED. +void _rpc__Signal_CancelOn(void); + +//*** _rpc__Signal_CancelOff() +// This function is used to turn off the indication to cancel a command in process. +void _rpc__Signal_CancelOff(void); + +//*** _rpc__Signal_NvOn() +// In a system where the NV memory used by the TPM is not within the TPM, the +// NV may not always be available. This function turns on the indicator that +// indicates that NV is available. +void _rpc__Signal_NvOn(void); + +//*** _rpc__Signal_NvOff() +// This function is used to set the indication that NV memory is no +// longer available. +void _rpc__Signal_NvOff(void); + +//*** _rpc__RsaKeyCacheControl() +// This function is used to enable/disable the use of the RSA key cache during +// simulation. +void _rpc__RsaKeyCacheControl(int state); + +//*** _rpc__ACT_GetSignaled() +// This function is used to count the ACT second tick. +bool _rpc__ACT_GetSignaled(uint32_t actHandle); + +//** From TPMCmds.c + +//*** main() +// This is the main entry point for the simulator. +// It registers the interface and starts listening for clients +int main(int argc, char* argv[]); + +#endif // _SIMULATOR_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/simulator.vcxproj b/optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/simulator.vcxproj new file mode 100644 index 0000000..ac23db5 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/simulator.vcxproj @@ -0,0 +1,491 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + Static + Win32 + + + Static + x64 + + + WolfDebug + Win32 + + + WolfDebug + x64 + + + WolfRelease + Win32 + + + WolfRelease + x64 + + + + {AAB9FA21-8671-4792-B000-B40A526058AD} + simulator + Win32Proj + Simulator + $([Microsoft.Build.Utilities.ToolLocationHelper]::GetLatestSDKTargetPlatformVersion('Windows', '10.0')) + + + + Application + Unicode + false + v141 + + + Application + Unicode + false + v141 + + + Application + Unicode + false + v141 + + + Application + Unicode + false + v141 + + + Application + Unicode + v141 + + + Application + Unicode + v141 + + + Application + Unicode + v141 + + + Application + Unicode + v141 + + + Application + Unicode + v141 + + + Application + Unicode + v141 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)\$(Configuration)\ + $(SolutionDir)\bin\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)\bin\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)\bin\$(ProjectName)\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)\bin\$(ProjectName)\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)\bin\$(ProjectName)\$(PlatformTarget)\$(Configuration)\ + true + true + true + true + true + true + $(SolutionDir)\$(Configuration)\ + $(SolutionDir)\bin\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)\bin\$(ProjectName)\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)\bin\$(ProjectName)\$(PlatformTarget)\$(Configuration)\ + false + false + false + false + AllRules.ruleset + AllRules.ruleset + AllRules.ruleset + AllRules.ruleset + AllRules.ruleset + AllRules.ruleset + + + + + + + + + + + + + AllRules.ruleset + AllRules.ruleset + AllRules.ruleset + AllRules.ruleset + + + + + + + + + + + $(SolutionDir)\bin\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)\bin\$(ProjectName)\$(PlatformTarget)\$(Configuration)\ + + + $(SolutionDir)\bin\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)\bin\$(ProjectName)\$(PlatformTarget)\$(Configuration)\ + + + $(SolutionDir)\bin\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)\bin\$(ProjectName)\$(PlatformTarget)\$(Configuration)\ + + + $(SolutionDir)\bin\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)\bin\$(ProjectName)\$(PlatformTarget)\$(Configuration)\ + + + $(SolutionDir)\bin\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)\bin\$(ProjectName)\$(PlatformTarget)\$(Configuration)\ + + + false + + + false + + + + Disabled + $(ProjectDir)include\;$(ProjectDir)include\prototypes;$(SolutionDir)tpm\include\;$(SolutionDir)tpm\include\prototypes;$(SolutionDir)platform\include\;$(SolutionDir)platform\include\prototypes + WIN32;DEBUG;_CONSOLE;%(PreprocessorDefinitions);_DIAGNOSTICS + EnableFastChecks + MultiThreadedDebugDLL + NotUsing + EnableAllWarnings + ProgramDatabase + CompileAsC + true + true + 4127;4668;4710;4711;4820;5045 + + + + tpm.lib;platform.lib;Ws2_32.lib;Rpcrt4.lib;%(AdditionalDependencies) + $(OutDir);%(AdditionalLibraryDirectories) + true + Console + MachineX86 + $(OutDir)$(TargetName)$(TargetExt) + false + $(OutDir)Simulator.map + false + + + true + + + + + Disabled + $(ProjectDir)include\;$(ProjectDir)include\prototypes;$(SolutionDir)tpm\include\;$(SolutionDir)tpm\include\prototypes;$(SolutionDir)platform\include\;$(SolutionDir)platform\include\prototypes + WIN32;DEBUG;_CONSOLE;%(PreprocessorDefinitions);_DIAGNOSTICS + EnableFastChecks + MultiThreadedDebugDLL + NotUsing + EnableAllWarnings + ProgramDatabase + CompileAsC + true + true + 4127;4668;4710;4711;4820;5045 + + + + tpm.lib;platform.lib;Ws2_32.lib;Rpcrt4.lib;%(AdditionalDependencies) + $(OutDir);%(AdditionalLibraryDirectories) + true + Console + MachineX86 + $(OutDir)$(TargetName)$(TargetExt) + false + $(OutDir)Simulator.map + false + + + true + + + + + Disabled + $(ProjectDir)include\;$(ProjectDir)include\prototypes;$(SolutionDir)tpm\include\;$(SolutionDir)tpm\include\prototypes;$(SolutionDir)platform\include\;$(SolutionDir)platform\include\prototypes + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);_DIAGNOSTICS + EnableFastChecks + MultiThreadedDebugDLL + NotUsing + EnableAllWarnings + ProgramDatabase + CompileAsC + true + 4668;4710;4711;4820;5045 + + + + libeay32.lib;tpm.lib;platform.lib;Ws2_32.lib;Rpcrt4.lib;%(AdditionalDependencies) + $(SolutionDir)\lib;$(OutDir);%(AdditionalLibraryDirectories) + true + Console + MachineX86 + $(OutDir)$(TargetName)$(TargetExt) + + + + + Disabled + $(ProjectDir)include\;$(ProjectDir)include\prototypes;$(SolutionDir)tpm\include\;$(SolutionDir)tpm\include\prototypes;$(SolutionDir)platform\include\;$(SolutionDir)platform\include\prototypes + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);_DIAGNOSTICS + EnableFastChecks + MultiThreadedDebugDLL + + + EnableAllWarnings + ProgramDatabase + true + 4127;4668;4710;4711;4820;5045 + + + + tpm.lib;platform.lib;Ws2_32.lib;Rpcrt4.lib;%(AdditionalDependencies) + $(OutDir);%(AdditionalLibraryDirectories) + true + Console + + + + + Disabled + $(ProjectDir)include\;$(ProjectDir)include\prototypes;$(SolutionDir)tpm\include\;$(SolutionDir)tpm\include\prototypes;$(SolutionDir)platform\include\;$(SolutionDir)platform\include\prototypes + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);_DIAGNOSTICS + EnableFastChecks + MultiThreadedDebugDLL + + + EnableAllWarnings + ProgramDatabase + true + 4127;4668;4710;4711;4820;5045 + + + + tpm.lib;platform.lib;Ws2_32.lib;Rpcrt4.lib;%(AdditionalDependencies) + $(OutDir);%(AdditionalLibraryDirectories) + true + Console + + + + + Disabled + $(ProjectDir)include\;$(ProjectDir)include\prototypes;$(SolutionDir)tpm\include\;$(SolutionDir)tpm\include\prototypes;$(SolutionDir)platform\include\;$(SolutionDir)platform\include\prototypes + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);_DIAGNOSTICS + EnableFastChecks + MultiThreadedDebugDLL + + + EnableAllWarnings + ProgramDatabase + true + 4668;4710;4711;4820;5045 + + + + libeay32.lib;tpm.lib;platform.lib;Ws2_32.lib;Rpcrt4.lib;%(AdditionalDependencies) + $(SolutionDir)\lib\x64;$(OutDir);%(AdditionalLibraryDirectories) + true + Console + + + + + MaxSpeed + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + true + NotUsing + EnableAllWarnings + ProgramDatabase + $(ProjectDir)include\;$(ProjectDir)include\prototypes;$(SolutionDir)tpm\include\;$(SolutionDir)tpm\include\prototypes;$(SolutionDir)platform\include\;$(SolutionDir)platform\include\prototypes + true + 4668;4710;4711;4820;5045 + + + + true + Console + true + true + MachineX86 + tpm.lib;platform.lib;Ws2_32.lib;Rpcrt4.lib;%(AdditionalDependencies) + $(OutDir);%(AdditionalLibraryDirectories) + $(OutDir)$(TargetName)$(TargetExt) + + + + + MaxSpeed + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + true + NotUsing + EnableAllWarnings + ProgramDatabase + $(ProjectDir)include\;$(ProjectDir)include\prototypes;$(SolutionDir)tpm\include\;$(SolutionDir)tpm\include\prototypes;$(SolutionDir)platform\include\;$(SolutionDir)platform\include\prototypes + true + 4668;4710;4711;4820;5045 + + + + true + Console + true + true + MachineX86 + tpm.lib;platform.lib;Ws2_32.lib;Rpcrt4.lib;%(AdditionalDependencies) + $(OutDir);%(AdditionalLibraryDirectories) + $(OutDir)$(TargetName)$(TargetExt) + + + + + MaxSpeed + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + EnableAllWarnings + ProgramDatabase + $(ProjectDir)include\;$(ProjectDir)include\prototypes;$(SolutionDir)tpm\include\;$(SolutionDir)tpm\include\prototypes;$(SolutionDir)platform\include\;$(SolutionDir)platform\include\prototypes + true + 4668;4710;4711;4820;5045 + + + + true + Console + true + true + tpm.lib;platform.lib;Ws2_32.lib;Rpcrt4.lib + $(OutDir);%(AdditionalLibraryDirectories) + + + false + + + + + MaxSpeed + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + EnableAllWarnings + ProgramDatabase + $(ProjectDir)include\;$(ProjectDir)include\prototypes;$(SolutionDir)tpm\include\;$(SolutionDir)tpm\include\prototypes;$(SolutionDir)platform\include\;$(SolutionDir)platform\include\prototypes + true + 4668;4710;4711;4820;5045 + + + + true + Console + true + true + tpm.lib;platform.lib;Ws2_32.lib;Rpcrt4.lib + $(ProjectDir)\lib;$(OutDir);%(AdditionalLibraryDirectories) + + + false + + + + + + + + + + + + + + \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/src/TPMCmdp.c b/optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/src/TPMCmdp.c new file mode 100644 index 0000000..3bcc590 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/src/TPMCmdp.c @@ -0,0 +1,282 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Description +// This file contains the functions that process the commands received on the +// control port or the command port of the simulator. The control port is used +// to allow simulation of hardware events (such as, _TPM_Hash_Start) to test +// the simulated TPM's reaction to those events. This improves code coverage +// of the testing. + +//** Includes and Data Definitions +#include +#include "TpmBuildSwitches.h" + +#ifdef _MSC_VER +# pragma warning(push, 3) +# include +# include +# pragma warning(pop) +#elif defined(__unix__) || defined(__APPLE__) +# include "BaseTypes.h" // on behalf of TpmFail_fp.h +typedef int SOCKET; +#else +# error "Unsupported platform." +#endif + +#include "Platform_fp.h" +#include "ExecCommand_fp.h" +#include "Manufacture_fp.h" +#include "_TPM_Init_fp.h" +#include "_TPM_Hash_Start_fp.h" +#include "_TPM_Hash_Data_fp.h" +#include "_TPM_Hash_End_fp.h" +#include "TpmFail_fp.h" + +#include "TpmTcpProtocol.h" +#include "Simulator_fp.h" + +static bool s_isPowerOn = false; + +//** Functions + +//*** Signal_PowerOn() +// This function processes a power-on indication. Among other things, it +// calls the _TPM_Init() handler. +void _rpc__Signal_PowerOn(bool isReset) +{ + // if power is on and this is not a call to do TPM reset then return + if(s_isPowerOn && !isReset) + return; + // If this is a reset but power is not on, then return + if(isReset && !s_isPowerOn) + return; + // Unless this is just a reset, pass power on signal to platform + if(!isReset) + _plat__Signal_PowerOn(); + // Power on and reset both lead to _TPM_Init() + _plat__Signal_Reset(); + + // Set state as power on + s_isPowerOn = true; +} + +//*** Signal_Restart() +// This function processes the clock restart indication. All it does is call +// the platform function. +void _rpc__Signal_Restart(void) +{ + _plat__TimerRestart(); +} + +//***Signal_PowerOff() +// This function processes the power off indication. Its primary function is +// to set a flag indicating that the next power on indication should cause +// _TPM_Init() to be called. +void _rpc__Signal_PowerOff(void) +{ + if(s_isPowerOn) + // Pass power off signal to platform + _plat__Signal_PowerOff(); + // This could be redundant, but... + s_isPowerOn = false; + + return; +} + +//*** _rpc__ForceFailureMode() +// This function is used to debug the Failure Mode logic of the TPM. It will set +// a flag in the TPM code such that the next call to TPM2_SelfTest() will result +// in a failure, putting the TPM into Failure Mode. +void _rpc__ForceFailureMode(void) +{ +#if SIMULATION + SetForceFailureMode(); +#endif + return; +} + +//*** _rpc__Signal_PhysicalPresenceOn() +// This function is called to simulate activation of the physical presence "pin". +void _rpc__Signal_PhysicalPresenceOn(void) +{ + // If TPM power is on... + if(s_isPowerOn) + // ... pass physical presence on to platform + _plat__Signal_PhysicalPresenceOn(); + return; +} + +//*** _rpc__Signal_PhysicalPresenceOff() +// This function is called to simulate deactivation of the physical presence "pin". +void _rpc__Signal_PhysicalPresenceOff(void) +{ + // If TPM is power on... + if(s_isPowerOn) + // ... pass physical presence off to platform + _plat__Signal_PhysicalPresenceOff(); + return; +} + +//*** _rpc__Signal_Hash_Start() +// This function is called to simulate a _TPM_Hash_Start event. It will call +// +void _rpc__Signal_Hash_Start(void) +{ + // If TPM power is on... + if(s_isPowerOn) + // ... pass _TPM_Hash_Start signal to TPM + _TPM_Hash_Start(); + return; +} + +//*** _rpc__Signal_Hash_Data() +// This function is called to simulate a _TPM_Hash_Data event. +void _rpc__Signal_Hash_Data(_IN_BUFFER input) +{ + // If TPM power is on... + if(s_isPowerOn) + // ... pass _TPM_Hash_Data signal to TPM + _TPM_Hash_Data(input.BufferSize, input.Buffer); + return; +} + +//*** _rpc__Signal_HashEnd() +// This function is called to simulate a _TPM_Hash_End event. +void _rpc__Signal_HashEnd(void) +{ + // If TPM power is on... + if(s_isPowerOn) + // ... pass _TPM_HashEnd signal to TPM + _TPM_Hash_End(); + return; +} + +//*** _rpc__Send_Command() +// This is the interface to the TPM code. +// Return Type: void +void _rpc__Send_Command( + unsigned char locality, _IN_BUFFER request, _OUT_BUFFER* response) +{ + // If TPM is power off, reject any commands. + if(!s_isPowerOn) + { + response->BufferSize = 0; + return; + } + // Set the locality of the command so that it doesn't change during the command + _plat__LocalitySet(locality); + // Do implementation-specific command dispatch + _plat__RunCommand( + request.BufferSize, request.Buffer, &response->BufferSize, &response->Buffer); + return; +} + +//*** _rpc__Signal_CancelOn() +// This function is used to turn on the indication to cancel a command in process. +// An executing command is not interrupted. The command code may periodically check +// this indication to see if it should abort the current command processing and +// returned TPM_RC_CANCELLED. +void _rpc__Signal_CancelOn(void) +{ + // If TPM power is on... + if(s_isPowerOn) + // ... set the platform canceling flag. + _plat__SetCancel(); + return; +} + +//*** _rpc__Signal_CancelOff() +// This function is used to turn off the indication to cancel a command in process. +void _rpc__Signal_CancelOff(void) +{ + // If TPM power is on... + if(s_isPowerOn) + // ... set the platform canceling flag. + _plat__ClearCancel(); + return; +} + +//*** _rpc__Signal_NvOn() +// In a system where the NV memory used by the TPM is not within the TPM, the +// NV may not always be available. This function turns on the indicator that +// indicates that NV is available. +void _rpc__Signal_NvOn(void) +{ + // If TPM power is on... + if(s_isPowerOn) + // ... make the NV available + _plat__SetNvAvail(); + return; +} + +//*** _rpc__Signal_NvOff() +// This function is used to set the indication that NV memory is no +// longer available. +void _rpc__Signal_NvOff(void) +{ + // If TPM power is on... + if(s_isPowerOn) + // ... make NV not available + _plat__ClearNvAvail(); + return; +} + +void RsaKeyCacheControl(int state); + +//*** _rpc__RsaKeyCacheControl() +// This function is used to enable/disable the use of the RSA key cache during +// simulation. +void _rpc__RsaKeyCacheControl(int state) +{ +#if USE_RSA_KEY_CACHE + RsaKeyCacheControl(state); +#else + NOT_REFERENCED(state); +#endif + return; +} + +#define TPM_RH_ACT_0 0x40000110 + +//*** _rpc__ACT_GetSignaled() +// This function is used to count the ACT second tick. +bool _rpc__ACT_GetSignaled(uint32_t actHandle) +{ + // If TPM power is on... + if(s_isPowerOn) + // ... query the platform + return _plat__ACT_GetSignaled(actHandle - TPM_RH_ACT_0); + return false; +} diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/src/TPMCmds.c b/optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/src/TPMCmds.c new file mode 100644 index 0000000..a2c6fb5 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/src/TPMCmds.c @@ -0,0 +1,293 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Description +// This file contains the entry point for the simulator. + +//** Includes, Defines, Data Definitions, and Function Prototypes +#include "TpmBuildSwitches.h" + +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +# pragma warning(push, 3) +# include +# include +# pragma warning(pop) +#elif defined(__unix__) || defined(__APPLE__) +# define _strcmpi strcasecmp +typedef int SOCKET; +#else +# error "Unsupported platform." +#endif + +#include "TpmTcpProtocol.h" +#include "Manufacture_fp.h" +#include "Platform_fp.h" +#include "Simulator_fp.h" + +#define PURPOSE \ + "TPM 2.0 Reference Simulator.\n" \ + "Copyright (c) Microsoft Corporation. All rights reserved." + +#define DEFAULT_TPM_PORT 2321 + +// Information about command line arguments (does not include program name) +static uint32_t s_ArgsMask = 0; // Bit mask of unmatched command line args +static int s_Argc = 0; +static const char** s_Argv = NULL; + +//** Functions + +#if DEBUG +//*** Assert() +// This function implements a run-time assertion. +// Computation of its parameters must not result in any side effects, as these +// computations will be stripped from the release builds. +static void Assert(bool cond, const char* msg) +{ + if(cond) + return; + fputs(msg, stderr); + exit(2); +} +#else +# define Assert(cond, msg) +#endif + +//*** Usage() +// This function prints the proper calling sequence for the simulator. +static void Usage(const char* programName) +{ + fprintf(stderr, "%s\n\n", PURPOSE); + fprintf(stderr, + "Usage: %s [PortNum] [opts]\n\n" + "Starts the TPM server listening on TCP port PortNum (by default %d).\n\n" + "An option can be in the short form (one letter preceded with '-' or " + "'/')\n" + "or in the full form (preceded with '--' or no option marker at all).\n" + "Possible options are:\n" + " -h (--help) or ? - print this message\n" + " -m (--manufacture) - forces NV state of the TPM simulator to be " + "(re)manufactured\n", + programName, + DEFAULT_TPM_PORT); + exit(1); +} + +//*** CmdLineParser_Init() +// This function initializes command line option parser. +static bool CmdLineParser_Init(int argc, char* argv[], int maxOpts) +{ + if(argc == 1) + return false; + + if(maxOpts && (argc - 1) > maxOpts) + { + fprintf(stderr, "No more than %d options can be specified\n\n", maxOpts); + Usage(argv[0]); + } + + s_Argc = argc - 1; + s_Argv = (const char**)(argv + 1); + s_ArgsMask = (1 << s_Argc) - 1; + return true; +} + +//*** CmdLineParser_More() +// Returns true if there are unparsed options still. +static bool CmdLineParser_More(void) +{ + return s_ArgsMask != 0; +} + +//*** CmdLineParser_IsOpt() +// This function determines if the given command line parameter represents a valid +// option. +static bool CmdLineParser_IsOpt( + const char* opt, // Command line parameter to check + const char* optFull, // Expected full name + const char* optShort, // Expected short (single letter) name + bool dashed // The parameter is preceded by a single dash +) +{ + return 0 == strcmp(opt, optFull) + || (optShort && opt[0] == optShort[0] && opt[1] == 0) + || (dashed && opt[0] == '-' && 0 == strcmp(opt + 1, optFull)); +} + +//*** CmdLineParser_IsOptPresent() +// This function determines if the given command line parameter represents a valid +// option. +static bool CmdLineParser_IsOptPresent(const char* optFull, const char* optShort) +{ + int i; + int curArgBit; + Assert(s_Argv != NULL, "InitCmdLineOptParser(argc, argv) has not been invoked\n"); + Assert(optFull && optFull[0], + "Full form of a command line option must be present.\n" + "If only a short (single letter) form is supported, it must be" + "specified as the full one.\n"); + Assert(!optShort || (optShort[0] && !optShort[1]), + "If a short form of an option is specified, it must consist " + "of a single letter only.\n"); + + if(!CmdLineParser_More()) + return false; + + for(i = 0, curArgBit = 1; i < s_Argc; ++i, curArgBit <<= 1) + { + const char* opt = s_Argv[i]; + if((s_ArgsMask & curArgBit) && opt + && (0 == strcmp(opt, optFull) + || ((opt[0] == '/' || opt[0] == '-') + && CmdLineParser_IsOpt( + opt + 1, optFull, optShort, opt[0] == '-')))) + { + s_ArgsMask ^= curArgBit; + return true; + } + } + return false; +} + +//*** CmdLineParser_Done() +// This function notifies the parser that no more options are needed. +static void CmdLineParser_Done(const char* programName) +{ + char delim = ':'; + int i; + int curArgBit; + + if(!CmdLineParser_More()) + return; + + fprintf(stderr, + "Command line contains unknown option%s", + s_ArgsMask & (s_ArgsMask - 1) ? "s" : ""); + for(i = 0, curArgBit = 1; i < s_Argc; ++i, curArgBit <<= 1) + { + if(s_ArgsMask & curArgBit) + { + fprintf(stderr, "%c %s", delim, s_Argv[i]); + delim = ','; + } + } + fprintf(stderr, "\n\n"); + Usage(programName); +} + +//*** main() +// This is the main entry point for the simulator. +// It registers the interface and starts listening for clients +int main(int argc, char* argv[]) +{ + bool manufacture = false; + int PortNum = DEFAULT_TPM_PORT; + + // Parse command line options + + if(CmdLineParser_Init(argc, argv, 2)) + { + if(CmdLineParser_IsOptPresent("?", "?") + || CmdLineParser_IsOptPresent("help", "h")) + { + Usage(argv[0]); + } + if(CmdLineParser_IsOptPresent("manufacture", "m")) + { + manufacture = true; + } + if(CmdLineParser_More()) + { + int i; + for(i = 0; i < s_Argc; ++i) + { + char* nptr = NULL; + int portNum = (int)strtol(s_Argv[i], &nptr, 0); + if(s_Argv[i] != nptr) + { + // A numeric option is found + if(!*nptr && portNum > 0 && portNum < 65535) + { + PortNum = portNum; + s_ArgsMask ^= 1 << i; + break; + } + fprintf(stderr, "Invalid numeric option %s\n\n", s_Argv[i]); + Usage(argv[0]); + } + } + } + CmdLineParser_Done(argv[0]); + } + printf("LIBRARY_COMPATIBILITY_CHECK is %s\n", + (LIBRARY_COMPATIBILITY_CHECK ? "ON" : "OFF")); + // Enable NV memory + _plat__NVEnable(NULL); + + if(manufacture || _plat__NVNeedsManufacture()) + { + printf("Manufacturing NV state...\n"); + if(TPM_Manufacture(1) != 0) + { + // if the manufacture didn't work, then make sure that the NV file doesn't + // survive. This prevents manufacturing failures from being ignored the + // next time the code is run. + _plat__NVDisable(1); + exit(1); + } + // Coverage test - repeated manufacturing attempt + if(TPM_Manufacture(0) != 1) + { + exit(2); + } + // Coverage test - re-manufacturing + TPM_TearDown(); + if(TPM_Manufacture(1) != 0) + { + exit(3); + } + } + // Disable NV memory + _plat__NVDisable(0); + + StartTcpServer(PortNum); + return EXIT_SUCCESS; +} diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/src/TcpServer.c b/optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/src/TcpServer.c new file mode 100644 index 0000000..ee3afbe --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/src/TcpServer.c @@ -0,0 +1,711 @@ + +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Description +// +// This file contains the socket interface to a TPM simulator. +// +//** Includes, Locals, Defines and Function Prototypes +#include "TpmBuildSwitches.h" +#include +#include + +#ifdef _MSC_VER +# pragma warning(push, 3) +# include +# include +# pragma warning(pop) +typedef int socklen_t; +#elif defined(__unix__) || defined(__APPLE__) +# include +# include +# include +# include +# include +# include +# include +# define ZeroMemory(ptr, sz) (memset((ptr), 0, (sz))) +# define closesocket(x) close(x) +# define INVALID_SOCKET (-1) +# define SOCKET_ERROR (-1) +# define WSAGetLastError() (errno) +# define INT_PTR intptr_t + +typedef int SOCKET; +#else +# error "Unsupported platform." +#endif + +#include "TpmTcpProtocol.h" +#include "Manufacture_fp.h" +#include "TpmProfile.h" + +#include "Simulator_fp.h" +#include "Platform_fp.h" + +// To access key cache control in TPM +void RsaKeyCacheControl(int state); + +#ifndef __IGNORE_STATE__ + +static uint32_t ServerVersion = 1; + +# define MAX_BUFFER 1048576 +char InputBuffer[MAX_BUFFER]; //The input data buffer for the simulator. +char OutputBuffer[MAX_BUFFER]; //The output data buffer for the simulator. + +struct +{ + uint32_t largestCommandSize; + uint32_t largestCommand; + uint32_t largestResponseSize; + uint32_t largestResponse; +} CommandResponseSizes = {0}; + +#endif // __IGNORE_STATE___ + +//** Functions + +//*** CreateSocket() +// This function creates a socket listening on 'PortNumber'. +static int CreateSocket(int PortNumber, SOCKET* listenSocket) +{ + struct sockaddr_in MyAddress; + int res; +// +// Initialize Winsock +#ifdef _MSC_VER + WSADATA wsaData; + res = WSAStartup(MAKEWORD(2, 2), &wsaData); + if(res != 0) + { + printf("WSAStartup failed with error: %d\n", res); + return -1; + } +#endif + // create listening socket + *listenSocket = socket(PF_INET, SOCK_STREAM, 0); + if(INVALID_SOCKET == *listenSocket) + { + printf("Cannot create server listen socket. Error is 0x%x\n", + WSAGetLastError()); + return -1; + } + // bind the listening socket to the specified port + ZeroMemory(&MyAddress, sizeof(MyAddress)); + MyAddress.sin_port = htons((short)PortNumber); + MyAddress.sin_family = AF_INET; + + res = bind(*listenSocket, (struct sockaddr*)&MyAddress, sizeof(MyAddress)); + if(res == SOCKET_ERROR) + { + printf("Bind error. Error is 0x%x\n", WSAGetLastError()); + return -1; + } + // listen/wait for server connections + res = listen(*listenSocket, 3); + if(res == SOCKET_ERROR) + { + printf("Listen error. Error is 0x%x\n", WSAGetLastError()); + return -1; + } + return 0; +} + +//*** PlatformServer() +// This function processes incoming platform requests. +bool PlatformServer(SOCKET s) +{ + bool OK = true; + uint32_t Command; + // + for(;;) + { + OK = ReadBytes(s, (char*)&Command, 4); + // client disconnected (or other error). We stop processing this client + // and return to our caller who can stop the server or listen for another + // connection. + if(!OK) + return true; + Command = ntohl(Command); + switch(Command) + { + case TPM_SIGNAL_POWER_ON: + _rpc__Signal_PowerOn(false); + break; + case TPM_SIGNAL_POWER_OFF: + _rpc__Signal_PowerOff(); + break; + case TPM_SIGNAL_RESET: + _rpc__Signal_PowerOn(true); + break; + case TPM_SIGNAL_RESTART: + _rpc__Signal_Restart(); + break; + case TPM_SIGNAL_PHYS_PRES_ON: + _rpc__Signal_PhysicalPresenceOn(); + break; + case TPM_SIGNAL_PHYS_PRES_OFF: + _rpc__Signal_PhysicalPresenceOff(); + break; + case TPM_SIGNAL_CANCEL_ON: + _rpc__Signal_CancelOn(); + break; + case TPM_SIGNAL_CANCEL_OFF: + _rpc__Signal_CancelOff(); + break; + case TPM_SIGNAL_NV_ON: + _rpc__Signal_NvOn(); + break; + case TPM_SIGNAL_NV_OFF: + _rpc__Signal_NvOff(); + break; + case TPM_SIGNAL_KEY_CACHE_ON: + _rpc__RsaKeyCacheControl(true); + break; + case TPM_SIGNAL_KEY_CACHE_OFF: + _rpc__RsaKeyCacheControl(false); + break; + case TPM_SESSION_END: + // Client signaled end-of-session + TpmEndSimulation(); + return true; + case TPM_STOP: + // Client requested the simulator to exit + return false; + case TPM_TEST_FAILURE_MODE: + _rpc__ForceFailureMode(); + break; + case TPM_GET_COMMAND_RESPONSE_SIZES: + OK = WriteVarBytes( + s, (char*)&CommandResponseSizes, sizeof(CommandResponseSizes)); + memset(&CommandResponseSizes, 0, sizeof(CommandResponseSizes)); + if(!OK) + return true; + break; + case TPM_ACT_GET_SIGNALED: + { + uint32_t actHandle; + OK = ReadUINT32(s, &actHandle); + WriteUINT32(s, _rpc__ACT_GetSignaled(actHandle)); + break; + } + default: + printf("Unrecognized platform interface command %d\n", (int)Command); + WriteUINT32(s, 1); + return true; + } + WriteUINT32(s, 0); + } +} + +//*** PlatformSvcRoutine() +// This function is called to set up the socket interfaces to listen for +// commands. +DWORD WINAPI PlatformSvcRoutine(LPVOID port) +{ + int PortNumber = (int)(INT_PTR)port; + SOCKET listenSocket, serverSocket; + struct sockaddr_in HerAddress; + int res; + socklen_t length; + bool continueServing; + // + res = CreateSocket(PortNumber, &listenSocket); + if(res != 0) + { + printf("Create platform service socket fail\n"); + return res; + } + // Loop accepting connections one-by-one until we are killed or asked to stop + // Note the platform service is single-threaded so we don't listen for a new + // connection until the prior connection drops. + do + { + printf("Platform server listening on port %d\n", PortNumber); + + // blocking accept + length = sizeof(HerAddress); + serverSocket = accept(listenSocket, (struct sockaddr*)&HerAddress, &length); + if(serverSocket == INVALID_SOCKET) + { + printf("Accept error. Error is 0x%x\n", WSAGetLastError()); + return (DWORD)-1; + } + printf("Client accepted\n"); + + // normal behavior on client disconnection is to wait for a new client + // to connect + continueServing = PlatformServer(serverSocket); + closesocket(serverSocket); + } while(continueServing); + + return 0; +} + +//*** PlatformSignalService() +// This function starts a new thread waiting for platform signals. +// Platform signals are processed one at a time in the order in which they are +// received. +int PlatformSignalService(int PortNumber) +{ +#if defined(_MSC_VER) + HANDLE hPlatformSvc; + int ThreadId; + int port = PortNumber; + // + // Create service thread for platform signals + hPlatformSvc = CreateThread(NULL, + 0, + (LPTHREAD_START_ROUTINE)PlatformSvcRoutine, + (LPVOID)(INT_PTR)port, + 0, + (LPDWORD)&ThreadId); + if(hPlatformSvc == NULL) + { + printf("Thread Creation failed\n"); + return -1; + } + return 0; +#else + pthread_t thread_id; + int ret; + int port = PortNumber; + + ret = pthread_create( + &thread_id, NULL, (void*)PlatformSvcRoutine, (LPVOID)(INT_PTR)port); + if(ret == -1) + { + printf("pthread_create failed: %s", strerror(ret)); + } + return ret; +#endif // _MSC_VER +} + +//*** RegularCommandService() +// This function services regular commands. +int RegularCommandService(int PortNumber) +{ + SOCKET listenSocket; + SOCKET serverSocket; + struct sockaddr_in HerAddress; + int res; + socklen_t length; + bool continueServing; + // + res = CreateSocket(PortNumber, &listenSocket); + if(res != 0) + { + printf("Create platform service socket fail\n"); + return res; + } + // Loop accepting connections one-by-one until we are killed or asked to stop + // Note the TPM command service is single-threaded so we don't listen for + // a new connection until the prior connection drops. + do + { + printf("TPM command server listening on port %d\n", PortNumber); + + // blocking accept + length = sizeof(HerAddress); + serverSocket = accept(listenSocket, (struct sockaddr*)&HerAddress, &length); + if(serverSocket == INVALID_SOCKET) + { + printf("Accept error. Error is 0x%x\n", WSAGetLastError()); + return -1; + } + printf("Client accepted\n"); + + // normal behavior on client disconnection is to wait for a new client + // to connect + continueServing = TpmServer(serverSocket); + closesocket(serverSocket); + } while(continueServing); + return 0; +} + +#if RH_ACT_0 + +//*** SimulatorTimeServiceRoutine() +// This function is called to service the time 'ticks'. +static unsigned long WINAPI SimulatorTimeServiceRoutine(LPVOID notUsed) +{ + // All time is in ms + const int64_t tick = 1000; + uint64_t prevTime = _plat__RealTime(); + int64_t timeout = tick; + + (void)notUsed; + + while(true) + { + uint64_t curTime; + +# if defined(_MSC_VER) + Sleep((DWORD)timeout); +# else + struct timespec req = {timeout / 1000, (timeout % 1000) * 1000}; + struct timespec rem; + nanosleep(&req, &rem); +# endif // _MSC_VER + curTime = _plat__RealTime(); + + // May need to issue several ticks if the Sleep() took longer than asked, + // or no ticks at all, it Sleep() was interrupted prematurely. + while(prevTime < curTime - tick / 2) + { + //printf("%05lld | %05lld\n", + // prevTime % 100000, (curTime - tick / 2) % 100000); + _plat__ACT_Tick(); + prevTime += (uint64_t)tick; + } + // Adjust the next timeout to keep the average interval of one second + timeout = tick + (prevTime - curTime); + //prevTime = curTime; + //printf("%04lld | c:%05lld | p:%05llu\n", + // timeout, curTime % 100000, prevTime); + } + return 0; +} + +//*** ActTimeService() +// This function starts a new thread waiting to wait for time ticks. +// Return Type: int +// ==0 success +// !=0 failure +static int ActTimeService(void) +{ + static bool running = false; + int ret = 0; + if(!running) + { +# if defined(_MSC_VER) + HANDLE hThr; + int ThreadId; + // + printf("Starting ACT thread...\n"); + // Don't allow ticks to be processed before TPM is manufactured. + _plat__ACT_EnableTicks(false); + + // Create service thread for ACT internal timer + hThr = CreateThread(NULL, + 0, + (LPTHREAD_START_ROUTINE)SimulatorTimeServiceRoutine, + (LPVOID)(INT_PTR)NULL, + 0, + (LPDWORD)&ThreadId); + if(hThr != NULL) + CloseHandle(hThr); + else + ret = -1; +# else + pthread_t thread_id; + // + ret = pthread_create(&thread_id, + NULL, + (void*)SimulatorTimeServiceRoutine, + (LPVOID)(INT_PTR)NULL); +# endif // _MSC_VER + + if(ret != 0) + printf("ACT thread Creation failed\n"); + else + running = true; + } + return ret; +} + +#endif // RH_ACT_0 + +//*** StartTcpServer() +// This is the main entry-point to the TCP server. The server listens on port +// specified. +// +// Note that there is no way to specify the network interface in this implementation. +int StartTcpServer(int PortNumber) +{ + int res; +// +#ifdef RH_ACT_0 + // Start the Time Service routine + res = ActTimeService(); + if(res != 0) + { + printf("TimeService failed\n"); + return res; + } +#endif + + // Start Platform Signal Processing Service + res = PlatformSignalService(PortNumber + 1); + if(res != 0) + { + printf("PlatformSignalService failed\n"); + return res; + } + // Start Regular/DRTM TPM command service + res = RegularCommandService(PortNumber); + if(res != 0) + { + printf("RegularCommandService failed\n"); + return res; + } + return 0; +} + +//*** ReadBytes() +// This function reads the indicated number of bytes ('NumBytes') into buffer +// from the indicated socket. +bool ReadBytes(SOCKET s, char* buffer, int NumBytes) +{ + int res; + int numGot = 0; + // + while(numGot < NumBytes) + { + res = recv(s, buffer + numGot, NumBytes - numGot, 0); + if(res == -1) + { + printf("Receive error. Error is 0x%x\n", WSAGetLastError()); + return false; + } + if(res == 0) + { + return false; + } + numGot += res; + } + return true; +} + +//*** WriteBytes() +// This function will send the indicated number of bytes ('NumBytes') to the +// indicated socket +bool WriteBytes(SOCKET s, char* buffer, int NumBytes) +{ + int res; + int numSent = 0; + // + while(numSent < NumBytes) + { + res = send(s, buffer + numSent, NumBytes - numSent, 0); + if(res == -1) + { + if(WSAGetLastError() == 0x2745) + { + printf("Client disconnected\n"); + } + else + { + printf("Send error. Error is 0x%x\n", WSAGetLastError()); + } + return false; + } + numSent += res; + } + return true; +} + +//*** WriteUINT32() +// Send 4 byte integer +bool WriteUINT32(SOCKET s, uint32_t val) +{ + uint32_t netVal = htonl(val); + // + return WriteBytes(s, (char*)&netVal, 4); +} + +//*** ReadUINT32() +// Function to read 4 byte integer from socket. +bool ReadUINT32(SOCKET s, uint32_t* val) +{ + uint32_t netVal; + // + if(!ReadBytes(s, (char*)&netVal, 4)) + return false; + *val = ntohl(netVal); + return true; +} + +//*** ReadVarBytes() +// Get a uint32-length-prepended binary array. Note that the 4-byte length is +// in network byte order (big-endian). +bool ReadVarBytes(SOCKET s, char* buffer, uint32_t* BytesReceived, int MaxLen) +{ + int length; + bool res; + // + res = ReadBytes(s, (char*)&length, 4); + if(!res) + return res; + length = ntohl(length); + *BytesReceived = length; + if(length > MaxLen) + { + printf("Buffer too big. Client says %d\n", length); + return false; + } + if(length == 0) + return true; + res = ReadBytes(s, buffer, length); + if(!res) + return res; + return true; +} + +//*** WriteVarBytes() +// Send a uint32-length-prepended binary array. Note that the 4-byte length is +// in network byte order (big-endian). +bool WriteVarBytes(SOCKET s, char* buffer, int BytesToSend) +{ + uint32_t netLength = htonl(BytesToSend); + bool res; + // + res = WriteBytes(s, (char*)&netLength, 4); + if(!res) + return res; + res = WriteBytes(s, buffer, BytesToSend); + if(!res) + return res; + return true; +} + +//*** TpmServer() +// Processing incoming TPM command requests using the protocol / interface +// defined above. +bool TpmServer(SOCKET s) +{ + uint32_t length; + uint32_t Command; + uint8_t locality; + bool OK; + int result; + int clientVersion; + _IN_BUFFER InBuffer; + _OUT_BUFFER OutBuffer; + // + for(;;) + { + OK = ReadBytes(s, (char*)&Command, 4); + // client disconnected (or other error). We stop processing this client + // and return to our caller who can stop the server or listen for another + // connection. + if(!OK) + return true; + Command = ntohl(Command); + switch(Command) + { + case TPM_SIGNAL_HASH_START: + _rpc__Signal_Hash_Start(); + break; + case TPM_SIGNAL_HASH_END: + _rpc__Signal_HashEnd(); + break; + case TPM_SIGNAL_HASH_DATA: + OK = ReadVarBytes(s, InputBuffer, &length, MAX_BUFFER); + if(!OK) + return true; + InBuffer.Buffer = (uint8_t*)InputBuffer; + InBuffer.BufferSize = length; + _rpc__Signal_Hash_Data(InBuffer); + break; + case TPM_SEND_COMMAND: + OK = ReadBytes(s, (char*)&locality, 1); + if(!OK) + return true; + OK = ReadVarBytes(s, InputBuffer, &length, MAX_BUFFER); + if(!OK) + return true; + InBuffer.Buffer = (uint8_t*)InputBuffer; + InBuffer.BufferSize = length; + OutBuffer.BufferSize = MAX_BUFFER; + OutBuffer.Buffer = (_OUTPUT_BUFFER)OutputBuffer; + // record the number of bytes in the command if it is the largest + // we have seen so far. + if(InBuffer.BufferSize > CommandResponseSizes.largestCommandSize) + { + CommandResponseSizes.largestCommandSize = InBuffer.BufferSize; + memcpy(&CommandResponseSizes.largestCommand, + &InputBuffer[6], + sizeof(uint32_t)); + } + _rpc__Send_Command(locality, InBuffer, &OutBuffer); + // record the number of bytes in the response if it is the largest + // we have seen so far. + if(OutBuffer.BufferSize > CommandResponseSizes.largestResponseSize) + { + CommandResponseSizes.largestResponseSize = OutBuffer.BufferSize; + memcpy(&CommandResponseSizes.largestResponse, + &OutputBuffer[6], + sizeof(uint32_t)); + } + OK = WriteVarBytes(s, (char*)OutBuffer.Buffer, OutBuffer.BufferSize); + if(!OK) + return true; + break; + case TPM_REMOTE_HANDSHAKE: + OK = ReadBytes(s, (char*)&clientVersion, 4); + if(!OK) + return true; + if(clientVersion == 0) + { + printf("Unsupported client version (0).\n"); + return true; + } + OK &= WriteUINT32(s, ServerVersion); + OK &= WriteUINT32( + s, tpmInRawMode | tpmPlatformAvailable | tpmSupportsPP); + break; + case TPM_SET_ALTERNATIVE_RESULT: + OK = ReadBytes(s, (char*)&result, 4); + if(!OK) + return true; + // Alternative result is not applicable to the simulator. + break; + case TPM_SESSION_END: + // Client signaled end-of-session + return true; + case TPM_STOP: + // Client requested the simulator to exit + return false; + default: + printf("Unrecognized TPM interface command %d\n", (int)Command); + return true; + } + OK = WriteUINT32(s, 0); + if(!OK) + return true; + } +} diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/src/tpmsim.service b/optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/src/tpmsim.service new file mode 100644 index 0000000..f5f60b0 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/Simulator/src/tpmsim.service @@ -0,0 +1,18 @@ +[Unit] +Description=TPM 2.0 Simulator +#ConditionPathExists=!/dev/tpm0 +After=network.target + +[Service] +Type=simple +WorkingDirectory=/etc/tpmsim +ExecStart=/src/ms-tpm-20-ref/TPMCmd/Simulator/src/tpm2-simulator +ExecStartPost=/bin/sleep 1s +ExecStartPost=/bin/tpm2_startup -T mssim:host=localhost,port=2321 -c +KillMode=SIGKILL +ExecStop=/bin/tpm2_shutdown -T mssim:host=localhost,port=2321 -c +ExecStop=/bin/kill $MAINPID + +[Install] +WantedBy=multi-user.target + diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/bootstrap b/optee/samples/ms-tpm-20-ref/TPMCmd/bootstrap new file mode 100755 index 0000000..293581c --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/bootstrap @@ -0,0 +1,66 @@ +#!/usr/bin/env sh +# The copyright in this software is being made available under the BSD License, +# included below. This software may be subject to other third party and +# contributor rights, including patent rights, and no such rights are granted +# under this license. +# +# Copyright (c) Intel Corporation +# +# All rights reserved. +# +# BSD License +# +# 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. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +AUTORECONF=${AUTORECONF:-autoreconf} + +# generate list of source files for use in Makefile.am +# if you add new source files, you must run ./bootstrap again +src_listvar () { + basedir=$1 + suffix=$2 + var=$3 + + find "${basedir}" -name "${suffix}" | LC_ALL=C sort | tr '\n' ' ' | (printf "${var} = " && cat) + echo "" +} + +echo "Generating file lists: src.mk" +( + src_listvar "Platform" "*.c" "PLATFORM_C" + src_listvar "Platform" "*.h" "PLATFORM_H" + src_listvar "Simulator" "*.c" "SIMULATOR_C" + src_listvar "Simulator" "*.h" "SIMULATOR_H" + src_listvar "tpm" "*.c" "TPM_C" + src_listvar "tpm" "*.h" "TPM_H" +) > src.mk + +echo "Setting up build" +${AUTORECONF} --install --sym + +# A freshly checked out source tree will not build. VendorString.h must have +# these symbols defined to build. +echo "Setting default vendor strings" +sed -i.bak 's&^\/\/\(#define[[:space:]]\+FIRMWARE_V1.*\)&\1&; + s&^\/\/\(#define[[:space:]]\+MANUFACTURER.*\)&\1&; + s&^\/\/\(#define[[:space:]]\+VENDOR_STRING_1.*\)&\1&' \ + tpm/include/VendorString.h && rm tpm/include/VendorString.h.bak diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/configure.ac b/optee/samples/ms-tpm-20-ref/TPMCmd/configure.ac new file mode 100644 index 0000000..58a74b4 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/configure.ac @@ -0,0 +1,89 @@ +dnl The copyright in this software is being made available under the BSD License, +dnl included below. This software may be subject to other third party and +dnl contributor rights, including patent rights, and no such rights are granted +dnl under this license. +dnl +dnl Copyright (c) Intel Corporation +dnl +dnl All rights reserved. +dnl +dnl BSD License +dnl +dnl Redistribution and use in source and binary forms, with or without modification, +dnl are permitted provided that the following conditions are met: +dnl +dnl Redistributions of source code must retain the above copyright notice, this list +dnl of conditions and the following disclaimer. +dnl +dnl Redistributions in binary form must reproduce the above copyright notice, this +dnl list of conditions and the following disclaimer in the documentation and/or +dnl other materials provided with the distribution. +dnl +dnl THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" +dnl AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +dnl IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +dnl DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +dnl ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +dnl (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +dnl LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +dnl ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +dnl (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +dnl SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +AC_INIT([ms-tpm-20-ref], + [0.1], + [https://github.com/microsoft/ms-tpm-20-ref/issues], + [], + [https://github.com/microsoft/ms-tpm-20-ref]) +AC_CONFIG_MACRO_DIR([.]) +AC_PROG_CC +AC_PROG_LN_S +AC_PROG_RANLIB +AM_INIT_AUTOMAKE([foreign subdir-objects]) +AC_CONFIG_FILES([Makefile]) +AC_SUBST([DISTCHECK_CONFIGURE_FLAGS],[$ac_configure_args]) + +dnl By enabling this feature tpm simulator gets seeds derived from hardware parameters. +dnl It is enabled only for linux devices. +dnl Note that the seeds are not derived from secure hardware source. + +AC_ARG_ENABLE(usedeviceid, + AS_HELP_STRING([--enable-usedeviceid], + [tpm simulator get seeds derived from hardware parameters. Seeds are not derived from secure hardware source.])) + +PKG_CHECK_MODULES([LIBCRYPTO], [libcrypto]) +AS_IF([test "x$enable_usedeviceid" = "xyes"], [ + PKG_CHECK_MODULES([LIBUDEV], [libudev]) + [ADDITIONAL_LIBS="-ludev"] +]) +AX_PTHREAD([], [AC_MSG_ERROR([requires pthread])]) + +AC_DEFINE([HASH_LIB], [Ossl], [Crypto lib for hash algorithms]) +AC_DEFINE([SYM_LIB], [Ossl], [Crypto lib for symmetric encryption algorithms]) +AC_DEFINE([MATH_LIB], [Ossl], [Crypto lib for bignum operations]) + +ADD_COMPILER_FLAG([-std=gnu11]) +ADD_COMPILER_FLAG([-Werror]) +ADD_COMPILER_FLAG([-Wall]) +ADD_COMPILER_FLAG([-Wformat-security]) +ADD_COMPILER_FLAG([-fstack-protector-all]) +ADD_COMPILER_FLAG([-fPIC]) +ADD_COMPILER_FLAG([-Wno-error=empty-body]) +ADD_COMPILER_FLAG([-Wno-error=expansion-to-defined]) +ADD_COMPILER_FLAG([-Wno-error=parentheses]) +ADD_COMPILER_FLAG([-Wno-error=pointer-to-int-cast]) +ADD_COMPILER_FLAG([-Wno-error=missing-braces]) +ADD_COMPILER_FLAG([-Wno-error=unused-result]) + +AS_IF([test "x$enable_usedeviceid" = "xyes"], [ + ADD_COMPILER_FLAG([-DNDEBUG]) + ADD_COMPILER_FLAG([-g]) + ADD_COMPILER_FLAG([-DUSE_PLATFORM_EPS]) + AC_SUBST(ADDITIONAL_LIBS) +]) +ADD_LINK_FLAG([-Wl,--no-undefined]) +ADD_LINK_FLAG([-Wl,-z,noexecstack]) +ADD_LINK_FLAG([-Wl,-z,now]) +ADD_LINK_FLAG([-Wl,-z,relro]) + +AC_OUTPUT diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/flags.m4 b/optee/samples/ms-tpm-20-ref/TPMCmd/flags.m4 new file mode 100644 index 0000000..286c10b --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/flags.m4 @@ -0,0 +1,84 @@ +dnl The copyright in this software is being made available under the BSD License, +dnl included below. This software may be subject to other third party and +dnl contributor rights, including patent rights, and no such rights are granted +dnl under this license. +dnl +dnl Copyright (c) Intel Corporation +dnl +dnl All rights reserved. +dnl +dnl BSD License +dnl +dnl Redistribution and use in source and binary forms, with or without modification, +dnl are permitted provided that the following conditions are met: +dnl +dnl Redistributions of source code must retain the above copyright notice, this list +dnl of conditions and the following disclaimer. +dnl +dnl Redistributions in binary form must reproduce the above copyright notice, this +dnl list of conditions and the following disclaimer in the documentation and/or +dnl other materials provided with the distribution. +dnl +dnl THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" +dnl AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +dnl IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +dnl DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +dnl ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +dnl (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +dnl LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +dnl ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +dnl (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +dnl SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +dnl ADD_COMPILER_FLAG: +dnl A macro to add a CFLAG to the EXTRA_CFLAGS variable. This macro will +dnl check to be sure the compiler supprts the flag. Flags can be made +dnl mandatory (configure will fail). +dnl $1: C compiler flag to add to EXTRA_CFLAGS. +dnl $2: Set to "required" to cause configure failure if flag not supported.. +AC_DEFUN([ADD_COMPILER_FLAG],[ + AX_CHECK_COMPILE_FLAG([$1],[ + EXTRA_CFLAGS="$EXTRA_CFLAGS $1" + AC_SUBST([EXTRA_CFLAGS])],[ + AS_IF([test x$2 != xrequired],[ + AC_MSG_WARN([Optional CFLAG "$1" not supported by your compiler, continuing.])],[ + AC_MSG_ERROR([Required CFLAG "$1" not supported by your compiler, aborting.])] + )],[ + -Wall -Werror] + )] +) +dnl ADD_PREPROC_FLAG: +dnl Add the provided preprocessor flag to the EXTRA_CFLAGS variable. This +dnl macro will check to be sure the preprocessor supports the flag. +dnl The flag can be made mandatory by provideing the string 'required' as +dnl the second parameter. +dnl $1: Preprocessor flag to add to EXTRA_CFLAGS. +dnl $2: Set to "required" t ocause configure failure if preprocesor flag +dnl is not supported. +AC_DEFUN([ADD_PREPROC_FLAG],[ + AX_CHECK_PREPROC_FLAG([$1],[ + EXTRA_CFLAGS="$EXTRA_CFLAGS $1" + AC_SUBST([EXTRA_CFLAGS])],[ + AS_IF([test x$2 != xrequired],[ + AC_MSG_WARN([Optional preprocessor flag "$1" not supported by your compiler, continuing.])],[ + AC_MSG_ERROR([Required preprocessor flag "$1" not supported by your compiler, aborting.])] + )],[ + -Wall -Werror] + )] +) +dnl ADD_LINK_FLAG: +dnl A macro to add a LDLAG to the EXTRA_LDFLAGS variable. This macro will +dnl check to be sure the linker supprts the flag. Flags can be made +dnl mandatory (configure will fail). +dnl $1: linker flag to add to EXTRA_LDFLAGS. +dnl $2: Set to "required" to cause configure failure if flag not supported. +AC_DEFUN([ADD_LINK_FLAG],[ + AX_CHECK_LINK_FLAG([$1],[ + EXTRA_LDFLAGS="$EXTRA_LDFLAGS $1" + AC_SUBST([EXTRA_LDFLAGS])],[ + AS_IF([test x$2 != xrequired],[ + AC_MSG_WARN([Optional LDFLAG "$1" not supported by your linker, continuing.])],[ + AC_MSG_ERROR([Required LDFLAG "$1" not supported by your linker, aborting.])] + )] + )] +) diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/simulator.sln b/optee/samples/ms-tpm-20-ref/TPMCmd/simulator.sln new file mode 100644 index 0000000..59a398a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/simulator.sln @@ -0,0 +1,109 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.1062 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Simulator", "simulator\simulator.vcxproj", "{AAB9FA21-8671-4792-B000-B40A526058AD}" + ProjectSection(ProjectDependencies) = postProject + {A9249F05-0DF5-4D06-9873-FBBE61B6768B} = {A9249F05-0DF5-4D06-9873-FBBE61B6768B} + {B7456491-A2ED-4B1C-B59E-41C7B32B7E3B} = {B7456491-A2ED-4B1C-B59E-41C7B32B7E3B} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Platform", "Platform\platform.vcxproj", "{A9249F05-0DF5-4D06-9873-FBBE61B6768B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tpm", "tpm\TPM.vcxproj", "{B7456491-A2ED-4B1C-B59E-41C7B32B7E3B}" + ProjectSection(ProjectDependencies) = postProject + {A9249F05-0DF5-4D06-9873-FBBE61B6768B} = {A9249F05-0DF5-4D06-9873-FBBE61B6768B} + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Crypt", "Crypt", "{26AD7978-27E2-46E7-9F8C-36CDB1B5AB01}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{3587DA28-BEC1-44AE-8F4F-D24ECB719905}" + ProjectSection(SolutionItems) = preProject + ..\README.md = ..\README.md + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + Static|Win32 = Static|Win32 + Static|x64 = Static|x64 + WolfDebug|Win32 = WolfDebug|Win32 + WolfDebug|x64 = WolfDebug|x64 + WolfRelease|Win32 = WolfRelease|Win32 + WolfRelease|x64 = WolfRelease|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {AAB9FA21-8671-4792-B000-B40A526058AD}.Debug|Win32.ActiveCfg = Debug|Win32 + {AAB9FA21-8671-4792-B000-B40A526058AD}.Debug|Win32.Build.0 = Debug|Win32 + {AAB9FA21-8671-4792-B000-B40A526058AD}.Debug|x64.ActiveCfg = Debug|x64 + {AAB9FA21-8671-4792-B000-B40A526058AD}.Debug|x64.Build.0 = Debug|x64 + {AAB9FA21-8671-4792-B000-B40A526058AD}.Release|Win32.ActiveCfg = Release|Win32 + {AAB9FA21-8671-4792-B000-B40A526058AD}.Release|Win32.Build.0 = Release|Win32 + {AAB9FA21-8671-4792-B000-B40A526058AD}.Release|x64.ActiveCfg = Release|x64 + {AAB9FA21-8671-4792-B000-B40A526058AD}.Release|x64.Build.0 = Release|x64 + {AAB9FA21-8671-4792-B000-B40A526058AD}.Static|Win32.ActiveCfg = Static|Win32 + {AAB9FA21-8671-4792-B000-B40A526058AD}.Static|Win32.Build.0 = Static|Win32 + {AAB9FA21-8671-4792-B000-B40A526058AD}.Static|x64.ActiveCfg = Static|x64 + {AAB9FA21-8671-4792-B000-B40A526058AD}.Static|x64.Build.0 = Static|x64 + {AAB9FA21-8671-4792-B000-B40A526058AD}.WolfDebug|Win32.ActiveCfg = WolfDebug|Win32 + {AAB9FA21-8671-4792-B000-B40A526058AD}.WolfDebug|Win32.Build.0 = WolfDebug|Win32 + {AAB9FA21-8671-4792-B000-B40A526058AD}.WolfDebug|x64.ActiveCfg = WolfDebug|x64 + {AAB9FA21-8671-4792-B000-B40A526058AD}.WolfDebug|x64.Build.0 = WolfDebug|x64 + {AAB9FA21-8671-4792-B000-B40A526058AD}.WolfRelease|Win32.ActiveCfg = WolfRelease|Win32 + {AAB9FA21-8671-4792-B000-B40A526058AD}.WolfRelease|Win32.Build.0 = WolfRelease|Win32 + {AAB9FA21-8671-4792-B000-B40A526058AD}.WolfRelease|x64.ActiveCfg = WolfRelease|x64 + {AAB9FA21-8671-4792-B000-B40A526058AD}.WolfRelease|x64.Build.0 = WolfRelease|x64 + {A9249F05-0DF5-4D06-9873-FBBE61B6768B}.Debug|Win32.ActiveCfg = Debug|Win32 + {A9249F05-0DF5-4D06-9873-FBBE61B6768B}.Debug|Win32.Build.0 = Debug|Win32 + {A9249F05-0DF5-4D06-9873-FBBE61B6768B}.Debug|x64.ActiveCfg = Debug|x64 + {A9249F05-0DF5-4D06-9873-FBBE61B6768B}.Debug|x64.Build.0 = Debug|x64 + {A9249F05-0DF5-4D06-9873-FBBE61B6768B}.Release|Win32.ActiveCfg = Release|Win32 + {A9249F05-0DF5-4D06-9873-FBBE61B6768B}.Release|Win32.Build.0 = Release|Win32 + {A9249F05-0DF5-4D06-9873-FBBE61B6768B}.Release|x64.ActiveCfg = Release|x64 + {A9249F05-0DF5-4D06-9873-FBBE61B6768B}.Release|x64.Build.0 = Release|x64 + {A9249F05-0DF5-4D06-9873-FBBE61B6768B}.Static|Win32.ActiveCfg = Static|Win32 + {A9249F05-0DF5-4D06-9873-FBBE61B6768B}.Static|Win32.Build.0 = Static|Win32 + {A9249F05-0DF5-4D06-9873-FBBE61B6768B}.Static|x64.ActiveCfg = Static|x64 + {A9249F05-0DF5-4D06-9873-FBBE61B6768B}.Static|x64.Build.0 = Static|x64 + {A9249F05-0DF5-4D06-9873-FBBE61B6768B}.WolfDebug|Win32.ActiveCfg = WolfDebug|Win32 + {A9249F05-0DF5-4D06-9873-FBBE61B6768B}.WolfDebug|Win32.Build.0 = WolfDebug|Win32 + {A9249F05-0DF5-4D06-9873-FBBE61B6768B}.WolfDebug|x64.ActiveCfg = WolfDebug|x64 + {A9249F05-0DF5-4D06-9873-FBBE61B6768B}.WolfDebug|x64.Build.0 = WolfDebug|x64 + {A9249F05-0DF5-4D06-9873-FBBE61B6768B}.WolfDebug|x64.Deploy.0 = WolfDebug|x64 + {A9249F05-0DF5-4D06-9873-FBBE61B6768B}.WolfRelease|Win32.ActiveCfg = WolfRelease|Win32 + {A9249F05-0DF5-4D06-9873-FBBE61B6768B}.WolfRelease|Win32.Build.0 = WolfRelease|Win32 + {A9249F05-0DF5-4D06-9873-FBBE61B6768B}.WolfRelease|x64.ActiveCfg = WolfRelease|x64 + {A9249F05-0DF5-4D06-9873-FBBE61B6768B}.WolfRelease|x64.Build.0 = WolfRelease|x64 + {A9249F05-0DF5-4D06-9873-FBBE61B6768B}.WolfRelease|x64.Deploy.0 = WolfRelease|x64 + {B7456491-A2ED-4B1C-B59E-41C7B32B7E3B}.Debug|Win32.ActiveCfg = Debug|Win32 + {B7456491-A2ED-4B1C-B59E-41C7B32B7E3B}.Debug|Win32.Build.0 = Debug|Win32 + {B7456491-A2ED-4B1C-B59E-41C7B32B7E3B}.Debug|x64.ActiveCfg = Debug|x64 + {B7456491-A2ED-4B1C-B59E-41C7B32B7E3B}.Debug|x64.Build.0 = Debug|x64 + {B7456491-A2ED-4B1C-B59E-41C7B32B7E3B}.Release|Win32.ActiveCfg = Release|Win32 + {B7456491-A2ED-4B1C-B59E-41C7B32B7E3B}.Release|Win32.Build.0 = Release|Win32 + {B7456491-A2ED-4B1C-B59E-41C7B32B7E3B}.Release|x64.ActiveCfg = Release|x64 + {B7456491-A2ED-4B1C-B59E-41C7B32B7E3B}.Release|x64.Build.0 = Release|x64 + {B7456491-A2ED-4B1C-B59E-41C7B32B7E3B}.Static|Win32.ActiveCfg = Static|Win32 + {B7456491-A2ED-4B1C-B59E-41C7B32B7E3B}.Static|Win32.Build.0 = Static|Win32 + {B7456491-A2ED-4B1C-B59E-41C7B32B7E3B}.Static|x64.ActiveCfg = Static|x64 + {B7456491-A2ED-4B1C-B59E-41C7B32B7E3B}.Static|x64.Build.0 = Static|x64 + {B7456491-A2ED-4B1C-B59E-41C7B32B7E3B}.WolfDebug|Win32.ActiveCfg = WolfDebug|Win32 + {B7456491-A2ED-4B1C-B59E-41C7B32B7E3B}.WolfDebug|Win32.Build.0 = WolfDebug|Win32 + {B7456491-A2ED-4B1C-B59E-41C7B32B7E3B}.WolfDebug|x64.ActiveCfg = WolfDebug|x64 + {B7456491-A2ED-4B1C-B59E-41C7B32B7E3B}.WolfDebug|x64.Build.0 = WolfDebug|x64 + {B7456491-A2ED-4B1C-B59E-41C7B32B7E3B}.WolfRelease|Win32.ActiveCfg = WolfRelease|Win32 + {B7456491-A2ED-4B1C-B59E-41C7B32B7E3B}.WolfRelease|Win32.Build.0 = WolfRelease|Win32 + {B7456491-A2ED-4B1C-B59E-41C7B32B7E3B}.WolfRelease|x64.ActiveCfg = WolfRelease|x64 + {B7456491-A2ED-4B1C-B59E-41C7B32B7E3B}.WolfRelease|x64.Build.0 = WolfRelease|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {C15EF5ED-F2C1-4785-A9C2-A2D213A367F7} + EndGlobalSection +EndGlobal diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/Tpm.vcxproj b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/Tpm.vcxproj new file mode 100644 index 0000000..7c4af04 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/Tpm.vcxproj @@ -0,0 +1,1061 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + Static + Win32 + + + Static + x64 + + + WolfDebug + Win32 + + + WolfDebug + x64 + + + WolfRelease + Win32 + + + WolfRelease + x64 + + + + tpm + {B7456491-A2ED-4B1C-B59E-41C7B32B7E3B} + TPMCmd + Win32Proj + $([Microsoft.Build.Utilities.ToolLocationHelper]::GetLatestSDKTargetPlatformVersion('Windows', '10.0')) + + + + DynamicLibrary + Unicode + false + v141 + + + DynamicLibrary + Unicode + false + v141 + + + DynamicLibrary + Unicode + v141 + + + DynamicLibrary + Unicode + v141 + + + StaticLibrary + Unicode + v141 + + + DynamicLibrary + Unicode + false + v141 + + + DynamicLibrary + Unicode + false + v141 + + + DynamicLibrary + Unicode + v141 + + + DynamicLibrary + Unicode + v141 + + + StaticLibrary + Unicode + v141 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + .\Debug;$(ReferencePath) + .\Debug;$(ReferencePath) + .\Debug;$(ReferencePath) + $(SolutionDir)\$(Configuration)\ + $(SolutionDir)\bin\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)\bin\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)\bin\$(ProjectName)\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)\bin\$(ProjectName)\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)\bin\$(ProjectName)\$(PlatformTarget)\$(Configuration)\ + true + true + true + .\Debug;$(ReferencePath) + .\Debug;$(ReferencePath) + .\Debug;$(ReferencePath) + $(SolutionDir)\bin\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)\bin\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)\bin\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)\bin\$(ProjectName)\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)\bin\$(ProjectName)\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)\bin\$(ProjectName)\$(PlatformTarget)\$(Configuration)\ + true + true + true + .\Debug;$(ReferencePath) + .\Debug;$(ReferencePath) + $(SolutionDir)\$(Configuration)\ + $(SolutionDir)\bin\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)\bin\$(ProjectName)\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)\bin\$(ProjectName)\$(PlatformTarget)\$(Configuration)\ + false + false + .\Debug;$(ReferencePath) + .\Debug;$(ReferencePath) + $(SolutionDir)\bin\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)\bin\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)\bin\$(ProjectName)\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)\bin\$(ProjectName)\$(PlatformTarget)\$(Configuration)\ + false + false + AllRules.ruleset + AllRules.ruleset + AllRules.ruleset + + + + + + + AllRules.ruleset + AllRules.ruleset + AllRules.ruleset + + + + + + + AllRules.ruleset + AllRules.ruleset + + + + + AllRules.ruleset + AllRules.ruleset + + + + + .dll + .dll + .lib + BuildLink + + + false + + + false + + + + $(ProjectDir)include\;$(ProjectDir)include\prototypes\;$(SolutionDir)Platform\include\;$(SolutionDir)Platform\include\prototypes\;$(SolutionDir)LtcInclude\;$(SolutionDIr)OsslInclude\;$(SolutionDir)MsBnInclude\ + + + + + + Disabled + $(ProjectDir)include\;$(ProjectDir)include\prototypes\;$(SolutionDir)Platform\include\;$(SolutionDir)Platform\include\prototypes\;$(SolutionDir)LtcInclude\;$(SolutionDIr)OsslInclude\;$(SolutionDir)MsBnInclude\ + TABLE_DRIVEN_DISPATCH=0;HASH_LIB=Ossl;SYM_LIB=Ossl;MATH_LIB=Ossl;%(PreprocessorDefinitions); + false + MultiThreadedDebugDLL + NotUsing + $(IntDir)Server.pdb + EnableAllWarnings + Cdecl + CompileAsC + Default + 4668;4710;4711;4820;5045 + true + Default + EnableFastChecks + true + + + true + true + + + platform.lib;libcrypto.lib;%(AdditionalDependencies) + $(SolutionDir)\lib;$(OutDir);%(AdditionalLibraryDirectories) + + + true + NotSet + MachineX86 + $(OutDir)$(TargetName)$(TargetExt) + false + false + $(OutDir)Tpm.map + + + $(OutDir)$(TargetName)$(TargetExt) + + + $(SolutionDir)lib;$(OutDir) + + + $(ProjectDir)\tpm\TPM.def + CryptoEngine.dll;platform.lib + + + true + + + del $(SolutionDir)Simulator\NVChip +del $(SolutionDir)Simulator\RsaKeyCache*.data + + + + + Disabled + $(ProjectDir)include\wolf;$(SolutionDir)..\external\wolfssl;$(SolutionDir)\wolfcrypt\include;%(AdditionalIncludeDirectories) + TABLE_DRIVEN_DISPATCH=0;COMPILER_CHECKS;LIBRARY_COMPATIBILITY_CHECK;HASH_LIB=Wolf;SYM_LIB=Wolf;MATH_LIB=Wolf;WOLFSSL_USER_SETTINGS;%(PreprocessorDefinitions) + false + MultiThreadedDebugDLL + NotUsing + $(IntDir)Server.pdb + EnableAllWarnings + Cdecl + CompileAsC + Default + 4127;4255;4668; 4710;4711; 4820;5045 + true + Default + EnableFastChecks + true + + + true + true + + + wolfssl.lib;platform.lib;%(AdditionalDependencies) + $(SolutionDir)\$(Configuration);$(OutDir);%(AdditionalLibraryDirectories) + + + true + NotSet + MachineX86 + $(OutDir)$(TargetName)$(TargetExt) + false + false + $(OutDir)Tpm.map + + + $(OutDir)$(TargetName)$(TargetExt) + + + $(ProjectDir)\lib;$(OutDir); + + + $(ProjectDir)\tpm\TPM.def + CryptoEngine.dll;platform.lib + + + true + + + + + Disabled + $(ProjectDir)include\;$(ProjectDir)include\prototypes\;$(SolutionDir)Platform\include\;$(SolutionDir)Platform\include\prototypes\;$(SolutionDir)LtcInclude\;$(SolutionDIr)OsslInclude\;$(SolutionDir)MsBnInclude\ + TABLE_DRIVEN_DISPATCH=0;HASH_LIB=Ossl;SYM_LIB=Ossl;MATH_LIB=Ossl;CRYPTO_ALIGN_4;_DEBUG;%(PreprocessorDefinitions) + false + EnableFastChecks + MultiThreadedDebugDLL + NotUsing + $(IntDir)Server.pdb + EnableAllWarnings + EditAndContinue + Cdecl + CompileAsC + Default + 4668; 4710;4711; 4820;5045 + false + true + + + true + true + + + cryptoengine.lib;platform.lib;%(AdditionalDependencies) + $(ProjectDir)\lib;$(OutDir);%(AdditionalLibraryDirectories) + + + true + Console + MachineX86 + $(OutDir)$(TargetName)$(TargetExt) + + + $(OutDir)$(TargetName)$(TargetExt) + + + + + + + + + + + + + + + X64 + + + Disabled + $(ProjectDir)include\;$(ProjectDir)include\prototypes\;$(SolutionDir)Platform\include\;$(SolutionDir)Platform\include\prototypes\;$(SolutionDir)LtcInclude\;$(SolutionDIr)OsslInclude\;$(SolutionDir)MsBnInclude\ + TABLE_DRIVEN_DISPATCH=0;HASH_LIB=Ossl;SYM_LIB=Ossl;MATH_LIB=Ossl;CRYPTO_ALIGN_16;_DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + EnableAllWarnings + ProgramDatabase + 4668; 4710;4711; 4820;5045 + true + + + platform.lib;libcrypto.lib;%(AdditionalDependencies) + true + Console + MachineX64 + $(SolutionDir)\lib\x64;$(OutDir);%(AdditionalLibraryDirectories) + + + + + + + X64 + + + Disabled + $(ProjectDir)include\wolf;$(SolutionDir)..\external\wolfssl;$(SolutionDir)\wolfcrypt\include;%(AdditionalIncludeDirectories) + TABLE_DRIVEN_DISPATCH=0;COMPILER_CHECKS;LIBRARY_COMPATIBILITY_CHECK;HASH_LIB=Wolf;SYM_LIB=Wolf;MATH_LIB=Wolf;WOLFSSL_USER_SETTINGS;_DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + EnableAllWarnings + ProgramDatabase + 4127;4255;4668; 4710;4711; 4820;5045 + true + + + wolfssl.lib;platform.lib;%(AdditionalDependencies) + true + Console + MachineX64 + $(OutDir);%(AdditionalLibraryDirectories) + + + + + + + X64 + + + Disabled + $(ProjectDir)include\;$(ProjectDir)include\prototypes\;$(SolutionDir)Platform\include\;$(SolutionDir)Platform\include\prototypes\;$(SolutionDir)LtcInclude\;$(SolutionDIr)OsslInclude\;$(SolutionDir)MsBnInclude\ + TABLE_DRIVEN_DISPATCH=0;HASH_LIB=Ossl;SYM_LIB=Ossl;MATH_LIB=Ossl;CRYPTO_ALIGN_16;_DEBUG;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + EnableAllWarnings + ProgramDatabase + 4668; 4710;4711; 4820;5045 + true + + + cryptoengine.lib;platform.lib;%(AdditionalDependencies) + true + Console + MachineX64 + $(SolutionDir)\lib\x64;$(OutDir);%(AdditionalLibraryDirectories) + + + + + + + MaxSpeed + $(ProjectDir)include\;$(ProjectDir)include\prototypes\;$(SolutionDir)Platform\include\;$(SolutionDir)Platform\include\prototypes\;$(SolutionDir)LtcInclude\;$(SolutionDIr)OsslInclude\;$(SolutionDir)MsBnInclude\ + true + TABLE_DRIVEN_DISPATCH=0;HASH_LIB=Ossl;SYM_LIB=Ossl;MATH_LIB=Ossl;CRYPTO_ALIGN_4;NDEBUG;%(PreprocessorDefinitions) + MultiThreadedDLL + true + NotUsing + EnableAllWarnings + ProgramDatabase + CompileAsC + true + 4668;4710;4711;4820;5045 + + + platform.lib;libcrypto.lib;%(AdditionalDependencies) + true + Console + true + true + MachineX86 + $(SolutionDir)\lib;$(OutDir);%(AdditionalLibraryDirectories) + + + $(OutDir)$(TargetName)$(TargetExt) + + + + + MaxSpeed + $(ProjectDir)include\wolf;$(SolutionDir)..\external\wolfssl;$(SolutionDir)\wolfcrypt\include;%(AdditionalIncludeDirectories) + true + TABLE_DRIVEN_DISPATCH=0;HASH_LIB=Wolf;SYM_LIB=Wolf;MATH_LIB=Wolf;WOLFSSL_USER_SETTINGS;CRYPTO_ALIGN_4;NDEBUG;%(PreprocessorDefinitions) + MultiThreadedDLL + true + NotUsing + EnableAllWarnings + ProgramDatabase + CompileAsC + 4127;4255;4668; 4710;4711; 4820;5045 + true + + + wolfssl.lib;platform.lib;%(AdditionalDependencies) + true + Console + true + true + MachineX86 + $(SolutionDir)\lib;$(OutDir);%(AdditionalLibraryDirectories) + + + $(OutDir)$(TargetName)$(TargetExt) + + + + + X64 + + + MaxSpeed + $(ProjectDir)include\;$(ProjectDir)include\prototypes\;$(SolutionDir)Platform\include\;$(SolutionDir)Platform\include\prototypes\;$(SolutionDir)LtcInclude\;$(SolutionDIr)OsslInclude\;$(SolutionDir)MsBnInclude\ + true + TABLE_DRIVEN_DISPATCH=0;HASH_LIB=Ossl;SYM_LIB=Ossl;MATH_LIB=Ossl;CRYPTO_ALIGN_16;NDEBUG;%(PreprocessorDefinitions); + MultiThreadedDLL + true + + + EnableAllWarnings + ProgramDatabase + 16Bytes + true + 4668;4710;4711;4820;5045 + + + true + Console + true + true + MachineX64 + $(SolutionDir)\lib\x64;$(OutDir);%(AdditionalLibraryDirectories) + platform.lib;libcrypto.lib;Advapi32.lib;User32.lib;Gdi32.lib + + + + + false + true + + + + + X64 + + + MaxSpeed + $(ProjectDir)include\wolf;$(SolutionDir)..\external\wolfssl;$(SolutionDir)\wolfcrypt\include;%(AdditionalIncludeDirectories) + true + TABLE_DRIVEN_DISPATCH=0;HASH_LIB=Wolf;SYM_LIB=Wolf;MATH_LIB=Wolf;WOLFSSL_USER_SETTINGS;NDEBUG;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + EnableAllWarnings + ProgramDatabase + 16Bytes + true + 4127;4255;4668; 4710;4711; 4820;5045 + + + true + Console + true + true + MachineX64 + $(OutDir);%(AdditionalLibraryDirectories) + wolfssl.lib;platform.lib;Advapi32.lib + + + + + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/Tpm.vcxproj.filters b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/Tpm.vcxproj.filters new file mode 100644 index 0000000..3e4c499 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/Tpm.vcxproj.filters @@ -0,0 +1,1428 @@ + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files\Crypt + + + Source Files\Crypt + + + Source Files\Crypt + + + Source Files\Crypt + + + Source Files\Crypt + + + Source Files\Crypt + + + Source Files\Crypt + + + Source Files\Crypt + + + Source Files\Crypt + + + Source Files\Crypt + + + Source Files\Crypt + + + Source Files\Crypt + + + Source Files\Crypt + + + Source Files\Crypt\ossl + + + Source Files\Crypt\ossl + + + Source Files\Crypt + + + Source Files\Crypt + + + Source Files + + + Source Files\Crypt + + + Source Files + + + Source Files\Crypt + + + Source Files\Crypt\ossl + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files\Crypt + + + Source Files\AttachedComponent + + + Source Files\AttachedComponent + + + Source Files\AttachedComponent + + + Source Files\AttachedComponent + + + Source Files + + + Source Files\Crypt + + + Source Files + + + Source Files\Crypt + + + Source Files\Crypt + + + Source Files + + + Source Files\X509 + + + Source Files\X509 + + + Source Files\X509 + + + Source Files + + + Source Files + + + Source Files\X509 + + + Source Files\ACT + + + Source Files\ACT + + + Source Files\Crypt\wolf + + + Source Files\Crypt\wolf + + + Source Files\Crypt\wolf + + + Source Files\Crypt\ltc + + + Source Files\Crypt\ltc + + + Source Files\Crypt\ltc + + + Source Files\Crypt + + + Source Files + + + Source Files + + + + + Headers + + + Headers + + + Headers + + + Headers + + + Headers + + + Headers + + + Headers + + + Headers + + + Headers + + + Headers + + + Headers + + + Headers + + + Headers + + + Headers + + + Headers + + + Headers + + + Headers + + + Headers + + + Headers + + + Headers + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\Crypt + + + Source Files\X509 + + + Source Files\X509 + + + Source Files\X509 + + + Headers\Crypt + + + Headers\Crypt + + + Headers\Crypt + + + Headers\Crypt + + + Headers\Crypt + + + Headers\Crypt + + + Headers\Crypt + + + Headers\Crypt + + + Headers\Crypt + + + Headers + + + Headers\prototypes + + + Headers\Crypt + + + Headers\Crypt + + + Headers\Crypt + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\Crypt + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers\Crypt\ltc + + + Headers\Crypt\ltc + + + Headers\Crypt\ltc + + + Headers\Crypt\ltc + + + Headers\Crypt\ossl + + + Headers\Crypt\ossl + + + Headers\Crypt\ossl + + + Headers\Crypt\wolf + + + Headers\Crypt\wolf + + + Headers\Crypt\wolf + + + Headers\prototypes + + + Headers\prototypes + + + Headers\prototypes + + + Headers + + + Headers + + + Headers\Crypt\wolf + + + Headers + + + Source Files\Crypt + + + Source Files\Crypt + + + Source Files\ACT + + + Headers + + + Headers + + + Headers + + + Headers + + + Headers + + + Headers\prototypes + + + + + {0860d8a3-a60e-4ead-918e-79534b3c000d} + + + {0ac750c7-149f-40fc-9820-47287d744b3b} + + + {be59b71d-f8f7-4132-80f5-e5f6f311614f} + + + {cdeea2ca-7d66-43fc-9431-4bb51e70e78e} + + + {ef67ef8f-3c7e-492b-b8de-0fd83194ad1d} + + + {46a498d0-be4d-4034-b163-014a2ebcf2e1} + + + {6170bedc-9916-44b4-a24b-340b04313b20} + + + {c1608ff8-dc12-4101-8859-6d763377b840} + + + {eb07d621-fe5c-415a-84f0-d0e4c68039ed} + + + {1a979e04-0e58-4286-b6b0-52cb2b86d037} + + + {17d101a1-3063-43f5-960b-b0df7b0950cc} + + + {19c87ebb-c1f3-4521-a442-d9120957d238} + + + {c0101f08-45d5-48bf-bc4d-a64e300da76d} + + + {c4ec5a52-b2f4-4af2-a654-3116ed9da682} + + + \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/ACT.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/ACT.h new file mode 100644 index 0000000..52da535 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/ACT.h @@ -0,0 +1,235 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 _ACT_H_ +#define _ACT_H_ + +#include "TpmProfile.h" + +#if !(defined RH_ACT_0) || (RH_ACT_0 != YES) +# undef RH_ACT_0 +# define RH_ACT_0 NO +# define IF_ACT_0_IMPLEMENTED(op) +#else +# define IF_ACT_0_IMPLEMENTED(op) op(0) +#endif +#if !(defined RH_ACT_1) || (RH_ACT_1 != YES) +# undef RH_ACT_1 +# define RH_ACT_1 NO +# define IF_ACT_1_IMPLEMENTED(op) +#else +# define IF_ACT_1_IMPLEMENTED(op) op(1) +#endif +#if !(defined RH_ACT_2) || (RH_ACT_2 != YES) +# undef RH_ACT_2 +# define RH_ACT_2 NO +# define IF_ACT_2_IMPLEMENTED(op) +#else +# define IF_ACT_2_IMPLEMENTED(op) op(2) +#endif +#if !(defined RH_ACT_3) || (RH_ACT_3 != YES) +# undef RH_ACT_3 +# define RH_ACT_3 NO +# define IF_ACT_3_IMPLEMENTED(op) +#else +# define IF_ACT_3_IMPLEMENTED(op) op(3) +#endif +#if !(defined RH_ACT_4) || (RH_ACT_4 != YES) +# undef RH_ACT_4 +# define RH_ACT_4 NO +# define IF_ACT_4_IMPLEMENTED(op) +#else +# define IF_ACT_4_IMPLEMENTED(op) op(4) +#endif +#if !(defined RH_ACT_5) || (RH_ACT_5 != YES) +# undef RH_ACT_5 +# define RH_ACT_5 NO +# define IF_ACT_5_IMPLEMENTED(op) +#else +# define IF_ACT_5_IMPLEMENTED(op) op(5) +#endif +#if !(defined RH_ACT_6) || (RH_ACT_6 != YES) +# undef RH_ACT_6 +# define RH_ACT_6 NO +# define IF_ACT_6_IMPLEMENTED(op) +#else +# define IF_ACT_6_IMPLEMENTED(op) op(6) +#endif +#if !(defined RH_ACT_7) || (RH_ACT_7 != YES) +# undef RH_ACT_7 +# define RH_ACT_7 NO +# define IF_ACT_7_IMPLEMENTED(op) +#else +# define IF_ACT_7_IMPLEMENTED(op) op(7) +#endif +#if !(defined RH_ACT_8) || (RH_ACT_8 != YES) +# undef RH_ACT_8 +# define RH_ACT_8 NO +# define IF_ACT_8_IMPLEMENTED(op) +#else +# define IF_ACT_8_IMPLEMENTED(op) op(8) +#endif +#if !(defined RH_ACT_9) || (RH_ACT_9 != YES) +# undef RH_ACT_9 +# define RH_ACT_9 NO +# define IF_ACT_9_IMPLEMENTED(op) +#else +# define IF_ACT_9_IMPLEMENTED(op) op(9) +#endif +#if !(defined RH_ACT_A) || (RH_ACT_A != YES) +# undef RH_ACT_A +# define RH_ACT_A NO +# define IF_ACT_A_IMPLEMENTED(op) +#else +# define IF_ACT_A_IMPLEMENTED(op) op(A) +#endif +#if !(defined RH_ACT_B) || (RH_ACT_B != YES) +# undef RH_ACT_B +# define RH_ACT_B NO +# define IF_ACT_B_IMPLEMENTED(op) +#else +# define IF_ACT_B_IMPLEMENTED(op) op(B) +#endif +#if !(defined RH_ACT_C) || (RH_ACT_C != YES) +# undef RH_ACT_C +# define RH_ACT_C NO +# define IF_ACT_C_IMPLEMENTED(op) +#else +# define IF_ACT_C_IMPLEMENTED(op) op(C) +#endif +#if !(defined RH_ACT_D) || (RH_ACT_D != YES) +# undef RH_ACT_D +# define RH_ACT_D NO +# define IF_ACT_D_IMPLEMENTED(op) +#else +# define IF_ACT_D_IMPLEMENTED(op) op(D) +#endif +#if !(defined RH_ACT_E) || (RH_ACT_E != YES) +# undef RH_ACT_E +# define RH_ACT_E NO +# define IF_ACT_E_IMPLEMENTED(op) +#else +# define IF_ACT_E_IMPLEMENTED(op) op(E) +#endif +#if !(defined RH_ACT_F) || (RH_ACT_F != YES) +# undef RH_ACT_F +# define RH_ACT_F NO +# define IF_ACT_F_IMPLEMENTED(op) +#else +# define IF_ACT_F_IMPLEMENTED(op) op(F) +#endif + +#ifndef TPM_RH_ACT_0 +# error Need numeric definition for TPM_RH_ACT_0 +#endif + +#ifndef TPM_RH_ACT_1 +# define TPM_RH_ACT_1 (TPM_RH_ACT_0 + 1) +#endif +#ifndef TPM_RH_ACT_2 +# define TPM_RH_ACT_2 (TPM_RH_ACT_0 + 2) +#endif +#ifndef TPM_RH_ACT_3 +# define TPM_RH_ACT_3 (TPM_RH_ACT_0 + 3) +#endif +#ifndef TPM_RH_ACT_4 +# define TPM_RH_ACT_4 (TPM_RH_ACT_0 + 4) +#endif +#ifndef TPM_RH_ACT_5 +# define TPM_RH_ACT_5 (TPM_RH_ACT_0 + 5) +#endif +#ifndef TPM_RH_ACT_6 +# define TPM_RH_ACT_6 (TPM_RH_ACT_0 + 6) +#endif +#ifndef TPM_RH_ACT_7 +# define TPM_RH_ACT_7 (TPM_RH_ACT_0 + 7) +#endif +#ifndef TPM_RH_ACT_8 +# define TPM_RH_ACT_8 (TPM_RH_ACT_0 + 8) +#endif +#ifndef TPM_RH_ACT_9 +# define TPM_RH_ACT_9 (TPM_RH_ACT_0 + 9) +#endif +#ifndef TPM_RH_ACT_A +# define TPM_RH_ACT_A (TPM_RH_ACT_0 + 0xA) +#endif +#ifndef TPM_RH_ACT_B +# define TPM_RH_ACT_B (TPM_RH_ACT_0 + 0xB) +#endif +#ifndef TPM_RH_ACT_C +# define TPM_RH_ACT_C (TPM_RH_ACT_0 + 0xC) +#endif +#ifndef TPM_RH_ACT_D +# define TPM_RH_ACT_D (TPM_RH_ACT_0 + 0xD) +#endif +#ifndef TPM_RH_ACT_E +# define TPM_RH_ACT_E (TPM_RH_ACT_0 + 0xE) +#endif +#ifndef TPM_RH_ACT_F +# define TPM_RH_ACT_F (TPM_RH_ACT_0 + 0xF) +#endif + +#define FOR_EACH_ACT(op) \ + IF_ACT_0_IMPLEMENTED(op) \ + IF_ACT_1_IMPLEMENTED(op) \ + IF_ACT_2_IMPLEMENTED(op) \ + IF_ACT_3_IMPLEMENTED(op) \ + IF_ACT_4_IMPLEMENTED(op) \ + IF_ACT_5_IMPLEMENTED(op) \ + IF_ACT_6_IMPLEMENTED(op) \ + IF_ACT_7_IMPLEMENTED(op) \ + IF_ACT_8_IMPLEMENTED(op) \ + IF_ACT_9_IMPLEMENTED(op) \ + IF_ACT_A_IMPLEMENTED(op) \ + IF_ACT_B_IMPLEMENTED(op) \ + IF_ACT_C_IMPLEMENTED(op) \ + IF_ACT_D_IMPLEMENTED(op) \ + IF_ACT_E_IMPLEMENTED(op) \ + IF_ACT_F_IMPLEMENTED(op) + +// This is the mask for ACT that are implemented +//#define ACT_MASK(N) | (1 << 0x##N) +//#define ACT_IMPLEMENTED_MASK (0 FOR_EACH_ACT(ACT_MASK)) + +#define CASE_ACT_HANDLE(N) case TPM_RH_ACT_##N: +#define CASE_ACT_NUMBER(N) case 0x##N: + +typedef struct ACT_STATE +{ + UINT32 remaining; + TPM_ALG_ID hashAlg; + TPM2B_DIGEST authPolicy; +} ACT_STATE, *P_ACT_STATE; + +#endif // _ACT_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/BaseTypes.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/BaseTypes.h new file mode 100644 index 0000000..008739a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/BaseTypes.h @@ -0,0 +1,59 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.2 Feb 22, 2019 + * Date: Mar 20, 2019 Time: 08:27:26PM + */ + +#ifndef _BASE_TYPES_H_ +#define _BASE_TYPES_H_ + +// NULL definition +#ifndef NULL +# define NULL (0) +#endif + +typedef uint8_t UINT8; +typedef uint8_t BYTE; +typedef int8_t INT8; +typedef int BOOL; +typedef uint16_t UINT16; +typedef int16_t INT16; +typedef uint32_t UINT32; +typedef int32_t INT32; +typedef uint64_t UINT64; +typedef int64_t INT64; + +#endif // _BASE_TYPES_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/BnValues.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/BnValues.h new file mode 100644 index 0000000..fa7dc10 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/BnValues.h @@ -0,0 +1,354 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction + +// This file contains the definitions needed for defining the internal BIGNUM +// structure. + +// A BIGNUM is a pointer to a structure. The structure has three fields. The +// last field is and array (d) of crypt_uword_t. Each word is in machine format +// (big- or little-endian) with the words in ascending significance (i.e. words +// in little-endian order). This is the order that seems to be used in every +// big number library in the worlds, so... +// +// The first field in the structure (allocated) is the number of words in 'd'. +// This is the upper limit on the size of the number that can be held in the +// structure. This differs from libraries like OpenSSL as this is not intended +// to deal with numbers of arbitrary size; just numbers that are needed to deal +// with the algorithms that are defined in the TPM implementation. +// +// The second field in the structure (size) is the number of significant words +// in 'n'. When this number is zero, the number is zero. The word at used-1 should +// never be zero. All words between d[size] and d[allocated-1] should be zero. + +//** Defines + +#ifndef _BN_NUMBERS_H +#define _BN_NUMBERS_H + +#if RADIX_BITS == 64 +# define RADIX_LOG2 6 +#elif RADIX_BITS == 32 +# define RADIX_LOG2 5 +#else +# error "Unsupported radix" +#endif + +#define RADIX_MOD(x) ((x) & ((1 << RADIX_LOG2) - 1)) +#define RADIX_DIV(x) ((x) >> RADIX_LOG2) +#define RADIX_MASK ((((crypt_uword_t)1) << RADIX_LOG2) - 1) + +#define BITS_TO_CRYPT_WORDS(bits) RADIX_DIV((bits) + (RADIX_BITS - 1)) +#define BYTES_TO_CRYPT_WORDS(bytes) BITS_TO_CRYPT_WORDS(bytes * 8) +#define SIZE_IN_CRYPT_WORDS(thing) BYTES_TO_CRYPT_WORDS(sizeof(thing)) + +#if RADIX_BITS == 64 +# define SWAP_CRYPT_WORD(x) REVERSE_ENDIAN_64(x) +typedef uint64_t crypt_uword_t; +typedef int64_t crypt_word_t; +# define TO_CRYPT_WORD_64 BIG_ENDIAN_BYTES_TO_UINT64 +# define TO_CRYPT_WORD_32(a, b, c, d) TO_CRYPT_WORD_64(0, 0, 0, 0, a, b, c, d) +#elif RADIX_BITS == 32 +# define SWAP_CRYPT_WORD(x) REVERSE_ENDIAN_32((x)) +typedef uint32_t crypt_uword_t; +typedef int32_t crypt_word_t; +# define TO_CRYPT_WORD_64(a, b, c, d, e, f, g, h) \ + BIG_ENDIAN_BYTES_TO_UINT32(e, f, g, h), BIG_ENDIAN_BYTES_TO_UINT32(a, b, c, d) +#endif + +#define MAX_CRYPT_UWORD (~((crypt_uword_t)0)) +#define MAX_CRYPT_WORD ((crypt_word_t)(MAX_CRYPT_UWORD >> 1)) +#define MIN_CRYPT_WORD (~MAX_CRYPT_WORD) + +#define LARGEST_NUMBER \ + (MAX((ALG_RSA * MAX_RSA_KEY_BYTES), \ + MAX((ALG_ECC * MAX_ECC_KEY_BYTES), MAX_DIGEST_SIZE))) +#define LARGEST_NUMBER_BITS (LARGEST_NUMBER * 8) + +#define MAX_ECC_PARAMETER_BYTES (MAX_ECC_KEY_BYTES * ALG_ECC) + +// These are the basic big number formats. This is convertible to the library- +// specific format without too much difficulty. For the math performed using +// these numbers, the value is always positive. +#define BN_STRUCT_DEF(count) \ + struct \ + { \ + crypt_uword_t allocated; \ + crypt_uword_t size; \ + crypt_uword_t d[count]; \ + } + +typedef BN_STRUCT_DEF(1) bignum_t; +#ifndef bigNum +typedef bignum_t* bigNum; +typedef const bignum_t* bigConst; +#endif + +extern const bignum_t BnConstZero; + +// The Functions to access the properties of a big number. +// Get number of allocated words +#define BnGetAllocated(x) (unsigned)((x)->allocated) + +// Get number of words used +#define BnGetSize(x) ((x)->size) + +// Get a pointer to the data array +#define BnGetArray(x) ((crypt_uword_t*)&((x)->d[0])) + +// Get the nth word of a BIGNUM (zero-based) +#define BnGetWord(x, i) (crypt_uword_t)((x)->d[i]) + +// Some things that are done often. + +// Test to see if a bignum_t is equal to zero +#define BnEqualZero(bn) (BnGetSize(bn) == 0) + +// Test to see if a bignum_t is equal to a word type +#define BnEqualWord(bn, word) \ + ((BnGetSize(bn) == 1) && (BnGetWord(bn, 0) == (crypt_uword_t)word)) + +// Determine if a BIGNUM is even. A zero is even. Although the +// indication that a number is zero is that its size is zero, +// all words of the number are 0 so this test works on zero. +#define BnIsEven(n) ((BnGetWord(n, 0) & 1) == 0) + +// The macros below are used to define BIGNUM values of the required +// size. The values are allocated on the stack so they can be +// treated like simple local values. + +// This will call the initialization function for a defined bignum_t. +// This sets the allocated and used fields and clears the words of 'n'. +#define BN_INIT(name) \ + (bigNum) BnInit((bigNum) & (name), BYTES_TO_CRYPT_WORDS(sizeof(name.d))) + +// In some cases, a function will need the address of the structure +// associated with a variable. The structure for a BIGNUM variable +// of 'name' is 'name_'. Generally, when the structure is created, it +// is initialized and a parameter is created with a pointer to the +// structure. The pointer has the 'name' and the structure it points +// to is 'name_' +#define BN_ADDRESS(name) (bigNum) & name##_ + +#define CRYPT_WORDS(bytes) BYTES_TO_CRYPT_WORDS(bytes) +#define MIN_ALLOC(bytes) (CRYPT_WORDS(bytes) < 1 ? 1 : CRYPT_WORDS(bytes)) +#define BN_CONST(name, bytes, initializer) \ + typedef const struct name##_type \ + { \ + crypt_uword_t allocated; \ + crypt_uword_t size; \ + crypt_uword_t d[MIN_ALLOC(bytes)]; \ + } name##_type; \ + name##_type name = {MIN_ALLOC(bytes), CRYPT_WORDS(bytes), {initializer}}; + +#define BN_STRUCT_ALLOCATION(bits) (BITS_TO_CRYPT_WORDS(bits) + 1) + +// Create a structure of the correct size. +#define BN_STRUCT(bits) BN_STRUCT_DEF(BN_STRUCT_ALLOCATION(bits)) + +// Define a BIGNUM type with a specific allocation +#define BN_TYPE(name, bits) typedef BN_STRUCT(bits) bn_##name##_t + +// This creates a local BIGNUM variable of a specific size and +// initializes it from a TPM2B input parameter. +#define BN_INITIALIZED(name, bits, initializer) \ + BN_STRUCT(bits) name##_; \ + bigNum name = BnFrom2B(BN_INIT(name##_), (const TPM2B*)initializer) + +// Create a local variable that can hold a number with 'bits' +#define BN_VAR(name, bits) \ + BN_STRUCT(bits) _##name; \ + bigNum name = BN_INIT(_##name) + +// Create a type that can hold the largest number defined by the +// implementation. +#define BN_MAX(name) BN_VAR(name, LARGEST_NUMBER_BITS) +#define BN_MAX_INITIALIZED(name, initializer) \ + BN_INITIALIZED(name, LARGEST_NUMBER_BITS, initializer) + +// A word size value is useful +#define BN_WORD(name) BN_VAR(name, RADIX_BITS) + +// This is used to create a word-size BIGNUM and initialize it with +// an input parameter to a function. +#define BN_WORD_INITIALIZED(name, initial) \ + BN_STRUCT(RADIX_BITS) name##_; \ + bigNum name = \ + BnInitializeWord((bigNum)&name##_, BN_STRUCT_ALLOCATION(RADIX_BITS), initial) + +// ECC-Specific Values + +// This is the format for a point. It is always in affine format. The Z value is +// carried as part of the point, primarily to simplify the interface to the support +// library. Rather than have the interface layer have to create space for the +// point each time it is used... +// The x, y, and z values are pointers to bigNum values and not in-line versions of +// the numbers. This is a relic of the days when there was no standard TPM format +// for the numbers +typedef struct _bn_point_t +{ + bigNum x; + bigNum y; + bigNum z; +} bn_point_t; + +typedef bn_point_t* bigPoint; +typedef const bn_point_t* pointConst; + +typedef struct constant_point_t +{ + bigConst x; + bigConst y; + bigConst z; +} constant_point_t; + +#define ECC_BITS (MAX_ECC_KEY_BYTES * 8) +BN_TYPE(ecc, ECC_BITS); +#define ECC_NUM(name) BN_VAR(name, ECC_BITS) +#define ECC_INITIALIZED(name, initializer) BN_INITIALIZED(name, ECC_BITS, initializer) + +#define POINT_INSTANCE(name, bits) \ + BN_STRUCT(bits) name##_x = {BITS_TO_CRYPT_WORDS(bits), 0, {0}}; \ + BN_STRUCT(bits) name##_y = {BITS_TO_CRYPT_WORDS(bits), 0, {0}}; \ + BN_STRUCT(bits) name##_z = {BITS_TO_CRYPT_WORDS(bits), 0, {0}}; \ + bn_point_t name##_ + +#define POINT_INITIALIZER(name) \ + BnInitializePoint(&name##_, (bigNum)&name##_x, (bigNum)&name##_y, (bigNum)&name##_z) + +#define POINT_INITIALIZED(name, initValue) \ + POINT_INSTANCE(name, MAX_ECC_KEY_BITS); \ + bigPoint name = BnPointFrom2B(POINT_INITIALIZER(name), initValue) + +#define POINT_VAR(name, bits) \ + POINT_INSTANCE(name, bits); \ + bigPoint name = POINT_INITIALIZER(name) + +#define POINT(name) POINT_VAR(name, MAX_ECC_KEY_BITS) + +// Structure for the curve parameters. This is an analog to the +// TPMS_ALGORITHM_DETAIL_ECC +typedef struct +{ + bigConst prime; // a prime number + bigConst order; // the order of the curve + bigConst h; // cofactor + bigConst a; // linear coefficient + bigConst b; // constant term + constant_point_t base; // base point +} ECC_CURVE_DATA; + +// Access macros for the ECC_CURVE structure. The parameter 'C' is a pointer +// to an ECC_CURVE_DATA structure. In some libraries, the curve structure contains +// a pointer to an ECC_CURVE_DATA structure as well as some other bits. For those +// cases, the AccessCurveData macro is used in the code to first get the pointer +// to the ECC_CURVE_DATA for access. In some cases, the macro does nothing. +#define CurveGetPrime(C) ((C)->prime) +#define CurveGetOrder(C) ((C)->order) +#define CurveGetCofactor(C) ((C)->h) +#define CurveGet_a(C) ((C)->a) +#define CurveGet_b(C) ((C)->b) +#define CurveGetG(C) ((pointConst) & ((C)->base)) +#define CurveGetGx(C) ((C)->base.x) +#define CurveGetGy(C) ((C)->base.y) + +// Convert bytes in initializers +// This is used for CryptEccData.c. +#define BIG_ENDIAN_BYTES_TO_UINT32(a, b, c, d) \ + (((UINT32)(a) << 24) + ((UINT32)(b) << 16) + ((UINT32)(c) << 8) + ((UINT32)(d))) + +#define BIG_ENDIAN_BYTES_TO_UINT64(a, b, c, d, e, f, g, h) \ + (((UINT64)(a) << 56) + ((UINT64)(b) << 48) + ((UINT64)(c) << 40) \ + + ((UINT64)(d) << 32) + ((UINT64)(e) << 24) + ((UINT64)(f) << 16) \ + + ((UINT64)(g) << 8) + ((UINT64)(h))) + +#ifndef RADIX_BYTES +# if RADIX_BITS == 32 +# define RADIX_BYTES 4 +# elif RADIX_BITS == 64 +# define RADIX_BYTES 8 +# else +# error "RADIX_BITS must either be 32 or 64" +# endif +#endif + +// These macros are used for data initialization of big number ECC constants +// These two macros combine a macro for data definition with a macro for +// structure initialization. The 'a' parameter is a macro that gives numbers to +// each of the bytes of the initializer and defines where each of the numberd +// bytes will show up in the final structure. The 'b' value is a structure that +// contains the requisite number of bytes in big endian order. S, the MJOIN +// and JOIND macros will combine a macro defining a data layout with a macro defining +// the data to be places. Generally, these macros will only need expansion when +// CryptEccData.c gets compiled. +#define JOINED(a, b) a b +#define MJOIN(a, b) a b + +#if RADIX_BYTES == 64 +# define B8_TO_BN(a, b, c, d, e, f, g, h) \ + ((((((((((((((((UINT64)a) << 8) | (UINT64)b) << 8) | (UINT64)c) << 8) \ + | (UINT64)d) \ + << 8) \ + | (UINT64)e) \ + << 8) \ + | (UINT64)f) \ + << 8) \ + | (UINT64)g) \ + << 8) \ + | (UINT64)h) +# define B1_TO_BN(a) B8_TO_BN(0, 0, 0, 0, 0, 0, 0, a) +# define B2_TO_BN(a, b) B8_TO_BN(0, 0, 0, 0, 0, 0, a, b) +# define B3_TO_BN(a, b, c) B8_TO_BN(0, 0, 0, 0, 0, a, b, c) +# define B4_TO_BN(a, b, c, d) B8_TO_BN(0, 0, 0, 0, a, b, c, d) +# define B5_TO_BN(a, b, c, d, e) B8_TO_BN(0, 0, 0, a, b, c, d, e) +# define B6_TO_BN(a, b, c, d, e, f) B8_TO_BN(0, 0, a, b, c, d, e, f) +# define B7_TO_BN(a, b, c, d, e, f, g) B8_TO_BN(0, a, b, c, d, e, f, g) +#else +# define B1_TO_BN(a) B4_TO_BN(0, 0, 0, a) +# define B2_TO_BN(a, b) B4_TO_BN(0, 0, a, b) +# define B3_TO_BN(a, b, c) B4_TO_BN(0, a, b, c) +# define B4_TO_BN(a, b, c, d) \ + (((((((UINT32)a << 8) | (UINT32)b) << 8) | (UINT32)c) << 8) | (UINT32)d) +# define B5_TO_BN(a, b, c, d, e) B4_TO_BN(b, c, d, e), B1_TO_BN(a) +# define B6_TO_BN(a, b, c, d, e, f) B4_TO_BN(c, d, e, f), B2_TO_BN(a, b) +# define B7_TO_BN(a, b, c, d, e, f, g) B4_TO_BN(d, e, f, g), B3_TO_BN(a, b, c) +# define B8_TO_BN(a, b, c, d, e, f, g, h) B4_TO_BN(e, f, g, h), B4_TO_BN(a, b, c, d) + +#endif + +// Add implementation dependent definitions for other ECC Values and for linkages. +#include LIB_INCLUDE(MATH_LIB, Math) + +#endif // _BN_NUMBERS_H \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Capabilities.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Capabilities.h new file mode 100644 index 0000000..6304881 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Capabilities.h @@ -0,0 +1,50 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 _CAPABILITIES_H +#define _CAPABILITIES_H + +#define MAX_CAP_DATA (MAX_CAP_BUFFER - sizeof(TPM_CAP) - sizeof(UINT32)) +#define MAX_CAP_ALGS (MAX_CAP_DATA / sizeof(TPMS_ALG_PROPERTY)) +#define MAX_CAP_HANDLES (MAX_CAP_DATA / sizeof(TPM_HANDLE)) +#define MAX_CAP_CC (MAX_CAP_DATA / sizeof(TPM_CC)) +#define MAX_TPM_PROPERTIES (MAX_CAP_DATA / sizeof(TPMS_TAGGED_PROPERTY)) +#define MAX_PCR_PROPERTIES (MAX_CAP_DATA / sizeof(TPMS_TAGGED_PCR_SELECT)) +#define MAX_ECC_CURVES (MAX_CAP_DATA / sizeof(TPM_ECC_CURVE)) +#define MAX_TAGGED_POLICIES (MAX_CAP_DATA / sizeof(TPMS_TAGGED_POLICY)) +#define MAX_ACT_DATA (MAX_CAP_DATA / sizeof(TPMS_ACT_DATA)) + +#define MAX_AC_CAPABILITIES (MAX_CAP_DATA / sizeof(TPMS_AC_OUTPUT)) + +#endif diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CommandAttributeData.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CommandAttributeData.h new file mode 100644 index 0000000..d063729 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CommandAttributeData.h @@ -0,0 +1,944 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Sep 7, 2019 Time: 04:51:22PM + */ + +// This file should only be included by CommandCodeAttibutes.c +#ifdef _COMMAND_CODE_ATTRIBUTES_ + +# include "CommandAttributes.h" + +# if COMPRESSED_LISTS +# define PAD_LIST 0 +# else +# define PAD_LIST 1 +# endif + +// This is the command code attribute array for GetCapability. +// Both this array and s_commandAttributes provides command code attributes, +// but tuned for different purpose +const TPMA_CC s_ccAttr[] = { +# if(PAD_LIST || CC_NV_UndefineSpaceSpecial) + TPMA_CC_INITIALIZER(0x011F, 0, 1, 0, 0, 2, 0, 0, 0), +# endif +# if(PAD_LIST || CC_EvictControl) + TPMA_CC_INITIALIZER(0x0120, 0, 1, 0, 0, 2, 0, 0, 0), +# endif +# if(PAD_LIST || CC_HierarchyControl) + TPMA_CC_INITIALIZER(0x0121, 0, 1, 1, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_NV_UndefineSpace) + TPMA_CC_INITIALIZER(0x0122, 0, 1, 0, 0, 2, 0, 0, 0), +# endif +# if(PAD_LIST) + TPMA_CC_INITIALIZER(0x0123, 0, 0, 0, 0, 0, 0, 0, 0), +# endif +# if(PAD_LIST || CC_ChangeEPS) + TPMA_CC_INITIALIZER(0x0124, 0, 1, 1, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_ChangePPS) + TPMA_CC_INITIALIZER(0x0125, 0, 1, 1, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_Clear) + TPMA_CC_INITIALIZER(0x0126, 0, 1, 1, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_ClearControl) + TPMA_CC_INITIALIZER(0x0127, 0, 1, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_ClockSet) + TPMA_CC_INITIALIZER(0x0128, 0, 1, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_HierarchyChangeAuth) + TPMA_CC_INITIALIZER(0x0129, 0, 1, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_NV_DefineSpace) + TPMA_CC_INITIALIZER(0x012A, 0, 1, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_PCR_Allocate) + TPMA_CC_INITIALIZER(0x012B, 0, 1, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_PCR_SetAuthPolicy) + TPMA_CC_INITIALIZER(0x012C, 0, 1, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_PP_Commands) + TPMA_CC_INITIALIZER(0x012D, 0, 1, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_SetPrimaryPolicy) + TPMA_CC_INITIALIZER(0x012E, 0, 1, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_FieldUpgradeStart) + TPMA_CC_INITIALIZER(0x012F, 0, 0, 0, 0, 2, 0, 0, 0), +# endif +# if(PAD_LIST || CC_ClockRateAdjust) + TPMA_CC_INITIALIZER(0x0130, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_CreatePrimary) + TPMA_CC_INITIALIZER(0x0131, 0, 0, 0, 0, 1, 1, 0, 0), +# endif +# if(PAD_LIST || CC_NV_GlobalWriteLock) + TPMA_CC_INITIALIZER(0x0132, 0, 1, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_GetCommandAuditDigest) + TPMA_CC_INITIALIZER(0x0133, 0, 1, 0, 0, 2, 0, 0, 0), +# endif +# if(PAD_LIST || CC_NV_Increment) + TPMA_CC_INITIALIZER(0x0134, 0, 1, 0, 0, 2, 0, 0, 0), +# endif +# if(PAD_LIST || CC_NV_SetBits) + TPMA_CC_INITIALIZER(0x0135, 0, 1, 0, 0, 2, 0, 0, 0), +# endif +# if(PAD_LIST || CC_NV_Extend) + TPMA_CC_INITIALIZER(0x0136, 0, 1, 0, 0, 2, 0, 0, 0), +# endif +# if(PAD_LIST || CC_NV_Write) + TPMA_CC_INITIALIZER(0x0137, 0, 1, 0, 0, 2, 0, 0, 0), +# endif +# if(PAD_LIST || CC_NV_WriteLock) + TPMA_CC_INITIALIZER(0x0138, 0, 1, 0, 0, 2, 0, 0, 0), +# endif +# if(PAD_LIST || CC_DictionaryAttackLockReset) + TPMA_CC_INITIALIZER(0x0139, 0, 1, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_DictionaryAttackParameters) + TPMA_CC_INITIALIZER(0x013A, 0, 1, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_NV_ChangeAuth) + TPMA_CC_INITIALIZER(0x013B, 0, 1, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_PCR_Event) + TPMA_CC_INITIALIZER(0x013C, 0, 1, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_PCR_Reset) + TPMA_CC_INITIALIZER(0x013D, 0, 1, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_SequenceComplete) + TPMA_CC_INITIALIZER(0x013E, 0, 0, 0, 1, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_SetAlgorithmSet) + TPMA_CC_INITIALIZER(0x013F, 0, 1, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_SetCommandCodeAuditStatus) + TPMA_CC_INITIALIZER(0x0140, 0, 1, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_FieldUpgradeData) + TPMA_CC_INITIALIZER(0x0141, 0, 1, 0, 0, 0, 0, 0, 0), +# endif +# if(PAD_LIST || CC_IncrementalSelfTest) + TPMA_CC_INITIALIZER(0x0142, 0, 1, 0, 0, 0, 0, 0, 0), +# endif +# if(PAD_LIST || CC_SelfTest) + TPMA_CC_INITIALIZER(0x0143, 0, 1, 0, 0, 0, 0, 0, 0), +# endif +# if(PAD_LIST || CC_Startup) + TPMA_CC_INITIALIZER(0x0144, 0, 1, 0, 0, 0, 0, 0, 0), +# endif +# if(PAD_LIST || CC_Shutdown) + TPMA_CC_INITIALIZER(0x0145, 0, 1, 0, 0, 0, 0, 0, 0), +# endif +# if(PAD_LIST || CC_StirRandom) + TPMA_CC_INITIALIZER(0x0146, 0, 1, 0, 0, 0, 0, 0, 0), +# endif +# if(PAD_LIST || CC_ActivateCredential) + TPMA_CC_INITIALIZER(0x0147, 0, 0, 0, 0, 2, 0, 0, 0), +# endif +# if(PAD_LIST || CC_Certify) + TPMA_CC_INITIALIZER(0x0148, 0, 0, 0, 0, 2, 0, 0, 0), +# endif +# if(PAD_LIST || CC_PolicyNV) + TPMA_CC_INITIALIZER(0x0149, 0, 0, 0, 0, 3, 0, 0, 0), +# endif +# if(PAD_LIST || CC_CertifyCreation) + TPMA_CC_INITIALIZER(0x014A, 0, 0, 0, 0, 2, 0, 0, 0), +# endif +# if(PAD_LIST || CC_Duplicate) + TPMA_CC_INITIALIZER(0x014B, 0, 0, 0, 0, 2, 0, 0, 0), +# endif +# if(PAD_LIST || CC_GetTime) + TPMA_CC_INITIALIZER(0x014C, 0, 0, 0, 0, 2, 0, 0, 0), +# endif +# if(PAD_LIST || CC_GetSessionAuditDigest) + TPMA_CC_INITIALIZER(0x014D, 0, 0, 0, 0, 3, 0, 0, 0), +# endif +# if(PAD_LIST || CC_NV_Read) + TPMA_CC_INITIALIZER(0x014E, 0, 0, 0, 0, 2, 0, 0, 0), +# endif +# if(PAD_LIST || CC_NV_ReadLock) + TPMA_CC_INITIALIZER(0x014F, 0, 1, 0, 0, 2, 0, 0, 0), +# endif +# if(PAD_LIST || CC_ObjectChangeAuth) + TPMA_CC_INITIALIZER(0x0150, 0, 0, 0, 0, 2, 0, 0, 0), +# endif +# if(PAD_LIST || CC_PolicySecret) + TPMA_CC_INITIALIZER(0x0151, 0, 0, 0, 0, 2, 0, 0, 0), +# endif +# if(PAD_LIST || CC_Rewrap) + TPMA_CC_INITIALIZER(0x0152, 0, 0, 0, 0, 2, 0, 0, 0), +# endif +# if(PAD_LIST || CC_Create) + TPMA_CC_INITIALIZER(0x0153, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_ECDH_ZGen) + TPMA_CC_INITIALIZER(0x0154, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || (CC_HMAC || CC_MAC)) + TPMA_CC_INITIALIZER(0x0155, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_Import) + TPMA_CC_INITIALIZER(0x0156, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_Load) + TPMA_CC_INITIALIZER(0x0157, 0, 0, 0, 0, 1, 1, 0, 0), +# endif +# if(PAD_LIST || CC_Quote) + TPMA_CC_INITIALIZER(0x0158, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_RSA_Decrypt) + TPMA_CC_INITIALIZER(0x0159, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST) + TPMA_CC_INITIALIZER(0x015A, 0, 0, 0, 0, 0, 0, 0, 0), +# endif +# if(PAD_LIST || (CC_HMAC_Start || CC_MAC_Start)) + TPMA_CC_INITIALIZER(0x015B, 0, 0, 0, 0, 1, 1, 0, 0), +# endif +# if(PAD_LIST || CC_SequenceUpdate) + TPMA_CC_INITIALIZER(0x015C, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_Sign) + TPMA_CC_INITIALIZER(0x015D, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_Unseal) + TPMA_CC_INITIALIZER(0x015E, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST) + TPMA_CC_INITIALIZER(0x015F, 0, 0, 0, 0, 0, 0, 0, 0), +# endif +# if(PAD_LIST || CC_PolicySigned) + TPMA_CC_INITIALIZER(0x0160, 0, 0, 0, 0, 2, 0, 0, 0), +# endif +# if(PAD_LIST || CC_ContextLoad) + TPMA_CC_INITIALIZER(0x0161, 0, 0, 0, 0, 0, 1, 0, 0), +# endif +# if(PAD_LIST || CC_ContextSave) + TPMA_CC_INITIALIZER(0x0162, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_ECDH_KeyGen) + TPMA_CC_INITIALIZER(0x0163, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_EncryptDecrypt) + TPMA_CC_INITIALIZER(0x0164, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_FlushContext) + TPMA_CC_INITIALIZER(0x0165, 0, 0, 0, 0, 0, 0, 0, 0), +# endif +# if(PAD_LIST) + TPMA_CC_INITIALIZER(0x0166, 0, 0, 0, 0, 0, 0, 0, 0), +# endif +# if(PAD_LIST || CC_LoadExternal) + TPMA_CC_INITIALIZER(0x0167, 0, 0, 0, 0, 0, 1, 0, 0), +# endif +# if(PAD_LIST || CC_MakeCredential) + TPMA_CC_INITIALIZER(0x0168, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_NV_ReadPublic) + TPMA_CC_INITIALIZER(0x0169, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_PolicyAuthorize) + TPMA_CC_INITIALIZER(0x016A, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_PolicyAuthValue) + TPMA_CC_INITIALIZER(0x016B, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_PolicyCommandCode) + TPMA_CC_INITIALIZER(0x016C, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_PolicyCounterTimer) + TPMA_CC_INITIALIZER(0x016D, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_PolicyCpHash) + TPMA_CC_INITIALIZER(0x016E, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_PolicyLocality) + TPMA_CC_INITIALIZER(0x016F, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_PolicyNameHash) + TPMA_CC_INITIALIZER(0x0170, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_PolicyOR) + TPMA_CC_INITIALIZER(0x0171, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_PolicyTicket) + TPMA_CC_INITIALIZER(0x0172, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_ReadPublic) + TPMA_CC_INITIALIZER(0x0173, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_RSA_Encrypt) + TPMA_CC_INITIALIZER(0x0174, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST) + TPMA_CC_INITIALIZER(0x0175, 0, 0, 0, 0, 0, 0, 0, 0), +# endif +# if(PAD_LIST || CC_StartAuthSession) + TPMA_CC_INITIALIZER(0x0176, 0, 0, 0, 0, 2, 1, 0, 0), +# endif +# if(PAD_LIST || CC_VerifySignature) + TPMA_CC_INITIALIZER(0x0177, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_ECC_Parameters) + TPMA_CC_INITIALIZER(0x0178, 0, 0, 0, 0, 0, 0, 0, 0), +# endif +# if(PAD_LIST || CC_FirmwareRead) + TPMA_CC_INITIALIZER(0x0179, 0, 0, 0, 0, 0, 0, 0, 0), +# endif +# if(PAD_LIST || CC_GetCapability) + TPMA_CC_INITIALIZER(0x017A, 0, 0, 0, 0, 0, 0, 0, 0), +# endif +# if(PAD_LIST || CC_GetRandom) + TPMA_CC_INITIALIZER(0x017B, 0, 0, 0, 0, 0, 0, 0, 0), +# endif +# if(PAD_LIST || CC_GetTestResult) + TPMA_CC_INITIALIZER(0x017C, 0, 0, 0, 0, 0, 0, 0, 0), +# endif +# if(PAD_LIST || CC_Hash) + TPMA_CC_INITIALIZER(0x017D, 0, 0, 0, 0, 0, 0, 0, 0), +# endif +# if(PAD_LIST || CC_PCR_Read) + TPMA_CC_INITIALIZER(0x017E, 0, 0, 0, 0, 0, 0, 0, 0), +# endif +# if(PAD_LIST || CC_PolicyPCR) + TPMA_CC_INITIALIZER(0x017F, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_PolicyRestart) + TPMA_CC_INITIALIZER(0x0180, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_ReadClock) + TPMA_CC_INITIALIZER(0x0181, 0, 0, 0, 0, 0, 0, 0, 0), +# endif +# if(PAD_LIST || CC_PCR_Extend) + TPMA_CC_INITIALIZER(0x0182, 0, 1, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_PCR_SetAuthValue) + TPMA_CC_INITIALIZER(0x0183, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_NV_Certify) + TPMA_CC_INITIALIZER(0x0184, 0, 0, 0, 0, 3, 0, 0, 0), +# endif +# if(PAD_LIST || CC_EventSequenceComplete) + TPMA_CC_INITIALIZER(0x0185, 0, 1, 0, 1, 2, 0, 0, 0), +# endif +# if(PAD_LIST || CC_HashSequenceStart) + TPMA_CC_INITIALIZER(0x0186, 0, 0, 0, 0, 0, 1, 0, 0), +# endif +# if(PAD_LIST || CC_PolicyPhysicalPresence) + TPMA_CC_INITIALIZER(0x0187, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_PolicyDuplicationSelect) + TPMA_CC_INITIALIZER(0x0188, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_PolicyGetDigest) + TPMA_CC_INITIALIZER(0x0189, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_TestParms) + TPMA_CC_INITIALIZER(0x018A, 0, 0, 0, 0, 0, 0, 0, 0), +# endif +# if(PAD_LIST || CC_Commit) + TPMA_CC_INITIALIZER(0x018B, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_PolicyPassword) + TPMA_CC_INITIALIZER(0x018C, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_ZGen_2Phase) + TPMA_CC_INITIALIZER(0x018D, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_EC_Ephemeral) + TPMA_CC_INITIALIZER(0x018E, 0, 0, 0, 0, 0, 0, 0, 0), +# endif +# if(PAD_LIST || CC_PolicyNvWritten) + TPMA_CC_INITIALIZER(0x018F, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_PolicyTemplate) + TPMA_CC_INITIALIZER(0x0190, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_CreateLoaded) + TPMA_CC_INITIALIZER(0x0191, 0, 0, 0, 0, 1, 1, 0, 0), +# endif +# if(PAD_LIST || CC_PolicyAuthorizeNV) + TPMA_CC_INITIALIZER(0x0192, 0, 0, 0, 0, 3, 0, 0, 0), +# endif +# if(PAD_LIST || CC_EncryptDecrypt2) + TPMA_CC_INITIALIZER(0x0193, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_AC_GetCapability) + TPMA_CC_INITIALIZER(0x0194, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_AC_Send) + TPMA_CC_INITIALIZER(0x0195, 0, 0, 0, 0, 3, 0, 0, 0), +# endif +# if(PAD_LIST || CC_Policy_AC_SendSelect) + TPMA_CC_INITIALIZER(0x0196, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_CertifyX509) + TPMA_CC_INITIALIZER(0x0197, 0, 0, 0, 0, 2, 0, 0, 0), +# endif +# if(PAD_LIST || CC_ACT_SetTimeout) + TPMA_CC_INITIALIZER(0x0198, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_ECC_Encrypt) + TPMA_CC_INITIALIZER(0x0199, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_ECC_Decrypt) + TPMA_CC_INITIALIZER(0x019A, 0, 0, 0, 0, 1, 0, 0, 0), +# endif +# if(PAD_LIST || CC_Vendor_TCG_Test) + TPMA_CC_INITIALIZER(0x0000, 0, 0, 0, 0, 0, 0, 1, 0), +# endif + TPMA_ZERO_INITIALIZER()}; + +// This is the command code attribute structure. +const COMMAND_ATTRIBUTES s_commandAttributes[] = { +# if(PAD_LIST || CC_NV_UndefineSpaceSpecial) + (COMMAND_ATTRIBUTES)(CC_NV_UndefineSpaceSpecial * // 0x011F + (IS_IMPLEMENTED + HANDLE_1_ADMIN + HANDLE_2_USER + + PP_COMMAND)), +# endif +# if(PAD_LIST || CC_EvictControl) + (COMMAND_ATTRIBUTES)(CC_EvictControl* // 0x0120 + (IS_IMPLEMENTED + HANDLE_1_USER + PP_COMMAND)), +# endif +# if(PAD_LIST || CC_HierarchyControl) + (COMMAND_ATTRIBUTES)(CC_HierarchyControl* // 0x0121 + (IS_IMPLEMENTED + HANDLE_1_USER + PP_COMMAND)), +# endif +# if(PAD_LIST || CC_NV_UndefineSpace) + (COMMAND_ATTRIBUTES)(CC_NV_UndefineSpace* // 0x0122 + (IS_IMPLEMENTED + HANDLE_1_USER + PP_COMMAND)), +# endif +# if(PAD_LIST) + (COMMAND_ATTRIBUTES)(0), // 0x0123 +# endif +# if(PAD_LIST || CC_ChangeEPS) + (COMMAND_ATTRIBUTES)(CC_ChangeEPS* // 0x0124 + (IS_IMPLEMENTED + HANDLE_1_USER + PP_COMMAND)), +# endif +# if(PAD_LIST || CC_ChangePPS) + (COMMAND_ATTRIBUTES)(CC_ChangePPS* // 0x0125 + (IS_IMPLEMENTED + HANDLE_1_USER + PP_COMMAND)), +# endif +# if(PAD_LIST || CC_Clear) + (COMMAND_ATTRIBUTES)(CC_Clear* // 0x0126 + (IS_IMPLEMENTED + HANDLE_1_USER + PP_COMMAND)), +# endif +# if(PAD_LIST || CC_ClearControl) + (COMMAND_ATTRIBUTES)(CC_ClearControl* // 0x0127 + (IS_IMPLEMENTED + HANDLE_1_USER + PP_COMMAND)), +# endif +# if(PAD_LIST || CC_ClockSet) + (COMMAND_ATTRIBUTES)(CC_ClockSet* // 0x0128 + (IS_IMPLEMENTED + HANDLE_1_USER + PP_COMMAND)), +# endif +# if(PAD_LIST || CC_HierarchyChangeAuth) + (COMMAND_ATTRIBUTES)(CC_HierarchyChangeAuth* // 0x0129 + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_USER + PP_COMMAND)), +# endif +# if(PAD_LIST || CC_NV_DefineSpace) + (COMMAND_ATTRIBUTES)(CC_NV_DefineSpace* // 0x012A + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_USER + PP_COMMAND)), +# endif +# if(PAD_LIST || CC_PCR_Allocate) + (COMMAND_ATTRIBUTES)(CC_PCR_Allocate* // 0x012B + (IS_IMPLEMENTED + HANDLE_1_USER + PP_COMMAND)), +# endif +# if(PAD_LIST || CC_PCR_SetAuthPolicy) + (COMMAND_ATTRIBUTES)(CC_PCR_SetAuthPolicy* // 0x012C + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_USER + PP_COMMAND)), +# endif +# if(PAD_LIST || CC_PP_Commands) + (COMMAND_ATTRIBUTES)(CC_PP_Commands* // 0x012D + (IS_IMPLEMENTED + HANDLE_1_USER + PP_REQUIRED)), +# endif +# if(PAD_LIST || CC_SetPrimaryPolicy) + (COMMAND_ATTRIBUTES)(CC_SetPrimaryPolicy* // 0x012E + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_USER + PP_COMMAND)), +# endif +# if(PAD_LIST || CC_FieldUpgradeStart) + (COMMAND_ATTRIBUTES)(CC_FieldUpgradeStart* // 0x012F + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_ADMIN + PP_COMMAND)), +# endif +# if(PAD_LIST || CC_ClockRateAdjust) + (COMMAND_ATTRIBUTES)(CC_ClockRateAdjust* // 0x0130 + (IS_IMPLEMENTED + HANDLE_1_USER + PP_COMMAND)), +# endif +# if(PAD_LIST || CC_CreatePrimary) + (COMMAND_ATTRIBUTES)(CC_CreatePrimary* // 0x0131 + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_USER + PP_COMMAND + + ENCRYPT_2 + R_HANDLE)), +# endif +# if(PAD_LIST || CC_NV_GlobalWriteLock) + (COMMAND_ATTRIBUTES)(CC_NV_GlobalWriteLock* // 0x0132 + (IS_IMPLEMENTED + HANDLE_1_USER + PP_COMMAND)), +# endif +# if(PAD_LIST || CC_GetCommandAuditDigest) + (COMMAND_ATTRIBUTES)(CC_GetCommandAuditDigest* // 0x0133 + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_USER + HANDLE_2_USER + + ENCRYPT_2)), +# endif +# if(PAD_LIST || CC_NV_Increment) + (COMMAND_ATTRIBUTES)(CC_NV_Increment* // 0x0134 + (IS_IMPLEMENTED + HANDLE_1_USER)), +# endif +# if(PAD_LIST || CC_NV_SetBits) + (COMMAND_ATTRIBUTES)(CC_NV_SetBits* // 0x0135 + (IS_IMPLEMENTED + HANDLE_1_USER)), +# endif +# if(PAD_LIST || CC_NV_Extend) + (COMMAND_ATTRIBUTES)(CC_NV_Extend* // 0x0136 + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_USER)), +# endif +# if(PAD_LIST || CC_NV_Write) + (COMMAND_ATTRIBUTES)(CC_NV_Write* // 0x0137 + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_USER)), +# endif +# if(PAD_LIST || CC_NV_WriteLock) + (COMMAND_ATTRIBUTES)(CC_NV_WriteLock* // 0x0138 + (IS_IMPLEMENTED + HANDLE_1_USER)), +# endif +# if(PAD_LIST || CC_DictionaryAttackLockReset) + (COMMAND_ATTRIBUTES)(CC_DictionaryAttackLockReset* // 0x0139 + (IS_IMPLEMENTED + HANDLE_1_USER)), +# endif +# if(PAD_LIST || CC_DictionaryAttackParameters) + (COMMAND_ATTRIBUTES)(CC_DictionaryAttackParameters* // 0x013A + (IS_IMPLEMENTED + HANDLE_1_USER)), +# endif +# if(PAD_LIST || CC_NV_ChangeAuth) + (COMMAND_ATTRIBUTES)(CC_NV_ChangeAuth* // 0x013B + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_ADMIN)), +# endif +# if(PAD_LIST || CC_PCR_Event) + (COMMAND_ATTRIBUTES)(CC_PCR_Event* // 0x013C + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_USER)), +# endif +# if(PAD_LIST || CC_PCR_Reset) + (COMMAND_ATTRIBUTES)(CC_PCR_Reset* // 0x013D + (IS_IMPLEMENTED + HANDLE_1_USER)), +# endif +# if(PAD_LIST || CC_SequenceComplete) + (COMMAND_ATTRIBUTES)(CC_SequenceComplete* // 0x013E + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_USER + ENCRYPT_2)), +# endif +# if(PAD_LIST || CC_SetAlgorithmSet) + (COMMAND_ATTRIBUTES)(CC_SetAlgorithmSet* // 0x013F + (IS_IMPLEMENTED + HANDLE_1_USER)), +# endif +# if(PAD_LIST || CC_SetCommandCodeAuditStatus) + (COMMAND_ATTRIBUTES)(CC_SetCommandCodeAuditStatus* // 0x0140 + (IS_IMPLEMENTED + HANDLE_1_USER + PP_COMMAND)), +# endif +# if(PAD_LIST || CC_FieldUpgradeData) + (COMMAND_ATTRIBUTES)(CC_FieldUpgradeData* // 0x0141 + (IS_IMPLEMENTED + DECRYPT_2)), +# endif +# if(PAD_LIST || CC_IncrementalSelfTest) + (COMMAND_ATTRIBUTES)(CC_IncrementalSelfTest* // 0x0142 + (IS_IMPLEMENTED)), +# endif +# if(PAD_LIST || CC_SelfTest) + (COMMAND_ATTRIBUTES)(CC_SelfTest* // 0x0143 + (IS_IMPLEMENTED)), +# endif +# if(PAD_LIST || CC_Startup) + (COMMAND_ATTRIBUTES)(CC_Startup* // 0x0144 + (IS_IMPLEMENTED + NO_SESSIONS)), +# endif +# if(PAD_LIST || CC_Shutdown) + (COMMAND_ATTRIBUTES)(CC_Shutdown* // 0x0145 + (IS_IMPLEMENTED)), +# endif +# if(PAD_LIST || CC_StirRandom) + (COMMAND_ATTRIBUTES)(CC_StirRandom* // 0x0146 + (IS_IMPLEMENTED + DECRYPT_2)), +# endif +# if(PAD_LIST || CC_ActivateCredential) + (COMMAND_ATTRIBUTES)(CC_ActivateCredential* // 0x0147 + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_ADMIN + HANDLE_2_USER + + ENCRYPT_2)), +# endif +# if(PAD_LIST || CC_Certify) + (COMMAND_ATTRIBUTES)(CC_Certify* // 0x0148 + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_ADMIN + HANDLE_2_USER + + ENCRYPT_2)), +# endif +# if(PAD_LIST || CC_PolicyNV) + (COMMAND_ATTRIBUTES)(CC_PolicyNV* // 0x0149 + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_USER + ALLOW_TRIAL)), +# endif +# if(PAD_LIST || CC_CertifyCreation) + (COMMAND_ATTRIBUTES)(CC_CertifyCreation* // 0x014A + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_USER + ENCRYPT_2)), +# endif +# if(PAD_LIST || CC_Duplicate) + (COMMAND_ATTRIBUTES)(CC_Duplicate* // 0x014B + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_DUP + ENCRYPT_2)), +# endif +# if(PAD_LIST || CC_GetTime) + (COMMAND_ATTRIBUTES)(CC_GetTime* // 0x014C + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_USER + HANDLE_2_USER + + ENCRYPT_2)), +# endif +# if(PAD_LIST || CC_GetSessionAuditDigest) + (COMMAND_ATTRIBUTES)(CC_GetSessionAuditDigest* // 0x014D + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_USER + HANDLE_2_USER + + ENCRYPT_2)), +# endif +# if(PAD_LIST || CC_NV_Read) + (COMMAND_ATTRIBUTES)(CC_NV_Read* // 0x014E + (IS_IMPLEMENTED + HANDLE_1_USER + ENCRYPT_2)), +# endif +# if(PAD_LIST || CC_NV_ReadLock) + (COMMAND_ATTRIBUTES)(CC_NV_ReadLock* // 0x014F + (IS_IMPLEMENTED + HANDLE_1_USER)), +# endif +# if(PAD_LIST || CC_ObjectChangeAuth) + (COMMAND_ATTRIBUTES)(CC_ObjectChangeAuth* // 0x0150 + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_ADMIN + ENCRYPT_2)), +# endif +# if(PAD_LIST || CC_PolicySecret) + (COMMAND_ATTRIBUTES)(CC_PolicySecret* // 0x0151 + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_USER + ALLOW_TRIAL + + ENCRYPT_2)), +# endif +# if(PAD_LIST || CC_Rewrap) + (COMMAND_ATTRIBUTES)(CC_Rewrap* // 0x0152 + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_USER + ENCRYPT_2)), +# endif +# if(PAD_LIST || CC_Create) + (COMMAND_ATTRIBUTES)(CC_Create* // 0x0153 + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_USER + ENCRYPT_2)), +# endif +# if(PAD_LIST || CC_ECDH_ZGen) + (COMMAND_ATTRIBUTES)(CC_ECDH_ZGen* // 0x0154 + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_USER + ENCRYPT_2)), +# endif +# if(PAD_LIST || (CC_HMAC || CC_MAC)) + (COMMAND_ATTRIBUTES)((CC_HMAC || CC_MAC) * // 0x0155 + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_USER + ENCRYPT_2)), +# endif +# if(PAD_LIST || CC_Import) + (COMMAND_ATTRIBUTES)(CC_Import* // 0x0156 + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_USER + ENCRYPT_2)), +# endif +# if(PAD_LIST || CC_Load) + (COMMAND_ATTRIBUTES)(CC_Load* // 0x0157 + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_USER + ENCRYPT_2 + + R_HANDLE)), +# endif +# if(PAD_LIST || CC_Quote) + (COMMAND_ATTRIBUTES)(CC_Quote* // 0x0158 + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_USER + ENCRYPT_2)), +# endif +# if(PAD_LIST || CC_RSA_Decrypt) + (COMMAND_ATTRIBUTES)(CC_RSA_Decrypt* // 0x0159 + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_USER + ENCRYPT_2)), +# endif +# if(PAD_LIST) + (COMMAND_ATTRIBUTES)(0), // 0x015A +# endif +# if(PAD_LIST || (CC_HMAC_Start || CC_MAC_Start)) + (COMMAND_ATTRIBUTES)((CC_HMAC_Start || CC_MAC_Start) * // 0x015B + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_USER + R_HANDLE)), +# endif +# if(PAD_LIST || CC_SequenceUpdate) + (COMMAND_ATTRIBUTES)(CC_SequenceUpdate* // 0x015C + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_USER)), +# endif +# if(PAD_LIST || CC_Sign) + (COMMAND_ATTRIBUTES)(CC_Sign* // 0x015D + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_USER)), +# endif +# if(PAD_LIST || CC_Unseal) + (COMMAND_ATTRIBUTES)(CC_Unseal* // 0x015E + (IS_IMPLEMENTED + HANDLE_1_USER + ENCRYPT_2)), +# endif +# if(PAD_LIST) + (COMMAND_ATTRIBUTES)(0), // 0x015F +# endif +# if(PAD_LIST || CC_PolicySigned) + (COMMAND_ATTRIBUTES)(CC_PolicySigned* // 0x0160 + (IS_IMPLEMENTED + DECRYPT_2 + ALLOW_TRIAL + ENCRYPT_2)), +# endif +# if(PAD_LIST || CC_ContextLoad) + (COMMAND_ATTRIBUTES)(CC_ContextLoad* // 0x0161 + (IS_IMPLEMENTED + NO_SESSIONS + R_HANDLE)), +# endif +# if(PAD_LIST || CC_ContextSave) + (COMMAND_ATTRIBUTES)(CC_ContextSave* // 0x0162 + (IS_IMPLEMENTED + NO_SESSIONS)), +# endif +# if(PAD_LIST || CC_ECDH_KeyGen) + (COMMAND_ATTRIBUTES)(CC_ECDH_KeyGen* // 0x0163 + (IS_IMPLEMENTED + ENCRYPT_2)), +# endif +# if(PAD_LIST || CC_EncryptDecrypt) + (COMMAND_ATTRIBUTES)(CC_EncryptDecrypt* // 0x0164 + (IS_IMPLEMENTED + HANDLE_1_USER + ENCRYPT_2)), +# endif +# if(PAD_LIST || CC_FlushContext) + (COMMAND_ATTRIBUTES)(CC_FlushContext* // 0x0165 + (IS_IMPLEMENTED + NO_SESSIONS)), +# endif +# if(PAD_LIST) + (COMMAND_ATTRIBUTES)(0), // 0x0166 +# endif +# if(PAD_LIST || CC_LoadExternal) + (COMMAND_ATTRIBUTES)(CC_LoadExternal* // 0x0167 + (IS_IMPLEMENTED + DECRYPT_2 + ENCRYPT_2 + R_HANDLE)), +# endif +# if(PAD_LIST || CC_MakeCredential) + (COMMAND_ATTRIBUTES)(CC_MakeCredential* // 0x0168 + (IS_IMPLEMENTED + DECRYPT_2 + ENCRYPT_2)), +# endif +# if(PAD_LIST || CC_NV_ReadPublic) + (COMMAND_ATTRIBUTES)(CC_NV_ReadPublic* // 0x0169 + (IS_IMPLEMENTED + ENCRYPT_2)), +# endif +# if(PAD_LIST || CC_PolicyAuthorize) + (COMMAND_ATTRIBUTES)(CC_PolicyAuthorize* // 0x016A + (IS_IMPLEMENTED + DECRYPT_2 + ALLOW_TRIAL)), +# endif +# if(PAD_LIST || CC_PolicyAuthValue) + (COMMAND_ATTRIBUTES)(CC_PolicyAuthValue* // 0x016B + (IS_IMPLEMENTED + ALLOW_TRIAL)), +# endif +# if(PAD_LIST || CC_PolicyCommandCode) + (COMMAND_ATTRIBUTES)(CC_PolicyCommandCode* // 0x016C + (IS_IMPLEMENTED + ALLOW_TRIAL)), +# endif +# if(PAD_LIST || CC_PolicyCounterTimer) + (COMMAND_ATTRIBUTES)(CC_PolicyCounterTimer* // 0x016D + (IS_IMPLEMENTED + DECRYPT_2 + ALLOW_TRIAL)), +# endif +# if(PAD_LIST || CC_PolicyCpHash) + (COMMAND_ATTRIBUTES)(CC_PolicyCpHash* // 0x016E + (IS_IMPLEMENTED + DECRYPT_2 + ALLOW_TRIAL)), +# endif +# if(PAD_LIST || CC_PolicyLocality) + (COMMAND_ATTRIBUTES)(CC_PolicyLocality* // 0x016F + (IS_IMPLEMENTED + ALLOW_TRIAL)), +# endif +# if(PAD_LIST || CC_PolicyNameHash) + (COMMAND_ATTRIBUTES)(CC_PolicyNameHash* // 0x0170 + (IS_IMPLEMENTED + DECRYPT_2 + ALLOW_TRIAL)), +# endif +# if(PAD_LIST || CC_PolicyOR) + (COMMAND_ATTRIBUTES)(CC_PolicyOR* // 0x0171 + (IS_IMPLEMENTED + ALLOW_TRIAL)), +# endif +# if(PAD_LIST || CC_PolicyTicket) + (COMMAND_ATTRIBUTES)(CC_PolicyTicket* // 0x0172 + (IS_IMPLEMENTED + DECRYPT_2 + ALLOW_TRIAL)), +# endif +# if(PAD_LIST || CC_ReadPublic) + (COMMAND_ATTRIBUTES)(CC_ReadPublic* // 0x0173 + (IS_IMPLEMENTED + ENCRYPT_2)), +# endif +# if(PAD_LIST || CC_RSA_Encrypt) + (COMMAND_ATTRIBUTES)(CC_RSA_Encrypt* // 0x0174 + (IS_IMPLEMENTED + DECRYPT_2 + ENCRYPT_2)), +# endif +# if(PAD_LIST) + (COMMAND_ATTRIBUTES)(0), // 0x0175 +# endif +# if(PAD_LIST || CC_StartAuthSession) + (COMMAND_ATTRIBUTES)(CC_StartAuthSession* // 0x0176 + (IS_IMPLEMENTED + DECRYPT_2 + ENCRYPT_2 + R_HANDLE)), +# endif +# if(PAD_LIST || CC_VerifySignature) + (COMMAND_ATTRIBUTES)(CC_VerifySignature* // 0x0177 + (IS_IMPLEMENTED + DECRYPT_2)), +# endif +# if(PAD_LIST || CC_ECC_Parameters) + (COMMAND_ATTRIBUTES)(CC_ECC_Parameters* // 0x0178 + (IS_IMPLEMENTED)), +# endif +# if(PAD_LIST || CC_FirmwareRead) + (COMMAND_ATTRIBUTES)(CC_FirmwareRead* // 0x0179 + (IS_IMPLEMENTED + ENCRYPT_2)), +# endif +# if(PAD_LIST || CC_GetCapability) + (COMMAND_ATTRIBUTES)(CC_GetCapability* // 0x017A + (IS_IMPLEMENTED)), +# endif +# if(PAD_LIST || CC_GetRandom) + (COMMAND_ATTRIBUTES)(CC_GetRandom* // 0x017B + (IS_IMPLEMENTED + ENCRYPT_2)), +# endif +# if(PAD_LIST || CC_GetTestResult) + (COMMAND_ATTRIBUTES)(CC_GetTestResult* // 0x017C + (IS_IMPLEMENTED + ENCRYPT_2)), +# endif +# if(PAD_LIST || CC_Hash) + (COMMAND_ATTRIBUTES)(CC_Hash* // 0x017D + (IS_IMPLEMENTED + DECRYPT_2 + ENCRYPT_2)), +# endif +# if(PAD_LIST || CC_PCR_Read) + (COMMAND_ATTRIBUTES)(CC_PCR_Read* // 0x017E + (IS_IMPLEMENTED)), +# endif +# if(PAD_LIST || CC_PolicyPCR) + (COMMAND_ATTRIBUTES)(CC_PolicyPCR* // 0x017F + (IS_IMPLEMENTED + DECRYPT_2 + ALLOW_TRIAL)), +# endif +# if(PAD_LIST || CC_PolicyRestart) + (COMMAND_ATTRIBUTES)(CC_PolicyRestart* // 0x0180 + (IS_IMPLEMENTED + ALLOW_TRIAL)), +# endif +# if(PAD_LIST || CC_ReadClock) + (COMMAND_ATTRIBUTES)(CC_ReadClock* // 0x0181 + (IS_IMPLEMENTED)), +# endif +# if(PAD_LIST || CC_PCR_Extend) + (COMMAND_ATTRIBUTES)(CC_PCR_Extend* // 0x0182 + (IS_IMPLEMENTED + HANDLE_1_USER)), +# endif +# if(PAD_LIST || CC_PCR_SetAuthValue) + (COMMAND_ATTRIBUTES)(CC_PCR_SetAuthValue* // 0x0183 + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_USER)), +# endif +# if(PAD_LIST || CC_NV_Certify) + (COMMAND_ATTRIBUTES)(CC_NV_Certify* // 0x0184 + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_USER + HANDLE_2_USER + + ENCRYPT_2)), +# endif +# if(PAD_LIST || CC_EventSequenceComplete) + (COMMAND_ATTRIBUTES)(CC_EventSequenceComplete* // 0x0185 + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_USER + + HANDLE_2_USER)), +# endif +# if(PAD_LIST || CC_HashSequenceStart) + (COMMAND_ATTRIBUTES)(CC_HashSequenceStart* // 0x0186 + (IS_IMPLEMENTED + DECRYPT_2 + R_HANDLE)), +# endif +# if(PAD_LIST || CC_PolicyPhysicalPresence) + (COMMAND_ATTRIBUTES)(CC_PolicyPhysicalPresence* // 0x0187 + (IS_IMPLEMENTED + ALLOW_TRIAL)), +# endif +# if(PAD_LIST || CC_PolicyDuplicationSelect) + (COMMAND_ATTRIBUTES)(CC_PolicyDuplicationSelect* // 0x0188 + (IS_IMPLEMENTED + DECRYPT_2 + ALLOW_TRIAL)), +# endif +# if(PAD_LIST || CC_PolicyGetDigest) + (COMMAND_ATTRIBUTES)(CC_PolicyGetDigest* // 0x0189 + (IS_IMPLEMENTED + ALLOW_TRIAL + ENCRYPT_2)), +# endif +# if(PAD_LIST || CC_TestParms) + (COMMAND_ATTRIBUTES)(CC_TestParms* // 0x018A + (IS_IMPLEMENTED)), +# endif +# if(PAD_LIST || CC_Commit) + (COMMAND_ATTRIBUTES)(CC_Commit* // 0x018B + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_USER + ENCRYPT_2)), +# endif +# if(PAD_LIST || CC_PolicyPassword) + (COMMAND_ATTRIBUTES)(CC_PolicyPassword* // 0x018C + (IS_IMPLEMENTED + ALLOW_TRIAL)), +# endif +# if(PAD_LIST || CC_ZGen_2Phase) + (COMMAND_ATTRIBUTES)(CC_ZGen_2Phase* // 0x018D + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_USER + ENCRYPT_2)), +# endif +# if(PAD_LIST || CC_EC_Ephemeral) + (COMMAND_ATTRIBUTES)(CC_EC_Ephemeral* // 0x018E + (IS_IMPLEMENTED + ENCRYPT_2)), +# endif +# if(PAD_LIST || CC_PolicyNvWritten) + (COMMAND_ATTRIBUTES)(CC_PolicyNvWritten* // 0x018F + (IS_IMPLEMENTED + ALLOW_TRIAL)), +# endif +# if(PAD_LIST || CC_PolicyTemplate) + (COMMAND_ATTRIBUTES)(CC_PolicyTemplate* // 0x0190 + (IS_IMPLEMENTED + DECRYPT_2 + ALLOW_TRIAL)), +# endif +# if(PAD_LIST || CC_CreateLoaded) + (COMMAND_ATTRIBUTES)(CC_CreateLoaded* // 0x0191 + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_USER + PP_COMMAND + + ENCRYPT_2 + R_HANDLE)), +# endif +# if(PAD_LIST || CC_PolicyAuthorizeNV) + (COMMAND_ATTRIBUTES)(CC_PolicyAuthorizeNV* // 0x0192 + (IS_IMPLEMENTED + HANDLE_1_USER + ALLOW_TRIAL)), +# endif +# if(PAD_LIST || CC_EncryptDecrypt2) + (COMMAND_ATTRIBUTES)(CC_EncryptDecrypt2* // 0x0193 + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_USER + ENCRYPT_2)), +# endif +# if(PAD_LIST || CC_AC_GetCapability) + (COMMAND_ATTRIBUTES)(CC_AC_GetCapability* // 0x0194 + (IS_IMPLEMENTED)), +# endif +# if(PAD_LIST || CC_AC_Send) + (COMMAND_ATTRIBUTES)(CC_AC_Send* // 0x0195 + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_DUP + HANDLE_2_USER)), +# endif +# if(PAD_LIST || CC_Policy_AC_SendSelect) + (COMMAND_ATTRIBUTES)(CC_Policy_AC_SendSelect* // 0x0196 + (IS_IMPLEMENTED + DECRYPT_2 + ALLOW_TRIAL)), +# endif +# if(PAD_LIST || CC_CertifyX509) + (COMMAND_ATTRIBUTES)(CC_CertifyX509* // 0x0197 + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_ADMIN + HANDLE_2_USER + + ENCRYPT_2)), +# endif +# if(PAD_LIST || CC_ACT_SetTimeout) + (COMMAND_ATTRIBUTES)(CC_ACT_SetTimeout* // 0x0198 + (IS_IMPLEMENTED + HANDLE_1_USER)), +# endif +# if(PAD_LIST || CC_ECC_Encrypt) + (COMMAND_ATTRIBUTES)(CC_ECC_Encrypt* // 0x0199 + (IS_IMPLEMENTED + DECRYPT_2 + ENCRYPT_2)), +# endif +# if(PAD_LIST || CC_ECC_Decrypt) + (COMMAND_ATTRIBUTES)(CC_ECC_Decrypt* // 0x019A + (IS_IMPLEMENTED + DECRYPT_2 + HANDLE_1_USER + ENCRYPT_2)), +# endif +# if(PAD_LIST || CC_Vendor_TCG_Test) + (COMMAND_ATTRIBUTES)(CC_Vendor_TCG_Test* // 0x0000 + (IS_IMPLEMENTED + DECRYPT_2 + ENCRYPT_2)), +# endif + 0}; + +#endif // _COMMAND_CODE_ATTRIBUTES_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CommandAttributes.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CommandAttributes.h new file mode 100644 index 0000000..40c2dbd --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CommandAttributes.h @@ -0,0 +1,67 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Aug 30, 2019 Time: 02:11:52PM + */ + +// The attributes defined in this file are produced by the parser that +// creates the structure definitions from Part 3. The attributes are defined +// in that parser and should track the attributes being tested in +// CommandCodeAttributes.c. Generally, when an attribute is added to this list, +// new code will be needed in CommandCodeAttributes.c to test it. + +#ifndef COMMAND_ATTRIBUTES_H +#define COMMAND_ATTRIBUTES_H + +typedef UINT16 COMMAND_ATTRIBUTES; +#define NOT_IMPLEMENTED (COMMAND_ATTRIBUTES)(0) +#define ENCRYPT_2 ((COMMAND_ATTRIBUTES)1 << 0) +#define ENCRYPT_4 ((COMMAND_ATTRIBUTES)1 << 1) +#define DECRYPT_2 ((COMMAND_ATTRIBUTES)1 << 2) +#define DECRYPT_4 ((COMMAND_ATTRIBUTES)1 << 3) +#define HANDLE_1_USER ((COMMAND_ATTRIBUTES)1 << 4) +#define HANDLE_1_ADMIN ((COMMAND_ATTRIBUTES)1 << 5) +#define HANDLE_1_DUP ((COMMAND_ATTRIBUTES)1 << 6) +#define HANDLE_2_USER ((COMMAND_ATTRIBUTES)1 << 7) +#define PP_COMMAND ((COMMAND_ATTRIBUTES)1 << 8) +#define IS_IMPLEMENTED ((COMMAND_ATTRIBUTES)1 << 9) +#define NO_SESSIONS ((COMMAND_ATTRIBUTES)1 << 10) +#define NV_COMMAND ((COMMAND_ATTRIBUTES)1 << 11) +#define PP_REQUIRED ((COMMAND_ATTRIBUTES)1 << 12) +#define R_HANDLE ((COMMAND_ATTRIBUTES)1 << 13) +#define ALLOW_TRIAL ((COMMAND_ATTRIBUTES)1 << 14) + +#endif // COMMAND_ATTRIBUTES_H diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CommandDispatchData.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CommandDispatchData.h new file mode 100644 index 0000000..f9b95c3 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CommandDispatchData.h @@ -0,0 +1,5090 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 6, 2020 Time: 01:50:09PM + */ + +// This file should only be included by CommandCodeAttibutes.c +#ifdef _COMMAND_TABLE_DISPATCH_ + +// Define the stop value +# define END_OF_LIST 0xff +# define ADD_FLAG 0x80 + +// These macros provide some variability in how the data is encoded. They also make +// the lines a little shorter. ;-) +# if TABLE_DRIVEN_MARSHAL +# define UNMARSHAL_DISPATCH(name) (marshalIndex_t) name##_MARSHAL_REF +# define MARSHAL_DISPATCH(name) (marshalIndex_t) name##_MARSHAL_REF +# define _UNMARSHAL_T_ marshalIndex_t +# define _MARSHAL_T_ marshalIndex_t +# else +# define UNMARSHAL_DISPATCH(name) (UNMARSHAL_t) name##_Unmarshal +# define MARSHAL_DISPATCH(name) (MARSHAL_t) name##_Marshal +# define _UNMARSHAL_T_ UNMARSHAL_t +# define _MARSHAL_T_ MARSHAL_t +# endif + +// The unmarshalArray contains the dispatch functions for the unmarshaling code. +// The defines in this array are used to make it easier to cross reference the +// unmarshaling values in the types array of each command + +const _UNMARSHAL_T_ unmarshalArray[] = { +# define TPMI_DH_CONTEXT_H_UNMARSHAL 0 + UNMARSHAL_DISPATCH(TPMI_DH_CONTEXT), +# define TPMI_RH_AC_H_UNMARSHAL (TPMI_DH_CONTEXT_H_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_RH_AC), +# define TPMI_RH_ACT_H_UNMARSHAL (TPMI_RH_AC_H_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_RH_ACT), +# define TPMI_RH_CLEAR_H_UNMARSHAL (TPMI_RH_ACT_H_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_RH_CLEAR), +# define TPMI_RH_HIERARCHY_AUTH_H_UNMARSHAL (TPMI_RH_CLEAR_H_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_RH_HIERARCHY_AUTH), +# define TPMI_RH_HIERARCHY_POLICY_H_UNMARSHAL \ + (TPMI_RH_HIERARCHY_AUTH_H_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_RH_HIERARCHY_POLICY), +# define TPMI_RH_LOCKOUT_H_UNMARSHAL (TPMI_RH_HIERARCHY_POLICY_H_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_RH_LOCKOUT), +# define TPMI_RH_NV_AUTH_H_UNMARSHAL (TPMI_RH_LOCKOUT_H_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_RH_NV_AUTH), +# define TPMI_RH_NV_INDEX_H_UNMARSHAL (TPMI_RH_NV_AUTH_H_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_RH_NV_INDEX), +# define TPMI_RH_PLATFORM_H_UNMARSHAL (TPMI_RH_NV_INDEX_H_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_RH_PLATFORM), +# define TPMI_RH_PROVISION_H_UNMARSHAL (TPMI_RH_PLATFORM_H_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_RH_PROVISION), +# define TPMI_SH_HMAC_H_UNMARSHAL (TPMI_RH_PROVISION_H_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_SH_HMAC), +# define TPMI_SH_POLICY_H_UNMARSHAL (TPMI_SH_HMAC_H_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_SH_POLICY), +// HANDLE_FIRST_FLAG_TYPE is the first handle that needs a flag when called. +# define HANDLE_FIRST_FLAG_TYPE (TPMI_SH_POLICY_H_UNMARSHAL + 1) +# define TPMI_DH_ENTITY_H_UNMARSHAL (TPMI_SH_POLICY_H_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_DH_ENTITY), +# define TPMI_DH_OBJECT_H_UNMARSHAL (TPMI_DH_ENTITY_H_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_DH_OBJECT), +# define TPMI_DH_PARENT_H_UNMARSHAL (TPMI_DH_OBJECT_H_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_DH_PARENT), +# define TPMI_DH_PCR_H_UNMARSHAL (TPMI_DH_PARENT_H_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_DH_PCR), +# define TPMI_RH_ENDORSEMENT_H_UNMARSHAL (TPMI_DH_PCR_H_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_RH_ENDORSEMENT), +# define TPMI_RH_HIERARCHY_H_UNMARSHAL (TPMI_RH_ENDORSEMENT_H_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_RH_HIERARCHY), +// PARAMETER_FIRST_TYPE marks the end of the handle list. +# define PARAMETER_FIRST_TYPE (TPMI_RH_HIERARCHY_H_UNMARSHAL + 1) +# define TPM2B_DATA_P_UNMARSHAL (TPMI_RH_HIERARCHY_H_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_DATA), +# define TPM2B_DIGEST_P_UNMARSHAL (TPM2B_DATA_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_DIGEST), +# define TPM2B_ECC_PARAMETER_P_UNMARSHAL (TPM2B_DIGEST_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_ECC_PARAMETER), +# define TPM2B_ECC_POINT_P_UNMARSHAL (TPM2B_ECC_PARAMETER_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_ECC_POINT), +# define TPM2B_ENCRYPTED_SECRET_P_UNMARSHAL (TPM2B_ECC_POINT_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_ENCRYPTED_SECRET), +# define TPM2B_EVENT_P_UNMARSHAL (TPM2B_ENCRYPTED_SECRET_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_EVENT), +# define TPM2B_ID_OBJECT_P_UNMARSHAL (TPM2B_EVENT_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_ID_OBJECT), +# define TPM2B_IV_P_UNMARSHAL (TPM2B_ID_OBJECT_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_IV), +# define TPM2B_MAX_BUFFER_P_UNMARSHAL (TPM2B_IV_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_MAX_BUFFER), +# define TPM2B_MAX_NV_BUFFER_P_UNMARSHAL (TPM2B_MAX_BUFFER_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_MAX_NV_BUFFER), +# define TPM2B_NAME_P_UNMARSHAL (TPM2B_MAX_NV_BUFFER_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_NAME), +# define TPM2B_NV_PUBLIC_P_UNMARSHAL (TPM2B_NAME_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_NV_PUBLIC), +# define TPM2B_PRIVATE_P_UNMARSHAL (TPM2B_NV_PUBLIC_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_PRIVATE), +# define TPM2B_PUBLIC_KEY_RSA_P_UNMARSHAL (TPM2B_PRIVATE_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_PUBLIC_KEY_RSA), +# define TPM2B_SENSITIVE_P_UNMARSHAL (TPM2B_PUBLIC_KEY_RSA_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_SENSITIVE), +# define TPM2B_SENSITIVE_CREATE_P_UNMARSHAL (TPM2B_SENSITIVE_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_SENSITIVE_CREATE), +# define TPM2B_SENSITIVE_DATA_P_UNMARSHAL (TPM2B_SENSITIVE_CREATE_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_SENSITIVE_DATA), +# define TPM2B_TEMPLATE_P_UNMARSHAL (TPM2B_SENSITIVE_DATA_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_TEMPLATE), +# define TPM2B_TIMEOUT_P_UNMARSHAL (TPM2B_TEMPLATE_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_TIMEOUT), +# define TPMI_DH_CONTEXT_P_UNMARSHAL (TPM2B_TIMEOUT_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_DH_CONTEXT), +# define TPMI_DH_PERSISTENT_P_UNMARSHAL (TPMI_DH_CONTEXT_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_DH_PERSISTENT), +# define TPMI_ECC_CURVE_P_UNMARSHAL (TPMI_DH_PERSISTENT_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_ECC_CURVE), +# define TPMI_YES_NO_P_UNMARSHAL (TPMI_ECC_CURVE_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_YES_NO), +# define TPML_ALG_P_UNMARSHAL (TPMI_YES_NO_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPML_ALG), +# define TPML_CC_P_UNMARSHAL (TPML_ALG_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPML_CC), +# define TPML_DIGEST_P_UNMARSHAL (TPML_CC_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPML_DIGEST), +# define TPML_DIGEST_VALUES_P_UNMARSHAL (TPML_DIGEST_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPML_DIGEST_VALUES), +# define TPML_PCR_SELECTION_P_UNMARSHAL (TPML_DIGEST_VALUES_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPML_PCR_SELECTION), +# define TPMS_CONTEXT_P_UNMARSHAL (TPML_PCR_SELECTION_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMS_CONTEXT), +# define TPMT_PUBLIC_PARMS_P_UNMARSHAL (TPMS_CONTEXT_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMT_PUBLIC_PARMS), +# define TPMT_TK_AUTH_P_UNMARSHAL (TPMT_PUBLIC_PARMS_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMT_TK_AUTH), +# define TPMT_TK_CREATION_P_UNMARSHAL (TPMT_TK_AUTH_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMT_TK_CREATION), +# define TPMT_TK_HASHCHECK_P_UNMARSHAL (TPMT_TK_CREATION_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMT_TK_HASHCHECK), +# define TPMT_TK_VERIFIED_P_UNMARSHAL (TPMT_TK_HASHCHECK_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMT_TK_VERIFIED), +# define TPM_AT_P_UNMARSHAL (TPMT_TK_VERIFIED_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM_AT), +# define TPM_CAP_P_UNMARSHAL (TPM_AT_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM_CAP), +# define TPM_CLOCK_ADJUST_P_UNMARSHAL (TPM_CAP_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM_CLOCK_ADJUST), +# define TPM_EO_P_UNMARSHAL (TPM_CLOCK_ADJUST_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM_EO), +# define TPM_SE_P_UNMARSHAL (TPM_EO_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM_SE), +# define TPM_SU_P_UNMARSHAL (TPM_SE_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM_SU), +# define UINT16_P_UNMARSHAL (TPM_SU_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(UINT16), +# define UINT32_P_UNMARSHAL (UINT16_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(UINT32), +# define UINT64_P_UNMARSHAL (UINT32_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(UINT64), +# define UINT8_P_UNMARSHAL (UINT64_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(UINT8), +// PARAMETER_FIRST_FLAG_TYPE is the first parameter to need a flag. +# define PARAMETER_FIRST_FLAG_TYPE (UINT8_P_UNMARSHAL + 1) +# define TPM2B_PUBLIC_P_UNMARSHAL (UINT8_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPM2B_PUBLIC), +# define TPMI_ALG_CIPHER_MODE_P_UNMARSHAL (TPM2B_PUBLIC_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_ALG_CIPHER_MODE), +# define TPMI_ALG_HASH_P_UNMARSHAL (TPMI_ALG_CIPHER_MODE_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_ALG_HASH), +# define TPMI_ALG_MAC_SCHEME_P_UNMARSHAL (TPMI_ALG_HASH_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_ALG_MAC_SCHEME), +# define TPMI_DH_PCR_P_UNMARSHAL (TPMI_ALG_MAC_SCHEME_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_DH_PCR), +# define TPMI_ECC_KEY_EXCHANGE_P_UNMARSHAL (TPMI_DH_PCR_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_ECC_KEY_EXCHANGE), +# define TPMI_RH_ENABLES_P_UNMARSHAL (TPMI_ECC_KEY_EXCHANGE_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_RH_ENABLES), +# define TPMI_RH_HIERARCHY_P_UNMARSHAL (TPMI_RH_ENABLES_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMI_RH_HIERARCHY), +# define TPMT_KDF_SCHEME_P_UNMARSHAL (TPMI_RH_HIERARCHY_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMT_KDF_SCHEME), +# define TPMT_RSA_DECRYPT_P_UNMARSHAL (TPMT_KDF_SCHEME_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMT_RSA_DECRYPT), +# define TPMT_SIGNATURE_P_UNMARSHAL (TPMT_RSA_DECRYPT_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMT_SIGNATURE), +# define TPMT_SIG_SCHEME_P_UNMARSHAL (TPMT_SIGNATURE_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMT_SIG_SCHEME), +# define TPMT_SYM_DEF_P_UNMARSHAL (TPMT_SIG_SCHEME_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMT_SYM_DEF), +# define TPMT_SYM_DEF_OBJECT_P_UNMARSHAL (TPMT_SYM_DEF_P_UNMARSHAL + 1) + UNMARSHAL_DISPATCH(TPMT_SYM_DEF_OBJECT) +// PARAMETER_LAST_TYPE is the end of the command parameter list. +# define PARAMETER_LAST_TYPE (TPMT_SYM_DEF_OBJECT_P_UNMARSHAL) +}; + +// The marshalArray contains the dispatch functions for the marshaling code. +// The defines in this array are used to make it easier to cross reference the +// marshaling values in the types array of each command +const _MARSHAL_T_ marshalArray[] = { + +# define UINT32_H_MARSHAL 0 + MARSHAL_DISPATCH(UINT32), +// RESPONSE_PARAMETER_FIRST_TYPE marks the end of the response handles. +# define RESPONSE_PARAMETER_FIRST_TYPE (UINT32_H_MARSHAL + 1) +# define TPM2B_ATTEST_P_MARSHAL (UINT32_H_MARSHAL + 1) + MARSHAL_DISPATCH(TPM2B_ATTEST), +# define TPM2B_CREATION_DATA_P_MARSHAL (TPM2B_ATTEST_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPM2B_CREATION_DATA), +# define TPM2B_DATA_P_MARSHAL (TPM2B_CREATION_DATA_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPM2B_DATA), +# define TPM2B_DIGEST_P_MARSHAL (TPM2B_DATA_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPM2B_DIGEST), +# define TPM2B_ECC_POINT_P_MARSHAL (TPM2B_DIGEST_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPM2B_ECC_POINT), +# define TPM2B_ENCRYPTED_SECRET_P_MARSHAL (TPM2B_ECC_POINT_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPM2B_ENCRYPTED_SECRET), +# define TPM2B_ID_OBJECT_P_MARSHAL (TPM2B_ENCRYPTED_SECRET_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPM2B_ID_OBJECT), +# define TPM2B_IV_P_MARSHAL (TPM2B_ID_OBJECT_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPM2B_IV), +# define TPM2B_MAX_BUFFER_P_MARSHAL (TPM2B_IV_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPM2B_MAX_BUFFER), +# define TPM2B_MAX_NV_BUFFER_P_MARSHAL (TPM2B_MAX_BUFFER_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPM2B_MAX_NV_BUFFER), +# define TPM2B_NAME_P_MARSHAL (TPM2B_MAX_NV_BUFFER_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPM2B_NAME), +# define TPM2B_NV_PUBLIC_P_MARSHAL (TPM2B_NAME_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPM2B_NV_PUBLIC), +# define TPM2B_PRIVATE_P_MARSHAL (TPM2B_NV_PUBLIC_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPM2B_PRIVATE), +# define TPM2B_PUBLIC_P_MARSHAL (TPM2B_PRIVATE_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPM2B_PUBLIC), +# define TPM2B_PUBLIC_KEY_RSA_P_MARSHAL (TPM2B_PUBLIC_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPM2B_PUBLIC_KEY_RSA), +# define TPM2B_SENSITIVE_DATA_P_MARSHAL (TPM2B_PUBLIC_KEY_RSA_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPM2B_SENSITIVE_DATA), +# define TPM2B_TIMEOUT_P_MARSHAL (TPM2B_SENSITIVE_DATA_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPM2B_TIMEOUT), +# define UINT8_P_MARSHAL (TPM2B_TIMEOUT_P_MARSHAL + 1) + MARSHAL_DISPATCH(UINT8), +# define TPML_AC_CAPABILITIES_P_MARSHAL (UINT8_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPML_AC_CAPABILITIES), +# define TPML_ALG_P_MARSHAL (TPML_AC_CAPABILITIES_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPML_ALG), +# define TPML_DIGEST_P_MARSHAL (TPML_ALG_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPML_DIGEST), +# define TPML_DIGEST_VALUES_P_MARSHAL (TPML_DIGEST_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPML_DIGEST_VALUES), +# define TPML_PCR_SELECTION_P_MARSHAL (TPML_DIGEST_VALUES_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPML_PCR_SELECTION), +# define TPMS_AC_OUTPUT_P_MARSHAL (TPML_PCR_SELECTION_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPMS_AC_OUTPUT), +# define TPMS_ALGORITHM_DETAIL_ECC_P_MARSHAL (TPMS_AC_OUTPUT_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPMS_ALGORITHM_DETAIL_ECC), +# define TPMS_CAPABILITY_DATA_P_MARSHAL (TPMS_ALGORITHM_DETAIL_ECC_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPMS_CAPABILITY_DATA), +# define TPMS_CONTEXT_P_MARSHAL (TPMS_CAPABILITY_DATA_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPMS_CONTEXT), +# define TPMS_TIME_INFO_P_MARSHAL (TPMS_CONTEXT_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPMS_TIME_INFO), +# define TPMT_HA_P_MARSHAL (TPMS_TIME_INFO_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPMT_HA), +# define TPMT_SIGNATURE_P_MARSHAL (TPMT_HA_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPMT_SIGNATURE), +# define TPMT_TK_AUTH_P_MARSHAL (TPMT_SIGNATURE_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPMT_TK_AUTH), +# define TPMT_TK_CREATION_P_MARSHAL (TPMT_TK_AUTH_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPMT_TK_CREATION), +# define TPMT_TK_HASHCHECK_P_MARSHAL (TPMT_TK_CREATION_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPMT_TK_HASHCHECK), +# define TPMT_TK_VERIFIED_P_MARSHAL (TPMT_TK_HASHCHECK_P_MARSHAL + 1) + MARSHAL_DISPATCH(TPMT_TK_VERIFIED), +# define UINT32_P_MARSHAL (TPMT_TK_VERIFIED_P_MARSHAL + 1) + MARSHAL_DISPATCH(UINT32), +# define UINT16_P_MARSHAL (UINT32_P_MARSHAL + 1) + MARSHAL_DISPATCH(UINT16) +// RESPONSE_PARAMETER_LAST_TYPE is the end of the response parameter list. +# define RESPONSE_PARAMETER_LAST_TYPE (UINT16_P_MARSHAL) +}; + +// This list of aliases allows the types in the _COMMAND_DESCRIPTOR_T to match the +// types in the command/response templates of part 3. +# define INT32_P_UNMARSHAL UINT32_P_UNMARSHAL +# define TPM2B_AUTH_P_UNMARSHAL TPM2B_DIGEST_P_UNMARSHAL +# define TPM2B_NONCE_P_UNMARSHAL TPM2B_DIGEST_P_UNMARSHAL +# define TPM2B_OPERAND_P_UNMARSHAL TPM2B_DIGEST_P_UNMARSHAL +# define TPMA_LOCALITY_P_UNMARSHAL UINT8_P_UNMARSHAL +# define TPM_CC_P_UNMARSHAL UINT32_P_UNMARSHAL +# define TPMI_DH_CONTEXT_H_MARSHAL UINT32_H_MARSHAL +# define TPMI_DH_OBJECT_H_MARSHAL UINT32_H_MARSHAL +# define TPMI_SH_AUTH_SESSION_H_MARSHAL UINT32_H_MARSHAL +# define TPM_HANDLE_H_MARSHAL UINT32_H_MARSHAL +# define TPM2B_NONCE_P_MARSHAL TPM2B_DIGEST_P_MARSHAL +# define TPMI_YES_NO_P_MARSHAL UINT8_P_MARSHAL +# define TPM_RC_P_MARSHAL UINT32_P_MARSHAL + +# if CC_Startup + +# include "Startup_fp.h" + +typedef TPM_RC(Startup_Entry)(Startup_In* in); + +typedef const struct +{ + Startup_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[3]; +} Startup_COMMAND_DESCRIPTOR_t; + +Startup_COMMAND_DESCRIPTOR_t _StartupData = { + /* entry */ &TPM2_Startup, + /* inSize */ (UINT16)(sizeof(Startup_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(Startup_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets; + /* types */ {TPM_SU_P_UNMARSHAL, END_OF_LIST, END_OF_LIST}}; + +# define _StartupDataAddress (&_StartupData) +# else +# define _StartupDataAddress 0 +# endif // CC_Startup + +# if CC_Shutdown + +# include "Shutdown_fp.h" + +typedef TPM_RC(Shutdown_Entry)(Shutdown_In* in); + +typedef const struct +{ + Shutdown_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[3]; +} Shutdown_COMMAND_DESCRIPTOR_t; + +Shutdown_COMMAND_DESCRIPTOR_t _ShutdownData = { + /* entry */ &TPM2_Shutdown, + /* inSize */ (UINT16)(sizeof(Shutdown_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(Shutdown_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets; + /* types */ {TPM_SU_P_UNMARSHAL, END_OF_LIST, END_OF_LIST}}; + +# define _ShutdownDataAddress (&_ShutdownData) +# else +# define _ShutdownDataAddress 0 +# endif // CC_Shutdown + +# if CC_SelfTest + +# include "SelfTest_fp.h" + +typedef TPM_RC(SelfTest_Entry)(SelfTest_In* in); + +typedef const struct +{ + SelfTest_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[3]; +} SelfTest_COMMAND_DESCRIPTOR_t; + +SelfTest_COMMAND_DESCRIPTOR_t _SelfTestData = { + /* entry */ &TPM2_SelfTest, + /* inSize */ (UINT16)(sizeof(SelfTest_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(SelfTest_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets; + /* types */ {TPMI_YES_NO_P_UNMARSHAL, END_OF_LIST, END_OF_LIST}}; + +# define _SelfTestDataAddress (&_SelfTestData) +# else +# define _SelfTestDataAddress 0 +# endif // CC_SelfTest + +# if CC_IncrementalSelfTest + +# include "IncrementalSelfTest_fp.h" + +typedef TPM_RC(IncrementalSelfTest_Entry)(IncrementalSelfTest_In* in, + IncrementalSelfTest_Out* out); + +typedef const struct +{ + IncrementalSelfTest_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[4]; +} IncrementalSelfTest_COMMAND_DESCRIPTOR_t; + +IncrementalSelfTest_COMMAND_DESCRIPTOR_t _IncrementalSelfTestData = { + /* entry */ &TPM2_IncrementalSelfTest, + /* inSize */ (UINT16)(sizeof(IncrementalSelfTest_In)), + /* outSize */ (UINT16)(sizeof(IncrementalSelfTest_Out)), + /* offsetOfTypes */ offsetof(IncrementalSelfTest_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets; + /* types */ + {TPML_ALG_P_UNMARSHAL, END_OF_LIST, TPML_ALG_P_MARSHAL, END_OF_LIST}}; + +# define _IncrementalSelfTestDataAddress (&_IncrementalSelfTestData) +# else +# define _IncrementalSelfTestDataAddress 0 +# endif // CC_IncrementalSelfTest + +# if CC_GetTestResult + +# include "GetTestResult_fp.h" + +typedef TPM_RC(GetTestResult_Entry)(GetTestResult_Out* out); + +typedef const struct +{ + GetTestResult_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} GetTestResult_COMMAND_DESCRIPTOR_t; + +GetTestResult_COMMAND_DESCRIPTOR_t _GetTestResultData = { + /* entry */ &TPM2_GetTestResult, + /* inSize */ 0, + /* outSize */ (UINT16)(sizeof(GetTestResult_Out)), + /* offsetOfTypes */ offsetof(GetTestResult_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(GetTestResult_Out, testResult))}, + /* types */ + {END_OF_LIST, TPM2B_MAX_BUFFER_P_MARSHAL, TPM_RC_P_MARSHAL, END_OF_LIST}}; + +# define _GetTestResultDataAddress (&_GetTestResultData) +# else +# define _GetTestResultDataAddress 0 +# endif // CC_GetTestResult + +# if CC_StartAuthSession + +# include "StartAuthSession_fp.h" + +typedef TPM_RC(StartAuthSession_Entry)(StartAuthSession_In* in, + StartAuthSession_Out* out); + +typedef const struct +{ + StartAuthSession_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[7]; + BYTE types[11]; +} StartAuthSession_COMMAND_DESCRIPTOR_t; + +StartAuthSession_COMMAND_DESCRIPTOR_t _StartAuthSessionData = { + /* entry */ &TPM2_StartAuthSession, + /* inSize */ (UINT16)(sizeof(StartAuthSession_In)), + /* outSize */ (UINT16)(sizeof(StartAuthSession_Out)), + /* offsetOfTypes */ offsetof(StartAuthSession_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(StartAuthSession_In, bind)), + (UINT16)(offsetof(StartAuthSession_In, nonceCaller)), + (UINT16)(offsetof(StartAuthSession_In, encryptedSalt)), + (UINT16)(offsetof(StartAuthSession_In, sessionType)), + (UINT16)(offsetof(StartAuthSession_In, symmetric)), + (UINT16)(offsetof(StartAuthSession_In, authHash)), + (UINT16)(offsetof(StartAuthSession_Out, nonceTPM))}, + /* types */ + {TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG, + TPMI_DH_ENTITY_H_UNMARSHAL + ADD_FLAG, + TPM2B_NONCE_P_UNMARSHAL, + TPM2B_ENCRYPTED_SECRET_P_UNMARSHAL, + TPM_SE_P_UNMARSHAL, + TPMT_SYM_DEF_P_UNMARSHAL + ADD_FLAG, + TPMI_ALG_HASH_P_UNMARSHAL, + END_OF_LIST, + TPMI_SH_AUTH_SESSION_H_MARSHAL, + TPM2B_NONCE_P_MARSHAL, + END_OF_LIST}}; + +# define _StartAuthSessionDataAddress (&_StartAuthSessionData) +# else +# define _StartAuthSessionDataAddress 0 +# endif // CC_StartAuthSession + +# if CC_PolicyRestart + +# include "PolicyRestart_fp.h" + +typedef TPM_RC(PolicyRestart_Entry)(PolicyRestart_In* in); + +typedef const struct +{ + PolicyRestart_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[3]; +} PolicyRestart_COMMAND_DESCRIPTOR_t; + +PolicyRestart_COMMAND_DESCRIPTOR_t _PolicyRestartData = { + /* entry */ &TPM2_PolicyRestart, + /* inSize */ (UINT16)(sizeof(PolicyRestart_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PolicyRestart_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets; + /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, END_OF_LIST, END_OF_LIST}}; + +# define _PolicyRestartDataAddress (&_PolicyRestartData) +# else +# define _PolicyRestartDataAddress 0 +# endif // CC_PolicyRestart + +# if CC_Create + +# include "Create_fp.h" + +typedef TPM_RC(Create_Entry)(Create_In* in, Create_Out* out); + +typedef const struct +{ + Create_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[8]; + BYTE types[12]; +} Create_COMMAND_DESCRIPTOR_t; + +Create_COMMAND_DESCRIPTOR_t _CreateData = { + /* entry */ &TPM2_Create, + /* inSize */ (UINT16)(sizeof(Create_In)), + /* outSize */ (UINT16)(sizeof(Create_Out)), + /* offsetOfTypes */ offsetof(Create_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(Create_In, inSensitive)), + (UINT16)(offsetof(Create_In, inPublic)), + (UINT16)(offsetof(Create_In, outsideInfo)), + (UINT16)(offsetof(Create_In, creationPCR)), + (UINT16)(offsetof(Create_Out, outPublic)), + (UINT16)(offsetof(Create_Out, creationData)), + (UINT16)(offsetof(Create_Out, creationHash)), + (UINT16)(offsetof(Create_Out, creationTicket))}, + /* types */ + {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_SENSITIVE_CREATE_P_UNMARSHAL, + TPM2B_PUBLIC_P_UNMARSHAL, + TPM2B_DATA_P_UNMARSHAL, + TPML_PCR_SELECTION_P_UNMARSHAL, + END_OF_LIST, + TPM2B_PRIVATE_P_MARSHAL, + TPM2B_PUBLIC_P_MARSHAL, + TPM2B_CREATION_DATA_P_MARSHAL, + TPM2B_DIGEST_P_MARSHAL, + TPMT_TK_CREATION_P_MARSHAL, + END_OF_LIST}}; + +# define _CreateDataAddress (&_CreateData) +# else +# define _CreateDataAddress 0 +# endif // CC_Create + +# if CC_Load + +# include "Load_fp.h" + +typedef TPM_RC(Load_Entry)(Load_In* in, Load_Out* out); + +typedef const struct +{ + Load_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[7]; +} Load_COMMAND_DESCRIPTOR_t; + +Load_COMMAND_DESCRIPTOR_t _LoadData = { + /* entry */ &TPM2_Load, + /* inSize */ (UINT16)(sizeof(Load_In)), + /* outSize */ (UINT16)(sizeof(Load_Out)), + /* offsetOfTypes */ offsetof(Load_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(Load_In, inPrivate)), + (UINT16)(offsetof(Load_In, inPublic)), + (UINT16)(offsetof(Load_Out, name))}, + /* types */ + {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_PRIVATE_P_UNMARSHAL, + TPM2B_PUBLIC_P_UNMARSHAL, + END_OF_LIST, + TPM_HANDLE_H_MARSHAL, + TPM2B_NAME_P_MARSHAL, + END_OF_LIST}}; + +# define _LoadDataAddress (&_LoadData) +# else +# define _LoadDataAddress 0 +# endif // CC_Load + +# if CC_LoadExternal + +# include "LoadExternal_fp.h" + +typedef TPM_RC(LoadExternal_Entry)(LoadExternal_In* in, LoadExternal_Out* out); + +typedef const struct +{ + LoadExternal_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[7]; +} LoadExternal_COMMAND_DESCRIPTOR_t; + +LoadExternal_COMMAND_DESCRIPTOR_t _LoadExternalData = { + /* entry */ &TPM2_LoadExternal, + /* inSize */ (UINT16)(sizeof(LoadExternal_In)), + /* outSize */ (UINT16)(sizeof(LoadExternal_Out)), + /* offsetOfTypes */ offsetof(LoadExternal_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(LoadExternal_In, inPublic)), + (UINT16)(offsetof(LoadExternal_In, hierarchy)), + (UINT16)(offsetof(LoadExternal_Out, name))}, + /* types */ + {TPM2B_SENSITIVE_P_UNMARSHAL, + TPM2B_PUBLIC_P_UNMARSHAL + ADD_FLAG, + TPMI_RH_HIERARCHY_P_UNMARSHAL + ADD_FLAG, + END_OF_LIST, + TPM_HANDLE_H_MARSHAL, + TPM2B_NAME_P_MARSHAL, + END_OF_LIST}}; + +# define _LoadExternalDataAddress (&_LoadExternalData) +# else +# define _LoadExternalDataAddress 0 +# endif // CC_LoadExternal + +# if CC_ReadPublic + +# include "ReadPublic_fp.h" + +typedef TPM_RC(ReadPublic_Entry)(ReadPublic_In* in, ReadPublic_Out* out); + +typedef const struct +{ + ReadPublic_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[2]; + BYTE types[6]; +} ReadPublic_COMMAND_DESCRIPTOR_t; + +ReadPublic_COMMAND_DESCRIPTOR_t _ReadPublicData = { + /* entry */ &TPM2_ReadPublic, + /* inSize */ (UINT16)(sizeof(ReadPublic_In)), + /* outSize */ (UINT16)(sizeof(ReadPublic_Out)), + /* offsetOfTypes */ offsetof(ReadPublic_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(ReadPublic_Out, name)), + (UINT16)(offsetof(ReadPublic_Out, qualifiedName))}, + /* types */ + {TPMI_DH_OBJECT_H_UNMARSHAL, + END_OF_LIST, + TPM2B_PUBLIC_P_MARSHAL, + TPM2B_NAME_P_MARSHAL, + TPM2B_NAME_P_MARSHAL, + END_OF_LIST}}; + +# define _ReadPublicDataAddress (&_ReadPublicData) +# else +# define _ReadPublicDataAddress 0 +# endif // CC_ReadPublic + +# if CC_ActivateCredential + +# include "ActivateCredential_fp.h" + +typedef TPM_RC(ActivateCredential_Entry)(ActivateCredential_In* in, + ActivateCredential_Out* out); + +typedef const struct +{ + ActivateCredential_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[7]; +} ActivateCredential_COMMAND_DESCRIPTOR_t; + +ActivateCredential_COMMAND_DESCRIPTOR_t _ActivateCredentialData = { + /* entry */ &TPM2_ActivateCredential, + /* inSize */ (UINT16)(sizeof(ActivateCredential_In)), + /* outSize */ (UINT16)(sizeof(ActivateCredential_Out)), + /* offsetOfTypes */ offsetof(ActivateCredential_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(ActivateCredential_In, keyHandle)), + (UINT16)(offsetof(ActivateCredential_In, credentialBlob)), + (UINT16)(offsetof(ActivateCredential_In, secret))}, + /* types */ + {TPMI_DH_OBJECT_H_UNMARSHAL, + TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_ID_OBJECT_P_UNMARSHAL, + TPM2B_ENCRYPTED_SECRET_P_UNMARSHAL, + END_OF_LIST, + TPM2B_DIGEST_P_MARSHAL, + END_OF_LIST}}; + +# define _ActivateCredentialDataAddress (&_ActivateCredentialData) +# else +# define _ActivateCredentialDataAddress 0 +# endif // CC_ActivateCredential + +# if CC_MakeCredential + +# include "MakeCredential_fp.h" + +typedef TPM_RC(MakeCredential_Entry)(MakeCredential_In* in, MakeCredential_Out* out); + +typedef const struct +{ + MakeCredential_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[7]; +} MakeCredential_COMMAND_DESCRIPTOR_t; + +MakeCredential_COMMAND_DESCRIPTOR_t _MakeCredentialData = { + /* entry */ &TPM2_MakeCredential, + /* inSize */ (UINT16)(sizeof(MakeCredential_In)), + /* outSize */ (UINT16)(sizeof(MakeCredential_Out)), + /* offsetOfTypes */ offsetof(MakeCredential_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(MakeCredential_In, credential)), + (UINT16)(offsetof(MakeCredential_In, objectName)), + (UINT16)(offsetof(MakeCredential_Out, secret))}, + /* types */ + {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_DIGEST_P_UNMARSHAL, + TPM2B_NAME_P_UNMARSHAL, + END_OF_LIST, + TPM2B_ID_OBJECT_P_MARSHAL, + TPM2B_ENCRYPTED_SECRET_P_MARSHAL, + END_OF_LIST}}; + +# define _MakeCredentialDataAddress (&_MakeCredentialData) +# else +# define _MakeCredentialDataAddress 0 +# endif // CC_MakeCredential + +# if CC_Unseal + +# include "Unseal_fp.h" + +typedef TPM_RC(Unseal_Entry)(Unseal_In* in, Unseal_Out* out); + +typedef const struct +{ + Unseal_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[4]; +} Unseal_COMMAND_DESCRIPTOR_t; + +Unseal_COMMAND_DESCRIPTOR_t _UnsealData = { + /* entry */ &TPM2_Unseal, + /* inSize */ (UINT16)(sizeof(Unseal_In)), + /* outSize */ (UINT16)(sizeof(Unseal_Out)), + /* offsetOfTypes */ offsetof(Unseal_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets; + /* types */ + {TPMI_DH_OBJECT_H_UNMARSHAL, + END_OF_LIST, + TPM2B_SENSITIVE_DATA_P_MARSHAL, + END_OF_LIST}}; + +# define _UnsealDataAddress (&_UnsealData) +# else +# define _UnsealDataAddress 0 +# endif // CC_Unseal + +# if CC_ObjectChangeAuth + +# include "ObjectChangeAuth_fp.h" + +typedef TPM_RC(ObjectChangeAuth_Entry)(ObjectChangeAuth_In* in, + ObjectChangeAuth_Out* out); + +typedef const struct +{ + ObjectChangeAuth_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[2]; + BYTE types[6]; +} ObjectChangeAuth_COMMAND_DESCRIPTOR_t; + +ObjectChangeAuth_COMMAND_DESCRIPTOR_t _ObjectChangeAuthData = { + /* entry */ &TPM2_ObjectChangeAuth, + /* inSize */ (UINT16)(sizeof(ObjectChangeAuth_In)), + /* outSize */ (UINT16)(sizeof(ObjectChangeAuth_Out)), + /* offsetOfTypes */ offsetof(ObjectChangeAuth_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(ObjectChangeAuth_In, parentHandle)), + (UINT16)(offsetof(ObjectChangeAuth_In, newAuth))}, + /* types */ + {TPMI_DH_OBJECT_H_UNMARSHAL, + TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_AUTH_P_UNMARSHAL, + END_OF_LIST, + TPM2B_PRIVATE_P_MARSHAL, + END_OF_LIST}}; + +# define _ObjectChangeAuthDataAddress (&_ObjectChangeAuthData) +# else +# define _ObjectChangeAuthDataAddress 0 +# endif // CC_ObjectChangeAuth + +# if CC_CreateLoaded + +# include "CreateLoaded_fp.h" + +typedef TPM_RC(CreateLoaded_Entry)(CreateLoaded_In* in, CreateLoaded_Out* out); + +typedef const struct +{ + CreateLoaded_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[5]; + BYTE types[9]; +} CreateLoaded_COMMAND_DESCRIPTOR_t; + +CreateLoaded_COMMAND_DESCRIPTOR_t _CreateLoadedData = { + /* entry */ &TPM2_CreateLoaded, + /* inSize */ (UINT16)(sizeof(CreateLoaded_In)), + /* outSize */ (UINT16)(sizeof(CreateLoaded_Out)), + /* offsetOfTypes */ offsetof(CreateLoaded_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(CreateLoaded_In, inSensitive)), + (UINT16)(offsetof(CreateLoaded_In, inPublic)), + (UINT16)(offsetof(CreateLoaded_Out, outPrivate)), + (UINT16)(offsetof(CreateLoaded_Out, outPublic)), + (UINT16)(offsetof(CreateLoaded_Out, name))}, + /* types */ + {TPMI_DH_PARENT_H_UNMARSHAL + ADD_FLAG, + TPM2B_SENSITIVE_CREATE_P_UNMARSHAL, + TPM2B_TEMPLATE_P_UNMARSHAL, + END_OF_LIST, + TPM_HANDLE_H_MARSHAL, + TPM2B_PRIVATE_P_MARSHAL, + TPM2B_PUBLIC_P_MARSHAL, + TPM2B_NAME_P_MARSHAL, + END_OF_LIST}}; + +# define _CreateLoadedDataAddress (&_CreateLoadedData) +# else +# define _CreateLoadedDataAddress 0 +# endif // CC_CreateLoaded + +# if CC_Duplicate + +# include "Duplicate_fp.h" + +typedef TPM_RC(Duplicate_Entry)(Duplicate_In* in, Duplicate_Out* out); + +typedef const struct +{ + Duplicate_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[5]; + BYTE types[9]; +} Duplicate_COMMAND_DESCRIPTOR_t; + +Duplicate_COMMAND_DESCRIPTOR_t _DuplicateData = { + /* entry */ &TPM2_Duplicate, + /* inSize */ (UINT16)(sizeof(Duplicate_In)), + /* outSize */ (UINT16)(sizeof(Duplicate_Out)), + /* offsetOfTypes */ offsetof(Duplicate_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(Duplicate_In, newParentHandle)), + (UINT16)(offsetof(Duplicate_In, encryptionKeyIn)), + (UINT16)(offsetof(Duplicate_In, symmetricAlg)), + (UINT16)(offsetof(Duplicate_Out, duplicate)), + (UINT16)(offsetof(Duplicate_Out, outSymSeed))}, + /* types */ + {TPMI_DH_OBJECT_H_UNMARSHAL, + TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG, + TPM2B_DATA_P_UNMARSHAL, + TPMT_SYM_DEF_OBJECT_P_UNMARSHAL + ADD_FLAG, + END_OF_LIST, + TPM2B_DATA_P_MARSHAL, + TPM2B_PRIVATE_P_MARSHAL, + TPM2B_ENCRYPTED_SECRET_P_MARSHAL, + END_OF_LIST}}; + +# define _DuplicateDataAddress (&_DuplicateData) +# else +# define _DuplicateDataAddress 0 +# endif // CC_Duplicate + +# if CC_Rewrap + +# include "Rewrap_fp.h" + +typedef TPM_RC(Rewrap_Entry)(Rewrap_In* in, Rewrap_Out* out); + +typedef const struct +{ + Rewrap_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[5]; + BYTE types[9]; +} Rewrap_COMMAND_DESCRIPTOR_t; + +Rewrap_COMMAND_DESCRIPTOR_t _RewrapData = { + /* entry */ &TPM2_Rewrap, + /* inSize */ (UINT16)(sizeof(Rewrap_In)), + /* outSize */ (UINT16)(sizeof(Rewrap_Out)), + /* offsetOfTypes */ offsetof(Rewrap_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(Rewrap_In, newParent)), + (UINT16)(offsetof(Rewrap_In, inDuplicate)), + (UINT16)(offsetof(Rewrap_In, name)), + (UINT16)(offsetof(Rewrap_In, inSymSeed)), + (UINT16)(offsetof(Rewrap_Out, outSymSeed))}, + /* types */ + {TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG, + TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG, + TPM2B_PRIVATE_P_UNMARSHAL, + TPM2B_NAME_P_UNMARSHAL, + TPM2B_ENCRYPTED_SECRET_P_UNMARSHAL, + END_OF_LIST, + TPM2B_PRIVATE_P_MARSHAL, + TPM2B_ENCRYPTED_SECRET_P_MARSHAL, + END_OF_LIST}}; + +# define _RewrapDataAddress (&_RewrapData) +# else +# define _RewrapDataAddress 0 +# endif // CC_Rewrap + +# if CC_Import + +# include "Import_fp.h" + +typedef TPM_RC(Import_Entry)(Import_In* in, Import_Out* out); + +typedef const struct +{ + Import_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[5]; + BYTE types[9]; +} Import_COMMAND_DESCRIPTOR_t; + +Import_COMMAND_DESCRIPTOR_t _ImportData = { + /* entry */ &TPM2_Import, + /* inSize */ (UINT16)(sizeof(Import_In)), + /* outSize */ (UINT16)(sizeof(Import_Out)), + /* offsetOfTypes */ offsetof(Import_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(Import_In, encryptionKey)), + (UINT16)(offsetof(Import_In, objectPublic)), + (UINT16)(offsetof(Import_In, duplicate)), + (UINT16)(offsetof(Import_In, inSymSeed)), + (UINT16)(offsetof(Import_In, symmetricAlg))}, + /* types */ + {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_DATA_P_UNMARSHAL, + TPM2B_PUBLIC_P_UNMARSHAL, + TPM2B_PRIVATE_P_UNMARSHAL, + TPM2B_ENCRYPTED_SECRET_P_UNMARSHAL, + TPMT_SYM_DEF_OBJECT_P_UNMARSHAL + ADD_FLAG, + END_OF_LIST, + TPM2B_PRIVATE_P_MARSHAL, + END_OF_LIST}}; + +# define _ImportDataAddress (&_ImportData) +# else +# define _ImportDataAddress 0 +# endif // CC_Import + +# if CC_RSA_Encrypt + +# include "RSA_Encrypt_fp.h" + +typedef TPM_RC(RSA_Encrypt_Entry)(RSA_Encrypt_In* in, RSA_Encrypt_Out* out); + +typedef const struct +{ + RSA_Encrypt_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[7]; +} RSA_Encrypt_COMMAND_DESCRIPTOR_t; + +RSA_Encrypt_COMMAND_DESCRIPTOR_t _RSA_EncryptData = { + /* entry */ &TPM2_RSA_Encrypt, + /* inSize */ (UINT16)(sizeof(RSA_Encrypt_In)), + /* outSize */ (UINT16)(sizeof(RSA_Encrypt_Out)), + /* offsetOfTypes */ offsetof(RSA_Encrypt_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(RSA_Encrypt_In, message)), + (UINT16)(offsetof(RSA_Encrypt_In, inScheme)), + (UINT16)(offsetof(RSA_Encrypt_In, label))}, + /* types */ + {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_PUBLIC_KEY_RSA_P_UNMARSHAL, + TPMT_RSA_DECRYPT_P_UNMARSHAL + ADD_FLAG, + TPM2B_DATA_P_UNMARSHAL, + END_OF_LIST, + TPM2B_PUBLIC_KEY_RSA_P_MARSHAL, + END_OF_LIST}}; + +# define _RSA_EncryptDataAddress (&_RSA_EncryptData) +# else +# define _RSA_EncryptDataAddress 0 +# endif // CC_RSA_Encrypt + +# if CC_RSA_Decrypt + +# include "RSA_Decrypt_fp.h" + +typedef TPM_RC(RSA_Decrypt_Entry)(RSA_Decrypt_In* in, RSA_Decrypt_Out* out); + +typedef const struct +{ + RSA_Decrypt_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[7]; +} RSA_Decrypt_COMMAND_DESCRIPTOR_t; + +RSA_Decrypt_COMMAND_DESCRIPTOR_t _RSA_DecryptData = { + /* entry */ &TPM2_RSA_Decrypt, + /* inSize */ (UINT16)(sizeof(RSA_Decrypt_In)), + /* outSize */ (UINT16)(sizeof(RSA_Decrypt_Out)), + /* offsetOfTypes */ offsetof(RSA_Decrypt_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(RSA_Decrypt_In, cipherText)), + (UINT16)(offsetof(RSA_Decrypt_In, inScheme)), + (UINT16)(offsetof(RSA_Decrypt_In, label))}, + /* types */ + {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_PUBLIC_KEY_RSA_P_UNMARSHAL, + TPMT_RSA_DECRYPT_P_UNMARSHAL + ADD_FLAG, + TPM2B_DATA_P_UNMARSHAL, + END_OF_LIST, + TPM2B_PUBLIC_KEY_RSA_P_MARSHAL, + END_OF_LIST}}; + +# define _RSA_DecryptDataAddress (&_RSA_DecryptData) +# else +# define _RSA_DecryptDataAddress 0 +# endif // CC_RSA_Decrypt + +# if CC_ECDH_KeyGen + +# include "ECDH_KeyGen_fp.h" + +typedef TPM_RC(ECDH_KeyGen_Entry)(ECDH_KeyGen_In* in, ECDH_KeyGen_Out* out); + +typedef const struct +{ + ECDH_KeyGen_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[5]; +} ECDH_KeyGen_COMMAND_DESCRIPTOR_t; + +ECDH_KeyGen_COMMAND_DESCRIPTOR_t _ECDH_KeyGenData = { + /* entry */ &TPM2_ECDH_KeyGen, + /* inSize */ (UINT16)(sizeof(ECDH_KeyGen_In)), + /* outSize */ (UINT16)(sizeof(ECDH_KeyGen_Out)), + /* offsetOfTypes */ offsetof(ECDH_KeyGen_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(ECDH_KeyGen_Out, pubPoint))}, + /* types */ + {TPMI_DH_OBJECT_H_UNMARSHAL, + END_OF_LIST, + TPM2B_ECC_POINT_P_MARSHAL, + TPM2B_ECC_POINT_P_MARSHAL, + END_OF_LIST}}; + +# define _ECDH_KeyGenDataAddress (&_ECDH_KeyGenData) +# else +# define _ECDH_KeyGenDataAddress 0 +# endif // CC_ECDH_KeyGen + +# if CC_ECDH_ZGen + +# include "ECDH_ZGen_fp.h" + +typedef TPM_RC(ECDH_ZGen_Entry)(ECDH_ZGen_In* in, ECDH_ZGen_Out* out); + +typedef const struct +{ + ECDH_ZGen_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[5]; +} ECDH_ZGen_COMMAND_DESCRIPTOR_t; + +ECDH_ZGen_COMMAND_DESCRIPTOR_t _ECDH_ZGenData = { + /* entry */ &TPM2_ECDH_ZGen, + /* inSize */ (UINT16)(sizeof(ECDH_ZGen_In)), + /* outSize */ (UINT16)(sizeof(ECDH_ZGen_Out)), + /* offsetOfTypes */ offsetof(ECDH_ZGen_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(ECDH_ZGen_In, inPoint))}, + /* types */ + {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_ECC_POINT_P_UNMARSHAL, + END_OF_LIST, + TPM2B_ECC_POINT_P_MARSHAL, + END_OF_LIST}}; + +# define _ECDH_ZGenDataAddress (&_ECDH_ZGenData) +# else +# define _ECDH_ZGenDataAddress 0 +# endif // CC_ECDH_ZGen + +# if CC_ECC_Parameters + +# include "ECC_Parameters_fp.h" + +typedef TPM_RC(ECC_Parameters_Entry)(ECC_Parameters_In* in, ECC_Parameters_Out* out); + +typedef const struct +{ + ECC_Parameters_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[4]; +} ECC_Parameters_COMMAND_DESCRIPTOR_t; + +ECC_Parameters_COMMAND_DESCRIPTOR_t _ECC_ParametersData = { + /* entry */ &TPM2_ECC_Parameters, + /* inSize */ (UINT16)(sizeof(ECC_Parameters_In)), + /* outSize */ (UINT16)(sizeof(ECC_Parameters_Out)), + /* offsetOfTypes */ offsetof(ECC_Parameters_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets; + /* types */ + {TPMI_ECC_CURVE_P_UNMARSHAL, + END_OF_LIST, + TPMS_ALGORITHM_DETAIL_ECC_P_MARSHAL, + END_OF_LIST}}; + +# define _ECC_ParametersDataAddress (&_ECC_ParametersData) +# else +# define _ECC_ParametersDataAddress 0 +# endif // CC_ECC_Parameters + +# if CC_ZGen_2Phase + +# include "ZGen_2Phase_fp.h" + +typedef TPM_RC(ZGen_2Phase_Entry)(ZGen_2Phase_In* in, ZGen_2Phase_Out* out); + +typedef const struct +{ + ZGen_2Phase_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[5]; + BYTE types[9]; +} ZGen_2Phase_COMMAND_DESCRIPTOR_t; + +ZGen_2Phase_COMMAND_DESCRIPTOR_t _ZGen_2PhaseData = { + /* entry */ &TPM2_ZGen_2Phase, + /* inSize */ (UINT16)(sizeof(ZGen_2Phase_In)), + /* outSize */ (UINT16)(sizeof(ZGen_2Phase_Out)), + /* offsetOfTypes */ offsetof(ZGen_2Phase_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(ZGen_2Phase_In, inQsB)), + (UINT16)(offsetof(ZGen_2Phase_In, inQeB)), + (UINT16)(offsetof(ZGen_2Phase_In, inScheme)), + (UINT16)(offsetof(ZGen_2Phase_In, counter)), + (UINT16)(offsetof(ZGen_2Phase_Out, outZ2))}, + /* types */ + {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_ECC_POINT_P_UNMARSHAL, + TPM2B_ECC_POINT_P_UNMARSHAL, + TPMI_ECC_KEY_EXCHANGE_P_UNMARSHAL, + UINT16_P_UNMARSHAL, + END_OF_LIST, + TPM2B_ECC_POINT_P_MARSHAL, + TPM2B_ECC_POINT_P_MARSHAL, + END_OF_LIST}}; + +# define _ZGen_2PhaseDataAddress (&_ZGen_2PhaseData) +# else +# define _ZGen_2PhaseDataAddress 0 +# endif // CC_ZGen_2Phase + +# if CC_ECC_Encrypt + +# include "ECC_Encrypt_fp.h" + +typedef TPM_RC(ECC_Encrypt_Entry)(ECC_Encrypt_In* in, ECC_Encrypt_Out* out); + +typedef const struct +{ + ECC_Encrypt_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[4]; + BYTE types[8]; +} ECC_Encrypt_COMMAND_DESCRIPTOR_t; + +ECC_Encrypt_COMMAND_DESCRIPTOR_t _ECC_EncryptData = { + /* entry */ &TPM2_ECC_Encrypt, + /* inSize */ (UINT16)(sizeof(ECC_Encrypt_In)), + /* outSize */ (UINT16)(sizeof(ECC_Encrypt_Out)), + /* offsetOfTypes */ offsetof(ECC_Encrypt_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(ECC_Encrypt_In, plainText)), + (UINT16)(offsetof(ECC_Encrypt_In, inScheme)), + (UINT16)(offsetof(ECC_Encrypt_Out, C2)), + (UINT16)(offsetof(ECC_Encrypt_Out, C3))}, + /* types */ + {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_MAX_BUFFER_P_UNMARSHAL, + TPMT_KDF_SCHEME_P_UNMARSHAL + ADD_FLAG, + END_OF_LIST, + TPM2B_ECC_POINT_P_MARSHAL, + TPM2B_MAX_BUFFER_P_MARSHAL, + TPM2B_DIGEST_P_MARSHAL, + END_OF_LIST}}; + +# define _ECC_EncryptDataAddress (&_ECC_EncryptData) +# else +# define _ECC_EncryptDataAddress 0 +# endif // CC_ECC_Encrypt + +# if CC_ECC_Decrypt + +# include "ECC_Decrypt_fp.h" + +typedef TPM_RC(ECC_Decrypt_Entry)(ECC_Decrypt_In* in, ECC_Decrypt_Out* out); + +typedef const struct +{ + ECC_Decrypt_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[4]; + BYTE types[8]; +} ECC_Decrypt_COMMAND_DESCRIPTOR_t; + +ECC_Decrypt_COMMAND_DESCRIPTOR_t _ECC_DecryptData = { + /* entry */ &TPM2_ECC_Decrypt, + /* inSize */ (UINT16)(sizeof(ECC_Decrypt_In)), + /* outSize */ (UINT16)(sizeof(ECC_Decrypt_Out)), + /* offsetOfTypes */ offsetof(ECC_Decrypt_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(ECC_Decrypt_In, C1)), + (UINT16)(offsetof(ECC_Decrypt_In, C2)), + (UINT16)(offsetof(ECC_Decrypt_In, C3)), + (UINT16)(offsetof(ECC_Decrypt_In, inScheme))}, + /* types */ + {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_ECC_POINT_P_UNMARSHAL, + TPM2B_MAX_BUFFER_P_UNMARSHAL, + TPM2B_DIGEST_P_UNMARSHAL, + TPMT_KDF_SCHEME_P_UNMARSHAL + ADD_FLAG, + END_OF_LIST, + TPM2B_MAX_BUFFER_P_MARSHAL, + END_OF_LIST}}; + +# define _ECC_DecryptDataAddress (&_ECC_DecryptData) +# else +# define _ECC_DecryptDataAddress 0 +# endif // CC_ECC_Decrypt + +# if CC_EncryptDecrypt + +# include "EncryptDecrypt_fp.h" + +typedef TPM_RC(EncryptDecrypt_Entry)(EncryptDecrypt_In* in, EncryptDecrypt_Out* out); + +typedef const struct +{ + EncryptDecrypt_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[5]; + BYTE types[9]; +} EncryptDecrypt_COMMAND_DESCRIPTOR_t; + +EncryptDecrypt_COMMAND_DESCRIPTOR_t _EncryptDecryptData = { + /* entry */ &TPM2_EncryptDecrypt, + /* inSize */ (UINT16)(sizeof(EncryptDecrypt_In)), + /* outSize */ (UINT16)(sizeof(EncryptDecrypt_Out)), + /* offsetOfTypes */ offsetof(EncryptDecrypt_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(EncryptDecrypt_In, decrypt)), + (UINT16)(offsetof(EncryptDecrypt_In, mode)), + (UINT16)(offsetof(EncryptDecrypt_In, ivIn)), + (UINT16)(offsetof(EncryptDecrypt_In, inData)), + (UINT16)(offsetof(EncryptDecrypt_Out, ivOut))}, + /* types */ + {TPMI_DH_OBJECT_H_UNMARSHAL, + TPMI_YES_NO_P_UNMARSHAL, + TPMI_ALG_CIPHER_MODE_P_UNMARSHAL + ADD_FLAG, + TPM2B_IV_P_UNMARSHAL, + TPM2B_MAX_BUFFER_P_UNMARSHAL, + END_OF_LIST, + TPM2B_MAX_BUFFER_P_MARSHAL, + TPM2B_IV_P_MARSHAL, + END_OF_LIST}}; + +# define _EncryptDecryptDataAddress (&_EncryptDecryptData) +# else +# define _EncryptDecryptDataAddress 0 +# endif // CC_EncryptDecrypt + +# if CC_EncryptDecrypt2 + +# include "EncryptDecrypt2_fp.h" + +typedef TPM_RC(EncryptDecrypt2_Entry)(EncryptDecrypt2_In* in, + EncryptDecrypt2_Out* out); + +typedef const struct +{ + EncryptDecrypt2_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[5]; + BYTE types[9]; +} EncryptDecrypt2_COMMAND_DESCRIPTOR_t; + +EncryptDecrypt2_COMMAND_DESCRIPTOR_t _EncryptDecrypt2Data = { + /* entry */ &TPM2_EncryptDecrypt2, + /* inSize */ (UINT16)(sizeof(EncryptDecrypt2_In)), + /* outSize */ (UINT16)(sizeof(EncryptDecrypt2_Out)), + /* offsetOfTypes */ offsetof(EncryptDecrypt2_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(EncryptDecrypt2_In, inData)), + (UINT16)(offsetof(EncryptDecrypt2_In, decrypt)), + (UINT16)(offsetof(EncryptDecrypt2_In, mode)), + (UINT16)(offsetof(EncryptDecrypt2_In, ivIn)), + (UINT16)(offsetof(EncryptDecrypt2_Out, ivOut))}, + /* types */ + {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_MAX_BUFFER_P_UNMARSHAL, + TPMI_YES_NO_P_UNMARSHAL, + TPMI_ALG_CIPHER_MODE_P_UNMARSHAL + ADD_FLAG, + TPM2B_IV_P_UNMARSHAL, + END_OF_LIST, + TPM2B_MAX_BUFFER_P_MARSHAL, + TPM2B_IV_P_MARSHAL, + END_OF_LIST}}; + +# define _EncryptDecrypt2DataAddress (&_EncryptDecrypt2Data) +# else +# define _EncryptDecrypt2DataAddress 0 +# endif // CC_EncryptDecrypt2 + +# if CC_Hash + +# include "Hash_fp.h" + +typedef TPM_RC(Hash_Entry)(Hash_In* in, Hash_Out* out); + +typedef const struct +{ + Hash_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[7]; +} Hash_COMMAND_DESCRIPTOR_t; + +Hash_COMMAND_DESCRIPTOR_t _HashData = { + /* entry */ &TPM2_Hash, + /* inSize */ (UINT16)(sizeof(Hash_In)), + /* outSize */ (UINT16)(sizeof(Hash_Out)), + /* offsetOfTypes */ offsetof(Hash_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(Hash_In, hashAlg)), + (UINT16)(offsetof(Hash_In, hierarchy)), + (UINT16)(offsetof(Hash_Out, validation))}, + /* types */ + {TPM2B_MAX_BUFFER_P_UNMARSHAL, + TPMI_ALG_HASH_P_UNMARSHAL, + TPMI_RH_HIERARCHY_P_UNMARSHAL + ADD_FLAG, + END_OF_LIST, + TPM2B_DIGEST_P_MARSHAL, + TPMT_TK_HASHCHECK_P_MARSHAL, + END_OF_LIST}}; + +# define _HashDataAddress (&_HashData) +# else +# define _HashDataAddress 0 +# endif // CC_Hash + +# if CC_HMAC + +# include "HMAC_fp.h" + +typedef TPM_RC(HMAC_Entry)(HMAC_In* in, HMAC_Out* out); + +typedef const struct +{ + HMAC_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[2]; + BYTE types[6]; +} HMAC_COMMAND_DESCRIPTOR_t; + +HMAC_COMMAND_DESCRIPTOR_t _HMACData = { + /* entry */ &TPM2_HMAC, + /* inSize */ (UINT16)(sizeof(HMAC_In)), + /* outSize */ (UINT16)(sizeof(HMAC_Out)), + /* offsetOfTypes */ offsetof(HMAC_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(HMAC_In, buffer)), (UINT16)(offsetof(HMAC_In, hashAlg))}, + /* types */ + {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_MAX_BUFFER_P_UNMARSHAL, + TPMI_ALG_HASH_P_UNMARSHAL + ADD_FLAG, + END_OF_LIST, + TPM2B_DIGEST_P_MARSHAL, + END_OF_LIST}}; + +# define _HMACDataAddress (&_HMACData) +# else +# define _HMACDataAddress 0 +# endif // CC_HMAC + +# if CC_MAC + +# include "MAC_fp.h" + +typedef TPM_RC(MAC_Entry)(MAC_In* in, MAC_Out* out); + +typedef const struct +{ + MAC_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[2]; + BYTE types[6]; +} MAC_COMMAND_DESCRIPTOR_t; + +MAC_COMMAND_DESCRIPTOR_t _MACData = { + /* entry */ &TPM2_MAC, + /* inSize */ (UINT16)(sizeof(MAC_In)), + /* outSize */ (UINT16)(sizeof(MAC_Out)), + /* offsetOfTypes */ offsetof(MAC_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(MAC_In, buffer)), (UINT16)(offsetof(MAC_In, inScheme))}, + /* types */ + {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_MAX_BUFFER_P_UNMARSHAL, + TPMI_ALG_MAC_SCHEME_P_UNMARSHAL + ADD_FLAG, + END_OF_LIST, + TPM2B_DIGEST_P_MARSHAL, + END_OF_LIST}}; + +# define _MACDataAddress (&_MACData) +# else +# define _MACDataAddress 0 +# endif // CC_MAC + +# if CC_GetRandom + +# include "GetRandom_fp.h" + +typedef TPM_RC(GetRandom_Entry)(GetRandom_In* in, GetRandom_Out* out); + +typedef const struct +{ + GetRandom_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[4]; +} GetRandom_COMMAND_DESCRIPTOR_t; + +GetRandom_COMMAND_DESCRIPTOR_t _GetRandomData = { + /* entry */ &TPM2_GetRandom, + /* inSize */ (UINT16)(sizeof(GetRandom_In)), + /* outSize */ (UINT16)(sizeof(GetRandom_Out)), + /* offsetOfTypes */ offsetof(GetRandom_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets; + /* types */ + {UINT16_P_UNMARSHAL, END_OF_LIST, TPM2B_DIGEST_P_MARSHAL, END_OF_LIST}}; + +# define _GetRandomDataAddress (&_GetRandomData) +# else +# define _GetRandomDataAddress 0 +# endif // CC_GetRandom + +# if CC_StirRandom + +# include "StirRandom_fp.h" + +typedef TPM_RC(StirRandom_Entry)(StirRandom_In* in); + +typedef const struct +{ + StirRandom_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[3]; +} StirRandom_COMMAND_DESCRIPTOR_t; + +StirRandom_COMMAND_DESCRIPTOR_t _StirRandomData = { + /* entry */ &TPM2_StirRandom, + /* inSize */ (UINT16)(sizeof(StirRandom_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(StirRandom_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets; + /* types */ {TPM2B_SENSITIVE_DATA_P_UNMARSHAL, END_OF_LIST, END_OF_LIST}}; + +# define _StirRandomDataAddress (&_StirRandomData) +# else +# define _StirRandomDataAddress 0 +# endif // CC_StirRandom + +# if CC_HMAC_Start + +# include "HMAC_Start_fp.h" + +typedef TPM_RC(HMAC_Start_Entry)(HMAC_Start_In* in, HMAC_Start_Out* out); + +typedef const struct +{ + HMAC_Start_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[2]; + BYTE types[6]; +} HMAC_Start_COMMAND_DESCRIPTOR_t; + +HMAC_Start_COMMAND_DESCRIPTOR_t _HMAC_StartData = { + /* entry */ &TPM2_HMAC_Start, + /* inSize */ (UINT16)(sizeof(HMAC_Start_In)), + /* outSize */ (UINT16)(sizeof(HMAC_Start_Out)), + /* offsetOfTypes */ offsetof(HMAC_Start_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(HMAC_Start_In, auth)), + (UINT16)(offsetof(HMAC_Start_In, hashAlg))}, + /* types */ + {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_AUTH_P_UNMARSHAL, + TPMI_ALG_HASH_P_UNMARSHAL + ADD_FLAG, + END_OF_LIST, + TPMI_DH_OBJECT_H_MARSHAL, + END_OF_LIST}}; + +# define _HMAC_StartDataAddress (&_HMAC_StartData) +# else +# define _HMAC_StartDataAddress 0 +# endif // CC_HMAC_Start + +# if CC_MAC_Start + +# include "MAC_Start_fp.h" + +typedef TPM_RC(MAC_Start_Entry)(MAC_Start_In* in, MAC_Start_Out* out); + +typedef const struct +{ + MAC_Start_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[2]; + BYTE types[6]; +} MAC_Start_COMMAND_DESCRIPTOR_t; + +MAC_Start_COMMAND_DESCRIPTOR_t _MAC_StartData = { + /* entry */ &TPM2_MAC_Start, + /* inSize */ (UINT16)(sizeof(MAC_Start_In)), + /* outSize */ (UINT16)(sizeof(MAC_Start_Out)), + /* offsetOfTypes */ offsetof(MAC_Start_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(MAC_Start_In, auth)), + (UINT16)(offsetof(MAC_Start_In, inScheme))}, + /* types */ + {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_AUTH_P_UNMARSHAL, + TPMI_ALG_MAC_SCHEME_P_UNMARSHAL + ADD_FLAG, + END_OF_LIST, + TPMI_DH_OBJECT_H_MARSHAL, + END_OF_LIST}}; + +# define _MAC_StartDataAddress (&_MAC_StartData) +# else +# define _MAC_StartDataAddress 0 +# endif // CC_MAC_Start + +# if CC_HashSequenceStart + +# include "HashSequenceStart_fp.h" + +typedef TPM_RC(HashSequenceStart_Entry)(HashSequenceStart_In* in, + HashSequenceStart_Out* out); + +typedef const struct +{ + HashSequenceStart_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[5]; +} HashSequenceStart_COMMAND_DESCRIPTOR_t; + +HashSequenceStart_COMMAND_DESCRIPTOR_t _HashSequenceStartData = { + /* entry */ &TPM2_HashSequenceStart, + /* inSize */ (UINT16)(sizeof(HashSequenceStart_In)), + /* outSize */ (UINT16)(sizeof(HashSequenceStart_Out)), + /* offsetOfTypes */ offsetof(HashSequenceStart_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(HashSequenceStart_In, hashAlg))}, + /* types */ + {TPM2B_AUTH_P_UNMARSHAL, + TPMI_ALG_HASH_P_UNMARSHAL + ADD_FLAG, + END_OF_LIST, + TPMI_DH_OBJECT_H_MARSHAL, + END_OF_LIST}}; + +# define _HashSequenceStartDataAddress (&_HashSequenceStartData) +# else +# define _HashSequenceStartDataAddress 0 +# endif // CC_HashSequenceStart + +# if CC_SequenceUpdate + +# include "SequenceUpdate_fp.h" + +typedef TPM_RC(SequenceUpdate_Entry)(SequenceUpdate_In* in); + +typedef const struct +{ + SequenceUpdate_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} SequenceUpdate_COMMAND_DESCRIPTOR_t; + +SequenceUpdate_COMMAND_DESCRIPTOR_t _SequenceUpdateData = { + /* entry */ &TPM2_SequenceUpdate, + /* inSize */ (UINT16)(sizeof(SequenceUpdate_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(SequenceUpdate_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(SequenceUpdate_In, buffer))}, + /* types */ + {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_MAX_BUFFER_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST}}; + +# define _SequenceUpdateDataAddress (&_SequenceUpdateData) +# else +# define _SequenceUpdateDataAddress 0 +# endif // CC_SequenceUpdate + +# if CC_SequenceComplete + +# include "SequenceComplete_fp.h" + +typedef TPM_RC(SequenceComplete_Entry)(SequenceComplete_In* in, + SequenceComplete_Out* out); + +typedef const struct +{ + SequenceComplete_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[7]; +} SequenceComplete_COMMAND_DESCRIPTOR_t; + +SequenceComplete_COMMAND_DESCRIPTOR_t _SequenceCompleteData = { + /* entry */ &TPM2_SequenceComplete, + /* inSize */ (UINT16)(sizeof(SequenceComplete_In)), + /* outSize */ (UINT16)(sizeof(SequenceComplete_Out)), + /* offsetOfTypes */ offsetof(SequenceComplete_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(SequenceComplete_In, buffer)), + (UINT16)(offsetof(SequenceComplete_In, hierarchy)), + (UINT16)(offsetof(SequenceComplete_Out, validation))}, + /* types */ + {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_MAX_BUFFER_P_UNMARSHAL, + TPMI_RH_HIERARCHY_P_UNMARSHAL + ADD_FLAG, + END_OF_LIST, + TPM2B_DIGEST_P_MARSHAL, + TPMT_TK_HASHCHECK_P_MARSHAL, + END_OF_LIST}}; + +# define _SequenceCompleteDataAddress (&_SequenceCompleteData) +# else +# define _SequenceCompleteDataAddress 0 +# endif // CC_SequenceComplete + +# if CC_EventSequenceComplete + +# include "EventSequenceComplete_fp.h" + +typedef TPM_RC(EventSequenceComplete_Entry)(EventSequenceComplete_In* in, + EventSequenceComplete_Out* out); + +typedef const struct +{ + EventSequenceComplete_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[2]; + BYTE types[6]; +} EventSequenceComplete_COMMAND_DESCRIPTOR_t; + +EventSequenceComplete_COMMAND_DESCRIPTOR_t _EventSequenceCompleteData = { + /* entry */ &TPM2_EventSequenceComplete, + /* inSize */ (UINT16)(sizeof(EventSequenceComplete_In)), + /* outSize */ (UINT16)(sizeof(EventSequenceComplete_Out)), + /* offsetOfTypes */ offsetof(EventSequenceComplete_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(EventSequenceComplete_In, sequenceHandle)), + (UINT16)(offsetof(EventSequenceComplete_In, buffer))}, + /* types */ + {TPMI_DH_PCR_H_UNMARSHAL + ADD_FLAG, + TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_MAX_BUFFER_P_UNMARSHAL, + END_OF_LIST, + TPML_DIGEST_VALUES_P_MARSHAL, + END_OF_LIST}}; + +# define _EventSequenceCompleteDataAddress (&_EventSequenceCompleteData) +# else +# define _EventSequenceCompleteDataAddress 0 +# endif // CC_EventSequenceComplete + +# if CC_Certify + +# include "Certify_fp.h" + +typedef TPM_RC(Certify_Entry)(Certify_In* in, Certify_Out* out); + +typedef const struct +{ + Certify_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[4]; + BYTE types[8]; +} Certify_COMMAND_DESCRIPTOR_t; + +Certify_COMMAND_DESCRIPTOR_t _CertifyData = { + /* entry */ &TPM2_Certify, + /* inSize */ (UINT16)(sizeof(Certify_In)), + /* outSize */ (UINT16)(sizeof(Certify_Out)), + /* offsetOfTypes */ offsetof(Certify_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(Certify_In, signHandle)), + (UINT16)(offsetof(Certify_In, qualifyingData)), + (UINT16)(offsetof(Certify_In, inScheme)), + (UINT16)(offsetof(Certify_Out, signature))}, + /* types */ + {TPMI_DH_OBJECT_H_UNMARSHAL, + TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG, + TPM2B_DATA_P_UNMARSHAL, + TPMT_SIG_SCHEME_P_UNMARSHAL + ADD_FLAG, + END_OF_LIST, + TPM2B_ATTEST_P_MARSHAL, + TPMT_SIGNATURE_P_MARSHAL, + END_OF_LIST}}; + +# define _CertifyDataAddress (&_CertifyData) +# else +# define _CertifyDataAddress 0 +# endif // CC_Certify + +# if CC_CertifyCreation + +# include "CertifyCreation_fp.h" + +typedef TPM_RC(CertifyCreation_Entry)(CertifyCreation_In* in, + CertifyCreation_Out* out); + +typedef const struct +{ + CertifyCreation_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[6]; + BYTE types[10]; +} CertifyCreation_COMMAND_DESCRIPTOR_t; + +CertifyCreation_COMMAND_DESCRIPTOR_t _CertifyCreationData = { + /* entry */ &TPM2_CertifyCreation, + /* inSize */ (UINT16)(sizeof(CertifyCreation_In)), + /* outSize */ (UINT16)(sizeof(CertifyCreation_Out)), + /* offsetOfTypes */ offsetof(CertifyCreation_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(CertifyCreation_In, objectHandle)), + (UINT16)(offsetof(CertifyCreation_In, qualifyingData)), + (UINT16)(offsetof(CertifyCreation_In, creationHash)), + (UINT16)(offsetof(CertifyCreation_In, inScheme)), + (UINT16)(offsetof(CertifyCreation_In, creationTicket)), + (UINT16)(offsetof(CertifyCreation_Out, signature))}, + /* types */ + {TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG, + TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_DATA_P_UNMARSHAL, + TPM2B_DIGEST_P_UNMARSHAL, + TPMT_SIG_SCHEME_P_UNMARSHAL + ADD_FLAG, + TPMT_TK_CREATION_P_UNMARSHAL, + END_OF_LIST, + TPM2B_ATTEST_P_MARSHAL, + TPMT_SIGNATURE_P_MARSHAL, + END_OF_LIST}}; + +# define _CertifyCreationDataAddress (&_CertifyCreationData) +# else +# define _CertifyCreationDataAddress 0 +# endif // CC_CertifyCreation + +# if CC_Quote + +# include "Quote_fp.h" + +typedef TPM_RC(Quote_Entry)(Quote_In* in, Quote_Out* out); + +typedef const struct +{ + Quote_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[4]; + BYTE types[8]; +} Quote_COMMAND_DESCRIPTOR_t; + +Quote_COMMAND_DESCRIPTOR_t _QuoteData = { + /* entry */ &TPM2_Quote, + /* inSize */ (UINT16)(sizeof(Quote_In)), + /* outSize */ (UINT16)(sizeof(Quote_Out)), + /* offsetOfTypes */ offsetof(Quote_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(Quote_In, qualifyingData)), + (UINT16)(offsetof(Quote_In, inScheme)), + (UINT16)(offsetof(Quote_In, PCRselect)), + (UINT16)(offsetof(Quote_Out, signature))}, + /* types */ + {TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG, + TPM2B_DATA_P_UNMARSHAL, + TPMT_SIG_SCHEME_P_UNMARSHAL + ADD_FLAG, + TPML_PCR_SELECTION_P_UNMARSHAL, + END_OF_LIST, + TPM2B_ATTEST_P_MARSHAL, + TPMT_SIGNATURE_P_MARSHAL, + END_OF_LIST}}; + +# define _QuoteDataAddress (&_QuoteData) +# else +# define _QuoteDataAddress 0 +# endif // CC_Quote + +# if CC_GetSessionAuditDigest + +# include "GetSessionAuditDigest_fp.h" + +typedef TPM_RC(GetSessionAuditDigest_Entry)(GetSessionAuditDigest_In* in, + GetSessionAuditDigest_Out* out); + +typedef const struct +{ + GetSessionAuditDigest_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[5]; + BYTE types[9]; +} GetSessionAuditDigest_COMMAND_DESCRIPTOR_t; + +GetSessionAuditDigest_COMMAND_DESCRIPTOR_t _GetSessionAuditDigestData = { + /* entry */ &TPM2_GetSessionAuditDigest, + /* inSize */ (UINT16)(sizeof(GetSessionAuditDigest_In)), + /* outSize */ (UINT16)(sizeof(GetSessionAuditDigest_Out)), + /* offsetOfTypes */ offsetof(GetSessionAuditDigest_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(GetSessionAuditDigest_In, signHandle)), + (UINT16)(offsetof(GetSessionAuditDigest_In, sessionHandle)), + (UINT16)(offsetof(GetSessionAuditDigest_In, qualifyingData)), + (UINT16)(offsetof(GetSessionAuditDigest_In, inScheme)), + (UINT16)(offsetof(GetSessionAuditDigest_Out, signature))}, + /* types */ + {TPMI_RH_ENDORSEMENT_H_UNMARSHAL, + TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG, + TPMI_SH_HMAC_H_UNMARSHAL, + TPM2B_DATA_P_UNMARSHAL, + TPMT_SIG_SCHEME_P_UNMARSHAL + ADD_FLAG, + END_OF_LIST, + TPM2B_ATTEST_P_MARSHAL, + TPMT_SIGNATURE_P_MARSHAL, + END_OF_LIST}}; + +# define _GetSessionAuditDigestDataAddress (&_GetSessionAuditDigestData) +# else +# define _GetSessionAuditDigestDataAddress 0 +# endif // CC_GetSessionAuditDigest + +# if CC_GetCommandAuditDigest + +# include "GetCommandAuditDigest_fp.h" + +typedef TPM_RC(GetCommandAuditDigest_Entry)(GetCommandAuditDigest_In* in, + GetCommandAuditDigest_Out* out); + +typedef const struct +{ + GetCommandAuditDigest_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[4]; + BYTE types[8]; +} GetCommandAuditDigest_COMMAND_DESCRIPTOR_t; + +GetCommandAuditDigest_COMMAND_DESCRIPTOR_t _GetCommandAuditDigestData = { + /* entry */ &TPM2_GetCommandAuditDigest, + /* inSize */ (UINT16)(sizeof(GetCommandAuditDigest_In)), + /* outSize */ (UINT16)(sizeof(GetCommandAuditDigest_Out)), + /* offsetOfTypes */ offsetof(GetCommandAuditDigest_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(GetCommandAuditDigest_In, signHandle)), + (UINT16)(offsetof(GetCommandAuditDigest_In, qualifyingData)), + (UINT16)(offsetof(GetCommandAuditDigest_In, inScheme)), + (UINT16)(offsetof(GetCommandAuditDigest_Out, signature))}, + /* types */ + {TPMI_RH_ENDORSEMENT_H_UNMARSHAL, + TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG, + TPM2B_DATA_P_UNMARSHAL, + TPMT_SIG_SCHEME_P_UNMARSHAL + ADD_FLAG, + END_OF_LIST, + TPM2B_ATTEST_P_MARSHAL, + TPMT_SIGNATURE_P_MARSHAL, + END_OF_LIST}}; + +# define _GetCommandAuditDigestDataAddress (&_GetCommandAuditDigestData) +# else +# define _GetCommandAuditDigestDataAddress 0 +# endif // CC_GetCommandAuditDigest + +# if CC_GetTime + +# include "GetTime_fp.h" + +typedef TPM_RC(GetTime_Entry)(GetTime_In* in, GetTime_Out* out); + +typedef const struct +{ + GetTime_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[4]; + BYTE types[8]; +} GetTime_COMMAND_DESCRIPTOR_t; + +GetTime_COMMAND_DESCRIPTOR_t _GetTimeData = { + /* entry */ &TPM2_GetTime, + /* inSize */ (UINT16)(sizeof(GetTime_In)), + /* outSize */ (UINT16)(sizeof(GetTime_Out)), + /* offsetOfTypes */ offsetof(GetTime_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(GetTime_In, signHandle)), + (UINT16)(offsetof(GetTime_In, qualifyingData)), + (UINT16)(offsetof(GetTime_In, inScheme)), + (UINT16)(offsetof(GetTime_Out, signature))}, + /* types */ + {TPMI_RH_ENDORSEMENT_H_UNMARSHAL, + TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG, + TPM2B_DATA_P_UNMARSHAL, + TPMT_SIG_SCHEME_P_UNMARSHAL + ADD_FLAG, + END_OF_LIST, + TPM2B_ATTEST_P_MARSHAL, + TPMT_SIGNATURE_P_MARSHAL, + END_OF_LIST}}; + +# define _GetTimeDataAddress (&_GetTimeData) +# else +# define _GetTimeDataAddress 0 +# endif // CC_GetTime + +# if CC_CertifyX509 + +# include "CertifyX509_fp.h" + +typedef TPM_RC(CertifyX509_Entry)(CertifyX509_In* in, CertifyX509_Out* out); + +typedef const struct +{ + CertifyX509_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[6]; + BYTE types[10]; +} CertifyX509_COMMAND_DESCRIPTOR_t; + +CertifyX509_COMMAND_DESCRIPTOR_t _CertifyX509Data = { + /* entry */ &TPM2_CertifyX509, + /* inSize */ (UINT16)(sizeof(CertifyX509_In)), + /* outSize */ (UINT16)(sizeof(CertifyX509_Out)), + /* offsetOfTypes */ offsetof(CertifyX509_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(CertifyX509_In, signHandle)), + (UINT16)(offsetof(CertifyX509_In, reserved)), + (UINT16)(offsetof(CertifyX509_In, inScheme)), + (UINT16)(offsetof(CertifyX509_In, partialCertificate)), + (UINT16)(offsetof(CertifyX509_Out, tbsDigest)), + (UINT16)(offsetof(CertifyX509_Out, signature))}, + /* types */ + {TPMI_DH_OBJECT_H_UNMARSHAL, + TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG, + TPM2B_DATA_P_UNMARSHAL, + TPMT_SIG_SCHEME_P_UNMARSHAL + ADD_FLAG, + TPM2B_MAX_BUFFER_P_UNMARSHAL, + END_OF_LIST, + TPM2B_MAX_BUFFER_P_MARSHAL, + TPM2B_DIGEST_P_MARSHAL, + TPMT_SIGNATURE_P_MARSHAL, + END_OF_LIST}}; + +# define _CertifyX509DataAddress (&_CertifyX509Data) +# else +# define _CertifyX509DataAddress 0 +# endif // CC_CertifyX509 + +# if CC_Commit + +# include "Commit_fp.h" + +typedef TPM_RC(Commit_Entry)(Commit_In* in, Commit_Out* out); + +typedef const struct +{ + Commit_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[6]; + BYTE types[10]; +} Commit_COMMAND_DESCRIPTOR_t; + +Commit_COMMAND_DESCRIPTOR_t _CommitData = { + /* entry */ &TPM2_Commit, + /* inSize */ (UINT16)(sizeof(Commit_In)), + /* outSize */ (UINT16)(sizeof(Commit_Out)), + /* offsetOfTypes */ offsetof(Commit_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(Commit_In, P1)), + (UINT16)(offsetof(Commit_In, s2)), + (UINT16)(offsetof(Commit_In, y2)), + (UINT16)(offsetof(Commit_Out, L)), + (UINT16)(offsetof(Commit_Out, E)), + (UINT16)(offsetof(Commit_Out, counter))}, + /* types */ + {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_ECC_POINT_P_UNMARSHAL, + TPM2B_SENSITIVE_DATA_P_UNMARSHAL, + TPM2B_ECC_PARAMETER_P_UNMARSHAL, + END_OF_LIST, + TPM2B_ECC_POINT_P_MARSHAL, + TPM2B_ECC_POINT_P_MARSHAL, + TPM2B_ECC_POINT_P_MARSHAL, + UINT16_P_MARSHAL, + END_OF_LIST}}; + +# define _CommitDataAddress (&_CommitData) +# else +# define _CommitDataAddress 0 +# endif // CC_Commit + +# if CC_EC_Ephemeral + +# include "EC_Ephemeral_fp.h" + +typedef TPM_RC(EC_Ephemeral_Entry)(EC_Ephemeral_In* in, EC_Ephemeral_Out* out); + +typedef const struct +{ + EC_Ephemeral_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[5]; +} EC_Ephemeral_COMMAND_DESCRIPTOR_t; + +EC_Ephemeral_COMMAND_DESCRIPTOR_t _EC_EphemeralData = { + /* entry */ &TPM2_EC_Ephemeral, + /* inSize */ (UINT16)(sizeof(EC_Ephemeral_In)), + /* outSize */ (UINT16)(sizeof(EC_Ephemeral_Out)), + /* offsetOfTypes */ offsetof(EC_Ephemeral_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(EC_Ephemeral_Out, counter))}, + /* types */ + {TPMI_ECC_CURVE_P_UNMARSHAL, + END_OF_LIST, + TPM2B_ECC_POINT_P_MARSHAL, + UINT16_P_MARSHAL, + END_OF_LIST}}; + +# define _EC_EphemeralDataAddress (&_EC_EphemeralData) +# else +# define _EC_EphemeralDataAddress 0 +# endif // CC_EC_Ephemeral + +# if CC_VerifySignature + +# include "VerifySignature_fp.h" + +typedef TPM_RC(VerifySignature_Entry)(VerifySignature_In* in, + VerifySignature_Out* out); + +typedef const struct +{ + VerifySignature_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[2]; + BYTE types[6]; +} VerifySignature_COMMAND_DESCRIPTOR_t; + +VerifySignature_COMMAND_DESCRIPTOR_t _VerifySignatureData = { + /* entry */ &TPM2_VerifySignature, + /* inSize */ (UINT16)(sizeof(VerifySignature_In)), + /* outSize */ (UINT16)(sizeof(VerifySignature_Out)), + /* offsetOfTypes */ offsetof(VerifySignature_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(VerifySignature_In, digest)), + (UINT16)(offsetof(VerifySignature_In, signature))}, + /* types */ + {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_DIGEST_P_UNMARSHAL, + TPMT_SIGNATURE_P_UNMARSHAL, + END_OF_LIST, + TPMT_TK_VERIFIED_P_MARSHAL, + END_OF_LIST}}; + +# define _VerifySignatureDataAddress (&_VerifySignatureData) +# else +# define _VerifySignatureDataAddress 0 +# endif // CC_VerifySignature + +# if CC_Sign + +# include "Sign_fp.h" + +typedef TPM_RC(Sign_Entry)(Sign_In* in, Sign_Out* out); + +typedef const struct +{ + Sign_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[7]; +} Sign_COMMAND_DESCRIPTOR_t; + +Sign_COMMAND_DESCRIPTOR_t _SignData = { + /* entry */ &TPM2_Sign, + /* inSize */ (UINT16)(sizeof(Sign_In)), + /* outSize */ (UINT16)(sizeof(Sign_Out)), + /* offsetOfTypes */ offsetof(Sign_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(Sign_In, digest)), + (UINT16)(offsetof(Sign_In, inScheme)), + (UINT16)(offsetof(Sign_In, validation))}, + /* types */ + {TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_DIGEST_P_UNMARSHAL, + TPMT_SIG_SCHEME_P_UNMARSHAL + ADD_FLAG, + TPMT_TK_HASHCHECK_P_UNMARSHAL, + END_OF_LIST, + TPMT_SIGNATURE_P_MARSHAL, + END_OF_LIST}}; + +# define _SignDataAddress (&_SignData) +# else +# define _SignDataAddress 0 +# endif // CC_Sign + +# if CC_SetCommandCodeAuditStatus + +# include "SetCommandCodeAuditStatus_fp.h" + +typedef TPM_RC(SetCommandCodeAuditStatus_Entry)(SetCommandCodeAuditStatus_In* in); + +typedef const struct +{ + SetCommandCodeAuditStatus_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[6]; +} SetCommandCodeAuditStatus_COMMAND_DESCRIPTOR_t; + +SetCommandCodeAuditStatus_COMMAND_DESCRIPTOR_t _SetCommandCodeAuditStatusData = { + /* entry */ &TPM2_SetCommandCodeAuditStatus, + /* inSize */ (UINT16)(sizeof(SetCommandCodeAuditStatus_In)), + /* outSize */ 0, + /* offsetOfTypes */ + offsetof(SetCommandCodeAuditStatus_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(SetCommandCodeAuditStatus_In, auditAlg)), + (UINT16)(offsetof(SetCommandCodeAuditStatus_In, setList)), + (UINT16)(offsetof(SetCommandCodeAuditStatus_In, clearList))}, + /* types */ + {TPMI_RH_PROVISION_H_UNMARSHAL, + TPMI_ALG_HASH_P_UNMARSHAL + ADD_FLAG, + TPML_CC_P_UNMARSHAL, + TPML_CC_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST}}; + +# define _SetCommandCodeAuditStatusDataAddress (&_SetCommandCodeAuditStatusData) +# else +# define _SetCommandCodeAuditStatusDataAddress 0 +# endif // CC_SetCommandCodeAuditStatus + +# if CC_PCR_Extend + +# include "PCR_Extend_fp.h" + +typedef TPM_RC(PCR_Extend_Entry)(PCR_Extend_In* in); + +typedef const struct +{ + PCR_Extend_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} PCR_Extend_COMMAND_DESCRIPTOR_t; + +PCR_Extend_COMMAND_DESCRIPTOR_t _PCR_ExtendData = { + /* entry */ &TPM2_PCR_Extend, + /* inSize */ (UINT16)(sizeof(PCR_Extend_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PCR_Extend_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(PCR_Extend_In, digests))}, + /* types */ + {TPMI_DH_PCR_H_UNMARSHAL + ADD_FLAG, + TPML_DIGEST_VALUES_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST}}; + +# define _PCR_ExtendDataAddress (&_PCR_ExtendData) +# else +# define _PCR_ExtendDataAddress 0 +# endif // CC_PCR_Extend + +# if CC_PCR_Event + +# include "PCR_Event_fp.h" + +typedef TPM_RC(PCR_Event_Entry)(PCR_Event_In* in, PCR_Event_Out* out); + +typedef const struct +{ + PCR_Event_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[5]; +} PCR_Event_COMMAND_DESCRIPTOR_t; + +PCR_Event_COMMAND_DESCRIPTOR_t _PCR_EventData = { + /* entry */ &TPM2_PCR_Event, + /* inSize */ (UINT16)(sizeof(PCR_Event_In)), + /* outSize */ (UINT16)(sizeof(PCR_Event_Out)), + /* offsetOfTypes */ offsetof(PCR_Event_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(PCR_Event_In, eventData))}, + /* types */ + {TPMI_DH_PCR_H_UNMARSHAL + ADD_FLAG, + TPM2B_EVENT_P_UNMARSHAL, + END_OF_LIST, + TPML_DIGEST_VALUES_P_MARSHAL, + END_OF_LIST}}; + +# define _PCR_EventDataAddress (&_PCR_EventData) +# else +# define _PCR_EventDataAddress 0 +# endif // CC_PCR_Event + +# if CC_PCR_Read + +# include "PCR_Read_fp.h" + +typedef TPM_RC(PCR_Read_Entry)(PCR_Read_In* in, PCR_Read_Out* out); + +typedef const struct +{ + PCR_Read_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[2]; + BYTE types[6]; +} PCR_Read_COMMAND_DESCRIPTOR_t; + +PCR_Read_COMMAND_DESCRIPTOR_t _PCR_ReadData = { + /* entry */ &TPM2_PCR_Read, + /* inSize */ (UINT16)(sizeof(PCR_Read_In)), + /* outSize */ (UINT16)(sizeof(PCR_Read_Out)), + /* offsetOfTypes */ offsetof(PCR_Read_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(PCR_Read_Out, pcrSelectionOut)), + (UINT16)(offsetof(PCR_Read_Out, pcrValues))}, + /* types */ + {TPML_PCR_SELECTION_P_UNMARSHAL, + END_OF_LIST, + UINT32_P_MARSHAL, + TPML_PCR_SELECTION_P_MARSHAL, + TPML_DIGEST_P_MARSHAL, + END_OF_LIST}}; + +# define _PCR_ReadDataAddress (&_PCR_ReadData) +# else +# define _PCR_ReadDataAddress 0 +# endif // CC_PCR_Read + +# if CC_PCR_Allocate + +# include "PCR_Allocate_fp.h" + +typedef TPM_RC(PCR_Allocate_Entry)(PCR_Allocate_In* in, PCR_Allocate_Out* out); + +typedef const struct +{ + PCR_Allocate_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[4]; + BYTE types[8]; +} PCR_Allocate_COMMAND_DESCRIPTOR_t; + +PCR_Allocate_COMMAND_DESCRIPTOR_t _PCR_AllocateData = { + /* entry */ &TPM2_PCR_Allocate, + /* inSize */ (UINT16)(sizeof(PCR_Allocate_In)), + /* outSize */ (UINT16)(sizeof(PCR_Allocate_Out)), + /* offsetOfTypes */ offsetof(PCR_Allocate_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(PCR_Allocate_In, pcrAllocation)), + (UINT16)(offsetof(PCR_Allocate_Out, maxPCR)), + (UINT16)(offsetof(PCR_Allocate_Out, sizeNeeded)), + (UINT16)(offsetof(PCR_Allocate_Out, sizeAvailable))}, + /* types */ + {TPMI_RH_PLATFORM_H_UNMARSHAL, + TPML_PCR_SELECTION_P_UNMARSHAL, + END_OF_LIST, + TPMI_YES_NO_P_MARSHAL, + UINT32_P_MARSHAL, + UINT32_P_MARSHAL, + UINT32_P_MARSHAL, + END_OF_LIST}}; + +# define _PCR_AllocateDataAddress (&_PCR_AllocateData) +# else +# define _PCR_AllocateDataAddress 0 +# endif // CC_PCR_Allocate + +# if CC_PCR_SetAuthPolicy + +# include "PCR_SetAuthPolicy_fp.h" + +typedef TPM_RC(PCR_SetAuthPolicy_Entry)(PCR_SetAuthPolicy_In* in); + +typedef const struct +{ + PCR_SetAuthPolicy_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[6]; +} PCR_SetAuthPolicy_COMMAND_DESCRIPTOR_t; + +PCR_SetAuthPolicy_COMMAND_DESCRIPTOR_t _PCR_SetAuthPolicyData = { + /* entry */ &TPM2_PCR_SetAuthPolicy, + /* inSize */ (UINT16)(sizeof(PCR_SetAuthPolicy_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PCR_SetAuthPolicy_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(PCR_SetAuthPolicy_In, authPolicy)), + (UINT16)(offsetof(PCR_SetAuthPolicy_In, hashAlg)), + (UINT16)(offsetof(PCR_SetAuthPolicy_In, pcrNum))}, + /* types */ + {TPMI_RH_PLATFORM_H_UNMARSHAL, + TPM2B_DIGEST_P_UNMARSHAL, + TPMI_ALG_HASH_P_UNMARSHAL + ADD_FLAG, + TPMI_DH_PCR_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST}}; + +# define _PCR_SetAuthPolicyDataAddress (&_PCR_SetAuthPolicyData) +# else +# define _PCR_SetAuthPolicyDataAddress 0 +# endif // CC_PCR_SetAuthPolicy + +# if CC_PCR_SetAuthValue + +# include "PCR_SetAuthValue_fp.h" + +typedef TPM_RC(PCR_SetAuthValue_Entry)(PCR_SetAuthValue_In* in); + +typedef const struct +{ + PCR_SetAuthValue_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} PCR_SetAuthValue_COMMAND_DESCRIPTOR_t; + +PCR_SetAuthValue_COMMAND_DESCRIPTOR_t _PCR_SetAuthValueData = { + /* entry */ &TPM2_PCR_SetAuthValue, + /* inSize */ (UINT16)(sizeof(PCR_SetAuthValue_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PCR_SetAuthValue_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(PCR_SetAuthValue_In, auth))}, + /* types */ + {TPMI_DH_PCR_H_UNMARSHAL, TPM2B_DIGEST_P_UNMARSHAL, END_OF_LIST, END_OF_LIST}}; + +# define _PCR_SetAuthValueDataAddress (&_PCR_SetAuthValueData) +# else +# define _PCR_SetAuthValueDataAddress 0 +# endif // CC_PCR_SetAuthValue + +# if CC_PCR_Reset + +# include "PCR_Reset_fp.h" + +typedef TPM_RC(PCR_Reset_Entry)(PCR_Reset_In* in); + +typedef const struct +{ + PCR_Reset_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[3]; +} PCR_Reset_COMMAND_DESCRIPTOR_t; + +PCR_Reset_COMMAND_DESCRIPTOR_t _PCR_ResetData = { + /* entry */ &TPM2_PCR_Reset, + /* inSize */ (UINT16)(sizeof(PCR_Reset_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PCR_Reset_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets; + /* types */ {TPMI_DH_PCR_H_UNMARSHAL, END_OF_LIST, END_OF_LIST}}; + +# define _PCR_ResetDataAddress (&_PCR_ResetData) +# else +# define _PCR_ResetDataAddress 0 +# endif // CC_PCR_Reset + +# if CC_PolicySigned + +# include "PolicySigned_fp.h" + +typedef TPM_RC(PolicySigned_Entry)(PolicySigned_In* in, PolicySigned_Out* out); + +typedef const struct +{ + PolicySigned_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[7]; + BYTE types[11]; +} PolicySigned_COMMAND_DESCRIPTOR_t; + +PolicySigned_COMMAND_DESCRIPTOR_t _PolicySignedData = { + /* entry */ &TPM2_PolicySigned, + /* inSize */ (UINT16)(sizeof(PolicySigned_In)), + /* outSize */ (UINT16)(sizeof(PolicySigned_Out)), + /* offsetOfTypes */ offsetof(PolicySigned_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(PolicySigned_In, policySession)), + (UINT16)(offsetof(PolicySigned_In, nonceTPM)), + (UINT16)(offsetof(PolicySigned_In, cpHashA)), + (UINT16)(offsetof(PolicySigned_In, policyRef)), + (UINT16)(offsetof(PolicySigned_In, expiration)), + (UINT16)(offsetof(PolicySigned_In, auth)), + (UINT16)(offsetof(PolicySigned_Out, policyTicket))}, + /* types */ + {TPMI_DH_OBJECT_H_UNMARSHAL, + TPMI_SH_POLICY_H_UNMARSHAL, + TPM2B_NONCE_P_UNMARSHAL, + TPM2B_DIGEST_P_UNMARSHAL, + TPM2B_NONCE_P_UNMARSHAL, + INT32_P_UNMARSHAL, + TPMT_SIGNATURE_P_UNMARSHAL, + END_OF_LIST, + TPM2B_TIMEOUT_P_MARSHAL, + TPMT_TK_AUTH_P_MARSHAL, + END_OF_LIST}}; + +# define _PolicySignedDataAddress (&_PolicySignedData) +# else +# define _PolicySignedDataAddress 0 +# endif // CC_PolicySigned + +# if CC_PolicySecret + +# include "PolicySecret_fp.h" + +typedef TPM_RC(PolicySecret_Entry)(PolicySecret_In* in, PolicySecret_Out* out); + +typedef const struct +{ + PolicySecret_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[6]; + BYTE types[10]; +} PolicySecret_COMMAND_DESCRIPTOR_t; + +PolicySecret_COMMAND_DESCRIPTOR_t _PolicySecretData = { + /* entry */ &TPM2_PolicySecret, + /* inSize */ (UINT16)(sizeof(PolicySecret_In)), + /* outSize */ (UINT16)(sizeof(PolicySecret_Out)), + /* offsetOfTypes */ offsetof(PolicySecret_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(PolicySecret_In, policySession)), + (UINT16)(offsetof(PolicySecret_In, nonceTPM)), + (UINT16)(offsetof(PolicySecret_In, cpHashA)), + (UINT16)(offsetof(PolicySecret_In, policyRef)), + (UINT16)(offsetof(PolicySecret_In, expiration)), + (UINT16)(offsetof(PolicySecret_Out, policyTicket))}, + /* types */ + {TPMI_DH_ENTITY_H_UNMARSHAL, + TPMI_SH_POLICY_H_UNMARSHAL, + TPM2B_NONCE_P_UNMARSHAL, + TPM2B_DIGEST_P_UNMARSHAL, + TPM2B_NONCE_P_UNMARSHAL, + INT32_P_UNMARSHAL, + END_OF_LIST, + TPM2B_TIMEOUT_P_MARSHAL, + TPMT_TK_AUTH_P_MARSHAL, + END_OF_LIST}}; + +# define _PolicySecretDataAddress (&_PolicySecretData) +# else +# define _PolicySecretDataAddress 0 +# endif // CC_PolicySecret + +# if CC_PolicyTicket + +# include "PolicyTicket_fp.h" + +typedef TPM_RC(PolicyTicket_Entry)(PolicyTicket_In* in); + +typedef const struct +{ + PolicyTicket_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[5]; + BYTE types[8]; +} PolicyTicket_COMMAND_DESCRIPTOR_t; + +PolicyTicket_COMMAND_DESCRIPTOR_t _PolicyTicketData = { + /* entry */ &TPM2_PolicyTicket, + /* inSize */ (UINT16)(sizeof(PolicyTicket_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PolicyTicket_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(PolicyTicket_In, timeout)), + (UINT16)(offsetof(PolicyTicket_In, cpHashA)), + (UINT16)(offsetof(PolicyTicket_In, policyRef)), + (UINT16)(offsetof(PolicyTicket_In, authName)), + (UINT16)(offsetof(PolicyTicket_In, ticket))}, + /* types */ + {TPMI_SH_POLICY_H_UNMARSHAL, + TPM2B_TIMEOUT_P_UNMARSHAL, + TPM2B_DIGEST_P_UNMARSHAL, + TPM2B_NONCE_P_UNMARSHAL, + TPM2B_NAME_P_UNMARSHAL, + TPMT_TK_AUTH_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST}}; + +# define _PolicyTicketDataAddress (&_PolicyTicketData) +# else +# define _PolicyTicketDataAddress 0 +# endif // CC_PolicyTicket + +# if CC_PolicyOR + +# include "PolicyOR_fp.h" + +typedef TPM_RC(PolicyOR_Entry)(PolicyOR_In* in); + +typedef const struct +{ + PolicyOR_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} PolicyOR_COMMAND_DESCRIPTOR_t; + +PolicyOR_COMMAND_DESCRIPTOR_t _PolicyORData = { + /* entry */ &TPM2_PolicyOR, + /* inSize */ (UINT16)(sizeof(PolicyOR_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PolicyOR_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(PolicyOR_In, pHashList))}, + /* types */ + {TPMI_SH_POLICY_H_UNMARSHAL, TPML_DIGEST_P_UNMARSHAL, END_OF_LIST, END_OF_LIST}}; + +# define _PolicyORDataAddress (&_PolicyORData) +# else +# define _PolicyORDataAddress 0 +# endif // CC_PolicyOR + +# if CC_PolicyPCR + +# include "PolicyPCR_fp.h" + +typedef TPM_RC(PolicyPCR_Entry)(PolicyPCR_In* in); + +typedef const struct +{ + PolicyPCR_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[2]; + BYTE types[5]; +} PolicyPCR_COMMAND_DESCRIPTOR_t; + +PolicyPCR_COMMAND_DESCRIPTOR_t _PolicyPCRData = { + /* entry */ &TPM2_PolicyPCR, + /* inSize */ (UINT16)(sizeof(PolicyPCR_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PolicyPCR_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(PolicyPCR_In, pcrDigest)), + (UINT16)(offsetof(PolicyPCR_In, pcrs))}, + /* types */ + {TPMI_SH_POLICY_H_UNMARSHAL, + TPM2B_DIGEST_P_UNMARSHAL, + TPML_PCR_SELECTION_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST}}; + +# define _PolicyPCRDataAddress (&_PolicyPCRData) +# else +# define _PolicyPCRDataAddress 0 +# endif // CC_PolicyPCR + +# if CC_PolicyLocality + +# include "PolicyLocality_fp.h" + +typedef TPM_RC(PolicyLocality_Entry)(PolicyLocality_In* in); + +typedef const struct +{ + PolicyLocality_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} PolicyLocality_COMMAND_DESCRIPTOR_t; + +PolicyLocality_COMMAND_DESCRIPTOR_t _PolicyLocalityData = { + /* entry */ &TPM2_PolicyLocality, + /* inSize */ (UINT16)(sizeof(PolicyLocality_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PolicyLocality_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(PolicyLocality_In, locality))}, + /* types */ + {TPMI_SH_POLICY_H_UNMARSHAL, + TPMA_LOCALITY_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST}}; + +# define _PolicyLocalityDataAddress (&_PolicyLocalityData) +# else +# define _PolicyLocalityDataAddress 0 +# endif // CC_PolicyLocality + +# if CC_PolicyNV + +# include "PolicyNV_fp.h" + +typedef TPM_RC(PolicyNV_Entry)(PolicyNV_In* in); + +typedef const struct +{ + PolicyNV_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[5]; + BYTE types[8]; +} PolicyNV_COMMAND_DESCRIPTOR_t; + +PolicyNV_COMMAND_DESCRIPTOR_t _PolicyNVData = { + /* entry */ &TPM2_PolicyNV, + /* inSize */ (UINT16)(sizeof(PolicyNV_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PolicyNV_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(PolicyNV_In, nvIndex)), + (UINT16)(offsetof(PolicyNV_In, policySession)), + (UINT16)(offsetof(PolicyNV_In, operandB)), + (UINT16)(offsetof(PolicyNV_In, offset)), + (UINT16)(offsetof(PolicyNV_In, operation))}, + /* types */ + {TPMI_RH_NV_AUTH_H_UNMARSHAL, + TPMI_RH_NV_INDEX_H_UNMARSHAL, + TPMI_SH_POLICY_H_UNMARSHAL, + TPM2B_OPERAND_P_UNMARSHAL, + UINT16_P_UNMARSHAL, + TPM_EO_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST}}; + +# define _PolicyNVDataAddress (&_PolicyNVData) +# else +# define _PolicyNVDataAddress 0 +# endif // CC_PolicyNV + +# if CC_PolicyCounterTimer + +# include "PolicyCounterTimer_fp.h" + +typedef TPM_RC(PolicyCounterTimer_Entry)(PolicyCounterTimer_In* in); + +typedef const struct +{ + PolicyCounterTimer_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[6]; +} PolicyCounterTimer_COMMAND_DESCRIPTOR_t; + +PolicyCounterTimer_COMMAND_DESCRIPTOR_t _PolicyCounterTimerData = { + /* entry */ &TPM2_PolicyCounterTimer, + /* inSize */ (UINT16)(sizeof(PolicyCounterTimer_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PolicyCounterTimer_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(PolicyCounterTimer_In, operandB)), + (UINT16)(offsetof(PolicyCounterTimer_In, offset)), + (UINT16)(offsetof(PolicyCounterTimer_In, operation))}, + /* types */ + {TPMI_SH_POLICY_H_UNMARSHAL, + TPM2B_OPERAND_P_UNMARSHAL, + UINT16_P_UNMARSHAL, + TPM_EO_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST}}; + +# define _PolicyCounterTimerDataAddress (&_PolicyCounterTimerData) +# else +# define _PolicyCounterTimerDataAddress 0 +# endif // CC_PolicyCounterTimer + +# if CC_PolicyCommandCode + +# include "PolicyCommandCode_fp.h" + +typedef TPM_RC(PolicyCommandCode_Entry)(PolicyCommandCode_In* in); + +typedef const struct +{ + PolicyCommandCode_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} PolicyCommandCode_COMMAND_DESCRIPTOR_t; + +PolicyCommandCode_COMMAND_DESCRIPTOR_t _PolicyCommandCodeData = { + /* entry */ &TPM2_PolicyCommandCode, + /* inSize */ (UINT16)(sizeof(PolicyCommandCode_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PolicyCommandCode_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(PolicyCommandCode_In, code))}, + /* types */ + {TPMI_SH_POLICY_H_UNMARSHAL, TPM_CC_P_UNMARSHAL, END_OF_LIST, END_OF_LIST}}; + +# define _PolicyCommandCodeDataAddress (&_PolicyCommandCodeData) +# else +# define _PolicyCommandCodeDataAddress 0 +# endif // CC_PolicyCommandCode + +# if CC_PolicyPhysicalPresence + +# include "PolicyPhysicalPresence_fp.h" + +typedef TPM_RC(PolicyPhysicalPresence_Entry)(PolicyPhysicalPresence_In* in); + +typedef const struct +{ + PolicyPhysicalPresence_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[3]; +} PolicyPhysicalPresence_COMMAND_DESCRIPTOR_t; + +PolicyPhysicalPresence_COMMAND_DESCRIPTOR_t _PolicyPhysicalPresenceData = { + /* entry */ &TPM2_PolicyPhysicalPresence, + /* inSize */ (UINT16)(sizeof(PolicyPhysicalPresence_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PolicyPhysicalPresence_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets; + /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, END_OF_LIST, END_OF_LIST}}; + +# define _PolicyPhysicalPresenceDataAddress (&_PolicyPhysicalPresenceData) +# else +# define _PolicyPhysicalPresenceDataAddress 0 +# endif // CC_PolicyPhysicalPresence + +# if CC_PolicyCpHash + +# include "PolicyCpHash_fp.h" + +typedef TPM_RC(PolicyCpHash_Entry)(PolicyCpHash_In* in); + +typedef const struct +{ + PolicyCpHash_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} PolicyCpHash_COMMAND_DESCRIPTOR_t; + +PolicyCpHash_COMMAND_DESCRIPTOR_t _PolicyCpHashData = { + /* entry */ &TPM2_PolicyCpHash, + /* inSize */ (UINT16)(sizeof(PolicyCpHash_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PolicyCpHash_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(PolicyCpHash_In, cpHashA))}, + /* types */ + {TPMI_SH_POLICY_H_UNMARSHAL, TPM2B_DIGEST_P_UNMARSHAL, END_OF_LIST, END_OF_LIST}}; + +# define _PolicyCpHashDataAddress (&_PolicyCpHashData) +# else +# define _PolicyCpHashDataAddress 0 +# endif // CC_PolicyCpHash + +# if CC_PolicyNameHash + +# include "PolicyNameHash_fp.h" + +typedef TPM_RC(PolicyNameHash_Entry)(PolicyNameHash_In* in); + +typedef const struct +{ + PolicyNameHash_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} PolicyNameHash_COMMAND_DESCRIPTOR_t; + +PolicyNameHash_COMMAND_DESCRIPTOR_t _PolicyNameHashData = { + /* entry */ &TPM2_PolicyNameHash, + /* inSize */ (UINT16)(sizeof(PolicyNameHash_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PolicyNameHash_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(PolicyNameHash_In, nameHash))}, + /* types */ + {TPMI_SH_POLICY_H_UNMARSHAL, TPM2B_DIGEST_P_UNMARSHAL, END_OF_LIST, END_OF_LIST}}; + +# define _PolicyNameHashDataAddress (&_PolicyNameHashData) +# else +# define _PolicyNameHashDataAddress 0 +# endif // CC_PolicyNameHash + +# if CC_PolicyDuplicationSelect + +# include "PolicyDuplicationSelect_fp.h" + +typedef TPM_RC(PolicyDuplicationSelect_Entry)(PolicyDuplicationSelect_In* in); + +typedef const struct +{ + PolicyDuplicationSelect_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[6]; +} PolicyDuplicationSelect_COMMAND_DESCRIPTOR_t; + +PolicyDuplicationSelect_COMMAND_DESCRIPTOR_t _PolicyDuplicationSelectData = { + /* entry */ &TPM2_PolicyDuplicationSelect, + /* inSize */ (UINT16)(sizeof(PolicyDuplicationSelect_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PolicyDuplicationSelect_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(PolicyDuplicationSelect_In, objectName)), + (UINT16)(offsetof(PolicyDuplicationSelect_In, newParentName)), + (UINT16)(offsetof(PolicyDuplicationSelect_In, includeObject))}, + /* types */ + {TPMI_SH_POLICY_H_UNMARSHAL, + TPM2B_NAME_P_UNMARSHAL, + TPM2B_NAME_P_UNMARSHAL, + TPMI_YES_NO_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST}}; + +# define _PolicyDuplicationSelectDataAddress (&_PolicyDuplicationSelectData) +# else +# define _PolicyDuplicationSelectDataAddress 0 +# endif // CC_PolicyDuplicationSelect + +# if CC_PolicyAuthorize + +# include "PolicyAuthorize_fp.h" + +typedef TPM_RC(PolicyAuthorize_Entry)(PolicyAuthorize_In* in); + +typedef const struct +{ + PolicyAuthorize_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[4]; + BYTE types[7]; +} PolicyAuthorize_COMMAND_DESCRIPTOR_t; + +PolicyAuthorize_COMMAND_DESCRIPTOR_t _PolicyAuthorizeData = { + /* entry */ &TPM2_PolicyAuthorize, + /* inSize */ (UINT16)(sizeof(PolicyAuthorize_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PolicyAuthorize_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(PolicyAuthorize_In, approvedPolicy)), + (UINT16)(offsetof(PolicyAuthorize_In, policyRef)), + (UINT16)(offsetof(PolicyAuthorize_In, keySign)), + (UINT16)(offsetof(PolicyAuthorize_In, checkTicket))}, + /* types */ + {TPMI_SH_POLICY_H_UNMARSHAL, + TPM2B_DIGEST_P_UNMARSHAL, + TPM2B_NONCE_P_UNMARSHAL, + TPM2B_NAME_P_UNMARSHAL, + TPMT_TK_VERIFIED_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST}}; + +# define _PolicyAuthorizeDataAddress (&_PolicyAuthorizeData) +# else +# define _PolicyAuthorizeDataAddress 0 +# endif // CC_PolicyAuthorize + +# if CC_PolicyAuthValue + +# include "PolicyAuthValue_fp.h" + +typedef TPM_RC(PolicyAuthValue_Entry)(PolicyAuthValue_In* in); + +typedef const struct +{ + PolicyAuthValue_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[3]; +} PolicyAuthValue_COMMAND_DESCRIPTOR_t; + +PolicyAuthValue_COMMAND_DESCRIPTOR_t _PolicyAuthValueData = { + /* entry */ &TPM2_PolicyAuthValue, + /* inSize */ (UINT16)(sizeof(PolicyAuthValue_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PolicyAuthValue_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets; + /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, END_OF_LIST, END_OF_LIST}}; + +# define _PolicyAuthValueDataAddress (&_PolicyAuthValueData) +# else +# define _PolicyAuthValueDataAddress 0 +# endif // CC_PolicyAuthValue + +# if CC_PolicyPassword + +# include "PolicyPassword_fp.h" + +typedef TPM_RC(PolicyPassword_Entry)(PolicyPassword_In* in); + +typedef const struct +{ + PolicyPassword_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[3]; +} PolicyPassword_COMMAND_DESCRIPTOR_t; + +PolicyPassword_COMMAND_DESCRIPTOR_t _PolicyPasswordData = { + /* entry */ &TPM2_PolicyPassword, + /* inSize */ (UINT16)(sizeof(PolicyPassword_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PolicyPassword_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets; + /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, END_OF_LIST, END_OF_LIST}}; + +# define _PolicyPasswordDataAddress (&_PolicyPasswordData) +# else +# define _PolicyPasswordDataAddress 0 +# endif // CC_PolicyPassword + +# if CC_PolicyGetDigest + +# include "PolicyGetDigest_fp.h" + +typedef TPM_RC(PolicyGetDigest_Entry)(PolicyGetDigest_In* in, + PolicyGetDigest_Out* out); + +typedef const struct +{ + PolicyGetDigest_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[4]; +} PolicyGetDigest_COMMAND_DESCRIPTOR_t; + +PolicyGetDigest_COMMAND_DESCRIPTOR_t _PolicyGetDigestData = { + /* entry */ &TPM2_PolicyGetDigest, + /* inSize */ (UINT16)(sizeof(PolicyGetDigest_In)), + /* outSize */ (UINT16)(sizeof(PolicyGetDigest_Out)), + /* offsetOfTypes */ offsetof(PolicyGetDigest_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets; + /* types */ + {TPMI_SH_POLICY_H_UNMARSHAL, END_OF_LIST, TPM2B_DIGEST_P_MARSHAL, END_OF_LIST}}; + +# define _PolicyGetDigestDataAddress (&_PolicyGetDigestData) +# else +# define _PolicyGetDigestDataAddress 0 +# endif // CC_PolicyGetDigest + +# if CC_PolicyNvWritten + +# include "PolicyNvWritten_fp.h" + +typedef TPM_RC(PolicyNvWritten_Entry)(PolicyNvWritten_In* in); + +typedef const struct +{ + PolicyNvWritten_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} PolicyNvWritten_COMMAND_DESCRIPTOR_t; + +PolicyNvWritten_COMMAND_DESCRIPTOR_t _PolicyNvWrittenData = { + /* entry */ &TPM2_PolicyNvWritten, + /* inSize */ (UINT16)(sizeof(PolicyNvWritten_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PolicyNvWritten_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(PolicyNvWritten_In, writtenSet))}, + /* types */ + {TPMI_SH_POLICY_H_UNMARSHAL, TPMI_YES_NO_P_UNMARSHAL, END_OF_LIST, END_OF_LIST}}; + +# define _PolicyNvWrittenDataAddress (&_PolicyNvWrittenData) +# else +# define _PolicyNvWrittenDataAddress 0 +# endif // CC_PolicyNvWritten + +# if CC_PolicyTemplate + +# include "PolicyTemplate_fp.h" + +typedef TPM_RC(PolicyTemplate_Entry)(PolicyTemplate_In* in); + +typedef const struct +{ + PolicyTemplate_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} PolicyTemplate_COMMAND_DESCRIPTOR_t; + +PolicyTemplate_COMMAND_DESCRIPTOR_t _PolicyTemplateData = { + /* entry */ &TPM2_PolicyTemplate, + /* inSize */ (UINT16)(sizeof(PolicyTemplate_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PolicyTemplate_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(PolicyTemplate_In, templateHash))}, + /* types */ + {TPMI_SH_POLICY_H_UNMARSHAL, TPM2B_DIGEST_P_UNMARSHAL, END_OF_LIST, END_OF_LIST}}; + +# define _PolicyTemplateDataAddress (&_PolicyTemplateData) +# else +# define _PolicyTemplateDataAddress 0 +# endif // CC_PolicyTemplate + +# if CC_PolicyAuthorizeNV + +# include "PolicyAuthorizeNV_fp.h" + +typedef TPM_RC(PolicyAuthorizeNV_Entry)(PolicyAuthorizeNV_In* in); + +typedef const struct +{ + PolicyAuthorizeNV_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[2]; + BYTE types[5]; +} PolicyAuthorizeNV_COMMAND_DESCRIPTOR_t; + +PolicyAuthorizeNV_COMMAND_DESCRIPTOR_t _PolicyAuthorizeNVData = { + /* entry */ &TPM2_PolicyAuthorizeNV, + /* inSize */ (UINT16)(sizeof(PolicyAuthorizeNV_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PolicyAuthorizeNV_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(PolicyAuthorizeNV_In, nvIndex)), + (UINT16)(offsetof(PolicyAuthorizeNV_In, policySession))}, + /* types */ + {TPMI_RH_NV_AUTH_H_UNMARSHAL, + TPMI_RH_NV_INDEX_H_UNMARSHAL, + TPMI_SH_POLICY_H_UNMARSHAL, + END_OF_LIST, + END_OF_LIST}}; + +# define _PolicyAuthorizeNVDataAddress (&_PolicyAuthorizeNVData) +# else +# define _PolicyAuthorizeNVDataAddress 0 +# endif // CC_PolicyAuthorizeNV + +# if CC_CreatePrimary + +# include "CreatePrimary_fp.h" + +typedef TPM_RC(CreatePrimary_Entry)(CreatePrimary_In* in, CreatePrimary_Out* out); + +typedef const struct +{ + CreatePrimary_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[9]; + BYTE types[13]; +} CreatePrimary_COMMAND_DESCRIPTOR_t; + +CreatePrimary_COMMAND_DESCRIPTOR_t _CreatePrimaryData = { + /* entry */ &TPM2_CreatePrimary, + /* inSize */ (UINT16)(sizeof(CreatePrimary_In)), + /* outSize */ (UINT16)(sizeof(CreatePrimary_Out)), + /* offsetOfTypes */ offsetof(CreatePrimary_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(CreatePrimary_In, inSensitive)), + (UINT16)(offsetof(CreatePrimary_In, inPublic)), + (UINT16)(offsetof(CreatePrimary_In, outsideInfo)), + (UINT16)(offsetof(CreatePrimary_In, creationPCR)), + (UINT16)(offsetof(CreatePrimary_Out, outPublic)), + (UINT16)(offsetof(CreatePrimary_Out, creationData)), + (UINT16)(offsetof(CreatePrimary_Out, creationHash)), + (UINT16)(offsetof(CreatePrimary_Out, creationTicket)), + (UINT16)(offsetof(CreatePrimary_Out, name))}, + /* types */ + {TPMI_RH_HIERARCHY_H_UNMARSHAL + ADD_FLAG, + TPM2B_SENSITIVE_CREATE_P_UNMARSHAL, + TPM2B_PUBLIC_P_UNMARSHAL, + TPM2B_DATA_P_UNMARSHAL, + TPML_PCR_SELECTION_P_UNMARSHAL, + END_OF_LIST, + TPM_HANDLE_H_MARSHAL, + TPM2B_PUBLIC_P_MARSHAL, + TPM2B_CREATION_DATA_P_MARSHAL, + TPM2B_DIGEST_P_MARSHAL, + TPMT_TK_CREATION_P_MARSHAL, + TPM2B_NAME_P_MARSHAL, + END_OF_LIST}}; + +# define _CreatePrimaryDataAddress (&_CreatePrimaryData) +# else +# define _CreatePrimaryDataAddress 0 +# endif // CC_CreatePrimary + +# if CC_HierarchyControl + +# include "HierarchyControl_fp.h" + +typedef TPM_RC(HierarchyControl_Entry)(HierarchyControl_In* in); + +typedef const struct +{ + HierarchyControl_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[2]; + BYTE types[5]; +} HierarchyControl_COMMAND_DESCRIPTOR_t; + +HierarchyControl_COMMAND_DESCRIPTOR_t _HierarchyControlData = { + /* entry */ &TPM2_HierarchyControl, + /* inSize */ (UINT16)(sizeof(HierarchyControl_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(HierarchyControl_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(HierarchyControl_In, enable)), + (UINT16)(offsetof(HierarchyControl_In, state))}, + /* types */ + {TPMI_RH_HIERARCHY_H_UNMARSHAL, + TPMI_RH_ENABLES_P_UNMARSHAL, + TPMI_YES_NO_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST}}; + +# define _HierarchyControlDataAddress (&_HierarchyControlData) +# else +# define _HierarchyControlDataAddress 0 +# endif // CC_HierarchyControl + +# if CC_SetPrimaryPolicy + +# include "SetPrimaryPolicy_fp.h" + +typedef TPM_RC(SetPrimaryPolicy_Entry)(SetPrimaryPolicy_In* in); + +typedef const struct +{ + SetPrimaryPolicy_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[2]; + BYTE types[5]; +} SetPrimaryPolicy_COMMAND_DESCRIPTOR_t; + +SetPrimaryPolicy_COMMAND_DESCRIPTOR_t _SetPrimaryPolicyData = { + /* entry */ &TPM2_SetPrimaryPolicy, + /* inSize */ (UINT16)(sizeof(SetPrimaryPolicy_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(SetPrimaryPolicy_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(SetPrimaryPolicy_In, authPolicy)), + (UINT16)(offsetof(SetPrimaryPolicy_In, hashAlg))}, + /* types */ + {TPMI_RH_HIERARCHY_POLICY_H_UNMARSHAL, + TPM2B_DIGEST_P_UNMARSHAL, + TPMI_ALG_HASH_P_UNMARSHAL + ADD_FLAG, + END_OF_LIST, + END_OF_LIST}}; + +# define _SetPrimaryPolicyDataAddress (&_SetPrimaryPolicyData) +# else +# define _SetPrimaryPolicyDataAddress 0 +# endif // CC_SetPrimaryPolicy + +# if CC_ChangePPS + +# include "ChangePPS_fp.h" + +typedef TPM_RC(ChangePPS_Entry)(ChangePPS_In* in); + +typedef const struct +{ + ChangePPS_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[3]; +} ChangePPS_COMMAND_DESCRIPTOR_t; + +ChangePPS_COMMAND_DESCRIPTOR_t _ChangePPSData = { + /* entry */ &TPM2_ChangePPS, + /* inSize */ (UINT16)(sizeof(ChangePPS_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(ChangePPS_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets; + /* types */ {TPMI_RH_PLATFORM_H_UNMARSHAL, END_OF_LIST, END_OF_LIST}}; + +# define _ChangePPSDataAddress (&_ChangePPSData) +# else +# define _ChangePPSDataAddress 0 +# endif // CC_ChangePPS + +# if CC_ChangeEPS + +# include "ChangeEPS_fp.h" + +typedef TPM_RC(ChangeEPS_Entry)(ChangeEPS_In* in); + +typedef const struct +{ + ChangeEPS_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[3]; +} ChangeEPS_COMMAND_DESCRIPTOR_t; + +ChangeEPS_COMMAND_DESCRIPTOR_t _ChangeEPSData = { + /* entry */ &TPM2_ChangeEPS, + /* inSize */ (UINT16)(sizeof(ChangeEPS_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(ChangeEPS_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets; + /* types */ {TPMI_RH_PLATFORM_H_UNMARSHAL, END_OF_LIST, END_OF_LIST}}; + +# define _ChangeEPSDataAddress (&_ChangeEPSData) +# else +# define _ChangeEPSDataAddress 0 +# endif // CC_ChangeEPS + +# if CC_Clear + +# include "Clear_fp.h" + +typedef TPM_RC(Clear_Entry)(Clear_In* in); + +typedef const struct +{ + Clear_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[3]; +} Clear_COMMAND_DESCRIPTOR_t; + +Clear_COMMAND_DESCRIPTOR_t _ClearData = { + /* entry */ &TPM2_Clear, + /* inSize */ (UINT16)(sizeof(Clear_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(Clear_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets; + /* types */ {TPMI_RH_CLEAR_H_UNMARSHAL, END_OF_LIST, END_OF_LIST}}; + +# define _ClearDataAddress (&_ClearData) +# else +# define _ClearDataAddress 0 +# endif // CC_Clear + +# if CC_ClearControl + +# include "ClearControl_fp.h" + +typedef TPM_RC(ClearControl_Entry)(ClearControl_In* in); + +typedef const struct +{ + ClearControl_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} ClearControl_COMMAND_DESCRIPTOR_t; + +ClearControl_COMMAND_DESCRIPTOR_t _ClearControlData = { + /* entry */ &TPM2_ClearControl, + /* inSize */ (UINT16)(sizeof(ClearControl_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(ClearControl_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(ClearControl_In, disable))}, + /* types */ + {TPMI_RH_CLEAR_H_UNMARSHAL, TPMI_YES_NO_P_UNMARSHAL, END_OF_LIST, END_OF_LIST}}; + +# define _ClearControlDataAddress (&_ClearControlData) +# else +# define _ClearControlDataAddress 0 +# endif // CC_ClearControl + +# if CC_HierarchyChangeAuth + +# include "HierarchyChangeAuth_fp.h" + +typedef TPM_RC(HierarchyChangeAuth_Entry)(HierarchyChangeAuth_In* in); + +typedef const struct +{ + HierarchyChangeAuth_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} HierarchyChangeAuth_COMMAND_DESCRIPTOR_t; + +HierarchyChangeAuth_COMMAND_DESCRIPTOR_t _HierarchyChangeAuthData = { + /* entry */ &TPM2_HierarchyChangeAuth, + /* inSize */ (UINT16)(sizeof(HierarchyChangeAuth_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(HierarchyChangeAuth_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(HierarchyChangeAuth_In, newAuth))}, + /* types */ + {TPMI_RH_HIERARCHY_AUTH_H_UNMARSHAL, + TPM2B_AUTH_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST}}; + +# define _HierarchyChangeAuthDataAddress (&_HierarchyChangeAuthData) +# else +# define _HierarchyChangeAuthDataAddress 0 +# endif // CC_HierarchyChangeAuth + +# if CC_DictionaryAttackLockReset + +# include "DictionaryAttackLockReset_fp.h" + +typedef TPM_RC(DictionaryAttackLockReset_Entry)(DictionaryAttackLockReset_In* in); + +typedef const struct +{ + DictionaryAttackLockReset_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[3]; +} DictionaryAttackLockReset_COMMAND_DESCRIPTOR_t; + +DictionaryAttackLockReset_COMMAND_DESCRIPTOR_t _DictionaryAttackLockResetData = { + /* entry */ &TPM2_DictionaryAttackLockReset, + /* inSize */ (UINT16)(sizeof(DictionaryAttackLockReset_In)), + /* outSize */ 0, + /* offsetOfTypes */ + offsetof(DictionaryAttackLockReset_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets; + /* types */ {TPMI_RH_LOCKOUT_H_UNMARSHAL, END_OF_LIST, END_OF_LIST}}; + +# define _DictionaryAttackLockResetDataAddress (&_DictionaryAttackLockResetData) +# else +# define _DictionaryAttackLockResetDataAddress 0 +# endif // CC_DictionaryAttackLockReset + +# if CC_DictionaryAttackParameters + +# include "DictionaryAttackParameters_fp.h" + +typedef TPM_RC(DictionaryAttackParameters_Entry)(DictionaryAttackParameters_In* in); + +typedef const struct +{ + DictionaryAttackParameters_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[6]; +} DictionaryAttackParameters_COMMAND_DESCRIPTOR_t; + +DictionaryAttackParameters_COMMAND_DESCRIPTOR_t _DictionaryAttackParametersData = { + /* entry */ &TPM2_DictionaryAttackParameters, + /* inSize */ (UINT16)(sizeof(DictionaryAttackParameters_In)), + /* outSize */ 0, + /* offsetOfTypes */ + offsetof(DictionaryAttackParameters_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(DictionaryAttackParameters_In, newMaxTries)), + (UINT16)(offsetof(DictionaryAttackParameters_In, newRecoveryTime)), + (UINT16)(offsetof(DictionaryAttackParameters_In, lockoutRecovery))}, + /* types */ + {TPMI_RH_LOCKOUT_H_UNMARSHAL, + UINT32_P_UNMARSHAL, + UINT32_P_UNMARSHAL, + UINT32_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST}}; + +# define _DictionaryAttackParametersDataAddress (&_DictionaryAttackParametersData) +# else +# define _DictionaryAttackParametersDataAddress 0 +# endif // CC_DictionaryAttackParameters + +# if CC_PP_Commands + +# include "PP_Commands_fp.h" + +typedef TPM_RC(PP_Commands_Entry)(PP_Commands_In* in); + +typedef const struct +{ + PP_Commands_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[2]; + BYTE types[5]; +} PP_Commands_COMMAND_DESCRIPTOR_t; + +PP_Commands_COMMAND_DESCRIPTOR_t _PP_CommandsData = { + /* entry */ &TPM2_PP_Commands, + /* inSize */ (UINT16)(sizeof(PP_Commands_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(PP_Commands_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(PP_Commands_In, setList)), + (UINT16)(offsetof(PP_Commands_In, clearList))}, + /* types */ + {TPMI_RH_PLATFORM_H_UNMARSHAL, + TPML_CC_P_UNMARSHAL, + TPML_CC_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST}}; + +# define _PP_CommandsDataAddress (&_PP_CommandsData) +# else +# define _PP_CommandsDataAddress 0 +# endif // CC_PP_Commands + +# if CC_SetAlgorithmSet + +# include "SetAlgorithmSet_fp.h" + +typedef TPM_RC(SetAlgorithmSet_Entry)(SetAlgorithmSet_In* in); + +typedef const struct +{ + SetAlgorithmSet_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} SetAlgorithmSet_COMMAND_DESCRIPTOR_t; + +SetAlgorithmSet_COMMAND_DESCRIPTOR_t _SetAlgorithmSetData = { + /* entry */ &TPM2_SetAlgorithmSet, + /* inSize */ (UINT16)(sizeof(SetAlgorithmSet_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(SetAlgorithmSet_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(SetAlgorithmSet_In, algorithmSet))}, + /* types */ + {TPMI_RH_PLATFORM_H_UNMARSHAL, UINT32_P_UNMARSHAL, END_OF_LIST, END_OF_LIST}}; + +# define _SetAlgorithmSetDataAddress (&_SetAlgorithmSetData) +# else +# define _SetAlgorithmSetDataAddress 0 +# endif // CC_SetAlgorithmSet + +# if CC_FieldUpgradeStart + +# include "FieldUpgradeStart_fp.h" + +typedef TPM_RC(FieldUpgradeStart_Entry)(FieldUpgradeStart_In* in); + +typedef const struct +{ + FieldUpgradeStart_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[6]; +} FieldUpgradeStart_COMMAND_DESCRIPTOR_t; + +FieldUpgradeStart_COMMAND_DESCRIPTOR_t _FieldUpgradeStartData = { + /* entry */ &TPM2_FieldUpgradeStart, + /* inSize */ (UINT16)(sizeof(FieldUpgradeStart_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(FieldUpgradeStart_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(FieldUpgradeStart_In, keyHandle)), + (UINT16)(offsetof(FieldUpgradeStart_In, fuDigest)), + (UINT16)(offsetof(FieldUpgradeStart_In, manifestSignature))}, + /* types */ + {TPMI_RH_PLATFORM_H_UNMARSHAL, + TPMI_DH_OBJECT_H_UNMARSHAL, + TPM2B_DIGEST_P_UNMARSHAL, + TPMT_SIGNATURE_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST}}; + +# define _FieldUpgradeStartDataAddress (&_FieldUpgradeStartData) +# else +# define _FieldUpgradeStartDataAddress 0 +# endif // CC_FieldUpgradeStart + +# if CC_FieldUpgradeData + +# include "FieldUpgradeData_fp.h" + +typedef TPM_RC(FieldUpgradeData_Entry)(FieldUpgradeData_In* in, + FieldUpgradeData_Out* out); + +typedef const struct +{ + FieldUpgradeData_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[5]; +} FieldUpgradeData_COMMAND_DESCRIPTOR_t; + +FieldUpgradeData_COMMAND_DESCRIPTOR_t _FieldUpgradeDataData = { + /* entry */ &TPM2_FieldUpgradeData, + /* inSize */ (UINT16)(sizeof(FieldUpgradeData_In)), + /* outSize */ (UINT16)(sizeof(FieldUpgradeData_Out)), + /* offsetOfTypes */ offsetof(FieldUpgradeData_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(FieldUpgradeData_Out, firstDigest))}, + /* types */ + {TPM2B_MAX_BUFFER_P_UNMARSHAL, + END_OF_LIST, + TPMT_HA_P_MARSHAL, + TPMT_HA_P_MARSHAL, + END_OF_LIST}}; + +# define _FieldUpgradeDataDataAddress (&_FieldUpgradeDataData) +# else +# define _FieldUpgradeDataDataAddress 0 +# endif // CC_FieldUpgradeData + +# if CC_FirmwareRead + +# include "FirmwareRead_fp.h" + +typedef TPM_RC(FirmwareRead_Entry)(FirmwareRead_In* in, FirmwareRead_Out* out); + +typedef const struct +{ + FirmwareRead_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[4]; +} FirmwareRead_COMMAND_DESCRIPTOR_t; + +FirmwareRead_COMMAND_DESCRIPTOR_t _FirmwareReadData = { + /* entry */ &TPM2_FirmwareRead, + /* inSize */ (UINT16)(sizeof(FirmwareRead_In)), + /* outSize */ (UINT16)(sizeof(FirmwareRead_Out)), + /* offsetOfTypes */ offsetof(FirmwareRead_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets; + /* types */ + {UINT32_P_UNMARSHAL, END_OF_LIST, TPM2B_MAX_BUFFER_P_MARSHAL, END_OF_LIST}}; + +# define _FirmwareReadDataAddress (&_FirmwareReadData) +# else +# define _FirmwareReadDataAddress 0 +# endif // CC_FirmwareRead + +# if CC_ContextSave + +# include "ContextSave_fp.h" + +typedef TPM_RC(ContextSave_Entry)(ContextSave_In* in, ContextSave_Out* out); + +typedef const struct +{ + ContextSave_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[4]; +} ContextSave_COMMAND_DESCRIPTOR_t; + +ContextSave_COMMAND_DESCRIPTOR_t _ContextSaveData = { + /* entry */ &TPM2_ContextSave, + /* inSize */ (UINT16)(sizeof(ContextSave_In)), + /* outSize */ (UINT16)(sizeof(ContextSave_Out)), + /* offsetOfTypes */ offsetof(ContextSave_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets; + /* types */ + {TPMI_DH_CONTEXT_H_UNMARSHAL, END_OF_LIST, TPMS_CONTEXT_P_MARSHAL, END_OF_LIST}}; + +# define _ContextSaveDataAddress (&_ContextSaveData) +# else +# define _ContextSaveDataAddress 0 +# endif // CC_ContextSave + +# if CC_ContextLoad + +# include "ContextLoad_fp.h" + +typedef TPM_RC(ContextLoad_Entry)(ContextLoad_In* in, ContextLoad_Out* out); + +typedef const struct +{ + ContextLoad_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[4]; +} ContextLoad_COMMAND_DESCRIPTOR_t; + +ContextLoad_COMMAND_DESCRIPTOR_t _ContextLoadData = { + /* entry */ &TPM2_ContextLoad, + /* inSize */ (UINT16)(sizeof(ContextLoad_In)), + /* outSize */ (UINT16)(sizeof(ContextLoad_Out)), + /* offsetOfTypes */ offsetof(ContextLoad_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets; + /* types */ + {TPMS_CONTEXT_P_UNMARSHAL, END_OF_LIST, TPMI_DH_CONTEXT_H_MARSHAL, END_OF_LIST}}; + +# define _ContextLoadDataAddress (&_ContextLoadData) +# else +# define _ContextLoadDataAddress 0 +# endif // CC_ContextLoad + +# if CC_FlushContext + +# include "FlushContext_fp.h" + +typedef TPM_RC(FlushContext_Entry)(FlushContext_In* in); + +typedef const struct +{ + FlushContext_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[3]; +} FlushContext_COMMAND_DESCRIPTOR_t; + +FlushContext_COMMAND_DESCRIPTOR_t _FlushContextData = { + /* entry */ &TPM2_FlushContext, + /* inSize */ (UINT16)(sizeof(FlushContext_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(FlushContext_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets; + /* types */ {TPMI_DH_CONTEXT_P_UNMARSHAL, END_OF_LIST, END_OF_LIST}}; + +# define _FlushContextDataAddress (&_FlushContextData) +# else +# define _FlushContextDataAddress 0 +# endif // CC_FlushContext + +# if CC_EvictControl + +# include "EvictControl_fp.h" + +typedef TPM_RC(EvictControl_Entry)(EvictControl_In* in); + +typedef const struct +{ + EvictControl_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[2]; + BYTE types[5]; +} EvictControl_COMMAND_DESCRIPTOR_t; + +EvictControl_COMMAND_DESCRIPTOR_t _EvictControlData = { + /* entry */ &TPM2_EvictControl, + /* inSize */ (UINT16)(sizeof(EvictControl_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(EvictControl_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(EvictControl_In, objectHandle)), + (UINT16)(offsetof(EvictControl_In, persistentHandle))}, + /* types */ + {TPMI_RH_PROVISION_H_UNMARSHAL, + TPMI_DH_OBJECT_H_UNMARSHAL, + TPMI_DH_PERSISTENT_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST}}; + +# define _EvictControlDataAddress (&_EvictControlData) +# else +# define _EvictControlDataAddress 0 +# endif // CC_EvictControl + +# if CC_ReadClock + +# include "ReadClock_fp.h" + +typedef TPM_RC(ReadClock_Entry)(ReadClock_Out* out); + +typedef const struct +{ + ReadClock_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[3]; +} ReadClock_COMMAND_DESCRIPTOR_t; + +ReadClock_COMMAND_DESCRIPTOR_t _ReadClockData = { + /* entry */ &TPM2_ReadClock, + /* inSize */ 0, + /* outSize */ (UINT16)(sizeof(ReadClock_Out)), + /* offsetOfTypes */ offsetof(ReadClock_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets; + /* types */ {END_OF_LIST, TPMS_TIME_INFO_P_MARSHAL, END_OF_LIST}}; + +# define _ReadClockDataAddress (&_ReadClockData) +# else +# define _ReadClockDataAddress 0 +# endif // CC_ReadClock + +# if CC_ClockSet + +# include "ClockSet_fp.h" + +typedef TPM_RC(ClockSet_Entry)(ClockSet_In* in); + +typedef const struct +{ + ClockSet_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} ClockSet_COMMAND_DESCRIPTOR_t; + +ClockSet_COMMAND_DESCRIPTOR_t _ClockSetData = { + /* entry */ &TPM2_ClockSet, + /* inSize */ (UINT16)(sizeof(ClockSet_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(ClockSet_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(ClockSet_In, newTime))}, + /* types */ + {TPMI_RH_PROVISION_H_UNMARSHAL, UINT64_P_UNMARSHAL, END_OF_LIST, END_OF_LIST}}; + +# define _ClockSetDataAddress (&_ClockSetData) +# else +# define _ClockSetDataAddress 0 +# endif // CC_ClockSet + +# if CC_ClockRateAdjust + +# include "ClockRateAdjust_fp.h" + +typedef TPM_RC(ClockRateAdjust_Entry)(ClockRateAdjust_In* in); + +typedef const struct +{ + ClockRateAdjust_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} ClockRateAdjust_COMMAND_DESCRIPTOR_t; + +ClockRateAdjust_COMMAND_DESCRIPTOR_t _ClockRateAdjustData = { + /* entry */ &TPM2_ClockRateAdjust, + /* inSize */ (UINT16)(sizeof(ClockRateAdjust_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(ClockRateAdjust_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(ClockRateAdjust_In, rateAdjust))}, + /* types */ + {TPMI_RH_PROVISION_H_UNMARSHAL, + TPM_CLOCK_ADJUST_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST}}; + +# define _ClockRateAdjustDataAddress (&_ClockRateAdjustData) +# else +# define _ClockRateAdjustDataAddress 0 +# endif // CC_ClockRateAdjust + +# if CC_GetCapability + +# include "GetCapability_fp.h" + +typedef TPM_RC(GetCapability_Entry)(GetCapability_In* in, GetCapability_Out* out); + +typedef const struct +{ + GetCapability_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[7]; +} GetCapability_COMMAND_DESCRIPTOR_t; + +GetCapability_COMMAND_DESCRIPTOR_t _GetCapabilityData = { + /* entry */ &TPM2_GetCapability, + /* inSize */ (UINT16)(sizeof(GetCapability_In)), + /* outSize */ (UINT16)(sizeof(GetCapability_Out)), + /* offsetOfTypes */ offsetof(GetCapability_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(GetCapability_In, property)), + (UINT16)(offsetof(GetCapability_In, propertyCount)), + (UINT16)(offsetof(GetCapability_Out, capabilityData))}, + /* types */ + {TPM_CAP_P_UNMARSHAL, + UINT32_P_UNMARSHAL, + UINT32_P_UNMARSHAL, + END_OF_LIST, + TPMI_YES_NO_P_MARSHAL, + TPMS_CAPABILITY_DATA_P_MARSHAL, + END_OF_LIST}}; + +# define _GetCapabilityDataAddress (&_GetCapabilityData) +# else +# define _GetCapabilityDataAddress 0 +# endif // CC_GetCapability + +# if CC_TestParms + +# include "TestParms_fp.h" + +typedef TPM_RC(TestParms_Entry)(TestParms_In* in); + +typedef const struct +{ + TestParms_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[3]; +} TestParms_COMMAND_DESCRIPTOR_t; + +TestParms_COMMAND_DESCRIPTOR_t _TestParmsData = { + /* entry */ &TPM2_TestParms, + /* inSize */ (UINT16)(sizeof(TestParms_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(TestParms_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets; + /* types */ {TPMT_PUBLIC_PARMS_P_UNMARSHAL, END_OF_LIST, END_OF_LIST}}; + +# define _TestParmsDataAddress (&_TestParmsData) +# else +# define _TestParmsDataAddress 0 +# endif // CC_TestParms + +# if CC_NV_DefineSpace + +# include "NV_DefineSpace_fp.h" + +typedef TPM_RC(NV_DefineSpace_Entry)(NV_DefineSpace_In* in); + +typedef const struct +{ + NV_DefineSpace_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[2]; + BYTE types[5]; +} NV_DefineSpace_COMMAND_DESCRIPTOR_t; + +NV_DefineSpace_COMMAND_DESCRIPTOR_t _NV_DefineSpaceData = { + /* entry */ &TPM2_NV_DefineSpace, + /* inSize */ (UINT16)(sizeof(NV_DefineSpace_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(NV_DefineSpace_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(NV_DefineSpace_In, auth)), + (UINT16)(offsetof(NV_DefineSpace_In, publicInfo))}, + /* types */ + {TPMI_RH_PROVISION_H_UNMARSHAL, + TPM2B_AUTH_P_UNMARSHAL, + TPM2B_NV_PUBLIC_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST}}; + +# define _NV_DefineSpaceDataAddress (&_NV_DefineSpaceData) +# else +# define _NV_DefineSpaceDataAddress 0 +# endif // CC_NV_DefineSpace + +# if CC_NV_UndefineSpace + +# include "NV_UndefineSpace_fp.h" + +typedef TPM_RC(NV_UndefineSpace_Entry)(NV_UndefineSpace_In* in); + +typedef const struct +{ + NV_UndefineSpace_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} NV_UndefineSpace_COMMAND_DESCRIPTOR_t; + +NV_UndefineSpace_COMMAND_DESCRIPTOR_t _NV_UndefineSpaceData = { + /* entry */ &TPM2_NV_UndefineSpace, + /* inSize */ (UINT16)(sizeof(NV_UndefineSpace_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(NV_UndefineSpace_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(NV_UndefineSpace_In, nvIndex))}, + /* types */ + {TPMI_RH_PROVISION_H_UNMARSHAL, + TPMI_RH_NV_INDEX_H_UNMARSHAL, + END_OF_LIST, + END_OF_LIST}}; + +# define _NV_UndefineSpaceDataAddress (&_NV_UndefineSpaceData) +# else +# define _NV_UndefineSpaceDataAddress 0 +# endif // CC_NV_UndefineSpace + +# if CC_NV_UndefineSpaceSpecial + +# include "NV_UndefineSpaceSpecial_fp.h" + +typedef TPM_RC(NV_UndefineSpaceSpecial_Entry)(NV_UndefineSpaceSpecial_In* in); + +typedef const struct +{ + NV_UndefineSpaceSpecial_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} NV_UndefineSpaceSpecial_COMMAND_DESCRIPTOR_t; + +NV_UndefineSpaceSpecial_COMMAND_DESCRIPTOR_t _NV_UndefineSpaceSpecialData = { + /* entry */ &TPM2_NV_UndefineSpaceSpecial, + /* inSize */ (UINT16)(sizeof(NV_UndefineSpaceSpecial_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(NV_UndefineSpaceSpecial_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(NV_UndefineSpaceSpecial_In, platform))}, + /* types */ + {TPMI_RH_NV_INDEX_H_UNMARSHAL, + TPMI_RH_PLATFORM_H_UNMARSHAL, + END_OF_LIST, + END_OF_LIST}}; + +# define _NV_UndefineSpaceSpecialDataAddress (&_NV_UndefineSpaceSpecialData) +# else +# define _NV_UndefineSpaceSpecialDataAddress 0 +# endif // CC_NV_UndefineSpaceSpecial + +# if CC_NV_ReadPublic + +# include "NV_ReadPublic_fp.h" + +typedef TPM_RC(NV_ReadPublic_Entry)(NV_ReadPublic_In* in, NV_ReadPublic_Out* out); + +typedef const struct +{ + NV_ReadPublic_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[5]; +} NV_ReadPublic_COMMAND_DESCRIPTOR_t; + +NV_ReadPublic_COMMAND_DESCRIPTOR_t _NV_ReadPublicData = { + /* entry */ &TPM2_NV_ReadPublic, + /* inSize */ (UINT16)(sizeof(NV_ReadPublic_In)), + /* outSize */ (UINT16)(sizeof(NV_ReadPublic_Out)), + /* offsetOfTypes */ offsetof(NV_ReadPublic_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(NV_ReadPublic_Out, nvName))}, + /* types */ + {TPMI_RH_NV_INDEX_H_UNMARSHAL, + END_OF_LIST, + TPM2B_NV_PUBLIC_P_MARSHAL, + TPM2B_NAME_P_MARSHAL, + END_OF_LIST}}; + +# define _NV_ReadPublicDataAddress (&_NV_ReadPublicData) +# else +# define _NV_ReadPublicDataAddress 0 +# endif // CC_NV_ReadPublic + +# if CC_NV_Write + +# include "NV_Write_fp.h" + +typedef TPM_RC(NV_Write_Entry)(NV_Write_In* in); + +typedef const struct +{ + NV_Write_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[6]; +} NV_Write_COMMAND_DESCRIPTOR_t; + +NV_Write_COMMAND_DESCRIPTOR_t _NV_WriteData = { + /* entry */ &TPM2_NV_Write, + /* inSize */ (UINT16)(sizeof(NV_Write_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(NV_Write_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(NV_Write_In, nvIndex)), + (UINT16)(offsetof(NV_Write_In, data)), + (UINT16)(offsetof(NV_Write_In, offset))}, + /* types */ + {TPMI_RH_NV_AUTH_H_UNMARSHAL, + TPMI_RH_NV_INDEX_H_UNMARSHAL, + TPM2B_MAX_NV_BUFFER_P_UNMARSHAL, + UINT16_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST}}; + +# define _NV_WriteDataAddress (&_NV_WriteData) +# else +# define _NV_WriteDataAddress 0 +# endif // CC_NV_Write + +# if CC_NV_Increment + +# include "NV_Increment_fp.h" + +typedef TPM_RC(NV_Increment_Entry)(NV_Increment_In* in); + +typedef const struct +{ + NV_Increment_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} NV_Increment_COMMAND_DESCRIPTOR_t; + +NV_Increment_COMMAND_DESCRIPTOR_t _NV_IncrementData = { + /* entry */ &TPM2_NV_Increment, + /* inSize */ (UINT16)(sizeof(NV_Increment_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(NV_Increment_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(NV_Increment_In, nvIndex))}, + /* types */ + {TPMI_RH_NV_AUTH_H_UNMARSHAL, + TPMI_RH_NV_INDEX_H_UNMARSHAL, + END_OF_LIST, + END_OF_LIST}}; + +# define _NV_IncrementDataAddress (&_NV_IncrementData) +# else +# define _NV_IncrementDataAddress 0 +# endif // CC_NV_Increment + +# if CC_NV_Extend + +# include "NV_Extend_fp.h" + +typedef TPM_RC(NV_Extend_Entry)(NV_Extend_In* in); + +typedef const struct +{ + NV_Extend_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[2]; + BYTE types[5]; +} NV_Extend_COMMAND_DESCRIPTOR_t; + +NV_Extend_COMMAND_DESCRIPTOR_t _NV_ExtendData = { + /* entry */ &TPM2_NV_Extend, + /* inSize */ (UINT16)(sizeof(NV_Extend_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(NV_Extend_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(NV_Extend_In, nvIndex)), + (UINT16)(offsetof(NV_Extend_In, data))}, + /* types */ + {TPMI_RH_NV_AUTH_H_UNMARSHAL, + TPMI_RH_NV_INDEX_H_UNMARSHAL, + TPM2B_MAX_NV_BUFFER_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST}}; + +# define _NV_ExtendDataAddress (&_NV_ExtendData) +# else +# define _NV_ExtendDataAddress 0 +# endif // CC_NV_Extend + +# if CC_NV_SetBits + +# include "NV_SetBits_fp.h" + +typedef TPM_RC(NV_SetBits_Entry)(NV_SetBits_In* in); + +typedef const struct +{ + NV_SetBits_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[2]; + BYTE types[5]; +} NV_SetBits_COMMAND_DESCRIPTOR_t; + +NV_SetBits_COMMAND_DESCRIPTOR_t _NV_SetBitsData = { + /* entry */ &TPM2_NV_SetBits, + /* inSize */ (UINT16)(sizeof(NV_SetBits_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(NV_SetBits_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(NV_SetBits_In, nvIndex)), + (UINT16)(offsetof(NV_SetBits_In, bits))}, + /* types */ + {TPMI_RH_NV_AUTH_H_UNMARSHAL, + TPMI_RH_NV_INDEX_H_UNMARSHAL, + UINT64_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST}}; + +# define _NV_SetBitsDataAddress (&_NV_SetBitsData) +# else +# define _NV_SetBitsDataAddress 0 +# endif // CC_NV_SetBits + +# if CC_NV_WriteLock + +# include "NV_WriteLock_fp.h" + +typedef TPM_RC(NV_WriteLock_Entry)(NV_WriteLock_In* in); + +typedef const struct +{ + NV_WriteLock_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} NV_WriteLock_COMMAND_DESCRIPTOR_t; + +NV_WriteLock_COMMAND_DESCRIPTOR_t _NV_WriteLockData = { + /* entry */ &TPM2_NV_WriteLock, + /* inSize */ (UINT16)(sizeof(NV_WriteLock_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(NV_WriteLock_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(NV_WriteLock_In, nvIndex))}, + /* types */ + {TPMI_RH_NV_AUTH_H_UNMARSHAL, + TPMI_RH_NV_INDEX_H_UNMARSHAL, + END_OF_LIST, + END_OF_LIST}}; + +# define _NV_WriteLockDataAddress (&_NV_WriteLockData) +# else +# define _NV_WriteLockDataAddress 0 +# endif // CC_NV_WriteLock + +# if CC_NV_GlobalWriteLock + +# include "NV_GlobalWriteLock_fp.h" + +typedef TPM_RC(NV_GlobalWriteLock_Entry)(NV_GlobalWriteLock_In* in); + +typedef const struct +{ + NV_GlobalWriteLock_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[3]; +} NV_GlobalWriteLock_COMMAND_DESCRIPTOR_t; + +NV_GlobalWriteLock_COMMAND_DESCRIPTOR_t _NV_GlobalWriteLockData = { + /* entry */ &TPM2_NV_GlobalWriteLock, + /* inSize */ (UINT16)(sizeof(NV_GlobalWriteLock_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(NV_GlobalWriteLock_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets; + /* types */ {TPMI_RH_PROVISION_H_UNMARSHAL, END_OF_LIST, END_OF_LIST}}; + +# define _NV_GlobalWriteLockDataAddress (&_NV_GlobalWriteLockData) +# else +# define _NV_GlobalWriteLockDataAddress 0 +# endif // CC_NV_GlobalWriteLock + +# if CC_NV_Read + +# include "NV_Read_fp.h" + +typedef TPM_RC(NV_Read_Entry)(NV_Read_In* in, NV_Read_Out* out); + +typedef const struct +{ + NV_Read_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[7]; +} NV_Read_COMMAND_DESCRIPTOR_t; + +NV_Read_COMMAND_DESCRIPTOR_t _NV_ReadData = { + /* entry */ &TPM2_NV_Read, + /* inSize */ (UINT16)(sizeof(NV_Read_In)), + /* outSize */ (UINT16)(sizeof(NV_Read_Out)), + /* offsetOfTypes */ offsetof(NV_Read_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(NV_Read_In, nvIndex)), + (UINT16)(offsetof(NV_Read_In, size)), + (UINT16)(offsetof(NV_Read_In, offset))}, + /* types */ + {TPMI_RH_NV_AUTH_H_UNMARSHAL, + TPMI_RH_NV_INDEX_H_UNMARSHAL, + UINT16_P_UNMARSHAL, + UINT16_P_UNMARSHAL, + END_OF_LIST, + TPM2B_MAX_NV_BUFFER_P_MARSHAL, + END_OF_LIST}}; + +# define _NV_ReadDataAddress (&_NV_ReadData) +# else +# define _NV_ReadDataAddress 0 +# endif // CC_NV_Read + +# if CC_NV_ReadLock + +# include "NV_ReadLock_fp.h" + +typedef TPM_RC(NV_ReadLock_Entry)(NV_ReadLock_In* in); + +typedef const struct +{ + NV_ReadLock_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} NV_ReadLock_COMMAND_DESCRIPTOR_t; + +NV_ReadLock_COMMAND_DESCRIPTOR_t _NV_ReadLockData = { + /* entry */ &TPM2_NV_ReadLock, + /* inSize */ (UINT16)(sizeof(NV_ReadLock_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(NV_ReadLock_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(NV_ReadLock_In, nvIndex))}, + /* types */ + {TPMI_RH_NV_AUTH_H_UNMARSHAL, + TPMI_RH_NV_INDEX_H_UNMARSHAL, + END_OF_LIST, + END_OF_LIST}}; + +# define _NV_ReadLockDataAddress (&_NV_ReadLockData) +# else +# define _NV_ReadLockDataAddress 0 +# endif // CC_NV_ReadLock + +# if CC_NV_ChangeAuth + +# include "NV_ChangeAuth_fp.h" + +typedef TPM_RC(NV_ChangeAuth_Entry)(NV_ChangeAuth_In* in); + +typedef const struct +{ + NV_ChangeAuth_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} NV_ChangeAuth_COMMAND_DESCRIPTOR_t; + +NV_ChangeAuth_COMMAND_DESCRIPTOR_t _NV_ChangeAuthData = { + /* entry */ &TPM2_NV_ChangeAuth, + /* inSize */ (UINT16)(sizeof(NV_ChangeAuth_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(NV_ChangeAuth_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(NV_ChangeAuth_In, newAuth))}, + /* types */ + {TPMI_RH_NV_INDEX_H_UNMARSHAL, TPM2B_AUTH_P_UNMARSHAL, END_OF_LIST, END_OF_LIST}}; + +# define _NV_ChangeAuthDataAddress (&_NV_ChangeAuthData) +# else +# define _NV_ChangeAuthDataAddress 0 +# endif // CC_NV_ChangeAuth + +# if CC_NV_Certify + +# include "NV_Certify_fp.h" + +typedef TPM_RC(NV_Certify_Entry)(NV_Certify_In* in, NV_Certify_Out* out); + +typedef const struct +{ + NV_Certify_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[7]; + BYTE types[11]; +} NV_Certify_COMMAND_DESCRIPTOR_t; + +NV_Certify_COMMAND_DESCRIPTOR_t _NV_CertifyData = { + /* entry */ &TPM2_NV_Certify, + /* inSize */ (UINT16)(sizeof(NV_Certify_In)), + /* outSize */ (UINT16)(sizeof(NV_Certify_Out)), + /* offsetOfTypes */ offsetof(NV_Certify_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(NV_Certify_In, authHandle)), + (UINT16)(offsetof(NV_Certify_In, nvIndex)), + (UINT16)(offsetof(NV_Certify_In, qualifyingData)), + (UINT16)(offsetof(NV_Certify_In, inScheme)), + (UINT16)(offsetof(NV_Certify_In, size)), + (UINT16)(offsetof(NV_Certify_In, offset)), + (UINT16)(offsetof(NV_Certify_Out, signature))}, + /* types */ + {TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG, + TPMI_RH_NV_AUTH_H_UNMARSHAL, + TPMI_RH_NV_INDEX_H_UNMARSHAL, + TPM2B_DATA_P_UNMARSHAL, + TPMT_SIG_SCHEME_P_UNMARSHAL + ADD_FLAG, + UINT16_P_UNMARSHAL, + UINT16_P_UNMARSHAL, + END_OF_LIST, + TPM2B_ATTEST_P_MARSHAL, + TPMT_SIGNATURE_P_MARSHAL, + END_OF_LIST}}; + +# define _NV_CertifyDataAddress (&_NV_CertifyData) +# else +# define _NV_CertifyDataAddress 0 +# endif // CC_NV_Certify + +# if CC_AC_GetCapability + +# include "AC_GetCapability_fp.h" + +typedef TPM_RC(AC_GetCapability_Entry)(AC_GetCapability_In* in, + AC_GetCapability_Out* out); + +typedef const struct +{ + AC_GetCapability_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[7]; +} AC_GetCapability_COMMAND_DESCRIPTOR_t; + +AC_GetCapability_COMMAND_DESCRIPTOR_t _AC_GetCapabilityData = { + /* entry */ &TPM2_AC_GetCapability, + /* inSize */ (UINT16)(sizeof(AC_GetCapability_In)), + /* outSize */ (UINT16)(sizeof(AC_GetCapability_Out)), + /* offsetOfTypes */ offsetof(AC_GetCapability_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(AC_GetCapability_In, capability)), + (UINT16)(offsetof(AC_GetCapability_In, count)), + (UINT16)(offsetof(AC_GetCapability_Out, capabilitiesData))}, + /* types */ + {TPMI_RH_AC_H_UNMARSHAL, + TPM_AT_P_UNMARSHAL, + UINT32_P_UNMARSHAL, + END_OF_LIST, + TPMI_YES_NO_P_MARSHAL, + TPML_AC_CAPABILITIES_P_MARSHAL, + END_OF_LIST}}; + +# define _AC_GetCapabilityDataAddress (&_AC_GetCapabilityData) +# else +# define _AC_GetCapabilityDataAddress 0 +# endif // CC_AC_GetCapability + +# if CC_AC_Send + +# include "AC_Send_fp.h" + +typedef TPM_RC(AC_Send_Entry)(AC_Send_In* in, AC_Send_Out* out); + +typedef const struct +{ + AC_Send_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[3]; + BYTE types[7]; +} AC_Send_COMMAND_DESCRIPTOR_t; + +AC_Send_COMMAND_DESCRIPTOR_t _AC_SendData = { + /* entry */ &TPM2_AC_Send, + /* inSize */ (UINT16)(sizeof(AC_Send_In)), + /* outSize */ (UINT16)(sizeof(AC_Send_Out)), + /* offsetOfTypes */ offsetof(AC_Send_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(AC_Send_In, authHandle)), + (UINT16)(offsetof(AC_Send_In, ac)), + (UINT16)(offsetof(AC_Send_In, acDataIn))}, + /* types */ + {TPMI_DH_OBJECT_H_UNMARSHAL, + TPMI_RH_NV_AUTH_H_UNMARSHAL, + TPMI_RH_AC_H_UNMARSHAL, + TPM2B_MAX_BUFFER_P_UNMARSHAL, + END_OF_LIST, + TPMS_AC_OUTPUT_P_MARSHAL, + END_OF_LIST}}; + +# define _AC_SendDataAddress (&_AC_SendData) +# else +# define _AC_SendDataAddress 0 +# endif // CC_AC_Send + +# if CC_Policy_AC_SendSelect + +# include "Policy_AC_SendSelect_fp.h" + +typedef TPM_RC(Policy_AC_SendSelect_Entry)(Policy_AC_SendSelect_In* in); + +typedef const struct +{ + Policy_AC_SendSelect_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[4]; + BYTE types[7]; +} Policy_AC_SendSelect_COMMAND_DESCRIPTOR_t; + +Policy_AC_SendSelect_COMMAND_DESCRIPTOR_t _Policy_AC_SendSelectData = { + /* entry */ &TPM2_Policy_AC_SendSelect, + /* inSize */ (UINT16)(sizeof(Policy_AC_SendSelect_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(Policy_AC_SendSelect_COMMAND_DESCRIPTOR_t, types), + /* offsets */ + {(UINT16)(offsetof(Policy_AC_SendSelect_In, objectName)), + (UINT16)(offsetof(Policy_AC_SendSelect_In, authHandleName)), + (UINT16)(offsetof(Policy_AC_SendSelect_In, acName)), + (UINT16)(offsetof(Policy_AC_SendSelect_In, includeObject))}, + /* types */ + {TPMI_SH_POLICY_H_UNMARSHAL, + TPM2B_NAME_P_UNMARSHAL, + TPM2B_NAME_P_UNMARSHAL, + TPM2B_NAME_P_UNMARSHAL, + TPMI_YES_NO_P_UNMARSHAL, + END_OF_LIST, + END_OF_LIST}}; + +# define _Policy_AC_SendSelectDataAddress (&_Policy_AC_SendSelectData) +# else +# define _Policy_AC_SendSelectDataAddress 0 +# endif // CC_Policy_AC_SendSelect + +# if CC_ACT_SetTimeout + +# include "ACT_SetTimeout_fp.h" + +typedef TPM_RC(ACT_SetTimeout_Entry)(ACT_SetTimeout_In* in); + +typedef const struct +{ + ACT_SetTimeout_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + UINT16 paramOffsets[1]; + BYTE types[4]; +} ACT_SetTimeout_COMMAND_DESCRIPTOR_t; + +ACT_SetTimeout_COMMAND_DESCRIPTOR_t _ACT_SetTimeoutData = { + /* entry */ &TPM2_ACT_SetTimeout, + /* inSize */ (UINT16)(sizeof(ACT_SetTimeout_In)), + /* outSize */ 0, + /* offsetOfTypes */ offsetof(ACT_SetTimeout_COMMAND_DESCRIPTOR_t, types), + /* offsets */ {(UINT16)(offsetof(ACT_SetTimeout_In, startTimeout))}, + /* types */ + {TPMI_RH_ACT_H_UNMARSHAL, UINT32_P_UNMARSHAL, END_OF_LIST, END_OF_LIST}}; + +# define _ACT_SetTimeoutDataAddress (&_ACT_SetTimeoutData) +# else +# define _ACT_SetTimeoutDataAddress 0 +# endif // CC_ACT_SetTimeout + +# if CC_Vendor_TCG_Test + +# include "Vendor_TCG_Test_fp.h" + +typedef TPM_RC(Vendor_TCG_Test_Entry)(Vendor_TCG_Test_In* in, + Vendor_TCG_Test_Out* out); + +typedef const struct +{ + Vendor_TCG_Test_Entry* entry; + UINT16 inSize; + UINT16 outSize; + UINT16 offsetOfTypes; + BYTE types[4]; +} Vendor_TCG_Test_COMMAND_DESCRIPTOR_t; + +Vendor_TCG_Test_COMMAND_DESCRIPTOR_t _Vendor_TCG_TestData = { + /* entry */ &TPM2_Vendor_TCG_Test, + /* inSize */ (UINT16)(sizeof(Vendor_TCG_Test_In)), + /* outSize */ (UINT16)(sizeof(Vendor_TCG_Test_Out)), + /* offsetOfTypes */ offsetof(Vendor_TCG_Test_COMMAND_DESCRIPTOR_t, types), + /* offsets */ // No parameter offsets; + /* types */ + {TPM2B_DATA_P_UNMARSHAL, END_OF_LIST, TPM2B_DATA_P_MARSHAL, END_OF_LIST}}; + +# define _Vendor_TCG_TestDataAddress (&_Vendor_TCG_TestData) +# else +# define _Vendor_TCG_TestDataAddress 0 +# endif // CC_Vendor_TCG_Test + +COMMAND_DESCRIPTOR_t* s_CommandDataArray[] = { +# if(PAD_LIST || CC_NV_UndefineSpaceSpecial) + (COMMAND_DESCRIPTOR_t*)_NV_UndefineSpaceSpecialDataAddress, +# endif // CC_NV_UndefineSpaceSpecial +# if(PAD_LIST || CC_EvictControl) + (COMMAND_DESCRIPTOR_t*)_EvictControlDataAddress, +# endif // CC_EvictControl +# if(PAD_LIST || CC_HierarchyControl) + (COMMAND_DESCRIPTOR_t*)_HierarchyControlDataAddress, +# endif // CC_HierarchyControl +# if(PAD_LIST || CC_NV_UndefineSpace) + (COMMAND_DESCRIPTOR_t*)_NV_UndefineSpaceDataAddress, +# endif // CC_NV_UndefineSpace +# if(PAD_LIST) + (COMMAND_DESCRIPTOR_t*)0, +# endif // +# if(PAD_LIST || CC_ChangeEPS) + (COMMAND_DESCRIPTOR_t*)_ChangeEPSDataAddress, +# endif // CC_ChangeEPS +# if(PAD_LIST || CC_ChangePPS) + (COMMAND_DESCRIPTOR_t*)_ChangePPSDataAddress, +# endif // CC_ChangePPS +# if(PAD_LIST || CC_Clear) + (COMMAND_DESCRIPTOR_t*)_ClearDataAddress, +# endif // CC_Clear +# if(PAD_LIST || CC_ClearControl) + (COMMAND_DESCRIPTOR_t*)_ClearControlDataAddress, +# endif // CC_ClearControl +# if(PAD_LIST || CC_ClockSet) + (COMMAND_DESCRIPTOR_t*)_ClockSetDataAddress, +# endif // CC_ClockSet +# if(PAD_LIST || CC_HierarchyChangeAuth) + (COMMAND_DESCRIPTOR_t*)_HierarchyChangeAuthDataAddress, +# endif // CC_HierarchyChangeAuth +# if(PAD_LIST || CC_NV_DefineSpace) + (COMMAND_DESCRIPTOR_t*)_NV_DefineSpaceDataAddress, +# endif // CC_NV_DefineSpace +# if(PAD_LIST || CC_PCR_Allocate) + (COMMAND_DESCRIPTOR_t*)_PCR_AllocateDataAddress, +# endif // CC_PCR_Allocate +# if(PAD_LIST || CC_PCR_SetAuthPolicy) + (COMMAND_DESCRIPTOR_t*)_PCR_SetAuthPolicyDataAddress, +# endif // CC_PCR_SetAuthPolicy +# if(PAD_LIST || CC_PP_Commands) + (COMMAND_DESCRIPTOR_t*)_PP_CommandsDataAddress, +# endif // CC_PP_Commands +# if(PAD_LIST || CC_SetPrimaryPolicy) + (COMMAND_DESCRIPTOR_t*)_SetPrimaryPolicyDataAddress, +# endif // CC_SetPrimaryPolicy +# if(PAD_LIST || CC_FieldUpgradeStart) + (COMMAND_DESCRIPTOR_t*)_FieldUpgradeStartDataAddress, +# endif // CC_FieldUpgradeStart +# if(PAD_LIST || CC_ClockRateAdjust) + (COMMAND_DESCRIPTOR_t*)_ClockRateAdjustDataAddress, +# endif // CC_ClockRateAdjust +# if(PAD_LIST || CC_CreatePrimary) + (COMMAND_DESCRIPTOR_t*)_CreatePrimaryDataAddress, +# endif // CC_CreatePrimary +# if(PAD_LIST || CC_NV_GlobalWriteLock) + (COMMAND_DESCRIPTOR_t*)_NV_GlobalWriteLockDataAddress, +# endif // CC_NV_GlobalWriteLock +# if(PAD_LIST || CC_GetCommandAuditDigest) + (COMMAND_DESCRIPTOR_t*)_GetCommandAuditDigestDataAddress, +# endif // CC_GetCommandAuditDigest +# if(PAD_LIST || CC_NV_Increment) + (COMMAND_DESCRIPTOR_t*)_NV_IncrementDataAddress, +# endif // CC_NV_Increment +# if(PAD_LIST || CC_NV_SetBits) + (COMMAND_DESCRIPTOR_t*)_NV_SetBitsDataAddress, +# endif // CC_NV_SetBits +# if(PAD_LIST || CC_NV_Extend) + (COMMAND_DESCRIPTOR_t*)_NV_ExtendDataAddress, +# endif // CC_NV_Extend +# if(PAD_LIST || CC_NV_Write) + (COMMAND_DESCRIPTOR_t*)_NV_WriteDataAddress, +# endif // CC_NV_Write +# if(PAD_LIST || CC_NV_WriteLock) + (COMMAND_DESCRIPTOR_t*)_NV_WriteLockDataAddress, +# endif // CC_NV_WriteLock +# if(PAD_LIST || CC_DictionaryAttackLockReset) + (COMMAND_DESCRIPTOR_t*)_DictionaryAttackLockResetDataAddress, +# endif // CC_DictionaryAttackLockReset +# if(PAD_LIST || CC_DictionaryAttackParameters) + (COMMAND_DESCRIPTOR_t*)_DictionaryAttackParametersDataAddress, +# endif // CC_DictionaryAttackParameters +# if(PAD_LIST || CC_NV_ChangeAuth) + (COMMAND_DESCRIPTOR_t*)_NV_ChangeAuthDataAddress, +# endif // CC_NV_ChangeAuth +# if(PAD_LIST || CC_PCR_Event) + (COMMAND_DESCRIPTOR_t*)_PCR_EventDataAddress, +# endif // CC_PCR_Event +# if(PAD_LIST || CC_PCR_Reset) + (COMMAND_DESCRIPTOR_t*)_PCR_ResetDataAddress, +# endif // CC_PCR_Reset +# if(PAD_LIST || CC_SequenceComplete) + (COMMAND_DESCRIPTOR_t*)_SequenceCompleteDataAddress, +# endif // CC_SequenceComplete +# if(PAD_LIST || CC_SetAlgorithmSet) + (COMMAND_DESCRIPTOR_t*)_SetAlgorithmSetDataAddress, +# endif // CC_SetAlgorithmSet +# if(PAD_LIST || CC_SetCommandCodeAuditStatus) + (COMMAND_DESCRIPTOR_t*)_SetCommandCodeAuditStatusDataAddress, +# endif // CC_SetCommandCodeAuditStatus +# if(PAD_LIST || CC_FieldUpgradeData) + (COMMAND_DESCRIPTOR_t*)_FieldUpgradeDataDataAddress, +# endif // CC_FieldUpgradeData +# if(PAD_LIST || CC_IncrementalSelfTest) + (COMMAND_DESCRIPTOR_t*)_IncrementalSelfTestDataAddress, +# endif // CC_IncrementalSelfTest +# if(PAD_LIST || CC_SelfTest) + (COMMAND_DESCRIPTOR_t*)_SelfTestDataAddress, +# endif // CC_SelfTest +# if(PAD_LIST || CC_Startup) + (COMMAND_DESCRIPTOR_t*)_StartupDataAddress, +# endif // CC_Startup +# if(PAD_LIST || CC_Shutdown) + (COMMAND_DESCRIPTOR_t*)_ShutdownDataAddress, +# endif // CC_Shutdown +# if(PAD_LIST || CC_StirRandom) + (COMMAND_DESCRIPTOR_t*)_StirRandomDataAddress, +# endif // CC_StirRandom +# if(PAD_LIST || CC_ActivateCredential) + (COMMAND_DESCRIPTOR_t*)_ActivateCredentialDataAddress, +# endif // CC_ActivateCredential +# if(PAD_LIST || CC_Certify) + (COMMAND_DESCRIPTOR_t*)_CertifyDataAddress, +# endif // CC_Certify +# if(PAD_LIST || CC_PolicyNV) + (COMMAND_DESCRIPTOR_t*)_PolicyNVDataAddress, +# endif // CC_PolicyNV +# if(PAD_LIST || CC_CertifyCreation) + (COMMAND_DESCRIPTOR_t*)_CertifyCreationDataAddress, +# endif // CC_CertifyCreation +# if(PAD_LIST || CC_Duplicate) + (COMMAND_DESCRIPTOR_t*)_DuplicateDataAddress, +# endif // CC_Duplicate +# if(PAD_LIST || CC_GetTime) + (COMMAND_DESCRIPTOR_t*)_GetTimeDataAddress, +# endif // CC_GetTime +# if(PAD_LIST || CC_GetSessionAuditDigest) + (COMMAND_DESCRIPTOR_t*)_GetSessionAuditDigestDataAddress, +# endif // CC_GetSessionAuditDigest +# if(PAD_LIST || CC_NV_Read) + (COMMAND_DESCRIPTOR_t*)_NV_ReadDataAddress, +# endif // CC_NV_Read +# if(PAD_LIST || CC_NV_ReadLock) + (COMMAND_DESCRIPTOR_t*)_NV_ReadLockDataAddress, +# endif // CC_NV_ReadLock +# if(PAD_LIST || CC_ObjectChangeAuth) + (COMMAND_DESCRIPTOR_t*)_ObjectChangeAuthDataAddress, +# endif // CC_ObjectChangeAuth +# if(PAD_LIST || CC_PolicySecret) + (COMMAND_DESCRIPTOR_t*)_PolicySecretDataAddress, +# endif // CC_PolicySecret +# if(PAD_LIST || CC_Rewrap) + (COMMAND_DESCRIPTOR_t*)_RewrapDataAddress, +# endif // CC_Rewrap +# if(PAD_LIST || CC_Create) + (COMMAND_DESCRIPTOR_t*)_CreateDataAddress, +# endif // CC_Create +# if(PAD_LIST || CC_ECDH_ZGen) + (COMMAND_DESCRIPTOR_t*)_ECDH_ZGenDataAddress, +# endif // CC_ECDH_ZGen +# if(PAD_LIST || (CC_HMAC || CC_MAC)) +# if CC_HMAC + (COMMAND_DESCRIPTOR_t*)_HMACDataAddress, +# endif +# if CC_MAC + (COMMAND_DESCRIPTOR_t*)_MACDataAddress, +# endif +# if(CC_HMAC || CC_MAC) > 1 +# error "More than one aliased command defined" +# endif +# endif // CC_HMAC CC_MAC +# if(PAD_LIST || CC_Import) + (COMMAND_DESCRIPTOR_t*)_ImportDataAddress, +# endif // CC_Import +# if(PAD_LIST || CC_Load) + (COMMAND_DESCRIPTOR_t*)_LoadDataAddress, +# endif // CC_Load +# if(PAD_LIST || CC_Quote) + (COMMAND_DESCRIPTOR_t*)_QuoteDataAddress, +# endif // CC_Quote +# if(PAD_LIST || CC_RSA_Decrypt) + (COMMAND_DESCRIPTOR_t*)_RSA_DecryptDataAddress, +# endif // CC_RSA_Decrypt +# if(PAD_LIST) + (COMMAND_DESCRIPTOR_t*)0, +# endif // +# if(PAD_LIST || (CC_HMAC_Start || CC_MAC_Start)) +# if CC_HMAC_Start + (COMMAND_DESCRIPTOR_t*)_HMAC_StartDataAddress, +# endif +# if CC_MAC_Start + (COMMAND_DESCRIPTOR_t*)_MAC_StartDataAddress, +# endif +# if(CC_HMAC_Start || CC_MAC_Start) > 1 +# error "More than one aliased command defined" +# endif +# endif // CC_HMAC_Start CC_MAC_Start +# if(PAD_LIST || CC_SequenceUpdate) + (COMMAND_DESCRIPTOR_t*)_SequenceUpdateDataAddress, +# endif // CC_SequenceUpdate +# if(PAD_LIST || CC_Sign) + (COMMAND_DESCRIPTOR_t*)_SignDataAddress, +# endif // CC_Sign +# if(PAD_LIST || CC_Unseal) + (COMMAND_DESCRIPTOR_t*)_UnsealDataAddress, +# endif // CC_Unseal +# if(PAD_LIST) + (COMMAND_DESCRIPTOR_t*)0, +# endif // +# if(PAD_LIST || CC_PolicySigned) + (COMMAND_DESCRIPTOR_t*)_PolicySignedDataAddress, +# endif // CC_PolicySigned +# if(PAD_LIST || CC_ContextLoad) + (COMMAND_DESCRIPTOR_t*)_ContextLoadDataAddress, +# endif // CC_ContextLoad +# if(PAD_LIST || CC_ContextSave) + (COMMAND_DESCRIPTOR_t*)_ContextSaveDataAddress, +# endif // CC_ContextSave +# if(PAD_LIST || CC_ECDH_KeyGen) + (COMMAND_DESCRIPTOR_t*)_ECDH_KeyGenDataAddress, +# endif // CC_ECDH_KeyGen +# if(PAD_LIST || CC_EncryptDecrypt) + (COMMAND_DESCRIPTOR_t*)_EncryptDecryptDataAddress, +# endif // CC_EncryptDecrypt +# if(PAD_LIST || CC_FlushContext) + (COMMAND_DESCRIPTOR_t*)_FlushContextDataAddress, +# endif // CC_FlushContext +# if(PAD_LIST) + (COMMAND_DESCRIPTOR_t*)0, +# endif // +# if(PAD_LIST || CC_LoadExternal) + (COMMAND_DESCRIPTOR_t*)_LoadExternalDataAddress, +# endif // CC_LoadExternal +# if(PAD_LIST || CC_MakeCredential) + (COMMAND_DESCRIPTOR_t*)_MakeCredentialDataAddress, +# endif // CC_MakeCredential +# if(PAD_LIST || CC_NV_ReadPublic) + (COMMAND_DESCRIPTOR_t*)_NV_ReadPublicDataAddress, +# endif // CC_NV_ReadPublic +# if(PAD_LIST || CC_PolicyAuthorize) + (COMMAND_DESCRIPTOR_t*)_PolicyAuthorizeDataAddress, +# endif // CC_PolicyAuthorize +# if(PAD_LIST || CC_PolicyAuthValue) + (COMMAND_DESCRIPTOR_t*)_PolicyAuthValueDataAddress, +# endif // CC_PolicyAuthValue +# if(PAD_LIST || CC_PolicyCommandCode) + (COMMAND_DESCRIPTOR_t*)_PolicyCommandCodeDataAddress, +# endif // CC_PolicyCommandCode +# if(PAD_LIST || CC_PolicyCounterTimer) + (COMMAND_DESCRIPTOR_t*)_PolicyCounterTimerDataAddress, +# endif // CC_PolicyCounterTimer +# if(PAD_LIST || CC_PolicyCpHash) + (COMMAND_DESCRIPTOR_t*)_PolicyCpHashDataAddress, +# endif // CC_PolicyCpHash +# if(PAD_LIST || CC_PolicyLocality) + (COMMAND_DESCRIPTOR_t*)_PolicyLocalityDataAddress, +# endif // CC_PolicyLocality +# if(PAD_LIST || CC_PolicyNameHash) + (COMMAND_DESCRIPTOR_t*)_PolicyNameHashDataAddress, +# endif // CC_PolicyNameHash +# if(PAD_LIST || CC_PolicyOR) + (COMMAND_DESCRIPTOR_t*)_PolicyORDataAddress, +# endif // CC_PolicyOR +# if(PAD_LIST || CC_PolicyTicket) + (COMMAND_DESCRIPTOR_t*)_PolicyTicketDataAddress, +# endif // CC_PolicyTicket +# if(PAD_LIST || CC_ReadPublic) + (COMMAND_DESCRIPTOR_t*)_ReadPublicDataAddress, +# endif // CC_ReadPublic +# if(PAD_LIST || CC_RSA_Encrypt) + (COMMAND_DESCRIPTOR_t*)_RSA_EncryptDataAddress, +# endif // CC_RSA_Encrypt +# if(PAD_LIST) + (COMMAND_DESCRIPTOR_t*)0, +# endif // +# if(PAD_LIST || CC_StartAuthSession) + (COMMAND_DESCRIPTOR_t*)_StartAuthSessionDataAddress, +# endif // CC_StartAuthSession +# if(PAD_LIST || CC_VerifySignature) + (COMMAND_DESCRIPTOR_t*)_VerifySignatureDataAddress, +# endif // CC_VerifySignature +# if(PAD_LIST || CC_ECC_Parameters) + (COMMAND_DESCRIPTOR_t*)_ECC_ParametersDataAddress, +# endif // CC_ECC_Parameters +# if(PAD_LIST || CC_FirmwareRead) + (COMMAND_DESCRIPTOR_t*)_FirmwareReadDataAddress, +# endif // CC_FirmwareRead +# if(PAD_LIST || CC_GetCapability) + (COMMAND_DESCRIPTOR_t*)_GetCapabilityDataAddress, +# endif // CC_GetCapability +# if(PAD_LIST || CC_GetRandom) + (COMMAND_DESCRIPTOR_t*)_GetRandomDataAddress, +# endif // CC_GetRandom +# if(PAD_LIST || CC_GetTestResult) + (COMMAND_DESCRIPTOR_t*)_GetTestResultDataAddress, +# endif // CC_GetTestResult +# if(PAD_LIST || CC_Hash) + (COMMAND_DESCRIPTOR_t*)_HashDataAddress, +# endif // CC_Hash +# if(PAD_LIST || CC_PCR_Read) + (COMMAND_DESCRIPTOR_t*)_PCR_ReadDataAddress, +# endif // CC_PCR_Read +# if(PAD_LIST || CC_PolicyPCR) + (COMMAND_DESCRIPTOR_t*)_PolicyPCRDataAddress, +# endif // CC_PolicyPCR +# if(PAD_LIST || CC_PolicyRestart) + (COMMAND_DESCRIPTOR_t*)_PolicyRestartDataAddress, +# endif // CC_PolicyRestart +# if(PAD_LIST || CC_ReadClock) + (COMMAND_DESCRIPTOR_t*)_ReadClockDataAddress, +# endif // CC_ReadClock +# if(PAD_LIST || CC_PCR_Extend) + (COMMAND_DESCRIPTOR_t*)_PCR_ExtendDataAddress, +# endif // CC_PCR_Extend +# if(PAD_LIST || CC_PCR_SetAuthValue) + (COMMAND_DESCRIPTOR_t*)_PCR_SetAuthValueDataAddress, +# endif // CC_PCR_SetAuthValue +# if(PAD_LIST || CC_NV_Certify) + (COMMAND_DESCRIPTOR_t*)_NV_CertifyDataAddress, +# endif // CC_NV_Certify +# if(PAD_LIST || CC_EventSequenceComplete) + (COMMAND_DESCRIPTOR_t*)_EventSequenceCompleteDataAddress, +# endif // CC_EventSequenceComplete +# if(PAD_LIST || CC_HashSequenceStart) + (COMMAND_DESCRIPTOR_t*)_HashSequenceStartDataAddress, +# endif // CC_HashSequenceStart +# if(PAD_LIST || CC_PolicyPhysicalPresence) + (COMMAND_DESCRIPTOR_t*)_PolicyPhysicalPresenceDataAddress, +# endif // CC_PolicyPhysicalPresence +# if(PAD_LIST || CC_PolicyDuplicationSelect) + (COMMAND_DESCRIPTOR_t*)_PolicyDuplicationSelectDataAddress, +# endif // CC_PolicyDuplicationSelect +# if(PAD_LIST || CC_PolicyGetDigest) + (COMMAND_DESCRIPTOR_t*)_PolicyGetDigestDataAddress, +# endif // CC_PolicyGetDigest +# if(PAD_LIST || CC_TestParms) + (COMMAND_DESCRIPTOR_t*)_TestParmsDataAddress, +# endif // CC_TestParms +# if(PAD_LIST || CC_Commit) + (COMMAND_DESCRIPTOR_t*)_CommitDataAddress, +# endif // CC_Commit +# if(PAD_LIST || CC_PolicyPassword) + (COMMAND_DESCRIPTOR_t*)_PolicyPasswordDataAddress, +# endif // CC_PolicyPassword +# if(PAD_LIST || CC_ZGen_2Phase) + (COMMAND_DESCRIPTOR_t*)_ZGen_2PhaseDataAddress, +# endif // CC_ZGen_2Phase +# if(PAD_LIST || CC_EC_Ephemeral) + (COMMAND_DESCRIPTOR_t*)_EC_EphemeralDataAddress, +# endif // CC_EC_Ephemeral +# if(PAD_LIST || CC_PolicyNvWritten) + (COMMAND_DESCRIPTOR_t*)_PolicyNvWrittenDataAddress, +# endif // CC_PolicyNvWritten +# if(PAD_LIST || CC_PolicyTemplate) + (COMMAND_DESCRIPTOR_t*)_PolicyTemplateDataAddress, +# endif // CC_PolicyTemplate +# if(PAD_LIST || CC_CreateLoaded) + (COMMAND_DESCRIPTOR_t*)_CreateLoadedDataAddress, +# endif // CC_CreateLoaded +# if(PAD_LIST || CC_PolicyAuthorizeNV) + (COMMAND_DESCRIPTOR_t*)_PolicyAuthorizeNVDataAddress, +# endif // CC_PolicyAuthorizeNV +# if(PAD_LIST || CC_EncryptDecrypt2) + (COMMAND_DESCRIPTOR_t*)_EncryptDecrypt2DataAddress, +# endif // CC_EncryptDecrypt2 +# if(PAD_LIST || CC_AC_GetCapability) + (COMMAND_DESCRIPTOR_t*)_AC_GetCapabilityDataAddress, +# endif // CC_AC_GetCapability +# if(PAD_LIST || CC_AC_Send) + (COMMAND_DESCRIPTOR_t*)_AC_SendDataAddress, +# endif // CC_AC_Send +# if(PAD_LIST || CC_Policy_AC_SendSelect) + (COMMAND_DESCRIPTOR_t*)_Policy_AC_SendSelectDataAddress, +# endif // CC_Policy_AC_SendSelect +# if(PAD_LIST || CC_CertifyX509) + (COMMAND_DESCRIPTOR_t*)_CertifyX509DataAddress, +# endif // CC_CertifyX509 +# if(PAD_LIST || CC_ACT_SetTimeout) + (COMMAND_DESCRIPTOR_t*)_ACT_SetTimeoutDataAddress, +# endif // CC_ACT_SetTimeout +# if(PAD_LIST || CC_ECC_Encrypt) + (COMMAND_DESCRIPTOR_t*)_ECC_EncryptDataAddress, +# endif // CC_ECC_Encrypt +# if(PAD_LIST || CC_ECC_Decrypt) + (COMMAND_DESCRIPTOR_t*)_ECC_DecryptDataAddress, +# endif // CC_ECC_Decrypt +# if(PAD_LIST || CC_Vendor_TCG_Test) + (COMMAND_DESCRIPTOR_t*)_Vendor_TCG_TestDataAddress, +# endif // CC_Vendor_TCG_Test + 0}; + +#endif // _COMMAND_TABLE_DISPATCH_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CommandDispatcher.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CommandDispatcher.h new file mode 100644 index 0000000..8d036fe --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CommandDispatcher.h @@ -0,0 +1,2640 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmDispatch; Version 4.0 July 8,2017 + * Date: Mar 6, 2020 Time: 01:50:10PM + */ + +// This macro is added just so that the code is only excessively long. +#define EXIT_IF_ERROR_PLUS(x) \ + if(TPM_RC_SUCCESS != result) \ + { \ + result += (x); \ + goto Exit; \ + } +#if CC_Startup +case TPM_CC_Startup: +{ + Startup_In* in = (Startup_In*)MemoryGetInBuffer(sizeof(Startup_In)); + result = TPM_SU_Unmarshal(&in->startupType, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_Startup_startupType); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_Startup(in); + break; +} +#endif // CC_Startup +#if CC_Shutdown +case TPM_CC_Shutdown: +{ + Shutdown_In* in = (Shutdown_In*)MemoryGetInBuffer(sizeof(Shutdown_In)); + result = TPM_SU_Unmarshal(&in->shutdownType, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_Shutdown_shutdownType); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_Shutdown(in); + break; +} +#endif // CC_Shutdown +#if CC_SelfTest +case TPM_CC_SelfTest: +{ + SelfTest_In* in = (SelfTest_In*)MemoryGetInBuffer(sizeof(SelfTest_In)); + result = TPMI_YES_NO_Unmarshal(&in->fullTest, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_SelfTest_fullTest); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_SelfTest(in); + break; +} +#endif // CC_SelfTest +#if CC_IncrementalSelfTest +case TPM_CC_IncrementalSelfTest: +{ + IncrementalSelfTest_In* in = + (IncrementalSelfTest_In*)MemoryGetInBuffer(sizeof(IncrementalSelfTest_In)); + IncrementalSelfTest_Out* out = + (IncrementalSelfTest_Out*)MemoryGetOutBuffer(sizeof(IncrementalSelfTest_Out)); + result = TPML_ALG_Unmarshal(&in->toTest, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_IncrementalSelfTest_toTest); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_IncrementalSelfTest(in, out); + rSize = sizeof(IncrementalSelfTest_Out); + *respParmSize += TPML_ALG_Marshal(&out->toDoList, responseBuffer, &rSize); + break; +} +#endif // CC_IncrementalSelfTest +#if CC_GetTestResult +case TPM_CC_GetTestResult: +{ + GetTestResult_Out* out = + (GetTestResult_Out*)MemoryGetOutBuffer(sizeof(GetTestResult_Out)); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_GetTestResult(out); + rSize = sizeof(GetTestResult_Out); + *respParmSize += TPM2B_MAX_BUFFER_Marshal(&out->outData, responseBuffer, &rSize); + *respParmSize += TPM_RC_Marshal(&out->testResult, responseBuffer, &rSize); + break; +} +#endif // CC_GetTestResult +#if CC_StartAuthSession +case TPM_CC_StartAuthSession: +{ + StartAuthSession_In* in = + (StartAuthSession_In*)MemoryGetInBuffer(sizeof(StartAuthSession_In)); + StartAuthSession_Out* out = + (StartAuthSession_Out*)MemoryGetOutBuffer(sizeof(StartAuthSession_Out)); + in->tpmKey = handles[0]; + in->bind = handles[1]; + result = TPM2B_NONCE_Unmarshal(&in->nonceCaller, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_StartAuthSession_nonceCaller); + result = TPM2B_ENCRYPTED_SECRET_Unmarshal( + &in->encryptedSalt, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_StartAuthSession_encryptedSalt); + result = TPM_SE_Unmarshal(&in->sessionType, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_StartAuthSession_sessionType); + result = + TPMT_SYM_DEF_Unmarshal(&in->symmetric, paramBuffer, paramBufferSize, TRUE); + EXIT_IF_ERROR_PLUS(RC_StartAuthSession_symmetric); + result = + TPMI_ALG_HASH_Unmarshal(&in->authHash, paramBuffer, paramBufferSize, FALSE); + EXIT_IF_ERROR_PLUS(RC_StartAuthSession_authHash); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_StartAuthSession(in, out); + rSize = sizeof(StartAuthSession_Out); + if(TPM_RC_SUCCESS != result) + goto Exit; + command->handles[command->handleNum++] = out->sessionHandle; + *respParmSize += TPM2B_NONCE_Marshal(&out->nonceTPM, responseBuffer, &rSize); + break; +} +#endif // CC_StartAuthSession +#if CC_PolicyRestart +case TPM_CC_PolicyRestart: +{ + PolicyRestart_In* in = + (PolicyRestart_In*)MemoryGetInBuffer(sizeof(PolicyRestart_In)); + in->sessionHandle = handles[0]; + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_PolicyRestart(in); + break; +} +#endif // CC_PolicyRestart +#if CC_Create +case TPM_CC_Create: +{ + Create_In* in = (Create_In*)MemoryGetInBuffer(sizeof(Create_In)); + Create_Out* out = (Create_Out*)MemoryGetOutBuffer(sizeof(Create_Out)); + in->parentHandle = handles[0]; + result = TPM2B_SENSITIVE_CREATE_Unmarshal( + &in->inSensitive, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_Create_inSensitive); + result = + TPM2B_PUBLIC_Unmarshal(&in->inPublic, paramBuffer, paramBufferSize, FALSE); + EXIT_IF_ERROR_PLUS(RC_Create_inPublic); + result = TPM2B_DATA_Unmarshal(&in->outsideInfo, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_Create_outsideInfo); + result = + TPML_PCR_SELECTION_Unmarshal(&in->creationPCR, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_Create_creationPCR); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_Create(in, out); + rSize = sizeof(Create_Out); + *respParmSize += TPM2B_PRIVATE_Marshal(&out->outPrivate, responseBuffer, &rSize); + *respParmSize += TPM2B_PUBLIC_Marshal(&out->outPublic, responseBuffer, &rSize); + *respParmSize += + TPM2B_CREATION_DATA_Marshal(&out->creationData, responseBuffer, &rSize); + *respParmSize += TPM2B_DIGEST_Marshal(&out->creationHash, responseBuffer, &rSize); + *respParmSize += + TPMT_TK_CREATION_Marshal(&out->creationTicket, responseBuffer, &rSize); + break; +} +#endif // CC_Create +#if CC_Load +case TPM_CC_Load: +{ + Load_In* in = (Load_In*)MemoryGetInBuffer(sizeof(Load_In)); + Load_Out* out = (Load_Out*)MemoryGetOutBuffer(sizeof(Load_Out)); + in->parentHandle = handles[0]; + result = TPM2B_PRIVATE_Unmarshal(&in->inPrivate, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_Load_inPrivate); + result = + TPM2B_PUBLIC_Unmarshal(&in->inPublic, paramBuffer, paramBufferSize, FALSE); + EXIT_IF_ERROR_PLUS(RC_Load_inPublic); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_Load(in, out); + rSize = sizeof(Load_Out); + if(TPM_RC_SUCCESS != result) + goto Exit; + command->handles[command->handleNum++] = out->objectHandle; + *respParmSize += TPM2B_NAME_Marshal(&out->name, responseBuffer, &rSize); + break; +} +#endif // CC_Load +#if CC_LoadExternal +case TPM_CC_LoadExternal: +{ + LoadExternal_In* in = + (LoadExternal_In*)MemoryGetInBuffer(sizeof(LoadExternal_In)); + LoadExternal_Out* out = + (LoadExternal_Out*)MemoryGetOutBuffer(sizeof(LoadExternal_Out)); + result = TPM2B_SENSITIVE_Unmarshal(&in->inPrivate, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_LoadExternal_inPrivate); + result = + TPM2B_PUBLIC_Unmarshal(&in->inPublic, paramBuffer, paramBufferSize, TRUE); + EXIT_IF_ERROR_PLUS(RC_LoadExternal_inPublic); + result = TPMI_RH_HIERARCHY_Unmarshal( + &in->hierarchy, paramBuffer, paramBufferSize, TRUE); + EXIT_IF_ERROR_PLUS(RC_LoadExternal_hierarchy); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_LoadExternal(in, out); + rSize = sizeof(LoadExternal_Out); + if(TPM_RC_SUCCESS != result) + goto Exit; + command->handles[command->handleNum++] = out->objectHandle; + *respParmSize += TPM2B_NAME_Marshal(&out->name, responseBuffer, &rSize); + break; +} +#endif // CC_LoadExternal +#if CC_ReadPublic +case TPM_CC_ReadPublic: +{ + ReadPublic_In* in = (ReadPublic_In*)MemoryGetInBuffer(sizeof(ReadPublic_In)); + ReadPublic_Out* out = (ReadPublic_Out*)MemoryGetOutBuffer(sizeof(ReadPublic_Out)); + in->objectHandle = handles[0]; + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_ReadPublic(in, out); + rSize = sizeof(ReadPublic_Out); + *respParmSize += TPM2B_PUBLIC_Marshal(&out->outPublic, responseBuffer, &rSize); + *respParmSize += TPM2B_NAME_Marshal(&out->name, responseBuffer, &rSize); + *respParmSize += TPM2B_NAME_Marshal(&out->qualifiedName, responseBuffer, &rSize); + break; +} +#endif // CC_ReadPublic +#if CC_ActivateCredential +case TPM_CC_ActivateCredential: +{ + ActivateCredential_In* in = + (ActivateCredential_In*)MemoryGetInBuffer(sizeof(ActivateCredential_In)); + ActivateCredential_Out* out = + (ActivateCredential_Out*)MemoryGetOutBuffer(sizeof(ActivateCredential_Out)); + in->activateHandle = handles[0]; + in->keyHandle = handles[1]; + result = + TPM2B_ID_OBJECT_Unmarshal(&in->credentialBlob, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_ActivateCredential_credentialBlob); + result = + TPM2B_ENCRYPTED_SECRET_Unmarshal(&in->secret, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_ActivateCredential_secret); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_ActivateCredential(in, out); + rSize = sizeof(ActivateCredential_Out); + *respParmSize += TPM2B_DIGEST_Marshal(&out->certInfo, responseBuffer, &rSize); + break; +} +#endif // CC_ActivateCredential +#if CC_MakeCredential +case TPM_CC_MakeCredential: +{ + MakeCredential_In* in = + (MakeCredential_In*)MemoryGetInBuffer(sizeof(MakeCredential_In)); + MakeCredential_Out* out = + (MakeCredential_Out*)MemoryGetOutBuffer(sizeof(MakeCredential_Out)); + in->handle = handles[0]; + result = TPM2B_DIGEST_Unmarshal(&in->credential, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_MakeCredential_credential); + result = TPM2B_NAME_Unmarshal(&in->objectName, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_MakeCredential_objectName); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_MakeCredential(in, out); + rSize = sizeof(MakeCredential_Out); + *respParmSize += + TPM2B_ID_OBJECT_Marshal(&out->credentialBlob, responseBuffer, &rSize); + *respParmSize += + TPM2B_ENCRYPTED_SECRET_Marshal(&out->secret, responseBuffer, &rSize); + break; +} +#endif // CC_MakeCredential +#if CC_Unseal +case TPM_CC_Unseal: +{ + Unseal_In* in = (Unseal_In*)MemoryGetInBuffer(sizeof(Unseal_In)); + Unseal_Out* out = (Unseal_Out*)MemoryGetOutBuffer(sizeof(Unseal_Out)); + in->itemHandle = handles[0]; + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_Unseal(in, out); + rSize = sizeof(Unseal_Out); + *respParmSize += + TPM2B_SENSITIVE_DATA_Marshal(&out->outData, responseBuffer, &rSize); + break; +} +#endif // CC_Unseal +#if CC_ObjectChangeAuth +case TPM_CC_ObjectChangeAuth: +{ + ObjectChangeAuth_In* in = + (ObjectChangeAuth_In*)MemoryGetInBuffer(sizeof(ObjectChangeAuth_In)); + ObjectChangeAuth_Out* out = + (ObjectChangeAuth_Out*)MemoryGetOutBuffer(sizeof(ObjectChangeAuth_Out)); + in->objectHandle = handles[0]; + in->parentHandle = handles[1]; + result = TPM2B_AUTH_Unmarshal(&in->newAuth, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_ObjectChangeAuth_newAuth); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_ObjectChangeAuth(in, out); + rSize = sizeof(ObjectChangeAuth_Out); + *respParmSize += TPM2B_PRIVATE_Marshal(&out->outPrivate, responseBuffer, &rSize); + break; +} +#endif // CC_ObjectChangeAuth +#if CC_CreateLoaded +case TPM_CC_CreateLoaded: +{ + CreateLoaded_In* in = + (CreateLoaded_In*)MemoryGetInBuffer(sizeof(CreateLoaded_In)); + CreateLoaded_Out* out = + (CreateLoaded_Out*)MemoryGetOutBuffer(sizeof(CreateLoaded_Out)); + in->parentHandle = handles[0]; + result = TPM2B_SENSITIVE_CREATE_Unmarshal( + &in->inSensitive, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_CreateLoaded_inSensitive); + result = TPM2B_TEMPLATE_Unmarshal(&in->inPublic, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_CreateLoaded_inPublic); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_CreateLoaded(in, out); + rSize = sizeof(CreateLoaded_Out); + if(TPM_RC_SUCCESS != result) + goto Exit; + command->handles[command->handleNum++] = out->objectHandle; + *respParmSize += TPM2B_PRIVATE_Marshal(&out->outPrivate, responseBuffer, &rSize); + *respParmSize += TPM2B_PUBLIC_Marshal(&out->outPublic, responseBuffer, &rSize); + *respParmSize += TPM2B_NAME_Marshal(&out->name, responseBuffer, &rSize); + break; +} +#endif // CC_CreateLoaded +#if CC_Duplicate +case TPM_CC_Duplicate: +{ + Duplicate_In* in = (Duplicate_In*)MemoryGetInBuffer(sizeof(Duplicate_In)); + Duplicate_Out* out = (Duplicate_Out*)MemoryGetOutBuffer(sizeof(Duplicate_Out)); + in->objectHandle = handles[0]; + in->newParentHandle = handles[1]; + result = TPM2B_DATA_Unmarshal(&in->encryptionKeyIn, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_Duplicate_encryptionKeyIn); + result = TPMT_SYM_DEF_OBJECT_Unmarshal( + &in->symmetricAlg, paramBuffer, paramBufferSize, TRUE); + EXIT_IF_ERROR_PLUS(RC_Duplicate_symmetricAlg); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_Duplicate(in, out); + rSize = sizeof(Duplicate_Out); + *respParmSize += + TPM2B_DATA_Marshal(&out->encryptionKeyOut, responseBuffer, &rSize); + *respParmSize += TPM2B_PRIVATE_Marshal(&out->duplicate, responseBuffer, &rSize); + *respParmSize += + TPM2B_ENCRYPTED_SECRET_Marshal(&out->outSymSeed, responseBuffer, &rSize); + break; +} +#endif // CC_Duplicate +#if CC_Rewrap +case TPM_CC_Rewrap: +{ + Rewrap_In* in = (Rewrap_In*)MemoryGetInBuffer(sizeof(Rewrap_In)); + Rewrap_Out* out = (Rewrap_Out*)MemoryGetOutBuffer(sizeof(Rewrap_Out)); + in->oldParent = handles[0]; + in->newParent = handles[1]; + result = TPM2B_PRIVATE_Unmarshal(&in->inDuplicate, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_Rewrap_inDuplicate); + result = TPM2B_NAME_Unmarshal(&in->name, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_Rewrap_name); + result = TPM2B_ENCRYPTED_SECRET_Unmarshal( + &in->inSymSeed, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_Rewrap_inSymSeed); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_Rewrap(in, out); + rSize = sizeof(Rewrap_Out); + *respParmSize += + TPM2B_PRIVATE_Marshal(&out->outDuplicate, responseBuffer, &rSize); + *respParmSize += + TPM2B_ENCRYPTED_SECRET_Marshal(&out->outSymSeed, responseBuffer, &rSize); + break; +} +#endif // CC_Rewrap +#if CC_Import +case TPM_CC_Import: +{ + Import_In* in = (Import_In*)MemoryGetInBuffer(sizeof(Import_In)); + Import_Out* out = (Import_Out*)MemoryGetOutBuffer(sizeof(Import_Out)); + in->parentHandle = handles[0]; + result = TPM2B_DATA_Unmarshal(&in->encryptionKey, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_Import_encryptionKey); + result = TPM2B_PUBLIC_Unmarshal( + &in->objectPublic, paramBuffer, paramBufferSize, FALSE); + EXIT_IF_ERROR_PLUS(RC_Import_objectPublic); + result = TPM2B_PRIVATE_Unmarshal(&in->duplicate, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_Import_duplicate); + result = TPM2B_ENCRYPTED_SECRET_Unmarshal( + &in->inSymSeed, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_Import_inSymSeed); + result = TPMT_SYM_DEF_OBJECT_Unmarshal( + &in->symmetricAlg, paramBuffer, paramBufferSize, TRUE); + EXIT_IF_ERROR_PLUS(RC_Import_symmetricAlg); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_Import(in, out); + rSize = sizeof(Import_Out); + *respParmSize += TPM2B_PRIVATE_Marshal(&out->outPrivate, responseBuffer, &rSize); + break; +} +#endif // CC_Import +#if CC_RSA_Encrypt +case TPM_CC_RSA_Encrypt: +{ + RSA_Encrypt_In* in = (RSA_Encrypt_In*)MemoryGetInBuffer(sizeof(RSA_Encrypt_In)); + RSA_Encrypt_Out* out = + (RSA_Encrypt_Out*)MemoryGetOutBuffer(sizeof(RSA_Encrypt_Out)); + in->keyHandle = handles[0]; + result = + TPM2B_PUBLIC_KEY_RSA_Unmarshal(&in->message, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_RSA_Encrypt_message); + result = + TPMT_RSA_DECRYPT_Unmarshal(&in->inScheme, paramBuffer, paramBufferSize, TRUE); + EXIT_IF_ERROR_PLUS(RC_RSA_Encrypt_inScheme); + result = TPM2B_DATA_Unmarshal(&in->label, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_RSA_Encrypt_label); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_RSA_Encrypt(in, out); + rSize = sizeof(RSA_Encrypt_Out); + *respParmSize += + TPM2B_PUBLIC_KEY_RSA_Marshal(&out->outData, responseBuffer, &rSize); + break; +} +#endif // CC_RSA_Encrypt +#if CC_RSA_Decrypt +case TPM_CC_RSA_Decrypt: +{ + RSA_Decrypt_In* in = (RSA_Decrypt_In*)MemoryGetInBuffer(sizeof(RSA_Decrypt_In)); + RSA_Decrypt_Out* out = + (RSA_Decrypt_Out*)MemoryGetOutBuffer(sizeof(RSA_Decrypt_Out)); + in->keyHandle = handles[0]; + result = + TPM2B_PUBLIC_KEY_RSA_Unmarshal(&in->cipherText, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_RSA_Decrypt_cipherText); + result = + TPMT_RSA_DECRYPT_Unmarshal(&in->inScheme, paramBuffer, paramBufferSize, TRUE); + EXIT_IF_ERROR_PLUS(RC_RSA_Decrypt_inScheme); + result = TPM2B_DATA_Unmarshal(&in->label, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_RSA_Decrypt_label); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_RSA_Decrypt(in, out); + rSize = sizeof(RSA_Decrypt_Out); + *respParmSize += + TPM2B_PUBLIC_KEY_RSA_Marshal(&out->message, responseBuffer, &rSize); + break; +} +#endif // CC_RSA_Decrypt +#if CC_ECDH_KeyGen +case TPM_CC_ECDH_KeyGen: +{ + ECDH_KeyGen_In* in = (ECDH_KeyGen_In*)MemoryGetInBuffer(sizeof(ECDH_KeyGen_In)); + ECDH_KeyGen_Out* out = + (ECDH_KeyGen_Out*)MemoryGetOutBuffer(sizeof(ECDH_KeyGen_Out)); + in->keyHandle = handles[0]; + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_ECDH_KeyGen(in, out); + rSize = sizeof(ECDH_KeyGen_Out); + *respParmSize += TPM2B_ECC_POINT_Marshal(&out->zPoint, responseBuffer, &rSize); + *respParmSize += TPM2B_ECC_POINT_Marshal(&out->pubPoint, responseBuffer, &rSize); + break; +} +#endif // CC_ECDH_KeyGen +#if CC_ECDH_ZGen +case TPM_CC_ECDH_ZGen: +{ + ECDH_ZGen_In* in = (ECDH_ZGen_In*)MemoryGetInBuffer(sizeof(ECDH_ZGen_In)); + ECDH_ZGen_Out* out = (ECDH_ZGen_Out*)MemoryGetOutBuffer(sizeof(ECDH_ZGen_Out)); + in->keyHandle = handles[0]; + result = TPM2B_ECC_POINT_Unmarshal(&in->inPoint, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_ECDH_ZGen_inPoint); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_ECDH_ZGen(in, out); + rSize = sizeof(ECDH_ZGen_Out); + *respParmSize += TPM2B_ECC_POINT_Marshal(&out->outPoint, responseBuffer, &rSize); + break; +} +#endif // CC_ECDH_ZGen +#if CC_ECC_Parameters +case TPM_CC_ECC_Parameters: +{ + ECC_Parameters_In* in = + (ECC_Parameters_In*)MemoryGetInBuffer(sizeof(ECC_Parameters_In)); + ECC_Parameters_Out* out = + (ECC_Parameters_Out*)MemoryGetOutBuffer(sizeof(ECC_Parameters_Out)); + result = TPMI_ECC_CURVE_Unmarshal(&in->curveID, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_ECC_Parameters_curveID); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_ECC_Parameters(in, out); + rSize = sizeof(ECC_Parameters_Out); + *respParmSize += + TPMS_ALGORITHM_DETAIL_ECC_Marshal(&out->parameters, responseBuffer, &rSize); + break; +} +#endif // CC_ECC_Parameters +#if CC_ZGen_2Phase +case TPM_CC_ZGen_2Phase: +{ + ZGen_2Phase_In* in = (ZGen_2Phase_In*)MemoryGetInBuffer(sizeof(ZGen_2Phase_In)); + ZGen_2Phase_Out* out = + (ZGen_2Phase_Out*)MemoryGetOutBuffer(sizeof(ZGen_2Phase_Out)); + in->keyA = handles[0]; + result = TPM2B_ECC_POINT_Unmarshal(&in->inQsB, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_ZGen_2Phase_inQsB); + result = TPM2B_ECC_POINT_Unmarshal(&in->inQeB, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_ZGen_2Phase_inQeB); + result = TPMI_ECC_KEY_EXCHANGE_Unmarshal( + &in->inScheme, paramBuffer, paramBufferSize, FALSE); + EXIT_IF_ERROR_PLUS(RC_ZGen_2Phase_inScheme); + result = UINT16_Unmarshal(&in->counter, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_ZGen_2Phase_counter); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_ZGen_2Phase(in, out); + rSize = sizeof(ZGen_2Phase_Out); + *respParmSize += TPM2B_ECC_POINT_Marshal(&out->outZ1, responseBuffer, &rSize); + *respParmSize += TPM2B_ECC_POINT_Marshal(&out->outZ2, responseBuffer, &rSize); + break; +} +#endif // CC_ZGen_2Phase +#if CC_ECC_Encrypt +case TPM_CC_ECC_Encrypt: +{ + ECC_Encrypt_In* in = (ECC_Encrypt_In*)MemoryGetInBuffer(sizeof(ECC_Encrypt_In)); + ECC_Encrypt_Out* out = + (ECC_Encrypt_Out*)MemoryGetOutBuffer(sizeof(ECC_Encrypt_Out)); + in->keyHandle = handles[0]; + result = TPM2B_MAX_BUFFER_Unmarshal(&in->plainText, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_ECC_Encrypt_plainText); + result = + TPMT_KDF_SCHEME_Unmarshal(&in->inScheme, paramBuffer, paramBufferSize, TRUE); + EXIT_IF_ERROR_PLUS(RC_ECC_Encrypt_inScheme); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_ECC_Encrypt(in, out); + rSize = sizeof(ECC_Encrypt_Out); + *respParmSize += TPM2B_ECC_POINT_Marshal(&out->C1, responseBuffer, &rSize); + *respParmSize += TPM2B_MAX_BUFFER_Marshal(&out->C2, responseBuffer, &rSize); + *respParmSize += TPM2B_DIGEST_Marshal(&out->C3, responseBuffer, &rSize); + break; +} +#endif // CC_ECC_Encrypt +#if CC_ECC_Decrypt +case TPM_CC_ECC_Decrypt: +{ + ECC_Decrypt_In* in = (ECC_Decrypt_In*)MemoryGetInBuffer(sizeof(ECC_Decrypt_In)); + ECC_Decrypt_Out* out = + (ECC_Decrypt_Out*)MemoryGetOutBuffer(sizeof(ECC_Decrypt_Out)); + in->keyHandle = handles[0]; + result = TPM2B_ECC_POINT_Unmarshal(&in->C1, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_ECC_Decrypt_C1); + result = TPM2B_MAX_BUFFER_Unmarshal(&in->C2, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_ECC_Decrypt_C2); + result = TPM2B_DIGEST_Unmarshal(&in->C3, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_ECC_Decrypt_C3); + result = + TPMT_KDF_SCHEME_Unmarshal(&in->inScheme, paramBuffer, paramBufferSize, TRUE); + EXIT_IF_ERROR_PLUS(RC_ECC_Decrypt_inScheme); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_ECC_Decrypt(in, out); + rSize = sizeof(ECC_Decrypt_Out); + *respParmSize += + TPM2B_MAX_BUFFER_Marshal(&out->plainText, responseBuffer, &rSize); + break; +} +#endif // CC_ECC_Decrypt +#if CC_EncryptDecrypt +case TPM_CC_EncryptDecrypt: +{ + EncryptDecrypt_In* in = + (EncryptDecrypt_In*)MemoryGetInBuffer(sizeof(EncryptDecrypt_In)); + EncryptDecrypt_Out* out = + (EncryptDecrypt_Out*)MemoryGetOutBuffer(sizeof(EncryptDecrypt_Out)); + in->keyHandle = handles[0]; + result = TPMI_YES_NO_Unmarshal(&in->decrypt, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_EncryptDecrypt_decrypt); + result = + TPMI_ALG_CIPHER_MODE_Unmarshal(&in->mode, paramBuffer, paramBufferSize, TRUE); + EXIT_IF_ERROR_PLUS(RC_EncryptDecrypt_mode); + result = TPM2B_IV_Unmarshal(&in->ivIn, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_EncryptDecrypt_ivIn); + result = TPM2B_MAX_BUFFER_Unmarshal(&in->inData, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_EncryptDecrypt_inData); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_EncryptDecrypt(in, out); + rSize = sizeof(EncryptDecrypt_Out); + *respParmSize += TPM2B_MAX_BUFFER_Marshal(&out->outData, responseBuffer, &rSize); + *respParmSize += TPM2B_IV_Marshal(&out->ivOut, responseBuffer, &rSize); + break; +} +#endif // CC_EncryptDecrypt +#if CC_EncryptDecrypt2 +case TPM_CC_EncryptDecrypt2: +{ + EncryptDecrypt2_In* in = + (EncryptDecrypt2_In*)MemoryGetInBuffer(sizeof(EncryptDecrypt2_In)); + EncryptDecrypt2_Out* out = + (EncryptDecrypt2_Out*)MemoryGetOutBuffer(sizeof(EncryptDecrypt2_Out)); + in->keyHandle = handles[0]; + result = TPM2B_MAX_BUFFER_Unmarshal(&in->inData, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_EncryptDecrypt2_inData); + result = TPMI_YES_NO_Unmarshal(&in->decrypt, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_EncryptDecrypt2_decrypt); + result = + TPMI_ALG_CIPHER_MODE_Unmarshal(&in->mode, paramBuffer, paramBufferSize, TRUE); + EXIT_IF_ERROR_PLUS(RC_EncryptDecrypt2_mode); + result = TPM2B_IV_Unmarshal(&in->ivIn, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_EncryptDecrypt2_ivIn); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_EncryptDecrypt2(in, out); + rSize = sizeof(EncryptDecrypt2_Out); + *respParmSize += TPM2B_MAX_BUFFER_Marshal(&out->outData, responseBuffer, &rSize); + *respParmSize += TPM2B_IV_Marshal(&out->ivOut, responseBuffer, &rSize); + break; +} +#endif // CC_EncryptDecrypt2 +#if CC_Hash +case TPM_CC_Hash: +{ + Hash_In* in = (Hash_In*)MemoryGetInBuffer(sizeof(Hash_In)); + Hash_Out* out = (Hash_Out*)MemoryGetOutBuffer(sizeof(Hash_Out)); + result = TPM2B_MAX_BUFFER_Unmarshal(&in->data, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_Hash_data); + result = + TPMI_ALG_HASH_Unmarshal(&in->hashAlg, paramBuffer, paramBufferSize, FALSE); + EXIT_IF_ERROR_PLUS(RC_Hash_hashAlg); + result = TPMI_RH_HIERARCHY_Unmarshal( + &in->hierarchy, paramBuffer, paramBufferSize, TRUE); + EXIT_IF_ERROR_PLUS(RC_Hash_hierarchy); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_Hash(in, out); + rSize = sizeof(Hash_Out); + *respParmSize += TPM2B_DIGEST_Marshal(&out->outHash, responseBuffer, &rSize); + *respParmSize += + TPMT_TK_HASHCHECK_Marshal(&out->validation, responseBuffer, &rSize); + break; +} +#endif // CC_Hash +#if CC_HMAC +case TPM_CC_HMAC: +{ + HMAC_In* in = (HMAC_In*)MemoryGetInBuffer(sizeof(HMAC_In)); + HMAC_Out* out = (HMAC_Out*)MemoryGetOutBuffer(sizeof(HMAC_Out)); + in->handle = handles[0]; + result = TPM2B_MAX_BUFFER_Unmarshal(&in->buffer, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_HMAC_buffer); + result = + TPMI_ALG_HASH_Unmarshal(&in->hashAlg, paramBuffer, paramBufferSize, TRUE); + EXIT_IF_ERROR_PLUS(RC_HMAC_hashAlg); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_HMAC(in, out); + rSize = sizeof(HMAC_Out); + *respParmSize += TPM2B_DIGEST_Marshal(&out->outHMAC, responseBuffer, &rSize); + break; +} +#endif // CC_HMAC +#if CC_MAC +case TPM_CC_MAC: +{ + MAC_In* in = (MAC_In*)MemoryGetInBuffer(sizeof(MAC_In)); + MAC_Out* out = (MAC_Out*)MemoryGetOutBuffer(sizeof(MAC_Out)); + in->handle = handles[0]; + result = TPM2B_MAX_BUFFER_Unmarshal(&in->buffer, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_MAC_buffer); + result = TPMI_ALG_MAC_SCHEME_Unmarshal( + &in->inScheme, paramBuffer, paramBufferSize, TRUE); + EXIT_IF_ERROR_PLUS(RC_MAC_inScheme); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_MAC(in, out); + rSize = sizeof(MAC_Out); + *respParmSize += TPM2B_DIGEST_Marshal(&out->outMAC, responseBuffer, &rSize); + break; +} +#endif // CC_MAC +#if CC_GetRandom +case TPM_CC_GetRandom: +{ + GetRandom_In* in = (GetRandom_In*)MemoryGetInBuffer(sizeof(GetRandom_In)); + GetRandom_Out* out = (GetRandom_Out*)MemoryGetOutBuffer(sizeof(GetRandom_Out)); + result = UINT16_Unmarshal(&in->bytesRequested, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_GetRandom_bytesRequested); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_GetRandom(in, out); + rSize = sizeof(GetRandom_Out); + *respParmSize += TPM2B_DIGEST_Marshal(&out->randomBytes, responseBuffer, &rSize); + break; +} +#endif // CC_GetRandom +#if CC_StirRandom +case TPM_CC_StirRandom: +{ + StirRandom_In* in = (StirRandom_In*)MemoryGetInBuffer(sizeof(StirRandom_In)); + result = + TPM2B_SENSITIVE_DATA_Unmarshal(&in->inData, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_StirRandom_inData); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_StirRandom(in); + break; +} +#endif // CC_StirRandom +#if CC_HMAC_Start +case TPM_CC_HMAC_Start: +{ + HMAC_Start_In* in = (HMAC_Start_In*)MemoryGetInBuffer(sizeof(HMAC_Start_In)); + HMAC_Start_Out* out = (HMAC_Start_Out*)MemoryGetOutBuffer(sizeof(HMAC_Start_Out)); + in->handle = handles[0]; + result = TPM2B_AUTH_Unmarshal(&in->auth, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_HMAC_Start_auth); + result = + TPMI_ALG_HASH_Unmarshal(&in->hashAlg, paramBuffer, paramBufferSize, TRUE); + EXIT_IF_ERROR_PLUS(RC_HMAC_Start_hashAlg); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_HMAC_Start(in, out); + rSize = sizeof(HMAC_Start_Out); + if(TPM_RC_SUCCESS != result) + goto Exit; + command->handles[command->handleNum++] = out->sequenceHandle; + break; +} +#endif // CC_HMAC_Start +#if CC_MAC_Start +case TPM_CC_MAC_Start: +{ + MAC_Start_In* in = (MAC_Start_In*)MemoryGetInBuffer(sizeof(MAC_Start_In)); + MAC_Start_Out* out = (MAC_Start_Out*)MemoryGetOutBuffer(sizeof(MAC_Start_Out)); + in->handle = handles[0]; + result = TPM2B_AUTH_Unmarshal(&in->auth, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_MAC_Start_auth); + result = TPMI_ALG_MAC_SCHEME_Unmarshal( + &in->inScheme, paramBuffer, paramBufferSize, TRUE); + EXIT_IF_ERROR_PLUS(RC_MAC_Start_inScheme); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_MAC_Start(in, out); + rSize = sizeof(MAC_Start_Out); + if(TPM_RC_SUCCESS != result) + goto Exit; + command->handles[command->handleNum++] = out->sequenceHandle; + break; +} +#endif // CC_MAC_Start +#if CC_HashSequenceStart +case TPM_CC_HashSequenceStart: +{ + HashSequenceStart_In* in = + (HashSequenceStart_In*)MemoryGetInBuffer(sizeof(HashSequenceStart_In)); + HashSequenceStart_Out* out = + (HashSequenceStart_Out*)MemoryGetOutBuffer(sizeof(HashSequenceStart_Out)); + result = TPM2B_AUTH_Unmarshal(&in->auth, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_HashSequenceStart_auth); + result = + TPMI_ALG_HASH_Unmarshal(&in->hashAlg, paramBuffer, paramBufferSize, TRUE); + EXIT_IF_ERROR_PLUS(RC_HashSequenceStart_hashAlg); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_HashSequenceStart(in, out); + rSize = sizeof(HashSequenceStart_Out); + if(TPM_RC_SUCCESS != result) + goto Exit; + command->handles[command->handleNum++] = out->sequenceHandle; + break; +} +#endif // CC_HashSequenceStart +#if CC_SequenceUpdate +case TPM_CC_SequenceUpdate: +{ + SequenceUpdate_In* in = + (SequenceUpdate_In*)MemoryGetInBuffer(sizeof(SequenceUpdate_In)); + in->sequenceHandle = handles[0]; + result = TPM2B_MAX_BUFFER_Unmarshal(&in->buffer, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_SequenceUpdate_buffer); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_SequenceUpdate(in); + break; +} +#endif // CC_SequenceUpdate +#if CC_SequenceComplete +case TPM_CC_SequenceComplete: +{ + SequenceComplete_In* in = + (SequenceComplete_In*)MemoryGetInBuffer(sizeof(SequenceComplete_In)); + SequenceComplete_Out* out = + (SequenceComplete_Out*)MemoryGetOutBuffer(sizeof(SequenceComplete_Out)); + in->sequenceHandle = handles[0]; + result = TPM2B_MAX_BUFFER_Unmarshal(&in->buffer, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_SequenceComplete_buffer); + result = TPMI_RH_HIERARCHY_Unmarshal( + &in->hierarchy, paramBuffer, paramBufferSize, TRUE); + EXIT_IF_ERROR_PLUS(RC_SequenceComplete_hierarchy); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_SequenceComplete(in, out); + rSize = sizeof(SequenceComplete_Out); + *respParmSize += TPM2B_DIGEST_Marshal(&out->result, responseBuffer, &rSize); + *respParmSize += + TPMT_TK_HASHCHECK_Marshal(&out->validation, responseBuffer, &rSize); + break; +} +#endif // CC_SequenceComplete +#if CC_EventSequenceComplete +case TPM_CC_EventSequenceComplete: +{ + EventSequenceComplete_In* in = (EventSequenceComplete_In*)MemoryGetInBuffer( + sizeof(EventSequenceComplete_In)); + EventSequenceComplete_Out* out = (EventSequenceComplete_Out*)MemoryGetOutBuffer( + sizeof(EventSequenceComplete_Out)); + in->pcrHandle = handles[0]; + in->sequenceHandle = handles[1]; + result = TPM2B_MAX_BUFFER_Unmarshal(&in->buffer, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_EventSequenceComplete_buffer); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_EventSequenceComplete(in, out); + rSize = sizeof(EventSequenceComplete_Out); + *respParmSize += + TPML_DIGEST_VALUES_Marshal(&out->results, responseBuffer, &rSize); + break; +} +#endif // CC_EventSequenceComplete +#if CC_Certify +case TPM_CC_Certify: +{ + Certify_In* in = (Certify_In*)MemoryGetInBuffer(sizeof(Certify_In)); + Certify_Out* out = (Certify_Out*)MemoryGetOutBuffer(sizeof(Certify_Out)); + in->objectHandle = handles[0]; + in->signHandle = handles[1]; + result = TPM2B_DATA_Unmarshal(&in->qualifyingData, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_Certify_qualifyingData); + result = + TPMT_SIG_SCHEME_Unmarshal(&in->inScheme, paramBuffer, paramBufferSize, TRUE); + EXIT_IF_ERROR_PLUS(RC_Certify_inScheme); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_Certify(in, out); + rSize = sizeof(Certify_Out); + *respParmSize += TPM2B_ATTEST_Marshal(&out->certifyInfo, responseBuffer, &rSize); + *respParmSize += TPMT_SIGNATURE_Marshal(&out->signature, responseBuffer, &rSize); + break; +} +#endif // CC_Certify +#if CC_CertifyCreation +case TPM_CC_CertifyCreation: +{ + CertifyCreation_In* in = + (CertifyCreation_In*)MemoryGetInBuffer(sizeof(CertifyCreation_In)); + CertifyCreation_Out* out = + (CertifyCreation_Out*)MemoryGetOutBuffer(sizeof(CertifyCreation_Out)); + in->signHandle = handles[0]; + in->objectHandle = handles[1]; + result = TPM2B_DATA_Unmarshal(&in->qualifyingData, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_CertifyCreation_qualifyingData); + result = TPM2B_DIGEST_Unmarshal(&in->creationHash, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_CertifyCreation_creationHash); + result = + TPMT_SIG_SCHEME_Unmarshal(&in->inScheme, paramBuffer, paramBufferSize, TRUE); + EXIT_IF_ERROR_PLUS(RC_CertifyCreation_inScheme); + result = + TPMT_TK_CREATION_Unmarshal(&in->creationTicket, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_CertifyCreation_creationTicket); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_CertifyCreation(in, out); + rSize = sizeof(CertifyCreation_Out); + *respParmSize += TPM2B_ATTEST_Marshal(&out->certifyInfo, responseBuffer, &rSize); + *respParmSize += TPMT_SIGNATURE_Marshal(&out->signature, responseBuffer, &rSize); + break; +} +#endif // CC_CertifyCreation +#if CC_Quote +case TPM_CC_Quote: +{ + Quote_In* in = (Quote_In*)MemoryGetInBuffer(sizeof(Quote_In)); + Quote_Out* out = (Quote_Out*)MemoryGetOutBuffer(sizeof(Quote_Out)); + in->signHandle = handles[0]; + result = TPM2B_DATA_Unmarshal(&in->qualifyingData, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_Quote_qualifyingData); + result = + TPMT_SIG_SCHEME_Unmarshal(&in->inScheme, paramBuffer, paramBufferSize, TRUE); + EXIT_IF_ERROR_PLUS(RC_Quote_inScheme); + result = + TPML_PCR_SELECTION_Unmarshal(&in->PCRselect, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_Quote_PCRselect); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_Quote(in, out); + rSize = sizeof(Quote_Out); + *respParmSize += TPM2B_ATTEST_Marshal(&out->quoted, responseBuffer, &rSize); + *respParmSize += TPMT_SIGNATURE_Marshal(&out->signature, responseBuffer, &rSize); + break; +} +#endif // CC_Quote +#if CC_GetSessionAuditDigest +case TPM_CC_GetSessionAuditDigest: +{ + GetSessionAuditDigest_In* in = (GetSessionAuditDigest_In*)MemoryGetInBuffer( + sizeof(GetSessionAuditDigest_In)); + GetSessionAuditDigest_Out* out = (GetSessionAuditDigest_Out*)MemoryGetOutBuffer( + sizeof(GetSessionAuditDigest_Out)); + in->privacyAdminHandle = handles[0]; + in->signHandle = handles[1]; + in->sessionHandle = handles[2]; + result = TPM2B_DATA_Unmarshal(&in->qualifyingData, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_GetSessionAuditDigest_qualifyingData); + result = + TPMT_SIG_SCHEME_Unmarshal(&in->inScheme, paramBuffer, paramBufferSize, TRUE); + EXIT_IF_ERROR_PLUS(RC_GetSessionAuditDigest_inScheme); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_GetSessionAuditDigest(in, out); + rSize = sizeof(GetSessionAuditDigest_Out); + *respParmSize += TPM2B_ATTEST_Marshal(&out->auditInfo, responseBuffer, &rSize); + *respParmSize += TPMT_SIGNATURE_Marshal(&out->signature, responseBuffer, &rSize); + break; +} +#endif // CC_GetSessionAuditDigest +#if CC_GetCommandAuditDigest +case TPM_CC_GetCommandAuditDigest: +{ + GetCommandAuditDigest_In* in = (GetCommandAuditDigest_In*)MemoryGetInBuffer( + sizeof(GetCommandAuditDigest_In)); + GetCommandAuditDigest_Out* out = (GetCommandAuditDigest_Out*)MemoryGetOutBuffer( + sizeof(GetCommandAuditDigest_Out)); + in->privacyHandle = handles[0]; + in->signHandle = handles[1]; + result = TPM2B_DATA_Unmarshal(&in->qualifyingData, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_GetCommandAuditDigest_qualifyingData); + result = + TPMT_SIG_SCHEME_Unmarshal(&in->inScheme, paramBuffer, paramBufferSize, TRUE); + EXIT_IF_ERROR_PLUS(RC_GetCommandAuditDigest_inScheme); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_GetCommandAuditDigest(in, out); + rSize = sizeof(GetCommandAuditDigest_Out); + *respParmSize += TPM2B_ATTEST_Marshal(&out->auditInfo, responseBuffer, &rSize); + *respParmSize += TPMT_SIGNATURE_Marshal(&out->signature, responseBuffer, &rSize); + break; +} +#endif // CC_GetCommandAuditDigest +#if CC_GetTime +case TPM_CC_GetTime: +{ + GetTime_In* in = (GetTime_In*)MemoryGetInBuffer(sizeof(GetTime_In)); + GetTime_Out* out = (GetTime_Out*)MemoryGetOutBuffer(sizeof(GetTime_Out)); + in->privacyAdminHandle = handles[0]; + in->signHandle = handles[1]; + result = TPM2B_DATA_Unmarshal(&in->qualifyingData, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_GetTime_qualifyingData); + result = + TPMT_SIG_SCHEME_Unmarshal(&in->inScheme, paramBuffer, paramBufferSize, TRUE); + EXIT_IF_ERROR_PLUS(RC_GetTime_inScheme); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_GetTime(in, out); + rSize = sizeof(GetTime_Out); + *respParmSize += TPM2B_ATTEST_Marshal(&out->timeInfo, responseBuffer, &rSize); + *respParmSize += TPMT_SIGNATURE_Marshal(&out->signature, responseBuffer, &rSize); + break; +} +#endif // CC_GetTime +#if CC_CertifyX509 +case TPM_CC_CertifyX509: +{ + CertifyX509_In* in = (CertifyX509_In*)MemoryGetInBuffer(sizeof(CertifyX509_In)); + CertifyX509_Out* out = + (CertifyX509_Out*)MemoryGetOutBuffer(sizeof(CertifyX509_Out)); + in->objectHandle = handles[0]; + in->signHandle = handles[1]; + result = TPM2B_DATA_Unmarshal(&in->reserved, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_CertifyX509_reserved); + result = + TPMT_SIG_SCHEME_Unmarshal(&in->inScheme, paramBuffer, paramBufferSize, TRUE); + EXIT_IF_ERROR_PLUS(RC_CertifyX509_inScheme); + result = TPM2B_MAX_BUFFER_Unmarshal( + &in->partialCertificate, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_CertifyX509_partialCertificate); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_CertifyX509(in, out); + rSize = sizeof(CertifyX509_Out); + *respParmSize += + TPM2B_MAX_BUFFER_Marshal(&out->addedToCertificate, responseBuffer, &rSize); + *respParmSize += TPM2B_DIGEST_Marshal(&out->tbsDigest, responseBuffer, &rSize); + *respParmSize += TPMT_SIGNATURE_Marshal(&out->signature, responseBuffer, &rSize); + break; +} +#endif // CC_CertifyX509 +#if CC_Commit +case TPM_CC_Commit: +{ + Commit_In* in = (Commit_In*)MemoryGetInBuffer(sizeof(Commit_In)); + Commit_Out* out = (Commit_Out*)MemoryGetOutBuffer(sizeof(Commit_Out)); + in->signHandle = handles[0]; + result = TPM2B_ECC_POINT_Unmarshal(&in->P1, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_Commit_P1); + result = TPM2B_SENSITIVE_DATA_Unmarshal(&in->s2, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_Commit_s2); + result = TPM2B_ECC_PARAMETER_Unmarshal(&in->y2, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_Commit_y2); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_Commit(in, out); + rSize = sizeof(Commit_Out); + *respParmSize += TPM2B_ECC_POINT_Marshal(&out->K, responseBuffer, &rSize); + *respParmSize += TPM2B_ECC_POINT_Marshal(&out->L, responseBuffer, &rSize); + *respParmSize += TPM2B_ECC_POINT_Marshal(&out->E, responseBuffer, &rSize); + *respParmSize += UINT16_Marshal(&out->counter, responseBuffer, &rSize); + break; +} +#endif // CC_Commit +#if CC_EC_Ephemeral +case TPM_CC_EC_Ephemeral: +{ + EC_Ephemeral_In* in = + (EC_Ephemeral_In*)MemoryGetInBuffer(sizeof(EC_Ephemeral_In)); + EC_Ephemeral_Out* out = + (EC_Ephemeral_Out*)MemoryGetOutBuffer(sizeof(EC_Ephemeral_Out)); + result = TPMI_ECC_CURVE_Unmarshal(&in->curveID, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_EC_Ephemeral_curveID); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_EC_Ephemeral(in, out); + rSize = sizeof(EC_Ephemeral_Out); + *respParmSize += TPM2B_ECC_POINT_Marshal(&out->Q, responseBuffer, &rSize); + *respParmSize += UINT16_Marshal(&out->counter, responseBuffer, &rSize); + break; +} +#endif // CC_EC_Ephemeral +#if CC_VerifySignature +case TPM_CC_VerifySignature: +{ + VerifySignature_In* in = + (VerifySignature_In*)MemoryGetInBuffer(sizeof(VerifySignature_In)); + VerifySignature_Out* out = + (VerifySignature_Out*)MemoryGetOutBuffer(sizeof(VerifySignature_Out)); + in->keyHandle = handles[0]; + result = TPM2B_DIGEST_Unmarshal(&in->digest, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_VerifySignature_digest); + result = + TPMT_SIGNATURE_Unmarshal(&in->signature, paramBuffer, paramBufferSize, FALSE); + EXIT_IF_ERROR_PLUS(RC_VerifySignature_signature); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_VerifySignature(in, out); + rSize = sizeof(VerifySignature_Out); + *respParmSize += + TPMT_TK_VERIFIED_Marshal(&out->validation, responseBuffer, &rSize); + break; +} +#endif // CC_VerifySignature +#if CC_Sign +case TPM_CC_Sign: +{ + Sign_In* in = (Sign_In*)MemoryGetInBuffer(sizeof(Sign_In)); + Sign_Out* out = (Sign_Out*)MemoryGetOutBuffer(sizeof(Sign_Out)); + in->keyHandle = handles[0]; + result = TPM2B_DIGEST_Unmarshal(&in->digest, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_Sign_digest); + result = + TPMT_SIG_SCHEME_Unmarshal(&in->inScheme, paramBuffer, paramBufferSize, TRUE); + EXIT_IF_ERROR_PLUS(RC_Sign_inScheme); + result = + TPMT_TK_HASHCHECK_Unmarshal(&in->validation, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_Sign_validation); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_Sign(in, out); + rSize = sizeof(Sign_Out); + *respParmSize += TPMT_SIGNATURE_Marshal(&out->signature, responseBuffer, &rSize); + break; +} +#endif // CC_Sign +#if CC_SetCommandCodeAuditStatus +case TPM_CC_SetCommandCodeAuditStatus: +{ + SetCommandCodeAuditStatus_In* in = + (SetCommandCodeAuditStatus_In*)MemoryGetInBuffer( + sizeof(SetCommandCodeAuditStatus_In)); + in->auth = handles[0]; + result = + TPMI_ALG_HASH_Unmarshal(&in->auditAlg, paramBuffer, paramBufferSize, TRUE); + EXIT_IF_ERROR_PLUS(RC_SetCommandCodeAuditStatus_auditAlg); + result = TPML_CC_Unmarshal(&in->setList, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_SetCommandCodeAuditStatus_setList); + result = TPML_CC_Unmarshal(&in->clearList, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_SetCommandCodeAuditStatus_clearList); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_SetCommandCodeAuditStatus(in); + break; +} +#endif // CC_SetCommandCodeAuditStatus +#if CC_PCR_Extend +case TPM_CC_PCR_Extend: +{ + PCR_Extend_In* in = (PCR_Extend_In*)MemoryGetInBuffer(sizeof(PCR_Extend_In)); + in->pcrHandle = handles[0]; + result = TPML_DIGEST_VALUES_Unmarshal(&in->digests, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PCR_Extend_digests); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_PCR_Extend(in); + break; +} +#endif // CC_PCR_Extend +#if CC_PCR_Event +case TPM_CC_PCR_Event: +{ + PCR_Event_In* in = (PCR_Event_In*)MemoryGetInBuffer(sizeof(PCR_Event_In)); + PCR_Event_Out* out = (PCR_Event_Out*)MemoryGetOutBuffer(sizeof(PCR_Event_Out)); + in->pcrHandle = handles[0]; + result = TPM2B_EVENT_Unmarshal(&in->eventData, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PCR_Event_eventData); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_PCR_Event(in, out); + rSize = sizeof(PCR_Event_Out); + *respParmSize += + TPML_DIGEST_VALUES_Marshal(&out->digests, responseBuffer, &rSize); + break; +} +#endif // CC_PCR_Event +#if CC_PCR_Read +case TPM_CC_PCR_Read: +{ + PCR_Read_In* in = (PCR_Read_In*)MemoryGetInBuffer(sizeof(PCR_Read_In)); + PCR_Read_Out* out = (PCR_Read_Out*)MemoryGetOutBuffer(sizeof(PCR_Read_Out)); + result = TPML_PCR_SELECTION_Unmarshal( + &in->pcrSelectionIn, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PCR_Read_pcrSelectionIn); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_PCR_Read(in, out); + rSize = sizeof(PCR_Read_Out); + *respParmSize += UINT32_Marshal(&out->pcrUpdateCounter, responseBuffer, &rSize); + *respParmSize += + TPML_PCR_SELECTION_Marshal(&out->pcrSelectionOut, responseBuffer, &rSize); + *respParmSize += TPML_DIGEST_Marshal(&out->pcrValues, responseBuffer, &rSize); + break; +} +#endif // CC_PCR_Read +#if CC_PCR_Allocate +case TPM_CC_PCR_Allocate: +{ + PCR_Allocate_In* in = + (PCR_Allocate_In*)MemoryGetInBuffer(sizeof(PCR_Allocate_In)); + PCR_Allocate_Out* out = + (PCR_Allocate_Out*)MemoryGetOutBuffer(sizeof(PCR_Allocate_Out)); + in->authHandle = handles[0]; + result = TPML_PCR_SELECTION_Unmarshal( + &in->pcrAllocation, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PCR_Allocate_pcrAllocation); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_PCR_Allocate(in, out); + rSize = sizeof(PCR_Allocate_Out); + *respParmSize += + TPMI_YES_NO_Marshal(&out->allocationSuccess, responseBuffer, &rSize); + *respParmSize += UINT32_Marshal(&out->maxPCR, responseBuffer, &rSize); + *respParmSize += UINT32_Marshal(&out->sizeNeeded, responseBuffer, &rSize); + *respParmSize += UINT32_Marshal(&out->sizeAvailable, responseBuffer, &rSize); + break; +} +#endif // CC_PCR_Allocate +#if CC_PCR_SetAuthPolicy +case TPM_CC_PCR_SetAuthPolicy: +{ + PCR_SetAuthPolicy_In* in = + (PCR_SetAuthPolicy_In*)MemoryGetInBuffer(sizeof(PCR_SetAuthPolicy_In)); + in->authHandle = handles[0]; + result = TPM2B_DIGEST_Unmarshal(&in->authPolicy, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PCR_SetAuthPolicy_authPolicy); + result = + TPMI_ALG_HASH_Unmarshal(&in->hashAlg, paramBuffer, paramBufferSize, TRUE); + EXIT_IF_ERROR_PLUS(RC_PCR_SetAuthPolicy_hashAlg); + result = TPMI_DH_PCR_Unmarshal(&in->pcrNum, paramBuffer, paramBufferSize, FALSE); + EXIT_IF_ERROR_PLUS(RC_PCR_SetAuthPolicy_pcrNum); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_PCR_SetAuthPolicy(in); + break; +} +#endif // CC_PCR_SetAuthPolicy +#if CC_PCR_SetAuthValue +case TPM_CC_PCR_SetAuthValue: +{ + PCR_SetAuthValue_In* in = + (PCR_SetAuthValue_In*)MemoryGetInBuffer(sizeof(PCR_SetAuthValue_In)); + in->pcrHandle = handles[0]; + result = TPM2B_DIGEST_Unmarshal(&in->auth, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PCR_SetAuthValue_auth); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_PCR_SetAuthValue(in); + break; +} +#endif // CC_PCR_SetAuthValue +#if CC_PCR_Reset +case TPM_CC_PCR_Reset: +{ + PCR_Reset_In* in = (PCR_Reset_In*)MemoryGetInBuffer(sizeof(PCR_Reset_In)); + in->pcrHandle = handles[0]; + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_PCR_Reset(in); + break; +} +#endif // CC_PCR_Reset +#if CC_PolicySigned +case TPM_CC_PolicySigned: +{ + PolicySigned_In* in = + (PolicySigned_In*)MemoryGetInBuffer(sizeof(PolicySigned_In)); + PolicySigned_Out* out = + (PolicySigned_Out*)MemoryGetOutBuffer(sizeof(PolicySigned_Out)); + in->authObject = handles[0]; + in->policySession = handles[1]; + result = TPM2B_NONCE_Unmarshal(&in->nonceTPM, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PolicySigned_nonceTPM); + result = TPM2B_DIGEST_Unmarshal(&in->cpHashA, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PolicySigned_cpHashA); + result = TPM2B_NONCE_Unmarshal(&in->policyRef, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PolicySigned_policyRef); + result = INT32_Unmarshal(&in->expiration, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PolicySigned_expiration); + result = TPMT_SIGNATURE_Unmarshal(&in->auth, paramBuffer, paramBufferSize, FALSE); + EXIT_IF_ERROR_PLUS(RC_PolicySigned_auth); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_PolicySigned(in, out); + rSize = sizeof(PolicySigned_Out); + *respParmSize += TPM2B_TIMEOUT_Marshal(&out->timeout, responseBuffer, &rSize); + *respParmSize += TPMT_TK_AUTH_Marshal(&out->policyTicket, responseBuffer, &rSize); + break; +} +#endif // CC_PolicySigned +#if CC_PolicySecret +case TPM_CC_PolicySecret: +{ + PolicySecret_In* in = + (PolicySecret_In*)MemoryGetInBuffer(sizeof(PolicySecret_In)); + PolicySecret_Out* out = + (PolicySecret_Out*)MemoryGetOutBuffer(sizeof(PolicySecret_Out)); + in->authHandle = handles[0]; + in->policySession = handles[1]; + result = TPM2B_NONCE_Unmarshal(&in->nonceTPM, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PolicySecret_nonceTPM); + result = TPM2B_DIGEST_Unmarshal(&in->cpHashA, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PolicySecret_cpHashA); + result = TPM2B_NONCE_Unmarshal(&in->policyRef, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PolicySecret_policyRef); + result = INT32_Unmarshal(&in->expiration, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PolicySecret_expiration); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_PolicySecret(in, out); + rSize = sizeof(PolicySecret_Out); + *respParmSize += TPM2B_TIMEOUT_Marshal(&out->timeout, responseBuffer, &rSize); + *respParmSize += TPMT_TK_AUTH_Marshal(&out->policyTicket, responseBuffer, &rSize); + break; +} +#endif // CC_PolicySecret +#if CC_PolicyTicket +case TPM_CC_PolicyTicket: +{ + PolicyTicket_In* in = + (PolicyTicket_In*)MemoryGetInBuffer(sizeof(PolicyTicket_In)); + in->policySession = handles[0]; + result = TPM2B_TIMEOUT_Unmarshal(&in->timeout, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PolicyTicket_timeout); + result = TPM2B_DIGEST_Unmarshal(&in->cpHashA, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PolicyTicket_cpHashA); + result = TPM2B_NONCE_Unmarshal(&in->policyRef, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PolicyTicket_policyRef); + result = TPM2B_NAME_Unmarshal(&in->authName, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PolicyTicket_authName); + result = TPMT_TK_AUTH_Unmarshal(&in->ticket, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PolicyTicket_ticket); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_PolicyTicket(in); + break; +} +#endif // CC_PolicyTicket +#if CC_PolicyOR +case TPM_CC_PolicyOR: +{ + PolicyOR_In* in = (PolicyOR_In*)MemoryGetInBuffer(sizeof(PolicyOR_In)); + in->policySession = handles[0]; + result = TPML_DIGEST_Unmarshal(&in->pHashList, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PolicyOR_pHashList); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_PolicyOR(in); + break; +} +#endif // CC_PolicyOR +#if CC_PolicyPCR +case TPM_CC_PolicyPCR: +{ + PolicyPCR_In* in = (PolicyPCR_In*)MemoryGetInBuffer(sizeof(PolicyPCR_In)); + in->policySession = handles[0]; + result = TPM2B_DIGEST_Unmarshal(&in->pcrDigest, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PolicyPCR_pcrDigest); + result = TPML_PCR_SELECTION_Unmarshal(&in->pcrs, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PolicyPCR_pcrs); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_PolicyPCR(in); + break; +} +#endif // CC_PolicyPCR +#if CC_PolicyLocality +case TPM_CC_PolicyLocality: +{ + PolicyLocality_In* in = + (PolicyLocality_In*)MemoryGetInBuffer(sizeof(PolicyLocality_In)); + in->policySession = handles[0]; + result = TPMA_LOCALITY_Unmarshal(&in->locality, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PolicyLocality_locality); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_PolicyLocality(in); + break; +} +#endif // CC_PolicyLocality +#if CC_PolicyNV +case TPM_CC_PolicyNV: +{ + PolicyNV_In* in = (PolicyNV_In*)MemoryGetInBuffer(sizeof(PolicyNV_In)); + in->authHandle = handles[0]; + in->nvIndex = handles[1]; + in->policySession = handles[2]; + result = TPM2B_OPERAND_Unmarshal(&in->operandB, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PolicyNV_operandB); + result = UINT16_Unmarshal(&in->offset, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PolicyNV_offset); + result = TPM_EO_Unmarshal(&in->operation, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PolicyNV_operation); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_PolicyNV(in); + break; +} +#endif // CC_PolicyNV +#if CC_PolicyCounterTimer +case TPM_CC_PolicyCounterTimer: +{ + PolicyCounterTimer_In* in = + (PolicyCounterTimer_In*)MemoryGetInBuffer(sizeof(PolicyCounterTimer_In)); + in->policySession = handles[0]; + result = TPM2B_OPERAND_Unmarshal(&in->operandB, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PolicyCounterTimer_operandB); + result = UINT16_Unmarshal(&in->offset, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PolicyCounterTimer_offset); + result = TPM_EO_Unmarshal(&in->operation, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PolicyCounterTimer_operation); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_PolicyCounterTimer(in); + break; +} +#endif // CC_PolicyCounterTimer +#if CC_PolicyCommandCode +case TPM_CC_PolicyCommandCode: +{ + PolicyCommandCode_In* in = + (PolicyCommandCode_In*)MemoryGetInBuffer(sizeof(PolicyCommandCode_In)); + in->policySession = handles[0]; + result = TPM_CC_Unmarshal(&in->code, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PolicyCommandCode_code); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_PolicyCommandCode(in); + break; +} +#endif // CC_PolicyCommandCode +#if CC_PolicyPhysicalPresence +case TPM_CC_PolicyPhysicalPresence: +{ + PolicyPhysicalPresence_In* in = (PolicyPhysicalPresence_In*)MemoryGetInBuffer( + sizeof(PolicyPhysicalPresence_In)); + in->policySession = handles[0]; + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_PolicyPhysicalPresence(in); + break; +} +#endif // CC_PolicyPhysicalPresence +#if CC_PolicyCpHash +case TPM_CC_PolicyCpHash: +{ + PolicyCpHash_In* in = + (PolicyCpHash_In*)MemoryGetInBuffer(sizeof(PolicyCpHash_In)); + in->policySession = handles[0]; + result = TPM2B_DIGEST_Unmarshal(&in->cpHashA, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PolicyCpHash_cpHashA); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_PolicyCpHash(in); + break; +} +#endif // CC_PolicyCpHash +#if CC_PolicyNameHash +case TPM_CC_PolicyNameHash: +{ + PolicyNameHash_In* in = + (PolicyNameHash_In*)MemoryGetInBuffer(sizeof(PolicyNameHash_In)); + in->policySession = handles[0]; + result = TPM2B_DIGEST_Unmarshal(&in->nameHash, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PolicyNameHash_nameHash); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_PolicyNameHash(in); + break; +} +#endif // CC_PolicyNameHash +#if CC_PolicyDuplicationSelect +case TPM_CC_PolicyDuplicationSelect: +{ + PolicyDuplicationSelect_In* in = (PolicyDuplicationSelect_In*)MemoryGetInBuffer( + sizeof(PolicyDuplicationSelect_In)); + in->policySession = handles[0]; + result = TPM2B_NAME_Unmarshal(&in->objectName, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PolicyDuplicationSelect_objectName); + result = TPM2B_NAME_Unmarshal(&in->newParentName, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PolicyDuplicationSelect_newParentName); + result = TPMI_YES_NO_Unmarshal(&in->includeObject, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PolicyDuplicationSelect_includeObject); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_PolicyDuplicationSelect(in); + break; +} +#endif // CC_PolicyDuplicationSelect +#if CC_PolicyAuthorize +case TPM_CC_PolicyAuthorize: +{ + PolicyAuthorize_In* in = + (PolicyAuthorize_In*)MemoryGetInBuffer(sizeof(PolicyAuthorize_In)); + in->policySession = handles[0]; + result = + TPM2B_DIGEST_Unmarshal(&in->approvedPolicy, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PolicyAuthorize_approvedPolicy); + result = TPM2B_NONCE_Unmarshal(&in->policyRef, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PolicyAuthorize_policyRef); + result = TPM2B_NAME_Unmarshal(&in->keySign, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PolicyAuthorize_keySign); + result = + TPMT_TK_VERIFIED_Unmarshal(&in->checkTicket, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PolicyAuthorize_checkTicket); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_PolicyAuthorize(in); + break; +} +#endif // CC_PolicyAuthorize +#if CC_PolicyAuthValue +case TPM_CC_PolicyAuthValue: +{ + PolicyAuthValue_In* in = + (PolicyAuthValue_In*)MemoryGetInBuffer(sizeof(PolicyAuthValue_In)); + in->policySession = handles[0]; + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_PolicyAuthValue(in); + break; +} +#endif // CC_PolicyAuthValue +#if CC_PolicyPassword +case TPM_CC_PolicyPassword: +{ + PolicyPassword_In* in = + (PolicyPassword_In*)MemoryGetInBuffer(sizeof(PolicyPassword_In)); + in->policySession = handles[0]; + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_PolicyPassword(in); + break; +} +#endif // CC_PolicyPassword +#if CC_PolicyGetDigest +case TPM_CC_PolicyGetDigest: +{ + PolicyGetDigest_In* in = + (PolicyGetDigest_In*)MemoryGetInBuffer(sizeof(PolicyGetDigest_In)); + PolicyGetDigest_Out* out = + (PolicyGetDigest_Out*)MemoryGetOutBuffer(sizeof(PolicyGetDigest_Out)); + in->policySession = handles[0]; + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_PolicyGetDigest(in, out); + rSize = sizeof(PolicyGetDigest_Out); + *respParmSize += TPM2B_DIGEST_Marshal(&out->policyDigest, responseBuffer, &rSize); + break; +} +#endif // CC_PolicyGetDigest +#if CC_PolicyNvWritten +case TPM_CC_PolicyNvWritten: +{ + PolicyNvWritten_In* in = + (PolicyNvWritten_In*)MemoryGetInBuffer(sizeof(PolicyNvWritten_In)); + in->policySession = handles[0]; + result = TPMI_YES_NO_Unmarshal(&in->writtenSet, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PolicyNvWritten_writtenSet); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_PolicyNvWritten(in); + break; +} +#endif // CC_PolicyNvWritten +#if CC_PolicyTemplate +case TPM_CC_PolicyTemplate: +{ + PolicyTemplate_In* in = + (PolicyTemplate_In*)MemoryGetInBuffer(sizeof(PolicyTemplate_In)); + in->policySession = handles[0]; + result = TPM2B_DIGEST_Unmarshal(&in->templateHash, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PolicyTemplate_templateHash); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_PolicyTemplate(in); + break; +} +#endif // CC_PolicyTemplate +#if CC_PolicyAuthorizeNV +case TPM_CC_PolicyAuthorizeNV: +{ + PolicyAuthorizeNV_In* in = + (PolicyAuthorizeNV_In*)MemoryGetInBuffer(sizeof(PolicyAuthorizeNV_In)); + in->authHandle = handles[0]; + in->nvIndex = handles[1]; + in->policySession = handles[2]; + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_PolicyAuthorizeNV(in); + break; +} +#endif // CC_PolicyAuthorizeNV +#if CC_CreatePrimary +case TPM_CC_CreatePrimary: +{ + CreatePrimary_In* in = + (CreatePrimary_In*)MemoryGetInBuffer(sizeof(CreatePrimary_In)); + CreatePrimary_Out* out = + (CreatePrimary_Out*)MemoryGetOutBuffer(sizeof(CreatePrimary_Out)); + in->primaryHandle = handles[0]; + result = TPM2B_SENSITIVE_CREATE_Unmarshal( + &in->inSensitive, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_CreatePrimary_inSensitive); + result = + TPM2B_PUBLIC_Unmarshal(&in->inPublic, paramBuffer, paramBufferSize, FALSE); + EXIT_IF_ERROR_PLUS(RC_CreatePrimary_inPublic); + result = TPM2B_DATA_Unmarshal(&in->outsideInfo, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_CreatePrimary_outsideInfo); + result = + TPML_PCR_SELECTION_Unmarshal(&in->creationPCR, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_CreatePrimary_creationPCR); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_CreatePrimary(in, out); + rSize = sizeof(CreatePrimary_Out); + if(TPM_RC_SUCCESS != result) + goto Exit; + command->handles[command->handleNum++] = out->objectHandle; + *respParmSize += TPM2B_PUBLIC_Marshal(&out->outPublic, responseBuffer, &rSize); + *respParmSize += + TPM2B_CREATION_DATA_Marshal(&out->creationData, responseBuffer, &rSize); + *respParmSize += TPM2B_DIGEST_Marshal(&out->creationHash, responseBuffer, &rSize); + *respParmSize += + TPMT_TK_CREATION_Marshal(&out->creationTicket, responseBuffer, &rSize); + *respParmSize += TPM2B_NAME_Marshal(&out->name, responseBuffer, &rSize); + break; +} +#endif // CC_CreatePrimary +#if CC_HierarchyControl +case TPM_CC_HierarchyControl: +{ + HierarchyControl_In* in = + (HierarchyControl_In*)MemoryGetInBuffer(sizeof(HierarchyControl_In)); + in->authHandle = handles[0]; + result = + TPMI_RH_ENABLES_Unmarshal(&in->enable, paramBuffer, paramBufferSize, FALSE); + EXIT_IF_ERROR_PLUS(RC_HierarchyControl_enable); + result = TPMI_YES_NO_Unmarshal(&in->state, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_HierarchyControl_state); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_HierarchyControl(in); + break; +} +#endif // CC_HierarchyControl +#if CC_SetPrimaryPolicy +case TPM_CC_SetPrimaryPolicy: +{ + SetPrimaryPolicy_In* in = + (SetPrimaryPolicy_In*)MemoryGetInBuffer(sizeof(SetPrimaryPolicy_In)); + in->authHandle = handles[0]; + result = TPM2B_DIGEST_Unmarshal(&in->authPolicy, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_SetPrimaryPolicy_authPolicy); + result = + TPMI_ALG_HASH_Unmarshal(&in->hashAlg, paramBuffer, paramBufferSize, TRUE); + EXIT_IF_ERROR_PLUS(RC_SetPrimaryPolicy_hashAlg); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_SetPrimaryPolicy(in); + break; +} +#endif // CC_SetPrimaryPolicy +#if CC_ChangePPS +case TPM_CC_ChangePPS: +{ + ChangePPS_In* in = (ChangePPS_In*)MemoryGetInBuffer(sizeof(ChangePPS_In)); + in->authHandle = handles[0]; + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_ChangePPS(in); + break; +} +#endif // CC_ChangePPS +#if CC_ChangeEPS +case TPM_CC_ChangeEPS: +{ + ChangeEPS_In* in = (ChangeEPS_In*)MemoryGetInBuffer(sizeof(ChangeEPS_In)); + in->authHandle = handles[0]; + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_ChangeEPS(in); + break; +} +#endif // CC_ChangeEPS +#if CC_Clear +case TPM_CC_Clear: +{ + Clear_In* in = (Clear_In*)MemoryGetInBuffer(sizeof(Clear_In)); + in->authHandle = handles[0]; + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_Clear(in); + break; +} +#endif // CC_Clear +#if CC_ClearControl +case TPM_CC_ClearControl: +{ + ClearControl_In* in = + (ClearControl_In*)MemoryGetInBuffer(sizeof(ClearControl_In)); + in->auth = handles[0]; + result = TPMI_YES_NO_Unmarshal(&in->disable, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_ClearControl_disable); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_ClearControl(in); + break; +} +#endif // CC_ClearControl +#if CC_HierarchyChangeAuth +case TPM_CC_HierarchyChangeAuth: +{ + HierarchyChangeAuth_In* in = + (HierarchyChangeAuth_In*)MemoryGetInBuffer(sizeof(HierarchyChangeAuth_In)); + in->authHandle = handles[0]; + result = TPM2B_AUTH_Unmarshal(&in->newAuth, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_HierarchyChangeAuth_newAuth); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_HierarchyChangeAuth(in); + break; +} +#endif // CC_HierarchyChangeAuth +#if CC_DictionaryAttackLockReset +case TPM_CC_DictionaryAttackLockReset: +{ + DictionaryAttackLockReset_In* in = + (DictionaryAttackLockReset_In*)MemoryGetInBuffer( + sizeof(DictionaryAttackLockReset_In)); + in->lockHandle = handles[0]; + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_DictionaryAttackLockReset(in); + break; +} +#endif // CC_DictionaryAttackLockReset +#if CC_DictionaryAttackParameters +case TPM_CC_DictionaryAttackParameters: +{ + DictionaryAttackParameters_In* in = + (DictionaryAttackParameters_In*)MemoryGetInBuffer( + sizeof(DictionaryAttackParameters_In)); + in->lockHandle = handles[0]; + result = UINT32_Unmarshal(&in->newMaxTries, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_DictionaryAttackParameters_newMaxTries); + result = UINT32_Unmarshal(&in->newRecoveryTime, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_DictionaryAttackParameters_newRecoveryTime); + result = UINT32_Unmarshal(&in->lockoutRecovery, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_DictionaryAttackParameters_lockoutRecovery); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_DictionaryAttackParameters(in); + break; +} +#endif // CC_DictionaryAttackParameters +#if CC_PP_Commands +case TPM_CC_PP_Commands: +{ + PP_Commands_In* in = (PP_Commands_In*)MemoryGetInBuffer(sizeof(PP_Commands_In)); + in->auth = handles[0]; + result = TPML_CC_Unmarshal(&in->setList, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PP_Commands_setList); + result = TPML_CC_Unmarshal(&in->clearList, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_PP_Commands_clearList); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_PP_Commands(in); + break; +} +#endif // CC_PP_Commands +#if CC_SetAlgorithmSet +case TPM_CC_SetAlgorithmSet: +{ + SetAlgorithmSet_In* in = + (SetAlgorithmSet_In*)MemoryGetInBuffer(sizeof(SetAlgorithmSet_In)); + in->authHandle = handles[0]; + result = UINT32_Unmarshal(&in->algorithmSet, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_SetAlgorithmSet_algorithmSet); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_SetAlgorithmSet(in); + break; +} +#endif // CC_SetAlgorithmSet +#if CC_FieldUpgradeStart +case TPM_CC_FieldUpgradeStart: +{ + FieldUpgradeStart_In* in = + (FieldUpgradeStart_In*)MemoryGetInBuffer(sizeof(FieldUpgradeStart_In)); + in->authorization = handles[0]; + in->keyHandle = handles[1]; + result = TPM2B_DIGEST_Unmarshal(&in->fuDigest, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_FieldUpgradeStart_fuDigest); + result = TPMT_SIGNATURE_Unmarshal( + &in->manifestSignature, paramBuffer, paramBufferSize, FALSE); + EXIT_IF_ERROR_PLUS(RC_FieldUpgradeStart_manifestSignature); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_FieldUpgradeStart(in); + break; +} +#endif // CC_FieldUpgradeStart +#if CC_FieldUpgradeData +case TPM_CC_FieldUpgradeData: +{ + FieldUpgradeData_In* in = + (FieldUpgradeData_In*)MemoryGetInBuffer(sizeof(FieldUpgradeData_In)); + FieldUpgradeData_Out* out = + (FieldUpgradeData_Out*)MemoryGetOutBuffer(sizeof(FieldUpgradeData_Out)); + result = TPM2B_MAX_BUFFER_Unmarshal(&in->fuData, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_FieldUpgradeData_fuData); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_FieldUpgradeData(in, out); + rSize = sizeof(FieldUpgradeData_Out); + *respParmSize += TPMT_HA_Marshal(&out->nextDigest, responseBuffer, &rSize); + *respParmSize += TPMT_HA_Marshal(&out->firstDigest, responseBuffer, &rSize); + break; +} +#endif // CC_FieldUpgradeData +#if CC_FirmwareRead +case TPM_CC_FirmwareRead: +{ + FirmwareRead_In* in = + (FirmwareRead_In*)MemoryGetInBuffer(sizeof(FirmwareRead_In)); + FirmwareRead_Out* out = + (FirmwareRead_Out*)MemoryGetOutBuffer(sizeof(FirmwareRead_Out)); + result = UINT32_Unmarshal(&in->sequenceNumber, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_FirmwareRead_sequenceNumber); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_FirmwareRead(in, out); + rSize = sizeof(FirmwareRead_Out); + *respParmSize += TPM2B_MAX_BUFFER_Marshal(&out->fuData, responseBuffer, &rSize); + break; +} +#endif // CC_FirmwareRead +#if CC_ContextSave +case TPM_CC_ContextSave: +{ + ContextSave_In* in = (ContextSave_In*)MemoryGetInBuffer(sizeof(ContextSave_In)); + ContextSave_Out* out = + (ContextSave_Out*)MemoryGetOutBuffer(sizeof(ContextSave_Out)); + in->saveHandle = handles[0]; + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_ContextSave(in, out); + rSize = sizeof(ContextSave_Out); + *respParmSize += TPMS_CONTEXT_Marshal(&out->context, responseBuffer, &rSize); + break; +} +#endif // CC_ContextSave +#if CC_ContextLoad +case TPM_CC_ContextLoad: +{ + ContextLoad_In* in = (ContextLoad_In*)MemoryGetInBuffer(sizeof(ContextLoad_In)); + ContextLoad_Out* out = + (ContextLoad_Out*)MemoryGetOutBuffer(sizeof(ContextLoad_Out)); + result = TPMS_CONTEXT_Unmarshal(&in->context, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_ContextLoad_context); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_ContextLoad(in, out); + rSize = sizeof(ContextLoad_Out); + if(TPM_RC_SUCCESS != result) + goto Exit; + command->handles[command->handleNum++] = out->loadedHandle; + break; +} +#endif // CC_ContextLoad +#if CC_FlushContext +case TPM_CC_FlushContext: +{ + FlushContext_In* in = + (FlushContext_In*)MemoryGetInBuffer(sizeof(FlushContext_In)); + result = + TPMI_DH_CONTEXT_Unmarshal(&in->flushHandle, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_FlushContext_flushHandle); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_FlushContext(in); + break; +} +#endif // CC_FlushContext +#if CC_EvictControl +case TPM_CC_EvictControl: +{ + EvictControl_In* in = + (EvictControl_In*)MemoryGetInBuffer(sizeof(EvictControl_In)); + in->auth = handles[0]; + in->objectHandle = handles[1]; + result = TPMI_DH_PERSISTENT_Unmarshal( + &in->persistentHandle, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_EvictControl_persistentHandle); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_EvictControl(in); + break; +} +#endif // CC_EvictControl +#if CC_ReadClock +case TPM_CC_ReadClock: +{ + ReadClock_Out* out = (ReadClock_Out*)MemoryGetOutBuffer(sizeof(ReadClock_Out)); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_ReadClock(out); + rSize = sizeof(ReadClock_Out); + *respParmSize += + TPMS_TIME_INFO_Marshal(&out->currentTime, responseBuffer, &rSize); + break; +} +#endif // CC_ReadClock +#if CC_ClockSet +case TPM_CC_ClockSet: +{ + ClockSet_In* in = (ClockSet_In*)MemoryGetInBuffer(sizeof(ClockSet_In)); + in->auth = handles[0]; + result = UINT64_Unmarshal(&in->newTime, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_ClockSet_newTime); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_ClockSet(in); + break; +} +#endif // CC_ClockSet +#if CC_ClockRateAdjust +case TPM_CC_ClockRateAdjust: +{ + ClockRateAdjust_In* in = + (ClockRateAdjust_In*)MemoryGetInBuffer(sizeof(ClockRateAdjust_In)); + in->auth = handles[0]; + result = + TPM_CLOCK_ADJUST_Unmarshal(&in->rateAdjust, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_ClockRateAdjust_rateAdjust); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_ClockRateAdjust(in); + break; +} +#endif // CC_ClockRateAdjust +#if CC_GetCapability +case TPM_CC_GetCapability: +{ + GetCapability_In* in = + (GetCapability_In*)MemoryGetInBuffer(sizeof(GetCapability_In)); + GetCapability_Out* out = + (GetCapability_Out*)MemoryGetOutBuffer(sizeof(GetCapability_Out)); + result = TPM_CAP_Unmarshal(&in->capability, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_GetCapability_capability); + result = UINT32_Unmarshal(&in->property, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_GetCapability_property); + result = UINT32_Unmarshal(&in->propertyCount, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_GetCapability_propertyCount); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_GetCapability(in, out); + rSize = sizeof(GetCapability_Out); + *respParmSize += TPMI_YES_NO_Marshal(&out->moreData, responseBuffer, &rSize); + *respParmSize += + TPMS_CAPABILITY_DATA_Marshal(&out->capabilityData, responseBuffer, &rSize); + break; +} +#endif // CC_GetCapability +#if CC_TestParms +case TPM_CC_TestParms: +{ + TestParms_In* in = (TestParms_In*)MemoryGetInBuffer(sizeof(TestParms_In)); + result = + TPMT_PUBLIC_PARMS_Unmarshal(&in->parameters, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_TestParms_parameters); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_TestParms(in); + break; +} +#endif // CC_TestParms +#if CC_NV_DefineSpace +case TPM_CC_NV_DefineSpace: +{ + NV_DefineSpace_In* in = + (NV_DefineSpace_In*)MemoryGetInBuffer(sizeof(NV_DefineSpace_In)); + in->authHandle = handles[0]; + result = TPM2B_AUTH_Unmarshal(&in->auth, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_NV_DefineSpace_auth); + result = TPM2B_NV_PUBLIC_Unmarshal(&in->publicInfo, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_NV_DefineSpace_publicInfo); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_NV_DefineSpace(in); + break; +} +#endif // CC_NV_DefineSpace +#if CC_NV_UndefineSpace +case TPM_CC_NV_UndefineSpace: +{ + NV_UndefineSpace_In* in = + (NV_UndefineSpace_In*)MemoryGetInBuffer(sizeof(NV_UndefineSpace_In)); + in->authHandle = handles[0]; + in->nvIndex = handles[1]; + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_NV_UndefineSpace(in); + break; +} +#endif // CC_NV_UndefineSpace +#if CC_NV_UndefineSpaceSpecial +case TPM_CC_NV_UndefineSpaceSpecial: +{ + NV_UndefineSpaceSpecial_In* in = (NV_UndefineSpaceSpecial_In*)MemoryGetInBuffer( + sizeof(NV_UndefineSpaceSpecial_In)); + in->nvIndex = handles[0]; + in->platform = handles[1]; + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_NV_UndefineSpaceSpecial(in); + break; +} +#endif // CC_NV_UndefineSpaceSpecial +#if CC_NV_ReadPublic +case TPM_CC_NV_ReadPublic: +{ + NV_ReadPublic_In* in = + (NV_ReadPublic_In*)MemoryGetInBuffer(sizeof(NV_ReadPublic_In)); + NV_ReadPublic_Out* out = + (NV_ReadPublic_Out*)MemoryGetOutBuffer(sizeof(NV_ReadPublic_Out)); + in->nvIndex = handles[0]; + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_NV_ReadPublic(in, out); + rSize = sizeof(NV_ReadPublic_Out); + *respParmSize += TPM2B_NV_PUBLIC_Marshal(&out->nvPublic, responseBuffer, &rSize); + *respParmSize += TPM2B_NAME_Marshal(&out->nvName, responseBuffer, &rSize); + break; +} +#endif // CC_NV_ReadPublic +#if CC_NV_Write +case TPM_CC_NV_Write: +{ + NV_Write_In* in = (NV_Write_In*)MemoryGetInBuffer(sizeof(NV_Write_In)); + in->authHandle = handles[0]; + in->nvIndex = handles[1]; + result = TPM2B_MAX_NV_BUFFER_Unmarshal(&in->data, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_NV_Write_data); + result = UINT16_Unmarshal(&in->offset, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_NV_Write_offset); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_NV_Write(in); + break; +} +#endif // CC_NV_Write +#if CC_NV_Increment +case TPM_CC_NV_Increment: +{ + NV_Increment_In* in = + (NV_Increment_In*)MemoryGetInBuffer(sizeof(NV_Increment_In)); + in->authHandle = handles[0]; + in->nvIndex = handles[1]; + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_NV_Increment(in); + break; +} +#endif // CC_NV_Increment +#if CC_NV_Extend +case TPM_CC_NV_Extend: +{ + NV_Extend_In* in = (NV_Extend_In*)MemoryGetInBuffer(sizeof(NV_Extend_In)); + in->authHandle = handles[0]; + in->nvIndex = handles[1]; + result = TPM2B_MAX_NV_BUFFER_Unmarshal(&in->data, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_NV_Extend_data); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_NV_Extend(in); + break; +} +#endif // CC_NV_Extend +#if CC_NV_SetBits +case TPM_CC_NV_SetBits: +{ + NV_SetBits_In* in = (NV_SetBits_In*)MemoryGetInBuffer(sizeof(NV_SetBits_In)); + in->authHandle = handles[0]; + in->nvIndex = handles[1]; + result = UINT64_Unmarshal(&in->bits, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_NV_SetBits_bits); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_NV_SetBits(in); + break; +} +#endif // CC_NV_SetBits +#if CC_NV_WriteLock +case TPM_CC_NV_WriteLock: +{ + NV_WriteLock_In* in = + (NV_WriteLock_In*)MemoryGetInBuffer(sizeof(NV_WriteLock_In)); + in->authHandle = handles[0]; + in->nvIndex = handles[1]; + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_NV_WriteLock(in); + break; +} +#endif // CC_NV_WriteLock +#if CC_NV_GlobalWriteLock +case TPM_CC_NV_GlobalWriteLock: +{ + NV_GlobalWriteLock_In* in = + (NV_GlobalWriteLock_In*)MemoryGetInBuffer(sizeof(NV_GlobalWriteLock_In)); + in->authHandle = handles[0]; + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_NV_GlobalWriteLock(in); + break; +} +#endif // CC_NV_GlobalWriteLock +#if CC_NV_Read +case TPM_CC_NV_Read: +{ + NV_Read_In* in = (NV_Read_In*)MemoryGetInBuffer(sizeof(NV_Read_In)); + NV_Read_Out* out = (NV_Read_Out*)MemoryGetOutBuffer(sizeof(NV_Read_Out)); + in->authHandle = handles[0]; + in->nvIndex = handles[1]; + result = UINT16_Unmarshal(&in->size, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_NV_Read_size); + result = UINT16_Unmarshal(&in->offset, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_NV_Read_offset); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_NV_Read(in, out); + rSize = sizeof(NV_Read_Out); + *respParmSize += TPM2B_MAX_NV_BUFFER_Marshal(&out->data, responseBuffer, &rSize); + break; +} +#endif // CC_NV_Read +#if CC_NV_ReadLock +case TPM_CC_NV_ReadLock: +{ + NV_ReadLock_In* in = (NV_ReadLock_In*)MemoryGetInBuffer(sizeof(NV_ReadLock_In)); + in->authHandle = handles[0]; + in->nvIndex = handles[1]; + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_NV_ReadLock(in); + break; +} +#endif // CC_NV_ReadLock +#if CC_NV_ChangeAuth +case TPM_CC_NV_ChangeAuth: +{ + NV_ChangeAuth_In* in = + (NV_ChangeAuth_In*)MemoryGetInBuffer(sizeof(NV_ChangeAuth_In)); + in->nvIndex = handles[0]; + result = TPM2B_AUTH_Unmarshal(&in->newAuth, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_NV_ChangeAuth_newAuth); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_NV_ChangeAuth(in); + break; +} +#endif // CC_NV_ChangeAuth +#if CC_NV_Certify +case TPM_CC_NV_Certify: +{ + NV_Certify_In* in = (NV_Certify_In*)MemoryGetInBuffer(sizeof(NV_Certify_In)); + NV_Certify_Out* out = (NV_Certify_Out*)MemoryGetOutBuffer(sizeof(NV_Certify_Out)); + in->signHandle = handles[0]; + in->authHandle = handles[1]; + in->nvIndex = handles[2]; + result = TPM2B_DATA_Unmarshal(&in->qualifyingData, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_NV_Certify_qualifyingData); + result = + TPMT_SIG_SCHEME_Unmarshal(&in->inScheme, paramBuffer, paramBufferSize, TRUE); + EXIT_IF_ERROR_PLUS(RC_NV_Certify_inScheme); + result = UINT16_Unmarshal(&in->size, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_NV_Certify_size); + result = UINT16_Unmarshal(&in->offset, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_NV_Certify_offset); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_NV_Certify(in, out); + rSize = sizeof(NV_Certify_Out); + *respParmSize += TPM2B_ATTEST_Marshal(&out->certifyInfo, responseBuffer, &rSize); + *respParmSize += TPMT_SIGNATURE_Marshal(&out->signature, responseBuffer, &rSize); + break; +} +#endif // CC_NV_Certify +#if CC_AC_GetCapability +case TPM_CC_AC_GetCapability: +{ + AC_GetCapability_In* in = + (AC_GetCapability_In*)MemoryGetInBuffer(sizeof(AC_GetCapability_In)); + AC_GetCapability_Out* out = + (AC_GetCapability_Out*)MemoryGetOutBuffer(sizeof(AC_GetCapability_Out)); + in->ac = handles[0]; + result = TPM_AT_Unmarshal(&in->capability, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_AC_GetCapability_capability); + result = UINT32_Unmarshal(&in->count, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_AC_GetCapability_count); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_AC_GetCapability(in, out); + rSize = sizeof(AC_GetCapability_Out); + *respParmSize += TPMI_YES_NO_Marshal(&out->moreData, responseBuffer, &rSize); + *respParmSize += + TPML_AC_CAPABILITIES_Marshal(&out->capabilitiesData, responseBuffer, &rSize); + break; +} +#endif // CC_AC_GetCapability +#if CC_AC_Send +case TPM_CC_AC_Send: +{ + AC_Send_In* in = (AC_Send_In*)MemoryGetInBuffer(sizeof(AC_Send_In)); + AC_Send_Out* out = (AC_Send_Out*)MemoryGetOutBuffer(sizeof(AC_Send_Out)); + in->sendObject = handles[0]; + in->authHandle = handles[1]; + in->ac = handles[2]; + result = TPM2B_MAX_BUFFER_Unmarshal(&in->acDataIn, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_AC_Send_acDataIn); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_AC_Send(in, out); + rSize = sizeof(AC_Send_Out); + *respParmSize += TPMS_AC_OUTPUT_Marshal(&out->acDataOut, responseBuffer, &rSize); + break; +} +#endif // CC_AC_Send +#if CC_Policy_AC_SendSelect +case TPM_CC_Policy_AC_SendSelect: +{ + Policy_AC_SendSelect_In* in = + (Policy_AC_SendSelect_In*)MemoryGetInBuffer(sizeof(Policy_AC_SendSelect_In)); + in->policySession = handles[0]; + result = TPM2B_NAME_Unmarshal(&in->objectName, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_Policy_AC_SendSelect_objectName); + result = TPM2B_NAME_Unmarshal(&in->authHandleName, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_Policy_AC_SendSelect_authHandleName); + result = TPM2B_NAME_Unmarshal(&in->acName, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_Policy_AC_SendSelect_acName); + result = TPMI_YES_NO_Unmarshal(&in->includeObject, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_Policy_AC_SendSelect_includeObject); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_Policy_AC_SendSelect(in); + break; +} +#endif // CC_Policy_AC_SendSelect +#if CC_ACT_SetTimeout +case TPM_CC_ACT_SetTimeout: +{ + ACT_SetTimeout_In* in = + (ACT_SetTimeout_In*)MemoryGetInBuffer(sizeof(ACT_SetTimeout_In)); + in->actHandle = handles[0]; + result = UINT32_Unmarshal(&in->startTimeout, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_ACT_SetTimeout_startTimeout); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_ACT_SetTimeout(in); + break; +} +#endif // CC_ACT_SetTimeout +#if CC_Vendor_TCG_Test +case TPM_CC_Vendor_TCG_Test: +{ + Vendor_TCG_Test_In* in = + (Vendor_TCG_Test_In*)MemoryGetInBuffer(sizeof(Vendor_TCG_Test_In)); + Vendor_TCG_Test_Out* out = + (Vendor_TCG_Test_Out*)MemoryGetOutBuffer(sizeof(Vendor_TCG_Test_Out)); + result = TPM2B_DATA_Unmarshal(&in->inputData, paramBuffer, paramBufferSize); + EXIT_IF_ERROR_PLUS(RC_Vendor_TCG_Test_inputData); + if(*paramBufferSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + result = TPM2_Vendor_TCG_Test(in, out); + rSize = sizeof(Vendor_TCG_Test_Out); + *respParmSize += TPM2B_DATA_Marshal(&out->outputData, responseBuffer, &rSize); + break; +} +#endif // CC_Vendor_TCG_Test diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Commands.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Commands.h new file mode 100644 index 0000000..bcdc52e --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Commands.h @@ -0,0 +1,461 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Feb 28, 2020 Time: 03:04:47PM + */ + +#ifndef _COMMANDS_H_ +#define _COMMANDS_H_ + +// Start-up +#if CC_Startup +# include "Startup_fp.h" +#endif +#if CC_Shutdown +# include "Shutdown_fp.h" +#endif + +// Testing +#if CC_SelfTest +# include "SelfTest_fp.h" +#endif +#if CC_IncrementalSelfTest +# include "IncrementalSelfTest_fp.h" +#endif +#if CC_GetTestResult +# include "GetTestResult_fp.h" +#endif + +// Session Commands +#if CC_StartAuthSession +# include "StartAuthSession_fp.h" +#endif +#if CC_PolicyRestart +# include "PolicyRestart_fp.h" +#endif + +// Object Commands +#if CC_Create +# include "Create_fp.h" +#endif +#if CC_Load +# include "Load_fp.h" +#endif +#if CC_LoadExternal +# include "LoadExternal_fp.h" +#endif +#if CC_ReadPublic +# include "ReadPublic_fp.h" +#endif +#if CC_ActivateCredential +# include "ActivateCredential_fp.h" +#endif +#if CC_MakeCredential +# include "MakeCredential_fp.h" +#endif +#if CC_Unseal +# include "Unseal_fp.h" +#endif +#if CC_ObjectChangeAuth +# include "ObjectChangeAuth_fp.h" +#endif +#if CC_CreateLoaded +# include "CreateLoaded_fp.h" +#endif + +// Duplication Commands +#if CC_Duplicate +# include "Duplicate_fp.h" +#endif +#if CC_Rewrap +# include "Rewrap_fp.h" +#endif +#if CC_Import +# include "Import_fp.h" +#endif + +// Asymmetric Primitives +#if CC_RSA_Encrypt +# include "RSA_Encrypt_fp.h" +#endif +#if CC_RSA_Decrypt +# include "RSA_Decrypt_fp.h" +#endif +#if CC_ECDH_KeyGen +# include "ECDH_KeyGen_fp.h" +#endif +#if CC_ECDH_ZGen +# include "ECDH_ZGen_fp.h" +#endif +#if CC_ECC_Parameters +# include "ECC_Parameters_fp.h" +#endif +#if CC_ZGen_2Phase +# include "ZGen_2Phase_fp.h" +#endif +#if CC_ECC_Encrypt +# include "ECC_Encrypt_fp.h" +#endif +#if CC_ECC_Decrypt +# include "ECC_Decrypt_fp.h" +#endif + +// Symmetric Primitives +#if CC_EncryptDecrypt +# include "EncryptDecrypt_fp.h" +#endif +#if CC_EncryptDecrypt2 +# include "EncryptDecrypt2_fp.h" +#endif +#if CC_Hash +# include "Hash_fp.h" +#endif +#if CC_HMAC +# include "HMAC_fp.h" +#endif +#if CC_MAC +# include "MAC_fp.h" +#endif + +// Random Number Generator +#if CC_GetRandom +# include "GetRandom_fp.h" +#endif +#if CC_StirRandom +# include "StirRandom_fp.h" +#endif + +// Hash/HMAC/Event Sequences +#if CC_HMAC_Start +# include "HMAC_Start_fp.h" +#endif +#if CC_MAC_Start +# include "MAC_Start_fp.h" +#endif +#if CC_HashSequenceStart +# include "HashSequenceStart_fp.h" +#endif +#if CC_SequenceUpdate +# include "SequenceUpdate_fp.h" +#endif +#if CC_SequenceComplete +# include "SequenceComplete_fp.h" +#endif +#if CC_EventSequenceComplete +# include "EventSequenceComplete_fp.h" +#endif + +// Attestation Commands +#if CC_Certify +# include "Certify_fp.h" +#endif +#if CC_CertifyCreation +# include "CertifyCreation_fp.h" +#endif +#if CC_Quote +# include "Quote_fp.h" +#endif +#if CC_GetSessionAuditDigest +# include "GetSessionAuditDigest_fp.h" +#endif +#if CC_GetCommandAuditDigest +# include "GetCommandAuditDigest_fp.h" +#endif +#if CC_GetTime +# include "GetTime_fp.h" +#endif +#if CC_CertifyX509 +# include "CertifyX509_fp.h" +#endif + +// Ephemeral EC Keys +#if CC_Commit +# include "Commit_fp.h" +#endif +#if CC_EC_Ephemeral +# include "EC_Ephemeral_fp.h" +#endif + +// Signing and Signature Verification +#if CC_VerifySignature +# include "VerifySignature_fp.h" +#endif +#if CC_Sign +# include "Sign_fp.h" +#endif + +// Command Audit +#if CC_SetCommandCodeAuditStatus +# include "SetCommandCodeAuditStatus_fp.h" +#endif + +// Integrity Collection (PCR) +#if CC_PCR_Extend +# include "PCR_Extend_fp.h" +#endif +#if CC_PCR_Event +# include "PCR_Event_fp.h" +#endif +#if CC_PCR_Read +# include "PCR_Read_fp.h" +#endif +#if CC_PCR_Allocate +# include "PCR_Allocate_fp.h" +#endif +#if CC_PCR_SetAuthPolicy +# include "PCR_SetAuthPolicy_fp.h" +#endif +#if CC_PCR_SetAuthValue +# include "PCR_SetAuthValue_fp.h" +#endif +#if CC_PCR_Reset +# include "PCR_Reset_fp.h" +#endif + +// Enhanced Authorization (EA) Commands +#if CC_PolicySigned +# include "PolicySigned_fp.h" +#endif +#if CC_PolicySecret +# include "PolicySecret_fp.h" +#endif +#if CC_PolicyTicket +# include "PolicyTicket_fp.h" +#endif +#if CC_PolicyOR +# include "PolicyOR_fp.h" +#endif +#if CC_PolicyPCR +# include "PolicyPCR_fp.h" +#endif +#if CC_PolicyLocality +# include "PolicyLocality_fp.h" +#endif +#if CC_PolicyNV +# include "PolicyNV_fp.h" +#endif +#if CC_PolicyCounterTimer +# include "PolicyCounterTimer_fp.h" +#endif +#if CC_PolicyCommandCode +# include "PolicyCommandCode_fp.h" +#endif +#if CC_PolicyPhysicalPresence +# include "PolicyPhysicalPresence_fp.h" +#endif +#if CC_PolicyCpHash +# include "PolicyCpHash_fp.h" +#endif +#if CC_PolicyNameHash +# include "PolicyNameHash_fp.h" +#endif +#if CC_PolicyDuplicationSelect +# include "PolicyDuplicationSelect_fp.h" +#endif +#if CC_PolicyAuthorize +# include "PolicyAuthorize_fp.h" +#endif +#if CC_PolicyAuthValue +# include "PolicyAuthValue_fp.h" +#endif +#if CC_PolicyPassword +# include "PolicyPassword_fp.h" +#endif +#if CC_PolicyGetDigest +# include "PolicyGetDigest_fp.h" +#endif +#if CC_PolicyNvWritten +# include "PolicyNvWritten_fp.h" +#endif +#if CC_PolicyTemplate +# include "PolicyTemplate_fp.h" +#endif +#if CC_PolicyAuthorizeNV +# include "PolicyAuthorizeNV_fp.h" +#endif + +// Hierarchy Commands +#if CC_CreatePrimary +# include "CreatePrimary_fp.h" +#endif +#if CC_HierarchyControl +# include "HierarchyControl_fp.h" +#endif +#if CC_SetPrimaryPolicy +# include "SetPrimaryPolicy_fp.h" +#endif +#if CC_ChangePPS +# include "ChangePPS_fp.h" +#endif +#if CC_ChangeEPS +# include "ChangeEPS_fp.h" +#endif +#if CC_Clear +# include "Clear_fp.h" +#endif +#if CC_ClearControl +# include "ClearControl_fp.h" +#endif +#if CC_HierarchyChangeAuth +# include "HierarchyChangeAuth_fp.h" +#endif + +// Dictionary Attack Functions +#if CC_DictionaryAttackLockReset +# include "DictionaryAttackLockReset_fp.h" +#endif +#if CC_DictionaryAttackParameters +# include "DictionaryAttackParameters_fp.h" +#endif + +// Miscellaneous Management Functions +#if CC_PP_Commands +# include "PP_Commands_fp.h" +#endif +#if CC_SetAlgorithmSet +# include "SetAlgorithmSet_fp.h" +#endif + +// Field Upgrade +#if CC_FieldUpgradeStart +# include "FieldUpgradeStart_fp.h" +#endif +#if CC_FieldUpgradeData +# include "FieldUpgradeData_fp.h" +#endif +#if CC_FirmwareRead +# include "FirmwareRead_fp.h" +#endif + +// Context Management +#if CC_ContextSave +# include "ContextSave_fp.h" +#endif +#if CC_ContextLoad +# include "ContextLoad_fp.h" +#endif +#if CC_FlushContext +# include "FlushContext_fp.h" +#endif +#if CC_EvictControl +# include "EvictControl_fp.h" +#endif + +// Clocks and Timers +#if CC_ReadClock +# include "ReadClock_fp.h" +#endif +#if CC_ClockSet +# include "ClockSet_fp.h" +#endif +#if CC_ClockRateAdjust +# include "ClockRateAdjust_fp.h" +#endif + +// Capability Commands +#if CC_GetCapability +# include "GetCapability_fp.h" +#endif +#if CC_TestParms +# include "TestParms_fp.h" +#endif + +// Non-volatile Storage +#if CC_NV_DefineSpace +# include "NV_DefineSpace_fp.h" +#endif +#if CC_NV_UndefineSpace +# include "NV_UndefineSpace_fp.h" +#endif +#if CC_NV_UndefineSpaceSpecial +# include "NV_UndefineSpaceSpecial_fp.h" +#endif +#if CC_NV_ReadPublic +# include "NV_ReadPublic_fp.h" +#endif +#if CC_NV_Write +# include "NV_Write_fp.h" +#endif +#if CC_NV_Increment +# include "NV_Increment_fp.h" +#endif +#if CC_NV_Extend +# include "NV_Extend_fp.h" +#endif +#if CC_NV_SetBits +# include "NV_SetBits_fp.h" +#endif +#if CC_NV_WriteLock +# include "NV_WriteLock_fp.h" +#endif +#if CC_NV_GlobalWriteLock +# include "NV_GlobalWriteLock_fp.h" +#endif +#if CC_NV_Read +# include "NV_Read_fp.h" +#endif +#if CC_NV_ReadLock +# include "NV_ReadLock_fp.h" +#endif +#if CC_NV_ChangeAuth +# include "NV_ChangeAuth_fp.h" +#endif +#if CC_NV_Certify +# include "NV_Certify_fp.h" +#endif + +// Attached Components +#if CC_AC_GetCapability +# include "AC_GetCapability_fp.h" +#endif +#if CC_AC_Send +# include "AC_Send_fp.h" +#endif +#if CC_Policy_AC_SendSelect +# include "Policy_AC_SendSelect_fp.h" +#endif + +// Authenticated Countdown Timer +#if CC_ACT_SetTimeout +# include "ACT_SetTimeout_fp.h" +#endif + +// Vendor Specific +#if CC_Vendor_TCG_Test +# include "Vendor_TCG_Test_fp.h" +#endif + +#endif diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CompilerDependencies.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CompilerDependencies.h new file mode 100644 index 0000000..dd6e65f --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CompilerDependencies.h @@ -0,0 +1,130 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 contains the build switches. This contains switches for multiple +// versions of the crypto-library so some may not apply to your environment. +// + +#ifndef _COMPILER_DEPENDENCIES_H_ +#define _COMPILER_DEPENDENCIES_H_ + +#ifdef GCC +# undef _MSC_VER +# undef WIN32 +#endif + +#ifdef _MSC_VER +// These definitions are for the Microsoft compiler + +// Endian conversion for aligned structures +# define REVERSE_ENDIAN_16(_Number) _byteswap_ushort(_Number) +# define REVERSE_ENDIAN_32(_Number) _byteswap_ulong(_Number) +# define REVERSE_ENDIAN_64(_Number) _byteswap_uint64(_Number) + +// Avoid compiler warning for in line of stdio (or not) +//#define _NO_CRT_STDIO_INLINE + +// This macro is used to handle LIB_EXPORT of function and variable names in lieu +// of a .def file. Visual Studio requires that functions be explicitly exported and +// imported. +# define LIB_EXPORT __declspec(dllexport) // VS compatible version +# define LIB_IMPORT __declspec(dllimport) + +// This is defined to indicate a function that does not return. Microsoft compilers +// do not support the _Noretrun function parameter. +# define NORETURN __declspec(noreturn) +# if _MSC_VER >= 1400 // SAL processing when needed +# include +# endif + +# ifdef _WIN64 +# define _INTPTR 2 +# else +# define _INTPTR 1 +# endif + +# define NOT_REFERENCED(x) (x) + +// Lower the compiler error warning for system include +// files. They tend not to be that clean and there is no +// reason to sort through all the spurious errors that they +// generate when the normal error level is set to /Wall +# define _REDUCE_WARNING_LEVEL_(n) __pragma(warning(push, n)) +// Restore the compiler warning level +# define _NORMAL_WARNING_LEVEL_ __pragma(warning(pop)) +# include +#endif + +#ifndef _MSC_VER +# ifndef WINAPI +# define WINAPI +# endif +# ifndef __pragma +# define __pragma(x) +# endif +# define REVERSE_ENDIAN_16(_Number) __builtin_bswap16(_Number) +# define REVERSE_ENDIAN_32(_Number) __builtin_bswap32(_Number) +# define REVERSE_ENDIAN_64(_Number) __builtin_bswap64(_Number) +#endif + +#if defined(__GNUC__) +# define NORETURN __attribute__((noreturn)) +# include +#endif + +// Things that are not defined should be defined as NULL +#ifndef NORETURN +# define NORETURN +#endif +#ifndef LIB_EXPORT +# define LIB_EXPORT +#endif +#ifndef LIB_IMPORT +# define LIB_IMPORT +#endif +#ifndef _REDUCE_WARNING_LEVEL_ +# define _REDUCE_WARNING_LEVEL_(n) +#endif +#ifndef _NORMAL_WARNING_LEVEL_ +# define _NORMAL_WARNING_LEVEL_ +#endif +#ifndef NOT_REFERENCED +# define NOT_REFERENCED(x) (x = x) +#endif + +#ifdef _POSIX_ +typedef int SOCKET; +#endif + +#endif // _COMPILER_DEPENDENCIES_H_ \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CryptEcc.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CryptEcc.h new file mode 100644 index 0000000..ad59a4a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CryptEcc.h @@ -0,0 +1,80 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// This file contains structure definitions used for ECC. The +// structures in this file are only used internally. The ECC-related structures +// that cross the TPM interface are defined in TpmTypes.h +// + +#ifndef _CRYPT_ECC_H +#define _CRYPT_ECC_H + +//** Structures + +typedef struct ECC_CURVE +{ + const TPM_ECC_CURVE curveId; + const UINT16 keySizeBits; + const TPMT_KDF_SCHEME kdf; + const TPMT_ECC_SCHEME sign; + const ECC_CURVE_DATA* curveData; // the address of the curve data + const BYTE* OID; +} ECC_CURVE; + +//*** Macros + +// This macro is used to instance an ECC_CURVE_DATA structure for the curve. This +// structure is referenced by the ECC_CURVE structure +#define CURVE_DATA_DEF(CURVE) \ + const ECC_CURVE_DATA CURVE = {(bigNum)&CURVE##_p_DATA, \ + (bigNum)&CURVE##_n_DATA, \ + (bigNum)&CURVE##_h_DATA, \ + (bigNum)&CURVE##_a_DATA, \ + (bigNum)&CURVE##_b_DATA, \ + {(bigNum)&CURVE##_gX_DATA, \ + (bigNum)&CURVE##_gY_DATA, \ + (bigNum)&BN_ONE}}; + +extern const ECC_CURVE eccCurves[ECC_CURVE_COUNT]; + +#define CURVE_DEF(CURVE) \ + { \ + TPM_ECC_##CURVE, CURVE##_KEY_SIZE, CURVE##_KDF, CURVE##_SIGN, &##CURVE, \ + OID_ECC_##CURVE \ + } + +#define CURVE_NAME(N) + +#endif diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CryptHash.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CryptHash.h new file mode 100644 index 0000000..d13ef80 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CryptHash.h @@ -0,0 +1,324 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// This header contains the hash structure definitions used in the TPM code +// to define the amount of space to be reserved for the hash state. This allows +// the TPM code to not have to import all of the symbols used by the hash +// computations. This lets the build environment of the TPM code not to have +// include the header files associated with the CryptoEngine code. + +#ifndef _CRYPT_HASH_H +#define _CRYPT_HASH_H + +//** Hash-related Structures + +union SMAC_STATES; + +// These definitions add the high-level methods for processing state that may be +// an SMAC +typedef void (*SMAC_DATA_METHOD)( + union SMAC_STATES* state, UINT32 size, const BYTE* buffer); + +typedef UINT16 (*SMAC_END_METHOD)( + union SMAC_STATES* state, UINT32 size, BYTE* buffer); + +typedef struct sequenceMethods +{ + SMAC_DATA_METHOD data; + SMAC_END_METHOD end; +} SMAC_METHODS; + +#define SMAC_IMPLEMENTED (CC_MAC || CC_MAC_Start) + +// These definitions are here because the SMAC state is in the union of hash states. +typedef struct tpmCmacState +{ + TPM_ALG_ID symAlg; + UINT16 keySizeBits; + INT16 bcount; // current count of bytes accumulated in IV + TPM2B_IV iv; // IV buffer + TPM2B_SYM_KEY symKey; +} tpmCmacState_t; + +typedef union SMAC_STATES +{ +#if ALG_CMAC + tpmCmacState_t cmac; +#endif + UINT64 pad; +} SMAC_STATES; + +typedef struct SMAC_STATE +{ + SMAC_METHODS smacMethods; + SMAC_STATES state; +} SMAC_STATE; + +#if ALG_SHA1 +# define IF_IMPLEMENTED_SHA1(op) op(SHA1, Sha1) +#else +# define IF_IMPLEMENTED_SHA1(op) +#endif +#if ALG_SHA256 +# define IF_IMPLEMENTED_SHA256(op) op(SHA256, Sha256) +#else +# define IF_IMPLEMENTED_SHA256(op) +#endif +#if ALG_SHA384 +# define IF_IMPLEMENTED_SHA384(op) op(SHA384, Sha384) +#else +# define IF_IMPLEMENTED_SHA384(op) +#endif +#if ALG_SHA512 +# define IF_IMPLEMENTED_SHA512(op) op(SHA512, Sha512) +#else +# define IF_IMPLEMENTED_SHA512(op) +#endif +#if ALG_SM3_256 +# define IF_IMPLEMENTED_SM3_256(op) op(SM3_256, Sm3_256) +#else +# define IF_IMPLEMENTED_SM3_256(op) +#endif +#if ALG_SHA3_256 +# define IF_IMPLEMENTED_SHA3_256(op) op(SHA3_256, Sha3_256) +#else +# define IF_IMPLEMENTED_SHA3_256(op) +#endif +#if ALG_SHA3_384 +# define IF_IMPLEMENTED_SHA3_384(op) op(SHA3_384, Sha3_384) +#else +# define IF_IMPLEMENTED_SHA3_384(op) +#endif +#if ALG_SHA3_512 +# define IF_IMPLEMENTED_SHA3_512(op) op(SHA3_512, Sha3_512) +#else +# define IF_IMPLEMENTED_SHA3_512(op) +#endif + +#define FOR_EACH_HASH(op) \ + IF_IMPLEMENTED_SHA1(op) \ + IF_IMPLEMENTED_SHA256(op) \ + IF_IMPLEMENTED_SHA384(op) \ + IF_IMPLEMENTED_SHA512(op) \ + IF_IMPLEMENTED_SM3_256(op) \ + IF_IMPLEMENTED_SHA3_256(op) \ + IF_IMPLEMENTED_SHA3_384(op) \ + IF_IMPLEMENTED_SHA3_512(op) + +#define HASH_TYPE(HASH, Hash) tpmHashState##HASH##_t Hash; +typedef union +{ + FOR_EACH_HASH(HASH_TYPE) +// Additions for symmetric block cipher MAC +#if SMAC_IMPLEMENTED + SMAC_STATE smac; +#endif + // to force structure alignment to be no worse than HASH_ALIGNMENT +#if HASH_ALIGNMENT == 8 + uint64_t align; +#else + uint32_t align; +#endif +} ANY_HASH_STATE; + +typedef ANY_HASH_STATE* PANY_HASH_STATE; +typedef const ANY_HASH_STATE* PCANY_HASH_STATE; + +#define ALIGNED_SIZE(x, b) ((((x) + (b)-1) / (b)) * (b)) +// MAX_HASH_STATE_SIZE will change with each implementation. It is assumed that +// a hash state will not be larger than twice the block size plus some +// overhead (in this case, 16 bytes). The overall size needs to be as +// large as any of the hash contexts. The structure needs to start on an +// alignment boundary and be an even multiple of the alignment +#define MAX_HASH_STATE_SIZE ((2 * MAX_HASH_BLOCK_SIZE) + 16) +#define MAX_HASH_STATE_SIZE_ALIGNED ALIGNED_SIZE(MAX_HASH_STATE_SIZE, HASH_ALIGNMENT) + +// This is an aligned byte array that will hold any of the hash contexts. +typedef ANY_HASH_STATE ALIGNED_HASH_STATE; + +// The header associated with the hash library is expected to define the methods +// which include the calling sequence. When not compiling CryptHash.c, the methods +// are not defined so we need placeholder functions for the structures + +#ifndef HASH_START_METHOD_DEF +# define HASH_START_METHOD_DEF void(HASH_START_METHOD)(void) +#endif +#ifndef HASH_DATA_METHOD_DEF +# define HASH_DATA_METHOD_DEF void(HASH_DATA_METHOD)(void) +#endif +#ifndef HASH_END_METHOD_DEF +# define HASH_END_METHOD_DEF void(HASH_END_METHOD)(void) +#endif +#ifndef HASH_STATE_COPY_METHOD_DEF +# define HASH_STATE_COPY_METHOD_DEF void(HASH_STATE_COPY_METHOD)(void) +#endif +#ifndef HASH_STATE_EXPORT_METHOD_DEF +# define HASH_STATE_EXPORT_METHOD_DEF void(HASH_STATE_EXPORT_METHOD)(void) +#endif +#ifndef HASH_STATE_IMPORT_METHOD_DEF +# define HASH_STATE_IMPORT_METHOD_DEF void(HASH_STATE_IMPORT_METHOD)(void) +#endif + +// Define the prototypical function call for each of the methods. This defines the +// order in which the parameters are passed to the underlying function. +typedef HASH_START_METHOD_DEF; +typedef HASH_DATA_METHOD_DEF; +typedef HASH_END_METHOD_DEF; +typedef HASH_STATE_COPY_METHOD_DEF; +typedef HASH_STATE_EXPORT_METHOD_DEF; +typedef HASH_STATE_IMPORT_METHOD_DEF; + +typedef struct _HASH_METHODS +{ + HASH_START_METHOD* start; + HASH_DATA_METHOD* data; + HASH_END_METHOD* end; + HASH_STATE_COPY_METHOD* copy; // Copy a hash block + HASH_STATE_EXPORT_METHOD* copyOut; // Copy a hash block from a hash + // context + HASH_STATE_IMPORT_METHOD* copyIn; // Copy a hash block to a proper hash + // context +} HASH_METHODS, *PHASH_METHODS; + +#define HASH_TPM2B(HASH, Hash) TPM2B_TYPE(HASH##_DIGEST, HASH##_DIGEST_SIZE); + +FOR_EACH_HASH(HASH_TPM2B) + +// When the TPM implements RSA, the hash-dependent OID pointers are part of the +// HASH_DEF. These macros conditionally add the OID reference to the HASH_DEF and the +// HASH_DEF_TEMPLATE. +#if ALG_RSA +# define PKCS1_HASH_REF const BYTE* PKCS1; +# define PKCS1_OID(NAME) , OID_PKCS1_##NAME +#else +# define PKCS1_HASH_REF +# define PKCS1_OID(NAME) +#endif + +// When the TPM implements ECC, the hash-dependent OID pointers are part of the +// HASH_DEF. These macros conditionally add the OID reference to the HASH_DEF and the +// HASH_DEF_TEMPLATE. +#if ALG_ECDSA +# define ECDSA_HASH_REF const BYTE* ECDSA; +# define ECDSA_OID(NAME) , OID_ECDSA_##NAME +#else +# define ECDSA_HASH_REF +# define ECDSA_OID(NAME) +#endif + +typedef const struct HASH_DEF +{ + HASH_METHODS method; + uint16_t blockSize; + uint16_t digestSize; + uint16_t contextSize; + uint16_t hashAlg; + const BYTE* OID; + PKCS1_HASH_REF // PKCS1 OID + ECDSA_HASH_REF // ECDSA OID +} HASH_DEF, *PHASH_DEF; + +// Macro to fill in the HASH_DEF for an algorithm. For SHA1, the instance would be: +// HASH_DEF_TEMPLATE(Sha1, SHA1) +// This handles the difference in capitalization for the various pieces. +#define HASH_DEF_TEMPLATE(HASH, Hash) \ + HASH_DEF Hash##_Def = {{ \ + (HASH_START_METHOD*)&tpmHashStart_##HASH, \ + (HASH_DATA_METHOD*)&tpmHashData_##HASH, \ + (HASH_END_METHOD*)&tpmHashEnd_##HASH, \ + (HASH_STATE_COPY_METHOD*)&tpmHashStateCopy_##HASH, \ + (HASH_STATE_EXPORT_METHOD*)&tpmHashStateExport_##HASH, \ + (HASH_STATE_IMPORT_METHOD*)&tpmHashStateImport_##HASH, \ + }, \ + HASH##_BLOCK_SIZE, /*block size */ \ + HASH##_DIGEST_SIZE, /*data size */ \ + sizeof(tpmHashState##HASH##_t), \ + TPM_ALG_##HASH, \ + OID_##HASH PKCS1_OID(HASH) ECDSA_OID(HASH)}; + +// These definitions are for the types that can be in a hash state structure. +// These types are used in the cryptographic utilities. This is a define rather than +// an enum so that the size of this field can be explicit. +typedef BYTE HASH_STATE_TYPE; +#define HASH_STATE_EMPTY ((HASH_STATE_TYPE)0) +#define HASH_STATE_HASH ((HASH_STATE_TYPE)1) +#define HASH_STATE_HMAC ((HASH_STATE_TYPE)2) +#if CC_MAC || CC_MAC_Start +# define HASH_STATE_SMAC ((HASH_STATE_TYPE)3) +#endif + +// This is the structure that is used for passing a context into the hashing +// functions. It should be the same size as the function context used within +// the hashing functions. This is checked when the hash function is initialized. +// This version uses a new layout for the contexts and a different definition. The +// state buffer is an array of HASH_UNIT values so that a decent compiler will put +// the structure on a HASH_UNIT boundary. If the structure is not properly aligned, +// the code that manipulates the structure will copy to a properly aligned +// structure before it is used and copy the result back. This just makes things +// slower. +// NOTE: This version of the state had the pointer to the update method in the +// state. This is to allow the SMAC functions to use the same structure without +// having to replicate the entire HASH_DEF structure. +typedef struct _HASH_STATE +{ + HASH_STATE_TYPE type; // type of the context + TPM_ALG_ID hashAlg; + PHASH_DEF def; + ANY_HASH_STATE state; +} HASH_STATE, *PHASH_STATE; +typedef const HASH_STATE* PCHASH_STATE; + +//** HMAC State Structures + +// An HMAC_STATE structure contains an opaque HMAC stack state. A caller would +// use this structure when performing incremental HMAC operations. This structure +// contains a hash state and an HMAC key and allows slightly better stack +// optimization than adding an HMAC key to each hash state. +typedef struct hmacState +{ + HASH_STATE hashState; // the hash state + TPM2B_HASH_BLOCK hmacKey; // the HMAC key +} HMAC_STATE, *PHMAC_STATE; + +// This is for the external hash state. This implementation assumes that the size +// of the exported hash state is no larger than the internal hash state. +typedef struct +{ + BYTE buffer[sizeof(HASH_STATE)]; +} EXPORT_HASH_STATE, *PEXPORT_HASH_STATE; + +typedef const EXPORT_HASH_STATE* PCEXPORT_HASH_STATE; + +#endif // _CRYPT_HASH_H diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CryptRand.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CryptRand.h new file mode 100644 index 0000000..f679e6c --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CryptRand.h @@ -0,0 +1,195 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// This file contains constant definition shared by CryptUtil and the parts +// of the Crypto Engine. +// + +#ifndef _CRYPT_RAND_H +#define _CRYPT_RAND_H + +//** DRBG Structures and Defines + +// Values and structures for the random number generator. These values are defined +// in this header file so that the size of the RNG state can be known to TPM.lib. +// This allows the allocation of some space in NV memory for the state to +// be stored on an orderly shutdown. + +// The DRBG based on a symmetric block cipher is defined by three values, +// 1) the key size +// 2) the block size (the IV size) +// 3) the symmetric algorithm + +#define DRBG_KEY_SIZE_BITS AES_MAX_KEY_SIZE_BITS +#define DRBG_IV_SIZE_BITS (AES_MAX_BLOCK_SIZE * 8) +#define DRBG_ALGORITHM TPM_ALG_AES + +typedef tpmKeyScheduleAES DRBG_KEY_SCHEDULE; +#define DRBG_ENCRYPT_SETUP(key, keySizeInBits, schedule) \ + TpmCryptSetEncryptKeyAES(key, keySizeInBits, schedule) +#define DRBG_ENCRYPT(keySchedule, in, out) \ + TpmCryptEncryptAES(SWIZZLE(keySchedule, in, out)) + +#if((DRBG_KEY_SIZE_BITS % RADIX_BITS) != 0) || ((DRBG_IV_SIZE_BITS % RADIX_BITS) != 0) +# error "Key size and IV for DRBG must be even multiples of the radix" +#endif +#if(DRBG_KEY_SIZE_BITS % DRBG_IV_SIZE_BITS) != 0 +# error "Key size for DRBG must be even multiple of the cypher block size" +#endif + +// Derived values +#define DRBG_MAX_REQUESTS_PER_RESEED (1 << 48) +#define DRBG_MAX_REQEST_SIZE (1 << 32) + +#define pDRBG_KEY(seed) ((DRBG_KEY*)&(((BYTE*)(seed))[0])) +#define pDRBG_IV(seed) ((DRBG_IV*)&(((BYTE*)(seed))[DRBG_KEY_SIZE_BYTES])) + +#define DRBG_KEY_SIZE_WORDS (BITS_TO_CRYPT_WORDS(DRBG_KEY_SIZE_BITS)) +#define DRBG_KEY_SIZE_BYTES (DRBG_KEY_SIZE_WORDS * RADIX_BYTES) + +#define DRBG_IV_SIZE_WORDS (BITS_TO_CRYPT_WORDS(DRBG_IV_SIZE_BITS)) +#define DRBG_IV_SIZE_BYTES (DRBG_IV_SIZE_WORDS * RADIX_BYTES) + +#define DRBG_SEED_SIZE_WORDS (DRBG_KEY_SIZE_WORDS + DRBG_IV_SIZE_WORDS) +#define DRBG_SEED_SIZE_BYTES (DRBG_KEY_SIZE_BYTES + DRBG_IV_SIZE_BYTES) + +typedef union +{ + BYTE bytes[DRBG_KEY_SIZE_BYTES]; + crypt_uword_t words[DRBG_KEY_SIZE_WORDS]; +} DRBG_KEY; + +typedef union +{ + BYTE bytes[DRBG_IV_SIZE_BYTES]; + crypt_uword_t words[DRBG_IV_SIZE_WORDS]; +} DRBG_IV; + +typedef union +{ + BYTE bytes[DRBG_SEED_SIZE_BYTES]; + crypt_uword_t words[DRBG_SEED_SIZE_WORDS]; +} DRBG_SEED; + +#define CTR_DRBG_MAX_REQUESTS_PER_RESEED ((UINT64)1 << 20) +#define CTR_DRBG_MAX_BYTES_PER_REQUEST (1 << 16) + +#define CTR_DRBG_MIN_ENTROPY_INPUT_LENGTH DRBG_SEED_SIZE_BYTES +#define CTR_DRBG_MAX_ENTROPY_INPUT_LENGTH DRBG_SEED_SIZE_BYTES +#define CTR_DRBG_MAX_ADDITIONAL_INPUT_LENGTH DRBG_SEED_SIZE_BYTES + +#define TESTING (1 << 0) +#define ENTROPY (1 << 1) +#define TESTED (1 << 2) + +#define IsTestStateSet(BIT) ((g_cryptoSelfTestState.rng & BIT) != 0) +#define SetTestStateBit(BIT) (g_cryptoSelfTestState.rng |= BIT) +#define ClearTestStateBit(BIT) (g_cryptoSelfTestState.rng &= ~BIT) + +#define IsSelfTest() IsTestStateSet(TESTING) +#define SetSelfTest() SetTestStateBit(TESTING) +#define ClearSelfTest() ClearTestStateBit(TESTING) + +#define IsEntropyBad() IsTestStateSet(ENTROPY) +#define SetEntropyBad() SetTestStateBit(ENTROPY) +#define ClearEntropyBad() ClearTestStateBit(ENTROPY) + +#define IsDrbgTested() IsTestStateSet(TESTED) +#define SetDrbgTested() SetTestStateBit(TESTED) +#define ClearDrbgTested() ClearTestStateBit(TESTED) + +typedef struct +{ + UINT64 reseedCounter; + UINT32 magic; + DRBG_SEED seed; // contains the key and IV for the counter mode DRBG + UINT32 lastValue[4]; // used when the TPM does continuous self-test + // for FIPS compliance of DRBG +} DRBG_STATE, *pDRBG_STATE; +#define DRBG_MAGIC ((UINT32)0x47425244) // "DRBG" backwards so that it displays + +typedef struct KDF_STATE +{ + UINT64 counter; + UINT32 magic; + UINT32 limit; + TPM2B* seed; + const TPM2B* label; + TPM2B* context; + TPM_ALG_ID hash; + TPM_ALG_ID kdf; + UINT16 digestSize; + TPM2B_DIGEST residual; +} KDF_STATE, *pKDR_STATE; +#define KDF_MAGIC ((UINT32)0x4048444a) // "KDF " backwards + +// Make sure that any other structures added to this union start with a 64-bit +// counter and a 32-bit magic number +typedef union +{ + DRBG_STATE drbg; + KDF_STATE kdf; +} RAND_STATE; + +// This is the state used when the library uses a random number generator. +// A special function is installed for the library to call. That function +// picks up the state from this location and uses it for the generation +// of the random number. +extern RAND_STATE* s_random; + +// When instrumenting RSA key sieve +#if RSA_INSTRUMENT +# define PRIME_INDEX(x) ((x) == 512 ? 0 : (x) == 1024 ? 1 : 2) +# define INSTRUMENT_SET(a, b) ((a) = (b)) +# define INSTRUMENT_ADD(a, b) (a) = (a) + (b) +# define INSTRUMENT_INC(a) (a) = (a) + 1 + +extern UINT32 PrimeIndex; +extern UINT32 failedAtIteration[10]; +extern UINT32 PrimeCounts[3]; +extern UINT32 MillerRabinTrials[3]; +extern UINT32 totalFieldsSieved[3]; +extern UINT32 bitsInFieldAfterSieve[3]; +extern UINT32 emptyFieldsSieved[3]; +extern UINT32 noPrimeFields[3]; +extern UINT32 primesChecked[3]; +extern UINT16 lastSievePrime; +#else +# define INSTRUMENT_SET(a, b) +# define INSTRUMENT_ADD(a, b) +# define INSTRUMENT_INC(a) +#endif + +#endif // _CRYPT_RAND_H diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CryptRsa.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CryptRsa.h new file mode 100644 index 0000000..3cdb5fd --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CryptRsa.h @@ -0,0 +1,69 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 contains the RSA-related structures and defines. + +#ifndef _CRYPT_RSA_H +#define _CRYPT_RSA_H + +// These values are used in the bigNum representation of various RSA values. +BN_TYPE(rsa, MAX_RSA_KEY_BITS); +#define BN_RSA(name) BN_VAR(name, MAX_RSA_KEY_BITS) +#define BN_RSA_INITIALIZED(name, initializer) \ + BN_INITIALIZED(name, MAX_RSA_KEY_BITS, initializer) + +#define BN_PRIME(name) BN_VAR(name, (MAX_RSA_KEY_BITS / 2)) +BN_TYPE(prime, (MAX_RSA_KEY_BITS / 2)); +#define BN_PRIME_INITIALIZED(name, initializer) \ + BN_INITIALIZED(name, MAX_RSA_KEY_BITS / 2, initializer) + +#if !CRT_FORMAT_RSA +# error This verson only works with CRT formatted data +#endif // !CRT_FORMAT_RSA + +typedef struct privateExponent +{ + bigNum P; + bigNum Q; + bigNum dP; + bigNum dQ; + bigNum qInv; + bn_prime_t entries[5]; +} privateExponent; + +#define NEW_PRIVATE_EXPONENT(X) \ + privateExponent _##X; \ + privateExponent* X = RsaInitializeExponent(&(_##X)) + +#endif // _CRYPT_RSA_H diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CryptSym.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CryptSym.h new file mode 100644 index 0000000..c3582e3 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CryptSym.h @@ -0,0 +1,116 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// +// This file contains the implementation of the symmetric block cipher modes +// allowed for a TPM. These functions only use the single block encryption functions +// of the selected symmetric cryptographic library. + +//** Includes, Defines, and Typedefs +#ifndef CRYPT_SYM_H +#define CRYPT_SYM_H + +#if ALG_AES +# define IF_IMPLEMENTED_AES(op) op(AES, aes) +#else +# define IF_IMPLEMENTED_AES(op) +#endif +#if ALG_SM4 +# define IF_IMPLEMENTED_SM4(op) op(SM4, sm4) +#else +# define IF_IMPLEMENTED_SM4(op) +#endif +#if ALG_CAMELLIA +# define IF_IMPLEMENTED_CAMELLIA(op) op(CAMELLIA, camellia) +#else +# define IF_IMPLEMENTED_CAMELLIA(op) +#endif +#if ALG_TDES +# define IF_IMPLEMENTED_TDES(op) op(TDES, tdes) +#else +# define IF_IMPLEMENTED_TDES(op) +#endif + +#define FOR_EACH_SYM(op) \ + IF_IMPLEMENTED_AES(op) \ + IF_IMPLEMENTED_SM4(op) \ + IF_IMPLEMENTED_CAMELLIA(op) \ + IF_IMPLEMENTED_TDES(op) + +// Macros for creating the key schedule union +#define KEY_SCHEDULE(SYM, sym) tpmKeySchedule##SYM sym; +#define TDES DES[3] +typedef union tpmCryptKeySchedule_t +{ + FOR_EACH_SYM(KEY_SCHEDULE) + +#if SYMMETRIC_ALIGNMENT == 8 + uint64_t alignment; +#else + uint32_t alignment; +#endif +} tpmCryptKeySchedule_t; + +// Each block cipher within a library is expected to conform to the same calling +// conventions with three parameters ('keySchedule', 'in', and 'out') in the same +// order. That means that all algorithms would use the same order of the same +// parameters. The code is written assuming the ('keySchedule', 'in', and 'out') +// order. However, if the library uses a different order, the order can be changed +// with a SWIZZLE macro that puts the parameters in the correct order. +// Note that all algorithms have to use the same order and number of parameters +// because the code to build the calling list is common for each call to encrypt +// or decrypt with the algorithm chosen by setting a function pointer to select +// the algorithm that is used. + +#define ENCRYPT(keySchedule, in, out) encrypt(SWIZZLE(keySchedule, in, out)) + +#define DECRYPT(keySchedule, in, out) decrypt(SWIZZLE(keySchedule, in, out)) + +// Note that the macros rely on 'encrypt' as local values in the +// functions that use these macros. Those parameters are set by the macro that +// set the key schedule to be used for the call. + +#define ENCRYPT_CASE(ALG, alg) \ + case TPM_ALG_##ALG: \ + TpmCryptSetEncryptKey##ALG(key, keySizeInBits, &keySchedule.alg); \ + encrypt = (TpmCryptSetSymKeyCall_t)TpmCryptEncrypt##ALG; \ + break; +#define DECRYPT_CASE(ALG, alg) \ + case TPM_ALG_##ALG: \ + TpmCryptSetDecryptKey##ALG(key, keySizeInBits, &keySchedule.alg); \ + decrypt = (TpmCryptSetSymKeyCall_t)TpmCryptDecrypt##ALG; \ + break; + +#endif // CRYPT_SYM_H \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CryptTest.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CryptTest.h new file mode 100644 index 0000000..f587f45 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/CryptTest.h @@ -0,0 +1,69 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 contains constant definitions used for self-test. + +#ifndef _CRYPT_TEST_H +#define _CRYPT_TEST_H + +// This is the definition of a bit array with one bit per algorithm. +// NOTE: Since bit numbering starts at zero, when TPM_ALG_LAST is a multiple of 8, +// ALGORITHM_VECTOR will need to have byte for the single bit in the last byte. So, +// for example, when TPM_ALG_LAST is 8, ALGORITHM_VECTOR will need 2 bytes. +#define ALGORITHM_VECTOR_BYTES ((TPM_ALG_LAST + 8) / 8) +typedef BYTE ALGORITHM_VECTOR[ALGORITHM_VECTOR_BYTES]; + +#ifdef TEST_SELF_TEST +LIB_EXPORT extern ALGORITHM_VECTOR LibToTest; +#endif + +// This structure is used to contain self-test tracking information for the +// cryptographic modules. Each of the major modules is given a 32-bit value in +// which it may maintain its own self test information. The convention for this +// state is that when all of the bits in this structure are 0, all functions need +// to be tested. +typedef struct +{ + UINT32 rng; + UINT32 hash; + UINT32 sym; +#if ALG_RSA + UINT32 rsa; +#endif +#if ALG_ECC + UINT32 ecc; +#endif +} CRYPTO_SELF_TEST_STATE; + +#endif // _CRYPT_TEST_H diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/EccTestData.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/EccTestData.h new file mode 100644 index 0000000..d4f5e67 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/EccTestData.h @@ -0,0 +1,184 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 contains the parameter data for ECC testing. + +#ifdef SELF_TEST_DATA + +TPM2B_TYPE(EC_TEST, 32); +const TPM_ECC_CURVE c_testCurve = 00003; + +// The "static" key + +const TPM2B_EC_TEST c_ecTestKey_ds = { + {32, {0xdf, 0x8d, 0xa4, 0xa3, 0x88, 0xf6, 0x76, 0x96, 0x89, 0xfc, 0x2f, + 0x2d, 0xa1, 0xb4, 0x39, 0x7a, 0x78, 0xc4, 0x7f, 0x71, 0x8c, 0xa6, + 0x91, 0x85, 0xc0, 0xbf, 0xf3, 0x54, 0x20, 0x91, 0x2f, 0x73}}}; + +const TPM2B_EC_TEST c_ecTestKey_QsX = { + {32, {0x17, 0xad, 0x2f, 0xcb, 0x18, 0xd4, 0xdb, 0x3f, 0x2c, 0x53, 0x13, + 0x82, 0x42, 0x97, 0xff, 0x8d, 0x99, 0x50, 0x16, 0x02, 0x35, 0xa7, + 0x06, 0xae, 0x1f, 0xda, 0xe2, 0x9c, 0x12, 0x77, 0xc0, 0xf9}}}; + +const TPM2B_EC_TEST c_ecTestKey_QsY = { + {32, {0xa6, 0xca, 0xf2, 0x18, 0x45, 0x96, 0x6e, 0x58, 0xe6, 0x72, 0x34, + 0x12, 0x89, 0xcd, 0xaa, 0xad, 0xcb, 0x68, 0xb2, 0x51, 0xdc, 0x5e, + 0xd1, 0x6d, 0x38, 0x20, 0x35, 0x57, 0xb2, 0xfd, 0xc7, 0x52}}}; + +// The "ephemeral" key + +const TPM2B_EC_TEST c_ecTestKey_de = { + {32, {0xb6, 0xb5, 0x33, 0x5c, 0xd1, 0xee, 0x52, 0x07, 0x99, 0xea, 0x2e, + 0x8f, 0x8b, 0x19, 0x18, 0x07, 0xc1, 0xf8, 0xdf, 0xdd, 0xb8, 0x77, + 0x00, 0xc7, 0xd6, 0x53, 0x21, 0xed, 0x02, 0x53, 0xee, 0xac}}}; + +const TPM2B_EC_TEST c_ecTestKey_QeX = { + {32, {0xa5, 0x1e, 0x80, 0xd1, 0x76, 0x3e, 0x8b, 0x96, 0xce, 0xcc, 0x21, + 0x82, 0xc9, 0xa2, 0xa2, 0xed, 0x47, 0x21, 0x89, 0x53, 0x44, 0xe9, + 0xc7, 0x92, 0xe7, 0x31, 0x48, 0x38, 0xe6, 0xea, 0x93, 0x47}}}; + +const TPM2B_EC_TEST c_ecTestKey_QeY = { + {32, {0x30, 0xe6, 0x4f, 0x97, 0x03, 0xa1, 0xcb, 0x3b, 0x32, 0x2a, 0x70, + 0x39, 0x94, 0xeb, 0x4e, 0xea, 0x55, 0x88, 0x81, 0x3f, 0xb5, 0x00, + 0xb8, 0x54, 0x25, 0xab, 0xd4, 0xda, 0xfd, 0x53, 0x7a, 0x18}}}; + +// ECDH test results +const TPM2B_EC_TEST c_ecTestEcdh_X = { + {32, {0x64, 0x02, 0x68, 0x92, 0x78, 0xdb, 0x33, 0x52, 0xed, 0x3b, 0xfa, + 0x3b, 0x74, 0xa3, 0x3d, 0x2c, 0x2f, 0x9c, 0x59, 0x03, 0x07, 0xf8, + 0x22, 0x90, 0xed, 0xe3, 0x45, 0xf8, 0x2a, 0x0a, 0xd8, 0x1d}}}; + +const TPM2B_EC_TEST c_ecTestEcdh_Y = { + {32, {0x58, 0x94, 0x05, 0x82, 0xbe, 0x5f, 0x33, 0x02, 0x25, 0x90, 0x3a, + 0x33, 0x90, 0x89, 0xe3, 0xe5, 0x10, 0x4a, 0xbc, 0x78, 0xa5, 0xc5, + 0x07, 0x64, 0xaf, 0x91, 0xbc, 0xe6, 0xff, 0x85, 0x11, 0x40}}}; + +TPM2B_TYPE(TEST_VALUE, 64); +const TPM2B_TEST_VALUE c_ecTestValue = { + {64, + {0x78, 0xd5, 0xd4, 0x56, 0x43, 0x61, 0xdb, 0x97, 0xa4, 0x32, 0xc4, 0x0b, 0x06, + 0xa9, 0xa8, 0xa0, 0xf4, 0x45, 0x7f, 0x13, 0xd8, 0x13, 0x81, 0x0b, 0xe5, 0x76, + 0xbe, 0xaa, 0xb6, 0x3f, 0x8d, 0x4d, 0x23, 0x65, 0xcc, 0xa7, 0xc9, 0x19, 0x10, + 0xce, 0x69, 0xcb, 0x0c, 0xc7, 0x11, 0x8d, 0xc3, 0xff, 0x62, 0x69, 0xa2, 0xbe, + 0x46, 0x90, 0xe7, 0x7d, 0x81, 0x77, 0x94, 0x65, 0x1c, 0x3e, 0xc1, 0x3e}}}; + +# if ALG_SHA1_VALUE == DEFAULT_TEST_HASH + +const TPM2B_EC_TEST c_TestEcDsa_r = { + {32, {0x57, 0xf3, 0x36, 0xb7, 0xec, 0xc2, 0xdd, 0x76, 0x0e, 0xe2, 0x81, + 0x21, 0x49, 0xc5, 0x66, 0x11, 0x4b, 0x8a, 0x4f, 0x17, 0x62, 0x82, + 0xcc, 0x06, 0xf6, 0x64, 0x78, 0xef, 0x6b, 0x7c, 0xf2, 0x6c}}}; +const TPM2B_EC_TEST c_TestEcDsa_s = { + {32, {0x1b, 0xed, 0x23, 0x72, 0x8f, 0x17, 0x5f, 0x47, 0x2e, 0xa7, 0x97, + 0x2c, 0x51, 0x57, 0x20, 0x70, 0x6f, 0x89, 0x74, 0x8a, 0xa8, 0xf4, + 0x26, 0xf4, 0x96, 0xa1, 0xb8, 0x3e, 0xe5, 0x35, 0xc5, 0x94}}}; + +const TPM2B_EC_TEST c_TestEcSchnorr_r = { + {32, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1b, 0x08, 0x9f, 0xde, 0xef, 0x62, 0xe3, 0xf1, 0x14, 0xcb, + 0x54, 0x28, 0x13, 0x76, 0xfc, 0x6d, 0x69, 0x22, 0xb5, 0x3e}}}; +const TPM2B_EC_TEST c_TestEcSchnorr_s = { + {32, {0xd9, 0xd3, 0x20, 0xfb, 0x4d, 0x16, 0xf2, 0xe6, 0xe2, 0x45, 0x07, + 0x45, 0x1c, 0x92, 0x92, 0x92, 0xa9, 0x6b, 0x48, 0xf8, 0xd1, 0x98, + 0x29, 0x4d, 0xd3, 0x8f, 0x56, 0xf2, 0xbb, 0x2e, 0x22, 0x3b}}}; + +# endif // SHA1 + +# if ALG_SHA256_VALUE == DEFAULT_TEST_HASH + +const TPM2B_EC_TEST c_TestEcDsa_r = { + {32, {0x04, 0x7d, 0x54, 0xeb, 0x04, 0x6f, 0x56, 0xec, 0xa2, 0x6c, 0x38, + 0x8c, 0xeb, 0x43, 0x0b, 0x71, 0xf8, 0xf2, 0xf4, 0xa5, 0xe0, 0x1d, + 0x3c, 0xa2, 0x39, 0x31, 0xe4, 0xe7, 0x36, 0x3b, 0xb5, 0x5f}}}; +const TPM2B_EC_TEST c_TestEcDsa_s = { + {32, {0x8f, 0xd0, 0x12, 0xd9, 0x24, 0x75, 0xf6, 0xc4, 0x3b, 0xb5, 0x46, + 0x75, 0x3a, 0x41, 0x8d, 0x80, 0x23, 0x99, 0x38, 0xd7, 0xe2, 0x40, + 0xca, 0x9a, 0x19, 0x2a, 0xfc, 0x54, 0x75, 0xd3, 0x4a, 0x6e}}}; + +const TPM2B_EC_TEST c_TestEcSchnorr_r = { + {32, {0xf7, 0xb9, 0x15, 0x4c, 0x34, 0xf6, 0x41, 0x19, 0xa3, 0xd2, 0xf1, + 0xbd, 0xf4, 0x13, 0x6a, 0x4f, 0x63, 0xb8, 0x4d, 0xb5, 0xc8, 0xcd, + 0xde, 0x85, 0x95, 0xa5, 0x39, 0x0a, 0x14, 0x49, 0x3d, 0x2f}}}; +const TPM2B_EC_TEST c_TestEcSchnorr_s = { + {32, {0xfe, 0xbe, 0x17, 0xaa, 0x31, 0x22, 0x9f, 0xd0, 0xd2, 0xf5, 0x25, + 0x04, 0x92, 0xb0, 0xaa, 0x4e, 0xcc, 0x1c, 0xb6, 0x79, 0xd6, 0x42, + 0xb3, 0x4e, 0x3f, 0xbb, 0xfe, 0x5f, 0xd0, 0xd0, 0x8b, 0xc3}}}; + +# endif // SHA256 + +# if ALG_SHA384_VALUE == DEFAULT_TEST_HASH + +const TPM2B_EC_TEST c_TestEcDsa_r = { + {32, {0xf5, 0x74, 0x6d, 0xd6, 0xc6, 0x56, 0x86, 0xbb, 0xba, 0x1c, 0xba, + 0x75, 0x65, 0xee, 0x64, 0x31, 0xce, 0x04, 0xe3, 0x9f, 0x24, 0x3f, + 0xbd, 0xfe, 0x04, 0xcd, 0xab, 0x7e, 0xfe, 0xad, 0xcb, 0x82}}}; +const TPM2B_EC_TEST c_TestEcDsa_s = { + {32, {0xc2, 0x4f, 0x32, 0xa1, 0x06, 0xc0, 0x85, 0x4f, 0xc6, 0xd8, 0x31, + 0x66, 0x91, 0x9f, 0x79, 0xcd, 0x5b, 0xe5, 0x7b, 0x94, 0xa1, 0x91, + 0x38, 0xac, 0xd4, 0x20, 0xa2, 0x10, 0xf0, 0xd5, 0x9d, 0xbf}}}; + +const TPM2B_EC_TEST c_TestEcSchnorr_r = { + {32, {0x1e, 0xb8, 0xe1, 0xbf, 0xa1, 0x9e, 0x39, 0x1e, 0x58, 0xa2, 0xe6, + 0x59, 0xd0, 0x1a, 0x6a, 0x03, 0x6a, 0x1f, 0x1c, 0x4f, 0x36, 0x19, + 0xc1, 0xec, 0x30, 0xa4, 0x85, 0x1b, 0xe9, 0x74, 0x35, 0x66}}}; +const TPM2B_EC_TEST c_TestEcSchnorr_s = { + {32, {0xb9, 0xe6, 0xe3, 0x7e, 0xcb, 0xb9, 0xea, 0xf1, 0xcc, 0xf4, 0x48, + 0x44, 0x4a, 0xda, 0xc8, 0xd7, 0x87, 0xb4, 0xba, 0x40, 0xfe, 0x5b, + 0x68, 0x11, 0x14, 0xcf, 0xa0, 0x0e, 0x85, 0x46, 0x99, 0x01}}}; + +# endif // SHA384 + +# if ALG_SHA512_VALUE == DEFAULT_TEST_HASH + +const TPM2B_EC_TEST c_TestEcDsa_r = { + {32, {0xc9, 0x71, 0xa6, 0xb4, 0xaf, 0x46, 0x26, 0x8c, 0x27, 0x00, 0x06, + 0x3b, 0x00, 0x0f, 0xa3, 0x17, 0x72, 0x48, 0x40, 0x49, 0x4d, 0x51, + 0x4f, 0xa4, 0xcb, 0x7e, 0x86, 0xe9, 0xe7, 0xb4, 0x79, 0xb2}}}; +const TPM2B_EC_TEST c_TestEcDsa_s = { + {32, {0x87, 0xbc, 0xc0, 0xed, 0x74, 0x60, 0x9e, 0xfa, 0x4e, 0xe8, 0x16, + 0xf3, 0xf9, 0x6b, 0x26, 0x07, 0x3c, 0x74, 0x31, 0x7e, 0xf0, 0x62, + 0x46, 0xdc, 0xd6, 0x45, 0x22, 0x47, 0x3e, 0x0c, 0xa0, 0x02}}}; + +const TPM2B_EC_TEST c_TestEcSchnorr_r = { + {32, {0xcc, 0x07, 0xad, 0x65, 0x91, 0xdd, 0xa0, 0x10, 0x23, 0xae, 0x53, + 0xec, 0xdf, 0xf1, 0x50, 0x90, 0x16, 0x96, 0xf4, 0x45, 0x09, 0x73, + 0x9c, 0x84, 0xb5, 0x5c, 0x5f, 0x08, 0x51, 0xcb, 0x60, 0x01}}}; +const TPM2B_EC_TEST c_TestEcSchnorr_s = { + {32, {0x55, 0x20, 0x21, 0x54, 0xe2, 0x49, 0x07, 0x47, 0x71, 0xf4, 0x99, + 0x15, 0x54, 0xf3, 0xab, 0x14, 0xdb, 0x8e, 0xda, 0x79, 0xb6, 0x02, + 0x0e, 0xe3, 0x5e, 0x6f, 0x2c, 0xb6, 0x05, 0xbd, 0x14, 0x10}}}; + +# endif // SHA512 + +#endif // SELF_TEST_DATA diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Global.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Global.h new file mode 100644 index 0000000..7bf4dd3 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Global.h @@ -0,0 +1,1415 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//** Description + +// This file contains internal global type definitions and data declarations that +// are need between subsystems. The instantiation of global data is in Global.c. +// The initialization of global data is in the subsystem that is the primary owner +// of the data. +// +// The first part of this file has the 'typedefs' for structures and other defines +// used in many portions of the code. After the 'typedef' section, is a section that +// defines global values that are only present in RAM. The next three sections +// define the structures for the NV data areas: persistent, orderly, and state +// save. Additional sections define the data that is used in specific modules. That +// data is private to the module but is collected here to simplify the management +// of the instance data. +// +// All the data is instanced in Global.c. +#if !defined _TPM_H_ +# error "Should only be instanced in TPM.h" +#endif + +//** Includes + +#ifndef GLOBAL_H +# define GLOBAL_H + +_REDUCE_WARNING_LEVEL_(2) +# include +# include +_NORMAL_WARNING_LEVEL_ + +# include "Capabilities.h" +# include "TpmTypes.h" +# include "CommandAttributes.h" +# include "CryptTest.h" +# include "BnValues.h" +# include "CryptHash.h" +# include "CryptSym.h" +# include "CryptRand.h" +# include "CryptEcc.h" +# include "CryptRsa.h" +# include "CryptTest.h" +# include "TpmError.h" +# include "NV.h" +# include "ACT.h" + +//** Defines and Types + +//*** Size Types +// These types are used to differentiate the two different size values used. +// +// NUMBYTES is used when a size is a number of bytes (usually a TPM2B) +typedef UINT16 NUMBYTES; + +//*** Other Types +// An AUTH_VALUE is a BYTE array containing a digest (TPMU_HA) +typedef BYTE AUTH_VALUE[sizeof(TPMU_HA)]; + +// A TIME_INFO is a BYTE array that can contain a TPMS_TIME_INFO +typedef BYTE TIME_INFO[sizeof(TPMS_TIME_INFO)]; + +// A NAME is a BYTE array that can contain a TPMU_NAME +typedef BYTE NAME[sizeof(TPMU_NAME)]; + +// Definition for a PROOF value +TPM2B_TYPE(PROOF, PROOF_SIZE); + +// Definition for a Primary Seed value +TPM2B_TYPE(SEED, PRIMARY_SEED_SIZE); + +// A CLOCK_NONCE is used to tag the time value in the authorization session and +// in the ticket computation so that the ticket expires when there is a time +// discontinuity. When the clock stops during normal operation, the nonce is +// 64-bit value kept in RAM but it is a 32-bit counter when the clock only stops +// during power events. +# if CLOCK_STOPS +typedef UINT64 CLOCK_NONCE; +# else +typedef UINT32 CLOCK_NONCE; +# endif + +//** Loaded Object Structures +//*** Description +// The structures in this section define the object layout as it exists in TPM +// memory. +// +// Two types of objects are defined: an ordinary object such as a key, and a +// sequence object that may be a hash, HMAC, or event. +// +//*** OBJECT_ATTRIBUTES +// An OBJECT_ATTRIBUTES structure contains the variable attributes of an object. +// These properties are not part of the public properties but are used by the +// TPM in managing the object. An OBJECT_ATTRIBUTES is used in the definition of +// the OBJECT data type. + +typedef struct +{ + unsigned publicOnly : 1; //0) SET if only the public portion of + // an object is loaded + unsigned epsHierarchy : 1; //1) SET if the object belongs to EPS + // Hierarchy + unsigned ppsHierarchy : 1; //2) SET if the object belongs to PPS + // Hierarchy + unsigned spsHierarchy : 1; //3) SET f the object belongs to SPS + // Hierarchy + unsigned evict : 1; //4) SET if the object is a platform or + // owner evict object. Platform- + // evict object belongs to PPS + // hierarchy, owner-evict object + // belongs to SPS or EPS hierarchy. + // This bit is also used to mark a + // completed sequence object so it + // will be flush when the + // SequenceComplete command succeeds. + unsigned primary : 1; //5) SET for a primary object + unsigned temporary : 1; //6) SET for a temporary object + unsigned stClear : 1; //7) SET for an stClear object + unsigned hmacSeq : 1; //8) SET for an HMAC or MAC sequence + // object + unsigned hashSeq : 1; //9) SET for a hash sequence object + unsigned eventSeq : 1; //10) SET for an event sequence object + unsigned ticketSafe : 1; //11) SET if a ticket is safe to create + // for hash sequence object + unsigned firstBlock : 1; //12) SET if the first block of hash + // data has been received. It + // works with ticketSafe bit + unsigned isParent : 1; //13) SET if the key has the proper + // attributes to be a parent key + // unsigned privateExp : 1; //14) SET when the private exponent + // // of an RSA key has been validated. + unsigned not_used_14 : 1; + unsigned occupied : 1; //15) SET when the slot is occupied. + unsigned derivation : 1; //16) SET when the key is a derivation + // parent + unsigned external : 1; //17) SET when the object is loaded with + // TPM2_LoadExternal(); +} OBJECT_ATTRIBUTES; + +# if ALG_RSA +// There is an overload of the sensitive.rsa.t.size field of a TPMT_SENSITIVE when an +// RSA key is loaded. When the sensitive->sensitive contains an RSA key with all of +// the CRT values, then the MSB of the size field will be set to indicate that the +// buffer contains all 5 of the CRT private key values. +# define RSA_prime_flag 0x8000 +# endif + +//*** OBJECT Structure +// An OBJECT structure holds the object public, sensitive, and meta-data +// associated. This structure is implementation dependent. For this +// implementation, the structure is not optimized for space but rather +// for clarity of the reference implementation. Other implementations +// may choose to overlap portions of the structure that are not used +// simultaneously. These changes would necessitate changes to the source +// code but those changes would be compatible with the reference +// implementation. + +typedef struct OBJECT +{ + // The attributes field is required to be first followed by the publicArea. + // This allows the overlay of the object structure and a sequence structure + OBJECT_ATTRIBUTES attributes; // object attributes + TPMT_PUBLIC publicArea; // public area of an object + TPMT_SENSITIVE sensitive; // sensitive area of an object + TPM2B_NAME qualifiedName; // object qualified name + TPMI_DH_OBJECT evictHandle; // if the object is an evict object, + // the original handle is kept here. + // The 'working' handle will be the + // handle of an object slot. + TPM2B_NAME name; // Name of the object name. Kept here + // to avoid repeatedly computing it. +} OBJECT; + +//*** HASH_OBJECT Structure +// This structure holds a hash sequence object or an event sequence object. +// +// The first four components of this structure are manually set to be the same as +// the first four components of the object structure. This prevents the object +// from being inadvertently misused as sequence objects occupy the same memory as +// a regular object. A debug check is present to make sure that the offsets are +// what they are supposed to be. +// NOTE: In a future version, this will probably be renamed as SEQUENCE_OBJECT +typedef struct HASH_OBJECT +{ + OBJECT_ATTRIBUTES attributes; // The attributes of the HASH object + TPMI_ALG_PUBLIC type; // algorithm + TPMI_ALG_HASH nameAlg; // name algorithm + TPMA_OBJECT objectAttributes; // object attributes + + // The data below is unique to a sequence object + TPM2B_AUTH auth; // authorization for use of sequence + union + { + HASH_STATE hashState[HASH_COUNT]; + HMAC_STATE hmacState; + } state; +} HASH_OBJECT; + +typedef BYTE HASH_OBJECT_BUFFER[sizeof(HASH_OBJECT)]; + +//*** ANY_OBJECT +// This is the union for holding either a sequence object or a regular object +// for ContextSave and ContextLoad. +typedef union ANY_OBJECT +{ + OBJECT entity; + HASH_OBJECT hash; +} ANY_OBJECT; + +typedef BYTE ANY_OBJECT_BUFFER[sizeof(ANY_OBJECT)]; + +//**AUTH_DUP Types +// These values are used in the authorization processing. + +typedef UINT32 AUTH_ROLE; +# define AUTH_NONE ((AUTH_ROLE)(0)) +# define AUTH_USER ((AUTH_ROLE)(1)) +# define AUTH_ADMIN ((AUTH_ROLE)(2)) +# define AUTH_DUP ((AUTH_ROLE)(3)) + +//** Active Session Context +//*** Description +// The structures in this section define the internal structure of a session +// context. +// +//*** SESSION_ATTRIBUTES +// The attributes in the SESSION_ATTRIBUTES structure track the various properties +// of the session. It maintains most of the tracking state information for the +// policy session. It is used within the SESSION structure. + +typedef struct SESSION_ATTRIBUTES +{ + unsigned isPolicy : 1; //1) SET if the session may only be used + // for policy + unsigned isAudit : 1; //2) SET if the session is used for audit + unsigned isBound : 1; //3) SET if the session is bound to with an + // entity. This attribute will be CLEAR + // if either isPolicy or isAudit is SET. + unsigned isCpHashDefined : 1; //4) SET if the cpHash has been defined + // This attribute is not SET unless + // 'isPolicy' is SET. + unsigned isAuthValueNeeded : 1; //5) SET if the authValue is required for + // computing the session HMAC. This + // attribute is not SET unless 'isPolicy' + // is SET. + unsigned isPasswordNeeded : 1; //6) SET if a password authValue is required + // for authorization This attribute is not + // SET unless 'isPolicy' is SET. + unsigned isPPRequired : 1; //7) SET if physical presence is required to + // be asserted when the authorization is + // checked. This attribute is not SET + // unless 'isPolicy' is SET. + unsigned isTrialPolicy : 1; //8) SET if the policy session is created + // for trial of the policy's policyHash + // generation. This attribute is not SET + // unless 'isPolicy' is SET. + unsigned isDaBound : 1; //9) SET if the bind entity had noDA CLEAR. + // If this is SET, then an authorization + // failure using this session will count + // against lockout even if the object + // being authorized is exempt from DA. + unsigned isLockoutBound : 1; //10) SET if the session is bound to + // lockoutAuth. + unsigned includeAuth : 1; //11) This attribute is SET when the + // authValue of an object is to be + // included in the computation of the + // HMAC key for the command and response + // computations. (was 'requestWasBound') + unsigned checkNvWritten : 1; //12) SET if the TPMA_NV_WRITTEN attribute + // needs to be checked when the policy is + // used for authorization for NV access. + // If this is SET for any other type, the + // policy will fail. + unsigned nvWrittenState : 1; //13) SET if TPMA_NV_WRITTEN is required to + // be SET. Used when 'checkNvWritten' is + // SET + unsigned isTemplateSet : 1; //14) SET if the templateHash needs to be + // checked for Create, CreatePrimary, or + // CreateLoaded. +} SESSION_ATTRIBUTES; + +//*** SESSION Structure +// The SESSION structure contains all the context of a session except for the +// associated contextID. +// +// Note: The contextID of a session is only relevant when the session context +// is stored off the TPM. + +typedef struct SESSION +{ + SESSION_ATTRIBUTES attributes; // session attributes + UINT32 pcrCounter; // PCR counter value when PCR is + // included (policy session) + // If no PCR is included, this + // value is 0. + UINT64 startTime; // The value in g_time when the session + // was started (policy session) + UINT64 timeout; // The timeout relative to g_time + // There is no timeout if this value + // is 0. + CLOCK_NONCE epoch; // The g_clockEpoch value when the + // session was started. If g_clockEpoch + // does not match this value when the + // timeout is used, then + // then the command will fail. + TPM_CC commandCode; // command code (policy session) + TPM_ALG_ID authHashAlg; // session hash algorithm + TPMA_LOCALITY commandLocality; // command locality (policy session) + TPMT_SYM_DEF symmetric; // session symmetric algorithm (if any) + TPM2B_AUTH sessionKey; // session secret value used for + // this session + TPM2B_NONCE nonceTPM; // last TPM-generated nonce for + // generating HMAC and encryption keys + union + { + TPM2B_NAME boundEntity; // value used to track the entity to + // which the session is bound + + TPM2B_DIGEST cpHash; // the required cpHash value for the + // command being authorized + TPM2B_DIGEST nameHash; // the required nameHash + TPM2B_DIGEST templateHash; // the required template for creation + } u1; + + union + { + TPM2B_DIGEST auditDigest; // audit session digest + TPM2B_DIGEST policyDigest; // policyHash + } u2; // audit log and policyHash may + // share space to save memory +} SESSION; + +# define EXPIRES_ON_RESET INT32_MIN +# define TIMEOUT_ON_RESET UINT64_MAX +# define EXPIRES_ON_RESTART (INT32_MIN + 1) +# define TIMEOUT_ON_RESTART (UINT64_MAX - 1) + +typedef BYTE SESSION_BUF[sizeof(SESSION)]; + +//********************************************************************************* +//** PCR +//********************************************************************************* +//***PCR_SAVE Structure +// The PCR_SAVE structure type contains the PCR data that are saved across power +// cycles. Only the static PCR are required to be saved across power cycles. The +// DRTM and resettable PCR are not saved. The number of static and resettable PCR +// is determined by the platform-specific specification to which the TPM is built. + +# define PCR_SAVE_SPACE(HASH, Hash) BYTE Hash[NUM_STATIC_PCR][HASH##_DIGEST_SIZE]; + +typedef struct PCR_SAVE +{ + FOR_EACH_HASH(PCR_SAVE_SPACE) + + // This counter increments whenever the PCR are updated. + // NOTE: A platform-specific specification may designate + // certain PCR changes as not causing this counter + // to increment. + UINT32 pcrCounter; +} PCR_SAVE; + +//***PCR_POLICY +# if defined NUM_POLICY_PCR_GROUP && NUM_POLICY_PCR_GROUP > 0 +// This structure holds the PCR policies, one for each group of PCR controlled +// by policy. +typedef struct PCR_POLICY +{ + TPMI_ALG_HASH hashAlg[NUM_POLICY_PCR_GROUP]; + TPM2B_DIGEST a; + TPM2B_DIGEST policy[NUM_POLICY_PCR_GROUP]; +} PCR_POLICY; +# endif + +//***PCR_AUTHVALUE +// This structure holds the PCR policies, one for each group of PCR controlled +// by policy. +typedef struct PCR_AUTH_VALUE +{ + TPM2B_DIGEST auth[NUM_AUTHVALUE_PCR_GROUP]; +} PCR_AUTHVALUE; + +//**STARTUP_TYPE +// This enumeration is the possible startup types. The type is determined +// by the combination of TPM2_ShutDown and TPM2_Startup. +typedef enum +{ + SU_RESET, + SU_RESTART, + SU_RESUME +} STARTUP_TYPE; + +//**NV + +//***NV_INDEX +// The NV_INDEX structure defines the internal format for an NV index. +// The 'indexData' size varies according to the type of the index. +// In this implementation, all of the index is manipulated as a unit. +typedef struct NV_INDEX +{ + TPMS_NV_PUBLIC publicArea; + TPM2B_AUTH authValue; +} NV_INDEX; + +//*** NV_REF +// An NV_REF is an opaque value returned by the NV subsystem. It is used to +// reference and NV Index in a relatively efficient way. Rather than having to +// continually search for an Index, its reference value may be used. In this +// implementation, an NV_REF is a byte pointer that points to the copy of the +// NV memory that is kept in RAM. +typedef UINT32 NV_REF; + +typedef BYTE* NV_RAM_REF; +//***NV_PIN +// This structure deals with the possible endianess differences between the +// canonical form of the TPMS_NV_PIN_COUNTER_PARAMETERS structure and the internal +// value. The structures allow the data in a PIN index to be read as an 8-octet +// value using NvReadUINT64Data(). That function will byte swap all the values on a +// little endian system. This will put the bytes with the 4-octet values in the +// correct order but will swap the pinLimit and pinCount values. When written, the +// PIN index is simply handled as a normal index with the octets in canonical order. +# if BIG_ENDIAN_TPM +typedef struct +{ + UINT32 pinCount; + UINT32 pinLimit; +} PIN_DATA; +# else +typedef struct +{ + UINT32 pinLimit; + UINT32 pinCount; +} PIN_DATA; +# endif + +typedef union +{ + UINT64 intVal; + PIN_DATA pin; +} NV_PIN; + +//**COMMIT_INDEX_MASK +// This is the define for the mask value that is used when manipulating +// the bits in the commit bit array. The commit counter is a 64-bit +// value and the low order bits are used to index the commitArray. +// This mask value is applied to the commit counter to extract the +// bit number in the array. +# if ALG_ECC + +# define COMMIT_INDEX_MASK ((UINT16)((sizeof(gr.commitArray) * 8) - 1)) + +# endif + +//***************************************************************************** +//***************************************************************************** +//** RAM Global Values +//***************************************************************************** +//***************************************************************************** +//*** Description +// The values in this section are only extant in RAM or ROM as constant values. + +//*** Crypto Self-Test Values +EXTERN ALGORITHM_VECTOR g_implementedAlgorithms; +EXTERN ALGORITHM_VECTOR g_toTest; + +//*** g_rcIndex[] +// This array is used to contain the array of values that are added to a return +// code when it is a parameter-, handle-, or session-related error. +// This is an implementation choice and the same result can be achieved by using +// a macro. +# define g_rcIndexInitializer \ + { \ + TPM_RC_1, TPM_RC_2, TPM_RC_3, TPM_RC_4, TPM_RC_5, TPM_RC_6, TPM_RC_7, \ + TPM_RC_8, TPM_RC_9, TPM_RC_A, TPM_RC_B, TPM_RC_C, TPM_RC_D, TPM_RC_E, \ + TPM_RC_F \ + } +EXTERN const UINT16 g_rcIndex[15] INITIALIZER(g_rcIndexInitializer); + +//*** g_exclusiveAuditSession +// This location holds the session handle for the current exclusive audit +// session. If there is no exclusive audit session, the location is set to +// TPM_RH_UNASSIGNED. +EXTERN TPM_HANDLE g_exclusiveAuditSession; + +//*** g_time +// This is the value in which we keep the current command time. This is initialized +// at the start of each command. The time is the accumulated time since the last +// time that the TPM's timer was last powered up. Clock is the accumulated time +// since the last time that the TPM was cleared. g_time is in mS. +EXTERN UINT64 g_time; + +//*** g_timeEpoch +// This value contains the current clock Epoch. It changes when there is a clock +// discontinuity. It may be necessary to place this in NV should the timer be able +// to run across a power down of the TPM but not in all cases (e.g. dead battery). +// If the nonce is placed in NV, it should go in gp because it should be changing +// slowly. +# if CLOCK_STOPS +EXTERN CLOCK_NONCE g_timeEpoch; +# else +# define g_timeEpoch gp.timeEpoch +# endif + +//*** g_phEnable +// This is the platform hierarchy control and determines if the platform hierarchy +// is available. This value is SET on each TPM2_Startup(). The default value is +// SET. +EXTERN BOOL g_phEnable; + +//*** g_pcrReConfig +// This value is SET if a TPM2_PCR_Allocate command successfully executed since +// the last TPM2_Startup(). If so, then the next shutdown is required to be +// Shutdown(CLEAR). +EXTERN BOOL g_pcrReConfig; + +//*** g_DRTMHandle +// This location indicates the sequence object handle that holds the DRTM +// sequence data. When not used, it is set to TPM_RH_UNASSIGNED. A sequence +// DRTM sequence is started on either _TPM_Init or _TPM_Hash_Start. +EXTERN TPMI_DH_OBJECT g_DRTMHandle; + +//*** g_DrtmPreStartup +// This value indicates that an H-CRTM occurred after _TPM_Init but before +// TPM2_Startup(). The define for PRE_STARTUP_FLAG is used to add the +// g_DrtmPreStartup value to gp_orderlyState at shutdown. This hack is to avoid +// adding another NV variable. +EXTERN BOOL g_DrtmPreStartup; + +//*** g_StartupLocality3 +// This value indicates that a TPM2_Startup() occurred at locality 3. Otherwise, it +// at locality 0. The define for STARTUP_LOCALITY_3 is to +// indicate that the startup was not at locality 0. This hack is to avoid +// adding another NV variable. +EXTERN BOOL g_StartupLocality3; + +//***TPM_SU_NONE +// Part 2 defines the two shutdown/startup types that may be used in +// TPM2_Shutdown() and TPM2_Starup(). This additional define is +// used by the TPM to indicate that no shutdown was received. +// NOTE: This is a reserved value. +# define SU_NONE_VALUE (0xFFFF) +# define TPM_SU_NONE (TPM_SU)(SU_NONE_VALUE) + +//*** TPM_SU_DA_USED +// As with TPM_SU_NONE, this value is added to allow indication that the shutdown +// was not orderly and that a DA=protected object was reference during the previous +// cycle. +# define SU_DA_USED_VALUE (SU_NONE_VALUE - 1) +# define TPM_SU_DA_USED (TPM_SU)(SU_DA_USED_VALUE) + +//*** Startup Flags +// These flags are included in gp.orderlyState. These are hacks and are being +// used to avoid having to change the layout of gp. The PRE_STARTUP_FLAG indicates +// that a _TPM_Hash_Start/_Data/_End sequence was received after _TPM_Init but +// before TPM2_StartUp(). STARTUP_LOCALITY_3 indicates that the last TPM2_Startup() +// was received at locality 3. These flags are only relevant if after a +// TPM2_Shutdown(STATE). +# define PRE_STARTUP_FLAG 0x8000 +# define STARTUP_LOCALITY_3 0x4000 + +# if USE_DA_USED +//*** g_daUsed +// This location indicates if a DA-protected value is accessed during a boot +// cycle. If none has, then there is no need to increment 'failedTries' on the +// next non-orderly startup. This bit is merged with gp.orderlyState when +// gp.orderly is set to SU_NONE_VALUE +EXTERN BOOL g_daUsed; +# endif + +//*** g_updateNV +// This flag indicates if NV should be updated at the end of a command. +// This flag is set to UT_NONE at the beginning of each command in ExecuteCommand(). +// This flag is checked in ExecuteCommand() after the detailed actions of a command +// complete. If the command execution was successful and this flag is not UT_NONE, +// any pending NV writes will be committed to NV. +// UT_ORDERLY causes any RAM data to be written to the orderly space for staging +// the write to NV. +typedef BYTE UPDATE_TYPE; +# define UT_NONE (UPDATE_TYPE)0 +# define UT_NV (UPDATE_TYPE)1 +# define UT_ORDERLY (UPDATE_TYPE)(UT_NV + 2) +EXTERN UPDATE_TYPE g_updateNV; + +//*** g_powerWasLost +// This flag is used to indicate if the power was lost. It is SET in _TPM__Init. +// This flag is cleared by TPM2_Startup() after all power-lost activities are +// completed. +// Note: When power is applied, this value can come up as anything. However, +// _plat__WasPowerLost() will provide the proper indication in that case. So, when +// power is actually lost, we get the correct answer. When power was not lost, but +// the power-lost processing has not been completed before the next _TPM_Init(), +// then the TPM still does the correct thing. +EXTERN BOOL g_powerWasLost; + +//*** g_clearOrderly +// This flag indicates if the execution of a command should cause the orderly +// state to be cleared. This flag is set to FALSE at the beginning of each +// command in ExecuteCommand() and is checked in ExecuteCommand() after the +// detailed actions of a command complete but before the check of +// 'g_updateNV'. If this flag is TRUE, and the orderly state is not +// SU_NONE_VALUE, then the orderly state in NV memory will be changed to +// SU_NONE_VALUE or SU_DA_USED_VALUE. +EXTERN BOOL g_clearOrderly; + +//*** g_prevOrderlyState +// This location indicates how the TPM was shut down before the most recent +// TPM2_Startup(). This value, along with the startup type, determines if +// the TPM should do a TPM Reset, TPM Restart, or TPM Resume. +EXTERN TPM_SU g_prevOrderlyState; + +//*** g_nvOk +// This value indicates if the NV integrity check was successful or not. If not and +// the failure was severe, then the TPM would have been put into failure mode after +// it had been re-manufactured. If the NV failure was in the area where the state-save +// data is kept, then this variable will have a value of FALSE indicating that +// a TPM2_Startup(CLEAR) is required. +EXTERN BOOL g_nvOk; +// NV availability is sampled as the start of each command and stored here +// so that its value remains consistent during the command execution +EXTERN TPM_RC g_NvStatus; + +//*** g_platformUnique +// This location contains the unique value(s) used to identify the TPM. It is +// loaded on every _TPM2_Startup() +// The first value is used to seed the RNG. The second value is used as a vendor +// authValue. The value used by the RNG would be the value derived from the +// chip unique value (such as fused) with a dependency on the authorities of the +// code in the TPM boot path. The second would be derived from the chip unique value +// with a dependency on the details of the code in the boot path. That is, the +// first value depends on the various signers of the code and the second depends on +// what was signed. The TPM vendor should not be able to know the first value but +// they are expected to know the second. +EXTERN TPM2B_AUTH g_platformUniqueAuthorities; // Reserved for RNG + +EXTERN TPM2B_AUTH g_platformUniqueDetails; // referenced by VENDOR_PERMANENT + +//********************************************************************************* +//********************************************************************************* +//** Persistent Global Values +//********************************************************************************* +//********************************************************************************* +//*** Description +// The values in this section are global values that are persistent across power +// events. The lifetime of the values determines the structure in which the value +// is placed. + +//********************************************************************************* +//*** PERSISTENT_DATA +//********************************************************************************* +// This structure holds the persistent values that only change as a consequence +// of a specific Protected Capability and are not affected by TPM power events +// (TPM2_Startup() or TPM2_Shutdown(). +typedef struct +{ + //********************************************************************************* + // Hierarchy + //********************************************************************************* + // The values in this section are related to the hierarchies. + + BOOL disableClear; // TRUE if TPM2_Clear() using + // lockoutAuth is disabled + + // Hierarchy authPolicies + TPMI_ALG_HASH ownerAlg; + TPMI_ALG_HASH endorsementAlg; + TPMI_ALG_HASH lockoutAlg; + TPM2B_DIGEST ownerPolicy; + TPM2B_DIGEST endorsementPolicy; + TPM2B_DIGEST lockoutPolicy; + + // Hierarchy authValues + TPM2B_AUTH ownerAuth; + TPM2B_AUTH endorsementAuth; + TPM2B_AUTH lockoutAuth; + + // Primary Seeds + TPM2B_SEED EPSeed; + TPM2B_SEED SPSeed; + TPM2B_SEED PPSeed; + // Note there is a nullSeed in the state_reset memory. + + // Hierarchy proofs + TPM2B_PROOF phProof; + TPM2B_PROOF shProof; + TPM2B_PROOF ehProof; + // Note there is a nullProof in the state_reset memory. + + //********************************************************************************* + // Reset Events + //********************************************************************************* + // A count that increments at each TPM reset and never get reset during the life + // time of TPM. The value of this counter is initialized to 1 during TPM + // manufacture process. It is used to invalidate all saved contexts after a TPM + // Reset. + UINT64 totalResetCount; + + // This counter increments on each TPM Reset. The counter is reset by + // TPM2_Clear(). + UINT32 resetCount; + +//********************************************************************************* +// PCR +//********************************************************************************* +// This structure hold the policies for those PCR that have an update policy. +// This implementation only supports a single group of PCR controlled by +// policy. If more are required, then this structure would be changed to +// an array. +# if defined NUM_POLICY_PCR_GROUP && NUM_POLICY_PCR_GROUP > 0 + PCR_POLICY pcrPolicies; +# endif + + // This structure indicates the allocation of PCR. The structure contains a + // list of PCR allocations for each implemented algorithm. If no PCR are + // allocated for an algorithm, a list entry still exists but the bit map + // will contain no SET bits. + TPML_PCR_SELECTION pcrAllocated; + + //********************************************************************************* + // Physical Presence + //********************************************************************************* + // The PP_LIST type contains a bit map of the commands that require physical + // to be asserted when the authorization is evaluated. Physical presence will be + // checked if the corresponding bit in the array is SET and if the authorization + // handle is TPM_RH_PLATFORM. + // + // These bits may be changed with TPM2_PP_Commands(). + BYTE ppList[(COMMAND_COUNT + 7) / 8]; + + //********************************************************************************* + // Dictionary attack values + //********************************************************************************* + // These values are used for dictionary attack tracking and control. + UINT32 failedTries; // the current count of unexpired + // authorization failures + + UINT32 maxTries; // number of unexpired authorization + // failures before the TPM is in + // lockout + + UINT32 recoveryTime; // time between authorization failures + // before failedTries is decremented + + UINT32 lockoutRecovery; // time that must expire between + // authorization failures associated + // with lockoutAuth + + BOOL lockOutAuthEnabled; // TRUE if use of lockoutAuth is + // allowed + + //***************************************************************************** + // Orderly State + //***************************************************************************** + // The orderly state for current cycle + TPM_SU orderlyState; + + //***************************************************************************** + // Command audit values. + //***************************************************************************** + BYTE auditCommands[((COMMAND_COUNT + 1) + 7) / 8]; + TPMI_ALG_HASH auditHashAlg; + UINT64 auditCounter; + + //***************************************************************************** + // Algorithm selection + //***************************************************************************** + // + // The 'algorithmSet' value indicates the collection of algorithms that are + // currently in used on the TPM. The interpretation of value is vendor dependent. + UINT32 algorithmSet; + + //***************************************************************************** + // Firmware version + //***************************************************************************** + // The firmwareV1 and firmwareV2 values are instanced in TimeStamp.c. This is + // a scheme used in development to allow determination of the linker build time + // of the TPM. An actual implementation would implement these values in a way that + // is consistent with vendor needs. The values are maintained in RAM for simplified + // access with a master version in NV. These values are modified in a + // vendor-specific way. + + // g_firmwareV1 contains the more significant 32-bits of the vendor version number. + // In the reference implementation, if this value is printed as a hex + // value, it will have the format of YYYYMMDD + UINT32 firmwareV1; + + // g_firmwareV1 contains the less significant 32-bits of the vendor version number. + // In the reference implementation, if this value is printed as a hex + // value, it will have the format of 00 HH MM SS + UINT32 firmwareV2; +//***************************************************************************** +// Timer Epoch +//***************************************************************************** +// timeEpoch contains a nonce that has a vendor=specific size (should not be +// less than 8 bytes. This nonce changes when the clock epoch changes. The clock +// epoch changes when there is a discontinuity in the timing of the TPM. +# if !CLOCK_STOPS + CLOCK_NONCE timeEpoch; +# endif + +} PERSISTENT_DATA; + +EXTERN PERSISTENT_DATA gp; + +//********************************************************************************* +//********************************************************************************* +//*** ORDERLY_DATA +//********************************************************************************* +//********************************************************************************* +// The data in this structure is saved to NV on each TPM2_Shutdown(). +typedef struct orderly_data +{ + //***************************************************************************** + // TIME + //***************************************************************************** + + // Clock has two parts. One is the state save part and one is the NV part. The + // state save version is updated on each command. When the clock rolls over, the + // NV version is updated. When the TPM starts up, if the TPM was shutdown in and + // orderly way, then the sClock value is used to initialize the clock. If the + // TPM shutdown was not orderly, then the persistent value is used and the safe + // attribute is clear. + + UINT64 clock; // The orderly version of clock + TPMI_YES_NO clockSafe; // Indicates if the clock value is + // safe. + + // In many implementations, the quality of the entropy available is not that + // high. To compensate, the current value of the drbgState can be saved and + // restored on each power cycle. This prevents the internal state from reverting + // to the initial state on each power cycle and starting with a limited amount + // of entropy. By keeping the old state and adding entropy, the entropy will + // accumulate. + DRBG_STATE drbgState; + +// These values allow the accumulation of self-healing time across orderly shutdown +// of the TPM. +# if ACCUMULATE_SELF_HEAL_TIMER + UINT64 selfHealTimer; // current value of s_selfHealTimer + UINT64 lockoutTimer; // current value of s_lockoutTimer + UINT64 time; // current value of g_time at shutdown +# endif // ACCUMULATE_SELF_HEAL_TIMER + +// These are the ACT Timeout values. They are saved with the other timers +# define DefineActData(N) ACT_STATE ACT_##N; + FOR_EACH_ACT(DefineActData) + + // this is the 'signaled' attribute data for all the ACT. It is done this way so + // that they can be manipulated by ACT number rather than having to access a + // structure. + UINT16 signaledACT; + UINT16 preservedSignaled; +} ORDERLY_DATA; + +# if ACCUMULATE_SELF_HEAL_TIMER +# define s_selfHealTimer go.selfHealTimer +# define s_lockoutTimer go.lockoutTimer +# endif // ACCUMULATE_SELF_HEAL_TIMER + +# define drbgDefault go.drbgState + +EXTERN ORDERLY_DATA go; + +//********************************************************************************* +//********************************************************************************* +//*** STATE_CLEAR_DATA +//********************************************************************************* +//********************************************************************************* +// This structure contains the data that is saved on Shutdown(STATE) +// and restored on Startup(STATE). The values are set to their default +// settings on any Startup(Clear). In other words, the data is only persistent +// across TPM Resume. +// +// If the comments associated with a parameter indicate a default reset value, the +// value is applied on each Startup(CLEAR). + +typedef struct state_clear_data +{ + //***************************************************************************** + // Hierarchy Control + //***************************************************************************** + BOOL shEnable; // default reset is SET + BOOL ehEnable; // default reset is SET + BOOL phEnableNV; // default reset is SET + TPMI_ALG_HASH platformAlg; // default reset is TPM_ALG_NULL + TPM2B_DIGEST platformPolicy; // default reset is an Empty Buffer + TPM2B_AUTH platformAuth; // default reset is an Empty Buffer + + //***************************************************************************** + // PCR + //***************************************************************************** + // The set of PCR to be saved on Shutdown(STATE) + PCR_SAVE pcrSave; // default reset is 0...0 + + // This structure hold the authorization values for those PCR that have an + // update authorization. + // This implementation only supports a single group of PCR controlled by + // authorization. If more are required, then this structure would be changed to + // an array. + PCR_AUTHVALUE pcrAuthValues; + +//***************************************************************************** +// ACT +//***************************************************************************** +# define DefineActPolicySpace(N) TPMT_HA act_##N; + FOR_EACH_ACT(DefineActPolicySpace) + +} STATE_CLEAR_DATA; + +EXTERN STATE_CLEAR_DATA gc; + +//********************************************************************************* +//********************************************************************************* +//*** State Reset Data +//********************************************************************************* +//********************************************************************************* +// This structure contains data is that is saved on Shutdown(STATE) and restored on +// the subsequent Startup(ANY). That is, the data is preserved across TPM Resume +// and TPM Restart. +// +// If a default value is specified in the comments this value is applied on +// TPM Reset. + +typedef struct state_reset_data +{ + //***************************************************************************** + // Hierarchy Control + //***************************************************************************** + TPM2B_PROOF nullProof; // The proof value associated with + // the TPM_RH_NULL hierarchy. The + // default reset value is from the RNG. + + TPM2B_SEED nullSeed; // The seed value for the TPM_RN_NULL + // hierarchy. The default reset value + // is from the RNG. + + //***************************************************************************** + // Context + //***************************************************************************** + // The 'clearCount' counter is incremented each time the TPM successfully executes + // a TPM Resume. The counter is included in each saved context that has 'stClear' + // SET (including descendants of keys that have 'stClear' SET). This prevents these + // objects from being loaded after a TPM Resume. + // If 'clearCount' is at its maximum value when the TPM receives a Shutdown(STATE), + // the TPM will return TPM_RC_RANGE and the TPM will only accept Shutdown(CLEAR). + UINT32 clearCount; // The default reset value is 0. + + UINT64 objectContextID; // This is the context ID for a saved + // object context. The default reset + // value is 0. + CONTEXT_SLOT contextArray[MAX_ACTIVE_SESSIONS]; // This array contains + // contains the values used to track + // the version numbers of saved + // contexts (see + // Session.c in for details). The + // default reset value is {0}. + + CONTEXT_COUNTER contextCounter; // This is the value from which the + // 'contextID' is derived. The + // default reset value is {0}. + + //***************************************************************************** + // Command Audit + //***************************************************************************** + // When an audited command completes, ExecuteCommand() checks the return + // value. If it is TPM_RC_SUCCESS, and the command is an audited command, the + // TPM will extend the cpHash and rpHash for the command to this value. If this + // digest was the Zero Digest before the cpHash was extended, the audit counter + // is incremented. + + TPM2B_DIGEST commandAuditDigest; // This value is set to an Empty Digest + // by TPM2_GetCommandAuditDigest() or a + // TPM Reset. + + //***************************************************************************** + // Boot counter + //***************************************************************************** + + UINT32 restartCount; // This counter counts TPM Restarts. + // The default reset value is 0. + + //********************************************************************************* + // PCR + //********************************************************************************* + // This counter increments whenever the PCR are updated. This counter is preserved + // across TPM Resume even though the PCR are not preserved. This is because + // sessions remain active across TPM Restart and the count value in the session + // is compared to this counter so this counter must have values that are unique + // as long as the sessions are active. + // NOTE: A platform-specific specification may designate that certain PCR changes + // do not increment this counter to increment. + UINT32 pcrCounter; // The default reset value is 0. + +# if ALG_ECC + + //***************************************************************************** + // ECDAA + //***************************************************************************** + UINT64 commitCounter; // This counter increments each time + // TPM2_Commit() returns + // TPM_RC_SUCCESS. The default reset + // value is 0. + + TPM2B_NONCE commitNonce; // This random value is used to compute + // the commit values. The default reset + // value is from the RNG. + + // This implementation relies on the number of bits in g_commitArray being a + // power of 2 (8, 16, 32, 64, etc.) and no greater than 64K. + BYTE commitArray[16]; // The default reset value is {0}. + +# endif // ALG_ECC +} STATE_RESET_DATA; + +EXTERN STATE_RESET_DATA gr; + +//** NV Layout +// The NV data organization is +// 1) a PERSISTENT_DATA structure +// 2) a STATE_RESET_DATA structure +// 3) a STATE_CLEAR_DATA structure +// 4) an ORDERLY_DATA structure +// 5) the user defined NV index space +# define NV_PERSISTENT_DATA (0) +# define NV_STATE_RESET_DATA (NV_PERSISTENT_DATA + sizeof(PERSISTENT_DATA)) +# define NV_STATE_CLEAR_DATA (NV_STATE_RESET_DATA + sizeof(STATE_RESET_DATA)) +# define NV_ORDERLY_DATA (NV_STATE_CLEAR_DATA + sizeof(STATE_CLEAR_DATA)) +# define NV_INDEX_RAM_DATA (NV_ORDERLY_DATA + sizeof(ORDERLY_DATA)) +# define NV_USER_DYNAMIC (NV_INDEX_RAM_DATA + sizeof(s_indexOrderlyRam)) +# define NV_USER_DYNAMIC_END NV_MEMORY_SIZE + +//** Global Macro Definitions +// The NV_READ_PERSISTENT and NV_WRITE_PERSISTENT macros are used to access members +// of the PERSISTENT_DATA structure in NV. +# define NV_READ_PERSISTENT(to, from) \ + NvRead(&to, offsetof(PERSISTENT_DATA, from), sizeof(to)) + +# define NV_WRITE_PERSISTENT(to, from) \ + NvWrite(offsetof(PERSISTENT_DATA, to), sizeof(gp.to), &from) + +# define CLEAR_PERSISTENT(item) \ + NvClearPersistent(offsetof(PERSISTENT_DATA, item), sizeof(gp.item)) + +# define NV_SYNC_PERSISTENT(item) NV_WRITE_PERSISTENT(item, gp.item) + +// At the start of command processing, the index of the command is determined. This +// index value is used to access the various data tables that contain per-command +// information. There are multiple options for how the per-command tables can be +// implemented. This is resolved in GetClosestCommandIndex(). +typedef UINT16 COMMAND_INDEX; +# define UNIMPLEMENTED_COMMAND_INDEX ((COMMAND_INDEX)(~0)) + +typedef struct _COMMAND_FLAGS_ +{ + unsigned trialPolicy : 1; //1) If SET, one of the handles references a + // trial policy and authorization may be + // skipped. This is only allowed for a policy + // command. +} COMMAND_FLAGS; + +// This structure is used to avoid having to manage a large number of +// parameters being passed through various levels of the command input processing. +// + +// The following macros are used to define the space for the CP and RP hashes. Space, +// is provided for each implemented hash algorithm because it is not known what the +// caller may use. +# define CP_HASH(HASH, Hash) TPM2B_##HASH##_DIGEST Hash##CpHash; +# define RP_HASH(HASH, Hash) TPM2B_##HASH##_DIGEST Hash##RpHash; + +typedef struct COMMAND +{ + TPM_ST tag; // the parsed command tag + TPM_CC code; // the parsed command code + COMMAND_INDEX index; // the computed command index + UINT32 handleNum; // the number of entity handles in the + // handle area of the command + TPM_HANDLE handles[MAX_HANDLE_NUM]; // the parsed handle values + UINT32 sessionNum; // the number of sessions found + INT32 parameterSize; // starts out with the parsed command size + // and is reduced and values are + // unmarshaled. Just before calling the + // command actions, this should be zero. + // After the command actions, this number + // should grow as values are marshaled + // in to the response buffer. + INT32 authSize; // this is initialized with the parsed size + // of authorizationSize field and should + // be zero when the authorizations are + // parsed. + BYTE* parameterBuffer; // input to ExecuteCommand + BYTE* responseBuffer; // input to ExecuteCommand + FOR_EACH_HASH(CP_HASH) // space for the CP hashes + FOR_EACH_HASH(RP_HASH) // space for the RP hashes +} COMMAND; + +// Global string constants for consistency in KDF function calls. +// These string constants are shared across functions to make sure that they +// are all using consistent string values. + +# define STRING_INITIALIZER(value) \ + { \ + { \ + sizeof(value), \ + { \ + value \ + } \ + } \ + } +# define TPM2B_STRING(name, value) \ + typedef union name##_ \ + { \ + struct \ + { \ + UINT16 size; \ + BYTE buffer[sizeof(value)]; \ + } t; \ + TPM2B b; \ + } TPM2B_##name##_; \ + EXTERN const TPM2B_##name##_ name##_ INITIALIZER(STRING_INITIALIZER(value)); \ + EXTERN const TPM2B* name INITIALIZER(&name##_.b) + +TPM2B_STRING(PRIMARY_OBJECT_CREATION, "Primary Object Creation"); +TPM2B_STRING(CFB_KEY, "CFB"); +TPM2B_STRING(CONTEXT_KEY, "CONTEXT"); +TPM2B_STRING(INTEGRITY_KEY, "INTEGRITY"); +TPM2B_STRING(SECRET_KEY, "SECRET"); +TPM2B_STRING(SESSION_KEY, "ATH"); +TPM2B_STRING(STORAGE_KEY, "STORAGE"); +TPM2B_STRING(XOR_KEY, "XOR"); +TPM2B_STRING(COMMIT_STRING, "ECDAA Commit"); +TPM2B_STRING(DUPLICATE_STRING, "DUPLICATE"); +TPM2B_STRING(IDENTITY_STRING, "IDENTITY"); +TPM2B_STRING(OBFUSCATE_STRING, "OBFUSCATE"); +# if SELF_TEST +TPM2B_STRING(OAEP_TEST_STRING, "OAEP Test Value"); +# endif // SELF_TEST + +//***************************************************************************** +//** From CryptTest.c +//***************************************************************************** +// This structure contains the self-test state values for the cryptographic modules. +EXTERN CRYPTO_SELF_TEST_STATE g_cryptoSelfTestState; + +//***************************************************************************** +//** From Manufacture.c +//***************************************************************************** +EXTERN BOOL g_manufactured INITIALIZER(FALSE); + +// This value indicates if a TPM2_Startup commands has been +// receive since the power on event. This flag is maintained in power +// simulation module because this is the only place that may reliably set this +// flag to FALSE. +EXTERN BOOL g_initialized; + +//** Private data + +//***************************************************************************** +//*** From SessionProcess.c +//***************************************************************************** +# if defined SESSION_PROCESS_C || defined GLOBAL_C || defined MANUFACTURE_C +// The following arrays are used to save command sessions information so that the +// command handle/session buffer does not have to be preserved for the duration of +// the command. These arrays are indexed by the session index in accordance with +// the order of sessions in the session area of the command. +// +// Array of the authorization session handles +EXTERN TPM_HANDLE s_sessionHandles[MAX_SESSION_NUM]; + +// Array of authorization session attributes +EXTERN TPMA_SESSION s_attributes[MAX_SESSION_NUM]; + +// Array of handles authorized by the corresponding authorization sessions; +// and if none, then TPM_RH_UNASSIGNED value is used +EXTERN TPM_HANDLE s_associatedHandles[MAX_SESSION_NUM]; + +// Array of nonces provided by the caller for the corresponding sessions +EXTERN TPM2B_NONCE s_nonceCaller[MAX_SESSION_NUM]; + +// Array of authorization values (HMAC's or passwords) for the corresponding +// sessions +EXTERN TPM2B_AUTH s_inputAuthValues[MAX_SESSION_NUM]; + +// Array of pointers to the SESSION structures for the sessions in a command +EXTERN SESSION* s_usedSessions[MAX_SESSION_NUM]; + +// Special value to indicate an undefined session index +# define UNDEFINED_INDEX (0xFFFF) + +// Index of the session used for encryption of a response parameter +EXTERN UINT32 s_encryptSessionIndex; + +// Index of the session used for decryption of a command parameter +EXTERN UINT32 s_decryptSessionIndex; + +// Index of a session used for audit +EXTERN UINT32 s_auditSessionIndex; + +// The cpHash for command audit +# if CC_GetCommandAuditDigest +EXTERN TPM2B_DIGEST s_cpHashForCommandAudit; +# endif + +// Flag indicating if NV update is pending for the lockOutAuthEnabled or +// failedTries DA parameter +EXTERN BOOL s_DAPendingOnNV; + +# endif // SESSION_PROCESS_C + +//***************************************************************************** +//*** From DA.c +//***************************************************************************** +# if defined DA_C || defined GLOBAL_C || defined MANUFACTURE_C +// This variable holds the accumulated time since the last time +// that 'failedTries' was decremented. This value is in millisecond. +# if !ACCUMULATE_SELF_HEAL_TIMER +EXTERN UINT64 s_selfHealTimer; + +// This variable holds the accumulated time that the lockoutAuth has been +// blocked. +EXTERN UINT64 s_lockoutTimer; +# endif // ACCUMULATE_SELF_HEAL_TIMER + +# endif // DA_C + +//***************************************************************************** +//*** From NV.c +//***************************************************************************** +# if defined NV_C || defined GLOBAL_C +// This marks the end of the NV area. This is a run-time variable as it might +// not be compile-time constant. +EXTERN NV_REF s_evictNvEnd; + +// This space is used to hold the index data for an orderly Index. It also contains +// the attributes for the index. +EXTERN BYTE s_indexOrderlyRam[RAM_INDEX_SPACE]; // The orderly NV Index data + +// This value contains the current max counter value. It is written to the end of +// allocatable NV space each time an index is deleted or added. This value is +// initialized on Startup. The indices are searched and the maximum of all the +// current counter indices and this value is the initial value for this. +EXTERN UINT64 s_maxCounter; + +// This is space used for the NV Index cache. As with a persistent object, the +// contents of a referenced index are copied into the cache so that the +// NV Index memory scanning and data copying can be reduced. +// Only code that operates on NV Index data should use this cache directly. When +// that action code runs, s_lastNvIndex will contain the index header information. +// It will have been loaded when the handles were verified. +// NOTE: An NV index handle can appear in many commands that do not operate on the +// NV data (e.g. TPM2_StartAuthSession). However, only one NV Index at a time is +// ever directly referenced by any command. If that changes, then the NV Index +// caching needs to be changed to accommodate that. Currently, the code will verify +// that only one NV Index is referenced by the handles of the command. +EXTERN NV_INDEX s_cachedNvIndex; +EXTERN NV_REF s_cachedNvRef; +EXTERN BYTE* s_cachedNvRamRef; + +// Initial NV Index/evict object iterator value +# define NV_REF_INIT (NV_REF)0xFFFFFFFF + +# endif + +//***************************************************************************** +//*** From Object.c +//***************************************************************************** +# if defined OBJECT_C || defined GLOBAL_C +// This type is the container for an object. + +EXTERN OBJECT s_objects[MAX_LOADED_OBJECTS]; + +# endif // OBJECT_C + +//***************************************************************************** +//*** From PCR.c +//***************************************************************************** +# if defined PCR_C || defined GLOBAL_C +// The following macro is used to define the per-implemented-hash space. This +// implementation reserves space for all implemented hashes. +# define PCR_ALL_HASH(HASH, Hash) BYTE Hash##Pcr[HASH##_DIGEST_SIZE]; + +typedef struct +{ + FOR_EACH_HASH(PCR_ALL_HASH) +} PCR; + +typedef struct +{ + unsigned int stateSave : 1; // if the PCR value should be + // saved in state save + unsigned int resetLocality : 5; // The locality that the PCR + // can be reset + unsigned int extendLocality : 5; // The locality that the PCR + // can be extend +} PCR_Attributes; + +EXTERN PCR s_pcrs[IMPLEMENTATION_PCR]; + +# endif // PCR_C + +//***************************************************************************** +//*** From Session.c +//***************************************************************************** +# if defined SESSION_C || defined GLOBAL_C +// Container for HMAC or policy session tracking information +typedef struct +{ + BOOL occupied; + SESSION session; // session structure +} SESSION_SLOT; + +EXTERN SESSION_SLOT s_sessions[MAX_LOADED_SESSIONS]; + +// The index in contextArray that has the value of the oldest saved session +// context. When no context is saved, this will have a value that is greater +// than or equal to MAX_ACTIVE_SESSIONS. +EXTERN UINT32 s_oldestSavedSession; + +// The number of available session slot openings. When this is 1, +// a session can't be created or loaded if the GAP is maxed out. +// The exception is that the oldest saved session context can always +// be loaded (assuming that there is a space in memory to put it) +EXTERN int s_freeSessionSlots; + +# endif // SESSION_C + +//***************************************************************************** +//*** From IoBuffers.c +//***************************************************************************** +# if defined IO_BUFFER_C || defined GLOBAL_C +// Each command function is allowed a structure for the inputs to the function and +// a structure for the outputs. The command dispatch code unmarshals the input butter +// to the command action input structure starting at the first byte of +// s_actionIoBuffer. The value of s_actionIoAllocation is the number of UINT64 values +// allocated. It is used to set the pointer for the response structure. The command +// dispatch code will marshal the response values into the final output buffer. +EXTERN UINT64 s_actionIoBuffer[768]; // action I/O buffer +EXTERN UINT32 s_actionIoAllocation; // number of UIN64 allocated for the + // action input structure +# endif // IO_BUFFER_C + +//***************************************************************************** +//*** From TPMFail.c +//***************************************************************************** +// This value holds the address of the string containing the name of the function +// in which the failure occurred. This address value is not useful for anything +// other than helping the vendor to know in which file the failure occurred. +EXTERN BOOL g_inFailureMode; // Indicates that the TPM is in failure mode +# if SIMULATION +EXTERN BOOL g_forceFailureMode; // flag to force failure mode during test +# endif + +typedef void(FailFunction)(const char* function, int line, int code); + +# if defined TPM_FAIL_C || defined GLOBAL_C +EXTERN UINT32 s_failFunction; +EXTERN UINT32 s_failLine; // the line in the file at which + // the error was signaled +EXTERN UINT32 s_failCode; // the error code used + +EXTERN FailFunction* LibFailCallback; + +# endif // TPM_FAIL_C + +//***************************************************************************** +//*** From ACT_spt.c +//***************************************************************************** +// This value is used to indicate if an ACT has been updated since the last +// TPM2_Startup() (one bit for each ACT). If the ACT is not updated +// (TPM2_ACT_SetTimeout()) after a startup, then on each TPM2_Shutdown() the TPM will +// save 1/2 of the current timer value. This prevents an attack on the ACT by saving +// the counter and then running for a long period of time before doing a TPM Restart. +// A quick TPM2_Shutdown() after each +EXTERN UINT16 s_ActUpdated; + +//***************************************************************************** +//*** From CommandCodeAttributes.c +//***************************************************************************** +// This array is instanced in CommandCodeAttributes.c when it includes +// CommandCodeAttributes.h. Don't change the extern to EXTERN. +extern const TPMA_CC s_ccAttr[]; +extern const COMMAND_ATTRIBUTES s_commandAttributes[]; + +#endif // GLOBAL_H diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/GpMacros.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/GpMacros.h new file mode 100644 index 0000000..72ccac1 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/GpMacros.h @@ -0,0 +1,398 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// This file is a collection of miscellaneous macros. + +#ifndef GP_MACROS_H +#define GP_MACROS_H + +#ifndef NULL +# define NULL 0 +#endif + +#include "swap.h" +#include "VendorString.h" + +//** For Self-test +// These macros are used in CryptUtil to invoke the incremental self test. +#if SELF_TEST +# define TEST(alg) \ + do \ + { \ + if(TEST_BIT(alg, g_toTest)) \ + CryptTestAlgorithm(alg, NULL); \ + } while(0) + +// Use of TPM_ALG_NULL is reserved for RSAEP/RSADP testing. If someone is wanting +// to test a hash with that value, don't do it. +# define TEST_HASH(alg) \ + do \ + { \ + if(TEST_BIT(alg, g_toTest) && (alg != TPM_ALG_NULL)) \ + CryptTestAlgorithm(alg, NULL); \ + } while(0) +#else +# define TEST(alg) \ + do \ + { \ + } while(0) +# define TEST_HASH(alg) \ + do \ + { \ + } while(0) +#endif // SELF_TEST + +//** For Failures +#if defined _POSIX_ +# define FUNCTION_NAME 0 +#else +# define FUNCTION_NAME __FUNCTION__ +#endif + +#if !FAIL_TRACE +# define FAIL(errorCode) (TpmFail(errorCode)) +# define LOG_FAILURE(errorCode) (TpmLogFailure(errorCode)) +#else +# define FAIL(errorCode) TpmFail(FUNCTION_NAME, __LINE__, errorCode) +# define LOG_FAILURE(errorCode) TpmLogFailure(FUNCTION_NAME, __LINE__, errorCode) +#endif + +// If implementation is using longjmp, then the call to TpmFail() does not return +// and the compiler will complain about unreachable code that comes after. To allow +// for not having longjmp, TpmFail() will return and the subsequent code will be +// executed. This macro accounts for the difference. +#ifndef NO_LONGJMP +# define FAIL_RETURN(returnCode) \ + do \ + { \ + } while(0) +# define TPM_FAIL_RETURN NORETURN void +#else +# define FAIL_RETURN(returnCode) \ + do \ + { \ + return (returnCode); \ + } while(0) +# define TPM_FAIL_RETURN void +#endif + +// This macro tests that a condition is TRUE and puts the TPM into failure mode +// if it is not. If longjmp is being used, then the FAIL(FATAL_ERROR_) macro makes +// a call from which there is no return. Otherwise, it returns and the function +// will exit with the appropriate return code. +#define REQUIRE(condition, errorCode, returnCode) \ + do \ + { \ + if(!!(condition)) \ + { \ + FAIL(FATAL_ERROR_##errorCode); \ + FAIL_RETURN(returnCode); \ + } \ + } while(0) + +#define PARAMETER_CHECK(condition, returnCode) \ + REQUIRE((condition), PARAMETER, returnCode) + +#if(defined EMPTY_ASSERT) && (EMPTY_ASSERT != NO) +# define pAssert(a) \ + do \ + { \ + } while(0) +#else +# define pAssert(a) \ + do \ + { \ + if(!(a)) \ + FAIL(FATAL_ERROR_PARAMETER); \ + } while(0) +#endif + +//** Derived from Vendor-specific values +// Values derived from vendor specific settings in TpmProfile.h +#define PCR_SELECT_MIN ((PLATFORM_PCR + 7) / 8) +#define PCR_SELECT_MAX ((IMPLEMENTATION_PCR + 7) / 8) +#define MAX_ORDERLY_COUNT ((1 << ORDERLY_BITS) - 1) +#define RSA_MAX_PRIME (MAX_RSA_KEY_BYTES / 2) +#define RSA_PRIVATE_SIZE (RSA_MAX_PRIME * 5) + +//** Compile-time Checks +// In some cases, the relationship between two values may be dependent +// on things that change based on various selections like the chosen cryptographic +// libraries. It is possible that these selections will result in incompatible +// settings. These are often detectable by the compiler but it is not always +// possible to do the check in the preprocessor code. For example, when the +// check requires use of "sizeof" then the preprocessor can't do the comparison. +// For these cases, we include a special macro that, depending on the compiler +// will generate a warning to indicate if the check always passes or always fails +// because it involves fixed constants. To run these checks, define COMPILER_CHECKS +// in TpmBuildSwitches.h +#if COMPILER_CHECKS +# define cAssert pAssert +#else +# define cAssert(value) +#endif + +// This is used commonly in the "Crypt" code as a way to keep listings from +// getting too long. This is not to save paper but to allow one to see more +// useful stuff on the screen at any given time. +#define ERROR_RETURN(returnCode) \ + do \ + { \ + retVal = (returnCode); \ + goto Exit; \ + } while(0) + +#ifndef MAX +# define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif +#ifndef MIN +# define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif +#ifndef IsOdd +# define IsOdd(a) (((a)&1) != 0) +#endif + +#ifndef BITS_TO_BYTES +# define BITS_TO_BYTES(bits) (((bits) + 7) >> 3) +#endif + +// These are defined for use when the size of the vector being checked is known +// at compile time. +#define TEST_BIT(bit, vector) TestBit((bit), (BYTE*)&(vector), sizeof(vector)) +#define SET_BIT(bit, vector) SetBit((bit), (BYTE*)&(vector), sizeof(vector)) +#define CLEAR_BIT(bit, vector) ClearBit((bit), (BYTE*)&(vector), sizeof(vector)) + +// The following definitions are used if they have not already been defined. The +// defaults for these settings are compatible with ISO/IEC 9899:2011 (E) +#ifndef LIB_EXPORT +# define LIB_EXPORT +# define LIB_IMPORT +#endif +#ifndef NORETURN +# define NORETURN _Noreturn +#endif +#ifndef NOT_REFERENCED +# define NOT_REFERENCED(x = x) ((void)(x)) +#endif + +#define STD_RESPONSE_HEADER (sizeof(TPM_ST) + sizeof(UINT32) + sizeof(TPM_RC)) + +#define JOIN(x, y) x##y +#define JOIN3(x, y, z) x##y##z +#define CONCAT(x, y) JOIN(x, y) +#define CONCAT3(x, y, z) JOIN3(x, y, z) + +// If CONTEXT_INTEGRITY_HASH_ALG is defined, then the vendor is using the old style +// table. Otherwise, pick the "strongest" implemented hash algorithm as the context +// hash. +#ifndef CONTEXT_HASH_ALGORITHM +# if defined ALG_SHA3_512 && ALG_SHA3_512 == YES +# define CONTEXT_HASH_ALGORITHM SHA3_512 +# elif defined ALG_SHA512 && ALG_SHA512 == YES +# define CONTEXT_HASH_ALGORITHM SHA512 +# elif defined ALG_SHA3_384 && ALG_SHA3_384 == YES +# define CONTEXT_HASH_ALGORITHM SHA3_384 +# elif defined ALG_SHA384 && ALG_SHA384 == YES +# define CONTEXT_HASH_ALGORITHM SHA384 +# elif defined ALG_SHA3_256 && ALG_SHA3_256 == YES +# define CONTEXT_HASH_ALGORITHM SHA3_256 +# elif defined ALG_SHA256 && ALG_SHA256 == YES +# define CONTEXT_HASH_ALGORITHM SHA256 +# elif defined ALG_SM3_256 && ALG_SM3_256 == YES +# define CONTEXT_HASH_ALGORITHM SM3_256 +# elif defined ALG_SHA1 && ALG_SHA1 == YES +# define CONTEXT_HASH_ALGORITHM SHA1 +# endif +# define CONTEXT_INTEGRITY_HASH_ALG CONCAT(TPM_ALG_, CONTEXT_HASH_ALGORITHM) +#endif + +#ifndef CONTEXT_INTEGRITY_HASH_SIZE +# define CONTEXT_INTEGRITY_HASH_SIZE CONCAT(CONTEXT_HASH_ALGORITHM, _DIGEST_SIZE) +#endif +#if ALG_RSA +# define RSA_SECURITY_STRENGTH \ + (MAX_RSA_KEY_BITS >= 15360 \ + ? 256 \ + : (MAX_RSA_KEY_BITS >= 7680 \ + ? 192 \ + : (MAX_RSA_KEY_BITS >= 3072 \ + ? 128 \ + : (MAX_RSA_KEY_BITS >= 2048 \ + ? 112 \ + : (MAX_RSA_KEY_BITS >= 1024 ? 80 : 0))))) +#else +# define RSA_SECURITY_STRENGTH 0 +#endif // ALG_RSA + +#if ALG_ECC +# define ECC_SECURITY_STRENGTH \ + (MAX_ECC_KEY_BITS >= 521 \ + ? 256 \ + : (MAX_ECC_KEY_BITS >= 384 ? 192 : (MAX_ECC_KEY_BITS >= 256 ? 128 : 0))) +#else +# define ECC_SECURITY_STRENGTH 0 +#endif // ALG_ECC + +#define MAX_ASYM_SECURITY_STRENGTH MAX(RSA_SECURITY_STRENGTH, ECC_SECURITY_STRENGTH) + +#define MAX_HASH_SECURITY_STRENGTH ((CONTEXT_INTEGRITY_HASH_SIZE * 8) / 2) + +// Unless some algorithm is broken... +#define MAX_SYM_SECURITY_STRENGTH MAX_SYM_KEY_BITS + +#define MAX_SECURITY_STRENGTH_BITS \ + MAX(MAX_ASYM_SECURITY_STRENGTH, \ + MAX(MAX_SYM_SECURITY_STRENGTH, MAX_HASH_SECURITY_STRENGTH)) + +// This is the size that was used before the 1.38 errata requiring that P1.14.4 be +// followed +#define PROOF_SIZE CONTEXT_INTEGRITY_HASH_SIZE + +// As required by P1.14.4 +#define COMPLIANT_PROOF_SIZE \ + (MAX(CONTEXT_INTEGRITY_HASH_SIZE, (2 * MAX_SYM_KEY_BYTES))) + +// As required by P1.14.3.1 +#define COMPLIANT_PRIMARY_SEED_SIZE BITS_TO_BYTES(MAX_SECURITY_STRENGTH_BITS * 2) + +// This is the pre-errata version +#ifndef PRIMARY_SEED_SIZE +# define PRIMARY_SEED_SIZE PROOF_SIZE +#endif + +#if USE_SPEC_COMPLIANT_PROOFS +# undef PROOF_SIZE +# define PROOF_SIZE COMPLIANT_PROOF_SIZE +# undef PRIMARY_SEED_SIZE +# define PRIMARY_SEED_SIZE COMPLIANT_PRIMARY_SEED_SIZE +#endif // USE_SPEC_COMPLIANT_PROOFS + +#if !SKIP_PROOF_ERRORS +# if PROOF_SIZE < COMPLIANT_PROOF_SIZE +# error "PROOF_SIZE is not compliant with TPM specification" +# endif +# if PRIMARY_SEED_SIZE < COMPLIANT_PRIMARY_SEED_SIZE +# error Non-compliant PRIMARY_SEED_SIZE +# endif +#endif // !SKIP_PROOF_ERRORS + +// If CONTEXT_ENCRYPT_ALG is defined, then the vendor is using the old style table +#if defined CONTEXT_ENCRYPT_ALG +# undef CONTEXT_ENCRYPT_ALGORITHM +# if CONTEXT_ENCRYPT_ALG == ALG_AES_VALUE +# define CONTEXT_ENCRYPT_ALGORITHM AES +# elif CONTEXT_ENCRYPT_ALG == ALG_SM4_VALUE +# define CONTEXT_ENCRYPT_ALGORITHM SM4 +# elif CONTEXT_ENCRYPT_ALG == ALG_CAMELLIA_VALUE +# define CONTEXT_ENCRYPT_ALGORITHM CAMELLIA +# elif CONTEXT_ENCRYPT_ALG == ALG_TDES_VALUE +# error Are you kidding? +# else +# error Unknown value for CONTEXT_ENCRYPT_ALG +# endif // CONTEXT_ENCRYPT_ALG == ALG_AES_VALUE +#else +# define CONTEXT_ENCRYPT_ALG CONCAT3(ALG_, CONTEXT_ENCRYPT_ALGORITHM, _VALUE) +#endif // CONTEXT_ENCRYPT_ALG +#define CONTEXT_ENCRYPT_KEY_BITS CONCAT(CONTEXT_ENCRYPT_ALGORITHM, _MAX_KEY_SIZE_BITS) +#define CONTEXT_ENCRYPT_KEY_BYTES ((CONTEXT_ENCRYPT_KEY_BITS + 7) / 8) + +// This is updated to follow the requirement of P2 that the label not be larger +// than 32 bytes. +#ifndef LABEL_MAX_BUFFER +# define LABEL_MAX_BUFFER MIN(32, MAX(MAX_ECC_KEY_BYTES, MAX_DIGEST_SIZE)) +#endif + +// This bit is used to indicate that an authorization ticket expires on TPM Reset +// and TPM Restart. It is added to the timeout value returned by TPM2_PoliySigned() +// and TPM2_PolicySecret() and used by TPM2_PolicyTicket(). The timeout value is +// relative to Time (g_time). Time is reset whenever the TPM loses power and cannot +// be moved forward by the user (as can Clock). 'g_time' is a 64-bit value expressing +// time in ms. Stealing the MSb for a flag means that the TPM needs to be reset +// at least once every 292,471,208 years rather than once every 584,942,417 years. +#define EXPIRATION_BIT ((UINT64)1 << 63) + +// Check for consistency of the bit ordering of bit fields +#if BIG_ENDIAN_TPM && MOST_SIGNIFICANT_BIT_0 && USE_BIT_FIELD_STRUCTURES +# error "Settings not consistent" +#endif + +// These macros are used to handle the variation in handling of bit fields. If +#if USE_BIT_FIELD_STRUCTURES // The default, old version, with bit fields +# define IS_ATTRIBUTE(a, type, b) ((a.b) != 0) +# define SET_ATTRIBUTE(a, type, b) (a.b = SET) +# define CLEAR_ATTRIBUTE(a, type, b) (a.b = CLEAR) +# define GET_ATTRIBUTE(a, type, b) (a.b) +# define TPMA_ZERO_INITIALIZER() \ + { \ + 0 \ + } +#else +# define IS_ATTRIBUTE(a, type, b) ((a & type##_##b) != 0) +# define SET_ATTRIBUTE(a, type, b) (a |= type##_##b) +# define CLEAR_ATTRIBUTE(a, type, b) (a &= ~type##_##b) +# define GET_ATTRIBUTE(a, type, b) (type)((a & type##_##b) >> type##_##b##_SHIFT) +# define TPMA_ZERO_INITIALIZER() (0) +#endif + +#define VERIFY(_X) \ + do \ + { \ + if(!(_X)) \ + goto Error; \ + } while(0) + +// These macros determine if the values in this file are referenced or instanced. +// Global.c defines GLOBAL_C so all the values in this file will be instanced in +// Global.obj. For all other files that include this file, the values will simply +// be external references. For constants, there can be an initializer. +#ifdef GLOBAL_C +# define EXTERN +# define INITIALIZER(_value_) = _value_ +#else +# define EXTERN extern +# define INITIALIZER(_value_) +#endif + +// This macro will create an OID. All OIDs are in DER form with a first octet of +// 0x06 indicating an OID fallowed by an octet indicating the number of octets in the +// rest of the OID. This allows a user of this OID to know how much/little to copy. +#define MAKE_OID(NAME) EXTERN const BYTE OID##NAME[] INITIALIZER({OID##NAME##_VALUE}) + +// This definition is moved from TpmProfile.h because it is not actually vendor- +// specific. It has to be the same size as the 'sequence' parameter of a TPMS_CONTEXT +// and that is a UINT64. So, this is an invariant value +#define CONTEXT_COUNTER UINT64 + +#endif // GP_MACROS_H diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/HandleProcess.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/HandleProcess.h new file mode 100644 index 0000000..dc9e009 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/HandleProcess.h @@ -0,0 +1,1168 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmDispatch; Version 4.0 July 8,2017 + * Date: Feb 28, 2020 Time: 03:04:48PM + */ + +#if CC_Startup +case TPM_CC_Startup: + break; +#endif // CC_Startup +#if CC_Shutdown +case TPM_CC_Shutdown: + break; +#endif // CC_Shutdown +#if CC_SelfTest +case TPM_CC_SelfTest: + break; +#endif // CC_SelfTest +#if CC_IncrementalSelfTest +case TPM_CC_IncrementalSelfTest: + break; +#endif // CC_IncrementalSelfTest +#if CC_GetTestResult +case TPM_CC_GetTestResult: + break; +#endif // CC_GetTestResult +#if CC_StartAuthSession +case TPM_CC_StartAuthSession: + *handleCount = 2; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, TRUE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + result = TPMI_DH_ENTITY_Unmarshal( + &handles[1], handleBufferStart, bufferRemainingSize, TRUE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_2; + break; +#endif // CC_StartAuthSession +#if CC_PolicyRestart +case TPM_CC_PolicyRestart: + *handleCount = 1; + result = + TPMI_SH_POLICY_Unmarshal(&handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_PolicyRestart +#if CC_Create +case TPM_CC_Create: + *handleCount = 1; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_Create +#if CC_Load +case TPM_CC_Load: + *handleCount = 1; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_Load +#if CC_LoadExternal +case TPM_CC_LoadExternal: + break; +#endif // CC_LoadExternal +#if CC_ReadPublic +case TPM_CC_ReadPublic: + *handleCount = 1; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_ReadPublic +#if CC_ActivateCredential +case TPM_CC_ActivateCredential: + *handleCount = 2; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[1], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_2; + break; +#endif // CC_ActivateCredential +#if CC_MakeCredential +case TPM_CC_MakeCredential: + *handleCount = 1; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_MakeCredential +#if CC_Unseal +case TPM_CC_Unseal: + *handleCount = 1; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_Unseal +#if CC_ObjectChangeAuth +case TPM_CC_ObjectChangeAuth: + *handleCount = 2; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[1], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_2; + break; +#endif // CC_ObjectChangeAuth +#if CC_CreateLoaded +case TPM_CC_CreateLoaded: + *handleCount = 1; + result = TPMI_DH_PARENT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, TRUE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_CreateLoaded +#if CC_Duplicate +case TPM_CC_Duplicate: + *handleCount = 2; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[1], handleBufferStart, bufferRemainingSize, TRUE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_2; + break; +#endif // CC_Duplicate +#if CC_Rewrap +case TPM_CC_Rewrap: + *handleCount = 2; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, TRUE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[1], handleBufferStart, bufferRemainingSize, TRUE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_2; + break; +#endif // CC_Rewrap +#if CC_Import +case TPM_CC_Import: + *handleCount = 1; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_Import +#if CC_RSA_Encrypt +case TPM_CC_RSA_Encrypt: + *handleCount = 1; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_RSA_Encrypt +#if CC_RSA_Decrypt +case TPM_CC_RSA_Decrypt: + *handleCount = 1; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_RSA_Decrypt +#if CC_ECDH_KeyGen +case TPM_CC_ECDH_KeyGen: + *handleCount = 1; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_ECDH_KeyGen +#if CC_ECDH_ZGen +case TPM_CC_ECDH_ZGen: + *handleCount = 1; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_ECDH_ZGen +#if CC_ECC_Parameters +case TPM_CC_ECC_Parameters: + break; +#endif // CC_ECC_Parameters +#if CC_ZGen_2Phase +case TPM_CC_ZGen_2Phase: + *handleCount = 1; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_ZGen_2Phase +#if CC_ECC_Encrypt +case TPM_CC_ECC_Encrypt: + *handleCount = 1; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_ECC_Encrypt +#if CC_ECC_Decrypt +case TPM_CC_ECC_Decrypt: + *handleCount = 1; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_ECC_Decrypt +#if CC_EncryptDecrypt +case TPM_CC_EncryptDecrypt: + *handleCount = 1; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_EncryptDecrypt +#if CC_EncryptDecrypt2 +case TPM_CC_EncryptDecrypt2: + *handleCount = 1; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_EncryptDecrypt2 +#if CC_Hash +case TPM_CC_Hash: + break; +#endif // CC_Hash +#if CC_HMAC +case TPM_CC_HMAC: + *handleCount = 1; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_HMAC +#if CC_MAC +case TPM_CC_MAC: + *handleCount = 1; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_MAC +#if CC_GetRandom +case TPM_CC_GetRandom: + break; +#endif // CC_GetRandom +#if CC_StirRandom +case TPM_CC_StirRandom: + break; +#endif // CC_StirRandom +#if CC_HMAC_Start +case TPM_CC_HMAC_Start: + *handleCount = 1; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_HMAC_Start +#if CC_MAC_Start +case TPM_CC_MAC_Start: + *handleCount = 1; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_MAC_Start +#if CC_HashSequenceStart +case TPM_CC_HashSequenceStart: + break; +#endif // CC_HashSequenceStart +#if CC_SequenceUpdate +case TPM_CC_SequenceUpdate: + *handleCount = 1; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_SequenceUpdate +#if CC_SequenceComplete +case TPM_CC_SequenceComplete: + *handleCount = 1; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_SequenceComplete +#if CC_EventSequenceComplete +case TPM_CC_EventSequenceComplete: + *handleCount = 2; + result = TPMI_DH_PCR_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, TRUE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[1], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_2; + break; +#endif // CC_EventSequenceComplete +#if CC_Certify +case TPM_CC_Certify: + *handleCount = 2; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[1], handleBufferStart, bufferRemainingSize, TRUE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_2; + break; +#endif // CC_Certify +#if CC_CertifyCreation +case TPM_CC_CertifyCreation: + *handleCount = 2; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, TRUE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[1], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_2; + break; +#endif // CC_CertifyCreation +#if CC_Quote +case TPM_CC_Quote: + *handleCount = 1; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, TRUE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_Quote +#if CC_GetSessionAuditDigest +case TPM_CC_GetSessionAuditDigest: + *handleCount = 3; + result = TPMI_RH_ENDORSEMENT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[1], handleBufferStart, bufferRemainingSize, TRUE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_2; + result = + TPMI_SH_HMAC_Unmarshal(&handles[2], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_3; + break; +#endif // CC_GetSessionAuditDigest +#if CC_GetCommandAuditDigest +case TPM_CC_GetCommandAuditDigest: + *handleCount = 2; + result = TPMI_RH_ENDORSEMENT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[1], handleBufferStart, bufferRemainingSize, TRUE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_2; + break; +#endif // CC_GetCommandAuditDigest +#if CC_GetTime +case TPM_CC_GetTime: + *handleCount = 2; + result = TPMI_RH_ENDORSEMENT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[1], handleBufferStart, bufferRemainingSize, TRUE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_2; + break; +#endif // CC_GetTime +#if CC_CertifyX509 +case TPM_CC_CertifyX509: + *handleCount = 2; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[1], handleBufferStart, bufferRemainingSize, TRUE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_2; + break; +#endif // CC_CertifyX509 +#if CC_Commit +case TPM_CC_Commit: + *handleCount = 1; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_Commit +#if CC_EC_Ephemeral +case TPM_CC_EC_Ephemeral: + break; +#endif // CC_EC_Ephemeral +#if CC_VerifySignature +case TPM_CC_VerifySignature: + *handleCount = 1; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_VerifySignature +#if CC_Sign +case TPM_CC_Sign: + *handleCount = 1; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_Sign +#if CC_SetCommandCodeAuditStatus +case TPM_CC_SetCommandCodeAuditStatus: + *handleCount = 1; + result = TPMI_RH_PROVISION_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_SetCommandCodeAuditStatus +#if CC_PCR_Extend +case TPM_CC_PCR_Extend: + *handleCount = 1; + result = TPMI_DH_PCR_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, TRUE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_PCR_Extend +#if CC_PCR_Event +case TPM_CC_PCR_Event: + *handleCount = 1; + result = TPMI_DH_PCR_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, TRUE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_PCR_Event +#if CC_PCR_Read +case TPM_CC_PCR_Read: + break; +#endif // CC_PCR_Read +#if CC_PCR_Allocate +case TPM_CC_PCR_Allocate: + *handleCount = 1; + result = TPMI_RH_PLATFORM_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_PCR_Allocate +#if CC_PCR_SetAuthPolicy +case TPM_CC_PCR_SetAuthPolicy: + *handleCount = 1; + result = TPMI_RH_PLATFORM_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_PCR_SetAuthPolicy +#if CC_PCR_SetAuthValue +case TPM_CC_PCR_SetAuthValue: + *handleCount = 1; + result = TPMI_DH_PCR_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_PCR_SetAuthValue +#if CC_PCR_Reset +case TPM_CC_PCR_Reset: + *handleCount = 1; + result = TPMI_DH_PCR_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_PCR_Reset +#if CC_PolicySigned +case TPM_CC_PolicySigned: + *handleCount = 2; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + result = + TPMI_SH_POLICY_Unmarshal(&handles[1], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_2; + break; +#endif // CC_PolicySigned +#if CC_PolicySecret +case TPM_CC_PolicySecret: + *handleCount = 2; + result = TPMI_DH_ENTITY_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + result = + TPMI_SH_POLICY_Unmarshal(&handles[1], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_2; + break; +#endif // CC_PolicySecret +#if CC_PolicyTicket +case TPM_CC_PolicyTicket: + *handleCount = 1; + result = + TPMI_SH_POLICY_Unmarshal(&handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_PolicyTicket +#if CC_PolicyOR +case TPM_CC_PolicyOR: + *handleCount = 1; + result = + TPMI_SH_POLICY_Unmarshal(&handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_PolicyOR +#if CC_PolicyPCR +case TPM_CC_PolicyPCR: + *handleCount = 1; + result = + TPMI_SH_POLICY_Unmarshal(&handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_PolicyPCR +#if CC_PolicyLocality +case TPM_CC_PolicyLocality: + *handleCount = 1; + result = + TPMI_SH_POLICY_Unmarshal(&handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_PolicyLocality +#if CC_PolicyNV +case TPM_CC_PolicyNV: + *handleCount = 3; + result = TPMI_RH_NV_AUTH_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + result = TPMI_RH_NV_INDEX_Unmarshal( + &handles[1], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_2; + result = + TPMI_SH_POLICY_Unmarshal(&handles[2], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_3; + break; +#endif // CC_PolicyNV +#if CC_PolicyCounterTimer +case TPM_CC_PolicyCounterTimer: + *handleCount = 1; + result = + TPMI_SH_POLICY_Unmarshal(&handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_PolicyCounterTimer +#if CC_PolicyCommandCode +case TPM_CC_PolicyCommandCode: + *handleCount = 1; + result = + TPMI_SH_POLICY_Unmarshal(&handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_PolicyCommandCode +#if CC_PolicyPhysicalPresence +case TPM_CC_PolicyPhysicalPresence: + *handleCount = 1; + result = + TPMI_SH_POLICY_Unmarshal(&handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_PolicyPhysicalPresence +#if CC_PolicyCpHash +case TPM_CC_PolicyCpHash: + *handleCount = 1; + result = + TPMI_SH_POLICY_Unmarshal(&handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_PolicyCpHash +#if CC_PolicyNameHash +case TPM_CC_PolicyNameHash: + *handleCount = 1; + result = + TPMI_SH_POLICY_Unmarshal(&handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_PolicyNameHash +#if CC_PolicyDuplicationSelect +case TPM_CC_PolicyDuplicationSelect: + *handleCount = 1; + result = + TPMI_SH_POLICY_Unmarshal(&handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_PolicyDuplicationSelect +#if CC_PolicyAuthorize +case TPM_CC_PolicyAuthorize: + *handleCount = 1; + result = + TPMI_SH_POLICY_Unmarshal(&handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_PolicyAuthorize +#if CC_PolicyAuthValue +case TPM_CC_PolicyAuthValue: + *handleCount = 1; + result = + TPMI_SH_POLICY_Unmarshal(&handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_PolicyAuthValue +#if CC_PolicyPassword +case TPM_CC_PolicyPassword: + *handleCount = 1; + result = + TPMI_SH_POLICY_Unmarshal(&handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_PolicyPassword +#if CC_PolicyGetDigest +case TPM_CC_PolicyGetDigest: + *handleCount = 1; + result = + TPMI_SH_POLICY_Unmarshal(&handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_PolicyGetDigest +#if CC_PolicyNvWritten +case TPM_CC_PolicyNvWritten: + *handleCount = 1; + result = + TPMI_SH_POLICY_Unmarshal(&handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_PolicyNvWritten +#if CC_PolicyTemplate +case TPM_CC_PolicyTemplate: + *handleCount = 1; + result = + TPMI_SH_POLICY_Unmarshal(&handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_PolicyTemplate +#if CC_PolicyAuthorizeNV +case TPM_CC_PolicyAuthorizeNV: + *handleCount = 3; + result = TPMI_RH_NV_AUTH_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + result = TPMI_RH_NV_INDEX_Unmarshal( + &handles[1], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_2; + result = + TPMI_SH_POLICY_Unmarshal(&handles[2], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_3; + break; +#endif // CC_PolicyAuthorizeNV +#if CC_CreatePrimary +case TPM_CC_CreatePrimary: + *handleCount = 1; + result = TPMI_RH_HIERARCHY_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, TRUE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_CreatePrimary +#if CC_HierarchyControl +case TPM_CC_HierarchyControl: + *handleCount = 1; + result = TPMI_RH_HIERARCHY_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_HierarchyControl +#if CC_SetPrimaryPolicy +case TPM_CC_SetPrimaryPolicy: + *handleCount = 1; + result = TPMI_RH_HIERARCHY_POLICY_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_SetPrimaryPolicy +#if CC_ChangePPS +case TPM_CC_ChangePPS: + *handleCount = 1; + result = TPMI_RH_PLATFORM_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_ChangePPS +#if CC_ChangeEPS +case TPM_CC_ChangeEPS: + *handleCount = 1; + result = TPMI_RH_PLATFORM_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_ChangeEPS +#if CC_Clear +case TPM_CC_Clear: + *handleCount = 1; + result = + TPMI_RH_CLEAR_Unmarshal(&handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_Clear +#if CC_ClearControl +case TPM_CC_ClearControl: + *handleCount = 1; + result = + TPMI_RH_CLEAR_Unmarshal(&handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_ClearControl +#if CC_HierarchyChangeAuth +case TPM_CC_HierarchyChangeAuth: + *handleCount = 1; + result = TPMI_RH_HIERARCHY_AUTH_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_HierarchyChangeAuth +#if CC_DictionaryAttackLockReset +case TPM_CC_DictionaryAttackLockReset: + *handleCount = 1; + result = TPMI_RH_LOCKOUT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_DictionaryAttackLockReset +#if CC_DictionaryAttackParameters +case TPM_CC_DictionaryAttackParameters: + *handleCount = 1; + result = TPMI_RH_LOCKOUT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_DictionaryAttackParameters +#if CC_PP_Commands +case TPM_CC_PP_Commands: + *handleCount = 1; + result = TPMI_RH_PLATFORM_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_PP_Commands +#if CC_SetAlgorithmSet +case TPM_CC_SetAlgorithmSet: + *handleCount = 1; + result = TPMI_RH_PLATFORM_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_SetAlgorithmSet +#if CC_FieldUpgradeStart +case TPM_CC_FieldUpgradeStart: + *handleCount = 2; + result = TPMI_RH_PLATFORM_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[1], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_2; + break; +#endif // CC_FieldUpgradeStart +#if CC_FieldUpgradeData +case TPM_CC_FieldUpgradeData: + break; +#endif // CC_FieldUpgradeData +#if CC_FirmwareRead +case TPM_CC_FirmwareRead: + break; +#endif // CC_FirmwareRead +#if CC_ContextSave +case TPM_CC_ContextSave: + *handleCount = 1; + result = TPMI_DH_CONTEXT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_ContextSave +#if CC_ContextLoad +case TPM_CC_ContextLoad: + break; +#endif // CC_ContextLoad +#if CC_FlushContext +case TPM_CC_FlushContext: + break; +#endif // CC_FlushContext +#if CC_EvictControl +case TPM_CC_EvictControl: + *handleCount = 2; + result = TPMI_RH_PROVISION_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[1], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_2; + break; +#endif // CC_EvictControl +#if CC_ReadClock +case TPM_CC_ReadClock: + break; +#endif // CC_ReadClock +#if CC_ClockSet +case TPM_CC_ClockSet: + *handleCount = 1; + result = TPMI_RH_PROVISION_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_ClockSet +#if CC_ClockRateAdjust +case TPM_CC_ClockRateAdjust: + *handleCount = 1; + result = TPMI_RH_PROVISION_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_ClockRateAdjust +#if CC_GetCapability +case TPM_CC_GetCapability: + break; +#endif // CC_GetCapability +#if CC_TestParms +case TPM_CC_TestParms: + break; +#endif // CC_TestParms +#if CC_NV_DefineSpace +case TPM_CC_NV_DefineSpace: + *handleCount = 1; + result = TPMI_RH_PROVISION_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_NV_DefineSpace +#if CC_NV_UndefineSpace +case TPM_CC_NV_UndefineSpace: + *handleCount = 2; + result = TPMI_RH_PROVISION_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + result = TPMI_RH_NV_INDEX_Unmarshal( + &handles[1], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_2; + break; +#endif // CC_NV_UndefineSpace +#if CC_NV_UndefineSpaceSpecial +case TPM_CC_NV_UndefineSpaceSpecial: + *handleCount = 2; + result = TPMI_RH_NV_INDEX_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + result = TPMI_RH_PLATFORM_Unmarshal( + &handles[1], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_2; + break; +#endif // CC_NV_UndefineSpaceSpecial +#if CC_NV_ReadPublic +case TPM_CC_NV_ReadPublic: + *handleCount = 1; + result = TPMI_RH_NV_INDEX_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_NV_ReadPublic +#if CC_NV_Write +case TPM_CC_NV_Write: + *handleCount = 2; + result = TPMI_RH_NV_AUTH_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + result = TPMI_RH_NV_INDEX_Unmarshal( + &handles[1], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_2; + break; +#endif // CC_NV_Write +#if CC_NV_Increment +case TPM_CC_NV_Increment: + *handleCount = 2; + result = TPMI_RH_NV_AUTH_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + result = TPMI_RH_NV_INDEX_Unmarshal( + &handles[1], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_2; + break; +#endif // CC_NV_Increment +#if CC_NV_Extend +case TPM_CC_NV_Extend: + *handleCount = 2; + result = TPMI_RH_NV_AUTH_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + result = TPMI_RH_NV_INDEX_Unmarshal( + &handles[1], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_2; + break; +#endif // CC_NV_Extend +#if CC_NV_SetBits +case TPM_CC_NV_SetBits: + *handleCount = 2; + result = TPMI_RH_NV_AUTH_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + result = TPMI_RH_NV_INDEX_Unmarshal( + &handles[1], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_2; + break; +#endif // CC_NV_SetBits +#if CC_NV_WriteLock +case TPM_CC_NV_WriteLock: + *handleCount = 2; + result = TPMI_RH_NV_AUTH_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + result = TPMI_RH_NV_INDEX_Unmarshal( + &handles[1], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_2; + break; +#endif // CC_NV_WriteLock +#if CC_NV_GlobalWriteLock +case TPM_CC_NV_GlobalWriteLock: + *handleCount = 1; + result = TPMI_RH_PROVISION_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_NV_GlobalWriteLock +#if CC_NV_Read +case TPM_CC_NV_Read: + *handleCount = 2; + result = TPMI_RH_NV_AUTH_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + result = TPMI_RH_NV_INDEX_Unmarshal( + &handles[1], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_2; + break; +#endif // CC_NV_Read +#if CC_NV_ReadLock +case TPM_CC_NV_ReadLock: + *handleCount = 2; + result = TPMI_RH_NV_AUTH_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + result = TPMI_RH_NV_INDEX_Unmarshal( + &handles[1], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_2; + break; +#endif // CC_NV_ReadLock +#if CC_NV_ChangeAuth +case TPM_CC_NV_ChangeAuth: + *handleCount = 1; + result = TPMI_RH_NV_INDEX_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_NV_ChangeAuth +#if CC_NV_Certify +case TPM_CC_NV_Certify: + *handleCount = 3; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, TRUE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + result = TPMI_RH_NV_AUTH_Unmarshal( + &handles[1], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_2; + result = TPMI_RH_NV_INDEX_Unmarshal( + &handles[2], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_3; + break; +#endif // CC_NV_Certify +#if CC_AC_GetCapability +case TPM_CC_AC_GetCapability: + *handleCount = 1; + result = + TPMI_RH_AC_Unmarshal(&handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_AC_GetCapability +#if CC_AC_Send +case TPM_CC_AC_Send: + *handleCount = 3; + result = TPMI_DH_OBJECT_Unmarshal( + &handles[0], handleBufferStart, bufferRemainingSize, FALSE); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + result = TPMI_RH_NV_AUTH_Unmarshal( + &handles[1], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_2; + result = + TPMI_RH_AC_Unmarshal(&handles[2], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_3; + break; +#endif // CC_AC_Send +#if CC_Policy_AC_SendSelect +case TPM_CC_Policy_AC_SendSelect: + *handleCount = 1; + result = + TPMI_SH_POLICY_Unmarshal(&handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_Policy_AC_SendSelect +#if CC_ACT_SetTimeout +case TPM_CC_ACT_SetTimeout: + *handleCount = 1; + result = + TPMI_RH_ACT_Unmarshal(&handles[0], handleBufferStart, bufferRemainingSize); + if(TPM_RC_SUCCESS != result) + return result + TPM_RC_H + TPM_RC_1; + break; +#endif // CC_ACT_SetTimeout +#if CC_Vendor_TCG_Test +case TPM_CC_Vendor_TCG_Test: + break; +#endif // CC_Vendor_TCG_Test diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/HashTestData.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/HashTestData.h new file mode 100644 index 0000000..e84d039 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/HashTestData.h @@ -0,0 +1,128 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +// +// Hash Test Vectors +// + +TPM2B_TYPE(HASH_TEST_KEY, 128); // Twice the largest digest size +TPM2B_HASH_TEST_KEY c_hashTestKey = { + {128, + {0xa0, 0xed, 0x5c, 0x9a, 0xd2, 0x4a, 0x21, 0x40, 0x1a, 0xd0, 0x81, 0x47, 0x39, + 0x63, 0xf9, 0x50, 0xdc, 0x59, 0x47, 0x11, 0x40, 0x13, 0x99, 0x92, 0xc0, 0x72, + 0xa4, 0x0f, 0xe2, 0x33, 0xe4, 0x63, 0x9b, 0xb6, 0x76, 0xc3, 0x1e, 0x6f, 0x13, + 0xee, 0xcc, 0x99, 0x71, 0xa5, 0xc0, 0xcf, 0x9a, 0x40, 0xcf, 0xdb, 0x66, 0x70, + 0x05, 0x63, 0x54, 0x12, 0x25, 0xf4, 0xe0, 0x1b, 0x23, 0x35, 0xe3, 0x70, 0x7d, + 0x19, 0x5f, 0x00, 0xe4, 0xf1, 0x61, 0x73, 0x05, 0xd8, 0x58, 0x7f, 0x60, 0x61, + 0x84, 0x36, 0xec, 0xbe, 0x96, 0x1b, 0x69, 0x00, 0xf0, 0x9a, 0x6e, 0xe3, 0x26, + 0x73, 0x0d, 0x17, 0x5b, 0x33, 0x41, 0x44, 0x9d, 0x90, 0xab, 0xd9, 0x6b, 0x7d, + 0x48, 0x99, 0x25, 0x93, 0x29, 0x14, 0x2b, 0xce, 0x93, 0x8d, 0x8c, 0xaf, 0x31, + 0x0e, 0x9c, 0x57, 0xd8, 0x5b, 0x57, 0x20, 0x1b, 0x9f, 0x2d, 0xa5}}}; + +TPM2B_TYPE(HASH_TEST_DATA, 256); // Twice the largest block size +TPM2B_HASH_TEST_DATA c_hashTestData = { + {256, + {0x88, 0xac, 0xc3, 0xe5, 0x5f, 0x66, 0x9d, 0x18, 0x80, 0xc9, 0x7a, 0x9c, 0xa4, + 0x08, 0x90, 0x98, 0x0f, 0x3a, 0x53, 0x92, 0x4c, 0x67, 0x4e, 0xb7, 0x37, 0xec, + 0x67, 0x87, 0xb6, 0xbe, 0x10, 0xca, 0x11, 0x5b, 0x4a, 0x0b, 0x45, 0xc3, 0x32, + 0x68, 0x48, 0x69, 0xce, 0x25, 0x1b, 0xc8, 0xaf, 0x44, 0x79, 0x22, 0x83, 0xc8, + 0xfb, 0xe2, 0x63, 0x94, 0xa2, 0x3c, 0x59, 0x3e, 0x3e, 0xc6, 0x64, 0x2c, 0x1f, + 0x8c, 0x11, 0x93, 0x24, 0xa3, 0x17, 0xc5, 0x2f, 0x37, 0xcf, 0x95, 0x97, 0x8e, + 0x63, 0x39, 0x68, 0xd5, 0xca, 0xba, 0x18, 0x37, 0x69, 0x6e, 0x4f, 0x19, 0xfd, + 0x8a, 0xc0, 0x8d, 0x87, 0x3a, 0xbc, 0x31, 0x42, 0x04, 0x05, 0xef, 0xb5, 0x02, + 0xef, 0x1e, 0x92, 0x4b, 0xb7, 0x73, 0x2c, 0x8c, 0xeb, 0x23, 0x13, 0x81, 0x34, + 0xb9, 0xb5, 0xc1, 0x17, 0x37, 0x39, 0xf8, 0x3e, 0xe4, 0x4c, 0x06, 0xa8, 0x81, + 0x52, 0x2f, 0xef, 0xc9, 0x9c, 0x69, 0x89, 0xbc, 0x85, 0x9c, 0x30, 0x16, 0x02, + 0xca, 0xe3, 0x61, 0xd4, 0x0f, 0xed, 0x34, 0x1b, 0xca, 0xc1, 0x1b, 0xd1, 0xfa, + 0xc1, 0xa2, 0xe0, 0xdf, 0x52, 0x2f, 0x0b, 0x4b, 0x9f, 0x0e, 0x45, 0x54, 0xb9, + 0x17, 0xb6, 0xaf, 0xd6, 0xd5, 0xca, 0x90, 0x29, 0x57, 0x7b, 0x70, 0x50, 0x94, + 0x5c, 0x8e, 0xf6, 0x4e, 0x21, 0x8b, 0xc6, 0x8b, 0xa6, 0xbc, 0xb9, 0x64, 0xd4, + 0x4d, 0xf3, 0x68, 0xd8, 0xac, 0xde, 0xd8, 0xd8, 0xb5, 0x6d, 0xcd, 0x93, 0xeb, + 0x28, 0xa4, 0xe2, 0x5c, 0x44, 0xef, 0xf0, 0xe1, 0x6f, 0x38, 0x1a, 0x3c, 0xe6, + 0xef, 0xa2, 0x9d, 0xb9, 0xa8, 0x05, 0x2a, 0x95, 0xec, 0x5f, 0xdb, 0xb0, 0x25, + 0x67, 0x9c, 0x86, 0x7a, 0x8e, 0xea, 0x51, 0xcc, 0xc3, 0xd3, 0xff, 0x6e, 0xf0, + 0xed, 0xa3, 0xae, 0xf9, 0x5d, 0x33, 0x70, 0xf2, 0x11}}}; + +#if ALG_SHA1 == YES +TPM2B_TYPE(SHA1, 20); +TPM2B_SHA1 c_SHA1_digest = { + {20, {0xee, 0x2c, 0xef, 0x93, 0x76, 0xbd, 0xf8, 0x91, 0xbc, 0xe6, + 0xe5, 0x57, 0x53, 0x77, 0x01, 0xb5, 0x70, 0x95, 0xe5, 0x40}}}; +#endif + +#if ALG_SHA256 == YES +TPM2B_TYPE(SHA256, 32); +TPM2B_SHA256 c_SHA256_digest = { + {32, {0x64, 0xe8, 0xe0, 0xc3, 0xa9, 0xa4, 0x51, 0x49, 0x10, 0x55, 0x8d, + 0x31, 0x71, 0xe5, 0x2f, 0x69, 0x3a, 0xdc, 0xc7, 0x11, 0x32, 0x44, + 0x61, 0xbd, 0x34, 0x39, 0x57, 0xb0, 0xa8, 0x75, 0x86, 0x1b}}}; +#endif + +#if ALG_SHA384 == YES +TPM2B_TYPE(SHA384, 48); +TPM2B_SHA384 c_SHA384_digest = { + {48, {0x37, 0x75, 0x29, 0xb5, 0x20, 0x15, 0x6e, 0xa3, 0x7e, 0xa3, 0x0d, 0xcd, + 0x80, 0xa8, 0xa3, 0x3d, 0xeb, 0xe8, 0xad, 0x4e, 0x1c, 0x77, 0x94, 0x5a, + 0xaf, 0x6c, 0xd0, 0xc1, 0xfa, 0x43, 0x3f, 0xc7, 0xb8, 0xf1, 0x01, 0xc0, + 0x60, 0xbf, 0xf2, 0x87, 0xe8, 0x71, 0x9e, 0x51, 0x97, 0xa0, 0x09, 0x8d}}}; +#endif + +#if ALG_SHA512 == YES +TPM2B_TYPE(SHA512, 64); +TPM2B_SHA512 c_SHA512_digest = { + {64, + {0xe2, 0x7b, 0x10, 0x3d, 0x5e, 0x48, 0x58, 0x44, 0x67, 0xac, 0xa3, 0x81, 0x8c, + 0x1d, 0xc5, 0x71, 0x66, 0x92, 0x8a, 0x89, 0xaa, 0xd4, 0x35, 0x51, 0x60, 0x37, + 0x31, 0xd7, 0xba, 0xe7, 0x93, 0x0b, 0x16, 0x4d, 0xb3, 0xc8, 0x34, 0x98, 0x3c, + 0xd3, 0x53, 0xde, 0x5e, 0xe8, 0x0c, 0xbc, 0xaf, 0xc9, 0x24, 0x2c, 0xcc, 0xed, + 0xdb, 0xde, 0xba, 0x1f, 0x14, 0x14, 0x5a, 0x95, 0x80, 0xde, 0x66, 0xbd}}}; +#endif + +TPM2B_TYPE(EMPTY, 1); + +#if ALG_SM3_256 == YES +TPM2B_EMPTY c_SM3_256_digest = {{0, {0}}}; +#endif + +#if ALG_SHA3_256 == YES +TPM2B_EMPTY c_SHA3_256_digest = {{0, {0}}}; +#endif + +#if ALG_SHA3_384 == YES +TPM2B_EMPTY c_SHA3_384_digest = {{0, {0}}}; +#endif + +#if ALG_SHA3_512 == YES +TPM2B_EMPTY c_SHA3_512_digest = {{0, {0}}}; +#endif diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/InternalRoutines.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/InternalRoutines.h new file mode 100644 index 0000000..d71da32 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/InternalRoutines.h @@ -0,0 +1,129 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 INTERNAL_ROUTINES_H +#define INTERNAL_ROUTINES_H + +#if !defined _LIB_SUPPORT_H_ && !defined _TPM_H_ +# error "Should not be called" +#endif + +// DRTM functions +#include "_TPM_Hash_Start_fp.h" +#include "_TPM_Hash_Data_fp.h" +#include "_TPM_Hash_End_fp.h" + +// Internal subsystem functions +#include "Object_fp.h" +#include "Context_spt_fp.h" +#include "Object_spt_fp.h" +#include "Entity_fp.h" +#include "Session_fp.h" +#include "Hierarchy_fp.h" +#include "NvReserved_fp.h" +#include "NvDynamic_fp.h" +#include "NV_spt_fp.h" +#include "ACT_spt_fp.h" +#include "PCR_fp.h" +#include "DA_fp.h" +#include "TpmFail_fp.h" +#include "SessionProcess_fp.h" + +// Internal support functions +#include "CommandCodeAttributes_fp.h" +#include "Marshal.h" +#include "Time_fp.h" +#include "Locality_fp.h" +#include "PP_fp.h" +#include "CommandAudit_fp.h" +#include "Manufacture_fp.h" +#include "Handle_fp.h" +#include "Power_fp.h" +#include "Response_fp.h" +#include "CommandDispatcher_fp.h" + +#ifdef CC_AC_Send +# include "AC_spt_fp.h" +#endif // CC_AC_Send + +// Miscellaneous +#include "Bits_fp.h" +#include "AlgorithmCap_fp.h" +#include "PropertyCap_fp.h" +#include "IoBuffers_fp.h" +#include "Memory_fp.h" +#include "ResponseCodeProcessing_fp.h" + +// Internal cryptographic functions +#include "BnConvert_fp.h" +#include "BnMath_fp.h" +#include "BnMemory_fp.h" +#include "Ticket_fp.h" +#include "CryptUtil_fp.h" +#include "CryptHash_fp.h" +#include "CryptSym_fp.h" +#include "CryptDes_fp.h" +#include "CryptPrime_fp.h" +#include "CryptRand_fp.h" +#include "CryptSelfTest_fp.h" +#include "MathOnByteBuffers_fp.h" +#include "CryptSym_fp.h" +#include "AlgorithmTests_fp.h" + +#if ALG_RSA +# include "CryptRsa_fp.h" +# include "CryptPrimeSieve_fp.h" +#endif + +#if ALG_ECC +# include "CryptEccMain_fp.h" +# include "CryptEccSignature_fp.h" +# include "CryptEccKeyExchange_fp.h" +# include "CryptEccCrypt_fp.h" +#endif + +#if CC_MAC || CC_MAC_Start +# include "CryptSmac_fp.h" +# if ALG_CMAC +# include "CryptCmac_fp.h" +# endif +#endif + +// Support library +#include "SupportLibraryFunctionPrototypes_fp.h" + +// Linkage to platform functions +#include "Platform_fp.h" + +#endif diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/KdfTestData.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/KdfTestData.h new file mode 100644 index 0000000..07f6730 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/KdfTestData.h @@ -0,0 +1,98 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// +// Hash Test Vectors +// + +#define TEST_KDF_KEY_SIZE 20 + +TPM2B_TYPE(KDF_TEST_KEY, TEST_KDF_KEY_SIZE); +TPM2B_KDF_TEST_KEY c_kdfTestKeyIn = { + {TEST_KDF_KEY_SIZE, + {0x27, 0x1F, 0xA0, 0x8B, 0xBD, 0xC5, 0x06, 0x0E, 0xC3, 0xDF, + 0xA9, 0x28, 0xFF, 0x9B, 0x73, 0x12, 0x3A, 0x12, 0xDA, 0x0C}}}; + +TPM2B_TYPE(KDF_TEST_LABEL, 17); +TPM2B_KDF_TEST_LABEL c_kdfTestLabel = {{17, + {0x4B, + 0x44, + 0x46, + 0x53, + 0x45, + 0x4C, + 0x46, + 0x54, + 0x45, + 0x53, + 0x54, + 0x4C, + 0x41, + 0x42, + 0x45, + 0x4C, + 0x00}}}; + +TPM2B_TYPE(KDF_TEST_CONTEXT, 8); +TPM2B_KDF_TEST_CONTEXT c_kdfTestContextU = { + {8, {0xCE, 0x24, 0x4F, 0x39, 0x5D, 0xCA, 0x73, 0x91}}}; + +TPM2B_KDF_TEST_CONTEXT c_kdfTestContextV = { + {8, {0xDA, 0x50, 0x40, 0x31, 0xDD, 0xF1, 0x2E, 0x83}}}; + +#if ALG_SHA512 == ALG_YES +TPM2B_KDF_TEST_KEY c_kdfTestKeyOut = { + {20, {0x8b, 0xe2, 0xc1, 0xb8, 0x5b, 0x78, 0x56, 0x9b, 0x9f, 0xa7, + 0x59, 0xf5, 0x85, 0x7c, 0x56, 0xd6, 0x84, 0x81, 0x0f, 0xd3}}}; +# define KDF_TEST_ALG TPM_ALG_SHA512 + +#elif ALG_SHA384 == ALG_YES +TPM2B_KDF_TEST_KEY c_kdfTestKeyOut = { + {20, {0x1d, 0xce, 0x70, 0xc9, 0x11, 0x3e, 0xb2, 0xdb, 0xa4, 0x7b, + 0xd9, 0xcf, 0xc7, 0x2b, 0xf4, 0x6f, 0x45, 0xb0, 0x93, 0x12}}}; +# define KDF_TEST_ALG TPM_ALG_SHA384 + +#elif ALG_SHA256 == ALG_YES +TPM2B_KDF_TEST_KEY c_kdfTestKeyOut = { + {20, {0xbb, 0x02, 0x59, 0xe1, 0xc8, 0xba, 0x60, 0x7e, 0x6a, 0x2c, + 0xd7, 0x04, 0xb6, 0x9a, 0x90, 0x2e, 0x9a, 0xde, 0x84, 0xc4}}}; +# define KDF_TEST_ALG TPM_ALG_SHA256 + +#elif ALG_SHA1 == ALG_YES +TPM2B_KDF_TEST_KEY c_kdfTestKeyOut = { + {20, {0x55, 0xb5, 0xa7, 0x18, 0x4a, 0xa0, 0x74, 0x23, 0xc4, 0x7d, + 0xae, 0x76, 0x6c, 0x26, 0xa2, 0x37, 0x7d, 0x7c, 0xf8, 0x51}}}; +# define KDF_TEST_ALG TPM_ALG_SHA1 +#endif diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/LibSupport.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/LibSupport.h new file mode 100644 index 0000000..8a894d2 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/LibSupport.h @@ -0,0 +1,75 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * Copyright (c) 2023-2024, NVIDIA Corporation & AFFILIATES. + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 header file is used to select the library code that gets included in the +// TPM build. + +#ifndef _LIB_SUPPORT_H_ +#define _LIB_SUPPORT_H_ + +//********************* +#ifndef RADIX_BITS +# if defined(__x86_64__) || defined(__x86_64) || defined(__amd64__) \ + || defined(__amd64) || defined(_WIN64) || defined(_M_X64) || defined(_M_ARM64) \ + || defined(__aarch64__) || defined(__PPC64__) || defined(__s390x__) \ + || defined(__powerpc64__) || defined(__ppc64__) +# if defined(THIRTY_TWO_BIT) +# define RADIX_BITS 32 +# else +# define RADIX_BITS 64 +# endif +# elif defined(__i386__) || defined(__i386) || defined(i386) || defined(_WIN32) \ + || defined(_M_IX86) || defined(_M_ARM) || defined(__arm__) \ + || defined(__thumb__) +# define RADIX_BITS 32 +# else +# error Unable to determine RADIX_BITS from compiler environment +# endif +#endif // RADIX_BITS + +// These macros use the selected libraries to the proper include files. +#define LIB_QUOTE(_STRING_) #_STRING_ +#define LIB_INCLUDE2(_LIB_, _TYPE_) LIB_QUOTE(_LIB_/TpmTo##_LIB_##_TYPE_.h) +#define LIB_INCLUDE(_LIB_, _TYPE_) LIB_INCLUDE2(_LIB_, _TYPE_) + +// Include the options for hashing and symmetric. Defer the load of the math package +// Until the bignum parameters are defined. +#include LIB_INCLUDE(SYM_LIB, Sym) +#include LIB_INCLUDE(HASH_LIB, Hash) + +#undef MIN +#undef MAX + +#endif // _LIB_SUPPORT_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ltc/LtcSettings.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ltc/LtcSettings.h new file mode 100644 index 0000000..84a815e --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ltc/LtcSettings.h @@ -0,0 +1,84 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//** Introduction +// +// This header file contains some defines that are necessary to get LTC to compile +// correctly +// +#ifndef _LTC_SETTINGS_H_ +#define _LTC_SETTINGS_H_ + +#if(defined HASH_LIB_LTC) || (defined SYM_LIB_LTC) || (defined MATH_LIB_LTC) + +# if ALG_AES +# define LTC_RIJNDAEL +# endif +# if ALG_TDES +# define LTC_DES +# endif + +# define _Bool int + +// LibTomCrypt types +typedef unsigned long long ulong64; + +/* default no functions m for LTC */ +# 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) + +# ifndef XMEM_NEQ +# define XMEM_NEQ +# endif + +# define LTC_SHA512 +# define LTC_SHA384 +# define LTC_SHA256 +# define LTC_SHA1 + +// Define these function calls as needed +# define CryptLibStartup() LtcLibStartup() + +_REDUCE_WARNING_LEVEL_(0) +# include "tomcrypt.h" +_NORMAL_WARNING_LEVEL_ + +#endif + +#endif // diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ltc/TpmToLtcHash.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ltc/TpmToLtcHash.h new file mode 100644 index 0000000..007e825 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ltc/TpmToLtcHash.h @@ -0,0 +1,162 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//** Introduction +// This header defines the interface between the hashing code and the LIbTomCrypt +// hash functions. + +#ifndef HASH_LIB_DEFINED +#define HASH_LIB_DEFINED + +#define HASH_LIB_LTC + +// Avoid pulling in the MPA math if not doing asymmetric with LTC +#if !(defined MATH_LIB_LTC) +# define LTC_NO_ASYMMETRIC +#endif + +#define HASH_ALIGNMENT RADIX_BYTES + +#include "LtcSettings.h" + +//*************************************************************** +//******** Linking to the TomCrypt HASH code ******************** +//*************************************************************** +// These defines need to be known in all parts of the TPM so that the structure +// sizes can be properly computed when needed. +#define tpmHashStateSHA1_t struct sha1_state +#define tpmHashStateSHA256_t struct sha256_state +#define tpmHashStateSHA512_t struct sha512_state +#define tpmHashStateSHA384_t struct sha512_state + +// The following defines are only needed by CryptHash.c +#ifdef _CRYPT_HASH_C_ + +// Define the interface between CryptHash.c to the functions provided by the +// library. For each method, define the calling parameters of the method and then +// define how the method is invoked in CryptHash.c. +// +// All hashes are required to have the same calling sequence. If they don't, create +// a simple adaptation function that converts from the "standard" form of the call +// to the form used by the specific hash (and then send a nasty letter to the +// person who wrote the hash function for the library). +// +// The macro that calls the method also defines how the +// parameters get swizzled between the default form (in CryptHash.c)and the +// library form. +// +// Initialize the hash context +# define HASH_START_METHOD_DEF void(HASH_START_METHOD)(PANY_HASH_STATE state) +# define HASH_START(hashState) ((hashState)->def->method.start)(&(hashState)->state) + +// Add data to the hash +# define HASH_DATA_METHOD_DEF \ + void(HASH_DATA_METHOD)(PANY_HASH_STATE state, const BYTE* buffer, size_t size) +# define HASH_DATA(hashState, dInSize, dIn) \ + ((hashState)->def->method.data)(&(hashState)->state, dIn, dInSize) + +// Finalize the hash and get the digest +# define HASH_END_METHOD_DEF \ + void(HASH_END_METHOD)(PANY_HASH_STATE state, BYTE * buffer) +# define HASH_END(hashState, buffer) \ + ((hashState)->def->method.end)(&(hashState)->state, buffer) + +// Copy the hash context +// Note: For import, export, and copy, memcpy() is used since there is no +// reformatting necessary between the internal and external forms +# define HASH_STATE_COPY_METHOD_DEF \ + void(HASH_STATE_COPY_METHOD)( \ + PANY_HASH_STATE to, PCANY_HASH_STATE from, size_t size) +# define HASH_STATE_COPY(hashStateOut, hashStateIn) \ + ((hashStateIn)->def->method.copy)(&(hashStateOut)->state, \ + &(hashStateIn)->state, \ + (hashStateIn)->def->contextSize) + +// Copy (with reformatting when necessary) an internal hash structure to an +// external blob +# define HASH_STATE_EXPORT_METHOD_DEF \ + void(HASH_STATE_EXPORT_METHOD)(BYTE * to, PANY_HASH_STATE from, size_t size) +# define HASH_STATE_EXPORT(to, hashStateFrom) \ + ((hashStateFrom)->def->method.copyOut)( \ + &(((BYTE*)(to))[offsetof(HASH_STATE, state)]), \ + &(hashStateFrom)->state, \ + (hashStateFrom)->def->contextSize) + +// Copy from an external blob to an internal formate (with reformatting when +// necessary +# define HASH_STATE_IMPORT_METHOD_DEF \ + void(HASH_STATE_IMPORT_METHOD)(PANY_HASH_STATE to, const BYTE* from, size_t size) +# define HASH_STATE_IMPORT(hashStateTo, from) \ + ((hashStateTo)->def->method.copyIn)( \ + &(hashStateTo)->state, \ + &(((const BYTE*)(from))[offsetof(HASH_STATE, state)]), \ + (hashStateTo)->def->contextSize) + +// Internal External +// Designation Designation +# define tpmHashStart_SHA1 sha1_init +# define tpmHashData_SHA1 sha1_process +# define tpmHashEnd_SHA1 sha1_done +# define tpmHashStateCopy_SHA1 memcpy +# define tpmHashStateExport_SHA1 memcpy +# define tpmHashStateImport_SHA1 memcpy +# define tpmHashStart_SHA256 sha256_init +# define tpmHashData_SHA256 sha256_process +# define tpmHashEnd_SHA256 sha256_done +# define tpmHashStateCopy_SHA256 memcpy +# define tpmHashStateExport_SHA256 memcpy +# define tpmHashStateImport_SHA256 memcpy +# define tpmHashStart_SHA384 sha384_init +# define tpmHashData_SHA384 sha384_process +# define tpmHashEnd_SHA384 sha384_done +# define tpmHashStateCopy_SHA384 memcpy +# define tpmHashStateExport_SHA384 memcpy +# define tpmHashStateImport_SHA384 memcpy +# define tpmHashStart_SHA512 sha512_init +# define tpmHashData_SHA512 sha512_process +# define tpmHashEnd_SHA512 sha512_done +# define tpmHashStateCopy_SHA512 memcpy +# define tpmHashStateExport_SHA512 memcpy +# define tpmHashStateImport_SHA512 memcpy + +#endif // _CRYPT_HASH_C_ + +// No special processing to initialize the LTC hash library +#define LibHashInit() + +// No special processing at the end of the simulation (i.e., no statistics to print) +#define HashLibSimulationEnd() + +#endif // HASH_LIB_DEFINED diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ltc/TpmToLtcMath.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ltc/TpmToLtcMath.h new file mode 100644 index 0000000..60348e0 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ltc/TpmToLtcMath.h @@ -0,0 +1,87 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//** Introduction +// This file contains the structure definitions used for linking from the TPM +// code to the MPA and LTC math libraries. + +#ifndef MATH_LIB_DEFINED +#define MATH_LIB_DEFINED + +#define MATH_LIB_LTC + +_REDUCE_WARNING_LEVEL_(2) +#include "LtcSettings.h" +#include "mpalib.h" +#include "mpa.h" +#include "tomcrypt_mpa.h" +_NORMAL_WARNING_LEVEL_ + +#if RADIX_BITS != 32 +# error "The mpa library used with LibTomCrypt only works for 32-bit words" +#endif + +// These macros handle entering and leaving a scope +// from which an MPA or LibTomCrypt function may be called. +// Many of these functions require a scratch pool from which +// they will allocate scratch variables (rather than using their +// own stack). +extern mpa_scratch_mem external_mem_pool; + +#define MPA_ENTER(vars, bits) \ + mpa_word_t POOL_[mpa_scratch_mem_size_in_U32(vars, bits)]; \ + mpa_scratch_mem pool_save = external_mem_pool; \ + mpa_scratch_mem POOL = LtcPoolInit(POOL_, vars, bits) + +#define MPA_LEAVE() init_mpa_tomcrypt(pool_save) + +typedef ECC_CURVE_DATA bnCurve_t; + +typedef bnCurve_t* bigCurve; + +#define AccessCurveData(E) (E) + +// Include the support functions for the routines that are used by LTC thunk. +#include "TpmToLtcSupport_fp.h" + +#define CURVE_INITIALIZED(name, initializer) \ + bnCurve_t* name = (ECC_CURVE_DATA*)GetCurveData(initializer) + +#define CURVE_FREE(E) + +// This definition would change if there were something to report +#define MathLibSimulationEnd() + +#endif // MATH_LIB_DEFINED diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ltc/TpmToLtcSym.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ltc/TpmToLtcSym.h new file mode 100644 index 0000000..4074c85 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ltc/TpmToLtcSym.h @@ -0,0 +1,107 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//** Introduction +// +// This header file is used to "splice" the TPM to the LTC symmetric cipher code. + +#ifndef SYM_LIB_DEFINED +#define SYM_LIB_DEFINED + +#define SYM_LIB_LTC + +#define SYM_ALIGNMENT RADIX_BYTES + +// Avoid pulling in the MPA math if not doing asymmetric with LTC +#if !(defined MATH_LIB_LTC) +# define LTC_NO_ASYMMETRIC +#endif + +#include "LtcSettings.h" + +//*************************************************************** +//******** Linking to the TomCrypt AES code ********************* +//*************************************************************** + +#if ALG_SM4 +# error "SM4 is not available" +#endif + +#if ALG_CAMELLIA +# error "Camellia is not available" +#endif + +// Define the order of parameters to the functions that do block encryption and +// decryption. +typedef void (*TpmCryptSetSymKeyCall_t)(const void* in, void* out, void* keySchedule); + +// Macro to put the parameters in the order required by the library +#define SWIZZLE(keySchedule, in, out) \ + (const void*)(in), (void*)(out), (void*)(keySchedule) + +// Macros to set up the encryption/decryption key schedules +// +// AES: +#define TpmCryptSetEncryptKeyAES(key, keySizeInBits, schedule) \ + aes_setup((key), BITS_TO_BYTES(keySizeInBits), 0, (symmetric_key*)(schedule)) +#define TpmCryptSetDecryptKeyAES(key, keySizeInBits, schedule) \ + aes_setup((key), BITS_TO_BYTES(keySizeInBits), 0, (symmetric_key*)(schedule)) + +// TDES: +#define TpmCryptSetEncryptKeyTDES(key, keySizeInBits, schedule) \ + TDES_setup((key), (keySizeInBits), (symmetric_key*)(schedule)) +#define TpmCryptSetDecryptKeyTDES(key, keySizeInBits, schedule) \ + TDES_setup((key), (keySizeInBits), (symmetric_key*)(schedule)) + +// Macros to alias encrypt and decrypt function calls to library-specific values +// sparingly. These should be used sparingly. Currently, they are only used by +// CryptRand.c in the AES version of the DRBG. +#define TpmCryptEncryptAES aes_ecb_encrypt +#define TpmCryptDecryptAES aes_ecb_decrypt +#define tpmKeyScheduleAES struct rijndael_key +// +#define TpmCryptEncryptTDES des3_ecb_encrypt +#define TpmCryptDecryptTDES des3_ecb_decrypt +#define tpmKeyScheduleTDES struct des3_key + +typedef union tpmCryptKeySchedule_t tpmCryptKeySchedule_t; + +#include "TpmToLtcDesSupport_fp.h" + +// This is used to trigger printing of simulation statistics + +#define SymLibSimulationEnd() + +#endif // SYM_LIB_DEFINED diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Marshal.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Marshal.h new file mode 100644 index 0000000..c26a7f7 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Marshal.h @@ -0,0 +1,53 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//** Introduction +// This file is used to provide the things needed by a module that uses the marshaling +// functions. It handles the variations between the marshaling choices (procedural or +// table-driven). + +#if TABLE_DRIVEN_MARSHAL + +# include "TableMarshalTypes.h" + +# include "TableMarshalDefines.h" + +# include "TableDrivenMarshal_fp.h" + +#else + +# include "Marshal_fp.h" + +#endif diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Mbedtls/TpmToMbedtlsHash.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Mbedtls/TpmToMbedtlsHash.h new file mode 100644 index 0000000..0eac0d9 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Mbedtls/TpmToMbedtlsHash.h @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2023-2024, NVIDIA Corporation & AFFILIATES. All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +//** Introduction +// +// This header file is used to 'splice' the MbedTLS hash code into the TPM code. +// +#ifndef HASH_LIB_DEFINED +#define HASH_LIB_DEFINED + +#define HASH_LIB_MBEDTLS + +#define HASH_ALIGNMENT RADIX_BYTES + +#include +#include +#include + +//*************************************************************** +//** Links to the MbedTLS HASH code +//*************************************************************** + +// Redefine the internal name used for each of the hash state structures to the +// name used by the library. +// These defines need to be known in all parts of the TPM so that the structure +// sizes can be properly computed when needed. + +#define tpmHashStateSHA1_t mbedtls_sha1_context +#define tpmHashStateSHA256_t mbedtls_sha256_context +#define tpmHashStateSHA384_t mbedtls_sha512_context +#define tpmHashStateSHA512_t mbedtls_sha512_context + +// The defines below are only needed when compiling CryptHash.c or CryptSmac.c. +// This isolation is primarily to avoid name space collision. However, if there +// is a real collision, it will likely show up when the linker tries to put things +// together. + +#ifdef _CRYPT_HASH_C_ + +typedef BYTE *PBYTE; + +// Define the interface between CryptHash.c to the functions provided by the +// library. For each method, define the calling parameters of the method and then +// define how the method is invoked in CryptHash.c. +// +// All hashes are required to have the same calling sequence. If they don't, create +// a simple adaptation function that converts from the "standard" form of the call +// to the form used by the specific hash (and then send a nasty letter to the +// person who wrote the hash function for the library). +// +// The macro that calls the method also defines how the +// parameters get swizzled between the default form (in CryptHash.c)and the +// library form. +// +// Initialize the hash context +#define HASH_START_METHOD_DEF void (HASH_START_METHOD)(PANY_HASH_STATE state) +#define HASH_START(hashState) \ + ((hashState)->def->method.start)(&(hashState)->state); + +// Add data to the hash +#define HASH_DATA_METHOD_DEF \ + void (HASH_DATA_METHOD)(PANY_HASH_STATE state, \ + const BYTE *buffer, \ + size_t size) +#define HASH_DATA(hashState, dInSize, dIn) \ + ((hashState)->def->method.data)(&(hashState)->state, dIn, dInSize) + +// Finalize the hash and get the digest +#define HASH_END_METHOD_DEF \ + void (HASH_END_METHOD)(PANY_HASH_STATE state, BYTE *buffer) +#define HASH_END(hashState, buffer) \ + ((hashState)->def->method.end)(&(hashState)->state, buffer) + +// Copy the hash context +// Note: For import, export, and copy, memcpy() is used since there is no +// reformatting necessary between the internal and external forms. +#define HASH_STATE_COPY_METHOD_DEF \ + void (HASH_STATE_COPY_METHOD)(PANY_HASH_STATE to, \ + PCANY_HASH_STATE from, \ + size_t size) +#define HASH_STATE_COPY(hashStateOut, hashStateIn) \ + ((hashStateIn)->def->method.copy)(&(hashStateOut)->state, \ + &(hashStateIn)->state, \ + (hashStateIn)->def->contextSize) + +// Copy (with reformatting when necessary) an internal hash structure to an +// external blob +#define HASH_STATE_EXPORT_METHOD_DEF \ + void (HASH_STATE_EXPORT_METHOD)(BYTE *to, \ + PCANY_HASH_STATE from, \ + size_t size) +#define HASH_STATE_EXPORT(to, hashStateFrom) \ + ((hashStateFrom)->def->method.copyOut) \ + (&(((BYTE *)(to))[offsetof(HASH_STATE, state)]), \ + &(hashStateFrom)->state, \ + (hashStateFrom)->def->contextSize) + +// Copy from an external blob to an internal formate (with reformatting when +// necessary +#define HASH_STATE_IMPORT_METHOD_DEF \ + void (HASH_STATE_IMPORT_METHOD)(PANY_HASH_STATE to, \ + const BYTE *from, \ + size_t size) +#define HASH_STATE_IMPORT(hashStateTo, from) \ + ((hashStateTo)->def->method.copyIn) \ + (&(hashStateTo)->state, \ + &(((const BYTE *)(from))[offsetof(HASH_STATE, state)]),\ + (hashStateTo)->def->contextSize) + +static inline void mbedtls_sha256_start(mbedtls_sha256_context *ctx) \ +{ \ + mbedtls_sha256_starts(ctx, 0); \ +} + +static inline void mbedtls_sha384_start(mbedtls_sha512_context *ctx) \ +{ \ + mbedtls_sha512_starts(ctx, 1); \ +} + +static inline void mbedtls_sha512_start(mbedtls_sha512_context *ctx) \ +{ \ + mbedtls_sha512_starts(ctx, 0); \ +} + +// Function aliases. The code in CryptHash.c uses the internal designation for the +// functions. These need to be translated to the function names of the library. +#define tpmHashStart_SHA1 mbedtls_sha1_starts // external name of the + // initialization method +#define tpmHashData_SHA1 mbedtls_sha1_update +#define tpmHashEnd_SHA1 mbedtls_sha1_finish +#define tpmHashStateCopy_SHA1 memcpy +#define tpmHashStateExport_SHA1 memcpy +#define tpmHashStateImport_SHA1 memcpy +#define tpmHashStart_SHA256 mbedtls_sha256_start +#define tpmHashData_SHA256 mbedtls_sha256_update +#define tpmHashEnd_SHA256 mbedtls_sha256_finish +#define tpmHashStateCopy_SHA256 memcpy +#define tpmHashStateExport_SHA256 memcpy +#define tpmHashStateImport_SHA256 memcpy +#define tpmHashStart_SHA384 mbedtls_sha384_start +#define tpmHashData_SHA384 mbedtls_sha512_update +#define tpmHashEnd_SHA384 mbedtls_sha512_finish +#define tpmHashStateCopy_SHA384 memcpy +#define tpmHashStateExport_SHA384 memcpy +#define tpmHashStateImport_SHA384 memcpy +#define tpmHashStart_SHA512 mbedtls_sha512_start +#define tpmHashData_SHA512 mbedtls_sha512_update +#define tpmHashEnd_SHA512 mbedtls_sha512_finish +#define tpmHashStateCopy_SHA512 memcpy +#define tpmHashStateExport_SHA512 memcpy +#define tpmHashStateImport_SHA512 memcpy + +#endif // _CRYPT_HASH_C_ + +#define LibHashInit() +// This definition would change if there were something to report +#define HashLibSimulationEnd() + +#endif // HASH_LIB_DEFINED diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Mbedtls/TpmToMbedtlsMath.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Mbedtls/TpmToMbedtlsMath.h new file mode 100644 index 0000000..9aa527d --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Mbedtls/TpmToMbedtlsMath.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2023-2024, NVIDIA Corporation & AFFILIATES. All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +//** Introduction +// This file contains the structure definitions used for ECC in the MbedTLS +// version of the code. These definitions would change, based on the library. +// The ECC-related structures that cross the TPM interface are defined +// in TpmTypes.h +// + +#ifndef MATH_LIB_DEFINED +#define MATH_LIB_DEFINED + +#define MATH_LIB_MBEDTLS + +#include +#include + +#define MPI_VAR(name) \ + mbedtls_mpi _##name; \ + mbedtls_mpi *name = MpiInitialize(&_##name); + +// Allocate a mbedtls_mpi and initialize with the values in a mbedtls_mpi* initializer +#define MPI_INITIALIZED(name, initializer) \ + MPI_VAR(name); \ + BnToMbedtls(name, initializer); + +#define MPI_FREE(name) \ + mbedtls_mpi_free(name); + +#define POINT_CREATE(name, initializer) \ + ecc_point *name = EcPointInitialized(initializer); + +#define POINT_DELETE(name) \ + EcPointFree(name); \ + name = NULL; + +typedef ECC_CURVE_DATA bnCurve_t; + +typedef bnCurve_t *bigCurve; + +#define AccessCurveData(E) (E) + +#define CURVE_INITIALIZED(name, initializer) \ + bnCurve_t *name = (ECC_CURVE_DATA *)GetCurveData(initializer) + +#define CURVE_FREE(E) + +#include "TpmToMbedtlsSupport_fp.h" + +// This definition would change if there were something to report +#define MathLibSimulationEnd() + +#endif // MATH_LIB_DEFINED diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Mbedtls/TpmToMbedtlsSym.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Mbedtls/TpmToMbedtlsSym.h new file mode 100644 index 0000000..3caa411 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Mbedtls/TpmToMbedtlsSym.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2023-2024, NVIDIA Corporation & AFFILIATES. All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +//** Introduction +// +// This header file is used to 'splice' the MbedTLS library into the TPM code. + +#ifndef SYM_LIB_DEFINED +#define SYM_LIB_DEFINED + +#define SYM_LIB_MBEDTLS + +#define SYM_ALIGNMENT RADIX_BYTES + +#if ALG_SM4 +#undef ALG_SM4 +#define ALG_SM4 ALG_NO +#endif + +#if ALG_CAMELLIA +#undef ALG_CAMELLIA +#define ALG_CAMELLIA ALG_NO +#endif + +#if ALG_TDES +#undef ALG_TDES +#define ALG_TDES ALG_NO +#endif + +#include + +//*************************************************************** +//** Links to the MbedTLS AES code +//*************************************************************** + +// Define the order of parameters to the library functions that do block encryption +// and decryption. +typedef void(*TpmCryptSetSymKeyCall_t)( + void *keySchedule, + const BYTE *in, + BYTE *out + ); + +// The Crypt functions that call the block encryption function use the parameters +// in the order: +// 1) keySchedule +// 2) in buffer +// 3) out buffer +#define SWIZZLE(keySchedule, in, out) \ + (void *)(keySchedule), (const BYTE *)(in), (BYTE *)(out) + +// Macros to set up the encryption/decryption key schedules +// +// AES: +#define TpmCryptSetEncryptKeyAES(key, keySizeInBits, schedule) \ + mbedtls_aes_setkey_enc((tpmKeyScheduleAES *)(schedule), key, keySizeInBits) +#define TpmCryptSetDecryptKeyAES(key, keySizeInBits, schedule) \ + mbedtls_aes_setkey_dec((tpmKeyScheduleAES *)(schedule), key, keySizeInBits) + +// Macros to alias encryption calls to specific algorithms. This should be used +// sparingly. Currently, only used by CryptRand.c +// +// When using these calls, to call the AES block encryption code, the caller +// should use: +// TpmCryptEncryptAES(SWIZZLE(keySchedule, in, out)); +#define TpmCryptEncryptAES mbedtls_internal_aes_encrypt +#define TpmCryptDecryptAES mbedtls_internal_aes_decrypt +#define tpmKeyScheduleAES mbedtls_aes_context + +typedef union tpmCryptKeySchedule_t tpmCryptKeySchedule_t; + +// This definition would change if there were something to report +#define SymLibSimulationEnd() + +#endif // SYM_LIB_DEFINED diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/MinMax.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/MinMax.h new file mode 100644 index 0000000..613ef6d --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/MinMax.h @@ -0,0 +1,46 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 _MIN_MAX_H_ +#define _MIN_MAX_H_ + +#ifndef MAX +# define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif +#ifndef MIN +# define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif + +#endif // _MIN_MAX_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/NV.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/NV.h new file mode 100644 index 0000000..2f19a28 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/NV.h @@ -0,0 +1,150 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Index Type Definitions + +// These definitions allow the same code to be used pre and post 1.21. The main +// action is to redefine the index type values from the bit values. +// Use TPM_NT_ORDINARY to indicate if the TPM_NT type is defined + +#ifndef _NV_H_ +#define _NV_H_ + +#ifdef TPM_NT_ORDINARY +// If TPM_NT_ORDINARY is defined, then the TPM_NT field is present in a TPMA_NV +# define GET_TPM_NT(attributes) GET_ATTRIBUTE(attributes, TPMA_NV, TPM_NT) +#else +// If TPM_NT_ORDINARY is not defined, then need to synthesize it from the +// attributes +# define GetNv_TPM_NV(attributes) \ + (IS_ATTRIBUTE(attributes, TPMA_NV, COUNTER) \ + + (IS_ATTRIBUTE(attributes, TPMA_NV, BITS) << 1) \ + + (IS_ATTRIBUTE(attributes, TPMA_NV, EXTEND) << 2)) +# define TPM_NT_ORDINARY (0) +# define TPM_NT_COUNTER (1) +# define TPM_NT_BITS (2) +# define TPM_NT_EXTEND (4) +#endif + +//** Attribute Macros +// These macros are used to isolate the differences in the way that the index type +// changed in version 1.21 of the specification +#define IsNvOrdinaryIndex(attributes) (GET_TPM_NT(attributes) == TPM_NT_ORDINARY) + +#define IsNvCounterIndex(attributes) (GET_TPM_NT(attributes) == TPM_NT_COUNTER) + +#define IsNvBitsIndex(attributes) (GET_TPM_NT(attributes) == TPM_NT_BITS) + +#define IsNvExtendIndex(attributes) (GET_TPM_NT(attributes) == TPM_NT_EXTEND) + +#ifdef TPM_NT_PIN_PASS +# define IsNvPinPassIndex(attributes) (GET_TPM_NT(attributes) == TPM_NT_PIN_PASS) +#endif + +#ifdef TPM_NT_PIN_FAIL +# define IsNvPinFailIndex(attributes) (GET_TPM_NT(attributes) == TPM_NT_PIN_FAIL) +#endif + +typedef struct +{ + UINT32 size; + TPM_HANDLE handle; +} NV_ENTRY_HEADER; + +#define NV_EVICT_OBJECT_SIZE (sizeof(UINT32) + sizeof(TPM_HANDLE) + sizeof(OBJECT)) + +#define NV_INDEX_COUNTER_SIZE (sizeof(UINT32) + sizeof(NV_INDEX) + sizeof(UINT64)) + +#define NV_RAM_INDEX_COUNTER_SIZE (sizeof(NV_RAM_HEADER) + sizeof(UINT64)) + +typedef struct +{ + UINT32 size; + TPM_HANDLE handle; + TPMA_NV attributes; +} NV_RAM_HEADER; + +// Defines the end-of-list marker for NV. The list terminator is +// a UINT32 of zero, followed by the current value of s_maxCounter which is a +// 64-bit value. The structure is defined as an array of 3 UINT32 values so that +// there is no padding between the UINT32 list end marker and the UINT64 maxCounter +// value. +typedef UINT32 NV_LIST_TERMINATOR[3]; + +//** Orderly RAM Values +// The following defines are for accessing orderly RAM values. + +// This is the initialize for the RAM reference iterator. +#define NV_RAM_REF_INIT 0 +// This is the starting address of the RAM space used for orderly data +#define RAM_ORDERLY_START (&s_indexOrderlyRam[0]) +// This is the offset within NV that is used to save the orderly data on an +// orderly shutdown. +#define NV_ORDERLY_START (NV_INDEX_RAM_DATA) +// This is the end of the orderly RAM space. It is actually the first byte after the +// last byte of orderly RAM data +#define RAM_ORDERLY_END (RAM_ORDERLY_START + sizeof(s_indexOrderlyRam)) +// This is the end of the orderly space in NV memory. As with RAM_ORDERLY_END, it is +// actually the offset of the first byte after the end of the NV orderly data. +#define NV_ORDERLY_END (NV_ORDERLY_START + sizeof(s_indexOrderlyRam)) + +// Macro to check that an orderly RAM address is with range. +#define ORDERLY_RAM_ADDRESS_OK(start, offset) \ + ((start >= RAM_ORDERLY_START) && ((start + offset - 1) < RAM_ORDERLY_END)) + +#define RETURN_IF_NV_IS_NOT_AVAILABLE \ + { \ + if(g_NvStatus != TPM_RC_SUCCESS) \ + return g_NvStatus; \ + } + +// Routinely have to clear the orderly flag and fail if the +// NV is not available so that it can be cleared. +#define RETURN_IF_ORDERLY \ + { \ + if(NvClearOrderly() != TPM_RC_SUCCESS) \ + return g_NvStatus; \ + } + +#define NV_IS_AVAILABLE (g_NvStatus == TPM_RC_SUCCESS) + +#define IS_ORDERLY(value) (value < SU_DA_USED_VALUE) + +#define NV_IS_ORDERLY (IS_ORDERLY(gp.orderlyState)) + +// Macro to set the NV UPDATE_TYPE. This deals with the fact that the update is +// possibly a combination of UT_NV and UT_ORDERLY. +#define SET_NV_UPDATE(type) g_updateNV |= (type) + +#endif // _NV_H_ \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/OIDs.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/OIDs.h new file mode 100644 index 0000000..7482321 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/OIDs.h @@ -0,0 +1,287 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 _OIDS_H_ +#define _OIDS_H_ + +// All the OIDs in this file are defined as DER-encoded values with a leading tag +// 0x06 (ASN1_OBJECT_IDENTIFIER), followed by a single length byte. This allows the +// OID size to be determined by looking at octet[1] of the OID (total size is +// OID[1] + 2). + +// These macros allow OIDs to be defined (or not) depending on whether the associated +// hash algorithm is implemented. +// NOTE: When one of these macros is used, the NAME needs '_" on each side. The +// exception is when the macro is used for the hash OID when only a single '_' is +// used. +#ifndef ALG_SHA1 +# define ALG_SHA1 NO +#endif +#if ALG_SHA1 +# define SHA1_OID(NAME) MAKE_OID(NAME##SHA1) +#else +# define SHA1_OID(NAME) +#endif +#ifndef ALG_SHA256 +# define ALG_SHA256 NO +#endif +#if ALG_SHA256 +# define SHA256_OID(NAME) MAKE_OID(NAME##SHA256) +#else +# define SHA256_OID(NAME) +#endif +#ifndef ALG_SHA384 +# define ALG_SHA384 NO +#endif +#if ALG_SHA384 +# define SHA384_OID(NAME) MAKE_OID(NAME##SHA384) +#else +# define SHA384_OID(NAME) +#endif +#ifndef ALG_SHA512 +# define ALG_SHA512 NO +#endif +#if ALG_SHA512 +# define SHA512_OID(NAME) MAKE_OID(NAME##SHA512) +#else +# define SHA512_OID(NAME) +#endif +#ifndef ALG_SM3_256 +# define ALG_SM3_256 NO +#endif +#if ALG_SM3_256 +# define SM3_256_OID(NAME) MAKE_OID(NAME##SM3_256) +#else +# define SM3_256_OID(NAME) +#endif +#ifndef ALG_SHA3_256 +# define ALG_SHA3_256 NO +#endif +#if ALG_SHA3_256 +# define SHA3_256_OID(NAME) MAKE_OID(NAME##SHA3_256) +#else +# define SHA3_256_OID(NAME) +#endif +#ifndef ALG_SHA3_384 +# define ALG_SHA3_384 NO +#endif +#if ALG_SHA3_384 +# define SHA3_384_OID(NAME) MAKE_OID(NAME##SHA3_384) +#else +# define SHA3_384_OID(NAME) +#endif +#ifndef ALG_SHA3_512 +# define ALG_SHA3_512 NO +#endif +#if ALG_SHA3_512 +# define SHA3_512_OID(NAME) MAKE_OID(NAME##SHA3_512) +#else +# define SHA3_512_OID(NAME) +#endif + +// These are encoded to take one additional byte of algorithm selector +#define NIST_HASH 0x06, 0x09, 0x60, 0x86, 0x48, 1, 101, 3, 4, 2 +#define NIST_SIG 0x06, 0x09, 0x60, 0x86, 0x48, 1, 101, 3, 4, 3 + +// These hash OIDs used in a lot of places. +#define OID_SHA1_VALUE 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A +SHA1_OID(_); // Expands to: + // MAKE_OID(_SHA1) + // which expands to: + // EXTERN const BYTE OID_SHA1[] INITIALIZER({OID_SHA1_VALUE}) + // which, depending on the setting of EXTERN and + // INITIALIZER, expands to either: + // extern const BYTE OID_SHA1[] + // or + // const BYTE OID_SHA1[] = {OID_SHA1_VALUE} + // which is: + // const BYTE OID_SHA1[] = {0x06, 0x05, 0x2B, 0x0E, + // 0x03, 0x02, 0x1A} + +#define OID_SHA256_VALUE NIST_HASH, 1 +SHA256_OID(_); + +#define OID_SHA384_VALUE NIST_HASH, 2 +SHA384_OID(_); + +#define OID_SHA512_VALUE NIST_HASH, 3 +SHA512_OID(_); + +#define OID_SM3_256_VALUE 0x06, 0x08, 0x2A, 0x81, 0x1C, 0xCF, 0x55, 0x01, 0x83, 0x11 +SM3_256_OID(_); // (1.2.156.10197.1.401) + +#define OID_SHA3_256_VALUE NIST_HASH, 8 +SHA3_256_OID(_); + +#define OID_SHA3_384_VALUE NIST_HASH, 9 +SHA3_384_OID(_); + +#define OID_SHA3_512_VALUE NIST_HASH, 10 +SHA3_512_OID(_); + +// These are used for RSA-PSS +#if ALG_RSA + +# define OID_MGF1_VALUE \ + 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x08 +MAKE_OID(_MGF1); + +# define OID_RSAPSS_VALUE \ + 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0A +MAKE_OID(_RSAPSS); + +// This is the OID to designate the public part of an RSA key. +# define OID_PKCS1_PUB_VALUE \ + 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01 +MAKE_OID(_PKCS1_PUB); + +// These are used for RSA PKCS1 signature Algorithms +# define OID_PKCS1_SHA1_VALUE \ + 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05 +SHA1_OID(_PKCS1_); // (1.2.840.113549.1.1.5) + +# define OID_PKCS1_SHA256_VALUE \ + 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B +SHA256_OID(_PKCS1_); // (1.2.840.113549.1.1.11) + +# define OID_PKCS1_SHA384_VALUE \ + 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0C +SHA384_OID(_PKCS1_); // (1.2.840.113549.1.1.12) + +# define OID_PKCS1_SHA512_VALUE \ + 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0D +SHA512_OID(_PKCS1_); //(1.2.840.113549.1.1.13) + +# define OID_PKCS1_SM3_256_VALUE \ + 0x06, 0x08, 0x2A, 0x81, 0x1C, 0xCF, 0x55, 0x01, 0x83, 0x78 +SM3_256_OID(_PKCS1_); // 1.2.156.10197.1.504 + +# define OID_PKCS1_SHA3_256_VALUE NIST_SIG, 14 +SHA3_256_OID(_PKCS1_); +# define OID_PKCS1_SHA3_384_VALUE NIST_SIG, 15 +SHA3_384_OID(_PKCS1_); +# define OID_PKCS1_SHA3_512_VALUE NIST_SIG, 16 +SHA3_512_OID(_PKCS1_); + +#endif // ALG_RSA + +#if ALG_ECDSA + +# define OID_ECDSA_SHA1_VALUE 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x01 +SHA1_OID(_ECDSA_); // (1.2.840.10045.4.1) SHA1 digest signed by an ECDSA key. + +# define OID_ECDSA_SHA256_VALUE \ + 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02 +SHA256_OID(_ECDSA_); // (1.2.840.10045.4.3.2) SHA256 digest signed by an ECDSA key. + +# define OID_ECDSA_SHA384_VALUE \ + 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x03 +SHA384_OID(_ECDSA_); // (1.2.840.10045.4.3.3) SHA384 digest signed by an ECDSA key. + +# define OID_ECDSA_SHA512_VALUE \ + 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x04 +SHA512_OID(_ECDSA_); // (1.2.840.10045.4.3.4) SHA512 digest signed by an ECDSA key. + +# define OID_ECDSA_SM3_256_VALUE \ + 0x06, 0x08, 0x2A, 0x81, 0x1C, 0xCF, 0x55, 0x01, 0x83, 0x75 +SM3_256_OID(_ECDSA_); // 1.2.156.10197.1.501 + +# define OID_ECDSA_SHA3_256_VALUE NIST_SIG, 10 +SHA3_256_OID(_ECDSA_); +# define OID_ECDSA_SHA3_384_VALUE NIST_SIG, 11 +SHA3_384_OID(_ECDSA_); +# define OID_ECDSA_SHA3_512_VALUE NIST_SIG, 12 +SHA3_512_OID(_ECDSA_); + +#endif // ALG_ECDSA + +#if ALG_ECC + +# define OID_ECC_PUBLIC_VALUE 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01 +MAKE_OID(_ECC_PUBLIC); + +# define OID_ECC_NIST_P192_VALUE \ + 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x01 +# if ECC_NIST_P192 +MAKE_OID(_ECC_NIST_P192); // (1.2.840.10045.3.1.1) 'nistP192' +# endif // ECC_NIST_P192 + +# define OID_ECC_NIST_P224_VALUE 0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x21 +# if ECC_NIST_P224 +MAKE_OID(_ECC_NIST_P224); // (1.3.132.0.33) 'nistP224' +# endif // ECC_NIST_P224 + +# define OID_ECC_NIST_P256_VALUE \ + 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07 +# if ECC_NIST_P256 +MAKE_OID(_ECC_NIST_P256); // (1.2.840.10045.3.1.7) 'nistP256' +# endif // ECC_NIST_P256 + +# define OID_ECC_NIST_P384_VALUE 0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22 +# if ECC_NIST_P384 +MAKE_OID(_ECC_NIST_P384); // (1.3.132.0.34) 'nistP384' +# endif // ECC_NIST_P384 + +# define OID_ECC_NIST_P521_VALUE 0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x23 +# if ECC_NIST_P521 +MAKE_OID(_ECC_NIST_P521); // (1.3.132.0.35) 'nistP521' +# endif // ECC_NIST_P521 + +// No OIDs defined for these anonymous curves +# define OID_ECC_BN_P256_VALUE 0x00 +# if ECC_BN_P256 +MAKE_OID(_ECC_BN_P256); +# endif // ECC_BN_P256 + +# define OID_ECC_BN_P638_VALUE 0x00 +# if ECC_BN_P638 +MAKE_OID(_ECC_BN_P638); +# endif // ECC_BN_P638 + +# define OID_ECC_SM2_P256_VALUE \ + 0x06, 0x08, 0x2A, 0x81, 0x1C, 0xCF, 0x55, 0x01, 0x82, 0x2D +# if ECC_SM2_P256 +MAKE_OID(_ECC_SM2_P256); // Don't know where I found this OID. It needs checking +# endif // ECC_SM2_P256 + +# if ECC_BN_P256 +# define OID_ECC_BN_P256 NULL +# endif // ECC_BN_P256 + +#endif // ALG_ECC + +#define OID_SIZE(OID) (OID[1] + 2) + +#endif // !_OIDS_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ossl/TpmToOsslHash.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ossl/TpmToOsslHash.h new file mode 100644 index 0000000..0a45b99 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ossl/TpmToOsslHash.h @@ -0,0 +1,201 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// +// This header file is used to 'splice' the OpenSSL hash code into the TPM code. +// +#ifndef HASH_LIB_DEFINED +#define HASH_LIB_DEFINED + +#define HASH_LIB_OSSL + +#include +#include + +#if ALG_SM3_256 +# if defined(OPENSSL_NO_SM3) || OPENSSL_VERSION_NUMBER < 0x10101010L +# undef ALG_SM3_256 +# define ALG_SM3_256 ALG_NO +# elif OPENSSL_VERSION_NUMBER >= 0x10200000L +# include +# else +// OpenSSL 1.1.1 keeps smX.h headers in the include/crypto directory, +// and they do not get installed as part of the libssl package +# define SM3_LBLOCK (64 / 4) + +typedef struct SM3state_st +{ + unsigned int A, B, C, D, E, F, G, H; + unsigned int Nl, Nh; + unsigned int data[SM3_LBLOCK]; + unsigned int num; +} SM3_CTX; + +int sm3_init(SM3_CTX* c); +int sm3_update(SM3_CTX* c, const void* data, size_t len); +int sm3_final(unsigned char* md, SM3_CTX* c); +# endif // OpenSSL < 1.2 +#endif // ALG_SM3_256 + +#include + +#define HASH_ALIGNMENT RADIX_BYTES + +//*************************************************************** +//** Links to the OpenSSL HASH code +//*************************************************************** + +// Redefine the internal name used for each of the hash state structures to the +// name used by the library. +// These defines need to be known in all parts of the TPM so that the structure +// sizes can be properly computed when needed. +#define tpmHashStateSHA1_t SHA_CTX +#define tpmHashStateSHA256_t SHA256_CTX +#define tpmHashStateSHA384_t SHA512_CTX +#define tpmHashStateSHA512_t SHA512_CTX +#define tpmHashStateSM3_256_t SM3_CTX + +// The defines below are only needed when compiling CryptHash.c or CryptSmac.c. +// This isolation is primarily to avoid name space collision. However, if there +// is a real collision, it will likely show up when the linker tries to put things +// together. + +#ifdef _CRYPT_HASH_C_ + +typedef BYTE* PBYTE; +typedef const BYTE* PCBYTE; + +// Define the interface between CryptHash.c to the functions provided by the +// library. For each method, define the calling parameters of the method and then +// define how the method is invoked in CryptHash.c. +// +// All hashes are required to have the same calling sequence. If they don't, create +// a simple adaptation function that converts from the "standard" form of the call +// to the form used by the specific hash (and then send a nasty letter to the +// person who wrote the hash function for the library). +// +// The macro that calls the method also defines how the +// parameters get swizzled between the default form (in CryptHash.c)and the +// library form. +// +// Initialize the hash context +# define HASH_START_METHOD_DEF void(HASH_START_METHOD)(PANY_HASH_STATE state) +# define HASH_START(hashState) ((hashState)->def->method.start)(&(hashState)->state); + +// Add data to the hash +# define HASH_DATA_METHOD_DEF \ + void(HASH_DATA_METHOD)(PANY_HASH_STATE state, PCBYTE buffer, size_t size) +# define HASH_DATA(hashState, dInSize, dIn) \ + ((hashState)->def->method.data)(&(hashState)->state, dIn, dInSize) + +// Finalize the hash and get the digest +# define HASH_END_METHOD_DEF \ + void(HASH_END_METHOD)(BYTE * buffer, PANY_HASH_STATE state) +# define HASH_END(hashState, buffer) \ + ((hashState)->def->method.end)(buffer, &(hashState)->state) + +// Copy the hash context +// Note: For import, export, and copy, memcpy() is used since there is no +// reformatting necessary between the internal and external forms. +# define HASH_STATE_COPY_METHOD_DEF \ + void(HASH_STATE_COPY_METHOD)( \ + PANY_HASH_STATE to, PCANY_HASH_STATE from, size_t size) +# define HASH_STATE_COPY(hashStateOut, hashStateIn) \ + ((hashStateIn)->def->method.copy)(&(hashStateOut)->state, \ + &(hashStateIn)->state, \ + (hashStateIn)->def->contextSize) + +// Copy (with reformatting when necessary) an internal hash structure to an +// external blob +# define HASH_STATE_EXPORT_METHOD_DEF \ + void(HASH_STATE_EXPORT_METHOD)(BYTE * to, PCANY_HASH_STATE from, size_t size) +# define HASH_STATE_EXPORT(to, hashStateFrom) \ + ((hashStateFrom)->def->method.copyOut)( \ + &(((BYTE*)(to))[offsetof(HASH_STATE, state)]), \ + &(hashStateFrom)->state, \ + (hashStateFrom)->def->contextSize) + +// Copy from an external blob to an internal formate (with reformatting when +// necessary +# define HASH_STATE_IMPORT_METHOD_DEF \ + void(HASH_STATE_IMPORT_METHOD)(PANY_HASH_STATE to, const BYTE* from, size_t size) +# define HASH_STATE_IMPORT(hashStateTo, from) \ + ((hashStateTo)->def->method.copyIn)( \ + &(hashStateTo)->state, \ + &(((const BYTE*)(from))[offsetof(HASH_STATE, state)]), \ + (hashStateTo)->def->contextSize) + +// Function aliases. The code in CryptHash.c uses the internal designation for the +// functions. These need to be translated to the function names of the library. +// external name of the +// initialization method +# define tpmHashStart_SHA1 SHA1_Init +# define tpmHashData_SHA1 SHA1_Update +# define tpmHashEnd_SHA1 SHA1_Final +# define tpmHashStateCopy_SHA1 memcpy +# define tpmHashStateExport_SHA1 memcpy +# define tpmHashStateImport_SHA1 memcpy +# define tpmHashStart_SHA256 SHA256_Init +# define tpmHashData_SHA256 SHA256_Update +# define tpmHashEnd_SHA256 SHA256_Final +# define tpmHashStateCopy_SHA256 memcpy +# define tpmHashStateExport_SHA256 memcpy +# define tpmHashStateImport_SHA256 memcpy +# define tpmHashStart_SHA384 SHA384_Init +# define tpmHashData_SHA384 SHA384_Update +# define tpmHashEnd_SHA384 SHA384_Final +# define tpmHashStateCopy_SHA384 memcpy +# define tpmHashStateExport_SHA384 memcpy +# define tpmHashStateImport_SHA384 memcpy +# define tpmHashStart_SHA512 SHA512_Init +# define tpmHashData_SHA512 SHA512_Update +# define tpmHashEnd_SHA512 SHA512_Final +# define tpmHashStateCopy_SHA512 memcpy +# define tpmHashStateExport_SHA512 memcpy +# define tpmHashStateImport_SHA512 memcpy +# define tpmHashStart_SM3_256 sm3_init +# define tpmHashData_SM3_256 sm3_update +# define tpmHashEnd_SM3_256 sm3_final +# define tpmHashStateCopy_SM3_256 memcpy +# define tpmHashStateExport_SM3_256 memcpy +# define tpmHashStateImport_SM3_256 memcpy + +#endif // _CRYPT_HASH_C_ + +#define LibHashInit() +// This definition would change if there were something to report +#define HashLibSimulationEnd() + +#endif // HASH_LIB_DEFINED diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ossl/TpmToOsslMath.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ossl/TpmToOsslMath.h new file mode 100644 index 0000000..ddaded4 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ossl/TpmToOsslMath.h @@ -0,0 +1,132 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// This file contains the structure definitions used for ECC in the OpenSSL +// version of the code. These definitions would change, based on the library. +// The ECC-related structures that cross the TPM interface are defined +// in TpmTypes.h +// + +#ifndef MATH_LIB_DEFINED +#define MATH_LIB_DEFINED + +#define MATH_LIB_OSSL + +#include +#include + +#define SYMMETRIC_ALIGNMENT RADIX_BYTES + +#if OPENSSL_VERSION_NUMBER >= 0x10200000L +// Check the bignum_st definition in crypto/bn/bn_lcl.h and either update the +// version check or provide the new definition for this version. +# error Untested OpenSSL version +#elif OPENSSL_VERSION_NUMBER >= 0x10100000L +// from crypto/bn/bn_lcl.h +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; +}; +#else +# define EC_POINT_get_affine_coordinates EC_POINT_get_affine_coordinates_GFp +# define EC_POINT_set_affine_coordinates EC_POINT_set_affine_coordinates_GFp +#endif // OPENSSL_VERSION_NUMBER + +#include + +//** Macros and Defines + +// Make sure that the library is using the correct size for a crypt word +#if defined THIRTY_TWO_BIT && (RADIX_BITS != 32) \ + || ((defined SIXTY_FOUR_BIT_LONG || defined SIXTY_FOUR_BIT) \ + && (RADIX_BITS != 64)) +# error Ossl library is using different radix +#endif + +// Allocate a local BIGNUM value. For the allocation, a bigNum structure is created +// as is a local BIGNUM. The bigNum is initialized and then the BIGNUM is +// set to reference the local value. +#define BIG_VAR(name, bits) \ + BN_VAR(name##Bn, (bits)); \ + BIGNUM _##name; \ + BIGNUM* name = BigInitialized( \ + &_##name, BnInit(name##Bn, BYTES_TO_CRYPT_WORDS(sizeof(_##name##Bn.d)))) + +// Allocate a BIGNUM and initialize with the values in a bigNum initializer +#define BIG_INITIALIZED(name, initializer) \ + BIGNUM _##name; \ + BIGNUM* name = BigInitialized(&_##name, initializer) + +typedef struct +{ + const ECC_CURVE_DATA* C; // the TPM curve values + EC_GROUP* G; // group parameters + BN_CTX* CTX; // the context for the math (this might not be + // the context in which the curve was created>; +} OSSL_CURVE_DATA; + +typedef OSSL_CURVE_DATA* bigCurve; + +#define AccessCurveData(E) ((E)->C) + +#include "TpmToOsslSupport_fp.h" + +// Start and end a context within which the OpenSSL memory management works +#define OSSL_ENTER() BN_CTX* CTX = OsslContextEnter() +#define OSSL_LEAVE() OsslContextLeave(CTX) + +// Start and end a context that spans multiple ECC functions. This is used so that +// the group for the curve can persist across multiple frames. +#define CURVE_INITIALIZED(name, initializer) \ + OSSL_CURVE_DATA _##name; \ + bigCurve name = BnCurveInitialize(&_##name, initializer) +#define CURVE_FREE(name) BnCurveFree(name) + +// Start and end a local stack frame within the context of the curve frame +#define ECC_ENTER() BN_CTX* CTX = OsslPushContext(E->CTX) +#define ECC_LEAVE() OsslPopContext(CTX) + +#define BN_NEW() BnNewVariable(CTX) + +// This definition would change if there were something to report +#define MathLibSimulationEnd() + +#endif // MATH_LIB_DEFINED diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ossl/TpmToOsslSym.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ossl/TpmToOsslSym.h new file mode 100644 index 0000000..b07a0bc --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Ossl/TpmToOsslSym.h @@ -0,0 +1,181 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// +// This header file is used to 'splice' the OpenSSL library into the TPM code. +// +// The support required of a library are a hash module, a block cipher module and +// portions of a big number library. + +// All of the library-dependent headers should have the same guard to that only the +// first one gets defined. +#ifndef SYM_LIB_DEFINED +#define SYM_LIB_DEFINED + +#define SYM_LIB_OSSL + +#include + +#if ALG_TDES +# include +#endif + +#if ALG_SM4 +# if defined(OPENSSL_NO_SM4) || OPENSSL_VERSION_NUMBER < 0x10101010L +# undef ALG_SM4 +# define ALG_SM4 ALG_NO +# elif OPENSSL_VERSION_NUMBER >= 0x10200000L +# include +# else +// OpenSSL 1.1.1 keeps smX.h headers in the include/crypto directory, +// and they do not get installed as part of the libssl package + +# define SM4_KEY_SCHEDULE 32 + +typedef struct SM4_KEY_st +{ + uint32_t rk[SM4_KEY_SCHEDULE]; +} SM4_KEY; + +int SM4_set_key(const uint8_t* key, SM4_KEY* ks); +void SM4_encrypt(const uint8_t* in, uint8_t* out, const SM4_KEY* ks); +void SM4_decrypt(const uint8_t* in, uint8_t* out, const SM4_KEY* ks); +# endif // OpenSSL < 1.2 +#endif // ALG_SM4 + +#if ALG_CAMELLIA +# include +#endif + +#include +#include + +//*************************************************************** +//** Links to the OpenSSL symmetric algorithms. +//*************************************************************** + +// The Crypt functions that call the block encryption function use the parameters +// in the order: +// 1) keySchedule +// 2) in buffer +// 3) out buffer +// Since open SSL uses the order in encryptoCall_t above, need to swizzle the +// values to the order required by the library. +#define SWIZZLE(keySchedule, in, out) \ + (const BYTE*)(in), (BYTE*)(out), (void*)(keySchedule) + +// Define the order of parameters to the library functions that do block encryption +// and decryption. +typedef void (*TpmCryptSetSymKeyCall_t)(const BYTE* in, BYTE* out, void* keySchedule); + +#define SYM_ALIGNMENT RADIX_BYTES + +//*************************************************************** +//** Links to the OpenSSL AES code +//*************************************************************** +// Macros to set up the encryption/decryption key schedules +// +// AES: +#define TpmCryptSetEncryptKeyAES(key, keySizeInBits, schedule) \ + AES_set_encrypt_key((key), (keySizeInBits), (tpmKeyScheduleAES*)(schedule)) +#define TpmCryptSetDecryptKeyAES(key, keySizeInBits, schedule) \ + AES_set_decrypt_key((key), (keySizeInBits), (tpmKeyScheduleAES*)(schedule)) + +// Macros to alias encryption calls to specific algorithms. This should be used +// sparingly. Currently, only used by CryptSym.c and CryptRand.c +// +// When using these calls, to call the AES block encryption code, the caller +// should use: +// TpmCryptEncryptAES(SWIZZLE(keySchedule, in, out)); +#define TpmCryptEncryptAES AES_encrypt +#define TpmCryptDecryptAES AES_decrypt +#define tpmKeyScheduleAES AES_KEY + +//*************************************************************** +//** Links to the OpenSSL DES code +//*************************************************************** +#if ALG_TDES +# include "TpmToOsslDesSupport_fp.h" +#endif + +#define TpmCryptSetEncryptKeyTDES(key, keySizeInBits, schedule) \ + TDES_set_encrypt_key((key), (keySizeInBits), (tpmKeyScheduleTDES*)(schedule)) +#define TpmCryptSetDecryptKeyTDES(key, keySizeInBits, schedule) \ + TDES_set_encrypt_key((key), (keySizeInBits), (tpmKeyScheduleTDES*)(schedule)) + +// Macros to alias encryption calls to specific algorithms. This should be used +// sparingly. Currently, only used by CryptRand.c +#define TpmCryptEncryptTDES TDES_encrypt +#define TpmCryptDecryptTDES TDES_decrypt +#define tpmKeyScheduleTDES DES_key_schedule + +//*************************************************************** +//** Links to the OpenSSL SM4 code +//*************************************************************** +// Macros to set up the encryption/decryption key schedules +#define TpmCryptSetEncryptKeySM4(key, keySizeInBits, schedule) \ + SM4_set_key((key), (tpmKeyScheduleSM4*)(schedule)) +#define TpmCryptSetDecryptKeySM4(key, keySizeInBits, schedule) \ + SM4_set_key((key), (tpmKeyScheduleSM4*)(schedule)) + +// Macros to alias encryption calls to specific algorithms. This should be used +// sparingly. +#define TpmCryptEncryptSM4 SM4_encrypt +#define TpmCryptDecryptSM4 SM4_decrypt +#define tpmKeyScheduleSM4 SM4_KEY + +//*************************************************************** +//** Links to the OpenSSL CAMELLIA code +//*************************************************************** +// Macros to set up the encryption/decryption key schedules +#define TpmCryptSetEncryptKeyCAMELLIA(key, keySizeInBits, schedule) \ + Camellia_set_key((key), (keySizeInBits), (tpmKeyScheduleCAMELLIA*)(schedule)) +#define TpmCryptSetDecryptKeyCAMELLIA(key, keySizeInBits, schedule) \ + Camellia_set_key((key), (keySizeInBits), (tpmKeyScheduleCAMELLIA*)(schedule)) + +// Macros to alias encryption calls to specific algorithms. This should be used +// sparingly. +#define TpmCryptEncryptCAMELLIA Camellia_encrypt +#define TpmCryptDecryptCAMELLIA Camellia_decrypt +#define tpmKeyScheduleCAMELLIA CAMELLIA_KEY + +// Forward reference + +typedef union tpmCryptKeySchedule_t tpmCryptKeySchedule_t; + +// This definition would change if there were something to report +#define SymLibSimulationEnd() + +#endif // SYM_LIB_DEFINED diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/PRNG_TestVectors.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/PRNG_TestVectors.h new file mode 100644 index 0000000..4a53fff --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/PRNG_TestVectors.h @@ -0,0 +1,131 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 _MSBN_DRBG_TEST_VECTORS_H +#define _MSBN_DRBG_TEST_VECTORS_H + +//#if DRBG_ALGORITHM == TPM_ALG_AES && DRBG_KEY_BITS == 256 +#if DRBG_KEY_SIZE_BITS == 256 + +/*(NIST test vector) +[AES-256 no df] +[PredictionResistance = False] +[EntropyInputLen = 384] +[NonceLen = 128] +[PersonalizationStringLen = 0] +[AdditionalInputLen = 0] + +COUNT = 0 +EntropyInput = 0d15aa80 b16c3a10 906cfedb 795dae0b 5b81041c 5c5bfacb + 373d4440 d9120f7e 3d6cf909 86cf52d8 5d3e947d 8c061f91 +Nonce = 06caef5f b538e08e 1f3b0452 03f8f4b2 +PersonalizationString = +AdditionalInput = + INTERMEDIATE Key = be5df629 34cc1230 166a6773 345bbd6b + 4c8869cf 8aec1c3b 1aa98bca 37cacf61 + INTERMEDIATE V = 3182dd1e 7638ec70 014e93bd 813e524c + INTERMEDIATE ReturnedBits = 28e0ebb8 21016650 8c8f65f2 207bd0a3 +EntropyInputReseed = 6ee793a3 3955d72a d12fd80a 8a3fcf95 ed3b4dac 5795fe25 + cf869f7c 27573bbc 56f1acae 13a65042 b340093c 464a7a22 +AdditionalInputReseed = +AdditionalInput = +ReturnedBits = 946f5182 d54510b9 461248f5 71ca06c9 +*/ + +// Entropy is the size of the state. The state is the size of the key +// plus the IV. The IV is a block. If Key = 256 and Block = 128 then State = 384 +# define DRBG_TEST_INITIATE_ENTROPY \ + 0x0d, 0x15, 0xaa, 0x80, 0xb1, 0x6c, 0x3a, 0x10, 0x90, 0x6c, 0xfe, 0xdb, 0x79, \ + 0x5d, 0xae, 0x0b, 0x5b, 0x81, 0x04, 0x1c, 0x5c, 0x5b, 0xfa, 0xcb, 0x37, \ + 0x3d, 0x44, 0x40, 0xd9, 0x12, 0x0f, 0x7e, 0x3d, 0x6c, 0xf9, 0x09, 0x86, \ + 0xcf, 0x52, 0xd8, 0x5d, 0x3e, 0x94, 0x7d, 0x8c, 0x06, 0x1f, 0x91 + +# define DRBG_TEST_RESEED_ENTROPY \ + 0x6e, 0xe7, 0x93, 0xa3, 0x39, 0x55, 0xd7, 0x2a, 0xd1, 0x2f, 0xd8, 0x0a, 0x8a, \ + 0x3f, 0xcf, 0x95, 0xed, 0x3b, 0x4d, 0xac, 0x57, 0x95, 0xfe, 0x25, 0xcf, \ + 0x86, 0x9f, 0x7c, 0x27, 0x57, 0x3b, 0xbc, 0x56, 0xf1, 0xac, 0xae, 0x13, \ + 0xa6, 0x50, 0x42, 0xb3, 0x40, 0x09, 0x3c, 0x46, 0x4a, 0x7a, 0x22 + +# define DRBG_TEST_GENERATED_INTERM \ + 0x28, 0xe0, 0xeb, 0xb8, 0x21, 0x01, 0x66, 0x50, 0x8c, 0x8f, 0x65, 0xf2, 0x20, \ + 0x7b, 0xd0, 0xa3 + +# define DRBG_TEST_GENERATED \ + 0x94, 0x6f, 0x51, 0x82, 0xd5, 0x45, 0x10, 0xb9, 0x46, 0x12, 0x48, 0xf5, 0x71, \ + 0xca, 0x06, 0xc9 +#elif DRBG_KEY_SIZE_BITS == 128 +/*(NIST test vector) +[AES-128 no df] +[PredictionResistance = False] +[EntropyInputLen = 256] +[NonceLen = 64] +[PersonalizationStringLen = 0] +[AdditionalInputLen = 0] + +COUNT = 0 +EntropyInput = 8fc11bdb5aabb7e093b61428e0907303cb459f3b600dad870955f22da80a44f8 +Nonce = be1f73885ddd15aa +PersonalizationString = +AdditionalInput = + INTERMEDIATE Key = b134ecc836df6dbd624900af118dd7e6 + INTERMEDIATE V = 01bb09e86dabd75c9f26dbf6f9531368 + INTERMEDIATE ReturnedBits = dc3cf6bf5bd341135f2c6811a1071c87 +EntropyInputReseed = + 0cd53cd5eccd5a10d7ea266111259b05574fc6ddd8bed8bd72378cf82f1dba2a +AdditionalInputReseed = +AdditionalInput = +ReturnedBits = b61850decfd7106d44769a8e6e8c1ad4 +*/ + +# define DRBG_TEST_INITIATE_ENTROPY \ + 0x8f, 0xc1, 0x1b, 0xdb, 0x5a, 0xab, 0xb7, 0xe0, 0x93, 0xb6, 0x14, 0x28, 0xe0, \ + 0x90, 0x73, 0x03, 0xcb, 0x45, 0x9f, 0x3b, 0x60, 0x0d, 0xad, 0x87, 0x09, \ + 0x55, 0xf2, 0x2d, 0xa8, 0x0a, 0x44, 0xf8 + +# define DRBG_TEST_RESEED_ENTROPY \ + 0x0c, 0xd5, 0x3c, 0xd5, 0xec, 0xcd, 0x5a, 0x10, 0xd7, 0xea, 0x26, 0x61, 0x11, \ + 0x25, 0x9b, 0x05, 0x57, 0x4f, 0xc6, 0xdd, 0xd8, 0xbe, 0xd8, 0xbd, 0x72, \ + 0x37, 0x8c, 0xf8, 0x2f, 0x1d, 0xba, 0x2a + +# define DRBG_TEST_GENERATED_INTERM \ + 0xdc, 0x3c, 0xf6, 0xbf, 0x5b, 0xd3, 0x41, 0x13, 0x5f, 0x2c, 0x68, 0x11, 0xa1, \ + 0x07, 0x1c, 0x87 + +# define DRBG_TEST_GENERATED \ + 0xb6, 0x18, 0x50, 0xde, 0xcf, 0xd7, 0x10, 0x6d, 0x44, 0x76, 0x9a, 0x8e, 0x6e, \ + 0x8c, 0x1a, 0xd4 + +#endif + +#endif // _MSBN_DRBG_TEST_VECTORS_H \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/RsaTestData.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/RsaTestData.h new file mode 100644 index 0000000..3dc6cd3 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/RsaTestData.h @@ -0,0 +1,519 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +// +// RSA Test Vectors + +#define RSA_TEST_KEY_SIZE 256 + +typedef struct +{ + UINT16 size; + BYTE buffer[RSA_TEST_KEY_SIZE]; +} TPM2B_RSA_TEST_KEY; + +typedef TPM2B_RSA_TEST_KEY TPM2B_RSA_TEST_VALUE; + +typedef struct +{ + UINT16 size; + BYTE buffer[RSA_TEST_KEY_SIZE / 2]; +} TPM2B_RSA_TEST_PRIME; + +const TPM2B_RSA_TEST_KEY c_rsaPublicModulus = + {256, + {0x91, 0x12, 0xf5, 0x07, 0x9d, 0x5f, 0x6b, 0x1c, 0x90, 0xf6, 0xcc, 0x87, 0xde, + 0x3a, 0x7a, 0x15, 0xdc, 0x54, 0x07, 0x6c, 0x26, 0x8f, 0x25, 0xef, 0x7e, 0x66, + 0xc0, 0xe3, 0x82, 0x12, 0x2f, 0xab, 0x52, 0x82, 0x1e, 0x85, 0xbc, 0x53, 0xba, + 0x2b, 0x01, 0xad, 0x01, 0xc7, 0x8d, 0x46, 0x4f, 0x7d, 0xdd, 0x7e, 0xdc, 0xb0, + 0xad, 0xf6, 0x0c, 0xa1, 0x62, 0x92, 0x97, 0x8a, 0x3e, 0x6f, 0x7e, 0x3e, 0xf6, + 0x9a, 0xcc, 0xf9, 0xa9, 0x86, 0x77, 0xb6, 0x85, 0x43, 0x42, 0x04, 0x13, 0x65, + 0xe2, 0xad, 0x36, 0xc9, 0xbf, 0xc1, 0x97, 0x84, 0x6f, 0xee, 0x7c, 0xda, 0x58, + 0xd2, 0xae, 0x07, 0x00, 0xaf, 0xc5, 0x5f, 0x4d, 0x3a, 0x98, 0xb0, 0xed, 0x27, + 0x7c, 0xc2, 0xce, 0x26, 0x5d, 0x87, 0xe1, 0xe3, 0xa9, 0x69, 0x88, 0x4f, 0x8c, + 0x08, 0x31, 0x18, 0xae, 0x93, 0x16, 0xe3, 0x74, 0xde, 0xd3, 0xf6, 0x16, 0xaf, + 0xa3, 0xac, 0x37, 0x91, 0x8d, 0x10, 0xc6, 0x6b, 0x64, 0x14, 0x3a, 0xd9, 0xfc, + 0xe4, 0xa0, 0xf2, 0xd1, 0x01, 0x37, 0x4f, 0x4a, 0xeb, 0xe5, 0xec, 0x98, 0xc5, + 0xd9, 0x4b, 0x30, 0xd2, 0x80, 0x2a, 0x5a, 0x18, 0x5a, 0x7d, 0xd4, 0x3d, 0xb7, + 0x62, 0x98, 0xce, 0x6d, 0xa2, 0x02, 0x6e, 0x45, 0xaa, 0x95, 0x73, 0xe0, 0xaa, + 0x75, 0x57, 0xb1, 0x3d, 0x1b, 0x05, 0x75, 0x23, 0x6b, 0x20, 0x69, 0x9e, 0x14, + 0xb0, 0x7f, 0xac, 0xae, 0xd2, 0xc7, 0x48, 0x3b, 0xe4, 0x56, 0x11, 0x34, 0x1e, + 0x05, 0x1a, 0x30, 0x20, 0xef, 0x68, 0x93, 0x6b, 0x9d, 0x7e, 0xdd, 0xba, 0x96, + 0x50, 0xcc, 0x1c, 0x81, 0xb4, 0x59, 0xb9, 0x74, 0x36, 0xd9, 0x97, 0xdc, 0x8f, + 0x17, 0x82, 0x72, 0xb3, 0x59, 0xf6, 0x23, 0xfa, 0x84, 0xf7, 0x6d, 0xf2, 0x05, + 0xff, 0xf1, 0xb9, 0xcc, 0xe9, 0xa2, 0x82, 0x01, 0xfb}}; + +const TPM2B_RSA_TEST_PRIME c_rsaPrivatePrime = + {RSA_TEST_KEY_SIZE / 2, + {0xb7, 0xa0, 0x90, 0xc7, 0x92, 0x09, 0xde, 0x71, 0x03, 0x37, 0x4a, 0xb5, 0x2f, + 0xda, 0x61, 0xb8, 0x09, 0x1b, 0xba, 0x99, 0x70, 0x45, 0xc1, 0x0b, 0x15, 0x12, + 0x71, 0x8a, 0xb3, 0x2a, 0x4d, 0x5a, 0x41, 0x9b, 0x73, 0x89, 0x80, 0x0a, 0x8f, + 0x18, 0x4c, 0x8b, 0xa2, 0x5b, 0xda, 0xbd, 0x43, 0xbe, 0xdc, 0x76, 0x4d, 0x71, + 0x0f, 0xb9, 0xfc, 0x7a, 0x09, 0xfe, 0x4f, 0xac, 0x63, 0xd9, 0x2e, 0x50, 0x3a, + 0xa1, 0x37, 0xc6, 0xf2, 0xa1, 0x89, 0x12, 0xe7, 0x72, 0x64, 0x2b, 0xba, 0xc1, + 0x1f, 0xca, 0x9d, 0xb7, 0xaa, 0x3a, 0xa9, 0xd3, 0xa6, 0x6f, 0x73, 0x02, 0xbb, + 0x85, 0x5d, 0x9a, 0xb9, 0x5c, 0x08, 0x83, 0x22, 0x20, 0x49, 0x91, 0x5f, 0x4b, + 0x86, 0xbc, 0x3f, 0x76, 0x43, 0x08, 0x97, 0xbf, 0x82, 0x55, 0x36, 0x2d, 0x8b, + 0x6e, 0x9e, 0xfb, 0xc1, 0x67, 0x6a, 0x43, 0xa2, 0x46, 0x81, 0x71}}; + +const BYTE c_RsaTestValue[RSA_TEST_KEY_SIZE] = + {0x2a, 0x24, 0x3a, 0xbb, 0x50, 0x1d, 0xd4, 0x2a, 0xf9, 0x18, 0x32, 0x34, 0xa2, + 0x0f, 0xea, 0x5c, 0x91, 0x77, 0xe9, 0xe1, 0x09, 0x83, 0xdc, 0x5f, 0x71, 0x64, + 0x5b, 0xeb, 0x57, 0x79, 0xa0, 0x41, 0xc9, 0xe4, 0x5a, 0x0b, 0xf4, 0x9f, 0xdb, + 0x84, 0x04, 0xa6, 0x48, 0x24, 0xf6, 0x3f, 0x66, 0x1f, 0xa8, 0x04, 0x5c, 0xf0, + 0x7a, 0x6b, 0x4a, 0x9c, 0x7e, 0x21, 0xb6, 0xda, 0x6b, 0x65, 0x9c, 0x3a, 0x68, + 0x50, 0x13, 0x1e, 0xa4, 0xb7, 0xca, 0xec, 0xd3, 0xcc, 0xb2, 0x9b, 0x8c, 0x87, + 0xa4, 0x6a, 0xba, 0xc2, 0x06, 0x3f, 0x40, 0x48, 0x7b, 0xa8, 0xb8, 0x2c, 0x03, + 0x14, 0x33, 0xf3, 0x1d, 0xe9, 0xbd, 0x6f, 0x54, 0x66, 0xb4, 0x69, 0x5e, 0xbc, + 0x80, 0x7c, 0xe9, 0x6a, 0x43, 0x7f, 0xb8, 0x6a, 0xa0, 0x5f, 0x5d, 0x7a, 0x20, + 0xfd, 0x7a, 0x39, 0xe1, 0xea, 0x0e, 0x94, 0x91, 0x28, 0x63, 0x7a, 0xac, 0xc9, + 0xa5, 0x3a, 0x6d, 0x31, 0x7b, 0x7c, 0x54, 0x56, 0x99, 0x56, 0xbb, 0xb7, 0xa1, + 0x2d, 0xd2, 0x5c, 0x91, 0x5f, 0x1c, 0xd3, 0x06, 0x7f, 0x34, 0x53, 0x2f, 0x4c, + 0xd1, 0x8b, 0xd2, 0x9e, 0xdc, 0xc3, 0x94, 0x0a, 0xe1, 0x0f, 0xa5, 0x15, 0x46, + 0x2a, 0x8e, 0x10, 0xc2, 0xfe, 0xb7, 0x5e, 0x2d, 0x0d, 0xd1, 0x25, 0xfc, 0xe4, + 0xf7, 0x02, 0x19, 0xfe, 0xb6, 0xe4, 0x95, 0x9c, 0x17, 0x4a, 0x9b, 0xdb, 0xab, + 0xc7, 0x79, 0xe3, 0x5e, 0x40, 0xd0, 0x56, 0x6d, 0x25, 0x0a, 0x72, 0x65, 0x80, + 0x92, 0x9a, 0xa8, 0x07, 0x70, 0x32, 0x14, 0xfb, 0xfe, 0x08, 0xeb, 0x13, 0xb4, + 0x07, 0x68, 0xb4, 0x58, 0x39, 0xbe, 0x8e, 0x78, 0x3a, 0x59, 0x3f, 0x9c, 0x4c, + 0xe9, 0xa8, 0x64, 0x68, 0xf7, 0xb9, 0x6e, 0x20, 0xf5, 0xcb, 0xca, 0x47, 0xf2, + 0x17, 0xaa, 0x8b, 0xbc, 0x13, 0x14, 0x84, 0xf6, 0xab}; + +const TPM2B_RSA_TEST_VALUE c_RsaepKvt = + {RSA_TEST_KEY_SIZE, + {0x73, 0xbd, 0x65, 0x49, 0xda, 0x7b, 0xb8, 0x50, 0x9e, 0x87, 0xf0, 0x0a, 0x8a, + 0x9a, 0x07, 0xb6, 0x00, 0x82, 0x10, 0x14, 0x60, 0xd8, 0x01, 0xfc, 0xc5, 0x18, + 0xea, 0x49, 0x5f, 0x13, 0xcf, 0x65, 0x66, 0x30, 0x6c, 0x60, 0x3f, 0x24, 0x3c, + 0xfb, 0xe2, 0x31, 0x16, 0x99, 0x7e, 0x31, 0x98, 0xab, 0x93, 0xb8, 0x07, 0x53, + 0xcc, 0xdb, 0x7f, 0x44, 0xd9, 0xee, 0x5d, 0xe8, 0x5f, 0x97, 0x5f, 0xe8, 0x1f, + 0x88, 0x52, 0x24, 0x7b, 0xac, 0x62, 0x95, 0xb7, 0x7d, 0xf5, 0xf8, 0x9f, 0x5a, + 0xa8, 0x24, 0x9a, 0x76, 0x71, 0x2a, 0x35, 0x2a, 0xa1, 0x08, 0xbb, 0x95, 0xe3, + 0x64, 0xdc, 0xdb, 0xc2, 0x33, 0xa9, 0x5f, 0xbe, 0x4c, 0xc4, 0xcc, 0x28, 0xc9, + 0x25, 0xff, 0xee, 0x17, 0x15, 0x9a, 0x50, 0x90, 0x0e, 0x15, 0xb4, 0xea, 0x6a, + 0x09, 0xe6, 0xff, 0xa4, 0xee, 0xc7, 0x7e, 0xce, 0xa9, 0x73, 0xe4, 0xa0, 0x56, + 0xbd, 0x53, 0x2a, 0xe4, 0xc0, 0x2b, 0xa8, 0x9b, 0x09, 0x30, 0x72, 0x62, 0x0f, + 0xf9, 0xf6, 0xa1, 0x52, 0xd2, 0x8a, 0x37, 0xee, 0xa5, 0xc8, 0x47, 0xe1, 0x99, + 0x21, 0x47, 0xeb, 0xdd, 0x37, 0xaa, 0xe4, 0xbd, 0x55, 0x46, 0x5a, 0x5a, 0x5d, + 0xfb, 0x7b, 0xfc, 0xff, 0xbf, 0x26, 0x71, 0xf6, 0x1e, 0xad, 0xbc, 0xbf, 0x33, + 0xca, 0xe1, 0x92, 0x8f, 0x2a, 0x89, 0x6c, 0x45, 0x24, 0xd1, 0xa6, 0x52, 0x56, + 0x24, 0x5e, 0x90, 0x47, 0xe5, 0xcb, 0x12, 0xb0, 0x32, 0xf9, 0xa6, 0xbb, 0xea, + 0x37, 0xa9, 0xbd, 0xef, 0x23, 0xef, 0x63, 0x07, 0x6c, 0xc4, 0x4e, 0x64, 0x3c, + 0xc6, 0x11, 0x84, 0x7d, 0x65, 0xd6, 0x5d, 0x7a, 0x17, 0x58, 0xa5, 0xf7, 0x74, + 0x3b, 0x42, 0xe3, 0xd2, 0xda, 0x5f, 0x6f, 0xe0, 0x1e, 0x4b, 0xcf, 0x46, 0xe2, + 0xdf, 0x3e, 0x41, 0x8e, 0x0e, 0xb0, 0x3f, 0x8b, 0x65}}; + +#define OAEP_TEST_LABEL "OAEP Test Value" + +#if ALG_SHA1_VALUE == DEFAULT_TEST_HASH + +const TPM2B_RSA_TEST_VALUE c_OaepKvt = + {RSA_TEST_KEY_SIZE, + {0x32, 0x68, 0x84, 0x0b, 0x9c, 0xc9, 0x25, 0x26, 0xd9, 0xc0, 0xd0, 0xb1, 0xde, + 0x60, 0x55, 0xae, 0x33, 0xe5, 0xcf, 0x6c, 0x85, 0xbe, 0x0d, 0x71, 0x11, 0xe1, + 0x45, 0x60, 0xbb, 0x42, 0x3d, 0xf3, 0xb1, 0x18, 0x84, 0x7b, 0xc6, 0x5d, 0xce, + 0x1d, 0x5f, 0x9a, 0x97, 0xcf, 0xb1, 0x97, 0x9a, 0x85, 0x7c, 0xa7, 0xa1, 0x63, + 0x23, 0xb6, 0x74, 0x0f, 0x1a, 0xee, 0x29, 0x51, 0xeb, 0x50, 0x8f, 0x3c, 0x8e, + 0x4e, 0x31, 0x38, 0xdc, 0x11, 0xfc, 0x9a, 0x4e, 0xaf, 0x93, 0xc9, 0x7f, 0x6e, + 0x35, 0xf3, 0xc9, 0xe4, 0x89, 0x14, 0x53, 0xe2, 0xc2, 0x1a, 0xf7, 0x6b, 0x9b, + 0xf0, 0x7a, 0xa4, 0x69, 0x52, 0xe0, 0x24, 0x8f, 0xea, 0x31, 0xa7, 0x5c, 0x43, + 0xb0, 0x65, 0xc9, 0xfe, 0xba, 0xfe, 0x80, 0x9e, 0xa5, 0xc0, 0xf5, 0x8d, 0xce, + 0x41, 0xf9, 0x83, 0x0d, 0x8e, 0x0f, 0xef, 0x3d, 0x1f, 0x6a, 0xcc, 0x8a, 0x3d, + 0x3b, 0xdf, 0x22, 0x38, 0xd7, 0x34, 0x58, 0x7b, 0x55, 0xc9, 0xf6, 0xbc, 0x7c, + 0x4c, 0x3f, 0xd7, 0xde, 0x4e, 0x30, 0xa9, 0x69, 0xf3, 0x5f, 0x56, 0x8f, 0xc2, + 0xe7, 0x75, 0x79, 0xb8, 0xa5, 0xc8, 0x0d, 0xc0, 0xcd, 0xb6, 0xc9, 0x63, 0xad, + 0x7c, 0xe4, 0x8f, 0x39, 0x60, 0x4d, 0x7d, 0xdb, 0x34, 0x49, 0x2a, 0x47, 0xde, + 0xc0, 0x42, 0x4a, 0x19, 0x94, 0x2e, 0x50, 0x21, 0x03, 0x47, 0xff, 0x73, 0xb3, + 0xb7, 0x89, 0xcc, 0x7b, 0x2c, 0xeb, 0x03, 0xa7, 0x9a, 0x06, 0xfd, 0xed, 0x19, + 0xbb, 0x82, 0xa0, 0x13, 0xe9, 0xfa, 0xac, 0x06, 0x5f, 0xc5, 0xa9, 0x2b, 0xda, + 0x88, 0x23, 0xa2, 0x5d, 0xc2, 0x7f, 0xda, 0xc8, 0x5a, 0x94, 0x31, 0xc1, 0x21, + 0xd7, 0x1e, 0x6b, 0xd7, 0x89, 0xb1, 0x93, 0x80, 0xab, 0xd1, 0x37, 0xf2, 0x6f, + 0x50, 0xcd, 0x2a, 0xea, 0xb1, 0xc4, 0xcd, 0xcb, 0xb5}}; + +const TPM2B_RSA_TEST_VALUE c_RsaesKvt = + {RSA_TEST_KEY_SIZE, + {0x29, 0xa4, 0x2f, 0xbb, 0x8a, 0x14, 0x05, 0x1e, 0x3c, 0x72, 0x76, 0x77, 0x38, + 0xe7, 0x73, 0xe3, 0x6e, 0x24, 0x4b, 0x38, 0xd2, 0x1a, 0xcf, 0x23, 0x58, 0x78, + 0x36, 0x82, 0x23, 0x6e, 0x6b, 0xef, 0x2c, 0x3d, 0xf2, 0xe8, 0xd6, 0xc6, 0x87, + 0x8e, 0x78, 0x9b, 0x27, 0x39, 0xc0, 0xd6, 0xef, 0x4d, 0x0b, 0xfc, 0x51, 0x27, + 0x18, 0xf3, 0x51, 0x5e, 0x4d, 0x96, 0x3a, 0xe2, 0x15, 0xe2, 0x7e, 0x42, 0xf4, + 0x16, 0xd5, 0xc6, 0x52, 0x5d, 0x17, 0x44, 0x76, 0x09, 0x7a, 0xcf, 0xe3, 0x30, + 0xe3, 0x84, 0xf6, 0x6f, 0x3a, 0x33, 0xfb, 0x32, 0x0d, 0x1d, 0xe7, 0x7c, 0x80, + 0x82, 0x4f, 0xed, 0xda, 0x87, 0x11, 0x9c, 0xc3, 0x7e, 0x85, 0xbd, 0x18, 0x58, + 0x08, 0x2b, 0x23, 0x37, 0xe7, 0x9d, 0xd0, 0xd1, 0x79, 0xe2, 0x05, 0xbd, 0xf5, + 0x4f, 0x0e, 0x0f, 0xdb, 0x4a, 0x74, 0xeb, 0x09, 0x01, 0xb3, 0xca, 0xbd, 0xa6, + 0x7b, 0x09, 0xb1, 0x13, 0x77, 0x30, 0x4d, 0x87, 0x41, 0x06, 0x57, 0x2e, 0x5f, + 0x36, 0x6e, 0xfc, 0x35, 0x69, 0xfe, 0x0a, 0x24, 0x6c, 0x98, 0x8c, 0xda, 0x97, + 0xf4, 0xfb, 0xc7, 0x83, 0x2d, 0x3e, 0x7d, 0xc0, 0x5c, 0x34, 0xfd, 0x11, 0x2a, + 0x12, 0xa7, 0xae, 0x4a, 0xde, 0xc8, 0x4e, 0xcf, 0xf4, 0x85, 0x63, 0x77, 0xc6, + 0x33, 0x34, 0xe0, 0x27, 0xe4, 0x9e, 0x91, 0x0b, 0x4b, 0x85, 0xf0, 0xb0, 0x79, + 0xaa, 0x7c, 0xc6, 0xff, 0x3b, 0xbc, 0x04, 0x73, 0xb8, 0x95, 0xd7, 0x31, 0x54, + 0x3b, 0x56, 0xec, 0x52, 0x15, 0xd7, 0x3e, 0x62, 0xf5, 0x82, 0x99, 0x3e, 0x2a, + 0xc0, 0x4b, 0x2e, 0x06, 0x57, 0x6d, 0x3f, 0x3e, 0x77, 0x1f, 0x2b, 0x2d, 0xc5, + 0xb9, 0x3b, 0x68, 0x56, 0x73, 0x70, 0x32, 0x6b, 0x6b, 0x65, 0x25, 0x76, 0x45, + 0x6c, 0x45, 0xf1, 0x6c, 0x59, 0xfc, 0x94, 0xa7, 0x15}}; + +const TPM2B_RSA_TEST_VALUE c_RsapssKvt = + {RSA_TEST_KEY_SIZE, + {0x01, 0xfe, 0xd5, 0x83, 0x0b, 0x15, 0xba, 0x90, 0x2c, 0xdf, 0xf7, 0x26, 0xb7, + 0x8f, 0xb1, 0xd7, 0x0b, 0xfd, 0x83, 0xf9, 0x95, 0xd5, 0xd7, 0xb5, 0xc5, 0xc5, + 0x4a, 0xde, 0xd5, 0xe6, 0x20, 0x78, 0xca, 0x73, 0x77, 0x3d, 0x61, 0x36, 0x48, + 0xae, 0x3e, 0x8f, 0xee, 0x43, 0x29, 0x96, 0xdf, 0x3f, 0x1c, 0x97, 0x5a, 0xbe, + 0xe5, 0xa2, 0x7e, 0x5b, 0xd0, 0xc0, 0x29, 0x39, 0x83, 0x81, 0x77, 0x24, 0x43, + 0xdb, 0x3c, 0x64, 0x4d, 0xf0, 0x23, 0xe4, 0xae, 0x0f, 0x78, 0x31, 0x8c, 0xda, + 0x0c, 0xec, 0xf1, 0xdf, 0x09, 0xf2, 0x14, 0x6a, 0x4d, 0xaf, 0x36, 0x81, 0x6e, + 0xbd, 0xbe, 0x36, 0x79, 0x88, 0x98, 0xb6, 0x6f, 0x5a, 0xad, 0xcf, 0x7c, 0xee, + 0xe0, 0xdd, 0x00, 0xbe, 0x59, 0x97, 0x88, 0x00, 0x34, 0xc0, 0x8b, 0x48, 0x42, + 0x05, 0x04, 0x5a, 0xb7, 0x85, 0x38, 0xa0, 0x35, 0xd7, 0x3b, 0x51, 0xb8, 0x7b, + 0x81, 0x83, 0xee, 0xff, 0x76, 0x6f, 0x50, 0x39, 0x4d, 0xab, 0x89, 0x63, 0x07, + 0x6d, 0xf5, 0xe5, 0x01, 0x10, 0x56, 0xfe, 0x93, 0x06, 0x8f, 0xd3, 0xc9, 0x41, + 0xab, 0xc9, 0xdf, 0x6e, 0x59, 0xa8, 0xc3, 0x1d, 0xbf, 0x96, 0x4a, 0x59, 0x80, + 0x3c, 0x90, 0x3a, 0x59, 0x56, 0x4c, 0x6d, 0x44, 0x6d, 0xeb, 0xdc, 0x73, 0xcd, + 0xc1, 0xec, 0xb8, 0x41, 0xbf, 0x89, 0x8c, 0x03, 0x69, 0x4c, 0xaf, 0x3f, 0xc1, + 0xc5, 0xc7, 0xe7, 0x7d, 0xa7, 0x83, 0x39, 0x70, 0xa2, 0x6b, 0x83, 0xbc, 0xbe, + 0xf5, 0xbf, 0x1c, 0xee, 0x6e, 0xa3, 0x22, 0x1e, 0x25, 0x2f, 0x16, 0x68, 0x69, + 0x5a, 0x1d, 0xfa, 0x2c, 0x3a, 0x0f, 0x67, 0xe1, 0x77, 0x12, 0xe8, 0x3d, 0xba, + 0xaa, 0xef, 0x96, 0x9c, 0x1f, 0x64, 0x32, 0xf4, 0xa7, 0xb3, 0x3f, 0x7d, 0x61, + 0xbb, 0x9a, 0x27, 0xad, 0xfb, 0x2f, 0x33, 0xc4, 0x70}}; + +const TPM2B_RSA_TEST_VALUE c_RsassaKvt = + {RSA_TEST_KEY_SIZE, + {0x67, 0x4e, 0xdd, 0xc2, 0xd2, 0x6d, 0xe0, 0x03, 0xc4, 0xc2, 0x41, 0xd3, 0xd4, + 0x61, 0x30, 0xd0, 0xe1, 0x68, 0x31, 0x4a, 0xda, 0xd9, 0xc2, 0x5d, 0xaa, 0xa2, + 0x7b, 0xfb, 0x44, 0x02, 0xf5, 0xd6, 0xd8, 0x2e, 0xcd, 0x13, 0x36, 0xc9, 0x4b, + 0xdb, 0x1a, 0x4b, 0x66, 0x1b, 0x4f, 0x9c, 0xb7, 0x17, 0xac, 0x53, 0x37, 0x4f, + 0x21, 0xbd, 0x0c, 0x66, 0xac, 0x06, 0x65, 0x52, 0x9f, 0x04, 0xf6, 0xa5, 0x22, + 0x5b, 0xf7, 0xe6, 0x0d, 0x3c, 0x9f, 0x41, 0x19, 0x09, 0x88, 0x7c, 0x41, 0x4c, + 0x2f, 0x9c, 0x8b, 0x3c, 0xdd, 0x7c, 0x28, 0x78, 0x24, 0xd2, 0x09, 0xa6, 0x5b, + 0xf7, 0x3c, 0x88, 0x7e, 0x73, 0x5a, 0x2d, 0x36, 0x02, 0x4f, 0x65, 0xb0, 0xcb, + 0xc8, 0xdc, 0xac, 0xa2, 0xda, 0x8b, 0x84, 0x91, 0x71, 0xe4, 0x30, 0x8b, 0xb6, + 0x12, 0xf2, 0xf0, 0xd0, 0xa0, 0x38, 0xcf, 0x75, 0xb7, 0x20, 0xcb, 0x35, 0x51, + 0x52, 0x6b, 0xc4, 0xf4, 0x21, 0x95, 0xc2, 0xf7, 0x9a, 0x13, 0xc1, 0x1a, 0x7b, + 0x8f, 0x77, 0xda, 0x19, 0x48, 0xbb, 0x6d, 0x14, 0x5d, 0xba, 0x65, 0xb4, 0x9e, + 0x43, 0x42, 0x58, 0x98, 0x0b, 0x91, 0x46, 0xd8, 0x4c, 0xf3, 0x4c, 0xaf, 0x2e, + 0x02, 0xa6, 0xb2, 0x49, 0x12, 0x62, 0x43, 0x4e, 0xa8, 0xac, 0xbf, 0xfd, 0xfa, + 0x37, 0x24, 0xea, 0x69, 0x1c, 0xf5, 0xae, 0xfa, 0x08, 0x82, 0x30, 0xc3, 0xc0, + 0xf8, 0x9a, 0x89, 0x33, 0xe1, 0x40, 0x6d, 0x18, 0x5c, 0x7b, 0x90, 0x48, 0xbf, + 0x37, 0xdb, 0xea, 0xfb, 0x0e, 0xd4, 0x2e, 0x11, 0xfa, 0xa9, 0x86, 0xff, 0x00, + 0x0b, 0x7b, 0xca, 0x09, 0x64, 0x6a, 0x8f, 0x0c, 0x0e, 0x09, 0x14, 0x36, 0x4a, + 0x74, 0x31, 0x18, 0x5b, 0x18, 0xeb, 0xea, 0x83, 0xc3, 0x66, 0x68, 0xa6, 0x7d, + 0x43, 0x06, 0x0f, 0x99, 0x60, 0xce, 0x65, 0x08, 0xf6}}; + +#endif // SHA1 + +#if ALG_SHA256_VALUE == DEFAULT_TEST_HASH + +const TPM2B_RSA_TEST_VALUE c_OaepKvt = + {RSA_TEST_KEY_SIZE, + {0x33, 0x20, 0x6e, 0x21, 0xc3, 0xf6, 0xcd, 0xf8, 0xd7, 0x5d, 0x9f, 0xe9, 0x05, + 0x14, 0x8c, 0x7c, 0xbb, 0x69, 0x24, 0x9e, 0x52, 0x8f, 0xaf, 0x84, 0x73, 0x21, + 0x2c, 0x85, 0xa5, 0x30, 0x4d, 0xb6, 0xb8, 0xfa, 0x15, 0x9b, 0xc7, 0x8f, 0xc9, + 0x7a, 0x72, 0x4b, 0x85, 0xa4, 0x1c, 0xc5, 0xd8, 0xe4, 0x92, 0xb3, 0xec, 0xd9, + 0xa8, 0xca, 0x5e, 0x74, 0x73, 0x89, 0x7f, 0xb4, 0xac, 0x7e, 0x68, 0x12, 0xb2, + 0x53, 0x27, 0x4b, 0xbf, 0xd0, 0x71, 0x69, 0x46, 0x9f, 0xef, 0xf4, 0x70, 0x60, + 0xf8, 0xd7, 0xae, 0xc7, 0x5a, 0x27, 0x38, 0x25, 0x2d, 0x25, 0xab, 0x96, 0x56, + 0x66, 0x3a, 0x23, 0x40, 0xa8, 0xdb, 0xbc, 0x86, 0xe8, 0xf3, 0xd2, 0x58, 0x0b, + 0x44, 0xfc, 0x94, 0x1e, 0xb7, 0x5d, 0xb4, 0x57, 0xb5, 0xf3, 0x56, 0xee, 0x9b, + 0xcf, 0x97, 0x91, 0x29, 0x36, 0xe3, 0x06, 0x13, 0xa2, 0xea, 0xd6, 0xd6, 0x0b, + 0x86, 0x0b, 0x1a, 0x27, 0xe6, 0x22, 0xc4, 0x7b, 0xff, 0xde, 0x0f, 0xbf, 0x79, + 0xc8, 0x1b, 0xed, 0xf1, 0x27, 0x62, 0xb5, 0x8b, 0xf9, 0xd9, 0x76, 0x90, 0xf6, + 0xcc, 0x83, 0x0f, 0xce, 0xce, 0x2e, 0x63, 0x7a, 0x9b, 0xf4, 0x48, 0x5b, 0xd7, + 0x81, 0x2c, 0x3a, 0xdb, 0x59, 0x0d, 0x4d, 0x9e, 0x46, 0xe9, 0x9e, 0x92, 0x22, + 0x27, 0x1c, 0xb0, 0x67, 0x8a, 0xe6, 0x8a, 0x16, 0x8a, 0xdf, 0x95, 0x76, 0x24, + 0x82, 0xad, 0xf1, 0xbc, 0x97, 0xbf, 0xd3, 0x5e, 0x6e, 0x14, 0x0c, 0x5b, 0x25, + 0xfe, 0x58, 0xfa, 0x64, 0xe5, 0x14, 0x46, 0xb7, 0x58, 0xc6, 0x3f, 0x7f, 0x42, + 0xd2, 0x8e, 0x45, 0x13, 0x41, 0x85, 0x12, 0x2e, 0x96, 0x19, 0xd0, 0x5e, 0x7d, + 0x34, 0x06, 0x32, 0x2b, 0xc8, 0xd9, 0x0d, 0x6c, 0x06, 0x36, 0xa0, 0xff, 0x47, + 0x57, 0x2c, 0x25, 0xbc, 0x8a, 0xa5, 0xe2, 0xc7, 0xe3}}; + +const TPM2B_RSA_TEST_VALUE c_RsaesKvt = + {RSA_TEST_KEY_SIZE, + {0x39, 0xfc, 0x10, 0x5d, 0xf4, 0x45, 0x3d, 0x94, 0x53, 0x06, 0x89, 0x24, 0xe7, + 0xe8, 0xfd, 0x03, 0xac, 0xfd, 0xbd, 0xb2, 0x28, 0xd3, 0x4a, 0x52, 0xc5, 0xd4, + 0xdb, 0x17, 0xd4, 0x24, 0x05, 0xc4, 0xeb, 0x6a, 0xce, 0x1d, 0xbb, 0x37, 0xcb, + 0x09, 0xd8, 0x6c, 0x83, 0x19, 0x93, 0xd4, 0xe2, 0x88, 0x88, 0x9b, 0xaf, 0x92, + 0x16, 0xc4, 0x15, 0xbd, 0x49, 0x13, 0x22, 0xb7, 0x84, 0xcf, 0x23, 0xf2, 0x6f, + 0x0c, 0x3e, 0x8f, 0xde, 0x04, 0x09, 0x31, 0x2d, 0x99, 0xdf, 0xe6, 0x74, 0x70, + 0x30, 0xde, 0x8c, 0xad, 0x32, 0x86, 0xe2, 0x7c, 0x12, 0x90, 0x21, 0xf3, 0x86, + 0xb7, 0xe2, 0x64, 0xca, 0x98, 0xcc, 0x64, 0x4b, 0xef, 0x57, 0x4f, 0x5a, 0x16, + 0x6e, 0xd7, 0x2f, 0x5b, 0xf6, 0x07, 0xad, 0x33, 0xb4, 0x8f, 0x3b, 0x3a, 0x8b, + 0xd9, 0x06, 0x2b, 0xed, 0x3c, 0x3c, 0x76, 0xf6, 0x21, 0x31, 0xe3, 0xfb, 0x2c, + 0x45, 0x61, 0x42, 0xba, 0xe0, 0xc3, 0x72, 0x63, 0xd0, 0x6b, 0x8f, 0x36, 0x26, + 0xfb, 0x9e, 0x89, 0x0e, 0x44, 0x9a, 0xc1, 0x84, 0x5e, 0x84, 0x8d, 0xb6, 0xea, + 0xf1, 0x0d, 0x66, 0xc7, 0xdb, 0x44, 0xbd, 0x19, 0x7c, 0x05, 0xbe, 0xc4, 0xab, + 0x88, 0x32, 0xbe, 0xc7, 0x63, 0x31, 0xe6, 0x38, 0xd4, 0xe5, 0xb8, 0x4b, 0xf5, + 0x0e, 0x55, 0x9a, 0x3a, 0xe6, 0x0a, 0xec, 0xee, 0xe2, 0xa8, 0x88, 0x04, 0xf2, + 0xb8, 0xaa, 0x5a, 0xd8, 0x97, 0x5d, 0xa0, 0xa8, 0x42, 0xfb, 0xd9, 0xde, 0x80, + 0xae, 0x4c, 0xb3, 0xa1, 0x90, 0x47, 0x57, 0x03, 0x10, 0x78, 0xa6, 0x8f, 0x11, + 0xba, 0x4b, 0xce, 0x2d, 0x56, 0xa4, 0xe1, 0xbd, 0xf8, 0xa0, 0xa4, 0xd5, 0x48, + 0x3c, 0x63, 0x20, 0x00, 0x38, 0xa0, 0xd1, 0xe6, 0x12, 0xe9, 0x1d, 0xd8, 0x49, + 0xe3, 0xd5, 0x24, 0xb5, 0xc5, 0x3a, 0x1f, 0xb0, 0xd4}}; + +const TPM2B_RSA_TEST_VALUE c_RsapssKvt = + {RSA_TEST_KEY_SIZE, + {0x74, 0x89, 0x29, 0x3e, 0x1b, 0xac, 0xc6, 0x85, 0xca, 0xf0, 0x63, 0x43, 0x30, + 0x7d, 0x1c, 0x9b, 0x2f, 0xbd, 0x4d, 0x69, 0x39, 0x5e, 0x85, 0xe2, 0xef, 0x86, + 0x0a, 0xc6, 0x6b, 0xa6, 0x08, 0x19, 0x6c, 0x56, 0x38, 0x24, 0x55, 0x92, 0x84, + 0x9b, 0x1b, 0x8b, 0x04, 0xcf, 0x24, 0x14, 0x24, 0x13, 0x0e, 0x8b, 0x82, 0x6f, + 0x96, 0xc8, 0x9a, 0x68, 0xfc, 0x4c, 0x02, 0xf0, 0xdc, 0xcd, 0x36, 0x25, 0x31, + 0xd5, 0x82, 0xcf, 0xc9, 0x69, 0x72, 0xf6, 0x1d, 0xab, 0x68, 0x20, 0x2e, 0x2d, + 0x19, 0x49, 0xf0, 0x2e, 0xad, 0xd2, 0xda, 0xaf, 0xff, 0xb6, 0x92, 0x83, 0x5b, + 0x8a, 0x06, 0x2d, 0x0c, 0x32, 0x11, 0x32, 0x3b, 0x77, 0x17, 0xf6, 0x50, 0xfb, + 0xf8, 0x57, 0xc9, 0xc7, 0x9b, 0x9e, 0xc6, 0xd1, 0xa9, 0x55, 0xf0, 0x22, 0x35, + 0xda, 0xca, 0x3c, 0x8e, 0xc6, 0x9a, 0xd8, 0x25, 0xc8, 0x5e, 0x93, 0x0d, 0xaa, + 0xa7, 0x06, 0xaf, 0x11, 0x29, 0x99, 0xe7, 0x7c, 0xee, 0x49, 0x82, 0x30, 0xba, + 0x2c, 0xe2, 0x40, 0x8f, 0x0a, 0xa6, 0x7b, 0x24, 0x75, 0xc5, 0xcd, 0x03, 0x12, + 0xf4, 0xb2, 0x4b, 0x3a, 0xd1, 0x91, 0x3c, 0x20, 0x0e, 0x58, 0x2b, 0x31, 0xf8, + 0x8b, 0xee, 0xbc, 0x1f, 0x95, 0x35, 0x58, 0x6a, 0x73, 0xee, 0x99, 0xb0, 0x01, + 0x42, 0x4f, 0x66, 0xc0, 0x66, 0xbb, 0x35, 0x86, 0xeb, 0xd9, 0x7b, 0x55, 0x77, + 0x2d, 0x54, 0x78, 0x19, 0x49, 0xe8, 0xcc, 0xfd, 0xb1, 0xcb, 0x49, 0xc9, 0xea, + 0x20, 0xab, 0xed, 0xb5, 0xed, 0xfe, 0xb2, 0xb5, 0xa8, 0xcf, 0x05, 0x06, 0xd5, + 0x7d, 0x2b, 0xbb, 0x0b, 0x65, 0x6b, 0x2b, 0x6d, 0x55, 0x95, 0x85, 0x44, 0x8b, + 0x12, 0x05, 0xf3, 0x4b, 0xd4, 0x8e, 0x3d, 0x68, 0x2d, 0x29, 0x9c, 0x05, 0x79, + 0xd6, 0xfc, 0x72, 0x90, 0x6a, 0xab, 0x46, 0x38, 0x81}}; + +const TPM2B_RSA_TEST_VALUE c_RsassaKvt = + {RSA_TEST_KEY_SIZE, + {0x8a, 0xb1, 0x0a, 0xb5, 0xe4, 0x02, 0xf7, 0xdd, 0x45, 0x2a, 0xcc, 0x2b, 0x6b, + 0x8c, 0x0e, 0x9a, 0x92, 0x4f, 0x9b, 0xc5, 0xe4, 0x8b, 0x82, 0xb9, 0xb0, 0xd9, + 0x87, 0x8c, 0xcb, 0xf0, 0xb0, 0x59, 0xa5, 0x92, 0x21, 0xa0, 0xa7, 0x61, 0x5c, + 0xed, 0xa8, 0x6e, 0x22, 0x29, 0x46, 0xc7, 0x86, 0x37, 0x4b, 0x1b, 0x1e, 0x94, + 0x93, 0xc8, 0x4c, 0x17, 0x7a, 0xae, 0x59, 0x91, 0xf8, 0x83, 0x84, 0xc4, 0x8c, + 0x38, 0xc2, 0x35, 0x0e, 0x7e, 0x50, 0x67, 0x76, 0xe7, 0xd3, 0xec, 0x6f, 0x0d, + 0xa0, 0x5c, 0x2f, 0x0a, 0x80, 0x28, 0xd3, 0xc5, 0x7d, 0x2d, 0x1a, 0x0b, 0x96, + 0xd6, 0xe5, 0x98, 0x05, 0x8c, 0x4d, 0xa0, 0x1f, 0x8c, 0xb6, 0xfb, 0xb1, 0xcf, + 0xe9, 0xcb, 0x38, 0x27, 0x60, 0x64, 0x17, 0xca, 0xf4, 0x8b, 0x61, 0xb7, 0x1d, + 0xb6, 0x20, 0x9d, 0x40, 0x2a, 0x1c, 0xfd, 0x55, 0x40, 0x4b, 0x95, 0x39, 0x52, + 0x18, 0x3b, 0xab, 0x44, 0xe8, 0x83, 0x4b, 0x7c, 0x47, 0xfb, 0xed, 0x06, 0x9c, + 0xcd, 0x4f, 0xba, 0x81, 0xd6, 0xb7, 0x31, 0xcf, 0x5c, 0x23, 0xf8, 0x25, 0xab, + 0x95, 0x77, 0x0a, 0x8f, 0x46, 0xef, 0xfb, 0x59, 0xb8, 0x04, 0xd7, 0x1e, 0xf5, + 0xaf, 0x6a, 0x1a, 0x26, 0x9b, 0xae, 0xf4, 0xf5, 0x7f, 0x84, 0x6f, 0x3c, 0xed, + 0xf8, 0x24, 0x0b, 0x43, 0xd1, 0xba, 0x74, 0x89, 0x4e, 0x39, 0xfe, 0xab, 0xa5, + 0x16, 0xa5, 0x28, 0xee, 0x96, 0x84, 0x3e, 0x16, 0x6d, 0x5f, 0x4e, 0x0b, 0x7d, + 0x94, 0x16, 0x1b, 0x8c, 0xf9, 0xaa, 0x9b, 0xc0, 0x49, 0x02, 0x4c, 0x3e, 0x62, + 0xff, 0xfe, 0xa2, 0x20, 0x33, 0x5e, 0xa6, 0xdd, 0xda, 0x15, 0x2d, 0xb7, 0xcd, + 0xda, 0xff, 0xb1, 0x0b, 0x45, 0x7b, 0xd3, 0xa0, 0x42, 0x29, 0xab, 0xa9, 0x73, + 0xe9, 0xa4, 0xd9, 0x8d, 0xac, 0xa1, 0x88, 0x2c, 0x2d}}; + +#endif // SHA256 + +#if ALG_SHA384_VALUE == DEFAULT_TEST_HASH + +const TPM2B_RSA_TEST_VALUE c_OaepKvt = + {RSA_TEST_KEY_SIZE, + {0x0f, 0x3c, 0x42, 0x4d, 0x8c, 0x91, 0x96, 0x05, 0x3c, 0xfd, 0x59, 0x3b, 0x7f, + 0x29, 0xbc, 0x03, 0x67, 0xc1, 0xff, 0x74, 0xe7, 0x09, 0xf4, 0x13, 0x45, 0xbe, + 0x13, 0x1d, 0xc9, 0x86, 0x94, 0xfe, 0xed, 0xa6, 0xe8, 0x3a, 0xcb, 0x89, 0x4d, + 0xec, 0x86, 0x63, 0x4c, 0xdb, 0xf1, 0x95, 0xee, 0xc1, 0x46, 0xc5, 0x3b, 0xd8, + 0xf8, 0xa2, 0x41, 0x6a, 0x60, 0x8b, 0x9e, 0x5e, 0x7f, 0x20, 0x16, 0xe3, 0x69, + 0xb6, 0x2d, 0x92, 0xfc, 0x60, 0xa2, 0x74, 0x88, 0xd5, 0xc7, 0xa6, 0xd1, 0xff, + 0xe3, 0x45, 0x02, 0x51, 0x39, 0xd9, 0xf3, 0x56, 0x0b, 0x91, 0x80, 0xe0, 0x6c, + 0xa8, 0xc3, 0x78, 0xef, 0x34, 0x22, 0x8c, 0xf5, 0xfb, 0x47, 0x98, 0x5d, 0x57, + 0x8e, 0x3a, 0xb9, 0xff, 0x92, 0x04, 0xc7, 0xc2, 0x6e, 0xfa, 0x14, 0xc1, 0xb9, + 0x68, 0x15, 0x5c, 0x12, 0xe8, 0xa8, 0xbe, 0xea, 0xe8, 0x8d, 0x9b, 0x48, 0x28, + 0x35, 0xdb, 0x4b, 0x52, 0xc1, 0x2d, 0x85, 0x47, 0x83, 0xd0, 0xe9, 0xae, 0x90, + 0x6e, 0x65, 0xd4, 0x34, 0x7f, 0x81, 0xce, 0x69, 0xf0, 0x96, 0x62, 0xf7, 0xec, + 0x41, 0xd5, 0xc2, 0xe3, 0x4b, 0xba, 0x9c, 0x8a, 0x02, 0xce, 0xf0, 0x5d, 0x14, + 0xf7, 0x09, 0x42, 0x8e, 0x4a, 0x27, 0xfe, 0x3e, 0x66, 0x42, 0x99, 0x03, 0xe1, + 0x69, 0xbd, 0xdb, 0x7f, 0x9b, 0x70, 0xeb, 0x4e, 0x9c, 0xac, 0x45, 0x67, 0x91, + 0x9f, 0x75, 0x10, 0xc6, 0xfc, 0x14, 0xe1, 0x28, 0xc1, 0x0e, 0xe0, 0x7e, 0xc0, + 0x5c, 0x1d, 0xee, 0xe8, 0xff, 0x45, 0x79, 0x51, 0x86, 0x08, 0xe6, 0x39, 0xac, + 0xb5, 0xfd, 0xb8, 0xf1, 0xdd, 0x2e, 0xf4, 0xb2, 0x1a, 0x69, 0x0d, 0xd9, 0x98, + 0x8e, 0xdb, 0x85, 0x61, 0x70, 0x20, 0x82, 0x91, 0x26, 0x87, 0x80, 0xc4, 0x6a, + 0xd8, 0x3b, 0x91, 0x4d, 0xd3, 0x33, 0x84, 0xad, 0xb7}}; + +const TPM2B_RSA_TEST_VALUE c_RsaesKvt = + {RSA_TEST_KEY_SIZE, + {0x44, 0xd5, 0x9f, 0xbc, 0x48, 0x03, 0x3d, 0x9f, 0x22, 0x91, 0x2a, 0xab, 0x3c, + 0x31, 0x71, 0xab, 0x86, 0x3f, 0x0f, 0x6f, 0x59, 0x5b, 0x93, 0x27, 0xbc, 0xbc, + 0xcd, 0x29, 0x38, 0x43, 0x2a, 0x3b, 0x3b, 0xd2, 0xb3, 0x45, 0x40, 0xba, 0x15, + 0xb4, 0x45, 0xe3, 0x56, 0xab, 0xff, 0xb3, 0x20, 0x26, 0x39, 0xcc, 0x48, 0xc5, + 0x5d, 0x41, 0x0d, 0x2f, 0x57, 0x7f, 0x9d, 0x16, 0x2e, 0x26, 0x57, 0xc7, 0x6b, + 0xf3, 0x36, 0x54, 0xbd, 0xb6, 0x1d, 0x46, 0x4e, 0x13, 0x50, 0xd7, 0x61, 0x9d, + 0x8d, 0x7b, 0xeb, 0x21, 0x9f, 0x79, 0xf3, 0xfd, 0xe0, 0x1b, 0xa8, 0xed, 0x6d, + 0x29, 0x33, 0x0d, 0x65, 0x94, 0x24, 0x1e, 0x62, 0x88, 0x6b, 0x2b, 0x4e, 0x39, + 0xf5, 0x80, 0x39, 0xca, 0x76, 0x95, 0xbc, 0x7c, 0x27, 0x1d, 0xdd, 0x3a, 0x11, + 0xf1, 0x3e, 0x54, 0x03, 0xb7, 0x43, 0x91, 0x99, 0x33, 0xfe, 0x9d, 0x14, 0x2c, + 0x87, 0x9a, 0x95, 0x18, 0x1f, 0x02, 0x04, 0x6a, 0xe2, 0xb7, 0x81, 0x14, 0x13, + 0x45, 0x16, 0xfb, 0xe4, 0xb7, 0x8f, 0xab, 0x2b, 0xd7, 0x60, 0x34, 0x8a, 0x55, + 0xbc, 0x01, 0x8c, 0x49, 0x02, 0x29, 0xf1, 0x9c, 0x94, 0x98, 0x44, 0xd0, 0x94, + 0xcb, 0xd4, 0x85, 0x4c, 0x3b, 0x77, 0x72, 0x99, 0xd5, 0x4b, 0xc6, 0x3b, 0xe4, + 0xd2, 0xc8, 0xe9, 0x6a, 0x23, 0x18, 0x3b, 0x3b, 0x5e, 0x32, 0xec, 0x70, 0x84, + 0x5d, 0xbb, 0x6a, 0x8f, 0x0c, 0x5f, 0x55, 0xa5, 0x30, 0x34, 0x48, 0xbb, 0xc2, + 0xdf, 0x12, 0xb9, 0x81, 0xad, 0x36, 0x3f, 0xf0, 0x24, 0x16, 0x48, 0x04, 0x4a, + 0x7f, 0xfd, 0x9f, 0x4c, 0xea, 0xfe, 0x1d, 0x83, 0xd0, 0x81, 0xad, 0x25, 0x6c, + 0x5f, 0x45, 0x36, 0x91, 0xf0, 0xd5, 0x8b, 0x53, 0x0a, 0xdf, 0xec, 0x9f, 0x04, + 0x58, 0xc4, 0x35, 0xa0, 0x78, 0x1f, 0x68, 0xe0, 0x22}}; + +const TPM2B_RSA_TEST_VALUE c_RsapssKvt = + {RSA_TEST_KEY_SIZE, + {0x3f, 0x3a, 0x82, 0x6d, 0x42, 0xe3, 0x8b, 0x4f, 0x45, 0x9c, 0xda, 0x6c, 0xbe, + 0xbe, 0xcd, 0x00, 0x98, 0xfb, 0xbe, 0x59, 0x30, 0xc6, 0x3c, 0xaa, 0xb3, 0x06, + 0x27, 0xb5, 0xda, 0xfa, 0xb2, 0xc3, 0x43, 0xb7, 0xbd, 0xe9, 0xd3, 0x23, 0xed, + 0x80, 0xce, 0x74, 0xb3, 0xb8, 0x77, 0x8d, 0xe6, 0x8d, 0x3c, 0xe5, 0xf5, 0xd7, + 0x80, 0xcf, 0x38, 0x55, 0x76, 0xd7, 0x87, 0xa8, 0xd6, 0x3a, 0xcf, 0xfd, 0xd8, + 0x91, 0x65, 0xab, 0x43, 0x66, 0x50, 0xb7, 0x9a, 0x13, 0x6b, 0x45, 0x80, 0x76, + 0x86, 0x22, 0x27, 0x72, 0xf7, 0xbb, 0x65, 0x22, 0x5c, 0x55, 0x60, 0xd8, 0x84, + 0x9f, 0xf2, 0x61, 0x52, 0xac, 0xf2, 0x4f, 0x5b, 0x7b, 0x21, 0xe1, 0xf5, 0x4b, + 0x8f, 0x01, 0xf2, 0x4b, 0xcf, 0xd3, 0xfb, 0x74, 0x5e, 0x6e, 0x96, 0xb4, 0xa8, + 0x0f, 0x01, 0x9b, 0x26, 0x54, 0x0a, 0x70, 0x55, 0x26, 0xb7, 0x0b, 0xe8, 0x01, + 0x68, 0x66, 0x0d, 0x6f, 0xb5, 0xfc, 0x66, 0xbd, 0x9e, 0x44, 0xed, 0x6a, 0x1e, + 0x3c, 0x3b, 0x61, 0x5d, 0xe8, 0xdb, 0x99, 0x5b, 0x67, 0xbf, 0x94, 0xfb, 0xe6, + 0x8c, 0x4b, 0x07, 0xcb, 0x43, 0x3a, 0x0d, 0xb1, 0x1b, 0x10, 0x66, 0x81, 0xe2, + 0x0d, 0xe7, 0xd1, 0xca, 0x85, 0xa7, 0x50, 0x82, 0x2d, 0xbf, 0xed, 0xcf, 0x43, + 0x6d, 0xdb, 0x2c, 0x7b, 0x73, 0x20, 0xfe, 0x73, 0x3f, 0x19, 0xc6, 0xdb, 0x69, + 0xb8, 0xc3, 0xd3, 0xf4, 0xe5, 0x64, 0xf8, 0x36, 0x8e, 0xd5, 0xd8, 0x09, 0x2a, + 0x5f, 0x26, 0x70, 0xa1, 0xd9, 0x5b, 0x14, 0xf8, 0x22, 0xe9, 0x9d, 0x22, 0x51, + 0xf4, 0x52, 0xc1, 0x6f, 0x53, 0xf5, 0xca, 0x0d, 0xda, 0x39, 0x8c, 0x29, 0x42, + 0xe8, 0x58, 0x89, 0xbb, 0xd1, 0x2e, 0xc5, 0xdb, 0x86, 0x8d, 0xaf, 0xec, 0x58, + 0x36, 0x8d, 0x8d, 0x57, 0x23, 0xd5, 0xdd, 0xb9, 0x24}}; + +const TPM2B_RSA_TEST_VALUE c_RsassaKvt = + {RSA_TEST_KEY_SIZE, + {0x39, 0x10, 0x58, 0x7d, 0x6d, 0xa8, 0xd5, 0x90, 0x07, 0xd6, 0x2b, 0x13, 0xe9, + 0xd8, 0x93, 0x7e, 0xf3, 0x5d, 0x71, 0xe0, 0xf0, 0x33, 0x3a, 0x4a, 0x22, 0xf3, + 0xe6, 0x95, 0xd3, 0x8e, 0x8c, 0x41, 0xe7, 0xb3, 0x13, 0xde, 0x4a, 0x45, 0xd3, + 0xd1, 0xfb, 0xb1, 0x3f, 0x9b, 0x39, 0xa5, 0x50, 0x58, 0xef, 0xb6, 0x3a, 0x43, + 0xdd, 0x54, 0xab, 0xda, 0x9d, 0x32, 0x49, 0xe4, 0x57, 0x96, 0xe5, 0x1b, 0x1d, + 0x8f, 0x33, 0x8e, 0x07, 0x67, 0x56, 0x14, 0xc1, 0x18, 0x78, 0xa2, 0x52, 0xe6, + 0x2e, 0x07, 0x81, 0xbe, 0xd8, 0xca, 0x76, 0x63, 0x68, 0xc5, 0x47, 0xa2, 0x92, + 0x5e, 0x4c, 0xfd, 0x14, 0xc7, 0x46, 0x14, 0xbe, 0xc7, 0x85, 0xef, 0xe6, 0xb8, + 0x46, 0xcb, 0x3a, 0x67, 0x66, 0x89, 0xc6, 0xee, 0x9d, 0x64, 0xf5, 0x0d, 0x09, + 0x80, 0x9a, 0x6f, 0x0e, 0xeb, 0xe4, 0xb9, 0xe9, 0xab, 0x90, 0x4f, 0xe7, 0x5a, + 0xc8, 0xca, 0xf6, 0x16, 0x0a, 0x82, 0xbd, 0xb7, 0x76, 0x59, 0x08, 0x2d, 0xd9, + 0x40, 0x5d, 0xaa, 0xa5, 0xef, 0xfb, 0xe3, 0x81, 0x2c, 0x2c, 0x5c, 0xa8, 0x16, + 0xbd, 0x63, 0x20, 0xc2, 0x4d, 0x3b, 0x51, 0xaa, 0x62, 0x1f, 0x06, 0xe5, 0xbb, + 0x78, 0x44, 0x04, 0x0c, 0x5c, 0xe1, 0x1b, 0x6b, 0x9d, 0x21, 0x10, 0xaf, 0x48, + 0x48, 0x98, 0x97, 0x77, 0xc2, 0x73, 0xb4, 0x98, 0x64, 0xcc, 0x94, 0x2c, 0x29, + 0x28, 0x45, 0x36, 0xd1, 0xc5, 0xd0, 0x2f, 0x97, 0x27, 0x92, 0x65, 0x22, 0xbb, + 0x63, 0x79, 0xea, 0xf5, 0xff, 0x77, 0x0f, 0x4b, 0x56, 0x8a, 0x9f, 0xad, 0x1a, + 0x97, 0x67, 0x39, 0x69, 0xb8, 0x4c, 0x6c, 0xc2, 0x56, 0xc5, 0x7a, 0xa8, 0x14, + 0x5a, 0x24, 0x7a, 0xa4, 0x6e, 0x55, 0xb2, 0x86, 0x1d, 0xf4, 0x62, 0x5a, 0x2d, + 0x87, 0x6d, 0xde, 0x99, 0x78, 0x2d, 0xef, 0xd7, 0xdc}}; + +#endif // SHA384 + +#if ALG_SHA512_VALUE == DEFAULT_TEST_HASH + +const TPM2B_RSA_TEST_VALUE c_OaepKvt = + {RSA_TEST_KEY_SIZE, + {0x48, 0x45, 0xa7, 0x70, 0xb2, 0x41, 0xb7, 0x48, 0x5e, 0x79, 0x8c, 0xdf, 0x1c, + 0xc6, 0x7e, 0xbb, 0x11, 0x80, 0x82, 0x52, 0xbf, 0x40, 0x3d, 0x90, 0x03, 0x6e, + 0x20, 0x3a, 0xb9, 0x65, 0xc8, 0x51, 0x4c, 0xbd, 0x9c, 0xa9, 0x43, 0x89, 0xd0, + 0x57, 0x0c, 0xa3, 0x69, 0x22, 0x7e, 0x82, 0x2a, 0x1c, 0x1d, 0x5a, 0x80, 0x84, + 0x81, 0xbb, 0x5e, 0x5e, 0xd0, 0xc1, 0x66, 0x9a, 0xac, 0x00, 0xba, 0x14, 0xa2, + 0xe9, 0xd0, 0x3a, 0x89, 0x5a, 0x63, 0xe2, 0xec, 0x92, 0x05, 0xf4, 0x47, 0x66, + 0x12, 0x7f, 0xdb, 0xa7, 0x3c, 0x5b, 0x67, 0xe1, 0x55, 0xca, 0x0a, 0x27, 0xbf, + 0x39, 0x89, 0x11, 0x05, 0xba, 0x9b, 0x5a, 0x9b, 0x65, 0x44, 0xad, 0x78, 0xcf, + 0x8f, 0x94, 0xf6, 0x9a, 0xb4, 0x52, 0x39, 0x0e, 0x00, 0xba, 0xbc, 0xe0, 0xbd, + 0x6f, 0x81, 0x2d, 0x76, 0x42, 0x66, 0x70, 0x07, 0x77, 0xbf, 0x09, 0x88, 0x2a, + 0x0c, 0xb1, 0x56, 0x3e, 0xee, 0xfd, 0xdc, 0xb6, 0x3c, 0x0d, 0xc5, 0xa4, 0x0d, + 0x10, 0x32, 0x80, 0x3e, 0x1e, 0xfe, 0x36, 0x8f, 0xb5, 0x42, 0xc1, 0x21, 0x7b, + 0xdf, 0xdf, 0x4a, 0xd2, 0x68, 0x0c, 0x01, 0x9f, 0x4a, 0xfd, 0xd4, 0xec, 0xf7, + 0x49, 0x06, 0xab, 0xed, 0xc6, 0xd5, 0x1b, 0x63, 0x76, 0x38, 0xc8, 0x6c, 0xc7, + 0x4f, 0xcb, 0x29, 0x8a, 0x0e, 0x6f, 0x33, 0xaf, 0x69, 0x31, 0x8e, 0xa7, 0xdd, + 0x9a, 0x36, 0xde, 0x9b, 0xf1, 0x0b, 0xfb, 0x20, 0xa0, 0x6d, 0x33, 0x31, 0xc9, + 0x9e, 0xb4, 0x2e, 0xc5, 0x40, 0x0e, 0x60, 0x71, 0x36, 0x75, 0x05, 0xf9, 0x37, + 0xe0, 0xca, 0x8e, 0x8f, 0x56, 0xe0, 0xea, 0x9b, 0xeb, 0x17, 0xf3, 0xca, 0x40, + 0xc3, 0x48, 0x01, 0xba, 0xdc, 0xc6, 0x4b, 0x2b, 0x5b, 0x7b, 0x5c, 0x81, 0xa6, + 0xbb, 0xc7, 0x43, 0xc0, 0xbe, 0xc0, 0x30, 0x7b, 0x55}}; + +const TPM2B_RSA_TEST_VALUE c_RsaesKvt = + {RSA_TEST_KEY_SIZE, + {0x74, 0x83, 0xfa, 0x52, 0x65, 0x50, 0x68, 0xd0, 0x82, 0x05, 0x72, 0x70, 0x78, + 0x1c, 0xac, 0x10, 0x23, 0xc5, 0x07, 0xf8, 0x93, 0xd2, 0xeb, 0x65, 0x87, 0xbb, + 0x47, 0xc2, 0xfb, 0x30, 0x9e, 0x61, 0x4c, 0xac, 0x04, 0x57, 0x5a, 0x7c, 0xeb, + 0x29, 0x08, 0x84, 0x86, 0x89, 0x1e, 0x8f, 0x07, 0x32, 0xa3, 0x8b, 0x70, 0xe7, + 0xa2, 0x9f, 0x9c, 0x42, 0x71, 0x3d, 0x23, 0x59, 0x82, 0x5e, 0x8a, 0xde, 0xd6, + 0xfb, 0xd8, 0xc5, 0x8b, 0xc0, 0xdb, 0x10, 0x38, 0x87, 0xd3, 0xbf, 0x04, 0xb0, + 0x66, 0xb9, 0x85, 0x81, 0x54, 0x4c, 0x69, 0xdc, 0xba, 0x78, 0xf3, 0x4a, 0xdb, + 0x25, 0xa2, 0xf2, 0x34, 0x55, 0xdd, 0xaa, 0xa5, 0xc4, 0xed, 0x55, 0x06, 0x0e, + 0x2a, 0x30, 0x77, 0xab, 0x82, 0x79, 0xf0, 0xcd, 0x9d, 0x6f, 0x09, 0xa0, 0xc8, + 0x82, 0xc9, 0xe0, 0x61, 0xda, 0x40, 0xcd, 0x17, 0x59, 0xc0, 0xef, 0x95, 0x6d, + 0xa3, 0x6d, 0x1c, 0x2b, 0xee, 0x24, 0xef, 0xd8, 0x4a, 0x55, 0x6c, 0xd6, 0x26, + 0x42, 0x32, 0x17, 0xfd, 0x6a, 0xb3, 0x4f, 0xde, 0x07, 0x2f, 0x10, 0xd4, 0xac, + 0x14, 0xea, 0x89, 0x68, 0xcc, 0xd3, 0x07, 0xb7, 0xcf, 0xba, 0x39, 0x20, 0x63, + 0x20, 0x7b, 0x44, 0x8b, 0x48, 0x60, 0x5d, 0x3a, 0x2a, 0x0a, 0xe9, 0x68, 0xab, + 0x15, 0x46, 0x27, 0x64, 0xb5, 0x82, 0x06, 0x29, 0xe7, 0x25, 0xca, 0x46, 0x48, + 0x6e, 0x2a, 0x34, 0x57, 0x4b, 0x81, 0x75, 0xae, 0xb6, 0xfd, 0x6f, 0x51, 0x5f, + 0x04, 0x59, 0xc7, 0x15, 0x1f, 0xe0, 0x68, 0xf7, 0x36, 0x2d, 0xdf, 0xc8, 0x9d, + 0x05, 0x27, 0x2d, 0x3f, 0x2b, 0x59, 0x5d, 0xcb, 0xf3, 0xc4, 0x92, 0x6e, 0x00, + 0xa8, 0x8d, 0xd0, 0x69, 0xe5, 0x59, 0xda, 0xba, 0x4f, 0x38, 0xf5, 0xa0, 0x8b, + 0xf1, 0x73, 0xe9, 0x0d, 0xee, 0x64, 0xe5, 0xa2, 0xd8}}; + +const TPM2B_RSA_TEST_VALUE c_RsapssKvt = + {RSA_TEST_KEY_SIZE, + {0x1b, 0xca, 0x8b, 0x18, 0x15, 0x3b, 0x95, 0x5b, 0x0a, 0x89, 0x10, 0x03, 0x7f, + 0x7c, 0xa0, 0xc9, 0x66, 0x57, 0x86, 0x6a, 0xc9, 0xeb, 0x82, 0x71, 0xf3, 0x8d, + 0x6f, 0xa9, 0xa4, 0x2d, 0xd0, 0x22, 0xdf, 0xe9, 0xc6, 0x71, 0x5b, 0xf4, 0x27, + 0x38, 0x5b, 0x2c, 0x8a, 0x54, 0xcc, 0x85, 0x11, 0x69, 0x6d, 0x6f, 0x42, 0xe7, + 0x22, 0xcb, 0xd6, 0xad, 0x1a, 0xc5, 0xab, 0x6a, 0xa5, 0xfc, 0xa5, 0x70, 0x72, + 0x4a, 0x62, 0x25, 0xd0, 0xa2, 0x16, 0x61, 0xab, 0xac, 0x31, 0xa0, 0x46, 0x24, + 0x4f, 0xdd, 0x9a, 0x36, 0x55, 0xb6, 0x00, 0x9e, 0x23, 0x50, 0x0d, 0x53, 0x01, + 0xb3, 0x46, 0x56, 0xb2, 0x1d, 0x33, 0x5b, 0xca, 0x41, 0x7f, 0x65, 0x7e, 0x00, + 0x5c, 0x12, 0xff, 0x0a, 0x70, 0x5d, 0x8c, 0x69, 0x4a, 0x02, 0xee, 0x72, 0x30, + 0xa7, 0x5c, 0xa4, 0xbb, 0xbe, 0x03, 0x0c, 0xe4, 0x5f, 0x33, 0xb6, 0x78, 0x91, + 0x9d, 0xd8, 0xec, 0x34, 0x03, 0x2e, 0x63, 0x32, 0xc7, 0x2a, 0x36, 0x50, 0xd5, + 0x8b, 0x0e, 0x7f, 0x54, 0x4e, 0xf4, 0x29, 0x11, 0x1b, 0xcd, 0x0f, 0x37, 0xa5, + 0xbc, 0x61, 0x83, 0x50, 0xfa, 0x18, 0x75, 0xd9, 0xfe, 0xa7, 0xe8, 0x9b, 0xc1, + 0x4f, 0x96, 0x37, 0x81, 0x71, 0xdf, 0x71, 0x8b, 0x89, 0x81, 0xf4, 0x95, 0xb5, + 0x29, 0x66, 0x41, 0x0c, 0x73, 0xd7, 0x0b, 0x21, 0xb4, 0xfb, 0xf9, 0x63, 0x2f, + 0xe9, 0x7b, 0x38, 0xaa, 0x20, 0xc3, 0x96, 0xcc, 0xb7, 0xb2, 0x24, 0xa1, 0xe0, + 0x59, 0x9c, 0x10, 0x9e, 0x5a, 0xf7, 0xe3, 0x02, 0xe6, 0x23, 0xe2, 0x44, 0x21, + 0x3f, 0x6e, 0x5e, 0x79, 0xb2, 0x93, 0x7d, 0xce, 0xed, 0xe2, 0xe1, 0xab, 0x98, + 0x07, 0xa7, 0xbd, 0xbc, 0xd8, 0xf7, 0x06, 0xeb, 0xc5, 0xa6, 0x37, 0x18, 0x11, + 0x88, 0xf7, 0x63, 0x39, 0xb9, 0x57, 0x29, 0xdc, 0x03}}; + +const TPM2B_RSA_TEST_VALUE c_RsassaKvt = + {RSA_TEST_KEY_SIZE, + {0x05, 0x55, 0x00, 0x62, 0x01, 0xc6, 0x04, 0x31, 0x55, 0x73, 0x3f, 0x2a, 0xf9, + 0xd4, 0x0f, 0xc1, 0x2b, 0xeb, 0xd8, 0xc8, 0xdb, 0xb2, 0xab, 0x6c, 0x26, 0xde, + 0x2d, 0x89, 0xc2, 0x2d, 0x36, 0x62, 0xc8, 0x22, 0x5d, 0x58, 0x03, 0xb1, 0x46, + 0x14, 0xa5, 0xd4, 0xbc, 0x25, 0x6b, 0x7f, 0x8f, 0x14, 0x7e, 0x03, 0x2f, 0x3d, + 0xb8, 0x39, 0xa5, 0x79, 0x13, 0x7e, 0x22, 0x2a, 0xb9, 0x3e, 0x8f, 0xaa, 0x01, + 0x7c, 0x03, 0x12, 0x21, 0x6c, 0x2a, 0xb4, 0x39, 0x98, 0x6d, 0xff, 0x08, 0x6c, + 0x59, 0x2d, 0xdc, 0xc6, 0xf1, 0x77, 0x62, 0x10, 0xa6, 0xcc, 0xe2, 0x71, 0x8e, + 0x97, 0x00, 0x87, 0x5b, 0x0e, 0x20, 0x00, 0x3f, 0x18, 0x63, 0x83, 0xf0, 0xe4, + 0x0a, 0x64, 0x8c, 0xe9, 0x8c, 0x91, 0xe7, 0x89, 0x04, 0x64, 0x2c, 0x8b, 0x41, + 0xc8, 0xac, 0xf6, 0x5a, 0x75, 0xe6, 0xa5, 0x76, 0x43, 0xcb, 0xa5, 0x33, 0x8b, + 0x07, 0xc9, 0x73, 0x0f, 0x45, 0xa4, 0xc3, 0xac, 0xc1, 0xc3, 0xe6, 0xe7, 0x21, + 0x66, 0x1c, 0xba, 0xbf, 0xea, 0x3e, 0x39, 0xfa, 0xb2, 0xe2, 0x8f, 0xfe, 0x9c, + 0xb4, 0x85, 0x89, 0x33, 0x2a, 0x0c, 0xc8, 0x5d, 0x58, 0xe1, 0x89, 0x12, 0xe9, + 0x4d, 0x42, 0xb3, 0x1f, 0x99, 0x0c, 0x3e, 0xd8, 0xb2, 0xeb, 0xf5, 0x88, 0xfb, + 0xe1, 0x4b, 0x8e, 0xdc, 0xd3, 0xa8, 0xda, 0xbe, 0x04, 0x45, 0xbf, 0x56, 0xc6, + 0x54, 0x70, 0x00, 0xb8, 0x66, 0x46, 0x3a, 0xa3, 0x1e, 0xb6, 0xeb, 0x1a, 0xa0, + 0x0b, 0xd3, 0x9a, 0x9a, 0x52, 0xda, 0x60, 0x69, 0xb7, 0xef, 0x93, 0x47, 0x38, + 0xab, 0x1a, 0xa0, 0x22, 0x6e, 0x76, 0x06, 0xb6, 0x74, 0xaf, 0x74, 0x8f, 0x51, + 0xc0, 0x89, 0x5a, 0x4b, 0xbe, 0x6a, 0x91, 0x18, 0x25, 0x7d, 0xa6, 0x77, 0xe6, + 0xfd, 0xc2, 0x62, 0x36, 0x07, 0xc6, 0xef, 0x79, 0xc9}}; + +#endif // SHA512 diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/SelfTest.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/SelfTest.h new file mode 100644 index 0000000..f483932 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/SelfTest.h @@ -0,0 +1,105 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// This file contains the structure definitions for the self-test. It also contains +// macros for use when the self-test is implemented. +#ifndef _SELF_TEST_H_ +#define _SELF_TEST_H_ + +//** Defines + +// Was typing this a lot +#define SELF_TEST_FAILURE FAIL(FATAL_ERROR_SELF_TEST) + +// Use the definition of key sizes to set algorithm values for key size. +#define AES_ENTRIES (AES_128 + AES_192 + AES_256) +#define SM4_ENTRIES (SM4_128) +#define CAMELLIA_ENTRIES (CAMELLIA_128 + CAMELLIA_192 + CAMELLIA_256) +#define TDES_ENTRIES (TDES_128 + TDES_192) + +#define NUM_SYMS (AES_ENTRIES + SM4_ENTRIES + CAMELLIA_ENTRIES + TDES_ENTRIES) + +typedef UINT32 SYM_INDEX; + +// These two defines deal with the fact that the TPM_ALG_ID table does not delimit +// the symmetric mode values with a SYM_MODE_FIRST and SYM_MODE_LAST +#define SYM_MODE_FIRST ALG_CTR_VALUE +#define SYM_MODE_LAST ALG_ECB_VALUE + +#define NUM_SYM_MODES (SYM_MODE_LAST - SYM_MODE_FIRST + 1) + +// Define a type to hold a bit vector for the modes. +#if NUM_SYM_MODES <= 0 +# error "No symmetric modes implemented" +#elif NUM_SYM_MODES <= 8 +typedef BYTE SYM_MODES; +#elif NUM_SYM_MODES <= 16 +typedef UINT16 SYM_MODES; +#elif NUM_SYM_MODES <= 32 +typedef UINT32 SYM_MODES; +#else +# error "Too many symmetric modes" +#endif + +typedef struct SYMMETRIC_TEST_VECTOR +{ + const TPM_ALG_ID alg; // the algorithm + const UINT16 keyBits; // bits in the key + const BYTE* key; // The test key + const UINT32 ivSize; // block size of the algorithm + const UINT32 dataInOutSize; // size to encrypt/decrypt + const BYTE* dataIn; // data to encrypt + const BYTE* dataOut[NUM_SYM_MODES]; // data to decrypt +} SYMMETRIC_TEST_VECTOR; + +#if ALG_SHA512 +# define DEFAULT_TEST_HASH ALG_SHA512_VALUE +# define DEFAULT_TEST_DIGEST_SIZE SHA512_DIGEST_SIZE +# define DEFAULT_TEST_HASH_BLOCK_SIZE SHA512_BLOCK_SIZE +#elif ALG_SHA384 +# define DEFAULT_TEST_HASH ALG_SHA384_VALUE +# define DEFAULT_TEST_DIGEST_SIZE SHA384_DIGEST_SIZE +# define DEFAULT_TEST_HASH_BLOCK_SIZE SHA384_BLOCK_SIZE +#elif ALG_SHA256 +# define DEFAULT_TEST_HASH ALG_SHA256_VALUE +# define DEFAULT_TEST_DIGEST_SIZE SHA256_DIGEST_SIZE +# define DEFAULT_TEST_HASH_BLOCK_SIZE SHA256_BLOCK_SIZE +#elif ALG_SHA1 +# define DEFAULT_TEST_HASH ALG_SHA1_VALUE +# define DEFAULT_TEST_DIGEST_SIZE SHA1_DIGEST_SIZE +# define DEFAULT_TEST_HASH_BLOCK_SIZE SHA1_BLOCK_SIZE +#endif + +#endif // _SELF_TEST_H_ \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/SupportLibraryFunctionPrototypes_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/SupportLibraryFunctionPrototypes_fp.h new file mode 100644 index 0000000..c5cf455 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/SupportLibraryFunctionPrototypes_fp.h @@ -0,0 +1,124 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// This file contains the function prototypes for the functions that need to be +// present in the selected math library. For each function listed, there should +// be a small stub function. That stub provides the interface between the TPM +// code and the support library. In most cases, the stub function will only need +// to do a format conversion between the TPM big number and the support library +// big number. The TPM big number format was chosen to make this relatively +// simple and fast. +// +// Arithmetic operations return a BOOL to indicate if the operation completed +// successfully or not. + +#ifndef SUPPORT_LIBRARY_FUNCTION_PROTOTYPES_H +#define SUPPORT_LIBRARY_FUNCTION_PROTOTYPES_H + +//** SupportLibInit() +// This function is called by CryptInit() so that necessary initializations can be +// performed on the cryptographic library. +LIB_EXPORT +int SupportLibInit(void); + +//** MathLibraryCompatibililtyCheck() +// This function is only used during development to make sure that the library +// that is being referenced is using the same size of data structures as the TPM. +BOOL MathLibraryCompatibilityCheck(void); + +//** BnModMult() +// Does 'op1' * 'op2' and divide by 'modulus' returning the remainder of the divide. +LIB_EXPORT BOOL BnModMult( + bigNum result, bigConst op1, bigConst op2, bigConst modulus); + +//** BnMult() +// Multiplies two numbers and returns the result +LIB_EXPORT BOOL BnMult(bigNum result, bigConst multiplicand, bigConst multiplier); + +//** BnDiv() +// This function divides two bigNum values. The function returns FALSE if there is +// an error in the operation. +LIB_EXPORT BOOL BnDiv( + bigNum quotient, bigNum remainder, bigConst dividend, bigConst divisor); +//** BnMod() +#define BnMod(a, b) BnDiv(NULL, (a), (a), (b)) + +//** BnGcd() +// Get the greatest common divisor of two numbers. This function is only needed +// when the TPM implements RSA. +LIB_EXPORT BOOL BnGcd(bigNum gcd, bigConst number1, bigConst number2); + +//** BnModExp() +// Do modular exponentiation using bigNum values. This function is only needed +// when the TPM implements RSA. +LIB_EXPORT BOOL BnModExp( + bigNum result, bigConst number, bigConst exponent, bigConst modulus); +//** BnModInverse() +// Modular multiplicative inverse. This function is only needed +// when the TPM implements RSA. +LIB_EXPORT BOOL BnModInverse(bigNum result, bigConst number, bigConst modulus); + +//** BnEccModMult() +// This function does a point multiply of the form R = [d]S. A return of FALSE +// indicates that the result was the point at infinity. This function is only needed +// if the TPM supports ECC. +LIB_EXPORT BOOL BnEccModMult(bigPoint R, pointConst S, bigConst d, bigCurve E); + +//** BnEccModMult2() +// This function does a point multiply of the form R = [d]S + [u]Q. A return of +// FALSE indicates that the result was the point at infinity. This function is only +// needed if the TPM supports ECC. +LIB_EXPORT BOOL BnEccModMult2( + bigPoint R, pointConst S, bigConst d, pointConst Q, bigConst u, bigCurve E); + +//** BnEccAdd() +// This function does a point add R = S + Q. A return of FALSE +// indicates that the result was the point at infinity. This function is only needed +// if the TPM supports ECC. +LIB_EXPORT BOOL BnEccAdd(bigPoint R, pointConst S, pointConst Q, bigCurve E); + +//** BnCurveInitialize() +// This function is used to initialize the pointers of a bnCurve_t structure. The +// structure is a set of pointers to bigNum values. The curve-dependent values are +// set by a different function. This function is only needed +// if the TPM supports ECC. +LIB_EXPORT bigCurve BnCurveInitialize(bigCurve E, TPM_ECC_CURVE curveId); + +//*** BnCurveFree() +// This function will free the allocated components of the curve and end the +// frame in which the curve data exists +LIB_EXPORT void BnCurveFree(bigCurve E); + +#endif \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/SymmetricTest.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/SymmetricTest.h new file mode 100644 index 0000000..2f71ff1 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/SymmetricTest.h @@ -0,0 +1,107 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction + +// This file contains the structures and data definitions for the symmetric tests. +// This file references the header file that contains the actual test vectors. This +// organization was chosen so that the program that is used to generate the test +// vector values does not have to also re-generate this data. +#ifndef SELF_TEST_DATA +# error "This file may only be included in AlgorithmTests.c" +#endif + +#ifndef _SYMMETRIC_TEST_H +# define _SYMMETRIC_TEST_H +# include "SymmetricTestData.h" + +//** Symmetric Test Structures + +const SYMMETRIC_TEST_VECTOR c_symTestValues[NUM_SYMS + 1] = { +# if ALG_AES && AES_128 + {TPM_ALG_AES, + 128, + key_AES128, + 16, + sizeof(dataIn_AES128), + dataIn_AES128, + {dataOut_AES128_CTR, + dataOut_AES128_OFB, + dataOut_AES128_CBC, + dataOut_AES128_CFB, + dataOut_AES128_ECB}}, +# endif +# if ALG_AES && AES_192 + {TPM_ALG_AES, + 192, + key_AES192, + 16, + sizeof(dataIn_AES192), + dataIn_AES192, + {dataOut_AES192_CTR, + dataOut_AES192_OFB, + dataOut_AES192_CBC, + dataOut_AES192_CFB, + dataOut_AES192_ECB}}, +# endif +# if ALG_AES && AES_256 + {TPM_ALG_AES, + 256, + key_AES256, + 16, + sizeof(dataIn_AES256), + dataIn_AES256, + {dataOut_AES256_CTR, + dataOut_AES256_OFB, + dataOut_AES256_CBC, + dataOut_AES256_CFB, + dataOut_AES256_ECB}}, +# endif +// There are no SM4 test values yet so... +# if ALG_SM4 && SM4_128 && 0 + {TPM_ALG_SM4, + 128, + key_SM4128, + 16, + sizeof(dataIn_SM4128), + dataIn_SM4128, + {dataOut_SM4128_CTR, + dataOut_SM4128_OFB, + dataOut_SM4128_CBC, + dataOut_SM4128_CFB, + dataOut_AES128_ECB}}, +# endif + {0}}; + +#endif // _SYMMETRIC_TEST_H diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/SymmetricTestData.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/SymmetricTestData.h new file mode 100644 index 0000000..a419d42 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/SymmetricTestData.h @@ -0,0 +1,165 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 vector for testing either encrypt or decrypt. The premise for decrypt +// is that the IV for decryption is the same as the IV for encryption. However, +// the ivOut value may be different for encryption and decryption. We will encrypt +// at least two blocks. This means that the chaining value will be used for each +// of the schemes (if any) and that implicitly checks that the chaining value +// is handled properly. + +#if AES_128 + +const BYTE key_AES128[] = {0x2b, + 0x7e, + 0x15, + 0x16, + 0x28, + 0xae, + 0xd2, + 0xa6, + 0xab, + 0xf7, + 0x15, + 0x88, + 0x09, + 0xcf, + 0x4f, + 0x3c}; + +const BYTE dataIn_AES128[] = {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}; + +const BYTE dataOut_AES128_ECB[] = {0x3a, 0xd7, 0x7b, 0xb4, 0x0d, 0x7a, 0x36, 0x60, + 0xa8, 0x9e, 0xca, 0xf3, 0x24, 0x66, 0xef, 0x97, + 0xf5, 0xd3, 0xd5, 0x85, 0x03, 0xb9, 0x69, 0x9d, + 0xe7, 0x85, 0x89, 0x5a, 0x96, 0xfd, 0xba, 0xaf}; + +const BYTE dataOut_AES128_CBC[] = {0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, + 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d, + 0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee, + 0x95, 0xdb, 0x11, 0x3a, 0x91, 0x76, 0x78, 0xb2}; + +const BYTE dataOut_AES128_CFB[] = {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}; + +const BYTE dataOut_AES128_OFB[] = {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}; + +const BYTE dataOut_AES128_CTR[] = {0x87, 0x4d, 0x61, 0x91, 0xb6, 0x20, 0xe3, 0x26, + 0x1b, 0xef, 0x68, 0x64, 0x99, 0x0d, 0xb6, 0xce, + 0x98, 0x06, 0xf6, 0x6b, 0x79, 0x70, 0xfd, 0xff, + 0x86, 0x17, 0x18, 0x7b, 0xb9, 0xff, 0xfd, 0xff}; +#endif + +#if AES_192 + +const BYTE key_AES192[] = {0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, + 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, + 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b}; + +const BYTE dataIn_AES192[] = {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}; + +const BYTE dataOut_AES192_ECB[] = {0xbd, 0x33, 0x4f, 0x1d, 0x6e, 0x45, 0xf2, 0x5f, + 0xf7, 0x12, 0xa2, 0x14, 0x57, 0x1f, 0xa5, 0xcc, + 0x97, 0x41, 0x04, 0x84, 0x6d, 0x0a, 0xd3, 0xad, + 0x77, 0x34, 0xec, 0xb3, 0xec, 0xee, 0x4e, 0xef}; + +const BYTE dataOut_AES192_CBC[] = {0x4f, 0x02, 0x1d, 0xb2, 0x43, 0xbc, 0x63, 0x3d, + 0x71, 0x78, 0x18, 0x3a, 0x9f, 0xa0, 0x71, 0xe8, + 0xb4, 0xd9, 0xad, 0xa9, 0xad, 0x7d, 0xed, 0xf4, + 0xe5, 0xe7, 0x38, 0x76, 0x3f, 0x69, 0x14, 0x5a}; + +const BYTE dataOut_AES192_CFB[] = {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}; + +const BYTE dataOut_AES192_OFB[] = {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}; + +const BYTE dataOut_AES192_CTR[] = {0x1a, 0xbc, 0x93, 0x24, 0x17, 0x52, 0x1c, 0xa2, + 0x4f, 0x2b, 0x04, 0x59, 0xfe, 0x7e, 0x6e, 0x0b, + 0x09, 0x03, 0x39, 0xec, 0x0a, 0xa6, 0xfa, 0xef, + 0xd5, 0xcc, 0xc2, 0xc6, 0xf4, 0xce, 0x8e, 0x94}; +#endif + +#if AES_256 + +const BYTE key_AES256[] = {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}; + +const BYTE dataIn_AES256[] = {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}; + +const BYTE dataOut_AES256_ECB[] = {0xf3, 0xee, 0xd1, 0xbd, 0xb5, 0xd2, 0xa0, 0x3c, + 0x06, 0x4b, 0x5a, 0x7e, 0x3d, 0xb1, 0x81, 0xf8, + 0x59, 0x1c, 0xcb, 0x10, 0xd4, 0x10, 0xed, 0x26, + 0xdc, 0x5b, 0xa7, 0x4a, 0x31, 0x36, 0x28, 0x70}; + +const BYTE dataOut_AES256_CBC[] = {0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba, + 0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6, + 0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d, + 0x67, 0x9f, 0x77, 0x7b, 0xc6, 0x70, 0x2c, 0x7d}; + +const BYTE dataOut_AES256_CFB[] = {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}; + +const BYTE dataOut_AES256_OFB[] = {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}; + +const BYTE dataOut_AES256_CTR[] = {0x60, 0x1e, 0xc3, 0x13, 0x77, 0x57, 0x89, 0xa5, + 0xb7, 0xa7, 0xf5, 0x04, 0xbb, 0xf3, 0xd2, 0x28, + 0xf4, 0x43, 0xe3, 0xca, 0x4d, 0x62, 0xb5, 0x9a, + 0xca, 0x84, 0xe9, 0x90, 0xca, 0xca, 0xf5, 0xc5}; +#endif diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TPMB.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TPMB.h new file mode 100644 index 0000000..3a6cb26 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TPMB.h @@ -0,0 +1,74 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 contains extra TPM2B structures +// + +#ifndef _TPMB_H +#define _TPMB_H + +// TPM2B Types +typedef struct +{ + UINT16 size; + BYTE buffer[1]; +} TPM2B, *P2B; +typedef const TPM2B* PC2B; + +// This macro helps avoid having to type in the structure in order to create +// a new TPM2B type that is used in a function. +#define TPM2B_TYPE(name, bytes) \ + typedef union \ + { \ + struct \ + { \ + UINT16 size; \ + BYTE buffer[(bytes)]; \ + } t; \ + TPM2B b; \ + } TPM2B_##name + +// This macro defines a TPM2B with a constant character value. This macro +// sets the size of the string to the size minus the terminating zero byte. +// This lets the user of the label add their terminating 0. This method +// is chosen so that existing code that provides a label will continue +// to work correctly. + +// Macro to instance and initialize a TPM2B value +#define TPM2B_INIT(TYPE, name) TPM2B_##TYPE name = {sizeof(name.t.buffer), {0}} + +#define TPM2B_BYTE_VALUE(bytes) TPM2B_TYPE(bytes##_BYTE_VALUE, bytes) + +#endif diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TableMarshal.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TableMarshal.h new file mode 100644 index 0000000..76b0651 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TableMarshal.h @@ -0,0 +1,236 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 _TABLE_MARSHAL_H_ +#define _TABLE_MARSHAL_H_ + +// These are the basic unmarshaling types. This is in the first byte of +// each structure descriptor that is passed to Marshal()/Unmarshal() for processing. +#define UINT_MTYPE 0 +#define VALUES_MTYPE (UINT_MTYPE + 1) +#define TABLE_MTYPE (VALUES_MTYPE + 1) +#define MIN_MAX_MTYPE (TABLE_MTYPE + 1) +#define ATTRIBUTES_MTYPE (MIN_MAX_MTYPE + 1) +#define STRUCTURE_MTYPE (ATTRIBUTES_MTYPE + 1) +#define TPM2B_MTYPE (STRUCTURE_MTYPE + 1) +#define TPM2BS_MTYPE (TPM2B_MTYPE + 1) +#define LIST_MTYPE (TPM2BS_MTYPE + 1) // TPML +#define ERROR_MTYPE (LIST_MTYPE + 1) +#define NULL_MTYPE (ERROR_MTYPE + 1) +#define COMPOSITE_MTYPE (NULL_MTYPE + 1) + +//*** The Marshal Index +// A structure is used to hold the values that guide the marshaling/unmarshaling of +// each of the types. Each structure has a name and an address. For a structure to +// define a TPMS_name, the structure is a TPMS_name_MARSHAL_STRUCT and its +// index is TPMS_name_MARSHAL_INDEX. So, to get the proper structure, use the +// associated marshal index. The marshal index is passed to Marshal() or Unmarshal() +// and those functions look up the proper structure. +// +// To handle structures that allow a null value, the upper bit of each marshal +// index indicates if the null value is allowed. This is the NULL_FLAG. It is defined +// in TableMarshalIndex.h because it is needed by code outside of the marshaling +// code. + +// A structure will have a list of marshal indexes to indicate what to unmarshal. When +// that index appears in a structure/union, the value will contain a flag to indicate +// that the NULL_FLAG should be SET on the call to Unmarshal() to unmarshal the type. +// The caller simply takes the entry and passes it to Unmarshal() to indicate that the +// NULL_FLAG is SET. There is also the opportunity to SET the NULL_FLAG in the called +// structure if the NULL_FLAG was set in the call to the calling structure. This is +// indicated by: +#define NULL_MASK ~(NULL_FLAG) + +// When looking up the value to marshal, the upper bit of the marshal index is +// masked to yield the actual index. The MSb is the flag bit that indicates if a +// null flag is set. Code does not verify that the bit is clear when the called object +// does not take a flag as this is a benign error. + +// the modifier byte as used by each MTYPE shown as a structure. They are expressed +// as a bit maps below. However, the code uses masking and not bit fields. The types +// show below are just to help in understanding. +// NOTE: LSb0 bit numbering is assumed in these typedefs. +// +// When used in an UINT_MTYPE +typedef struct integerModifier +{ + unsigned size : 2; + unsigned sign : 1; + unsigned unused : 7; +} integerModifier; + +// When used in a VALUES_MTYPE +typedef struct valuesModifier +{ + unsigned size : 2; + unsigned sign : 1; + unsigned unused : 5; + unsigned takesNull : 1; +} valuesModifier; + +// When used in a TABLE_MTYPE +typedef struct tableModifier +{ + unsigned size : 2; + unsigned sign : 1; + unsigned unused : 3; + unsigned hasBits : 1; + unsigned takesNull : 1; +} tableModifier; + +// the modifier byte for MIN_MAX_MTYPE +typedef struct minMaxModifier +{ + unsigned size : 2; + unsigned sign : 1; + unsigned unused : 3; + unsigned hasBits : 1; + unsigned takesNull : 1; +} minMaxModifier; + +// the modifier byte for ATTRIBUTES_MTYPE +typedef struct attributesModifier +{ + unsigned size : 2; + unsigned sign : 1; + unsigned unused : 5; +} attributesModifier; + +// the modifier byte is not present in a STRUCTURE_MTYPE or an TPM2B_MTYPE + +// the modifier byte for a TPM2BS_MTYPE +typedef struct tpm2bsModifier +{ + unsigned offset : 4; + unsigned unused : 2; + unsigned sizeEqual : 1; + unsigned propigateNull : 1; +} tpm2bsModifier; + +// the modifier byte for a LIST_MTYPE +typedef struct listModifier +{ + unsigned offset : 4; + unsigned unused : 2; + unsigned sizeEqual : 1; + unsigned propigateNull : 1; +} listModifier; + +//*** Modifier Octet Values +// These are in used in anything that is an integer value. Theses would not be in +// structure modifier bytes (they would be used in values in structures but not the +// STRUCTURE_MTYPE header. +#define ONE_BYTES (0) +#define TWO_BYTES (1) +#define FOUR_BYTES (2) +#define EIGHT_BYTES (3) +#define SIZE_MASK (0x3) +#define IS_SIGNED (1 << 2) // when the unmarshaled type is a signed value +#define SIGNED_MASK (SIZE_MASK | IS_SIGNED) + +// This may be used for any type except a UINT_MTYPE +#define TAKES_NULL (1 << 7) // when the type takes a null + +// When referencing a structure, this flag indicates if a null is to be propagated +// to the referenced structure or type. +#define PROPAGATE_NULL (TAKES_NULL) + +// Can be used in min-max or table structures. +#define HAS_BITS (1 << 6) // when bit mask is present + +// In a union, we need to know if this is a union of constant arrays. +#define IS_ARRAY_UNION (1 << 6) + +// In a TPM2BS_MTYPE +#define SIZE_EQUAL (1 << 6) +#define OFFSET_MASK (0xF) + +// Right now, there are three spare bits in the modifiers field. + +// Within the descriptor word of each entry in a StructMarsh_mst, there is a selector +// field to determine which of the sub-types the entry represents and a field that is +// used to reference another structure entry. This is a 6-bit field allowing a +// structure to have 64 entries. This should be more than enough as the structures are +// not that long. As of now, only 10-bits of the descriptor word leaving room for +// expansion. + +// These are the values used in a STRUCTURE_MTYPE to identify the sub-type of the +// thing being processed +#define SIMPLE_STYPE 0 +#define UNION_STYPE 1 +#define ARRAY_STYPE 2 + +// The code used GET_ to get the element type and the compiler uses SET_ to initialize +// the value. The element type is the three bits (2:0). +#define GET_ELEMENT_TYPE(val) (val & 7) +#define SET_ELEMENT_TYPE(val) (val & 7) + +// When an entry is an array or union, this references the structure entry that +// contains the dimension or selector value. The code then uses this number to look up +// the structure entry for that element to find out what it and where is it in memory. +// When this is not a reference, it is a simple type and it could be used as an array +// value or a union selector. When a simple value, this field contains the size +// of the associated value (ONE_BYTES, TWO_BYTES ...) +// +// The entry size/number is 6 bits (13:8). +#define GET_ELEMENT_NUMBER(val) (((val) >> 8) & 0x3F) +#define SET_ELEMENT_NUMBER(val) (((val)&0x3F) << 8) +#define GET_ELEMENT_SIZE(val) GET_ELEMENT_NUMBER(val) +#define SET_ELEMENT_SIZE(val) SET_ELEMENT_NUMBER(val) +// This determines if the null flag is propagated to this type. If generate, the +// NULL_FLAG is SET in the index value. This flag is one bit (7) +#define ELEMENT_PROPAGATE (PROPAGATE_NULL) + +#define INDEX_MASK ((UINT16)NULL_MASK) + +// This is used in all bit-field checks. These are used when a value that is checked +// is conditional (dependent on the compilation). For example, if AES_128 is (NO), +// then the bit associated with AES_128 will be 0. In some cases, the bit value is +// found by checking that the input is within the range of the table, and then using +// the (val - min) value to index the bit. This would be used when verifying that +// a particular algorithm is implemented. In other cases, there is a bit for each +// value in a table. For example, if checking the key sizes, there is a list of +// possible key sizes allowed by the algorithm registry and a bit field to indicate +// if that key size is allowed in the implementation. The smallest bit field has +// 32-bits because it is implemented as part of the 'values' array in structures +// that allow bit fields. +#define IS_BIT_SET32(bit, bits) \ + ((((UINT32*)bits)[bit >> 5] & (1 << (bit & 0x1F))) != 0) + +// For a COMPOSITE_MTYPE, the qualifiers byte has an element size and count. +#define SET_ELEMENT_COUNT(count) ((count & 0x1F) << 3) +#define GET_ELEMENT_COUNT(val) ((val >> 3) & 0x1F) + +#endif // _TABLE_MARSHAL_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TableMarshalDefines.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TableMarshalDefines.h new file mode 100644 index 0000000..6b89855 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TableMarshalDefines.h @@ -0,0 +1,1453 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by NewMarshal; Version 1.4 Apr 7, 2019 + * Date: Mar 6, 2020 Time: 01:50:10PM + */ + +#ifndef _TABLE_MARSHAL_DEFINES_H_ +#define _TABLE_MARSHAL_DEFINES_H_ + +#define NULL_SHIFT 15 +#define NULL_FLAG (1 << NULL_SHIFT) + +// The range macro processes a min, max value and produces a values that is used in +// the computation to see if something is within a range. The max value is (max-min). +// This lets the check for something ('val') within a range become: +// if((val - min) <= max) // passes if in range +// if((val - min) > max) // passes if not in range +// This works because all values are converted to UINT32 values before the compare. +// For (val - min), all values greater than or equal to val will become positive +// values with a value equal to 'min' being zero. This means that in an unsigned +// compare against 'max,' any value that is outside the range will appear to be a +// number greater than max. The benefit of this operation is that this will work even +// if the input value is a signed number as long as the input is sign extended. + +#define RANGE(_min_, _max_, _base_) (UINT32) _min_, (UINT32)((_base_)(_max_ - _min_)) + +// This macro is like the offsetof macro but, instead of computing the offset of +// a structure element, it computes the stride between elements that are in a +// structure array. This is used instead of sizeof() because the sizeof() operator on +// a structure can return an implementation dependent value. +#define STRIDE(s) ((UINT16)(size_t) & (((s*)0)[1])) + +#define MARSHAL_REF(TYPE) ((UINT16)(offsetof(MARSHAL_DATA, TYPE))) + +// This macro creates the entry in the array lookup table +#define ARRAY_MARSHAL_ENTRY(TYPE) \ + { \ + (marshalIndex_t) TYPE##_MARSHAL_REF, (UINT16)STRIDE(TYPE) \ + } + +// Defines for array lookup +#define UINT8_ARRAY_MARSHAL_INDEX 0 // 0x00 +#define TPM_CC_ARRAY_MARSHAL_INDEX 1 // 0x01 +#define TPMA_CC_ARRAY_MARSHAL_INDEX 2 // 0x02 +#define TPM_ALG_ID_ARRAY_MARSHAL_INDEX 3 // 0x03 +#define TPM_HANDLE_ARRAY_MARSHAL_INDEX 4 // 0x04 +#define TPM2B_DIGEST_ARRAY_MARSHAL_INDEX 5 // 0x05 +#define TPMT_HA_ARRAY_MARSHAL_INDEX 6 // 0x06 +#define TPMS_PCR_SELECTION_ARRAY_MARSHAL_INDEX 7 // 0x07 +#define TPMS_ALG_PROPERTY_ARRAY_MARSHAL_INDEX 8 // 0x08 +#define TPMS_TAGGED_PROPERTY_ARRAY_MARSHAL_INDEX 9 // 0x09 +#define TPMS_TAGGED_PCR_SELECT_ARRAY_MARSHAL_INDEX 10 // 0x0A +#define TPM_ECC_CURVE_ARRAY_MARSHAL_INDEX 11 // 0x0B +#define TPMS_TAGGED_POLICY_ARRAY_MARSHAL_INDEX 12 // 0x0C +#define TPMS_ACT_DATA_ARRAY_MARSHAL_INDEX 13 // 0x0D +#define TPMS_AC_OUTPUT_ARRAY_MARSHAL_INDEX 14 // 0x0E + +// Defines for referencing a type by offset +#define UINT8_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, UINT8_DATA))) +#define BYTE_MARSHAL_REF UINT8_MARSHAL_REF +#define TPM_HT_MARSHAL_REF UINT8_MARSHAL_REF +#define TPMA_LOCALITY_MARSHAL_REF UINT8_MARSHAL_REF +#define UINT16_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, UINT16_DATA))) +#define TPM_KEY_SIZE_MARSHAL_REF UINT16_MARSHAL_REF +#define TPM_KEY_BITS_MARSHAL_REF UINT16_MARSHAL_REF +#define TPM_ALG_ID_MARSHAL_REF UINT16_MARSHAL_REF +#define TPM_ST_MARSHAL_REF UINT16_MARSHAL_REF +#define UINT32_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, UINT32_DATA))) +#define TPM_ALGORITHM_ID_MARSHAL_REF UINT32_MARSHAL_REF +#define TPM_MODIFIER_INDICATOR_MARSHAL_REF UINT32_MARSHAL_REF +#define TPM_AUTHORIZATION_SIZE_MARSHAL_REF UINT32_MARSHAL_REF +#define TPM_PARAMETER_SIZE_MARSHAL_REF UINT32_MARSHAL_REF +#define TPM_SPEC_MARSHAL_REF UINT32_MARSHAL_REF +#define TPM_CONSTANTS32_MARSHAL_REF UINT32_MARSHAL_REF +#define TPM_CC_MARSHAL_REF UINT32_MARSHAL_REF +#define TPM_RC_MARSHAL_REF UINT32_MARSHAL_REF +#define TPM_PT_MARSHAL_REF UINT32_MARSHAL_REF +#define TPM_PT_PCR_MARSHAL_REF UINT32_MARSHAL_REF +#define TPM_PS_MARSHAL_REF UINT32_MARSHAL_REF +#define TPM_HANDLE_MARSHAL_REF UINT32_MARSHAL_REF +#define TPM_RH_MARSHAL_REF UINT32_MARSHAL_REF +#define TPM_HC_MARSHAL_REF UINT32_MARSHAL_REF +#define TPMA_PERMANENT_MARSHAL_REF UINT32_MARSHAL_REF +#define TPMA_STARTUP_CLEAR_MARSHAL_REF UINT32_MARSHAL_REF +#define TPMA_MEMORY_MARSHAL_REF UINT32_MARSHAL_REF +#define TPMA_CC_MARSHAL_REF UINT32_MARSHAL_REF +#define TPMA_MODES_MARSHAL_REF UINT32_MARSHAL_REF +#define TPMA_X509_KEY_USAGE_MARSHAL_REF UINT32_MARSHAL_REF +#define TPM_NV_INDEX_MARSHAL_REF UINT32_MARSHAL_REF +#define TPM_AE_MARSHAL_REF UINT32_MARSHAL_REF +#define UINT64_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, UINT64_DATA))) +#define INT8_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, INT8_DATA))) +#define INT16_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, INT16_DATA))) +#define INT32_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, INT32_DATA))) +#define INT64_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, INT64_DATA))) +#define UINT0_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, UINT0_DATA))) +#define TPM_ECC_CURVE_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPM_ECC_CURVE_DATA))) +#define TPM_CLOCK_ADJUST_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPM_CLOCK_ADJUST_DATA))) +#define TPM_EO_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, TPM_EO_DATA))) +#define TPM_SU_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, TPM_SU_DATA))) +#define TPM_SE_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, TPM_SE_DATA))) +#define TPM_CAP_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, TPM_CAP_DATA))) +#define TPMA_ALGORITHM_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMA_ALGORITHM_DATA))) +#define TPMA_OBJECT_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, TPMA_OBJECT_DATA))) +#define TPMA_SESSION_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMA_SESSION_DATA))) +#define TPMA_ACT_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, TPMA_ACT_DATA))) +#define TPMI_YES_NO_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, TPMI_YES_NO_DATA))) +#define TPMI_DH_OBJECT_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_DH_OBJECT_DATA))) +#define TPMI_DH_PARENT_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_DH_PARENT_DATA))) +#define TPMI_DH_PERSISTENT_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_DH_PERSISTENT_DATA))) +#define TPMI_DH_ENTITY_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_DH_ENTITY_DATA))) +#define TPMI_DH_PCR_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, TPMI_DH_PCR_DATA))) +#define TPMI_SH_AUTH_SESSION_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_SH_AUTH_SESSION_DATA))) +#define TPMI_SH_HMAC_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_SH_HMAC_DATA))) +#define TPMI_SH_POLICY_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_SH_POLICY_DATA))) +#define TPMI_DH_CONTEXT_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_DH_CONTEXT_DATA))) +#define TPMI_DH_SAVED_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_DH_SAVED_DATA))) +#define TPMI_RH_HIERARCHY_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_RH_HIERARCHY_DATA))) +#define TPMI_RH_ENABLES_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_RH_ENABLES_DATA))) +#define TPMI_RH_HIERARCHY_AUTH_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_RH_HIERARCHY_AUTH_DATA))) +#define TPMI_RH_HIERARCHY_POLICY_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_RH_HIERARCHY_POLICY_DATA))) +#define TPMI_RH_PLATFORM_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_RH_PLATFORM_DATA))) +#define TPMI_RH_OWNER_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_RH_OWNER_DATA))) +#define TPMI_RH_ENDORSEMENT_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_RH_ENDORSEMENT_DATA))) +#define TPMI_RH_PROVISION_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_RH_PROVISION_DATA))) +#define TPMI_RH_CLEAR_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_RH_CLEAR_DATA))) +#define TPMI_RH_NV_AUTH_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_RH_NV_AUTH_DATA))) +#define TPMI_RH_LOCKOUT_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_RH_LOCKOUT_DATA))) +#define TPMI_RH_NV_INDEX_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_RH_NV_INDEX_DATA))) +#define TPMI_RH_AC_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, TPMI_RH_AC_DATA))) +#define TPMI_RH_ACT_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, TPMI_RH_ACT_DATA))) +#define TPMI_ALG_HASH_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_ALG_HASH_DATA))) +#define TPMI_ALG_ASYM_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_ALG_ASYM_DATA))) +#define TPMI_ALG_SYM_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_ALG_SYM_DATA))) +#define TPMI_ALG_SYM_OBJECT_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_ALG_SYM_OBJECT_DATA))) +#define TPMI_ALG_SYM_MODE_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_ALG_SYM_MODE_DATA))) +#define TPMI_ALG_KDF_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_ALG_KDF_DATA))) +#define TPMI_ALG_SIG_SCHEME_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_ALG_SIG_SCHEME_DATA))) +#define TPMI_ECC_KEY_EXCHANGE_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_ECC_KEY_EXCHANGE_DATA))) +#define TPMI_ST_COMMAND_TAG_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_ST_COMMAND_TAG_DATA))) +#define TPMI_ALG_MAC_SCHEME_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_ALG_MAC_SCHEME_DATA))) +#define TPMI_ALG_CIPHER_MODE_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_ALG_CIPHER_MODE_DATA))) +#define TPMS_EMPTY_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, TPMS_EMPTY_DATA))) +#define TPMS_ENC_SCHEME_RSAES_MARSHAL_REF TPMS_EMPTY_MARSHAL_REF +#define TPMS_ALGORITHM_DESCRIPTION_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMS_ALGORITHM_DESCRIPTION_DATA))) +#define TPMU_HA_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, TPMU_HA_DATA))) +#define TPMT_HA_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, TPMT_HA_DATA))) +#define TPM2B_DIGEST_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPM2B_DIGEST_DATA))) +#define TPM2B_NONCE_MARSHAL_REF TPM2B_DIGEST_MARSHAL_REF +#define TPM2B_AUTH_MARSHAL_REF TPM2B_DIGEST_MARSHAL_REF +#define TPM2B_OPERAND_MARSHAL_REF TPM2B_DIGEST_MARSHAL_REF +#define TPM2B_DATA_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, TPM2B_DATA_DATA))) +#define TPM2B_EVENT_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, TPM2B_EVENT_DATA))) +#define TPM2B_MAX_BUFFER_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPM2B_MAX_BUFFER_DATA))) +#define TPM2B_MAX_NV_BUFFER_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPM2B_MAX_NV_BUFFER_DATA))) +#define TPM2B_TIMEOUT_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPM2B_TIMEOUT_DATA))) +#define TPM2B_IV_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, TPM2B_IV_DATA))) +#define NULL_UNION_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, NULL_UNION_DATA))) +#define TPMU_NAME_MARSHAL_REF NULL_UNION_MARSHAL_REF +#define TPMU_SENSITIVE_CREATE_MARSHAL_REF NULL_UNION_MARSHAL_REF +#define TPM2B_NAME_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, TPM2B_NAME_DATA))) +#define TPMS_PCR_SELECT_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMS_PCR_SELECT_DATA))) +#define TPMS_PCR_SELECTION_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMS_PCR_SELECTION_DATA))) +#define TPMT_TK_CREATION_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMT_TK_CREATION_DATA))) +#define TPMT_TK_VERIFIED_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMT_TK_VERIFIED_DATA))) +#define TPMT_TK_AUTH_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMT_TK_AUTH_DATA))) +#define TPMT_TK_HASHCHECK_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMT_TK_HASHCHECK_DATA))) +#define TPMS_ALG_PROPERTY_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMS_ALG_PROPERTY_DATA))) +#define TPMS_TAGGED_PROPERTY_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMS_TAGGED_PROPERTY_DATA))) +#define TPMS_TAGGED_PCR_SELECT_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMS_TAGGED_PCR_SELECT_DATA))) +#define TPMS_TAGGED_POLICY_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMS_TAGGED_POLICY_DATA))) +#define TPMS_ACT_DATA_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMS_ACT_DATA_DATA))) +#define TPML_CC_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, TPML_CC_DATA))) +#define TPML_CCA_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, TPML_CCA_DATA))) +#define TPML_ALG_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, TPML_ALG_DATA))) +#define TPML_HANDLE_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, TPML_HANDLE_DATA))) +#define TPML_DIGEST_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, TPML_DIGEST_DATA))) +#define TPML_DIGEST_VALUES_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPML_DIGEST_VALUES_DATA))) +#define TPML_PCR_SELECTION_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPML_PCR_SELECTION_DATA))) +#define TPML_ALG_PROPERTY_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPML_ALG_PROPERTY_DATA))) +#define TPML_TAGGED_TPM_PROPERTY_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPML_TAGGED_TPM_PROPERTY_DATA))) +#define TPML_TAGGED_PCR_PROPERTY_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPML_TAGGED_PCR_PROPERTY_DATA))) +#define TPML_ECC_CURVE_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPML_ECC_CURVE_DATA))) +#define TPML_TAGGED_POLICY_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPML_TAGGED_POLICY_DATA))) +#define TPML_ACT_DATA_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPML_ACT_DATA_DATA))) +#define TPMU_CAPABILITIES_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMU_CAPABILITIES_DATA))) +#define TPMS_CAPABILITY_DATA_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMS_CAPABILITY_DATA_DATA))) +#define TPMS_CLOCK_INFO_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMS_CLOCK_INFO_DATA))) +#define TPMS_TIME_INFO_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMS_TIME_INFO_DATA))) +#define TPMS_TIME_ATTEST_INFO_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMS_TIME_ATTEST_INFO_DATA))) +#define TPMS_CERTIFY_INFO_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMS_CERTIFY_INFO_DATA))) +#define TPMS_QUOTE_INFO_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMS_QUOTE_INFO_DATA))) +#define TPMS_COMMAND_AUDIT_INFO_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMS_COMMAND_AUDIT_INFO_DATA))) +#define TPMS_SESSION_AUDIT_INFO_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMS_SESSION_AUDIT_INFO_DATA))) +#define TPMS_CREATION_INFO_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMS_CREATION_INFO_DATA))) +#define TPMS_NV_CERTIFY_INFO_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMS_NV_CERTIFY_INFO_DATA))) +#define TPMS_NV_DIGEST_CERTIFY_INFO_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMS_NV_DIGEST_CERTIFY_INFO_DATA))) +#define TPMI_ST_ATTEST_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_ST_ATTEST_DATA))) +#define TPMU_ATTEST_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, TPMU_ATTEST_DATA))) +#define TPMS_ATTEST_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, TPMS_ATTEST_DATA))) +#define TPM2B_ATTEST_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPM2B_ATTEST_DATA))) +#define TPMS_AUTH_COMMAND_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMS_AUTH_COMMAND_DATA))) +#define TPMS_AUTH_RESPONSE_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMS_AUTH_RESPONSE_DATA))) +#define TPMI_TDES_KEY_BITS_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_TDES_KEY_BITS_DATA))) +#define TPMI_AES_KEY_BITS_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_AES_KEY_BITS_DATA))) +#define TPMI_SM4_KEY_BITS_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_SM4_KEY_BITS_DATA))) +#define TPMI_CAMELLIA_KEY_BITS_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_CAMELLIA_KEY_BITS_DATA))) +#define TPMU_SYM_KEY_BITS_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMU_SYM_KEY_BITS_DATA))) +#define TPMU_SYM_MODE_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMU_SYM_MODE_DATA))) +#define TPMT_SYM_DEF_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMT_SYM_DEF_DATA))) +#define TPMT_SYM_DEF_OBJECT_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMT_SYM_DEF_OBJECT_DATA))) +#define TPM2B_SYM_KEY_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPM2B_SYM_KEY_DATA))) +#define TPMS_SYMCIPHER_PARMS_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMS_SYMCIPHER_PARMS_DATA))) +#define TPM2B_LABEL_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, TPM2B_LABEL_DATA))) +#define TPMS_DERIVE_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, TPMS_DERIVE_DATA))) +#define TPM2B_DERIVE_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPM2B_DERIVE_DATA))) +#define TPM2B_SENSITIVE_DATA_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPM2B_SENSITIVE_DATA_DATA))) +#define TPMS_SENSITIVE_CREATE_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMS_SENSITIVE_CREATE_DATA))) +#define TPM2B_SENSITIVE_CREATE_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPM2B_SENSITIVE_CREATE_DATA))) +#define TPMS_SCHEME_HASH_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMS_SCHEME_HASH_DATA))) +#define TPMS_SCHEME_HMAC_MARSHAL_REF TPMS_SCHEME_HASH_MARSHAL_REF +#define TPMS_SIG_SCHEME_RSASSA_MARSHAL_REF TPMS_SCHEME_HASH_MARSHAL_REF +#define TPMS_SIG_SCHEME_RSAPSS_MARSHAL_REF TPMS_SCHEME_HASH_MARSHAL_REF +#define TPMS_SIG_SCHEME_ECDSA_MARSHAL_REF TPMS_SCHEME_HASH_MARSHAL_REF +#define TPMS_SIG_SCHEME_SM2_MARSHAL_REF TPMS_SCHEME_HASH_MARSHAL_REF +#define TPMS_SIG_SCHEME_ECSCHNORR_MARSHAL_REF TPMS_SCHEME_HASH_MARSHAL_REF +#define TPMS_ENC_SCHEME_OAEP_MARSHAL_REF TPMS_SCHEME_HASH_MARSHAL_REF +#define TPMS_KEY_SCHEME_ECDH_MARSHAL_REF TPMS_SCHEME_HASH_MARSHAL_REF +#define TPMS_KEY_SCHEME_ECMQV_MARSHAL_REF TPMS_SCHEME_HASH_MARSHAL_REF +#define TPMS_KDF_SCHEME_MGF1_MARSHAL_REF TPMS_SCHEME_HASH_MARSHAL_REF +#define TPMS_KDF_SCHEME_KDF1_SP800_56A_MARSHAL_REF TPMS_SCHEME_HASH_MARSHAL_REF +#define TPMS_KDF_SCHEME_KDF2_MARSHAL_REF TPMS_SCHEME_HASH_MARSHAL_REF +#define TPMS_KDF_SCHEME_KDF1_SP800_108_MARSHAL_REF TPMS_SCHEME_HASH_MARSHAL_REF +#define TPMS_SCHEME_ECDAA_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMS_SCHEME_ECDAA_DATA))) +#define TPMS_SIG_SCHEME_ECDAA_MARSHAL_REF TPMS_SCHEME_ECDAA_MARSHAL_REF +#define TPMI_ALG_KEYEDHASH_SCHEME_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_ALG_KEYEDHASH_SCHEME_DATA))) +#define TPMS_SCHEME_XOR_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMS_SCHEME_XOR_DATA))) +#define TPMU_SCHEME_KEYEDHASH_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMU_SCHEME_KEYEDHASH_DATA))) +#define TPMT_KEYEDHASH_SCHEME_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMT_KEYEDHASH_SCHEME_DATA))) +#define TPMU_SIG_SCHEME_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMU_SIG_SCHEME_DATA))) +#define TPMT_SIG_SCHEME_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMT_SIG_SCHEME_DATA))) +#define TPMU_KDF_SCHEME_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMU_KDF_SCHEME_DATA))) +#define TPMT_KDF_SCHEME_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMT_KDF_SCHEME_DATA))) +#define TPMI_ALG_ASYM_SCHEME_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_ALG_ASYM_SCHEME_DATA))) +#define TPMU_ASYM_SCHEME_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMU_ASYM_SCHEME_DATA))) +#define TPMI_ALG_RSA_SCHEME_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_ALG_RSA_SCHEME_DATA))) +#define TPMT_RSA_SCHEME_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMT_RSA_SCHEME_DATA))) +#define TPMI_ALG_RSA_DECRYPT_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_ALG_RSA_DECRYPT_DATA))) +#define TPMT_RSA_DECRYPT_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMT_RSA_DECRYPT_DATA))) +#define TPM2B_PUBLIC_KEY_RSA_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPM2B_PUBLIC_KEY_RSA_DATA))) +#define TPMI_RSA_KEY_BITS_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_RSA_KEY_BITS_DATA))) +#define TPM2B_PRIVATE_KEY_RSA_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPM2B_PRIVATE_KEY_RSA_DATA))) +#define TPM2B_ECC_PARAMETER_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPM2B_ECC_PARAMETER_DATA))) +#define TPMS_ECC_POINT_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMS_ECC_POINT_DATA))) +#define TPM2B_ECC_POINT_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPM2B_ECC_POINT_DATA))) +#define TPMI_ALG_ECC_SCHEME_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_ALG_ECC_SCHEME_DATA))) +#define TPMI_ECC_CURVE_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_ECC_CURVE_DATA))) +#define TPMT_ECC_SCHEME_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMT_ECC_SCHEME_DATA))) +#define TPMS_ALGORITHM_DETAIL_ECC_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMS_ALGORITHM_DETAIL_ECC_DATA))) +#define TPMS_SIGNATURE_RSA_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMS_SIGNATURE_RSA_DATA))) +#define TPMS_SIGNATURE_RSASSA_MARSHAL_REF TPMS_SIGNATURE_RSA_MARSHAL_REF +#define TPMS_SIGNATURE_RSAPSS_MARSHAL_REF TPMS_SIGNATURE_RSA_MARSHAL_REF +#define TPMS_SIGNATURE_ECC_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMS_SIGNATURE_ECC_DATA))) +#define TPMS_SIGNATURE_ECDAA_MARSHAL_REF TPMS_SIGNATURE_ECC_MARSHAL_REF +#define TPMS_SIGNATURE_ECDSA_MARSHAL_REF TPMS_SIGNATURE_ECC_MARSHAL_REF +#define TPMS_SIGNATURE_SM2_MARSHAL_REF TPMS_SIGNATURE_ECC_MARSHAL_REF +#define TPMS_SIGNATURE_ECSCHNORR_MARSHAL_REF TPMS_SIGNATURE_ECC_MARSHAL_REF +#define TPMU_SIGNATURE_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMU_SIGNATURE_DATA))) +#define TPMT_SIGNATURE_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMT_SIGNATURE_DATA))) +#define TPMU_ENCRYPTED_SECRET_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMU_ENCRYPTED_SECRET_DATA))) +#define TPM2B_ENCRYPTED_SECRET_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPM2B_ENCRYPTED_SECRET_DATA))) +#define TPMI_ALG_PUBLIC_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMI_ALG_PUBLIC_DATA))) +#define TPMU_PUBLIC_ID_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMU_PUBLIC_ID_DATA))) +#define TPMS_KEYEDHASH_PARMS_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMS_KEYEDHASH_PARMS_DATA))) +#define TPMS_RSA_PARMS_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMS_RSA_PARMS_DATA))) +#define TPMS_ECC_PARMS_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMS_ECC_PARMS_DATA))) +#define TPMU_PUBLIC_PARMS_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMU_PUBLIC_PARMS_DATA))) +#define TPMT_PUBLIC_PARMS_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMT_PUBLIC_PARMS_DATA))) +#define TPMT_PUBLIC_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, TPMT_PUBLIC_DATA))) +#define TPM2B_PUBLIC_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPM2B_PUBLIC_DATA))) +#define TPM2B_TEMPLATE_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPM2B_TEMPLATE_DATA))) +#define TPM2B_PRIVATE_VENDOR_SPECIFIC_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPM2B_PRIVATE_VENDOR_SPECIFIC_DATA))) +#define TPMU_SENSITIVE_COMPOSITE_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMU_SENSITIVE_COMPOSITE_DATA))) +#define TPMT_SENSITIVE_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMT_SENSITIVE_DATA))) +#define TPM2B_SENSITIVE_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPM2B_SENSITIVE_DATA))) +#define TPM2B_PRIVATE_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPM2B_PRIVATE_DATA))) +#define TPM2B_ID_OBJECT_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPM2B_ID_OBJECT_DATA))) +#define TPMS_NV_PIN_COUNTER_PARAMETERS_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMS_NV_PIN_COUNTER_PARAMETERS_DATA))) +#define TPMA_NV_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, TPMA_NV_DATA))) +#define TPMS_NV_PUBLIC_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMS_NV_PUBLIC_DATA))) +#define TPM2B_NV_PUBLIC_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPM2B_NV_PUBLIC_DATA))) +#define TPM2B_CONTEXT_SENSITIVE_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPM2B_CONTEXT_SENSITIVE_DATA))) +#define TPMS_CONTEXT_DATA_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMS_CONTEXT_DATA_DATA))) +#define TPM2B_CONTEXT_DATA_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPM2B_CONTEXT_DATA_DATA))) +#define TPMS_CONTEXT_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMS_CONTEXT_DATA))) +#define TPMS_CREATION_DATA_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMS_CREATION_DATA_DATA))) +#define TPM2B_CREATION_DATA_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPM2B_CREATION_DATA_DATA))) +#define TPM_AT_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, TPM_AT_DATA))) +#define TPMS_AC_OUTPUT_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPMS_AC_OUTPUT_DATA))) +#define TPML_AC_CAPABILITIES_MARSHAL_REF \ + ((UINT16)(offsetof(MarshalData_st, TPML_AC_CAPABILITIES_DATA))) +#define Type00_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type00_DATA))) +#define Type01_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type01_DATA))) +#define Type02_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type02_DATA))) +#define Type03_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type03_DATA))) +#define Type04_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type04_DATA))) +#define Type05_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type05_DATA))) +#define Type06_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type06_DATA))) +#define Type07_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type07_DATA))) +#define Type08_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type08_DATA))) +#define Type09_MARSHAL_REF Type08_MARSHAL_REF +#define Type14_MARSHAL_REF Type08_MARSHAL_REF +#define Type10_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type10_DATA))) +#define Type11_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type11_DATA))) +#define Type12_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type12_DATA))) +#define Type13_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type13_DATA))) +#define Type15_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type15_DATA))) +#define Type16_MARSHAL_REF Type15_MARSHAL_REF +#define Type17_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type17_DATA))) +#define Type18_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type18_DATA))) +#define Type19_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type19_DATA))) +#define Type20_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type20_DATA))) +#define Type21_MARSHAL_REF Type20_MARSHAL_REF +#define Type22_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type22_DATA))) +#define Type23_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type23_DATA))) +#define Type24_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type24_DATA))) +#define Type25_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type25_DATA))) +#define Type26_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type26_DATA))) +#define Type27_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type27_DATA))) +#define Type28_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type28_DATA))) +#define Type29_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type29_DATA))) +#define Type30_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type30_DATA))) +#define Type31_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type31_DATA))) +#define Type32_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type32_DATA))) +#define Type33_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type33_DATA))) +#define Type34_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type34_DATA))) +#define Type35_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type35_DATA))) +#define Type36_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type36_DATA))) +#define Type37_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type37_DATA))) +#define Type38_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type38_DATA))) +#define Type39_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type39_DATA))) +#define Type40_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type40_DATA))) +#define Type41_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type41_DATA))) +#define Type42_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type42_DATA))) +#define Type43_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type43_DATA))) +#define Type44_MARSHAL_REF ((UINT16)(offsetof(MarshalData_st, Type44_DATA))) + +//#defines to change calling sequence for code using marshaling +#define UINT8_Unmarshal(target, buffer, size) \ + Unmarshal(UINT8_MARSHAL_REF, (target), (buffer), (size)) +#define UINT8_Marshal(source, buffer, size) \ + Marshal(UINT8_MARSHAL_REF, (source), (buffer), (size)) +#define BYTE_Unmarshal(target, buffer, size) \ + Unmarshal(UINT8_MARSHAL_REF, (target), (buffer), (size)) +#define BYTE_Marshal(source, buffer, size) \ + Marshal(UINT8_MARSHAL_REF, (source), (buffer), (size)) +#define INT8_Unmarshal(target, buffer, size) \ + Unmarshal(INT8_MARSHAL_REF, (target), (buffer), (size)) +#define INT8_Marshal(source, buffer, size) \ + Marshal(INT8_MARSHAL_REF, (source), (buffer), (size)) +#define UINT16_Unmarshal(target, buffer, size) \ + Unmarshal(UINT16_MARSHAL_REF, (target), (buffer), (size)) +#define UINT16_Marshal(source, buffer, size) \ + Marshal(UINT16_MARSHAL_REF, (source), (buffer), (size)) +#define INT16_Unmarshal(target, buffer, size) \ + Unmarshal(INT16_MARSHAL_REF, (target), (buffer), (size)) +#define INT16_Marshal(source, buffer, size) \ + Marshal(INT16_MARSHAL_REF, (source), (buffer), (size)) +#define UINT32_Unmarshal(target, buffer, size) \ + Unmarshal(UINT32_MARSHAL_REF, (target), (buffer), (size)) +#define UINT32_Marshal(source, buffer, size) \ + Marshal(UINT32_MARSHAL_REF, (source), (buffer), (size)) +#define INT32_Unmarshal(target, buffer, size) \ + Unmarshal(INT32_MARSHAL_REF, (target), (buffer), (size)) +#define INT32_Marshal(source, buffer, size) \ + Marshal(INT32_MARSHAL_REF, (source), (buffer), (size)) +#define UINT64_Unmarshal(target, buffer, size) \ + Unmarshal(UINT64_MARSHAL_REF, (target), (buffer), (size)) +#define UINT64_Marshal(source, buffer, size) \ + Marshal(UINT64_MARSHAL_REF, (source), (buffer), (size)) +#define INT64_Unmarshal(target, buffer, size) \ + Unmarshal(INT64_MARSHAL_REF, (target), (buffer), (size)) +#define INT64_Marshal(source, buffer, size) \ + Marshal(INT64_MARSHAL_REF, (source), (buffer), (size)) +#define TPM_ALGORITHM_ID_Unmarshal(target, buffer, size) \ + Unmarshal(TPM_ALGORITHM_ID_MARSHAL_REF, (target), (buffer), (size)) +#define TPM_ALGORITHM_ID_Marshal(source, buffer, size) \ + Marshal(TPM_ALGORITHM_ID_MARSHAL_REF, (source), (buffer), (size)) +#define TPM_MODIFIER_INDICATOR_Unmarshal(target, buffer, size) \ + Unmarshal(TPM_MODIFIER_INDICATOR_MARSHAL_REF, (target), (buffer), (size)) +#define TPM_MODIFIER_INDICATOR_Marshal(source, buffer, size) \ + Marshal(TPM_MODIFIER_INDICATOR_MARSHAL_REF, (source), (buffer), (size)) +#define TPM_AUTHORIZATION_SIZE_Unmarshal(target, buffer, size) \ + Unmarshal(TPM_AUTHORIZATION_SIZE_MARSHAL_REF, (target), (buffer), (size)) +#define TPM_AUTHORIZATION_SIZE_Marshal(source, buffer, size) \ + Marshal(TPM_AUTHORIZATION_SIZE_MARSHAL_REF, (source), (buffer), (size)) +#define TPM_PARAMETER_SIZE_Unmarshal(target, buffer, size) \ + Unmarshal(TPM_PARAMETER_SIZE_MARSHAL_REF, (target), (buffer), (size)) +#define TPM_PARAMETER_SIZE_Marshal(source, buffer, size) \ + Marshal(TPM_PARAMETER_SIZE_MARSHAL_REF, (source), (buffer), (size)) +#define TPM_KEY_SIZE_Unmarshal(target, buffer, size) \ + Unmarshal(TPM_KEY_SIZE_MARSHAL_REF, (target), (buffer), (size)) +#define TPM_KEY_SIZE_Marshal(source, buffer, size) \ + Marshal(TPM_KEY_SIZE_MARSHAL_REF, (source), (buffer), (size)) +#define TPM_KEY_BITS_Unmarshal(target, buffer, size) \ + Unmarshal(TPM_KEY_BITS_MARSHAL_REF, (target), (buffer), (size)) +#define TPM_KEY_BITS_Marshal(source, buffer, size) \ + Marshal(TPM_KEY_BITS_MARSHAL_REF, (source), (buffer), (size)) +#define TPM_CONSTANTS32_Marshal(source, buffer, size) \ + Marshal(TPM_CONSTANTS32_MARSHAL_REF, (source), (buffer), (size)) +#define TPM_ALG_ID_Unmarshal(target, buffer, size) \ + Unmarshal(TPM_ALG_ID_MARSHAL_REF, (target), (buffer), (size)) +#define TPM_ALG_ID_Marshal(source, buffer, size) \ + Marshal(TPM_ALG_ID_MARSHAL_REF, (source), (buffer), (size)) +#define TPM_ECC_CURVE_Unmarshal(target, buffer, size) \ + Unmarshal(TPM_ECC_CURVE_MARSHAL_REF, (target), (buffer), (size)) +#define TPM_ECC_CURVE_Marshal(source, buffer, size) \ + Marshal(TPM_ECC_CURVE_MARSHAL_REF, (source), (buffer), (size)) +#define TPM_CC_Unmarshal(target, buffer, size) \ + Unmarshal(TPM_CC_MARSHAL_REF, (target), (buffer), (size)) +#define TPM_CC_Marshal(source, buffer, size) \ + Marshal(TPM_CC_MARSHAL_REF, (source), (buffer), (size)) +#define TPM_RC_Marshal(source, buffer, size) \ + Marshal(TPM_RC_MARSHAL_REF, (source), (buffer), (size)) +#define TPM_CLOCK_ADJUST_Unmarshal(target, buffer, size) \ + Unmarshal(TPM_CLOCK_ADJUST_MARSHAL_REF, (target), (buffer), (size)) +#define TPM_EO_Unmarshal(target, buffer, size) \ + Unmarshal(TPM_EO_MARSHAL_REF, (target), (buffer), (size)) +#define TPM_EO_Marshal(source, buffer, size) \ + Marshal(TPM_EO_MARSHAL_REF, (source), (buffer), (size)) +#define TPM_ST_Unmarshal(target, buffer, size) \ + Unmarshal(TPM_ST_MARSHAL_REF, (target), (buffer), (size)) +#define TPM_ST_Marshal(source, buffer, size) \ + Marshal(TPM_ST_MARSHAL_REF, (source), (buffer), (size)) +#define TPM_SU_Unmarshal(target, buffer, size) \ + Unmarshal(TPM_SU_MARSHAL_REF, (target), (buffer), (size)) +#define TPM_SE_Unmarshal(target, buffer, size) \ + Unmarshal(TPM_SE_MARSHAL_REF, (target), (buffer), (size)) +#define TPM_CAP_Unmarshal(target, buffer, size) \ + Unmarshal(TPM_CAP_MARSHAL_REF, (target), (buffer), (size)) +#define TPM_CAP_Marshal(source, buffer, size) \ + Marshal(TPM_CAP_MARSHAL_REF, (source), (buffer), (size)) +#define TPM_PT_Unmarshal(target, buffer, size) \ + Unmarshal(TPM_PT_MARSHAL_REF, (target), (buffer), (size)) +#define TPM_PT_Marshal(source, buffer, size) \ + Marshal(TPM_PT_MARSHAL_REF, (source), (buffer), (size)) +#define TPM_PT_PCR_Unmarshal(target, buffer, size) \ + Unmarshal(TPM_PT_PCR_MARSHAL_REF, (target), (buffer), (size)) +#define TPM_PT_PCR_Marshal(source, buffer, size) \ + Marshal(TPM_PT_PCR_MARSHAL_REF, (source), (buffer), (size)) +#define TPM_PS_Marshal(source, buffer, size) \ + Marshal(TPM_PS_MARSHAL_REF, (source), (buffer), (size)) +#define TPM_HANDLE_Unmarshal(target, buffer, size) \ + Unmarshal(TPM_HANDLE_MARSHAL_REF, (target), (buffer), (size)) +#define TPM_HANDLE_Marshal(source, buffer, size) \ + Marshal(TPM_HANDLE_MARSHAL_REF, (source), (buffer), (size)) +#define TPM_HT_Unmarshal(target, buffer, size) \ + Unmarshal(TPM_HT_MARSHAL_REF, (target), (buffer), (size)) +#define TPM_HT_Marshal(source, buffer, size) \ + Marshal(TPM_HT_MARSHAL_REF, (source), (buffer), (size)) +#define TPM_RH_Unmarshal(target, buffer, size) \ + Unmarshal(TPM_RH_MARSHAL_REF, (target), (buffer), (size)) +#define TPM_RH_Marshal(source, buffer, size) \ + Marshal(TPM_RH_MARSHAL_REF, (source), (buffer), (size)) +#define TPM_HC_Unmarshal(target, buffer, size) \ + Unmarshal(TPM_HC_MARSHAL_REF, (target), (buffer), (size)) +#define TPM_HC_Marshal(source, buffer, size) \ + Marshal(TPM_HC_MARSHAL_REF, (source), (buffer), (size)) +#define TPMA_ALGORITHM_Unmarshal(target, buffer, size) \ + Unmarshal(TPMA_ALGORITHM_MARSHAL_REF, (target), (buffer), (size)) +#define TPMA_ALGORITHM_Marshal(source, buffer, size) \ + Marshal(TPMA_ALGORITHM_MARSHAL_REF, (source), (buffer), (size)) +#define TPMA_OBJECT_Unmarshal(target, buffer, size) \ + Unmarshal(TPMA_OBJECT_MARSHAL_REF, (target), (buffer), (size)) +#define TPMA_OBJECT_Marshal(source, buffer, size) \ + Marshal(TPMA_OBJECT_MARSHAL_REF, (source), (buffer), (size)) +#define TPMA_SESSION_Unmarshal(target, buffer, size) \ + Unmarshal(TPMA_SESSION_MARSHAL_REF, (target), (buffer), (size)) +#define TPMA_SESSION_Marshal(source, buffer, size) \ + Marshal(TPMA_SESSION_MARSHAL_REF, (source), (buffer), (size)) +#define TPMA_LOCALITY_Unmarshal(target, buffer, size) \ + Unmarshal(TPMA_LOCALITY_MARSHAL_REF, (target), (buffer), (size)) +#define TPMA_LOCALITY_Marshal(source, buffer, size) \ + Marshal(TPMA_LOCALITY_MARSHAL_REF, (source), (buffer), (size)) +#define TPMA_PERMANENT_Marshal(source, buffer, size) \ + Marshal(TPMA_PERMANENT_MARSHAL_REF, (source), (buffer), (size)) +#define TPMA_STARTUP_CLEAR_Marshal(source, buffer, size) \ + Marshal(TPMA_STARTUP_CLEAR_MARSHAL_REF, (source), (buffer), (size)) +#define TPMA_MEMORY_Marshal(source, buffer, size) \ + Marshal(TPMA_MEMORY_MARSHAL_REF, (source), (buffer), (size)) +#define TPMA_CC_Marshal(source, buffer, size) \ + Marshal(TPMA_CC_MARSHAL_REF, (source), (buffer), (size)) +#define TPMA_MODES_Marshal(source, buffer, size) \ + Marshal(TPMA_MODES_MARSHAL_REF, (source), (buffer), (size)) +#define TPMA_X509_KEY_USAGE_Marshal(source, buffer, size) \ + Marshal(TPMA_X509_KEY_USAGE_MARSHAL_REF, (source), (buffer), (size)) +#define TPMA_ACT_Unmarshal(target, buffer, size) \ + Unmarshal(TPMA_ACT_MARSHAL_REF, (target), (buffer), (size)) +#define TPMA_ACT_Marshal(source, buffer, size) \ + Marshal(TPMA_ACT_MARSHAL_REF, (source), (buffer), (size)) +#define TPMI_YES_NO_Unmarshal(target, buffer, size) \ + Unmarshal(TPMI_YES_NO_MARSHAL_REF, (target), (buffer), (size)) +#define TPMI_YES_NO_Marshal(source, buffer, size) \ + Marshal(TPMI_YES_NO_MARSHAL_REF, (source), (buffer), (size)) +#define TPMI_DH_OBJECT_Unmarshal(target, buffer, size, flag) \ + Unmarshal(TPMI_DH_OBJECT_MARSHAL_REF | (flag ? NULL_FLAG : 0), \ + (target), \ + (buffer), \ + (size)) +#define TPMI_DH_OBJECT_Marshal(source, buffer, size) \ + Marshal(TPMI_DH_OBJECT_MARSHAL_REF, (source), (buffer), (size)) +#define TPMI_DH_PARENT_Unmarshal(target, buffer, size, flag) \ + Unmarshal(TPMI_DH_PARENT_MARSHAL_REF | (flag ? NULL_FLAG : 0), \ + (target), \ + (buffer), \ + (size)) +#define TPMI_DH_PARENT_Marshal(source, buffer, size) \ + Marshal(TPMI_DH_PARENT_MARSHAL_REF, (source), (buffer), (size)) +#define TPMI_DH_PERSISTENT_Unmarshal(target, buffer, size) \ + Unmarshal(TPMI_DH_PERSISTENT_MARSHAL_REF, (target), (buffer), (size)) +#define TPMI_DH_PERSISTENT_Marshal(source, buffer, size) \ + Marshal(TPMI_DH_PERSISTENT_MARSHAL_REF, (source), (buffer), (size)) +#define TPMI_DH_ENTITY_Unmarshal(target, buffer, size, flag) \ + Unmarshal(TPMI_DH_ENTITY_MARSHAL_REF | (flag ? NULL_FLAG : 0), \ + (target), \ + (buffer), \ + (size)) +#define TPMI_DH_PCR_Unmarshal(target, buffer, size, flag) \ + Unmarshal( \ + TPMI_DH_PCR_MARSHAL_REF | (flag ? NULL_FLAG : 0), (target), (buffer), (size)) +#define TPMI_SH_AUTH_SESSION_Unmarshal(target, buffer, size, flag) \ + Unmarshal(TPMI_SH_AUTH_SESSION_MARSHAL_REF | (flag ? NULL_FLAG : 0), \ + (target), \ + (buffer), \ + (size)) +#define TPMI_SH_AUTH_SESSION_Marshal(source, buffer, size) \ + Marshal(TPMI_SH_AUTH_SESSION_MARSHAL_REF, (source), (buffer), (size)) +#define TPMI_SH_HMAC_Unmarshal(target, buffer, size) \ + Unmarshal(TPMI_SH_HMAC_MARSHAL_REF, (target), (buffer), (size)) +#define TPMI_SH_HMAC_Marshal(source, buffer, size) \ + Marshal(TPMI_SH_HMAC_MARSHAL_REF, (source), (buffer), (size)) +#define TPMI_SH_POLICY_Unmarshal(target, buffer, size) \ + Unmarshal(TPMI_SH_POLICY_MARSHAL_REF, (target), (buffer), (size)) +#define TPMI_SH_POLICY_Marshal(source, buffer, size) \ + Marshal(TPMI_SH_POLICY_MARSHAL_REF, (source), (buffer), (size)) +#define TPMI_DH_CONTEXT_Unmarshal(target, buffer, size) \ + Unmarshal(TPMI_DH_CONTEXT_MARSHAL_REF, (target), (buffer), (size)) +#define TPMI_DH_CONTEXT_Marshal(source, buffer, size) \ + Marshal(TPMI_DH_CONTEXT_MARSHAL_REF, (source), (buffer), (size)) +#define TPMI_DH_SAVED_Unmarshal(target, buffer, size) \ + Unmarshal(TPMI_DH_SAVED_MARSHAL_REF, (target), (buffer), (size)) +#define TPMI_DH_SAVED_Marshal(source, buffer, size) \ + Marshal(TPMI_DH_SAVED_MARSHAL_REF, (source), (buffer), (size)) +#define TPMI_RH_HIERARCHY_Unmarshal(target, buffer, size, flag) \ + Unmarshal(TPMI_RH_HIERARCHY_MARSHAL_REF | (flag ? NULL_FLAG : 0), \ + (target), \ + (buffer), \ + (size)) +#define TPMI_RH_HIERARCHY_Marshal(source, buffer, size) \ + Marshal(TPMI_RH_HIERARCHY_MARSHAL_REF, (source), (buffer), (size)) +#define TPMI_RH_ENABLES_Unmarshal(target, buffer, size, flag) \ + Unmarshal(TPMI_RH_ENABLES_MARSHAL_REF | (flag ? NULL_FLAG : 0), \ + (target), \ + (buffer), \ + (size)) +#define TPMI_RH_ENABLES_Marshal(source, buffer, size) \ + Marshal(TPMI_RH_ENABLES_MARSHAL_REF, (source), (buffer), (size)) +#define TPMI_RH_HIERARCHY_AUTH_Unmarshal(target, buffer, size) \ + Unmarshal(TPMI_RH_HIERARCHY_AUTH_MARSHAL_REF, (target), (buffer), (size)) +#define TPMI_RH_HIERARCHY_POLICY_Unmarshal(target, buffer, size) \ + Unmarshal(TPMI_RH_HIERARCHY_POLICY_MARSHAL_REF, (target), (buffer), (size)) +#define TPMI_RH_PLATFORM_Unmarshal(target, buffer, size) \ + Unmarshal(TPMI_RH_PLATFORM_MARSHAL_REF, (target), (buffer), (size)) +#define TPMI_RH_OWNER_Unmarshal(target, buffer, size, flag) \ + Unmarshal(TPMI_RH_OWNER_MARSHAL_REF | (flag ? NULL_FLAG : 0), \ + (target), \ + (buffer), \ + (size)) +#define TPMI_RH_ENDORSEMENT_Unmarshal(target, buffer, size, flag) \ + Unmarshal(TPMI_RH_ENDORSEMENT_MARSHAL_REF | (flag ? NULL_FLAG : 0), \ + (target), \ + (buffer), \ + (size)) +#define TPMI_RH_PROVISION_Unmarshal(target, buffer, size) \ + Unmarshal(TPMI_RH_PROVISION_MARSHAL_REF, (target), (buffer), (size)) +#define TPMI_RH_CLEAR_Unmarshal(target, buffer, size) \ + Unmarshal(TPMI_RH_CLEAR_MARSHAL_REF, (target), (buffer), (size)) +#define TPMI_RH_NV_AUTH_Unmarshal(target, buffer, size) \ + Unmarshal(TPMI_RH_NV_AUTH_MARSHAL_REF, (target), (buffer), (size)) +#define TPMI_RH_LOCKOUT_Unmarshal(target, buffer, size) \ + Unmarshal(TPMI_RH_LOCKOUT_MARSHAL_REF, (target), (buffer), (size)) +#define TPMI_RH_NV_INDEX_Unmarshal(target, buffer, size) \ + Unmarshal(TPMI_RH_NV_INDEX_MARSHAL_REF, (target), (buffer), (size)) +#define TPMI_RH_NV_INDEX_Marshal(source, buffer, size) \ + Marshal(TPMI_RH_NV_INDEX_MARSHAL_REF, (source), (buffer), (size)) +#define TPMI_RH_AC_Unmarshal(target, buffer, size) \ + Unmarshal(TPMI_RH_AC_MARSHAL_REF, (target), (buffer), (size)) +#define TPMI_RH_ACT_Unmarshal(target, buffer, size) \ + Unmarshal(TPMI_RH_ACT_MARSHAL_REF, (target), (buffer), (size)) +#define TPMI_RH_ACT_Marshal(source, buffer, size) \ + Marshal(TPMI_RH_ACT_MARSHAL_REF, (source), (buffer), (size)) +#define TPMI_ALG_HASH_Unmarshal(target, buffer, size, flag) \ + Unmarshal(TPMI_ALG_HASH_MARSHAL_REF | (flag ? NULL_FLAG : 0), \ + (target), \ + (buffer), \ + (size)) +#define TPMI_ALG_HASH_Marshal(source, buffer, size) \ + Marshal(TPMI_ALG_HASH_MARSHAL_REF, (source), (buffer), (size)) +#define TPMI_ALG_ASYM_Unmarshal(target, buffer, size, flag) \ + Unmarshal(TPMI_ALG_ASYM_MARSHAL_REF | (flag ? NULL_FLAG : 0), \ + (target), \ + (buffer), \ + (size)) +#define TPMI_ALG_ASYM_Marshal(source, buffer, size) \ + Marshal(TPMI_ALG_ASYM_MARSHAL_REF, (source), (buffer), (size)) +#define TPMI_ALG_SYM_Unmarshal(target, buffer, size, flag) \ + Unmarshal( \ + TPMI_ALG_SYM_MARSHAL_REF | (flag ? NULL_FLAG : 0), (target), (buffer), (size)) +#define TPMI_ALG_SYM_Marshal(source, buffer, size) \ + Marshal(TPMI_ALG_SYM_MARSHAL_REF, (source), (buffer), (size)) +#define TPMI_ALG_SYM_OBJECT_Unmarshal(target, buffer, size, flag) \ + Unmarshal(TPMI_ALG_SYM_OBJECT_MARSHAL_REF | (flag ? NULL_FLAG : 0), \ + (target), \ + (buffer), \ + (size)) +#define TPMI_ALG_SYM_OBJECT_Marshal(source, buffer, size) \ + Marshal(TPMI_ALG_SYM_OBJECT_MARSHAL_REF, (source), (buffer), (size)) +#define TPMI_ALG_SYM_MODE_Unmarshal(target, buffer, size, flag) \ + Unmarshal(TPMI_ALG_SYM_MODE_MARSHAL_REF | (flag ? NULL_FLAG : 0), \ + (target), \ + (buffer), \ + (size)) +#define TPMI_ALG_SYM_MODE_Marshal(source, buffer, size) \ + Marshal(TPMI_ALG_SYM_MODE_MARSHAL_REF, (source), (buffer), (size)) +#define TPMI_ALG_KDF_Unmarshal(target, buffer, size, flag) \ + Unmarshal( \ + TPMI_ALG_KDF_MARSHAL_REF | (flag ? NULL_FLAG : 0), (target), (buffer), (size)) +#define TPMI_ALG_KDF_Marshal(source, buffer, size) \ + Marshal(TPMI_ALG_KDF_MARSHAL_REF, (source), (buffer), (size)) +#define TPMI_ALG_SIG_SCHEME_Unmarshal(target, buffer, size, flag) \ + Unmarshal(TPMI_ALG_SIG_SCHEME_MARSHAL_REF | (flag ? NULL_FLAG : 0), \ + (target), \ + (buffer), \ + (size)) +#define TPMI_ALG_SIG_SCHEME_Marshal(source, buffer, size) \ + Marshal(TPMI_ALG_SIG_SCHEME_MARSHAL_REF, (source), (buffer), (size)) +#define TPMI_ECC_KEY_EXCHANGE_Unmarshal(target, buffer, size, flag) \ + Unmarshal(TPMI_ECC_KEY_EXCHANGE_MARSHAL_REF | (flag ? NULL_FLAG : 0), \ + (target), \ + (buffer), \ + (size)) +#define TPMI_ECC_KEY_EXCHANGE_Marshal(source, buffer, size) \ + Marshal(TPMI_ECC_KEY_EXCHANGE_MARSHAL_REF, (source), (buffer), (size)) +#define TPMI_ST_COMMAND_TAG_Unmarshal(target, buffer, size) \ + Unmarshal(TPMI_ST_COMMAND_TAG_MARSHAL_REF, (target), (buffer), (size)) +#define TPMI_ST_COMMAND_TAG_Marshal(source, buffer, size) \ + Marshal(TPMI_ST_COMMAND_TAG_MARSHAL_REF, (source), (buffer), (size)) +#define TPMI_ALG_MAC_SCHEME_Unmarshal(target, buffer, size, flag) \ + Unmarshal(TPMI_ALG_MAC_SCHEME_MARSHAL_REF | (flag ? NULL_FLAG : 0), \ + (target), \ + (buffer), \ + (size)) +#define TPMI_ALG_MAC_SCHEME_Marshal(source, buffer, size) \ + Marshal(TPMI_ALG_MAC_SCHEME_MARSHAL_REF, (source), (buffer), (size)) +#define TPMI_ALG_CIPHER_MODE_Unmarshal(target, buffer, size, flag) \ + Unmarshal(TPMI_ALG_CIPHER_MODE_MARSHAL_REF | (flag ? NULL_FLAG : 0), \ + (target), \ + (buffer), \ + (size)) +#define TPMI_ALG_CIPHER_MODE_Marshal(source, buffer, size) \ + Marshal(TPMI_ALG_CIPHER_MODE_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_EMPTY_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_EMPTY_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_EMPTY_Marshal(source, buffer, size) \ + Marshal(TPMS_EMPTY_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_ALGORITHM_DESCRIPTION_Marshal(source, buffer, size) \ + Marshal(TPMS_ALGORITHM_DESCRIPTION_MARSHAL_REF, (source), (buffer), (size)) +#define TPMU_HA_Unmarshal(target, buffer, size, selector) \ + UnmarshalUnion(TPMU_HA_MARSHAL_REF, (target), (buffer), (size), (selector)) +#define TPMU_HA_Marshal(source, buffer, size, selector) \ + MarshalUnion(TPMU_HA_MARSHAL_REF, (source), (buffer), (size), (selector)) +#define TPMT_HA_Unmarshal(target, buffer, size, flag) \ + Unmarshal(TPMT_HA_MARSHAL_REF | (flag ? NULL_FLAG : 0), (target), (buffer), (size)) +#define TPMT_HA_Marshal(source, buffer, size) \ + Marshal(TPMT_HA_MARSHAL_REF, (source), (buffer), (size)) +#define TPM2B_DIGEST_Unmarshal(target, buffer, size) \ + Unmarshal(TPM2B_DIGEST_MARSHAL_REF, (target), (buffer), (size)) +#define TPM2B_DIGEST_Marshal(source, buffer, size) \ + Marshal(TPM2B_DIGEST_MARSHAL_REF, (source), (buffer), (size)) +#define TPM2B_DATA_Unmarshal(target, buffer, size) \ + Unmarshal(TPM2B_DATA_MARSHAL_REF, (target), (buffer), (size)) +#define TPM2B_DATA_Marshal(source, buffer, size) \ + Marshal(TPM2B_DATA_MARSHAL_REF, (source), (buffer), (size)) +#define TPM2B_NONCE_Unmarshal(target, buffer, size) \ + Unmarshal(TPM2B_NONCE_MARSHAL_REF, (target), (buffer), (size)) +#define TPM2B_NONCE_Marshal(source, buffer, size) \ + Marshal(TPM2B_NONCE_MARSHAL_REF, (source), (buffer), (size)) +#define TPM2B_AUTH_Unmarshal(target, buffer, size) \ + Unmarshal(TPM2B_AUTH_MARSHAL_REF, (target), (buffer), (size)) +#define TPM2B_AUTH_Marshal(source, buffer, size) \ + Marshal(TPM2B_AUTH_MARSHAL_REF, (source), (buffer), (size)) +#define TPM2B_OPERAND_Unmarshal(target, buffer, size) \ + Unmarshal(TPM2B_OPERAND_MARSHAL_REF, (target), (buffer), (size)) +#define TPM2B_OPERAND_Marshal(source, buffer, size) \ + Marshal(TPM2B_OPERAND_MARSHAL_REF, (source), (buffer), (size)) +#define TPM2B_EVENT_Unmarshal(target, buffer, size) \ + Unmarshal(TPM2B_EVENT_MARSHAL_REF, (target), (buffer), (size)) +#define TPM2B_EVENT_Marshal(source, buffer, size) \ + Marshal(TPM2B_EVENT_MARSHAL_REF, (source), (buffer), (size)) +#define TPM2B_MAX_BUFFER_Unmarshal(target, buffer, size) \ + Unmarshal(TPM2B_MAX_BUFFER_MARSHAL_REF, (target), (buffer), (size)) +#define TPM2B_MAX_BUFFER_Marshal(source, buffer, size) \ + Marshal(TPM2B_MAX_BUFFER_MARSHAL_REF, (source), (buffer), (size)) +#define TPM2B_MAX_NV_BUFFER_Unmarshal(target, buffer, size) \ + Unmarshal(TPM2B_MAX_NV_BUFFER_MARSHAL_REF, (target), (buffer), (size)) +#define TPM2B_MAX_NV_BUFFER_Marshal(source, buffer, size) \ + Marshal(TPM2B_MAX_NV_BUFFER_MARSHAL_REF, (source), (buffer), (size)) +#define TPM2B_TIMEOUT_Unmarshal(target, buffer, size) \ + Unmarshal(TPM2B_TIMEOUT_MARSHAL_REF, (target), (buffer), (size)) +#define TPM2B_TIMEOUT_Marshal(source, buffer, size) \ + Marshal(TPM2B_TIMEOUT_MARSHAL_REF, (source), (buffer), (size)) +#define TPM2B_IV_Unmarshal(target, buffer, size) \ + Unmarshal(TPM2B_IV_MARSHAL_REF, (target), (buffer), (size)) +#define TPM2B_IV_Marshal(source, buffer, size) \ + Marshal(TPM2B_IV_MARSHAL_REF, (source), (buffer), (size)) +#define TPM2B_NAME_Unmarshal(target, buffer, size) \ + Unmarshal(TPM2B_NAME_MARSHAL_REF, (target), (buffer), (size)) +#define TPM2B_NAME_Marshal(source, buffer, size) \ + Marshal(TPM2B_NAME_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_PCR_SELECT_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_PCR_SELECT_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_PCR_SELECT_Marshal(source, buffer, size) \ + Marshal(TPMS_PCR_SELECT_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_PCR_SELECTION_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_PCR_SELECTION_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_PCR_SELECTION_Marshal(source, buffer, size) \ + Marshal(TPMS_PCR_SELECTION_MARSHAL_REF, (source), (buffer), (size)) +#define TPMT_TK_CREATION_Unmarshal(target, buffer, size) \ + Unmarshal(TPMT_TK_CREATION_MARSHAL_REF, (target), (buffer), (size)) +#define TPMT_TK_CREATION_Marshal(source, buffer, size) \ + Marshal(TPMT_TK_CREATION_MARSHAL_REF, (source), (buffer), (size)) +#define TPMT_TK_VERIFIED_Unmarshal(target, buffer, size) \ + Unmarshal(TPMT_TK_VERIFIED_MARSHAL_REF, (target), (buffer), (size)) +#define TPMT_TK_VERIFIED_Marshal(source, buffer, size) \ + Marshal(TPMT_TK_VERIFIED_MARSHAL_REF, (source), (buffer), (size)) +#define TPMT_TK_AUTH_Unmarshal(target, buffer, size) \ + Unmarshal(TPMT_TK_AUTH_MARSHAL_REF, (target), (buffer), (size)) +#define TPMT_TK_AUTH_Marshal(source, buffer, size) \ + Marshal(TPMT_TK_AUTH_MARSHAL_REF, (source), (buffer), (size)) +#define TPMT_TK_HASHCHECK_Unmarshal(target, buffer, size) \ + Unmarshal(TPMT_TK_HASHCHECK_MARSHAL_REF, (target), (buffer), (size)) +#define TPMT_TK_HASHCHECK_Marshal(source, buffer, size) \ + Marshal(TPMT_TK_HASHCHECK_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_ALG_PROPERTY_Marshal(source, buffer, size) \ + Marshal(TPMS_ALG_PROPERTY_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_TAGGED_PROPERTY_Marshal(source, buffer, size) \ + Marshal(TPMS_TAGGED_PROPERTY_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_TAGGED_PCR_SELECT_Marshal(source, buffer, size) \ + Marshal(TPMS_TAGGED_PCR_SELECT_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_TAGGED_POLICY_Marshal(source, buffer, size) \ + Marshal(TPMS_TAGGED_POLICY_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_ACT_DATA_Marshal(source, buffer, size) \ + Marshal(TPMS_ACT_DATA_MARSHAL_REF, (source), (buffer), (size)) +#define TPML_CC_Unmarshal(target, buffer, size) \ + Unmarshal(TPML_CC_MARSHAL_REF, (target), (buffer), (size)) +#define TPML_CC_Marshal(source, buffer, size) \ + Marshal(TPML_CC_MARSHAL_REF, (source), (buffer), (size)) +#define TPML_CCA_Marshal(source, buffer, size) \ + Marshal(TPML_CCA_MARSHAL_REF, (source), (buffer), (size)) +#define TPML_ALG_Unmarshal(target, buffer, size) \ + Unmarshal(TPML_ALG_MARSHAL_REF, (target), (buffer), (size)) +#define TPML_ALG_Marshal(source, buffer, size) \ + Marshal(TPML_ALG_MARSHAL_REF, (source), (buffer), (size)) +#define TPML_HANDLE_Marshal(source, buffer, size) \ + Marshal(TPML_HANDLE_MARSHAL_REF, (source), (buffer), (size)) +#define TPML_DIGEST_Unmarshal(target, buffer, size) \ + Unmarshal(TPML_DIGEST_MARSHAL_REF, (target), (buffer), (size)) +#define TPML_DIGEST_Marshal(source, buffer, size) \ + Marshal(TPML_DIGEST_MARSHAL_REF, (source), (buffer), (size)) +#define TPML_DIGEST_VALUES_Unmarshal(target, buffer, size) \ + Unmarshal(TPML_DIGEST_VALUES_MARSHAL_REF, (target), (buffer), (size)) +#define TPML_DIGEST_VALUES_Marshal(source, buffer, size) \ + Marshal(TPML_DIGEST_VALUES_MARSHAL_REF, (source), (buffer), (size)) +#define TPML_PCR_SELECTION_Unmarshal(target, buffer, size) \ + Unmarshal(TPML_PCR_SELECTION_MARSHAL_REF, (target), (buffer), (size)) +#define TPML_PCR_SELECTION_Marshal(source, buffer, size) \ + Marshal(TPML_PCR_SELECTION_MARSHAL_REF, (source), (buffer), (size)) +#define TPML_ALG_PROPERTY_Marshal(source, buffer, size) \ + Marshal(TPML_ALG_PROPERTY_MARSHAL_REF, (source), (buffer), (size)) +#define TPML_TAGGED_TPM_PROPERTY_Marshal(source, buffer, size) \ + Marshal(TPML_TAGGED_TPM_PROPERTY_MARSHAL_REF, (source), (buffer), (size)) +#define TPML_TAGGED_PCR_PROPERTY_Marshal(source, buffer, size) \ + Marshal(TPML_TAGGED_PCR_PROPERTY_MARSHAL_REF, (source), (buffer), (size)) +#define TPML_ECC_CURVE_Marshal(source, buffer, size) \ + Marshal(TPML_ECC_CURVE_MARSHAL_REF, (source), (buffer), (size)) +#define TPML_TAGGED_POLICY_Marshal(source, buffer, size) \ + Marshal(TPML_TAGGED_POLICY_MARSHAL_REF, (source), (buffer), (size)) +#define TPML_ACT_DATA_Marshal(source, buffer, size) \ + Marshal(TPML_ACT_DATA_MARSHAL_REF, (source), (buffer), (size)) +#define TPMU_CAPABILITIES_Marshal(source, buffer, size, selector) \ + MarshalUnion(TPMU_CAPABILITIES_MARSHAL_REF, (source), (buffer), (size), (selector)) +#define TPMS_CAPABILITY_DATA_Marshal(source, buffer, size) \ + Marshal(TPMS_CAPABILITY_DATA_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_CLOCK_INFO_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_CLOCK_INFO_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_CLOCK_INFO_Marshal(source, buffer, size) \ + Marshal(TPMS_CLOCK_INFO_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_TIME_INFO_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_TIME_INFO_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_TIME_INFO_Marshal(source, buffer, size) \ + Marshal(TPMS_TIME_INFO_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_TIME_ATTEST_INFO_Marshal(source, buffer, size) \ + Marshal(TPMS_TIME_ATTEST_INFO_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_CERTIFY_INFO_Marshal(source, buffer, size) \ + Marshal(TPMS_CERTIFY_INFO_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_QUOTE_INFO_Marshal(source, buffer, size) \ + Marshal(TPMS_QUOTE_INFO_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_COMMAND_AUDIT_INFO_Marshal(source, buffer, size) \ + Marshal(TPMS_COMMAND_AUDIT_INFO_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_SESSION_AUDIT_INFO_Marshal(source, buffer, size) \ + Marshal(TPMS_SESSION_AUDIT_INFO_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_CREATION_INFO_Marshal(source, buffer, size) \ + Marshal(TPMS_CREATION_INFO_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_NV_CERTIFY_INFO_Marshal(source, buffer, size) \ + Marshal(TPMS_NV_CERTIFY_INFO_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_NV_DIGEST_CERTIFY_INFO_Marshal(source, buffer, size) \ + Marshal(TPMS_NV_DIGEST_CERTIFY_INFO_MARSHAL_REF, (source), (buffer), (size)) +#define TPMI_ST_ATTEST_Marshal(source, buffer, size) \ + Marshal(TPMI_ST_ATTEST_MARSHAL_REF, (source), (buffer), (size)) +#define TPMU_ATTEST_Marshal(source, buffer, size, selector) \ + MarshalUnion(TPMU_ATTEST_MARSHAL_REF, (source), (buffer), (size), (selector)) +#define TPMS_ATTEST_Marshal(source, buffer, size) \ + Marshal(TPMS_ATTEST_MARSHAL_REF, (source), (buffer), (size)) +#define TPM2B_ATTEST_Marshal(source, buffer, size) \ + Marshal(TPM2B_ATTEST_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_AUTH_COMMAND_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_AUTH_COMMAND_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_AUTH_RESPONSE_Marshal(source, buffer, size) \ + Marshal(TPMS_AUTH_RESPONSE_MARSHAL_REF, (source), (buffer), (size)) +#define TPMI_TDES_KEY_BITS_Unmarshal(target, buffer, size) \ + Unmarshal(TPMI_TDES_KEY_BITS_MARSHAL_REF, (target), (buffer), (size)) +#define TPMI_TDES_KEY_BITS_Marshal(source, buffer, size) \ + Marshal(TPMI_TDES_KEY_BITS_MARSHAL_REF, (source), (buffer), (size)) +#define TPMI_AES_KEY_BITS_Unmarshal(target, buffer, size) \ + Unmarshal(TPMI_AES_KEY_BITS_MARSHAL_REF, (target), (buffer), (size)) +#define TPMI_AES_KEY_BITS_Marshal(source, buffer, size) \ + Marshal(TPMI_AES_KEY_BITS_MARSHAL_REF, (source), (buffer), (size)) +#define TPMI_SM4_KEY_BITS_Unmarshal(target, buffer, size) \ + Unmarshal(TPMI_SM4_KEY_BITS_MARSHAL_REF, (target), (buffer), (size)) +#define TPMI_SM4_KEY_BITS_Marshal(source, buffer, size) \ + Marshal(TPMI_SM4_KEY_BITS_MARSHAL_REF, (source), (buffer), (size)) +#define TPMI_CAMELLIA_KEY_BITS_Unmarshal(target, buffer, size) \ + Unmarshal(TPMI_CAMELLIA_KEY_BITS_MARSHAL_REF, (target), (buffer), (size)) +#define TPMI_CAMELLIA_KEY_BITS_Marshal(source, buffer, size) \ + Marshal(TPMI_CAMELLIA_KEY_BITS_MARSHAL_REF, (source), (buffer), (size)) +#define TPMU_SYM_KEY_BITS_Unmarshal(target, buffer, size, selector) \ + UnmarshalUnion( \ + TPMU_SYM_KEY_BITS_MARSHAL_REF, (target), (buffer), (size), (selector)) +#define TPMU_SYM_KEY_BITS_Marshal(source, buffer, size, selector) \ + MarshalUnion(TPMU_SYM_KEY_BITS_MARSHAL_REF, (source), (buffer), (size), (selector)) +#define TPMU_SYM_MODE_Unmarshal(target, buffer, size, selector) \ + UnmarshalUnion(TPMU_SYM_MODE_MARSHAL_REF, (target), (buffer), (size), (selector)) +#define TPMU_SYM_MODE_Marshal(source, buffer, size, selector) \ + MarshalUnion(TPMU_SYM_MODE_MARSHAL_REF, (source), (buffer), (size), (selector)) +#define TPMT_SYM_DEF_Unmarshal(target, buffer, size, flag) \ + Unmarshal( \ + TPMT_SYM_DEF_MARSHAL_REF | (flag ? NULL_FLAG : 0), (target), (buffer), (size)) +#define TPMT_SYM_DEF_Marshal(source, buffer, size) \ + Marshal(TPMT_SYM_DEF_MARSHAL_REF, (source), (buffer), (size)) +#define TPMT_SYM_DEF_OBJECT_Unmarshal(target, buffer, size, flag) \ + Unmarshal(TPMT_SYM_DEF_OBJECT_MARSHAL_REF | (flag ? NULL_FLAG : 0), \ + (target), \ + (buffer), \ + (size)) +#define TPMT_SYM_DEF_OBJECT_Marshal(source, buffer, size) \ + Marshal(TPMT_SYM_DEF_OBJECT_MARSHAL_REF, (source), (buffer), (size)) +#define TPM2B_SYM_KEY_Unmarshal(target, buffer, size) \ + Unmarshal(TPM2B_SYM_KEY_MARSHAL_REF, (target), (buffer), (size)) +#define TPM2B_SYM_KEY_Marshal(source, buffer, size) \ + Marshal(TPM2B_SYM_KEY_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_SYMCIPHER_PARMS_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_SYMCIPHER_PARMS_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_SYMCIPHER_PARMS_Marshal(source, buffer, size) \ + Marshal(TPMS_SYMCIPHER_PARMS_MARSHAL_REF, (source), (buffer), (size)) +#define TPM2B_LABEL_Unmarshal(target, buffer, size) \ + Unmarshal(TPM2B_LABEL_MARSHAL_REF, (target), (buffer), (size)) +#define TPM2B_LABEL_Marshal(source, buffer, size) \ + Marshal(TPM2B_LABEL_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_DERIVE_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_DERIVE_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_DERIVE_Marshal(source, buffer, size) \ + Marshal(TPMS_DERIVE_MARSHAL_REF, (source), (buffer), (size)) +#define TPM2B_DERIVE_Unmarshal(target, buffer, size) \ + Unmarshal(TPM2B_DERIVE_MARSHAL_REF, (target), (buffer), (size)) +#define TPM2B_DERIVE_Marshal(source, buffer, size) \ + Marshal(TPM2B_DERIVE_MARSHAL_REF, (source), (buffer), (size)) +#define TPM2B_SENSITIVE_DATA_Unmarshal(target, buffer, size) \ + Unmarshal(TPM2B_SENSITIVE_DATA_MARSHAL_REF, (target), (buffer), (size)) +#define TPM2B_SENSITIVE_DATA_Marshal(source, buffer, size) \ + Marshal(TPM2B_SENSITIVE_DATA_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_SENSITIVE_CREATE_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_SENSITIVE_CREATE_MARSHAL_REF, (target), (buffer), (size)) +#define TPM2B_SENSITIVE_CREATE_Unmarshal(target, buffer, size) \ + Unmarshal(TPM2B_SENSITIVE_CREATE_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_SCHEME_HASH_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_SCHEME_HASH_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_SCHEME_HASH_Marshal(source, buffer, size) \ + Marshal(TPMS_SCHEME_HASH_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_SCHEME_ECDAA_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_SCHEME_ECDAA_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_SCHEME_ECDAA_Marshal(source, buffer, size) \ + Marshal(TPMS_SCHEME_ECDAA_MARSHAL_REF, (source), (buffer), (size)) +#define TPMI_ALG_KEYEDHASH_SCHEME_Unmarshal(target, buffer, size, flag) \ + Unmarshal(TPMI_ALG_KEYEDHASH_SCHEME_MARSHAL_REF | (flag ? NULL_FLAG : 0), \ + (target), \ + (buffer), \ + (size)) +#define TPMI_ALG_KEYEDHASH_SCHEME_Marshal(source, buffer, size) \ + Marshal(TPMI_ALG_KEYEDHASH_SCHEME_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_SCHEME_HMAC_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_SCHEME_HMAC_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_SCHEME_HMAC_Marshal(source, buffer, size) \ + Marshal(TPMS_SCHEME_HMAC_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_SCHEME_XOR_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_SCHEME_XOR_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_SCHEME_XOR_Marshal(source, buffer, size) \ + Marshal(TPMS_SCHEME_XOR_MARSHAL_REF, (source), (buffer), (size)) +#define TPMU_SCHEME_KEYEDHASH_Unmarshal(target, buffer, size, selector) \ + UnmarshalUnion( \ + TPMU_SCHEME_KEYEDHASH_MARSHAL_REF, (target), (buffer), (size), (selector)) +#define TPMU_SCHEME_KEYEDHASH_Marshal(source, buffer, size, selector) \ + MarshalUnion( \ + TPMU_SCHEME_KEYEDHASH_MARSHAL_REF, (source), (buffer), (size), (selector)) +#define TPMT_KEYEDHASH_SCHEME_Unmarshal(target, buffer, size, flag) \ + Unmarshal(TPMT_KEYEDHASH_SCHEME_MARSHAL_REF | (flag ? NULL_FLAG : 0), \ + (target), \ + (buffer), \ + (size)) +#define TPMT_KEYEDHASH_SCHEME_Marshal(source, buffer, size) \ + Marshal(TPMT_KEYEDHASH_SCHEME_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_SIG_SCHEME_RSASSA_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_SIG_SCHEME_RSASSA_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_SIG_SCHEME_RSASSA_Marshal(source, buffer, size) \ + Marshal(TPMS_SIG_SCHEME_RSASSA_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_SIG_SCHEME_RSAPSS_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_SIG_SCHEME_RSAPSS_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_SIG_SCHEME_RSAPSS_Marshal(source, buffer, size) \ + Marshal(TPMS_SIG_SCHEME_RSAPSS_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_SIG_SCHEME_ECDSA_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_SIG_SCHEME_ECDSA_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_SIG_SCHEME_ECDSA_Marshal(source, buffer, size) \ + Marshal(TPMS_SIG_SCHEME_ECDSA_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_SIG_SCHEME_SM2_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_SIG_SCHEME_SM2_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_SIG_SCHEME_SM2_Marshal(source, buffer, size) \ + Marshal(TPMS_SIG_SCHEME_SM2_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_SIG_SCHEME_ECSCHNORR_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_SIG_SCHEME_ECSCHNORR_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_SIG_SCHEME_ECSCHNORR_Marshal(source, buffer, size) \ + Marshal(TPMS_SIG_SCHEME_ECSCHNORR_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_SIG_SCHEME_ECDAA_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_SIG_SCHEME_ECDAA_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_SIG_SCHEME_ECDAA_Marshal(source, buffer, size) \ + Marshal(TPMS_SIG_SCHEME_ECDAA_MARSHAL_REF, (source), (buffer), (size)) +#define TPMU_SIG_SCHEME_Unmarshal(target, buffer, size, selector) \ + UnmarshalUnion(TPMU_SIG_SCHEME_MARSHAL_REF, (target), (buffer), (size), (selector)) +#define TPMU_SIG_SCHEME_Marshal(source, buffer, size, selector) \ + MarshalUnion(TPMU_SIG_SCHEME_MARSHAL_REF, (source), (buffer), (size), (selector)) +#define TPMT_SIG_SCHEME_Unmarshal(target, buffer, size, flag) \ + Unmarshal(TPMT_SIG_SCHEME_MARSHAL_REF | (flag ? NULL_FLAG : 0), \ + (target), \ + (buffer), \ + (size)) +#define TPMT_SIG_SCHEME_Marshal(source, buffer, size) \ + Marshal(TPMT_SIG_SCHEME_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_ENC_SCHEME_OAEP_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_ENC_SCHEME_OAEP_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_ENC_SCHEME_OAEP_Marshal(source, buffer, size) \ + Marshal(TPMS_ENC_SCHEME_OAEP_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_ENC_SCHEME_RSAES_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_ENC_SCHEME_RSAES_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_ENC_SCHEME_RSAES_Marshal(source, buffer, size) \ + Marshal(TPMS_ENC_SCHEME_RSAES_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_KEY_SCHEME_ECDH_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_KEY_SCHEME_ECDH_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_KEY_SCHEME_ECDH_Marshal(source, buffer, size) \ + Marshal(TPMS_KEY_SCHEME_ECDH_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_KEY_SCHEME_ECMQV_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_KEY_SCHEME_ECMQV_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_KEY_SCHEME_ECMQV_Marshal(source, buffer, size) \ + Marshal(TPMS_KEY_SCHEME_ECMQV_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_KDF_SCHEME_MGF1_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_KDF_SCHEME_MGF1_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_KDF_SCHEME_MGF1_Marshal(source, buffer, size) \ + Marshal(TPMS_KDF_SCHEME_MGF1_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_KDF_SCHEME_KDF1_SP800_56A_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_KDF_SCHEME_KDF1_SP800_56A_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_KDF_SCHEME_KDF1_SP800_56A_Marshal(source, buffer, size) \ + Marshal(TPMS_KDF_SCHEME_KDF1_SP800_56A_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_KDF_SCHEME_KDF2_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_KDF_SCHEME_KDF2_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_KDF_SCHEME_KDF2_Marshal(source, buffer, size) \ + Marshal(TPMS_KDF_SCHEME_KDF2_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_KDF_SCHEME_KDF1_SP800_108_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_KDF_SCHEME_KDF1_SP800_108_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_KDF_SCHEME_KDF1_SP800_108_Marshal(source, buffer, size) \ + Marshal(TPMS_KDF_SCHEME_KDF1_SP800_108_MARSHAL_REF, (source), (buffer), (size)) +#define TPMU_KDF_SCHEME_Unmarshal(target, buffer, size, selector) \ + UnmarshalUnion(TPMU_KDF_SCHEME_MARSHAL_REF, (target), (buffer), (size), (selector)) +#define TPMU_KDF_SCHEME_Marshal(source, buffer, size, selector) \ + MarshalUnion(TPMU_KDF_SCHEME_MARSHAL_REF, (source), (buffer), (size), (selector)) +#define TPMT_KDF_SCHEME_Unmarshal(target, buffer, size, flag) \ + Unmarshal(TPMT_KDF_SCHEME_MARSHAL_REF | (flag ? NULL_FLAG : 0), \ + (target), \ + (buffer), \ + (size)) +#define TPMT_KDF_SCHEME_Marshal(source, buffer, size) \ + Marshal(TPMT_KDF_SCHEME_MARSHAL_REF, (source), (buffer), (size)) +#define TPMI_ALG_ASYM_SCHEME_Unmarshal(target, buffer, size, flag) \ + Unmarshal(TPMI_ALG_ASYM_SCHEME_MARSHAL_REF | (flag ? NULL_FLAG : 0), \ + (target), \ + (buffer), \ + (size)) +#define TPMI_ALG_ASYM_SCHEME_Marshal(source, buffer, size) \ + Marshal(TPMI_ALG_ASYM_SCHEME_MARSHAL_REF, (source), (buffer), (size)) +#define TPMU_ASYM_SCHEME_Unmarshal(target, buffer, size, selector) \ + UnmarshalUnion(TPMU_ASYM_SCHEME_MARSHAL_REF, (target), (buffer), (size), (selector)) +#define TPMU_ASYM_SCHEME_Marshal(source, buffer, size, selector) \ + MarshalUnion(TPMU_ASYM_SCHEME_MARSHAL_REF, (source), (buffer), (size), (selector)) +#define TPMI_ALG_RSA_SCHEME_Unmarshal(target, buffer, size, flag) \ + Unmarshal(TPMI_ALG_RSA_SCHEME_MARSHAL_REF | (flag ? NULL_FLAG : 0), \ + (target), \ + (buffer), \ + (size)) +#define TPMI_ALG_RSA_SCHEME_Marshal(source, buffer, size) \ + Marshal(TPMI_ALG_RSA_SCHEME_MARSHAL_REF, (source), (buffer), (size)) +#define TPMT_RSA_SCHEME_Unmarshal(target, buffer, size, flag) \ + Unmarshal(TPMT_RSA_SCHEME_MARSHAL_REF | (flag ? NULL_FLAG : 0), \ + (target), \ + (buffer), \ + (size)) +#define TPMT_RSA_SCHEME_Marshal(source, buffer, size) \ + Marshal(TPMT_RSA_SCHEME_MARSHAL_REF, (source), (buffer), (size)) +#define TPMI_ALG_RSA_DECRYPT_Unmarshal(target, buffer, size, flag) \ + Unmarshal(TPMI_ALG_RSA_DECRYPT_MARSHAL_REF | (flag ? NULL_FLAG : 0), \ + (target), \ + (buffer), \ + (size)) +#define TPMI_ALG_RSA_DECRYPT_Marshal(source, buffer, size) \ + Marshal(TPMI_ALG_RSA_DECRYPT_MARSHAL_REF, (source), (buffer), (size)) +#define TPMT_RSA_DECRYPT_Unmarshal(target, buffer, size, flag) \ + Unmarshal(TPMT_RSA_DECRYPT_MARSHAL_REF | (flag ? NULL_FLAG : 0), \ + (target), \ + (buffer), \ + (size)) +#define TPMT_RSA_DECRYPT_Marshal(source, buffer, size) \ + Marshal(TPMT_RSA_DECRYPT_MARSHAL_REF, (source), (buffer), (size)) +#define TPM2B_PUBLIC_KEY_RSA_Unmarshal(target, buffer, size) \ + Unmarshal(TPM2B_PUBLIC_KEY_RSA_MARSHAL_REF, (target), (buffer), (size)) +#define TPM2B_PUBLIC_KEY_RSA_Marshal(source, buffer, size) \ + Marshal(TPM2B_PUBLIC_KEY_RSA_MARSHAL_REF, (source), (buffer), (size)) +#define TPMI_RSA_KEY_BITS_Unmarshal(target, buffer, size) \ + Unmarshal(TPMI_RSA_KEY_BITS_MARSHAL_REF, (target), (buffer), (size)) +#define TPMI_RSA_KEY_BITS_Marshal(source, buffer, size) \ + Marshal(TPMI_RSA_KEY_BITS_MARSHAL_REF, (source), (buffer), (size)) +#define TPM2B_PRIVATE_KEY_RSA_Unmarshal(target, buffer, size) \ + Unmarshal(TPM2B_PRIVATE_KEY_RSA_MARSHAL_REF, (target), (buffer), (size)) +#define TPM2B_PRIVATE_KEY_RSA_Marshal(source, buffer, size) \ + Marshal(TPM2B_PRIVATE_KEY_RSA_MARSHAL_REF, (source), (buffer), (size)) +#define TPM2B_ECC_PARAMETER_Unmarshal(target, buffer, size) \ + Unmarshal(TPM2B_ECC_PARAMETER_MARSHAL_REF, (target), (buffer), (size)) +#define TPM2B_ECC_PARAMETER_Marshal(source, buffer, size) \ + Marshal(TPM2B_ECC_PARAMETER_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_ECC_POINT_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_ECC_POINT_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_ECC_POINT_Marshal(source, buffer, size) \ + Marshal(TPMS_ECC_POINT_MARSHAL_REF, (source), (buffer), (size)) +#define TPM2B_ECC_POINT_Unmarshal(target, buffer, size) \ + Unmarshal(TPM2B_ECC_POINT_MARSHAL_REF, (target), (buffer), (size)) +#define TPM2B_ECC_POINT_Marshal(source, buffer, size) \ + Marshal(TPM2B_ECC_POINT_MARSHAL_REF, (source), (buffer), (size)) +#define TPMI_ALG_ECC_SCHEME_Unmarshal(target, buffer, size, flag) \ + Unmarshal(TPMI_ALG_ECC_SCHEME_MARSHAL_REF | (flag ? NULL_FLAG : 0), \ + (target), \ + (buffer), \ + (size)) +#define TPMI_ALG_ECC_SCHEME_Marshal(source, buffer, size) \ + Marshal(TPMI_ALG_ECC_SCHEME_MARSHAL_REF, (source), (buffer), (size)) +#define TPMI_ECC_CURVE_Unmarshal(target, buffer, size) \ + Unmarshal(TPMI_ECC_CURVE_MARSHAL_REF, (target), (buffer), (size)) +#define TPMI_ECC_CURVE_Marshal(source, buffer, size) \ + Marshal(TPMI_ECC_CURVE_MARSHAL_REF, (source), (buffer), (size)) +#define TPMT_ECC_SCHEME_Unmarshal(target, buffer, size, flag) \ + Unmarshal(TPMT_ECC_SCHEME_MARSHAL_REF | (flag ? NULL_FLAG : 0), \ + (target), \ + (buffer), \ + (size)) +#define TPMT_ECC_SCHEME_Marshal(source, buffer, size) \ + Marshal(TPMT_ECC_SCHEME_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_ALGORITHM_DETAIL_ECC_Marshal(source, buffer, size) \ + Marshal(TPMS_ALGORITHM_DETAIL_ECC_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_SIGNATURE_RSA_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_SIGNATURE_RSA_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_SIGNATURE_RSA_Marshal(source, buffer, size) \ + Marshal(TPMS_SIGNATURE_RSA_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_SIGNATURE_RSASSA_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_SIGNATURE_RSASSA_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_SIGNATURE_RSASSA_Marshal(source, buffer, size) \ + Marshal(TPMS_SIGNATURE_RSASSA_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_SIGNATURE_RSAPSS_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_SIGNATURE_RSAPSS_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_SIGNATURE_RSAPSS_Marshal(source, buffer, size) \ + Marshal(TPMS_SIGNATURE_RSAPSS_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_SIGNATURE_ECC_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_SIGNATURE_ECC_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_SIGNATURE_ECC_Marshal(source, buffer, size) \ + Marshal(TPMS_SIGNATURE_ECC_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_SIGNATURE_ECDAA_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_SIGNATURE_ECDAA_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_SIGNATURE_ECDAA_Marshal(source, buffer, size) \ + Marshal(TPMS_SIGNATURE_ECDAA_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_SIGNATURE_ECDSA_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_SIGNATURE_ECDSA_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_SIGNATURE_ECDSA_Marshal(source, buffer, size) \ + Marshal(TPMS_SIGNATURE_ECDSA_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_SIGNATURE_SM2_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_SIGNATURE_SM2_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_SIGNATURE_SM2_Marshal(source, buffer, size) \ + Marshal(TPMS_SIGNATURE_SM2_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_SIGNATURE_ECSCHNORR_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_SIGNATURE_ECSCHNORR_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_SIGNATURE_ECSCHNORR_Marshal(source, buffer, size) \ + Marshal(TPMS_SIGNATURE_ECSCHNORR_MARSHAL_REF, (source), (buffer), (size)) +#define TPMU_SIGNATURE_Unmarshal(target, buffer, size, selector) \ + UnmarshalUnion(TPMU_SIGNATURE_MARSHAL_REF, (target), (buffer), (size), (selector)) +#define TPMU_SIGNATURE_Marshal(source, buffer, size, selector) \ + MarshalUnion(TPMU_SIGNATURE_MARSHAL_REF, (source), (buffer), (size), (selector)) +#define TPMT_SIGNATURE_Unmarshal(target, buffer, size, flag) \ + Unmarshal(TPMT_SIGNATURE_MARSHAL_REF | (flag ? NULL_FLAG : 0), \ + (target), \ + (buffer), \ + (size)) +#define TPMT_SIGNATURE_Marshal(source, buffer, size) \ + Marshal(TPMT_SIGNATURE_MARSHAL_REF, (source), (buffer), (size)) +#define TPMU_ENCRYPTED_SECRET_Unmarshal(target, buffer, size, selector) \ + UnmarshalUnion( \ + TPMU_ENCRYPTED_SECRET_MARSHAL_REF, (target), (buffer), (size), (selector)) +#define TPMU_ENCRYPTED_SECRET_Marshal(source, buffer, size, selector) \ + MarshalUnion( \ + TPMU_ENCRYPTED_SECRET_MARSHAL_REF, (source), (buffer), (size), (selector)) +#define TPM2B_ENCRYPTED_SECRET_Unmarshal(target, buffer, size) \ + Unmarshal(TPM2B_ENCRYPTED_SECRET_MARSHAL_REF, (target), (buffer), (size)) +#define TPM2B_ENCRYPTED_SECRET_Marshal(source, buffer, size) \ + Marshal(TPM2B_ENCRYPTED_SECRET_MARSHAL_REF, (source), (buffer), (size)) +#define TPMI_ALG_PUBLIC_Unmarshal(target, buffer, size) \ + Unmarshal(TPMI_ALG_PUBLIC_MARSHAL_REF, (target), (buffer), (size)) +#define TPMI_ALG_PUBLIC_Marshal(source, buffer, size) \ + Marshal(TPMI_ALG_PUBLIC_MARSHAL_REF, (source), (buffer), (size)) +#define TPMU_PUBLIC_ID_Unmarshal(target, buffer, size, selector) \ + UnmarshalUnion(TPMU_PUBLIC_ID_MARSHAL_REF, (target), (buffer), (size), (selector)) +#define TPMU_PUBLIC_ID_Marshal(source, buffer, size, selector) \ + MarshalUnion(TPMU_PUBLIC_ID_MARSHAL_REF, (source), (buffer), (size), (selector)) +#define TPMS_KEYEDHASH_PARMS_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_KEYEDHASH_PARMS_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_KEYEDHASH_PARMS_Marshal(source, buffer, size) \ + Marshal(TPMS_KEYEDHASH_PARMS_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_RSA_PARMS_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_RSA_PARMS_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_RSA_PARMS_Marshal(source, buffer, size) \ + Marshal(TPMS_RSA_PARMS_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_ECC_PARMS_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_ECC_PARMS_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_ECC_PARMS_Marshal(source, buffer, size) \ + Marshal(TPMS_ECC_PARMS_MARSHAL_REF, (source), (buffer), (size)) +#define TPMU_PUBLIC_PARMS_Unmarshal(target, buffer, size, selector) \ + UnmarshalUnion( \ + TPMU_PUBLIC_PARMS_MARSHAL_REF, (target), (buffer), (size), (selector)) +#define TPMU_PUBLIC_PARMS_Marshal(source, buffer, size, selector) \ + MarshalUnion(TPMU_PUBLIC_PARMS_MARSHAL_REF, (source), (buffer), (size), (selector)) +#define TPMT_PUBLIC_PARMS_Unmarshal(target, buffer, size) \ + Unmarshal(TPMT_PUBLIC_PARMS_MARSHAL_REF, (target), (buffer), (size)) +#define TPMT_PUBLIC_PARMS_Marshal(source, buffer, size) \ + Marshal(TPMT_PUBLIC_PARMS_MARSHAL_REF, (source), (buffer), (size)) +#define TPMT_PUBLIC_Unmarshal(target, buffer, size, flag) \ + Unmarshal( \ + TPMT_PUBLIC_MARSHAL_REF | (flag ? NULL_FLAG : 0), (target), (buffer), (size)) +#define TPMT_PUBLIC_Marshal(source, buffer, size) \ + Marshal(TPMT_PUBLIC_MARSHAL_REF, (source), (buffer), (size)) +#define TPM2B_PUBLIC_Unmarshal(target, buffer, size, flag) \ + Unmarshal( \ + TPM2B_PUBLIC_MARSHAL_REF | (flag ? NULL_FLAG : 0), (target), (buffer), (size)) +#define TPM2B_PUBLIC_Marshal(source, buffer, size) \ + Marshal(TPM2B_PUBLIC_MARSHAL_REF, (source), (buffer), (size)) +#define TPM2B_TEMPLATE_Unmarshal(target, buffer, size) \ + Unmarshal(TPM2B_TEMPLATE_MARSHAL_REF, (target), (buffer), (size)) +#define TPM2B_TEMPLATE_Marshal(source, buffer, size) \ + Marshal(TPM2B_TEMPLATE_MARSHAL_REF, (source), (buffer), (size)) +#define TPM2B_PRIVATE_VENDOR_SPECIFIC_Unmarshal(target, buffer, size) \ + Unmarshal(TPM2B_PRIVATE_VENDOR_SPECIFIC_MARSHAL_REF, (target), (buffer), (size)) +#define TPM2B_PRIVATE_VENDOR_SPECIFIC_Marshal(source, buffer, size) \ + Marshal(TPM2B_PRIVATE_VENDOR_SPECIFIC_MARSHAL_REF, (source), (buffer), (size)) +#define TPMU_SENSITIVE_COMPOSITE_Unmarshal(target, buffer, size, selector) \ + UnmarshalUnion( \ + TPMU_SENSITIVE_COMPOSITE_MARSHAL_REF, (target), (buffer), (size), (selector)) +#define TPMU_SENSITIVE_COMPOSITE_Marshal(source, buffer, size, selector) \ + MarshalUnion( \ + TPMU_SENSITIVE_COMPOSITE_MARSHAL_REF, (source), (buffer), (size), (selector)) +#define TPMT_SENSITIVE_Unmarshal(target, buffer, size) \ + Unmarshal(TPMT_SENSITIVE_MARSHAL_REF, (target), (buffer), (size)) +#define TPMT_SENSITIVE_Marshal(source, buffer, size) \ + Marshal(TPMT_SENSITIVE_MARSHAL_REF, (source), (buffer), (size)) +#define TPM2B_SENSITIVE_Unmarshal(target, buffer, size) \ + Unmarshal(TPM2B_SENSITIVE_MARSHAL_REF, (target), (buffer), (size)) +#define TPM2B_SENSITIVE_Marshal(source, buffer, size) \ + Marshal(TPM2B_SENSITIVE_MARSHAL_REF, (source), (buffer), (size)) +#define TPM2B_PRIVATE_Unmarshal(target, buffer, size) \ + Unmarshal(TPM2B_PRIVATE_MARSHAL_REF, (target), (buffer), (size)) +#define TPM2B_PRIVATE_Marshal(source, buffer, size) \ + Marshal(TPM2B_PRIVATE_MARSHAL_REF, (source), (buffer), (size)) +#define TPM2B_ID_OBJECT_Unmarshal(target, buffer, size) \ + Unmarshal(TPM2B_ID_OBJECT_MARSHAL_REF, (target), (buffer), (size)) +#define TPM2B_ID_OBJECT_Marshal(source, buffer, size) \ + Marshal(TPM2B_ID_OBJECT_MARSHAL_REF, (source), (buffer), (size)) +#define TPM_NV_INDEX_Marshal(source, buffer, size) \ + Marshal(TPM_NV_INDEX_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_NV_PIN_COUNTER_PARAMETERS_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_NV_PIN_COUNTER_PARAMETERS_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_NV_PIN_COUNTER_PARAMETERS_Marshal(source, buffer, size) \ + Marshal(TPMS_NV_PIN_COUNTER_PARAMETERS_MARSHAL_REF, (source), (buffer), (size)) +#define TPMA_NV_Unmarshal(target, buffer, size) \ + Unmarshal(TPMA_NV_MARSHAL_REF, (target), (buffer), (size)) +#define TPMA_NV_Marshal(source, buffer, size) \ + Marshal(TPMA_NV_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_NV_PUBLIC_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_NV_PUBLIC_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_NV_PUBLIC_Marshal(source, buffer, size) \ + Marshal(TPMS_NV_PUBLIC_MARSHAL_REF, (source), (buffer), (size)) +#define TPM2B_NV_PUBLIC_Unmarshal(target, buffer, size) \ + Unmarshal(TPM2B_NV_PUBLIC_MARSHAL_REF, (target), (buffer), (size)) +#define TPM2B_NV_PUBLIC_Marshal(source, buffer, size) \ + Marshal(TPM2B_NV_PUBLIC_MARSHAL_REF, (source), (buffer), (size)) +#define TPM2B_CONTEXT_SENSITIVE_Unmarshal(target, buffer, size) \ + Unmarshal(TPM2B_CONTEXT_SENSITIVE_MARSHAL_REF, (target), (buffer), (size)) +#define TPM2B_CONTEXT_SENSITIVE_Marshal(source, buffer, size) \ + Marshal(TPM2B_CONTEXT_SENSITIVE_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_CONTEXT_DATA_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_CONTEXT_DATA_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_CONTEXT_DATA_Marshal(source, buffer, size) \ + Marshal(TPMS_CONTEXT_DATA_MARSHAL_REF, (source), (buffer), (size)) +#define TPM2B_CONTEXT_DATA_Unmarshal(target, buffer, size) \ + Unmarshal(TPM2B_CONTEXT_DATA_MARSHAL_REF, (target), (buffer), (size)) +#define TPM2B_CONTEXT_DATA_Marshal(source, buffer, size) \ + Marshal(TPM2B_CONTEXT_DATA_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_CONTEXT_Unmarshal(target, buffer, size) \ + Unmarshal(TPMS_CONTEXT_MARSHAL_REF, (target), (buffer), (size)) +#define TPMS_CONTEXT_Marshal(source, buffer, size) \ + Marshal(TPMS_CONTEXT_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_CREATION_DATA_Marshal(source, buffer, size) \ + Marshal(TPMS_CREATION_DATA_MARSHAL_REF, (source), (buffer), (size)) +#define TPM2B_CREATION_DATA_Marshal(source, buffer, size) \ + Marshal(TPM2B_CREATION_DATA_MARSHAL_REF, (source), (buffer), (size)) +#define TPM_AT_Unmarshal(target, buffer, size) \ + Unmarshal(TPM_AT_MARSHAL_REF, (target), (buffer), (size)) +#define TPM_AT_Marshal(source, buffer, size) \ + Marshal(TPM_AT_MARSHAL_REF, (source), (buffer), (size)) +#define TPM_AE_Marshal(source, buffer, size) \ + Marshal(TPM_AE_MARSHAL_REF, (source), (buffer), (size)) +#define TPMS_AC_OUTPUT_Marshal(source, buffer, size) \ + Marshal(TPMS_AC_OUTPUT_MARSHAL_REF, (source), (buffer), (size)) +#define TPML_AC_CAPABILITIES_Marshal(source, buffer, size) \ + Marshal(TPML_AC_CAPABILITIES_MARSHAL_REF, (source), (buffer), (size)) + +#endif // _TABLE_MARSHAL_DEFINES_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TableMarshalTypes.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TableMarshalTypes.h new file mode 100644 index 0000000..27abc6e --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TableMarshalTypes.h @@ -0,0 +1,1671 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by NewMarshal; Version 1.4 Apr 7, 2019 + * Date: Mar 6, 2020 Time: 01:50:10PM + */ + +#ifndef _TABLE_MARSHAL_TYPES_H_ +#define _TABLE_MARSHAL_TYPES_H_ + +typedef UINT16 marshalIndex_t; + +//*** Structure Entries +// A structure contains a list of elements to unmarshal. Each of the entries is a +// UINT16. The structure descriptor is: + +// The 'values' array contains indicators for the things to marshal. The 'elements' +// parameter indicates how many different entities are unmarshaled. This number +// nominally corresponds to the number of rows in the Part 2 table that describes +// the structure (the number of rows minus the title row and any error code rows). + +// A schematic of a simple structure entry is shown here but the values are not +// actually in a structure. As shown, the third value is the offset in the structure +// where the value is placed when unmarshaled, or fetched from when marshaling. This +// is sufficient when the element type indicated by 'index' is always a simple type +// and never a union or array.This is just shown for illustrative purposes. +typedef struct simpleStructureEntry_t +{ + UINT16 qualifiers; // indicates the type of entry (array, union + // etc.) + marshalIndex_t index; // the index into the appropriate array of + // the descriptor of this type + UINT16 offset; // where this comes from or is placed +} simpleStructureEntry_t; + +typedef const struct UintMarshal_mst +{ + UINT8 marshalType; // UINT_MTYPE + UINT8 modifiers; // size and signed indicator. +} UintMarshal_mst; + +typedef struct UnionMarshal_mst +{ + UINT8 countOfselectors; + UINT8 modifiers; // NULL_SELECTOR + UINT16 offsetOfUnmarshalTypes; + UINT32 selectors[1]; + // UINT16 marshalingTypes[1]; // This is not part of the prototypical + // entry. It is here to show where the + // marshaling types will be in a union +} UnionMarshal_mst; + +typedef struct NullUnionMarshal_mst +{ + UINT8 count; +} NullUnionMarshal_mst; + +typedef struct MarshalHeader_mst +{ + UINT8 marshalType; // VALUES_MTYPE + UINT8 modifiers; + UINT8 errorCode; +} MarshalHeader_mst; + +typedef const struct ArrayMarshal_mst // used in a structure +{ + marshalIndex_t type; + UINT16 stride; +} ArrayMarshal_mst; + +typedef const struct StructMarshal_mst +{ + UINT8 marshalType; // STRUCTURE_MTYPE + UINT8 elements; + UINT16 values[1]; // three times elements +} StructMarshal_mst; + +typedef const struct ValuesMarshal_mst +{ + UINT8 marshalType; // VALUES_MTYPE + UINT8 modifiers; + UINT8 errorCode; + UINT8 ranges; + UINT8 singles; + UINT32 values[1]; +} ValuesMarshal_mst; + +typedef const struct TableMarshal_mst +{ + UINT8 marshalType; // TABLE_MTYPE + UINT8 modifiers; + UINT8 errorCode; + UINT8 singles; + UINT32 values[1]; +} TableMarshal_mst; + +typedef const struct MinMaxMarshal_mst +{ + UINT8 marshalType; // MIN_MAX_MTYPE + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[2]; +} MinMaxMarshal_mst; + +typedef const struct Tpm2bMarshal_mst +{ + UINT8 unmarshalType; // TPM2B_MTYPE + UINT16 sizeIndex; // reference to type for this size value +} Tpm2bMarshal_mst; + +typedef const struct Tpm2bsMarshal_mst +{ + UINT8 unmarshalType; // TPM2BS_MTYPE + UINT8 modifiers; // size= and offset (2 - 7) + UINT16 sizeIndex; // index of the size value; + UINT16 dataIndex; // the structure +} Tpm2bsMarshal_mst; + +typedef const struct ListMarshal_mst +{ + UINT8 unmarshalType; // LIST_MTYPE (for TPML) + UINT8 modifiers; // size offset 2-7 + UINT16 sizeIndex; // reference to the minmax structure that + // unmarshals the size parameter + UINT16 arrayRef; // reference to an array definition (type + // and stride) +} ListMarshal_mst; + +typedef const struct AttributesMarshal_mst +{ + UINT8 unmarashalType; // ATTRIBUTE_MTYPE + UINT8 modifiers; // size (ONE_BYTES, TWO_BYTES, or FOUR_BYTES + UINT32 attributeMask; // the values that must be zero. +} AttributesMarshal_mst; + +typedef const struct CompositeMarshal_mst +{ + UINT8 unmashalType; // COMPOSITE_MTYPE + UINT8 modifiers; // number of entries and size + marshalIndex_t types[1]; // array of unmarshaling types +} CompositeMarshal_mst; + +typedef const struct TPM_ECC_CURVE_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[4]; +} TPM_ECC_CURVE_mst; + +typedef const struct TPM_CLOCK_ADJUST_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[2]; +} TPM_CLOCK_ADJUST_mst; + +typedef const struct TPM_EO_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[2]; +} TPM_EO_mst; + +typedef const struct TPM_SU_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT8 entries; + UINT32 values[2]; +} TPM_SU_mst; + +typedef const struct TPM_SE_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT8 entries; + UINT32 values[3]; +} TPM_SE_mst; + +typedef const struct TPM_CAP_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT8 ranges; + UINT8 singles; + UINT32 values[3]; +} TPM_CAP_mst; + +typedef const struct TPMI_YES_NO_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT8 entries; + UINT32 values[2]; +} TPMI_YES_NO_mst; + +typedef const struct TPMI_DH_OBJECT_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT8 ranges; + UINT8 singles; + UINT32 values[5]; +} TPMI_DH_OBJECT_mst; + +typedef const struct TPMI_DH_PARENT_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT8 ranges; + UINT8 singles; + UINT32 values[8]; +} TPMI_DH_PARENT_mst; + +typedef const struct TPMI_DH_PERSISTENT_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[2]; +} TPMI_DH_PERSISTENT_mst; + +typedef const struct TPMI_DH_ENTITY_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT8 ranges; + UINT8 singles; + UINT32 values[15]; +} TPMI_DH_ENTITY_mst; + +typedef const struct TPMI_DH_PCR_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[3]; +} TPMI_DH_PCR_mst; + +typedef const struct TPMI_SH_AUTH_SESSION_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT8 ranges; + UINT8 singles; + UINT32 values[5]; +} TPMI_SH_AUTH_SESSION_mst; + +typedef const struct TPMI_SH_HMAC_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[2]; +} TPMI_SH_HMAC_mst; + +typedef const struct TPMI_SH_POLICY_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[2]; +} TPMI_SH_POLICY_mst; + +typedef const struct TPMI_DH_CONTEXT_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT8 ranges; + UINT8 singles; + UINT32 values[6]; +} TPMI_DH_CONTEXT_mst; + +typedef const struct TPMI_DH_SAVED_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT8 ranges; + UINT8 singles; + UINT32 values[7]; +} TPMI_DH_SAVED_mst; + +typedef const struct TPMI_RH_HIERARCHY_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT8 entries; + UINT32 values[4]; +} TPMI_RH_HIERARCHY_mst; + +typedef const struct TPMI_RH_ENABLES_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT8 entries; + UINT32 values[5]; +} TPMI_RH_ENABLES_mst; + +typedef const struct TPMI_RH_HIERARCHY_AUTH_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT8 entries; + UINT32 values[4]; +} TPMI_RH_HIERARCHY_AUTH_mst; + +typedef const struct TPMI_RH_HIERARCHY_POLICY_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT8 ranges; + UINT8 singles; + UINT32 values[6]; +} TPMI_RH_HIERARCHY_POLICY_mst; + +typedef const struct TPMI_RH_PLATFORM_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT8 entries; + UINT32 values[1]; +} TPMI_RH_PLATFORM_mst; + +typedef const struct TPMI_RH_OWNER_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT8 entries; + UINT32 values[2]; +} TPMI_RH_OWNER_mst; + +typedef const struct TPMI_RH_ENDORSEMENT_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT8 entries; + UINT32 values[2]; +} TPMI_RH_ENDORSEMENT_mst; + +typedef const struct TPMI_RH_PROVISION_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT8 entries; + UINT32 values[2]; +} TPMI_RH_PROVISION_mst; + +typedef const struct TPMI_RH_CLEAR_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT8 entries; + UINT32 values[2]; +} TPMI_RH_CLEAR_mst; + +typedef const struct TPMI_RH_NV_AUTH_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT8 ranges; + UINT8 singles; + UINT32 values[4]; +} TPMI_RH_NV_AUTH_mst; + +typedef const struct TPMI_RH_LOCKOUT_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT8 entries; + UINT32 values[1]; +} TPMI_RH_LOCKOUT_mst; + +typedef const struct TPMI_RH_NV_INDEX_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[2]; +} TPMI_RH_NV_INDEX_mst; + +typedef const struct TPMI_RH_AC_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[2]; +} TPMI_RH_AC_mst; + +typedef const struct TPMI_RH_ACT_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[2]; +} TPMI_RH_ACT_mst; + +typedef const struct TPMI_ALG_HASH_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[5]; +} TPMI_ALG_HASH_mst; + +typedef const struct TPMI_ALG_ASYM_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[5]; +} TPMI_ALG_ASYM_mst; + +typedef const struct TPMI_ALG_SYM_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[5]; +} TPMI_ALG_SYM_mst; + +typedef const struct TPMI_ALG_SYM_OBJECT_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[5]; +} TPMI_ALG_SYM_OBJECT_mst; + +typedef const struct TPMI_ALG_SYM_MODE_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[4]; +} TPMI_ALG_SYM_MODE_mst; + +typedef const struct TPMI_ALG_KDF_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[4]; +} TPMI_ALG_KDF_mst; + +typedef const struct TPMI_ALG_SIG_SCHEME_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[4]; +} TPMI_ALG_SIG_SCHEME_mst; + +typedef const struct TPMI_ECC_KEY_EXCHANGE_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[4]; +} TPMI_ECC_KEY_EXCHANGE_mst; + +typedef const struct TPMI_ST_COMMAND_TAG_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT8 entries; + UINT32 values[2]; +} TPMI_ST_COMMAND_TAG_mst; + +typedef const struct TPMI_ALG_MAC_SCHEME_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[5]; +} TPMI_ALG_MAC_SCHEME_mst; + +typedef const struct TPMI_ALG_CIPHER_MODE_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[4]; +} TPMI_ALG_CIPHER_MODE_mst; + +typedef const struct TPMS_EMPTY_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[3]; +} TPMS_EMPTY_mst; + +typedef const struct TPMS_ALGORITHM_DESCRIPTION_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[6]; +} TPMS_ALGORITHM_DESCRIPTION_mst; + +typedef struct TPMU_HA_mst +{ + BYTE countOfselectors; + BYTE modifiers; + UINT16 offsetOfUnmarshalTypes; + UINT32 selectors[9]; + UINT16 marshalingTypes[9]; +} TPMU_HA_mst; + +typedef const struct TPMT_HA_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[6]; +} TPMT_HA_mst; + +typedef const struct TPMS_PCR_SELECT_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[6]; +} TPMS_PCR_SELECT_mst; + +typedef const struct TPMS_PCR_SELECTION_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[9]; +} TPMS_PCR_SELECTION_mst; + +typedef const struct TPMT_TK_CREATION_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[9]; +} TPMT_TK_CREATION_mst; + +typedef const struct TPMT_TK_VERIFIED_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[9]; +} TPMT_TK_VERIFIED_mst; + +typedef const struct TPMT_TK_AUTH_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[9]; +} TPMT_TK_AUTH_mst; + +typedef const struct TPMT_TK_HASHCHECK_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[9]; +} TPMT_TK_HASHCHECK_mst; + +typedef const struct TPMS_ALG_PROPERTY_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[6]; +} TPMS_ALG_PROPERTY_mst; + +typedef const struct TPMS_TAGGED_PROPERTY_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[6]; +} TPMS_TAGGED_PROPERTY_mst; + +typedef const struct TPMS_TAGGED_PCR_SELECT_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[9]; +} TPMS_TAGGED_PCR_SELECT_mst; + +typedef const struct TPMS_TAGGED_POLICY_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[6]; +} TPMS_TAGGED_POLICY_mst; + +typedef const struct TPMS_ACT_DATA_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[9]; +} TPMS_ACT_DATA_mst; + +typedef struct TPMU_CAPABILITIES_mst +{ + BYTE countOfselectors; + BYTE modifiers; + UINT16 offsetOfUnmarshalTypes; + UINT32 selectors[11]; + UINT16 marshalingTypes[11]; +} TPMU_CAPABILITIES_mst; + +typedef const struct TPMS_CAPABILITY_DATA_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[6]; +} TPMS_CAPABILITY_DATA_mst; + +typedef const struct TPMS_CLOCK_INFO_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[12]; +} TPMS_CLOCK_INFO_mst; + +typedef const struct TPMS_TIME_INFO_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[6]; +} TPMS_TIME_INFO_mst; + +typedef const struct TPMS_TIME_ATTEST_INFO_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[6]; +} TPMS_TIME_ATTEST_INFO_mst; + +typedef const struct TPMS_CERTIFY_INFO_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[6]; +} TPMS_CERTIFY_INFO_mst; + +typedef const struct TPMS_QUOTE_INFO_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[6]; +} TPMS_QUOTE_INFO_mst; + +typedef const struct TPMS_COMMAND_AUDIT_INFO_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[12]; +} TPMS_COMMAND_AUDIT_INFO_mst; + +typedef const struct TPMS_SESSION_AUDIT_INFO_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[6]; +} TPMS_SESSION_AUDIT_INFO_mst; + +typedef const struct TPMS_CREATION_INFO_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[6]; +} TPMS_CREATION_INFO_mst; + +typedef const struct TPMS_NV_CERTIFY_INFO_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[9]; +} TPMS_NV_CERTIFY_INFO_mst; + +typedef const struct TPMS_NV_DIGEST_CERTIFY_INFO_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[6]; +} TPMS_NV_DIGEST_CERTIFY_INFO_mst; + +typedef const struct TPMI_ST_ATTEST_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT8 ranges; + UINT8 singles; + UINT32 values[3]; +} TPMI_ST_ATTEST_mst; + +typedef struct TPMU_ATTEST_mst +{ + BYTE countOfselectors; + BYTE modifiers; + UINT16 offsetOfUnmarshalTypes; + UINT32 selectors[8]; + UINT16 marshalingTypes[8]; +} TPMU_ATTEST_mst; + +typedef const struct TPMS_ATTEST_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[21]; +} TPMS_ATTEST_mst; + +typedef const struct TPMS_AUTH_COMMAND_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[12]; +} TPMS_AUTH_COMMAND_mst; + +typedef const struct TPMS_AUTH_RESPONSE_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[9]; +} TPMS_AUTH_RESPONSE_mst; + +typedef const struct TPMI_TDES_KEY_BITS_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT8 entries; + UINT32 values[1]; +} TPMI_TDES_KEY_BITS_mst; + +typedef const struct TPMI_AES_KEY_BITS_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT8 entries; + UINT32 values[3]; +} TPMI_AES_KEY_BITS_mst; + +typedef const struct TPMI_SM4_KEY_BITS_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT8 entries; + UINT32 values[1]; +} TPMI_SM4_KEY_BITS_mst; + +typedef const struct TPMI_CAMELLIA_KEY_BITS_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT8 entries; + UINT32 values[3]; +} TPMI_CAMELLIA_KEY_BITS_mst; + +typedef struct TPMU_SYM_KEY_BITS_mst +{ + BYTE countOfselectors; + BYTE modifiers; + UINT16 offsetOfUnmarshalTypes; + UINT32 selectors[6]; + UINT16 marshalingTypes[6]; +} TPMU_SYM_KEY_BITS_mst; + +typedef struct TPMU_SYM_MODE_mst +{ + BYTE countOfselectors; + BYTE modifiers; + UINT16 offsetOfUnmarshalTypes; + UINT32 selectors[6]; + UINT16 marshalingTypes[6]; +} TPMU_SYM_MODE_mst; + +typedef const struct TPMT_SYM_DEF_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[9]; +} TPMT_SYM_DEF_mst; + +typedef const struct TPMT_SYM_DEF_OBJECT_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[9]; +} TPMT_SYM_DEF_OBJECT_mst; + +typedef const struct TPMS_SYMCIPHER_PARMS_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[3]; +} TPMS_SYMCIPHER_PARMS_mst; + +typedef const struct TPMS_DERIVE_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[6]; +} TPMS_DERIVE_mst; + +typedef const struct TPMS_SENSITIVE_CREATE_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[6]; +} TPMS_SENSITIVE_CREATE_mst; + +typedef const struct TPMS_SCHEME_HASH_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[3]; +} TPMS_SCHEME_HASH_mst; + +typedef const struct TPMS_SCHEME_ECDAA_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[6]; +} TPMS_SCHEME_ECDAA_mst; + +typedef const struct TPMI_ALG_KEYEDHASH_SCHEME_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[4]; +} TPMI_ALG_KEYEDHASH_SCHEME_mst; + +typedef const struct TPMS_SCHEME_XOR_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[6]; +} TPMS_SCHEME_XOR_mst; + +typedef struct TPMU_SCHEME_KEYEDHASH_mst +{ + BYTE countOfselectors; + BYTE modifiers; + UINT16 offsetOfUnmarshalTypes; + UINT32 selectors[3]; + UINT16 marshalingTypes[3]; +} TPMU_SCHEME_KEYEDHASH_mst; + +typedef const struct TPMT_KEYEDHASH_SCHEME_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[6]; +} TPMT_KEYEDHASH_SCHEME_mst; + +typedef struct TPMU_SIG_SCHEME_mst +{ + BYTE countOfselectors; + BYTE modifiers; + UINT16 offsetOfUnmarshalTypes; + UINT32 selectors[8]; + UINT16 marshalingTypes[8]; +} TPMU_SIG_SCHEME_mst; + +typedef const struct TPMT_SIG_SCHEME_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[6]; +} TPMT_SIG_SCHEME_mst; + +typedef struct TPMU_KDF_SCHEME_mst +{ + BYTE countOfselectors; + BYTE modifiers; + UINT16 offsetOfUnmarshalTypes; + UINT32 selectors[5]; + UINT16 marshalingTypes[5]; +} TPMU_KDF_SCHEME_mst; + +typedef const struct TPMT_KDF_SCHEME_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[6]; +} TPMT_KDF_SCHEME_mst; + +typedef const struct TPMI_ALG_ASYM_SCHEME_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[4]; +} TPMI_ALG_ASYM_SCHEME_mst; + +typedef struct TPMU_ASYM_SCHEME_mst +{ + BYTE countOfselectors; + BYTE modifiers; + UINT16 offsetOfUnmarshalTypes; + UINT32 selectors[11]; + UINT16 marshalingTypes[11]; +} TPMU_ASYM_SCHEME_mst; + +typedef const struct TPMI_ALG_RSA_SCHEME_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[4]; +} TPMI_ALG_RSA_SCHEME_mst; + +typedef const struct TPMT_RSA_SCHEME_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[6]; +} TPMT_RSA_SCHEME_mst; + +typedef const struct TPMI_ALG_RSA_DECRYPT_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[4]; +} TPMI_ALG_RSA_DECRYPT_mst; + +typedef const struct TPMT_RSA_DECRYPT_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[6]; +} TPMT_RSA_DECRYPT_mst; + +typedef const struct TPMI_RSA_KEY_BITS_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT8 entries; + UINT32 values[3]; +} TPMI_RSA_KEY_BITS_mst; + +typedef const struct TPMS_ECC_POINT_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[6]; +} TPMS_ECC_POINT_mst; + +typedef const struct TPMI_ALG_ECC_SCHEME_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[4]; +} TPMI_ALG_ECC_SCHEME_mst; + +typedef const struct TPMI_ECC_CURVE_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[3]; +} TPMI_ECC_CURVE_mst; + +typedef const struct TPMT_ECC_SCHEME_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[6]; +} TPMT_ECC_SCHEME_mst; + +typedef const struct TPMS_ALGORITHM_DETAIL_ECC_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[33]; +} TPMS_ALGORITHM_DETAIL_ECC_mst; + +typedef const struct TPMS_SIGNATURE_RSA_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[6]; +} TPMS_SIGNATURE_RSA_mst; + +typedef const struct TPMS_SIGNATURE_ECC_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[9]; +} TPMS_SIGNATURE_ECC_mst; + +typedef struct TPMU_SIGNATURE_mst +{ + BYTE countOfselectors; + BYTE modifiers; + UINT16 offsetOfUnmarshalTypes; + UINT32 selectors[8]; + UINT16 marshalingTypes[8]; +} TPMU_SIGNATURE_mst; + +typedef const struct TPMT_SIGNATURE_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[6]; +} TPMT_SIGNATURE_mst; + +typedef struct TPMU_ENCRYPTED_SECRET_mst +{ + BYTE countOfselectors; + BYTE modifiers; + UINT16 offsetOfUnmarshalTypes; + UINT32 selectors[4]; + UINT16 marshalingTypes[4]; +} TPMU_ENCRYPTED_SECRET_mst; + +typedef const struct TPMI_ALG_PUBLIC_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[4]; +} TPMI_ALG_PUBLIC_mst; + +typedef struct TPMU_PUBLIC_ID_mst +{ + BYTE countOfselectors; + BYTE modifiers; + UINT16 offsetOfUnmarshalTypes; + UINT32 selectors[4]; + UINT16 marshalingTypes[4]; +} TPMU_PUBLIC_ID_mst; + +typedef const struct TPMS_KEYEDHASH_PARMS_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[3]; +} TPMS_KEYEDHASH_PARMS_mst; + +typedef const struct TPMS_RSA_PARMS_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[12]; +} TPMS_RSA_PARMS_mst; + +typedef const struct TPMS_ECC_PARMS_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[12]; +} TPMS_ECC_PARMS_mst; + +typedef struct TPMU_PUBLIC_PARMS_mst +{ + BYTE countOfselectors; + BYTE modifiers; + UINT16 offsetOfUnmarshalTypes; + UINT32 selectors[4]; + UINT16 marshalingTypes[4]; +} TPMU_PUBLIC_PARMS_mst; + +typedef const struct TPMT_PUBLIC_PARMS_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[6]; +} TPMT_PUBLIC_PARMS_mst; + +typedef const struct TPMT_PUBLIC_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[18]; +} TPMT_PUBLIC_mst; + +typedef struct TPMU_SENSITIVE_COMPOSITE_mst +{ + BYTE countOfselectors; + BYTE modifiers; + UINT16 offsetOfUnmarshalTypes; + UINT32 selectors[4]; + UINT16 marshalingTypes[4]; +} TPMU_SENSITIVE_COMPOSITE_mst; + +typedef const struct TPMT_SENSITIVE_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[12]; +} TPMT_SENSITIVE_mst; + +typedef const struct TPMS_NV_PIN_COUNTER_PARAMETERS_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[6]; +} TPMS_NV_PIN_COUNTER_PARAMETERS_mst; + +typedef const struct TPMS_NV_PUBLIC_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[15]; +} TPMS_NV_PUBLIC_mst; + +typedef const struct TPMS_CONTEXT_DATA_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[6]; +} TPMS_CONTEXT_DATA_mst; + +typedef const struct TPMS_CONTEXT_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[12]; +} TPMS_CONTEXT_mst; + +typedef const struct TPMS_CREATION_DATA_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[21]; +} TPMS_CREATION_DATA_mst; + +typedef const struct TPM_AT_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT8 entries; + UINT32 values[4]; +} TPM_AT_mst; + +typedef const struct TPMS_AC_OUTPUT_mst +{ + UINT8 marshalType; + UINT8 elements; + UINT16 values[6]; +} TPMS_AC_OUTPUT_mst; + +typedef const struct Type02_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[2]; +} Type02_mst; + +typedef const struct Type03_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[2]; +} Type03_mst; + +typedef const struct Type04_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[2]; +} Type04_mst; + +typedef const struct Type06_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[2]; +} Type06_mst; + +typedef const struct Type08_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[2]; +} Type08_mst; + +typedef const struct Type10_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT8 entries; + UINT32 values[1]; +} Type10_mst; + +typedef const struct Type11_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT8 entries; + UINT32 values[1]; +} Type11_mst; + +typedef const struct Type12_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT8 entries; + UINT32 values[2]; +} Type12_mst; + +typedef const struct Type13_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT8 entries; + UINT32 values[1]; +} Type13_mst; + +typedef const struct Type15_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[2]; +} Type15_mst; + +typedef const struct Type17_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[2]; +} Type17_mst; + +typedef const struct Type18_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[2]; +} Type18_mst; + +typedef const struct Type19_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[2]; +} Type19_mst; + +typedef const struct Type20_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[2]; +} Type20_mst; + +typedef const struct Type22_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[2]; +} Type22_mst; + +typedef const struct Type23_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[2]; +} Type23_mst; + +typedef const struct Type24_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[2]; +} Type24_mst; + +typedef const struct Type25_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[2]; +} Type25_mst; + +typedef const struct Type26_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[2]; +} Type26_mst; + +typedef const struct Type27_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[2]; +} Type27_mst; + +typedef const struct Type29_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[2]; +} Type29_mst; + +typedef const struct Type30_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[2]; +} Type30_mst; + +typedef const struct Type33_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[2]; +} Type33_mst; + +typedef const struct Type34_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[2]; +} Type34_mst; + +typedef const struct Type35_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[2]; +} Type35_mst; + +typedef const struct Type38_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[2]; +} Type38_mst; + +typedef const struct Type41_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[2]; +} Type41_mst; + +typedef const struct Type42_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[2]; +} Type42_mst; + +typedef const struct Type44_mst +{ + UINT8 marshalType; + UINT8 modifiers; + UINT8 errorCode; + UINT32 values[2]; +} Type44_mst; + +// This structure combines all the individual marshaling structures to build +// something that can be referenced by offset rather than full address +typedef const struct MarshalData_st +{ + UintMarshal_mst UINT8_DATA; + UintMarshal_mst UINT16_DATA; + UintMarshal_mst UINT32_DATA; + UintMarshal_mst UINT64_DATA; + UintMarshal_mst INT8_DATA; + UintMarshal_mst INT16_DATA; + UintMarshal_mst INT32_DATA; + UintMarshal_mst INT64_DATA; + UintMarshal_mst UINT0_DATA; + TPM_ECC_CURVE_mst TPM_ECC_CURVE_DATA; + TPM_CLOCK_ADJUST_mst TPM_CLOCK_ADJUST_DATA; + TPM_EO_mst TPM_EO_DATA; + TPM_SU_mst TPM_SU_DATA; + TPM_SE_mst TPM_SE_DATA; + TPM_CAP_mst TPM_CAP_DATA; + AttributesMarshal_mst TPMA_ALGORITHM_DATA; + AttributesMarshal_mst TPMA_OBJECT_DATA; + AttributesMarshal_mst TPMA_SESSION_DATA; + AttributesMarshal_mst TPMA_ACT_DATA; + TPMI_YES_NO_mst TPMI_YES_NO_DATA; + TPMI_DH_OBJECT_mst TPMI_DH_OBJECT_DATA; + TPMI_DH_PARENT_mst TPMI_DH_PARENT_DATA; + TPMI_DH_PERSISTENT_mst TPMI_DH_PERSISTENT_DATA; + TPMI_DH_ENTITY_mst TPMI_DH_ENTITY_DATA; + TPMI_DH_PCR_mst TPMI_DH_PCR_DATA; + TPMI_SH_AUTH_SESSION_mst TPMI_SH_AUTH_SESSION_DATA; + TPMI_SH_HMAC_mst TPMI_SH_HMAC_DATA; + TPMI_SH_POLICY_mst TPMI_SH_POLICY_DATA; + TPMI_DH_CONTEXT_mst TPMI_DH_CONTEXT_DATA; + TPMI_DH_SAVED_mst TPMI_DH_SAVED_DATA; + TPMI_RH_HIERARCHY_mst TPMI_RH_HIERARCHY_DATA; + TPMI_RH_ENABLES_mst TPMI_RH_ENABLES_DATA; + TPMI_RH_HIERARCHY_AUTH_mst TPMI_RH_HIERARCHY_AUTH_DATA; + TPMI_RH_HIERARCHY_POLICY_mst TPMI_RH_HIERARCHY_POLICY_DATA; + TPMI_RH_PLATFORM_mst TPMI_RH_PLATFORM_DATA; + TPMI_RH_OWNER_mst TPMI_RH_OWNER_DATA; + TPMI_RH_ENDORSEMENT_mst TPMI_RH_ENDORSEMENT_DATA; + TPMI_RH_PROVISION_mst TPMI_RH_PROVISION_DATA; + TPMI_RH_CLEAR_mst TPMI_RH_CLEAR_DATA; + TPMI_RH_NV_AUTH_mst TPMI_RH_NV_AUTH_DATA; + TPMI_RH_LOCKOUT_mst TPMI_RH_LOCKOUT_DATA; + TPMI_RH_NV_INDEX_mst TPMI_RH_NV_INDEX_DATA; + TPMI_RH_AC_mst TPMI_RH_AC_DATA; + TPMI_RH_ACT_mst TPMI_RH_ACT_DATA; + TPMI_ALG_HASH_mst TPMI_ALG_HASH_DATA; + TPMI_ALG_ASYM_mst TPMI_ALG_ASYM_DATA; + TPMI_ALG_SYM_mst TPMI_ALG_SYM_DATA; + TPMI_ALG_SYM_OBJECT_mst TPMI_ALG_SYM_OBJECT_DATA; + TPMI_ALG_SYM_MODE_mst TPMI_ALG_SYM_MODE_DATA; + TPMI_ALG_KDF_mst TPMI_ALG_KDF_DATA; + TPMI_ALG_SIG_SCHEME_mst TPMI_ALG_SIG_SCHEME_DATA; + TPMI_ECC_KEY_EXCHANGE_mst TPMI_ECC_KEY_EXCHANGE_DATA; + TPMI_ST_COMMAND_TAG_mst TPMI_ST_COMMAND_TAG_DATA; + TPMI_ALG_MAC_SCHEME_mst TPMI_ALG_MAC_SCHEME_DATA; + TPMI_ALG_CIPHER_MODE_mst TPMI_ALG_CIPHER_MODE_DATA; + TPMS_EMPTY_mst TPMS_EMPTY_DATA; + TPMS_ALGORITHM_DESCRIPTION_mst TPMS_ALGORITHM_DESCRIPTION_DATA; + TPMU_HA_mst TPMU_HA_DATA; + TPMT_HA_mst TPMT_HA_DATA; + Tpm2bMarshal_mst TPM2B_DIGEST_DATA; + Tpm2bMarshal_mst TPM2B_DATA_DATA; + Tpm2bMarshal_mst TPM2B_EVENT_DATA; + Tpm2bMarshal_mst TPM2B_MAX_BUFFER_DATA; + Tpm2bMarshal_mst TPM2B_MAX_NV_BUFFER_DATA; + Tpm2bMarshal_mst TPM2B_TIMEOUT_DATA; + Tpm2bMarshal_mst TPM2B_IV_DATA; + NullUnionMarshal_mst NULL_UNION_DATA; + Tpm2bMarshal_mst TPM2B_NAME_DATA; + TPMS_PCR_SELECT_mst TPMS_PCR_SELECT_DATA; + TPMS_PCR_SELECTION_mst TPMS_PCR_SELECTION_DATA; + TPMT_TK_CREATION_mst TPMT_TK_CREATION_DATA; + TPMT_TK_VERIFIED_mst TPMT_TK_VERIFIED_DATA; + TPMT_TK_AUTH_mst TPMT_TK_AUTH_DATA; + TPMT_TK_HASHCHECK_mst TPMT_TK_HASHCHECK_DATA; + TPMS_ALG_PROPERTY_mst TPMS_ALG_PROPERTY_DATA; + TPMS_TAGGED_PROPERTY_mst TPMS_TAGGED_PROPERTY_DATA; + TPMS_TAGGED_PCR_SELECT_mst TPMS_TAGGED_PCR_SELECT_DATA; + TPMS_TAGGED_POLICY_mst TPMS_TAGGED_POLICY_DATA; + TPMS_ACT_DATA_mst TPMS_ACT_DATA_DATA; + ListMarshal_mst TPML_CC_DATA; + ListMarshal_mst TPML_CCA_DATA; + ListMarshal_mst TPML_ALG_DATA; + ListMarshal_mst TPML_HANDLE_DATA; + ListMarshal_mst TPML_DIGEST_DATA; + ListMarshal_mst TPML_DIGEST_VALUES_DATA; + ListMarshal_mst TPML_PCR_SELECTION_DATA; + ListMarshal_mst TPML_ALG_PROPERTY_DATA; + ListMarshal_mst TPML_TAGGED_TPM_PROPERTY_DATA; + ListMarshal_mst TPML_TAGGED_PCR_PROPERTY_DATA; + ListMarshal_mst TPML_ECC_CURVE_DATA; + ListMarshal_mst TPML_TAGGED_POLICY_DATA; + ListMarshal_mst TPML_ACT_DATA_DATA; + TPMU_CAPABILITIES_mst TPMU_CAPABILITIES_DATA; + TPMS_CAPABILITY_DATA_mst TPMS_CAPABILITY_DATA_DATA; + TPMS_CLOCK_INFO_mst TPMS_CLOCK_INFO_DATA; + TPMS_TIME_INFO_mst TPMS_TIME_INFO_DATA; + TPMS_TIME_ATTEST_INFO_mst TPMS_TIME_ATTEST_INFO_DATA; + TPMS_CERTIFY_INFO_mst TPMS_CERTIFY_INFO_DATA; + TPMS_QUOTE_INFO_mst TPMS_QUOTE_INFO_DATA; + TPMS_COMMAND_AUDIT_INFO_mst TPMS_COMMAND_AUDIT_INFO_DATA; + TPMS_SESSION_AUDIT_INFO_mst TPMS_SESSION_AUDIT_INFO_DATA; + TPMS_CREATION_INFO_mst TPMS_CREATION_INFO_DATA; + TPMS_NV_CERTIFY_INFO_mst TPMS_NV_CERTIFY_INFO_DATA; + TPMS_NV_DIGEST_CERTIFY_INFO_mst TPMS_NV_DIGEST_CERTIFY_INFO_DATA; + TPMI_ST_ATTEST_mst TPMI_ST_ATTEST_DATA; + TPMU_ATTEST_mst TPMU_ATTEST_DATA; + TPMS_ATTEST_mst TPMS_ATTEST_DATA; + Tpm2bMarshal_mst TPM2B_ATTEST_DATA; + TPMS_AUTH_COMMAND_mst TPMS_AUTH_COMMAND_DATA; + TPMS_AUTH_RESPONSE_mst TPMS_AUTH_RESPONSE_DATA; + TPMI_TDES_KEY_BITS_mst TPMI_TDES_KEY_BITS_DATA; + TPMI_AES_KEY_BITS_mst TPMI_AES_KEY_BITS_DATA; + TPMI_SM4_KEY_BITS_mst TPMI_SM4_KEY_BITS_DATA; + TPMI_CAMELLIA_KEY_BITS_mst TPMI_CAMELLIA_KEY_BITS_DATA; + TPMU_SYM_KEY_BITS_mst TPMU_SYM_KEY_BITS_DATA; + TPMU_SYM_MODE_mst TPMU_SYM_MODE_DATA; + TPMT_SYM_DEF_mst TPMT_SYM_DEF_DATA; + TPMT_SYM_DEF_OBJECT_mst TPMT_SYM_DEF_OBJECT_DATA; + Tpm2bMarshal_mst TPM2B_SYM_KEY_DATA; + TPMS_SYMCIPHER_PARMS_mst TPMS_SYMCIPHER_PARMS_DATA; + Tpm2bMarshal_mst TPM2B_LABEL_DATA; + TPMS_DERIVE_mst TPMS_DERIVE_DATA; + Tpm2bMarshal_mst TPM2B_DERIVE_DATA; + Tpm2bMarshal_mst TPM2B_SENSITIVE_DATA_DATA; + TPMS_SENSITIVE_CREATE_mst TPMS_SENSITIVE_CREATE_DATA; + Tpm2bsMarshal_mst TPM2B_SENSITIVE_CREATE_DATA; + TPMS_SCHEME_HASH_mst TPMS_SCHEME_HASH_DATA; + TPMS_SCHEME_ECDAA_mst TPMS_SCHEME_ECDAA_DATA; + TPMI_ALG_KEYEDHASH_SCHEME_mst TPMI_ALG_KEYEDHASH_SCHEME_DATA; + TPMS_SCHEME_XOR_mst TPMS_SCHEME_XOR_DATA; + TPMU_SCHEME_KEYEDHASH_mst TPMU_SCHEME_KEYEDHASH_DATA; + TPMT_KEYEDHASH_SCHEME_mst TPMT_KEYEDHASH_SCHEME_DATA; + TPMU_SIG_SCHEME_mst TPMU_SIG_SCHEME_DATA; + TPMT_SIG_SCHEME_mst TPMT_SIG_SCHEME_DATA; + TPMU_KDF_SCHEME_mst TPMU_KDF_SCHEME_DATA; + TPMT_KDF_SCHEME_mst TPMT_KDF_SCHEME_DATA; + TPMI_ALG_ASYM_SCHEME_mst TPMI_ALG_ASYM_SCHEME_DATA; + TPMU_ASYM_SCHEME_mst TPMU_ASYM_SCHEME_DATA; + TPMI_ALG_RSA_SCHEME_mst TPMI_ALG_RSA_SCHEME_DATA; + TPMT_RSA_SCHEME_mst TPMT_RSA_SCHEME_DATA; + TPMI_ALG_RSA_DECRYPT_mst TPMI_ALG_RSA_DECRYPT_DATA; + TPMT_RSA_DECRYPT_mst TPMT_RSA_DECRYPT_DATA; + Tpm2bMarshal_mst TPM2B_PUBLIC_KEY_RSA_DATA; + TPMI_RSA_KEY_BITS_mst TPMI_RSA_KEY_BITS_DATA; + Tpm2bMarshal_mst TPM2B_PRIVATE_KEY_RSA_DATA; + Tpm2bMarshal_mst TPM2B_ECC_PARAMETER_DATA; + TPMS_ECC_POINT_mst TPMS_ECC_POINT_DATA; + Tpm2bsMarshal_mst TPM2B_ECC_POINT_DATA; + TPMI_ALG_ECC_SCHEME_mst TPMI_ALG_ECC_SCHEME_DATA; + TPMI_ECC_CURVE_mst TPMI_ECC_CURVE_DATA; + TPMT_ECC_SCHEME_mst TPMT_ECC_SCHEME_DATA; + TPMS_ALGORITHM_DETAIL_ECC_mst TPMS_ALGORITHM_DETAIL_ECC_DATA; + TPMS_SIGNATURE_RSA_mst TPMS_SIGNATURE_RSA_DATA; + TPMS_SIGNATURE_ECC_mst TPMS_SIGNATURE_ECC_DATA; + TPMU_SIGNATURE_mst TPMU_SIGNATURE_DATA; + TPMT_SIGNATURE_mst TPMT_SIGNATURE_DATA; + TPMU_ENCRYPTED_SECRET_mst TPMU_ENCRYPTED_SECRET_DATA; + Tpm2bMarshal_mst TPM2B_ENCRYPTED_SECRET_DATA; + TPMI_ALG_PUBLIC_mst TPMI_ALG_PUBLIC_DATA; + TPMU_PUBLIC_ID_mst TPMU_PUBLIC_ID_DATA; + TPMS_KEYEDHASH_PARMS_mst TPMS_KEYEDHASH_PARMS_DATA; + TPMS_RSA_PARMS_mst TPMS_RSA_PARMS_DATA; + TPMS_ECC_PARMS_mst TPMS_ECC_PARMS_DATA; + TPMU_PUBLIC_PARMS_mst TPMU_PUBLIC_PARMS_DATA; + TPMT_PUBLIC_PARMS_mst TPMT_PUBLIC_PARMS_DATA; + TPMT_PUBLIC_mst TPMT_PUBLIC_DATA; + Tpm2bsMarshal_mst TPM2B_PUBLIC_DATA; + Tpm2bMarshal_mst TPM2B_TEMPLATE_DATA; + Tpm2bMarshal_mst TPM2B_PRIVATE_VENDOR_SPECIFIC_DATA; + TPMU_SENSITIVE_COMPOSITE_mst TPMU_SENSITIVE_COMPOSITE_DATA; + TPMT_SENSITIVE_mst TPMT_SENSITIVE_DATA; + Tpm2bsMarshal_mst TPM2B_SENSITIVE_DATA; + Tpm2bMarshal_mst TPM2B_PRIVATE_DATA; + Tpm2bMarshal_mst TPM2B_ID_OBJECT_DATA; + TPMS_NV_PIN_COUNTER_PARAMETERS_mst TPMS_NV_PIN_COUNTER_PARAMETERS_DATA; + AttributesMarshal_mst TPMA_NV_DATA; + TPMS_NV_PUBLIC_mst TPMS_NV_PUBLIC_DATA; + Tpm2bsMarshal_mst TPM2B_NV_PUBLIC_DATA; + Tpm2bMarshal_mst TPM2B_CONTEXT_SENSITIVE_DATA; + TPMS_CONTEXT_DATA_mst TPMS_CONTEXT_DATA_DATA; + Tpm2bMarshal_mst TPM2B_CONTEXT_DATA_DATA; + TPMS_CONTEXT_mst TPMS_CONTEXT_DATA; + TPMS_CREATION_DATA_mst TPMS_CREATION_DATA_DATA; + Tpm2bsMarshal_mst TPM2B_CREATION_DATA_DATA; + TPM_AT_mst TPM_AT_DATA; + TPMS_AC_OUTPUT_mst TPMS_AC_OUTPUT_DATA; + ListMarshal_mst TPML_AC_CAPABILITIES_DATA; + MinMaxMarshal_mst Type00_DATA; + MinMaxMarshal_mst Type01_DATA; + Type02_mst Type02_DATA; + Type03_mst Type03_DATA; + Type04_mst Type04_DATA; + MinMaxMarshal_mst Type05_DATA; + Type06_mst Type06_DATA; + MinMaxMarshal_mst Type07_DATA; + Type08_mst Type08_DATA; + Type10_mst Type10_DATA; + Type11_mst Type11_DATA; + Type12_mst Type12_DATA; + Type13_mst Type13_DATA; + Type15_mst Type15_DATA; + Type17_mst Type17_DATA; + Type18_mst Type18_DATA; + Type19_mst Type19_DATA; + Type20_mst Type20_DATA; + Type22_mst Type22_DATA; + Type23_mst Type23_DATA; + Type24_mst Type24_DATA; + Type25_mst Type25_DATA; + Type26_mst Type26_DATA; + Type27_mst Type27_DATA; + MinMaxMarshal_mst Type28_DATA; + Type29_mst Type29_DATA; + Type30_mst Type30_DATA; + MinMaxMarshal_mst Type31_DATA; + MinMaxMarshal_mst Type32_DATA; + Type33_mst Type33_DATA; + Type34_mst Type34_DATA; + Type35_mst Type35_DATA; + MinMaxMarshal_mst Type36_DATA; + MinMaxMarshal_mst Type37_DATA; + Type38_mst Type38_DATA; + MinMaxMarshal_mst Type39_DATA; + MinMaxMarshal_mst Type40_DATA; + Type41_mst Type41_DATA; + Type42_mst Type42_DATA; + MinMaxMarshal_mst Type43_DATA; + Type44_mst Type44_DATA; +} MarshalData_st; + +#endif // _TABLE_MARSHAL_TYPES_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Tpm.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Tpm.h new file mode 100644 index 0000000..c7bc088 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Tpm.h @@ -0,0 +1,55 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +// Root header file for building any TPM.lib code + +#ifndef _TPM_H_ +#define _TPM_H_ + +#include "TpmBuildSwitches.h" +#include "BaseTypes.h" +#include "TPMB.h" +#include "MinMax.h" + +#include "TpmProfile.h" +#include "TpmAlgorithmDefines.h" +#include "LibSupport.h" // Types from the library. These need to come before + // Global.h because some of the structures in + // that file depend on the structures used by the + // cryptographic libraries. +#include "GpMacros.h" // Define additional macros +#include "Global.h" // Define other TPM types +#include "InternalRoutines.h" // Function prototypes + +#endif // _TPM_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TpmASN1.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TpmASN1.h new file mode 100644 index 0000000..66ad550 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TpmASN1.h @@ -0,0 +1,126 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// This file contains the macro and structure definitions for the X509 commands and +// functions. + +#ifndef _TPMASN1_H_ +#define _TPMASN1_H_ + +//** Includes + +#include "Tpm.h" +#include "OIDs.h" + +//** Defined Constants +//*** ASN.1 Universal Types (Class 00b) +#define ASN1_EOC 0x00 +#define ASN1_BOOLEAN 0x01 +#define ASN1_INTEGER 0x02 +#define ASN1_BITSTRING 0x03 +#define ASN1_OCTET_STRING 0x04 +#define ASN1_NULL 0x05 +#define ASN1_OBJECT_IDENTIFIER 0x06 +#define ASN1_OBJECT_DESCRIPTOR 0x07 +#define ASN1_EXTERNAL 0x08 +#define ASN1_REAL 0x09 +#define ASN1_ENUMERATED 0x0A +#define ASN1_EMBEDDED 0x0B +#define ASN1_UTF8String 0x0C +#define ASN1_RELATIVE_OID 0x0D +#define ASN1_SEQUENCE 0x10 // Primitive + Constructed + 0x10 +#define ASN1_SET 0x11 // Primitive + Constructed + 0x11 +#define ASN1_NumericString 0x12 +#define ASN1_PrintableString 0x13 +#define ASN1_T61String 0x14 +#define ASN1_VideoString 0x15 +#define ASN1_IA5String 0x16 +#define ASN1_UTCTime 0x17 +#define ASN1_GeneralizeTime 0x18 +#define ASN1_VisibleString 0x1A +#define ASN1_GeneralString 0x1B +#define ASN1_UniversalString 0x1C +#define ASN1_CHARACTER STRING 0x1D +#define ASN1_BMPString 0x1E +#define ASN1_CONSTRUCTED 0x20 + +#define ASN1_APPLICAIION_SPECIFIC 0xA0 + +#define ASN1_CONSTRUCTED_SEQUENCE (ASN1_SEQUENCE + ASN1_CONSTRUCTED) + +#define MAX_DEPTH 10 // maximum push depth for marshaling context. + +//** Macros + +//*** Unmarshaling Macros +// Checks the validity of the size making sure that there is no wrap around +#define CHECK_SIZE(context, length) \ + VERIFY((((length) + (context)->offset) >= (context)->offset) \ + && (((length) + (context)->offset) <= (context)->size)) +#define NEXT_OCTET(context) ((context)->buffer[(context)->offset++]) +#define PEEK_NEXT(context) ((context)->buffer[(context)->offset]) + +//*** Marshaling Macros + +// Marshaling works in reverse order. The offset is set to the top of the buffer and, +// as the buffer is filled, 'offset' counts down to zero. When the full thing is +// encoded it can be moved to the top of the buffer. This happens when the last +// context is closed. + +#define CHECK_SPACE(context, length) VERIFY(context->offset > length) + +//** Structures + +typedef struct ASN1UnmarshalContext +{ + BYTE* buffer; // pointer to the buffer + INT16 size; // size of the buffer (a negative number indicates + // a parsing failure). + INT16 offset; // current offset into the buffer (a negative number + // indicates a parsing failure). Not used + BYTE tag; // The last unmarshaled tag +} ASN1UnmarshalContext; + +typedef struct ASN1MarshalContext +{ + BYTE* buffer; // pointer to the start of the buffer + INT16 offset; // place on the top where the last entry was added + // items are added from the bottom up. + INT16 end; // the end offset of the current value + INT16 depth; // how many pushed end values. + INT16 ends[MAX_DEPTH]; +} ASN1MarshalContext; + +#endif // _TPMASN1_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TpmAlgorithmDefines.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TpmAlgorithmDefines.h new file mode 100644 index 0000000..07760c0 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TpmAlgorithmDefines.h @@ -0,0 +1,409 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Feb 28, 2020 Time: 03:04:46PM + */ + +#ifndef _TPM_ALGORITHM_DEFINES_H_ +#define _TPM_ALGORITHM_DEFINES_H_ + +// Table 2:3 - Definition of Base Types +// Base Types are in BaseTypes.h + +#define ECC_CURVES \ + { \ + TPM_ECC_BN_P256, TPM_ECC_BN_P638, TPM_ECC_NIST_P192, TPM_ECC_NIST_P224, \ + TPM_ECC_NIST_P256, TPM_ECC_NIST_P384, TPM_ECC_NIST_P521, TPM_ECC_SM2_P256 \ + } +#define ECC_CURVE_COUNT \ + (ECC_BN_P256 + ECC_BN_P638 + ECC_NIST_P192 + ECC_NIST_P224 + ECC_NIST_P256 \ + + ECC_NIST_P384 + ECC_NIST_P521 + ECC_SM2_P256) +#define MAX_ECC_KEY_BITS \ + MAX(ECC_BN_P256 * 256, \ + MAX(ECC_BN_P638 * 638, \ + MAX(ECC_NIST_P192 * 192, \ + MAX(ECC_NIST_P224 * 224, \ + MAX(ECC_NIST_P256 * 256, \ + MAX(ECC_NIST_P384 * 384, \ + MAX(ECC_NIST_P521 * 521, MAX(ECC_SM2_P256 * 256, 0)))))))) +#define MAX_ECC_KEY_BYTES BITS_TO_BYTES(MAX_ECC_KEY_BITS) + +// Table 0:6 - Defines for PLATFORM Values +#define PLATFORM_FAMILY TPM_SPEC_FAMILY +#define PLATFORM_LEVEL TPM_SPEC_LEVEL +#define PLATFORM_VERSION TPM_SPEC_VERSION +#define PLATFORM_YEAR TPM_SPEC_YEAR +#define PLATFORM_DAY_OF_YEAR TPM_SPEC_DAY_OF_YEAR + +// Table 1:3 - Defines for RSA Asymmetric Cipher Algorithm Constants +#define RSA_KEY_SIZES_BITS \ + (1024 * RSA_1024), (2048 * RSA_2048), (3072 * RSA_3072), (4096 * RSA_4096), \ + (16384 * RSA_16384) +#if RSA_16384 +# define RSA_MAX_KEY_SIZE_BITS 16384 +#elif RSA_4096 +# define RSA_MAX_KEY_SIZE_BITS 4096 +#elif RSA_3072 +# define RSA_MAX_KEY_SIZE_BITS 3072 +#elif RSA_2048 +# define RSA_MAX_KEY_SIZE_BITS 2048 +#elif RSA_1024 +# define RSA_MAX_KEY_SIZE_BITS 1024 +#else +# define RSA_MAX_KEY_SIZE_BITS 0 +#endif +#define MAX_RSA_KEY_BITS RSA_MAX_KEY_SIZE_BITS +#define MAX_RSA_KEY_BYTES ((RSA_MAX_KEY_SIZE_BITS + 7) / 8) + +// Table 1:13 - Defines for SHA1 Hash Values +#define SHA1_DIGEST_SIZE 20 +#define SHA1_BLOCK_SIZE 64 + +// Table 1:14 - Defines for SHA256 Hash Values +#define SHA256_DIGEST_SIZE 32 +#define SHA256_BLOCK_SIZE 64 + +// Table 1:15 - Defines for SHA384 Hash Values +#define SHA384_DIGEST_SIZE 48 +#define SHA384_BLOCK_SIZE 128 + +// Table 1:16 - Defines for SHA512 Hash Values +#define SHA512_DIGEST_SIZE 64 +#define SHA512_BLOCK_SIZE 128 + +// Table 1:17 - Defines for SM3_256 Hash Values +#define SM3_256_DIGEST_SIZE 32 +#define SM3_256_BLOCK_SIZE 64 + +// Table 1:18 - Defines for SHA3_256 Hash Values +#define SHA3_256_DIGEST_SIZE 32 +#define SHA3_256_BLOCK_SIZE 136 + +// Table 1:19 - Defines for SHA3_384 Hash Values +#define SHA3_384_DIGEST_SIZE 48 +#define SHA3_384_BLOCK_SIZE 104 + +// Table 1:20 - Defines for SHA3_512 Hash Values +#define SHA3_512_DIGEST_SIZE 64 +#define SHA3_512_BLOCK_SIZE 72 + +// Table 1:21 - Defines for AES Symmetric Cipher Algorithm Constants +#define AES_KEY_SIZES_BITS (128 * AES_128), (192 * AES_192), (256 * AES_256) +#if AES_256 +# define AES_MAX_KEY_SIZE_BITS 256 +#elif AES_192 +# define AES_MAX_KEY_SIZE_BITS 192 +#elif AES_128 +# define AES_MAX_KEY_SIZE_BITS 128 +#else +# define AES_MAX_KEY_SIZE_BITS 0 +#endif +#define MAX_AES_KEY_BITS AES_MAX_KEY_SIZE_BITS +#define MAX_AES_KEY_BYTES ((AES_MAX_KEY_SIZE_BITS + 7) / 8) +#define AES_128_BLOCK_SIZE_BYTES (AES_128 * 16) +#define AES_192_BLOCK_SIZE_BYTES (AES_192 * 16) +#define AES_256_BLOCK_SIZE_BYTES (AES_256 * 16) +#define AES_BLOCK_SIZES \ + AES_128_BLOCK_SIZE_BYTES, AES_192_BLOCK_SIZE_BYTES, AES_256_BLOCK_SIZE_BYTES +#if ALG_AES +# define AES_MAX_BLOCK_SIZE 16 +#else +# define AES_MAX_BLOCK_SIZE 0 +#endif +#define MAX_AES_BLOCK_SIZE_BYTES AES_MAX_BLOCK_SIZE + +// Table 1:22 - Defines for SM4 Symmetric Cipher Algorithm Constants +#define SM4_KEY_SIZES_BITS (128 * SM4_128) +#if SM4_128 +# define SM4_MAX_KEY_SIZE_BITS 128 +#else +# define SM4_MAX_KEY_SIZE_BITS 0 +#endif +#define MAX_SM4_KEY_BITS SM4_MAX_KEY_SIZE_BITS +#define MAX_SM4_KEY_BYTES ((SM4_MAX_KEY_SIZE_BITS + 7) / 8) +#define SM4_128_BLOCK_SIZE_BYTES (SM4_128 * 16) +#define SM4_BLOCK_SIZES SM4_128_BLOCK_SIZE_BYTES +#if ALG_SM4 +# define SM4_MAX_BLOCK_SIZE 16 +#else +# define SM4_MAX_BLOCK_SIZE 0 +#endif +#define MAX_SM4_BLOCK_SIZE_BYTES SM4_MAX_BLOCK_SIZE + +// Table 1:23 - Defines for CAMELLIA Symmetric Cipher Algorithm Constants +#define CAMELLIA_KEY_SIZES_BITS \ + (128 * CAMELLIA_128), (192 * CAMELLIA_192), (256 * CAMELLIA_256) +#if CAMELLIA_256 +# define CAMELLIA_MAX_KEY_SIZE_BITS 256 +#elif CAMELLIA_192 +# define CAMELLIA_MAX_KEY_SIZE_BITS 192 +#elif CAMELLIA_128 +# define CAMELLIA_MAX_KEY_SIZE_BITS 128 +#else +# define CAMELLIA_MAX_KEY_SIZE_BITS 0 +#endif +#define MAX_CAMELLIA_KEY_BITS CAMELLIA_MAX_KEY_SIZE_BITS +#define MAX_CAMELLIA_KEY_BYTES ((CAMELLIA_MAX_KEY_SIZE_BITS + 7) / 8) +#define CAMELLIA_128_BLOCK_SIZE_BYTES (CAMELLIA_128 * 16) +#define CAMELLIA_192_BLOCK_SIZE_BYTES (CAMELLIA_192 * 16) +#define CAMELLIA_256_BLOCK_SIZE_BYTES (CAMELLIA_256 * 16) +#define CAMELLIA_BLOCK_SIZES \ + CAMELLIA_128_BLOCK_SIZE_BYTES, CAMELLIA_192_BLOCK_SIZE_BYTES, \ + CAMELLIA_256_BLOCK_SIZE_BYTES +#if ALG_CAMELLIA +# define CAMELLIA_MAX_BLOCK_SIZE 16 +#else +# define CAMELLIA_MAX_BLOCK_SIZE 0 +#endif +#define MAX_CAMELLIA_BLOCK_SIZE_BYTES CAMELLIA_MAX_BLOCK_SIZE + +// Table 1:24 - Defines for TDES Symmetric Cipher Algorithm Constants +#define TDES_KEY_SIZES_BITS (128 * TDES_128), (192 * TDES_192) +#if TDES_192 +# define TDES_MAX_KEY_SIZE_BITS 192 +#elif TDES_128 +# define TDES_MAX_KEY_SIZE_BITS 128 +#else +# define TDES_MAX_KEY_SIZE_BITS 0 +#endif +#define MAX_TDES_KEY_BITS TDES_MAX_KEY_SIZE_BITS +#define MAX_TDES_KEY_BYTES ((TDES_MAX_KEY_SIZE_BITS + 7) / 8) +#define TDES_128_BLOCK_SIZE_BYTES (TDES_128 * 8) +#define TDES_192_BLOCK_SIZE_BYTES (TDES_192 * 8) +#define TDES_BLOCK_SIZES TDES_128_BLOCK_SIZE_BYTES, TDES_192_BLOCK_SIZE_BYTES +#if ALG_TDES +# define TDES_MAX_BLOCK_SIZE 8 +#else +# define TDES_MAX_BLOCK_SIZE 0 +#endif +#define MAX_TDES_BLOCK_SIZE_BYTES TDES_MAX_BLOCK_SIZE + +// Additional values for benefit of code +#define TPM_CC_FIRST 0x0000011F +#define TPM_CC_LAST 0x0000019A + +#if COMPRESSED_LISTS +# define ADD_FILL 0 +#else +# define ADD_FILL 1 +#endif + +// Size the array of library commands based on whether or not +// the array is packed (only defined commands) or dense +// (having entries for unimplemented commands) +#define LIBRARY_COMMAND_ARRAY_SIZE \ + (0 + (ADD_FILL || CC_NV_UndefineSpaceSpecial) /* 0x0000011F */ \ + + (ADD_FILL || CC_EvictControl) /* 0x00000120 */ \ + + (ADD_FILL || CC_HierarchyControl) /* 0x00000121 */ \ + + (ADD_FILL || CC_NV_UndefineSpace) /* 0x00000122 */ \ + + ADD_FILL /* 0x00000123 */ \ + + (ADD_FILL || CC_ChangeEPS) /* 0x00000124 */ \ + + (ADD_FILL || CC_ChangePPS) /* 0x00000125 */ \ + + (ADD_FILL || CC_Clear) /* 0x00000126 */ \ + + (ADD_FILL || CC_ClearControl) /* 0x00000127 */ \ + + (ADD_FILL || CC_ClockSet) /* 0x00000128 */ \ + + (ADD_FILL || CC_HierarchyChangeAuth) /* 0x00000129 */ \ + + (ADD_FILL || CC_NV_DefineSpace) /* 0x0000012A */ \ + + (ADD_FILL || CC_PCR_Allocate) /* 0x0000012B */ \ + + (ADD_FILL || CC_PCR_SetAuthPolicy) /* 0x0000012C */ \ + + (ADD_FILL || CC_PP_Commands) /* 0x0000012D */ \ + + (ADD_FILL || CC_SetPrimaryPolicy) /* 0x0000012E */ \ + + (ADD_FILL || CC_FieldUpgradeStart) /* 0x0000012F */ \ + + (ADD_FILL || CC_ClockRateAdjust) /* 0x00000130 */ \ + + (ADD_FILL || CC_CreatePrimary) /* 0x00000131 */ \ + + (ADD_FILL || CC_NV_GlobalWriteLock) /* 0x00000132 */ \ + + (ADD_FILL || CC_GetCommandAuditDigest) /* 0x00000133 */ \ + + (ADD_FILL || CC_NV_Increment) /* 0x00000134 */ \ + + (ADD_FILL || CC_NV_SetBits) /* 0x00000135 */ \ + + (ADD_FILL || CC_NV_Extend) /* 0x00000136 */ \ + + (ADD_FILL || CC_NV_Write) /* 0x00000137 */ \ + + (ADD_FILL || CC_NV_WriteLock) /* 0x00000138 */ \ + + (ADD_FILL || CC_DictionaryAttackLockReset) /* 0x00000139 */ \ + + (ADD_FILL || CC_DictionaryAttackParameters) /* 0x0000013A */ \ + + (ADD_FILL || CC_NV_ChangeAuth) /* 0x0000013B */ \ + + (ADD_FILL || CC_PCR_Event) /* 0x0000013C */ \ + + (ADD_FILL || CC_PCR_Reset) /* 0x0000013D */ \ + + (ADD_FILL || CC_SequenceComplete) /* 0x0000013E */ \ + + (ADD_FILL || CC_SetAlgorithmSet) /* 0x0000013F */ \ + + (ADD_FILL || CC_SetCommandCodeAuditStatus) /* 0x00000140 */ \ + + (ADD_FILL || CC_FieldUpgradeData) /* 0x00000141 */ \ + + (ADD_FILL || CC_IncrementalSelfTest) /* 0x00000142 */ \ + + (ADD_FILL || CC_SelfTest) /* 0x00000143 */ \ + + (ADD_FILL || CC_Startup) /* 0x00000144 */ \ + + (ADD_FILL || CC_Shutdown) /* 0x00000145 */ \ + + (ADD_FILL || CC_StirRandom) /* 0x00000146 */ \ + + (ADD_FILL || CC_ActivateCredential) /* 0x00000147 */ \ + + (ADD_FILL || CC_Certify) /* 0x00000148 */ \ + + (ADD_FILL || CC_PolicyNV) /* 0x00000149 */ \ + + (ADD_FILL || CC_CertifyCreation) /* 0x0000014A */ \ + + (ADD_FILL || CC_Duplicate) /* 0x0000014B */ \ + + (ADD_FILL || CC_GetTime) /* 0x0000014C */ \ + + (ADD_FILL || CC_GetSessionAuditDigest) /* 0x0000014D */ \ + + (ADD_FILL || CC_NV_Read) /* 0x0000014E */ \ + + (ADD_FILL || CC_NV_ReadLock) /* 0x0000014F */ \ + + (ADD_FILL || CC_ObjectChangeAuth) /* 0x00000150 */ \ + + (ADD_FILL || CC_PolicySecret) /* 0x00000151 */ \ + + (ADD_FILL || CC_Rewrap) /* 0x00000152 */ \ + + (ADD_FILL || CC_Create) /* 0x00000153 */ \ + + (ADD_FILL || CC_ECDH_ZGen) /* 0x00000154 */ \ + + (ADD_FILL || CC_HMAC || CC_MAC) /* 0x00000155 */ \ + + (ADD_FILL || CC_Import) /* 0x00000156 */ \ + + (ADD_FILL || CC_Load) /* 0x00000157 */ \ + + (ADD_FILL || CC_Quote) /* 0x00000158 */ \ + + (ADD_FILL || CC_RSA_Decrypt) /* 0x00000159 */ \ + + ADD_FILL /* 0x0000015A */ \ + + (ADD_FILL || CC_HMAC_Start || CC_MAC_Start) /* 0x0000015B */ \ + + (ADD_FILL || CC_SequenceUpdate) /* 0x0000015C */ \ + + (ADD_FILL || CC_Sign) /* 0x0000015D */ \ + + (ADD_FILL || CC_Unseal) /* 0x0000015E */ \ + + ADD_FILL /* 0x0000015F */ \ + + (ADD_FILL || CC_PolicySigned) /* 0x00000160 */ \ + + (ADD_FILL || CC_ContextLoad) /* 0x00000161 */ \ + + (ADD_FILL || CC_ContextSave) /* 0x00000162 */ \ + + (ADD_FILL || CC_ECDH_KeyGen) /* 0x00000163 */ \ + + (ADD_FILL || CC_EncryptDecrypt) /* 0x00000164 */ \ + + (ADD_FILL || CC_FlushContext) /* 0x00000165 */ \ + + ADD_FILL /* 0x00000166 */ \ + + (ADD_FILL || CC_LoadExternal) /* 0x00000167 */ \ + + (ADD_FILL || CC_MakeCredential) /* 0x00000168 */ \ + + (ADD_FILL || CC_NV_ReadPublic) /* 0x00000169 */ \ + + (ADD_FILL || CC_PolicyAuthorize) /* 0x0000016A */ \ + + (ADD_FILL || CC_PolicyAuthValue) /* 0x0000016B */ \ + + (ADD_FILL || CC_PolicyCommandCode) /* 0x0000016C */ \ + + (ADD_FILL || CC_PolicyCounterTimer) /* 0x0000016D */ \ + + (ADD_FILL || CC_PolicyCpHash) /* 0x0000016E */ \ + + (ADD_FILL || CC_PolicyLocality) /* 0x0000016F */ \ + + (ADD_FILL || CC_PolicyNameHash) /* 0x00000170 */ \ + + (ADD_FILL || CC_PolicyOR) /* 0x00000171 */ \ + + (ADD_FILL || CC_PolicyTicket) /* 0x00000172 */ \ + + (ADD_FILL || CC_ReadPublic) /* 0x00000173 */ \ + + (ADD_FILL || CC_RSA_Encrypt) /* 0x00000174 */ \ + + ADD_FILL /* 0x00000175 */ \ + + (ADD_FILL || CC_StartAuthSession) /* 0x00000176 */ \ + + (ADD_FILL || CC_VerifySignature) /* 0x00000177 */ \ + + (ADD_FILL || CC_ECC_Parameters) /* 0x00000178 */ \ + + (ADD_FILL || CC_FirmwareRead) /* 0x00000179 */ \ + + (ADD_FILL || CC_GetCapability) /* 0x0000017A */ \ + + (ADD_FILL || CC_GetRandom) /* 0x0000017B */ \ + + (ADD_FILL || CC_GetTestResult) /* 0x0000017C */ \ + + (ADD_FILL || CC_Hash) /* 0x0000017D */ \ + + (ADD_FILL || CC_PCR_Read) /* 0x0000017E */ \ + + (ADD_FILL || CC_PolicyPCR) /* 0x0000017F */ \ + + (ADD_FILL || CC_PolicyRestart) /* 0x00000180 */ \ + + (ADD_FILL || CC_ReadClock) /* 0x00000181 */ \ + + (ADD_FILL || CC_PCR_Extend) /* 0x00000182 */ \ + + (ADD_FILL || CC_PCR_SetAuthValue) /* 0x00000183 */ \ + + (ADD_FILL || CC_NV_Certify) /* 0x00000184 */ \ + + (ADD_FILL || CC_EventSequenceComplete) /* 0x00000185 */ \ + + (ADD_FILL || CC_HashSequenceStart) /* 0x00000186 */ \ + + (ADD_FILL || CC_PolicyPhysicalPresence) /* 0x00000187 */ \ + + (ADD_FILL || CC_PolicyDuplicationSelect) /* 0x00000188 */ \ + + (ADD_FILL || CC_PolicyGetDigest) /* 0x00000189 */ \ + + (ADD_FILL || CC_TestParms) /* 0x0000018A */ \ + + (ADD_FILL || CC_Commit) /* 0x0000018B */ \ + + (ADD_FILL || CC_PolicyPassword) /* 0x0000018C */ \ + + (ADD_FILL || CC_ZGen_2Phase) /* 0x0000018D */ \ + + (ADD_FILL || CC_EC_Ephemeral) /* 0x0000018E */ \ + + (ADD_FILL || CC_PolicyNvWritten) /* 0x0000018F */ \ + + (ADD_FILL || CC_PolicyTemplate) /* 0x00000190 */ \ + + (ADD_FILL || CC_CreateLoaded) /* 0x00000191 */ \ + + (ADD_FILL || CC_PolicyAuthorizeNV) /* 0x00000192 */ \ + + (ADD_FILL || CC_EncryptDecrypt2) /* 0x00000193 */ \ + + (ADD_FILL || CC_AC_GetCapability) /* 0x00000194 */ \ + + (ADD_FILL || CC_AC_Send) /* 0x00000195 */ \ + + (ADD_FILL || CC_Policy_AC_SendSelect) /* 0x00000196 */ \ + + (ADD_FILL || CC_CertifyX509) /* 0x00000197 */ \ + + (ADD_FILL || CC_ACT_SetTimeout) /* 0x00000198 */ \ + + (ADD_FILL || CC_ECC_Encrypt) /* 0x00000199 */ \ + + (ADD_FILL || CC_ECC_Decrypt) /* 0x0000019A */ \ + ) + +#define VENDOR_COMMAND_ARRAY_SIZE (0 + CC_Vendor_TCG_Test) + +#define COMMAND_COUNT (LIBRARY_COMMAND_ARRAY_SIZE + VENDOR_COMMAND_ARRAY_SIZE) + +#define HASH_COUNT \ + (ALG_SHA1 + ALG_SHA256 + ALG_SHA384 + ALG_SHA3_256 + ALG_SHA3_384 + ALG_SHA3_512 \ + + ALG_SHA512 + ALG_SM3_256) + +#define MAX_HASH_BLOCK_SIZE \ + (MAX(ALG_SHA1 * SHA1_BLOCK_SIZE, \ + MAX(ALG_SHA256 * SHA256_BLOCK_SIZE, \ + MAX(ALG_SHA384 * SHA384_BLOCK_SIZE, \ + MAX(ALG_SHA3_256 * SHA3_256_BLOCK_SIZE, \ + MAX(ALG_SHA3_384 * SHA3_384_BLOCK_SIZE, \ + MAX(ALG_SHA3_512 * SHA3_512_BLOCK_SIZE, \ + MAX(ALG_SHA512 * SHA512_BLOCK_SIZE, \ + MAX(ALG_SM3_256 * SM3_256_BLOCK_SIZE, 0))))))))) + +#define MAX_DIGEST_SIZE \ + (MAX(ALG_SHA1 * SHA1_DIGEST_SIZE, \ + MAX(ALG_SHA256 * SHA256_DIGEST_SIZE, \ + MAX(ALG_SHA384 * SHA384_DIGEST_SIZE, \ + MAX(ALG_SHA3_256 * SHA3_256_DIGEST_SIZE, \ + MAX(ALG_SHA3_384 * SHA3_384_DIGEST_SIZE, \ + MAX(ALG_SHA3_512 * SHA3_512_DIGEST_SIZE, \ + MAX(ALG_SHA512 * SHA512_DIGEST_SIZE, \ + MAX(ALG_SM3_256 * SM3_256_DIGEST_SIZE, 0))))))))) + +#if MAX_DIGEST_SIZE == 0 || MAX_HASH_BLOCK_SIZE == 0 +# error "Hash data not valid" +#endif + +// Define the 2B structure that would hold any hash block +TPM2B_TYPE(MAX_HASH_BLOCK, MAX_HASH_BLOCK_SIZE); + +// Following typedef is for some old code +typedef TPM2B_MAX_HASH_BLOCK TPM2B_HASH_BLOCK; + +/* Additional symmetric constants */ +#define MAX_SYM_KEY_BITS \ + (MAX(AES_MAX_KEY_SIZE_BITS, \ + MAX(CAMELLIA_MAX_KEY_SIZE_BITS, \ + MAX(SM4_MAX_KEY_SIZE_BITS, MAX(TDES_MAX_KEY_SIZE_BITS, 0))))) + +#define MAX_SYM_KEY_BYTES ((MAX_SYM_KEY_BITS + 7) / 8) + +#define MAX_SYM_BLOCK_SIZE \ + (MAX(AES_MAX_BLOCK_SIZE, \ + MAX(CAMELLIA_MAX_BLOCK_SIZE, \ + MAX(SM4_MAX_BLOCK_SIZE, MAX(TDES_MAX_BLOCK_SIZE, 0))))) + +#if MAX_SYM_KEY_BITS == 0 || MAX_SYM_BLOCK_SIZE == 0 +# error Bad size for MAX_SYM_KEY_BITS or MAX_SYM_BLOCK +#endif + +#endif // _TPM_ALGORITHM_DEFINES_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TpmBuildSwitches.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TpmBuildSwitches.h new file mode 100644 index 0000000..32d77f6 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TpmBuildSwitches.h @@ -0,0 +1,343 @@ + +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 contains the build switches. This contains switches for multiple +// versions of the crypto-library so some may not apply to your environment. +// +// The switches are guarded so that they can either be set on the command line or +// set here. If the switch is listed on the command line (-DSOME_SWITCH) with NO +// setting, then the switch will be set to YES. If the switch setting is not on the +// command line or if the setting is other than YES or NO, then the switch will be set +// to the default value. The default can either be YES or NO as indicated on each line +// where the default is selected. +// +// A caution: do not try to test these macros by inserting #defines in this file. For +// some curious reason, a variable set on the command line with no setting will have a +// value of 1. An "#if SOME_VARIABLE" will work if the variable is not defined or is +// defined on the command line with no initial setting. However, a +// "#define SOME_VARIABLE" is a null string and when used in "#if SOME_VARIABLE" will +// not be a proper expression If you want to test various switches, either use the +// command line or change the default. +// +#ifndef _TPM_BUILD_SWITCHES_H_ +#define _TPM_BUILD_SWITCHES_H_ + +#undef YES +#define YES 1 +#undef NO +#define NO 0 + +// Allow the command line to specify a "profile" file +#ifdef PROFILE +# define PROFILE_QUOTE(a) #a +# define PROFILE_INCLUDE(a) PROFILE_QUOTE(a) +# include PROFILE_INCLUDE(PROFILE) +#endif + +// Need an unambiguous definition for DEBUG. Do not change this +#ifndef DEBUG +# ifdef NDEBUG +# define DEBUG NO +# else +# define DEBUG YES +# endif +#elif(DEBUG != NO) && (DEBUG != YES) +# undef DEBUG +# define DEBUG YES // Default: Either YES or NO +#endif + +#include "CompilerDependencies.h" + +// This definition is required for the re-factored code +#if(!defined USE_BN_ECC_DATA) || ((USE_BN_ECC_DATA != NO) && (USE_BN_ECC_DATA != YES)) +# undef USE_BN_ECC_DATA +# define USE_BN_ECC_DATA YES // Default: Either YES or NO +#endif + +// The SIMULATION switch allows certain other macros to be enabled. The things that +// can be enabled in a simulation include key caching, reproducible "random" +// sequences, instrumentation of the RSA key generation process, and certain other +// debug code. SIMULATION Needs to be defined as either YES or NO. This grouping of +// macros will make sure that it is set correctly. A simulated TPM would include a +// Virtual TPM. The interfaces for a Virtual TPM should be modified from the standard +// ones in the Simulator project. +// +// If SIMULATION is in the compile parameters without modifiers, +// make SIMULATION == YES +#if !(defined SIMULATION) || ((SIMULATION != NO) && (SIMULATION != YES)) +# undef SIMULATION +# define SIMULATION YES // Default: Either YES or NO +#endif + +// Define this to run the function that checks the compatibility between the +// chosen big number math library and the TPM code. Not all ports use this. +#if !(defined LIBRARY_COMPATIBILITY_CHECK) \ + || ((LIBRARY_COMPATIBILITY_CHECK != NO) && (LIBRARY_COMPATIBILITY_CHECK != YES)) +# undef LIBRARY_COMPATIBILITY_CHECK +# define LIBRARY_COMPATIBILITY_CHECK YES // Default: Either YES or NO +#endif + +#if !(defined FIPS_COMPLIANT) || ((FIPS_COMPLIANT != NO) && (FIPS_COMPLIANT != YES)) +# undef FIPS_COMPLIANT +# define FIPS_COMPLIANT YES // Default: Either YES or NO +#endif + +// Definition to allow alternate behavior for non-orderly startup. If there is a +// chance that the TPM could not update 'failedTries' +#if !(defined USE_DA_USED) || ((USE_DA_USED != NO) && (USE_DA_USED != YES)) +# undef USE_DA_USED +# define USE_DA_USED YES // Default: Either YES or NO +#endif + +// Define TABLE_DRIVEN_DISPATCH to use tables rather than case statements +// for command dispatch and handle unmarshaling +#if !(defined TABLE_DRIVEN_DISPATCH) \ + || ((TABLE_DRIVEN_DISPATCH != NO) && (TABLE_DRIVEN_DISPATCH != YES)) +# undef TABLE_DRIVEN_DISPATCH +# define TABLE_DRIVEN_DISPATCH YES // Default: Either YES or NO +#endif + +// This switch is used to enable the self-test capability in AlgorithmTests.c +#if !(defined SELF_TEST) || ((SELF_TEST != NO) && (SELF_TEST != YES)) +# undef SELF_TEST +# define SELF_TEST YES // Default: Either YES or NO +#endif + +// Enable the generation of RSA primes using a sieve. +#if !(defined RSA_KEY_SIEVE) || ((RSA_KEY_SIEVE != NO) && (RSA_KEY_SIEVE != YES)) +# undef RSA_KEY_SIEVE +# define RSA_KEY_SIEVE YES // Default: Either YES or NO +#endif + +// Enable the instrumentation of the sieve process. This is used to tune the sieve +// variables. +#if RSA_KEY_SIEVE && SIMULATION +# if !(defined RSA_INSTRUMENT) || ((RSA_INSTRUMENT != NO) && (RSA_INSTRUMENT != YES)) +# undef RSA_INSTRUMENT +# define RSA_INSTRUMENT NO // Default: Either YES or NO +# endif +#endif + +// This switch enables the RNG state save and restore +#if !(defined _DRBG_STATE_SAVE) \ + || ((_DRBG_STATE_SAVE != NO) && (_DRBG_STATE_SAVE != YES)) +# undef _DRBG_STATE_SAVE +# define _DRBG_STATE_SAVE YES // Default: Either YES or NO +#endif + +// Switch added to support packed lists that leave out space associated with +// unimplemented commands. Comment this out to use linear lists. +// Note: if vendor specific commands are present, the associated list is always +// in compressed form. +#if !(defined COMPRESSED_LISTS) \ + || ((COMPRESSED_LISTS != NO) && (COMPRESSED_LISTS != YES)) +# undef COMPRESSED_LISTS +# define COMPRESSED_LISTS YES // Default: Either YES or NO +#endif + +// This switch indicates where clock epoch value should be stored. If this value +// defined, then it is assumed that the timer will change at any time so the +// nonce should be a random number kept in RAM. When it is not defined, then the +// timer only stops during power outages. +#if !(defined CLOCK_STOPS) || ((CLOCK_STOPS != NO) && (CLOCK_STOPS != YES)) +# undef CLOCK_STOPS +# define CLOCK_STOPS NO // Default: Either YES or NO +#endif + +// This switch allows use of #defines in place of pass-through marshaling or +// unmarshaling code. A pass-through function just calls another function to do +// the required function and does no parameter checking of its own. The +// table-driven dispatcher calls directly to the lowest level +// marshaling/unmarshaling code and by-passes any pass-through functions. +#if(defined USE_MARSHALING_DEFINES) && (USE_MARSHALING_DEFINES != NO) +# undef USE_MARSHALING_DEFINES +# define USE_MARSHALING_DEFINES YES +#else +# define USE_MARSHALING_DEFINES YES // Default: Either YES or NO +#endif + +//********************************** +// The switches in this group can only be enabled when doing debug during simulation +#if SIMULATION && DEBUG +// This forces the use of a smaller context slot size. This reduction reduces the +// range of the epoch allowing the tester to force the epoch to occur faster than +// the normal defined in TpmProfile.h +# if !(defined CONTEXT_SLOT) +# define CONTEXT_SLOT UINT8 +# endif +// Enables use of the key cache. Default is YES +# if !(defined USE_RSA_KEY_CACHE) \ + || ((USE_RSA_KEY_CACHE != NO) && (USE_RSA_KEY_CACHE != YES)) +# undef USE_RSA_KEY_CACHE +# define USE_RSA_KEY_CACHE YES // Default: Either YES or NO +# endif + +// Enables use of a file to store the key cache values so that the TPM will start +// faster during debug. Default for this is YES +# if USE_RSA_KEY_CACHE +# if !(defined USE_KEY_CACHE_FILE) \ + || ((USE_KEY_CACHE_FILE != NO) && (USE_KEY_CACHE_FILE != YES)) +# undef USE_KEY_CACHE_FILE +# define USE_KEY_CACHE_FILE YES // Default: Either YES or NO +# endif +# else +# undef USE_KEY_CACHE_FILE +# define USE_KEY_CACHE_FILE NO +# endif // USE_RSA_KEY_CACHE + +// This provides fixed seeding of the RNG when doing debug on a simulator. This +// should allow consistent results on test runs as long as the input parameters +// to the functions remains the same. There is no default value. +# if !(defined USE_DEBUG_RNG) || ((USE_DEBUG_RNG != NO) && (USE_DEBUG_RNG != YES)) +# undef USE_DEBUG_RNG +# define USE_DEBUG_RNG YES // Default: Either YES or NO +# endif + +// Do not change these. They are the settings needed when not doing a simulation and +// not doing debug. Can't use the key cache except during debug. Otherwise, all of the +// key values end up being the same +#else +# define USE_RSA_KEY_CACHE NO +# define USE_RSA_KEY_CACHE_FILE NO +# define USE_DEBUG_RNG NO +#endif // DEBUG && SIMULATION + +#if DEBUG + +// In some cases, the relationship between two values may be dependent +// on things that change based on various selections like the chosen cryptographic +// libraries. It is possible that these selections will result in incompatible +// settings. These are often detectable by the compiler but it is not always +// possible to do the check in the preprocessor code. For example, when the +// check requires use of 'sizeof'() then the preprocessor can't do the comparison. +// For these cases, we include a special macro that, depending on the compiler +// will generate a warning to indicate if the check always passes or always fails +// because it involves fixed constants. To run these checks, define COMPILER_CHECKS. +# if !(defined COMPILER_CHECKS) \ + || ((COMPILER_CHECKS != NO) && (COMPILER_CHECKS != YES)) +# undef COMPILER_CHECKS +# define COMPILER_CHECKS NO // Default: Either YES or NO +# endif + +// Some of the values (such as sizes) are the result of different options set in +// TpmProfile.h. The combination might not be consistent. A function is defined +// (TpmSizeChecks()) that is used to verify the sizes at run time. To enable the +// function, define this parameter. +# if !(defined RUNTIME_SIZE_CHECKS) \ + || ((RUNTIME_SIZE_CHECKS != NO) && (RUNTIME_SIZE_CHECKS != YES)) +# undef RUNTIME_SIZE_CHECKS +# define RUNTIME_SIZE_CHECKS YES // Default: Either YES or NO +# endif + +// If doing debug, can set the DRBG to print out the intermediate test values. +// Before enabling this, make sure that the dbgDumpMemBlock() function +// has been added someplace (preferably, somewhere in CryptRand.c) +# if !(defined DRBG_DEBUG_PRINT) \ + || ((DRBG_DEBUG_PRINT != NO) && (DRBG_DEBUG_PRINT != YES)) +# undef DRBG_DEBUG_PRINT +# define DRBG_DEBUG_PRINT NO // Default: Either YES or NO +# endif + +// If an assertion event it not going to produce any trace information (function and +// line number) then make FAIL_TRACE == NO +# if !(defined FAIL_TRACE) || ((FAIL_TRACE != NO) && (FAIL_TRACE != YES)) +# undef FAIL_TRACE +# define FAIL_TRACE YES // Default: Either YES or NO +# endif + +#endif // DEBUG + +// Indicate if the implementation is going to give lockout time credit for time up to +// the last orderly shutdown. +#if !(defined ACCUMULATE_SELF_HEAL_TIMER) \ + || ((ACCUMULATE_SELF_HEAL_TIMER != NO) && (ACCUMULATE_SELF_HEAL_TIMER != YES)) +# undef ACCUMULATE_SELF_HEAL_TIMER +# define ACCUMULATE_SELF_HEAL_TIMER YES // Default: Either YES or NO +#endif + +// Indicates if the implementation is to compute the sizes of the proof and primary +// seed size values based on the implemented algorithms. +#if !(defined USE_SPEC_COMPLIANT_PROOFS) \ + || ((USE_SPEC_COMPLIANT_PROOFS != NO) && (USE_SPEC_COMPLIANT_PROOFS != YES)) +# undef USE_SPEC_COMPLIANT_PROOFS +# define USE_SPEC_COMPLIANT_PROOFS YES // Default: Either YES or NO +#endif + +// Comment this out to allow compile to continue even though the chosen proof values +// do not match the compliant values. This is written so that someone would +// have to proactively ignore errors. +#if !(defined SKIP_PROOF_ERRORS) \ + || ((SKIP_PROOF_ERRORS != NO) && (SKIP_PROOF_ERRORS != YES)) +# undef SKIP_PROOF_ERRORS +# define SKIP_PROOF_ERRORS NO // Default: Either YES or NO +#endif + +// This define is used to eliminate the use of bit-fields. It can be enabled for big- +// or little-endian machines. For big-endian architectures that numbers bits in +// registers from left to right (MSb0) this must be enabled. Little-endian machines +// number from right to left with the least significant bit having assigned a bit +// number of 0. These are LSb0 machines (they are also little-endian so they are also +// least-significant byte 0 (LSB0) machines. Big-endian (MSB0) machines may number in +// either direction (MSb0 or LSb0). For an MSB0+MSb0 machine this value is required to +// be 'NO' +#if !(defined USE_BIT_FIELD_STRUCTURES) \ + || ((USE_BIT_FIELD_STRUCTURES != NO) && (USE_BIT_FIELD_STRUCTURES != YES)) +# undef USE_BIT_FIELD_STRUCTURES +# define USE_BIT_FIELD_STRUCTURES NO // Default: Either YES or NO +#endif + +// This define is used to control the debug for the CertifyX509 command. +#if !(defined CERTIFYX509_DEBUG) \ + || ((CERTIFYX509_DEBUG != NO) && (CERTIFYX509_DEBUG != YES)) +# undef CERTIFYX509_DEBUG +# define CERTIFYX509_DEBUG YES // Default: Either YES or NO +#endif + +// This define is used to enable the new table-driven marshaling code. +#if !(defined TABLE_DRIVEN_MARSHAL) \ + || ((TABLE_DRIVEN_MARSHAL != NO) && (TABLE_DRIVEN_MARSHAL != YES)) +# undef TABLE_DRIVEN_MARSHAL +# define TABLE_DRIVEN_MARSHAL NO // Default: Either YES or NO +#endif + +// Change these definitions to turn all algorithms or commands ON or OFF. That is, +// to turn all algorithms on, set ALG_NO to YES. This is mostly useful as a debug +// feature. +#define ALG_YES YES +#define ALG_NO NO +#define CC_YES YES +#define CC_NO NO + +#endif // _TPM_BUILD_SWITCHES_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TpmError.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TpmError.h new file mode 100644 index 0000000..80a057a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TpmError.h @@ -0,0 +1,57 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 _TPM_ERROR_H +#define _TPM_ERROR_H + +#define FATAL_ERROR_ALLOCATION (1) +#define FATAL_ERROR_DIVIDE_ZERO (2) +#define FATAL_ERROR_INTERNAL (3) +#define FATAL_ERROR_PARAMETER (4) +#define FATAL_ERROR_ENTROPY (5) +#define FATAL_ERROR_SELF_TEST (6) +#define FATAL_ERROR_CRYPTO (7) +#define FATAL_ERROR_NV_UNRECOVERABLE (8) +// indicates that the TPM has +// been re-manufactured after an +// unrecoverable NV error +#define FATAL_ERROR_REMANUFACTURED (9) +#define FATAL_ERROR_DRBG (10) +#define FATAL_ERROR_MOVE_SIZE (11) +#define FATAL_ERROR_COUNTER_OVERFLOW (12) +#define FATAL_ERROR_SUBTRACT (13) +#define FATAL_ERROR_MATHLIBRARY (14) +#define FATAL_ERROR_FORCED (666) + +#endif // _TPM_ERROR_H diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TpmProfile.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TpmProfile.h new file mode 100644 index 0000000..774e513 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TpmProfile.h @@ -0,0 +1,784 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 4, 2020 Time: 02:36:43PM + */ + +#ifndef _TPM_PROFILE_H_ +#define _TPM_PROFILE_H_ + +// Table 2:4 - Defines for Logic Values +#undef TRUE +#define TRUE 1 +#undef FALSE +#define FALSE 0 +#undef YES +#define YES 1 +#undef NO +#define NO 0 +#undef SET +#define SET 1 +#undef CLEAR +#define CLEAR 0 + +// Table 0:1 - Defines for Processor Values +#ifndef BIG_ENDIAN_TPM +# define BIG_ENDIAN_TPM NO +#endif +#ifndef LITTLE_ENDIAN_TPM +# define LITTLE_ENDIAN_TPM !BIG_ENDIAN_TPM +#endif +#ifndef MOST_SIGNIFICANT_BIT_0 +# define MOST_SIGNIFICANT_BIT_0 NO +#endif +#ifndef LEAST_SIGNIFICANT_BIT_0 +# define LEAST_SIGNIFICANT_BIT_0 !MOST_SIGNIFICANT_BIT_0 +#endif +#ifndef AUTO_ALIGN +# define AUTO_ALIGN NO +#endif + +// Table 0:4 - Defines for Implemented Curves +#ifndef ECC_NIST_P192 +# define ECC_NIST_P192 NO +#endif +#ifndef ECC_NIST_P224 +# define ECC_NIST_P224 NO +#endif +#ifndef ECC_NIST_P256 +# define ECC_NIST_P256 YES +#endif +#ifndef ECC_NIST_P384 +# define ECC_NIST_P384 YES +#endif +#ifndef ECC_NIST_P521 +# define ECC_NIST_P521 NO +#endif +#ifndef ECC_BN_P256 +# define ECC_BN_P256 YES +#endif +#ifndef ECC_BN_P638 +# define ECC_BN_P638 NO +#endif +#ifndef ECC_SM2_P256 +# define ECC_SM2_P256 YES +#endif + +// Table 0:6 - Defines for Implemented ACT +#ifndef RH_ACT_0 +# define RH_ACT_0 YES +#endif +#ifndef RH_ACT_1 +# define RH_ACT_1 NO +#endif +#ifndef RH_ACT_A +# define RH_ACT_A YES +#endif + +// Table 0:7 - Defines for Implementation Values +#ifndef FIELD_UPGRADE_IMPLEMENTED +# define FIELD_UPGRADE_IMPLEMENTED NO +#endif +#ifndef HASH_LIB +# define HASH_LIB Ossl +#endif +#ifndef SYM_LIB +# define SYM_LIB Ossl +#endif +#ifndef MATH_LIB +# define MATH_LIB Ossl +#endif +#ifndef IMPLEMENTATION_PCR +# define IMPLEMENTATION_PCR 24 +#endif +#ifndef PLATFORM_PCR +# define PLATFORM_PCR 24 +#endif +#ifndef DRTM_PCR +# define DRTM_PCR 17 +#endif +#ifndef HCRTM_PCR +# define HCRTM_PCR 0 +#endif +#ifndef NUM_LOCALITIES +# define NUM_LOCALITIES 5 +#endif +#ifndef MAX_HANDLE_NUM +# define MAX_HANDLE_NUM 3 +#endif +#ifndef MAX_ACTIVE_SESSIONS +# define MAX_ACTIVE_SESSIONS 64 +#endif +#ifndef CONTEXT_SLOT +# define CONTEXT_SLOT UINT16 +#endif +#ifndef MAX_LOADED_SESSIONS +# define MAX_LOADED_SESSIONS 3 +#endif +#ifndef MAX_SESSION_NUM +# define MAX_SESSION_NUM 3 +#endif +#ifndef MAX_LOADED_OBJECTS +# define MAX_LOADED_OBJECTS 3 +#endif +#ifndef MIN_EVICT_OBJECTS +# define MIN_EVICT_OBJECTS 2 +#endif +#ifndef NUM_POLICY_PCR_GROUP +# define NUM_POLICY_PCR_GROUP 1 +#endif +#ifndef NUM_AUTHVALUE_PCR_GROUP +# define NUM_AUTHVALUE_PCR_GROUP 1 +#endif +#ifndef MAX_CONTEXT_SIZE +# define MAX_CONTEXT_SIZE 1344 +#endif +#ifndef MAX_DIGEST_BUFFER +# define MAX_DIGEST_BUFFER 1024 +#endif +#ifndef MAX_NV_INDEX_SIZE +# define MAX_NV_INDEX_SIZE 2048 +#endif +#ifndef MAX_NV_BUFFER_SIZE +# define MAX_NV_BUFFER_SIZE 1024 +#endif +#ifndef MAX_CAP_BUFFER +# define MAX_CAP_BUFFER 1024 +#endif +#ifndef NV_MEMORY_SIZE +# define NV_MEMORY_SIZE 16384 +#endif +#ifndef MIN_COUNTER_INDICES +# define MIN_COUNTER_INDICES 8 +#endif +#ifndef NUM_STATIC_PCR +# define NUM_STATIC_PCR 16 +#endif +#ifndef MAX_ALG_LIST_SIZE +# define MAX_ALG_LIST_SIZE 64 +#endif +#ifndef PRIMARY_SEED_SIZE +# define PRIMARY_SEED_SIZE 32 +#endif +#ifndef CONTEXT_ENCRYPT_ALGORITHM +# define CONTEXT_ENCRYPT_ALGORITHM AES +#endif +#ifndef NV_CLOCK_UPDATE_INTERVAL +# define NV_CLOCK_UPDATE_INTERVAL 12 +#endif +#ifndef NUM_POLICY_PCR +# define NUM_POLICY_PCR 1 +#endif +#ifndef MAX_COMMAND_SIZE +# define MAX_COMMAND_SIZE 4096 +#endif +#ifndef MAX_RESPONSE_SIZE +# define MAX_RESPONSE_SIZE 4096 +#endif +#ifndef ORDERLY_BITS +# define ORDERLY_BITS 8 +#endif +#ifndef MAX_SYM_DATA +# define MAX_SYM_DATA 128 +#endif +#ifndef MAX_RNG_ENTROPY_SIZE +# define MAX_RNG_ENTROPY_SIZE 64 +#endif +#ifndef RAM_INDEX_SPACE +# define RAM_INDEX_SPACE 512 +#endif +#ifndef RSA_DEFAULT_PUBLIC_EXPONENT +# define RSA_DEFAULT_PUBLIC_EXPONENT 0x00010001 +#endif +#ifndef ENABLE_PCR_NO_INCREMENT +# define ENABLE_PCR_NO_INCREMENT YES +#endif +#ifndef CRT_FORMAT_RSA +# define CRT_FORMAT_RSA YES +#endif +#ifndef VENDOR_COMMAND_COUNT +# define VENDOR_COMMAND_COUNT 0 +#endif +#ifndef MAX_VENDOR_BUFFER_SIZE +# define MAX_VENDOR_BUFFER_SIZE 1024 +#endif +#ifndef SIZE_OF_X509_SERIAL_NUMBER +# define SIZE_OF_X509_SERIAL_NUMBER 20 +#endif +#ifndef PRIVATE_VENDOR_SPECIFIC_BYTES +# define PRIVATE_VENDOR_SPECIFIC_BYTES RSA_PRIVATE_SIZE +#endif + +// Table 0:2 - Defines for Implemented Algorithms +#ifndef ALG_AES +# define ALG_AES ALG_YES +#endif +#ifndef ALG_CAMELLIA +# define ALG_CAMELLIA ALG_YES +#endif +#ifndef ALG_CBC +# define ALG_CBC ALG_YES +#endif +#ifndef ALG_CFB +# define ALG_CFB ALG_YES +#endif +#ifndef ALG_CMAC +# define ALG_CMAC ALG_YES +#endif +#ifndef ALG_CTR +# define ALG_CTR ALG_YES +#endif +#ifndef ALG_ECB +# define ALG_ECB ALG_YES +#endif +#ifndef ALG_ECC +# define ALG_ECC ALG_YES +#endif +#ifndef ALG_ECDAA +# define ALG_ECDAA (ALG_YES && ALG_ECC) +#endif +#ifndef ALG_ECDH +# define ALG_ECDH (ALG_YES && ALG_ECC) +#endif +#ifndef ALG_ECDSA +# define ALG_ECDSA (ALG_YES && ALG_ECC) +#endif +#ifndef ALG_ECMQV +# define ALG_ECMQV (ALG_NO && ALG_ECC) +#endif +#ifndef ALG_ECSCHNORR +# define ALG_ECSCHNORR (ALG_YES && ALG_ECC) +#endif +#ifndef ALG_HMAC +# define ALG_HMAC ALG_YES +#endif +#ifndef ALG_KDF1_SP800_108 +# define ALG_KDF1_SP800_108 ALG_YES +#endif +#ifndef ALG_KDF1_SP800_56A +# define ALG_KDF1_SP800_56A (ALG_YES && ALG_ECC) +#endif +#ifndef ALG_KDF2 +# define ALG_KDF2 ALG_YES +#endif +#ifndef ALG_KEYEDHASH +# define ALG_KEYEDHASH ALG_YES +#endif +#ifndef ALG_MGF1 +# define ALG_MGF1 ALG_YES +#endif +#ifndef ALG_OAEP +# define ALG_OAEP (ALG_YES && ALG_RSA) +#endif +#ifndef ALG_OFB +# define ALG_OFB ALG_YES +#endif +#ifndef ALG_RSA +# define ALG_RSA ALG_YES +#endif +#ifndef ALG_RSAES +# define ALG_RSAES (ALG_YES && ALG_RSA) +#endif +#ifndef ALG_RSAPSS +# define ALG_RSAPSS (ALG_YES && ALG_RSA) +#endif +#ifndef ALG_RSASSA +# define ALG_RSASSA (ALG_YES && ALG_RSA) +#endif +#ifndef ALG_SHA +# define ALG_SHA ALG_NO /* Not specified by vendor */ +#endif +#ifndef ALG_SHA1 +# define ALG_SHA1 ALG_YES +#endif +#ifndef ALG_SHA256 +# define ALG_SHA256 ALG_YES +#endif +#ifndef ALG_SHA384 +# define ALG_SHA384 ALG_YES +#endif +#ifndef ALG_SHA3_256 +# define ALG_SHA3_256 ALG_NO /* Not specified by vendor */ +#endif +#ifndef ALG_SHA3_384 +# define ALG_SHA3_384 ALG_NO /* Not specified by vendor */ +#endif +#ifndef ALG_SHA3_512 +# define ALG_SHA3_512 ALG_NO /* Not specified by vendor */ +#endif +#ifndef ALG_SHA512 +# define ALG_SHA512 ALG_NO +#endif +#ifndef ALG_SM2 +# define ALG_SM2 (ALG_NO && ALG_ECC) +#endif +#ifndef ALG_SM3_256 +# define ALG_SM3_256 ALG_NO +#endif +#ifndef ALG_SM4 +# define ALG_SM4 ALG_NO +#endif +#ifndef ALG_SYMCIPHER +# define ALG_SYMCIPHER ALG_YES +#endif +#ifndef ALG_TDES +# define ALG_TDES ALG_NO +#endif +#ifndef ALG_XOR +# define ALG_XOR ALG_YES +#endif + +// Table 1:3 - Defines for RSA Asymmetric Cipher Algorithm Constants +#ifndef RSA_1024 +# define RSA_1024 (ALG_RSA && YES) +#endif +#ifndef RSA_2048 +# define RSA_2048 (ALG_RSA && YES) +#endif +#ifndef RSA_3072 +# define RSA_3072 (ALG_RSA && NO) +#endif +#ifndef RSA_4096 +# define RSA_4096 (ALG_RSA && NO) +#endif +#ifndef RSA_16384 +# define RSA_16384 (ALG_RSA && NO) +#endif + +// Table 1:21 - Defines for AES Symmetric Cipher Algorithm Constants +#ifndef AES_128 +# define AES_128 (ALG_AES && YES) +#endif +#ifndef AES_192 +# define AES_192 (ALG_AES && NO) +#endif +#ifndef AES_256 +# define AES_256 (ALG_AES && YES) +#endif + +// Table 1:22 - Defines for SM4 Symmetric Cipher Algorithm Constants +#ifndef SM4_128 +# define SM4_128 (ALG_SM4 && YES) +#endif + +// Table 1:23 - Defines for CAMELLIA Symmetric Cipher Algorithm Constants +#ifndef CAMELLIA_128 +# define CAMELLIA_128 (ALG_CAMELLIA && YES) +#endif +#ifndef CAMELLIA_192 +# define CAMELLIA_192 (ALG_CAMELLIA && NO) +#endif +#ifndef CAMELLIA_256 +# define CAMELLIA_256 (ALG_CAMELLIA && YES) +#endif + +// Table 1:24 - Defines for TDES Symmetric Cipher Algorithm Constants +#ifndef TDES_128 +# define TDES_128 (ALG_TDES && YES) +#endif +#ifndef TDES_192 +# define TDES_192 (ALG_TDES && YES) +#endif + +// Table 0:5 - Defines for Implemented Commands +#ifndef CC_ACT_SetTimeout +# define CC_ACT_SetTimeout CC_YES +#endif +#ifndef CC_AC_GetCapability +# define CC_AC_GetCapability CC_YES +#endif +#ifndef CC_AC_Send +# define CC_AC_Send CC_YES +#endif +#ifndef CC_ActivateCredential +# define CC_ActivateCredential CC_YES +#endif +#ifndef CC_Certify +# define CC_Certify CC_YES +#endif +#ifndef CC_CertifyCreation +# define CC_CertifyCreation CC_YES +#endif +#ifndef CC_CertifyX509 +# define CC_CertifyX509 CC_YES +#endif +#ifndef CC_ChangeEPS +# define CC_ChangeEPS CC_YES +#endif +#ifndef CC_ChangePPS +# define CC_ChangePPS CC_YES +#endif +#ifndef CC_Clear +# define CC_Clear CC_YES +#endif +#ifndef CC_ClearControl +# define CC_ClearControl CC_YES +#endif +#ifndef CC_ClockRateAdjust +# define CC_ClockRateAdjust CC_YES +#endif +#ifndef CC_ClockSet +# define CC_ClockSet CC_YES +#endif +#ifndef CC_Commit +# define CC_Commit (CC_YES && ALG_ECC) +#endif +#ifndef CC_ContextLoad +# define CC_ContextLoad CC_YES +#endif +#ifndef CC_ContextSave +# define CC_ContextSave CC_YES +#endif +#ifndef CC_Create +# define CC_Create CC_YES +#endif +#ifndef CC_CreateLoaded +# define CC_CreateLoaded CC_YES +#endif +#ifndef CC_CreatePrimary +# define CC_CreatePrimary CC_YES +#endif +#ifndef CC_DictionaryAttackLockReset +# define CC_DictionaryAttackLockReset CC_YES +#endif +#ifndef CC_DictionaryAttackParameters +# define CC_DictionaryAttackParameters CC_YES +#endif +#ifndef CC_Duplicate +# define CC_Duplicate CC_YES +#endif +#ifndef CC_ECC_Decrypt +# define CC_ECC_Decrypt (CC_YES && ALG_ECC) +#endif +#ifndef CC_ECC_Encrypt +# define CC_ECC_Encrypt (CC_YES && ALG_ECC) +#endif +#ifndef CC_ECC_Parameters +# define CC_ECC_Parameters (CC_YES && ALG_ECC) +#endif +#ifndef CC_ECDH_KeyGen +# define CC_ECDH_KeyGen (CC_YES && ALG_ECC) +#endif +#ifndef CC_ECDH_ZGen +# define CC_ECDH_ZGen (CC_YES && ALG_ECC) +#endif +#ifndef CC_EC_Ephemeral +# define CC_EC_Ephemeral (CC_YES && ALG_ECC) +#endif +#ifndef CC_EncryptDecrypt +# define CC_EncryptDecrypt CC_YES +#endif +#ifndef CC_EncryptDecrypt2 +# define CC_EncryptDecrypt2 CC_YES +#endif +#ifndef CC_EventSequenceComplete +# define CC_EventSequenceComplete CC_YES +#endif +#ifndef CC_EvictControl +# define CC_EvictControl CC_YES +#endif +#ifndef CC_FieldUpgradeData +# define CC_FieldUpgradeData CC_NO +#endif +#ifndef CC_FieldUpgradeStart +# define CC_FieldUpgradeStart CC_NO +#endif +#ifndef CC_FirmwareRead +# define CC_FirmwareRead CC_NO +#endif +#ifndef CC_FlushContext +# define CC_FlushContext CC_YES +#endif +#ifndef CC_GetCapability +# define CC_GetCapability CC_YES +#endif +#ifndef CC_GetCommandAuditDigest +# define CC_GetCommandAuditDigest CC_YES +#endif +#ifndef CC_GetRandom +# define CC_GetRandom CC_YES +#endif +#ifndef CC_GetSessionAuditDigest +# define CC_GetSessionAuditDigest CC_YES +#endif +#ifndef CC_GetTestResult +# define CC_GetTestResult CC_YES +#endif +#ifndef CC_GetTime +# define CC_GetTime CC_YES +#endif +#ifndef CC_HMAC +# define CC_HMAC (CC_YES && !ALG_CMAC) +#endif +#ifndef CC_HMAC_Start +# define CC_HMAC_Start (CC_YES && !ALG_CMAC) +#endif +#ifndef CC_Hash +# define CC_Hash CC_YES +#endif +#ifndef CC_HashSequenceStart +# define CC_HashSequenceStart CC_YES +#endif +#ifndef CC_HierarchyChangeAuth +# define CC_HierarchyChangeAuth CC_YES +#endif +#ifndef CC_HierarchyControl +# define CC_HierarchyControl CC_YES +#endif +#ifndef CC_Import +# define CC_Import CC_YES +#endif +#ifndef CC_IncrementalSelfTest +# define CC_IncrementalSelfTest CC_YES +#endif +#ifndef CC_Load +# define CC_Load CC_YES +#endif +#ifndef CC_LoadExternal +# define CC_LoadExternal CC_YES +#endif +#ifndef CC_MAC +# define CC_MAC (CC_YES && ALG_CMAC) +#endif +#ifndef CC_MAC_Start +# define CC_MAC_Start (CC_YES && ALG_CMAC) +#endif +#ifndef CC_MakeCredential +# define CC_MakeCredential CC_YES +#endif +#ifndef CC_NV_Certify +# define CC_NV_Certify CC_YES +#endif +#ifndef CC_NV_ChangeAuth +# define CC_NV_ChangeAuth CC_YES +#endif +#ifndef CC_NV_DefineSpace +# define CC_NV_DefineSpace CC_YES +#endif +#ifndef CC_NV_Extend +# define CC_NV_Extend CC_YES +#endif +#ifndef CC_NV_GlobalWriteLock +# define CC_NV_GlobalWriteLock CC_YES +#endif +#ifndef CC_NV_Increment +# define CC_NV_Increment CC_YES +#endif +#ifndef CC_NV_Read +# define CC_NV_Read CC_YES +#endif +#ifndef CC_NV_ReadLock +# define CC_NV_ReadLock CC_YES +#endif +#ifndef CC_NV_ReadPublic +# define CC_NV_ReadPublic CC_YES +#endif +#ifndef CC_NV_SetBits +# define CC_NV_SetBits CC_YES +#endif +#ifndef CC_NV_UndefineSpace +# define CC_NV_UndefineSpace CC_YES +#endif +#ifndef CC_NV_UndefineSpaceSpecial +# define CC_NV_UndefineSpaceSpecial CC_YES +#endif +#ifndef CC_NV_Write +# define CC_NV_Write CC_YES +#endif +#ifndef CC_NV_WriteLock +# define CC_NV_WriteLock CC_YES +#endif +#ifndef CC_ObjectChangeAuth +# define CC_ObjectChangeAuth CC_YES +#endif +#ifndef CC_PCR_Allocate +# define CC_PCR_Allocate CC_YES +#endif +#ifndef CC_PCR_Event +# define CC_PCR_Event CC_YES +#endif +#ifndef CC_PCR_Extend +# define CC_PCR_Extend CC_YES +#endif +#ifndef CC_PCR_Read +# define CC_PCR_Read CC_YES +#endif +#ifndef CC_PCR_Reset +# define CC_PCR_Reset CC_YES +#endif +#ifndef CC_PCR_SetAuthPolicy +# define CC_PCR_SetAuthPolicy CC_YES +#endif +#ifndef CC_PCR_SetAuthValue +# define CC_PCR_SetAuthValue CC_YES +#endif +#ifndef CC_PP_Commands +# define CC_PP_Commands CC_YES +#endif +#ifndef CC_PolicyAuthValue +# define CC_PolicyAuthValue CC_YES +#endif +#ifndef CC_PolicyAuthorize +# define CC_PolicyAuthorize CC_YES +#endif +#ifndef CC_PolicyAuthorizeNV +# define CC_PolicyAuthorizeNV CC_YES +#endif +#ifndef CC_PolicyCommandCode +# define CC_PolicyCommandCode CC_YES +#endif +#ifndef CC_PolicyCounterTimer +# define CC_PolicyCounterTimer CC_YES +#endif +#ifndef CC_PolicyCpHash +# define CC_PolicyCpHash CC_YES +#endif +#ifndef CC_PolicyDuplicationSelect +# define CC_PolicyDuplicationSelect CC_YES +#endif +#ifndef CC_PolicyGetDigest +# define CC_PolicyGetDigest CC_YES +#endif +#ifndef CC_PolicyLocality +# define CC_PolicyLocality CC_YES +#endif +#ifndef CC_PolicyNV +# define CC_PolicyNV CC_YES +#endif +#ifndef CC_PolicyNameHash +# define CC_PolicyNameHash CC_YES +#endif +#ifndef CC_PolicyNvWritten +# define CC_PolicyNvWritten CC_YES +#endif +#ifndef CC_PolicyOR +# define CC_PolicyOR CC_YES +#endif +#ifndef CC_PolicyPCR +# define CC_PolicyPCR CC_YES +#endif +#ifndef CC_PolicyPassword +# define CC_PolicyPassword CC_YES +#endif +#ifndef CC_PolicyPhysicalPresence +# define CC_PolicyPhysicalPresence CC_YES +#endif +#ifndef CC_PolicyRestart +# define CC_PolicyRestart CC_YES +#endif +#ifndef CC_PolicySecret +# define CC_PolicySecret CC_YES +#endif +#ifndef CC_PolicySigned +# define CC_PolicySigned CC_YES +#endif +#ifndef CC_PolicyTemplate +# define CC_PolicyTemplate CC_YES +#endif +#ifndef CC_PolicyTicket +# define CC_PolicyTicket CC_YES +#endif +#ifndef CC_Policy_AC_SendSelect +# define CC_Policy_AC_SendSelect CC_YES +#endif +#ifndef CC_Quote +# define CC_Quote CC_YES +#endif +#ifndef CC_RSA_Decrypt +# define CC_RSA_Decrypt (CC_YES && ALG_RSA) +#endif +#ifndef CC_RSA_Encrypt +# define CC_RSA_Encrypt (CC_YES && ALG_RSA) +#endif +#ifndef CC_ReadClock +# define CC_ReadClock CC_YES +#endif +#ifndef CC_ReadPublic +# define CC_ReadPublic CC_YES +#endif +#ifndef CC_Rewrap +# define CC_Rewrap CC_YES +#endif +#ifndef CC_SelfTest +# define CC_SelfTest CC_YES +#endif +#ifndef CC_SequenceComplete +# define CC_SequenceComplete CC_YES +#endif +#ifndef CC_SequenceUpdate +# define CC_SequenceUpdate CC_YES +#endif +#ifndef CC_SetAlgorithmSet +# define CC_SetAlgorithmSet CC_YES +#endif +#ifndef CC_SetCommandCodeAuditStatus +# define CC_SetCommandCodeAuditStatus CC_YES +#endif +#ifndef CC_SetPrimaryPolicy +# define CC_SetPrimaryPolicy CC_YES +#endif +#ifndef CC_Shutdown +# define CC_Shutdown CC_YES +#endif +#ifndef CC_Sign +# define CC_Sign CC_YES +#endif +#ifndef CC_StartAuthSession +# define CC_StartAuthSession CC_YES +#endif +#ifndef CC_Startup +# define CC_Startup CC_YES +#endif +#ifndef CC_StirRandom +# define CC_StirRandom CC_YES +#endif +#ifndef CC_TestParms +# define CC_TestParms CC_YES +#endif +#ifndef CC_Unseal +# define CC_Unseal CC_YES +#endif +#ifndef CC_Vendor_TCG_Test +# define CC_Vendor_TCG_Test CC_YES +#endif +#ifndef CC_VerifySignature +# define CC_VerifySignature CC_YES +#endif +#ifndef CC_ZGen_2Phase +# define CC_ZGen_2Phase (CC_YES && ALG_ECC) +#endif + +#endif // _TPM_PROFILE_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TpmTypes.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TpmTypes.h new file mode 100644 index 0000000..378e628 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/TpmTypes.h @@ -0,0 +1,2724 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 6, 2020 Time: 01:50:09PM + */ + +#ifndef _TPM_TYPES_H_ +#define _TPM_TYPES_H_ + +// Table 1:2 - Definition of TPM_ALG_ID Constants +typedef UINT16 TPM_ALG_ID; +#define TYPE_OF_TPM_ALG_ID UINT16 +#define ALG_ERROR_VALUE 0x0000 +#define TPM_ALG_ERROR (TPM_ALG_ID)(ALG_ERROR_VALUE) +#define ALG_RSA_VALUE 0x0001 +#define TPM_ALG_RSA (TPM_ALG_ID)(ALG_RSA_VALUE) +#define ALG_TDES_VALUE 0x0003 +#define TPM_ALG_TDES (TPM_ALG_ID)(ALG_TDES_VALUE) +#define ALG_SHA_VALUE 0x0004 +#define TPM_ALG_SHA (TPM_ALG_ID)(ALG_SHA_VALUE) +#define ALG_SHA1_VALUE 0x0004 +#define TPM_ALG_SHA1 (TPM_ALG_ID)(ALG_SHA1_VALUE) +#define ALG_HMAC_VALUE 0x0005 +#define TPM_ALG_HMAC (TPM_ALG_ID)(ALG_HMAC_VALUE) +#define ALG_AES_VALUE 0x0006 +#define TPM_ALG_AES (TPM_ALG_ID)(ALG_AES_VALUE) +#define ALG_MGF1_VALUE 0x0007 +#define TPM_ALG_MGF1 (TPM_ALG_ID)(ALG_MGF1_VALUE) +#define ALG_KEYEDHASH_VALUE 0x0008 +#define TPM_ALG_KEYEDHASH (TPM_ALG_ID)(ALG_KEYEDHASH_VALUE) +#define ALG_XOR_VALUE 0x000A +#define TPM_ALG_XOR (TPM_ALG_ID)(ALG_XOR_VALUE) +#define ALG_SHA256_VALUE 0x000B +#define TPM_ALG_SHA256 (TPM_ALG_ID)(ALG_SHA256_VALUE) +#define ALG_SHA384_VALUE 0x000C +#define TPM_ALG_SHA384 (TPM_ALG_ID)(ALG_SHA384_VALUE) +#define ALG_SHA512_VALUE 0x000D +#define TPM_ALG_SHA512 (TPM_ALG_ID)(ALG_SHA512_VALUE) +#define ALG_NULL_VALUE 0x0010 +#define TPM_ALG_NULL (TPM_ALG_ID)(ALG_NULL_VALUE) +#define ALG_SM3_256_VALUE 0x0012 +#define TPM_ALG_SM3_256 (TPM_ALG_ID)(ALG_SM3_256_VALUE) +#define ALG_SM4_VALUE 0x0013 +#define TPM_ALG_SM4 (TPM_ALG_ID)(ALG_SM4_VALUE) +#define ALG_RSASSA_VALUE 0x0014 +#define TPM_ALG_RSASSA (TPM_ALG_ID)(ALG_RSASSA_VALUE) +#define ALG_RSAES_VALUE 0x0015 +#define TPM_ALG_RSAES (TPM_ALG_ID)(ALG_RSAES_VALUE) +#define ALG_RSAPSS_VALUE 0x0016 +#define TPM_ALG_RSAPSS (TPM_ALG_ID)(ALG_RSAPSS_VALUE) +#define ALG_OAEP_VALUE 0x0017 +#define TPM_ALG_OAEP (TPM_ALG_ID)(ALG_OAEP_VALUE) +#define ALG_ECDSA_VALUE 0x0018 +#define TPM_ALG_ECDSA (TPM_ALG_ID)(ALG_ECDSA_VALUE) +#define ALG_ECDH_VALUE 0x0019 +#define TPM_ALG_ECDH (TPM_ALG_ID)(ALG_ECDH_VALUE) +#define ALG_ECDAA_VALUE 0x001A +#define TPM_ALG_ECDAA (TPM_ALG_ID)(ALG_ECDAA_VALUE) +#define ALG_SM2_VALUE 0x001B +#define TPM_ALG_SM2 (TPM_ALG_ID)(ALG_SM2_VALUE) +#define ALG_ECSCHNORR_VALUE 0x001C +#define TPM_ALG_ECSCHNORR (TPM_ALG_ID)(ALG_ECSCHNORR_VALUE) +#define ALG_ECMQV_VALUE 0x001D +#define TPM_ALG_ECMQV (TPM_ALG_ID)(ALG_ECMQV_VALUE) +#define ALG_KDF1_SP800_56A_VALUE 0x0020 +#define TPM_ALG_KDF1_SP800_56A (TPM_ALG_ID)(ALG_KDF1_SP800_56A_VALUE) +#define ALG_KDF2_VALUE 0x0021 +#define TPM_ALG_KDF2 (TPM_ALG_ID)(ALG_KDF2_VALUE) +#define ALG_KDF1_SP800_108_VALUE 0x0022 +#define TPM_ALG_KDF1_SP800_108 (TPM_ALG_ID)(ALG_KDF1_SP800_108_VALUE) +#define ALG_ECC_VALUE 0x0023 +#define TPM_ALG_ECC (TPM_ALG_ID)(ALG_ECC_VALUE) +#define ALG_SYMCIPHER_VALUE 0x0025 +#define TPM_ALG_SYMCIPHER (TPM_ALG_ID)(ALG_SYMCIPHER_VALUE) +#define ALG_CAMELLIA_VALUE 0x0026 +#define TPM_ALG_CAMELLIA (TPM_ALG_ID)(ALG_CAMELLIA_VALUE) +#define ALG_SHA3_256_VALUE 0x0027 +#define TPM_ALG_SHA3_256 (TPM_ALG_ID)(ALG_SHA3_256_VALUE) +#define ALG_SHA3_384_VALUE 0x0028 +#define TPM_ALG_SHA3_384 (TPM_ALG_ID)(ALG_SHA3_384_VALUE) +#define ALG_SHA3_512_VALUE 0x0029 +#define TPM_ALG_SHA3_512 (TPM_ALG_ID)(ALG_SHA3_512_VALUE) +#define ALG_CMAC_VALUE 0x003F +#define TPM_ALG_CMAC (TPM_ALG_ID)(ALG_CMAC_VALUE) +#define ALG_CTR_VALUE 0x0040 +#define TPM_ALG_CTR (TPM_ALG_ID)(ALG_CTR_VALUE) +#define ALG_OFB_VALUE 0x0041 +#define TPM_ALG_OFB (TPM_ALG_ID)(ALG_OFB_VALUE) +#define ALG_CBC_VALUE 0x0042 +#define TPM_ALG_CBC (TPM_ALG_ID)(ALG_CBC_VALUE) +#define ALG_CFB_VALUE 0x0043 +#define TPM_ALG_CFB (TPM_ALG_ID)(ALG_CFB_VALUE) +#define ALG_ECB_VALUE 0x0044 +#define TPM_ALG_ECB (TPM_ALG_ID)(ALG_ECB_VALUE) +// Values derived from Table 1:2 +#define ALG_FIRST_VALUE 0x0001 +#define TPM_ALG_FIRST (TPM_ALG_ID)(ALG_FIRST_VALUE) +#define ALG_LAST_VALUE 0x0044 +#define TPM_ALG_LAST (TPM_ALG_ID)(ALG_LAST_VALUE) + +// Table 1:4 - Definition of TPM_ECC_CURVE Constants +typedef UINT16 TPM_ECC_CURVE; +#define TYPE_OF_TPM_ECC_CURVE UINT16 +#define TPM_ECC_NONE (TPM_ECC_CURVE)(0x0000) +#define TPM_ECC_NIST_P192 (TPM_ECC_CURVE)(0x0001) +#define TPM_ECC_NIST_P224 (TPM_ECC_CURVE)(0x0002) +#define TPM_ECC_NIST_P256 (TPM_ECC_CURVE)(0x0003) +#define TPM_ECC_NIST_P384 (TPM_ECC_CURVE)(0x0004) +#define TPM_ECC_NIST_P521 (TPM_ECC_CURVE)(0x0005) +#define TPM_ECC_BN_P256 (TPM_ECC_CURVE)(0x0010) +#define TPM_ECC_BN_P638 (TPM_ECC_CURVE)(0x0011) +#define TPM_ECC_SM2_P256 (TPM_ECC_CURVE)(0x0020) + +// Table 2:12 - Definition of TPM_CC Constants +typedef UINT32 TPM_CC; +#define TYPE_OF_TPM_CC UINT32 +#define TPM_CC_NV_UndefineSpaceSpecial (TPM_CC)(0x0000011F) +#define TPM_CC_EvictControl (TPM_CC)(0x00000120) +#define TPM_CC_HierarchyControl (TPM_CC)(0x00000121) +#define TPM_CC_NV_UndefineSpace (TPM_CC)(0x00000122) +#define TPM_CC_ChangeEPS (TPM_CC)(0x00000124) +#define TPM_CC_ChangePPS (TPM_CC)(0x00000125) +#define TPM_CC_Clear (TPM_CC)(0x00000126) +#define TPM_CC_ClearControl (TPM_CC)(0x00000127) +#define TPM_CC_ClockSet (TPM_CC)(0x00000128) +#define TPM_CC_HierarchyChangeAuth (TPM_CC)(0x00000129) +#define TPM_CC_NV_DefineSpace (TPM_CC)(0x0000012A) +#define TPM_CC_PCR_Allocate (TPM_CC)(0x0000012B) +#define TPM_CC_PCR_SetAuthPolicy (TPM_CC)(0x0000012C) +#define TPM_CC_PP_Commands (TPM_CC)(0x0000012D) +#define TPM_CC_SetPrimaryPolicy (TPM_CC)(0x0000012E) +#define TPM_CC_FieldUpgradeStart (TPM_CC)(0x0000012F) +#define TPM_CC_ClockRateAdjust (TPM_CC)(0x00000130) +#define TPM_CC_CreatePrimary (TPM_CC)(0x00000131) +#define TPM_CC_NV_GlobalWriteLock (TPM_CC)(0x00000132) +#define TPM_CC_GetCommandAuditDigest (TPM_CC)(0x00000133) +#define TPM_CC_NV_Increment (TPM_CC)(0x00000134) +#define TPM_CC_NV_SetBits (TPM_CC)(0x00000135) +#define TPM_CC_NV_Extend (TPM_CC)(0x00000136) +#define TPM_CC_NV_Write (TPM_CC)(0x00000137) +#define TPM_CC_NV_WriteLock (TPM_CC)(0x00000138) +#define TPM_CC_DictionaryAttackLockReset (TPM_CC)(0x00000139) +#define TPM_CC_DictionaryAttackParameters (TPM_CC)(0x0000013A) +#define TPM_CC_NV_ChangeAuth (TPM_CC)(0x0000013B) +#define TPM_CC_PCR_Event (TPM_CC)(0x0000013C) +#define TPM_CC_PCR_Reset (TPM_CC)(0x0000013D) +#define TPM_CC_SequenceComplete (TPM_CC)(0x0000013E) +#define TPM_CC_SetAlgorithmSet (TPM_CC)(0x0000013F) +#define TPM_CC_SetCommandCodeAuditStatus (TPM_CC)(0x00000140) +#define TPM_CC_FieldUpgradeData (TPM_CC)(0x00000141) +#define TPM_CC_IncrementalSelfTest (TPM_CC)(0x00000142) +#define TPM_CC_SelfTest (TPM_CC)(0x00000143) +#define TPM_CC_Startup (TPM_CC)(0x00000144) +#define TPM_CC_Shutdown (TPM_CC)(0x00000145) +#define TPM_CC_StirRandom (TPM_CC)(0x00000146) +#define TPM_CC_ActivateCredential (TPM_CC)(0x00000147) +#define TPM_CC_Certify (TPM_CC)(0x00000148) +#define TPM_CC_PolicyNV (TPM_CC)(0x00000149) +#define TPM_CC_CertifyCreation (TPM_CC)(0x0000014A) +#define TPM_CC_Duplicate (TPM_CC)(0x0000014B) +#define TPM_CC_GetTime (TPM_CC)(0x0000014C) +#define TPM_CC_GetSessionAuditDigest (TPM_CC)(0x0000014D) +#define TPM_CC_NV_Read (TPM_CC)(0x0000014E) +#define TPM_CC_NV_ReadLock (TPM_CC)(0x0000014F) +#define TPM_CC_ObjectChangeAuth (TPM_CC)(0x00000150) +#define TPM_CC_PolicySecret (TPM_CC)(0x00000151) +#define TPM_CC_Rewrap (TPM_CC)(0x00000152) +#define TPM_CC_Create (TPM_CC)(0x00000153) +#define TPM_CC_ECDH_ZGen (TPM_CC)(0x00000154) +#define TPM_CC_HMAC (TPM_CC)(0x00000155) +#define TPM_CC_MAC (TPM_CC)(0x00000155) +#define TPM_CC_Import (TPM_CC)(0x00000156) +#define TPM_CC_Load (TPM_CC)(0x00000157) +#define TPM_CC_Quote (TPM_CC)(0x00000158) +#define TPM_CC_RSA_Decrypt (TPM_CC)(0x00000159) +#define TPM_CC_HMAC_Start (TPM_CC)(0x0000015B) +#define TPM_CC_MAC_Start (TPM_CC)(0x0000015B) +#define TPM_CC_SequenceUpdate (TPM_CC)(0x0000015C) +#define TPM_CC_Sign (TPM_CC)(0x0000015D) +#define TPM_CC_Unseal (TPM_CC)(0x0000015E) +#define TPM_CC_PolicySigned (TPM_CC)(0x00000160) +#define TPM_CC_ContextLoad (TPM_CC)(0x00000161) +#define TPM_CC_ContextSave (TPM_CC)(0x00000162) +#define TPM_CC_ECDH_KeyGen (TPM_CC)(0x00000163) +#define TPM_CC_EncryptDecrypt (TPM_CC)(0x00000164) +#define TPM_CC_FlushContext (TPM_CC)(0x00000165) +#define TPM_CC_LoadExternal (TPM_CC)(0x00000167) +#define TPM_CC_MakeCredential (TPM_CC)(0x00000168) +#define TPM_CC_NV_ReadPublic (TPM_CC)(0x00000169) +#define TPM_CC_PolicyAuthorize (TPM_CC)(0x0000016A) +#define TPM_CC_PolicyAuthValue (TPM_CC)(0x0000016B) +#define TPM_CC_PolicyCommandCode (TPM_CC)(0x0000016C) +#define TPM_CC_PolicyCounterTimer (TPM_CC)(0x0000016D) +#define TPM_CC_PolicyCpHash (TPM_CC)(0x0000016E) +#define TPM_CC_PolicyLocality (TPM_CC)(0x0000016F) +#define TPM_CC_PolicyNameHash (TPM_CC)(0x00000170) +#define TPM_CC_PolicyOR (TPM_CC)(0x00000171) +#define TPM_CC_PolicyTicket (TPM_CC)(0x00000172) +#define TPM_CC_ReadPublic (TPM_CC)(0x00000173) +#define TPM_CC_RSA_Encrypt (TPM_CC)(0x00000174) +#define TPM_CC_StartAuthSession (TPM_CC)(0x00000176) +#define TPM_CC_VerifySignature (TPM_CC)(0x00000177) +#define TPM_CC_ECC_Parameters (TPM_CC)(0x00000178) +#define TPM_CC_FirmwareRead (TPM_CC)(0x00000179) +#define TPM_CC_GetCapability (TPM_CC)(0x0000017A) +#define TPM_CC_GetRandom (TPM_CC)(0x0000017B) +#define TPM_CC_GetTestResult (TPM_CC)(0x0000017C) +#define TPM_CC_Hash (TPM_CC)(0x0000017D) +#define TPM_CC_PCR_Read (TPM_CC)(0x0000017E) +#define TPM_CC_PolicyPCR (TPM_CC)(0x0000017F) +#define TPM_CC_PolicyRestart (TPM_CC)(0x00000180) +#define TPM_CC_ReadClock (TPM_CC)(0x00000181) +#define TPM_CC_PCR_Extend (TPM_CC)(0x00000182) +#define TPM_CC_PCR_SetAuthValue (TPM_CC)(0x00000183) +#define TPM_CC_NV_Certify (TPM_CC)(0x00000184) +#define TPM_CC_EventSequenceComplete (TPM_CC)(0x00000185) +#define TPM_CC_HashSequenceStart (TPM_CC)(0x00000186) +#define TPM_CC_PolicyPhysicalPresence (TPM_CC)(0x00000187) +#define TPM_CC_PolicyDuplicationSelect (TPM_CC)(0x00000188) +#define TPM_CC_PolicyGetDigest (TPM_CC)(0x00000189) +#define TPM_CC_TestParms (TPM_CC)(0x0000018A) +#define TPM_CC_Commit (TPM_CC)(0x0000018B) +#define TPM_CC_PolicyPassword (TPM_CC)(0x0000018C) +#define TPM_CC_ZGen_2Phase (TPM_CC)(0x0000018D) +#define TPM_CC_EC_Ephemeral (TPM_CC)(0x0000018E) +#define TPM_CC_PolicyNvWritten (TPM_CC)(0x0000018F) +#define TPM_CC_PolicyTemplate (TPM_CC)(0x00000190) +#define TPM_CC_CreateLoaded (TPM_CC)(0x00000191) +#define TPM_CC_PolicyAuthorizeNV (TPM_CC)(0x00000192) +#define TPM_CC_EncryptDecrypt2 (TPM_CC)(0x00000193) +#define TPM_CC_AC_GetCapability (TPM_CC)(0x00000194) +#define TPM_CC_AC_Send (TPM_CC)(0x00000195) +#define TPM_CC_Policy_AC_SendSelect (TPM_CC)(0x00000196) +#define TPM_CC_CertifyX509 (TPM_CC)(0x00000197) +#define TPM_CC_ACT_SetTimeout (TPM_CC)(0x00000198) +#define TPM_CC_ECC_Encrypt (TPM_CC)(0x00000199) +#define TPM_CC_ECC_Decrypt (TPM_CC)(0x0000019A) +#define CC_VEND 0x20000000 +#define TPM_CC_Vendor_TCG_Test (TPM_CC)(0x20000000) + +// Table 2:5 - Definition of Types for Documentation Clarity +typedef UINT32 TPM_ALGORITHM_ID; +#define TYPE_OF_TPM_ALGORITHM_ID UINT32 +typedef UINT32 TPM_MODIFIER_INDICATOR; +#define TYPE_OF_TPM_MODIFIER_INDICATOR UINT32 +typedef UINT32 TPM_AUTHORIZATION_SIZE; +#define TYPE_OF_TPM_AUTHORIZATION_SIZE UINT32 +typedef UINT32 TPM_PARAMETER_SIZE; +#define TYPE_OF_TPM_PARAMETER_SIZE UINT32 +typedef UINT16 TPM_KEY_SIZE; +#define TYPE_OF_TPM_KEY_SIZE UINT16 +typedef UINT16 TPM_KEY_BITS; +#define TYPE_OF_TPM_KEY_BITS UINT16 + +// Table 2:6 - Definition of TPM_SPEC Constants +typedef UINT32 TPM_SPEC; +#define TYPE_OF_TPM_SPEC UINT32 +#define SPEC_FAMILY 0x322E3000 +#define TPM_SPEC_FAMILY (TPM_SPEC)(SPEC_FAMILY) +#define SPEC_LEVEL 00 +#define TPM_SPEC_LEVEL (TPM_SPEC)(SPEC_LEVEL) +#define SPEC_VERSION 162 +#define TPM_SPEC_VERSION (TPM_SPEC)(SPEC_VERSION) +#define SPEC_YEAR 2020 +#define TPM_SPEC_YEAR (TPM_SPEC)(SPEC_YEAR) +#define SPEC_DAY_OF_YEAR 53 +#define TPM_SPEC_DAY_OF_YEAR (TPM_SPEC)(SPEC_DAY_OF_YEAR) + +// Table 2:7 - Definition of TPM_CONSTANTS32 Constants +typedef UINT32 TPM_CONSTANTS32; +#define TYPE_OF_TPM_CONSTANTS32 UINT32 +#define TPM_GENERATED_VALUE (TPM_CONSTANTS32)(0xFF544347) +#define TPM_MAX_DERIVATION_BITS (TPM_CONSTANTS32)(8192) + +// Table 2:16 - Definition of TPM_RC Constants +typedef UINT32 TPM_RC; +#define TYPE_OF_TPM_RC UINT32 +#define TPM_RC_SUCCESS (TPM_RC)(0x000) +#define TPM_RC_BAD_TAG (TPM_RC)(0x01E) +#define RC_VER1 (TPM_RC)(0x100) +#define TPM_RC_INITIALIZE (TPM_RC)(RC_VER1 + 0x000) +#define TPM_RC_FAILURE (TPM_RC)(RC_VER1 + 0x001) +#define TPM_RC_SEQUENCE (TPM_RC)(RC_VER1 + 0x003) +#define TPM_RC_PRIVATE (TPM_RC)(RC_VER1 + 0x00B) +#define TPM_RC_HMAC (TPM_RC)(RC_VER1 + 0x019) +#define TPM_RC_DISABLED (TPM_RC)(RC_VER1 + 0x020) +#define TPM_RC_EXCLUSIVE (TPM_RC)(RC_VER1 + 0x021) +#define TPM_RC_AUTH_TYPE (TPM_RC)(RC_VER1 + 0x024) +#define TPM_RC_AUTH_MISSING (TPM_RC)(RC_VER1 + 0x025) +#define TPM_RC_POLICY (TPM_RC)(RC_VER1 + 0x026) +#define TPM_RC_PCR (TPM_RC)(RC_VER1 + 0x027) +#define TPM_RC_PCR_CHANGED (TPM_RC)(RC_VER1 + 0x028) +#define TPM_RC_UPGRADE (TPM_RC)(RC_VER1 + 0x02D) +#define TPM_RC_TOO_MANY_CONTEXTS (TPM_RC)(RC_VER1 + 0x02E) +#define TPM_RC_AUTH_UNAVAILABLE (TPM_RC)(RC_VER1 + 0x02F) +#define TPM_RC_REBOOT (TPM_RC)(RC_VER1 + 0x030) +#define TPM_RC_UNBALANCED (TPM_RC)(RC_VER1 + 0x031) +#define TPM_RC_COMMAND_SIZE (TPM_RC)(RC_VER1 + 0x042) +#define TPM_RC_COMMAND_CODE (TPM_RC)(RC_VER1 + 0x043) +#define TPM_RC_AUTHSIZE (TPM_RC)(RC_VER1 + 0x044) +#define TPM_RC_AUTH_CONTEXT (TPM_RC)(RC_VER1 + 0x045) +#define TPM_RC_NV_RANGE (TPM_RC)(RC_VER1 + 0x046) +#define TPM_RC_NV_SIZE (TPM_RC)(RC_VER1 + 0x047) +#define TPM_RC_NV_LOCKED (TPM_RC)(RC_VER1 + 0x048) +#define TPM_RC_NV_AUTHORIZATION (TPM_RC)(RC_VER1 + 0x049) +#define TPM_RC_NV_UNINITIALIZED (TPM_RC)(RC_VER1 + 0x04A) +#define TPM_RC_NV_SPACE (TPM_RC)(RC_VER1 + 0x04B) +#define TPM_RC_NV_DEFINED (TPM_RC)(RC_VER1 + 0x04C) +#define TPM_RC_BAD_CONTEXT (TPM_RC)(RC_VER1 + 0x050) +#define TPM_RC_CPHASH (TPM_RC)(RC_VER1 + 0x051) +#define TPM_RC_PARENT (TPM_RC)(RC_VER1 + 0x052) +#define TPM_RC_NEEDS_TEST (TPM_RC)(RC_VER1 + 0x053) +#define TPM_RC_NO_RESULT (TPM_RC)(RC_VER1 + 0x054) +#define TPM_RC_SENSITIVE (TPM_RC)(RC_VER1 + 0x055) +#define RC_MAX_FM0 (TPM_RC)(RC_VER1 + 0x07F) +#define RC_FMT1 (TPM_RC)(0x080) +#define TPM_RC_ASYMMETRIC (TPM_RC)(RC_FMT1 + 0x001) +#define TPM_RCS_ASYMMETRIC (TPM_RC)(RC_FMT1 + 0x001) +#define TPM_RC_ATTRIBUTES (TPM_RC)(RC_FMT1 + 0x002) +#define TPM_RCS_ATTRIBUTES (TPM_RC)(RC_FMT1 + 0x002) +#define TPM_RC_HASH (TPM_RC)(RC_FMT1 + 0x003) +#define TPM_RCS_HASH (TPM_RC)(RC_FMT1 + 0x003) +#define TPM_RC_VALUE (TPM_RC)(RC_FMT1 + 0x004) +#define TPM_RCS_VALUE (TPM_RC)(RC_FMT1 + 0x004) +#define TPM_RC_HIERARCHY (TPM_RC)(RC_FMT1 + 0x005) +#define TPM_RCS_HIERARCHY (TPM_RC)(RC_FMT1 + 0x005) +#define TPM_RC_KEY_SIZE (TPM_RC)(RC_FMT1 + 0x007) +#define TPM_RCS_KEY_SIZE (TPM_RC)(RC_FMT1 + 0x007) +#define TPM_RC_MGF (TPM_RC)(RC_FMT1 + 0x008) +#define TPM_RCS_MGF (TPM_RC)(RC_FMT1 + 0x008) +#define TPM_RC_MODE (TPM_RC)(RC_FMT1 + 0x009) +#define TPM_RCS_MODE (TPM_RC)(RC_FMT1 + 0x009) +#define TPM_RC_TYPE (TPM_RC)(RC_FMT1 + 0x00A) +#define TPM_RCS_TYPE (TPM_RC)(RC_FMT1 + 0x00A) +#define TPM_RC_HANDLE (TPM_RC)(RC_FMT1 + 0x00B) +#define TPM_RCS_HANDLE (TPM_RC)(RC_FMT1 + 0x00B) +#define TPM_RC_KDF (TPM_RC)(RC_FMT1 + 0x00C) +#define TPM_RCS_KDF (TPM_RC)(RC_FMT1 + 0x00C) +#define TPM_RC_RANGE (TPM_RC)(RC_FMT1 + 0x00D) +#define TPM_RCS_RANGE (TPM_RC)(RC_FMT1 + 0x00D) +#define TPM_RC_AUTH_FAIL (TPM_RC)(RC_FMT1 + 0x00E) +#define TPM_RCS_AUTH_FAIL (TPM_RC)(RC_FMT1 + 0x00E) +#define TPM_RC_NONCE (TPM_RC)(RC_FMT1 + 0x00F) +#define TPM_RCS_NONCE (TPM_RC)(RC_FMT1 + 0x00F) +#define TPM_RC_PP (TPM_RC)(RC_FMT1 + 0x010) +#define TPM_RCS_PP (TPM_RC)(RC_FMT1 + 0x010) +#define TPM_RC_SCHEME (TPM_RC)(RC_FMT1 + 0x012) +#define TPM_RCS_SCHEME (TPM_RC)(RC_FMT1 + 0x012) +#define TPM_RC_SIZE (TPM_RC)(RC_FMT1 + 0x015) +#define TPM_RCS_SIZE (TPM_RC)(RC_FMT1 + 0x015) +#define TPM_RC_SYMMETRIC (TPM_RC)(RC_FMT1 + 0x016) +#define TPM_RCS_SYMMETRIC (TPM_RC)(RC_FMT1 + 0x016) +#define TPM_RC_TAG (TPM_RC)(RC_FMT1 + 0x017) +#define TPM_RCS_TAG (TPM_RC)(RC_FMT1 + 0x017) +#define TPM_RC_SELECTOR (TPM_RC)(RC_FMT1 + 0x018) +#define TPM_RCS_SELECTOR (TPM_RC)(RC_FMT1 + 0x018) +#define TPM_RC_INSUFFICIENT (TPM_RC)(RC_FMT1 + 0x01A) +#define TPM_RCS_INSUFFICIENT (TPM_RC)(RC_FMT1 + 0x01A) +#define TPM_RC_SIGNATURE (TPM_RC)(RC_FMT1 + 0x01B) +#define TPM_RCS_SIGNATURE (TPM_RC)(RC_FMT1 + 0x01B) +#define TPM_RC_KEY (TPM_RC)(RC_FMT1 + 0x01C) +#define TPM_RCS_KEY (TPM_RC)(RC_FMT1 + 0x01C) +#define TPM_RC_POLICY_FAIL (TPM_RC)(RC_FMT1 + 0x01D) +#define TPM_RCS_POLICY_FAIL (TPM_RC)(RC_FMT1 + 0x01D) +#define TPM_RC_INTEGRITY (TPM_RC)(RC_FMT1 + 0x01F) +#define TPM_RCS_INTEGRITY (TPM_RC)(RC_FMT1 + 0x01F) +#define TPM_RC_TICKET (TPM_RC)(RC_FMT1 + 0x020) +#define TPM_RCS_TICKET (TPM_RC)(RC_FMT1 + 0x020) +#define TPM_RC_RESERVED_BITS (TPM_RC)(RC_FMT1 + 0x021) +#define TPM_RCS_RESERVED_BITS (TPM_RC)(RC_FMT1 + 0x021) +#define TPM_RC_BAD_AUTH (TPM_RC)(RC_FMT1 + 0x022) +#define TPM_RCS_BAD_AUTH (TPM_RC)(RC_FMT1 + 0x022) +#define TPM_RC_EXPIRED (TPM_RC)(RC_FMT1 + 0x023) +#define TPM_RCS_EXPIRED (TPM_RC)(RC_FMT1 + 0x023) +#define TPM_RC_POLICY_CC (TPM_RC)(RC_FMT1 + 0x024) +#define TPM_RCS_POLICY_CC (TPM_RC)(RC_FMT1 + 0x024) +#define TPM_RC_BINDING (TPM_RC)(RC_FMT1 + 0x025) +#define TPM_RCS_BINDING (TPM_RC)(RC_FMT1 + 0x025) +#define TPM_RC_CURVE (TPM_RC)(RC_FMT1 + 0x026) +#define TPM_RCS_CURVE (TPM_RC)(RC_FMT1 + 0x026) +#define TPM_RC_ECC_POINT (TPM_RC)(RC_FMT1 + 0x027) +#define TPM_RCS_ECC_POINT (TPM_RC)(RC_FMT1 + 0x027) +#define RC_WARN (TPM_RC)(0x900) +#define TPM_RC_CONTEXT_GAP (TPM_RC)(RC_WARN + 0x001) +#define TPM_RC_OBJECT_MEMORY (TPM_RC)(RC_WARN + 0x002) +#define TPM_RC_SESSION_MEMORY (TPM_RC)(RC_WARN + 0x003) +#define TPM_RC_MEMORY (TPM_RC)(RC_WARN + 0x004) +#define TPM_RC_SESSION_HANDLES (TPM_RC)(RC_WARN + 0x005) +#define TPM_RC_OBJECT_HANDLES (TPM_RC)(RC_WARN + 0x006) +#define TPM_RC_LOCALITY (TPM_RC)(RC_WARN + 0x007) +#define TPM_RC_YIELDED (TPM_RC)(RC_WARN + 0x008) +#define TPM_RC_CANCELED (TPM_RC)(RC_WARN + 0x009) +#define TPM_RC_TESTING (TPM_RC)(RC_WARN + 0x00A) +#define TPM_RC_REFERENCE_H0 (TPM_RC)(RC_WARN + 0x010) +#define TPM_RC_REFERENCE_H1 (TPM_RC)(RC_WARN + 0x011) +#define TPM_RC_REFERENCE_H2 (TPM_RC)(RC_WARN + 0x012) +#define TPM_RC_REFERENCE_H3 (TPM_RC)(RC_WARN + 0x013) +#define TPM_RC_REFERENCE_H4 (TPM_RC)(RC_WARN + 0x014) +#define TPM_RC_REFERENCE_H5 (TPM_RC)(RC_WARN + 0x015) +#define TPM_RC_REFERENCE_H6 (TPM_RC)(RC_WARN + 0x016) +#define TPM_RC_REFERENCE_S0 (TPM_RC)(RC_WARN + 0x018) +#define TPM_RC_REFERENCE_S1 (TPM_RC)(RC_WARN + 0x019) +#define TPM_RC_REFERENCE_S2 (TPM_RC)(RC_WARN + 0x01A) +#define TPM_RC_REFERENCE_S3 (TPM_RC)(RC_WARN + 0x01B) +#define TPM_RC_REFERENCE_S4 (TPM_RC)(RC_WARN + 0x01C) +#define TPM_RC_REFERENCE_S5 (TPM_RC)(RC_WARN + 0x01D) +#define TPM_RC_REFERENCE_S6 (TPM_RC)(RC_WARN + 0x01E) +#define TPM_RC_NV_RATE (TPM_RC)(RC_WARN + 0x020) +#define TPM_RC_LOCKOUT (TPM_RC)(RC_WARN + 0x021) +#define TPM_RC_RETRY (TPM_RC)(RC_WARN + 0x022) +#define TPM_RC_NV_UNAVAILABLE (TPM_RC)(RC_WARN + 0x023) +#define TPM_RC_NOT_USED (TPM_RC)(RC_WARN + 0x7F) +#define TPM_RC_H (TPM_RC)(0x000) +#define TPM_RC_P (TPM_RC)(0x040) +#define TPM_RC_S (TPM_RC)(0x800) +#define TPM_RC_1 (TPM_RC)(0x100) +#define TPM_RC_2 (TPM_RC)(0x200) +#define TPM_RC_3 (TPM_RC)(0x300) +#define TPM_RC_4 (TPM_RC)(0x400) +#define TPM_RC_5 (TPM_RC)(0x500) +#define TPM_RC_6 (TPM_RC)(0x600) +#define TPM_RC_7 (TPM_RC)(0x700) +#define TPM_RC_8 (TPM_RC)(0x800) +#define TPM_RC_9 (TPM_RC)(0x900) +#define TPM_RC_A (TPM_RC)(0xA00) +#define TPM_RC_B (TPM_RC)(0xB00) +#define TPM_RC_C (TPM_RC)(0xC00) +#define TPM_RC_D (TPM_RC)(0xD00) +#define TPM_RC_E (TPM_RC)(0xE00) +#define TPM_RC_F (TPM_RC)(0xF00) +#define TPM_RC_N_MASK (TPM_RC)(0xF00) + +// Table 2:17 - Definition of TPM_CLOCK_ADJUST Constants +typedef INT8 TPM_CLOCK_ADJUST; +#define TYPE_OF_TPM_CLOCK_ADJUST UINT8 +#define TPM_CLOCK_COARSE_SLOWER (TPM_CLOCK_ADJUST)(-3) +#define TPM_CLOCK_MEDIUM_SLOWER (TPM_CLOCK_ADJUST)(-2) +#define TPM_CLOCK_FINE_SLOWER (TPM_CLOCK_ADJUST)(-1) +#define TPM_CLOCK_NO_CHANGE (TPM_CLOCK_ADJUST)(0) +#define TPM_CLOCK_FINE_FASTER (TPM_CLOCK_ADJUST)(1) +#define TPM_CLOCK_MEDIUM_FASTER (TPM_CLOCK_ADJUST)(2) +#define TPM_CLOCK_COARSE_FASTER (TPM_CLOCK_ADJUST)(3) + +// Table 2:18 - Definition of TPM_EO Constants +typedef UINT16 TPM_EO; +#define TYPE_OF_TPM_EO UINT16 +#define TPM_EO_EQ (TPM_EO)(0x0000) +#define TPM_EO_NEQ (TPM_EO)(0x0001) +#define TPM_EO_SIGNED_GT (TPM_EO)(0x0002) +#define TPM_EO_UNSIGNED_GT (TPM_EO)(0x0003) +#define TPM_EO_SIGNED_LT (TPM_EO)(0x0004) +#define TPM_EO_UNSIGNED_LT (TPM_EO)(0x0005) +#define TPM_EO_SIGNED_GE (TPM_EO)(0x0006) +#define TPM_EO_UNSIGNED_GE (TPM_EO)(0x0007) +#define TPM_EO_SIGNED_LE (TPM_EO)(0x0008) +#define TPM_EO_UNSIGNED_LE (TPM_EO)(0x0009) +#define TPM_EO_BITSET (TPM_EO)(0x000A) +#define TPM_EO_BITCLEAR (TPM_EO)(0x000B) + +// Table 2:19 - Definition of TPM_ST Constants +typedef UINT16 TPM_ST; +#define TYPE_OF_TPM_ST UINT16 +#define TPM_ST_RSP_COMMAND (TPM_ST)(0x00C4) +#define TPM_ST_NULL (TPM_ST)(0x8000) +#define TPM_ST_NO_SESSIONS (TPM_ST)(0x8001) +#define TPM_ST_SESSIONS (TPM_ST)(0x8002) +#define TPM_ST_ATTEST_NV (TPM_ST)(0x8014) +#define TPM_ST_ATTEST_COMMAND_AUDIT (TPM_ST)(0x8015) +#define TPM_ST_ATTEST_SESSION_AUDIT (TPM_ST)(0x8016) +#define TPM_ST_ATTEST_CERTIFY (TPM_ST)(0x8017) +#define TPM_ST_ATTEST_QUOTE (TPM_ST)(0x8018) +#define TPM_ST_ATTEST_TIME (TPM_ST)(0x8019) +#define TPM_ST_ATTEST_CREATION (TPM_ST)(0x801A) +#define TPM_ST_ATTEST_NV_DIGEST (TPM_ST)(0x801C) +#define TPM_ST_CREATION (TPM_ST)(0x8021) +#define TPM_ST_VERIFIED (TPM_ST)(0x8022) +#define TPM_ST_AUTH_SECRET (TPM_ST)(0x8023) +#define TPM_ST_HASHCHECK (TPM_ST)(0x8024) +#define TPM_ST_AUTH_SIGNED (TPM_ST)(0x8025) +#define TPM_ST_FU_MANIFEST (TPM_ST)(0x8029) + +// Table 2:20 - Definition of TPM_SU Constants +typedef UINT16 TPM_SU; +#define TYPE_OF_TPM_SU UINT16 +#define TPM_SU_CLEAR (TPM_SU)(0x0000) +#define TPM_SU_STATE (TPM_SU)(0x0001) + +// Table 2:21 - Definition of TPM_SE Constants +typedef UINT8 TPM_SE; +#define TYPE_OF_TPM_SE UINT8 +#define TPM_SE_HMAC (TPM_SE)(0x00) +#define TPM_SE_POLICY (TPM_SE)(0x01) +#define TPM_SE_TRIAL (TPM_SE)(0x03) + +// Table 2:22 - Definition of TPM_CAP Constants +typedef UINT32 TPM_CAP; +#define TYPE_OF_TPM_CAP UINT32 +#define TPM_CAP_FIRST (TPM_CAP)(0x00000000) +#define TPM_CAP_ALGS (TPM_CAP)(0x00000000) +#define TPM_CAP_HANDLES (TPM_CAP)(0x00000001) +#define TPM_CAP_COMMANDS (TPM_CAP)(0x00000002) +#define TPM_CAP_PP_COMMANDS (TPM_CAP)(0x00000003) +#define TPM_CAP_AUDIT_COMMANDS (TPM_CAP)(0x00000004) +#define TPM_CAP_PCRS (TPM_CAP)(0x00000005) +#define TPM_CAP_TPM_PROPERTIES (TPM_CAP)(0x00000006) +#define TPM_CAP_PCR_PROPERTIES (TPM_CAP)(0x00000007) +#define TPM_CAP_ECC_CURVES (TPM_CAP)(0x00000008) +#define TPM_CAP_AUTH_POLICIES (TPM_CAP)(0x00000009) +#define TPM_CAP_ACT (TPM_CAP)(0x0000000A) +#define TPM_CAP_LAST (TPM_CAP)(0x0000000A) +#define TPM_CAP_VENDOR_PROPERTY (TPM_CAP)(0x00000100) + +// Table 2:23 - Definition of TPM_PT Constants +typedef UINT32 TPM_PT; +#define TYPE_OF_TPM_PT UINT32 +#define TPM_PT_NONE (TPM_PT)(0x00000000) +#define PT_GROUP (TPM_PT)(0x00000100) +#define PT_FIXED (TPM_PT)(PT_GROUP * 1) +#define TPM_PT_FAMILY_INDICATOR (TPM_PT)(PT_FIXED + 0) +#define TPM_PT_LEVEL (TPM_PT)(PT_FIXED + 1) +#define TPM_PT_REVISION (TPM_PT)(PT_FIXED + 2) +#define TPM_PT_DAY_OF_YEAR (TPM_PT)(PT_FIXED + 3) +#define TPM_PT_YEAR (TPM_PT)(PT_FIXED + 4) +#define TPM_PT_MANUFACTURER (TPM_PT)(PT_FIXED + 5) +#define TPM_PT_VENDOR_STRING_1 (TPM_PT)(PT_FIXED + 6) +#define TPM_PT_VENDOR_STRING_2 (TPM_PT)(PT_FIXED + 7) +#define TPM_PT_VENDOR_STRING_3 (TPM_PT)(PT_FIXED + 8) +#define TPM_PT_VENDOR_STRING_4 (TPM_PT)(PT_FIXED + 9) +#define TPM_PT_VENDOR_TPM_TYPE (TPM_PT)(PT_FIXED + 10) +#define TPM_PT_FIRMWARE_VERSION_1 (TPM_PT)(PT_FIXED + 11) +#define TPM_PT_FIRMWARE_VERSION_2 (TPM_PT)(PT_FIXED + 12) +#define TPM_PT_INPUT_BUFFER (TPM_PT)(PT_FIXED + 13) +#define TPM_PT_HR_TRANSIENT_MIN (TPM_PT)(PT_FIXED + 14) +#define TPM_PT_HR_PERSISTENT_MIN (TPM_PT)(PT_FIXED + 15) +#define TPM_PT_HR_LOADED_MIN (TPM_PT)(PT_FIXED + 16) +#define TPM_PT_ACTIVE_SESSIONS_MAX (TPM_PT)(PT_FIXED + 17) +#define TPM_PT_PCR_COUNT (TPM_PT)(PT_FIXED + 18) +#define TPM_PT_PCR_SELECT_MIN (TPM_PT)(PT_FIXED + 19) +#define TPM_PT_CONTEXT_GAP_MAX (TPM_PT)(PT_FIXED + 20) +#define TPM_PT_NV_COUNTERS_MAX (TPM_PT)(PT_FIXED + 22) +#define TPM_PT_NV_INDEX_MAX (TPM_PT)(PT_FIXED + 23) +#define TPM_PT_MEMORY (TPM_PT)(PT_FIXED + 24) +#define TPM_PT_CLOCK_UPDATE (TPM_PT)(PT_FIXED + 25) +#define TPM_PT_CONTEXT_HASH (TPM_PT)(PT_FIXED + 26) +#define TPM_PT_CONTEXT_SYM (TPM_PT)(PT_FIXED + 27) +#define TPM_PT_CONTEXT_SYM_SIZE (TPM_PT)(PT_FIXED + 28) +#define TPM_PT_ORDERLY_COUNT (TPM_PT)(PT_FIXED + 29) +#define TPM_PT_MAX_COMMAND_SIZE (TPM_PT)(PT_FIXED + 30) +#define TPM_PT_MAX_RESPONSE_SIZE (TPM_PT)(PT_FIXED + 31) +#define TPM_PT_MAX_DIGEST (TPM_PT)(PT_FIXED + 32) +#define TPM_PT_MAX_OBJECT_CONTEXT (TPM_PT)(PT_FIXED + 33) +#define TPM_PT_MAX_SESSION_CONTEXT (TPM_PT)(PT_FIXED + 34) +#define TPM_PT_PS_FAMILY_INDICATOR (TPM_PT)(PT_FIXED + 35) +#define TPM_PT_PS_LEVEL (TPM_PT)(PT_FIXED + 36) +#define TPM_PT_PS_REVISION (TPM_PT)(PT_FIXED + 37) +#define TPM_PT_PS_DAY_OF_YEAR (TPM_PT)(PT_FIXED + 38) +#define TPM_PT_PS_YEAR (TPM_PT)(PT_FIXED + 39) +#define TPM_PT_SPLIT_MAX (TPM_PT)(PT_FIXED + 40) +#define TPM_PT_TOTAL_COMMANDS (TPM_PT)(PT_FIXED + 41) +#define TPM_PT_LIBRARY_COMMANDS (TPM_PT)(PT_FIXED + 42) +#define TPM_PT_VENDOR_COMMANDS (TPM_PT)(PT_FIXED + 43) +#define TPM_PT_NV_BUFFER_MAX (TPM_PT)(PT_FIXED + 44) +#define TPM_PT_MODES (TPM_PT)(PT_FIXED + 45) +#define TPM_PT_MAX_CAP_BUFFER (TPM_PT)(PT_FIXED + 46) +#define PT_VAR (TPM_PT)(PT_GROUP * 2) +#define TPM_PT_PERMANENT (TPM_PT)(PT_VAR + 0) +#define TPM_PT_STARTUP_CLEAR (TPM_PT)(PT_VAR + 1) +#define TPM_PT_HR_NV_INDEX (TPM_PT)(PT_VAR + 2) +#define TPM_PT_HR_LOADED (TPM_PT)(PT_VAR + 3) +#define TPM_PT_HR_LOADED_AVAIL (TPM_PT)(PT_VAR + 4) +#define TPM_PT_HR_ACTIVE (TPM_PT)(PT_VAR + 5) +#define TPM_PT_HR_ACTIVE_AVAIL (TPM_PT)(PT_VAR + 6) +#define TPM_PT_HR_TRANSIENT_AVAIL (TPM_PT)(PT_VAR + 7) +#define TPM_PT_HR_PERSISTENT (TPM_PT)(PT_VAR + 8) +#define TPM_PT_HR_PERSISTENT_AVAIL (TPM_PT)(PT_VAR + 9) +#define TPM_PT_NV_COUNTERS (TPM_PT)(PT_VAR + 10) +#define TPM_PT_NV_COUNTERS_AVAIL (TPM_PT)(PT_VAR + 11) +#define TPM_PT_ALGORITHM_SET (TPM_PT)(PT_VAR + 12) +#define TPM_PT_LOADED_CURVES (TPM_PT)(PT_VAR + 13) +#define TPM_PT_LOCKOUT_COUNTER (TPM_PT)(PT_VAR + 14) +#define TPM_PT_MAX_AUTH_FAIL (TPM_PT)(PT_VAR + 15) +#define TPM_PT_LOCKOUT_INTERVAL (TPM_PT)(PT_VAR + 16) +#define TPM_PT_LOCKOUT_RECOVERY (TPM_PT)(PT_VAR + 17) +#define TPM_PT_NV_WRITE_RECOVERY (TPM_PT)(PT_VAR + 18) +#define TPM_PT_AUDIT_COUNTER_0 (TPM_PT)(PT_VAR + 19) +#define TPM_PT_AUDIT_COUNTER_1 (TPM_PT)(PT_VAR + 20) + +// Table 2:24 - Definition of TPM_PT_PCR Constants +typedef UINT32 TPM_PT_PCR; +#define TYPE_OF_TPM_PT_PCR UINT32 +#define TPM_PT_PCR_FIRST (TPM_PT_PCR)(0x00000000) +#define TPM_PT_PCR_SAVE (TPM_PT_PCR)(0x00000000) +#define TPM_PT_PCR_EXTEND_L0 (TPM_PT_PCR)(0x00000001) +#define TPM_PT_PCR_RESET_L0 (TPM_PT_PCR)(0x00000002) +#define TPM_PT_PCR_EXTEND_L1 (TPM_PT_PCR)(0x00000003) +#define TPM_PT_PCR_RESET_L1 (TPM_PT_PCR)(0x00000004) +#define TPM_PT_PCR_EXTEND_L2 (TPM_PT_PCR)(0x00000005) +#define TPM_PT_PCR_RESET_L2 (TPM_PT_PCR)(0x00000006) +#define TPM_PT_PCR_EXTEND_L3 (TPM_PT_PCR)(0x00000007) +#define TPM_PT_PCR_RESET_L3 (TPM_PT_PCR)(0x00000008) +#define TPM_PT_PCR_EXTEND_L4 (TPM_PT_PCR)(0x00000009) +#define TPM_PT_PCR_RESET_L4 (TPM_PT_PCR)(0x0000000A) +#define TPM_PT_PCR_NO_INCREMENT (TPM_PT_PCR)(0x00000011) +#define TPM_PT_PCR_DRTM_RESET (TPM_PT_PCR)(0x00000012) +#define TPM_PT_PCR_POLICY (TPM_PT_PCR)(0x00000013) +#define TPM_PT_PCR_AUTH (TPM_PT_PCR)(0x00000014) +#define TPM_PT_PCR_LAST (TPM_PT_PCR)(0x00000014) + +// Table 2:25 - Definition of TPM_PS Constants +typedef UINT32 TPM_PS; +#define TYPE_OF_TPM_PS UINT32 +#define TPM_PS_MAIN (TPM_PS)(0x00000000) +#define TPM_PS_PC (TPM_PS)(0x00000001) +#define TPM_PS_PDA (TPM_PS)(0x00000002) +#define TPM_PS_CELL_PHONE (TPM_PS)(0x00000003) +#define TPM_PS_SERVER (TPM_PS)(0x00000004) +#define TPM_PS_PERIPHERAL (TPM_PS)(0x00000005) +#define TPM_PS_TSS (TPM_PS)(0x00000006) +#define TPM_PS_STORAGE (TPM_PS)(0x00000007) +#define TPM_PS_AUTHENTICATION (TPM_PS)(0x00000008) +#define TPM_PS_EMBEDDED (TPM_PS)(0x00000009) +#define TPM_PS_HARDCOPY (TPM_PS)(0x0000000A) +#define TPM_PS_INFRASTRUCTURE (TPM_PS)(0x0000000B) +#define TPM_PS_VIRTUALIZATION (TPM_PS)(0x0000000C) +#define TPM_PS_TNC (TPM_PS)(0x0000000D) +#define TPM_PS_MULTI_TENANT (TPM_PS)(0x0000000E) +#define TPM_PS_TC (TPM_PS)(0x0000000F) + +// Table 2:26 - Definition of Types for Handles +typedef UINT32 TPM_HANDLE; +#define TYPE_OF_TPM_HANDLE UINT32 + +// Table 2:27 - Definition of TPM_HT Constants +typedef UINT8 TPM_HT; +#define TYPE_OF_TPM_HT UINT8 +#define TPM_HT_PCR (TPM_HT)(0x00) +#define TPM_HT_NV_INDEX (TPM_HT)(0x01) +#define TPM_HT_HMAC_SESSION (TPM_HT)(0x02) +#define TPM_HT_LOADED_SESSION (TPM_HT)(0x02) +#define TPM_HT_POLICY_SESSION (TPM_HT)(0x03) +#define TPM_HT_SAVED_SESSION (TPM_HT)(0x03) +#define TPM_HT_PERMANENT (TPM_HT)(0x40) +#define TPM_HT_TRANSIENT (TPM_HT)(0x80) +#define TPM_HT_PERSISTENT (TPM_HT)(0x81) +#define TPM_HT_AC (TPM_HT)(0x90) + +// Table 2:28 - Definition of TPM_RH Constants +typedef TPM_HANDLE TPM_RH; +#define TPM_RH_FIRST (TPM_RH)(0x40000000) +#define TPM_RH_SRK (TPM_RH)(0x40000000) +#define TPM_RH_OWNER (TPM_RH)(0x40000001) +#define TPM_RH_REVOKE (TPM_RH)(0x40000002) +#define TPM_RH_TRANSPORT (TPM_RH)(0x40000003) +#define TPM_RH_OPERATOR (TPM_RH)(0x40000004) +#define TPM_RH_ADMIN (TPM_RH)(0x40000005) +#define TPM_RH_EK (TPM_RH)(0x40000006) +#define TPM_RH_NULL (TPM_RH)(0x40000007) +#define TPM_RH_UNASSIGNED (TPM_RH)(0x40000008) +#define TPM_RS_PW (TPM_RH)(0x40000009) +#define TPM_RH_LOCKOUT (TPM_RH)(0x4000000A) +#define TPM_RH_ENDORSEMENT (TPM_RH)(0x4000000B) +#define TPM_RH_PLATFORM (TPM_RH)(0x4000000C) +#define TPM_RH_PLATFORM_NV (TPM_RH)(0x4000000D) +#define TPM_RH_AUTH_00 (TPM_RH)(0x40000010) +#define TPM_RH_AUTH_FF (TPM_RH)(0x4000010F) +#define TPM_RH_ACT_0 (TPM_RH)(0x40000110) +#define TPM_RH_ACT_F (TPM_RH)(0x4000011F) +#define TPM_RH_LAST (TPM_RH)(0x4000011F) + +// Table 2:29 - Definition of TPM_HC Constants +typedef TPM_HANDLE TPM_HC; +#define HR_HANDLE_MASK (TPM_HC)(0x00FFFFFF) +#define HR_RANGE_MASK (TPM_HC)(0xFF000000) +#define HR_SHIFT (TPM_HC)(24) +#define HR_PCR (TPM_HC)((TPM_HT_PCR << HR_SHIFT)) +#define HR_HMAC_SESSION (TPM_HC)((TPM_HT_HMAC_SESSION << HR_SHIFT)) +#define HR_POLICY_SESSION (TPM_HC)((TPM_HT_POLICY_SESSION << HR_SHIFT)) +#define HR_TRANSIENT (TPM_HC)((TPM_HT_TRANSIENT << HR_SHIFT)) +#define HR_PERSISTENT (TPM_HC)((TPM_HT_PERSISTENT << HR_SHIFT)) +#define HR_NV_INDEX (TPM_HC)((TPM_HT_NV_INDEX << HR_SHIFT)) +#define HR_PERMANENT (TPM_HC)((TPM_HT_PERMANENT << HR_SHIFT)) +#define PCR_FIRST (TPM_HC)((HR_PCR + 0)) +#define PCR_LAST (TPM_HC)((PCR_FIRST + IMPLEMENTATION_PCR - 1)) +#define HMAC_SESSION_FIRST (TPM_HC)((HR_HMAC_SESSION + 0)) +#define HMAC_SESSION_LAST (TPM_HC)((HMAC_SESSION_FIRST + MAX_ACTIVE_SESSIONS - 1)) +#define LOADED_SESSION_FIRST (TPM_HC)(HMAC_SESSION_FIRST) +#define LOADED_SESSION_LAST (TPM_HC)(HMAC_SESSION_LAST) +#define POLICY_SESSION_FIRST (TPM_HC)((HR_POLICY_SESSION + 0)) +#define POLICY_SESSION_LAST (TPM_HC)((POLICY_SESSION_FIRST + MAX_ACTIVE_SESSIONS - 1)) +#define TRANSIENT_FIRST (TPM_HC)((HR_TRANSIENT + 0)) +#define ACTIVE_SESSION_FIRST (TPM_HC)(POLICY_SESSION_FIRST) +#define ACTIVE_SESSION_LAST (TPM_HC)(POLICY_SESSION_LAST) +#define TRANSIENT_LAST (TPM_HC)((TRANSIENT_FIRST + MAX_LOADED_OBJECTS - 1)) +#define PERSISTENT_FIRST (TPM_HC)((HR_PERSISTENT + 0)) +#define PERSISTENT_LAST (TPM_HC)((PERSISTENT_FIRST + 0x00FFFFFF)) +#define PLATFORM_PERSISTENT (TPM_HC)((PERSISTENT_FIRST + 0x00800000)) +#define NV_INDEX_FIRST (TPM_HC)((HR_NV_INDEX + 0)) +#define NV_INDEX_LAST (TPM_HC)((NV_INDEX_FIRST + 0x00FFFFFF)) +#define PERMANENT_FIRST (TPM_HC)(TPM_RH_FIRST) +#define PERMANENT_LAST (TPM_HC)(TPM_RH_LAST) +#define HR_NV_AC (TPM_HC)(((TPM_HT_NV_INDEX << HR_SHIFT) + 0xD00000)) +#define NV_AC_FIRST (TPM_HC)((HR_NV_AC + 0)) +#define NV_AC_LAST (TPM_HC)((HR_NV_AC + 0x0000FFFF)) +#define HR_AC (TPM_HC)((TPM_HT_AC << HR_SHIFT)) +#define AC_FIRST (TPM_HC)((HR_AC + 0)) +#define AC_LAST (TPM_HC)((HR_AC + 0x0000FFFF)) + +#define TYPE_OF_TPMA_ALGORITHM UINT32 +#define TPMA_ALGORITHM_TO_UINT32(a) (*((UINT32*)&(a))) +#define UINT32_TO_TPMA_ALGORITHM(a) (*((TPMA_ALGORITHM*)&(a))) +#define TPMA_ALGORITHM_TO_BYTE_ARRAY(i, a) \ + UINT32_TO_BYTE_ARRAY((TPMA_ALGORITHM_TO_UINT32(i)), (a)) +#define BYTE_ARRAY_TO_TPMA_ALGORITHM(i, a) \ + { \ + UINT32 x = BYTE_ARRAY_TO_UINT32(a); \ + i = UINT32_TO_TPMA_ALGORITHM(x); \ + } +#if USE_BIT_FIELD_STRUCTURES +typedef struct TPMA_ALGORITHM +{ // Table 2:30 + unsigned asymmetric : 1; + unsigned symmetric : 1; + unsigned hash : 1; + unsigned object : 1; + unsigned Reserved_bits_at_4 : 4; + unsigned signing : 1; + unsigned encrypting : 1; + unsigned method : 1; + unsigned Reserved_bits_at_11 : 21; +} TPMA_ALGORITHM; /* Bits */ +// This is the initializer for a TPMA_ALGORITHM structure +# define TPMA_ALGORITHM_INITIALIZER(asymmetric, \ + symmetric, \ + hash, \ + object, \ + bits_at_4, \ + signing, \ + encrypting, \ + method, \ + bits_at_11) \ + { \ + asymmetric, symmetric, hash, object, bits_at_4, signing, encrypting, method, \ + bits_at_11 \ + } +#else // USE_BIT_FIELD_STRUCTURES +// This implements Table 2:30 TPMA_ALGORITHM using bit masking +typedef UINT32 TPMA_ALGORITHM; +# define TYPE_OF_TPMA_ALGORITHM UINT32 +# define TPMA_ALGORITHM_asymmetric ((TPMA_ALGORITHM)1 << 0) +# define TPMA_ALGORITHM_symmetric ((TPMA_ALGORITHM)1 << 1) +# define TPMA_ALGORITHM_hash ((TPMA_ALGORITHM)1 << 2) +# define TPMA_ALGORITHM_object ((TPMA_ALGORITHM)1 << 3) +# define TPMA_ALGORITHM_signing ((TPMA_ALGORITHM)1 << 8) +# define TPMA_ALGORITHM_encrypting ((TPMA_ALGORITHM)1 << 9) +# define TPMA_ALGORITHM_method ((TPMA_ALGORITHM)1 << 10) +// This is the initializer for a TPMA_ALGORITHM bit array. +# define TPMA_ALGORITHM_INITIALIZER(asymmetric, \ + symmetric, \ + hash, \ + object, \ + bits_at_4, \ + signing, \ + encrypting, \ + method, \ + bits_at_11) \ + (TPMA_ALGORITHM)((asymmetric << 0) + (symmetric << 1) + (hash << 2) \ + + (object << 3) + (signing << 8) + (encrypting << 9) \ + + (method << 10)) +#endif // USE_BIT_FIELD_STRUCTURES + +#define TYPE_OF_TPMA_OBJECT UINT32 +#define TPMA_OBJECT_TO_UINT32(a) (*((UINT32*)&(a))) +#define UINT32_TO_TPMA_OBJECT(a) (*((TPMA_OBJECT*)&(a))) +#define TPMA_OBJECT_TO_BYTE_ARRAY(i, a) \ + UINT32_TO_BYTE_ARRAY((TPMA_OBJECT_TO_UINT32(i)), (a)) +#define BYTE_ARRAY_TO_TPMA_OBJECT(i, a) \ + { \ + UINT32 x = BYTE_ARRAY_TO_UINT32(a); \ + i = UINT32_TO_TPMA_OBJECT(x); \ + } +#if USE_BIT_FIELD_STRUCTURES +typedef struct TPMA_OBJECT +{ // Table 2:31 + unsigned Reserved_bit_at_0 : 1; + unsigned fixedTPM : 1; + unsigned stClear : 1; + unsigned Reserved_bit_at_3 : 1; + unsigned fixedParent : 1; + unsigned sensitiveDataOrigin : 1; + unsigned userWithAuth : 1; + unsigned adminWithPolicy : 1; + unsigned Reserved_bits_at_8 : 2; + unsigned noDA : 1; + unsigned encryptedDuplication : 1; + unsigned Reserved_bits_at_12 : 4; + unsigned restricted : 1; + unsigned decrypt : 1; + unsigned sign : 1; + unsigned x509sign : 1; + unsigned Reserved_bits_at_20 : 12; +} TPMA_OBJECT; /* Bits */ +// This is the initializer for a TPMA_OBJECT structure +# define TPMA_OBJECT_INITIALIZER(bit_at_0, \ + fixedtpm, \ + stclear, \ + bit_at_3, \ + fixedparent, \ + sensitivedataorigin, \ + userwithauth, \ + adminwithpolicy, \ + bits_at_8, \ + noda, \ + encryptedduplication, \ + bits_at_12, \ + restricted, \ + decrypt, \ + sign, \ + x509sign, \ + bits_at_20) \ + { \ + bit_at_0, fixedtpm, stclear, bit_at_3, fixedparent, sensitivedataorigin, \ + userwithauth, adminwithpolicy, bits_at_8, noda, encryptedduplication, \ + bits_at_12, restricted, decrypt, sign, x509sign, bits_at_20 \ + } +#else // USE_BIT_FIELD_STRUCTURES +// This implements Table 2:31 TPMA_OBJECT using bit masking +typedef UINT32 TPMA_OBJECT; +# define TYPE_OF_TPMA_OBJECT UINT32 +# define TPMA_OBJECT_fixedTPM ((TPMA_OBJECT)1 << 1) +# define TPMA_OBJECT_stClear ((TPMA_OBJECT)1 << 2) +# define TPMA_OBJECT_fixedParent ((TPMA_OBJECT)1 << 4) +# define TPMA_OBJECT_sensitiveDataOrigin ((TPMA_OBJECT)1 << 5) +# define TPMA_OBJECT_userWithAuth ((TPMA_OBJECT)1 << 6) +# define TPMA_OBJECT_adminWithPolicy ((TPMA_OBJECT)1 << 7) +# define TPMA_OBJECT_noDA ((TPMA_OBJECT)1 << 10) +# define TPMA_OBJECT_encryptedDuplication ((TPMA_OBJECT)1 << 11) +# define TPMA_OBJECT_restricted ((TPMA_OBJECT)1 << 16) +# define TPMA_OBJECT_decrypt ((TPMA_OBJECT)1 << 17) +# define TPMA_OBJECT_sign ((TPMA_OBJECT)1 << 18) +# define TPMA_OBJECT_x509sign ((TPMA_OBJECT)1 << 19) +// This is the initializer for a TPMA_OBJECT bit array. +# define TPMA_OBJECT_INITIALIZER(bit_at_0, \ + fixedtpm, \ + stclear, \ + bit_at_3, \ + fixedparent, \ + sensitivedataorigin, \ + userwithauth, \ + adminwithpolicy, \ + bits_at_8, \ + noda, \ + encryptedduplication, \ + bits_at_12, \ + restricted, \ + decrypt, \ + sign, \ + x509sign, \ + bits_at_20) \ + (TPMA_OBJECT)((fixedtpm << 1) + (stclear << 2) + (fixedparent << 4) \ + + (sensitivedataorigin << 5) + (userwithauth << 6) \ + + (adminwithpolicy << 7) + (noda << 10) \ + + (encryptedduplication << 11) + (restricted << 16) \ + + (decrypt << 17) + (sign << 18) + (x509sign << 19)) +#endif // USE_BIT_FIELD_STRUCTURES + +#define TYPE_OF_TPMA_SESSION UINT8 +#define TPMA_SESSION_TO_UINT8(a) (*((UINT8*)&(a))) +#define UINT8_TO_TPMA_SESSION(a) (*((TPMA_SESSION*)&(a))) +#define TPMA_SESSION_TO_BYTE_ARRAY(i, a) \ + UINT8_TO_BYTE_ARRAY((TPMA_SESSION_TO_UINT8(i)), (a)) +#define BYTE_ARRAY_TO_TPMA_SESSION(i, a) \ + { \ + UINT8 x = BYTE_ARRAY_TO_UINT8(a); \ + i = UINT8_TO_TPMA_SESSION(x); \ + } +#if USE_BIT_FIELD_STRUCTURES +typedef struct TPMA_SESSION +{ // Table 2:32 + unsigned continueSession : 1; + unsigned auditExclusive : 1; + unsigned auditReset : 1; + unsigned Reserved_bits_at_3 : 2; + unsigned decrypt : 1; + unsigned encrypt : 1; + unsigned audit : 1; +} TPMA_SESSION; /* Bits */ +// This is the initializer for a TPMA_SESSION structure +# define TPMA_SESSION_INITIALIZER(continuesession, \ + auditexclusive, \ + auditreset, \ + bits_at_3, \ + decrypt, \ + encrypt, \ + audit) \ + { \ + continuesession, auditexclusive, auditreset, bits_at_3, decrypt, encrypt, \ + audit \ + } +#else // USE_BIT_FIELD_STRUCTURES +// This implements Table 2:32 TPMA_SESSION using bit masking +typedef UINT8 TPMA_SESSION; +# define TYPE_OF_TPMA_SESSION UINT8 +# define TPMA_SESSION_continueSession ((TPMA_SESSION)1 << 0) +# define TPMA_SESSION_auditExclusive ((TPMA_SESSION)1 << 1) +# define TPMA_SESSION_auditReset ((TPMA_SESSION)1 << 2) +# define TPMA_SESSION_decrypt ((TPMA_SESSION)1 << 5) +# define TPMA_SESSION_encrypt ((TPMA_SESSION)1 << 6) +# define TPMA_SESSION_audit ((TPMA_SESSION)1 << 7) +// This is the initializer for a TPMA_SESSION bit array. +# define TPMA_SESSION_INITIALIZER(continuesession, \ + auditexclusive, \ + auditreset, \ + bits_at_3, \ + decrypt, \ + encrypt, \ + audit) \ + (TPMA_SESSION)((continuesession << 0) + (auditexclusive << 1) \ + + (auditreset << 2) + (decrypt << 5) + (encrypt << 6) \ + + (audit << 7)) +#endif // USE_BIT_FIELD_STRUCTURES + +#define TYPE_OF_TPMA_LOCALITY UINT8 +#define TPMA_LOCALITY_TO_UINT8(a) (*((UINT8*)&(a))) +#define UINT8_TO_TPMA_LOCALITY(a) (*((TPMA_LOCALITY*)&(a))) +#define TPMA_LOCALITY_TO_BYTE_ARRAY(i, a) \ + UINT8_TO_BYTE_ARRAY((TPMA_LOCALITY_TO_UINT8(i)), (a)) +#define BYTE_ARRAY_TO_TPMA_LOCALITY(i, a) \ + { \ + UINT8 x = BYTE_ARRAY_TO_UINT8(a); \ + i = UINT8_TO_TPMA_LOCALITY(x); \ + } +#if USE_BIT_FIELD_STRUCTURES +typedef struct TPMA_LOCALITY +{ // Table 2:33 + unsigned TPM_LOC_ZERO : 1; + unsigned TPM_LOC_ONE : 1; + unsigned TPM_LOC_TWO : 1; + unsigned TPM_LOC_THREE : 1; + unsigned TPM_LOC_FOUR : 1; + unsigned Extended : 3; +} TPMA_LOCALITY; /* Bits */ +// This is the initializer for a TPMA_LOCALITY structure +# define TPMA_LOCALITY_INITIALIZER( \ + tpm_loc_zero, tpm_loc_one, tpm_loc_two, tpm_loc_three, tpm_loc_four, extended) \ + { \ + tpm_loc_zero, tpm_loc_one, tpm_loc_two, tpm_loc_three, tpm_loc_four, extended \ + } +#else // USE_BIT_FIELD_STRUCTURES +// This implements Table 2:33 TPMA_LOCALITY using bit masking +typedef UINT8 TPMA_LOCALITY; +# define TYPE_OF_TPMA_LOCALITY UINT8 +# define TPMA_LOCALITY_TPM_LOC_ZERO ((TPMA_LOCALITY)1 << 0) +# define TPMA_LOCALITY_TPM_LOC_ONE ((TPMA_LOCALITY)1 << 1) +# define TPMA_LOCALITY_TPM_LOC_TWO ((TPMA_LOCALITY)1 << 2) +# define TPMA_LOCALITY_TPM_LOC_THREE ((TPMA_LOCALITY)1 << 3) +# define TPMA_LOCALITY_TPM_LOC_FOUR ((TPMA_LOCALITY)1 << 4) +# define TPMA_LOCALITY_Extended_SHIFT 5 +# define TPMA_LOCALITY_Extended ((TPMA_LOCALITY)0x7 << 5) +// This is the initializer for a TPMA_LOCALITY bit array. +# define TPMA_LOCALITY_INITIALIZER( \ + tpm_loc_zero, tpm_loc_one, tpm_loc_two, tpm_loc_three, tpm_loc_four, extended) \ + (TPMA_LOCALITY)((tpm_loc_zero << 0) + (tpm_loc_one << 1) + (tpm_loc_two << 2) \ + + (tpm_loc_three << 3) + (tpm_loc_four << 4) + (extended << 5)) +#endif // USE_BIT_FIELD_STRUCTURES + +#define TYPE_OF_TPMA_PERMANENT UINT32 +#define TPMA_PERMANENT_TO_UINT32(a) (*((UINT32*)&(a))) +#define UINT32_TO_TPMA_PERMANENT(a) (*((TPMA_PERMANENT*)&(a))) +#define TPMA_PERMANENT_TO_BYTE_ARRAY(i, a) \ + UINT32_TO_BYTE_ARRAY((TPMA_PERMANENT_TO_UINT32(i)), (a)) +#define BYTE_ARRAY_TO_TPMA_PERMANENT(i, a) \ + { \ + UINT32 x = BYTE_ARRAY_TO_UINT32(a); \ + i = UINT32_TO_TPMA_PERMANENT(x); \ + } +#if USE_BIT_FIELD_STRUCTURES +typedef struct TPMA_PERMANENT +{ // Table 2:34 + unsigned ownerAuthSet : 1; + unsigned endorsementAuthSet : 1; + unsigned lockoutAuthSet : 1; + unsigned Reserved_bits_at_3 : 5; + unsigned disableClear : 1; + unsigned inLockout : 1; + unsigned tpmGeneratedEPS : 1; + unsigned Reserved_bits_at_11 : 21; +} TPMA_PERMANENT; /* Bits */ +// This is the initializer for a TPMA_PERMANENT structure +# define TPMA_PERMANENT_INITIALIZER(ownerauthset, \ + endorsementauthset, \ + lockoutauthset, \ + bits_at_3, \ + disableclear, \ + inlockout, \ + tpmgeneratedeps, \ + bits_at_11) \ + { \ + ownerauthset, endorsementauthset, lockoutauthset, bits_at_3, disableclear, \ + inlockout, tpmgeneratedeps, bits_at_11 \ + } +#else // USE_BIT_FIELD_STRUCTURES +// This implements Table 2:34 TPMA_PERMANENT using bit masking +typedef UINT32 TPMA_PERMANENT; +# define TYPE_OF_TPMA_PERMANENT UINT32 +# define TPMA_PERMANENT_ownerAuthSet ((TPMA_PERMANENT)1 << 0) +# define TPMA_PERMANENT_endorsementAuthSet ((TPMA_PERMANENT)1 << 1) +# define TPMA_PERMANENT_lockoutAuthSet ((TPMA_PERMANENT)1 << 2) +# define TPMA_PERMANENT_disableClear ((TPMA_PERMANENT)1 << 8) +# define TPMA_PERMANENT_inLockout ((TPMA_PERMANENT)1 << 9) +# define TPMA_PERMANENT_tpmGeneratedEPS ((TPMA_PERMANENT)1 << 10) +// This is the initializer for a TPMA_PERMANENT bit array. +# define TPMA_PERMANENT_INITIALIZER(ownerauthset, \ + endorsementauthset, \ + lockoutauthset, \ + bits_at_3, \ + disableclear, \ + inlockout, \ + tpmgeneratedeps, \ + bits_at_11) \ + (TPMA_PERMANENT)((ownerauthset << 0) + (endorsementauthset << 1) \ + + (lockoutauthset << 2) + (disableclear << 8) \ + + (inlockout << 9) + (tpmgeneratedeps << 10)) +#endif // USE_BIT_FIELD_STRUCTURES + +#define TYPE_OF_TPMA_STARTUP_CLEAR UINT32 +#define TPMA_STARTUP_CLEAR_TO_UINT32(a) (*((UINT32*)&(a))) +#define UINT32_TO_TPMA_STARTUP_CLEAR(a) (*((TPMA_STARTUP_CLEAR*)&(a))) +#define TPMA_STARTUP_CLEAR_TO_BYTE_ARRAY(i, a) \ + UINT32_TO_BYTE_ARRAY((TPMA_STARTUP_CLEAR_TO_UINT32(i)), (a)) +#define BYTE_ARRAY_TO_TPMA_STARTUP_CLEAR(i, a) \ + { \ + UINT32 x = BYTE_ARRAY_TO_UINT32(a); \ + i = UINT32_TO_TPMA_STARTUP_CLEAR(x); \ + } +#if USE_BIT_FIELD_STRUCTURES +typedef struct TPMA_STARTUP_CLEAR +{ // Table 2:35 + unsigned phEnable : 1; + unsigned shEnable : 1; + unsigned ehEnable : 1; + unsigned phEnableNV : 1; + unsigned Reserved_bits_at_4 : 27; + unsigned orderly : 1; +} TPMA_STARTUP_CLEAR; /* Bits */ +// This is the initializer for a TPMA_STARTUP_CLEAR structure +# define TPMA_STARTUP_CLEAR_INITIALIZER( \ + phenable, shenable, ehenable, phenablenv, bits_at_4, orderly) \ + { \ + phenable, shenable, ehenable, phenablenv, bits_at_4, orderly \ + } +#else // USE_BIT_FIELD_STRUCTURES +// This implements Table 2:35 TPMA_STARTUP_CLEAR using bit masking +typedef UINT32 TPMA_STARTUP_CLEAR; +# define TYPE_OF_TPMA_STARTUP_CLEAR UINT32 +# define TPMA_STARTUP_CLEAR_phEnable ((TPMA_STARTUP_CLEAR)1 << 0) +# define TPMA_STARTUP_CLEAR_shEnable ((TPMA_STARTUP_CLEAR)1 << 1) +# define TPMA_STARTUP_CLEAR_ehEnable ((TPMA_STARTUP_CLEAR)1 << 2) +# define TPMA_STARTUP_CLEAR_phEnableNV ((TPMA_STARTUP_CLEAR)1 << 3) +# define TPMA_STARTUP_CLEAR_orderly ((TPMA_STARTUP_CLEAR)1 << 31) +// This is the initializer for a TPMA_STARTUP_CLEAR bit array. +# define TPMA_STARTUP_CLEAR_INITIALIZER( \ + phenable, shenable, ehenable, phenablenv, bits_at_4, orderly) \ + (TPMA_STARTUP_CLEAR)((phenable << 0) + (shenable << 1) + (ehenable << 2) \ + + (phenablenv << 3) + (orderly << 31)) +#endif // USE_BIT_FIELD_STRUCTURES + +#define TYPE_OF_TPMA_MEMORY UINT32 +#define TPMA_MEMORY_TO_UINT32(a) (*((UINT32*)&(a))) +#define UINT32_TO_TPMA_MEMORY(a) (*((TPMA_MEMORY*)&(a))) +#define TPMA_MEMORY_TO_BYTE_ARRAY(i, a) \ + UINT32_TO_BYTE_ARRAY((TPMA_MEMORY_TO_UINT32(i)), (a)) +#define BYTE_ARRAY_TO_TPMA_MEMORY(i, a) \ + { \ + UINT32 x = BYTE_ARRAY_TO_UINT32(a); \ + i = UINT32_TO_TPMA_MEMORY(x); \ + } +#if USE_BIT_FIELD_STRUCTURES +typedef struct TPMA_MEMORY +{ // Table 2:36 + unsigned sharedRAM : 1; + unsigned sharedNV : 1; + unsigned objectCopiedToRam : 1; + unsigned Reserved_bits_at_3 : 29; +} TPMA_MEMORY; /* Bits */ +// This is the initializer for a TPMA_MEMORY structure +# define TPMA_MEMORY_INITIALIZER(sharedram, sharednv, objectcopiedtoram, bits_at_3) \ + { \ + sharedram, sharednv, objectcopiedtoram, bits_at_3 \ + } +#else // USE_BIT_FIELD_STRUCTURES +// This implements Table 2:36 TPMA_MEMORY using bit masking +typedef UINT32 TPMA_MEMORY; +# define TYPE_OF_TPMA_MEMORY UINT32 +# define TPMA_MEMORY_sharedRAM ((TPMA_MEMORY)1 << 0) +# define TPMA_MEMORY_sharedNV ((TPMA_MEMORY)1 << 1) +# define TPMA_MEMORY_objectCopiedToRam ((TPMA_MEMORY)1 << 2) +// This is the initializer for a TPMA_MEMORY bit array. +# define TPMA_MEMORY_INITIALIZER(sharedram, sharednv, objectcopiedtoram, bits_at_3) \ + (TPMA_MEMORY)((sharedram << 0) + (sharednv << 1) + (objectcopiedtoram << 2)) +#endif // USE_BIT_FIELD_STRUCTURES + +#define TYPE_OF_TPMA_CC UINT32 +#define TPMA_CC_TO_UINT32(a) (*((UINT32*)&(a))) +#define UINT32_TO_TPMA_CC(a) (*((TPMA_CC*)&(a))) +#define TPMA_CC_TO_BYTE_ARRAY(i, a) UINT32_TO_BYTE_ARRAY((TPMA_CC_TO_UINT32(i)), (a)) +#define BYTE_ARRAY_TO_TPMA_CC(i, a) \ + { \ + UINT32 x = BYTE_ARRAY_TO_UINT32(a); \ + i = UINT32_TO_TPMA_CC(x); \ + } +#if USE_BIT_FIELD_STRUCTURES +typedef struct TPMA_CC +{ // Table 2:37 + unsigned commandIndex : 16; + unsigned Reserved_bits_at_16 : 6; + unsigned nv : 1; + unsigned extensive : 1; + unsigned flushed : 1; + unsigned cHandles : 3; + unsigned rHandle : 1; + unsigned V : 1; + unsigned Reserved_bits_at_30 : 2; +} TPMA_CC; /* Bits */ +// This is the initializer for a TPMA_CC structure +# define TPMA_CC_INITIALIZER(commandindex, \ + bits_at_16, \ + nv, \ + extensive, \ + flushed, \ + chandles, \ + rhandle, \ + v, \ + bits_at_30) \ + { \ + commandindex, bits_at_16, nv, extensive, flushed, chandles, rhandle, v, \ + bits_at_30 \ + } +#else // USE_BIT_FIELD_STRUCTURES +// This implements Table 2:37 TPMA_CC using bit masking +typedef UINT32 TPMA_CC; +# define TYPE_OF_TPMA_CC UINT32 +# define TPMA_CC_commandIndex_SHIFT 0 +# define TPMA_CC_commandIndex ((TPMA_CC)0xffff << 0) +# define TPMA_CC_nv ((TPMA_CC)1 << 22) +# define TPMA_CC_extensive ((TPMA_CC)1 << 23) +# define TPMA_CC_flushed ((TPMA_CC)1 << 24) +# define TPMA_CC_cHandles_SHIFT 25 +# define TPMA_CC_cHandles ((TPMA_CC)0x7 << 25) +# define TPMA_CC_rHandle ((TPMA_CC)1 << 28) +# define TPMA_CC_V ((TPMA_CC)1 << 29) +// This is the initializer for a TPMA_CC bit array. +# define TPMA_CC_INITIALIZER(commandindex, \ + bits_at_16, \ + nv, \ + extensive, \ + flushed, \ + chandles, \ + rhandle, \ + v, \ + bits_at_30) \ + (TPMA_CC)((commandindex << 0) + (nv << 22) + (extensive << 23) + (flushed << 24) \ + + (chandles << 25) + (rhandle << 28) + (v << 29)) +#endif // USE_BIT_FIELD_STRUCTURES + +#define TYPE_OF_TPMA_MODES UINT32 +#define TPMA_MODES_TO_UINT32(a) (*((UINT32*)&(a))) +#define UINT32_TO_TPMA_MODES(a) (*((TPMA_MODES*)&(a))) +#define TPMA_MODES_TO_BYTE_ARRAY(i, a) \ + UINT32_TO_BYTE_ARRAY((TPMA_MODES_TO_UINT32(i)), (a)) +#define BYTE_ARRAY_TO_TPMA_MODES(i, a) \ + { \ + UINT32 x = BYTE_ARRAY_TO_UINT32(a); \ + i = UINT32_TO_TPMA_MODES(x); \ + } +#if USE_BIT_FIELD_STRUCTURES +typedef struct TPMA_MODES +{ // Table 2:38 + unsigned FIPS_140_2 : 1; + unsigned Reserved_bits_at_1 : 31; +} TPMA_MODES; /* Bits */ +// This is the initializer for a TPMA_MODES structure +# define TPMA_MODES_INITIALIZER(fips_140_2, bits_at_1) \ + { \ + fips_140_2, bits_at_1 \ + } +#else // USE_BIT_FIELD_STRUCTURES +// This implements Table 2:38 TPMA_MODES using bit masking +typedef UINT32 TPMA_MODES; +# define TYPE_OF_TPMA_MODES UINT32 +# define TPMA_MODES_FIPS_140_2 ((TPMA_MODES)1 << 0) +// This is the initializer for a TPMA_MODES bit array. +# define TPMA_MODES_INITIALIZER(fips_140_2, bits_at_1) \ + (TPMA_MODES)((fips_140_2 << 0)) +#endif // USE_BIT_FIELD_STRUCTURES + +#define TYPE_OF_TPMA_X509_KEY_USAGE UINT32 +#define TPMA_X509_KEY_USAGE_TO_UINT32(a) (*((UINT32*)&(a))) +#define UINT32_TO_TPMA_X509_KEY_USAGE(a) (*((TPMA_X509_KEY_USAGE*)&(a))) +#define TPMA_X509_KEY_USAGE_TO_BYTE_ARRAY(i, a) \ + UINT32_TO_BYTE_ARRAY((TPMA_X509_KEY_USAGE_TO_UINT32(i)), (a)) +#define BYTE_ARRAY_TO_TPMA_X509_KEY_USAGE(i, a) \ + { \ + UINT32 x = BYTE_ARRAY_TO_UINT32(a); \ + i = UINT32_TO_TPMA_X509_KEY_USAGE(x); \ + } +#if USE_BIT_FIELD_STRUCTURES +typedef struct TPMA_X509_KEY_USAGE +{ // Table 2:39 + unsigned Reserved_bits_at_0 : 23; + unsigned decipherOnly : 1; + unsigned encipherOnly : 1; + unsigned cRLSign : 1; + unsigned keyCertSign : 1; + unsigned keyAgreement : 1; + unsigned dataEncipherment : 1; + unsigned keyEncipherment : 1; + unsigned nonrepudiation : 1; + unsigned digitalSignature : 1; +} TPMA_X509_KEY_USAGE; /* Bits */ +// This is the initializer for a TPMA_X509_KEY_USAGE structure +# define TPMA_X509_KEY_USAGE_INITIALIZER(bits_at_0, \ + decipheronly, \ + encipheronly, \ + crlsign, \ + keycertsign, \ + keyagreement, \ + dataencipherment, \ + keyencipherment, \ + nonrepudiation, \ + digitalsignature) \ + { \ + bits_at_0, decipheronly, encipheronly, crlsign, keycertsign, keyagreement, \ + dataencipherment, keyencipherment, nonrepudiation, digitalsignature \ + } +#else // USE_BIT_FIELD_STRUCTURES +// This implements Table 2:39 TPMA_X509_KEY_USAGE using bit masking +typedef UINT32 TPMA_X509_KEY_USAGE; +# define TYPE_OF_TPMA_X509_KEY_USAGE UINT32 +# define TPMA_X509_KEY_USAGE_decipherOnly ((TPMA_X509_KEY_USAGE)1 << 23) +# define TPMA_X509_KEY_USAGE_encipherOnly ((TPMA_X509_KEY_USAGE)1 << 24) +# define TPMA_X509_KEY_USAGE_cRLSign ((TPMA_X509_KEY_USAGE)1 << 25) +# define TPMA_X509_KEY_USAGE_keyCertSign ((TPMA_X509_KEY_USAGE)1 << 26) +# define TPMA_X509_KEY_USAGE_keyAgreement ((TPMA_X509_KEY_USAGE)1 << 27) +# define TPMA_X509_KEY_USAGE_dataEncipherment ((TPMA_X509_KEY_USAGE)1 << 28) +# define TPMA_X509_KEY_USAGE_keyEncipherment ((TPMA_X509_KEY_USAGE)1 << 29) +# define TPMA_X509_KEY_USAGE_nonrepudiation ((TPMA_X509_KEY_USAGE)1 << 30) +# define TPMA_X509_KEY_USAGE_digitalSignature ((TPMA_X509_KEY_USAGE)1 << 31) +// This is the initializer for a TPMA_X509_KEY_USAGE bit array. +# define TPMA_X509_KEY_USAGE_INITIALIZER(bits_at_0, \ + decipheronly, \ + encipheronly, \ + crlsign, \ + keycertsign, \ + keyagreement, \ + dataencipherment, \ + keyencipherment, \ + nonrepudiation, \ + digitalsignature) \ + (TPMA_X509_KEY_USAGE)((decipheronly << 23) + (encipheronly << 24) \ + + (crlsign << 25) + (keycertsign << 26) \ + + (keyagreement << 27) + (dataencipherment << 28) \ + + (keyencipherment << 29) + (nonrepudiation << 30) \ + + (digitalsignature << 31)) +#endif // USE_BIT_FIELD_STRUCTURES + +#define TYPE_OF_TPMA_ACT UINT32 +#define TPMA_ACT_TO_UINT32(a) (*((UINT32*)&(a))) +#define UINT32_TO_TPMA_ACT(a) (*((TPMA_ACT*)&(a))) +#define TPMA_ACT_TO_BYTE_ARRAY(i, a) \ + UINT32_TO_BYTE_ARRAY((TPMA_ACT_TO_UINT32(i)), (a)) +#define BYTE_ARRAY_TO_TPMA_ACT(i, a) \ + { \ + UINT32 x = BYTE_ARRAY_TO_UINT32(a); \ + i = UINT32_TO_TPMA_ACT(x); \ + } +#if USE_BIT_FIELD_STRUCTURES +typedef struct TPMA_ACT +{ // Table 2:40 + unsigned signaled : 1; + unsigned preserveSignaled : 1; + unsigned Reserved_bits_at_2 : 30; +} TPMA_ACT; /* Bits */ +// This is the initializer for a TPMA_ACT structure +# define TPMA_ACT_INITIALIZER(signaled, preservesignaled, bits_at_2) \ + { \ + signaled, preservesignaled, bits_at_2 \ + } +#else // USE_BIT_FIELD_STRUCTURES +// This implements Table 2:40 TPMA_ACT using bit masking +typedef UINT32 TPMA_ACT; +# define TYPE_OF_TPMA_ACT UINT32 +# define TPMA_ACT_signaled ((TPMA_ACT)1 << 0) +# define TPMA_ACT_preserveSignaled ((TPMA_ACT)1 << 1) +// This is the initializer for a TPMA_ACT bit array. +# define TPMA_ACT_INITIALIZER(signaled, preservesignaled, bits_at_2) \ + (TPMA_ACT)((signaled << 0) + (preservesignaled << 1)) +#endif // USE_BIT_FIELD_STRUCTURES + +typedef BYTE TPMI_YES_NO; // Table 2:41 /* Interface */ + +typedef TPM_HANDLE TPMI_DH_OBJECT; // Table 2:42 /* Interface */ + +typedef TPM_HANDLE TPMI_DH_PARENT; // Table 2:43 /* Interface */ + +typedef TPM_HANDLE TPMI_DH_PERSISTENT; // Table 2:44 /* Interface */ + +typedef TPM_HANDLE TPMI_DH_ENTITY; // Table 2:45 /* Interface */ + +typedef TPM_HANDLE TPMI_DH_PCR; // Table 2:46 /* Interface */ + +typedef TPM_HANDLE TPMI_SH_AUTH_SESSION; // Table 2:47 /* Interface */ + +typedef TPM_HANDLE TPMI_SH_HMAC; // Table 2:48 /* Interface */ + +typedef TPM_HANDLE TPMI_SH_POLICY; // Table 2:49 /* Interface */ + +typedef TPM_HANDLE TPMI_DH_CONTEXT; // Table 2:50 /* Interface */ + +typedef TPM_HANDLE TPMI_DH_SAVED; // Table 2:51 /* Interface */ + +typedef TPM_HANDLE TPMI_RH_HIERARCHY; // Table 2:52 /* Interface */ + +typedef TPM_HANDLE TPMI_RH_ENABLES; // Table 2:53 /* Interface */ + +typedef TPM_HANDLE TPMI_RH_HIERARCHY_AUTH; // Table 2:54 /* Interface */ + +typedef TPM_HANDLE TPMI_RH_HIERARCHY_POLICY; + +typedef TPM_HANDLE TPMI_RH_PLATFORM; // Table 2:56 /* Interface */ + +typedef TPM_HANDLE TPMI_RH_OWNER; // Table 2:57 /* Interface */ + +typedef TPM_HANDLE TPMI_RH_ENDORSEMENT; // Table 2:58 /* Interface */ + +typedef TPM_HANDLE TPMI_RH_PROVISION; // Table 2:59 /* Interface */ + +typedef TPM_HANDLE TPMI_RH_CLEAR; // Table 2:60 /* Interface */ + +typedef TPM_HANDLE TPMI_RH_NV_AUTH; // Table 2:61 /* Interface */ + +typedef TPM_HANDLE TPMI_RH_LOCKOUT; // Table 2:62 /* Interface */ + +typedef TPM_HANDLE TPMI_RH_NV_INDEX; // Table 2:63 /* Interface */ + +typedef TPM_HANDLE TPMI_RH_AC; // Table 2:64 /* Interface */ + +typedef TPM_HANDLE TPMI_RH_ACT; // Table 2:65 /* Interface */ + +typedef TPM_ALG_ID TPMI_ALG_HASH; // Table 2:66 /* Interface */ + +typedef TPM_ALG_ID TPMI_ALG_ASYM; // Table 2:67 /* Interface */ + +typedef TPM_ALG_ID TPMI_ALG_SYM; // Table 2:68 /* Interface */ + +typedef TPM_ALG_ID TPMI_ALG_SYM_OBJECT; // Table 2:69 /* Interface */ + +typedef TPM_ALG_ID TPMI_ALG_SYM_MODE; // Table 2:70 /* Interface */ + +typedef TPM_ALG_ID TPMI_ALG_KDF; // Table 2:71 /* Interface */ + +typedef TPM_ALG_ID TPMI_ALG_SIG_SCHEME; // Table 2:72 /* Interface */ + +typedef TPM_ALG_ID TPMI_ECC_KEY_EXCHANGE; // Table 2:73 /* Interface */ + +typedef TPM_ST TPMI_ST_COMMAND_TAG; // Table 2:74 /* Interface */ + +typedef TPM_ALG_ID TPMI_ALG_MAC_SCHEME; // Table 2:75 /* Interface */ + +typedef TPM_ALG_ID TPMI_ALG_CIPHER_MODE; // Table 2:76 /* Interface */ + +typedef BYTE TPMS_EMPTY; // Table 2:77 + +typedef struct +{ // Table 2:78 + TPM_ALG_ID alg; + TPMA_ALGORITHM attributes; +} TPMS_ALGORITHM_DESCRIPTION; /* Structure */ + +typedef union +{ // Table 2:79 +#if ALG_SHA1 + BYTE sha1[SHA1_DIGEST_SIZE]; +#endif // ALG_SHA1 +#if ALG_SHA256 + BYTE sha256[SHA256_DIGEST_SIZE]; +#endif // ALG_SHA256 +#if ALG_SHA384 + BYTE sha384[SHA384_DIGEST_SIZE]; +#endif // ALG_SHA384 +#if ALG_SHA512 + BYTE sha512[SHA512_DIGEST_SIZE]; +#endif // ALG_SHA512 +#if ALG_SM3_256 + BYTE sm3_256[SM3_256_DIGEST_SIZE]; +#endif // ALG_SM3_256 +#if ALG_SHA3_256 + BYTE sha3_256[SHA3_256_DIGEST_SIZE]; +#endif // ALG_SHA3_256 +#if ALG_SHA3_384 + BYTE sha3_384[SHA3_384_DIGEST_SIZE]; +#endif // ALG_SHA3_384 +#if ALG_SHA3_512 + BYTE sha3_512[SHA3_512_DIGEST_SIZE]; +#endif // ALG_SHA3_512 +} TPMU_HA; /* Structure */ + +typedef struct +{ // Table 2:80 + TPMI_ALG_HASH hashAlg; + TPMU_HA digest; +} TPMT_HA; /* Structure */ + +typedef union +{ // Table 2:81 + struct + { + UINT16 size; + BYTE buffer[sizeof(TPMU_HA)]; + } t; + TPM2B b; +} TPM2B_DIGEST; /* Structure */ + +typedef union +{ // Table 2:82 + struct + { + UINT16 size; + BYTE buffer[sizeof(TPMT_HA)]; + } t; + TPM2B b; +} TPM2B_DATA; /* Structure */ + +// Table 2:83 - Definition of Types for TPM2B_NONCE +typedef TPM2B_DIGEST TPM2B_NONCE; + +// Table 2:84 - Definition of Types for TPM2B_AUTH +typedef TPM2B_DIGEST TPM2B_AUTH; + +// Table 2:85 - Definition of Types for TPM2B_OPERAND +typedef TPM2B_DIGEST TPM2B_OPERAND; + +typedef union +{ // Table 2:86 + struct + { + UINT16 size; + BYTE buffer[1024]; + } t; + TPM2B b; +} TPM2B_EVENT; /* Structure */ + +typedef union +{ // Table 2:87 + struct + { + UINT16 size; + BYTE buffer[MAX_DIGEST_BUFFER]; + } t; + TPM2B b; +} TPM2B_MAX_BUFFER; /* Structure */ + +typedef union +{ // Table 2:88 + struct + { + UINT16 size; + BYTE buffer[MAX_NV_BUFFER_SIZE]; + } t; + TPM2B b; +} TPM2B_MAX_NV_BUFFER; /* Structure */ + +typedef union +{ // Table 2:89 + struct + { + UINT16 size; + BYTE buffer[sizeof(UINT64)]; + } t; + TPM2B b; +} TPM2B_TIMEOUT; /* Structure */ + +typedef union +{ // Table 2:90 + struct + { + UINT16 size; + BYTE buffer[MAX_SYM_BLOCK_SIZE]; + } t; + TPM2B b; +} TPM2B_IV; /* Structure */ + +typedef union +{ // Table 2:91 + TPMT_HA digest; + TPM_HANDLE handle; +} TPMU_NAME; /* Structure */ + +typedef union +{ // Table 2:92 + struct + { + UINT16 size; + BYTE name[sizeof(TPMU_NAME)]; + } t; + TPM2B b; +} TPM2B_NAME; /* Structure */ + +typedef struct +{ // Table 2:93 + UINT8 sizeofSelect; + BYTE pcrSelect[PCR_SELECT_MAX]; +} TPMS_PCR_SELECT; /* Structure */ + +typedef struct +{ // Table 2:94 + TPMI_ALG_HASH hash; + UINT8 sizeofSelect; + BYTE pcrSelect[PCR_SELECT_MAX]; +} TPMS_PCR_SELECTION; /* Structure */ + +typedef struct +{ // Table 2:97 + TPM_ST tag; + TPMI_RH_HIERARCHY hierarchy; + TPM2B_DIGEST digest; +} TPMT_TK_CREATION; /* Structure */ + +typedef struct +{ // Table 2:98 + TPM_ST tag; + TPMI_RH_HIERARCHY hierarchy; + TPM2B_DIGEST digest; +} TPMT_TK_VERIFIED; /* Structure */ + +typedef struct +{ // Table 2:99 + TPM_ST tag; + TPMI_RH_HIERARCHY hierarchy; + TPM2B_DIGEST digest; +} TPMT_TK_AUTH; /* Structure */ + +typedef struct +{ // Table 2:100 + TPM_ST tag; + TPMI_RH_HIERARCHY hierarchy; + TPM2B_DIGEST digest; +} TPMT_TK_HASHCHECK; /* Structure */ + +typedef struct +{ // Table 2:101 + TPM_ALG_ID alg; + TPMA_ALGORITHM algProperties; +} TPMS_ALG_PROPERTY; /* Structure */ + +typedef struct +{ // Table 2:102 + TPM_PT property; + UINT32 value; +} TPMS_TAGGED_PROPERTY; /* Structure */ + +typedef struct +{ // Table 2:103 + TPM_PT_PCR tag; + UINT8 sizeofSelect; + BYTE pcrSelect[PCR_SELECT_MAX]; +} TPMS_TAGGED_PCR_SELECT; /* Structure */ + +typedef struct +{ // Table 2:104 + TPM_HANDLE handle; + TPMT_HA policyHash; +} TPMS_TAGGED_POLICY; /* Structure */ + +typedef struct +{ // Table 2:105 + TPM_HANDLE handle; + UINT32 timeout; + TPMA_ACT attributes; +} TPMS_ACT_DATA; /* Structure */ + +typedef struct +{ // Table 2:106 + UINT32 count; + TPM_CC commandCodes[MAX_CAP_CC]; +} TPML_CC; /* Structure */ + +typedef struct +{ // Table 2:107 + UINT32 count; + TPMA_CC commandAttributes[MAX_CAP_CC]; +} TPML_CCA; /* Structure */ + +typedef struct +{ // Table 2:108 + UINT32 count; + TPM_ALG_ID algorithms[MAX_ALG_LIST_SIZE]; +} TPML_ALG; /* Structure */ + +typedef struct +{ // Table 2:109 + UINT32 count; + TPM_HANDLE handle[MAX_CAP_HANDLES]; +} TPML_HANDLE; /* Structure */ + +typedef struct +{ // Table 2:110 + UINT32 count; + TPM2B_DIGEST digests[8]; +} TPML_DIGEST; /* Structure */ + +typedef struct +{ // Table 2:111 + UINT32 count; + TPMT_HA digests[HASH_COUNT]; +} TPML_DIGEST_VALUES; /* Structure */ + +typedef struct +{ // Table 2:112 + UINT32 count; + TPMS_PCR_SELECTION pcrSelections[HASH_COUNT]; +} TPML_PCR_SELECTION; /* Structure */ + +typedef struct +{ // Table 2:113 + UINT32 count; + TPMS_ALG_PROPERTY algProperties[MAX_CAP_ALGS]; +} TPML_ALG_PROPERTY; /* Structure */ + +typedef struct +{ // Table 2:114 + UINT32 count; + TPMS_TAGGED_PROPERTY tpmProperty[MAX_TPM_PROPERTIES]; +} TPML_TAGGED_TPM_PROPERTY; /* Structure */ + +typedef struct +{ // Table 2:115 + UINT32 count; + TPMS_TAGGED_PCR_SELECT pcrProperty[MAX_PCR_PROPERTIES]; +} TPML_TAGGED_PCR_PROPERTY; /* Structure */ + +typedef struct +{ // Table 2:116 + UINT32 count; + TPM_ECC_CURVE eccCurves[MAX_ECC_CURVES]; +} TPML_ECC_CURVE; /* Structure */ + +typedef struct +{ // Table 2:117 + UINT32 count; + TPMS_TAGGED_POLICY policies[MAX_TAGGED_POLICIES]; +} TPML_TAGGED_POLICY; /* Structure */ + +typedef struct +{ // Table 2:118 + UINT32 count; + TPMS_ACT_DATA actData[MAX_ACT_DATA]; +} TPML_ACT_DATA; /* Structure */ + +typedef union +{ // Table 2:119 + TPML_ALG_PROPERTY algorithms; + TPML_HANDLE handles; + TPML_CCA command; + TPML_CC ppCommands; + TPML_CC auditCommands; + TPML_PCR_SELECTION assignedPCR; + TPML_TAGGED_TPM_PROPERTY tpmProperties; + TPML_TAGGED_PCR_PROPERTY pcrProperties; +#if ALG_ECC + TPML_ECC_CURVE eccCurves; +#endif // ALG_ECC + TPML_TAGGED_POLICY authPolicies; + TPML_ACT_DATA actData; +} TPMU_CAPABILITIES; /* Structure */ + +typedef struct +{ // Table 2:120 + TPM_CAP capability; + TPMU_CAPABILITIES data; +} TPMS_CAPABILITY_DATA; /* Structure */ + +typedef struct +{ // Table 2:121 + UINT64 clock; + UINT32 resetCount; + UINT32 restartCount; + TPMI_YES_NO safe; +} TPMS_CLOCK_INFO; /* Structure */ + +typedef struct +{ // Table 2:122 + UINT64 time; + TPMS_CLOCK_INFO clockInfo; +} TPMS_TIME_INFO; /* Structure */ + +typedef struct +{ // Table 2:123 + TPMS_TIME_INFO time; + UINT64 firmwareVersion; +} TPMS_TIME_ATTEST_INFO; /* Structure */ + +typedef struct +{ // Table 2:124 + TPM2B_NAME name; + TPM2B_NAME qualifiedName; +} TPMS_CERTIFY_INFO; /* Structure */ + +typedef struct +{ // Table 2:125 + TPML_PCR_SELECTION pcrSelect; + TPM2B_DIGEST pcrDigest; +} TPMS_QUOTE_INFO; /* Structure */ + +typedef struct +{ // Table 2:126 + UINT64 auditCounter; + TPM_ALG_ID digestAlg; + TPM2B_DIGEST auditDigest; + TPM2B_DIGEST commandDigest; +} TPMS_COMMAND_AUDIT_INFO; /* Structure */ + +typedef struct +{ // Table 2:127 + TPMI_YES_NO exclusiveSession; + TPM2B_DIGEST sessionDigest; +} TPMS_SESSION_AUDIT_INFO; /* Structure */ + +typedef struct +{ // Table 2:128 + TPM2B_NAME objectName; + TPM2B_DIGEST creationHash; +} TPMS_CREATION_INFO; /* Structure */ + +typedef struct +{ // Table 2:129 + TPM2B_NAME indexName; + UINT16 offset; + TPM2B_MAX_NV_BUFFER nvContents; +} TPMS_NV_CERTIFY_INFO; /* Structure */ + +typedef struct +{ // Table 2:130 + TPM2B_NAME indexName; + TPM2B_DIGEST nvDigest; +} TPMS_NV_DIGEST_CERTIFY_INFO; /* Structure */ + +typedef TPM_ST TPMI_ST_ATTEST; // Table 2:131 /* Interface */ + +typedef union +{ // Table 2:132 + TPMS_CERTIFY_INFO certify; + TPMS_CREATION_INFO creation; + TPMS_QUOTE_INFO quote; + TPMS_COMMAND_AUDIT_INFO commandAudit; + TPMS_SESSION_AUDIT_INFO sessionAudit; + TPMS_TIME_ATTEST_INFO time; + TPMS_NV_CERTIFY_INFO nv; + TPMS_NV_DIGEST_CERTIFY_INFO nvDigest; +} TPMU_ATTEST; /* Structure */ + +typedef struct +{ // Table 2:133 + TPM_CONSTANTS32 magic; + TPMI_ST_ATTEST type; + TPM2B_NAME qualifiedSigner; + TPM2B_DATA extraData; + TPMS_CLOCK_INFO clockInfo; + UINT64 firmwareVersion; + TPMU_ATTEST attested; +} TPMS_ATTEST; /* Structure */ + +typedef union +{ // Table 2:134 + struct + { + UINT16 size; + BYTE attestationData[sizeof(TPMS_ATTEST)]; + } t; + TPM2B b; +} TPM2B_ATTEST; /* Structure */ + +typedef struct +{ // Table 2:135 + TPMI_SH_AUTH_SESSION sessionHandle; + TPM2B_NONCE nonce; + TPMA_SESSION sessionAttributes; + TPM2B_AUTH hmac; +} TPMS_AUTH_COMMAND; /* Structure */ + +typedef struct +{ // Table 2:136 + TPM2B_NONCE nonce; + TPMA_SESSION sessionAttributes; + TPM2B_AUTH hmac; +} TPMS_AUTH_RESPONSE; /* Structure */ + +typedef TPM_KEY_BITS TPMI_TDES_KEY_BITS; // Table 2:137 /* Interface */ + +typedef TPM_KEY_BITS TPMI_AES_KEY_BITS; // Table 2:137 /* Interface */ + +typedef TPM_KEY_BITS TPMI_SM4_KEY_BITS; // Table 2:137 /* Interface */ + +typedef TPM_KEY_BITS TPMI_CAMELLIA_KEY_BITS; // Table 2:137 /* Interface */ + +typedef union +{ // Table 2:138 +#if ALG_TDES + TPMI_TDES_KEY_BITS tdes; +#endif // ALG_TDES +#if ALG_AES + TPMI_AES_KEY_BITS aes; +#endif // ALG_AES +#if ALG_SM4 + TPMI_SM4_KEY_BITS sm4; +#endif // ALG_SM4 +#if ALG_CAMELLIA + TPMI_CAMELLIA_KEY_BITS camellia; +#endif // ALG_CAMELLIA + TPM_KEY_BITS sym; +#if ALG_XOR + TPMI_ALG_HASH xor ; +#endif // ALG_XOR +} TPMU_SYM_KEY_BITS; /* Structure */ + +typedef union +{ // Table 2:139 +#if ALG_TDES + TPMI_ALG_SYM_MODE tdes; +#endif // ALG_TDES +#if ALG_AES + TPMI_ALG_SYM_MODE aes; +#endif // ALG_AES +#if ALG_SM4 + TPMI_ALG_SYM_MODE sm4; +#endif // ALG_SM4 +#if ALG_CAMELLIA + TPMI_ALG_SYM_MODE camellia; +#endif // ALG_CAMELLIA + TPMI_ALG_SYM_MODE sym; +} TPMU_SYM_MODE; /* Structure */ + +typedef struct +{ // Table 2:141 + TPMI_ALG_SYM algorithm; + TPMU_SYM_KEY_BITS keyBits; + TPMU_SYM_MODE mode; +} TPMT_SYM_DEF; /* Structure */ + +typedef struct +{ // Table 2:142 + TPMI_ALG_SYM_OBJECT algorithm; + TPMU_SYM_KEY_BITS keyBits; + TPMU_SYM_MODE mode; +} TPMT_SYM_DEF_OBJECT; /* Structure */ + +typedef union +{ // Table 2:143 + struct + { + UINT16 size; + BYTE buffer[MAX_SYM_KEY_BYTES]; + } t; + TPM2B b; +} TPM2B_SYM_KEY; /* Structure */ + +typedef struct +{ // Table 2:144 + TPMT_SYM_DEF_OBJECT sym; +} TPMS_SYMCIPHER_PARMS; /* Structure */ + +typedef union +{ // Table 2:145 + struct + { + UINT16 size; + BYTE buffer[LABEL_MAX_BUFFER]; + } t; + TPM2B b; +} TPM2B_LABEL; /* Structure */ + +typedef struct +{ // Table 2:146 + TPM2B_LABEL label; + TPM2B_LABEL context; +} TPMS_DERIVE; /* Structure */ + +typedef union +{ // Table 2:147 + struct + { + UINT16 size; + BYTE buffer[sizeof(TPMS_DERIVE)]; + } t; + TPM2B b; +} TPM2B_DERIVE; /* Structure */ + +typedef union +{ // Table 2:148 + BYTE create[MAX_SYM_DATA]; + TPMS_DERIVE derive; +} TPMU_SENSITIVE_CREATE; /* Structure */ + +typedef union +{ // Table 2:149 + struct + { + UINT16 size; + BYTE buffer[sizeof(TPMU_SENSITIVE_CREATE)]; + } t; + TPM2B b; +} TPM2B_SENSITIVE_DATA; /* Structure */ + +typedef struct +{ // Table 2:150 + TPM2B_AUTH userAuth; + TPM2B_SENSITIVE_DATA data; +} TPMS_SENSITIVE_CREATE; /* Structure */ + +typedef struct +{ // Table 2:151 + UINT16 size; + TPMS_SENSITIVE_CREATE sensitive; +} TPM2B_SENSITIVE_CREATE; /* Structure */ + +typedef struct +{ // Table 2:152 + TPMI_ALG_HASH hashAlg; +} TPMS_SCHEME_HASH; /* Structure */ + +typedef struct +{ // Table 2:153 + TPMI_ALG_HASH hashAlg; + UINT16 count; +} TPMS_SCHEME_ECDAA; /* Structure */ + +typedef TPM_ALG_ID TPMI_ALG_KEYEDHASH_SCHEME; + +// Table 2:155 - Definition of Types for HMAC_SIG_SCHEME +typedef TPMS_SCHEME_HASH TPMS_SCHEME_HMAC; + +typedef struct +{ // Table 2:156 + TPMI_ALG_HASH hashAlg; + TPMI_ALG_KDF kdf; +} TPMS_SCHEME_XOR; /* Structure */ + +typedef union +{ // Table 2:157 +#if ALG_HMAC + TPMS_SCHEME_HMAC hmac; +#endif // ALG_HMAC +#if ALG_XOR + TPMS_SCHEME_XOR xor ; +#endif // ALG_XOR +} TPMU_SCHEME_KEYEDHASH; /* Structure */ + +typedef struct +{ // Table 2:158 + TPMI_ALG_KEYEDHASH_SCHEME scheme; + TPMU_SCHEME_KEYEDHASH details; +} TPMT_KEYEDHASH_SCHEME; /* Structure */ + +// Table 2:159 - Definition of Types for RSA Signature Schemes +typedef TPMS_SCHEME_HASH TPMS_SIG_SCHEME_RSASSA; +typedef TPMS_SCHEME_HASH TPMS_SIG_SCHEME_RSAPSS; + +// Table 2:160 - Definition of Types for ECC Signature Schemes +typedef TPMS_SCHEME_HASH TPMS_SIG_SCHEME_ECDSA; +typedef TPMS_SCHEME_HASH TPMS_SIG_SCHEME_SM2; +typedef TPMS_SCHEME_HASH TPMS_SIG_SCHEME_ECSCHNORR; +typedef TPMS_SCHEME_ECDAA TPMS_SIG_SCHEME_ECDAA; + +typedef union +{ // Table 2:161 +#if ALG_ECC + TPMS_SIG_SCHEME_ECDAA ecdaa; +#endif // ALG_ECC +#if ALG_RSASSA + TPMS_SIG_SCHEME_RSASSA rsassa; +#endif // ALG_RSASSA +#if ALG_RSAPSS + TPMS_SIG_SCHEME_RSAPSS rsapss; +#endif // ALG_RSAPSS +#if ALG_ECDSA + TPMS_SIG_SCHEME_ECDSA ecdsa; +#endif // ALG_ECDSA +#if ALG_SM2 + TPMS_SIG_SCHEME_SM2 sm2; +#endif // ALG_SM2 +#if ALG_ECSCHNORR + TPMS_SIG_SCHEME_ECSCHNORR ecschnorr; +#endif // ALG_ECSCHNORR +#if ALG_HMAC + TPMS_SCHEME_HMAC hmac; +#endif // ALG_HMAC + TPMS_SCHEME_HASH any; +} TPMU_SIG_SCHEME; /* Structure */ + +typedef struct +{ // Table 2:162 + TPMI_ALG_SIG_SCHEME scheme; + TPMU_SIG_SCHEME details; +} TPMT_SIG_SCHEME; /* Structure */ + +// Table 2:163 - Definition of Types for Encryption Schemes +typedef TPMS_SCHEME_HASH TPMS_ENC_SCHEME_OAEP; +typedef TPMS_EMPTY TPMS_ENC_SCHEME_RSAES; + +// Table 2:164 - Definition of Types for ECC Key Exchange +typedef TPMS_SCHEME_HASH TPMS_KEY_SCHEME_ECDH; +typedef TPMS_SCHEME_HASH TPMS_KEY_SCHEME_ECMQV; + +// Table 2:165 - Definition of Types for KDF Schemes +typedef TPMS_SCHEME_HASH TPMS_KDF_SCHEME_MGF1; +typedef TPMS_SCHEME_HASH TPMS_KDF_SCHEME_KDF1_SP800_56A; +typedef TPMS_SCHEME_HASH TPMS_KDF_SCHEME_KDF2; +typedef TPMS_SCHEME_HASH TPMS_KDF_SCHEME_KDF1_SP800_108; + +typedef union +{ // Table 2:166 +#if ALG_MGF1 + TPMS_KDF_SCHEME_MGF1 mgf1; +#endif // ALG_MGF1 +#if ALG_KDF1_SP800_56A + TPMS_KDF_SCHEME_KDF1_SP800_56A kdf1_sp800_56a; +#endif // ALG_KDF1_SP800_56A +#if ALG_KDF2 + TPMS_KDF_SCHEME_KDF2 kdf2; +#endif // ALG_KDF2 +#if ALG_KDF1_SP800_108 + TPMS_KDF_SCHEME_KDF1_SP800_108 kdf1_sp800_108; +#endif // ALG_KDF1_SP800_108 + TPMS_SCHEME_HASH anyKdf; +} TPMU_KDF_SCHEME; /* Structure */ + +typedef struct +{ // Table 2:167 + TPMI_ALG_KDF scheme; + TPMU_KDF_SCHEME details; +} TPMT_KDF_SCHEME; /* Structure */ + +typedef TPM_ALG_ID TPMI_ALG_ASYM_SCHEME; // Table 2:168 /* Interface */ + +typedef union +{ // Table 2:169 +#if ALG_ECDH + TPMS_KEY_SCHEME_ECDH ecdh; +#endif // ALG_ECDH +#if ALG_ECMQV + TPMS_KEY_SCHEME_ECMQV ecmqv; +#endif // ALG_ECMQV +#if ALG_ECC + TPMS_SIG_SCHEME_ECDAA ecdaa; +#endif // ALG_ECC +#if ALG_RSASSA + TPMS_SIG_SCHEME_RSASSA rsassa; +#endif // ALG_RSASSA +#if ALG_RSAPSS + TPMS_SIG_SCHEME_RSAPSS rsapss; +#endif // ALG_RSAPSS +#if ALG_ECDSA + TPMS_SIG_SCHEME_ECDSA ecdsa; +#endif // ALG_ECDSA +#if ALG_SM2 + TPMS_SIG_SCHEME_SM2 sm2; +#endif // ALG_SM2 +#if ALG_ECSCHNORR + TPMS_SIG_SCHEME_ECSCHNORR ecschnorr; +#endif // ALG_ECSCHNORR +#if ALG_RSAES + TPMS_ENC_SCHEME_RSAES rsaes; +#endif // ALG_RSAES +#if ALG_OAEP + TPMS_ENC_SCHEME_OAEP oaep; +#endif // ALG_OAEP + TPMS_SCHEME_HASH anySig; +} TPMU_ASYM_SCHEME; /* Structure */ + +typedef struct +{ // Table 2:170 + TPMI_ALG_ASYM_SCHEME scheme; + TPMU_ASYM_SCHEME details; +} TPMT_ASYM_SCHEME; /* Structure */ + +typedef TPM_ALG_ID TPMI_ALG_RSA_SCHEME; // Table 2:171 /* Interface */ + +typedef struct +{ // Table 2:172 + TPMI_ALG_RSA_SCHEME scheme; + TPMU_ASYM_SCHEME details; +} TPMT_RSA_SCHEME; /* Structure */ + +typedef TPM_ALG_ID TPMI_ALG_RSA_DECRYPT; // Table 2:173 /* Interface */ + +typedef struct +{ // Table 2:174 + TPMI_ALG_RSA_DECRYPT scheme; + TPMU_ASYM_SCHEME details; +} TPMT_RSA_DECRYPT; /* Structure */ + +typedef union +{ // Table 2:175 + struct + { + UINT16 size; + BYTE buffer[MAX_RSA_KEY_BYTES]; + } t; + TPM2B b; +} TPM2B_PUBLIC_KEY_RSA; /* Structure */ + +typedef TPM_KEY_BITS TPMI_RSA_KEY_BITS; // Table 2:176 /* Interface */ + +typedef union +{ // Table 2:177 + struct + { + UINT16 size; + BYTE buffer[RSA_PRIVATE_SIZE]; + } t; + TPM2B b; +} TPM2B_PRIVATE_KEY_RSA; /* Structure */ + +typedef union +{ // Table 2:178 + struct + { + UINT16 size; + BYTE buffer[MAX_ECC_KEY_BYTES]; + } t; + TPM2B b; +} TPM2B_ECC_PARAMETER; /* Structure */ + +typedef struct +{ // Table 2:179 + TPM2B_ECC_PARAMETER x; + TPM2B_ECC_PARAMETER y; +} TPMS_ECC_POINT; /* Structure */ + +typedef struct +{ // Table 2:180 + UINT16 size; + TPMS_ECC_POINT point; +} TPM2B_ECC_POINT; /* Structure */ + +typedef TPM_ALG_ID TPMI_ALG_ECC_SCHEME; // Table 2:181 /* Interface */ + +typedef TPM_ECC_CURVE TPMI_ECC_CURVE; // Table 2:182 /* Interface */ + +typedef struct +{ // Table 2:183 + TPMI_ALG_ECC_SCHEME scheme; + TPMU_ASYM_SCHEME details; +} TPMT_ECC_SCHEME; /* Structure */ + +typedef struct +{ // Table 2:184 + TPM_ECC_CURVE curveID; + UINT16 keySize; + TPMT_KDF_SCHEME kdf; + TPMT_ECC_SCHEME sign; + TPM2B_ECC_PARAMETER p; + TPM2B_ECC_PARAMETER a; + TPM2B_ECC_PARAMETER b; + TPM2B_ECC_PARAMETER gX; + TPM2B_ECC_PARAMETER gY; + TPM2B_ECC_PARAMETER n; + TPM2B_ECC_PARAMETER h; +} TPMS_ALGORITHM_DETAIL_ECC; /* Structure */ + +typedef struct +{ // Table 2:185 + TPMI_ALG_HASH hash; + TPM2B_PUBLIC_KEY_RSA sig; +} TPMS_SIGNATURE_RSA; /* Structure */ + +// Table 2:186 - Definition of Types for Signature +typedef TPMS_SIGNATURE_RSA TPMS_SIGNATURE_RSASSA; +typedef TPMS_SIGNATURE_RSA TPMS_SIGNATURE_RSAPSS; + +typedef struct +{ // Table 2:187 + TPMI_ALG_HASH hash; + TPM2B_ECC_PARAMETER signatureR; + TPM2B_ECC_PARAMETER signatureS; +} TPMS_SIGNATURE_ECC; /* Structure */ + +// Table 2:188 - Definition of Types for TPMS_SIGNATURE_ECC +typedef TPMS_SIGNATURE_ECC TPMS_SIGNATURE_ECDAA; +typedef TPMS_SIGNATURE_ECC TPMS_SIGNATURE_ECDSA; +typedef TPMS_SIGNATURE_ECC TPMS_SIGNATURE_SM2; +typedef TPMS_SIGNATURE_ECC TPMS_SIGNATURE_ECSCHNORR; + +typedef union +{ // Table 2:189 +#if ALG_ECC + TPMS_SIGNATURE_ECDAA ecdaa; +#endif // ALG_ECC +#if ALG_RSA + TPMS_SIGNATURE_RSASSA rsassa; +#endif // ALG_RSA +#if ALG_RSA + TPMS_SIGNATURE_RSAPSS rsapss; +#endif // ALG_RSA +#if ALG_ECC + TPMS_SIGNATURE_ECDSA ecdsa; +#endif // ALG_ECC +#if ALG_ECC + TPMS_SIGNATURE_SM2 sm2; +#endif // ALG_ECC +#if ALG_ECC + TPMS_SIGNATURE_ECSCHNORR ecschnorr; +#endif // ALG_ECC +#if ALG_HMAC + TPMT_HA hmac; +#endif // ALG_HMAC + TPMS_SCHEME_HASH any; +} TPMU_SIGNATURE; /* Structure */ + +typedef struct +{ // Table 2:190 + TPMI_ALG_SIG_SCHEME sigAlg; + TPMU_SIGNATURE signature; +} TPMT_SIGNATURE; /* Structure */ + +typedef union +{ // Table 2:191 +#if ALG_ECC + BYTE ecc[sizeof(TPMS_ECC_POINT)]; +#endif // ALG_ECC +#if ALG_RSA + BYTE rsa[MAX_RSA_KEY_BYTES]; +#endif // ALG_RSA +#if ALG_SYMCIPHER + BYTE symmetric[sizeof(TPM2B_DIGEST)]; +#endif // ALG_SYMCIPHER +#if ALG_KEYEDHASH + BYTE keyedHash[sizeof(TPM2B_DIGEST)]; +#endif // ALG_KEYEDHASH +} TPMU_ENCRYPTED_SECRET; /* Structure */ + +typedef union +{ // Table 2:192 + struct + { + UINT16 size; + BYTE secret[sizeof(TPMU_ENCRYPTED_SECRET)]; + } t; + TPM2B b; +} TPM2B_ENCRYPTED_SECRET; /* Structure */ + +typedef TPM_ALG_ID TPMI_ALG_PUBLIC; // Table 2:193 /* Interface */ + +typedef union +{ // Table 2:194 +#if ALG_KEYEDHASH + TPM2B_DIGEST keyedHash; +#endif // ALG_KEYEDHASH +#if ALG_SYMCIPHER + TPM2B_DIGEST sym; +#endif // ALG_SYMCIPHER +#if ALG_RSA + TPM2B_PUBLIC_KEY_RSA rsa; +#endif // ALG_RSA +#if ALG_ECC + TPMS_ECC_POINT ecc; +#endif // ALG_ECC + TPMS_DERIVE derive; +} TPMU_PUBLIC_ID; /* Structure */ + +typedef struct +{ // Table 2:195 + TPMT_KEYEDHASH_SCHEME scheme; +} TPMS_KEYEDHASH_PARMS; /* Structure */ + +typedef struct +{ // Table 2:196 + TPMT_SYM_DEF_OBJECT symmetric; + TPMT_ASYM_SCHEME scheme; +} TPMS_ASYM_PARMS; /* Structure */ + +typedef struct +{ // Table 2:197 + TPMT_SYM_DEF_OBJECT symmetric; + TPMT_RSA_SCHEME scheme; + TPMI_RSA_KEY_BITS keyBits; + UINT32 exponent; +} TPMS_RSA_PARMS; /* Structure */ + +typedef struct +{ // Table 2:198 + TPMT_SYM_DEF_OBJECT symmetric; + TPMT_ECC_SCHEME scheme; + TPMI_ECC_CURVE curveID; + TPMT_KDF_SCHEME kdf; +} TPMS_ECC_PARMS; /* Structure */ + +typedef union +{ // Table 2:199 +#if ALG_KEYEDHASH + TPMS_KEYEDHASH_PARMS keyedHashDetail; +#endif // ALG_KEYEDHASH +#if ALG_SYMCIPHER + TPMS_SYMCIPHER_PARMS symDetail; +#endif // ALG_SYMCIPHER +#if ALG_RSA + TPMS_RSA_PARMS rsaDetail; +#endif // ALG_RSA +#if ALG_ECC + TPMS_ECC_PARMS eccDetail; +#endif // ALG_ECC + TPMS_ASYM_PARMS asymDetail; +} TPMU_PUBLIC_PARMS; /* Structure */ + +typedef struct +{ // Table 2:200 + TPMI_ALG_PUBLIC type; + TPMU_PUBLIC_PARMS parameters; +} TPMT_PUBLIC_PARMS; /* Structure */ + +typedef struct +{ // Table 2:201 + TPMI_ALG_PUBLIC type; + TPMI_ALG_HASH nameAlg; + TPMA_OBJECT objectAttributes; + TPM2B_DIGEST authPolicy; + TPMU_PUBLIC_PARMS parameters; + TPMU_PUBLIC_ID unique; +} TPMT_PUBLIC; /* Structure */ + +typedef struct +{ // Table 2:202 + UINT16 size; + TPMT_PUBLIC publicArea; +} TPM2B_PUBLIC; /* Structure */ + +typedef union +{ // Table 2:203 + struct + { + UINT16 size; + BYTE buffer[sizeof(TPMT_PUBLIC)]; + } t; + TPM2B b; +} TPM2B_TEMPLATE; /* Structure */ + +typedef union +{ // Table 2:204 + struct + { + UINT16 size; + BYTE buffer[PRIVATE_VENDOR_SPECIFIC_BYTES]; + } t; + TPM2B b; +} TPM2B_PRIVATE_VENDOR_SPECIFIC; /* Structure */ + +typedef union +{ // Table 2:205 +#if ALG_RSA + TPM2B_PRIVATE_KEY_RSA rsa; +#endif // ALG_RSA +#if ALG_ECC + TPM2B_ECC_PARAMETER ecc; +#endif // ALG_ECC +#if ALG_KEYEDHASH + TPM2B_SENSITIVE_DATA bits; +#endif // ALG_KEYEDHASH +#if ALG_SYMCIPHER + TPM2B_SYM_KEY sym; +#endif // ALG_SYMCIPHER + TPM2B_PRIVATE_VENDOR_SPECIFIC any; +} TPMU_SENSITIVE_COMPOSITE; /* Structure */ + +typedef struct +{ // Table 2:206 + TPMI_ALG_PUBLIC sensitiveType; + TPM2B_AUTH authValue; + TPM2B_DIGEST seedValue; + TPMU_SENSITIVE_COMPOSITE sensitive; +} TPMT_SENSITIVE; /* Structure */ + +typedef struct +{ // Table 2:207 + UINT16 size; + TPMT_SENSITIVE sensitiveArea; +} TPM2B_SENSITIVE; /* Structure */ + +typedef struct +{ // Table 2:208 + TPM2B_DIGEST integrityOuter; + TPM2B_DIGEST integrityInner; + TPM2B_SENSITIVE sensitive; +} _PRIVATE; /* Structure */ + +typedef union +{ // Table 2:209 + struct + { + UINT16 size; + BYTE buffer[sizeof(_PRIVATE)]; + } t; + TPM2B b; +} TPM2B_PRIVATE; /* Structure */ + +typedef struct +{ // Table 2:210 + TPM2B_DIGEST integrityHMAC; + TPM2B_DIGEST encIdentity; +} TPMS_ID_OBJECT; /* Structure */ + +typedef union +{ // Table 2:211 + struct + { + UINT16 size; + BYTE credential[sizeof(TPMS_ID_OBJECT)]; + } t; + TPM2B b; +} TPM2B_ID_OBJECT; /* Structure */ + +#define TYPE_OF_TPM_NV_INDEX UINT32 +#define TPM_NV_INDEX_TO_UINT32(a) (*((UINT32*)&(a))) +#define UINT32_TO_TPM_NV_INDEX(a) (*((TPM_NV_INDEX*)&(a))) +#define TPM_NV_INDEX_TO_BYTE_ARRAY(i, a) \ + UINT32_TO_BYTE_ARRAY((TPM_NV_INDEX_TO_UINT32(i)), (a)) +#define BYTE_ARRAY_TO_TPM_NV_INDEX(i, a) \ + { \ + UINT32 x = BYTE_ARRAY_TO_UINT32(a); \ + i = UINT32_TO_TPM_NV_INDEX(x); \ + } +#if USE_BIT_FIELD_STRUCTURES +typedef struct TPM_NV_INDEX +{ // Table 2:212 + unsigned index : 24; + unsigned RH_NV : 8; +} TPM_NV_INDEX; /* Bits */ +// This is the initializer for a TPM_NV_INDEX structure +# define TPM_NV_INDEX_INITIALIZER(index, rh_nv) \ + { \ + index, rh_nv \ + } +#else // USE_BIT_FIELD_STRUCTURES +// This implements Table 2:212 TPM_NV_INDEX using bit masking +typedef UINT32 TPM_NV_INDEX; +# define TYPE_OF_TPM_NV_INDEX UINT32 +# define TPM_NV_INDEX_index_SHIFT 0 +# define TPM_NV_INDEX_index ((TPM_NV_INDEX)0xffffff << 0) +# define TPM_NV_INDEX_RH_NV_SHIFT 24 +# define TPM_NV_INDEX_RH_NV ((TPM_NV_INDEX)0xff << 24) +// This is the initializer for a TPM_NV_INDEX bit array. +# define TPM_NV_INDEX_INITIALIZER(index, rh_nv) \ + (TPM_NV_INDEX)((index << 0) + (rh_nv << 24)) +#endif // USE_BIT_FIELD_STRUCTURES + +// Table 2:213 - Definition of TPM_NT Constants +typedef UINT32 TPM_NT; +#define TYPE_OF_TPM_NT UINT32 +#define TPM_NT_ORDINARY (TPM_NT)(0x0) +#define TPM_NT_COUNTER (TPM_NT)(0x1) +#define TPM_NT_BITS (TPM_NT)(0x2) +#define TPM_NT_EXTEND (TPM_NT)(0x4) +#define TPM_NT_PIN_FAIL (TPM_NT)(0x8) +#define TPM_NT_PIN_PASS (TPM_NT)(0x9) + +typedef struct +{ // Table 2:214 + UINT32 pinCount; + UINT32 pinLimit; +} TPMS_NV_PIN_COUNTER_PARAMETERS; /* Structure */ + +#define TYPE_OF_TPMA_NV UINT32 +#define TPMA_NV_TO_UINT32(a) (*((UINT32*)&(a))) +#define UINT32_TO_TPMA_NV(a) (*((TPMA_NV*)&(a))) +#define TPMA_NV_TO_BYTE_ARRAY(i, a) UINT32_TO_BYTE_ARRAY((TPMA_NV_TO_UINT32(i)), (a)) +#define BYTE_ARRAY_TO_TPMA_NV(i, a) \ + { \ + UINT32 x = BYTE_ARRAY_TO_UINT32(a); \ + i = UINT32_TO_TPMA_NV(x); \ + } +#if USE_BIT_FIELD_STRUCTURES +typedef struct TPMA_NV +{ // Table 2:215 + unsigned PPWRITE : 1; + unsigned OWNERWRITE : 1; + unsigned AUTHWRITE : 1; + unsigned POLICYWRITE : 1; + unsigned TPM_NT : 4; + unsigned Reserved_bits_at_8 : 2; + unsigned POLICY_DELETE : 1; + unsigned WRITELOCKED : 1; + unsigned WRITEALL : 1; + unsigned WRITEDEFINE : 1; + unsigned WRITE_STCLEAR : 1; + unsigned GLOBALLOCK : 1; + unsigned PPREAD : 1; + unsigned OWNERREAD : 1; + unsigned AUTHREAD : 1; + unsigned POLICYREAD : 1; + unsigned Reserved_bits_at_20 : 5; + unsigned NO_DA : 1; + unsigned ORDERLY : 1; + unsigned CLEAR_STCLEAR : 1; + unsigned READLOCKED : 1; + unsigned WRITTEN : 1; + unsigned PLATFORMCREATE : 1; + unsigned READ_STCLEAR : 1; +} TPMA_NV; /* Bits */ +// This is the initializer for a TPMA_NV structure +# define TPMA_NV_INITIALIZER(ppwrite, \ + ownerwrite, \ + authwrite, \ + policywrite, \ + tpm_nt, \ + bits_at_8, \ + policy_delete, \ + writelocked, \ + writeall, \ + writedefine, \ + write_stclear, \ + globallock, \ + ppread, \ + ownerread, \ + authread, \ + policyread, \ + bits_at_20, \ + no_da, \ + orderly, \ + clear_stclear, \ + readlocked, \ + written, \ + platformcreate, \ + read_stclear) \ + { \ + ppwrite, ownerwrite, authwrite, policywrite, tpm_nt, bits_at_8, policy_delete, \ + writelocked, writeall, writedefine, write_stclear, globallock, ppread, \ + ownerread, authread, policyread, bits_at_20, no_da, orderly, \ + clear_stclear, readlocked, written, platformcreate, read_stclear \ + } +#else // USE_BIT_FIELD_STRUCTURES +// This implements Table 2:215 TPMA_NV using bit masking +typedef UINT32 TPMA_NV; +# define TYPE_OF_TPMA_NV UINT32 +# define TPMA_NV_PPWRITE ((TPMA_NV)1 << 0) +# define TPMA_NV_OWNERWRITE ((TPMA_NV)1 << 1) +# define TPMA_NV_AUTHWRITE ((TPMA_NV)1 << 2) +# define TPMA_NV_POLICYWRITE ((TPMA_NV)1 << 3) +# define TPMA_NV_TPM_NT_SHIFT 4 +# define TPMA_NV_TPM_NT ((TPMA_NV)0xf << 4) +# define TPMA_NV_POLICY_DELETE ((TPMA_NV)1 << 10) +# define TPMA_NV_WRITELOCKED ((TPMA_NV)1 << 11) +# define TPMA_NV_WRITEALL ((TPMA_NV)1 << 12) +# define TPMA_NV_WRITEDEFINE ((TPMA_NV)1 << 13) +# define TPMA_NV_WRITE_STCLEAR ((TPMA_NV)1 << 14) +# define TPMA_NV_GLOBALLOCK ((TPMA_NV)1 << 15) +# define TPMA_NV_PPREAD ((TPMA_NV)1 << 16) +# define TPMA_NV_OWNERREAD ((TPMA_NV)1 << 17) +# define TPMA_NV_AUTHREAD ((TPMA_NV)1 << 18) +# define TPMA_NV_POLICYREAD ((TPMA_NV)1 << 19) +# define TPMA_NV_NO_DA ((TPMA_NV)1 << 25) +# define TPMA_NV_ORDERLY ((TPMA_NV)1 << 26) +# define TPMA_NV_CLEAR_STCLEAR ((TPMA_NV)1 << 27) +# define TPMA_NV_READLOCKED ((TPMA_NV)1 << 28) +# define TPMA_NV_WRITTEN ((TPMA_NV)1 << 29) +# define TPMA_NV_PLATFORMCREATE ((TPMA_NV)1 << 30) +# define TPMA_NV_READ_STCLEAR ((TPMA_NV)1 << 31) +// This is the initializer for a TPMA_NV bit array. +# define TPMA_NV_INITIALIZER(ppwrite, \ + ownerwrite, \ + authwrite, \ + policywrite, \ + tpm_nt, \ + bits_at_8, \ + policy_delete, \ + writelocked, \ + writeall, \ + writedefine, \ + write_stclear, \ + globallock, \ + ppread, \ + ownerread, \ + authread, \ + policyread, \ + bits_at_20, \ + no_da, \ + orderly, \ + clear_stclear, \ + readlocked, \ + written, \ + platformcreate, \ + read_stclear) \ + (TPMA_NV)((ppwrite << 0) + (ownerwrite << 1) + (authwrite << 2) \ + + (policywrite << 3) + (tpm_nt << 4) + (policy_delete << 10) \ + + (writelocked << 11) + (writeall << 12) + (writedefine << 13) \ + + (write_stclear << 14) + (globallock << 15) + (ppread << 16) \ + + (ownerread << 17) + (authread << 18) + (policyread << 19) \ + + (no_da << 25) + (orderly << 26) + (clear_stclear << 27) \ + + (readlocked << 28) + (written << 29) + (platformcreate << 30) \ + + (read_stclear << 31)) +#endif // USE_BIT_FIELD_STRUCTURES + +typedef struct +{ // Table 2:216 + TPMI_RH_NV_INDEX nvIndex; + TPMI_ALG_HASH nameAlg; + TPMA_NV attributes; + TPM2B_DIGEST authPolicy; + UINT16 dataSize; +} TPMS_NV_PUBLIC; /* Structure */ + +typedef struct +{ // Table 2:217 + UINT16 size; + TPMS_NV_PUBLIC nvPublic; +} TPM2B_NV_PUBLIC; /* Structure */ + +typedef union +{ // Table 2:218 + struct + { + UINT16 size; + BYTE buffer[MAX_CONTEXT_SIZE]; + } t; + TPM2B b; +} TPM2B_CONTEXT_SENSITIVE; /* Structure */ + +typedef struct +{ // Table 2:219 + TPM2B_DIGEST integrity; + TPM2B_CONTEXT_SENSITIVE encrypted; +} TPMS_CONTEXT_DATA; /* Structure */ + +typedef union +{ // Table 2:220 + struct + { + UINT16 size; + BYTE buffer[sizeof(TPMS_CONTEXT_DATA)]; + } t; + TPM2B b; +} TPM2B_CONTEXT_DATA; /* Structure */ + +typedef struct +{ // Table 2:221 + UINT64 sequence; + TPMI_DH_SAVED savedHandle; + TPMI_RH_HIERARCHY hierarchy; + TPM2B_CONTEXT_DATA contextBlob; +} TPMS_CONTEXT; /* Structure */ + +typedef struct +{ // Table 2:223 + TPML_PCR_SELECTION pcrSelect; + TPM2B_DIGEST pcrDigest; + TPMA_LOCALITY locality; + TPM_ALG_ID parentNameAlg; + TPM2B_NAME parentName; + TPM2B_NAME parentQualifiedName; + TPM2B_DATA outsideInfo; +} TPMS_CREATION_DATA; /* Structure */ + +typedef struct +{ // Table 2:224 + UINT16 size; + TPMS_CREATION_DATA creationData; +} TPM2B_CREATION_DATA; /* Structure */ + +// Table 2:225 - Definition of TPM_AT Constants +typedef UINT32 TPM_AT; +#define TYPE_OF_TPM_AT UINT32 +#define TPM_AT_ANY (TPM_AT)(0x00000000) +#define TPM_AT_ERROR (TPM_AT)(0x00000001) +#define TPM_AT_PV1 (TPM_AT)(0x00000002) +#define TPM_AT_VEND (TPM_AT)(0x80000000) + +// Table 2:226 - Definition of TPM_AE Constants +typedef UINT32 TPM_AE; +#define TYPE_OF_TPM_AE UINT32 +#define TPM_AE_NONE (TPM_AE)(0x00000000) + +typedef struct +{ // Table 2:227 + TPM_AT tag; + UINT32 data; +} TPMS_AC_OUTPUT; /* Structure */ + +typedef struct +{ // Table 2:228 + UINT32 count; + TPMS_AC_OUTPUT acCapabilities[MAX_AC_CAPABILITIES]; +} TPML_AC_CAPABILITIES; /* Structure */ + +#endif // _TPM_TYPES_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/VendorString.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/VendorString.h new file mode 100644 index 0000000..bb7525f --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/VendorString.h @@ -0,0 +1,88 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 _VENDOR_STRING_H +#define _VENDOR_STRING_H + +// Define up to 4-byte values for MANUFACTURER. This value defines the response +// for TPM_PT_MANUFACTURER in TPM2_GetCapability. +// The following line should be un-commented and a vendor specific string +// should be provided here. +#define MANUFACTURER "MSFT" + +// The following #if macro may be deleted after a proper MANUFACTURER is provided. +#ifndef MANUFACTURER +# error MANUFACTURER is not provided. \ +Please modify include/VendorString.h to provide a specific \ +manufacturer name. +#endif + +// Define up to 4, 4-byte values. The values must each be 4 bytes long and the last +// value used may contain trailing zeros. +// These values define the response for TPM_PT_VENDOR_STRING_(1-4) +// in TPM2_GetCapability. +// The following line should be un-commented and a vendor specific string +// should be provided here. +// The vendor strings 2-4 may also be defined as appropriate. +#define VENDOR_STRING_1 "xCG " +#define VENDOR_STRING_2 "fTPM" +// #define VENDOR_STRING_3 +// #define VENDOR_STRING_4 + +// The following #if macro may be deleted after a proper VENDOR_STRING_1 +// is provided. +#ifndef VENDOR_STRING_1 +# error VENDOR_STRING_1 is not provided. \ +Please modify include/VendorString.h to provide a vendor-specific string. +#endif + +// the more significant 32-bits of a vendor-specific value +// indicating the version of the firmware +// The following line should be un-commented and a vendor specific firmware V1 +// should be provided here. +// The FIRMWARE_V2 may also be defined as appropriate. +#define FIRMWARE_V1 (0x20170619) +// the less significant 32-bits of a vendor-specific value +// indicating the version of the firmware +#define FIRMWARE_V2 (0x00163636) + +// The following #if macro may be deleted after a proper FIRMWARE_V1 is provided. +#ifndef FIRMWARE_V1 +# error FIRMWARE_V1 is not provided. \ +Please modify include/VendorString.h to provide a vendor-specific firmware \ +version +#endif + +#endif diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Wolf/TpmToWolfHash.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Wolf/TpmToWolfHash.h new file mode 100644 index 0000000..5af59cb --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Wolf/TpmToWolfHash.h @@ -0,0 +1,190 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//** Introduction +// +// This header file is used to 'splice' the wolfcrypt hash code into the TPM code. +// +#ifndef HASH_LIB_DEFINED +#define HASH_LIB_DEFINED + +#define HASH_LIB_WOLF + +#define HASH_ALIGNMENT RADIX_BYTES + +#ifndef WOLFSSL_USER_SETTINGS +# define WOLFSSL_USER_SETTINGS +#endif + +#if ALG_SHA384 || ALG_SHA512 +# define WOLFSSL_SHA512 +#endif + +#if ALG_SM3_256 +# undef ALG_SM3_256 +# define ALG_SM3_256 ALG_NO +//#error "SM3 is not available" +#endif + +#include +#include +#include + +//*************************************************************** +//** Links to the wolfcrypt HASH code +//*************************************************************** + +// Redefine the internal name used for each of the hash state structures to the +// name used by the library. +// These defines need to be known in all parts of the TPM so that the structure +// sizes can be properly computed when needed. + +#define tpmHashStateSHA1_t wc_Sha +#define tpmHashStateSHA256_t wc_Sha256 +#define tpmHashStateSHA384_t wc_Sha512 +#define tpmHashStateSHA512_t wc_Sha512 + +#if ALG_SM3 +# error "The version of WolfCrypt used by this code does not support SM3" +#endif + +// The defines below are only needed when compiling CryptHash.c or CryptSmac.c. +// This isolation is primarily to avoid name space collision. However, if there +// is a real collision, it will likely show up when the linker tries to put things +// together. + +#ifdef _CRYPT_HASH_C_ + +typedef BYTE* PBYTE; +typedef const BYTE* PCBYTE; + +// Define the interface between CryptHash.c to the functions provided by the +// library. For each method, define the calling parameters of the method and then +// define how the method is invoked in CryptHash.c. +// +// All hashes are required to have the same calling sequence. If they don't, create +// a simple adaptation function that converts from the "standard" form of the call +// to the form used by the specific hash (and then send a nasty letter to the +// person who wrote the hash function for the library). +// +// The macro that calls the method also defines how the +// parameters get swizzled between the default form (in CryptHash.c)and the +// library form. +// +// Initialize the hash context +# define HASH_START_METHOD_DEF void(HASH_START_METHOD)(PANY_HASH_STATE state) +# define HASH_START(hashState) ((hashState)->def->method.start)(&(hashState)->state); + +// Add data to the hash +# define HASH_DATA_METHOD_DEF \ + void(HASH_DATA_METHOD)(PANY_HASH_STATE state, PCBYTE buffer, size_t size) +# define HASH_DATA(hashState, dInSize, dIn) \ + ((hashState)->def->method.data)(&(hashState)->state, dIn, dInSize) + +// Finalize the hash and get the digest +# define HASH_END_METHOD_DEF \ + void(HASH_END_METHOD)(PANY_HASH_STATE state, BYTE * buffer) +# define HASH_END(hashState, buffer) \ + ((hashState)->def->method.end)(&(hashState)->state, buffer) + +// Copy the hash context +// Note: For import, export, and copy, memcpy() is used since there is no +// reformatting necessary between the internal and external forms. +# define HASH_STATE_COPY_METHOD_DEF \ + void(HASH_STATE_COPY_METHOD)( \ + PANY_HASH_STATE to, PCANY_HASH_STATE from, size_t size) +# define HASH_STATE_COPY(hashStateOut, hashStateIn) \ + ((hashStateIn)->def->method.copy)(&(hashStateOut)->state, \ + &(hashStateIn)->state, \ + (hashStateIn)->def->contextSize) + +// Copy (with reformatting when necessary) an internal hash structure to an +// external blob +# define HASH_STATE_EXPORT_METHOD_DEF \ + void(HASH_STATE_EXPORT_METHOD)(BYTE * to, PCANY_HASH_STATE from, size_t size) +# define HASH_STATE_EXPORT(to, hashStateFrom) \ + ((hashStateFrom)->def->method.copyOut)( \ + &(((BYTE*)(to))[offsetof(HASH_STATE, state)]), \ + &(hashStateFrom)->state, \ + (hashStateFrom)->def->contextSize) + +// Copy from an external blob to an internal formate (with reformatting when +// necessary +# define HASH_STATE_IMPORT_METHOD_DEF \ + void(HASH_STATE_IMPORT_METHOD)(PANY_HASH_STATE to, const BYTE* from, size_t size) +# define HASH_STATE_IMPORT(hashStateTo, from) \ + ((hashStateTo)->def->method.copyIn)( \ + &(hashStateTo)->state, \ + &(((const BYTE*)(from))[offsetof(HASH_STATE, state)]), \ + (hashStateTo)->def->contextSize) + +// Function aliases. The code in CryptHash.c uses the internal designation for the +// functions. These need to be translated to the function names of the library. +// Internal External +// Designation Designation +// external name of the +// initialization method +# define tpmHashStart_SHA1 wc_InitSha +# define tpmHashData_SHA1 wc_ShaUpdate +# define tpmHashEnd_SHA1 wc_ShaFinal +# define tpmHashStateCopy_SHA1 memcpy +# define tpmHashStateExport_SHA1 memcpy +# define tpmHashStateImport_SHA1 memcpy +# define tpmHashStart_SHA256 wc_InitSha256 +# define tpmHashData_SHA256 wc_Sha256Update +# define tpmHashEnd_SHA256 wc_Sha256Final +# define tpmHashStateCopy_SHA256 memcpy +# define tpmHashStateExport_SHA256 memcpy +# define tpmHashStateImport_SHA256 memcpy +# define tpmHashStart_SHA384 wc_InitSha384 +# define tpmHashData_SHA384 wc_Sha384Update +# define tpmHashEnd_SHA384 wc_Sha384Final +# define tpmHashStateCopy_SHA384 memcpy +# define tpmHashStateExport_SHA384 memcpy +# define tpmHashStateImport_SHA384 memcpy +# define tpmHashStart_SHA512 wc_InitSha512 +# define tpmHashData_SHA512 wc_Sha512Update +# define tpmHashEnd_SHA512 wc_Sha512Final +# define tpmHashStateCopy_SHA512 memcpy +# define tpmHashStateExport_SHA512 memcpy +# define tpmHashStateImport_SHA512 memcpy + +#endif // _CRYPT_HASH_C_ + +#define LibHashInit() +// This definition would change if there were something to report +#define HashLibSimulationEnd() + +#endif // HASH_LIB_DEFINED diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Wolf/TpmToWolfMath.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Wolf/TpmToWolfMath.h new file mode 100644 index 0000000..82237bd --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Wolf/TpmToWolfMath.h @@ -0,0 +1,91 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//** Introduction +// This file contains the structure definitions used for ECC in the LibTomCrypt +// version of the code. These definitions would change, based on the library. +// The ECC-related structures that cross the TPM interface are defined +// in TpmTypes.h +// + +#ifndef MATH_LIB_DEFINED +#define MATH_LIB_DEFINED + +#define MATH_LIB_WOLF + +#if ALG_ECC +# define HAVE_ECC +#endif + +#include +#include + +#define MP_VAR(name) \ + mp_int _##name; \ + mp_int* name = MpInitialize(&_##name); + +// Allocate a mp_int and initialize with the values in a mp_int* initializer +#define MP_INITIALIZED(name, initializer) \ + MP_VAR(name); \ + BnToWolf(name, initializer); + +#define POINT_CREATE(name, initializer) \ + ecc_point* name = EcPointInitialized(initializer); + +#define POINT_DELETE(name) \ + wc_ecc_del_point(name); \ + name = NULL; + +typedef ECC_CURVE_DATA bnCurve_t; + +typedef bnCurve_t* bigCurve; + +#define AccessCurveData(E) (E) + +#define CURVE_INITIALIZED(name, initializer) \ + bnCurve_t* name = (ECC_CURVE_DATA*)GetCurveData(initializer) + +#define CURVE_FREE(E) + +#include "TpmToWolfSupport_fp.h" + +#define WOLF_ENTER() + +#define WOLF_LEAVE() + +// This definition would change if there were something to report +#define MathLibSimulationEnd() + +#endif // MATH_LIB_DEFINED diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Wolf/TpmToWolfSym.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Wolf/TpmToWolfSym.h new file mode 100644 index 0000000..5a48db2 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Wolf/TpmToWolfSym.h @@ -0,0 +1,124 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//** Introduction +// +// This header file is used to 'splice' the wolfcrypt library into the TPM code. + +#ifndef SYM_LIB_DEFINED +#define SYM_LIB_DEFINED + +#define SYM_LIB_WOLF + +#define SYM_ALIGNMENT RADIX_BYTES + +#include +#include + +//*************************************************************** +//** Links to the wolfCrypt AES code +//*************************************************************** +#if ALG_SM4 +# undef ALG_SM4 +# define ALG_SM4 ALG_NO +//#error "SM4 is not available" +#endif + +#if ALG_CAMELLIA +# undef ALG_CAMELLIA +# define ALG_CAMELLIA ALG_NO +//#error "Camellia is not available" +#endif + +// Define the order of parameters to the library functions that do block encryption +// and decryption. +typedef void (*TpmCryptSetSymKeyCall_t)(void* keySchedule, BYTE* out, const BYTE* in); + +// The Crypt functions that call the block encryption function use the parameters +// in the order: +// 1) keySchedule +// 2) in buffer +// 3) out buffer +// Since wolfcrypt uses the order in encryptoCall_t above, need to swizzle the +// values to the order required by the library. +#define SWIZZLE(keySchedule, in, out) \ + (void*)(keySchedule), (BYTE*)(out), (const BYTE*)(in) + +// Macros to set up the encryption/decryption key schedules +// +// AES: +#define TpmCryptSetEncryptKeyAES(key, keySizeInBits, schedule) \ + wc_AesSetKeyDirect((tpmKeyScheduleAES*)(schedule), \ + key, \ + BITS_TO_BYTES(keySizeInBits), \ + 0, \ + AES_ENCRYPTION) +#define TpmCryptSetDecryptKeyAES(key, keySizeInBits, schedule) \ + wc_AesSetKeyDirect((tpmKeyScheduleAES*)(schedule), \ + key, \ + BITS_TO_BYTES(keySizeInBits), \ + 0, \ + AES_DECRYPTION) + +// TDES: +#define TpmCryptSetEncryptKeyTDES(key, keySizeInBits, schedule) \ + TDES_setup_encrypt_key((key), (keySizeInBits), (tpmKeyScheduleTDES*)(schedule)) +#define TpmCryptSetDecryptKeyTDES(key, keySizeInBits, schedule) \ + TDES_setup_decrypt_key((key), (keySizeInBits), (tpmKeyScheduleTDES*)(schedule)) + +// Macros to alias encryption calls to specific algorithms. This should be used +// sparingly. Currently, only used by CryptRand.c +// +// When using these calls, to call the AES block encryption code, the caller +// should use: +// TpmCryptEncryptAES(SWIZZLE(keySchedule, in, out)); +#define TpmCryptEncryptAES wc_AesEncryptDirect +#define TpmCryptDecryptAES wc_AesDecryptDirect +#define tpmKeyScheduleAES Aes + +#define TpmCryptEncryptTDES TDES_encrypt +#define TpmCryptDecryptTDES TDES_decrypt +#define tpmKeyScheduleTDES Des3 + +typedef union tpmCryptKeySchedule_t tpmCryptKeySchedule_t; + +#if ALG_TDES +# include "TpmToWolfDesSupport_fp.h" +#endif + +// This definition would change if there were something to report +#define SymLibSimulationEnd() + +#endif // SYM_LIB_DEFINED diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Wolf/user_settings.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Wolf/user_settings.h new file mode 100644 index 0000000..652028e --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/Wolf/user_settings.h @@ -0,0 +1,104 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* TPM specific preprocessor flags for wolfcrypt */ + +#ifndef WOLF_CRYPT_USER_SETTINGS_H +#define WOLF_CRYPT_USER_SETTINGS_H + +/* Remove the automatic setting of the default I/O functions EmbedSend() + and EmbedReceive(). */ +#define WOLFSSL_USER_IO + +/* Avoid naming conflicts */ +#define NO_OLD_WC_NAMES + +/* Use stack based fast math for all big integer math */ +#define USE_FAST_MATH +#define TFM_TIMING_RESISTANT + +/* Expose direct encryption functions */ +#define WOLFSSL_AES_DIRECT + +/* Enable/Disable algorithm support based on TPM implementation header */ +#if ALG_SHA256 +# define WOLFSSL_SHA256 +#endif +#if ALG_SHA384 || ALG_SHA512 +# define WOLFSSL_SHA384 +# define WOLFSSL_SHA512 +#endif +#if ALG_TDES +# define WOLFSSL_DES_ECB +#endif +#if ALG_RSA +/* Turn on RSA key generation functionality */ +# define WOLFSSL_KEY_GEN +#endif +#if ALG_ECC || defined(WOLFSSL_LIB) +# define HAVE_ECC + +/* Expose additional ECC primitives */ +# define WOLFSSL_PUBLIC_ECC_ADD_DBL +# define ECC_TIMING_RESISTANT + +/* Enables Shamir calc method */ +# define ECC_SHAMIR + +/* The TPM only needs low level ECC crypto */ +# define NO_ECC_SIGN +# define NO_ECC_VERIFY +# define NO_ECC_SECP + +# undef ECC_BN_P256 +# undef ECC_SM2_P256 +# undef ECC_BN_P638 +# define ECC_BN_P256 NO +# define ECC_SM2_P256 NO +# define ECC_BN_P638 NO + +#endif + +/* Disable explicit RSA. The TPM support for RSA is dependent only on TFM */ +#define NO_RSA +#define NO_RC4 +#define NO_ASN + +/* Enable debug wolf library check */ +//#define LIBRARY_COMPATIBILITY_CHECK + +#define WOLFSSL_ + +#endif // WOLF_CRYPT_USER_SETTINGS_H diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/X509.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/X509.h new file mode 100644 index 0000000..e3b2355 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/X509.h @@ -0,0 +1,132 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// This file contains the macro and structure definitions for the X509 commands and +// functions. + +#ifndef _X509_H_ +#define _X509_H_ + +//** Includes + +#include "Tpm.h" +#include "TpmASN1.h" + +//** Defined Constants + +//*** X509 Application-specific types +#define X509_SELECTION 0xA0 +#define X509_ISSUER_UNIQUE_ID 0xA1 +#define X509_SUBJECT_UNIQUE_ID 0xA2 +#define X509_EXTENSIONS 0xA3 + +// These defines give the order in which values appear in the TBScertificate +// of an x.509 certificate. These values are used to index into an array of +// +#define ENCODED_SIZE_REF 0 +#define VERSION_REF (ENCODED_SIZE_REF + 1) +#define SERIAL_NUMBER_REF (VERSION_REF + 1) +#define SIGNATURE_REF (SERIAL_NUMBER_REF + 1) +#define ISSUER_REF (SIGNATURE_REF + 1) +#define VALIDITY_REF (ISSUER_REF + 1) +#define SUBJECT_KEY_REF (VALIDITY_REF + 1) +#define SUBJECT_PUBLIC_KEY_REF (SUBJECT_KEY_REF + 1) +#define EXTENSIONS_REF (SUBJECT_PUBLIC_KEY_REF + 1) +#define REF_COUNT (EXTENSIONS_REF + 1) + +//** Structures + +// Used to access the fields of a TBSsignature some of which are in the in_CertifyX509 +// structure and some of which are in the out_CertifyX509 structure. +typedef struct stringRef +{ + BYTE* buf; + INT16 len; +} stringRef; + +// This is defined to avoid bit by bit comparisons within a UINT32 +typedef union x509KeyUsageUnion +{ + TPMA_X509_KEY_USAGE x509; + UINT32 integer; +} x509KeyUsageUnion; + +//** Global X509 Constants +// These values are instanced by X509_spt.c and referenced by other X509-related +// files. + +// This is the DER-encoded value for the Key Usage OID (2.5.29.15). This is the +// full OID, not just the numeric value +#define OID_KEY_USAGE_EXTENSION_VALUE 0x06, 0x03, 0x55, 0x1D, 0x0F +MAKE_OID(_KEY_USAGE_EXTENSION); + +// This is the DER-encoded value for the TCG-defined TPMA_OBJECT OID +// (2.23.133.10.1.1.1) +#define OID_TCG_TPMA_OBJECT_VALUE 0x06, 0x07, 0x67, 0x81, 0x05, 0x0a, 0x01, 0x01, 0x01 +MAKE_OID(_TCG_TPMA_OBJECT); + +#ifdef _X509_SPT_ +// If a bit is SET in KEY_USAGE_SIGN is also SET in keyUsage then +// the associated key has to have 'sign' SET. +const x509KeyUsageUnion KEY_USAGE_SIGN = {TPMA_X509_KEY_USAGE_INITIALIZER( + /* bits_at_0 */ 0, + /* decipheronly */ 0, + /* encipheronly */ 0, + /* crlsign */ 1, + /* keycertsign */ 1, + /* keyagreement */ 0, + /* dataencipherment */ 0, + /* keyencipherment */ 0, + /* nonrepudiation */ 0, + /* digitalsignature */ 1)}; +// If a bit is SET in KEY_USAGE_DECRYPT is also SET in keyUsage then +// the associated key has to have 'decrypt' SET. +const x509KeyUsageUnion KEY_USAGE_DECRYPT = {TPMA_X509_KEY_USAGE_INITIALIZER( + /* bits_at_0 */ 0, + /* decipheronly */ 1, + /* encipheronly */ 1, + /* crlsign */ 0, + /* keycertsign */ 0, + /* keyagreement */ 1, + /* dataencipherment */ 1, + /* keyencipherment */ 1, + /* nonrepudiation */ 0, + /* digitalsignature */ 0)}; +#else +extern x509KeyUsageUnion KEY_USAGE_SIGN; +extern x509KeyUsageUnion KEY_USAGE_DECRYPT; +#endif + +#endif // _X509_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ACT_SetTimeout_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ACT_SetTimeout_fp.h new file mode 100644 index 0000000..3a00147 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ACT_SetTimeout_fp.h @@ -0,0 +1,61 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Oct 2, 2019 Time: 07:41:19PM + */ + +#if CC_ACT_SetTimeout // Command must be enabled + +# ifndef _ACT_SETTIMEOUT_FP_H_ +# define _ACT_SETTIMEOUT_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_RH_ACT actHandle; + UINT32 startTimeout; +} ACT_SetTimeout_In; + +// Response code modifiers +# define RC_ACT_SetTimeout_actHandle (TPM_RC_H + TPM_RC_1) +# define RC_ACT_SetTimeout_startTimeout (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_ACT_SetTimeout(ACT_SetTimeout_In* in); + +# endif // _ACT_SETTIMEOUT_FP_H_ +#endif // CC_ACT_SetTimeout diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ACT_spt_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ACT_spt_fp.h new file mode 100644 index 0000000..3629c69 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ACT_spt_fp.h @@ -0,0 +1,80 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes 1.00 + * Date: Oct 24, 2019 Time: 10:38:43AM + */ + +#ifndef _ACT_SPT_FP_H_ +#define _ACT_SPT_FP_H_ + +//*** ActStartup() +// This function is called by TPM2_Startup() to initialize the ACT counter values. +BOOL ActStartup(STARTUP_TYPE type); + +//*** ActGetSignaled() +// This function returns the state of the signaled flag associated with an ACT. +BOOL ActGetSignaled(TPM_RH actHandle); + +//***ActShutdown() +// This function saves the current state of the counters +BOOL ActShutdown(TPM_SU state //IN: the type of the shutdown. +); + +//*** ActIsImplemented() +// This function determines if an ACT is implemented in both the TPM and the platform +// code. +BOOL ActIsImplemented(UINT32 act); + +//***ActCounterUpdate() +// This function updates the ACT counter. If the counter already has a pending update, +// it returns TPM_RC_RETRY so that the update can be tried again later. +TPM_RC +ActCounterUpdate(TPM_RH handle, //IN: the handle of the act + UINT32 newValue //IN: the value to set in the ACT +); + +//*** ActGetCapabilityData() +// This function returns the list of ACT data +// Return Type: TPMI_YES_NO +// YES if more ACT data is available +// NO if no more ACT data to +TPMI_YES_NO +ActGetCapabilityData(TPM_HANDLE actHandle, // IN: the handle for the starting ACT + UINT32 maxCount, // IN: maximum allowed return values + TPML_ACT_DATA* actList // OUT: ACT data list +); + +#endif // _ACT_SPT_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/AC_GetCapability_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/AC_GetCapability_fp.h new file mode 100644 index 0000000..ae5d8c1 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/AC_GetCapability_fp.h @@ -0,0 +1,70 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_AC_GetCapability // Command must be enabled + +# ifndef _AC_Get_Capability_FP_H_ +# define _AC_Get_Capability_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_RH_AC ac; + TPM_AT capability; + UINT32 count; +} AC_GetCapability_In; + +// Output structure definition +typedef struct +{ + TPMI_YES_NO moreData; + TPML_AC_CAPABILITIES capabilitiesData; +} AC_GetCapability_Out; + +// Response code modifiers +# define RC_AC_GetCapability_ac (TPM_RC_H + TPM_RC_1) +# define RC_AC_GetCapability_capability (TPM_RC_P + TPM_RC_1) +# define RC_AC_GetCapability_count (TPM_RC_P + TPM_RC_2) + +// Function prototype +TPM_RC +TPM2_AC_GetCapability(AC_GetCapability_In* in, AC_GetCapability_Out* out); + +# endif // _AC_Get_Capability_FP_H_ +#endif // CC_AC_GetCapability diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/AC_Send_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/AC_Send_fp.h new file mode 100644 index 0000000..8080664 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/AC_Send_fp.h @@ -0,0 +1,71 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_AC_Send // Command must be enabled + +# ifndef _AC_Send_FP_H_ +# define _AC_Send_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_OBJECT sendObject; + TPMI_RH_NV_AUTH authHandle; + TPMI_RH_AC ac; + TPM2B_MAX_BUFFER acDataIn; +} AC_Send_In; + +// Output structure definition +typedef struct +{ + TPMS_AC_OUTPUT acDataOut; +} AC_Send_Out; + +// Response code modifiers +# define RC_AC_Send_sendObject (TPM_RC_H + TPM_RC_1) +# define RC_AC_Send_authHandle (TPM_RC_H + TPM_RC_2) +# define RC_AC_Send_ac (TPM_RC_H + TPM_RC_3) +# define RC_AC_Send_acDataIn (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_AC_Send(AC_Send_In* in, AC_Send_Out* out); + +# endif // _AC_Send_FP_H_ +#endif // CC_AC_Send diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/AC_spt_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/AC_spt_fp.h new file mode 100644 index 0000000..2557349 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/AC_spt_fp.h @@ -0,0 +1,74 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 4, 2020 Time: 02:36:44PM + */ + +#ifndef _AC_SPT_FP_H_ +#define _AC_SPT_FP_H_ + +//*** AcToCapabilities() +// This function returns a pointer to a list of AC capabilities. +TPML_AC_CAPABILITIES* AcToCapabilities(TPMI_RH_AC component // IN: component +); + +//*** AcIsAccessible() +// Function to determine if an AC handle references an actual AC +// Return Type: BOOL +BOOL AcIsAccessible(TPM_HANDLE acHandle); + +//*** AcCapabilitiesGet() +// This function returns a list of capabilities associated with an AC +// Return Type: TPMI_YES_NO +// YES if there are more handles available +// NO all the available handles has been returned +TPMI_YES_NO +AcCapabilitiesGet(TPMI_RH_AC component, // IN: the component + TPM_AT type, // IN: start capability type + UINT32 count, // IN: requested number + TPML_AC_CAPABILITIES* capabilityList // OUT: list of handle +); + +//*** AcSendObject() +// Stub to handle sending of an AC object +// Return Type: TPM_RC +TPM_RC +AcSendObject(TPM_HANDLE acHandle, // IN: Handle of AC receiving object + OBJECT* object, // IN: object structure to send + TPMS_AC_OUTPUT* acDataOut // OUT: results of operation +); + +#endif // _AC_SPT_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ActivateCredential_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ActivateCredential_fp.h new file mode 100644 index 0000000..5d942e5 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ActivateCredential_fp.h @@ -0,0 +1,71 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_ActivateCredential // Command must be enabled + +# ifndef _Activate_Credential_FP_H_ +# define _Activate_Credential_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_OBJECT activateHandle; + TPMI_DH_OBJECT keyHandle; + TPM2B_ID_OBJECT credentialBlob; + TPM2B_ENCRYPTED_SECRET secret; +} ActivateCredential_In; + +// Output structure definition +typedef struct +{ + TPM2B_DIGEST certInfo; +} ActivateCredential_Out; + +// Response code modifiers +# define RC_ActivateCredential_activateHandle (TPM_RC_H + TPM_RC_1) +# define RC_ActivateCredential_keyHandle (TPM_RC_H + TPM_RC_2) +# define RC_ActivateCredential_credentialBlob (TPM_RC_P + TPM_RC_1) +# define RC_ActivateCredential_secret (TPM_RC_P + TPM_RC_2) + +// Function prototype +TPM_RC +TPM2_ActivateCredential(ActivateCredential_In* in, ActivateCredential_Out* out); + +# endif // _Activate_Credential_FP_H_ +#endif // CC_ActivateCredential diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/AlgorithmCap_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/AlgorithmCap_fp.h new file mode 100644 index 0000000..9290c9f --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/AlgorithmCap_fp.h @@ -0,0 +1,63 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 28, 2019 Time: 08:25:19PM + */ + +#ifndef _ALGORITHM_CAP_FP_H_ +#define _ALGORITHM_CAP_FP_H_ + +//** AlgorithmCapGetImplemented() +// This function is used by TPM2_GetCapability() to return a list of the +// implemented algorithms. +// +// Return Type: TPMI_YES_NO +// YES more algorithms to report +// NO no more algorithms to report +TPMI_YES_NO +AlgorithmCapGetImplemented(TPM_ALG_ID algID, // IN: the starting algorithm ID + UINT32 count, // IN: count of returned algorithms + TPML_ALG_PROPERTY* algList // OUT: algorithm list +); + +//** AlgorithmGetImplementedVector() +// This function returns the bit vector of the implemented algorithms. +LIB_EXPORT +void AlgorithmGetImplementedVector( + ALGORITHM_VECTOR* implemented // OUT: the implemented bits are SET +); + +#endif // _ALGORITHM_CAP_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/AlgorithmTests_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/AlgorithmTests_fp.h new file mode 100644 index 0000000..98d080b --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/AlgorithmTests_fp.h @@ -0,0 +1,69 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 4, 2020 Time: 02:36:44PM + */ + +#ifndef _ALGORITHM_TESTS_FP_H_ +#define _ALGORITHM_TESTS_FP_H_ + +#if SELF_TEST + +//*** TestAlgorithm() +// Dispatches to the correct test function for the algorithm or gets a list of +// testable algorithms. +// +// If 'toTest' is not NULL, then the test decisions are based on the algorithm +// selections in 'toTest'. Otherwise, 'g_toTest' is used. When bits are clear in +// 'g_toTest' they will also be cleared 'toTest'. +// +// If there doesn't happen to be a test for the algorithm, its associated bit is +// quietly cleared. +// +// If 'alg' is zero (TPM_ALG_ERROR), then the toTest vector is cleared of any bits +// for which there is no test (i.e. no tests are actually run but the vector is +// cleared). +// +// Note: 'toTest' will only ever have bits set for implemented algorithms but 'alg' +// can be anything. +// Return Type: TPM_RC +// TPM_RC_CANCELED test was canceled +LIB_EXPORT +TPM_RC +TestAlgorithm(TPM_ALG_ID alg, ALGORITHM_VECTOR* toTest); +#endif // SELF_TESTS + +#endif // _ALGORITHM_TESTS_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Attest_spt_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Attest_spt_fp.h new file mode 100644 index 0000000..81da0ce --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Attest_spt_fp.h @@ -0,0 +1,84 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 28, 2019 Time: 08:25:18PM + */ + +#ifndef _ATTEST_SPT_FP_H_ +#define _ATTEST_SPT_FP_H_ + +//***FillInAttestInfo() +// Fill in common fields of TPMS_ATTEST structure. +void FillInAttestInfo( + TPMI_DH_OBJECT signHandle, // IN: handle of signing object + TPMT_SIG_SCHEME* scheme, // IN/OUT: scheme to be used for signing + TPM2B_DATA* data, // IN: qualifying data + TPMS_ATTEST* attest // OUT: attest structure +); + +//***SignAttestInfo() +// Sign a TPMS_ATTEST structure. If signHandle is TPM_RH_NULL, a null signature +// is returned. +// +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES 'signHandle' references not a signing key +// TPM_RC_SCHEME 'scheme' is not compatible with 'signHandle' type +// TPM_RC_VALUE digest generated for the given 'scheme' is greater than +// the modulus of 'signHandle' (for an RSA key); +// invalid commit status or failed to generate "r" value +// (for an ECC key) +TPM_RC +SignAttestInfo(OBJECT* signKey, // IN: sign object + TPMT_SIG_SCHEME* scheme, // IN: sign scheme + TPMS_ATTEST* certifyInfo, // IN: the data to be signed + TPM2B_DATA* qualifyingData, // IN: extra data for the signing + // process + TPM2B_ATTEST* attest, // OUT: marshaled attest blob to be + // signed + TPMT_SIGNATURE* signature // OUT: signature +); + +//*** IsSigningObject() +// Checks to see if the object is OK for signing. This is here rather than in +// Object_spt.c because all the attestation commands use this file but not +// Object_spt.c. +// Return Type: BOOL +// TRUE(1) object may sign +// FALSE(0) object may not sign +BOOL IsSigningObject(OBJECT* object // IN: +); + +#endif // _ATTEST_SPT_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Bits_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Bits_fp.h new file mode 100644 index 0000000..52a21f0 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Bits_fp.h @@ -0,0 +1,67 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 28, 2019 Time: 08:25:19PM + */ + +#ifndef _BITS_FP_H_ +#define _BITS_FP_H_ + +//*** TestBit() +// This function is used to check the setting of a bit in an array of bits. +// Return Type: BOOL +// TRUE(1) bit is set +// FALSE(0) bit is not set +BOOL TestBit(unsigned int bitNum, // IN: number of the bit in 'bArray' + BYTE* bArray, // IN: array containing the bits + unsigned int bytesInArray // IN: size in bytes of 'bArray' +); + +//*** SetBit() +// This function will set the indicated bit in 'bArray'. +void SetBit(unsigned int bitNum, // IN: number of the bit in 'bArray' + BYTE* bArray, // IN: array containing the bits + unsigned int bytesInArray // IN: size in bytes of 'bArray' +); + +//*** ClearBit() +// This function will clear the indicated bit in 'bArray'. +void ClearBit(unsigned int bitNum, // IN: number of the bit in 'bArray'. + BYTE* bArray, // IN: array containing the bits + unsigned int bytesInArray // IN: size in bytes of 'bArray' +); + +#endif // _BITS_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/BnConvert_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/BnConvert_fp.h new file mode 100644 index 0000000..346e6a7 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/BnConvert_fp.h @@ -0,0 +1,114 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 28, 2019 Time: 08:25:18PM + */ + +#ifndef _BN_CONVERT_FP_H_ +#define _BN_CONVERT_FP_H_ + +//*** BnFromBytes() +// This function will convert a big-endian byte array to the internal number +// format. If bn is NULL, then the output is NULL. If bytes is null or the +// required size is 0, then the output is set to zero +LIB_EXPORT bigNum BnFromBytes(bigNum bn, const BYTE* bytes, NUMBYTES nBytes); + +//*** BnFrom2B() +// Convert an TPM2B to a BIG_NUM. +// If the input value does not exist, or the output does not exist, or the input +// will not fit into the output the function returns NULL +LIB_EXPORT bigNum BnFrom2B(bigNum bn, // OUT: + const TPM2B* a2B // IN: number to convert +); + +//*** BnFromHex() +// Convert a hex string into a bigNum. This is primarily used in debugging. +LIB_EXPORT bigNum BnFromHex(bigNum bn, // OUT: + const char* hex // IN: +); + +//*** BnToBytes() +// This function converts a BIG_NUM to a byte array. It converts the bigNum to a +// big-endian byte string and sets 'size' to the normalized value. If 'size' is an +// input 0, then the receiving buffer is guaranteed to be large enough for the result +// and the size will be set to the size required for bigNum (leading zeros +// suppressed). +// +// The conversion for a little-endian machine simply requires that all significant +// bytes of the bigNum be reversed. For a big-endian machine, rather than +// unpack each word individually, the bigNum is converted to little-endian words, +// copied, and then converted back to big-endian. +LIB_EXPORT BOOL BnToBytes(bigConst bn, + BYTE* buffer, + NUMBYTES* size // This the number of bytes that are + // available in the buffer. The result + // should be this big. +); + +//*** BnTo2B() +// Function to convert a BIG_NUM to TPM2B. +// The TPM2B size is set to the requested 'size' which may require padding. +// If 'size' is non-zero and less than required by the value in 'bn' then an error +// is returned. If 'size' is zero, then the TPM2B is assumed to be large enough +// for the data and a2b->size will be adjusted accordingly. +LIB_EXPORT BOOL BnTo2B(bigConst bn, // IN: + TPM2B* a2B, // OUT: + NUMBYTES size // IN: the desired size +); +#if ALG_ECC + +//*** BnPointFrom2B() +// Function to create a BIG_POINT structure from a 2B point. +// A point is going to be two ECC values in the same buffer. The values are going +// to be the size of the modulus. They are in modular form. +LIB_EXPORT bn_point_t* BnPointFrom2B( + bigPoint ecP, // OUT: the preallocated point structure + TPMS_ECC_POINT* p // IN: the number to convert +); + +//*** BnPointTo2B() +// This function converts a BIG_POINT into a TPMS_ECC_POINT. A TPMS_ECC_POINT +// contains two TPM2B_ECC_PARAMETER values. The maximum size of the parameters +// is dependent on the maximum EC key size used in an implementation. +// The presumption is that the TPMS_ECC_POINT is large enough to hold 2 TPM2B +// values, each as large as a MAX_ECC_PARAMETER_BYTES +LIB_EXPORT BOOL BnPointTo2B(TPMS_ECC_POINT* p, // OUT: the converted 2B structure + bigPoint ecP, // IN: the values to be converted + bigCurve E // IN: curve descriptor for the point +); +#endif // ALG_ECC + +#endif // _BN_CONVERT_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/BnMath_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/BnMath_fp.h new file mode 100644 index 0000000..c7d280a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/BnMath_fp.h @@ -0,0 +1,173 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Aug 30, 2019 Time: 02:11:54PM + */ + +#ifndef _BN_MATH_FP_H_ +#define _BN_MATH_FP_H_ + +//*** BnAdd() +// This function adds two bigNum values. This function always returns TRUE. +LIB_EXPORT BOOL BnAdd(bigNum result, bigConst op1, bigConst op2); + +//*** BnAddWord() +// This function adds a word value to a bigNum. This function always returns TRUE. +LIB_EXPORT BOOL BnAddWord(bigNum result, bigConst op, crypt_uword_t word); + +//*** BnSub() +// This function does subtraction of two bigNum values and returns result = op1 - op2 +// when op1 is greater than op2. If op2 is greater than op1, then a fault is +// generated. This function always returns TRUE. +LIB_EXPORT BOOL BnSub(bigNum result, bigConst op1, bigConst op2); + +//*** BnSubWord() +// This function subtracts a word value from a bigNum. This function always +// returns TRUE. +LIB_EXPORT BOOL BnSubWord(bigNum result, bigConst op, crypt_uword_t word); + +//*** BnUnsignedCmp() +// This function performs a comparison of op1 to op2. The compare is approximately +// constant time if the size of the values used in the compare is consistent +// across calls (from the same line in the calling code). +// Return Type: int +// < 0 op1 is less than op2 +// 0 op1 is equal to op2 +// > 0 op1 is greater than op2 +LIB_EXPORT int BnUnsignedCmp(bigConst op1, bigConst op2); + +//*** BnUnsignedCmpWord() +// Compare a bigNum to a crypt_uword_t. +// Return Type: int +// -1 op1 is less that word +// 0 op1 is equal to word +// 1 op1 is greater than word +LIB_EXPORT int BnUnsignedCmpWord(bigConst op1, crypt_uword_t word); + +//*** BnModWord() +// This function does modular division of a big number when the modulus is a +// word value. +LIB_EXPORT crypt_word_t BnModWord(bigConst numerator, crypt_word_t modulus); + +//*** Msb() +// This function returns the bit number of the most significant bit of a +// crypt_uword_t. The number for the least significant bit of any bigNum value is 0. +// The maximum return value is RADIX_BITS - 1, +// Return Type: int +// -1 the word was zero +// n the bit number of the most significant bit in the word +LIB_EXPORT int Msb(crypt_uword_t word); + +//*** BnMsb() +// This function returns the number of the MSb of a bigNum value. +// Return Type: int +// -1 the word was zero or 'bn' was NULL +// n the bit number of the most significant bit in the word +LIB_EXPORT int BnMsb(bigConst bn); + +//*** BnSizeInBits() +// This function returns the number of bits required to hold a number. It is one +// greater than the Msb. +// +LIB_EXPORT unsigned BnSizeInBits(bigConst n); + +//*** BnSetWord() +// Change the value of a bignum_t to a word value. +LIB_EXPORT bigNum BnSetWord(bigNum n, crypt_uword_t w); + +//*** BnSetBit() +// This function will SET a bit in a bigNum. Bit 0 is the least-significant bit in +// the 0th digit_t. The function always return TRUE +LIB_EXPORT BOOL BnSetBit(bigNum bn, // IN/OUT: big number to modify + unsigned int bitNum // IN: Bit number to SET +); + +//*** BnTestBit() +// This function is used to check to see if a bit is SET in a bignum_t. The 0th bit +// is the LSb of d[0]. +// Return Type: BOOL +// TRUE(1) the bit is set +// FALSE(0) the bit is not set or the number is out of range +LIB_EXPORT BOOL BnTestBit(bigNum bn, // IN: number to check + unsigned int bitNum // IN: bit to test +); + +//***BnMaskBits() +// This function is used to mask off high order bits of a big number. +// The returned value will have no more than 'maskBit' bits +// set. +// Note: There is a requirement that unused words of a bignum_t are set to zero. +// Return Type: BOOL +// TRUE(1) result masked +// FALSE(0) the input was not as large as the mask +LIB_EXPORT BOOL BnMaskBits(bigNum bn, // IN/OUT: number to mask + crypt_uword_t maskBit // IN: the bit number for the mask. +); + +//*** BnShiftRight() +// This function will shift a bigNum to the right by the shiftAmount. +// This function always returns TRUE. +LIB_EXPORT BOOL BnShiftRight(bigNum result, bigConst toShift, uint32_t shiftAmount); + +//*** BnGetRandomBits() +// This function gets random bits for use in various places. To make sure that the +// number is generated in a portable format, it is created as a TPM2B and then +// converted to the internal format. +// +// One consequence of the generation scheme is that, if the number of bits requested +// is not a multiple of 8, then the high-order bits are set to zero. This would come +// into play when generating a 521-bit ECC key. A 66-byte (528-bit) value is +// generated an the high order 7 bits are masked off (CLEAR). +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure +LIB_EXPORT BOOL BnGetRandomBits(bigNum n, size_t bits, RAND_STATE* rand); + +//*** BnGenerateRandomInRange() +// This function is used to generate a random number r in the range 1 <= r < limit. +// The function gets a random number of bits that is the size of limit. There is some +// some probability that the returned number is going to be greater than or equal +// to the limit. If it is, try again. There is no more than 50% chance that the +// next number is also greater, so try again. We keep trying until we get a +// value that meets the criteria. Since limit is very often a number with a LOT of +// high order ones, this rarely would need a second try. +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure ('limit' is too small) +LIB_EXPORT BOOL BnGenerateRandomInRange( + bigNum dest, bigConst limit, RAND_STATE* rand); + +#endif // _BN_MATH_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/BnMemory_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/BnMemory_fp.h new file mode 100644 index 0000000..90e9167 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/BnMemory_fp.h @@ -0,0 +1,90 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 28, 2019 Time: 08:25:18PM + */ + +#ifndef _BN_MEMORY_FP_H_ +#define _BN_MEMORY_FP_H_ + +//*** BnSetTop() +// This function is used when the size of a bignum_t is changed. It +// makes sure that the unused words are set to zero and that any significant +// words of zeros are eliminated from the used size indicator. +LIB_EXPORT bigNum BnSetTop(bigNum bn, // IN/OUT: number to clean + crypt_uword_t top // IN: the new top +); + +//*** BnClearTop() +// This function will make sure that all unused words are zero. +LIB_EXPORT bigNum BnClearTop(bigNum bn); + +//*** BnInitializeWord() +// This function is used to initialize an allocated bigNum with a word value. The +// bigNum does not have to be allocated with a single word. +LIB_EXPORT bigNum BnInitializeWord(bigNum bn, // IN: + crypt_uword_t allocated, // IN: + crypt_uword_t word // IN: +); + +//*** BnInit() +// This function initializes a stack allocated bignum_t. It initializes +// 'allocated' and 'size' and zeros the words of 'd'. +LIB_EXPORT bigNum BnInit(bigNum bn, crypt_uword_t allocated); + +//*** BnCopy() +// Function to copy a bignum_t. If the output is NULL, then +// nothing happens. If the input is NULL, the output is set +// to zero. +LIB_EXPORT BOOL BnCopy(bigNum out, bigConst in); +#if ALG_ECC + +//*** BnPointCopy() +// Function to copy a bn point. +LIB_EXPORT BOOL BnPointCopy(bigPoint pOut, pointConst pIn); + +//*** BnInitializePoint() +// This function is used to initialize a point structure with the addresses +// of the coordinates. +LIB_EXPORT bn_point_t* BnInitializePoint( + bigPoint p, // OUT: structure to receive pointers + bigNum x, // IN: x coordinate + bigNum y, // IN: y coordinate + bigNum z // IN: x coordinate +); +#endif // ALG_ECC + +#endif // _BN_MEMORY_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CertifyCreation_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CertifyCreation_fp.h new file mode 100644 index 0000000..b460f3b --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CertifyCreation_fp.h @@ -0,0 +1,76 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_CertifyCreation // Command must be enabled + +# ifndef _Certify_Creation_FP_H_ +# define _Certify_Creation_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_OBJECT signHandle; + TPMI_DH_OBJECT objectHandle; + TPM2B_DATA qualifyingData; + TPM2B_DIGEST creationHash; + TPMT_SIG_SCHEME inScheme; + TPMT_TK_CREATION creationTicket; +} CertifyCreation_In; + +// Output structure definition +typedef struct +{ + TPM2B_ATTEST certifyInfo; + TPMT_SIGNATURE signature; +} CertifyCreation_Out; + +// Response code modifiers +# define RC_CertifyCreation_signHandle (TPM_RC_H + TPM_RC_1) +# define RC_CertifyCreation_objectHandle (TPM_RC_H + TPM_RC_2) +# define RC_CertifyCreation_qualifyingData (TPM_RC_P + TPM_RC_1) +# define RC_CertifyCreation_creationHash (TPM_RC_P + TPM_RC_2) +# define RC_CertifyCreation_inScheme (TPM_RC_P + TPM_RC_3) +# define RC_CertifyCreation_creationTicket (TPM_RC_P + TPM_RC_4) + +// Function prototype +TPM_RC +TPM2_CertifyCreation(CertifyCreation_In* in, CertifyCreation_Out* out); + +# endif // _Certify_Creation_FP_H_ +#endif // CC_CertifyCreation diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CertifyX509_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CertifyX509_fp.h new file mode 100644 index 0000000..062ae5e --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CertifyX509_fp.h @@ -0,0 +1,75 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Sep 5, 2019 Time: 06:45:31PM + */ + +#if CC_CertifyX509 // Command must be enabled + +# ifndef _CERTIFYX509_FP_H_ +# define _CERTIFYX509_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_OBJECT objectHandle; + TPMI_DH_OBJECT signHandle; + TPM2B_DATA reserved; + TPMT_SIG_SCHEME inScheme; + TPM2B_MAX_BUFFER partialCertificate; +} CertifyX509_In; + +// Output structure definition +typedef struct +{ + TPM2B_MAX_BUFFER addedToCertificate; + TPM2B_DIGEST tbsDigest; + TPMT_SIGNATURE signature; +} CertifyX509_Out; + +// Response code modifiers +# define RC_CertifyX509_objectHandle (TPM_RC_H + TPM_RC_1) +# define RC_CertifyX509_signHandle (TPM_RC_H + TPM_RC_2) +# define RC_CertifyX509_reserved (TPM_RC_P + TPM_RC_1) +# define RC_CertifyX509_inScheme (TPM_RC_P + TPM_RC_2) +# define RC_CertifyX509_partialCertificate (TPM_RC_P + TPM_RC_3) + +// Function prototype +TPM_RC +TPM2_CertifyX509(CertifyX509_In* in, CertifyX509_Out* out); + +# endif // _CERTIFYX509_FP_H_ +#endif // CC_CertifyX509 diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Certify_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Certify_fp.h new file mode 100644 index 0000000..b6234d4 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Certify_fp.h @@ -0,0 +1,72 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_Certify // Command must be enabled + +# ifndef _Certify_FP_H_ +# define _Certify_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_OBJECT objectHandle; + TPMI_DH_OBJECT signHandle; + TPM2B_DATA qualifyingData; + TPMT_SIG_SCHEME inScheme; +} Certify_In; + +// Output structure definition +typedef struct +{ + TPM2B_ATTEST certifyInfo; + TPMT_SIGNATURE signature; +} Certify_Out; + +// Response code modifiers +# define RC_Certify_objectHandle (TPM_RC_H + TPM_RC_1) +# define RC_Certify_signHandle (TPM_RC_H + TPM_RC_2) +# define RC_Certify_qualifyingData (TPM_RC_P + TPM_RC_1) +# define RC_Certify_inScheme (TPM_RC_P + TPM_RC_2) + +// Function prototype +TPM_RC +TPM2_Certify(Certify_In* in, Certify_Out* out); + +# endif // _Certify_FP_H_ +#endif // CC_Certify diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ChangeEPS_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ChangeEPS_fp.h new file mode 100644 index 0000000..320ca83 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ChangeEPS_fp.h @@ -0,0 +1,59 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_ChangeEPS // Command must be enabled + +# ifndef _Change_EPS_FP_H_ +# define _Change_EPS_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_RH_PLATFORM authHandle; +} ChangeEPS_In; + +// Response code modifiers +# define RC_ChangeEPS_authHandle (TPM_RC_H + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_ChangeEPS(ChangeEPS_In* in); + +# endif // _Change_EPS_FP_H_ +#endif // CC_ChangeEPS diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ChangePPS_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ChangePPS_fp.h new file mode 100644 index 0000000..7ed0e5b --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ChangePPS_fp.h @@ -0,0 +1,59 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_ChangePPS // Command must be enabled + +# ifndef _Change_PPS_FP_H_ +# define _Change_PPS_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_RH_PLATFORM authHandle; +} ChangePPS_In; + +// Response code modifiers +# define RC_ChangePPS_authHandle (TPM_RC_H + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_ChangePPS(ChangePPS_In* in); + +# endif // _Change_PPS_FP_H_ +#endif // CC_ChangePPS diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ClearControl_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ClearControl_fp.h new file mode 100644 index 0000000..978d4bd --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ClearControl_fp.h @@ -0,0 +1,61 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_ClearControl // Command must be enabled + +# ifndef _Clear_Control_FP_H_ +# define _Clear_Control_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_RH_CLEAR auth; + TPMI_YES_NO disable; +} ClearControl_In; + +// Response code modifiers +# define RC_ClearControl_auth (TPM_RC_H + TPM_RC_1) +# define RC_ClearControl_disable (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_ClearControl(ClearControl_In* in); + +# endif // _Clear_Control_FP_H_ +#endif // CC_ClearControl diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Clear_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Clear_fp.h new file mode 100644 index 0000000..610546c --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Clear_fp.h @@ -0,0 +1,59 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_Clear // Command must be enabled + +# ifndef _Clear_FP_H_ +# define _Clear_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_RH_CLEAR authHandle; +} Clear_In; + +// Response code modifiers +# define RC_Clear_authHandle (TPM_RC_H + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_Clear(Clear_In* in); + +# endif // _Clear_FP_H_ +#endif // CC_Clear diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ClockRateAdjust_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ClockRateAdjust_fp.h new file mode 100644 index 0000000..cd7bc86 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ClockRateAdjust_fp.h @@ -0,0 +1,61 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_ClockRateAdjust // Command must be enabled + +# ifndef _Clock_Rate_Adjust_FP_H_ +# define _Clock_Rate_Adjust_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_RH_PROVISION auth; + TPM_CLOCK_ADJUST rateAdjust; +} ClockRateAdjust_In; + +// Response code modifiers +# define RC_ClockRateAdjust_auth (TPM_RC_H + TPM_RC_1) +# define RC_ClockRateAdjust_rateAdjust (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_ClockRateAdjust(ClockRateAdjust_In* in); + +# endif // _Clock_Rate_Adjust_FP_H_ +#endif // CC_ClockRateAdjust diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ClockSet_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ClockSet_fp.h new file mode 100644 index 0000000..6b5b1d2 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ClockSet_fp.h @@ -0,0 +1,61 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_ClockSet // Command must be enabled + +# ifndef _Clock_Set_FP_H_ +# define _Clock_Set_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_RH_PROVISION auth; + UINT64 newTime; +} ClockSet_In; + +// Response code modifiers +# define RC_ClockSet_auth (TPM_RC_H + TPM_RC_1) +# define RC_ClockSet_newTime (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_ClockSet(ClockSet_In* in); + +# endif // _Clock_Set_FP_H_ +#endif // CC_ClockSet diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CommandAudit_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CommandAudit_fp.h new file mode 100644 index 0000000..00dc358 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CommandAudit_fp.h @@ -0,0 +1,117 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Apr 2, 2019 Time: 04:23:27PM + */ + +#ifndef _COMMAND_AUDIT_FP_H_ +#define _COMMAND_AUDIT_FP_H_ + +//*** CommandAuditPreInstall_Init() +// This function initializes the command audit list. This function simulates +// the behavior of manufacturing. A function is used instead of a structure +// definition because this is easier than figuring out the initialization value +// for a bit array. +// +// This function would not be implemented outside of a manufacturing or +// simulation environment. +void CommandAuditPreInstall_Init(void); + +//*** CommandAuditStartup() +// This function clears the command audit digest on a TPM Reset. +BOOL CommandAuditStartup(STARTUP_TYPE type // IN: start up type +); + +//*** CommandAuditSet() +// This function will SET the audit flag for a command. This function +// will not SET the audit flag for a command that is not implemented. This +// ensures that the audit status is not SET when TPM2_GetCapability() is +// used to read the list of audited commands. +// +// This function is only used by TPM2_SetCommandCodeAuditStatus(). +// +// The actions in TPM2_SetCommandCodeAuditStatus() are expected to cause the +// changes to be saved to NV after it is setting and clearing bits. +// Return Type: BOOL +// TRUE(1) command code audit status was changed +// FALSE(0) command code audit status was not changed +BOOL CommandAuditSet(TPM_CC commandCode // IN: command code +); + +//*** CommandAuditClear() +// This function will CLEAR the audit flag for a command. It will not CLEAR the +// audit flag for TPM_CC_SetCommandCodeAuditStatus(). +// +// This function is only used by TPM2_SetCommandCodeAuditStatus(). +// +// The actions in TPM2_SetCommandCodeAuditStatus() are expected to cause the +// changes to be saved to NV after it is setting and clearing bits. +// Return Type: BOOL +// TRUE(1) command code audit status was changed +// FALSE(0) command code audit status was not changed +BOOL CommandAuditClear(TPM_CC commandCode // IN: command code +); + +//*** CommandAuditIsRequired() +// This function indicates if the audit flag is SET for a command. +// Return Type: BOOL +// TRUE(1) command is audited +// FALSE(0) command is not audited +BOOL CommandAuditIsRequired(COMMAND_INDEX commandIndex // IN: command index +); + +//*** CommandAuditCapGetCCList() +// This function returns a list of commands that have their audit bit SET. +// +// The list starts at the input commandCode. +// Return Type: TPMI_YES_NO +// YES if there are more command code available +// NO all the available command code has been returned +TPMI_YES_NO +CommandAuditCapGetCCList(TPM_CC commandCode, // IN: start command code + UINT32 count, // IN: count of returned TPM_CC + TPML_CC* commandList // OUT: list of TPM_CC +); + +//*** CommandAuditGetDigest +// This command is used to create a digest of the commands being audited. The +// commands are processed in ascending numeric order with a list of TPM_CC being +// added to a hash. This operates as if all the audited command codes were +// concatenated and then hashed. +void CommandAuditGetDigest(TPM2B_DIGEST* digest // OUT: command digest +); + +#endif // _COMMAND_AUDIT_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CommandCodeAttributes_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CommandCodeAttributes_fp.h new file mode 100644 index 0000000..8b1a109 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CommandCodeAttributes_fp.h @@ -0,0 +1,161 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 28, 2019 Time: 08:25:19PM + */ + +#ifndef _COMMAND_CODE_ATTRIBUTES_FP_H_ +#define _COMMAND_CODE_ATTRIBUTES_FP_H_ + +//*** GetClosestCommandIndex() +// This function returns the command index for the command with a value that is +// equal to or greater than the input value +// Return Type: COMMAND_INDEX +// UNIMPLEMENTED_COMMAND_INDEX command is not implemented +// other index of a command +COMMAND_INDEX +GetClosestCommandIndex(TPM_CC commandCode // IN: the command code to start at +); + +//*** CommandCodeToComandIndex() +// This function returns the index in the various attributes arrays of the +// command. +// Return Type: COMMAND_INDEX +// UNIMPLEMENTED_COMMAND_INDEX command is not implemented +// other index of the command +COMMAND_INDEX +CommandCodeToCommandIndex(TPM_CC commandCode // IN: the command code to look up +); + +//*** GetNextCommandIndex() +// This function returns the index of the next implemented command. +// Return Type: COMMAND_INDEX +// UNIMPLEMENTED_COMMAND_INDEX no more implemented commands +// other the index of the next implemented command +COMMAND_INDEX +GetNextCommandIndex(COMMAND_INDEX commandIndex // IN: the starting index +); + +//*** GetCommandCode() +// This function returns the commandCode associated with the command index +TPM_CC +GetCommandCode(COMMAND_INDEX commandIndex // IN: the command index +); + +//*** CommandAuthRole() +// +// This function returns the authorization role required of a handle. +// +// Return Type: AUTH_ROLE +// AUTH_NONE no authorization is required +// AUTH_USER user role authorization is required +// AUTH_ADMIN admin role authorization is required +// AUTH_DUP duplication role authorization is required +AUTH_ROLE +CommandAuthRole(COMMAND_INDEX commandIndex, // IN: command index + UINT32 handleIndex // IN: handle index (zero based) +); + +//*** EncryptSize() +// This function returns the size of the decrypt size field. This function returns +// 0 if encryption is not allowed +// Return Type: int +// 0 encryption not allowed +// 2 size field is two bytes +// 4 size field is four bytes +int EncryptSize(COMMAND_INDEX commandIndex // IN: command index +); + +//*** DecryptSize() +// This function returns the size of the decrypt size field. This function returns +// 0 if decryption is not allowed +// Return Type: int +// 0 encryption not allowed +// 2 size field is two bytes +// 4 size field is four bytes +int DecryptSize(COMMAND_INDEX commandIndex // IN: command index +); + +//*** IsSessionAllowed() +// +// This function indicates if the command is allowed to have sessions. +// +// This function must not be called if the command is not known to be implemented. +// +// Return Type: BOOL +// TRUE(1) session is allowed with this command +// FALSE(0) session is not allowed with this command +BOOL IsSessionAllowed(COMMAND_INDEX commandIndex // IN: the command to be checked +); + +//*** IsHandleInResponse() +// This function determines if a command has a handle in the response +BOOL IsHandleInResponse(COMMAND_INDEX commandIndex); + +//*** IsWriteOperation() +// Checks to see if an operation will write to an NV Index and is subject to being +// blocked by read-lock +BOOL IsWriteOperation(COMMAND_INDEX commandIndex // IN: Command to check +); + +//*** IsReadOperation() +// Checks to see if an operation will write to an NV Index and is +// subject to being blocked by write-lock. +BOOL IsReadOperation(COMMAND_INDEX commandIndex // IN: Command to check +); + +//*** CommandCapGetCCList() +// This function returns a list of implemented commands and command attributes +// starting from the command in 'commandCode'. +// Return Type: TPMI_YES_NO +// YES more command attributes are available +// NO no more command attributes are available +TPMI_YES_NO +CommandCapGetCCList(TPM_CC commandCode, // IN: start command code + UINT32 count, // IN: maximum count for number of entries in + // 'commandList' + TPML_CCA* commandList // OUT: list of TPMA_CC +); + +//*** IsVendorCommand() +// Function indicates if a command index references a vendor command. +// Return Type: BOOL +// TRUE(1) command is a vendor command +// FALSE(0) command is not a vendor command +BOOL IsVendorCommand(COMMAND_INDEX commandIndex // IN: command index to check +); + +#endif // _COMMAND_CODE_ATTRIBUTES_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CommandDispatcher_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CommandDispatcher_fp.h new file mode 100644 index 0000000..f906c4d --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CommandDispatcher_fp.h @@ -0,0 +1,54 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 7, 2020 Time: 07:06:44PM + */ + +#ifndef _COMMAND_DISPATCHER_FP_H_ +#define _COMMAND_DISPATCHER_FP_H_ + +//** ParseHandleBuffer() +// This is the table-driven version of the handle buffer unmarshaling code +TPM_RC +ParseHandleBuffer(COMMAND* command); + +//** CommandDispatcher() +// Function to unmarshal the command parameters, call the selected action code, and +// marshal the response parameters. +TPM_RC +CommandDispatcher(COMMAND* command); + +#endif // _COMMAND_DISPATCHER_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Commit_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Commit_fp.h new file mode 100644 index 0000000..dca1573 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Commit_fp.h @@ -0,0 +1,74 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_Commit // Command must be enabled + +# ifndef _Commit_FP_H_ +# define _Commit_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_OBJECT signHandle; + TPM2B_ECC_POINT P1; + TPM2B_SENSITIVE_DATA s2; + TPM2B_ECC_PARAMETER y2; +} Commit_In; + +// Output structure definition +typedef struct +{ + TPM2B_ECC_POINT K; + TPM2B_ECC_POINT L; + TPM2B_ECC_POINT E; + UINT16 counter; +} Commit_Out; + +// Response code modifiers +# define RC_Commit_signHandle (TPM_RC_H + TPM_RC_1) +# define RC_Commit_P1 (TPM_RC_P + TPM_RC_1) +# define RC_Commit_s2 (TPM_RC_P + TPM_RC_2) +# define RC_Commit_y2 (TPM_RC_P + TPM_RC_3) + +// Function prototype +TPM_RC +TPM2_Commit(Commit_In* in, Commit_Out* out); + +# endif // _Commit_FP_H_ +#endif // CC_Commit diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ContextLoad_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ContextLoad_fp.h new file mode 100644 index 0000000..515174a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ContextLoad_fp.h @@ -0,0 +1,65 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_ContextLoad // Command must be enabled + +# ifndef _Context_Load_FP_H_ +# define _Context_Load_FP_H_ + +// Input structure definition +typedef struct +{ + TPMS_CONTEXT context; +} ContextLoad_In; + +// Output structure definition +typedef struct +{ + TPMI_DH_CONTEXT loadedHandle; +} ContextLoad_Out; + +// Response code modifiers +# define RC_ContextLoad_context (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_ContextLoad(ContextLoad_In* in, ContextLoad_Out* out); + +# endif // _Context_Load_FP_H_ +#endif // CC_ContextLoad diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ContextSave_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ContextSave_fp.h new file mode 100644 index 0000000..de3aa80 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ContextSave_fp.h @@ -0,0 +1,65 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_ContextSave // Command must be enabled + +# ifndef _Context_Save_FP_H_ +# define _Context_Save_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_CONTEXT saveHandle; +} ContextSave_In; + +// Output structure definition +typedef struct +{ + TPMS_CONTEXT context; +} ContextSave_Out; + +// Response code modifiers +# define RC_ContextSave_saveHandle (TPM_RC_H + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_ContextSave(ContextSave_In* in, ContextSave_Out* out); + +# endif // _Context_Save_FP_H_ +#endif // CC_ContextSave diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Context_spt_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Context_spt_fp.h new file mode 100644 index 0000000..a5a94f4 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Context_spt_fp.h @@ -0,0 +1,90 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 28, 2019 Time: 08:25:18PM + */ + +#ifndef _CONTEXT_SPT_FP_H_ +#define _CONTEXT_SPT_FP_H_ + +//*** ComputeContextProtectionKey() +// This function retrieves the symmetric protection key for context encryption +// It is used by TPM2_ConextSave and TPM2_ContextLoad to create the symmetric +// encryption key and iv +// Return Type: void +void ComputeContextProtectionKey(TPMS_CONTEXT* contextBlob, // IN: context blob + TPM2B_SYM_KEY* symKey, // OUT: the symmetric key + TPM2B_IV* iv // OUT: the IV. +); + +//*** ComputeContextIntegrity() +// Generate the integrity hash for a context +// It is used by TPM2_ContextSave to create an integrity hash +// and by TPM2_ContextLoad to compare an integrity hash +// Return Type: void +void ComputeContextIntegrity(TPMS_CONTEXT* contextBlob, // IN: context blob + TPM2B_DIGEST* integrity // OUT: integrity +); + +//*** SequenceDataExport() +// This function is used scan through the sequence object and +// either modify the hash state data for export (contextSave) or to +// import it into the internal format (contextLoad). +// This function should only be called after the sequence object has been copied +// to the context buffer (contextSave) or from the context buffer into the sequence +// object. The presumption is that the context buffer version of the data is the +// same size as the internal representation so nothing outsize of the hash context +// area gets modified. +void SequenceDataExport( + HASH_OBJECT* object, // IN: an internal hash object + HASH_OBJECT_BUFFER* exportObject // OUT: a sequence context in a buffer +); + +//*** SequenceDataImport() +// This function is used scan through the sequence object and +// either modify the hash state data for export (contextSave) or to +// import it into the internal format (contextLoad). +// This function should only be called after the sequence object has been copied +// to the context buffer (contextSave) or from the context buffer into the sequence +// object. The presumption is that the context buffer version of the data is the +// same size as the internal representation so nothing outsize of the hash context +// area gets modified. +void SequenceDataImport( + HASH_OBJECT* object, // IN/OUT: an internal hash object + HASH_OBJECT_BUFFER* exportObject // IN/OUT: a sequence context in a buffer +); + +#endif // _CONTEXT_SPT_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CreateLoaded_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CreateLoaded_fp.h new file mode 100644 index 0000000..0180183 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CreateLoaded_fp.h @@ -0,0 +1,72 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_CreateLoaded // Command must be enabled + +# ifndef _Create_Loaded_FP_H_ +# define _Create_Loaded_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_PARENT parentHandle; + TPM2B_SENSITIVE_CREATE inSensitive; + TPM2B_TEMPLATE inPublic; +} CreateLoaded_In; + +// Output structure definition +typedef struct +{ + TPM_HANDLE objectHandle; + TPM2B_PRIVATE outPrivate; + TPM2B_PUBLIC outPublic; + TPM2B_NAME name; +} CreateLoaded_Out; + +// Response code modifiers +# define RC_CreateLoaded_parentHandle (TPM_RC_H + TPM_RC_1) +# define RC_CreateLoaded_inSensitive (TPM_RC_P + TPM_RC_1) +# define RC_CreateLoaded_inPublic (TPM_RC_P + TPM_RC_2) + +// Function prototype +TPM_RC +TPM2_CreateLoaded(CreateLoaded_In* in, CreateLoaded_Out* out); + +# endif // _Create_Loaded_FP_H_ +#endif // CC_CreateLoaded diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CreatePrimary_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CreatePrimary_fp.h new file mode 100644 index 0000000..b058dbf --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CreatePrimary_fp.h @@ -0,0 +1,78 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_CreatePrimary // Command must be enabled + +# ifndef _Create_Primary_FP_H_ +# define _Create_Primary_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_RH_HIERARCHY primaryHandle; + TPM2B_SENSITIVE_CREATE inSensitive; + TPM2B_PUBLIC inPublic; + TPM2B_DATA outsideInfo; + TPML_PCR_SELECTION creationPCR; +} CreatePrimary_In; + +// Output structure definition +typedef struct +{ + TPM_HANDLE objectHandle; + TPM2B_PUBLIC outPublic; + TPM2B_CREATION_DATA creationData; + TPM2B_DIGEST creationHash; + TPMT_TK_CREATION creationTicket; + TPM2B_NAME name; +} CreatePrimary_Out; + +// Response code modifiers +# define RC_CreatePrimary_primaryHandle (TPM_RC_H + TPM_RC_1) +# define RC_CreatePrimary_inSensitive (TPM_RC_P + TPM_RC_1) +# define RC_CreatePrimary_inPublic (TPM_RC_P + TPM_RC_2) +# define RC_CreatePrimary_outsideInfo (TPM_RC_P + TPM_RC_3) +# define RC_CreatePrimary_creationPCR (TPM_RC_P + TPM_RC_4) + +// Function prototype +TPM_RC +TPM2_CreatePrimary(CreatePrimary_In* in, CreatePrimary_Out* out); + +# endif // _Create_Primary_FP_H_ +#endif // CC_CreatePrimary diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Create_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Create_fp.h new file mode 100644 index 0000000..50987a2 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Create_fp.h @@ -0,0 +1,77 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_Create // Command must be enabled + +# ifndef _Create_FP_H_ +# define _Create_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_OBJECT parentHandle; + TPM2B_SENSITIVE_CREATE inSensitive; + TPM2B_PUBLIC inPublic; + TPM2B_DATA outsideInfo; + TPML_PCR_SELECTION creationPCR; +} Create_In; + +// Output structure definition +typedef struct +{ + TPM2B_PRIVATE outPrivate; + TPM2B_PUBLIC outPublic; + TPM2B_CREATION_DATA creationData; + TPM2B_DIGEST creationHash; + TPMT_TK_CREATION creationTicket; +} Create_Out; + +// Response code modifiers +# define RC_Create_parentHandle (TPM_RC_H + TPM_RC_1) +# define RC_Create_inSensitive (TPM_RC_P + TPM_RC_1) +# define RC_Create_inPublic (TPM_RC_P + TPM_RC_2) +# define RC_Create_outsideInfo (TPM_RC_P + TPM_RC_3) +# define RC_Create_creationPCR (TPM_RC_P + TPM_RC_4) + +// Function prototype +TPM_RC +TPM2_Create(Create_In* in, Create_Out* out); + +# endif // _Create_FP_H_ +#endif // CC_Create diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptCmac_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptCmac_fp.h new file mode 100644 index 0000000..4c7d726 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptCmac_fp.h @@ -0,0 +1,71 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 28, 2019 Time: 08:25:18PM + */ + +#ifndef _CRYPT_CMAC_FP_H_ +#define _CRYPT_CMAC_FP_H_ + +#if ALG_CMAC + +//*** CryptCmacStart() +// This is the function to start the CMAC sequence operation. It initializes the +// dispatch functions for the data and end operations for CMAC and initializes the +// parameters that are used for the processing of data, including the key, key size +// and block cipher algorithm. +UINT16 +CryptCmacStart( + SMAC_STATE* state, TPMU_PUBLIC_PARMS* keyParms, TPM_ALG_ID macAlg, TPM2B* key); + +//*** CryptCmacData() +// This function is used to add data to the CMAC sequence computation. The function +// will XOR new data into the IV. If the buffer is full, and there is additional +// input data, the data is encrypted into the IV buffer, the new data is then +// XOR into the IV. When the data runs out, the function returns without encrypting +// even if the buffer is full. The last data block of a sequence will not be +// encrypted until the call to CryptCmacEnd(). This is to allow the proper subkey +// to be computed and applied before the last block is encrypted. +void CryptCmacData(SMAC_STATES* state, UINT32 size, const BYTE* buffer); + +//*** CryptCmacEnd() +// This is the completion function for the CMAC. It does padding, if needed, and +// selects the subkey to be applied before the last block is encrypted. +UINT16 +CryptCmacEnd(SMAC_STATES* state, UINT32 outSize, BYTE* outBuffer); +#endif + +#endif // _CRYPT_CMAC_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptDes_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptDes_fp.h new file mode 100644 index 0000000..d797682 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptDes_fp.h @@ -0,0 +1,71 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 28, 2019 Time: 08:25:18PM + */ + +#ifndef _CRYPT_DES_FP_H_ +#define _CRYPT_DES_FP_H_ + +#if ALG_TDES + +//*** CryptSetOddByteParity() +// This function sets the per byte parity of a 64-bit value. The least-significant +// bit is of each byte is replaced with the odd parity of the other 7 bits in the +// byte. With odd parity, no byte will ever be 0x00. +UINT64 +CryptSetOddByteParity(UINT64 k); + +//*** CryptDesValidateKey() +// Function to check to see if the input key is a valid DES key where the definition +// of valid is that none of the elements are on the list of weak, semi-weak, or +// possibly weak keys; and that for two keys, K1!=K2, and for three keys that +// K1!=K2 and K2!=K3. +BOOL CryptDesValidateKey(TPM2B_SYM_KEY* desKey // IN: key to validate +); + +//*** CryptGenerateKeyDes() +// This function is used to create a DES key of the appropriate size. The key will +// have odd parity in the bytes. +TPM_RC +CryptGenerateKeyDes(TPMT_PUBLIC* publicArea, // IN/OUT: The public area template + // for the new key. + TPMT_SENSITIVE* sensitive, // OUT: sensitive area + RAND_STATE* rand // IN: the "entropy" source for +); +#endif + +#endif // _CRYPT_DES_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptEccCrypt_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptEccCrypt_fp.h new file mode 100644 index 0000000..7570598 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptEccCrypt_fp.h @@ -0,0 +1,94 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Feb 28, 2020 Time: 03:04:48PM + */ + +#ifndef _CRYPT_ECC_CRYPT_FP_H_ +#define _CRYPT_ECC_CRYPT_FP_H_ + +#if CC_ECC_Encrypt || CC_ECC_Encrypt + +//*** CryptEccSelectScheme() +// This function is used by TPM2_ECC_Decrypt and TPM2_ECC_Encrypt. It sets scheme +// either the input scheme or the key scheme. If they key scheme is not TPM_ALG_NULL +// then the input scheme must be TPM_ALG_NULL or the same as the key scheme. If +// not, then the function returns FALSE. +// Return Type: BOOL +// TRUE 'scheme' is set +// FALSE 'scheme' is not valid (it may have been changed). +BOOL CryptEccSelectScheme(OBJECT* key, //IN: key containing default scheme + TPMT_KDF_SCHEME* scheme // IN: a decrypt scheme +); + +//*** CryptEccEncrypt() +//This function performs ECC-based data obfuscation. The only scheme that is currently +// supported is MGF1 based. See Part 1, Annex D for details. +// Return Type: TPM_RC +// TPM_RC_CURVE unsupported curve +// TPM_RC_HASH hash not allowed +// TPM_RC_SCHEME 'scheme' is not supported +// TPM_RC_NO_RESULT internal error in big number processing +LIB_EXPORT TPM_RC CryptEccEncrypt( + OBJECT* key, // IN: public key of recipient + TPMT_KDF_SCHEME* scheme, // IN: scheme to use. + TPM2B_MAX_BUFFER* plainText, // IN: the text to obfuscate + TPMS_ECC_POINT* c1, // OUT: public ephemeral key + TPM2B_MAX_BUFFER* c2, // OUT: obfuscated text + TPM2B_DIGEST* c3 // OUT: digest of ephemeral key + // and plainText +); + +//*** CryptEccDecrypt() +// This function performs ECC decryption and integrity check of the input data. +// Return Type: TPM_RC +// TPM_RC_CURVE unsupported curve +// TPM_RC_HASH hash not allowed +// TPM_RC_SCHEME 'scheme' is not supported +// TPM_RC_NO_RESULT internal error in big number processing +// TPM_RC_VALUE C3 did not match hash of recovered data +LIB_EXPORT TPM_RC CryptEccDecrypt( + OBJECT* key, // IN: key used for data recovery + TPMT_KDF_SCHEME* scheme, // IN: scheme to use. + TPM2B_MAX_BUFFER* plainText, // OUT: the recovered text + TPMS_ECC_POINT* c1, // IN: public ephemeral key + TPM2B_MAX_BUFFER* c2, // IN: obfuscated text + TPM2B_DIGEST* c3 // IN: digest of ephemeral key + // and plainText +); +#endif // CC_ECC_Encrypt || CC_ECC_Encrypt + +#endif // _CRYPT_ECC_CRYPT_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptEccKeyExchange_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptEccKeyExchange_fp.h new file mode 100644 index 0000000..28d1f60 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptEccKeyExchange_fp.h @@ -0,0 +1,86 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 28, 2019 Time: 08:25:18PM + */ + +#ifndef _CRYPT_ECC_KEY_EXCHANGE_FP_H_ +#define _CRYPT_ECC_KEY_EXCHANGE_FP_H_ + +#if CC_ZGen_2Phase == YES + +//*** CryptEcc2PhaseKeyExchange() +// This function is the dispatch routine for the EC key exchange functions that use +// two ephemeral and two static keys. +// Return Type: TPM_RC +// TPM_RC_SCHEME scheme is not defined +LIB_EXPORT TPM_RC CryptEcc2PhaseKeyExchange( + TPMS_ECC_POINT* outZ1, // OUT: a computed point + TPMS_ECC_POINT* outZ2, // OUT: and optional second point + TPM_ECC_CURVE curveId, // IN: the curve for the computations + TPM_ALG_ID scheme, // IN: the key exchange scheme + TPM2B_ECC_PARAMETER* dsA, // IN: static private TPM key + TPM2B_ECC_PARAMETER* deA, // IN: ephemeral private TPM key + TPMS_ECC_POINT* QsB, // IN: static public party B key + TPMS_ECC_POINT* QeB // IN: ephemeral public party B key +); +# if ALG_SM2 + +//*** SM2KeyExchange() +// This function performs the key exchange defined in SM2. +// The first step is to compute +// 'tA' = ('dsA' + 'deA' avf(Xe,A)) mod 'n' +// Then, compute the 'Z' value from +// 'outZ' = ('h' 'tA' mod 'n') ('QsA' + [avf('QeB.x')]('QeB')). +// The function will compute the ephemeral public key from the ephemeral +// private key. +// All points are required to be on the curve of 'inQsA'. The function will fail +// catastrophically if this is not the case +// Return Type: TPM_RC +// TPM_RC_NO_RESULT the value for dsA does not give a valid point on the +// curve +LIB_EXPORT TPM_RC SM2KeyExchange( + TPMS_ECC_POINT* outZ, // OUT: the computed point + TPM_ECC_CURVE curveId, // IN: the curve for the computations + TPM2B_ECC_PARAMETER* dsAIn, // IN: static private TPM key + TPM2B_ECC_PARAMETER* deAIn, // IN: ephemeral private TPM key + TPMS_ECC_POINT* QsBIn, // IN: static public party B key + TPMS_ECC_POINT* QeBIn // IN: ephemeral public party B key +); +# endif +#endif // CC_ZGen_2Phase + +#endif // _CRYPT_ECC_KEY_EXCHANGE_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptEccMain_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptEccMain_fp.h new file mode 100644 index 0000000..1ec3736 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptEccMain_fp.h @@ -0,0 +1,318 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Apr 2, 2019 Time: 03:18:00PM + */ + +#ifndef _CRYPT_ECC_MAIN_FP_H_ +#define _CRYPT_ECC_MAIN_FP_H_ + +#if ALG_ECC + +//** Functions +# if SIMULATION +void EccSimulationEnd(void); +# endif // SIMULATION + +//*** CryptEccInit() +// This function is called at _TPM_Init +BOOL CryptEccInit(void); + +//*** CryptEccStartup() +// This function is called at TPM2_Startup(). +BOOL CryptEccStartup(void); + +//*** ClearPoint2B(generic) +// Initialize the size values of a TPMS_ECC_POINT structure. +void ClearPoint2B(TPMS_ECC_POINT* p // IN: the point +); + +//*** CryptEccGetParametersByCurveId() +// This function returns a pointer to the curve data that is associated with +// the indicated curveId. +// If there is no curve with the indicated ID, the function returns NULL. This +// function is in this module so that it can be called by GetCurve data. +// Return Type: const ECC_CURVE_DATA +// NULL curve with the indicated TPM_ECC_CURVE is not implemented +// != NULL pointer to the curve data +LIB_EXPORT const ECC_CURVE* CryptEccGetParametersByCurveId( + TPM_ECC_CURVE curveId // IN: the curveID +); + +//*** CryptEccGetKeySizeForCurve() +// This function returns the key size in bits of the indicated curve. +LIB_EXPORT UINT16 CryptEccGetKeySizeForCurve(TPM_ECC_CURVE curveId // IN: the curve +); + +//*** GetCurveData() +// This function returns the a pointer for the parameter data +// associated with a curve. +const ECC_CURVE_DATA* GetCurveData(TPM_ECC_CURVE curveId // IN: the curveID +); + +//***CryptEccGetOID() +const BYTE* CryptEccGetOID(TPM_ECC_CURVE curveId); + +//*** CryptEccGetCurveByIndex() +// This function returns the number of the 'i'-th implemented curve. The normal +// use would be to call this function with 'i' starting at 0. When the 'i' is greater +// than or equal to the number of implemented curves, TPM_ECC_NONE is returned. +LIB_EXPORT TPM_ECC_CURVE CryptEccGetCurveByIndex(UINT16 i); + +//*** CryptEccGetParameter() +// This function returns an ECC curve parameter. The parameter is +// selected by a single character designator from the set of ""PNABXYH"". +// Return Type: BOOL +// TRUE(1) curve exists and parameter returned +// FALSE(0) curve does not exist or parameter selector +LIB_EXPORT BOOL CryptEccGetParameter( + TPM2B_ECC_PARAMETER* out, // OUT: place to put parameter + char p, // IN: the parameter selector + TPM_ECC_CURVE curveId // IN: the curve id +); + +//*** CryptCapGetECCCurve() +// This function returns the list of implemented ECC curves. +// Return Type: TPMI_YES_NO +// YES if no more ECC curve is available +// NO if there are more ECC curves not reported +TPMI_YES_NO +CryptCapGetECCCurve(TPM_ECC_CURVE curveID, // IN: the starting ECC curve + UINT32 maxCount, // IN: count of returned curves + TPML_ECC_CURVE* curveList // OUT: ECC curve list +); + +//*** CryptGetCurveSignScheme() +// This function will return a pointer to the scheme of the curve. +const TPMT_ECC_SCHEME* CryptGetCurveSignScheme( + TPM_ECC_CURVE curveId // IN: The curve selector +); + +//*** CryptGenerateR() +// This function computes the commit random value for a split signing scheme. +// +// If 'c' is NULL, it indicates that 'r' is being generated +// for TPM2_Commit. +// If 'c' is not NULL, the TPM will validate that the 'gr.commitArray' +// bit associated with the input value of 'c' is SET. If not, the TPM +// returns FALSE and no 'r' value is generated. +// Return Type: BOOL +// TRUE(1) r value computed +// FALSE(0) no r value computed +BOOL CryptGenerateR(TPM2B_ECC_PARAMETER* r, // OUT: the generated random value + UINT16* c, // IN/OUT: count value. + TPMI_ECC_CURVE curveID, // IN: the curve for the value + TPM2B_NAME* name // IN: optional name of a key to + // associate with 'r' +); + +//*** CryptCommit() +// This function is called when the count value is committed. The 'gr.commitArray' +// value associated with the current count value is SET and g_commitCounter is +// incremented. The low-order 16 bits of old value of the counter is returned. +UINT16 +CryptCommit(void); + +//*** CryptEndCommit() +// This function is called when the signing operation using the committed value +// is completed. It clears the gr.commitArray bit associated with the count +// value so that it can't be used again. +void CryptEndCommit(UINT16 c // IN: the counter value of the commitment +); + +//*** CryptEccGetParameters() +// This function returns the ECC parameter details of the given curve. +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) unsupported ECC curve ID +BOOL CryptEccGetParameters( + TPM_ECC_CURVE curveId, // IN: ECC curve ID + TPMS_ALGORITHM_DETAIL_ECC* parameters // OUT: ECC parameters +); + +//*** BnGetCurvePrime() +// This function is used to get just the prime modulus associated with a curve. +const bignum_t* BnGetCurvePrime(TPM_ECC_CURVE curveId); + +//*** BnGetCurveOrder() +// This function is used to get just the curve order +const bignum_t* BnGetCurveOrder(TPM_ECC_CURVE curveId); + +//*** BnIsOnCurve() +// This function checks if a point is on the curve. +BOOL BnIsOnCurve(pointConst Q, const ECC_CURVE_DATA* C); + +//*** BnIsValidPrivateEcc() +// Checks that 0 < 'x' < 'q' +BOOL BnIsValidPrivateEcc(bigConst x, // IN: private key to check + bigCurve E // IN: the curve to check + ); + +LIB_EXPORT BOOL CryptEccIsValidPrivateKey(TPM2B_ECC_PARAMETER* d, + TPM_ECC_CURVE curveId); + +//*** BnPointMul() +// This function does a point multiply of the form 'R' = ['d']'S' + ['u']'Q' where the +// parameters are bigNum values. If 'S' is NULL and d is not NULL, then it computes +// 'R' = ['d']'G' + ['u']'Q' or just 'R' = ['d']'G' if 'u' and 'Q' are NULL. +// If 'skipChecks' is TRUE, then the function will not verify that the inputs are +// correct for the domain. This would be the case when the values were created by the +// CryptoEngine code. +// It will return TPM_RC_NO_RESULT if the resulting point is the point at infinity. +// Return Type: TPM_RC +// TPM_RC_NO_RESULT result of multiplication is a point at infinity +// TPM_RC_ECC_POINT 'S' or 'Q' is not on the curve +// TPM_RC_VALUE 'd' or 'u' is not < n +TPM_RC +BnPointMult(bigPoint R, // OUT: computed point + pointConst S, // IN: optional point to multiply by 'd' + bigConst d, // IN: scalar for [d]S or [d]G + pointConst Q, // IN: optional second point + bigConst u, // IN: optional second scalar + bigCurve E // IN: curve parameters +); + +//***BnEccGetPrivate() +// This function gets random values that are the size of the key plus 64 bits. The +// value is reduced (mod ('q' - 1)) and incremented by 1 ('q' is the order of the +// curve. This produces a value ('d') such that 1 <= 'd' < 'q'. This is the method +// of FIPS 186-4 Section B.4.1 ""Key Pair Generation Using Extra Random Bits"". +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure generating private key +BOOL BnEccGetPrivate(bigNum dOut, // OUT: the qualified random value + const ECC_CURVE_DATA* C, // IN: curve for which the private key + // needs to be appropriate + RAND_STATE* rand // IN: state for DRBG +); + +//*** BnEccGenerateKeyPair() +// This function gets a private scalar from the source of random bits and does +// the point multiply to get the public key. +BOOL BnEccGenerateKeyPair(bigNum bnD, // OUT: private scalar + bn_point_t* ecQ, // OUT: public point + bigCurve E, // IN: curve for the point + RAND_STATE* rand // IN: DRBG state to use +); + +//***CryptEccNewKeyPair(***) +// This function creates an ephemeral ECC. It is ephemeral in that +// is expected that the private part of the key will be discarded +LIB_EXPORT TPM_RC CryptEccNewKeyPair( + TPMS_ECC_POINT* Qout, // OUT: the public point + TPM2B_ECC_PARAMETER* dOut, // OUT: the private scalar + TPM_ECC_CURVE curveId // IN: the curve for the key +); + +//*** CryptEccPointMultiply() +// This function computes 'R' := ['dIn']'G' + ['uIn']'QIn'. Where 'dIn' and +// 'uIn' are scalars, 'G' and 'QIn' are points on the specified curve and 'G' is the +// default generator of the curve. +// +// The 'xOut' and 'yOut' parameters are optional and may be set to NULL if not +// used. +// +// It is not necessary to provide 'uIn' if 'QIn' is specified but one of 'uIn' and +// 'dIn' must be provided. If 'dIn' and 'QIn' are specified but 'uIn' is not +// provided, then 'R' = ['dIn']'QIn'. +// +// If the multiply produces the point at infinity, the TPM_RC_NO_RESULT is returned. +// +// The sizes of 'xOut' and yOut' will be set to be the size of the degree of +// the curve +// +// It is a fatal error if 'dIn' and 'uIn' are both unspecified (NULL) or if 'Qin' +// or 'Rout' is unspecified. +// +// Return Type: TPM_RC +// TPM_RC_ECC_POINT the point 'Pin' or 'Qin' is not on the curve +// TPM_RC_NO_RESULT the product point is at infinity +// TPM_RC_CURVE bad curve +// TPM_RC_VALUE 'dIn' or 'uIn' out of range +// +LIB_EXPORT TPM_RC CryptEccPointMultiply( + TPMS_ECC_POINT* Rout, // OUT: the product point R + TPM_ECC_CURVE curveId, // IN: the curve to use + TPMS_ECC_POINT* Pin, // IN: first point (can be null) + TPM2B_ECC_PARAMETER* dIn, // IN: scalar value for [dIn]Qin + // the Pin + TPMS_ECC_POINT* Qin, // IN: point Q + TPM2B_ECC_PARAMETER* uIn // IN: scalar value for the multiplier + // of Q +); + +//*** CryptEccIsPointOnCurve() +// This function is used to test if a point is on a defined curve. It does this +// by checking that 'y'^2 mod 'p' = 'x'^3 + 'a'*'x' + 'b' mod 'p'. +// +// It is a fatal error if 'Q' is not specified (is NULL). +// Return Type: BOOL +// TRUE(1) point is on curve +// FALSE(0) point is not on curve or curve is not supported +LIB_EXPORT BOOL CryptEccIsPointOnCurve( + TPM_ECC_CURVE curveId, // IN: the curve selector + TPMS_ECC_POINT* Qin // IN: the point. +); + +//*** CryptEccGenerateKey() +// This function generates an ECC key pair based on the input parameters. +// This routine uses KDFa to produce candidate numbers. The method is according +// to FIPS 186-3, section B.1.2 "Key Pair Generation by Testing Candidates." +// According to the method in FIPS 186-3, the resulting private value 'd' should be +// 1 <= 'd' < 'n' where 'n' is the order of the base point. +// +// It is a fatal error if 'Qout', 'dOut', is not provided (is NULL). +// +// If the curve is not supported +// If 'seed' is not provided, then a random number will be used for the key +// Return Type: TPM_RC +// TPM_RC_CURVE curve is not supported +// TPM_RC_NO_RESULT could not verify key with signature (FIPS only) +LIB_EXPORT TPM_RC CryptEccGenerateKey( + TPMT_PUBLIC* publicArea, // IN/OUT: The public area template for + // the new key. The public key + // area will be replaced computed + // ECC public key + TPMT_SENSITIVE* sensitive, // OUT: the sensitive area will be + // updated to contain the private + // ECC key and the symmetric + // encryption key + RAND_STATE* rand // IN: if not NULL, the deterministic + // RNG state +); +#endif // ALG_ECC + +#endif // _CRYPT_ECC_MAIN_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptEccSignature_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptEccSignature_fp.h new file mode 100644 index 0000000..e784b77 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptEccSignature_fp.h @@ -0,0 +1,132 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 28, 2019 Time: 08:25:18PM + */ + +#ifndef _CRYPT_ECC_SIGNATURE_FP_H_ +#define _CRYPT_ECC_SIGNATURE_FP_H_ + +#if ALG_ECC + +//*** BnSignEcdsa() +// This function implements the ECDSA signing algorithm. The method is described +// in the comments below. +TPM_RC +BnSignEcdsa(bigNum bnR, // OUT: 'r' component of the signature + bigNum bnS, // OUT: 's' component of the signature + bigCurve E, // IN: the curve used in the signature + // process + bigNum bnD, // IN: private signing key + const TPM2B_DIGEST* digest, // IN: the digest to sign + RAND_STATE* rand // IN: used in debug of signing +); + +//*** CryptEccSign() +// This function is the dispatch function for the various ECC-based +// signing schemes. +// There is a bit of ugliness to the parameter passing. In order to test this, +// we sometime would like to use a deterministic RNG so that we can get the same +// signatures during testing. The easiest way to do this for most schemes is to +// pass in a deterministic RNG and let it return canned values during testing. +// There is a competing need for a canned parameter to use in ECDAA. To accommodate +// both needs with minimal fuss, a special type of RAND_STATE is defined to carry +// the address of the commit value. The setup and handling of this is not very +// different for the caller than what was in previous versions of the code. +// Return Type: TPM_RC +// TPM_RC_SCHEME 'scheme' is not supported +LIB_EXPORT TPM_RC CryptEccSign(TPMT_SIGNATURE* signature, // OUT: signature + OBJECT* signKey, // IN: ECC key to sign the hash + const TPM2B_DIGEST* digest, // IN: digest to sign + TPMT_ECC_SCHEME* scheme, // IN: signing scheme + RAND_STATE* rand); +# if ALG_ECDSA + +//*** BnValidateSignatureEcdsa() +// This function validates an ECDSA signature. rIn and sIn should have been checked +// to make sure that they are in the range 0 < 'v' < 'n' +// Return Type: TPM_RC +// TPM_RC_SIGNATURE signature not valid +TPM_RC +BnValidateSignatureEcdsa(bigNum bnR, // IN: 'r' component of the signature + bigNum bnS, // IN: 's' component of the signature + bigCurve E, // IN: the curve used in the signature + // process + bn_point_t* ecQ, // IN: the public point of the key + const TPM2B_DIGEST* digest // IN: the digest that was signed +); +# endif // ALG_ECDSA + +//*** CryptEccValidateSignature() +// This function validates an EcDsa or EcSchnorr signature. +// The point 'Qin' needs to have been validated to be on the curve of 'curveId'. +// Return Type: TPM_RC +// TPM_RC_SIGNATURE not a valid signature +LIB_EXPORT TPM_RC CryptEccValidateSignature( + TPMT_SIGNATURE* signature, // IN: signature to be verified + OBJECT* signKey, // IN: ECC key signed the hash + const TPM2B_DIGEST* digest // IN: digest that was signed +); + +//***CryptEccCommitCompute() +// This function performs the point multiply operations required by TPM2_Commit. +// +// If 'B' or 'M' is provided, they must be on the curve defined by 'curveId'. This +// routine does not check that they are on the curve and results are unpredictable +// if they are not. +// +// It is a fatal error if 'r' is NULL. If 'B' is not NULL, then it is a +// fatal error if 'd' is NULL or if 'K' and 'L' are both NULL. +// If 'M' is not NULL, then it is a fatal error if 'E' is NULL. +// +// Return Type: TPM_RC +// TPM_RC_NO_RESULT if 'K', 'L' or 'E' was computed to be the point +// at infinity +// TPM_RC_CANCELED a cancel indication was asserted during this +// function +LIB_EXPORT TPM_RC CryptEccCommitCompute( + TPMS_ECC_POINT* K, // OUT: [d]B or [r]Q + TPMS_ECC_POINT* L, // OUT: [r]B + TPMS_ECC_POINT* E, // OUT: [r]M + TPM_ECC_CURVE curveId, // IN: the curve for the computations + TPMS_ECC_POINT* M, // IN: M (optional) + TPMS_ECC_POINT* B, // IN: B (optional) + TPM2B_ECC_PARAMETER* d, // IN: d (optional) + TPM2B_ECC_PARAMETER* r // IN: the computed r value (required) +); +#endif // ALG_ECC + +#endif // _CRYPT_ECC_SIGNATURE_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptHash_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptHash_fp.h new file mode 100644 index 0000000..9bd4c3f --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptHash_fp.h @@ -0,0 +1,369 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Feb 28, 2020 Time: 03:04:48PM + */ + +#ifndef _CRYPT_HASH_FP_H_ +#define _CRYPT_HASH_FP_H_ + +//*** CryptHashInit() +// This function is called by _TPM_Init do perform the initialization operations for +// the library. +BOOL CryptHashInit(void); + +//*** CryptHashStartup() +// This function is called by TPM2_Startup(). It checks that the size of the +// HashDefArray is consistent with the HASH_COUNT. +BOOL CryptHashStartup(void); + +//*** CryptGetHashDef() +// This function accesses the hash descriptor associated with a hash a +// algorithm. The function returns a pointer to a 'null' descriptor if hashAlg is +// TPM_ALG_NULL or not a defined algorithm. +PHASH_DEF +CryptGetHashDef(TPM_ALG_ID hashAlg); + +//*** CryptHashIsValidAlg() +// This function tests to see if an algorithm ID is a valid hash algorithm. If +// flag is true, then TPM_ALG_NULL is a valid hash. +// Return Type: BOOL +// TRUE(1) hashAlg is a valid, implemented hash on this TPM +// FALSE(0) hashAlg is not valid for this TPM +BOOL CryptHashIsValidAlg(TPM_ALG_ID hashAlg, // IN: the algorithm to check + BOOL flag // IN: TRUE if TPM_ALG_NULL is to be treated + // as a valid hash +); + +//*** CryptHashGetAlgByIndex() +// This function is used to iterate through the hashes. TPM_ALG_NULL +// is returned for all indexes that are not valid hashes. +// If the TPM implements 3 hashes, then an 'index' value of 0 will +// return the first implemented hash and an 'index' of 2 will return the +// last. All other index values will return TPM_ALG_NULL. +// +// Return Type: TPM_ALG_ID +// TPM_ALG_xxx a hash algorithm +// TPM_ALG_NULL this can be used as a stop value +LIB_EXPORT TPM_ALG_ID CryptHashGetAlgByIndex(UINT32 index // IN: the index +); + +//*** CryptHashGetDigestSize() +// Returns the size of the digest produced by the hash. If 'hashAlg' is not a hash +// algorithm, the TPM will FAIL. +// Return Type: UINT16 +// 0 TPM_ALG_NULL +// > 0 the digest size +// +LIB_EXPORT UINT16 CryptHashGetDigestSize( + TPM_ALG_ID hashAlg // IN: hash algorithm to look up +); + +//*** CryptHashGetBlockSize() +// Returns the size of the block used by the hash. If 'hashAlg' is not a hash +// algorithm, the TPM will FAIL. +// Return Type: UINT16 +// 0 TPM_ALG_NULL +// > 0 the digest size +// +LIB_EXPORT UINT16 CryptHashGetBlockSize( + TPM_ALG_ID hashAlg // IN: hash algorithm to look up +); + +//*** CryptHashGetOid() +// This function returns a pointer to DER=encoded OID for a hash algorithm. All OIDs +// are full OID values including the Tag (0x06) and length byte. +LIB_EXPORT const BYTE* CryptHashGetOid(TPM_ALG_ID hashAlg); + +//*** CryptHashGetContextAlg() +// This function returns the hash algorithm associated with a hash context. +TPM_ALG_ID +CryptHashGetContextAlg(PHASH_STATE state // IN: the context to check +); + +//*** CryptHashCopyState +// This function is used to clone a HASH_STATE. +LIB_EXPORT void CryptHashCopyState(HASH_STATE* out, // OUT: destination of the state + const HASH_STATE* in // IN: source of the state +); + +//*** CryptHashExportState() +// This function is used to export a hash or HMAC hash state. This function +// would be called when preparing to context save a sequence object. +void CryptHashExportState( + PCHASH_STATE internalFmt, // IN: the hash state formatted for use by + // library + PEXPORT_HASH_STATE externalFmt // OUT: the exported hash state +); + +//*** CryptHashImportState() +// This function is used to import the hash state. This function +// would be called to import a hash state when the context of a sequence object +// was being loaded. +void CryptHashImportState( + PHASH_STATE internalFmt, // OUT: the hash state formatted for use by + // the library + PCEXPORT_HASH_STATE externalFmt // IN: the exported hash state +); + +//*** CryptHashStart() +// Functions starts a hash stack +// Start a hash stack and returns the digest size. As a side effect, the +// value of 'stateSize' in hashState is updated to indicate the number of bytes +// of state that were saved. This function calls GetHashServer() and that function +// will put the TPM into failure mode if the hash algorithm is not supported. +// +// This function does not use the sequence parameter. If it is necessary to import +// or export context, this will start the sequence in a local state +// and export the state to the input buffer. Will need to add a flag to the state +// structure to indicate that it needs to be imported before it can be used. +// (BLEH). +// Return Type: UINT16 +// 0 hash is TPM_ALG_NULL +// >0 digest size +LIB_EXPORT UINT16 CryptHashStart( + PHASH_STATE hashState, // OUT: the running hash state + TPM_ALG_ID hashAlg // IN: hash algorithm +); + +//*** CryptDigestUpdate() +// Add data to a hash or HMAC, SMAC stack. +// +void CryptDigestUpdate(PHASH_STATE hashState, // IN: the hash context information + UINT32 dataSize, // IN: the size of data to be added + const BYTE* data // IN: data to be hashed +); + +//*** CryptHashEnd() +// Complete a hash or HMAC computation. This function will place the smaller of +// 'digestSize' or the size of the digest in 'dOut'. The number of bytes in the +// placed in the buffer is returned. If there is a failure, the returned value +// is <= 0. +// Return Type: UINT16 +// 0 no data returned +// > 0 the number of bytes in the digest or dOutSize, whichever is smaller +LIB_EXPORT UINT16 CryptHashEnd(PHASH_STATE hashState, // IN: the state of hash stack + UINT32 dOutSize, // IN: size of digest buffer + BYTE* dOut // OUT: hash digest +); + +//*** CryptHashBlock() +// Start a hash, hash a single block, update 'digest' and return the size of +// the results. +// +// The 'digestSize' parameter can be smaller than the digest. If so, only the more +// significant bytes are returned. +// Return Type: UINT16 +// >= 0 number of bytes placed in 'dOut' +LIB_EXPORT UINT16 CryptHashBlock(TPM_ALG_ID hashAlg, // IN: The hash algorithm + UINT32 dataSize, // IN: size of buffer to hash + const BYTE* data, // IN: the buffer to hash + UINT32 dOutSize, // IN: size of the digest buffer + BYTE* dOut // OUT: digest buffer +); + +//*** CryptDigestUpdate2B() +// This function updates a digest (hash or HMAC) with a TPM2B. +// +// This function can be used for both HMAC and hash functions so the +// 'digestState' is void so that either state type can be passed. +LIB_EXPORT void CryptDigestUpdate2B(PHASH_STATE state, // IN: the digest state + const TPM2B* bIn // IN: 2B containing the data +); + +//*** CryptHashEnd2B() +// This function is the same as CryptCompleteHash() but the digest is +// placed in a TPM2B. This is the most common use and this is provided +// for specification clarity. 'digest.size' should be set to indicate the number of +// bytes to place in the buffer +// Return Type: UINT16 +// >=0 the number of bytes placed in 'digest.buffer' +LIB_EXPORT UINT16 CryptHashEnd2B( + PHASH_STATE state, // IN: the hash state + P2B digest // IN: the size of the buffer Out: requested + // number of bytes +); + +//*** CryptDigestUpdateInt() +// This function is used to include an integer value to a hash stack. The function +// marshals the integer into its canonical form before calling CryptDigestUpdate(). +LIB_EXPORT void CryptDigestUpdateInt( + void* state, // IN: the state of hash stack + UINT32 intSize, // IN: the size of 'intValue' in bytes + UINT64 intValue // IN: integer value to be hashed +); + +//*** CryptHmacStart() +// This function is used to start an HMAC using a temp +// hash context. The function does the initialization +// of the hash with the HMAC key XOR iPad and updates the +// HMAC key XOR oPad. +// +// The function returns the number of bytes in a digest produced by 'hashAlg'. +// Return Type: UINT16 +// >= 0 number of bytes in digest produced by 'hashAlg' (may be zero) +// +LIB_EXPORT UINT16 CryptHmacStart(PHMAC_STATE state, // IN/OUT: the state buffer + TPM_ALG_ID hashAlg, // IN: the algorithm to use + UINT16 keySize, // IN: the size of the HMAC key + const BYTE* key // IN: the HMAC key +); + +//*** CryptHmacEnd() +// This function is called to complete an HMAC. It will finish the current +// digest, and start a new digest. It will then add the oPadKey and the +// completed digest and return the results in dOut. It will not return more +// than dOutSize bytes. +// Return Type: UINT16 +// >= 0 number of bytes in 'dOut' (may be zero) +LIB_EXPORT UINT16 CryptHmacEnd(PHMAC_STATE state, // IN: the hash state buffer + UINT32 dOutSize, // IN: size of digest buffer + BYTE* dOut // OUT: hash digest +); + +//*** CryptHmacStart2B() +// This function starts an HMAC and returns the size of the digest +// that will be produced. +// +// This function is provided to support the most common use of starting an HMAC +// with a TPM2B key. +// +// The caller must provide a block of memory in which the hash sequence state +// is kept. The caller should not alter the contents of this buffer until the +// hash sequence is completed or abandoned. +// +// Return Type: UINT16 +// > 0 the digest size of the algorithm +// = 0 the hashAlg was TPM_ALG_NULL +LIB_EXPORT UINT16 CryptHmacStart2B( + PHMAC_STATE hmacState, // OUT: the state of HMAC stack. It will be used + // in HMAC update and completion + TPMI_ALG_HASH hashAlg, // IN: hash algorithm + P2B key // IN: HMAC key +); + +//*** CryptHmacEnd2B() +// This function is the same as CryptHmacEnd() but the HMAC result +// is returned in a TPM2B which is the most common use. +// Return Type: UINT16 +// >=0 the number of bytes placed in 'digest' +LIB_EXPORT UINT16 CryptHmacEnd2B( + PHMAC_STATE hmacState, // IN: the state of HMAC stack + P2B digest // OUT: HMAC +); + +//** Mask and Key Generation Functions +//*** CryptMGF_KDF() +// This function performs MGF1/KDF1 or KDF2 using the selected hash. KDF1 and KDF2 are +// T('n') = T('n'-1) || H('seed' || 'counter') with the difference being that, with +// KDF1, 'counter' starts at 0 but with KDF2, 'counter' starts at 1. The caller +// determines which version by setting the initial value of counter to either 0 or 1. +// Note: Any value that is not 0 is considered to be 1. +// +// This function returns the length of the mask produced which +// could be zero if the digest algorithm is not supported +// Return Type: UINT16 +// 0 hash algorithm was TPM_ALG_NULL +// > 0 should be the same as 'mSize' +LIB_EXPORT UINT16 CryptMGF_KDF(UINT32 mSize, // IN: length of the mask to be produced + BYTE* mask, // OUT: buffer to receive the mask + TPM_ALG_ID hashAlg, // IN: hash to use + UINT32 seedSize, // IN: size of the seed + BYTE* seed, // IN: seed size + UINT32 counter // IN: counter initial value +); + +//*** CryptKDFa() +// This function performs the key generation according to Part 1 of the +// TPM specification. +// +// This function returns the number of bytes generated which may be zero. +// +// The 'key' and 'keyStream' pointers are not allowed to be NULL. The other +// pointer values may be NULL. The value of 'sizeInBits' must be no larger +// than (2^18)-1 = 256K bits (32385 bytes). +// +// The 'once' parameter is set to allow incremental generation of a large +// value. If this flag is TRUE, 'sizeInBits' will be used in the HMAC computation +// but only one iteration of the KDF is performed. This would be used for +// XOR obfuscation so that the mask value can be generated in digest-sized +// chunks rather than having to be generated all at once in an arbitrarily +// large buffer and then XORed into the result. If 'once' is TRUE, then +// 'sizeInBits' must be a multiple of 8. +// +// Any error in the processing of this command is considered fatal. +// Return Type: UINT16 +// 0 hash algorithm is not supported or is TPM_ALG_NULL +// > 0 the number of bytes in the 'keyStream' buffer +LIB_EXPORT UINT16 CryptKDFa( + TPM_ALG_ID hashAlg, // IN: hash algorithm used in HMAC + const TPM2B* key, // IN: HMAC key + const TPM2B* label, // IN: a label for the KDF + const TPM2B* contextU, // IN: context U + const TPM2B* contextV, // IN: context V + UINT32 sizeInBits, // IN: size of generated key in bits + BYTE* keyStream, // OUT: key buffer + UINT32* counterInOut, // IN/OUT: caller may provide the iteration + // counter for incremental operations to + // avoid large intermediate buffers. + UINT16 blocks // IN: If non-zero, this is the maximum number + // of blocks to be returned, regardless + // of sizeInBits +); + +//*** CryptKDFe() +// This function implements KDFe() as defined in TPM specification part 1. +// +// This function returns the number of bytes generated which may be zero. +// +// The 'Z' and 'keyStream' pointers are not allowed to be NULL. The other +// pointer values may be NULL. The value of 'sizeInBits' must be no larger +// than (2^18)-1 = 256K bits (32385 bytes). +// Any error in the processing of this command is considered fatal. +// Return Type: UINT16 +// 0 hash algorithm is not supported or is TPM_ALG_NULL +// > 0 the number of bytes in the 'keyStream' buffer +// +LIB_EXPORT UINT16 CryptKDFe(TPM_ALG_ID hashAlg, // IN: hash algorithm used in HMAC + TPM2B* Z, // IN: Z + const TPM2B* label, // IN: a label value for the KDF + TPM2B* partyUInfo, // IN: PartyUInfo + TPM2B* partyVInfo, // IN: PartyVInfo + UINT32 sizeInBits, // IN: size of generated key in bits + BYTE* keyStream // OUT: key buffer +); + +#endif // _CRYPT_HASH_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptPrimeSieve_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptPrimeSieve_fp.h new file mode 100644 index 0000000..2fd4c5f --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptPrimeSieve_fp.h @@ -0,0 +1,137 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Aug 30, 2019 Time: 02:11:54PM + */ + +#ifndef _CRYPT_PRIME_SIEVE_FP_H_ +#define _CRYPT_PRIME_SIEVE_FP_H_ + +#if RSA_KEY_SIEVE + +//*** RsaAdjustPrimeLimit() +// This used during the sieve process. The iterator for getting the +// next prime (RsaNextPrime()) will return primes until it hits the +// limit (primeLimit) set up by this function. This causes the sieve +// process to stop when an appropriate number of primes have been +// sieved. +LIB_EXPORT void RsaAdjustPrimeLimit(uint32_t requestedPrimes); + +//*** RsaNextPrime() +// This the iterator used during the sieve process. The input is the +// last prime returned (or any starting point) and the output is the +// next higher prime. The function returns 0 when the primeLimit is +// reached. +LIB_EXPORT uint32_t RsaNextPrime(uint32_t lastPrime); + +//*** FindNthSetBit() +// This function finds the nth SET bit in a bit array. The 'n' parameter is +// between 1 and the number of bits in the array (always a multiple of 8). +// If called when the array does not have n bits set, it will return -1 +// Return Type: unsigned int +// <0 no bit is set or no bit with the requested number is set +// >=0 the number of the bit in the array that is the nth set +LIB_EXPORT int FindNthSetBit( + const UINT16 aSize, // IN: the size of the array to check + const BYTE* a, // IN: the array to check + const UINT32 n // IN, the number of the SET bit +); + +//*** PrimeSieve() +// This function does a prime sieve over the input 'field' which has as its +// starting address the value in bnN. Since this initializes the Sieve +// using a precomputed field with the bits associated with 3, 5 and 7 already +// turned off, the value of pnN may need to be adjusted by a few counts to allow +// the precomputed field to be used without modification. +// +// To get better performance, one could address the issue of developing the +// composite numbers. When the size of the prime gets large, the time for doing +// the divisions goes up, noticeably. It could be better to develop larger composite +// numbers even if they need to be bigNum's themselves. The object would be to +// reduce the number of times that the large prime is divided into a few large +// divides and then use smaller divides to get to the final 16 bit (or smaller) +// remainders. +LIB_EXPORT UINT32 PrimeSieve(bigNum bnN, // IN/OUT: number to sieve + UINT32 fieldSize, // IN: size of the field area in bytes + BYTE* field // IN: field +); +# ifdef SIEVE_DEBUG + +//***SetFieldSize() +// Function to set the field size used for prime generation. Used for tuning. +LIB_EXPORT uint32_t SetFieldSize(uint32_t newFieldSize); +# endif // SIEVE_DEBUG + +//*** PrimeSelectWithSieve() +// This function will sieve the field around the input prime candidate. If the +// sieve field is not empty, one of the one bits in the field is chosen for testing +// with Miller-Rabin. If the value is prime, 'pnP' is updated with this value +// and the function returns success. If this value is not prime, another +// pseudo-random candidate is chosen and tested. This process repeats until +// all values in the field have been checked. If all bits in the field have +// been checked and none is prime, the function returns FALSE and a new random +// value needs to be chosen. +// Return Type: TPM_RC +// TPM_RC_FAILURE TPM in failure mode, probably due to entropy source +// TPM_RC_SUCCESS candidate is probably prime +// TPM_RC_NO_RESULT candidate is not prime and couldn't find and alternative +// in the field +LIB_EXPORT TPM_RC PrimeSelectWithSieve( + bigNum candidate, // IN/OUT: The candidate to filter + UINT32 e, // IN: the exponent + RAND_STATE* rand // IN: the random number generator state +); +# if RSA_INSTRUMENT + +//*** PrintTuple() +char* PrintTuple(UINT32* i); + +//*** RsaSimulationEnd() +void RsaSimulationEnd(void); + +//*** GetSieveStats() +LIB_EXPORT void GetSieveStats( + uint32_t* trials, uint32_t* emptyFields, uint32_t* averageBits); +# endif +#endif // RSA_KEY_SIEVE +#if !RSA_INSTRUMENT + +//*** RsaSimulationEnd() +// Stub for call when not doing instrumentation. +void RsaSimulationEnd(void); +#endif + +#endif // _CRYPT_PRIME_SIEVE_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptPrime_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptPrime_fp.h new file mode 100644 index 0000000..5bb1fcd --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptPrime_fp.h @@ -0,0 +1,130 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Aug 30, 2019 Time: 02:11:54PM + */ + +#ifndef _CRYPT_PRIME_FP_H_ +#define _CRYPT_PRIME_FP_H_ + +//*** IsPrimeInt() +// This will do a test of a word of up to 32-bits in size. +BOOL IsPrimeInt(uint32_t n); + +//*** BnIsProbablyPrime() +// This function is used when the key sieve is not implemented. This function +// Will try to eliminate some of the obvious things before going on +// to perform MillerRabin as a final verification of primeness. +BOOL BnIsProbablyPrime(bigNum prime, // IN: + RAND_STATE* rand // IN: the random state just + // in case Miller-Rabin is required +); + +//*** MillerRabinRounds() +// Function returns the number of Miller-Rabin rounds necessary to give an +// error probability equal to the security strength of the prime. These values +// are from FIPS 186-3. +UINT32 +MillerRabinRounds(UINT32 bits // IN: Number of bits in the RSA prime +); + +//*** MillerRabin() +// This function performs a Miller-Rabin test from FIPS 186-3. It does +// 'iterations' trials on the number. In all likelihood, if the number +// is not prime, the first test fails. +// Return Type: BOOL +// TRUE(1) probably prime +// FALSE(0) composite +BOOL MillerRabin(bigNum bnW, RAND_STATE* rand); +#if ALG_RSA + +//*** RsaCheckPrime() +// This will check to see if a number is prime and appropriate for an +// RSA prime. +// +// This has different functionality based on whether we are using key +// sieving or not. If not, the number checked to see if it is divisible by +// the public exponent, then the number is adjusted either up or down +// in order to make it a better candidate. It is then checked for being +// probably prime. +// +// If sieving is used, the number is used to root a sieving process. +// +TPM_RC +RsaCheckPrime(bigNum prime, UINT32 exponent, RAND_STATE* rand); + +//*** RsaAdjustPrimeCandiate() +// For this math, we assume that the RSA numbers are fixed-point numbers with +// the decimal point to the "left" of the most significant bit. This approach helps +// make it clear what is happening with the MSb of the values. +// The two RSA primes have to be large enough so that their product will be a number +// with the necessary number of significant bits. For example, we want to be able +// to multiply two 1024-bit numbers to produce a number with 2028 significant bits. If +// we accept any 1024-bit prime that has its MSb set, then it is possible to produce a +// product that does not have the MSb SET. For example, if we use tiny keys of 16 bits +// and have two 8-bit 'primes' of 0x80, then the public key would be 0x4000 which is +// only 15-bits. So, what we need to do is made sure that each of the primes is large +// enough so that the product of the primes is twice as large as each prime. A little +// arithmetic will show that the only way to do this is to make sure that each of the +// primes is no less than root(2)/2. That's what this functions does. +// This function adjusts the candidate prime so that it is odd and >= root(2)/2. +// This allows the product of these two numbers to be .5, which, in fixed point +// notation means that the most significant bit is 1. +// For this routine, the root(2)/2 (0.7071067811865475) approximated with 0xB505 +// which is, in fixed point, 0.7071075439453125 or an error of 0.000108%. Just setting +// the upper two bits would give a value > 0.75 which is an error of > 6%. Given the +// amount of time all the other computations take, reducing the error is not much of +// a cost, but it isn't totally required either. +// +// This function can be replaced with a function that just sets the two most +// significant bits of each prime candidate without introducing any computational +// issues. +// +LIB_EXPORT void RsaAdjustPrimeCandidate(bigNum prime); + +//***BnGeneratePrimeForRSA() +// Function to generate a prime of the desired size with the proper attributes +// for an RSA prime. +TPM_RC +BnGeneratePrimeForRSA(bigNum prime, // IN/OUT: points to the BN that will get the + // random value + UINT32 bits, // IN: number of bits to get + UINT32 exponent, // IN: the exponent + RAND_STATE* rand // IN: the random state +); +#endif // ALG_RSA + +#endif // _CRYPT_PRIME_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptRand_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptRand_fp.h new file mode 100644 index 0000000..0bb6126 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptRand_fp.h @@ -0,0 +1,182 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 4, 2020 Time: 02:36:44PM + */ + +#ifndef _CRYPT_RAND_FP_H_ +#define _CRYPT_RAND_FP_H_ + +//*** DRBG_GetEntropy() +// Even though this implementation never fails, it may get blocked +// indefinitely long in the call to get entropy from the platform +// (DRBG_GetEntropy32()). +// This function is only used during instantiation of the DRBG for +// manufacturing and on each start-up after an non-orderly shutdown. +// +// Return Type: BOOL +// TRUE(1) requested entropy returned +// FALSE(0) entropy Failure +BOOL DRBG_GetEntropy(UINT32 requiredEntropy, // IN: requested number of bytes of full + // entropy + BYTE* entropy // OUT: buffer to return collected entropy +); + +//*** IncrementIv() +// This function increments the IV value by 1. It is used by EncryptDRBG(). +void IncrementIv(DRBG_IV* iv); + +//*** DRBG_Reseed() +// This function is used when reseeding of the DRBG is required. If +// entropy is provided, it is used in lieu of using hardware entropy. +// Note: the provided entropy must be the required size. +// +// Return Type: BOOL +// TRUE(1) reseed succeeded +// FALSE(0) reseed failed, probably due to the entropy generation +BOOL DRBG_Reseed(DRBG_STATE* drbgState, // IN: the state to update + DRBG_SEED* providedEntropy, // IN: entropy + DRBG_SEED* additionalData // IN: +); + +//*** DRBG_SelfTest() +// This is run when the DRBG is instantiated and at startup. +// +// Return Type: BOOL +// TRUE(1) test OK +// FALSE(0) test failed +BOOL DRBG_SelfTest(void); + +//*** CryptRandomStir() +// This function is used to cause a reseed. A DRBG_SEED amount of entropy is +// collected from the hardware and then additional data is added. +// +// Return Type: TPM_RC +// TPM_RC_NO_RESULT failure of the entropy generator +LIB_EXPORT TPM_RC CryptRandomStir(UINT16 additionalDataSize, BYTE* additionalData); + +//*** CryptRandomGenerate() +// Generate a 'randomSize' number or random bytes. +LIB_EXPORT UINT16 CryptRandomGenerate(UINT16 randomSize, BYTE* buffer); + +//*** DRBG_InstantiateSeededKdf() +// This function is used to instantiate a KDF-based RNG. This is used for derivations. +// This function always returns TRUE. +LIB_EXPORT BOOL DRBG_InstantiateSeededKdf( + KDF_STATE* state, // OUT: buffer to hold the state + TPM_ALG_ID hashAlg, // IN: hash algorithm + TPM_ALG_ID kdf, // IN: the KDF to use + TPM2B* seed, // IN: the seed to use + const TPM2B* label, // IN: a label for the generation process. + TPM2B* context, // IN: the context value + UINT32 limit // IN: Maximum number of bits from the KDF +); + +//*** DRBG_AdditionalData() +// Function to reseed the DRBG with additional entropy. This is normally called +// before computing the protection value of a primary key in the Endorsement +// hierarchy. +LIB_EXPORT void DRBG_AdditionalData(DRBG_STATE* drbgState, // IN:OUT state to update + TPM2B* additionalData // IN: value to incorporate +); + +//*** DRBG_InstantiateSeeded() +// This function is used to instantiate a random number generator from seed values. +// The nominal use of this generator is to create sequences of pseudo-random +// numbers from a seed value. +// +// Return Type: TPM_RC +// TPM_RC_FAILURE DRBG self-test failure +LIB_EXPORT TPM_RC DRBG_InstantiateSeeded( + DRBG_STATE* drbgState, // IN/OUT: buffer to hold the state + const TPM2B* seed, // IN: the seed to use + const TPM2B* purpose, // IN: a label for the generation process. + const TPM2B* name, // IN: name of the object + const TPM2B* additional // IN: additional data +); + +//*** CryptRandStartup() +// This function is called when TPM_Startup is executed. This function always returns +// TRUE. +LIB_EXPORT BOOL CryptRandStartup(void); + +//**** CryptRandInit() +// This function is called when _TPM_Init is being processed. +// +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure +LIB_EXPORT BOOL CryptRandInit(void); + +//*** DRBG_Generate() +// This function generates a random sequence according SP800-90A. +// If 'random' is not NULL, then 'randomSize' bytes of random values are generated. +// If 'random' is NULL or 'randomSize' is zero, then the function returns +// zero without generating any bits or updating the reseed counter. +// This function returns the number of bytes produced which could be less than the +// number requested if the request is too large ("too large" is implementation +// dependent.) +LIB_EXPORT UINT16 DRBG_Generate( + RAND_STATE* state, + BYTE* random, // OUT: buffer to receive the random values + UINT16 randomSize // IN: the number of bytes to generate +); + +//*** DRBG_Instantiate() +// This is CTR_DRBG_Instantiate_algorithm() from [SP 800-90A 10.2.1.3.1]. +// This is called when a the TPM DRBG is to be instantiated. This is +// called to instantiate a DRBG used by the TPM for normal +// operations. +// +// Return Type: BOOL +// TRUE(1) instantiation succeeded +// FALSE(0) instantiation failed +LIB_EXPORT BOOL DRBG_Instantiate( + DRBG_STATE* drbgState, // OUT: the instantiated value + UINT16 pSize, // IN: Size of personalization string + BYTE* personalization // IN: The personalization string +); + +//*** DRBG_Uninstantiate() +// This is Uninstantiate_function() from [SP 800-90A 9.4]. +// +// Return Type: TPM_RC +// TPM_RC_VALUE not a valid state +LIB_EXPORT TPM_RC DRBG_Uninstantiate( + DRBG_STATE* drbgState // IN/OUT: working state to erase +); + +#endif // _CRYPT_RAND_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptRsa_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptRsa_fp.h new file mode 100644 index 0000000..0f93330 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptRsa_fp.h @@ -0,0 +1,187 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Apr 2, 2019 Time: 03:18:00PM + */ + +#ifndef _CRYPT_RSA_FP_H_ +#define _CRYPT_RSA_FP_H_ + +#if ALG_RSA + +//*** CryptRsaInit() +// Function called at _TPM_Init(). +BOOL CryptRsaInit(void); + +//*** CryptRsaStartup() +// Function called at TPM2_Startup() +BOOL CryptRsaStartup(void); + +//*** CryptRsaPssSaltSize() +// This function computes the salt size used in PSS. It is broken out so that +// the X509 code can get the same value that is used by the encoding function in this +// module. +INT16 +CryptRsaPssSaltSize(INT16 hashSize, INT16 outSize); + +//*** MakeDerTag() +// Construct the DER value that is used in RSASSA +// Return Type: INT16 +// > 0 size of value +// <= 0 no hash exists +INT16 +MakeDerTag(TPM_ALG_ID hashAlg, INT16 sizeOfBuffer, BYTE* buffer); + +//*** CryptRsaSelectScheme() +// This function is used by TPM2_RSA_Decrypt and TPM2_RSA_Encrypt. It sets up +// the rules to select a scheme between input and object default. +// This function assume the RSA object is loaded. +// If a default scheme is defined in object, the default scheme should be chosen, +// otherwise, the input scheme should be chosen. +// In the case that both the object and 'scheme' are not TPM_ALG_NULL, then +// if the schemes are the same, the input scheme will be chosen. +// if the scheme are not compatible, a NULL pointer will be returned. +// +// The return pointer may point to a TPM_ALG_NULL scheme. +TPMT_RSA_DECRYPT* CryptRsaSelectScheme( + TPMI_DH_OBJECT rsaHandle, // IN: handle of an RSA key + TPMT_RSA_DECRYPT* scheme // IN: a sign or decrypt scheme +); + +//*** CryptRsaLoadPrivateExponent() +// This function is called to generate the private exponent of an RSA key. +// Return Type: TPM_RC +// TPM_RC_BINDING public and private parts of 'rsaKey' are not matched +TPM_RC +CryptRsaLoadPrivateExponent(TPMT_PUBLIC* publicArea, TPMT_SENSITIVE* sensitive); + +//*** CryptRsaEncrypt() +// This is the entry point for encryption using RSA. Encryption is +// use of the public exponent. The padding parameter determines what +// padding will be used. +// +// The 'cOutSize' parameter must be at least as large as the size of the key. +// +// If the padding is RSA_PAD_NONE, 'dIn' is treated as a number. It must be +// lower in value than the key modulus. +// NOTE: If dIn has fewer bytes than cOut, then we don't add low-order zeros to +// dIn to make it the size of the RSA key for the call to RSAEP. This is +// because the high order bytes of dIn might have a numeric value that is +// greater than the value of the key modulus. If this had low-order zeros +// added, it would have a numeric value larger than the modulus even though +// it started out with a lower numeric value. +// +// Return Type: TPM_RC +// TPM_RC_VALUE 'cOutSize' is too small (must be the size +// of the modulus) +// TPM_RC_SCHEME 'padType' is not a supported scheme +// +LIB_EXPORT TPM_RC CryptRsaEncrypt( + TPM2B_PUBLIC_KEY_RSA* cOut, // OUT: the encrypted data + TPM2B* dIn, // IN: the data to encrypt + OBJECT* key, // IN: the key used for encryption + TPMT_RSA_DECRYPT* scheme, // IN: the type of padding and hash + // if needed + const TPM2B* label, // IN: in case it is needed + RAND_STATE* rand // IN: random number generator + // state (mostly for testing) +); + +//*** CryptRsaDecrypt() +// This is the entry point for decryption using RSA. Decryption is +// use of the private exponent. The 'padType' parameter determines what +// padding was used. +// +// Return Type: TPM_RC +// TPM_RC_SIZE 'cInSize' is not the same as the size of the public +// modulus of 'key'; or numeric value of the encrypted +// data is greater than the modulus +// TPM_RC_VALUE 'dOutSize' is not large enough for the result +// TPM_RC_SCHEME 'padType' is not supported +// +LIB_EXPORT TPM_RC CryptRsaDecrypt( + TPM2B* dOut, // OUT: the decrypted data + TPM2B* cIn, // IN: the data to decrypt + OBJECT* key, // IN: the key to use for decryption + TPMT_RSA_DECRYPT* scheme, // IN: the padding scheme + const TPM2B* label // IN: in case it is needed for the scheme +); + +//*** CryptRsaSign() +// This function is used to generate an RSA signature of the type indicated in +// 'scheme'. +// +// Return Type: TPM_RC +// TPM_RC_SCHEME 'scheme' or 'hashAlg' are not supported +// TPM_RC_VALUE 'hInSize' does not match 'hashAlg' (for RSASSA) +// +LIB_EXPORT TPM_RC CryptRsaSign(TPMT_SIGNATURE* sigOut, + OBJECT* key, // IN: key to use + TPM2B_DIGEST* hIn, // IN: the digest to sign + RAND_STATE* rand // IN: the random number generator + // to use (mostly for testing) +); + +//*** CryptRsaValidateSignature() +// This function is used to validate an RSA signature. If the signature is valid +// TPM_RC_SUCCESS is returned. If the signature is not valid, TPM_RC_SIGNATURE is +// returned. Other return codes indicate either parameter problems or fatal errors. +// +// Return Type: TPM_RC +// TPM_RC_SIGNATURE the signature does not check +// TPM_RC_SCHEME unsupported scheme or hash algorithm +// +LIB_EXPORT TPM_RC CryptRsaValidateSignature( + TPMT_SIGNATURE* sig, // IN: signature + OBJECT* key, // IN: public modulus + TPM2B_DIGEST* digest // IN: The digest being validated +); + +//*** CryptRsaGenerateKey() +// Generate an RSA key from a provided seed +// Return Type: TPM_RC +// TPM_RC_CANCELED operation was canceled +// TPM_RC_RANGE public exponent is not supported +// TPM_RC_VALUE could not find a prime using the provided parameters +LIB_EXPORT TPM_RC CryptRsaGenerateKey( + TPMT_PUBLIC* publicArea, + TPMT_SENSITIVE* sensitive, + RAND_STATE* rand // IN: if not NULL, the deterministic + // RNG state +); +#endif // ALG_RSA + +#endif // _CRYPT_RSA_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptSelfTest_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptSelfTest_fp.h new file mode 100644 index 0000000..ec7c9c8 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptSelfTest_fp.h @@ -0,0 +1,100 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 4, 2020 Time: 02:36:44PM + */ + +#ifndef _CRYPT_SELF_TEST_FP_H_ +#define _CRYPT_SELF_TEST_FP_H_ + +//*** CryptSelfTest() +// This function is called to start/complete a full self-test. +// If 'fullTest' is NO, then only the untested algorithms will be run. If +// 'fullTest' is YES, then 'g_untestedDecryptionAlgorithms' is reinitialized and then +// all tests are run. +// This implementation of the reference design does not support processing outside +// the framework of a TPM command. As a consequence, this command does not +// complete until all tests are done. Since this can take a long time, the TPM +// will check after each test to see if the command is canceled. If so, then the +// TPM will returned TPM_RC_CANCELLED. To continue with the self-tests, call +// TPM2_SelfTest(fullTest == No) and the TPM will complete the testing. +// Return Type: TPM_RC +// TPM_RC_CANCELED if the command is canceled +LIB_EXPORT +TPM_RC +CryptSelfTest(TPMI_YES_NO fullTest // IN: if full test is required +); + +//*** CryptIncrementalSelfTest() +// This function is used to perform an incremental self-test. This implementation +// will perform the toTest values before returning. That is, it assumes that the +// TPM cannot perform background tasks between commands. +// +// This command may be canceled. If it is, then there is no return result. +// However, this command can be run again and the incremental progress will not +// be lost. +// Return Type: TPM_RC +// TPM_RC_CANCELED processing of this command was canceled +// TPM_RC_TESTING if toTest list is not empty +// TPM_RC_VALUE an algorithm in the toTest list is not implemented +TPM_RC +CryptIncrementalSelfTest(TPML_ALG* toTest, // IN: list of algorithms to be tested + TPML_ALG* toDoList // OUT: list of algorithms needing test +); + +//*** CryptInitializeToTest() +// This function will initialize the data structures for testing all the +// algorithms. This should not be called unless CryptAlgsSetImplemented() has +// been called +void CryptInitializeToTest(void); + +//*** CryptTestAlgorithm() +// Only point of contact with the actual self tests. If a self-test fails, there +// is no return and the TPM goes into failure mode. +// The call to TestAlgorithm uses an algorithm selector and a bit vector. When the +// test is run, the corresponding bit in 'toTest' and in 'g_toTest' is CLEAR. If +// 'toTest' is NULL, then only the bit in 'g_toTest' is CLEAR. +// There is a special case for the call to TestAlgorithm(). When 'alg' is +// ALG_ERROR, TestAlgorithm() will CLEAR any bit in 'toTest' for which it has +// no test. This allows the knowledge about which algorithms have test to be +// accessed through the interface that provides the test. +// Return Type: TPM_RC +// TPM_RC_CANCELED test was canceled +LIB_EXPORT +TPM_RC +CryptTestAlgorithm(TPM_ALG_ID alg, ALGORITHM_VECTOR* toTest); + +#endif // _CRYPT_SELF_TEST_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptSmac_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptSmac_fp.h new file mode 100644 index 0000000..e2d3dcc --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptSmac_fp.h @@ -0,0 +1,73 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 28, 2019 Time: 08:25:19PM + */ + +#ifndef _CRYPT_SMAC_FP_H_ +#define _CRYPT_SMAC_FP_H_ + +#if SMAC_IMPLEMENTED + +//*** CryptSmacStart() +// Function to start an SMAC. +UINT16 +CryptSmacStart(HASH_STATE* state, + TPMU_PUBLIC_PARMS* keyParameters, + TPM_ALG_ID macAlg, // IN: the type of MAC + TPM2B* key); + +//*** CryptMacStart() +// Function to start either an HMAC or an SMAC. Cannot reuse the CryptHmacStart +// function because of the difference in number of parameters. +UINT16 +CryptMacStart(HMAC_STATE* state, + TPMU_PUBLIC_PARMS* keyParameters, + TPM_ALG_ID macAlg, // IN: the type of MAC + TPM2B* key); + +//*** CryptMacEnd() +// Dispatch to the MAC end function using a size and buffer pointer. +UINT16 +CryptMacEnd(HMAC_STATE* state, UINT32 size, BYTE* buffer); + +//*** CryptMacEnd2B() +// Dispatch to the MAC end function using a 2B. +UINT16 +CryptMacEnd2B(HMAC_STATE* state, TPM2B* data); +#endif // SMAC_IMPLEMENTED + +#endif // _CRYPT_SMAC_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptSym_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptSym_fp.h new file mode 100644 index 0000000..cac60c5 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptSym_fp.h @@ -0,0 +1,114 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Apr 2, 2019 Time: 03:18:00PM + */ + +#ifndef _CRYPT_SYM_FP_H_ +#define _CRYPT_SYM_FP_H_ + +//** Initialization and Data Access Functions +// +//*** CryptSymInit() +// This function is called to do _TPM_Init processing +BOOL CryptSymInit(void); + +//*** CryptSymStartup() +// This function is called to do TPM2_Startup() processing +BOOL CryptSymStartup(void); + +//*** CryptGetSymmetricBlockSize() +// This function returns the block size of the algorithm. The table of bit sizes has +// an entry for each allowed key size. The entry for a key size is 0 if the TPM does +// not implement that key size. The key size table is delimited with a negative number +// (-1). After the delimiter is a list of block sizes with each entry corresponding +// to the key bit size. For most symmetric algorithms, the block size is the same +// regardless of the key size but this arrangement allows them to be different. +// Return Type: INT16 +// <= 0 cipher not supported +// > 0 the cipher block size in bytes +LIB_EXPORT INT16 CryptGetSymmetricBlockSize( + TPM_ALG_ID symmetricAlg, // IN: the symmetric algorithm + UINT16 keySizeInBits // IN: the key size +); + +//** Symmetric Encryption +// This function performs symmetric encryption based on the mode. +// Return Type: TPM_RC +// TPM_RC_SIZE 'dSize' is not a multiple of the block size for an +// algorithm that requires it +// TPM_RC_FAILURE Fatal error +LIB_EXPORT TPM_RC CryptSymmetricEncrypt( + BYTE* dOut, // OUT: + TPM_ALG_ID algorithm, // IN: the symmetric algorithm + UINT16 keySizeInBits, // IN: key size in bits + const BYTE* key, // IN: key buffer. The size of this buffer + // in bytes is (keySizeInBits + 7) / 8 + TPM2B_IV* ivInOut, // IN/OUT: IV for decryption. + TPM_ALG_ID mode, // IN: Mode to use + INT32 dSize, // IN: data size (may need to be a + // multiple of the blockSize) + const BYTE* dIn // IN: data buffer +); + +//*** CryptSymmetricDecrypt() +// This function performs symmetric decryption based on the mode. +// Return Type: TPM_RC +// TPM_RC_FAILURE A fatal error +// TPM_RCS_SIZE 'dSize' is not a multiple of the block size for an +// algorithm that requires it +LIB_EXPORT TPM_RC CryptSymmetricDecrypt( + BYTE* dOut, // OUT: decrypted data + TPM_ALG_ID algorithm, // IN: the symmetric algorithm + UINT16 keySizeInBits, // IN: key size in bits + const BYTE* key, // IN: key buffer. The size of this buffer + // in bytes is (keySizeInBits + 7) / 8 + TPM2B_IV* ivInOut, // IN/OUT: IV for decryption. + TPM_ALG_ID mode, // IN: Mode to use + INT32 dSize, // IN: data size (may need to be a + // multiple of the blockSize) + const BYTE* dIn // IN: data buffer +); + +//*** CryptSymKeyValidate() +// Validate that a provided symmetric key meets the requirements of the TPM +// Return Type: TPM_RC +// TPM_RC_KEY_SIZE Key size specifiers do not match +// TPM_RC_KEY Key is not allowed +TPM_RC +CryptSymKeyValidate(TPMT_SYM_DEF_OBJECT* symDef, TPM2B_SYM_KEY* key); + +#endif // _CRYPT_SYM_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptUtil_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptUtil_fp.h new file mode 100644 index 0000000..307f14b --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/CryptUtil_fp.h @@ -0,0 +1,410 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Aug 30, 2019 Time: 02:11:54PM + */ + +#ifndef _CRYPT_UTIL_FP_H_ +#define _CRYPT_UTIL_FP_H_ + +//*** CryptIsSchemeAnonymous() +// This function is used to test a scheme to see if it is an anonymous scheme +// The only anonymous scheme is ECDAA. ECDAA can be used to do things +// like U-Prove. +BOOL CryptIsSchemeAnonymous(TPM_ALG_ID scheme // IN: the scheme algorithm to test +); + +//*** ParmDecryptSym() +// This function performs parameter decryption using symmetric block cipher. +void ParmDecryptSym(TPM_ALG_ID symAlg, // IN: the symmetric algorithm + TPM_ALG_ID hash, // IN: hash algorithm for KDFa + UINT16 keySizeInBits, // IN: the key size in bits + TPM2B* key, // IN: KDF HMAC key + TPM2B* nonceCaller, // IN: nonce caller + TPM2B* nonceTpm, // IN: nonce TPM + UINT32 dataSize, // IN: size of parameter buffer + BYTE* data // OUT: buffer to be decrypted +); + +//*** ParmEncryptSym() +// This function performs parameter encryption using symmetric block cipher. +void ParmEncryptSym(TPM_ALG_ID symAlg, // IN: symmetric algorithm + TPM_ALG_ID hash, // IN: hash algorithm for KDFa + UINT16 keySizeInBits, // IN: symmetric key size in bits + TPM2B* key, // IN: KDF HMAC key + TPM2B* nonceCaller, // IN: nonce caller + TPM2B* nonceTpm, // IN: nonce TPM + UINT32 dataSize, // IN: size of parameter buffer + BYTE* data // OUT: buffer to be encrypted +); + +//*** CryptXORObfuscation() +// This function implements XOR obfuscation. It should not be called if the +// hash algorithm is not implemented. The only return value from this function +// is TPM_RC_SUCCESS. +void CryptXORObfuscation(TPM_ALG_ID hash, // IN: hash algorithm for KDF + TPM2B* key, // IN: KDF key + TPM2B* contextU, // IN: contextU + TPM2B* contextV, // IN: contextV + UINT32 dataSize, // IN: size of data buffer + BYTE* data // IN/OUT: data to be XORed in place +); + +//*** CryptInit() +// This function is called when the TPM receives a _TPM_Init indication. +// +// NOTE: The hash algorithms do not have to be tested, they just need to be +// available. They have to be tested before the TPM can accept HMAC authorization +// or return any result that relies on a hash algorithm. +// Return Type: BOOL +// TRUE(1) initializations succeeded +// FALSE(0) initialization failed and caller should place the TPM into +// Failure Mode +BOOL CryptInit(void); + +//*** CryptStartup() +// This function is called by TPM2_Startup() to initialize the functions in +// this cryptographic library and in the provided CryptoLibrary. This function +// and CryptUtilInit() are both provided so that the implementation may move the +// initialization around to get the best interaction. +// Return Type: BOOL +// TRUE(1) startup succeeded +// FALSE(0) startup failed and caller should place the TPM into +// Failure Mode +BOOL CryptStartup(STARTUP_TYPE type // IN: the startup type +); + +//**************************************************************************** +//** Algorithm-Independent Functions +//**************************************************************************** +//*** Introduction +// These functions are used generically when a function of a general type +// (e.g., symmetric encryption) is required. The functions will modify the +// parameters as required to interface to the indicated algorithms. +// +//*** CryptIsAsymAlgorithm() +// This function indicates if an algorithm is an asymmetric algorithm. +// Return Type: BOOL +// TRUE(1) if it is an asymmetric algorithm +// FALSE(0) if it is not an asymmetric algorithm +BOOL CryptIsAsymAlgorithm(TPM_ALG_ID algID // IN: algorithm ID +); + +//*** CryptSecretEncrypt() +// This function creates a secret value and its associated secret structure using +// an asymmetric algorithm. +// +// This function is used by TPM2_Rewrap() TPM2_MakeCredential(), +// and TPM2_Duplicate(). +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES 'keyHandle' does not reference a valid decryption key +// TPM_RC_KEY invalid ECC key (public point is not on the curve) +// TPM_RC_SCHEME RSA key with an unsupported padding scheme +// TPM_RC_VALUE numeric value of the data to be decrypted is greater +// than the RSA key modulus +TPM_RC +CryptSecretEncrypt(OBJECT* encryptKey, // IN: encryption key object + const TPM2B* label, // IN: a null-terminated string as L + TPM2B_DATA* data, // OUT: secret value + TPM2B_ENCRYPTED_SECRET* secret // OUT: secret structure +); + +//*** CryptSecretDecrypt() +// Decrypt a secret value by asymmetric (or symmetric) algorithm +// This function is used for ActivateCredential and Import for asymmetric +// decryption, and StartAuthSession for both asymmetric and symmetric +// decryption process +// +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES RSA key is not a decryption key +// TPM_RC_BINDING Invalid RSA key (public and private parts are not +// cryptographically bound. +// TPM_RC_ECC_POINT ECC point in the secret is not on the curve +// TPM_RC_INSUFFICIENT failed to retrieve ECC point from the secret +// TPM_RC_NO_RESULT multiplication resulted in ECC point at infinity +// TPM_RC_SIZE data to decrypt is not of the same size as RSA key +// TPM_RC_VALUE For RSA key, numeric value of the encrypted data is +// greater than the modulus, or the recovered data is +// larger than the output buffer. +// For keyedHash or symmetric key, the secret is +// larger than the size of the digest produced by +// the name algorithm. +// TPM_RC_FAILURE internal error +TPM_RC +CryptSecretDecrypt(OBJECT* decryptKey, // IN: decrypt key + TPM2B_NONCE* nonceCaller, // IN: nonceCaller. It is needed for + // symmetric decryption. For + // asymmetric decryption, this + // parameter is NULL + const TPM2B* label, // IN: a value for L + TPM2B_ENCRYPTED_SECRET* secret, // IN: input secret + TPM2B_DATA* data // OUT: decrypted secret value +); + +//*** CryptParameterEncryption() +// This function does in-place encryption of a response parameter. +void CryptParameterEncryption( + TPM_HANDLE handle, // IN: encrypt session handle + TPM2B* nonceCaller, // IN: nonce caller + INT32 bufferSize, // IN: size of parameter buffer + UINT16 leadingSizeInByte, // IN: the size of the leading size field in + // bytes + TPM2B_AUTH* extraKey, // IN: additional key material other than + // sessionAuth + BYTE* buffer // IN/OUT: parameter buffer to be encrypted +); + +//*** CryptParameterDecryption() +// This function does in-place decryption of a command parameter. +// Return Type: TPM_RC +// TPM_RC_SIZE The number of bytes in the input buffer is less than +// the number of bytes to be decrypted. +TPM_RC +CryptParameterDecryption( + TPM_HANDLE handle, // IN: encrypted session handle + TPM2B* nonceCaller, // IN: nonce caller + INT32 bufferSize, // IN: size of parameter buffer + UINT16 leadingSizeInByte, // IN: the size of the leading size field in + // byte + TPM2B_AUTH* extraKey, // IN: the authValue + BYTE* buffer // IN/OUT: parameter buffer to be decrypted +); + +//*** CryptComputeSymmetricUnique() +// This function computes the unique field in public area for symmetric objects. +void CryptComputeSymmetricUnique( + TPMT_PUBLIC* publicArea, // IN: the object's public area + TPMT_SENSITIVE* sensitive, // IN: the associated sensitive area + TPM2B_DIGEST* unique // OUT: unique buffer +); + +//*** CryptCreateObject() +// This function creates an object. +// For an asymmetric key, it will create a key pair and, for a parent key, a seed +// value for child protections. +// +// For an symmetric object, (TPM_ALG_SYMCIPHER or TPM_ALG_KEYEDHASH), it will +// create a secret key if the caller did not provide one. It will create a random +// secret seed value that is hashed with the secret value to create the public +// unique value. +// +// 'publicArea', 'sensitive', and 'sensitiveCreate' are the only required parameters +// and are the only ones that are used by TPM2_Create(). The other parameters +// are optional and are used when the generated Object needs to be deterministic. +// This is the case for both Primary Objects and Derived Objects. +// +// When a seed value is provided, a RAND_STATE will be populated and used for +// all operations in the object generation that require a random number. In the +// simplest case, TPM2_CreatePrimary() will use 'seed', 'label' and 'context' with +// context being the hash of the template. If the Primary Object is in +// the Endorsement hierarchy, it will also populate 'proof' with ehProof. +// +// For derived keys, 'seed' will be the secret value from the parent, 'label' and +// 'context' will be set according to the parameters of TPM2_CreateLoaded() and +// 'hashAlg' will be set which causes the RAND_STATE to be a KDF generator. +// +// Return Type: TPM_RC +// TPM_RC_KEY a provided key is not an allowed value +// TPM_RC_KEY_SIZE key size in the public area does not match the size +// in the sensitive creation area for a symmetric key +// TPM_RC_NO_RESULT unable to get random values (only in derivation) +// TPM_RC_RANGE for an RSA key, the exponent is not supported +// TPM_RC_SIZE sensitive data size is larger than allowed for the +// scheme for a keyed hash object +// TPM_RC_VALUE exponent is not prime or could not find a prime using +// the provided parameters for an RSA key; +// unsupported name algorithm for an ECC key +TPM_RC +CryptCreateObject(OBJECT* object, // IN: new object structure pointer + TPMS_SENSITIVE_CREATE* sensitiveCreate, // IN: sensitive creation + RAND_STATE* rand // IN: the random number generator + // to use +); + +//*** CryptGetSignHashAlg() +// Get the hash algorithm of signature from a TPMT_SIGNATURE structure. +// It assumes the signature is not NULL +// This is a function for easy access +TPMI_ALG_HASH +CryptGetSignHashAlg(TPMT_SIGNATURE* auth // IN: signature +); + +//*** CryptIsSplitSign() +// This function us used to determine if the signing operation is a split +// signing operation that required a TPM2_Commit(). +// +BOOL CryptIsSplitSign(TPM_ALG_ID scheme // IN: the algorithm selector +); + +//*** CryptIsAsymSignScheme() +// This function indicates if a scheme algorithm is a sign algorithm. +BOOL CryptIsAsymSignScheme(TPMI_ALG_PUBLIC publicType, // IN: Type of the object + TPMI_ALG_ASYM_SCHEME scheme // IN: the scheme +); + +//*** CryptIsAsymDecryptScheme() +// This function indicate if a scheme algorithm is a decrypt algorithm. +BOOL CryptIsAsymDecryptScheme(TPMI_ALG_PUBLIC publicType, // IN: Type of the object + TPMI_ALG_ASYM_SCHEME scheme // IN: the scheme +); + +//*** CryptSelectSignScheme() +// This function is used by the attestation and signing commands. It implements +// the rules for selecting the signature scheme to use in signing. This function +// requires that the signing key either be TPM_RH_NULL or be loaded. +// +// If a default scheme is defined in object, the default scheme should be chosen, +// otherwise, the input scheme should be chosen. +// In the case that both object and input scheme has a non-NULL scheme +// algorithm, if the schemes are compatible, the input scheme will be chosen. +// +// This function should not be called if 'signObject->publicArea.type' == +// ALG_SYMCIPHER. +// +// Return Type: BOOL +// TRUE(1) scheme selected +// FALSE(0) both 'scheme' and key's default scheme are empty; or +// 'scheme' is empty while key's default scheme requires +// explicit input scheme (split signing); or +// non-empty default key scheme differs from 'scheme' +BOOL CryptSelectSignScheme(OBJECT* signObject, // IN: signing key + TPMT_SIG_SCHEME* scheme // IN/OUT: signing scheme +); + +//*** CryptSign() +// Sign a digest with asymmetric key or HMAC. +// This function is called by attestation commands and the generic TPM2_Sign +// command. +// This function checks the key scheme and digest size. It does not +// check if the sign operation is allowed for restricted key. It should be +// checked before the function is called. +// The function will assert if the key is not a signing key. +// +// Return Type: TPM_RC +// TPM_RC_SCHEME 'signScheme' is not compatible with the signing key type +// TPM_RC_VALUE 'digest' value is greater than the modulus of +// 'signHandle' or size of 'hashData' does not match hash +// algorithm in'signScheme' (for an RSA key); +// invalid commit status or failed to generate "r" value +// (for an ECC key) +TPM_RC +CryptSign(OBJECT* signKey, // IN: signing key + TPMT_SIG_SCHEME* signScheme, // IN: sign scheme. + TPM2B_DIGEST* digest, // IN: The digest being signed + TPMT_SIGNATURE* signature // OUT: signature +); + +//*** CryptValidateSignature() +// This function is used to verify a signature. It is called by +// TPM2_VerifySignature() and TPM2_PolicySigned. +// +// Since this operation only requires use of a public key, no consistency +// checks are necessary for the key to signature type because a caller can load +// any public key that they like with any scheme that they like. This routine +// simply makes sure that the signature is correct, whatever the type. +// +// Return Type: TPM_RC +// TPM_RC_SIGNATURE the signature is not genuine +// TPM_RC_SCHEME the scheme is not supported +// TPM_RC_HANDLE an HMAC key was selected but the +// private part of the key is not loaded +TPM_RC +CryptValidateSignature(TPMI_DH_OBJECT keyHandle, // IN: The handle of sign key + TPM2B_DIGEST* digest, // IN: The digest being validated + TPMT_SIGNATURE* signature // IN: signature +); + +//*** CryptGetTestResult +// This function returns the results of a self-test function. +// Note: the behavior in this function is NOT the correct behavior for a real +// TPM implementation. An artificial behavior is placed here due to the +// limitation of a software simulation environment. For the correct behavior, +// consult the part 3 specification for TPM2_GetTestResult(). +TPM_RC +CryptGetTestResult(TPM2B_MAX_BUFFER* outData // OUT: test result data +); + +//*** CryptValidateKeys() +// This function is used to verify that the key material of and object is valid. +// For a 'publicOnly' object, the key is verified for size and, if it is an ECC +// key, it is verified to be on the specified curve. For a key with a sensitive +// area, the binding between the public and private parts of the key are verified. +// If the nameAlg of the key is TPM_ALG_NULL, then the size of the sensitive area +// is verified but the public portion is not verified, unless the key is an RSA key. +// For an RSA key, the reason for loading the sensitive area is to use it. The +// only way to use a private RSA key is to compute the private exponent. To compute +// the private exponent, the public modulus is used. +// Return Type: TPM_RC +// TPM_RC_BINDING the public and private parts are not cryptographically +// bound +// TPM_RC_HASH cannot have a publicOnly key with nameAlg of TPM_ALG_NULL +// TPM_RC_KEY the public unique is not valid +// TPM_RC_KEY_SIZE the private area key is not valid +// TPM_RC_TYPE the types of the sensitive and private parts do not match +TPM_RC +CryptValidateKeys(TPMT_PUBLIC* publicArea, + TPMT_SENSITIVE* sensitive, + TPM_RC blamePublic, + TPM_RC blameSensitive); + +//*** CryptSelectMac() +// This function is used to set the MAC scheme based on the key parameters and +// the input scheme. +// Return Type: TPM_RC +// TPM_RC_SCHEME the scheme is not a valid mac scheme +// TPM_RC_TYPE the input key is not a type that supports a mac +// TPM_RC_VALUE the input scheme and the key scheme are not compatible +TPM_RC +CryptSelectMac(TPMT_PUBLIC* publicArea, TPMI_ALG_MAC_SCHEME* inMac); + +//*** CryptMacIsValidForKey() +// Check to see if the key type is compatible with the mac type +BOOL CryptMacIsValidForKey(TPM_ALG_ID keyType, TPM_ALG_ID macAlg, BOOL flag); + +//*** CryptSmacIsValidAlg() +// This function is used to test if an algorithm is a supported SMAC algorithm. It +// needs to be updated as new algorithms are added. +BOOL CryptSmacIsValidAlg(TPM_ALG_ID alg, + BOOL FLAG // IN: Indicates if TPM_ALG_NULL is valid +); + +//*** CryptSymModeIsValid() +// Function checks to see if an algorithm ID is a valid, symmetric block cipher +// mode for the TPM. If 'flag' is SET, them TPM_ALG_NULL is a valid mode. +// not include the modes used for SMAC +BOOL CryptSymModeIsValid(TPM_ALG_ID mode, BOOL flag); + +#endif // _CRYPT_UTIL_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/DA_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/DA_fp.h new file mode 100644 index 0000000..291ef0e --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/DA_fp.h @@ -0,0 +1,78 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Apr 2, 2019 Time: 04:23:27PM + */ + +#ifndef _DA_FP_H_ +#define _DA_FP_H_ + +//*** DAPreInstall_Init() +// This function initializes the DA parameters to their manufacturer-default +// values. The default values are determined by a platform-specific specification. +// +// This function should not be called outside of a manufacturing or simulation +// environment. +// +// The DA parameters will be restored to these initial values by TPM2_Clear(). +void DAPreInstall_Init(void); + +//*** DAStartup() +// This function is called by TPM2_Startup() to initialize the DA parameters. +// In the case of Startup(CLEAR), use of lockoutAuth will be enabled if the +// lockout recovery time is 0. Otherwise, lockoutAuth will not be enabled until +// the TPM has been continuously powered for the lockoutRecovery time. +// +// This function requires that NV be available and not rate limiting. +BOOL DAStartup(STARTUP_TYPE type // IN: startup type +); + +//*** DARegisterFailure() +// This function is called when a authorization failure occurs on an entity +// that is subject to dictionary-attack protection. When a DA failure is +// triggered, register the failure by resetting the relevant self-healing +// timer to the current time. +void DARegisterFailure(TPM_HANDLE handle // IN: handle for failure +); + +//*** DASelfHeal() +// This function is called to check if sufficient time has passed to allow +// decrement of failedTries or to re-enable use of lockoutAuth. +// +// This function should be called when the time interval is updated. +void DASelfHeal(void); + +#endif // _DA_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/DictionaryAttackLockReset_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/DictionaryAttackLockReset_fp.h new file mode 100644 index 0000000..eaf8843 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/DictionaryAttackLockReset_fp.h @@ -0,0 +1,59 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_DictionaryAttackLockReset // Command must be enabled + +# ifndef _Dictionary_Attack_Lock_Reset_FP_H_ +# define _Dictionary_Attack_Lock_Reset_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_RH_LOCKOUT lockHandle; +} DictionaryAttackLockReset_In; + +// Response code modifiers +# define RC_DictionaryAttackLockReset_lockHandle (TPM_RC_H + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_DictionaryAttackLockReset(DictionaryAttackLockReset_In* in); + +# endif // _Dictionary_Attack_Lock_Reset_FP_H_ +#endif // CC_DictionaryAttackLockReset diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/DictionaryAttackParameters_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/DictionaryAttackParameters_fp.h new file mode 100644 index 0000000..6e3b399 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/DictionaryAttackParameters_fp.h @@ -0,0 +1,65 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_DictionaryAttackParameters // Command must be enabled + +# ifndef _Dictionary_Attack_Parameters_FP_H_ +# define _Dictionary_Attack_Parameters_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_RH_LOCKOUT lockHandle; + UINT32 newMaxTries; + UINT32 newRecoveryTime; + UINT32 lockoutRecovery; +} DictionaryAttackParameters_In; + +// Response code modifiers +# define RC_DictionaryAttackParameters_lockHandle (TPM_RC_H + TPM_RC_1) +# define RC_DictionaryAttackParameters_newMaxTries (TPM_RC_P + TPM_RC_1) +# define RC_DictionaryAttackParameters_newRecoveryTime (TPM_RC_P + TPM_RC_2) +# define RC_DictionaryAttackParameters_lockoutRecovery (TPM_RC_P + TPM_RC_3) + +// Function prototype +TPM_RC +TPM2_DictionaryAttackParameters(DictionaryAttackParameters_In* in); + +# endif // _Dictionary_Attack_Parameters_FP_H_ +#endif // CC_DictionaryAttackParameters diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Duplicate_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Duplicate_fp.h new file mode 100644 index 0000000..cdbd2e9 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Duplicate_fp.h @@ -0,0 +1,73 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_Duplicate // Command must be enabled + +# ifndef _Duplicate_FP_H_ +# define _Duplicate_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_OBJECT objectHandle; + TPMI_DH_OBJECT newParentHandle; + TPM2B_DATA encryptionKeyIn; + TPMT_SYM_DEF_OBJECT symmetricAlg; +} Duplicate_In; + +// Output structure definition +typedef struct +{ + TPM2B_DATA encryptionKeyOut; + TPM2B_PRIVATE duplicate; + TPM2B_ENCRYPTED_SECRET outSymSeed; +} Duplicate_Out; + +// Response code modifiers +# define RC_Duplicate_objectHandle (TPM_RC_H + TPM_RC_1) +# define RC_Duplicate_newParentHandle (TPM_RC_H + TPM_RC_2) +# define RC_Duplicate_encryptionKeyIn (TPM_RC_P + TPM_RC_1) +# define RC_Duplicate_symmetricAlg (TPM_RC_P + TPM_RC_2) + +// Function prototype +TPM_RC +TPM2_Duplicate(Duplicate_In* in, Duplicate_Out* out); + +# endif // _Duplicate_FP_H_ +#endif // CC_Duplicate diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ECC_Decrypt_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ECC_Decrypt_fp.h new file mode 100644 index 0000000..ca7e22f --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ECC_Decrypt_fp.h @@ -0,0 +1,73 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Feb 28, 2020 Time: 03:04:47PM + */ + +#if CC_ECC_Decrypt // Command must be enabled + +# ifndef _ECC_DECRYPT_FP_H_ +# define _ECC_DECRYPT_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_OBJECT keyHandle; + TPM2B_ECC_POINT C1; + TPM2B_MAX_BUFFER C2; + TPM2B_DIGEST C3; + TPMT_KDF_SCHEME inScheme; +} ECC_Decrypt_In; + +// Output structure definition +typedef struct +{ + TPM2B_MAX_BUFFER plainText; +} ECC_Decrypt_Out; + +// Response code modifiers +# define RC_ECC_Decrypt_keyHandle (TPM_RC_H + TPM_RC_1) +# define RC_ECC_Decrypt_C1 (TPM_RC_P + TPM_RC_1) +# define RC_ECC_Decrypt_C2 (TPM_RC_P + TPM_RC_2) +# define RC_ECC_Decrypt_C3 (TPM_RC_P + TPM_RC_3) +# define RC_ECC_Decrypt_inScheme (TPM_RC_P + TPM_RC_4) + +// Function prototype +TPM_RC +TPM2_ECC_Decrypt(ECC_Decrypt_In* in, ECC_Decrypt_Out* out); + +# endif // _ECC_DECRYPT_FP_H_ +#endif // CC_ECC_Decrypt diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ECC_Encrypt_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ECC_Encrypt_fp.h new file mode 100644 index 0000000..2dfed38 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ECC_Encrypt_fp.h @@ -0,0 +1,71 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Feb 28, 2020 Time: 03:04:47PM + */ + +#if CC_ECC_Encrypt // Command must be enabled + +# ifndef _ECC_ENCRYPT_FP_H_ +# define _ECC_ENCRYPT_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_OBJECT keyHandle; + TPM2B_MAX_BUFFER plainText; + TPMT_KDF_SCHEME inScheme; +} ECC_Encrypt_In; + +// Output structure definition +typedef struct +{ + TPM2B_ECC_POINT C1; + TPM2B_MAX_BUFFER C2; + TPM2B_DIGEST C3; +} ECC_Encrypt_Out; + +// Response code modifiers +# define RC_ECC_Encrypt_keyHandle (TPM_RC_H + TPM_RC_1) +# define RC_ECC_Encrypt_plainText (TPM_RC_P + TPM_RC_1) +# define RC_ECC_Encrypt_inScheme (TPM_RC_P + TPM_RC_2) + +// Function prototype +TPM_RC +TPM2_ECC_Encrypt(ECC_Encrypt_In* in, ECC_Encrypt_Out* out); + +# endif // _ECC_ENCRYPT_FP_H_ +#endif // CC_ECC_Encrypt diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ECC_Parameters_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ECC_Parameters_fp.h new file mode 100644 index 0000000..94c3918 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ECC_Parameters_fp.h @@ -0,0 +1,65 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_ECC_Parameters // Command must be enabled + +# ifndef _ECC_Parameters_FP_H_ +# define _ECC_Parameters_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_ECC_CURVE curveID; +} ECC_Parameters_In; + +// Output structure definition +typedef struct +{ + TPMS_ALGORITHM_DETAIL_ECC parameters; +} ECC_Parameters_Out; + +// Response code modifiers +# define RC_ECC_Parameters_curveID (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_ECC_Parameters(ECC_Parameters_In* in, ECC_Parameters_Out* out); + +# endif // _ECC_Parameters_FP_H_ +#endif // CC_ECC_Parameters diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ECDH_KeyGen_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ECDH_KeyGen_fp.h new file mode 100644 index 0000000..71309f5 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ECDH_KeyGen_fp.h @@ -0,0 +1,66 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_ECDH_KeyGen // Command must be enabled + +# ifndef _ECDH_Key_Gen_FP_H_ +# define _ECDH_Key_Gen_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_OBJECT keyHandle; +} ECDH_KeyGen_In; + +// Output structure definition +typedef struct +{ + TPM2B_ECC_POINT zPoint; + TPM2B_ECC_POINT pubPoint; +} ECDH_KeyGen_Out; + +// Response code modifiers +# define RC_ECDH_KeyGen_keyHandle (TPM_RC_H + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_ECDH_KeyGen(ECDH_KeyGen_In* in, ECDH_KeyGen_Out* out); + +# endif // _ECDH_Key_Gen_FP_H_ +#endif // CC_ECDH_KeyGen diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ECDH_ZGen_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ECDH_ZGen_fp.h new file mode 100644 index 0000000..4abba61 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ECDH_ZGen_fp.h @@ -0,0 +1,67 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_ECDH_ZGen // Command must be enabled + +# ifndef _ECDH_ZGen_FP_H_ +# define _ECDH_ZGen_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_OBJECT keyHandle; + TPM2B_ECC_POINT inPoint; +} ECDH_ZGen_In; + +// Output structure definition +typedef struct +{ + TPM2B_ECC_POINT outPoint; +} ECDH_ZGen_Out; + +// Response code modifiers +# define RC_ECDH_ZGen_keyHandle (TPM_RC_H + TPM_RC_1) +# define RC_ECDH_ZGen_inPoint (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_ECDH_ZGen(ECDH_ZGen_In* in, ECDH_ZGen_Out* out); + +# endif // _ECDH_ZGen_FP_H_ +#endif // CC_ECDH_ZGen diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/EC_Ephemeral_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/EC_Ephemeral_fp.h new file mode 100644 index 0000000..718b90b --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/EC_Ephemeral_fp.h @@ -0,0 +1,66 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_EC_Ephemeral // Command must be enabled + +# ifndef _EC_Ephemeral_FP_H_ +# define _EC_Ephemeral_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_ECC_CURVE curveID; +} EC_Ephemeral_In; + +// Output structure definition +typedef struct +{ + TPM2B_ECC_POINT Q; + UINT16 counter; +} EC_Ephemeral_Out; + +// Response code modifiers +# define RC_EC_Ephemeral_curveID (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_EC_Ephemeral(EC_Ephemeral_In* in, EC_Ephemeral_Out* out); + +# endif // _EC_Ephemeral_FP_H_ +#endif // CC_EC_Ephemeral diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/EncryptDecrypt2_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/EncryptDecrypt2_fp.h new file mode 100644 index 0000000..831f808 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/EncryptDecrypt2_fp.h @@ -0,0 +1,74 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_EncryptDecrypt2 // Command must be enabled + +# ifndef _Encrypt_Decrypt2_FP_H_ +# define _Encrypt_Decrypt2_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_OBJECT keyHandle; + TPM2B_MAX_BUFFER inData; + TPMI_YES_NO decrypt; + TPMI_ALG_CIPHER_MODE mode; + TPM2B_IV ivIn; +} EncryptDecrypt2_In; + +// Output structure definition +typedef struct +{ + TPM2B_MAX_BUFFER outData; + TPM2B_IV ivOut; +} EncryptDecrypt2_Out; + +// Response code modifiers +# define RC_EncryptDecrypt2_keyHandle (TPM_RC_H + TPM_RC_1) +# define RC_EncryptDecrypt2_inData (TPM_RC_P + TPM_RC_1) +# define RC_EncryptDecrypt2_decrypt (TPM_RC_P + TPM_RC_2) +# define RC_EncryptDecrypt2_mode (TPM_RC_P + TPM_RC_3) +# define RC_EncryptDecrypt2_ivIn (TPM_RC_P + TPM_RC_4) + +// Function prototype +TPM_RC +TPM2_EncryptDecrypt2(EncryptDecrypt2_In* in, EncryptDecrypt2_Out* out); + +# endif // _Encrypt_Decrypt2_FP_H_ +#endif // CC_EncryptDecrypt2 diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/EncryptDecrypt_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/EncryptDecrypt_fp.h new file mode 100644 index 0000000..b8046e9 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/EncryptDecrypt_fp.h @@ -0,0 +1,74 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_EncryptDecrypt // Command must be enabled + +# ifndef _Encrypt_Decrypt_FP_H_ +# define _Encrypt_Decrypt_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_OBJECT keyHandle; + TPMI_YES_NO decrypt; + TPMI_ALG_CIPHER_MODE mode; + TPM2B_IV ivIn; + TPM2B_MAX_BUFFER inData; +} EncryptDecrypt_In; + +// Output structure definition +typedef struct +{ + TPM2B_MAX_BUFFER outData; + TPM2B_IV ivOut; +} EncryptDecrypt_Out; + +// Response code modifiers +# define RC_EncryptDecrypt_keyHandle (TPM_RC_H + TPM_RC_1) +# define RC_EncryptDecrypt_decrypt (TPM_RC_P + TPM_RC_1) +# define RC_EncryptDecrypt_mode (TPM_RC_P + TPM_RC_2) +# define RC_EncryptDecrypt_ivIn (TPM_RC_P + TPM_RC_3) +# define RC_EncryptDecrypt_inData (TPM_RC_P + TPM_RC_4) + +// Function prototype +TPM_RC +TPM2_EncryptDecrypt(EncryptDecrypt_In* in, EncryptDecrypt_Out* out); + +# endif // _Encrypt_Decrypt_FP_H_ +#endif // CC_EncryptDecrypt diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/EncryptDecrypt_spt_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/EncryptDecrypt_spt_fp.h new file mode 100644 index 0000000..e015c3e --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/EncryptDecrypt_spt_fp.h @@ -0,0 +1,62 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 28, 2019 Time: 08:25:18PM + */ + +#ifndef _ENCRYPT_DECRYPT_SPT_FP_H_ +#define _ENCRYPT_DECRYPT_SPT_FP_H_ + +#if CC_EncryptDecrypt2 + +// Return Type: TPM_RC +// TPM_RC_KEY is not a symmetric decryption key with both +// public and private portions loaded +// TPM_RC_SIZE 'IvIn' size is incompatible with the block cipher mode; +// or 'inData' size is not an even multiple of the block +// size for CBC or ECB mode +// TPM_RC_VALUE 'keyHandle' is restricted and the argument 'mode' does +// not match the key's mode +TPM_RC +EncryptDecryptShared(TPMI_DH_OBJECT keyHandleIn, + TPMI_YES_NO decryptIn, + TPMI_ALG_SYM_MODE modeIn, + TPM2B_IV* ivIn, + TPM2B_MAX_BUFFER* inData, + EncryptDecrypt_Out* out); +#endif // CC_EncryptDecrypt + +#endif // _ENCRYPT_DECRYPT_SPT_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Entity_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Entity_fp.h new file mode 100644 index 0000000..f948916 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Entity_fp.h @@ -0,0 +1,102 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 7, 2020 Time: 07:19:36PM + */ + +#ifndef _ENTITY_FP_H_ +#define _ENTITY_FP_H_ + +//** Functions +//*** EntityGetLoadStatus() +// This function will check that all the handles access loaded entities. +// Return Type: TPM_RC +// TPM_RC_HANDLE handle type does not match +// TPM_RC_REFERENCE_Hx entity is not present +// TPM_RC_HIERARCHY entity belongs to a disabled hierarchy +// TPM_RC_OBJECT_MEMORY handle is an evict object but there is no +// space to load it to RAM +TPM_RC +EntityGetLoadStatus(COMMAND* command // IN/OUT: command parsing structure +); + +//*** EntityGetAuthValue() +// This function is used to access the 'authValue' associated with a handle. +// This function assumes that the handle references an entity that is accessible +// and the handle is not for a persistent objects. That is EntityGetLoadStatus() +// should have been called. Also, the accessibility of the authValue should have +// been verified by IsAuthValueAvailable(). +// +// This function copies the authorization value of the entity to 'auth'. +// Return Type: UINT16 +// count number of bytes in the authValue with 0's stripped +UINT16 +EntityGetAuthValue(TPMI_DH_ENTITY handle, // IN: handle of entity + TPM2B_AUTH* auth // OUT: authValue of the entity +); + +//*** EntityGetAuthPolicy() +// This function is used to access the 'authPolicy' associated with a handle. +// This function assumes that the handle references an entity that is accessible +// and the handle is not for a persistent objects. That is EntityGetLoadStatus() +// should have been called. Also, the accessibility of the authPolicy should have +// been verified by IsAuthPolicyAvailable(). +// +// This function copies the authorization policy of the entity to 'authPolicy'. +// +// The return value is the hash algorithm for the policy. +TPMI_ALG_HASH +EntityGetAuthPolicy(TPMI_DH_ENTITY handle, // IN: handle of entity + TPM2B_DIGEST* authPolicy // OUT: authPolicy of the entity +); + +//*** EntityGetName() +// This function returns the Name associated with a handle. +TPM2B_NAME* EntityGetName(TPMI_DH_ENTITY handle, // IN: handle of entity + TPM2B_NAME* name // OUT: name of entity +); + +//*** EntityGetHierarchy() +// This function returns the hierarchy handle associated with an entity. +// a) A handle that is a hierarchy handle is associated with itself. +// b) An NV index belongs to TPM_RH_PLATFORM if TPMA_NV_PLATFORMCREATE, +// is SET, otherwise it belongs to TPM_RH_OWNER +// c) An object handle belongs to its hierarchy. +TPMI_RH_HIERARCHY +EntityGetHierarchy(TPMI_DH_ENTITY handle // IN :handle of entity +); + +#endif // _ENTITY_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/EventSequenceComplete_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/EventSequenceComplete_fp.h new file mode 100644 index 0000000..31bf37c --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/EventSequenceComplete_fp.h @@ -0,0 +1,70 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_EventSequenceComplete // Command must be enabled + +# ifndef _Event_Sequence_Complete_FP_H_ +# define _Event_Sequence_Complete_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_PCR pcrHandle; + TPMI_DH_OBJECT sequenceHandle; + TPM2B_MAX_BUFFER buffer; +} EventSequenceComplete_In; + +// Output structure definition +typedef struct +{ + TPML_DIGEST_VALUES results; +} EventSequenceComplete_Out; + +// Response code modifiers +# define RC_EventSequenceComplete_pcrHandle (TPM_RC_H + TPM_RC_1) +# define RC_EventSequenceComplete_sequenceHandle (TPM_RC_H + TPM_RC_2) +# define RC_EventSequenceComplete_buffer (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_EventSequenceComplete(EventSequenceComplete_In* in, + EventSequenceComplete_Out* out); + +# endif // _Event_Sequence_Complete_FP_H_ +#endif // CC_EventSequenceComplete diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/EvictControl_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/EvictControl_fp.h new file mode 100644 index 0000000..1bdfbd5 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/EvictControl_fp.h @@ -0,0 +1,63 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_EvictControl // Command must be enabled + +# ifndef _Evict_Control_FP_H_ +# define _Evict_Control_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_RH_PROVISION auth; + TPMI_DH_OBJECT objectHandle; + TPMI_DH_PERSISTENT persistentHandle; +} EvictControl_In; + +// Response code modifiers +# define RC_EvictControl_auth (TPM_RC_H + TPM_RC_1) +# define RC_EvictControl_objectHandle (TPM_RC_H + TPM_RC_2) +# define RC_EvictControl_persistentHandle (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_EvictControl(EvictControl_In* in); + +# endif // _Evict_Control_FP_H_ +#endif // CC_EvictControl diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ExecCommand_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ExecCommand_fp.h new file mode 100644 index 0000000..f438eb5 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ExecCommand_fp.h @@ -0,0 +1,87 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 28, 2019 Time: 08:25:19PM + */ + +#ifndef _EXEC_COMMAND_FP_H_ +#define _EXEC_COMMAND_FP_H_ + +//** ExecuteCommand() +// +// The function performs the following steps. +// +// a) Parses the command header from input buffer. +// b) Calls ParseHandleBuffer() to parse the handle area of the command. +// c) Validates that each of the handles references a loaded entity. +// d) Calls ParseSessionBuffer () to: +// 1) unmarshal and parse the session area; +// 2) check the authorizations; and +// 3) when necessary, decrypt a parameter. +// e) Calls CommandDispatcher() to: +// 1) unmarshal the command parameters from the command buffer; +// 2) call the routine that performs the command actions; and +// 3) marshal the responses into the response buffer. +// f) If any error occurs in any of the steps above create the error response +// and return. +// g) Calls BuildResponseSession() to: +// 1) when necessary, encrypt a parameter +// 2) build the response authorization sessions +// 3) update the audit sessions and nonces +// h) Calls BuildResponseHeader() to complete the construction of the response. +// +// 'responseSize' is set by the caller to the maximum number of bytes available in +// the output buffer. ExecuteCommand will adjust the value and return the number +// of bytes placed in the buffer. +// +// 'response' is also set by the caller to indicate the buffer into which +// ExecuteCommand is to place the response. +// +// 'request' and 'response' may point to the same buffer +// +// Note: As of February, 2016, the failure processing has been moved to the +// platform-specific code. When the TPM code encounters an unrecoverable failure, it +// will SET g_inFailureMode and call _plat__Fail(). That function should not return +// but may call ExecuteCommand(). +// +LIB_EXPORT void ExecuteCommand( + uint32_t requestSize, // IN: command buffer size + unsigned char* request, // IN: command buffer + uint32_t* responseSize, // IN/OUT: response buffer size + unsigned char** response // IN/OUT: response buffer +); + +#endif // _EXEC_COMMAND_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/FieldUpgradeData_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/FieldUpgradeData_fp.h new file mode 100644 index 0000000..2f3a2d1 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/FieldUpgradeData_fp.h @@ -0,0 +1,66 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_FieldUpgradeData // Command must be enabled + +# ifndef _Field_Upgrade_Data_FP_H_ +# define _Field_Upgrade_Data_FP_H_ + +// Input structure definition +typedef struct +{ + TPM2B_MAX_BUFFER fuData; +} FieldUpgradeData_In; + +// Output structure definition +typedef struct +{ + TPMT_HA nextDigest; + TPMT_HA firstDigest; +} FieldUpgradeData_Out; + +// Response code modifiers +# define RC_FieldUpgradeData_fuData (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_FieldUpgradeData(FieldUpgradeData_In* in, FieldUpgradeData_Out* out); + +# endif // _Field_Upgrade_Data_FP_H_ +#endif // CC_FieldUpgradeData diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/FieldUpgradeStart_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/FieldUpgradeStart_fp.h new file mode 100644 index 0000000..536d4ee --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/FieldUpgradeStart_fp.h @@ -0,0 +1,65 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_FieldUpgradeStart // Command must be enabled + +# ifndef _Field_Upgrade_Start_FP_H_ +# define _Field_Upgrade_Start_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_RH_PLATFORM authorization; + TPMI_DH_OBJECT keyHandle; + TPM2B_DIGEST fuDigest; + TPMT_SIGNATURE manifestSignature; +} FieldUpgradeStart_In; + +// Response code modifiers +# define RC_FieldUpgradeStart_authorization (TPM_RC_H + TPM_RC_1) +# define RC_FieldUpgradeStart_keyHandle (TPM_RC_H + TPM_RC_2) +# define RC_FieldUpgradeStart_fuDigest (TPM_RC_P + TPM_RC_1) +# define RC_FieldUpgradeStart_manifestSignature (TPM_RC_P + TPM_RC_2) + +// Function prototype +TPM_RC +TPM2_FieldUpgradeStart(FieldUpgradeStart_In* in); + +# endif // _Field_Upgrade_Start_FP_H_ +#endif // CC_FieldUpgradeStart diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/FirmwareRead_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/FirmwareRead_fp.h new file mode 100644 index 0000000..189c984 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/FirmwareRead_fp.h @@ -0,0 +1,65 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_FirmwareRead // Command must be enabled + +# ifndef _Firmware_Read_FP_H_ +# define _Firmware_Read_FP_H_ + +// Input structure definition +typedef struct +{ + UINT32 sequenceNumber; +} FirmwareRead_In; + +// Output structure definition +typedef struct +{ + TPM2B_MAX_BUFFER fuData; +} FirmwareRead_Out; + +// Response code modifiers +# define RC_FirmwareRead_sequenceNumber (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_FirmwareRead(FirmwareRead_In* in, FirmwareRead_Out* out); + +# endif // _Firmware_Read_FP_H_ +#endif // CC_FirmwareRead diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/FlushContext_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/FlushContext_fp.h new file mode 100644 index 0000000..b93f47b --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/FlushContext_fp.h @@ -0,0 +1,59 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_FlushContext // Command must be enabled + +# ifndef _Flush_Context_FP_H_ +# define _Flush_Context_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_CONTEXT flushHandle; +} FlushContext_In; + +// Response code modifiers +# define RC_FlushContext_flushHandle (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_FlushContext(FlushContext_In* in); + +# endif // _Flush_Context_FP_H_ +#endif // CC_FlushContext diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/GetCapability_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/GetCapability_fp.h new file mode 100644 index 0000000..60148d5 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/GetCapability_fp.h @@ -0,0 +1,70 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_GetCapability // Command must be enabled + +# ifndef _Get_Capability_FP_H_ +# define _Get_Capability_FP_H_ + +// Input structure definition +typedef struct +{ + TPM_CAP capability; + UINT32 property; + UINT32 propertyCount; +} GetCapability_In; + +// Output structure definition +typedef struct +{ + TPMI_YES_NO moreData; + TPMS_CAPABILITY_DATA capabilityData; +} GetCapability_Out; + +// Response code modifiers +# define RC_GetCapability_capability (TPM_RC_P + TPM_RC_1) +# define RC_GetCapability_property (TPM_RC_P + TPM_RC_2) +# define RC_GetCapability_propertyCount (TPM_RC_P + TPM_RC_3) + +// Function prototype +TPM_RC +TPM2_GetCapability(GetCapability_In* in, GetCapability_Out* out); + +# endif // _Get_Capability_FP_H_ +#endif // CC_GetCapability diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/GetCommandAuditDigest_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/GetCommandAuditDigest_fp.h new file mode 100644 index 0000000..880c07a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/GetCommandAuditDigest_fp.h @@ -0,0 +1,73 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_GetCommandAuditDigest // Command must be enabled + +# ifndef _Get_Command_Audit_Digest_FP_H_ +# define _Get_Command_Audit_Digest_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_RH_ENDORSEMENT privacyHandle; + TPMI_DH_OBJECT signHandle; + TPM2B_DATA qualifyingData; + TPMT_SIG_SCHEME inScheme; +} GetCommandAuditDigest_In; + +// Output structure definition +typedef struct +{ + TPM2B_ATTEST auditInfo; + TPMT_SIGNATURE signature; +} GetCommandAuditDigest_Out; + +// Response code modifiers +# define RC_GetCommandAuditDigest_privacyHandle (TPM_RC_H + TPM_RC_1) +# define RC_GetCommandAuditDigest_signHandle (TPM_RC_H + TPM_RC_2) +# define RC_GetCommandAuditDigest_qualifyingData (TPM_RC_P + TPM_RC_1) +# define RC_GetCommandAuditDigest_inScheme (TPM_RC_P + TPM_RC_2) + +// Function prototype +TPM_RC +TPM2_GetCommandAuditDigest(GetCommandAuditDigest_In* in, + GetCommandAuditDigest_Out* out); + +# endif // _Get_Command_Audit_Digest_FP_H_ +#endif // CC_GetCommandAuditDigest diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/GetRandom_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/GetRandom_fp.h new file mode 100644 index 0000000..8a6e3ce --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/GetRandom_fp.h @@ -0,0 +1,65 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_GetRandom // Command must be enabled + +# ifndef _Get_Random_FP_H_ +# define _Get_Random_FP_H_ + +// Input structure definition +typedef struct +{ + UINT16 bytesRequested; +} GetRandom_In; + +// Output structure definition +typedef struct +{ + TPM2B_DIGEST randomBytes; +} GetRandom_Out; + +// Response code modifiers +# define RC_GetRandom_bytesRequested (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_GetRandom(GetRandom_In* in, GetRandom_Out* out); + +# endif // _Get_Random_FP_H_ +#endif // CC_GetRandom diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/GetSessionAuditDigest_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/GetSessionAuditDigest_fp.h new file mode 100644 index 0000000..f79e09d --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/GetSessionAuditDigest_fp.h @@ -0,0 +1,75 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_GetSessionAuditDigest // Command must be enabled + +# ifndef _Get_Session_Audit_Digest_FP_H_ +# define _Get_Session_Audit_Digest_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_RH_ENDORSEMENT privacyAdminHandle; + TPMI_DH_OBJECT signHandle; + TPMI_SH_HMAC sessionHandle; + TPM2B_DATA qualifyingData; + TPMT_SIG_SCHEME inScheme; +} GetSessionAuditDigest_In; + +// Output structure definition +typedef struct +{ + TPM2B_ATTEST auditInfo; + TPMT_SIGNATURE signature; +} GetSessionAuditDigest_Out; + +// Response code modifiers +# define RC_GetSessionAuditDigest_privacyAdminHandle (TPM_RC_H + TPM_RC_1) +# define RC_GetSessionAuditDigest_signHandle (TPM_RC_H + TPM_RC_2) +# define RC_GetSessionAuditDigest_sessionHandle (TPM_RC_H + TPM_RC_3) +# define RC_GetSessionAuditDigest_qualifyingData (TPM_RC_P + TPM_RC_1) +# define RC_GetSessionAuditDigest_inScheme (TPM_RC_P + TPM_RC_2) + +// Function prototype +TPM_RC +TPM2_GetSessionAuditDigest(GetSessionAuditDigest_In* in, + GetSessionAuditDigest_Out* out); + +# endif // _Get_Session_Audit_Digest_FP_H_ +#endif // CC_GetSessionAuditDigest diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/GetTestResult_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/GetTestResult_fp.h new file mode 100644 index 0000000..9df305a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/GetTestResult_fp.h @@ -0,0 +1,57 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_GetTestResult // Command must be enabled + +# ifndef _Get_Test_Result_FP_H_ +# define _Get_Test_Result_FP_H_ + +// Output structure definition +typedef struct +{ + TPM2B_MAX_BUFFER outData; + TPM_RC testResult; +} GetTestResult_Out; + +// Function prototype +TPM_RC +TPM2_GetTestResult(GetTestResult_Out* out); + +# endif // _Get_Test_Result_FP_H_ +#endif // CC_GetTestResult diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/GetTime_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/GetTime_fp.h new file mode 100644 index 0000000..2d5a33f --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/GetTime_fp.h @@ -0,0 +1,72 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_GetTime // Command must be enabled + +# ifndef _Get_Time_FP_H_ +# define _Get_Time_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_RH_ENDORSEMENT privacyAdminHandle; + TPMI_DH_OBJECT signHandle; + TPM2B_DATA qualifyingData; + TPMT_SIG_SCHEME inScheme; +} GetTime_In; + +// Output structure definition +typedef struct +{ + TPM2B_ATTEST timeInfo; + TPMT_SIGNATURE signature; +} GetTime_Out; + +// Response code modifiers +# define RC_GetTime_privacyAdminHandle (TPM_RC_H + TPM_RC_1) +# define RC_GetTime_signHandle (TPM_RC_H + TPM_RC_2) +# define RC_GetTime_qualifyingData (TPM_RC_P + TPM_RC_1) +# define RC_GetTime_inScheme (TPM_RC_P + TPM_RC_2) + +// Function prototype +TPM_RC +TPM2_GetTime(GetTime_In* in, GetTime_Out* out); + +# endif // _Get_Time_FP_H_ +#endif // CC_GetTime diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/HMAC_Start_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/HMAC_Start_fp.h new file mode 100644 index 0000000..6bbde6e --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/HMAC_Start_fp.h @@ -0,0 +1,69 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_HMAC_Start // Command must be enabled + +# ifndef _HMAC_Start_FP_H_ +# define _HMAC_Start_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_OBJECT handle; + TPM2B_AUTH auth; + TPMI_ALG_HASH hashAlg; +} HMAC_Start_In; + +// Output structure definition +typedef struct +{ + TPMI_DH_OBJECT sequenceHandle; +} HMAC_Start_Out; + +// Response code modifiers +# define RC_HMAC_Start_handle (TPM_RC_H + TPM_RC_1) +# define RC_HMAC_Start_auth (TPM_RC_P + TPM_RC_1) +# define RC_HMAC_Start_hashAlg (TPM_RC_P + TPM_RC_2) + +// Function prototype +TPM_RC +TPM2_HMAC_Start(HMAC_Start_In* in, HMAC_Start_Out* out); + +# endif // _HMAC_Start_FP_H_ +#endif // CC_HMAC_Start diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/HMAC_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/HMAC_fp.h new file mode 100644 index 0000000..3da7057 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/HMAC_fp.h @@ -0,0 +1,69 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_HMAC // Command must be enabled + +# ifndef _HMAC_FP_H_ +# define _HMAC_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_OBJECT handle; + TPM2B_MAX_BUFFER buffer; + TPMI_ALG_HASH hashAlg; +} HMAC_In; + +// Output structure definition +typedef struct +{ + TPM2B_DIGEST outHMAC; +} HMAC_Out; + +// Response code modifiers +# define RC_HMAC_handle (TPM_RC_H + TPM_RC_1) +# define RC_HMAC_buffer (TPM_RC_P + TPM_RC_1) +# define RC_HMAC_hashAlg (TPM_RC_P + TPM_RC_2) + +// Function prototype +TPM_RC +TPM2_HMAC(HMAC_In* in, HMAC_Out* out); + +# endif // _HMAC_FP_H_ +#endif // CC_HMAC diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Handle_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Handle_fp.h new file mode 100644 index 0000000..420be74 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Handle_fp.h @@ -0,0 +1,83 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 28, 2019 Time: 08:25:19PM + */ + +#ifndef _HANDLE_FP_H_ +#define _HANDLE_FP_H_ + +//*** HandleGetType() +// This function returns the type of a handle which is the MSO of the handle. +TPM_HT +HandleGetType(TPM_HANDLE handle // IN: a handle to be checked +); + +//*** NextPermanentHandle() +// This function returns the permanent handle that is equal to the input value or +// is the next higher value. If there is no handle with the input value and there +// is no next higher value, it returns 0: +TPM_HANDLE +NextPermanentHandle(TPM_HANDLE inHandle // IN: the handle to check +); + +//*** PermanentCapGetHandles() +// This function returns a list of the permanent handles of PCR, started from +// 'handle'. If 'handle' is larger than the largest permanent handle, an empty list +// will be returned with 'more' set to NO. +// Return Type: TPMI_YES_NO +// YES if there are more handles available +// NO all the available handles has been returned +TPMI_YES_NO +PermanentCapGetHandles(TPM_HANDLE handle, // IN: start handle + UINT32 count, // IN: count of returned handles + TPML_HANDLE* handleList // OUT: list of handle +); + +//*** PermanentHandleGetPolicy() +// This function returns a list of the permanent handles of PCR, started from +// 'handle'. If 'handle' is larger than the largest permanent handle, an empty list +// will be returned with 'more' set to NO. +// Return Type: TPMI_YES_NO +// YES if there are more handles available +// NO all the available handles has been returned +TPMI_YES_NO +PermanentHandleGetPolicy(TPM_HANDLE handle, // IN: start handle + UINT32 count, // IN: max count of returned handles + TPML_TAGGED_POLICY* policyList // OUT: list of handle +); + +#endif // _HANDLE_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/HashSequenceStart_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/HashSequenceStart_fp.h new file mode 100644 index 0000000..2687cf2 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/HashSequenceStart_fp.h @@ -0,0 +1,67 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_HashSequenceStart // Command must be enabled + +# ifndef _Hash_Sequence_Start_FP_H_ +# define _Hash_Sequence_Start_FP_H_ + +// Input structure definition +typedef struct +{ + TPM2B_AUTH auth; + TPMI_ALG_HASH hashAlg; +} HashSequenceStart_In; + +// Output structure definition +typedef struct +{ + TPMI_DH_OBJECT sequenceHandle; +} HashSequenceStart_Out; + +// Response code modifiers +# define RC_HashSequenceStart_auth (TPM_RC_P + TPM_RC_1) +# define RC_HashSequenceStart_hashAlg (TPM_RC_P + TPM_RC_2) + +// Function prototype +TPM_RC +TPM2_HashSequenceStart(HashSequenceStart_In* in, HashSequenceStart_Out* out); + +# endif // _Hash_Sequence_Start_FP_H_ +#endif // CC_HashSequenceStart diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Hash_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Hash_fp.h new file mode 100644 index 0000000..f397990 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Hash_fp.h @@ -0,0 +1,70 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_Hash // Command must be enabled + +# ifndef _Hash_FP_H_ +# define _Hash_FP_H_ + +// Input structure definition +typedef struct +{ + TPM2B_MAX_BUFFER data; + TPMI_ALG_HASH hashAlg; + TPMI_RH_HIERARCHY hierarchy; +} Hash_In; + +// Output structure definition +typedef struct +{ + TPM2B_DIGEST outHash; + TPMT_TK_HASHCHECK validation; +} Hash_Out; + +// Response code modifiers +# define RC_Hash_data (TPM_RC_P + TPM_RC_1) +# define RC_Hash_hashAlg (TPM_RC_P + TPM_RC_2) +# define RC_Hash_hierarchy (TPM_RC_P + TPM_RC_3) + +// Function prototype +TPM_RC +TPM2_Hash(Hash_In* in, Hash_Out* out); + +# endif // _Hash_FP_H_ +#endif // CC_Hash diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/HierarchyChangeAuth_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/HierarchyChangeAuth_fp.h new file mode 100644 index 0000000..a665175 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/HierarchyChangeAuth_fp.h @@ -0,0 +1,61 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_HierarchyChangeAuth // Command must be enabled + +# ifndef _Hierarchy_Change_Auth_FP_H_ +# define _Hierarchy_Change_Auth_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_RH_HIERARCHY_AUTH authHandle; + TPM2B_AUTH newAuth; +} HierarchyChangeAuth_In; + +// Response code modifiers +# define RC_HierarchyChangeAuth_authHandle (TPM_RC_H + TPM_RC_1) +# define RC_HierarchyChangeAuth_newAuth (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_HierarchyChangeAuth(HierarchyChangeAuth_In* in); + +# endif // _Hierarchy_Change_Auth_FP_H_ +#endif // CC_HierarchyChangeAuth diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/HierarchyControl_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/HierarchyControl_fp.h new file mode 100644 index 0000000..a2f2df1 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/HierarchyControl_fp.h @@ -0,0 +1,63 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_HierarchyControl // Command must be enabled + +# ifndef _Hierarchy_Control_FP_H_ +# define _Hierarchy_Control_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_RH_HIERARCHY authHandle; + TPMI_RH_ENABLES enable; + TPMI_YES_NO state; +} HierarchyControl_In; + +// Response code modifiers +# define RC_HierarchyControl_authHandle (TPM_RC_H + TPM_RC_1) +# define RC_HierarchyControl_enable (TPM_RC_P + TPM_RC_1) +# define RC_HierarchyControl_state (TPM_RC_P + TPM_RC_2) + +// Function prototype +TPM_RC +TPM2_HierarchyControl(HierarchyControl_In* in); + +# endif // _Hierarchy_Control_FP_H_ +#endif // CC_HierarchyControl diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Hierarchy_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Hierarchy_fp.h new file mode 100644 index 0000000..032a165 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Hierarchy_fp.h @@ -0,0 +1,76 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Apr 2, 2019 Time: 04:23:27PM + */ + +#ifndef _HIERARCHY_FP_H_ +#define _HIERARCHY_FP_H_ + +//*** HierarchyPreInstall() +// This function performs the initialization functions for the hierarchy +// when the TPM is simulated. This function should not be called if the +// TPM is not in a manufacturing mode at the manufacturer, or in a simulated +// environment. +void HierarchyPreInstall_Init(void); + +//*** HierarchyStartup() +// This function is called at TPM2_Startup() to initialize the hierarchy +// related values. +BOOL HierarchyStartup(STARTUP_TYPE type // IN: start up type +); + +//*** HierarchyGetProof() +// This function finds the proof value associated with a hierarchy.It returns a +// pointer to the proof value. +TPM2B_PROOF* HierarchyGetProof(TPMI_RH_HIERARCHY hierarchy // IN: hierarchy constant +); + +//*** HierarchyGetPrimarySeed() +// This function returns the primary seed of a hierarchy. +TPM2B_SEED* HierarchyGetPrimarySeed(TPMI_RH_HIERARCHY hierarchy // IN: hierarchy +); + +//*** HierarchyIsEnabled() +// This function checks to see if a hierarchy is enabled. +// NOTE: The TPM_RH_NULL hierarchy is always enabled. +// Return Type: BOOL +// TRUE(1) hierarchy is enabled +// FALSE(0) hierarchy is disabled +BOOL HierarchyIsEnabled(TPMI_RH_HIERARCHY hierarchy // IN: hierarchy +); + +#endif // _HIERARCHY_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Import_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Import_fp.h new file mode 100644 index 0000000..c9e2475 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Import_fp.h @@ -0,0 +1,75 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_Import // Command must be enabled + +# ifndef _Import_FP_H_ +# define _Import_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_OBJECT parentHandle; + TPM2B_DATA encryptionKey; + TPM2B_PUBLIC objectPublic; + TPM2B_PRIVATE duplicate; + TPM2B_ENCRYPTED_SECRET inSymSeed; + TPMT_SYM_DEF_OBJECT symmetricAlg; +} Import_In; + +// Output structure definition +typedef struct +{ + TPM2B_PRIVATE outPrivate; +} Import_Out; + +// Response code modifiers +# define RC_Import_parentHandle (TPM_RC_H + TPM_RC_1) +# define RC_Import_encryptionKey (TPM_RC_P + TPM_RC_1) +# define RC_Import_objectPublic (TPM_RC_P + TPM_RC_2) +# define RC_Import_duplicate (TPM_RC_P + TPM_RC_3) +# define RC_Import_inSymSeed (TPM_RC_P + TPM_RC_4) +# define RC_Import_symmetricAlg (TPM_RC_P + TPM_RC_5) + +// Function prototype +TPM_RC +TPM2_Import(Import_In* in, Import_Out* out); + +# endif // _Import_FP_H_ +#endif // CC_Import diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/IncrementalSelfTest_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/IncrementalSelfTest_fp.h new file mode 100644 index 0000000..23352ed --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/IncrementalSelfTest_fp.h @@ -0,0 +1,65 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_IncrementalSelfTest // Command must be enabled + +# ifndef _Incremental_Self_Test_FP_H_ +# define _Incremental_Self_Test_FP_H_ + +// Input structure definition +typedef struct +{ + TPML_ALG toTest; +} IncrementalSelfTest_In; + +// Output structure definition +typedef struct +{ + TPML_ALG toDoList; +} IncrementalSelfTest_Out; + +// Response code modifiers +# define RC_IncrementalSelfTest_toTest (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_IncrementalSelfTest(IncrementalSelfTest_In* in, IncrementalSelfTest_Out* out); + +# endif // _Incremental_Self_Test_FP_H_ +#endif // CC_IncrementalSelfTest diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/IoBuffers_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/IoBuffers_fp.h new file mode 100644 index 0000000..d2d7963 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/IoBuffers_fp.h @@ -0,0 +1,74 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 28, 2019 Time: 08:25:19PM + */ + +#ifndef _IO_BUFFERS_FP_H_ +#define _IO_BUFFERS_FP_H_ + +//*** MemoryIoBufferAllocationReset() +// This function is used to reset the allocation of buffers. +void MemoryIoBufferAllocationReset(void); + +//*** MemoryIoBufferZero() +// Function zeros the action I/O buffer at the end of a command. Calling this is +// not mandatory for proper functionality. +void MemoryIoBufferZero(void); + +//*** MemoryGetInBuffer() +// This function returns the address of the buffer into which the +// command parameters will be unmarshaled in preparation for calling +// the command actions. +BYTE* MemoryGetInBuffer(UINT32 size // Size, in bytes, required for the input + // unmarshaling +); + +//*** MemoryGetOutBuffer() +// This function returns the address of the buffer into which the command +// action code places its output values. +BYTE* MemoryGetOutBuffer(UINT32 size // required size of the buffer +); + +//*** IsLabelProperlyFormatted() +// This function checks that a label is a null-terminated string. +// NOTE: this function is here because there was no better place for it. +// Return Type: BOOL +// TRUE(1) string is null terminated +// FALSE(0) string is not null terminated +BOOL IsLabelProperlyFormatted(TPM2B* x); + +#endif // _IO_BUFFERS_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/LoadExternal_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/LoadExternal_fp.h new file mode 100644 index 0000000..377ff8d --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/LoadExternal_fp.h @@ -0,0 +1,70 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_LoadExternal // Command must be enabled + +# ifndef _Load_External_FP_H_ +# define _Load_External_FP_H_ + +// Input structure definition +typedef struct +{ + TPM2B_SENSITIVE inPrivate; + TPM2B_PUBLIC inPublic; + TPMI_RH_HIERARCHY hierarchy; +} LoadExternal_In; + +// Output structure definition +typedef struct +{ + TPM_HANDLE objectHandle; + TPM2B_NAME name; +} LoadExternal_Out; + +// Response code modifiers +# define RC_LoadExternal_inPrivate (TPM_RC_P + TPM_RC_1) +# define RC_LoadExternal_inPublic (TPM_RC_P + TPM_RC_2) +# define RC_LoadExternal_hierarchy (TPM_RC_P + TPM_RC_3) + +// Function prototype +TPM_RC +TPM2_LoadExternal(LoadExternal_In* in, LoadExternal_Out* out); + +# endif // _Load_External_FP_H_ +#endif // CC_LoadExternal diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Load_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Load_fp.h new file mode 100644 index 0000000..babd253 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Load_fp.h @@ -0,0 +1,70 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_Load // Command must be enabled + +# ifndef _Load_FP_H_ +# define _Load_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_OBJECT parentHandle; + TPM2B_PRIVATE inPrivate; + TPM2B_PUBLIC inPublic; +} Load_In; + +// Output structure definition +typedef struct +{ + TPM_HANDLE objectHandle; + TPM2B_NAME name; +} Load_Out; + +// Response code modifiers +# define RC_Load_parentHandle (TPM_RC_H + TPM_RC_1) +# define RC_Load_inPrivate (TPM_RC_P + TPM_RC_1) +# define RC_Load_inPublic (TPM_RC_P + TPM_RC_2) + +// Function prototype +TPM_RC +TPM2_Load(Load_In* in, Load_Out* out); + +# endif // _Load_FP_H_ +#endif // CC_Load diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Locality_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Locality_fp.h new file mode 100644 index 0000000..5843a39 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Locality_fp.h @@ -0,0 +1,52 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 28, 2019 Time: 08:25:19PM + */ + +#ifndef _LOCALITY_FP_H_ +#define _LOCALITY_FP_H_ + +//** LocalityGetAttributes() +// This function will convert a locality expressed as an integer into +// TPMA_LOCALITY form. +// +// The function returns the locality attribute. +TPMA_LOCALITY +LocalityGetAttributes(UINT8 locality // IN: locality value +); + +#endif // _LOCALITY_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/MAC_Start_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/MAC_Start_fp.h new file mode 100644 index 0000000..80a58a4 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/MAC_Start_fp.h @@ -0,0 +1,69 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_MAC_Start // Command must be enabled + +# ifndef _MAC_Start_FP_H_ +# define _MAC_Start_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_OBJECT handle; + TPM2B_AUTH auth; + TPMI_ALG_MAC_SCHEME inScheme; +} MAC_Start_In; + +// Output structure definition +typedef struct +{ + TPMI_DH_OBJECT sequenceHandle; +} MAC_Start_Out; + +// Response code modifiers +# define RC_MAC_Start_handle (TPM_RC_H + TPM_RC_1) +# define RC_MAC_Start_auth (TPM_RC_P + TPM_RC_1) +# define RC_MAC_Start_inScheme (TPM_RC_P + TPM_RC_2) + +// Function prototype +TPM_RC +TPM2_MAC_Start(MAC_Start_In* in, MAC_Start_Out* out); + +# endif // _MAC_Start_FP_H_ +#endif // CC_MAC_Start diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/MAC_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/MAC_fp.h new file mode 100644 index 0000000..07e2785 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/MAC_fp.h @@ -0,0 +1,69 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_MAC // Command must be enabled + +# ifndef _MAC_FP_H_ +# define _MAC_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_OBJECT handle; + TPM2B_MAX_BUFFER buffer; + TPMI_ALG_MAC_SCHEME inScheme; +} MAC_In; + +// Output structure definition +typedef struct +{ + TPM2B_DIGEST outMAC; +} MAC_Out; + +// Response code modifiers +# define RC_MAC_handle (TPM_RC_H + TPM_RC_1) +# define RC_MAC_buffer (TPM_RC_P + TPM_RC_1) +# define RC_MAC_inScheme (TPM_RC_P + TPM_RC_2) + +// Function prototype +TPM_RC +TPM2_MAC(MAC_In* in, MAC_Out* out); + +# endif // _MAC_FP_H_ +#endif // CC_MAC diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/MakeCredential_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/MakeCredential_fp.h new file mode 100644 index 0000000..cbec15c --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/MakeCredential_fp.h @@ -0,0 +1,70 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_MakeCredential // Command must be enabled + +# ifndef _Make_Credential_FP_H_ +# define _Make_Credential_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_OBJECT handle; + TPM2B_DIGEST credential; + TPM2B_NAME objectName; +} MakeCredential_In; + +// Output structure definition +typedef struct +{ + TPM2B_ID_OBJECT credentialBlob; + TPM2B_ENCRYPTED_SECRET secret; +} MakeCredential_Out; + +// Response code modifiers +# define RC_MakeCredential_handle (TPM_RC_H + TPM_RC_1) +# define RC_MakeCredential_credential (TPM_RC_P + TPM_RC_1) +# define RC_MakeCredential_objectName (TPM_RC_P + TPM_RC_2) + +// Function prototype +TPM_RC +TPM2_MakeCredential(MakeCredential_In* in, MakeCredential_Out* out); + +# endif // _Make_Credential_FP_H_ +#endif // CC_MakeCredential diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Manufacture_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Manufacture_fp.h new file mode 100644 index 0000000..328e87b --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Manufacture_fp.h @@ -0,0 +1,73 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 4, 2020 Time: 02:36:44PM + */ + +#ifndef _MANUFACTURE_FP_H_ +#define _MANUFACTURE_FP_H_ + +//*** TPM_Manufacture() +// This function initializes the TPM values in preparation for the TPM's first +// use. This function will fail if previously called. The TPM can be re-manufactured +// by calling TPM_Teardown() first and then calling this function again. +// Return Type: int +// -1 failure +// 0 success +// 1 manufacturing process previously performed +LIB_EXPORT int TPM_Manufacture( + int firstTime // IN: indicates if this is the first call from + // main() +); + +//*** TPM_TearDown() +// This function prepares the TPM for re-manufacture. It should not be implemented +// in anything other than a simulated TPM. +// +// In this implementation, all that is needs is to stop the cryptographic units +// and set a flag to indicate that the TPM can be re-manufactured. This should +// be all that is necessary to start the manufacturing process again. +// Return Type: int +// 0 success +// 1 TPM not previously manufactured +LIB_EXPORT int TPM_TearDown(void); + +//*** TpmEndSimulation() +// This function is called at the end of the simulation run. It is used to provoke +// printing of any statistics that might be needed. +LIB_EXPORT void TpmEndSimulation(void); + +#endif // _MANUFACTURE_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Marshal_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Marshal_fp.h new file mode 100644 index 0000000..81bed00 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Marshal_fp.h @@ -0,0 +1,2345 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmMarshal; Version 4.1 Dec 10, 2018 + * Date: Mar 6, 2020 Time: 01:50:10PM + */ + +#ifndef _MARSHAL_FP_H_ +#define _MARSHAL_FP_H_ + +// Table 2:3 - Definition of Base Types +// UINT8 definition from table 2:3 +TPM_RC +UINT8_Unmarshal(UINT8* target, BYTE** buffer, INT32* size); +UINT16 +UINT8_Marshal(UINT8* source, BYTE** buffer, INT32* size); + +// BYTE definition from table 2:3 +#if !USE_MARSHALING_DEFINES +TPM_RC +BYTE_Unmarshal(BYTE* target, BYTE** buffer, INT32* size); +#else +# define BYTE_Unmarshal(target, buffer, size) \ + UINT8_Unmarshal((UINT8*)(target), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES +#if !USE_MARSHALING_DEFINES +UINT16 +BYTE_Marshal(BYTE* source, BYTE** buffer, INT32* size); +#else +# define BYTE_Marshal(source, buffer, size) \ + UINT8_Marshal((UINT8*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// INT8 definition from table 2:3 +#if !USE_MARSHALING_DEFINES +TPM_RC +INT8_Unmarshal(INT8* target, BYTE** buffer, INT32* size); +#else +# define INT8_Unmarshal(target, buffer, size) \ + UINT8_Unmarshal((UINT8*)(target), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES +#if !USE_MARSHALING_DEFINES +UINT16 +INT8_Marshal(INT8* source, BYTE** buffer, INT32* size); +#else +# define INT8_Marshal(source, buffer, size) \ + UINT8_Marshal((UINT8*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// UINT16 definition from table 2:3 +TPM_RC +UINT16_Unmarshal(UINT16* target, BYTE** buffer, INT32* size); +UINT16 +UINT16_Marshal(UINT16* source, BYTE** buffer, INT32* size); + +// INT16 definition from table 2:3 +#if !USE_MARSHALING_DEFINES +TPM_RC +INT16_Unmarshal(INT16* target, BYTE** buffer, INT32* size); +#else +# define INT16_Unmarshal(target, buffer, size) \ + UINT16_Unmarshal((UINT16*)(target), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES +#if !USE_MARSHALING_DEFINES +UINT16 +INT16_Marshal(INT16* source, BYTE** buffer, INT32* size); +#else +# define INT16_Marshal(source, buffer, size) \ + UINT16_Marshal((UINT16*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// UINT32 definition from table 2:3 +TPM_RC +UINT32_Unmarshal(UINT32* target, BYTE** buffer, INT32* size); +UINT16 +UINT32_Marshal(UINT32* source, BYTE** buffer, INT32* size); + +// INT32 definition from table 2:3 +#if !USE_MARSHALING_DEFINES +TPM_RC +INT32_Unmarshal(INT32* target, BYTE** buffer, INT32* size); +#else +# define INT32_Unmarshal(target, buffer, size) \ + UINT32_Unmarshal((UINT32*)(target), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES +#if !USE_MARSHALING_DEFINES +UINT16 +INT32_Marshal(INT32* source, BYTE** buffer, INT32* size); +#else +# define INT32_Marshal(source, buffer, size) \ + UINT32_Marshal((UINT32*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// UINT64 definition from table 2:3 +TPM_RC +UINT64_Unmarshal(UINT64* target, BYTE** buffer, INT32* size); +UINT16 +UINT64_Marshal(UINT64* source, BYTE** buffer, INT32* size); + +// INT64 definition from table 2:3 +#if !USE_MARSHALING_DEFINES +TPM_RC +INT64_Unmarshal(INT64* target, BYTE** buffer, INT32* size); +#else +# define INT64_Unmarshal(target, buffer, size) \ + UINT64_Unmarshal((UINT64*)(target), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES +#if !USE_MARSHALING_DEFINES +UINT16 +INT64_Marshal(INT64* source, BYTE** buffer, INT32* size); +#else +# define INT64_Marshal(source, buffer, size) \ + UINT64_Marshal((UINT64*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:4 - Defines for Logic Values +// Table 2:5 - Definition of Types for Documentation Clarity +#if !USE_MARSHALING_DEFINES +TPM_RC +TPM_ALGORITHM_ID_Unmarshal(TPM_ALGORITHM_ID* target, BYTE** buffer, INT32* size); +#else +# define TPM_ALGORITHM_ID_Unmarshal(target, buffer, size) \ + UINT32_Unmarshal((UINT32*)(target), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES +#if !USE_MARSHALING_DEFINES +UINT16 +TPM_ALGORITHM_ID_Marshal(TPM_ALGORITHM_ID* source, BYTE** buffer, INT32* size); +#else +# define TPM_ALGORITHM_ID_Marshal(source, buffer, size) \ + UINT32_Marshal((UINT32*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES +#if !USE_MARSHALING_DEFINES +TPM_RC +TPM_MODIFIER_INDICATOR_Unmarshal( + TPM_MODIFIER_INDICATOR* target, BYTE** buffer, INT32* size); +#else +# define TPM_MODIFIER_INDICATOR_Unmarshal(target, buffer, size) \ + UINT32_Unmarshal((UINT32*)(target), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES +#if !USE_MARSHALING_DEFINES +UINT16 +TPM_MODIFIER_INDICATOR_Marshal( + TPM_MODIFIER_INDICATOR* source, BYTE** buffer, INT32* size); +#else +# define TPM_MODIFIER_INDICATOR_Marshal(source, buffer, size) \ + UINT32_Marshal((UINT32*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES +#if !USE_MARSHALING_DEFINES +TPM_RC +TPM_AUTHORIZATION_SIZE_Unmarshal( + TPM_AUTHORIZATION_SIZE* target, BYTE** buffer, INT32* size); +#else +# define TPM_AUTHORIZATION_SIZE_Unmarshal(target, buffer, size) \ + UINT32_Unmarshal((UINT32*)(target), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES +#if !USE_MARSHALING_DEFINES +UINT16 +TPM_AUTHORIZATION_SIZE_Marshal( + TPM_AUTHORIZATION_SIZE* source, BYTE** buffer, INT32* size); +#else +# define TPM_AUTHORIZATION_SIZE_Marshal(source, buffer, size) \ + UINT32_Marshal((UINT32*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES +#if !USE_MARSHALING_DEFINES +TPM_RC +TPM_PARAMETER_SIZE_Unmarshal(TPM_PARAMETER_SIZE* target, BYTE** buffer, INT32* size); +#else +# define TPM_PARAMETER_SIZE_Unmarshal(target, buffer, size) \ + UINT32_Unmarshal((UINT32*)(target), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES +#if !USE_MARSHALING_DEFINES +UINT16 +TPM_PARAMETER_SIZE_Marshal(TPM_PARAMETER_SIZE* source, BYTE** buffer, INT32* size); +#else +# define TPM_PARAMETER_SIZE_Marshal(source, buffer, size) \ + UINT32_Marshal((UINT32*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES +#if !USE_MARSHALING_DEFINES +TPM_RC +TPM_KEY_SIZE_Unmarshal(TPM_KEY_SIZE* target, BYTE** buffer, INT32* size); +#else +# define TPM_KEY_SIZE_Unmarshal(target, buffer, size) \ + UINT16_Unmarshal((UINT16*)(target), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES +#if !USE_MARSHALING_DEFINES +UINT16 +TPM_KEY_SIZE_Marshal(TPM_KEY_SIZE* source, BYTE** buffer, INT32* size); +#else +# define TPM_KEY_SIZE_Marshal(source, buffer, size) \ + UINT16_Marshal((UINT16*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES +#if !USE_MARSHALING_DEFINES +TPM_RC +TPM_KEY_BITS_Unmarshal(TPM_KEY_BITS* target, BYTE** buffer, INT32* size); +#else +# define TPM_KEY_BITS_Unmarshal(target, buffer, size) \ + UINT16_Unmarshal((UINT16*)(target), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES +#if !USE_MARSHALING_DEFINES +UINT16 +TPM_KEY_BITS_Marshal(TPM_KEY_BITS* source, BYTE** buffer, INT32* size); +#else +# define TPM_KEY_BITS_Marshal(source, buffer, size) \ + UINT16_Marshal((UINT16*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:6 - Definition of TPM_SPEC Constants +// Table 2:7 - Definition of TPM_CONSTANTS32 Constants +#if !USE_MARSHALING_DEFINES +UINT16 +TPM_CONSTANTS32_Marshal(TPM_CONSTANTS32* source, BYTE** buffer, INT32* size); +#else +# define TPM_CONSTANTS32_Marshal(source, buffer, size) \ + UINT32_Marshal((UINT32*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:9 - Definition of TPM_ALG_ID Constants +#if !USE_MARSHALING_DEFINES +TPM_RC +TPM_ALG_ID_Unmarshal(TPM_ALG_ID* target, BYTE** buffer, INT32* size); +#else +# define TPM_ALG_ID_Unmarshal(target, buffer, size) \ + UINT16_Unmarshal((UINT16*)(target), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES +#if !USE_MARSHALING_DEFINES +UINT16 +TPM_ALG_ID_Marshal(TPM_ALG_ID* source, BYTE** buffer, INT32* size); +#else +# define TPM_ALG_ID_Marshal(source, buffer, size) \ + UINT16_Marshal((UINT16*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:10 - Definition of TPM_ECC_CURVE Constants +#if ALG_ECC +TPM_RC +TPM_ECC_CURVE_Unmarshal(TPM_ECC_CURVE* target, BYTE** buffer, INT32* size); +# if !USE_MARSHALING_DEFINES +UINT16 +TPM_ECC_CURVE_Marshal(TPM_ECC_CURVE* source, BYTE** buffer, INT32* size); +# else +# define TPM_ECC_CURVE_Marshal(source, buffer, size) \ + UINT16_Marshal((UINT16*)(source), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +#endif // ALG_ECC + +// Table 2:12 - Definition of TPM_CC Constants +#if !USE_MARSHALING_DEFINES +TPM_RC +TPM_CC_Unmarshal(TPM_CC* target, BYTE** buffer, INT32* size); +#else +# define TPM_CC_Unmarshal(target, buffer, size) \ + UINT32_Unmarshal((UINT32*)(target), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES +#if !USE_MARSHALING_DEFINES +UINT16 +TPM_CC_Marshal(TPM_CC* source, BYTE** buffer, INT32* size); +#else +# define TPM_CC_Marshal(source, buffer, size) \ + UINT32_Marshal((UINT32*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:16 - Definition of TPM_RC Constants +#if !USE_MARSHALING_DEFINES +UINT16 +TPM_RC_Marshal(TPM_RC* source, BYTE** buffer, INT32* size); +#else +# define TPM_RC_Marshal(source, buffer, size) \ + UINT32_Marshal((UINT32*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:17 - Definition of TPM_CLOCK_ADJUST Constants +TPM_RC +TPM_CLOCK_ADJUST_Unmarshal(TPM_CLOCK_ADJUST* target, BYTE** buffer, INT32* size); + +// Table 2:18 - Definition of TPM_EO Constants +TPM_RC +TPM_EO_Unmarshal(TPM_EO* target, BYTE** buffer, INT32* size); +#if !USE_MARSHALING_DEFINES +UINT16 +TPM_EO_Marshal(TPM_EO* source, BYTE** buffer, INT32* size); +#else +# define TPM_EO_Marshal(source, buffer, size) \ + UINT16_Marshal((UINT16*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:19 - Definition of TPM_ST Constants +#if !USE_MARSHALING_DEFINES +TPM_RC +TPM_ST_Unmarshal(TPM_ST* target, BYTE** buffer, INT32* size); +#else +# define TPM_ST_Unmarshal(target, buffer, size) \ + UINT16_Unmarshal((UINT16*)(target), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES +#if !USE_MARSHALING_DEFINES +UINT16 +TPM_ST_Marshal(TPM_ST* source, BYTE** buffer, INT32* size); +#else +# define TPM_ST_Marshal(source, buffer, size) \ + UINT16_Marshal((UINT16*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:20 - Definition of TPM_SU Constants +TPM_RC +TPM_SU_Unmarshal(TPM_SU* target, BYTE** buffer, INT32* size); + +// Table 2:21 - Definition of TPM_SE Constants +TPM_RC +TPM_SE_Unmarshal(TPM_SE* target, BYTE** buffer, INT32* size); + +// Table 2:22 - Definition of TPM_CAP Constants +TPM_RC +TPM_CAP_Unmarshal(TPM_CAP* target, BYTE** buffer, INT32* size); +#if !USE_MARSHALING_DEFINES +UINT16 +TPM_CAP_Marshal(TPM_CAP* source, BYTE** buffer, INT32* size); +#else +# define TPM_CAP_Marshal(source, buffer, size) \ + UINT32_Marshal((UINT32*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:23 - Definition of TPM_PT Constants +#if !USE_MARSHALING_DEFINES +TPM_RC +TPM_PT_Unmarshal(TPM_PT* target, BYTE** buffer, INT32* size); +#else +# define TPM_PT_Unmarshal(target, buffer, size) \ + UINT32_Unmarshal((UINT32*)(target), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES +#if !USE_MARSHALING_DEFINES +UINT16 +TPM_PT_Marshal(TPM_PT* source, BYTE** buffer, INT32* size); +#else +# define TPM_PT_Marshal(source, buffer, size) \ + UINT32_Marshal((UINT32*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:24 - Definition of TPM_PT_PCR Constants +#if !USE_MARSHALING_DEFINES +TPM_RC +TPM_PT_PCR_Unmarshal(TPM_PT_PCR* target, BYTE** buffer, INT32* size); +#else +# define TPM_PT_PCR_Unmarshal(target, buffer, size) \ + UINT32_Unmarshal((UINT32*)(target), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES +#if !USE_MARSHALING_DEFINES +UINT16 +TPM_PT_PCR_Marshal(TPM_PT_PCR* source, BYTE** buffer, INT32* size); +#else +# define TPM_PT_PCR_Marshal(source, buffer, size) \ + UINT32_Marshal((UINT32*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:25 - Definition of TPM_PS Constants +#if !USE_MARSHALING_DEFINES +UINT16 +TPM_PS_Marshal(TPM_PS* source, BYTE** buffer, INT32* size); +#else +# define TPM_PS_Marshal(source, buffer, size) \ + UINT32_Marshal((UINT32*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:26 - Definition of Types for Handles +#if !USE_MARSHALING_DEFINES +TPM_RC +TPM_HANDLE_Unmarshal(TPM_HANDLE* target, BYTE** buffer, INT32* size); +#else +# define TPM_HANDLE_Unmarshal(target, buffer, size) \ + UINT32_Unmarshal((UINT32*)(target), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES +#if !USE_MARSHALING_DEFINES +UINT16 +TPM_HANDLE_Marshal(TPM_HANDLE* source, BYTE** buffer, INT32* size); +#else +# define TPM_HANDLE_Marshal(source, buffer, size) \ + UINT32_Marshal((UINT32*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:27 - Definition of TPM_HT Constants +#if !USE_MARSHALING_DEFINES +TPM_RC +TPM_HT_Unmarshal(TPM_HT* target, BYTE** buffer, INT32* size); +#else +# define TPM_HT_Unmarshal(target, buffer, size) \ + UINT8_Unmarshal((UINT8*)(target), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES +#if !USE_MARSHALING_DEFINES +UINT16 +TPM_HT_Marshal(TPM_HT* source, BYTE** buffer, INT32* size); +#else +# define TPM_HT_Marshal(source, buffer, size) \ + UINT8_Marshal((UINT8*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:28 - Definition of TPM_RH Constants +#if !USE_MARSHALING_DEFINES +TPM_RC +TPM_RH_Unmarshal(TPM_RH* target, BYTE** buffer, INT32* size); +#else +# define TPM_RH_Unmarshal(target, buffer, size) \ + TPM_HANDLE_Unmarshal((TPM_HANDLE*)(target), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES +#if !USE_MARSHALING_DEFINES +UINT16 +TPM_RH_Marshal(TPM_RH* source, BYTE** buffer, INT32* size); +#else +# define TPM_RH_Marshal(source, buffer, size) \ + TPM_HANDLE_Marshal((TPM_HANDLE*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:29 - Definition of TPM_HC Constants +#if !USE_MARSHALING_DEFINES +TPM_RC +TPM_HC_Unmarshal(TPM_HC* target, BYTE** buffer, INT32* size); +#else +# define TPM_HC_Unmarshal(target, buffer, size) \ + TPM_HANDLE_Unmarshal((TPM_HANDLE*)(target), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES +#if !USE_MARSHALING_DEFINES +UINT16 +TPM_HC_Marshal(TPM_HC* source, BYTE** buffer, INT32* size); +#else +# define TPM_HC_Marshal(source, buffer, size) \ + TPM_HANDLE_Marshal((TPM_HANDLE*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:30 - Definition of TPMA_ALGORITHM Bits +TPM_RC +TPMA_ALGORITHM_Unmarshal(TPMA_ALGORITHM* target, BYTE** buffer, INT32* size); + +#if !USE_MARSHALING_DEFINES +UINT16 +TPMA_ALGORITHM_Marshal(TPMA_ALGORITHM* source, BYTE** buffer, INT32* size); +#else +# define TPMA_ALGORITHM_Marshal(source, buffer, size) \ + UINT32_Marshal((UINT32*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:31 - Definition of TPMA_OBJECT Bits +TPM_RC +TPMA_OBJECT_Unmarshal(TPMA_OBJECT* target, BYTE** buffer, INT32* size); + +#if !USE_MARSHALING_DEFINES +UINT16 +TPMA_OBJECT_Marshal(TPMA_OBJECT* source, BYTE** buffer, INT32* size); +#else +# define TPMA_OBJECT_Marshal(source, buffer, size) \ + UINT32_Marshal((UINT32*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:32 - Definition of TPMA_SESSION Bits +TPM_RC +TPMA_SESSION_Unmarshal(TPMA_SESSION* target, BYTE** buffer, INT32* size); + +#if !USE_MARSHALING_DEFINES +UINT16 +TPMA_SESSION_Marshal(TPMA_SESSION* source, BYTE** buffer, INT32* size); +#else +# define TPMA_SESSION_Marshal(source, buffer, size) \ + UINT8_Marshal((UINT8*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:33 - Definition of TPMA_LOCALITY Bits +#if !USE_MARSHALING_DEFINES +TPM_RC +TPMA_LOCALITY_Unmarshal(TPMA_LOCALITY* target, BYTE** buffer, INT32* size); +#else +# define TPMA_LOCALITY_Unmarshal(target, buffer, size) \ + UINT8_Unmarshal((UINT8*)(target), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +#if !USE_MARSHALING_DEFINES +UINT16 +TPMA_LOCALITY_Marshal(TPMA_LOCALITY* source, BYTE** buffer, INT32* size); +#else +# define TPMA_LOCALITY_Marshal(source, buffer, size) \ + UINT8_Marshal((UINT8*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:34 - Definition of TPMA_PERMANENT Bits +#if !USE_MARSHALING_DEFINES +UINT16 +TPMA_PERMANENT_Marshal(TPMA_PERMANENT* source, BYTE** buffer, INT32* size); +#else +# define TPMA_PERMANENT_Marshal(source, buffer, size) \ + UINT32_Marshal((UINT32*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:35 - Definition of TPMA_STARTUP_CLEAR Bits +#if !USE_MARSHALING_DEFINES +UINT16 +TPMA_STARTUP_CLEAR_Marshal(TPMA_STARTUP_CLEAR* source, BYTE** buffer, INT32* size); +#else +# define TPMA_STARTUP_CLEAR_Marshal(source, buffer, size) \ + UINT32_Marshal((UINT32*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:36 - Definition of TPMA_MEMORY Bits +#if !USE_MARSHALING_DEFINES +UINT16 +TPMA_MEMORY_Marshal(TPMA_MEMORY* source, BYTE** buffer, INT32* size); +#else +# define TPMA_MEMORY_Marshal(source, buffer, size) \ + UINT32_Marshal((UINT32*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:37 - Definition of TPMA_CC Bits +#if !USE_MARSHALING_DEFINES +UINT16 +TPMA_CC_Marshal(TPMA_CC* source, BYTE** buffer, INT32* size); +#else +# define TPMA_CC_Marshal(source, buffer, size) \ + TPM_CC_Marshal((TPM_CC*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:38 - Definition of TPMA_MODES Bits +#if !USE_MARSHALING_DEFINES +UINT16 +TPMA_MODES_Marshal(TPMA_MODES* source, BYTE** buffer, INT32* size); +#else +# define TPMA_MODES_Marshal(source, buffer, size) \ + UINT32_Marshal((UINT32*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:39 - Definition of TPMA_X509_KEY_USAGE Bits +#if !USE_MARSHALING_DEFINES +UINT16 +TPMA_X509_KEY_USAGE_Marshal(TPMA_X509_KEY_USAGE* source, BYTE** buffer, INT32* size); +#else +# define TPMA_X509_KEY_USAGE_Marshal(source, buffer, size) \ + UINT32_Marshal((UINT32*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:40 - Definition of TPMA_ACT Bits +TPM_RC +TPMA_ACT_Unmarshal(TPMA_ACT* target, BYTE** buffer, INT32* size); + +#if !USE_MARSHALING_DEFINES +UINT16 +TPMA_ACT_Marshal(TPMA_ACT* source, BYTE** buffer, INT32* size); +#else +# define TPMA_ACT_Marshal(source, buffer, size) \ + UINT32_Marshal((UINT32*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:41 - Definition of TPMI_YES_NO Type +TPM_RC +TPMI_YES_NO_Unmarshal(TPMI_YES_NO* target, BYTE** buffer, INT32* size); +#if !USE_MARSHALING_DEFINES +UINT16 +TPMI_YES_NO_Marshal(TPMI_YES_NO* source, BYTE** buffer, INT32* size); +#else +# define TPMI_YES_NO_Marshal(source, buffer, size) \ + BYTE_Marshal((BYTE*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:42 - Definition of TPMI_DH_OBJECT Type +TPM_RC +TPMI_DH_OBJECT_Unmarshal( + TPMI_DH_OBJECT* target, BYTE** buffer, INT32* size, BOOL flag); +#if !USE_MARSHALING_DEFINES +UINT16 +TPMI_DH_OBJECT_Marshal(TPMI_DH_OBJECT* source, BYTE** buffer, INT32* size); +#else +# define TPMI_DH_OBJECT_Marshal(source, buffer, size) \ + TPM_HANDLE_Marshal((TPM_HANDLE*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:43 - Definition of TPMI_DH_PARENT Type +TPM_RC +TPMI_DH_PARENT_Unmarshal( + TPMI_DH_PARENT* target, BYTE** buffer, INT32* size, BOOL flag); +#if !USE_MARSHALING_DEFINES +UINT16 +TPMI_DH_PARENT_Marshal(TPMI_DH_PARENT* source, BYTE** buffer, INT32* size); +#else +# define TPMI_DH_PARENT_Marshal(source, buffer, size) \ + TPM_HANDLE_Marshal((TPM_HANDLE*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:44 - Definition of TPMI_DH_PERSISTENT Type +TPM_RC +TPMI_DH_PERSISTENT_Unmarshal(TPMI_DH_PERSISTENT* target, BYTE** buffer, INT32* size); +#if !USE_MARSHALING_DEFINES +UINT16 +TPMI_DH_PERSISTENT_Marshal(TPMI_DH_PERSISTENT* source, BYTE** buffer, INT32* size); +#else +# define TPMI_DH_PERSISTENT_Marshal(source, buffer, size) \ + TPM_HANDLE_Marshal((TPM_HANDLE*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:45 - Definition of TPMI_DH_ENTITY Type +TPM_RC +TPMI_DH_ENTITY_Unmarshal( + TPMI_DH_ENTITY* target, BYTE** buffer, INT32* size, BOOL flag); + +// Table 2:46 - Definition of TPMI_DH_PCR Type +TPM_RC +TPMI_DH_PCR_Unmarshal(TPMI_DH_PCR* target, BYTE** buffer, INT32* size, BOOL flag); + +// Table 2:47 - Definition of TPMI_SH_AUTH_SESSION Type +TPM_RC +TPMI_SH_AUTH_SESSION_Unmarshal( + TPMI_SH_AUTH_SESSION* target, BYTE** buffer, INT32* size, BOOL flag); +#if !USE_MARSHALING_DEFINES +UINT16 +TPMI_SH_AUTH_SESSION_Marshal( + TPMI_SH_AUTH_SESSION* source, BYTE** buffer, INT32* size); +#else +# define TPMI_SH_AUTH_SESSION_Marshal(source, buffer, size) \ + TPM_HANDLE_Marshal((TPM_HANDLE*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:48 - Definition of TPMI_SH_HMAC Type +TPM_RC +TPMI_SH_HMAC_Unmarshal(TPMI_SH_HMAC* target, BYTE** buffer, INT32* size); +#if !USE_MARSHALING_DEFINES +UINT16 +TPMI_SH_HMAC_Marshal(TPMI_SH_HMAC* source, BYTE** buffer, INT32* size); +#else +# define TPMI_SH_HMAC_Marshal(source, buffer, size) \ + TPM_HANDLE_Marshal((TPM_HANDLE*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:49 - Definition of TPMI_SH_POLICY Type +TPM_RC +TPMI_SH_POLICY_Unmarshal(TPMI_SH_POLICY* target, BYTE** buffer, INT32* size); +#if !USE_MARSHALING_DEFINES +UINT16 +TPMI_SH_POLICY_Marshal(TPMI_SH_POLICY* source, BYTE** buffer, INT32* size); +#else +# define TPMI_SH_POLICY_Marshal(source, buffer, size) \ + TPM_HANDLE_Marshal((TPM_HANDLE*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:50 - Definition of TPMI_DH_CONTEXT Type +TPM_RC +TPMI_DH_CONTEXT_Unmarshal(TPMI_DH_CONTEXT* target, BYTE** buffer, INT32* size); +#if !USE_MARSHALING_DEFINES +UINT16 +TPMI_DH_CONTEXT_Marshal(TPMI_DH_CONTEXT* source, BYTE** buffer, INT32* size); +#else +# define TPMI_DH_CONTEXT_Marshal(source, buffer, size) \ + TPM_HANDLE_Marshal((TPM_HANDLE*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:51 - Definition of TPMI_DH_SAVED Type +TPM_RC +TPMI_DH_SAVED_Unmarshal(TPMI_DH_SAVED* target, BYTE** buffer, INT32* size); +#if !USE_MARSHALING_DEFINES +UINT16 +TPMI_DH_SAVED_Marshal(TPMI_DH_SAVED* source, BYTE** buffer, INT32* size); +#else +# define TPMI_DH_SAVED_Marshal(source, buffer, size) \ + TPM_HANDLE_Marshal((TPM_HANDLE*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:52 - Definition of TPMI_RH_HIERARCHY Type +TPM_RC +TPMI_RH_HIERARCHY_Unmarshal( + TPMI_RH_HIERARCHY* target, BYTE** buffer, INT32* size, BOOL flag); +#if !USE_MARSHALING_DEFINES +UINT16 +TPMI_RH_HIERARCHY_Marshal(TPMI_RH_HIERARCHY* source, BYTE** buffer, INT32* size); +#else +# define TPMI_RH_HIERARCHY_Marshal(source, buffer, size) \ + TPM_HANDLE_Marshal((TPM_HANDLE*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:53 - Definition of TPMI_RH_ENABLES Type +TPM_RC +TPMI_RH_ENABLES_Unmarshal( + TPMI_RH_ENABLES* target, BYTE** buffer, INT32* size, BOOL flag); +#if !USE_MARSHALING_DEFINES +UINT16 +TPMI_RH_ENABLES_Marshal(TPMI_RH_ENABLES* source, BYTE** buffer, INT32* size); +#else +# define TPMI_RH_ENABLES_Marshal(source, buffer, size) \ + TPM_HANDLE_Marshal((TPM_HANDLE*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:54 - Definition of TPMI_RH_HIERARCHY_AUTH Type +TPM_RC +TPMI_RH_HIERARCHY_AUTH_Unmarshal( + TPMI_RH_HIERARCHY_AUTH* target, BYTE** buffer, INT32* size); + +// Table 2:55 - Definition of TPMI_RH_HIERARCHY_POLICY Type +TPM_RC +TPMI_RH_HIERARCHY_POLICY_Unmarshal( + TPMI_RH_HIERARCHY_POLICY* target, BYTE** buffer, INT32* size); + +// Table 2:56 - Definition of TPMI_RH_PLATFORM Type +TPM_RC +TPMI_RH_PLATFORM_Unmarshal(TPMI_RH_PLATFORM* target, BYTE** buffer, INT32* size); + +// Table 2:57 - Definition of TPMI_RH_OWNER Type +TPM_RC +TPMI_RH_OWNER_Unmarshal(TPMI_RH_OWNER* target, BYTE** buffer, INT32* size, BOOL flag); + +// Table 2:58 - Definition of TPMI_RH_ENDORSEMENT Type +TPM_RC +TPMI_RH_ENDORSEMENT_Unmarshal( + TPMI_RH_ENDORSEMENT* target, BYTE** buffer, INT32* size, BOOL flag); + +// Table 2:59 - Definition of TPMI_RH_PROVISION Type +TPM_RC +TPMI_RH_PROVISION_Unmarshal(TPMI_RH_PROVISION* target, BYTE** buffer, INT32* size); + +// Table 2:60 - Definition of TPMI_RH_CLEAR Type +TPM_RC +TPMI_RH_CLEAR_Unmarshal(TPMI_RH_CLEAR* target, BYTE** buffer, INT32* size); + +// Table 2:61 - Definition of TPMI_RH_NV_AUTH Type +TPM_RC +TPMI_RH_NV_AUTH_Unmarshal(TPMI_RH_NV_AUTH* target, BYTE** buffer, INT32* size); + +// Table 2:62 - Definition of TPMI_RH_LOCKOUT Type +TPM_RC +TPMI_RH_LOCKOUT_Unmarshal(TPMI_RH_LOCKOUT* target, BYTE** buffer, INT32* size); + +// Table 2:63 - Definition of TPMI_RH_NV_INDEX Type +TPM_RC +TPMI_RH_NV_INDEX_Unmarshal(TPMI_RH_NV_INDEX* target, BYTE** buffer, INT32* size); +#if !USE_MARSHALING_DEFINES +UINT16 +TPMI_RH_NV_INDEX_Marshal(TPMI_RH_NV_INDEX* source, BYTE** buffer, INT32* size); +#else +# define TPMI_RH_NV_INDEX_Marshal(source, buffer, size) \ + TPM_HANDLE_Marshal((TPM_HANDLE*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:64 - Definition of TPMI_RH_AC Type +TPM_RC +TPMI_RH_AC_Unmarshal(TPMI_RH_AC* target, BYTE** buffer, INT32* size); + +// Table 2:65 - Definition of TPMI_RH_ACT Type +TPM_RC +TPMI_RH_ACT_Unmarshal(TPMI_RH_ACT* target, BYTE** buffer, INT32* size); +#if !USE_MARSHALING_DEFINES +UINT16 +TPMI_RH_ACT_Marshal(TPMI_RH_ACT* source, BYTE** buffer, INT32* size); +#else +# define TPMI_RH_ACT_Marshal(source, buffer, size) \ + TPM_HANDLE_Marshal((TPM_HANDLE*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:66 - Definition of TPMI_ALG_HASH Type +TPM_RC +TPMI_ALG_HASH_Unmarshal(TPMI_ALG_HASH* target, BYTE** buffer, INT32* size, BOOL flag); +#if !USE_MARSHALING_DEFINES +UINT16 +TPMI_ALG_HASH_Marshal(TPMI_ALG_HASH* source, BYTE** buffer, INT32* size); +#else +# define TPMI_ALG_HASH_Marshal(source, buffer, size) \ + TPM_ALG_ID_Marshal((TPM_ALG_ID*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:67 - Definition of TPMI_ALG_ASYM Type +TPM_RC +TPMI_ALG_ASYM_Unmarshal(TPMI_ALG_ASYM* target, BYTE** buffer, INT32* size, BOOL flag); +#if !USE_MARSHALING_DEFINES +UINT16 +TPMI_ALG_ASYM_Marshal(TPMI_ALG_ASYM* source, BYTE** buffer, INT32* size); +#else +# define TPMI_ALG_ASYM_Marshal(source, buffer, size) \ + TPM_ALG_ID_Marshal((TPM_ALG_ID*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:68 - Definition of TPMI_ALG_SYM Type +TPM_RC +TPMI_ALG_SYM_Unmarshal(TPMI_ALG_SYM* target, BYTE** buffer, INT32* size, BOOL flag); +#if !USE_MARSHALING_DEFINES +UINT16 +TPMI_ALG_SYM_Marshal(TPMI_ALG_SYM* source, BYTE** buffer, INT32* size); +#else +# define TPMI_ALG_SYM_Marshal(source, buffer, size) \ + TPM_ALG_ID_Marshal((TPM_ALG_ID*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:69 - Definition of TPMI_ALG_SYM_OBJECT Type +TPM_RC +TPMI_ALG_SYM_OBJECT_Unmarshal( + TPMI_ALG_SYM_OBJECT* target, BYTE** buffer, INT32* size, BOOL flag); +#if !USE_MARSHALING_DEFINES +UINT16 +TPMI_ALG_SYM_OBJECT_Marshal(TPMI_ALG_SYM_OBJECT* source, BYTE** buffer, INT32* size); +#else +# define TPMI_ALG_SYM_OBJECT_Marshal(source, buffer, size) \ + TPM_ALG_ID_Marshal((TPM_ALG_ID*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:70 - Definition of TPMI_ALG_SYM_MODE Type +TPM_RC +TPMI_ALG_SYM_MODE_Unmarshal( + TPMI_ALG_SYM_MODE* target, BYTE** buffer, INT32* size, BOOL flag); +#if !USE_MARSHALING_DEFINES +UINT16 +TPMI_ALG_SYM_MODE_Marshal(TPMI_ALG_SYM_MODE* source, BYTE** buffer, INT32* size); +#else +# define TPMI_ALG_SYM_MODE_Marshal(source, buffer, size) \ + TPM_ALG_ID_Marshal((TPM_ALG_ID*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:71 - Definition of TPMI_ALG_KDF Type +TPM_RC +TPMI_ALG_KDF_Unmarshal(TPMI_ALG_KDF* target, BYTE** buffer, INT32* size, BOOL flag); +#if !USE_MARSHALING_DEFINES +UINT16 +TPMI_ALG_KDF_Marshal(TPMI_ALG_KDF* source, BYTE** buffer, INT32* size); +#else +# define TPMI_ALG_KDF_Marshal(source, buffer, size) \ + TPM_ALG_ID_Marshal((TPM_ALG_ID*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:72 - Definition of TPMI_ALG_SIG_SCHEME Type +TPM_RC +TPMI_ALG_SIG_SCHEME_Unmarshal( + TPMI_ALG_SIG_SCHEME* target, BYTE** buffer, INT32* size, BOOL flag); +#if !USE_MARSHALING_DEFINES +UINT16 +TPMI_ALG_SIG_SCHEME_Marshal(TPMI_ALG_SIG_SCHEME* source, BYTE** buffer, INT32* size); +#else +# define TPMI_ALG_SIG_SCHEME_Marshal(source, buffer, size) \ + TPM_ALG_ID_Marshal((TPM_ALG_ID*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:73 - Definition of TPMI_ECC_KEY_EXCHANGE Type +#if ALG_ECC +TPM_RC +TPMI_ECC_KEY_EXCHANGE_Unmarshal( + TPMI_ECC_KEY_EXCHANGE* target, BYTE** buffer, INT32* size, BOOL flag); +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_ECC_KEY_EXCHANGE_Marshal( + TPMI_ECC_KEY_EXCHANGE* source, BYTE** buffer, INT32* size); +# else +# define TPMI_ECC_KEY_EXCHANGE_Marshal(source, buffer, size) \ + TPM_ALG_ID_Marshal((TPM_ALG_ID*)(source), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +#endif // ALG_ECC + +// Table 2:74 - Definition of TPMI_ST_COMMAND_TAG Type +TPM_RC +TPMI_ST_COMMAND_TAG_Unmarshal( + TPMI_ST_COMMAND_TAG* target, BYTE** buffer, INT32* size); +#if !USE_MARSHALING_DEFINES +UINT16 +TPMI_ST_COMMAND_TAG_Marshal(TPMI_ST_COMMAND_TAG* source, BYTE** buffer, INT32* size); +#else +# define TPMI_ST_COMMAND_TAG_Marshal(source, buffer, size) \ + TPM_ST_Marshal((TPM_ST*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:75 - Definition of TPMI_ALG_MAC_SCHEME Type +TPM_RC +TPMI_ALG_MAC_SCHEME_Unmarshal( + TPMI_ALG_MAC_SCHEME* target, BYTE** buffer, INT32* size, BOOL flag); +#if !USE_MARSHALING_DEFINES +UINT16 +TPMI_ALG_MAC_SCHEME_Marshal(TPMI_ALG_MAC_SCHEME* source, BYTE** buffer, INT32* size); +#else +# define TPMI_ALG_MAC_SCHEME_Marshal(source, buffer, size) \ + TPM_ALG_ID_Marshal((TPM_ALG_ID*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:76 - Definition of TPMI_ALG_CIPHER_MODE Type +TPM_RC +TPMI_ALG_CIPHER_MODE_Unmarshal( + TPMI_ALG_CIPHER_MODE* target, BYTE** buffer, INT32* size, BOOL flag); +#if !USE_MARSHALING_DEFINES +UINT16 +TPMI_ALG_CIPHER_MODE_Marshal( + TPMI_ALG_CIPHER_MODE* source, BYTE** buffer, INT32* size); +#else +# define TPMI_ALG_CIPHER_MODE_Marshal(source, buffer, size) \ + TPM_ALG_ID_Marshal((TPM_ALG_ID*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:77 - Definition of TPMS_EMPTY Structure +TPM_RC +TPMS_EMPTY_Unmarshal(TPMS_EMPTY* target, BYTE** buffer, INT32* size); +UINT16 +TPMS_EMPTY_Marshal(TPMS_EMPTY* source, BYTE** buffer, INT32* size); + +// Table 2:78 - Definition of TPMS_ALGORITHM_DESCRIPTION Structure +UINT16 +TPMS_ALGORITHM_DESCRIPTION_Marshal( + TPMS_ALGORITHM_DESCRIPTION* source, BYTE** buffer, INT32* size); + +// Table 2:79 - Definition of TPMU_HA Union +TPM_RC +TPMU_HA_Unmarshal(TPMU_HA* target, BYTE** buffer, INT32* size, UINT32 selector); +UINT16 +TPMU_HA_Marshal(TPMU_HA* source, BYTE** buffer, INT32* size, UINT32 selector); + +// Table 2:80 - Definition of TPMT_HA Structure +TPM_RC +TPMT_HA_Unmarshal(TPMT_HA* target, BYTE** buffer, INT32* size, BOOL flag); +UINT16 +TPMT_HA_Marshal(TPMT_HA* source, BYTE** buffer, INT32* size); + +// Table 2:81 - Definition of TPM2B_DIGEST Structure +TPM_RC +TPM2B_DIGEST_Unmarshal(TPM2B_DIGEST* target, BYTE** buffer, INT32* size); +UINT16 +TPM2B_DIGEST_Marshal(TPM2B_DIGEST* source, BYTE** buffer, INT32* size); + +// Table 2:82 - Definition of TPM2B_DATA Structure +TPM_RC +TPM2B_DATA_Unmarshal(TPM2B_DATA* target, BYTE** buffer, INT32* size); +UINT16 +TPM2B_DATA_Marshal(TPM2B_DATA* source, BYTE** buffer, INT32* size); + +// Table 2:83 - Definition of Types for TPM2B_NONCE +#if !USE_MARSHALING_DEFINES +TPM_RC +TPM2B_NONCE_Unmarshal(TPM2B_NONCE* target, BYTE** buffer, INT32* size); +#else +# define TPM2B_NONCE_Unmarshal(target, buffer, size) \ + TPM2B_DIGEST_Unmarshal((TPM2B_DIGEST*)(target), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES +#if !USE_MARSHALING_DEFINES +UINT16 +TPM2B_NONCE_Marshal(TPM2B_NONCE* source, BYTE** buffer, INT32* size); +#else +# define TPM2B_NONCE_Marshal(source, buffer, size) \ + TPM2B_DIGEST_Marshal((TPM2B_DIGEST*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:84 - Definition of Types for TPM2B_AUTH +#if !USE_MARSHALING_DEFINES +TPM_RC +TPM2B_AUTH_Unmarshal(TPM2B_AUTH* target, BYTE** buffer, INT32* size); +#else +# define TPM2B_AUTH_Unmarshal(target, buffer, size) \ + TPM2B_DIGEST_Unmarshal((TPM2B_DIGEST*)(target), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES +#if !USE_MARSHALING_DEFINES +UINT16 +TPM2B_AUTH_Marshal(TPM2B_AUTH* source, BYTE** buffer, INT32* size); +#else +# define TPM2B_AUTH_Marshal(source, buffer, size) \ + TPM2B_DIGEST_Marshal((TPM2B_DIGEST*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:85 - Definition of Types for TPM2B_OPERAND +#if !USE_MARSHALING_DEFINES +TPM_RC +TPM2B_OPERAND_Unmarshal(TPM2B_OPERAND* target, BYTE** buffer, INT32* size); +#else +# define TPM2B_OPERAND_Unmarshal(target, buffer, size) \ + TPM2B_DIGEST_Unmarshal((TPM2B_DIGEST*)(target), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES +#if !USE_MARSHALING_DEFINES +UINT16 +TPM2B_OPERAND_Marshal(TPM2B_OPERAND* source, BYTE** buffer, INT32* size); +#else +# define TPM2B_OPERAND_Marshal(source, buffer, size) \ + TPM2B_DIGEST_Marshal((TPM2B_DIGEST*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:86 - Definition of TPM2B_EVENT Structure +TPM_RC +TPM2B_EVENT_Unmarshal(TPM2B_EVENT* target, BYTE** buffer, INT32* size); +UINT16 +TPM2B_EVENT_Marshal(TPM2B_EVENT* source, BYTE** buffer, INT32* size); + +// Table 2:87 - Definition of TPM2B_MAX_BUFFER Structure +TPM_RC +TPM2B_MAX_BUFFER_Unmarshal(TPM2B_MAX_BUFFER* target, BYTE** buffer, INT32* size); +UINT16 +TPM2B_MAX_BUFFER_Marshal(TPM2B_MAX_BUFFER* source, BYTE** buffer, INT32* size); + +// Table 2:88 - Definition of TPM2B_MAX_NV_BUFFER Structure +TPM_RC +TPM2B_MAX_NV_BUFFER_Unmarshal( + TPM2B_MAX_NV_BUFFER* target, BYTE** buffer, INT32* size); +UINT16 +TPM2B_MAX_NV_BUFFER_Marshal(TPM2B_MAX_NV_BUFFER* source, BYTE** buffer, INT32* size); + +// Table 2:89 - Definition of TPM2B_TIMEOUT Structure +TPM_RC +TPM2B_TIMEOUT_Unmarshal(TPM2B_TIMEOUT* target, BYTE** buffer, INT32* size); +UINT16 +TPM2B_TIMEOUT_Marshal(TPM2B_TIMEOUT* source, BYTE** buffer, INT32* size); + +// Table 2:90 - Definition of TPM2B_IV Structure +TPM_RC +TPM2B_IV_Unmarshal(TPM2B_IV* target, BYTE** buffer, INT32* size); +UINT16 +TPM2B_IV_Marshal(TPM2B_IV* source, BYTE** buffer, INT32* size); + +// Table 2:91 - Definition of TPMU_NAME Union +// Table 2:92 - Definition of TPM2B_NAME Structure +TPM_RC +TPM2B_NAME_Unmarshal(TPM2B_NAME* target, BYTE** buffer, INT32* size); +UINT16 +TPM2B_NAME_Marshal(TPM2B_NAME* source, BYTE** buffer, INT32* size); + +// Table 2:93 - Definition of TPMS_PCR_SELECT Structure +TPM_RC +TPMS_PCR_SELECT_Unmarshal(TPMS_PCR_SELECT* target, BYTE** buffer, INT32* size); +UINT16 +TPMS_PCR_SELECT_Marshal(TPMS_PCR_SELECT* source, BYTE** buffer, INT32* size); + +// Table 2:94 - Definition of TPMS_PCR_SELECTION Structure +TPM_RC +TPMS_PCR_SELECTION_Unmarshal(TPMS_PCR_SELECTION* target, BYTE** buffer, INT32* size); +UINT16 +TPMS_PCR_SELECTION_Marshal(TPMS_PCR_SELECTION* source, BYTE** buffer, INT32* size); + +// Table 2:97 - Definition of TPMT_TK_CREATION Structure +TPM_RC +TPMT_TK_CREATION_Unmarshal(TPMT_TK_CREATION* target, BYTE** buffer, INT32* size); +UINT16 +TPMT_TK_CREATION_Marshal(TPMT_TK_CREATION* source, BYTE** buffer, INT32* size); + +// Table 2:98 - Definition of TPMT_TK_VERIFIED Structure +TPM_RC +TPMT_TK_VERIFIED_Unmarshal(TPMT_TK_VERIFIED* target, BYTE** buffer, INT32* size); +UINT16 +TPMT_TK_VERIFIED_Marshal(TPMT_TK_VERIFIED* source, BYTE** buffer, INT32* size); + +// Table 2:99 - Definition of TPMT_TK_AUTH Structure +TPM_RC +TPMT_TK_AUTH_Unmarshal(TPMT_TK_AUTH* target, BYTE** buffer, INT32* size); +UINT16 +TPMT_TK_AUTH_Marshal(TPMT_TK_AUTH* source, BYTE** buffer, INT32* size); + +// Table 2:100 - Definition of TPMT_TK_HASHCHECK Structure +TPM_RC +TPMT_TK_HASHCHECK_Unmarshal(TPMT_TK_HASHCHECK* target, BYTE** buffer, INT32* size); +UINT16 +TPMT_TK_HASHCHECK_Marshal(TPMT_TK_HASHCHECK* source, BYTE** buffer, INT32* size); + +// Table 2:101 - Definition of TPMS_ALG_PROPERTY Structure +UINT16 +TPMS_ALG_PROPERTY_Marshal(TPMS_ALG_PROPERTY* source, BYTE** buffer, INT32* size); + +// Table 2:102 - Definition of TPMS_TAGGED_PROPERTY Structure +UINT16 +TPMS_TAGGED_PROPERTY_Marshal( + TPMS_TAGGED_PROPERTY* source, BYTE** buffer, INT32* size); + +// Table 2:103 - Definition of TPMS_TAGGED_PCR_SELECT Structure +UINT16 +TPMS_TAGGED_PCR_SELECT_Marshal( + TPMS_TAGGED_PCR_SELECT* source, BYTE** buffer, INT32* size); + +// Table 2:104 - Definition of TPMS_TAGGED_POLICY Structure +UINT16 +TPMS_TAGGED_POLICY_Marshal(TPMS_TAGGED_POLICY* source, BYTE** buffer, INT32* size); + +// Table 2:105 - Definition of TPMS_ACT_DATA Structure +UINT16 +TPMS_ACT_DATA_Marshal(TPMS_ACT_DATA* source, BYTE** buffer, INT32* size); + +// Table 2:106 - Definition of TPML_CC Structure +TPM_RC +TPML_CC_Unmarshal(TPML_CC* target, BYTE** buffer, INT32* size); +UINT16 +TPML_CC_Marshal(TPML_CC* source, BYTE** buffer, INT32* size); + +// Table 2:107 - Definition of TPML_CCA Structure +UINT16 +TPML_CCA_Marshal(TPML_CCA* source, BYTE** buffer, INT32* size); + +// Table 2:108 - Definition of TPML_ALG Structure +TPM_RC +TPML_ALG_Unmarshal(TPML_ALG* target, BYTE** buffer, INT32* size); +UINT16 +TPML_ALG_Marshal(TPML_ALG* source, BYTE** buffer, INT32* size); + +// Table 2:109 - Definition of TPML_HANDLE Structure +UINT16 +TPML_HANDLE_Marshal(TPML_HANDLE* source, BYTE** buffer, INT32* size); + +// Table 2:110 - Definition of TPML_DIGEST Structure +TPM_RC +TPML_DIGEST_Unmarshal(TPML_DIGEST* target, BYTE** buffer, INT32* size); +UINT16 +TPML_DIGEST_Marshal(TPML_DIGEST* source, BYTE** buffer, INT32* size); + +// Table 2:111 - Definition of TPML_DIGEST_VALUES Structure +TPM_RC +TPML_DIGEST_VALUES_Unmarshal(TPML_DIGEST_VALUES* target, BYTE** buffer, INT32* size); +UINT16 +TPML_DIGEST_VALUES_Marshal(TPML_DIGEST_VALUES* source, BYTE** buffer, INT32* size); + +// Table 2:112 - Definition of TPML_PCR_SELECTION Structure +TPM_RC +TPML_PCR_SELECTION_Unmarshal(TPML_PCR_SELECTION* target, BYTE** buffer, INT32* size); +UINT16 +TPML_PCR_SELECTION_Marshal(TPML_PCR_SELECTION* source, BYTE** buffer, INT32* size); + +// Table 2:113 - Definition of TPML_ALG_PROPERTY Structure +UINT16 +TPML_ALG_PROPERTY_Marshal(TPML_ALG_PROPERTY* source, BYTE** buffer, INT32* size); + +// Table 2:114 - Definition of TPML_TAGGED_TPM_PROPERTY Structure +UINT16 +TPML_TAGGED_TPM_PROPERTY_Marshal( + TPML_TAGGED_TPM_PROPERTY* source, BYTE** buffer, INT32* size); + +// Table 2:115 - Definition of TPML_TAGGED_PCR_PROPERTY Structure +UINT16 +TPML_TAGGED_PCR_PROPERTY_Marshal( + TPML_TAGGED_PCR_PROPERTY* source, BYTE** buffer, INT32* size); + +// Table 2:116 - Definition of TPML_ECC_CURVE Structure +#if ALG_ECC +UINT16 +TPML_ECC_CURVE_Marshal(TPML_ECC_CURVE* source, BYTE** buffer, INT32* size); +#endif // ALG_ECC + +// Table 2:117 - Definition of TPML_TAGGED_POLICY Structure +UINT16 +TPML_TAGGED_POLICY_Marshal(TPML_TAGGED_POLICY* source, BYTE** buffer, INT32* size); + +// Table 2:118 - Definition of TPML_ACT_DATA Structure +UINT16 +TPML_ACT_DATA_Marshal(TPML_ACT_DATA* source, BYTE** buffer, INT32* size); + +// Table 2:119 - Definition of TPMU_CAPABILITIES Union +UINT16 +TPMU_CAPABILITIES_Marshal( + TPMU_CAPABILITIES* source, BYTE** buffer, INT32* size, UINT32 selector); + +// Table 2:120 - Definition of TPMS_CAPABILITY_DATA Structure +UINT16 +TPMS_CAPABILITY_DATA_Marshal( + TPMS_CAPABILITY_DATA* source, BYTE** buffer, INT32* size); + +// Table 2:121 - Definition of TPMS_CLOCK_INFO Structure +TPM_RC +TPMS_CLOCK_INFO_Unmarshal(TPMS_CLOCK_INFO* target, BYTE** buffer, INT32* size); +UINT16 +TPMS_CLOCK_INFO_Marshal(TPMS_CLOCK_INFO* source, BYTE** buffer, INT32* size); + +// Table 2:122 - Definition of TPMS_TIME_INFO Structure +TPM_RC +TPMS_TIME_INFO_Unmarshal(TPMS_TIME_INFO* target, BYTE** buffer, INT32* size); +UINT16 +TPMS_TIME_INFO_Marshal(TPMS_TIME_INFO* source, BYTE** buffer, INT32* size); + +// Table 2:123 - Definition of TPMS_TIME_ATTEST_INFO Structure +UINT16 +TPMS_TIME_ATTEST_INFO_Marshal( + TPMS_TIME_ATTEST_INFO* source, BYTE** buffer, INT32* size); + +// Table 2:124 - Definition of TPMS_CERTIFY_INFO Structure +UINT16 +TPMS_CERTIFY_INFO_Marshal(TPMS_CERTIFY_INFO* source, BYTE** buffer, INT32* size); + +// Table 2:125 - Definition of TPMS_QUOTE_INFO Structure +UINT16 +TPMS_QUOTE_INFO_Marshal(TPMS_QUOTE_INFO* source, BYTE** buffer, INT32* size); + +// Table 2:126 - Definition of TPMS_COMMAND_AUDIT_INFO Structure +UINT16 +TPMS_COMMAND_AUDIT_INFO_Marshal( + TPMS_COMMAND_AUDIT_INFO* source, BYTE** buffer, INT32* size); + +// Table 2:127 - Definition of TPMS_SESSION_AUDIT_INFO Structure +UINT16 +TPMS_SESSION_AUDIT_INFO_Marshal( + TPMS_SESSION_AUDIT_INFO* source, BYTE** buffer, INT32* size); + +// Table 2:128 - Definition of TPMS_CREATION_INFO Structure +UINT16 +TPMS_CREATION_INFO_Marshal(TPMS_CREATION_INFO* source, BYTE** buffer, INT32* size); + +// Table 2:129 - Definition of TPMS_NV_CERTIFY_INFO Structure +UINT16 +TPMS_NV_CERTIFY_INFO_Marshal( + TPMS_NV_CERTIFY_INFO* source, BYTE** buffer, INT32* size); + +// Table 2:130 - Definition of TPMS_NV_DIGEST_CERTIFY_INFO Structure +UINT16 +TPMS_NV_DIGEST_CERTIFY_INFO_Marshal( + TPMS_NV_DIGEST_CERTIFY_INFO* source, BYTE** buffer, INT32* size); + +// Table 2:131 - Definition of TPMI_ST_ATTEST Type +#if !USE_MARSHALING_DEFINES +UINT16 +TPMI_ST_ATTEST_Marshal(TPMI_ST_ATTEST* source, BYTE** buffer, INT32* size); +#else +# define TPMI_ST_ATTEST_Marshal(source, buffer, size) \ + TPM_ST_Marshal((TPM_ST*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:132 - Definition of TPMU_ATTEST Union +UINT16 +TPMU_ATTEST_Marshal(TPMU_ATTEST* source, BYTE** buffer, INT32* size, UINT32 selector); + +// Table 2:133 - Definition of TPMS_ATTEST Structure +UINT16 +TPMS_ATTEST_Marshal(TPMS_ATTEST* source, BYTE** buffer, INT32* size); + +// Table 2:134 - Definition of TPM2B_ATTEST Structure +UINT16 +TPM2B_ATTEST_Marshal(TPM2B_ATTEST* source, BYTE** buffer, INT32* size); + +// Table 2:135 - Definition of TPMS_AUTH_COMMAND Structure +TPM_RC +TPMS_AUTH_COMMAND_Unmarshal(TPMS_AUTH_COMMAND* target, BYTE** buffer, INT32* size); + +// Table 2:136 - Definition of TPMS_AUTH_RESPONSE Structure +UINT16 +TPMS_AUTH_RESPONSE_Marshal(TPMS_AUTH_RESPONSE* source, BYTE** buffer, INT32* size); + +// Table 2:137 - Definition of TPMI_TDES_KEY_BITS Type +#if ALG_TDES +TPM_RC +TPMI_TDES_KEY_BITS_Unmarshal(TPMI_TDES_KEY_BITS* target, BYTE** buffer, INT32* size); +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_TDES_KEY_BITS_Marshal(TPMI_TDES_KEY_BITS* source, BYTE** buffer, INT32* size); +# else +# define TPMI_TDES_KEY_BITS_Marshal(source, buffer, size) \ + TPM_KEY_BITS_Marshal((TPM_KEY_BITS*)(source), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +#endif // ALG_TDES + +// Table 2:137 - Definition of TPMI_AES_KEY_BITS Type +#if ALG_AES +TPM_RC +TPMI_AES_KEY_BITS_Unmarshal(TPMI_AES_KEY_BITS* target, BYTE** buffer, INT32* size); +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_AES_KEY_BITS_Marshal(TPMI_AES_KEY_BITS* source, BYTE** buffer, INT32* size); +# else +# define TPMI_AES_KEY_BITS_Marshal(source, buffer, size) \ + TPM_KEY_BITS_Marshal((TPM_KEY_BITS*)(source), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +#endif // ALG_AES + +// Table 2:137 - Definition of TPMI_SM4_KEY_BITS Type +#if ALG_SM4 +TPM_RC +TPMI_SM4_KEY_BITS_Unmarshal(TPMI_SM4_KEY_BITS* target, BYTE** buffer, INT32* size); +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_SM4_KEY_BITS_Marshal(TPMI_SM4_KEY_BITS* source, BYTE** buffer, INT32* size); +# else +# define TPMI_SM4_KEY_BITS_Marshal(source, buffer, size) \ + TPM_KEY_BITS_Marshal((TPM_KEY_BITS*)(source), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +#endif // ALG_SM4 + +// Table 2:137 - Definition of TPMI_CAMELLIA_KEY_BITS Type +#if ALG_CAMELLIA +TPM_RC +TPMI_CAMELLIA_KEY_BITS_Unmarshal( + TPMI_CAMELLIA_KEY_BITS* target, BYTE** buffer, INT32* size); +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_CAMELLIA_KEY_BITS_Marshal( + TPMI_CAMELLIA_KEY_BITS* source, BYTE** buffer, INT32* size); +# else +# define TPMI_CAMELLIA_KEY_BITS_Marshal(source, buffer, size) \ + TPM_KEY_BITS_Marshal((TPM_KEY_BITS*)(source), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +#endif // ALG_CAMELLIA + +// Table 2:138 - Definition of TPMU_SYM_KEY_BITS Union +TPM_RC +TPMU_SYM_KEY_BITS_Unmarshal( + TPMU_SYM_KEY_BITS* target, BYTE** buffer, INT32* size, UINT32 selector); +UINT16 +TPMU_SYM_KEY_BITS_Marshal( + TPMU_SYM_KEY_BITS* source, BYTE** buffer, INT32* size, UINT32 selector); + +// Table 2:139 - Definition of TPMU_SYM_MODE Union +TPM_RC +TPMU_SYM_MODE_Unmarshal( + TPMU_SYM_MODE* target, BYTE** buffer, INT32* size, UINT32 selector); +UINT16 +TPMU_SYM_MODE_Marshal( + TPMU_SYM_MODE* source, BYTE** buffer, INT32* size, UINT32 selector); + +// Table 2:141 - Definition of TPMT_SYM_DEF Structure +TPM_RC +TPMT_SYM_DEF_Unmarshal(TPMT_SYM_DEF* target, BYTE** buffer, INT32* size, BOOL flag); +UINT16 +TPMT_SYM_DEF_Marshal(TPMT_SYM_DEF* source, BYTE** buffer, INT32* size); + +// Table 2:142 - Definition of TPMT_SYM_DEF_OBJECT Structure +TPM_RC +TPMT_SYM_DEF_OBJECT_Unmarshal( + TPMT_SYM_DEF_OBJECT* target, BYTE** buffer, INT32* size, BOOL flag); +UINT16 +TPMT_SYM_DEF_OBJECT_Marshal(TPMT_SYM_DEF_OBJECT* source, BYTE** buffer, INT32* size); + +// Table 2:143 - Definition of TPM2B_SYM_KEY Structure +TPM_RC +TPM2B_SYM_KEY_Unmarshal(TPM2B_SYM_KEY* target, BYTE** buffer, INT32* size); +UINT16 +TPM2B_SYM_KEY_Marshal(TPM2B_SYM_KEY* source, BYTE** buffer, INT32* size); + +// Table 2:144 - Definition of TPMS_SYMCIPHER_PARMS Structure +TPM_RC +TPMS_SYMCIPHER_PARMS_Unmarshal( + TPMS_SYMCIPHER_PARMS* target, BYTE** buffer, INT32* size); +UINT16 +TPMS_SYMCIPHER_PARMS_Marshal( + TPMS_SYMCIPHER_PARMS* source, BYTE** buffer, INT32* size); + +// Table 2:145 - Definition of TPM2B_LABEL Structure +TPM_RC +TPM2B_LABEL_Unmarshal(TPM2B_LABEL* target, BYTE** buffer, INT32* size); +UINT16 +TPM2B_LABEL_Marshal(TPM2B_LABEL* source, BYTE** buffer, INT32* size); + +// Table 2:146 - Definition of TPMS_DERIVE Structure +TPM_RC +TPMS_DERIVE_Unmarshal(TPMS_DERIVE* target, BYTE** buffer, INT32* size); +UINT16 +TPMS_DERIVE_Marshal(TPMS_DERIVE* source, BYTE** buffer, INT32* size); + +// Table 2:147 - Definition of TPM2B_DERIVE Structure +TPM_RC +TPM2B_DERIVE_Unmarshal(TPM2B_DERIVE* target, BYTE** buffer, INT32* size); +UINT16 +TPM2B_DERIVE_Marshal(TPM2B_DERIVE* source, BYTE** buffer, INT32* size); + +// Table 2:148 - Definition of TPMU_SENSITIVE_CREATE Union +// Table 2:149 - Definition of TPM2B_SENSITIVE_DATA Structure +TPM_RC +TPM2B_SENSITIVE_DATA_Unmarshal( + TPM2B_SENSITIVE_DATA* target, BYTE** buffer, INT32* size); +UINT16 +TPM2B_SENSITIVE_DATA_Marshal( + TPM2B_SENSITIVE_DATA* source, BYTE** buffer, INT32* size); + +// Table 2:150 - Definition of TPMS_SENSITIVE_CREATE Structure +TPM_RC +TPMS_SENSITIVE_CREATE_Unmarshal( + TPMS_SENSITIVE_CREATE* target, BYTE** buffer, INT32* size); + +// Table 2:151 - Definition of TPM2B_SENSITIVE_CREATE Structure +TPM_RC +TPM2B_SENSITIVE_CREATE_Unmarshal( + TPM2B_SENSITIVE_CREATE* target, BYTE** buffer, INT32* size); + +// Table 2:152 - Definition of TPMS_SCHEME_HASH Structure +TPM_RC +TPMS_SCHEME_HASH_Unmarshal(TPMS_SCHEME_HASH* target, BYTE** buffer, INT32* size); +UINT16 +TPMS_SCHEME_HASH_Marshal(TPMS_SCHEME_HASH* source, BYTE** buffer, INT32* size); + +// Table 2:153 - Definition of TPMS_SCHEME_ECDAA Structure +#if ALG_ECC +TPM_RC +TPMS_SCHEME_ECDAA_Unmarshal(TPMS_SCHEME_ECDAA* target, BYTE** buffer, INT32* size); +UINT16 +TPMS_SCHEME_ECDAA_Marshal(TPMS_SCHEME_ECDAA* source, BYTE** buffer, INT32* size); +#endif // ALG_ECC + +// Table 2:154 - Definition of TPMI_ALG_KEYEDHASH_SCHEME Type +TPM_RC +TPMI_ALG_KEYEDHASH_SCHEME_Unmarshal( + TPMI_ALG_KEYEDHASH_SCHEME* target, BYTE** buffer, INT32* size, BOOL flag); +#if !USE_MARSHALING_DEFINES +UINT16 +TPMI_ALG_KEYEDHASH_SCHEME_Marshal( + TPMI_ALG_KEYEDHASH_SCHEME* source, BYTE** buffer, INT32* size); +#else +# define TPMI_ALG_KEYEDHASH_SCHEME_Marshal(source, buffer, size) \ + TPM_ALG_ID_Marshal((TPM_ALG_ID*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:155 - Definition of Types for HMAC_SIG_SCHEME +#if !USE_MARSHALING_DEFINES +TPM_RC +TPMS_SCHEME_HMAC_Unmarshal(TPMS_SCHEME_HMAC* target, BYTE** buffer, INT32* size); +#else +# define TPMS_SCHEME_HMAC_Unmarshal(target, buffer, size) \ + TPMS_SCHEME_HASH_Unmarshal((TPMS_SCHEME_HASH*)(target), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES +#if !USE_MARSHALING_DEFINES +UINT16 +TPMS_SCHEME_HMAC_Marshal(TPMS_SCHEME_HMAC* source, BYTE** buffer, INT32* size); +#else +# define TPMS_SCHEME_HMAC_Marshal(source, buffer, size) \ + TPMS_SCHEME_HASH_Marshal((TPMS_SCHEME_HASH*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:156 - Definition of TPMS_SCHEME_XOR Structure +TPM_RC +TPMS_SCHEME_XOR_Unmarshal(TPMS_SCHEME_XOR* target, BYTE** buffer, INT32* size); +UINT16 +TPMS_SCHEME_XOR_Marshal(TPMS_SCHEME_XOR* source, BYTE** buffer, INT32* size); + +// Table 2:157 - Definition of TPMU_SCHEME_KEYEDHASH Union +TPM_RC +TPMU_SCHEME_KEYEDHASH_Unmarshal( + TPMU_SCHEME_KEYEDHASH* target, BYTE** buffer, INT32* size, UINT32 selector); +UINT16 +TPMU_SCHEME_KEYEDHASH_Marshal( + TPMU_SCHEME_KEYEDHASH* source, BYTE** buffer, INT32* size, UINT32 selector); + +// Table 2:158 - Definition of TPMT_KEYEDHASH_SCHEME Structure +TPM_RC +TPMT_KEYEDHASH_SCHEME_Unmarshal( + TPMT_KEYEDHASH_SCHEME* target, BYTE** buffer, INT32* size, BOOL flag); +UINT16 +TPMT_KEYEDHASH_SCHEME_Marshal( + TPMT_KEYEDHASH_SCHEME* source, BYTE** buffer, INT32* size); + +// Table 2:159 - Definition of Types for RSA Signature Schemes +#if ALG_RSA +# if !USE_MARSHALING_DEFINES +TPM_RC +TPMS_SIG_SCHEME_RSASSA_Unmarshal( + TPMS_SIG_SCHEME_RSASSA* target, BYTE** buffer, INT32* size); +# else +# define TPMS_SIG_SCHEME_RSASSA_Unmarshal(target, buffer, size) \ + TPMS_SCHEME_HASH_Unmarshal((TPMS_SCHEME_HASH*)(target), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +# if !USE_MARSHALING_DEFINES +UINT16 +TPMS_SIG_SCHEME_RSASSA_Marshal( + TPMS_SIG_SCHEME_RSASSA* source, BYTE** buffer, INT32* size); +# else +# define TPMS_SIG_SCHEME_RSASSA_Marshal(source, buffer, size) \ + TPMS_SCHEME_HASH_Marshal((TPMS_SCHEME_HASH*)(source), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +# if !USE_MARSHALING_DEFINES +TPM_RC +TPMS_SIG_SCHEME_RSAPSS_Unmarshal( + TPMS_SIG_SCHEME_RSAPSS* target, BYTE** buffer, INT32* size); +# else +# define TPMS_SIG_SCHEME_RSAPSS_Unmarshal(target, buffer, size) \ + TPMS_SCHEME_HASH_Unmarshal((TPMS_SCHEME_HASH*)(target), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +# if !USE_MARSHALING_DEFINES +UINT16 +TPMS_SIG_SCHEME_RSAPSS_Marshal( + TPMS_SIG_SCHEME_RSAPSS* source, BYTE** buffer, INT32* size); +# else +# define TPMS_SIG_SCHEME_RSAPSS_Marshal(source, buffer, size) \ + TPMS_SCHEME_HASH_Marshal((TPMS_SCHEME_HASH*)(source), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +#endif // ALG_RSA + +// Table 2:160 - Definition of Types for ECC Signature Schemes +#if ALG_ECC +# if !USE_MARSHALING_DEFINES +TPM_RC +TPMS_SIG_SCHEME_ECDSA_Unmarshal( + TPMS_SIG_SCHEME_ECDSA* target, BYTE** buffer, INT32* size); +# else +# define TPMS_SIG_SCHEME_ECDSA_Unmarshal(target, buffer, size) \ + TPMS_SCHEME_HASH_Unmarshal((TPMS_SCHEME_HASH*)(target), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +# if !USE_MARSHALING_DEFINES +UINT16 +TPMS_SIG_SCHEME_ECDSA_Marshal( + TPMS_SIG_SCHEME_ECDSA* source, BYTE** buffer, INT32* size); +# else +# define TPMS_SIG_SCHEME_ECDSA_Marshal(source, buffer, size) \ + TPMS_SCHEME_HASH_Marshal((TPMS_SCHEME_HASH*)(source), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +# if !USE_MARSHALING_DEFINES +TPM_RC +TPMS_SIG_SCHEME_SM2_Unmarshal( + TPMS_SIG_SCHEME_SM2* target, BYTE** buffer, INT32* size); +# else +# define TPMS_SIG_SCHEME_SM2_Unmarshal(target, buffer, size) \ + TPMS_SCHEME_HASH_Unmarshal((TPMS_SCHEME_HASH*)(target), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +# if !USE_MARSHALING_DEFINES +UINT16 +TPMS_SIG_SCHEME_SM2_Marshal(TPMS_SIG_SCHEME_SM2* source, BYTE** buffer, INT32* size); +# else +# define TPMS_SIG_SCHEME_SM2_Marshal(source, buffer, size) \ + TPMS_SCHEME_HASH_Marshal((TPMS_SCHEME_HASH*)(source), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +# if !USE_MARSHALING_DEFINES +TPM_RC +TPMS_SIG_SCHEME_ECSCHNORR_Unmarshal( + TPMS_SIG_SCHEME_ECSCHNORR* target, BYTE** buffer, INT32* size); +# else +# define TPMS_SIG_SCHEME_ECSCHNORR_Unmarshal(target, buffer, size) \ + TPMS_SCHEME_HASH_Unmarshal((TPMS_SCHEME_HASH*)(target), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +# if !USE_MARSHALING_DEFINES +UINT16 +TPMS_SIG_SCHEME_ECSCHNORR_Marshal( + TPMS_SIG_SCHEME_ECSCHNORR* source, BYTE** buffer, INT32* size); +# else +# define TPMS_SIG_SCHEME_ECSCHNORR_Marshal(source, buffer, size) \ + TPMS_SCHEME_HASH_Marshal((TPMS_SCHEME_HASH*)(source), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +# if !USE_MARSHALING_DEFINES +TPM_RC +TPMS_SIG_SCHEME_ECDAA_Unmarshal( + TPMS_SIG_SCHEME_ECDAA* target, BYTE** buffer, INT32* size); +# else +# define TPMS_SIG_SCHEME_ECDAA_Unmarshal(target, buffer, size) \ + TPMS_SCHEME_ECDAA_Unmarshal((TPMS_SCHEME_ECDAA*)(target), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +# if !USE_MARSHALING_DEFINES +UINT16 +TPMS_SIG_SCHEME_ECDAA_Marshal( + TPMS_SIG_SCHEME_ECDAA* source, BYTE** buffer, INT32* size); +# else +# define TPMS_SIG_SCHEME_ECDAA_Marshal(source, buffer, size) \ + TPMS_SCHEME_ECDAA_Marshal((TPMS_SCHEME_ECDAA*)(source), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +#endif // ALG_ECC + +// Table 2:161 - Definition of TPMU_SIG_SCHEME Union +TPM_RC +TPMU_SIG_SCHEME_Unmarshal( + TPMU_SIG_SCHEME* target, BYTE** buffer, INT32* size, UINT32 selector); +UINT16 +TPMU_SIG_SCHEME_Marshal( + TPMU_SIG_SCHEME* source, BYTE** buffer, INT32* size, UINT32 selector); + +// Table 2:162 - Definition of TPMT_SIG_SCHEME Structure +TPM_RC +TPMT_SIG_SCHEME_Unmarshal( + TPMT_SIG_SCHEME* target, BYTE** buffer, INT32* size, BOOL flag); +UINT16 +TPMT_SIG_SCHEME_Marshal(TPMT_SIG_SCHEME* source, BYTE** buffer, INT32* size); + +// Table 2:163 - Definition of Types for Encryption Schemes +#if ALG_RSA +# if !USE_MARSHALING_DEFINES +TPM_RC +TPMS_ENC_SCHEME_OAEP_Unmarshal( + TPMS_ENC_SCHEME_OAEP* target, BYTE** buffer, INT32* size); +# else +# define TPMS_ENC_SCHEME_OAEP_Unmarshal(target, buffer, size) \ + TPMS_SCHEME_HASH_Unmarshal((TPMS_SCHEME_HASH*)(target), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +# if !USE_MARSHALING_DEFINES +UINT16 +TPMS_ENC_SCHEME_OAEP_Marshal( + TPMS_ENC_SCHEME_OAEP* source, BYTE** buffer, INT32* size); +# else +# define TPMS_ENC_SCHEME_OAEP_Marshal(source, buffer, size) \ + TPMS_SCHEME_HASH_Marshal((TPMS_SCHEME_HASH*)(source), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +# if !USE_MARSHALING_DEFINES +TPM_RC +TPMS_ENC_SCHEME_RSAES_Unmarshal( + TPMS_ENC_SCHEME_RSAES* target, BYTE** buffer, INT32* size); +# else +# define TPMS_ENC_SCHEME_RSAES_Unmarshal(target, buffer, size) \ + TPMS_EMPTY_Unmarshal((TPMS_EMPTY*)(target), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +# if !USE_MARSHALING_DEFINES +UINT16 +TPMS_ENC_SCHEME_RSAES_Marshal( + TPMS_ENC_SCHEME_RSAES* source, BYTE** buffer, INT32* size); +# else +# define TPMS_ENC_SCHEME_RSAES_Marshal(source, buffer, size) \ + TPMS_EMPTY_Marshal((TPMS_EMPTY*)(source), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +#endif // ALG_RSA + +// Table 2:164 - Definition of Types for ECC Key Exchange +#if ALG_ECC +# if !USE_MARSHALING_DEFINES +TPM_RC +TPMS_KEY_SCHEME_ECDH_Unmarshal( + TPMS_KEY_SCHEME_ECDH* target, BYTE** buffer, INT32* size); +# else +# define TPMS_KEY_SCHEME_ECDH_Unmarshal(target, buffer, size) \ + TPMS_SCHEME_HASH_Unmarshal((TPMS_SCHEME_HASH*)(target), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +# if !USE_MARSHALING_DEFINES +UINT16 +TPMS_KEY_SCHEME_ECDH_Marshal( + TPMS_KEY_SCHEME_ECDH* source, BYTE** buffer, INT32* size); +# else +# define TPMS_KEY_SCHEME_ECDH_Marshal(source, buffer, size) \ + TPMS_SCHEME_HASH_Marshal((TPMS_SCHEME_HASH*)(source), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +# if !USE_MARSHALING_DEFINES +TPM_RC +TPMS_KEY_SCHEME_ECMQV_Unmarshal( + TPMS_KEY_SCHEME_ECMQV* target, BYTE** buffer, INT32* size); +# else +# define TPMS_KEY_SCHEME_ECMQV_Unmarshal(target, buffer, size) \ + TPMS_SCHEME_HASH_Unmarshal((TPMS_SCHEME_HASH*)(target), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +# if !USE_MARSHALING_DEFINES +UINT16 +TPMS_KEY_SCHEME_ECMQV_Marshal( + TPMS_KEY_SCHEME_ECMQV* source, BYTE** buffer, INT32* size); +# else +# define TPMS_KEY_SCHEME_ECMQV_Marshal(source, buffer, size) \ + TPMS_SCHEME_HASH_Marshal((TPMS_SCHEME_HASH*)(source), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +#endif // ALG_ECC + +// Table 2:165 - Definition of Types for KDF Schemes +#if !USE_MARSHALING_DEFINES +TPM_RC +TPMS_KDF_SCHEME_MGF1_Unmarshal( + TPMS_KDF_SCHEME_MGF1* target, BYTE** buffer, INT32* size); +#else +# define TPMS_KDF_SCHEME_MGF1_Unmarshal(target, buffer, size) \ + TPMS_SCHEME_HASH_Unmarshal((TPMS_SCHEME_HASH*)(target), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES +#if !USE_MARSHALING_DEFINES +UINT16 +TPMS_KDF_SCHEME_MGF1_Marshal( + TPMS_KDF_SCHEME_MGF1* source, BYTE** buffer, INT32* size); +#else +# define TPMS_KDF_SCHEME_MGF1_Marshal(source, buffer, size) \ + TPMS_SCHEME_HASH_Marshal((TPMS_SCHEME_HASH*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES +#if !USE_MARSHALING_DEFINES +TPM_RC +TPMS_KDF_SCHEME_KDF1_SP800_56A_Unmarshal( + TPMS_KDF_SCHEME_KDF1_SP800_56A* target, BYTE** buffer, INT32* size); +#else +# define TPMS_KDF_SCHEME_KDF1_SP800_56A_Unmarshal(target, buffer, size) \ + TPMS_SCHEME_HASH_Unmarshal((TPMS_SCHEME_HASH*)(target), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES +#if !USE_MARSHALING_DEFINES +UINT16 +TPMS_KDF_SCHEME_KDF1_SP800_56A_Marshal( + TPMS_KDF_SCHEME_KDF1_SP800_56A* source, BYTE** buffer, INT32* size); +#else +# define TPMS_KDF_SCHEME_KDF1_SP800_56A_Marshal(source, buffer, size) \ + TPMS_SCHEME_HASH_Marshal((TPMS_SCHEME_HASH*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES +#if !USE_MARSHALING_DEFINES +TPM_RC +TPMS_KDF_SCHEME_KDF2_Unmarshal( + TPMS_KDF_SCHEME_KDF2* target, BYTE** buffer, INT32* size); +#else +# define TPMS_KDF_SCHEME_KDF2_Unmarshal(target, buffer, size) \ + TPMS_SCHEME_HASH_Unmarshal((TPMS_SCHEME_HASH*)(target), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES +#if !USE_MARSHALING_DEFINES +UINT16 +TPMS_KDF_SCHEME_KDF2_Marshal( + TPMS_KDF_SCHEME_KDF2* source, BYTE** buffer, INT32* size); +#else +# define TPMS_KDF_SCHEME_KDF2_Marshal(source, buffer, size) \ + TPMS_SCHEME_HASH_Marshal((TPMS_SCHEME_HASH*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES +#if !USE_MARSHALING_DEFINES +TPM_RC +TPMS_KDF_SCHEME_KDF1_SP800_108_Unmarshal( + TPMS_KDF_SCHEME_KDF1_SP800_108* target, BYTE** buffer, INT32* size); +#else +# define TPMS_KDF_SCHEME_KDF1_SP800_108_Unmarshal(target, buffer, size) \ + TPMS_SCHEME_HASH_Unmarshal((TPMS_SCHEME_HASH*)(target), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES +#if !USE_MARSHALING_DEFINES +UINT16 +TPMS_KDF_SCHEME_KDF1_SP800_108_Marshal( + TPMS_KDF_SCHEME_KDF1_SP800_108* source, BYTE** buffer, INT32* size); +#else +# define TPMS_KDF_SCHEME_KDF1_SP800_108_Marshal(source, buffer, size) \ + TPMS_SCHEME_HASH_Marshal((TPMS_SCHEME_HASH*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:166 - Definition of TPMU_KDF_SCHEME Union +TPM_RC +TPMU_KDF_SCHEME_Unmarshal( + TPMU_KDF_SCHEME* target, BYTE** buffer, INT32* size, UINT32 selector); +UINT16 +TPMU_KDF_SCHEME_Marshal( + TPMU_KDF_SCHEME* source, BYTE** buffer, INT32* size, UINT32 selector); + +// Table 2:167 - Definition of TPMT_KDF_SCHEME Structure +TPM_RC +TPMT_KDF_SCHEME_Unmarshal( + TPMT_KDF_SCHEME* target, BYTE** buffer, INT32* size, BOOL flag); +UINT16 +TPMT_KDF_SCHEME_Marshal(TPMT_KDF_SCHEME* source, BYTE** buffer, INT32* size); + +// Table 2:168 - Definition of TPMI_ALG_ASYM_SCHEME Type +TPM_RC +TPMI_ALG_ASYM_SCHEME_Unmarshal( + TPMI_ALG_ASYM_SCHEME* target, BYTE** buffer, INT32* size, BOOL flag); +#if !USE_MARSHALING_DEFINES +UINT16 +TPMI_ALG_ASYM_SCHEME_Marshal( + TPMI_ALG_ASYM_SCHEME* source, BYTE** buffer, INT32* size); +#else +# define TPMI_ALG_ASYM_SCHEME_Marshal(source, buffer, size) \ + TPM_ALG_ID_Marshal((TPM_ALG_ID*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:169 - Definition of TPMU_ASYM_SCHEME Union +TPM_RC +TPMU_ASYM_SCHEME_Unmarshal( + TPMU_ASYM_SCHEME* target, BYTE** buffer, INT32* size, UINT32 selector); +UINT16 +TPMU_ASYM_SCHEME_Marshal( + TPMU_ASYM_SCHEME* source, BYTE** buffer, INT32* size, UINT32 selector); + +// Table 2:170 - Definition of TPMT_ASYM_SCHEME Structure +// Table 2:171 - Definition of TPMI_ALG_RSA_SCHEME Type +#if ALG_RSA +TPM_RC +TPMI_ALG_RSA_SCHEME_Unmarshal( + TPMI_ALG_RSA_SCHEME* target, BYTE** buffer, INT32* size, BOOL flag); +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_ALG_RSA_SCHEME_Marshal(TPMI_ALG_RSA_SCHEME* source, BYTE** buffer, INT32* size); +# else +# define TPMI_ALG_RSA_SCHEME_Marshal(source, buffer, size) \ + TPM_ALG_ID_Marshal((TPM_ALG_ID*)(source), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +#endif // ALG_RSA + +// Table 2:172 - Definition of TPMT_RSA_SCHEME Structure +#if ALG_RSA +TPM_RC +TPMT_RSA_SCHEME_Unmarshal( + TPMT_RSA_SCHEME* target, BYTE** buffer, INT32* size, BOOL flag); +UINT16 +TPMT_RSA_SCHEME_Marshal(TPMT_RSA_SCHEME* source, BYTE** buffer, INT32* size); +#endif // ALG_RSA + +// Table 2:173 - Definition of TPMI_ALG_RSA_DECRYPT Type +#if ALG_RSA +TPM_RC +TPMI_ALG_RSA_DECRYPT_Unmarshal( + TPMI_ALG_RSA_DECRYPT* target, BYTE** buffer, INT32* size, BOOL flag); +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_ALG_RSA_DECRYPT_Marshal( + TPMI_ALG_RSA_DECRYPT* source, BYTE** buffer, INT32* size); +# else +# define TPMI_ALG_RSA_DECRYPT_Marshal(source, buffer, size) \ + TPM_ALG_ID_Marshal((TPM_ALG_ID*)(source), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +#endif // ALG_RSA + +// Table 2:174 - Definition of TPMT_RSA_DECRYPT Structure +#if ALG_RSA +TPM_RC +TPMT_RSA_DECRYPT_Unmarshal( + TPMT_RSA_DECRYPT* target, BYTE** buffer, INT32* size, BOOL flag); +UINT16 +TPMT_RSA_DECRYPT_Marshal(TPMT_RSA_DECRYPT* source, BYTE** buffer, INT32* size); +#endif // ALG_RSA + +// Table 2:175 - Definition of TPM2B_PUBLIC_KEY_RSA Structure +#if ALG_RSA +TPM_RC +TPM2B_PUBLIC_KEY_RSA_Unmarshal( + TPM2B_PUBLIC_KEY_RSA* target, BYTE** buffer, INT32* size); +UINT16 +TPM2B_PUBLIC_KEY_RSA_Marshal( + TPM2B_PUBLIC_KEY_RSA* source, BYTE** buffer, INT32* size); +#endif // ALG_RSA + +// Table 2:176 - Definition of TPMI_RSA_KEY_BITS Type +#if ALG_RSA +TPM_RC +TPMI_RSA_KEY_BITS_Unmarshal(TPMI_RSA_KEY_BITS* target, BYTE** buffer, INT32* size); +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_RSA_KEY_BITS_Marshal(TPMI_RSA_KEY_BITS* source, BYTE** buffer, INT32* size); +# else +# define TPMI_RSA_KEY_BITS_Marshal(source, buffer, size) \ + TPM_KEY_BITS_Marshal((TPM_KEY_BITS*)(source), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +#endif // ALG_RSA + +// Table 2:177 - Definition of TPM2B_PRIVATE_KEY_RSA Structure +#if ALG_RSA +TPM_RC +TPM2B_PRIVATE_KEY_RSA_Unmarshal( + TPM2B_PRIVATE_KEY_RSA* target, BYTE** buffer, INT32* size); +UINT16 +TPM2B_PRIVATE_KEY_RSA_Marshal( + TPM2B_PRIVATE_KEY_RSA* source, BYTE** buffer, INT32* size); +#endif // ALG_RSA + +// Table 2:178 - Definition of TPM2B_ECC_PARAMETER Structure +TPM_RC +TPM2B_ECC_PARAMETER_Unmarshal( + TPM2B_ECC_PARAMETER* target, BYTE** buffer, INT32* size); +UINT16 +TPM2B_ECC_PARAMETER_Marshal(TPM2B_ECC_PARAMETER* source, BYTE** buffer, INT32* size); + +// Table 2:179 - Definition of TPMS_ECC_POINT Structure +#if ALG_ECC +TPM_RC +TPMS_ECC_POINT_Unmarshal(TPMS_ECC_POINT* target, BYTE** buffer, INT32* size); +UINT16 +TPMS_ECC_POINT_Marshal(TPMS_ECC_POINT* source, BYTE** buffer, INT32* size); +#endif // ALG_ECC + +// Table 2:180 - Definition of TPM2B_ECC_POINT Structure +#if ALG_ECC +TPM_RC +TPM2B_ECC_POINT_Unmarshal(TPM2B_ECC_POINT* target, BYTE** buffer, INT32* size); +UINT16 +TPM2B_ECC_POINT_Marshal(TPM2B_ECC_POINT* source, BYTE** buffer, INT32* size); +#endif // ALG_ECC + +// Table 2:181 - Definition of TPMI_ALG_ECC_SCHEME Type +#if ALG_ECC +TPM_RC +TPMI_ALG_ECC_SCHEME_Unmarshal( + TPMI_ALG_ECC_SCHEME* target, BYTE** buffer, INT32* size, BOOL flag); +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_ALG_ECC_SCHEME_Marshal(TPMI_ALG_ECC_SCHEME* source, BYTE** buffer, INT32* size); +# else +# define TPMI_ALG_ECC_SCHEME_Marshal(source, buffer, size) \ + TPM_ALG_ID_Marshal((TPM_ALG_ID*)(source), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +#endif // ALG_ECC + +// Table 2:182 - Definition of TPMI_ECC_CURVE Type +#if ALG_ECC +TPM_RC +TPMI_ECC_CURVE_Unmarshal(TPMI_ECC_CURVE* target, BYTE** buffer, INT32* size); +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_ECC_CURVE_Marshal(TPMI_ECC_CURVE* source, BYTE** buffer, INT32* size); +# else +# define TPMI_ECC_CURVE_Marshal(source, buffer, size) \ + TPM_ECC_CURVE_Marshal((TPM_ECC_CURVE*)(source), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +#endif // ALG_ECC + +// Table 2:183 - Definition of TPMT_ECC_SCHEME Structure +#if ALG_ECC +TPM_RC +TPMT_ECC_SCHEME_Unmarshal( + TPMT_ECC_SCHEME* target, BYTE** buffer, INT32* size, BOOL flag); +UINT16 +TPMT_ECC_SCHEME_Marshal(TPMT_ECC_SCHEME* source, BYTE** buffer, INT32* size); +#endif // ALG_ECC + +// Table 2:184 - Definition of TPMS_ALGORITHM_DETAIL_ECC Structure +#if ALG_ECC +UINT16 +TPMS_ALGORITHM_DETAIL_ECC_Marshal( + TPMS_ALGORITHM_DETAIL_ECC* source, BYTE** buffer, INT32* size); +#endif // ALG_ECC + +// Table 2:185 - Definition of TPMS_SIGNATURE_RSA Structure +#if ALG_RSA +TPM_RC +TPMS_SIGNATURE_RSA_Unmarshal(TPMS_SIGNATURE_RSA* target, BYTE** buffer, INT32* size); +UINT16 +TPMS_SIGNATURE_RSA_Marshal(TPMS_SIGNATURE_RSA* source, BYTE** buffer, INT32* size); +#endif // ALG_RSA + +// Table 2:186 - Definition of Types for Signature +#if ALG_RSA +# if !USE_MARSHALING_DEFINES +TPM_RC +TPMS_SIGNATURE_RSASSA_Unmarshal( + TPMS_SIGNATURE_RSASSA* target, BYTE** buffer, INT32* size); +# else +# define TPMS_SIGNATURE_RSASSA_Unmarshal(target, buffer, size) \ + TPMS_SIGNATURE_RSA_Unmarshal((TPMS_SIGNATURE_RSA*)(target), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +# if !USE_MARSHALING_DEFINES +UINT16 +TPMS_SIGNATURE_RSASSA_Marshal( + TPMS_SIGNATURE_RSASSA* source, BYTE** buffer, INT32* size); +# else +# define TPMS_SIGNATURE_RSASSA_Marshal(source, buffer, size) \ + TPMS_SIGNATURE_RSA_Marshal((TPMS_SIGNATURE_RSA*)(source), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +# if !USE_MARSHALING_DEFINES +TPM_RC +TPMS_SIGNATURE_RSAPSS_Unmarshal( + TPMS_SIGNATURE_RSAPSS* target, BYTE** buffer, INT32* size); +# else +# define TPMS_SIGNATURE_RSAPSS_Unmarshal(target, buffer, size) \ + TPMS_SIGNATURE_RSA_Unmarshal((TPMS_SIGNATURE_RSA*)(target), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +# if !USE_MARSHALING_DEFINES +UINT16 +TPMS_SIGNATURE_RSAPSS_Marshal( + TPMS_SIGNATURE_RSAPSS* source, BYTE** buffer, INT32* size); +# else +# define TPMS_SIGNATURE_RSAPSS_Marshal(source, buffer, size) \ + TPMS_SIGNATURE_RSA_Marshal((TPMS_SIGNATURE_RSA*)(source), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +#endif // ALG_RSA + +// Table 2:187 - Definition of TPMS_SIGNATURE_ECC Structure +#if ALG_ECC +TPM_RC +TPMS_SIGNATURE_ECC_Unmarshal(TPMS_SIGNATURE_ECC* target, BYTE** buffer, INT32* size); +UINT16 +TPMS_SIGNATURE_ECC_Marshal(TPMS_SIGNATURE_ECC* source, BYTE** buffer, INT32* size); +#endif // ALG_ECC + +// Table 2:188 - Definition of Types for TPMS_SIGNATURE_ECC +#if ALG_ECC +# if !USE_MARSHALING_DEFINES +TPM_RC +TPMS_SIGNATURE_ECDAA_Unmarshal( + TPMS_SIGNATURE_ECDAA* target, BYTE** buffer, INT32* size); +# else +# define TPMS_SIGNATURE_ECDAA_Unmarshal(target, buffer, size) \ + TPMS_SIGNATURE_ECC_Unmarshal((TPMS_SIGNATURE_ECC*)(target), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +# if !USE_MARSHALING_DEFINES +UINT16 +TPMS_SIGNATURE_ECDAA_Marshal( + TPMS_SIGNATURE_ECDAA* source, BYTE** buffer, INT32* size); +# else +# define TPMS_SIGNATURE_ECDAA_Marshal(source, buffer, size) \ + TPMS_SIGNATURE_ECC_Marshal((TPMS_SIGNATURE_ECC*)(source), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +# if !USE_MARSHALING_DEFINES +TPM_RC +TPMS_SIGNATURE_ECDSA_Unmarshal( + TPMS_SIGNATURE_ECDSA* target, BYTE** buffer, INT32* size); +# else +# define TPMS_SIGNATURE_ECDSA_Unmarshal(target, buffer, size) \ + TPMS_SIGNATURE_ECC_Unmarshal((TPMS_SIGNATURE_ECC*)(target), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +# if !USE_MARSHALING_DEFINES +UINT16 +TPMS_SIGNATURE_ECDSA_Marshal( + TPMS_SIGNATURE_ECDSA* source, BYTE** buffer, INT32* size); +# else +# define TPMS_SIGNATURE_ECDSA_Marshal(source, buffer, size) \ + TPMS_SIGNATURE_ECC_Marshal((TPMS_SIGNATURE_ECC*)(source), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +# if !USE_MARSHALING_DEFINES +TPM_RC +TPMS_SIGNATURE_SM2_Unmarshal(TPMS_SIGNATURE_SM2* target, BYTE** buffer, INT32* size); +# else +# define TPMS_SIGNATURE_SM2_Unmarshal(target, buffer, size) \ + TPMS_SIGNATURE_ECC_Unmarshal((TPMS_SIGNATURE_ECC*)(target), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +# if !USE_MARSHALING_DEFINES +UINT16 +TPMS_SIGNATURE_SM2_Marshal(TPMS_SIGNATURE_SM2* source, BYTE** buffer, INT32* size); +# else +# define TPMS_SIGNATURE_SM2_Marshal(source, buffer, size) \ + TPMS_SIGNATURE_ECC_Marshal((TPMS_SIGNATURE_ECC*)(source), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +# if !USE_MARSHALING_DEFINES +TPM_RC +TPMS_SIGNATURE_ECSCHNORR_Unmarshal( + TPMS_SIGNATURE_ECSCHNORR* target, BYTE** buffer, INT32* size); +# else +# define TPMS_SIGNATURE_ECSCHNORR_Unmarshal(target, buffer, size) \ + TPMS_SIGNATURE_ECC_Unmarshal((TPMS_SIGNATURE_ECC*)(target), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +# if !USE_MARSHALING_DEFINES +UINT16 +TPMS_SIGNATURE_ECSCHNORR_Marshal( + TPMS_SIGNATURE_ECSCHNORR* source, BYTE** buffer, INT32* size); +# else +# define TPMS_SIGNATURE_ECSCHNORR_Marshal(source, buffer, size) \ + TPMS_SIGNATURE_ECC_Marshal((TPMS_SIGNATURE_ECC*)(source), (buffer), (size)) +# endif // !USE_MARSHALING_DEFINES +#endif // ALG_ECC + +// Table 2:189 - Definition of TPMU_SIGNATURE Union +TPM_RC +TPMU_SIGNATURE_Unmarshal( + TPMU_SIGNATURE* target, BYTE** buffer, INT32* size, UINT32 selector); +UINT16 +TPMU_SIGNATURE_Marshal( + TPMU_SIGNATURE* source, BYTE** buffer, INT32* size, UINT32 selector); + +// Table 2:190 - Definition of TPMT_SIGNATURE Structure +TPM_RC +TPMT_SIGNATURE_Unmarshal( + TPMT_SIGNATURE* target, BYTE** buffer, INT32* size, BOOL flag); +UINT16 +TPMT_SIGNATURE_Marshal(TPMT_SIGNATURE* source, BYTE** buffer, INT32* size); + +// Table 2:191 - Definition of TPMU_ENCRYPTED_SECRET Union +TPM_RC +TPMU_ENCRYPTED_SECRET_Unmarshal( + TPMU_ENCRYPTED_SECRET* target, BYTE** buffer, INT32* size, UINT32 selector); +UINT16 +TPMU_ENCRYPTED_SECRET_Marshal( + TPMU_ENCRYPTED_SECRET* source, BYTE** buffer, INT32* size, UINT32 selector); + +// Table 2:192 - Definition of TPM2B_ENCRYPTED_SECRET Structure +TPM_RC +TPM2B_ENCRYPTED_SECRET_Unmarshal( + TPM2B_ENCRYPTED_SECRET* target, BYTE** buffer, INT32* size); +UINT16 +TPM2B_ENCRYPTED_SECRET_Marshal( + TPM2B_ENCRYPTED_SECRET* source, BYTE** buffer, INT32* size); + +// Table 2:193 - Definition of TPMI_ALG_PUBLIC Type +TPM_RC +TPMI_ALG_PUBLIC_Unmarshal(TPMI_ALG_PUBLIC* target, BYTE** buffer, INT32* size); +#if !USE_MARSHALING_DEFINES +UINT16 +TPMI_ALG_PUBLIC_Marshal(TPMI_ALG_PUBLIC* source, BYTE** buffer, INT32* size); +#else +# define TPMI_ALG_PUBLIC_Marshal(source, buffer, size) \ + TPM_ALG_ID_Marshal((TPM_ALG_ID*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:194 - Definition of TPMU_PUBLIC_ID Union +TPM_RC +TPMU_PUBLIC_ID_Unmarshal( + TPMU_PUBLIC_ID* target, BYTE** buffer, INT32* size, UINT32 selector); +UINT16 +TPMU_PUBLIC_ID_Marshal( + TPMU_PUBLIC_ID* source, BYTE** buffer, INT32* size, UINT32 selector); + +// Table 2:195 - Definition of TPMS_KEYEDHASH_PARMS Structure +TPM_RC +TPMS_KEYEDHASH_PARMS_Unmarshal( + TPMS_KEYEDHASH_PARMS* target, BYTE** buffer, INT32* size); +UINT16 +TPMS_KEYEDHASH_PARMS_Marshal( + TPMS_KEYEDHASH_PARMS* source, BYTE** buffer, INT32* size); + +// Table 2:196 - Definition of TPMS_ASYM_PARMS Structure +// Table 2:197 - Definition of TPMS_RSA_PARMS Structure +#if ALG_RSA +TPM_RC +TPMS_RSA_PARMS_Unmarshal(TPMS_RSA_PARMS* target, BYTE** buffer, INT32* size); +UINT16 +TPMS_RSA_PARMS_Marshal(TPMS_RSA_PARMS* source, BYTE** buffer, INT32* size); +#endif // ALG_RSA + +// Table 2:198 - Definition of TPMS_ECC_PARMS Structure +#if ALG_ECC +TPM_RC +TPMS_ECC_PARMS_Unmarshal(TPMS_ECC_PARMS* target, BYTE** buffer, INT32* size); +UINT16 +TPMS_ECC_PARMS_Marshal(TPMS_ECC_PARMS* source, BYTE** buffer, INT32* size); +#endif // ALG_ECC + +// Table 2:199 - Definition of TPMU_PUBLIC_PARMS Union +TPM_RC +TPMU_PUBLIC_PARMS_Unmarshal( + TPMU_PUBLIC_PARMS* target, BYTE** buffer, INT32* size, UINT32 selector); +UINT16 +TPMU_PUBLIC_PARMS_Marshal( + TPMU_PUBLIC_PARMS* source, BYTE** buffer, INT32* size, UINT32 selector); + +// Table 2:200 - Definition of TPMT_PUBLIC_PARMS Structure +TPM_RC +TPMT_PUBLIC_PARMS_Unmarshal(TPMT_PUBLIC_PARMS* target, BYTE** buffer, INT32* size); +UINT16 +TPMT_PUBLIC_PARMS_Marshal(TPMT_PUBLIC_PARMS* source, BYTE** buffer, INT32* size); + +// Table 2:201 - Definition of TPMT_PUBLIC Structure +TPM_RC +TPMT_PUBLIC_Unmarshal(TPMT_PUBLIC* target, BYTE** buffer, INT32* size, BOOL flag); +UINT16 +TPMT_PUBLIC_Marshal(TPMT_PUBLIC* source, BYTE** buffer, INT32* size); + +// Table 2:202 - Definition of TPM2B_PUBLIC Structure +TPM_RC +TPM2B_PUBLIC_Unmarshal(TPM2B_PUBLIC* target, BYTE** buffer, INT32* size, BOOL flag); +UINT16 +TPM2B_PUBLIC_Marshal(TPM2B_PUBLIC* source, BYTE** buffer, INT32* size); + +// Table 2:203 - Definition of TPM2B_TEMPLATE Structure +TPM_RC +TPM2B_TEMPLATE_Unmarshal(TPM2B_TEMPLATE* target, BYTE** buffer, INT32* size); +UINT16 +TPM2B_TEMPLATE_Marshal(TPM2B_TEMPLATE* source, BYTE** buffer, INT32* size); + +// Table 2:204 - Definition of TPM2B_PRIVATE_VENDOR_SPECIFIC Structure +TPM_RC +TPM2B_PRIVATE_VENDOR_SPECIFIC_Unmarshal( + TPM2B_PRIVATE_VENDOR_SPECIFIC* target, BYTE** buffer, INT32* size); +UINT16 +TPM2B_PRIVATE_VENDOR_SPECIFIC_Marshal( + TPM2B_PRIVATE_VENDOR_SPECIFIC* source, BYTE** buffer, INT32* size); + +// Table 2:205 - Definition of TPMU_SENSITIVE_COMPOSITE Union +TPM_RC +TPMU_SENSITIVE_COMPOSITE_Unmarshal( + TPMU_SENSITIVE_COMPOSITE* target, BYTE** buffer, INT32* size, UINT32 selector); +UINT16 +TPMU_SENSITIVE_COMPOSITE_Marshal( + TPMU_SENSITIVE_COMPOSITE* source, BYTE** buffer, INT32* size, UINT32 selector); + +// Table 2:206 - Definition of TPMT_SENSITIVE Structure +TPM_RC +TPMT_SENSITIVE_Unmarshal(TPMT_SENSITIVE* target, BYTE** buffer, INT32* size); +UINT16 +TPMT_SENSITIVE_Marshal(TPMT_SENSITIVE* source, BYTE** buffer, INT32* size); + +// Table 2:207 - Definition of TPM2B_SENSITIVE Structure +TPM_RC +TPM2B_SENSITIVE_Unmarshal(TPM2B_SENSITIVE* target, BYTE** buffer, INT32* size); +UINT16 +TPM2B_SENSITIVE_Marshal(TPM2B_SENSITIVE* source, BYTE** buffer, INT32* size); + +// Table 2:208 - Definition of _PRIVATE Structure +// Table 2:209 - Definition of TPM2B_PRIVATE Structure +TPM_RC +TPM2B_PRIVATE_Unmarshal(TPM2B_PRIVATE* target, BYTE** buffer, INT32* size); +UINT16 +TPM2B_PRIVATE_Marshal(TPM2B_PRIVATE* source, BYTE** buffer, INT32* size); + +// Table 2:210 - Definition of TPMS_ID_OBJECT Structure +// Table 2:211 - Definition of TPM2B_ID_OBJECT Structure +TPM_RC +TPM2B_ID_OBJECT_Unmarshal(TPM2B_ID_OBJECT* target, BYTE** buffer, INT32* size); +UINT16 +TPM2B_ID_OBJECT_Marshal(TPM2B_ID_OBJECT* source, BYTE** buffer, INT32* size); + +// Table 2:212 - Definition of TPM_NV_INDEX Bits +#if !USE_MARSHALING_DEFINES +UINT16 +TPM_NV_INDEX_Marshal(TPM_NV_INDEX* source, BYTE** buffer, INT32* size); +#else +# define TPM_NV_INDEX_Marshal(source, buffer, size) \ + UINT32_Marshal((UINT32*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:213 - Definition of TPM_NT Constants +// Table 2:214 - Definition of TPMS_NV_PIN_COUNTER_PARAMETERS Structure +TPM_RC +TPMS_NV_PIN_COUNTER_PARAMETERS_Unmarshal( + TPMS_NV_PIN_COUNTER_PARAMETERS* target, BYTE** buffer, INT32* size); +UINT16 +TPMS_NV_PIN_COUNTER_PARAMETERS_Marshal( + TPMS_NV_PIN_COUNTER_PARAMETERS* source, BYTE** buffer, INT32* size); + +// Table 2:215 - Definition of TPMA_NV Bits +TPM_RC +TPMA_NV_Unmarshal(TPMA_NV* target, BYTE** buffer, INT32* size); + +#if !USE_MARSHALING_DEFINES +UINT16 +TPMA_NV_Marshal(TPMA_NV* source, BYTE** buffer, INT32* size); +#else +# define TPMA_NV_Marshal(source, buffer, size) \ + UINT32_Marshal((UINT32*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:216 - Definition of TPMS_NV_PUBLIC Structure +TPM_RC +TPMS_NV_PUBLIC_Unmarshal(TPMS_NV_PUBLIC* target, BYTE** buffer, INT32* size); +UINT16 +TPMS_NV_PUBLIC_Marshal(TPMS_NV_PUBLIC* source, BYTE** buffer, INT32* size); + +// Table 2:217 - Definition of TPM2B_NV_PUBLIC Structure +TPM_RC +TPM2B_NV_PUBLIC_Unmarshal(TPM2B_NV_PUBLIC* target, BYTE** buffer, INT32* size); +UINT16 +TPM2B_NV_PUBLIC_Marshal(TPM2B_NV_PUBLIC* source, BYTE** buffer, INT32* size); + +// Table 2:218 - Definition of TPM2B_CONTEXT_SENSITIVE Structure +TPM_RC +TPM2B_CONTEXT_SENSITIVE_Unmarshal( + TPM2B_CONTEXT_SENSITIVE* target, BYTE** buffer, INT32* size); +UINT16 +TPM2B_CONTEXT_SENSITIVE_Marshal( + TPM2B_CONTEXT_SENSITIVE* source, BYTE** buffer, INT32* size); + +// Table 2:219 - Definition of TPMS_CONTEXT_DATA Structure +TPM_RC +TPMS_CONTEXT_DATA_Unmarshal(TPMS_CONTEXT_DATA* target, BYTE** buffer, INT32* size); +UINT16 +TPMS_CONTEXT_DATA_Marshal(TPMS_CONTEXT_DATA* source, BYTE** buffer, INT32* size); + +// Table 2:220 - Definition of TPM2B_CONTEXT_DATA Structure +TPM_RC +TPM2B_CONTEXT_DATA_Unmarshal(TPM2B_CONTEXT_DATA* target, BYTE** buffer, INT32* size); +UINT16 +TPM2B_CONTEXT_DATA_Marshal(TPM2B_CONTEXT_DATA* source, BYTE** buffer, INT32* size); + +// Table 2:221 - Definition of TPMS_CONTEXT Structure +TPM_RC +TPMS_CONTEXT_Unmarshal(TPMS_CONTEXT* target, BYTE** buffer, INT32* size); +UINT16 +TPMS_CONTEXT_Marshal(TPMS_CONTEXT* source, BYTE** buffer, INT32* size); + +// Table 2:223 - Definition of TPMS_CREATION_DATA Structure +UINT16 +TPMS_CREATION_DATA_Marshal(TPMS_CREATION_DATA* source, BYTE** buffer, INT32* size); + +// Table 2:224 - Definition of TPM2B_CREATION_DATA Structure +UINT16 +TPM2B_CREATION_DATA_Marshal(TPM2B_CREATION_DATA* source, BYTE** buffer, INT32* size); + +// Table 2:225 - Definition of TPM_AT Constants +TPM_RC +TPM_AT_Unmarshal(TPM_AT* target, BYTE** buffer, INT32* size); +#if !USE_MARSHALING_DEFINES +UINT16 +TPM_AT_Marshal(TPM_AT* source, BYTE** buffer, INT32* size); +#else +# define TPM_AT_Marshal(source, buffer, size) \ + UINT32_Marshal((UINT32*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:226 - Definition of TPM_AE Constants +#if !USE_MARSHALING_DEFINES +UINT16 +TPM_AE_Marshal(TPM_AE* source, BYTE** buffer, INT32* size); +#else +# define TPM_AE_Marshal(source, buffer, size) \ + UINT32_Marshal((UINT32*)(source), (buffer), (size)) +#endif // !USE_MARSHALING_DEFINES + +// Table 2:227 - Definition of TPMS_AC_OUTPUT Structure +UINT16 +TPMS_AC_OUTPUT_Marshal(TPMS_AC_OUTPUT* source, BYTE** buffer, INT32* size); + +// Table 2:228 - Definition of TPML_AC_CAPABILITIES Structure +UINT16 +TPML_AC_CAPABILITIES_Marshal( + TPML_AC_CAPABILITIES* source, BYTE** buffer, INT32* size); + +// Array Marshal/Unmarshal for BYTE +TPM_RC +BYTE_Array_Unmarshal(BYTE* target, BYTE** buffer, INT32* size, INT32 count); +UINT16 +BYTE_Array_Marshal(BYTE* source, BYTE** buffer, INT32* size, INT32 count); + +// Array Marshal/Unmarshal for TPM2B_DIGEST +TPM_RC +TPM2B_DIGEST_Array_Unmarshal( + TPM2B_DIGEST* target, BYTE** buffer, INT32* size, INT32 count); +UINT16 +TPM2B_DIGEST_Array_Marshal( + TPM2B_DIGEST* source, BYTE** buffer, INT32* size, INT32 count); + +// Array Marshal for TPMA_CC +UINT16 +TPMA_CC_Array_Marshal(TPMA_CC* source, BYTE** buffer, INT32* size, INT32 count); + +// Array Marshal for TPMS_ACT_DATA +UINT16 +TPMS_ACT_DATA_Array_Marshal( + TPMS_ACT_DATA* source, BYTE** buffer, INT32* size, INT32 count); + +// Array Marshal for TPMS_AC_OUTPUT +UINT16 +TPMS_AC_OUTPUT_Array_Marshal( + TPMS_AC_OUTPUT* source, BYTE** buffer, INT32* size, INT32 count); + +// Array Marshal for TPMS_ALG_PROPERTY +UINT16 +TPMS_ALG_PROPERTY_Array_Marshal( + TPMS_ALG_PROPERTY* source, BYTE** buffer, INT32* size, INT32 count); + +// Array Marshal/Unmarshal for TPMS_PCR_SELECTION +TPM_RC +TPMS_PCR_SELECTION_Array_Unmarshal( + TPMS_PCR_SELECTION* target, BYTE** buffer, INT32* size, INT32 count); +UINT16 +TPMS_PCR_SELECTION_Array_Marshal( + TPMS_PCR_SELECTION* source, BYTE** buffer, INT32* size, INT32 count); + +// Array Marshal for TPMS_TAGGED_PCR_SELECT +UINT16 +TPMS_TAGGED_PCR_SELECT_Array_Marshal( + TPMS_TAGGED_PCR_SELECT* source, BYTE** buffer, INT32* size, INT32 count); + +// Array Marshal for TPMS_TAGGED_POLICY +UINT16 +TPMS_TAGGED_POLICY_Array_Marshal( + TPMS_TAGGED_POLICY* source, BYTE** buffer, INT32* size, INT32 count); + +// Array Marshal for TPMS_TAGGED_PROPERTY +UINT16 +TPMS_TAGGED_PROPERTY_Array_Marshal( + TPMS_TAGGED_PROPERTY* source, BYTE** buffer, INT32* size, INT32 count); + +// Array Marshal/Unmarshal for TPMT_HA +TPM_RC +TPMT_HA_Array_Unmarshal( + TPMT_HA* target, BYTE** buffer, INT32* size, BOOL flag, INT32 count); +UINT16 +TPMT_HA_Array_Marshal(TPMT_HA* source, BYTE** buffer, INT32* size, INT32 count); + +// Array Marshal/Unmarshal for TPM_ALG_ID +TPM_RC +TPM_ALG_ID_Array_Unmarshal( + TPM_ALG_ID* target, BYTE** buffer, INT32* size, INT32 count); +UINT16 +TPM_ALG_ID_Array_Marshal(TPM_ALG_ID* source, BYTE** buffer, INT32* size, INT32 count); + +// Array Marshal/Unmarshal for TPM_CC +TPM_RC +TPM_CC_Array_Unmarshal(TPM_CC* target, BYTE** buffer, INT32* size, INT32 count); +UINT16 +TPM_CC_Array_Marshal(TPM_CC* source, BYTE** buffer, INT32* size, INT32 count); + +// Array Marshal/Unmarshal for TPM_ECC_CURVE +#if ALG_ECC +TPM_RC +TPM_ECC_CURVE_Array_Unmarshal( + TPM_ECC_CURVE* target, BYTE** buffer, INT32* size, INT32 count); +UINT16 +TPM_ECC_CURVE_Array_Marshal( + TPM_ECC_CURVE* source, BYTE** buffer, INT32* size, INT32 count); +#endif // ALG_ECC + +// Array Marshal/Unmarshal for TPM_HANDLE +TPM_RC +TPM_HANDLE_Array_Unmarshal( + TPM_HANDLE* target, BYTE** buffer, INT32* size, INT32 count); +UINT16 +TPM_HANDLE_Array_Marshal(TPM_HANDLE* source, BYTE** buffer, INT32* size, INT32 count); +#endif // _MARSHAL_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/MathOnByteBuffers_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/MathOnByteBuffers_fp.h new file mode 100644 index 0000000..cfb602e --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/MathOnByteBuffers_fp.h @@ -0,0 +1,128 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 28, 2019 Time: 08:25:19PM + */ + +#ifndef _MATH_ON_BYTE_BUFFERS_FP_H_ +#define _MATH_ON_BYTE_BUFFERS_FP_H_ + +//*** UnsignedCmpB +// This function compare two unsigned values. The values are byte-aligned, +// big-endian numbers (e.g, a hash). +// Return Type: int +// 1 if (a > b) +// 0 if (a = b) +// -1 if (a < b) +LIB_EXPORT int UnsignedCompareB(UINT32 aSize, // IN: size of a + const BYTE* a, // IN: a + UINT32 bSize, // IN: size of b + const BYTE* b // IN: b +); + +//***SignedCompareB() +// Compare two signed integers: +// Return Type: int +// 1 if a > b +// 0 if a = b +// -1 if a < b +int SignedCompareB(const UINT32 aSize, // IN: size of a + const BYTE* a, // IN: a buffer + const UINT32 bSize, // IN: size of b + const BYTE* b // IN: b buffer +); + +//*** ModExpB +// This function is used to do modular exponentiation in support of RSA. +// The most typical uses are: 'c' = 'm'^'e' mod 'n' (RSA encrypt) and +// 'm' = 'c'^'d' mod 'n' (RSA decrypt). When doing decryption, the 'e' parameter +// of the function will contain the private exponent 'd' instead of the public +// exponent 'e'. +// +// If the results will not fit in the provided buffer, +// an error is returned (CRYPT_ERROR_UNDERFLOW). If the results is smaller +// than the buffer, the results is de-normalized. +// +// This version is intended for use with RSA and requires that 'm' be +// less than 'n'. +// +// Return Type: TPM_RC +// TPM_RC_SIZE number to exponentiate is larger than the modulus +// TPM_RC_NO_RESULT result will not fit into the provided buffer +// +TPM_RC +ModExpB(UINT32 cSize, // IN: the size of the output buffer. It will + // need to be the same size as the modulus + BYTE* c, // OUT: the buffer to receive the results + // (c->size must be set to the maximum size + // for the returned value) + const UINT32 mSize, + const BYTE* m, // IN: number to exponentiate + const UINT32 eSize, + const BYTE* e, // IN: power + const UINT32 nSize, + const BYTE* n // IN: modulus +); + +//*** DivideB() +// Divide an integer ('n') by an integer ('d') producing a quotient ('q') and +// a remainder ('r'). If 'q' or 'r' is not needed, then the pointer to them +// may be set to NULL. +// +// Return Type: TPM_RC +// TPM_RC_NO_RESULT 'q' or 'r' is too small to receive the result +// +LIB_EXPORT TPM_RC DivideB(const TPM2B* n, // IN: numerator + const TPM2B* d, // IN: denominator + TPM2B* q, // OUT: quotient + TPM2B* r // OUT: remainder +); + +//*** AdjustNumberB() +// Remove/add leading zeros from a number in a TPM2B. Will try to make the number +// by adding or removing leading zeros. If the number is larger than the requested +// size, it will make the number as small as possible. Setting 'requestedSize' to +// zero is equivalent to requesting that the number be normalized. +UINT16 +AdjustNumberB(TPM2B* num, UINT16 requestedSize); + +//*** ShiftLeft() +// This function shifts a byte buffer (a TPM2B) one byte to the left. That is, +// the most significant bit of the most significant byte is lost. +TPM2B* ShiftLeft(TPM2B* value // IN/OUT: value to shift and shifted value out +); + +#endif // _MATH_ON_BYTE_BUFFERS_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Memory_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Memory_fp.h new file mode 100644 index 0000000..2e94a07 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Memory_fp.h @@ -0,0 +1,138 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Apr 7, 2019 Time: 06:58:58PM + */ + +#ifndef _MEMORY_FP_H_ +#define _MEMORY_FP_H_ + +//*** MemoryCopy() +// This is an alias for memmove. This is used in place of memcpy because +// some of the moves may overlap and rather than try to make sure that +// memmove is used when necessary, it is always used. +void MemoryCopy(void* dest, const void* src, int sSize); + +//*** MemoryEqual() +// This function indicates if two buffers have the same values in the indicated +// number of bytes. +// Return Type: BOOL +// TRUE(1) all octets are the same +// FALSE(0) all octets are not the same +BOOL MemoryEqual(const void* buffer1, // IN: compare buffer1 + const void* buffer2, // IN: compare buffer2 + unsigned int size // IN: size of bytes being compared +); + +//*** MemoryCopy2B() +// This function copies a TPM2B. This can be used when the TPM2B types are +// the same or different. +// +// This function returns the number of octets in the data buffer of the TPM2B. +LIB_EXPORT INT16 MemoryCopy2B(TPM2B* dest, // OUT: receiving TPM2B + const TPM2B* source, // IN: source TPM2B + unsigned int dSize // IN: size of the receiving buffer +); + +//*** MemoryConcat2B() +// This function will concatenate the buffer contents of a TPM2B to an +// the buffer contents of another TPM2B and adjust the size accordingly +// ('a' := ('a' | 'b')). +void MemoryConcat2B( + TPM2B* aInOut, // IN/OUT: destination 2B + TPM2B* bIn, // IN: second 2B + unsigned int aMaxSize // IN: The size of aInOut.buffer (max values for + // aInOut.size) +); + +//*** MemoryEqual2B() +// This function will compare two TPM2B structures. To be equal, they +// need to be the same size and the buffer contexts need to be the same +// in all octets. +// Return Type: BOOL +// TRUE(1) size and buffer contents are the same +// FALSE(0) size or buffer contents are not the same +BOOL MemoryEqual2B(const TPM2B* aIn, // IN: compare value + const TPM2B* bIn // IN: compare value +); + +//*** MemorySet() +// This function will set all the octets in the specified memory range to +// the specified octet value. +// Note: A previous version had an additional parameter (dSize) that was +// intended to make sure that the destination would not be overrun. The +// problem is that, in use, all that was happening was that the value of +// size was used for dSize so there was no benefit in the extra parameter. +void MemorySet(void* dest, int value, size_t size); + +//*** MemoryPad2B() +// Function to pad a TPM2B with zeros and adjust the size. +void MemoryPad2B(TPM2B* b, UINT16 newSize); + +//*** Uint16ToByteArray() +// Function to write an integer to a byte array +void Uint16ToByteArray(UINT16 i, BYTE* a); + +//*** Uint32ToByteArray() +// Function to write an integer to a byte array +void Uint32ToByteArray(UINT32 i, BYTE* a); + +//*** Uint64ToByteArray() +// Function to write an integer to a byte array +void Uint64ToByteArray(UINT64 i, BYTE* a); + +//*** ByteArrayToUint8() +// Function to write a UINT8 to a byte array. This is included for completeness +// and to allow certain macro expansions +UINT8 +ByteArrayToUint8(BYTE* a); + +//*** ByteArrayToUint16() +// Function to write an integer to a byte array +UINT16 +ByteArrayToUint16(BYTE* a); + +//*** ByteArrayToUint32() +// Function to write an integer to a byte array +UINT32 +ByteArrayToUint32(BYTE* a); + +//*** ByteArrayToUint64() +// Function to write an integer to a byte array +UINT64 +ByteArrayToUint64(BYTE* a); + +#endif // _MEMORY_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_Certify_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_Certify_fp.h new file mode 100644 index 0000000..aa63fca --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_Certify_fp.h @@ -0,0 +1,78 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_NV_Certify // Command must be enabled + +# ifndef _NV_Certify_FP_H_ +# define _NV_Certify_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_OBJECT signHandle; + TPMI_RH_NV_AUTH authHandle; + TPMI_RH_NV_INDEX nvIndex; + TPM2B_DATA qualifyingData; + TPMT_SIG_SCHEME inScheme; + UINT16 size; + UINT16 offset; +} NV_Certify_In; + +// Output structure definition +typedef struct +{ + TPM2B_ATTEST certifyInfo; + TPMT_SIGNATURE signature; +} NV_Certify_Out; + +// Response code modifiers +# define RC_NV_Certify_signHandle (TPM_RC_H + TPM_RC_1) +# define RC_NV_Certify_authHandle (TPM_RC_H + TPM_RC_2) +# define RC_NV_Certify_nvIndex (TPM_RC_H + TPM_RC_3) +# define RC_NV_Certify_qualifyingData (TPM_RC_P + TPM_RC_1) +# define RC_NV_Certify_inScheme (TPM_RC_P + TPM_RC_2) +# define RC_NV_Certify_size (TPM_RC_P + TPM_RC_3) +# define RC_NV_Certify_offset (TPM_RC_P + TPM_RC_4) + +// Function prototype +TPM_RC +TPM2_NV_Certify(NV_Certify_In* in, NV_Certify_Out* out); + +# endif // _NV_Certify_FP_H_ +#endif // CC_NV_Certify diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_ChangeAuth_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_ChangeAuth_fp.h new file mode 100644 index 0000000..d9df437 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_ChangeAuth_fp.h @@ -0,0 +1,61 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_NV_ChangeAuth // Command must be enabled + +# ifndef _NV_Change_Auth_FP_H_ +# define _NV_Change_Auth_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_RH_NV_INDEX nvIndex; + TPM2B_AUTH newAuth; +} NV_ChangeAuth_In; + +// Response code modifiers +# define RC_NV_ChangeAuth_nvIndex (TPM_RC_H + TPM_RC_1) +# define RC_NV_ChangeAuth_newAuth (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_NV_ChangeAuth(NV_ChangeAuth_In* in); + +# endif // _NV_Change_Auth_FP_H_ +#endif // CC_NV_ChangeAuth diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_DefineSpace_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_DefineSpace_fp.h new file mode 100644 index 0000000..b446afb --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_DefineSpace_fp.h @@ -0,0 +1,63 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_NV_DefineSpace // Command must be enabled + +# ifndef _NV_Define_Space_FP_H_ +# define _NV_Define_Space_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_RH_PROVISION authHandle; + TPM2B_AUTH auth; + TPM2B_NV_PUBLIC publicInfo; +} NV_DefineSpace_In; + +// Response code modifiers +# define RC_NV_DefineSpace_authHandle (TPM_RC_H + TPM_RC_1) +# define RC_NV_DefineSpace_auth (TPM_RC_P + TPM_RC_1) +# define RC_NV_DefineSpace_publicInfo (TPM_RC_P + TPM_RC_2) + +// Function prototype +TPM_RC +TPM2_NV_DefineSpace(NV_DefineSpace_In* in); + +# endif // _NV_Define_Space_FP_H_ +#endif // CC_NV_DefineSpace diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_Extend_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_Extend_fp.h new file mode 100644 index 0000000..2fd6d20 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_Extend_fp.h @@ -0,0 +1,63 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_NV_Extend // Command must be enabled + +# ifndef _NV_Extend_FP_H_ +# define _NV_Extend_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_RH_NV_AUTH authHandle; + TPMI_RH_NV_INDEX nvIndex; + TPM2B_MAX_NV_BUFFER data; +} NV_Extend_In; + +// Response code modifiers +# define RC_NV_Extend_authHandle (TPM_RC_H + TPM_RC_1) +# define RC_NV_Extend_nvIndex (TPM_RC_H + TPM_RC_2) +# define RC_NV_Extend_data (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_NV_Extend(NV_Extend_In* in); + +# endif // _NV_Extend_FP_H_ +#endif // CC_NV_Extend diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_GlobalWriteLock_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_GlobalWriteLock_fp.h new file mode 100644 index 0000000..26a1f74 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_GlobalWriteLock_fp.h @@ -0,0 +1,59 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_NV_GlobalWriteLock // Command must be enabled + +# ifndef _NV_Global_Write_Lock_FP_H_ +# define _NV_Global_Write_Lock_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_RH_PROVISION authHandle; +} NV_GlobalWriteLock_In; + +// Response code modifiers +# define RC_NV_GlobalWriteLock_authHandle (TPM_RC_H + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_NV_GlobalWriteLock(NV_GlobalWriteLock_In* in); + +# endif // _NV_Global_Write_Lock_FP_H_ +#endif // CC_NV_GlobalWriteLock diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_Increment_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_Increment_fp.h new file mode 100644 index 0000000..a0dc73b --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_Increment_fp.h @@ -0,0 +1,61 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_NV_Increment // Command must be enabled + +# ifndef _NV_Increment_FP_H_ +# define _NV_Increment_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_RH_NV_AUTH authHandle; + TPMI_RH_NV_INDEX nvIndex; +} NV_Increment_In; + +// Response code modifiers +# define RC_NV_Increment_authHandle (TPM_RC_H + TPM_RC_1) +# define RC_NV_Increment_nvIndex (TPM_RC_H + TPM_RC_2) + +// Function prototype +TPM_RC +TPM2_NV_Increment(NV_Increment_In* in); + +# endif // _NV_Increment_FP_H_ +#endif // CC_NV_Increment diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_ReadLock_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_ReadLock_fp.h new file mode 100644 index 0000000..f97296a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_ReadLock_fp.h @@ -0,0 +1,61 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_NV_ReadLock // Command must be enabled + +# ifndef _NV_Read_Lock_FP_H_ +# define _NV_Read_Lock_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_RH_NV_AUTH authHandle; + TPMI_RH_NV_INDEX nvIndex; +} NV_ReadLock_In; + +// Response code modifiers +# define RC_NV_ReadLock_authHandle (TPM_RC_H + TPM_RC_1) +# define RC_NV_ReadLock_nvIndex (TPM_RC_H + TPM_RC_2) + +// Function prototype +TPM_RC +TPM2_NV_ReadLock(NV_ReadLock_In* in); + +# endif // _NV_Read_Lock_FP_H_ +#endif // CC_NV_ReadLock diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_ReadPublic_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_ReadPublic_fp.h new file mode 100644 index 0000000..2a6d3f3 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_ReadPublic_fp.h @@ -0,0 +1,66 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_NV_ReadPublic // Command must be enabled + +# ifndef _NV_Read_Public_FP_H_ +# define _NV_Read_Public_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_RH_NV_INDEX nvIndex; +} NV_ReadPublic_In; + +// Output structure definition +typedef struct +{ + TPM2B_NV_PUBLIC nvPublic; + TPM2B_NAME nvName; +} NV_ReadPublic_Out; + +// Response code modifiers +# define RC_NV_ReadPublic_nvIndex (TPM_RC_H + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_NV_ReadPublic(NV_ReadPublic_In* in, NV_ReadPublic_Out* out); + +# endif // _NV_Read_Public_FP_H_ +#endif // CC_NV_ReadPublic diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_Read_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_Read_fp.h new file mode 100644 index 0000000..f542333 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_Read_fp.h @@ -0,0 +1,71 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_NV_Read // Command must be enabled + +# ifndef _NV_Read_FP_H_ +# define _NV_Read_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_RH_NV_AUTH authHandle; + TPMI_RH_NV_INDEX nvIndex; + UINT16 size; + UINT16 offset; +} NV_Read_In; + +// Output structure definition +typedef struct +{ + TPM2B_MAX_NV_BUFFER data; +} NV_Read_Out; + +// Response code modifiers +# define RC_NV_Read_authHandle (TPM_RC_H + TPM_RC_1) +# define RC_NV_Read_nvIndex (TPM_RC_H + TPM_RC_2) +# define RC_NV_Read_size (TPM_RC_P + TPM_RC_1) +# define RC_NV_Read_offset (TPM_RC_P + TPM_RC_2) + +// Function prototype +TPM_RC +TPM2_NV_Read(NV_Read_In* in, NV_Read_Out* out); + +# endif // _NV_Read_FP_H_ +#endif // CC_NV_Read diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_SetBits_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_SetBits_fp.h new file mode 100644 index 0000000..71b9ddd --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_SetBits_fp.h @@ -0,0 +1,63 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_NV_SetBits // Command must be enabled + +# ifndef _NV_Set_Bits_FP_H_ +# define _NV_Set_Bits_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_RH_NV_AUTH authHandle; + TPMI_RH_NV_INDEX nvIndex; + UINT64 bits; +} NV_SetBits_In; + +// Response code modifiers +# define RC_NV_SetBits_authHandle (TPM_RC_H + TPM_RC_1) +# define RC_NV_SetBits_nvIndex (TPM_RC_H + TPM_RC_2) +# define RC_NV_SetBits_bits (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_NV_SetBits(NV_SetBits_In* in); + +# endif // _NV_Set_Bits_FP_H_ +#endif // CC_NV_SetBits diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_UndefineSpaceSpecial_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_UndefineSpaceSpecial_fp.h new file mode 100644 index 0000000..52abfaf --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_UndefineSpaceSpecial_fp.h @@ -0,0 +1,61 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_NV_UndefineSpaceSpecial // Command must be enabled + +# ifndef _NV_Undefine_Space_Special_FP_H_ +# define _NV_Undefine_Space_Special_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_RH_NV_INDEX nvIndex; + TPMI_RH_PLATFORM platform; +} NV_UndefineSpaceSpecial_In; + +// Response code modifiers +# define RC_NV_UndefineSpaceSpecial_nvIndex (TPM_RC_H + TPM_RC_1) +# define RC_NV_UndefineSpaceSpecial_platform (TPM_RC_H + TPM_RC_2) + +// Function prototype +TPM_RC +TPM2_NV_UndefineSpaceSpecial(NV_UndefineSpaceSpecial_In* in); + +# endif // _NV_Undefine_Space_Special_FP_H_ +#endif // CC_NV_UndefineSpaceSpecial diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_UndefineSpace_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_UndefineSpace_fp.h new file mode 100644 index 0000000..5c54714 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_UndefineSpace_fp.h @@ -0,0 +1,61 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_NV_UndefineSpace // Command must be enabled + +# ifndef _NV_Undefine_Space_FP_H_ +# define _NV_Undefine_Space_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_RH_PROVISION authHandle; + TPMI_RH_NV_INDEX nvIndex; +} NV_UndefineSpace_In; + +// Response code modifiers +# define RC_NV_UndefineSpace_authHandle (TPM_RC_H + TPM_RC_1) +# define RC_NV_UndefineSpace_nvIndex (TPM_RC_H + TPM_RC_2) + +// Function prototype +TPM_RC +TPM2_NV_UndefineSpace(NV_UndefineSpace_In* in); + +# endif // _NV_Undefine_Space_FP_H_ +#endif // CC_NV_UndefineSpace diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_WriteLock_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_WriteLock_fp.h new file mode 100644 index 0000000..1441a5c --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_WriteLock_fp.h @@ -0,0 +1,61 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_NV_WriteLock // Command must be enabled + +# ifndef _NV_Write_Lock_FP_H_ +# define _NV_Write_Lock_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_RH_NV_AUTH authHandle; + TPMI_RH_NV_INDEX nvIndex; +} NV_WriteLock_In; + +// Response code modifiers +# define RC_NV_WriteLock_authHandle (TPM_RC_H + TPM_RC_1) +# define RC_NV_WriteLock_nvIndex (TPM_RC_H + TPM_RC_2) + +// Function prototype +TPM_RC +TPM2_NV_WriteLock(NV_WriteLock_In* in); + +# endif // _NV_Write_Lock_FP_H_ +#endif // CC_NV_WriteLock diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_Write_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_Write_fp.h new file mode 100644 index 0000000..7a83d2b --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_Write_fp.h @@ -0,0 +1,65 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_NV_Write // Command must be enabled + +# ifndef _NV_Write_FP_H_ +# define _NV_Write_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_RH_NV_AUTH authHandle; + TPMI_RH_NV_INDEX nvIndex; + TPM2B_MAX_NV_BUFFER data; + UINT16 offset; +} NV_Write_In; + +// Response code modifiers +# define RC_NV_Write_authHandle (TPM_RC_H + TPM_RC_1) +# define RC_NV_Write_nvIndex (TPM_RC_H + TPM_RC_2) +# define RC_NV_Write_data (TPM_RC_P + TPM_RC_1) +# define RC_NV_Write_offset (TPM_RC_P + TPM_RC_2) + +// Function prototype +TPM_RC +TPM2_NV_Write(NV_Write_In* in); + +# endif // _NV_Write_FP_H_ +#endif // CC_NV_Write diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_spt_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_spt_fp.h new file mode 100644 index 0000000..dee8e8e --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NV_spt_fp.h @@ -0,0 +1,88 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 28, 2019 Time: 08:25:18PM + */ + +#ifndef _NV_SPT_FP_H_ +#define _NV_SPT_FP_H_ + +//*** NvReadAccessChecks() +// Common routine for validating a read +// Used by TPM2_NV_Read, TPM2_NV_ReadLock and TPM2_PolicyNV +// Return Type: TPM_RC +// TPM_RC_NV_AUTHORIZATION autHandle is not allowed to authorize read +// of the index +// TPM_RC_NV_LOCKED Read locked +// TPM_RC_NV_UNINITIALIZED Try to read an uninitialized index +// +TPM_RC +NvReadAccessChecks(TPM_HANDLE authHandle, // IN: the handle that provided the + // authorization + TPM_HANDLE nvHandle, // IN: the handle of the NV index to be read + TPMA_NV attributes // IN: the attributes of 'nvHandle' +); + +//*** NvWriteAccessChecks() +// Common routine for validating a write +// Used by TPM2_NV_Write, TPM2_NV_Increment, TPM2_SetBits, and TPM2_NV_WriteLock +// Return Type: TPM_RC +// TPM_RC_NV_AUTHORIZATION Authorization fails +// TPM_RC_NV_LOCKED Write locked +// +TPM_RC +NvWriteAccessChecks( + TPM_HANDLE authHandle, // IN: the handle that provided the + // authorization + TPM_HANDLE nvHandle, // IN: the handle of the NV index to be written + TPMA_NV attributes // IN: the attributes of 'nvHandle' +); + +//*** NvClearOrderly() +// This function is used to cause gp.orderlyState to be cleared to the +// non-orderly state. +TPM_RC +NvClearOrderly(void); + +//*** NvIsPinPassIndex() +// Function to check to see if an NV index is a PIN Pass Index +// Return Type: BOOL +// TRUE(1) is pin pass +// FALSE(0) is not pin pass +BOOL NvIsPinPassIndex(TPM_HANDLE index // IN: Handle to check +); + +#endif // _NV_SPT_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NvDynamic_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NvDynamic_fp.h new file mode 100644 index 0000000..0d145db --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NvDynamic_fp.h @@ -0,0 +1,408 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 7, 2020 Time: 07:15:54PM + */ + +#ifndef _NV_DYNAMIC_FP_H_ +#define _NV_DYNAMIC_FP_H_ + +//*** NvWriteNvListEnd() +// Function to write the list terminator. +NV_REF +NvWriteNvListEnd(NV_REF end); + +//*** NvUpdateIndexOrderlyData() +// This function is used to cause an update of the orderly data to the NV backing +// store. +void NvUpdateIndexOrderlyData(void); + +//*** NvReadIndex() +// This function is used to read the NV Index NV_INDEX. This is used so that the +// index information can be compressed and only this function would be needed +// to decompress it. Mostly, compression would only be able to save the space +// needed by the policy. +void NvReadNvIndexInfo(NV_REF ref, // IN: points to NV where index is located + NV_INDEX* nvIndex // OUT: place to receive index data +); + +//*** NvReadObject() +// This function is used to read a persistent object. This is used so that the +// object information can be compressed and only this function would be needed +// to uncompress it. +void NvReadObject(NV_REF ref, // IN: points to NV where index is located + OBJECT* object // OUT: place to receive the object data +); + +//*** NvIndexIsDefined() +// See if an index is already defined +BOOL NvIndexIsDefined(TPM_HANDLE nvHandle // IN: Index to look for +); + +//*** NvIsPlatformPersistentHandle() +// This function indicates if a handle references a persistent object in the +// range belonging to the platform. +// Return Type: BOOL +// TRUE(1) handle references a platform persistent object +// and may reference an owner persistent object either +// FALSE(0) handle does not reference platform persistent object +BOOL NvIsPlatformPersistentHandle(TPM_HANDLE handle // IN: handle +); + +//*** NvIsOwnerPersistentHandle() +// This function indicates if a handle references a persistent object in the +// range belonging to the owner. +// Return Type: BOOL +// TRUE(1) handle is owner persistent handle +// FALSE(0) handle is not owner persistent handle and may not be +// a persistent handle at all +BOOL NvIsOwnerPersistentHandle(TPM_HANDLE handle // IN: handle +); + +//*** NvIndexIsAccessible() +// +// This function validates that a handle references a defined NV Index and +// that the Index is currently accessible. +// Return Type: TPM_RC +// TPM_RC_HANDLE the handle points to an undefined NV Index +// If shEnable is CLEAR, this would include an index +// created using ownerAuth. If phEnableNV is CLEAR, +// this would include and index created using +// platformAuth +// TPM_RC_NV_READLOCKED Index is present but locked for reading and command +// does not write to the index +// TPM_RC_NV_WRITELOCKED Index is present but locked for writing and command +// writes to the index +TPM_RC +NvIndexIsAccessible(TPMI_RH_NV_INDEX handle // IN: handle +); + +//*** NvGetEvictObject() +// This function is used to dereference an evict object handle and get a pointer +// to the object. +// Return Type: TPM_RC +// TPM_RC_HANDLE the handle does not point to an existing +// persistent object +TPM_RC +NvGetEvictObject(TPM_HANDLE handle, // IN: handle + OBJECT* object // OUT: object data +); + +//*** NvIndexCacheInit() +// Function to initialize the Index cache +void NvIndexCacheInit(void); + +//*** NvGetIndexData() +// This function is used to access the data in an NV Index. The data is returned +// as a byte sequence. +// +// This function requires that the NV Index be defined, and that the +// required data is within the data range. It also requires that TPMA_NV_WRITTEN +// of the Index is SET. +void NvGetIndexData(NV_INDEX* nvIndex, // IN: the in RAM index descriptor + NV_REF locator, // IN: where the data is located + UINT32 offset, // IN: offset of NV data + UINT16 size, // IN: number of octets of NV data to read + void* data // OUT: data buffer +); + +//*** NvHashIndexData() +// This function adds Index data to a hash. It does this in parts to avoid large stack +// buffers. +void NvHashIndexData(HASH_STATE* hashState, // IN: Initialized hash state + NV_INDEX* nvIndex, // IN: Index + NV_REF locator, // IN: where the data is located + UINT32 offset, // IN: starting offset + UINT16 size // IN: amount to hash +); + +//*** NvGetUINT64Data() +// Get data in integer format of a bit or counter NV Index. +// +// This function requires that the NV Index is defined and that the NV Index +// previously has been written. +UINT64 +NvGetUINT64Data(NV_INDEX* nvIndex, // IN: the in RAM index descriptor + NV_REF locator // IN: where index exists in NV +); + +//*** NvWriteIndexAttributes() +// This function is used to write just the attributes of an index. +// Return type: TPM_RC +// TPM_RC_NV_RATE NV is rate limiting so retry +// TPM_RC_NV_UNAVAILABLE NV is not available +TPM_RC +NvWriteIndexAttributes(TPM_HANDLE handle, + NV_REF locator, // IN: location of the index + TPMA_NV attributes // IN: attributes to write +); + +//*** NvWriteIndexAuth() +// This function is used to write the authValue of an index. It is used by +// TPM2_NV_ChangeAuth() +// Return type: TPM_RC +// TPM_RC_NV_RATE NV is rate limiting so retry +// TPM_RC_NV_UNAVAILABLE NV is not available +TPM_RC +NvWriteIndexAuth(NV_REF locator, // IN: location of the index + TPM2B_AUTH* authValue // IN: the authValue to write +); + +//*** NvGetIndexInfo() +// This function loads the nvIndex Info into the NV cache and returns a pointer +// to the NV_INDEX. If the returned value is zero, the index was not found. +// The 'locator' parameter, if not NULL, will be set to the offset in NV of the +// Index (the location of the handle of the Index). +// +// This function will set the index cache. If the index is orderly, the attributes +// from RAM are substituted for the attributes in the cached index +NV_INDEX* NvGetIndexInfo(TPM_HANDLE nvHandle, // IN: the index handle + NV_REF* locator // OUT: location of the index +); + +//*** NvWriteIndexData() +// This function is used to write NV index data. It is intended to be used to +// update the data associated with the default index. +// +// This function requires that the NV Index is defined, and the data is +// within the defined data range for the index. +// +// Index data is only written due to a command that modifies the data in a single +// index. There is no case where changes are made to multiple indexes data at the +// same time. Multiple attributes may be change but not multiple index data. This +// is important because we will normally be handling the index for which we have +// the cached pointer values. +// Return type: TPM_RC +// TPM_RC_NV_RATE NV is rate limiting so retry +// TPM_RC_NV_UNAVAILABLE NV is not available +TPM_RC +NvWriteIndexData(NV_INDEX* nvIndex, // IN: the description of the index + UINT32 offset, // IN: offset of NV data + UINT32 size, // IN: size of NV data + void* data // IN: data buffer +); + +//*** NvWriteUINT64Data() +// This function to write back a UINT64 value. The various UINT64 values (bits, +// counters, and PINs) are kept in canonical format but manipulate in native +// format. This takes a native format value converts it and saves it back as +// in canonical format. +// +// This function will return the value from NV or RAM depending on the type of the +// index (orderly or not) +// +TPM_RC +NvWriteUINT64Data(NV_INDEX* nvIndex, // IN: the description of the index + UINT64 intValue // IN: the value to write +); + +//*** NvGetIndexName() +// This function computes the Name of an index +// The 'name' buffer receives the bytes of the Name and the return value +// is the number of octets in the Name. +// +// This function requires that the NV Index is defined. +TPM2B_NAME* NvGetIndexName( + NV_INDEX* nvIndex, // IN: the index over which the name is to be + // computed + TPM2B_NAME* name // OUT: name of the index +); + +//*** NvGetNameByIndexHandle() +// This function is used to compute the Name of an NV Index referenced by handle. +// +// The 'name' buffer receives the bytes of the Name and the return value +// is the number of octets in the Name. +// +// This function requires that the NV Index is defined. +TPM2B_NAME* NvGetNameByIndexHandle( + TPMI_RH_NV_INDEX handle, // IN: handle of the index + TPM2B_NAME* name // OUT: name of the index +); + +//*** NvDefineIndex() +// This function is used to assign NV memory to an NV Index. +// +// Return Type: TPM_RC +// TPM_RC_NV_SPACE insufficient NV space +TPM_RC +NvDefineIndex(TPMS_NV_PUBLIC* publicArea, // IN: A template for an area to create. + TPM2B_AUTH* authValue // IN: The initial authorization value +); + +//*** NvAddEvictObject() +// This function is used to assign NV memory to a persistent object. +// Return Type: TPM_RC +// TPM_RC_NV_HANDLE the requested handle is already in use +// TPM_RC_NV_SPACE insufficient NV space +TPM_RC +NvAddEvictObject(TPMI_DH_OBJECT evictHandle, // IN: new evict handle + OBJECT* object // IN: object to be added +); + +//*** NvDeleteIndex() +// This function is used to delete an NV Index. +// Return Type: TPM_RC +// TPM_RC_NV_UNAVAILABLE NV is not accessible +// TPM_RC_NV_RATE NV is rate limiting +TPM_RC +NvDeleteIndex(NV_INDEX* nvIndex, // IN: an in RAM index descriptor + NV_REF entityAddr // IN: location in NV +); + +TPM_RC +NvDeleteEvict(TPM_HANDLE handle // IN: handle of entity to be deleted +); + +//*** NvFlushHierarchy() +// This function will delete persistent objects belonging to the indicated hierarchy. +// If the storage hierarchy is selected, the function will also delete any +// NV Index defined using ownerAuth. +// Return Type: TPM_RC +// TPM_RC_NV_RATE NV is unavailable because of rate limit +// TPM_RC_NV_UNAVAILABLE NV is inaccessible +TPM_RC +NvFlushHierarchy(TPMI_RH_HIERARCHY hierarchy // IN: hierarchy to be flushed. +); + +//*** NvSetGlobalLock() +// This function is used to SET the TPMA_NV_WRITELOCKED attribute for all +// NV indexes that have TPMA_NV_GLOBALLOCK SET. This function is use by +// TPM2_NV_GlobalWriteLock(). +// Return Type: TPM_RC +// TPM_RC_NV_RATE NV is unavailable because of rate limit +// TPM_RC_NV_UNAVAILABLE NV is inaccessible +TPM_RC +NvSetGlobalLock(void); + +//*** NvCapGetPersistent() +// This function is used to get a list of handles of the persistent objects, +// starting at 'handle'. +// +// 'Handle' must be in valid persistent object handle range, but does not +// have to reference an existing persistent object. +// Return Type: TPMI_YES_NO +// YES if there are more handles available +// NO all the available handles has been returned +TPMI_YES_NO +NvCapGetPersistent(TPMI_DH_OBJECT handle, // IN: start handle + UINT32 count, // IN: maximum number of returned handles + TPML_HANDLE* handleList // OUT: list of handle +); + +//*** NvCapGetIndex() +// This function returns a list of handles of NV indexes, starting from 'handle'. +// 'Handle' must be in the range of NV indexes, but does not have to reference +// an existing NV Index. +// Return Type: TPMI_YES_NO +// YES if there are more handles to report +// NO all the available handles has been reported +TPMI_YES_NO +NvCapGetIndex(TPMI_DH_OBJECT handle, // IN: start handle + UINT32 count, // IN: max number of returned handles + TPML_HANDLE* handleList // OUT: list of handle +); + +//*** NvCapGetIndexNumber() +// This function returns the count of NV Indexes currently defined. +UINT32 +NvCapGetIndexNumber(void); + +//*** NvCapGetPersistentNumber() +// Function returns the count of persistent objects currently in NV memory. +UINT32 +NvCapGetPersistentNumber(void); + +//*** NvCapGetPersistentAvail() +// This function returns an estimate of the number of additional persistent +// objects that could be loaded into NV memory. +UINT32 +NvCapGetPersistentAvail(void); + +//*** NvCapGetCounterNumber() +// Get the number of defined NV Indexes that are counter indexes. +UINT32 +NvCapGetCounterNumber(void); + +//*** NvEntityStartup() +// This function is called at TPM_Startup(). If the startup completes +// a TPM Resume cycle, no action is taken. If the startup is a TPM Reset +// or a TPM Restart, then this function will: +// a) clear read/write lock; +// b) reset NV Index data that has TPMA_NV_CLEAR_STCLEAR SET; and +// c) set the lower bits in orderly counters to 1 for a non-orderly startup +// +// It is a prerequisite that NV be available for writing before this +// function is called. +BOOL NvEntityStartup(STARTUP_TYPE type // IN: start up type +); + +//*** NvCapGetCounterAvail() +// This function returns an estimate of the number of additional counter type +// NV indexes that can be defined. +UINT32 +NvCapGetCounterAvail(void); + +//*** NvFindHandle() +// this function returns the offset in NV memory of the entity associated +// with the input handle. A value of zero indicates that handle does not +// exist reference an existing persistent object or defined NV Index. +NV_REF +NvFindHandle(TPM_HANDLE handle); + +//*** NvReadMaxCount() +// This function returns the max NV counter value. +// +UINT64 +NvReadMaxCount(void); + +//*** NvUpdateMaxCount() +// This function updates the max counter value to NV memory. This is just staging +// for the actual write that will occur when the NV index memory is modified. +// +void NvUpdateMaxCount(UINT64 count); + +//*** NvSetMaxCount() +// This function is used at NV initialization time to set the initial value of +// the maximum counter. +void NvSetMaxCount(UINT64 value); + +//*** NvGetMaxCount() +// Function to get the NV max counter value from the end-of-list marker +UINT64 +NvGetMaxCount(void); + +#endif // _NV_DYNAMIC_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NvReserved_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NvReserved_fp.h new file mode 100644 index 0000000..a583ef5 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/NvReserved_fp.h @@ -0,0 +1,108 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Apr 2, 2019 Time: 04:23:27PM + */ + +#ifndef _NV_RESERVED_FP_H_ +#define _NV_RESERVED_FP_H_ + +//*** NvCheckState() +// Function to check the NV state by accessing the platform-specific function +// to get the NV state. The result state is registered in s_NvIsAvailable +// that will be reported by NvIsAvailable. +// +// This function is called at the beginning of ExecuteCommand before any potential +// check of g_NvStatus. +void NvCheckState(void); + +//*** NvCommit +// This is a wrapper for the platform function to commit pending NV writes. +BOOL NvCommit(void); + +//*** NvPowerOn() +// This function is called at _TPM_Init to initialize the NV environment. +// Return Type: BOOL +// TRUE(1) all NV was initialized +// FALSE(0) the NV containing saved state had an error and +// TPM2_Startup(CLEAR) is required +BOOL NvPowerOn(void); + +//*** NvManufacture() +// This function initializes the NV system at pre-install time. +// +// This function should only be called in a manufacturing environment or in a +// simulation. +// +// The layout of NV memory space is an implementation choice. +void NvManufacture(void); + +//*** NvRead() +// This function is used to move reserved data from NV memory to RAM. +void NvRead(void* outBuffer, // OUT: buffer to receive data + UINT32 nvOffset, // IN: offset in NV of value + UINT32 size // IN: size of the value to read +); + +//*** NvWrite() +// This function is used to post reserved data for writing to NV memory. Before +// the TPM completes the operation, the value will be written. +BOOL NvWrite(UINT32 nvOffset, // IN: location in NV to receive data + UINT32 size, // IN: size of the data to move + void* inBuffer // IN: location containing data to write +); + +//*** NvUpdatePersistent() +// This function is used to update a value in the PERSISTENT_DATA structure and +// commits the value to NV. +void NvUpdatePersistent( + UINT32 offset, // IN: location in PERMANENT_DATA to be updated + UINT32 size, // IN: size of the value + void* buffer // IN: the new data +); + +//*** NvClearPersistent() +// This function is used to clear a persistent data entry and commit it to NV +void NvClearPersistent(UINT32 offset, // IN: the offset in the PERMANENT_DATA + // structure to be cleared (zeroed) + UINT32 size // IN: number of bytes to clear +); + +//*** NvReadPersistent() +// This function reads persistent data to the RAM copy of the 'gp' structure. +void NvReadPersistent(void); + +#endif // _NV_RESERVED_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ObjectChangeAuth_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ObjectChangeAuth_fp.h new file mode 100644 index 0000000..cc2205f --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ObjectChangeAuth_fp.h @@ -0,0 +1,69 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_ObjectChangeAuth // Command must be enabled + +# ifndef _Object_Change_Auth_FP_H_ +# define _Object_Change_Auth_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_OBJECT objectHandle; + TPMI_DH_OBJECT parentHandle; + TPM2B_AUTH newAuth; +} ObjectChangeAuth_In; + +// Output structure definition +typedef struct +{ + TPM2B_PRIVATE outPrivate; +} ObjectChangeAuth_Out; + +// Response code modifiers +# define RC_ObjectChangeAuth_objectHandle (TPM_RC_H + TPM_RC_1) +# define RC_ObjectChangeAuth_parentHandle (TPM_RC_H + TPM_RC_2) +# define RC_ObjectChangeAuth_newAuth (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_ObjectChangeAuth(ObjectChangeAuth_In* in, ObjectChangeAuth_Out* out); + +# endif // _Object_Change_Auth_FP_H_ +#endif // CC_ObjectChangeAuth diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Object_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Object_fp.h new file mode 100644 index 0000000..76277bb --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Object_fp.h @@ -0,0 +1,302 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 4, 2020 Time: 02:36:44PM + */ + +#ifndef _OBJECT_FP_H_ +#define _OBJECT_FP_H_ + +//*** ObjectFlush() +// This function marks an object slot as available. +// Since there is no checking of the input parameters, it should be used +// judiciously. +// Note: This could be converted to a macro. +void ObjectFlush(OBJECT* object); + +//*** ObjectSetInUse() +// This access function sets the occupied attribute of an object slot. +void ObjectSetInUse(OBJECT* object); + +//*** ObjectStartup() +// This function is called at TPM2_Startup() to initialize the object subsystem. +BOOL ObjectStartup(void); + +//*** ObjectCleanupEvict() +// +// In this implementation, a persistent object is moved from NV into an object slot +// for processing. It is flushed after command execution. This function is called +// from ExecuteCommand(). +void ObjectCleanupEvict(void); + +//*** IsObjectPresent() +// This function checks to see if a transient handle references a loaded +// object. This routine should not be called if the handle is not a +// transient handle. The function validates that the handle is in the +// implementation-dependent allowed in range for loaded transient objects. +// Return Type: BOOL +// TRUE(1) handle references a loaded object +// FALSE(0) handle is not an object handle, or it does not +// reference to a loaded object +BOOL IsObjectPresent(TPMI_DH_OBJECT handle // IN: handle to be checked +); + +//*** ObjectIsSequence() +// This function is used to check if the object is a sequence object. This function +// should not be called if the handle does not reference a loaded object. +// Return Type: BOOL +// TRUE(1) object is an HMAC, hash, or event sequence object +// FALSE(0) object is not an HMAC, hash, or event sequence object +BOOL ObjectIsSequence(OBJECT* object // IN: handle to be checked +); + +//*** HandleToObject() +// This function is used to find the object structure associated with a handle. +// +// This function requires that 'handle' references a loaded object or a permanent +// handle. +OBJECT* HandleToObject(TPMI_DH_OBJECT handle // IN: handle of the object +); + +//*** GetQualifiedName() +// This function returns the Qualified Name of the object. In this implementation, +// the Qualified Name is computed when the object is loaded and is saved in the +// internal representation of the object. The alternative would be to retain the +// Name of the parent and compute the QN when needed. This would take the same +// amount of space so it is not recommended that the alternate be used. +// +// This function requires that 'handle' references a loaded object. +void GetQualifiedName(TPMI_DH_OBJECT handle, // IN: handle of the object + TPM2B_NAME* qualifiedName // OUT: qualified name of the object +); + +//*** ObjectGetHierarchy() +// This function returns the handle for the hierarchy of an object. +TPMI_RH_HIERARCHY +ObjectGetHierarchy(OBJECT* object // IN :object +); + +//*** GetHierarchy() +// This function returns the handle of the hierarchy to which a handle belongs. +// This function is similar to ObjectGetHierarchy() but this routine takes +// a handle but ObjectGetHierarchy() takes an pointer to an object. +// +// This function requires that 'handle' references a loaded object. +TPMI_RH_HIERARCHY +GetHierarchy(TPMI_DH_OBJECT handle // IN :object handle +); + +//*** FindEmptyObjectSlot() +// This function finds an open object slot, if any. It will clear the attributes +// but will not set the occupied attribute. This is so that a slot may be used +// and discarded if everything does not go as planned. +// Return Type: OBJECT * +// NULL no open slot found +// != NULL pointer to available slot +OBJECT* FindEmptyObjectSlot(TPMI_DH_OBJECT* handle // OUT: (optional) +); + +//*** ObjectAllocateSlot() +// This function is used to allocate a slot in internal object array. +OBJECT* ObjectAllocateSlot(TPMI_DH_OBJECT* handle // OUT: handle of allocated object +); + +//*** ObjectSetLoadedAttributes() +// This function sets the internal attributes for a loaded object. It is called to +// finalize the OBJECT attributes (not the TPMA_OBJECT attributes) for a loaded +// object. +void ObjectSetLoadedAttributes(OBJECT* object, // IN: object attributes to finalize + TPM_HANDLE parentHandle // IN: the parent handle +); + +//*** ObjectLoad() +// Common function to load an object. A loaded object has its public area validated +// (unless its 'nameAlg' is TPM_ALG_NULL). If a sensitive part is loaded, it is +// verified to be correct and if both public and sensitive parts are loaded, then +// the cryptographic binding between the objects is validated. This function does +// not cause the allocated slot to be marked as in use. +TPM_RC +ObjectLoad(OBJECT* object, // IN: pointer to object slot + // object + OBJECT* parent, // IN: (optional) the parent object + TPMT_PUBLIC* publicArea, // IN: public area to be installed in the object + TPMT_SENSITIVE* sensitive, // IN: (optional) sensitive area to be + // installed in the object + TPM_RC blamePublic, // IN: parameter number to associate with the + // publicArea errors + TPM_RC blameSensitive, // IN: parameter number to associate with the + // sensitive area errors + TPM2B_NAME* name // IN: (optional) +); + +#if CC_HMAC_Start || CC_MAC_Start +//*** ObjectCreateHMACSequence() +// This function creates an internal HMAC sequence object. +// Return Type: TPM_RC +// TPM_RC_OBJECT_MEMORY if there is no free slot for an object +TPM_RC +ObjectCreateHMACSequence( + TPMI_ALG_HASH hashAlg, // IN: hash algorithm + OBJECT* keyObject, // IN: the object containing the HMAC key + TPM2B_AUTH* auth, // IN: authValue + TPMI_DH_OBJECT* newHandle // OUT: HMAC sequence object handle +); +#endif + +//*** ObjectCreateHashSequence() +// This function creates a hash sequence object. +// Return Type: TPM_RC +// TPM_RC_OBJECT_MEMORY if there is no free slot for an object +TPM_RC +ObjectCreateHashSequence(TPMI_ALG_HASH hashAlg, // IN: hash algorithm + TPM2B_AUTH* auth, // IN: authValue + TPMI_DH_OBJECT* newHandle // OUT: sequence object handle +); + +//*** ObjectCreateEventSequence() +// This function creates an event sequence object. +// Return Type: TPM_RC +// TPM_RC_OBJECT_MEMORY if there is no free slot for an object +TPM_RC +ObjectCreateEventSequence(TPM2B_AUTH* auth, // IN: authValue + TPMI_DH_OBJECT* newHandle // OUT: sequence object handle +); + +//*** ObjectTerminateEvent() +// This function is called to close out the event sequence and clean up the hash +// context states. +void ObjectTerminateEvent(void); + +//*** ObjectContextLoad() +// This function loads an object from a saved object context. +// Return Type: OBJECT * +// NULL if there is no free slot for an object +// != NULL points to the loaded object +OBJECT* ObjectContextLoad( + ANY_OBJECT_BUFFER* object, // IN: pointer to object structure in saved + // context + TPMI_DH_OBJECT* handle // OUT: object handle +); + +//*** FlushObject() +// This function frees an object slot. +// +// This function requires that the object is loaded. +void FlushObject(TPMI_DH_OBJECT handle // IN: handle to be freed +); + +//*** ObjectFlushHierarchy() +// This function is called to flush all the loaded transient objects associated +// with a hierarchy when the hierarchy is disabled. +void ObjectFlushHierarchy(TPMI_RH_HIERARCHY hierarchy // IN: hierarchy to be flush +); + +//*** ObjectLoadEvict() +// This function loads a persistent object into a transient object slot. +// +// This function requires that 'handle' is associated with a persistent object. +// Return Type: TPM_RC +// TPM_RC_HANDLE the persistent object does not exist +// or the associated hierarchy is disabled. +// TPM_RC_OBJECT_MEMORY no object slot +TPM_RC +ObjectLoadEvict(TPM_HANDLE* handle, // IN:OUT: evict object handle. If success, it + // will be replace by the loaded object handle + COMMAND_INDEX commandIndex // IN: the command being processed +); + +//*** ObjectComputeName() +// This does the name computation from a public area (can be marshaled or not). +TPM2B_NAME* ObjectComputeName(UINT32 size, // IN: the size of the area to digest + BYTE* publicArea, // IN: the public area to digest + TPM_ALG_ID nameAlg, // IN: the hash algorithm to use + TPM2B_NAME* name // OUT: Computed name +); + +//*** PublicMarshalAndComputeName() +// This function computes the Name of an object from its public area. +TPM2B_NAME* PublicMarshalAndComputeName( + TPMT_PUBLIC* publicArea, // IN: public area of an object + TPM2B_NAME* name // OUT: name of the object +); + +//*** ComputeQualifiedName() +// This function computes the qualified name of an object. +void ComputeQualifiedName( + TPM_HANDLE parentHandle, // IN: parent's handle + TPM_ALG_ID nameAlg, // IN: name hash + TPM2B_NAME* name, // IN: name of the object + TPM2B_NAME* qualifiedName // OUT: qualified name of the object +); + +//*** ObjectIsStorage() +// This function determines if an object has the attributes associated +// with a parent. A parent is an asymmetric or symmetric block cipher key +// that has its 'restricted' and 'decrypt' attributes SET, and 'sign' CLEAR. +// Return Type: BOOL +// TRUE(1) object is a storage key +// FALSE(0) object is not a storage key +BOOL ObjectIsStorage(TPMI_DH_OBJECT handle // IN: object handle +); + +//*** ObjectCapGetLoaded() +// This function returns a a list of handles of loaded object, starting from +// 'handle'. 'Handle' must be in the range of valid transient object handles, +// but does not have to be the handle of a loaded transient object. +// Return Type: TPMI_YES_NO +// YES if there are more handles available +// NO all the available handles has been returned +TPMI_YES_NO +ObjectCapGetLoaded(TPMI_DH_OBJECT handle, // IN: start handle + UINT32 count, // IN: count of returned handles + TPML_HANDLE* handleList // OUT: list of handle +); + +//*** ObjectCapGetTransientAvail() +// This function returns an estimate of the number of additional transient +// objects that could be loaded into the TPM. +UINT32 +ObjectCapGetTransientAvail(void); + +//*** ObjectGetPublicAttributes() +// Returns the attributes associated with an object handles. +TPMA_OBJECT +ObjectGetPublicAttributes(TPM_HANDLE handle); + +OBJECT_ATTRIBUTES +ObjectGetProperties(TPM_HANDLE handle); + +#endif // _OBJECT_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Object_spt_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Object_spt_fp.h new file mode 100644 index 0000000..7ee3d76 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Object_spt_fp.h @@ -0,0 +1,368 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 7, 2020 Time: 07:06:44PM + */ + +#ifndef _OBJECT_SPT_FP_H_ +#define _OBJECT_SPT_FP_H_ + +//*** AdjustAuthSize() +// This function will validate that the input authValue is no larger than the +// digestSize for the nameAlg. It will then pad with zeros to the size of the +// digest. +BOOL AdjustAuthSize(TPM2B_AUTH* auth, // IN/OUT: value to adjust + TPMI_ALG_HASH nameAlg // IN: +); + +//*** AreAttributesForParent() +// This function is called by create, load, and import functions. +// +// Note: The 'isParent' attribute is SET when an object is loaded and it has +// attributes that are suitable for a parent object. +// Return Type: BOOL +// TRUE(1) properties are those of a parent +// FALSE(0) properties are not those of a parent +BOOL ObjectIsParent(OBJECT* parentObject // IN: parent handle +); + +//*** CreateChecks() +// Attribute checks that are unique to creation. +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES sensitiveDataOrigin is not consistent with the +// object type +// other returns from PublicAttributesValidation() +TPM_RC +CreateChecks(OBJECT* parentObject, TPMT_PUBLIC* publicArea, UINT16 sensitiveDataSize); + +//*** SchemeChecks +// This function is called by TPM2_LoadExternal() and PublicAttributesValidation(). +// This function validates the schemes in the public area of an object. +// Return Type: TPM_RC +// TPM_RC_HASH non-duplicable storage key and its parent have different +// name algorithm +// TPM_RC_KDF incorrect KDF specified for decrypting keyed hash object +// TPM_RC_KEY invalid key size values in an asymmetric key public area +// TPM_RCS_SCHEME inconsistent attributes 'decrypt', 'sign', 'restricted' +// and key's scheme ID; or hash algorithm is inconsistent +// with the scheme ID for keyed hash object +// TPM_RC_SYMMETRIC a storage key with no symmetric algorithm specified; or +// non-storage key with symmetric algorithm different from +// TPM_ALG_NULL +TPM_RC +SchemeChecks(OBJECT* parentObject, // IN: parent (null if primary seed) + TPMT_PUBLIC* publicArea // IN: public area of the object +); + +//*** PublicAttributesValidation() +// This function validates the values in the public area of an object. +// This function is used in the processing of TPM2_Create, TPM2_CreatePrimary, +// TPM2_CreateLoaded(), TPM2_Load(), TPM2_Import(), and TPM2_LoadExternal(). +// For TPM2_Import() this is only used if the new parent has fixedTPM SET. For +// TPM2_LoadExternal(), this is not used for a public-only key +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES 'fixedTPM', 'fixedParent', or 'encryptedDuplication' +// attributes are inconsistent between themselves or with +// those of the parent object; +// inconsistent 'restricted', 'decrypt' and 'sign' +// attributes; +// attempt to inject sensitive data for an asymmetric key; +// attempt to create a symmetric cipher key that is not +// a decryption key +// TPM_RC_HASH nameAlg is TPM_ALG_NULL +// TPM_RC_SIZE 'authPolicy' size does not match digest size of the name +// algorithm in 'publicArea' +// other returns from SchemeChecks() +TPM_RC +PublicAttributesValidation(OBJECT* parentObject, // IN: input parent object + TPMT_PUBLIC* publicArea // IN: public area of the object +); + +//*** FillInCreationData() +// Fill in creation data for an object. +// Return Type: void +void FillInCreationData( + TPMI_DH_OBJECT parentHandle, // IN: handle of parent + TPMI_ALG_HASH nameHashAlg, // IN: name hash algorithm + TPML_PCR_SELECTION* creationPCR, // IN: PCR selection + TPM2B_DATA* outsideData, // IN: outside data + TPM2B_CREATION_DATA* outCreation, // OUT: creation data for output + TPM2B_DIGEST* creationDigest // OUT: creation digest +); + +//*** GetSeedForKDF() +// Get a seed for KDF. The KDF for encryption and HMAC key use the same seed. +const TPM2B* GetSeedForKDF(OBJECT* protector // IN: the protector handle +); + +//*** ProduceOuterWrap() +// This function produce outer wrap for a buffer containing the sensitive data. +// It requires the sensitive data being marshaled to the outerBuffer, with the +// leading bytes reserved for integrity hash. If iv is used, iv space should +// be reserved at the beginning of the buffer. It assumes the sensitive data +// starts at address (outerBuffer + integrity size @). +// This function: +// a) adds IV before sensitive area if required; +// b) encrypts sensitive data with IV or a NULL IV as required; +// c) adds HMAC integrity at the beginning of the buffer; and +// d) returns the total size of blob with outer wrap. +UINT16 +ProduceOuterWrap(OBJECT* protector, // IN: The handle of the object that provides + // protection. For object, it is parent + // handle. For credential, it is the handle + // of encrypt object. + TPM2B* name, // IN: the name of the object + TPM_ALG_ID hashAlg, // IN: hash algorithm for outer wrap + TPM2B* seed, // IN: an external seed may be provided for + // duplication blob. For non duplication + // blob, this parameter should be NULL + BOOL useIV, // IN: indicate if an IV is used + UINT16 dataSize, // IN: the size of sensitive data, excluding the + // leading integrity buffer size or the + // optional iv size + BYTE* outerBuffer // IN/OUT: outer buffer with sensitive data in + // it +); + +//*** UnwrapOuter() +// This function remove the outer wrap of a blob containing sensitive data +// This function: +// a) checks integrity of outer blob; and +// b) decrypts the outer blob. +// +// Return Type: TPM_RC +// TPM_RCS_INSUFFICIENT error during sensitive data unmarshaling +// TPM_RCS_INTEGRITY sensitive data integrity is broken +// TPM_RCS_SIZE error during sensitive data unmarshaling +// TPM_RCS_VALUE IV size for CFB does not match the encryption +// algorithm block size +TPM_RC +UnwrapOuter(OBJECT* protector, // IN: The object that provides + // protection. For object, it is parent + // handle. For credential, it is the + // encrypt object. + TPM2B* name, // IN: the name of the object + TPM_ALG_ID hashAlg, // IN: hash algorithm for outer wrap + TPM2B* seed, // IN: an external seed may be provided for + // duplication blob. For non duplication + // blob, this parameter should be NULL. + BOOL useIV, // IN: indicates if an IV is used + UINT16 dataSize, // IN: size of sensitive data in outerBuffer, + // including the leading integrity buffer + // size, and an optional iv area + BYTE* outerBuffer // IN/OUT: sensitive data +); + +//*** SensitiveToPrivate() +// This function prepare the private blob for off the chip storage +// This function: +// a) marshals TPM2B_SENSITIVE structure into the buffer of TPM2B_PRIVATE +// b) applies encryption to the sensitive area; and +// c) applies outer integrity computation. +void SensitiveToPrivate( + TPMT_SENSITIVE* sensitive, // IN: sensitive structure + TPM2B_NAME* name, // IN: the name of the object + OBJECT* parent, // IN: The parent object + TPM_ALG_ID nameAlg, // IN: hash algorithm in public area. This + // parameter is used when parentHandle is + // NULL, in which case the object is + // temporary. + TPM2B_PRIVATE* outPrivate // OUT: output private structure +); + +//*** PrivateToSensitive() +// Unwrap a input private area. Check the integrity, decrypt and retrieve data +// to a sensitive structure. +// This function: +// a) checks the integrity HMAC of the input private area; +// b) decrypts the private buffer; and +// c) unmarshals TPMT_SENSITIVE structure into the buffer of TPMT_SENSITIVE. +// Return Type: TPM_RC +// TPM_RCS_INTEGRITY if the private area integrity is bad +// TPM_RC_SENSITIVE unmarshal errors while unmarshaling TPMS_ENCRYPT +// from input private +// TPM_RCS_SIZE error during sensitive data unmarshaling +// TPM_RCS_VALUE outer wrapper does not have an iV of the correct +// size +TPM_RC +PrivateToSensitive(TPM2B* inPrivate, // IN: input private structure + TPM2B* name, // IN: the name of the object + OBJECT* parent, // IN: parent object + TPM_ALG_ID nameAlg, // IN: hash algorithm in public area. It is + // passed separately because we only pass + // name, rather than the whole public area + // of the object. This parameter is used in + // the following two cases: 1. primary + // objects. 2. duplication blob with inner + // wrap. In other cases, this parameter + // will be ignored + TPMT_SENSITIVE* sensitive // OUT: sensitive structure +); + +//*** SensitiveToDuplicate() +// This function prepare the duplication blob from the sensitive area. +// This function: +// a) marshals TPMT_SENSITIVE structure into the buffer of TPM2B_PRIVATE; +// b) applies inner wrap to the sensitive area if required; and +// c) applies outer wrap if required. +void SensitiveToDuplicate( + TPMT_SENSITIVE* sensitive, // IN: sensitive structure + TPM2B* name, // IN: the name of the object + OBJECT* parent, // IN: The new parent object + TPM_ALG_ID nameAlg, // IN: hash algorithm in public area. It + // is passed separately because we + // only pass name, rather than the + // whole public area of the object. + TPM2B* seed, // IN: the external seed. If external + // seed is provided with size of 0, + // no outer wrap should be applied + // to duplication blob. + TPMT_SYM_DEF_OBJECT* symDef, // IN: Symmetric key definition. If the + // symmetric key algorithm is NULL, + // no inner wrap should be applied. + TPM2B_DATA* innerSymKey, // IN/OUT: a symmetric key may be + // provided to encrypt the inner + // wrap of a duplication blob. May + // be generated here if needed. + TPM2B_PRIVATE* outPrivate // OUT: output private structure +); + +//*** DuplicateToSensitive() +// Unwrap a duplication blob. Check the integrity, decrypt and retrieve data +// to a sensitive structure. +// This function: +// a) checks the integrity HMAC of the input private area; +// b) decrypts the private buffer; and +// c) unmarshals TPMT_SENSITIVE structure into the buffer of TPMT_SENSITIVE. +// +// Return Type: TPM_RC +// TPM_RC_INSUFFICIENT unmarshaling sensitive data from 'inPrivate' failed +// TPM_RC_INTEGRITY 'inPrivate' data integrity is broken +// TPM_RC_SIZE unmarshaling sensitive data from 'inPrivate' failed +TPM_RC +DuplicateToSensitive( + TPM2B* inPrivate, // IN: input private structure + TPM2B* name, // IN: the name of the object + OBJECT* parent, // IN: the parent + TPM_ALG_ID nameAlg, // IN: hash algorithm in public area. + TPM2B* seed, // IN: an external seed may be provided. + // If external seed is provided with + // size of 0, no outer wrap is + // applied + TPMT_SYM_DEF_OBJECT* symDef, // IN: Symmetric key definition. If the + // symmetric key algorithm is NULL, + // no inner wrap is applied + TPM2B* innerSymKey, // IN: a symmetric key may be provided + // to decrypt the inner wrap of a + // duplication blob. + TPMT_SENSITIVE* sensitive // OUT: sensitive structure +); + +//*** SecretToCredential() +// This function prepare the credential blob from a secret (a TPM2B_DIGEST) +// This function: +// a) marshals TPM2B_DIGEST structure into the buffer of TPM2B_ID_OBJECT; +// b) encrypts the private buffer, excluding the leading integrity HMAC area; +// c) computes integrity HMAC and append to the beginning of the buffer; and +// d) sets the total size of TPM2B_ID_OBJECT buffer. +void SecretToCredential(TPM2B_DIGEST* secret, // IN: secret information + TPM2B* name, // IN: the name of the object + TPM2B* seed, // IN: an external seed. + OBJECT* protector, // IN: the protector + TPM2B_ID_OBJECT* outIDObject // OUT: output credential +); + +//*** CredentialToSecret() +// Unwrap a credential. Check the integrity, decrypt and retrieve data +// to a TPM2B_DIGEST structure. +// This function: +// a) checks the integrity HMAC of the input credential area; +// b) decrypts the credential buffer; and +// c) unmarshals TPM2B_DIGEST structure into the buffer of TPM2B_DIGEST. +// +// Return Type: TPM_RC +// TPM_RC_INSUFFICIENT error during credential unmarshaling +// TPM_RC_INTEGRITY credential integrity is broken +// TPM_RC_SIZE error during credential unmarshaling +// TPM_RC_VALUE IV size does not match the encryption algorithm +// block size +TPM_RC +CredentialToSecret(TPM2B* inIDObject, // IN: input credential blob + TPM2B* name, // IN: the name of the object + TPM2B* seed, // IN: an external seed. + OBJECT* protector, // IN: the protector + TPM2B_DIGEST* secret // OUT: secret information +); + +//*** MemoryRemoveTrailingZeros() +// This function is used to adjust the length of an authorization value. +// It adjusts the size of the TPM2B so that it does not include octets +// at the end of the buffer that contain zero. +// +// This function returns the number of non-zero octets in the buffer. +UINT16 +MemoryRemoveTrailingZeros(TPM2B_AUTH* auth // IN/OUT: value to adjust +); + +//*** SetLabelAndContext() +// This function sets the label and context for a derived key. It is possible +// that 'label' or 'context' can end up being an Empty Buffer. +TPM_RC +SetLabelAndContext(TPMS_DERIVE* labelContext, // IN/OUT: the recovered label and + // context + TPM2B_SENSITIVE_DATA* sensitive // IN: the sensitive data +); + +//*** UnmarshalToPublic() +// Support function to unmarshal the template. This is used because the +// Input may be a TPMT_TEMPLATE and that structure does not have the same +// size as a TPMT_PUBLIC because of the difference between the 'unique' and +// 'seed' fields. +// +// If 'derive' is not NULL, then the 'seed' field is assumed to contain +// a 'label' and 'context' that are unmarshaled into 'derive'. +TPM_RC +UnmarshalToPublic(TPMT_PUBLIC* tOut, // OUT: output + TPM2B_TEMPLATE* tIn, // IN: + BOOL derivation, // IN: indicates if this is for a derivation + TPMS_DERIVE* labelContext // OUT: label and context if derivation +); + +//*** ObjectSetExternal() +// Set the external attributes for an object. +void ObjectSetExternal(OBJECT* object); + +#endif // _OBJECT_SPT_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_Allocate_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_Allocate_fp.h new file mode 100644 index 0000000..d30ece0 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_Allocate_fp.h @@ -0,0 +1,70 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_PCR_Allocate // Command must be enabled + +# ifndef _PCR_Allocate_FP_H_ +# define _PCR_Allocate_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_RH_PLATFORM authHandle; + TPML_PCR_SELECTION pcrAllocation; +} PCR_Allocate_In; + +// Output structure definition +typedef struct +{ + TPMI_YES_NO allocationSuccess; + UINT32 maxPCR; + UINT32 sizeNeeded; + UINT32 sizeAvailable; +} PCR_Allocate_Out; + +// Response code modifiers +# define RC_PCR_Allocate_authHandle (TPM_RC_H + TPM_RC_1) +# define RC_PCR_Allocate_pcrAllocation (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_PCR_Allocate(PCR_Allocate_In* in, PCR_Allocate_Out* out); + +# endif // _PCR_Allocate_FP_H_ +#endif // CC_PCR_Allocate diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_Event_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_Event_fp.h new file mode 100644 index 0000000..7883722 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_Event_fp.h @@ -0,0 +1,67 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_PCR_Event // Command must be enabled + +# ifndef _PCR_Event_FP_H_ +# define _PCR_Event_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_PCR pcrHandle; + TPM2B_EVENT eventData; +} PCR_Event_In; + +// Output structure definition +typedef struct +{ + TPML_DIGEST_VALUES digests; +} PCR_Event_Out; + +// Response code modifiers +# define RC_PCR_Event_pcrHandle (TPM_RC_H + TPM_RC_1) +# define RC_PCR_Event_eventData (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_PCR_Event(PCR_Event_In* in, PCR_Event_Out* out); + +# endif // _PCR_Event_FP_H_ +#endif // CC_PCR_Event diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_Extend_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_Extend_fp.h new file mode 100644 index 0000000..52059bf --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_Extend_fp.h @@ -0,0 +1,61 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_PCR_Extend // Command must be enabled + +# ifndef _PCR_Extend_FP_H_ +# define _PCR_Extend_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_PCR pcrHandle; + TPML_DIGEST_VALUES digests; +} PCR_Extend_In; + +// Response code modifiers +# define RC_PCR_Extend_pcrHandle (TPM_RC_H + TPM_RC_1) +# define RC_PCR_Extend_digests (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_PCR_Extend(PCR_Extend_In* in); + +# endif // _PCR_Extend_FP_H_ +#endif // CC_PCR_Extend diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_Read_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_Read_fp.h new file mode 100644 index 0000000..b9592f7 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_Read_fp.h @@ -0,0 +1,67 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_PCR_Read // Command must be enabled + +# ifndef _PCR_Read_FP_H_ +# define _PCR_Read_FP_H_ + +// Input structure definition +typedef struct +{ + TPML_PCR_SELECTION pcrSelectionIn; +} PCR_Read_In; + +// Output structure definition +typedef struct +{ + UINT32 pcrUpdateCounter; + TPML_PCR_SELECTION pcrSelectionOut; + TPML_DIGEST pcrValues; +} PCR_Read_Out; + +// Response code modifiers +# define RC_PCR_Read_pcrSelectionIn (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_PCR_Read(PCR_Read_In* in, PCR_Read_Out* out); + +# endif // _PCR_Read_FP_H_ +#endif // CC_PCR_Read diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_Reset_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_Reset_fp.h new file mode 100644 index 0000000..c9b1860 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_Reset_fp.h @@ -0,0 +1,59 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_PCR_Reset // Command must be enabled + +# ifndef _PCR_Reset_FP_H_ +# define _PCR_Reset_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_PCR pcrHandle; +} PCR_Reset_In; + +// Response code modifiers +# define RC_PCR_Reset_pcrHandle (TPM_RC_H + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_PCR_Reset(PCR_Reset_In* in); + +# endif // _PCR_Reset_FP_H_ +#endif // CC_PCR_Reset diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_SetAuthPolicy_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_SetAuthPolicy_fp.h new file mode 100644 index 0000000..893835a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_SetAuthPolicy_fp.h @@ -0,0 +1,65 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_PCR_SetAuthPolicy // Command must be enabled + +# ifndef _PCR_Set_Auth_Policy_FP_H_ +# define _PCR_Set_Auth_Policy_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_RH_PLATFORM authHandle; + TPM2B_DIGEST authPolicy; + TPMI_ALG_HASH hashAlg; + TPMI_DH_PCR pcrNum; +} PCR_SetAuthPolicy_In; + +// Response code modifiers +# define RC_PCR_SetAuthPolicy_authHandle (TPM_RC_H + TPM_RC_1) +# define RC_PCR_SetAuthPolicy_authPolicy (TPM_RC_P + TPM_RC_1) +# define RC_PCR_SetAuthPolicy_hashAlg (TPM_RC_P + TPM_RC_2) +# define RC_PCR_SetAuthPolicy_pcrNum (TPM_RC_P + TPM_RC_3) + +// Function prototype +TPM_RC +TPM2_PCR_SetAuthPolicy(PCR_SetAuthPolicy_In* in); + +# endif // _PCR_Set_Auth_Policy_FP_H_ +#endif // CC_PCR_SetAuthPolicy diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_SetAuthValue_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_SetAuthValue_fp.h new file mode 100644 index 0000000..6f6507a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_SetAuthValue_fp.h @@ -0,0 +1,61 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_PCR_SetAuthValue // Command must be enabled + +# ifndef _PCR_Set_Auth_Value_FP_H_ +# define _PCR_Set_Auth_Value_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_PCR pcrHandle; + TPM2B_DIGEST auth; +} PCR_SetAuthValue_In; + +// Response code modifiers +# define RC_PCR_SetAuthValue_pcrHandle (TPM_RC_H + TPM_RC_1) +# define RC_PCR_SetAuthValue_auth (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_PCR_SetAuthValue(PCR_SetAuthValue_In* in); + +# endif // _PCR_Set_Auth_Value_FP_H_ +#endif // CC_PCR_SetAuthValue diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_fp.h new file mode 100644 index 0000000..855a432 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PCR_fp.h @@ -0,0 +1,278 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * Copyright (c) 2023-2024, NVIDIA Corporation & AFFILIATES. All rights reserved. + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 4, 2020 Time: 02:36:44PM + */ + +#ifndef _PCR_FP_H_ +#define _PCR_FP_H_ + +//*** PCRBelongsAuthGroup() +// This function indicates if a PCR belongs to a group that requires an authValue +// in order to modify the PCR. If it does, 'groupIndex' is set to value of +// the group index. This feature of PCR is decided by the platform specification. +// +// Return Type: BOOL +// TRUE(1) PCR belongs an authorization group +// FALSE(0) PCR does not belong an authorization group +BOOL PCRBelongsAuthGroup(TPMI_DH_PCR handle, // IN: handle of PCR + UINT32* groupIndex // OUT: group index if PCR belongs a + // group that allows authValue. If PCR + // does not belong to an authorization + // group, the value in this parameter is + // invalid +); + +//*** PCRBelongsPolicyGroup() +// This function indicates if a PCR belongs to a group that requires a policy +// authorization in order to modify the PCR. If it does, 'groupIndex' is set +// to value of the group index. This feature of PCR is decided by the platform +// specification. +// +// Return Type: BOOL +// TRUE(1) PCR belongs to a policy group +// FALSE(0) PCR does not belong to a policy group +BOOL PCRBelongsPolicyGroup( + TPMI_DH_PCR handle, // IN: handle of PCR + UINT32* groupIndex // OUT: group index if PCR belongs a group that + // allows policy. If PCR does not belong to + // a policy group, the value in this + // parameter is invalid +); + +//*** PCRPolicyIsAvailable() +// This function indicates if a policy is available for a PCR. +// +// Return Type: BOOL +// TRUE(1) the PCR may be authorized by policy +// FALSE(0) the PCR does not allow policy +BOOL PCRPolicyIsAvailable(TPMI_DH_PCR handle // IN: PCR handle +); + +//*** PCRGetAuthValue() +// This function is used to access the authValue of a PCR. If PCR does not +// belong to an authValue group, an EmptyAuth will be returned. +TPM2B_AUTH* PCRGetAuthValue(TPMI_DH_PCR handle // IN: PCR handle +); + +//*** PCRGetAuthPolicy() +// This function is used to access the authorization policy of a PCR. It sets +// 'policy' to the authorization policy and returns the hash algorithm for policy +// If the PCR does not allow a policy, TPM_ALG_NULL is returned. +TPMI_ALG_HASH +PCRGetAuthPolicy(TPMI_DH_PCR handle, // IN: PCR handle + TPM2B_DIGEST* policy // OUT: policy of PCR +); + +//*** PCRSimStart() +// This function is used to initialize the policies when a TPM is manufactured. +// This function would only be called in a manufacturing environment or in +// a TPM simulator. +void PCRSimStart(void); + +//*** PcrIsAllocated() +// This function indicates if a PCR number for the particular hash algorithm +// is allocated. +// Return Type: BOOL +// TRUE(1) PCR is allocated +// FALSE(0) PCR is not allocated +BOOL PcrIsAllocated(UINT32 pcr, // IN: The number of the PCR + TPMI_ALG_HASH hashAlg // IN: The PCR algorithm +); + +//*** PcrDrtm() +// This function does the DRTM and H-CRTM processing it is called from +// _TPM_Hash_End. +void PcrDrtm(const TPMI_DH_PCR pcrHandle, // IN: the index of the PCR to be + // modified + const TPMI_ALG_HASH hash, // IN: the bank identifier + const TPM2B_DIGEST* digest // IN: the digest to modify the PCR +); + +//*** PCR_ClearAuth() +// This function is used to reset the PCR authorization values. It is called +// on TPM2_Startup(CLEAR) and TPM2_Clear(). +void PCR_ClearAuth(void); + +//*** PCRStartup() +// This function initializes the PCR subsystem at TPM2_Startup(). +BOOL PCRStartup(STARTUP_TYPE type, // IN: startup type + BYTE locality // IN: startup locality +); + +//*** PCRStateSave() +// This function is used to save the PCR values that will be restored on TPM Resume. +void PCRStateSave(TPM_SU type // IN: startup type +); + +//*** PCRIsStateSaved() +// This function indicates if the selected PCR is a PCR that is state saved +// on TPM2_Shutdown(STATE). The return value is based on PCR attributes. +// Return Type: BOOL +// TRUE(1) PCR is state saved +// FALSE(0) PCR is not state saved +BOOL PCRIsStateSaved(TPMI_DH_PCR handle // IN: PCR handle to be extended +); + +//*** PCRIsResetAllowed() +// This function indicates if a PCR may be reset by the current command locality. +// The return value is based on PCR attributes, and not the PCR allocation. +// Return Type: BOOL +// TRUE(1) TPM2_PCR_Reset is allowed +// FALSE(0) TPM2_PCR_Reset is not allowed +BOOL PCRIsResetAllowed(TPMI_DH_PCR handle // IN: PCR handle to be extended +); + +//*** PCRChanged() +// This function checks a PCR handle to see if the attributes for the PCR are set +// so that any change to the PCR causes an increment of the pcrCounter. If it does, +// then the function increments the counter. Will also bump the counter if the +// handle is zero which means that PCR 0 can not be in the TCB group. Bump on zero +// is used by TPM2_Clear(). +void PCRChanged(TPM_HANDLE pcrHandle // IN: the handle of the PCR that changed. +); + +//*** PCRIsExtendAllowed() +// This function indicates a PCR may be extended at the current command locality. +// The return value is based on PCR attributes, and not the PCR allocation. +// Return Type: BOOL +// TRUE(1) extend is allowed +// FALSE(0) extend is not allowed +BOOL PCRIsExtendAllowed(TPMI_DH_PCR handle // IN: PCR handle to be extended +); + +//*** PCRExtend() +// This function is used to extend a PCR in a specific bank. +void PCRExtend(TPMI_DH_PCR handle, // IN: PCR handle to be extended + TPMI_ALG_HASH hash, // IN: hash algorithm of PCR + UINT32 size, // IN: size of data to be extended + BYTE* data // IN: data to be extended +); + +//*** PCRComputeCurrentDigest() +// This function computes the digest of the selected PCR. +// +// As a side-effect, 'selection' is modified so that only the implemented PCR +// will have their bits still set. +void PCRComputeCurrentDigest( + TPMI_ALG_HASH hashAlg, // IN: hash algorithm to compute digest + TPML_PCR_SELECTION* selection, // IN/OUT: PCR selection (filtered on + // output) + TPM2B_DIGEST* digest // OUT: digest +); + +//*** PCRRead() +// This function is used to read a list of selected PCR. If the requested PCR +// number exceeds the maximum number that can be output, the 'selection' is +// adjusted to reflect the actual output PCR. +void PCRRead(TPML_PCR_SELECTION* selection, // IN/OUT: PCR selection (filtered on + // output) + TPML_DIGEST* digest, // OUT: digest + UINT32* pcrCounter // OUT: the current value of PCR generation + // number +); + +//*** PCRAllocate() +// This function is used to change the PCR allocation. +// Return Type: TPM_RC +// TPM_RC_NO_RESULT allocate failed +// TPM_RC_PCR improper allocation +TPM_RC +PCRAllocate(TPML_PCR_SELECTION* allocate, // IN: required allocation + UINT32* maxPCR, // OUT: Maximum number of PCR + UINT32* sizeNeeded, // OUT: required space + UINT32* sizeAvailable // OUT: available space +); + +//*** PCRSetValue() +// This function is used to set the designated PCR in all banks to an initial value. +// The initial value is signed and will be sign extended into the entire PCR. +// +void PCRSetValue(TPM_HANDLE handle, // IN: the handle of the PCR to set + INT8 initialValue // IN: the value to set +); + +//*** PCRResetDynamics +// This function is used to reset a dynamic PCR to 0. This function is used in +// DRTM sequence. +void PCRResetDynamics(void); + +//*** PCRCapGetAllocation() +// This function is used to get the current allocation of PCR banks. +// Return Type: TPMI_YES_NO +// YES if the return count is 0 +// NO if the return count is not 0 +TPMI_YES_NO +PCRCapGetAllocation(UINT32 count, // IN: count of return + TPML_PCR_SELECTION* pcrSelection // OUT: PCR allocation list +); + +//*** PCRCapGetProperties() +// This function returns a list of PCR properties starting at 'property'. +// Return Type: TPMI_YES_NO +// YES if no more property is available +// NO if there are more properties not reported +TPMI_YES_NO +PCRCapGetProperties(TPM_PT_PCR property, // IN: the starting PCR property + UINT32 count, // IN: count of returned properties + TPML_TAGGED_PCR_PROPERTY* select // OUT: PCR select +); + +//*** PCRCapGetHandles() +// This function is used to get a list of handles of PCR, started from 'handle'. +// If 'handle' exceeds the maximum PCR handle range, an empty list will be +// returned and the return value will be NO. +// Return Type: TPMI_YES_NO +// YES if there are more handles available +// NO all the available handles has been returned +TPMI_YES_NO +PCRCapGetHandles(TPMI_DH_PCR handle, // IN: start handle + UINT32 count, // IN: count of returned handles + TPML_HANDLE* handleList // OUT: list of handle +); + +//*** PCRBankSave() +// This function is for fTPM TA internal use only. +// It saves the PCR values during early boot stage. +void PCRBankSave(void); + +//*** PCRBankRestore() +// This function is for fTPM TA internal use only. +// It restores the PCR values after early boot stage. +void PCRBankRestore(void); + +#endif // _PCR_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PP_Commands_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PP_Commands_fp.h new file mode 100644 index 0000000..17fb085 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PP_Commands_fp.h @@ -0,0 +1,63 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_PP_Commands // Command must be enabled + +# ifndef _PP_Commands_FP_H_ +# define _PP_Commands_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_RH_PLATFORM auth; + TPML_CC setList; + TPML_CC clearList; +} PP_Commands_In; + +// Response code modifiers +# define RC_PP_Commands_auth (TPM_RC_H + TPM_RC_1) +# define RC_PP_Commands_setList (TPM_RC_P + TPM_RC_1) +# define RC_PP_Commands_clearList (TPM_RC_P + TPM_RC_2) + +// Function prototype +TPM_RC +TPM2_PP_Commands(PP_Commands_In* in); + +# endif // _PP_Commands_FP_H_ +#endif // CC_PP_Commands diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PP_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PP_fp.h new file mode 100644 index 0000000..bdb93eb --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PP_fp.h @@ -0,0 +1,88 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 28, 2019 Time: 08:25:19PM + */ + +#ifndef _PP_FP_H_ +#define _PP_FP_H_ + +//*** PhysicalPresencePreInstall_Init() +// This function is used to initialize the array of commands that always require +// confirmation with physical presence. The array is an array of bits that +// has a correspondence with the command code. +// +// This command should only ever be executable in a manufacturing setting or in +// a simulation. +// +// When set, these cannot be cleared. +// +void PhysicalPresencePreInstall_Init(void); + +//*** PhysicalPresenceCommandSet() +// This function is used to set the indicator that a command requires +// PP confirmation. +void PhysicalPresenceCommandSet(TPM_CC commandCode // IN: command code +); + +//*** PhysicalPresenceCommandClear() +// This function is used to clear the indicator that a command requires PP +// confirmation. +void PhysicalPresenceCommandClear(TPM_CC commandCode // IN: command code +); + +//*** PhysicalPresenceIsRequired() +// This function indicates if PP confirmation is required for a command. +// Return Type: BOOL +// TRUE(1) physical presence is required +// FALSE(0) physical presence is not required +BOOL PhysicalPresenceIsRequired(COMMAND_INDEX commandIndex // IN: command index +); + +//*** PhysicalPresenceCapGetCCList() +// This function returns a list of commands that require PP confirmation. The +// list starts from the first implemented command that has a command code that +// the same or greater than 'commandCode'. +// Return Type: TPMI_YES_NO +// YES if there are more command codes available +// NO all the available command codes have been returned +TPMI_YES_NO +PhysicalPresenceCapGetCCList(TPM_CC commandCode, // IN: start command code + UINT32 count, // IN: count of returned TPM_CC + TPML_CC* commandList // OUT: list of TPM_CC +); + +#endif // _PP_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyAuthValue_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyAuthValue_fp.h new file mode 100644 index 0000000..01de032 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyAuthValue_fp.h @@ -0,0 +1,59 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_PolicyAuthValue // Command must be enabled + +# ifndef _Policy_Auth_Value_FP_H_ +# define _Policy_Auth_Value_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_SH_POLICY policySession; +} PolicyAuthValue_In; + +// Response code modifiers +# define RC_PolicyAuthValue_policySession (TPM_RC_H + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_PolicyAuthValue(PolicyAuthValue_In* in); + +# endif // _Policy_Auth_Value_FP_H_ +#endif // CC_PolicyAuthValue diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyAuthorizeNV_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyAuthorizeNV_fp.h new file mode 100644 index 0000000..9f70e9d --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyAuthorizeNV_fp.h @@ -0,0 +1,63 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_PolicyAuthorizeNV // Command must be enabled + +# ifndef _Policy_Authorize_NV_FP_H_ +# define _Policy_Authorize_NV_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_RH_NV_AUTH authHandle; + TPMI_RH_NV_INDEX nvIndex; + TPMI_SH_POLICY policySession; +} PolicyAuthorizeNV_In; + +// Response code modifiers +# define RC_PolicyAuthorizeNV_authHandle (TPM_RC_H + TPM_RC_1) +# define RC_PolicyAuthorizeNV_nvIndex (TPM_RC_H + TPM_RC_2) +# define RC_PolicyAuthorizeNV_policySession (TPM_RC_H + TPM_RC_3) + +// Function prototype +TPM_RC +TPM2_PolicyAuthorizeNV(PolicyAuthorizeNV_In* in); + +# endif // _Policy_Authorize_NV_FP_H_ +#endif // CC_PolicyAuthorizeNV diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyAuthorize_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyAuthorize_fp.h new file mode 100644 index 0000000..fddf534 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyAuthorize_fp.h @@ -0,0 +1,67 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_PolicyAuthorize // Command must be enabled + +# ifndef _Policy_Authorize_FP_H_ +# define _Policy_Authorize_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_SH_POLICY policySession; + TPM2B_DIGEST approvedPolicy; + TPM2B_NONCE policyRef; + TPM2B_NAME keySign; + TPMT_TK_VERIFIED checkTicket; +} PolicyAuthorize_In; + +// Response code modifiers +# define RC_PolicyAuthorize_policySession (TPM_RC_H + TPM_RC_1) +# define RC_PolicyAuthorize_approvedPolicy (TPM_RC_P + TPM_RC_1) +# define RC_PolicyAuthorize_policyRef (TPM_RC_P + TPM_RC_2) +# define RC_PolicyAuthorize_keySign (TPM_RC_P + TPM_RC_3) +# define RC_PolicyAuthorize_checkTicket (TPM_RC_P + TPM_RC_4) + +// Function prototype +TPM_RC +TPM2_PolicyAuthorize(PolicyAuthorize_In* in); + +# endif // _Policy_Authorize_FP_H_ +#endif // CC_PolicyAuthorize diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyCommandCode_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyCommandCode_fp.h new file mode 100644 index 0000000..9643b07 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyCommandCode_fp.h @@ -0,0 +1,61 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_PolicyCommandCode // Command must be enabled + +# ifndef _Policy_Command_Code_FP_H_ +# define _Policy_Command_Code_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_SH_POLICY policySession; + TPM_CC code; +} PolicyCommandCode_In; + +// Response code modifiers +# define RC_PolicyCommandCode_policySession (TPM_RC_H + TPM_RC_1) +# define RC_PolicyCommandCode_code (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_PolicyCommandCode(PolicyCommandCode_In* in); + +# endif // _Policy_Command_Code_FP_H_ +#endif // CC_PolicyCommandCode diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyCounterTimer_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyCounterTimer_fp.h new file mode 100644 index 0000000..91b5f52 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyCounterTimer_fp.h @@ -0,0 +1,65 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_PolicyCounterTimer // Command must be enabled + +# ifndef _Policy_Counter_Timer_FP_H_ +# define _Policy_Counter_Timer_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_SH_POLICY policySession; + TPM2B_OPERAND operandB; + UINT16 offset; + TPM_EO operation; +} PolicyCounterTimer_In; + +// Response code modifiers +# define RC_PolicyCounterTimer_policySession (TPM_RC_H + TPM_RC_1) +# define RC_PolicyCounterTimer_operandB (TPM_RC_P + TPM_RC_1) +# define RC_PolicyCounterTimer_offset (TPM_RC_P + TPM_RC_2) +# define RC_PolicyCounterTimer_operation (TPM_RC_P + TPM_RC_3) + +// Function prototype +TPM_RC +TPM2_PolicyCounterTimer(PolicyCounterTimer_In* in); + +# endif // _Policy_Counter_Timer_FP_H_ +#endif // CC_PolicyCounterTimer diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyCpHash_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyCpHash_fp.h new file mode 100644 index 0000000..6faebed --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyCpHash_fp.h @@ -0,0 +1,61 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_PolicyCpHash // Command must be enabled + +# ifndef _Policy_Cp_Hash_FP_H_ +# define _Policy_Cp_Hash_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_SH_POLICY policySession; + TPM2B_DIGEST cpHashA; +} PolicyCpHash_In; + +// Response code modifiers +# define RC_PolicyCpHash_policySession (TPM_RC_H + TPM_RC_1) +# define RC_PolicyCpHash_cpHashA (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_PolicyCpHash(PolicyCpHash_In* in); + +# endif // _Policy_Cp_Hash_FP_H_ +#endif // CC_PolicyCpHash diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyDuplicationSelect_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyDuplicationSelect_fp.h new file mode 100644 index 0000000..dab0749 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyDuplicationSelect_fp.h @@ -0,0 +1,65 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_PolicyDuplicationSelect // Command must be enabled + +# ifndef _Policy_Duplication_Select_FP_H_ +# define _Policy_Duplication_Select_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_SH_POLICY policySession; + TPM2B_NAME objectName; + TPM2B_NAME newParentName; + TPMI_YES_NO includeObject; +} PolicyDuplicationSelect_In; + +// Response code modifiers +# define RC_PolicyDuplicationSelect_policySession (TPM_RC_H + TPM_RC_1) +# define RC_PolicyDuplicationSelect_objectName (TPM_RC_P + TPM_RC_1) +# define RC_PolicyDuplicationSelect_newParentName (TPM_RC_P + TPM_RC_2) +# define RC_PolicyDuplicationSelect_includeObject (TPM_RC_P + TPM_RC_3) + +// Function prototype +TPM_RC +TPM2_PolicyDuplicationSelect(PolicyDuplicationSelect_In* in); + +# endif // _Policy_Duplication_Select_FP_H_ +#endif // CC_PolicyDuplicationSelect diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyGetDigest_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyGetDigest_fp.h new file mode 100644 index 0000000..7451c84 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyGetDigest_fp.h @@ -0,0 +1,65 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_PolicyGetDigest // Command must be enabled + +# ifndef _Policy_Get_Digest_FP_H_ +# define _Policy_Get_Digest_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_SH_POLICY policySession; +} PolicyGetDigest_In; + +// Output structure definition +typedef struct +{ + TPM2B_DIGEST policyDigest; +} PolicyGetDigest_Out; + +// Response code modifiers +# define RC_PolicyGetDigest_policySession (TPM_RC_H + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_PolicyGetDigest(PolicyGetDigest_In* in, PolicyGetDigest_Out* out); + +# endif // _Policy_Get_Digest_FP_H_ +#endif // CC_PolicyGetDigest diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyLocality_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyLocality_fp.h new file mode 100644 index 0000000..44ad3f9 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyLocality_fp.h @@ -0,0 +1,61 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_PolicyLocality // Command must be enabled + +# ifndef _Policy_Locality_FP_H_ +# define _Policy_Locality_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_SH_POLICY policySession; + TPMA_LOCALITY locality; +} PolicyLocality_In; + +// Response code modifiers +# define RC_PolicyLocality_policySession (TPM_RC_H + TPM_RC_1) +# define RC_PolicyLocality_locality (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_PolicyLocality(PolicyLocality_In* in); + +# endif // _Policy_Locality_FP_H_ +#endif // CC_PolicyLocality diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyNV_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyNV_fp.h new file mode 100644 index 0000000..21cdb86 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyNV_fp.h @@ -0,0 +1,69 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_PolicyNV // Command must be enabled + +# ifndef _Policy_NV_FP_H_ +# define _Policy_NV_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_RH_NV_AUTH authHandle; + TPMI_RH_NV_INDEX nvIndex; + TPMI_SH_POLICY policySession; + TPM2B_OPERAND operandB; + UINT16 offset; + TPM_EO operation; +} PolicyNV_In; + +// Response code modifiers +# define RC_PolicyNV_authHandle (TPM_RC_H + TPM_RC_1) +# define RC_PolicyNV_nvIndex (TPM_RC_H + TPM_RC_2) +# define RC_PolicyNV_policySession (TPM_RC_H + TPM_RC_3) +# define RC_PolicyNV_operandB (TPM_RC_P + TPM_RC_1) +# define RC_PolicyNV_offset (TPM_RC_P + TPM_RC_2) +# define RC_PolicyNV_operation (TPM_RC_P + TPM_RC_3) + +// Function prototype +TPM_RC +TPM2_PolicyNV(PolicyNV_In* in); + +# endif // _Policy_NV_FP_H_ +#endif // CC_PolicyNV diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyNameHash_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyNameHash_fp.h new file mode 100644 index 0000000..eb4d8f8 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyNameHash_fp.h @@ -0,0 +1,61 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_PolicyNameHash // Command must be enabled + +# ifndef _Policy_Name_Hash_FP_H_ +# define _Policy_Name_Hash_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_SH_POLICY policySession; + TPM2B_DIGEST nameHash; +} PolicyNameHash_In; + +// Response code modifiers +# define RC_PolicyNameHash_policySession (TPM_RC_H + TPM_RC_1) +# define RC_PolicyNameHash_nameHash (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_PolicyNameHash(PolicyNameHash_In* in); + +# endif // _Policy_Name_Hash_FP_H_ +#endif // CC_PolicyNameHash diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyNvWritten_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyNvWritten_fp.h new file mode 100644 index 0000000..1257978 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyNvWritten_fp.h @@ -0,0 +1,61 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_PolicyNvWritten // Command must be enabled + +# ifndef _Policy_Nv_Written_FP_H_ +# define _Policy_Nv_Written_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_SH_POLICY policySession; + TPMI_YES_NO writtenSet; +} PolicyNvWritten_In; + +// Response code modifiers +# define RC_PolicyNvWritten_policySession (TPM_RC_H + TPM_RC_1) +# define RC_PolicyNvWritten_writtenSet (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_PolicyNvWritten(PolicyNvWritten_In* in); + +# endif // _Policy_Nv_Written_FP_H_ +#endif // CC_PolicyNvWritten diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyOR_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyOR_fp.h new file mode 100644 index 0000000..f53c3b3 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyOR_fp.h @@ -0,0 +1,61 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_PolicyOR // Command must be enabled + +# ifndef _Policy_OR_FP_H_ +# define _Policy_OR_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_SH_POLICY policySession; + TPML_DIGEST pHashList; +} PolicyOR_In; + +// Response code modifiers +# define RC_PolicyOR_policySession (TPM_RC_H + TPM_RC_1) +# define RC_PolicyOR_pHashList (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_PolicyOR(PolicyOR_In* in); + +# endif // _Policy_OR_FP_H_ +#endif // CC_PolicyOR diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyPCR_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyPCR_fp.h new file mode 100644 index 0000000..4998b8b --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyPCR_fp.h @@ -0,0 +1,63 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_PolicyPCR // Command must be enabled + +# ifndef _Policy_PCR_FP_H_ +# define _Policy_PCR_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_SH_POLICY policySession; + TPM2B_DIGEST pcrDigest; + TPML_PCR_SELECTION pcrs; +} PolicyPCR_In; + +// Response code modifiers +# define RC_PolicyPCR_policySession (TPM_RC_H + TPM_RC_1) +# define RC_PolicyPCR_pcrDigest (TPM_RC_P + TPM_RC_1) +# define RC_PolicyPCR_pcrs (TPM_RC_P + TPM_RC_2) + +// Function prototype +TPM_RC +TPM2_PolicyPCR(PolicyPCR_In* in); + +# endif // _Policy_PCR_FP_H_ +#endif // CC_PolicyPCR diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyPassword_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyPassword_fp.h new file mode 100644 index 0000000..72abc40 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyPassword_fp.h @@ -0,0 +1,59 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_PolicyPassword // Command must be enabled + +# ifndef _Policy_Password_FP_H_ +# define _Policy_Password_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_SH_POLICY policySession; +} PolicyPassword_In; + +// Response code modifiers +# define RC_PolicyPassword_policySession (TPM_RC_H + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_PolicyPassword(PolicyPassword_In* in); + +# endif // _Policy_Password_FP_H_ +#endif // CC_PolicyPassword diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyPhysicalPresence_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyPhysicalPresence_fp.h new file mode 100644 index 0000000..7974d3c --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyPhysicalPresence_fp.h @@ -0,0 +1,59 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_PolicyPhysicalPresence // Command must be enabled + +# ifndef _Policy_Physical_Presence_FP_H_ +# define _Policy_Physical_Presence_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_SH_POLICY policySession; +} PolicyPhysicalPresence_In; + +// Response code modifiers +# define RC_PolicyPhysicalPresence_policySession (TPM_RC_H + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_PolicyPhysicalPresence(PolicyPhysicalPresence_In* in); + +# endif // _Policy_Physical_Presence_FP_H_ +#endif // CC_PolicyPhysicalPresence diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyRestart_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyRestart_fp.h new file mode 100644 index 0000000..613ce56 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyRestart_fp.h @@ -0,0 +1,59 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_PolicyRestart // Command must be enabled + +# ifndef _Policy_Restart_FP_H_ +# define _Policy_Restart_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_SH_POLICY sessionHandle; +} PolicyRestart_In; + +// Response code modifiers +# define RC_PolicyRestart_sessionHandle (TPM_RC_H + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_PolicyRestart(PolicyRestart_In* in); + +# endif // _Policy_Restart_FP_H_ +#endif // CC_PolicyRestart diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicySecret_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicySecret_fp.h new file mode 100644 index 0000000..2aaedd1 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicySecret_fp.h @@ -0,0 +1,76 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_PolicySecret // Command must be enabled + +# ifndef _Policy_Secret_FP_H_ +# define _Policy_Secret_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_ENTITY authHandle; + TPMI_SH_POLICY policySession; + TPM2B_NONCE nonceTPM; + TPM2B_DIGEST cpHashA; + TPM2B_NONCE policyRef; + INT32 expiration; +} PolicySecret_In; + +// Output structure definition +typedef struct +{ + TPM2B_TIMEOUT timeout; + TPMT_TK_AUTH policyTicket; +} PolicySecret_Out; + +// Response code modifiers +# define RC_PolicySecret_authHandle (TPM_RC_H + TPM_RC_1) +# define RC_PolicySecret_policySession (TPM_RC_H + TPM_RC_2) +# define RC_PolicySecret_nonceTPM (TPM_RC_P + TPM_RC_1) +# define RC_PolicySecret_cpHashA (TPM_RC_P + TPM_RC_2) +# define RC_PolicySecret_policyRef (TPM_RC_P + TPM_RC_3) +# define RC_PolicySecret_expiration (TPM_RC_P + TPM_RC_4) + +// Function prototype +TPM_RC +TPM2_PolicySecret(PolicySecret_In* in, PolicySecret_Out* out); + +# endif // _Policy_Secret_FP_H_ +#endif // CC_PolicySecret diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicySigned_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicySigned_fp.h new file mode 100644 index 0000000..6f8d8df --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicySigned_fp.h @@ -0,0 +1,78 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_PolicySigned // Command must be enabled + +# ifndef _Policy_Signed_FP_H_ +# define _Policy_Signed_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_OBJECT authObject; + TPMI_SH_POLICY policySession; + TPM2B_NONCE nonceTPM; + TPM2B_DIGEST cpHashA; + TPM2B_NONCE policyRef; + INT32 expiration; + TPMT_SIGNATURE auth; +} PolicySigned_In; + +// Output structure definition +typedef struct +{ + TPM2B_TIMEOUT timeout; + TPMT_TK_AUTH policyTicket; +} PolicySigned_Out; + +// Response code modifiers +# define RC_PolicySigned_authObject (TPM_RC_H + TPM_RC_1) +# define RC_PolicySigned_policySession (TPM_RC_H + TPM_RC_2) +# define RC_PolicySigned_nonceTPM (TPM_RC_P + TPM_RC_1) +# define RC_PolicySigned_cpHashA (TPM_RC_P + TPM_RC_2) +# define RC_PolicySigned_policyRef (TPM_RC_P + TPM_RC_3) +# define RC_PolicySigned_expiration (TPM_RC_P + TPM_RC_4) +# define RC_PolicySigned_auth (TPM_RC_P + TPM_RC_5) + +// Function prototype +TPM_RC +TPM2_PolicySigned(PolicySigned_In* in, PolicySigned_Out* out); + +# endif // _Policy_Signed_FP_H_ +#endif // CC_PolicySigned diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyTemplate_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyTemplate_fp.h new file mode 100644 index 0000000..f2b075c --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyTemplate_fp.h @@ -0,0 +1,61 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_PolicyTemplate // Command must be enabled + +# ifndef _Policy_Template_FP_H_ +# define _Policy_Template_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_SH_POLICY policySession; + TPM2B_DIGEST templateHash; +} PolicyTemplate_In; + +// Response code modifiers +# define RC_PolicyTemplate_policySession (TPM_RC_H + TPM_RC_1) +# define RC_PolicyTemplate_templateHash (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_PolicyTemplate(PolicyTemplate_In* in); + +# endif // _Policy_Template_FP_H_ +#endif // CC_PolicyTemplate diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyTicket_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyTicket_fp.h new file mode 100644 index 0000000..cc7e60f --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PolicyTicket_fp.h @@ -0,0 +1,69 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_PolicyTicket // Command must be enabled + +# ifndef _Policy_Ticket_FP_H_ +# define _Policy_Ticket_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_SH_POLICY policySession; + TPM2B_TIMEOUT timeout; + TPM2B_DIGEST cpHashA; + TPM2B_NONCE policyRef; + TPM2B_NAME authName; + TPMT_TK_AUTH ticket; +} PolicyTicket_In; + +// Response code modifiers +# define RC_PolicyTicket_policySession (TPM_RC_H + TPM_RC_1) +# define RC_PolicyTicket_timeout (TPM_RC_P + TPM_RC_1) +# define RC_PolicyTicket_cpHashA (TPM_RC_P + TPM_RC_2) +# define RC_PolicyTicket_policyRef (TPM_RC_P + TPM_RC_3) +# define RC_PolicyTicket_authName (TPM_RC_P + TPM_RC_4) +# define RC_PolicyTicket_ticket (TPM_RC_P + TPM_RC_5) + +// Function prototype +TPM_RC +TPM2_PolicyTicket(PolicyTicket_In* in); + +# endif // _Policy_Ticket_FP_H_ +#endif // CC_PolicyTicket diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Policy_AC_SendSelect_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Policy_AC_SendSelect_fp.h new file mode 100644 index 0000000..8b5c14e --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Policy_AC_SendSelect_fp.h @@ -0,0 +1,67 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_Policy_AC_SendSelect // Command must be enabled + +# ifndef _Policy_AC_Send_Select_FP_H_ +# define _Policy_AC_Send_Select_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_SH_POLICY policySession; + TPM2B_NAME objectName; + TPM2B_NAME authHandleName; + TPM2B_NAME acName; + TPMI_YES_NO includeObject; +} Policy_AC_SendSelect_In; + +// Response code modifiers +# define RC_Policy_AC_SendSelect_policySession (TPM_RC_H + TPM_RC_1) +# define RC_Policy_AC_SendSelect_objectName (TPM_RC_P + TPM_RC_1) +# define RC_Policy_AC_SendSelect_authHandleName (TPM_RC_P + TPM_RC_2) +# define RC_Policy_AC_SendSelect_acName (TPM_RC_P + TPM_RC_3) +# define RC_Policy_AC_SendSelect_includeObject (TPM_RC_P + TPM_RC_4) + +// Function prototype +TPM_RC +TPM2_Policy_AC_SendSelect(Policy_AC_SendSelect_In* in); + +# endif // _Policy_AC_Send_Select_FP_H_ +#endif // CC_Policy_AC_SendSelect diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Policy_spt_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Policy_spt_fp.h new file mode 100644 index 0000000..1f0cf40 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Policy_spt_fp.h @@ -0,0 +1,92 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 4, 2020 Time: 02:36:44PM + */ + +#ifndef _POLICY_SPT_FP_H_ +#define _POLICY_SPT_FP_H_ + +//** Functions +//*** PolicyParameterChecks() +// This function validates the common parameters of TPM2_PolicySiged() +// and TPM2_PolicySecret(). The common parameters are 'nonceTPM', +// 'expiration', and 'cpHashA'. +TPM_RC +PolicyParameterChecks(SESSION* session, + UINT64 authTimeout, + TPM2B_DIGEST* cpHashA, + TPM2B_NONCE* nonce, + TPM_RC blameNonce, + TPM_RC blameCpHash, + TPM_RC blameExpiration); + +//*** PolicyContextUpdate() +// Update policy hash +// Update the policyDigest in policy session by extending policyRef and +// objectName to it. This will also update the cpHash if it is present. +// +// Return Type: void +void PolicyContextUpdate( + TPM_CC commandCode, // IN: command code + TPM2B_NAME* name, // IN: name of entity + TPM2B_NONCE* ref, // IN: the reference data + TPM2B_DIGEST* cpHash, // IN: the cpHash (optional) + UINT64 policyTimeout, // IN: the timeout value for the policy + SESSION* session // IN/OUT: policy session to be updated +); + +//*** ComputeAuthTimeout() +// This function is used to determine what the authorization timeout value for +// the session should be. +UINT64 +ComputeAuthTimeout(SESSION* session, // IN: the session containing the time + // values + INT32 expiration, // IN: either the number of seconds from + // the start of the session or the + // time in g_timer; + TPM2B_NONCE* nonce // IN: indicator of the time base +); + +//*** PolicyDigestClear() +// Function to reset the policyDigest of a session +void PolicyDigestClear(SESSION* session); + +//*** PolicySptCheckCondition() +// Checks to see if the condition in the policy is satisfied. +BOOL PolicySptCheckCondition(TPM_EO operation, BYTE* opA, BYTE* opB, UINT16 size); + +#endif // _POLICY_SPT_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Power_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Power_fp.h new file mode 100644 index 0000000..6c61c36 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Power_fp.h @@ -0,0 +1,60 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Apr 2, 2019 Time: 11:00:49AM + */ + +#ifndef _POWER_FP_H_ +#define _POWER_FP_H_ + +//*** TPMInit() +// This function is used to process a power on event. +void TPMInit(void); + +//*** TPMRegisterStartup() +// This function registers the fact that the TPM has been initialized +// (a TPM2_Startup() has completed successfully). +BOOL TPMRegisterStartup(void); + +//*** TPMIsStarted() +// Indicates if the TPM has been initialized (a TPM2_Startup() has completed +// successfully after a _TPM_Init). +// Return Type: BOOL +// TRUE(1) TPM has been initialized +// FALSE(0) TPM has not been initialized +BOOL TPMIsStarted(void); + +#endif // _POWER_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PropertyCap_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PropertyCap_fp.h new file mode 100644 index 0000000..ea4d7c4 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/PropertyCap_fp.h @@ -0,0 +1,58 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 28, 2019 Time: 08:25:19PM + */ + +#ifndef _PROPERTY_CAP_FP_H_ +#define _PROPERTY_CAP_FP_H_ + +//*** TPMCapGetProperties() +// This function is used to get the TPM_PT values. The search of properties will +// start at 'property' and continue until 'propertyList' has as many values as +// will fit, or the last property has been reported, or the list has as many +// values as requested in 'count'. +// Return Type: TPMI_YES_NO +// YES more properties are available +// NO no more properties to be reported +TPMI_YES_NO +TPMCapGetProperties(TPM_PT property, // IN: the starting TPM property + UINT32 count, // IN: maximum number of returned + // properties + TPML_TAGGED_TPM_PROPERTY* propertyList // OUT: property list +); + +#endif // _PROPERTY_CAP_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Quote_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Quote_fp.h new file mode 100644 index 0000000..d02ef64 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Quote_fp.h @@ -0,0 +1,72 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_Quote // Command must be enabled + +# ifndef _Quote_FP_H_ +# define _Quote_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_OBJECT signHandle; + TPM2B_DATA qualifyingData; + TPMT_SIG_SCHEME inScheme; + TPML_PCR_SELECTION PCRselect; +} Quote_In; + +// Output structure definition +typedef struct +{ + TPM2B_ATTEST quoted; + TPMT_SIGNATURE signature; +} Quote_Out; + +// Response code modifiers +# define RC_Quote_signHandle (TPM_RC_H + TPM_RC_1) +# define RC_Quote_qualifyingData (TPM_RC_P + TPM_RC_1) +# define RC_Quote_inScheme (TPM_RC_P + TPM_RC_2) +# define RC_Quote_PCRselect (TPM_RC_P + TPM_RC_3) + +// Function prototype +TPM_RC +TPM2_Quote(Quote_In* in, Quote_Out* out); + +# endif // _Quote_FP_H_ +#endif // CC_Quote diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/RSA_Decrypt_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/RSA_Decrypt_fp.h new file mode 100644 index 0000000..a35d400 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/RSA_Decrypt_fp.h @@ -0,0 +1,71 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_RSA_Decrypt // Command must be enabled + +# ifndef _RSA_Decrypt_FP_H_ +# define _RSA_Decrypt_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_OBJECT keyHandle; + TPM2B_PUBLIC_KEY_RSA cipherText; + TPMT_RSA_DECRYPT inScheme; + TPM2B_DATA label; +} RSA_Decrypt_In; + +// Output structure definition +typedef struct +{ + TPM2B_PUBLIC_KEY_RSA message; +} RSA_Decrypt_Out; + +// Response code modifiers +# define RC_RSA_Decrypt_keyHandle (TPM_RC_H + TPM_RC_1) +# define RC_RSA_Decrypt_cipherText (TPM_RC_P + TPM_RC_1) +# define RC_RSA_Decrypt_inScheme (TPM_RC_P + TPM_RC_2) +# define RC_RSA_Decrypt_label (TPM_RC_P + TPM_RC_3) + +// Function prototype +TPM_RC +TPM2_RSA_Decrypt(RSA_Decrypt_In* in, RSA_Decrypt_Out* out); + +# endif // _RSA_Decrypt_FP_H_ +#endif // CC_RSA_Decrypt diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/RSA_Encrypt_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/RSA_Encrypt_fp.h new file mode 100644 index 0000000..dccf30b --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/RSA_Encrypt_fp.h @@ -0,0 +1,71 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_RSA_Encrypt // Command must be enabled + +# ifndef _RSA_Encrypt_FP_H_ +# define _RSA_Encrypt_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_OBJECT keyHandle; + TPM2B_PUBLIC_KEY_RSA message; + TPMT_RSA_DECRYPT inScheme; + TPM2B_DATA label; +} RSA_Encrypt_In; + +// Output structure definition +typedef struct +{ + TPM2B_PUBLIC_KEY_RSA outData; +} RSA_Encrypt_Out; + +// Response code modifiers +# define RC_RSA_Encrypt_keyHandle (TPM_RC_H + TPM_RC_1) +# define RC_RSA_Encrypt_message (TPM_RC_P + TPM_RC_1) +# define RC_RSA_Encrypt_inScheme (TPM_RC_P + TPM_RC_2) +# define RC_RSA_Encrypt_label (TPM_RC_P + TPM_RC_3) + +// Function prototype +TPM_RC +TPM2_RSA_Encrypt(RSA_Encrypt_In* in, RSA_Encrypt_Out* out); + +# endif // _RSA_Encrypt_FP_H_ +#endif // CC_RSA_Encrypt diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ReadClock_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ReadClock_fp.h new file mode 100644 index 0000000..ef301f7 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ReadClock_fp.h @@ -0,0 +1,56 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_ReadClock // Command must be enabled + +# ifndef _Read_Clock_FP_H_ +# define _Read_Clock_FP_H_ + +// Output structure definition +typedef struct +{ + TPMS_TIME_INFO currentTime; +} ReadClock_Out; + +// Function prototype +TPM_RC +TPM2_ReadClock(ReadClock_Out* out); + +# endif // _Read_Clock_FP_H_ +#endif // CC_ReadClock diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ReadPublic_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ReadPublic_fp.h new file mode 100644 index 0000000..099676e --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ReadPublic_fp.h @@ -0,0 +1,67 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_ReadPublic // Command must be enabled + +# ifndef _Read_Public_FP_H_ +# define _Read_Public_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_OBJECT objectHandle; +} ReadPublic_In; + +// Output structure definition +typedef struct +{ + TPM2B_PUBLIC outPublic; + TPM2B_NAME name; + TPM2B_NAME qualifiedName; +} ReadPublic_Out; + +// Response code modifiers +# define RC_ReadPublic_objectHandle (TPM_RC_H + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_ReadPublic(ReadPublic_In* in, ReadPublic_Out* out); + +# endif // _Read_Public_FP_H_ +#endif // CC_ReadPublic diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ResponseCodeProcessing_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ResponseCodeProcessing_fp.h new file mode 100644 index 0000000..ec4b83a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ResponseCodeProcessing_fp.h @@ -0,0 +1,49 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 28, 2019 Time: 08:25:19PM + */ + +#ifndef _RESPONSE_CODE_PROCESSING_FP_H_ +#define _RESPONSE_CODE_PROCESSING_FP_H_ + +//** RcSafeAddToResult() +// Adds a modifier to a response code as long as the response code allows a modifier +// and no modifier has already been added. +TPM_RC +RcSafeAddToResult(TPM_RC responseCode, TPM_RC modifier); + +#endif // _RESPONSE_CODE_PROCESSING_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Response_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Response_fp.h new file mode 100644 index 0000000..d054742 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Response_fp.h @@ -0,0 +1,51 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 28, 2019 Time: 08:25:19PM + */ + +#ifndef _RESPONSE_FP_H_ +#define _RESPONSE_FP_H_ + +//** BuildResponseHeader() +// Adds the response header to the response. It will update command->parameterSize +// to indicate the total size of the response. +void BuildResponseHeader(COMMAND* command, // IN: main control structure + BYTE* buffer, // OUT: the output buffer + TPM_RC result // IN: the response code +); + +#endif // _RESPONSE_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Rewrap_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Rewrap_fp.h new file mode 100644 index 0000000..4e20855 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Rewrap_fp.h @@ -0,0 +1,74 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_Rewrap // Command must be enabled + +# ifndef _Rewrap_FP_H_ +# define _Rewrap_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_OBJECT oldParent; + TPMI_DH_OBJECT newParent; + TPM2B_PRIVATE inDuplicate; + TPM2B_NAME name; + TPM2B_ENCRYPTED_SECRET inSymSeed; +} Rewrap_In; + +// Output structure definition +typedef struct +{ + TPM2B_PRIVATE outDuplicate; + TPM2B_ENCRYPTED_SECRET outSymSeed; +} Rewrap_Out; + +// Response code modifiers +# define RC_Rewrap_oldParent (TPM_RC_H + TPM_RC_1) +# define RC_Rewrap_newParent (TPM_RC_H + TPM_RC_2) +# define RC_Rewrap_inDuplicate (TPM_RC_P + TPM_RC_1) +# define RC_Rewrap_name (TPM_RC_P + TPM_RC_2) +# define RC_Rewrap_inSymSeed (TPM_RC_P + TPM_RC_3) + +// Function prototype +TPM_RC +TPM2_Rewrap(Rewrap_In* in, Rewrap_Out* out); + +# endif // _Rewrap_FP_H_ +#endif // CC_Rewrap diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/RsaKeyCache_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/RsaKeyCache_fp.h new file mode 100644 index 0000000..030ecd8 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/RsaKeyCache_fp.h @@ -0,0 +1,60 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 28, 2019 Time: 08:25:19PM + */ + +#ifndef _RSA_KEY_CACHE_FP_H_ +#define _RSA_KEY_CACHE_FP_H_ + +#if USE_RSA_KEY_CACHE + +//*** RsaKeyCacheControl() +// Used to enable and disable the RSA key cache. +LIB_EXPORT void RsaKeyCacheControl(int state); + +//*** GetCachedRsaKey() +// Return Type: BOOL +// TRUE(1) key loaded +// FALSE(0) key not loaded +BOOL GetCachedRsaKey(TPMT_PUBLIC* publicArea, + TPMT_SENSITIVE* sensitive, + RAND_STATE* rand // IN: if not NULL, the deterministic + // RNG state +); +#endif // defined SIMULATION && defined USE_RSA_KEY_CACHE + +#endif // _RSA_KEY_CACHE_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SelfTest_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SelfTest_fp.h new file mode 100644 index 0000000..a4277c6 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SelfTest_fp.h @@ -0,0 +1,59 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_SelfTest // Command must be enabled + +# ifndef _Self_Test_FP_H_ +# define _Self_Test_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_YES_NO fullTest; +} SelfTest_In; + +// Response code modifiers +# define RC_SelfTest_fullTest (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_SelfTest(SelfTest_In* in); + +# endif // _Self_Test_FP_H_ +#endif // CC_SelfTest diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SequenceComplete_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SequenceComplete_fp.h new file mode 100644 index 0000000..f2be48b --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SequenceComplete_fp.h @@ -0,0 +1,70 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_SequenceComplete // Command must be enabled + +# ifndef _Sequence_Complete_FP_H_ +# define _Sequence_Complete_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_OBJECT sequenceHandle; + TPM2B_MAX_BUFFER buffer; + TPMI_RH_HIERARCHY hierarchy; +} SequenceComplete_In; + +// Output structure definition +typedef struct +{ + TPM2B_DIGEST result; + TPMT_TK_HASHCHECK validation; +} SequenceComplete_Out; + +// Response code modifiers +# define RC_SequenceComplete_sequenceHandle (TPM_RC_H + TPM_RC_1) +# define RC_SequenceComplete_buffer (TPM_RC_P + TPM_RC_1) +# define RC_SequenceComplete_hierarchy (TPM_RC_P + TPM_RC_2) + +// Function prototype +TPM_RC +TPM2_SequenceComplete(SequenceComplete_In* in, SequenceComplete_Out* out); + +# endif // _Sequence_Complete_FP_H_ +#endif // CC_SequenceComplete diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SequenceUpdate_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SequenceUpdate_fp.h new file mode 100644 index 0000000..8f258d3 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SequenceUpdate_fp.h @@ -0,0 +1,61 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_SequenceUpdate // Command must be enabled + +# ifndef _Sequence_Update_FP_H_ +# define _Sequence_Update_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_OBJECT sequenceHandle; + TPM2B_MAX_BUFFER buffer; +} SequenceUpdate_In; + +// Response code modifiers +# define RC_SequenceUpdate_sequenceHandle (TPM_RC_H + TPM_RC_1) +# define RC_SequenceUpdate_buffer (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_SequenceUpdate(SequenceUpdate_In* in); + +# endif // _Sequence_Update_FP_H_ +#endif // CC_SequenceUpdate diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SessionProcess_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SessionProcess_fp.h new file mode 100644 index 0000000..bdf007b --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SessionProcess_fp.h @@ -0,0 +1,110 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 7, 2020 Time: 07:17:48PM + */ + +#ifndef _SESSION_PROCESS_FP_H_ +#define _SESSION_PROCESS_FP_H_ + +//*** IsDAExempted() +// This function indicates if a handle is exempted from DA logic. +// A handle is exempted if it is: +// a) a primary seed handle; +// b) an object with noDA bit SET; +// c) an NV Index with TPMA_NV_NO_DA bit SET; or +// d) a PCR handle. +// +// Return Type: BOOL +// TRUE(1) handle is exempted from DA logic +// FALSE(0) handle is not exempted from DA logic +BOOL IsDAExempted(TPM_HANDLE handle // IN: entity handle +); + +//*** ClearCpRpHashes() +void ClearCpRpHashes(COMMAND* command); + +//*** CompareNameHash() +// This function computes the name hash and compares it to the nameHash in the +// session data. +BOOL CompareNameHash(COMMAND* command, // IN: main parsing structure + SESSION* session // IN: session structure with nameHash +); + +//*** ParseSessionBuffer() +// This function is the entry function for command session processing. +// It iterates sessions in session area and reports if the required authorization +// has been properly provided. It also processes audit session and passes the +// information of encryption sessions to parameter encryption module. +// +// Return Type: TPM_RC +// various parsing failure or authorization failure +// +TPM_RC +ParseSessionBuffer(COMMAND* command // IN: the structure that contains +); + +//*** CheckAuthNoSession() +// Function to process a command with no session associated. +// The function makes sure all the handles in the command require no authorization. +// +// Return Type: TPM_RC +// TPM_RC_AUTH_MISSING failure - one or more handles require +// authorization +TPM_RC +CheckAuthNoSession(COMMAND* command // IN: command parsing structure +); + +//*** BuildResponseSession() +// Function to build Session buffer in a response. The authorization data is added +// to the end of command->responseBuffer. The size of the authorization area is +// accumulated in command->authSize. +// When this is called, command->responseBuffer is pointing at the next location +// in the response buffer to be filled. This is where the authorization sessions +// will go, if any. command->parameterSize is the number of bytes that have been +// marshaled as parameters in the output buffer. +TPM_RC +BuildResponseSession(COMMAND* command // IN: structure that has relevant command + // information +); + +//*** SessionRemoveAssociationToHandle() +// This function deals with the case where an entity associated with an authorization +// is deleted during command processing. The primary use of this is to support +// UndefineSpaceSpecial(). +void SessionRemoveAssociationToHandle(TPM_HANDLE handle); + +#endif // _SESSION_PROCESS_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Session_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Session_fp.h new file mode 100644 index 0000000..02381ad --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Session_fp.h @@ -0,0 +1,254 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 4, 2020 Time: 02:36:44PM + */ + +#ifndef _SESSION_FP_H_ +#define _SESSION_FP_H_ + +//** Startup Function -- SessionStartup() +// This function initializes the session subsystem on TPM2_Startup(). +BOOL SessionStartup(STARTUP_TYPE type); + +//*** SessionIsLoaded() +// This function test a session handle references a loaded session. The handle +// must have previously been checked to make sure that it is a valid handle for +// an authorization session. +// NOTE: A PWAP authorization does not have a session. +// +// Return Type: BOOL +// TRUE(1) session is loaded +// FALSE(0) session is not loaded +// +BOOL SessionIsLoaded(TPM_HANDLE handle // IN: session handle +); + +//*** SessionIsSaved() +// This function test a session handle references a saved session. The handle +// must have previously been checked to make sure that it is a valid handle for +// an authorization session. +// NOTE: An password authorization does not have a session. +// +// This function requires that the handle be a valid session handle. +// +// Return Type: BOOL +// TRUE(1) session is saved +// FALSE(0) session is not saved +// +BOOL SessionIsSaved(TPM_HANDLE handle // IN: session handle +); + +//*** SequenceNumberForSavedContextIsValid() +// This function validates that the sequence number and handle value within a +// saved context are valid. +BOOL SequenceNumberForSavedContextIsValid( + TPMS_CONTEXT* context // IN: pointer to a context structure to be + // validated +); + +//*** SessionPCRValueIsCurrent() +// +// This function is used to check if PCR values have been updated since the +// last time they were checked in a policy session. +// +// This function requires the session is loaded. +// Return Type: BOOL +// TRUE(1) PCR value is current +// FALSE(0) PCR value is not current +BOOL SessionPCRValueIsCurrent(SESSION* session // IN: session structure +); + +//*** SessionGet() +// This function returns a pointer to the session object associated with a +// session handle. +// +// The function requires that the session is loaded. +SESSION* SessionGet(TPM_HANDLE handle // IN: session handle +); + +//*** SessionCreate() +// +// This function does the detailed work for starting an authorization session. +// This is done in a support routine rather than in the action code because +// the session management may differ in implementations. This implementation +// uses a fixed memory allocation to hold sessions and a fixed allocation +// to hold the contextID for the saved contexts. +// +// Return Type: TPM_RC +// TPM_RC_CONTEXT_GAP need to recycle sessions +// TPM_RC_SESSION_HANDLE active session space is full +// TPM_RC_SESSION_MEMORY loaded session space is full +TPM_RC +SessionCreate(TPM_SE sessionType, // IN: the session type + TPMI_ALG_HASH authHash, // IN: the hash algorithm + TPM2B_NONCE* nonceCaller, // IN: initial nonceCaller + TPMT_SYM_DEF* symmetric, // IN: the symmetric algorithm + TPMI_DH_ENTITY bind, // IN: the bind object + TPM2B_DATA* seed, // IN: seed data + TPM_HANDLE* sessionHandle, // OUT: the session handle + TPM2B_NONCE* nonceTpm // OUT: the session nonce +); + +//*** SessionContextSave() +// This function is called when a session context is to be saved. The +// contextID of the saved session is returned. If no contextID can be +// assigned, then the routine returns TPM_RC_CONTEXT_GAP. +// If the function completes normally, the session slot will be freed. +// +// This function requires that 'handle' references a loaded session. +// Otherwise, it should not be called at the first place. +// +// Return Type: TPM_RC +// TPM_RC_CONTEXT_GAP a contextID could not be assigned +// TPM_RC_TOO_MANY_CONTEXTS the counter maxed out +// +TPM_RC +SessionContextSave(TPM_HANDLE handle, // IN: session handle + CONTEXT_COUNTER* contextID // OUT: assigned contextID +); + +//*** SessionContextLoad() +// This function is used to load a session from saved context. The session +// handle must be for a saved context. +// +// If the gap is at a maximum, then the only session that can be loaded is +// the oldest session, otherwise TPM_RC_CONTEXT_GAP is returned. +/// +// This function requires that 'handle' references a valid saved session. +// +// Return Type: TPM_RC +// TPM_RC_SESSION_MEMORY no free session slots +// TPM_RC_CONTEXT_GAP the gap count is maximum and this +// is not the oldest saved context +// +TPM_RC +SessionContextLoad(SESSION_BUF* session, // IN: session structure from saved context + TPM_HANDLE* handle // IN/OUT: session handle +); + +//*** SessionFlush() +// This function is used to flush a session referenced by its handle. If the +// session associated with 'handle' is loaded, the session array entry is +// marked as available. +// +// This function requires that 'handle' be a valid active session. +// +void SessionFlush(TPM_HANDLE handle // IN: loaded or saved session handle +); + +//*** SessionComputeBoundEntity() +// This function computes the binding value for a session. The binding value +// for a reserved handle is the handle itself. For all the other entities, +// the authValue at the time of binding is included to prevent squatting. +// For those values, the Name and the authValue are concatenated +// into the bind buffer. If they will not both fit, the will be overlapped +// by XORing bytes. If XOR is required, the bind value will be full. +void SessionComputeBoundEntity(TPMI_DH_ENTITY entityHandle, // IN: handle of entity + TPM2B_NAME* bind // OUT: binding value +); + +//*** SessionSetStartTime() +// This function is used to initialize the session timing +void SessionSetStartTime(SESSION* session // IN: the session to update +); + +//*** SessionResetPolicyData() +// This function is used to reset the policy data without changing the nonce +// or the start time of the session. +void SessionResetPolicyData(SESSION* session // IN: the session to reset +); + +//*** SessionCapGetLoaded() +// This function returns a list of handles of loaded session, started +// from input 'handle' +// +// 'Handle' must be in valid loaded session handle range, but does not +// have to point to a loaded session. +// Return Type: TPMI_YES_NO +// YES if there are more handles available +// NO all the available handles has been returned +TPMI_YES_NO +SessionCapGetLoaded(TPMI_SH_POLICY handle, // IN: start handle + UINT32 count, // IN: count of returned handles + TPML_HANDLE* handleList // OUT: list of handle +); + +//*** SessionCapGetSaved() +// This function returns a list of handles for saved session, starting at +// 'handle'. +// +// 'Handle' must be in a valid handle range, but does not have to point to a +// saved session +// +// Return Type: TPMI_YES_NO +// YES if there are more handles available +// NO all the available handles has been returned +TPMI_YES_NO +SessionCapGetSaved(TPMI_SH_HMAC handle, // IN: start handle + UINT32 count, // IN: count of returned handles + TPML_HANDLE* handleList // OUT: list of handle +); + +//*** SessionCapGetLoadedNumber() +// This function return the number of authorization sessions currently +// loaded into TPM RAM. +UINT32 +SessionCapGetLoadedNumber(void); + +//*** SessionCapGetLoadedAvail() +// This function returns the number of additional authorization sessions, of +// any type, that could be loaded into TPM RAM. +// NOTE: In other implementations, this number may just be an estimate. The only +// requirement for the estimate is, if it is one or more, then at least one +// session must be loadable. +UINT32 +SessionCapGetLoadedAvail(void); + +//*** SessionCapGetActiveNumber() +// This function returns the number of active authorization sessions currently +// being tracked by the TPM. +UINT32 +SessionCapGetActiveNumber(void); + +//*** SessionCapGetActiveAvail() +// This function returns the number of additional authorization sessions, of any +// type, that could be created. This not the number of slots for sessions, but +// the number of additional sessions that the TPM is capable of tracking. +UINT32 +SessionCapGetActiveAvail(void); + +#endif // _SESSION_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SetAlgorithmSet_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SetAlgorithmSet_fp.h new file mode 100644 index 0000000..8136ee1 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SetAlgorithmSet_fp.h @@ -0,0 +1,61 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_SetAlgorithmSet // Command must be enabled + +# ifndef _Set_Algorithm_Set_FP_H_ +# define _Set_Algorithm_Set_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_RH_PLATFORM authHandle; + UINT32 algorithmSet; +} SetAlgorithmSet_In; + +// Response code modifiers +# define RC_SetAlgorithmSet_authHandle (TPM_RC_H + TPM_RC_1) +# define RC_SetAlgorithmSet_algorithmSet (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_SetAlgorithmSet(SetAlgorithmSet_In* in); + +# endif // _Set_Algorithm_Set_FP_H_ +#endif // CC_SetAlgorithmSet diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SetCommandCodeAuditStatus_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SetCommandCodeAuditStatus_fp.h new file mode 100644 index 0000000..30013c5 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SetCommandCodeAuditStatus_fp.h @@ -0,0 +1,65 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_SetCommandCodeAuditStatus // Command must be enabled + +# ifndef _Set_Command_Code_Audit_Status_FP_H_ +# define _Set_Command_Code_Audit_Status_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_RH_PROVISION auth; + TPMI_ALG_HASH auditAlg; + TPML_CC setList; + TPML_CC clearList; +} SetCommandCodeAuditStatus_In; + +// Response code modifiers +# define RC_SetCommandCodeAuditStatus_auth (TPM_RC_H + TPM_RC_1) +# define RC_SetCommandCodeAuditStatus_auditAlg (TPM_RC_P + TPM_RC_1) +# define RC_SetCommandCodeAuditStatus_setList (TPM_RC_P + TPM_RC_2) +# define RC_SetCommandCodeAuditStatus_clearList (TPM_RC_P + TPM_RC_3) + +// Function prototype +TPM_RC +TPM2_SetCommandCodeAuditStatus(SetCommandCodeAuditStatus_In* in); + +# endif // _Set_Command_Code_Audit_Status_FP_H_ +#endif // CC_SetCommandCodeAuditStatus diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SetPrimaryPolicy_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SetPrimaryPolicy_fp.h new file mode 100644 index 0000000..352eadf --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/SetPrimaryPolicy_fp.h @@ -0,0 +1,63 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Oct 2, 2019 Time: 07:41:19PM + */ + +#if CC_SetPrimaryPolicy // Command must be enabled + +# ifndef _SETPRIMARYPOLICY_FP_H_ +# define _SETPRIMARYPOLICY_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_RH_HIERARCHY_POLICY authHandle; + TPM2B_DIGEST authPolicy; + TPMI_ALG_HASH hashAlg; +} SetPrimaryPolicy_In; + +// Response code modifiers +# define RC_SetPrimaryPolicy_authHandle (TPM_RC_H + TPM_RC_1) +# define RC_SetPrimaryPolicy_authPolicy (TPM_RC_P + TPM_RC_1) +# define RC_SetPrimaryPolicy_hashAlg (TPM_RC_P + TPM_RC_2) + +// Function prototype +TPM_RC +TPM2_SetPrimaryPolicy(SetPrimaryPolicy_In* in); + +# endif // _SETPRIMARYPOLICY_FP_H_ +#endif // CC_SetPrimaryPolicy diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Shutdown_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Shutdown_fp.h new file mode 100644 index 0000000..41c28e7 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Shutdown_fp.h @@ -0,0 +1,59 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_Shutdown // Command must be enabled + +# ifndef _Shutdown_FP_H_ +# define _Shutdown_FP_H_ + +// Input structure definition +typedef struct +{ + TPM_SU shutdownType; +} Shutdown_In; + +// Response code modifiers +# define RC_Shutdown_shutdownType (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_Shutdown(Shutdown_In* in); + +# endif // _Shutdown_FP_H_ +#endif // CC_Shutdown diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Sign_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Sign_fp.h new file mode 100644 index 0000000..f3a873e --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Sign_fp.h @@ -0,0 +1,71 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_Sign // Command must be enabled + +# ifndef _Sign_FP_H_ +# define _Sign_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_OBJECT keyHandle; + TPM2B_DIGEST digest; + TPMT_SIG_SCHEME inScheme; + TPMT_TK_HASHCHECK validation; +} Sign_In; + +// Output structure definition +typedef struct +{ + TPMT_SIGNATURE signature; +} Sign_Out; + +// Response code modifiers +# define RC_Sign_keyHandle (TPM_RC_H + TPM_RC_1) +# define RC_Sign_digest (TPM_RC_P + TPM_RC_1) +# define RC_Sign_inScheme (TPM_RC_P + TPM_RC_2) +# define RC_Sign_validation (TPM_RC_P + TPM_RC_3) + +// Function prototype +TPM_RC +TPM2_Sign(Sign_In* in, Sign_Out* out); + +# endif // _Sign_FP_H_ +#endif // CC_Sign diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/StartAuthSession_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/StartAuthSession_fp.h new file mode 100644 index 0000000..294ce5a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/StartAuthSession_fp.h @@ -0,0 +1,78 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_StartAuthSession // Command must be enabled + +# ifndef _Start_Auth_Session_FP_H_ +# define _Start_Auth_Session_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_OBJECT tpmKey; + TPMI_DH_ENTITY bind; + TPM2B_NONCE nonceCaller; + TPM2B_ENCRYPTED_SECRET encryptedSalt; + TPM_SE sessionType; + TPMT_SYM_DEF symmetric; + TPMI_ALG_HASH authHash; +} StartAuthSession_In; + +// Output structure definition +typedef struct +{ + TPMI_SH_AUTH_SESSION sessionHandle; + TPM2B_NONCE nonceTPM; +} StartAuthSession_Out; + +// Response code modifiers +# define RC_StartAuthSession_tpmKey (TPM_RC_H + TPM_RC_1) +# define RC_StartAuthSession_bind (TPM_RC_H + TPM_RC_2) +# define RC_StartAuthSession_nonceCaller (TPM_RC_P + TPM_RC_1) +# define RC_StartAuthSession_encryptedSalt (TPM_RC_P + TPM_RC_2) +# define RC_StartAuthSession_sessionType (TPM_RC_P + TPM_RC_3) +# define RC_StartAuthSession_symmetric (TPM_RC_P + TPM_RC_4) +# define RC_StartAuthSession_authHash (TPM_RC_P + TPM_RC_5) + +// Function prototype +TPM_RC +TPM2_StartAuthSession(StartAuthSession_In* in, StartAuthSession_Out* out); + +# endif // _Start_Auth_Session_FP_H_ +#endif // CC_StartAuthSession diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Startup_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Startup_fp.h new file mode 100644 index 0000000..5e4b1e3 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Startup_fp.h @@ -0,0 +1,59 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_Startup // Command must be enabled + +# ifndef _Startup_FP_H_ +# define _Startup_FP_H_ + +// Input structure definition +typedef struct +{ + TPM_SU startupType; +} Startup_In; + +// Response code modifiers +# define RC_Startup_startupType (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_Startup(Startup_In* in); + +# endif // _Startup_FP_H_ +#endif // CC_Startup diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/StirRandom_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/StirRandom_fp.h new file mode 100644 index 0000000..aa013b1 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/StirRandom_fp.h @@ -0,0 +1,59 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_StirRandom // Command must be enabled + +# ifndef _Stir_Random_FP_H_ +# define _Stir_Random_FP_H_ + +// Input structure definition +typedef struct +{ + TPM2B_SENSITIVE_DATA inData; +} StirRandom_In; + +// Response code modifiers +# define RC_StirRandom_inData (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_StirRandom(StirRandom_In* in); + +# endif // _Stir_Random_FP_H_ +#endif // CC_StirRandom diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TableDrivenMarshal_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TableDrivenMarshal_fp.h new file mode 100644 index 0000000..4b053fb --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TableDrivenMarshal_fp.h @@ -0,0 +1,92 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 4, 2020 Time: 02:36:44PM + */ + +#ifndef _TABLE_DRIVEN_MARSHAL_FP_H_ +#define _TABLE_DRIVEN_MARSHAL_FP_H_ + +#if TABLE_DRIVEN_MARSHAL + +//***UnmarshalUnion() +TPM_RC +UnmarshalUnion(UINT16 typeIndex, // IN: the thing to unmarshal + void* target, // IN: were the data goes to + UINT8** buffer, // IN/OUT: the data source buffer + INT32* size, // IN/OUT: the remaining size + UINT32 selector); + +//*** MarshalUnion() +UINT16 +MarshalUnion(UINT16 typeIndex, // IN: the thing to marshal + void* source, // IN: were the data comes from + UINT8** buffer, // IN/OUT: the data source buffer + INT32* size, // IN/OUT: the remaining size + UINT32 selector // IN: the union selector +); + +TPM_RC +UnmarshalInteger(int iSize, // IN: Number of bytes in the integer + void* target, // OUT: receives the integer + UINT8** buffer, // IN/OUT: source of the data + INT32* size, // IN/OUT: amount of data available + UINT32* value // OUT: optional copy of 'target' +); + +//*** Unmarshal() +// This is the function that performs unmarshaling of different numbered types. Each +// TPM type has a number. The number is used to lookup the address of the data +// structure that describes how to unmarshal that data type. +// +TPM_RC +Unmarshal(UINT16 typeIndex, // IN: the thing to marshal + void* target, // IN: were the data goes from + UINT8** buffer, // IN/OUT: the data source buffer + INT32* size // IN/OUT: the remaining size +); + +//*** Marshal() +// This is the function that drives marshaling of output. Because there is no +// validation of the output, there is a lot less code. +UINT16 Marshal(UINT16 typeIndex, // IN: the thing to marshal + void* source, // IN: were the data comes from + UINT8** buffer, // IN/OUT: the data source buffer + INT32* size // IN/OUT: the remaining size +); +#endif // TABLE_DRIVEN_MARSHAL + +#endif // _TABLE_DRIVEN_MARSHAL_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TestParms_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TestParms_fp.h new file mode 100644 index 0000000..7a29196 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TestParms_fp.h @@ -0,0 +1,59 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_TestParms // Command must be enabled + +# ifndef _Test_Parms_FP_H_ +# define _Test_Parms_FP_H_ + +// Input structure definition +typedef struct +{ + TPMT_PUBLIC_PARMS parameters; +} TestParms_In; + +// Response code modifiers +# define RC_TestParms_parameters (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_TestParms(TestParms_In* in); + +# endif // _Test_Parms_FP_H_ +#endif // CC_TestParms diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Ticket_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Ticket_fp.h new file mode 100644 index 0000000..48a3a84 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Ticket_fp.h @@ -0,0 +1,93 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 28, 2019 Time: 08:25:19PM + */ + +#ifndef _TICKET_FP_H_ +#define _TICKET_FP_H_ + +//*** TicketIsSafe() +// This function indicates if producing a ticket is safe. +// It checks if the leading bytes of an input buffer is TPM_GENERATED_VALUE +// or its substring of canonical form. If so, it is not safe to produce ticket +// for an input buffer claiming to be TPM generated buffer +// Return Type: BOOL +// TRUE(1) safe to produce ticket +// FALSE(0) not safe to produce ticket +BOOL TicketIsSafe(TPM2B* buffer); + +//*** TicketComputeVerified() +// This function creates a TPMT_TK_VERIFIED ticket. +void TicketComputeVerified( + TPMI_RH_HIERARCHY hierarchy, // IN: hierarchy constant for ticket + TPM2B_DIGEST* digest, // IN: digest + TPM2B_NAME* keyName, // IN: name of key that signed the values + TPMT_TK_VERIFIED* ticket // OUT: verified ticket +); + +//*** TicketComputeAuth() +// This function creates a TPMT_TK_AUTH ticket. +void TicketComputeAuth( + TPM_ST type, // IN: the type of ticket. + TPMI_RH_HIERARCHY hierarchy, // IN: hierarchy constant for ticket + UINT64 timeout, // IN: timeout + BOOL expiresOnReset, // IN: flag to indicate if ticket expires on + // TPM Reset + TPM2B_DIGEST* cpHashA, // IN: input cpHashA + TPM2B_NONCE* policyRef, // IN: input policyRef + TPM2B_NAME* entityName, // IN: name of entity + TPMT_TK_AUTH* ticket // OUT: Created ticket +); + +//*** TicketComputeHashCheck() +// This function creates a TPMT_TK_HASHCHECK ticket. +void TicketComputeHashCheck( + TPMI_RH_HIERARCHY hierarchy, // IN: hierarchy constant for ticket + TPM_ALG_ID hashAlg, // IN: the hash algorithm for 'digest' + TPM2B_DIGEST* digest, // IN: input digest + TPMT_TK_HASHCHECK* ticket // OUT: Created ticket +); + +//*** TicketComputeCreation() +// This function creates a TPMT_TK_CREATION ticket. +void TicketComputeCreation(TPMI_RH_HIERARCHY hierarchy, // IN: hierarchy for ticket + TPM2B_NAME* name, // IN: object name + TPM2B_DIGEST* creation, // IN: creation hash + TPMT_TK_CREATION* ticket // OUT: created ticket +); + +#endif // _TICKET_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Time_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Time_fp.h new file mode 100644 index 0000000..329c6b2 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Time_fp.h @@ -0,0 +1,120 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Apr 2, 2019 Time: 04:23:27PM + */ + +#ifndef _TIME_FP_H_ +#define _TIME_FP_H_ + +//*** TimePowerOn() +// This function initialize time info at _TPM_Init(). +// +// This function is called at _TPM_Init() so that the TPM time can start counting +// as soon as the TPM comes out of reset and doesn't have to wait until +// TPM2_Startup() in order to begin the new time epoch. This could be significant +// for systems that could get powered up but not run any TPM commands for some +// period of time. +// +void TimePowerOn(void); + +//*** TimeStartup() +// This function updates the resetCount and restartCount components of +// TPMS_CLOCK_INFO structure at TPM2_Startup(). +// +// This function will deal with the deferred creation of a new epoch. +// TimeUpdateToCurrent() will not start a new epoch even if one is due when +// TPM_Startup() has not been run. This is because the state of NV is not known +// until startup completes. When Startup is done, then it will create the epoch +// nonce to complete the initializations by calling this function. +BOOL TimeStartup(STARTUP_TYPE type // IN: start up type +); + +//*** TimeClockUpdate() +// This function updates go.clock. If 'newTime' requires an update of NV, then +// NV is checked for availability. If it is not available or is rate limiting, then +// go.clock is not updated and the function returns an error. If 'newTime' would +// not cause an NV write, then go.clock is updated. If an NV write occurs, then +// go.safe is SET. +void TimeClockUpdate(UINT64 newTime // IN: New time value in mS. +); + +//*** TimeUpdate() +// This function is used to update the time and clock values. If the TPM +// has run TPM2_Startup(), this function is called at the start of each command. +// If the TPM has not run TPM2_Startup(), this is called from TPM2_Startup() to +// get the clock values initialized. It is not called on command entry because, in +// this implementation, the go structure is not read from NV until TPM2_Startup(). +// The reason for this is that the initialization code (_TPM_Init()) may run before +// NV is accessible. +void TimeUpdate(void); + +//*** TimeUpdateToCurrent() +// This function updates the 'Time' and 'Clock' in the global +// TPMS_TIME_INFO structure. +// +// In this implementation, 'Time' and 'Clock' are updated at the beginning +// of each command and the values are unchanged for the duration of the +// command. +// +// Because 'Clock' updates may require a write to NV memory, 'Time' and 'Clock' +// are not allowed to advance if NV is not available. When clock is not advancing, +// any function that uses 'Clock' will fail and return TPM_RC_NV_UNAVAILABLE or +// TPM_RC_NV_RATE. +// +// This implementation does not do rate limiting. If the implementation does do +// rate limiting, then the 'Clock' update should not be inhibited even when doing +// rate limiting. +void TimeUpdateToCurrent(void); + +//*** TimeSetAdjustRate() +// This function is used to perform rate adjustment on 'Time' and 'Clock'. +void TimeSetAdjustRate(TPM_CLOCK_ADJUST adjust // IN: adjust constant +); + +//*** TimeGetMarshaled() +// This function is used to access TPMS_TIME_INFO in canonical form. +// The function collects the time information and marshals it into 'dataBuffer' +// and returns the marshaled size +UINT16 +TimeGetMarshaled(TIME_INFO* dataBuffer // OUT: result buffer +); + +//*** TimeFillInfo +// This function gathers information to fill in a TPMS_CLOCK_INFO structure. +void TimeFillInfo(TPMS_CLOCK_INFO* clockInfo); + +#endif // _TIME_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmASN1_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmASN1_fp.h new file mode 100644 index 0000000..ea3f15d --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmASN1_fp.h @@ -0,0 +1,183 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Aug 30, 2019 Time: 02:11:54PM + */ + +#ifndef _TPM_ASN1_FP_H_ +#define _TPM_ASN1_FP_H_ + +//*** ASN1UnmarshalContextInitialize() +// Function does standard initialization of a context. +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure +BOOL ASN1UnmarshalContextInitialize( + ASN1UnmarshalContext* ctx, INT16 size, BYTE* buffer); + +//***ASN1DecodeLength() +// This function extracts the length of an element from 'buffer' starting at 'offset'. +// Return Type: UINT16 +// >=0 the extracted length +// <0 an error +INT16 +ASN1DecodeLength(ASN1UnmarshalContext* ctx); + +//***ASN1NextTag() +// This function extracts the next type from 'buffer' starting at 'offset'. +// It advances 'offset' as it parses the type and the length of the type. It returns +// the length of the type. On return, the 'length' octets starting at 'offset' are the +// octets of the type. +// Return Type: UINT +// >=0 the number of octets in 'type' +// <0 an error +INT16 +ASN1NextTag(ASN1UnmarshalContext* ctx); + +//*** ASN1GetBitStringValue() +// Try to parse a bit string of up to 32 bits from a value that is expected to be +// a bit string. The bit string is left justified so that the MSb of the input is +// the MSb of the returned value. +// If there is a general parsing error, the context->size is set to -1. +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure +BOOL ASN1GetBitStringValue(ASN1UnmarshalContext* ctx, UINT32* val); + +//*** ASN1InitialializeMarshalContext() +// This creates a structure for handling marshaling of an ASN.1 formatted data +// structure. +void ASN1InitialializeMarshalContext( + ASN1MarshalContext* ctx, INT16 length, BYTE* buffer); + +//*** ASN1StartMarshalContext() +// This starts a new constructed element. It is constructed on 'top' of the value +// that was previously placed in the structure. +void ASN1StartMarshalContext(ASN1MarshalContext* ctx); + +//*** ASN1EndMarshalContext() +// This function restores the end pointer for an encapsulating structure. +// Return Type: INT16 +// > 0 the size of the encapsulated structure that was just ended +// <= 0 an error +INT16 +ASN1EndMarshalContext(ASN1MarshalContext* ctx); + +//***ASN1EndEncapsulation() +// This function puts a tag and length in the buffer. In this function, an embedded +// BIT_STRING is assumed to be a collection of octets. To indicate that all bits +// are used, a byte of zero is prepended. If a raw bit-string is needed, a new +// function like ASN1PushInteger() would be needed. +// Return Type: INT16 +// > 0 number of octets in the encapsulation +// == 0 failure +UINT16 +ASN1EndEncapsulation(ASN1MarshalContext* ctx, BYTE tag); + +//*** ASN1PushByte() +BOOL ASN1PushByte(ASN1MarshalContext* ctx, BYTE b); + +//*** ASN1PushBytes() +// Push some raw bytes onto the buffer. 'count' cannot be zero. +// Return Type: IN16 +// > 0 count bytes +// == 0 failure unless count was zero +INT16 +ASN1PushBytes(ASN1MarshalContext* ctx, INT16 count, const BYTE* buffer); + +//*** ASN1PushNull() +// Return Type: IN16 +// > 0 count bytes +// == 0 failure unless count was zero +INT16 +ASN1PushNull(ASN1MarshalContext* ctx); + +//*** ASN1PushLength() +// Push a length value. This will only handle length values that fit in an INT16. +// Return Type: UINT16 +// > 0 number of bytes added +// == 0 failure +INT16 +ASN1PushLength(ASN1MarshalContext* ctx, INT16 len); + +//*** ASN1PushTagAndLength() +// Return Type: INT16 +// > 0 number of bytes added +// == 0 failure +INT16 +ASN1PushTagAndLength(ASN1MarshalContext* ctx, BYTE tag, INT16 length); + +//*** ASN1PushTaggedOctetString() +// This function will push a random octet string. +// Return Type: INT16 +// > 0 number of bytes added +// == 0 failure +INT16 +ASN1PushTaggedOctetString( + ASN1MarshalContext* ctx, INT16 size, const BYTE* string, BYTE tag); + +//*** ASN1PushUINT() +// This function pushes an native-endian integer value. This just changes a +// native-endian integer into a big-endian byte string and calls ASN1PushInteger(). +// That function will remove leading zeros and make sure that the number is positive. +// Return Type: IN16 +// > 0 count bytes +// == 0 failure unless count was zero +INT16 +ASN1PushUINT(ASN1MarshalContext* ctx, UINT32 integer); + +//*** ASN1PushInteger +// Push a big-endian integer on the end of the buffer +// Return Type: UINT16 +// > 0 the number of bytes marshaled for the integer +// == 0 failure +INT16 +ASN1PushInteger(ASN1MarshalContext* ctx, // IN/OUT: buffer context + INT16 iLen, // IN: octets of the integer + BYTE* integer // IN: big-endian integer +); + +//*** ASN1PushOID() +// This function is used to add an OID. An OID is 0x06 followed by a byte of size +// followed by size bytes. This is used to avoid having to do anything special in the +// definition of an OID. +// Return Type: UINT16 +// > 0 the number of bytes marshaled for the integer +// == 0 failure +INT16 +ASN1PushOID(ASN1MarshalContext* ctx, const BYTE* OID); + +#endif // _TPM_ASN1_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmFail_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmFail_fp.h new file mode 100644 index 0000000..e4754ed --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmFail_fp.h @@ -0,0 +1,84 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Apr 2, 2019 Time: 03:18:00PM + */ + +#ifndef _TPM_FAIL_FP_H_ +#define _TPM_FAIL_FP_H_ + +//*** SetForceFailureMode() +// This function is called by the simulator to enable failure mode testing. +#if SIMULATION +LIB_EXPORT void SetForceFailureMode(void); +#endif + +//*** TpmLogFailure() +// This function saves the failure values when the code will continue to operate. It +// if similar to TpmFail() but returns to the caller. The assumption is that the +// caller will propagate a failure back up the stack. +void TpmLogFailure( +#if FAIL_TRACE + const char* function, + int line, +#endif + int code); + +//*** TpmFail() +// This function is called by TPM.lib when a failure occurs. It will set up the +// failure values to be returned on TPM2_GetTestResult(). +NORETURN void TpmFail( +#if FAIL_TRACE + const char* function, + int line, +#endif + int code); + +//*** TpmFailureMode( +// This function is called by the interface code when the platform is in failure +// mode. +void TpmFailureMode(unsigned int inRequestSize, // IN: command buffer size + unsigned char* inRequest, // IN: command buffer + unsigned int* outResponseSize, // OUT: response buffer size + unsigned char** outResponse // OUT: response buffer +); + +//*** UnmarshalFail() +// This is a stub that is used to catch an attempt to unmarshal an entry +// that is not defined. Don't ever expect this to be called but... +void UnmarshalFail(void* type, BYTE** buffer, INT32* size); + +#endif // _TPM_FAIL_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmSizeChecks_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmSizeChecks_fp.h new file mode 100644 index 0000000..f999ca6 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmSizeChecks_fp.h @@ -0,0 +1,53 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Oct 24, 2019 Time: 11:37:07AM + */ + +#ifndef _TPM_SIZE_CHECKS_FP_H_ +#define _TPM_SIZE_CHECKS_FP_H_ + +#if RUNTIME_SIZE_CHECKS + +//** TpmSizeChecks() +// This function is used during the development process to make sure that the +// vendor-specific values result in a consistent implementation. When possible, +// the code contains "#if" to do compile-time checks. However, in some cases, the +// values require the use of "sizeof()" and that can't be used in an #if. +BOOL TpmSizeChecks(void); +#endif // RUNTIME_SIZE_CHECKS + +#endif // _TPM_SIZE_CHECKS_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToLtcDesSupport_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToLtcDesSupport_fp.h new file mode 100644 index 0000000..ede9616 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToLtcDesSupport_fp.h @@ -0,0 +1,53 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Aug 30, 2019 Time: 02:11:54PM + */ + +#ifndef _TPM_TO_LTC_DES_SUPPORT_FP_H_ +#define _TPM_TO_LTC_DES_SUPPORT_FP_H_ + +#if(defined SYM_LIB_LTC) && ALG_TDES + +//** TDES_setup +// This function calls the LTC function to generate a TDES key schedule. If the +// key is one DES key (8 bytes), then it is replicated two more times to create a +// 24-byte TDES key. If the key is two key (16 bytes), then the first DES key is +// replicated to the third key position. +void TDES_setup(const BYTE* key, UINT32 keyBits, symmetric_key* skey); +#endif // MATH_LIB_LTC && ALG_TDES + +#endif // _TPM_TO_LTC_DES_SUPPORT_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToLtcMath_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToLtcMath_fp.h new file mode 100644 index 0000000..805b377 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToLtcMath_fp.h @@ -0,0 +1,118 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Aug 30, 2019 Time: 02:11:54PM + */ + +#ifndef _TPM_TO_LTC_MATH_FP_H_ +#define _TPM_TO_LTC_MATH_FP_H_ + +#ifdef MATH_LIB_LTC + +//*** BnModMult() +// Does multiply and divide returning the remainder of the divide. +LIB_EXPORT BOOL BnModMult( + bigNum result, bigConst op1, bigConst op2, bigConst modulus); + +//*** BnMult() +// Multiplies two numbers +LIB_EXPORT BOOL BnMult(bigNum result, bigConst multiplicand, bigConst multiplier); + +//*** BnDiv() +// This function divides two BIGNUM values. The function always returns TRUE. +LIB_EXPORT BOOL BnDiv( + bigNum quotient, bigNum remainder, bigConst dividend, bigConst divisor); + +# ifdef TPM_ALG_RSA +//*** BnGcd() +// Get the greatest common divisor of two numbers +LIB_EXPORT BOOL BnGcd(bigNum gcd, // OUT: the common divisor + bigConst number1, // IN: + bigConst number2 // IN: +); + +//***BnModExp() +// Do modular exponentiation using BIGNUM values. The conversion from a bignum_t +// to a BIGNUM is trivial as they are based on the same structure +LIB_EXPORT BOOL BnModExp(bigNum result, // OUT: the result + bigConst number, // IN: number to exponentiate + bigConst exponent, // IN: + bigConst modulus // IN: +); + +//*** BnModInverse() +// Modular multiplicative inverse +LIB_EXPORT BOOL BnModInverse(bigNum result, bigConst number, bigConst modulus); +# endif // TPM_ALG_RSA +# ifdef TPM_ALG_ECC + +//*** BnEccModMult() +// This function does a point multiply of the form R = [d]S +// return type: BOOL +// FALSE failure in operation; treat as result being point at infinity +LIB_EXPORT BOOL BnEccModMult(bigPoint R, // OUT: computed point + pointConst S, // IN: point to multiply by 'd' + bigConst d, // IN: scalar for [d]S + bigCurve E); + +//*** BnEccModMult2() +// This function does a point multiply of the form R = [d]S + [u]Q +// return type: BOOL +// FALSE failure in operation; treat as result being point at infinity +LIB_EXPORT BOOL BnEccModMult2(bigPoint R, // OUT: computed point + pointConst S, // IN: first point (optional) + bigConst d, // IN: scalar for [d]S or [d]G + pointConst Q, // IN: second point + bigConst u, // IN: second scalar + bigCurve E // IN: curve +); + +//*** BnEccAdd() +// This function does addition of two points. Since this is not implemented +// in LibTomCrypt() will try to trick it by doing multiply with scalar of 1. +// I have no idea if this will work and it's not needed unless MQV or the SM2 +// variant is enabled. +// return type: BOOL +// FALSE failure in operation; treat as result being point at infinity +LIB_EXPORT BOOL BnEccAdd(bigPoint R, // OUT: computed point + pointConst S, // IN: point to multiply by 'd' + pointConst Q, // IN: second point + bigCurve E // IN: curve +); +# endif // TPM_ALG_ECC +#endif // MATH_LIB_LTC + +#endif // _TPM_TO_LTC_MATH_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToLtcSupport_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToLtcSupport_fp.h new file mode 100644 index 0000000..4037a60 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToLtcSupport_fp.h @@ -0,0 +1,61 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Aug 30, 2019 Time: 02:11:54PM + */ + +#ifndef _TPM_TO_LTC_SUPPORT_FP_H_ +#define _TPM_TO_LTC_SUPPORT_FP_H_ + +#if defined(HASH_LIB_LTC) || defined(MATH_LIB_LTC) || defined(SYM_LIB_LTC) + +//*** LtcRand() +// This is a stub function that is called from the LibTomCrypt or libmpa code +// to get a random number. In turn, this will call the random RandGenerate +// function that was passed in LibraryInit(). This function will pass the pointer +// to the current rand state along with the random byte request. +uint32_t LtcRand(void* buf, size_t blen); + +//*** SupportLibInit() +// This does any initialization required by the support library. +LIB_EXPORT int SupportLibInit(void); + +//*** LtcPoolInit() +// Function to initialize a pool. **** +LIB_EXPORT mpa_scratch_mem LtcPoolInit(mpa_word_t* poolAddress, int vars, int bits); +#endif // HASH_LIB_LTC || MATH_LIB_LTC || SYM_LIB_LTC + +#endif // _TPM_TO_LTC_SUPPORT_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToMbedtlsMath_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToMbedtlsMath_fp.h new file mode 100644 index 0000000..992dbc5 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToMbedtlsMath_fp.h @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2023-2024, NVIDIA Corporation & AFFILIATES. All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef _TPM_TO_MBEDTLS_MATH_FP_H_ +#define _TPM_TO_MBEDTLS_MATH_FP_H_ + +#ifdef MATH_LIB_MBEDTLS + +//*** BnFromMbedtls() +// This function converts a mbedtls_mpi to a TPM bignum. In this implementation +// it is assumed that Mbedtls used the same format for a big number as does the +// TPM -- an array of native-endian words in little-endian order. +void +BnFromMbedtls( + bigNum bn, + mbedtls_mpi *mbedBn +); + +//*** BnToMbedtls() +// This function converts a TPM bignum to a mbedtls_mpi, and has the same +// assumptions as made by BnFromMbedtls() +void +BnToMbedtls( + mbedtls_mpi *toInit, + bigConst initializer +); + +//*** MpiInitialize() +// This function initializes an Mbedtls mbedtls_mpi. +mbedtls_mpi * +MpiInitialize( + mbedtls_mpi *toInit +); + +#if LIBRARY_COMPATIBILITY_CHECK +//** MathLibraryCompatibilityCheck() +// This function is only used during development to make sure that the library +// that is being referenced is using the same size of data structures as the TPM. +BOOL +MathLibraryCompatibilityCheck( + void +); +#endif + +//*** BnModMult() +// Does multiply and divide returning the remainder of the divide. +LIB_EXPORT BOOL +BnModMult( + bigNum result, + bigConst op1, + bigConst op2, + bigConst modulus +); + +//*** BnMult() +// Multiplies two numbers +LIB_EXPORT BOOL +BnMult( + bigNum result, + bigConst multiplicand, + bigConst multiplier +); + +//*** BnDiv() +// This function divides two bigNum values. The function returns FALSE if +// there is an error in the operation. +LIB_EXPORT BOOL +BnDiv( + bigNum quotient, + bigNum remainder, + bigConst dividend, + bigConst divisor +); + +#if ALG_RSA +//*** BnGcd() +// Get the greatest common divisor of two numbers +LIB_EXPORT BOOL +BnGcd( + bigNum gcd, // OUT: the common divisor + bigConst number1, // IN: + bigConst number2 // IN: +); + +//***BnModExp() +// Do modular exponentiation using bigNum values. The conversion from a mp_int to +// a bigNum is trivial as they are based on the same structure +LIB_EXPORT BOOL +BnModExp( + bigNum result, // OUT: the result + bigConst number, // IN: number to exponentiate + bigConst exponent, // IN: + bigConst modulus // IN: +); + +//*** BnModInverse() +// Modular multiplicative inverse +LIB_EXPORT BOOL +BnModInverse( + bigNum result, + bigConst number, + bigConst modulus +); +#endif // TPM_ALG_RSA + +#if ALG_ECC +//*** PointFromMbedtls() +// Function to copy the point result from a mbedtls_mpi to a bigNum +void +PointFromMbedtls( + bigPoint pOut, // OUT: resulting point + ecc_point *pIn // IN: the point to return +); + +//*** PointToMbedtls() +// Function to copy the point result from a bigNum to a mbedtls_mpi +void +PointToMbedtls( + ecc_point *pOut, // OUT: resulting point + pointConst pIn // IN: the point to return +); + +//*** BnEccModMult() +// This function does a point multiply of the form R = [d]S +// return type: BOOL +// FALSE failure in operation; treat as result being point at infinity +LIB_EXPORT BOOL +BnEccModMult( + bigPoint R, // OUT: computed point + pointConst S, // IN: point to multiply by 'd' (optional) + bigConst d, // IN: scalar for [d]S + bigCurve E +); + +//*** BnEccModMult2() +// This function does a point multiply of the form R = [d]G + [u]Q +// return type: BOOL +// FALSE failure in operation; treat as result being point at infinity +LIB_EXPORT BOOL +BnEccModMult2( + bigPoint R, // OUT: computed point + pointConst S, // IN: optional point + bigConst d, // IN: scalar for [d]S or [d]G + pointConst Q, // IN: second point + bigConst u, // IN: second scalar + bigCurve E // IN: curve +); + +//** BnEccAdd() +// This function does addition of two points. +// return type: BOOL +// FALSE failure in operation; treat as result being point at infinity +LIB_EXPORT BOOL +BnEccAdd( + bigPoint R, // OUT: computed point + pointConst S, // IN: point to multiply by 'd' + pointConst Q, // IN: second point + bigCurve E // IN: curve +); +#endif // TPM_ALG_ECC +#endif // MATH_LIB_MBEDTLS + +#endif // _TPM_TO_MBEDTLS_MATH_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToMbedtlsSupport_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToMbedtlsSupport_fp.h new file mode 100644 index 0000000..e69c97e --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToMbedtlsSupport_fp.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2023-2024, NVIDIA Corporation & AFFILIATES. All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef _TPM_TO_MBEDTLS_SUPPORT_FP_H_ +#define _TPM_TO_MBEDTLS_SUPPORT_FP_H_ + +#if defined(HASH_LIB_MBEDTLS) || defined(MATH_LIB_MBEDTLS) || defined(SYM_LIB_MBEDTLS) + +//*** SupportLibInit() +// This does any initialization required by the support library. +LIB_EXPORT int +SupportLibInit( + void +); + +#endif // HASH_LIB_MBEDTLS || MATH_LIB_MBEDTLS || SYM_LIB_MBEDTLS + +#endif // _TPM_TO_MBEDTLS_SUPPORT_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToOsslDesSupport_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToOsslDesSupport_fp.h new file mode 100644 index 0000000..1ebcb40 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToOsslDesSupport_fp.h @@ -0,0 +1,66 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Apr 2, 2019 Time: 03:18:00PM + */ + +#ifndef _TPM_TO_OSSL_DES_SUPPORT_FP_H_ +#define _TPM_TO_OSSL_DES_SUPPORT_FP_H_ + +#if(defined SYM_LIB_OSSL) && ALG_TDES + +//**Functions +//*** TDES_set_encyrpt_key() +// This function makes creation of a TDES key look like the creation of a key for +// any of the other OpenSSL block ciphers. It will create three key schedules, +// one for each of the DES keys. If there are only two keys, then the third schedule +// is a copy of the first. +void TDES_set_encrypt_key( + const BYTE* key, UINT16 keySizeInBits, tpmKeyScheduleTDES* keySchedule); + +//*** TDES_encyrpt() +// The TPM code uses one key schedule. For TDES, the schedule contains three +// schedules. OpenSSL wants the schedules referenced separately. This function +// does that. +void TDES_encrypt(const BYTE* in, BYTE* out, tpmKeyScheduleTDES* ks); + +//*** TDES_decrypt() +// As with TDES_encypt() this function bridges between the TPM single schedule +// model and the OpenSSL three schedule model. +void TDES_decrypt(const BYTE* in, BYTE* out, tpmKeyScheduleTDES* ks); +#endif // SYM_LIB_OSSL + +#endif // _TPM_TO_OSSL_DES_SUPPORT_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToOsslMath_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToOsslMath_fp.h new file mode 100644 index 0000000..daedf56 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToOsslMath_fp.h @@ -0,0 +1,177 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Oct 24, 2019 Time: 11:37:07AM + */ + +#ifndef _TPM_TO_OSSL_MATH_FP_H_ +#define _TPM_TO_OSSL_MATH_FP_H_ + +#ifdef MATH_LIB_OSSL + +//*** OsslToTpmBn() +// This function converts an OpenSSL BIGNUM to a TPM bignum. In this implementation +// it is assumed that OpenSSL uses a different control structure but the same data +// layout -- an array of native-endian words in little-endian order. +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure because value will not fit or OpenSSL variable doesn't +// exist +BOOL OsslToTpmBn(bigNum bn, BIGNUM* osslBn); + +//*** BigInitialized() +// This function initializes an OSSL BIGNUM from a TPM bigConst. Do not use this for +// values that are passed to OpenSLL when they are not declared as const in the +// function prototype. Instead, use BnNewVariable(). +BIGNUM* BigInitialized(BIGNUM* toInit, bigConst initializer); +# if LIBRARY_COMPATIBILITY_CHECK + +//*** MathLibraryCompatibilityCheck() +BOOL MathLibraryCompatibilityCheck(void); +# endif + +//*** BnModMult() +// This function does a modular multiply. It first does a multiply and then a divide +// and returns the remainder of the divide. +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure in operation +LIB_EXPORT BOOL BnModMult( + bigNum result, bigConst op1, bigConst op2, bigConst modulus); + +//*** BnMult() +// Multiplies two numbers +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure in operation +LIB_EXPORT BOOL BnMult(bigNum result, bigConst multiplicand, bigConst multiplier); + +//*** BnDiv() +// This function divides two bigNum values. The function returns FALSE if +// there is an error in the operation. +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure in operation +LIB_EXPORT BOOL BnDiv( + bigNum quotient, bigNum remainder, bigConst dividend, bigConst divisor); + +# if ALG_RSA +//*** BnGcd() +// Get the greatest common divisor of two numbers +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure in operation +LIB_EXPORT BOOL BnGcd(bigNum gcd, // OUT: the common divisor + bigConst number1, // IN: + bigConst number2 // IN: +); + +//***BnModExp() +// Do modular exponentiation using bigNum values. The conversion from a bignum_t to +// a bigNum is trivial as they are based on the same structure +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure in operation +LIB_EXPORT BOOL BnModExp(bigNum result, // OUT: the result + bigConst number, // IN: number to exponentiate + bigConst exponent, // IN: + bigConst modulus // IN: +); + +//*** BnModInverse() +// Modular multiplicative inverse +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure in operation +LIB_EXPORT BOOL BnModInverse(bigNum result, bigConst number, bigConst modulus); +# endif // ALG_RSA +# if ALG_ECC + +//*** BnCurveInitialize() +// This function initializes the OpenSSL curve information structure. This +// structure points to the TPM-defined values for the curve, to the context for the +// number values in the frame, and to the OpenSSL-defined group values. +// Return Type: bigCurve * +// NULL the TPM_ECC_CURVE is not valid or there was a problem in +// in initializing the curve data +// non-NULL points to 'E' +LIB_EXPORT bigCurve BnCurveInitialize( + bigCurve E, // IN: curve structure to initialize + TPM_ECC_CURVE curveId // IN: curve identifier +); + +//*** BnCurveFree() +// This function will free the allocated components of the curve and end the +// frame in which the curve data exists +LIB_EXPORT void BnCurveFree(bigCurve E); + +//*** BnEccModMult() +// This function does a point multiply of the form R = [d]S +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure in operation; treat as result being point at infinity +LIB_EXPORT BOOL BnEccModMult(bigPoint R, // OUT: computed point + pointConst S, // IN: point to multiply by 'd' (optional) + bigConst d, // IN: scalar for [d]S + bigCurve E); + +//*** BnEccModMult2() +// This function does a point multiply of the form R = [d]G + [u]Q +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure in operation; treat as result being point at infinity +LIB_EXPORT BOOL BnEccModMult2(bigPoint R, // OUT: computed point + pointConst S, // IN: optional point + bigConst d, // IN: scalar for [d]S or [d]G + pointConst Q, // IN: second point + bigConst u, // IN: second scalar + bigCurve E // IN: curve +); + +//** BnEccAdd() +// This function does addition of two points. +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure in operation; treat as result being point at infinity +LIB_EXPORT BOOL BnEccAdd(bigPoint R, // OUT: computed point + pointConst S, // IN: point to multiply by 'd' + pointConst Q, // IN: second point + bigCurve E // IN: curve +); +# endif // ALG_ECC +#endif // MATHLIB OSSL + +#endif // _TPM_TO_OSSL_MATH_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToOsslSupport_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToOsslSupport_fp.h new file mode 100644 index 0000000..109cd0b --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToOsslSupport_fp.h @@ -0,0 +1,69 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 28, 2019 Time: 08:25:19PM + */ + +#ifndef _TPM_TO_OSSL_SUPPORT_FP_H_ +#define _TPM_TO_OSSL_SUPPORT_FP_H_ + +#if defined(HASH_LIB_OSSL) || defined(MATH_LIB_OSSL) || defined(SYM_LIB_OSSL) + +//*** SupportLibInit() +// This does any initialization required by the support library. +LIB_EXPORT int SupportLibInit(void); + +//*** OsslContextEnter() +// This function is used to initialize an OpenSSL context at the start of a function +// that will call to an OpenSSL math function. +BN_CTX* OsslContextEnter(void); + +//*** OsslContextLeave() +// This is the companion function to OsslContextEnter(). +void OsslContextLeave(BN_CTX* CTX); + +//*** OsslPushContext() +// This function is used to create a frame in a context. All values allocated within +// this context after the frame is started will be automatically freed when the +// context (OsslPopContext() +BN_CTX* OsslPushContext(BN_CTX* CTX); + +//*** OsslPopContext() +// This is the companion function to OsslPushContext(). +void OsslPopContext(BN_CTX* CTX); +#endif // HASH_LIB_OSSL || MATH_LIB_OSSL || SYM_LIB_OSSL + +#endif // _TPM_TO_OSSL_SUPPORT_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToWolfDesSupport_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToWolfDesSupport_fp.h new file mode 100644 index 0000000..7d6d862 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToWolfDesSupport_fp.h @@ -0,0 +1,67 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Aug 30, 2019 Time: 02:11:54PM + */ + +#ifndef _TPM_TO_WOLF_DES_SUPPORT_FP_H_ +#define _TPM_TO_WOLF_DES_SUPPORT_FP_H_ + +#if(defined SYM_LIB_WOLF) && ALG_TDES + +//**Functions +//** TDES_setup +// This function calls the wolfcrypt function to generate a TDES key schedule. If the +// If the key is two key (16 bytes), then the first DES key is replicated to the third +// key position. +int TDES_setup(const BYTE* key, UINT32 keyBits, tpmKeyScheduleTDES* skey, int dir); + +//** TDES_setup_encrypt_key +// This function calls into TDES_setup(), specifically for an encryption key. +int TDES_setup_encrypt_key(const BYTE* key, UINT32 keyBits, tpmKeyScheduleTDES* skey); + +//** TDES_setup_decrypt_key +// This function calls into TDES_setup(), specifically for an decryption key. +int TDES_setup_decrypt_key(const BYTE* key, UINT32 keyBits, tpmKeyScheduleTDES* skey); + +//*** TDES_encyrpt() +void TDES_encrypt(const BYTE* in, BYTE* out, tpmKeyScheduleTDES* ks); + +//*** TDES_decrypt() +void TDES_decrypt(const BYTE* in, BYTE* out, tpmKeyScheduleTDES* ks); +#endif // MATH_LIB_WOLF && ALG_TDES + +#endif // _TPM_TO_WOLF_DES_SUPPORT_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToWolfMath_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToWolfMath_fp.h new file mode 100644 index 0000000..262dd7c --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToWolfMath_fp.h @@ -0,0 +1,150 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Aug 30, 2019 Time: 02:11:54PM + */ + +#ifndef _TPM_TO_WOLF_MATH_FP_H_ +#define _TPM_TO_WOLF_MATH_FP_H_ + +#ifdef MATH_LIB_WOLF + +//*** BnFromWolf() +// This function converts a wolfcrypt mp_int to a TPM bignum. In this implementation +// it is assumed that wolfcrypt used the same format for a big number as does the +// TPM -- an array of native-endian words in little-endian order. +void BnFromWolf(bigNum bn, mp_int* wolfBn); + +//*** BnToWolf() +// This function converts a TPM bignum to a wolfcrypt mp_init, and has the same +// assumptions as made by BnFromWolf() +void BnToWolf(mp_int* toInit, bigConst initializer); + +//*** MpInitialize() +// This function initializes an wolfcrypt mp_int. +mp_int* MpInitialize(mp_int* toInit); + +# if LIBRARY_COMPATIBILITY_CHECK +//** MathLibraryCompatibililtyCheck() +// This function is only used during development to make sure that the library +// that is being referenced is using the same size of data structures as the TPM. +BOOL MathLibraryCompatibilityCheck(void); +# endif + +//*** BnModMult() +// Does multiply and divide returning the remainder of the divide. +LIB_EXPORT BOOL BnModMult( + bigNum result, bigConst op1, bigConst op2, bigConst modulus); + +//*** BnMult() +// Multiplies two numbers +LIB_EXPORT BOOL BnMult(bigNum result, bigConst multiplicand, bigConst multiplier); + +//*** BnDiv() +// This function divides two bigNum values. The function returns FALSE if +// there is an error in the operation. +LIB_EXPORT BOOL BnDiv( + bigNum quotient, bigNum remainder, bigConst dividend, bigConst divisor); + +# if ALG_RSA +//*** BnGcd() +// Get the greatest common divisor of two numbers +LIB_EXPORT BOOL BnGcd(bigNum gcd, // OUT: the common divisor + bigConst number1, // IN: + bigConst number2 // IN: +); + +//***BnModExp() +// Do modular exponentiation using bigNum values. The conversion from a mp_int to +// a bigNum is trivial as they are based on the same structure +LIB_EXPORT BOOL BnModExp(bigNum result, // OUT: the result + bigConst number, // IN: number to exponentiate + bigConst exponent, // IN: + bigConst modulus // IN: +); + +//*** BnModInverse() +// Modular multiplicative inverse +LIB_EXPORT BOOL BnModInverse(bigNum result, bigConst number, bigConst modulus); +# endif // TPM_ALG_RSA +# if ALG_ECC + +//*** PointFromWolf() +// Function to copy the point result from a wolf ecc_point to a bigNum +void PointFromWolf(bigPoint pOut, // OUT: resulting point + ecc_point* pIn // IN: the point to return +); + +//*** PointToWolf() +// Function to copy the point result from a bigNum to a wolf ecc_point +void PointToWolf(ecc_point* pOut, // OUT: resulting point + pointConst pIn // IN: the point to return +); + +//*** BnEccModMult() +// This function does a point multiply of the form R = [d]S +// return type: BOOL +// FALSE failure in operation; treat as result being point at infinity +LIB_EXPORT BOOL BnEccModMult(bigPoint R, // OUT: computed point + pointConst S, // IN: point to multiply by 'd' (optional) + bigConst d, // IN: scalar for [d]S + bigCurve E); + +//*** BnEccModMult2() +// This function does a point multiply of the form R = [d]G + [u]Q +// return type: BOOL +// FALSE failure in operation; treat as result being point at infinity +LIB_EXPORT BOOL BnEccModMult2(bigPoint R, // OUT: computed point + pointConst S, // IN: optional point + bigConst d, // IN: scalar for [d]S or [d]G + pointConst Q, // IN: second point + bigConst u, // IN: second scalar + bigCurve E // IN: curve +); + +//** BnEccAdd() +// This function does addition of two points. +// return type: BOOL +// FALSE failure in operation; treat as result being point at infinity +LIB_EXPORT BOOL BnEccAdd(bigPoint R, // OUT: computed point + pointConst S, // IN: point to multiply by 'd' + pointConst Q, // IN: second point + bigCurve E // IN: curve +); +# endif // TPM_ALG_ECC +#endif // MATH_LIB_WOLF + +#endif // _TPM_TO_WOLF_MATH_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToWolfSupport_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToWolfSupport_fp.h new file mode 100644 index 0000000..4df9c49 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/TpmToWolfSupport_fp.h @@ -0,0 +1,50 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Aug 30, 2019 Time: 02:11:54PM + */ + +#ifndef _TPM_TO_WOLF_SUPPORT_FP_H_ +#define _TPM_TO_WOLF_SUPPORT_FP_H_ + +#if defined(HASH_LIB_WOLF) || defined(MATH_LIB_WOLF) || defined(SYM_LIB_WOLF) + +//*** SupportLibInit() +// This does any initialization required by the support library. +LIB_EXPORT int SupportLibInit(void); +#endif // HASH_LIB_WOLF || MATH_LIB_WOLF || SYM_LIB_WOLF + +#endif // _TPM_TO_WOLF_SUPPORT_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Unseal_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Unseal_fp.h new file mode 100644 index 0000000..d5b1a95 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Unseal_fp.h @@ -0,0 +1,65 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_Unseal // Command must be enabled + +# ifndef _Unseal_FP_H_ +# define _Unseal_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_OBJECT itemHandle; +} Unseal_In; + +// Output structure definition +typedef struct +{ + TPM2B_SENSITIVE_DATA outData; +} Unseal_Out; + +// Response code modifiers +# define RC_Unseal_itemHandle (TPM_RC_H + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_Unseal(Unseal_In* in, Unseal_Out* out); + +# endif // _Unseal_FP_H_ +#endif // CC_Unseal diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Vendor_TCG_Test_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Vendor_TCG_Test_fp.h new file mode 100644 index 0000000..04d2c4a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/Vendor_TCG_Test_fp.h @@ -0,0 +1,65 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_Vendor_TCG_Test // Command must be enabled + +# ifndef _Vendor_TCG_Test_FP_H_ +# define _Vendor_TCG_Test_FP_H_ + +// Input structure definition +typedef struct +{ + TPM2B_DATA inputData; +} Vendor_TCG_Test_In; + +// Output structure definition +typedef struct +{ + TPM2B_DATA outputData; +} Vendor_TCG_Test_Out; + +// Response code modifiers +# define RC_Vendor_TCG_Test_inputData (TPM_RC_P + TPM_RC_1) + +// Function prototype +TPM_RC +TPM2_Vendor_TCG_Test(Vendor_TCG_Test_In* in, Vendor_TCG_Test_Out* out); + +# endif // _Vendor_TCG_Test_FP_H_ +#endif // CC_Vendor_TCG_Test diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/VerifySignature_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/VerifySignature_fp.h new file mode 100644 index 0000000..b0ae580 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/VerifySignature_fp.h @@ -0,0 +1,69 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_VerifySignature // Command must be enabled + +# ifndef _Verify_Signature_FP_H_ +# define _Verify_Signature_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_OBJECT keyHandle; + TPM2B_DIGEST digest; + TPMT_SIGNATURE signature; +} VerifySignature_In; + +// Output structure definition +typedef struct +{ + TPMT_TK_VERIFIED validation; +} VerifySignature_Out; + +// Response code modifiers +# define RC_VerifySignature_keyHandle (TPM_RC_H + TPM_RC_1) +# define RC_VerifySignature_digest (TPM_RC_P + TPM_RC_1) +# define RC_VerifySignature_signature (TPM_RC_P + TPM_RC_2) + +// Function prototype +TPM_RC +TPM2_VerifySignature(VerifySignature_In* in, VerifySignature_Out* out); + +# endif // _Verify_Signature_FP_H_ +#endif // CC_VerifySignature diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/X509_ECC_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/X509_ECC_fp.h new file mode 100644 index 0000000..1e56459 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/X509_ECC_fp.h @@ -0,0 +1,70 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Apr 2, 2019 Time: 11:00:49AM + */ + +#ifndef _X509_ECC_FP_H_ +#define _X509_ECC_FP_H_ + +//*** X509PushPoint() +// This seems like it might be used more than once so... +// Return Type: INT16 +// > 0 number of bytes added +// == 0 failure +INT16 +X509PushPoint(ASN1MarshalContext* ctx, TPMS_ECC_POINT* p); + +//*** X509AddSigningAlgorithmECC() +// This creates the singing algorithm data. +// Return Type: INT16 +// > 0 number of bytes added +// == 0 failure +INT16 +X509AddSigningAlgorithmECC( + OBJECT* signKey, TPMT_SIG_SCHEME* scheme, ASN1MarshalContext* ctx); + +//*** X509AddPublicECC() +// This function will add the publicKey description to the DER data. If ctx is +// NULL, then no data is transferred and this function will indicate if the TPM +// has the values for DER-encoding of the public key. +// Return Type: INT16 +// > 0 number of bytes added +// == 0 failure +INT16 +X509AddPublicECC(OBJECT* object, ASN1MarshalContext* ctx); + +#endif // _X509_ECC_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/X509_RSA_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/X509_RSA_fp.h new file mode 100644 index 0000000..9a856ec --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/X509_RSA_fp.h @@ -0,0 +1,65 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Apr 2, 2019 Time: 11:00:49AM + */ + +#ifndef _X509_RSA_FP_H_ +#define _X509_RSA_FP_H_ + +#if ALG_RSA + +//*** X509AddSigningAlgorithmRSA() +// This creates the singing algorithm data. +// Return Type: INT16 +// > 0 number of bytes added +// == 0 failure +INT16 +X509AddSigningAlgorithmRSA( + OBJECT* signKey, TPMT_SIG_SCHEME* scheme, ASN1MarshalContext* ctx); + +//*** X509AddPublicRSA() +// This function will add the publicKey description to the DER data. If fillPtr is +// NULL, then no data is transferred and this function will indicate if the TPM +// has the values for DER-encoding of the public key. +// Return Type: INT16 +// > 0 number of bytes added +// == 0 failure +INT16 +X509AddPublicRSA(OBJECT* object, ASN1MarshalContext* ctx); +#endif // ALG_RSA + +#endif // _X509_RSA_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/X509_spt_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/X509_spt_fp.h new file mode 100644 index 0000000..f09cf23 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/X509_spt_fp.h @@ -0,0 +1,105 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Nov 14, 2019 Time: 05:57:02PM + */ + +#ifndef _X509_SPT_FP_H_ +#define _X509_SPT_FP_H_ + +//*** X509FindExtensionByOID() +// This will search a list of X509 extensions to find an extension with the +// requested OID. If the extension is found, the output context ('ctx') is set up +// to point to the OID in the extension. +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure (could be catastrophic) +BOOL X509FindExtensionByOID(ASN1UnmarshalContext* ctxIn, // IN: the context to search + ASN1UnmarshalContext* ctx, // OUT: the extension context + const BYTE* OID // IN: oid to search for +); + +//*** X509GetExtensionBits() +// This function will extract a bit field from an extension. If the extension doesn't +// contain a bit string, it will fail. +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure +UINT32 +X509GetExtensionBits(ASN1UnmarshalContext* ctx, UINT32* value); + +//***X509ProcessExtensions() +// This function is used to process the TPMA_OBJECT and KeyUsage extensions. It is not +// in the CertifyX509.c code because it makes the code harder to follow. +// Return Type: TPM_RC +// TPM_RCS_ATTRIBUTES the attributes of object are not consistent with +// the extension setting +// TPM_RC_VALUE problem parsing the extensions +TPM_RC +X509ProcessExtensions( + OBJECT* object, // IN: The object with the attributes to + // check + stringRef* extension // IN: The start and length of the extensions +); + +//*** X509AddSigningAlgorithm() +// This creates the singing algorithm data. +// Return Type: INT16 +// > 0 number of octets added +// <= 0 failure +INT16 +X509AddSigningAlgorithm( + ASN1MarshalContext* ctx, OBJECT* signKey, TPMT_SIG_SCHEME* scheme); + +//*** X509AddPublicKey() +// This function will add the publicKey description to the DER data. If fillPtr is +// NULL, then no data is transferred and this function will indicate if the TPM +// has the values for DER-encoding of the public key. +// Return Type: INT16 +// > 0 number of octets added +// == 0 failure +INT16 +X509AddPublicKey(ASN1MarshalContext* ctx, OBJECT* object); + +//*** X509PushAlgorithmIdentifierSequence() +// The function adds the algorithm identifier sequence. +// Return Type: INT16 +// > 0 number of bytes added +// == 0 failure +INT16 +X509PushAlgorithmIdentifierSequence(ASN1MarshalContext* ctx, const BYTE* OID); + +#endif // _X509_SPT_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ZGen_2Phase_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ZGen_2Phase_fp.h new file mode 100644 index 0000000..e4c8eba --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/ZGen_2Phase_fp.h @@ -0,0 +1,74 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Mar 28, 2019 Time: 08:25:17PM + */ + +#if CC_ZGen_2Phase // Command must be enabled + +# ifndef _ZGen_2Phase_FP_H_ +# define _ZGen_2Phase_FP_H_ + +// Input structure definition +typedef struct +{ + TPMI_DH_OBJECT keyA; + TPM2B_ECC_POINT inQsB; + TPM2B_ECC_POINT inQeB; + TPMI_ECC_KEY_EXCHANGE inScheme; + UINT16 counter; +} ZGen_2Phase_In; + +// Output structure definition +typedef struct +{ + TPM2B_ECC_POINT outZ1; + TPM2B_ECC_POINT outZ2; +} ZGen_2Phase_Out; + +// Response code modifiers +# define RC_ZGen_2Phase_keyA (TPM_RC_H + TPM_RC_1) +# define RC_ZGen_2Phase_inQsB (TPM_RC_P + TPM_RC_1) +# define RC_ZGen_2Phase_inQeB (TPM_RC_P + TPM_RC_2) +# define RC_ZGen_2Phase_inScheme (TPM_RC_P + TPM_RC_3) +# define RC_ZGen_2Phase_counter (TPM_RC_P + TPM_RC_4) + +// Function prototype +TPM_RC +TPM2_ZGen_2Phase(ZGen_2Phase_In* in, ZGen_2Phase_Out* out); + +# endif // _ZGen_2Phase_FP_H_ +#endif // CC_ZGen_2Phase diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/_TPM_Hash_Data_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/_TPM_Hash_Data_fp.h new file mode 100644 index 0000000..3723f82 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/_TPM_Hash_Data_fp.h @@ -0,0 +1,48 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 28, 2019 Time: 08:25:19PM + */ + +#ifndef __TPM_HASH_DATA_FP_H_ +#define __TPM_HASH_DATA_FP_H_ + +// This function is called to process a _TPM_Hash_Data indication. +LIB_EXPORT void _TPM_Hash_Data(uint32_t dataSize, // IN: size of data to be extend + unsigned char* data // IN: data buffer +); + +#endif // __TPM_HASH_DATA_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/_TPM_Hash_End_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/_TPM_Hash_End_fp.h new file mode 100644 index 0000000..0a9c72a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/_TPM_Hash_End_fp.h @@ -0,0 +1,46 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 28, 2019 Time: 08:25:19PM + */ + +#ifndef __TPM_HASH_END_FP_H_ +#define __TPM_HASH_END_FP_H_ + +// This function is called to process a _TPM_Hash_End indication. +LIB_EXPORT void _TPM_Hash_End(void); + +#endif // __TPM_HASH_END_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/_TPM_Hash_Start_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/_TPM_Hash_Start_fp.h new file mode 100644 index 0000000..d67b015 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/_TPM_Hash_Start_fp.h @@ -0,0 +1,46 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 28, 2019 Time: 08:25:19PM + */ + +#ifndef __TPM_HASH_START_FP_H_ +#define __TPM_HASH_START_FP_H_ + +// This function is called to process a _TPM_Hash_Start indication. +LIB_EXPORT void _TPM_Hash_Start(void); + +#endif // __TPM_HASH_START_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/_TPM_Init_fp.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/_TPM_Init_fp.h new file mode 100644 index 0000000..42fbba2 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/prototypes/_TPM_Init_fp.h @@ -0,0 +1,46 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmPrototypes; Version 3.0 July 18, 2017 + * Date: Mar 28, 2019 Time: 08:25:19PM + */ + +#ifndef __TPM_INIT_FP_H_ +#define __TPM_INIT_FP_H_ + +// This function is used to process a _TPM_Init indication. +LIB_EXPORT void _TPM_Init(void); + +#endif // __TPM_INIT_FP_H_ diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/swap.h b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/swap.h new file mode 100644 index 0000000..6b3a3e4 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/include/swap.h @@ -0,0 +1,129 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (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 _SWAP_H +#define _SWAP_H + +#if LITTLE_ENDIAN_TPM +# define TO_BIG_ENDIAN_UINT16(i) REVERSE_ENDIAN_16(i) +# define FROM_BIG_ENDIAN_UINT16(i) REVERSE_ENDIAN_16(i) +# define TO_BIG_ENDIAN_UINT32(i) REVERSE_ENDIAN_32(i) +# define FROM_BIG_ENDIAN_UINT32(i) REVERSE_ENDIAN_32(i) +# define TO_BIG_ENDIAN_UINT64(i) REVERSE_ENDIAN_64(i) +# define FROM_BIG_ENDIAN_UINT64(i) REVERSE_ENDIAN_64(i) +#else +# define TO_BIG_ENDIAN_UINT16(i) (i) +# define FROM_BIG_ENDIAN_UINT16(i) (i) +# define TO_BIG_ENDIAN_UINT32(i) (i) +# define FROM_BIG_ENDIAN_UINT32(i) (i) +# define TO_BIG_ENDIAN_UINT64(i) (i) +# define FROM_BIG_ENDIAN_UINT64(i) (i) +#endif + +#if AUTO_ALIGN == NO + +// The aggregation macros for machines that do not allow unaligned access or for +// little-endian machines. + +// Aggregate bytes into an UINT + +# define BYTE_ARRAY_TO_UINT8(b) (uint8_t)((b)[0]) +# define BYTE_ARRAY_TO_UINT16(b) ByteArrayToUint16((BYTE*)(b)) +# define BYTE_ARRAY_TO_UINT32(b) ByteArrayToUint32((BYTE*)(b)) +# define BYTE_ARRAY_TO_UINT64(b) ByteArrayToUint64((BYTE*)(b)) +# define UINT8_TO_BYTE_ARRAY(i, b) ((b)[0] = (uint8_t)(i)) +# define UINT16_TO_BYTE_ARRAY(i, b) Uint16ToByteArray((i), (BYTE*)(b)) +# define UINT32_TO_BYTE_ARRAY(i, b) Uint32ToByteArray((i), (BYTE*)(b)) +# define UINT64_TO_BYTE_ARRAY(i, b) Uint64ToByteArray((i), (BYTE*)(b)) + +#else // AUTO_ALIGN + +# if BIG_ENDIAN_TPM +// the big-endian macros for machines that allow unaligned memory access +// Aggregate a byte array into a UINT +# define BYTE_ARRAY_TO_UINT8(b) *((uint8_t*)(b)) +# define BYTE_ARRAY_TO_UINT16(b) *((uint16_t*)(b)) +# define BYTE_ARRAY_TO_UINT32(b) *((uint32_t*)(b)) +# define BYTE_ARRAY_TO_UINT64(b) *((uint64_t*)(b)) + +// Disaggregate a UINT into a byte array + +# define UINT8_TO_BYTE_ARRAY(i, b) \ + { \ + *((uint8_t*)(b)) = (i); \ + } +# define UINT16_TO_BYTE_ARRAY(i, b) \ + { \ + *((uint16_t*)(b)) = (i); \ + } +# define UINT32_TO_BYTE_ARRAY(i, b) \ + { \ + *((uint32_t*)(b)) = (i); \ + } +# define UINT64_TO_BYTE_ARRAY(i, b) \ + { \ + *((uint64_t*)(b)) = (i); \ + } +# else +// the little endian macros for machines that allow unaligned memory access +// the big-endian macros for machines that allow unaligned memory access +// Aggregate a byte array into a UINT +# define BYTE_ARRAY_TO_UINT8(b) *((uint8_t*)(b)) +# define BYTE_ARRAY_TO_UINT16(b) REVERSE_ENDIAN_16(*((uint16_t*)(b))) +# define BYTE_ARRAY_TO_UINT32(b) REVERSE_ENDIAN_32(*((uint32_t*)(b))) +# define BYTE_ARRAY_TO_UINT64(b) REVERSE_ENDIAN_64(*((uint64_t*)(b))) + +// Disaggregate a UINT into a byte array + +# define UINT8_TO_BYTE_ARRAY(i, b) \ + { \ + *((uint8_t*)(b)) = (i); \ + } +# define UINT16_TO_BYTE_ARRAY(i, b) \ + { \ + *((uint16_t*)(b)) = REVERSE_ENDIAN_16(i); \ + } +# define UINT32_TO_BYTE_ARRAY(i, b) \ + { \ + *((uint32_t*)(b)) = REVERSE_ENDIAN_32(i); \ + } +# define UINT64_TO_BYTE_ARRAY(i, b) \ + { \ + *((uint64_t*)(b)) = REVERSE_ENDIAN_64(i); \ + } +# endif // BIG_ENDIAN_TPM + +#endif // AUTO_ALIGN == NO + +#endif // _SWAP_H diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/X509/TpmASN1.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/X509/TpmASN1.c new file mode 100644 index 0000000..f891442 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/X509/TpmASN1.c @@ -0,0 +1,460 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Includes +#include "Tpm.h" +#define _OIDS_ +#include "OIDs.h" +#include "TpmASN1.h" +#include "TpmASN1_fp.h" + +//** Unmarshaling Functions + +//*** ASN1UnmarshalContextInitialize() +// Function does standard initialization of a context. +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure +BOOL ASN1UnmarshalContextInitialize( + ASN1UnmarshalContext* ctx, INT16 size, BYTE* buffer) +{ + VERIFY(buffer != NULL); + VERIFY(size > 0); + ctx->buffer = buffer; + ctx->size = size; + ctx->offset = 0; + ctx->tag = 0xFF; + return TRUE; +Error: + return FALSE; +} + +//***ASN1DecodeLength() +// This function extracts the length of an element from 'buffer' starting at 'offset'. +// Return Type: UINT16 +// >=0 the extracted length +// <0 an error +INT16 +ASN1DecodeLength(ASN1UnmarshalContext* ctx) +{ + BYTE first; // Next octet in buffer + INT16 value; + // + VERIFY(ctx->offset < ctx->size); + first = NEXT_OCTET(ctx); + // If the number of octets of the entity is larger than 127, then the first octet + // is the number of octets in the length specifier. + if(first >= 0x80) + { + // Make sure that this length field is contained with the structure being + // parsed + CHECK_SIZE(ctx, (first & 0x7F)); + if(first == 0x82) + { + // Two octets of size + // get the next value + value = (INT16)NEXT_OCTET(ctx); + // Make sure that the result will fit in an INT16 + VERIFY(value < 0x0080); + // Shift up and add next octet + value = (value << 8) + NEXT_OCTET(ctx); + } + else if(first == 0x81) + value = NEXT_OCTET(ctx); + // Sizes larger than will fit in a INT16 are an error + else + goto Error; + } + else + value = first; + // Make sure that the size defined something within the current context + CHECK_SIZE(ctx, value); + return value; +Error: + ctx->size = -1; // Makes everything fail from now on. + return -1; +} + +//***ASN1NextTag() +// This function extracts the next type from 'buffer' starting at 'offset'. +// It advances 'offset' as it parses the type and the length of the type. It returns +// the length of the type. On return, the 'length' octets starting at 'offset' are the +// octets of the type. +// Return Type: UINT +// >=0 the number of octets in 'type' +// <0 an error +INT16 +ASN1NextTag(ASN1UnmarshalContext* ctx) +{ + // A tag to get? + VERIFY(ctx->offset < ctx->size); + // Get it + ctx->tag = NEXT_OCTET(ctx); + // Make sure that it is not an extended tag + VERIFY((ctx->tag & 0x1F) != 0x1F); + // Get the length field and return that + return ASN1DecodeLength(ctx); + +Error: + // Attempt to read beyond the end of the context or an illegal tag + ctx->size = -1; // Persistent failure + ctx->tag = 0xFF; + return -1; +} + +//*** ASN1GetBitStringValue() +// Try to parse a bit string of up to 32 bits from a value that is expected to be +// a bit string. The bit string is left justified so that the MSb of the input is +// the MSb of the returned value. +// If there is a general parsing error, the context->size is set to -1. +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure +BOOL ASN1GetBitStringValue(ASN1UnmarshalContext* ctx, UINT32* val) +{ + int shift; + INT16 length; + UINT32 value = 0; + int inputBits; + // + length = ASN1NextTag(ctx); + VERIFY(length >= 1); + VERIFY(ctx->tag == ASN1_BITSTRING); + // Get the shift value for the bit field (how many bits to lop off of the end) + shift = NEXT_OCTET(ctx); + length--; + // Get the number of bits in the input + inputBits = (8 * length) - shift; + // the shift count has to make sense + VERIFY((shift < 8) && ((length > 0) || (shift == 0))); + // if there are any bytes left + for(; length > 1; length--) + { + + // for all but the last octet, just shift and add the new octet + VERIFY((value & 0xFF000000) == 0); // can't loose significant bits + value = (value << 8) + NEXT_OCTET(ctx); + } + if(length == 1) + { + // for the last octet, just shift the accumulated value enough to + // accept the significant bits in the last octet and shift the last + // octet down + VERIFY(((value & (0xFF000000 << (8 - shift)))) == 0); + value = (value << (8 - shift)) + (NEXT_OCTET(ctx) >> shift); + } + // 'Left justify' the result + if(inputBits > 0) + value <<= (32 - inputBits); + *val = value; + return TRUE; +Error: + ctx->size = -1; + return FALSE; +} + +//******************************************************************* +//** Marshaling Functions +//******************************************************************* + +//*** Introduction +// Marshaling of an ASN.1 structure is accomplished from the bottom up. That is, +// the things that will be at the end of the structure are added last. To manage the +// collecting of the relative sizes, start a context for the outermost container, if +// there is one, and then placing items in from the bottom up. If the bottom-most +// item is also within a structure, create a nested context by calling +// ASN1StartMarshalingContext(). +// +// The context control structure contains a 'buffer' pointer, an 'offset', an 'end' +// and a stack. 'offset' is the offset from the start of the buffer of the last added +// byte. When 'offset' reaches 0, the buffer is full. 'offset' is a signed value so +// that, when it becomes negative, there is an overflow. Only two functions are +// allowed to move bytes into the buffer: ASN1PushByte() and ASN1PushBytes(). These +// functions make sure that no data is written beyond the end of the buffer. +// +// When a new context is started, the current value of 'end' is pushed +// on the stack and 'end' is set to 'offset. As bytes are added, offset gets smaller. +// At any time, the count of bytes in the current context is simply 'end' - 'offset'. +// +// Since starting a new context involves setting 'end' = 'offset', the number of bytes +// in the context starts at 0. The nominal way of ending a context is to use +// 'end' - 'offset' to set the length value, and then a tag is added to the buffer. +// Then the previous 'end' value is popped meaning that the context just ended +// becomes a member of the now current context. +// +// The nominal strategy for building a completed ASN.1 structure is to push everything +// into the buffer and then move everything to the start of the buffer. The move is +// simple as the size of the move is the initial 'end' value minus the final 'offset' +// value. The destination is 'buffer' and the source is 'buffer' + 'offset'. As Skippy +// would say "Easy peasy, Joe." +// +// It is not necessary to provide a buffer into which the data is placed. If no buffer +// is provided, then the marshaling process will return values needed for marshaling. +// On strategy for filling the buffer would be to execute the process for building +// the structure without using a buffer. This would return the overall size of the +// structure. Then that amount of data could be allocated for the buffer and the fill +// process executed again with the data going into the buffer. At the end, the data +// would be in its final resting place. + +//*** ASN1InitialializeMarshalContext() +// This creates a structure for handling marshaling of an ASN.1 formatted data +// structure. +void ASN1InitialializeMarshalContext( + ASN1MarshalContext* ctx, INT16 length, BYTE* buffer) +{ + ctx->buffer = buffer; + if(buffer) + ctx->offset = length; + else + ctx->offset = INT16_MAX; + ctx->end = ctx->offset; + ctx->depth = -1; +} + +//*** ASN1StartMarshalContext() +// This starts a new constructed element. It is constructed on 'top' of the value +// that was previously placed in the structure. +void ASN1StartMarshalContext(ASN1MarshalContext* ctx) +{ + pAssert((ctx->depth + 1) < MAX_DEPTH); + ctx->depth++; + ctx->ends[ctx->depth] = ctx->end; + ctx->end = ctx->offset; +} + +//*** ASN1EndMarshalContext() +// This function restores the end pointer for an encapsulating structure. +// Return Type: INT16 +// > 0 the size of the encapsulated structure that was just ended +// <= 0 an error +INT16 +ASN1EndMarshalContext(ASN1MarshalContext* ctx) +{ + INT16 length; + pAssert(ctx->depth >= 0); + length = ctx->end - ctx->offset; + ctx->end = ctx->ends[ctx->depth--]; + if((ctx->depth == -1) && (ctx->buffer)) + { + MemoryCopy(ctx->buffer, ctx->buffer + ctx->offset, ctx->end - ctx->offset); + } + return length; +} + +//***ASN1EndEncapsulation() +// This function puts a tag and length in the buffer. In this function, an embedded +// BIT_STRING is assumed to be a collection of octets. To indicate that all bits +// are used, a byte of zero is prepended. If a raw bit-string is needed, a new +// function like ASN1PushInteger() would be needed. +// Return Type: INT16 +// > 0 number of octets in the encapsulation +// == 0 failure +UINT16 +ASN1EndEncapsulation(ASN1MarshalContext* ctx, BYTE tag) +{ + // only add a leading zero for an encapsulated BIT STRING + if(tag == ASN1_BITSTRING) + ASN1PushByte(ctx, 0); + ASN1PushTagAndLength(ctx, tag, ctx->end - ctx->offset); + return ASN1EndMarshalContext(ctx); +} + +//*** ASN1PushByte() +BOOL ASN1PushByte(ASN1MarshalContext* ctx, BYTE b) +{ + if(ctx->offset > 0) + { + ctx->offset -= 1; + if(ctx->buffer) + ctx->buffer[ctx->offset] = b; + return TRUE; + } + ctx->offset = -1; + return FALSE; +} + +//*** ASN1PushBytes() +// Push some raw bytes onto the buffer. 'count' cannot be zero. +// Return Type: IN16 +// > 0 count bytes +// == 0 failure unless count was zero +INT16 +ASN1PushBytes(ASN1MarshalContext* ctx, INT16 count, const BYTE* buffer) +{ + // make sure that count is not negative which would mess up the math; and that + // if there is a count, there is a buffer + VERIFY((count >= 0) && ((buffer != NULL) || (count == 0))); + // back up the offset to determine where the new octets will get pushed + ctx->offset -= count; + // can't go negative + VERIFY(ctx->offset >= 0); + // if there are buffers, move the data, otherwise, assume that this is just a + // test. + if(count && buffer && ctx->buffer) + MemoryCopy(&ctx->buffer[ctx->offset], buffer, count); + return count; +Error: + ctx->offset = -1; + return 0; +} + +//*** ASN1PushNull() +// Return Type: IN16 +// > 0 count bytes +// == 0 failure unless count was zero +INT16 +ASN1PushNull(ASN1MarshalContext* ctx) +{ + ASN1PushByte(ctx, 0); + ASN1PushByte(ctx, ASN1_NULL); + return (ctx->offset >= 0) ? 2 : 0; +} + +//*** ASN1PushLength() +// Push a length value. This will only handle length values that fit in an INT16. +// Return Type: UINT16 +// > 0 number of bytes added +// == 0 failure +INT16 +ASN1PushLength(ASN1MarshalContext* ctx, INT16 len) +{ + UINT16 start = ctx->offset; + VERIFY(len >= 0); + if(len <= 127) + ASN1PushByte(ctx, (BYTE)len); + else + { + ASN1PushByte(ctx, (BYTE)(len & 0xFF)); + len >>= 8; + if(len == 0) + ASN1PushByte(ctx, 0x81); + else + { + ASN1PushByte(ctx, (BYTE)(len)); + ASN1PushByte(ctx, 0x82); + } + } + goto Exit; +Error: + ctx->offset = -1; +Exit: + return (ctx->offset > 0) ? start - ctx->offset : 0; +} + +//*** ASN1PushTagAndLength() +// Return Type: INT16 +// > 0 number of bytes added +// == 0 failure +INT16 +ASN1PushTagAndLength(ASN1MarshalContext* ctx, BYTE tag, INT16 length) +{ + INT16 bytes; + bytes = ASN1PushLength(ctx, length); + bytes += (INT16)ASN1PushByte(ctx, tag); + return (ctx->offset < 0) ? 0 : bytes; +} + +//*** ASN1PushTaggedOctetString() +// This function will push a random octet string. +// Return Type: INT16 +// > 0 number of bytes added +// == 0 failure +INT16 +ASN1PushTaggedOctetString( + ASN1MarshalContext* ctx, INT16 size, const BYTE* string, BYTE tag) +{ + ASN1PushBytes(ctx, size, string); + // PushTagAndLenght just tells how many octets it added so the total size of this + // element is the sum of those octets and input size. + size += ASN1PushTagAndLength(ctx, tag, size); + return size; +} + +//*** ASN1PushUINT() +// This function pushes an native-endian integer value. This just changes a +// native-endian integer into a big-endian byte string and calls ASN1PushInteger(). +// That function will remove leading zeros and make sure that the number is positive. +// Return Type: IN16 +// > 0 count bytes +// == 0 failure unless count was zero +INT16 +ASN1PushUINT(ASN1MarshalContext* ctx, UINT32 integer) +{ + BYTE marshaled[4]; + UINT32_TO_BYTE_ARRAY(integer, marshaled); + return ASN1PushInteger(ctx, 4, marshaled); +} + +//*** ASN1PushInteger +// Push a big-endian integer on the end of the buffer +// Return Type: UINT16 +// > 0 the number of bytes marshaled for the integer +// == 0 failure +INT16 +ASN1PushInteger(ASN1MarshalContext* ctx, // IN/OUT: buffer context + INT16 iLen, // IN: octets of the integer + BYTE* integer // IN: big-endian integer +) +{ + // no leading 0's + while((*integer == 0) && (--iLen > 0)) + integer++; + // Move the bytes to the buffer + ASN1PushBytes(ctx, iLen, integer); + // if needed, add a leading byte of 0 to make the number positive + if(*integer & 0x80) + iLen += (INT16)ASN1PushByte(ctx, 0); + // PushTagAndLength just tells how many octets it added so the total size of this + // element is the sum of those octets and the adjusted input size. + iLen += ASN1PushTagAndLength(ctx, ASN1_INTEGER, iLen); + return iLen; +} + +//*** ASN1PushOID() +// This function is used to add an OID. An OID is 0x06 followed by a byte of size +// followed by size bytes. This is used to avoid having to do anything special in the +// definition of an OID. +// Return Type: UINT16 +// > 0 the number of bytes marshaled for the integer +// == 0 failure +INT16 +ASN1PushOID(ASN1MarshalContext* ctx, const BYTE* OID) +{ + if((*OID == ASN1_OBJECT_IDENTIFIER) && ((OID[1] & 0x80) == 0)) + { + return ASN1PushBytes(ctx, OID[1] + 2, OID); + } + ctx->offset = -1; + return 0; +} diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/X509/X509_ECC.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/X509/X509_ECC.c new file mode 100644 index 0000000..336e148 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/X509/X509_ECC.c @@ -0,0 +1,139 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Includes +#include "Tpm.h" +#include "X509.h" +#include "OIDs.h" +#include "TpmASN1_fp.h" +#include "X509_ECC_fp.h" +#include "X509_spt_fp.h" +#include "CryptHash_fp.h" + +//** Functions + +//*** X509PushPoint() +// This seems like it might be used more than once so... +// Return Type: INT16 +// > 0 number of bytes added +// == 0 failure +INT16 +X509PushPoint(ASN1MarshalContext* ctx, TPMS_ECC_POINT* p) +{ + // Push a bit string containing the public key. For now, push the x, and y + // coordinates of the public point, bottom up + ASN1StartMarshalContext(ctx); // BIT STRING + { + ASN1PushBytes(ctx, p->y.t.size, p->y.t.buffer); + ASN1PushBytes(ctx, p->x.t.size, p->x.t.buffer); + ASN1PushByte(ctx, 0x04); + } + return ASN1EndEncapsulation(ctx, ASN1_BITSTRING); // Ends BIT STRING +} + +//*** X509AddSigningAlgorithmECC() +// This creates the singing algorithm data. +// Return Type: INT16 +// > 0 number of bytes added +// == 0 failure +INT16 +X509AddSigningAlgorithmECC( + OBJECT* signKey, TPMT_SIG_SCHEME* scheme, ASN1MarshalContext* ctx) +{ + PHASH_DEF hashDef = CryptGetHashDef(scheme->details.any.hashAlg); + // + NOT_REFERENCED(signKey); + // If the desired hashAlg definition wasn't found... + if(hashDef->hashAlg != scheme->details.any.hashAlg) + return 0; + + switch(scheme->scheme) + { +#if ALG_ECDSA + case TPM_ALG_ECDSA: + // Make sure that we have an OID for this hash and ECC + if((hashDef->ECDSA)[0] != ASN1_OBJECT_IDENTIFIER) + break; + // if this is just an implementation check, indicate that this + // combination is supported + if(!ctx) + return 1; + ASN1StartMarshalContext(ctx); + ASN1PushOID(ctx, hashDef->ECDSA); + return ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE); +#endif // ALG_ECDSA + default: + break; + } + return 0; +} + +//*** X509AddPublicECC() +// This function will add the publicKey description to the DER data. If ctx is +// NULL, then no data is transferred and this function will indicate if the TPM +// has the values for DER-encoding of the public key. +// Return Type: INT16 +// > 0 number of bytes added +// == 0 failure +INT16 +X509AddPublicECC(OBJECT* object, ASN1MarshalContext* ctx) +{ + const BYTE* curveOid = + CryptEccGetOID(object->publicArea.parameters.eccDetail.curveID); + if((curveOid == NULL) || (*curveOid != ASN1_OBJECT_IDENTIFIER)) + return 0; + // + // + // SEQUENCE (2 elem) 1st + // SEQUENCE (2 elem) 2nd + // OBJECT IDENTIFIER 1.2.840.10045.2.1 ecPublicKey (ANSI X9.62 public key type) + // OBJECT IDENTIFIER 1.2.840.10045.3.1.7 prime256v1 (ANSI X9.62 named curve) + // BIT STRING (520 bit) 000001001010000111010101010111001001101101000100000010... + // + // If this is a check to see if the key can be encoded, it can. + // Need to mark the end sequence + if(ctx == NULL) + return 1; + ASN1StartMarshalContext(ctx); // SEQUENCE (2 elem) 1st + { + X509PushPoint(ctx, &object->publicArea.unique.ecc); // BIT STRING + ASN1StartMarshalContext(ctx); // SEQUENCE (2 elem) 2nd + { + ASN1PushOID(ctx, curveOid); // curve dependent + ASN1PushOID(ctx, OID_ECC_PUBLIC); // (1.2.840.10045.2.1) + } + ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE); // Ends SEQUENCE 2nd + } + return ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE); // Ends SEQUENCE 1st +} diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/X509/X509_RSA.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/X509/X509_RSA.c new file mode 100644 index 0000000..15d3369 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/X509/X509_RSA.c @@ -0,0 +1,230 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Includes +#include "Tpm.h" +#include "X509.h" +#include "TpmASN1_fp.h" +#include "X509_RSA_fp.h" +#include "X509_spt_fp.h" +#include "CryptHash_fp.h" +#include "CryptRsa_fp.h" + +//** Functions + +#if ALG_RSA + +//*** X509AddSigningAlgorithmRSA() +// This creates the singing algorithm data. +// Return Type: INT16 +// > 0 number of bytes added +// == 0 failure +INT16 +X509AddSigningAlgorithmRSA( + OBJECT* signKey, TPMT_SIG_SCHEME* scheme, ASN1MarshalContext* ctx) +{ + TPM_ALG_ID hashAlg = scheme->details.any.hashAlg; + PHASH_DEF hashDef = CryptGetHashDef(hashAlg); + // + NOT_REFERENCED(signKey); + // return failure if hash isn't implemented + if(hashDef->hashAlg != hashAlg) + return 0; + switch(scheme->scheme) + { + case TPM_ALG_RSASSA: + { + // if the hash is implemented but there is no PKCS1 OID defined + // then this is not a valid signing combination. + if(hashDef->PKCS1[0] != ASN1_OBJECT_IDENTIFIER) + break; + if(ctx == NULL) + return 1; + return X509PushAlgorithmIdentifierSequence(ctx, hashDef->PKCS1); + } + case TPM_ALG_RSAPSS: + // leave if this is just an implementation check + if(ctx == NULL) + return 1; + // In the case of SHA1, everything is default and RFC4055 says that + // implementations that do signature generation MUST omit the parameter + // when defaults are used. )-: + if(hashDef->hashAlg == TPM_ALG_SHA1) + { + return X509PushAlgorithmIdentifierSequence(ctx, OID_RSAPSS); + } + else + { + // Going to build something that looks like: + // SEQUENCE (2 elem) + // OBJECT IDENTIFIER 1.2.840.113549.1.1.10 rsaPSS (PKCS #1) + // SEQUENCE (3 elem) + // [0] (1 elem) + // SEQUENCE (2 elem) + // OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.1 sha-256 + // NULL + // [1] (1 elem) + // SEQUENCE (2 elem) + // OBJECT IDENTIFIER 1.2.840.113549.1.1.8 pkcs1-MGF + // SEQUENCE (2 elem) + // OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.1 sha-256 + // NULL + // [2] (1 elem) salt length + // INTEGER 32 + + // The indentation is just to keep track of where we are in the + // structure + ASN1StartMarshalContext(ctx); // SEQUENCE (2 elements) + { + ASN1StartMarshalContext(ctx); // SEQUENCE (3 elements) + { + // [2] (1 elem) salt length + // INTEGER 32 + ASN1StartMarshalContext(ctx); + { + INT16 saltSize = CryptRsaPssSaltSize( + (INT16)hashDef->digestSize, + (INT16)signKey->publicArea.unique.rsa.t.size); + ASN1PushUINT(ctx, saltSize); + } + ASN1EndEncapsulation(ctx, ASN1_APPLICAIION_SPECIFIC + 2); + + // Add the mask generation algorithm + // [1] (1 elem) + // SEQUENCE (2 elem) 1st + // OBJECT IDENTIFIER 1.2.840.113549.1.1.8 pkcs1-MGF + // SEQUENCE (2 elem) 2nd + // OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.1 sha-256 + // NULL + ASN1StartMarshalContext(ctx); // mask context [1] (1 elem) + { + ASN1StartMarshalContext(ctx); // SEQUENCE (2 elem) 1st + // Handle the 2nd Sequence (sequence (object, null)) + { + // This adds a NULL, then an OID and a SEQUENCE + // wrapper. + X509PushAlgorithmIdentifierSequence(ctx, + hashDef->OID); + // add the pkcs1-MGF OID + ASN1PushOID(ctx, OID_MGF1); + } + // End outer sequence + ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE); + } + // End the [1] + ASN1EndEncapsulation(ctx, ASN1_APPLICAIION_SPECIFIC + 1); + + // Add the hash algorithm + // [0] (1 elem) + // SEQUENCE (2 elem) (done by + // X509PushAlgorithmIdentifierSequence) + // OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.1 sha-256 (NIST) + // NULL + ASN1StartMarshalContext(ctx); // [0] (1 elem) + { + X509PushAlgorithmIdentifierSequence(ctx, hashDef->OID); + } + ASN1EndEncapsulation(ctx, (ASN1_APPLICAIION_SPECIFIC + 0)); + } + // SEQUENCE (3 elements) end + ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE); + + // RSA PSS OID + // OBJECT IDENTIFIER 1.2.840.113549.1.1.10 rsaPSS (PKCS #1) + ASN1PushOID(ctx, OID_RSAPSS); + } + // End Sequence (2 elements) + return ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE); + } + default: + break; + } + return 0; +} + +//*** X509AddPublicRSA() +// This function will add the publicKey description to the DER data. If fillPtr is +// NULL, then no data is transferred and this function will indicate if the TPM +// has the values for DER-encoding of the public key. +// Return Type: INT16 +// > 0 number of bytes added +// == 0 failure +INT16 +X509AddPublicRSA(OBJECT* object, ASN1MarshalContext* ctx) +{ + UINT32 exp = object->publicArea.parameters.rsaDetail.exponent; + // + /* + SEQUENCE (2 elem) 1st + SEQUENCE (2 elem) 2nd + OBJECT IDENTIFIER 1.2.840.113549.1.1.1 rsaEncryption (PKCS #1) + NULL + BIT STRING (1 elem) + SEQUENCE (2 elem) 3rd + INTEGER (2048 bit) 2197304513741227955725834199357401 + INTEGER 65537 +*/ + // If this is a check to see if the key can be encoded, it can. + // Need to mark the end sequence + if(ctx == NULL) + return 1; + ASN1StartMarshalContext(ctx); // SEQUENCE (2 elem) 1st + ASN1StartMarshalContext(ctx); // BIT STRING + ASN1StartMarshalContext(ctx); // SEQUENCE *(2 elem) 3rd + + // Get public exponent in big-endian byte order. + if(exp == 0) + exp = RSA_DEFAULT_PUBLIC_EXPONENT; + + // Push a 4 byte integer. This might get reduced if there are leading zeros or + // extended if the high order byte is negative. + ASN1PushUINT(ctx, exp); + // Push the public key as an integer + ASN1PushInteger(ctx, + object->publicArea.unique.rsa.t.size, + object->publicArea.unique.rsa.t.buffer); + // Embed this in a SEQUENCE tag and length in for the key, exponent sequence + ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE); // SEQUENCE (3rd) + + // Embed this in a BIT STRING + ASN1EndEncapsulation(ctx, ASN1_BITSTRING); + + // Now add the formatted SEQUENCE for the RSA public key OID. This is a + // fully constructed value so it doesn't need to have a context started + X509PushAlgorithmIdentifierSequence(ctx, OID_PKCS1_PUB); + + return ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE); +} + +#endif // ALG_RSA diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/X509/X509_spt.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/X509/X509_spt.c new file mode 100644 index 0000000..7594b6b --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/X509/X509_spt.c @@ -0,0 +1,285 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Includes +#include "Tpm.h" +#include "TpmASN1.h" +#include "TpmASN1_fp.h" +#define _X509_SPT_ +#include "X509.h" +#include "X509_spt_fp.h" +#if ALG_RSA +# include "X509_RSA_fp.h" +#endif // ALG_RSA +#if ALG_ECC +# include "X509_ECC_fp.h" +#endif // ALG_ECC +#if ALG_SM2 +//# include "X509_SM2_fp.h" +#endif // ALG_RSA + +//** Unmarshaling Functions + +//*** X509FindExtensionByOID() +// This will search a list of X509 extensions to find an extension with the +// requested OID. If the extension is found, the output context ('ctx') is set up +// to point to the OID in the extension. +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure (could be catastrophic) +BOOL X509FindExtensionByOID(ASN1UnmarshalContext* ctxIn, // IN: the context to search + ASN1UnmarshalContext* ctx, // OUT: the extension context + const BYTE* OID // IN: oid to search for +) +{ + INT16 length; + // + pAssert(ctxIn != NULL); + // Make the search non-destructive of the input if ctx provided. Otherwise, use + // the provided context. + if(ctx == NULL) + ctx = ctxIn; + // if the provided search context is different from the context of the extension, + // then copy the search context to the search context. + else if(ctx != ctxIn) + *ctx = *ctxIn; + // Now, search in the extension context + for(; ctx->size > ctx->offset; ctx->offset += length) + { + VERIFY((length = ASN1NextTag(ctx)) >= 0); + // If this is not a constructed sequence, then it doesn't belong + // in the extensions. + VERIFY(ctx->tag == ASN1_CONSTRUCTED_SEQUENCE); + // Make sure that this entry could hold the OID + if(length >= OID_SIZE(OID)) + { + // See if this is a match for the provided object identifier. + if(MemoryEqual(OID, &(ctx->buffer[ctx->offset]), OID_SIZE(OID))) + { + // Return with ' ctx' set to point to the start of the OID with the size + // set to be the size of the SEQUENCE + ctx->buffer += ctx->offset; + ctx->offset = 0; + ctx->size = length; + return TRUE; + } + } + } + VERIFY(ctx->offset == ctx->size); + return FALSE; +Error: + ctxIn->size = -1; + ctx->size = -1; + return FALSE; +} + +//*** X509GetExtensionBits() +// This function will extract a bit field from an extension. If the extension doesn't +// contain a bit string, it will fail. +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure +UINT32 +X509GetExtensionBits(ASN1UnmarshalContext* ctx, UINT32* value) +{ + INT16 length; + // + while(((length = ASN1NextTag(ctx)) > 0) && (ctx->size > ctx->offset)) + { + // Since this is an extension, the extension value will be in an OCTET STRING + if(ctx->tag == ASN1_OCTET_STRING) + { + return ASN1GetBitStringValue(ctx, value); + } + ctx->offset += length; + } + ctx->size = -1; + return FALSE; +} + +//***X509ProcessExtensions() +// This function is used to process the TPMA_OBJECT and KeyUsage extensions. It is not +// in the CertifyX509.c code because it makes the code harder to follow. +// Return Type: TPM_RC +// TPM_RCS_ATTRIBUTES the attributes of object are not consistent with +// the extension setting +// TPM_RCS_VALUE problem parsing the extensions +TPM_RC +X509ProcessExtensions( + OBJECT* object, // IN: The object with the attributes to + // check + stringRef* extension // IN: The start and length of the extensions +) +{ + ASN1UnmarshalContext ctx; + ASN1UnmarshalContext extensionCtx; + INT16 length; + UINT32 value; + TPMA_OBJECT attributes = object->publicArea.objectAttributes; + // + if(!ASN1UnmarshalContextInitialize(&ctx, extension->len, extension->buf) + || ((length = ASN1NextTag(&ctx)) < 0) || (ctx.tag != X509_EXTENSIONS)) + return TPM_RCS_VALUE; + if(((length = ASN1NextTag(&ctx)) < 0) || (ctx.tag != (ASN1_CONSTRUCTED_SEQUENCE))) + return TPM_RCS_VALUE; + + // Get the extension for the TPMA_OBJECT if there is one + if(X509FindExtensionByOID(&ctx, &extensionCtx, OID_TCG_TPMA_OBJECT) + && X509GetExtensionBits(&extensionCtx, &value)) + { + // If an keyAttributes extension was found, it must be exactly the same as the + // attributes of the object. + // NOTE: MemoryEqual() is used rather than a simple UINT32 compare to avoid + // type-punned pointer warning/error. + if(!MemoryEqual(&value, &attributes, sizeof(value))) + return TPM_RCS_ATTRIBUTES; + } + // Make sure the failure to find the value wasn't because of a fatal error + else if(extensionCtx.size < 0) + return TPM_RCS_VALUE; + + // Get the keyUsage extension. This one is required + if(X509FindExtensionByOID(&ctx, &extensionCtx, OID_KEY_USAGE_EXTENSION) + && X509GetExtensionBits(&extensionCtx, &value)) + { + x509KeyUsageUnion keyUsage; + BOOL badSign; + BOOL badDecrypt; + BOOL badFixedTPM; + BOOL badRestricted; + + // + keyUsage.integer = value; + // For KeyUsage: + // 1) 'sign' is SET if Key Usage includes signing + badSign = ((KEY_USAGE_SIGN.integer & keyUsage.integer) != 0) + && !IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign); + // 2) 'decrypt' is SET if Key Usage includes decryption uses + badDecrypt = ((KEY_USAGE_DECRYPT.integer & keyUsage.integer) != 0) + && !IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt); + // 3) 'fixedTPM' is SET if Key Usage is non-repudiation + badFixedTPM = IS_ATTRIBUTE(keyUsage.x509, TPMA_X509_KEY_USAGE, nonrepudiation) + && !IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM); + // 4)'restricted' is SET if Key Usage is for key agreement. + badRestricted = IS_ATTRIBUTE(keyUsage.x509, TPMA_X509_KEY_USAGE, keyAgreement) + && !IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted); + if(badSign || badDecrypt || badFixedTPM || badRestricted) + return TPM_RCS_VALUE; + } + else + // The KeyUsage extension is required + return TPM_RCS_VALUE; + + return TPM_RC_SUCCESS; +} + +//** Marshaling Functions + +//*** X509AddSigningAlgorithm() +// This creates the singing algorithm data. +// Return Type: INT16 +// > 0 number of octets added +// <= 0 failure +INT16 +X509AddSigningAlgorithm( + ASN1MarshalContext* ctx, OBJECT* signKey, TPMT_SIG_SCHEME* scheme) +{ + switch(signKey->publicArea.type) + { +#if ALG_RSA + case TPM_ALG_RSA: + return X509AddSigningAlgorithmRSA(signKey, scheme, ctx); +#endif // ALG_RSA +#if ALG_ECC + case TPM_ALG_ECC: + return X509AddSigningAlgorithmECC(signKey, scheme, ctx); +#endif // ALG_ECC +#if ALG_SM2 + case TPM_ALG_SM2: + break; // no signing algorithm for SM2 yet +// return X509AddSigningAlgorithmSM2(signKey, scheme, ctx); +#endif // ALG_SM2 + default: + break; + } + return 0; +} + +//*** X509AddPublicKey() +// This function will add the publicKey description to the DER data. If fillPtr is +// NULL, then no data is transferred and this function will indicate if the TPM +// has the values for DER-encoding of the public key. +// Return Type: INT16 +// > 0 number of octets added +// == 0 failure +INT16 +X509AddPublicKey(ASN1MarshalContext* ctx, OBJECT* object) +{ + switch(object->publicArea.type) + { +#if ALG_RSA + case TPM_ALG_RSA: + return X509AddPublicRSA(object, ctx); +#endif +#if ALG_ECC + case TPM_ALG_ECC: + return X509AddPublicECC(object, ctx); +#endif +#if ALG_SM2 + case TPM_ALG_SM2: + break; +#endif + default: + break; + } + return FALSE; +} + +//*** X509PushAlgorithmIdentifierSequence() +// The function adds the algorithm identifier sequence. +// Return Type: INT16 +// > 0 number of bytes added +// == 0 failure +INT16 +X509PushAlgorithmIdentifierSequence(ASN1MarshalContext* ctx, const BYTE* OID) +{ + // An algorithm ID sequence is: + // SEQUENCE + // OID + // NULL + ASN1StartMarshalContext(ctx); // hash algorithm + ASN1PushNull(ctx); + ASN1PushOID(ctx, OID); + return ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE); +} diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/ECC_Decrypt.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/ECC_Decrypt.c new file mode 100644 index 0000000..b62638a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/ECC_Decrypt.c @@ -0,0 +1,68 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "ECC_Decrypt_fp.h" +#include "CryptEccCrypt_fp.h" + +#if CC_ECC_Decrypt // Conditional expansion of this file + +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES key referenced by 'keyHandle' is restricted +// TPM_RC_KEY keyHandle does not reference an ECC key +// TPM_RC_NO_RESULT internal error in big number processing +// TPM_RC_SCHEME bad scheme +// TPM_RC_VALUE C3 did not match hash of recovered data +TPM_RC +TPM2_ECC_Decrypt(ECC_Decrypt_In* in, // IN: input parameter list + ECC_Decrypt_Out* out // OUT: output parameter list +) +{ + OBJECT* key = HandleToObject(in->keyHandle); + // Parameter validation + // Must be the correct type of key with correct attributes + if(key->publicArea.type != TPM_ALG_ECC) + return TPM_RC_KEY + RC_ECC_Decrypt_keyHandle; + if(IS_ATTRIBUTE(key->publicArea.objectAttributes, TPMA_OBJECT, restricted) + || !IS_ATTRIBUTE(key->publicArea.objectAttributes, TPMA_OBJECT, decrypt)) + return TPM_RCS_ATTRIBUTES + RC_ECC_Decrypt_keyHandle; + // Have to have a scheme selected + if(!CryptEccSelectScheme(key, &in->inScheme)) + return TPM_RCS_SCHEME + RC_ECC_Decrypt_inScheme; + // Command Output + return CryptEccDecrypt( + key, &in->inScheme, &out->plainText, &in->C1.point, &in->C2, &in->C3); +} + +#endif // CC_ECC_Decrypt \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/ECC_Encrypt.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/ECC_Encrypt.c new file mode 100644 index 0000000..914f9eb --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/ECC_Encrypt.c @@ -0,0 +1,61 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "ECC_Encrypt_fp.h" + +#if CC_ECC_Encrypt // Conditional expansion of this file + +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES key referenced by 'keyHandle' is restricted +// TPM_RC_KEY keyHandle does not reference an ECC key +// TPM_RCS_SCHEME bad scheme +TPM_RC +TPM2_ECC_Encrypt(ECC_Encrypt_In* in, // IN: input parameter list + ECC_Encrypt_Out* out // OUT: output parameter list +) +{ + OBJECT* pubKey = HandleToObject(in->keyHandle); + // Parameter validation + if(pubKey->publicArea.type != TPM_ALG_ECC) + return TPM_RC_KEY + RC_ECC_Encrypt_keyHandle; + // Have to have a scheme selected + if(!CryptEccSelectScheme(pubKey, &in->inScheme)) + return TPM_RCS_SCHEME + RC_ECC_Encrypt_inScheme; + // Command Output + return CryptEccEncrypt( + pubKey, &in->inScheme, &in->plainText, &out->C1.point, &out->C2, &out->C3); +} + +#endif // CC_ECC_Encrypt \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/ECC_Parameters.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/ECC_Parameters.c new file mode 100644 index 0000000..42ea0b4 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/ECC_Parameters.c @@ -0,0 +1,60 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "ECC_Parameters_fp.h" + +#if CC_ECC_Parameters // Conditional expansion of this file + +/*(See part 3 specification) +// This command returns the parameters of an ECC curve identified by its TCG +// assigned curveID +*/ +// Return Type: TPM_RC +// TPM_RC_VALUE Unsupported ECC curve ID +TPM_RC +TPM2_ECC_Parameters(ECC_Parameters_In* in, // IN: input parameter list + ECC_Parameters_Out* out // OUT: output parameter list +) +{ + // Command Output + + // Get ECC curve parameters + if(CryptEccGetParameters(in->curveID, &out->parameters)) + return TPM_RC_SUCCESS; + else + return TPM_RCS_VALUE + RC_ECC_Parameters_curveID; +} + +#endif // CC_ECC_Parameters \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/ECDH_KeyGen.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/ECDH_KeyGen.c new file mode 100644 index 0000000..927c1a7 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/ECDH_KeyGen.c @@ -0,0 +1,93 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "ECDH_KeyGen_fp.h" + +#if CC_ECDH_KeyGen // Conditional expansion of this file + +/*(See part 3 specification) +// This command uses the TPM to generate an ephemeral public key and the product +// of the ephemeral private key and the public portion of an ECC key. +*/ +// Return Type: TPM_RC +// TPM_RC_KEY 'keyHandle' does not reference an ECC key +TPM_RC +TPM2_ECDH_KeyGen(ECDH_KeyGen_In* in, // IN: input parameter list + ECDH_KeyGen_Out* out // OUT: output parameter list +) +{ + OBJECT* eccKey; + TPM2B_ECC_PARAMETER sensitive; + TPM_RC result; + + // Input Validation + + eccKey = HandleToObject(in->keyHandle); + + // Referenced key must be an ECC key + if(eccKey->publicArea.type != TPM_ALG_ECC) + return TPM_RCS_KEY + RC_ECDH_KeyGen_keyHandle; + + // Command Output + do + { + TPMT_PUBLIC* keyPublic = &eccKey->publicArea; + // Create ephemeral ECC key + result = CryptEccNewKeyPair(&out->pubPoint.point, + &sensitive, + keyPublic->parameters.eccDetail.curveID); + if(result == TPM_RC_SUCCESS) + { + // Compute Z + result = CryptEccPointMultiply(&out->zPoint.point, + keyPublic->parameters.eccDetail.curveID, + &keyPublic->unique.ecc, + &sensitive, + NULL, + NULL); + // The point in the key is not on the curve. Indicate + // that the key is bad. + if(result == TPM_RC_ECC_POINT) + return TPM_RCS_KEY + RC_ECDH_KeyGen_keyHandle; + // The other possible error from CryptEccPointMultiply is + // TPM_RC_NO_RESULT indicating that the multiplication resulted in + // the point at infinity, so get a new random key and start over + // BTW, this never happens. + } + } while(result == TPM_RC_NO_RESULT); + return result; +} + +#endif // CC_ECDH_KeyGen \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/ECDH_ZGen.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/ECDH_ZGen.c new file mode 100644 index 0000000..db79e7e --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/ECDH_ZGen.c @@ -0,0 +1,86 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "ECDH_ZGen_fp.h" + +#if CC_ECDH_ZGen // Conditional expansion of this file + +/*(See part 3 specification) +// This command uses the TPM to recover the Z value from a public point +*/ +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES key referenced by 'keyA' is restricted or +// not a decrypt key +// TPM_RC_KEY key referenced by 'keyA' is not an ECC key +// TPM_RC_NO_RESULT multiplying 'inPoint' resulted in a +// point at infinity +// TPM_RC_SCHEME the scheme of the key referenced by 'keyA' +// is not TPM_ALG_NULL, TPM_ALG_ECDH, +TPM_RC +TPM2_ECDH_ZGen(ECDH_ZGen_In* in, // IN: input parameter list + ECDH_ZGen_Out* out // OUT: output parameter list +) +{ + TPM_RC result; + OBJECT* eccKey; + + // Input Validation + eccKey = HandleToObject(in->keyHandle); + + // Selected key must be a non-restricted, decrypt ECC key + if(eccKey->publicArea.type != TPM_ALG_ECC) + return TPM_RCS_KEY + RC_ECDH_ZGen_keyHandle; + // Selected key needs to be unrestricted with the 'decrypt' attribute + if(IS_ATTRIBUTE(eccKey->publicArea.objectAttributes, TPMA_OBJECT, restricted) + || !IS_ATTRIBUTE(eccKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt)) + return TPM_RCS_ATTRIBUTES + RC_ECDH_ZGen_keyHandle; + // Make sure the scheme allows this use + if(eccKey->publicArea.parameters.eccDetail.scheme.scheme != TPM_ALG_ECDH + && eccKey->publicArea.parameters.eccDetail.scheme.scheme != TPM_ALG_NULL) + return TPM_RCS_SCHEME + RC_ECDH_ZGen_keyHandle; + // Command Output + // Compute Z. TPM_RC_ECC_POINT or TPM_RC_NO_RESULT may be returned here. + result = CryptEccPointMultiply(&out->outPoint.point, + eccKey->publicArea.parameters.eccDetail.curveID, + &in->inPoint.point, + &eccKey->sensitive.sensitive.ecc, + NULL, + NULL); + if(result != TPM_RC_SUCCESS) + return RcSafeAddToResult(result, RC_ECDH_ZGen_inPoint); + return result; +} + +#endif // CC_ECDH_ZGen \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/EC_Ephemeral.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/EC_Ephemeral.c new file mode 100644 index 0000000..46dda0f --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/EC_Ephemeral.c @@ -0,0 +1,72 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "EC_Ephemeral_fp.h" + +#if CC_EC_Ephemeral // Conditional expansion of this file + +/*(See part 3 specification) +// This command creates an ephemeral key using the commit mechanism +*/ +// Return Type: TPM_RC +// TPM_RC_NO_RESULT the TPM is not able to generate an 'r' value +TPM_RC +TPM2_EC_Ephemeral(EC_Ephemeral_In* in, // IN: input parameter list + EC_Ephemeral_Out* out // OUT: output parameter list +) +{ + TPM2B_ECC_PARAMETER r; + TPM_RC result; + // + do + { + // Get the random value that will be used in the point multiplications + // Note: this does not commit the count. + if(!CryptGenerateR(&r, NULL, in->curveID, NULL)) + return TPM_RC_NO_RESULT; + // do a point multiply + result = + CryptEccPointMultiply(&out->Q.point, in->curveID, NULL, &r, NULL, NULL); + // commit the count value if either the r value results in the point at + // infinity or if the value is good. The commit on the r value for infinity + // is so that the r value will be skipped. + if((result == TPM_RC_SUCCESS) || (result == TPM_RC_NO_RESULT)) + out->counter = CryptCommit(); + } while(result == TPM_RC_NO_RESULT); + + return TPM_RC_SUCCESS; +} + +#endif // CC_EC_Ephemeral \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/RSA_Decrypt.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/RSA_Decrypt.c new file mode 100644 index 0000000..06af24a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/RSA_Decrypt.c @@ -0,0 +1,105 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "RSA_Decrypt_fp.h" + +#if CC_RSA_Decrypt // Conditional expansion of this file + +/*(See part 3 specification) +// decrypts the provided data block and removes the padding if applicable +*/ +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES 'decrypt' is not SET or if 'restricted' is SET in +// the key referenced by 'keyHandle' +// TPM_RC_BINDING The public and private parts of the key are not +// properly bound +// TPM_RC_KEY 'keyHandle' does not reference an unrestricted +// decrypt key +// TPM_RC_SCHEME incorrect input scheme, or the chosen +// 'scheme' is not a valid RSA decrypt scheme +// TPM_RC_SIZE 'cipherText' is not the size of the modulus +// of key referenced by 'keyHandle' +// TPM_RC_VALUE 'label' is not a null terminated string or the value +// of 'cipherText' is greater that the modulus of +// 'keyHandle' or the encoding of the data is not +// valid + +TPM_RC +TPM2_RSA_Decrypt(RSA_Decrypt_In* in, // IN: input parameter list + RSA_Decrypt_Out* out // OUT: output parameter list +) +{ + TPM_RC result; + OBJECT* rsaKey; + TPMT_RSA_DECRYPT* scheme; + + // Input Validation + + rsaKey = HandleToObject(in->keyHandle); + + // The selected key must be an RSA key + if(rsaKey->publicArea.type != TPM_ALG_RSA) + return TPM_RCS_KEY + RC_RSA_Decrypt_keyHandle; + + // The selected key must be an unrestricted decryption key + if(IS_ATTRIBUTE(rsaKey->publicArea.objectAttributes, TPMA_OBJECT, restricted) + || !IS_ATTRIBUTE(rsaKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt)) + return TPM_RCS_ATTRIBUTES + RC_RSA_Decrypt_keyHandle; + + // NOTE: Proper operation of this command requires that the sensitive area + // of the key is loaded. This is assured because authorization is required + // to use the sensitive area of the key. In order to check the authorization, + // the sensitive area has to be loaded, even if authorization is with policy. + + // If label is present, make sure that it is a NULL-terminated string + if(!IsLabelProperlyFormatted(&in->label.b)) + return TPM_RCS_VALUE + RC_RSA_Decrypt_label; + // Command Output + // Select a scheme for decrypt. + scheme = CryptRsaSelectScheme(in->keyHandle, &in->inScheme); + if(scheme == NULL) + return TPM_RCS_SCHEME + RC_RSA_Decrypt_inScheme; + + // Decryption. TPM_RC_VALUE, TPM_RC_SIZE, and TPM_RC_KEY error may be + // returned by CryptRsaDecrypt. + // NOTE: CryptRsaDecrypt can also return TPM_RC_ATTRIBUTES or TPM_RC_BINDING + // when the key is not a decryption key but that was checked above. + out->message.t.size = sizeof(out->message.t.buffer); + result = CryptRsaDecrypt( + &out->message.b, &in->cipherText.b, rsaKey, scheme, &in->label.b); + return result; +} + +#endif // CC_RSA_Decrypt \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/RSA_Encrypt.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/RSA_Encrypt.c new file mode 100644 index 0000000..ec88b7f --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/RSA_Encrypt.c @@ -0,0 +1,89 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "RSA_Encrypt_fp.h" + +#if CC_RSA_Encrypt // Conditional expansion of this file + +/*(See part 3 specification) +// This command performs the padding and encryption of a data block +*/ +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES 'decrypt' attribute is not SET in key referenced +// by 'keyHandle' +// TPM_RC_KEY 'keyHandle' does not reference an RSA key +// TPM_RC_SCHEME incorrect input scheme, or the chosen +// scheme is not a valid RSA decrypt scheme +// TPM_RC_VALUE the numeric value of 'message' is greater than +// the public modulus of the key referenced by +// 'keyHandle', or 'label' is not a null-terminated +// string +TPM_RC +TPM2_RSA_Encrypt(RSA_Encrypt_In* in, // IN: input parameter list + RSA_Encrypt_Out* out // OUT: output parameter list +) +{ + TPM_RC result; + OBJECT* rsaKey; + TPMT_RSA_DECRYPT* scheme; + // Input Validation + rsaKey = HandleToObject(in->keyHandle); + + // selected key must be an RSA key + if(rsaKey->publicArea.type != TPM_ALG_RSA) + return TPM_RCS_KEY + RC_RSA_Encrypt_keyHandle; + // selected key must have the decryption attribute + if(!IS_ATTRIBUTE(rsaKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt)) + return TPM_RCS_ATTRIBUTES + RC_RSA_Encrypt_keyHandle; + + // Is there a label? + if(!IsLabelProperlyFormatted(&in->label.b)) + return TPM_RCS_VALUE + RC_RSA_Encrypt_label; + // Command Output + // Select a scheme for encryption + scheme = CryptRsaSelectScheme(in->keyHandle, &in->inScheme); + if(scheme == NULL) + return TPM_RCS_SCHEME + RC_RSA_Encrypt_inScheme; + + // Encryption. TPM_RC_VALUE, or TPM_RC_SCHEME errors my be returned buy + // CryptEncyptRSA. + out->outData.t.size = sizeof(out->outData.t.buffer); + + result = CryptRsaEncrypt( + &out->outData, &in->message.b, rsaKey, scheme, &in->label.b, NULL); + return result; +} + +#endif // CC_RSA_Encrypt \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/ZGen_2Phase.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/ZGen_2Phase.c new file mode 100644 index 0000000..994427a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Asymmetric/ZGen_2Phase.c @@ -0,0 +1,119 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "ZGen_2Phase_fp.h" + +#if CC_ZGen_2Phase // Conditional expansion of this file + +// This command uses the TPM to recover one or two Z values in a two phase key +// exchange protocol +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES key referenced by 'keyA' is restricted or +// not a decrypt key +// TPM_RC_ECC_POINT 'inQsB' or 'inQeB' is not on the curve of +// the key reference by 'keyA' +// TPM_RC_KEY key referenced by 'keyA' is not an ECC key +// TPM_RC_SCHEME the scheme of the key referenced by 'keyA' +// is not TPM_ALG_NULL, TPM_ALG_ECDH, +// TPM_ALG_ECMQV or TPM_ALG_SM2 +TPM_RC +TPM2_ZGen_2Phase(ZGen_2Phase_In* in, // IN: input parameter list + ZGen_2Phase_Out* out // OUT: output parameter list +) +{ + TPM_RC result; + OBJECT* eccKey; + TPM2B_ECC_PARAMETER r; + TPM_ALG_ID scheme; + + // Input Validation + + eccKey = HandleToObject(in->keyA); + + // keyA must be an ECC key + if(eccKey->publicArea.type != TPM_ALG_ECC) + return TPM_RCS_KEY + RC_ZGen_2Phase_keyA; + + // keyA must not be restricted and must be a decrypt key + if(IS_ATTRIBUTE(eccKey->publicArea.objectAttributes, TPMA_OBJECT, restricted) + || !IS_ATTRIBUTE(eccKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt)) + return TPM_RCS_ATTRIBUTES + RC_ZGen_2Phase_keyA; + + // if the scheme of keyA is TPM_ALG_NULL, then use the input scheme; otherwise + // the input scheme must be the same as the scheme of keyA + scheme = eccKey->publicArea.parameters.asymDetail.scheme.scheme; + if(scheme != TPM_ALG_NULL) + { + if(scheme != in->inScheme) + return TPM_RCS_SCHEME + RC_ZGen_2Phase_inScheme; + } + else + scheme = in->inScheme; + if(scheme == TPM_ALG_NULL) + return TPM_RCS_SCHEME + RC_ZGen_2Phase_inScheme; + + // Input points must be on the curve of keyA + if(!CryptEccIsPointOnCurve(eccKey->publicArea.parameters.eccDetail.curveID, + &in->inQsB.point)) + return TPM_RCS_ECC_POINT + RC_ZGen_2Phase_inQsB; + + if(!CryptEccIsPointOnCurve(eccKey->publicArea.parameters.eccDetail.curveID, + &in->inQeB.point)) + return TPM_RCS_ECC_POINT + RC_ZGen_2Phase_inQeB; + + if(!CryptGenerateR( + &r, &in->counter, eccKey->publicArea.parameters.eccDetail.curveID, NULL)) + return TPM_RCS_VALUE + RC_ZGen_2Phase_counter; + + // Command Output + + result = + CryptEcc2PhaseKeyExchange(&out->outZ1.point, + &out->outZ2.point, + eccKey->publicArea.parameters.eccDetail.curveID, + scheme, + &eccKey->sensitive.sensitive.ecc, + &r, + &in->inQsB.point, + &in->inQeB.point); + if(result == TPM_RC_SCHEME) + return TPM_RCS_SCHEME + RC_ZGen_2Phase_inScheme; + + if(result == TPM_RC_SUCCESS) + CryptEndCommit(in->counter); + + return result; +} +#endif // CC_ZGen_2Phase \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/AttachedComponent/AC_GetCapability.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/AttachedComponent/AC_GetCapability.c new file mode 100644 index 0000000..4fc3c78 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/AttachedComponent/AC_GetCapability.c @@ -0,0 +1,56 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "AC_GetCapability_fp.h" +#include "AC_spt_fp.h" + +#if CC_AC_GetCapability // Conditional expansion of this file + +/*(See part 3 specification) +// This command returns various information regarding Attached Components +*/ +TPM_RC +TPM2_AC_GetCapability(AC_GetCapability_In* in, // IN: input parameter list + AC_GetCapability_Out* out // OUT: output parameter list +) +{ + // Command Output + out->moreData = + AcCapabilitiesGet(in->ac, in->capability, in->count, &out->capabilitiesData); + + return TPM_RC_SUCCESS; +} + +#endif // CC_AC_GetCapability \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/AttachedComponent/AC_Send.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/AttachedComponent/AC_Send.c new file mode 100644 index 0000000..e888356 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/AttachedComponent/AC_Send.c @@ -0,0 +1,99 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "AC_Send_fp.h" +#include "AC_spt_fp.h" + +#if CC_AC_Send // Conditional expansion of this file + +/*(See part 3 specification) +// Duplicate a loaded object +*/ +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES key to duplicate has 'fixedParent' SET +// TPM_RC_HASH for an RSA key, the nameAlg digest size for the +// newParent is not compatible with the key size +// TPM_RC_HIERARCHY 'encryptedDuplication' is SET and 'newParentHandle' +// specifies Null Hierarchy +// TPM_RC_KEY 'newParentHandle' references invalid ECC key (public +// point not on the curve) +// TPM_RC_SIZE input encryption key size does not match the +// size specified in symmetric algorithm +// TPM_RC_SYMMETRIC 'encryptedDuplication' is SET but no symmetric +// algorithm is provided +// TPM_RC_TYPE 'newParentHandle' is neither a storage key nor +// TPM_RH_NULL; or the object has a NULL nameAlg +// TPM_RC_VALUE for an RSA newParent, the sizes of the digest and +// the encryption key are too large to be OAEP encoded +TPM_RC +TPM2_AC_Send(AC_Send_In* in, // IN: input parameter list + AC_Send_Out* out // OUT: output parameter list +) +{ + NV_REF locator; + TPM_HANDLE nvAlias = ((in->ac - AC_FIRST) + NV_AC_FIRST); + NV_INDEX* nvIndex = NvGetIndexInfo(nvAlias, &locator); + OBJECT* object = HandleToObject(in->sendObject); + TPM_RC result; + // Input validation + // If there is an NV alias, then the index must allow the authorization provided + if(nvIndex != NULL) + { + // Common access checks, NvWriteAccessCheck() may return + // TPM_RC_NV_AUTHORIZATION or TPM_RC_NV_LOCKED + result = NvWriteAccessChecks( + in->authHandle, nvAlias, nvIndex->publicArea.attributes); + if(result != TPM_RC_SUCCESS) + return result; + } + // If 'ac' did not have an alias then the authorization had to be with either + // platform or owner authorization. The type of TPMI_RH_NV_AUTH only allows + // owner or platform or an NV index. If it was a valid index, it would have had + // an alias and be processed above, so only success here is if this is a + // permanent handle. + else if(HandleGetType(in->authHandle) != TPM_HT_PERMANENT) + return TPM_RCS_HANDLE + RC_AC_Send_authHandle; + // Make sure that the object to be duplicated has the right attributes + if(IS_ATTRIBUTE( + object->publicArea.objectAttributes, TPMA_OBJECT, encryptedDuplication) + || IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, fixedParent) + || IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, fixedTPM)) + return TPM_RCS_ATTRIBUTES + RC_AC_Send_sendObject; + // Command output + // Do the implementation dependent send + return AcSendObject(in->ac, object, &out->acDataOut); +} + +#endif // TPM_CC_AC_Send \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/AttachedComponent/AC_spt.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/AttachedComponent/AC_spt.c new file mode 100644 index 0000000..a0cf59e --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/AttachedComponent/AC_spt.c @@ -0,0 +1,153 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// This code in this clause is provided for testing of the TPM's command interface. +// The implementation of Attached Components is not expected to be as shown in this +// code. + +//** Includes +#include "Tpm.h" +#include "AC_spt_fp.h" + +// This is the simulated AC data. This should be present in an actual +// implementation. +#if 1 + +typedef struct +{ + TPMI_RH_AC ac; + TPML_AC_CAPABILITIES* acData; + +} acCapabilities; + +TPML_AC_CAPABILITIES acData0001 = {1, {{TPM_AT_PV1, 0x01234567}}}; + +acCapabilities ac[1] = {{0x0001, &acData0001}}; + +# define NUM_AC (sizeof(ac) / sizeof(acCapabilities)) + +#endif // 1 The simulated AC data + +//** Functions + +//*** AcToCapabilities() +// This function returns a pointer to a list of AC capabilities. +TPML_AC_CAPABILITIES* AcToCapabilities(TPMI_RH_AC component // IN: component +) +{ + UINT32 index; + // + for(index = 0; index < NUM_AC; index++) + { + if(ac[index].ac == component) + return ac[index].acData; + } + return NULL; +} + +//*** AcIsAccessible() +// Function to determine if an AC handle references an actual AC +// Return Type: BOOL +BOOL AcIsAccessible(TPM_HANDLE acHandle) +{ + // In this implementation, the AC exists if there are some capabilities to go + // with the handle + return AcToCapabilities(acHandle) != NULL; +} + +//*** AcCapabilitiesGet() +// This function returns a list of capabilities associated with an AC +// Return Type: TPMI_YES_NO +// YES if there are more handles available +// NO all the available handles has been returned +TPMI_YES_NO +AcCapabilitiesGet(TPMI_RH_AC component, // IN: the component + TPM_AT type, // IN: start capability type + UINT32 count, // IN: requested number + TPML_AC_CAPABILITIES* capabilityList // OUT: list of handle +) +{ + TPMI_YES_NO more = NO; + UINT32 i; + // Get the list of capabilities and their values associated with the AC + TPML_AC_CAPABILITIES* capabilities; + + pAssert(HandleGetType(component) == TPM_HT_AC); + capabilities = AcToCapabilities(component); + + // Initialize output handle list + capabilityList->count = 0; + if(count > MAX_AC_CAPABILITIES) + count = MAX_AC_CAPABILITIES; + + if(capabilities != NULL) + { + // Find the first capability less than or equal to type + for(i = 0; i < capabilities->count; i++) + { + if(capabilities->acCapabilities[i].tag >= type) + { + // copy the capabilities until we run out or fill the list + for(; (capabilityList->count < count) && (i < capabilities->count); + i++) + { + capabilityList->acCapabilities[capabilityList->count] = + capabilities->acCapabilities[i]; + capabilityList->count++; + } + more = i < capabilities->count; + } + } + } + return more; +} + +//*** AcSendObject() +// Stub to handle sending of an AC object +// Return Type: TPM_RC +TPM_RC +AcSendObject(TPM_HANDLE acHandle, // IN: Handle of AC receiving object + OBJECT* object, // IN: object structure to send + TPMS_AC_OUTPUT* acDataOut // OUT: results of operation +) +{ + NOT_REFERENCED(object); + NOT_REFERENCED(acHandle); + acDataOut->tag = TPM_AT_ERROR; // indicate that the response contains an + // error code + acDataOut->data = TPM_AE_NONE; // but there is no error. + + return TPM_RC_SUCCESS; +} diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/AttachedComponent/Policy_AC_SendSelect.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/AttachedComponent/Policy_AC_SendSelect.c new file mode 100644 index 0000000..fab698d --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/AttachedComponent/Policy_AC_SendSelect.c @@ -0,0 +1,114 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "Policy_AC_SendSelect_fp.h" + +#if CC_Policy_AC_SendSelect // Conditional expansion of this file + +/*(See part 3 specification) +// allows qualification of attached component and object to be sent. +*/ +// Return Type: TPM_RC +// TPM_RC_COMMAND_CODE 'commandCode' of 'policySession' is not empty +// TPM_RC_CPHASH 'cpHash' of 'policySession' is not empty +TPM_RC +TPM2_Policy_AC_SendSelect(Policy_AC_SendSelect_In* in // IN: input parameter list +) +{ + SESSION* session; + HASH_STATE hashState; + TPM_CC commandCode = TPM_CC_Policy_AC_SendSelect; + + // Input Validation + + // Get pointer to the session structure + session = SessionGet(in->policySession); + + // cpHash in session context must be empty + if(session->u1.cpHash.t.size != 0) + return TPM_RC_CPHASH; + // commandCode in session context must be empty + if(session->commandCode != 0) + return TPM_RC_COMMAND_CODE; + // Internal Data Update + // Update name hash + session->u1.cpHash.t.size = CryptHashStart(&hashState, session->authHashAlg); + + // add objectName + CryptDigestUpdate2B(&hashState, &in->objectName.b); + + // add authHandleName + CryptDigestUpdate2B(&hashState, &in->authHandleName.b); + + // add ac name + CryptDigestUpdate2B(&hashState, &in->acName.b); + + // complete hash + CryptHashEnd2B(&hashState, &session->u1.cpHash.b); + + // update policy hash + // Old policyDigest size should be the same as the new policyDigest size since + // they are using the same hash algorithm + session->u2.policyDigest.t.size = + CryptHashStart(&hashState, session->authHashAlg); + // add old policy + CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); + + // add command code + CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); + + // add objectName + if(in->includeObject == YES) + CryptDigestUpdate2B(&hashState, &in->objectName.b); + + // add authHandleName + CryptDigestUpdate2B(&hashState, &in->authHandleName.b); + + // add acName + CryptDigestUpdate2B(&hashState, &in->acName.b); + + // add includeObject + CryptDigestUpdateInt(&hashState, sizeof(TPMI_YES_NO), in->includeObject); + + // complete digest + CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); + + // set commandCode in session context + session->commandCode = TPM_CC_AC_Send; + + return TPM_RC_SUCCESS; +} + +#endif // CC_Policy_AC_SendSelect \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/Attest_spt.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/Attest_spt.c new file mode 100644 index 0000000..4aff6aa --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/Attest_spt.c @@ -0,0 +1,203 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Includes +#include "Tpm.h" +#include "Attest_spt_fp.h" +#include "Marshal.h" + +//** Functions + +//***FillInAttestInfo() +// Fill in common fields of TPMS_ATTEST structure. +void FillInAttestInfo( + TPMI_DH_OBJECT signHandle, // IN: handle of signing object + TPMT_SIG_SCHEME* scheme, // IN/OUT: scheme to be used for signing + TPM2B_DATA* data, // IN: qualifying data + TPMS_ATTEST* attest // OUT: attest structure +) +{ + OBJECT* signObject = HandleToObject(signHandle); + + // Magic number + attest->magic = TPM_GENERATED_VALUE; + + if(signObject == NULL) + { + // The name for a null handle is TPM_RH_NULL + // This is defined because UINT32_TO_BYTE_ARRAY does a cast. If the + // size of the cast is smaller than a constant, the compiler warns + // about the truncation of a constant value. + TPM_HANDLE nullHandle = TPM_RH_NULL; + attest->qualifiedSigner.t.size = sizeof(TPM_HANDLE); + UINT32_TO_BYTE_ARRAY(nullHandle, attest->qualifiedSigner.t.name); + } + else + { + // Certifying object qualified name + // if the scheme is anonymous, this is an empty buffer + if(CryptIsSchemeAnonymous(scheme->scheme)) + attest->qualifiedSigner.t.size = 0; + else + attest->qualifiedSigner = signObject->qualifiedName; + } + // current clock in plain text + TimeFillInfo(&attest->clockInfo); + + // Firmware version in plain text + attest->firmwareVersion = ((UINT64)gp.firmwareV1 << (sizeof(UINT32) * 8)); + attest->firmwareVersion += gp.firmwareV2; + + // Check the hierarchy of sign object. For NULL sign handle, the hierarchy + // will be TPM_RH_NULL + if((signObject == NULL) + || (!signObject->attributes.epsHierarchy + && !signObject->attributes.ppsHierarchy)) + { + // For signing key that is not in platform or endorsement hierarchy, + // obfuscate the reset, restart and firmware version information + UINT64 obfuscation[2]; + CryptKDFa(CONTEXT_INTEGRITY_HASH_ALG, + &gp.shProof.b, + OBFUSCATE_STRING, + &attest->qualifiedSigner.b, + NULL, + 128, + (BYTE*)&obfuscation[0], + NULL, + FALSE); + // Obfuscate data + attest->firmwareVersion += obfuscation[0]; + attest->clockInfo.resetCount += (UINT32)(obfuscation[1] >> 32); + attest->clockInfo.restartCount += (UINT32)obfuscation[1]; + } + // External data + if(CryptIsSchemeAnonymous(scheme->scheme)) + attest->extraData.t.size = 0; + else + { + // If we move the data to the attestation structure, then it is not + // used in the signing operation except as part of the signed data + attest->extraData = *data; + data->t.size = 0; + } +} + +//***SignAttestInfo() +// Sign a TPMS_ATTEST structure. If signHandle is TPM_RH_NULL, a null signature +// is returned. +// +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES 'signHandle' references not a signing key +// TPM_RC_SCHEME 'scheme' is not compatible with 'signHandle' type +// TPM_RC_VALUE digest generated for the given 'scheme' is greater than +// the modulus of 'signHandle' (for an RSA key); +// invalid commit status or failed to generate "r" value +// (for an ECC key) +TPM_RC +SignAttestInfo(OBJECT* signKey, // IN: sign object + TPMT_SIG_SCHEME* scheme, // IN: sign scheme + TPMS_ATTEST* certifyInfo, // IN: the data to be signed + TPM2B_DATA* qualifyingData, // IN: extra data for the signing + // process + TPM2B_ATTEST* attest, // OUT: marshaled attest blob to be + // signed + TPMT_SIGNATURE* signature // OUT: signature +) +{ + BYTE* buffer; + HASH_STATE hashState; + TPM2B_DIGEST digest; + TPM_RC result; + + // Marshal TPMS_ATTEST structure for hash + buffer = attest->t.attestationData; + attest->t.size = TPMS_ATTEST_Marshal(certifyInfo, &buffer, NULL); + + if(signKey == NULL) + { + signature->sigAlg = TPM_ALG_NULL; + result = TPM_RC_SUCCESS; + } + else + { + TPMI_ALG_HASH hashAlg; + // Compute hash + hashAlg = scheme->details.any.hashAlg; + // need to set the receive buffer to get something put in it + digest.t.size = sizeof(digest.t.buffer); + digest.t.size = CryptHashBlock(hashAlg, + attest->t.size, + attest->t.attestationData, + digest.t.size, + digest.t.buffer); + // If there is qualifying data, need to rehash the data + // hash(qualifyingData || hash(attestationData)) + if(qualifyingData->t.size != 0) + { + CryptHashStart(&hashState, hashAlg); + CryptDigestUpdate2B(&hashState, &qualifyingData->b); + CryptDigestUpdate2B(&hashState, &digest.b); + CryptHashEnd2B(&hashState, &digest.b); + } + // Sign the hash. A TPM_RC_VALUE, TPM_RC_SCHEME, or + // TPM_RC_ATTRIBUTES error may be returned at this point + result = CryptSign(signKey, scheme, &digest, signature); + + // Since the clock is used in an attestation, the state in NV is no longer + // "orderly" with respect to the data in RAM if the signature is valid + if(result == TPM_RC_SUCCESS) + { + // Command uses the clock so need to clear the orderly state if it is + // set. + result = NvClearOrderly(); + } + } + return result; +} + +//*** IsSigningObject() +// Checks to see if the object is OK for signing. This is here rather than in +// Object_spt.c because all the attestation commands use this file but not +// Object_spt.c. +// Return Type: BOOL +// TRUE(1) object may sign +// FALSE(0) object may not sign +BOOL IsSigningObject(OBJECT* object // IN: +) +{ + return ((object == NULL) + || ((IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, sign) + && object->publicArea.type != TPM_ALG_SYMCIPHER))); +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/Certify.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/Certify.c new file mode 100644 index 0000000..39aa663 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/Certify.c @@ -0,0 +1,96 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "Attest_spt_fp.h" +#include "Certify_fp.h" + +#if CC_Certify // Conditional expansion of this file + +/*(See part 3 specification) +// prove an object with a specific Name is loaded in the TPM +*/ +// Return Type: TPM_RC +// TPM_RC_KEY key referenced by 'signHandle' is not a signing key +// TPM_RC_SCHEME 'inScheme' is not compatible with 'signHandle' +// TPM_RC_VALUE digest generated for 'inScheme' is greater or has larger +// size than the modulus of 'signHandle', or the buffer for +// the result in 'signature' is too small (for an RSA key); +// invalid commit status (for an ECC key with a split scheme) +TPM_RC +TPM2_Certify(Certify_In* in, // IN: input parameter list + Certify_Out* out // OUT: output parameter list +) +{ + TPMS_ATTEST certifyInfo; + OBJECT* signObject = HandleToObject(in->signHandle); + OBJECT* certifiedObject = HandleToObject(in->objectHandle); + // Input validation + if(!IsSigningObject(signObject)) + return TPM_RCS_KEY + RC_Certify_signHandle; + if(!CryptSelectSignScheme(signObject, &in->inScheme)) + return TPM_RCS_SCHEME + RC_Certify_inScheme; + + // Command Output + // Filling in attest information + // Common fields + FillInAttestInfo( + in->signHandle, &in->inScheme, &in->qualifyingData, &certifyInfo); + + // Certify specific fields + certifyInfo.type = TPM_ST_ATTEST_CERTIFY; + // NOTE: the certified object is not allowed to be TPM_ALG_NULL so + // 'certifiedObject' will never be NULL + certifyInfo.attested.certify.name = certifiedObject->name; + + // When using an anonymous signing scheme, need to set the qualified Name to the + // empty buffer to avoid correlation between keys + if(CryptIsSchemeAnonymous(in->inScheme.scheme)) + certifyInfo.attested.certify.qualifiedName.t.size = 0; + else + certifyInfo.attested.certify.qualifiedName = certifiedObject->qualifiedName; + + // Sign attestation structure. A NULL signature will be returned if + // signHandle is TPM_RH_NULL. A TPM_RC_NV_UNAVAILABLE, TPM_RC_NV_RATE, + // TPM_RC_VALUE, TPM_RC_SCHEME or TPM_RC_ATTRIBUTES error may be returned + // by SignAttestInfo() + return SignAttestInfo(signObject, + &in->inScheme, + &certifyInfo, + &in->qualifyingData, + &out->certifyInfo, + &out->signature); +} + +#endif // CC_Certify \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/CertifyCreation.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/CertifyCreation.c new file mode 100644 index 0000000..ad2ef13 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/CertifyCreation.c @@ -0,0 +1,100 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "Attest_spt_fp.h" +#include "CertifyCreation_fp.h" + +#if CC_CertifyCreation // Conditional expansion of this file + +/*(See part 3 specification) +// Prove the association between an object and its creation data +*/ +// Return Type: TPM_RC +// TPM_RC_KEY key referenced by 'signHandle' is not a signing key +// TPM_RC_SCHEME 'inScheme' is not compatible with 'signHandle' +// TPM_RC_TICKET 'creationTicket' does not match 'objectHandle' +// TPM_RC_VALUE digest generated for 'inScheme' is greater or has larger +// size than the modulus of 'signHandle', or the buffer for +// the result in 'signature' is too small (for an RSA key); +// invalid commit status (for an ECC key with a split scheme). +TPM_RC +TPM2_CertifyCreation(CertifyCreation_In* in, // IN: input parameter list + CertifyCreation_Out* out // OUT: output parameter list +) +{ + TPMT_TK_CREATION ticket; + TPMS_ATTEST certifyInfo; + OBJECT* certified = HandleToObject(in->objectHandle); + OBJECT* signObject = HandleToObject(in->signHandle); + // Input Validation + if(!IsSigningObject(signObject)) + return TPM_RCS_KEY + RC_CertifyCreation_signHandle; + if(!CryptSelectSignScheme(signObject, &in->inScheme)) + return TPM_RCS_SCHEME + RC_CertifyCreation_inScheme; + + // CertifyCreation specific input validation + // Re-compute ticket + TicketComputeCreation( + in->creationTicket.hierarchy, &certified->name, &in->creationHash, &ticket); + // Compare ticket + if(!MemoryEqual2B(&ticket.digest.b, &in->creationTicket.digest.b)) + return TPM_RCS_TICKET + RC_CertifyCreation_creationTicket; + + // Command Output + // Common fields + FillInAttestInfo( + in->signHandle, &in->inScheme, &in->qualifyingData, &certifyInfo); + + // CertifyCreation specific fields + // Attestation type + certifyInfo.type = TPM_ST_ATTEST_CREATION; + certifyInfo.attested.creation.objectName = certified->name; + + // Copy the creationHash + certifyInfo.attested.creation.creationHash = in->creationHash; + + // Sign attestation structure. A NULL signature will be returned if + // signObject is TPM_RH_NULL. A TPM_RC_NV_UNAVAILABLE, TPM_RC_NV_RATE, + // TPM_RC_VALUE, TPM_RC_SCHEME or TPM_RC_ATTRIBUTES error may be returned at + // this point + return SignAttestInfo(signObject, + &in->inScheme, + &certifyInfo, + &in->qualifyingData, + &out->certifyInfo, + &out->signature); +} + +#endif // CC_CertifyCreation \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/CertifyX509.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/CertifyX509.c new file mode 100644 index 0000000..a109c79 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/CertifyX509.c @@ -0,0 +1,282 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "CertifyX509_fp.h" +#include "X509.h" +#include "TpmASN1_fp.h" +#include "X509_spt_fp.h" +#include "Attest_spt_fp.h" +#if CERTIFYX509_DEBUG +# include "Platform_fp.h" +#endif + +#if CC_CertifyX509 // Conditional expansion of this file + +/*(See part 3 specification) +// Certify using an X509-formatted certificate +*/ +// return type: TPM_RC +// TPM_RC_ATTRIBUTES the attributes of 'objectHandle' are not compatible +// with the KeyUsage or TPMA_OBJECT values in the +// extensions fields +// TPM_RC_BINDING the public and private portions of the key are not +// properly bound. +// TPM_RC_HASH the hash algorithm in the scheme is not supported +// TPM_RC_KEY 'signHandle' does not reference a signing key; +// TPM_RC_SCHEME the scheme is not compatible with sign key type, +// or input scheme is not compatible with default +// scheme, or the chosen scheme is not a valid +// sign scheme +// TPM_RC_VALUE most likely a problem with the format of +// 'partialCertificate' +TPM_RC +TPM2_CertifyX509(CertifyX509_In* in, // IN: input parameter list + CertifyX509_Out* out // OUT: output parameter list +) +{ + TPM_RC result; + OBJECT* signKey = HandleToObject(in->signHandle); + OBJECT* object = HandleToObject(in->objectHandle); + HASH_STATE hash; + INT16 length; // length for a tagged element + ASN1UnmarshalContext ctx; + ASN1MarshalContext ctxOut; + // certTBS holds an array of pointers and lengths. Each entry references the + // corresponding value in a TBSCertificate structure. For example, the 1th + // element references the version number + stringRef certTBS[REF_COUNT] = {{0}}; +# define ALLOWED_SEQUENCES (SUBJECT_PUBLIC_KEY_REF - SIGNATURE_REF) + stringRef partial[ALLOWED_SEQUENCES] = {{0}}; + INT16 countOfSequences = 0; + INT16 i; + // +# if CERTIFYX509_DEBUG + DebugFileInit(); + DebugDumpBuffer(in->partialCertificate.t.size, + in->partialCertificate.t.buffer, + "partialCertificate"); +# endif + + // Input Validation + if(in->reserved.b.size != 0) + return TPM_RC_SIZE + RC_CertifyX509_reserved; + // signing key must be able to sign + if(!IsSigningObject(signKey)) + return TPM_RCS_KEY + RC_CertifyX509_signHandle; + // Pick a scheme for sign. If the input sign scheme is not compatible with + // the default scheme, return an error. + if(!CryptSelectSignScheme(signKey, &in->inScheme)) + return TPM_RCS_SCHEME + RC_CertifyX509_inScheme; + // Make sure that the public Key encoding is known + if(X509AddPublicKey(NULL, object) == 0) + return TPM_RCS_ASYMMETRIC + RC_CertifyX509_objectHandle; + // Unbundle 'partialCertificate'. + // Initialize the unmarshaling context + if(!ASN1UnmarshalContextInitialize( + &ctx, in->partialCertificate.t.size, in->partialCertificate.t.buffer)) + return TPM_RCS_VALUE + RC_CertifyX509_partialCertificate; + // Make sure that this is a constructed SEQUENCE + length = ASN1NextTag(&ctx); + // Must be a constructed SEQUENCE that uses all of the input parameter + if((ctx.tag != (ASN1_CONSTRUCTED_SEQUENCE)) + || ((ctx.offset + length) != in->partialCertificate.t.size)) + return TPM_RCS_SIZE + RC_CertifyX509_partialCertificate; + + // This scans through the contents of the outermost SEQUENCE. This would be the + // 'issuer', 'validity', 'subject', 'issuerUniqueID' (optional), + // 'subjectUniqueID' (optional), and 'extensions.' + while(ctx.offset < ctx.size) + { + INT16 startOfElement = ctx.offset; + // + // Read the next tag and length field. + length = ASN1NextTag(&ctx); + if(length < 0) + break; + if(ctx.tag == ASN1_CONSTRUCTED_SEQUENCE) + { + partial[countOfSequences].buf = &ctx.buffer[startOfElement]; + ctx.offset += length; + partial[countOfSequences].len = (INT16)ctx.offset - startOfElement; + if(++countOfSequences > ALLOWED_SEQUENCES) + break; + } + else if(ctx.tag == X509_EXTENSIONS) + { + if(certTBS[EXTENSIONS_REF].len != 0) + return TPM_RCS_VALUE + RC_CertifyX509_partialCertificate; + certTBS[EXTENSIONS_REF].buf = &ctx.buffer[startOfElement]; + ctx.offset += length; + certTBS[EXTENSIONS_REF].len = (INT16)ctx.offset - startOfElement; + } + else + return TPM_RCS_VALUE + RC_CertifyX509_partialCertificate; + } + // Make sure that we used all of the data and found at least the required + // number of elements. + if((ctx.offset != ctx.size) || (countOfSequences < 3) || (countOfSequences > 4) + || (certTBS[EXTENSIONS_REF].buf == NULL)) + return TPM_RCS_VALUE + RC_CertifyX509_partialCertificate; + // Now that we know how many sequences there were, we can put them where they + // belong + for(i = 0; i < countOfSequences; i++) + certTBS[SUBJECT_KEY_REF - i] = partial[countOfSequences - 1 - i]; + + // If only three SEQUENCES, then the TPM needs to produce the signature algorithm. + // See if it can + if((countOfSequences == 3) + && (X509AddSigningAlgorithm(NULL, signKey, &in->inScheme) == 0)) + return TPM_RCS_SCHEME + RC_CertifyX509_signHandle; + + // Process the extensions + result = X509ProcessExtensions(object, &certTBS[EXTENSIONS_REF]); + if(result != TPM_RC_SUCCESS) + // If the extension has the TPMA_OBJECT extension and the attributes don't + // match, then the error code will be TPM_RCS_ATTRIBUTES. Otherwise, the error + // indicates a malformed partialCertificate. + return result + + ((result == TPM_RCS_ATTRIBUTES) ? RC_CertifyX509_objectHandle + : RC_CertifyX509_partialCertificate); + // Command Output + // Create the addedToCertificate values + + // Build the addedToCertificate from the bottom up. + // Initialize the context structure + ASN1InitialializeMarshalContext(&ctxOut, + sizeof(out->addedToCertificate.t.buffer), + out->addedToCertificate.t.buffer); + // Place a marker for the overall context + ASN1StartMarshalContext(&ctxOut); // SEQUENCE for addedToCertificate + + // Add the subject public key descriptor + certTBS[SUBJECT_PUBLIC_KEY_REF].len = X509AddPublicKey(&ctxOut, object); + certTBS[SUBJECT_PUBLIC_KEY_REF].buf = ctxOut.buffer + ctxOut.offset; + // If the caller didn't provide the algorithm identifier, create it + if(certTBS[SIGNATURE_REF].len == 0) + { + certTBS[SIGNATURE_REF].len = + X509AddSigningAlgorithm(&ctxOut, signKey, &in->inScheme); + certTBS[SIGNATURE_REF].buf = ctxOut.buffer + ctxOut.offset; + } + // Create the serial number value. Use the out->tbsDigest as scratch. + { + TPM2B* digest = &out->tbsDigest.b; + // + digest->size = (INT16)CryptHashStart(&hash, signKey->publicArea.nameAlg); + pAssert(digest->size != 0); + + // The serial number size is the smaller of the digest and the vendor-defined + // value + digest->size = MIN(digest->size, SIZE_OF_X509_SERIAL_NUMBER); + // Add all the parts of the certificate other than the serial number + // and version number + for(i = SIGNATURE_REF; i < REF_COUNT; i++) + CryptDigestUpdate(&hash, certTBS[i].len, certTBS[i].buf); + // throw in the Name of the signing key... + CryptDigestUpdate2B(&hash, &signKey->name.b); + // ...and the Name of the signed key. + CryptDigestUpdate2B(&hash, &object->name.b); + // Done + CryptHashEnd2B(&hash, digest); + } + + // Add the serial number + certTBS[SERIAL_NUMBER_REF].len = + ASN1PushInteger(&ctxOut, out->tbsDigest.t.size, out->tbsDigest.t.buffer); + certTBS[SERIAL_NUMBER_REF].buf = ctxOut.buffer + ctxOut.offset; + + // Add the static version number + ASN1StartMarshalContext(&ctxOut); + ASN1PushUINT(&ctxOut, 2); + certTBS[VERSION_REF].len = + ASN1EndEncapsulation(&ctxOut, ASN1_APPLICAIION_SPECIFIC); + certTBS[VERSION_REF].buf = ctxOut.buffer + ctxOut.offset; + + // Create a fake tag and length for the TBS in the space used for + // 'addedToCertificate' + { + for(length = 0, i = 0; i < REF_COUNT; i++) + length += certTBS[i].len; + // Put a fake tag and length into the buffer for use in the tbsDigest + certTBS[ENCODED_SIZE_REF].len = + ASN1PushTagAndLength(&ctxOut, ASN1_CONSTRUCTED_SEQUENCE, length); + certTBS[ENCODED_SIZE_REF].buf = ctxOut.buffer + ctxOut.offset; + // Restore the buffer pointer to add back the number of octets used for the + // tag and length + ctxOut.offset += certTBS[ENCODED_SIZE_REF].len; + } + // sanity check + if(ctxOut.offset < 0) + return TPM_RC_FAILURE; + // Create the tbsDigest to sign + out->tbsDigest.t.size = CryptHashStart(&hash, in->inScheme.details.any.hashAlg); + for(i = 0; i < REF_COUNT; i++) + CryptDigestUpdate(&hash, certTBS[i].len, certTBS[i].buf); + CryptHashEnd2B(&hash, &out->tbsDigest.b); + +# if CERTIFYX509_DEBUG + { + BYTE fullTBS[4096]; + BYTE* fill = fullTBS; + int j; + for(j = 0; j < REF_COUNT; j++) + { + MemoryCopy(fill, certTBS[j].buf, certTBS[j].len); + fill += certTBS[j].len; + } + DebugDumpBuffer((int)(fill - &fullTBS[0]), fullTBS, "\nfull TBS"); + } +# endif + + // Finish up the processing of addedToCertificate + // Create the actual tag and length for the addedToCertificate structure + out->addedToCertificate.t.size = + ASN1EndEncapsulation(&ctxOut, ASN1_CONSTRUCTED_SEQUENCE); + // Now move all the addedToContext to the start of the buffer + MemoryCopy(out->addedToCertificate.t.buffer, + ctxOut.buffer + ctxOut.offset, + out->addedToCertificate.t.size); +# if CERTIFYX509_DEBUG + DebugDumpBuffer(out->addedToCertificate.t.size, + out->addedToCertificate.t.buffer, + "\naddedToCertificate"); +# endif + // only thing missing is the signature + result = CryptSign(signKey, &in->inScheme, &out->tbsDigest, &out->signature); + + return result; +} + +#endif // CC_CertifyX509 diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/GetCommandAuditDigest.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/GetCommandAuditDigest.c new file mode 100644 index 0000000..6abac73 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/GetCommandAuditDigest.c @@ -0,0 +1,101 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "Attest_spt_fp.h" +#include "GetCommandAuditDigest_fp.h" + +#if CC_GetCommandAuditDigest // Conditional expansion of this file + +/*(See part 3 specification) +// Get current value of command audit log +*/ +// Return Type: TPM_RC +// TPM_RC_KEY key referenced by 'signHandle' is not a signing key +// TPM_RC_SCHEME 'inScheme' is incompatible with 'signHandle' type; or +// both 'scheme' and key's default scheme are empty; or +// 'scheme' is empty while key's default scheme requires +// explicit input scheme (split signing); or +// non-empty default key scheme differs from 'scheme' +// TPM_RC_VALUE digest generated for the given 'scheme' is greater than +// the modulus of 'signHandle' (for an RSA key); +// invalid commit status or failed to generate "r" value +// (for an ECC key) +TPM_RC +TPM2_GetCommandAuditDigest( + GetCommandAuditDigest_In* in, // IN: input parameter list + GetCommandAuditDigest_Out* out // OUT: output parameter list +) +{ + TPM_RC result; + TPMS_ATTEST auditInfo; + OBJECT* signObject = HandleToObject(in->signHandle); + // Input validation + if(!IsSigningObject(signObject)) + return TPM_RCS_KEY + RC_GetCommandAuditDigest_signHandle; + if(!CryptSelectSignScheme(signObject, &in->inScheme)) + return TPM_RCS_SCHEME + RC_GetCommandAuditDigest_inScheme; + + // Command Output + // Fill in attest information common fields + FillInAttestInfo(in->signHandle, &in->inScheme, &in->qualifyingData, &auditInfo); + + // CommandAuditDigest specific fields + auditInfo.type = TPM_ST_ATTEST_COMMAND_AUDIT; + auditInfo.attested.commandAudit.digestAlg = gp.auditHashAlg; + auditInfo.attested.commandAudit.auditCounter = gp.auditCounter; + + // Copy command audit log + auditInfo.attested.commandAudit.auditDigest = gr.commandAuditDigest; + CommandAuditGetDigest(&auditInfo.attested.commandAudit.commandDigest); + + // Sign attestation structure. A NULL signature will be returned if + // signHandle is TPM_RH_NULL. A TPM_RC_NV_UNAVAILABLE, TPM_RC_NV_RATE, + // TPM_RC_VALUE, TPM_RC_SCHEME or TPM_RC_ATTRIBUTES error may be returned at + // this point + result = SignAttestInfo(signObject, + &in->inScheme, + &auditInfo, + &in->qualifyingData, + &out->auditInfo, + &out->signature); + // Internal Data Update + if(result == TPM_RC_SUCCESS && in->signHandle != TPM_RH_NULL) + // Reset log + gr.commandAuditDigest.t.size = 0; + + return result; +} + +#endif // CC_GetCommandAuditDigest \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/GetSessionAuditDigest.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/GetSessionAuditDigest.c new file mode 100644 index 0000000..f23264f --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/GetSessionAuditDigest.c @@ -0,0 +1,97 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "Attest_spt_fp.h" +#include "GetSessionAuditDigest_fp.h" + +#if CC_GetSessionAuditDigest // Conditional expansion of this file + +/*(See part 3 specification) +// Get audit session digest +*/ +// Return Type: TPM_RC +// TPM_RC_KEY key referenced by 'signHandle' is not a signing key +// TPM_RC_SCHEME 'inScheme' is incompatible with 'signHandle' type; or +// both 'scheme' and key's default scheme are empty; or +// 'scheme' is empty while key's default scheme requires +// explicit input scheme (split signing); or +// non-empty default key scheme differs from 'scheme' +// TPM_RC_TYPE 'sessionHandle' does not reference an audit session +// TPM_RC_VALUE digest generated for the given 'scheme' is greater than +// the modulus of 'signHandle' (for an RSA key); +// invalid commit status or failed to generate "r" value +// (for an ECC key) +TPM_RC +TPM2_GetSessionAuditDigest( + GetSessionAuditDigest_In* in, // IN: input parameter list + GetSessionAuditDigest_Out* out // OUT: output parameter list +) +{ + SESSION* session = SessionGet(in->sessionHandle); + TPMS_ATTEST auditInfo; + OBJECT* signObject = HandleToObject(in->signHandle); + // Input Validation + if(!IsSigningObject(signObject)) + return TPM_RCS_KEY + RC_GetSessionAuditDigest_signHandle; + if(!CryptSelectSignScheme(signObject, &in->inScheme)) + return TPM_RCS_SCHEME + RC_GetSessionAuditDigest_inScheme; + + // session must be an audit session + if(session->attributes.isAudit == CLEAR) + return TPM_RCS_TYPE + RC_GetSessionAuditDigest_sessionHandle; + + // Command Output + // Fill in attest information common fields + FillInAttestInfo(in->signHandle, &in->inScheme, &in->qualifyingData, &auditInfo); + + // SessionAuditDigest specific fields + auditInfo.type = TPM_ST_ATTEST_SESSION_AUDIT; + auditInfo.attested.sessionAudit.sessionDigest = session->u2.auditDigest; + + // Exclusive audit session + auditInfo.attested.sessionAudit.exclusiveSession = + (g_exclusiveAuditSession == in->sessionHandle); + + // Sign attestation structure. A NULL signature will be returned if + // signObject is NULL. + return SignAttestInfo(signObject, + &in->inScheme, + &auditInfo, + &in->qualifyingData, + &out->auditInfo, + &out->signature); +} + +#endif // CC_GetSessionAuditDigest \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/GetTime.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/GetTime.c new file mode 100644 index 0000000..1f570c3 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/GetTime.c @@ -0,0 +1,91 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "Attest_spt_fp.h" +#include "GetTime_fp.h" + +#if CC_GetTime // Conditional expansion of this file + +/*(See part 3 specification) +// Applies a time stamp to the passed blob (qualifyingData). +*/ +// Return Type: TPM_RC +// TPM_RC_KEY key referenced by 'signHandle' is not a signing key +// TPM_RC_SCHEME 'inScheme' is incompatible with 'signHandle' type; or +// both 'scheme' and key's default scheme are empty; or +// 'scheme' is empty while key's default scheme requires +// explicit input scheme (split signing); or +// non-empty default key scheme differs from 'scheme' +// TPM_RC_VALUE digest generated for the given 'scheme' is greater than +// the modulus of 'signHandle' (for an RSA key); +// invalid commit status or failed to generate "r" value +// (for an ECC key) +TPM_RC +TPM2_GetTime(GetTime_In* in, // IN: input parameter list + GetTime_Out* out // OUT: output parameter list +) +{ + TPMS_ATTEST timeInfo; + OBJECT* signObject = HandleToObject(in->signHandle); + // Input Validation + if(!IsSigningObject(signObject)) + return TPM_RCS_KEY + RC_GetTime_signHandle; + if(!CryptSelectSignScheme(signObject, &in->inScheme)) + return TPM_RCS_SCHEME + RC_GetTime_inScheme; + + // Command Output + // Fill in attest common fields + FillInAttestInfo(in->signHandle, &in->inScheme, &in->qualifyingData, &timeInfo); + + // GetClock specific fields + timeInfo.type = TPM_ST_ATTEST_TIME; + timeInfo.attested.time.time.time = g_time; + TimeFillInfo(&timeInfo.attested.time.time.clockInfo); + + // Firmware version in plain text + timeInfo.attested.time.firmwareVersion = + (((UINT64)gp.firmwareV1) << 32) + gp.firmwareV2; + + // Sign attestation structure. A NULL signature will be returned if + // signObject is NULL. + return SignAttestInfo(signObject, + &in->inScheme, + &timeInfo, + &in->qualifyingData, + &out->timeInfo, + &out->signature); +} + +#endif // CC_GetTime \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/Quote.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/Quote.c new file mode 100644 index 0000000..f69a4fe --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Attestation/Quote.c @@ -0,0 +1,101 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "Attest_spt_fp.h" +#include "Quote_fp.h" + +#if CC_Quote // Conditional expansion of this file + +/*(See part 3 specification) +// quote PCR values +*/ +// Return Type: TPM_RC +// TPM_RC_KEY 'signHandle' does not reference a signing key; +// TPM_RC_SCHEME the scheme is not compatible with sign key type, +// or input scheme is not compatible with default +// scheme, or the chosen scheme is not a valid +// sign scheme +TPM_RC +TPM2_Quote(Quote_In* in, // IN: input parameter list + Quote_Out* out // OUT: output parameter list +) +{ + TPMI_ALG_HASH hashAlg; + TPMS_ATTEST quoted; + OBJECT* signObject = HandleToObject(in->signHandle); + // Input Validation + if(!IsSigningObject(signObject)) + return TPM_RCS_KEY + RC_Quote_signHandle; + if(!CryptSelectSignScheme(signObject, &in->inScheme)) + return TPM_RCS_SCHEME + RC_Quote_inScheme; + + // Command Output + + // Filling in attest information + // Common fields + // FillInAttestInfo may return TPM_RC_SCHEME or TPM_RC_KEY + FillInAttestInfo(in->signHandle, &in->inScheme, &in->qualifyingData, "ed); + + // Quote specific fields + // Attestation type + quoted.type = TPM_ST_ATTEST_QUOTE; + + // Get hash algorithm in sign scheme. This hash algorithm is used to + // compute PCR digest. If there is no algorithm, then the PCR cannot + // be digested and this command returns TPM_RC_SCHEME + hashAlg = in->inScheme.details.any.hashAlg; + + if(hashAlg == TPM_ALG_NULL) + return TPM_RCS_SCHEME + RC_Quote_inScheme; + + // Compute PCR digest + PCRComputeCurrentDigest( + hashAlg, &in->PCRselect, "ed.attested.quote.pcrDigest); + + // Copy PCR select. "PCRselect" is modified in PCRComputeCurrentDigest + // function + quoted.attested.quote.pcrSelect = in->PCRselect; + + // Sign attestation structure. A NULL signature will be returned if + // signObject is NULL. + return SignAttestInfo(signObject, + &in->inScheme, + "ed, + &in->qualifyingData, + &out->quoted, + &out->signature); +} + +#endif // CC_Quote \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Capability/GetCapability.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Capability/GetCapability.c new file mode 100644 index 0000000..a630fda --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Capability/GetCapability.c @@ -0,0 +1,171 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "GetCapability_fp.h" + +#if CC_GetCapability // Conditional expansion of this file + +/*(See part 3 specification) +// This command returns various information regarding the TPM and its current +// state +*/ +// Return Type: TPM_RC +// TPM_RC_HANDLE value of 'property' is in an unsupported handle range +// for the TPM_CAP_HANDLES 'capability' value +// TPM_RC_VALUE invalid 'capability'; or 'property' is not 0 for the +// TPM_CAP_PCRS 'capability' value +TPM_RC +TPM2_GetCapability(GetCapability_In* in, // IN: input parameter list + GetCapability_Out* out // OUT: output parameter list +) +{ + TPMU_CAPABILITIES* data = &out->capabilityData.data; + // Command Output + + // Set output capability type the same as input type + out->capabilityData.capability = in->capability; + + switch(in->capability) + { + case TPM_CAP_ALGS: + out->moreData = AlgorithmCapGetImplemented( + (TPM_ALG_ID)in->property, in->propertyCount, &data->algorithms); + break; + case TPM_CAP_HANDLES: + switch(HandleGetType((TPM_HANDLE)in->property)) + { + case TPM_HT_TRANSIENT: + // Get list of handles of loaded transient objects + out->moreData = ObjectCapGetLoaded( + (TPM_HANDLE)in->property, in->propertyCount, &data->handles); + break; + case TPM_HT_PERSISTENT: + // Get list of handles of persistent objects + out->moreData = NvCapGetPersistent( + (TPM_HANDLE)in->property, in->propertyCount, &data->handles); + break; + case TPM_HT_NV_INDEX: + // Get list of defined NV index + out->moreData = NvCapGetIndex( + (TPM_HANDLE)in->property, in->propertyCount, &data->handles); + break; + case TPM_HT_LOADED_SESSION: + // Get list of handles of loaded sessions + out->moreData = SessionCapGetLoaded( + (TPM_HANDLE)in->property, in->propertyCount, &data->handles); + break; +# ifdef TPM_HT_SAVED_SESSION + case TPM_HT_SAVED_SESSION: +# else + case TPM_HT_ACTIVE_SESSION: +# endif + // Get list of handles of + out->moreData = SessionCapGetSaved( + (TPM_HANDLE)in->property, in->propertyCount, &data->handles); + break; + case TPM_HT_PCR: + // Get list of handles of PCR + out->moreData = PCRCapGetHandles( + (TPM_HANDLE)in->property, in->propertyCount, &data->handles); + break; + case TPM_HT_PERMANENT: + // Get list of permanent handles + out->moreData = PermanentCapGetHandles( + (TPM_HANDLE)in->property, in->propertyCount, &data->handles); + break; + default: + // Unsupported input handle type + return TPM_RCS_HANDLE + RC_GetCapability_property; + break; + } + break; + case TPM_CAP_COMMANDS: + out->moreData = CommandCapGetCCList( + (TPM_CC)in->property, in->propertyCount, &data->command); + break; + case TPM_CAP_PP_COMMANDS: + out->moreData = PhysicalPresenceCapGetCCList( + (TPM_CC)in->property, in->propertyCount, &data->ppCommands); + break; + case TPM_CAP_AUDIT_COMMANDS: + out->moreData = CommandAuditCapGetCCList( + (TPM_CC)in->property, in->propertyCount, &data->auditCommands); + break; + case TPM_CAP_PCRS: + // Input property must be 0 + if(in->property != 0) + return TPM_RCS_VALUE + RC_GetCapability_property; + out->moreData = + PCRCapGetAllocation(in->propertyCount, &data->assignedPCR); + break; + case TPM_CAP_PCR_PROPERTIES: + out->moreData = PCRCapGetProperties( + (TPM_PT_PCR)in->property, in->propertyCount, &data->pcrProperties); + break; + case TPM_CAP_TPM_PROPERTIES: + out->moreData = TPMCapGetProperties( + (TPM_PT)in->property, in->propertyCount, &data->tpmProperties); + break; +# if ALG_ECC + case TPM_CAP_ECC_CURVES: + out->moreData = CryptCapGetECCCurve( + (TPM_ECC_CURVE)in->property, in->propertyCount, &data->eccCurves); + break; +# endif // ALG_ECC + case TPM_CAP_AUTH_POLICIES: + if(HandleGetType((TPM_HANDLE)in->property) != TPM_HT_PERMANENT) + return TPM_RCS_VALUE + RC_GetCapability_property; + out->moreData = PermanentHandleGetPolicy( + (TPM_HANDLE)in->property, in->propertyCount, &data->authPolicies); + break; + case TPM_CAP_ACT: + if(((TPM_RH)in->property < TPM_RH_ACT_0) + || ((TPM_RH)in->property > TPM_RH_ACT_F)) + return TPM_RCS_VALUE + RC_GetCapability_property; + out->moreData = ActGetCapabilityData( + (TPM_HANDLE)in->property, in->propertyCount, &data->actData); + break; + case TPM_CAP_VENDOR_PROPERTY: + // vendor property is not implemented + default: + // Unsupported TPM_CAP value + return TPM_RCS_VALUE + RC_GetCapability_capability; + break; + } + + return TPM_RC_SUCCESS; +} + +#endif // CC_GetCapability \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Capability/TestParms.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Capability/TestParms.c new file mode 100644 index 0000000..44ca754 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Capability/TestParms.c @@ -0,0 +1,55 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "TestParms_fp.h" + +#if CC_TestParms // Conditional expansion of this file + +/*(See part 3 specification) +// TestParms +*/ +TPM_RC +TPM2_TestParms(TestParms_In* in // IN: input parameter list +) +{ + // Input parameter is not reference in command action + NOT_REFERENCED(in); + + // The parameters are tested at unmarshal process. We do nothing in command + // action + return TPM_RC_SUCCESS; +} + +#endif // CC_TestParms \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/ClockTimer/ACT_SetTimeout.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/ClockTimer/ACT_SetTimeout.c new file mode 100644 index 0000000..3617191 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/ClockTimer/ACT_SetTimeout.c @@ -0,0 +1,60 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "ACT_SetTimeout_fp.h" + +#if CC_ACT_SetTimeout // Conditional expansion of this file + +/*(See part 3 specification) +// prove an object with a specific Name is loaded in the TPM +*/ +// Return Type: TPM_RC +// TPM_RC_RETRY returned when an update for the selected ACT is +// already pending +// TPM_RC_VALUE attempt to disable signaling from an ACT that has +// not expired +TPM_RC +TPM2_ACT_SetTimeout(ACT_SetTimeout_In* in // IN: input parameter list +) +{ + // If 'startTimeout' is UINT32_MAX, then this is an attempt to disable the ACT + // and turn off the signaling for the ACT. This is only valid if the ACT + // is signaling. + if((in->startTimeout == UINT32_MAX) && !ActGetSignaled(in->actHandle)) + return TPM_RC_VALUE + RC_ACT_SetTimeout_startTimeout; + return ActCounterUpdate(in->actHandle, in->startTimeout); +} + +#endif // CC_ACT_SetTimeout \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/ClockTimer/ACT_spt.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/ClockTimer/ACT_spt.c new file mode 100644 index 0000000..6ac37c3 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/ClockTimer/ACT_spt.c @@ -0,0 +1,264 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// This code implements the ACT update code. It does not use a mutex. This code uses +// a platform service (_plat__ACT_UpdateCounter()) that returns 'false' if the update +// is not accepted. If this occurs, then TPM_RC_RETRY should be sent to the caller so +// that they can retry the operation later. The implementation of this is platform +// dependent but the reference uses a simple flag to indicate that an update is +// pending and the only process that can clear that flag is the process that does the +// actual update. + +//** Includes +#include "Tpm.h" +#include "ACT_spt_fp.h" +#include "Platform_fp.h" + +//** Functions + +//*** _ActResume() +// This function does the resume processing for an ACT. It updates the saved count +// and turns signaling back on if necessary. +static void _ActResume(UINT32 act, //IN: the act number + ACT_STATE* actData //IN: pointer to the saved ACT data +) +{ + // If the act was non-zero, then restore the counter value. + if(actData->remaining > 0) + _plat__ACT_UpdateCounter(act, actData->remaining); + // if the counter was zero and the ACT signaling, enable the signaling. + else if(go.signaledACT & (1 << act)) + _plat__ACT_SetSignaled(act, TRUE); +} + +//*** ActStartup() +// This function is called by TPM2_Startup() to initialize the ACT counter values. +BOOL ActStartup(STARTUP_TYPE type) +{ + // Reset all the ACT hardware + _plat__ACT_Initialize(); + + // If this not a cold start, copy all the current 'signaled' settings to + // 'preservedSignaled'. + if(g_powerWasLost) + go.preservedSignaled = 0; + else + go.preservedSignaled |= go.signaledACT; + + // For TPM_RESET or TPM_RESTART, the ACTs will all be disabled and the output + // de-asserted. + if(type != SU_RESUME) + { + go.signaledACT = 0; +#define CLEAR_ACT_POLICY(N) \ + go.ACT_##N.hashAlg = TPM_ALG_NULL; \ + go.ACT_##N.authPolicy.b.size = 0; + FOR_EACH_ACT(CLEAR_ACT_POLICY) + } + else + { + // Resume each of the implemented ACT +#define RESUME_ACT(N) _ActResume(0x##N, &go.ACT_##N); + + FOR_EACH_ACT(RESUME_ACT) + } + // set no ACT updated since last startup. This is to enable the halving of the + // timeout value + s_ActUpdated = 0; + _plat__ACT_EnableTicks(TRUE); + return TRUE; +} + +//*** _ActSaveState() +// Get the counter state and the signaled state for an ACT. If the ACT has not been +// updated since the last time it was saved, then divide the count by 2. +static void _ActSaveState(UINT32 act, P_ACT_STATE actData) +{ + actData->remaining = _plat__ACT_GetRemaining(act); + // If the ACT hasn't been updated since the last startup, then it should be + // be halved. + if((s_ActUpdated & (1 << act)) == 0) + { + // Don't halve if the count is set to max or if halving would make it zero + if((actData->remaining != UINT32_MAX) && (actData->remaining > 1)) + actData->remaining /= 2; + } + if(_plat__ACT_GetSignaled(act)) + go.signaledACT |= (1 << act); +} + +//*** ActGetSignaled() +// This function returns the state of the signaled flag associated with an ACT. +BOOL ActGetSignaled(TPM_RH actHandle) +{ + UINT32 act = actHandle - TPM_RH_ACT_0; + // + return _plat__ACT_GetSignaled(act); +} + +//***ActShutdown() +// This function saves the current state of the counters +BOOL ActShutdown(TPM_SU state //IN: the type of the shutdown. +) +{ + // if this is not shutdown state, then the only type of startup is TPM_RESTART + // so the timer values will be cleared. If this is shutdown state, get the current + // countdown and signaled values. Plus, if the counter has not been updated + // since the last restart, divide the time by 2 so that there is no attack on the + // countdown by saving the countdown state early and then not using the TPM. + if(state == TPM_SU_STATE) + { + // This will be populated as each of the ACT is queried + go.signaledACT = 0; + // Get the current count and the signaled state +#define SAVE_ACT_STATE(N) _ActSaveState(0x##N, &go.ACT_##N); + + FOR_EACH_ACT(SAVE_ACT_STATE); + } + return TRUE; +} + +//*** ActIsImplemented() +// This function determines if an ACT is implemented in both the TPM and the platform +// code. +BOOL ActIsImplemented(UINT32 act) +{ + // This switch accounts for the TPM implemented values. + switch(act) + { + FOR_EACH_ACT(CASE_ACT_NUMBER) + // This ensures that the platform implements the values implemented by + // the TPM + return _plat__ACT_GetImplemented(act); + default: + break; + } + return FALSE; +} + +//***ActCounterUpdate() +// This function updates the ACT counter. If the counter already has a pending update, +// it returns TPM_RC_RETRY so that the update can be tried again later. +TPM_RC +ActCounterUpdate(TPM_RH handle, //IN: the handle of the act + UINT32 newValue //IN: the value to set in the ACT +) +{ + UINT32 act; + TPM_RC result; + // + act = handle - TPM_RH_ACT_0; + // This should never fail, but... + if(!_plat__ACT_GetImplemented(act)) + result = TPM_RC_VALUE; + else + { + // Will need to clear orderly so fail if we are orderly and NV is + // not available + if(NV_IS_ORDERLY) + RETURN_IF_NV_IS_NOT_AVAILABLE; + // if the attempt to update the counter fails, it means that there is an + // update pending so wait until it has occurred and then do an update. + if(!_plat__ACT_UpdateCounter(act, newValue)) + result = TPM_RC_RETRY; + else + { + // Indicate that the ACT has been updated since last TPM2_Startup(). + s_ActUpdated |= (UINT16)(1 << act); + + // Clear the preservedSignaled attribute. + go.preservedSignaled &= ~((UINT16)(1 << act)); + + // Need to clear the orderly flag + g_clearOrderly = TRUE; + + result = TPM_RC_SUCCESS; + } + } + return result; +} + +//*** ActGetCapabilityData() +// This function returns the list of ACT data +// Return Type: TPMI_YES_NO +// YES if more ACT data is available +// NO if no more ACT data to +TPMI_YES_NO +ActGetCapabilityData(TPM_HANDLE actHandle, // IN: the handle for the starting ACT + UINT32 maxCount, // IN: maximum allowed return values + TPML_ACT_DATA* actList // OUT: ACT data list +) +{ + // Initialize output property list + actList->count = 0; + + // Make sure that the starting handle value is in range (again) + if((actHandle < TPM_RH_ACT_0) || (actHandle > TPM_RH_ACT_F)) + return FALSE; + // The maximum count of curves we may return is MAX_ECC_CURVES + if(maxCount > MAX_ACT_DATA) + maxCount = MAX_ACT_DATA; + // Scan the ACT data from the starting ACT + for(; actHandle <= TPM_RH_ACT_F; actHandle++) + { + UINT32 act = actHandle - TPM_RH_ACT_0; + if(actList->count < maxCount) + { + if(ActIsImplemented(act)) + { + TPMS_ACT_DATA* actData = &actList->actData[actList->count]; + // + memset(&actData->attributes, 0, sizeof(actData->attributes)); + actData->handle = actHandle; + actData->timeout = _plat__ACT_GetRemaining(act); + if(_plat__ACT_GetSignaled(act)) + SET_ATTRIBUTE(actData->attributes, TPMA_ACT, signaled); + else + CLEAR_ATTRIBUTE(actData->attributes, TPMA_ACT, signaled); + if(go.preservedSignaled & (1 << act)) + SET_ATTRIBUTE(actData->attributes, TPMA_ACT, preserveSignaled); + actList->count++; + } + } + else + { + if(_plat__ACT_GetImplemented(act)) + return YES; + } + } + // If we get here, either all of the ACT values were put in the list, or the list + // was filled and there are no more ACT values to return + return NO; +} diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/ClockTimer/ClockRateAdjust.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/ClockTimer/ClockRateAdjust.c new file mode 100644 index 0000000..7156142 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/ClockTimer/ClockRateAdjust.c @@ -0,0 +1,54 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "ClockRateAdjust_fp.h" + +#if CC_ClockRateAdjust // Conditional expansion of this file + +/*(See part 3 specification) +// adjusts the rate of advance of Clock and Timer to provide a better +// approximation to real time. +*/ +TPM_RC +TPM2_ClockRateAdjust(ClockRateAdjust_In* in // IN: input parameter list +) +{ + // Internal Data Update + TimeSetAdjustRate(in->rateAdjust); + + return TPM_RC_SUCCESS; +} + +#endif // CC_ClockRateAdjust \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/ClockTimer/ClockSet.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/ClockTimer/ClockSet.c new file mode 100644 index 0000000..10a8830 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/ClockTimer/ClockSet.c @@ -0,0 +1,64 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "ClockSet_fp.h" + +#if CC_ClockSet // Conditional expansion of this file + +// Read the current TPMS_TIMER_INFO structure settings +// Return Type: TPM_RC +// TPM_RC_NV_RATE NV is unavailable because of rate limit +// TPM_RC_NV_UNAVAILABLE NV is inaccessible +// TPM_RC_VALUE invalid new clock + +TPM_RC +TPM2_ClockSet(ClockSet_In* in // IN: input parameter list +) +{ + // Input Validation + // new time can not be bigger than 0xFFFF000000000000 or smaller than + // current clock + if(in->newTime > 0xFFFF000000000000ULL || in->newTime < go.clock) + return TPM_RCS_VALUE + RC_ClockSet_newTime; + + // Internal Data Update + // Can't modify the clock if NV is not available. + RETURN_IF_NV_IS_NOT_AVAILABLE; + + TimeClockUpdate(in->newTime); + return TPM_RC_SUCCESS; +} + +#endif // CC_ClockSet \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/ClockTimer/ReadClock.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/ClockTimer/ReadClock.c new file mode 100644 index 0000000..d588a29 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/ClockTimer/ReadClock.c @@ -0,0 +1,55 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "ReadClock_fp.h" + +#if CC_ReadClock // Conditional expansion of this file + +/*(See part 3 specification) +// read the current TPMS_TIMER_INFO structure settings +*/ +TPM_RC +TPM2_ReadClock(ReadClock_Out* out // OUT: output parameter list +) +{ + // Command Output + + out->currentTime.time = g_time; + TimeFillInfo(&out->currentTime.clockInfo); + + return TPM_RC_SUCCESS; +} + +#endif // CC_ReadClock \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/CommandAudit/SetCommandCodeAuditStatus.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/CommandAudit/SetCommandCodeAuditStatus.c new file mode 100644 index 0000000..34139b5 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/CommandAudit/SetCommandCodeAuditStatus.c @@ -0,0 +1,103 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "SetCommandCodeAuditStatus_fp.h" + +#if CC_SetCommandCodeAuditStatus // Conditional expansion of this file + +/*(See part 3 specification) +// change the audit status of a command or to set the hash algorithm used for +// the audit digest. +*/ +TPM_RC +TPM2_SetCommandCodeAuditStatus( + SetCommandCodeAuditStatus_In* in // IN: input parameter list +) +{ + + // The command needs NV update. Check if NV is available. + // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at + // this point + RETURN_IF_NV_IS_NOT_AVAILABLE; + + // Internal Data Update + + // Update hash algorithm + if(in->auditAlg != TPM_ALG_NULL && in->auditAlg != gp.auditHashAlg) + { + // Can't change the algorithm and command list at the same time + if(in->setList.count != 0 || in->clearList.count != 0) + return TPM_RCS_VALUE + RC_SetCommandCodeAuditStatus_auditAlg; + + // Change the hash algorithm for audit + gp.auditHashAlg = in->auditAlg; + + // Set the digest size to a unique value that indicates that the digest + // algorithm has been changed. The size will be cleared to zero in the + // command audit processing on exit. + gr.commandAuditDigest.t.size = 1; + + // Save the change of command audit data (this sets g_updateNV so that NV + // will be updated on exit.) + NV_SYNC_PERSISTENT(auditHashAlg); + } + else + { + UINT32 i; + BOOL changed = FALSE; + + // Process set list + for(i = 0; i < in->setList.count; i++) + + // If change is made in CommandAuditSet, set changed flag + if(CommandAuditSet(in->setList.commandCodes[i])) + changed = TRUE; + + // Process clear list + for(i = 0; i < in->clearList.count; i++) + // If change is made in CommandAuditClear, set changed flag + if(CommandAuditClear(in->clearList.commandCodes[i])) + changed = TRUE; + + // if change was made to command list, update NV + if(changed) + // this sets g_updateNV so that NV will be updated on exit. + NV_SYNC_PERSISTENT(auditCommands); + } + + return TPM_RC_SUCCESS; +} + +#endif // CC_SetCommandCodeAuditStatus \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Context/ContextLoad.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Context/ContextLoad.c new file mode 100644 index 0000000..76163bf --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Context/ContextLoad.c @@ -0,0 +1,199 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" + +#if CC_ContextLoad // Conditional expansion of this file + +# include "ContextLoad_fp.h" +# include "Marshal.h" +# include "Context_spt_fp.h" + +/*(See part 3 specification) +// Load context +*/ + +// Return Type: TPM_RC +// TPM_RC_CONTEXT_GAP there is only one available slot and this is not +// the oldest saved session context +// TPM_RC_HANDLE 'context.savedHandle' does not reference a saved +// session +// TPM_RC_HIERARCHY 'context.hierarchy' is disabled +// TPM_RC_INTEGRITY 'context' integrity check fail +// TPM_RC_OBJECT_MEMORY no free slot for an object +// TPM_RC_SESSION_MEMORY no free session slots +// TPM_RC_SIZE incorrect context blob size +TPM_RC +TPM2_ContextLoad(ContextLoad_In* in, // IN: input parameter list + ContextLoad_Out* out // OUT: output parameter list +) +{ + TPM_RC result; + TPM2B_DIGEST integrityToCompare; + TPM2B_DIGEST integrity; + BYTE* buffer; // defined to save some typing + INT32 size; // defined to save some typing + TPM_HT handleType; + TPM2B_SYM_KEY symKey; + TPM2B_IV iv; + + // Input Validation + + // See discussion about the context format in TPM2_ContextSave Detailed Actions + + // IF this is a session context, make sure that the sequence number is + // consistent with the version in the slot + + // Check context blob size + handleType = HandleGetType(in->context.savedHandle); + + // Get integrity from context blob + buffer = in->context.contextBlob.t.buffer; + size = (INT32)in->context.contextBlob.t.size; + result = TPM2B_DIGEST_Unmarshal(&integrity, &buffer, &size); + if(result != TPM_RC_SUCCESS) + return result; + + // the size of the integrity value has to match the size of digest produced + // by the integrity hash + if(integrity.t.size != CryptHashGetDigestSize(CONTEXT_INTEGRITY_HASH_ALG)) + return TPM_RCS_SIZE + RC_ContextLoad_context; + + // Make sure that the context blob has enough space for the fingerprint. This + // is elastic pants to go with the belt and suspenders we already have to make + // sure that the context is complete and untampered. + if((unsigned)size < sizeof(in->context.sequence)) + return TPM_RCS_SIZE + RC_ContextLoad_context; + + // After unmarshaling the integrity value, 'buffer' is pointing at the first + // byte of the integrity protected and encrypted buffer and 'size' is the number + // of integrity protected and encrypted bytes. + + // Compute context integrity + ComputeContextIntegrity(&in->context, &integrityToCompare); + + // Compare integrity + if(!MemoryEqual2B(&integrity.b, &integrityToCompare.b)) + return TPM_RCS_INTEGRITY + RC_ContextLoad_context; + // Compute context encryption key + ComputeContextProtectionKey(&in->context, &symKey, &iv); + + // Decrypt context data in place + CryptSymmetricDecrypt(buffer, + CONTEXT_ENCRYPT_ALG, + CONTEXT_ENCRYPT_KEY_BITS, + symKey.t.buffer, + &iv, + TPM_ALG_CFB, + size, + buffer); + // See if the fingerprint value matches. If not, it is symptomatic of either + // a broken TPM or that the TPM is under attack so go into failure mode. + if(!MemoryEqual(buffer, &in->context.sequence, sizeof(in->context.sequence))) + FAIL(FATAL_ERROR_INTERNAL); + + // step over fingerprint + buffer += sizeof(in->context.sequence); + + // set the remaining size of the context + size -= sizeof(in->context.sequence); + + // Perform object or session specific input check + switch(handleType) + { + case TPM_HT_TRANSIENT: + { + OBJECT* outObject; + + if(size > (INT32)sizeof(OBJECT)) + FAIL(FATAL_ERROR_INTERNAL); + + // Discard any changes to the handle that the TRM might have made + in->context.savedHandle = TRANSIENT_FIRST; + + // If hierarchy is disabled, no object context can be loaded in this + // hierarchy + if(!HierarchyIsEnabled(in->context.hierarchy)) + return TPM_RCS_HIERARCHY + RC_ContextLoad_context; + + // Restore object. If there is no empty space, indicate as much + outObject = + ObjectContextLoad((ANY_OBJECT_BUFFER*)buffer, &out->loadedHandle); + if(outObject == NULL) + return TPM_RC_OBJECT_MEMORY; + + break; + } + case TPM_HT_POLICY_SESSION: + case TPM_HT_HMAC_SESSION: + { + if(size != sizeof(SESSION)) + FAIL(FATAL_ERROR_INTERNAL); + + // This command may cause the orderlyState to be cleared due to + // the update of state reset data. If this is the case, check if NV is + // available first + RETURN_IF_ORDERLY; + + // Check if input handle points to a valid saved session and that the + // sequence number makes sense + if(!SequenceNumberForSavedContextIsValid(&in->context)) + return TPM_RCS_HANDLE + RC_ContextLoad_context; + + // Restore session. A TPM_RC_SESSION_MEMORY, TPM_RC_CONTEXT_GAP error + // may be returned at this point + result = + SessionContextLoad((SESSION_BUF*)buffer, &in->context.savedHandle); + if(result != TPM_RC_SUCCESS) + return result; + + out->loadedHandle = in->context.savedHandle; + + // orderly state should be cleared because of the update of state + // reset and state clear data + g_clearOrderly = TRUE; + + break; + } + default: + // Context blob may only have an object handle or a session handle. + // All the other handle type should be filtered out at unmarshal + FAIL(FATAL_ERROR_INTERNAL); + break; + } + + return TPM_RC_SUCCESS; +} + +#endif // CC_ContextLoad \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Context/ContextSave.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Context/ContextSave.c new file mode 100644 index 0000000..352e52f --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Context/ContextSave.c @@ -0,0 +1,238 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" + +#if CC_ContextSave // Conditional expansion of this file + +# include "ContextSave_fp.h" +# include "Marshal.h" +# include "Context_spt_fp.h" + +/*(See part 3 specification) + Save context +*/ +// Return Type: TPM_RC +// TPM_RC_CONTEXT_GAP a contextID could not be assigned for a session +// context save +// TPM_RC_TOO_MANY_CONTEXTS no more contexts can be saved as the counter has +// maxed out +TPM_RC +TPM2_ContextSave(ContextSave_In* in, // IN: input parameter list + ContextSave_Out* out // OUT: output parameter list +) +{ + TPM_RC result = TPM_RC_SUCCESS; + UINT16 fingerprintSize; // The size of fingerprint in context + // blob. + UINT64 contextID = 0; // session context ID + TPM2B_SYM_KEY symKey; + TPM2B_IV iv; + + TPM2B_DIGEST integrity; + UINT16 integritySize; + BYTE* buffer; + + // This command may cause the orderlyState to be cleared due to + // the update of state reset data. If the state is orderly and + // cannot be changed, exit early. + RETURN_IF_ORDERLY; + + // Internal Data Update + + // This implementation does not do things in quite the same way as described in + // Part 2 of the specification. In Part 2, it indicates that the + // TPMS_CONTEXT_DATA contains two TPM2B values. That is not how this is + // implemented. Rather, the size field of the TPM2B_CONTEXT_DATA is used to + // determine the amount of data in the encrypted data. That part is not + // independently sized. This makes the actual size 2 bytes smaller than + // calculated using Part 2. Since this is opaque to the caller, it is not + // necessary to fix. The actual size is returned by TPM2_GetCapabilties(). + + // Initialize output handle. At the end of command action, the output + // handle of an object will be replaced, while the output handle + // for a session will be the same as input + out->context.savedHandle = in->saveHandle; + + // Get the size of fingerprint in context blob. The sequence value in + // TPMS_CONTEXT structure is used as the fingerprint + fingerprintSize = sizeof(out->context.sequence); + + // Compute the integrity size at the beginning of context blob + integritySize = + sizeof(integrity.t.size) + CryptHashGetDigestSize(CONTEXT_INTEGRITY_HASH_ALG); + + // Perform object or session specific context save + switch(HandleGetType(in->saveHandle)) + { + case TPM_HT_TRANSIENT: + { + OBJECT* object = HandleToObject(in->saveHandle); + ANY_OBJECT_BUFFER* outObject; + UINT16 objectSize = ObjectIsSequence(object) ? sizeof(HASH_OBJECT) + : sizeof(OBJECT); + + outObject = (ANY_OBJECT_BUFFER*)(out->context.contextBlob.t.buffer + + integritySize + fingerprintSize); + + // Set size of the context data. The contents of context blob is vendor + // defined. In this implementation, the size is size of integrity + // plus fingerprint plus the whole internal OBJECT structure + out->context.contextBlob.t.size = + integritySize + fingerprintSize + objectSize; +# if ALG_RSA + // For an RSA key, make sure that the key has had the private exponent + // computed before saving. + if(object->publicArea.type == TPM_ALG_RSA + && !(object->attributes.publicOnly)) + CryptRsaLoadPrivateExponent(&object->publicArea, &object->sensitive); +# endif + // Make sure things fit + pAssert(out->context.contextBlob.t.size + <= sizeof(out->context.contextBlob.t.buffer)); + // Copy the whole internal OBJECT structure to context blob + MemoryCopy(outObject, object, objectSize); + + // Increment object context ID + gr.objectContextID++; + // If object context ID overflows, TPM should be put in failure mode + if(gr.objectContextID == 0) + FAIL(FATAL_ERROR_INTERNAL); + + // Fill in other return values for an object. + out->context.sequence = gr.objectContextID; + // For regular object, savedHandle is 0x80000000. For sequence object, + // savedHandle is 0x80000001. For object with stClear, savedHandle + // is 0x80000002 + if(ObjectIsSequence(object)) + { + out->context.savedHandle = 0x80000001; + SequenceDataExport((HASH_OBJECT*)object, + (HASH_OBJECT_BUFFER*)outObject); + } + else + out->context.savedHandle = + (object->attributes.stClear == SET) ? 0x80000002 : 0x80000000; + // Get object hierarchy + out->context.hierarchy = ObjectGetHierarchy(object); + + break; + } + case TPM_HT_HMAC_SESSION: + case TPM_HT_POLICY_SESSION: + { + SESSION* session = SessionGet(in->saveHandle); + + // Set size of the context data. The contents of context blob is vendor + // defined. In this implementation, the size of context blob is the + // size of a internal session structure plus the size of + // fingerprint plus the size of integrity + out->context.contextBlob.t.size = + integritySize + fingerprintSize + sizeof(*session); + + // Make sure things fit + pAssert(out->context.contextBlob.t.size + < sizeof(out->context.contextBlob.t.buffer)); + + // Copy the whole internal SESSION structure to context blob. + // Save space for fingerprint at the beginning of the buffer + // This is done before anything else so that the actual context + // can be reclaimed after this call + pAssert(sizeof(*session) <= sizeof(out->context.contextBlob.t.buffer) + - integritySize - fingerprintSize); + MemoryCopy( + out->context.contextBlob.t.buffer + integritySize + fingerprintSize, + session, + sizeof(*session)); + // Fill in the other return parameters for a session + // Get a context ID and set the session tracking values appropriately + // TPM_RC_CONTEXT_GAP is a possible error. + // SessionContextSave() will flush the in-memory context + // so no additional errors may occur after this call. + result = SessionContextSave(out->context.savedHandle, &contextID); + if(result != TPM_RC_SUCCESS) + return result; + // sequence number is the current session contextID + out->context.sequence = contextID; + + // use TPM_RH_NULL as hierarchy for session context + out->context.hierarchy = TPM_RH_NULL; + + break; + } + default: + // SaveContext may only take an object handle or a session handle. + // All the other handle type should be filtered out at unmarshal + FAIL(FATAL_ERROR_INTERNAL); + break; + } + + // Save fingerprint at the beginning of encrypted area of context blob. + // Reserve the integrity space + pAssert(sizeof(out->context.sequence) + <= sizeof(out->context.contextBlob.t.buffer) - integritySize); + MemoryCopy(out->context.contextBlob.t.buffer + integritySize, + &out->context.sequence, + sizeof(out->context.sequence)); + + // Compute context encryption key + ComputeContextProtectionKey(&out->context, &symKey, &iv); + + // Encrypt context blob + CryptSymmetricEncrypt(out->context.contextBlob.t.buffer + integritySize, + CONTEXT_ENCRYPT_ALG, + CONTEXT_ENCRYPT_KEY_BITS, + symKey.t.buffer, + &iv, + TPM_ALG_CFB, + out->context.contextBlob.t.size - integritySize, + out->context.contextBlob.t.buffer + integritySize); + + // Compute integrity hash for the object + // In this implementation, the same routine is used for both sessions + // and objects. + ComputeContextIntegrity(&out->context, &integrity); + + // add integrity at the beginning of context blob + buffer = out->context.contextBlob.t.buffer; + TPM2B_DIGEST_Marshal(&integrity, &buffer, NULL); + + // orderly state should be cleared because of the update of state reset and + // state clear data + g_clearOrderly = TRUE; + + return result; +} + +#endif // CC_ContextSave \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Context/Context_spt.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Context/Context_spt.c new file mode 100644 index 0000000..abd98e6 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Context/Context_spt.c @@ -0,0 +1,243 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Includes + +#include "Tpm.h" +#include "Context_spt_fp.h" + +//** Functions + +//*** ComputeContextProtectionKey() +// This function retrieves the symmetric protection key for context encryption +// It is used by TPM2_ConextSave and TPM2_ContextLoad to create the symmetric +// encryption key and iv +/*(See part 1 specification) + KDFa is used to generate the symmetric encryption key and IV. The parameters + of the call are: + Symkey = KDFa(hashAlg, hProof, vendorString, sequence, handle, bits) + where + hashAlg a vendor-defined hash algorithm + hProof the hierarchy proof as selected by the hierarchy parameter + of the TPMS_CONTEXT + vendorString a value used to differentiate the uses of the KDF + sequence the sequence parameter of the TPMS_CONTEXT + handle the handle parameter of the TPMS_CONTEXT + bits the number of bits needed for a symmetric key and IV for + the context encryption +*/ +// Return Type: void +void ComputeContextProtectionKey(TPMS_CONTEXT* contextBlob, // IN: context blob + TPM2B_SYM_KEY* symKey, // OUT: the symmetric key + TPM2B_IV* iv // OUT: the IV. +) +{ + UINT16 symKeyBits; // number of bits in the parent's + // symmetric key + TPM2B_PROOF* proof = NULL; // the proof value to use. Is null for + // everything but a primary object in + // the Endorsement Hierarchy + + BYTE kdfResult[sizeof(TPMU_HA) * 2]; // Value produced by the KDF + + TPM2B_DATA sequence2B, handle2B; + + // Get proof value + proof = HierarchyGetProof(contextBlob->hierarchy); + + // Get sequence value in 2B format + sequence2B.t.size = sizeof(contextBlob->sequence); + cAssert(sequence2B.t.size <= sizeof(sequence2B.t.buffer)); + MemoryCopy(sequence2B.t.buffer, &contextBlob->sequence, sequence2B.t.size); + + // Get handle value in 2B format + handle2B.t.size = sizeof(contextBlob->savedHandle); + cAssert(handle2B.t.size <= sizeof(handle2B.t.buffer)); + MemoryCopy(handle2B.t.buffer, &contextBlob->savedHandle, handle2B.t.size); + + // Get the symmetric encryption key size + symKey->t.size = CONTEXT_ENCRYPT_KEY_BYTES; + symKeyBits = CONTEXT_ENCRYPT_KEY_BITS; + // Get the size of the IV for the algorithm + iv->t.size = CryptGetSymmetricBlockSize(CONTEXT_ENCRYPT_ALG, symKeyBits); + + // KDFa to generate symmetric key and IV value + CryptKDFa(CONTEXT_INTEGRITY_HASH_ALG, + &proof->b, + CONTEXT_KEY, + &sequence2B.b, + &handle2B.b, + (symKey->t.size + iv->t.size) * 8, + kdfResult, + NULL, + FALSE); + + // Copy part of the returned value as the key + pAssert(symKey->t.size <= sizeof(symKey->t.buffer)); + MemoryCopy(symKey->t.buffer, kdfResult, symKey->t.size); + + // Copy the rest as the IV + pAssert(iv->t.size <= sizeof(iv->t.buffer)); + MemoryCopy(iv->t.buffer, &kdfResult[symKey->t.size], iv->t.size); + + return; +} + +//*** ComputeContextIntegrity() +// Generate the integrity hash for a context +// It is used by TPM2_ContextSave to create an integrity hash +// and by TPM2_ContextLoad to compare an integrity hash +/*(See part 1 specification) + The HMAC integrity computation for a saved context is: + HMACvendorAlg(hProof, resetValue {|| clearCount} || sequence || handle || + encContext) + where + HMACvendorAlg HMAC using a vendor-defined hash algorithm + hProof the hierarchy proof as selected by the hierarchy + parameter of the TPMS_CONTEXT + resetValue either a counter value that increments on each TPM Reset + and is not reset over the lifetime of the TPM or a random + value that changes on each TPM Reset and has the size of + the digest produced by vendorAlg + clearCount a counter value that is incremented on each TPM Reset + or TPM Restart. This value is only included if the handle + value is 0x80000002. + sequence the sequence parameter of the TPMS_CONTEXT + handle the handle parameter of the TPMS_CONTEXT + encContext the encrypted context blob +*/ +// Return Type: void +void ComputeContextIntegrity(TPMS_CONTEXT* contextBlob, // IN: context blob + TPM2B_DIGEST* integrity // OUT: integrity +) +{ + HMAC_STATE hmacState; + TPM2B_PROOF* proof; + UINT16 integritySize; + + // Get proof value + proof = HierarchyGetProof(contextBlob->hierarchy); + + // Start HMAC + integrity->t.size = + CryptHmacStart2B(&hmacState, CONTEXT_INTEGRITY_HASH_ALG, &proof->b); + + // Compute integrity size at the beginning of context blob + integritySize = sizeof(integrity->t.size) + integrity->t.size; + + // Adding total reset counter so that the context cannot be + // used after a TPM Reset + CryptDigestUpdateInt( + &hmacState.hashState, sizeof(gp.totalResetCount), gp.totalResetCount); + + // If this is a ST_CLEAR object, add the clear count + // so that this contest cannot be loaded after a TPM Restart + if(contextBlob->savedHandle == 0x80000002) + CryptDigestUpdateInt( + &hmacState.hashState, sizeof(gr.clearCount), gr.clearCount); + + // Adding sequence number to the HMAC to make sure that it doesn't + // get changed + CryptDigestUpdateInt( + &hmacState.hashState, sizeof(contextBlob->sequence), contextBlob->sequence); + + // Protect the handle + CryptDigestUpdateInt(&hmacState.hashState, + sizeof(contextBlob->savedHandle), + contextBlob->savedHandle); + + // Adding sensitive contextData, skip the leading integrity area + CryptDigestUpdate(&hmacState.hashState, + contextBlob->contextBlob.t.size - integritySize, + contextBlob->contextBlob.t.buffer + integritySize); + + // Complete HMAC + CryptHmacEnd2B(&hmacState, &integrity->b); + + return; +} + +//*** SequenceDataExport(); +// This function is used scan through the sequence object and +// either modify the hash state data for export (contextSave) or to +// import it into the internal format (contextLoad). +// This function should only be called after the sequence object has been copied +// to the context buffer (contextSave) or from the context buffer into the sequence +// object. The presumption is that the context buffer version of the data is the +// same size as the internal representation so nothing outsize of the hash context +// area gets modified. +void SequenceDataExport( + HASH_OBJECT* object, // IN: an internal hash object + HASH_OBJECT_BUFFER* exportObject // OUT: a sequence context in a buffer +) +{ + // If the hash object is not an event, then only one hash context is needed + int count = (object->attributes.eventSeq) ? HASH_COUNT : 1; + + for(count--; count >= 0; count--) + { + HASH_STATE* hash = &object->state.hashState[count]; + size_t offset = (BYTE*)hash - (BYTE*)object; + BYTE* exportHash = &((BYTE*)exportObject)[offset]; + + CryptHashExportState(hash, (EXPORT_HASH_STATE*)exportHash); + } +} + +//*** SequenceDataImport(); +// This function is used scan through the sequence object and +// either modify the hash state data for export (contextSave) or to +// import it into the internal format (contextLoad). +// This function should only be called after the sequence object has been copied +// to the context buffer (contextSave) or from the context buffer into the sequence +// object. The presumption is that the context buffer version of the data is the +// same size as the internal representation so nothing outsize of the hash context +// area gets modified. +void SequenceDataImport( + HASH_OBJECT* object, // IN/OUT: an internal hash object + HASH_OBJECT_BUFFER* exportObject // IN/OUT: a sequence context in a buffer +) +{ + // If the hash object is not an event, then only one hash context is needed + int count = (object->attributes.eventSeq) ? HASH_COUNT : 1; + + for(count--; count >= 0; count--) + { + HASH_STATE* hash = &object->state.hashState[count]; + size_t offset = (BYTE*)hash - (BYTE*)object; + BYTE* importHash = &((BYTE*)exportObject)[offset]; + // + CryptHashImportState(hash, (EXPORT_HASH_STATE*)importHash); + } +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Context/EvictControl.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Context/EvictControl.c new file mode 100644 index 0000000..3cb26aa --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Context/EvictControl.c @@ -0,0 +1,130 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "EvictControl_fp.h" + +#if CC_EvictControl // Conditional expansion of this file + +/*(See part 3 specification) +// Make a transient object persistent or evict a persistent object +*/ +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES an object with 'temporary', 'stClear' or 'publicOnly' +// attribute SET cannot be made persistent +// TPM_RC_HIERARCHY 'auth' cannot authorize the operation in the hierarchy +// of 'evictObject' +// TPM_RC_HANDLE 'evictHandle' of the persistent object to be evicted is +// not the same as the 'persistentHandle' argument +// TPM_RC_NV_HANDLE 'persistentHandle' is unavailable +// TPM_RC_NV_SPACE no space in NV to make 'evictHandle' persistent +// TPM_RC_RANGE 'persistentHandle' is not in the range corresponding to +// the hierarchy of 'evictObject' +TPM_RC +TPM2_EvictControl(EvictControl_In* in // IN: input parameter list +) +{ + TPM_RC result; + OBJECT* evictObject; + + // Input Validation + + // Get internal object pointer + evictObject = HandleToObject(in->objectHandle); + + // Temporary, stClear or public only objects can not be made persistent + if(evictObject->attributes.temporary == SET + || evictObject->attributes.stClear == SET + || evictObject->attributes.publicOnly == SET) + return TPM_RCS_ATTRIBUTES + RC_EvictControl_objectHandle; + + // If objectHandle refers to a persistent object, it should be the same as + // input persistentHandle + if(evictObject->attributes.evict == SET + && evictObject->evictHandle != in->persistentHandle) + return TPM_RCS_HANDLE + RC_EvictControl_objectHandle; + + // Additional authorization validation + if(in->auth == TPM_RH_PLATFORM) + { + // To make persistent + if(evictObject->attributes.evict == CLEAR) + { + // PlatformAuth can not set evict object in storage or endorsement + // hierarchy + if(evictObject->attributes.ppsHierarchy == CLEAR) + return TPM_RCS_HIERARCHY + RC_EvictControl_objectHandle; + // Platform cannot use a handle outside of platform persistent range. + if(!NvIsPlatformPersistentHandle(in->persistentHandle)) + return TPM_RCS_RANGE + RC_EvictControl_persistentHandle; + } + // PlatformAuth can delete any persistent object + } + else if(in->auth == TPM_RH_OWNER) + { + // OwnerAuth can not set or clear evict object in platform hierarchy + if(evictObject->attributes.ppsHierarchy == SET) + return TPM_RCS_HIERARCHY + RC_EvictControl_objectHandle; + + // Owner cannot use a handle outside of owner persistent range. + if(evictObject->attributes.evict == CLEAR + && !NvIsOwnerPersistentHandle(in->persistentHandle)) + return TPM_RCS_RANGE + RC_EvictControl_persistentHandle; + } + else + { + // Other authorization is not allowed in this command and should have been + // filtered out in unmarshal process + FAIL(FATAL_ERROR_INTERNAL); + } + // Internal Data Update + // Change evict state + if(evictObject->attributes.evict == CLEAR) + { + // Make object persistent + if(NvFindHandle(in->persistentHandle) != 0) + return TPM_RC_NV_DEFINED; + // A TPM_RC_NV_HANDLE or TPM_RC_NV_SPACE error may be returned at this + // point + result = NvAddEvictObject(in->persistentHandle, evictObject); + } + else + { + // Delete the persistent object in NV + result = NvDeleteEvict(evictObject->evictHandle); + } + return result; +} + +#endif // CC_EvictControl \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Context/FlushContext.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Context/FlushContext.c new file mode 100644 index 0000000..b968d6f --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Context/FlushContext.c @@ -0,0 +1,83 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "FlushContext_fp.h" + +#if CC_FlushContext // Conditional expansion of this file + +/*(See part 3 specification) +// Flush a specific object or session +*/ +// Return Type: TPM_RC +// TPM_RC_HANDLE 'flushHandle' does not reference a loaded object or session +TPM_RC +TPM2_FlushContext(FlushContext_In* in // IN: input parameter list +) +{ + // Internal Data Update + + // Call object or session specific routine to flush + switch(HandleGetType(in->flushHandle)) + { + case TPM_HT_TRANSIENT: + if(!IsObjectPresent(in->flushHandle)) + return TPM_RCS_HANDLE + RC_FlushContext_flushHandle; + // Flush object + FlushObject(in->flushHandle); + break; + case TPM_HT_HMAC_SESSION: + case TPM_HT_POLICY_SESSION: + if(!SessionIsLoaded(in->flushHandle) && !SessionIsSaved(in->flushHandle)) + return TPM_RCS_HANDLE + RC_FlushContext_flushHandle; + + // If the session to be flushed is the exclusive audit session, then + // indicate that there is no exclusive audit session any longer. + if(in->flushHandle == g_exclusiveAuditSession) + g_exclusiveAuditSession = TPM_RH_UNASSIGNED; + + // Flush session + SessionFlush(in->flushHandle); + break; + default: + // This command only takes object or session handle. Other handles + // should be filtered out at handle unmarshal + FAIL(FATAL_ERROR_INTERNAL); + break; + } + + return TPM_RC_SUCCESS; +} + +#endif // CC_FlushContext \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/DA/DictionaryAttackLockReset.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/DA/DictionaryAttackLockReset.c new file mode 100644 index 0000000..3a8c18f --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/DA/DictionaryAttackLockReset.c @@ -0,0 +1,67 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "DictionaryAttackLockReset_fp.h" + +#if CC_DictionaryAttackLockReset // Conditional expansion of this file + +/*(See part 3 specification) +// This command cancels the effect of a TPM lockout due to a number of +// successive authorization failures. If this command is properly authorized, +// the lockout counter is set to 0. +*/ +TPM_RC +TPM2_DictionaryAttackLockReset( + DictionaryAttackLockReset_In* in // IN: input parameter list +) +{ + // Input parameter is not reference in command action + NOT_REFERENCED(in); + + // The command needs NV update. + RETURN_IF_NV_IS_NOT_AVAILABLE; + + // Internal Data Update + + // Set failed tries to 0 + gp.failedTries = 0; + + // Record the changes to NV + NV_SYNC_PERSISTENT(failedTries); + + return TPM_RC_SUCCESS; +} + +#endif // CC_DictionaryAttackLockReset \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/DA/DictionaryAttackParameters.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/DA/DictionaryAttackParameters.c new file mode 100644 index 0000000..ab1e17b --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/DA/DictionaryAttackParameters.c @@ -0,0 +1,76 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "DictionaryAttackParameters_fp.h" + +#if CC_DictionaryAttackParameters // Conditional expansion of this file + +/*(See part 3 specification) +// change the lockout parameters +*/ +TPM_RC +TPM2_DictionaryAttackParameters( + DictionaryAttackParameters_In* in // IN: input parameter list +) +{ + // The command needs NV update. + RETURN_IF_NV_IS_NOT_AVAILABLE; + + // Internal Data Update + + // Set dictionary attack parameters + gp.maxTries = in->newMaxTries; + gp.recoveryTime = in->newRecoveryTime; + gp.lockoutRecovery = in->lockoutRecovery; + +# if 0 // Errata eliminates this code + // This functionality has been disabled. The preferred implementation is now + // to leave failedTries unchanged when the parameters are changed. This could + // have the effect of putting the TPM into DA lockout if in->newMaxTries is + // not greater than the current value of gp.failedTries. + // Set failed tries to 0 + gp.failedTries = 0; +# endif + + // Record the changes to NV + NV_SYNC_PERSISTENT(failedTries); + NV_SYNC_PERSISTENT(maxTries); + NV_SYNC_PERSISTENT(recoveryTime); + NV_SYNC_PERSISTENT(lockoutRecovery); + + return TPM_RC_SUCCESS; +} + +#endif // CC_DictionaryAttackParameters \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Duplication/Duplicate.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Duplication/Duplicate.c new file mode 100644 index 0000000..38111f0 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Duplication/Duplicate.c @@ -0,0 +1,162 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "Duplicate_fp.h" + +#if CC_Duplicate // Conditional expansion of this file + +# include "Object_spt_fp.h" + +/*(See part 3 specification) +// Duplicate a loaded object +*/ +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES key to duplicate has 'fixedParent' SET +// TPM_RC_HASH for an RSA key, the nameAlg digest size for the +// newParent is not compatible with the key size +// TPM_RC_HIERARCHY 'encryptedDuplication' is SET and 'newParentHandle' +// specifies Null Hierarchy +// TPM_RC_KEY 'newParentHandle' references invalid ECC key (public +// point not on the curve) +// TPM_RC_SIZE input encryption key size does not match the +// size specified in symmetric algorithm +// TPM_RC_SYMMETRIC 'encryptedDuplication' is SET but no symmetric +// algorithm is provided +// TPM_RC_TYPE 'newParentHandle' is neither a storage key nor +// TPM_RH_NULL; or the object has a NULL nameAlg +// TPM_RC_VALUE for an RSA newParent, the sizes of the digest and +// the encryption key are too large to be OAEP encoded +TPM_RC +TPM2_Duplicate(Duplicate_In* in, // IN: input parameter list + Duplicate_Out* out // OUT: output parameter list +) +{ + TPM_RC result = TPM_RC_SUCCESS; + TPMT_SENSITIVE sensitive; + + UINT16 innerKeySize = 0; // encrypt key size for inner wrap + + OBJECT* object; + OBJECT* newParent; + TPM2B_DATA data; + + // Input Validation + + // Get duplicate object pointer + object = HandleToObject(in->objectHandle); + // Get new parent + newParent = HandleToObject(in->newParentHandle); + + // duplicate key must have fixParent bit CLEAR. + if(IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, fixedParent)) + return TPM_RCS_ATTRIBUTES + RC_Duplicate_objectHandle; + + // Do not duplicate object with NULL nameAlg + if(object->publicArea.nameAlg == TPM_ALG_NULL) + return TPM_RCS_TYPE + RC_Duplicate_objectHandle; + + // new parent key must be a storage object or TPM_RH_NULL + if(in->newParentHandle != TPM_RH_NULL && !ObjectIsStorage(in->newParentHandle)) + return TPM_RCS_TYPE + RC_Duplicate_newParentHandle; + + // If the duplicated object has encryptedDuplication SET, then there must be + // an inner wrapper and the new parent may not be TPM_RH_NULL + if(IS_ATTRIBUTE( + object->publicArea.objectAttributes, TPMA_OBJECT, encryptedDuplication)) + { + if(in->symmetricAlg.algorithm == TPM_ALG_NULL) + return TPM_RCS_SYMMETRIC + RC_Duplicate_symmetricAlg; + if(in->newParentHandle == TPM_RH_NULL) + return TPM_RCS_HIERARCHY + RC_Duplicate_newParentHandle; + } + + if(in->symmetricAlg.algorithm == TPM_ALG_NULL) + { + // if algorithm is TPM_ALG_NULL, input key size must be 0 + if(in->encryptionKeyIn.t.size != 0) + return TPM_RCS_SIZE + RC_Duplicate_encryptionKeyIn; + } + else + { + // Get inner wrap key size + innerKeySize = in->symmetricAlg.keyBits.sym; + + // If provided the input symmetric key must match the size of the algorithm + if(in->encryptionKeyIn.t.size != 0 + && in->encryptionKeyIn.t.size != (innerKeySize + 7) / 8) + return TPM_RCS_SIZE + RC_Duplicate_encryptionKeyIn; + } + + // Command Output + + if(in->newParentHandle != TPM_RH_NULL) + { + // Make encrypt key and its associated secret structure. A TPM_RC_KEY + // error may be returned at this point + out->outSymSeed.t.size = sizeof(out->outSymSeed.t.secret); + result = + CryptSecretEncrypt(newParent, DUPLICATE_STRING, &data, &out->outSymSeed); + if(result != TPM_RC_SUCCESS) + return result; + } + else + { + // Do not apply outer wrapper + data.t.size = 0; + out->outSymSeed.t.size = 0; + } + + // Copy sensitive area + sensitive = object->sensitive; + + // Prepare output private data from sensitive. + // Note: If there is no encryption key, one will be provided by + // SensitiveToDuplicate(). This is why the assignment of encryptionKeyIn to + // encryptionKeyOut will work properly and is not conditional. + SensitiveToDuplicate(&sensitive, + &object->name.b, + newParent, + object->publicArea.nameAlg, + &data.b, + &in->symmetricAlg, + &in->encryptionKeyIn, + &out->duplicate); + + out->encryptionKeyOut = in->encryptionKeyIn; + + return TPM_RC_SUCCESS; +} + +#endif // CC_Duplicate \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Duplication/Import.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Duplication/Import.c new file mode 100644 index 0000000..690fc8b --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Duplication/Import.c @@ -0,0 +1,218 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "Import_fp.h" + +#if CC_Import // Conditional expansion of this file + +# include "Object_spt_fp.h" + +/*(See part 3 specification) +// This command allows an asymmetrically encrypted blob, containing a duplicated +// object to be re-encrypted using the group symmetric key associated with the +// parent. +*/ +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES 'FixedTPM' and 'fixedParent' of 'objectPublic' are not +// both CLEAR; or 'inSymSeed' is nonempty and +// 'parentHandle' does not reference a decryption key; or +// 'objectPublic' and 'parentHandle' have incompatible +// or inconsistent attributes; or +// encrytpedDuplication is SET in 'objectPublic' but the +// inner or outer wrapper is missing. +// Note that if the TPM provides parameter values, the +// parameter number will indicate 'symmetricKey' (missing +// inner wrapper) or 'inSymSeed' (missing outer wrapper) +// TPM_RC_BINDING 'duplicate' and 'objectPublic' are not +// cryptographically bound +// TPM_RC_ECC_POINT 'inSymSeed' is nonempty and ECC point in 'inSymSeed' +// is not on the curve +// TPM_RC_HASH 'objectPublic' does not have a valid nameAlg +// TPM_RC_INSUFFICIENT 'inSymSeed' is nonempty and failed to retrieve ECC +// point from the secret; or unmarshaling sensitive value +// from 'duplicate' failed the result of 'inSymSeed' +// decryption +// TPM_RC_INTEGRITY 'duplicate' integrity is broken +// TPM_RC_KDF 'objectPublic' representing decrypting keyed hash +// object specifies invalid KDF +// TPM_RC_KEY inconsistent parameters of 'objectPublic'; or +// 'inSymSeed' is nonempty and 'parentHandle' does not +// reference a key of supported type; or +// invalid key size in 'objectPublic' representing an +// asymmetric key +// TPM_RC_NO_RESULT 'inSymSeed' is nonempty and multiplication resulted in +// ECC point at infinity +// TPM_RC_OBJECT_MEMORY no available object slot +// TPM_RC_SCHEME inconsistent attributes 'decrypt', 'sign', +// 'restricted' and key's scheme ID in 'objectPublic'; +// or hash algorithm is inconsistent with the scheme ID +// for keyed hash object +// TPM_RC_SIZE 'authPolicy' size does not match digest size of the +// name algorithm in 'objectPublic'; or +// 'symmetricAlg' and 'encryptionKey' have different +// sizes; or +// 'inSymSeed' is nonempty and it size is not +// consistent with the type of 'parentHandle'; or +// unmarshaling sensitive value from 'duplicate' failed +// TPM_RC_SYMMETRIC 'objectPublic' is either a storage key with no +// symmetric algorithm or a non-storage key with +// symmetric algorithm different from TPM_ALG_NULL +// TPM_RC_TYPE unsupported type of 'objectPublic'; or +// 'parentHandle' is not a storage key; or +// only the public portion of 'parentHandle' is loaded; +// or 'objectPublic' and 'duplicate' are of different +// types +// TPM_RC_VALUE nonempty 'inSymSeed' and its numeric value is +// greater than the modulus of the key referenced by +// 'parentHandle' or 'inSymSeed' is larger than the +// size of the digest produced by the name algorithm of +// the symmetric key referenced by 'parentHandle' +TPM_RC +TPM2_Import(Import_In* in, // IN: input parameter list + Import_Out* out // OUT: output parameter list +) +{ + TPM_RC result = TPM_RC_SUCCESS; + OBJECT* parentObject; + TPM2B_DATA data; // symmetric key + TPMT_SENSITIVE sensitive; + TPM2B_NAME name; + TPMA_OBJECT attributes; + UINT16 innerKeySize = 0; // encrypt key size for inner + // wrapper + + // Input Validation + // to save typing + attributes = in->objectPublic.publicArea.objectAttributes; + // FixedTPM and fixedParent must be CLEAR + if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM) + || IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedParent)) + return TPM_RCS_ATTRIBUTES + RC_Import_objectPublic; + + // Get parent pointer + parentObject = HandleToObject(in->parentHandle); + + if(!ObjectIsParent(parentObject)) + return TPM_RCS_TYPE + RC_Import_parentHandle; + + if(in->symmetricAlg.algorithm != TPM_ALG_NULL) + { + // Get inner wrap key size + innerKeySize = in->symmetricAlg.keyBits.sym; + // Input symmetric key must match the size of algorithm. + if(in->encryptionKey.t.size != (innerKeySize + 7) / 8) + return TPM_RCS_SIZE + RC_Import_encryptionKey; + } + else + { + // If input symmetric algorithm is NULL, input symmetric key size must + // be 0 as well + if(in->encryptionKey.t.size != 0) + return TPM_RCS_SIZE + RC_Import_encryptionKey; + // If encryptedDuplication is SET, then the object must have an inner + // wrapper + if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, encryptedDuplication)) + return TPM_RCS_ATTRIBUTES + RC_Import_encryptionKey; + } + // See if there is an outer wrapper + if(in->inSymSeed.t.size != 0) + { + // in->inParentHandle is a parent, but in order to decrypt an outer wrapper, + // it must be able to do key exchange and a symmetric key can't do that. + if(parentObject->publicArea.type == TPM_ALG_SYMCIPHER) + return TPM_RCS_TYPE + RC_Import_parentHandle; + + // Decrypt input secret data via asymmetric decryption. TPM_RC_ATTRIBUTES, + // TPM_RC_ECC_POINT, TPM_RC_INSUFFICIENT, TPM_RC_KEY, TPM_RC_NO_RESULT, + // TPM_RC_SIZE, TPM_RC_VALUE may be returned at this point + result = CryptSecretDecrypt( + parentObject, NULL, DUPLICATE_STRING, &in->inSymSeed, &data); + pAssert(result != TPM_RC_BINDING); + if(result != TPM_RC_SUCCESS) + return RcSafeAddToResult(result, RC_Import_inSymSeed); + } + else + { + // If encrytpedDuplication is set, then the object must have an outer + // wrapper + if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, encryptedDuplication)) + return TPM_RCS_ATTRIBUTES + RC_Import_inSymSeed; + data.t.size = 0; + } + // Compute name of object + PublicMarshalAndComputeName(&(in->objectPublic.publicArea), &name); + if(name.t.size == 0) + return TPM_RCS_HASH + RC_Import_objectPublic; + + // Retrieve sensitive from private. + // TPM_RC_INSUFFICIENT, TPM_RC_INTEGRITY, TPM_RC_SIZE may be returned here. + result = DuplicateToSensitive(&in->duplicate.b, + &name.b, + parentObject, + in->objectPublic.publicArea.nameAlg, + &data.b, + &in->symmetricAlg, + &in->encryptionKey.b, + &sensitive); + if(result != TPM_RC_SUCCESS) + return RcSafeAddToResult(result, RC_Import_duplicate); + + // If the parent of this object has fixedTPM SET, then validate this + // object as if it were being loaded so that validation can be skipped + // when it is actually loaded. + if(IS_ATTRIBUTE(parentObject->publicArea.objectAttributes, TPMA_OBJECT, fixedTPM)) + { + result = ObjectLoad(NULL, + NULL, + &in->objectPublic.publicArea, + &sensitive, + RC_Import_objectPublic, + RC_Import_duplicate, + NULL); + } + // Command output + if(result == TPM_RC_SUCCESS) + { + // Prepare output private data from sensitive + SensitiveToPrivate(&sensitive, + &name, + parentObject, + in->objectPublic.publicArea.nameAlg, + &out->outPrivate); + } + return result; +} + +#endif // CC_Import \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Duplication/Rewrap.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Duplication/Rewrap.c new file mode 100644 index 0000000..c76a1ec --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Duplication/Rewrap.c @@ -0,0 +1,164 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "Rewrap_fp.h" + +#if CC_Rewrap // Conditional expansion of this file + +# include "Object_spt_fp.h" + +/*(See part 3 specification) +// This command allows the TPM to serve in the role as an MA. +*/ +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES 'newParent' is not a decryption key +// TPM_RC_HANDLE 'oldParent' is not consistent with inSymSeed +// TPM_RC_INTEGRITY the integrity check of 'inDuplicate' failed +// TPM_RC_KEY for an ECC key, the public key is not on the curve +// of the curve ID +// TPM_RC_KEY_SIZE the decrypted input symmetric key size +// does not match the symmetric algorithm +// key size of 'oldParent' +// TPM_RC_TYPE 'oldParent' is not a storage key, or 'newParent' +// is not a storage key +// TPM_RC_VALUE for an 'oldParent'; RSA key, the data to be decrypted +// is greater than the public exponent +// Unmarshal errors errors during unmarshaling the input +// encrypted buffer to a ECC public key, or +// unmarshal the private buffer to 'sensitive' +TPM_RC +TPM2_Rewrap(Rewrap_In* in, // IN: input parameter list + Rewrap_Out* out // OUT: output parameter list +) +{ + TPM_RC result = TPM_RC_SUCCESS; + TPM2B_DATA data; // symmetric key + UINT16 hashSize = 0; + TPM2B_PRIVATE privateBlob; // A temporary private blob + // to transit between old + // and new wrappers + // Input Validation + if((in->inSymSeed.t.size == 0 && in->oldParent != TPM_RH_NULL) + || (in->inSymSeed.t.size != 0 && in->oldParent == TPM_RH_NULL)) + return TPM_RCS_HANDLE + RC_Rewrap_oldParent; + if(in->oldParent != TPM_RH_NULL) + { + OBJECT* oldParent = HandleToObject(in->oldParent); + + // old parent key must be a storage object + if(!ObjectIsStorage(in->oldParent)) + return TPM_RCS_TYPE + RC_Rewrap_oldParent; + // Decrypt input secret data via asymmetric decryption. A + // TPM_RC_VALUE, TPM_RC_KEY or unmarshal errors may be returned at this + // point + result = CryptSecretDecrypt( + oldParent, NULL, DUPLICATE_STRING, &in->inSymSeed, &data); + if(result != TPM_RC_SUCCESS) + return TPM_RCS_VALUE + RC_Rewrap_inSymSeed; + // Unwrap Outer + result = UnwrapOuter(oldParent, + &in->name.b, + oldParent->publicArea.nameAlg, + &data.b, + FALSE, + in->inDuplicate.t.size, + in->inDuplicate.t.buffer); + if(result != TPM_RC_SUCCESS) + return RcSafeAddToResult(result, RC_Rewrap_inDuplicate); + // Copy unwrapped data to temporary variable, remove the integrity field + hashSize = + sizeof(UINT16) + CryptHashGetDigestSize(oldParent->publicArea.nameAlg); + privateBlob.t.size = in->inDuplicate.t.size - hashSize; + pAssert(privateBlob.t.size <= sizeof(privateBlob.t.buffer)); + MemoryCopy(privateBlob.t.buffer, + in->inDuplicate.t.buffer + hashSize, + privateBlob.t.size); + } + else + { + // No outer wrap from input blob. Direct copy. + privateBlob = in->inDuplicate; + } + if(in->newParent != TPM_RH_NULL) + { + OBJECT* newParent; + newParent = HandleToObject(in->newParent); + + // New parent must be a storage object + if(!ObjectIsStorage(in->newParent)) + return TPM_RCS_TYPE + RC_Rewrap_newParent; + // Make new encrypt key and its associated secret structure. A + // TPM_RC_VALUE error may be returned at this point if RSA algorithm is + // enabled in TPM + out->outSymSeed.t.size = sizeof(out->outSymSeed.t.secret); + result = + CryptSecretEncrypt(newParent, DUPLICATE_STRING, &data, &out->outSymSeed); + if(result != TPM_RC_SUCCESS) + return result; + // Copy temporary variable to output, reserve the space for integrity + hashSize = + sizeof(UINT16) + CryptHashGetDigestSize(newParent->publicArea.nameAlg); + // Make sure that everything fits into the output buffer + // Note: this is mostly only an issue if there was no outer wrapper on + // 'inDuplicate'. It could be as large as a TPM2B_PRIVATE buffer. If we add + // a digest for an outer wrapper, it won't fit anymore. + if((privateBlob.t.size + hashSize) > sizeof(out->outDuplicate.t.buffer)) + return TPM_RCS_VALUE + RC_Rewrap_inDuplicate; + // Command output + out->outDuplicate.t.size = privateBlob.t.size; + pAssert(privateBlob.t.size <= sizeof(out->outDuplicate.t.buffer) - hashSize); + MemoryCopy(out->outDuplicate.t.buffer + hashSize, + privateBlob.t.buffer, + privateBlob.t.size); + // Produce outer wrapper for output + out->outDuplicate.t.size = ProduceOuterWrap(newParent, + &in->name.b, + newParent->publicArea.nameAlg, + &data.b, + FALSE, + out->outDuplicate.t.size, + out->outDuplicate.t.buffer); + } + else // New parent is a null key so there is no seed + { + out->outSymSeed.t.size = 0; + + // Copy privateBlob directly + out->outDuplicate = privateBlob; + } + return TPM_RC_SUCCESS; +} + +#endif // CC_Rewrap \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyAuthValue.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyAuthValue.c new file mode 100644 index 0000000..42bff9a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyAuthValue.c @@ -0,0 +1,80 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "PolicyAuthValue_fp.h" + +#if CC_PolicyAuthValue // Conditional expansion of this file + +# include "Policy_spt_fp.h" + +/*(See part 3 specification) +// allows a policy to be bound to the authorization value of the authorized +// object +*/ +TPM_RC +TPM2_PolicyAuthValue(PolicyAuthValue_In* in // IN: input parameter list +) +{ + SESSION* session; + TPM_CC commandCode = TPM_CC_PolicyAuthValue; + HASH_STATE hashState; + + // Internal Data Update + + // Get pointer to the session structure + session = SessionGet(in->policySession); + + // Update policy hash + // policyDigestnew = hash(policyDigestold || TPM_CC_PolicyAuthValue) + // Start hash + CryptHashStart(&hashState, session->authHashAlg); + + // add old digest + CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); + + // add commandCode + CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); + + // complete the hash and get the results + CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); + + // update isAuthValueNeeded bit in the session context + session->attributes.isAuthValueNeeded = SET; + session->attributes.isPasswordNeeded = CLEAR; + + return TPM_RC_SUCCESS; +} + +#endif // CC_PolicyAuthValue \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyAuthorize.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyAuthorize.c new file mode 100644 index 0000000..0486836 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyAuthorize.c @@ -0,0 +1,128 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "PolicyAuthorize_fp.h" + +#if CC_PolicyAuthorize // Conditional expansion of this file + +# include "Policy_spt_fp.h" + +/*(See part 3 specification) +// Change policy by a signature from authority +*/ +// Return Type: TPM_RC +// TPM_RC_HASH hash algorithm in 'keyName' is not supported +// TPM_RC_SIZE 'keyName' is not the correct size for its hash algorithm +// TPM_RC_VALUE the current policyDigest of 'policySession' does not +// match 'approvedPolicy'; or 'checkTicket' doesn't match +// the provided values +TPM_RC +TPM2_PolicyAuthorize(PolicyAuthorize_In* in // IN: input parameter list +) +{ + SESSION* session; + TPM2B_DIGEST authHash; + HASH_STATE hashState; + TPMT_TK_VERIFIED ticket; + TPM_ALG_ID hashAlg; + UINT16 digestSize; + + // Input Validation + + // Get pointer to the session structure + session = SessionGet(in->policySession); + + if(in->keySign.t.size < 2) + { + return TPM_RCS_SIZE + RC_PolicyAuthorize_keySign; + } + + // Extract from the Name of the key, the algorithm used to compute its Name + hashAlg = BYTE_ARRAY_TO_UINT16(in->keySign.t.name); + + // 'keySign' parameter needs to use a supported hash algorithm, otherwise + // can't tell how large the digest should be + if(!CryptHashIsValidAlg(hashAlg, FALSE)) + return TPM_RCS_HASH + RC_PolicyAuthorize_keySign; + + digestSize = CryptHashGetDigestSize(hashAlg); + if(digestSize != (in->keySign.t.size - 2)) + return TPM_RCS_SIZE + RC_PolicyAuthorize_keySign; + + //If this is a trial policy, skip all validations + if(session->attributes.isTrialPolicy == CLEAR) + { + // Check that "approvedPolicy" matches the current value of the + // policyDigest in policy session + if(!MemoryEqual2B(&session->u2.policyDigest.b, &in->approvedPolicy.b)) + return TPM_RCS_VALUE + RC_PolicyAuthorize_approvedPolicy; + + // Validate ticket TPMT_TK_VERIFIED + // Compute aHash. The authorizing object sign a digest + // aHash := hash(approvedPolicy || policyRef). + // Start hash + authHash.t.size = CryptHashStart(&hashState, hashAlg); + + // add approvedPolicy + CryptDigestUpdate2B(&hashState, &in->approvedPolicy.b); + + // add policyRef + CryptDigestUpdate2B(&hashState, &in->policyRef.b); + + // complete hash + CryptHashEnd2B(&hashState, &authHash.b); + + // re-compute TPMT_TK_VERIFIED + TicketComputeVerified( + in->checkTicket.hierarchy, &authHash, &in->keySign, &ticket); + + // Compare ticket digest. If not match, return error + if(!MemoryEqual2B(&in->checkTicket.digest.b, &ticket.digest.b)) + return TPM_RCS_VALUE + RC_PolicyAuthorize_checkTicket; + } + + // Internal Data Update + + // Set policyDigest to zero digest + PolicyDigestClear(session); + + // Update policyDigest + PolicyContextUpdate( + TPM_CC_PolicyAuthorize, &in->keySign, &in->policyRef, NULL, 0, session); + + return TPM_RC_SUCCESS; +} + +#endif // CC_PolicyAuthorize diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyAuthorizeNV.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyAuthorizeNV.c new file mode 100644 index 0000000..4039580 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyAuthorizeNV.c @@ -0,0 +1,122 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" + +#if CC_PolicyAuthorizeNV // Conditional expansion of this file + +# include "PolicyAuthorizeNV_fp.h" +# include "Policy_spt_fp.h" +# include "Marshal.h" + +/*(See part 3 specification) +// Change policy by a signature from authority +*/ +// Return Type: TPM_RC +// TPM_RC_HASH hash algorithm in 'keyName' is not supported or is not +// the same as the hash algorithm of the policy session +// TPM_RC_SIZE 'keyName' is not the correct size for its hash algorithm +// TPM_RC_VALUE the current policyDigest of 'policySession' does not +// match 'approvedPolicy'; or 'checkTicket' doesn't match +// the provided values +TPM_RC +TPM2_PolicyAuthorizeNV(PolicyAuthorizeNV_In* in) +{ + SESSION* session; + TPM_RC result; + NV_REF locator; + NV_INDEX* nvIndex = NvGetIndexInfo(in->nvIndex, &locator); + TPM2B_NAME name; + TPMT_HA policyInNv; + BYTE nvTemp[sizeof(TPMT_HA)]; + BYTE* buffer = nvTemp; + INT32 size; + + // Input Validation + // Get pointer to the session structure + session = SessionGet(in->policySession); + + // Skip checks if this is a trial policy + if(!session->attributes.isTrialPolicy) + { + // Check the authorizations for reading + // Common read access checks. NvReadAccessChecks() returns + // TPM_RC_NV_AUTHORIZATION, TPM_RC_NV_LOCKED, or TPM_RC_NV_UNINITIALIZED + // error may be returned at this point + result = NvReadAccessChecks( + in->authHandle, in->nvIndex, nvIndex->publicArea.attributes); + if(result != TPM_RC_SUCCESS) + return result; + + // Read the contents of the index into a temp buffer + size = MIN(nvIndex->publicArea.dataSize, sizeof(TPMT_HA)); + NvGetIndexData(nvIndex, locator, 0, (UINT16)size, nvTemp); + + // Unmarshal the contents of the buffer into the internal format of a + // TPMT_HA so that the hash and digest elements can be accessed from the + // structure rather than the byte array that is in the Index (written by + // user of the Index). + result = TPMT_HA_Unmarshal(&policyInNv, &buffer, &size, FALSE); + if(result != TPM_RC_SUCCESS) + return result; + + // Verify that the hash is the same + if(policyInNv.hashAlg != session->authHashAlg) + return TPM_RC_HASH; + + // See if the contents of the digest in the Index matches the value + // in the policy + if(!MemoryEqual(&policyInNv.digest, + &session->u2.policyDigest.t.buffer, + session->u2.policyDigest.t.size)) + return TPM_RC_VALUE; + } + + // Internal Data Update + + // Set policyDigest to zero digest + PolicyDigestClear(session); + + // Update policyDigest + PolicyContextUpdate(TPM_CC_PolicyAuthorizeNV, + EntityGetName(in->nvIndex, &name), + NULL, + NULL, + 0, + session); + + return TPM_RC_SUCCESS; +} + +#endif // CC_PolicyAuthorize \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyCommandCode.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyCommandCode.c new file mode 100644 index 0000000..5a49be2 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyCommandCode.c @@ -0,0 +1,89 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "PolicyCommandCode_fp.h" + +#if CC_PolicyCommandCode // Conditional expansion of this file + +/*(See part 3 specification) +// Add a Command Code restriction to the policyDigest +*/ +// Return Type: TPM_RC +// TPM_RC_VALUE 'commandCode' of 'policySession' previously set to +// a different value + +TPM_RC +TPM2_PolicyCommandCode(PolicyCommandCode_In* in // IN: input parameter list +) +{ + SESSION* session; + TPM_CC commandCode = TPM_CC_PolicyCommandCode; + HASH_STATE hashState; + + // Input validation + + // Get pointer to the session structure + session = SessionGet(in->policySession); + + if(session->commandCode != 0 && session->commandCode != in->code) + return TPM_RCS_VALUE + RC_PolicyCommandCode_code; + if(CommandCodeToCommandIndex(in->code) == UNIMPLEMENTED_COMMAND_INDEX) + return TPM_RCS_POLICY_CC + RC_PolicyCommandCode_code; + + // Internal Data Update + // Update policy hash + // policyDigestnew = hash(policyDigestold || TPM_CC_PolicyCommandCode || code) + // Start hash + CryptHashStart(&hashState, session->authHashAlg); + + // add old digest + CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); + + // add commandCode + CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); + + // add input commandCode + CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), in->code); + + // complete the hash and get the results + CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); + + // update commandCode value in session context + session->commandCode = in->code; + + return TPM_RC_SUCCESS; +} + +#endif // CC_PolicyCommandCode \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyCounterTimer.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyCounterTimer.c new file mode 100644 index 0000000..065ea43 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyCounterTimer.c @@ -0,0 +1,130 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "PolicyCounterTimer_fp.h" + +#if CC_PolicyCounterTimer // Conditional expansion of this file + +# include "Policy_spt_fp.h" + +/*(See part 3 specification) +// Add a conditional gating of a policy based on the contents of the +// TPMS_TIME_INFO structure. +*/ +// Return Type: TPM_RC +// TPM_RC_POLICY the comparison of the selected portion of the +// TPMS_TIME_INFO with 'operandB' failed +// TPM_RC_RANGE 'offset' + 'size' exceed size of TPMS_TIME_INFO +// structure +TPM_RC +TPM2_PolicyCounterTimer(PolicyCounterTimer_In* in // IN: input parameter list +) +{ + SESSION* session; + TIME_INFO infoData; // data buffer of TPMS_TIME_INFO + BYTE* pInfoData = (BYTE*)&infoData; + UINT16 infoDataSize; + TPM_CC commandCode = TPM_CC_PolicyCounterTimer; + HASH_STATE hashState; + TPM2B_DIGEST argHash; + + // Input Validation + // Get a marshaled time structure + infoDataSize = TimeGetMarshaled(&infoData); + // Make sure that the referenced stays within the bounds of the structure. + // NOTE: the offset checks are made even for a trial policy because the policy + // will not make any sense if the references are out of bounds of the timer + // structure. + if(in->offset > infoDataSize) + return TPM_RCS_VALUE + RC_PolicyCounterTimer_offset; + if((UINT32)in->offset + (UINT32)in->operandB.t.size > infoDataSize) + return TPM_RCS_RANGE; + // Get pointer to the session structure + session = SessionGet(in->policySession); + + //If this is a trial policy, skip the check to see if the condition is met. + if(session->attributes.isTrialPolicy == CLEAR) + { + // If the command is going to use any part of the counter or timer, need + // to verify that time is advancing. + // The time and clock vales are the first two 64-bit values in the clock + if(in->offset < sizeof(UINT64) + sizeof(UINT64)) + { + // Using Clock or Time so see if clock is running. Clock doesn't + // run while NV is unavailable. + // TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned here. + RETURN_IF_NV_IS_NOT_AVAILABLE; + } + // offset to the starting position + pInfoData = (BYTE*)infoData; + // Check to see if the condition is valid + if(!PolicySptCheckCondition(in->operation, + pInfoData + in->offset, + in->operandB.t.buffer, + in->operandB.t.size)) + return TPM_RC_POLICY; + } + // Internal Data Update + // Start argument list hash + argHash.t.size = CryptHashStart(&hashState, session->authHashAlg); + // add operandB + CryptDigestUpdate2B(&hashState, &in->operandB.b); + // add offset + CryptDigestUpdateInt(&hashState, sizeof(UINT16), in->offset); + // add operation + CryptDigestUpdateInt(&hashState, sizeof(TPM_EO), in->operation); + // complete argument hash + CryptHashEnd2B(&hashState, &argHash.b); + + // update policyDigest + // start hash + CryptHashStart(&hashState, session->authHashAlg); + + // add old digest + CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); + + // add commandCode + CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); + + // add argument digest + CryptDigestUpdate2B(&hashState, &argHash.b); + + // complete the digest + CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); + + return TPM_RC_SUCCESS; +} + +#endif // CC_PolicyCounterTimer \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyCpHash.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyCpHash.c new file mode 100644 index 0000000..32bf665 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyCpHash.c @@ -0,0 +1,101 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "PolicyCpHash_fp.h" + +#if CC_PolicyCpHash // Conditional expansion of this file + +/*(See part 3 specification) +// Add a cpHash restriction to the policyDigest +*/ +// Return Type: TPM_RC +// TPM_RC_CPHASH cpHash of 'policySession' has previously been set +// to a different value +// TPM_RC_SIZE 'cpHashA' is not the size of a digest produced +// by the hash algorithm associated with +// 'policySession' +TPM_RC +TPM2_PolicyCpHash(PolicyCpHash_In* in // IN: input parameter list +) +{ + SESSION* session; + TPM_CC commandCode = TPM_CC_PolicyCpHash; + HASH_STATE hashState; + + // Input Validation + + // Get pointer to the session structure + session = SessionGet(in->policySession); + + // A valid cpHash must have the same size as session hash digest + // NOTE: the size of the digest can't be zero because TPM_ALG_NULL + // can't be used for the authHashAlg. + if(in->cpHashA.t.size != CryptHashGetDigestSize(session->authHashAlg)) + return TPM_RCS_SIZE + RC_PolicyCpHash_cpHashA; + + // error if the cpHash in session context is not empty and is not the same + // as the input or is not a cpHash + if((session->u1.cpHash.t.size != 0) + && (!session->attributes.isCpHashDefined + || !MemoryEqual2B(&in->cpHashA.b, &session->u1.cpHash.b))) + return TPM_RC_CPHASH; + + // Internal Data Update + + // Update policy hash + // policyDigestnew = hash(policyDigestold || TPM_CC_PolicyCpHash || cpHashA) + // Start hash + CryptHashStart(&hashState, session->authHashAlg); + + // add old digest + CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); + + // add commandCode + CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); + + // add cpHashA + CryptDigestUpdate2B(&hashState, &in->cpHashA.b); + + // complete the digest and get the results + CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); + + // update cpHash in session context + session->u1.cpHash = in->cpHashA; + session->attributes.isCpHashDefined = SET; + + return TPM_RC_SUCCESS; +} + +#endif // CC_PolicyCpHash \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyDuplicationSelect.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyDuplicationSelect.c new file mode 100644 index 0000000..c96135d --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyDuplicationSelect.c @@ -0,0 +1,113 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "PolicyDuplicationSelect_fp.h" + +#if CC_PolicyDuplicationSelect // Conditional expansion of this file + +/*(See part 3 specification) +// allows qualification of duplication so that it a specific new parent may be +// selected or a new parent selected for a specific object. +*/ +// Return Type: TPM_RC +// TPM_RC_COMMAND_CODE 'commandCode' of 'policySession' is not empty +// TPM_RC_CPHASH 'cpHash' of 'policySession' is not empty +TPM_RC +TPM2_PolicyDuplicationSelect( + PolicyDuplicationSelect_In* in // IN: input parameter list +) +{ + SESSION* session; + HASH_STATE hashState; + TPM_CC commandCode = TPM_CC_PolicyDuplicationSelect; + + // Input Validation + + // Get pointer to the session structure + session = SessionGet(in->policySession); + + // cpHash in session context must be empty + if(session->u1.cpHash.t.size != 0) + return TPM_RC_CPHASH; + + // commandCode in session context must be empty + if(session->commandCode != 0) + return TPM_RC_COMMAND_CODE; + + // Internal Data Update + + // Update name hash + session->u1.cpHash.t.size = CryptHashStart(&hashState, session->authHashAlg); + + // add objectName + CryptDigestUpdate2B(&hashState, &in->objectName.b); + + // add new parent name + CryptDigestUpdate2B(&hashState, &in->newParentName.b); + + // complete hash + CryptHashEnd2B(&hashState, &session->u1.cpHash.b); + + // update policy hash + // Old policyDigest size should be the same as the new policyDigest size since + // they are using the same hash algorithm + session->u2.policyDigest.t.size = + CryptHashStart(&hashState, session->authHashAlg); + // add old policy + CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); + + // add command code + CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); + + // add objectName + if(in->includeObject == YES) + CryptDigestUpdate2B(&hashState, &in->objectName.b); + + // add new parent name + CryptDigestUpdate2B(&hashState, &in->newParentName.b); + + // add includeObject + CryptDigestUpdateInt(&hashState, sizeof(TPMI_YES_NO), in->includeObject); + + // complete digest + CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); + + // set commandCode in session context + session->commandCode = TPM_CC_Duplicate; + + return TPM_RC_SUCCESS; +} + +#endif // CC_PolicyDuplicationSelect \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyGetDigest.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyGetDigest.c new file mode 100644 index 0000000..7e21737 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyGetDigest.c @@ -0,0 +1,60 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "PolicyGetDigest_fp.h" + +#if CC_PolicyGetDigest // Conditional expansion of this file + +/*(See part 3 specification) +// returns the current policyDigest of the session +*/ +TPM_RC +TPM2_PolicyGetDigest(PolicyGetDigest_In* in, // IN: input parameter list + PolicyGetDigest_Out* out // OUT: output parameter list +) +{ + SESSION* session; + + // Command Output + + // Get pointer to the session structure + session = SessionGet(in->policySession); + + out->policyDigest = session->u2.policyDigest; + + return TPM_RC_SUCCESS; +} + +#endif // CC_PolicyGetDigest \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyLocality.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyLocality.c new file mode 100644 index 0000000..1fb0878 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyLocality.c @@ -0,0 +1,136 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "PolicyLocality_fp.h" +#include "Marshal.h" + +#if CC_PolicyLocality // Conditional expansion of this file + +// Return Type: TPM_RC +// TPM_RC_RANGE all the locality values selected by +// 'locality' have been disabled +// by previous TPM2_PolicyLocality() calls. +TPM_RC +TPM2_PolicyLocality(PolicyLocality_In* in // IN: input parameter list +) +{ + SESSION* session; + BYTE marshalBuffer[sizeof(TPMA_LOCALITY)]; + BYTE prevSetting[sizeof(TPMA_LOCALITY)]; + UINT32 marshalSize; + BYTE* buffer; + TPM_CC commandCode = TPM_CC_PolicyLocality; + HASH_STATE hashState; + + // Input Validation + + // Get pointer to the session structure + session = SessionGet(in->policySession); + + // Get new locality setting in canonical form + marshalBuffer[0] = 0; // Code analysis says that this is not initialized + buffer = marshalBuffer; + marshalSize = TPMA_LOCALITY_Marshal(&in->locality, &buffer, NULL); + + // Its an error if the locality parameter is zero + if(marshalBuffer[0] == 0) + return TPM_RCS_RANGE + RC_PolicyLocality_locality; + + // Get existing locality setting in canonical form + prevSetting[0] = 0; // Code analysis says that this is not initialized + buffer = prevSetting; + TPMA_LOCALITY_Marshal(&session->commandLocality, &buffer, NULL); + + // If the locality has previously been set + if(prevSetting[0] != 0 + // then the current locality setting and the requested have to be the same + // type (that is, either both normal or both extended + && ((prevSetting[0] < 32) != (marshalBuffer[0] < 32))) + return TPM_RCS_RANGE + RC_PolicyLocality_locality; + + // See if the input is a regular or extended locality + if(marshalBuffer[0] < 32) + { + // if there was no previous setting, start with all normal localities + // enabled + if(prevSetting[0] == 0) + prevSetting[0] = 0x1F; + + // AND the new setting with the previous setting and store it in prevSetting + prevSetting[0] &= marshalBuffer[0]; + + // The result setting can not be 0 + if(prevSetting[0] == 0) + return TPM_RCS_RANGE + RC_PolicyLocality_locality; + } + else + { + // for extended locality + // if the locality has already been set, then it must match the + if(prevSetting[0] != 0 && prevSetting[0] != marshalBuffer[0]) + return TPM_RCS_RANGE + RC_PolicyLocality_locality; + + // Setting is OK + prevSetting[0] = marshalBuffer[0]; + } + + // Internal Data Update + + // Update policy hash + // policyDigestnew = hash(policyDigestold || TPM_CC_PolicyLocality || locality) + // Start hash + CryptHashStart(&hashState, session->authHashAlg); + + // add old digest + CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); + + // add commandCode + CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); + + // add input locality + CryptDigestUpdate(&hashState, marshalSize, marshalBuffer); + + // complete the digest + CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); + + // update session locality by unmarshal function. The function must succeed + // because both input and existing locality setting have been validated. + buffer = prevSetting; + TPMA_LOCALITY_Unmarshal(&session->commandLocality, &buffer, (INT32*)&marshalSize); + + return TPM_RC_SUCCESS; +} + +#endif // CC_PolicyLocality \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyNV.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyNV.c new file mode 100644 index 0000000..8d8943d --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyNV.c @@ -0,0 +1,140 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "PolicyNV_fp.h" + +#if CC_PolicyNV // Conditional expansion of this file + +# include "Policy_spt_fp.h" + +/*(See part 3 specification) +// Do comparison to NV location +*/ +// Return Type: TPM_RC +// TPM_RC_AUTH_TYPE NV index authorization type is not correct +// TPM_RC_NV_LOCKED NV index read locked +// TPM_RC_NV_UNINITIALIZED the NV index has not been initialized +// TPM_RC_POLICY the comparison to the NV contents failed +// TPM_RC_SIZE the size of 'nvIndex' data starting at 'offset' +// is less than the size of 'operandB' +// TPM_RC_VALUE 'offset' is too large +TPM_RC +TPM2_PolicyNV(PolicyNV_In* in // IN: input parameter list +) +{ + TPM_RC result; + SESSION* session; + NV_REF locator; + NV_INDEX* nvIndex; + BYTE nvBuffer[sizeof(in->operandB.t.buffer)]; + TPM2B_NAME nvName; + TPM_CC commandCode = TPM_CC_PolicyNV; + HASH_STATE hashState; + TPM2B_DIGEST argHash; + + // Input Validation + + // Get pointer to the session structure + session = SessionGet(in->policySession); + + //If this is a trial policy, skip all validations and the operation + if(session->attributes.isTrialPolicy == CLEAR) + { + // No need to access the actual NV index information for a trial policy. + nvIndex = NvGetIndexInfo(in->nvIndex, &locator); + + // Common read access checks. NvReadAccessChecks() may return + // TPM_RC_NV_AUTHORIZATION, TPM_RC_NV_LOCKED, or TPM_RC_NV_UNINITIALIZED + result = NvReadAccessChecks( + in->authHandle, in->nvIndex, nvIndex->publicArea.attributes); + if(result != TPM_RC_SUCCESS) + return result; + + // Make sure that offset is withing range + if(in->offset > nvIndex->publicArea.dataSize) + return TPM_RCS_VALUE + RC_PolicyNV_offset; + + // Valid NV data size should not be smaller than input operandB size + if((nvIndex->publicArea.dataSize - in->offset) < in->operandB.t.size) + return TPM_RCS_SIZE + RC_PolicyNV_operandB; + + // Get NV data. The size of NV data equals the input operand B size + NvGetIndexData(nvIndex, locator, in->offset, in->operandB.t.size, nvBuffer); + + // Check to see if the condition is valid + if(!PolicySptCheckCondition( + in->operation, nvBuffer, in->operandB.t.buffer, in->operandB.t.size)) + return TPM_RC_POLICY; + } + // Internal Data Update + + // Start argument hash + argHash.t.size = CryptHashStart(&hashState, session->authHashAlg); + + // add operandB + CryptDigestUpdate2B(&hashState, &in->operandB.b); + + // add offset + CryptDigestUpdateInt(&hashState, sizeof(UINT16), in->offset); + + // add operation + CryptDigestUpdateInt(&hashState, sizeof(TPM_EO), in->operation); + + // complete argument digest + CryptHashEnd2B(&hashState, &argHash.b); + + // Update policyDigest + // Start digest + CryptHashStart(&hashState, session->authHashAlg); + + // add old digest + CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); + + // add commandCode + CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); + + // add argument digest + CryptDigestUpdate2B(&hashState, &argHash.b); + + // Adding nvName + CryptDigestUpdate2B(&hashState, &EntityGetName(in->nvIndex, &nvName)->b); + + // complete the digest + CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); + + return TPM_RC_SUCCESS; +} + +#endif // CC_PolicyNV \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyNameHash.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyNameHash.c new file mode 100644 index 0000000..ba6cab5 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyNameHash.c @@ -0,0 +1,96 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "PolicyNameHash_fp.h" + +#if CC_PolicyNameHash // Conditional expansion of this file + +/*(See part 3 specification) +// Add a nameHash restriction to the policyDigest +*/ +// Return Type: TPM_RC +// TPM_RC_CPHASH 'nameHash' has been previously set to a different value +// TPM_RC_SIZE 'nameHash' is not the size of the digest produced by the +// hash algorithm associated with 'policySession' +TPM_RC +TPM2_PolicyNameHash(PolicyNameHash_In* in // IN: input parameter list +) +{ + SESSION* session; + TPM_CC commandCode = TPM_CC_PolicyNameHash; + HASH_STATE hashState; + + // Input Validation + + // Get pointer to the session structure + session = SessionGet(in->policySession); + + // A valid nameHash must have the same size as session hash digest + // Since the authHashAlg for a session cannot be TPM_ALG_NULL, the digest size + // is always non-zero. + if(in->nameHash.t.size != CryptHashGetDigestSize(session->authHashAlg)) + return TPM_RCS_SIZE + RC_PolicyNameHash_nameHash; + + // u1 in the policy session context cannot otherwise be occupied + if(session->u1.cpHash.b.size != 0 || session->attributes.isBound + || session->attributes.isCpHashDefined || session->attributes.isTemplateSet) + return TPM_RC_CPHASH; + + // Internal Data Update + + // Update policy hash + // policyDigestnew = hash(policyDigestold || TPM_CC_PolicyNameHash || nameHash) + // Start hash + CryptHashStart(&hashState, session->authHashAlg); + + // add old digest + CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); + + // add commandCode + CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); + + // add nameHash + CryptDigestUpdate2B(&hashState, &in->nameHash.b); + + // complete the digest + CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); + + // update nameHash in session context + session->u1.cpHash = in->nameHash; + + return TPM_RC_SUCCESS; +} + +#endif // CC_PolicyNameHash \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyNvWritten.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyNvWritten.c new file mode 100644 index 0000000..17e01ab --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyNvWritten.c @@ -0,0 +1,93 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "PolicyNvWritten_fp.h" + +#if CC_PolicyNvWritten // Conditional expansion of this file + +// Make an NV Index policy dependent on the state of the TPMA_NV_WRITTEN +// attribute of the index. +// Return Type: TPM_RC +// TPM_RC_VALUE a conflicting request for the attribute has +// already been processed +TPM_RC +TPM2_PolicyNvWritten(PolicyNvWritten_In* in // IN: input parameter list +) +{ + SESSION* session; + TPM_CC commandCode = TPM_CC_PolicyNvWritten; + HASH_STATE hashState; + + // Input Validation + + // Get pointer to the session structure + session = SessionGet(in->policySession); + + // If already set is this a duplicate (the same setting)? If it + // is a conflicting setting, it is an error + if(session->attributes.checkNvWritten == SET) + { + if(((session->attributes.nvWrittenState == SET) != (in->writtenSet == YES))) + return TPM_RCS_VALUE + RC_PolicyNvWritten_writtenSet; + } + + // Internal Data Update + + // Set session attributes so that the NV Index needs to be checked + session->attributes.checkNvWritten = SET; + session->attributes.nvWrittenState = (in->writtenSet == YES); + + // Update policy hash + // policyDigestnew = hash(policyDigestold || TPM_CC_PolicyNvWritten + // || writtenSet) + // Start hash + CryptHashStart(&hashState, session->authHashAlg); + + // add old digest + CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); + + // add commandCode + CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); + + // add the byte of writtenState + CryptDigestUpdateInt(&hashState, sizeof(TPMI_YES_NO), in->writtenSet); + + // complete the digest + CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); + + return TPM_RC_SUCCESS; +} + +#endif // CC_PolicyNvWritten \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyOR.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyOR.c new file mode 100644 index 0000000..26ee1f0 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyOR.c @@ -0,0 +1,99 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "PolicyOR_fp.h" + +#if CC_PolicyOR // Conditional expansion of this file + +# include "Policy_spt_fp.h" + +/*(See part 3 specification) +// PolicyOR command +*/ +// Return Type: TPM_RC +// TPM_RC_VALUE no digest in 'pHashList' matched the current +// value of policyDigest for 'policySession' +TPM_RC +TPM2_PolicyOR(PolicyOR_In* in // IN: input parameter list +) +{ + SESSION* session; + UINT32 i; + + // Input Validation and Update + + // Get pointer to the session structure + session = SessionGet(in->policySession); + + // Compare and Update Internal Session policy if match + for(i = 0; i < in->pHashList.count; i++) + { + if(session->attributes.isTrialPolicy == SET + || (MemoryEqual2B(&session->u2.policyDigest.b, + &in->pHashList.digests[i].b))) + { + // Found a match + HASH_STATE hashState; + TPM_CC commandCode = TPM_CC_PolicyOR; + + // Start hash + session->u2.policyDigest.t.size = + CryptHashStart(&hashState, session->authHashAlg); + // Set policyDigest to 0 string and add it to hash + MemorySet(session->u2.policyDigest.t.buffer, + 0, + session->u2.policyDigest.t.size); + CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); + + // add command code + CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); + + // Add each of the hashes in the list + for(i = 0; i < in->pHashList.count; i++) + { + // Extend policyDigest + CryptDigestUpdate2B(&hashState, &in->pHashList.digests[i].b); + } + // Complete digest + CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); + + return TPM_RC_SUCCESS; + } + } + // None of the values in the list matched the current policyDigest + return TPM_RCS_VALUE + RC_PolicyOR_pHashList; +} + +#endif // CC_PolicyOR \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyPCR.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyPCR.c new file mode 100644 index 0000000..444b830 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyPCR.c @@ -0,0 +1,126 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" + +#if CC_PolicyPCR // Conditional expansion of this file + +# include "PolicyPCR_fp.h" +# include "Marshal.h" + +/*(See part 3 specification) +// Add a PCR gate for a policy session +*/ +// Return Type: TPM_RC +// TPM_RC_VALUE if provided, 'pcrDigest' does not match the +// current PCR settings +// TPM_RC_PCR_CHANGED a previous TPM2_PolicyPCR() set +// pcrCounter and it has changed +TPM_RC +TPM2_PolicyPCR(PolicyPCR_In* in // IN: input parameter list +) +{ + SESSION* session; + TPM2B_DIGEST pcrDigest; + BYTE pcrs[sizeof(TPML_PCR_SELECTION)]; + UINT32 pcrSize; + BYTE* buffer; + TPM_CC commandCode = TPM_CC_PolicyPCR; + HASH_STATE hashState; + + // Input Validation + + // Get pointer to the session structure + session = SessionGet(in->policySession); + + // Compute current PCR digest + PCRComputeCurrentDigest(session->authHashAlg, &in->pcrs, &pcrDigest); + + // Do validation for non trial session + if(session->attributes.isTrialPolicy == CLEAR) + { + // Make sure that this is not going to invalidate a previous PCR check + if(session->pcrCounter != 0 && session->pcrCounter != gr.pcrCounter) + return TPM_RC_PCR_CHANGED; + + // If the caller specified the PCR digest and it does not + // match the current PCR settings, return an error.. + if(in->pcrDigest.t.size != 0) + { + if(!MemoryEqual2B(&in->pcrDigest.b, &pcrDigest.b)) + return TPM_RCS_VALUE + RC_PolicyPCR_pcrDigest; + } + } + else + { + // For trial session, just use the input PCR digest if one provided + // Note: It can't be too big because it is a TPM2B_DIGEST and the size + // would have been checked during unmarshaling + if(in->pcrDigest.t.size != 0) + pcrDigest = in->pcrDigest; + } + // Internal Data Update + // Update policy hash + // policyDigestnew = hash( policyDigestold || TPM_CC_PolicyPCR + // || PCRS || pcrDigest) + // Start hash + CryptHashStart(&hashState, session->authHashAlg); + + // add old digest + CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); + + // add commandCode + CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); + + // add PCRS + buffer = pcrs; + pcrSize = TPML_PCR_SELECTION_Marshal(&in->pcrs, &buffer, NULL); + CryptDigestUpdate(&hashState, pcrSize, pcrs); + + // add PCR digest + CryptDigestUpdate2B(&hashState, &pcrDigest.b); + + // complete the hash and get the results + CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); + + // update pcrCounter in session context for non trial session + if(session->attributes.isTrialPolicy == CLEAR) + { + session->pcrCounter = gr.pcrCounter; + } + + return TPM_RC_SUCCESS; +} + +#endif // CC_PolicyPCR \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyPassword.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyPassword.c new file mode 100644 index 0000000..9f9baa6 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyPassword.c @@ -0,0 +1,80 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "PolicyPassword_fp.h" + +#if CC_PolicyPassword // Conditional expansion of this file + +# include "Policy_spt_fp.h" + +/*(See part 3 specification) +// allows a policy to be bound to the authorization value of the authorized +// object +*/ +TPM_RC +TPM2_PolicyPassword(PolicyPassword_In* in // IN: input parameter list +) +{ + SESSION* session; + TPM_CC commandCode = TPM_CC_PolicyAuthValue; + HASH_STATE hashState; + + // Internal Data Update + + // Get pointer to the session structure + session = SessionGet(in->policySession); + + // Update policy hash + // policyDigestnew = hash(policyDigestold || TPM_CC_PolicyAuthValue) + // Start hash + CryptHashStart(&hashState, session->authHashAlg); + + // add old digest + CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); + + // add commandCode + CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); + + // complete the digest + CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); + + // Update isPasswordNeeded bit + session->attributes.isPasswordNeeded = SET; + session->attributes.isAuthValueNeeded = CLEAR; + + return TPM_RC_SUCCESS; +} + +#endif // CC_PolicyPassword \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyPhysicalPresence.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyPhysicalPresence.c new file mode 100644 index 0000000..6a2aa8a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyPhysicalPresence.c @@ -0,0 +1,77 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "PolicyPhysicalPresence_fp.h" + +#if CC_PolicyPhysicalPresence // Conditional expansion of this file + +/*(See part 3 specification) +// indicate that physical presence will need to be asserted at the time the +// authorization is performed +*/ +TPM_RC +TPM2_PolicyPhysicalPresence(PolicyPhysicalPresence_In* in // IN: input parameter list +) +{ + SESSION* session; + TPM_CC commandCode = TPM_CC_PolicyPhysicalPresence; + HASH_STATE hashState; + + // Internal Data Update + + // Get pointer to the session structure + session = SessionGet(in->policySession); + + // Update policy hash + // policyDigestnew = hash(policyDigestold || TPM_CC_PolicyPhysicalPresence) + // Start hash + CryptHashStart(&hashState, session->authHashAlg); + + // add old digest + CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); + + // add commandCode + CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); + + // complete the digest + CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); + + // update session attribute + session->attributes.isPPRequired = SET; + + return TPM_RC_SUCCESS; +} + +#endif // CC_PolicyPhysicalPresence \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicySecret.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicySecret.c new file mode 100644 index 0000000..3294d04 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicySecret.c @@ -0,0 +1,136 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "PolicySecret_fp.h" + +#if CC_PolicySecret // Conditional expansion of this file + +# include "Policy_spt_fp.h" +# include "NV_spt_fp.h" + +/*(See part 3 specification) +// Add a secret-based authorization to the policy evaluation +*/ +// Return Type: TPM_RC +// TPM_RC_CPHASH cpHash for policy was previously set to a +// value that is not the same as 'cpHashA' +// TPM_RC_EXPIRED 'expiration' indicates a time in the past +// TPM_RC_NONCE 'nonceTPM' does not match the nonce associated +// with 'policySession' +// TPM_RC_SIZE 'cpHashA' is not the size of a digest for the +// hash associated with 'policySession' +TPM_RC +TPM2_PolicySecret(PolicySecret_In* in, // IN: input parameter list + PolicySecret_Out* out // OUT: output parameter list +) +{ + TPM_RC result; + SESSION* session; + TPM2B_NAME entityName; + UINT64 authTimeout = 0; + // Input Validation + // Get pointer to the session structure + session = SessionGet(in->policySession); + + //Only do input validation if this is not a trial policy session + if(session->attributes.isTrialPolicy == CLEAR) + { + authTimeout = ComputeAuthTimeout(session, in->expiration, &in->nonceTPM); + + result = PolicyParameterChecks(session, + authTimeout, + &in->cpHashA, + &in->nonceTPM, + RC_PolicySecret_nonceTPM, + RC_PolicySecret_cpHashA, + RC_PolicySecret_expiration); + if(result != TPM_RC_SUCCESS) + return result; + } + // Internal Data Update + // Update policy context with input policyRef and name of authorizing key + // This value is computed even for trial sessions. Possibly update the cpHash + PolicyContextUpdate(TPM_CC_PolicySecret, + EntityGetName(in->authHandle, &entityName), + &in->policyRef, + &in->cpHashA, + authTimeout, + session); + // Command Output + // Create ticket and timeout buffer if in->expiration < 0 and this is not + // a trial session. + // NOTE: PolicyParameterChecks() makes sure that nonceTPM is present + // when expiration is non-zero. + if(in->expiration < 0 && session->attributes.isTrialPolicy == CLEAR + && !NvIsPinPassIndex(in->authHandle)) + { + BOOL expiresOnReset = (in->nonceTPM.t.size == 0); + // Compute policy ticket + authTimeout &= ~EXPIRATION_BIT; + TicketComputeAuth(TPM_ST_AUTH_SECRET, + EntityGetHierarchy(in->authHandle), + authTimeout, + expiresOnReset, + &in->cpHashA, + &in->policyRef, + &entityName, + &out->policyTicket); + // Generate timeout buffer. The format of output timeout buffer is + // TPM-specific. + // Note: In this implementation, the timeout buffer value is computed after + // the ticket is produced so, when the ticket is checked, the expiration + // flag needs to be extracted before the ticket is checked. + out->timeout.t.size = sizeof(authTimeout); + // In the Windows compatible version, the least-significant bit of the + // timeout value is used as a flag to indicate if the authorization expires + // on reset. The flag is the MSb. + if(expiresOnReset) + authTimeout |= EXPIRATION_BIT; + UINT64_TO_BYTE_ARRAY(authTimeout, out->timeout.t.buffer); + } + else + { + // timeout buffer is null + out->timeout.t.size = 0; + + // authorization ticket is null + out->policyTicket.tag = TPM_ST_AUTH_SECRET; + out->policyTicket.hierarchy = TPM_RH_NULL; + out->policyTicket.digest.t.size = 0; + } + return TPM_RC_SUCCESS; +} + +#endif // CC_PolicySecret \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicySigned.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicySigned.c new file mode 100644 index 0000000..d4c3023 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicySigned.c @@ -0,0 +1,186 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "Policy_spt_fp.h" +#include "PolicySigned_fp.h" + +#if CC_PolicySigned // Conditional expansion of this file + +/*(See part 3 specification) +// Include an asymmetrically signed authorization to the policy evaluation +*/ +// Return Type: TPM_RC +// TPM_RC_CPHASH cpHash was previously set to a different value +// TPM_RC_EXPIRED 'expiration' indicates a time in the past or +// 'expiration' is non-zero but no nonceTPM is present +// TPM_RC_NONCE 'nonceTPM' is not the nonce associated with the +// 'policySession' +// TPM_RC_SCHEME the signing scheme of 'auth' is not supported by the +// TPM +// TPM_RC_SIGNATURE the signature is not genuine +// TPM_RC_SIZE input cpHash has wrong size +TPM_RC +TPM2_PolicySigned(PolicySigned_In* in, // IN: input parameter list + PolicySigned_Out* out // OUT: output parameter list +) +{ + TPM_RC result = TPM_RC_SUCCESS; + SESSION* session; + TPM2B_NAME entityName; + TPM2B_DIGEST authHash; + HASH_STATE hashState; + UINT64 authTimeout = 0; + // Input Validation + // Set up local pointers + session = SessionGet(in->policySession); // the session structure + + // Only do input validation if this is not a trial policy session + if(session->attributes.isTrialPolicy == CLEAR) + { + authTimeout = ComputeAuthTimeout(session, in->expiration, &in->nonceTPM); + + result = PolicyParameterChecks(session, + authTimeout, + &in->cpHashA, + &in->nonceTPM, + RC_PolicySigned_nonceTPM, + RC_PolicySigned_cpHashA, + RC_PolicySigned_expiration); + if(result != TPM_RC_SUCCESS) + return result; + // Re-compute the digest being signed + /*(See part 3 specification) + // The digest is computed as: + // aHash := hash ( nonceTPM | expiration | cpHashA | policyRef) + // where: + // hash() the hash associated with the signed authorization + // nonceTPM the nonceTPM value from the TPM2_StartAuthSession . + // response If the authorization is not limited to this + // session, the size of this value is zero. + // expiration time limit on authorization set by authorizing object. + // This 32-bit value is set to zero if the expiration + // time is not being set. + // cpHashA hash of the command parameters for the command being + // approved using the hash algorithm of the PSAP session. + // Set to NULLauth if the authorization is not limited + // to a specific command. + // policyRef hash of an opaque value determined by the authorizing + // object. Set to the NULLdigest if no hash is present. + */ + // Start hash + authHash.t.size = CryptHashStart(&hashState, CryptGetSignHashAlg(&in->auth)); + // If there is no digest size, then we don't have a verification function + // for this algorithm (e.g. TPM_ALG_ECDAA) so indicate that it is a + // bad scheme. + if(authHash.t.size == 0) + return TPM_RCS_SCHEME + RC_PolicySigned_auth; + + // nonceTPM + CryptDigestUpdate2B(&hashState, &in->nonceTPM.b); + + // expiration + CryptDigestUpdateInt(&hashState, sizeof(UINT32), in->expiration); + + // cpHashA + CryptDigestUpdate2B(&hashState, &in->cpHashA.b); + + // policyRef + CryptDigestUpdate2B(&hashState, &in->policyRef.b); + + // Complete digest + CryptHashEnd2B(&hashState, &authHash.b); + + // Validate Signature. A TPM_RC_SCHEME, TPM_RC_HANDLE or TPM_RC_SIGNATURE + // error may be returned at this point + result = CryptValidateSignature(in->authObject, &authHash, &in->auth); + if(result != TPM_RC_SUCCESS) + return RcSafeAddToResult(result, RC_PolicySigned_auth); + } + // Internal Data Update + // Update policy with input policyRef and name of authorization key + // These values are updated even if the session is a trial session + PolicyContextUpdate(TPM_CC_PolicySigned, + EntityGetName(in->authObject, &entityName), + &in->policyRef, + &in->cpHashA, + authTimeout, + session); + // Command Output + // Create ticket and timeout buffer if in->expiration < 0 and this is not + // a trial session. + // NOTE: PolicyParameterChecks() makes sure that nonceTPM is present + // when expiration is non-zero. + if(in->expiration < 0 && session->attributes.isTrialPolicy == CLEAR) + { + BOOL expiresOnReset = (in->nonceTPM.t.size == 0); + // Compute policy ticket + authTimeout &= ~EXPIRATION_BIT; + + TicketComputeAuth(TPM_ST_AUTH_SIGNED, + EntityGetHierarchy(in->authObject), + authTimeout, + expiresOnReset, + &in->cpHashA, + &in->policyRef, + &entityName, + &out->policyTicket); + // Generate timeout buffer. The format of output timeout buffer is + // TPM-specific. + // Note: In this implementation, the timeout buffer value is computed after + // the ticket is produced so, when the ticket is checked, the expiration + // flag needs to be extracted before the ticket is checked. + // In the Windows compatible version, the least-significant bit of the + // timeout value is used as a flag to indicate if the authorization expires + // on reset. The flag is the MSb. + out->timeout.t.size = sizeof(authTimeout); + if(expiresOnReset) + authTimeout |= EXPIRATION_BIT; + UINT64_TO_BYTE_ARRAY(authTimeout, out->timeout.t.buffer); + } + else + { + // Generate a null ticket. + // timeout buffer is null + out->timeout.t.size = 0; + + // authorization ticket is null + out->policyTicket.tag = TPM_ST_AUTH_SIGNED; + out->policyTicket.hierarchy = TPM_RH_NULL; + out->policyTicket.digest.t.size = 0; + } + return TPM_RC_SUCCESS; +} + +#endif // CC_PolicySigned \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyTemplate.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyTemplate.c new file mode 100644 index 0000000..f5d4466 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyTemplate.c @@ -0,0 +1,102 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "PolicyTemplate_fp.h" + +#if CC_PolicyTemplate // Conditional expansion of this file + +/*(See part 3 specification) +// Add a cpHash restriction to the policyDigest +*/ +// Return Type: TPM_RC +// TPM_RC_CPHASH cpHash of 'policySession' has previously been set +// to a different value +// TPM_RC_SIZE 'templateHash' is not the size of a digest produced +// by the hash algorithm associated with +// 'policySession' +TPM_RC +TPM2_PolicyTemplate(PolicyTemplate_In* in // IN: input parameter list +) +{ + SESSION* session; + TPM_CC commandCode = TPM_CC_PolicyTemplate; + HASH_STATE hashState; + + // Input Validation + + // Get pointer to the session structure + session = SessionGet(in->policySession); + + // If the template is set, make sure that it is the same as the input value + if(session->attributes.isTemplateSet) + { + if(!MemoryEqual2B(&in->templateHash.b, &session->u1.cpHash.b)) + return TPM_RCS_VALUE + RC_PolicyTemplate_templateHash; + } + // error if cpHash contains something that is not a template + else if(session->u1.templateHash.t.size != 0) + return TPM_RC_CPHASH; + + // A valid templateHash must have the same size as session hash digest + if(in->templateHash.t.size != CryptHashGetDigestSize(session->authHashAlg)) + return TPM_RCS_SIZE + RC_PolicyTemplate_templateHash; + + // Internal Data Update + // Update policy hash + // policyDigestnew = hash(policyDigestold || TPM_CC_PolicyCpHash + // || cpHashA.buffer) + // Start hash + CryptHashStart(&hashState, session->authHashAlg); + + // add old digest + CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); + + // add commandCode + CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); + + // add cpHashA + CryptDigestUpdate2B(&hashState, &in->templateHash.b); + + // complete the digest and get the results + CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); + + // update cpHash in session context + session->u1.templateHash = in->templateHash; + session->attributes.isTemplateSet = SET; + + return TPM_RC_SUCCESS; +} + +#endif // CC_PolicyTemplateHash \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyTicket.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyTicket.c new file mode 100644 index 0000000..c3b9ae2 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/PolicyTicket.c @@ -0,0 +1,137 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "PolicyTicket_fp.h" + +#if CC_PolicyTicket // Conditional expansion of this file + +# include "Policy_spt_fp.h" + +/*(See part 3 specification) +// Include ticket to the policy evaluation +*/ +// Return Type: TPM_RC +// TPM_RC_CPHASH policy's cpHash was previously set to a different +// value +// TPM_RC_EXPIRED 'timeout' value in the ticket is in the past and the +// ticket has expired +// TPM_RC_SIZE 'timeout' or 'cpHash' has invalid size for the +// TPM_RC_TICKET 'ticket' is not valid +TPM_RC +TPM2_PolicyTicket(PolicyTicket_In* in // IN: input parameter list +) +{ + TPM_RC result; + SESSION* session; + UINT64 authTimeout; + TPMT_TK_AUTH ticketToCompare; + TPM_CC commandCode = TPM_CC_PolicySecret; + BOOL expiresOnReset; + + // Input Validation + + // Get pointer to the session structure + session = SessionGet(in->policySession); + + // NOTE: A trial policy session is not allowed to use this command. + // A ticket is used in place of a previously given authorization. Since + // a trial policy doesn't actually authenticate, the validated + // ticket is not necessary and, in place of using a ticket, one + // should use the intended authorization for which the ticket + // would be a substitute. + if(session->attributes.isTrialPolicy) + return TPM_RCS_ATTRIBUTES + RC_PolicyTicket_policySession; + // Restore timeout data. The format of timeout buffer is TPM-specific. + // In this implementation, the most significant bit of the timeout value is + // used as the flag to indicate that the ticket expires on TPM Reset or + // TPM Restart. The flag has to be removed before the parameters and ticket + // are checked. + if(in->timeout.t.size != sizeof(UINT64)) + return TPM_RCS_SIZE + RC_PolicyTicket_timeout; + authTimeout = BYTE_ARRAY_TO_UINT64(in->timeout.t.buffer); + + // extract the flag + expiresOnReset = (authTimeout & EXPIRATION_BIT) != 0; + authTimeout &= ~EXPIRATION_BIT; + + // Do the normal checks on the cpHashA and timeout values + result = PolicyParameterChecks(session, + authTimeout, + &in->cpHashA, + NULL, // no nonce + 0, // no bad nonce return + RC_PolicyTicket_cpHashA, + RC_PolicyTicket_timeout); + if(result != TPM_RC_SUCCESS) + return result; + // Validate Ticket + // Re-generate policy ticket by input parameters + TicketComputeAuth(in->ticket.tag, + in->ticket.hierarchy, + authTimeout, + expiresOnReset, + &in->cpHashA, + &in->policyRef, + &in->authName, + &ticketToCompare); + // Compare generated digest with input ticket digest + if(!MemoryEqual2B(&in->ticket.digest.b, &ticketToCompare.digest.b)) + return TPM_RCS_TICKET + RC_PolicyTicket_ticket; + + // Internal Data Update + + // Is this ticket to take the place of a TPM2_PolicySigned() or + // a TPM2_PolicySecret()? + if(in->ticket.tag == TPM_ST_AUTH_SIGNED) + commandCode = TPM_CC_PolicySigned; + else if(in->ticket.tag == TPM_ST_AUTH_SECRET) + commandCode = TPM_CC_PolicySecret; + else + // There could only be two possible tag values. Any other value should + // be caught by the ticket validation process. + FAIL(FATAL_ERROR_INTERNAL); + + // Update policy context + PolicyContextUpdate(commandCode, + &in->authName, + &in->policyRef, + &in->cpHashA, + authTimeout, + session); + + return TPM_RC_SUCCESS; +} + +#endif // CC_PolicyTicket \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/Policy_spt.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/Policy_spt.c new file mode 100644 index 0000000..e6378d3 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/EA/Policy_spt.c @@ -0,0 +1,276 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Includes +#include "Tpm.h" +#include "Policy_spt_fp.h" +#include "PolicySigned_fp.h" +#include "PolicySecret_fp.h" +#include "PolicyTicket_fp.h" + +//** Functions +//*** PolicyParameterChecks() +// This function validates the common parameters of TPM2_PolicySiged() +// and TPM2_PolicySecret(). The common parameters are 'nonceTPM', +// 'expiration', and 'cpHashA'. +TPM_RC +PolicyParameterChecks(SESSION* session, + UINT64 authTimeout, + TPM2B_DIGEST* cpHashA, + TPM2B_NONCE* nonce, + TPM_RC blameNonce, + TPM_RC blameCpHash, + TPM_RC blameExpiration) +{ + // Validate that input nonceTPM is correct if present + if(nonce != NULL && nonce->t.size != 0) + { + if(!MemoryEqual2B(&nonce->b, &session->nonceTPM.b)) + return TPM_RCS_NONCE + blameNonce; + } + // If authTimeout is set (expiration != 0... + if(authTimeout != 0) + { + // Validate input expiration. + // Cannot compare time if clock stop advancing. A TPM_RC_NV_UNAVAILABLE + // or TPM_RC_NV_RATE error may be returned here. + RETURN_IF_NV_IS_NOT_AVAILABLE; + + // if the time has already passed or the time epoch has changed then the + // time value is no longer good. + if((authTimeout < g_time) || (session->epoch != g_timeEpoch)) + return TPM_RCS_EXPIRED + blameExpiration; + } + // If the cpHash is present, then check it + if(cpHashA != NULL && cpHashA->t.size != 0) + { + // The cpHash input has to have the correct size + if(cpHashA->t.size != session->u2.policyDigest.t.size) + return TPM_RCS_SIZE + blameCpHash; + + // If the cpHash has already been set, then this input value + // must match the current value. + if(session->u1.cpHash.b.size != 0 + && !MemoryEqual2B(&cpHashA->b, &session->u1.cpHash.b)) + return TPM_RC_CPHASH; + } + return TPM_RC_SUCCESS; +} + +//*** PolicyContextUpdate() +// Update policy hash +// Update the policyDigest in policy session by extending policyRef and +// objectName to it. This will also update the cpHash if it is present. +// +// Return Type: void +void PolicyContextUpdate( + TPM_CC commandCode, // IN: command code + TPM2B_NAME* name, // IN: name of entity + TPM2B_NONCE* ref, // IN: the reference data + TPM2B_DIGEST* cpHash, // IN: the cpHash (optional) + UINT64 policyTimeout, // IN: the timeout value for the policy + SESSION* session // IN/OUT: policy session to be updated +) +{ + HASH_STATE hashState; + + // Start hash + CryptHashStart(&hashState, session->authHashAlg); + + // policyDigest size should always be the digest size of session hash algorithm. + pAssert(session->u2.policyDigest.t.size + == CryptHashGetDigestSize(session->authHashAlg)); + + // add old digest + CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); + + // add commandCode + CryptDigestUpdateInt(&hashState, sizeof(commandCode), commandCode); + + // add name if applicable + if(name != NULL) + CryptDigestUpdate2B(&hashState, &name->b); + + // Complete the digest and get the results + CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); + + // If the policy reference is not null, do a second update to the digest. + if(ref != NULL) + { + + // Start second hash computation + CryptHashStart(&hashState, session->authHashAlg); + + // add policyDigest + CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); + + // add policyRef + CryptDigestUpdate2B(&hashState, &ref->b); + + // Complete second digest + CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); + } + // Deal with the cpHash. If the cpHash value is present + // then it would have already been checked to make sure that + // it is compatible with the current value so all we need + // to do here is copy it and set the isCpHashDefined attribute + if(cpHash != NULL && cpHash->t.size != 0) + { + session->u1.cpHash = *cpHash; + session->attributes.isCpHashDefined = SET; + } + + // update the timeout if it is specified + if(policyTimeout != 0) + { + // If the timeout has not been set, then set it to the new value + // than the current timeout then set it to the new value + if(session->timeout == 0 || session->timeout > policyTimeout) + session->timeout = policyTimeout; + } + return; +} +//*** ComputeAuthTimeout() +// This function is used to determine what the authorization timeout value for +// the session should be. +UINT64 +ComputeAuthTimeout(SESSION* session, // IN: the session containing the time + // values + INT32 expiration, // IN: either the number of seconds from + // the start of the session or the + // time in g_timer; + TPM2B_NONCE* nonce // IN: indicator of the time base +) +{ + UINT64 policyTime; + // If no expiration, policy time is 0 + if(expiration == 0) + policyTime = 0; + else + { + if(expiration < 0) + expiration = -expiration; + if(nonce->t.size == 0) + // The input time is absolute Time (not Clock), but it is expressed + // in seconds. To make sure that we don't time out too early, take the + // current value of milliseconds in g_time and add that to the input + // seconds value. + policyTime = (((UINT64)expiration) * 1000) + g_time % 1000; + else + // The policy timeout is the absolute value of the expiration in seconds + // added to the start time of the policy. + policyTime = session->startTime + (((UINT64)expiration) * 1000); + } + return policyTime; +} + +//*** PolicyDigestClear() +// Function to reset the policyDigest of a session +void PolicyDigestClear(SESSION* session) +{ + session->u2.policyDigest.t.size = CryptHashGetDigestSize(session->authHashAlg); + MemorySet(session->u2.policyDigest.t.buffer, 0, session->u2.policyDigest.t.size); +} + +//*** PolicySptCheckCondition() +// Checks to see if the condition in the policy is satisfied. +BOOL PolicySptCheckCondition(TPM_EO operation, BYTE* opA, BYTE* opB, UINT16 size) +{ + // Arithmetic Comparison + switch(operation) + { + case TPM_EO_EQ: + // compare A = B + return (UnsignedCompareB(size, opA, size, opB) == 0); + break; + case TPM_EO_NEQ: + // compare A != B + return (UnsignedCompareB(size, opA, size, opB) != 0); + break; + case TPM_EO_SIGNED_GT: + // compare A > B signed + return (SignedCompareB(size, opA, size, opB) > 0); + break; + case TPM_EO_UNSIGNED_GT: + // compare A > B unsigned + return (UnsignedCompareB(size, opA, size, opB) > 0); + break; + case TPM_EO_SIGNED_LT: + // compare A < B signed + return (SignedCompareB(size, opA, size, opB) < 0); + break; + case TPM_EO_UNSIGNED_LT: + // compare A < B unsigned + return (UnsignedCompareB(size, opA, size, opB) < 0); + break; + case TPM_EO_SIGNED_GE: + // compare A >= B signed + return (SignedCompareB(size, opA, size, opB) >= 0); + break; + case TPM_EO_UNSIGNED_GE: + // compare A >= B unsigned + return (UnsignedCompareB(size, opA, size, opB) >= 0); + break; + case TPM_EO_SIGNED_LE: + // compare A <= B signed + return (SignedCompareB(size, opA, size, opB) <= 0); + break; + case TPM_EO_UNSIGNED_LE: + // compare A <= B unsigned + return (UnsignedCompareB(size, opA, size, opB) <= 0); + break; + case TPM_EO_BITSET: + // All bits SET in B are SET in A. ((A&B)=B) + { + UINT32 i; + for(i = 0; i < size; i++) + if((opA[i] & opB[i]) != opB[i]) + return FALSE; + } + break; + case TPM_EO_BITCLEAR: + // All bits SET in B are CLEAR in A. ((A&B)=0) + { + UINT32 i; + for(i = 0; i < size; i++) + if((opA[i] & opB[i]) != 0) + return FALSE; + } + break; + default: + FAIL(FATAL_ERROR_INTERNAL); + break; + } + return TRUE; +} diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Ecdaa/Commit.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Ecdaa/Commit.c new file mode 100644 index 0000000..dbbd240 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Ecdaa/Commit.c @@ -0,0 +1,168 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "Commit_fp.h" + +#if CC_Commit // Conditional expansion of this file + +/*(See part 3 specification) +// This command performs the point multiply operations for anonymous signing +// scheme. +*/ +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES 'keyHandle' references a restricted key that is not a +// signing key +// TPM_RC_ECC_POINT either 'P1' or the point derived from 's2' is not on +// the curve of 'keyHandle' +// TPM_RC_HASH invalid name algorithm in 'keyHandle' +// TPM_RC_KEY 'keyHandle' does not reference an ECC key +// TPM_RC_SCHEME the scheme of 'keyHandle' is not an anonymous scheme +// TPM_RC_NO_RESULT 'K', 'L' or 'E' was a point at infinity; or +// failed to generate "r" value +// TPM_RC_SIZE 's2' is empty but 'y2' is not or 's2' provided but +// 'y2' is not +TPM_RC +TPM2_Commit(Commit_In* in, // IN: input parameter list + Commit_Out* out // OUT: output parameter list +) +{ + OBJECT* eccKey; + TPMS_ECC_POINT P2; + TPMS_ECC_POINT* pP2 = NULL; + TPMS_ECC_POINT* pP1 = NULL; + TPM2B_ECC_PARAMETER r; + TPM2B_ECC_PARAMETER p; + TPM_RC result; + TPMS_ECC_PARMS* parms; + + // Input Validation + + eccKey = HandleToObject(in->signHandle); + parms = &eccKey->publicArea.parameters.eccDetail; + + // Input key must be an ECC key + if(eccKey->publicArea.type != TPM_ALG_ECC) + return TPM_RCS_KEY + RC_Commit_signHandle; + + // This command may only be used with a sign-only key using an anonymous + // scheme. + // NOTE: a sign + decrypt key has no scheme so it will not be an anonymous one + // and an unrestricted sign key might no have a signing scheme but it can't + // be use in Commit() + if(!CryptIsSchemeAnonymous(parms->scheme.scheme)) + return TPM_RCS_SCHEME + RC_Commit_signHandle; + + // Make sure that both parts of P2 are present if either is present + if((in->s2.t.size == 0) != (in->y2.t.size == 0)) + return TPM_RCS_SIZE + RC_Commit_y2; + + // Get prime modulus for the curve. This is needed later but getting this now + // allows confirmation that the curve exists. + if(!CryptEccGetParameter(&p, 'p', parms->curveID)) + return TPM_RCS_KEY + RC_Commit_signHandle; + + // Get the random value that will be used in the point multiplications + // Note: this does not commit the count. + if(!CryptGenerateR(&r, NULL, parms->curveID, &eccKey->name)) + return TPM_RC_NO_RESULT; + + // Set up P2 if s2 and Y2 are provided + if(in->s2.t.size != 0) + { + TPM2B_DIGEST x2; + + pP2 = &P2; + + // copy y2 for P2 + P2.y = in->y2; + + // Compute x2 HnameAlg(s2) mod p + // do the hash operation on s2 with the size of curve 'p' + x2.t.size = CryptHashBlock(eccKey->publicArea.nameAlg, + in->s2.t.size, + in->s2.t.buffer, + sizeof(x2.t.buffer), + x2.t.buffer); + + // If there were error returns in the hash routine, indicate a problem + // with the hash algorithm selection + if(x2.t.size == 0) + return TPM_RCS_HASH + RC_Commit_signHandle; + // The size of the remainder will be same as the size of p. DivideB() will + // pad the results (leading zeros) if necessary to make the size the same + P2.x.t.size = p.t.size; + // set p2.x = hash(s2) mod p + if(DivideB(&x2.b, &p.b, NULL, &P2.x.b) != TPM_RC_SUCCESS) + return TPM_RC_NO_RESULT; + + if(!CryptEccIsPointOnCurve(parms->curveID, pP2)) + return TPM_RCS_ECC_POINT + RC_Commit_s2; + + if(eccKey->attributes.publicOnly == SET) + return TPM_RCS_KEY + RC_Commit_signHandle; + } + // If there is a P1, make sure that it is on the curve + // NOTE: an "empty" point has two UINT16 values which are the size values + // for each of the coordinates. + if(in->P1.size > 4) + { + pP1 = &in->P1.point; + if(!CryptEccIsPointOnCurve(parms->curveID, pP1)) + return TPM_RCS_ECC_POINT + RC_Commit_P1; + } + + // Pass the parameters to CryptCommit. + // The work is not done in-line because it does several point multiplies + // with the same curve. It saves work by not having to reload the curve + // parameters multiple times. + result = CryptEccCommitCompute(&out->K.point, + &out->L.point, + &out->E.point, + parms->curveID, + pP1, + pP2, + &eccKey->sensitive.sensitive.ecc, + &r); + if(result != TPM_RC_SUCCESS) + return result; + + // The commit computation was successful so complete the commit by setting + // the bit + out->counter = CryptCommit(); + + return TPM_RC_SUCCESS; +} + +#endif // CC_Commit \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/FieldUpgrade/FieldUpgradeData.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/FieldUpgrade/FieldUpgradeData.c new file mode 100644 index 0000000..16a2e44 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/FieldUpgrade/FieldUpgradeData.c @@ -0,0 +1,52 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "FieldUpgradeData_fp.h" +#if CC_FieldUpgradeData // Conditional expansion of this file + +/*(See part 3 specification) +// FieldUpgradeData +*/ +TPM_RC +TPM2_FieldUpgradeData(FieldUpgradeData_In* in, // IN: input parameter list + FieldUpgradeData_Out* out // OUT: output parameter list +) +{ + // Not implemented + UNUSED_PARAMETER(in); + UNUSED_PARAMETER(out); + return TPM_RC_SUCCESS; +} +#endif \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/FieldUpgrade/FieldUpgradeStart.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/FieldUpgrade/FieldUpgradeStart.c new file mode 100644 index 0000000..6e8b1c6 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/FieldUpgrade/FieldUpgradeStart.c @@ -0,0 +1,50 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "FieldUpgradeStart_fp.h" +#if CC_FieldUpgradeStart // Conditional expansion of this file + +/*(See part 3 specification) +// FieldUpgradeStart +*/ +TPM_RC +TPM2_FieldUpgradeStart(FieldUpgradeStart_In* in // IN: input parameter list +) +{ + // Not implemented + UNUSED_PARAMETER(in); + return TPM_RC_SUCCESS; +} +#endif \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/FieldUpgrade/FirmwareRead.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/FieldUpgrade/FirmwareRead.c new file mode 100644 index 0000000..79092c8 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/FieldUpgrade/FirmwareRead.c @@ -0,0 +1,54 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "FirmwareRead_fp.h" + +#if CC_FirmwareRead // Conditional expansion of this file + +/*(See part 3 specification) +// FirmwareRead +*/ +TPM_RC +TPM2_FirmwareRead(FirmwareRead_In* in, // IN: input parameter list + FirmwareRead_Out* out // OUT: output parameter list +) +{ + // Not implemented + UNUSED_PARAMETER(in); + UNUSED_PARAMETER(out); + return TPM_RC_SUCCESS; +} + +#endif // CC_FirmwareRead \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/HashHMAC/EventSequenceComplete.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/HashHMAC/EventSequenceComplete.c new file mode 100644 index 0000000..b0da0d6 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/HashHMAC/EventSequenceComplete.c @@ -0,0 +1,110 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "EventSequenceComplete_fp.h" + +#if CC_EventSequenceComplete // Conditional expansion of this file + +/*(See part 3 specification) + Complete an event sequence and flush the object. +*/ +// Return Type: TPM_RC +// TPM_RC_LOCALITY PCR extension is not allowed at the current locality +// TPM_RC_MODE input handle is not a valid event sequence object +TPM_RC +TPM2_EventSequenceComplete( + EventSequenceComplete_In* in, // IN: input parameter list + EventSequenceComplete_Out* out // OUT: output parameter list +) +{ + HASH_OBJECT* hashObject; + UINT32 i; + TPM_ALG_ID hashAlg; + // Input validation + // get the event sequence object pointer + hashObject = (HASH_OBJECT*)HandleToObject(in->sequenceHandle); + + // input handle must reference an event sequence object + if(hashObject->attributes.eventSeq != SET) + return TPM_RCS_MODE + RC_EventSequenceComplete_sequenceHandle; + + // see if a PCR extend is requested in call + if(in->pcrHandle != TPM_RH_NULL) + { + // see if extend of the PCR is allowed at the locality of the command, + if(!PCRIsExtendAllowed(in->pcrHandle)) + return TPM_RC_LOCALITY; + // if an extend is going to take place, then check to see if there has + // been an orderly shutdown. If so, and the selected PCR is one of the + // state saved PCR, then the orderly state has to change. The orderly state + // does not change for PCR that are not preserved. + // NOTE: This doesn't just check for Shutdown(STATE) because the orderly + // state will have to change if this is a state-saved PCR regardless + // of the current state. This is because a subsequent Shutdown(STATE) will + // check to see if there was an orderly shutdown and not do anything if + // there was. So, this must indicate that a future Shutdown(STATE) has + // something to do. + if(PCRIsStateSaved(in->pcrHandle)) + RETURN_IF_ORDERLY; + } + // Command Output + out->results.count = 0; + + for(i = 0; i < HASH_COUNT; i++) + { + hashAlg = CryptHashGetAlgByIndex(i); + // Update last piece of data + CryptDigestUpdate2B(&hashObject->state.hashState[i], &in->buffer.b); + // Complete hash + out->results.digests[out->results.count].hashAlg = hashAlg; + CryptHashEnd(&hashObject->state.hashState[i], + CryptHashGetDigestSize(hashAlg), + (BYTE*)&out->results.digests[out->results.count].digest); + // Extend PCR + if(in->pcrHandle != TPM_RH_NULL) + PCRExtend(in->pcrHandle, + hashAlg, + CryptHashGetDigestSize(hashAlg), + (BYTE*)&out->results.digests[out->results.count].digest); + out->results.count++; + } + // Internal Data Update + // mark sequence object as evict so it will be flushed on the way out + hashObject->attributes.evict = SET; + + return TPM_RC_SUCCESS; +} + +#endif // CC_EventSequenceComplete \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/HashHMAC/HMAC_Start.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/HashHMAC/HMAC_Start.c new file mode 100644 index 0000000..2c4150c --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/HashHMAC/HMAC_Start.c @@ -0,0 +1,101 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "HMAC_Start_fp.h" + +#if CC_HMAC_Start // Conditional expansion of this file + +/*(See part 3 specification) +// Initialize a HMAC sequence and create a sequence object +*/ +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES key referenced by 'handle' is not a signing key +// or is restricted +// TPM_RC_OBJECT_MEMORY no space to create an internal object +// TPM_RC_KEY key referenced by 'handle' is not an HMAC key +// TPM_RC_VALUE 'hashAlg' is not compatible with the hash algorithm +// of the scheme of the object referenced by 'handle' +TPM_RC +TPM2_HMAC_Start(HMAC_Start_In* in, // IN: input parameter list + HMAC_Start_Out* out // OUT: output parameter list +) +{ + OBJECT* keyObject; + TPMT_PUBLIC* publicArea; + TPM_ALG_ID hashAlg; + + // Input Validation + + // Get HMAC key object and public area pointers + keyObject = HandleToObject(in->handle); + publicArea = &keyObject->publicArea; + + // Make sure that the key is an HMAC key + if(publicArea->type != TPM_ALG_KEYEDHASH) + return TPM_RCS_TYPE + RC_HMAC_Start_handle; + + // and that it is unrestricted + if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted)) + return TPM_RCS_ATTRIBUTES + RC_HMAC_Start_handle; + + // and that it is a signing key + if(!IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign)) + return TPM_RCS_KEY + RC_HMAC_Start_handle; + + // See if the key has a default + if(publicArea->parameters.keyedHashDetail.scheme.scheme == TPM_ALG_NULL) + // it doesn't so use the input value + hashAlg = in->hashAlg; + else + { + // key has a default so use it + hashAlg = publicArea->parameters.keyedHashDetail.scheme.details.hmac.hashAlg; + // and verify that the input was either the TPM_ALG_NULL or the default + if(in->hashAlg != TPM_ALG_NULL && in->hashAlg != hashAlg) + hashAlg = TPM_ALG_NULL; + } + // if we ended up without a hash algorithm then return an error + if(hashAlg == TPM_ALG_NULL) + return TPM_RCS_VALUE + RC_HMAC_Start_hashAlg; + + // Internal Data Update + + // Create a HMAC sequence object. A TPM_RC_OBJECT_MEMORY error may be + // returned at this point + return ObjectCreateHMACSequence( + hashAlg, keyObject, &in->auth, &out->sequenceHandle); +} + +#endif // CC_HMAC_Start \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/HashHMAC/HashSequenceStart.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/HashHMAC/HashSequenceStart.c new file mode 100644 index 0000000..d78cfd3 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/HashHMAC/HashSequenceStart.c @@ -0,0 +1,62 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "HashSequenceStart_fp.h" + +#if CC_HashSequenceStart // Conditional expansion of this file + +/*(See part 3 specification) +// Start a hash or an event sequence +*/ +// Return Type: TPM_RC +// TPM_RC_OBJECT_MEMORY no space to create an internal object +TPM_RC +TPM2_HashSequenceStart(HashSequenceStart_In* in, // IN: input parameter list + HashSequenceStart_Out* out // OUT: output parameter list +) +{ + // Internal Data Update + + if(in->hashAlg == TPM_ALG_NULL) + // Start a event sequence. A TPM_RC_OBJECT_MEMORY error may be + // returned at this point + return ObjectCreateEventSequence(&in->auth, &out->sequenceHandle); + + // Start a hash sequence. A TPM_RC_OBJECT_MEMORY error may be + // returned at this point + return ObjectCreateHashSequence(in->hashAlg, &in->auth, &out->sequenceHandle); +} + +#endif // CC_HashSequenceStart \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/HashHMAC/MAC_Start.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/HashHMAC/MAC_Start.c new file mode 100644 index 0000000..14c667c --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/HashHMAC/MAC_Start.c @@ -0,0 +1,89 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "MAC_Start_fp.h" + +#if CC_MAC_Start // Conditional expansion of this file + +/*(See part 3 specification) +// Initialize a HMAC sequence and create a sequence object +*/ +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES key referenced by 'handle' is not a signing key +// or is restricted +// TPM_RC_OBJECT_MEMORY no space to create an internal object +// TPM_RC_KEY key referenced by 'handle' is not an HMAC key +// TPM_RC_VALUE 'hashAlg' is not compatible with the hash algorithm +// of the scheme of the object referenced by 'handle' +TPM_RC +TPM2_MAC_Start(MAC_Start_In* in, // IN: input parameter list + MAC_Start_Out* out // OUT: output parameter list +) +{ + OBJECT* keyObject; + TPMT_PUBLIC* publicArea; + TPM_RC result; + + // Input Validation + + // Get HMAC key object and public area pointers + keyObject = HandleToObject(in->handle); + publicArea = &keyObject->publicArea; + + // Make sure that the key can do what is required + result = CryptSelectMac(publicArea, &in->inScheme); + // If the key is not able to do a MAC, indicate that the handle selects an + // object that can't do a MAC + if(result == TPM_RCS_TYPE) + return TPM_RCS_TYPE + RC_MAC_Start_handle; + // If there is another error type, indicate that the scheme and key are not + // compatible + if(result != TPM_RC_SUCCESS) + return RcSafeAddToResult(result, RC_MAC_Start_inScheme); + // Make sure that the key is not restricted + if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted)) + return TPM_RCS_ATTRIBUTES + RC_MAC_Start_handle; + // and that it is a signing key + if(!IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign)) + return TPM_RCS_KEY + RC_MAC_Start_handle; + + // Internal Data Update + // Create a HMAC sequence object. A TPM_RC_OBJECT_MEMORY error may be + // returned at this point + return ObjectCreateHMACSequence( + in->inScheme, keyObject, &in->auth, &out->sequenceHandle); +} + +#endif // CC_MAC_Start \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/HashHMAC/SequenceComplete.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/HashHMAC/SequenceComplete.c new file mode 100644 index 0000000..19aa328 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/HashHMAC/SequenceComplete.c @@ -0,0 +1,130 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "SequenceComplete_fp.h" + +#if CC_SequenceComplete // Conditional expansion of this file + +/*(See part 3 specification) +// Complete a sequence and flush the object. +*/ +// Return Type: TPM_RC +// TPM_RC_MODE 'sequenceHandle' does not reference a hash or HMAC +// sequence object +TPM_RC +TPM2_SequenceComplete(SequenceComplete_In* in, // IN: input parameter list + SequenceComplete_Out* out // OUT: output parameter list +) +{ + HASH_OBJECT* hashObject; + // Input validation + // Get hash object pointer + hashObject = (HASH_OBJECT*)HandleToObject(in->sequenceHandle); + + // input handle must be a hash or HMAC sequence object. + if(hashObject->attributes.hashSeq == CLEAR + && hashObject->attributes.hmacSeq == CLEAR) + return TPM_RCS_MODE + RC_SequenceComplete_sequenceHandle; + // Command Output + if(hashObject->attributes.hashSeq == SET) // sequence object for hash + { + // Get the hash algorithm before the algorithm is lost in CryptHashEnd + TPM_ALG_ID hashAlg = hashObject->state.hashState[0].hashAlg; + + // Update last piece of the data + CryptDigestUpdate2B(&hashObject->state.hashState[0], &in->buffer.b); + + // Complete hash + out->result.t.size = CryptHashEnd(&hashObject->state.hashState[0], + sizeof(out->result.t.buffer), + out->result.t.buffer); + // Check if the first block of the sequence has been received + if(hashObject->attributes.firstBlock == CLEAR) + { + // If not, then this is the first block so see if it is 'safe' + // to sign. + if(TicketIsSafe(&in->buffer.b)) + hashObject->attributes.ticketSafe = SET; + } + // Output ticket + out->validation.tag = TPM_ST_HASHCHECK; + out->validation.hierarchy = in->hierarchy; + + if(in->hierarchy == TPM_RH_NULL) + { + // Ticket is not required + out->validation.digest.t.size = 0; + } + else if(hashObject->attributes.ticketSafe == CLEAR) + { + // Ticket is not safe to generate + out->validation.hierarchy = TPM_RH_NULL; + out->validation.digest.t.size = 0; + } + else + { + // Compute ticket + TicketComputeHashCheck( + out->validation.hierarchy, hashAlg, &out->result, &out->validation); + } + } + else + { + // Update last piece of data + CryptDigestUpdate2B(&hashObject->state.hmacState.hashState, &in->buffer.b); +# if !SMAC_IMPLEMENTED + // Complete HMAC + out->result.t.size = CryptHmacEnd(&(hashObject->state.hmacState), + sizeof(out->result.t.buffer), + out->result.t.buffer); +# else + // Complete the MAC + out->result.t.size = CryptMacEnd(&hashObject->state.hmacState, + sizeof(out->result.t.buffer), + out->result.t.buffer); +# endif + // No ticket is generated for HMAC sequence + out->validation.tag = TPM_ST_HASHCHECK; + out->validation.hierarchy = TPM_RH_NULL; + out->validation.digest.t.size = 0; + } + // Internal Data Update + // mark sequence object as evict so it will be flushed on the way out + hashObject->attributes.evict = SET; + + return TPM_RC_SUCCESS; +} + +#endif // CC_SequenceComplete \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/HashHMAC/SequenceUpdate.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/HashHMAC/SequenceUpdate.c new file mode 100644 index 0000000..938c01b --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/HashHMAC/SequenceUpdate.c @@ -0,0 +1,105 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "SequenceUpdate_fp.h" + +#if CC_SequenceUpdate // Conditional expansion of this file + +/*(See part 3 specification) +// This function is used to add data to a sequence object. +*/ +// Return Type: TPM_RC +// TPM_RC_MODE 'sequenceHandle' does not reference a hash or HMAC +// sequence object +TPM_RC +TPM2_SequenceUpdate(SequenceUpdate_In* in // IN: input parameter list +) +{ + OBJECT* object; + HASH_OBJECT* hashObject; + + // Input Validation + + // Get sequence object pointer + object = HandleToObject(in->sequenceHandle); + hashObject = (HASH_OBJECT*)object; + + // Check that referenced object is a sequence object. + if(!ObjectIsSequence(object)) + return TPM_RCS_MODE + RC_SequenceUpdate_sequenceHandle; + + // Internal Data Update + + if(object->attributes.eventSeq == SET) + { + // Update event sequence object + UINT32 i; + for(i = 0; i < HASH_COUNT; i++) + { + // Update sequence object + CryptDigestUpdate2B(&hashObject->state.hashState[i], &in->buffer.b); + } + } + else + { + // Update hash/HMAC sequence object + if(hashObject->attributes.hashSeq == SET) + { + // Is this the first block of the sequence + if(hashObject->attributes.firstBlock == CLEAR) + { + // If so, indicate that first block was received + hashObject->attributes.firstBlock = SET; + + // Check the first block to see if the first block can contain + // the TPM_GENERATED_VALUE. If it does, it is not safe for + // a ticket. + if(TicketIsSafe(&in->buffer.b)) + hashObject->attributes.ticketSafe = SET; + } + // Update sequence object hash/HMAC stack + CryptDigestUpdate2B(&hashObject->state.hashState[0], &in->buffer.b); + } + else if(object->attributes.hmacSeq == SET) + { + // Update sequence object HMAC stack + CryptDigestUpdate2B(&hashObject->state.hmacState.hashState, + &in->buffer.b); + } + } + return TPM_RC_SUCCESS; +} + +#endif // CC_SequenceUpdate \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/ChangeEPS.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/ChangeEPS.c new file mode 100644 index 0000000..a7140f1 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/ChangeEPS.c @@ -0,0 +1,98 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "ChangeEPS_fp.h" + +#if CC_ChangeEPS // Conditional expansion of this file + +/*(See part 3 specification) +// Reset current EPS value +*/ +TPM_RC +TPM2_ChangeEPS(ChangeEPS_In* in // IN: input parameter list +) +{ + // The command needs NV update. Check if NV is available. + // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at + // this point + RETURN_IF_NV_IS_NOT_AVAILABLE; + + // Input parameter is not reference in command action + NOT_REFERENCED(in); + + // Internal Data Update + + // Reset endorsement hierarchy seed from RNG +#if(defined USE_PLATFORM_EPS) && (USE_PLATFORM_EPS != NO) + _plat__GetEPS(gp.EPSeed.t.size, gp.EPSeed.t.buffer); +#else + CryptRandomGenerate(sizeof(gp.EPSeed.t.buffer), gp.EPSeed.t.buffer); +#endif + + // Create new ehProof value from RNG + CryptRandomGenerate(sizeof(gp.ehProof.t.buffer), gp.ehProof.t.buffer); + + // Enable endorsement hierarchy + gc.ehEnable = TRUE; + + // set authValue buffer to zeros + MemorySet(gp.endorsementAuth.t.buffer, 0, gp.endorsementAuth.t.size); + // Set endorsement authValue to null + gp.endorsementAuth.t.size = 0; + + // Set endorsement authPolicy to null + gp.endorsementAlg = TPM_ALG_NULL; + gp.endorsementPolicy.t.size = 0; + + // Flush loaded object in endorsement hierarchy + ObjectFlushHierarchy(TPM_RH_ENDORSEMENT); + + // Flush evict object of endorsement hierarchy stored in NV + NvFlushHierarchy(TPM_RH_ENDORSEMENT); + + // Save hierarchy changes to NV + NV_SYNC_PERSISTENT(EPSeed); + NV_SYNC_PERSISTENT(ehProof); + NV_SYNC_PERSISTENT(endorsementAuth); + NV_SYNC_PERSISTENT(endorsementAlg); + NV_SYNC_PERSISTENT(endorsementPolicy); + + // orderly state should be cleared because of the update to state clear data + g_clearOrderly = TRUE; + + return TPM_RC_SUCCESS; +} + +#endif // CC_ChangeEPS \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/ChangePPS.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/ChangePPS.c new file mode 100644 index 0000000..d9359d9 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/ChangePPS.c @@ -0,0 +1,95 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "ChangePPS_fp.h" + +#if CC_ChangePPS // Conditional expansion of this file + +/*(See part 3 specification) +// Reset current PPS value +*/ +TPM_RC +TPM2_ChangePPS(ChangePPS_In* in // IN: input parameter list +) +{ + UINT32 i; + + // Check if NV is available. A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE + // error may be returned at this point + RETURN_IF_NV_IS_NOT_AVAILABLE; + + // Input parameter is not reference in command action + NOT_REFERENCED(in); + + // Internal Data Update + + // Reset platform hierarchy seed from RNG + CryptRandomGenerate(sizeof(gp.PPSeed.t.buffer), gp.PPSeed.t.buffer); + + // Create a new phProof value from RNG to prevent the saved platform + // hierarchy contexts being loaded + CryptRandomGenerate(sizeof(gp.phProof.t.buffer), gp.phProof.t.buffer); + + // Set platform authPolicy to null + gc.platformAlg = TPM_ALG_NULL; + gc.platformPolicy.t.size = 0; + + // Flush loaded object in platform hierarchy + ObjectFlushHierarchy(TPM_RH_PLATFORM); + + // Flush platform evict object and index in NV + NvFlushHierarchy(TPM_RH_PLATFORM); + + // Save hierarchy changes to NV + NV_SYNC_PERSISTENT(PPSeed); + NV_SYNC_PERSISTENT(phProof); + + // Re-initialize PCR policies +# if defined NUM_POLICY_PCR_GROUP && NUM_POLICY_PCR_GROUP > 0 + for(i = 0; i < NUM_POLICY_PCR_GROUP; i++) + { + gp.pcrPolicies.hashAlg[i] = TPM_ALG_NULL; + gp.pcrPolicies.policy[i].t.size = 0; + } + NV_SYNC_PERSISTENT(pcrPolicies); +# endif + + // orderly state should be cleared because of the update to state clear data + g_clearOrderly = TRUE; + + return TPM_RC_SUCCESS; +} + +#endif // CC_ChangePPS \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/Clear.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/Clear.c new file mode 100644 index 0000000..ee48969 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/Clear.c @@ -0,0 +1,123 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "Clear_fp.h" + +#if CC_Clear // Conditional expansion of this file + +/*(See part 3 specification) +// Clear owner +*/ +// Return Type: TPM_RC +// TPM_RC_DISABLED Clear command has been disabled +TPM_RC +TPM2_Clear(Clear_In* in // IN: input parameter list +) +{ + // Input parameter is not reference in command action + NOT_REFERENCED(in); + + // The command needs NV update. Check if NV is available. + // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at + // this point + RETURN_IF_NV_IS_NOT_AVAILABLE; + + // Input Validation + + // If Clear command is disabled, return an error + if(gp.disableClear) + return TPM_RC_DISABLED; + + // Internal Data Update + + // Reset storage hierarchy seed from RNG + CryptRandomGenerate(sizeof(gp.SPSeed.t.buffer), gp.SPSeed.t.buffer); + + // Create new shProof and ehProof value from RNG + CryptRandomGenerate(sizeof(gp.shProof.t.buffer), gp.shProof.t.buffer); + CryptRandomGenerate(sizeof(gp.ehProof.t.buffer), gp.ehProof.t.buffer); + + // Enable storage and endorsement hierarchy + gc.shEnable = gc.ehEnable = TRUE; + + // set the authValue buffers to zero + MemorySet(&gp.ownerAuth, 0, sizeof(gp.ownerAuth)); + MemorySet(&gp.endorsementAuth, 0, sizeof(gp.endorsementAuth)); + MemorySet(&gp.lockoutAuth, 0, sizeof(gp.lockoutAuth)); + + // Set storage, endorsement, and lockout authPolicy to null + gp.ownerAlg = gp.endorsementAlg = gp.lockoutAlg = TPM_ALG_NULL; + MemorySet(&gp.ownerPolicy, 0, sizeof(gp.ownerPolicy)); + MemorySet(&gp.endorsementPolicy, 0, sizeof(gp.endorsementPolicy)); + MemorySet(&gp.lockoutPolicy, 0, sizeof(gp.lockoutPolicy)); + + // Flush loaded object in storage and endorsement hierarchy + ObjectFlushHierarchy(TPM_RH_OWNER); + ObjectFlushHierarchy(TPM_RH_ENDORSEMENT); + + // Flush owner and endorsement object and owner index in NV + NvFlushHierarchy(TPM_RH_OWNER); + NvFlushHierarchy(TPM_RH_ENDORSEMENT); + + // Initialize dictionary attack parameters + DAPreInstall_Init(); + + // Reset clock + go.clock = 0; + go.clockSafe = YES; + NvWrite(NV_ORDERLY_DATA, sizeof(ORDERLY_DATA), &go); + + // Reset counters + gp.resetCount = gr.restartCount = gr.clearCount = 0; + gp.auditCounter = 0; + + // Save persistent data changes to NV + // Note: since there are so many changes to the persistent data structure, the + // entire PERSISTENT_DATA structure is written as a unit + NvWrite(NV_PERSISTENT_DATA, sizeof(PERSISTENT_DATA), &gp); + + // Reset the PCR authValues (this does not change the PCRs) + PCR_ClearAuth(); + + // Bump the PCR counter + PCRChanged(0); + + // orderly state should be cleared because of the update to state clear data + g_clearOrderly = TRUE; + + return TPM_RC_SUCCESS; +} + +#endif // CC_Clear \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/ClearControl.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/ClearControl.c new file mode 100644 index 0000000..cb18ca0 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/ClearControl.c @@ -0,0 +1,71 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "ClearControl_fp.h" + +#if CC_ClearControl // Conditional expansion of this file + +/*(See part 3 specification) +// Enable or disable the execution of TPM2_Clear command +*/ +// Return Type: TPM_RC +// TPM_RC_AUTH_FAIL authorization is not properly given +TPM_RC +TPM2_ClearControl(ClearControl_In* in // IN: input parameter list +) +{ + // The command needs NV update. + RETURN_IF_NV_IS_NOT_AVAILABLE; + + // Input Validation + + // LockoutAuth may be used to set disableLockoutClear to TRUE but not to FALSE + if(in->auth == TPM_RH_LOCKOUT && in->disable == NO) + return TPM_RC_AUTH_FAIL; + + // Internal Data Update + + if(in->disable == YES) + gp.disableClear = TRUE; + else + gp.disableClear = FALSE; + + // Record the change to NV + NV_SYNC_PERSISTENT(disableClear); + + return TPM_RC_SUCCESS; +} + +#endif // CC_ClearControl \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/CreatePrimary.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/CreatePrimary.c new file mode 100644 index 0000000..a9ab1cb --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/CreatePrimary.c @@ -0,0 +1,146 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "CreatePrimary_fp.h" + +#if CC_CreatePrimary // Conditional expansion of this file + +/*(See part 3 specification) +// Creates a primary or temporary object from a primary seed. +*/ +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES sensitiveDataOrigin is CLEAR when sensitive.data is an +// Empty Buffer 'fixedTPM', 'fixedParent', or +// 'encryptedDuplication' attributes are inconsistent +// between themselves or with those of the parent object; +// inconsistent 'restricted', 'decrypt' and 'sign' +// attributes +// attempt to inject sensitive data for an asymmetric +// key; +// TPM_RC_KDF incorrect KDF specified for decrypting keyed hash +// object +// TPM_RC_KEY a provided symmetric key value is not allowed +// TPM_RC_OBJECT_MEMORY there is no free slot for the object +// TPM_RC_SCHEME inconsistent attributes 'decrypt', 'sign', +// 'restricted' and key's scheme ID; or hash algorithm is +// inconsistent with the scheme ID for keyed hash object +// TPM_RC_SIZE size of public authorization policy or sensitive +// authorization value does not match digest size of the +// name algorithm; or sensitive data size for the keyed +// hash object is larger than is allowed for the scheme +// TPM_RC_SYMMETRIC a storage key with no symmetric algorithm specified; +// or non-storage key with symmetric algorithm different +// from TPM_ALG_NULL +// TPM_RC_TYPE unknown object type +TPM_RC +TPM2_CreatePrimary(CreatePrimary_In* in, // IN: input parameter list + CreatePrimary_Out* out // OUT: output parameter list +) +{ + TPM_RC result = TPM_RC_SUCCESS; + TPMT_PUBLIC* publicArea; + DRBG_STATE rand; + OBJECT* newObject; + TPM2B_NAME name; + + // Input Validation + // Will need a place to put the result + newObject = FindEmptyObjectSlot(&out->objectHandle); + if(newObject == NULL) + return TPM_RC_OBJECT_MEMORY; + // Get the address of the public area in the new object + // (this is just to save typing) + publicArea = &newObject->publicArea; + + *publicArea = in->inPublic.publicArea; + + // Check attributes in input public area. CreateChecks() checks the things that + // are unique to creation and then validates the attributes and values that are + // common to create and load. + result = CreateChecks(NULL, publicArea, in->inSensitive.sensitive.data.t.size); + if(result != TPM_RC_SUCCESS) + return RcSafeAddToResult(result, RC_CreatePrimary_inPublic); + // Validate the sensitive area values + if(!AdjustAuthSize(&in->inSensitive.sensitive.userAuth, publicArea->nameAlg)) + return TPM_RCS_SIZE + RC_CreatePrimary_inSensitive; + // Command output + // Compute the name using out->name as a scratch area (this is not the value + // that ultimately will be returned, then instantiate the state that will be + // used as a random number generator during the object creation. + // The caller does not know the seed values so the actual name does not have + // to be over the input, it can be over the unmarshaled structure. + result = + DRBG_InstantiateSeeded(&rand, + &HierarchyGetPrimarySeed(in->primaryHandle)->b, + PRIMARY_OBJECT_CREATION, + (TPM2B*)PublicMarshalAndComputeName(publicArea, &name), + &in->inSensitive.sensitive.data.b); + if(result == TPM_RC_SUCCESS) + { + newObject->attributes.primary = SET; + if(in->primaryHandle == TPM_RH_ENDORSEMENT) + newObject->attributes.epsHierarchy = SET; + + // Create the primary object. + result = CryptCreateObject( + newObject, &in->inSensitive.sensitive, (RAND_STATE*)&rand); + } + if(result != TPM_RC_SUCCESS) + return result; + + // Set the publicArea and name from the computed values + out->outPublic.publicArea = newObject->publicArea; + out->name = newObject->name; + + // Fill in creation data + FillInCreationData(in->primaryHandle, + publicArea->nameAlg, + &in->creationPCR, + &in->outsideInfo, + &out->creationData, + &out->creationHash); + + // Compute creation ticket + TicketComputeCreation(EntityGetHierarchy(in->primaryHandle), + &out->name, + &out->creationHash, + &out->creationTicket); + + // Set the remaining attributes for a loaded object + ObjectSetLoadedAttributes(newObject, in->primaryHandle); + return result; +} + +#endif // CC_CreatePrimary \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/HierarchyChangeAuth.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/HierarchyChangeAuth.c new file mode 100644 index 0000000..8b4a65c --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/HierarchyChangeAuth.c @@ -0,0 +1,90 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "HierarchyChangeAuth_fp.h" + +#if CC_HierarchyChangeAuth // Conditional expansion of this file + +# include "Object_spt_fp.h" + +/*(See part 3 specification) +// Set a hierarchy authValue +*/ +// Return Type: TPM_RC +// TPM_RC_SIZE 'newAuth' size is greater than that of integrity hash +// digest +TPM_RC +TPM2_HierarchyChangeAuth(HierarchyChangeAuth_In* in // IN: input parameter list +) +{ + // The command needs NV update. + RETURN_IF_NV_IS_NOT_AVAILABLE; + + // Make sure that the authorization value is a reasonable size (not larger than + // the size of the digest produced by the integrity hash. The integrity + // hash is assumed to produce the longest digest of any hash implemented + // on the TPM. This will also remove trailing zeros from the authValue. + if(MemoryRemoveTrailingZeros(&in->newAuth) > CONTEXT_INTEGRITY_HASH_SIZE) + return TPM_RCS_SIZE + RC_HierarchyChangeAuth_newAuth; + + // Set hierarchy authValue + switch(in->authHandle) + { + case TPM_RH_OWNER: + gp.ownerAuth = in->newAuth; + NV_SYNC_PERSISTENT(ownerAuth); + break; + case TPM_RH_ENDORSEMENT: + gp.endorsementAuth = in->newAuth; + NV_SYNC_PERSISTENT(endorsementAuth); + break; + case TPM_RH_PLATFORM: + gc.platformAuth = in->newAuth; + // orderly state should be cleared + g_clearOrderly = TRUE; + break; + case TPM_RH_LOCKOUT: + gp.lockoutAuth = in->newAuth; + NV_SYNC_PERSISTENT(lockoutAuth); + break; + default: + FAIL(FATAL_ERROR_INTERNAL); + break; + } + + return TPM_RC_SUCCESS; +} + +#endif // CC_HierarchyChangeAuth \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/HierarchyControl.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/HierarchyControl.c new file mode 100644 index 0000000..73ddb6f --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/HierarchyControl.c @@ -0,0 +1,142 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "HierarchyControl_fp.h" + +#if CC_HierarchyControl // Conditional expansion of this file + +/*(See part 3 specification) +// Enable or disable use of a hierarchy +*/ +// Return Type: TPM_RC +// TPM_RC_AUTH_TYPE 'authHandle' is not applicable to 'hierarchy' in its +// current state +TPM_RC +TPM2_HierarchyControl(HierarchyControl_In* in // IN: input parameter list +) +{ + BOOL select = (in->state == YES); + BOOL* selected = NULL; + + // Input Validation + switch(in->enable) + { + // Platform hierarchy has to be disabled by PlatformAuth + // If the platform hierarchy has already been disabled, only a reboot + // can enable it again + case TPM_RH_PLATFORM: + case TPM_RH_PLATFORM_NV: + if(in->authHandle != TPM_RH_PLATFORM) + return TPM_RC_AUTH_TYPE; + break; + + // ShEnable may be disabled if PlatformAuth/PlatformPolicy or + // OwnerAuth/OwnerPolicy is provided. If ShEnable is disabled, then it + // may only be enabled if PlatformAuth/PlatformPolicy is provided. + case TPM_RH_OWNER: + if(in->authHandle != TPM_RH_PLATFORM && in->authHandle != TPM_RH_OWNER) + return TPM_RC_AUTH_TYPE; + if(gc.shEnable == FALSE && in->state == YES + && in->authHandle != TPM_RH_PLATFORM) + return TPM_RC_AUTH_TYPE; + break; + + // EhEnable may be disabled if either PlatformAuth/PlatformPolicy or + // EndosementAuth/EndorsementPolicy is provided. If EhEnable is disabled, + // then it may only be enabled if PlatformAuth/PlatformPolicy is + // provided. + case TPM_RH_ENDORSEMENT: + if(in->authHandle != TPM_RH_PLATFORM + && in->authHandle != TPM_RH_ENDORSEMENT) + return TPM_RC_AUTH_TYPE; + if(gc.ehEnable == FALSE && in->state == YES + && in->authHandle != TPM_RH_PLATFORM) + return TPM_RC_AUTH_TYPE; + break; + default: + FAIL(FATAL_ERROR_INTERNAL); + break; + } + + // Internal Data Update + + // Enable or disable the selected hierarchy + // Note: the authorization processing for this command may keep these + // command actions from being executed. For example, if phEnable is + // CLEAR, then platformAuth cannot be used for authorization. This + // means that would not be possible to use platformAuth to change the + // state of phEnable from CLEAR to SET. + // If it is decided that platformPolicy can still be used when phEnable + // is CLEAR, then this code could SET phEnable when proper platform + // policy is provided. + switch(in->enable) + { + case TPM_RH_OWNER: + selected = &gc.shEnable; + break; + case TPM_RH_ENDORSEMENT: + selected = &gc.ehEnable; + break; + case TPM_RH_PLATFORM: + selected = &g_phEnable; + break; + case TPM_RH_PLATFORM_NV: + selected = &gc.phEnableNV; + break; + default: + FAIL(FATAL_ERROR_INTERNAL); + break; + } + if(selected != NULL && *selected != select) + { + // Before changing the internal state, make sure that NV is available. + // Only need to update NV if changing the orderly state + RETURN_IF_ORDERLY; + + // state is changing and NV is available so modify + *selected = select; + // If a hierarchy was just disabled, flush it + if(select == CLEAR && in->enable != TPM_RH_PLATFORM_NV) + // Flush hierarchy + ObjectFlushHierarchy(in->enable); + + // orderly state should be cleared because of the update to state clear data + // This gets processed in ExecuteCommand() on the way out. + g_clearOrderly = TRUE; + } + return TPM_RC_SUCCESS; +} + +#endif // CC_HierarchyControl \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/SetPrimaryPolicy.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/SetPrimaryPolicy.c new file mode 100644 index 0000000..e75275d --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Hierarchy/SetPrimaryPolicy.c @@ -0,0 +1,110 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "SetPrimaryPolicy_fp.h" + +#if CC_SetPrimaryPolicy // Conditional expansion of this file + +/*(See part 3 specification) +// Set a hierarchy policy +*/ +// Return Type: TPM_RC +// TPM_RC_SIZE size of input authPolicy is not consistent with +// input hash algorithm +TPM_RC +TPM2_SetPrimaryPolicy(SetPrimaryPolicy_In* in // IN: input parameter list +) +{ + // Input Validation + + // Check the authPolicy consistent with hash algorithm. If the policy size is + // zero, then the algorithm is required to be TPM_ALG_NULL + if(in->authPolicy.t.size != CryptHashGetDigestSize(in->hashAlg)) + return TPM_RCS_SIZE + RC_SetPrimaryPolicy_authPolicy; + + // The command need NV update for OWNER and ENDORSEMENT hierarchy, and + // might need orderlyState update for PLATFROM hierarchy. + // Check if NV is available. A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE + // error may be returned at this point + RETURN_IF_NV_IS_NOT_AVAILABLE; + + // Internal Data Update + + // Set hierarchy policy + switch(in->authHandle) + { + case TPM_RH_OWNER: + gp.ownerAlg = in->hashAlg; + gp.ownerPolicy = in->authPolicy; + NV_SYNC_PERSISTENT(ownerAlg); + NV_SYNC_PERSISTENT(ownerPolicy); + break; + case TPM_RH_ENDORSEMENT: + gp.endorsementAlg = in->hashAlg; + gp.endorsementPolicy = in->authPolicy; + NV_SYNC_PERSISTENT(endorsementAlg); + NV_SYNC_PERSISTENT(endorsementPolicy); + break; + case TPM_RH_PLATFORM: + gc.platformAlg = in->hashAlg; + gc.platformPolicy = in->authPolicy; + // need to update orderly state + g_clearOrderly = TRUE; + break; + case TPM_RH_LOCKOUT: + gp.lockoutAlg = in->hashAlg; + gp.lockoutPolicy = in->authPolicy; + NV_SYNC_PERSISTENT(lockoutAlg); + NV_SYNC_PERSISTENT(lockoutPolicy); + break; + +# define SET_ACT_POLICY(N) \ + case TPM_RH_ACT_##N: \ + go.ACT_##N.hashAlg = in->hashAlg; \ + go.ACT_##N.authPolicy = in->authPolicy; \ + g_clearOrderly = TRUE; \ + break; + + FOR_EACH_ACT(SET_ACT_POLICY) + + default: + FAIL(FATAL_ERROR_INTERNAL); + break; + } + + return TPM_RC_SUCCESS; +} + +#endif // CC_SetPrimaryPolicy \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Misc/PP_Commands.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Misc/PP_Commands.c new file mode 100644 index 0000000..052dab3 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Misc/PP_Commands.c @@ -0,0 +1,79 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "PP_Commands_fp.h" + +#if CC_PP_Commands // Conditional expansion of this file + +/*(See part 3 specification) +// This command is used to determine which commands require assertion of +// Physical Presence in addition to platformAuth/platformPolicy. +*/ +TPM_RC +TPM2_PP_Commands(PP_Commands_In* in // IN: input parameter list +) +{ + UINT32 i; + + // The command needs NV update. Check if NV is available. + // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at + // this point + RETURN_IF_NV_IS_NOT_AVAILABLE; + + // Internal Data Update + + // Process set list + for(i = 0; i < in->setList.count; i++) + // If command is implemented, set it as PP required. If the input + // command is not a PP command, it will be ignored at + // PhysicalPresenceCommandSet(). + // Note: PhysicalPresenceCommandSet() checks if the command is implemented. + PhysicalPresenceCommandSet(in->setList.commandCodes[i]); + + // Process clear list + for(i = 0; i < in->clearList.count; i++) + // If command is implemented, clear it as PP required. If the input + // command is not a PP command, it will be ignored at + // PhysicalPresenceCommandClear(). If the input command is + // TPM2_PP_Commands, it will be ignored as well + PhysicalPresenceCommandClear(in->clearList.commandCodes[i]); + + // Save the change of PP list + NV_SYNC_PERSISTENT(ppList); + + return TPM_RC_SUCCESS; +} + +#endif // CC_PP_Commands \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Misc/SetAlgorithmSet.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Misc/SetAlgorithmSet.c new file mode 100644 index 0000000..56de309 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Misc/SetAlgorithmSet.c @@ -0,0 +1,61 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "SetAlgorithmSet_fp.h" + +#if CC_SetAlgorithmSet // Conditional expansion of this file + +/*(See part 3 specification) +// This command allows the platform to change the algorithm set setting of the TPM +*/ +TPM_RC +TPM2_SetAlgorithmSet(SetAlgorithmSet_In* in // IN: input parameter list +) +{ + // The command needs NV update. Check if NV is available. + // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at + // this point + RETURN_IF_NV_IS_NOT_AVAILABLE; + + // Internal Data Update + gp.algorithmSet = in->algorithmSet; + + // Write the algorithm set changes to NV + NV_SYNC_PERSISTENT(algorithmSet); + + return TPM_RC_SUCCESS; +} + +#endif // CC_SetAlgorithmSet \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_Certify.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_Certify.c new file mode 100644 index 0000000..f499f28 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_Certify.c @@ -0,0 +1,147 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "Attest_spt_fp.h" +#include "NV_Certify_fp.h" + +#if CC_NV_Certify // Conditional expansion of this file + +/*(See part 3 specification) +// certify the contents of an NV index or portion of an NV index +*/ +// Return Type: TPM_RC +// TPM_RC_NV_AUTHORIZATION the authorization was valid but the +// authorizing entity ('authHandle') +// is not allowed to read from the Index +// referenced by 'nvIndex' +// TPM_RC_KEY 'signHandle' does not reference a signing +// key +// TPM_RC_NV_LOCKED Index referenced by 'nvIndex' is locked +// for reading +// TPM_RC_NV_RANGE 'offset' plus 'size' extends outside of the +// data range of the Index referenced by +// 'nvIndex' +// TPM_RC_NV_UNINITIALIZED Index referenced by 'nvIndex' has not been +// written +// TPM_RC_SCHEME 'inScheme' is not an allowed value for the +// key definition +TPM_RC +TPM2_NV_Certify(NV_Certify_In* in, // IN: input parameter list + NV_Certify_Out* out // OUT: output parameter list +) +{ + TPM_RC result; + NV_REF locator; + NV_INDEX* nvIndex = NvGetIndexInfo(in->nvIndex, &locator); + TPMS_ATTEST certifyInfo; + OBJECT* signObject = HandleToObject(in->signHandle); + // Input Validation + if(!IsSigningObject(signObject)) + return TPM_RCS_KEY + RC_NV_Certify_signHandle; + if(!CryptSelectSignScheme(signObject, &in->inScheme)) + return TPM_RCS_SCHEME + RC_NV_Certify_inScheme; + + // Common access checks, NvWriteAccessCheck() may return TPM_RC_NV_AUTHORIZATION + // or TPM_RC_NV_LOCKED + result = NvReadAccessChecks( + in->authHandle, in->nvIndex, nvIndex->publicArea.attributes); + if(result != TPM_RC_SUCCESS) + return result; + + // make sure that the selection is within the range of the Index (cast to avoid + // any wrap issues with addition) + if((UINT32)in->size + (UINT32)in->offset > (UINT32)nvIndex->publicArea.dataSize) + return TPM_RC_NV_RANGE; + // Make sure the data will fit the return buffer. + // NOTE: This check may be modified if the output buffer will not hold the + // maximum sized NV buffer as part of the certified data. The difference in + // size could be substantial if the signature scheme was produced a large + // signature (e.g., RSA 4096). + if(in->size > MAX_NV_BUFFER_SIZE) + return TPM_RCS_VALUE + RC_NV_Certify_size; + + // Command Output + + // Fill in attest information common fields + FillInAttestInfo( + in->signHandle, &in->inScheme, &in->qualifyingData, &certifyInfo); + + // Get the name of the index + NvGetIndexName(nvIndex, &certifyInfo.attested.nv.indexName); + + // See if this is old format or new format + if((in->size != 0) || (in->offset != 0)) + { + // NV certify specific fields + // Attestation type + certifyInfo.type = TPM_ST_ATTEST_NV; + + // Set the return size + certifyInfo.attested.nv.nvContents.t.size = in->size; + + // Set the offset + certifyInfo.attested.nv.offset = in->offset; + + // Perform the read + NvGetIndexData(nvIndex, + locator, + in->offset, + in->size, + certifyInfo.attested.nv.nvContents.t.buffer); + } + else + { + HASH_STATE hashState; + // This is to sign a digest of the data + certifyInfo.type = TPM_ST_ATTEST_NV_DIGEST; + // Initialize the hash before calling the function to add the Index data to + // the hash. + certifyInfo.attested.nvDigest.nvDigest.t.size = + CryptHashStart(&hashState, in->inScheme.details.any.hashAlg); + NvHashIndexData( + &hashState, nvIndex, locator, 0, nvIndex->publicArea.dataSize); + CryptHashEnd2B(&hashState, &certifyInfo.attested.nvDigest.nvDigest.b); + } + // Sign attestation structure. A NULL signature will be returned if + // signObject is NULL. + return SignAttestInfo(signObject, + &in->inScheme, + &certifyInfo, + &in->qualifyingData, + &out->certifyInfo, + &out->signature); +} + +#endif // CC_NV_Certify \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_ChangeAuth.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_ChangeAuth.c new file mode 100644 index 0000000..eceaca7 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_ChangeAuth.c @@ -0,0 +1,67 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "NV_ChangeAuth_fp.h" + +#if CC_NV_ChangeAuth // Conditional expansion of this file + +/*(See part 3 specification) +// change authorization value of a NV index +*/ +// Return Type: TPM_RC +// TPM_RC_SIZE 'newAuth' size is larger than the digest +// size of the Name algorithm for the Index +// referenced by 'nvIndex' +TPM_RC +TPM2_NV_ChangeAuth(NV_ChangeAuth_In* in // IN: input parameter list +) +{ + NV_REF locator; + NV_INDEX* nvIndex = NvGetIndexInfo(in->nvIndex, &locator); + + // Input Validation + + // Remove trailing zeros and make sure that the result is not larger than the + // digest of the nameAlg. + if(MemoryRemoveTrailingZeros(&in->newAuth) + > CryptHashGetDigestSize(nvIndex->publicArea.nameAlg)) + return TPM_RCS_SIZE + RC_NV_ChangeAuth_newAuth; + + // Internal Data Update + // Change authValue + return NvWriteIndexAuth(locator, &in->newAuth); +} + +#endif // CC_NV_ChangeAuth \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_DefineSpace.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_DefineSpace.c new file mode 100644 index 0000000..5fa0b53 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_DefineSpace.c @@ -0,0 +1,225 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "NV_DefineSpace_fp.h" + +#if CC_NV_DefineSpace // Conditional expansion of this file + +/*(See part 3 specification) +// Define a NV index space +*/ +// Return Type: TPM_RC +// TPM_RC_HIERARCHY for authorizations using TPM_RH_PLATFORM +// phEnable_NV is clear preventing access to NV +// data in the platform hierarchy. +// TPM_RC_ATTRIBUTES attributes of the index are not consistent +// TPM_RC_NV_DEFINED index already exists +// TPM_RC_NV_SPACE insufficient space for the index +// TPM_RC_SIZE 'auth->size' or 'publicInfo->authPolicy.size' is +// larger than the digest size of +// 'publicInfo->nameAlg'; or 'publicInfo->dataSize' +// is not consistent with 'publicInfo->attributes' +// (this includes the case when the index is +// larger than a MAX_NV_BUFFER_SIZE but the +// TPMA_NV_WRITEALL attribute is SET) +TPM_RC +TPM2_NV_DefineSpace(NV_DefineSpace_In* in // IN: input parameter list +) +{ + TPMA_NV attributes = in->publicInfo.nvPublic.attributes; + UINT16 nameSize; + + nameSize = CryptHashGetDigestSize(in->publicInfo.nvPublic.nameAlg); + + // Input Validation + + // Checks not specific to type + + // If the UndefineSpaceSpecial command is not implemented, then can't have + // an index that can only be deleted with policy +# if CC_NV_UndefineSpaceSpecial == NO + if(IS_ATTRIBUTE(attributes, TPMA_NV, POLICY_DELETE)) + return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; +# endif + + // check that the authPolicy consistent with hash algorithm + + if(in->publicInfo.nvPublic.authPolicy.t.size != 0 + && in->publicInfo.nvPublic.authPolicy.t.size != nameSize) + return TPM_RCS_SIZE + RC_NV_DefineSpace_publicInfo; + + // make sure that the authValue is not too large + if(MemoryRemoveTrailingZeros(&in->auth) + > CryptHashGetDigestSize(in->publicInfo.nvPublic.nameAlg)) + return TPM_RCS_SIZE + RC_NV_DefineSpace_auth; + + // If an index is being created by the owner and shEnable is + // clear, then we would not reach this point because ownerAuth + // can't be given when shEnable is CLEAR. However, if phEnable + // is SET but phEnableNV is CLEAR, we have to check here + if(in->authHandle == TPM_RH_PLATFORM && gc.phEnableNV == CLEAR) + return TPM_RCS_HIERARCHY + RC_NV_DefineSpace_authHandle; + + // Attribute checks + // Eliminate the unsupported types + switch(GET_TPM_NT(attributes)) + { +# if CC_NV_Increment == YES + case TPM_NT_COUNTER: +# endif +# if CC_NV_SetBits == YES + case TPM_NT_BITS: +# endif +# if CC_NV_Extend == YES + case TPM_NT_EXTEND: +# endif +# if CC_PolicySecret == YES && defined TPM_NT_PIN_PASS + case TPM_NT_PIN_PASS: + case TPM_NT_PIN_FAIL: +# endif + case TPM_NT_ORDINARY: + break; + default: + return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; + break; + } + // Check that the sizes are OK based on the type + switch(GET_TPM_NT(attributes)) + { + case TPM_NT_ORDINARY: + // Can't exceed the allowed size for the implementation + if(in->publicInfo.nvPublic.dataSize > MAX_NV_INDEX_SIZE) + return TPM_RCS_SIZE + RC_NV_DefineSpace_publicInfo; + break; + case TPM_NT_EXTEND: + if(in->publicInfo.nvPublic.dataSize != nameSize) + return TPM_RCS_SIZE + RC_NV_DefineSpace_publicInfo; + break; + default: + // Everything else needs a size of 8 + if(in->publicInfo.nvPublic.dataSize != 8) + return TPM_RCS_SIZE + RC_NV_DefineSpace_publicInfo; + break; + } + // Handle other specifics + switch(GET_TPM_NT(attributes)) + { + case TPM_NT_COUNTER: + // Counter can't have TPMA_NV_CLEAR_STCLEAR SET (don't clear counters) + if(IS_ATTRIBUTE(attributes, TPMA_NV, CLEAR_STCLEAR)) + return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; + break; +# ifdef TPM_NT_PIN_FAIL + case TPM_NT_PIN_FAIL: + // NV_NO_DA must be SET and AUTHWRITE must be CLEAR + // NOTE: As with a PIN_PASS index, the authValue of the index is not + // available until the index is written. If AUTHWRITE is the only way to + // write then index, it could never be written. Rather than go through + // all of the other possible ways to write the Index, it is simply + // prohibited to write the index with the authValue. Other checks + // below will insure that there seems to be a way to write the index + // (i.e., with platform authorization , owner authorization, + // or with policyAuth.) + // It is not allowed to create a PIN Index that can't be modified. + if(!IS_ATTRIBUTE(attributes, TPMA_NV, NO_DA)) + return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; +# endif +# ifdef TPM_NT_PIN_PASS + case TPM_NT_PIN_PASS: + // AUTHWRITE must be CLEAR (see note above to TPM_NT_PIN_FAIL) + if(IS_ATTRIBUTE(attributes, TPMA_NV, AUTHWRITE) + || IS_ATTRIBUTE(attributes, TPMA_NV, GLOBALLOCK) + || IS_ATTRIBUTE(attributes, TPMA_NV, WRITEDEFINE)) + return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; +# endif // this comes before break because PIN_FAIL falls through + break; + default: + break; + } + + // Locks may not be SET and written cannot be SET + if(IS_ATTRIBUTE(attributes, TPMA_NV, WRITTEN) + || IS_ATTRIBUTE(attributes, TPMA_NV, WRITELOCKED) + || IS_ATTRIBUTE(attributes, TPMA_NV, READLOCKED)) + return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; + + // There must be a way to read the index. + if(!IS_ATTRIBUTE(attributes, TPMA_NV, OWNERREAD) + && !IS_ATTRIBUTE(attributes, TPMA_NV, PPREAD) + && !IS_ATTRIBUTE(attributes, TPMA_NV, AUTHREAD) + && !IS_ATTRIBUTE(attributes, TPMA_NV, POLICYREAD)) + return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; + + // There must be a way to write the index + if(!IS_ATTRIBUTE(attributes, TPMA_NV, OWNERWRITE) + && !IS_ATTRIBUTE(attributes, TPMA_NV, PPWRITE) + && !IS_ATTRIBUTE(attributes, TPMA_NV, AUTHWRITE) + && !IS_ATTRIBUTE(attributes, TPMA_NV, POLICYWRITE)) + return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; + + // An index with TPMA_NV_CLEAR_STCLEAR can't have TPMA_NV_WRITEDEFINE SET + if(IS_ATTRIBUTE(attributes, TPMA_NV, CLEAR_STCLEAR) + && IS_ATTRIBUTE(attributes, TPMA_NV, WRITEDEFINE)) + return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; + + // Make sure that the creator of the index can delete the index + if((IS_ATTRIBUTE(attributes, TPMA_NV, PLATFORMCREATE) + && in->authHandle == TPM_RH_OWNER) + || (!IS_ATTRIBUTE(attributes, TPMA_NV, PLATFORMCREATE) + && in->authHandle == TPM_RH_PLATFORM)) + return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_authHandle; + + // If TPMA_NV_POLICY_DELETE is SET, then the index must be defined by + // the platform + if(IS_ATTRIBUTE(attributes, TPMA_NV, POLICY_DELETE) + && TPM_RH_PLATFORM != in->authHandle) + return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; + + // Make sure that the TPMA_NV_WRITEALL is not set if the index size is larger + // than the allowed NV buffer size. + if(in->publicInfo.nvPublic.dataSize > MAX_NV_BUFFER_SIZE + && IS_ATTRIBUTE(attributes, TPMA_NV, WRITEALL)) + return TPM_RCS_SIZE + RC_NV_DefineSpace_publicInfo; + + // And finally, see if the index is already defined. + if(NvIndexIsDefined(in->publicInfo.nvPublic.nvIndex)) + return TPM_RC_NV_DEFINED; + + // Internal Data Update + // define the space. A TPM_RC_NV_SPACE error may be returned at this point + return NvDefineIndex(&in->publicInfo.nvPublic, &in->auth); +} + +#endif // CC_NV_DefineSpace \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_Extend.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_Extend.c new file mode 100644 index 0000000..ee8910f --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_Extend.c @@ -0,0 +1,107 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "NV_Extend_fp.h" + +#if CC_NV_Extend // Conditional expansion of this file + +/*(See part 3 specification) +// Write to a NV index +*/ +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES the TPMA_NV_EXTEND attribute is not SET in +// the Index referenced by 'nvIndex' +// TPM_RC_NV_AUTHORIZATION the authorization was valid but the +// authorizing entity ('authHandle') +// is not allowed to write to the Index +// referenced by 'nvIndex' +// TPM_RC_NV_LOCKED the Index referenced by 'nvIndex' is locked +// for writing +TPM_RC +TPM2_NV_Extend(NV_Extend_In* in // IN: input parameter list +) +{ + TPM_RC result; + NV_REF locator; + NV_INDEX* nvIndex = NvGetIndexInfo(in->nvIndex, &locator); + + TPM2B_DIGEST oldDigest; + TPM2B_DIGEST newDigest; + HASH_STATE hashState; + + // Input Validation + + // Common access checks, NvWriteAccessCheck() may return TPM_RC_NV_AUTHORIZATION + // or TPM_RC_NV_LOCKED + result = NvWriteAccessChecks( + in->authHandle, in->nvIndex, nvIndex->publicArea.attributes); + if(result != TPM_RC_SUCCESS) + return result; + + // Make sure that this is an extend index + if(!IsNvExtendIndex(nvIndex->publicArea.attributes)) + return TPM_RCS_ATTRIBUTES + RC_NV_Extend_nvIndex; + + // Internal Data Update + + // Perform the write. + oldDigest.t.size = CryptHashGetDigestSize(nvIndex->publicArea.nameAlg); + pAssert(oldDigest.t.size <= sizeof(oldDigest.t.buffer)); + if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN)) + { + NvGetIndexData(nvIndex, locator, 0, oldDigest.t.size, oldDigest.t.buffer); + } + else + { + MemorySet(oldDigest.t.buffer, 0, oldDigest.t.size); + } + // Start hash + newDigest.t.size = CryptHashStart(&hashState, nvIndex->publicArea.nameAlg); + + // Adding old digest + CryptDigestUpdate2B(&hashState, &oldDigest.b); + + // Adding new data + CryptDigestUpdate2B(&hashState, &in->data.b); + + // Complete hash + CryptHashEnd2B(&hashState, &newDigest.b); + + // Write extended hash back. + // Note, this routine will SET the TPMA_NV_WRITTEN attribute if necessary + return NvWriteIndexData(nvIndex, 0, newDigest.t.size, newDigest.t.buffer); +} + +#endif // CC_NV_Extend \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_GlobalWriteLock.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_GlobalWriteLock.c new file mode 100644 index 0000000..7b03a41 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_GlobalWriteLock.c @@ -0,0 +1,56 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "NV_GlobalWriteLock_fp.h" + +#if CC_NV_GlobalWriteLock // Conditional expansion of this file + +/*(See part 3 specification) +// Set global write lock for NV index +*/ +TPM_RC +TPM2_NV_GlobalWriteLock(NV_GlobalWriteLock_In* in // IN: input parameter list +) +{ + // Input parameter (the authorization handle) is not reference in command action. + NOT_REFERENCED(in); + + // Internal Data Update + + // Implementation dependent method of setting the global lock + return NvSetGlobalLock(); +} + +#endif // CC_NV_GlobalWriteLock \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_Increment.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_Increment.c new file mode 100644 index 0000000..ddf64e4 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_Increment.c @@ -0,0 +1,100 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "NV_Increment_fp.h" + +#if CC_NV_Increment // Conditional expansion of this file + +/*(See part 3 specification) +// Increment a NV counter +*/ +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES NV index is not a counter +// TPM_RC_NV_AUTHORIZATION authorization failure +// TPM_RC_NV_LOCKED Index is write locked +TPM_RC +TPM2_NV_Increment(NV_Increment_In* in // IN: input parameter list +) +{ + TPM_RC result; + NV_REF locator; + NV_INDEX* nvIndex = NvGetIndexInfo(in->nvIndex, &locator); + UINT64 countValue; + + // Input Validation + + // Common access checks, NvWriteAccessCheck() may return TPM_RC_NV_AUTHORIZATION + // or TPM_RC_NV_LOCKED + result = NvWriteAccessChecks( + in->authHandle, in->nvIndex, nvIndex->publicArea.attributes); + if(result != TPM_RC_SUCCESS) + return result; + + // Make sure that this is a counter + if(!IsNvCounterIndex(nvIndex->publicArea.attributes)) + return TPM_RCS_ATTRIBUTES + RC_NV_Increment_nvIndex; + + // Internal Data Update + + // If counter index is not been written, initialize it + if(!IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN)) + countValue = NvReadMaxCount(); + else + // Read NV data in native format for TPM CPU. + countValue = NvGetUINT64Data(nvIndex, locator); + + // Do the increment + countValue++; + + // Write NV data back. A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may + // be returned at this point. If necessary, this function will set the + // TPMA_NV_WRITTEN attribute + result = NvWriteUINT64Data(nvIndex, countValue); + if(result == TPM_RC_SUCCESS) + { + // If a counter just rolled over, then force the NV update. + // Note, if this is an orderly counter, then the write-back needs to be + // forced, for other counters, the write-back will happen anyway + if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, ORDERLY) + && (countValue & MAX_ORDERLY_COUNT) == 0) + { + // Need to force an NV update of orderly data + SET_NV_UPDATE(UT_ORDERLY); + } + } + return result; +} + +#endif // CC_NV_Increment \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_Read.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_Read.c new file mode 100644 index 0000000..f5a4e22 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_Read.c @@ -0,0 +1,96 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "NV_Read_fp.h" + +#if CC_NV_Read // Conditional expansion of this file + +/*(See part 3 specification) +// Read of an NV index +*/ +// Return Type: TPM_RC +// TPM_RC_NV_AUTHORIZATION the authorization was valid but the +// authorizing entity ('authHandle') +// is not allowed to read from the Index +// referenced by 'nvIndex' +// TPM_RC_NV_LOCKED the Index referenced by 'nvIndex' is +// read locked +// TPM_RC_NV_RANGE read range defined by 'size' and 'offset' +// is outside the range of the Index referenced +// by 'nvIndex' +// TPM_RC_NV_UNINITIALIZED the Index referenced by 'nvIndex' has +// not been initialized (written) +// TPM_RC_VALUE the read size is larger than the +// MAX_NV_BUFFER_SIZE +TPM_RC +TPM2_NV_Read(NV_Read_In* in, // IN: input parameter list + NV_Read_Out* out // OUT: output parameter list +) +{ + NV_REF locator; + NV_INDEX* nvIndex = NvGetIndexInfo(in->nvIndex, &locator); + TPM_RC result; + + // Input Validation + // Common read access checks. NvReadAccessChecks() may return + // TPM_RC_NV_AUTHORIZATION, TPM_RC_NV_LOCKED, or TPM_RC_NV_UNINITIALIZED + result = NvReadAccessChecks( + in->authHandle, in->nvIndex, nvIndex->publicArea.attributes); + if(result != TPM_RC_SUCCESS) + return result; + + // Make sure the data will fit the return buffer + if(in->size > MAX_NV_BUFFER_SIZE) + return TPM_RCS_VALUE + RC_NV_Read_size; + + // Verify that the offset is not too large + if(in->offset > nvIndex->publicArea.dataSize) + return TPM_RCS_VALUE + RC_NV_Read_offset; + + // Make sure that the selection is within the range of the Index + if(in->size > (nvIndex->publicArea.dataSize - in->offset)) + return TPM_RC_NV_RANGE; + + // Command Output + // Set the return size + out->data.t.size = in->size; + + // Perform the read + NvGetIndexData(nvIndex, locator, in->offset, in->size, out->data.t.buffer); + + return TPM_RC_SUCCESS; +} + +#endif // CC_NV_Read \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_ReadLock.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_ReadLock.c new file mode 100644 index 0000000..f550e60 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_ReadLock.c @@ -0,0 +1,88 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "NV_ReadLock_fp.h" + +#if CC_NV_ReadLock // Conditional expansion of this file + +/*(See part 3 specification) +// Set read lock on a NV index +*/ +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES TPMA_NV_READ_STCLEAR is not SET so +// Index referenced by 'nvIndex' may not be +// write locked +// TPM_RC_NV_AUTHORIZATION the authorization was valid but the +// authorizing entity ('authHandle') +// is not allowed to read from the Index +// referenced by 'nvIndex' +TPM_RC +TPM2_NV_ReadLock(NV_ReadLock_In* in // IN: input parameter list +) +{ + TPM_RC result; + NV_REF locator; + // The referenced index has been checked multiple times before this is called + // so it must be present and will be loaded into cache + NV_INDEX* nvIndex = NvGetIndexInfo(in->nvIndex, &locator); + TPMA_NV nvAttributes = nvIndex->publicArea.attributes; + + // Input Validation + // Common read access checks. NvReadAccessChecks() may return + // TPM_RC_NV_AUTHORIZATION, TPM_RC_NV_LOCKED, or TPM_RC_NV_UNINITIALIZED + result = NvReadAccessChecks(in->authHandle, in->nvIndex, nvAttributes); + if(result == TPM_RC_NV_AUTHORIZATION) + return TPM_RC_NV_AUTHORIZATION; + // Index is already locked for write + else if(result == TPM_RC_NV_LOCKED) + return TPM_RC_SUCCESS; + + // If NvReadAccessChecks return TPM_RC_NV_UNINITALIZED, then continue. + // It is not an error to read lock an uninitialized Index. + + // if TPMA_NV_READ_STCLEAR is not set, the index can not be read-locked + if(!IS_ATTRIBUTE(nvAttributes, TPMA_NV, READ_STCLEAR)) + return TPM_RCS_ATTRIBUTES + RC_NV_ReadLock_nvIndex; + + // Internal Data Update + + // Set the READLOCK attribute + SET_ATTRIBUTE(nvAttributes, TPMA_NV, READLOCKED); + + // Write NV info back + return NvWriteIndexAttributes(nvIndex->publicArea.nvIndex, locator, nvAttributes); +} + +#endif // CC_NV_ReadLock \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_ReadPublic.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_ReadPublic.c new file mode 100644 index 0000000..09e9786 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_ReadPublic.c @@ -0,0 +1,61 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "NV_ReadPublic_fp.h" + +#if CC_NV_ReadPublic // Conditional expansion of this file + +/*(See part 3 specification) +// Read the public information of a NV index +*/ +TPM_RC +TPM2_NV_ReadPublic(NV_ReadPublic_In* in, // IN: input parameter list + NV_ReadPublic_Out* out // OUT: output parameter list +) +{ + NV_INDEX* nvIndex = NvGetIndexInfo(in->nvIndex, NULL); + + // Command Output + + // Copy index public data to output + out->nvPublic.nvPublic = nvIndex->publicArea; + + // Compute NV name + NvGetIndexName(nvIndex, &out->nvName); + + return TPM_RC_SUCCESS; +} + +#endif // CC_NV_ReadPublic \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_SetBits.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_SetBits.c new file mode 100644 index 0000000..5dfb8b7 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_SetBits.c @@ -0,0 +1,89 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "NV_SetBits_fp.h" + +#if CC_NV_SetBits // Conditional expansion of this file + +/*(See part 3 specification) +// Set bits in a NV index +*/ +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES the TPMA_NV_BITS attribute is not SET in the +// Index referenced by 'nvIndex' +// TPM_RC_NV_AUTHORIZATION the authorization was valid but the +// authorizing entity ('authHandle') +// is not allowed to write to the Index +// referenced by 'nvIndex' +// TPM_RC_NV_LOCKED the Index referenced by 'nvIndex' is locked +// for writing +TPM_RC +TPM2_NV_SetBits(NV_SetBits_In* in // IN: input parameter list +) +{ + TPM_RC result; + NV_REF locator; + NV_INDEX* nvIndex = NvGetIndexInfo(in->nvIndex, &locator); + UINT64 oldValue; + UINT64 newValue; + + // Input Validation + + // Common access checks, NvWriteAccessCheck() may return TPM_RC_NV_AUTHORIZATION + // or TPM_RC_NV_LOCKED + result = NvWriteAccessChecks( + in->authHandle, in->nvIndex, nvIndex->publicArea.attributes); + if(result != TPM_RC_SUCCESS) + return result; + + // Make sure that this is a bit field + if(!IsNvBitsIndex(nvIndex->publicArea.attributes)) + return TPM_RCS_ATTRIBUTES + RC_NV_SetBits_nvIndex; + + // If index is not been written, initialize it + if(!IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN)) + oldValue = 0; + else + // Read index data + oldValue = NvGetUINT64Data(nvIndex, locator); + + // Figure out what the new value is going to be + newValue = oldValue | in->bits; + + // Internal Data Update + return NvWriteUINT64Data(nvIndex, newValue); +} + +#endif // CC_NV_SetBits \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_UndefineSpace.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_UndefineSpace.c new file mode 100644 index 0000000..71da9a8 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_UndefineSpace.c @@ -0,0 +1,75 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "NV_UndefineSpace_fp.h" + +#if CC_NV_UndefineSpace // Conditional expansion of this file + +/*(See part 3 specification) +// Delete an NV Index +*/ +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES TPMA_NV_POLICY_DELETE is SET in the Index +// referenced by 'nvIndex' so this command may +// not be used to delete this Index (see +// TPM2_NV_UndefineSpaceSpecial()) +// TPM_RC_NV_AUTHORIZATION attempt to use ownerAuth to delete an index +// created by the platform +// +TPM_RC +TPM2_NV_UndefineSpace(NV_UndefineSpace_In* in // IN: input parameter list +) +{ + NV_REF locator; + NV_INDEX* nvIndex = NvGetIndexInfo(in->nvIndex, &locator); + + // Input Validation + // This command can't be used to delete an index with TPMA_NV_POLICY_DELETE SET + if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, POLICY_DELETE)) + return TPM_RCS_ATTRIBUTES + RC_NV_UndefineSpace_nvIndex; + + // The owner may only delete an index that was defined with ownerAuth. The + // platform may delete an index that was created with either authorization. + if(in->authHandle == TPM_RH_OWNER + && IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, PLATFORMCREATE)) + return TPM_RC_NV_AUTHORIZATION; + + // Internal Data Update + + // Call implementation dependent internal routine to delete NV index + return NvDeleteIndex(nvIndex, locator); +} + +#endif // CC_NV_UndefineSpace \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_UndefineSpaceSpecial.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_UndefineSpaceSpecial.c new file mode 100644 index 0000000..1340b78 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_UndefineSpaceSpecial.c @@ -0,0 +1,71 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "NV_UndefineSpaceSpecial_fp.h" +#include "SessionProcess_fp.h" + +#if CC_NV_UndefineSpaceSpecial // Conditional expansion of this file + +/*(See part 3 specification) +// Delete a NV index that requires policy to delete. +*/ +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES TPMA_NV_POLICY_DELETE is not SET in the +// Index referenced by 'nvIndex' +TPM_RC +TPM2_NV_UndefineSpaceSpecial( + NV_UndefineSpaceSpecial_In* in // IN: input parameter list +) +{ + TPM_RC result; + NV_REF locator; + NV_INDEX* nvIndex = NvGetIndexInfo(in->nvIndex, &locator); + // Input Validation + // This operation only applies when the TPMA_NV_POLICY_DELETE attribute is SET + if(!IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, POLICY_DELETE)) + return TPM_RCS_ATTRIBUTES + RC_NV_UndefineSpaceSpecial_nvIndex; + // Internal Data Update + // Call implementation dependent internal routine to delete NV index + result = NvDeleteIndex(nvIndex, locator); + + // If we just removed the index providing the authorization, make sure that the + // authorization session computation is modified so that it doesn't try to + // access the authValue of the just deleted index + if(result == TPM_RC_SUCCESS) + SessionRemoveAssociationToHandle(in->nvIndex); + return result; +} + +#endif // CC_NV_UndefineSpaceSpecial \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_Write.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_Write.c new file mode 100644 index 0000000..72f2bf0 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_Write.c @@ -0,0 +1,104 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "NV_Write_fp.h" + +#if CC_NV_Write // Conditional expansion of this file + +/*(See part 3 specification) +// Write to a NV index +*/ +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES Index referenced by 'nvIndex' has either +// TPMA_NV_BITS, TPMA_NV_COUNTER, or +// TPMA_NV_EVENT attribute SET +// TPM_RC_NV_AUTHORIZATION the authorization was valid but the +// authorizing entity ('authHandle') +// is not allowed to write to the Index +// referenced by 'nvIndex' +// TPM_RC_NV_LOCKED Index referenced by 'nvIndex' is write +// locked +// TPM_RC_NV_RANGE if TPMA_NV_WRITEALL is SET then the write +// is not the size of the Index referenced by +// 'nvIndex'; otherwise, the write extends +// beyond the limits of the Index +// +TPM_RC +TPM2_NV_Write(NV_Write_In* in // IN: input parameter list +) +{ + NV_INDEX* nvIndex = NvGetIndexInfo(in->nvIndex, NULL); + TPMA_NV attributes = nvIndex->publicArea.attributes; + TPM_RC result; + + // Input Validation + + // Common access checks, NvWriteAccessCheck() may return TPM_RC_NV_AUTHORIZATION + // or TPM_RC_NV_LOCKED + result = NvWriteAccessChecks(in->authHandle, in->nvIndex, attributes); + if(result != TPM_RC_SUCCESS) + return result; + + // Bits index, extend index or counter index may not be updated by + // TPM2_NV_Write + if(IsNvCounterIndex(attributes) || IsNvBitsIndex(attributes) + || IsNvExtendIndex(attributes)) + return TPM_RC_ATTRIBUTES; + + // Make sure that the offset is not too large + if(in->offset > nvIndex->publicArea.dataSize) + return TPM_RCS_VALUE + RC_NV_Write_offset; + + // Make sure that the selection is within the range of the Index + if(in->data.t.size > (nvIndex->publicArea.dataSize - in->offset)) + return TPM_RC_NV_RANGE; + + // If this index requires a full sized write, make sure that input range is + // full sized. + // Note: if the requested size is the same as the Index data size, then offset + // will have to be zero. Otherwise, the range check above would have failed. + if(IS_ATTRIBUTE(attributes, TPMA_NV, WRITEALL) + && in->data.t.size < nvIndex->publicArea.dataSize) + return TPM_RC_NV_RANGE; + + // Internal Data Update + + // Perform the write. This called routine will SET the TPMA_NV_WRITTEN + // attribute if it has not already been SET. If NV isn't available, an error + // will be returned. + return NvWriteIndexData(nvIndex, in->offset, in->data.t.size, in->data.t.buffer); +} + +#endif // CC_NV_Write \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_WriteLock.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_WriteLock.c new file mode 100644 index 0000000..3974f16 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_WriteLock.c @@ -0,0 +1,89 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "NV_WriteLock_fp.h" + +#if CC_NV_WriteLock // Conditional expansion of this file + +/*(See part 3 specification) +// Set write lock on a NV index +*/ +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES neither TPMA_NV_WRITEDEFINE nor +// TPMA_NV_WRITE_STCLEAR is SET in Index +// referenced by 'nvIndex' +// TPM_RC_NV_AUTHORIZATION the authorization was valid but the +// authorizing entity ('authHandle') +// is not allowed to write to the Index +// referenced by 'nvIndex' +// +TPM_RC +TPM2_NV_WriteLock(NV_WriteLock_In* in // IN: input parameter list +) +{ + TPM_RC result; + NV_REF locator; + NV_INDEX* nvIndex = NvGetIndexInfo(in->nvIndex, &locator); + TPMA_NV nvAttributes = nvIndex->publicArea.attributes; + + // Input Validation: + + // Common access checks, NvWriteAccessCheck() may return TPM_RC_NV_AUTHORIZATION + // or TPM_RC_NV_LOCKED + result = NvWriteAccessChecks(in->authHandle, in->nvIndex, nvAttributes); + if(result != TPM_RC_SUCCESS) + { + if(result == TPM_RC_NV_AUTHORIZATION) + return result; + // If write access failed because the index is already locked, then it is + // no error. + return TPM_RC_SUCCESS; + } + // if neither TPMA_NV_WRITEDEFINE nor TPMA_NV_WRITE_STCLEAR is set, the index + // can not be write-locked + if(!IS_ATTRIBUTE(nvAttributes, TPMA_NV, WRITEDEFINE) + && !IS_ATTRIBUTE(nvAttributes, TPMA_NV, WRITE_STCLEAR)) + return TPM_RCS_ATTRIBUTES + RC_NV_WriteLock_nvIndex; + // Internal Data Update + // Set the WRITELOCK attribute. + // Note: if TPMA_NV_WRITELOCKED were already SET, then the write access check + // above would have failed and this code isn't executed. + SET_ATTRIBUTE(nvAttributes, TPMA_NV, WRITELOCKED); + + // Write index info back + return NvWriteIndexAttributes(nvIndex->publicArea.nvIndex, locator, nvAttributes); +} + +#endif // CC_NV_WriteLock \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_spt.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_spt.c new file mode 100644 index 0000000..afd2ba2 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/NVStorage/NV_spt.c @@ -0,0 +1,158 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Includes +#include "Tpm.h" +#include "NV_spt_fp.h" + +//** Functions + +//*** NvReadAccessChecks() +// Common routine for validating a read +// Used by TPM2_NV_Read, TPM2_NV_ReadLock and TPM2_PolicyNV +// Return Type: TPM_RC +// TPM_RC_NV_AUTHORIZATION autHandle is not allowed to authorize read +// of the index +// TPM_RC_NV_LOCKED Read locked +// TPM_RC_NV_UNINITIALIZED Try to read an uninitialized index +// +TPM_RC +NvReadAccessChecks(TPM_HANDLE authHandle, // IN: the handle that provided the + // authorization + TPM_HANDLE nvHandle, // IN: the handle of the NV index to be read + TPMA_NV attributes // IN: the attributes of 'nvHandle' +) +{ + // If data is read locked, returns an error + if(IS_ATTRIBUTE(attributes, TPMA_NV, READLOCKED)) + return TPM_RC_NV_LOCKED; + // If the authorization was provided by the owner or platform, then check + // that the attributes allow the read. If the authorization handle + // is the same as the index, then the checks were made when the authorization + // was checked.. + if(authHandle == TPM_RH_OWNER) + { + // If Owner provided authorization then ONWERWRITE must be SET + if(!IS_ATTRIBUTE(attributes, TPMA_NV, OWNERREAD)) + return TPM_RC_NV_AUTHORIZATION; + } + else if(authHandle == TPM_RH_PLATFORM) + { + // If Platform provided authorization then PPWRITE must be SET + if(!IS_ATTRIBUTE(attributes, TPMA_NV, PPREAD)) + return TPM_RC_NV_AUTHORIZATION; + } + // If neither Owner nor Platform provided authorization, make sure that it was + // provided by this index. + else if(authHandle != nvHandle) + return TPM_RC_NV_AUTHORIZATION; + + // If the index has not been written, then the value cannot be read + // NOTE: This has to come after other access checks to make sure that + // the proper authorization is given to TPM2_NV_ReadLock() + if(!IS_ATTRIBUTE(attributes, TPMA_NV, WRITTEN)) + return TPM_RC_NV_UNINITIALIZED; + + return TPM_RC_SUCCESS; +} + +//*** NvWriteAccessChecks() +// Common routine for validating a write +// Used by TPM2_NV_Write, TPM2_NV_Increment, TPM2_SetBits, and TPM2_NV_WriteLock +// Return Type: TPM_RC +// TPM_RC_NV_AUTHORIZATION Authorization fails +// TPM_RC_NV_LOCKED Write locked +// +TPM_RC +NvWriteAccessChecks( + TPM_HANDLE authHandle, // IN: the handle that provided the + // authorization + TPM_HANDLE nvHandle, // IN: the handle of the NV index to be written + TPMA_NV attributes // IN: the attributes of 'nvHandle' +) +{ + // If data is write locked, returns an error + if(IS_ATTRIBUTE(attributes, TPMA_NV, WRITELOCKED)) + return TPM_RC_NV_LOCKED; + // If the authorization was provided by the owner or platform, then check + // that the attributes allow the write. If the authorization handle + // is the same as the index, then the checks were made when the authorization + // was checked.. + if(authHandle == TPM_RH_OWNER) + { + // If Owner provided authorization then ONWERWRITE must be SET + if(!IS_ATTRIBUTE(attributes, TPMA_NV, OWNERWRITE)) + return TPM_RC_NV_AUTHORIZATION; + } + else if(authHandle == TPM_RH_PLATFORM) + { + // If Platform provided authorization then PPWRITE must be SET + if(!IS_ATTRIBUTE(attributes, TPMA_NV, PPWRITE)) + return TPM_RC_NV_AUTHORIZATION; + } + // If neither Owner nor Platform provided authorization, make sure that it was + // provided by this index. + else if(authHandle != nvHandle) + return TPM_RC_NV_AUTHORIZATION; + return TPM_RC_SUCCESS; +} + +//*** NvClearOrderly() +// This function is used to cause gp.orderlyState to be cleared to the +// non-orderly state. +TPM_RC +NvClearOrderly(void) +{ + if(gp.orderlyState < SU_DA_USED_VALUE) + RETURN_IF_NV_IS_NOT_AVAILABLE; + g_clearOrderly = TRUE; + return TPM_RC_SUCCESS; +} + +//*** NvIsPinPassIndex() +// Function to check to see if an NV index is a PIN Pass Index +// Return Type: BOOL +// TRUE(1) is pin pass +// FALSE(0) is not pin pass +BOOL NvIsPinPassIndex(TPM_HANDLE index // IN: Handle to check +) +{ + if(HandleGetType(index) == TPM_HT_NV_INDEX) + { + NV_INDEX* nvIndex = NvGetIndexInfo(index, NULL); + + return IsNvPinPassIndex(nvIndex->publicArea.attributes); + } + return FALSE; +} diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/ActivateCredential.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/ActivateCredential.c new file mode 100644 index 0000000..3d4e529 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/ActivateCredential.c @@ -0,0 +1,105 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "ActivateCredential_fp.h" + +#if CC_ActivateCredential // Conditional expansion of this file + +# include "Object_spt_fp.h" + +/*(See part 3 specification) +// Activate Credential with an object +*/ +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES 'keyHandle' does not reference a decryption key +// TPM_RC_ECC_POINT 'secret' is invalid (when 'keyHandle' is an ECC key) +// TPM_RC_INSUFFICIENT 'secret' is invalid (when 'keyHandle' is an ECC key) +// TPM_RC_INTEGRITY 'credentialBlob' fails integrity test +// TPM_RC_NO_RESULT 'secret' is invalid (when 'keyHandle' is an ECC key) +// TPM_RC_SIZE 'secret' size is invalid or the 'credentialBlob' +// does not unmarshal correctly +// TPM_RC_TYPE 'keyHandle' does not reference an asymmetric key. +// TPM_RC_VALUE 'secret' is invalid (when 'keyHandle' is an RSA key) +TPM_RC +TPM2_ActivateCredential(ActivateCredential_In* in, // IN: input parameter list + ActivateCredential_Out* out // OUT: output parameter list +) +{ + TPM_RC result = TPM_RC_SUCCESS; + OBJECT* object; // decrypt key + OBJECT* activateObject; // key associated with credential + TPM2B_DATA data; // credential data + + // Input Validation + + // Get decrypt key pointer + object = HandleToObject(in->keyHandle); + + // Get certificated object pointer + activateObject = HandleToObject(in->activateHandle); + + // input decrypt key must be an asymmetric, restricted decryption key + if(!CryptIsAsymAlgorithm(object->publicArea.type) + || !IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, decrypt) + || !IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, restricted)) + return TPM_RCS_TYPE + RC_ActivateCredential_keyHandle; + + // Command output + + // Decrypt input credential data via asymmetric decryption. A + // TPM_RC_VALUE, TPM_RC_KEY or unmarshal errors may be returned at this + // point + result = CryptSecretDecrypt(object, NULL, IDENTITY_STRING, &in->secret, &data); + if(result != TPM_RC_SUCCESS) + { + if(result == TPM_RC_KEY) + return TPM_RC_FAILURE; + return RcSafeAddToResult(result, RC_ActivateCredential_secret); + } + + // Retrieve secret data. A TPM_RC_INTEGRITY error or unmarshal + // errors may be returned at this point + result = CredentialToSecret(&in->credentialBlob.b, + &activateObject->name.b, + &data.b, + object, + &out->certInfo); + if(result != TPM_RC_SUCCESS) + return RcSafeAddToResult(result, RC_ActivateCredential_credentialBlob); + + return TPM_RC_SUCCESS; +} + +#endif // CC_ActivateCredential \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/Create.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/Create.c new file mode 100644 index 0000000..07722a1 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/Create.c @@ -0,0 +1,161 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "Object_spt_fp.h" +#include "Create_fp.h" + +#if CC_Create // Conditional expansion of this file + +/*(See part 3 specification) +// Create a regular object +*/ +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES 'sensitiveDataOrigin' is CLEAR when 'sensitive.data' +// is an Empty Buffer, or is SET when 'sensitive.data' is +// not empty; +// 'fixedTPM', 'fixedParent', or 'encryptedDuplication' +// attributes are inconsistent between themselves or with +// those of the parent object; +// inconsistent 'restricted', 'decrypt' and 'sign' +// attributes; +// attempt to inject sensitive data for an asymmetric +// key; +// TPM_RC_HASH non-duplicable storage key and its parent have +// different name algorithm +// TPM_RC_KDF incorrect KDF specified for decrypting keyed hash +// object +// TPM_RC_KEY invalid key size values in an asymmetric key public +// area or a provided symmetric key has a value that is +// not allowed +// TPM_RC_KEY_SIZE key size in public area for symmetric key differs from +// the size in the sensitive creation area; may also be +// returned if the TPM does not allow the key size to be +// used for a Storage Key +// TPM_RC_OBJECT_MEMORY a free slot is not available as scratch memory for +// object creation +// TPM_RC_RANGE the exponent value of an RSA key is not supported. +// TPM_RC_SCHEME inconsistent attributes 'decrypt', 'sign', or +// 'restricted' and key's scheme ID; or hash algorithm is +// inconsistent with the scheme ID for keyed hash object +// TPM_RC_SIZE size of public authPolicy or sensitive authValue does +// not match digest size of the name algorithm +// sensitive data size for the keyed hash object is +// larger than is allowed for the scheme +// TPM_RC_SYMMETRIC a storage key with no symmetric algorithm specified; +// or non-storage key with symmetric algorithm different +// from TPM_ALG_NULL +// TPM_RC_TYPE unknown object type; +// 'parentHandle' does not reference a restricted +// decryption key in the storage hierarchy with both +// public and sensitive portion loaded +// TPM_RC_VALUE exponent is not prime or could not find a prime using +// the provided parameters for an RSA key; +// unsupported name algorithm for an ECC key +// TPM_RC_OBJECT_MEMORY there is no free slot for the object +TPM_RC +TPM2_Create(Create_In* in, // IN: input parameter list + Create_Out* out // OUT: output parameter list +) +{ + TPM_RC result = TPM_RC_SUCCESS; + OBJECT* parentObject; + OBJECT* newObject; + TPMT_PUBLIC* publicArea; + + // Input Validation + parentObject = HandleToObject(in->parentHandle); + pAssert(parentObject != NULL); + + // Does parent have the proper attributes? + if(!ObjectIsParent(parentObject)) + return TPM_RCS_TYPE + RC_Create_parentHandle; + + // Get a slot for the creation + newObject = FindEmptyObjectSlot(NULL); + if(newObject == NULL) + return TPM_RC_OBJECT_MEMORY; + // If the TPM2B_PUBLIC was passed as a structure, marshal it into is canonical + // form for processing + + // to save typing. + publicArea = &newObject->publicArea; + + // Copy the input structure to the allocated structure + *publicArea = in->inPublic.publicArea; + + // Check attributes in input public area. CreateChecks() checks the things that + // are unique to creation and then validates the attributes and values that are + // common to create and load. + result = + CreateChecks(parentObject, publicArea, in->inSensitive.sensitive.data.t.size); + if(result != TPM_RC_SUCCESS) + return RcSafeAddToResult(result, RC_Create_inPublic); + // Clean up the authValue if necessary + if(!AdjustAuthSize(&in->inSensitive.sensitive.userAuth, publicArea->nameAlg)) + return TPM_RCS_SIZE + RC_Create_inSensitive; + + // Command Output + // Create the object using the default TPM random-number generator + result = CryptCreateObject(newObject, &in->inSensitive.sensitive, NULL); + if(result != TPM_RC_SUCCESS) + return result; + // Fill in creation data + FillInCreationData(in->parentHandle, + publicArea->nameAlg, + &in->creationPCR, + &in->outsideInfo, + &out->creationData, + &out->creationHash); + + // Compute creation ticket + TicketComputeCreation(EntityGetHierarchy(in->parentHandle), + &newObject->name, + &out->creationHash, + &out->creationTicket); + + // Prepare output private data from sensitive + SensitiveToPrivate(&newObject->sensitive, + &newObject->name, + parentObject, + publicArea->nameAlg, + &out->outPrivate); + + // Finish by copying the remaining return values + out->outPublic.publicArea = newObject->publicArea; + + return TPM_RC_SUCCESS; +} + +#endif // CC_Create \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/CreateLoaded.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/CreateLoaded.c new file mode 100644 index 0000000..b1d001c --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/CreateLoaded.c @@ -0,0 +1,221 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "CreateLoaded_fp.h" + +#if CC_CreateLoaded // Conditional expansion of this file + +/*(See part 3 of specification) + * Create and load any type of key, including a temporary key. + * The input template is a marshaled public area rather than an unmarshaled one as + * used in Create and CreatePrimary. This is so that the label and context that + * could be in the template can be processed without changing the formats for the + * calls to Create and CreatePrimary. +*/ +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES 'sensitiveDataOrigin' is CLEAR when 'sensitive.data' +// is an Empty Buffer; +// 'fixedTPM', 'fixedParent', or 'encryptedDuplication' +// attributes are inconsistent between themselves or with +// those of the parent object; +// inconsistent 'restricted', 'decrypt' and 'sign' +// attributes; +// attempt to inject sensitive data for an asymmetric +// key; +// attempt to create a symmetric cipher key that is not +// a decryption key +// TPM_RC_KDF incorrect KDF specified for decrypting keyed hash +// object +// TPM_RC_KEY the value of a provided symmetric key is not allowed +// TPM_RC_OBJECT_MEMORY there is no free slot for the object +// TPM_RC_SCHEME inconsistent attributes 'decrypt', 'sign', +// 'restricted' and key's scheme ID; or hash algorithm is +// inconsistent with the scheme ID for keyed hash object +// TPM_RC_SIZE size of public authorization policy or sensitive +// authorization value does not match digest size of the +// name algorithm sensitive data size for the keyed hash +// object is larger than is allowed for the scheme +// TPM_RC_SYMMETRIC a storage key with no symmetric algorithm specified; +// or non-storage key with symmetric algorithm different +// from TPM_ALG_NULL +// TPM_RC_TYPE cannot create the object of the indicated type +// (usually only occurs if trying to derive an RSA key). +TPM_RC +TPM2_CreateLoaded(CreateLoaded_In* in, // IN: input parameter list + CreateLoaded_Out* out // OUT: output parameter list +) +{ + TPM_RC result = TPM_RC_SUCCESS; + OBJECT* parent = HandleToObject(in->parentHandle); + OBJECT* newObject; + BOOL derivation; + TPMT_PUBLIC* publicArea; + RAND_STATE randState; + RAND_STATE* rand = &randState; + TPMS_DERIVE labelContext; + + // Input Validation + + // How the public area is unmarshaled is determined by the parent, so + // see if parent is a derivation parent + derivation = (parent != NULL && parent->attributes.derivation); + + // If the parent is an object, then make sure that it is either a parent or + // derivation parent + if(parent != NULL && !parent->attributes.isParent && !derivation) + return TPM_RCS_TYPE + RC_CreateLoaded_parentHandle; + + // Get a spot in which to create the newObject + newObject = FindEmptyObjectSlot(&out->objectHandle); + if(newObject == NULL) + return TPM_RC_OBJECT_MEMORY; + + // Do this to save typing + publicArea = &newObject->publicArea; + + // Unmarshal the template into the object space. TPM2_Create() and + // TPM2_CreatePrimary() have the publicArea unmarshaled by CommandDispatcher. + // This command is different because of an unfortunate property of the + // unique field of an ECC key. It is a structure rather than a single TPM2B. If + // if had been a TPM2B, then the label and context could be within a TPM2B and + // unmarshaled like other public areas. Since it is not, this command needs its + // on template that is a TPM2B that is unmarshaled as a BYTE array with a + // its own unmarshal function. + result = UnmarshalToPublic(publicArea, &in->inPublic, derivation, &labelContext); + if(result != TPM_RC_SUCCESS) + return result + RC_CreateLoaded_inPublic; + + // Validate that the authorization size is appropriate + if(!AdjustAuthSize(&in->inSensitive.sensitive.userAuth, publicArea->nameAlg)) + return TPM_RCS_SIZE + RC_CreateLoaded_inSensitive; + + // Command output + if(derivation) + { + TPMT_KEYEDHASH_SCHEME* scheme; + scheme = &parent->publicArea.parameters.keyedHashDetail.scheme; + + // SP800-108 is the only KDF supported by this implementation and there is + // no default hash algorithm. + pAssert(scheme->details.xor.hashAlg != TPM_ALG_NULL + && scheme->details.xor.kdf == TPM_ALG_KDF1_SP800_108); + // Don't derive RSA keys + if(publicArea->type == TPM_ALG_RSA) + return TPM_RCS_TYPE + RC_CreateLoaded_inPublic; + // sensitiveDataOrigin has to be CLEAR in a derived object. Since this + // is specific to a derived object, it is checked here. + if(IS_ATTRIBUTE( + publicArea->objectAttributes, TPMA_OBJECT, sensitiveDataOrigin)) + return TPM_RCS_ATTRIBUTES; + // Check the reset of the attributes + result = PublicAttributesValidation(parent, publicArea); + if(result != TPM_RC_SUCCESS) + return RcSafeAddToResult(result, RC_CreateLoaded_inPublic); + // Process the template and sensitive areas to get the actual 'label' and + // 'context' values to be used for this derivation. + result = SetLabelAndContext(&labelContext, &in->inSensitive.sensitive.data); + if(result != TPM_RC_SUCCESS) + return result; + // Set up the KDF for object generation + DRBG_InstantiateSeededKdf((KDF_STATE*)rand, + scheme->details.xor.hashAlg, + scheme->details.xor.kdf, + &parent->sensitive.sensitive.bits.b, + &labelContext.label.b, + &labelContext.context.b, + TPM_MAX_DERIVATION_BITS); + // Clear the sensitive size so that the creation functions will not try + // to use this value. + in->inSensitive.sensitive.data.t.size = 0; + } + else + { + // Check attributes in input public area. CreateChecks() checks the things + // that are unique to creation and then validates the attributes and values + // that are common to create and load. + result = + CreateChecks(parent, publicArea, in->inSensitive.sensitive.data.t.size); + if(result != TPM_RC_SUCCESS) + return RcSafeAddToResult(result, RC_CreateLoaded_inPublic); + // Creating a primary object + if(parent == NULL) + { + TPM2B_NAME name; + newObject->attributes.primary = SET; + if(in->parentHandle == TPM_RH_ENDORSEMENT) + newObject->attributes.epsHierarchy = SET; + // If so, use the primary seed and the digest of the template + // to seed the DRBG + result = DRBG_InstantiateSeeded( + (DRBG_STATE*)rand, + &HierarchyGetPrimarySeed(in->parentHandle)->b, + PRIMARY_OBJECT_CREATION, + (TPM2B*)PublicMarshalAndComputeName(publicArea, &name), + &in->inSensitive.sensitive.data.b); + if(result != TPM_RC_SUCCESS) + return result; + } + else + { + // This is an ordinary object so use the normal random number generator + rand = NULL; + } + } + // Internal data update + // Create the object + result = CryptCreateObject(newObject, &in->inSensitive.sensitive, rand); + if(result != TPM_RC_SUCCESS) + return result; + // if this is not a Primary key and not a derived key, then return the sensitive + // area + if(parent != NULL && !derivation) + // Prepare output private data from sensitive + SensitiveToPrivate(&newObject->sensitive, + &newObject->name, + parent, + newObject->publicArea.nameAlg, + &out->outPrivate); + else + out->outPrivate.t.size = 0; + // Set the remaining return values + out->outPublic.publicArea = newObject->publicArea; + out->name = newObject->name; + // Set the remaining attributes for a loaded object + ObjectSetLoadedAttributes(newObject, in->parentHandle); + + return result; +} + +#endif // CC_CreateLoaded \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/Load.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/Load.c new file mode 100644 index 0000000..1ee7e5e --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/Load.c @@ -0,0 +1,124 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "Load_fp.h" + +#if CC_Load // Conditional expansion of this file + +# include "Object_spt_fp.h" + +/*(See part 3 specification) +// Load an ordinary or temporary object +*/ +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES 'inPulblic' attributes are not allowed with selected +// parent +// TPM_RC_BINDING 'inPrivate' and 'inPublic' are not +// cryptographically bound +// TPM_RC_HASH incorrect hash selection for signing key or +// the 'nameAlg' for 'inPubic' is not valid +// TPM_RC_INTEGRITY HMAC on 'inPrivate' was not valid +// TPM_RC_KDF KDF selection not allowed +// TPM_RC_KEY the size of the object's 'unique' field is not +// consistent with the indicated size in the object's +// parameters +// TPM_RC_OBJECT_MEMORY no available object slot +// TPM_RC_SCHEME the signing scheme is not valid for the key +// TPM_RC_SENSITIVE the 'inPrivate' did not unmarshal correctly +// TPM_RC_SIZE 'inPrivate' missing, or 'authPolicy' size for +// 'inPublic' or is not valid +// TPM_RC_SYMMETRIC symmetric algorithm not provided when required +// TPM_RC_TYPE 'parentHandle' is not a storage key, or the object +// to load is a storage key but its parameters do not +// match the parameters of the parent. +// TPM_RC_VALUE decryption failure +TPM_RC +TPM2_Load(Load_In* in, // IN: input parameter list + Load_Out* out // OUT: output parameter list +) +{ + TPM_RC result = TPM_RC_SUCCESS; + TPMT_SENSITIVE sensitive; + OBJECT* parentObject; + OBJECT* newObject; + + // Input Validation + // Don't get invested in loading if there is no place to put it. + newObject = FindEmptyObjectSlot(&out->objectHandle); + if(newObject == NULL) + return TPM_RC_OBJECT_MEMORY; + + if(in->inPrivate.t.size == 0) + return TPM_RCS_SIZE + RC_Load_inPrivate; + + parentObject = HandleToObject(in->parentHandle); + pAssert(parentObject != NULL); + // Is the object that is being used as the parent actually a parent. + if(!ObjectIsParent(parentObject)) + return TPM_RCS_TYPE + RC_Load_parentHandle; + + // Compute the name of object. If there isn't one, it is because the nameAlg is + // not valid. + PublicMarshalAndComputeName(&in->inPublic.publicArea, &out->name); + if(out->name.t.size == 0) + return TPM_RCS_HASH + RC_Load_inPublic; + + // Retrieve sensitive data. + result = PrivateToSensitive(&in->inPrivate.b, + &out->name.b, + parentObject, + in->inPublic.publicArea.nameAlg, + &sensitive); + if(result != TPM_RC_SUCCESS) + return RcSafeAddToResult(result, RC_Load_inPrivate); + + // Internal Data Update + // Load and validate object + result = ObjectLoad(newObject, + parentObject, + &in->inPublic.publicArea, + &sensitive, + RC_Load_inPublic, + RC_Load_inPrivate, + &out->name); + if(result == TPM_RC_SUCCESS) + { + // Set the common OBJECT attributes for a loaded object. + ObjectSetLoadedAttributes(newObject, in->parentHandle); + } + return result; +} + +#endif // CC_Load \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/LoadExternal.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/LoadExternal.c new file mode 100644 index 0000000..cab9585 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/LoadExternal.c @@ -0,0 +1,133 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "LoadExternal_fp.h" + +#if CC_LoadExternal // Conditional expansion of this file + +# include "Object_spt_fp.h" + +/*(See part 3 specification) +// to load an object that is not a Protected Object into the public portion +// of an object into the TPM. The command allows loading of a public area or +// both a public and sensitive area +*/ +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES 'fixedParent', 'fixedTPM', and 'restricted' must +// be CLEAR if sensitive portion of an object is loaded +// TPM_RC_BINDING the 'inPublic' and 'inPrivate' structures are not +// cryptographically bound +// TPM_RC_HASH incorrect hash selection for signing key +// TPM_RC_HIERARCHY 'hierarchy' is turned off, or only NULL hierarchy +// is allowed when loading public and private parts +// of an object +// TPM_RC_KDF incorrect KDF selection for decrypting +// keyedHash object +// TPM_RC_KEY the size of the object's 'unique' field is not +// consistent with the indicated size in the object's +// parameters +// TPM_RC_OBJECT_MEMORY if there is no free slot for an object +// TPM_RC_ECC_POINT for a public-only ECC key, the ECC point is not +// on the curve +// TPM_RC_SCHEME the signing scheme is not valid for the key +// TPM_RC_SIZE 'authPolicy' is not zero and is not the size of a +// digest produced by the object's 'nameAlg' +// TPM_RH_NULL hierarchy +// TPM_RC_SYMMETRIC symmetric algorithm not provided when required +// TPM_RC_TYPE 'inPublic' and 'inPrivate' are not the same type +TPM_RC +TPM2_LoadExternal(LoadExternal_In* in, // IN: input parameter list + LoadExternal_Out* out // OUT: output parameter list +) +{ + TPM_RC result; + OBJECT* object; + TPMT_SENSITIVE* sensitive = NULL; + + // Input Validation + // Don't get invested in loading if there is no place to put it. + object = FindEmptyObjectSlot(&out->objectHandle); + if(object == NULL) + return TPM_RC_OBJECT_MEMORY; + + // If the hierarchy to be associated with this object is turned off, the object + // cannot be loaded. + if(!HierarchyIsEnabled(in->hierarchy)) + return TPM_RCS_HIERARCHY + RC_LoadExternal_hierarchy; + + // For loading an object with both public and sensitive + if(in->inPrivate.size != 0) + { + // An external object with a sensitive area can only be loaded in the + // NULL hierarchy + if(in->hierarchy != TPM_RH_NULL) + return TPM_RCS_HIERARCHY + RC_LoadExternal_hierarchy; + // An external object with a sensitive area must have fixedTPM == CLEAR + // fixedParent == CLEAR so that it does not appear to be a key created by + // this TPM. + if(IS_ATTRIBUTE( + in->inPublic.publicArea.objectAttributes, TPMA_OBJECT, fixedTPM) + || IS_ATTRIBUTE( + in->inPublic.publicArea.objectAttributes, TPMA_OBJECT, fixedParent) + || IS_ATTRIBUTE( + in->inPublic.publicArea.objectAttributes, TPMA_OBJECT, restricted)) + return TPM_RCS_ATTRIBUTES + RC_LoadExternal_inPublic; + + // Have sensitive point to something other than NULL so that object + // initialization will load the sensitive part too + sensitive = &in->inPrivate.sensitiveArea; + } + + // Need the name to initialize the object structure + PublicMarshalAndComputeName(&in->inPublic.publicArea, &out->name); + + // Load and validate key + result = ObjectLoad(object, + NULL, + &in->inPublic.publicArea, + sensitive, + RC_LoadExternal_inPublic, + RC_LoadExternal_inPrivate, + &out->name); + if(result == TPM_RC_SUCCESS) + { + object->attributes.external = SET; + // Set the common OBJECT attributes for a loaded object. + ObjectSetLoadedAttributes(object, in->hierarchy); + } + return result; +} + +#endif // CC_LoadExternal \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/MakeCredential.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/MakeCredential.c new file mode 100644 index 0000000..85962b0 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/MakeCredential.c @@ -0,0 +1,94 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "MakeCredential_fp.h" + +#if CC_MakeCredential // Conditional expansion of this file + +# include "Object_spt_fp.h" + +/*(See part 3 specification) +// Make Credential with an object +*/ +// Return Type: TPM_RC +// TPM_RC_KEY 'handle' referenced an ECC key that has a unique +// field that is not a point on the curve of the key +// TPM_RC_SIZE 'credential' is larger than the digest size of +// Name algorithm of 'handle' +// TPM_RC_TYPE 'handle' does not reference an asymmetric +// decryption key +TPM_RC +TPM2_MakeCredential(MakeCredential_In* in, // IN: input parameter list + MakeCredential_Out* out // OUT: output parameter list +) +{ + TPM_RC result = TPM_RC_SUCCESS; + + OBJECT* object; + TPM2B_DATA data; + + // Input Validation + + // Get object pointer + object = HandleToObject(in->handle); + + // input key must be an asymmetric, restricted decryption key + // NOTE: Needs to be restricted to have a symmetric value. + if(!CryptIsAsymAlgorithm(object->publicArea.type) + || !IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, decrypt) + || !IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, restricted)) + return TPM_RCS_TYPE + RC_MakeCredential_handle; + + // The credential information may not be larger than the digest size used for + // the Name of the key associated with handle. + if(in->credential.t.size > CryptHashGetDigestSize(object->publicArea.nameAlg)) + return TPM_RCS_SIZE + RC_MakeCredential_credential; + + // Command Output + + // Make encrypt key and its associated secret structure. + out->secret.t.size = sizeof(out->secret.t.secret); + result = CryptSecretEncrypt(object, IDENTITY_STRING, &data, &out->secret); + if(result != TPM_RC_SUCCESS) + return result; + + // Prepare output credential data from secret + SecretToCredential( + &in->credential, &in->objectName.b, &data.b, object, &out->credentialBlob); + + return TPM_RC_SUCCESS; +} + +#endif // CC_MakeCredential \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/ObjectChangeAuth.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/ObjectChangeAuth.c new file mode 100644 index 0000000..fbb25ba --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/ObjectChangeAuth.c @@ -0,0 +1,93 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "ObjectChangeAuth_fp.h" + +#if CC_ObjectChangeAuth // Conditional expansion of this file + +# include "Object_spt_fp.h" + +/*(See part 3 specification) +// Create an object +*/ +// Return Type: TPM_RC +// TPM_RC_SIZE 'newAuth' is larger than the size of the digest +// of the Name algorithm of 'objectHandle' +// TPM_RC_TYPE the key referenced by 'parentHandle' is not the +// parent of the object referenced by 'objectHandle'; +// or 'objectHandle' is a sequence object. +TPM_RC +TPM2_ObjectChangeAuth(ObjectChangeAuth_In* in, // IN: input parameter list + ObjectChangeAuth_Out* out // OUT: output parameter list +) +{ + TPMT_SENSITIVE sensitive; + + OBJECT* object = HandleToObject(in->objectHandle); + TPM2B_NAME QNCompare; + + // Input Validation + + // Can not change authorization on sequence object + if(ObjectIsSequence(object)) + return TPM_RCS_TYPE + RC_ObjectChangeAuth_objectHandle; + + // Make sure that the authorization value is consistent with the nameAlg + if(!AdjustAuthSize(&in->newAuth, object->publicArea.nameAlg)) + return TPM_RCS_SIZE + RC_ObjectChangeAuth_newAuth; + + // Parent handle should be the parent of object handle. In this + // implementation we verify this by checking the QN of object. Other + // implementation may choose different method to verify this attribute. + ComputeQualifiedName( + in->parentHandle, object->publicArea.nameAlg, &object->name, &QNCompare); + if(!MemoryEqual2B(&object->qualifiedName.b, &QNCompare.b)) + return TPM_RCS_TYPE + RC_ObjectChangeAuth_parentHandle; + + // Command Output + // Prepare the sensitive area with the new authorization value + sensitive = object->sensitive; + sensitive.authValue = in->newAuth; + + // Protect the sensitive area + SensitiveToPrivate(&sensitive, + &object->name, + HandleToObject(in->parentHandle), + object->publicArea.nameAlg, + &out->outPrivate); + return TPM_RC_SUCCESS; +} + +#endif // CC_ObjectChangeAuth \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/Object_spt.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/Object_spt.c new file mode 100644 index 0000000..5399c4c --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/Object_spt.c @@ -0,0 +1,1596 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Includes +#include "Tpm.h" +#include "Object_spt_fp.h" +#include "Marshal.h" + +//** Local Functions + +//*** GetIV2BSize() +// Get the size of TPM2B_IV in canonical form that will be append to the start of +// the sensitive data. It includes both size of size field and size of iv data +static UINT16 GetIV2BSize(OBJECT* protector // IN: the protector handle +) +{ + TPM_ALG_ID symAlg; + UINT16 keyBits; + + // Determine the symmetric algorithm and size of key + if(protector == NULL) + { + // Use the context encryption algorithm and key size + symAlg = CONTEXT_ENCRYPT_ALG; + keyBits = CONTEXT_ENCRYPT_KEY_BITS; + } + else + { + symAlg = protector->publicArea.parameters.asymDetail.symmetric.algorithm; + keyBits = protector->publicArea.parameters.asymDetail.symmetric.keyBits.sym; + } + + // The IV size is a UINT16 size field plus the block size of the symmetric + // algorithm + return sizeof(UINT16) + CryptGetSymmetricBlockSize(symAlg, keyBits); +} + +//*** ComputeProtectionKeyParms() +// This function retrieves the symmetric protection key parameters for +// the sensitive data +// The parameters retrieved from this function include encryption algorithm, +// key size in bit, and a TPM2B_SYM_KEY containing the key material as well as +// the key size in bytes +// This function is used for any action that requires encrypting or decrypting of +// the sensitive area of an object or a credential blob +// +/*(See part 1 specification) + KDF for generating the protection key material: + KDFa(hashAlg, seed, "STORAGE", Name, NULL , bits) +where + hashAlg for a Primary Object, an algorithm chosen by the TPM vendor + for derivations from Primary Seeds. For all other objects, + the nameAlg of the object's parent. + seed for a Primary Object in the Platform Hierarchy, the PPS. + For Primary Objects in either Storage or Endorsement Hierarchy, + the SPS. For Temporary Objects, the context encryption seed. + For all other objects, the symmetric seed value in the + sensitive area of the object's parent. + STORAGE label to differentiate use of KDFa() (see 4.7) + Name the Name of the object being encrypted + bits the number of bits required for a symmetric key and IV +*/ +// Return Type: void +static void ComputeProtectionKeyParms( + OBJECT* protector, // IN: the protector object + TPM_ALG_ID hashAlg, // IN: hash algorithm for KDFa + TPM2B* name, // IN: name of the object + TPM2B* seedIn, // IN: optional seed for duplication blob. + // For non duplication blob, this + // parameter should be NULL + TPM_ALG_ID* symAlg, // OUT: the symmetric algorithm + UINT16* keyBits, // OUT: the symmetric key size in bits + TPM2B_SYM_KEY* symKey // OUT: the symmetric key +) +{ + const TPM2B* seed = seedIn; + + // Determine the algorithms for the KDF and the encryption/decryption + // For TPM_RH_NULL, using context settings + if(protector == NULL) + { + // Use the context encryption algorithm and key size + *symAlg = CONTEXT_ENCRYPT_ALG; + symKey->t.size = CONTEXT_ENCRYPT_KEY_BYTES; + *keyBits = CONTEXT_ENCRYPT_KEY_BITS; + } + else + { + TPMT_SYM_DEF_OBJECT* symDef; + symDef = &protector->publicArea.parameters.asymDetail.symmetric; + *symAlg = symDef->algorithm; + *keyBits = symDef->keyBits.sym; + symKey->t.size = (*keyBits + 7) / 8; + } + // Get seed for KDF + if(seed == NULL) + seed = GetSeedForKDF(protector); + // KDFa to generate symmetric key and IV value + CryptKDFa(hashAlg, + seed, + STORAGE_KEY, + name, + NULL, + symKey->t.size * 8, + symKey->t.buffer, + NULL, + FALSE); + return; +} + +//*** ComputeOuterIntegrity() +// The sensitive area parameter is a buffer that holds a space for +// the integrity value and the marshaled sensitive area. The caller should +// skip over the area set aside for the integrity value +// and compute the hash of the remainder of the object. +// The size field of sensitive is in unmarshaled form and the +// sensitive area contents is an array of bytes. +/*(See part 1 specification) + KDFa(hashAlg, seed, "INTEGRITY", NULL, NULL , bits) (38) +where + hashAlg for a Primary Object, the nameAlg of the object. For all other + objects the nameAlg of the object's parent. + seed for a Primary Object in the Platform Hierarchy, the PPS. For + Primary Objects in either Storage or Endorsement Hierarchy, + the SPS. For a Temporary Object, the context encryption key. + For all other objects, the symmetric seed value in the sensitive + area of the object's parent. + "INTEGRITY" a value used to differentiate the uses of the KDF. + bits the number of bits in the digest produced by hashAlg. +Key is then used in the integrity computation. + HMACnameAlg(HMACkey, encSensitive || Name ) +where + HMACnameAlg() the HMAC function using nameAlg of the object's parent + HMACkey value derived from the parent symmetric protection value + encSensitive symmetrically encrypted sensitive area + Name the Name of the object being protected +*/ +// Return Type: void +static void ComputeOuterIntegrity( + TPM2B* name, // IN: the name of the object + OBJECT* protector, // IN: the object that + // provides protection. For an object, + // it is a parent. For a credential, it + // is the encrypt object. For + // a Temporary Object, it is NULL + TPMI_ALG_HASH hashAlg, // IN: algorithm to use for integrity + TPM2B* seedIn, // IN: an external seed may be provided for + // duplication blob. For non duplication + // blob, this parameter should be NULL + UINT32 sensitiveSize, // IN: size of the marshaled sensitive data + BYTE* sensitiveData, // IN: sensitive area + TPM2B_DIGEST* integrity // OUT: integrity +) +{ + HMAC_STATE hmacState; + TPM2B_DIGEST hmacKey; + const TPM2B* seed = seedIn; + // + // Get seed for KDF + if(seed == NULL) + seed = GetSeedForKDF(protector); + // Determine the HMAC key bits + hmacKey.t.size = CryptHashGetDigestSize(hashAlg); + + // KDFa to generate HMAC key + CryptKDFa(hashAlg, + seed, + INTEGRITY_KEY, + NULL, + NULL, + hmacKey.t.size * 8, + hmacKey.t.buffer, + NULL, + FALSE); + // Start HMAC and get the size of the digest which will become the integrity + integrity->t.size = CryptHmacStart2B(&hmacState, hashAlg, &hmacKey.b); + + // Adding the marshaled sensitive area to the integrity value + CryptDigestUpdate(&hmacState.hashState, sensitiveSize, sensitiveData); + + // Adding name + CryptDigestUpdate2B(&hmacState.hashState, name); + + // Compute HMAC + CryptHmacEnd2B(&hmacState, &integrity->b); + + return; +} + +//*** ComputeInnerIntegrity() +// This function computes the integrity of an inner wrap +static void ComputeInnerIntegrity( + TPM_ALG_ID hashAlg, // IN: hash algorithm for inner wrap + TPM2B* name, // IN: the name of the object + UINT16 dataSize, // IN: the size of sensitive data + BYTE* sensitiveData, // IN: sensitive data + TPM2B_DIGEST* integrity // OUT: inner integrity +) +{ + HASH_STATE hashState; + // + // Start hash and get the size of the digest which will become the integrity + integrity->t.size = CryptHashStart(&hashState, hashAlg); + + // Adding the marshaled sensitive area to the integrity value + CryptDigestUpdate(&hashState, dataSize, sensitiveData); + + // Adding name + CryptDigestUpdate2B(&hashState, name); + + // Compute hash + CryptHashEnd2B(&hashState, &integrity->b); + + return; +} + +//*** ProduceInnerIntegrity() +// This function produces an inner integrity for regular private, credential or +// duplication blob +// It requires the sensitive data being marshaled to the innerBuffer, with the +// leading bytes reserved for integrity hash. It assume the sensitive data +// starts at address (innerBuffer + integrity size). +// This function integrity at the beginning of the inner buffer +// It returns the total size of buffer with the inner wrap +static UINT16 ProduceInnerIntegrity( + TPM2B* name, // IN: the name of the object + TPM_ALG_ID hashAlg, // IN: hash algorithm for inner wrap + UINT16 dataSize, // IN: the size of sensitive data, excluding the + // leading integrity buffer size + BYTE* innerBuffer // IN/OUT: inner buffer with sensitive data in + // it. At input, the leading bytes of this + // buffer is reserved for integrity +) +{ + BYTE* sensitiveData; // pointer to the sensitive data + TPM2B_DIGEST integrity; + UINT16 integritySize; + BYTE* buffer; // Auxiliary buffer pointer + // + // sensitiveData points to the beginning of sensitive data in innerBuffer + integritySize = sizeof(UINT16) + CryptHashGetDigestSize(hashAlg); + sensitiveData = innerBuffer + integritySize; + + ComputeInnerIntegrity(hashAlg, name, dataSize, sensitiveData, &integrity); + + // Add integrity at the beginning of inner buffer + buffer = innerBuffer; + TPM2B_DIGEST_Marshal(&integrity, &buffer, NULL); + + return dataSize + integritySize; +} + +//*** CheckInnerIntegrity() +// This function check integrity of inner blob +// Return Type: TPM_RC +// TPM_RC_INTEGRITY if the outer blob integrity is bad +// unmarshal errors unmarshal errors while unmarshaling integrity +static TPM_RC CheckInnerIntegrity( + TPM2B* name, // IN: the name of the object + TPM_ALG_ID hashAlg, // IN: hash algorithm for inner wrap + UINT16 dataSize, // IN: the size of sensitive data, including the + // leading integrity buffer size + BYTE* innerBuffer // IN/OUT: inner buffer with sensitive data in + // it +) +{ + TPM_RC result; + TPM2B_DIGEST integrity; + TPM2B_DIGEST integrityToCompare; + BYTE* buffer; // Auxiliary buffer pointer + INT32 size; + // + // Unmarshal integrity + buffer = innerBuffer; + size = (INT32)dataSize; + result = TPM2B_DIGEST_Unmarshal(&integrity, &buffer, &size); + if(result == TPM_RC_SUCCESS) + { + // Compute integrity to compare + ComputeInnerIntegrity( + hashAlg, name, (UINT16)size, buffer, &integrityToCompare); + // Compare outer blob integrity + if(!MemoryEqual2B(&integrity.b, &integrityToCompare.b)) + result = TPM_RC_INTEGRITY; + } + return result; +} + +//** Public Functions + +//*** AdjustAuthSize() +// This function will validate that the input authValue is no larger than the +// digestSize for the nameAlg. It will then pad with zeros to the size of the +// digest. +BOOL AdjustAuthSize(TPM2B_AUTH* auth, // IN/OUT: value to adjust + TPMI_ALG_HASH nameAlg // IN: +) +{ + UINT16 digestSize; + // + // If there is no nameAlg, then this is a LoadExternal and the authVale can + // be any size up to the maximum allowed by the implementation + digestSize = (nameAlg == TPM_ALG_NULL) ? sizeof(TPMU_HA) + : CryptHashGetDigestSize(nameAlg); + if(digestSize < MemoryRemoveTrailingZeros(auth)) + return FALSE; + else if(digestSize > auth->t.size) + MemoryPad2B(&auth->b, digestSize); + auth->t.size = digestSize; + + return TRUE; +} + +//*** AreAttributesForParent() +// This function is called by create, load, and import functions. +// +// Note: The 'isParent' attribute is SET when an object is loaded and it has +// attributes that are suitable for a parent object. +// Return Type: BOOL +// TRUE(1) properties are those of a parent +// FALSE(0) properties are not those of a parent +BOOL ObjectIsParent(OBJECT* parentObject // IN: parent handle +) +{ + return parentObject->attributes.isParent; +} + +//*** CreateChecks() +// Attribute checks that are unique to creation. +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES sensitiveDataOrigin is not consistent with the +// object type +// other returns from PublicAttributesValidation() +TPM_RC +CreateChecks(OBJECT* parentObject, TPMT_PUBLIC* publicArea, UINT16 sensitiveDataSize) +{ + TPMA_OBJECT attributes = publicArea->objectAttributes; + TPM_RC result = TPM_RC_SUCCESS; + // + // If the caller indicates that they have provided the data, then make sure that + // they have provided some data. + if((!IS_ATTRIBUTE(attributes, TPMA_OBJECT, sensitiveDataOrigin)) + && (sensitiveDataSize == 0)) + return TPM_RCS_ATTRIBUTES; + // For an ordinary object, data can only be provided when sensitiveDataOrigin + // is CLEAR + if((parentObject != NULL) + && (IS_ATTRIBUTE(attributes, TPMA_OBJECT, sensitiveDataOrigin)) + && (sensitiveDataSize != 0)) + return TPM_RCS_ATTRIBUTES; + switch(publicArea->type) + { + case TPM_ALG_KEYEDHASH: + // if this is a data object (sign == decrypt == CLEAR) then the + // TPM cannot be the data source. + if(!IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign) + && !IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt) + && IS_ATTRIBUTE(attributes, TPMA_OBJECT, sensitiveDataOrigin)) + result = TPM_RC_ATTRIBUTES; + // comment out the next line in order to prevent a fixedTPM derivation + // parent + // break; + case TPM_ALG_SYMCIPHER: + // A restricted key symmetric key (SYMCIPHER and KEYEDHASH) + // must have sensitiveDataOrigin SET unless it has fixedParent and + // fixedTPM CLEAR. + if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted)) + if(!IS_ATTRIBUTE(attributes, TPMA_OBJECT, sensitiveDataOrigin)) + if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedParent) + || IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM)) + result = TPM_RCS_ATTRIBUTES; + break; + default: // Asymmetric keys cannot have the sensitive portion provided + if(!IS_ATTRIBUTE(attributes, TPMA_OBJECT, sensitiveDataOrigin)) + result = TPM_RCS_ATTRIBUTES; + break; + } + if(TPM_RC_SUCCESS == result) + { + result = PublicAttributesValidation(parentObject, publicArea); + } + return result; +} +//*** SchemeChecks +// This function is called by TPM2_LoadExternal() and PublicAttributesValidation(). +// This function validates the schemes in the public area of an object. +// Return Type: TPM_RC +// TPM_RC_HASH non-duplicable storage key and its parent have different +// name algorithm +// TPM_RC_KDF incorrect KDF specified for decrypting keyed hash object +// TPM_RC_KEY invalid key size values in an asymmetric key public area +// TPM_RCS_SCHEME inconsistent attributes 'decrypt', 'sign', 'restricted' +// and key's scheme ID; or hash algorithm is inconsistent +// with the scheme ID for keyed hash object +// TPM_RC_SYMMETRIC a storage key with no symmetric algorithm specified; or +// non-storage key with symmetric algorithm different from +// TPM_ALG_NULL +TPM_RC +SchemeChecks(OBJECT* parentObject, // IN: parent (null if primary seed) + TPMT_PUBLIC* publicArea // IN: public area of the object +) +{ + TPMT_SYM_DEF_OBJECT* symAlgs = NULL; + TPM_ALG_ID scheme = TPM_ALG_NULL; + TPMA_OBJECT attributes = publicArea->objectAttributes; + TPMU_PUBLIC_PARMS* parms = &publicArea->parameters; + // + switch(publicArea->type) + { + case TPM_ALG_SYMCIPHER: + symAlgs = &parms->symDetail.sym; + // If this is a decrypt key, then only the block cipher modes (not + // SMAC) are valid. TPM_ALG_NULL is OK too. If this is a 'sign' key, + // then any mode that got through the unmarshaling is OK. + if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt) + && !CryptSymModeIsValid(symAlgs->mode.sym, TRUE)) + return TPM_RCS_SCHEME; + break; + case TPM_ALG_KEYEDHASH: + scheme = parms->keyedHashDetail.scheme.scheme; + // if both sign and decrypt + if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign) + == IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt)) + { + // if both sign and decrypt are set or clear, then need + // TPM_ALG_NULL as scheme + if(scheme != TPM_ALG_NULL) + return TPM_RCS_SCHEME; + } + else if( + IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign) && scheme != TPM_ALG_HMAC) + return TPM_RCS_SCHEME; + else if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt)) + { + if(scheme != TPM_ALG_XOR) + return TPM_RCS_SCHEME; + // If this is a derivation parent, then the KDF needs to be + // SP800-108 for this implementation. This is the only derivation + // supported by this implementation. Other implementations could + // support additional schemes. There is no default. + if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted)) + { + if(parms->keyedHashDetail.scheme.details. + xor.kdf != TPM_ALG_KDF1_SP800_108) + return TPM_RCS_SCHEME; + // Must select a digest. + if(CryptHashGetDigestSize( + parms->keyedHashDetail.scheme.details.xor.hashAlg) + == 0) + return TPM_RCS_HASH; + } + } + break; + default: // handling for asymmetric + scheme = parms->asymDetail.scheme.scheme; + symAlgs = &parms->asymDetail.symmetric; + // if the key is both sign and decrypt, then the scheme must be + // TPM_ALG_NULL because there is no way to specify both a sign and a + // decrypt scheme in the key. + if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign) + == IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt)) + { + // scheme must be TPM_ALG_NULL + if(scheme != TPM_ALG_NULL) + return TPM_RCS_SCHEME; + } + else if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign)) + { + // If this is a signing key, see if it has a signing scheme + if(CryptIsAsymSignScheme(publicArea->type, scheme)) + { + // if proper signing scheme then it needs a proper hash + if(parms->asymDetail.scheme.details.anySig.hashAlg + == TPM_ALG_NULL) + return TPM_RCS_SCHEME; + } + else + { + // signing key that does not have a proper signing scheme. + // This is OK if the key is not restricted and its scheme + // is TPM_ALG_NULL + if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted) + || scheme != TPM_ALG_NULL) + return TPM_RCS_SCHEME; + } + } + else if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt)) + { + if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted)) + { + // for a restricted decryption key (a parent), scheme + // is required to be TPM_ALG_NULL + if(scheme != TPM_ALG_NULL) + return TPM_RCS_SCHEME; + } + else + { + // For an unrestricted decryption key, the scheme has to + // be a valid scheme or TPM_ALG_NULL + if(scheme != TPM_ALG_NULL + && !CryptIsAsymDecryptScheme(publicArea->type, scheme)) + return TPM_RCS_SCHEME; + } + } + if(!IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted) + || !IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt)) + { + // For an asymmetric key that is not a parent, the symmetric + // algorithms must be TPM_ALG_NULL + if(symAlgs->algorithm != TPM_ALG_NULL) + return TPM_RCS_SYMMETRIC; + } + // Special checks for an ECC key +#if ALG_ECC + if(publicArea->type == TPM_ALG_ECC) + { + TPM_ECC_CURVE curveID; + const TPMT_ECC_SCHEME* curveScheme; + + curveID = publicArea->parameters.eccDetail.curveID; + curveScheme = CryptGetCurveSignScheme(curveID); + // The curveId must be valid or the unmarshaling is busted. + pAssert(curveScheme != NULL); + + // If the curveID requires a specific scheme, then the key must + // select the same scheme + if(curveScheme->scheme != TPM_ALG_NULL) + { + TPMS_ECC_PARMS* ecc = &publicArea->parameters.eccDetail; + if(scheme != curveScheme->scheme) + return TPM_RCS_SCHEME; + // The scheme can allow any hash, or not... + if(curveScheme->details.anySig.hashAlg != TPM_ALG_NULL + && (ecc->scheme.details.anySig.hashAlg + != curveScheme->details.anySig.hashAlg)) + return TPM_RCS_SCHEME; + } + // For now, the KDF must be TPM_ALG_NULL + if(publicArea->parameters.eccDetail.kdf.scheme != TPM_ALG_NULL) + return TPM_RCS_KDF; + } +#endif + break; + } + // If this is a restricted decryption key with symmetric algorithms, then it + // is an ordinary parent (not a derivation parent). It needs to specific + // symmetric algorithms other than TPM_ALG_NULL + if(symAlgs != NULL && IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted) + && IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt)) + { + if(symAlgs->algorithm == TPM_ALG_NULL) + return TPM_RCS_SYMMETRIC; +#if 0 //?? +// This next check is under investigation. Need to see if it will break Windows +// before it is enabled. If it does not, then it should be default because a +// the mode used with a parent is always CFB and Part 2 indicates as much. + if(symAlgs->mode.sym != TPM_ALG_CFB) + return TPM_RCS_MODE; +#endif + // If this parent is not duplicable, then the symmetric algorithms + // (encryption and hash) must match those of its parent + if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedParent) + && (parentObject != NULL)) + { + if(publicArea->nameAlg != parentObject->publicArea.nameAlg) + return TPM_RCS_HASH; + if(!MemoryEqual(symAlgs, + &parentObject->publicArea.parameters, + sizeof(TPMT_SYM_DEF_OBJECT))) + return TPM_RCS_SYMMETRIC; + } + } + return TPM_RC_SUCCESS; +} + +//*** PublicAttributesValidation() +// This function validates the values in the public area of an object. +// This function is used in the processing of TPM2_Create, TPM2_CreatePrimary, +// TPM2_CreateLoaded(), TPM2_Load(), TPM2_Import(), and TPM2_LoadExternal(). +// For TPM2_Import() this is only used if the new parent has fixedTPM SET. For +// TPM2_LoadExternal(), this is not used for a public-only key +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES 'fixedTPM', 'fixedParent', or 'encryptedDuplication' +// attributes are inconsistent between themselves or with +// those of the parent object; +// inconsistent 'restricted', 'decrypt' and 'sign' +// attributes; +// attempt to inject sensitive data for an asymmetric key; +// attempt to create a symmetric cipher key that is not +// a decryption key +// TPM_RC_HASH nameAlg is TPM_ALG_NULL +// TPM_RC_SIZE 'authPolicy' size does not match digest size of the name +// algorithm in 'publicArea' +// other returns from SchemeChecks() +TPM_RC +PublicAttributesValidation(OBJECT* parentObject, // IN: input parent object + TPMT_PUBLIC* publicArea // IN: public area of the object +) +{ + TPMA_OBJECT attributes = publicArea->objectAttributes; + TPMA_OBJECT parentAttributes = TPMA_ZERO_INITIALIZER(); + // + if(parentObject != NULL) + parentAttributes = parentObject->publicArea.objectAttributes; + if(publicArea->nameAlg == TPM_ALG_NULL) + return TPM_RCS_HASH; + // If there is an authPolicy, it needs to be the size of the digest produced + // by the nameAlg of the object + if((publicArea->authPolicy.t.size != 0 + && (publicArea->authPolicy.t.size + != CryptHashGetDigestSize(publicArea->nameAlg)))) + return TPM_RCS_SIZE; + // If the parent is fixedTPM (including a Primary Object) the object must have + // the same value for fixedTPM and fixedParent + if(parentObject == NULL || IS_ATTRIBUTE(parentAttributes, TPMA_OBJECT, fixedTPM)) + { + if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedParent) + != IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM)) + return TPM_RCS_ATTRIBUTES; + } + else + { + // The parent is not fixedTPM so the object can't be fixedTPM + if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM)) + return TPM_RCS_ATTRIBUTES; + } + // See if sign and decrypt are the same + if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign) + == IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt)) + { + // a restricted key cannot have both SET or both CLEAR + if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted)) + return TPM_RC_ATTRIBUTES; + // only a data object may have both sign and decrypt CLEAR + // BTW, since we know that decrypt==sign, no need to check both + if(publicArea->type != TPM_ALG_KEYEDHASH + && !IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign)) + return TPM_RC_ATTRIBUTES; + } + // If the object can't be duplicated (directly or indirectly) then there + // is no justification for having encryptedDuplication SET + if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM) + && IS_ATTRIBUTE(attributes, TPMA_OBJECT, encryptedDuplication)) + return TPM_RCS_ATTRIBUTES; + // If a parent object has fixedTPM CLEAR, the child must have the + // same encryptedDuplication value as its parent. + // Primary objects are considered to have a fixedTPM parent (the seeds). + if(parentObject != NULL && !IS_ATTRIBUTE(parentAttributes, TPMA_OBJECT, fixedTPM)) + { + if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, encryptedDuplication) + != IS_ATTRIBUTE(parentAttributes, TPMA_OBJECT, encryptedDuplication)) + return TPM_RCS_ATTRIBUTES; + } + // Special checks for derived objects + if((parentObject != NULL) && (parentObject->attributes.derivation == SET)) + { + // A derived object has the same settings for fixedTPM as its parent + if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM) + != IS_ATTRIBUTE(parentAttributes, TPMA_OBJECT, fixedTPM)) + return TPM_RCS_ATTRIBUTES; + // A derived object is required to be fixedParent + if(!IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedParent)) + return TPM_RCS_ATTRIBUTES; + } + return SchemeChecks(parentObject, publicArea); +} + +//*** FillInCreationData() +// Fill in creation data for an object. +// Return Type: void +void FillInCreationData( + TPMI_DH_OBJECT parentHandle, // IN: handle of parent + TPMI_ALG_HASH nameHashAlg, // IN: name hash algorithm + TPML_PCR_SELECTION* creationPCR, // IN: PCR selection + TPM2B_DATA* outsideData, // IN: outside data + TPM2B_CREATION_DATA* outCreation, // OUT: creation data for output + TPM2B_DIGEST* creationDigest // OUT: creation digest +) +{ + BYTE creationBuffer[sizeof(TPMS_CREATION_DATA)]; + BYTE* buffer; + HASH_STATE hashState; + // + // Fill in TPMS_CREATION_DATA in outCreation + + // Compute PCR digest + PCRComputeCurrentDigest( + nameHashAlg, creationPCR, &outCreation->creationData.pcrDigest); + + // Put back PCR selection list + outCreation->creationData.pcrSelect = *creationPCR; + + // Get locality + outCreation->creationData.locality = LocalityGetAttributes(_plat__LocalityGet()); + outCreation->creationData.parentNameAlg = TPM_ALG_NULL; + + // If the parent is either a primary seed or TPM_ALG_NULL, then the Name + // and QN of the parent are the parent's handle. + if(HandleGetType(parentHandle) == TPM_HT_PERMANENT) + { + buffer = &outCreation->creationData.parentName.t.name[0]; + outCreation->creationData.parentName.t.size = + TPM_HANDLE_Marshal(&parentHandle, &buffer, NULL); + // For a primary or temporary object, the parent name (a handle) and the + // parent's QN are the same + outCreation->creationData.parentQualifiedName = + outCreation->creationData.parentName; + } + else // Regular object + { + OBJECT* parentObject = HandleToObject(parentHandle); + // + // Set name algorithm + outCreation->creationData.parentNameAlg = parentObject->publicArea.nameAlg; + + // Copy parent name + outCreation->creationData.parentName = parentObject->name; + + // Copy parent qualified name + outCreation->creationData.parentQualifiedName = parentObject->qualifiedName; + } + // Copy outside information + outCreation->creationData.outsideInfo = *outsideData; + + // Marshal creation data to canonical form + buffer = creationBuffer; + outCreation->size = + TPMS_CREATION_DATA_Marshal(&outCreation->creationData, &buffer, NULL); + // Compute hash for creation field in public template + creationDigest->t.size = CryptHashStart(&hashState, nameHashAlg); + CryptDigestUpdate(&hashState, outCreation->size, creationBuffer); + CryptHashEnd2B(&hashState, &creationDigest->b); + + return; +} + +//*** GetSeedForKDF() +// Get a seed for KDF. The KDF for encryption and HMAC key use the same seed. +const TPM2B* GetSeedForKDF(OBJECT* protector // IN: the protector handle +) +{ + // Get seed for encryption key. Use input seed if provided. + // Otherwise, using protector object's seedValue. TPM_RH_NULL is the only + // exception that we may not have a loaded object as protector. In such a + // case, use nullProof as seed. + if(protector == NULL) + return &gr.nullProof.b; + else + return &protector->sensitive.seedValue.b; +} + +//*** ProduceOuterWrap() +// This function produce outer wrap for a buffer containing the sensitive data. +// It requires the sensitive data being marshaled to the outerBuffer, with the +// leading bytes reserved for integrity hash. If iv is used, iv space should +// be reserved at the beginning of the buffer. It assumes the sensitive data +// starts at address (outerBuffer + integrity size [+ iv size]). +// This function performs: +// 1. Add IV before sensitive area if required +// 2. encrypt sensitive data, if iv is required, encrypt by iv. otherwise, +// encrypted by a NULL iv +// 3. add HMAC integrity at the beginning of the buffer +// It returns the total size of blob with outer wrap +UINT16 +ProduceOuterWrap(OBJECT* protector, // IN: The handle of the object that provides + // protection. For object, it is parent + // handle. For credential, it is the handle + // of encrypt object. + TPM2B* name, // IN: the name of the object + TPM_ALG_ID hashAlg, // IN: hash algorithm for outer wrap + TPM2B* seed, // IN: an external seed may be provided for + // duplication blob. For non duplication + // blob, this parameter should be NULL + BOOL useIV, // IN: indicate if an IV is used + UINT16 dataSize, // IN: the size of sensitive data, excluding the + // leading integrity buffer size or the + // optional iv size + BYTE* outerBuffer // IN/OUT: outer buffer with sensitive data in + // it +) +{ + TPM_ALG_ID symAlg; + UINT16 keyBits; + TPM2B_SYM_KEY symKey; + TPM2B_IV ivRNG; // IV from RNG + TPM2B_IV* iv = NULL; + UINT16 ivSize = 0; // size of iv area, including the size field + BYTE* sensitiveData; // pointer to the sensitive data + TPM2B_DIGEST integrity; + UINT16 integritySize; + BYTE* buffer; // Auxiliary buffer pointer + // + // Compute the beginning of sensitive data. The outer integrity should + // always exist if this function is called to make an outer wrap + integritySize = sizeof(UINT16) + CryptHashGetDigestSize(hashAlg); + sensitiveData = outerBuffer + integritySize; + + // If iv is used, adjust the pointer of sensitive data and add iv before it + if(useIV) + { + ivSize = GetIV2BSize(protector); + + // Generate IV from RNG. The iv data size should be the total IV area + // size minus the size of size field + ivRNG.t.size = ivSize - sizeof(UINT16); + CryptRandomGenerate(ivRNG.t.size, ivRNG.t.buffer); + + // Marshal IV to buffer + buffer = sensitiveData; + TPM2B_IV_Marshal(&ivRNG, &buffer, NULL); + + // adjust sensitive data starting after IV area + sensitiveData += ivSize; + + // Use iv for encryption + iv = &ivRNG; + } + // Compute symmetric key parameters for outer buffer encryption + ComputeProtectionKeyParms( + protector, hashAlg, name, seed, &symAlg, &keyBits, &symKey); + // Encrypt inner buffer in place + CryptSymmetricEncrypt(sensitiveData, + symAlg, + keyBits, + symKey.t.buffer, + iv, + TPM_ALG_CFB, + dataSize, + sensitiveData); + // Compute outer integrity. Integrity computation includes the optional IV + // area + ComputeOuterIntegrity(name, + protector, + hashAlg, + seed, + dataSize + ivSize, + outerBuffer + integritySize, + &integrity); + // Add integrity at the beginning of outer buffer + buffer = outerBuffer; + TPM2B_DIGEST_Marshal(&integrity, &buffer, NULL); + + // return the total size in outer wrap + return dataSize + integritySize + ivSize; +} + +//*** UnwrapOuter() +// This function remove the outer wrap of a blob containing sensitive data +// This function performs: +// 1. check integrity of outer blob +// 2. decrypt outer blob +// +// Return Type: TPM_RC +// TPM_RCS_INSUFFICIENT error during sensitive data unmarshaling +// TPM_RCS_INTEGRITY sensitive data integrity is broken +// TPM_RCS_SIZE error during sensitive data unmarshaling +// TPM_RCS_VALUE IV size for CFB does not match the encryption +// algorithm block size +TPM_RC +UnwrapOuter(OBJECT* protector, // IN: The object that provides + // protection. For object, it is parent + // handle. For credential, it is the + // encrypt object. + TPM2B* name, // IN: the name of the object + TPM_ALG_ID hashAlg, // IN: hash algorithm for outer wrap + TPM2B* seed, // IN: an external seed may be provided for + // duplication blob. For non duplication + // blob, this parameter should be NULL. + BOOL useIV, // IN: indicates if an IV is used + UINT16 dataSize, // IN: size of sensitive data in outerBuffer, + // including the leading integrity buffer + // size, and an optional iv area + BYTE* outerBuffer // IN/OUT: sensitive data +) +{ + TPM_RC result; + TPM_ALG_ID symAlg = TPM_ALG_NULL; + TPM2B_SYM_KEY symKey; + UINT16 keyBits = 0; + TPM2B_IV ivIn; // input IV retrieved from input buffer + TPM2B_IV* iv = NULL; + BYTE* sensitiveData; // pointer to the sensitive data + TPM2B_DIGEST integrityToCompare; + TPM2B_DIGEST integrity; + INT32 size; + // + // Unmarshal integrity + sensitiveData = outerBuffer; + size = (INT32)dataSize; + result = TPM2B_DIGEST_Unmarshal(&integrity, &sensitiveData, &size); + if(result == TPM_RC_SUCCESS) + { + // Compute integrity to compare + ComputeOuterIntegrity(name, + protector, + hashAlg, + seed, + (UINT16)size, + sensitiveData, + &integrityToCompare); + // Compare outer blob integrity + if(!MemoryEqual2B(&integrity.b, &integrityToCompare.b)) + return TPM_RCS_INTEGRITY; + // Get the symmetric algorithm parameters used for encryption + ComputeProtectionKeyParms( + protector, hashAlg, name, seed, &symAlg, &keyBits, &symKey); + // Retrieve IV if it is used + if(useIV) + { + result = TPM2B_IV_Unmarshal(&ivIn, &sensitiveData, &size); + if(result == TPM_RC_SUCCESS) + { + // The input iv size for CFB must match the encryption algorithm + // block size + if(ivIn.t.size != CryptGetSymmetricBlockSize(symAlg, keyBits)) + result = TPM_RC_VALUE; + else + iv = &ivIn; + } + } + } + // If no errors, decrypt private in place. Since this function uses CFB, + // CryptSymmetricDecrypt() will not return any errors. It may fail but it will + // not return an error. + if(result == TPM_RC_SUCCESS) + CryptSymmetricDecrypt(sensitiveData, + symAlg, + keyBits, + symKey.t.buffer, + iv, + TPM_ALG_CFB, + (UINT16)size, + sensitiveData); + return result; +} + +//*** MarshalSensitive() +// This function is used to marshal a sensitive area. Among other things, it +// adjusts the size of the authValue to be no smaller than the digest of +// 'nameAlg' +// Returns the size of the marshaled area. +static UINT16 MarshalSensitive( + OBJECT* parent, // IN: the object parent (optional) + BYTE* buffer, // OUT: receiving buffer + TPMT_SENSITIVE* sensitive, // IN: the sensitive area to marshal + TPMI_ALG_HASH nameAlg // IN: +) +{ + BYTE* sizeField = buffer; // saved so that size can be + // marshaled after it is known + UINT16 retVal; + // + // Pad the authValue if needed + MemoryPad2B(&sensitive->authValue.b, CryptHashGetDigestSize(nameAlg)); + buffer += 2; + + // Marshal the structure +#if ALG_RSA + // If the sensitive size is the special case for a prime in the type + if((sensitive->sensitive.rsa.t.size & RSA_prime_flag) > 0) + { + UINT16 sizeSave = sensitive->sensitive.rsa.t.size; + // + // Turn off the flag that indicates that the sensitive->sensitive contains + // the CRT form of the exponent. + sensitive->sensitive.rsa.t.size &= ~(RSA_prime_flag); + // If the parent isn't fixedTPM, then truncate the sensitive data to be + // the size of the prime. Otherwise, leave it at the current size which + // is the full CRT size. + if(parent == NULL + || !IS_ATTRIBUTE( + parent->publicArea.objectAttributes, TPMA_OBJECT, fixedTPM)) + sensitive->sensitive.rsa.t.size /= 5; + retVal = TPMT_SENSITIVE_Marshal(sensitive, &buffer, NULL); + // Restore the flag and the size. + sensitive->sensitive.rsa.t.size = sizeSave; + } + else +#endif + retVal = TPMT_SENSITIVE_Marshal(sensitive, &buffer, NULL); + + // Marshal the size + retVal = (UINT16)(retVal + UINT16_Marshal(&retVal, &sizeField, NULL)); + + return retVal; +} + +//*** SensitiveToPrivate() +// This function prepare the private blob for off the chip storage +// The operations in this function: +// 1. marshal TPM2B_SENSITIVE structure into the buffer of TPM2B_PRIVATE +// 2. apply encryption to the sensitive area. +// 3. apply outer integrity computation. +void SensitiveToPrivate( + TPMT_SENSITIVE* sensitive, // IN: sensitive structure + TPM2B_NAME* name, // IN: the name of the object + OBJECT* parent, // IN: The parent object + TPM_ALG_ID nameAlg, // IN: hash algorithm in public area. This + // parameter is used when parentHandle is + // NULL, in which case the object is + // temporary. + TPM2B_PRIVATE* outPrivate // OUT: output private structure +) +{ + BYTE* sensitiveData; // pointer to the sensitive data + UINT16 dataSize; // data blob size + TPMI_ALG_HASH hashAlg; // hash algorithm for integrity + UINT16 integritySize; + UINT16 ivSize; + // + pAssert(name != NULL && name->t.size != 0); + + // Find the hash algorithm for integrity computation + if(parent == NULL) + { + // For Temporary Object, using self name algorithm + hashAlg = nameAlg; + } + else + { + // Otherwise, using parent's name algorithm + hashAlg = parent->publicArea.nameAlg; + } + // Starting of sensitive data without wrappers + sensitiveData = outPrivate->t.buffer; + + // Compute the integrity size + integritySize = sizeof(UINT16) + CryptHashGetDigestSize(hashAlg); + + // Reserve space for integrity + sensitiveData += integritySize; + + // Get iv size + ivSize = GetIV2BSize(parent); + + // Reserve space for iv + sensitiveData += ivSize; + + // Marshal the sensitive area including authValue size adjustments. + dataSize = MarshalSensitive(parent, sensitiveData, sensitive, nameAlg); + + //Produce outer wrap, including encryption and HMAC + outPrivate->t.size = ProduceOuterWrap( + parent, &name->b, hashAlg, NULL, TRUE, dataSize, outPrivate->t.buffer); + return; +} + +//*** PrivateToSensitive() +// Unwrap an input private area; check the integrity; decrypt and retrieve data +// to a sensitive structure. +// The operations in this function: +// 1. check the integrity HMAC of the input private area +// 2. decrypt the private buffer +// 3. unmarshal TPMT_SENSITIVE structure into the buffer of TPMT_SENSITIVE +// +// Return Type: TPM_RC +// TPM_RCS_INTEGRITY if the private area integrity is bad +// TPM_RC_SENSITIVE unmarshal errors while unmarshaling TPMS_ENCRYPT +// from input private +// TPM_RCS_SIZE error during sensitive data unmarshaling +// TPM_RCS_VALUE outer wrapper does not have an iV of the correct +// size +TPM_RC +PrivateToSensitive(TPM2B* inPrivate, // IN: input private structure + TPM2B* name, // IN: the name of the object + OBJECT* parent, // IN: parent object + TPM_ALG_ID nameAlg, // IN: hash algorithm in public area. It is + // passed separately because we only pass + // name, rather than the whole public area + // of the object. This parameter is used in + // the following two cases: 1. primary + // objects. 2. duplication blob with inner + // wrap. In other cases, this parameter + // will be ignored + TPMT_SENSITIVE* sensitive // OUT: sensitive structure +) +{ + TPM_RC result; + BYTE* buffer; + INT32 size; + BYTE* sensitiveData; // pointer to the sensitive data + UINT16 dataSize; + UINT16 dataSizeInput; + TPMI_ALG_HASH hashAlg; // hash algorithm for integrity + UINT16 integritySize; + UINT16 ivSize; + // + // Make sure that name is provided + pAssert(name != NULL && name->size != 0); + + // Find the hash algorithm for integrity computation + // For Temporary Object (parent == NULL) use self name algorithm; + // Otherwise, using parent's name algorithm + hashAlg = (parent == NULL) ? nameAlg : parent->publicArea.nameAlg; + + // unwrap outer + result = UnwrapOuter( + parent, name, hashAlg, NULL, TRUE, inPrivate->size, inPrivate->buffer); + if(result != TPM_RC_SUCCESS) + return result; + // Compute the inner integrity size. + integritySize = sizeof(UINT16) + CryptHashGetDigestSize(hashAlg); + + // Get iv size + ivSize = GetIV2BSize(parent); + + // The starting of sensitive data and data size without outer wrapper + sensitiveData = inPrivate->buffer + integritySize + ivSize; + dataSize = inPrivate->size - integritySize - ivSize; + + // Unmarshal input data size + buffer = sensitiveData; + size = (INT32)dataSize; + result = UINT16_Unmarshal(&dataSizeInput, &buffer, &size); + if(result == TPM_RC_SUCCESS) + { + if((dataSizeInput + sizeof(UINT16)) != dataSize) + result = TPM_RC_SENSITIVE; + else + { + // Unmarshal sensitive buffer to sensitive structure + result = TPMT_SENSITIVE_Unmarshal(sensitive, &buffer, &size); + if(result != TPM_RC_SUCCESS || size != 0) + { + result = TPM_RC_SENSITIVE; + } + } + } + return result; +} + +//*** SensitiveToDuplicate() +// This function prepare the duplication blob from the sensitive area. +// The operations in this function: +// 1. marshal TPMT_SENSITIVE structure into the buffer of TPM2B_PRIVATE +// 2. apply inner wrap to the sensitive area if required +// 3. apply outer wrap if required +void SensitiveToDuplicate( + TPMT_SENSITIVE* sensitive, // IN: sensitive structure + TPM2B* name, // IN: the name of the object + OBJECT* parent, // IN: The new parent object + TPM_ALG_ID nameAlg, // IN: hash algorithm in public area. It + // is passed separately because we + // only pass name, rather than the + // whole public area of the object. + TPM2B* seed, // IN: the external seed. If external + // seed is provided with size of 0, + // no outer wrap should be applied + // to duplication blob. + TPMT_SYM_DEF_OBJECT* symDef, // IN: Symmetric key definition. If the + // symmetric key algorithm is NULL, + // no inner wrap should be applied. + TPM2B_DATA* innerSymKey, // IN/OUT: a symmetric key may be + // provided to encrypt the inner + // wrap of a duplication blob. May + // be generated here if needed. + TPM2B_PRIVATE* outPrivate // OUT: output private structure +) +{ + BYTE* sensitiveData; // pointer to the sensitive data + TPMI_ALG_HASH outerHash = TPM_ALG_NULL; // The hash algorithm for outer wrap + TPMI_ALG_HASH innerHash = TPM_ALG_NULL; // The hash algorithm for inner wrap + UINT16 dataSize; // data blob size + BOOL doInnerWrap = FALSE; + BOOL doOuterWrap = FALSE; + // + // Make sure that name is provided + pAssert(name != NULL && name->size != 0); + + // Make sure symDef and innerSymKey are not NULL + pAssert(symDef != NULL && innerSymKey != NULL); + + // Starting of sensitive data without wrappers + sensitiveData = outPrivate->t.buffer; + + // Find out if inner wrap is required + if(symDef->algorithm != TPM_ALG_NULL) + { + doInnerWrap = TRUE; + + // Use self nameAlg as inner hash algorithm + innerHash = nameAlg; + + // Adjust sensitive data pointer + sensitiveData += sizeof(UINT16) + CryptHashGetDigestSize(innerHash); + } + // Find out if outer wrap is required + if(seed->size != 0) + { + doOuterWrap = TRUE; + + // Use parent nameAlg as outer hash algorithm + outerHash = parent->publicArea.nameAlg; + + // Adjust sensitive data pointer + sensitiveData += sizeof(UINT16) + CryptHashGetDigestSize(outerHash); + } + // Marshal sensitive area + dataSize = MarshalSensitive(NULL, sensitiveData, sensitive, nameAlg); + + // Apply inner wrap for duplication blob. It includes both integrity and + // encryption + if(doInnerWrap) + { + BYTE* innerBuffer = NULL; + BOOL symKeyInput = TRUE; + innerBuffer = outPrivate->t.buffer; + // Skip outer integrity space + if(doOuterWrap) + innerBuffer += sizeof(UINT16) + CryptHashGetDigestSize(outerHash); + dataSize = ProduceInnerIntegrity(name, innerHash, dataSize, innerBuffer); + // Generate inner encryption key if needed + if(innerSymKey->t.size == 0) + { + innerSymKey->t.size = (symDef->keyBits.sym + 7) / 8; + CryptRandomGenerate(innerSymKey->t.size, innerSymKey->t.buffer); + + // TPM generates symmetric encryption. Set the flag to FALSE + symKeyInput = FALSE; + } + else + { + // assume the input key size should matches the symmetric definition + pAssert(innerSymKey->t.size == (symDef->keyBits.sym + 7) / 8); + } + + // Encrypt inner buffer in place + CryptSymmetricEncrypt(innerBuffer, + symDef->algorithm, + symDef->keyBits.sym, + innerSymKey->t.buffer, + NULL, + TPM_ALG_CFB, + dataSize, + innerBuffer); + + // If the symmetric encryption key is imported, clear the buffer for + // output + if(symKeyInput) + innerSymKey->t.size = 0; + } + // Apply outer wrap for duplication blob. It includes both integrity and + // encryption + if(doOuterWrap) + { + dataSize = ProduceOuterWrap( + parent, name, outerHash, seed, FALSE, dataSize, outPrivate->t.buffer); + } + // Data size for output + outPrivate->t.size = dataSize; + + return; +} + +//*** DuplicateToSensitive() +// Unwrap a duplication blob. Check the integrity, decrypt and retrieve data +// to a sensitive structure. +// The operations in this function: +// 1. check the integrity HMAC of the input private area +// 2. decrypt the private buffer +// 3. unmarshal TPMT_SENSITIVE structure into the buffer of TPMT_SENSITIVE +// +// Return Type: TPM_RC +// TPM_RC_INSUFFICIENT unmarshaling sensitive data from 'inPrivate' failed +// TPM_RC_INTEGRITY 'inPrivate' data integrity is broken +// TPM_RC_SIZE unmarshaling sensitive data from 'inPrivate' failed +TPM_RC +DuplicateToSensitive( + TPM2B* inPrivate, // IN: input private structure + TPM2B* name, // IN: the name of the object + OBJECT* parent, // IN: the parent + TPM_ALG_ID nameAlg, // IN: hash algorithm in public area. + TPM2B* seed, // IN: an external seed may be provided. + // If external seed is provided with + // size of 0, no outer wrap is + // applied + TPMT_SYM_DEF_OBJECT* symDef, // IN: Symmetric key definition. If the + // symmetric key algorithm is NULL, + // no inner wrap is applied + TPM2B* innerSymKey, // IN: a symmetric key may be provided + // to decrypt the inner wrap of a + // duplication blob. + TPMT_SENSITIVE* sensitive // OUT: sensitive structure +) +{ + TPM_RC result; + BYTE* buffer; + INT32 size; + BYTE* sensitiveData; // pointer to the sensitive data + UINT16 dataSize; + UINT16 dataSizeInput; + // + // Make sure that name is provided + pAssert(name != NULL && name->size != 0); + + // Make sure symDef and innerSymKey are not NULL + pAssert(symDef != NULL && innerSymKey != NULL); + + // Starting of sensitive data + sensitiveData = inPrivate->buffer; + dataSize = inPrivate->size; + + // Find out if outer wrap is applied + if(seed->size != 0) + { + // Use parent nameAlg as outer hash algorithm + TPMI_ALG_HASH outerHash = parent->publicArea.nameAlg; + + result = UnwrapOuter( + parent, name, outerHash, seed, FALSE, dataSize, sensitiveData); + if(result != TPM_RC_SUCCESS) + return result; + // Adjust sensitive data pointer and size + sensitiveData += sizeof(UINT16) + CryptHashGetDigestSize(outerHash); + dataSize -= sizeof(UINT16) + CryptHashGetDigestSize(outerHash); + } + // Find out if inner wrap is applied + if(symDef->algorithm != TPM_ALG_NULL) + { + // assume the input key size matches the symmetric definition + pAssert(innerSymKey->size == (symDef->keyBits.sym + 7) / 8); + + // Decrypt inner buffer in place + CryptSymmetricDecrypt(sensitiveData, + symDef->algorithm, + symDef->keyBits.sym, + innerSymKey->buffer, + NULL, + TPM_ALG_CFB, + dataSize, + sensitiveData); + // Check inner integrity + result = CheckInnerIntegrity(name, nameAlg, dataSize, sensitiveData); + if(result != TPM_RC_SUCCESS) + return result; + // Adjust sensitive data pointer and size + sensitiveData += sizeof(UINT16) + CryptHashGetDigestSize(nameAlg); + dataSize -= sizeof(UINT16) + CryptHashGetDigestSize(nameAlg); + } + // Unmarshal input data size + buffer = sensitiveData; + size = (INT32)dataSize; + result = UINT16_Unmarshal(&dataSizeInput, &buffer, &size); + if(result == TPM_RC_SUCCESS) + { + if((dataSizeInput + sizeof(UINT16)) != dataSize) + result = TPM_RC_SIZE; + else + { + // Unmarshal sensitive buffer to sensitive structure + result = TPMT_SENSITIVE_Unmarshal(sensitive, &buffer, &size); + + // if the results is OK make sure that all the data was unmarshaled + if(result == TPM_RC_SUCCESS && size != 0) + result = TPM_RC_SIZE; + } + } + return result; +} + +//*** SecretToCredential() +// This function prepare the credential blob from a secret (a TPM2B_DIGEST) +// The operations in this function: +// 1. marshal TPM2B_DIGEST structure into the buffer of TPM2B_ID_OBJECT +// 2. encrypt the private buffer, excluding the leading integrity HMAC area +// 3. compute integrity HMAC and append to the beginning of the buffer. +// 4. Set the total size of TPM2B_ID_OBJECT buffer +void SecretToCredential(TPM2B_DIGEST* secret, // IN: secret information + TPM2B* name, // IN: the name of the object + TPM2B* seed, // IN: an external seed. + OBJECT* protector, // IN: the protector + TPM2B_ID_OBJECT* outIDObject // OUT: output credential +) +{ + BYTE* buffer; // Auxiliary buffer pointer + BYTE* sensitiveData; // pointer to the sensitive data + TPMI_ALG_HASH outerHash; // The hash algorithm for outer wrap + UINT16 dataSize; // data blob size + // + pAssert(secret != NULL && outIDObject != NULL); + + // use protector's name algorithm as outer hash ???? + outerHash = protector->publicArea.nameAlg; + + // Marshal secret area to credential buffer, leave space for integrity + sensitiveData = outIDObject->t.credential + sizeof(UINT16) + + CryptHashGetDigestSize(outerHash); + // Marshal secret area + buffer = sensitiveData; + dataSize = TPM2B_DIGEST_Marshal(secret, &buffer, NULL); + + // Apply outer wrap + outIDObject->t.size = ProduceOuterWrap( + protector, name, outerHash, seed, FALSE, dataSize, outIDObject->t.credential); + return; +} + +//*** CredentialToSecret() +// Unwrap a credential. Check the integrity, decrypt and retrieve data +// to a TPM2B_DIGEST structure. +// The operations in this function: +// 1. check the integrity HMAC of the input credential area +// 2. decrypt the credential buffer +// 3. unmarshal TPM2B_DIGEST structure into the buffer of TPM2B_DIGEST +// +// Return Type: TPM_RC +// TPM_RC_INSUFFICIENT error during credential unmarshaling +// TPM_RC_INTEGRITY credential integrity is broken +// TPM_RC_SIZE error during credential unmarshaling +// TPM_RC_VALUE IV size does not match the encryption algorithm +// block size +TPM_RC +CredentialToSecret(TPM2B* inIDObject, // IN: input credential blob + TPM2B* name, // IN: the name of the object + TPM2B* seed, // IN: an external seed. + OBJECT* protector, // IN: the protector + TPM2B_DIGEST* secret // OUT: secret information +) +{ + TPM_RC result; + BYTE* buffer; + INT32 size; + TPMI_ALG_HASH outerHash; // The hash algorithm for outer wrap + BYTE* sensitiveData; // pointer to the sensitive data + UINT16 dataSize; + // + // use protector's name algorithm as outer hash + outerHash = protector->publicArea.nameAlg; + + // Unwrap outer, a TPM_RC_INTEGRITY error may be returned at this point + result = UnwrapOuter(protector, + name, + outerHash, + seed, + FALSE, + inIDObject->size, + inIDObject->buffer); + if(result == TPM_RC_SUCCESS) + { + // Compute the beginning of sensitive data + sensitiveData = + inIDObject->buffer + sizeof(UINT16) + CryptHashGetDigestSize(outerHash); + dataSize = + inIDObject->size - (sizeof(UINT16) + CryptHashGetDigestSize(outerHash)); + // Unmarshal secret buffer to TPM2B_DIGEST structure + buffer = sensitiveData; + size = (INT32)dataSize; + result = TPM2B_DIGEST_Unmarshal(secret, &buffer, &size); + + // If there were no other unmarshaling errors, make sure that the + // expected amount of data was recovered + if(result == TPM_RC_SUCCESS && size != 0) + return TPM_RC_SIZE; + } + return result; +} + +//*** MemoryRemoveTrailingZeros() +// This function is used to adjust the length of an authorization value. +// It adjusts the size of the TPM2B so that it does not include octets +// at the end of the buffer that contain zero. +// The function returns the number of non-zero octets in the buffer. +UINT16 +MemoryRemoveTrailingZeros(TPM2B_AUTH* auth // IN/OUT: value to adjust +) +{ + while((auth->t.size > 0) && (auth->t.buffer[auth->t.size - 1] == 0)) + auth->t.size--; + return auth->t.size; +} + +//*** SetLabelAndContext() +// This function sets the label and context for a derived key. It is possible +// that 'label' or 'context' can end up being an Empty Buffer. +TPM_RC +SetLabelAndContext(TPMS_DERIVE* labelContext, // IN/OUT: the recovered label and + // context + TPM2B_SENSITIVE_DATA* sensitive // IN: the sensitive data +) +{ + TPMS_DERIVE sensitiveValue; + TPM_RC result; + INT32 size; + BYTE* buff; + // + // Unmarshal a TPMS_DERIVE from the TPM2B_SENSITIVE_DATA buffer + // If there is something to unmarshal... + if(sensitive->t.size != 0) + { + size = sensitive->t.size; + buff = sensitive->t.buffer; + result = TPMS_DERIVE_Unmarshal(&sensitiveValue, &buff, &size); + if(result != TPM_RC_SUCCESS) + return result; + // If there was a label in the public area leave it there, otherwise, copy + // the new value + if(labelContext->label.t.size == 0) + MemoryCopy2B(&labelContext->label.b, + &sensitiveValue.label.b, + sizeof(labelContext->label.t.buffer)); + // if there was a context string in publicArea, it overrides + if(labelContext->context.t.size == 0) + MemoryCopy2B(&labelContext->context.b, + &sensitiveValue.context.b, + sizeof(labelContext->label.t.buffer)); + } + return TPM_RC_SUCCESS; +} + +//*** UnmarshalToPublic() +// Support function to unmarshal the template. This is used because the +// Input may be a TPMT_TEMPLATE and that structure does not have the same +// size as a TPMT_PUBLIC because of the difference between the 'unique' and +// 'seed' fields. +// If 'derive' is not NULL, then the 'seed' field is assumed to contain +// a 'label' and 'context' that are unmarshaled into 'derive'. +TPM_RC +UnmarshalToPublic(TPMT_PUBLIC* tOut, // OUT: output + TPM2B_TEMPLATE* tIn, // IN: + BOOL derivation, // IN: indicates if this is for a derivation + TPMS_DERIVE* labelContext // OUT: label and context if derivation +) +{ + BYTE* buffer = tIn->t.buffer; + INT32 size = tIn->t.size; + TPM_RC result; + // + // make sure that tOut is zeroed so that there are no remnants from previous + // uses + MemorySet(tOut, 0, sizeof(TPMT_PUBLIC)); + // Unmarshal the components of the TPMT_PUBLIC up to the unique field + result = TPMI_ALG_PUBLIC_Unmarshal(&tOut->type, &buffer, &size); + if(result != TPM_RC_SUCCESS) + return result; + result = TPMI_ALG_HASH_Unmarshal(&tOut->nameAlg, &buffer, &size, FALSE); + if(result != TPM_RC_SUCCESS) + return result; + result = TPMA_OBJECT_Unmarshal(&tOut->objectAttributes, &buffer, &size); + if(result != TPM_RC_SUCCESS) + return result; + result = TPM2B_DIGEST_Unmarshal(&tOut->authPolicy, &buffer, &size); + if(result != TPM_RC_SUCCESS) + return result; + result = + TPMU_PUBLIC_PARMS_Unmarshal(&tOut->parameters, &buffer, &size, tOut->type); + if(result != TPM_RC_SUCCESS) + return result; + // Now unmarshal a TPMS_DERIVE if this is for derivation + if(derivation) + result = TPMS_DERIVE_Unmarshal(labelContext, &buffer, &size); + else + // otherwise, unmarshal a TPMU_PUBLIC_ID + result = TPMU_PUBLIC_ID_Unmarshal(&tOut->unique, &buffer, &size, tOut->type); + // Make sure the template was used up + if((result == TPM_RC_SUCCESS) && (size != 0)) + result = TPM_RC_SIZE; + return result; +} + +//*** ObjectSetExternal() +// Set the external attributes for an object. +void ObjectSetExternal(OBJECT* object) +{ + object->attributes.external = SET; +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/ReadPublic.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/ReadPublic.c new file mode 100644 index 0000000..f22af37 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/ReadPublic.c @@ -0,0 +1,66 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "ReadPublic_fp.h" + +#if CC_ReadPublic // Conditional expansion of this file + +/*(See part 3 specification) +// read public area of a loaded object +*/ +// Return Type: TPM_RC +// TPM_RC_SEQUENCE can not read the public area of a sequence +// object +TPM_RC +TPM2_ReadPublic(ReadPublic_In* in, // IN: input parameter list + ReadPublic_Out* out // OUT: output parameter list +) +{ + OBJECT* object = HandleToObject(in->objectHandle); + + // Input Validation + // Can not read public area of a sequence object + if(ObjectIsSequence(object)) + return TPM_RC_SEQUENCE; + + // Command Output + out->outPublic.publicArea = object->publicArea; + out->name = object->name; + out->qualifiedName = object->qualifiedName; + + return TPM_RC_SUCCESS; +} + +#endif // CC_ReadPublic \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/Unseal.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/Unseal.c new file mode 100644 index 0000000..802c83e --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Object/Unseal.c @@ -0,0 +1,67 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "Unseal_fp.h" + +#if CC_Unseal // Conditional expansion of this file + +/*(See part 3 specification) +// return data in a sealed data blob +*/ +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES 'itemHandle' has wrong attributes +// TPM_RC_TYPE 'itemHandle' is not a KEYEDHASH data object +TPM_RC +TPM2_Unseal(Unseal_In* in, Unseal_Out* out) +{ + OBJECT* object; + // Input Validation + // Get pointer to loaded object + object = HandleToObject(in->itemHandle); + + // Input handle must be a data object + if(object->publicArea.type != TPM_ALG_KEYEDHASH) + return TPM_RCS_TYPE + RC_Unseal_itemHandle; + if(IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, decrypt) + || IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, sign) + || IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, restricted)) + return TPM_RCS_ATTRIBUTES + RC_Unseal_itemHandle; + // Command Output + // Copy data + out->outData = object->sensitive.sensitive.bits; + return TPM_RC_SUCCESS; +} + +#endif // CC_Unseal \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_Allocate.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_Allocate.c new file mode 100644 index 0000000..aaec83d --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_Allocate.c @@ -0,0 +1,82 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "PCR_Allocate_fp.h" + +#if CC_PCR_Allocate // Conditional expansion of this file + +/*(See part 3 specification) +// Allocate PCR banks +*/ +// Return Type: TPM_RC +// TPM_RC_PCR the allocation did not have required PCR +// TPM_RC_NV_UNAVAILABLE NV is not accessible +// TPM_RC_NV_RATE NV is in a rate-limiting mode +TPM_RC +TPM2_PCR_Allocate(PCR_Allocate_In* in, // IN: input parameter list + PCR_Allocate_Out* out // OUT: output parameter list +) +{ + TPM_RC result; + + // The command needs NV update. Check if NV is available. + // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at + // this point. + // Note: These codes are not listed in the return values above because it is + // an implementation choice to check in this routine rather than in a common + // function that is called before these actions are called. These return values + // are described in the Response Code section of Part 3. + RETURN_IF_NV_IS_NOT_AVAILABLE; + + // Command Output + + // Call PCR Allocation function. + result = PCRAllocate( + &in->pcrAllocation, &out->maxPCR, &out->sizeNeeded, &out->sizeAvailable); + if(result == TPM_RC_PCR) + return result; + + // + out->allocationSuccess = (result == TPM_RC_SUCCESS); + + // if re-configuration succeeds, set the flag to indicate PCR configuration is + // going to be changed in next boot + if(out->allocationSuccess == YES) + g_pcrReConfig = TRUE; + + return TPM_RC_SUCCESS; +} + +#endif // CC_PCR_Allocate \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_Event.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_Event.c new file mode 100644 index 0000000..0af4de7 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_Event.c @@ -0,0 +1,90 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "PCR_Event_fp.h" + +#if CC_PCR_Event // Conditional expansion of this file + +/*(See part 3 specification) +// Update PCR +*/ +// Return Type: TPM_RC +// TPM_RC_LOCALITY current command locality is not allowed to +// extend the PCR referenced by 'pcrHandle' +TPM_RC +TPM2_PCR_Event(PCR_Event_In* in, // IN: input parameter list + PCR_Event_Out* out // OUT: output parameter list +) +{ + HASH_STATE hashState; + UINT32 i; + UINT16 size; + + // Input Validation + + // If a PCR extend is required + if(in->pcrHandle != TPM_RH_NULL) + { + // If the PCR is not allow to extend, return error + if(!PCRIsExtendAllowed(in->pcrHandle)) + return TPM_RC_LOCALITY; + + // If PCR is state saved and we need to update orderlyState, check NV + // availability + if(PCRIsStateSaved(in->pcrHandle)) + RETURN_IF_ORDERLY; + } + + // Internal Data Update + + out->digests.count = HASH_COUNT; + + // Iterate supported PCR bank algorithms to extend + for(i = 0; i < HASH_COUNT; i++) + { + TPM_ALG_ID hash = CryptHashGetAlgByIndex(i); + out->digests.digests[i].hashAlg = hash; + size = CryptHashStart(&hashState, hash); + CryptDigestUpdate2B(&hashState, &in->eventData.b); + CryptHashEnd(&hashState, size, (BYTE*)&out->digests.digests[i].digest); + if(in->pcrHandle != TPM_RH_NULL) + PCRExtend( + in->pcrHandle, hash, size, (BYTE*)&out->digests.digests[i].digest); + } + + return TPM_RC_SUCCESS; +} + +#endif // CC_PCR_Event \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_Extend.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_Extend.c new file mode 100644 index 0000000..c2bf172 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_Extend.c @@ -0,0 +1,89 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "PCR_Extend_fp.h" + +#if CC_PCR_Extend // Conditional expansion of this file + +/*(See part 3 specification) +// Update PCR +*/ +// Return Type: TPM_RC +// TPM_RC_LOCALITY current command locality is not allowed to +// extend the PCR referenced by 'pcrHandle' +TPM_RC +TPM2_PCR_Extend(PCR_Extend_In* in // IN: input parameter list +) +{ + UINT32 i; + + // Input Validation + + // NOTE: This function assumes that the unmarshaling function for 'digests' will + // have validated that all of the indicated hash algorithms are valid. If the + // hash algorithms are correct, the unmarshaling code will unmarshal a digest + // of the size indicated by the hash algorithm. If the overall size is not + // consistent, the unmarshaling code will run out of input data or have input + // data left over. In either case, it will cause an unmarshaling error and this + // function will not be called. + + // For NULL handle, do nothing and return success + if(in->pcrHandle == TPM_RH_NULL) + return TPM_RC_SUCCESS; + + // Check if the extend operation is allowed by the current command locality + if(!PCRIsExtendAllowed(in->pcrHandle)) + return TPM_RC_LOCALITY; + + // If PCR is state saved and we need to update orderlyState, check NV + // availability + if(PCRIsStateSaved(in->pcrHandle)) + RETURN_IF_ORDERLY; + + // Internal Data Update + + // Iterate input digest list to extend + for(i = 0; i < in->digests.count; i++) + { + PCRExtend(in->pcrHandle, + in->digests.digests[i].hashAlg, + CryptHashGetDigestSize(in->digests.digests[i].hashAlg), + (BYTE*)&in->digests.digests[i].digest); + } + + return TPM_RC_SUCCESS; +} + +#endif // CC_PCR_Extend \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_Read.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_Read.c new file mode 100644 index 0000000..5ff742b --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_Read.c @@ -0,0 +1,59 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "PCR_Read_fp.h" + +#if CC_PCR_Read // Conditional expansion of this file + +/*(See part 3 specification) +// Read a set of PCR +*/ +TPM_RC +TPM2_PCR_Read(PCR_Read_In* in, // IN: input parameter list + PCR_Read_Out* out // OUT: output parameter list +) +{ + // Command Output + + // Call PCR read function. input pcrSelectionIn parameter could be changed + // to reflect the actual PCR being returned + PCRRead(&in->pcrSelectionIn, &out->pcrValues, &out->pcrUpdateCounter); + + out->pcrSelectionOut = in->pcrSelectionIn; + + return TPM_RC_SUCCESS; +} + +#endif // CC_PCR_Read \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_Reset.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_Reset.c new file mode 100644 index 0000000..910adad --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_Reset.c @@ -0,0 +1,73 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "PCR_Reset_fp.h" + +#if CC_PCR_Reset // Conditional expansion of this file + +/*(See part 3 specification) +// Reset PCR +*/ +// Return Type: TPM_RC +// TPM_RC_LOCALITY current command locality is not allowed to +// reset the PCR referenced by 'pcrHandle' +TPM_RC +TPM2_PCR_Reset(PCR_Reset_In* in // IN: input parameter list +) +{ + // Input Validation + + // Check if the reset operation is allowed by the current command locality + if(!PCRIsResetAllowed(in->pcrHandle)) + return TPM_RC_LOCALITY; + + // If PCR is state saved and we need to update orderlyState, check NV + // availability + if(PCRIsStateSaved(in->pcrHandle)) + RETURN_IF_ORDERLY; + + // Internal Data Update + + // Reset selected PCR in all banks to 0 + PCRSetValue(in->pcrHandle, 0); + + // Indicate that the PCR changed so that pcrCounter will be incremented if + // necessary. + PCRChanged(in->pcrHandle); + + return TPM_RC_SUCCESS; +} + +#endif // CC_PCR_Reset \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_SetAuthPolicy.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_SetAuthPolicy.c new file mode 100644 index 0000000..1a0b94a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_SetAuthPolicy.c @@ -0,0 +1,81 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "PCR_SetAuthPolicy_fp.h" + +#if CC_PCR_SetAuthPolicy // Conditional expansion of this file + +/*(See part 3 specification) +// Set authPolicy to a group of PCR +*/ +// Return Type: TPM_RC +// TPM_RC_SIZE size of 'authPolicy' is not the size of a digest +// produced by 'policyDigest' +// TPM_RC_VALUE PCR referenced by 'pcrNum' is not a member +// of a PCR policy group +TPM_RC +TPM2_PCR_SetAuthPolicy(PCR_SetAuthPolicy_In* in // IN: input parameter list +) +{ + UINT32 groupIndex; + + // The command needs NV update. Check if NV is available. + // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at + // this point + RETURN_IF_NV_IS_NOT_AVAILABLE; + + // Input Validation: + + // Check the authPolicy consistent with hash algorithm + if(in->authPolicy.t.size != CryptHashGetDigestSize(in->hashAlg)) + return TPM_RCS_SIZE + RC_PCR_SetAuthPolicy_authPolicy; + + // If PCR does not belong to a policy group, return TPM_RC_VALUE + if(!PCRBelongsPolicyGroup(in->pcrNum, &groupIndex)) + return TPM_RCS_VALUE + RC_PCR_SetAuthPolicy_pcrNum; + + // Internal Data Update + + // Set PCR policy + gp.pcrPolicies.hashAlg[groupIndex] = in->hashAlg; + gp.pcrPolicies.policy[groupIndex] = in->authPolicy; + + // Save new policy to NV + NV_SYNC_PERSISTENT(pcrPolicies); + + return TPM_RC_SUCCESS; +} + +#endif // CC_PCR_SetAuthPolicy \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_SetAuthValue.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_SetAuthValue.c new file mode 100644 index 0000000..4f8b7cb --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/PCR/PCR_SetAuthValue.c @@ -0,0 +1,72 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "PCR_SetAuthValue_fp.h" + +#if CC_PCR_SetAuthValue // Conditional expansion of this file + +/*(See part 3 specification) +// Set authValue to a group of PCR +*/ +// Return Type: TPM_RC +// TPM_RC_VALUE PCR referenced by 'pcrHandle' is not a member +// of a PCR authorization group +TPM_RC +TPM2_PCR_SetAuthValue(PCR_SetAuthValue_In* in // IN: input parameter list +) +{ + UINT32 groupIndex; + // Input Validation: + + // If PCR does not belong to an auth group, return TPM_RC_VALUE + if(!PCRBelongsAuthGroup(in->pcrHandle, &groupIndex)) + return TPM_RC_VALUE; + + // The command may cause the orderlyState to be cleared due to the update of + // state clear data. If this is the case, Check if NV is available. + // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at + // this point + RETURN_IF_ORDERLY; + + // Internal Data Update + + // Set PCR authValue + MemoryRemoveTrailingZeros(&in->auth); + gc.pcrAuthValues.auth[groupIndex] = in->auth; + + return TPM_RC_SUCCESS; +} + +#endif // CC_PCR_SetAuthValue \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Random/GetRandom.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Random/GetRandom.c new file mode 100644 index 0000000..ef88807 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Random/GetRandom.c @@ -0,0 +1,62 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "GetRandom_fp.h" + +#if CC_GetRandom // Conditional expansion of this file + +/*(See part 3 specification) +// random number generator +*/ +TPM_RC +TPM2_GetRandom(GetRandom_In* in, // IN: input parameter list + GetRandom_Out* out // OUT: output parameter list +) +{ + // Command Output + + // if the requested bytes exceed the output buffer size, generates the + // maximum bytes that the output buffer allows + if(in->bytesRequested > sizeof(TPMU_HA)) + out->randomBytes.t.size = sizeof(TPMU_HA); + else + out->randomBytes.t.size = in->bytesRequested; + + CryptRandomGenerate(out->randomBytes.t.size, out->randomBytes.t.buffer); + + return TPM_RC_SUCCESS; +} + +#endif // CC_GetRandom \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Random/StirRandom.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Random/StirRandom.c new file mode 100644 index 0000000..b53573f --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Random/StirRandom.c @@ -0,0 +1,53 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "StirRandom_fp.h" + +#if CC_StirRandom // Conditional expansion of this file + +/*(See part 3 specification) +// add entropy to the RNG state +*/ +TPM_RC +TPM2_StirRandom(StirRandom_In* in // IN: input parameter list +) +{ + // Internal Data Update + CryptRandomStir(in->inData.t.size, in->inData.t.buffer); + + return TPM_RC_SUCCESS; +} + +#endif // CC_StirRandom \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Session/PolicyRestart.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Session/PolicyRestart.c new file mode 100644 index 0000000..87f5178 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Session/PolicyRestart.c @@ -0,0 +1,53 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "PolicyRestart_fp.h" + +#if CC_PolicyRestart // Conditional expansion of this file + +/*(See part 3 specification) +// Restore a policy session to its initial state +*/ +TPM_RC +TPM2_PolicyRestart(PolicyRestart_In* in // IN: input parameter list +) +{ + // Initialize policy session data + SessionResetPolicyData(SessionGet(in->sessionHandle)); + + return TPM_RC_SUCCESS; +} + +#endif // CC_PolicyRestart \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Session/StartAuthSession.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Session/StartAuthSession.c new file mode 100644 index 0000000..71a3d72 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Session/StartAuthSession.c @@ -0,0 +1,169 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "StartAuthSession_fp.h" + +#if CC_StartAuthSession // Conditional expansion of this file + +/*(See part 3 specification) +// Start an authorization session +*/ +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES 'tpmKey' does not reference a decrypt key +// TPM_RC_CONTEXT_GAP the difference between the most recently created +// active context and the oldest active context is at +// the limits of the TPM +// TPM_RC_HANDLE input decrypt key handle only has public portion +// loaded +// TPM_RC_MODE 'symmetric' specifies a block cipher but the mode +// is not TPM_ALG_CFB. +// TPM_RC_SESSION_HANDLES no session handle is available +// TPM_RC_SESSION_MEMORY no more slots for loading a session +// TPM_RC_SIZE nonce less than 16 octets or greater than the size +// of the digest produced by 'authHash' +// TPM_RC_VALUE secret size does not match decrypt key type; or the +// recovered secret is larger than the digest size of +// the nameAlg of 'tpmKey'; or, for an RSA decrypt key, +// if 'encryptedSecret' is greater than the +// public modulus of 'tpmKey'. +TPM_RC +TPM2_StartAuthSession(StartAuthSession_In* in, // IN: input parameter buffer + StartAuthSession_Out* out // OUT: output parameter buffer +) +{ + TPM_RC result = TPM_RC_SUCCESS; + OBJECT* tpmKey; // TPM key for decrypt salt + TPM2B_DATA salt; + + // Input Validation + + // Check input nonce size. IT should be at least 16 bytes but not larger + // than the digest size of session hash. + if(in->nonceCaller.t.size < 16 + || in->nonceCaller.t.size > CryptHashGetDigestSize(in->authHash)) + return TPM_RCS_SIZE + RC_StartAuthSession_nonceCaller; + + // If an decrypt key is passed in, check its validation + if(in->tpmKey != TPM_RH_NULL) + { + // Get pointer to loaded decrypt key + tpmKey = HandleToObject(in->tpmKey); + + // key must be asymmetric with its sensitive area loaded. Since this + // command does not require authorization, the presence of the sensitive + // area was not already checked as it is with most other commands that + // use the sensitive are so check it here + if(!CryptIsAsymAlgorithm(tpmKey->publicArea.type)) + return TPM_RCS_KEY + RC_StartAuthSession_tpmKey; + // secret size cannot be 0 + if(in->encryptedSalt.t.size == 0) + return TPM_RCS_VALUE + RC_StartAuthSession_encryptedSalt; + // Decrypting salt requires accessing the private portion of a key. + // Therefore, tmpKey can not be a key with only public portion loaded + if(tpmKey->attributes.publicOnly) + return TPM_RCS_HANDLE + RC_StartAuthSession_tpmKey; + // HMAC session input handle check. + // tpmKey should be a decryption key + if(!IS_ATTRIBUTE(tpmKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt)) + return TPM_RCS_ATTRIBUTES + RC_StartAuthSession_tpmKey; + // Secret Decryption. A TPM_RC_VALUE, TPM_RC_KEY or Unmarshal errors + // may be returned at this point + result = CryptSecretDecrypt( + tpmKey, &in->nonceCaller, SECRET_KEY, &in->encryptedSalt, &salt); + if(result != TPM_RC_SUCCESS) + return TPM_RCS_VALUE + RC_StartAuthSession_encryptedSalt; + } + else + { + // secret size must be 0 + if(in->encryptedSalt.t.size != 0) + return TPM_RCS_VALUE + RC_StartAuthSession_encryptedSalt; + salt.t.size = 0; + } + switch(HandleGetType(in->bind)) + { + case TPM_HT_TRANSIENT: + { + OBJECT* object = HandleToObject(in->bind); + // If the bind handle references a transient object, make sure that we + // can get to the authorization value. Also, make sure that the object + // has a proper Name (nameAlg != TPM_ALG_NULL). If it doesn't, then + // it might be possible to bind to an object where the authValue is + // known. This does not create a real issue in that, if you know the + // authorization value, you can actually bind to the object. However, + // there is a potential + if(object->attributes.publicOnly == SET) + return TPM_RCS_HANDLE + RC_StartAuthSession_bind; + break; + } + case TPM_HT_NV_INDEX: + // a PIN index can't be a bind object + { + NV_INDEX* nvIndex = NvGetIndexInfo(in->bind, NULL); + if(IsNvPinPassIndex(nvIndex->publicArea.attributes) + || IsNvPinFailIndex(nvIndex->publicArea.attributes)) + return TPM_RCS_HANDLE + RC_StartAuthSession_bind; + break; + } + default: + break; + } + // If 'symmetric' is a symmetric block cipher (not TPM_ALG_NULL or TPM_ALG_XOR) + // then the mode must be CFB. + if(in->symmetric.algorithm != TPM_ALG_NULL + && in->symmetric.algorithm != TPM_ALG_XOR + && in->symmetric.mode.sym != TPM_ALG_CFB) + return TPM_RCS_MODE + RC_StartAuthSession_symmetric; + + // Internal Data Update and command output + + // Create internal session structure. TPM_RC_CONTEXT_GAP, TPM_RC_NO_HANDLES + // or TPM_RC_SESSION_MEMORY errors may be returned at this point. + // + // The detailed actions for creating the session context are not shown here + // as the details are implementation dependent + // SessionCreate sets the output handle and nonceTPM + result = SessionCreate(in->sessionType, + in->authHash, + &in->nonceCaller, + &in->symmetric, + in->bind, + &salt, + &out->sessionHandle, + &out->nonceTPM); + return result; +} + +#endif // CC_StartAuthSession \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Signature/Sign.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Signature/Sign.c new file mode 100644 index 0000000..560bcd3 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Signature/Sign.c @@ -0,0 +1,112 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "Sign_fp.h" + +#if CC_Sign // Conditional expansion of this file + +# include "Attest_spt_fp.h" + +/*(See part 3 specification) +// sign an externally provided hash using an asymmetric signing key +*/ +// Return Type: TPM_RC +// TPM_RC_BINDING The public and private portions of the key are not +// properly bound. +// TPM_RC_KEY 'signHandle' does not reference a signing key; +// TPM_RC_SCHEME the scheme is not compatible with sign key type, +// or input scheme is not compatible with default +// scheme, or the chosen scheme is not a valid +// sign scheme +// TPM_RC_TICKET 'validation' is not a valid ticket +// TPM_RC_VALUE the value to sign is larger than allowed for the +// type of 'keyHandle' + +TPM_RC +TPM2_Sign(Sign_In* in, // IN: input parameter list + Sign_Out* out // OUT: output parameter list +) +{ + TPM_RC result; + TPMT_TK_HASHCHECK ticket; + OBJECT* signObject = HandleToObject(in->keyHandle); + // + // Input Validation + if(!IsSigningObject(signObject)) + return TPM_RCS_KEY + RC_Sign_keyHandle; + + // A key that will be used for x.509 signatures can't be used in TPM2_Sign(). + if(IS_ATTRIBUTE(signObject->publicArea.objectAttributes, TPMA_OBJECT, x509sign)) + return TPM_RCS_ATTRIBUTES + RC_Sign_keyHandle; + + // pick a scheme for sign. If the input sign scheme is not compatible with + // the default scheme, return an error. + if(!CryptSelectSignScheme(signObject, &in->inScheme)) + return TPM_RCS_SCHEME + RC_Sign_inScheme; + + // If validation is provided, or the key is restricted, check the ticket + if(in->validation.digest.t.size != 0 + || IS_ATTRIBUTE( + signObject->publicArea.objectAttributes, TPMA_OBJECT, restricted)) + { + // Compute and compare ticket + TicketComputeHashCheck(in->validation.hierarchy, + in->inScheme.details.any.hashAlg, + &in->digest, + &ticket); + + if(!MemoryEqual2B(&in->validation.digest.b, &ticket.digest.b)) + return TPM_RCS_TICKET + RC_Sign_validation; + } + else + // If we don't have a ticket, at least verify that the provided 'digest' + // is the size of the scheme hashAlg digest. + // NOTE: this does not guarantee that the 'digest' is actually produced using + // the indicated hash algorithm, but at least it might be. + { + if(in->digest.t.size + != CryptHashGetDigestSize(in->inScheme.details.any.hashAlg)) + return TPM_RCS_SIZE + RC_Sign_digest; + } + + // Command Output + // Sign the hash. A TPM_RC_VALUE or TPM_RC_SCHEME + // error may be returned at this point + result = CryptSign(signObject, &in->inScheme, &in->digest, &out->signature); + + return result; +} + +#endif // CC_Sign \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Signature/VerifySignature.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Signature/VerifySignature.c new file mode 100644 index 0000000..f2bd4dc --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Signature/VerifySignature.c @@ -0,0 +1,91 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "VerifySignature_fp.h" + +#if CC_VerifySignature // Conditional expansion of this file + +/*(See part 3 specification) +// This command uses loaded key to validate an asymmetric signature on a message +// with the message digest passed to the TPM. +*/ +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES 'keyHandle' does not reference a signing key +// TPM_RC_SIGNATURE signature is not genuine +// TPM_RC_SCHEME CryptValidateSignature() +// TPM_RC_HANDLE the input handle is references an HMAC key but +// the private portion is not loaded +TPM_RC +TPM2_VerifySignature(VerifySignature_In* in, // IN: input parameter list + VerifySignature_Out* out // OUT: output parameter list +) +{ + TPM_RC result; + OBJECT* signObject = HandleToObject(in->keyHandle); + TPMI_RH_HIERARCHY hierarchy; + + // Input Validation + // The object to validate the signature must be a signing key. + if(!IS_ATTRIBUTE(signObject->publicArea.objectAttributes, TPMA_OBJECT, sign)) + return TPM_RCS_ATTRIBUTES + RC_VerifySignature_keyHandle; + + // Validate Signature. TPM_RC_SCHEME, TPM_RC_HANDLE or TPM_RC_SIGNATURE + // error may be returned by CryptCVerifySignatrue() + result = CryptValidateSignature(in->keyHandle, &in->digest, &in->signature); + if(result != TPM_RC_SUCCESS) + return RcSafeAddToResult(result, RC_VerifySignature_signature); + + // Command Output + + hierarchy = GetHierarchy(in->keyHandle); + if(hierarchy == TPM_RH_NULL || signObject->publicArea.nameAlg == TPM_ALG_NULL) + { + // produce empty ticket if hierarchy is TPM_RH_NULL or nameAlg is + // TPM_ALG_NULL + out->validation.tag = TPM_ST_VERIFIED; + out->validation.hierarchy = TPM_RH_NULL; + out->validation.digest.t.size = 0; + } + else + { + // Compute ticket + TicketComputeVerified( + hierarchy, &in->digest, &signObject->name, &out->validation); + } + + return TPM_RC_SUCCESS; +} + +#endif // CC_VerifySignature \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Startup/Shutdown.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Startup/Shutdown.c new file mode 100644 index 0000000..eb652c2 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Startup/Shutdown.c @@ -0,0 +1,109 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "Shutdown_fp.h" + +#if CC_Shutdown // Conditional expansion of this file + +/*(See part 3 specification) +// Shut down TPM for power off +*/ +// Return Type: TPM_RC +// TPM_RC_TYPE if PCR bank has been re-configured, a +// Shutdown(CLEAR) is required +TPM_RC +TPM2_Shutdown(Shutdown_In* in // IN: input parameter list +) +{ + // The command needs NV update. Check if NV is available. + // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at + // this point + RETURN_IF_NV_IS_NOT_AVAILABLE; + + // Input Validation + // If PCR bank has been reconfigured, a CLEAR state save is required + if(g_pcrReConfig && in->shutdownType == TPM_SU_STATE) + return TPM_RCS_TYPE + RC_Shutdown_shutdownType; + // Internal Data Update + gp.orderlyState = in->shutdownType; + +# if USE_DA_USED + // CLEAR g_daUsed so that any future DA-protected access will cause the + // shutdown to become non-orderly. It is not sufficient to invalidate the + // shutdown state after a DA failure because an attacker can inhibit access + // to NV and use the fact that an update of failedTries was attempted as an + // indication of an authorization failure. By making sure that the orderly state + // is CLEAR before any DA attempt, this prevents the possibility of this 'attack.' + g_daUsed = FALSE; +# endif + + // PCR private date state save + PCRStateSave(in->shutdownType); + + // Save the ACT state + ActShutdown(in->shutdownType); + + // Save RAM backed NV index data + NvUpdateIndexOrderlyData(); + +# if ACCUMULATE_SELF_HEAL_TIMER + // Save the current time value + go.time = g_time; +# endif + + // Save all orderly data + NvWrite(NV_ORDERLY_DATA, sizeof(ORDERLY_DATA), &go); + + if(in->shutdownType == TPM_SU_STATE) + { + // Save STATE_RESET and STATE_CLEAR data + NvWrite(NV_STATE_CLEAR_DATA, sizeof(STATE_CLEAR_DATA), &gc); + NvWrite(NV_STATE_RESET_DATA, sizeof(STATE_RESET_DATA), &gr); + + // Save the startup flags for resume + if(g_DrtmPreStartup) + gp.orderlyState = TPM_SU_STATE | PRE_STARTUP_FLAG; + else if(g_StartupLocality3) + gp.orderlyState = TPM_SU_STATE | STARTUP_LOCALITY_3; + } + // only two shutdown options. + else if(in->shutdownType != TPM_SU_CLEAR) + return TPM_RCS_VALUE + RC_Shutdown_shutdownType; + + NV_SYNC_PERSISTENT(orderlyState); + + return TPM_RC_SUCCESS; +} +#endif // CC_Shutdown \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Startup/Startup.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Startup/Startup.c new file mode 100644 index 0000000..285b5fb --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Startup/Startup.c @@ -0,0 +1,246 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "Startup_fp.h" + +#if CC_Startup // Conditional expansion of this file + +/*(See part 3 specification) +// Initialize TPM because a system-wide reset +*/ +// Return Type: TPM_RC +// TPM_RC_LOCALITY a Startup(STATE) does not have the same H-CRTM +// state as the previous Startup() or the locality +// of the startup is not 0 or 3 +// TPM_RC_NV_UNINITIALIZED the saved state cannot be recovered and a +// Startup(CLEAR) is required. +// TPM_RC_VALUE 'startup' type is not compatible with previous +// shutdown sequence + +TPM_RC +TPM2_Startup(Startup_In* in // IN: input parameter list +) +{ + STARTUP_TYPE startup; + BYTE locality = _plat__LocalityGet(); + BOOL OK = TRUE; + // + // The command needs NV update. + RETURN_IF_NV_IS_NOT_AVAILABLE; + + // Get the flags for the current startup locality and the H-CRTM. + // Rather than generalizing the locality setting, this code takes advantage + // of the fact that the PC Client specification only allows Startup() + // from locality 0 and 3. To generalize this probably would require a + // redo of the NV space and since this is a feature that is hardly ever used + // outside of the PC Client, this code just support the PC Client needs. + + // Input Validation + // Check that the locality is a supported value + if(locality != 0 && locality != 3) + return TPM_RC_LOCALITY; + // If there was a H-CRTM, then treat the locality as being 3 + // regardless of what the Startup() was. This is done to preserve the + // H-CRTM PCR so that they don't get overwritten with the normal + // PCR startup initialization. This basically means that g_StartupLocality3 + // and g_DrtmPreStartup can't both be SET at the same time. + if(g_DrtmPreStartup) + locality = 0; + g_StartupLocality3 = (locality == 3); + +# if USE_DA_USED + // If there was no orderly shutdown, then there might have been a write to + // failedTries that didn't get recorded but only if g_daUsed was SET in the + // shutdown state + g_daUsed = (gp.orderlyState == SU_DA_USED_VALUE); + if(g_daUsed) + gp.orderlyState = SU_NONE_VALUE; +# endif + + g_prevOrderlyState = gp.orderlyState; + + // If there was a proper shutdown, then the startup modifiers are in the + // orderlyState. Turn them off in the copy. + if(IS_ORDERLY(g_prevOrderlyState)) + g_prevOrderlyState &= ~(PRE_STARTUP_FLAG | STARTUP_LOCALITY_3); + // If this is a Resume, + if(in->startupType == TPM_SU_STATE) + { + // then there must have been a prior TPM2_ShutdownState(STATE) + if(g_prevOrderlyState != TPM_SU_STATE) + return TPM_RCS_VALUE + RC_Startup_startupType; + // and the part of NV used for state save must have been recovered + // correctly. + // NOTE: if this fails, then the caller will need to do Startup(CLEAR). The + // code for Startup(Clear) cannot fail if the NV can't be read correctly + // because that would prevent the TPM from ever getting unstuck. + if(g_nvOk == FALSE) + return TPM_RC_NV_UNINITIALIZED; + // For Resume, the H-CRTM has to be the same as the previous boot + if(g_DrtmPreStartup != ((gp.orderlyState & PRE_STARTUP_FLAG) != 0)) + return TPM_RCS_VALUE + RC_Startup_startupType; + if(g_StartupLocality3 != ((gp.orderlyState & STARTUP_LOCALITY_3) != 0)) + return TPM_RC_LOCALITY; + } + // Clean up the gp state + gp.orderlyState = g_prevOrderlyState; + + // Internal Date Update + if((gp.orderlyState == TPM_SU_STATE) && (g_nvOk == TRUE)) + { + // Always read the data that is only cleared on a Reset because this is not + // a reset + NvRead(&gr, NV_STATE_RESET_DATA, sizeof(gr)); + if(in->startupType == TPM_SU_STATE) + { + // If this is a startup STATE (a Resume) need to read the data + // that is cleared on a startup CLEAR because this is not a Reset + // or Restart. + NvRead(&gc, NV_STATE_CLEAR_DATA, sizeof(gc)); + startup = SU_RESUME; + } + else + startup = SU_RESTART; + } + else + // Will do a TPM reset if Shutdown(CLEAR) and Startup(CLEAR) or no shutdown + // or there was a failure reading the NV data. + startup = SU_RESET; + // Startup for cryptographic library. Don't do this until after the orderly + // state has been read in from NV. + OK = OK && CryptStartup(startup); + + // When the cryptographic library has been started, indicate that a TPM2_Startup + // command has been received. + OK = OK && TPMRegisterStartup(); + + // Read the platform unique value that is used as VENDOR_PERMANENT + // authorization value + g_platformUniqueDetails.t.size = + (UINT16)_plat__GetUnique(1, + sizeof(g_platformUniqueDetails.t.buffer), + g_platformUniqueDetails.t.buffer); + + // Start up subsystems + // Start set the safe flag + OK = OK && TimeStartup(startup); + + // Start dictionary attack subsystem + OK = OK && DAStartup(startup); + + // Enable hierarchies + OK = OK && HierarchyStartup(startup); + + // Restore/Initialize PCR + OK = OK && PCRStartup(startup, locality); + + // Restore/Initialize command audit information + OK = OK && CommandAuditStartup(startup); + + // Restore the ACT + OK = OK && ActStartup(startup); + + //// The following code was moved from Time.c where it made no sense + if(OK) + { + switch(startup) + { + case SU_RESUME: + // Resume sequence + gr.restartCount++; + break; + case SU_RESTART: + // Hibernate sequence + gr.clearCount++; + gr.restartCount++; + break; + case SU_RESET: + default: + // Reset object context ID to 0 + gr.objectContextID = 0; + // Reset clearCount to 0 + gr.clearCount = 0; + + // Reset sequence + // Increase resetCount + gp.resetCount++; + + // Write resetCount to NV + NV_SYNC_PERSISTENT(resetCount); + + gp.totalResetCount++; + // We do not expect the total reset counter overflow during the life + // time of TPM. if it ever happens, TPM will be put to failure mode + // and there is no way to recover it. + // The reason that there is no recovery is that we don't increment + // the NV totalResetCount when incrementing would make it 0. When the + // TPM starts up again, the old value of totalResetCount will be read + // and we will get right back to here with the increment failing. + if(gp.totalResetCount == 0) + FAIL(FATAL_ERROR_INTERNAL); + + // Write total reset counter to NV + NV_SYNC_PERSISTENT(totalResetCount); + + // Reset restartCount + gr.restartCount = 0; + + break; + } + } + // Initialize session table + OK = OK && SessionStartup(startup); + + // Initialize object table + OK = OK && ObjectStartup(); + + // Initialize index/evict data. This function clears read/write locks + // in NV index + OK = OK && NvEntityStartup(startup); + + // Initialize the orderly shut down flag for this cycle to SU_NONE_VALUE. + gp.orderlyState = SU_NONE_VALUE; + + OK = OK && NV_SYNC_PERSISTENT(orderlyState); + + // This can be reset after the first completion of a TPM2_Startup() after + // a power loss. It can probably be reset earlier but this is an OK place. + if(OK) + g_powerWasLost = FALSE; + + return (OK) ? TPM_RC_SUCCESS : TPM_RC_FAILURE; +} + +#endif // CC_Startup diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Symmetric/EncryptDecrypt.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Symmetric/EncryptDecrypt.c new file mode 100644 index 0000000..ad0a539 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Symmetric/EncryptDecrypt.c @@ -0,0 +1,169 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "EncryptDecrypt_fp.h" +#if CC_EncryptDecrypt2 +# include "EncryptDecrypt_spt_fp.h" +#endif + +#if CC_EncryptDecrypt // Conditional expansion of this file + +/*(See part 3 specification) +// symmetric encryption or decryption +*/ +// Return Type: TPM_RC +// TPM_RC_KEY is not a symmetric decryption key with both +// public and private portions loaded +// TPM_RC_SIZE 'IvIn' size is incompatible with the block cipher mode; +// or 'inData' size is not an even multiple of the block +// size for CBC or ECB mode +// TPM_RC_VALUE 'keyHandle' is restricted and the argument 'mode' does +// not match the key's mode +TPM_RC +TPM2_EncryptDecrypt(EncryptDecrypt_In* in, // IN: input parameter list + EncryptDecrypt_Out* out // OUT: output parameter list +) +{ +# if CC_EncryptDecrypt2 + return EncryptDecryptShared( + in->keyHandle, in->decrypt, in->mode, &in->ivIn, &in->inData, out); +# else + OBJECT* symKey; + UINT16 keySize; + UINT16 blockSize; + BYTE* key; + TPM_ALG_ID alg; + TPM_ALG_ID mode; + TPM_RC result; + BOOL OK; + TPMA_OBJECT attributes; + + // Input Validation + symKey = HandleToObject(in->keyHandle); + mode = symKey->publicArea.parameters.symDetail.sym.mode.sym; + attributes = symKey->publicArea.objectAttributes; + + // The input key should be a symmetric key + if(symKey->publicArea.type != TPM_ALG_SYMCIPHER) + return TPM_RCS_KEY + RC_EncryptDecrypt_keyHandle; + // The key must be unrestricted and allow the selected operation + OK = IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted) if(YES == in->decrypt) + OK = OK && IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt); + else OK = OK && IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign); + if(!OK) + return TPM_RCS_ATTRIBUTES + RC_EncryptDecrypt_keyHandle; + + // If the key mode is not TPM_ALG_NULL... + // or TPM_ALG_NULL + if(mode != TPM_ALG_NULL) + { + // then the input mode has to be TPM_ALG_NULL or the same as the key + if((in->mode != TPM_ALG_NULL) && (in->mode != mode)) + return TPM_RCS_MODE + RC_EncryptDecrypt_mode; + } + else + { + // if the key mode is null, then the input can't be null + if(in->mode == TPM_ALG_NULL) + return TPM_RCS_MODE + RC_EncryptDecrypt_mode; + mode = in->mode; + } + // The input iv for ECB mode should be an Empty Buffer. All the other modes + // should have an iv size same as encryption block size + keySize = symKey->publicArea.parameters.symDetail.sym.keyBits.sym; + alg = symKey->publicArea.parameters.symDetail.sym.algorithm; + blockSize = CryptGetSymmetricBlockSize(alg, keySize); + + // reverify the algorithm. This is mainly to keep static analysis tools happy + if(blockSize == 0) + return TPM_RCS_KEY + RC_EncryptDecrypt_keyHandle; + + // Note: When an algorithm is not supported by a TPM, the TPM_ALG_xxx for that + // algorithm is not defined. However, it is assumed that the TPM_ALG_xxx for + // the algorithm is always defined. Both have the same numeric value. + // TPM_ALG_xxx is used here so that the code does not get cluttered with + // #ifdef's. Having this check does not mean that the algorithm is supported. + // If it was not supported the unmarshaling code would have rejected it before + // this function were called. This means that, depending on the implementation, + // the check could be redundant but it doesn't hurt. + if(((mode == TPM_ALG_ECB) && (in->ivIn.t.size != 0)) + || ((mode != TPM_ALG_ECB) && (in->ivIn.t.size != blockSize))) + return TPM_RCS_SIZE + RC_EncryptDecrypt_ivIn; + + // The input data size of CBC mode or ECB mode must be an even multiple of + // the symmetric algorithm's block size + if(((mode == TPM_ALG_CBC) || (mode == TPM_ALG_ECB)) + && ((in->inData.t.size % blockSize) != 0)) + return TPM_RCS_SIZE + RC_EncryptDecrypt_inData; + + // Copy IV + // Note: This is copied here so that the calls to the encrypt/decrypt functions + // will modify the output buffer, not the input buffer + out->ivOut = in->ivIn; + + // Command Output + key = symKey->sensitive.sensitive.sym.t.buffer; + // For symmetric encryption, the cipher data size is the same as plain data + // size. + out->outData.t.size = in->inData.t.size; + if(in->decrypt == YES) + { + // Decrypt data to output + result = CryptSymmetricDecrypt(out->outData.t.buffer, + alg, + keySize, + key, + &(out->ivOut), + mode, + in->inData.t.size, + in->inData.t.buffer); + } + else + { + // Encrypt data to output + result = CryptSymmetricEncrypt(out->outData.t.buffer, + alg, + keySize, + key, + &(out->ivOut), + mode, + in->inData.t.size, + in->inData.t.buffer); + } + return result; +# endif // CC_EncryptDecrypt2 +} + +#endif // CC_EncryptDecrypt \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Symmetric/EncryptDecrypt2.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Symmetric/EncryptDecrypt2.c new file mode 100644 index 0000000..f4e9832 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Symmetric/EncryptDecrypt2.c @@ -0,0 +1,85 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "EncryptDecrypt2_fp.h" +#include "EncryptDecrypt_fp.h" +#include "EncryptDecrypt_spt_fp.h" + +#if CC_EncryptDecrypt2 // Conditional expansion of this file + +/*(See part 3 specification) +// symmetric encryption or decryption using modified parameter list +*/ +// Return Type: TPM_RC +// TPM_RC_KEY is not a symmetric decryption key with both +// public and private portions loaded +// TPM_RC_SIZE 'IvIn' size is incompatible with the block cipher mode; +// or 'inData' size is not an even multiple of the block +// size for CBC or ECB mode +// TPM_RC_VALUE 'keyHandle' is restricted and the argument 'mode' does +// not match the key's mode +TPM_RC +TPM2_EncryptDecrypt2(EncryptDecrypt2_In* in, // IN: input parameter list + EncryptDecrypt2_Out* out // OUT: output parameter list +) +{ + TPM_RC result; + // EncryptDecyrptShared() performs the operations as shown in + // TPM2_EncrypDecrypt + result = EncryptDecryptShared(in->keyHandle, + in->decrypt, + in->mode, + &in->ivIn, + &in->inData, + (EncryptDecrypt_Out*)out); + // Handle response code swizzle. + switch(result) + { + case TPM_RCS_MODE + RC_EncryptDecrypt_mode: + result = TPM_RCS_MODE + RC_EncryptDecrypt2_mode; + break; + case TPM_RCS_SIZE + RC_EncryptDecrypt_ivIn: + result = TPM_RCS_SIZE + RC_EncryptDecrypt2_ivIn; + break; + case TPM_RCS_SIZE + RC_EncryptDecrypt_inData: + result = TPM_RCS_SIZE + RC_EncryptDecrypt2_inData; + break; + default: + break; + } + return result; +} + +#endif // CC_EncryptDecrypt2 \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Symmetric/EncryptDecrypt_spt.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Symmetric/EncryptDecrypt_spt.c new file mode 100644 index 0000000..16f1daf --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Symmetric/EncryptDecrypt_spt.c @@ -0,0 +1,163 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "EncryptDecrypt_fp.h" +#include "EncryptDecrypt_spt_fp.h" + +#if CC_EncryptDecrypt2 + +/*(See part 3 specification) +// symmetric encryption or decryption +*/ +// Return Type: TPM_RC +// TPM_RC_KEY is not a symmetric decryption key with both +// public and private portions loaded +// TPM_RC_SIZE 'IvIn' size is incompatible with the block cipher mode; +// or 'inData' size is not an even multiple of the block +// size for CBC or ECB mode +// TPM_RC_VALUE 'keyHandle' is restricted and the argument 'mode' does +// not match the key's mode +TPM_RC +EncryptDecryptShared(TPMI_DH_OBJECT keyHandleIn, + TPMI_YES_NO decryptIn, + TPMI_ALG_SYM_MODE modeIn, + TPM2B_IV* ivIn, + TPM2B_MAX_BUFFER* inData, + EncryptDecrypt_Out* out) +{ + OBJECT* symKey; + UINT16 keySize; + UINT16 blockSize; + BYTE* key; + TPM_ALG_ID alg; + TPM_ALG_ID mode; + TPM_RC result; + BOOL OK; + // Input Validation + symKey = HandleToObject(keyHandleIn); + mode = symKey->publicArea.parameters.symDetail.sym.mode.sym; + + // The input key should be a symmetric key + if(symKey->publicArea.type != TPM_ALG_SYMCIPHER) + return TPM_RCS_KEY + RC_EncryptDecrypt_keyHandle; + // The key must be unrestricted and allow the selected operation + OK = !IS_ATTRIBUTE(symKey->publicArea.objectAttributes, TPMA_OBJECT, restricted); + if(YES == decryptIn) + OK = OK + && IS_ATTRIBUTE( + symKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt); + else + OK = OK + && IS_ATTRIBUTE(symKey->publicArea.objectAttributes, TPMA_OBJECT, sign); + if(!OK) + return TPM_RCS_ATTRIBUTES + RC_EncryptDecrypt_keyHandle; + + // Make sure that key is an encrypt/decrypt key and not SMAC + if(!CryptSymModeIsValid(mode, TRUE)) + return TPM_RCS_MODE + RC_EncryptDecrypt_keyHandle; + + // If the key mode is not TPM_ALG_NULL... + // or TPM_ALG_NULL + if(mode != TPM_ALG_NULL) + { + // then the input mode has to be TPM_ALG_NULL or the same as the key + if((modeIn != TPM_ALG_NULL) && (modeIn != mode)) + return TPM_RCS_MODE + RC_EncryptDecrypt_mode; + } + else + { + // if the key mode is null, then the input can't be null + if(modeIn == TPM_ALG_NULL) + return TPM_RCS_MODE + RC_EncryptDecrypt_mode; + mode = modeIn; + } + // The input iv for ECB mode should be an Empty Buffer. All the other modes + // should have an iv size same as encryption block size + keySize = symKey->publicArea.parameters.symDetail.sym.keyBits.sym; + alg = symKey->publicArea.parameters.symDetail.sym.algorithm; + blockSize = CryptGetSymmetricBlockSize(alg, keySize); + + // reverify the algorithm. This is mainly to keep static analysis tools happy + if(blockSize == 0) + return TPM_RCS_KEY + RC_EncryptDecrypt_keyHandle; + + if(((mode == TPM_ALG_ECB) && (ivIn->t.size != 0)) + || ((mode != TPM_ALG_ECB) && (ivIn->t.size != blockSize))) + return TPM_RCS_SIZE + RC_EncryptDecrypt_ivIn; + + // The input data size of CBC mode or ECB mode must be an even multiple of + // the symmetric algorithm's block size + if(((mode == TPM_ALG_CBC) || (mode == TPM_ALG_ECB)) + && ((inData->t.size % blockSize) != 0)) + return TPM_RCS_SIZE + RC_EncryptDecrypt_inData; + + // Copy IV + // Note: This is copied here so that the calls to the encrypt/decrypt functions + // will modify the output buffer, not the input buffer + out->ivOut = *ivIn; + + // Command Output + key = symKey->sensitive.sensitive.sym.t.buffer; + // For symmetric encryption, the cipher data size is the same as plain data + // size. + out->outData.t.size = inData->t.size; + if(decryptIn == YES) + { + // Decrypt data to output + result = CryptSymmetricDecrypt(out->outData.t.buffer, + alg, + keySize, + key, + &(out->ivOut), + mode, + inData->t.size, + inData->t.buffer); + } + else + { + // Encrypt data to output + result = CryptSymmetricEncrypt(out->outData.t.buffer, + alg, + keySize, + key, + &(out->ivOut), + mode, + inData->t.size, + inData->t.buffer); + } + return result; +} + +#endif // CC_EncryptDecrypt \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Symmetric/HMAC.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Symmetric/HMAC.c new file mode 100644 index 0000000..4463f1a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Symmetric/HMAC.c @@ -0,0 +1,106 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "HMAC_fp.h" + +#if CC_HMAC // Conditional expansion of this file + +/*(See part 3 specification) +// Compute HMAC on a data buffer +*/ +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES key referenced by 'handle' is a restricted key +// TPM_RC_KEY 'handle' does not reference a signing key +// TPM_RC_TYPE key referenced by 'handle' is not an HMAC key +// TPM_RC_VALUE 'hashAlg' is not compatible with the hash algorithm +// of the scheme of the object referenced by 'handle' +TPM_RC +TPM2_HMAC(HMAC_In* in, // IN: input parameter list + HMAC_Out* out // OUT: output parameter list +) +{ + HMAC_STATE hmacState; + OBJECT* hmacObject; + TPMI_ALG_HASH hashAlg; + TPMT_PUBLIC* publicArea; + + // Input Validation + + // Get HMAC key object and public area pointers + hmacObject = HandleToObject(in->handle); + publicArea = &hmacObject->publicArea; + // Make sure that the key is an HMAC key + if(publicArea->type != TPM_ALG_KEYEDHASH) + return TPM_RCS_TYPE + RC_HMAC_handle; + + // and that it is unrestricted + if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted)) + return TPM_RCS_ATTRIBUTES + RC_HMAC_handle; + + // and that it is a signing key + if(!IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign)) + return TPM_RCS_KEY + RC_HMAC_handle; + + // See if the key has a default + if(publicArea->parameters.keyedHashDetail.scheme.scheme == TPM_ALG_NULL) + // it doesn't so use the input value + hashAlg = in->hashAlg; + else + { + // key has a default so use it + hashAlg = publicArea->parameters.keyedHashDetail.scheme.details.hmac.hashAlg; + // and verify that the input was either the TPM_ALG_NULL or the default + if(in->hashAlg != TPM_ALG_NULL && in->hashAlg != hashAlg) + hashAlg = TPM_ALG_NULL; + } + // if we ended up without a hash algorithm then return an error + if(hashAlg == TPM_ALG_NULL) + return TPM_RCS_VALUE + RC_HMAC_hashAlg; + + // Command Output + + // Start HMAC stack + out->outHMAC.t.size = CryptHmacStart2B( + &hmacState, hashAlg, &hmacObject->sensitive.sensitive.bits.b); + // Adding HMAC data + CryptDigestUpdate2B(&hmacState.hashState, &in->buffer.b); + + // Complete HMAC + CryptHmacEnd2B(&hmacState, &out->outHMAC.b); + + return TPM_RC_SUCCESS; +} + +#endif // CC_HMAC \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Symmetric/Hash.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Symmetric/Hash.c new file mode 100644 index 0000000..fca68ad --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Symmetric/Hash.c @@ -0,0 +1,87 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "Hash_fp.h" + +#if CC_Hash // Conditional expansion of this file + +/*(See part 3 specification) +// Hash a data buffer +*/ +TPM_RC +TPM2_Hash(Hash_In* in, // IN: input parameter list + Hash_Out* out // OUT: output parameter list +) +{ + HASH_STATE hashState; + + // Command Output + + // Output hash + // Start hash stack + out->outHash.t.size = CryptHashStart(&hashState, in->hashAlg); + // Adding hash data + CryptDigestUpdate2B(&hashState, &in->data.b); + // Complete hash + CryptHashEnd2B(&hashState, &out->outHash.b); + + // Output ticket + out->validation.tag = TPM_ST_HASHCHECK; + out->validation.hierarchy = in->hierarchy; + + if(in->hierarchy == TPM_RH_NULL) + { + // Ticket is not required + out->validation.hierarchy = TPM_RH_NULL; + out->validation.digest.t.size = 0; + } + else if( + in->data.t.size >= sizeof(TPM_GENERATED_VALUE) && !TicketIsSafe(&in->data.b)) + { + // Ticket is not safe + out->validation.hierarchy = TPM_RH_NULL; + out->validation.digest.t.size = 0; + } + else + { + // Compute ticket + TicketComputeHashCheck( + in->hierarchy, in->hashAlg, &out->outHash, &out->validation); + } + + return TPM_RC_SUCCESS; +} + +#endif // CC_Hash \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Symmetric/MAC.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Symmetric/MAC.c new file mode 100644 index 0000000..a463809 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Symmetric/MAC.c @@ -0,0 +1,94 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "MAC_fp.h" + +#if CC_MAC // Conditional expansion of this file + +/*(See part 3 specification) +// Compute MAC on a data buffer +*/ +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES key referenced by 'handle' is a restricted key +// TPM_RC_KEY 'handle' does not reference a signing key +// TPM_RC_TYPE key referenced by 'handle' is not an HMAC key +// TPM_RC_VALUE 'hashAlg' is not compatible with the hash algorithm +// of the scheme of the object referenced by 'handle' +TPM_RC +TPM2_MAC(MAC_In* in, // IN: input parameter list + MAC_Out* out // OUT: output parameter list +) +{ + OBJECT* keyObject; + HMAC_STATE state; + TPMT_PUBLIC* publicArea; + TPM_RC result; + + // Input Validation + // Get MAC key object and public area pointers + keyObject = HandleToObject(in->handle); + publicArea = &keyObject->publicArea; + + // If the key is not able to do a MAC, indicate that the handle selects an + // object that can't do a MAC + result = CryptSelectMac(publicArea, &in->inScheme); + if(result == TPM_RCS_TYPE) + return TPM_RCS_TYPE + RC_MAC_handle; + // If there is another error type, indicate that the scheme and key are not + // compatible + if(result != TPM_RC_SUCCESS) + return RcSafeAddToResult(result, RC_MAC_inScheme); + // Make sure that the key is not restricted + if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted)) + return TPM_RCS_ATTRIBUTES + RC_MAC_handle; + // and that it is a signing key + if(!IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign)) + return TPM_RCS_KEY + RC_MAC_handle; + // Command Output + out->outMAC.t.size = CryptMacStart(&state, + &publicArea->parameters, + in->inScheme, + &keyObject->sensitive.sensitive.any.b); + // If the mac can't start, treat it as a fatal error + if(out->outMAC.t.size == 0) + return TPM_RC_FAILURE; + CryptDigestUpdate2B(&state.hashState, &in->buffer.b); + // If the MAC result is not what was expected, it is a fatal error + if(CryptHmacEnd2B(&state, &out->outMAC.b) != out->outMAC.t.size) + return TPM_RC_FAILURE; + return TPM_RC_SUCCESS; +} + +#endif // CC_MAC \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Testing/GetTestResult.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Testing/GetTestResult.c new file mode 100644 index 0000000..dce7e97 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Testing/GetTestResult.c @@ -0,0 +1,60 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "GetTestResult_fp.h" + +#if CC_GetTestResult // Conditional expansion of this file + +/*(See part 3 specification) +// returns manufacturer-specific information regarding the results of a self- +// test and an indication of the test status. +*/ + +// In the reference implementation, this function is only reachable if the TPM is +// not in failure mode meaning that all tests that have been run have completed +// successfully. There is not test data and the test result is TPM_RC_SUCCESS. +TPM_RC +TPM2_GetTestResult(GetTestResult_Out* out // OUT: output parameter list +) +{ + // Command Output + + // Call incremental self test function in crypt module + out->testResult = CryptGetTestResult(&out->outData); + + return TPM_RC_SUCCESS; +} + +#endif // CC_GetTestResult \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Testing/IncrementalSelfTest.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Testing/IncrementalSelfTest.c new file mode 100644 index 0000000..a359bc8 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Testing/IncrementalSelfTest.c @@ -0,0 +1,64 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "IncrementalSelfTest_fp.h" + +#if CC_IncrementalSelfTest // Conditional expansion of this file + +/*(See part 3 specification) +// perform a test of selected algorithms +*/ +// Return Type: TPM_RC +// TPM_RC_CANCELED the command was canceled (some tests may have +// completed) +// TPM_RC_VALUE an algorithm in the toTest list is not implemented +TPM_RC +TPM2_IncrementalSelfTest(IncrementalSelfTest_In* in, // IN: input parameter list + IncrementalSelfTest_Out* out // OUT: output parameter list +) +{ + TPM_RC result; + // Command Output + + // Call incremental self test function in crypt module. If this function + // returns TPM_RC_VALUE, it means that an algorithm on the 'toTest' list is + // not implemented. + result = CryptIncrementalSelfTest(&in->toTest, &out->toDoList); + if(result == TPM_RC_VALUE) + return TPM_RCS_VALUE + RC_IncrementalSelfTest_toTest; + return result; +} + +#endif // CC_IncrementalSelfTest \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Testing/SelfTest.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Testing/SelfTest.c new file mode 100644 index 0000000..97c776e --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Testing/SelfTest.c @@ -0,0 +1,57 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "SelfTest_fp.h" + +#if CC_SelfTest // Conditional expansion of this file + +/*(See part 3 specification) +// perform a test of TPM capabilities +*/ +// Return Type: TPM_RC +// TPM_RC_CANCELED the command was canceled (some incremental +// process may have been made) +// TPM_RC_TESTING self test in process +TPM_RC +TPM2_SelfTest(SelfTest_In* in // IN: input parameter list +) +{ + // Command Output + + // Call self test function in crypt module + return CryptSelfTest(in->fullTest); +} + +#endif // CC_SelfTest \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Vendor/Vendor_TCG_Test.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Vendor/Vendor_TCG_Test.c new file mode 100644 index 0000000..d38d4f1 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/command/Vendor/Vendor_TCG_Test.c @@ -0,0 +1,49 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" + +#if CC_Vendor_TCG_Test // Conditional expansion of this file +# include "Vendor_TCG_Test_fp.h" + +TPM_RC +TPM2_Vendor_TCG_Test(Vendor_TCG_Test_In* in, // IN: input parameter list + Vendor_TCG_Test_Out* out // OUT: output parameter list +) +{ + out->outputData = in->inputData; + return TPM_RC_SUCCESS; +} + +#endif // CC_Vendor_TCG_Test \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/AlgorithmTests.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/AlgorithmTests.c new file mode 100644 index 0000000..6057471 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/AlgorithmTests.c @@ -0,0 +1,912 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// This file contains the code to perform the various self-test functions. +// +// NOTE: In this implementation, large local variables are made static to minimize +// stack usage, which is critical for stack-constrained platforms. + +//** Includes and Defines +#include "Tpm.h" + +#define SELF_TEST_DATA + +#if SELF_TEST + +// These includes pull in the data structures. They contain data definitions for the +// various tests. +# include "SelfTest.h" +# include "SymmetricTest.h" +# include "RsaTestData.h" +# include "EccTestData.h" +# include "HashTestData.h" +# include "KdfTestData.h" + +# define TEST_DEFAULT_TEST_HASH(vector) \ + if(TEST_BIT(DEFAULT_TEST_HASH, g_toTest)) \ + TestHash(DEFAULT_TEST_HASH, vector); + +// Make sure that the algorithm has been tested +# define CLEAR_BOTH(alg) \ + { \ + CLEAR_BIT(alg, *toTest); \ + if(toTest != &g_toTest) \ + CLEAR_BIT(alg, g_toTest); \ + } + +# define SET_BOTH(alg) \ + { \ + SET_BIT(alg, *toTest); \ + if(toTest != &g_toTest) \ + SET_BIT(alg, g_toTest); \ + } + +# define TEST_BOTH(alg) \ + ((toTest != &g_toTest) ? TEST_BIT(alg, *toTest) || TEST_BIT(alg, g_toTest) \ + : TEST_BIT(alg, *toTest)) + +// Can only cancel if doing a list. +# define CHECK_CANCELED \ + if(_plat__IsCanceled() && toTest != &g_toTest) \ + return TPM_RC_CANCELED; + +//** Hash Tests + +//*** Description +// The hash test does a known-value HMAC using the specified hash algorithm. + +//*** TestHash() +// The hash test function. +static TPM_RC TestHash(TPM_ALG_ID hashAlg, ALGORITHM_VECTOR* toTest) +{ + static TPM2B_DIGEST computed; // value computed + static HMAC_STATE state; + UINT16 digestSize; + const TPM2B* testDigest = NULL; + // TPM2B_TYPE(HMAC_BLOCK, DEFAULT_TEST_HASH_BLOCK_SIZE); + + pAssert(hashAlg != TPM_ALG_NULL); +# define HASH_CASE_FOR_TEST(HASH, hash) \ + case ALG_##HASH##_VALUE: \ + testDigest = &c_##HASH##_digest.b; \ + break; + switch(hashAlg) + { + FOR_EACH_HASH(HASH_CASE_FOR_TEST) + + default: + FAIL(FATAL_ERROR_INTERNAL); + } + // Clear the to-test bits + CLEAR_BOTH(hashAlg); + + // If there is an algorithm without test vectors, then assume that things are OK. + if(testDigest == NULL || testDigest->size == 0) + return TPM_RC_SUCCESS; + + // Set the HMAC key to twice the digest size + digestSize = CryptHashGetDigestSize(hashAlg); + CryptHmacStart(&state, hashAlg, digestSize * 2, (BYTE*)c_hashTestKey.t.buffer); + CryptDigestUpdate(&state.hashState, + 2 * CryptHashGetBlockSize(hashAlg), + (BYTE*)c_hashTestData.t.buffer); + computed.t.size = digestSize; + CryptHmacEnd(&state, digestSize, computed.t.buffer); + if((testDigest->size != computed.t.size) + || (memcmp(testDigest->buffer, computed.t.buffer, computed.b.size) != 0)) + SELF_TEST_FAILURE; + return TPM_RC_SUCCESS; +} + +//** Symmetric Test Functions + +//*** MakeIv() +// Internal function to make the appropriate IV depending on the mode. +static UINT32 MakeIv(TPM_ALG_ID mode, // IN: symmetric mode + UINT32 size, // IN: block size of the algorithm + BYTE* iv // OUT: IV to fill in +) +{ + BYTE i; + + if(mode == TPM_ALG_ECB) + return 0; + if(mode == TPM_ALG_CTR) + { + // The test uses an IV that has 0xff in the last byte + for(i = 1; i <= size; i++) + *iv++ = 0xff - (BYTE)(size - i); + } + else + { + for(i = 0; i < size; i++) + *iv++ = i; + } + return size; +} + +//*** TestSymmetricAlgorithm() +// Function to test a specific algorithm, key size, and mode. +static void TestSymmetricAlgorithm(const SYMMETRIC_TEST_VECTOR* test, // + TPM_ALG_ID mode // +) +{ + static BYTE encrypted[MAX_SYM_BLOCK_SIZE * 2]; + static BYTE decrypted[MAX_SYM_BLOCK_SIZE * 2]; + static TPM2B_IV iv; + // + // Get the appropriate IV + iv.t.size = (UINT16)MakeIv(mode, test->ivSize, iv.t.buffer); + + // Encrypt known data + CryptSymmetricEncrypt(encrypted, + test->alg, + test->keyBits, + test->key, + &iv, + mode, + test->dataInOutSize, + test->dataIn); + // Check that it matches the expected value + if(!MemoryEqual( + encrypted, test->dataOut[mode - TPM_ALG_CTR], test->dataInOutSize)) + SELF_TEST_FAILURE; + // Reinitialize the iv for decryption + MakeIv(mode, test->ivSize, iv.t.buffer); + CryptSymmetricDecrypt(decrypted, + test->alg, + test->keyBits, + test->key, + &iv, + mode, + test->dataInOutSize, + test->dataOut[mode - TPM_ALG_CTR]); + // Make sure that it matches what we started with + if(!MemoryEqual(decrypted, test->dataIn, test->dataInOutSize)) + SELF_TEST_FAILURE; +} + +//*** AllSymsAreDone() +// Checks if both symmetric algorithms have been tested. This is put here +// so that addition of a symmetric algorithm will be relatively easy to handle. +// +// Return Type: BOOL +// TRUE(1) all symmetric algorithms tested +// FALSE(0) not all symmetric algorithms tested +static BOOL AllSymsAreDone(ALGORITHM_VECTOR* toTest) +{ + return (!TEST_BOTH(TPM_ALG_AES) && !TEST_BOTH(TPM_ALG_SM4)); +} + +//*** AllModesAreDone() +// Checks if all the modes have been tested. +// +// Return Type: BOOL +// TRUE(1) all modes tested +// FALSE(0) all modes not tested +static BOOL AllModesAreDone(ALGORITHM_VECTOR* toTest) +{ + TPM_ALG_ID alg; + for(alg = SYM_MODE_FIRST; alg <= SYM_MODE_LAST; alg++) + if(TEST_BOTH(alg)) + return FALSE; + return TRUE; +} + +//*** TestSymmetric() +// If 'alg' is a symmetric block cipher, then all of the modes that are selected are +// tested. If 'alg' is a mode, then all algorithms of that mode are tested. +static TPM_RC TestSymmetric(TPM_ALG_ID alg, ALGORITHM_VECTOR* toTest) +{ + SYM_INDEX index; + TPM_ALG_ID mode; + // + if(!TEST_BIT(alg, *toTest)) + return TPM_RC_SUCCESS; + if(alg == TPM_ALG_AES || alg == TPM_ALG_SM4 || alg == TPM_ALG_CAMELLIA) + { + // Will test the algorithm for all modes and key sizes + CLEAR_BOTH(alg); + + // A test this algorithm for all modes + for(index = 0; index < NUM_SYMS; index++) + { + if(c_symTestValues[index].alg == alg) + { + for(mode = SYM_MODE_FIRST; mode <= SYM_MODE_LAST; mode++) + { + if(TEST_BIT(mode, *toTest)) + TestSymmetricAlgorithm(&c_symTestValues[index], mode); + } + } + } + // if all the symmetric tests are done + if(AllSymsAreDone(toTest)) + { + // all symmetric algorithms tested so no modes should be set + for(alg = SYM_MODE_FIRST; alg <= SYM_MODE_LAST; alg++) + CLEAR_BOTH(alg); + } + } + else if(SYM_MODE_FIRST <= alg && alg <= SYM_MODE_LAST) + { + // Test this mode for all key sizes and algorithms + for(index = 0; index < NUM_SYMS; index++) + { + // The mode testing only comes into play when doing self tests + // by command. When doing self tests by command, the block ciphers are + // tested first. That means that all of their modes would have been + // tested for all key sizes. If there is no block cipher left to + // test, then clear this mode bit. + if(!TEST_BIT(TPM_ALG_AES, *toTest) && !TEST_BIT(TPM_ALG_SM4, *toTest)) + { + CLEAR_BOTH(alg); + } + else + { + for(index = 0; index < NUM_SYMS; index++) + { + if(TEST_BIT(c_symTestValues[index].alg, *toTest)) + TestSymmetricAlgorithm(&c_symTestValues[index], alg); + } + // have tested this mode for all algorithms + CLEAR_BOTH(alg); + } + } + if(AllModesAreDone(toTest)) + { + CLEAR_BOTH(TPM_ALG_AES); + CLEAR_BOTH(TPM_ALG_SM4); + } + } + else + pAssert(alg == 0 && alg != 0); + return TPM_RC_SUCCESS; +} + +//** RSA Tests +# if ALG_RSA + +//*** Introduction +// The tests are for public key only operations and for private key operations. +// Signature verification and encryption are public key operations. They are tested +// by using a KVT. For signature verification, this means that a known good +// signature is checked by CryptRsaValidateSignature(). If it fails, then the +// TPM enters failure mode. For encryption, the TPM encrypts known values using +// the selected scheme and checks that the returned value matches the expected +// value. +// +// For private key operations, a full scheme check is used. For a signing key, a +// known key is used to sign a known message. Then that signature is verified. +// since the signature may involve use of random values, the signature will be +// different each time and we can't always check that the signature matches a +// known value. The same technique is used for decryption (RSADP/RSAEP). +// +// When an operation uses the public key and the verification has not been +// tested, the TPM will do a KVT. +// +// The test for the signing algorithm is built into the call for the algorithm + +//*** RsaKeyInitialize() +// The test key is defined by a public modulus and a private prime. The TPM's RSA +// code computes the second prime and the private exponent. +static void RsaKeyInitialize(OBJECT* testObject) +{ + MemoryCopy2B(&testObject->publicArea.unique.rsa.b, + (P2B)&c_rsaPublicModulus, + sizeof(c_rsaPublicModulus)); + MemoryCopy2B(&testObject->sensitive.sensitive.rsa.b, + (P2B)&c_rsaPrivatePrime, + sizeof(testObject->sensitive.sensitive.rsa.t.buffer)); + testObject->publicArea.parameters.rsaDetail.keyBits = RSA_TEST_KEY_SIZE * 8; + // Use the default exponent + testObject->publicArea.parameters.rsaDetail.exponent = 0; +} + +//*** TestRsaEncryptDecrypt() +// These tests are for a public key encryption that uses a random value. +static TPM_RC TestRsaEncryptDecrypt(TPM_ALG_ID scheme, // IN: the scheme + ALGORITHM_VECTOR* toTest // +) +{ + static TPM2B_PUBLIC_KEY_RSA testInput; + static TPM2B_PUBLIC_KEY_RSA testOutput; + static OBJECT testObject; + const TPM2B_RSA_TEST_KEY* kvtValue = NULL; + TPM_RC result = TPM_RC_SUCCESS; + const TPM2B* testLabel = NULL; + TPMT_RSA_DECRYPT rsaScheme; + // + // Don't need to initialize much of the test object + RsaKeyInitialize(&testObject); + rsaScheme.scheme = scheme; + rsaScheme.details.anySig.hashAlg = DEFAULT_TEST_HASH; + CLEAR_BOTH(scheme); + CLEAR_BOTH(TPM_ALG_NULL); + if(scheme == TPM_ALG_NULL) + { + // This is an encryption scheme using the private key without any encoding. + memcpy(testInput.t.buffer, c_RsaTestValue, sizeof(c_RsaTestValue)); + testInput.t.size = sizeof(c_RsaTestValue); + if(TPM_RC_SUCCESS + != CryptRsaEncrypt( + &testOutput, &testInput.b, &testObject, &rsaScheme, NULL, NULL)) + SELF_TEST_FAILURE; + if(!MemoryEqual(testOutput.t.buffer, c_RsaepKvt.buffer, c_RsaepKvt.size)) + SELF_TEST_FAILURE; + MemoryCopy2B(&testInput.b, &testOutput.b, sizeof(testInput.t.buffer)); + if(TPM_RC_SUCCESS + != CryptRsaDecrypt( + &testOutput.b, &testInput.b, &testObject, &rsaScheme, NULL)) + SELF_TEST_FAILURE; + if(!MemoryEqual(testOutput.t.buffer, c_RsaTestValue, sizeof(c_RsaTestValue))) + SELF_TEST_FAILURE; + } + else + { + // TPM_ALG_RSAES: + // This is an decryption scheme using padding according to + // PKCS#1v2.1, 7.2. This padding uses random bits. To test a public + // key encryption that uses random data, encrypt a value and then + // decrypt the value and see that we get the encrypted data back. + // The hash is not used by this encryption so it can be TMP_ALG_NULL + + // TPM_ALG_OAEP: + // This is also an decryption scheme and it also uses a + // pseudo-random + // value. However, this also uses a hash algorithm. So, we may need + // to test that algorithm before use. + if(scheme == TPM_ALG_OAEP) + { + TEST_DEFAULT_TEST_HASH(toTest); + kvtValue = &c_OaepKvt; + testLabel = OAEP_TEST_STRING; + } + else if(scheme == TPM_ALG_RSAES) + { + kvtValue = &c_RsaesKvt; + testLabel = NULL; + } + else + SELF_TEST_FAILURE; + // Only use a digest-size portion of the test value + memcpy(testInput.t.buffer, c_RsaTestValue, DEFAULT_TEST_DIGEST_SIZE); + testInput.t.size = DEFAULT_TEST_DIGEST_SIZE; + + // See if the encryption works + if(TPM_RC_SUCCESS + != CryptRsaEncrypt( + &testOutput, &testInput.b, &testObject, &rsaScheme, testLabel, NULL)) + SELF_TEST_FAILURE; + MemoryCopy2B(&testInput.b, &testOutput.b, sizeof(testInput.t.buffer)); + // see if we can decrypt this value and get the original data back + if(TPM_RC_SUCCESS + != CryptRsaDecrypt( + &testOutput.b, &testInput.b, &testObject, &rsaScheme, testLabel)) + SELF_TEST_FAILURE; + // See if the results compare + if(testOutput.t.size != DEFAULT_TEST_DIGEST_SIZE + || !MemoryEqual( + testOutput.t.buffer, c_RsaTestValue, DEFAULT_TEST_DIGEST_SIZE)) + SELF_TEST_FAILURE; + // Now check that the decryption works on a known value + MemoryCopy2B(&testInput.b, (P2B)kvtValue, sizeof(testInput.t.buffer)); + if(TPM_RC_SUCCESS + != CryptRsaDecrypt( + &testOutput.b, &testInput.b, &testObject, &rsaScheme, testLabel)) + SELF_TEST_FAILURE; + if(testOutput.t.size != DEFAULT_TEST_DIGEST_SIZE + || !MemoryEqual( + testOutput.t.buffer, c_RsaTestValue, DEFAULT_TEST_DIGEST_SIZE)) + SELF_TEST_FAILURE; + } + return result; +} + +//*** TestRsaSignAndVerify() +// This function does the testing of the RSA sign and verification functions. This +// test does a KVT. +static TPM_RC TestRsaSignAndVerify(TPM_ALG_ID scheme, ALGORITHM_VECTOR* toTest) +{ + TPM_RC result = TPM_RC_SUCCESS; + static OBJECT testObject; + static TPM2B_DIGEST testDigest; + static TPMT_SIGNATURE testSig; + + // Do a sign and signature verification. + // RSASSA: + // This is a signing scheme according to PKCS#1-v2.1 8.2. It does not + // use random data so there is a KVT for the signing operation. On + // first use of the scheme for signing, use the TPM's RSA key to + // sign a portion of c_RsaTestData and compare the results to c_RsassaKvt. Then + // decrypt the data to see that it matches the starting value. This verifies + // the signature with a KVT + + // Clear the bits indicating that the function has not been checked. This is to + // prevent looping + CLEAR_BOTH(scheme); + CLEAR_BOTH(TPM_ALG_NULL); + CLEAR_BOTH(TPM_ALG_RSA); + + RsaKeyInitialize(&testObject); + memcpy(testDigest.t.buffer, (BYTE*)c_RsaTestValue, DEFAULT_TEST_DIGEST_SIZE); + testDigest.t.size = DEFAULT_TEST_DIGEST_SIZE; + testSig.sigAlg = scheme; + testSig.signature.rsapss.hash = DEFAULT_TEST_HASH; + + // RSAPSS: + // This is a signing scheme a according to PKCS#1-v2.2 8.1 it uses + // random data in the signature so there is no KVT for the signing + // operation. To test signing, the TPM will use the TPM's RSA key + // to sign a portion of c_RsaTestValue and then it will verify the + // signature. For verification, c_RsapssKvt is verified before the + // user signature blob is verified. The worst case for testing of this + // algorithm is two private and one public key operation. + + // The process is to sign known data. If RSASSA is being done, verify that the + // signature matches the precomputed value. For both, use the signed value and + // see that the verification says that it is a good signature. Then + // if testing RSAPSS, do a verify of a known good signature. This ensures that + // the validation function works. + + if(TPM_RC_SUCCESS != CryptRsaSign(&testSig, &testObject, &testDigest, NULL)) + SELF_TEST_FAILURE; + // For RSASSA, make sure the results is what we are looking for + if(testSig.sigAlg == TPM_ALG_RSASSA) + { + if(testSig.signature.rsassa.sig.t.size != RSA_TEST_KEY_SIZE + || !MemoryEqual(c_RsassaKvt.buffer, + testSig.signature.rsassa.sig.t.buffer, + RSA_TEST_KEY_SIZE)) + SELF_TEST_FAILURE; + } + // See if the TPM will validate its own signatures + if(TPM_RC_SUCCESS + != CryptRsaValidateSignature(&testSig, &testObject, &testDigest)) + SELF_TEST_FAILURE; + // If this is RSAPSS, check the verification with known signature + // Have to copy because CrytpRsaValidateSignature() eats the signature + if(TPM_ALG_RSAPSS == scheme) + { + MemoryCopy2B(&testSig.signature.rsapss.sig.b, + (P2B)&c_RsapssKvt, + sizeof(testSig.signature.rsapss.sig.t.buffer)); + if(TPM_RC_SUCCESS + != CryptRsaValidateSignature(&testSig, &testObject, &testDigest)) + SELF_TEST_FAILURE; + } + return result; +} + +//*** TestRSA() +// Function uses the provided vector to indicate which tests to run. It will clear +// the vector after each test is run and also clear g_toTest +static TPM_RC TestRsa(TPM_ALG_ID alg, ALGORITHM_VECTOR* toTest) +{ + TPM_RC result = TPM_RC_SUCCESS; + // + switch(alg) + { + case TPM_ALG_NULL: + // This is the RSAEP/RSADP function. If we are processing a list, don't + // need to test these now because any other test will validate + // RSAEP/RSADP. Can tell this is list of test by checking to see if + // 'toTest' is pointing at g_toTest. If so, this is an isolated test + // an need to go ahead and do the test; + if((toTest == &g_toTest) + || (!TEST_BIT(TPM_ALG_RSASSA, *toTest) + && !TEST_BIT(TPM_ALG_RSAES, *toTest) + && !TEST_BIT(TPM_ALG_RSAPSS, *toTest) + && !TEST_BIT(TPM_ALG_OAEP, *toTest))) + // Not running a list of tests or no other tests on the list + // so run the test now + result = TestRsaEncryptDecrypt(alg, toTest); + // if not running the test now, leave the bit on, just in case things + // get interrupted + break; + case TPM_ALG_OAEP: + case TPM_ALG_RSAES: + result = TestRsaEncryptDecrypt(alg, toTest); + break; + case TPM_ALG_RSAPSS: + case TPM_ALG_RSASSA: + result = TestRsaSignAndVerify(alg, toTest); + break; + default: + SELF_TEST_FAILURE; + } + return result; +} + +# endif // ALG_RSA + +//** ECC Tests + +# if ALG_ECC + +//*** LoadEccParameter() +// This function is mostly for readability and type checking +static void LoadEccParameter(TPM2B_ECC_PARAMETER* to, // target + const TPM2B_EC_TEST* from // source +) +{ + MemoryCopy2B(&to->b, &from->b, sizeof(to->t.buffer)); +} + +//*** LoadEccPoint() +static void LoadEccPoint(TPMS_ECC_POINT* point, // target + const TPM2B_EC_TEST* x, // source + const TPM2B_EC_TEST* y) +{ + MemoryCopy2B(&point->x.b, (TPM2B*)x, sizeof(point->x.t.buffer)); + MemoryCopy2B(&point->y.b, (TPM2B*)y, sizeof(point->y.t.buffer)); +} + +//*** TestECDH() +// This test does a KVT on a point multiply. +static TPM_RC TestECDH(TPM_ALG_ID scheme, // IN: for consistency + ALGORITHM_VECTOR* toTest // IN/OUT: modified after test is run +) +{ + static TPMS_ECC_POINT Z; + static TPMS_ECC_POINT Qe; + static TPM2B_ECC_PARAMETER ds; + TPM_RC result = TPM_RC_SUCCESS; + // + NOT_REFERENCED(scheme); + CLEAR_BOTH(TPM_ALG_ECDH); + LoadEccParameter(&ds, &c_ecTestKey_ds); + LoadEccPoint(&Qe, &c_ecTestKey_QeX, &c_ecTestKey_QeY); + if(TPM_RC_SUCCESS != CryptEccPointMultiply(&Z, c_testCurve, &Qe, &ds, NULL, NULL)) + SELF_TEST_FAILURE; + if(!MemoryEqual2B(&c_ecTestEcdh_X.b, &Z.x.b) + || !MemoryEqual2B(&c_ecTestEcdh_Y.b, &Z.y.b)) + SELF_TEST_FAILURE; + return result; +} + +//*** TestEccSignAndVerify() +static TPM_RC TestEccSignAndVerify(TPM_ALG_ID scheme, ALGORITHM_VECTOR* toTest) +{ + static OBJECT testObject; + static TPMT_SIGNATURE testSig; + static TPMT_ECC_SCHEME eccScheme; + + testSig.sigAlg = scheme; + testSig.signature.ecdsa.hash = DEFAULT_TEST_HASH; + + eccScheme.scheme = scheme; + eccScheme.details.anySig.hashAlg = DEFAULT_TEST_HASH; + + CLEAR_BOTH(scheme); + CLEAR_BOTH(TPM_ALG_ECDH); + + // ECC signature verification testing uses a KVT. + switch(scheme) + { + case TPM_ALG_ECDSA: + LoadEccParameter(&testSig.signature.ecdsa.signatureR, &c_TestEcDsa_r); + LoadEccParameter(&testSig.signature.ecdsa.signatureS, &c_TestEcDsa_s); + break; + case TPM_ALG_ECSCHNORR: + LoadEccParameter(&testSig.signature.ecschnorr.signatureR, + &c_TestEcSchnorr_r); + LoadEccParameter(&testSig.signature.ecschnorr.signatureS, + &c_TestEcSchnorr_s); + break; + case TPM_ALG_SM2: + // don't have a test for SM2 + return TPM_RC_SUCCESS; + default: + SELF_TEST_FAILURE; + break; + } + TEST_DEFAULT_TEST_HASH(toTest); + + // Have to copy the key. This is because the size used in the test vectors + // is the size of the ECC parameter for the test key while the size of a point + // is TPM dependent + MemoryCopy2B(&testObject.sensitive.sensitive.ecc.b, + &c_ecTestKey_ds.b, + sizeof(testObject.sensitive.sensitive.ecc.t.buffer)); + LoadEccPoint( + &testObject.publicArea.unique.ecc, &c_ecTestKey_QsX, &c_ecTestKey_QsY); + testObject.publicArea.parameters.eccDetail.curveID = c_testCurve; + + if(TPM_RC_SUCCESS + != CryptEccValidateSignature( + &testSig, &testObject, (TPM2B_DIGEST*)&c_ecTestValue.b)) + { + SELF_TEST_FAILURE; + } + CHECK_CANCELED; + + // Now sign and verify some data + if(TPM_RC_SUCCESS + != CryptEccSign( + &testSig, &testObject, (TPM2B_DIGEST*)&c_ecTestValue, &eccScheme, NULL)) + SELF_TEST_FAILURE; + + CHECK_CANCELED; + + if(TPM_RC_SUCCESS + != CryptEccValidateSignature( + &testSig, &testObject, (TPM2B_DIGEST*)&c_ecTestValue)) + SELF_TEST_FAILURE; + + CHECK_CANCELED; + + return TPM_RC_SUCCESS; +} + +//*** TestKDFa() +static TPM_RC TestKDFa(ALGORITHM_VECTOR* toTest) +{ + static TPM2B_KDF_TEST_KEY keyOut; + UINT32 counter = 0; + // + CLEAR_BOTH(TPM_ALG_KDF1_SP800_108); + + keyOut.t.size = CryptKDFa(KDF_TEST_ALG, + &c_kdfTestKeyIn.b, + &c_kdfTestLabel.b, + &c_kdfTestContextU.b, + &c_kdfTestContextV.b, + TEST_KDF_KEY_SIZE * 8, + keyOut.t.buffer, + &counter, + FALSE); + if(keyOut.t.size != TEST_KDF_KEY_SIZE + || !MemoryEqual(keyOut.t.buffer, c_kdfTestKeyOut.t.buffer, TEST_KDF_KEY_SIZE)) + SELF_TEST_FAILURE; + + return TPM_RC_SUCCESS; +} + +//*** TestEcc() +static TPM_RC TestEcc(TPM_ALG_ID alg, ALGORITHM_VECTOR* toTest) +{ + TPM_RC result = TPM_RC_SUCCESS; + NOT_REFERENCED(toTest); + switch(alg) + { + case TPM_ALG_ECC: + case TPM_ALG_ECDH: + // If this is in a loop then see if another test is going to deal with + // this. + // If toTest is not a self-test list + if((toTest == &g_toTest) + // or this is the only ECC test in the list + || !(TEST_BIT(TPM_ALG_ECDSA, *toTest) + || TEST_BIT(ALG_ECSCHNORR, *toTest) + || TEST_BIT(TPM_ALG_SM2, *toTest))) + { + result = TestECDH(alg, toTest); + } + break; + case TPM_ALG_ECDSA: + case TPM_ALG_ECSCHNORR: + case TPM_ALG_SM2: + result = TestEccSignAndVerify(alg, toTest); + break; + default: + SELF_TEST_FAILURE; + break; + } + return result; +} + +# endif // ALG_ECC + +//*** TestAlgorithm() +// Dispatches to the correct test function for the algorithm or gets a list of +// testable algorithms. +// +// If 'toTest' is not NULL, then the test decisions are based on the algorithm +// selections in 'toTest'. Otherwise, 'g_toTest' is used. When bits are clear in +// 'g_toTest' they will also be cleared 'toTest'. +// +// If there doesn't happen to be a test for the algorithm, its associated bit is +// quietly cleared. +// +// If 'alg' is zero (TPM_ALG_ERROR), then the toTest vector is cleared of any bits +// for which there is no test (i.e. no tests are actually run but the vector is +// cleared). +// +// Note: 'toTest' will only ever have bits set for implemented algorithms but 'alg' +// can be anything. +// +// Return Type: TPM_RC +// TPM_RC_CANCELED test was canceled +LIB_EXPORT +TPM_RC +TestAlgorithm(TPM_ALG_ID alg, ALGORITHM_VECTOR* toTest) +{ + TPM_ALG_ID first = (alg == TPM_ALG_ERROR) ? TPM_ALG_FIRST : alg; + TPM_ALG_ID last = (alg == TPM_ALG_ERROR) ? TPM_ALG_LAST : alg; + BOOL doTest = (alg != TPM_ALG_ERROR); + TPM_RC result = TPM_RC_SUCCESS; + + if(toTest == NULL) + toTest = &g_toTest; + + // This is kind of strange. This function will either run a test of the selected + // algorithm or just clear a bit if there is no test for the algorithm. So, + // either this loop will be executed once for the selected algorithm or once for + // each of the possible algorithms. If it is executed more than once ('alg' == + // ALG_ERROR), then no test will be run but bits will be cleared for + // unimplemented algorithms. This was done this way so that there is only one + // case statement with all of the algorithms. It was easier to have one case + // statement than to have multiple ones to manage whenever an algorithm ID is + // added. + for(alg = first; (alg <= last); alg++) + { + // if 'alg' was TPM_ALG_ERROR, then we will be cycling through + // values, some of which may not be implemented. If the bit in toTest + // happens to be set, then we could either generated an assert, or just + // silently CLEAR it. Decided to just clear. + if(!TEST_BIT(alg, g_implementedAlgorithms)) + { + CLEAR_BIT(alg, *toTest); + continue; + } + // Process whatever is left. + // NOTE: since this switch will only be called if the algorithm is + // implemented, it is not necessary to modify this list except to comment + // out the algorithms for which there is no test + switch(alg) + { + // Symmetric block ciphers +# if ALG_AES + case TPM_ALG_AES: +# endif // ALG_AES +# if ALG_SM4 + // if SM4 is implemented, its test is like other block ciphers but there + // aren't any test vectors for it yet +// case TPM_ALG_SM4: +# endif // ALG_SM4 +# if ALG_CAMELLIA + // no test vectors for camellia +// case TPM_ALG_CAMELLIA: +# endif + // Symmetric modes +# if !ALG_CFB +# error CFB is required in all TPM implementations +# endif // !ALG_CFB + case TPM_ALG_CFB: + if(doTest) + result = TestSymmetric(alg, toTest); + break; +# if ALG_CTR + case TPM_ALG_CTR: +# endif // ALG_CRT +# if ALG_OFB + case TPM_ALG_OFB: +# endif // ALG_OFB +# if ALG_CBC + case TPM_ALG_CBC: +# endif // ALG_CBC +# if ALG_ECB + case TPM_ALG_ECB: +# endif + if(doTest) + result = TestSymmetric(alg, toTest); + else + // If doing the initialization of g_toTest vector, only need + // to test one of the modes for the symmetric algorithms. If + // initializing for a SelfTest(FULL_TEST), allow all the modes. + if(toTest == &g_toTest) + CLEAR_BIT(alg, *toTest); + break; +# if !ALG_HMAC +# error HMAC is required in all TPM implementations +# endif + case TPM_ALG_HMAC: + // Clear the bit that indicates that HMAC is required because + // HMAC is used as the basic test for all hash algorithms. + CLEAR_BOTH(alg); + // Testing HMAC means test the default hash + if(doTest) + TestHash(DEFAULT_TEST_HASH, toTest); + else + // If not testing, then indicate that the hash needs to be + // tested because this uses HMAC + SET_BOTH(DEFAULT_TEST_HASH); + break; +// Have to use two arguments for the macro even though only the first is used in the +// expansion. +# define HASH_CASE_TEST(HASH, hash) case ALG_##HASH##_VALUE: + FOR_EACH_HASH(HASH_CASE_TEST) +# undef HASH_CASE_TEST + if(doTest) + result = TestHash(alg, toTest); + break; + // RSA-dependent +# if ALG_RSA + case TPM_ALG_RSA: + CLEAR_BOTH(alg); + if(doTest) + result = TestRsa(TPM_ALG_NULL, toTest); + else + SET_BOTH(TPM_ALG_NULL); + break; + case TPM_ALG_RSASSA: + case TPM_ALG_RSAES: + case TPM_ALG_RSAPSS: + case TPM_ALG_OAEP: + case TPM_ALG_NULL: // used or RSADP + if(doTest) + result = TestRsa(alg, toTest); + break; +# endif // ALG_RSA +# if ALG_KDF1_SP800_108 + case TPM_ALG_KDF1_SP800_108: + if(doTest) + result = TestKDFa(toTest); + break; +# endif // ALG_KDF1_SP800_108 +# if ALG_ECC + // ECC dependent but no tests + // case TPM_ALG_ECDAA: + // case TPM_ALG_ECMQV: + // case TPM_ALG_KDF1_SP800_56a: + // case TPM_ALG_KDF2: + // case TPM_ALG_MGF1: + case TPM_ALG_ECC: + CLEAR_BOTH(alg); + if(doTest) + result = TestEcc(TPM_ALG_ECDH, toTest); + else + SET_BOTH(TPM_ALG_ECDH); + break; + case TPM_ALG_ECDSA: + case TPM_ALG_ECDH: + case TPM_ALG_ECSCHNORR: + // case TPM_ALG_SM2: + if(doTest) + result = TestEcc(alg, toTest); + break; +# endif // ALG_ECC + default: + CLEAR_BIT(alg, *toTest); + break; + } + if(result != TPM_RC_SUCCESS) + break; + } + return result; +} + +#endif // SELF_TESTS \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/BnConvert.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/BnConvert.c new file mode 100644 index 0000000..d682cc8 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/BnConvert.c @@ -0,0 +1,278 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// This file contains the basic conversion functions that will convert TPM2B +// to/from the internal format. The internal format is a bigNum, +// + +//** Includes + +#include "Tpm.h" + +//** Functions + +//*** BnFromBytes() +// This function will convert a big-endian byte array to the internal number +// format. If bn is NULL, then the output is NULL. If bytes is null or the +// required size is 0, then the output is set to zero +LIB_EXPORT bigNum BnFromBytes(bigNum bn, const BYTE* bytes, NUMBYTES nBytes) +{ + const BYTE* pFrom; // 'p' points to the least significant bytes of source + BYTE* pTo; // points to least significant bytes of destination + crypt_uword_t size; + // + + size = (bytes != NULL) ? BYTES_TO_CRYPT_WORDS(nBytes) : 0; + + // If nothing in, nothing out + if(bn == NULL) + return NULL; + + // make sure things fit + pAssert(BnGetAllocated(bn) >= size); + + if(size > 0) + { + // Clear the topmost word in case it is not filled with data + bn->d[size - 1] = 0; + // Moving the input bytes from the end of the list (LSB) end + pFrom = bytes + nBytes - 1; + // To the LS0 of the LSW of the bigNum. + pTo = (BYTE*)bn->d; + for(; nBytes != 0; nBytes--) + *pTo++ = *pFrom--; + // For a little-endian machine, the conversion is a straight byte + // reversal. For a big-endian machine, we have to put the words in + // big-endian byte order +#if BIG_ENDIAN_TPM + { + crypt_word_t t; + for(t = (crypt_word_t)size - 1; t >= 0; t--) + bn->d[t] = SWAP_CRYPT_WORD(bn->d[t]); + } +#endif + } + BnSetTop(bn, size); + return bn; +} + +//*** BnFrom2B() +// Convert an TPM2B to a BIG_NUM. +// If the input value does not exist, or the output does not exist, or the input +// will not fit into the output the function returns NULL +LIB_EXPORT bigNum BnFrom2B(bigNum bn, // OUT: + const TPM2B* a2B // IN: number to convert +) +{ + if(a2B != NULL) + return BnFromBytes(bn, a2B->buffer, a2B->size); + // Make sure that the number has an initialized value rather than whatever + // was there before + BnSetTop(bn, 0); // Function accepts NULL + return NULL; +} + +//*** BnFromHex() +// Convert a hex string into a bigNum. This is primarily used in debugging. +LIB_EXPORT bigNum BnFromHex(bigNum bn, // OUT: + const char* hex // IN: +) +{ +#define FromHex(a) ((a) - (((a) > 'a') ? ('a' + 10) : ((a) > 'A') ? ('A' - 10) : '0')) + unsigned i; + unsigned wordCount; + const char* p; + BYTE* d = (BYTE*)&(bn->d[0]); + // + pAssert(bn && hex); + i = (unsigned)strlen(hex); + wordCount = BYTES_TO_CRYPT_WORDS((i + 1) / 2); + if((i == 0) || (wordCount >= BnGetAllocated(bn))) + BnSetWord(bn, 0); + else + { + bn->d[wordCount - 1] = 0; + p = hex + i - 1; + for(; i > 1; i -= 2) + { + BYTE a; + a = FromHex(*p); + p--; + *d++ = a + (FromHex(*p) << 4); + p--; + } + if(i == 1) + *d = FromHex(*p); + } +#if !BIG_ENDIAN_TPM + for(i = 0; i < wordCount; i++) + bn->d[i] = SWAP_CRYPT_WORD(bn->d[i]); +#endif // BIG_ENDIAN_TPM + BnSetTop(bn, wordCount); + return bn; +} + +//*** BnToBytes() +// This function converts a BIG_NUM to a byte array. It converts the bigNum to a +// big-endian byte string and sets 'size' to the normalized value. If 'size' is an +// input 0, then the receiving buffer is guaranteed to be large enough for the result +// and the size will be set to the size required for bigNum (leading zeros +// suppressed). +// +// The conversion for a little-endian machine simply requires that all significant +// bytes of the bigNum be reversed. For a big-endian machine, rather than +// unpack each word individually, the bigNum is converted to little-endian words, +// copied, and then converted back to big-endian. +LIB_EXPORT BOOL BnToBytes(bigConst bn, + BYTE* buffer, + NUMBYTES* size // This the number of bytes that are + // available in the buffer. The result + // should be this big. +) +{ + crypt_uword_t requiredSize; + BYTE* pFrom; + BYTE* pTo; + crypt_uword_t count; + // + // validate inputs + pAssert(bn && buffer && size); + + requiredSize = (BnSizeInBits(bn) + 7) / 8; + if(requiredSize == 0) + { + // If the input value is 0, return a byte of zero + *size = 1; + *buffer = 0; + } + else + { +#if BIG_ENDIAN_TPM + // Copy the constant input value into a modifiable value + BN_VAR(bnL, LARGEST_NUMBER_BITS * 2); + BnCopy(bnL, bn); + // byte swap the words in the local value to make them little-endian + for(count = 0; count < bnL->size; count++) + bnL->d[count] = SWAP_CRYPT_WORD(bnL->d[count]); + bn = (bigConst)bnL; +#endif + if(*size == 0) + *size = (NUMBYTES)requiredSize; + pAssert(requiredSize <= *size); + // Byte swap the number (not words but the whole value) + count = *size; + // Start from the least significant word and offset to the most significant + // byte which is in some high word + pFrom = (BYTE*)(&bn->d[0]) + requiredSize - 1; + pTo = buffer; + + // If the number of output bytes is larger than the number bytes required + // for the input number, pad with zeros + for(count = *size; count > requiredSize; count--) + *pTo++ = 0; + // Move the most significant byte at the end of the BigNum to the next most + // significant byte position of the 2B and repeat for all significant bytes. + for(; requiredSize > 0; requiredSize--) + *pTo++ = *pFrom--; + } + return TRUE; +} + +//*** BnTo2B() +// Function to convert a BIG_NUM to TPM2B. +// The TPM2B size is set to the requested 'size' which may require padding. +// If 'size' is non-zero and less than required by the value in 'bn' then an error +// is returned. If 'size' is zero, then the TPM2B is assumed to be large enough +// for the data and a2b->size will be adjusted accordingly. +LIB_EXPORT BOOL BnTo2B(bigConst bn, // IN: + TPM2B* a2B, // OUT: + NUMBYTES size // IN: the desired size +) +{ + // Set the output size + if(bn && a2B) + { + a2B->size = size; + return BnToBytes(bn, a2B->buffer, &a2B->size); + } + return FALSE; +} + +#if ALG_ECC + +//*** BnPointFrom2B() +// Function to create a BIG_POINT structure from a 2B point. +// A point is going to be two ECC values in the same buffer. The values are going +// to be the size of the modulus. They are in modular form. +LIB_EXPORT bn_point_t* BnPointFrom2B( + bigPoint ecP, // OUT: the preallocated point structure + TPMS_ECC_POINT* p // IN: the number to convert +) +{ + if(p == NULL) + return NULL; + + if(NULL != ecP) + { + BnFrom2B(ecP->x, &p->x.b); + BnFrom2B(ecP->y, &p->y.b); + BnSetWord(ecP->z, 1); + } + return ecP; +} + +//*** BnPointTo2B() +// This function converts a BIG_POINT into a TPMS_ECC_POINT. A TPMS_ECC_POINT +// contains two TPM2B_ECC_PARAMETER values. The maximum size of the parameters +// is dependent on the maximum EC key size used in an implementation. +// The presumption is that the TPMS_ECC_POINT is large enough to hold 2 TPM2B +// values, each as large as a MAX_ECC_PARAMETER_BYTES +LIB_EXPORT BOOL BnPointTo2B(TPMS_ECC_POINT* p, // OUT: the converted 2B structure + bigPoint ecP, // IN: the values to be converted + bigCurve E // IN: curve descriptor for the point +) +{ + UINT16 size; + // + pAssert(p && ecP && E); + pAssert(BnEqualWord(ecP->z, 1)); + // BnMsb is the bit number of the MSB. This is one less than the number of bits + size = (UINT16)BITS_TO_BYTES(BnSizeInBits(CurveGetOrder(AccessCurveData(E)))); + BnTo2B(ecP->x, &p->x.b, size); + BnTo2B(ecP->y, &p->y.b, size); + return TRUE; +} + +#endif // ALG_ECC \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/BnMath.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/BnMath.c new file mode 100644 index 0000000..d6f69a3 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/BnMath.c @@ -0,0 +1,536 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// The simulator code uses the canonical form whenever possible in order to make +// the code in Part 3 more accessible. The canonical data formats are simple and +// not well suited for complex big number computations. When operating on big +// numbers, the data format is changed for easier manipulation. The format is native +// words in little-endian format. As the magnitude of the number decreases, the +// length of the array containing the number decreases but the starting address +// doesn't change. +// +// The functions in this file perform simple operations on these big numbers. Only +// the more complex operations are passed to the underlying support library. +// Although the support library would have most of these functions, the interface +// code to convert the format for the values is greater than the size of the +// code to implement the functions here. So, rather than incur the overhead of +// conversion, they are done here. +// +// If an implementer would prefer, the underlying library can be used simply by +// making code substitutions here. +// +// NOTE: There is an intention to continue to augment these functions so that there +// would be no need to use an external big number library. +// +// Many of these functions have no error returns and will always return TRUE. This +// is to allow them to be used in "guarded" sequences. That is: +// OK = OK || BnSomething(s); +// where the BnSomething() function should not be called if OK isn't true. + +//** Includes +#include "Tpm.h" + +// A constant value of zero as a stand in for NULL bigNum values +const bignum_t BnConstZero = {1, 0, {0}}; + +//** Functions + +//*** AddSame() +// Adds two values that are the same size. This function allows 'result' to be +// the same as either of the addends. This is a nice function to put into assembly +// because handling the carry for multi-precision stuff is not as easy in C +// (unless there is a REALLY smart compiler). It would be nice if there were idioms +// in a language that a compiler could recognize what is going on and optimize +// loops like this. +// Return Type: int +// 0 no carry out +// 1 carry out +static BOOL AddSame(crypt_uword_t* result, + const crypt_uword_t* op1, + const crypt_uword_t* op2, + int count) +{ + int carry = 0; + int i; + + for(i = 0; i < count; i++) + { + crypt_uword_t a = op1[i]; + crypt_uword_t sum = a + op2[i]; + result[i] = sum + carry; + // generate a carry if the sum is less than either of the inputs + // propagate a carry if there was a carry and the sum + carry is zero + // do this using bit operations rather than logical operations so that + // the time is about the same. + // propagate term | generate term + carry = ((result[i] == 0) & carry) | (sum < a); + } + return carry; +} + +//*** CarryProp() +// Propagate a carry +static int CarryProp( + crypt_uword_t* result, const crypt_uword_t* op, int count, int carry) +{ + for(; count; count--) + carry = ((*result++ = *op++ + carry) == 0) & carry; + return carry; +} + +static void CarryResolve(bigNum result, int stop, int carry) +{ + if(carry) + { + pAssert((unsigned)stop < result->allocated); + result->d[stop++] = 1; + } + BnSetTop(result, stop); +} + +//*** BnAdd() +// This function adds two bigNum values. This function always returns TRUE. +LIB_EXPORT BOOL BnAdd(bigNum result, bigConst op1, bigConst op2) +{ + crypt_uword_t stop; + int carry; + const bignum_t* n1 = op1; + const bignum_t* n2 = op2; + + // + if(n2->size > n1->size) + { + n1 = op2; + n2 = op1; + } + pAssert(result->allocated >= n1->size); + stop = MIN(n1->size, n2->allocated); + carry = (int)AddSame(result->d, n1->d, n2->d, (int)stop); + if(n1->size > stop) + carry = + CarryProp(&result->d[stop], &n1->d[stop], (int)(n1->size - stop), carry); + CarryResolve(result, (int)n1->size, carry); + return TRUE; +} + +//*** BnAddWord() +// This function adds a word value to a bigNum. This function always returns TRUE. +LIB_EXPORT BOOL BnAddWord(bigNum result, bigConst op, crypt_uword_t word) +{ + int carry; + // + carry = (result->d[0] = op->d[0] + word) < word; + carry = CarryProp(&result->d[1], &op->d[1], (int)(op->size - 1), carry); + CarryResolve(result, (int)op->size, carry); + return TRUE; +} + +//*** SubSame() +// This function subtracts two values that have the same size. +static int SubSame(crypt_uword_t* result, + const crypt_uword_t* op1, + const crypt_uword_t* op2, + int count) +{ + int borrow = 0; + int i; + for(i = 0; i < count; i++) + { + crypt_uword_t a = op1[i]; + crypt_uword_t diff = a - op2[i]; + result[i] = diff - borrow; + // generate | propagate + borrow = (diff > a) | ((diff == 0) & borrow); + } + return borrow; +} + +//*** BorrowProp() +// This propagates a borrow. If borrow is true when the end +// of the array is reached, then it means that op2 was larger than +// op1 and we don't handle that case so an assert is generated. +// This design choice was made because our only bigNum computations +// are on large positive numbers (primes) or on fields. +// Propagate a borrow. +static int BorrowProp( + crypt_uword_t* result, const crypt_uword_t* op, int size, int borrow) +{ + for(; size > 0; size--) + borrow = ((*result++ = *op++ - borrow) == MAX_CRYPT_UWORD) && borrow; + return borrow; +} + +//*** BnSub() +// This function does subtraction of two bigNum values and returns result = op1 - op2 +// when op1 is greater than op2. If op2 is greater than op1, then a fault is +// generated. This function always returns TRUE. +LIB_EXPORT BOOL BnSub(bigNum result, bigConst op1, bigConst op2) +{ + int borrow; + int stop = (int)MIN(op1->size, op2->allocated); + // + // Make sure that op2 is not obviously larger than op1 + pAssert(op1->size >= op2->size); + borrow = SubSame(result->d, op1->d, op2->d, stop); + if(op1->size > (crypt_uword_t)stop) + borrow = BorrowProp( + &result->d[stop], &op1->d[stop], (int)(op1->size - stop), borrow); + pAssert(!borrow); + BnSetTop(result, op1->size); + return TRUE; +} + +//*** BnSubWord() +// This function subtracts a word value from a bigNum. This function always +// returns TRUE. +LIB_EXPORT BOOL BnSubWord(bigNum result, bigConst op, crypt_uword_t word) +{ + int borrow; + // + pAssert(op->size > 1 || word <= op->d[0]); + borrow = word > op->d[0]; + result->d[0] = op->d[0] - word; + borrow = BorrowProp(&result->d[1], &op->d[1], (int)(op->size - 1), borrow); + pAssert(!borrow); + BnSetTop(result, op->size); + return TRUE; +} + +//*** BnUnsignedCmp() +// This function performs a comparison of op1 to op2. The compare is approximately +// constant time if the size of the values used in the compare is consistent +// across calls (from the same line in the calling code). +// Return Type: int +// < 0 op1 is less than op2 +// 0 op1 is equal to op2 +// > 0 op1 is greater than op2 +LIB_EXPORT int BnUnsignedCmp(bigConst op1, bigConst op2) +{ + int retVal; + int diff; + int i; + // + pAssert((op1 != NULL) && (op2 != NULL)); + retVal = (int)(op1->size - op2->size); + if(retVal == 0) + { + for(i = (int)(op1->size - 1); i >= 0; i--) + { + diff = (op1->d[i] < op2->d[i]) ? -1 : (op1->d[i] != op2->d[i]); + retVal = retVal == 0 ? diff : retVal; + } + } + else + retVal = (retVal < 0) ? -1 : 1; + return retVal; +} + +//*** BnUnsignedCmpWord() +// Compare a bigNum to a crypt_uword_t. +// Return Type: int +// -1 op1 is less that word +// 0 op1 is equal to word +// 1 op1 is greater than word +LIB_EXPORT int BnUnsignedCmpWord(bigConst op1, crypt_uword_t word) +{ + if(op1->size > 1) + return 1; + else if(op1->size == 1) + return (op1->d[0] < word) ? -1 : (op1->d[0] > word); + else // op1 is zero + // equal if word is zero + return (word == 0) ? 0 : -1; +} + +//*** BnModWord() +// This function does modular division of a big number when the modulus is a +// word value. +LIB_EXPORT crypt_word_t BnModWord(bigConst numerator, crypt_word_t modulus) +{ + BN_MAX(remainder); + BN_VAR(mod, RADIX_BITS); + // + mod->d[0] = modulus; + mod->size = (modulus != 0); + BnDiv(NULL, remainder, numerator, mod); + return remainder->d[0]; +} + +//*** Msb() +// This function returns the bit number of the most significant bit of a +// crypt_uword_t. The number for the least significant bit of any bigNum value is 0. +// The maximum return value is RADIX_BITS - 1, +// Return Type: int +// -1 the word was zero +// n the bit number of the most significant bit in the word +LIB_EXPORT int Msb(crypt_uword_t word) +{ + int retVal = -1; +// +#if RADIX_BITS == 64 + if(word & 0xffffffff00000000) + { + retVal += 32; + word >>= 32; + } +#endif + if(word & 0xffff0000) + { + retVal += 16; + word >>= 16; + } + if(word & 0x0000ff00) + { + retVal += 8; + word >>= 8; + } + if(word & 0x000000f0) + { + retVal += 4; + word >>= 4; + } + if(word & 0x0000000c) + { + retVal += 2; + word >>= 2; + } + if(word & 0x00000002) + { + retVal += 1; + word >>= 1; + } + return retVal + (int)word; +} + +//*** BnMsb() +// This function returns the number of the MSb of a bigNum value. +// Return Type: int +// -1 the word was zero or 'bn' was NULL +// n the bit number of the most significant bit in the word +LIB_EXPORT int BnMsb(bigConst bn) +{ + // If the value is NULL, or the size is zero then treat as zero and return -1 + if(bn != NULL && bn->size > 0) + { + int retVal = Msb(bn->d[bn->size - 1]); + retVal += (int)(bn->size - 1) * RADIX_BITS; + return retVal; + } + else + return -1; +} + +//*** BnSizeInBits() +// This function returns the number of bits required to hold a number. It is one +// greater than the Msb. +// +LIB_EXPORT unsigned BnSizeInBits(bigConst n) +{ + int bits = BnMsb(n) + 1; + // + return bits < 0 ? 0 : (unsigned)bits; +} + +//*** BnSetWord() +// Change the value of a bignum_t to a word value. +LIB_EXPORT bigNum BnSetWord(bigNum n, crypt_uword_t w) +{ + if(n != NULL) + { + pAssert(n->allocated > 1); + n->d[0] = w; + BnSetTop(n, (w != 0) ? 1 : 0); + } + return n; +} + +//*** BnSetBit() +// This function will SET a bit in a bigNum. Bit 0 is the least-significant bit in +// the 0th digit_t. The function always return TRUE +LIB_EXPORT BOOL BnSetBit(bigNum bn, // IN/OUT: big number to modify + unsigned int bitNum // IN: Bit number to SET +) +{ + crypt_uword_t offset = bitNum / RADIX_BITS; + pAssert(bn->allocated * RADIX_BITS >= bitNum); + // Grow the number if necessary to set the bit. + while(bn->size <= offset) + bn->d[bn->size++] = 0; + bn->d[offset] |= ((crypt_uword_t)1 << RADIX_MOD(bitNum)); + return TRUE; +} + +//*** BnTestBit() +// This function is used to check to see if a bit is SET in a bignum_t. The 0th bit +// is the LSb of d[0]. +// Return Type: BOOL +// TRUE(1) the bit is set +// FALSE(0) the bit is not set or the number is out of range +LIB_EXPORT BOOL BnTestBit(bigNum bn, // IN: number to check + unsigned int bitNum // IN: bit to test +) +{ + crypt_uword_t offset = RADIX_DIV(bitNum); + // + if(bn->size > offset) + return ((bn->d[offset] & (((crypt_uword_t)1) << RADIX_MOD(bitNum))) != 0); + else + return FALSE; +} + +//***BnMaskBits() +// This function is used to mask off high order bits of a big number. +// The returned value will have no more than 'maskBit' bits +// set. +// Note: There is a requirement that unused words of a bignum_t are set to zero. +// Return Type: BOOL +// TRUE(1) result masked +// FALSE(0) the input was not as large as the mask +LIB_EXPORT BOOL BnMaskBits(bigNum bn, // IN/OUT: number to mask + crypt_uword_t maskBit // IN: the bit number for the mask. +) +{ + crypt_uword_t finalSize; + BOOL retVal; + + finalSize = BITS_TO_CRYPT_WORDS(maskBit); + retVal = (finalSize <= bn->allocated); + if(retVal && (finalSize > 0)) + { + crypt_uword_t mask; + mask = ~((crypt_uword_t)0) >> RADIX_MOD(maskBit); + bn->d[finalSize - 1] &= mask; + } + BnSetTop(bn, finalSize); + return retVal; +} + +//*** BnShiftRight() +// This function will shift a bigNum to the right by the shiftAmount. +// This function always returns TRUE. +LIB_EXPORT BOOL BnShiftRight(bigNum result, bigConst toShift, uint32_t shiftAmount) +{ + uint32_t offset = (shiftAmount >> RADIX_LOG2); + uint32_t i; + uint32_t shiftIn; + crypt_uword_t finalSize; + // + shiftAmount = shiftAmount & RADIX_MASK; + shiftIn = RADIX_BITS - shiftAmount; + + // The end size is toShift->size - offset less one additional + // word if the shiftAmount would make the upper word == 0 + if(toShift->size > offset) + { + finalSize = toShift->size - offset; + finalSize -= (toShift->d[toShift->size - 1] >> shiftAmount) == 0 ? 1 : 0; + } + else + finalSize = 0; + + pAssert(finalSize <= result->allocated); + if(finalSize != 0) + { + for(i = 0; i < finalSize; i++) + { + result->d[i] = (toShift->d[i + offset] >> shiftAmount) + | (toShift->d[i + offset + 1] << shiftIn); + } + if(offset == 0) + result->d[i] = toShift->d[i] >> shiftAmount; + } + BnSetTop(result, finalSize); + return TRUE; +} + +//*** BnGetRandomBits() +// This function gets random bits for use in various places. To make sure that the +// number is generated in a portable format, it is created as a TPM2B and then +// converted to the internal format. +// +// One consequence of the generation scheme is that, if the number of bits requested +// is not a multiple of 8, then the high-order bits are set to zero. This would come +// into play when generating a 521-bit ECC key. A 66-byte (528-bit) value is +// generated an the high order 7 bits are masked off (CLEAR). +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure +LIB_EXPORT BOOL BnGetRandomBits(bigNum n, size_t bits, RAND_STATE* rand) +{ + // Since this could be used for ECC key generation using the extra bits method, + // make sure that the value is large enough + TPM2B_TYPE(LARGEST, LARGEST_NUMBER + 8); + TPM2B_LARGEST large; + // + large.b.size = (UINT16)BITS_TO_BYTES(bits); + if(DRBG_Generate(rand, large.t.buffer, large.t.size) == large.t.size) + { + if(BnFrom2B(n, &large.b) != NULL) + { + if(BnMaskBits(n, (crypt_uword_t)bits)) + return TRUE; + } + } + return FALSE; +} + +//*** BnGenerateRandomInRange() +// This function is used to generate a random number r in the range 1 <= r < limit. +// The function gets a random number of bits that is the size of limit. There is some +// some probability that the returned number is going to be greater than or equal +// to the limit. If it is, try again. There is no more than 50% chance that the +// next number is also greater, so try again. We keep trying until we get a +// value that meets the criteria. Since limit is very often a number with a LOT of +// high order ones, this rarely would need a second try. +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure ('limit' is too small) +LIB_EXPORT BOOL BnGenerateRandomInRange(bigNum dest, bigConst limit, RAND_STATE* rand) +{ + size_t bits = BnSizeInBits(limit); + // + if(bits < 2) + { + BnSetWord(dest, 0); + return FALSE; + } + else + { + while(BnGetRandomBits(dest, bits, rand) + && (BnEqualZero(dest) || (BnUnsignedCmp(dest, limit) >= 0))) + ; + } + return !g_inFailureMode; +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/BnMemory.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/BnMemory.c new file mode 100644 index 0000000..3b9e904 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/BnMemory.c @@ -0,0 +1,166 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// This file contains the memory setup functions used by the bigNum functions +// in CryptoEngine + +//** Includes +#include "Tpm.h" + +//** Functions + +//*** BnSetTop() +// This function is used when the size of a bignum_t is changed. It +// makes sure that the unused words are set to zero and that any significant +// words of zeros are eliminated from the used size indicator. +LIB_EXPORT bigNum BnSetTop(bigNum bn, // IN/OUT: number to clean + crypt_uword_t top // IN: the new top +) +{ + if(bn != NULL) + { + pAssert(top <= bn->allocated); + // If forcing the size to be decreased, make sure that the words being + // discarded are being set to 0 + while(bn->size > top) + bn->d[--bn->size] = 0; + bn->size = top; + // Now make sure that the words that are left are 'normalized' (no high-order + // words of zero. + while((bn->size > 0) && (bn->d[bn->size - 1] == 0)) + bn->size -= 1; + } + return bn; +} + +//*** BnClearTop() +// This function will make sure that all unused words are zero. +LIB_EXPORT bigNum BnClearTop(bigNum bn) +{ + crypt_uword_t i; + // + if(bn != NULL) + { + for(i = bn->size; i < bn->allocated; i++) + bn->d[i] = 0; + while((bn->size > 0) && (bn->d[bn->size] == 0)) + bn->size -= 1; + } + return bn; +} + +//*** BnInitializeWord() +// This function is used to initialize an allocated bigNum with a word value. The +// bigNum does not have to be allocated with a single word. +LIB_EXPORT bigNum BnInitializeWord(bigNum bn, // IN: + crypt_uword_t allocated, // IN: + crypt_uword_t word // IN: +) +{ + bn->allocated = allocated; + bn->size = (word != 0); + bn->d[0] = word; + while(allocated > 1) + bn->d[--allocated] = 0; + return bn; +} + +//*** BnInit() +// This function initializes a stack allocated bignum_t. It initializes +// 'allocated' and 'size' and zeros the words of 'd'. +LIB_EXPORT bigNum BnInit(bigNum bn, crypt_uword_t allocated) +{ + if(bn != NULL) + { + bn->allocated = allocated; + bn->size = 0; + while(allocated != 0) + bn->d[--allocated] = 0; + } + return bn; +} + +//*** BnCopy() +// Function to copy a bignum_t. If the output is NULL, then +// nothing happens. If the input is NULL, the output is set +// to zero. +LIB_EXPORT BOOL BnCopy(bigNum out, bigConst in) +{ + if(in == out) + BnSetTop(out, BnGetSize(out)); + else if(out != NULL) + { + if(in != NULL) + { + unsigned int i; + pAssert(BnGetAllocated(out) >= BnGetSize(in)); + for(i = 0; i < BnGetSize(in); i++) + out->d[i] = in->d[i]; + BnSetTop(out, BnGetSize(in)); + } + else + BnSetTop(out, 0); + } + return TRUE; +} + +#if ALG_ECC + +//*** BnPointCopy() +// Function to copy a bn point. +LIB_EXPORT BOOL BnPointCopy(bigPoint pOut, pointConst pIn) +{ + return BnCopy(pOut->x, pIn->x) && BnCopy(pOut->y, pIn->y) + && BnCopy(pOut->z, pIn->z); +} + +//*** BnInitializePoint() +// This function is used to initialize a point structure with the addresses +// of the coordinates. +LIB_EXPORT bn_point_t* BnInitializePoint( + bigPoint p, // OUT: structure to receive pointers + bigNum x, // IN: x coordinate + bigNum y, // IN: y coordinate + bigNum z // IN: x coordinate +) +{ + p->x = x; + p->y = y; + p->z = z; + BnSetWord(z, 1); + return p; +} + +#endif // ALG_ECC \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptCmac.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptCmac.c new file mode 100644 index 0000000..b33c3da --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptCmac.c @@ -0,0 +1,172 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// +// This file contains the implementation of the message authentication codes based +// on a symmetric block cipher. These functions only use the single block +// encryption functions of the selected symmetric cryptographic library. + +//** Includes, Defines, and Typedefs +#define _CRYPT_HASH_C_ +#include "Tpm.h" +#include "CryptSym.h" + +#if ALG_CMAC + +//** Functions + +//*** CryptCmacStart() +// This is the function to start the CMAC sequence operation. It initializes the +// dispatch functions for the data and end operations for CMAC and initializes the +// parameters that are used for the processing of data, including the key, key size +// and block cipher algorithm. +UINT16 +CryptCmacStart( + SMAC_STATE* state, TPMU_PUBLIC_PARMS* keyParms, TPM_ALG_ID macAlg, TPM2B* key) +{ + tpmCmacState_t* cState = &state->state.cmac; + TPMT_SYM_DEF_OBJECT* def = &keyParms->symDetail.sym; + // + if(macAlg != TPM_ALG_CMAC) + return 0; + // set up the encryption algorithm and parameters + cState->symAlg = def->algorithm; + cState->keySizeBits = def->keyBits.sym; + cState->iv.t.size = CryptGetSymmetricBlockSize(def->algorithm, def->keyBits.sym); + MemoryCopy2B(&cState->symKey.b, key, sizeof(cState->symKey.t.buffer)); + + // Set up the dispatch methods for the CMAC + state->smacMethods.data = CryptCmacData; + state->smacMethods.end = CryptCmacEnd; + return cState->iv.t.size; +} + +//*** CryptCmacData() +// This function is used to add data to the CMAC sequence computation. The function +// will XOR new data into the IV. If the buffer is full, and there is additional +// input data, the data is encrypted into the IV buffer, the new data is then +// XOR into the IV. When the data runs out, the function returns without encrypting +// even if the buffer is full. The last data block of a sequence will not be +// encrypted until the call to CryptCmacEnd(). This is to allow the proper subkey +// to be computed and applied before the last block is encrypted. +void CryptCmacData(SMAC_STATES* state, UINT32 size, const BYTE* buffer) +{ + tpmCmacState_t* cmacState = &state->cmac; + TPM_ALG_ID algorithm = cmacState->symAlg; + BYTE* key = cmacState->symKey.t.buffer; + UINT16 keySizeInBits = cmacState->keySizeBits; + tpmCryptKeySchedule_t keySchedule; + TpmCryptSetSymKeyCall_t encrypt; + // + // Set up the encryption values based on the algorithm + switch(algorithm) + { + FOR_EACH_SYM(ENCRYPT_CASE) + default: + FAIL(FATAL_ERROR_INTERNAL); + } + while(size > 0) + { + if(cmacState->bcount == cmacState->iv.t.size) + { + ENCRYPT(&keySchedule, cmacState->iv.t.buffer, cmacState->iv.t.buffer); + cmacState->bcount = 0; + } + for(; (size > 0) && (cmacState->bcount < cmacState->iv.t.size); + size--, cmacState->bcount++) + { + cmacState->iv.t.buffer[cmacState->bcount] ^= *buffer++; + } + } +} + +//*** CryptCmacEnd() +// This is the completion function for the CMAC. It does padding, if needed, and +// selects the subkey to be applied before the last block is encrypted. +UINT16 +CryptCmacEnd(SMAC_STATES* state, UINT32 outSize, BYTE* outBuffer) +{ + tpmCmacState_t* cState = &state->cmac; + // Need to set algorithm, key, and keySizeInBits in the local context so that + // the SELECT and ENCRYPT macros will work here + TPM_ALG_ID algorithm = cState->symAlg; + BYTE* key = cState->symKey.t.buffer; + UINT16 keySizeInBits = cState->keySizeBits; + tpmCryptKeySchedule_t keySchedule; + TpmCryptSetSymKeyCall_t encrypt; + TPM2B_IV subkey = {{0, {0}}}; + BOOL xorVal; + UINT16 i; + + subkey.t.size = cState->iv.t.size; + // Encrypt a block of zero + // Set up the encryption values based on the algorithm + switch(algorithm) + { + FOR_EACH_SYM(ENCRYPT_CASE) + default: + return 0; + } + ENCRYPT(&keySchedule, subkey.t.buffer, subkey.t.buffer); + + // shift left by 1 and XOR with 0x0...87 if the MSb was 0 + xorVal = ((subkey.t.buffer[0] & 0x80) == 0) ? 0 : 0x87; + ShiftLeft(&subkey.b); + subkey.t.buffer[subkey.t.size - 1] ^= xorVal; + // this is a sanity check to make sure that the algorithm is working properly. + // remove this check when debug is done + pAssert(cState->bcount <= cState->iv.t.size); + // If the buffer is full then no need to compute subkey 2. + if(cState->bcount < cState->iv.t.size) + { + //Pad the data + cState->iv.t.buffer[cState->bcount++] ^= 0x80; + // The rest of the data is a pad of zero which would simply be XORed + // with the iv value so nothing to do... + // Now compute K2 + xorVal = ((subkey.t.buffer[0] & 0x80) == 0) ? 0 : 0x87; + ShiftLeft(&subkey.b); + subkey.t.buffer[subkey.t.size - 1] ^= xorVal; + } + // XOR the subkey into the IV + for(i = 0; i < subkey.t.size; i++) + cState->iv.t.buffer[i] ^= subkey.t.buffer[i]; + ENCRYPT(&keySchedule, cState->iv.t.buffer, cState->iv.t.buffer); + i = (UINT16)MIN(cState->iv.t.size, outSize); + MemoryCopy(outBuffer, cState->iv.t.buffer, i); + + return i; +} +#endif diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptDes.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptDes.c new file mode 100644 index 0000000..f0ec62e --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptDes.c @@ -0,0 +1,174 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// +// This file contains the extra functions required for TDES. + +//** Includes, Defines, and Typedefs +#include "Tpm.h" + +#if ALG_TDES + +# define DES_NUM_WEAK 64 +const UINT64 DesWeakKeys[DES_NUM_WEAK] = + {0x0101010101010101ULL, 0xFEFEFEFEFEFEFEFEULL, 0xE0E0E0E0F1F1F1F1ULL, + 0x1F1F1F1F0E0E0E0EULL, 0x011F011F010E010EULL, 0x1F011F010E010E01ULL, + 0x01E001E001F101F1ULL, 0xE001E001F101F101ULL, 0x01FE01FE01FE01FEULL, + 0xFE01FE01FE01FE01ULL, 0x1FE01FE00EF10EF1ULL, 0xE01FE01FF10EF10EULL, + 0x1FFE1FFE0EFE0EFEULL, 0xFE1FFE1FFE0EFE0EULL, 0xE0FEE0FEF1FEF1FEULL, + 0xFEE0FEE0FEF1FEF1ULL, 0x01011F1F01010E0EULL, 0x1F1F01010E0E0101ULL, + 0xE0E01F1FF1F10E0EULL, 0x0101E0E00101F1F1ULL, 0x1F1FE0E00E0EF1F1ULL, + 0xE0E0FEFEF1F1FEFEULL, 0x0101FEFE0101FEFEULL, 0x1F1FFEFE0E0EFEFEULL, + 0xE0FE011FF1FE010EULL, 0x011F1F01010E0E01ULL, 0x1FE001FE0EF101FEULL, + 0xE0FE1F01F1FE0E01ULL, 0x011FE0FE010EF1FEULL, 0x1FE0E01F0EF1F10EULL, + 0xE0FEFEE0F1FEFEF1ULL, 0x011FFEE0010EFEF1ULL, 0x1FE0FE010EF1FE01ULL, + 0xFE0101FEFE0101FEULL, 0x01E01FFE01F10EFEULL, 0x1FFE01E00EFE01F1ULL, + 0xFE011FE0FE010EF1ULL, 0xFE01E01FFE01F10EULL, 0x1FFEE0010EFEF101ULL, + 0xFE1F01E0FE0E01F1ULL, 0x01E0E00101F1F101ULL, 0x1FFEFE1F0EFEFE0EULL, + 0xFE1FE001FE0EF101ULL, 0x01E0FE1F01F1FE0EULL, 0xE00101E0F10101F1ULL, + 0xFE1F1FFEFE0E0EFEULL, 0x01FE1FE001FE0EF1ULL, 0xE0011FFEF1010EFEULL, + 0xFEE0011FFEF1010EULL, 0x01FEE01F01FEF10EULL, 0xE001FE1FF101FE0EULL, + 0xFEE01F01FEF10E01ULL, 0x01FEFE0101FEFE01ULL, 0xE01F01FEF10E01FEULL, + 0xFEE0E0FEFEF1F1FEULL, 0x1F01011F0E01010EULL, 0xE01F1FE0F10E0EF1ULL, + 0xFEFE0101FEFE0101ULL, 0x1F01E0FE0E01F1FEULL, 0xE01FFE01F10EFE01ULL, + 0xFEFE1F1FFEFE0E0EULL, 0x1F01FEE00E01FEF1ULL, 0xE0E00101F1F10101ULL, + 0xFEFEE0E0FEFEF1F1ULL}; + +//*** CryptSetOddByteParity() +// This function sets the per byte parity of a 64-bit value. The least-significant +// bit is of each byte is replaced with the odd parity of the other 7 bits in the +// byte. With odd parity, no byte will ever be 0x00. +UINT64 +CryptSetOddByteParity(UINT64 k) +{ +# define PMASK 0x0101010101010101ULL + UINT64 out; + k |= PMASK; // set the parity bit + out = k; + k ^= k >> 4; + k ^= k >> 2; + k ^= k >> 1; + k &= PMASK; // odd parity extracted + out ^= k; // out is now even parity because parity bit was already set + out ^= PMASK; // out is now even parity + return out; +} + +//*** CryptDesIsWeakKey() +// Check to see if a DES key is on the list of weak, semi-weak, or possibly weak +// keys. +// Return Type: BOOL +// TRUE(1) DES key is weak +// FALSE(0) DES key is not weak +static BOOL CryptDesIsWeakKey(UINT64 k) +{ + int i; + // + for(i = 0; i < DES_NUM_WEAK; i++) + { + if(k == DesWeakKeys[i]) + return TRUE; + } + return FALSE; +} + +//*** CryptDesValidateKey() +// Function to check to see if the input key is a valid DES key where the definition +// of valid is that none of the elements are on the list of weak, semi-weak, or +// possibly weak keys; and that for two keys, K1!=K2, and for three keys that +// K1!=K2 and K2!=K3. +BOOL CryptDesValidateKey(TPM2B_SYM_KEY* desKey // IN: key to validate +) +{ + UINT64 k[3]; + int i; + int keys = (desKey->t.size + 7) / 8; + BYTE* pk = desKey->t.buffer; + BOOL ok; + // + // Note: 'keys' is the number of keys, not the maximum index for 'k' + ok = ((keys == 2) || (keys == 3)) && ((desKey->t.size % 8) == 0); + for(i = 0; ok && i < keys; pk += 8, i++) + { + k[i] = CryptSetOddByteParity(BYTE_ARRAY_TO_UINT64(pk)); + ok = !CryptDesIsWeakKey(k[i]); + } + ok = ok && k[0] != k[1]; + if(keys == 3) + ok = ok && k[1] != k[2]; + return ok; +} + +//*** CryptGenerateKeyDes() +// This function is used to create a DES key of the appropriate size. The key will +// have odd parity in the bytes. +TPM_RC +CryptGenerateKeyDes(TPMT_PUBLIC* publicArea, // IN/OUT: The public area template + // for the new key. + TPMT_SENSITIVE* sensitive, // OUT: sensitive area + RAND_STATE* rand // IN: the "entropy" source for +) +{ + // Assume that the publicArea key size has been validated and is a supported + // number of bits. + sensitive->sensitive.sym.t.size = + BITS_TO_BYTES(publicArea->parameters.symDetail.sym.keyBits.sym); + + // Because we use BYTE_ARRAY_TO_UINT64 below, require the requested DES key + // to be a multiple of 8 bytes in size. + if((sensitive->sensitive.sym.t.size % 8) != 0) + { + return TPM_RC_SYMMETRIC; + } + + do + { + BYTE* pK = sensitive->sensitive.sym.t.buffer; + int i = (sensitive->sensitive.sym.t.size + 7) / 8; + // Use the random number generator to generate the required number of bits + if(DRBG_Generate(rand, pK, sensitive->sensitive.sym.t.size) == 0) + return TPM_RC_NO_RESULT; + for(; i > 0; pK += 8, i--) + { + UINT64 k = BYTE_ARRAY_TO_UINT64(pK); + k = CryptSetOddByteParity(k); + UINT64_TO_BYTE_ARRAY(k, pK); + } + } while(!CryptDesValidateKey(&sensitive->sensitive.sym)); + return TPM_RC_SUCCESS; +} + +#endif +//*** diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptEccCrypt.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptEccCrypt.c new file mode 100644 index 0000000..619b0bd --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptEccCrypt.c @@ -0,0 +1,214 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Includes and Defines +#include "Tpm.h" + +#if CC_ECC_Encrypt || CC_ECC_Encrypt + +//** Functions + +//*** CryptEccSelectScheme() +// This function is used by TPM2_ECC_Decrypt and TPM2_ECC_Encrypt. It sets scheme +// either the input scheme or the key scheme. If they key scheme is not TPM_ALG_NULL +// then the input scheme must be TPM_ALG_NULL or the same as the key scheme. If +// not, then the function returns FALSE. +// Return Type: BOOL +// TRUE 'scheme' is set +// FALSE 'scheme' is not valid (it may have been changed). +BOOL CryptEccSelectScheme(OBJECT* key, //IN: key containing default scheme + TPMT_KDF_SCHEME* scheme // IN: a decrypt scheme +) +{ + TPMT_KDF_SCHEME* keyScheme = &key->publicArea.parameters.eccDetail.kdf; + + // Get sign object pointer + if(scheme->scheme == TPM_ALG_NULL) + *scheme = *keyScheme; + if(keyScheme->scheme == TPM_ALG_NULL) + keyScheme = scheme; + return ( + scheme->scheme != TPM_ALG_NULL + && (keyScheme->scheme == scheme->scheme + && keyScheme->details.anyKdf.hashAlg == scheme->details.anyKdf.hashAlg)); +} + +//*** CryptEccEncrypt() +//This function performs ECC-based data obfuscation. The only scheme that is currently +// supported is MGF1 based. See Part 1, Annex D for details. +// Return Type: TPM_RC +// TPM_RC_CURVE unsupported curve +// TPM_RC_HASH hash not allowed +// TPM_RC_SCHEME 'scheme' is not supported +// TPM_RC_NO_RESULT internal error in big number processing +LIB_EXPORT TPM_RC CryptEccEncrypt( + OBJECT* key, // IN: public key of recipient + TPMT_KDF_SCHEME* scheme, // IN: scheme to use. + TPM2B_MAX_BUFFER* plainText, // IN: the text to obfuscate + TPMS_ECC_POINT* c1, // OUT: public ephemeral key + TPM2B_MAX_BUFFER* c2, // OUT: obfuscated text + TPM2B_DIGEST* c3 // OUT: digest of ephemeral key + // and plainText +) +{ + CURVE_INITIALIZED(E, key->publicArea.parameters.eccDetail.curveID); + POINT_INITIALIZED(PB, &key->publicArea.unique.ecc); + POINT_VAR(Px, MAX_ECC_KEY_BITS); + TPMS_ECC_POINT p2; + ECC_NUM(D); + TPM2B_TYPE(2ECC, MAX_ECC_KEY_BYTES * 2); + TPM2B_2ECC z; + int i; + HASH_STATE hashState; + TPM_RC retVal = TPM_RC_SUCCESS; + // +# if defined DEBUG_ECC_ENCRYPT && DEBUG_ECC_ENCRYPT == YES + RND_DEBUG dbg; + // This value is one less than the value from the reference so that it + // will become the correct value after having one added + TPM2B_ECC_PARAMETER k = {24, {0x38, 0x4F, 0x30, 0x35, 0x30, 0x73, 0xAE, 0xEC, + 0xE7, 0xA1, 0x65, 0x43, 0x30, 0xA9, 0x62, 0x04, + 0xD3, 0x79, 0x82, 0xA3, 0xE1, 0x5B, 0x2C, 0xB4}}; + RND_DEBUG_Instantiate(&dbg, &k.b); +# define RANDOM (RAND_STATE*)&dbg + +# else +# define RANDOM NULL +# endif + if(E == NULL) + ERROR_RETURN(TPM_RC_CURVE); + if(TPM_ALG_KDF2 != scheme->scheme) + ERROR_RETURN(TPM_RC_SCHEME); + // generate an ephemeral key from a random k + if(!BnEccGenerateKeyPair(D, Px, E, RANDOM) + // C1 is the public part of the ephemeral key + || !BnPointTo2B(c1, Px, E) + // Compute P2 + || (BnPointMult(Px, PB, D, NULL, NULL, E) != TPM_RC_SUCCESS) + || !BnPointTo2B(&p2, Px, E)) + ERROR_RETURN(TPM_RC_NO_RESULT); + + //Compute the C3 value hash(x2 || M || y2) + if(0 == CryptHashStart(&hashState, scheme->details.mgf1.hashAlg)) + ERROR_RETURN(TPM_RC_HASH); + CryptDigestUpdate2B(&hashState, &p2.x.b); + CryptDigestUpdate2B(&hashState, &plainText->b); + CryptDigestUpdate2B(&hashState, &p2.y.b); + c3->t.size = CryptHashEnd(&hashState, sizeof(c3->t.buffer), c3->t.buffer); + + MemoryCopy2B(&z.b, &p2.x.b, sizeof(z.t.buffer)); + MemoryConcat2B(&z.b, &p2.y.b, sizeof(z.t.buffer)); + // Generate the mask value from MGF1 and put it in the return buffer + c2->t.size = CryptMGF_KDF(plainText->t.size, + c2->t.buffer, + scheme->details.mgf1.hashAlg, + z.t.size, + z.t.buffer, + 1); + // XOR the plainText into the generated mask to create the obfuscated data + for(i = 0; i < plainText->t.size; i++) + c2->t.buffer[i] ^= plainText->t.buffer[i]; +Exit: + CURVE_FREE(E); + return retVal; +} + +//*** CryptEccDecrypt() +// This function performs ECC decryption and integrity check of the input data. +// Return Type: TPM_RC +// TPM_RC_CURVE unsupported curve +// TPM_RC_HASH hash not allowed +// TPM_RC_SCHEME 'scheme' is not supported +// TPM_RC_NO_RESULT internal error in big number processing +// TPM_RC_VALUE C3 did not match hash of recovered data +LIB_EXPORT TPM_RC CryptEccDecrypt( + OBJECT* key, // IN: key used for data recovery + TPMT_KDF_SCHEME* scheme, // IN: scheme to use. + TPM2B_MAX_BUFFER* plainText, // OUT: the recovered text + TPMS_ECC_POINT* c1, // IN: public ephemeral key + TPM2B_MAX_BUFFER* c2, // IN: obfuscated text + TPM2B_DIGEST* c3 // IN: digest of ephemeral key + // and plainText +) +{ + CURVE_INITIALIZED(E, key->publicArea.parameters.eccDetail.curveID); + ECC_INITIALIZED(D, &key->sensitive.sensitive.ecc.b); + POINT_INITIALIZED(C1, c1); + TPMS_ECC_POINT p2; + TPM2B_TYPE(2ECC, MAX_ECC_KEY_BYTES * 2); + TPM2B_DIGEST check; + TPM2B_2ECC z; + int i; + HASH_STATE hashState; + TPM_RC retVal = TPM_RC_SUCCESS; + // + if(E == NULL) + ERROR_RETURN(TPM_RC_CURVE); + if(TPM_ALG_KDF2 != scheme->scheme) + ERROR_RETURN(TPM_RC_SCHEME); + // Generate the Z value + BnPointMult(C1, C1, D, NULL, NULL, E); + BnPointTo2B(&p2, C1, E); + + // Start the hash to check the algorithm + if(0 == CryptHashStart(&hashState, scheme->details.mgf1.hashAlg)) + ERROR_RETURN(TPM_RC_HASH); + CryptDigestUpdate2B(&hashState, &p2.x.b); + + MemoryCopy2B(&z.b, &p2.x.b, sizeof(z.t.buffer)); + MemoryConcat2B(&z.b, &p2.y.b, sizeof(z.t.buffer)); + + // Generate the mask + plainText->t.size = CryptMGF_KDF(c2->t.size, + plainText->t.buffer, + scheme->details.mgf1.hashAlg, + z.t.size, + z.t.buffer, + 1); + // XOR the obfuscated data into the generated mask to create the plainText data + for(i = 0; i < plainText->t.size; i++) + plainText->t.buffer[i] ^= c2->t.buffer[i]; + + // Complete the hash and verify the data + CryptDigestUpdate2B(&hashState, &plainText->b); + CryptDigestUpdate2B(&hashState, &p2.y.b); + check.t.size = CryptHashEnd(&hashState, sizeof(check.t.buffer), check.t.buffer); + if(!MemoryEqual2B(&check.b, &c3->b)) + ERROR_RETURN(TPM_RC_VALUE); +Exit: + CURVE_FREE(E); + return retVal; +} + +#endif // CC_ECC_Encrypt || CC_ECC_Encrypt diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptEccData.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptEccData.c new file mode 100644 index 0000000..3646f6f --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptEccData.c @@ -0,0 +1,731 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmStructures; Version 4.4 Mar 26, 2019 + * Date: Aug 30, 2019 Time: 02:11:52PM + */ + +#include "Tpm.h" +#include "OIDs.h" + +// This file contains the ECC curve data. The format of the data depends on the +// setting of USE_BN_ECC_DATA. If it is defined, then the TPM's BigNum format is +// used. Otherwise, it is kept in TPM2B format. The purpose of having the data in +// BigNum format is so that it does not have to be reformatted before being used +// by the crypto library. + +#if ALG_ECC + +# if USE_BN_ECC_DATA +# define TO_ECC_64 TO_CRYPT_WORD_64 +# define TO_ECC_56(a, b, c, d, e, f, g) TO_ECC_64(0, a, b, c, d, e, f, g) +# define TO_ECC_48(a, b, c, d, e, f) TO_ECC_64(0, 0, a, b, c, d, e, f) +# define TO_ECC_40(a, b, c, d, e) TO_ECC_64(0, 0, 0, a, b, c, d, e) +# if RADIX_BITS > 32 +# define TO_ECC_32(a, b, c, d) TO_ECC_64(0, 0, 0, 0, a, b, c, d) +# define TO_ECC_24(a, b, c) TO_ECC_64(0, 0, 0, 0, 0, a, b, c) +# define TO_ECC_16(a, b) TO_ECC_64(0, 0, 0, 0, 0, 0, a, b) +# define TO_ECC_8(a) TO_ECC_64(0, 0, 0, 0, 0, 0, 0, a) +# else // RADIX_BITS == 32 +# define TO_ECC_32 BIG_ENDIAN_BYTES_TO_UINT32 +# define TO_ECC_24(a, b, c) TO_ECC_32(0, a, b, c) +# define TO_ECC_16(a, b) TO_ECC_32(0, 0, a, b) +# define TO_ECC_8(a) TO_ECC_32(0, 0, 0, a) +# endif +# else // TPM2B_ +# define TO_ECC_64(a, b, c, d, e, f, g, h) a, b, c, d, e, f, g, h +# define TO_ECC_56(a, b, c, d, e, f, g) a, b, c, d, e, f, g +# define TO_ECC_48(a, b, c, d, e, f) a, b, c, d, e, f +# define TO_ECC_40(a, b, c, d, e) a, b, c, d, e +# define TO_ECC_32(a, b, c, d) a, b, c, d +# define TO_ECC_24(a, b, c) a, b, c +# define TO_ECC_16(a, b) a, b +# define TO_ECC_8(a) a +# endif + +# if USE_BN_ECC_DATA +# define BN_MIN_ALLOC(bytes) \ + (BYTES_TO_CRYPT_WORDS(bytes) == 0) ? 1 : BYTES_TO_CRYPT_WORDS(bytes) +# define ECC_CONST(NAME, bytes, initializer) \ + const struct \ + { \ + crypt_uword_t allocate, size, d[BN_MIN_ALLOC(bytes)]; \ + } NAME = {BN_MIN_ALLOC(bytes), BYTES_TO_CRYPT_WORDS(bytes), {initializer}} + +ECC_CONST(ECC_ZERO, 0, 0); + +# else +# define ECC_CONST(NAME, bytes, initializer) \ + const TPM2B_##bytes##_BYTE_VALUE NAME = {bytes, {initializer}} + +// Have to special case ECC_ZERO +TPM2B_BYTE_VALUE(1); +TPM2B_1_BYTE_VALUE ECC_ZERO = {1, {0}}; + +# endif + +ECC_CONST(ECC_ONE, 1, 1); + +# if !USE_BN_ECC_DATA +TPM2B_BYTE_VALUE(24); +# define TO_ECC_192(a, b, c) a, b, c +TPM2B_BYTE_VALUE(28); +# define TO_ECC_224(a, b, c, d) a, b, c, d +TPM2B_BYTE_VALUE(32); +# define TO_ECC_256(a, b, c, d) a, b, c, d +TPM2B_BYTE_VALUE(48); +# define TO_ECC_384(a, b, c, d, e, f) a, b, c, d, e, f +TPM2B_BYTE_VALUE(66); +# define TO_ECC_528(a, b, c, d, e, f, g, h, i) a, b, c, d, e, f, g, h, i +TPM2B_BYTE_VALUE(80); +# define TO_ECC_640(a, b, c, d, e, f, g, h, i, j) a, b, c, d, e, f, g, h, i, j +# else +# define TO_ECC_192(a, b, c) c, b, a +# define TO_ECC_224(a, b, c, d) d, c, b, a +# define TO_ECC_256(a, b, c, d) d, c, b, a +# define TO_ECC_384(a, b, c, d, e, f) f, e, d, c, b, a +# define TO_ECC_528(a, b, c, d, e, f, g, h, i) i, h, g, f, e, d, c, b, a +# define TO_ECC_640(a, b, c, d, e, f, g, h, i, j) j, i, h, g, f, e, d, c, b, a +# endif // !USE_BN_ECC_DATA + +# if ECC_NIST_P192 +ECC_CONST(NIST_P192_p, + 24, + TO_ECC_192(TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF))); +ECC_CONST(NIST_P192_a, + 24, + TO_ECC_192(TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC))); +ECC_CONST(NIST_P192_b, + 24, + TO_ECC_192(TO_ECC_64(0x64, 0x21, 0x05, 0x19, 0xE5, 0x9C, 0x80, 0xE7), + TO_ECC_64(0x0F, 0xA7, 0xE9, 0xAB, 0x72, 0x24, 0x30, 0x49), + TO_ECC_64(0xFE, 0xB8, 0xDE, 0xEC, 0xC1, 0x46, 0xB9, 0xB1))); +ECC_CONST(NIST_P192_gX, + 24, + TO_ECC_192(TO_ECC_64(0x18, 0x8D, 0xA8, 0x0E, 0xB0, 0x30, 0x90, 0xF6), + TO_ECC_64(0x7C, 0xBF, 0x20, 0xEB, 0x43, 0xA1, 0x88, 0x00), + TO_ECC_64(0xF4, 0xFF, 0x0A, 0xFD, 0x82, 0xFF, 0x10, 0x12))); +ECC_CONST(NIST_P192_gY, + 24, + TO_ECC_192(TO_ECC_64(0x07, 0x19, 0x2B, 0x95, 0xFF, 0xC8, 0xDA, 0x78), + TO_ECC_64(0x63, 0x10, 0x11, 0xED, 0x6B, 0x24, 0xCD, 0xD5), + TO_ECC_64(0x73, 0xF9, 0x77, 0xA1, 0x1E, 0x79, 0x48, 0x11))); +ECC_CONST(NIST_P192_n, + 24, + TO_ECC_192(TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x99, 0xDE, 0xF8, 0x36), + TO_ECC_64(0x14, 0x6B, 0xC9, 0xB1, 0xB4, 0xD2, 0x28, 0x31))); +# define NIST_P192_h ECC_ONE +# define NIST_P192_gZ ECC_ONE + +# if USE_BN_ECC_DATA +const ECC_CURVE_DATA NIST_P192 = {(bigNum)&NIST_P192_p, + (bigNum)&NIST_P192_n, + (bigNum)&NIST_P192_h, + (bigNum)&NIST_P192_a, + (bigNum)&NIST_P192_b, + {(bigNum)&NIST_P192_gX, + (bigNum)&NIST_P192_gY, + (bigNum)&NIST_P192_gZ}}; + +# else +const ECC_CURVE_DATA NIST_P192 = {&NIST_P192_p.b, + &NIST_P192_n.b, + &NIST_P192_h.b, + &NIST_P192_a.b, + &NIST_P192_b.b, + {&NIST_P192_gX.b, + &NIST_P192_gY.b, + &NIST_P192_gZ.b}}; + +# endif // USE_BN_ECC_DATA + +# endif // ECC_NIST_P192 + +# if ECC_NIST_P224 +ECC_CONST(NIST_P224_p, + 28, + TO_ECC_224(TO_ECC_32(0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00), + TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01))); +ECC_CONST(NIST_P224_a, + 28, + TO_ECC_224(TO_ECC_32(0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE))); +ECC_CONST(NIST_P224_b, + 28, + TO_ECC_224(TO_ECC_32(0xB4, 0x05, 0x0A, 0x85), + TO_ECC_64(0x0C, 0x04, 0xB3, 0xAB, 0xF5, 0x41, 0x32, 0x56), + TO_ECC_64(0x50, 0x44, 0xB0, 0xB7, 0xD7, 0xBF, 0xD8, 0xBA), + TO_ECC_64(0x27, 0x0B, 0x39, 0x43, 0x23, 0x55, 0xFF, 0xB4))); +ECC_CONST(NIST_P224_gX, + 28, + TO_ECC_224(TO_ECC_32(0xB7, 0x0E, 0x0C, 0xBD), + TO_ECC_64(0x6B, 0xB4, 0xBF, 0x7F, 0x32, 0x13, 0x90, 0xB9), + TO_ECC_64(0x4A, 0x03, 0xC1, 0xD3, 0x56, 0xC2, 0x11, 0x22), + TO_ECC_64(0x34, 0x32, 0x80, 0xD6, 0x11, 0x5C, 0x1D, 0x21))); +ECC_CONST(NIST_P224_gY, + 28, + TO_ECC_224(TO_ECC_32(0xBD, 0x37, 0x63, 0x88), + TO_ECC_64(0xB5, 0xF7, 0x23, 0xFB, 0x4C, 0x22, 0xDF, 0xE6), + TO_ECC_64(0xCD, 0x43, 0x75, 0xA0, 0x5A, 0x07, 0x47, 0x64), + TO_ECC_64(0x44, 0xD5, 0x81, 0x99, 0x85, 0x00, 0x7E, 0x34))); +ECC_CONST(NIST_P224_n, + 28, + TO_ECC_224(TO_ECC_32(0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0x16, 0xA2, 0xE0, 0xB8, 0xF0, 0x3E), + TO_ECC_64(0x13, 0xDD, 0x29, 0x45, 0x5C, 0x5C, 0x2A, 0x3D))); +# define NIST_P224_h ECC_ONE +# define NIST_P224_gZ ECC_ONE + +# if USE_BN_ECC_DATA +const ECC_CURVE_DATA NIST_P224 = {(bigNum)&NIST_P224_p, + (bigNum)&NIST_P224_n, + (bigNum)&NIST_P224_h, + (bigNum)&NIST_P224_a, + (bigNum)&NIST_P224_b, + {(bigNum)&NIST_P224_gX, + (bigNum)&NIST_P224_gY, + (bigNum)&NIST_P224_gZ}}; + +# else +const ECC_CURVE_DATA NIST_P224 = {&NIST_P224_p.b, + &NIST_P224_n.b, + &NIST_P224_h.b, + &NIST_P224_a.b, + &NIST_P224_b.b, + {&NIST_P224_gX.b, + &NIST_P224_gY.b, + &NIST_P224_gZ.b}}; + +# endif // USE_BN_ECC_DATA + +# endif // ECC_NIST_P224 + +# if ECC_NIST_P256 +ECC_CONST(NIST_P256_p, + 32, + TO_ECC_256(TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01), + TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF))); +ECC_CONST(NIST_P256_a, + 32, + TO_ECC_256(TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01), + TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), + TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC))); +ECC_CONST(NIST_P256_b, + 32, + TO_ECC_256(TO_ECC_64(0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7), + TO_ECC_64(0xB3, 0xEB, 0xBD, 0x55, 0x76, 0x98, 0x86, 0xBC), + TO_ECC_64(0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6), + TO_ECC_64(0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B))); +ECC_CONST(NIST_P256_gX, + 32, + TO_ECC_256(TO_ECC_64(0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47), + TO_ECC_64(0xF8, 0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40, 0xF2), + TO_ECC_64(0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0), + TO_ECC_64(0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96))); +ECC_CONST(NIST_P256_gY, + 32, + TO_ECC_256(TO_ECC_64(0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B), + TO_ECC_64(0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16), + TO_ECC_64(0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE), + TO_ECC_64(0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5))); +ECC_CONST(NIST_P256_n, + 32, + TO_ECC_256(TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84), + TO_ECC_64(0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51))); +# define NIST_P256_h ECC_ONE +# define NIST_P256_gZ ECC_ONE + +# if USE_BN_ECC_DATA +const ECC_CURVE_DATA NIST_P256 = {(bigNum)&NIST_P256_p, + (bigNum)&NIST_P256_n, + (bigNum)&NIST_P256_h, + (bigNum)&NIST_P256_a, + (bigNum)&NIST_P256_b, + {(bigNum)&NIST_P256_gX, + (bigNum)&NIST_P256_gY, + (bigNum)&NIST_P256_gZ}}; + +# else +const ECC_CURVE_DATA NIST_P256 = {&NIST_P256_p.b, + &NIST_P256_n.b, + &NIST_P256_h.b, + &NIST_P256_a.b, + &NIST_P256_b.b, + {&NIST_P256_gX.b, + &NIST_P256_gY.b, + &NIST_P256_gZ.b}}; + +# endif // USE_BN_ECC_DATA + +# endif // ECC_NIST_P256 + +# if ECC_NIST_P384 +ECC_CONST(NIST_P384_p, + 48, + TO_ECC_384(TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00), + TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF))); +ECC_CONST(NIST_P384_a, + 48, + TO_ECC_384(TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00), + TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFC))); +ECC_CONST(NIST_P384_b, + 48, + TO_ECC_384(TO_ECC_64(0xB3, 0x31, 0x2F, 0xA7, 0xE2, 0x3E, 0xE7, 0xE4), + TO_ECC_64(0x98, 0x8E, 0x05, 0x6B, 0xE3, 0xF8, 0x2D, 0x19), + TO_ECC_64(0x18, 0x1D, 0x9C, 0x6E, 0xFE, 0x81, 0x41, 0x12), + TO_ECC_64(0x03, 0x14, 0x08, 0x8F, 0x50, 0x13, 0x87, 0x5A), + TO_ECC_64(0xC6, 0x56, 0x39, 0x8D, 0x8A, 0x2E, 0xD1, 0x9D), + TO_ECC_64(0x2A, 0x85, 0xC8, 0xED, 0xD3, 0xEC, 0x2A, 0xEF))); +ECC_CONST(NIST_P384_gX, + 48, + TO_ECC_384(TO_ECC_64(0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37), + TO_ECC_64(0x8E, 0xB1, 0xC7, 0x1E, 0xF3, 0x20, 0xAD, 0x74), + TO_ECC_64(0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98), + TO_ECC_64(0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38), + TO_ECC_64(0x55, 0x02, 0xF2, 0x5D, 0xBF, 0x55, 0x29, 0x6C), + TO_ECC_64(0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7))); +ECC_CONST(NIST_P384_gY, + 48, + TO_ECC_384(TO_ECC_64(0x36, 0x17, 0xDE, 0x4A, 0x96, 0x26, 0x2C, 0x6F), + TO_ECC_64(0x5D, 0x9E, 0x98, 0xBF, 0x92, 0x92, 0xDC, 0x29), + TO_ECC_64(0xF8, 0xF4, 0x1D, 0xBD, 0x28, 0x9A, 0x14, 0x7C), + TO_ECC_64(0xE9, 0xDA, 0x31, 0x13, 0xB5, 0xF0, 0xB8, 0xC0), + TO_ECC_64(0x0A, 0x60, 0xB1, 0xCE, 0x1D, 0x7E, 0x81, 0x9D), + TO_ECC_64(0x7A, 0x43, 0x1D, 0x7C, 0x90, 0xEA, 0x0E, 0x5F))); +ECC_CONST(NIST_P384_n, + 48, + TO_ECC_384(TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF), + TO_ECC_64(0x58, 0x1A, 0x0D, 0xB2, 0x48, 0xB0, 0xA7, 0x7A), + TO_ECC_64(0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73))); +# define NIST_P384_h ECC_ONE +# define NIST_P384_gZ ECC_ONE + +# if USE_BN_ECC_DATA +const ECC_CURVE_DATA NIST_P384 = {(bigNum)&NIST_P384_p, + (bigNum)&NIST_P384_n, + (bigNum)&NIST_P384_h, + (bigNum)&NIST_P384_a, + (bigNum)&NIST_P384_b, + {(bigNum)&NIST_P384_gX, + (bigNum)&NIST_P384_gY, + (bigNum)&NIST_P384_gZ}}; + +# else +const ECC_CURVE_DATA NIST_P384 = {&NIST_P384_p.b, + &NIST_P384_n.b, + &NIST_P384_h.b, + &NIST_P384_a.b, + &NIST_P384_b.b, + {&NIST_P384_gX.b, + &NIST_P384_gY.b, + &NIST_P384_gZ.b}}; + +# endif // USE_BN_ECC_DATA + +# endif // ECC_NIST_P384 + +# if ECC_NIST_P521 +ECC_CONST(NIST_P521_p, + 66, + TO_ECC_528(TO_ECC_16(0x01, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF))); +ECC_CONST(NIST_P521_a, + 66, + TO_ECC_528(TO_ECC_16(0x01, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC))); +ECC_CONST(NIST_P521_b, + 66, + TO_ECC_528(TO_ECC_16(0x00, 0x51), + TO_ECC_64(0x95, 0x3E, 0xB9, 0x61, 0x8E, 0x1C, 0x9A, 0x1F), + TO_ECC_64(0x92, 0x9A, 0x21, 0xA0, 0xB6, 0x85, 0x40, 0xEE), + TO_ECC_64(0xA2, 0xDA, 0x72, 0x5B, 0x99, 0xB3, 0x15, 0xF3), + TO_ECC_64(0xB8, 0xB4, 0x89, 0x91, 0x8E, 0xF1, 0x09, 0xE1), + TO_ECC_64(0x56, 0x19, 0x39, 0x51, 0xEC, 0x7E, 0x93, 0x7B), + TO_ECC_64(0x16, 0x52, 0xC0, 0xBD, 0x3B, 0xB1, 0xBF, 0x07), + TO_ECC_64(0x35, 0x73, 0xDF, 0x88, 0x3D, 0x2C, 0x34, 0xF1), + TO_ECC_64(0xEF, 0x45, 0x1F, 0xD4, 0x6B, 0x50, 0x3F, 0x00))); +ECC_CONST(NIST_P521_gX, + 66, + TO_ECC_528(TO_ECC_16(0x00, 0xC6), + TO_ECC_64(0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD), + TO_ECC_64(0x9E, 0x3E, 0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42), + TO_ECC_64(0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F, 0xB5, 0x21), + TO_ECC_64(0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA), + TO_ECC_64(0xA1, 0x4B, 0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28), + TO_ECC_64(0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF, 0xA8, 0xDE), + TO_ECC_64(0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B), + TO_ECC_64(0xF9, 0x7E, 0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66))); +ECC_CONST(NIST_P521_gY, + 66, + TO_ECC_528(TO_ECC_16(0x01, 0x18), + TO_ECC_64(0x39, 0x29, 0x6A, 0x78, 0x9A, 0x3B, 0xC0, 0x04), + TO_ECC_64(0x5C, 0x8A, 0x5F, 0xB4, 0x2C, 0x7D, 0x1B, 0xD9), + TO_ECC_64(0x98, 0xF5, 0x44, 0x49, 0x57, 0x9B, 0x44, 0x68), + TO_ECC_64(0x17, 0xAF, 0xBD, 0x17, 0x27, 0x3E, 0x66, 0x2C), + TO_ECC_64(0x97, 0xEE, 0x72, 0x99, 0x5E, 0xF4, 0x26, 0x40), + TO_ECC_64(0xC5, 0x50, 0xB9, 0x01, 0x3F, 0xAD, 0x07, 0x61), + TO_ECC_64(0x35, 0x3C, 0x70, 0x86, 0xA2, 0x72, 0xC2, 0x40), + TO_ECC_64(0x88, 0xBE, 0x94, 0x76, 0x9F, 0xD1, 0x66, 0x50))); +ECC_CONST(NIST_P521_n, + 66, + TO_ECC_528(TO_ECC_16(0x01, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA), + TO_ECC_64(0x51, 0x86, 0x87, 0x83, 0xBF, 0x2F, 0x96, 0x6B), + TO_ECC_64(0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09, 0xA5, 0xD0), + TO_ECC_64(0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C, 0x47, 0xAE), + TO_ECC_64(0xBB, 0x6F, 0xB7, 0x1E, 0x91, 0x38, 0x64, 0x09))); +# define NIST_P521_h ECC_ONE +# define NIST_P521_gZ ECC_ONE + +# if USE_BN_ECC_DATA +const ECC_CURVE_DATA NIST_P521 = {(bigNum)&NIST_P521_p, + (bigNum)&NIST_P521_n, + (bigNum)&NIST_P521_h, + (bigNum)&NIST_P521_a, + (bigNum)&NIST_P521_b, + {(bigNum)&NIST_P521_gX, + (bigNum)&NIST_P521_gY, + (bigNum)&NIST_P521_gZ}}; + +# else +const ECC_CURVE_DATA NIST_P521 = {&NIST_P521_p.b, + &NIST_P521_n.b, + &NIST_P521_h.b, + &NIST_P521_a.b, + &NIST_P521_b.b, + {&NIST_P521_gX.b, + &NIST_P521_gY.b, + &NIST_P521_gZ.b}}; + +# endif // USE_BN_ECC_DATA + +# endif // ECC_NIST_P521 + +# if ECC_BN_P256 +ECC_CONST(BN_P256_p, + 32, + TO_ECC_256(TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF0, 0xCD), + TO_ECC_64(0x46, 0xE5, 0xF2, 0x5E, 0xEE, 0x71, 0xA4, 0x9F), + TO_ECC_64(0x0C, 0xDC, 0x65, 0xFB, 0x12, 0x98, 0x0A, 0x82), + TO_ECC_64(0xD3, 0x29, 0x2D, 0xDB, 0xAE, 0xD3, 0x30, 0x13))); +# define BN_P256_a ECC_ZERO +ECC_CONST(BN_P256_b, 1, TO_ECC_8(3)); +# define BN_P256_gX ECC_ONE +ECC_CONST(BN_P256_gY, 1, TO_ECC_8(2)); +ECC_CONST(BN_P256_n, + 32, + TO_ECC_256(TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF0, 0xCD), + TO_ECC_64(0x46, 0xE5, 0xF2, 0x5E, 0xEE, 0x71, 0xA4, 0x9E), + TO_ECC_64(0x0C, 0xDC, 0x65, 0xFB, 0x12, 0x99, 0x92, 0x1A), + TO_ECC_64(0xF6, 0x2D, 0x53, 0x6C, 0xD1, 0x0B, 0x50, 0x0D))); +# define BN_P256_h ECC_ONE +# define BN_P256_gZ ECC_ONE + +# if USE_BN_ECC_DATA +const ECC_CURVE_DATA BN_P256 = {(bigNum)&BN_P256_p, + (bigNum)&BN_P256_n, + (bigNum)&BN_P256_h, + (bigNum)&BN_P256_a, + (bigNum)&BN_P256_b, + {(bigNum)&BN_P256_gX, + (bigNum)&BN_P256_gY, + (bigNum)&BN_P256_gZ}}; + +# else +const ECC_CURVE_DATA BN_P256 = {&BN_P256_p.b, + &BN_P256_n.b, + &BN_P256_h.b, + &BN_P256_a.b, + &BN_P256_b.b, + {&BN_P256_gX.b, &BN_P256_gY.b, &BN_P256_gZ.b}}; + +# endif // USE_BN_ECC_DATA + +# endif // ECC_BN_P256 + +# if ECC_BN_P638 +ECC_CONST(BN_P638_p, + 80, + TO_ECC_640(TO_ECC_64(0x23, 0xFF, 0xFF, 0xFD, 0xC0, 0x00, 0x00, 0x0D), + TO_ECC_64(0x7F, 0xFF, 0xFF, 0xB8, 0x00, 0x00, 0x01, 0xD3), + TO_ECC_64(0xFF, 0xFF, 0xF9, 0x42, 0xD0, 0x00, 0x16, 0x5E), + TO_ECC_64(0x3F, 0xFF, 0x94, 0x87, 0x00, 0x00, 0xD5, 0x2F), + TO_ECC_64(0xFF, 0xFD, 0xD0, 0xE0, 0x00, 0x08, 0xDE, 0x55), + TO_ECC_64(0xC0, 0x00, 0x86, 0x52, 0x00, 0x21, 0xE5, 0x5B), + TO_ECC_64(0xFF, 0xFF, 0xF5, 0x1F, 0xFF, 0xF4, 0xEB, 0x80), + TO_ECC_64(0x00, 0x00, 0x00, 0x4C, 0x80, 0x01, 0x5A, 0xCD), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEC, 0xE0), + TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67))); +# define BN_P638_a ECC_ZERO +ECC_CONST(BN_P638_b, 2, TO_ECC_16(0x01, 0x01)); +ECC_CONST(BN_P638_gX, + 80, + TO_ECC_640(TO_ECC_64(0x23, 0xFF, 0xFF, 0xFD, 0xC0, 0x00, 0x00, 0x0D), + TO_ECC_64(0x7F, 0xFF, 0xFF, 0xB8, 0x00, 0x00, 0x01, 0xD3), + TO_ECC_64(0xFF, 0xFF, 0xF9, 0x42, 0xD0, 0x00, 0x16, 0x5E), + TO_ECC_64(0x3F, 0xFF, 0x94, 0x87, 0x00, 0x00, 0xD5, 0x2F), + TO_ECC_64(0xFF, 0xFD, 0xD0, 0xE0, 0x00, 0x08, 0xDE, 0x55), + TO_ECC_64(0xC0, 0x00, 0x86, 0x52, 0x00, 0x21, 0xE5, 0x5B), + TO_ECC_64(0xFF, 0xFF, 0xF5, 0x1F, 0xFF, 0xF4, 0xEB, 0x80), + TO_ECC_64(0x00, 0x00, 0x00, 0x4C, 0x80, 0x01, 0x5A, 0xCD), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEC, 0xE0), + TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66))); +ECC_CONST(BN_P638_gY, 1, TO_ECC_8(0x10)); +ECC_CONST(BN_P638_n, + 80, + TO_ECC_640(TO_ECC_64(0x23, 0xFF, 0xFF, 0xFD, 0xC0, 0x00, 0x00, 0x0D), + TO_ECC_64(0x7F, 0xFF, 0xFF, 0xB8, 0x00, 0x00, 0x01, 0xD3), + TO_ECC_64(0xFF, 0xFF, 0xF9, 0x42, 0xD0, 0x00, 0x16, 0x5E), + TO_ECC_64(0x3F, 0xFF, 0x94, 0x87, 0x00, 0x00, 0xD5, 0x2F), + TO_ECC_64(0xFF, 0xFD, 0xD0, 0xE0, 0x00, 0x08, 0xDE, 0x55), + TO_ECC_64(0x60, 0x00, 0x86, 0x55, 0x00, 0x21, 0xE5, 0x55), + TO_ECC_64(0xFF, 0xFF, 0xF5, 0x4F, 0xFF, 0xF4, 0xEA, 0xC0), + TO_ECC_64(0x00, 0x00, 0x00, 0x49, 0x80, 0x01, 0x54, 0xD9), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED, 0xA0), + TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61))); +# define BN_P638_h ECC_ONE +# define BN_P638_gZ ECC_ONE + +# if USE_BN_ECC_DATA +const ECC_CURVE_DATA BN_P638 = {(bigNum)&BN_P638_p, + (bigNum)&BN_P638_n, + (bigNum)&BN_P638_h, + (bigNum)&BN_P638_a, + (bigNum)&BN_P638_b, + {(bigNum)&BN_P638_gX, + (bigNum)&BN_P638_gY, + (bigNum)&BN_P638_gZ}}; + +# else +const ECC_CURVE_DATA BN_P638 = {&BN_P638_p.b, + &BN_P638_n.b, + &BN_P638_h.b, + &BN_P638_a.b, + &BN_P638_b.b, + {&BN_P638_gX.b, &BN_P638_gY.b, &BN_P638_gZ.b}}; + +# endif // USE_BN_ECC_DATA + +# endif // ECC_BN_P638 + +# if ECC_SM2_P256 +ECC_CONST(SM2_P256_p, + 32, + TO_ECC_256(TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF))); +ECC_CONST(SM2_P256_a, + 32, + TO_ECC_256(TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC))); +ECC_CONST(SM2_P256_b, + 32, + TO_ECC_256(TO_ECC_64(0x28, 0xE9, 0xFA, 0x9E, 0x9D, 0x9F, 0x5E, 0x34), + TO_ECC_64(0x4D, 0x5A, 0x9E, 0x4B, 0xCF, 0x65, 0x09, 0xA7), + TO_ECC_64(0xF3, 0x97, 0x89, 0xF5, 0x15, 0xAB, 0x8F, 0x92), + TO_ECC_64(0xDD, 0xBC, 0xBD, 0x41, 0x4D, 0x94, 0x0E, 0x93))); +ECC_CONST(SM2_P256_gX, + 32, + TO_ECC_256(TO_ECC_64(0x32, 0xC4, 0xAE, 0x2C, 0x1F, 0x19, 0x81, 0x19), + TO_ECC_64(0x5F, 0x99, 0x04, 0x46, 0x6A, 0x39, 0xC9, 0x94), + TO_ECC_64(0x8F, 0xE3, 0x0B, 0xBF, 0xF2, 0x66, 0x0B, 0xE1), + TO_ECC_64(0x71, 0x5A, 0x45, 0x89, 0x33, 0x4C, 0x74, 0xC7))); +ECC_CONST(SM2_P256_gY, + 32, + TO_ECC_256(TO_ECC_64(0xBC, 0x37, 0x36, 0xA2, 0xF4, 0xF6, 0x77, 0x9C), + TO_ECC_64(0x59, 0xBD, 0xCE, 0xE3, 0x6B, 0x69, 0x21, 0x53), + TO_ECC_64(0xD0, 0xA9, 0x87, 0x7C, 0xC6, 0x2A, 0x47, 0x40), + TO_ECC_64(0x02, 0xDF, 0x32, 0xE5, 0x21, 0x39, 0xF0, 0xA0))); +ECC_CONST(SM2_P256_n, + 32, + TO_ECC_256(TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), + TO_ECC_64(0x72, 0x03, 0xDF, 0x6B, 0x21, 0xC6, 0x05, 0x2B), + TO_ECC_64(0x53, 0xBB, 0xF4, 0x09, 0x39, 0xD5, 0x41, 0x23))); +# define SM2_P256_h ECC_ONE +# define SM2_P256_gZ ECC_ONE + +# if USE_BN_ECC_DATA +const ECC_CURVE_DATA SM2_P256 = {(bigNum)&SM2_P256_p, + (bigNum)&SM2_P256_n, + (bigNum)&SM2_P256_h, + (bigNum)&SM2_P256_a, + (bigNum)&SM2_P256_b, + {(bigNum)&SM2_P256_gX, + (bigNum)&SM2_P256_gY, + (bigNum)&SM2_P256_gZ}}; + +# else +const ECC_CURVE_DATA SM2_P256 = {&SM2_P256_p.b, + &SM2_P256_n.b, + &SM2_P256_h.b, + &SM2_P256_a.b, + &SM2_P256_b.b, + {&SM2_P256_gX.b, &SM2_P256_gY.b, &SM2_P256_gZ.b}}; + +# endif // USE_BN_ECC_DATA + +# endif // ECC_SM2_P256 + +# define comma +const ECC_CURVE eccCurves[] = { +# if ECC_NIST_P192 + comma{TPM_ECC_NIST_P192, + 192, + {TPM_ALG_KDF1_SP800_56A, {{TPM_ALG_SHA256}}}, + {TPM_ALG_NULL, {{TPM_ALG_NULL}}}, + &NIST_P192, + OID_ECC_NIST_P192 CURVE_NAME("NIST_P192")} +# undef comma +# define comma , +# endif // ECC_NIST_P192 +# if ECC_NIST_P224 + comma{TPM_ECC_NIST_P224, + 224, + {TPM_ALG_KDF1_SP800_56A, {{TPM_ALG_SHA256}}}, + {TPM_ALG_NULL, {{TPM_ALG_NULL}}}, + &NIST_P224, + OID_ECC_NIST_P224 CURVE_NAME("NIST_P224")} +# undef comma +# define comma , +# endif // ECC_NIST_P224 +# if ECC_NIST_P256 + comma{TPM_ECC_NIST_P256, + 256, + {TPM_ALG_KDF1_SP800_56A, {{TPM_ALG_SHA256}}}, + {TPM_ALG_NULL, {{TPM_ALG_NULL}}}, + &NIST_P256, + OID_ECC_NIST_P256 CURVE_NAME("NIST_P256")} +# undef comma +# define comma , +# endif // ECC_NIST_P256 +# if ECC_NIST_P384 + comma{TPM_ECC_NIST_P384, + 384, + {TPM_ALG_KDF1_SP800_56A, {{TPM_ALG_SHA384}}}, + {TPM_ALG_NULL, {{TPM_ALG_NULL}}}, + &NIST_P384, + OID_ECC_NIST_P384 CURVE_NAME("NIST_P384")} +# undef comma +# define comma , +# endif // ECC_NIST_P384 +# if ECC_NIST_P521 + comma{TPM_ECC_NIST_P521, + 521, + {TPM_ALG_KDF1_SP800_56A, {{TPM_ALG_SHA512}}}, + {TPM_ALG_NULL, {{TPM_ALG_NULL}}}, + &NIST_P521, + OID_ECC_NIST_P521 CURVE_NAME("NIST_P521")} +# undef comma +# define comma , +# endif // ECC_NIST_P521 +# if ECC_BN_P256 + comma{TPM_ECC_BN_P256, + 256, + {TPM_ALG_NULL, {{TPM_ALG_NULL}}}, + {TPM_ALG_NULL, {{TPM_ALG_NULL}}}, + &BN_P256, + OID_ECC_BN_P256 CURVE_NAME("BN_P256")} +# undef comma +# define comma , +# endif // ECC_BN_P256 +# if ECC_BN_P638 + comma{TPM_ECC_BN_P638, + 638, + {TPM_ALG_NULL, {{TPM_ALG_NULL}}}, + {TPM_ALG_NULL, {{TPM_ALG_NULL}}}, + &BN_P638, + OID_ECC_BN_P638 CURVE_NAME("BN_P638")} +# undef comma +# define comma , +# endif // ECC_BN_P638 +# if ECC_SM2_P256 + comma{TPM_ECC_SM2_P256, + 256, + {TPM_ALG_KDF1_SP800_56A, {{TPM_ALG_SM3_256}}}, + {TPM_ALG_NULL, {{TPM_ALG_NULL}}}, + &SM2_P256, + OID_ECC_SM2_P256 CURVE_NAME("SM2_P256")} +# undef comma +# define comma , +# endif // ECC_SM2_P256 +}; +#endif // TPM_ALG_ECC diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptEccKeyExchange.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptEccKeyExchange.c new file mode 100644 index 0000000..0db9729 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptEccKeyExchange.c @@ -0,0 +1,367 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// This file contains the functions that are used for the two-phase, ECC, +// key-exchange protocols + +#include "Tpm.h" + +#if CC_ZGen_2Phase == YES + +//** Functions + +# if ALG_ECMQV + +//*** avf1() +// This function does the associated value computation required by MQV key +// exchange. +// Process: +// 1. Convert 'xQ' to an integer 'xqi' using the convention specified in Appendix C.3. +// 2. Calculate +// xqm = xqi mod 2^ceil(f/2) (where f = ceil(log2(n)). +// 3. Calculate the associate value function +// avf(Q) = xqm + 2ceil(f / 2) +// Always returns TRUE(1). +static BOOL avf1(bigNum bnX, // IN/OUT: the reduced value + bigNum bnN // IN: the order of the curve +) +{ + // compute f = 2^(ceil(ceil(log2(n)) / 2)) + int f = (BnSizeInBits(bnN) + 1) / 2; + // x' = 2^f + (x mod 2^f) + BnMaskBits(bnX, f); // This is mod 2*2^f but it doesn't matter because + // the next operation will SET the extra bit anyway + BnSetBit(bnX, f); + return TRUE; +} + +//*** C_2_2_MQV() +// This function performs the key exchange defined in SP800-56A +// 6.1.1.4 Full MQV, C(2, 2, ECC MQV). +// +// CAUTION: Implementation of this function may require use of essential claims in +// patents not owned by TCG members. +// +// Points 'QsB' and 'QeB' are required to be on the curve of 'inQsA'. The function +// will fail, possibly catastrophically, if this is not the case. +// Return Type: TPM_RC +// TPM_RC_NO_RESULT the value for dsA does not give a valid point on the +// curve +static TPM_RC C_2_2_MQV(TPMS_ECC_POINT* outZ, // OUT: the computed point + TPM_ECC_CURVE curveId, // IN: the curve for the computations + TPM2B_ECC_PARAMETER* dsA, // IN: static private TPM key + TPM2B_ECC_PARAMETER* deA, // IN: ephemeral private TPM key + TPMS_ECC_POINT* QsB, // IN: static public party B key + TPMS_ECC_POINT* QeB // IN: ephemeral public party B key +) +{ + CURVE_INITIALIZED(E, curveId); + const ECC_CURVE_DATA* C; + POINT(pQeA); + POINT_INITIALIZED(pQeB, QeB); + POINT_INITIALIZED(pQsB, QsB); + ECC_NUM(bnTa); + ECC_INITIALIZED(bnDeA, deA); + ECC_INITIALIZED(bnDsA, dsA); + ECC_NUM(bnN); + ECC_NUM(bnXeB); + TPM_RC retVal; + // + // Parameter checks + if(E == NULL) + ERROR_RETURN(TPM_RC_VALUE); + pAssert( + outZ != NULL && pQeB != NULL && pQsB != NULL && deA != NULL && dsA != NULL); + C = AccessCurveData(E); + // Process: + // 1. implicitsigA = (de,A + avf(Qe,A)ds,A ) mod n. + // 2. P = h(implicitsigA)(Qe,B + avf(Qe,B)Qs,B). + // 3. If P = O, output an error indicator. + // 4. Z=xP, where xP is the x-coordinate of P. + + // Compute the public ephemeral key pQeA = [de,A]G + if((retVal = BnPointMult(pQeA, CurveGetG(C), bnDeA, NULL, NULL, E)) + != TPM_RC_SUCCESS) + goto Exit; + + // 1. implicitsigA = (de,A + avf(Qe,A)ds,A ) mod n. + // tA := (ds,A + de,A avf(Xe,A)) mod n (3) + // Compute 'tA' = ('deA' + 'dsA' avf('XeA')) mod n + // Ta = avf(XeA); + BnCopy(bnTa, pQeA->x); + avf1(bnTa, bnN); + // do Ta = ds,A * Ta mod n = dsA * avf(XeA) mod n + BnModMult(bnTa, bnDsA, bnTa, bnN); + // now Ta = deA + Ta mod n = deA + dsA * avf(XeA) mod n + BnAdd(bnTa, bnTa, bnDeA); + BnMod(bnTa, bnN); + + // 2. P = h(implicitsigA)(Qe,B + avf(Qe,B)Qs,B). + // Put this in because almost every case of h is == 1 so skip the call when + // not necessary. + if(!BnEqualWord(CurveGetCofactor(C), 1)) + // Cofactor is not 1 so compute Ta := Ta * h mod n + BnModMult(bnTa, bnTa, CurveGetCofactor(C), CurveGetOrder(C)); + + // Now that 'tA' is (h * 'tA' mod n) + // 'outZ' = (tA)(Qe,B + avf(Qe,B)Qs,B). + + // first, compute XeB = avf(XeB) + avf1(bnXeB, bnN); + + // QsB := [XeB]QsB + BnPointMult(pQsB, pQsB, bnXeB, NULL, NULL, E); + BnEccAdd(pQeB, pQeB, pQsB, E); + + // QeB := [tA]QeB = [tA](QsB + [Xe,B]QeB) and check for at infinity + // If the result is not the point at infinity, return QeB + BnPointMult(pQeB, pQeB, bnTa, NULL, NULL, E); + if(BnEqualZero(pQeB->z)) + ERROR_RETURN(TPM_RC_NO_RESULT); + // Convert BIGNUM E to TPM2B E + BnPointTo2B(outZ, pQeB, E); + +Exit: + CURVE_FREE(E); + return retVal; +} + +# endif // ALG_ECMQV + +//*** C_2_2_ECDH() +// This function performs the two phase key exchange defined in SP800-56A, +// 6.1.1.2 Full Unified Model, C(2, 2, ECC CDH). +// +static TPM_RC C_2_2_ECDH(TPMS_ECC_POINT* outZs, // OUT: Zs + TPMS_ECC_POINT* outZe, // OUT: Ze + TPM_ECC_CURVE curveId, // IN: the curve for the computations + TPM2B_ECC_PARAMETER* dsA, // IN: static private TPM key + TPM2B_ECC_PARAMETER* deA, // IN: ephemeral private TPM key + TPMS_ECC_POINT* QsB, // IN: static public party B key + TPMS_ECC_POINT* QeB // IN: ephemeral public party B key +) +{ + CURVE_INITIALIZED(E, curveId); + ECC_INITIALIZED(bnAs, dsA); + ECC_INITIALIZED(bnAe, deA); + POINT_INITIALIZED(ecBs, QsB); + POINT_INITIALIZED(ecBe, QeB); + POINT(ecZ); + TPM_RC retVal; + // + // Parameter checks + if(E == NULL) + ERROR_RETURN(TPM_RC_CURVE); + pAssert( + outZs != NULL && dsA != NULL && deA != NULL && QsB != NULL && QeB != NULL); + + // Do the point multiply for the Zs value ([dsA]QsB) + retVal = BnPointMult(ecZ, ecBs, bnAs, NULL, NULL, E); + if(retVal == TPM_RC_SUCCESS) + { + // Convert the Zs value. + BnPointTo2B(outZs, ecZ, E); + // Do the point multiply for the Ze value ([deA]QeB) + retVal = BnPointMult(ecZ, ecBe, bnAe, NULL, NULL, E); + if(retVal == TPM_RC_SUCCESS) + BnPointTo2B(outZe, ecZ, E); + } +Exit: + CURVE_FREE(E); + return retVal; +} + +//*** CryptEcc2PhaseKeyExchange() +// This function is the dispatch routine for the EC key exchange functions that use +// two ephemeral and two static keys. +// Return Type: TPM_RC +// TPM_RC_SCHEME scheme is not defined +LIB_EXPORT TPM_RC CryptEcc2PhaseKeyExchange( + TPMS_ECC_POINT* outZ1, // OUT: a computed point + TPMS_ECC_POINT* outZ2, // OUT: and optional second point + TPM_ECC_CURVE curveId, // IN: the curve for the computations + TPM_ALG_ID scheme, // IN: the key exchange scheme + TPM2B_ECC_PARAMETER* dsA, // IN: static private TPM key + TPM2B_ECC_PARAMETER* deA, // IN: ephemeral private TPM key + TPMS_ECC_POINT* QsB, // IN: static public party B key + TPMS_ECC_POINT* QeB // IN: ephemeral public party B key +) +{ + pAssert( + outZ1 != NULL && dsA != NULL && deA != NULL && QsB != NULL && QeB != NULL); + + // Initialize the output points so that they are empty until one of the + // functions decides otherwise + outZ1->x.b.size = 0; + outZ1->y.b.size = 0; + if(outZ2 != NULL) + { + outZ2->x.b.size = 0; + outZ2->y.b.size = 0; + } + switch(scheme) + { + case TPM_ALG_ECDH: + return C_2_2_ECDH(outZ1, outZ2, curveId, dsA, deA, QsB, QeB); + break; +# if ALG_ECMQV + case TPM_ALG_ECMQV: + return C_2_2_MQV(outZ1, curveId, dsA, deA, QsB, QeB); + break; +# endif +# if ALG_SM2 + case TPM_ALG_SM2: + return SM2KeyExchange(outZ1, curveId, dsA, deA, QsB, QeB); + break; +# endif + default: + return TPM_RC_SCHEME; + } +} + +# if ALG_SM2 + +//*** ComputeWForSM2() +// Compute the value for w used by SM2 +static UINT32 ComputeWForSM2(bigCurve E) +{ + // w := ceil(ceil(log2(n)) / 2) - 1 + return (BnMsb(CurveGetOrder(AccessCurveData(E))) / 2 - 1); +} + +//*** avfSm2() +// This function does the associated value computation required by SM2 key +// exchange. This is different from the avf() in the international standards +// because it returns a value that is half the size of the value returned by the +// standard avf(). For example, if 'n' is 15, 'Ws' ('w' in the standard) is 2 but +// the 'W' here is 1. This means that an input value of 14 (1110b) would return a +// value of 110b with the standard but 10b with the scheme in SM2. +static bigNum avfSm2(bigNum bn, // IN/OUT: the reduced value + UINT32 w // IN: the value of w +) +{ + // a) set w := ceil(ceil(log2(n)) / 2) - 1 + // b) set x' := 2^w + ( x & (2^w - 1)) + // This is just like the avf for MQV where x' = 2^w + (x mod 2^w) + + BnMaskBits(bn, w); // as with avf1, this is too big by a factor of 2 but + // it doesn't matter because we SET the extra bit + // anyway + BnSetBit(bn, w); + return bn; +} + +//*** SM2KeyExchange() +// This function performs the key exchange defined in SM2. +// The first step is to compute +// 'tA' = ('dsA' + 'deA' avf(Xe,A)) mod 'n' +// Then, compute the 'Z' value from +// 'outZ' = ('h' 'tA' mod 'n') ('QsA' + [avf('QeB.x')]('QeB')). +// The function will compute the ephemeral public key from the ephemeral +// private key. +// All points are required to be on the curve of 'inQsA'. The function will fail +// catastrophically if this is not the case +// Return Type: TPM_RC +// TPM_RC_NO_RESULT the value for dsA does not give a valid point on the +// curve +LIB_EXPORT TPM_RC SM2KeyExchange( + TPMS_ECC_POINT* outZ, // OUT: the computed point + TPM_ECC_CURVE curveId, // IN: the curve for the computations + TPM2B_ECC_PARAMETER* dsAIn, // IN: static private TPM key + TPM2B_ECC_PARAMETER* deAIn, // IN: ephemeral private TPM key + TPMS_ECC_POINT* QsBIn, // IN: static public party B key + TPMS_ECC_POINT* QeBIn // IN: ephemeral public party B key +) +{ + CURVE_INITIALIZED(E, curveId); + const ECC_CURVE_DATA* C; + ECC_INITIALIZED(dsA, dsAIn); + ECC_INITIALIZED(deA, deAIn); + POINT_INITIALIZED(QsB, QsBIn); + POINT_INITIALIZED(QeB, QeBIn); + BN_WORD_INITIALIZED(One, 1); + POINT(QeA); + ECC_NUM(XeB); + POINT(Z); + ECC_NUM(Ta); + UINT32 w; + TPM_RC retVal = TPM_RC_NO_RESULT; + // + // Parameter checks + if(E == NULL) + ERROR_RETURN(TPM_RC_CURVE); + C = AccessCurveData(E); + pAssert(outZ != NULL && dsA != NULL && deA != NULL && QsB != NULL && QeB != NULL); + + // Compute the value for w + w = ComputeWForSM2(E); + + // Compute the public ephemeral key pQeA = [de,A]G + if(!BnEccModMult(QeA, CurveGetG(C), deA, E)) + goto Exit; + + // tA := (ds,A + de,A avf(Xe,A)) mod n (3) + // Compute 'tA' = ('dsA' + 'deA' avf('XeA')) mod n + // Ta = avf(XeA); + // do Ta = de,A * Ta = deA * avf(XeA) + BnMult(Ta, deA, avfSm2(QeA->x, w)); + // now Ta = dsA + Ta = dsA + deA * avf(XeA) + BnAdd(Ta, dsA, Ta); + BnMod(Ta, CurveGetOrder(C)); + + // outZ = [h tA mod n] (Qs,B + [avf(Xe,B)](Qe,B)) (4) + // Put this in because almost every case of h is == 1 so skip the call when + // not necessary. + if(!BnEqualWord(CurveGetCofactor(C), 1)) + // Cofactor is not 1 so compute Ta := Ta * h mod n + BnModMult(Ta, Ta, CurveGetCofactor(C), CurveGetOrder(C)); + // Now that 'tA' is (h * 'tA' mod n) + // 'outZ' = ['tA'](QsB + [avf(QeB.x)](QeB)). + BnCopy(XeB, QeB->x); + if(!BnEccModMult2(Z, QsB, One, QeB, avfSm2(XeB, w), E)) + goto Exit; + // QeB := [tA]QeB = [tA](QsB + [Xe,B]QeB) and check for at infinity + if(!BnEccModMult(Z, Z, Ta, E)) + goto Exit; + // Convert BIGNUM E to TPM2B E + BnPointTo2B(outZ, Z, E); + retVal = TPM_RC_SUCCESS; +Exit: + CURVE_FREE(E); + return retVal; +} +# endif + +#endif // CC_ZGen_2Phase \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptEccMain.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptEccMain.c new file mode 100644 index 0000000..57bd783 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptEccMain.c @@ -0,0 +1,771 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Includes and Defines +#include "Tpm.h" + +#if ALG_ECC + +// This version requires that the new format for ECC data be used +# if !USE_BN_ECC_DATA +# error "Need to SET USE_BN_ECC_DATA to YES in Implementaion.h" +# endif + +//** Functions + +# if SIMULATION +void EccSimulationEnd(void) +{ +# if SIMULATION +// put things to be printed at the end of the simulation here +# endif +} +# endif // SIMULATION + +//*** CryptEccInit() +// This function is called at _TPM_Init +BOOL CryptEccInit(void) +{ + return TRUE; +} + +//*** CryptEccStartup() +// This function is called at TPM2_Startup(). +BOOL CryptEccStartup(void) +{ + return TRUE; +} + +//*** ClearPoint2B(generic) +// Initialize the size values of a TPMS_ECC_POINT structure. +void ClearPoint2B(TPMS_ECC_POINT* p // IN: the point +) +{ + if(p != NULL) + { + p->x.t.size = 0; + p->y.t.size = 0; + } +} + +//*** CryptEccGetParametersByCurveId() +// This function returns a pointer to the curve data that is associated with +// the indicated curveId. +// If there is no curve with the indicated ID, the function returns NULL. This +// function is in this module so that it can be called by GetCurve data. +// Return Type: const ECC_CURVE_DATA +// NULL curve with the indicated TPM_ECC_CURVE is not implemented +// != NULL pointer to the curve data +LIB_EXPORT const ECC_CURVE* CryptEccGetParametersByCurveId( + TPM_ECC_CURVE curveId // IN: the curveID +) +{ + int i; + for(i = 0; i < ECC_CURVE_COUNT; i++) + { + if(eccCurves[i].curveId == curveId) + return &eccCurves[i]; + } + return NULL; +} + +//*** CryptEccGetKeySizeForCurve() +// This function returns the key size in bits of the indicated curve. +LIB_EXPORT UINT16 CryptEccGetKeySizeForCurve(TPM_ECC_CURVE curveId // IN: the curve +) +{ + const ECC_CURVE* curve = CryptEccGetParametersByCurveId(curveId); + UINT16 keySizeInBits; + // + keySizeInBits = (curve != NULL) ? curve->keySizeBits : 0; + return keySizeInBits; +} + +//*** GetCurveData() +// This function returns the a pointer for the parameter data +// associated with a curve. +const ECC_CURVE_DATA* GetCurveData(TPM_ECC_CURVE curveId // IN: the curveID +) +{ + const ECC_CURVE* curve = CryptEccGetParametersByCurveId(curveId); + return (curve != NULL) ? curve->curveData : NULL; +} + +//***CryptEccGetOID() +const BYTE* CryptEccGetOID(TPM_ECC_CURVE curveId) +{ + const ECC_CURVE* curve = CryptEccGetParametersByCurveId(curveId); + return (curve != NULL) ? curve->OID : NULL; +} + +//*** CryptEccGetCurveByIndex() +// This function returns the number of the 'i'-th implemented curve. The normal +// use would be to call this function with 'i' starting at 0. When the 'i' is greater +// than or equal to the number of implemented curves, TPM_ECC_NONE is returned. +LIB_EXPORT TPM_ECC_CURVE CryptEccGetCurveByIndex(UINT16 i) +{ + if(i >= ECC_CURVE_COUNT) + return TPM_ECC_NONE; + return eccCurves[i].curveId; +} + +//*** CryptEccGetParameter() +// This function returns an ECC curve parameter. The parameter is +// selected by a single character designator from the set of ""PNABXYH"". +// Return Type: BOOL +// TRUE(1) curve exists and parameter returned +// FALSE(0) curve does not exist or parameter selector +LIB_EXPORT BOOL CryptEccGetParameter( + TPM2B_ECC_PARAMETER* out, // OUT: place to put parameter + char p, // IN: the parameter selector + TPM_ECC_CURVE curveId // IN: the curve id +) +{ + const ECC_CURVE_DATA* curve = GetCurveData(curveId); + bigConst parameter = NULL; + + if(curve != NULL) + { + switch(p) + { + case 'p': + parameter = CurveGetPrime(curve); + break; + case 'n': + parameter = CurveGetOrder(curve); + break; + case 'a': + parameter = CurveGet_a(curve); + break; + case 'b': + parameter = CurveGet_b(curve); + break; + case 'x': + parameter = CurveGetGx(curve); + break; + case 'y': + parameter = CurveGetGy(curve); + break; + case 'h': + parameter = CurveGetCofactor(curve); + break; + default: + FAIL(FATAL_ERROR_INTERNAL); + break; + } + } + // If not debugging and we get here with parameter still NULL, had better + // not try to convert so just return FALSE instead. + return (parameter != NULL) ? BnTo2B(parameter, &out->b, 0) : 0; +} + +//*** CryptCapGetECCCurve() +// This function returns the list of implemented ECC curves. +// Return Type: TPMI_YES_NO +// YES if no more ECC curve is available +// NO if there are more ECC curves not reported +TPMI_YES_NO +CryptCapGetECCCurve(TPM_ECC_CURVE curveID, // IN: the starting ECC curve + UINT32 maxCount, // IN: count of returned curves + TPML_ECC_CURVE* curveList // OUT: ECC curve list +) +{ + TPMI_YES_NO more = NO; + UINT16 i; + UINT32 count = ECC_CURVE_COUNT; + TPM_ECC_CURVE curve; + + // Initialize output property list + curveList->count = 0; + + // The maximum count of curves we may return is MAX_ECC_CURVES + if(maxCount > MAX_ECC_CURVES) + maxCount = MAX_ECC_CURVES; + + // Scan the eccCurveValues array + for(i = 0; i < count; i++) + { + curve = CryptEccGetCurveByIndex(i); + // If curveID is less than the starting curveID, skip it + if(curve < curveID) + continue; + if(curveList->count < maxCount) + { + // If we have not filled up the return list, add more curves to + // it + curveList->eccCurves[curveList->count] = curve; + curveList->count++; + } + else + { + // If the return list is full but we still have curves + // available, report this and stop iterating + more = YES; + break; + } + } + return more; +} + +//*** CryptGetCurveSignScheme() +// This function will return a pointer to the scheme of the curve. +const TPMT_ECC_SCHEME* CryptGetCurveSignScheme( + TPM_ECC_CURVE curveId // IN: The curve selector +) +{ + const ECC_CURVE* curve = CryptEccGetParametersByCurveId(curveId); + + if(curve != NULL) + return &(curve->sign); + else + return NULL; +} + +//*** CryptGenerateR() +// This function computes the commit random value for a split signing scheme. +// +// If 'c' is NULL, it indicates that 'r' is being generated +// for TPM2_Commit. +// If 'c' is not NULL, the TPM will validate that the 'gr.commitArray' +// bit associated with the input value of 'c' is SET. If not, the TPM +// returns FALSE and no 'r' value is generated. +// Return Type: BOOL +// TRUE(1) r value computed +// FALSE(0) no r value computed +BOOL CryptGenerateR(TPM2B_ECC_PARAMETER* r, // OUT: the generated random value + UINT16* c, // IN/OUT: count value. + TPMI_ECC_CURVE curveID, // IN: the curve for the value + TPM2B_NAME* name // IN: optional name of a key to + // associate with 'r' +) +{ + // This holds the marshaled g_commitCounter. + TPM2B_TYPE(8B, 8); + TPM2B_8B cntr = {{8, {0}}}; + UINT32 iterations; + TPM2B_ECC_PARAMETER n; + UINT64 currentCount = gr.commitCounter; + UINT16 t1; + // + if(!CryptEccGetParameter(&n, 'n', curveID)) + return FALSE; + + // If this is the commit phase, use the current value of the commit counter + if(c != NULL) + { + // if the array bit is not set, can't use the value. + if(!TEST_BIT((*c & COMMIT_INDEX_MASK), gr.commitArray)) + return FALSE; + + // If it is the sign phase, figure out what the counter value was + // when the commitment was made. + // + // When gr.commitArray has less than 64K bits, the extra + // bits of 'c' are used as a check to make sure that the + // signing operation is not using an out of range count value + t1 = (UINT16)currentCount; + + // If the lower bits of c are greater or equal to the lower bits of t1 + // then the upper bits of t1 must be one more than the upper bits + // of c + if((*c & COMMIT_INDEX_MASK) >= (t1 & COMMIT_INDEX_MASK)) + // Since the counter is behind, reduce the current count + currentCount = currentCount - (COMMIT_INDEX_MASK + 1); + + t1 = (UINT16)currentCount; + if((t1 & ~COMMIT_INDEX_MASK) != (*c & ~COMMIT_INDEX_MASK)) + return FALSE; + // set the counter to the value that was + // present when the commitment was made + currentCount = (currentCount & 0xffffffffffff0000) | *c; + } + // Marshal the count value to a TPM2B buffer for the KDF + cntr.t.size = sizeof(currentCount); + UINT64_TO_BYTE_ARRAY(currentCount, cntr.t.buffer); + + // Now can do the KDF to create the random value for the signing operation + // During the creation process, we may generate an r that does not meet the + // requirements of the random value. + // want to generate a new r. + r->t.size = n.t.size; + + for(iterations = 1; iterations < 1000000;) + { + int i; + CryptKDFa(CONTEXT_INTEGRITY_HASH_ALG, + &gr.commitNonce.b, + COMMIT_STRING, + &name->b, + &cntr.b, + n.t.size * 8, + r->t.buffer, + &iterations, + FALSE); + + // "random" value must be less than the prime + if(UnsignedCompareB(r->b.size, r->b.buffer, n.t.size, n.t.buffer) >= 0) + continue; + + // in this implementation it is required that at least bit + // in the upper half of the number be set + for(i = n.t.size / 2; i >= 0; i--) + if(r->b.buffer[i] != 0) + return TRUE; + } + return FALSE; +} + +//*** CryptCommit() +// This function is called when the count value is committed. The 'gr.commitArray' +// value associated with the current count value is SET and g_commitCounter is +// incremented. The low-order 16 bits of old value of the counter is returned. +UINT16 +CryptCommit(void) +{ + UINT16 oldCount = (UINT16)gr.commitCounter; + gr.commitCounter++; + SET_BIT(oldCount & COMMIT_INDEX_MASK, gr.commitArray); + return oldCount; +} + +//*** CryptEndCommit() +// This function is called when the signing operation using the committed value +// is completed. It clears the gr.commitArray bit associated with the count +// value so that it can't be used again. +void CryptEndCommit(UINT16 c // IN: the counter value of the commitment +) +{ + ClearBit((c & COMMIT_INDEX_MASK), gr.commitArray, sizeof(gr.commitArray)); +} + +//*** CryptEccGetParameters() +// This function returns the ECC parameter details of the given curve. +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) unsupported ECC curve ID +BOOL CryptEccGetParameters( + TPM_ECC_CURVE curveId, // IN: ECC curve ID + TPMS_ALGORITHM_DETAIL_ECC* parameters // OUT: ECC parameters +) +{ + const ECC_CURVE* curve = CryptEccGetParametersByCurveId(curveId); + const ECC_CURVE_DATA* data; + BOOL found = curve != NULL; + + if(found) + { + data = curve->curveData; + parameters->curveID = curve->curveId; + parameters->keySize = curve->keySizeBits; + parameters->kdf = curve->kdf; + parameters->sign = curve->sign; + // BnTo2B(data->prime, ¶meters->p.b, 0); + BnTo2B(data->prime, ¶meters->p.b, parameters->p.t.size); + BnTo2B(data->a, ¶meters->a.b, 0); + BnTo2B(data->b, ¶meters->b.b, 0); + BnTo2B(data->base.x, ¶meters->gX.b, parameters->p.t.size); + BnTo2B(data->base.y, ¶meters->gY.b, parameters->p.t.size); + // BnTo2B(data->base.x, ¶meters->gX.b, 0); + // BnTo2B(data->base.y, ¶meters->gY.b, 0); + BnTo2B(data->order, ¶meters->n.b, 0); + BnTo2B(data->h, ¶meters->h.b, 0); + } + return found; +} + +//*** BnGetCurvePrime() +// This function is used to get just the prime modulus associated with a curve. +const bignum_t* BnGetCurvePrime(TPM_ECC_CURVE curveId) +{ + const ECC_CURVE_DATA* C = GetCurveData(curveId); + return (C != NULL) ? CurveGetPrime(C) : NULL; +} + +//*** BnGetCurveOrder() +// This function is used to get just the curve order +const bignum_t* BnGetCurveOrder(TPM_ECC_CURVE curveId) +{ + const ECC_CURVE_DATA* C = GetCurveData(curveId); + return (C != NULL) ? CurveGetOrder(C) : NULL; +} + +//*** BnIsOnCurve() +// This function checks if a point is on the curve. +BOOL BnIsOnCurve(pointConst Q, const ECC_CURVE_DATA* C) +{ + BN_VAR(right, (MAX_ECC_KEY_BITS * 3)); + BN_VAR(left, (MAX_ECC_KEY_BITS * 2)); + bigConst prime = CurveGetPrime(C); + // + // Show that point is on the curve y^2 = x^3 + ax + b; + // Or y^2 = x(x^2 + a) + b + // y^2 + BnMult(left, Q->y, Q->y); + + BnMod(left, prime); + // x^2 + BnMult(right, Q->x, Q->x); + + // x^2 + a + BnAdd(right, right, CurveGet_a(C)); + + // BnMod(right, CurveGetPrime(C)); + // x(x^2 + a) + BnMult(right, right, Q->x); + + // x(x^2 + a) + b + BnAdd(right, right, CurveGet_b(C)); + + BnMod(right, prime); + if(BnUnsignedCmp(left, right) == 0) + return TRUE; + else + return FALSE; +} + +//*** BnIsValidPrivateEcc() +// Checks that 0 < 'x' < 'q' +BOOL BnIsValidPrivateEcc(bigConst x, // IN: private key to check + bigCurve E // IN: the curve to check +) +{ + BOOL retVal; + retVal = (!BnEqualZero(x) + && (BnUnsignedCmp(x, CurveGetOrder(AccessCurveData(E))) < 0)); + return retVal; +} + +LIB_EXPORT BOOL CryptEccIsValidPrivateKey(TPM2B_ECC_PARAMETER* d, + TPM_ECC_CURVE curveId) +{ + BN_INITIALIZED(bnD, MAX_ECC_PARAMETER_BYTES * 8, d); + return !BnEqualZero(bnD) && (BnUnsignedCmp(bnD, BnGetCurveOrder(curveId)) < 0); +} + +//*** BnPointMul() +// This function does a point multiply of the form 'R' = ['d']'S' + ['u']'Q' where the +// parameters are bigNum values. If 'S' is NULL and d is not NULL, then it computes +// 'R' = ['d']'G' + ['u']'Q' or just 'R' = ['d']'G' if 'u' and 'Q' are NULL. +// If 'skipChecks' is TRUE, then the function will not verify that the inputs are +// correct for the domain. This would be the case when the values were created by the +// CryptoEngine code. +// It will return TPM_RC_NO_RESULT if the resulting point is the point at infinity. +// Return Type: TPM_RC +// TPM_RC_NO_RESULT result of multiplication is a point at infinity +// TPM_RC_ECC_POINT 'S' or 'Q' is not on the curve +// TPM_RC_VALUE 'd' or 'u' is not < n +TPM_RC +BnPointMult(bigPoint R, // OUT: computed point + pointConst S, // IN: optional point to multiply by 'd' + bigConst d, // IN: scalar for [d]S or [d]G + pointConst Q, // IN: optional second point + bigConst u, // IN: optional second scalar + bigCurve E // IN: curve parameters +) +{ + BOOL OK; + // + TEST(TPM_ALG_ECDH); + + // Need one scalar + OK = (d != NULL || u != NULL); + + // If S is present, then d has to be present. If S is not + // present, then d may or may not be present + OK = OK && (((S == NULL) == (d == NULL)) || (d != NULL)); + + // either both u and Q have to be provided or neither can be provided (don't + // know what to do if only one is provided. + OK = OK && ((u == NULL) == (Q == NULL)); + + OK = OK && (E != NULL); + if(!OK) + return TPM_RC_VALUE; + + OK = (S == NULL) || BnIsOnCurve(S, AccessCurveData(E)); + OK = OK && ((Q == NULL) || BnIsOnCurve(Q, AccessCurveData(E))); + if(!OK) + return TPM_RC_ECC_POINT; + + if((d != NULL) && (S == NULL)) + S = CurveGetG(AccessCurveData(E)); + // If only one scalar, don't need Shamir's trick + if((d == NULL) || (u == NULL)) + { + if(d == NULL) + OK = BnEccModMult(R, Q, u, E); + else + OK = BnEccModMult(R, S, d, E); + } + else + { + OK = BnEccModMult2(R, S, d, Q, u, E); + } + return (OK ? TPM_RC_SUCCESS : TPM_RC_NO_RESULT); +} + +//***BnEccGetPrivate() +// This function gets random values that are the size of the key plus 64 bits. The +// value is reduced (mod ('q' - 1)) and incremented by 1 ('q' is the order of the +// curve. This produces a value ('d') such that 1 <= 'd' < 'q'. This is the method +// of FIPS 186-4 Section B.4.1 ""Key Pair Generation Using Extra Random Bits"". +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure generating private key +BOOL BnEccGetPrivate(bigNum dOut, // OUT: the qualified random value + const ECC_CURVE_DATA* C, // IN: curve for which the private key + // needs to be appropriate + RAND_STATE* rand // IN: state for DRBG +) +{ + bigConst order = CurveGetOrder(C); + BOOL OK; + UINT32 orderBits = BnSizeInBits(order); + UINT32 orderBytes = BITS_TO_BYTES(orderBits); + BN_VAR(bnExtraBits, MAX_ECC_KEY_BITS + 64); + BN_VAR(nMinus1, MAX_ECC_KEY_BITS); + // + OK = BnGetRandomBits(bnExtraBits, (orderBytes * 8) + 64, rand); + OK = OK && BnSubWord(nMinus1, order, 1); + OK = OK && BnMod(bnExtraBits, nMinus1); + OK = OK && BnAddWord(dOut, bnExtraBits, 1); + return OK && !g_inFailureMode; +} + +//*** BnEccGenerateKeyPair() +// This function gets a private scalar from the source of random bits and does +// the point multiply to get the public key. +BOOL BnEccGenerateKeyPair(bigNum bnD, // OUT: private scalar + bn_point_t* ecQ, // OUT: public point + bigCurve E, // IN: curve for the point + RAND_STATE* rand // IN: DRBG state to use +) +{ + BOOL OK = FALSE; + // Get a private scalar + OK = BnEccGetPrivate(bnD, AccessCurveData(E), rand); + + // Do a point multiply + OK = OK && BnEccModMult(ecQ, NULL, bnD, E); + if(!OK) + BnSetWord(ecQ->z, 0); + else + BnSetWord(ecQ->z, 1); + return OK; +} + +//***CryptEccNewKeyPair(***) +// This function creates an ephemeral ECC. It is ephemeral in that +// is expected that the private part of the key will be discarded +LIB_EXPORT TPM_RC CryptEccNewKeyPair( + TPMS_ECC_POINT* Qout, // OUT: the public point + TPM2B_ECC_PARAMETER* dOut, // OUT: the private scalar + TPM_ECC_CURVE curveId // IN: the curve for the key +) +{ + CURVE_INITIALIZED(E, curveId); + POINT(ecQ); + ECC_NUM(bnD); + BOOL OK; + + if(E == NULL) + return TPM_RC_CURVE; + + TEST(TPM_ALG_ECDH); + OK = BnEccGenerateKeyPair(bnD, ecQ, E, NULL); + if(OK) + { + BnPointTo2B(Qout, ecQ, E); + BnTo2B(bnD, &dOut->b, Qout->x.t.size); + } + else + { + Qout->x.t.size = Qout->y.t.size = dOut->t.size = 0; + } + CURVE_FREE(E); + return OK ? TPM_RC_SUCCESS : TPM_RC_NO_RESULT; +} + +//*** CryptEccPointMultiply() +// This function computes 'R' := ['dIn']'G' + ['uIn']'QIn'. Where 'dIn' and +// 'uIn' are scalars, 'G' and 'QIn' are points on the specified curve and 'G' is the +// default generator of the curve. +// +// The 'xOut' and 'yOut' parameters are optional and may be set to NULL if not +// used. +// +// It is not necessary to provide 'uIn' if 'QIn' is specified but one of 'uIn' and +// 'dIn' must be provided. If 'dIn' and 'QIn' are specified but 'uIn' is not +// provided, then 'R' = ['dIn']'QIn'. +// +// If the multiply produces the point at infinity, the TPM_RC_NO_RESULT is returned. +// +// The sizes of 'xOut' and yOut' will be set to be the size of the degree of +// the curve +// +// It is a fatal error if 'dIn' and 'uIn' are both unspecified (NULL) or if 'Qin' +// or 'Rout' is unspecified. +// +// Return Type: TPM_RC +// TPM_RC_ECC_POINT the point 'Pin' or 'Qin' is not on the curve +// TPM_RC_NO_RESULT the product point is at infinity +// TPM_RC_CURVE bad curve +// TPM_RC_VALUE 'dIn' or 'uIn' out of range +// +LIB_EXPORT TPM_RC CryptEccPointMultiply( + TPMS_ECC_POINT* Rout, // OUT: the product point R + TPM_ECC_CURVE curveId, // IN: the curve to use + TPMS_ECC_POINT* Pin, // IN: first point (can be null) + TPM2B_ECC_PARAMETER* dIn, // IN: scalar value for [dIn]Qin + // the Pin + TPMS_ECC_POINT* Qin, // IN: point Q + TPM2B_ECC_PARAMETER* uIn // IN: scalar value for the multiplier + // of Q +) +{ + CURVE_INITIALIZED(E, curveId); + POINT_INITIALIZED(ecP, Pin); + ECC_INITIALIZED(bnD, dIn); // If dIn is null, then bnD is null + ECC_INITIALIZED(bnU, uIn); + POINT_INITIALIZED(ecQ, Qin); + POINT(ecR); + TPM_RC retVal; + // + retVal = BnPointMult(ecR, ecP, bnD, ecQ, bnU, E); + + if(retVal == TPM_RC_SUCCESS) + BnPointTo2B(Rout, ecR, E); + else + ClearPoint2B(Rout); + CURVE_FREE(E); + return retVal; +} + +//*** CryptEccIsPointOnCurve() +// This function is used to test if a point is on a defined curve. It does this +// by checking that 'y'^2 mod 'p' = 'x'^3 + 'a'*'x' + 'b' mod 'p'. +// +// It is a fatal error if 'Q' is not specified (is NULL). +// Return Type: BOOL +// TRUE(1) point is on curve +// FALSE(0) point is not on curve or curve is not supported +LIB_EXPORT BOOL CryptEccIsPointOnCurve( + TPM_ECC_CURVE curveId, // IN: the curve selector + TPMS_ECC_POINT* Qin // IN: the point. +) +{ + const ECC_CURVE_DATA* C = GetCurveData(curveId); + POINT_INITIALIZED(ecQ, Qin); + BOOL OK; + // + pAssert(Qin != NULL); + OK = (C != NULL && (BnIsOnCurve(ecQ, C))); + return OK; +} + +//*** CryptEccGenerateKey() +// This function generates an ECC key pair based on the input parameters. +// This routine uses KDFa to produce candidate numbers. The method is according +// to FIPS 186-3, section B.1.2 "Key Pair Generation by Testing Candidates." +// According to the method in FIPS 186-3, the resulting private value 'd' should be +// 1 <= 'd' < 'n' where 'n' is the order of the base point. +// +// It is a fatal error if 'Qout', 'dOut', is not provided (is NULL). +// +// If the curve is not supported +// If 'seed' is not provided, then a random number will be used for the key +// Return Type: TPM_RC +// TPM_RC_CURVE curve is not supported +// TPM_RC_NO_RESULT could not verify key with signature (FIPS only) +LIB_EXPORT TPM_RC CryptEccGenerateKey( + TPMT_PUBLIC* publicArea, // IN/OUT: The public area template for + // the new key. The public key + // area will be replaced computed + // ECC public key + TPMT_SENSITIVE* sensitive, // OUT: the sensitive area will be + // updated to contain the private + // ECC key and the symmetric + // encryption key + RAND_STATE* rand // IN: if not NULL, the deterministic + // RNG state +) +{ + CURVE_INITIALIZED(E, publicArea->parameters.eccDetail.curveID); + ECC_NUM(bnD); + POINT(ecQ); + BOOL OK; + TPM_RC retVal; + // + TEST(TPM_ALG_ECDSA); // ECDSA is used to verify each key + + // Validate parameters + if(E == NULL) + ERROR_RETURN(TPM_RC_CURVE); + + publicArea->unique.ecc.x.t.size = 0; + publicArea->unique.ecc.y.t.size = 0; + sensitive->sensitive.ecc.t.size = 0; + + OK = BnEccGenerateKeyPair(bnD, ecQ, E, rand); + if(OK) + { + BnPointTo2B(&publicArea->unique.ecc, ecQ, E); + BnTo2B(bnD, &sensitive->sensitive.ecc.b, publicArea->unique.ecc.x.t.size); + } +# if FIPS_COMPLIANT + // See if PWCT is required + if(OK && IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign)) + { + ECC_NUM(bnT); + ECC_NUM(bnS); + TPM2B_DIGEST digest; + // + TEST(TPM_ALG_ECDSA); + digest.t.size = MIN(sensitive->sensitive.ecc.t.size, sizeof(digest.t.buffer)); + // Get a random value to sign using the built in DRBG state + DRBG_Generate(NULL, digest.t.buffer, digest.t.size); + if(g_inFailureMode) + return TPM_RC_FAILURE; + BnSignEcdsa(bnT, bnS, E, bnD, &digest, NULL); + // and make sure that we can validate the signature + OK = BnValidateSignatureEcdsa(bnT, bnS, E, ecQ, &digest) == TPM_RC_SUCCESS; + } +# endif + retVal = (OK) ? TPM_RC_SUCCESS : TPM_RC_NO_RESULT; +Exit: + CURVE_FREE(E); + return retVal; +} + +#endif // ALG_ECC \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptEccSignature.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptEccSignature.c new file mode 100644 index 0000000..75c2e5e --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptEccSignature.c @@ -0,0 +1,920 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Includes and Defines +#include "Tpm.h" +#include "CryptEccSignature_fp.h" + +#if ALG_ECC + +//** Utility Functions + +//*** EcdsaDigest() +// Function to adjust the digest so that it is no larger than the order of the +// curve. This is used for ECDSA sign and verification. +static bigNum EcdsaDigest(bigNum bnD, // OUT: the adjusted digest + const TPM2B_DIGEST* digest, // IN: digest to adjust + bigConst max // IN: value that indicates the maximum + // number of bits in the results +) +{ + int bitsInMax = BnSizeInBits(max); + int shift; + // + if(digest == NULL) + BnSetWord(bnD, 0); + else + { + BnFromBytes(bnD, + digest->t.buffer, + (NUMBYTES)MIN(digest->t.size, BITS_TO_BYTES(bitsInMax))); + shift = BnSizeInBits(bnD) - bitsInMax; + if(shift > 0) + BnShiftRight(bnD, bnD, shift); + } + return bnD; +} + +//*** BnSchnorrSign() +// This contains the Schnorr signature computation. It is used by both ECDSA and +// Schnorr signing. The result is computed as: ['s' = 'k' + 'r' * 'd' (mod 'n')] +// where +// 1) 's' is the signature +// 2) 'k' is a random value +// 3) 'r' is the value to sign +// 4) 'd' is the private EC key +// 5) 'n' is the order of the curve +// Return Type: TPM_RC +// TPM_RC_NO_RESULT the result of the operation was zero or 'r' (mod 'n') +// is zero +static TPM_RC BnSchnorrSign(bigNum bnS, // OUT: 's' component of the signature + bigConst bnK, // IN: a random value + bigNum bnR, // IN: the signature 'r' value + bigConst bnD, // IN: the private key + bigConst bnN // IN: the order of the curve +) +{ + // Need a local temp value to store the intermediate computation because product + // size can be larger than will fit in bnS. + BN_VAR(bnT1, MAX_ECC_PARAMETER_BYTES * 2 * 8); + // + // Reduce bnR without changing the input value + BnDiv(NULL, bnT1, bnR, bnN); + if(BnEqualZero(bnT1)) + return TPM_RC_NO_RESULT; + // compute s = (k + r * d)(mod n) + // r * d + BnMult(bnT1, bnT1, bnD); + // k * r * d + BnAdd(bnT1, bnT1, bnK); + // k + r * d (mod n) + BnDiv(NULL, bnS, bnT1, bnN); + return (BnEqualZero(bnS)) ? TPM_RC_NO_RESULT : TPM_RC_SUCCESS; +} + +//** Signing Functions + +//*** BnSignEcdsa() +// This function implements the ECDSA signing algorithm. The method is described +// in the comments below. +TPM_RC +BnSignEcdsa(bigNum bnR, // OUT: 'r' component of the signature + bigNum bnS, // OUT: 's' component of the signature + bigCurve E, // IN: the curve used in the signature + // process + bigNum bnD, // IN: private signing key + const TPM2B_DIGEST* digest, // IN: the digest to sign + RAND_STATE* rand // IN: used in debug of signing +) +{ + ECC_NUM(bnK); + ECC_NUM(bnIk); + BN_VAR(bnE, MAX(MAX_ECC_KEY_BYTES, MAX_DIGEST_SIZE) * 8); + POINT(ecR); + bigConst order = CurveGetOrder(AccessCurveData(E)); + TPM_RC retVal = TPM_RC_SUCCESS; + INT32 tries = 10; + BOOL OK = FALSE; + // + pAssert(digest != NULL); + // The algorithm as described in "Suite B Implementer's Guide to FIPS + // 186-3(ECDSA)" + // 1. Use one of the routines in Appendix A.2 to generate (k, k^-1), a + // per-message secret number and its inverse modulo n. Since n is prime, + // the output will be invalid only if there is a failure in the RBG. + // 2. Compute the elliptic curve point R = [k]G = (xR, yR) using EC scalar + // multiplication (see [Routines]), where G is the base point included in + // the set of domain parameters. + // 3. Compute r = xR mod n. If r = 0, then return to Step 1. 1. + // 4. Use the selected hash function to compute H = Hash(M). + // 5. Convert the bit string H to an integer e as described in Appendix B.2. + // 6. Compute s = (k^-1 * (e + d * r)) mod q. If s = 0, return to Step 1.2. + // 7. Return (r, s). + // In the code below, q is n (that it, the order of the curve is p) + + do // This implements the loop at step 6. If s is zero, start over. + { + for(; tries > 0; tries--) + { + // Step 1 and 2 -- generate an ephemeral key and the modular inverse + // of the private key. + if(!BnEccGenerateKeyPair(bnK, ecR, E, rand)) + continue; + // x coordinate is mod p. Make it mod q + BnMod(ecR->x, order); + // Make sure that it is not zero; + if(BnEqualZero(ecR->x)) + continue; + // write the modular reduced version of r as part of the signature + BnCopy(bnR, ecR->x); + // Make sure that a modular inverse exists and try again if not + OK = (BnModInverse(bnIk, bnK, order)); + if(OK) + break; + } + if(!OK) + goto Exit; + + EcdsaDigest(bnE, digest, order); + + // now have inverse of K (bnIk), e (bnE), r (bnR), d (bnD) and + // CurveGetOrder(E) + // Compute s = k^-1 (e + r*d)(mod q) + // first do s = r*d mod q + BnModMult(bnS, bnR, bnD, order); + // s = e + s = e + r * d + BnAdd(bnS, bnE, bnS); + // s = k^(-1)s (mod n) = k^(-1)(e + r * d)(mod n) + BnModMult(bnS, bnIk, bnS, order); + + // If S is zero, try again + } while(BnEqualZero(bnS)); +Exit: + return retVal; +} + +# if ALG_ECDAA + +//*** BnSignEcdaa() +// +// This function performs 's' = 'r' + 'T' * 'd' mod 'q' where +// 1) 'r' is a random, or pseudo-random value created in the commit phase +// 2) 'nonceK' is a TPM-generated, random value 0 < 'nonceK' < 'n' +// 3) 'T' is mod 'q' of "Hash"('nonceK' || 'digest'), and +// 4) 'd' is a private key. +// +// The signature is the tuple ('nonceK', 's') +// +// Regrettably, the parameters in this function kind of collide with the parameter +// names used in ECSCHNORR making for a lot of confusion. +// Return Type: TPM_RC +// TPM_RC_SCHEME unsupported hash algorithm +// TPM_RC_NO_RESULT cannot get values from random number generator +static TPM_RC BnSignEcdaa( + TPM2B_ECC_PARAMETER* nonceK, // OUT: 'nonce' component of the signature + bigNum bnS, // OUT: 's' component of the signature + bigCurve E, // IN: the curve used in signing + bigNum bnD, // IN: the private key + const TPM2B_DIGEST* digest, // IN: the value to sign (mod 'q') + TPMT_ECC_SCHEME* scheme, // IN: signing scheme (contains the + // commit count value). + OBJECT* eccKey, // IN: The signing key + RAND_STATE* rand // IN: a random number state +) +{ + TPM_RC retVal; + TPM2B_ECC_PARAMETER r; + HASH_STATE state; + TPM2B_DIGEST T; + BN_MAX(bnT); + // + NOT_REFERENCED(rand); + if(!CryptGenerateR(&r, + &scheme->details.ecdaa.count, + eccKey->publicArea.parameters.eccDetail.curveID, + &eccKey->name)) + retVal = TPM_RC_VALUE; + else + { + // This allocation is here because 'r' doesn't have a value until + // CrypGenerateR() is done. + ECC_INITIALIZED(bnR, &r); + do + { + // generate nonceK such that 0 < nonceK < n + // use bnT as a temp. + if(!BnEccGetPrivate(bnT, AccessCurveData(E), rand)) + { + retVal = TPM_RC_NO_RESULT; + break; + } + BnTo2B(bnT, &nonceK->b, 0); + + T.t.size = CryptHashStart(&state, scheme->details.ecdaa.hashAlg); + if(T.t.size == 0) + { + retVal = TPM_RC_SCHEME; + } + else + { + CryptDigestUpdate2B(&state, &nonceK->b); + CryptDigestUpdate2B(&state, &digest->b); + CryptHashEnd2B(&state, &T.b); + BnFrom2B(bnT, &T.b); + // Watch out for the name collisions in this call!! + retVal = BnSchnorrSign(bnS, bnR, bnT, bnD, AccessCurveData(E)->order); + } + } while(retVal == TPM_RC_NO_RESULT); + // Because the rule is that internal state is not modified if the command + // fails, only end the commit if the command succeeds. + // NOTE that if the result of the Schnorr computation was zero + // it will probably not be worthwhile to run the same command again because + // the result will still be zero. This means that the Commit command will + // need to be run again to get a new commit value for the signature. + if(retVal == TPM_RC_SUCCESS) + CryptEndCommit(scheme->details.ecdaa.count); + } + return retVal; +} +# endif // ALG_ECDAA + +# if ALG_ECSCHNORR + +//*** SchnorrReduce() +// Function to reduce a hash result if it's magnitude is too large. The size of +// 'number' is set so that it has no more bytes of significance than 'reference' +// value. If the resulting number can have more bits of significance than +// 'reference'. +static void SchnorrReduce(TPM2B* number, // IN/OUT: Value to reduce + bigConst reference // IN: the reference value +) +{ + UINT16 maxBytes = (UINT16)BITS_TO_BYTES(BnSizeInBits(reference)); + if(number->size > maxBytes) + number->size = maxBytes; +} + +//*** SchnorrEcc() +// This function is used to perform a modified Schnorr signature. +// +// This function will generate a random value 'k' and compute +// a) ('xR', 'yR') = ['k']'G' +// b) 'r' = "Hash"('xR' || 'P')(mod 'q') +// c) 'rT' = truncated 'r' +// d) 's'= 'k' + 'rT' * 'ds' (mod 'q') +// e) return the tuple 'rT', 's' +// +// Return Type: TPM_RC +// TPM_RC_NO_RESULT failure in the Schnorr sign process +// TPM_RC_SCHEME hashAlg can't produce zero-length digest +static TPM_RC BnSignEcSchnorr( + bigNum bnR, // OUT: 'r' component of the signature + bigNum bnS, // OUT: 's' component of the signature + bigCurve E, // IN: the curve used in signing + bigNum bnD, // IN: the signing key + const TPM2B_DIGEST* digest, // IN: the digest to sign + TPM_ALG_ID hashAlg, // IN: signing scheme (contains a hash) + RAND_STATE* rand // IN: non-NULL when testing +) +{ + HASH_STATE hashState; + UINT16 digestSize = CryptHashGetDigestSize(hashAlg); + TPM2B_TYPE(T, MAX(MAX_DIGEST_SIZE, MAX_ECC_KEY_BYTES)); + TPM2B_T T2b; + TPM2B* e = &T2b.b; + TPM_RC retVal = TPM_RC_NO_RESULT; + const ECC_CURVE_DATA* C; + bigConst order; + bigConst prime; + ECC_NUM(bnK); + POINT(ecR); + // + // Parameter checks + if(E == NULL) + ERROR_RETURN(TPM_RC_VALUE); + C = AccessCurveData(E); + order = CurveGetOrder(C); + prime = CurveGetOrder(C); + + // If the digest does not produce a hash, then null the signature and return + // a failure. + if(digestSize == 0) + { + BnSetWord(bnR, 0); + BnSetWord(bnS, 0); + ERROR_RETURN(TPM_RC_SCHEME); + } + do + { + // Generate a random key pair + if(!BnEccGenerateKeyPair(bnK, ecR, E, rand)) + break; + // Convert R.x to a string + BnTo2B(ecR->x, e, (NUMBYTES)BITS_TO_BYTES(BnSizeInBits(prime))); + + // f) compute r = Hash(e || P) (mod n) + CryptHashStart(&hashState, hashAlg); + CryptDigestUpdate2B(&hashState, e); + CryptDigestUpdate2B(&hashState, &digest->b); + e->size = CryptHashEnd(&hashState, digestSize, e->buffer); + // Reduce the hash size if it is larger than the curve order + SchnorrReduce(e, order); + // Convert hash to number + BnFrom2B(bnR, e); + // Do the Schnorr computation + retVal = BnSchnorrSign(bnS, bnK, bnR, bnD, CurveGetOrder(C)); + } while(retVal == TPM_RC_NO_RESULT); +Exit: + return retVal; +} + +# endif // ALG_ECSCHNORR + +# if ALG_SM2 +# ifdef _SM2_SIGN_DEBUG + +//*** BnHexEqual() +// This function compares a bignum value to a hex string. +// Return Type: BOOL +// TRUE(1) values equal +// FALSE(0) values not equal +static BOOL BnHexEqual(bigNum bn, //IN: big number value + const char* c //IN: character string number +) +{ + ECC_NUM(bnC); + BnFromHex(bnC, c); + return (BnUnsignedCmp(bn, bnC) == 0); +} +# endif // _SM2_SIGN_DEBUG + +//*** BnSignEcSm2() +// This function signs a digest using the method defined in SM2 Part 2. The method +// in the standard will add a header to the message to be signed that is a hash of +// the values that define the key. This then hashed with the message to produce a +// digest ('e'). This function signs 'e'. +// Return Type: TPM_RC +// TPM_RC_VALUE bad curve +static TPM_RC BnSignEcSm2(bigNum bnR, // OUT: 'r' component of the signature + bigNum bnS, // OUT: 's' component of the signature + bigCurve E, // IN: the curve used in signing + bigNum bnD, // IN: the private key + const TPM2B_DIGEST* digest, // IN: the digest to sign + RAND_STATE* rand // IN: random number generator (mostly for + // debug) +) +{ + BN_MAX_INITIALIZED(bnE, digest); // Don't know how big digest might be + ECC_NUM(bnN); + ECC_NUM(bnK); + ECC_NUM(bnT); // temp + POINT(Q1); + bigConst order = (E != NULL) ? CurveGetOrder(AccessCurveData(E)) : NULL; +// +# ifdef _SM2_SIGN_DEBUG + BnFromHex(bnE, + "B524F552CD82B8B028476E005C377FB1" + "9A87E6FC682D48BB5D42E3D9B9EFFE76"); + BnFromHex(bnD, + "128B2FA8BD433C6C068C8D803DFF7979" + "2A519A55171B1B650C23661D15897263"); +# endif + // A3: Use random number generator to generate random number 1 <= k <= n-1; + // NOTE: Ax: numbers are from the SM2 standard +loop: +{ + // Get a random number 0 < k < n + BnGenerateRandomInRange(bnK, order, rand); +# ifdef _SM2_SIGN_DEBUG + BnFromHex(bnK, + "6CB28D99385C175C94F94E934817663F" + "C176D925DD72B727260DBAAE1FB2F96F"); +# endif + // A4: Figure out the point of elliptic curve (x1, y1)=[k]G, and according + // to details specified in 4.2.7 in Part 1 of this document, transform the + // data type of x1 into an integer; + if(!BnEccModMult(Q1, NULL, bnK, E)) + goto loop; + // A5: Figure out 'r' = ('e' + 'x1') mod 'n', + BnAdd(bnR, bnE, Q1->x); + BnMod(bnR, order); +# ifdef _SM2_SIGN_DEBUG + pAssert(BnHexEqual(bnR, + "40F1EC59F793D9F49E09DCEF49130D41" + "94F79FB1EED2CAA55BACDB49C4E755D1")); +# endif + // if r=0 or r+k=n, return to A3; + if(BnEqualZero(bnR)) + goto loop; + BnAdd(bnT, bnK, bnR); + if(BnUnsignedCmp(bnT, bnN) == 0) + goto loop; + // A6: Figure out s = ((1 + dA)^-1 (k - r dA)) mod n, + // if s=0, return to A3; + // compute t = (1+dA)^-1 + BnAddWord(bnT, bnD, 1); + BnModInverse(bnT, bnT, order); +# ifdef _SM2_SIGN_DEBUG + pAssert(BnHexEqual(bnT, + "79BFCF3052C80DA7B939E0C6914A18CB" + "B2D96D8555256E83122743A7D4F5F956")); +# endif + // compute s = t * (k - r * dA) mod n + BnModMult(bnS, bnR, bnD, order); + // k - r * dA mod n = k + n - ((r * dA) mod n) + BnSub(bnS, order, bnS); + BnAdd(bnS, bnK, bnS); + BnModMult(bnS, bnS, bnT, order); +# ifdef _SM2_SIGN_DEBUG + pAssert(BnHexEqual(bnS, + "6FC6DAC32C5D5CF10C77DFB20F7C2EB6" + "67A457872FB09EC56327A67EC7DEEBE7")); +# endif + if(BnEqualZero(bnS)) + goto loop; +} +// A7: According to details specified in 4.2.1 in Part 1 of this document, +// transform the data type of r, s into bit strings, signature of message M +// is (r, s). +// This is handled by the common return code +# ifdef _SM2_SIGN_DEBUG + pAssert(BnHexEqual(bnR, + "40F1EC59F793D9F49E09DCEF49130D41" + "94F79FB1EED2CAA55BACDB49C4E755D1")); + pAssert(BnHexEqual(bnS, + "6FC6DAC32C5D5CF10C77DFB20F7C2EB6" + "67A457872FB09EC56327A67EC7DEEBE7")); +# endif + return TPM_RC_SUCCESS; +} +# endif // ALG_SM2 + +//*** CryptEccSign() +// This function is the dispatch function for the various ECC-based +// signing schemes. +// There is a bit of ugliness to the parameter passing. In order to test this, +// we sometime would like to use a deterministic RNG so that we can get the same +// signatures during testing. The easiest way to do this for most schemes is to +// pass in a deterministic RNG and let it return canned values during testing. +// There is a competing need for a canned parameter to use in ECDAA. To accommodate +// both needs with minimal fuss, a special type of RAND_STATE is defined to carry +// the address of the commit value. The setup and handling of this is not very +// different for the caller than what was in previous versions of the code. +// Return Type: TPM_RC +// TPM_RC_SCHEME 'scheme' is not supported +LIB_EXPORT TPM_RC CryptEccSign(TPMT_SIGNATURE* signature, // OUT: signature + OBJECT* signKey, // IN: ECC key to sign the hash + const TPM2B_DIGEST* digest, // IN: digest to sign + TPMT_ECC_SCHEME* scheme, // IN: signing scheme + RAND_STATE* rand) +{ + CURVE_INITIALIZED(E, signKey->publicArea.parameters.eccDetail.curveID); + ECC_INITIALIZED(bnD, &signKey->sensitive.sensitive.ecc.b); + ECC_NUM(bnR); + ECC_NUM(bnS); + const ECC_CURVE_DATA* C; + TPM_RC retVal = TPM_RC_SCHEME; + // + NOT_REFERENCED(scheme); + if(E == NULL) + ERROR_RETURN(TPM_RC_VALUE); + C = AccessCurveData(E); + signature->signature.ecdaa.signatureR.t.size = + sizeof(signature->signature.ecdaa.signatureR.t.buffer); + signature->signature.ecdaa.signatureS.t.size = + sizeof(signature->signature.ecdaa.signatureS.t.buffer); + TEST(signature->sigAlg); + switch(signature->sigAlg) + { + case TPM_ALG_ECDSA: + retVal = BnSignEcdsa(bnR, bnS, E, bnD, digest, rand); + break; +# if ALG_ECDAA + case TPM_ALG_ECDAA: + retVal = BnSignEcdaa(&signature->signature.ecdaa.signatureR, + bnS, + E, + bnD, + digest, + scheme, + signKey, + rand); + bnR = NULL; + break; +# endif +# if ALG_ECSCHNORR + case TPM_ALG_ECSCHNORR: + retVal = BnSignEcSchnorr( + bnR, bnS, E, bnD, digest, signature->signature.ecschnorr.hash, rand); + break; +# endif +# if ALG_SM2 + case TPM_ALG_SM2: + retVal = BnSignEcSm2(bnR, bnS, E, bnD, digest, rand); + break; +# endif + default: + break; + } + // If signature generation worked, convert the results. + if(retVal == TPM_RC_SUCCESS) + { + NUMBYTES orderBytes = (NUMBYTES)BITS_TO_BYTES(BnSizeInBits(CurveGetOrder(C))); + if(bnR != NULL) + BnTo2B(bnR, &signature->signature.ecdaa.signatureR.b, orderBytes); + if(bnS != NULL) + BnTo2B(bnS, &signature->signature.ecdaa.signatureS.b, orderBytes); + } +Exit: + CURVE_FREE(E); + return retVal; +} + +//********************* Signature Validation ******************** + +# if ALG_ECDSA + +//*** BnValidateSignatureEcdsa() +// This function validates an ECDSA signature. rIn and sIn should have been checked +// to make sure that they are in the range 0 < 'v' < 'n' +// Return Type: TPM_RC +// TPM_RC_SIGNATURE signature not valid +TPM_RC +BnValidateSignatureEcdsa(bigNum bnR, // IN: 'r' component of the signature + bigNum bnS, // IN: 's' component of the signature + bigCurve E, // IN: the curve used in the signature + // process + bn_point_t* ecQ, // IN: the public point of the key + const TPM2B_DIGEST* digest // IN: the digest that was signed +) +{ + // Make sure that the allocation for the digest is big enough for a maximum + // digest + BN_VAR(bnE, MAX(MAX_ECC_KEY_BYTES, MAX_DIGEST_SIZE) * 8); + POINT(ecR); + ECC_NUM(bnU1); + ECC_NUM(bnU2); + ECC_NUM(bnW); + bigConst order = CurveGetOrder(AccessCurveData(E)); + TPM_RC retVal = TPM_RC_SIGNATURE; + // + // Get adjusted digest + EcdsaDigest(bnE, digest, order); + // 1. If r and s are not both integers in the interval [1, n - 1], output + // INVALID. + // bnR and bnS were validated by the caller + // 2. Use the selected hash function to compute H0 = Hash(M0). + // This is an input parameter + // 3. Convert the bit string H0 to an integer e as described in Appendix B.2. + // Done at entry + // 4. Compute w = (s')^-1 mod n, using the routine in Appendix B.1. + if(!BnModInverse(bnW, bnS, order)) + goto Exit; + // 5. Compute u1 = (e' * w) mod n, and compute u2 = (r' * w) mod n. + BnModMult(bnU1, bnE, bnW, order); + BnModMult(bnU2, bnR, bnW, order); + // 6. Compute the elliptic curve point R = (xR, yR) = u1G+u2Q, using EC + // scalar multiplication and EC addition (see [Routines]). If R is equal to + // the point at infinity O, output INVALID. + if(BnPointMult(ecR, CurveGetG(AccessCurveData(E)), bnU1, ecQ, bnU2, E) + != TPM_RC_SUCCESS) + goto Exit; + // 7. Compute v = Rx mod n. + BnMod(ecR->x, order); + // 8. Compare v and r0. If v = r0, output VALID; otherwise, output INVALID + if(BnUnsignedCmp(ecR->x, bnR) != 0) + goto Exit; + + retVal = TPM_RC_SUCCESS; +Exit: + return retVal; +} + +# endif // ALG_ECDSA + +# if ALG_SM2 + +//*** BnValidateSignatureEcSm2() +// This function is used to validate an SM2 signature. +// Return Type: TPM_RC +// TPM_RC_SIGNATURE signature not valid +static TPM_RC BnValidateSignatureEcSm2( + bigNum bnR, // IN: 'r' component of the signature + bigNum bnS, // IN: 's' component of the signature + bigCurve E, // IN: the curve used in the signature + // process + bigPoint ecQ, // IN: the public point of the key + const TPM2B_DIGEST* digest // IN: the digest that was signed +) +{ + POINT(P); + ECC_NUM(bnRp); + ECC_NUM(bnT); + BN_MAX_INITIALIZED(bnE, digest); + BOOL OK; + bigConst order = CurveGetOrder(AccessCurveData(E)); + +# ifdef _SM2_SIGN_DEBUG + // Make sure that the input signature is the test signature + pAssert(BnHexEqual(bnR, + "40F1EC59F793D9F49E09DCEF49130D41" + "94F79FB1EED2CAA55BACDB49C4E755D1")); + pAssert(BnHexEqual(bnS, + "6FC6DAC32C5D5CF10C77DFB20F7C2EB6" + "67A457872FB09EC56327A67EC7DEEBE7")); +# endif + // b) compute t := (r + s) mod n + BnAdd(bnT, bnR, bnS); + BnMod(bnT, order); +# ifdef _SM2_SIGN_DEBUG + pAssert(BnHexEqual(bnT, + "2B75F07ED7ECE7CCC1C8986B991F441A" + "D324D6D619FE06DD63ED32E0C997C801")); +# endif + // c) verify that t > 0 + OK = !BnEqualZero(bnT); + if(!OK) + // set T to a value that should allow rest of the computations to run + // without trouble + BnCopy(bnT, bnS); + // d) compute (x, y) := [s]G + [t]Q + OK = BnEccModMult2(P, NULL, bnS, ecQ, bnT, E); +# ifdef _SM2_SIGN_DEBUG + pAssert(OK + && BnHexEqual(P->x, + "110FCDA57615705D5E7B9324AC4B856D" + "23E6D9188B2AE47759514657CE25D112")); +# endif + // e) compute r' := (e + x) mod n (the x coordinate is in bnT) + OK = OK && BnAdd(bnRp, bnE, P->x); + OK = OK && BnMod(bnRp, order); + + // f) verify that r' = r + OK = OK && (BnUnsignedCmp(bnR, bnRp) == 0); + + if(!OK) + return TPM_RC_SIGNATURE; + else + return TPM_RC_SUCCESS; +} + +# endif // ALG_SM2 + +# if ALG_ECSCHNORR + +//*** BnValidateSignatureEcSchnorr() +// This function is used to validate an EC Schnorr signature. +// Return Type: TPM_RC +// TPM_RC_SIGNATURE signature not valid +static TPM_RC BnValidateSignatureEcSchnorr( + bigNum bnR, // IN: 'r' component of the signature + bigNum bnS, // IN: 's' component of the signature + TPM_ALG_ID hashAlg, // IN: hash algorithm of the signature + bigCurve E, // IN: the curve used in the signature + // process + bigPoint ecQ, // IN: the public point of the key + const TPM2B_DIGEST* digest // IN: the digest that was signed +) +{ + BN_MAX(bnRn); + POINT(ecE); + BN_MAX(bnEx); + const ECC_CURVE_DATA* C = AccessCurveData(E); + bigConst order = CurveGetOrder(C); + UINT16 digestSize = CryptHashGetDigestSize(hashAlg); + HASH_STATE hashState; + TPM2B_TYPE(BUFFER, MAX(MAX_ECC_PARAMETER_BYTES, MAX_DIGEST_SIZE)); + TPM2B_BUFFER Ex2 = {{sizeof(Ex2.t.buffer), {0}}}; + BOOL OK; + // + // E = [s]G - [r]Q + BnMod(bnR, order); + // Make -r = n - r + BnSub(bnRn, order, bnR); + // E = [s]G + [-r]Q + OK = BnPointMult(ecE, CurveGetG(C), bnS, ecQ, bnRn, E) == TPM_RC_SUCCESS; + // // reduce the x portion of E mod q + // OK = OK && BnMod(ecE->x, order); + // Convert to byte string + OK = OK && BnTo2B(ecE->x, &Ex2.b, (NUMBYTES)(BITS_TO_BYTES(BnSizeInBits(order)))); + if(OK) + { + // Ex = h(pE.x || digest) + CryptHashStart(&hashState, hashAlg); + CryptDigestUpdate(&hashState, Ex2.t.size, Ex2.t.buffer); + CryptDigestUpdate(&hashState, digest->t.size, digest->t.buffer); + Ex2.t.size = CryptHashEnd(&hashState, digestSize, Ex2.t.buffer); + SchnorrReduce(&Ex2.b, order); + BnFrom2B(bnEx, &Ex2.b); + // see if Ex matches R + OK = BnUnsignedCmp(bnEx, bnR) == 0; + } + return (OK) ? TPM_RC_SUCCESS : TPM_RC_SIGNATURE; +} +# endif // ALG_ECSCHNORR + +//*** CryptEccValidateSignature() +// This function validates an EcDsa or EcSchnorr signature. +// The point 'Qin' needs to have been validated to be on the curve of 'curveId'. +// Return Type: TPM_RC +// TPM_RC_SIGNATURE not a valid signature +LIB_EXPORT TPM_RC CryptEccValidateSignature( + TPMT_SIGNATURE* signature, // IN: signature to be verified + OBJECT* signKey, // IN: ECC key signed the hash + const TPM2B_DIGEST* digest // IN: digest that was signed +) +{ + CURVE_INITIALIZED(E, signKey->publicArea.parameters.eccDetail.curveID); + ECC_NUM(bnR); + ECC_NUM(bnS); + POINT_INITIALIZED(ecQ, &signKey->publicArea.unique.ecc); + bigConst order; + TPM_RC retVal; + + if(E == NULL) + ERROR_RETURN(TPM_RC_VALUE); + + order = CurveGetOrder(AccessCurveData(E)); + + // // Make sure that the scheme is valid + switch(signature->sigAlg) + { + case TPM_ALG_ECDSA: +# if ALG_ECSCHNORR + case TPM_ALG_ECSCHNORR: +# endif +# if ALG_SM2 + case TPM_ALG_SM2: +# endif + break; + default: + ERROR_RETURN(TPM_RC_SCHEME); + break; + } + // Can convert r and s after determining that the scheme is an ECC scheme. If + // this conversion doesn't work, it means that the unmarshaling code for + // an ECC signature is broken. + BnFrom2B(bnR, &signature->signature.ecdsa.signatureR.b); + BnFrom2B(bnS, &signature->signature.ecdsa.signatureS.b); + + // r and s have to be greater than 0 but less than the curve order + if(BnEqualZero(bnR) || BnEqualZero(bnS)) + ERROR_RETURN(TPM_RC_SIGNATURE); + if((BnUnsignedCmp(bnS, order) >= 0) || (BnUnsignedCmp(bnR, order) >= 0)) + ERROR_RETURN(TPM_RC_SIGNATURE); + + switch(signature->sigAlg) + { + case TPM_ALG_ECDSA: + retVal = BnValidateSignatureEcdsa(bnR, bnS, E, ecQ, digest); + break; + +# if ALG_ECSCHNORR + case TPM_ALG_ECSCHNORR: + retVal = BnValidateSignatureEcSchnorr( + bnR, bnS, signature->signature.any.hashAlg, E, ecQ, digest); + break; +# endif +# if ALG_SM2 + case TPM_ALG_SM2: + retVal = BnValidateSignatureEcSm2(bnR, bnS, E, ecQ, digest); + break; +# endif + default: + FAIL(FATAL_ERROR_INTERNAL); + } +Exit: + CURVE_FREE(E); + return retVal; +} + +//***CryptEccCommitCompute() +// This function performs the point multiply operations required by TPM2_Commit. +// +// If 'B' or 'M' is provided, they must be on the curve defined by 'curveId'. This +// routine does not check that they are on the curve and results are unpredictable +// if they are not. +// +// It is a fatal error if 'r' is NULL. If 'B' is not NULL, then it is a +// fatal error if 'd' is NULL or if 'K' and 'L' are both NULL. +// If 'M' is not NULL, then it is a fatal error if 'E' is NULL. +// +// Return Type: TPM_RC +// TPM_RC_NO_RESULT if 'K', 'L' or 'E' was computed to be the point +// at infinity +// TPM_RC_CANCELED a cancel indication was asserted during this +// function +LIB_EXPORT TPM_RC CryptEccCommitCompute( + TPMS_ECC_POINT* K, // OUT: [d]B or [r]Q + TPMS_ECC_POINT* L, // OUT: [r]B + TPMS_ECC_POINT* E, // OUT: [r]M + TPM_ECC_CURVE curveId, // IN: the curve for the computations + TPMS_ECC_POINT* M, // IN: M (optional) + TPMS_ECC_POINT* B, // IN: B (optional) + TPM2B_ECC_PARAMETER* d, // IN: d (optional) + TPM2B_ECC_PARAMETER* r // IN: the computed r value (required) +) +{ + CURVE_INITIALIZED(curve, curveId); // Normally initialize E as the curve, but + // E means something else in this function + ECC_INITIALIZED(bnR, r); + TPM_RC retVal = TPM_RC_SUCCESS; + // + // Validate that the required parameters are provided. + // Note: E has to be provided if computing E := [r]Q or E := [r]M. Will do + // E := [r]Q if both M and B are NULL. + pAssert(r != NULL && E != NULL); + + // Initialize the output points in case they are not computed + ClearPoint2B(K); + ClearPoint2B(L); + ClearPoint2B(E); + + // Sizes of the r parameter may not be zero + pAssert(r->t.size > 0); + + // If B is provided, compute K=[d]B and L=[r]B + if(B != NULL) + { + ECC_INITIALIZED(bnD, d); + POINT_INITIALIZED(pB, B); + POINT(pK); + POINT(pL); + // + pAssert(d != NULL && K != NULL && L != NULL); + + if(!BnIsOnCurve(pB, AccessCurveData(curve))) + ERROR_RETURN(TPM_RC_VALUE); + // do the math for K = [d]B + if((retVal = BnPointMult(pK, pB, bnD, NULL, NULL, curve)) != TPM_RC_SUCCESS) + goto Exit; + // Convert BN K to TPM2B K + BnPointTo2B(K, pK, curve); + // compute L= [r]B after checking for cancel + if(_plat__IsCanceled()) + ERROR_RETURN(TPM_RC_CANCELED); + // compute L = [r]B + if(!BnIsValidPrivateEcc(bnR, curve)) + ERROR_RETURN(TPM_RC_VALUE); + if((retVal = BnPointMult(pL, pB, bnR, NULL, NULL, curve)) != TPM_RC_SUCCESS) + goto Exit; + // Convert BN L to TPM2B L + BnPointTo2B(L, pL, curve); + } + if((M != NULL) || (B == NULL)) + { + POINT_INITIALIZED(pM, M); + POINT(pE); + // + // Make sure that a place was provided for the result + pAssert(E != NULL); + + // if this is the third point multiply, check for cancel first + if((B != NULL) && _plat__IsCanceled()) + ERROR_RETURN(TPM_RC_CANCELED); + + // If M provided, then pM will not be NULL and will compute E = [r]M. + // However, if M was not provided, then pM will be NULL and E = [r]G + // will be computed + if((retVal = BnPointMult(pE, pM, bnR, NULL, NULL, curve)) != TPM_RC_SUCCESS) + goto Exit; + // Convert E to 2B format + BnPointTo2B(E, pE, curve); + } +Exit: + CURVE_FREE(curve); + return retVal; +} + +#endif // ALG_ECC \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptHash.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptHash.c new file mode 100644 index 0000000..e713785 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptHash.c @@ -0,0 +1,857 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Description +// +// This file contains implementation of cryptographic functions for hashing. +// +//** Includes, Defines, and Types + +#define _CRYPT_HASH_C_ +#include "Tpm.h" +#include "CryptHash_fp.h" +#include "CryptHash.h" +#include "OIDs.h" + +// Instance each of the hash descriptors based on the implemented algorithms +FOR_EACH_HASH(HASH_DEF_TEMPLATE) +// Instance a 'null' def. +HASH_DEF NULL_Def = {{0}}; + +// Create a table of pointers to the defined hash definitions +#define HASH_DEF_ENTRY(HASH, Hash) &Hash##_Def, +PHASH_DEF HashDefArray[] = { + // for each implemented HASH, expands to: &HASH_Def, + FOR_EACH_HASH(HASH_DEF_ENTRY) & NULL_Def}; +#undef HASH_DEF_ENTRY + +//** Obligatory Initialization Functions + +//*** CryptHashInit() +// This function is called by _TPM_Init do perform the initialization operations for +// the library. +BOOL CryptHashInit(void) +{ + LibHashInit(); + return TRUE; +} + +//*** CryptHashStartup() +// This function is called by TPM2_Startup(). It checks that the size of the +// HashDefArray is consistent with the HASH_COUNT. +BOOL CryptHashStartup(void) +{ + int i = sizeof(HashDefArray) / sizeof(PHASH_DEF) - 1; + return (i == HASH_COUNT); +} + +//** Hash Information Access Functions +//*** Introduction +// These functions provide access to the hash algorithm description information. + +//*** CryptGetHashDef() +// This function accesses the hash descriptor associated with a hash a +// algorithm. The function returns a pointer to a 'null' descriptor if hashAlg is +// TPM_ALG_NULL or not a defined algorithm. +PHASH_DEF +CryptGetHashDef(TPM_ALG_ID hashAlg) +{ +#define GET_DEF(HASH, Hash) \ + case ALG_##HASH##_VALUE: \ + return &Hash##_Def; + switch(hashAlg) + { + FOR_EACH_HASH(GET_DEF) + default: + return &NULL_Def; + } +#undef GET_DEF +} + +//*** CryptHashIsValidAlg() +// This function tests to see if an algorithm ID is a valid hash algorithm. If +// flag is true, then TPM_ALG_NULL is a valid hash. +// Return Type: BOOL +// TRUE(1) hashAlg is a valid, implemented hash on this TPM +// FALSE(0) hashAlg is not valid for this TPM +BOOL CryptHashIsValidAlg(TPM_ALG_ID hashAlg, // IN: the algorithm to check + BOOL flag // IN: TRUE if TPM_ALG_NULL is to be treated + // as a valid hash +) +{ + if(hashAlg == TPM_ALG_NULL) + return flag; + return CryptGetHashDef(hashAlg) != &NULL_Def; +} + +//*** CryptHashGetAlgByIndex() +// This function is used to iterate through the hashes. TPM_ALG_NULL +// is returned for all indexes that are not valid hashes. +// If the TPM implements 3 hashes, then an 'index' value of 0 will +// return the first implemented hash and an 'index' of 2 will return the +// last. All other index values will return TPM_ALG_NULL. +// +// Return Type: TPM_ALG_ID +// TPM_ALG_xxx a hash algorithm +// TPM_ALG_NULL this can be used as a stop value +LIB_EXPORT TPM_ALG_ID CryptHashGetAlgByIndex(UINT32 index // IN: the index +) +{ + TPM_ALG_ID hashAlg; + if(index >= HASH_COUNT) + hashAlg = TPM_ALG_NULL; + else + hashAlg = HashDefArray[index]->hashAlg; + return hashAlg; +} + +//*** CryptHashGetDigestSize() +// Returns the size of the digest produced by the hash. If 'hashAlg' is not a hash +// algorithm, the TPM will FAIL. +// Return Type: UINT16 +// 0 TPM_ALG_NULL +// > 0 the digest size +// +LIB_EXPORT UINT16 CryptHashGetDigestSize( + TPM_ALG_ID hashAlg // IN: hash algorithm to look up +) +{ + return CryptGetHashDef(hashAlg)->digestSize; +} + +//*** CryptHashGetBlockSize() +// Returns the size of the block used by the hash. If 'hashAlg' is not a hash +// algorithm, the TPM will FAIL. +// Return Type: UINT16 +// 0 TPM_ALG_NULL +// > 0 the digest size +// +LIB_EXPORT UINT16 CryptHashGetBlockSize( + TPM_ALG_ID hashAlg // IN: hash algorithm to look up +) +{ + return CryptGetHashDef(hashAlg)->blockSize; +} + +//*** CryptHashGetOid() +// This function returns a pointer to DER=encoded OID for a hash algorithm. All OIDs +// are full OID values including the Tag (0x06) and length byte. +LIB_EXPORT const BYTE* CryptHashGetOid(TPM_ALG_ID hashAlg) +{ + return CryptGetHashDef(hashAlg)->OID; +} + +//*** CryptHashGetContextAlg() +// This function returns the hash algorithm associated with a hash context. +TPM_ALG_ID +CryptHashGetContextAlg(PHASH_STATE state // IN: the context to check +) +{ + return state->hashAlg; +} + +//** State Import and Export + +//*** CryptHashCopyState +// This function is used to clone a HASH_STATE. +LIB_EXPORT void CryptHashCopyState(HASH_STATE* out, // OUT: destination of the state + const HASH_STATE* in // IN: source of the state +) +{ + pAssert(out->type == in->type); + out->hashAlg = in->hashAlg; + out->def = in->def; + if(in->hashAlg != TPM_ALG_NULL) + { + HASH_STATE_COPY(out, in); + } + if(in->type == HASH_STATE_HMAC) + { + const HMAC_STATE* hIn = (HMAC_STATE*)in; + HMAC_STATE* hOut = (HMAC_STATE*)out; + hOut->hmacKey = hIn->hmacKey; + } + return; +} + +//*** CryptHashExportState() +// This function is used to export a hash or HMAC hash state. This function +// would be called when preparing to context save a sequence object. +void CryptHashExportState( + PCHASH_STATE internalFmt, // IN: the hash state formatted for use by + // library + PEXPORT_HASH_STATE externalFmt // OUT: the exported hash state +) +{ + BYTE* outBuf = (BYTE*)externalFmt; + // + cAssert(sizeof(HASH_STATE) <= sizeof(EXPORT_HASH_STATE)); + // the following #define is used to move data from an aligned internal data + // structure to a byte buffer (external format data. +#define CopyToOffset(value) \ + memcpy(&outBuf[offsetof(HASH_STATE, value)], \ + &internalFmt->value, \ + sizeof(internalFmt->value)) + // Copy the hashAlg + CopyToOffset(hashAlg); + CopyToOffset(type); +#ifdef HASH_STATE_SMAC + if(internalFmt->type == HASH_STATE_SMAC) + { + memcpy(outBuf, internalFmt, sizeof(HASH_STATE)); + return; + } +#endif + if(internalFmt->type == HASH_STATE_HMAC) + { + HMAC_STATE* from = (HMAC_STATE*)internalFmt; + memcpy(&outBuf[offsetof(HMAC_STATE, hmacKey)], + &from->hmacKey, + sizeof(from->hmacKey)); + } + if(internalFmt->hashAlg != TPM_ALG_NULL) + HASH_STATE_EXPORT(externalFmt, internalFmt); +} + +//*** CryptHashImportState() +// This function is used to import the hash state. This function +// would be called to import a hash state when the context of a sequence object +// was being loaded. +void CryptHashImportState( + PHASH_STATE internalFmt, // OUT: the hash state formatted for use by + // the library + PCEXPORT_HASH_STATE externalFmt // IN: the exported hash state +) +{ + BYTE* inBuf = (BYTE*)externalFmt; +// +#define CopyFromOffset(value) \ + memcpy(&internalFmt->value, \ + &inBuf[offsetof(HASH_STATE, value)], \ + sizeof(internalFmt->value)) + + // Copy the hashAlg of the byte-aligned input structure to the structure-aligned + // internal structure. + CopyFromOffset(hashAlg); + CopyFromOffset(type); + if(internalFmt->hashAlg != TPM_ALG_NULL) + { +#ifdef HASH_STATE_SMAC + if(internalFmt->type == HASH_STATE_SMAC) + { + memcpy(internalFmt, inBuf, sizeof(HASH_STATE)); + return; + } +#endif + internalFmt->def = CryptGetHashDef(internalFmt->hashAlg); + HASH_STATE_IMPORT(internalFmt, inBuf); + if(internalFmt->type == HASH_STATE_HMAC) + { + HMAC_STATE* to = (HMAC_STATE*)internalFmt; + memcpy(&to->hmacKey, + &inBuf[offsetof(HMAC_STATE, hmacKey)], + sizeof(to->hmacKey)); + } + } +} + +//** State Modification Functions + +//***HashEnd() +// Local function to complete a hash that uses the hashDef instead of an algorithm +// ID. This function is used to complete the hash and only return a partial digest. +// The return value is the size of the data copied. +static UINT16 HashEnd(PHASH_STATE hashState, // IN: the hash state + UINT32 dOutSize, // IN: the size of receive buffer + PBYTE dOut // OUT: the receive buffer +) +{ + BYTE temp[MAX_DIGEST_SIZE]; + if((hashState->hashAlg == TPM_ALG_NULL) || (hashState->type != HASH_STATE_HASH)) + dOutSize = 0; + if(dOutSize > 0) + { + hashState->def = CryptGetHashDef(hashState->hashAlg); + // Set the final size + dOutSize = MIN(dOutSize, hashState->def->digestSize); + // Complete into the temp buffer and then copy + HASH_END(hashState, temp); + // Don't want any other functions calling the HASH_END method + // directly. +#undef HASH_END + memcpy(dOut, &temp, dOutSize); + } + hashState->type = HASH_STATE_EMPTY; + return (UINT16)dOutSize; +} + +//*** CryptHashStart() +// Functions starts a hash stack +// Start a hash stack and returns the digest size. As a side effect, the +// value of 'stateSize' in hashState is updated to indicate the number of bytes +// of state that were saved. This function calls GetHashServer() and that function +// will put the TPM into failure mode if the hash algorithm is not supported. +// +// This function does not use the sequence parameter. If it is necessary to import +// or export context, this will start the sequence in a local state +// and export the state to the input buffer. Will need to add a flag to the state +// structure to indicate that it needs to be imported before it can be used. +// (BLEH). +// Return Type: UINT16 +// 0 hash is TPM_ALG_NULL +// >0 digest size +LIB_EXPORT UINT16 CryptHashStart( + PHASH_STATE hashState, // OUT: the running hash state + TPM_ALG_ID hashAlg // IN: hash algorithm +) +{ + UINT16 retVal; + + TEST(hashAlg); + + hashState->hashAlg = hashAlg; + if(hashAlg == TPM_ALG_NULL) + { + retVal = 0; + } + else + { + hashState->def = CryptGetHashDef(hashAlg); + HASH_START(hashState); + retVal = hashState->def->digestSize; + } +#undef HASH_START + hashState->type = HASH_STATE_HASH; + return retVal; +} + +//*** CryptDigestUpdate() +// Add data to a hash or HMAC, SMAC stack. +// +void CryptDigestUpdate(PHASH_STATE hashState, // IN: the hash context information + UINT32 dataSize, // IN: the size of data to be added + const BYTE* data // IN: data to be hashed +) +{ + if(hashState->hashAlg != TPM_ALG_NULL) + { + if((hashState->type == HASH_STATE_HASH) + || (hashState->type == HASH_STATE_HMAC)) + HASH_DATA(hashState, dataSize, (BYTE*)data); +#if SMAC_IMPLEMENTED + else if(hashState->type == HASH_STATE_SMAC) + (hashState->state.smac.smacMethods.data)( + &hashState->state.smac.state, dataSize, data); +#endif // SMAC_IMPLEMENTED + else + FAIL(FATAL_ERROR_INTERNAL); + } + return; +} + +//*** CryptHashEnd() +// Complete a hash or HMAC computation. This function will place the smaller of +// 'digestSize' or the size of the digest in 'dOut'. The number of bytes in the +// placed in the buffer is returned. If there is a failure, the returned value +// is <= 0. +// Return Type: UINT16 +// 0 no data returned +// > 0 the number of bytes in the digest or dOutSize, whichever is smaller +LIB_EXPORT UINT16 CryptHashEnd(PHASH_STATE hashState, // IN: the state of hash stack + UINT32 dOutSize, // IN: size of digest buffer + BYTE* dOut // OUT: hash digest +) +{ + pAssert(hashState->type == HASH_STATE_HASH); + return HashEnd(hashState, dOutSize, dOut); +} + +//*** CryptHashBlock() +// Start a hash, hash a single block, update 'digest' and return the size of +// the results. +// +// The 'digestSize' parameter can be smaller than the digest. If so, only the more +// significant bytes are returned. +// Return Type: UINT16 +// >= 0 number of bytes placed in 'dOut' +LIB_EXPORT UINT16 CryptHashBlock(TPM_ALG_ID hashAlg, // IN: The hash algorithm + UINT32 dataSize, // IN: size of buffer to hash + const BYTE* data, // IN: the buffer to hash + UINT32 dOutSize, // IN: size of the digest buffer + BYTE* dOut // OUT: digest buffer +) +{ + HASH_STATE state; + CryptHashStart(&state, hashAlg); + CryptDigestUpdate(&state, dataSize, data); + return HashEnd(&state, dOutSize, dOut); +} + +//*** CryptDigestUpdate2B() +// This function updates a digest (hash or HMAC) with a TPM2B. +// +// This function can be used for both HMAC and hash functions so the +// 'digestState' is void so that either state type can be passed. +LIB_EXPORT void CryptDigestUpdate2B(PHASH_STATE state, // IN: the digest state + const TPM2B* bIn // IN: 2B containing the data +) +{ + // Only compute the digest if a pointer to the 2B is provided. + // In CryptDigestUpdate(), if size is zero or buffer is NULL, then no change + // to the digest occurs. This function should not provide a buffer if bIn is + // not provided. + pAssert(bIn != NULL); + CryptDigestUpdate(state, bIn->size, bIn->buffer); + return; +} + +//*** CryptHashEnd2B() +// This function is the same as CryptCompleteHash() but the digest is +// placed in a TPM2B. This is the most common use and this is provided +// for specification clarity. 'digest.size' should be set to indicate the number of +// bytes to place in the buffer +// Return Type: UINT16 +// >=0 the number of bytes placed in 'digest.buffer' +LIB_EXPORT UINT16 CryptHashEnd2B( + PHASH_STATE state, // IN: the hash state + P2B digest // IN: the size of the buffer Out: requested + // number of bytes +) +{ + return CryptHashEnd(state, digest->size, digest->buffer); +} + +//*** CryptDigestUpdateInt() +// This function is used to include an integer value to a hash stack. The function +// marshals the integer into its canonical form before calling CryptDigestUpdate(). +LIB_EXPORT void CryptDigestUpdateInt( + void* state, // IN: the state of hash stack + UINT32 intSize, // IN: the size of 'intValue' in bytes + UINT64 intValue // IN: integer value to be hashed +) +{ +#if LITTLE_ENDIAN_TPM + intValue = REVERSE_ENDIAN_64(intValue); +#endif + CryptDigestUpdate(state, intSize, &((BYTE*)&intValue)[8 - intSize]); +} + +//** HMAC Functions + +//*** CryptHmacStart() +// This function is used to start an HMAC using a temp +// hash context. The function does the initialization +// of the hash with the HMAC key XOR iPad and updates the +// HMAC key XOR oPad. +// +// The function returns the number of bytes in a digest produced by 'hashAlg'. +// Return Type: UINT16 +// >= 0 number of bytes in digest produced by 'hashAlg' (may be zero) +// +LIB_EXPORT UINT16 CryptHmacStart(PHMAC_STATE state, // IN/OUT: the state buffer + TPM_ALG_ID hashAlg, // IN: the algorithm to use + UINT16 keySize, // IN: the size of the HMAC key + const BYTE* key // IN: the HMAC key +) +{ + PHASH_DEF hashDef; + BYTE* pb; + UINT32 i; + // + hashDef = CryptGetHashDef(hashAlg); + if(hashDef->digestSize != 0) + { + // If the HMAC key is larger than the hash block size, it has to be reduced + // to fit. The reduction is a digest of the hashKey. + if(keySize > hashDef->blockSize) + { + // if the key is too big, reduce it to a digest of itself + state->hmacKey.t.size = CryptHashBlock( + hashAlg, keySize, key, hashDef->digestSize, state->hmacKey.t.buffer); + } + else + { + memcpy(state->hmacKey.t.buffer, key, keySize); + state->hmacKey.t.size = keySize; + } + // XOR the key with iPad (0x36) + pb = state->hmacKey.t.buffer; + for(i = state->hmacKey.t.size; i > 0; i--) + *pb++ ^= 0x36; + + // if the keySize is smaller than a block, fill the rest with 0x36 + for(i = hashDef->blockSize - state->hmacKey.t.size; i > 0; i--) + *pb++ = 0x36; + + // Increase the oPadSize to a full block + state->hmacKey.t.size = hashDef->blockSize; + + // Start a new hash with the HMAC key + // This will go in the caller's state structure and may be a sequence or not + CryptHashStart((PHASH_STATE)state, hashAlg); + CryptDigestUpdate( + (PHASH_STATE)state, state->hmacKey.t.size, state->hmacKey.t.buffer); + // XOR the key block with 0x5c ^ 0x36 + for(pb = state->hmacKey.t.buffer, i = hashDef->blockSize; i > 0; i--) + *pb++ ^= (0x5c ^ 0x36); + } + // Set the hash algorithm + state->hashState.hashAlg = hashAlg; + // Set the hash state type + state->hashState.type = HASH_STATE_HMAC; + + return hashDef->digestSize; +} + +//*** CryptHmacEnd() +// This function is called to complete an HMAC. It will finish the current +// digest, and start a new digest. It will then add the oPadKey and the +// completed digest and return the results in dOut. It will not return more +// than dOutSize bytes. +// Return Type: UINT16 +// >= 0 number of bytes in 'dOut' (may be zero) +LIB_EXPORT UINT16 CryptHmacEnd(PHMAC_STATE state, // IN: the hash state buffer + UINT32 dOutSize, // IN: size of digest buffer + BYTE* dOut // OUT: hash digest +) +{ + BYTE temp[MAX_DIGEST_SIZE]; + PHASH_STATE hState = (PHASH_STATE)&state->hashState; + +#if SMAC_IMPLEMENTED + if(hState->type == HASH_STATE_SMAC) + return (state->hashState.state.smac.smacMethods.end)( + &state->hashState.state.smac.state, dOutSize, dOut); +#endif + pAssert(hState->type == HASH_STATE_HMAC); + hState->def = CryptGetHashDef(hState->hashAlg); + // Change the state type for completion processing + hState->type = HASH_STATE_HASH; + if(hState->hashAlg == TPM_ALG_NULL) + dOutSize = 0; + else + { + // Complete the current hash + HashEnd(hState, hState->def->digestSize, temp); + // Do another hash starting with the oPad + CryptHashStart(hState, hState->hashAlg); + CryptDigestUpdate(hState, state->hmacKey.t.size, state->hmacKey.t.buffer); + CryptDigestUpdate(hState, hState->def->digestSize, temp); + } + return HashEnd(hState, dOutSize, dOut); +} + +//*** CryptHmacStart2B() +// This function starts an HMAC and returns the size of the digest +// that will be produced. +// +// This function is provided to support the most common use of starting an HMAC +// with a TPM2B key. +// +// The caller must provide a block of memory in which the hash sequence state +// is kept. The caller should not alter the contents of this buffer until the +// hash sequence is completed or abandoned. +// +// Return Type: UINT16 +// > 0 the digest size of the algorithm +// = 0 the hashAlg was TPM_ALG_NULL +LIB_EXPORT UINT16 CryptHmacStart2B( + PHMAC_STATE hmacState, // OUT: the state of HMAC stack. It will be used + // in HMAC update and completion + TPMI_ALG_HASH hashAlg, // IN: hash algorithm + P2B key // IN: HMAC key +) +{ + return CryptHmacStart(hmacState, hashAlg, key->size, key->buffer); +} + +//*** CryptHmacEnd2B() +// This function is the same as CryptHmacEnd() but the HMAC result +// is returned in a TPM2B which is the most common use. +// Return Type: UINT16 +// >=0 the number of bytes placed in 'digest' +LIB_EXPORT UINT16 CryptHmacEnd2B( + PHMAC_STATE hmacState, // IN: the state of HMAC stack + P2B digest // OUT: HMAC +) +{ + return CryptHmacEnd(hmacState, digest->size, digest->buffer); +} + +//** Mask and Key Generation Functions +//*** CryptMGF_KDF() +// This function performs MGF1/KDF1 or KDF2 using the selected hash. KDF1 and KDF2 are +// T('n') = T('n'-1) || H('seed' || 'counter') with the difference being that, with +// KDF1, 'counter' starts at 0 but with KDF2, 'counter' starts at 1. The caller +// determines which version by setting the initial value of counter to either 0 or 1. +// Note: Any value that is not 0 is considered to be 1. +// +// This function returns the length of the mask produced which +// could be zero if the digest algorithm is not supported +// Return Type: UINT16 +// 0 hash algorithm was TPM_ALG_NULL +// > 0 should be the same as 'mSize' +LIB_EXPORT UINT16 CryptMGF_KDF(UINT32 mSize, // IN: length of the mask to be produced + BYTE* mask, // OUT: buffer to receive the mask + TPM_ALG_ID hashAlg, // IN: hash to use + UINT32 seedSize, // IN: size of the seed + BYTE* seed, // IN: seed size + UINT32 counter // IN: counter initial value +) +{ + HASH_STATE hashState; + PHASH_DEF hDef = CryptGetHashDef(hashAlg); + UINT32 hLen; + UINT32 bytes; + // + // If there is no digest to compute return + if((hDef->digestSize == 0) || (mSize == 0)) + return 0; + if(counter != 0) + counter = 1; + hLen = hDef->digestSize; + for(bytes = 0; bytes < mSize; bytes += hLen) + { + // Start the hash and include the seed and counter + CryptHashStart(&hashState, hashAlg); + CryptDigestUpdate(&hashState, seedSize, seed); + CryptDigestUpdateInt(&hashState, 4, counter); + // Get as much as will fit. + CryptHashEnd(&hashState, MIN((mSize - bytes), hLen), &mask[bytes]); + counter++; + } + return (UINT16)mSize; +} + +//*** CryptKDFa() +// This function performs the key generation according to Part 1 of the +// TPM specification. +// +// This function returns the number of bytes generated which may be zero. +// +// The 'key' and 'keyStream' pointers are not allowed to be NULL. The other +// pointer values may be NULL. The value of 'sizeInBits' must be no larger +// than (2^18)-1 = 256K bits (32385 bytes). +// +// The 'once' parameter is set to allow incremental generation of a large +// value. If this flag is TRUE, 'sizeInBits' will be used in the HMAC computation +// but only one iteration of the KDF is performed. This would be used for +// XOR obfuscation so that the mask value can be generated in digest-sized +// chunks rather than having to be generated all at once in an arbitrarily +// large buffer and then XORed into the result. If 'once' is TRUE, then +// 'sizeInBits' must be a multiple of 8. +// +// Any error in the processing of this command is considered fatal. +// Return Type: UINT16 +// 0 hash algorithm is not supported or is TPM_ALG_NULL +// > 0 the number of bytes in the 'keyStream' buffer +LIB_EXPORT UINT16 CryptKDFa( + TPM_ALG_ID hashAlg, // IN: hash algorithm used in HMAC + const TPM2B* key, // IN: HMAC key + const TPM2B* label, // IN: a label for the KDF + const TPM2B* contextU, // IN: context U + const TPM2B* contextV, // IN: context V + UINT32 sizeInBits, // IN: size of generated key in bits + BYTE* keyStream, // OUT: key buffer + UINT32* counterInOut, // IN/OUT: caller may provide the iteration + // counter for incremental operations to + // avoid large intermediate buffers. + UINT16 blocks // IN: If non-zero, this is the maximum number + // of blocks to be returned, regardless + // of sizeInBits +) +{ + UINT32 counter = 0; // counter value + INT16 bytes; // number of bytes to produce + UINT16 generated; // number of bytes generated + BYTE* stream = keyStream; + HMAC_STATE hState; + UINT16 digestSize = CryptHashGetDigestSize(hashAlg); + + pAssert(key != NULL && keyStream != NULL); + + TEST(TPM_ALG_KDF1_SP800_108); + + if(digestSize == 0) + return 0; + + if(counterInOut != NULL) + counter = *counterInOut; + + // If the size of the request is larger than the numbers will handle, + // it is a fatal error. + pAssert(((sizeInBits + 7) / 8) <= INT16_MAX); + + // The number of bytes to be generated is the smaller of the sizeInBits bytes or + // the number of requested blocks. The number of blocks is the smaller of the + // number requested or the number allowed by sizeInBits. A partial block is + // a full block. + bytes = (blocks > 0) ? blocks * digestSize : (UINT16)BITS_TO_BYTES(sizeInBits); + generated = bytes; + + // Generate required bytes + for(; bytes > 0; bytes -= digestSize) + { + counter++; + // Start HMAC + if(CryptHmacStart(&hState, hashAlg, key->size, key->buffer) == 0) + return 0; + // Adding counter + CryptDigestUpdateInt(&hState.hashState, 4, counter); + + // Adding label + if(label != NULL) + HASH_DATA(&hState.hashState, label->size, (BYTE*)label->buffer); + // Add a null. SP108 is not very clear about when the 0 is needed but to + // make this like the previous version that did not add an 0x00 after + // a null-terminated string, this version will only add a null byte + // if the label parameter did not end in a null byte, or if no label + // is present. + if((label == NULL) || (label->size == 0) + || (label->buffer[label->size - 1] != 0)) + CryptDigestUpdateInt(&hState.hashState, 1, 0); + // Adding contextU + if(contextU != NULL) + HASH_DATA(&hState.hashState, contextU->size, contextU->buffer); + // Adding contextV + if(contextV != NULL) + HASH_DATA(&hState.hashState, contextV->size, contextV->buffer); + // Adding size in bits + CryptDigestUpdateInt(&hState.hashState, 4, sizeInBits); + + // Complete and put the data in the buffer + CryptHmacEnd(&hState, bytes, stream); + stream = &stream[digestSize]; + } + // Masking in the KDF is disabled. If the calling function wants something + // less than even number of bytes, then the caller should do the masking + // because there is no universal way to do it here + if(counterInOut != NULL) + *counterInOut = counter; + return generated; +} + +//*** CryptKDFe() +// This function implements KDFe() as defined in TPM specification part 1. +// +// This function returns the number of bytes generated which may be zero. +// +// The 'Z' and 'keyStream' pointers are not allowed to be NULL. The other +// pointer values may be NULL. The value of 'sizeInBits' must be no larger +// than (2^18)-1 = 256K bits (32385 bytes). +// Any error in the processing of this command is considered fatal. +// Return Type: UINT16 +// 0 hash algorithm is not supported or is TPM_ALG_NULL +// > 0 the number of bytes in the 'keyStream' buffer +// +LIB_EXPORT UINT16 CryptKDFe(TPM_ALG_ID hashAlg, // IN: hash algorithm used in HMAC + TPM2B* Z, // IN: Z + const TPM2B* label, // IN: a label value for the KDF + TPM2B* partyUInfo, // IN: PartyUInfo + TPM2B* partyVInfo, // IN: PartyVInfo + UINT32 sizeInBits, // IN: size of generated key in bits + BYTE* keyStream // OUT: key buffer +) +{ + HASH_STATE hashState; + PHASH_DEF hashDef = CryptGetHashDef(hashAlg); + + UINT32 counter = 0; // counter value + UINT16 hLen; + BYTE* stream = keyStream; + INT16 bytes; // number of bytes to generate + + pAssert(keyStream != NULL && Z != NULL && ((sizeInBits + 7) / 8) < INT16_MAX); + // + hLen = hashDef->digestSize; + bytes = (INT16)((sizeInBits + 7) / 8); + if(hashAlg == TPM_ALG_NULL || bytes == 0) + return 0; + + // Generate required bytes + //The inner loop of that KDF uses: + // Hash[i] := H(counter | Z | OtherInfo) (5) + // Where: + // Hash[i] the hash generated on the i-th iteration of the loop. + // H() an approved hash function + // counter a 32-bit counter that is initialized to 1 and incremented + // on each iteration + // Z the X coordinate of the product of a public ECC key and a + // different private ECC key. + // OtherInfo a collection of qualifying data for the KDF defined below. + // In this specification, OtherInfo will be constructed by: + // OtherInfo := Use | PartyUInfo | PartyVInfo + for(; bytes > 0; stream = &stream[hLen], bytes = bytes - hLen) + { + if(bytes < hLen) + hLen = bytes; + counter++; + // Do the hash + CryptHashStart(&hashState, hashAlg); + // Add counter + CryptDigestUpdateInt(&hashState, 4, counter); + + // Add Z + if(Z != NULL) + CryptDigestUpdate2B(&hashState, Z); + // Add label + if(label != NULL) + CryptDigestUpdate2B(&hashState, label); + // Add a null. SP108 is not very clear about when the 0 is needed but to + // make this like the previous version that did not add an 0x00 after + // a null-terminated string, this version will only add a null byte + // if the label parameter did not end in a null byte, or if no label + // is present. + if((label == NULL) || (label->size == 0) + || (label->buffer[label->size - 1] != 0)) + CryptDigestUpdateInt(&hashState, 1, 0); + // Add PartyUInfo + if(partyUInfo != NULL) + CryptDigestUpdate2B(&hashState, partyUInfo); + + // Add PartyVInfo + if(partyVInfo != NULL) + CryptDigestUpdate2B(&hashState, partyVInfo); + + // Compute Hash. hLen was changed to be the smaller of bytes or hLen + // at the start of each iteration. + CryptHashEnd(&hashState, hLen, stream); + } + + // Mask off bits if the required bits is not a multiple of byte size + if((sizeInBits % 8) != 0) + keyStream[0] &= ((1 << (sizeInBits % 8)) - 1); + + return (UINT16)((sizeInBits + 7) / 8); +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptPrime.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptPrime.c new file mode 100644 index 0000000..46f994a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptPrime.c @@ -0,0 +1,367 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// This file contains the code for prime validation. + +#include "Tpm.h" +#include "CryptPrime_fp.h" + +//#define CPRI_PRIME +//#include "PrimeTable.h" + +#include "CryptPrimeSieve_fp.h" + +extern const uint32_t s_LastPrimeInTable; +extern const uint32_t s_PrimeTableSize; +extern const uint32_t s_PrimesInTable; +extern const unsigned char s_PrimeTable[]; +extern bigConst s_CompositeOfSmallPrimes; + +//** Functions + +//*** Root2() +// This finds ceil(sqrt(n)) to use as a stopping point for searching the prime +// table. +static uint32_t Root2(uint32_t n) +{ + int32_t last = (int32_t)(n >> 2); + int32_t next = (int32_t)(n >> 1); + int32_t diff; + int32_t stop = 10; + // + // get a starting point + for(; next != 0; last >>= 1, next >>= 2) + ; + last++; + do + { + next = (last + (n / last)) >> 1; + diff = next - last; + last = next; + if(stop-- == 0) + FAIL(FATAL_ERROR_INTERNAL); + } while(diff < -1 || diff > 1); + if((n / next) > (unsigned)next) + next++; + pAssert(next != 0); + pAssert(((n / next) <= (unsigned)next) && (n / (next + 1) < (unsigned)next)); + return next; +} + +//*** IsPrimeInt() +// This will do a test of a word of up to 32-bits in size. +BOOL IsPrimeInt(uint32_t n) +{ + uint32_t i; + uint32_t stop; + if(n < 3 || ((n & 1) == 0)) + return (n == 2); + if(n <= s_LastPrimeInTable) + { + n >>= 1; + return ((s_PrimeTable[n >> 3] >> (n & 7)) & 1); + } + // Need to search + stop = Root2(n) >> 1; + // starting at 1 is equivalent to staring at (1 << 1) + 1 = 3 + for(i = 1; i < stop; i++) + { + if((s_PrimeTable[i >> 3] >> (i & 7)) & 1) + // see if this prime evenly divides the number + if((n % ((i << 1) + 1)) == 0) + return FALSE; + } + return TRUE; +} + +//*** BnIsProbablyPrime() +// This function is used when the key sieve is not implemented. This function +// Will try to eliminate some of the obvious things before going on +// to perform MillerRabin as a final verification of primeness. +BOOL BnIsProbablyPrime(bigNum prime, // IN: + RAND_STATE* rand // IN: the random state just + // in case Miller-Rabin is required +) +{ +#if RADIX_BITS > 32 + if(BnUnsignedCmpWord(prime, UINT32_MAX) <= 0) +#else + if(BnGetSize(prime) == 1) +#endif + return IsPrimeInt((uint32_t)prime->d[0]); + + if(BnIsEven(prime)) + return FALSE; + if(BnUnsignedCmpWord(prime, s_LastPrimeInTable) <= 0) + { + crypt_uword_t temp = prime->d[0] >> 1; + return ((s_PrimeTable[temp >> 3] >> (temp & 7)) & 1); + } + { + BN_VAR(n, LARGEST_NUMBER_BITS); + BnGcd(n, prime, s_CompositeOfSmallPrimes); + if(!BnEqualWord(n, 1)) + return FALSE; + } + return MillerRabin(prime, rand); +} + +//*** MillerRabinRounds() +// Function returns the number of Miller-Rabin rounds necessary to give an +// error probability equal to the security strength of the prime. These values +// are from FIPS 186-3. +UINT32 +MillerRabinRounds(UINT32 bits // IN: Number of bits in the RSA prime +) +{ + if(bits < 511) + return 8; // don't really expect this + if(bits < 1536) + return 5; // for 512 and 1K primes + return 4; // for 3K public modulus and greater +} + +//*** MillerRabin() +// This function performs a Miller-Rabin test from FIPS 186-3. It does +// 'iterations' trials on the number. In all likelihood, if the number +// is not prime, the first test fails. +// Return Type: BOOL +// TRUE(1) probably prime +// FALSE(0) composite +BOOL MillerRabin(bigNum bnW, RAND_STATE* rand) +{ + BN_MAX(bnWm1); + BN_PRIME(bnM); + BN_PRIME(bnB); + BN_PRIME(bnZ); + BOOL ret = FALSE; // Assumed composite for easy exit + unsigned int a; + unsigned int j; + int wLen; + int i; + int iterations = MillerRabinRounds(BnSizeInBits(bnW)); + // + INSTRUMENT_INC(MillerRabinTrials[PrimeIndex]); + + pAssert(bnW->size > 1); + // Let a be the largest integer such that 2^a divides w1. + BnSubWord(bnWm1, bnW, 1); + pAssert(bnWm1->size != 0); + + // Since w is odd (w-1) is even so start at bit number 1 rather than 0 + // Get the number of bits in bnWm1 so that it doesn't have to be recomputed + // on each iteration. + i = (int)(bnWm1->size * RADIX_BITS); + // Now find the largest power of 2 that divides w1 + for(a = 1; (a < (bnWm1->size * RADIX_BITS)) && (BnTestBit(bnWm1, a) == 0); a++) + ; + // 2. m = (w1) / 2^a + BnShiftRight(bnM, bnWm1, a); + // 3. wlen = len (w). + wLen = BnSizeInBits(bnW); + // 4. For i = 1 to iterations do + for(i = 0; i < iterations; i++) + { + // 4.1 Obtain a string b of wlen bits from an RBG. + // Ensure that 1 < b < w1. + // 4.2 If ((b <= 1) or (b >= w1)), then go to step 4.1. + while( + BnGetRandomBits(bnB, wLen, rand) + && ((BnUnsignedCmpWord(bnB, 1) <= 0) || (BnUnsignedCmp(bnB, bnWm1) >= 0))) + ; + if(g_inFailureMode) + return FALSE; + + // 4.3 z = b^m mod w. + // if ModExp fails, then say this is not + // prime and bail out. + BnModExp(bnZ, bnB, bnM, bnW); + + // 4.4 If ((z == 1) or (z = w == 1)), then go to step 4.7. + if((BnUnsignedCmpWord(bnZ, 1) == 0) || (BnUnsignedCmp(bnZ, bnWm1) == 0)) + goto step4point7; + // 4.5 For j = 1 to a 1 do. + for(j = 1; j < a; j++) + { + // 4.5.1 z = z^2 mod w. + BnModMult(bnZ, bnZ, bnZ, bnW); + // 4.5.2 If (z = w1), then go to step 4.7. + if(BnUnsignedCmp(bnZ, bnWm1) == 0) + goto step4point7; + // 4.5.3 If (z = 1), then go to step 4.6. + if(BnEqualWord(bnZ, 1)) + goto step4point6; + } + // 4.6 Return COMPOSITE. +step4point6: + INSTRUMENT_INC(failedAtIteration[i]); + goto end; + // 4.7 Continue. Comment: Increment i for the do-loop in step 4. +step4point7: + continue; + } + // 5. Return PROBABLY PRIME + ret = TRUE; +end: + return ret; +} + +#if ALG_RSA + +//*** RsaCheckPrime() +// This will check to see if a number is prime and appropriate for an +// RSA prime. +// +// This has different functionality based on whether we are using key +// sieving or not. If not, the number checked to see if it is divisible by +// the public exponent, then the number is adjusted either up or down +// in order to make it a better candidate. It is then checked for being +// probably prime. +// +// If sieving is used, the number is used to root a sieving process. +// +TPM_RC +RsaCheckPrime(bigNum prime, UINT32 exponent, RAND_STATE* rand) +{ +# if !RSA_KEY_SIEVE + TPM_RC retVal = TPM_RC_SUCCESS; + UINT32 modE = BnModWord(prime, exponent); + + NOT_REFERENCED(rand); + + if(modE == 0) + // evenly divisible so add two keeping the number odd + BnAddWord(prime, prime, 2); + // want 0 != (p - 1) mod e + // which is 1 != p mod e + else if(modE == 1) + // subtract 2 keeping number odd and insuring that + // 0 != (p - 1) mod e + BnSubWord(prime, prime, 2); + + if(BnIsProbablyPrime(prime, rand) == 0) + ERROR_RETURN(g_inFailureMode ? TPM_RC_FAILURE : TPM_RC_VALUE); +Exit: + return retVal; +# else + return PrimeSelectWithSieve(prime, exponent, rand); +# endif +} + +//*** RsaAdjustPrimeCandiate() +// For this math, we assume that the RSA numbers are fixed-point numbers with +// the decimal point to the "left" of the most significant bit. This approach helps +// make it clear what is happening with the MSb of the values. +// The two RSA primes have to be large enough so that their product will be a number +// with the necessary number of significant bits. For example, we want to be able +// to multiply two 1024-bit numbers to produce a number with 2028 significant bits. If +// we accept any 1024-bit prime that has its MSb set, then it is possible to produce a +// product that does not have the MSb SET. For example, if we use tiny keys of 16 bits +// and have two 8-bit 'primes' of 0x80, then the public key would be 0x4000 which is +// only 15-bits. So, what we need to do is made sure that each of the primes is large +// enough so that the product of the primes is twice as large as each prime. A little +// arithmetic will show that the only way to do this is to make sure that each of the +// primes is no less than root(2)/2. That's what this functions does. +// This function adjusts the candidate prime so that it is odd and >= root(2)/2. +// This allows the product of these two numbers to be .5, which, in fixed point +// notation means that the most significant bit is 1. +// For this routine, the root(2)/2 (0.7071067811865475) approximated with 0xB505 +// which is, in fixed point, 0.7071075439453125 or an error of 0.000108%. Just setting +// the upper two bits would give a value > 0.75 which is an error of > 6%. Given the +// amount of time all the other computations take, reducing the error is not much of +// a cost, but it isn't totally required either. +// +// This function can be replaced with a function that just sets the two most +// significant bits of each prime candidate without introducing any computational +// issues. +// +LIB_EXPORT void RsaAdjustPrimeCandidate(bigNum prime) +{ + UINT32 msw; + UINT32 adjusted; + + // If the radix is 32, the compiler should turn this into a simple assignment + msw = prime->d[prime->size - 1] >> ((RADIX_BITS == 64) ? 32 : 0); + // Multiplying 0xff...f by 0x4AFB gives 0xff..f - 0xB5050...0 + adjusted = (msw >> 16) * 0x4AFB; + adjusted += ((msw & 0xFFFF) * 0x4AFB) >> 16; + adjusted += 0xB5050000UL; +# if RADIX_BITS == 64 + // Save the low-order 32 bits + prime->d[prime->size - 1] &= 0xFFFFFFFFUL; + // replace the upper 32-bits + prime->d[prime->size - 1] |= ((crypt_uword_t)adjusted << 32); +# else + prime->d[prime->size - 1] = (crypt_uword_t)adjusted; +# endif + // make sure the number is odd + prime->d[0] |= 1; +} + +//***BnGeneratePrimeForRSA() +// Function to generate a prime of the desired size with the proper attributes +// for an RSA prime. +TPM_RC +BnGeneratePrimeForRSA(bigNum prime, // IN/OUT: points to the BN that will get the + // random value + UINT32 bits, // IN: number of bits to get + UINT32 exponent, // IN: the exponent + RAND_STATE* rand // IN: the random state +) +{ + BOOL found = FALSE; + // + // Make sure that the prime is large enough + pAssert(prime->allocated >= BITS_TO_CRYPT_WORDS(bits)); + // Only try to handle specific sizes of keys in order to save overhead + pAssert((bits % 32) == 0); + + prime->size = BITS_TO_CRYPT_WORDS(bits); + + while(!found) + { + // The change below is to make sure that all keys that are generated from the same + // seed value will be the same regardless of the endianess or word size of the CPU. + // DRBG_Generate(rand, (BYTE *)prime->d, (UINT16)BITS_TO_BYTES(bits));// old + // if(g_inFailureMode) // old + if(!BnGetRandomBits(prime, bits, rand)) // new + return TPM_RC_FAILURE; + RsaAdjustPrimeCandidate(prime); + found = RsaCheckPrime(prime, exponent, rand) == TPM_RC_SUCCESS; + } + return TPM_RC_SUCCESS; +} + +#endif // ALG_RSA \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptPrimeSieve.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptPrimeSieve.c new file mode 100644 index 0000000..a7d71df --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptPrimeSieve.c @@ -0,0 +1,537 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Includes and defines + +#include "Tpm.h" + +#if RSA_KEY_SIEVE + +# include "CryptPrimeSieve_fp.h" + +// This determines the number of bits in the largest sieve field. +# define MAX_FIELD_SIZE 2048 + +extern const uint32_t s_LastPrimeInTable; +extern const uint32_t s_PrimeTableSize; +extern const uint32_t s_PrimesInTable; +extern const unsigned char s_PrimeTable[]; + +// This table is set of prime markers. Each entry is the prime value +// for the ((n + 1) * 1024) prime. That is, the entry in s_PrimeMarkers[1] +// is the value for the 2,048th prime. This is used in the PrimeSieve +// to adjust the limit for the prime search. When processing smaller +// prime candidates, fewer primes are checked directly before going to +// Miller-Rabin. As the prime grows, it is worth spending more time eliminating +// primes as, a) the density is lower, and b) the cost of Miller-Rabin is +// higher. +const uint32_t s_PrimeMarkersCount = 6; +const uint32_t s_PrimeMarkers[] = {8167, 17881, 28183, 38891, 49871, 60961}; +uint32_t primeLimit; + +//** Functions + +//*** RsaAdjustPrimeLimit() +// This used during the sieve process. The iterator for getting the +// next prime (RsaNextPrime()) will return primes until it hits the +// limit (primeLimit) set up by this function. This causes the sieve +// process to stop when an appropriate number of primes have been +// sieved. +LIB_EXPORT void RsaAdjustPrimeLimit(uint32_t requestedPrimes) +{ + if(requestedPrimes == 0 || requestedPrimes > s_PrimesInTable) + requestedPrimes = s_PrimesInTable; + requestedPrimes = (requestedPrimes - 1) / 1024; + if(requestedPrimes < s_PrimeMarkersCount) + primeLimit = s_PrimeMarkers[requestedPrimes]; + else + primeLimit = s_LastPrimeInTable; + primeLimit >>= 1; +} + +//*** RsaNextPrime() +// This the iterator used during the sieve process. The input is the +// last prime returned (or any starting point) and the output is the +// next higher prime. The function returns 0 when the primeLimit is +// reached. +LIB_EXPORT uint32_t RsaNextPrime(uint32_t lastPrime) +{ + if(lastPrime == 0) + return 0; + lastPrime >>= 1; + for(lastPrime += 1; lastPrime <= primeLimit; lastPrime++) + { + if(((s_PrimeTable[lastPrime >> 3] >> (lastPrime & 0x7)) & 1) == 1) + return ((lastPrime << 1) + 1); + } + return 0; +} + +// This table contains a previously sieved table. It has +// the bits for 3, 5, and 7 removed. Because of the +// factors, it needs to be aligned to 105 and has +// a repeat of 105. +const BYTE seedValues[] = {0x16, 0x29, 0xcb, 0xa4, 0x65, 0xda, 0x30, 0x6c, 0x99, 0x96, + 0x4c, 0x53, 0xa2, 0x2d, 0x52, 0x96, 0x49, 0xcb, 0xb4, 0x61, + 0xd8, 0x32, 0x2d, 0x99, 0xa6, 0x44, 0x5b, 0xa4, 0x2c, 0x93, + 0x96, 0x69, 0xc3, 0xb0, 0x65, 0x5a, 0x32, 0x4d, 0x89, 0xb6, + 0x48, 0x59, 0x26, 0x2d, 0xd3, 0x86, 0x61, 0xcb, 0xb4, 0x64, + 0x9a, 0x12, 0x6d, 0x91, 0xb2, 0x4c, 0x5a, 0xa6, 0x0d, 0xc3, + 0x96, 0x69, 0xc9, 0x34, 0x25, 0xda, 0x22, 0x65, 0x99, 0xb4, + 0x4c, 0x1b, 0x86, 0x2d, 0xd3, 0x92, 0x69, 0x4a, 0xb4, 0x45, + 0xca, 0x32, 0x69, 0x99, 0x36, 0x0c, 0x5b, 0xa6, 0x25, 0xd3, + 0x94, 0x68, 0x8b, 0x94, 0x65, 0xd2, 0x32, 0x6d, 0x18, 0xb6, + 0x4c, 0x4b, 0xa6, 0x29, 0xd1}; + +# define USE_NIBBLE + +# ifndef USE_NIBBLE +static const BYTE bitsInByte[256] = + {0x00, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x03, 0x01, 0x02, 0x02, 0x03, 0x02, + 0x03, 0x03, 0x04, 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x02, 0x03, + 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, + 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x02, 0x03, 0x03, 0x04, + 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x01, + 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, + 0x04, 0x05, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, + 0x05, 0x04, 0x05, 0x05, 0x06, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, + 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x03, 0x04, 0x04, 0x05, 0x04, + 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, 0x01, 0x02, + 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, + 0x05, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, + 0x04, 0x05, 0x05, 0x06, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, + 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, + 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, 0x02, 0x03, 0x03, + 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, + 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, + 0x06, 0x06, 0x07, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x04, 0x05, + 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, + 0x07, 0x05, 0x06, 0x06, 0x07, 0x06, 0x07, 0x07, 0x08}; +# define BitsInByte(x) bitsInByte[(unsigned char)x] +# else +const BYTE bitsInNibble[16] = {0x00, + 0x01, + 0x01, + 0x02, + 0x01, + 0x02, + 0x02, + 0x03, + 0x01, + 0x02, + 0x02, + 0x03, + 0x02, + 0x03, + 0x03, + 0x04}; +# define BitsInByte(x) \ + (bitsInNibble[(unsigned char)(x)&0xf] \ + + bitsInNibble[((unsigned char)(x) >> 4) & 0xf]) +# endif + +//*** BitsInArry() +// This function counts the number of bits set in an array of bytes. +static int BitsInArray(const unsigned char* a, // IN: A pointer to an array of bytes + unsigned int aSize // IN: the number of bytes to sum +) +{ + int j = 0; + for(; aSize; a++, aSize--) + j += BitsInByte(*a); + return j; +} + +//*** FindNthSetBit() +// This function finds the nth SET bit in a bit array. The 'n' parameter is +// between 1 and the number of bits in the array (always a multiple of 8). +// If called when the array does not have n bits set, it will return -1 +// Return Type: unsigned int +// <0 no bit is set or no bit with the requested number is set +// >=0 the number of the bit in the array that is the nth set +LIB_EXPORT int FindNthSetBit( + const UINT16 aSize, // IN: the size of the array to check + const BYTE* a, // IN: the array to check + const UINT32 n // IN, the number of the SET bit +) +{ + UINT16 i; + int retValue; + UINT32 sum = 0; + BYTE sel; + + //find the bit + for(i = 0; (i < (int)aSize) && (sum < n); i++) + sum += BitsInByte(a[i]); + i--; + // The chosen bit is in the byte that was just accessed + // Compute the offset to the start of that byte + retValue = i * 8 - 1; + sel = a[i]; + // Subtract the bits in the last byte added. + sum -= BitsInByte(sel); + // Now process the byte, one bit at a time. + for(; (sel != 0) && (sum != n); retValue++, sel = sel >> 1) + sum += (sel & 1) != 0; + return (sum == n) ? retValue : -1; +} + +typedef struct +{ + UINT16 prime; + UINT16 count; +} SIEVE_MARKS; + +const SIEVE_MARKS sieveMarks[5] = {{31, 7}, + {73, 5}, + {241, 4}, + {1621, 3}, + {UINT16_MAX, 2}}; + +//*** PrimeSieve() +// This function does a prime sieve over the input 'field' which has as its +// starting address the value in bnN. Since this initializes the Sieve +// using a precomputed field with the bits associated with 3, 5 and 7 already +// turned off, the value of pnN may need to be adjusted by a few counts to allow +// the precomputed field to be used without modification. +// +// To get better performance, one could address the issue of developing the +// composite numbers. When the size of the prime gets large, the time for doing +// the divisions goes up, noticeably. It could be better to develop larger composite +// numbers even if they need to be bigNum's themselves. The object would be to +// reduce the number of times that the large prime is divided into a few large +// divides and then use smaller divides to get to the final 16 bit (or smaller) +// remainders. +LIB_EXPORT UINT32 PrimeSieve(bigNum bnN, // IN/OUT: number to sieve + UINT32 fieldSize, // IN: size of the field area in bytes + BYTE* field // IN: field +) +{ + UINT32 i; + UINT32 j; + UINT32 fieldBits = fieldSize * 8; + UINT32 r; + BYTE* pField; + INT32 iter; + UINT32 adjust; + UINT32 mark = 0; + UINT32 count = sieveMarks[0].count; + UINT32 stop = sieveMarks[0].prime; + UINT32 composite; + UINT32 pList[8]; + UINT32 next; + + pAssert(field != NULL && bnN != NULL); + + // If the remainder is odd, then subtracting the value will give an even number, + // but we want an odd number, so subtract the 105+rem. Otherwise, just subtract + // the even remainder. + adjust = (UINT32)BnModWord(bnN, 105); + if(adjust & 1) + adjust += 105; + + // Adjust the input number so that it points to the first number in a + // aligned field. + BnSubWord(bnN, bnN, adjust); + // pAssert(BnModWord(bnN, 105) == 0); + pField = field; + for(i = fieldSize; i >= sizeof(seedValues); + pField += sizeof(seedValues), i -= sizeof(seedValues)) + { + memcpy(pField, seedValues, sizeof(seedValues)); + } + if(i != 0) + memcpy(pField, seedValues, i); + + // Cycle through the primes, clearing bits + // Have already done 3, 5, and 7 + iter = 7; + +# define NEXT_PRIME(iter) (iter = RsaNextPrime(iter)) + // Get the next N primes where N is determined by the mark in the sieveMarks + while((composite = NEXT_PRIME(iter)) != 0) + { + next = 0; + i = count; + pList[i--] = composite; + for(; i > 0; i--) + { + next = NEXT_PRIME(iter); + pList[i] = next; + if(next != 0) + composite *= next; + } + // Get the remainder when dividing the base field address + // by the composite + composite = (UINT32)BnModWord(bnN, composite); + // 'composite' is divisible by the composite components. for each of the + // composite components, divide 'composite'. That remainder (r) is used to + // pick a starting point for clearing the array. The stride is equal to the + // composite component. Note, the field only contains odd numbers. If the + // field were expanded to contain all numbers, then half of the bits would + // have already been cleared. We can save the trouble of clearing them a + // second time by having a stride of 2*next. Or we can take all of the even + // numbers out of the field and use a stride of 'next' + for(i = count; i > 0; i--) + { + next = pList[i]; + if(next == 0) + goto done; + r = composite % next; + // these computations deal with the fact that we have picked a field-sized + // range that is aligned to a 105 count boundary. The problem is, this field + // only contains odd numbers. If we take our prime guess and walk through all + // the numbers using that prime as the 'stride', then every other 'stride' is + // going to be an even number. So, we are actually counting by 2 * the stride + // We want the count to start on an odd number at the start of our field. That + // is, we want to assume that we have counted up to the edge of the field by + // the 'stride' and now we are going to start flipping bits in the field as we + // continue to count up by 'stride'. If we take the base of our field and + // divide by the stride, we find out how much we find out how short the last + // count was from reaching the edge of the bit field. Say we get a quotient of + // 3 and remainder of 1. This means that after 3 strides, we are 1 short of + // the start of the field and the next stride will either land within the + // field or step completely over it. The confounding factor is that our field + // only contains odd numbers and our stride is actually 2 * stride. If the + // quoitent is even, then that means that when we add 2 * stride, we are going + // to hit another even number. So, we have to know if we need to back off + // by 1 stride before we start couting by 2 * stride. + // We can tell from the remainder whether we are on an even or odd + // stride when we hit the beginning of the table. If we are on an odd stride + // (r & 1), we would start half a stride in (next - r)/2. If we are on an + // even stride, we need 0.5 strides (next - r/2) because the table only has + // odd numbers. If the remainder happens to be zero, then the start of the + // table is on stride so no adjustment is necessary. + if(r & 1) + j = (next - r) / 2; + else if(r == 0) + j = 0; + else + j = next - (r / 2); + for(; j < fieldBits; j += next) + ClearBit(j, field, fieldSize); + } + if(next >= stop) + { + mark++; + count = sieveMarks[mark].count; + stop = sieveMarks[mark].prime; + } + } +done: + INSTRUMENT_INC(totalFieldsSieved[PrimeIndex]); + i = BitsInArray(field, fieldSize); + INSTRUMENT_ADD(bitsInFieldAfterSieve[PrimeIndex], i); + INSTRUMENT_ADD(emptyFieldsSieved[PrimeIndex], (i == 0)); + return i; +} + +# ifdef SIEVE_DEBUG +static uint32_t fieldSize = 210; + +//***SetFieldSize() +// Function to set the field size used for prime generation. Used for tuning. +LIB_EXPORT uint32_t SetFieldSize(uint32_t newFieldSize) +{ + if(newFieldSize == 0 || newFieldSize > MAX_FIELD_SIZE) + fieldSize = MAX_FIELD_SIZE; + else + fieldSize = newFieldSize; + return fieldSize; +} +# endif // SIEVE_DEBUG + +//*** PrimeSelectWithSieve() +// This function will sieve the field around the input prime candidate. If the +// sieve field is not empty, one of the one bits in the field is chosen for testing +// with Miller-Rabin. If the value is prime, 'pnP' is updated with this value +// and the function returns success. If this value is not prime, another +// pseudo-random candidate is chosen and tested. This process repeats until +// all values in the field have been checked. If all bits in the field have +// been checked and none is prime, the function returns FALSE and a new random +// value needs to be chosen. +// Return Type: TPM_RC +// TPM_RC_FAILURE TPM in failure mode, probably due to entropy source +// TPM_RC_SUCCESS candidate is probably prime +// TPM_RC_NO_RESULT candidate is not prime and couldn't find and alternative +// in the field +LIB_EXPORT TPM_RC PrimeSelectWithSieve( + bigNum candidate, // IN/OUT: The candidate to filter + UINT32 e, // IN: the exponent + RAND_STATE* rand // IN: the random number generator state +) +{ + BYTE field[MAX_FIELD_SIZE]; + UINT32 first; + UINT32 ones; + INT32 chosen; + BN_PRIME(test); + UINT32 modE; +# ifndef SIEVE_DEBUG + UINT32 fieldSize = MAX_FIELD_SIZE; +# endif + UINT32 primeSize; + // + // Adjust the field size and prime table list to fit the size of the prime + // being tested. This is done to try to optimize the trade-off between the + // dividing done for sieving and the time for Miller-Rabin. When the size + // of the prime is large, the cost of Miller-Rabin is fairly high, as is the + // cost of the sieving. However, the time for Miller-Rabin goes up considerably + // faster than the cost of dividing by a number of primes. + primeSize = BnSizeInBits(candidate); + + if(primeSize <= 512) + { + RsaAdjustPrimeLimit(1024); // Use just the first 1024 primes + } + else if(primeSize <= 1024) + { + RsaAdjustPrimeLimit(4096); // Use just the first 4K primes + } + else + { + RsaAdjustPrimeLimit(0); // Use all available + } + + // Save the low-order word to use as a search generator and make sure that + // it has some interesting range to it + first = (UINT32)(candidate->d[0] | 0x80000000); + + // Sieve the field + ones = PrimeSieve(candidate, fieldSize, field); + pAssert(ones > 0 && ones < (fieldSize * 8)); + for(; ones > 0; ones--) + { + // Decide which bit to look at and find its offset + chosen = FindNthSetBit((UINT16)fieldSize, field, ((first % ones) + 1)); + + if((chosen < 0) || (chosen >= (INT32)(fieldSize * 8))) + FAIL(FATAL_ERROR_INTERNAL); + + // Set this as the trial prime + BnAddWord(test, candidate, (crypt_uword_t)(chosen * 2)); + + // The exponent might not have been one of the tested primes so + // make sure that it isn't divisible and make sure that 0 != (p-1) mod e + // Note: This is the same as 1 != p mod e + modE = (UINT32)BnModWord(test, e); + if((modE != 0) && (modE != 1) && MillerRabin(test, rand)) + { + BnCopy(candidate, test); + return TPM_RC_SUCCESS; + } + // Clear the bit just tested + ClearBit(chosen, field, fieldSize); + } + // Ran out of bits and couldn't find a prime in this field + INSTRUMENT_INC(noPrimeFields[PrimeIndex]); + return (g_inFailureMode ? TPM_RC_FAILURE : TPM_RC_NO_RESULT); +} + +# if RSA_INSTRUMENT +static char a[256]; + +//*** PrintTuple() +char* PrintTuple(UINT32* i) +{ + sprintf(a, "{%d, %d, %d}", i[0], i[1], i[2]); + return a; +} + +# define CLEAR_VALUE(x) memset(x, 0, sizeof(x)) + +//*** RsaSimulationEnd() +void RsaSimulationEnd(void) +{ + int i; + UINT32 averages[3]; + UINT32 nonFirst = 0; + if((PrimeCounts[0] + PrimeCounts[1] + PrimeCounts[2]) != 0) + { + printf("Primes generated = %s\n", PrintTuple(PrimeCounts)); + printf("Fields sieved = %s\n", PrintTuple(totalFieldsSieved)); + printf("Fields with no primes = %s\n", PrintTuple(noPrimeFields)); + printf("Primes checked with Miller-Rabin = %s\n", + PrintTuple(MillerRabinTrials)); + for(i = 0; i < 3; i++) + averages[i] = (totalFieldsSieved[i] != 0 + ? bitsInFieldAfterSieve[i] / totalFieldsSieved[i] + : 0); + printf("Average candidates in field %s\n", PrintTuple(averages)); + for(i = 1; i < (sizeof(failedAtIteration) / sizeof(failedAtIteration[0])); + i++) + nonFirst += failedAtIteration[i]; + printf("Miller-Rabin failures not in first round = %d\n", nonFirst); + } + CLEAR_VALUE(PrimeCounts); + CLEAR_VALUE(totalFieldsSieved); + CLEAR_VALUE(noPrimeFields); + CLEAR_VALUE(MillerRabinTrials); + CLEAR_VALUE(bitsInFieldAfterSieve); +} + +//*** GetSieveStats() +LIB_EXPORT void GetSieveStats( + uint32_t* trials, uint32_t* emptyFields, uint32_t* averageBits) +{ + uint32_t totalBits; + uint32_t fields; + *trials = MillerRabinTrials[0] + MillerRabinTrials[1] + MillerRabinTrials[2]; + *emptyFields = noPrimeFields[0] + noPrimeFields[1] + noPrimeFields[2]; + fields = totalFieldsSieved[0] + totalFieldsSieved[1] + totalFieldsSieved[2]; + totalBits = bitsInFieldAfterSieve[0] + bitsInFieldAfterSieve[1] + + bitsInFieldAfterSieve[2]; + if(fields != 0) + *averageBits = totalBits / fields; + else + *averageBits = 0; + CLEAR_VALUE(PrimeCounts); + CLEAR_VALUE(totalFieldsSieved); + CLEAR_VALUE(noPrimeFields); + CLEAR_VALUE(MillerRabinTrials); + CLEAR_VALUE(bitsInFieldAfterSieve); +} +# endif + +#endif // RSA_KEY_SIEVE + +#if !RSA_INSTRUMENT + +//*** RsaSimulationEnd() +// Stub for call when not doing instrumentation. +void RsaSimulationEnd(void) +{ + return; +} +#endif \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptRand.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptRand.c new file mode 100644 index 0000000..b3638d3 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptRand.c @@ -0,0 +1,943 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// This file implements a DRBG with a behavior according to SP800-90A using +// a block cypher. This is also compliant to ISO/IEC 18031:2011(E) C.3.2. +// +// A state structure is created for use by TPM.lib and functions +// within the CryptoEngine my use their own state structures when they need to have +// deterministic values. +// +// A debug mode is available that allows the random numbers generated for TPM.lib +// to be repeated during runs of the simulator. The switch for it is in +// TpmBuildSwitches.h. It is USE_DEBUG_RNG. +// +// +// This is the implementation layer of CTR DRGB mechanism as defined in SP800-90A +// and the functions are organized as closely as practical to the organization in +// SP800-90A. It is intended to be compiled as a separate module that is linked +// with a secure application so that both reside inside the same boundary +// [SP 800-90A 8.5]. The secure application in particular manages the accesses +// protected storage for the state of the DRBG instantiations, and supplies the +// implementation functions here with a valid pointer to the working state of the +// given instantiations (as a DRBG_STATE structure). +// +// This DRBG mechanism implementation does not support prediction resistance. Thus +// 'prediction_resistance_flag' is omitted from Instantiate_function(), +// Reseed_function(), Generate_function() argument lists [SP 800-90A 9.1, 9.2, +// 9.3], as well as from the working state data structure DRBG_STATE [SP 800-90A +// 9.1]. +// +// This DRBG mechanism implementation always uses the highest security strength of +// available in the block ciphers. Thus 'requested_security_strength' parameter is +// omitted from Instantiate_function() and Generate_function() argument lists +// [SP 800-90A 9.1, 9.2, 9.3], as well as from the working state data structure +// DRBG_STATE [SP 800-90A 9.1]. +// +// Internal functions (ones without Crypt prefix) expect validated arguments and +// therefore use assertions instead of runtime parameter checks and mostly return +// void instead of a status value. + +#include "Tpm.h" + +// Pull in the test vector definitions and define the space +#include "PRNG_TestVectors.h" + +const BYTE DRBG_NistTestVector_Entropy[] = {DRBG_TEST_INITIATE_ENTROPY}; +const BYTE DRBG_NistTestVector_GeneratedInterm[] = {DRBG_TEST_GENERATED_INTERM}; + +const BYTE DRBG_NistTestVector_EntropyReseed[] = {DRBG_TEST_RESEED_ENTROPY}; +const BYTE DRBG_NistTestVector_Generated[] = {DRBG_TEST_GENERATED}; + +//** Derivation Functions +//*** Description +// The functions in this section are used to reduce the personalization input values +// to make them usable as input for reseeding and instantiation. The overall +// behavior is intended to produce the same results as described in SP800-90A, +// section 10.4.2 "Derivation Function Using a Block Cipher Algorithm +// (Block_Cipher_df)." The code is broken into several subroutines to deal with the +// fact that the data used for personalization may come in several separate blocks +// such as a Template hash and a proof value and a primary seed. + +//*** Derivation Function Defines and Structures + +#define DF_COUNT (DRBG_KEY_SIZE_WORDS / DRBG_IV_SIZE_WORDS + 1) +#if DRBG_KEY_SIZE_BITS != 128 && DRBG_KEY_SIZE_BITS != 256 +# error "CryptRand.c only written for AES with 128- or 256-bit keys." +#endif + +typedef struct +{ + DRBG_KEY_SCHEDULE keySchedule; + DRBG_IV iv[DF_COUNT]; + DRBG_IV out1; + DRBG_IV buf; + int contents; +} DF_STATE, *PDF_STATE; + +//*** DfCompute() +// This function does the incremental update of the derivation function state. It +// encrypts the 'iv' value and XOR's the results into each of the blocks of the +// output. This is equivalent to processing all of input data for each output block. +static void DfCompute(PDF_STATE dfState) +{ + int i; + int iv; + crypt_uword_t* pIv; + crypt_uword_t temp[DRBG_IV_SIZE_WORDS] = {0}; + // + for(iv = 0; iv < DF_COUNT; iv++) + { + pIv = (crypt_uword_t*)&dfState->iv[iv].words[0]; + for(i = 0; i < DRBG_IV_SIZE_WORDS; i++) + { + temp[i] ^= pIv[i] ^ dfState->buf.words[i]; + } + DRBG_ENCRYPT(&dfState->keySchedule, &temp, pIv); + } + for(i = 0; i < DRBG_IV_SIZE_WORDS; i++) + dfState->buf.words[i] = 0; + dfState->contents = 0; +} + +//*** DfStart() +// This initializes the output blocks with an encrypted counter value and +// initializes the key schedule. +static void DfStart(PDF_STATE dfState, uint32_t inputLength) +{ + BYTE init[8]; + int i; + UINT32 drbgSeedSize = sizeof(DRBG_SEED); + + const BYTE dfKey[DRBG_KEY_SIZE_BYTES] = + { 0x00, + 0x01, + 0x02, + 0x03, + 0x04, + 0x05, + 0x06, + 0x07, + 0x08, + 0x09, + 0x0a, + 0x0b, + 0x0c, + 0x0d, + 0x0e, + 0x0f +#if DRBG_KEY_SIZE_BYTES > 16 + , + 0x10, + 0x11, + 0x12, + 0x13, + 0x14, + 0x15, + 0x16, + 0x17, + 0x18, + 0x19, + 0x1a, + 0x1b, + 0x1c, + 0x1d, + 0x1e, + 0x1f +#endif + }; + memset(dfState, 0, sizeof(DF_STATE)); + DRBG_ENCRYPT_SETUP(&dfKey[0], DRBG_KEY_SIZE_BITS, &dfState->keySchedule); + // Create the first chaining values + for(i = 0; i < DF_COUNT; i++) + ((BYTE*)&dfState->iv[i])[3] = (BYTE)i; + DfCompute(dfState); + // initialize the first 64 bits of the IV in a way that doesn't depend + // on the size of the words used. + UINT32_TO_BYTE_ARRAY(inputLength, init); + UINT32_TO_BYTE_ARRAY(drbgSeedSize, &init[4]); + memcpy(&dfState->iv[0], init, 8); + dfState->contents = 4; +} + +//*** DfUpdate() +// This updates the state with the input data. A byte at a time is moved into the +// state buffer until it is full and then that block is encrypted by DfCompute(). +static void DfUpdate(PDF_STATE dfState, int size, const BYTE* data) +{ + while(size > 0) + { + int toFill = DRBG_IV_SIZE_BYTES - dfState->contents; + if(size < toFill) + toFill = size; + // Copy as many bytes as there are or until the state buffer is full + memcpy(&dfState->buf.bytes[dfState->contents], data, toFill); + // Reduce the size left by the amount copied + size -= toFill; + // Advance the data pointer by the amount copied + data += toFill; + // increase the buffer contents count by the amount copied + dfState->contents += toFill; + pAssert(dfState->contents <= DRBG_IV_SIZE_BYTES); + // If we have a full buffer, do a computation pass. + if(dfState->contents == DRBG_IV_SIZE_BYTES) + DfCompute(dfState); + } +} + +//*** DfEnd() +// This function is called to get the result of the derivation function computation. +// If the buffer is not full, it is padded with zeros. The output buffer is +// structured to be the same as a DRBG_SEED value so that the function can return +// a pointer to the DRBG_SEED value in the DF_STATE structure. +static DRBG_SEED* DfEnd(PDF_STATE dfState) +{ + // Since DfCompute is always called when a buffer is full, there is always + // space in the buffer for the terminator + dfState->buf.bytes[dfState->contents++] = 0x80; + // If the buffer is not full, pad with zeros + while(dfState->contents < DRBG_IV_SIZE_BYTES) + dfState->buf.bytes[dfState->contents++] = 0; + // Do a final state update + DfCompute(dfState); + return (DRBG_SEED*)&dfState->iv; +} + +//*** DfBuffer() +// Function to take an input buffer and do the derivation function to produce a +// DRBG_SEED value that can be used in DRBG_Reseed(); +static DRBG_SEED* DfBuffer(DRBG_SEED* output, // OUT: receives the result + int size, // IN: size of the buffer to add + BYTE* buf // IN: address of the buffer +) +{ + DF_STATE dfState; + if(size == 0 || buf == NULL) + return NULL; + // Initialize the derivation function + DfStart(&dfState, size); + DfUpdate(&dfState, size, buf); + DfEnd(&dfState); + memcpy(output, &dfState.iv[0], sizeof(DRBG_SEED)); + return output; +} + +//*** DRBG_GetEntropy() +// Even though this implementation never fails, it may get blocked +// indefinitely long in the call to get entropy from the platform +// (DRBG_GetEntropy32()). +// This function is only used during instantiation of the DRBG for +// manufacturing and on each start-up after an non-orderly shutdown. +// +// Return Type: BOOL +// TRUE(1) requested entropy returned +// FALSE(0) entropy Failure +BOOL DRBG_GetEntropy(UINT32 requiredEntropy, // IN: requested number of bytes of full + // entropy + BYTE* entropy // OUT: buffer to return collected entropy +) +{ +#if !USE_DEBUG_RNG + + UINT32 obtainedEntropy; + INT32 returnedEntropy; + + // If in debug mode, always use the self-test values for initialization + if(IsSelfTest()) + { +#endif + // If doing simulated DRBG, then check to see if the + // entropyFailure condition is being tested + if(!IsEntropyBad()) + { + // In self-test, the caller should be asking for exactly the seed + // size of entropy. + pAssert(requiredEntropy == sizeof(DRBG_NistTestVector_Entropy)); + memcpy(entropy, + DRBG_NistTestVector_Entropy, + sizeof(DRBG_NistTestVector_Entropy)); + } +#if !USE_DEBUG_RNG + } + else if(!IsEntropyBad()) + { + // Collect entropy + // Note: In debug mode, the only "entropy" value ever returned + // is the value of the self-test vector. + for(returnedEntropy = 1, obtainedEntropy = 0; + obtainedEntropy < requiredEntropy && !IsEntropyBad(); + obtainedEntropy += returnedEntropy) + { + returnedEntropy = _plat__GetEntropy(&entropy[obtainedEntropy], + requiredEntropy - obtainedEntropy); + if(returnedEntropy <= 0) + SetEntropyBad(); + } + } +#endif + return !IsEntropyBad(); +} + +//*** IncrementIv() +// This function increments the IV value by 1. It is used by EncryptDRBG(). +void IncrementIv(DRBG_IV* iv) +{ + BYTE* ivP = ((BYTE*)iv) + DRBG_IV_SIZE_BYTES; + while((--ivP >= (BYTE*)iv) && ((*ivP = ((*ivP + 1) & 0xFF)) == 0)) + ; +} + +//*** EncryptDRBG() +// This does the encryption operation for the DRBG. It will encrypt +// the input state counter (IV) using the state key. Into the output +// buffer for as many times as it takes to generate the required +// number of bytes. +static BOOL EncryptDRBG(BYTE* dOut, + UINT32 dOutBytes, + DRBG_KEY_SCHEDULE* keySchedule, + DRBG_IV* iv, + UINT32* lastValue // Points to the last output value +) +{ +#if FIPS_COMPLIANT + // For FIPS compliance, the DRBG has to do a continuous self-test to make sure that + // no two consecutive values are the same. This overhead is not incurred if the TPM + // is not required to be FIPS compliant + // + UINT32 temp[DRBG_IV_SIZE_BYTES / sizeof(UINT32)]; + int i; + BYTE* p; + + for(; dOutBytes > 0;) + { + // Increment the IV before each encryption (this is what makes this + // different from normal counter-mode encryption + IncrementIv(iv); + DRBG_ENCRYPT(keySchedule, iv, temp); +// Expect a 16 byte block +# if DRBG_IV_SIZE_BITS != 128 +# error "Unsuppored IV size in DRBG" +# endif + if((lastValue[0] == temp[0]) && (lastValue[1] == temp[1]) + && (lastValue[2] == temp[2]) && (lastValue[3] == temp[3])) + { + LOG_FAILURE(FATAL_ERROR_ENTROPY); + return FALSE; + } + lastValue[0] = temp[0]; + lastValue[1] = temp[1]; + lastValue[2] = temp[2]; + lastValue[3] = temp[3]; + i = MIN(dOutBytes, DRBG_IV_SIZE_BYTES); + dOutBytes -= i; + for(p = (BYTE*)temp; i > 0; i--) + *dOut++ = *p++; + } +#else // version without continuous self-test + NOT_REFERENCED(lastValue); + for(; dOutBytes >= DRBG_IV_SIZE_BYTES; + dOut = &dOut[DRBG_IV_SIZE_BYTES], dOutBytes -= DRBG_IV_SIZE_BYTES) + { + // Increment the IV + IncrementIv(iv); + DRBG_ENCRYPT(keySchedule, iv, dOut); + } + // If there is a partial, generate into a block-sized + // temp buffer and copy to the output. + if(dOutBytes != 0) + { + BYTE temp[DRBG_IV_SIZE_BYTES]; + // Increment the IV + IncrementIv(iv); + DRBG_ENCRYPT(keySchedule, iv, temp); + memcpy(dOut, temp, dOutBytes); + } +#endif + return TRUE; +} + +//*** DRBG_Update() +// This function performs the state update function. +// According to SP800-90A, a temp value is created by doing CTR mode +// encryption of 'providedData' and replacing the key and IV with +// these values. The one difference is that, with counter mode, the +// IV is incremented after each block is encrypted and in this +// operation, the counter is incremented before each block is +// encrypted. This function implements an 'optimized' version +// of the algorithm in that it does the update of the drbgState->seed +// in place and then 'providedData' is XORed into drbgState->seed +// to complete the encryption of 'providedData'. This works because +// the IV is the last thing that gets encrypted. +// +static BOOL DRBG_Update( + DRBG_STATE* drbgState, // IN:OUT state to update + DRBG_KEY_SCHEDULE* keySchedule, // IN: the key schedule (optional) + DRBG_SEED* providedData // IN: additional data +) +{ + UINT32 i; + BYTE* temp = (BYTE*)&drbgState->seed; + DRBG_KEY* key = pDRBG_KEY(&drbgState->seed); + DRBG_IV* iv = pDRBG_IV(&drbgState->seed); + DRBG_KEY_SCHEDULE localKeySchedule; + // + pAssert(drbgState->magic == DRBG_MAGIC); + + // If an key schedule was not provided, make one + if(keySchedule == NULL) + { + if(DRBG_ENCRYPT_SETUP((BYTE*)key, DRBG_KEY_SIZE_BITS, &localKeySchedule) != 0) + { + LOG_FAILURE(FATAL_ERROR_INTERNAL); + return FALSE; + } + keySchedule = &localKeySchedule; + } + // Encrypt the temp value + + EncryptDRBG(temp, sizeof(DRBG_SEED), keySchedule, iv, drbgState->lastValue); + if(providedData != NULL) + { + BYTE* pP = (BYTE*)providedData; + for(i = DRBG_SEED_SIZE_BYTES; i != 0; i--) + *temp++ ^= *pP++; + } + // Since temp points to the input key and IV, we are done and + // don't need to copy the resulting 'temp' to drbgState->seed + return TRUE; +} + +//*** DRBG_Reseed() +// This function is used when reseeding of the DRBG is required. If +// entropy is provided, it is used in lieu of using hardware entropy. +// Note: the provided entropy must be the required size. +// +// Return Type: BOOL +// TRUE(1) reseed succeeded +// FALSE(0) reseed failed, probably due to the entropy generation +BOOL DRBG_Reseed(DRBG_STATE* drbgState, // IN: the state to update + DRBG_SEED* providedEntropy, // IN: entropy + DRBG_SEED* additionalData // IN: +) +{ + DRBG_SEED seed; + + pAssert((drbgState != NULL) && (drbgState->magic == DRBG_MAGIC)); + + if(providedEntropy == NULL) + { + providedEntropy = &seed; + if(!DRBG_GetEntropy(sizeof(DRBG_SEED), (BYTE*)providedEntropy)) + return FALSE; + } + if(additionalData != NULL) + { + unsigned int i; + + // XOR the provided data into the provided entropy + for(i = 0; i < sizeof(DRBG_SEED); i++) + ((BYTE*)providedEntropy)[i] ^= ((BYTE*)additionalData)[i]; + } + DRBG_Update(drbgState, NULL, providedEntropy); + + drbgState->reseedCounter = 1; + + return TRUE; +} + +//*** DRBG_SelfTest() +// This is run when the DRBG is instantiated and at startup. +// +// Return Type: BOOL +// TRUE(1) test OK +// FALSE(0) test failed +BOOL DRBG_SelfTest(void) +{ + BYTE buf[sizeof(DRBG_NistTestVector_Generated)]; + DRBG_SEED seed; + UINT32 i; + BYTE* p; + DRBG_STATE testState; + // + pAssert(!IsSelfTest()); + + SetSelfTest(); + SetDrbgTested(); + // Do an instantiate + if(!DRBG_Instantiate(&testState, 0, NULL)) + return FALSE; +#if DRBG_DEBUG_PRINT + dbgDumpMemBlock( + pDRBG_KEY(&testState), DRBG_KEY_SIZE_BYTES, "Key after Instantiate"); + dbgDumpMemBlock( + pDRBG_IV(&testState), DRBG_IV_SIZE_BYTES, "Value after Instantiate"); +#endif + if(DRBG_Generate((RAND_STATE*)&testState, buf, sizeof(buf)) == 0) + return FALSE; +#if DRBG_DEBUG_PRINT + dbgDumpMemBlock( + pDRBG_KEY(&testState.seed), DRBG_KEY_SIZE_BYTES, "Key after 1st Generate"); + dbgDumpMemBlock( + pDRBG_IV(&testState.seed), DRBG_IV_SIZE_BYTES, "Value after 1st Generate"); +#endif + if(memcmp(buf, DRBG_NistTestVector_GeneratedInterm, sizeof(buf)) != 0) + return FALSE; + memcpy(seed.bytes, DRBG_NistTestVector_EntropyReseed, sizeof(seed)); + DRBG_Reseed(&testState, &seed, NULL); +#if DRBG_DEBUG_PRINT + dbgDumpMemBlock((BYTE*)pDRBG_KEY(&testState.seed), + DRBG_KEY_SIZE_BYTES, + "Key after 2nd Generate"); + dbgDumpMemBlock((BYTE*)pDRBG_IV(&testState.seed), + DRBG_IV_SIZE_BYTES, + "Value after 2nd Generate"); + dbgDumpMemBlock(buf, sizeof(buf), "2nd Generated"); +#endif + if(DRBG_Generate((RAND_STATE*)&testState, buf, sizeof(buf)) == 0) + return FALSE; + if(memcmp(buf, DRBG_NistTestVector_Generated, sizeof(buf)) != 0) + return FALSE; + ClearSelfTest(); + + DRBG_Uninstantiate(&testState); + for(p = (BYTE*)&testState, i = 0; i < sizeof(DRBG_STATE); i++) + { + if(*p++) + return FALSE; + } + // Simulate hardware failure to make sure that we get an error when + // trying to instantiate + SetEntropyBad(); + if(DRBG_Instantiate(&testState, 0, NULL)) + return FALSE; + ClearEntropyBad(); + + return TRUE; +} + +//** Public Interface +//*** Description +// The functions in this section are the interface to the RNG. These +// are the functions that are used by TPM.lib. + +//*** CryptRandomStir() +// This function is used to cause a reseed. A DRBG_SEED amount of entropy is +// collected from the hardware and then additional data is added. +// +// Return Type: TPM_RC +// TPM_RC_NO_RESULT failure of the entropy generator +LIB_EXPORT TPM_RC CryptRandomStir(UINT16 additionalDataSize, BYTE* additionalData) +{ +#if !USE_DEBUG_RNG + DRBG_SEED tmpBuf; + DRBG_SEED dfResult; + // + // All reseed with outside data starts with a buffer full of entropy + if(!DRBG_GetEntropy(sizeof(tmpBuf), (BYTE*)&tmpBuf)) + return TPM_RC_NO_RESULT; + + DRBG_Reseed(&drbgDefault, + &tmpBuf, + DfBuffer(&dfResult, additionalDataSize, additionalData)); + drbgDefault.reseedCounter = 1; + + return TPM_RC_SUCCESS; + +#else + // If doing debug, use the input data as the initial setting for the RNG state + // so that the test can be reset at any time. + // Note: If this is called with a data size of 0 or less, nothing happens. The + // presumption is that, in a debug environment, the caller will have specific + // values for initialization, so this check is just a simple way to prevent + // inadvertent programming errors from screwing things up. This doesn't use an + // pAssert() because the non-debug version of this function will accept these + // parameters as meaning that there is no additionalData and only hardware + // entropy is used. + if((additionalDataSize > 0) && (additionalData != NULL)) + { + memset(drbgDefault.seed.bytes, 0, sizeof(drbgDefault.seed.bytes)); + memcpy(drbgDefault.seed.bytes, + additionalData, + MIN(additionalDataSize, sizeof(drbgDefault.seed.bytes))); + } + drbgDefault.reseedCounter = 1; + + return TPM_RC_SUCCESS; +#endif +} + +//*** CryptRandomGenerate() +// Generate a 'randomSize' number or random bytes. +LIB_EXPORT UINT16 CryptRandomGenerate(UINT16 randomSize, BYTE* buffer) +{ + return DRBG_Generate((RAND_STATE*)&drbgDefault, buffer, randomSize); +} + +//*** DRBG_InstantiateSeededKdf() +// This function is used to instantiate a KDF-based RNG. This is used for derivations. +// This function always returns TRUE. +LIB_EXPORT BOOL DRBG_InstantiateSeededKdf( + KDF_STATE* state, // OUT: buffer to hold the state + TPM_ALG_ID hashAlg, // IN: hash algorithm + TPM_ALG_ID kdf, // IN: the KDF to use + TPM2B* seed, // IN: the seed to use + const TPM2B* label, // IN: a label for the generation process. + TPM2B* context, // IN: the context value + UINT32 limit // IN: Maximum number of bits from the KDF +) +{ + state->magic = KDF_MAGIC; + state->limit = limit; + state->seed = seed; + state->hash = hashAlg; + state->kdf = kdf; + state->label = label; + state->context = context; + state->digestSize = CryptHashGetDigestSize(hashAlg); + state->counter = 0; + state->residual.t.size = 0; + return TRUE; +} + +//*** DRBG_AdditionalData() +// Function to reseed the DRBG with additional entropy. This is normally called +// before computing the protection value of a primary key in the Endorsement +// hierarchy. +LIB_EXPORT void DRBG_AdditionalData(DRBG_STATE* drbgState, // IN:OUT state to update + TPM2B* additionalData // IN: value to incorporate +) +{ + DRBG_SEED dfResult; + if(drbgState->magic == DRBG_MAGIC) + { + DfBuffer(&dfResult, additionalData->size, additionalData->buffer); + DRBG_Reseed(drbgState, &dfResult, NULL); + } +} + +//*** DRBG_InstantiateSeeded() +// This function is used to instantiate a random number generator from seed values. +// The nominal use of this generator is to create sequences of pseudo-random +// numbers from a seed value. +// +// Return Type: TPM_RC +// TPM_RC_FAILURE DRBG self-test failure +LIB_EXPORT TPM_RC DRBG_InstantiateSeeded( + DRBG_STATE* drbgState, // IN/OUT: buffer to hold the state + const TPM2B* seed, // IN: the seed to use + const TPM2B* purpose, // IN: a label for the generation process. + const TPM2B* name, // IN: name of the object + const TPM2B* additional // IN: additional data +) +{ + DF_STATE dfState; + int totalInputSize; + // DRBG should have been tested, but... + if(!IsDrbgTested() && !DRBG_SelfTest()) + { + LOG_FAILURE(FATAL_ERROR_SELF_TEST); + return TPM_RC_FAILURE; + } + // Initialize the DRBG state + memset(drbgState, 0, sizeof(DRBG_STATE)); + drbgState->magic = DRBG_MAGIC; + + // Size all of the values + totalInputSize = (seed != NULL) ? seed->size : 0; + totalInputSize += (purpose != NULL) ? purpose->size : 0; + totalInputSize += (name != NULL) ? name->size : 0; + totalInputSize += (additional != NULL) ? additional->size : 0; + + // Initialize the derivation + DfStart(&dfState, totalInputSize); + + // Run all the input strings through the derivation function + if(seed != NULL) + DfUpdate(&dfState, seed->size, seed->buffer); + if(purpose != NULL) + DfUpdate(&dfState, purpose->size, purpose->buffer); + if(name != NULL) + DfUpdate(&dfState, name->size, name->buffer); + if(additional != NULL) + DfUpdate(&dfState, additional->size, additional->buffer); + + // Used the derivation function output as the "entropy" input. This is not + // how it is described in SP800-90A but this is the equivalent function + DRBG_Reseed(((DRBG_STATE*)drbgState), DfEnd(&dfState), NULL); + + return TPM_RC_SUCCESS; +} + +//*** CryptRandStartup() +// This function is called when TPM_Startup is executed. This function always returns +// TRUE. +LIB_EXPORT BOOL CryptRandStartup(void) +{ +#if !_DRBG_STATE_SAVE + // If not saved in NV, re-instantiate on each startup + return DRBG_Instantiate(&drbgDefault, 0, NULL); +#else + // If the running state is saved in NV, NV has to be loaded before it can + // be updated + if(go.drbgState.magic == DRBG_MAGIC) + return DRBG_Reseed(&go.drbgState, NULL, NULL); + else + return DRBG_Instantiate(&go.drbgState, 0, NULL); +#endif +} + +//*** CryptRandInit() +// This function is called when _TPM_Init is being processed. +// +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure +LIB_EXPORT BOOL CryptRandInit(void) +{ +#if !USE_DEBUG_RNG + _plat__GetEntropy(NULL, 0); +#endif + return DRBG_SelfTest(); +} + +//*** DRBG_Generate() +// This function generates a random sequence according SP800-90A. +// If 'random' is not NULL, then 'randomSize' bytes of random values are generated. +// If 'random' is NULL or 'randomSize' is zero, then the function returns +// zero without generating any bits or updating the reseed counter. +// This function returns the number of bytes produced which could be less than the +// number requested if the request is too large ("too large" is implementation +// dependent.) +LIB_EXPORT UINT16 DRBG_Generate( + RAND_STATE* state, + BYTE* random, // OUT: buffer to receive the random values + UINT16 randomSize // IN: the number of bytes to generate +) +{ + if(state == NULL) + state = (RAND_STATE*)&drbgDefault; + if(random == NULL) + return 0; + + // If the caller used a KDF state, generate a sequence from the KDF not to + // exceed the limit. + if(state->kdf.magic == KDF_MAGIC) + { + KDF_STATE* kdf = (KDF_STATE*)state; + UINT32 counter = (UINT32)kdf->counter; + INT32 bytesLeft = randomSize; + // + // If the number of bytes to be returned would put the generator + // over the limit, then return 0 + if((((kdf->counter * kdf->digestSize) + randomSize) * 8) > kdf->limit) + return 0; + // Process partial and full blocks until all requested bytes provided + while(bytesLeft > 0) + { + // If there is any residual data in the buffer, copy it to the output + // buffer + if(kdf->residual.t.size > 0) + { + INT32 size; + // + // Don't use more of the residual than will fit or more than are + // available + size = MIN(kdf->residual.t.size, bytesLeft); + + // Copy some or all of the residual to the output. The residual is + // at the end of the buffer. The residual might be a full buffer. + MemoryCopy( + random, + &kdf->residual.t.buffer[kdf->digestSize - kdf->residual.t.size], + size); + + // Advance the buffer pointer + random += size; + + // Reduce the number of bytes left to get + bytesLeft -= size; + + // And reduce the residual size appropriately + kdf->residual.t.size -= (UINT16)size; + } + else + { + UINT16 blocks = (UINT16)(bytesLeft / kdf->digestSize); + // + // Get the number of required full blocks + if(blocks > 0) + { + UINT16 size = blocks * kdf->digestSize; + // Get some number of full blocks and put them in the return buffer + CryptKDFa(kdf->hash, + kdf->seed, + kdf->label, + kdf->context, + NULL, + kdf->limit, + random, + &counter, + blocks); + + // reduce the size remaining to be moved and advance the pointer + bytesLeft -= size; + random += size; + } + else + { + // Fill the residual buffer with a full block and then loop to + // top to get part of it copied to the output. + kdf->residual.t.size = CryptKDFa(kdf->hash, + kdf->seed, + kdf->label, + kdf->context, + NULL, + kdf->limit, + kdf->residual.t.buffer, + &counter, + 1); + } + } + } + kdf->counter = counter; + return randomSize; + } + else if(state->drbg.magic == DRBG_MAGIC) + { + DRBG_STATE* drbgState = (DRBG_STATE*)state; + DRBG_KEY_SCHEDULE keySchedule; + DRBG_SEED* seed = &drbgState->seed; + + if(drbgState->reseedCounter >= CTR_DRBG_MAX_REQUESTS_PER_RESEED) + { + if(drbgState == &drbgDefault) + { + DRBG_Reseed(drbgState, NULL, NULL); + if(IsEntropyBad() && !IsSelfTest()) + return 0; + } + else + { + // If this is a PRNG then the only way to get + // here is if the SW has run away. + LOG_FAILURE(FATAL_ERROR_INTERNAL); + return 0; + } + } + // if the allowed number of bytes in a request is larger than the + // less than the number of bytes that can be requested, then check +#if UINT16_MAX >= CTR_DRBG_MAX_BYTES_PER_REQUEST + if(randomSize > CTR_DRBG_MAX_BYTES_PER_REQUEST) + randomSize = CTR_DRBG_MAX_BYTES_PER_REQUEST; +#endif + // Create encryption schedule + if(DRBG_ENCRYPT_SETUP( + (BYTE*)pDRBG_KEY(seed), DRBG_KEY_SIZE_BITS, &keySchedule) + != 0) + { + LOG_FAILURE(FATAL_ERROR_INTERNAL); + return 0; + } + // Generate the random data + EncryptDRBG( + random, randomSize, &keySchedule, pDRBG_IV(seed), drbgState->lastValue); + // Do a key update + DRBG_Update(drbgState, &keySchedule, NULL); + + // Increment the reseed counter + drbgState->reseedCounter += 1; + } + else + { + LOG_FAILURE(FATAL_ERROR_INTERNAL); + return FALSE; + } + return randomSize; +} + +//*** DRBG_Instantiate() +// This is CTR_DRBG_Instantiate_algorithm() from [SP 800-90A 10.2.1.3.1]. +// This is called when a the TPM DRBG is to be instantiated. This is +// called to instantiate a DRBG used by the TPM for normal +// operations. +// +// Return Type: BOOL +// TRUE(1) instantiation succeeded +// FALSE(0) instantiation failed +LIB_EXPORT BOOL DRBG_Instantiate( + DRBG_STATE* drbgState, // OUT: the instantiated value + UINT16 pSize, // IN: Size of personalization string + BYTE* personalization // IN: The personalization string +) +{ + DRBG_SEED seed; + DRBG_SEED dfResult; + // + pAssert((pSize == 0) || (pSize <= sizeof(seed)) || (personalization != NULL)); + // If the DRBG has not been tested, test when doing an instantiation. Since + // Instantiation is called during self test, make sure we don't get stuck in a + // loop. + if(!IsDrbgTested() && !IsSelfTest() && !DRBG_SelfTest()) + return FALSE; + // If doing a self test, DRBG_GetEntropy will return the NIST + // test vector value. + if(!DRBG_GetEntropy(sizeof(seed), (BYTE*)&seed)) + return FALSE; + // set everything to zero + memset(drbgState, 0, sizeof(DRBG_STATE)); + drbgState->magic = DRBG_MAGIC; + + // Steps 1, 2, 3, 6, 7 of SP 800-90A 10.2.1.3.1 are exactly what + // reseeding does. So, do a reduction on the personalization value (if any) + // and do a reseed. + DRBG_Reseed(drbgState, &seed, DfBuffer(&dfResult, pSize, personalization)); + + return TRUE; +} + +//*** DRBG_Uninstantiate() +// This is Uninstantiate_function() from [SP 800-90A 9.4]. +// +// Return Type: TPM_RC +// TPM_RC_VALUE not a valid state +LIB_EXPORT TPM_RC DRBG_Uninstantiate( + DRBG_STATE* drbgState // IN/OUT: working state to erase +) +{ + if((drbgState == NULL) || (drbgState->magic != DRBG_MAGIC)) + return TPM_RC_VALUE; + memset(drbgState, 0, sizeof(DRBG_STATE)); + return TPM_RC_SUCCESS; +} diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptRsa.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptRsa.c new file mode 100644 index 0000000..63b6227 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptRsa.c @@ -0,0 +1,1445 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// +// This file contains implementation of cryptographic primitives for RSA. +// Vendors may replace the implementation in this file with their own library +// functions. + +//** Includes +// Need this define to get the 'private' defines for this function +#define CRYPT_RSA_C +#include "Tpm.h" + +#if ALG_RSA + +//** Obligatory Initialization Functions + +//*** CryptRsaInit() +// Function called at _TPM_Init(). +BOOL CryptRsaInit(void) +{ + return TRUE; +} + +//*** CryptRsaStartup() +// Function called at TPM2_Startup() +BOOL CryptRsaStartup(void) +{ + return TRUE; +} + +//** Internal Functions + +//*** RsaInitializeExponent() +// This function initializes the bignum data structure that holds the private +// exponent. This function returns the pointer to the private exponent value so that +// it can be used in an initializer for a data declaration. +static privateExponent* RsaInitializeExponent(privateExponent* Z) +{ + bigNum* bn = (bigNum*)&Z->P; + int i; + // + for(i = 0; i < 5; i++) + { + bn[i] = (bigNum)&Z->entries[i]; + BnInit(bn[i], BYTES_TO_CRYPT_WORDS(sizeof(Z->entries[0].d))); + } + return Z; +} + +//*** MakePgreaterThanQ() +// This function swaps the pointers for P and Q if Q happens to be larger than Q. +static void MakePgreaterThanQ(privateExponent* Z) +{ + if(BnUnsignedCmp(Z->P, Z->Q) < 0) + { + bigNum bnT = Z->P; + Z->P = Z->Q; + Z->Q = bnT; + } +} + +//*** PackExponent() +// This function takes the bignum private exponent and converts it into TPM2B form. +// In this form, the size field contains the overall size of the packed data. The +// buffer contains 5, equal sized values in P, Q, dP, dQ, qInv order. For example, if +// a key has a 2Kb public key, then the packed private key will contain 5, 1Kb values. +// This form makes it relatively easy to load and save the values without changing +// the normal unmarshaling to do anything more than allow a larger TPM2B for the +// private key. Also, when exporting the value, all that is needed is to change the +// size field of the private key in order to save just the P value. +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure // The data is too big to fit +static BOOL PackExponent(TPM2B_PRIVATE_KEY_RSA* packed, privateExponent* Z) +{ + int i; + UINT16 primeSize = (UINT16)BITS_TO_BYTES(BnMsb(Z->P)); + UINT16 pS = primeSize; + // + pAssert((primeSize * 5) <= sizeof(packed->t.buffer)); + packed->t.size = (primeSize * 5) + RSA_prime_flag; + for(i = 0; i < 5; i++) + if(!BnToBytes((bigNum)&Z->entries[i], &packed->t.buffer[primeSize * i], &pS)) + return FALSE; + if(pS != primeSize) + return FALSE; + return TRUE; +} + +//*** UnpackExponent() +// This function unpacks the private exponent from its TPM2B form into its bignum +// form. +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) TPM2B is not the correct size +static BOOL UnpackExponent(TPM2B_PRIVATE_KEY_RSA* b, privateExponent* Z) +{ + UINT16 primeSize = b->t.size & ~RSA_prime_flag; + int i; + bigNum* bn = &Z->P; + // + VERIFY(b->t.size & RSA_prime_flag); + RsaInitializeExponent(Z); + VERIFY((primeSize % 5) == 0); + primeSize /= 5; + for(i = 0; i < 5; i++) + VERIFY(BnFromBytes(bn[i], &b->t.buffer[primeSize * i], primeSize) != NULL); + MakePgreaterThanQ(Z); + return TRUE; +Error: + return FALSE; +} + +//*** ComputePrivateExponent() +// This function computes the private exponent from the primes. +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure +static BOOL ComputePrivateExponent( + bigNum pubExp, // IN: the public exponent + privateExponent* Z // IN/OUT: on input, has primes P and Q. On + // output, has P, Q, dP, dQ, and pInv +) +{ + BOOL pOK; + BOOL qOK; + BN_PRIME(pT); + // + // make p the larger value so that m2 is always less than p + MakePgreaterThanQ(Z); + + //dP = (1/e) mod (p-1) + pOK = BnSubWord(pT, Z->P, 1); + pOK = pOK && BnModInverse(Z->dP, pubExp, pT); + //dQ = (1/e) mod (q-1) + qOK = BnSubWord(pT, Z->Q, 1); + qOK = qOK && BnModInverse(Z->dQ, pubExp, pT); + // qInv = (1/q) mod p + if(pOK && qOK) + pOK = qOK = BnModInverse(Z->qInv, Z->Q, Z->P); + if(!pOK) + BnSetWord(Z->P, 0); + if(!qOK) + BnSetWord(Z->Q, 0); + return pOK && qOK; +} + +//*** RsaPrivateKeyOp() +// This function is called to do the exponentiation with the private key. Compile +// options allow use of the simple (but slow) private exponent, or the more complex +// but faster CRT method. +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure +static BOOL RsaPrivateKeyOp(bigNum inOut, // IN/OUT: number to be exponentiated + privateExponent* Z) +{ + BN_RSA(M1); + BN_RSA(M2); + BN_RSA(M); + BN_RSA(H); + // + MakePgreaterThanQ(Z); + // m1 = cdP mod p + VERIFY(BnModExp(M1, inOut, Z->dP, Z->P)); + // m2 = cdQ mod q + VERIFY(BnModExp(M2, inOut, Z->dQ, Z->Q)); + // h = qInv * (m1 - m2) mod p = qInv * (m1 + P - m2) mod P because Q < P + // so m2 < P + VERIFY(BnSub(H, Z->P, M2)); + VERIFY(BnAdd(H, H, M1)); + VERIFY(BnModMult(H, H, Z->qInv, Z->P)); + // m = m2 + h * q + VERIFY(BnMult(M, H, Z->Q)); + VERIFY(BnAdd(inOut, M2, M)); + return TRUE; +Error: + return FALSE; +} + +//*** RSAEP() +// This function performs the RSAEP operation defined in PKCS#1v2.1. It is +// an exponentiation of a value ('m') with the public exponent ('e'), modulo +// the public ('n'). +// +// Return Type: TPM_RC +// TPM_RC_VALUE number to exponentiate is larger than the modulus +// +static TPM_RC RSAEP(TPM2B* dInOut, // IN: size of the encrypted block and the size of + // the encrypted value. It must be the size of + // the modulus. + // OUT: the encrypted data. Will receive the + // decrypted value + OBJECT* key // IN: the key to use +) +{ + TPM2B_TYPE(4BYTES, 4); + TPM2B_4BYTES e2B; + UINT32 e = key->publicArea.parameters.rsaDetail.exponent; + // + if(e == 0) + e = RSA_DEFAULT_PUBLIC_EXPONENT; + UINT32_TO_BYTE_ARRAY(e, e2B.t.buffer); + e2B.t.size = 4; + return ModExpB(dInOut->size, + dInOut->buffer, + dInOut->size, + dInOut->buffer, + e2B.t.size, + e2B.t.buffer, + key->publicArea.unique.rsa.t.size, + key->publicArea.unique.rsa.t.buffer); +} + +//*** RSADP() +// This function performs the RSADP operation defined in PKCS#1v2.1. It is +// an exponentiation of a value ('c') with the private exponent ('d'), modulo +// the public modulus ('n'). The decryption is in place. +// +// This function also checks the size of the private key. If the size indicates +// that only a prime value is present, the key is converted to being a private +// exponent. +// +// Return Type: TPM_RC +// TPM_RC_SIZE the value to decrypt is larger than the modulus +// +static TPM_RC RSADP(TPM2B* inOut, // IN/OUT: the value to encrypt + OBJECT* key // IN: the key +) +{ + BN_RSA_INITIALIZED(bnM, inOut); + NEW_PRIVATE_EXPONENT(Z); + if(UnsignedCompareB(inOut->size, + inOut->buffer, + key->publicArea.unique.rsa.t.size, + key->publicArea.unique.rsa.t.buffer) + >= 0) + return TPM_RC_SIZE; + // private key operation requires that private exponent be loaded + // During self-test, this might not be the case so load it up if it hasn't + // already done + // been done + if((key->sensitive.sensitive.rsa.t.size & RSA_prime_flag) == 0) + { + if(CryptRsaLoadPrivateExponent(&key->publicArea, &key->sensitive) + != TPM_RC_SUCCESS) + return TPM_RC_BINDING; + } + VERIFY(UnpackExponent(&key->sensitive.sensitive.rsa, Z)); + VERIFY(RsaPrivateKeyOp(bnM, Z)); + VERIFY(BnTo2B(bnM, inOut, inOut->size)); + return TPM_RC_SUCCESS; +Error: + return TPM_RC_FAILURE; +} + +//*** OaepEncode() +// This function performs OAEP padding. The size of the buffer to receive the +// OAEP padded data must equal the size of the modulus +// +// Return Type: TPM_RC +// TPM_RC_VALUE 'hashAlg' is not valid or message size is too large +// +static TPM_RC OaepEncode( + TPM2B* padded, // OUT: the pad data + TPM_ALG_ID hashAlg, // IN: algorithm to use for padding + const TPM2B* label, // IN: null-terminated string (may be NULL) + TPM2B* message, // IN: the message being padded + RAND_STATE* rand // IN: the random number generator to use +) +{ + INT32 padLen; + INT32 dbSize; + INT32 i; + BYTE mySeed[MAX_DIGEST_SIZE]; + BYTE* seed = mySeed; + UINT16 hLen = CryptHashGetDigestSize(hashAlg); + BYTE mask[MAX_RSA_KEY_BYTES]; + BYTE* pp; + BYTE* pm; + TPM_RC retVal = TPM_RC_SUCCESS; + + pAssert(padded != NULL && message != NULL); + + // A value of zero is not allowed because the KDF can't produce a result + // if the digest size is zero. + if(hLen == 0) + return TPM_RC_VALUE; + + // Basic size checks + // make sure digest isn't too big for key size + if(padded->size < (2 * hLen) + 2) + ERROR_RETURN(TPM_RC_HASH); + + // and that message will fit messageSize <= k - 2hLen - 2 + if(message->size > (padded->size - (2 * hLen) - 2)) + ERROR_RETURN(TPM_RC_VALUE); + + // Hash L even if it is null + // Offset into padded leaving room for masked seed and byte of zero + pp = &padded->buffer[hLen + 1]; + if(CryptHashBlock(hashAlg, label->size, (BYTE*)label->buffer, hLen, pp) != hLen) + ERROR_RETURN(TPM_RC_FAILURE); + + // concatenate PS of k mLen 2hLen 2 + padLen = padded->size - message->size - (2 * hLen) - 2; + MemorySet(&pp[hLen], 0, padLen); + pp[hLen + padLen] = 0x01; + padLen += 1; + memcpy(&pp[hLen + padLen], message->buffer, message->size); + + // The total size of db = hLen + pad + mSize; + dbSize = hLen + padLen + message->size; + + // If testing, then use the provided seed. Otherwise, use values + // from the RNG + CryptRandomGenerate(hLen, mySeed); + DRBG_Generate(rand, mySeed, (UINT16)hLen); + if(g_inFailureMode) + ERROR_RETURN(TPM_RC_FAILURE); + // mask = MGF1 (seed, nSize hLen 1) + CryptMGF_KDF(dbSize, mask, hashAlg, hLen, seed, 0); + + // Create the masked db + pm = mask; + for(i = dbSize; i > 0; i--) + *pp++ ^= *pm++; + pp = &padded->buffer[hLen + 1]; + + // Run the masked data through MGF1 + if(CryptMGF_KDF(hLen, &padded->buffer[1], hashAlg, dbSize, pp, 0) + != (unsigned)hLen) + ERROR_RETURN(TPM_RC_VALUE); + // Now XOR the seed to create masked seed + pp = &padded->buffer[1]; + pm = seed; + for(i = hLen; i > 0; i--) + *pp++ ^= *pm++; + // Set the first byte to zero + padded->buffer[0] = 0x00; +Exit: + return retVal; +} + +//*** OaepDecode() +// This function performs OAEP padding checking. The size of the buffer to receive +// the recovered data. If the padding is not valid, the 'dSize' size is set to zero +// and the function returns TPM_RC_VALUE. +// +// The 'dSize' parameter is used as an input to indicate the size available in the +// buffer. + +// If insufficient space is available, the size is not changed and the return code +// is TPM_RC_VALUE. +// +// Return Type: TPM_RC +// TPM_RC_VALUE the value to decode was larger than the modulus, or +// the padding is wrong or the buffer to receive the +// results is too small +// +// +static TPM_RC OaepDecode( + TPM2B* dataOut, // OUT: the recovered data + TPM_ALG_ID hashAlg, // IN: algorithm to use for padding + const TPM2B* label, // IN: null-terminated string (may be NULL) + TPM2B* padded // IN: the padded data +) +{ + UINT32 i; + BYTE seedMask[MAX_DIGEST_SIZE]; + UINT32 hLen = CryptHashGetDigestSize(hashAlg); + + BYTE mask[MAX_RSA_KEY_BYTES]; + BYTE* pp; + BYTE* pm; + TPM_RC retVal = TPM_RC_SUCCESS; + + // Strange size (anything smaller can't be an OAEP padded block) + // Also check for no leading 0 + if((padded->size < (unsigned)((2 * hLen) + 2)) || (padded->buffer[0] != 0)) + ERROR_RETURN(TPM_RC_VALUE); + // Use the hash size to determine what to put through MGF1 in order + // to recover the seedMask + CryptMGF_KDF(hLen, + seedMask, + hashAlg, + padded->size - hLen - 1, + &padded->buffer[hLen + 1], + 0); + + // Recover the seed into seedMask + pAssert(hLen <= sizeof(seedMask)); + pp = &padded->buffer[1]; + pm = seedMask; + for(i = hLen; i > 0; i--) + *pm++ ^= *pp++; + + // Use the seed to generate the data mask + CryptMGF_KDF(padded->size - hLen - 1, mask, hashAlg, hLen, seedMask, 0); + + // Use the mask generated from seed to recover the padded data + pp = &padded->buffer[hLen + 1]; + pm = mask; + for(i = (padded->size - hLen - 1); i > 0; i--) + *pm++ ^= *pp++; + + // Make sure that the recovered data has the hash of the label + // Put trial value in the seed mask + if((CryptHashBlock(hashAlg, label->size, (BYTE*)label->buffer, hLen, seedMask)) + != hLen) + FAIL(FATAL_ERROR_INTERNAL); + if(memcmp(seedMask, mask, hLen) != 0) + ERROR_RETURN(TPM_RC_VALUE); + + // find the start of the data + pm = &mask[hLen]; + for(i = (UINT32)padded->size - (2 * hLen) - 1; i > 0; i--) + { + if(*pm++ != 0) + break; + } + // If we ran out of data or didn't end with 0x01, then return an error + if(i == 0 || pm[-1] != 0x01) + ERROR_RETURN(TPM_RC_VALUE); + + // pm should be pointing at the first part of the data + // and i is one greater than the number of bytes to move + i--; + if(i > dataOut->size) + // Special exit to preserve the size of the output buffer + return TPM_RC_VALUE; + memcpy(dataOut->buffer, pm, i); + dataOut->size = (UINT16)i; +Exit: + if(retVal != TPM_RC_SUCCESS) + dataOut->size = 0; + return retVal; +} + +//*** PKCS1v1_5Encode() +// This function performs the encoding for RSAES-PKCS1-V1_5-ENCRYPT as defined in +// PKCS#1V2.1 +// Return Type: TPM_RC +// TPM_RC_VALUE message size is too large +// +static TPM_RC RSAES_PKCS1v1_5Encode(TPM2B* padded, // OUT: the pad data + TPM2B* message, // IN: the message being padded + RAND_STATE* rand) +{ + UINT32 ps = padded->size - message->size - 3; + // + if(message->size > padded->size - 11) + return TPM_RC_VALUE; + // move the message to the end of the buffer + memcpy(&padded->buffer[padded->size - message->size], + message->buffer, + message->size); + // Set the first byte to 0x00 and the second to 0x02 + padded->buffer[0] = 0; + padded->buffer[1] = 2; + + // Fill with random bytes + DRBG_Generate(rand, &padded->buffer[2], (UINT16)ps); + if(g_inFailureMode) + return TPM_RC_FAILURE; + + // Set the delimiter for the random field to 0 + padded->buffer[2 + ps] = 0; + + // Now, the only messy part. Make sure that all the 'ps' bytes are non-zero + // In this implementation, use the value of the current index + for(ps++; ps > 1; ps--) + { + if(padded->buffer[ps] == 0) + padded->buffer[ps] = 0x55; // In the < 0.5% of the cases that the + // random value is 0, just pick a value to + // put into the spot. + } + return TPM_RC_SUCCESS; +} + +//*** RSAES_Decode() +// This function performs the decoding for RSAES-PKCS1-V1_5-ENCRYPT as defined in +// PKCS#1V2.1 +// +// Return Type: TPM_RC +// TPM_RC_FAIL decoding error or results would no fit into provided buffer +// +static TPM_RC RSAES_Decode(TPM2B* message, // OUT: the recovered message + TPM2B* coded // IN: the encoded message +) +{ + BOOL fail = FALSE; + UINT16 pSize; + + fail = (coded->size < 11); + fail = (coded->buffer[0] != 0x00) | fail; + fail = (coded->buffer[1] != 0x02) | fail; + for(pSize = 2; pSize < coded->size; pSize++) + { + if(coded->buffer[pSize] == 0) + break; + } + pSize++; + + // Make sure that pSize has not gone over the end and that there are at least 8 + // bytes of pad data. + fail = (pSize > coded->size) | fail; + fail = ((pSize - 2) <= 8) | fail; + if((message->size < (UINT16)(coded->size - pSize)) || fail) + return TPM_RC_VALUE; + message->size = coded->size - pSize; + memcpy(message->buffer, &coded->buffer[pSize], coded->size - pSize); + return TPM_RC_SUCCESS; +} + +//*** CryptRsaPssSaltSize() +// This function computes the salt size used in PSS. It is broken out so that +// the X509 code can get the same value that is used by the encoding function in this +// module. +INT16 +CryptRsaPssSaltSize(INT16 hashSize, INT16 outSize) +{ + INT16 saltSize; + // + // (Mask Length) = (outSize - hashSize - 1); + // Max saltSize is (Mask Length) - 1 + saltSize = (outSize - hashSize - 1) - 1; + // Use the maximum salt size allowed by FIPS 186-4 + if(saltSize > hashSize) + saltSize = hashSize; + else if(saltSize < 0) + saltSize = 0; + return saltSize; +} + +//*** PssEncode() +// This function creates an encoded block of data that is the size of modulus. +// The function uses the maximum salt size that will fit in the encoded block. +// +// Returns TPM_RC_SUCCESS or goes into failure mode. +static TPM_RC PssEncode(TPM2B* out, // OUT: the encoded buffer + TPM_ALG_ID hashAlg, // IN: hash algorithm for the encoding + TPM2B* digest, // IN: the digest + RAND_STATE* rand // IN: random number source +) +{ + UINT32 hLen = CryptHashGetDigestSize(hashAlg); + BYTE salt[MAX_RSA_KEY_BYTES - 1]; + UINT16 saltSize; + BYTE* ps = salt; + BYTE* pOut; + UINT16 mLen; + HASH_STATE hashState; + + // These are fatal errors indicating bad TPM firmware + pAssert(out != NULL && hLen > 0 && digest != NULL); + + // Get the size of the mask + mLen = (UINT16)(out->size - hLen - 1); + + // Set the salt size + saltSize = CryptRsaPssSaltSize((INT16)hLen, (INT16)out->size); + + //using eOut for scratch space + // Set the first 8 bytes to zero + pOut = out->buffer; + memset(pOut, 0, 8); + + // Get set the salt + DRBG_Generate(rand, salt, saltSize); + if(g_inFailureMode) + return TPM_RC_FAILURE; + + // Create the hash of the pad || input hash || salt + CryptHashStart(&hashState, hashAlg); + CryptDigestUpdate(&hashState, 8, pOut); + CryptDigestUpdate2B(&hashState, digest); + CryptDigestUpdate(&hashState, saltSize, salt); + CryptHashEnd(&hashState, hLen, &pOut[out->size - hLen - 1]); + + // Create a mask + if(CryptMGF_KDF(mLen, pOut, hashAlg, hLen, &pOut[mLen], 0) != mLen) + FAIL(FATAL_ERROR_INTERNAL); + + // Since this implementation uses key sizes that are all even multiples of + // 8, just need to make sure that the most significant bit is CLEAR + *pOut &= 0x7f; + + // Before we mess up the pOut value, set the last byte to 0xbc + pOut[out->size - 1] = 0xbc; + + // XOR a byte of 0x01 at the position just before where the salt will be XOR'ed + pOut = &pOut[mLen - saltSize - 1]; + *pOut++ ^= 0x01; + + // XOR the salt data into the buffer + for(; saltSize > 0; saltSize--) + *pOut++ ^= *ps++; + + // and we are done + return TPM_RC_SUCCESS; +} + +//*** PssDecode() +// This function checks that the PSS encoded block was built from the +// provided digest. If the check is successful, TPM_RC_SUCCESS is returned. +// Any other value indicates an error. +// +// This implementation of PSS decoding is intended for the reference TPM +// implementation and is not at all generalized. It is used to check +// signatures over hashes and assumptions are made about the sizes of values. +// Those assumptions are enforce by this implementation. +// This implementation does allow for a variable size salt value to have been +// used by the creator of the signature. +// +// Return Type: TPM_RC +// TPM_RC_SCHEME 'hashAlg' is not a supported hash algorithm +// TPM_RC_VALUE decode operation failed +// +static TPM_RC PssDecode( + TPM_ALG_ID hashAlg, // IN: hash algorithm to use for the encoding + TPM2B* dIn, // In: the digest to compare + TPM2B* eIn // IN: the encoded data +) +{ + UINT32 hLen = CryptHashGetDigestSize(hashAlg); + BYTE mask[MAX_RSA_KEY_BYTES]; + BYTE* pm = mask; + BYTE* pe; + BYTE pad[8] = {0}; + UINT32 i; + UINT32 mLen; + BYTE fail; + TPM_RC retVal = TPM_RC_SUCCESS; + HASH_STATE hashState; + + // These errors are indicative of failures due to programmer error + pAssert(dIn != NULL && eIn != NULL); + pe = eIn->buffer; + + // check the hash scheme + if(hLen == 0) + ERROR_RETURN(TPM_RC_SCHEME); + + // most significant bit must be zero + fail = pe[0] & 0x80; + + // last byte must be 0xbc + fail |= pe[eIn->size - 1] ^ 0xbc; + + // Use the hLen bytes at the end of the buffer to generate a mask + // Doesn't start at the end which is a flag byte + mLen = eIn->size - hLen - 1; + CryptMGF_KDF(mLen, mask, hashAlg, hLen, &pe[mLen], 0); + + // Clear the MSO of the mask to make it consistent with the encoding. + mask[0] &= 0x7F; + + pAssert(mLen <= sizeof(mask)); + // XOR the data into the mask to recover the salt. This sequence + // advances eIn so that it will end up pointing to the seed data + // which is the hash of the signature data + for(i = mLen; i > 0; i--) + *pm++ ^= *pe++; + + // Find the first byte of 0x01 after a string of all 0x00 + for(pm = mask, i = mLen; i > 0; i--) + { + if(*pm == 0x01) + break; + else + fail |= *pm++; + } + // i should not be zero + fail |= (i == 0); + + // if we have failed, will continue using the entire mask as the salt value so + // that the timing attacks will not disclose anything (I don't think that this + // is a problem for TPM applications but, usually, we don't fail so this + // doesn't cost anything). + if(fail) + { + i = mLen; + pm = mask; + } + else + { + pm++; + i--; + } + // i contains the salt size and pm points to the salt. Going to use the input + // hash and the seed to recreate the hash in the lower portion of eIn. + CryptHashStart(&hashState, hashAlg); + + // add the pad of 8 zeros + CryptDigestUpdate(&hashState, 8, pad); + + // add the provided digest value + CryptDigestUpdate(&hashState, dIn->size, dIn->buffer); + + // and the salt + CryptDigestUpdate(&hashState, i, pm); + + // get the result + fail |= (CryptHashEnd(&hashState, hLen, mask) != hLen); + + // Compare all bytes + for(pm = mask; hLen > 0; hLen--) + // don't use fail = because that could skip the increment and compare + // operations after the first failure and that gives away timing + // information. + fail |= *pm++ ^ *pe++; + + retVal = (fail != 0) ? TPM_RC_VALUE : TPM_RC_SUCCESS; +Exit: + return retVal; +} + +//*** MakeDerTag() +// Construct the DER value that is used in RSASSA +// Return Type: INT16 +// > 0 size of value +// <= 0 no hash exists +INT16 +MakeDerTag(TPM_ALG_ID hashAlg, INT16 sizeOfBuffer, BYTE* buffer) +{ + // 0x30, 0x31, // SEQUENCE (2 elements) 1st + // 0x30, 0x0D, // SEQUENCE (2 elements) + // 0x06, 0x09, // HASH OID + // 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, + // 0x05, 0x00, // NULL + // 0x04, 0x20 // OCTET STRING + HASH_DEF* info = CryptGetHashDef(hashAlg); + INT16 oidSize; + // If no OID, can't do encode + VERIFY(info != NULL); + oidSize = 2 + (info->OID)[1]; + // make sure this fits in the buffer + VERIFY(sizeOfBuffer >= (oidSize + 8)); + *buffer++ = 0x30; // 1st SEQUENCE + // Size of the 1st SEQUENCE is 6 bytes + size of the hash OID + size of the + // digest size + *buffer++ = (BYTE)(6 + oidSize + info->digestSize); // + *buffer++ = 0x30; // 2nd SEQUENCE + // size is 4 bytes of overhead plus the side of the OID + *buffer++ = (BYTE)(2 + oidSize); + MemoryCopy(buffer, info->OID, oidSize); + buffer += oidSize; + *buffer++ = 0x05; // Add a NULL + *buffer++ = 0x00; + + *buffer++ = 0x04; + *buffer++ = (BYTE)(info->digestSize); + return oidSize + 8; +Error: + return 0; +} + +//*** RSASSA_Encode() +// Encode a message using PKCS1v1.5 method. +// +// Return Type: TPM_RC +// TPM_RC_SCHEME 'hashAlg' is not a supported hash algorithm +// TPM_RC_SIZE 'eOutSize' is not large enough +// TPM_RC_VALUE 'hInSize' does not match the digest size of hashAlg +static TPM_RC RSASSA_Encode(TPM2B* pOut, // IN:OUT on in, the size of the public key + // on out, the encoded area + TPM_ALG_ID hashAlg, // IN: hash algorithm for PKCS1v1_5 + TPM2B* hIn // IN: digest value to encode +) +{ + BYTE DER[20]; + BYTE* der = DER; + INT32 derSize = MakeDerTag(hashAlg, sizeof(DER), DER); + BYTE* eOut; + INT32 fillSize; + TPM_RC retVal = TPM_RC_SUCCESS; + + // Can't use this scheme if the algorithm doesn't have a DER string defined. + if(derSize == 0) + ERROR_RETURN(TPM_RC_SCHEME); + + // If the digest size of 'hashAl' doesn't match the input digest size, then + // the DER will misidentify the digest so return an error + if(CryptHashGetDigestSize(hashAlg) != hIn->size) + ERROR_RETURN(TPM_RC_VALUE); + fillSize = pOut->size - derSize - hIn->size - 3; + eOut = pOut->buffer; + + // Make sure that this combination will fit in the provided space + if(fillSize < 8) + ERROR_RETURN(TPM_RC_SIZE); + + // Start filling + *eOut++ = 0; // initial byte of zero + *eOut++ = 1; // byte of 0x01 + for(; fillSize > 0; fillSize--) + *eOut++ = 0xff; // bunch of 0xff + *eOut++ = 0; // another 0 + for(; derSize > 0; derSize--) + *eOut++ = *der++; // copy the DER + der = hIn->buffer; + for(fillSize = hIn->size; fillSize > 0; fillSize--) + *eOut++ = *der++; // copy the hash +Exit: + return retVal; +} + +//*** RSASSA_Decode() +// This function performs the RSASSA decoding of a signature. +// +// Return Type: TPM_RC +// TPM_RC_VALUE decode unsuccessful +// TPM_RC_SCHEME 'haslAlg' is not supported +// +static TPM_RC RSASSA_Decode( + TPM_ALG_ID hashAlg, // IN: hash algorithm to use for the encoding + TPM2B* hIn, // In: the digest to compare + TPM2B* eIn // IN: the encoded data +) +{ + BYTE fail; + BYTE DER[20]; + BYTE* der = DER; + INT32 derSize = MakeDerTag(hashAlg, sizeof(DER), DER); + BYTE* pe; + INT32 hashSize = CryptHashGetDigestSize(hashAlg); + INT32 fillSize; + TPM_RC retVal; + BYTE* digest; + UINT16 digestSize; + + pAssert(hIn != NULL && eIn != NULL); + pe = eIn->buffer; + + // Can't use this scheme if the algorithm doesn't have a DER string + // defined or if the provided hash isn't the right size + if(derSize == 0 || (unsigned)hashSize != hIn->size) + ERROR_RETURN(TPM_RC_SCHEME); + + // Make sure that this combination will fit in the provided space + // Since no data movement takes place, can just walk though this + // and accept nearly random values. This can only be called from + // CryptValidateSignature() so eInSize is known to be in range. + fillSize = eIn->size - derSize - hashSize - 3; + + // Start checking (fail will become non-zero if any of the bytes do not have + // the expected value. + fail = *pe++; // initial byte of zero + fail |= *pe++ ^ 1; // byte of 0x01 + for(; fillSize > 0; fillSize--) + fail |= *pe++ ^ 0xff; // bunch of 0xff + fail |= *pe++; // another 0 + for(; derSize > 0; derSize--) + fail |= *pe++ ^ *der++; // match the DER + digestSize = hIn->size; + digest = hIn->buffer; + for(; digestSize > 0; digestSize--) + fail |= *pe++ ^ *digest++; // match the hash + retVal = (fail != 0) ? TPM_RC_VALUE : TPM_RC_SUCCESS; +Exit: + return retVal; +} + +//** Externally Accessible Functions + +//*** CryptRsaSelectScheme() +// This function is used by TPM2_RSA_Decrypt and TPM2_RSA_Encrypt. It sets up +// the rules to select a scheme between input and object default. +// This function assume the RSA object is loaded. +// If a default scheme is defined in object, the default scheme should be chosen, +// otherwise, the input scheme should be chosen. +// In the case that both the object and 'scheme' are not TPM_ALG_NULL, then +// if the schemes are the same, the input scheme will be chosen. +// if the scheme are not compatible, a NULL pointer will be returned. +// +// The return pointer may point to a TPM_ALG_NULL scheme. +TPMT_RSA_DECRYPT* CryptRsaSelectScheme( + TPMI_DH_OBJECT rsaHandle, // IN: handle of an RSA key + TPMT_RSA_DECRYPT* scheme // IN: a sign or decrypt scheme +) +{ + OBJECT* rsaObject; + TPMT_ASYM_SCHEME* keyScheme; + TPMT_RSA_DECRYPT* retVal = NULL; + + // Get sign object pointer + rsaObject = HandleToObject(rsaHandle); + keyScheme = &rsaObject->publicArea.parameters.asymDetail.scheme; + + // if the default scheme of the object is TPM_ALG_NULL, then select the + // input scheme + if(keyScheme->scheme == TPM_ALG_NULL) + { + retVal = scheme; + } + // if the object scheme is not TPM_ALG_NULL and the input scheme is + // TPM_ALG_NULL, then select the default scheme of the object. + else if(scheme->scheme == TPM_ALG_NULL) + { + // if input scheme is NULL + retVal = (TPMT_RSA_DECRYPT*)keyScheme; + } + // get here if both the object scheme and the input scheme are + // not TPM_ALG_NULL. Need to insure that they are the same. + // IMPLEMENTATION NOTE: This could cause problems if future versions have + // schemes that have more values than just a hash algorithm. A new function + // (IsSchemeSame()) might be needed then. + else if(keyScheme->scheme == scheme->scheme + && keyScheme->details.anySig.hashAlg == scheme->details.anySig.hashAlg) + { + retVal = scheme; + } + // two different, incompatible schemes specified will return NULL + return retVal; +} + +//*** CryptRsaLoadPrivateExponent() +// This function is called to generate the private exponent of an RSA key. +// Return Type: TPM_RC +// TPM_RC_BINDING public and private parts of 'rsaKey' are not matched +TPM_RC +CryptRsaLoadPrivateExponent(TPMT_PUBLIC* publicArea, TPMT_SENSITIVE* sensitive) +{ + // + if((sensitive->sensitive.rsa.t.size & RSA_prime_flag) == 0) + { + if((sensitive->sensitive.rsa.t.size * 2) == publicArea->unique.rsa.t.size) + { + NEW_PRIVATE_EXPONENT(Z); + BN_RSA_INITIALIZED(bnN, &publicArea->unique.rsa); + BN_RSA(bnQr); + BN_VAR(bnE, RADIX_BITS); + + TEST(TPM_ALG_NULL); + + VERIFY((sensitive->sensitive.rsa.t.size * 2) + == publicArea->unique.rsa.t.size); + // Initialize the exponent + BnSetWord(bnE, publicArea->parameters.rsaDetail.exponent); + if(BnEqualZero(bnE)) + BnSetWord(bnE, RSA_DEFAULT_PUBLIC_EXPONENT); + // Convert first prime to 2B + VERIFY(BnFrom2B(Z->P, &sensitive->sensitive.rsa.b) != NULL); + + // Find the second prime by division. This uses 'bQ' rather than Z->Q + // because the division could make the quotient larger than a prime during + // some intermediate step. + VERIFY(BnDiv(Z->Q, bnQr, bnN, Z->P)); + VERIFY(BnEqualZero(bnQr)); + // Compute the private exponent and return it if found + VERIFY(ComputePrivateExponent(bnE, Z)); + VERIFY(PackExponent(&sensitive->sensitive.rsa, Z)); + } + else + VERIFY(((sensitive->sensitive.rsa.t.size / 5) * 2) + == publicArea->unique.rsa.t.size); + sensitive->sensitive.rsa.t.size |= RSA_prime_flag; + } + return TPM_RC_SUCCESS; +Error: + return TPM_RC_BINDING; +} + +//*** CryptRsaEncrypt() +// This is the entry point for encryption using RSA. Encryption is +// use of the public exponent. The padding parameter determines what +// padding will be used. +// +// The 'cOutSize' parameter must be at least as large as the size of the key. +// +// If the padding is RSA_PAD_NONE, 'dIn' is treated as a number. It must be +// lower in value than the key modulus. +// NOTE: If dIn has fewer bytes than cOut, then we don't add low-order zeros to +// dIn to make it the size of the RSA key for the call to RSAEP. This is +// because the high order bytes of dIn might have a numeric value that is +// greater than the value of the key modulus. If this had low-order zeros +// added, it would have a numeric value larger than the modulus even though +// it started out with a lower numeric value. +// +// Return Type: TPM_RC +// TPM_RC_VALUE 'cOutSize' is too small (must be the size +// of the modulus) +// TPM_RC_SCHEME 'padType' is not a supported scheme +// +LIB_EXPORT TPM_RC CryptRsaEncrypt( + TPM2B_PUBLIC_KEY_RSA* cOut, // OUT: the encrypted data + TPM2B* dIn, // IN: the data to encrypt + OBJECT* key, // IN: the key used for encryption + TPMT_RSA_DECRYPT* scheme, // IN: the type of padding and hash + // if needed + const TPM2B* label, // IN: in case it is needed + RAND_STATE* rand // IN: random number generator + // state (mostly for testing) +) +{ + TPM_RC retVal = TPM_RC_SUCCESS; + TPM2B_PUBLIC_KEY_RSA dataIn; + // + // if the input and output buffers are the same, copy the input to a scratch + // buffer so that things don't get messed up. + if(dIn == &cOut->b) + { + MemoryCopy2B(&dataIn.b, dIn, sizeof(dataIn.t.buffer)); + dIn = &dataIn.b; + } + // All encryption schemes return the same size of data + cOut->t.size = key->publicArea.unique.rsa.t.size; + TEST(scheme->scheme); + + switch(scheme->scheme) + { + case TPM_ALG_NULL: // 'raw' encryption + { + INT32 i; + INT32 dSize = dIn->size; + // dIn can have more bytes than cOut as long as the extra bytes + // are zero. Note: the more significant bytes of a number in a byte + // buffer are the bytes at the start of the array. + for(i = 0; (i < dSize) && (dIn->buffer[i] == 0); i++) + ; + dSize -= i; + if(dSize > cOut->t.size) + ERROR_RETURN(TPM_RC_VALUE); + // Pad cOut with zeros if dIn is smaller + memset(cOut->t.buffer, 0, cOut->t.size - dSize); + // And copy the rest of the value + memcpy(&cOut->t.buffer[cOut->t.size - dSize], &dIn->buffer[i], dSize); + + // If the size of dIn is the same as cOut dIn could be larger than + // the modulus. If it is, then RSAEP() will catch it. + } + break; + case TPM_ALG_RSAES: + retVal = RSAES_PKCS1v1_5Encode(&cOut->b, dIn, rand); + break; + case TPM_ALG_OAEP: + retVal = + OaepEncode(&cOut->b, scheme->details.oaep.hashAlg, label, dIn, rand); + break; + default: + ERROR_RETURN(TPM_RC_SCHEME); + break; + } + // All the schemes that do padding will come here for the encryption step + // Check that the Encoding worked + if(retVal == TPM_RC_SUCCESS) + // Padding OK so do the encryption + retVal = RSAEP(&cOut->b, key); +Exit: + return retVal; +} + +//*** CryptRsaDecrypt() +// This is the entry point for decryption using RSA. Decryption is +// use of the private exponent. The 'padType' parameter determines what +// padding was used. +// +// Return Type: TPM_RC +// TPM_RC_SIZE 'cInSize' is not the same as the size of the public +// modulus of 'key'; or numeric value of the encrypted +// data is greater than the modulus +// TPM_RC_VALUE 'dOutSize' is not large enough for the result +// TPM_RC_SCHEME 'padType' is not supported +// +LIB_EXPORT TPM_RC CryptRsaDecrypt( + TPM2B* dOut, // OUT: the decrypted data + TPM2B* cIn, // IN: the data to decrypt + OBJECT* key, // IN: the key to use for decryption + TPMT_RSA_DECRYPT* scheme, // IN: the padding scheme + const TPM2B* label // IN: in case it is needed for the scheme +) +{ + TPM_RC retVal; + + // Make sure that the necessary parameters are provided + pAssert(cIn != NULL && dOut != NULL && key != NULL); + + // Size is checked to make sure that the encrypted value is the right size + if(cIn->size != key->publicArea.unique.rsa.t.size) + ERROR_RETURN(TPM_RC_SIZE); + + TEST(scheme->scheme); + + // For others that do padding, do the decryption in place and then + // go handle the decoding. + retVal = RSADP(cIn, key); + if(retVal == TPM_RC_SUCCESS) + { + // Remove padding + switch(scheme->scheme) + { + case TPM_ALG_NULL: + if(dOut->size < cIn->size) + return TPM_RC_VALUE; + MemoryCopy2B(dOut, cIn, dOut->size); + break; + case TPM_ALG_RSAES: + retVal = RSAES_Decode(dOut, cIn); + break; + case TPM_ALG_OAEP: + retVal = OaepDecode(dOut, scheme->details.oaep.hashAlg, label, cIn); + break; + default: + retVal = TPM_RC_SCHEME; + break; + } + } +Exit: + return retVal; +} + +//*** CryptRsaSign() +// This function is used to generate an RSA signature of the type indicated in +// 'scheme'. +// +// Return Type: TPM_RC +// TPM_RC_SCHEME 'scheme' or 'hashAlg' are not supported +// TPM_RC_VALUE 'hInSize' does not match 'hashAlg' (for RSASSA) +// +LIB_EXPORT TPM_RC CryptRsaSign(TPMT_SIGNATURE* sigOut, + OBJECT* key, // IN: key to use + TPM2B_DIGEST* hIn, // IN: the digest to sign + RAND_STATE* rand // IN: the random number generator + // to use (mostly for testing) +) +{ + TPM_RC retVal = TPM_RC_SUCCESS; + UINT16 modSize; + + // parameter checks + pAssert(sigOut != NULL && key != NULL && hIn != NULL); + + modSize = key->publicArea.unique.rsa.t.size; + + // for all non-null signatures, the size is the size of the key modulus + sigOut->signature.rsapss.sig.t.size = modSize; + + TEST(sigOut->sigAlg); + + switch(sigOut->sigAlg) + { + case TPM_ALG_NULL: + sigOut->signature.rsapss.sig.t.size = 0; + return TPM_RC_SUCCESS; + case TPM_ALG_RSAPSS: + retVal = PssEncode(&sigOut->signature.rsapss.sig.b, + sigOut->signature.rsapss.hash, + &hIn->b, + rand); + break; + case TPM_ALG_RSASSA: + retVal = RSASSA_Encode(&sigOut->signature.rsassa.sig.b, + sigOut->signature.rsassa.hash, + &hIn->b); + break; + default: + retVal = TPM_RC_SCHEME; + } + if(retVal == TPM_RC_SUCCESS) + { + // Do the encryption using the private key + retVal = RSADP(&sigOut->signature.rsapss.sig.b, key); + } + return retVal; +} + +//*** CryptRsaValidateSignature() +// This function is used to validate an RSA signature. If the signature is valid +// TPM_RC_SUCCESS is returned. If the signature is not valid, TPM_RC_SIGNATURE is +// returned. Other return codes indicate either parameter problems or fatal errors. +// +// Return Type: TPM_RC +// TPM_RC_SIGNATURE the signature does not check +// TPM_RC_SCHEME unsupported scheme or hash algorithm +// +LIB_EXPORT TPM_RC CryptRsaValidateSignature( + TPMT_SIGNATURE* sig, // IN: signature + OBJECT* key, // IN: public modulus + TPM2B_DIGEST* digest // IN: The digest being validated +) +{ + TPM_RC retVal; + // + // Fatal programming errors + pAssert(key != NULL && sig != NULL && digest != NULL); + switch(sig->sigAlg) + { + case TPM_ALG_RSAPSS: + case TPM_ALG_RSASSA: + break; + default: + return TPM_RC_SCHEME; + } + + // Errors that might be caused by calling parameters + if(sig->signature.rsassa.sig.t.size != key->publicArea.unique.rsa.t.size) + ERROR_RETURN(TPM_RC_SIGNATURE); + + TEST(sig->sigAlg); + + // Decrypt the block + retVal = RSAEP(&sig->signature.rsassa.sig.b, key); + if(retVal == TPM_RC_SUCCESS) + { + switch(sig->sigAlg) + { + case TPM_ALG_RSAPSS: + retVal = PssDecode(sig->signature.any.hashAlg, + &digest->b, + &sig->signature.rsassa.sig.b); + break; + case TPM_ALG_RSASSA: + retVal = RSASSA_Decode(sig->signature.any.hashAlg, + &digest->b, + &sig->signature.rsassa.sig.b); + break; + default: + return TPM_RC_SCHEME; + } + } +Exit: + return (retVal != TPM_RC_SUCCESS) ? TPM_RC_SIGNATURE : TPM_RC_SUCCESS; +} + +# if SIMULATION && USE_RSA_KEY_CACHE +extern int s_rsaKeyCacheEnabled; +int GetCachedRsaKey( + TPMT_PUBLIC* publicArea, TPMT_SENSITIVE* sensitive, RAND_STATE* rand); +# define GET_CACHED_KEY(publicArea, sensitive, rand) \ + (s_rsaKeyCacheEnabled && GetCachedRsaKey(publicArea, sensitive, rand)) +# else +# define GET_CACHED_KEY(key, rand) +# endif + +//*** CryptRsaGenerateKey() +// Generate an RSA key from a provided seed +/*(See part 1 specification) +// The formulation is: +// KDFa(hash, seed, label, Name, Counter, bits) +// Where: +// hash the nameAlg from the public template +// seed a seed (will be a primary seed for a primary key) +// label a distinguishing label including vendor ID and +// vendor-assigned part number for the TPM. +// Name the nameAlg from the template and the hash of the template +// using nameAlg. +// Counter a 32-bit integer that is incremented each time the KDF is +// called in order to produce a specific key. This value +// can be a 32-bit integer in host format and does not need +// to be put in canonical form. +// bits the number of bits needed for the key. +// The following process is implemented to find a RSA key pair: +// 1. pick a random number with enough bits from KDFa as a prime candidate +// 2. set the first two significant bits and the least significant bit of the +// prime candidate +// 3. check if the number is a prime. if not, pick another random number +// 4. Make sure the difference between the two primes are more than 2^104. +// Otherwise, restart the process for the second prime +// 5. If the counter has reached its maximum but we still can not find a valid +// RSA key pair, return an internal error. This is an artificial bound. +// Other implementation may choose a smaller number to indicate how many +// times they are willing to try. +*/ +// Return Type: TPM_RC +// TPM_RC_CANCELED operation was canceled +// TPM_RC_RANGE public exponent is not supported +// TPM_RC_VALUE could not find a prime using the provided parameters +LIB_EXPORT TPM_RC CryptRsaGenerateKey( + TPMT_PUBLIC* publicArea, + TPMT_SENSITIVE* sensitive, + RAND_STATE* rand // IN: if not NULL, the deterministic + // RNG state +) +{ + UINT32 i; + BN_RSA(bnD); + BN_RSA(bnN); + BN_WORD(bnPubExp); + UINT32 e = publicArea->parameters.rsaDetail.exponent; + int keySizeInBits; + TPM_RC retVal = TPM_RC_NO_RESULT; + NEW_PRIVATE_EXPONENT(Z); + // + + // Need to make sure that the caller did not specify an exponent that is + // not supported + e = publicArea->parameters.rsaDetail.exponent; + if(e == 0) + e = RSA_DEFAULT_PUBLIC_EXPONENT; + else + { + if(e < 65537) + ERROR_RETURN(TPM_RC_RANGE); + // Check that e is prime + if(!IsPrimeInt(e)) + ERROR_RETURN(TPM_RC_RANGE); + } + BnSetWord(bnPubExp, e); + + // check for supported key size. + keySizeInBits = publicArea->parameters.rsaDetail.keyBits; + if(((keySizeInBits % 1024) != 0) + || (keySizeInBits > MAX_RSA_KEY_BITS) // this might be redundant, but... + || (keySizeInBits == 0)) + ERROR_RETURN(TPM_RC_VALUE); + + // Set the prime size for instrumentation purposes + INSTRUMENT_SET(PrimeIndex, PRIME_INDEX(keySizeInBits / 2)); + +# if SIMULATION && USE_RSA_KEY_CACHE + if(GET_CACHED_KEY(publicArea, sensitive, rand)) + return TPM_RC_SUCCESS; +# endif + + // Make sure that key generation has been tested + TEST(TPM_ALG_NULL); + + // The prime is computed in P. When a new prime is found, Q is checked to + // see if it is zero. If so, P is copied to Q and a new P is found. + // When both P and Q are non-zero, the modulus and + // private exponent are computed and a trial encryption/decryption is + // performed. If the encrypt/decrypt fails, assume that at least one of the + // primes is composite. Since we don't know which one, set Q to zero and start + // over and find a new pair of primes. + + for(i = 1; (retVal == TPM_RC_NO_RESULT) && (i != 100); i++) + { + if(_plat__IsCanceled()) + ERROR_RETURN(TPM_RC_CANCELED); + + if(BnGeneratePrimeForRSA(Z->P, keySizeInBits / 2, e, rand) == TPM_RC_FAILURE) + { + retVal = TPM_RC_FAILURE; + goto Exit; + } + + INSTRUMENT_INC(PrimeCounts[PrimeIndex]); + + // If this is the second prime, make sure that it differs from the + // first prime by at least 2^100 + if(BnEqualZero(Z->Q)) + { + // copy p to q and compute another prime in p + BnCopy(Z->Q, Z->P); + continue; + } + // Make sure that the difference is at least 100 bits. Need to do it this + // way because the big numbers are only positive values + if(BnUnsignedCmp(Z->P, Z->Q) < 0) + BnSub(bnD, Z->Q, Z->P); + else + BnSub(bnD, Z->P, Z->Q); + if(BnMsb(bnD) < 100) + continue; + + //Form the public modulus and set the unique value + BnMult(bnN, Z->P, Z->Q); + BnTo2B( + bnN, &publicArea->unique.rsa.b, (NUMBYTES)BITS_TO_BYTES(keySizeInBits)); + // Make sure everything came out right. The MSb of the values must be one + if(((publicArea->unique.rsa.t.buffer[0] & 0x80) == 0) + || (publicArea->unique.rsa.t.size + != (NUMBYTES)BITS_TO_BYTES(keySizeInBits))) + FAIL(FATAL_ERROR_INTERNAL); + + // Make sure that we can form the private exponent values + if(ComputePrivateExponent(bnPubExp, Z) != TRUE) + { + // If ComputePrivateExponent could not find an inverse for + // Q, then copy P and recompute P. This might + // cause both to be recomputed if P is also zero + if(BnEqualZero(Z->Q)) + BnCopy(Z->Q, Z->P); + continue; + } + + // Pack the private exponent into the sensitive area + PackExponent(&sensitive->sensitive.rsa, Z); + // Make sure everything came out right. The MSb of the values must be one + if(((publicArea->unique.rsa.t.buffer[0] & 0x80) == 0) + || ((sensitive->sensitive.rsa.t.buffer[0] & 0x80) == 0)) + FAIL(FATAL_ERROR_INTERNAL); + + retVal = TPM_RC_SUCCESS; + // Do a trial encryption decryption if this is a signing key + if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign)) + { + BN_RSA(temp1); + BN_RSA(temp2); + BnGenerateRandomInRange(temp1, bnN, rand); + + // Encrypt with public exponent... + BnModExp(temp2, temp1, bnPubExp, bnN); + // ... then decrypt with private exponent + RsaPrivateKeyOp(temp2, Z); + + // If the starting and ending values are not the same, + // start over )-; + if(BnUnsignedCmp(temp2, temp1) != 0) + { + BnSetWord(Z->Q, 0); + retVal = TPM_RC_NO_RESULT; + } + } + } +Exit: + return retVal; +} + +#endif // ALG_RSA \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptSelfTest.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptSelfTest.c new file mode 100644 index 0000000..bc8d3e1 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptSelfTest.c @@ -0,0 +1,211 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// The functions in this file are designed to support self-test of cryptographic +// functions in the TPM. The TPM allows the user to decide whether to run self-test +// on a demand basis or to run all the self-tests before proceeding. +// +// The self-tests are controlled by a set of bit vectors. The +// 'g_untestedDecryptionAlgorithms' vector has a bit for each decryption algorithm +// that needs to be tested and 'g_untestedEncryptionAlgorithms' has a bit for +// each encryption algorithm that needs to be tested. Before an algorithm +// is used, the appropriate vector is checked (indexed using the algorithm ID). +// If the bit is 1, then the test function should be called. +// +// For more information, see TpmSelfTests.txt + +#include "Tpm.h" + +//** Functions + +//*** RunSelfTest() +// Local function to run self-test +static TPM_RC CryptRunSelfTests( + ALGORITHM_VECTOR* toTest // IN: the vector of the algorithms to test +) +{ + TPM_ALG_ID alg; + + // For each of the algorithms that are in the toTestVecor, need to run a + // test + for(alg = TPM_ALG_FIRST; alg <= TPM_ALG_LAST; alg++) + { + if(TEST_BIT(alg, *toTest)) + { + TPM_RC result = CryptTestAlgorithm(alg, toTest); + if(result != TPM_RC_SUCCESS) + return result; + } + } + return TPM_RC_SUCCESS; +} + +//*** CryptSelfTest() +// This function is called to start/complete a full self-test. +// If 'fullTest' is NO, then only the untested algorithms will be run. If +// 'fullTest' is YES, then 'g_untestedDecryptionAlgorithms' is reinitialized and then +// all tests are run. +// This implementation of the reference design does not support processing outside +// the framework of a TPM command. As a consequence, this command does not +// complete until all tests are done. Since this can take a long time, the TPM +// will check after each test to see if the command is canceled. If so, then the +// TPM will returned TPM_RC_CANCELLED. To continue with the self-tests, call +// TPM2_SelfTest(fullTest == No) and the TPM will complete the testing. +// Return Type: TPM_RC +// TPM_RC_CANCELED if the command is canceled +LIB_EXPORT +TPM_RC +CryptSelfTest(TPMI_YES_NO fullTest // IN: if full test is required +) +{ +#if SIMULATION + if(g_forceFailureMode) + FAIL(FATAL_ERROR_FORCED); +#endif + + // If the caller requested a full test, then reset the to test vector so that + // all the tests will be run + if(fullTest == YES) + { + MemoryCopy(g_toTest, g_implementedAlgorithms, sizeof(g_toTest)); + } + return CryptRunSelfTests(&g_toTest); +} + +//*** CryptIncrementalSelfTest() +// This function is used to perform an incremental self-test. This implementation +// will perform the toTest values before returning. That is, it assumes that the +// TPM cannot perform background tasks between commands. +// +// This command may be canceled. If it is, then there is no return result. +// However, this command can be run again and the incremental progress will not +// be lost. +// Return Type: TPM_RC +// TPM_RC_CANCELED processing of this command was canceled +// TPM_RC_TESTING if toTest list is not empty +// TPM_RC_VALUE an algorithm in the toTest list is not implemented +TPM_RC +CryptIncrementalSelfTest(TPML_ALG* toTest, // IN: list of algorithms to be tested + TPML_ALG* toDoList // OUT: list of algorithms needing test +) +{ + ALGORITHM_VECTOR toTestVector = {0}; + TPM_ALG_ID alg; + UINT32 i; + + pAssert(toTest != NULL && toDoList != NULL); + if(toTest->count > 0) + { + // Transcribe the toTest list into the toTestVector + for(i = 0; i < toTest->count; i++) + { + alg = toTest->algorithms[i]; + + // make sure that the algorithm value is not out of range + if((alg > TPM_ALG_LAST) || !TEST_BIT(alg, g_implementedAlgorithms)) + return TPM_RC_VALUE; + SET_BIT(alg, toTestVector); + } + // Run the test + if(CryptRunSelfTests(&toTestVector) == TPM_RC_CANCELED) + return TPM_RC_CANCELED; + } + // Fill in the toDoList with the algorithms that are still untested + toDoList->count = 0; + + for(alg = TPM_ALG_FIRST; + toDoList->count < MAX_ALG_LIST_SIZE && alg <= TPM_ALG_LAST; + alg++) + { + if(TEST_BIT(alg, g_toTest)) + toDoList->algorithms[toDoList->count++] = alg; + } + return TPM_RC_SUCCESS; +} + +//*** CryptInitializeToTest() +// This function will initialize the data structures for testing all the +// algorithms. This should not be called unless CryptAlgsSetImplemented() has +// been called +void CryptInitializeToTest(void) +{ + // Indicate that nothing has been tested + memset(&g_cryptoSelfTestState, 0, sizeof(g_cryptoSelfTestState)); + + // Copy the implemented algorithm vector + MemoryCopy(g_toTest, g_implementedAlgorithms, sizeof(g_toTest)); + + // Setting the algorithm to null causes the test function to just clear + // out any algorithms for which there is no test. + CryptTestAlgorithm(TPM_ALG_ERROR, &g_toTest); + + return; +} + +//*** CryptTestAlgorithm() +// Only point of contact with the actual self tests. If a self-test fails, there +// is no return and the TPM goes into failure mode. +// The call to TestAlgorithm uses an algorithm selector and a bit vector. When the +// test is run, the corresponding bit in 'toTest' and in 'g_toTest' is CLEAR. If +// 'toTest' is NULL, then only the bit in 'g_toTest' is CLEAR. +// There is a special case for the call to TestAlgorithm(). When 'alg' is +// ALG_ERROR, TestAlgorithm() will CLEAR any bit in 'toTest' for which it has +// no test. This allows the knowledge about which algorithms have test to be +// accessed through the interface that provides the test. +// Return Type: TPM_RC +// TPM_RC_CANCELED test was canceled +LIB_EXPORT +TPM_RC +CryptTestAlgorithm(TPM_ALG_ID alg, ALGORITHM_VECTOR* toTest) +{ + TPM_RC result; +#if SELF_TEST + result = TestAlgorithm(alg, toTest); +#else + // If this is an attempt to determine the algorithms for which there is a + // self test, pretend that all of them do. We do that by not clearing any + // of the algorithm bits. When/if this function is called to run tests, it + // will over report. This can be changed so that any call to check on which + // algorithms have tests, 'toTest' can be cleared. + if(alg != TPM_ALG_ERROR) + { + CLEAR_BIT(alg, g_toTest); + if(toTest != NULL) + CLEAR_BIT(alg, *toTest); + } + result = TPM_RC_SUCCESS; +#endif + return result; +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptSmac.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptSmac.c new file mode 100644 index 0000000..3da1cf5 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptSmac.c @@ -0,0 +1,121 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// +// This file contains the implementation of the message authentication codes based +// on a symmetric block cipher. These functions only use the single block +// encryption functions of the selected symmetric cryptographic library. + +//** Includes, Defines, and Typedefs +#define _CRYPT_HASH_C_ +#include "Tpm.h" + +#if SMAC_IMPLEMENTED + +//*** CryptSmacStart() +// Function to start an SMAC. +UINT16 +CryptSmacStart(HASH_STATE* state, + TPMU_PUBLIC_PARMS* keyParameters, + TPM_ALG_ID macAlg, // IN: the type of MAC + TPM2B* key) +{ + UINT16 retVal = 0; + // + // Make sure that the key size is correct. This should have been checked + // at key load, but... + if(BITS_TO_BYTES(keyParameters->symDetail.sym.keyBits.sym) == key->size) + { + switch(macAlg) + { +# if ALG_CMAC + case TPM_ALG_CMAC: + retVal = + CryptCmacStart(&state->state.smac, keyParameters, macAlg, key); + break; +# endif + default: + break; + } + } + state->type = (retVal != 0) ? HASH_STATE_SMAC : HASH_STATE_EMPTY; + return retVal; +} + +//*** CryptMacStart() +// Function to start either an HMAC or an SMAC. Cannot reuse the CryptHmacStart +// function because of the difference in number of parameters. +UINT16 +CryptMacStart(HMAC_STATE* state, + TPMU_PUBLIC_PARMS* keyParameters, + TPM_ALG_ID macAlg, // IN: the type of MAC + TPM2B* key) +{ + MemorySet(state, 0, sizeof(HMAC_STATE)); + if(CryptHashIsValidAlg(macAlg, FALSE)) + { + return CryptHmacStart(state, macAlg, key->size, key->buffer); + } + else if(CryptSmacIsValidAlg(macAlg, FALSE)) + { + return CryptSmacStart(&state->hashState, keyParameters, macAlg, key); + } + else + return 0; +} + +//*** CryptMacEnd() +// Dispatch to the MAC end function using a size and buffer pointer. +UINT16 +CryptMacEnd(HMAC_STATE* state, UINT32 size, BYTE* buffer) +{ + UINT16 retVal = 0; + if(state->hashState.type == HASH_STATE_SMAC) + retVal = (state->hashState.state.smac.smacMethods.end)( + &state->hashState.state.smac.state, size, buffer); + else if(state->hashState.type == HASH_STATE_HMAC) + retVal = CryptHmacEnd(state, size, buffer); + state->hashState.type = HASH_STATE_EMPTY; + return retVal; +} + +//*** CryptMacEnd2B() +// Dispatch to the MAC end function using a 2B. +UINT16 +CryptMacEnd2B(HMAC_STATE* state, TPM2B* data) +{ + return CryptMacEnd(state, data->size, data->buffer); +} +#endif // SMAC_IMPLEMENTED diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptSym.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptSym.c new file mode 100644 index 0000000..a6bfbfc --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptSym.c @@ -0,0 +1,466 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// +// This file contains the implementation of the symmetric block cipher modes +// allowed for a TPM. These functions only use the single block encryption functions +// of the selected symmetric crypto library. + +//** Includes, Defines, and Typedefs +#include "Tpm.h" + +#include "CryptSym.h" + +#define KEY_BLOCK_SIZES(ALG, alg) \ + static const INT16 alg##KeyBlockSizes[] = {ALG##_KEY_SIZES_BITS, \ + -1, \ + ALG##_BLOCK_SIZES}; + +FOR_EACH_SYM(KEY_BLOCK_SIZES) + +//** Initialization and Data Access Functions +// +//*** CryptSymInit() +// This function is called to do _TPM_Init processing +BOOL CryptSymInit(void) +{ + return TRUE; +} + +//*** CryptSymStartup() +// This function is called to do TPM2_Startup() processing +BOOL CryptSymStartup(void) +{ + return TRUE; +} + +//*** CryptGetSymmetricBlockSize() +// This function returns the block size of the algorithm. The table of bit sizes has +// an entry for each allowed key size. The entry for a key size is 0 if the TPM does +// not implement that key size. The key size table is delimited with a negative number +// (-1). After the delimiter is a list of block sizes with each entry corresponding +// to the key bit size. For most symmetric algorithms, the block size is the same +// regardless of the key size but this arrangement allows them to be different. +// Return Type: INT16 +// <= 0 cipher not supported +// > 0 the cipher block size in bytes +LIB_EXPORT INT16 CryptGetSymmetricBlockSize( + TPM_ALG_ID symmetricAlg, // IN: the symmetric algorithm + UINT16 keySizeInBits // IN: the key size +) +{ + const INT16* sizes; + INT16 i; +#define ALG_CASE(SYM, sym) \ + case TPM_ALG_##SYM: \ + sizes = sym##KeyBlockSizes; \ + break + switch(symmetricAlg) + { +#define GET_KEY_BLOCK_POINTER(SYM, sym) \ + case TPM_ALG_##SYM: \ + sizes = sym##KeyBlockSizes; \ + break; + // Get the pointer to the block size array + FOR_EACH_SYM(GET_KEY_BLOCK_POINTER); + + default: + return 0; + } + // Find the index of the indicated keySizeInBits + for(i = 0; *sizes >= 0; i++, sizes++) + { + if(*sizes == keySizeInBits) + break; + } + // If sizes is pointing at the end of the list of key sizes, then the desired + // key size was not found so set the block size to zero. + if(*sizes++ < 0) + return 0; + // Advance until the end of the list is found + while(*sizes++ >= 0) + ; + // sizes is pointing to the first entry in the list of block sizes. Use the + // ith index to find the block size for the corresponding key size. + return sizes[i]; +} + +//** Symmetric Encryption +// This function performs symmetric encryption based on the mode. +// Return Type: TPM_RC +// TPM_RC_SIZE 'dSize' is not a multiple of the block size for an +// algorithm that requires it +// TPM_RC_FAILURE Fatal error +LIB_EXPORT TPM_RC CryptSymmetricEncrypt( + BYTE* dOut, // OUT: + TPM_ALG_ID algorithm, // IN: the symmetric algorithm + UINT16 keySizeInBits, // IN: key size in bits + const BYTE* key, // IN: key buffer. The size of this buffer + // in bytes is (keySizeInBits + 7) / 8 + TPM2B_IV* ivInOut, // IN/OUT: IV for decryption. + TPM_ALG_ID mode, // IN: Mode to use + INT32 dSize, // IN: data size (may need to be a + // multiple of the blockSize) + const BYTE* dIn // IN: data buffer +) +{ + BYTE* pIv; + int i; + BYTE tmp[MAX_SYM_BLOCK_SIZE]; + BYTE* pT; + tpmCryptKeySchedule_t keySchedule; + INT16 blockSize; + TpmCryptSetSymKeyCall_t encrypt; + BYTE* iv; + BYTE defaultIv[MAX_SYM_BLOCK_SIZE] = {0}; + // + pAssert(dOut != NULL && key != NULL && dIn != NULL); + if(dSize == 0) + return TPM_RC_SUCCESS; + + TEST(algorithm); + blockSize = CryptGetSymmetricBlockSize(algorithm, keySizeInBits); + if(blockSize == 0) + return TPM_RC_FAILURE; + // If the iv is provided, then it is expected to be block sized. In some cases, + // the caller is providing an array of 0's that is equal to [MAX_SYM_BLOCK_SIZE] + // with no knowledge of the actual block size. This function will set it. + if((ivInOut != NULL) && (mode != TPM_ALG_ECB)) + { + ivInOut->t.size = blockSize; + iv = ivInOut->t.buffer; + } + else + iv = defaultIv; + pIv = iv; + + // Create encrypt key schedule and set the encryption function pointer. + switch(algorithm) + { + FOR_EACH_SYM(ENCRYPT_CASE) + + default: + return TPM_RC_SYMMETRIC; + } + switch(mode) + { +#if ALG_CTR + case TPM_ALG_CTR: + for(; dSize > 0; dSize -= blockSize) + { + // Encrypt the current value of the IV(counter) + ENCRYPT(&keySchedule, iv, tmp); + + //increment the counter (counter is big-endian so start at end) + for(i = blockSize - 1; i >= 0; i--) + if((iv[i] += 1) != 0) + break; + // XOR the encrypted counter value with input and put into output + pT = tmp; + for(i = (dSize < blockSize) ? dSize : blockSize; i > 0; i--) + *dOut++ = *dIn++ ^ *pT++; + } + break; +#endif +#if ALG_OFB + case TPM_ALG_OFB: + // This is written so that dIn and dOut may be the same + for(; dSize > 0; dSize -= blockSize) + { + // Encrypt the current value of the "IV" + ENCRYPT(&keySchedule, iv, iv); + + // XOR the encrypted IV into dIn to create the cipher text (dOut) + pIv = iv; + for(i = (dSize < blockSize) ? dSize : blockSize; i > 0; i--) + *dOut++ = (*pIv++ ^ *dIn++); + } + break; +#endif +#if ALG_CBC + case TPM_ALG_CBC: + // For CBC the data size must be an even multiple of the + // cipher block size + if((dSize % blockSize) != 0) + return TPM_RC_SIZE; + // XOR the data block into the IV, encrypt the IV into the IV + // and then copy the IV to the output + for(; dSize > 0; dSize -= blockSize) + { + pIv = iv; + for(i = blockSize; i > 0; i--) + *pIv++ ^= *dIn++; + ENCRYPT(&keySchedule, iv, iv); + pIv = iv; + for(i = blockSize; i > 0; i--) + *dOut++ = *pIv++; + } + break; +#endif + // CFB is not optional + case TPM_ALG_CFB: + // Encrypt the IV into the IV, XOR in the data, and copy to output + for(; dSize > 0; dSize -= blockSize) + { + // Encrypt the current value of the IV + ENCRYPT(&keySchedule, iv, iv); + pIv = iv; + for(i = (int)(dSize < blockSize) ? dSize : blockSize; i > 0; i--) + // XOR the data into the IV to create the cipher text + // and put into the output + *dOut++ = *pIv++ ^= *dIn++; + } + // If the inner loop (i loop) was smaller than blockSize, then dSize + // would have been smaller than blockSize and it is now negative. If + // it is negative, then it indicates how many bytes are needed to pad + // out the IV for the next round. + for(; dSize < 0; dSize++) + *pIv++ = 0; + break; +#if ALG_ECB + case TPM_ALG_ECB: + // For ECB the data size must be an even multiple of the + // cipher block size + if((dSize % blockSize) != 0) + return TPM_RC_SIZE; + // Encrypt the input block to the output block + for(; dSize > 0; dSize -= blockSize) + { + ENCRYPT(&keySchedule, dIn, dOut); + dIn = &dIn[blockSize]; + dOut = &dOut[blockSize]; + } + break; +#endif + default: + return TPM_RC_FAILURE; + } + return TPM_RC_SUCCESS; +} + +//*** CryptSymmetricDecrypt() +// This function performs symmetric decryption based on the mode. +// Return Type: TPM_RC +// TPM_RC_FAILURE A fatal error +// TPM_RCS_SIZE 'dSize' is not a multiple of the block size for an +// algorithm that requires it +LIB_EXPORT TPM_RC CryptSymmetricDecrypt( + BYTE* dOut, // OUT: decrypted data + TPM_ALG_ID algorithm, // IN: the symmetric algorithm + UINT16 keySizeInBits, // IN: key size in bits + const BYTE* key, // IN: key buffer. The size of this buffer + // in bytes is (keySizeInBits + 7) / 8 + TPM2B_IV* ivInOut, // IN/OUT: IV for decryption. + TPM_ALG_ID mode, // IN: Mode to use + INT32 dSize, // IN: data size (may need to be a + // multiple of the blockSize) + const BYTE* dIn // IN: data buffer +) +{ + BYTE* pIv; + int i; + BYTE tmp[MAX_SYM_BLOCK_SIZE]; + BYTE* pT; + tpmCryptKeySchedule_t keySchedule; + INT16 blockSize; + BYTE* iv; + TpmCryptSetSymKeyCall_t encrypt; + TpmCryptSetSymKeyCall_t decrypt; + BYTE defaultIv[MAX_SYM_BLOCK_SIZE] = {0}; + + // These are used but the compiler can't tell because they are initialized + // in case statements and it can't tell if they are always initialized + // when needed, so... Comment these out if the compiler can tell or doesn't + // care that these are initialized before use. + encrypt = NULL; + decrypt = NULL; + + pAssert(dOut != NULL && key != NULL && dIn != NULL); + if(dSize == 0) + return TPM_RC_SUCCESS; + + TEST(algorithm); + blockSize = CryptGetSymmetricBlockSize(algorithm, keySizeInBits); + if(blockSize == 0) + return TPM_RC_FAILURE; + // If the iv is provided, then it is expected to be block sized. In some cases, + // the caller is providing an array of 0's that is equal to [MAX_SYM_BLOCK_SIZE] + // with no knowledge of the actual block size. This function will set it. + if((ivInOut != NULL) && (mode != TPM_ALG_ECB)) + { + ivInOut->t.size = blockSize; + iv = ivInOut->t.buffer; + } + else + iv = defaultIv; + + pIv = iv; + // Use the mode to select the key schedule to create. Encrypt always uses the + // encryption schedule. Depending on the mode, decryption might use either + // the decryption or encryption schedule. + switch(mode) + { +#if ALG_CBC || ALG_ECB + case TPM_ALG_CBC: // decrypt = decrypt + case TPM_ALG_ECB: + // For ECB and CBC, the data size must be an even multiple of the + // cipher block size + if((dSize % blockSize) != 0) + return TPM_RC_SIZE; + switch(algorithm) + { + FOR_EACH_SYM(DECRYPT_CASE) + default: + return TPM_RC_SYMMETRIC; + } + break; +#endif + default: + // For the remaining stream ciphers, use encryption to decrypt + switch(algorithm) + { + FOR_EACH_SYM(ENCRYPT_CASE) + default: + return TPM_RC_SYMMETRIC; + } + } + // Now do the mode-dependent decryption + switch(mode) + { +#if ALG_CBC + case TPM_ALG_CBC: + // Copy the input data to a temp buffer, decrypt the buffer into the + // output, XOR in the IV, and copy the temp buffer to the IV and repeat. + for(; dSize > 0; dSize -= blockSize) + { + pT = tmp; + for(i = blockSize; i > 0; i--) + *pT++ = *dIn++; + DECRYPT(&keySchedule, tmp, dOut); + pIv = iv; + pT = tmp; + for(i = blockSize; i > 0; i--) + { + *dOut++ ^= *pIv; + *pIv++ = *pT++; + } + } + break; +#endif + case TPM_ALG_CFB: + for(; dSize > 0; dSize -= blockSize) + { + // Encrypt the IV into the temp buffer + ENCRYPT(&keySchedule, iv, tmp); + pT = tmp; + pIv = iv; + for(i = (dSize < blockSize) ? dSize : blockSize; i > 0; i--) + // Copy the current cipher text to IV, XOR + // with the temp buffer and put into the output + *dOut++ = *pT++ ^ (*pIv++ = *dIn++); + } + // If the inner loop (i loop) was smaller than blockSize, then dSize + // would have been smaller than blockSize and it is now negative + // If it is negative, then it indicates how may fill bytes + // are needed to pad out the IV for the next round. + for(; dSize < 0; dSize++) + *pIv++ = 0; + + break; +#if ALG_CTR + case TPM_ALG_CTR: + for(; dSize > 0; dSize -= blockSize) + { + // Encrypt the current value of the IV(counter) + ENCRYPT(&keySchedule, iv, tmp); + + //increment the counter (counter is big-endian so start at end) + for(i = blockSize - 1; i >= 0; i--) + if((iv[i] += 1) != 0) + break; + // XOR the encrypted counter value with input and put into output + pT = tmp; + for(i = (dSize < blockSize) ? dSize : blockSize; i > 0; i--) + *dOut++ = *dIn++ ^ *pT++; + } + break; +#endif +#if ALG_ECB + case TPM_ALG_ECB: + for(; dSize > 0; dSize -= blockSize) + { + DECRYPT(&keySchedule, dIn, dOut); + dIn = &dIn[blockSize]; + dOut = &dOut[blockSize]; + } + break; +#endif +#if ALG_OFB + case TPM_ALG_OFB: + // This is written so that dIn and dOut may be the same + for(; dSize > 0; dSize -= blockSize) + { + // Encrypt the current value of the "IV" + ENCRYPT(&keySchedule, iv, iv); + + // XOR the encrypted IV into dIn to create the cipher text (dOut) + pIv = iv; + for(i = (dSize < blockSize) ? dSize : blockSize; i > 0; i--) + *dOut++ = (*pIv++ ^ *dIn++); + } + break; +#endif + default: + return TPM_RC_FAILURE; + } + return TPM_RC_SUCCESS; +} + +//*** CryptSymKeyValidate() +// Validate that a provided symmetric key meets the requirements of the TPM +// Return Type: TPM_RC +// TPM_RC_KEY_SIZE Key size specifiers do not match +// TPM_RC_KEY Key is not allowed +TPM_RC +CryptSymKeyValidate(TPMT_SYM_DEF_OBJECT* symDef, TPM2B_SYM_KEY* key) +{ + if(key->t.size != BITS_TO_BYTES(symDef->keyBits.sym)) + return TPM_RCS_KEY_SIZE; +#if ALG_TDES + if(symDef->algorithm == TPM_ALG_TDES && !CryptDesValidateKey(key)) + return TPM_RCS_KEY; +#endif // ALG_TDES + return TPM_RC_SUCCESS; +} diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptUtil.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptUtil.c new file mode 100644 index 0000000..52fcd0b --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/CryptUtil.c @@ -0,0 +1,1917 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// +// This module contains the interfaces to the CryptoEngine and provides +// miscellaneous cryptographic functions in support of the TPM. +// + +//** Includes +#include "Tpm.h" +#include "Marshal.h" + +//****************************************************************************/ +//** Hash/HMAC Functions +//****************************************************************************/ + +//*** CryptHmacSign() +// Sign a digest using an HMAC key. This an HMAC of a digest, not an HMAC of a +// message. +// Return Type: TPM_RC +// TPM_RC_HASH not a valid hash +static TPM_RC CryptHmacSign(TPMT_SIGNATURE* signature, // OUT: signature + OBJECT* signKey, // IN: HMAC key sign the hash + TPM2B_DIGEST* hashData // IN: hash to be signed +) +{ + HMAC_STATE hmacState; + UINT32 digestSize; + + digestSize = CryptHmacStart2B(&hmacState, + signature->signature.any.hashAlg, + &signKey->sensitive.sensitive.bits.b); + CryptDigestUpdate2B(&hmacState.hashState, &hashData->b); + CryptHmacEnd(&hmacState, digestSize, (BYTE*)&signature->signature.hmac.digest); + return TPM_RC_SUCCESS; +} + +//*** CryptHMACVerifySignature() +// This function will verify a signature signed by a HMAC key. +// Note that a caller needs to prepare 'signature' with the signature algorithm +// (TPM_ALG_HMAC) and the hash algorithm to use. This function then builds a +// signature of that type. +// Return Type: TPM_RC +// TPM_RC_SCHEME not the proper scheme for this key type +// TPM_RC_SIGNATURE if invalid input or signature is not genuine +static TPM_RC CryptHMACVerifySignature( + OBJECT* signKey, // IN: HMAC key signed the hash + TPM2B_DIGEST* hashData, // IN: digest being verified + TPMT_SIGNATURE* signature // IN: signature to be verified +) +{ + TPMT_SIGNATURE test; + TPMT_KEYEDHASH_SCHEME* keyScheme = + &signKey->publicArea.parameters.keyedHashDetail.scheme; + // + if((signature->sigAlg != TPM_ALG_HMAC) + || (signature->signature.hmac.hashAlg == TPM_ALG_NULL)) + return TPM_RC_SCHEME; + // This check is not really needed for verification purposes. However, it does + // prevent someone from trying to validate a signature using a weaker hash + // algorithm than otherwise allowed by the key. That is, a key with a scheme + // other than TMP_ALG_NULL can only be used to validate signatures that have + // a matching scheme. + if((keyScheme->scheme != TPM_ALG_NULL) + && ((keyScheme->scheme != signature->sigAlg) + || (keyScheme->details.hmac.hashAlg != signature->signature.any.hashAlg))) + return TPM_RC_SIGNATURE; + test.sigAlg = signature->sigAlg; + test.signature.hmac.hashAlg = signature->signature.hmac.hashAlg; + + CryptHmacSign(&test, signKey, hashData); + + // Compare digest + if(!MemoryEqual(&test.signature.hmac.digest, + &signature->signature.hmac.digest, + CryptHashGetDigestSize(signature->signature.any.hashAlg))) + return TPM_RC_SIGNATURE; + + return TPM_RC_SUCCESS; +} + +//*** CryptGenerateKeyedHash() +// This function creates a keyedHash object. +// Return type: TPM_RC +// TPM_RC_NO_RESULT cannot get values from random number generator +// TPM_RC_SIZE sensitive data size is larger than allowed for +// the scheme +static TPM_RC CryptGenerateKeyedHash( + TPMT_PUBLIC* publicArea, // IN/OUT: the public area template + // for the new key. + TPMT_SENSITIVE* sensitive, // OUT: sensitive area + TPMS_SENSITIVE_CREATE* sensitiveCreate, // IN: sensitive creation data + RAND_STATE* rand // IN: "entropy" source +) +{ + TPMT_KEYEDHASH_SCHEME* scheme; + TPM_ALG_ID hashAlg; + UINT16 digestSize; + + scheme = &publicArea->parameters.keyedHashDetail.scheme; + + if(publicArea->type != TPM_ALG_KEYEDHASH) + return TPM_RC_FAILURE; + + // Pick the limiting hash algorithm + if(scheme->scheme == TPM_ALG_NULL) + hashAlg = publicArea->nameAlg; + else if(scheme->scheme == TPM_ALG_XOR) + hashAlg = scheme->details.xor.hashAlg; + else + hashAlg = scheme->details.hmac.hashAlg; + digestSize = CryptHashGetDigestSize(hashAlg); + + // if this is a signing or a decryption key, then the limit + // for the data size is the block size of the hash. This limit + // is set because larger values have lower entropy because of the + // HMAC function. The lower limit is 1/2 the size of the digest + // + //If the user provided the key, check that it is a proper size + if(sensitiveCreate->data.t.size != 0) + { + if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, decrypt) + || IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign)) + { + if(sensitiveCreate->data.t.size > CryptHashGetBlockSize(hashAlg)) + return TPM_RC_SIZE; +#if 0 // May make this a FIPS-mode requirement + if(sensitiveCreate->data.t.size < (digestSize / 2)) + return TPM_RC_SIZE; +#endif + } + // If this is a data blob, then anything that will get past the unmarshaling + // is OK + MemoryCopy2B(&sensitive->sensitive.bits.b, + &sensitiveCreate->data.b, + sizeof(sensitive->sensitive.bits.t.buffer)); + } + else + { + // The TPM is going to generate the data so set the size to be the + // size of the digest of the algorithm + sensitive->sensitive.bits.t.size = + DRBG_Generate(rand, sensitive->sensitive.bits.t.buffer, digestSize); + if(sensitive->sensitive.bits.t.size == 0) + return (g_inFailureMode) ? TPM_RC_FAILURE : TPM_RC_NO_RESULT; + } + return TPM_RC_SUCCESS; +} + +//*** CryptIsSchemeAnonymous() +// This function is used to test a scheme to see if it is an anonymous scheme +// The only anonymous scheme is ECDAA. ECDAA can be used to do things +// like U-Prove. +BOOL CryptIsSchemeAnonymous(TPM_ALG_ID scheme // IN: the scheme algorithm to test +) +{ + return scheme == TPM_ALG_ECDAA; +} + +//**** ************************************************************************ +//** Symmetric Functions +//**** ************************************************************************ + +//*** ParmDecryptSym() +// This function performs parameter decryption using symmetric block cipher. +/*(See Part 1 specification) +// Symmetric parameter decryption +// When parameter decryption uses a symmetric block cipher, a decryption +// key and IV will be generated from: +// KDFa(hash, sessionAuth, "CFB", nonceNewer, nonceOlder, bits) (24) +// Where: +// hash the hash function associated with the session +// sessionAuth the sessionAuth associated with the session +// nonceNewer nonceCaller for a command +// nonceOlder nonceTPM for a command +// bits the number of bits required for the symmetric key +// plus an IV +*/ +void ParmDecryptSym(TPM_ALG_ID symAlg, // IN: the symmetric algorithm + TPM_ALG_ID hash, // IN: hash algorithm for KDFa + UINT16 keySizeInBits, // IN: the key size in bits + TPM2B* key, // IN: KDF HMAC key + TPM2B* nonceCaller, // IN: nonce caller + TPM2B* nonceTpm, // IN: nonce TPM + UINT32 dataSize, // IN: size of parameter buffer + BYTE* data // OUT: buffer to be decrypted +) +{ + // KDF output buffer + // It contains parameters for the CFB encryption + // From MSB to LSB, they are the key and iv + BYTE symParmString[MAX_SYM_KEY_BYTES + MAX_SYM_BLOCK_SIZE]; + // Symmetric key size in byte + UINT16 keySize = (keySizeInBits + 7) / 8; + TPM2B_IV iv; + + iv.t.size = CryptGetSymmetricBlockSize(symAlg, keySizeInBits); + // If there is decryption to do... + if(iv.t.size > 0) + { + // Generate key and iv + CryptKDFa(hash, + key, + CFB_KEY, + nonceCaller, + nonceTpm, + keySizeInBits + (iv.t.size * 8), + symParmString, + NULL, + FALSE); + MemoryCopy(iv.t.buffer, &symParmString[keySize], iv.t.size); + + CryptSymmetricDecrypt(data, + symAlg, + keySizeInBits, + symParmString, + &iv, + TPM_ALG_CFB, + dataSize, + data); + } + return; +} + +//*** ParmEncryptSym() +// This function performs parameter encryption using symmetric block cipher. +/*(See part 1 specification) +// When parameter decryption uses a symmetric block cipher, an encryption +// key and IV will be generated from: +// KDFa(hash, sessionAuth, "CFB", nonceNewer, nonceOlder, bits) (24) +// Where: +// hash the hash function associated with the session +// sessionAuth the sessionAuth associated with the session +// nonceNewer nonceTPM for a response +// nonceOlder nonceCaller for a response +// bits the number of bits required for the symmetric key +// plus an IV +*/ +void ParmEncryptSym(TPM_ALG_ID symAlg, // IN: symmetric algorithm + TPM_ALG_ID hash, // IN: hash algorithm for KDFa + UINT16 keySizeInBits, // IN: symmetric key size in bits + TPM2B* key, // IN: KDF HMAC key + TPM2B* nonceCaller, // IN: nonce caller + TPM2B* nonceTpm, // IN: nonce TPM + UINT32 dataSize, // IN: size of parameter buffer + BYTE* data // OUT: buffer to be encrypted +) +{ + // KDF output buffer + // It contains parameters for the CFB encryption + BYTE symParmString[MAX_SYM_KEY_BYTES + MAX_SYM_BLOCK_SIZE]; + + // Symmetric key size in bytes + UINT16 keySize = (keySizeInBits + 7) / 8; + + TPM2B_IV iv; + + iv.t.size = CryptGetSymmetricBlockSize(symAlg, keySizeInBits); + // See if there is any encryption to do + if(iv.t.size > 0) + { + // Generate key and iv + CryptKDFa(hash, + key, + CFB_KEY, + nonceTpm, + nonceCaller, + keySizeInBits + (iv.t.size * 8), + symParmString, + NULL, + FALSE); + MemoryCopy(iv.t.buffer, &symParmString[keySize], iv.t.size); + + CryptSymmetricEncrypt(data, + symAlg, + keySizeInBits, + symParmString, + &iv, + TPM_ALG_CFB, + dataSize, + data); + } + return; +} + +//*** CryptGenerateKeySymmetric() +// This function generates a symmetric cipher key. The derivation process is +// determined by the type of the provided 'rand' +// Return type: TPM_RC +// TPM_RC_NO_RESULT cannot get a random value +// TPM_RC_KEY_SIZE key size in the public area does not match the size +// in the sensitive creation area +// TPM_RC_KEY provided key value is not allowed +static TPM_RC CryptGenerateKeySymmetric( + TPMT_PUBLIC* publicArea, // IN/OUT: The public area template + // for the new key. + TPMT_SENSITIVE* sensitive, // OUT: sensitive area + TPMS_SENSITIVE_CREATE* sensitiveCreate, // IN: sensitive creation data + RAND_STATE* rand // IN: the "entropy" source for +) +{ + UINT16 keyBits = publicArea->parameters.symDetail.sym.keyBits.sym; + TPM_RC result; + // + // only do multiples of RADIX_BITS + if((keyBits % RADIX_BITS) != 0) + return TPM_RC_KEY_SIZE; + // If this is not a new key, then the provided key data must be the right size + if(sensitiveCreate->data.t.size != 0) + { + result = CryptSymKeyValidate(&publicArea->parameters.symDetail.sym, + (TPM2B_SYM_KEY*)&sensitiveCreate->data); + if(result == TPM_RC_SUCCESS) + MemoryCopy2B(&sensitive->sensitive.sym.b, + &sensitiveCreate->data.b, + sizeof(sensitive->sensitive.sym.t.buffer)); + } +#if ALG_TDES + else if(publicArea->parameters.symDetail.sym.algorithm == TPM_ALG_TDES) + { + result = CryptGenerateKeyDes(publicArea, sensitive, rand); + } +#endif + else + { + sensitive->sensitive.sym.t.size = DRBG_Generate( + rand, sensitive->sensitive.sym.t.buffer, BITS_TO_BYTES(keyBits)); + if(g_inFailureMode) + result = TPM_RC_FAILURE; + else if(sensitive->sensitive.sym.t.size == 0) + result = TPM_RC_NO_RESULT; + else + result = TPM_RC_SUCCESS; + } + return result; +} + +//*** CryptXORObfuscation() +// This function implements XOR obfuscation. It should not be called if the +// hash algorithm is not implemented. The only return value from this function +// is TPM_RC_SUCCESS. +void CryptXORObfuscation(TPM_ALG_ID hash, // IN: hash algorithm for KDF + TPM2B* key, // IN: KDF key + TPM2B* contextU, // IN: contextU + TPM2B* contextV, // IN: contextV + UINT32 dataSize, // IN: size of data buffer + BYTE* data // IN/OUT: data to be XORed in place +) +{ + BYTE mask[MAX_DIGEST_SIZE]; // Allocate a digest sized buffer + BYTE* pm; + UINT32 i; + UINT32 counter = 0; + UINT16 hLen = CryptHashGetDigestSize(hash); + UINT32 requestSize = dataSize * 8; + INT32 remainBytes = (INT32)dataSize; + + pAssert((key != NULL) && (data != NULL) && (hLen != 0)); + + // Call KDFa to generate XOR mask + for(; remainBytes > 0; remainBytes -= hLen) + { + // Make a call to KDFa to get next iteration + CryptKDFa(hash, + key, + XOR_KEY, + contextU, + contextV, + requestSize, + mask, + &counter, + TRUE); + + // XOR next piece of the data + pm = mask; + for(i = hLen < remainBytes ? hLen : remainBytes; i > 0; i--) + *data++ ^= *pm++; + } + return; +} + +//**************************************************************************** +//** Initialization and shut down +//**************************************************************************** + +//*** CryptInit() +// This function is called when the TPM receives a _TPM_Init indication. +// +// NOTE: The hash algorithms do not have to be tested, they just need to be +// available. They have to be tested before the TPM can accept HMAC authorization +// or return any result that relies on a hash algorithm. +// Return Type: BOOL +// TRUE(1) initializations succeeded +// FALSE(0) initialization failed and caller should place the TPM into +// Failure Mode +BOOL CryptInit(void) +{ + BOOL ok; + // Initialize the vector of implemented algorithms + AlgorithmGetImplementedVector(&g_implementedAlgorithms); + + // Indicate that all test are necessary + CryptInitializeToTest(); + + // Do any library initializations that are necessary. If any fails, + // the caller should go into failure mode; + ok = SupportLibInit(); + ok = ok && CryptSymInit(); + ok = ok && CryptRandInit(); + ok = ok && CryptHashInit(); +#if ALG_RSA + ok = ok && CryptRsaInit(); +#endif // ALG_RSA +#if ALG_ECC + ok = ok && CryptEccInit(); +#endif // ALG_ECC + return ok; +} + +//*** CryptStartup() +// This function is called by TPM2_Startup() to initialize the functions in +// this cryptographic library and in the provided CryptoLibrary. This function +// and CryptUtilInit() are both provided so that the implementation may move the +// initialization around to get the best interaction. +// Return Type: BOOL +// TRUE(1) startup succeeded +// FALSE(0) startup failed and caller should place the TPM into +// Failure Mode +BOOL CryptStartup(STARTUP_TYPE type // IN: the startup type +) +{ + BOOL OK; + NOT_REFERENCED(type); + + OK = CryptSymStartup() && CryptRandStartup() && CryptHashStartup() +#if ALG_RSA + && CryptRsaStartup() +#endif // ALG_RSA +#if ALG_ECC + && CryptEccStartup() +#endif // ALG_ECC + ; +#if ALG_ECC + // Don't directly check for SU_RESET because that is the default + if(OK && (type != SU_RESTART) && (type != SU_RESUME)) + { + // If the shutdown was orderly, then the values recovered from NV will + // be OK to use. + // Get a new random commit nonce + gr.commitNonce.t.size = sizeof(gr.commitNonce.t.buffer); + CryptRandomGenerate(gr.commitNonce.t.size, gr.commitNonce.t.buffer); + // Reset the counter and commit array + gr.commitCounter = 0; + MemorySet(gr.commitArray, 0, sizeof(gr.commitArray)); + } +#endif // ALG_ECC + return OK; +} + +//**************************************************************************** +//** Algorithm-Independent Functions +//**************************************************************************** +//*** Introduction +// These functions are used generically when a function of a general type +// (e.g., symmetric encryption) is required. The functions will modify the +// parameters as required to interface to the indicated algorithms. +// +//*** CryptIsAsymAlgorithm() +// This function indicates if an algorithm is an asymmetric algorithm. +// Return Type: BOOL +// TRUE(1) if it is an asymmetric algorithm +// FALSE(0) if it is not an asymmetric algorithm +BOOL CryptIsAsymAlgorithm(TPM_ALG_ID algID // IN: algorithm ID +) +{ + switch(algID) + { +#if ALG_RSA + case TPM_ALG_RSA: +#endif +#if ALG_ECC + case TPM_ALG_ECC: +#endif + return TRUE; + break; + default: + break; + } + return FALSE; +} + +//*** CryptSecretEncrypt() +// This function creates a secret value and its associated secret structure using +// an asymmetric algorithm. +// +// This function is used by TPM2_Rewrap() TPM2_MakeCredential(), +// and TPM2_Duplicate(). +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES 'keyHandle' does not reference a valid decryption key +// TPM_RC_KEY invalid ECC key (public point is not on the curve) +// TPM_RC_SCHEME RSA key with an unsupported padding scheme +// TPM_RC_VALUE numeric value of the data to be decrypted is greater +// than the RSA key modulus +TPM_RC +CryptSecretEncrypt(OBJECT* encryptKey, // IN: encryption key object + const TPM2B* label, // IN: a null-terminated string as L + TPM2B_DATA* data, // OUT: secret value + TPM2B_ENCRYPTED_SECRET* secret // OUT: secret structure +) +{ + TPMT_RSA_DECRYPT scheme; + TPM_RC result = TPM_RC_SUCCESS; + // + if(data == NULL || secret == NULL) + return TPM_RC_FAILURE; + + // The output secret value has the size of the digest produced by the nameAlg. + data->t.size = CryptHashGetDigestSize(encryptKey->publicArea.nameAlg); + // The encryption scheme is OAEP using the nameAlg of the encrypt key. + scheme.scheme = TPM_ALG_OAEP; + scheme.details.anySig.hashAlg = encryptKey->publicArea.nameAlg; + + if(!IS_ATTRIBUTE(encryptKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt)) + return TPM_RC_ATTRIBUTES; + switch(encryptKey->publicArea.type) + { +#if ALG_RSA + case TPM_ALG_RSA: + { + // Create secret data from RNG + CryptRandomGenerate(data->t.size, data->t.buffer); + + // Encrypt the data by RSA OAEP into encrypted secret + result = CryptRsaEncrypt((TPM2B_PUBLIC_KEY_RSA*)secret, + &data->b, + encryptKey, + &scheme, + label, + NULL); + } + break; +#endif // ALG_RSA + +#if ALG_ECC + case TPM_ALG_ECC: + { + TPMS_ECC_POINT eccPublic; + TPM2B_ECC_PARAMETER eccPrivate; + TPMS_ECC_POINT eccSecret; + BYTE* buffer = secret->t.secret; + + // Need to make sure that the public point of the key is on the + // curve defined by the key. + if(!CryptEccIsPointOnCurve( + encryptKey->publicArea.parameters.eccDetail.curveID, + &encryptKey->publicArea.unique.ecc)) + result = TPM_RC_KEY; + else + { + // Call crypto engine to create an auxiliary ECC key + // We assume crypt engine initialization should always success. + // Otherwise, TPM should go to failure mode. + + CryptEccNewKeyPair( + &eccPublic, + &eccPrivate, + encryptKey->publicArea.parameters.eccDetail.curveID); + // Marshal ECC public to secret structure. This will be used by the + // recipient to decrypt the secret with their private key. + secret->t.size = TPMS_ECC_POINT_Marshal(&eccPublic, &buffer, NULL); + + // Compute ECDH shared secret which is R = [d]Q where d is the + // private part of the ephemeral key and Q is the public part of a + // TPM key. TPM_RC_KEY error return from CryptComputeECDHSecret + // because the auxiliary ECC key is just created according to the + // parameters of input ECC encrypt key. + if(CryptEccPointMultiply( + &eccSecret, + encryptKey->publicArea.parameters.eccDetail.curveID, + &encryptKey->publicArea.unique.ecc, + &eccPrivate, + NULL, + NULL) + != TPM_RC_SUCCESS) + result = TPM_RC_KEY; + else + { + // The secret value is computed from Z using KDFe as: + // secret := KDFe(HashID, Z, Use, PartyUInfo, PartyVInfo, bits) + // Where: + // HashID the nameAlg of the decrypt key + // Z the x coordinate (Px) of the product (P) of the point + // (Q) of the secret and the private x coordinate (de,V) + // of the decryption key + // Use a null-terminated string containing "SECRET" + // PartyUInfo the x coordinate of the point in the secret + // (Qe,U ) + // PartyVInfo the x coordinate of the public key (Qs,V ) + // bits the number of bits in the digest of HashID + // Retrieve seed from KDFe + CryptKDFe(encryptKey->publicArea.nameAlg, + &eccSecret.x.b, + label, + &eccPublic.x.b, + &encryptKey->publicArea.unique.ecc.x.b, + data->t.size * 8, + data->t.buffer); + } + } + } + break; +#endif // ALG_ECC + default: + FAIL(FATAL_ERROR_INTERNAL); + break; + } + return result; +} + +//*** CryptSecretDecrypt() +// Decrypt a secret value by asymmetric (or symmetric) algorithm +// This function is used for ActivateCredential and Import for asymmetric +// decryption, and StartAuthSession for both asymmetric and symmetric +// decryption process +// +// Return Type: TPM_RC +// TPM_RC_ATTRIBUTES RSA key is not a decryption key +// TPM_RC_BINDING Invalid RSA key (public and private parts are not +// cryptographically bound. +// TPM_RC_ECC_POINT ECC point in the secret is not on the curve +// TPM_RC_INSUFFICIENT failed to retrieve ECC point from the secret +// TPM_RC_NO_RESULT multiplication resulted in ECC point at infinity +// TPM_RC_SIZE data to decrypt is not of the same size as RSA key +// TPM_RC_VALUE For RSA key, numeric value of the encrypted data is +// greater than the modulus, or the recovered data is +// larger than the output buffer. +// For keyedHash or symmetric key, the secret is +// larger than the size of the digest produced by +// the name algorithm. +// TPM_RC_FAILURE internal error +TPM_RC +CryptSecretDecrypt(OBJECT* decryptKey, // IN: decrypt key + TPM2B_NONCE* nonceCaller, // IN: nonceCaller. It is needed for + // symmetric decryption. For + // asymmetric decryption, this + // parameter is NULL + const TPM2B* label, // IN: a value for L + TPM2B_ENCRYPTED_SECRET* secret, // IN: input secret + TPM2B_DATA* data // OUT: decrypted secret value +) +{ + TPM_RC result = TPM_RC_SUCCESS; + + // Decryption for secret + switch(decryptKey->publicArea.type) + { +#if ALG_RSA + case TPM_ALG_RSA: + { + TPMT_RSA_DECRYPT scheme; + TPMT_RSA_SCHEME* keyScheme = + &decryptKey->publicArea.parameters.rsaDetail.scheme; + UINT16 digestSize; + + scheme = *(TPMT_RSA_DECRYPT*)keyScheme; + // If the key scheme is TPM_ALG_NULL, set the scheme to OAEP and + // set the algorithm to the name algorithm. + if(scheme.scheme == TPM_ALG_NULL) + { + // Use OAEP scheme + scheme.scheme = TPM_ALG_OAEP; + scheme.details.oaep.hashAlg = decryptKey->publicArea.nameAlg; + } + // use the digestSize as an indicator of whether or not the scheme + // is using a supported hash algorithm. + // Note: depending on the scheme used for encryption, a hashAlg might + // not be needed. However, the return value has to have some upper + // limit on the size. In this case, it is the size of the digest of the + // hash algorithm. It is checked after the decryption is done but, there + // is no point in doing the decryption if the size is going to be + // 'wrong' anyway. + digestSize = CryptHashGetDigestSize(scheme.details.oaep.hashAlg); + if(scheme.scheme != TPM_ALG_OAEP || digestSize == 0) + return TPM_RC_SCHEME; + + // Set the output buffer capacity + data->t.size = sizeof(data->t.buffer); + + // Decrypt seed by RSA OAEP + result = + CryptRsaDecrypt(&data->b, &secret->b, decryptKey, &scheme, label); + if((result == TPM_RC_SUCCESS) && (data->t.size > digestSize)) + result = TPM_RC_VALUE; + } + break; +#endif // ALG_RSA +#if ALG_ECC + case TPM_ALG_ECC: + { + TPMS_ECC_POINT eccPublic; + TPMS_ECC_POINT eccSecret; + BYTE* buffer = secret->t.secret; + INT32 size = secret->t.size; + + // Retrieve ECC point from secret buffer + result = TPMS_ECC_POINT_Unmarshal(&eccPublic, &buffer, &size); + if(result == TPM_RC_SUCCESS) + { + result = CryptEccPointMultiply( + &eccSecret, + decryptKey->publicArea.parameters.eccDetail.curveID, + &eccPublic, + &decryptKey->sensitive.sensitive.ecc, + NULL, + NULL); + if(result == TPM_RC_SUCCESS) + { + // Set the size of the "recovered" secret value to be the size + // of the digest produced by the nameAlg. + data->t.size = + CryptHashGetDigestSize(decryptKey->publicArea.nameAlg); + + // The secret value is computed from Z using KDFe as: + // secret := KDFe(HashID, Z, Use, PartyUInfo, PartyVInfo, bits) + // Where: + // HashID -- the nameAlg of the decrypt key + // Z -- the x coordinate (Px) of the product (P) of the point + // (Q) of the secret and the private x coordinate (de,V) + // of the decryption key + // Use -- a null-terminated string containing "SECRET" + // PartyUInfo -- the x coordinate of the point in the secret + // (Qe,U ) + // PartyVInfo -- the x coordinate of the public key (Qs,V ) + // bits -- the number of bits in the digest of HashID + // Retrieve seed from KDFe + CryptKDFe(decryptKey->publicArea.nameAlg, + &eccSecret.x.b, + label, + &eccPublic.x.b, + &decryptKey->publicArea.unique.ecc.x.b, + data->t.size * 8, + data->t.buffer); + } + } + } + break; +#endif // ALG_ECC +#if !ALG_KEYEDHASH +# error "KEYEDHASH support is required" +#endif + case TPM_ALG_KEYEDHASH: + // The seed size can not be bigger than the digest size of nameAlg + if(secret->t.size + > CryptHashGetDigestSize(decryptKey->publicArea.nameAlg)) + result = TPM_RC_VALUE; + else + { + // Retrieve seed by XOR Obfuscation: + // seed = XOR(secret, hash, key, nonceCaller, nullNonce) + // where: + // secret the secret parameter from the TPM2_StartAuthHMAC + // command that contains the seed value + // hash nameAlg of tpmKey + // key the key or data value in the object referenced by + // entityHandle in the TPM2_StartAuthHMAC command + // nonceCaller the parameter from the TPM2_StartAuthHMAC command + // nullNonce a zero-length nonce + // XOR Obfuscation in place + CryptXORObfuscation(decryptKey->publicArea.nameAlg, + &decryptKey->sensitive.sensitive.bits.b, + &nonceCaller->b, + NULL, + secret->t.size, + secret->t.secret); + // Copy decrypted seed + MemoryCopy2B(&data->b, &secret->b, sizeof(data->t.buffer)); + } + break; + case TPM_ALG_SYMCIPHER: + { + TPM2B_IV iv = {{0}}; + TPMT_SYM_DEF_OBJECT* symDef; + // The seed size can not be bigger than the digest size of nameAlg + if(secret->t.size + > CryptHashGetDigestSize(decryptKey->publicArea.nameAlg)) + result = TPM_RC_VALUE; + else + { + symDef = &decryptKey->publicArea.parameters.symDetail.sym; + iv.t.size = CryptGetSymmetricBlockSize(symDef->algorithm, + symDef->keyBits.sym); + if(iv.t.size == 0) + return TPM_RC_FAILURE; + if(nonceCaller->t.size >= iv.t.size) + { + MemoryCopy(iv.t.buffer, nonceCaller->t.buffer, iv.t.size); + } + else + { + if(nonceCaller->t.size > sizeof(iv.t.buffer)) + return TPM_RC_FAILURE; + MemoryCopy( + iv.b.buffer, nonceCaller->t.buffer, nonceCaller->t.size); + } + // make sure secret will fit + if(secret->t.size > data->t.size) + return TPM_RC_FAILURE; + data->t.size = secret->t.size; + // CFB decrypt, using nonceCaller as iv + CryptSymmetricDecrypt(data->t.buffer, + symDef->algorithm, + symDef->keyBits.sym, + decryptKey->sensitive.sensitive.sym.t.buffer, + &iv, + TPM_ALG_CFB, + secret->t.size, + secret->t.secret); + } + } + break; + default: + FAIL(FATAL_ERROR_INTERNAL); + break; + } + return result; +} + +//*** CryptParameterEncryption() +// This function does in-place encryption of a response parameter. +void CryptParameterEncryption( + TPM_HANDLE handle, // IN: encrypt session handle + TPM2B* nonceCaller, // IN: nonce caller + INT32 bufferSize, // IN: size of parameter buffer + UINT16 leadingSizeInByte, // IN: the size of the leading size field in + // bytes + TPM2B_AUTH* extraKey, // IN: additional key material other than + // sessionAuth + BYTE* buffer // IN/OUT: parameter buffer to be encrypted +) +{ + SESSION* session = SessionGet(handle); // encrypt session + TPM2B_TYPE(TEMP_KEY, + (sizeof(extraKey->t.buffer) + sizeof(session->sessionKey.t.buffer))); + TPM2B_TEMP_KEY key; // encryption key + UINT16 cipherSize = 0; // size of cipher text + + if(bufferSize < leadingSizeInByte) + { + FAIL(FATAL_ERROR_INTERNAL); + return; + } + + // Parameter encryption for a non-2B is not supported. + if(leadingSizeInByte != 2) + { + FAIL(FATAL_ERROR_INTERNAL); + return; + } + + // Retrieve encrypted data size. + if(UINT16_Unmarshal(&cipherSize, &buffer, &bufferSize) != TPM_RC_SUCCESS) + { + FAIL(FATAL_ERROR_INTERNAL); + return; + } + + if(cipherSize > bufferSize) + { + FAIL(FATAL_ERROR_INTERNAL); + return; + } + + // Compute encryption key by concatenating sessionKey with extra key + MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer)); + MemoryConcat2B(&key.b, &extraKey->b, sizeof(key.t.buffer)); + + if(session->symmetric.algorithm == TPM_ALG_XOR) + + // XOR parameter encryption formulation: + // XOR(parameter, hash, sessionAuth, nonceNewer, nonceOlder) + CryptXORObfuscation(session->authHashAlg, + &(key.b), + &(session->nonceTPM.b), + nonceCaller, + (UINT32)cipherSize, + buffer); + else + ParmEncryptSym(session->symmetric.algorithm, + session->authHashAlg, + session->symmetric.keyBits.aes, + &(key.b), + nonceCaller, + &(session->nonceTPM.b), + (UINT32)cipherSize, + buffer); + return; +} + +//*** CryptParameterDecryption() +// This function does in-place decryption of a command parameter. +// Return Type: TPM_RC +// TPM_RC_SIZE The number of bytes in the input buffer is less than +// the number of bytes to be decrypted. +TPM_RC +CryptParameterDecryption( + TPM_HANDLE handle, // IN: encrypted session handle + TPM2B* nonceCaller, // IN: nonce caller + INT32 bufferSize, // IN: size of parameter buffer + UINT16 leadingSizeInByte, // IN: the size of the leading size field in + // byte + TPM2B_AUTH* extraKey, // IN: the authValue + BYTE* buffer // IN/OUT: parameter buffer to be decrypted +) +{ + SESSION* session = SessionGet(handle); // encrypt session + // The HMAC key is going to be the concatenation of the session key and any + // additional key material (like the authValue). The size of both of these + // is the size of the buffer which can contain a TPMT_HA. + TPM2B_TYPE(HMAC_KEY, + (sizeof(extraKey->t.buffer) + sizeof(session->sessionKey.t.buffer))); + TPM2B_HMAC_KEY key; // decryption key + UINT16 cipherSize = 0; // size of ciphertext + + if(bufferSize < leadingSizeInByte) + { + return TPM_RC_INSUFFICIENT; + } + + // Parameter encryption for a non-2B is not supported. + if(leadingSizeInByte != 2) + { + FAIL(FATAL_ERROR_INTERNAL); + return TPM_RC_FAILURE; + } + + // Retrieve encrypted data size. + if(UINT16_Unmarshal(&cipherSize, &buffer, &bufferSize) != TPM_RC_SUCCESS) + { + return TPM_RC_INSUFFICIENT; + } + + if(cipherSize > bufferSize) + { + return TPM_RC_SIZE; + } + + // Compute decryption key by concatenating sessionAuth with extra input key + MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer)); + MemoryConcat2B(&key.b, &extraKey->b, sizeof(key.t.buffer)); + + if(session->symmetric.algorithm == TPM_ALG_XOR) + // XOR parameter decryption formulation: + // XOR(parameter, hash, sessionAuth, nonceNewer, nonceOlder) + // Call XOR obfuscation function + CryptXORObfuscation(session->authHashAlg, + &key.b, + nonceCaller, + &(session->nonceTPM.b), + (UINT32)cipherSize, + buffer); + else + // Assume that it is one of the symmetric block ciphers. + ParmDecryptSym(session->symmetric.algorithm, + session->authHashAlg, + session->symmetric.keyBits.sym, + &key.b, + nonceCaller, + &session->nonceTPM.b, + (UINT32)cipherSize, + buffer); + + return TPM_RC_SUCCESS; +} + +//*** CryptComputeSymmetricUnique() +// This function computes the unique field in public area for symmetric objects. +void CryptComputeSymmetricUnique( + TPMT_PUBLIC* publicArea, // IN: the object's public area + TPMT_SENSITIVE* sensitive, // IN: the associated sensitive area + TPM2B_DIGEST* unique // OUT: unique buffer +) +{ + // For parents (symmetric and derivation), use an HMAC to compute + // the 'unique' field + if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted) + && IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, decrypt)) + { + // Unique field is HMAC(sensitive->seedValue, sensitive->sensitive) + HMAC_STATE hmacState; + unique->b.size = CryptHmacStart2B( + &hmacState, publicArea->nameAlg, &sensitive->seedValue.b); + CryptDigestUpdate2B(&hmacState.hashState, &sensitive->sensitive.any.b); + CryptHmacEnd2B(&hmacState, &unique->b); + } + else + { + HASH_STATE hashState; + // Unique := Hash(sensitive->seedValue || sensitive->sensitive) + unique->t.size = CryptHashStart(&hashState, publicArea->nameAlg); + CryptDigestUpdate2B(&hashState, &sensitive->seedValue.b); + CryptDigestUpdate2B(&hashState, &sensitive->sensitive.any.b); + CryptHashEnd2B(&hashState, &unique->b); + } + return; +} + +//*** CryptCreateObject() +// This function creates an object. +// For an asymmetric key, it will create a key pair and, for a parent key, a seed +// value for child protections. +// +// For an symmetric object, (TPM_ALG_SYMCIPHER or TPM_ALG_KEYEDHASH), it will +// create a secret key if the caller did not provide one. It will create a random +// secret seed value that is hashed with the secret value to create the public +// unique value. +// +// 'publicArea', 'sensitive', and 'sensitiveCreate' are the only required parameters +// and are the only ones that are used by TPM2_Create(). The other parameters +// are optional and are used when the generated Object needs to be deterministic. +// This is the case for both Primary Objects and Derived Objects. +// +// When a seed value is provided, a RAND_STATE will be populated and used for +// all operations in the object generation that require a random number. In the +// simplest case, TPM2_CreatePrimary() will use 'seed', 'label' and 'context' with +// context being the hash of the template. If the Primary Object is in +// the Endorsement hierarchy, it will also populate 'proof' with ehProof. +// +// For derived keys, 'seed' will be the secret value from the parent, 'label' and +// 'context' will be set according to the parameters of TPM2_CreateLoaded() and +// 'hashAlg' will be set which causes the RAND_STATE to be a KDF generator. +// +// Return Type: TPM_RC +// TPM_RC_KEY a provided key is not an allowed value +// TPM_RC_KEY_SIZE key size in the public area does not match the size +// in the sensitive creation area for a symmetric key +// TPM_RC_NO_RESULT unable to get random values (only in derivation) +// TPM_RC_RANGE for an RSA key, the exponent is not supported +// TPM_RC_SIZE sensitive data size is larger than allowed for the +// scheme for a keyed hash object +// TPM_RC_VALUE exponent is not prime or could not find a prime using +// the provided parameters for an RSA key; +// unsupported name algorithm for an ECC key +TPM_RC +CryptCreateObject(OBJECT* object, // IN: new object structure pointer + TPMS_SENSITIVE_CREATE* sensitiveCreate, // IN: sensitive creation + RAND_STATE* rand // IN: the random number generator + // to use +) +{ + TPMT_PUBLIC* publicArea = &object->publicArea; + TPMT_SENSITIVE* sensitive = &object->sensitive; + TPM_RC result = TPM_RC_SUCCESS; + // + // Set the sensitive type for the object + sensitive->sensitiveType = publicArea->type; + + // For all objects, copy the initial authorization data + sensitive->authValue = sensitiveCreate->userAuth; + + // If the TPM is the source of the data, set the size of the provided data to + // zero so that there's no confusion about what to do. + if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sensitiveDataOrigin)) + sensitiveCreate->data.t.size = 0; + + // Generate the key and unique fields for the asymmetric keys and just the + // sensitive value for symmetric object + switch(publicArea->type) + { +#if ALG_RSA + // Create RSA key + case TPM_ALG_RSA: + // RSA uses full object so that it has a place to put the private + // exponent + result = CryptRsaGenerateKey(publicArea, sensitive, rand); + break; +#endif // ALG_RSA + +#if ALG_ECC + // Create ECC key + case TPM_ALG_ECC: + result = CryptEccGenerateKey(publicArea, sensitive, rand); + break; +#endif // ALG_ECC + case TPM_ALG_SYMCIPHER: + result = CryptGenerateKeySymmetric( + publicArea, sensitive, sensitiveCreate, rand); + break; + case TPM_ALG_KEYEDHASH: + result = + CryptGenerateKeyedHash(publicArea, sensitive, sensitiveCreate, rand); + break; + default: + FAIL(FATAL_ERROR_INTERNAL); + break; + } + if(result != TPM_RC_SUCCESS) + return result; + // Create the sensitive seed value + // If this is a primary key in the endorsement hierarchy, stir the DRBG state + // This implementation uses both shProof and ehProof to make sure that there + // is no leakage of either. + if(object->attributes.primary && object->attributes.epsHierarchy) + { + DRBG_AdditionalData((DRBG_STATE*)rand, &gp.shProof.b); + DRBG_AdditionalData((DRBG_STATE*)rand, &gp.ehProof.b); + } + // Generate a seedValue that is the size of the digest produced by nameAlg + sensitive->seedValue.t.size = + DRBG_Generate(rand, + sensitive->seedValue.t.buffer, + CryptHashGetDigestSize(publicArea->nameAlg)); + if(g_inFailureMode) + return TPM_RC_FAILURE; + else if(sensitive->seedValue.t.size == 0) + return TPM_RC_NO_RESULT; + // For symmetric objects, need to compute the unique value for the public area + if(publicArea->type == TPM_ALG_SYMCIPHER || publicArea->type == TPM_ALG_KEYEDHASH) + { + CryptComputeSymmetricUnique(publicArea, sensitive, &publicArea->unique.sym); + } + else + { + // if this is an asymmetric key and it isn't a parent, then + // get rid of the seed. + if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign) + || !IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted)) + memset(&sensitive->seedValue, 0, sizeof(sensitive->seedValue)); + } + // Compute the name + PublicMarshalAndComputeName(publicArea, &object->name); + return result; +} + +//*** CryptGetSignHashAlg() +// Get the hash algorithm of signature from a TPMT_SIGNATURE structure. +// It assumes the signature is not NULL +// This is a function for easy access +TPMI_ALG_HASH +CryptGetSignHashAlg(TPMT_SIGNATURE* auth // IN: signature +) +{ + if(auth->sigAlg == TPM_ALG_NULL) + FAIL(FATAL_ERROR_INTERNAL); + + // Get authHash algorithm based on signing scheme + switch(auth->sigAlg) + { +#if ALG_RSA + // If RSA is supported, both RSASSA and RSAPSS are required +# if !defined TPM_ALG_RSASSA || !defined TPM_ALG_RSAPSS +# error "RSASSA and RSAPSS are required for RSA" +# endif + case TPM_ALG_RSASSA: + return auth->signature.rsassa.hash; + case TPM_ALG_RSAPSS: + return auth->signature.rsapss.hash; +#endif // ALG_RSA + +#if ALG_ECC + // If ECC is defined, ECDSA is mandatory +# if !ALG_ECDSA +# error "ECDSA is requried for ECC" +# endif + case TPM_ALG_ECDSA: + // SM2 and ECSCHNORR are optional + +# if ALG_SM2 + case TPM_ALG_SM2: +# endif +# if ALG_ECSCHNORR + case TPM_ALG_ECSCHNORR: +# endif + //all ECC signatures look the same + return auth->signature.ecdsa.hash; + +# if ALG_ECDAA + // Don't know how to verify an ECDAA signature + case TPM_ALG_ECDAA: + break; +# endif + +#endif // ALG_ECC + + case TPM_ALG_HMAC: + return auth->signature.hmac.hashAlg; + + default: + break; + } + return TPM_ALG_NULL; +} + +//*** CryptIsSplitSign() +// This function us used to determine if the signing operation is a split +// signing operation that required a TPM2_Commit(). +// +BOOL CryptIsSplitSign(TPM_ALG_ID scheme // IN: the algorithm selector +) +{ + switch(scheme) + { +#if ALG_ECDAA + case TPM_ALG_ECDAA: + return TRUE; + break; +#endif // ALG_ECDAA + default: + return FALSE; + break; + } +} + +//*** CryptIsAsymSignScheme() +// This function indicates if a scheme algorithm is a sign algorithm. +BOOL CryptIsAsymSignScheme(TPMI_ALG_PUBLIC publicType, // IN: Type of the object + TPMI_ALG_ASYM_SCHEME scheme // IN: the scheme +) +{ + BOOL isSignScheme = TRUE; + + switch(publicType) + { +#if ALG_RSA + case TPM_ALG_RSA: + switch(scheme) + { +# if !ALG_RSASSA || !ALG_RSAPSS +# error "RSASSA and PSAPSS required if RSA used." +# endif + case TPM_ALG_RSASSA: + case TPM_ALG_RSAPSS: + break; + default: + isSignScheme = FALSE; + break; + } + break; +#endif // ALG_RSA + +#if ALG_ECC + // If ECC is implemented ECDSA is required + case TPM_ALG_ECC: + switch(scheme) + { + // Support for ECDSA is required for ECC + case TPM_ALG_ECDSA: +# if ALG_ECDAA // ECDAA is optional + case TPM_ALG_ECDAA: +# endif +# if ALG_ECSCHNORR // Schnorr is also optional + case TPM_ALG_ECSCHNORR: +# endif +# if ALG_SM2 // SM2 is optional + case TPM_ALG_SM2: +# endif + break; + default: + isSignScheme = FALSE; + break; + } + break; +#endif // ALG_ECC + default: + isSignScheme = FALSE; + break; + } + return isSignScheme; +} + +//*** CryptIsAsymDecryptScheme() +// This function indicate if a scheme algorithm is a decrypt algorithm. +BOOL CryptIsAsymDecryptScheme(TPMI_ALG_PUBLIC publicType, // IN: Type of the object + TPMI_ALG_ASYM_SCHEME scheme // IN: the scheme +) +{ + BOOL isDecryptScheme = TRUE; + + switch(publicType) + { +#if ALG_RSA + case TPM_ALG_RSA: + switch(scheme) + { + case TPM_ALG_RSAES: + case TPM_ALG_OAEP: + break; + default: + isDecryptScheme = FALSE; + break; + } + break; +#endif // ALG_RSA + +#if ALG_ECC + // If ECC is implemented ECDH is required + case TPM_ALG_ECC: + switch(scheme) + { +# if !ALG_ECDH +# error "ECDH is required for ECC" +# endif + case TPM_ALG_ECDH: +# if ALG_SM2 + case TPM_ALG_SM2: +# endif +# if ALG_ECMQV + case TPM_ALG_ECMQV: +# endif + break; + default: + isDecryptScheme = FALSE; + break; + } + break; +#endif // ALG_ECC + default: + isDecryptScheme = FALSE; + break; + } + return isDecryptScheme; +} + +//*** CryptSelectSignScheme() +// This function is used by the attestation and signing commands. It implements +// the rules for selecting the signature scheme to use in signing. This function +// requires that the signing key either be TPM_RH_NULL or be loaded. +// +// If a default scheme is defined in object, the default scheme should be chosen, +// otherwise, the input scheme should be chosen. +// In the case that both object and input scheme has a non-NULL scheme +// algorithm, if the schemes are compatible, the input scheme will be chosen. +// +// This function should not be called if 'signObject->publicArea.type' == +// ALG_SYMCIPHER. +// +// Return Type: BOOL +// TRUE(1) scheme selected +// FALSE(0) both 'scheme' and key's default scheme are empty; or +// 'scheme' is empty while key's default scheme requires +// explicit input scheme (split signing); or +// non-empty default key scheme differs from 'scheme' +BOOL CryptSelectSignScheme(OBJECT* signObject, // IN: signing key + TPMT_SIG_SCHEME* scheme // IN/OUT: signing scheme +) +{ + TPMT_SIG_SCHEME* objectScheme; + TPMT_PUBLIC* publicArea; + BOOL OK; + + // If the signHandle is TPM_RH_NULL, then the NULL scheme is used, regardless + // of the setting of scheme + if(signObject == NULL) + { + OK = TRUE; + scheme->scheme = TPM_ALG_NULL; + scheme->details.any.hashAlg = TPM_ALG_NULL; + } + else + { + // assignment to save typing. + publicArea = &signObject->publicArea; + + // A symmetric cipher can be used to encrypt and decrypt but it can't + // be used for signing + if(publicArea->type == TPM_ALG_SYMCIPHER) + return FALSE; + // Point to the scheme object + if(CryptIsAsymAlgorithm(publicArea->type)) + objectScheme = + (TPMT_SIG_SCHEME*)&publicArea->parameters.asymDetail.scheme; + else + objectScheme = + (TPMT_SIG_SCHEME*)&publicArea->parameters.keyedHashDetail.scheme; + + // If the object doesn't have a default scheme, then use the + // input scheme. + if(objectScheme->scheme == TPM_ALG_NULL) + { + // Input and default can't both be NULL + OK = (scheme->scheme != TPM_ALG_NULL); + // Assume that the scheme is compatible with the key. If not, + // an error will be generated in the signing operation. + } + else if(scheme->scheme == TPM_ALG_NULL) + { + // input scheme is NULL so use default + + // First, check to see if the default requires that the caller + // provided scheme data + OK = !CryptIsSplitSign(objectScheme->scheme); + if(OK) + { + // The object has a scheme and the input is TPM_ALG_NULL so copy + // the object scheme as the final scheme. It is better to use a + // structure copy than a copy of the individual fields. + *scheme = *objectScheme; + } + } + else + { + // Both input and object have scheme selectors + // If the scheme and the hash are not the same then... + // NOTE: the reason that there is no copy here is that the input + // might contain extra data for a split signing scheme and that + // data is not in the object so, it has to be preserved. + OK = + (objectScheme->scheme == scheme->scheme) + && (objectScheme->details.any.hashAlg == scheme->details.any.hashAlg); + } + } + return OK; +} + +//*** CryptSign() +// Sign a digest with asymmetric key or HMAC. +// This function is called by attestation commands and the generic TPM2_Sign +// command. +// This function checks the key scheme and digest size. It does not +// check if the sign operation is allowed for restricted key. It should be +// checked before the function is called. +// The function will assert if the key is not a signing key. +// +// Return Type: TPM_RC +// TPM_RC_SCHEME 'signScheme' is not compatible with the signing key type +// TPM_RC_VALUE 'digest' value is greater than the modulus of +// 'signHandle' or size of 'hashData' does not match hash +// algorithm in'signScheme' (for an RSA key); +// invalid commit status or failed to generate "r" value +// (for an ECC key) +TPM_RC +CryptSign(OBJECT* signKey, // IN: signing key + TPMT_SIG_SCHEME* signScheme, // IN: sign scheme. + TPM2B_DIGEST* digest, // IN: The digest being signed + TPMT_SIGNATURE* signature // OUT: signature +) +{ + TPM_RC result = TPM_RC_SCHEME; + + // Initialize signature scheme + signature->sigAlg = signScheme->scheme; + + // If the signature algorithm is TPM_ALG_NULL or the signing key is NULL, + // then we are done + if((signature->sigAlg == TPM_ALG_NULL) || (signKey == NULL)) + return TPM_RC_SUCCESS; + + // Initialize signature hash + // Note: need to do the check for TPM_ALG_NULL first because the null scheme + // doesn't have a hashAlg member. + signature->signature.any.hashAlg = signScheme->details.any.hashAlg; + + // perform sign operation based on different key type + switch(signKey->publicArea.type) + { +#if ALG_RSA + case TPM_ALG_RSA: + result = CryptRsaSign(signature, signKey, digest, NULL); + break; +#endif // ALG_RSA +#if ALG_ECC + case TPM_ALG_ECC: + // The reason that signScheme is passed to CryptEccSign but not to the + // other signing methods is that the signing for ECC may be split and + // need the 'r' value that is in the scheme but not in the signature. + result = CryptEccSign( + signature, signKey, digest, (TPMT_ECC_SCHEME*)signScheme, NULL); + break; +#endif // ALG_ECC + case TPM_ALG_KEYEDHASH: + result = CryptHmacSign(signature, signKey, digest); + break; + default: + FAIL(FATAL_ERROR_INTERNAL); + break; + } + return result; +} + +//*** CryptValidateSignature() +// This function is used to verify a signature. It is called by +// TPM2_VerifySignature() and TPM2_PolicySigned. +// +// Since this operation only requires use of a public key, no consistency +// checks are necessary for the key to signature type because a caller can load +// any public key that they like with any scheme that they like. This routine +// simply makes sure that the signature is correct, whatever the type. +// +// Return Type: TPM_RC +// TPM_RC_SIGNATURE the signature is not genuine +// TPM_RC_SCHEME the scheme is not supported +// TPM_RC_HANDLE an HMAC key was selected but the +// private part of the key is not loaded +TPM_RC +CryptValidateSignature(TPMI_DH_OBJECT keyHandle, // IN: The handle of sign key + TPM2B_DIGEST* digest, // IN: The digest being validated + TPMT_SIGNATURE* signature // IN: signature +) +{ + // NOTE: HandleToObject will either return a pointer to a loaded object or + // will assert. It will never return a non-valid value. This makes it save + // to initialize 'publicArea' with the return value from HandleToObject() + // without checking it first. + OBJECT* signObject = HandleToObject(keyHandle); + TPMT_PUBLIC* publicArea = &signObject->publicArea; + TPM_RC result = TPM_RC_SCHEME; + + // The input unmarshaling should prevent any input signature from being + // a NULL signature, but just in case + if(signature->sigAlg == TPM_ALG_NULL) + return TPM_RC_SIGNATURE; + + switch(publicArea->type) + { +#if ALG_RSA + case TPM_ALG_RSA: + { + // + // Call RSA code to verify signature + result = CryptRsaValidateSignature(signature, signObject, digest); + break; + } +#endif // ALG_RSA + +#if ALG_ECC + case TPM_ALG_ECC: + result = CryptEccValidateSignature(signature, signObject, digest); + break; +#endif // ALG_ECC + + case TPM_ALG_KEYEDHASH: + if(signObject->attributes.publicOnly) + result = TPM_RCS_HANDLE; + else + result = CryptHMACVerifySignature(signObject, digest, signature); + break; + default: + break; + } + return result; +} + +//*** CryptGetTestResult +// This function returns the results of a self-test function. +// Note: the behavior in this function is NOT the correct behavior for a real +// TPM implementation. An artificial behavior is placed here due to the +// limitation of a software simulation environment. For the correct behavior, +// consult the part 3 specification for TPM2_GetTestResult(). +TPM_RC +CryptGetTestResult(TPM2B_MAX_BUFFER* outData // OUT: test result data +) +{ + outData->t.size = 0; + return TPM_RC_SUCCESS; +} + +//*** CryptValidateKeys() +// This function is used to verify that the key material of and object is valid. +// For a 'publicOnly' object, the key is verified for size and, if it is an ECC +// key, it is verified to be on the specified curve. For a key with a sensitive +// area, the binding between the public and private parts of the key are verified. +// If the nameAlg of the key is TPM_ALG_NULL, then the size of the sensitive area +// is verified but the public portion is not verified, unless the key is an RSA key. +// For an RSA key, the reason for loading the sensitive area is to use it. The +// only way to use a private RSA key is to compute the private exponent. To compute +// the private exponent, the public modulus is used. +// Return Type: TPM_RC +// TPM_RC_BINDING the public and private parts are not cryptographically +// bound +// TPM_RC_HASH cannot have a publicOnly key with nameAlg of TPM_ALG_NULL +// TPM_RC_KEY the public unique is not valid +// TPM_RC_KEY_SIZE the private area key is not valid +// TPM_RC_TYPE the types of the sensitive and private parts do not match +TPM_RC +CryptValidateKeys(TPMT_PUBLIC* publicArea, + TPMT_SENSITIVE* sensitive, + TPM_RC blamePublic, + TPM_RC blameSensitive) +{ + TPM_RC result; + UINT16 keySizeInBytes; + UINT16 digestSize = CryptHashGetDigestSize(publicArea->nameAlg); + TPMU_PUBLIC_PARMS* params = &publicArea->parameters; + TPMU_PUBLIC_ID* unique = &publicArea->unique; + + if(sensitive != NULL) + { + // Make sure that the types of the public and sensitive are compatible + if(publicArea->type != sensitive->sensitiveType) + return TPM_RCS_TYPE + blameSensitive; + // Make sure that the authValue is not bigger than allowed + // If there is no name algorithm, then the size just needs to be less than + // the maximum size of the buffer used for authorization. That size check + // was made during unmarshaling of the sensitive area + if((sensitive->authValue.t.size) > digestSize && (digestSize > 0)) + return TPM_RCS_SIZE + blameSensitive; + } + switch(publicArea->type) + { +#if ALG_RSA + case TPM_ALG_RSA: + keySizeInBytes = BITS_TO_BYTES(params->rsaDetail.keyBits); + + // Regardless of whether there is a sensitive area, the public modulus + // needs to have the correct size. Otherwise, it can't be used for + // any public key operation nor can it be used to compute the private + // exponent. + // NOTE: This implementation only supports key sizes that are multiples + // of 1024 bits which means that the MSb of the 0th byte will always be + // SET in any prime and in the public modulus. + if((unique->rsa.t.size != keySizeInBytes) + || (unique->rsa.t.buffer[0] < 0x80)) + return TPM_RCS_KEY + blamePublic; + if(params->rsaDetail.exponent != 0 && params->rsaDetail.exponent < 7) + return TPM_RCS_VALUE + blamePublic; + if(sensitive != NULL) + { + // If there is a sensitive area, it has to be the correct size + // including having the correct high order bit SET. + if(((sensitive->sensitive.rsa.t.size * 2) != keySizeInBytes) + || (sensitive->sensitive.rsa.t.buffer[0] < 0x80)) + return TPM_RCS_KEY_SIZE + blameSensitive; + } + break; +#endif +#if ALG_ECC + case TPM_ALG_ECC: + { + TPMI_ECC_CURVE curveId; + curveId = params->eccDetail.curveID; + keySizeInBytes = BITS_TO_BYTES(CryptEccGetKeySizeForCurve(curveId)); + if(sensitive == NULL) + { + // Validate the public key size + if(unique->ecc.x.t.size != keySizeInBytes + || unique->ecc.y.t.size != keySizeInBytes) + return TPM_RCS_KEY + blamePublic; + if(publicArea->nameAlg != TPM_ALG_NULL) + { + if(!CryptEccIsPointOnCurve(curveId, &unique->ecc)) + return TPM_RCS_ECC_POINT + blamePublic; + } + } + else + { + // If the nameAlg is TPM_ALG_NULL, then only verify that the + // private part of the key is OK. + if(!CryptEccIsValidPrivateKey(&sensitive->sensitive.ecc, curveId)) + return TPM_RCS_KEY_SIZE; + if(publicArea->nameAlg != TPM_ALG_NULL) + { + // Full key load, verify that the public point belongs to the + // private key. + TPMS_ECC_POINT toCompare; + result = CryptEccPointMultiply(&toCompare, + curveId, + NULL, + &sensitive->sensitive.ecc, + NULL, + NULL); + if(result != TPM_RC_SUCCESS) + return TPM_RCS_BINDING; + else + { + // Make sure that the private key generated the public key. + // The input values and the values produced by the point + // multiply may not be the same size so adjust the computed + // value to match the size of the input value by adding or + // removing zeros. + AdjustNumberB(&toCompare.x.b, unique->ecc.x.t.size); + AdjustNumberB(&toCompare.y.b, unique->ecc.y.t.size); + if(!MemoryEqual2B(&unique->ecc.x.b, &toCompare.x.b) + || !MemoryEqual2B(&unique->ecc.y.b, &toCompare.y.b)) + return TPM_RCS_BINDING; + } + } + } + break; + } +#endif + default: + // Checks for SYMCIPHER and KEYEDHASH are largely the same + // If public area has a nameAlg, then validate the public area size + // and if there is also a sensitive area, validate the binding + + // For consistency, if the object is public-only just make sure that + // the unique field is consistent with the name algorithm + if(sensitive == NULL) + { + if(unique->sym.t.size != digestSize) + return TPM_RCS_KEY + blamePublic; + } + else + { + // Make sure that the key size in the sensitive area is consistent. + if(publicArea->type == TPM_ALG_SYMCIPHER) + { + result = CryptSymKeyValidate(¶ms->symDetail.sym, + &sensitive->sensitive.sym); + if(result != TPM_RC_SUCCESS) + return result + blameSensitive; + } + else + { + // For a keyed hash object, the key has to be less than the + // smaller of the block size of the hash used in the scheme or + // 128 bytes. The worst case value is limited by the + // unmarshaling code so the only thing left to be checked is + // that it does not exceed the block size of the hash. + // by the hash algorithm of the scheme. + TPMT_KEYEDHASH_SCHEME* scheme; + UINT16 maxSize; + scheme = ¶ms->keyedHashDetail.scheme; + if(scheme->scheme == TPM_ALG_XOR) + { + maxSize = CryptHashGetBlockSize(scheme->details.xor.hashAlg); + } + else if(scheme->scheme == TPM_ALG_HMAC) + { + maxSize = CryptHashGetBlockSize(scheme->details.hmac.hashAlg); + } + else if(scheme->scheme == TPM_ALG_NULL) + { + // Not signing or xor so must be a data block + maxSize = 128; + } + else + return TPM_RCS_SCHEME + blamePublic; + if(sensitive->sensitive.bits.t.size > maxSize) + return TPM_RCS_KEY_SIZE + blameSensitive; + } + // If there is a nameAlg, check the binding + if(publicArea->nameAlg != TPM_ALG_NULL) + { + TPM2B_DIGEST compare; + if(sensitive->seedValue.t.size != digestSize) + return TPM_RCS_KEY_SIZE + blameSensitive; + + CryptComputeSymmetricUnique(publicArea, sensitive, &compare); + if(!MemoryEqual2B(&unique->sym.b, &compare.b)) + return TPM_RC_BINDING; + } + } + break; + } + // For a parent, need to check that the seedValue is the correct size for + // protections. It should be at least half the size of the nameAlg + if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted) + && IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, decrypt) + && sensitive != NULL && publicArea->nameAlg != TPM_ALG_NULL) + { + if((sensitive->seedValue.t.size < (digestSize / 2)) + || (sensitive->seedValue.t.size > digestSize)) + return TPM_RCS_SIZE + blameSensitive; + } + return TPM_RC_SUCCESS; +} + +//*** CryptSelectMac() +// This function is used to set the MAC scheme based on the key parameters and +// the input scheme. +// Return Type: TPM_RC +// TPM_RC_SCHEME the scheme is not a valid mac scheme +// TPM_RC_TYPE the input key is not a type that supports a mac +// TPM_RC_VALUE the input scheme and the key scheme are not compatible +TPM_RC +CryptSelectMac(TPMT_PUBLIC* publicArea, TPMI_ALG_MAC_SCHEME* inMac) +{ + TPM_ALG_ID macAlg = TPM_ALG_NULL; + switch(publicArea->type) + { + case TPM_ALG_KEYEDHASH: + { + // Local value to keep lines from getting too long + TPMT_KEYEDHASH_SCHEME* scheme; + scheme = &publicArea->parameters.keyedHashDetail.scheme; + // Expect that the scheme is either HMAC or NULL + if(scheme->scheme != TPM_ALG_NULL) + macAlg = scheme->details.hmac.hashAlg; + break; + } + case TPM_ALG_SYMCIPHER: + { + TPMT_SYM_DEF_OBJECT* scheme; + scheme = &publicArea->parameters.symDetail.sym; + // Expect that the scheme is either valid symmetric cipher or NULL + if(scheme->algorithm != TPM_ALG_NULL) + macAlg = scheme->mode.sym; + break; + } + default: + return TPM_RCS_TYPE; + } + // If the input value is not TPM_ALG_NULL ... + if(*inMac != TPM_ALG_NULL) + { + // ... then either the scheme in the key must be TPM_ALG_NULL or the input + // value must match + if((macAlg != TPM_ALG_NULL) && (*inMac != macAlg)) + return TPM_RCS_VALUE; + } + else + { + // Since the input value is TPM_ALG_NULL, then the key value can't be + // TPM_ALG_NULL + if(macAlg == TPM_ALG_NULL) + return TPM_RCS_VALUE; + *inMac = macAlg; + } + if(!CryptMacIsValidForKey(publicArea->type, *inMac, FALSE)) + return TPM_RCS_SCHEME; + return TPM_RC_SUCCESS; +} + +//*** CryptMacIsValidForKey() +// Check to see if the key type is compatible with the mac type +BOOL CryptMacIsValidForKey(TPM_ALG_ID keyType, TPM_ALG_ID macAlg, BOOL flag) +{ + switch(keyType) + { + case TPM_ALG_KEYEDHASH: + return CryptHashIsValidAlg(macAlg, flag); + break; + case TPM_ALG_SYMCIPHER: + return CryptSmacIsValidAlg(macAlg, flag); + break; + default: + break; + } + return FALSE; +} + +//*** CryptSmacIsValidAlg() +// This function is used to test if an algorithm is a supported SMAC algorithm. It +// needs to be updated as new algorithms are added. +BOOL CryptSmacIsValidAlg(TPM_ALG_ID alg, + BOOL FLAG // IN: Indicates if TPM_ALG_NULL is valid +) +{ + switch(alg) + { +#if ALG_CMAC + case TPM_ALG_CMAC: + return TRUE; + break; +#endif + case TPM_ALG_NULL: + return FLAG; + break; + default: + return FALSE; + } +} + +//*** CryptSymModeIsValid() +// Function checks to see if an algorithm ID is a valid, symmetric block cipher +// mode for the TPM. If 'flag' is SET, them TPM_ALG_NULL is a valid mode. +// not include the modes used for SMAC +BOOL CryptSymModeIsValid(TPM_ALG_ID mode, BOOL flag) +{ + switch(mode) + { +#if ALG_CTR + case TPM_ALG_CTR: +#endif // ALG_CTR +#if ALG_OFB + case TPM_ALG_OFB: +#endif // ALG_OFB +#if ALG_CBC + case TPM_ALG_CBC: +#endif // ALG_CBC +#if ALG_CFB + case TPM_ALG_CFB: +#endif // ALG_CFB +#if ALG_ECB + case TPM_ALG_ECB: +#endif // ALG_ECB + return TRUE; + case TPM_ALG_NULL: + return flag; + break; + default: + break; + } + return FALSE; +} diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/Mbedtls/Mbedtls_mpi_Ltc_desc.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/Mbedtls/Mbedtls_mpi_Ltc_desc.c new file mode 100644 index 0000000..01b5249 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/Mbedtls/Mbedtls_mpi_Ltc_desc.c @@ -0,0 +1,600 @@ +/* + * Copyright (c) 2018, Linaro Limited + * Copyright (c) 2023-2024, NVIDIA Corporation & AFFILIATES. All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause + * + * The original source is from optee_os/core/lib/libtomcrypt/mpi_desc.c + */ + +#include +#include +#include +#include +#include + +/* 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)) + +static int init(void **a) +{ + mbedtls_mpi *bn = calloc(1, sizeof(*bn)); + + if (!bn) + return CRYPT_MEM; + + mbedtls_mpi_init(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); + free(a); +} + +static int neg(void *a, void *b) +{ + if (mbedtls_mpi_copy(b, a)) + return CRYPT_MEM; + + ((mbedtls_mpi *)b)->MBEDTLS_PRIVATE(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 = { .MBEDTLS_PRIVATE(s) = 1, + .MBEDTLS_PRIVATE(n) = 1, + .MBEDTLS_PRIVATE(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->MBEDTLS_PRIVATE(n)) + return 0; + + return bn->MBEDTLS_PRIVATE(p)[bn->MBEDTLS_PRIVATE(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->MBEDTLS_PRIVATE(n)) + return 0; + + return bn->MBEDTLS_PRIVATE(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(&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; +} + +/* 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 = { .MBEDTLS_PRIVATE(s) = 1, + .MBEDTLS_PRIVATE(n) = 1, + .MBEDTLS_PRIVATE(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 = { .MBEDTLS_PRIVATE(s) = 1, + .MBEDTLS_PRIVATE(n) = 1, + .MBEDTLS_PRIVATE(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(&bn_b); + mbedtls_mpi_init(&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(&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(&ta); + mbedtls_mpi_init(&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 = calloc(1, 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(&T); + mbedtls_mpi_init(&A); + + if (mbedtls_mpi_grow(&T, (N->MBEDTLS_PRIVATE(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->MBEDTLS_PRIVATE(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) +{ + free(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(&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; +} + +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, + + .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, + +#ifdef LTC_MECC + .ecc_ptmul = ltc_ecc_mulmod, + .ecc_ptadd = ltc_ecc_projective_add_point, + .ecc_ptdbl = ltc_ecc_projective_dbl_point, + .ecc_map = ltc_ecc_map, + + .ecc_mul2add = ltc_ecc_mul2add, +#endif /* LTC_MECC */ + + .addmod = addmod, + .submod = submod, +}; diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/Mbedtls/TpmToMbedtlsMath.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/Mbedtls/TpmToMbedtlsMath.c new file mode 100644 index 0000000..b01fbdc --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/Mbedtls/TpmToMbedtlsMath.c @@ -0,0 +1,476 @@ +/* + * Copyright (c) 2023-2024, NVIDIA Corporation & AFFILIATES. All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +//** Introduction +// The functions in this file provide the low-level interface between the TPM code +// and the big number and elliptic curve math routines in MbedTLS. + +//** Includes and Defines +#include "Tpm.h" + +#ifdef MATH_LIB_MBEDTLS +#include "TpmToMbedtlsMath_fp.h" + +#define DIV_ROUND_UP(x,y) ((x + y - 1)/y) + +//*** BnFromMbedtls() +// This function converts a mbedtls_mpi to a TPM bignum. In this implementation +// it is assumed that Mbedtls used the same format for a big number as does the +// TPM -- an array of native-endian words in little-endian order. +void +BnFromMbedtls( + bigNum bn, + mbedtls_mpi *mbedBn + ) +{ + if(bn != NULL) + { + mbedtls_mpi_write_binary_le(mbedBn, (unsigned char*)bn->d, + BnGetAllocated(bn) * sizeof(crypt_uword_t)); + + BnSetTop(bn, DIV_ROUND_UP(mbedtls_mpi_size(mbedBn), sizeof(crypt_uword_t))); + } +} + +//*** BnToMbedtls() +// This function converts a TPM bignum to a mbedtls_mpi, and has the same +// assumptions as made by BnFromMbedtls(). +void +BnToMbedtls( + mbedtls_mpi *toInit, + bigConst initializer + ) +{ + if ((toInit != NULL) && (initializer != NULL)) + mbedtls_mpi_read_binary_le(toInit, (unsigned char*)initializer->d, + initializer->size * sizeof(crypt_uword_t)); +} + +//*** MpiInitialize() +// This function initializes an MbedTls mbedtls_mpi. +mbedtls_mpi * +MpiInitialize( + mbedtls_mpi *toInit + ) +{ + mbedtls_mpi_init(toInit); + return toInit; +} + +#if LIBRARY_COMPATIBILITY_CHECK +//** MathLibraryCompatibilityCheck() +// This function is only used during development to make sure that the library +// that is being referenced is using the same size of data structures as the TPM. +BOOL +MathLibraryCompatibilityCheck( + void + ) +{ + BN_VAR(tpmTemp, 64 * 8); // allocate some space for a test value + crypt_uword_t i; + TPM2B_TYPE(TEST, 32); + TPM2B_TEST test = {{32, {0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x18, + 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, + 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00}}}; + // Convert the test TPM2B to a bigNum + BnFrom2B(tpmTemp, &test.b); + MPI_INITIALIZED(mbedTemp, tpmTemp); + //(mbedTemp); // compiler warning + // Make sure the values are consistent + VERIFY(mbedTemp->MBEDTLS_PRIVATE(n) * sizeof(mbedtls_mpi_uint) == (int)tpmTemp->size * sizeof(crypt_uword_t)); + for(i = 0; i < tpmTemp->size; i++) + VERIFY(((crypt_uword_t*)mbedTemp->MBEDTLS_PRIVATE(p))[i] == tpmTemp->d[i]); + + MPI_FREE(mbedTemp); + return TRUE; +Error: + MPI_FREE(mbedTemp); + return FALSE; +} +#endif + +//*** BnModMult() +// Does multiply and divide returning the remainder of the divide. +LIB_EXPORT BOOL +BnModMult( + bigNum result, + bigConst op1, + bigConst op2, + bigConst modulus + ) +{ + BOOL OK; + MPI_INITIALIZED(bnOp1, op1); + MPI_INITIALIZED(bnOp2, op2); + MPI_INITIALIZED(bnTemp, NULL); + BN_VAR(temp, LARGEST_NUMBER_BITS * 2); + + pAssert(BnGetAllocated(result) >= BnGetSize(modulus)); + + OK = (mbedtls_mpi_mul_mpi(bnTemp, bnOp1, bnOp2) == 0); + if(OK) + { + BnFromMbedtls(temp, bnTemp); + OK = BnDiv(NULL, result, temp, modulus); + } + + MPI_FREE(bnOp1); + MPI_FREE(bnOp2); + MPI_FREE(bnTemp); + + return OK; +} + +//*** BnMult() +// Multiplies two numbers. +LIB_EXPORT BOOL +BnMult( + bigNum result, + bigConst multiplicand, + bigConst multiplier + ) +{ + BOOL OK; + MPI_INITIALIZED(bnTemp, NULL); + MPI_INITIALIZED(bnA, multiplicand); + MPI_INITIALIZED(bnB, multiplier); + + pAssert(result->allocated >= + (BITS_TO_CRYPT_WORDS(BnSizeInBits(multiplicand) + + BnSizeInBits(multiplier)))); + + OK = (mbedtls_mpi_mul_mpi(bnTemp, bnA, bnB) == 0); + if(OK) + { + BnFromMbedtls(result, bnTemp); + } + + MPI_FREE(bnTemp); + MPI_FREE(bnA); + MPI_FREE(bnB); + + return OK; +} + +//*** BnDiv() +// This function divides two bigNum values. The function returns FALSE if +// there is an error in the operation. +LIB_EXPORT BOOL +BnDiv( + bigNum quotient, + bigNum remainder, + bigConst dividend, + bigConst divisor + ) +{ + BOOL OK; + MPI_INITIALIZED(bnQ, quotient); + MPI_INITIALIZED(bnR, remainder); + MPI_INITIALIZED(bnDend, dividend); + MPI_INITIALIZED(bnSor, divisor); + + pAssert(!BnEqualZero(divisor)); + + if(BnGetSize(dividend) < BnGetSize(divisor)) + { + if(quotient) + BnSetWord(quotient, 0); + if(remainder) + BnCopy(remainder, dividend); + OK = TRUE; + } + else + { + pAssert((quotient == NULL) + || (quotient->allocated >= (unsigned)(dividend->size + - divisor->size))); + pAssert((remainder == NULL) + || (remainder->allocated >= divisor->size)); + + OK = (mbedtls_mpi_div_mpi(bnQ, bnR, bnDend, bnSor) == 0); + if(OK) + { + BnFromMbedtls(quotient, bnQ); + BnFromMbedtls(remainder, bnR); + } + } + + MPI_FREE(bnQ); + MPI_FREE(bnR); + MPI_FREE(bnDend); + MPI_FREE(bnSor); + + return OK; +} + +#if ALG_RSA +//*** BnGcd() +// Get the greatest common divisor of two numbers. +LIB_EXPORT BOOL +BnGcd( + bigNum gcd, // OUT: the common divisor + bigConst number1, // IN: + bigConst number2 // IN: + ) +{ + BOOL OK; + MPI_INITIALIZED(bnGcd, gcd); + MPI_INITIALIZED(bn1, number1); + MPI_INITIALIZED(bn2, number2); + + pAssert(gcd != NULL); + + OK = (mbedtls_mpi_gcd(bnGcd, bn1, bn2) == 0); + if(OK) + { + BnFromMbedtls(gcd, bnGcd); + } + + MPI_FREE(bnGcd); + MPI_FREE(bn1); + MPI_FREE(bn2); + + return OK; +} + +//***BnModExp() +// Do modular exponentiation using bigNum values. +LIB_EXPORT BOOL +BnModExp( + bigNum result, // OUT: the result + bigConst number, // IN: number to exponentiate + bigConst exponent, // IN: + bigConst modulus // IN: + ) +{ + BOOL OK; + MPI_INITIALIZED(bnResult, result); + MPI_INITIALIZED(bnN, number); + MPI_INITIALIZED(bnE, exponent); + MPI_INITIALIZED(bnM, modulus); + + OK = (mbedtls_mpi_exp_mod(bnResult, bnN, bnE, bnM, NULL) == 0); + if(OK) + { + BnFromMbedtls(result, bnResult); + } + + MPI_FREE(bnResult); + MPI_FREE(bnN); + MPI_FREE(bnE); + MPI_FREE(bnM); + + return OK; +} + +//*** BnModInverse() +// Modular multiplicative inverse +LIB_EXPORT BOOL +BnModInverse( + bigNum result, + bigConst number, + bigConst modulus + ) +{ + BOOL OK; + MPI_INITIALIZED(bnResult, result); + MPI_INITIALIZED(bnN, number); + MPI_INITIALIZED(bnM, modulus); + + OK = (mbedtls_mpi_inv_mod(bnResult, bnN, bnM) == 0); + if(OK) + { + BnFromMbedtls(result, bnResult); + } + + MPI_FREE(bnResult); + MPI_FREE(bnN); + MPI_FREE(bnM); + + return OK; +} +#endif // TPM_ALG_RSA + +#if ALG_ECC +//*** PointFromMbedtls() +// Function to copy the point result from a mbedtls_mpi to a bigNum +void +PointFromMbedtls( + bigPoint pOut, // OUT: resulting point + ecc_point *pIn // IN: the point to return + ) +{ + BnFromMbedtls(pOut->x, pIn->x); + BnFromMbedtls(pOut->y, pIn->y); + BnFromMbedtls(pOut->z, pIn->z); +} + +//*** PointToMbedtls() +// Function to copy the point result from a bigNum to a mbedtls_mpi +void +PointToMbedtls( + ecc_point *pOut, // OUT: resulting point + pointConst pIn // IN: the point to return + ) +{ + BnToMbedtls(pOut->x, pIn->x); + BnToMbedtls(pOut->y, pIn->y); + BnToMbedtls(pOut->z, pIn->z); +} + +//*** EcPointInitialized() +// Allocate and initialize a point. +static ecc_point * +EcPointInitialized( + pointConst initializer + ) +{ + ecc_point *P; + + P = ltc_ecc_new_point(); + pAssert(P != NULL); + + if (P != NULL && initializer != NULL) + { + PointToMbedtls(P, initializer); + } + + return P; +} + +//*** EcPointFree() +// Free a point. +static void +EcPointFree( + ecc_point *pEcc + ) +{ + ltc_ecc_del_point(pEcc); +} + +//*** BnEccModMult() +// This function does a point multiply of the form R = [d]S +// return type: BOOL +// FALSE failure in operation; treat as result being point at infinity +LIB_EXPORT BOOL +BnEccModMult( + bigPoint R, // OUT: computed point + pointConst S, // IN: point to multiply by 'd' + bigConst d, // IN: scalar for [d]S + bigCurve E + ) +{ + BOOL OK; + MPI_INITIALIZED(bnD, d); + MPI_INITIALIZED(bnPrime, CurveGetPrime(E)); + MPI_INITIALIZED(bnA, CurveGet_a(E)); + POINT_CREATE(pS, NULL); + POINT_CREATE(pR, NULL); + + if(S == NULL) + S = CurveGetG(AccessCurveData(E)); + + PointToMbedtls(pS, S); + + OK = (ltc_ecc_mulmod(bnD, pS, pR, bnA, bnPrime, 1) == CRYPT_OK); + if(OK) + { + PointFromMbedtls(R, pR); + } + + POINT_DELETE(pR); + POINT_DELETE(pS); + MPI_FREE(bnD); + MPI_FREE(bnPrime); + MPI_FREE(bnA); + + return !BnEqualZero(R->z); +} + +//*** BnEccModMult2() +// This function does a point multiply of the form R = [d]S + [u]Q +// return type: BOOL +// FALSE failure in operation; treat as result being point at infinity +LIB_EXPORT BOOL +BnEccModMult2( + bigPoint R, // OUT: computed point + pointConst S, // IN: first point (optional) + bigConst d, // IN: scalar for [d]S or [d]G + pointConst Q, // IN: second point + bigConst u, // IN: second scalar + bigCurve E // IN: curve + ) +{ + BOOL OK; + POINT_CREATE(pR, NULL); + POINT_CREATE(pS, NULL); + POINT_CREATE(pQ, Q); + MPI_INITIALIZED(bnD, d); + MPI_INITIALIZED(bnU, u); + MPI_INITIALIZED(bnPrime, CurveGetPrime(E)); + + if(S == NULL) + S = CurveGetG(AccessCurveData(E)); + + PointToMbedtls(pS, S); + + OK = (ltc_ecc_mul2add(pS, bnD, pQ, bnU, pR, NULL, bnPrime) == CRYPT_OK); + if(OK) + { + PointFromMbedtls(R, pR); + } + + POINT_DELETE(pR); + POINT_DELETE(pS); + POINT_DELETE(pQ); + MPI_FREE(bnD); + MPI_FREE(bnU); + MPI_FREE(bnPrime); + + return !BnEqualZero(R->z); +} + +//** BnEccAdd() +// This function does addition of two points. +// return type: BOOL +// FALSE failure in operation; treat as result being point at infinity +LIB_EXPORT BOOL +BnEccAdd( + bigPoint R, // OUT: computed point + pointConst S, // IN: point to multiply by 'd' + pointConst Q, // IN: second point + bigCurve E // IN: curve + ) +{ + BOOL OK; + void *mp; + POINT_CREATE(pR, NULL); + POINT_CREATE(pS, S); + POINT_CREATE(pQ, Q); + MPI_INITIALIZED(bnA, CurveGet_a(E)); + MPI_INITIALIZED(bnMod, CurveGetPrime(E)); + + OK = (mp_montgomery_setup(bnMod, &mp) == CRYPT_OK); + OK = OK && (ltc_ecc_projective_add_point(pS, pQ, pR, bnA, bnMod, mp) == CRYPT_OK); + if(OK) + { + PointFromMbedtls(R, pR); + } + + POINT_DELETE(pR); + POINT_DELETE(pS); + POINT_DELETE(pQ); + MPI_FREE(bnA); + MPI_FREE(bnMod); + mp_montgomery_free(mp); + + return !BnEqualZero(R->z); +} + +#endif // TPM_ALG_ECC + +#endif // MATH_LIB_MBEDTLS diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/Mbedtls/TpmToMbedtlsSupport.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/Mbedtls/TpmToMbedtlsSupport.c new file mode 100644 index 0000000..4a7fcf0 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/Mbedtls/TpmToMbedtlsSupport.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023-2024, NVIDIA Corporation & AFFILIATES. All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +//** Introduction +// +// The functions in this file are used for initialization of the interface to the +// MbedTLS library. + +//** Defines and Includes + +#include "Tpm.h" + +#if defined(HASH_LIB_MBEDTLS) || defined(MATH_LIB_MBEDTLS) || defined(SYM_LIB_MBEDTLS) + +//*** SupportLibInit() +// This does any initialization required by the support library. +LIB_EXPORT int +SupportLibInit( + void + ) +{ + return TRUE; +} + +#endif // HASH_LIB_MBEDTLS || MATH_LIB_MBEDTLS || SYM_LIB_MBEDTLS diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/PrimeData.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/PrimeData.c new file mode 100644 index 0000000..b24af02 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/PrimeData.c @@ -0,0 +1,391 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" + +// This table is the product of all of the primes up to 1000. +// Checking to see if there is a GCD between a prime candidate +// and this number will eliminate many prime candidates from +// consideration before running Miller-Rabin on the result. + +const BN_STRUCT(43 * RADIX_BITS) s_CompositeOfSmallPrimes_ = + {44, 44, {0x2ED42696, 0x2BBFA177, 0x4820594F, 0xF73F4841, 0xBFAC313A, 0xCAC3EB81, + 0xF6F26BF8, 0x7FAB5061, 0x59746FB7, 0xF71377F6, 0x3B19855B, 0xCBD03132, + 0xBB92EF1B, 0x3AC3152C, 0xE87C8273, 0xC0AE0E69, 0x74A9E295, 0x448CCE86, + 0x63CA1907, 0x8A0BF944, 0xF8CC3BE0, 0xC26F0AF5, 0xC501C02F, 0x6579441A, + 0xD1099CDA, 0x6BC76A00, 0xC81A3228, 0xBFB1AB25, 0x70FA3841, 0x51B3D076, + 0xCC2359ED, 0xD9EE0769, 0x75E47AF0, 0xD45FF31E, 0x52CCE4F6, 0x04DBC891, + 0x96658ED2, 0x1753EFE5, 0x3AE4A5A6, 0x8FD4A97F, 0x8B15E7EB, 0x0243C3E1, + 0xE0F0C31D, 0x0000000B}}; + +bigConst s_CompositeOfSmallPrimes = (const bigNum)&s_CompositeOfSmallPrimes_; + +// This table contains a bit for each of the odd values between 1 and 2^16 + 1. +// This table allows fast checking of the primes in that range. +// Don't change the size of this table unless you are prepared to do redo +// IsPrimeInt(). + +const uint32_t s_LastPrimeInTable = 65537; +const uint32_t s_PrimeTableSize = 4097; +const uint32_t s_PrimesInTable = 6542; +const unsigned char s_PrimeTable[] = + {0x6e, 0xcb, 0xb4, 0x64, 0x9a, 0x12, 0x6d, 0x81, 0x32, 0x4c, 0x4a, 0x86, 0x0d, + 0x82, 0x96, 0x21, 0xc9, 0x34, 0x04, 0x5a, 0x20, 0x61, 0x89, 0xa4, 0x44, 0x11, + 0x86, 0x29, 0xd1, 0x82, 0x28, 0x4a, 0x30, 0x40, 0x42, 0x32, 0x21, 0x99, 0x34, + 0x08, 0x4b, 0x06, 0x25, 0x42, 0x84, 0x48, 0x8a, 0x14, 0x05, 0x42, 0x30, 0x6c, + 0x08, 0xb4, 0x40, 0x0b, 0xa0, 0x08, 0x51, 0x12, 0x28, 0x89, 0x04, 0x65, 0x98, + 0x30, 0x4c, 0x80, 0x96, 0x44, 0x12, 0x80, 0x21, 0x42, 0x12, 0x41, 0xc9, 0x04, + 0x21, 0xc0, 0x32, 0x2d, 0x98, 0x00, 0x00, 0x49, 0x04, 0x08, 0x81, 0x96, 0x68, + 0x82, 0xb0, 0x25, 0x08, 0x22, 0x48, 0x89, 0xa2, 0x40, 0x59, 0x26, 0x04, 0x90, + 0x06, 0x40, 0x43, 0x30, 0x44, 0x92, 0x00, 0x69, 0x10, 0x82, 0x08, 0x08, 0xa4, + 0x0d, 0x41, 0x12, 0x60, 0xc0, 0x00, 0x24, 0xd2, 0x22, 0x61, 0x08, 0x84, 0x04, + 0x1b, 0x82, 0x01, 0xd3, 0x10, 0x01, 0x02, 0xa0, 0x44, 0xc0, 0x22, 0x60, 0x91, + 0x14, 0x0c, 0x40, 0xa6, 0x04, 0xd2, 0x94, 0x20, 0x09, 0x94, 0x20, 0x52, 0x00, + 0x08, 0x10, 0xa2, 0x4c, 0x00, 0x82, 0x01, 0x51, 0x10, 0x08, 0x8b, 0xa4, 0x25, + 0x9a, 0x30, 0x44, 0x81, 0x10, 0x4c, 0x03, 0x02, 0x25, 0x52, 0x80, 0x08, 0x49, + 0x84, 0x20, 0x50, 0x32, 0x00, 0x18, 0xa2, 0x40, 0x11, 0x24, 0x28, 0x01, 0x84, + 0x01, 0x01, 0xa0, 0x41, 0x0a, 0x12, 0x45, 0x00, 0x36, 0x08, 0x00, 0x26, 0x29, + 0x83, 0x82, 0x61, 0xc0, 0x80, 0x04, 0x10, 0x10, 0x6d, 0x00, 0x22, 0x48, 0x58, + 0x26, 0x0c, 0xc2, 0x10, 0x48, 0x89, 0x24, 0x20, 0x58, 0x20, 0x45, 0x88, 0x24, + 0x00, 0x19, 0x02, 0x25, 0xc0, 0x10, 0x68, 0x08, 0x14, 0x01, 0xca, 0x32, 0x28, + 0x80, 0x00, 0x04, 0x4b, 0x26, 0x00, 0x13, 0x90, 0x60, 0x82, 0x80, 0x25, 0xd0, + 0x00, 0x01, 0x10, 0x32, 0x0c, 0x43, 0x86, 0x21, 0x11, 0x00, 0x08, 0x43, 0x24, + 0x04, 0x48, 0x10, 0x0c, 0x90, 0x92, 0x00, 0x43, 0x20, 0x2d, 0x00, 0x06, 0x09, + 0x88, 0x24, 0x40, 0xc0, 0x32, 0x09, 0x09, 0x82, 0x00, 0x53, 0x80, 0x08, 0x80, + 0x96, 0x41, 0x81, 0x00, 0x40, 0x48, 0x10, 0x48, 0x08, 0x96, 0x48, 0x58, 0x20, + 0x29, 0xc3, 0x80, 0x20, 0x02, 0x94, 0x60, 0x92, 0x00, 0x20, 0x81, 0x22, 0x44, + 0x10, 0xa0, 0x05, 0x40, 0x90, 0x01, 0x49, 0x20, 0x04, 0x0a, 0x00, 0x24, 0x89, + 0x34, 0x48, 0x13, 0x80, 0x2c, 0xc0, 0x82, 0x29, 0x00, 0x24, 0x45, 0x08, 0x00, + 0x08, 0x98, 0x36, 0x04, 0x52, 0x84, 0x04, 0xd0, 0x04, 0x00, 0x8a, 0x90, 0x44, + 0x82, 0x32, 0x65, 0x18, 0x90, 0x00, 0x0a, 0x02, 0x01, 0x40, 0x02, 0x28, 0x40, + 0xa4, 0x04, 0x92, 0x30, 0x04, 0x11, 0x86, 0x08, 0x42, 0x00, 0x2c, 0x52, 0x04, + 0x08, 0xc9, 0x84, 0x60, 0x48, 0x12, 0x09, 0x99, 0x24, 0x44, 0x00, 0x24, 0x00, + 0x03, 0x14, 0x21, 0x00, 0x10, 0x01, 0x1a, 0x32, 0x05, 0x88, 0x20, 0x40, 0x40, + 0x06, 0x09, 0xc3, 0x84, 0x40, 0x01, 0x30, 0x60, 0x18, 0x02, 0x68, 0x11, 0x90, + 0x0c, 0x02, 0xa2, 0x04, 0x00, 0x86, 0x29, 0x89, 0x14, 0x24, 0x82, 0x02, 0x41, + 0x08, 0x80, 0x04, 0x19, 0x80, 0x08, 0x10, 0x12, 0x68, 0x42, 0xa4, 0x04, 0x00, + 0x02, 0x61, 0x10, 0x06, 0x0c, 0x10, 0x00, 0x01, 0x12, 0x10, 0x20, 0x03, 0x94, + 0x21, 0x42, 0x12, 0x65, 0x18, 0x94, 0x0c, 0x0a, 0x04, 0x28, 0x01, 0x14, 0x29, + 0x0a, 0xa4, 0x40, 0xd0, 0x00, 0x40, 0x01, 0x90, 0x04, 0x41, 0x20, 0x2d, 0x40, + 0x82, 0x48, 0xc1, 0x20, 0x00, 0x10, 0x30, 0x01, 0x08, 0x24, 0x04, 0x59, 0x84, + 0x24, 0x00, 0x02, 0x29, 0x82, 0x00, 0x61, 0x58, 0x02, 0x48, 0x81, 0x16, 0x48, + 0x10, 0x00, 0x21, 0x11, 0x06, 0x00, 0xca, 0xa0, 0x40, 0x02, 0x00, 0x04, 0x91, + 0xb0, 0x00, 0x42, 0x04, 0x0c, 0x81, 0x06, 0x09, 0x48, 0x14, 0x25, 0x92, 0x20, + 0x25, 0x11, 0xa0, 0x00, 0x0a, 0x86, 0x0c, 0xc1, 0x02, 0x48, 0x00, 0x20, 0x45, + 0x08, 0x32, 0x00, 0x98, 0x06, 0x04, 0x13, 0x22, 0x00, 0x82, 0x04, 0x48, 0x81, + 0x14, 0x44, 0x82, 0x12, 0x24, 0x18, 0x10, 0x40, 0x43, 0x80, 0x28, 0xd0, 0x04, + 0x20, 0x81, 0x24, 0x64, 0xd8, 0x00, 0x2c, 0x09, 0x12, 0x08, 0x41, 0xa2, 0x00, + 0x00, 0x02, 0x41, 0xca, 0x20, 0x41, 0xc0, 0x10, 0x01, 0x18, 0xa4, 0x04, 0x18, + 0xa4, 0x20, 0x12, 0x94, 0x20, 0x83, 0xa0, 0x40, 0x02, 0x32, 0x44, 0x80, 0x04, + 0x00, 0x18, 0x00, 0x0c, 0x40, 0x86, 0x60, 0x8a, 0x00, 0x64, 0x88, 0x12, 0x05, + 0x01, 0x82, 0x00, 0x4a, 0xa2, 0x01, 0xc1, 0x10, 0x61, 0x09, 0x04, 0x01, 0x88, + 0x00, 0x60, 0x01, 0xb4, 0x40, 0x08, 0x06, 0x01, 0x03, 0x80, 0x08, 0x40, 0x94, + 0x04, 0x8a, 0x20, 0x29, 0x80, 0x02, 0x0c, 0x52, 0x02, 0x01, 0x42, 0x84, 0x00, + 0x80, 0x84, 0x64, 0x02, 0x32, 0x48, 0x00, 0x30, 0x44, 0x40, 0x22, 0x21, 0x00, + 0x02, 0x08, 0xc3, 0xa0, 0x04, 0xd0, 0x20, 0x40, 0x18, 0x16, 0x40, 0x40, 0x00, + 0x28, 0x52, 0x90, 0x08, 0x82, 0x14, 0x01, 0x18, 0x10, 0x08, 0x09, 0x82, 0x40, + 0x0a, 0xa0, 0x20, 0x93, 0x80, 0x08, 0xc0, 0x00, 0x20, 0x52, 0x00, 0x05, 0x01, + 0x10, 0x40, 0x11, 0x06, 0x0c, 0x82, 0x00, 0x00, 0x4b, 0x90, 0x44, 0x9a, 0x00, + 0x28, 0x80, 0x90, 0x04, 0x4a, 0x06, 0x09, 0x43, 0x02, 0x28, 0x00, 0x34, 0x01, + 0x18, 0x00, 0x65, 0x09, 0x80, 0x44, 0x03, 0x00, 0x24, 0x02, 0x82, 0x61, 0x48, + 0x14, 0x41, 0x00, 0x12, 0x28, 0x00, 0x34, 0x08, 0x51, 0x04, 0x05, 0x12, 0x90, + 0x28, 0x89, 0x84, 0x60, 0x12, 0x10, 0x49, 0x10, 0x26, 0x40, 0x49, 0x82, 0x00, + 0x91, 0x10, 0x01, 0x0a, 0x24, 0x40, 0x88, 0x10, 0x4c, 0x10, 0x04, 0x00, 0x50, + 0xa2, 0x2c, 0x40, 0x90, 0x48, 0x0a, 0xb0, 0x01, 0x50, 0x12, 0x08, 0x00, 0xa4, + 0x04, 0x09, 0xa0, 0x28, 0x92, 0x02, 0x00, 0x43, 0x10, 0x21, 0x02, 0x20, 0x41, + 0x81, 0x32, 0x00, 0x08, 0x04, 0x0c, 0x52, 0x00, 0x21, 0x49, 0x84, 0x20, 0x10, + 0x02, 0x01, 0x81, 0x10, 0x48, 0x40, 0x22, 0x01, 0x01, 0x84, 0x69, 0xc1, 0x30, + 0x01, 0xc8, 0x02, 0x44, 0x88, 0x00, 0x0c, 0x01, 0x02, 0x2d, 0xc0, 0x12, 0x61, + 0x00, 0xa0, 0x00, 0xc0, 0x30, 0x40, 0x01, 0x12, 0x08, 0x0b, 0x20, 0x00, 0x80, + 0x94, 0x40, 0x01, 0x84, 0x40, 0x00, 0x32, 0x00, 0x10, 0x84, 0x00, 0x0b, 0x24, + 0x00, 0x01, 0x06, 0x29, 0x8a, 0x84, 0x41, 0x80, 0x10, 0x08, 0x08, 0x94, 0x4c, + 0x03, 0x80, 0x01, 0x40, 0x96, 0x40, 0x41, 0x20, 0x20, 0x50, 0x22, 0x25, 0x89, + 0xa2, 0x40, 0x40, 0xa4, 0x20, 0x02, 0x86, 0x28, 0x01, 0x20, 0x21, 0x4a, 0x10, + 0x08, 0x00, 0x14, 0x08, 0x40, 0x04, 0x25, 0x42, 0x02, 0x21, 0x43, 0x10, 0x04, + 0x92, 0x00, 0x21, 0x11, 0xa0, 0x4c, 0x18, 0x22, 0x09, 0x03, 0x84, 0x41, 0x89, + 0x10, 0x04, 0x82, 0x22, 0x24, 0x01, 0x14, 0x08, 0x08, 0x84, 0x08, 0xc1, 0x00, + 0x09, 0x42, 0xb0, 0x41, 0x8a, 0x02, 0x00, 0x80, 0x36, 0x04, 0x49, 0xa0, 0x24, + 0x91, 0x00, 0x00, 0x02, 0x94, 0x41, 0x92, 0x02, 0x01, 0x08, 0x06, 0x08, 0x09, + 0x00, 0x01, 0xd0, 0x16, 0x28, 0x89, 0x80, 0x60, 0x00, 0x00, 0x68, 0x01, 0x90, + 0x0c, 0x50, 0x20, 0x01, 0x40, 0x80, 0x40, 0x42, 0x30, 0x41, 0x00, 0x20, 0x25, + 0x81, 0x06, 0x40, 0x49, 0x00, 0x08, 0x01, 0x12, 0x49, 0x00, 0xa0, 0x20, 0x18, + 0x30, 0x05, 0x01, 0xa6, 0x00, 0x10, 0x24, 0x28, 0x00, 0x02, 0x20, 0xc8, 0x20, + 0x00, 0x88, 0x12, 0x0c, 0x90, 0x92, 0x00, 0x02, 0x26, 0x01, 0x42, 0x16, 0x49, + 0x00, 0x04, 0x24, 0x42, 0x02, 0x01, 0x88, 0x80, 0x0c, 0x1a, 0x80, 0x08, 0x10, + 0x00, 0x60, 0x02, 0x94, 0x44, 0x88, 0x00, 0x69, 0x11, 0x30, 0x08, 0x12, 0xa0, + 0x24, 0x13, 0x84, 0x00, 0x82, 0x00, 0x65, 0xc0, 0x10, 0x28, 0x00, 0x30, 0x04, + 0x03, 0x20, 0x01, 0x11, 0x06, 0x01, 0xc8, 0x80, 0x00, 0xc2, 0x20, 0x08, 0x10, + 0x82, 0x0c, 0x13, 0x02, 0x0c, 0x52, 0x06, 0x40, 0x00, 0xb0, 0x61, 0x40, 0x10, + 0x01, 0x98, 0x86, 0x04, 0x10, 0x84, 0x08, 0x92, 0x14, 0x60, 0x41, 0x80, 0x41, + 0x1a, 0x10, 0x04, 0x81, 0x22, 0x40, 0x41, 0x20, 0x29, 0x52, 0x00, 0x41, 0x08, + 0x34, 0x60, 0x10, 0x00, 0x28, 0x01, 0x10, 0x40, 0x00, 0x84, 0x08, 0x42, 0x90, + 0x20, 0x48, 0x04, 0x04, 0x52, 0x02, 0x00, 0x08, 0x20, 0x04, 0x00, 0x82, 0x0d, + 0x00, 0x82, 0x40, 0x02, 0x10, 0x05, 0x48, 0x20, 0x40, 0x99, 0x00, 0x00, 0x01, + 0x06, 0x24, 0xc0, 0x00, 0x68, 0x82, 0x04, 0x21, 0x12, 0x10, 0x44, 0x08, 0x04, + 0x00, 0x40, 0xa6, 0x20, 0xd0, 0x16, 0x09, 0xc9, 0x24, 0x41, 0x02, 0x20, 0x0c, + 0x09, 0x92, 0x40, 0x12, 0x00, 0x00, 0x40, 0x00, 0x09, 0x43, 0x84, 0x20, 0x98, + 0x02, 0x01, 0x11, 0x24, 0x00, 0x43, 0x24, 0x00, 0x03, 0x90, 0x08, 0x41, 0x30, + 0x24, 0x58, 0x20, 0x4c, 0x80, 0x82, 0x08, 0x10, 0x24, 0x25, 0x81, 0x06, 0x41, + 0x09, 0x10, 0x20, 0x18, 0x10, 0x44, 0x80, 0x10, 0x00, 0x4a, 0x24, 0x0d, 0x01, + 0x94, 0x28, 0x80, 0x30, 0x00, 0xc0, 0x02, 0x60, 0x10, 0x84, 0x0c, 0x02, 0x00, + 0x09, 0x02, 0x82, 0x01, 0x08, 0x10, 0x04, 0xc2, 0x20, 0x68, 0x09, 0x06, 0x04, + 0x18, 0x00, 0x00, 0x11, 0x90, 0x08, 0x0b, 0x10, 0x21, 0x82, 0x02, 0x0c, 0x10, + 0xb6, 0x08, 0x00, 0x26, 0x00, 0x41, 0x02, 0x01, 0x4a, 0x24, 0x21, 0x1a, 0x20, + 0x24, 0x80, 0x00, 0x44, 0x02, 0x00, 0x2d, 0x40, 0x02, 0x00, 0x8b, 0x94, 0x20, + 0x10, 0x00, 0x20, 0x90, 0xa6, 0x40, 0x13, 0x00, 0x2c, 0x11, 0x86, 0x61, 0x01, + 0x80, 0x41, 0x10, 0x02, 0x04, 0x81, 0x30, 0x48, 0x48, 0x20, 0x28, 0x50, 0x80, + 0x21, 0x8a, 0x10, 0x04, 0x08, 0x10, 0x09, 0x10, 0x10, 0x48, 0x42, 0xa0, 0x0c, + 0x82, 0x92, 0x60, 0xc0, 0x20, 0x05, 0xd2, 0x20, 0x40, 0x01, 0x00, 0x04, 0x08, + 0x82, 0x2d, 0x82, 0x02, 0x00, 0x48, 0x80, 0x41, 0x48, 0x10, 0x00, 0x91, 0x04, + 0x04, 0x03, 0x84, 0x00, 0xc2, 0x04, 0x68, 0x00, 0x00, 0x64, 0xc0, 0x22, 0x40, + 0x08, 0x32, 0x44, 0x09, 0x86, 0x00, 0x91, 0x02, 0x28, 0x01, 0x00, 0x64, 0x48, + 0x00, 0x24, 0x10, 0x90, 0x00, 0x43, 0x00, 0x21, 0x52, 0x86, 0x41, 0x8b, 0x90, + 0x20, 0x40, 0x20, 0x08, 0x88, 0x04, 0x44, 0x13, 0x20, 0x00, 0x02, 0x84, 0x60, + 0x81, 0x90, 0x24, 0x40, 0x30, 0x00, 0x08, 0x10, 0x08, 0x08, 0x02, 0x01, 0x10, + 0x04, 0x20, 0x43, 0xb4, 0x40, 0x90, 0x12, 0x68, 0x01, 0x80, 0x4c, 0x18, 0x00, + 0x08, 0xc0, 0x12, 0x49, 0x40, 0x10, 0x24, 0x1a, 0x00, 0x41, 0x89, 0x24, 0x4c, + 0x10, 0x00, 0x04, 0x52, 0x10, 0x09, 0x4a, 0x20, 0x41, 0x48, 0x22, 0x69, 0x11, + 0x14, 0x08, 0x10, 0x06, 0x24, 0x80, 0x84, 0x28, 0x00, 0x10, 0x00, 0x40, 0x10, + 0x01, 0x08, 0x26, 0x08, 0x48, 0x06, 0x28, 0x00, 0x14, 0x01, 0x42, 0x84, 0x04, + 0x0a, 0x20, 0x00, 0x01, 0x82, 0x08, 0x00, 0x82, 0x24, 0x12, 0x04, 0x40, 0x40, + 0xa0, 0x40, 0x90, 0x10, 0x04, 0x90, 0x22, 0x40, 0x10, 0x20, 0x2c, 0x80, 0x10, + 0x28, 0x43, 0x00, 0x04, 0x58, 0x00, 0x01, 0x81, 0x10, 0x48, 0x09, 0x20, 0x21, + 0x83, 0x04, 0x00, 0x42, 0xa4, 0x44, 0x00, 0x00, 0x6c, 0x10, 0xa0, 0x44, 0x48, + 0x80, 0x00, 0x83, 0x80, 0x48, 0xc9, 0x00, 0x00, 0x00, 0x02, 0x05, 0x10, 0xb0, + 0x04, 0x13, 0x04, 0x29, 0x10, 0x92, 0x40, 0x08, 0x04, 0x44, 0x82, 0x22, 0x00, + 0x19, 0x20, 0x00, 0x19, 0x20, 0x01, 0x81, 0x90, 0x60, 0x8a, 0x00, 0x41, 0xc0, + 0x02, 0x45, 0x10, 0x04, 0x00, 0x02, 0xa2, 0x09, 0x40, 0x10, 0x21, 0x49, 0x20, + 0x01, 0x42, 0x30, 0x2c, 0x00, 0x14, 0x44, 0x01, 0x22, 0x04, 0x02, 0x92, 0x08, + 0x89, 0x04, 0x21, 0x80, 0x10, 0x05, 0x01, 0x20, 0x40, 0x41, 0x80, 0x04, 0x00, + 0x12, 0x09, 0x40, 0xb0, 0x64, 0x58, 0x32, 0x01, 0x08, 0x90, 0x00, 0x41, 0x04, + 0x09, 0xc1, 0x80, 0x61, 0x08, 0x90, 0x00, 0x9a, 0x00, 0x24, 0x01, 0x12, 0x08, + 0x02, 0x26, 0x05, 0x82, 0x06, 0x08, 0x08, 0x00, 0x20, 0x48, 0x20, 0x00, 0x18, + 0x24, 0x48, 0x03, 0x02, 0x00, 0x11, 0x00, 0x09, 0x00, 0x84, 0x01, 0x4a, 0x10, + 0x01, 0x98, 0x00, 0x04, 0x18, 0x86, 0x00, 0xc0, 0x00, 0x20, 0x81, 0x80, 0x04, + 0x10, 0x30, 0x05, 0x00, 0xb4, 0x0c, 0x4a, 0x82, 0x29, 0x91, 0x02, 0x28, 0x00, + 0x20, 0x44, 0xc0, 0x00, 0x2c, 0x91, 0x80, 0x40, 0x01, 0xa2, 0x00, 0x12, 0x04, + 0x09, 0xc3, 0x20, 0x00, 0x08, 0x02, 0x0c, 0x10, 0x22, 0x04, 0x00, 0x00, 0x2c, + 0x11, 0x86, 0x00, 0xc0, 0x00, 0x00, 0x12, 0x32, 0x40, 0x89, 0x80, 0x40, 0x40, + 0x02, 0x05, 0x50, 0x86, 0x60, 0x82, 0xa4, 0x60, 0x0a, 0x12, 0x4d, 0x80, 0x90, + 0x08, 0x12, 0x80, 0x09, 0x02, 0x14, 0x48, 0x01, 0x24, 0x20, 0x8a, 0x00, 0x44, + 0x90, 0x04, 0x04, 0x01, 0x02, 0x00, 0xd1, 0x12, 0x00, 0x0a, 0x04, 0x40, 0x00, + 0x32, 0x21, 0x81, 0x24, 0x08, 0x19, 0x84, 0x20, 0x02, 0x04, 0x08, 0x89, 0x80, + 0x24, 0x02, 0x02, 0x68, 0x18, 0x82, 0x44, 0x42, 0x00, 0x21, 0x40, 0x00, 0x28, + 0x01, 0x80, 0x45, 0x82, 0x20, 0x40, 0x11, 0x80, 0x0c, 0x02, 0x00, 0x24, 0x40, + 0x90, 0x01, 0x40, 0x20, 0x20, 0x50, 0x20, 0x28, 0x19, 0x00, 0x40, 0x09, 0x20, + 0x08, 0x80, 0x04, 0x60, 0x40, 0x80, 0x20, 0x08, 0x30, 0x49, 0x09, 0x34, 0x00, + 0x11, 0x24, 0x24, 0x82, 0x00, 0x41, 0xc2, 0x00, 0x04, 0x92, 0x02, 0x24, 0x80, + 0x00, 0x0c, 0x02, 0xa0, 0x00, 0x01, 0x06, 0x60, 0x41, 0x04, 0x21, 0xd0, 0x00, + 0x01, 0x01, 0x00, 0x48, 0x12, 0x84, 0x04, 0x91, 0x12, 0x08, 0x00, 0x24, 0x44, + 0x00, 0x12, 0x41, 0x18, 0x26, 0x0c, 0x41, 0x80, 0x00, 0x52, 0x04, 0x20, 0x09, + 0x00, 0x24, 0x90, 0x20, 0x48, 0x18, 0x02, 0x00, 0x03, 0xa2, 0x09, 0xd0, 0x14, + 0x00, 0x8a, 0x84, 0x25, 0x4a, 0x00, 0x20, 0x98, 0x14, 0x40, 0x00, 0xa2, 0x05, + 0x00, 0x00, 0x00, 0x40, 0x14, 0x01, 0x58, 0x20, 0x2c, 0x80, 0x84, 0x00, 0x09, + 0x20, 0x20, 0x91, 0x02, 0x08, 0x02, 0xb0, 0x41, 0x08, 0x30, 0x00, 0x09, 0x10, + 0x00, 0x18, 0x02, 0x21, 0x02, 0x02, 0x00, 0x00, 0x24, 0x44, 0x08, 0x12, 0x60, + 0x00, 0xb2, 0x44, 0x12, 0x02, 0x0c, 0xc0, 0x80, 0x40, 0xc8, 0x20, 0x04, 0x50, + 0x20, 0x05, 0x00, 0xb0, 0x04, 0x0b, 0x04, 0x29, 0x53, 0x00, 0x61, 0x48, 0x30, + 0x00, 0x82, 0x20, 0x29, 0x00, 0x16, 0x00, 0x53, 0x22, 0x20, 0x43, 0x10, 0x48, + 0x00, 0x80, 0x04, 0xd2, 0x00, 0x40, 0x00, 0xa2, 0x44, 0x03, 0x80, 0x29, 0x00, + 0x04, 0x08, 0xc0, 0x04, 0x64, 0x40, 0x30, 0x28, 0x09, 0x84, 0x44, 0x50, 0x80, + 0x21, 0x02, 0x92, 0x00, 0xc0, 0x10, 0x60, 0x88, 0x22, 0x08, 0x80, 0x00, 0x00, + 0x18, 0x84, 0x04, 0x83, 0x96, 0x00, 0x81, 0x20, 0x05, 0x02, 0x00, 0x45, 0x88, + 0x84, 0x00, 0x51, 0x20, 0x20, 0x51, 0x86, 0x41, 0x4b, 0x94, 0x00, 0x80, 0x00, + 0x08, 0x11, 0x20, 0x4c, 0x58, 0x80, 0x04, 0x03, 0x06, 0x20, 0x89, 0x00, 0x05, + 0x08, 0x22, 0x05, 0x90, 0x00, 0x40, 0x00, 0x82, 0x09, 0x50, 0x00, 0x00, 0x00, + 0xa0, 0x41, 0xc2, 0x20, 0x08, 0x00, 0x16, 0x08, 0x40, 0x26, 0x21, 0xd0, 0x90, + 0x08, 0x81, 0x90, 0x41, 0x00, 0x02, 0x44, 0x08, 0x10, 0x0c, 0x0a, 0x86, 0x09, + 0x90, 0x04, 0x00, 0xc8, 0xa0, 0x04, 0x08, 0x30, 0x20, 0x89, 0x84, 0x00, 0x11, + 0x22, 0x2c, 0x40, 0x00, 0x08, 0x02, 0xb0, 0x01, 0x48, 0x02, 0x01, 0x09, 0x20, + 0x04, 0x03, 0x04, 0x00, 0x80, 0x02, 0x60, 0x42, 0x30, 0x21, 0x4a, 0x10, 0x44, + 0x09, 0x02, 0x00, 0x01, 0x24, 0x00, 0x12, 0x82, 0x21, 0x80, 0xa4, 0x20, 0x10, + 0x02, 0x04, 0x91, 0xa0, 0x40, 0x18, 0x04, 0x00, 0x02, 0x06, 0x69, 0x09, 0x00, + 0x05, 0x58, 0x02, 0x01, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x03, 0x92, 0x20, + 0x00, 0x34, 0x01, 0xc8, 0x20, 0x48, 0x08, 0x30, 0x08, 0x42, 0x80, 0x20, 0x91, + 0x90, 0x68, 0x01, 0x04, 0x40, 0x12, 0x02, 0x61, 0x00, 0x12, 0x08, 0x01, 0xa0, + 0x00, 0x11, 0x04, 0x21, 0x48, 0x04, 0x24, 0x92, 0x00, 0x0c, 0x01, 0x84, 0x04, + 0x00, 0x00, 0x01, 0x12, 0x96, 0x40, 0x01, 0xa0, 0x41, 0x88, 0x22, 0x28, 0x88, + 0x00, 0x44, 0x42, 0x80, 0x24, 0x12, 0x14, 0x01, 0x42, 0x90, 0x60, 0x1a, 0x10, + 0x04, 0x81, 0x10, 0x48, 0x08, 0x06, 0x29, 0x83, 0x02, 0x40, 0x02, 0x24, 0x64, + 0x80, 0x10, 0x05, 0x80, 0x10, 0x40, 0x02, 0x02, 0x08, 0x42, 0x84, 0x01, 0x09, + 0x20, 0x04, 0x50, 0x00, 0x60, 0x11, 0x30, 0x40, 0x13, 0x02, 0x04, 0x81, 0x00, + 0x09, 0x08, 0x20, 0x45, 0x4a, 0x10, 0x61, 0x90, 0x26, 0x0c, 0x08, 0x02, 0x21, + 0x91, 0x00, 0x60, 0x02, 0x04, 0x00, 0x02, 0x00, 0x0c, 0x08, 0x06, 0x08, 0x48, + 0x84, 0x08, 0x11, 0x02, 0x00, 0x80, 0xa4, 0x00, 0x5a, 0x20, 0x00, 0x88, 0x04, + 0x04, 0x02, 0x00, 0x09, 0x00, 0x14, 0x08, 0x49, 0x14, 0x20, 0xc8, 0x00, 0x04, + 0x91, 0xa0, 0x40, 0x59, 0x80, 0x00, 0x12, 0x10, 0x00, 0x80, 0x80, 0x65, 0x00, + 0x00, 0x04, 0x00, 0x80, 0x40, 0x19, 0x00, 0x21, 0x03, 0x84, 0x60, 0xc0, 0x04, + 0x24, 0x1a, 0x12, 0x61, 0x80, 0x80, 0x08, 0x02, 0x04, 0x09, 0x42, 0x12, 0x20, + 0x08, 0x34, 0x04, 0x90, 0x20, 0x01, 0x01, 0xa0, 0x00, 0x0b, 0x00, 0x08, 0x91, + 0x92, 0x40, 0x02, 0x34, 0x40, 0x88, 0x10, 0x61, 0x19, 0x02, 0x00, 0x40, 0x04, + 0x25, 0xc0, 0x80, 0x68, 0x08, 0x04, 0x21, 0x80, 0x22, 0x04, 0x00, 0xa0, 0x0c, + 0x01, 0x84, 0x20, 0x41, 0x00, 0x08, 0x8a, 0x00, 0x20, 0x8a, 0x00, 0x48, 0x88, + 0x04, 0x04, 0x11, 0x82, 0x08, 0x40, 0x86, 0x09, 0x49, 0xa4, 0x40, 0x00, 0x10, + 0x01, 0x01, 0xa2, 0x04, 0x50, 0x80, 0x0c, 0x80, 0x00, 0x48, 0x82, 0xa0, 0x01, + 0x18, 0x12, 0x41, 0x01, 0x04, 0x48, 0x41, 0x00, 0x24, 0x01, 0x00, 0x00, 0x88, + 0x14, 0x00, 0x02, 0x00, 0x68, 0x01, 0x20, 0x08, 0x4a, 0x22, 0x08, 0x83, 0x80, + 0x00, 0x89, 0x04, 0x01, 0xc2, 0x00, 0x00, 0x00, 0x34, 0x04, 0x00, 0x82, 0x28, + 0x02, 0x02, 0x41, 0x4a, 0x90, 0x05, 0x82, 0x02, 0x09, 0x80, 0x24, 0x04, 0x41, + 0x00, 0x01, 0x92, 0x80, 0x28, 0x01, 0x14, 0x00, 0x50, 0x20, 0x4c, 0x10, 0xb0, + 0x04, 0x43, 0xa4, 0x21, 0x90, 0x04, 0x01, 0x02, 0x00, 0x44, 0x48, 0x00, 0x64, + 0x08, 0x06, 0x00, 0x42, 0x20, 0x08, 0x02, 0x92, 0x01, 0x4a, 0x00, 0x20, 0x50, + 0x32, 0x25, 0x90, 0x22, 0x04, 0x09, 0x00, 0x08, 0x11, 0x80, 0x21, 0x01, 0x10, + 0x05, 0x00, 0x32, 0x08, 0x88, 0x94, 0x08, 0x08, 0x24, 0x0d, 0xc1, 0x80, 0x40, + 0x0b, 0x20, 0x40, 0x18, 0x12, 0x04, 0x00, 0x22, 0x40, 0x10, 0x26, 0x05, 0xc1, + 0x82, 0x00, 0x01, 0x30, 0x24, 0x02, 0x22, 0x41, 0x08, 0x24, 0x48, 0x1a, 0x00, + 0x25, 0xd2, 0x12, 0x28, 0x42, 0x00, 0x04, 0x40, 0x30, 0x41, 0x00, 0x02, 0x00, + 0x13, 0x20, 0x24, 0xd1, 0x84, 0x08, 0x89, 0x80, 0x04, 0x52, 0x00, 0x44, 0x18, + 0xa4, 0x00, 0x00, 0x06, 0x20, 0x91, 0x10, 0x09, 0x42, 0x20, 0x24, 0x40, 0x30, + 0x28, 0x00, 0x84, 0x40, 0x40, 0x80, 0x08, 0x10, 0x04, 0x09, 0x08, 0x04, 0x40, + 0x08, 0x22, 0x00, 0x19, 0x02, 0x00, 0x00, 0x80, 0x2c, 0x02, 0x02, 0x21, 0x01, + 0x90, 0x20, 0x40, 0x00, 0x0c, 0x00, 0x34, 0x48, 0x58, 0x20, 0x01, 0x43, 0x04, + 0x20, 0x80, 0x14, 0x00, 0x90, 0x00, 0x6d, 0x11, 0x00, 0x00, 0x40, 0x20, 0x00, + 0x03, 0x10, 0x40, 0x88, 0x30, 0x05, 0x4a, 0x00, 0x65, 0x10, 0x24, 0x08, 0x18, + 0x84, 0x28, 0x03, 0x80, 0x20, 0x42, 0xb0, 0x40, 0x00, 0x10, 0x69, 0x19, 0x04, + 0x00, 0x00, 0x80, 0x04, 0xc2, 0x04, 0x00, 0x01, 0x00, 0x05, 0x00, 0x22, 0x25, + 0x08, 0x96, 0x04, 0x02, 0x22, 0x00, 0xd0, 0x10, 0x29, 0x01, 0xa0, 0x60, 0x08, + 0x10, 0x04, 0x01, 0x16, 0x44, 0x10, 0x02, 0x28, 0x02, 0x82, 0x48, 0x40, 0x84, + 0x20, 0x90, 0x22, 0x28, 0x80, 0x04, 0x00, 0x40, 0x04, 0x24, 0x00, 0x80, 0x29, + 0x03, 0x10, 0x60, 0x48, 0x00, 0x00, 0x81, 0xa0, 0x00, 0x51, 0x20, 0x0c, 0xd1, + 0x00, 0x01, 0x41, 0x20, 0x04, 0x92, 0x00, 0x00, 0x10, 0x92, 0x00, 0x42, 0x04, + 0x05, 0x01, 0x86, 0x40, 0x80, 0x10, 0x20, 0x52, 0x20, 0x21, 0x00, 0x10, 0x48, + 0x0a, 0x02, 0x00, 0xd0, 0x12, 0x41, 0x48, 0x80, 0x04, 0x00, 0x00, 0x48, 0x09, + 0x22, 0x04, 0x00, 0x24, 0x00, 0x43, 0x10, 0x60, 0x0a, 0x00, 0x44, 0x12, 0x20, + 0x2c, 0x08, 0x20, 0x44, 0x00, 0x84, 0x09, 0x40, 0x06, 0x08, 0xc1, 0x00, 0x40, + 0x80, 0x20, 0x00, 0x98, 0x12, 0x48, 0x10, 0xa2, 0x20, 0x00, 0x84, 0x48, 0xc0, + 0x10, 0x20, 0x90, 0x12, 0x08, 0x98, 0x82, 0x00, 0x0a, 0xa0, 0x04, 0x03, 0x00, + 0x28, 0xc3, 0x00, 0x44, 0x42, 0x10, 0x04, 0x08, 0x04, 0x40, 0x00, 0x00, 0x05, + 0x10, 0x00, 0x21, 0x03, 0x80, 0x04, 0x88, 0x12, 0x69, 0x10, 0x00, 0x04, 0x08, + 0x04, 0x04, 0x02, 0x84, 0x48, 0x49, 0x04, 0x20, 0x18, 0x02, 0x64, 0x80, 0x30, + 0x08, 0x01, 0x02, 0x00, 0x52, 0x12, 0x49, 0x08, 0x20, 0x41, 0x88, 0x10, 0x48, + 0x08, 0x34, 0x00, 0x01, 0x86, 0x05, 0xd0, 0x00, 0x00, 0x83, 0x84, 0x21, 0x40, + 0x02, 0x41, 0x10, 0x80, 0x48, 0x40, 0xa2, 0x20, 0x51, 0x00, 0x00, 0x49, 0x00, + 0x01, 0x90, 0x20, 0x40, 0x18, 0x02, 0x40, 0x02, 0x22, 0x05, 0x40, 0x80, 0x08, + 0x82, 0x10, 0x20, 0x18, 0x00, 0x05, 0x01, 0x82, 0x40, 0x58, 0x00, 0x04, 0x81, + 0x90, 0x29, 0x01, 0xa0, 0x64, 0x00, 0x22, 0x40, 0x01, 0xa2, 0x00, 0x18, 0x04, + 0x0d, 0x00, 0x00, 0x60, 0x80, 0x94, 0x60, 0x82, 0x10, 0x0d, 0x80, 0x30, 0x0c, + 0x12, 0x20, 0x00, 0x00, 0x12, 0x40, 0xc0, 0x20, 0x21, 0x58, 0x02, 0x41, 0x10, + 0x80, 0x44, 0x03, 0x02, 0x04, 0x13, 0x90, 0x29, 0x08, 0x00, 0x44, 0xc0, 0x00, + 0x21, 0x00, 0x26, 0x00, 0x1a, 0x80, 0x01, 0x13, 0x14, 0x20, 0x0a, 0x14, 0x20, + 0x00, 0x32, 0x61, 0x08, 0x00, 0x40, 0x42, 0x20, 0x09, 0x80, 0x06, 0x01, 0x81, + 0x80, 0x60, 0x42, 0x00, 0x68, 0x90, 0x82, 0x08, 0x42, 0x80, 0x04, 0x02, 0x80, + 0x09, 0x0b, 0x04, 0x00, 0x98, 0x00, 0x0c, 0x81, 0x06, 0x44, 0x48, 0x84, 0x28, + 0x03, 0x92, 0x00, 0x01, 0x80, 0x40, 0x0a, 0x00, 0x0c, 0x81, 0x02, 0x08, 0x51, + 0x04, 0x28, 0x90, 0x02, 0x20, 0x09, 0x10, 0x60, 0x00, 0x00, 0x09, 0x81, 0xa0, + 0x0c, 0x00, 0xa4, 0x09, 0x00, 0x02, 0x28, 0x80, 0x20, 0x00, 0x02, 0x02, 0x04, + 0x81, 0x14, 0x04, 0x00, 0x04, 0x09, 0x11, 0x12, 0x60, 0x40, 0x20, 0x01, 0x48, + 0x30, 0x40, 0x11, 0x00, 0x08, 0x0a, 0x86, 0x00, 0x00, 0x04, 0x60, 0x81, 0x04, + 0x01, 0xd0, 0x02, 0x41, 0x18, 0x90, 0x00, 0x0a, 0x20, 0x00, 0xc1, 0x06, 0x01, + 0x08, 0x80, 0x64, 0xca, 0x10, 0x04, 0x99, 0x80, 0x48, 0x01, 0x82, 0x20, 0x50, + 0x90, 0x48, 0x80, 0x84, 0x20, 0x90, 0x22, 0x00, 0x19, 0x00, 0x04, 0x18, 0x20, + 0x24, 0x10, 0x86, 0x40, 0xc2, 0x00, 0x24, 0x12, 0x10, 0x44, 0x00, 0x16, 0x08, + 0x10, 0x24, 0x00, 0x12, 0x06, 0x01, 0x08, 0x90, 0x00, 0x12, 0x02, 0x4d, 0x10, + 0x80, 0x40, 0x50, 0x22, 0x00, 0x43, 0x10, 0x01, 0x00, 0x30, 0x21, 0x0a, 0x00, + 0x00, 0x01, 0x14, 0x00, 0x10, 0x84, 0x04, 0xc1, 0x10, 0x29, 0x0a, 0x00, 0x01, + 0x8a, 0x00, 0x20, 0x01, 0x12, 0x0c, 0x49, 0x20, 0x04, 0x81, 0x00, 0x48, 0x01, + 0x04, 0x60, 0x80, 0x12, 0x0c, 0x08, 0x10, 0x48, 0x4a, 0x04, 0x28, 0x10, 0x00, + 0x28, 0x40, 0x84, 0x45, 0x50, 0x10, 0x60, 0x10, 0x06, 0x44, 0x01, 0x80, 0x09, + 0x00, 0x86, 0x01, 0x42, 0xa0, 0x00, 0x90, 0x00, 0x05, 0x90, 0x22, 0x40, 0x41, + 0x00, 0x08, 0x80, 0x02, 0x08, 0xc0, 0x00, 0x01, 0x58, 0x30, 0x49, 0x09, 0x14, + 0x00, 0x41, 0x02, 0x0c, 0x02, 0x80, 0x40, 0x89, 0x00, 0x24, 0x08, 0x10, 0x05, + 0x90, 0x32, 0x40, 0x0a, 0x82, 0x08, 0x00, 0x12, 0x61, 0x00, 0x04, 0x21, 0x00, + 0x22, 0x04, 0x10, 0x24, 0x08, 0x0a, 0x04, 0x01, 0x10, 0x00, 0x20, 0x40, 0x84, + 0x04, 0x88, 0x22, 0x20, 0x90, 0x12, 0x00, 0x53, 0x06, 0x24, 0x01, 0x04, 0x40, + 0x0b, 0x14, 0x60, 0x82, 0x02, 0x0d, 0x10, 0x90, 0x0c, 0x08, 0x20, 0x09, 0x00, + 0x14, 0x09, 0x80, 0x80, 0x24, 0x82, 0x00, 0x40, 0x01, 0x02, 0x44, 0x01, 0x20, + 0x0c, 0x40, 0x84, 0x40, 0x0a, 0x10, 0x41, 0x00, 0x30, 0x05, 0x09, 0x80, 0x44, + 0x08, 0x20, 0x20, 0x02, 0x00, 0x49, 0x43, 0x20, 0x21, 0x00, 0x20, 0x00, 0x01, + 0xb6, 0x08, 0x40, 0x04, 0x08, 0x02, 0x80, 0x01, 0x41, 0x80, 0x40, 0x08, 0x10, + 0x24, 0x00, 0x20, 0x04, 0x12, 0x86, 0x09, 0xc0, 0x12, 0x21, 0x81, 0x14, 0x04, + 0x00, 0x02, 0x20, 0x89, 0xb4, 0x44, 0x12, 0x80, 0x00, 0xd1, 0x00, 0x69, 0x40, + 0x80, 0x00, 0x42, 0x12, 0x00, 0x18, 0x04, 0x00, 0x49, 0x06, 0x21, 0x02, 0x04, + 0x28, 0x02, 0x84, 0x01, 0xc0, 0x10, 0x68, 0x00, 0x20, 0x08, 0x40, 0x00, 0x08, + 0x91, 0x10, 0x01, 0x81, 0x24, 0x04, 0xd2, 0x10, 0x4c, 0x88, 0x86, 0x00, 0x10, + 0x80, 0x0c, 0x02, 0x14, 0x00, 0x8a, 0x90, 0x40, 0x18, 0x20, 0x21, 0x80, 0xa4, + 0x00, 0x58, 0x24, 0x20, 0x10, 0x10, 0x60, 0xc1, 0x30, 0x41, 0x48, 0x02, 0x48, + 0x09, 0x00, 0x40, 0x09, 0x02, 0x05, 0x11, 0x82, 0x20, 0x4a, 0x20, 0x24, 0x18, + 0x02, 0x0c, 0x10, 0x22, 0x0c, 0x0a, 0x04, 0x00, 0x03, 0x06, 0x48, 0x48, 0x04, + 0x04, 0x02, 0x00, 0x21, 0x80, 0x84, 0x00, 0x18, 0x00, 0x0c, 0x02, 0x12, 0x01, + 0x00, 0x14, 0x05, 0x82, 0x10, 0x41, 0x89, 0x12, 0x08, 0x40, 0xa4, 0x21, 0x01, + 0x84, 0x48, 0x02, 0x10, 0x60, 0x40, 0x02, 0x28, 0x00, 0x14, 0x08, 0x40, 0xa0, + 0x20, 0x51, 0x12, 0x00, 0xc2, 0x00, 0x01, 0x1a, 0x30, 0x40, 0x89, 0x12, 0x4c, + 0x02, 0x80, 0x00, 0x00, 0x14, 0x01, 0x01, 0xa0, 0x21, 0x18, 0x22, 0x21, 0x18, + 0x06, 0x40, 0x01, 0x80, 0x00, 0x90, 0x04, 0x48, 0x02, 0x30, 0x04, 0x08, 0x00, + 0x05, 0x88, 0x24, 0x08, 0x48, 0x04, 0x24, 0x02, 0x06, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x10, 0x65, 0x11, 0x90, 0x00, 0x0a, 0x82, 0x04, 0xc3, 0x04, 0x60, 0x48, + 0x24, 0x04, 0x92, 0x02, 0x44, 0x88, 0x80, 0x40, 0x18, 0x06, 0x29, 0x80, 0x10, + 0x01, 0x00, 0x00, 0x44, 0xc8, 0x10, 0x21, 0x89, 0x30, 0x00, 0x4b, 0xa0, 0x01, + 0x10, 0x14, 0x00, 0x02, 0x94, 0x40, 0x00, 0x20, 0x65, 0x00, 0xa2, 0x0c, 0x40, + 0x22, 0x20, 0x81, 0x12, 0x20, 0x82, 0x04, 0x01, 0x10, 0x00, 0x08, 0x88, 0x00, + 0x00, 0x11, 0x80, 0x04, 0x42, 0x80, 0x40, 0x41, 0x14, 0x00, 0x40, 0x32, 0x2c, + 0x80, 0x24, 0x04, 0x19, 0x00, 0x00, 0x91, 0x00, 0x20, 0x83, 0x00, 0x05, 0x40, + 0x20, 0x09, 0x01, 0x84, 0x40, 0x40, 0x20, 0x20, 0x11, 0x00, 0x40, 0x41, 0x90, + 0x20, 0x00, 0x00, 0x40, 0x90, 0x92, 0x48, 0x18, 0x06, 0x08, 0x81, 0x80, 0x48, + 0x01, 0x34, 0x24, 0x10, 0x20, 0x04, 0x00, 0x20, 0x04, 0x18, 0x06, 0x2d, 0x90, + 0x10, 0x01, 0x00, 0x90, 0x00, 0x0a, 0x22, 0x01, 0x00, 0x22, 0x00, 0x11, 0x84, + 0x01, 0x01, 0x00, 0x20, 0x88, 0x00, 0x44, 0x00, 0x22, 0x01, 0x00, 0xa6, 0x40, + 0x02, 0x06, 0x20, 0x11, 0x00, 0x01, 0xc8, 0xa0, 0x04, 0x8a, 0x00, 0x28, 0x19, + 0x80, 0x00, 0x52, 0xa0, 0x24, 0x12, 0x12, 0x09, 0x08, 0x24, 0x01, 0x48, 0x00, + 0x04, 0x00, 0x24, 0x40, 0x02, 0x84, 0x08, 0x00, 0x04, 0x48, 0x40, 0x90, 0x60, + 0x0a, 0x22, 0x01, 0x88, 0x14, 0x08, 0x01, 0x02, 0x08, 0xd3, 0x00, 0x20, 0xc0, + 0x90, 0x24, 0x10, 0x00, 0x00, 0x01, 0xb0, 0x08, 0x0a, 0xa0, 0x00, 0x80, 0x00, + 0x01, 0x09, 0x00, 0x20, 0x52, 0x02, 0x25, 0x00, 0x24, 0x04, 0x02, 0x84, 0x24, + 0x10, 0x92, 0x40, 0x02, 0xa0, 0x40, 0x00, 0x22, 0x08, 0x11, 0x04, 0x08, 0x01, + 0x22, 0x00, 0x42, 0x14, 0x00, 0x09, 0x90, 0x21, 0x00, 0x30, 0x6c, 0x00, 0x00, + 0x0c, 0x00, 0x22, 0x09, 0x90, 0x10, 0x28, 0x40, 0x00, 0x20, 0xc0, 0x20, 0x00, + 0x90, 0x00, 0x40, 0x01, 0x82, 0x05, 0x12, 0x12, 0x09, 0xc1, 0x04, 0x61, 0x80, + 0x02, 0x28, 0x81, 0x24, 0x00, 0x49, 0x04, 0x08, 0x10, 0x86, 0x29, 0x41, 0x80, + 0x21, 0x0a, 0x30, 0x49, 0x88, 0x90, 0x00, 0x41, 0x04, 0x29, 0x81, 0x80, 0x41, + 0x09, 0x00, 0x40, 0x12, 0x10, 0x40, 0x00, 0x10, 0x40, 0x48, 0x02, 0x05, 0x80, + 0x02, 0x21, 0x40, 0x20, 0x00, 0x58, 0x20, 0x60, 0x00, 0x90, 0x48, 0x00, 0x80, + 0x28, 0xc0, 0x80, 0x48, 0x00, 0x00, 0x44, 0x80, 0x02, 0x00, 0x09, 0x06, 0x00, + 0x12, 0x02, 0x01, 0x00, 0x10, 0x08, 0x83, 0x10, 0x45, 0x12, 0x00, 0x2c, 0x08, + 0x04, 0x44, 0x00, 0x20, 0x20, 0xc0, 0x10, 0x20, 0x01, 0x00, 0x05, 0xc8, 0x20, + 0x04, 0x98, 0x10, 0x08, 0x10, 0x00, 0x24, 0x02, 0x16, 0x40, 0x88, 0x00, 0x61, + 0x88, 0x12, 0x24, 0x80, 0xa6, 0x00, 0x42, 0x00, 0x08, 0x10, 0x06, 0x48, 0x40, + 0xa0, 0x00, 0x50, 0x20, 0x04, 0x81, 0xa4, 0x40, 0x18, 0x00, 0x08, 0x10, 0x80, + 0x01, 0x01}; + +#if RSA_KEY_SIEVE && SIMULATION && RSA_INSTRUMENT +UINT32 PrimeIndex = 0; +UINT32 failedAtIteration[10] = {0}; +UINT32 PrimeCounts[3] = {0}; +UINT32 MillerRabinTrials[3] = {0}; +UINT32 totalFieldsSieved[3] = {0}; +UINT32 bitsInFieldAfterSieve[3] = {0}; +UINT32 emptyFieldsSieved[3] = {0}; +UINT32 noPrimeFields[3] = {0}; +UINT32 primesChecked[3] = {0}; +UINT16 lastSievePrime = 0; +#endif \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/RsaKeyCache.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/RsaKeyCache.c new file mode 100644 index 0000000..d538bf6 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/RsaKeyCache.c @@ -0,0 +1,244 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// This file contains the functions to implement the RSA key cache that can be used +// to speed up simulation. +// +// Only one key is created for each supported key size and it is returned whenever +// a key of that size is requested. +// +// If desired, the key cache can be populated from a file. This allows multiple +// TPM to run with the same RSA keys. Also, when doing simulation, the DRBG will +// use preset sequences so it is not too hard to repeat sequences for debug or +// profile or stress. +// +// When the key cache is enabled, a call to CryptRsaGenerateKey() will call the +// GetCachedRsaKey(). If the cache is enabled and populated, then the cached key +// of the requested size is returned. If a key of the requested size is not +// available, the no key is loaded and the requested key will need to be generated. +// If the cache is not populated, the TPM will open a file that has the appropriate +// name for the type of keys required (CRT or no-CRT). If the file is the right +// size, it is used. If the file doesn't exist or the file does not have the correct +// size, the TMP will populate the cache with new keys of the required size and +// write the cache data to the file so that they will be available the next time. +// +// Currently, if two simulations are being run with TPM's that have different RSA +// key sizes (e.g,, one with 1024 and 2048 and another with 2048 and 3072, then the +// files will not match for the both of them and they will both try to overwrite +// the other's cache file. I may try to do something about this if necessary. + +//** Includes, Types, Locals, and Defines + +#include "Tpm.h" + +#if USE_RSA_KEY_CACHE + +# include +# include "RsaKeyCache_fp.h" + +# if CRT_FORMAT_RSA == YES +# define CACHE_FILE_NAME "RsaKeyCacheCrt.data" +# else +# define CACHE_FILE_NAME "RsaKeyCacheNoCrt.data" +# endif + +typedef struct _RSA_KEY_CACHE_ +{ + TPM2B_PUBLIC_KEY_RSA publicModulus; + TPM2B_PRIVATE_KEY_RSA privateExponent; +} RSA_KEY_CACHE; + +// Determine the number of RSA key sizes for the cache +TPMI_RSA_KEY_BITS SupportedRsaKeySizes[] = { +# if RSA_1024 + 1024, +# endif +# if RSA_2048 + 2048, +# endif +# if RSA_3072 + 3072, +# endif +# if RSA_4096 + 4096, +# endif + 0}; + +# define RSA_KEY_CACHE_ENTRIES (RSA_1024 + RSA_2048 + RSA_3072 + RSA_4096) + +// The key cache holds one entry for each of the supported key sizes +RSA_KEY_CACHE s_rsaKeyCache[RSA_KEY_CACHE_ENTRIES]; +// Indicates if the key cache is loaded. It can be loaded and enabled or disabled. +BOOL s_keyCacheLoaded = 0; + +// Indicates if the key cache is enabled +int s_rsaKeyCacheEnabled = FALSE; + +//*** RsaKeyCacheControl() +// Used to enable and disable the RSA key cache. +LIB_EXPORT void RsaKeyCacheControl(int state) +{ + s_rsaKeyCacheEnabled = state; +} + +//*** InitializeKeyCache() +// This will initialize the key cache and attempt to write it to a file for later +// use. +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure +static BOOL InitializeKeyCache(TPMT_PUBLIC* publicArea, + TPMT_SENSITIVE* sensitive, + RAND_STATE* rand // IN: if not NULL, the deterministic + // RNG state +) +{ + int index; + TPM_KEY_BITS keySave = publicArea->parameters.rsaDetail.keyBits; + BOOL OK = TRUE; + // + s_rsaKeyCacheEnabled = FALSE; + for(index = 0; OK && index < RSA_KEY_CACHE_ENTRIES; index++) + { + publicArea->parameters.rsaDetail.keyBits = SupportedRsaKeySizes[index]; + OK = (CryptRsaGenerateKey(publicArea, sensitive, rand) == TPM_RC_SUCCESS); + if(OK) + { + s_rsaKeyCache[index].publicModulus = publicArea->unique.rsa; + s_rsaKeyCache[index].privateExponent = sensitive->sensitive.rsa; + } + } + publicArea->parameters.rsaDetail.keyBits = keySave; + s_keyCacheLoaded = OK; +# if SIMULATION && USE_RSA_KEY_CACHE && USE_KEY_CACHE_FILE + if(OK) + { + FILE* cacheFile; + const char* fn = CACHE_FILE_NAME; + +# if defined _MSC_VER + if(fopen_s(&cacheFile, fn, "w+b") != 0) +# else + cacheFile = fopen(fn, "w+b"); + if(NULL == cacheFile) +# endif + { + printf("Can't open %s for write.\n", fn); + } + else + { + fseek(cacheFile, 0, SEEK_SET); + if(fwrite(s_rsaKeyCache, 1, sizeof(s_rsaKeyCache), cacheFile) + != sizeof(s_rsaKeyCache)) + { + printf("Error writing cache to %s.", fn); + } + } + if(cacheFile) + fclose(cacheFile); + } +# endif + return s_keyCacheLoaded; +} + +//*** KeyCacheLoaded() +// Checks that key cache is loaded. +// Return Type: BOOL +// TRUE(1) cache loaded +// FALSE(0) cache not loaded +static BOOL KeyCacheLoaded(TPMT_PUBLIC* publicArea, + TPMT_SENSITIVE* sensitive, + RAND_STATE* rand // IN: if not NULL, the deterministic + // RNG state +) +{ +# if SIMULATION && USE_RSA_KEY_CACHE && USE_KEY_CACHE_FILE + if(!s_keyCacheLoaded) + { + FILE* cacheFile; + const char* fn = CACHE_FILE_NAME; +# if defined _MSC_VER && 1 + if(fopen_s(&cacheFile, fn, "r+b") == 0) +# else + cacheFile = fopen(fn, "r+b"); + if(NULL != cacheFile) +# endif + { + fseek(cacheFile, 0L, SEEK_END); + if(ftell(cacheFile) == sizeof(s_rsaKeyCache)) + { + fseek(cacheFile, 0L, SEEK_SET); + s_keyCacheLoaded = + (fread(&s_rsaKeyCache, 1, sizeof(s_rsaKeyCache), cacheFile) + == sizeof(s_rsaKeyCache)); + } + fclose(cacheFile); + } + } +# endif + if(!s_keyCacheLoaded) + s_rsaKeyCacheEnabled = InitializeKeyCache(publicArea, sensitive, rand); + return s_keyCacheLoaded; +} + +//*** GetCachedRsaKey() +// Return Type: BOOL +// TRUE(1) key loaded +// FALSE(0) key not loaded +BOOL GetCachedRsaKey(TPMT_PUBLIC* publicArea, + TPMT_SENSITIVE* sensitive, + RAND_STATE* rand // IN: if not NULL, the deterministic + // RNG state +) +{ + int keyBits = publicArea->parameters.rsaDetail.keyBits; + int index; + // + if(KeyCacheLoaded(publicArea, sensitive, rand)) + { + for(index = 0; index < RSA_KEY_CACHE_ENTRIES; index++) + { + if((s_rsaKeyCache[index].publicModulus.t.size * 8) == keyBits) + { + publicArea->unique.rsa = s_rsaKeyCache[index].publicModulus; + sensitive->sensitive.rsa = s_rsaKeyCache[index].privateExponent; + return TRUE; + } + } + return FALSE; + } + return s_keyCacheLoaded; +} +#endif // defined SIMULATION && defined USE_RSA_KEY_CACHE diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/Ticket.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/Ticket.c new file mode 100644 index 0000000..bc321c3 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/Ticket.c @@ -0,0 +1,269 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +/* + This clause contains the functions used for ticket computations. +*/ + +//** Includes +#include "Tpm.h" +#include "Marshal.h" + +//** Functions + +//*** TicketIsSafe() +// This function indicates if producing a ticket is safe. +// It checks if the leading bytes of an input buffer is TPM_GENERATED_VALUE +// or its substring of canonical form. If so, it is not safe to produce ticket +// for an input buffer claiming to be TPM generated buffer +// Return Type: BOOL +// TRUE(1) safe to produce ticket +// FALSE(0) not safe to produce ticket +BOOL TicketIsSafe(TPM2B* buffer) +{ + TPM_CONSTANTS32 valueToCompare = TPM_GENERATED_VALUE; + BYTE bufferToCompare[sizeof(valueToCompare)]; + BYTE* marshalBuffer; + // + // If the buffer size is less than the size of TPM_GENERATED_VALUE, assume + // it is not safe to generate a ticket + if(buffer->size < sizeof(valueToCompare)) + return FALSE; + marshalBuffer = bufferToCompare; + TPM_CONSTANTS32_Marshal(&valueToCompare, &marshalBuffer, NULL); + if(MemoryEqual(buffer->buffer, bufferToCompare, sizeof(valueToCompare))) + return FALSE; + else + return TRUE; +} + +//*** TicketComputeVerified() +// This function creates a TPMT_TK_VERIFIED ticket. +/*(See part 2 specification) +// The ticket is computed as: +// HMAC(proof, (TPM_ST_VERIFIED | digest | keyName)) +// Where: +// HMAC() an HMAC using the hash of proof +// proof a TPM secret value associated with the hierarchy +// associated with keyName +// TPM_ST_VERIFIED a value to differentiate the tickets +// digest the signed digest +// keyName the Name of the key that signed digest +*/ +void TicketComputeVerified( + TPMI_RH_HIERARCHY hierarchy, // IN: hierarchy constant for ticket + TPM2B_DIGEST* digest, // IN: digest + TPM2B_NAME* keyName, // IN: name of key that signed the values + TPMT_TK_VERIFIED* ticket // OUT: verified ticket +) +{ + TPM2B_PROOF* proof; + HMAC_STATE hmacState; + // + // Fill in ticket fields + ticket->tag = TPM_ST_VERIFIED; + ticket->hierarchy = hierarchy; + proof = HierarchyGetProof(hierarchy); + + // Start HMAC using the proof value of the hierarchy as the HMAC key + ticket->digest.t.size = + CryptHmacStart2B(&hmacState, CONTEXT_INTEGRITY_HASH_ALG, &proof->b); + // TPM_ST_VERIFIED + CryptDigestUpdateInt(&hmacState, sizeof(TPM_ST), ticket->tag); + // digest + CryptDigestUpdate2B(&hmacState.hashState, &digest->b); + // key name + CryptDigestUpdate2B(&hmacState.hashState, &keyName->b); + // done + CryptHmacEnd2B(&hmacState, &ticket->digest.b); + + return; +} + +//*** TicketComputeAuth() +// This function creates a TPMT_TK_AUTH ticket. +/*(See part 2 specification) +// The ticket is computed as: +// HMAC(proof, (type || timeout || timeEpoch || cpHash +// || policyRef || keyName)) +// where: +// HMAC() an HMAC using the hash of proof +// proof a TPM secret value associated with the hierarchy of the key +// associated with keyName. +// type a value to differentiate the tickets. It could be either +// TPM_ST_AUTH_SECRET or TPM_ST_AUTH_SIGNED +// timeout TPM-specific value indicating when the authorization expires +// timeEpoch TPM-specific value indicating the epoch for the timeout +// cpHash optional hash (digest only) of the authorized command +// policyRef optional reference to a policy value +// keyName name of the key that signed the authorization +*/ +void TicketComputeAuth( + TPM_ST type, // IN: the type of ticket. + TPMI_RH_HIERARCHY hierarchy, // IN: hierarchy constant for ticket + UINT64 timeout, // IN: timeout + BOOL expiresOnReset, // IN: flag to indicate if ticket expires on + // TPM Reset + TPM2B_DIGEST* cpHashA, // IN: input cpHashA + TPM2B_NONCE* policyRef, // IN: input policyRef + TPM2B_NAME* entityName, // IN: name of entity + TPMT_TK_AUTH* ticket // OUT: Created ticket +) +{ + TPM2B_PROOF* proof; + HMAC_STATE hmacState; + // + // Get proper proof + proof = HierarchyGetProof(hierarchy); + + // Fill in ticket fields + ticket->tag = type; + ticket->hierarchy = hierarchy; + + // Start HMAC with hierarchy proof as the HMAC key + ticket->digest.t.size = + CryptHmacStart2B(&hmacState, CONTEXT_INTEGRITY_HASH_ALG, &proof->b); + // TPM_ST_AUTH_SECRET or TPM_ST_AUTH_SIGNED, + CryptDigestUpdateInt(&hmacState, sizeof(UINT16), ticket->tag); + // cpHash + CryptDigestUpdate2B(&hmacState.hashState, &cpHashA->b); + // policyRef + CryptDigestUpdate2B(&hmacState.hashState, &policyRef->b); + // keyName + CryptDigestUpdate2B(&hmacState.hashState, &entityName->b); + // timeout + CryptDigestUpdateInt(&hmacState, sizeof(timeout), timeout); + if(timeout != 0) + { + // epoch + CryptDigestUpdateInt(&hmacState.hashState, sizeof(CLOCK_NONCE), g_timeEpoch); + // reset count + if(expiresOnReset) + CryptDigestUpdateInt( + &hmacState.hashState, sizeof(gp.totalResetCount), gp.totalResetCount); + } + // done + CryptHmacEnd2B(&hmacState, &ticket->digest.b); + + return; +} + +//*** TicketComputeHashCheck() +// This function creates a TPMT_TK_HASHCHECK ticket. +/*(See part 2 specification) +// The ticket is computed as: +// HMAC(proof, (TPM_ST_HASHCHECK || digest )) +// where: +// HMAC() an HMAC using the hash of proof +// proof a TPM secret value associated with the hierarchy +// TPM_ST_HASHCHECK +// a value to differentiate the tickets +// digest the digest of the data +*/ +void TicketComputeHashCheck( + TPMI_RH_HIERARCHY hierarchy, // IN: hierarchy constant for ticket + TPM_ALG_ID hashAlg, // IN: the hash algorithm for 'digest' + TPM2B_DIGEST* digest, // IN: input digest + TPMT_TK_HASHCHECK* ticket // OUT: Created ticket +) +{ + TPM2B_PROOF* proof; + HMAC_STATE hmacState; + // + // Get proper proof + proof = HierarchyGetProof(hierarchy); + + // Fill in ticket fields + ticket->tag = TPM_ST_HASHCHECK; + ticket->hierarchy = hierarchy; + + // Start HMAC using hierarchy proof as HMAC key + ticket->digest.t.size = + CryptHmacStart2B(&hmacState, CONTEXT_INTEGRITY_HASH_ALG, &proof->b); + // TPM_ST_HASHCHECK + CryptDigestUpdateInt(&hmacState, sizeof(TPM_ST), ticket->tag); + // hash algorithm + CryptDigestUpdateInt(&hmacState, sizeof(hashAlg), hashAlg); + // digest + CryptDigestUpdate2B(&hmacState.hashState, &digest->b); + // done + CryptHmacEnd2B(&hmacState, &ticket->digest.b); + + return; +} + +//*** TicketComputeCreation() +// This function creates a TPMT_TK_CREATION ticket. +/*(See part 2 specification) +// The ticket is computed as: +// HMAC(proof, (TPM_ST_CREATION || Name || hash(TPMS_CREATION_DATA))) +// Where: +// HMAC() an HMAC using the hash of proof +// proof a TPM secret value associated with the hierarchy associated with Name +// TPM_ST_VERIFIED a value to differentiate the tickets +// Name the Name of the object to which the creation data is to be associated +// TPMS_CREATION_DATA the creation data structure associated with Name +*/ +void TicketComputeCreation(TPMI_RH_HIERARCHY hierarchy, // IN: hierarchy for ticket + TPM2B_NAME* name, // IN: object name + TPM2B_DIGEST* creation, // IN: creation hash + TPMT_TK_CREATION* ticket // OUT: created ticket +) +{ + TPM2B_PROOF* proof; + HMAC_STATE hmacState; + + // Get proper proof + proof = HierarchyGetProof(hierarchy); + + // Fill in ticket fields + ticket->tag = TPM_ST_CREATION; + ticket->hierarchy = hierarchy; + + // Start HMAC using hierarchy proof as HMAC key + ticket->digest.t.size = + CryptHmacStart2B(&hmacState, CONTEXT_INTEGRITY_HASH_ALG, &proof->b); + // TPM_ST_CREATION + CryptDigestUpdateInt(&hmacState, sizeof(TPM_ST), ticket->tag); + // name if provided + if(name != NULL) + CryptDigestUpdate2B(&hmacState.hashState, &name->b); + // creation hash + CryptDigestUpdate2B(&hmacState.hashState, &creation->b); + // Done + CryptHmacEnd2B(&hmacState, &ticket->digest.b); + + return; +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/ltc/TpmToLtcDesSupport.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/ltc/TpmToLtcDesSupport.c new file mode 100644 index 0000000..0d73c16 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/ltc/TpmToLtcDesSupport.c @@ -0,0 +1,71 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//** Introduction +// +// The functions in this file are used for initialization of the interface to the +// LibTomCrypt and MpaLib libraries. This is not used if only the LTC hash and +// symmetric functions are used. + +//** Defines and Includes + +#include "Tpm.h" + +#if(defined SYM_LIB_LTC) && ALG_TDES + +//** TDES_setup +// This function calls the LTC function to generate a TDES key schedule. If the +// key is one DES key (8 bytes), then it is replicated two more times to create a +// 24-byte TDES key. If the key is two key (16 bytes), then the first DES key is +// replicated to the third key position. +void TDES_setup(const BYTE* key, UINT32 keyBits, symmetric_key* skey) +{ + BYTE k[24]; + BYTE* kp; + + // If this is two-key, make it three key by replicating K1 + if(keyBits == 128) + { + memcpy(k, key, 16); + memcpy(&k[16], key, 8); + kp = k; + } + else + kp = (BYTE*)key; + + des3_setup(kp, 24, 0, skey); +} + +#endif // MATH_LIB_LTC && ALG_TDES diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/ltc/TpmToLtcMath.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/ltc/TpmToLtcMath.c new file mode 100644 index 0000000..b6da974 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/ltc/TpmToLtcMath.c @@ -0,0 +1,267 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//** Introduction +// +// This file contains the math functions that are not implemented in the BnMath +// library (yet). These math functions will call the ST MPA library or the +// LibTomCrypt library to execute the operations. Since the TPM internal big number +// format is identical to the MPA format, no reformatting is required. + +//** Includes +#include "Tpm.h" + +#ifdef MATH_LIB_LTC + +# if defined ECC_NIST_P256 && ECC_NIST_P256 == YES && ECC_CURVE_COUNT > 1 +# error "LibTomCrypt only supports P256" +# endif + +//** Functions + +//*** BnModMult() +// Does multiply and divide returning the remainder of the divide. +LIB_EXPORT BOOL BnModMult(bigNum result, bigConst op1, bigConst op2, bigConst modulus) +{ + BN_VAR(temp, LARGEST_NUMBER_BITS * 2); + // mpa_mul does not allocate from the pool if the result is not the same as + // op1 or op2. since this is assured by the stack allocation of 'temp', the + // pool pointer can be NULL + pAssert(BnGetAllocated(result) >= BnGetSize(modulus)); + mpa_mul((mpanum)temp, (const mpanum)op1, (const mpanum)op2, NULL); + return BnDiv(NULL, result, temp, modulus); +} + +//*** BnMult() +// Multiplies two numbers +LIB_EXPORT BOOL BnMult(bigNum result, bigConst multiplicand, bigConst multiplier) +{ + // Make sure that the mpa_mul function does not allocate anything + // from the POOL by eliminating the reason for doing it. + BN_VAR(tempResult, LARGEST_NUMBER_BITS * 2); + if(result != multiplicand && result != multiplier) + tempResult = result; + mpa_mul((mpanum)tempResult, + (const mpanum)multiplicand, + (const mpanum)multiplier, + NULL); + BnCopy(result, tempResult); + return TRUE; +} + +//*** BnDiv() +// This function divides two BIGNUM values. The function always returns TRUE. +LIB_EXPORT BOOL BnDiv( + bigNum quotient, bigNum remainder, bigConst dividend, bigConst divisor) +{ + MPA_ENTER(10, LARGEST_NUMBER_BITS); + pAssert(!BnEqualZero(divisor)); + if(BnGetSize(dividend) < BnGetSize(divisor)) + { + if(quotient) + BnSetWord(quotient, 0); + if(remainder) + BnCopy(remainder, dividend); + } + else + { + pAssert( + (quotient == NULL) + || (quotient->allocated >= (unsigned)(dividend->size - divisor->size))); + pAssert((remainder == NULL) || (remainder->allocated >= divisor->size)); + mpa_div((mpanum)quotient, + (mpanum)remainder, + (const mpanum)dividend, + (const mpanum)divisor, + POOL); + } + MPA_LEAVE(); + return TRUE; +} + +# ifdef TPM_ALG_RSA +//*** BnGcd() +// Get the greatest common divisor of two numbers +LIB_EXPORT BOOL BnGcd(bigNum gcd, // OUT: the common divisor + bigConst number1, // IN: + bigConst number2 // IN: +) +{ + MPA_ENTER(20, LARGEST_NUMBER_BITS); + // + mpa_gcd((mpanum)gcd, (mpanum)number1, (mpanum)number2, POOL); + MPA_LEAVE(); + return TRUE; +} + +//***BnModExp() +// Do modular exponentiation using BIGNUM values. The conversion from a bignum_t +// to a BIGNUM is trivial as they are based on the same structure +LIB_EXPORT BOOL BnModExp(bigNum result, // OUT: the result + bigConst number, // IN: number to exponentiate + bigConst exponent, // IN: + bigConst modulus // IN: +) +{ + MPA_ENTER(20, LARGEST_NUMBER_BITS); + BN_VAR(bnR, MAX_RSA_KEY_BITS); + BN_VAR(bnR2, MAX_RSA_KEY_BITS); + mpa_word_t n_inv; + mpa_word_t ffmCtx[mpa_fmm_context_size_in_U32(MAX_RSA_KEY_BITS)]; + // + mpa_init_static_fmm_context((mpa_fmm_context_base*)ffmCtx, + BYTES_TO_CRYPT_WORDS(sizeof(ffmCtx))); + // Generate modular form + if(mpa_compute_fmm_context( + (const mpanum)modulus, (mpanum)bnR, (mpanum)bnR2, &n_inv, POOL) + != 0) + FAIL(FATAL_ERROR_INTERNAL); + // Do exponentiation + mpa_exp_mod((mpanum)result, + (const mpanum)number, + (const mpanum)exponent, + (const mpanum)modulus, + (const mpanum)bnR, + (const mpanum)bnR2, + n_inv, + POOL); + MPA_LEAVE(); + return TRUE; +} + +//*** BnModInverse() +// Modular multiplicative inverse +LIB_EXPORT BOOL BnModInverse(bigNum result, bigConst number, bigConst modulus) +{ + BOOL retVal; + MPA_ENTER(10, LARGEST_NUMBER_BITS); + retVal = (mpa_inv_mod( + (mpanum)result, (const mpanum)number, (const mpanum)modulus, POOL) + == 0); + MPA_LEAVE(); + return retVal; +} +# endif // TPM_ALG_RSA + +# ifdef TPM_ALG_ECC + +//*** BnEccModMult() +// This function does a point multiply of the form R = [d]S +// return type: BOOL +// FALSE failure in operation; treat as result being point at infinity +LIB_EXPORT BOOL BnEccModMult(bigPoint R, // OUT: computed point + pointConst S, // IN: point to multiply by 'd' + bigConst d, // IN: scalar for [d]S + bigCurve E) +{ + MPA_ENTER(30, MAX_ECC_KEY_BITS * 2); + // The point multiply in LTC seems to need a large reciprocal for + // intermediate results + POINT_VAR(result, MAX_ECC_KEY_BITS * 4); + BOOL OK; + // + (POOL); // Avoid compiler warning + if(S == NULL) + S = CurveGetG(AccessCurveData(E)); + OK = + (ltc_ecc_mulmod( + (mpanum)d, (ecc_point*)S, (ecc_point*)result, (void*)CurveGetPrime(E), 1) + == CRYPT_OK); + OK = OK && !BnEqualZero(result->z); + if(OK) + BnPointCopy(R, result); + + MPA_LEAVE(); + return OK ? TPM_RC_SUCCESS : TPM_RC_NO_RESULT; +} + +//*** BnEccModMult2() +// This function does a point multiply of the form R = [d]S + [u]Q +// return type: BOOL +// FALSE failure in operation; treat as result being point at infinity +LIB_EXPORT BOOL BnEccModMult2(bigPoint R, // OUT: computed point + pointConst S, // IN: first point (optional) + bigConst d, // IN: scalar for [d]S or [d]G + pointConst Q, // IN: second point + bigConst u, // IN: second scalar + bigCurve E // IN: curve +) +{ + MPA_ENTER(80, MAX_ECC_KEY_BITS); + BOOL OK; + // The point multiply in LTC seems to need a large reciprocal for + // intermediate results + POINT_VAR(result, MAX_ECC_KEY_BITS * 4); + // + (POOL); // Avoid compiler warning + if(S == NULL) + S = CurveGetG(AccessCurveData(E)); + + OK = (ltc_ecc_mul2add((ecc_point*)S, + (mpanum)d, + (ecc_point*)Q, + (mpanum)u, + (ecc_point*)result, + (mpanum)CurveGetPrime(E)) + == CRYPT_OK); + OK = OK && !BnEqualZero(result->z); + + if(OK) + BnPointCopy(R, result); + + MPA_LEAVE(); + return OK ? TPM_RC_SUCCESS : TPM_RC_NO_RESULT; +} + +//*** BnEccAdd() +// This function does addition of two points. Since this is not implemented +// in LibTomCrypt() will try to trick it by doing multiply with scalar of 1. +// I have no idea if this will work and it's not needed unless MQV or the SM2 +// variant is enabled. +// return type: BOOL +// FALSE failure in operation; treat as result being point at infinity +LIB_EXPORT BOOL BnEccAdd(bigPoint R, // OUT: computed point + pointConst S, // IN: point to multiply by 'd' + pointConst Q, // IN: second point + bigCurve E // IN: curve +) +{ + BN_WORD_INITIALIZED(one, 1); + return BnEccModMult2(R, S, one, Q, one, E); +} + +# endif // TPM_ALG_ECC + +#endif // MATH_LIB_LTC diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/ltc/TpmToLtcSupport.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/ltc/TpmToLtcSupport.c new file mode 100644 index 0000000..b30d993 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/ltc/TpmToLtcSupport.c @@ -0,0 +1,85 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//** Introduction +// +// The functions in this file are used for initialization of the interface to the +// LibTomCrypt and MpsLib libraries. This is not used if only the LTC hash and +// symmetric functions are used. + +//** Defines and Includes + +#include "Tpm.h" + +#if defined(HASH_LIB_LTC) || defined(MATH_LIB_LTC) || defined(SYM_LIB_LTC) + +// This state is used because there is no way to pass the random number state +// to LibTomCrypt. I do not think that this is currently an issue because... +// Heck, just put in an assert and see what happens. +static void* s_randState; + +//*** LtcRand() +// This is a stub function that is called from the LibTomCrypt or libmpa code +// to get a random number. In turn, this will call the random RandGenerate +// function that was passed in LibraryInit(). This function will pass the pointer +// to the current rand state along with the random byte request. +uint32_t LtcRand(void* buf, size_t blen) +{ + pAssert(1); + DRBG_Generate(s_randState, buf, (uint16_t)blen); + return 0; +} + +//*** SupportLibInit() +// This does any initialization required by the support library. +LIB_EXPORT int SupportLibInit(void) +{ + mpa_set_random_generator(LtcRand); + s_randState = NULL; + external_mem_pool = NULL; + return 1; +} + +//*** LtcPoolInit() +// Function to initialize a pool. **** +LIB_EXPORT mpa_scratch_mem LtcPoolInit(mpa_word_t* poolAddress, int vars, int bits) +{ + mpa_scratch_mem pool = (mpa_scratch_mem)poolAddress; + mpa_init_scratch_mem(pool, vars, bits); + init_mpa_tomcrypt(pool); + return pool; +} + +#endif // HASH_LIB_LTC || MATH_LIB_LTC || SYM_LIB_LTC diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/ossl/TpmToOsslDesSupport.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/ossl/TpmToOsslDesSupport.c new file mode 100644 index 0000000..bb8872b --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/ossl/TpmToOsslDesSupport.c @@ -0,0 +1,84 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// +// The functions in this file are used for initialization of the interface to the +// OpenSSL library. + +//** Defines and Includes + +#include "Tpm.h" + +#if(defined SYM_LIB_OSSL) && ALG_TDES + +//**Functions +//*** TDES_set_encyrpt_key() +// This function makes creation of a TDES key look like the creation of a key for +// any of the other OpenSSL block ciphers. It will create three key schedules, +// one for each of the DES keys. If there are only two keys, then the third schedule +// is a copy of the first. +void TDES_set_encrypt_key( + const BYTE* key, UINT16 keySizeInBits, tpmKeyScheduleTDES* keySchedule) +{ + DES_set_key_unchecked((const_DES_cblock*)key, &keySchedule[0]); + DES_set_key_unchecked((const_DES_cblock*)&key[8], &keySchedule[1]); + // If is two-key, copy the schedule for K1 into K3, otherwise, compute the + // the schedule for K3 + if(keySizeInBits == 128) + keySchedule[2] = keySchedule[0]; + else + DES_set_key_unchecked((const_DES_cblock*)&key[16], &keySchedule[2]); +} + +//*** TDES_encyrpt() +// The TPM code uses one key schedule. For TDES, the schedule contains three +// schedules. OpenSSL wants the schedules referenced separately. This function +// does that. +void TDES_encrypt(const BYTE* in, BYTE* out, tpmKeyScheduleTDES* ks) +{ + DES_ecb3_encrypt( + (const_DES_cblock*)in, (DES_cblock*)out, &ks[0], &ks[1], &ks[2], DES_ENCRYPT); +} + +//*** TDES_decrypt() +// As with TDES_encypt() this function bridges between the TPM single schedule +// model and the OpenSSL three schedule model. +void TDES_decrypt(const BYTE* in, BYTE* out, tpmKeyScheduleTDES* ks) +{ + DES_ecb3_encrypt( + (const_DES_cblock*)in, (DES_cblock*)out, &ks[0], &ks[1], &ks[2], DES_DECRYPT); +} + +#endif // SYM_LIB_OSSL diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/ossl/TpmToOsslMath.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/ossl/TpmToOsslMath.c new file mode 100644 index 0000000..d1255b7 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/ossl/TpmToOsslMath.c @@ -0,0 +1,574 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// The functions in this file provide the low-level interface between the TPM code +// and the big number and elliptic curve math routines in OpenSSL. +// +// Most math on big numbers require a context. The context contains the memory in +// which OpenSSL creates and manages the big number values. When a OpenSSL math +// function will be called that modifies a BIGNUM value, that value must be created in +// an OpenSSL context. The first line of code in such a function must be: +// OSSL_ENTER(); and the last operation before returning must be OSSL_LEAVE(). +// OpenSSL variables can then be created with BnNewVariable(). Constant values to be +// used by OpenSSL are created from the bigNum values passed to the functions in this +// file. Space for the BIGNUM control block is allocated in the stack of the +// function and then it is initialized by calling BigInitialized(). That function +// sets up the values in the BIGNUM structure and sets the data pointer to point to +// the data in the bignum_t. This is only used when the value is known to be a +// constant in the called function. +// +// Because the allocations of constants is on the local stack and the +// OSSL_ENTER()/OSSL_LEAVE() pair flushes everything created in OpenSSL memory, there +// should be no chance of a memory leak. + +//** Includes and Defines +#include "Tpm.h" + +#ifdef MATH_LIB_OSSL +# include "TpmToOsslMath_fp.h" + +//** Functions + +//*** OsslToTpmBn() +// This function converts an OpenSSL BIGNUM to a TPM bignum. In this implementation +// it is assumed that OpenSSL uses a different control structure but the same data +// layout -- an array of native-endian words in little-endian order. +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure because value will not fit or OpenSSL variable doesn't +// exist +BOOL OsslToTpmBn(bigNum bn, BIGNUM* osslBn) +{ + VERIFY(osslBn != NULL); + // If the bn is NULL, it means that an output value pointer was NULL meaning that + // the results is simply to be discarded. + if(bn != NULL) + { + int i; + // + VERIFY((unsigned)osslBn->top <= BnGetAllocated(bn)); + for(i = 0; i < osslBn->top; i++) + bn->d[i] = osslBn->d[i]; + BnSetTop(bn, osslBn->top); + } + return TRUE; +Error: + return FALSE; +} + +//*** BigInitialized() +// This function initializes an OSSL BIGNUM from a TPM bigConst. Do not use this for +// values that are passed to OpenSLL when they are not declared as const in the +// function prototype. Instead, use BnNewVariable(). +BIGNUM* BigInitialized(BIGNUM* toInit, bigConst initializer) +{ + if(initializer == NULL) + FAIL(FATAL_ERROR_PARAMETER); + if(toInit == NULL || initializer == NULL) + return NULL; + toInit->d = (BN_ULONG*)&initializer->d[0]; + toInit->dmax = (int)initializer->allocated; + toInit->top = (int)initializer->size; + toInit->neg = 0; + toInit->flags = 0; + return toInit; +} + +# ifndef OSSL_DEBUG +# define BIGNUM_PRINT(label, bn, eol) +# define DEBUG_PRINT(x) +# else +# define DEBUG_PRINT(x) printf("%s", x) +# define BIGNUM_PRINT(label, bn, eol) BIGNUM_print((label), (bn), (eol)) + +//*** BIGNUM_print() +static void BIGNUM_print(const char* label, const BIGNUM* a, BOOL eol) +{ + BN_ULONG* d; + int i; + int notZero = FALSE; + + if(label != NULL) + printf("%s", label); + if(a == NULL) + { + printf("NULL"); + goto done; + } + if(a->neg) + printf("-"); + for(i = a->top, d = &a->d[i - 1]; i > 0; i--) + { + int j; + BN_ULONG l = *d--; + for(j = BN_BITS2 - 8; j >= 0; j -= 8) + { + BYTE b = (BYTE)((l >> j) & 0xFF); + notZero = notZero || (b != 0); + if(notZero) + printf("%02x", b); + } + if(!notZero) + printf("0"); + } +done: + if(eol) + printf("\n"); + return; +} +# endif + +//*** BnNewVariable() +// This function allocates a new variable in the provided context. If the context +// does not exist or the allocation fails, it is a catastrophic failure. +static BIGNUM* BnNewVariable(BN_CTX* CTX) +{ + BIGNUM* new; + // + // This check is intended to protect against calling this function without + // having initialized the CTX. + if((CTX == NULL) || ((new = BN_CTX_get(CTX)) == NULL)) + FAIL(FATAL_ERROR_ALLOCATION); + return new; +} + +# if LIBRARY_COMPATIBILITY_CHECK + +//*** MathLibraryCompatibilityCheck() +BOOL MathLibraryCompatibilityCheck(void) +{ + OSSL_ENTER(); + BIGNUM* osslTemp = BnNewVariable(CTX); + crypt_uword_t i; + BYTE test[] = {0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x18, 0x17, 0x16, 0x15, + 0x14, 0x13, 0x12, 0x11, 0x10, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, + 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00}; + BN_VAR(tpmTemp, sizeof(test) * 8); // allocate some space for a test value + // + // Convert the test data to a bigNum + BnFromBytes(tpmTemp, test, sizeof(test)); + // Convert the test data to an OpenSSL BIGNUM + BN_bin2bn(test, sizeof(test), osslTemp); + // Make sure the values are consistent + VERIFY(osslTemp->top == (int)tpmTemp->size); + for(i = 0; i < tpmTemp->size; i++) + VERIFY(osslTemp->d[i] == tpmTemp->d[i]); + OSSL_LEAVE(); + return 1; +Error: + return 0; +} +# endif + +//*** BnModMult() +// This function does a modular multiply. It first does a multiply and then a divide +// and returns the remainder of the divide. +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure in operation +LIB_EXPORT BOOL BnModMult(bigNum result, bigConst op1, bigConst op2, bigConst modulus) +{ + OSSL_ENTER(); + BOOL OK = TRUE; + BIGNUM* bnResult = BN_NEW(); + BIGNUM* bnTemp = BN_NEW(); + BIG_INITIALIZED(bnOp1, op1); + BIG_INITIALIZED(bnOp2, op2); + BIG_INITIALIZED(bnMod, modulus); + // + VERIFY(BN_mul(bnTemp, bnOp1, bnOp2, CTX)); + VERIFY(BN_div(NULL, bnResult, bnTemp, bnMod, CTX)); + VERIFY(OsslToTpmBn(result, bnResult)); + goto Exit; +Error: + OK = FALSE; +Exit: + OSSL_LEAVE(); + return OK; +} + +//*** BnMult() +// Multiplies two numbers +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure in operation +LIB_EXPORT BOOL BnMult(bigNum result, bigConst multiplicand, bigConst multiplier) +{ + OSSL_ENTER(); + BIGNUM* bnTemp = BN_NEW(); + BOOL OK = TRUE; + BIG_INITIALIZED(bnA, multiplicand); + BIG_INITIALIZED(bnB, multiplier); + // + VERIFY(BN_mul(bnTemp, bnA, bnB, CTX)); + VERIFY(OsslToTpmBn(result, bnTemp)); + goto Exit; +Error: + OK = FALSE; +Exit: + OSSL_LEAVE(); + return OK; +} + +//*** BnDiv() +// This function divides two bigNum values. The function returns FALSE if +// there is an error in the operation. +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure in operation +LIB_EXPORT BOOL BnDiv( + bigNum quotient, bigNum remainder, bigConst dividend, bigConst divisor) +{ + OSSL_ENTER(); + BIGNUM* bnQ = BN_NEW(); + BIGNUM* bnR = BN_NEW(); + BOOL OK = TRUE; + BIG_INITIALIZED(bnDend, dividend); + BIG_INITIALIZED(bnSor, divisor); + // + if(BnEqualZero(divisor)) + FAIL(FATAL_ERROR_DIVIDE_ZERO); + VERIFY(BN_div(bnQ, bnR, bnDend, bnSor, CTX)); + VERIFY(OsslToTpmBn(quotient, bnQ)); + VERIFY(OsslToTpmBn(remainder, bnR)); + DEBUG_PRINT("In BnDiv:\n"); + BIGNUM_PRINT(" bnDividend: ", bnDend, TRUE); + BIGNUM_PRINT(" bnDivisor: ", bnSor, TRUE); + BIGNUM_PRINT(" bnQuotient: ", bnQ, TRUE); + BIGNUM_PRINT(" bnRemainder: ", bnR, TRUE); + goto Exit; +Error: + OK = FALSE; +Exit: + OSSL_LEAVE(); + return OK; +} + +# if ALG_RSA +//*** BnGcd() +// Get the greatest common divisor of two numbers +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure in operation +LIB_EXPORT BOOL BnGcd(bigNum gcd, // OUT: the common divisor + bigConst number1, // IN: + bigConst number2 // IN: +) +{ + OSSL_ENTER(); + BIGNUM* bnGcd = BN_NEW(); + BOOL OK = TRUE; + BIG_INITIALIZED(bn1, number1); + BIG_INITIALIZED(bn2, number2); + // + VERIFY(BN_gcd(bnGcd, bn1, bn2, CTX)); + VERIFY(OsslToTpmBn(gcd, bnGcd)); + goto Exit; +Error: + OK = FALSE; +Exit: + OSSL_LEAVE(); + return OK; +} + +//***BnModExp() +// Do modular exponentiation using bigNum values. The conversion from a bignum_t to +// a bigNum is trivial as they are based on the same structure +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure in operation +LIB_EXPORT BOOL BnModExp(bigNum result, // OUT: the result + bigConst number, // IN: number to exponentiate + bigConst exponent, // IN: + bigConst modulus // IN: +) +{ + OSSL_ENTER(); + BIGNUM* bnResult = BN_NEW(); + BOOL OK = TRUE; + BIG_INITIALIZED(bnN, number); + BIG_INITIALIZED(bnE, exponent); + BIG_INITIALIZED(bnM, modulus); + // + VERIFY(BN_mod_exp(bnResult, bnN, bnE, bnM, CTX)); + VERIFY(OsslToTpmBn(result, bnResult)); + goto Exit; +Error: + OK = FALSE; +Exit: + OSSL_LEAVE(); + return OK; +} + +//*** BnModInverse() +// Modular multiplicative inverse +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure in operation +LIB_EXPORT BOOL BnModInverse(bigNum result, bigConst number, bigConst modulus) +{ + OSSL_ENTER(); + BIGNUM* bnResult = BN_NEW(); + BOOL OK = TRUE; + BIG_INITIALIZED(bnN, number); + BIG_INITIALIZED(bnM, modulus); + // + VERIFY(BN_mod_inverse(bnResult, bnN, bnM, CTX) != NULL); + VERIFY(OsslToTpmBn(result, bnResult)); + goto Exit; +Error: + OK = FALSE; +Exit: + OSSL_LEAVE(); + return OK; +} +# endif // ALG_RSA + +# if ALG_ECC + +//*** PointFromOssl() +// Function to copy the point result from an OSSL function to a bigNum +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure in operation +static BOOL PointFromOssl(bigPoint pOut, // OUT: resulting point + EC_POINT* pIn, // IN: the point to return + bigCurve E // IN: the curve +) +{ + BIGNUM* x = NULL; + BIGNUM* y = NULL; + BOOL OK; + BN_CTX_start(E->CTX); + // + x = BN_CTX_get(E->CTX); + y = BN_CTX_get(E->CTX); + + if(y == NULL) + FAIL(FATAL_ERROR_ALLOCATION); + // If this returns false, then the point is at infinity + OK = EC_POINT_get_affine_coordinates_GFp(E->G, pIn, x, y, E->CTX); + if(OK) + { + OsslToTpmBn(pOut->x, x); + OsslToTpmBn(pOut->y, y); + BnSetWord(pOut->z, 1); + } + else + BnSetWord(pOut->z, 0); + BN_CTX_end(E->CTX); + return OK; +} + +//*** EcPointInitialized() +// Allocate and initialize a point. +static EC_POINT* EcPointInitialized(pointConst initializer, bigCurve E) +{ + EC_POINT* P = NULL; + + if(initializer != NULL) + { + BIG_INITIALIZED(bnX, initializer->x); + BIG_INITIALIZED(bnY, initializer->y); + if(E == NULL) + FAIL(FATAL_ERROR_ALLOCATION); + P = EC_POINT_new(E->G); + if(!EC_POINT_set_affine_coordinates_GFp(E->G, P, bnX, bnY, E->CTX)) + P = NULL; + } + return P; +} + +//*** BnCurveInitialize() +// This function initializes the OpenSSL curve information structure. This +// structure points to the TPM-defined values for the curve, to the context for the +// number values in the frame, and to the OpenSSL-defined group values. +// Return Type: bigCurve * +// NULL the TPM_ECC_CURVE is not valid or there was a problem in +// in initializing the curve data +// non-NULL points to 'E' +LIB_EXPORT bigCurve BnCurveInitialize( + bigCurve E, // IN: curve structure to initialize + TPM_ECC_CURVE curveId // IN: curve identifier +) +{ + const ECC_CURVE_DATA* C = GetCurveData(curveId); + if(C == NULL) + E = NULL; + if(E != NULL) + { + // This creates the OpenSSL memory context that stays in effect as long as the + // curve (E) is defined. + OSSL_ENTER(); // if the allocation fails, the TPM fails + EC_POINT* P = NULL; + BIG_INITIALIZED(bnP, C->prime); + BIG_INITIALIZED(bnA, C->a); + BIG_INITIALIZED(bnB, C->b); + BIG_INITIALIZED(bnX, C->base.x); + BIG_INITIALIZED(bnY, C->base.y); + BIG_INITIALIZED(bnN, C->order); + BIG_INITIALIZED(bnH, C->h); + // + E->C = C; + E->CTX = CTX; + + // initialize EC group, associate a generator point and initialize the point + // from the parameter data + // Create a group structure + E->G = EC_GROUP_new_curve_GFp(bnP, bnA, bnB, CTX); + VERIFY(E->G != NULL); + + // Allocate a point in the group that will be used in setting the + // generator. This is not needed after the generator is set. + P = EC_POINT_new(E->G); + VERIFY(P != NULL); + + // Need to use this in case Montgomery method is being used + VERIFY(EC_POINT_set_affine_coordinates_GFp(E->G, P, bnX, bnY, CTX)); + // Now set the generator + VERIFY(EC_GROUP_set_generator(E->G, P, bnN, bnH)); + + EC_POINT_free(P); + goto Exit; +Error: + EC_POINT_free(P); + BnCurveFree(E); + E = NULL; + } +Exit: + return E; +} + +//*** BnCurveFree() +// This function will free the allocated components of the curve and end the +// frame in which the curve data exists +LIB_EXPORT void BnCurveFree(bigCurve E) +{ + if(E) + { + EC_GROUP_free(E->G); + OsslContextLeave(E->CTX); + } +} + +//*** BnEccModMult() +// This function does a point multiply of the form R = [d]S +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure in operation; treat as result being point at infinity +LIB_EXPORT BOOL BnEccModMult(bigPoint R, // OUT: computed point + pointConst S, // IN: point to multiply by 'd' (optional) + bigConst d, // IN: scalar for [d]S + bigCurve E) +{ + EC_POINT* pR = EC_POINT_new(E->G); + EC_POINT* pS = EcPointInitialized(S, E); + BIG_INITIALIZED(bnD, d); + + if(S == NULL) + EC_POINT_mul(E->G, pR, bnD, NULL, NULL, E->CTX); + else + EC_POINT_mul(E->G, pR, NULL, pS, bnD, E->CTX); + PointFromOssl(R, pR, E); + EC_POINT_free(pR); + EC_POINT_free(pS); + return !BnEqualZero(R->z); +} + +//*** BnEccModMult2() +// This function does a point multiply of the form R = [d]G + [u]Q +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure in operation; treat as result being point at infinity +LIB_EXPORT BOOL BnEccModMult2(bigPoint R, // OUT: computed point + pointConst S, // IN: optional point + bigConst d, // IN: scalar for [d]S or [d]G + pointConst Q, // IN: second point + bigConst u, // IN: second scalar + bigCurve E // IN: curve +) +{ + EC_POINT* pR = EC_POINT_new(E->G); + EC_POINT* pS = EcPointInitialized(S, E); + BIG_INITIALIZED(bnD, d); + EC_POINT* pQ = EcPointInitialized(Q, E); + BIG_INITIALIZED(bnU, u); + + if(S == NULL || S == (pointConst) & (AccessCurveData(E)->base)) + EC_POINT_mul(E->G, pR, bnD, pQ, bnU, E->CTX); + else + { + const EC_POINT* points[2]; + const BIGNUM* scalars[2]; + points[0] = pS; + points[1] = pQ; + scalars[0] = bnD; + scalars[1] = bnU; + EC_POINTs_mul(E->G, pR, NULL, 2, points, scalars, E->CTX); + } + PointFromOssl(R, pR, E); + EC_POINT_free(pR); + EC_POINT_free(pS); + EC_POINT_free(pQ); + return !BnEqualZero(R->z); +} + +//** BnEccAdd() +// This function does addition of two points. +// Return Type: BOOL +// TRUE(1) success +// FALSE(0) failure in operation; treat as result being point at infinity +LIB_EXPORT BOOL BnEccAdd(bigPoint R, // OUT: computed point + pointConst S, // IN: point to multiply by 'd' + pointConst Q, // IN: second point + bigCurve E // IN: curve +) +{ + EC_POINT* pR = EC_POINT_new(E->G); + EC_POINT* pS = EcPointInitialized(S, E); + EC_POINT* pQ = EcPointInitialized(Q, E); + // + EC_POINT_add(E->G, pR, pS, pQ, E->CTX); + + PointFromOssl(R, pR, E); + EC_POINT_free(pR); + EC_POINT_free(pS); + EC_POINT_free(pQ); + return !BnEqualZero(R->z); +} + +# endif // ALG_ECC + +#endif // MATHLIB OSSL \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/ossl/TpmToOsslSupport.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/ossl/TpmToOsslSupport.c new file mode 100644 index 0000000..f30263c --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/ossl/TpmToOsslSupport.c @@ -0,0 +1,94 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// +// The functions in this file are used for initialization of the interface to the +// OpenSSL library. + +//** Defines and Includes + +#include "Tpm.h" + +#if defined(HASH_LIB_OSSL) || defined(MATH_LIB_OSSL) || defined(SYM_LIB_OSSL) +// Used to pass the pointers to the correct sub-keys +typedef const BYTE* desKeyPointers[3]; + +//*** SupportLibInit() +// This does any initialization required by the support library. +LIB_EXPORT int SupportLibInit(void) +{ + return TRUE; +} + +//*** OsslContextEnter() +// This function is used to initialize an OpenSSL context at the start of a function +// that will call to an OpenSSL math function. +BN_CTX* OsslContextEnter(void) +{ + BN_CTX* CTX = BN_CTX_new(); + // + return OsslPushContext(CTX); +} + +//*** OsslContextLeave() +// This is the companion function to OsslContextEnter(). +void OsslContextLeave(BN_CTX* CTX) +{ + OsslPopContext(CTX); + BN_CTX_free(CTX); +} + +//*** OsslPushContext() +// This function is used to create a frame in a context. All values allocated within +// this context after the frame is started will be automatically freed when the +// context (OsslPopContext() +BN_CTX* OsslPushContext(BN_CTX* CTX) +{ + if(CTX == NULL) + FAIL(FATAL_ERROR_ALLOCATION); + BN_CTX_start(CTX); + return CTX; +} + +//*** OsslPopContext() +// This is the companion function to OsslPushContext(). +void OsslPopContext(BN_CTX* CTX) +{ + // BN_CTX_end can't be called with NULL. It will blow up. + if(CTX != NULL) + BN_CTX_end(CTX); +} + +#endif // HASH_LIB_OSSL || MATH_LIB_OSSL || SYM_LIB_OSSL diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/wolf/TpmToWolfDesSupport.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/wolf/TpmToWolfDesSupport.c new file mode 100644 index 0000000..ba36504 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/wolf/TpmToWolfDesSupport.c @@ -0,0 +1,96 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//** Introduction +// +// The functions in this file are used for initialization of the interface to the +// wolfcrypt library. + +//** Defines and Includes + +#include "Tpm.h" + +#if(defined SYM_LIB_WOLF) && ALG_TDES + +//**Functions +//** TDES_setup +// This function calls the wolfcrypt function to generate a TDES key schedule. If the +// If the key is two key (16 bytes), then the first DES key is replicated to the third +// key position. +int TDES_setup(const BYTE* key, UINT32 keyBits, tpmKeyScheduleTDES* skey, int dir) +{ + BYTE k[24]; + BYTE* kp; + + // If this is two-key, make it three key by replicating K1 + if(keyBits == 128) + { + memcpy(k, key, 16); + memcpy(&k[16], key, 8); + kp = k; + } + else + kp = (BYTE*)key; + + return wc_Des3_SetKey(skey, kp, 0, dir); +} + +//** TDES_setup_encrypt_key +// This function calls into TDES_setup(), specifically for an encryption key. +int TDES_setup_encrypt_key(const BYTE* key, UINT32 keyBits, tpmKeyScheduleTDES* skey) +{ + return TDES_setup(key, keyBits, skey, DES_ENCRYPTION); +} + +//** TDES_setup_decrypt_key +// This function calls into TDES_setup(), specifically for an decryption key. +int TDES_setup_decrypt_key(const BYTE* key, UINT32 keyBits, tpmKeyScheduleTDES* skey) +{ + return TDES_setup(key, keyBits, skey, DES_DECRYPTION); +} + +//*** TDES_encyrpt() +void TDES_encrypt(const BYTE* in, BYTE* out, tpmKeyScheduleTDES* ks) +{ + wc_Des3_EcbEncrypt(ks, out, in, DES_BLOCK_SIZE); +} + +//*** TDES_decrypt() +void TDES_decrypt(const BYTE* in, BYTE* out, tpmKeyScheduleTDES* ks) +{ + wc_Des3_EcbDecrypt(ks, out, in, DES_BLOCK_SIZE); +} + +#endif // MATH_LIB_WOLF && ALG_TDES diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/wolf/TpmToWolfMath.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/wolf/TpmToWolfMath.c new file mode 100644 index 0000000..beda61d --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/wolf/TpmToWolfMath.c @@ -0,0 +1,482 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//** Introduction +// +// This file contains the math functions that are not implemented in the BnMath +// library (yet). These math functions will call the wolfcrypt library to execute +// the operations. There is a difference between the internal format and the +// wolfcrypt format. To call the wolfcrypt function, a mp_int structure is created +// for each passed variable. We define USE_FAST_MATH wolfcrypt option, which allocates +// mp_int on the stack. We must copy each word to the new structure, and set the used +// size. +// +// Not using USE_FAST_MATH would allow for a simple pointer swap for the big integer +// buffer 'd', however wolfcrypt expects to manage this memory, and will swap out +// the pointer to and from temporary variables and free the reference underneath us. +// Using USE_FAST_MATH also instructs wolfcrypt to use the stack for all these +// intermediate variables + +//** Includes and Defines +#include "Tpm.h" + +#ifdef MATH_LIB_WOLF +# include "BnConvert_fp.h" +# include "TpmToWolfMath_fp.h" + +# define WOLF_HALF_RADIX (RADIX_BITS == 64 && !defined(FP_64BIT)) + +//** Functions + +//*** BnFromWolf() +// This function converts a wolfcrypt mp_int to a TPM bignum. In this implementation +// it is assumed that wolfcrypt used the same format for a big number as does the +// TPM -- an array of native-endian words in little-endian order. +void BnFromWolf(bigNum bn, mp_int* wolfBn) +{ + if(bn != NULL) + { + int i; +# if WOLF_HALF_RADIX + pAssert((unsigned)wolfBn->used <= 2 * BnGetAllocated(bn)); +# else + pAssert((unsigned)wolfBn->used <= BnGetAllocated(bn)); +# endif + for(i = 0; i < wolfBn->used; i++) + { +# if WOLF_HALF_RADIX + if(i & 1) + bn->d[i / 2] |= (crypt_uword_t)wolfBn->dp[i] << 32; + else + bn->d[i / 2] = wolfBn->dp[i]; +# else + bn->d[i] = wolfBn->dp[i]; +# endif + } + +# if WOLF_HALF_RADIX + BnSetTop(bn, (wolfBn->used + 1) / 2); +# else + BnSetTop(bn, wolfBn->used); +# endif + } +} + +//*** BnToWolf() +// This function converts a TPM bignum to a wolfcrypt mp_init, and has the same +// assumptions as made by BnFromWolf() +void BnToWolf(mp_int* toInit, bigConst initializer) +{ + uint32_t i; + if(toInit != NULL && initializer != NULL) + { + for(i = 0; i < initializer->size; i++) + { +# if WOLF_HALF_RADIX + toInit->dp[2 * i] = (fp_digit)initializer->d[i]; + toInit->dp[2 * i + 1] = (fp_digit)(initializer->d[i] >> 32); +# else + toInit->dp[i] = initializer->d[i]; +# endif + } + +# if WOLF_HALF_RADIX + toInit->used = (int)initializer->size * 2; + if(toInit->dp[toInit->used - 1] == 0 && toInit->dp[toInit->used - 2] != 0) + --toInit->used; +# else + toInit->used = (int)initializer->size; +# endif + toInit->sign = 0; + } +} + +//*** MpInitialize() +// This function initializes an wolfcrypt mp_int. +mp_int* MpInitialize(mp_int* toInit) +{ + mp_init(toInit); + return toInit; +} + +# if LIBRARY_COMPATIBILITY_CHECK +//** MathLibraryCompatibililtyCheck() +// This function is only used during development to make sure that the library +// that is being referenced is using the same size of data structures as the TPM. +BOOL MathLibraryCompatibilityCheck(void) +{ + BN_VAR(tpmTemp, 64 * 8); // allocate some space for a test value + crypt_uword_t i; + TPM2B_TYPE(TEST, 16); + TPM2B_TEST test = {{16, + {0x0F, + 0x0E, + 0x0D, + 0x0C, + 0x0B, + 0x0A, + 0x09, + 0x08, + 0x07, + 0x06, + 0x05, + 0x04, + 0x03, + 0x02, + 0x01, + 0x00}}}; + // Convert the test TPM2B to a bigNum + BnFrom2B(tpmTemp, &test.b); + MP_INITIALIZED(wolfTemp, tpmTemp); + (wolfTemp); // compiler warning + // Make sure the values are consistent + VERIFY(wolfTemp->used * sizeof(fp_digit) + == (int)tpmTemp->size * sizeof(crypt_uword_t)); + for(i = 0; i < tpmTemp->size; i++) + VERIFY(((crypt_uword_t*)wolfTemp->dp)[i] == tpmTemp->d[i]); + return 1; +Error: + return 0; +} +# endif + +//*** BnModMult() +// Does multiply and divide returning the remainder of the divide. +LIB_EXPORT BOOL BnModMult(bigNum result, bigConst op1, bigConst op2, bigConst modulus) +{ + WOLF_ENTER(); + BOOL OK; + MP_INITIALIZED(bnOp1, op1); + MP_INITIALIZED(bnOp2, op2); + MP_INITIALIZED(bnTemp, NULL); + BN_VAR(temp, LARGEST_NUMBER_BITS * 2); + + pAssert(BnGetAllocated(result) >= BnGetSize(modulus)); + + OK = (mp_mul(bnOp1, bnOp2, bnTemp) == MP_OKAY); + if(OK) + { + BnFromWolf(temp, bnTemp); + OK = BnDiv(NULL, result, temp, modulus); + } + + WOLF_LEAVE(); + return OK; +} + +//*** BnMult() +// Multiplies two numbers +LIB_EXPORT BOOL BnMult(bigNum result, bigConst multiplicand, bigConst multiplier) +{ + WOLF_ENTER(); + BOOL OK; + MP_INITIALIZED(bnTemp, NULL); + MP_INITIALIZED(bnA, multiplicand); + MP_INITIALIZED(bnB, multiplier); + + pAssert(result->allocated >= (BITS_TO_CRYPT_WORDS( + BnSizeInBits(multiplicand) + BnSizeInBits(multiplier)))); + + OK = (mp_mul(bnA, bnB, bnTemp) == MP_OKAY); + if(OK) + { + BnFromWolf(result, bnTemp); + } + + WOLF_LEAVE(); + return OK; +} + +//*** BnDiv() +// This function divides two bigNum values. The function returns FALSE if +// there is an error in the operation. +LIB_EXPORT BOOL BnDiv( + bigNum quotient, bigNum remainder, bigConst dividend, bigConst divisor) +{ + WOLF_ENTER(); + BOOL OK; + MP_INITIALIZED(bnQ, quotient); + MP_INITIALIZED(bnR, remainder); + MP_INITIALIZED(bnDend, dividend); + MP_INITIALIZED(bnSor, divisor); + pAssert(!BnEqualZero(divisor)); + if(BnGetSize(dividend) < BnGetSize(divisor)) + { + if(quotient) + BnSetWord(quotient, 0); + if(remainder) + BnCopy(remainder, dividend); + OK = TRUE; + } + else + { + pAssert( + (quotient == NULL) + || (quotient->allocated >= (unsigned)(dividend->size - divisor->size))); + pAssert((remainder == NULL) || (remainder->allocated >= divisor->size)); + OK = (mp_div(bnDend, bnSor, bnQ, bnR) == MP_OKAY); + if(OK) + { + BnFromWolf(quotient, bnQ); + BnFromWolf(remainder, bnR); + } + } + + WOLF_LEAVE(); + return OK; +} + +# if ALG_RSA +//*** BnGcd() +// Get the greatest common divisor of two numbers +LIB_EXPORT BOOL BnGcd(bigNum gcd, // OUT: the common divisor + bigConst number1, // IN: + bigConst number2 // IN: +) +{ + WOLF_ENTER(); + BOOL OK; + MP_INITIALIZED(bnGcd, gcd); + MP_INITIALIZED(bn1, number1); + MP_INITIALIZED(bn2, number2); + pAssert(gcd != NULL); + OK = (mp_gcd(bn1, bn2, bnGcd) == MP_OKAY); + if(OK) + { + BnFromWolf(gcd, bnGcd); + } + WOLF_LEAVE(); + return OK; +} + +//***BnModExp() +// Do modular exponentiation using bigNum values. The conversion from a mp_int to +// a bigNum is trivial as they are based on the same structure +LIB_EXPORT BOOL BnModExp(bigNum result, // OUT: the result + bigConst number, // IN: number to exponentiate + bigConst exponent, // IN: + bigConst modulus // IN: +) +{ + WOLF_ENTER(); + BOOL OK; + MP_INITIALIZED(bnResult, result); + MP_INITIALIZED(bnN, number); + MP_INITIALIZED(bnE, exponent); + MP_INITIALIZED(bnM, modulus); + OK = (mp_exptmod(bnN, bnE, bnM, bnResult) == MP_OKAY); + if(OK) + { + BnFromWolf(result, bnResult); + } + + WOLF_LEAVE(); + return OK; +} + +//*** BnModInverse() +// Modular multiplicative inverse +LIB_EXPORT BOOL BnModInverse(bigNum result, bigConst number, bigConst modulus) +{ + WOLF_ENTER(); + BOOL OK; + MP_INITIALIZED(bnResult, result); + MP_INITIALIZED(bnN, number); + MP_INITIALIZED(bnM, modulus); + + OK = (mp_invmod(bnN, bnM, bnResult) == MP_OKAY); + if(OK) + { + BnFromWolf(result, bnResult); + } + + WOLF_LEAVE(); + return OK; +} +# endif // TPM_ALG_RSA + +# if ALG_ECC + +//*** PointFromWolf() +// Function to copy the point result from a wolf ecc_point to a bigNum +void PointFromWolf(bigPoint pOut, // OUT: resulting point + ecc_point* pIn // IN: the point to return +) +{ + BnFromWolf(pOut->x, pIn->x); + BnFromWolf(pOut->y, pIn->y); + BnFromWolf(pOut->z, pIn->z); +} + +//*** PointToWolf() +// Function to copy the point result from a bigNum to a wolf ecc_point +void PointToWolf(ecc_point* pOut, // OUT: resulting point + pointConst pIn // IN: the point to return +) +{ + BnToWolf(pOut->x, pIn->x); + BnToWolf(pOut->y, pIn->y); + BnToWolf(pOut->z, pIn->z); +} + +//*** EcPointInitialized() +// Allocate and initialize a point. +static ecc_point* EcPointInitialized(pointConst initializer) +{ + ecc_point* P; + + P = wc_ecc_new_point(); + pAssert(P != NULL); + // mp_int x,y,z are stack allocated. + // initializer is not required + if(P != NULL && initializer != NULL) + { + PointToWolf(P, initializer); + } + + return P; +} + +//*** BnEccModMult() +// This function does a point multiply of the form R = [d]S +// return type: BOOL +// FALSE failure in operation; treat as result being point at infinity +LIB_EXPORT BOOL BnEccModMult(bigPoint R, // OUT: computed point + pointConst S, // IN: point to multiply by 'd' (optional) + bigConst d, // IN: scalar for [d]S + bigCurve E) +{ + WOLF_ENTER(); + BOOL OK; + MP_INITIALIZED(bnD, d); + MP_INITIALIZED(bnPrime, CurveGetPrime(E)); + POINT_CREATE(pS, NULL); + POINT_CREATE(pR, NULL); + + if(S == NULL) + S = CurveGetG(AccessCurveData(E)); + + PointToWolf(pS, S); + + OK = (wc_ecc_mulmod(bnD, pS, pR, NULL, bnPrime, 1) == MP_OKAY); + if(OK) + { + PointFromWolf(R, pR); + } + + POINT_DELETE(pR); + POINT_DELETE(pS); + + WOLF_LEAVE(); + return !BnEqualZero(R->z); +} + +//*** BnEccModMult2() +// This function does a point multiply of the form R = [d]G + [u]Q +// return type: BOOL +// FALSE failure in operation; treat as result being point at infinity +LIB_EXPORT BOOL BnEccModMult2(bigPoint R, // OUT: computed point + pointConst S, // IN: optional point + bigConst d, // IN: scalar for [d]S or [d]G + pointConst Q, // IN: second point + bigConst u, // IN: second scalar + bigCurve E // IN: curve +) +{ + WOLF_ENTER(); + BOOL OK; + POINT_CREATE(pR, NULL); + POINT_CREATE(pS, NULL); + POINT_CREATE(pQ, Q); + MP_INITIALIZED(bnD, d); + MP_INITIALIZED(bnU, u); + MP_INITIALIZED(bnPrime, CurveGetPrime(E)); + MP_INITIALIZED(bnA, CurveGet_a(E)); + + if(S == NULL) + S = CurveGetG(AccessCurveData(E)); + PointToWolf(pS, S); + + OK = (ecc_mul2add(pS, bnD, pQ, bnU, pR, bnA, bnPrime, NULL) == MP_OKAY); + if(OK) + { + PointFromWolf(R, pR); + } + + POINT_DELETE(pS); + POINT_DELETE(pQ); + POINT_DELETE(pR); + + WOLF_LEAVE(); + return !BnEqualZero(R->z); +} + +//** BnEccAdd() +// This function does addition of two points. +// return type: BOOL +// FALSE failure in operation; treat as result being point at infinity +LIB_EXPORT BOOL BnEccAdd(bigPoint R, // OUT: computed point + pointConst S, // IN: point to multiply by 'd' + pointConst Q, // IN: second point + bigCurve E // IN: curve +) +{ + WOLF_ENTER(); + BOOL OK; + mp_digit mp; + POINT_CREATE(pR, NULL); + POINT_CREATE(pS, S); + POINT_CREATE(pQ, Q); + MP_INITIALIZED(bnA, CurveGet_a(E)); + MP_INITIALIZED(bnMod, CurveGetPrime(E)); + // + OK = (mp_montgomery_setup(bnMod, &mp) == MP_OKAY); + OK = OK && (ecc_projective_add_point(pS, pQ, pR, bnA, bnMod, mp) == MP_OKAY); + if(OK) + { + PointFromWolf(R, pR); + } + + POINT_DELETE(pS); + POINT_DELETE(pQ); + POINT_DELETE(pR); + + WOLF_LEAVE(); + return !BnEqualZero(R->z); +} + +# endif // TPM_ALG_ECC + +#endif // MATH_LIB_WOLF \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/wolf/TpmToWolfSupport.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/wolf/TpmToWolfSupport.c new file mode 100644 index 0000000..4068a65 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/wolf/TpmToWolfSupport.c @@ -0,0 +1,57 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//** Introduction +// +// The functions in this file are used for initialization of the interface to the +// wolfSSL library. + +//** Defines and Includes + +#include "Tpm.h" + +#if defined(HASH_LIB_WOLF) || defined(MATH_LIB_WOLF) || defined(SYM_LIB_WOLF) + +//*** SupportLibInit() +// This does any initialization required by the support library. +LIB_EXPORT int SupportLibInit(void) +{ +# if LIBRARY_COMPATIBILITY_CHECK + MathLibraryCompatibilityCheck(); +# endif + return TRUE; +} + +#endif // HASH_LIB_WOLF || MATH_LIB_WOLF || SYM_LIB_WOLF diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/wolf/wolfssl.vcxproj b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/wolf/wolfssl.vcxproj new file mode 100644 index 0000000..afdb9e5 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/crypt/wolf/wolfssl.vcxproj @@ -0,0 +1,194 @@ + + + + + Coverage + Win32 + + + Coverage + x64 + + + WolfDebug + Win32 + + + WolfDebug + x64 + + + WolfRelease + Win32 + + + WolfRelease + x64 + + + + {73973223-5EE8-41CA-8E88-1D60E89A237B} + wolfssl + Win32Proj + 8.1 + $(SolutionDir)..\external\wolfssl\ + + + + StaticLibrary + v141 + Unicode + true + + + StaticLibrary + v141 + Unicode + true + + + StaticLibrary + v141 + Unicode + + + StaticLibrary + v141 + Unicode + + + StaticLibrary + v141 + Unicode + + + StaticLibrary + v141 + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + $(SolutionDir)\bin\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)\bin\$(ProjectName)\$(PlatformTarget)\$(Configuration)\ + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(WolfRootDir) + + + + WOLFSSL_SHA384;WOLFSSL_SHA512;WOLFSSL_KEY_GEN;WOLFSSL_LIB;WOLFSSL_USER_SETTINGS;CYASSL_USER_SETTINGS;%(PreprocessorDefinitions) + + + + + Disabled + true + EnableFastChecks + MultiThreadedDebugDLL + + Level4 + EditAndContinue + 4206;4214;4706;%(DisableSpecificWarnings) + $(SolutionDir)\tpm\include;$(SolutionDir)\tpm\include\wolf;%(AdditionalIncludeDirectories) + + + + + Disabled + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + EditAndContinue + 4206;4214;4706;%(DisableSpecificWarnings) + $(SolutionDir)\tpm\include;$(SolutionDir)\tpm\include\wolf;%(AdditionalIncludeDirectories) + + + + + Disabled + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + ProgramDatabase + 4206;4214;4706;%(DisableSpecificWarnings) + $(SolutionDir)\tpm\include;$(SolutionDir)\tpm\include\wolf;%(AdditionalIncludeDirectories) + + + + + Disabled + EnableFastChecks + MultiThreadedDebugDLL + + + Level4 + ProgramDatabase + 4206;4214;4706;%(DisableSpecificWarnings) + + + + + MaxSpeed + true + MultiThreadedDLL + true + + Level3 + ProgramDatabase + $(SolutionDir)\tpm\include;$(SolutionDir)\tpm\include\wolf;%(AdditionalIncludeDirectories) + + + + + MaxSpeed + true + MultiThreadedDLL + true + + + Level3 + ProgramDatabase + $(SolutionDir)\tpm\include;$(SolutionDir)\tpm\include\wolf;%(AdditionalIncludeDirectories) + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/events/_TPM_Hash_Data.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/events/_TPM_Hash_Data.c new file mode 100644 index 0000000..55e81aa --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/events/_TPM_Hash_Data.c @@ -0,0 +1,67 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" + +// This function is called to process a _TPM_Hash_Data indication. +LIB_EXPORT void _TPM_Hash_Data(uint32_t dataSize, // IN: size of data to be extend + unsigned char* data // IN: data buffer +) +{ + UINT32 i; + HASH_OBJECT* hashObject; + TPMI_DH_PCR pcrHandle = TPMIsStarted() ? PCR_FIRST + DRTM_PCR + : PCR_FIRST + HCRTM_PCR; + + // If there is no DRTM sequence object, then _TPM_Hash_Start + // was not called so this function returns without doing + // anything. + if(g_DRTMHandle == TPM_RH_UNASSIGNED) + return; + + hashObject = (HASH_OBJECT*)HandleToObject(g_DRTMHandle); + pAssert(hashObject->attributes.eventSeq); + + // For each of the implemented hash algorithms, update the digest with the + // data provided. + for(i = 0; i < HASH_COUNT; i++) + { + // make sure that the PCR is implemented for this algorithm + if(PcrIsAllocated(pcrHandle, hashObject->state.hashState[i].hashAlg)) + // Update sequence object + CryptDigestUpdate(&hashObject->state.hashState[i], dataSize, data); + } + + return; +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/events/_TPM_Hash_End.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/events/_TPM_Hash_End.c new file mode 100644 index 0000000..43c4e2c --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/events/_TPM_Hash_End.c @@ -0,0 +1,97 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" + +// This function is called to process a _TPM_Hash_End indication. +LIB_EXPORT void _TPM_Hash_End(void) +{ + UINT32 i; + TPM2B_DIGEST digest; + HASH_OBJECT* hashObject; + TPMI_DH_PCR pcrHandle; + + // If the DRTM handle is not being used, then either _TPM_Hash_Start has not + // been called, _TPM_Hash_End was previously called, or some other command + // was executed and the sequence was aborted. + if(g_DRTMHandle == TPM_RH_UNASSIGNED) + return; + + // Get DRTM sequence object + hashObject = (HASH_OBJECT*)HandleToObject(g_DRTMHandle); + + // Is this _TPM_Hash_End after Startup or before + if(TPMIsStarted()) + { + // After + + // Reset the DRTM PCR + PCRResetDynamics(); + + // Extend the DRTM_PCR. + pcrHandle = PCR_FIRST + DRTM_PCR; + + // DRTM sequence increments restartCount + gr.restartCount++; + } + else + { + pcrHandle = PCR_FIRST + HCRTM_PCR; + g_DrtmPreStartup = TRUE; + } + + // Complete hash and extend PCR, or if this is an HCRTM, complete + // the hash, reset the H-CRTM register (PCR[0]) to 0...04, and then + // extend the H-CRTM data + for(i = 0; i < HASH_COUNT; i++) + { + TPMI_ALG_HASH hash = CryptHashGetAlgByIndex(i); + // make sure that the PCR is implemented for this algorithm + if(PcrIsAllocated(pcrHandle, hashObject->state.hashState[i].hashAlg)) + { + // Complete hash + digest.t.size = CryptHashGetDigestSize(hash); + CryptHashEnd2B(&hashObject->state.hashState[i], &digest.b); + + PcrDrtm(pcrHandle, hash, &digest); + } + } + + // Flush sequence object. + FlushObject(g_DRTMHandle); + + g_DRTMHandle = TPM_RH_UNASSIGNED; + + return; +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/events/_TPM_Hash_Start.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/events/_TPM_Hash_Start.c new file mode 100644 index 0000000..1338611 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/events/_TPM_Hash_Start.c @@ -0,0 +1,89 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" + +// This function is called to process a _TPM_Hash_Start indication. +LIB_EXPORT void _TPM_Hash_Start(void) +{ + TPM_RC result; + TPMI_DH_OBJECT handle; + + // If a DRTM sequence object exists, free it up + if(g_DRTMHandle != TPM_RH_UNASSIGNED) + { + FlushObject(g_DRTMHandle); + g_DRTMHandle = TPM_RH_UNASSIGNED; + } + + // Create an event sequence object and store the handle in global + // g_DRTMHandle. A TPM_RC_OBJECT_MEMORY error may be returned at this point + // The NULL value for the first parameter will cause the sequence structure to + // be allocated without being set as present. This keeps the sequence from + // being left behind if the sequence is terminated early. + result = ObjectCreateEventSequence(NULL, &g_DRTMHandle); + + // If a free slot was not available, then free up a slot. + if(result != TPM_RC_SUCCESS) + { + // An implementation does not need to have a fixed relationship between + // slot numbers and handle numbers. To handle the general case, scan for + // a handle that is assigned and free it for the DRTM sequence. + // In the reference implementation, the relationship between handles and + // slots is fixed. So, if the call to ObjectCreateEvenSequence() + // failed indicating that all slots are occupied, then the first handle we + // are going to check (TRANSIENT_FIRST) will be occupied. It will be freed + // so that it can be assigned for use as the DRTM sequence object. + for(handle = TRANSIENT_FIRST; handle < TRANSIENT_LAST; handle++) + { + // try to flush the first object + if(IsObjectPresent(handle)) + break; + } + // If the first call to find a slot fails but none of the slots is occupied + // then there's a big problem + pAssert(handle < TRANSIENT_LAST); + + // Free the slot + FlushObject(handle); + + // Try to create an event sequence object again. This time, we must + // succeed. + result = ObjectCreateEventSequence(NULL, &g_DRTMHandle); + if(result != TPM_RC_SUCCESS) + FAIL(FATAL_ERROR_INTERNAL); + } + + return; +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/events/_TPM_Init.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/events/_TPM_Init.c new file mode 100644 index 0000000..ea862fa --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/events/_TPM_Init.c @@ -0,0 +1,90 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "Tpm.h" +#include "_TPM_Init_fp.h" + +// This function is used to process a _TPM_Init indication. +LIB_EXPORT void _TPM_Init(void) +{ + g_powerWasLost = g_powerWasLost | _plat__WasPowerLost(); + +#if SIMULATION && DEBUG + // If power was lost and this was a simulation, put canary in RAM used by NV + // so that uninitialized memory can be detected more easily + if(g_powerWasLost) + { + memset(&gc, 0xbb, sizeof(gc)); + memset(&gr, 0xbb, sizeof(gr)); + memset(&gp, 0xbb, sizeof(gp)); + memset(&go, 0xbb, sizeof(go)); + } +#endif + +#if SIMULATION + // Clear the flag that forces failure on self-test + g_forceFailureMode = FALSE; +#endif + + // Disable the tick processing + _plat__ACT_EnableTicks(FALSE); + + // Set initialization state + TPMInit(); + + // Set g_DRTMHandle as unassigned + g_DRTMHandle = TPM_RH_UNASSIGNED; + + // No H-CRTM, yet. + g_DrtmPreStartup = FALSE; + + // Initialize the NvEnvironment. + g_nvOk = NvPowerOn(); + + // Initialize cryptographic functions + g_inFailureMode = (g_nvOk == FALSE) || (CryptInit() == FALSE); + if(!g_inFailureMode) + { + // Load the persistent data + NvReadPersistent(); + + // Load the orderly data (clock and DRBG state). + // If this is not done here, things break + NvRead(&go, NV_ORDERLY_DATA, sizeof(go)); + + // Start clock. Need to do this after NV has been restored. + TimePowerOn(); + } + return; +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/main/CommandDispatcher.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/main/CommandDispatcher.c new file mode 100644 index 0000000..32d4f83 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/main/CommandDispatcher.c @@ -0,0 +1,457 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//* Includes and Typedefs +#include "Tpm.h" +#include "Marshal.h" + +#if TABLE_DRIVEN_DISPATCH || TABLE_DRIVEN_MARSHAL + +typedef TPM_RC(NoFlagFunction)(void* target, BYTE** buffer, INT32* size); +typedef TPM_RC(FlagFunction)(void* target, BYTE** buffer, INT32* size, BOOL flag); + +typedef FlagFunction* UNMARSHAL_t; + +typedef INT16(MarshalFunction)(void* source, BYTE** buffer, INT32* size); +typedef MarshalFunction* MARSHAL_t; + +typedef TPM_RC(COMMAND_NO_ARGS)(void); +typedef TPM_RC(COMMAND_IN_ARG)(void* in); +typedef TPM_RC(COMMAND_OUT_ARG)(void* out); +typedef TPM_RC(COMMAND_INOUT_ARG)(void* in, void* out); + +typedef union COMMAND_t +{ + COMMAND_NO_ARGS* noArgs; + COMMAND_IN_ARG* inArg; + COMMAND_OUT_ARG* outArg; + COMMAND_INOUT_ARG* inOutArg; +} COMMAND_t; + +// This structure is used by ParseHandleBuffer() and CommandDispatcher(). The +// parameters in this structure are unique for each command. The parameters are: +// command holds the address of the command processing function that is called +// by Command Dispatcher +// inSize This is the size of the command-dependent input structure. The +// input structure holds the unmarshaled handles and command +// parameters. If the command takes no arguments (handles or +// parameters) then inSize will have a value of 0. +// outSize This is the size of the command-dependent output structure. The +// output structure holds the results of the command in an unmarshaled +// form. When command processing is completed, these values are +// marshaled into the output buffer. It is always the case that the +// unmarshaled version of an output structure is larger then the +// marshaled version. This is because the marshaled version contains +// the exact same number of significant bytes but with padding removed. +// typesOffsets This parameter points to the list of data types that are to be +// marshaled or unmarshaled. The list of types follows the 'offsets' +// array. The offsets array is variable sized so the typesOffset filed +// is necessary for the handle and command processing to be able to +// find the types that are being handled. The 'offsets' array may be +// empty. The 'types' structure is described below. +// offsets This is an array of offsets of each of the parameters in the +// command or response. When processing the command parameters (not +// handles) the list contains the offset of the next parameter. For +// example, if the first command parameter has a size of 4 and there is +// a second command parameter, then the offset would be 4, indicating +// that the second parameter starts at 4. If the second parameter has +// a size of 8, and there is a third parameter, then the second entry +// in offsets is 12 (4 for the first parameter and 8 for the second). +// An offset value of 0 in the list indicates the start of the response +// parameter list. When CommandDispatcher hits this value, it will stop +// unmarshaling the parameters and call 'command'. If a command has no +// response parameters and only one command parameter, then offsets can +// be an empty list. + +typedef struct COMMAND_DESCRIPTOR_t +{ + COMMAND_t command; // Address of the command + UINT16 inSize; // Maximum size of the input structure + UINT16 outSize; // Maximum size of the output structure + UINT16 typesOffset; // address of the types field + UINT16 offsets[1]; +} COMMAND_DESCRIPTOR_t; + +// The 'types' list is an encoded byte array. The byte value has two parts. The most +// significant bit is used when a parameter takes a flag and indicates if the flag +// should be SET or not. The remaining 7 bits are an index into an array of +// addresses of marshaling and unmarshaling functions. +// The array of functions is divided into 6 sections with a value assigned +// to denote the start of that section (and the end of the previous section). The +// defined offset values for each section are: +// 0 unmarshaling for handles that do not take flags +// HANDLE_FIRST_FLAG_TYPE unmarshaling for handles that take flags +// PARAMETER_FIRST_TYPE unmarshaling for parameters that do not take flags +// PARAMETER_FIRST_FLAG_TYPE unmarshaling for parameters that take flags +// PARAMETER_LAST_TYPE + 1 marshaling for handles +// RESPONSE_PARAMETER_FIRST_TYPE marshaling for parameters +// RESPONSE_PARAMETER_LAST_TYPE is the last value in the list of marshaling and +// unmarshaling functions. +// +// The types list is constructed with a byte of 0xff at the end of the command +// parameters and with an 0xff at the end of the response parameters. + +# if COMPRESSED_LISTS +# define PAD_LIST 0 +# else +# define PAD_LIST 1 +# endif +# define _COMMAND_TABLE_DISPATCH_ +# include "CommandDispatchData.h" + +# define TEST_COMMAND TPM_CC_Startup + +# define NEW_CC + +#else + +# include "Commands.h" + +#endif + +//* Marshal/Unmarshal Functions + +//** ParseHandleBuffer() +// This is the table-driven version of the handle buffer unmarshaling code +TPM_RC +ParseHandleBuffer(COMMAND* command) +{ + TPM_RC result; +#if TABLE_DRIVEN_DISPATCH || TABLE_DRIVEN_MARSHAL + COMMAND_DESCRIPTOR_t* desc; + BYTE* types; + BYTE type; + BYTE dType; + + // Make sure that nothing strange has happened + pAssert( + command->index < sizeof(s_CommandDataArray) / sizeof(COMMAND_DESCRIPTOR_t*)); + // Get the address of the descriptor for this command + desc = s_CommandDataArray[command->index]; + + pAssert(desc != NULL); + // Get the associated list of unmarshaling data types. + types = &((BYTE*)desc)[desc->typesOffset]; + + // if(s_ccAttr[commandIndex].commandIndex == TEST_COMMAND) + // commandIndex = commandIndex; + // No handles yet + command->handleNum = 0; + + // Get the first type value + for(type = *types++; + // check each byte to make sure that we have not hit the start + // of the parameters + (dType = (type & 0x7F)) < PARAMETER_FIRST_TYPE; + // get the next type + type = *types++) + { +# if TABLE_DRIVEN_MARSHAL + marshalIndex_t index; + index = unmarshalArray[dType] | ((type & 0x80) ? NULL_FLAG : 0); + result = Unmarshal(index, + &(command->handles[command->handleNum]), + &command->parameterBuffer, + &command->parameterSize); + +# else + // See if unmarshaling of this handle type requires a flag + if(dType < HANDLE_FIRST_FLAG_TYPE) + { + // Look up the function to do the unmarshaling + NoFlagFunction* f = (NoFlagFunction*)unmarshalArray[dType]; + // call it + result = f(&(command->handles[command->handleNum]), + &command->parameterBuffer, + &command->parameterSize); + } + else + { + // Look up the function + FlagFunction* f = unmarshalArray[dType]; + + // Call it setting the flag to the appropriate value + result = f(&(command->handles[command->handleNum]), + &command->parameterBuffer, + &command->parameterSize, + (type & 0x80) != 0); + } +# endif + + // Got a handle + // We do this first so that the match for the handle offset of the + // response code works correctly. + command->handleNum += 1; + if(result != TPM_RC_SUCCESS) + // if the unmarshaling failed, return the response code with the + // handle indication set + return result + TPM_RC_H + (command->handleNum * TPM_RC_1); + } +#else + BYTE** handleBufferStart = &command->parameterBuffer; + INT32* bufferRemainingSize = &command->parameterSize; + TPM_HANDLE* handles = &command->handles[0]; + UINT32* handleCount = &command->handleNum; + *handleCount = 0; + switch(command->code) + { +# include "HandleProcess.h" +# undef handles + default: + FAIL(FATAL_ERROR_INTERNAL); + break; + } +#endif + return TPM_RC_SUCCESS; +} + +//** CommandDispatcher() +// Function to unmarshal the command parameters, call the selected action code, and +// marshal the response parameters. +TPM_RC +CommandDispatcher(COMMAND* command) +{ +#if !TABLE_DRIVEN_DISPATCH || TABLE_DRIVEN_MARSHAL + TPM_RC result; + BYTE** paramBuffer = &command->parameterBuffer; + INT32* paramBufferSize = &command->parameterSize; + BYTE** responseBuffer = &command->responseBuffer; + INT32* respParmSize = &command->parameterSize; + INT32 rSize; + TPM_HANDLE* handles = &command->handles[0]; + // + command->handleNum = 0; // The command-specific code knows how + // many handles there are. This is for + // cataloging the number of response + // handles + MemoryIoBufferAllocationReset(); // Initialize so that allocation will + // work properly + switch(GetCommandCode(command->index)) + { +# include "CommandDispatcher.h" + + default: + FAIL(FATAL_ERROR_INTERNAL); + break; + } +Exit: + MemoryIoBufferZero(); + return result; +#else + COMMAND_DESCRIPTOR_t* desc; + BYTE* types; + BYTE type; + UINT16* offsets; + UINT16 offset = 0; + UINT32 maxInSize; + BYTE* commandIn; + INT32 maxOutSize; + BYTE* commandOut; + COMMAND_t cmd; + TPM_HANDLE* handles; + UINT32 hasInParameters = 0; + BOOL hasOutParameters = FALSE; + UINT32 pNum = 0; + BYTE dType; // dispatch type + TPM_RC result; + // + // Get the address of the descriptor for this command + pAssert( + command->index < sizeof(s_CommandDataArray) / sizeof(COMMAND_DESCRIPTOR_t*)); + desc = s_CommandDataArray[command->index]; + + // Get the list of parameter types for this command + pAssert(desc != NULL); + types = &((BYTE*)desc)[desc->typesOffset]; + + // Get a pointer to the list of parameter offsets + offsets = &desc->offsets[0]; + // pointer to handles + handles = command->handles; + + // Get the size required to hold all the unmarshaled parameters for this command + maxInSize = desc->inSize; + // and the size of the output parameter structure returned by this command + maxOutSize = desc->outSize; + + MemoryIoBufferAllocationReset(); + // Get a buffer for the input parameters + commandIn = MemoryGetInBuffer(maxInSize); + // And the output parameters + commandOut = (BYTE*)MemoryGetOutBuffer((UINT32)maxOutSize); + + // Get the address of the action code dispatch + cmd = desc->command; + + // Copy any handles into the input buffer + for(type = *types++; (type & 0x7F) < PARAMETER_FIRST_TYPE; type = *types++) + { + // 'offset' was initialized to zero so the first unmarshaling will always + // be to the start of the data structure + *(TPM_HANDLE*)&(commandIn[offset]) = *handles++; + // This check is used so that we don't have to add an additional offset + // value to the offsets list to correspond to the stop value in the + // command parameter list. + if(*types != 0xFF) + offset = *offsets++; + // maxInSize -= sizeof(TPM_HANDLE); + hasInParameters++; + } + // Exit loop with type containing the last value read from types + // maxInSize has the amount of space remaining in the command action input + // buffer. Make sure that we don't have more data to unmarshal than is going to + // fit. + + // type contains the last value read from types so it is not necessary to + // reload it, which is good because *types now points to the next value + for(; (dType = (type & 0x7F)) <= PARAMETER_LAST_TYPE; type = *types++) + { + pNum++; +# if TABLE_DRIVEN_MARSHAL + { + marshalIndex_t index = unmarshalArray[dType]; + index |= (type & 0x80) ? NULL_FLAG : 0; + result = Unmarshal(index, + &commandIn[offset], + &command->parameterBuffer, + &command->parameterSize); + } +# else + if(dType < PARAMETER_FIRST_FLAG_TYPE) + { + NoFlagFunction* f = (NoFlagFunction*)unmarshalArray[dType]; + result = f(&commandIn[offset], + &command->parameterBuffer, + &command->parameterSize); + } + else + { + FlagFunction* f = unmarshalArray[dType]; + result = f(&commandIn[offset], + &command->parameterBuffer, + &command->parameterSize, + (type & 0x80) != 0); + } +# endif + if(result != TPM_RC_SUCCESS) + { + result += TPM_RC_P + (TPM_RC_1 * pNum); + goto Exit; + } + // This check is used so that we don't have to add an additional offset + // value to the offsets list to correspond to the stop value in the + // command parameter list. + if(*types != 0xFF) + offset = *offsets++; + hasInParameters++; + } + // Should have used all the bytes in the input + if(command->parameterSize != 0) + { + result = TPM_RC_SIZE; + goto Exit; + } + + // The command parameter unmarshaling stopped when it hit a value that was out + // of range for unmarshaling values and left *types pointing to the first + // marshaling type. If that type happens to be the STOP value, then there + // are no response parameters. So, set the flag to indicate if there are + // output parameters. + hasOutParameters = *types != 0xFF; + + // There are four cases for calling, with and without input parameters and with + // and without output parameters. + if(hasInParameters > 0) + { + if(hasOutParameters) + result = cmd.inOutArg(commandIn, commandOut); + else + result = cmd.inArg(commandIn); + } + else + { + if(hasOutParameters) + result = cmd.outArg(commandOut); + else + result = cmd.noArgs(); + } + if(result != TPM_RC_SUCCESS) + goto Exit; + + // Offset in the marshaled output structure + offset = 0; + + // Process the return handles, if any + command->handleNum = 0; + + // Could make this a loop to process output handles but there is only ever + // one handle in the outputs (for now). + type = *types++; + if((dType = (type & 0x7F)) < RESPONSE_PARAMETER_FIRST_TYPE) + { + // The out->handle value was referenced as TPM_HANDLE in the + // action code so it has to be properly aligned. + command->handles[command->handleNum++] = + *((TPM_HANDLE*)&(commandOut[offset])); + maxOutSize -= sizeof(UINT32); + type = *types++; + offset = *offsets++; + } + // Use the size of the command action output buffer as the maximum for the + // number of bytes that can get marshaled. Since the marshaling code has + // no pointers to data, all of the data being returned has to be in the + // command action output buffer. If we try to marshal more bytes than + // could fit into the output buffer, we need to fail. + for(; (dType = (type & 0x7F)) <= RESPONSE_PARAMETER_LAST_TYPE && !g_inFailureMode; + type = *types++) + { +# if TABLE_DRIVEN_MARSHAL + marshalIndex_t index = marshalArray[dType]; + command->parameterSize += Marshal( + index, &commandOut[offset], &command->responseBuffer, &maxOutSize); +# else + const MARSHAL_t f = marshalArray[dType]; + + command->parameterSize += + f(&commandOut[offset], &command->responseBuffer, &maxOutSize); +# endif + offset = *offsets++; + } + result = (maxOutSize < 0) ? TPM_RC_FAILURE : TPM_RC_SUCCESS; +Exit: + MemoryIoBufferZero(); + return result; +#endif +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/main/ExecCommand.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/main/ExecCommand.c new file mode 100644 index 0000000..8d0cdfc --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/main/ExecCommand.c @@ -0,0 +1,330 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// +// This file contains the entry function ExecuteCommand() which provides the main +// control flow for TPM command execution. + +//** Includes + +#include "Tpm.h" +#include "Marshal.h" +#include "ExecCommand_fp.h" + +// Uncomment this next #include if doing static command/response buffer sizing +// #include "CommandResponseSizes_fp.h" + +//** ExecuteCommand() +// +// The function performs the following steps. +// +// a) Parses the command header from input buffer. +// b) Calls ParseHandleBuffer() to parse the handle area of the command. +// c) Validates that each of the handles references a loaded entity. +// d) Calls ParseSessionBuffer () to: +// 1) unmarshal and parse the session area; +// 2) check the authorizations; and +// 3) when necessary, decrypt a parameter. +// e) Calls CommandDispatcher() to: +// 1) unmarshal the command parameters from the command buffer; +// 2) call the routine that performs the command actions; and +// 3) marshal the responses into the response buffer. +// f) If any error occurs in any of the steps above create the error response +// and return. +// g) Calls BuildResponseSession() to: +// 1) when necessary, encrypt a parameter +// 2) build the response authorization sessions +// 3) update the audit sessions and nonces +// h) Calls BuildResponseHeader() to complete the construction of the response. +// +// 'responseSize' is set by the caller to the maximum number of bytes available in +// the output buffer. ExecuteCommand will adjust the value and return the number +// of bytes placed in the buffer. +// +// 'response' is also set by the caller to indicate the buffer into which +// ExecuteCommand is to place the response. +// +// 'request' and 'response' may point to the same buffer +// +// Note: As of February, 2016, the failure processing has been moved to the +// platform-specific code. When the TPM code encounters an unrecoverable failure, it +// will SET g_inFailureMode and call _plat__Fail(). That function should not return +// but may call ExecuteCommand(). +// +LIB_EXPORT void ExecuteCommand( + uint32_t requestSize, // IN: command buffer size + unsigned char* request, // IN: command buffer + uint32_t* responseSize, // IN/OUT: response buffer size + unsigned char** response // IN/OUT: response buffer +) +{ + // Command local variables + UINT32 commandSize; + COMMAND command; + + // Response local variables + UINT32 maxResponse = *responseSize; + TPM_RC result; // return code for the command + +#if MAX_COMMAND_SIZE < 6 || MAX_COMMAND_SIZE > UINT_MAX - 1 \ + || MAX_COMMAND_SIZE > INT32_MAX - 1 +# error bad MAX_COMMAND_SIZE +#endif + // Protect the unmarshaling code from obscenely long requests. The + // preceding #error ensures that MAX_COMMAND_SIZE + 1 fits in both an INT32 + // (used by the unmarshaling code) and an unsigned int (the argument type + // of TpmFailureMode). + if(requestSize > MAX_COMMAND_SIZE) + { + requestSize = MAX_COMMAND_SIZE + 1; + } + + // This next function call is used in development to size the command and response + // buffers. The values printed are the sizes of the internal structures and + // not the sizes of the canonical forms of the command response structures. Also, + // the sizes do not include the tag, command.code, requestSize, or the authorization + // fields. + //CommandResponseSizes(); + // Set flags for NV access state. This should happen before any other + // operation that may require a NV write. Note, that this needs to be done + // even when in failure mode. Otherwise, g_updateNV would stay SET while in + // Failure mode and the NV would be written on each call. + g_updateNV = UT_NONE; + g_clearOrderly = FALSE; + if(g_inFailureMode) + { + // Do failure mode processing + TpmFailureMode(requestSize, request, responseSize, response); + return; + } + // Query platform to get the NV state. The result state is saved internally + // and will be reported by NvIsAvailable(). The reference code requires that + // accessibility of NV does not change during the execution of a command. + // Specifically, if NV is available when the command execution starts and then + // is not available later when it is necessary to write to NV, then the TPM + // will go into failure mode. + NvCheckState(); + + // Due to the limitations of the simulation, TPM clock must be explicitly + // synchronized with the system clock whenever a command is received. + // This function call is not necessary in a hardware TPM. However, taking + // a snapshot of the hardware timer at the beginning of the command allows + // the time value to be consistent for the duration of the command execution. + TimeUpdateToCurrent(); + + // Any command through this function will unceremoniously end the + // _TPM_Hash_Data/_TPM_Hash_End sequence. + if(g_DRTMHandle != TPM_RH_UNASSIGNED) + ObjectTerminateEvent(); + + // Get command buffer size and command buffer. + command.parameterBuffer = request; + command.parameterSize = requestSize; + + // Parse command header: tag, commandSize and command.code. + // First parse the tag. The unmarshaling routine will validate + // that it is either TPM_ST_SESSIONS or TPM_ST_NO_SESSIONS. + result = TPMI_ST_COMMAND_TAG_Unmarshal( + &command.tag, &command.parameterBuffer, &command.parameterSize); + if(result != TPM_RC_SUCCESS) + goto Cleanup; + // Unmarshal the commandSize indicator. + result = UINT32_Unmarshal( + &commandSize, &command.parameterBuffer, &command.parameterSize); + if(result != TPM_RC_SUCCESS) + goto Cleanup; + // On a TPM that receives bytes on a port, the number of bytes that were + // received on that port is requestSize it must be identical to commandSize. + // In addition, commandSize must not be larger than MAX_COMMAND_SIZE allowed + // by the implementation. The check against MAX_COMMAND_SIZE may be redundant + // as the input processing (the function that receives the command bytes and + // places them in the input buffer) would likely have the input truncated when + // it reaches MAX_COMMAND_SIZE, and requestSize would not equal commandSize. + if(commandSize != requestSize || commandSize > MAX_COMMAND_SIZE) + { + result = TPM_RC_COMMAND_SIZE; + goto Cleanup; + } + // Unmarshal the command code. + result = TPM_CC_Unmarshal( + &command.code, &command.parameterBuffer, &command.parameterSize); + if(result != TPM_RC_SUCCESS) + goto Cleanup; + // Check to see if the command is implemented. + command.index = CommandCodeToCommandIndex(command.code); + if(UNIMPLEMENTED_COMMAND_INDEX == command.index) + { + result = TPM_RC_COMMAND_CODE; + goto Cleanup; + } +#if FIELD_UPGRADE_IMPLEMENTED == YES + // If the TPM is in FUM, then the only allowed command is + // TPM_CC_FieldUpgradeData. + if(IsFieldUgradeMode() && (command.code != TPM_CC_FieldUpgradeData)) + { + result = TPM_RC_UPGRADE; + goto Cleanup; + } + else +#endif + // Excepting FUM, the TPM only accepts TPM2_Startup() after + // _TPM_Init. After getting a TPM2_Startup(), TPM2_Startup() + // is no longer allowed. + if((!TPMIsStarted() && command.code != TPM_CC_Startup) + || (TPMIsStarted() && command.code == TPM_CC_Startup)) + { + result = TPM_RC_INITIALIZE; + goto Cleanup; + } + // Start regular command process. + NvIndexCacheInit(); + // Parse Handle buffer. + result = ParseHandleBuffer(&command); + if(result != TPM_RC_SUCCESS) + goto Cleanup; + // All handles in the handle area are required to reference TPM-resident + // entities. + result = EntityGetLoadStatus(&command); + if(result != TPM_RC_SUCCESS) + goto Cleanup; + // Authorization session handling for the command. + ClearCpRpHashes(&command); + if(command.tag == TPM_ST_SESSIONS) + { + // Find out session buffer size. + result = UINT32_Unmarshal((UINT32*)&command.authSize, + &command.parameterBuffer, + &command.parameterSize); + if(result != TPM_RC_SUCCESS) + goto Cleanup; + // Perform sanity check on the unmarshaled value. If it is smaller than + // the smallest possible session or larger than the remaining size of + // the command, then it is an error. NOTE: This check could pass but the + // session size could still be wrong. That will be determined after the + // sessions are unmarshaled. + if(command.authSize < 9 || command.authSize > command.parameterSize) + { + result = TPM_RC_SIZE; + goto Cleanup; + } + command.parameterSize -= command.authSize; + + // The actions of ParseSessionBuffer() are described in the introduction. + // As the sessions are parsed command.parameterBuffer is advanced so, on a + // successful return, command.parameterBuffer should be pointing at the + // first byte of the parameters. + result = ParseSessionBuffer(&command); + if(result != TPM_RC_SUCCESS) + goto Cleanup; + } + else + { + command.authSize = 0; + // The command has no authorization sessions. + // If the command requires authorizations, then CheckAuthNoSession() will + // return an error. + result = CheckAuthNoSession(&command); + if(result != TPM_RC_SUCCESS) + goto Cleanup; + } + // Set up the response buffer pointers. CommandDispatch will marshal the + // response parameters starting at the address in command.responseBuffer. + //*response = MemoryGetResponseBuffer(command.index); + // leave space for the command header + command.responseBuffer = *response + STD_RESPONSE_HEADER; + + // leave space for the parameter size field if needed + if(command.tag == TPM_ST_SESSIONS) + command.responseBuffer += sizeof(UINT32); + if(IsHandleInResponse(command.index)) + command.responseBuffer += sizeof(TPM_HANDLE); + + // CommandDispatcher returns a response handle buffer and a response parameter + // buffer if it succeeds. It will also set the parameterSize field in the + // buffer if the tag is TPM_RC_SESSIONS. + result = CommandDispatcher(&command); + if(result != TPM_RC_SUCCESS) + goto Cleanup; + + // Build the session area at the end of the parameter area. + result = BuildResponseSession(&command); + if(result != TPM_RC_SUCCESS) + { + goto Cleanup; + } + +Cleanup: + if(g_clearOrderly == TRUE && NV_IS_ORDERLY) + { +#if USE_DA_USED + gp.orderlyState = g_daUsed ? SU_DA_USED_VALUE : SU_NONE_VALUE; +#else + gp.orderlyState = SU_NONE_VALUE; +#endif + NV_SYNC_PERSISTENT(orderlyState); + } + // This implementation loads an "evict" object to a transient object slot in + // RAM whenever an "evict" object handle is used in a command so that the + // access to any object is the same. These temporary objects need to be + // cleared from RAM whether the command succeeds or fails. + ObjectCleanupEvict(); + + // The parameters and sessions have been marshaled. Now tack on the header and + // set the sizes + BuildResponseHeader(&command, *response, result); + + // Try to commit all the writes to NV if any NV write happened during this + // command execution. This check should be made for both succeeded and failed + // commands, because a failed one may trigger a NV write in DA logic as well. + // This is the only place in the command execution path that may call the NV + // commit. If the NV commit fails, the TPM should be put in failure mode. + if((g_updateNV != UT_NONE) && !g_inFailureMode) + { + if(g_updateNV == UT_ORDERLY) + NvUpdateIndexOrderlyData(); + if(!NvCommit()) + FAIL(FATAL_ERROR_INTERNAL); + g_updateNV = UT_NONE; + } + pAssert((UINT32)command.parameterSize <= maxResponse); + + // Clear unused bits in response buffer. + MemorySet(*response + *responseSize, 0, maxResponse - *responseSize); + + // as a final act, and not before, update the response size. + *responseSize = (UINT32)command.parameterSize; + + return; +} diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/main/SessionProcess.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/main/SessionProcess.c new file mode 100644 index 0000000..dfaf476 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/main/SessionProcess.c @@ -0,0 +1,2149 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// This file contains the subsystem that process the authorization sessions +// including implementation of the Dictionary Attack logic. ExecCommand() uses +// ParseSessionBuffer() to process the authorization session area of a command and +// BuildResponseSession() to create the authorization session area of a response. + +//** Includes and Data Definitions + +#define SESSION_PROCESS_C + +#include "Tpm.h" +#include "ACT.h" +#include "Marshal.h" + +// +//** Authorization Support Functions +// + +//*** IsDAExempted() +// This function indicates if a handle is exempted from DA logic. +// A handle is exempted if it is: +// a) a primary seed handle; +// b) an object with noDA bit SET; +// c) an NV Index with TPMA_NV_NO_DA bit SET; or +// d) a PCR handle. +// +// Return Type: BOOL +// TRUE(1) handle is exempted from DA logic +// FALSE(0) handle is not exempted from DA logic +BOOL IsDAExempted(TPM_HANDLE handle // IN: entity handle +) +{ + BOOL result = FALSE; + // + switch(HandleGetType(handle)) + { + case TPM_HT_PERMANENT: + // All permanent handles, other than TPM_RH_LOCKOUT, are exempt from + // DA protection. + result = (handle != TPM_RH_LOCKOUT); + break; + // When this function is called, a persistent object will have been loaded + // into an object slot and assigned a transient handle. + case TPM_HT_TRANSIENT: + { + TPMA_OBJECT attributes = ObjectGetPublicAttributes(handle); + result = IS_ATTRIBUTE(attributes, TPMA_OBJECT, noDA); + break; + } + case TPM_HT_NV_INDEX: + { + NV_INDEX* nvIndex = NvGetIndexInfo(handle, NULL); + result = IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, NO_DA); + break; + } + case TPM_HT_PCR: + // PCRs are always exempted from DA. + result = TRUE; + break; + default: + break; + } + return result; +} + +//*** IncrementLockout() +// This function is called after an authorization failure that involves use of +// an authValue. If the entity referenced by the handle is not exempt from DA +// protection, then the failedTries counter will be incremented. +// +// Return Type: TPM_RC +// TPM_RC_AUTH_FAIL authorization failure that caused DA lockout to increment +// TPM_RC_BAD_AUTH authorization failure did not cause DA lockout to +// increment +static TPM_RC IncrementLockout(UINT32 sessionIndex) +{ + TPM_HANDLE handle = s_associatedHandles[sessionIndex]; + TPM_HANDLE sessionHandle = s_sessionHandles[sessionIndex]; + SESSION* session = NULL; + // + // Don't increment lockout unless the handle associated with the session + // is DA protected or the session is bound to a DA protected entity. + if(sessionHandle == TPM_RS_PW) + { + if(IsDAExempted(handle)) + return TPM_RC_BAD_AUTH; + } + else + { + session = SessionGet(sessionHandle); + // If the session is bound to lockout, then use that as the relevant + // handle. This means that an authorization failure with a bound session + // bound to lockoutAuth will take precedence over any other + // lockout check + if(session->attributes.isLockoutBound == SET) + handle = TPM_RH_LOCKOUT; + if(session->attributes.isDaBound == CLEAR + && (IsDAExempted(handle) || session->attributes.includeAuth == CLEAR)) + // If the handle was changed to TPM_RH_LOCKOUT, this will not return + // TPM_RC_BAD_AUTH + return TPM_RC_BAD_AUTH; + } + if(handle == TPM_RH_LOCKOUT) + { + pAssert(gp.lockOutAuthEnabled == TRUE); + + // lockout is no longer enabled + gp.lockOutAuthEnabled = FALSE; + + // For TPM_RH_LOCKOUT, if lockoutRecovery is 0, no need to update NV since + // the lockout authorization will be reset at startup. + if(gp.lockoutRecovery != 0) + { + if(NV_IS_AVAILABLE) + // Update NV. + NV_SYNC_PERSISTENT(lockOutAuthEnabled); + else + // No NV access for now. Put the TPM in pending mode. + s_DAPendingOnNV = TRUE; + } + } + else + { + if(gp.recoveryTime != 0) + { + gp.failedTries++; + if(NV_IS_AVAILABLE) + // Record changes to NV. NvWrite will SET g_updateNV + NV_SYNC_PERSISTENT(failedTries); + else + // No NV access for now. Put the TPM in pending mode. + s_DAPendingOnNV = TRUE; + } + } + // Register a DA failure and reset the timers. + DARegisterFailure(handle); + + return TPM_RC_AUTH_FAIL; +} + +//*** IsSessionBindEntity() +// This function indicates if the entity associated with the handle is the entity, +// to which this session is bound. The binding would occur by making the "bind" +// parameter in TPM2_StartAuthSession() not equal to TPM_RH_NULL. The binding only +// occurs if the session is an HMAC session. The bind value is a combination of +// the Name and the authValue of the entity. +// +// Return Type: BOOL +// TRUE(1) handle points to the session start entity +// FALSE(0) handle does not point to the session start entity +static BOOL IsSessionBindEntity( + TPM_HANDLE associatedHandle, // IN: handle to be authorized + SESSION* session // IN: associated session +) +{ + TPM2B_NAME entity; // The bind value for the entity + // + // If the session is not bound, return FALSE. + if(session->attributes.isBound) + { + // Compute the bind value for the entity. + SessionComputeBoundEntity(associatedHandle, &entity); + + // Compare to the bind value in the session. + return MemoryEqual2B(&entity.b, &session->u1.boundEntity.b); + } + return FALSE; +} + +//*** IsPolicySessionRequired() +// Checks if a policy session is required for a command. If a command requires +// DUP or ADMIN role authorization, then the handle that requires that role is the +// first handle in the command. This simplifies this checking. If a new command +// is created that requires multiple ADMIN role authorizations, then it will +// have to be special-cased in this function. +// A policy session is required if: +// a) the command requires the DUP role; +// b) the command requires the ADMIN role and the authorized entity +// is an object and its adminWithPolicy bit is SET; +// c) the command requires the ADMIN role and the authorized entity +// is a permanent handle or an NV Index; or +// d) the authorized entity is a PCR belonging to a policy group, and +// has its policy initialized +// Return Type: BOOL +// TRUE(1) policy session is required +// FALSE(0) policy session is not required +static BOOL IsPolicySessionRequired(COMMAND_INDEX commandIndex, // IN: command index + UINT32 sessionIndex // IN: session index +) +{ + AUTH_ROLE role = CommandAuthRole(commandIndex, sessionIndex); + TPM_HT type = HandleGetType(s_associatedHandles[sessionIndex]); + // + if(role == AUTH_DUP) + return TRUE; + if(role == AUTH_ADMIN) + { + // We allow an exception for ADMIN role in a transient object. If the object + // allows ADMIN role actions with authorization, then policy is not + // required. For all other cases, there is no way to override the command + // requirement that a policy be used + if(type == TPM_HT_TRANSIENT) + { + OBJECT* object = HandleToObject(s_associatedHandles[sessionIndex]); + + if(!IS_ATTRIBUTE( + object->publicArea.objectAttributes, TPMA_OBJECT, adminWithPolicy)) + return FALSE; + } + return TRUE; + } + + if(type == TPM_HT_PCR) + { + if(PCRPolicyIsAvailable(s_associatedHandles[sessionIndex])) + { + TPM2B_DIGEST policy; + TPMI_ALG_HASH policyAlg; + policyAlg = PCRGetAuthPolicy(s_associatedHandles[sessionIndex], &policy); + if(policyAlg != TPM_ALG_NULL) + return TRUE; + } + } + return FALSE; +} + +//*** IsAuthValueAvailable() +// This function indicates if authValue is available and allowed for USER role +// authorization of an entity. +// +// This function is similar to IsAuthPolicyAvailable() except that it does not +// check the size of the authValue as IsAuthPolicyAvailable() does (a null +// authValue is a valid authorization, but a null policy is not a valid policy). +// +// This function does not check that the handle reference is valid or if the entity +// is in an enabled hierarchy. Those checks are assumed to have been performed +// during the handle unmarshaling. +// +// Return Type: BOOL +// TRUE(1) authValue is available +// FALSE(0) authValue is not available +static BOOL IsAuthValueAvailable(TPM_HANDLE handle, // IN: handle of entity + COMMAND_INDEX commandIndex, // IN: command index + UINT32 sessionIndex // IN: session index +) +{ + BOOL result = FALSE; + // + switch(HandleGetType(handle)) + { + case TPM_HT_PERMANENT: + switch(handle) + { + // At this point hierarchy availability has already been + // checked so primary seed handles are always available here + case TPM_RH_OWNER: + case TPM_RH_ENDORSEMENT: + case TPM_RH_PLATFORM: +#ifdef VENDOR_PERMANENT + // This vendor defined handle associated with the + // manufacturer's shared secret + case VENDOR_PERMANENT: +#endif + // The DA checking has been performed on LockoutAuth but we + // bypass the DA logic if we are using lockout policy. The + // policy would allow execution to continue an lockoutAuth + // could be used, even if direct use of lockoutAuth is disabled + case TPM_RH_LOCKOUT: + // NullAuth is always available. + case TPM_RH_NULL: + result = TRUE; + break; + FOR_EACH_ACT(CASE_ACT_HANDLE) + { + // The ACT auth value is not available if the platform is disabled + result = g_phEnable == SET; + break; + } + default: + // Otherwise authValue is not available. + break; + } + break; + case TPM_HT_TRANSIENT: + // A persistent object has already been loaded and the internal + // handle changed. + { + OBJECT* object; + TPMA_OBJECT attributes; + // + object = HandleToObject(handle); + attributes = object->publicArea.objectAttributes; + + // authValue is always available for a sequence object. + // An alternative for this is to + // SET_ATTRIBUTE(object->publicArea, TPMA_OBJECT, userWithAuth) when the + // sequence is started. + if(ObjectIsSequence(object)) + { + result = TRUE; + break; + } + // authValue is available for an object if it has its sensitive + // portion loaded and + // a) userWithAuth bit is SET, or + // b) ADMIN role is required + if(object->attributes.publicOnly == CLEAR + && (IS_ATTRIBUTE(attributes, TPMA_OBJECT, userWithAuth) + || (CommandAuthRole(commandIndex, sessionIndex) == AUTH_ADMIN + && !IS_ATTRIBUTE( + attributes, TPMA_OBJECT, adminWithPolicy)))) + result = TRUE; + } + break; + case TPM_HT_NV_INDEX: + // NV Index. + { + NV_REF locator; + NV_INDEX* nvIndex = NvGetIndexInfo(handle, &locator); + TPMA_NV nvAttributes; + // + pAssert(nvIndex != 0); + + nvAttributes = nvIndex->publicArea.attributes; + + if(IsWriteOperation(commandIndex)) + { + // AuthWrite can't be set for a PIN index + if(IS_ATTRIBUTE(nvAttributes, TPMA_NV, AUTHWRITE)) + result = TRUE; + } + else + { + // A "read" operation + // For a PIN Index, the authValue is available as long as the + // Index has been written and the pinCount is less than pinLimit + if(IsNvPinFailIndex(nvAttributes) + || IsNvPinPassIndex(nvAttributes)) + { + NV_PIN pin; + if(!IS_ATTRIBUTE(nvAttributes, TPMA_NV, WRITTEN)) + break; // return false + // get the index values + pin.intVal = NvGetUINT64Data(nvIndex, locator); + if(pin.pin.pinCount < pin.pin.pinLimit) + result = TRUE; + } + // For non-PIN Indexes, need to allow use of the authValue + else if(IS_ATTRIBUTE(nvAttributes, TPMA_NV, AUTHREAD)) + result = TRUE; + } + } + break; + case TPM_HT_PCR: + // PCR handle. + // authValue is always allowed for PCR + result = TRUE; + break; + default: + // Otherwise, authValue is not available + break; + } + return result; +} + +//*** IsAuthPolicyAvailable() +// This function indicates if an authPolicy is available and allowed. +// +// This function does not check that the handle reference is valid or if the entity +// is in an enabled hierarchy. Those checks are assumed to have been performed +// during the handle unmarshaling. +// +// Return Type: BOOL +// TRUE(1) authPolicy is available +// FALSE(0) authPolicy is not available +static BOOL IsAuthPolicyAvailable(TPM_HANDLE handle, // IN: handle of entity + COMMAND_INDEX commandIndex, // IN: command index + UINT32 sessionIndex // IN: session index +) +{ + BOOL result = FALSE; + // + switch(HandleGetType(handle)) + { + case TPM_HT_PERMANENT: + switch(handle) + { + // At this point hierarchy availability has already been checked. + case TPM_RH_OWNER: + if(gp.ownerPolicy.t.size != 0) + result = TRUE; + break; + case TPM_RH_ENDORSEMENT: + if(gp.endorsementPolicy.t.size != 0) + result = TRUE; + break; + case TPM_RH_PLATFORM: + if(gc.platformPolicy.t.size != 0) + result = TRUE; + break; +#define ACT_GET_POLICY(N) \ + case TPM_RH_ACT_##N: \ + if(go.ACT_##N.authPolicy.t.size != 0) \ + result = TRUE; \ + break; + + FOR_EACH_ACT(ACT_GET_POLICY) + + case TPM_RH_LOCKOUT: + if(gp.lockoutPolicy.t.size != 0) + result = TRUE; + break; + default: + break; + } + break; + case TPM_HT_TRANSIENT: + { + // Object handle. + // An evict object would already have been loaded and given a + // transient object handle by this point. + OBJECT* object = HandleToObject(handle); + // Policy authorization is not available for an object with only + // public portion loaded. + if(object->attributes.publicOnly == CLEAR) + { + // Policy authorization is always available for an object but + // is never available for a sequence. + if(!ObjectIsSequence(object)) + result = TRUE; + } + break; + } + case TPM_HT_NV_INDEX: + // An NV Index. + { + NV_INDEX* nvIndex = NvGetIndexInfo(handle, NULL); + TPMA_NV nvAttributes = nvIndex->publicArea.attributes; + // + // If the policy size is not zero, check if policy can be used. + if(nvIndex->publicArea.authPolicy.t.size != 0) + { + // If policy session is required for this handle, always + // uses policy regardless of the attributes bit setting + if(IsPolicySessionRequired(commandIndex, sessionIndex)) + result = TRUE; + // Otherwise, the presence of the policy depends on the NV + // attributes. + else if(IsWriteOperation(commandIndex)) + { + if(IS_ATTRIBUTE(nvAttributes, TPMA_NV, POLICYWRITE)) + result = TRUE; + } + else + { + if(IS_ATTRIBUTE(nvAttributes, TPMA_NV, POLICYREAD)) + result = TRUE; + } + } + } + break; + case TPM_HT_PCR: + // PCR handle. + if(PCRPolicyIsAvailable(handle)) + result = TRUE; + break; + default: + break; + } + return result; +} + +//** Session Parsing Functions + +//*** ClearCpRpHashes() +void ClearCpRpHashes(COMMAND* command) +{ + // The macros expand according to the implemented hash algorithms. An IDE may + // complain that COMMAND does not contain SHA1CpHash or SHA1RpHash because of the + // complexity of the macro expansion where the data space is defined; but, if SHA1 + // is implemented, it actually does and the compiler is happy. +#define CLEAR_CP_HASH(HASH, Hash) command->Hash##CpHash.b.size = 0; + FOR_EACH_HASH(CLEAR_CP_HASH) +#define CLEAR_RP_HASH(HASH, Hash) command->Hash##RpHash.b.size = 0; + FOR_EACH_HASH(CLEAR_RP_HASH) +} + +//*** GetCpHashPointer() +// Function to get a pointer to the cpHash of the command +static TPM2B_DIGEST* GetCpHashPointer(COMMAND* command, TPMI_ALG_HASH hashAlg) +{ + TPM2B_DIGEST* retVal; +// +// Define the macro that will expand for each implemented algorithm in the switch +// statement below. +#define GET_CP_HASH_POINTER(HASH, Hash) \ + case ALG_##HASH##_VALUE: \ + retVal = (TPM2B_DIGEST*)&command->Hash##CpHash; \ + break; + + switch(hashAlg) + { + // For each implemented hash, this will expand as defined above + // by GET_CP_HASH_POINTER. Your IDE may complain that + // 'struct "COMMAND" has no field "SHA1CpHash"' but the compiler says + // it does, so... + FOR_EACH_HASH(GET_CP_HASH_POINTER) + default: + retVal = NULL; + break; + } + return retVal; +} + +//*** GetRpHashPointer() +// Function to get a pointer to the RpHash of the command +static TPM2B_DIGEST* GetRpHashPointer(COMMAND* command, TPMI_ALG_HASH hashAlg) +{ + TPM2B_DIGEST* retVal; +// +// Define the macro that will expand for each implemented algorithm in the switch +// statement below. +#define GET_RP_HASH_POINTER(HASH, Hash) \ + case ALG_##HASH##_VALUE: \ + retVal = (TPM2B_DIGEST*)&command->Hash##RpHash; \ + break; + + switch(hashAlg) + { + // For each implemented hash, this will expand as defined above + // by GET_RP_HASH_POINTER. Your IDE may complain that + // 'struct "COMMAND" has no field 'SHA1RpHash'" but the compiler says + // it does, so... + FOR_EACH_HASH(GET_RP_HASH_POINTER) + default: + retVal = NULL; + break; + } + return retVal; +} + +//*** ComputeCpHash() +// This function computes the cpHash as defined in Part 2 and described in Part 1. +static TPM2B_DIGEST* ComputeCpHash(COMMAND* command, // IN: command parsing structure + TPMI_ALG_HASH hashAlg // IN: hash algorithm +) +{ + UINT32 i; + HASH_STATE hashState; + TPM2B_NAME name; + TPM2B_DIGEST* cpHash; + // + // cpHash = hash(commandCode [ || authName1 + // [ || authName2 + // [ || authName 3 ]]] + // [ || parameters]) + // A cpHash can contain just a commandCode only if the lone session is + // an audit session. + // Get pointer to the hash value + cpHash = GetCpHashPointer(command, hashAlg); + if(cpHash->t.size == 0) + { + cpHash->t.size = CryptHashStart(&hashState, hashAlg); + // Add commandCode. + CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), command->code); + // Add authNames for each of the handles. + for(i = 0; i < command->handleNum; i++) + CryptDigestUpdate2B(&hashState, + &EntityGetName(command->handles[i], &name)->b); + // Add the parameters. + CryptDigestUpdate( + &hashState, command->parameterSize, command->parameterBuffer); + // Complete the hash. + CryptHashEnd2B(&hashState, &cpHash->b); + } + return cpHash; +} + +//*** GetCpHash() +// This function is used to access a precomputed cpHash. +static TPM2B_DIGEST* GetCpHash(COMMAND* command, TPMI_ALG_HASH hashAlg) +{ + TPM2B_DIGEST* cpHash = GetCpHashPointer(command, hashAlg); + // + pAssert(cpHash->t.size != 0); + return cpHash; +} + +//*** CompareTemplateHash() +// This function computes the template hash and compares it to the session +// templateHash. It is the hash of the second parameter +// assuming that the command is TPM2_Create(), TPM2_CreatePrimary(), or +// TPM2_CreateLoaded() +// Return Type: BOOL +// TRUE(1) template hash equal to session->templateHash +// FALSE(0) template hash not equal to session->templateHash +static BOOL CompareTemplateHash(COMMAND* command, // IN: parsing structure + SESSION* session // IN: session data +) +{ + BYTE* pBuffer = command->parameterBuffer; + INT32 pSize = command->parameterSize; + TPM2B_DIGEST tHash; + UINT16 size; + // + // Only try this for the three commands for which it is intended + if(command->code != TPM_CC_Create && command->code != TPM_CC_CreatePrimary +#if CC_CreateLoaded + && command->code != TPM_CC_CreateLoaded +#endif + ) + return FALSE; + // Assume that the first parameter is a TPM2B and unmarshal the size field + // Note: this will not affect the parameter buffer and size in the calling + // function. + if(UINT16_Unmarshal(&size, &pBuffer, &pSize) != TPM_RC_SUCCESS) + return FALSE; + // reduce the space in the buffer. + // NOTE: this could make pSize go negative if the parameters are not correct but + // the unmarshaling code does not try to unmarshal if the remaining size is + // negative. + pSize -= size; + + // Advance the pointer + pBuffer += size; + + // Get the size of what should be the template + if(UINT16_Unmarshal(&size, &pBuffer, &pSize) != TPM_RC_SUCCESS) + return FALSE; + // See if this is reasonable + if(size > pSize) + return FALSE; + // Hash the template data + tHash.t.size = CryptHashBlock( + session->authHashAlg, size, pBuffer, sizeof(tHash.t.buffer), tHash.t.buffer); + return (MemoryEqual2B(&session->u1.templateHash.b, &tHash.b)); +} + +//*** CompareNameHash() +// This function computes the name hash and compares it to the nameHash in the +// session data. +BOOL CompareNameHash(COMMAND* command, // IN: main parsing structure + SESSION* session // IN: session structure with nameHash +) +{ + HASH_STATE hashState; + TPM2B_DIGEST nameHash; + UINT32 i; + TPM2B_NAME name; + // + nameHash.t.size = CryptHashStart(&hashState, session->authHashAlg); + // Add names. + for(i = 0; i < command->handleNum; i++) + CryptDigestUpdate2B(&hashState, + &EntityGetName(command->handles[i], &name)->b); + // Complete hash. + CryptHashEnd2B(&hashState, &nameHash.b); + // and compare + return MemoryEqual( + session->u1.nameHash.t.buffer, nameHash.t.buffer, nameHash.t.size); +} + +//*** CheckPWAuthSession() +// This function validates the authorization provided in a PWAP session. It +// compares the input value to authValue of the authorized entity. Argument +// sessionIndex is used to get handles handle of the referenced entities from +// s_inputAuthValues[] and s_associatedHandles[]. +// +// Return Type: TPM_RC +// TPM_RC_AUTH_FAIL authorization fails and increments DA failure +// count +// TPM_RC_BAD_AUTH authorization fails but DA does not apply +// +static TPM_RC CheckPWAuthSession( + UINT32 sessionIndex // IN: index of session to be processed +) +{ + TPM2B_AUTH authValue; + TPM_HANDLE associatedHandle = s_associatedHandles[sessionIndex]; + // + // Strip trailing zeros from the password. + MemoryRemoveTrailingZeros(&s_inputAuthValues[sessionIndex]); + + // Get the authValue with trailing zeros removed + EntityGetAuthValue(associatedHandle, &authValue); + + // Success if the values are identical. + if(MemoryEqual2B(&s_inputAuthValues[sessionIndex].b, &authValue.b)) + { + return TPM_RC_SUCCESS; + } + else // if the digests are not identical + { + // Invoke DA protection if applicable. + return IncrementLockout(sessionIndex); + } +} + +//*** ComputeCommandHMAC() +// This function computes the HMAC for an authorization session in a command. +/*(See part 1 specification -- this tag keeps this comment from showing up in +// merged document which is probably good because this comment doesn't look right. +// The sessionAuth value +// authHMAC := HMACsHash((sessionKey | authValue), +// (pHash | nonceNewer | nonceOlder | nonceTPMencrypt-only +// | nonceTPMaudit | sessionAttributes)) +// Where: +// HMACsHash() The HMAC algorithm using the hash algorithm specified +// when the session was started. +// +// sessionKey A value that is computed in a protocol-dependent way, +// using KDFa. When used in an HMAC or KDF, the size field +// for this value is not included. +// +// authValue A value that is found in the sensitive area of an entity. +// When used in an HMAC or KDF, the size field for this +// value is not included. +// +// pHash Hash of the command (cpHash) using the session hash. +// When using a pHash in an HMAC computation, only the +// digest is used. +// +// nonceNewer A value that is generated by the entity using the +// session. A new nonce is generated on each use of the +// session. For a command, this will be nonceCaller. +// When used in an HMAC or KDF, the size field is not used. +// +// nonceOlder A TPM2B_NONCE that was received the previous time the +// session was used. For a command, this is nonceTPM. +// When used in an HMAC or KDF, the size field is not used. +// +// nonceTPMdecrypt The nonceTPM of the decrypt session is included in +// the HMAC, but only in the command. +// +// nonceTPMencrypt The nonceTPM of the encrypt session is included in +// the HMAC but only in the command. +// +// sessionAttributes A byte indicating the attributes associated with the +// particular use of the session. +*/ +static TPM2B_DIGEST* ComputeCommandHMAC( + COMMAND* command, // IN: primary control structure + UINT32 sessionIndex, // IN: index of session to be processed + TPM2B_DIGEST* hmac // OUT: authorization HMAC +) +{ + TPM2B_TYPE(KEY, (sizeof(AUTH_VALUE) * 2)); + TPM2B_KEY key; + BYTE marshalBuffer[sizeof(TPMA_SESSION)]; + BYTE* buffer; + UINT32 marshalSize; + HMAC_STATE hmacState; + TPM2B_NONCE* nonceDecrypt; + TPM2B_NONCE* nonceEncrypt; + SESSION* session; + // + nonceDecrypt = NULL; + nonceEncrypt = NULL; + + // Determine if extra nonceTPM values are going to be required. + // If this is the first session (sessionIndex = 0) and it is an authorization + // session that uses an HMAC, then check if additional session nonces are to be + // included. + if(sessionIndex == 0 && s_associatedHandles[sessionIndex] != TPM_RH_UNASSIGNED) + { + // If there is a decrypt session and if this is not the decrypt session, + // then an extra nonce may be needed. + if(s_decryptSessionIndex != UNDEFINED_INDEX + && s_decryptSessionIndex != sessionIndex) + { + // Will add the nonce for the decrypt session. + SESSION* decryptSession = + SessionGet(s_sessionHandles[s_decryptSessionIndex]); + nonceDecrypt = &decryptSession->nonceTPM; + } + // Now repeat for the encrypt session. + if(s_encryptSessionIndex != UNDEFINED_INDEX + && s_encryptSessionIndex != sessionIndex + && s_encryptSessionIndex != s_decryptSessionIndex) + { + // Have to have the nonce for the encrypt session. + SESSION* encryptSession = + SessionGet(s_sessionHandles[s_encryptSessionIndex]); + nonceEncrypt = &encryptSession->nonceTPM; + } + } + + // Continue with the HMAC processing. + session = SessionGet(s_sessionHandles[sessionIndex]); + + // Generate HMAC key. + MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer)); + + // Check if the session has an associated handle and if the associated entity + // is the one to which the session is bound. If not, add the authValue of + // this entity to the HMAC key. + // If the session is bound to the object or the session is a policy session + // with no authValue required, do not include the authValue in the HMAC key. + // Note: For a policy session, its isBound attribute is CLEARED. + // + // Include the entity authValue if it is needed + if(session->attributes.includeAuth == SET) + { + TPM2B_AUTH authValue; + // Get the entity authValue with trailing zeros removed + EntityGetAuthValue(s_associatedHandles[sessionIndex], &authValue); + // add the authValue to the HMAC key + MemoryConcat2B(&key.b, &authValue.b, sizeof(key.t.buffer)); + } + // if the HMAC key size is 0, a NULL string HMAC is allowed + if(key.t.size == 0 && s_inputAuthValues[sessionIndex].t.size == 0) + { + hmac->t.size = 0; + return hmac; + } + // Start HMAC + hmac->t.size = CryptHmacStart2B(&hmacState, session->authHashAlg, &key.b); + + // Add cpHash + CryptDigestUpdate2B(&hmacState.hashState, + &ComputeCpHash(command, session->authHashAlg)->b); + // Add nonces as required + CryptDigestUpdate2B(&hmacState.hashState, &s_nonceCaller[sessionIndex].b); + CryptDigestUpdate2B(&hmacState.hashState, &session->nonceTPM.b); + if(nonceDecrypt != NULL) + CryptDigestUpdate2B(&hmacState.hashState, &nonceDecrypt->b); + if(nonceEncrypt != NULL) + CryptDigestUpdate2B(&hmacState.hashState, &nonceEncrypt->b); + // Add sessionAttributes + buffer = marshalBuffer; + marshalSize = TPMA_SESSION_Marshal(&(s_attributes[sessionIndex]), &buffer, NULL); + CryptDigestUpdate(&hmacState.hashState, marshalSize, marshalBuffer); + // Complete the HMAC computation + CryptHmacEnd2B(&hmacState, &hmac->b); + + return hmac; +} + +//*** CheckSessionHMAC() +// This function checks the HMAC of in a session. It uses ComputeCommandHMAC() +// to compute the expected HMAC value and then compares the result with the +// HMAC in the authorization session. The authorization is successful if they +// are the same. +// +// If the authorizations are not the same, IncrementLockout() is called. It will +// return TPM_RC_AUTH_FAIL if the failure caused the failureCount to increment. +// Otherwise, it will return TPM_RC_BAD_AUTH. +// +// Return Type: TPM_RC +// TPM_RC_AUTH_FAIL authorization failure caused failureCount increment +// TPM_RC_BAD_AUTH authorization failure did not cause failureCount +// increment +// +static TPM_RC CheckSessionHMAC( + COMMAND* command, // IN: primary control structure + UINT32 sessionIndex // IN: index of session to be processed +) +{ + TPM2B_DIGEST hmac; // authHMAC for comparing + // + // Compute authHMAC + ComputeCommandHMAC(command, sessionIndex, &hmac); + + // Compare the input HMAC with the authHMAC computed above. + if(!MemoryEqual2B(&s_inputAuthValues[sessionIndex].b, &hmac.b)) + { + // If an HMAC session has a failure, invoke the anti-hammering + // if it applies to the authorized entity or the session. + // Otherwise, just indicate that the authorization is bad. + return IncrementLockout(sessionIndex); + } + return TPM_RC_SUCCESS; +} + +//*** CheckPolicyAuthSession() +// This function is used to validate the authorization in a policy session. +// This function performs the following comparisons to see if a policy +// authorization is properly provided. The check are: +// a) compare policyDigest in session with authPolicy associated with +// the entity to be authorized; +// b) compare timeout if applicable; +// c) compare commandCode if applicable; +// d) compare cpHash if applicable; and +// e) see if PCR values have changed since computed. +// +// If all the above checks succeed, the handle is authorized. +// The order of these comparisons is not important because any failure will +// result in the same error code. +// +// Return Type: TPM_RC +// TPM_RC_PCR_CHANGED PCR value is not current +// TPM_RC_POLICY_FAIL policy session fails +// TPM_RC_LOCALITY command locality is not allowed +// TPM_RC_POLICY_CC CC doesn't match +// TPM_RC_EXPIRED policy session has expired +// TPM_RC_PP PP is required but not asserted +// TPM_RC_NV_UNAVAILABLE NV is not available for write +// TPM_RC_NV_RATE NV is rate limiting +static TPM_RC CheckPolicyAuthSession( + COMMAND* command, // IN: primary parsing structure + UINT32 sessionIndex // IN: index of session to be processed +) +{ + SESSION* session; + TPM2B_DIGEST authPolicy; + TPMI_ALG_HASH policyAlg; + UINT8 locality; + // + // Initialize pointer to the authorization session. + session = SessionGet(s_sessionHandles[sessionIndex]); + + // If the command is TPM2_PolicySecret(), make sure that + // either password or authValue is required + if(command->code == TPM_CC_PolicySecret + && session->attributes.isPasswordNeeded == CLEAR + && session->attributes.isAuthValueNeeded == CLEAR) + return TPM_RC_MODE; + // See if the PCR counter for the session is still valid. + if(!SessionPCRValueIsCurrent(session)) + return TPM_RC_PCR_CHANGED; + // Get authPolicy. + policyAlg = EntityGetAuthPolicy(s_associatedHandles[sessionIndex], &authPolicy); + // Compare authPolicy. + if(!MemoryEqual2B(&session->u2.policyDigest.b, &authPolicy.b)) + return TPM_RC_POLICY_FAIL; + // Policy is OK so check if the other factors are correct + + // Compare policy hash algorithm. + if(policyAlg != session->authHashAlg) + return TPM_RC_POLICY_FAIL; + + // Compare timeout. + if(session->timeout != 0) + { + // Cannot compare time if clock stop advancing. An TPM_RC_NV_UNAVAILABLE + // or TPM_RC_NV_RATE error may be returned here. This doesn't mean that + // a new nonce will be created just that, because TPM time can't advance + // we can't do time-based operations. + RETURN_IF_NV_IS_NOT_AVAILABLE; + + if((session->timeout < g_time) || (session->epoch != g_timeEpoch)) + return TPM_RC_EXPIRED; + } + // If command code is provided it must match + if(session->commandCode != 0) + { + if(session->commandCode != command->code) + return TPM_RC_POLICY_CC; + } + else + { + // If command requires a DUP or ADMIN authorization, the session must have + // command code set. + AUTH_ROLE role = CommandAuthRole(command->index, sessionIndex); + if(role == AUTH_ADMIN || role == AUTH_DUP) + return TPM_RC_POLICY_FAIL; + } + // Check command locality. + { + BYTE sessionLocality[sizeof(TPMA_LOCALITY)]; + BYTE* buffer = sessionLocality; + + // Get existing locality setting in canonical form + sessionLocality[0] = 0; + TPMA_LOCALITY_Marshal(&session->commandLocality, &buffer, NULL); + + // See if the locality has been set + if(sessionLocality[0] != 0) + { + // If so, get the current locality + locality = _plat__LocalityGet(); + if(locality < 5) + { + if(((sessionLocality[0] & (1 << locality)) == 0) + || sessionLocality[0] > 31) + return TPM_RC_LOCALITY; + } + else if(locality > 31) + { + if(sessionLocality[0] != locality) + return TPM_RC_LOCALITY; + } + else + { + // Could throw an assert here but a locality error is just + // as good. It just means that, whatever the locality is, it isn't + // the locality requested so... + return TPM_RC_LOCALITY; + } + } + } // end of locality check + // Check physical presence. + if(session->attributes.isPPRequired == SET && !_plat__PhysicalPresenceAsserted()) + return TPM_RC_PP; + // Compare cpHash/nameHash if defined, or if the command requires an ADMIN or + // DUP role for this handle. + if(session->u1.cpHash.b.size != 0) + { + BOOL OK; + if(session->attributes.isCpHashDefined) + // Compare cpHash. + OK = MemoryEqual2B(&session->u1.cpHash.b, + &ComputeCpHash(command, session->authHashAlg)->b); + else if(session->attributes.isTemplateSet) + OK = CompareTemplateHash(command, session); + else + OK = CompareNameHash(command, session); + if(!OK) + return TPM_RCS_POLICY_FAIL; + } + if(session->attributes.checkNvWritten) + { + NV_REF locator; + NV_INDEX* nvIndex; + // + // If this is not an NV index, the policy makes no sense so fail it. + if(HandleGetType(s_associatedHandles[sessionIndex]) != TPM_HT_NV_INDEX) + return TPM_RC_POLICY_FAIL; + // Get the index data + nvIndex = NvGetIndexInfo(s_associatedHandles[sessionIndex], &locator); + + // Make sure that the TPMA_WRITTEN_ATTRIBUTE has the desired state + if((IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN)) + != (session->attributes.nvWrittenState == SET)) + return TPM_RC_POLICY_FAIL; + } + return TPM_RC_SUCCESS; +} + +//*** RetrieveSessionData() +// This function will unmarshal the sessions in the session area of a command. The +// values are placed in the arrays that are defined at the beginning of this file. +// The normal unmarshaling errors are possible. +// +// Return Type: TPM_RC +// TPM_RC_SUCCSS unmarshaled without error +// TPM_RC_SIZE the number of bytes unmarshaled is not the same +// as the value for authorizationSize in the command +// +static TPM_RC RetrieveSessionData( + COMMAND* command // IN: main parsing structure for command +) +{ + int i; + TPM_RC result; + SESSION* session; + TPMA_SESSION sessionAttributes; + TPM_HT sessionType; + INT32 sessionIndex; + TPM_RC errorIndex; + // + s_decryptSessionIndex = UNDEFINED_INDEX; + s_encryptSessionIndex = UNDEFINED_INDEX; + s_auditSessionIndex = UNDEFINED_INDEX; + + for(sessionIndex = 0; command->authSize > 0; sessionIndex++) + { + errorIndex = TPM_RC_S + g_rcIndex[sessionIndex]; + + // If maximum allowed number of sessions has been parsed, return a size + // error with a session number that is larger than the number of allowed + // sessions + if(sessionIndex == MAX_SESSION_NUM) + return TPM_RCS_SIZE + errorIndex; + // make sure that the associated handle for each session starts out + // unassigned + s_associatedHandles[sessionIndex] = TPM_RH_UNASSIGNED; + + // First parameter: Session handle. + result = TPMI_SH_AUTH_SESSION_Unmarshal(&s_sessionHandles[sessionIndex], + &command->parameterBuffer, + &command->authSize, + TRUE); + if(result != TPM_RC_SUCCESS) + return result + TPM_RC_S + g_rcIndex[sessionIndex]; + // Second parameter: Nonce. + result = TPM2B_NONCE_Unmarshal(&s_nonceCaller[sessionIndex], + &command->parameterBuffer, + &command->authSize); + if(result != TPM_RC_SUCCESS) + return result + TPM_RC_S + g_rcIndex[sessionIndex]; + // Third parameter: sessionAttributes. + result = TPMA_SESSION_Unmarshal(&s_attributes[sessionIndex], + &command->parameterBuffer, + &command->authSize); + if(result != TPM_RC_SUCCESS) + return result + TPM_RC_S + g_rcIndex[sessionIndex]; + // Fourth parameter: authValue (PW or HMAC). + result = TPM2B_AUTH_Unmarshal(&s_inputAuthValues[sessionIndex], + &command->parameterBuffer, + &command->authSize); + if(result != TPM_RC_SUCCESS) + return result + errorIndex; + + sessionAttributes = s_attributes[sessionIndex]; + if(s_sessionHandles[sessionIndex] == TPM_RS_PW) + { + // A PWAP session needs additional processing. + // Can't have any attributes set other than continueSession bit + if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, encrypt) + || IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, decrypt) + || IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, audit) + || IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, auditExclusive) + || IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, auditReset)) + return TPM_RCS_ATTRIBUTES + errorIndex; + // The nonce size must be zero. + if(s_nonceCaller[sessionIndex].t.size != 0) + return TPM_RCS_NONCE + errorIndex; + continue; + } + // For not password sessions... + // Find out if the session is loaded. + if(!SessionIsLoaded(s_sessionHandles[sessionIndex])) + return TPM_RC_REFERENCE_S0 + sessionIndex; + sessionType = HandleGetType(s_sessionHandles[sessionIndex]); + session = SessionGet(s_sessionHandles[sessionIndex]); + + // Check if the session is an HMAC/policy session. + if((session->attributes.isPolicy == SET && sessionType == TPM_HT_HMAC_SESSION) + || (session->attributes.isPolicy == CLEAR + && sessionType == TPM_HT_POLICY_SESSION)) + return TPM_RCS_HANDLE + errorIndex; + // Check that this handle has not previously been used. + for(i = 0; i < sessionIndex; i++) + { + if(s_sessionHandles[i] == s_sessionHandles[sessionIndex]) + return TPM_RCS_HANDLE + errorIndex; + } + // If the session is used for parameter encryption or audit as well, set + // the corresponding Indexes. + + // First process decrypt. + if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, decrypt)) + { + // Check if the commandCode allows command parameter encryption. + if(DecryptSize(command->index) == 0) + return TPM_RCS_ATTRIBUTES + errorIndex; + // Encrypt attribute can only appear in one session + if(s_decryptSessionIndex != UNDEFINED_INDEX) + return TPM_RCS_ATTRIBUTES + errorIndex; + // Can't decrypt if the session's symmetric algorithm is TPM_ALG_NULL + if(session->symmetric.algorithm == TPM_ALG_NULL) + return TPM_RCS_SYMMETRIC + errorIndex; + // All checks passed, so set the index for the session used to decrypt + // a command parameter. + s_decryptSessionIndex = sessionIndex; + } + // Now process encrypt. + if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, encrypt)) + { + // Check if the commandCode allows response parameter encryption. + if(EncryptSize(command->index) == 0) + return TPM_RCS_ATTRIBUTES + errorIndex; + // Encrypt attribute can only appear in one session. + if(s_encryptSessionIndex != UNDEFINED_INDEX) + return TPM_RCS_ATTRIBUTES + errorIndex; + // Can't encrypt if the session's symmetric algorithm is TPM_ALG_NULL + if(session->symmetric.algorithm == TPM_ALG_NULL) + return TPM_RCS_SYMMETRIC + errorIndex; + // All checks passed, so set the index for the session used to encrypt + // a response parameter. + s_encryptSessionIndex = sessionIndex; + } + // At last process audit. + if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, audit)) + { + // Audit attribute can only appear in one session. + if(s_auditSessionIndex != UNDEFINED_INDEX) + return TPM_RCS_ATTRIBUTES + errorIndex; + // An audit session can not be policy session. + if(HandleGetType(s_sessionHandles[sessionIndex]) == TPM_HT_POLICY_SESSION) + return TPM_RCS_ATTRIBUTES + errorIndex; + // If this is a reset of the audit session, or the first use + // of the session as an audit session, it doesn't matter what + // the exclusive state is. The session will become exclusive. + if(!IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, auditReset) + && session->attributes.isAudit == SET) + { + // Not first use or reset. If auditExlusive is SET, then this + // session must be the current exclusive session. + if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, auditExclusive) + && g_exclusiveAuditSession != s_sessionHandles[sessionIndex]) + return TPM_RC_EXCLUSIVE; + } + s_auditSessionIndex = sessionIndex; + } + // Initialize associated handle as undefined. This will be changed when + // the handles are processed. + s_associatedHandles[sessionIndex] = TPM_RH_UNASSIGNED; + } + command->sessionNum = sessionIndex; + return TPM_RC_SUCCESS; +} + +//*** CheckLockedOut() +// This function checks to see if the TPM is in lockout. This function should only +// be called if the entity being checked is subject to DA protection. The TPM +// is in lockout if the NV is not available and a DA write is pending. Otherwise +// the TPM is locked out if checking for lockoutAuth ('lockoutAuthCheck' == TRUE) +// and use of lockoutAuth is disabled, or 'failedTries' >= 'maxTries' +// Return Type: TPM_RC +// TPM_RC_NV_RATE NV is rate limiting +// TPM_RC_NV_UNAVAILABLE NV is not available at this time +// TPM_RC_LOCKOUT TPM is in lockout +static TPM_RC CheckLockedOut( + BOOL lockoutAuthCheck // IN: TRUE if checking is for lockoutAuth +) +{ + // If NV is unavailable, and current cycle state recorded in NV is not + // SU_NONE_VALUE, refuse to check any authorization because we would + // not be able to handle a DA failure. + if(!NV_IS_AVAILABLE && NV_IS_ORDERLY) + return g_NvStatus; + // Check if DA info needs to be updated in NV. + if(s_DAPendingOnNV) + { + // If NV is accessible, + RETURN_IF_NV_IS_NOT_AVAILABLE; + + // ... write the pending DA data and proceed. + NV_SYNC_PERSISTENT(lockOutAuthEnabled); + NV_SYNC_PERSISTENT(failedTries); + s_DAPendingOnNV = FALSE; + } + // Lockout is in effect if checking for lockoutAuth and use of lockoutAuth + // is disabled... + if(lockoutAuthCheck) + { + if(gp.lockOutAuthEnabled == FALSE) + return TPM_RC_LOCKOUT; + } + else + { + // ... or if the number of failed tries has been maxed out. + if(gp.failedTries >= gp.maxTries) + return TPM_RC_LOCKOUT; +#if USE_DA_USED + // If the daUsed flag is not SET, then no DA validation until the + // daUsed state is written to NV + if(!g_daUsed) + { + RETURN_IF_NV_IS_NOT_AVAILABLE; + g_daUsed = TRUE; + gp.orderlyState = SU_DA_USED_VALUE; + NV_SYNC_PERSISTENT(orderlyState); + return TPM_RC_RETRY; + } +#endif + } + return TPM_RC_SUCCESS; +} + +//*** CheckAuthSession() +// This function checks that the authorization session properly authorizes the +// use of the associated handle. +// +// Return Type: TPM_RC +// TPM_RC_LOCKOUT entity is protected by DA and TPM is in +// lockout, or TPM is locked out on NV update +// pending on DA parameters +// +// TPM_RC_PP Physical Presence is required but not provided +// TPM_RC_AUTH_FAIL HMAC or PW authorization failed +// with DA side-effects (can be a policy session) +// +// TPM_RC_BAD_AUTH HMAC or PW authorization failed without DA +// side-effects (can be a policy session) +// +// TPM_RC_POLICY_FAIL if policy session fails +// TPM_RC_POLICY_CC command code of policy was wrong +// TPM_RC_EXPIRED the policy session has expired +// TPM_RC_PCR +// TPM_RC_AUTH_UNAVAILABLE authValue or authPolicy unavailable +static TPM_RC CheckAuthSession( + COMMAND* command, // IN: primary parsing structure + UINT32 sessionIndex // IN: index of session to be processed +) +{ + TPM_RC result = TPM_RC_SUCCESS; + SESSION* session = NULL; + TPM_HANDLE sessionHandle = s_sessionHandles[sessionIndex]; + TPM_HANDLE associatedHandle = s_associatedHandles[sessionIndex]; + TPM_HT sessionHandleType = HandleGetType(sessionHandle); + BOOL authUsed; + // + pAssert(sessionHandle != TPM_RH_UNASSIGNED); + + // Take care of physical presence + if(associatedHandle == TPM_RH_PLATFORM) + { + // If the physical presence is required for this command, check for PP + // assertion. If it isn't asserted, no point going any further. + if(PhysicalPresenceIsRequired(command->index) + && !_plat__PhysicalPresenceAsserted()) + return TPM_RC_PP; + } + if(sessionHandle != TPM_RS_PW) + { + session = SessionGet(sessionHandle); + + // Set includeAuth to indicate if DA checking will be required and if the + // authValue will be included in any HMAC. + if(sessionHandleType == TPM_HT_POLICY_SESSION) + { + // For a policy session, will check the DA status of the entity if either + // isAuthValueNeeded or isPasswordNeeded is SET. + session->attributes.includeAuth = session->attributes.isAuthValueNeeded + || session->attributes.isPasswordNeeded; + } + else + { + // For an HMAC session, need to check unless the session + // is bound. + session->attributes.includeAuth = + !IsSessionBindEntity(s_associatedHandles[sessionIndex], session); + } + authUsed = session->attributes.includeAuth; + } + else + // Password session + authUsed = TRUE; + // If the authorization session is going to use an authValue, then make sure + // that access to that authValue isn't locked out. + if(authUsed) + { + // See if entity is subject to lockout. + if(!IsDAExempted(associatedHandle)) + { + // See if in lockout + result = CheckLockedOut(associatedHandle == TPM_RH_LOCKOUT); + if(result != TPM_RC_SUCCESS) + return result; + } + } + // Policy or HMAC+PW? + if(sessionHandleType != TPM_HT_POLICY_SESSION) + { + // for non-policy session make sure that a policy session is not required + if(IsPolicySessionRequired(command->index, sessionIndex)) + return TPM_RC_AUTH_TYPE; + // The authValue must be available. + // Note: The authValue is going to be "used" even if it is an EmptyAuth. + // and the session is bound. + if(!IsAuthValueAvailable(associatedHandle, command->index, sessionIndex)) + return TPM_RC_AUTH_UNAVAILABLE; + } + else + { + // ... see if the entity has a policy, ... + // Note: IsAuthPolicyAvalable will return FALSE if the sensitive area of the + // object is not loaded + if(!IsAuthPolicyAvailable(associatedHandle, command->index, sessionIndex)) + return TPM_RC_AUTH_UNAVAILABLE; + // ... and check the policy session. + result = CheckPolicyAuthSession(command, sessionIndex); + if(result != TPM_RC_SUCCESS) + return result; + } + // Check authorization according to the type + if((TPM_RS_PW == sessionHandle) || (session->attributes.isPasswordNeeded == SET)) + result = CheckPWAuthSession(sessionIndex); + else + result = CheckSessionHMAC(command, sessionIndex); + // Do processing for PIN Indexes are only three possibilities for 'result' at + // this point: TPM_RC_SUCCESS, TPM_RC_AUTH_FAIL, and TPM_RC_BAD_AUTH. + // For all these cases, we would have to process a PIN index if the + // authValue of the index was used for authorization. + if((TPM_HT_NV_INDEX == HandleGetType(associatedHandle)) && authUsed) + { + NV_REF locator; + NV_INDEX* nvIndex = NvGetIndexInfo(associatedHandle, &locator); + NV_PIN pinData; + TPMA_NV nvAttributes; + // + pAssert(nvIndex != NULL); + nvAttributes = nvIndex->publicArea.attributes; + // If this is a PIN FAIL index and the value has been written + // then we can update the counter (increment or clear) + if(IsNvPinFailIndex(nvAttributes) + && IS_ATTRIBUTE(nvAttributes, TPMA_NV, WRITTEN)) + { + pinData.intVal = NvGetUINT64Data(nvIndex, locator); + if(result != TPM_RC_SUCCESS) + pinData.pin.pinCount++; + else + pinData.pin.pinCount = 0; + NvWriteUINT64Data(nvIndex, pinData.intVal); + } + // If this is a PIN PASS Index, increment if we have used the + // authorization value. + // NOTE: If the counter has already hit the limit, then we + // would not get here because the authorization value would not + // be available and the TPM would have returned before it gets here + else if(IsNvPinPassIndex(nvAttributes) + && IS_ATTRIBUTE(nvAttributes, TPMA_NV, WRITTEN) + && result == TPM_RC_SUCCESS) + { + // If the access is valid, then increment the use counter + pinData.intVal = NvGetUINT64Data(nvIndex, locator); + pinData.pin.pinCount++; + NvWriteUINT64Data(nvIndex, pinData.intVal); + } + } + return result; +} + +#if CC_GetCommandAuditDigest +//*** CheckCommandAudit() +// This function is called before the command is processed if audit is enabled +// for the command. It will check to see if the audit can be performed and +// will ensure that the cpHash is available for the audit. +// Return Type: TPM_RC +// TPM_RC_NV_UNAVAILABLE NV is not available for write +// TPM_RC_NV_RATE NV is rate limiting +static TPM_RC CheckCommandAudit(COMMAND* command) +{ + // If the audit digest is clear and command audit is required, NV must be + // available so that TPM2_GetCommandAuditDigest() is able to increment + // audit counter. If NV is not available, the function bails out to prevent + // the TPM from attempting an operation that would fail anyway. + if(gr.commandAuditDigest.t.size == 0 + || GetCommandCode(command->index) == TPM_CC_GetCommandAuditDigest) + { + RETURN_IF_NV_IS_NOT_AVAILABLE; + } + // Make sure that the cpHash is computed for the algorithm + ComputeCpHash(command, gp.auditHashAlg); + return TPM_RC_SUCCESS; +} +#endif + +//*** ParseSessionBuffer() +// This function is the entry function for command session processing. +// It iterates sessions in session area and reports if the required authorization +// has been properly provided. It also processes audit session and passes the +// information of encryption sessions to parameter encryption module. +// +// Return Type: TPM_RC +// various parsing failure or authorization failure +// +TPM_RC +ParseSessionBuffer(COMMAND* command // IN: the structure that contains +) +{ + TPM_RC result; + UINT32 i; + INT32 size = 0; + TPM2B_AUTH extraKey; + UINT32 sessionIndex; + TPM_RC errorIndex; + SESSION* session = NULL; + // + // Check if a command allows any session in its session area. + if(!IsSessionAllowed(command->index)) + return TPM_RC_AUTH_CONTEXT; + // Default-initialization. + command->sessionNum = 0; + + result = RetrieveSessionData(command); + if(result != TPM_RC_SUCCESS) + return result; + // There is no command in the TPM spec that has more handles than + // MAX_SESSION_NUM. + pAssert(command->handleNum <= MAX_SESSION_NUM); + + // Associate the session with an authorization handle. + for(i = 0; i < command->handleNum; i++) + { + if(CommandAuthRole(command->index, i) != AUTH_NONE) + { + // If the received session number is less than the number of handles + // that requires authorization, an error should be returned. + // Note: for all the TPM 2.0 commands, handles requiring + // authorization come first in a command input and there are only ever + // two values requiring authorization + if(i > (command->sessionNum - 1)) + return TPM_RC_AUTH_MISSING; + // Record the handle associated with the authorization session + s_associatedHandles[i] = command->handles[i]; + } + } + // Consistency checks are done first to avoid authorization failure when the + // command will not be executed anyway. + for(sessionIndex = 0; sessionIndex < command->sessionNum; sessionIndex++) + { + errorIndex = TPM_RC_S + g_rcIndex[sessionIndex]; + // PW session must be an authorization session + if(s_sessionHandles[sessionIndex] == TPM_RS_PW) + { + if(s_associatedHandles[sessionIndex] == TPM_RH_UNASSIGNED) + return TPM_RCS_HANDLE + errorIndex; + // a password session can't be audit, encrypt or decrypt + if(IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, audit) + || IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, encrypt) + || IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, decrypt)) + return TPM_RCS_ATTRIBUTES + errorIndex; + session = NULL; + } + else + { + session = SessionGet(s_sessionHandles[sessionIndex]); + + // A trial session can not appear in session area, because it cannot + // be used for authorization, audit or encrypt/decrypt. + if(session->attributes.isTrialPolicy == SET) + return TPM_RCS_ATTRIBUTES + errorIndex; + + // See if the session is bound to a DA protected entity + // NOTE: Since a policy session is never bound, a policy is still + // usable even if the object is DA protected and the TPM is in + // lockout. + if(session->attributes.isDaBound == SET) + { + result = CheckLockedOut(session->attributes.isLockoutBound == SET); + if(result != TPM_RC_SUCCESS) + return result; + } + // If this session is for auditing, make sure the cpHash is computed. + if(IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, audit)) + ComputeCpHash(command, session->authHashAlg); + } + + // if the session has an associated handle, check the authorization + if(s_associatedHandles[sessionIndex] != TPM_RH_UNASSIGNED) + { + result = CheckAuthSession(command, sessionIndex); + if(result != TPM_RC_SUCCESS) + return RcSafeAddToResult(result, errorIndex); + } + else + { + // a session that is not for authorization must either be encrypt, + // decrypt, or audit + if(!IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, audit) + && !IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, encrypt) + && !IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, decrypt)) + return TPM_RCS_ATTRIBUTES + errorIndex; + + // no authValue included in any of the HMAC computations + pAssert(session != NULL); + session->attributes.includeAuth = CLEAR; + + // check HMAC for encrypt/decrypt/audit only sessions + result = CheckSessionHMAC(command, sessionIndex); + if(result != TPM_RC_SUCCESS) + return RcSafeAddToResult(result, errorIndex); + } + } +#if CC_GetCommandAuditDigest + // Check if the command should be audited. Need to do this before any parameter + // encryption so that the cpHash for the audit is correct + if(CommandAuditIsRequired(command->index)) + { + result = CheckCommandAudit(command); + if(result != TPM_RC_SUCCESS) + return result; // No session number to reference + } +#endif + // Decrypt the first parameter if applicable. This should be the last operation + // in session processing. + // If the encrypt session is associated with a handle and the handle's + // authValue is available, then authValue is concatenated with sessionKey to + // generate encryption key, no matter if the handle is the session bound entity + // or not. + if(s_decryptSessionIndex != UNDEFINED_INDEX) + { + // If this is an authorization session, include the authValue in the + // generation of the decryption key + if(s_associatedHandles[s_decryptSessionIndex] != TPM_RH_UNASSIGNED) + { + EntityGetAuthValue(s_associatedHandles[s_decryptSessionIndex], &extraKey); + } + else + { + extraKey.b.size = 0; + } + size = DecryptSize(command->index); + result = CryptParameterDecryption(s_sessionHandles[s_decryptSessionIndex], + &s_nonceCaller[s_decryptSessionIndex].b, + command->parameterSize, + (UINT16)size, + &extraKey, + command->parameterBuffer); + if(result != TPM_RC_SUCCESS) + return RcSafeAddToResult(result, + TPM_RC_S + g_rcIndex[s_decryptSessionIndex]); + } + + return TPM_RC_SUCCESS; +} + +//*** CheckAuthNoSession() +// Function to process a command with no session associated. +// The function makes sure all the handles in the command require no authorization. +// +// Return Type: TPM_RC +// TPM_RC_AUTH_MISSING failure - one or more handles require +// authorization +TPM_RC +CheckAuthNoSession(COMMAND* command // IN: command parsing structure +) +{ + UINT32 i; +#if CC_GetCommandAuditDigest + TPM_RC result = TPM_RC_SUCCESS; +#endif + // + // Check if the command requires authorization + for(i = 0; i < command->handleNum; i++) + { + if(CommandAuthRole(command->index, i) != AUTH_NONE) + return TPM_RC_AUTH_MISSING; + } +#if CC_GetCommandAuditDigest + // Check if the command should be audited. + if(CommandAuditIsRequired(command->index)) + { + result = CheckCommandAudit(command); + if(result != TPM_RC_SUCCESS) + return result; + } +#endif + // Initialize number of sessions to be 0 + command->sessionNum = 0; + + return TPM_RC_SUCCESS; +} + +//** Response Session Processing +//*** Introduction +// +// The following functions build the session area in a response and handle +// the audit sessions (if present). +// + +//*** ComputeRpHash() +// Function to compute rpHash (Response Parameter Hash). The rpHash is only +// computed if there is an HMAC authorization session and the return code is +// TPM_RC_SUCCESS. +static TPM2B_DIGEST* ComputeRpHash( + COMMAND* command, // IN: command structure + TPM_ALG_ID hashAlg // IN: hash algorithm to compute rpHash +) +{ + TPM2B_DIGEST* rpHash = GetRpHashPointer(command, hashAlg); + HASH_STATE hashState; + // + if(rpHash->t.size == 0) + { + // rpHash := hash(responseCode || commandCode || parameters) + + // Initiate hash creation. + rpHash->t.size = CryptHashStart(&hashState, hashAlg); + + // Add hash constituents. + CryptDigestUpdateInt(&hashState, sizeof(TPM_RC), TPM_RC_SUCCESS); + CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), command->code); + CryptDigestUpdate( + &hashState, command->parameterSize, command->parameterBuffer); + // Complete hash computation. + CryptHashEnd2B(&hashState, &rpHash->b); + } + return rpHash; +} + +//*** InitAuditSession() +// This function initializes the audit data in an audit session. +static void InitAuditSession(SESSION* session // session to be initialized +) +{ + // Mark session as an audit session. + session->attributes.isAudit = SET; + + // Audit session can not be bound. + session->attributes.isBound = CLEAR; + + // Size of the audit log is the size of session hash algorithm digest. + session->u2.auditDigest.t.size = CryptHashGetDigestSize(session->authHashAlg); + + // Set the original digest value to be 0. + MemorySet(&session->u2.auditDigest.t.buffer, 0, session->u2.auditDigest.t.size); + return; +} + +//*** UpdateAuditDigest +// Function to update an audit digest +static void UpdateAuditDigest( + COMMAND* command, TPMI_ALG_HASH hashAlg, TPM2B_DIGEST* digest) +{ + HASH_STATE hashState; + TPM2B_DIGEST* cpHash = GetCpHash(command, hashAlg); + TPM2B_DIGEST* rpHash = ComputeRpHash(command, hashAlg); + // + pAssert(cpHash != NULL); + + // digestNew := hash (digestOld || cpHash || rpHash) + // Start hash computation. + digest->t.size = CryptHashStart(&hashState, hashAlg); + // Add old digest. + CryptDigestUpdate2B(&hashState, &digest->b); + // Add cpHash + CryptDigestUpdate2B(&hashState, &cpHash->b); + // Add rpHash + CryptDigestUpdate2B(&hashState, &rpHash->b); + // Finalize the hash. + CryptHashEnd2B(&hashState, &digest->b); +} + +//*** Audit() +//This function updates the audit digest in an audit session. +static void Audit(COMMAND* command, // IN: primary control structure + SESSION* auditSession // IN: loaded audit session +) +{ + UpdateAuditDigest( + command, auditSession->authHashAlg, &auditSession->u2.auditDigest); + return; +} + +#if CC_GetCommandAuditDigest +//*** CommandAudit() +// This function updates the command audit digest. +static void CommandAudit(COMMAND* command // IN: +) +{ + // If the digest.size is one, it indicates the special case of changing + // the audit hash algorithm. For this case, no audit is done on exit. + // NOTE: When the hash algorithm is changed, g_updateNV is set in order to + // force an update to the NV on exit so that the change in digest will + // be recorded. So, it is safe to exit here without setting any flags + // because the digest change will be written to NV when this code exits. + if(gr.commandAuditDigest.t.size == 1) + { + gr.commandAuditDigest.t.size = 0; + return; + } + // If the digest size is zero, need to start a new digest and increment + // the audit counter. + if(gr.commandAuditDigest.t.size == 0) + { + gr.commandAuditDigest.t.size = CryptHashGetDigestSize(gp.auditHashAlg); + MemorySet(gr.commandAuditDigest.t.buffer, 0, gr.commandAuditDigest.t.size); + + // Bump the counter and save its value to NV. + gp.auditCounter++; + NV_SYNC_PERSISTENT(auditCounter); + } + UpdateAuditDigest(command, gp.auditHashAlg, &gr.commandAuditDigest); + return; +} +#endif + +//*** UpdateAuditSessionStatus() +// This function updates the internal audit related states of a session. It will: +// a) initialize the session as audit session and set it to be exclusive if this +// is the first time it is used for audit or audit reset was requested; +// b) report exclusive audit session; +// c) extend audit log; and +// d) clear exclusive audit session if no audit session found in the command. +static void UpdateAuditSessionStatus( + COMMAND* command // IN: primary control structure +) +{ + UINT32 i; + TPM_HANDLE auditSession = TPM_RH_UNASSIGNED; + // + // Iterate through sessions + for(i = 0; i < command->sessionNum; i++) + { + SESSION* session; + // + // PW session do not have a loaded session and can not be an audit + // session either. Skip it. + if(s_sessionHandles[i] == TPM_RS_PW) + continue; + session = SessionGet(s_sessionHandles[i]); + + // If a session is used for audit + if(IS_ATTRIBUTE(s_attributes[i], TPMA_SESSION, audit)) + { + // An audit session has been found + auditSession = s_sessionHandles[i]; + + // If the session has not been an audit session yet, or + // the auditSetting bits indicate a reset, initialize it and set + // it to be the exclusive session + if(session->attributes.isAudit == CLEAR + || IS_ATTRIBUTE(s_attributes[i], TPMA_SESSION, auditReset)) + { + InitAuditSession(session); + g_exclusiveAuditSession = auditSession; + } + else + { + // Check if the audit session is the current exclusive audit + // session and, if not, clear previous exclusive audit session. + if(g_exclusiveAuditSession != auditSession) + g_exclusiveAuditSession = TPM_RH_UNASSIGNED; + } + // Report audit session exclusivity. + if(g_exclusiveAuditSession == auditSession) + { + SET_ATTRIBUTE(s_attributes[i], TPMA_SESSION, auditExclusive); + } + else + { + CLEAR_ATTRIBUTE(s_attributes[i], TPMA_SESSION, auditExclusive); + } + // Extend audit log. + Audit(command, session); + } + } + // If no audit session is found in the command, and the command allows + // a session then, clear the current exclusive + // audit session. + if(auditSession == TPM_RH_UNASSIGNED && IsSessionAllowed(command->index)) + { + g_exclusiveAuditSession = TPM_RH_UNASSIGNED; + } + return; +} + +//*** ComputeResponseHMAC() +// Function to compute HMAC for authorization session in a response. +/*(See part 1 specification) +// Function: Compute HMAC for response sessions +// The sessionAuth value +// authHMAC := HMACsHASH((sessionAuth | authValue), +// (pHash | nonceTPM | nonceCaller | sessionAttributes)) +// Where: +// HMACsHASH() The HMAC algorithm using the hash algorithm specified when +// the session was started. +// +// sessionAuth A TPMB_MEDIUM computed in a protocol-dependent way, using +// KDFa. In an HMAC or KDF, only sessionAuth.buffer is used. +// +// authValue A TPM2B_AUTH that is found in the sensitive area of an +// object. In an HMAC or KDF, only authValue.buffer is used +// and all trailing zeros are removed. +// +// pHash Response parameters (rpHash) using the session hash. When +// using a pHash in an HMAC computation, both the algorithm ID +// and the digest are included. +// +// nonceTPM A TPM2B_NONCE that is generated by the entity using the +// session. In an HMAC or KDF, only nonceTPM.buffer is used. +// +// nonceCaller a TPM2B_NONCE that was received the previous time the +// session was used. In an HMAC or KDF, only +// nonceCaller.buffer is used. +// +// sessionAttributes A TPMA_SESSION that indicates the attributes associated +// with a particular use of the session. +*/ +static void ComputeResponseHMAC( + COMMAND* command, // IN: command structure + UINT32 sessionIndex, // IN: session index to be processed + SESSION* session, // IN: loaded session + TPM2B_DIGEST* hmac // OUT: authHMAC +) +{ + TPM2B_TYPE(KEY, (sizeof(AUTH_VALUE) * 2)); + TPM2B_KEY key; // HMAC key + BYTE marshalBuffer[sizeof(TPMA_SESSION)]; + BYTE* buffer; + UINT32 marshalSize; + HMAC_STATE hmacState; + TPM2B_DIGEST* rpHash = ComputeRpHash(command, session->authHashAlg); + // + // Generate HMAC key + MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer)); + + // Add the object authValue if required + if(session->attributes.includeAuth == SET) + { + // Note: includeAuth may be SET for a policy that is used in + // UndefineSpaceSpecial(). At this point, the Index has been deleted + // so the includeAuth will have no meaning. However, the + // s_associatedHandles[] value for the session is now set to TPM_RH_NULL so + // this will return the authValue associated with TPM_RH_NULL and that is + // and empty buffer. + TPM2B_AUTH authValue; + // + // Get the authValue with trailing zeros removed + EntityGetAuthValue(s_associatedHandles[sessionIndex], &authValue); + + // Add it to the key + MemoryConcat2B(&key.b, &authValue.b, sizeof(key.t.buffer)); + } + + // if the HMAC key size is 0, the response HMAC is computed according to the + // input HMAC + if(key.t.size == 0 && s_inputAuthValues[sessionIndex].t.size == 0) + { + hmac->t.size = 0; + return; + } + // Start HMAC computation. + hmac->t.size = CryptHmacStart2B(&hmacState, session->authHashAlg, &key.b); + + // Add hash components. + CryptDigestUpdate2B(&hmacState.hashState, &rpHash->b); + CryptDigestUpdate2B(&hmacState.hashState, &session->nonceTPM.b); + CryptDigestUpdate2B(&hmacState.hashState, &s_nonceCaller[sessionIndex].b); + + // Add session attributes. + buffer = marshalBuffer; + marshalSize = TPMA_SESSION_Marshal(&s_attributes[sessionIndex], &buffer, NULL); + CryptDigestUpdate(&hmacState.hashState, marshalSize, marshalBuffer); + + // Finalize HMAC. + CryptHmacEnd2B(&hmacState, &hmac->b); + + return; +} + +//*** UpdateInternalSession() +// This function updates internal sessions by: +// a) restarting session time; and +// b) clearing a policy session since nonce is rolling. +static void UpdateInternalSession(SESSION* session, // IN: the session structure + UINT32 i // IN: session number +) +{ + // If nonce is rolling in a policy session, the policy related data + // will be re-initialized. + if(HandleGetType(s_sessionHandles[i]) == TPM_HT_POLICY_SESSION + && IS_ATTRIBUTE(s_attributes[i], TPMA_SESSION, continueSession)) + { + // When the nonce rolls it starts a new timing interval for the + // policy session. + SessionResetPolicyData(session); + SessionSetStartTime(session); + } + return; +} + +//*** BuildSingleResponseAuth() +// Function to compute response HMAC value for a policy or HMAC session. +static TPM2B_NONCE* BuildSingleResponseAuth( + COMMAND* command, // IN: command structure + UINT32 sessionIndex, // IN: session index to be processed + TPM2B_AUTH* auth // OUT: authHMAC +) +{ + // Fill in policy/HMAC based session response. + SESSION* session = SessionGet(s_sessionHandles[sessionIndex]); + // + // If the session is a policy session with isPasswordNeeded SET, the + // authorization field is empty. + if(HandleGetType(s_sessionHandles[sessionIndex]) == TPM_HT_POLICY_SESSION + && session->attributes.isPasswordNeeded == SET) + auth->t.size = 0; + else + // Compute response HMAC. + ComputeResponseHMAC(command, sessionIndex, session, auth); + + UpdateInternalSession(session, sessionIndex); + return &session->nonceTPM; +} + +//*** UpdateAllNonceTPM() +// Updates TPM nonce for all sessions in command. +static void UpdateAllNonceTPM(COMMAND* command // IN: controlling structure +) +{ + UINT32 i; + SESSION* session; + // + for(i = 0; i < command->sessionNum; i++) + { + // If not a PW session, compute the new nonceTPM. + if(s_sessionHandles[i] != TPM_RS_PW) + { + session = SessionGet(s_sessionHandles[i]); + // Update nonceTPM in both internal session and response. + CryptRandomGenerate(session->nonceTPM.t.size, session->nonceTPM.t.buffer); + } + } + return; +} + +//*** BuildResponseSession() +// Function to build Session buffer in a response. The authorization data is added +// to the end of command->responseBuffer. The size of the authorization area is +// accumulated in command->authSize. +// When this is called, command->responseBuffer is pointing at the next location +// in the response buffer to be filled. This is where the authorization sessions +// will go, if any. command->parameterSize is the number of bytes that have been +// marshaled as parameters in the output buffer. +TPM_RC +BuildResponseSession(COMMAND* command // IN: structure that has relevant command + // information +) +{ + TPM_RC result = TPM_RC_SUCCESS; + + pAssert(command->authSize == 0); + + // Reset the parameter buffer to point to the start of the parameters so that + // there is a starting point for any rpHash that might be generated and so there + // is a place where parameter encryption would start + command->parameterBuffer = command->responseBuffer - command->parameterSize; + + // Session nonces should be updated before parameter encryption + if(command->tag == TPM_ST_SESSIONS) + { + UpdateAllNonceTPM(command); + + // Encrypt first parameter if applicable. Parameter encryption should + // happen after nonce update and before any rpHash is computed. + // If the encrypt session is associated with a handle, the authValue of + // this handle will be concatenated with sessionKey to generate + // encryption key, no matter if the handle is the session bound entity + // or not. The authValue is added to sessionKey only when the authValue + // is available. + if(s_encryptSessionIndex != UNDEFINED_INDEX) + { + UINT32 size; + TPM2B_AUTH extraKey; + // + extraKey.b.size = 0; + // If this is an authorization session, include the authValue in the + // generation of the encryption key + if(s_associatedHandles[s_encryptSessionIndex] != TPM_RH_UNASSIGNED) + { + EntityGetAuthValue(s_associatedHandles[s_encryptSessionIndex], + &extraKey); + } + size = EncryptSize(command->index); + // This function operates on internally-generated data that is + // expected to be well-formed for parameter encryption. + // In the event that there is a bug elsewhere in the code and the + // input data is not well-formed, CryptParameterEncryption will + // put the TPM into failure mode. + CryptParameterEncryption(s_sessionHandles[s_encryptSessionIndex], + &s_nonceCaller[s_encryptSessionIndex].b, + command->parameterSize, + (UINT16)size, + &extraKey, + command->parameterBuffer); + if(g_inFailureMode) + { + result = TPM_RC_FAILURE; + goto Cleanup; + } + } + } + // Audit sessions should be processed regardless of the tag because + // a command with no session may cause a change of the exclusivity state. + UpdateAuditSessionStatus(command); +#if CC_GetCommandAuditDigest + // Command Audit + if(CommandAuditIsRequired(command->index)) + CommandAudit(command); +#endif + // Process command with sessions. + if(command->tag == TPM_ST_SESSIONS) + { + UINT32 i; + // + pAssert(command->sessionNum > 0); + + // Iterate over each session in the command session area, and create + // corresponding sessions for response. + for(i = 0; i < command->sessionNum; i++) + { + TPM2B_NONCE* nonceTPM; + TPM2B_DIGEST responseAuth; + // Make sure that continueSession is SET on any Password session. + // This makes it marginally easier for the management software + // to keep track of the closed sessions. + if(s_sessionHandles[i] == TPM_RS_PW) + { + SET_ATTRIBUTE(s_attributes[i], TPMA_SESSION, continueSession); + responseAuth.t.size = 0; + nonceTPM = (TPM2B_NONCE*)&responseAuth; + } + else + { + // Compute the response HMAC and get a pointer to the nonce used. + // This function will also update the values if needed. Note, the + nonceTPM = BuildSingleResponseAuth(command, i, &responseAuth); + } + command->authSize += + TPM2B_NONCE_Marshal(nonceTPM, &command->responseBuffer, NULL); + command->authSize += TPMA_SESSION_Marshal( + &s_attributes[i], &command->responseBuffer, NULL); + command->authSize += + TPM2B_DIGEST_Marshal(&responseAuth, &command->responseBuffer, NULL); + if(!IS_ATTRIBUTE(s_attributes[i], TPMA_SESSION, continueSession)) + SessionFlush(s_sessionHandles[i]); + } + } + +Cleanup: + return result; +} + +//*** SessionRemoveAssociationToHandle() +// This function deals with the case where an entity associated with an authorization +// is deleted during command processing. The primary use of this is to support +// UndefineSpaceSpecial(). +void SessionRemoveAssociationToHandle(TPM_HANDLE handle) +{ + UINT32 i; + // + for(i = 0; i < MAX_SESSION_NUM; i++) + { + if(s_associatedHandles[i] == handle) + { + s_associatedHandles[i] = TPM_RH_NULL; + } + } +} diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/CommandAudit.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/CommandAudit.c new file mode 100644 index 0000000..15c3dae --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/CommandAudit.c @@ -0,0 +1,255 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// This file contains the functions that support command audit. + +//** Includes +#include "Tpm.h" + +//** Functions + +//*** CommandAuditPreInstall_Init() +// This function initializes the command audit list. This function simulates +// the behavior of manufacturing. A function is used instead of a structure +// definition because this is easier than figuring out the initialization value +// for a bit array. +// +// This function would not be implemented outside of a manufacturing or +// simulation environment. +void CommandAuditPreInstall_Init(void) +{ + // Clear all the audit commands + MemorySet(gp.auditCommands, 0x00, sizeof(gp.auditCommands)); + + // TPM_CC_SetCommandCodeAuditStatus always being audited + CommandAuditSet(TPM_CC_SetCommandCodeAuditStatus); + + // Set initial command audit hash algorithm to be context integrity hash + // algorithm + gp.auditHashAlg = CONTEXT_INTEGRITY_HASH_ALG; + + // Set up audit counter to be 0 + gp.auditCounter = 0; + + // Write command audit persistent data to NV + NV_SYNC_PERSISTENT(auditCommands); + NV_SYNC_PERSISTENT(auditHashAlg); + NV_SYNC_PERSISTENT(auditCounter); + + return; +} + +//*** CommandAuditStartup() +// This function clears the command audit digest on a TPM Reset. +BOOL CommandAuditStartup(STARTUP_TYPE type // IN: start up type +) +{ + if((type != SU_RESTART) && (type != SU_RESUME)) + { + // Reset the digest size to initialize the digest + gr.commandAuditDigest.t.size = 0; + } + return TRUE; +} + +//*** CommandAuditSet() +// This function will SET the audit flag for a command. This function +// will not SET the audit flag for a command that is not implemented. This +// ensures that the audit status is not SET when TPM2_GetCapability() is +// used to read the list of audited commands. +// +// This function is only used by TPM2_SetCommandCodeAuditStatus(). +// +// The actions in TPM2_SetCommandCodeAuditStatus() are expected to cause the +// changes to be saved to NV after it is setting and clearing bits. +// Return Type: BOOL +// TRUE(1) command code audit status was changed +// FALSE(0) command code audit status was not changed +BOOL CommandAuditSet(TPM_CC commandCode // IN: command code +) +{ + COMMAND_INDEX commandIndex = CommandCodeToCommandIndex(commandCode); + + // Only SET a bit if the corresponding command is implemented + if(commandIndex != UNIMPLEMENTED_COMMAND_INDEX) + { + // Can't audit shutdown + if(commandCode != TPM_CC_Shutdown) + { + if(!TEST_BIT(commandIndex, gp.auditCommands)) + { + // Set bit + SET_BIT(commandIndex, gp.auditCommands); + return TRUE; + } + } + } + // No change + return FALSE; +} + +//*** CommandAuditClear() +// This function will CLEAR the audit flag for a command. It will not CLEAR the +// audit flag for TPM_CC_SetCommandCodeAuditStatus(). +// +// This function is only used by TPM2_SetCommandCodeAuditStatus(). +// +// The actions in TPM2_SetCommandCodeAuditStatus() are expected to cause the +// changes to be saved to NV after it is setting and clearing bits. +// Return Type: BOOL +// TRUE(1) command code audit status was changed +// FALSE(0) command code audit status was not changed +BOOL CommandAuditClear(TPM_CC commandCode // IN: command code +) +{ + COMMAND_INDEX commandIndex = CommandCodeToCommandIndex(commandCode); + + // Do nothing if the command is not implemented + if(commandIndex != UNIMPLEMENTED_COMMAND_INDEX) + { + // The bit associated with TPM_CC_SetCommandCodeAuditStatus() cannot be + // cleared + if(commandCode != TPM_CC_SetCommandCodeAuditStatus) + { + if(TEST_BIT(commandIndex, gp.auditCommands)) + { + // Clear bit + CLEAR_BIT(commandIndex, gp.auditCommands); + return TRUE; + } + } + } + // No change + return FALSE; +} + +//*** CommandAuditIsRequired() +// This function indicates if the audit flag is SET for a command. +// Return Type: BOOL +// TRUE(1) command is audited +// FALSE(0) command is not audited +BOOL CommandAuditIsRequired(COMMAND_INDEX commandIndex // IN: command index +) +{ + // Check the bit map. If the bit is SET, command audit is required + return (TEST_BIT(commandIndex, gp.auditCommands)); +} + +//*** CommandAuditCapGetCCList() +// This function returns a list of commands that have their audit bit SET. +// +// The list starts at the input commandCode. +// Return Type: TPMI_YES_NO +// YES if there are more command code available +// NO all the available command code has been returned +TPMI_YES_NO +CommandAuditCapGetCCList(TPM_CC commandCode, // IN: start command code + UINT32 count, // IN: count of returned TPM_CC + TPML_CC* commandList // OUT: list of TPM_CC +) +{ + TPMI_YES_NO more = NO; + COMMAND_INDEX commandIndex; + + // Initialize output handle list + commandList->count = 0; + + // The maximum count of command we may return is MAX_CAP_CC + if(count > MAX_CAP_CC) + count = MAX_CAP_CC; + + // Find the implemented command that has a command code that is the same or + // higher than the input + // Collect audit commands + for(commandIndex = GetClosestCommandIndex(commandCode); + commandIndex != UNIMPLEMENTED_COMMAND_INDEX; + commandIndex = GetNextCommandIndex(commandIndex)) + { + if(CommandAuditIsRequired(commandIndex)) + { + if(commandList->count < count) + { + // If we have not filled up the return list, add this command + // code to its + TPM_CC cc = + GET_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, commandIndex); + if(IS_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, V)) + cc += (1 << 29); + commandList->commandCodes[commandList->count] = cc; + commandList->count++; + } + else + { + // If the return list is full but we still have command + // available, report this and stop iterating + more = YES; + break; + } + } + } + + return more; +} + +//*** CommandAuditGetDigest +// This command is used to create a digest of the commands being audited. The +// commands are processed in ascending numeric order with a list of TPM_CC being +// added to a hash. This operates as if all the audited command codes were +// concatenated and then hashed. +void CommandAuditGetDigest(TPM2B_DIGEST* digest // OUT: command digest +) +{ + TPM_CC commandCode; + COMMAND_INDEX commandIndex; + HASH_STATE hashState; + + // Start hash + digest->t.size = CryptHashStart(&hashState, gp.auditHashAlg); + + // Add command code + for(commandIndex = 0; commandIndex < COMMAND_COUNT; commandIndex++) + { + if(CommandAuditIsRequired(commandIndex)) + { + commandCode = GetCommandCode(commandIndex); + CryptDigestUpdateInt(&hashState, sizeof(commandCode), commandCode); + } + } + + // Complete hash + CryptHashEnd2B(&hashState, &digest->b); + + return; +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/DA.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/DA.c new file mode 100644 index 0000000..8d2c8cb --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/DA.c @@ -0,0 +1,224 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// This file contains the functions and data definitions relating to the +// dictionary attack logic. + +//** Includes and Data Definitions +#define DA_C +#include "Tpm.h" + +//** Functions + +//*** DAPreInstall_Init() +// This function initializes the DA parameters to their manufacturer-default +// values. The default values are determined by a platform-specific specification. +// +// This function should not be called outside of a manufacturing or simulation +// environment. +// +// The DA parameters will be restored to these initial values by TPM2_Clear(). +void DAPreInstall_Init(void) +{ + gp.failedTries = 0; + gp.maxTries = 3; + gp.recoveryTime = 1000; // in seconds (~16.67 minutes) + gp.lockoutRecovery = 1000; // in seconds + gp.lockOutAuthEnabled = TRUE; // Use of lockoutAuth is enabled + + // Record persistent DA parameter changes to NV + NV_SYNC_PERSISTENT(failedTries); + NV_SYNC_PERSISTENT(maxTries); + NV_SYNC_PERSISTENT(recoveryTime); + NV_SYNC_PERSISTENT(lockoutRecovery); + NV_SYNC_PERSISTENT(lockOutAuthEnabled); + + return; +} + +//*** DAStartup() +// This function is called by TPM2_Startup() to initialize the DA parameters. +// In the case of Startup(CLEAR), use of lockoutAuth will be enabled if the +// lockout recovery time is 0. Otherwise, lockoutAuth will not be enabled until +// the TPM has been continuously powered for the lockoutRecovery time. +// +// This function requires that NV be available and not rate limiting. +BOOL DAStartup(STARTUP_TYPE type // IN: startup type +) +{ + NOT_REFERENCED(type); +#if !ACCUMULATE_SELF_HEAL_TIMER + _plat__TimerWasReset(); + s_selfHealTimer = 0; + s_lockoutTimer = 0; +#else + if(_plat__TimerWasReset()) + { + if(!NV_IS_ORDERLY) + { + // If shutdown was not orderly, then don't really know if go.time has + // any useful value so reset the timer to 0. This is what the tick + // was reset to + s_selfHealTimer = 0; + s_lockoutTimer = 0; + } + else + { + // If we know how much time was accumulated at the last orderly shutdown + // subtract that from the saved timer values so that they effectively + // have the accumulated values + s_selfHealTimer -= go.time; + s_lockoutTimer -= go.time; + } + } +#endif + + // For any Startup(), if lockoutRecovery is 0, enable use of lockoutAuth. + if(gp.lockoutRecovery == 0) + { + gp.lockOutAuthEnabled = TRUE; + // Record the changes to NV + NV_SYNC_PERSISTENT(lockOutAuthEnabled); + } + + // If DA has not been disabled and the previous shutdown is not orderly + // failedTries is not already at its maximum then increment 'failedTries' + if(gp.recoveryTime != 0 && gp.failedTries < gp.maxTries + && !IS_ORDERLY(g_prevOrderlyState)) + { +#if USE_DA_USED + gp.failedTries += g_daUsed; + g_daUsed = FALSE; +#else + gp.failedTries++; +#endif + // Record the change to NV + NV_SYNC_PERSISTENT(failedTries); + } + // Before Startup, the TPM will not do clock updates. At startup, need to + // do a time update which will do the DA update. + TimeUpdate(); + + return TRUE; +} + +//*** DARegisterFailure() +// This function is called when an authorization failure occurs on an entity +// that is subject to dictionary-attack protection. When a DA failure is +// triggered, register the failure by resetting the relevant self-healing +// timer to the current time. +void DARegisterFailure(TPM_HANDLE handle // IN: handle for failure +) +{ + // Reset the timer associated with lockout if the handle is the lockoutAuth. + if(handle == TPM_RH_LOCKOUT) + s_lockoutTimer = g_time; + else + s_selfHealTimer = g_time; + return; +} + +//*** DASelfHeal() +// This function is called to check if sufficient time has passed to allow +// decrement of failedTries or to re-enable use of lockoutAuth. +// +// This function should be called when the time interval is updated. +void DASelfHeal(void) +{ + // Regular authorization self healing logic + // If no failed authorization tries, do nothing. Otherwise, try to + // decrease failedTries + if(gp.failedTries != 0) + { + // if recovery time is 0, DA logic has been disabled. Clear failed tries + // immediately + if(gp.recoveryTime == 0) + { + gp.failedTries = 0; + // Update NV record + NV_SYNC_PERSISTENT(failedTries); + } + else + { + UINT64 decreaseCount; + // Errata eliminates this code +#if 0 + // In the unlikely event that failedTries should become larger than + // maxTries + if(gp.failedTries > gp.maxTries) + gp.failedTries = gp.maxTries; +#endif + // How much can failedTries be decreased + + // Cast s_selfHealTimer to an int in case it became negative at + // startup + decreaseCount = + ((g_time - (INT64)s_selfHealTimer) / 1000) / gp.recoveryTime; + + if(gp.failedTries <= (UINT32)decreaseCount) + // should not set failedTries below zero + gp.failedTries = 0; + else + gp.failedTries -= (UINT32)decreaseCount; + + // the cast prevents overflow of the product + s_selfHealTimer += (decreaseCount * (UINT64)gp.recoveryTime) * 1000; + if(decreaseCount != 0) + // If there was a change to the failedTries, record the changes + // to NV + NV_SYNC_PERSISTENT(failedTries); + } + } + + // LockoutAuth self healing logic + // If lockoutAuth is enabled, do nothing. Otherwise, try to see if we + // may enable it + if(!gp.lockOutAuthEnabled) + { + // if lockout authorization recovery time is 0, a reboot is required to + // re-enable use of lockout authorization. Self-healing would not + // apply in this case. + if(gp.lockoutRecovery != 0) + { + if(((g_time - (INT64)s_lockoutTimer) / 1000) >= gp.lockoutRecovery) + { + gp.lockOutAuthEnabled = TRUE; + // Record the changes to NV + NV_SYNC_PERSISTENT(lockOutAuthEnabled); + } + } + } + return; +} diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/Hierarchy.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/Hierarchy.c new file mode 100644 index 0000000..a06759d --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/Hierarchy.c @@ -0,0 +1,226 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// This file contains the functions used for managing and accessing the +// hierarchy-related values. + +//** Includes + +#include "Tpm.h" + +//** Functions + +//*** HierarchyPreInstall() +// This function performs the initialization functions for the hierarchy +// when the TPM is simulated. This function should not be called if the +// TPM is not in a manufacturing mode at the manufacturer, or in a simulated +// environment. +void HierarchyPreInstall_Init(void) +{ + // Allow lockout clear command + gp.disableClear = FALSE; + + // Initialize Primary Seeds + gp.EPSeed.t.size = sizeof(gp.EPSeed.t.buffer); + gp.SPSeed.t.size = sizeof(gp.SPSeed.t.buffer); + gp.PPSeed.t.size = sizeof(gp.PPSeed.t.buffer); +#if(defined USE_PLATFORM_EPS) && (USE_PLATFORM_EPS != NO) + _plat__GetEPS(gp.EPSeed.t.size, gp.EPSeed.t.buffer); +#else + CryptRandomGenerate(gp.EPSeed.t.size, gp.EPSeed.t.buffer); +#endif + CryptRandomGenerate(gp.SPSeed.t.size, gp.SPSeed.t.buffer); + CryptRandomGenerate(gp.PPSeed.t.size, gp.PPSeed.t.buffer); + + // Initialize owner, endorsement and lockout authorization + gp.ownerAuth.t.size = 0; + gp.endorsementAuth.t.size = 0; + gp.lockoutAuth.t.size = 0; + + // Initialize owner, endorsement, and lockout policy + gp.ownerAlg = TPM_ALG_NULL; + gp.ownerPolicy.t.size = 0; + gp.endorsementAlg = TPM_ALG_NULL; + gp.endorsementPolicy.t.size = 0; + gp.lockoutAlg = TPM_ALG_NULL; + gp.lockoutPolicy.t.size = 0; + + // Initialize ehProof, shProof and phProof + gp.phProof.t.size = sizeof(gp.phProof.t.buffer); + gp.shProof.t.size = sizeof(gp.shProof.t.buffer); + gp.ehProof.t.size = sizeof(gp.ehProof.t.buffer); + CryptRandomGenerate(gp.phProof.t.size, gp.phProof.t.buffer); + CryptRandomGenerate(gp.shProof.t.size, gp.shProof.t.buffer); + CryptRandomGenerate(gp.ehProof.t.size, gp.ehProof.t.buffer); + + // Write hierarchy data to NV + NV_SYNC_PERSISTENT(disableClear); + NV_SYNC_PERSISTENT(EPSeed); + NV_SYNC_PERSISTENT(SPSeed); + NV_SYNC_PERSISTENT(PPSeed); + NV_SYNC_PERSISTENT(ownerAuth); + NV_SYNC_PERSISTENT(endorsementAuth); + NV_SYNC_PERSISTENT(lockoutAuth); + NV_SYNC_PERSISTENT(ownerAlg); + NV_SYNC_PERSISTENT(ownerPolicy); + NV_SYNC_PERSISTENT(endorsementAlg); + NV_SYNC_PERSISTENT(endorsementPolicy); + NV_SYNC_PERSISTENT(lockoutAlg); + NV_SYNC_PERSISTENT(lockoutPolicy); + NV_SYNC_PERSISTENT(phProof); + NV_SYNC_PERSISTENT(shProof); + NV_SYNC_PERSISTENT(ehProof); + + return; +} + +//*** HierarchyStartup() +// This function is called at TPM2_Startup() to initialize the hierarchy +// related values. +BOOL HierarchyStartup(STARTUP_TYPE type // IN: start up type +) +{ + // phEnable is SET on any startup + g_phEnable = TRUE; + + // Reset platformAuth, platformPolicy; enable SH and EH at TPM_RESET and + // TPM_RESTART + if(type != SU_RESUME) + { + gc.platformAuth.t.size = 0; + gc.platformPolicy.t.size = 0; + gc.platformAlg = TPM_ALG_NULL; + + // enable the storage and endorsement hierarchies and the platformNV + gc.shEnable = gc.ehEnable = gc.phEnableNV = TRUE; + } + + // nullProof and nullSeed are updated at every TPM_RESET + if((type != SU_RESTART) && (type != SU_RESUME)) + { + gr.nullProof.t.size = sizeof(gr.nullProof.t.buffer); + CryptRandomGenerate(gr.nullProof.t.size, gr.nullProof.t.buffer); + gr.nullSeed.t.size = sizeof(gr.nullSeed.t.buffer); + CryptRandomGenerate(gr.nullSeed.t.size, gr.nullSeed.t.buffer); + } + + return TRUE; +} + +//*** HierarchyGetProof() +// This function finds the proof value associated with a hierarchy.It returns a +// pointer to the proof value. +TPM2B_PROOF* HierarchyGetProof(TPMI_RH_HIERARCHY hierarchy // IN: hierarchy constant +) +{ + TPM2B_PROOF* proof = NULL; + + switch(hierarchy) + { + case TPM_RH_PLATFORM: + // phProof for TPM_RH_PLATFORM + proof = &gp.phProof; + break; + case TPM_RH_ENDORSEMENT: + // ehProof for TPM_RH_ENDORSEMENT + proof = &gp.ehProof; + break; + case TPM_RH_OWNER: + // shProof for TPM_RH_OWNER + proof = &gp.shProof; + break; + default: + // nullProof for TPM_RH_NULL or anything else + proof = &gr.nullProof; + break; + } + return proof; +} + +//*** HierarchyGetPrimarySeed() +// This function returns the primary seed of a hierarchy. +TPM2B_SEED* HierarchyGetPrimarySeed(TPMI_RH_HIERARCHY hierarchy // IN: hierarchy +) +{ + TPM2B_SEED* seed = NULL; + switch(hierarchy) + { + case TPM_RH_PLATFORM: + seed = &gp.PPSeed; + break; + case TPM_RH_OWNER: + seed = &gp.SPSeed; + break; + case TPM_RH_ENDORSEMENT: + seed = &gp.EPSeed; + break; + default: + seed = &gr.nullSeed; + break; + } + return seed; +} + +//*** HierarchyIsEnabled() +// This function checks to see if a hierarchy is enabled. +// NOTE: The TPM_RH_NULL hierarchy is always enabled. +// Return Type: BOOL +// TRUE(1) hierarchy is enabled +// FALSE(0) hierarchy is disabled +BOOL HierarchyIsEnabled(TPMI_RH_HIERARCHY hierarchy // IN: hierarchy +) +{ + BOOL enabled = FALSE; + + switch(hierarchy) + { + case TPM_RH_PLATFORM: + enabled = g_phEnable; + break; + case TPM_RH_OWNER: + enabled = gc.shEnable; + break; + case TPM_RH_ENDORSEMENT: + enabled = gc.ehEnable; + break; + case TPM_RH_NULL: + enabled = TRUE; + break; + default: + enabled = FALSE; + break; + } + return enabled; +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/NvDynamic.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/NvDynamic.c new file mode 100644 index 0000000..181d179 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/NvDynamic.c @@ -0,0 +1,1813 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction + +// The NV memory is divided into two areas: dynamic space for user defined NV +// indexes and evict objects, and reserved space for TPM persistent and state save +// data. +// +// The entries in dynamic space are a linked list of entries. Each entry has, as its +// first field, a size. If the size field is zero, it marks the end of the +// list. +// +// An Index allocation will contain an NV_INDEX structure. If the Index does not +// have the orderly attribute, the NV_INDEX is followed immediately by the NV data. +// +// An evict object entry contains a handle followed by an OBJECT structure. This +// results in both the Index and Evict Object having an identifying handle as the +// first field following the size field. +// +// When an Index has the orderly attribute, the data is kept in RAM. This RAM is +// saved to backing store in NV memory on any orderly shutdown. The entries in +// orderly memory are also a linked list using a size field as the first entry. +// +// The attributes of an orderly index are maintained in RAM memory in order to +// reduce the number of NV writes needed for orderly data. When an orderly index +// is created, an entry is made in the dynamic NV memory space that holds the Index +// authorizations (authPolicy and authValue) and the size of the data. This entry is +// only modified if the authValue of the index is changed. The more volatile data +// of the index is kept in RAM. When an orderly Index is created or deleted, the +// RAM data is copied to NV backing store so that the image in the backing store +// matches the layout of RAM. In normal operation. The RAM data is also copied on +// any orderly shutdown. In normal operation, the only other reason for writing +// to the backing store for RAM is when a counter is first written (TPMA_NV_WRITTEN +// changes from CLEAR to SET) or when a counter ""rolls over"". +// +// Static space contains items that are individually modifiable. The values are in +// the 'gp' PERSISTENT_DATA structure in RAM and mapped to locations in NV. +// + +//** Includes, Defines and Data Definitions +#define NV_C +#include "Tpm.h" +#include "Marshal.h" + +//** Local Functions + +//*** NvNext() +// This function provides a method to traverse every data entry in NV dynamic +// area. +// +// To begin with, parameter 'iter' should be initialized to NV_REF_INIT +// indicating the first element. Every time this function is called, the +// value in 'iter' would be adjusted pointing to the next element in +// traversal. If there is no next element, 'iter' value would be 0. +// This function returns the address of the 'data entry' pointed by the +// 'iter'. If there are no more elements in the set, a 0 value is returned +// indicating the end of traversal. +// +static NV_REF NvNext(NV_REF* iter, // IN/OUT: the list iterator + TPM_HANDLE* handle // OUT: the handle of the next item. +) +{ + NV_REF currentAddr; + NV_ENTRY_HEADER header; + // + // If iterator is at the beginning of list + if(*iter == NV_REF_INIT) + { + // Initialize iterator + *iter = NV_USER_DYNAMIC; + } + // Step over the size field and point to the handle + currentAddr = *iter + sizeof(UINT32); + + // read the header of the next entry + NvRead(&header, *iter, sizeof(NV_ENTRY_HEADER)); + + // if the size field is zero, then we have hit the end of the list + if(header.size == 0) + // leave the *iter pointing at the end of the list + return 0; + // advance the header by the size of the entry + *iter += header.size; + + if(handle != NULL) + *handle = header.handle; + return currentAddr; +} + +//*** NvNextByType() +// This function returns a reference to the next NV entry of the desired type +// Return Type: NV_REF +// 0 end of list +// != 0 the next entry of the indicated type +static NV_REF NvNextByType( + TPM_HANDLE* handle, // OUT: the handle of the found type or 0 + NV_REF* iter, // IN: the iterator + TPM_HT type // IN: the handle type to look for +) +{ + NV_REF addr; + TPM_HANDLE nvHandle = 0; + // + while((addr = NvNext(iter, &nvHandle)) != 0) + { + // addr: the address of the location containing the handle of the value + // iter: the next location. + if(HandleGetType(nvHandle) == type) + break; + } + if(handle != NULL) + *handle = nvHandle; + return addr; +} + +//*** NvNextIndex() +// This function returns the reference to the next NV Index entry. A value +// of 0 indicates the end of the list. +// Return Type: NV_REF +// 0 end of list +// != 0 the next reference +#define NvNextIndex(handle, iter) NvNextByType(handle, iter, TPM_HT_NV_INDEX) + +//*** NvNextEvict() +// This function returns the offset in NV of the next evict object entry. A value +// of 0 indicates the end of the list. +#define NvNextEvict(handle, iter) NvNextByType(handle, iter, TPM_HT_PERSISTENT) + +//*** NvGetEnd() +// Function to find the end of the NV dynamic data list +static NV_REF NvGetEnd(void) +{ + NV_REF iter = NV_REF_INIT; + NV_REF currentAddr; + // + // Scan until the next address is 0 + while((currentAddr = NvNext(&iter, NULL)) != 0) + ; + return iter; +} + +//*** NvGetFreeBytes +// This function returns the number of free octets in NV space. +static UINT32 NvGetFreeBytes(void) +{ + // This does not have an overflow issue because NvGetEnd() cannot return a value + // that is larger than s_evictNvEnd. This is because there is always a 'stop' + // word in the NV memory that terminates the search for the end before the + // value can go past s_evictNvEnd. + return s_evictNvEnd - NvGetEnd(); +} + +//*** NvTestSpace() +// This function will test if there is enough space to add a new entity. +// Return Type: BOOL +// TRUE(1) space available +// FALSE(0) no enough space +static BOOL NvTestSpace(UINT32 size, // IN: size of the entity to be added + BOOL isIndex, // IN: TRUE if the entity is an index + BOOL isCounter // IN: TRUE if the index is a counter +) +{ + UINT32 remainBytes = NvGetFreeBytes(); + UINT32 reserved = sizeof(UINT32) // size of the forward pointer + + sizeof(NV_LIST_TERMINATOR); +// +// Do a compile time sanity check on the setting for NV_MEMORY_SIZE +#if NV_MEMORY_SIZE < 1024 +# error "NV_MEMORY_SIZE probably isn't large enough" +#endif + + // For NV Index, need to make sure that we do not allocate an Index if this + // would mean that the TPM cannot allocate the minimum number of evict + // objects. + if(isIndex) + { + // Get the number of persistent objects allocated + UINT32 persistentNum = NvCapGetPersistentNumber(); + + // If we have not allocated the requisite number of evict objects, then we + // need to reserve space for them. + // NOTE: some of this is not written as simply as it might seem because + // the values are all unsigned and subtracting needs to be done carefully + // so that an underflow doesn't cause problems. + if(persistentNum < MIN_EVICT_OBJECTS) + reserved += (MIN_EVICT_OBJECTS - persistentNum) * NV_EVICT_OBJECT_SIZE; + } + // If this is not an index or is not a counter, reserve space for the + // required number of counter indexes + if(!isIndex || !isCounter) + { + // Get the number of counters + UINT32 counterNum = NvCapGetCounterNumber(); + + // If the required number of counters have not been allocated, reserved + // space for the extra needed counters + if(counterNum < MIN_COUNTER_INDICES) + reserved += (MIN_COUNTER_INDICES - counterNum) * NV_INDEX_COUNTER_SIZE; + } + // Check that the requested allocation will fit after making sure that there + // will be no chance of overflow + return ((reserved < remainBytes) && (size <= remainBytes) + && (size + reserved <= remainBytes)); +} + +//*** NvWriteNvListEnd() +// Function to write the list terminator. +NV_REF +NvWriteNvListEnd(NV_REF end) +{ + // Marker is initialized with zeros + BYTE listEndMarker[sizeof(NV_LIST_TERMINATOR)] = {0}; + UINT64 maxCount = NvReadMaxCount(); + // + // This is a constant check that can be resolved at compile time. + cAssert(sizeof(UINT64) <= sizeof(NV_LIST_TERMINATOR) - sizeof(UINT32)); + + // Copy the maxCount value to the marker buffer + MemoryCopy(&listEndMarker[sizeof(UINT32)], &maxCount, sizeof(UINT64)); + pAssert(end + sizeof(NV_LIST_TERMINATOR) <= s_evictNvEnd); + + // Write it to memory + NvWrite(end, sizeof(NV_LIST_TERMINATOR), &listEndMarker); + return end + sizeof(NV_LIST_TERMINATOR); +} + +//*** NvAdd() +// This function adds a new entity to NV. +// +// This function requires that there is enough space to add a new entity (i.e., +// that NvTestSpace() has been called and the available space is at least as +// large as the required space). +// +// The 'totalSize' will be the size of 'entity'. If a handle is added, this +// function will increase the size accordingly. +static TPM_RC NvAdd(UINT32 totalSize, // IN: total size needed for this entity For + // evict object, totalSize is the same as + // bufferSize. For NV Index, totalSize is + // bufferSize plus index data size + UINT32 bufferSize, // IN: size of initial buffer + TPM_HANDLE handle, // IN: optional handle + BYTE* entity // IN: initial buffer +) +{ + NV_REF newAddr; // IN: where the new entity will start + NV_REF nextAddr; + // + RETURN_IF_NV_IS_NOT_AVAILABLE; + + // Get the end of data list + newAddr = NvGetEnd(); + + // Step over the forward pointer + nextAddr = newAddr + sizeof(UINT32); + + // Optionally write the handle. For indexes, the handle is TPM_RH_UNASSIGNED + // so that the handle in the nvIndex is used instead of writing this value + if(handle != TPM_RH_UNASSIGNED) + { + NvWrite((UINT32)nextAddr, sizeof(TPM_HANDLE), &handle); + nextAddr += sizeof(TPM_HANDLE); + } + // Write entity data + NvWrite((UINT32)nextAddr, bufferSize, entity); + + // Advance the pointer by the amount of the total + nextAddr += totalSize; + + // Finish by writing the link value + + // Write the next offset (relative addressing) + totalSize = nextAddr - newAddr; + + // Write link value + NvWrite((UINT32)newAddr, sizeof(UINT32), &totalSize); + + // Write the list terminator + NvWriteNvListEnd(nextAddr); + + return TPM_RC_SUCCESS; +} + +//*** NvDelete() +// This function is used to delete an NV Index or persistent object from NV memory. +static TPM_RC NvDelete(NV_REF entityRef // IN: reference to entity to be deleted +) +{ + UINT32 entrySize; + // adjust entityAddr to back up and point to the forward pointer + NV_REF entryRef = entityRef - sizeof(UINT32); + NV_REF endRef = NvGetEnd(); + NV_REF nextAddr; // address of the next entry + // + RETURN_IF_NV_IS_NOT_AVAILABLE; + + // Get the offset of the next entry. That is, back up and point to the size + // field of the entry + NvRead(&entrySize, entryRef, sizeof(UINT32)); + + // The next entry after the one being deleted is at a relative offset + // from the current entry + nextAddr = entryRef + entrySize; + + // If this is not the last entry, move everything up + if(nextAddr < endRef) + { + pAssert(nextAddr > entryRef); + _plat__NvMemoryMove(nextAddr, entryRef, (endRef - nextAddr)); + } + // The end of the used space is now moved up by the amount of space we just + // reclaimed + endRef -= entrySize; + + // Write the end marker, and make the new end equal to the first byte after + // the just added end value. This will automatically update the NV value for + // maxCounter. + // NOTE: This is the call that sets flag to cause NV to be updated + endRef = NvWriteNvListEnd(endRef); + + // Clear the reclaimed memory + _plat__NvMemoryClear(endRef, entrySize); + + return TPM_RC_SUCCESS; +} + +//************************************************ +//** RAM-based NV Index Data Access Functions +//************************************************ +//*** Introduction +// The data layout in ram buffer is {size of(NV_handle + attributes + data +// NV_handle, attributes, data} +// for each NV Index data stored in RAM. +// +// NV storage associated with orderly data is updated when a NV Index is added +// but NOT when the data or attributes are changed. Orderly data is only updated +// to NV on an orderly shutdown (TPM2_Shutdown()) + +//*** NvRamNext() +// This function is used to iterate trough the list of Ram Index values. *iter needs +// to be initialized by calling +static NV_RAM_REF NvRamNext(NV_RAM_REF* iter, // IN/OUT: the list iterator + TPM_HANDLE* handle // OUT: the handle of the next item. +) +{ + NV_RAM_REF currentAddr; + NV_RAM_HEADER header; + // + // If iterator is at the beginning of list + if(*iter == NV_RAM_REF_INIT) + { + // Initialize iterator + *iter = &s_indexOrderlyRam[0]; + } + // if we are going to return what the iter is currently pointing to... + currentAddr = *iter; + + // If iterator reaches the end of NV space, then don't advance and return + // that we are at the end of the list. The end of the list occurs when + // we don't have space for a size and a handle + if(currentAddr + sizeof(NV_RAM_HEADER) > RAM_ORDERLY_END) + return NULL; + // read the header of the next entry + MemoryCopy(&header, currentAddr, sizeof(NV_RAM_HEADER)); + + // if the size field is zero, then we have hit the end of the list + if(header.size == 0) + // leave the *iter pointing at the end of the list + return NULL; + // advance the header by the size of the entry + *iter = currentAddr + header.size; + + // pAssert(*iter <= RAM_ORDERLY_END); + if(handle != NULL) + *handle = header.handle; + return currentAddr; +} + +//*** NvRamGetEnd() +// This routine performs the same function as NvGetEnd() but for the RAM data. +static NV_RAM_REF NvRamGetEnd(void) +{ + NV_RAM_REF iter = NV_RAM_REF_INIT; + NV_RAM_REF currentAddr; + // + // Scan until the next address is 0 + while((currentAddr = NvRamNext(&iter, NULL)) != 0) + ; + return iter; +} + +//*** NvRamTestSpaceIndex() +// This function indicates if there is enough RAM space to add a data for a +// new NV Index. +// Return Type: BOOL +// TRUE(1) space available +// FALSE(0) no enough space +static BOOL NvRamTestSpaceIndex( + UINT32 size // IN: size of the data to be added to RAM +) +{ + UINT32 remaining = (UINT32)(RAM_ORDERLY_END - NvRamGetEnd()); + UINT32 needed = sizeof(NV_RAM_HEADER) + size; + // + // NvRamGetEnd points to the next available byte. + return remaining >= needed; +} + +//*** NvRamGetIndex() +// This function returns the offset of NV data in the RAM buffer +// +// This function requires that NV Index is in RAM. That is, the +// index must be known to exist. +static NV_RAM_REF NvRamGetIndex(TPMI_RH_NV_INDEX handle // IN: NV handle +) +{ + NV_RAM_REF iter = NV_RAM_REF_INIT; + NV_RAM_REF currentAddr; + TPM_HANDLE foundHandle; + // + while((currentAddr = NvRamNext(&iter, &foundHandle)) != 0) + { + if(handle == foundHandle) + break; + } + return currentAddr; +} + +//*** NvUpdateIndexOrderlyData() +// This function is used to cause an update of the orderly data to the NV backing +// store. +void NvUpdateIndexOrderlyData(void) +{ + // Write reserved RAM space to NV + NvWrite(NV_INDEX_RAM_DATA, sizeof(s_indexOrderlyRam), s_indexOrderlyRam); +} + +//*** NvAddRAM() +// This function adds a new data area to RAM. +// +// This function requires that enough free RAM space is available to add +// the new data. +// +// This function should be called after the NV Index space has been updated +// and the index removed. This insures that NV is available so that checking +// for NV availability is not required during this function. +static void NvAddRAM(TPMS_NV_PUBLIC* index // IN: the index descriptor +) +{ + NV_RAM_HEADER header; + NV_RAM_REF end = NvRamGetEnd(); + // + header.size = sizeof(NV_RAM_HEADER) + index->dataSize; + header.handle = index->nvIndex; + MemoryCopy(&header.attributes, &index->attributes, sizeof(TPMA_NV)); + + pAssert(ORDERLY_RAM_ADDRESS_OK(end, header.size)); + + // Copy the header to the memory + MemoryCopy(end, &header, sizeof(NV_RAM_HEADER)); + + // Clear the data area (just in case) + MemorySet(end + sizeof(NV_RAM_HEADER), 0, index->dataSize); + + // Step over this new entry + end += header.size; + + // If the end marker will fit, add it + if(end + sizeof(UINT32) < RAM_ORDERLY_END) + MemorySet(end, 0, sizeof(UINT32)); + // Write reserved RAM space to NV to reflect the newly added NV Index + SET_NV_UPDATE(UT_ORDERLY); + + return; +} + +//*** NvDeleteRAM() +// This function is used to delete a RAM-backed NV Index data area. +// The space used by the entry are overwritten by the contents of the +// Index data that comes after (the data is moved up to fill the hole left +// by removing this index. The reclaimed space is cleared to zeros. +// This function assumes the data of NV Index exists in RAM. +// +// This function should be called after the NV Index space has been updated +// and the index removed. This insures that NV is available so that checking +// for NV availability is not required during this function. +static void NvDeleteRAM(TPMI_RH_NV_INDEX handle // IN: NV handle +) +{ + NV_RAM_REF nodeAddress; + NV_RAM_REF nextNode; + UINT32 size; + NV_RAM_REF lastUsed = NvRamGetEnd(); + // + nodeAddress = NvRamGetIndex(handle); + + pAssert(nodeAddress != 0); + + // Get node size + MemoryCopy(&size, nodeAddress, sizeof(size)); + + // Get the offset of next node + nextNode = nodeAddress + size; + + // Copy the data + MemoryCopy(nodeAddress, nextNode, (int)(lastUsed - nextNode)); + + // Clear out the reclaimed space + MemorySet(lastUsed - size, 0, size); + + // Write reserved RAM space to NV to reflect the newly delete NV Index + SET_NV_UPDATE(UT_ORDERLY); + + return; +} + +//*** NvReadIndex() +// This function is used to read the NV Index NV_INDEX. This is used so that the +// index information can be compressed and only this function would be needed +// to decompress it. Mostly, compression would only be able to save the space +// needed by the policy. +void NvReadNvIndexInfo(NV_REF ref, // IN: points to NV where index is located + NV_INDEX* nvIndex // OUT: place to receive index data +) +{ + pAssert(nvIndex != NULL); + NvRead(nvIndex, ref, sizeof(NV_INDEX)); + return; +} + +//*** NvReadObject() +// This function is used to read a persistent object. This is used so that the +// object information can be compressed and only this function would be needed +// to uncompress it. +void NvReadObject(NV_REF ref, // IN: points to NV where index is located + OBJECT* object // OUT: place to receive the object data +) +{ + NvRead(object, (ref + sizeof(TPM_HANDLE)), sizeof(OBJECT)); + return; +} + +//*** NvFindEvict() +// This function will return the NV offset of an evict object +// Return Type: UINT32 +// 0 evict object not found +// != 0 offset of evict object +static NV_REF NvFindEvict(TPM_HANDLE nvHandle, OBJECT* object) +{ + NV_REF found = NvFindHandle(nvHandle); + // + // If we found the handle and the request included an object pointer, fill it in + if(found != 0 && object != NULL) + NvReadObject(found, object); + return found; +} + +//*** NvIndexIsDefined() +// See if an index is already defined +BOOL NvIndexIsDefined(TPM_HANDLE nvHandle // IN: Index to look for +) +{ + return (NvFindHandle(nvHandle) != 0); +} + +//*** NvConditionallyWrite() +// Function to check if the data to be written has changed +// and write it if it has +// Return Type: TPM_RC +// TPM_RC_NV_RATE NV is unavailable because of rate limit +// TPM_RC_NV_UNAVAILABLE NV is inaccessible +static TPM_RC NvConditionallyWrite(NV_REF entryAddr, // IN: stating address + UINT32 size, // IN: size of the data to write + void* data // IN: the data to write +) +{ + // If the index data is actually changed, then a write to NV is required + if(_plat__NvIsDifferent(entryAddr, size, data)) + { + // Write the data if NV is available + if(g_NvStatus == TPM_RC_SUCCESS) + { + NvWrite(entryAddr, size, data); + } + return g_NvStatus; + } + return TPM_RC_SUCCESS; +} + +//*** NvReadNvIndexAttributes() +// This function returns the attributes of an NV Index. +static TPMA_NV NvReadNvIndexAttributes(NV_REF locator // IN: reference to an NV index +) +{ + TPMA_NV attributes; + // + NvRead(&attributes, + locator + offsetof(NV_INDEX, publicArea.attributes), + sizeof(TPMA_NV)); + return attributes; +} + +//*** NvReadRamIndexAttributes() +// This function returns the attributes from the RAM header structure. This function +// is used to deal with the fact that the header structure is only byte aligned. +static TPMA_NV NvReadRamIndexAttributes( + NV_RAM_REF ref // IN: pointer to a NV_RAM_HEADER +) +{ + TPMA_NV attributes; + // + MemoryCopy( + &attributes, ref + offsetof(NV_RAM_HEADER, attributes), sizeof(TPMA_NV)); + return attributes; +} + +//*** NvWriteNvIndexAttributes() +// This function is used to write just the attributes of an index to NV. +// Return type: TPM_RC +// TPM_RC_NV_RATE NV is rate limiting so retry +// TPM_RC_NV_UNAVAILABLE NV is not available +static TPM_RC NvWriteNvIndexAttributes(NV_REF locator, // IN: location of the index + TPMA_NV attributes // IN: attributes to write +) +{ + return NvConditionallyWrite(locator + offsetof(NV_INDEX, publicArea.attributes), + sizeof(TPMA_NV), + &attributes); +} + +//*** NvWriteRamIndexAttributes() +// This function is used to write the index attributes into an unaligned structure +static void NvWriteRamIndexAttributes( + NV_RAM_REF ref, // IN: address of the header + TPMA_NV attributes // IN: the attributes to write +) +{ + MemoryCopy( + ref + offsetof(NV_RAM_HEADER, attributes), &attributes, sizeof(TPMA_NV)); + return; +} + +//************************************************ +//** Externally Accessible Functions +//************************************************ + +//*** NvIsPlatformPersistentHandle() +// This function indicates if a handle references a persistent object in the +// range belonging to the platform. +// Return Type: BOOL +// TRUE(1) handle references a platform persistent object +// FALSE(0) handle does not reference platform persistent object +BOOL NvIsPlatformPersistentHandle(TPM_HANDLE handle // IN: handle +) +{ + return (handle >= PLATFORM_PERSISTENT && handle <= PERSISTENT_LAST); +} + +//*** NvIsOwnerPersistentHandle() +// This function indicates if a handle references a persistent object in the +// range belonging to the owner. +// Return Type: BOOL +// TRUE(1) handle is owner persistent handle +// FALSE(0) handle is not owner persistent handle and may not be +// a persistent handle at all +BOOL NvIsOwnerPersistentHandle(TPM_HANDLE handle // IN: handle +) +{ + return (handle >= PERSISTENT_FIRST && handle < PLATFORM_PERSISTENT); +} + +//*** NvIndexIsAccessible() +// +// This function validates that a handle references a defined NV Index and +// that the Index is currently accessible. +// Return Type: TPM_RC +// TPM_RC_HANDLE the handle points to an undefined NV Index +// If shEnable is CLEAR, this would include an index +// created using ownerAuth. If phEnableNV is CLEAR, +// this would include and index created using +// platformAuth +// TPM_RC_NV_READLOCKED Index is present but locked for reading and command +// does not write to the index +// TPM_RC_NV_WRITELOCKED Index is present but locked for writing and command +// writes to the index +TPM_RC +NvIndexIsAccessible(TPMI_RH_NV_INDEX handle // IN: handle +) +{ + NV_INDEX* nvIndex = NvGetIndexInfo(handle, NULL); + // + if(nvIndex == NULL) + // If index is not found, return TPM_RC_HANDLE + return TPM_RC_HANDLE; + if(gc.shEnable == FALSE || gc.phEnableNV == FALSE) + { + // if shEnable is CLEAR, an ownerCreate NV Index should not be + // indicated as present + if(!IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, PLATFORMCREATE)) + { + if(gc.shEnable == FALSE) + return TPM_RC_HANDLE; + } + // if phEnableNV is CLEAR, a platform created Index should not + // be visible + else if(gc.phEnableNV == FALSE) + return TPM_RC_HANDLE; + } +#if 0 // Writelock test for debug + // If the Index is write locked and this is an NV Write operation... + if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITELOCKED) + && IsWriteOperation(commandIndex)) + { + // then return a locked indication unless the command is TPM2_NV_WriteLock + if(GetCommandCode(commandIndex) != TPM_CC_NV_WriteLock) + return TPM_RC_NV_LOCKED; + return TPM_RC_SUCCESS; + } +#endif +#if 0 // Readlock Test for debug + // If the Index is read locked and this is an NV Read operation... + if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, READLOCKED) + && IsReadOperation(commandIndex)) + { + // then return a locked indication unless the command is TPM2_NV_ReadLock + if(GetCommandCode(commandIndex) != TPM_CC_NV_ReadLock) + return TPM_RC_NV_LOCKED; + } +#endif + // NV Index is accessible + return TPM_RC_SUCCESS; +} + +//*** NvGetEvictObject() +// This function is used to dereference an evict object handle and get a pointer +// to the object. +// Return Type: TPM_RC +// TPM_RC_HANDLE the handle does not point to an existing +// persistent object +TPM_RC +NvGetEvictObject(TPM_HANDLE handle, // IN: handle + OBJECT* object // OUT: object data +) +{ + NV_REF entityAddr; // offset points to the entity + // + // Find the address of evict object and copy to object + entityAddr = NvFindEvict(handle, object); + + // whether there is an error or not, make sure that the evict + // status of the object is set so that the slot will get freed on exit + // Must do this after NvFindEvict loads the object + object->attributes.evict = SET; + + // If handle is not found, return an error + if(entityAddr == 0) + return TPM_RC_HANDLE; + return TPM_RC_SUCCESS; +} + +//*** NvIndexCacheInit() +// Function to initialize the Index cache +void NvIndexCacheInit(void) +{ + s_cachedNvRef = NV_REF_INIT; + s_cachedNvRamRef = NV_RAM_REF_INIT; + s_cachedNvIndex.publicArea.nvIndex = TPM_RH_UNASSIGNED; + return; +} + +//*** NvGetIndexData() +// This function is used to access the data in an NV Index. The data is returned +// as a byte sequence. +// +// This function requires that the NV Index be defined, and that the +// required data is within the data range. It also requires that TPMA_NV_WRITTEN +// of the Index is SET. +void NvGetIndexData(NV_INDEX* nvIndex, // IN: the in RAM index descriptor + NV_REF locator, // IN: where the data is located + UINT32 offset, // IN: offset of NV data + UINT16 size, // IN: number of octets of NV data to read + void* data // OUT: data buffer +) +{ + TPMA_NV nvAttributes; + // + pAssert(nvIndex != NULL); + + nvAttributes = nvIndex->publicArea.attributes; + + pAssert(IS_ATTRIBUTE(nvAttributes, TPMA_NV, WRITTEN)); + + if(IS_ATTRIBUTE(nvAttributes, TPMA_NV, ORDERLY)) + { + // Get data from RAM buffer + NV_RAM_REF ramAddr = NvRamGetIndex(nvIndex->publicArea.nvIndex); + pAssert(ramAddr != 0 + && (size <= ((NV_RAM_HEADER*)ramAddr)->size - sizeof(NV_RAM_HEADER) + - offset)); + MemoryCopy(data, ramAddr + sizeof(NV_RAM_HEADER) + offset, size); + } + else + { + // Validate that read falls within range of the index + pAssert(offset <= nvIndex->publicArea.dataSize + && size <= (nvIndex->publicArea.dataSize - offset)); + NvRead(data, locator + sizeof(NV_INDEX) + offset, size); + } + return; +} + +//*** NvHashIndexData() +// This function adds Index data to a hash. It does this in parts to avoid large stack +// buffers. +void NvHashIndexData(HASH_STATE* hashState, // IN: Initialized hash state + NV_INDEX* nvIndex, // IN: Index + NV_REF locator, // IN: where the data is located + UINT32 offset, // IN: starting offset + UINT16 size // IN: amount to hash +) +{ +#define BUFFER_SIZE 64 + BYTE buffer[BUFFER_SIZE]; + if(offset > nvIndex->publicArea.dataSize) + return; + // Make sure that we don't try to read off the end. + if((offset + size) > nvIndex->publicArea.dataSize) + size = nvIndex->publicArea.dataSize - (UINT16)offset; +#if BUFFER_SIZE >= MAX_NV_INDEX_SIZE + NvGetIndexData(nvIndex, locator, offset, size, buffer); + CryptDigestUpdate(hashState, size, buffer); +#else + { + INT16 i; + UINT16 readSize; + // + for(i = size; i > 0; offset += readSize, i -= readSize) + { + readSize = (i < BUFFER_SIZE) ? i : BUFFER_SIZE; + NvGetIndexData(nvIndex, locator, offset, readSize, buffer); + CryptDigestUpdate(hashState, readSize, buffer); + } + } +#endif // BUFFER_SIZE >= MAX_NV_INDEX_SIZE +#undef BUFFER_SIZE +} + +//*** NvGetUINT64Data() +// Get data in integer format of a bit or counter NV Index. +// +// This function requires that the NV Index is defined and that the NV Index +// previously has been written. +UINT64 +NvGetUINT64Data(NV_INDEX* nvIndex, // IN: the in RAM index descriptor + NV_REF locator // IN: where index exists in NV +) +{ + UINT64 intVal; + // + // Read the value and convert it to internal format + NvGetIndexData(nvIndex, locator, 0, 8, &intVal); + return BYTE_ARRAY_TO_UINT64(((BYTE*)&intVal)); +} + +//*** NvWriteIndexAttributes() +// This function is used to write just the attributes of an index. +// Return type: TPM_RC +// TPM_RC_NV_RATE NV is rate limiting so retry +// TPM_RC_NV_UNAVAILABLE NV is not available +TPM_RC +NvWriteIndexAttributes(TPM_HANDLE handle, + NV_REF locator, // IN: location of the index + TPMA_NV attributes // IN: attributes to write +) +{ + TPM_RC result; + // + if(IS_ATTRIBUTE(attributes, TPMA_NV, ORDERLY)) + { + NV_RAM_REF ram = NvRamGetIndex(handle); + NvWriteRamIndexAttributes(ram, attributes); + result = TPM_RC_SUCCESS; + } + else + { + result = NvWriteNvIndexAttributes(locator, attributes); + } + return result; +} + +//*** NvWriteIndexAuth() +// This function is used to write the authValue of an index. It is used by +// TPM2_NV_ChangeAuth() +// Return type: TPM_RC +// TPM_RC_NV_RATE NV is rate limiting so retry +// TPM_RC_NV_UNAVAILABLE NV is not available +TPM_RC +NvWriteIndexAuth(NV_REF locator, // IN: location of the index + TPM2B_AUTH* authValue // IN: the authValue to write +) +{ + TPM_RC result; + // + // If the locator is pointing to the cached index value... + if(locator == s_cachedNvRef) + { + // copy the authValue to the cached index so it will be there if we + // look for it. This is a safety thing. + MemoryCopy2B(&s_cachedNvIndex.authValue.b, + &authValue->b, + sizeof(s_cachedNvIndex.authValue.t.buffer)); + } + result = NvConditionallyWrite(locator + offsetof(NV_INDEX, authValue), + sizeof(UINT16) + authValue->t.size, + authValue); + return result; +} + +//*** NvGetIndexInfo() +// This function loads the nvIndex Info into the NV cache and returns a pointer +// to the NV_INDEX. If the returned value is zero, the index was not found. +// The 'locator' parameter, if not NULL, will be set to the offset in NV of the +// Index (the location of the handle of the Index). +// +// This function will set the index cache. If the index is orderly, the attributes +// from RAM are substituted for the attributes in the cached index +NV_INDEX* NvGetIndexInfo(TPM_HANDLE nvHandle, // IN: the index handle + NV_REF* locator // OUT: location of the index +) +{ + if(s_cachedNvIndex.publicArea.nvIndex != nvHandle) + { + s_cachedNvIndex.publicArea.nvIndex = TPM_RH_UNASSIGNED; + s_cachedNvRamRef = 0; + s_cachedNvRef = NvFindHandle(nvHandle); + if(s_cachedNvRef == 0) + return NULL; + NvReadNvIndexInfo(s_cachedNvRef, &s_cachedNvIndex); + if(IS_ATTRIBUTE(s_cachedNvIndex.publicArea.attributes, TPMA_NV, ORDERLY)) + { + s_cachedNvRamRef = NvRamGetIndex(nvHandle); + s_cachedNvIndex.publicArea.attributes = + NvReadRamIndexAttributes(s_cachedNvRamRef); + } + } + if(locator != NULL) + *locator = s_cachedNvRef; + return &s_cachedNvIndex; +} + +//*** NvWriteIndexData() +// This function is used to write NV index data. It is intended to be used to +// update the data associated with the default index. +// +// This function requires that the NV Index is defined, and the data is +// within the defined data range for the index. +// +// Index data is only written due to a command that modifies the data in a single +// index. There is no case where changes are made to multiple indexes data at the +// same time. Multiple attributes may be change but not multiple index data. This +// is important because we will normally be handling the index for which we have +// the cached pointer values. +// Return type: TPM_RC +// TPM_RC_NV_RATE NV is rate limiting so retry +// TPM_RC_NV_UNAVAILABLE NV is not available +TPM_RC +NvWriteIndexData(NV_INDEX* nvIndex, // IN: the description of the index + UINT32 offset, // IN: offset of NV data + UINT32 size, // IN: size of NV data + void* data // IN: data buffer +) +{ + TPM_RC result = TPM_RC_SUCCESS; + // + pAssert(nvIndex != NULL); + // Make sure that this is dealing with the 'default' index. + // Note: it is tempting to change the calling sequence so that the 'default' is + // presumed. + pAssert(nvIndex->publicArea.nvIndex == s_cachedNvIndex.publicArea.nvIndex); + + // Validate that write falls within range of the index + pAssert(offset <= nvIndex->publicArea.dataSize + && size <= (nvIndex->publicArea.dataSize - offset)); + + // Update TPMA_NV_WRITTEN bit if necessary + if(!IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN)) + { + // Update the in memory version of the attributes + SET_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN); + + // If this is not orderly, then update the NV version of + // the attributes + if(!IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, ORDERLY)) + { + result = NvWriteNvIndexAttributes(s_cachedNvRef, + nvIndex->publicArea.attributes); + if(result != TPM_RC_SUCCESS) + return result; + // If this is a partial write of an ordinary index, clear the whole + // index. + if(IsNvOrdinaryIndex(nvIndex->publicArea.attributes) + && (nvIndex->publicArea.dataSize > size)) + _plat__NvMemoryClear(s_cachedNvRef + sizeof(NV_INDEX), + nvIndex->publicArea.dataSize); + } + else + { + // This is orderly so update the RAM version + MemoryCopy(s_cachedNvRamRef + offsetof(NV_RAM_HEADER, attributes), + &nvIndex->publicArea.attributes, + sizeof(TPMA_NV)); + // If setting WRITTEN for an orderly counter, make sure that the + // state saved version of the counter is saved + if(IsNvCounterIndex(nvIndex->publicArea.attributes)) + SET_NV_UPDATE(UT_ORDERLY); + // If setting the written attribute on an ordinary index, make sure that + // the data is all cleared out in case there is a partial write. This + // is only necessary for ordinary indexes because all of the other types + // are always written in total. + else if(IsNvOrdinaryIndex(nvIndex->publicArea.attributes)) + MemorySet(s_cachedNvRamRef + sizeof(NV_RAM_HEADER), + 0, + nvIndex->publicArea.dataSize); + } + } + // If this is orderly data, write it to RAM + if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, ORDERLY)) + { + // Note: if this is the first write to a counter, the code above will queue + // the write to NV of the RAM data in order to update TPMA_NV_WRITTEN. In + // process of doing that write, it will also write the initial counter value + + // Update RAM + MemoryCopy(s_cachedNvRamRef + sizeof(NV_RAM_HEADER) + offset, data, size); + + // And indicate that the TPM is no longer orderly + g_clearOrderly = TRUE; + } + else + { + // Offset into the index to the first byte of the data to be written to NV + result = NvConditionallyWrite( + s_cachedNvRef + sizeof(NV_INDEX) + offset, size, data); + } + return result; +} + +//*** NvWriteUINT64Data() +// This function to write back a UINT64 value. The various UINT64 values (bits, +// counters, and PINs) are kept in canonical format but manipulate in native +// format. This takes a native format value converts it and saves it back as +// in canonical format. +// +// This function will return the value from NV or RAM depending on the type of the +// index (orderly or not) +// +TPM_RC +NvWriteUINT64Data(NV_INDEX* nvIndex, // IN: the description of the index + UINT64 intValue // IN: the value to write +) +{ + BYTE bytes[8]; + UINT64_TO_BYTE_ARRAY(intValue, bytes); + // + return NvWriteIndexData(nvIndex, 0, 8, &bytes); +} + +//*** NvGetIndexName() +// This function computes the Name of an index +// The 'name' buffer receives the bytes of the Name and the return value +// is the number of octets in the Name. +// +// This function requires that the NV Index is defined. +TPM2B_NAME* NvGetIndexName( + NV_INDEX* nvIndex, // IN: the index over which the name is to be + // computed + TPM2B_NAME* name // OUT: name of the index +) +{ + UINT16 dataSize, digestSize; + BYTE marshalBuffer[sizeof(TPMS_NV_PUBLIC)]; + BYTE* buffer; + HASH_STATE hashState; + // + // Marshal public area + buffer = marshalBuffer; + dataSize = TPMS_NV_PUBLIC_Marshal(&nvIndex->publicArea, &buffer, NULL); + + // hash public area + digestSize = CryptHashStart(&hashState, nvIndex->publicArea.nameAlg); + CryptDigestUpdate(&hashState, dataSize, marshalBuffer); + + // Complete digest leaving room for the nameAlg + CryptHashEnd(&hashState, digestSize, &name->b.buffer[2]); + + // Include the nameAlg + UINT16_TO_BYTE_ARRAY(nvIndex->publicArea.nameAlg, name->b.buffer); + name->t.size = digestSize + 2; + return name; +} + +//*** NvGetNameByIndexHandle() +// This function is used to compute the Name of an NV Index referenced by handle. +// +// The 'name' buffer receives the bytes of the Name and the return value +// is the number of octets in the Name. +// +// This function requires that the NV Index is defined. +TPM2B_NAME* NvGetNameByIndexHandle( + TPMI_RH_NV_INDEX handle, // IN: handle of the index + TPM2B_NAME* name // OUT: name of the index +) +{ + NV_INDEX* nvIndex = NvGetIndexInfo(handle, NULL); + // + return NvGetIndexName(nvIndex, name); +} + +//*** NvDefineIndex() +// This function is used to assign NV memory to an NV Index. +// +// Return Type: TPM_RC +// TPM_RC_NV_SPACE insufficient NV space +TPM_RC +NvDefineIndex(TPMS_NV_PUBLIC* publicArea, // IN: A template for an area to create. + TPM2B_AUTH* authValue // IN: The initial authorization value +) +{ + // The buffer to be written to NV memory + NV_INDEX nvIndex; // the index data + UINT16 entrySize; // size of entry + TPM_RC result; + // + entrySize = sizeof(NV_INDEX); + + // only allocate data space for indexes that are going to be written to NV. + // Orderly indexes don't need space. + if(!IS_ATTRIBUTE(publicArea->attributes, TPMA_NV, ORDERLY)) + entrySize += publicArea->dataSize; + // Check if we have enough space to create the NV Index + // In this implementation, the only resource limitation is the available NV + // space (and possibly RAM space.) Other implementation may have other + // limitation on counter or on NV slots + if(!NvTestSpace(entrySize, TRUE, IsNvCounterIndex(publicArea->attributes))) + return TPM_RC_NV_SPACE; + + // if the index to be defined is RAM backed, check RAM space availability + // as well + if(IS_ATTRIBUTE(publicArea->attributes, TPMA_NV, ORDERLY) + && !NvRamTestSpaceIndex(publicArea->dataSize)) + return TPM_RC_NV_SPACE; + // Copy input value to nvBuffer + nvIndex.publicArea = *publicArea; + + // Copy the authValue + nvIndex.authValue = *authValue; + + // Add index to NV memory + result = NvAdd(entrySize, sizeof(NV_INDEX), TPM_RH_UNASSIGNED, (BYTE*)&nvIndex); + if(result == TPM_RC_SUCCESS) + { + // If the data of NV Index is RAM backed, add the data area in RAM as well + if(IS_ATTRIBUTE(publicArea->attributes, TPMA_NV, ORDERLY)) + NvAddRAM(publicArea); + } + return result; +} + +//*** NvAddEvictObject() +// This function is used to assign NV memory to a persistent object. +// Return Type: TPM_RC +// TPM_RC_NV_HANDLE the requested handle is already in use +// TPM_RC_NV_SPACE insufficient NV space +TPM_RC +NvAddEvictObject(TPMI_DH_OBJECT evictHandle, // IN: new evict handle + OBJECT* object // IN: object to be added +) +{ + TPM_HANDLE temp = object->evictHandle; + TPM_RC result; + // + // Check if we have enough space to add the evict object + // An evict object needs 8 bytes in index table + sizeof OBJECT + // In this implementation, the only resource limitation is the available NV + // space. Other implementation may have other limitation on evict object + // handle space + if(!NvTestSpace(sizeof(OBJECT) + sizeof(TPM_HANDLE), FALSE, FALSE)) + return TPM_RC_NV_SPACE; + + // Set evict attribute and handle + object->attributes.evict = SET; + object->evictHandle = evictHandle; + + // Now put this in NV + result = NvAdd(sizeof(OBJECT), sizeof(OBJECT), evictHandle, (BYTE*)object); + + // Put things back the way they were + object->attributes.evict = CLEAR; + object->evictHandle = temp; + + return result; +} + +//*** NvDeleteIndex() +// This function is used to delete an NV Index. +// Return Type: TPM_RC +// TPM_RC_NV_UNAVAILABLE NV is not accessible +// TPM_RC_NV_RATE NV is rate limiting +TPM_RC +NvDeleteIndex(NV_INDEX* nvIndex, // IN: an in RAM index descriptor + NV_REF entityAddr // IN: location in NV +) +{ + TPM_RC result; + // + if(nvIndex != NULL) + { + // Whenever a counter is deleted, make sure that the MaxCounter value is + // updated to reflect the value + if(IsNvCounterIndex(nvIndex->publicArea.attributes) + && IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN)) + NvUpdateMaxCount(NvGetUINT64Data(nvIndex, entityAddr)); + result = NvDelete(entityAddr); + if(result != TPM_RC_SUCCESS) + return result; + // If the NV Index is RAM backed, delete the RAM data as well + if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, ORDERLY)) + NvDeleteRAM(nvIndex->publicArea.nvIndex); + NvIndexCacheInit(); + } + return TPM_RC_SUCCESS; +} + +//*** NvDeleteEvict() +// This function will delete a NV evict object. +// Will return success if object deleted or if it does not exist + +TPM_RC +NvDeleteEvict(TPM_HANDLE handle // IN: handle of entity to be deleted +) +{ + NV_REF entityAddr = NvFindEvict(handle, NULL); // pointer to entity + TPM_RC result = TPM_RC_SUCCESS; + // + if(entityAddr != 0) + result = NvDelete(entityAddr); + return result; +} + +//*** NvFlushHierarchy() +// This function will delete persistent objects belonging to the indicated hierarchy. +// If the storage hierarchy is selected, the function will also delete any +// NV Index defined using ownerAuth. +// Return Type: TPM_RC +// TPM_RC_NV_RATE NV is unavailable because of rate limit +// TPM_RC_NV_UNAVAILABLE NV is inaccessible +TPM_RC +NvFlushHierarchy(TPMI_RH_HIERARCHY hierarchy // IN: hierarchy to be flushed. +) +{ + NV_REF iter = NV_REF_INIT; + NV_REF currentAddr; + TPM_HANDLE entityHandle; + TPM_RC result = TPM_RC_SUCCESS; + // + while((currentAddr = NvNext(&iter, &entityHandle)) != 0) + { + if(HandleGetType(entityHandle) == TPM_HT_NV_INDEX) + { + NV_INDEX nvIndex; + // + // If flush endorsement or platform hierarchy, no NV Index would be + // flushed + if(hierarchy == TPM_RH_ENDORSEMENT || hierarchy == TPM_RH_PLATFORM) + continue; + // Get the index information + NvReadNvIndexInfo(currentAddr, &nvIndex); + + // For storage hierarchy, flush OwnerCreated index + if(!IS_ATTRIBUTE(nvIndex.publicArea.attributes, TPMA_NV, PLATFORMCREATE)) + { + // Delete the index (including RAM for orderly) + result = NvDeleteIndex(&nvIndex, currentAddr); + if(result != TPM_RC_SUCCESS) + break; + // Re-iterate from beginning after a delete + iter = NV_REF_INIT; + } + } + else if(HandleGetType(entityHandle) == TPM_HT_PERSISTENT) + { + OBJECT_ATTRIBUTES attributes; + // + NvRead(&attributes, + (UINT32)(currentAddr + sizeof(TPM_HANDLE) + + offsetof(OBJECT, attributes)), + sizeof(OBJECT_ATTRIBUTES)); + // If the evict object belongs to the hierarchy to be flushed... + if((hierarchy == TPM_RH_PLATFORM && attributes.ppsHierarchy == SET) + || (hierarchy == TPM_RH_OWNER && attributes.spsHierarchy == SET) + || (hierarchy == TPM_RH_ENDORSEMENT && attributes.epsHierarchy == SET)) + { + // ...then delete the evict object + result = NvDelete(currentAddr); + if(result != TPM_RC_SUCCESS) + break; + // Re-iterate from beginning after a delete + iter = NV_REF_INIT; + } + } + else + { + FAIL(FATAL_ERROR_INTERNAL); + } + } + return result; +} + +//*** NvSetGlobalLock() +// This function is used to SET the TPMA_NV_WRITELOCKED attribute for all +// NV indexes that have TPMA_NV_GLOBALLOCK SET. This function is use by +// TPM2_NV_GlobalWriteLock(). +// Return Type: TPM_RC +// TPM_RC_NV_RATE NV is unavailable because of rate limit +// TPM_RC_NV_UNAVAILABLE NV is inaccessible +TPM_RC +NvSetGlobalLock(void) +{ + NV_REF iter = NV_REF_INIT; + NV_RAM_REF ramIter = NV_RAM_REF_INIT; + NV_REF currentAddr; + NV_RAM_REF currentRamAddr; + TPM_RC result = TPM_RC_SUCCESS; + // + // Check all normal indexes + while((currentAddr = NvNextIndex(NULL, &iter)) != 0) + { + TPMA_NV attributes = NvReadNvIndexAttributes(currentAddr); + // + // See if it should be locked + if(!IS_ATTRIBUTE(attributes, TPMA_NV, ORDERLY) + && IS_ATTRIBUTE(attributes, TPMA_NV, GLOBALLOCK)) + { + SET_ATTRIBUTE(attributes, TPMA_NV, WRITELOCKED); + result = NvWriteNvIndexAttributes(currentAddr, attributes); + if(result != TPM_RC_SUCCESS) + return result; + } + } + // Now search all the orderly attributes + while((currentRamAddr = NvRamNext(&ramIter, NULL)) != 0) + { + // See if it should be locked + TPMA_NV attributes = NvReadRamIndexAttributes(currentRamAddr); + if(IS_ATTRIBUTE(attributes, TPMA_NV, GLOBALLOCK)) + { + SET_ATTRIBUTE(attributes, TPMA_NV, WRITELOCKED); + NvWriteRamIndexAttributes(currentRamAddr, attributes); + } + } + return result; +} + +//***InsertSort() +// Sort a handle into handle list in ascending order. The total handle number in +// the list should not exceed MAX_CAP_HANDLES +static void InsertSort(TPML_HANDLE* handleList, // IN/OUT: sorted handle list + UINT32 count, // IN: maximum count in the handle list + TPM_HANDLE entityHandle // IN: handle to be inserted +) +{ + UINT32 i, j; + UINT32 originalCount; + // + // For a corner case that the maximum count is 0, do nothing + if(count == 0) + return; + // For empty list, add the handle at the beginning and return + if(handleList->count == 0) + { + handleList->handle[0] = entityHandle; + handleList->count++; + return; + } + // Check if the maximum of the list has been reached + originalCount = handleList->count; + if(originalCount < count) + handleList->count++; + // Insert the handle to the list + for(i = 0; i < originalCount; i++) + { + if(handleList->handle[i] > entityHandle) + { + for(j = handleList->count - 1; j > i; j--) + { + handleList->handle[j] = handleList->handle[j - 1]; + } + break; + } + } + // If a slot was found, insert the handle in this position + if(i < originalCount || handleList->count > originalCount) + handleList->handle[i] = entityHandle; + return; +} + +//*** NvCapGetPersistent() +// This function is used to get a list of handles of the persistent objects, +// starting at 'handle'. +// +// 'Handle' must be in valid persistent object handle range, but does not +// have to reference an existing persistent object. +// Return Type: TPMI_YES_NO +// YES if there are more handles available +// NO all the available handles has been returned +TPMI_YES_NO +NvCapGetPersistent(TPMI_DH_OBJECT handle, // IN: start handle + UINT32 count, // IN: maximum number of returned handles + TPML_HANDLE* handleList // OUT: list of handle +) +{ + TPMI_YES_NO more = NO; + NV_REF iter = NV_REF_INIT; + NV_REF currentAddr; + TPM_HANDLE entityHandle; + // + pAssert(HandleGetType(handle) == TPM_HT_PERSISTENT); + + // Initialize output handle list + handleList->count = 0; + + // The maximum count of handles we may return is MAX_CAP_HANDLES + if(count > MAX_CAP_HANDLES) + count = MAX_CAP_HANDLES; + + while((currentAddr = NvNextEvict(&entityHandle, &iter)) != 0) + { + // Ignore persistent handles that have values less than the input handle + if(entityHandle < handle) + continue; + // if the handles in the list have reached the requested count, and there + // are still handles need to be inserted, indicate that there are more. + if(handleList->count == count) + more = YES; + // A handle with a value larger than start handle is a candidate + // for return. Insert sort it to the return list. Insert sort algorithm + // is chosen here for simplicity based on the assumption that the total + // number of NV indexes is small. For an implementation that may allow + // large number of NV indexes, a more efficient sorting algorithm may be + // used here. + InsertSort(handleList, count, entityHandle); + } + return more; +} + +//*** NvCapGetIndex() +// This function returns a list of handles of NV indexes, starting from 'handle'. +// 'Handle' must be in the range of NV indexes, but does not have to reference +// an existing NV Index. +// Return Type: TPMI_YES_NO +// YES if there are more handles to report +// NO all the available handles has been reported +TPMI_YES_NO +NvCapGetIndex(TPMI_DH_OBJECT handle, // IN: start handle + UINT32 count, // IN: max number of returned handles + TPML_HANDLE* handleList // OUT: list of handle +) +{ + TPMI_YES_NO more = NO; + NV_REF iter = NV_REF_INIT; + NV_REF currentAddr; + TPM_HANDLE nvHandle; + // + pAssert(HandleGetType(handle) == TPM_HT_NV_INDEX); + + // Initialize output handle list + handleList->count = 0; + + // The maximum count of handles we may return is MAX_CAP_HANDLES + if(count > MAX_CAP_HANDLES) + count = MAX_CAP_HANDLES; + + while((currentAddr = NvNextIndex(&nvHandle, &iter)) != 0) + { + // Ignore index handles that have values less than the 'handle' + if(nvHandle < handle) + continue; + // if the count of handles in the list has reached the requested count, + // and there are still handles to report, set more. + if(handleList->count == count) + more = YES; + // A handle with a value larger than start handle is a candidate + // for return. Insert sort it to the return list. Insert sort algorithm + // is chosen here for simplicity based on the assumption that the total + // number of NV indexes is small. For an implementation that may allow + // large number of NV indexes, a more efficient sorting algorithm may be + // used here. + InsertSort(handleList, count, nvHandle); + } + return more; +} + +//*** NvCapGetIndexNumber() +// This function returns the count of NV Indexes currently defined. +UINT32 +NvCapGetIndexNumber(void) +{ + UINT32 num = 0; + NV_REF iter = NV_REF_INIT; + // + while(NvNextIndex(NULL, &iter) != 0) + num++; + return num; +} + +//*** NvCapGetPersistentNumber() +// Function returns the count of persistent objects currently in NV memory. +UINT32 +NvCapGetPersistentNumber(void) +{ + UINT32 num = 0; + NV_REF iter = NV_REF_INIT; + TPM_HANDLE handle; + // + while(NvNextEvict(&handle, &iter) != 0) + num++; + return num; +} + +//*** NvCapGetPersistentAvail() +// This function returns an estimate of the number of additional persistent +// objects that could be loaded into NV memory. +UINT32 +NvCapGetPersistentAvail(void) +{ + UINT32 availNVSpace; + UINT32 counterNum = NvCapGetCounterNumber(); + UINT32 reserved = sizeof(NV_LIST_TERMINATOR); + // + // Get the available space in NV storage + availNVSpace = NvGetFreeBytes(); + + if(counterNum < MIN_COUNTER_INDICES) + { + // Some space has to be reserved for counter objects. + reserved += (MIN_COUNTER_INDICES - counterNum) * NV_INDEX_COUNTER_SIZE; + if(reserved > availNVSpace) + availNVSpace = 0; + else + availNVSpace -= reserved; + } + return availNVSpace / NV_EVICT_OBJECT_SIZE; +} + +//*** NvCapGetCounterNumber() +// Get the number of defined NV Indexes that are counter indexes. +UINT32 +NvCapGetCounterNumber(void) +{ + NV_REF iter = NV_REF_INIT; + NV_REF currentAddr; + UINT32 num = 0; + // + while((currentAddr = NvNextIndex(NULL, &iter)) != 0) + { + TPMA_NV attributes = NvReadNvIndexAttributes(currentAddr); + if(IsNvCounterIndex(attributes)) + num++; + } + return num; +} + +//*** NvSetStartupAttributes() +// Local function to set the attributes of an Index at TPM Reset and TPM Restart. +static TPMA_NV NvSetStartupAttributes(TPMA_NV attributes, // IN: attributes to change + STARTUP_TYPE type // IN: start up type +) +{ + // Clear read lock + CLEAR_ATTRIBUTE(attributes, TPMA_NV, READLOCKED); + + // Will change a non counter index to the unwritten state if: + // a) TPMA_NV_CLEAR_STCLEAR is SET + // b) orderly and TPM Reset + if(!IsNvCounterIndex(attributes)) + { + if(IS_ATTRIBUTE(attributes, TPMA_NV, CLEAR_STCLEAR) + || (IS_ATTRIBUTE(attributes, TPMA_NV, ORDERLY) && (type == SU_RESET))) + CLEAR_ATTRIBUTE(attributes, TPMA_NV, WRITTEN); + } + // Unlock any index that is not written or that does not have + // TPMA_NV_WRITEDEFINE SET. + if(!IS_ATTRIBUTE(attributes, TPMA_NV, WRITTEN) + || !IS_ATTRIBUTE(attributes, TPMA_NV, WRITEDEFINE)) + CLEAR_ATTRIBUTE(attributes, TPMA_NV, WRITELOCKED); + return attributes; +} + +//*** NvEntityStartup() +// This function is called at TPM_Startup(). If the startup completes +// a TPM Resume cycle, no action is taken. If the startup is a TPM Reset +// or a TPM Restart, then this function will: +// a) clear read/write lock; +// b) reset NV Index data that has TPMA_NV_CLEAR_STCLEAR SET; and +// c) set the lower bits in orderly counters to 1 for a non-orderly startup +// +// It is a prerequisite that NV be available for writing before this +// function is called. +BOOL NvEntityStartup(STARTUP_TYPE type // IN: start up type +) +{ + NV_REF iter = NV_REF_INIT; + NV_RAM_REF ramIter = NV_RAM_REF_INIT; + NV_REF currentAddr; // offset points to the current entity + NV_RAM_REF currentRamAddr; + TPM_HANDLE nvHandle; + TPMA_NV attributes; + // + // Restore RAM index data + NvRead(s_indexOrderlyRam, NV_INDEX_RAM_DATA, sizeof(s_indexOrderlyRam)); + + // Initialize the max NV counter value + NvSetMaxCount(NvGetMaxCount()); + + // If recovering from state save, do nothing else + if(type == SU_RESUME) + return TRUE; + // Iterate all the NV Index to clear the locks + while((currentAddr = NvNextIndex(&nvHandle, &iter)) != 0) + { + attributes = NvReadNvIndexAttributes(currentAddr); + + // If this is an orderly index, defer processing until loop below + if(IS_ATTRIBUTE(attributes, TPMA_NV, ORDERLY)) + continue; + // Set the attributes appropriate for this startup type + attributes = NvSetStartupAttributes(attributes, type); + NvWriteNvIndexAttributes(currentAddr, attributes); + } + // Iterate all the orderly indexes to clear the locks and initialize counters + while((currentRamAddr = NvRamNext(&ramIter, NULL)) != 0) + { + attributes = NvReadRamIndexAttributes(currentRamAddr); + + attributes = NvSetStartupAttributes(attributes, type); + + // update attributes in RAM + NvWriteRamIndexAttributes(currentRamAddr, attributes); + + // Set the lower bits in an orderly counter to 1 for a non-orderly startup + if(IsNvCounterIndex(attributes) && (g_prevOrderlyState == SU_NONE_VALUE)) + { + UINT64 counter; + // + // Read the counter value last saved to NV. + counter = BYTE_ARRAY_TO_UINT64(currentRamAddr + sizeof(NV_RAM_HEADER)); + + // Set the lower bits of counter to 1's + counter |= MAX_ORDERLY_COUNT; + + // Write back to RAM + // NOTE: Do not want to force a write to NV here. The counter value will + // stay in RAM until the next shutdown or rollover. + UINT64_TO_BYTE_ARRAY(counter, currentRamAddr + sizeof(NV_RAM_HEADER)); + } + } + return TRUE; +} + +//*** NvCapGetCounterAvail() +// This function returns an estimate of the number of additional counter type +// NV indexes that can be defined. +UINT32 +NvCapGetCounterAvail(void) +{ + UINT32 availNVSpace; + UINT32 availRAMSpace; + UINT32 persistentNum = NvCapGetPersistentNumber(); + UINT32 reserved = sizeof(NV_LIST_TERMINATOR); + // + // Get the available space in NV storage + availNVSpace = NvGetFreeBytes(); + + if(persistentNum < MIN_EVICT_OBJECTS) + { + // Some space has to be reserved for evict object. Adjust availNVSpace. + reserved += (MIN_EVICT_OBJECTS - persistentNum) * NV_EVICT_OBJECT_SIZE; + if(reserved > availNVSpace) + availNVSpace = 0; + else + availNVSpace -= reserved; + } + // Compute the available space in RAM + availRAMSpace = (int)(RAM_ORDERLY_END - NvRamGetEnd()); + + // Return the min of counter number in NV and in RAM + if(availNVSpace / NV_INDEX_COUNTER_SIZE + > availRAMSpace / NV_RAM_INDEX_COUNTER_SIZE) + return availRAMSpace / NV_RAM_INDEX_COUNTER_SIZE; + else + return availNVSpace / NV_INDEX_COUNTER_SIZE; +} + +//*** NvFindHandle() +// this function returns the offset in NV memory of the entity associated +// with the input handle. A value of zero indicates that handle does not +// exist reference an existing persistent object or defined NV Index. +NV_REF +NvFindHandle(TPM_HANDLE handle) +{ + NV_REF addr; + NV_REF iter = NV_REF_INIT; + TPM_HANDLE nextHandle; + // + while((addr = NvNext(&iter, &nextHandle)) != 0) + { + if(nextHandle == handle) + break; + } + return addr; +} + +//** NV Max Counter +//*** Introduction +// The TPM keeps track of the highest value of a deleted counter index. When an +// index is deleted, this value is updated if the deleted counter index is greater +// than the previous value. When a new index is created and first incremented, it +// will get a value that is at least one greater than any other index than any +// previously deleted index. This insures that it is not possible to roll back an +// index. +// +// The highest counter value is kept in NV in a special end-of-list marker. This +// marker is only updated when an index is deleted. Otherwise it just moves. +// +// When the TPM starts up, it searches NV for the end of list marker and initializes +// an in memory value (s_maxCounter). + +//*** NvReadMaxCount() +// This function returns the max NV counter value. +// +UINT64 +NvReadMaxCount(void) +{ + return s_maxCounter; +} + +//*** NvUpdateMaxCount() +// This function updates the max counter value to NV memory. This is just staging +// for the actual write that will occur when the NV index memory is modified. +// +void NvUpdateMaxCount(UINT64 count) +{ + if(count > s_maxCounter) + s_maxCounter = count; +} + +//*** NvSetMaxCount() +// This function is used at NV initialization time to set the initial value of +// the maximum counter. +void NvSetMaxCount(UINT64 value) +{ + s_maxCounter = value; +} + +//*** NvGetMaxCount() +// Function to get the NV max counter value from the end-of-list marker +UINT64 +NvGetMaxCount(void) +{ + NV_REF iter = NV_REF_INIT; + NV_REF currentAddr; + UINT64 maxCount; + // + // Find the end of list marker and initialize the NV Max Counter value. + while((currentAddr = NvNext(&iter, NULL)) != 0) + ; + // 'iter' should be pointing at the end of list marker so read in the current + // value of the s_maxCounter. + NvRead(&maxCount, iter + sizeof(UINT32), sizeof(maxCount)); + + return maxCount; +} diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/NvReserved.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/NvReserved.c new file mode 100644 index 0000000..04a9bc2 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/NvReserved.c @@ -0,0 +1,237 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction + +// The NV memory is divided into two areas: dynamic space for user defined NV +// Indices and evict objects, and reserved space for TPM persistent and state save +// data. +// +// The entries in dynamic space are a linked list of entries. Each entry has, as its +// first field, a size. If the size field is zero, it marks the end of the +// list. +// +// An allocation of an Index or evict object may use almost all of the remaining +// NV space such that the size field will not fit. The functions that search the +// list are aware of this and will terminate the search if they either find a zero +// size or recognize that there is insufficient space for the size field. +// +// An Index allocation will contain an NV_INDEX structure. If the Index does not +// have the orderly attribute, the NV_INDEX is followed immediately by the NV data. +// +// An evict object entry contains a handle followed by an OBJECT structure. This +// results in both the Index and Evict Object having an identifying handle as the +// first field following the size field. +// +// When an Index has the orderly attribute, the data is kept in RAM. This RAM is +// saved to backing store in NV memory on any orderly shutdown. The entries in +// orderly memory are also a linked list using a size field as the first entry. As +// with the NV memory, the list is terminated by a zero size field or when the last +// entry leaves insufficient space for the terminating size field. +// +// The attributes of an orderly index are maintained in RAM memory in order to +// reduce the number of NV writes needed for orderly data. When an orderly index +// is created, an entry is made in the dynamic NV memory space that holds the Index +// authorizations (authPolicy and authValue) and the size of the data. This entry is +// only modified if the authValue of the index is changed. The more volatile data +// of the index is kept in RAM. When an orderly Index is created or deleted, the +// RAM data is copied to NV backing store so that the image in the backing store +// matches the layout of RAM. In normal operation. The RAM data is also copied on +// any orderly shutdown. In normal operation, the only other reason for writing +// to the backing store for RAM is when a counter is first written (TPMA_NV_WRITTEN +// changes from CLEAR to SET) or when a counter "rolls over." +// +// Static space contains items that are individually modifiable. The values are in +// the 'gp' PERSISTENT_DATA structure in RAM and mapped to locations in NV. +// + +//** Includes, Defines +#define NV_C +#include "Tpm.h" + +//************************************************ +//** Functions +//************************************************ + +//*** NvInitStatic() +// This function initializes the static variables used in the NV subsystem. +static void NvInitStatic(void) +{ + // In some implementations, the end of NV is variable and is set at boot time. + // This value will be the same for each boot, but is not necessarily known + // at compile time. + s_evictNvEnd = (NV_REF)NV_MEMORY_SIZE; + return; +} + +//*** NvCheckState() +// Function to check the NV state by accessing the platform-specific function +// to get the NV state. The result state is registered in s_NvIsAvailable +// that will be reported by NvIsAvailable. +// +// This function is called at the beginning of ExecuteCommand before any potential +// check of g_NvStatus. +void NvCheckState(void) +{ + int func_return; + // + func_return = _plat__IsNvAvailable(); + if(func_return == 0) + g_NvStatus = TPM_RC_SUCCESS; + else if(func_return == 1) + g_NvStatus = TPM_RC_NV_UNAVAILABLE; + else + g_NvStatus = TPM_RC_NV_RATE; + return; +} + +//*** NvCommit +// This is a wrapper for the platform function to commit pending NV writes. +BOOL NvCommit(void) +{ + return (_plat__NvCommit() == 0); +} + +//*** NvPowerOn() +// This function is called at _TPM_Init to initialize the NV environment. +// Return Type: BOOL +// TRUE(1) all NV was initialized +// FALSE(0) the NV containing saved state had an error and +// TPM2_Startup(CLEAR) is required +BOOL NvPowerOn(void) +{ + int nvError = 0; + // If power was lost, need to re-establish the RAM data that is loaded from + // NV and initialize the static variables + if(g_powerWasLost) + { + if((nvError = _plat__NVEnable(0)) < 0) + FAIL(FATAL_ERROR_NV_UNRECOVERABLE); + NvInitStatic(); + } + return nvError == 0; +} + +//*** NvManufacture() +// This function initializes the NV system at pre-install time. +// +// This function should only be called in a manufacturing environment or in a +// simulation. +// +// The layout of NV memory space is an implementation choice. +void NvManufacture(void) +{ +#if SIMULATION + // Simulate the NV memory being in the erased state. + _plat__NvMemoryClear(0, NV_MEMORY_SIZE); +#endif + // Initialize static variables + NvInitStatic(); + // Clear the RAM used for Orderly Index data + MemorySet(s_indexOrderlyRam, 0, RAM_INDEX_SPACE); + // Write that Orderly Index data to NV + NvUpdateIndexOrderlyData(); + // Initialize the next offset of the first entry in evict/index list to 0 (the + // end of list marker) and the initial s_maxCounterValue; + NvSetMaxCount(0); + // Put the end of list marker at the end of memory. This contains the MaxCount + // value as well as the end marker. + NvWriteNvListEnd(NV_USER_DYNAMIC); + return; +} + +//*** NvRead() +// This function is used to move reserved data from NV memory to RAM. +void NvRead(void* outBuffer, // OUT: buffer to receive data + UINT32 nvOffset, // IN: offset in NV of value + UINT32 size // IN: size of the value to read +) +{ + // Input type should be valid + pAssert(nvOffset + size < NV_MEMORY_SIZE); + _plat__NvMemoryRead(nvOffset, size, outBuffer); + return; +} + +//*** NvWrite() +// This function is used to post reserved data for writing to NV memory. Before +// the TPM completes the operation, the value will be written. +BOOL NvWrite(UINT32 nvOffset, // IN: location in NV to receive data + UINT32 size, // IN: size of the data to move + void* inBuffer // IN: location containing data to write +) +{ + // Input type should be valid + if(nvOffset + size <= NV_MEMORY_SIZE) + { + // Set the flag that a NV write happened + SET_NV_UPDATE(UT_NV); + return _plat__NvMemoryWrite(nvOffset, size, inBuffer); + } + return FALSE; +} + +//*** NvUpdatePersistent() +// This function is used to update a value in the PERSISTENT_DATA structure and +// commits the value to NV. +void NvUpdatePersistent( + UINT32 offset, // IN: location in PERMANENT_DATA to be updated + UINT32 size, // IN: size of the value + void* buffer // IN: the new data +) +{ + pAssert(offset + size <= sizeof(gp)); + MemoryCopy(&gp + offset, buffer, size); + NvWrite(offset, size, buffer); +} + +//*** NvClearPersistent() +// This function is used to clear a persistent data entry and commit it to NV +void NvClearPersistent(UINT32 offset, // IN: the offset in the PERMANENT_DATA + // structure to be cleared (zeroed) + UINT32 size // IN: number of bytes to clear +) +{ + pAssert(offset + size <= sizeof(gp)); + MemorySet((&gp) + offset, 0, size); + NvWrite(offset, size, (&gp) + offset); +} + +//*** NvReadPersistent() +// This function reads persistent data to the RAM copy of the 'gp' structure. +void NvReadPersistent(void) +{ + NvRead(&gp, NV_PERSISTENT_DATA, sizeof(gp)); + return; +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/Object.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/Object.c new file mode 100644 index 0000000..ca67d93 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/Object.c @@ -0,0 +1,936 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// This file contains the functions that manage the object store of the TPM. + +//** Includes and Data Definitions +#define OBJECT_C + +#include "Tpm.h" +#include "Marshal.h" + +//** Functions + +//*** ObjectFlush() +// This function marks an object slot as available. +// Since there is no checking of the input parameters, it should be used +// judiciously. +// Note: This could be converted to a macro. +void ObjectFlush(OBJECT* object) +{ + object->attributes.occupied = CLEAR; +} + +//*** ObjectSetInUse() +// This access function sets the occupied attribute of an object slot. +void ObjectSetInUse(OBJECT* object) +{ + object->attributes.occupied = SET; +} + +//*** ObjectStartup() +// This function is called at TPM2_Startup() to initialize the object subsystem. +BOOL ObjectStartup(void) +{ + UINT32 i; + // + // object slots initialization + for(i = 0; i < MAX_LOADED_OBJECTS; i++) + { + //Set the slot to not occupied + ObjectFlush(&s_objects[i]); + } + return TRUE; +} + +//*** ObjectCleanupEvict() +// +// In this implementation, a persistent object is moved from NV into an object slot +// for processing. It is flushed after command execution. This function is called +// from ExecuteCommand(). +void ObjectCleanupEvict(void) +{ + UINT32 i; + // + // This has to be iterated because a command may have two handles + // and they may both be persistent. + // This could be made to be more efficient so that a search is not needed. + for(i = 0; i < MAX_LOADED_OBJECTS; i++) + { + // If an object is a temporary evict object, flush it from slot + OBJECT* object = &s_objects[i]; + if(object->attributes.evict == SET) + ObjectFlush(object); + } + return; +} + +//*** IsObjectPresent() +// This function checks to see if a transient handle references a loaded +// object. This routine should not be called if the handle is not a +// transient handle. The function validates that the handle is in the +// implementation-dependent allowed in range for loaded transient objects. +// Return Type: BOOL +// TRUE(1) handle references a loaded object +// FALSE(0) handle is not an object handle, or it does not +// reference to a loaded object +BOOL IsObjectPresent(TPMI_DH_OBJECT handle // IN: handle to be checked +) +{ + UINT32 slotIndex = handle - TRANSIENT_FIRST; + // Since the handle is just an index into the array that is zero based, any + // handle value outsize of the range of: + // TRANSIENT_FIRST -- (TRANSIENT_FIRST + MAX_LOADED_OBJECT - 1) + // will now be greater than or equal to MAX_LOADED_OBJECTS + if(slotIndex >= MAX_LOADED_OBJECTS) + return FALSE; + // Indicate if the slot is occupied + return (s_objects[slotIndex].attributes.occupied == TRUE); +} + +//*** ObjectIsSequence() +// This function is used to check if the object is a sequence object. This function +// should not be called if the handle does not reference a loaded object. +// Return Type: BOOL +// TRUE(1) object is an HMAC, hash, or event sequence object +// FALSE(0) object is not an HMAC, hash, or event sequence object +BOOL ObjectIsSequence(OBJECT* object // IN: handle to be checked +) +{ + pAssert(object != NULL); + return (object->attributes.hmacSeq == SET || object->attributes.hashSeq == SET + || object->attributes.eventSeq == SET); +} + +//*** HandleToObject() +// This function is used to find the object structure associated with a handle. +// +// This function requires that 'handle' references a loaded object or a permanent +// handle. +OBJECT* HandleToObject(TPMI_DH_OBJECT handle // IN: handle of the object +) +{ + UINT32 index; + // + // Return NULL if the handle references a permanent handle because there is no + // associated OBJECT. + if(HandleGetType(handle) == TPM_HT_PERMANENT) + return NULL; + // In this implementation, the handle is determined by the slot occupied by the + // object. + index = handle - TRANSIENT_FIRST; + pAssert(index < MAX_LOADED_OBJECTS); + pAssert(s_objects[index].attributes.occupied); + return &s_objects[index]; +} + +//*** GetQualifiedName() +// This function returns the Qualified Name of the object. In this implementation, +// the Qualified Name is computed when the object is loaded and is saved in the +// internal representation of the object. The alternative would be to retain the +// Name of the parent and compute the QN when needed. This would take the same +// amount of space so it is not recommended that the alternate be used. +// +// This function requires that 'handle' references a loaded object. +void GetQualifiedName(TPMI_DH_OBJECT handle, // IN: handle of the object + TPM2B_NAME* qualifiedName // OUT: qualified name of the object +) +{ + OBJECT* object; + // + switch(HandleGetType(handle)) + { + case TPM_HT_PERMANENT: + qualifiedName->t.size = sizeof(TPM_HANDLE); + UINT32_TO_BYTE_ARRAY(handle, qualifiedName->t.name); + break; + case TPM_HT_TRANSIENT: + object = HandleToObject(handle); + if(object == NULL || object->publicArea.nameAlg == TPM_ALG_NULL) + qualifiedName->t.size = 0; + else + // Copy the name + *qualifiedName = object->qualifiedName; + break; + default: + FAIL(FATAL_ERROR_INTERNAL); + } + return; +} + +//*** ObjectGetHierarchy() +// This function returns the handle for the hierarchy of an object. +TPMI_RH_HIERARCHY +ObjectGetHierarchy(OBJECT* object // IN :object +) +{ + if(object->attributes.spsHierarchy) + { + return TPM_RH_OWNER; + } + else if(object->attributes.epsHierarchy) + { + return TPM_RH_ENDORSEMENT; + } + else if(object->attributes.ppsHierarchy) + { + return TPM_RH_PLATFORM; + } + else + { + return TPM_RH_NULL; + } +} + +//*** GetHierarchy() +// This function returns the handle of the hierarchy to which a handle belongs. +// This function is similar to ObjectGetHierarchy() but this routine takes +// a handle but ObjectGetHierarchy() takes an pointer to an object. +// +// This function requires that 'handle' references a loaded object. +TPMI_RH_HIERARCHY +GetHierarchy(TPMI_DH_OBJECT handle // IN :object handle +) +{ + OBJECT* object = HandleToObject(handle); + // + return ObjectGetHierarchy(object); +} + +//*** FindEmptyObjectSlot() +// This function finds an open object slot, if any. It will clear the attributes +// but will not set the occupied attribute. This is so that a slot may be used +// and discarded if everything does not go as planned. +// Return Type: OBJECT * +// NULL no open slot found +// != NULL pointer to available slot +OBJECT* FindEmptyObjectSlot(TPMI_DH_OBJECT* handle // OUT: (optional) +) +{ + UINT32 i; + OBJECT* object; + // + for(i = 0; i < MAX_LOADED_OBJECTS; i++) + { + object = &s_objects[i]; + if(object->attributes.occupied == CLEAR) + { + if(handle) + *handle = i + TRANSIENT_FIRST; + // Initialize the object attributes + MemorySet(&object->attributes, 0, sizeof(OBJECT_ATTRIBUTES)); + return object; + } + } + return NULL; +} + +//*** ObjectAllocateSlot() +// This function is used to allocate a slot in internal object array. +OBJECT* ObjectAllocateSlot(TPMI_DH_OBJECT* handle // OUT: handle of allocated object +) +{ + OBJECT* object = FindEmptyObjectSlot(handle); + // + if(object != NULL) + { + // if found, mark as occupied + ObjectSetInUse(object); + } + return object; +} + +//*** ObjectSetLoadedAttributes() +// This function sets the internal attributes for a loaded object. It is called to +// finalize the OBJECT attributes (not the TPMA_OBJECT attributes) for a loaded +// object. +void ObjectSetLoadedAttributes(OBJECT* object, // IN: object attributes to finalize + TPM_HANDLE parentHandle // IN: the parent handle +) +{ + OBJECT* parent = HandleToObject(parentHandle); + TPMA_OBJECT objectAttributes = object->publicArea.objectAttributes; + // + // Copy the stClear attribute from the public area. This could be overwritten + // if the parent has stClear SET + object->attributes.stClear = IS_ATTRIBUTE(objectAttributes, TPMA_OBJECT, stClear); + // If parent handle is a permanent handle, it is a primary (unless it is NULL + if(parent == NULL) + { + object->attributes.primary = SET; + switch(parentHandle) + { + case TPM_RH_ENDORSEMENT: + object->attributes.epsHierarchy = SET; + break; + case TPM_RH_OWNER: + object->attributes.spsHierarchy = SET; + break; + case TPM_RH_PLATFORM: + object->attributes.ppsHierarchy = SET; + break; + default: + // Treat the temporary attribute as a hierarchy + object->attributes.temporary = SET; + object->attributes.primary = CLEAR; + break; + } + } + else + { + // is this a stClear object + object->attributes.stClear = + (IS_ATTRIBUTE(objectAttributes, TPMA_OBJECT, stClear) + || (parent->attributes.stClear == SET)); + object->attributes.epsHierarchy = parent->attributes.epsHierarchy; + object->attributes.spsHierarchy = parent->attributes.spsHierarchy; + object->attributes.ppsHierarchy = parent->attributes.ppsHierarchy; + // An object is temporary if its parent is temporary or if the object + // is external + object->attributes.temporary = parent->attributes.temporary + || object->attributes.external; + } + // If this is an external object, set the QN == name but don't SET other + // key properties ('parent' or 'derived') + if(object->attributes.external) + object->qualifiedName = object->name; + else + { + // check attributes for different types of parents + if(IS_ATTRIBUTE(objectAttributes, TPMA_OBJECT, restricted) + && !object->attributes.publicOnly + && IS_ATTRIBUTE(objectAttributes, TPMA_OBJECT, decrypt) + && object->publicArea.nameAlg != TPM_ALG_NULL) + { + // This is a parent. If it is not a KEYEDHASH, it is an ordinary parent. + // Otherwise, it is a derivation parent. + if(object->publicArea.type == TPM_ALG_KEYEDHASH) + object->attributes.derivation = SET; + else + object->attributes.isParent = SET; + } + ComputeQualifiedName(parentHandle, + object->publicArea.nameAlg, + &object->name, + &object->qualifiedName); + } + // Set slot occupied + ObjectSetInUse(object); + return; +} + +//*** ObjectLoad() +// Common function to load an object. A loaded object has its public area validated +// (unless its 'nameAlg' is TPM_ALG_NULL). If a sensitive part is loaded, it is +// verified to be correct and if both public and sensitive parts are loaded, then +// the cryptographic binding between the objects is validated. This function does +// not cause the allocated slot to be marked as in use. +TPM_RC +ObjectLoad(OBJECT* object, // IN: pointer to object slot + // object + OBJECT* parent, // IN: (optional) the parent object + TPMT_PUBLIC* publicArea, // IN: public area to be installed in the object + TPMT_SENSITIVE* sensitive, // IN: (optional) sensitive area to be + // installed in the object + TPM_RC blamePublic, // IN: parameter number to associate with the + // publicArea errors + TPM_RC blameSensitive, // IN: parameter number to associate with the + // sensitive area errors + TPM2B_NAME* name // IN: (optional) +) +{ + TPM_RC result = TPM_RC_SUCCESS; + // + // Do validations of public area object descriptions + pAssert(publicArea != NULL); + + // Is this public only or a no-name object? + if(sensitive == NULL || publicArea->nameAlg == TPM_ALG_NULL) + { + // Need to have schemes checked so that we do the right thing with the + // public key. + result = SchemeChecks(NULL, publicArea); + } + else + { + // For any sensitive area, make sure that the seedSize is no larger than the + // digest size of nameAlg + if(sensitive->seedValue.t.size > CryptHashGetDigestSize(publicArea->nameAlg)) + return TPM_RCS_KEY_SIZE + blameSensitive; + // Check attributes and schemes for consistency + result = PublicAttributesValidation(parent, publicArea); + } + if(result != TPM_RC_SUCCESS) + return RcSafeAddToResult(result, blamePublic); + + // Sensitive area and binding checks + + // On load, check nothing if the parent is fixedTPM. For all other cases, validate + // the keys. + if((parent == NULL) + || ((parent != NULL) + && !IS_ATTRIBUTE( + parent->publicArea.objectAttributes, TPMA_OBJECT, fixedTPM))) + { + // Do the cryptographic key validation + result = + CryptValidateKeys(publicArea, sensitive, blamePublic, blameSensitive); + if(result != TPM_RC_SUCCESS) + return result; + } +#if ALG_RSA + // If this is an RSA key, then expand the private exponent. + // Note: ObjectLoad() is only called by TPM2_Import() if the parent is fixedTPM. + // For any key that does not have a fixedTPM parent, the exponent is computed + // whenever it is loaded + if((publicArea->type == TPM_ALG_RSA) && (sensitive != NULL)) + { + result = CryptRsaLoadPrivateExponent(publicArea, sensitive); + if(result != TPM_RC_SUCCESS) + return result; + } +#endif // ALG_RSA + // See if there is an object to populate + if((result == TPM_RC_SUCCESS) && (object != NULL)) + { + // Initialize public + object->publicArea = *publicArea; + // Copy sensitive if there is one + if(sensitive == NULL) + object->attributes.publicOnly = SET; + else + object->sensitive = *sensitive; + // Set the name, if one was provided + if(name != NULL) + object->name = *name; + else + object->name.t.size = 0; + } + return result; +} + +//*** AllocateSequenceSlot() +// This function allocates a sequence slot and initializes the parts that +// are used by the normal objects so that a sequence object is not inadvertently +// used for an operation that is not appropriate for a sequence. +// +static HASH_OBJECT* AllocateSequenceSlot( + TPM_HANDLE* newHandle, // OUT: receives the allocated handle + TPM2B_AUTH* auth // IN: the authValue for the slot +) +{ + HASH_OBJECT* object = (HASH_OBJECT*)ObjectAllocateSlot(newHandle); + // + // Validate that the proper location of the hash state data relative to the + // object state data. It would be good if this could have been done at compile + // time but it can't so do it in something that can be removed after debug. + cAssert(offsetof(HASH_OBJECT, auth) == offsetof(OBJECT, publicArea.authPolicy)); + + if(object != NULL) + { + + // Set the common values that a sequence object shares with an ordinary object + // First, clear all attributes + MemorySet(&object->objectAttributes, 0, sizeof(TPMA_OBJECT)); + + // The type is TPM_ALG_NULL + object->type = TPM_ALG_NULL; + + // This has no name algorithm and the name is the Empty Buffer + object->nameAlg = TPM_ALG_NULL; + + // A sequence object is considered to be in the NULL hierarchy so it should + // be marked as temporary so that it can't be persisted + object->attributes.temporary = SET; + + // A sequence object is DA exempt. + SET_ATTRIBUTE(object->objectAttributes, TPMA_OBJECT, noDA); + + // Copy the authorization value + if(auth != NULL) + object->auth = *auth; + else + object->auth.t.size = 0; + } + return object; +} + +#if CC_HMAC_Start || CC_MAC_Start +//*** ObjectCreateHMACSequence() +// This function creates an internal HMAC sequence object. +// Return Type: TPM_RC +// TPM_RC_OBJECT_MEMORY if there is no free slot for an object +TPM_RC +ObjectCreateHMACSequence( + TPMI_ALG_HASH hashAlg, // IN: hash algorithm + OBJECT* keyObject, // IN: the object containing the HMAC key + TPM2B_AUTH* auth, // IN: authValue + TPMI_DH_OBJECT* newHandle // OUT: HMAC sequence object handle +) +{ + HASH_OBJECT* hmacObject; + // + // Try to allocate a slot for new object + hmacObject = AllocateSequenceSlot(newHandle, auth); + + if(hmacObject == NULL) + return TPM_RC_OBJECT_MEMORY; + // Set HMAC sequence bit + hmacObject->attributes.hmacSeq = SET; + +# if !SMAC_IMPLEMENTED + if(CryptHmacStart(&hmacObject->state.hmacState, + hashAlg, + keyObject->sensitive.sensitive.bits.b.size, + keyObject->sensitive.sensitive.bits.b.buffer) + == 0) +# else + if(CryptMacStart(&hmacObject->state.hmacState, + &keyObject->publicArea.parameters, + hashAlg, + &keyObject->sensitive.sensitive.any.b) + == 0) +# endif // SMAC_IMPLEMENTED + return TPM_RC_FAILURE; + return TPM_RC_SUCCESS; +} +#endif + +//*** ObjectCreateHashSequence() +// This function creates a hash sequence object. +// Return Type: TPM_RC +// TPM_RC_OBJECT_MEMORY if there is no free slot for an object +TPM_RC +ObjectCreateHashSequence(TPMI_ALG_HASH hashAlg, // IN: hash algorithm + TPM2B_AUTH* auth, // IN: authValue + TPMI_DH_OBJECT* newHandle // OUT: sequence object handle +) +{ + HASH_OBJECT* hashObject = AllocateSequenceSlot(newHandle, auth); + // + // See if slot allocated + if(hashObject == NULL) + return TPM_RC_OBJECT_MEMORY; + // Set hash sequence bit + hashObject->attributes.hashSeq = SET; + + // Start hash for hash sequence + CryptHashStart(&hashObject->state.hashState[0], hashAlg); + + return TPM_RC_SUCCESS; +} + +//*** ObjectCreateEventSequence() +// This function creates an event sequence object. +// Return Type: TPM_RC +// TPM_RC_OBJECT_MEMORY if there is no free slot for an object +TPM_RC +ObjectCreateEventSequence(TPM2B_AUTH* auth, // IN: authValue + TPMI_DH_OBJECT* newHandle // OUT: sequence object handle +) +{ + HASH_OBJECT* hashObject = AllocateSequenceSlot(newHandle, auth); + UINT32 count; + TPM_ALG_ID hash; + // + // See if slot allocated + if(hashObject == NULL) + return TPM_RC_OBJECT_MEMORY; + // Set the event sequence attribute + hashObject->attributes.eventSeq = SET; + + // Initialize hash states for each implemented PCR algorithms + for(count = 0; (hash = CryptHashGetAlgByIndex(count)) != TPM_ALG_NULL; count++) + CryptHashStart(&hashObject->state.hashState[count], hash); + return TPM_RC_SUCCESS; +} + +//*** ObjectTerminateEvent() +// This function is called to close out the event sequence and clean up the hash +// context states. +void ObjectTerminateEvent(void) +{ + HASH_OBJECT* hashObject; + int count; + BYTE buffer[MAX_DIGEST_SIZE]; + // + hashObject = (HASH_OBJECT*)HandleToObject(g_DRTMHandle); + + // Don't assume that this is a proper sequence object + if(hashObject->attributes.eventSeq) + { + // If it is, close any open hash contexts. This is done in case + // the cryptographic implementation has some context values that need to be + // cleaned up (hygiene). + // + for(count = 0; CryptHashGetAlgByIndex(count) != TPM_ALG_NULL; count++) + { + CryptHashEnd(&hashObject->state.hashState[count], 0, buffer); + } + // Flush sequence object + FlushObject(g_DRTMHandle); + } + g_DRTMHandle = TPM_RH_UNASSIGNED; +} + +//*** ObjectContextLoad() +// This function loads an object from a saved object context. +// Return Type: OBJECT * +// NULL if there is no free slot for an object +// != NULL points to the loaded object +OBJECT* ObjectContextLoad( + ANY_OBJECT_BUFFER* object, // IN: pointer to object structure in saved + // context + TPMI_DH_OBJECT* handle // OUT: object handle +) +{ + OBJECT* newObject = ObjectAllocateSlot(handle); + // + // Try to allocate a slot for new object + if(newObject != NULL) + { + // Copy the first part of the object + MemoryCopy(newObject, object, offsetof(HASH_OBJECT, state)); + // See if this is a sequence object + if(ObjectIsSequence(newObject)) + { + // If this is a sequence object, import the data + SequenceDataImport((HASH_OBJECT*)newObject, (HASH_OBJECT_BUFFER*)object); + } + else + { + // Copy input object data to internal structure + MemoryCopy(newObject, object, sizeof(OBJECT)); + } + } + return newObject; +} + +//*** FlushObject() +// This function frees an object slot. +// +// This function requires that the object is loaded. +void FlushObject(TPMI_DH_OBJECT handle // IN: handle to be freed +) +{ + UINT32 index = handle - TRANSIENT_FIRST; + // + pAssert(index < MAX_LOADED_OBJECTS); + // Clear all the object attributes + MemorySet((BYTE*)&(s_objects[index].attributes), 0, sizeof(OBJECT_ATTRIBUTES)); + return; +} + +//*** ObjectFlushHierarchy() +// This function is called to flush all the loaded transient objects associated +// with a hierarchy when the hierarchy is disabled. +void ObjectFlushHierarchy(TPMI_RH_HIERARCHY hierarchy // IN: hierarchy to be flush +) +{ + UINT16 i; + // + // iterate object slots + for(i = 0; i < MAX_LOADED_OBJECTS; i++) + { + if(s_objects[i].attributes.occupied) // If found an occupied slot + { + switch(hierarchy) + { + case TPM_RH_PLATFORM: + if(s_objects[i].attributes.ppsHierarchy == SET) + s_objects[i].attributes.occupied = FALSE; + break; + case TPM_RH_OWNER: + if(s_objects[i].attributes.spsHierarchy == SET) + s_objects[i].attributes.occupied = FALSE; + break; + case TPM_RH_ENDORSEMENT: + if(s_objects[i].attributes.epsHierarchy == SET) + s_objects[i].attributes.occupied = FALSE; + break; + default: + FAIL(FATAL_ERROR_INTERNAL); + break; + } + } + } + + return; +} + +//*** ObjectLoadEvict() +// This function loads a persistent object into a transient object slot. +// +// This function requires that 'handle' is associated with a persistent object. +// Return Type: TPM_RC +// TPM_RC_HANDLE the persistent object does not exist +// or the associated hierarchy is disabled. +// TPM_RC_OBJECT_MEMORY no object slot +TPM_RC +ObjectLoadEvict(TPM_HANDLE* handle, // IN:OUT: evict object handle. If success, it + // will be replace by the loaded object handle + COMMAND_INDEX commandIndex // IN: the command being processed +) +{ + TPM_RC result; + TPM_HANDLE evictHandle = *handle; // Save the evict handle + OBJECT* object; + // + // If this is an index that references a persistent object created by + // the platform, then return TPM_RH_HANDLE if the phEnable is FALSE + if(*handle >= PLATFORM_PERSISTENT) + { + // belongs to platform + if(g_phEnable == CLEAR) + return TPM_RC_HANDLE; + } + // belongs to owner + else if(gc.shEnable == CLEAR) + return TPM_RC_HANDLE; + // Try to allocate a slot for an object + object = ObjectAllocateSlot(handle); + if(object == NULL) + return TPM_RC_OBJECT_MEMORY; + // Copy persistent object to transient object slot. A TPM_RC_HANDLE + // may be returned at this point. This will mark the slot as containing + // a transient object so that it will be flushed at the end of the + // command + result = NvGetEvictObject(evictHandle, object); + + // Bail out if this failed + if(result != TPM_RC_SUCCESS) + return result; + // check the object to see if it is in the endorsement hierarchy + // if it is and this is not a TPM2_EvictControl() command, indicate + // that the hierarchy is disabled. + // If the associated hierarchy is disabled, make it look like the + // handle is not defined + if(ObjectGetHierarchy(object) == TPM_RH_ENDORSEMENT && gc.ehEnable == CLEAR + && GetCommandCode(commandIndex) != TPM_CC_EvictControl) + return TPM_RC_HANDLE; + + return result; +} + +//*** ObjectComputeName() +// This does the name computation from a public area (can be marshaled or not). +TPM2B_NAME* ObjectComputeName(UINT32 size, // IN: the size of the area to digest + BYTE* publicArea, // IN: the public area to digest + TPM_ALG_ID nameAlg, // IN: the hash algorithm to use + TPM2B_NAME* name // OUT: Computed name +) +{ + // Hash the publicArea into the name buffer leaving room for the nameAlg + name->t.size = CryptHashBlock( + nameAlg, size, publicArea, sizeof(name->t.name) - 2, &name->t.name[2]); + // set the nameAlg + UINT16_TO_BYTE_ARRAY(nameAlg, name->t.name); + name->t.size += 2; + return name; +} + +//*** PublicMarshalAndComputeName() +// This function computes the Name of an object from its public area. +TPM2B_NAME* PublicMarshalAndComputeName( + TPMT_PUBLIC* publicArea, // IN: public area of an object + TPM2B_NAME* name // OUT: name of the object +) +{ + // Will marshal a public area into a template. This is because the internal + // format for a TPM2B_PUBLIC is a structure and not a simple BYTE buffer. + TPM2B_TEMPLATE marshaled; // this is big enough to hold a + // marshaled TPMT_PUBLIC + BYTE* buffer = (BYTE*)&marshaled.t.buffer; + // + // if the nameAlg is NULL then there is no name. + if(publicArea->nameAlg == TPM_ALG_NULL) + name->t.size = 0; + else + { + // Marshal the public area into its canonical form + marshaled.t.size = TPMT_PUBLIC_Marshal(publicArea, &buffer, NULL); + // and compute the name + ObjectComputeName( + marshaled.t.size, marshaled.t.buffer, publicArea->nameAlg, name); + } + return name; +} + +//*** ComputeQualifiedName() +// This function computes the qualified name of an object. +void ComputeQualifiedName( + TPM_HANDLE parentHandle, // IN: parent's handle + TPM_ALG_ID nameAlg, // IN: name hash + TPM2B_NAME* name, // IN: name of the object + TPM2B_NAME* qualifiedName // OUT: qualified name of the object +) +{ + HASH_STATE hashState; // hash state + TPM2B_NAME parentName; + // + if(parentHandle == TPM_RH_UNASSIGNED) + { + MemoryCopy2B(&qualifiedName->b, &name->b, sizeof(qualifiedName->t.name)); + *qualifiedName = *name; + } + else + { + GetQualifiedName(parentHandle, &parentName); + + // QN_A = hash_A (QN of parent || NAME_A) + + // Start hash + qualifiedName->t.size = CryptHashStart(&hashState, nameAlg); + + // Add parent's qualified name + CryptDigestUpdate2B(&hashState, &parentName.b); + + // Add self name + CryptDigestUpdate2B(&hashState, &name->b); + + // Complete hash leaving room for the name algorithm + CryptHashEnd(&hashState, qualifiedName->t.size, &qualifiedName->t.name[2]); + UINT16_TO_BYTE_ARRAY(nameAlg, qualifiedName->t.name); + qualifiedName->t.size += 2; + } + return; +} + +//*** ObjectIsStorage() +// This function determines if an object has the attributes associated +// with a parent. A parent is an asymmetric or symmetric block cipher key +// that has its 'restricted' and 'decrypt' attributes SET, and 'sign' CLEAR. +// Return Type: BOOL +// TRUE(1) object is a storage key +// FALSE(0) object is not a storage key +BOOL ObjectIsStorage(TPMI_DH_OBJECT handle // IN: object handle +) +{ + OBJECT* object = HandleToObject(handle); + TPMT_PUBLIC* publicArea = ((object != NULL) ? &object->publicArea : NULL); + // + return (publicArea != NULL + && IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted) + && IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, decrypt) + && !IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign) + && (object->publicArea.type == TPM_ALG_RSA + || object->publicArea.type == TPM_ALG_ECC)); +} + +//*** ObjectCapGetLoaded() +// This function returns a a list of handles of loaded object, starting from +// 'handle'. 'Handle' must be in the range of valid transient object handles, +// but does not have to be the handle of a loaded transient object. +// Return Type: TPMI_YES_NO +// YES if there are more handles available +// NO all the available handles has been returned +TPMI_YES_NO +ObjectCapGetLoaded(TPMI_DH_OBJECT handle, // IN: start handle + UINT32 count, // IN: count of returned handles + TPML_HANDLE* handleList // OUT: list of handle +) +{ + TPMI_YES_NO more = NO; + UINT32 i; + // + pAssert(HandleGetType(handle) == TPM_HT_TRANSIENT); + + // Initialize output handle list + handleList->count = 0; + + // The maximum count of handles we may return is MAX_CAP_HANDLES + if(count > MAX_CAP_HANDLES) + count = MAX_CAP_HANDLES; + + // Iterate object slots to get loaded object handles + for(i = handle - TRANSIENT_FIRST; i < MAX_LOADED_OBJECTS; i++) + { + if(s_objects[i].attributes.occupied == TRUE) + { + // A valid transient object can not be the copy of a persistent object + pAssert(s_objects[i].attributes.evict == CLEAR); + + if(handleList->count < count) + { + // If we have not filled up the return list, add this object + // handle to it + handleList->handle[handleList->count] = i + TRANSIENT_FIRST; + handleList->count++; + } + else + { + // If the return list is full but we still have loaded object + // available, report this and stop iterating + more = YES; + break; + } + } + } + + return more; +} + +//*** ObjectCapGetTransientAvail() +// This function returns an estimate of the number of additional transient +// objects that could be loaded into the TPM. +UINT32 +ObjectCapGetTransientAvail(void) +{ + UINT32 i; + UINT32 num = 0; + // + // Iterate object slot to get the number of unoccupied slots + for(i = 0; i < MAX_LOADED_OBJECTS; i++) + { + if(s_objects[i].attributes.occupied == FALSE) + num++; + } + + return num; +} + +//*** ObjectGetPublicAttributes() +// Returns the attributes associated with an object handles. +TPMA_OBJECT +ObjectGetPublicAttributes(TPM_HANDLE handle) +{ + return HandleToObject(handle)->publicArea.objectAttributes; +} + +OBJECT_ATTRIBUTES +ObjectGetProperties(TPM_HANDLE handle) +{ + return HandleToObject(handle)->attributes; +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/PCR.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/PCR.c new file mode 100644 index 0000000..76c9e1f --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/PCR.c @@ -0,0 +1,1281 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * Copyright (c) 2023-2024, NVIDIA Corporation & AFFILIATES. All rights reserved. + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// +// This function contains the functions needed for PCR access and manipulation. +// +// This implementation uses a static allocation for the PCR. The amount of +// memory is allocated based on the number of PCR in the implementation and +// the number of implemented hash algorithms. This is not the expected +// implementation. PCR SPACE DEFINITIONS. +// +// In the definitions below, the g_hashPcrMap is a bit array that indicates +// which of the PCR are implemented. The g_hashPcr array is an array of digests. +// In this implementation, the space is allocated whether the PCR is implemented +// or not. + +//** Includes, Defines, and Data Definitions +#define PCR_C +#include "Tpm.h" + +// The initial value of PCR attributes. The value of these fields should be +// consistent with PC Client specification +// In this implementation, we assume the total number of implemented PCR is 24. +static const PCR_Attributes s_initAttributes[] = { + // PCR 0 - 15, static RTM + {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, + {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, + {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, + {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, + + {0, 0x0F, 0x1F}, // PCR 16, Debug + {0, 0x10, 0x1C}, // PCR 17, Locality 4 + {0, 0x10, 0x1C}, // PCR 18, Locality 3 + {0, 0x10, 0x0C}, // PCR 19, Locality 2 + {0, 0x14, 0x0E}, // PCR 20, Locality 1 + {0, 0x14, 0x04}, // PCR 21, Dynamic OS + {0, 0x14, 0x04}, // PCR 22, Dynamic OS + {0, 0x0F, 0x1F}, // PCR 23, Application specific + {0, 0x0F, 0x1F} // PCR 24, testing policy +}; + +//** Functions + +//*** PCRBelongsAuthGroup() +// This function indicates if a PCR belongs to a group that requires an authValue +// in order to modify the PCR. If it does, 'groupIndex' is set to value of +// the group index. This feature of PCR is decided by the platform specification. +// +// Return Type: BOOL +// TRUE(1) PCR belongs an authorization group +// FALSE(0) PCR does not belong an authorization group +BOOL PCRBelongsAuthGroup(TPMI_DH_PCR handle, // IN: handle of PCR + UINT32* groupIndex // OUT: group index if PCR belongs a + // group that allows authValue. If PCR + // does not belong to an authorization + // group, the value in this parameter is + // invalid +) +{ +#if defined NUM_AUTHVALUE_PCR_GROUP && NUM_AUTHVALUE_PCR_GROUP > 0 + // Platform specification determines to which authorization group a PCR belongs + // (if any). In this implementation, we assume there is only + // one authorization group which contains PCR[20-22]. If the platform + // specification requires differently, the implementation should be changed + // accordingly + if(handle >= 20 && handle <= 22) + { + *groupIndex = 0; + return TRUE; + } + +#endif + return FALSE; +} + +//*** PCRBelongsPolicyGroup() +// This function indicates if a PCR belongs to a group that requires a policy +// authorization in order to modify the PCR. If it does, 'groupIndex' is set +// to value of the group index. This feature of PCR is decided by the platform +// specification. +// +// Return Type: BOOL +// TRUE(1) PCR belongs to a policy group +// FALSE(0) PCR does not belong to a policy group +BOOL PCRBelongsPolicyGroup( + TPMI_DH_PCR handle, // IN: handle of PCR + UINT32* groupIndex // OUT: group index if PCR belongs a group that + // allows policy. If PCR does not belong to + // a policy group, the value in this + // parameter is invalid +) +{ +#if defined NUM_POLICY_PCR_GROUP && NUM_POLICY_PCR_GROUP > 0 + // Platform specification decides if a PCR belongs to a policy group and + // belongs to which group. In this implementation, we assume there is only + // one policy group which contains PCR20-22. If the platform specification + // requires differently, the implementation should be changed accordingly + if(handle >= 20 && handle <= 22) + { + *groupIndex = 0; + return TRUE; + } +#endif + return FALSE; +} + +//*** PCRBelongsTCBGroup() +// This function indicates if a PCR belongs to the TCB group. +// +// Return Type: BOOL +// TRUE(1) PCR belongs to a TCB group +// FALSE(0) PCR does not belong to a TCB group +static BOOL PCRBelongsTCBGroup(TPMI_DH_PCR handle // IN: handle of PCR +) +{ +#if ENABLE_PCR_NO_INCREMENT == YES + // Platform specification decides if a PCR belongs to a TCB group. In this + // implementation, we assume PCR[20-22] belong to TCB group. If the platform + // specification requires differently, the implementation should be + // changed accordingly + if(handle >= 20 && handle <= 22) + return TRUE; + +#endif + return FALSE; +} + +//*** PCRPolicyIsAvailable() +// This function indicates if a policy is available for a PCR. +// +// Return Type: BOOL +// TRUE(1) the PCR may be authorized by policy +// FALSE(0) the PCR does not allow policy +BOOL PCRPolicyIsAvailable(TPMI_DH_PCR handle // IN: PCR handle +) +{ + UINT32 groupIndex; + + return PCRBelongsPolicyGroup(handle, &groupIndex); +} + +//*** PCRGetAuthValue() +// This function is used to access the authValue of a PCR. If PCR does not +// belong to an authValue group, an EmptyAuth will be returned. +TPM2B_AUTH* PCRGetAuthValue(TPMI_DH_PCR handle // IN: PCR handle +) +{ + UINT32 groupIndex; + + if(PCRBelongsAuthGroup(handle, &groupIndex)) + { + return &gc.pcrAuthValues.auth[groupIndex]; + } + else + { + return NULL; + } +} + +//*** PCRGetAuthPolicy() +// This function is used to access the authorization policy of a PCR. It sets +// 'policy' to the authorization policy and returns the hash algorithm for policy +// If the PCR does not allow a policy, TPM_ALG_NULL is returned. +TPMI_ALG_HASH +PCRGetAuthPolicy(TPMI_DH_PCR handle, // IN: PCR handle + TPM2B_DIGEST* policy // OUT: policy of PCR +) +{ + UINT32 groupIndex; + + if(PCRBelongsPolicyGroup(handle, &groupIndex)) + { + *policy = gp.pcrPolicies.policy[groupIndex]; + return gp.pcrPolicies.hashAlg[groupIndex]; + } + else + { + policy->t.size = 0; + return TPM_ALG_NULL; + } +} + +//*** PCRSimStart() +// This function is used to initialize the policies when a TPM is manufactured. +// This function would only be called in a manufacturing environment or in +// a TPM simulator. +void PCRSimStart(void) +{ + UINT32 i; +#if defined NUM_POLICY_PCR_GROUP && NUM_POLICY_PCR_GROUP > 0 + for(i = 0; i < NUM_POLICY_PCR_GROUP; i++) + { + gp.pcrPolicies.hashAlg[i] = TPM_ALG_NULL; + gp.pcrPolicies.policy[i].t.size = 0; + } +#endif +#if defined NUM_AUTHVALUE_PCR_GROUP && NUM_AUTHVALUE_PCR_GROUP > 0 + for(i = 0; i < NUM_AUTHVALUE_PCR_GROUP; i++) + { + gc.pcrAuthValues.auth[i].t.size = 0; + } +#endif + // We need to give an initial configuration on allocated PCR before + // receiving any TPM2_PCR_Allocate command to change this configuration + // When the simulation environment starts, we allocate all the PCRs + for(gp.pcrAllocated.count = 0; gp.pcrAllocated.count < HASH_COUNT; + gp.pcrAllocated.count++) + { + gp.pcrAllocated.pcrSelections[gp.pcrAllocated.count].hash = + CryptHashGetAlgByIndex(gp.pcrAllocated.count); + + gp.pcrAllocated.pcrSelections[gp.pcrAllocated.count].sizeofSelect = + PCR_SELECT_MAX; + for(i = 0; i < PCR_SELECT_MAX; i++) + gp.pcrAllocated.pcrSelections[gp.pcrAllocated.count].pcrSelect[i] = 0xFF; + } + + // Store the initial configuration to NV + NV_SYNC_PERSISTENT(pcrPolicies); + NV_SYNC_PERSISTENT(pcrAllocated); + + return; +} + +//*** GetSavedPcrPointer() +// This function returns the address of an array of state saved PCR based +// on the hash algorithm. +// +// Return Type: BYTE * +// NULL no such algorithm +// != NULL pointer to the 0th byte of the 0th PCR +static BYTE* GetSavedPcrPointer(TPM_ALG_ID alg, // IN: algorithm for bank + UINT32 pcrIndex // IN: PCR index in PCR_SAVE +) +{ + BYTE* retVal; + switch(alg) + { +#define HASH_CASE(HASH, Hash) \ + case TPM_ALG_##HASH: \ + retVal = gc.pcrSave.Hash[pcrIndex]; \ + break; + + FOR_EACH_HASH(HASH_CASE) +#undef HASH_CASE + + default: + FAIL(FATAL_ERROR_INTERNAL); + } + return retVal; +} + +//*** PcrIsAllocated() +// This function indicates if a PCR number for the particular hash algorithm +// is allocated. +// Return Type: BOOL +// TRUE(1) PCR is allocated +// FALSE(0) PCR is not allocated +BOOL PcrIsAllocated(UINT32 pcr, // IN: The number of the PCR + TPMI_ALG_HASH hashAlg // IN: The PCR algorithm +) +{ + UINT32 i; + BOOL allocated = FALSE; + + if(pcr < IMPLEMENTATION_PCR) + { + for(i = 0; i < gp.pcrAllocated.count; i++) + { + if(gp.pcrAllocated.pcrSelections[i].hash == hashAlg) + { + if(((gp.pcrAllocated.pcrSelections[i].pcrSelect[pcr / 8]) + & (1 << (pcr % 8))) + != 0) + allocated = TRUE; + else + allocated = FALSE; + break; + } + } + } + return allocated; +} + +//*** GetPcrPointer() +// This function returns the address of an array of PCR based on the +// hash algorithm. +// +// Return Type: BYTE * +// NULL no such algorithm +// != NULL pointer to the 0th byte of the 0th PCR +static BYTE* GetPcrPointer(TPM_ALG_ID alg, // IN: algorithm for bank + UINT32 pcrNumber // IN: PCR number +) +{ + static BYTE* pcr = NULL; + // + if(!PcrIsAllocated(pcrNumber, alg)) + return NULL; + + switch(alg) + { +#define HASH_CASE(HASH, Hash) \ + case TPM_ALG_##HASH: \ + pcr = s_pcrs[pcrNumber].Hash##Pcr; \ + break; + + FOR_EACH_HASH(HASH_CASE) +#undef HASH_CASE + + default: + FAIL(FATAL_ERROR_INTERNAL); + break; + } + return pcr; +} + +//*** IsPcrSelected() +// This function indicates if an indicated PCR number is selected by the bit map in +// 'selection'. +// +// Return Type: BOOL +// TRUE(1) PCR is selected +// FALSE(0) PCR is not selected +static BOOL IsPcrSelected( + UINT32 pcr, // IN: The number of the PCR + TPMS_PCR_SELECTION* selection // IN: The selection structure +) +{ + BOOL selected; + selected = (pcr < IMPLEMENTATION_PCR + && ((selection->pcrSelect[pcr / 8]) & (1 << (pcr % 8))) != 0); + return selected; +} + +//*** FilterPcr() +// This function modifies a PCR selection array based on the implemented +// PCR. +static void FilterPcr(TPMS_PCR_SELECTION* selection // IN: input PCR selection +) +{ + UINT32 i; + TPMS_PCR_SELECTION* allocated = NULL; + + // If size of select is less than PCR_SELECT_MAX, zero the unspecified PCR + for(i = selection->sizeofSelect; i < PCR_SELECT_MAX; i++) + selection->pcrSelect[i] = 0; + + // Find the internal configuration for the bank + for(i = 0; i < gp.pcrAllocated.count; i++) + { + if(gp.pcrAllocated.pcrSelections[i].hash == selection->hash) + { + allocated = &gp.pcrAllocated.pcrSelections[i]; + break; + } + } + + for(i = 0; i < selection->sizeofSelect; i++) + { + if(allocated == NULL) + { + // If the required bank does not exist, clear input selection + selection->pcrSelect[i] = 0; + } + else + selection->pcrSelect[i] &= allocated->pcrSelect[i]; + } + + return; +} + +//*** PcrDrtm() +// This function does the DRTM and H-CRTM processing it is called from +// _TPM_Hash_End. +void PcrDrtm(const TPMI_DH_PCR pcrHandle, // IN: the index of the PCR to be + // modified + const TPMI_ALG_HASH hash, // IN: the bank identifier + const TPM2B_DIGEST* digest // IN: the digest to modify the PCR +) +{ + BYTE* pcrData = GetPcrPointer(hash, pcrHandle); + + if(pcrData != NULL) + { + // Rest the PCR to zeros + MemorySet(pcrData, 0, digest->t.size); + + // if the TPM has not started, then set the PCR to 0...04 and then extend + if(!TPMIsStarted()) + { + pcrData[digest->t.size - 1] = 4; + } + // Now, extend the value + PCRExtend(pcrHandle, hash, digest->t.size, (BYTE*)digest->t.buffer); + } +} + +//*** PCR_ClearAuth() +// This function is used to reset the PCR authorization values. It is called +// on TPM2_Startup(CLEAR) and TPM2_Clear(). +void PCR_ClearAuth(void) +{ +#if defined NUM_AUTHVALUE_PCR_GROUP && NUM_AUTHVALUE_PCR_GROUP > 0 + int j; + for(j = 0; j < NUM_AUTHVALUE_PCR_GROUP; j++) + { + gc.pcrAuthValues.auth[j].t.size = 0; + } +#endif +} + +//*** PCRStartup() +// This function initializes the PCR subsystem at TPM2_Startup(). +BOOL PCRStartup(STARTUP_TYPE type, // IN: startup type + BYTE locality // IN: startup locality +) +{ + UINT32 pcr, j; + UINT32 saveIndex = 0; + + g_pcrReConfig = FALSE; + + // Don't test for SU_RESET because that should be the default when nothing + // else is selected + if(type != SU_RESUME && type != SU_RESTART) + { + // PCR generation counter is cleared at TPM_RESET + gr.pcrCounter = 0; + } + + // Initialize/Restore PCR values + for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++) + { + // On resume, need to know if this PCR had its state saved or not + UINT32 stateSaved; + + if(type == SU_RESUME && s_initAttributes[pcr].stateSave == SET) + { + stateSaved = 1; + } + else + { + stateSaved = 0; + PCRChanged(pcr); + } + + // If this is the H-CRTM PCR and we are not doing a resume and we + // had an H-CRTM event, then we don't change this PCR + if(pcr == HCRTM_PCR && type != SU_RESUME && g_DrtmPreStartup == TRUE) + continue; + + // Iterate each hash algorithm bank + for(j = 0; j < gp.pcrAllocated.count; j++) + { + TPMI_ALG_HASH hash = gp.pcrAllocated.pcrSelections[j].hash; + BYTE* pcrData = GetPcrPointer(hash, pcr); + UINT16 pcrSize = CryptHashGetDigestSize(hash); + + if(pcrData != NULL) + { + // if state was saved + if(stateSaved == 1) + { + // Restore saved PCR value + BYTE* pcrSavedData; + pcrSavedData = GetSavedPcrPointer( + gp.pcrAllocated.pcrSelections[j].hash, saveIndex); + if(pcrSavedData == NULL) + return FALSE; + MemoryCopy(pcrData, pcrSavedData, pcrSize); + } + else + // PCR was not restored by state save + { + // If the reset locality of the PCR is 4, then + // the reset value is all one's, otherwise it is + // all zero. + if((s_initAttributes[pcr].resetLocality & 0x10) != 0) + MemorySet(pcrData, 0xFF, pcrSize); + else + { + MemorySet(pcrData, 0, pcrSize); + if(pcr == HCRTM_PCR) + pcrData[pcrSize - 1] = locality; + } + } + } + } + saveIndex += stateSaved; + } + // Reset authValues on TPM2_Startup(CLEAR) + if(type != SU_RESUME) + PCR_ClearAuth(); + return TRUE; +} + +//*** PCRStateSave() +// This function is used to save the PCR values that will be restored on TPM Resume. +void PCRStateSave(TPM_SU type // IN: startup type +) +{ + UINT32 pcr, j; + UINT32 saveIndex = 0; + + // if state save CLEAR, nothing to be done. Return here + if(type == TPM_SU_CLEAR) + return; + + // Copy PCR values to the structure that should be saved to NV + for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++) + { + UINT32 stateSaved = (s_initAttributes[pcr].stateSave == SET) ? 1 : 0; + + // Iterate each hash algorithm bank + for(j = 0; j < gp.pcrAllocated.count; j++) + { + BYTE* pcrData; + UINT32 pcrSize; + + pcrData = GetPcrPointer(gp.pcrAllocated.pcrSelections[j].hash, pcr); + + if(pcrData != NULL) + { + pcrSize = + CryptHashGetDigestSize(gp.pcrAllocated.pcrSelections[j].hash); + + if(stateSaved == 1) + { + // Restore saved PCR value + BYTE* pcrSavedData; + pcrSavedData = GetSavedPcrPointer( + gp.pcrAllocated.pcrSelections[j].hash, saveIndex); + MemoryCopy(pcrSavedData, pcrData, pcrSize); + } + } + } + saveIndex += stateSaved; + } + + return; +} + +//*** PCRIsStateSaved() +// This function indicates if the selected PCR is a PCR that is state saved +// on TPM2_Shutdown(STATE). The return value is based on PCR attributes. +// Return Type: BOOL +// TRUE(1) PCR is state saved +// FALSE(0) PCR is not state saved +BOOL PCRIsStateSaved(TPMI_DH_PCR handle // IN: PCR handle to be extended +) +{ + UINT32 pcr = handle - PCR_FIRST; + + if(s_initAttributes[pcr].stateSave == SET) + return TRUE; + else + return FALSE; +} + +//*** PCRIsResetAllowed() +// This function indicates if a PCR may be reset by the current command locality. +// The return value is based on PCR attributes, and not the PCR allocation. +// Return Type: BOOL +// TRUE(1) TPM2_PCR_Reset is allowed +// FALSE(0) TPM2_PCR_Reset is not allowed +BOOL PCRIsResetAllowed(TPMI_DH_PCR handle // IN: PCR handle to be extended +) +{ + UINT8 commandLocality; + UINT8 localityBits = 1; + UINT32 pcr = handle - PCR_FIRST; + + // Check for the locality + commandLocality = _plat__LocalityGet(); + +#ifdef DRTM_PCR + // For a TPM that does DRTM, Reset is not allowed at locality 4 + if(commandLocality == 4) + return FALSE; +#endif + + localityBits = localityBits << commandLocality; + if((localityBits & s_initAttributes[pcr].resetLocality) == 0) + return FALSE; + else + return TRUE; +} + +//*** PCRChanged() +// This function checks a PCR handle to see if the attributes for the PCR are set +// so that any change to the PCR causes an increment of the pcrCounter. If it does, +// then the function increments the counter. Will also bump the counter if the +// handle is zero which means that PCR 0 can not be in the TCB group. Bump on zero +// is used by TPM2_Clear(). +void PCRChanged(TPM_HANDLE pcrHandle // IN: the handle of the PCR that changed. +) +{ + // For the reference implementation, the only change that does not cause + // increment is a change to a PCR in the TCB group. + if((pcrHandle == 0) || !PCRBelongsTCBGroup(pcrHandle)) + { + gr.pcrCounter++; + if(gr.pcrCounter == 0) + FAIL(FATAL_ERROR_COUNTER_OVERFLOW); + } +} + +//*** PCRIsExtendAllowed() +// This function indicates a PCR may be extended at the current command locality. +// The return value is based on PCR attributes, and not the PCR allocation. +// Return Type: BOOL +// TRUE(1) extend is allowed +// FALSE(0) extend is not allowed +BOOL PCRIsExtendAllowed(TPMI_DH_PCR handle // IN: PCR handle to be extended +) +{ + UINT8 commandLocality; + UINT8 localityBits = 1; + UINT32 pcr = handle - PCR_FIRST; + + // Check for the locality + commandLocality = _plat__LocalityGet(); + localityBits = localityBits << commandLocality; + if((localityBits & s_initAttributes[pcr].extendLocality) == 0) + return FALSE; + else + return TRUE; +} + +//*** PCRExtend() +// This function is used to extend a PCR in a specific bank. +void PCRExtend(TPMI_DH_PCR handle, // IN: PCR handle to be extended + TPMI_ALG_HASH hash, // IN: hash algorithm of PCR + UINT32 size, // IN: size of data to be extended + BYTE* data // IN: data to be extended +) +{ + BYTE* pcrData; + HASH_STATE hashState; + UINT16 pcrSize; + + pcrData = GetPcrPointer(hash, handle - PCR_FIRST); + + // Extend PCR if it is allocated + if(pcrData != NULL) + { + pcrSize = CryptHashGetDigestSize(hash); + CryptHashStart(&hashState, hash); + CryptDigestUpdate(&hashState, pcrSize, pcrData); + CryptDigestUpdate(&hashState, size, data); + CryptHashEnd(&hashState, pcrSize, pcrData); + + // PCR has changed so update the pcrCounter if necessary + PCRChanged(handle); + } + + return; +} + +//*** PCRComputeCurrentDigest() +// This function computes the digest of the selected PCR. +// +// As a side-effect, 'selection' is modified so that only the implemented PCR +// will have their bits still set. +void PCRComputeCurrentDigest( + TPMI_ALG_HASH hashAlg, // IN: hash algorithm to compute digest + TPML_PCR_SELECTION* selection, // IN/OUT: PCR selection (filtered on + // output) + TPM2B_DIGEST* digest // OUT: digest +) +{ + HASH_STATE hashState; + TPMS_PCR_SELECTION* select; + BYTE* pcrData; // will point to a digest + UINT32 pcrSize; + UINT32 pcr; + UINT32 i; + + // Initialize the hash + digest->t.size = CryptHashStart(&hashState, hashAlg); + pAssert(digest->t.size > 0 && digest->t.size < UINT16_MAX); + + // Iterate through the list of PCR selection structures + for(i = 0; i < selection->count; i++) + { + // Point to the current selection + select = &selection->pcrSelections[i]; // Point to the current selection + FilterPcr(select); // Clear out the bits for unimplemented PCR + + // Need the size of each digest + pcrSize = CryptHashGetDigestSize(selection->pcrSelections[i].hash); + + // Iterate through the selection + for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++) + { + if(IsPcrSelected(pcr, select)) // Is this PCR selected + { + // Get pointer to the digest data for the bank + pcrData = GetPcrPointer(selection->pcrSelections[i].hash, pcr); + pAssert(pcrData != NULL); + CryptDigestUpdate(&hashState, pcrSize, pcrData); // add to digest + } + } + } + // Complete hash stack + CryptHashEnd2B(&hashState, &digest->b); + + return; +} + +//*** PCRRead() +// This function is used to read a list of selected PCR. If the requested PCR +// number exceeds the maximum number that can be output, the 'selection' is +// adjusted to reflect the actual output PCR. +void PCRRead(TPML_PCR_SELECTION* selection, // IN/OUT: PCR selection (filtered on + // output) + TPML_DIGEST* digest, // OUT: digest + UINT32* pcrCounter // OUT: the current value of PCR generation + // number +) +{ + TPMS_PCR_SELECTION* select; + BYTE* pcrData; // will point to a digest + UINT32 pcr; + UINT32 i; + + digest->count = 0; + + // Iterate through the list of PCR selection structures + for(i = 0; i < selection->count; i++) + { + // Point to the current selection + select = &selection->pcrSelections[i]; // Point to the current selection + FilterPcr(select); // Clear out the bits for unimplemented PCR + + // Iterate through the selection + for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++) + { + if(IsPcrSelected(pcr, select)) // Is this PCR selected + { + // Check if number of digest exceed upper bound + if(digest->count > 7) + { + // Clear rest of the current select bitmap + while(pcr < IMPLEMENTATION_PCR + // do not round up! + && (pcr / 8) < select->sizeofSelect) + { + // do not round up! + select->pcrSelect[pcr / 8] &= (BYTE) ~(1 << (pcr % 8)); + pcr++; + } + // Exit inner loop + break; + } + // Need the size of each digest + digest->digests[digest->count].t.size = + CryptHashGetDigestSize(selection->pcrSelections[i].hash); + + // Get pointer to the digest data for the bank + pcrData = GetPcrPointer(selection->pcrSelections[i].hash, pcr); + pAssert(pcrData != NULL); + // Add to the data to digest + MemoryCopy(digest->digests[digest->count].t.buffer, + pcrData, + digest->digests[digest->count].t.size); + digest->count++; + } + } + // If we exit inner loop because we have exceed the output upper bound + if(digest->count > 7 && pcr < IMPLEMENTATION_PCR) + { + // Clear rest of the selection + while(i < selection->count) + { + MemorySet(selection->pcrSelections[i].pcrSelect, + 0, + selection->pcrSelections[i].sizeofSelect); + i++; + } + // exit outer loop + break; + } + } + + *pcrCounter = gr.pcrCounter; + + return; +} + +//*** PCRAllocate() +// This function is used to change the PCR allocation. +// Return Type: TPM_RC +// TPM_RC_NO_RESULT allocate failed +// TPM_RC_PCR improper allocation +TPM_RC +PCRAllocate(TPML_PCR_SELECTION* allocate, // IN: required allocation + UINT32* maxPCR, // OUT: Maximum number of PCR + UINT32* sizeNeeded, // OUT: required space + UINT32* sizeAvailable // OUT: available space +) +{ + UINT32 i, j, k; + TPML_PCR_SELECTION newAllocate; + // Initialize the flags to indicate if HCRTM PCR and DRTM PCR are allocated. + BOOL pcrHcrtm = FALSE; + BOOL pcrDrtm = FALSE; + + // Create the expected new PCR allocation based on the existing allocation + // and the new input: + // 1. if a PCR bank does not appear in the new allocation, the existing + // allocation of this PCR bank will be preserved. + // 2. if a PCR bank appears multiple times in the new allocation, only the + // last one will be in effect. + newAllocate = gp.pcrAllocated; + for(i = 0; i < allocate->count; i++) + { + for(j = 0; j < newAllocate.count; j++) + { + // If hash matches, the new allocation covers the old allocation + // for this particular bank. + // The assumption is the initial PCR allocation (from manufacture) + // has all the supported hash algorithms with an assigned bank + // (possibly empty). So there must be a match for any new bank + // allocation from the input. + if(newAllocate.pcrSelections[j].hash == allocate->pcrSelections[i].hash) + { + newAllocate.pcrSelections[j] = allocate->pcrSelections[i]; + break; + } + } + // The j loop must exit with a match. + pAssert(j < newAllocate.count); + } + + // Max PCR in a bank is MIN(implemented PCR, PCR with attributes defined) + *maxPCR = sizeof(s_initAttributes) / sizeof(PCR_Attributes); + if(*maxPCR > IMPLEMENTATION_PCR) + *maxPCR = IMPLEMENTATION_PCR; + + // Compute required size for allocation + *sizeNeeded = 0; + for(i = 0; i < newAllocate.count; i++) + { + UINT32 digestSize = CryptHashGetDigestSize(newAllocate.pcrSelections[i].hash); +#if defined(DRTM_PCR) + // Make sure that we end up with at least one DRTM PCR + pcrDrtm = pcrDrtm + || TestBit(DRTM_PCR, + newAllocate.pcrSelections[i].pcrSelect, + newAllocate.pcrSelections[i].sizeofSelect); + +#else // if DRTM PCR is not required, indicate that the allocation is OK + pcrDrtm = TRUE; +#endif + +#if defined(HCRTM_PCR) + // and one HCRTM PCR (since this is usually PCR 0...) + pcrHcrtm = pcrHcrtm + || TestBit(HCRTM_PCR, + newAllocate.pcrSelections[i].pcrSelect, + newAllocate.pcrSelections[i].sizeofSelect); +#else + pcrHcrtm = TRUE; +#endif + for(j = 0; j < newAllocate.pcrSelections[i].sizeofSelect; j++) + { + BYTE mask = 1; + for(k = 0; k < 8; k++) + { + if((newAllocate.pcrSelections[i].pcrSelect[j] & mask) != 0) + *sizeNeeded += digestSize; + mask = mask << 1; + } + } + } + + if(!pcrDrtm || !pcrHcrtm) + return TPM_RC_PCR; + + // In this particular implementation, we always have enough space to + // allocate PCR. Different implementation may return a sizeAvailable less + // than the sizeNeed. + *sizeAvailable = sizeof(s_pcrs); + + // Save the required allocation to NV. Note that after NV is written, the + // PCR allocation in NV is no longer consistent with the RAM data + // gp.pcrAllocated. The NV version reflect the allocate after next + // TPM_RESET, while the RAM version reflects the current allocation + NV_WRITE_PERSISTENT(pcrAllocated, newAllocate); + + return TPM_RC_SUCCESS; +} + +//*** PCRSetValue() +// This function is used to set the designated PCR in all banks to an initial value. +// The initial value is signed and will be sign extended into the entire PCR. +// +void PCRSetValue(TPM_HANDLE handle, // IN: the handle of the PCR to set + INT8 initialValue // IN: the value to set +) +{ + int i; + UINT32 pcr = handle - PCR_FIRST; + TPMI_ALG_HASH hash; + UINT16 digestSize; + BYTE* pcrData; + + // Iterate supported PCR bank algorithms to reset + for(i = 0; i < HASH_COUNT; i++) + { + hash = CryptHashGetAlgByIndex(i); + // Prevent runaway + if(hash == TPM_ALG_NULL) + break; + + // Get a pointer to the data + pcrData = GetPcrPointer(gp.pcrAllocated.pcrSelections[i].hash, pcr); + + // If the PCR is allocated + if(pcrData != NULL) + { + // And the size of the digest + digestSize = CryptHashGetDigestSize(hash); + + // Set the LSO to the input value + pcrData[digestSize - 1] = initialValue; + + // Sign extend + if(initialValue >= 0) + MemorySet(pcrData, 0, digestSize - 1); + else + MemorySet(pcrData, -1, digestSize - 1); + } + } +} + +//*** PCRResetDynamics +// This function is used to reset a dynamic PCR to 0. This function is used in +// DRTM sequence. +void PCRResetDynamics(void) +{ + UINT32 pcr, i; + + // Initialize PCR values + for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++) + { + // Iterate each hash algorithm bank + for(i = 0; i < gp.pcrAllocated.count; i++) + { + BYTE* pcrData; + UINT32 pcrSize; + + pcrData = GetPcrPointer(gp.pcrAllocated.pcrSelections[i].hash, pcr); + + if(pcrData != NULL) + { + pcrSize = + CryptHashGetDigestSize(gp.pcrAllocated.pcrSelections[i].hash); + + // Reset PCR + // Any PCR can be reset by locality 4 should be reset to 0 + if((s_initAttributes[pcr].resetLocality & 0x10) != 0) + MemorySet(pcrData, 0, pcrSize); + } + } + } + return; +} + +//*** PCRCapGetAllocation() +// This function is used to get the current allocation of PCR banks. +// Return Type: TPMI_YES_NO +// YES if the return count is 0 +// NO if the return count is not 0 +TPMI_YES_NO +PCRCapGetAllocation(UINT32 count, // IN: count of return + TPML_PCR_SELECTION* pcrSelection // OUT: PCR allocation list +) +{ + if(count == 0) + { + pcrSelection->count = 0; + return YES; + } + else + { + *pcrSelection = gp.pcrAllocated; + return NO; + } +} + +//*** PCRSetSelectBit() +// This function sets a bit in a bitmap array. +static void PCRSetSelectBit(UINT32 pcr, // IN: PCR number + BYTE* bitmap // OUT: bit map to be set +) +{ + bitmap[pcr / 8] |= (1 << (pcr % 8)); + return; +} + +//*** PCRGetProperty() +// This function returns the selected PCR property. +// Return Type: BOOL +// TRUE(1) the property type is implemented +// FALSE(0) the property type is not implemented +static BOOL PCRGetProperty(TPM_PT_PCR property, TPMS_TAGGED_PCR_SELECT* select) +{ + UINT32 pcr; + UINT32 groupIndex; + + select->tag = property; + // Always set the bitmap to be the size of all PCR + select->sizeofSelect = (IMPLEMENTATION_PCR + 7) / 8; + + // Initialize bitmap + MemorySet(select->pcrSelect, 0, select->sizeofSelect); + + // Collecting properties + for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++) + { + switch(property) + { + case TPM_PT_PCR_SAVE: + if(s_initAttributes[pcr].stateSave == SET) + PCRSetSelectBit(pcr, select->pcrSelect); + break; + case TPM_PT_PCR_EXTEND_L0: + if((s_initAttributes[pcr].extendLocality & 0x01) != 0) + PCRSetSelectBit(pcr, select->pcrSelect); + break; + case TPM_PT_PCR_RESET_L0: + if((s_initAttributes[pcr].resetLocality & 0x01) != 0) + PCRSetSelectBit(pcr, select->pcrSelect); + break; + case TPM_PT_PCR_EXTEND_L1: + if((s_initAttributes[pcr].extendLocality & 0x02) != 0) + PCRSetSelectBit(pcr, select->pcrSelect); + break; + case TPM_PT_PCR_RESET_L1: + if((s_initAttributes[pcr].resetLocality & 0x02) != 0) + PCRSetSelectBit(pcr, select->pcrSelect); + break; + case TPM_PT_PCR_EXTEND_L2: + if((s_initAttributes[pcr].extendLocality & 0x04) != 0) + PCRSetSelectBit(pcr, select->pcrSelect); + break; + case TPM_PT_PCR_RESET_L2: + if((s_initAttributes[pcr].resetLocality & 0x04) != 0) + PCRSetSelectBit(pcr, select->pcrSelect); + break; + case TPM_PT_PCR_EXTEND_L3: + if((s_initAttributes[pcr].extendLocality & 0x08) != 0) + PCRSetSelectBit(pcr, select->pcrSelect); + break; + case TPM_PT_PCR_RESET_L3: + if((s_initAttributes[pcr].resetLocality & 0x08) != 0) + PCRSetSelectBit(pcr, select->pcrSelect); + break; + case TPM_PT_PCR_EXTEND_L4: + if((s_initAttributes[pcr].extendLocality & 0x10) != 0) + PCRSetSelectBit(pcr, select->pcrSelect); + break; + case TPM_PT_PCR_RESET_L4: + if((s_initAttributes[pcr].resetLocality & 0x10) != 0) + PCRSetSelectBit(pcr, select->pcrSelect); + break; + case TPM_PT_PCR_DRTM_RESET: + // DRTM reset PCRs are the PCR reset by locality 4 + if((s_initAttributes[pcr].resetLocality & 0x10) != 0) + PCRSetSelectBit(pcr, select->pcrSelect); + break; +#if defined NUM_POLICY_PCR_GROUP && NUM_POLICY_PCR_GROUP > 0 + case TPM_PT_PCR_POLICY: + if(PCRBelongsPolicyGroup(pcr + PCR_FIRST, &groupIndex)) + PCRSetSelectBit(pcr, select->pcrSelect); + break; +#endif +#if defined NUM_AUTHVALUE_PCR_GROUP && NUM_AUTHVALUE_PCR_GROUP > 0 + case TPM_PT_PCR_AUTH: + if(PCRBelongsAuthGroup(pcr + PCR_FIRST, &groupIndex)) + PCRSetSelectBit(pcr, select->pcrSelect); + break; +#endif +#if ENABLE_PCR_NO_INCREMENT == YES + case TPM_PT_PCR_NO_INCREMENT: + if(PCRBelongsTCBGroup(pcr + PCR_FIRST)) + PCRSetSelectBit(pcr, select->pcrSelect); + break; +#endif + default: + // If property is not supported, stop scanning PCR attributes + // and return. + return FALSE; + break; + } + } + return TRUE; +} + +//*** PCRCapGetProperties() +// This function returns a list of PCR properties starting at 'property'. +// Return Type: TPMI_YES_NO +// YES if no more property is available +// NO if there are more properties not reported +TPMI_YES_NO +PCRCapGetProperties(TPM_PT_PCR property, // IN: the starting PCR property + UINT32 count, // IN: count of returned properties + TPML_TAGGED_PCR_PROPERTY* select // OUT: PCR select +) +{ + TPMI_YES_NO more = NO; + UINT32 i; + + // Initialize output property list + select->count = 0; + + // The maximum count of properties we may return is MAX_PCR_PROPERTIES + if(count > MAX_PCR_PROPERTIES) + count = MAX_PCR_PROPERTIES; + + // TPM_PT_PCR_FIRST is defined as 0 in spec. It ensures that property + // value would never be less than TPM_PT_PCR_FIRST + cAssert(TPM_PT_PCR_FIRST == 0); + + // Iterate PCR properties. TPM_PT_PCR_LAST is the index of the last property + // implemented on the TPM. + for(i = property; i <= TPM_PT_PCR_LAST; i++) + { + if(select->count < count) + { + // If we have not filled up the return list, add more properties to it + if(PCRGetProperty(i, &select->pcrProperty[select->count])) + // only increment if the property is implemented + select->count++; + } + else + { + // If the return list is full but we still have properties + // available, report this and stop iterating. + more = YES; + break; + } + } + return more; +} + +//*** PCRCapGetHandles() +// This function is used to get a list of handles of PCR, started from 'handle'. +// If 'handle' exceeds the maximum PCR handle range, an empty list will be +// returned and the return value will be NO. +// Return Type: TPMI_YES_NO +// YES if there are more handles available +// NO all the available handles has been returned +TPMI_YES_NO +PCRCapGetHandles(TPMI_DH_PCR handle, // IN: start handle + UINT32 count, // IN: count of returned handles + TPML_HANDLE* handleList // OUT: list of handle +) +{ + TPMI_YES_NO more = NO; + UINT32 i; + + pAssert(HandleGetType(handle) == TPM_HT_PCR); + + // Initialize output handle list + handleList->count = 0; + + // The maximum count of handles we may return is MAX_CAP_HANDLES + if(count > MAX_CAP_HANDLES) + count = MAX_CAP_HANDLES; + + // Iterate PCR handle range + for(i = handle & HR_HANDLE_MASK; i <= PCR_LAST; i++) + { + if(handleList->count < count) + { + // If we have not filled up the return list, add this PCR + // handle to it + handleList->handle[handleList->count] = i + PCR_FIRST; + handleList->count++; + } + else + { + // If the return list is full but we still have PCR handle + // available, report this and stop iterating + more = YES; + break; + } + } + return more; +} + +//*** PCRBankSave() +// This function is for fTPM TA internal use only. +// It saves the PCR values during early boot stage. +// https://trustedcomputinggroup.org/wp-content/uploads/TCG_PCClient_PFP_r1p05_v23_pub.pdf#page=36 +#define BACKUP_LAST_PCR_INDEX 7 +void PCRBankSave(void) +{ + INT32 pcr, i; + TPM_ALG_ID hash_alg[] = { TPM_ALG_SHA256, TPM_ALG_SHA384, TPM_ALG_SHA512 }; + UINT32 hash_alg_count = sizeof(hash_alg) / sizeof(TYPE_OF_TPM_ALG_ID); + UINT32 backup_pcr_index = BACKUP_LAST_PCR_INDEX; + + for (pcr = backup_pcr_index; pcr >= 0; pcr--) { + for (i = 0; i < hash_alg_count; i++) { + TPM_ALG_ID alg_id = hash_alg[i]; + BYTE *pcr_data, *pcr_saved_data; + UINT32 pcr_size; + + pcr_data = GetPcrPointer(alg_id, pcr); + pcr_saved_data = GetSavedPcrPointer(alg_id, pcr); + pcr_size = CryptHashGetDigestSize(alg_id); + + if ((NULL != pcr_data) && (NULL != pcr_saved_data)) + memcpy(pcr_saved_data, pcr_data, pcr_size); + } + } +} + +//*** PCRBankRestore() +// This function is for fTPM TA internal use only. +// It restores the PCR values after early boot stage. +void PCRBankRestore(void) +{ + INT32 pcr, i; + TPM_ALG_ID hash_alg[] = { TPM_ALG_SHA256, TPM_ALG_SHA384, TPM_ALG_SHA512 }; + UINT32 hash_alg_count = sizeof(hash_alg) / sizeof(TYPE_OF_TPM_ALG_ID); + UINT32 backup_pcr_index = BACKUP_LAST_PCR_INDEX; + + for (pcr = backup_pcr_index; pcr >= 0; pcr--) { + for (i = 0; i < hash_alg_count; i++) { + TPM_ALG_ID alg_id = hash_alg[i]; + BYTE *pcr_data, *pcr_saved_data; + UINT32 pcr_size; + + pcr_data = GetPcrPointer(alg_id, pcr); + pcr_saved_data = GetSavedPcrPointer(alg_id, pcr); + pcr_size = CryptHashGetDigestSize(alg_id); + + if ((NULL != pcr_data) && (NULL != pcr_saved_data)) + memcpy(pcr_data, pcr_saved_data, pcr_size); + } + } +} diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/PP.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/PP.c new file mode 100644 index 0000000..5d31f80 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/PP.c @@ -0,0 +1,170 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// This file contains the functions that support the physical presence operations +// of the TPM. + +//** Includes + +#include "Tpm.h" + +//** Functions + +//*** PhysicalPresencePreInstall_Init() +// This function is used to initialize the array of commands that always require +// confirmation with physical presence. The array is an array of bits that +// has a correspondence with the command code. +// +// This command should only ever be executable in a manufacturing setting or in +// a simulation. +// +// When set, these cannot be cleared. +// +void PhysicalPresencePreInstall_Init(void) +{ + COMMAND_INDEX commandIndex; + // Clear all the PP commands + MemorySet(&gp.ppList, 0, sizeof(gp.ppList)); + + // Any command that is PP_REQUIRED should be SET + for(commandIndex = 0; commandIndex < COMMAND_COUNT; commandIndex++) + { + if(s_commandAttributes[commandIndex] & IS_IMPLEMENTED + && s_commandAttributes[commandIndex] & PP_REQUIRED) + SET_BIT(commandIndex, gp.ppList); + } + // Write PP list to NV + NV_SYNC_PERSISTENT(ppList); + return; +} + +//*** PhysicalPresenceCommandSet() +// This function is used to set the indicator that a command requires +// PP confirmation. +void PhysicalPresenceCommandSet(TPM_CC commandCode // IN: command code +) +{ + COMMAND_INDEX commandIndex = CommandCodeToCommandIndex(commandCode); + + // if the command isn't implemented, the do nothing + if(commandIndex == UNIMPLEMENTED_COMMAND_INDEX) + return; + + // only set the bit if this is a command for which PP is allowed + if(s_commandAttributes[commandIndex] & PP_COMMAND) + SET_BIT(commandIndex, gp.ppList); + return; +} + +//*** PhysicalPresenceCommandClear() +// This function is used to clear the indicator that a command requires PP +// confirmation. +void PhysicalPresenceCommandClear(TPM_CC commandCode // IN: command code +) +{ + COMMAND_INDEX commandIndex = CommandCodeToCommandIndex(commandCode); + + // If the command isn't implemented, then don't do anything + if(commandIndex == UNIMPLEMENTED_COMMAND_INDEX) + return; + + // Only clear the bit if the command does not require PP + if((s_commandAttributes[commandIndex] & PP_REQUIRED) == 0) + CLEAR_BIT(commandIndex, gp.ppList); + + return; +} + +//*** PhysicalPresenceIsRequired() +// This function indicates if PP confirmation is required for a command. +// Return Type: BOOL +// TRUE(1) physical presence is required +// FALSE(0) physical presence is not required +BOOL PhysicalPresenceIsRequired(COMMAND_INDEX commandIndex // IN: command index +) +{ + // Check the bit map. If the bit is SET, PP authorization is required + return (TEST_BIT(commandIndex, gp.ppList)); +} + +//*** PhysicalPresenceCapGetCCList() +// This function returns a list of commands that require PP confirmation. The +// list starts from the first implemented command that has a command code that +// the same or greater than 'commandCode'. +// Return Type: TPMI_YES_NO +// YES if there are more command codes available +// NO all the available command codes have been returned +TPMI_YES_NO +PhysicalPresenceCapGetCCList(TPM_CC commandCode, // IN: start command code + UINT32 count, // IN: count of returned TPM_CC + TPML_CC* commandList // OUT: list of TPM_CC +) +{ + TPMI_YES_NO more = NO; + COMMAND_INDEX commandIndex; + + // Initialize output handle list + commandList->count = 0; + + // The maximum count of command we may return is MAX_CAP_CC + if(count > MAX_CAP_CC) + count = MAX_CAP_CC; + + // Collect PP commands + for(commandIndex = GetClosestCommandIndex(commandCode); + commandIndex != UNIMPLEMENTED_COMMAND_INDEX; + commandIndex = GetNextCommandIndex(commandIndex)) + { + if(PhysicalPresenceIsRequired(commandIndex)) + { + if(commandList->count < count) + { + // If we have not filled up the return list, add this command + // code to it + commandList->commandCodes[commandList->count] = + GetCommandCode(commandIndex); + commandList->count++; + } + else + { + // If the return list is full but we still have PP command + // available, report this and stop iterating + more = YES; + break; + } + } + } + return more; +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/Session.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/Session.c new file mode 100644 index 0000000..a6a1eb5 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/Session.c @@ -0,0 +1,1026 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//**Introduction +/* + The code in this file is used to manage the session context counter. + The scheme implemented here is a "truncated counter". + This scheme allows the TPM to not need TPM_SU_CLEAR for a + very long period of time and still not have the context + count for a session repeated. + + The counter (contextCounter)in this implementation is a UINT64 but + can be smaller. The "tracking array" (contextArray) only + has 16-bits per context. The tracking array is the data + that needs to be saved and restored across TPM_SU_STATE so that + sessions are not lost when the system enters the sleep state. + Also, when the TPM is active, the tracking array is kept in + RAM making it important that the number of bytes for each + entry be kept as small as possible. + + The TPM prevents "collisions" of these truncated values by + not allowing a contextID to be assigned if it would be the + same as an existing value. Since the array holds 16 bits, + after a context has been saved, an additional 2^16-1 contexts + may be saved before the count would again match. The normal + expectation is that the context will be flushed before its count + value is needed again but it is always possible to have long-lived + sessions. + + The contextID is assigned when the context is saved (TPM2_ContextSave()). + At that time, the TPM will compare the low-order 16 bits of + contextCounter to the existing values in contextArray and if one + matches, the TPM will return TPM_RC_CONTEXT_GAP (by construction, + the entry that contains the matching value is the oldest + context). + + The expected remediation by the TRM is to load the oldest saved + session context (the one found by the TPM), and save it. Since loading + the oldest session also eliminates its contextID value from + contextArray, there TPM will always be able to load and save the oldest + existing context. + + In the worst case, software may have to load and save several contexts + in order to save an additional one. This should happen very infrequently. + + When the TPM searches contextArray and finds that none of the contextIDs + match the low-order 16-bits of contextCount, the TPM can copy the low bits + to the contextArray associated with the session, and increment contextCount. + + There is one entry in contextArray for each of the active sessions + allowed by the TPM implementation. This array contains either a + context count, an index, or a value indicating the slot is available (0). + + The index into the contextArray is the handle for the session with the region + selector byte of the session set to zero. If an entry in contextArray contains + 0, then the corresponding handle may be assigned to a session. If the entry + contains a value that is less than or equal to the number of loaded sessions + for the TPM, then the array entry is the slot in which the context is loaded. + + EXAMPLE: If the TPM allows 8 loaded sessions, then the slot numbers would + be 1-8 and a contextArrary value in that range would represent the loaded + session. + + NOTE: When the TPM firmware determines that the array entry is for a loaded + session, it will subtract 1 to create the zero-based slot number. + + There is one significant corner case in this scheme. When the contextCount + is equal to a value in the contextArray, the oldest session needs to be + recycled or flushed. In order to recycle the session, it must be loaded. + To be loaded, there must be an available slot. Rather than require that a + spare slot be available all the time, the TPM will check to see if the + contextCount is equal to some value in the contextArray when a session is + created. This prevents the last session slot from being used when it + is likely that a session will need to be recycled. + + If a TPM with both 1.2 and 2.0 functionality uses this scheme for both + 1.2 and 2.0 sessions, and the list of active contexts is read with + TPM_GetCapabiltiy(), the TPM will create 32-bit representations of the + list that contains 16-bit values (the TPM2_GetCapability() returns a list + of handles for active sessions rather than a list of contextID). The full + contextID has high-order bits that are either the same as the current + contextCount or one less. It is one less if the 16-bits + of the contextArray has a value that is larger than the low-order 16 bits + of contextCount. +*/ + +//** Includes, Defines, and Local Variables +#define SESSION_C +#include "Tpm.h" + +//** File Scope Function -- ContextIdSetOldest() +/* + This function is called when the oldest contextID is being loaded or deleted. + Once a saved context becomes the oldest, it stays the oldest until it is + deleted. + + Finding the oldest is a bit tricky. It is not just the numeric comparison of + values but is dependent on the value of contextCounter. + + Assume we have a small contextArray with 8, 4-bit values with values 1 and 2 + used to indicate the loaded context slot number. Also assume that the array + contains hex values of (0 0 1 0 3 0 9 F) and that the contextCounter is an + 8-bit counter with a value of 0x37. Since the low nibble is 7, that means + that values above 7 are older than values below it and, in this example, + 9 is the oldest value. + + Note if we subtract the counter value, from each slot that contains a saved + contextID we get (- - - - B - 2 - 8) and the oldest entry is now easy to find. +*/ +static void ContextIdSetOldest(void) +{ + CONTEXT_SLOT lowBits; + CONTEXT_SLOT entry; + CONTEXT_SLOT smallest = ((CONTEXT_SLOT)~0); + UINT32 i; + + // Set oldestSaveContext to a value indicating none assigned + s_oldestSavedSession = MAX_ACTIVE_SESSIONS + 1; + + lowBits = (CONTEXT_SLOT)gr.contextCounter; + for(i = 0; i < MAX_ACTIVE_SESSIONS; i++) + { + entry = gr.contextArray[i]; + + // only look at entries that are saved contexts + if(entry > MAX_LOADED_SESSIONS) + { + // Use a less than or equal in case the oldest + // is brand new (= lowBits-1) and equal to our initial + // value for smallest. + if(((CONTEXT_SLOT)(entry - lowBits)) <= smallest) + { + smallest = (entry - lowBits); + s_oldestSavedSession = i; + } + } + } + // When we finish, either the s_oldestSavedSession still has its initial + // value, or it has the index of the oldest saved context. +} + +//** Startup Function -- SessionStartup() +// This function initializes the session subsystem on TPM2_Startup(). +BOOL SessionStartup(STARTUP_TYPE type) +{ + UINT32 i; + + // Initialize session slots. At startup, all the in-memory session slots + // are cleared and marked as not occupied + for(i = 0; i < MAX_LOADED_SESSIONS; i++) + s_sessions[i].occupied = FALSE; // session slot is not occupied + + // The free session slots the number of maximum allowed loaded sessions + s_freeSessionSlots = MAX_LOADED_SESSIONS; + + // Initialize context ID data. On a ST_SAVE or hibernate sequence, it will + // scan the saved array of session context counts, and clear any entry that + // references a session that was in memory during the state save since that + // memory was not preserved over the ST_SAVE. + if(type == SU_RESUME || type == SU_RESTART) + { + // On ST_SAVE we preserve the contexts that were saved but not the ones + // in memory + for(i = 0; i < MAX_ACTIVE_SESSIONS; i++) + { + // If the array value is unused or references a loaded session then + // that loaded session context is lost and the array entry is + // reclaimed. + if(gr.contextArray[i] <= MAX_LOADED_SESSIONS) + gr.contextArray[i] = 0; + } + // Find the oldest session in context ID data and set it in + // s_oldestSavedSession + ContextIdSetOldest(); + } + else + { + // For STARTUP_CLEAR, clear out the contextArray + for(i = 0; i < MAX_ACTIVE_SESSIONS; i++) + gr.contextArray[i] = 0; + + // reset the context counter + gr.contextCounter = MAX_LOADED_SESSIONS + 1; + + // Initialize oldest saved session + s_oldestSavedSession = MAX_ACTIVE_SESSIONS + 1; + } + return TRUE; +} + +//************************************************ +//** Access Functions +//************************************************ + +//*** SessionIsLoaded() +// This function test a session handle references a loaded session. The handle +// must have previously been checked to make sure that it is a valid handle for +// an authorization session. +// NOTE: A PWAP authorization does not have a session. +// +// Return Type: BOOL +// TRUE(1) session is loaded +// FALSE(0) session is not loaded +// +BOOL SessionIsLoaded(TPM_HANDLE handle // IN: session handle +) +{ + pAssert(HandleGetType(handle) == TPM_HT_POLICY_SESSION + || HandleGetType(handle) == TPM_HT_HMAC_SESSION); + + handle = handle & HR_HANDLE_MASK; + + // if out of range of possible active session, or not assigned to a loaded + // session return false + if(handle >= MAX_ACTIVE_SESSIONS || gr.contextArray[handle] == 0 + || gr.contextArray[handle] > MAX_LOADED_SESSIONS) + return FALSE; + + return TRUE; +} + +//*** SessionIsSaved() +// This function test a session handle references a saved session. The handle +// must have previously been checked to make sure that it is a valid handle for +// an authorization session. +// NOTE: An password authorization does not have a session. +// +// This function requires that the handle be a valid session handle. +// +// Return Type: BOOL +// TRUE(1) session is saved +// FALSE(0) session is not saved +// +BOOL SessionIsSaved(TPM_HANDLE handle // IN: session handle +) +{ + pAssert(HandleGetType(handle) == TPM_HT_POLICY_SESSION + || HandleGetType(handle) == TPM_HT_HMAC_SESSION); + + handle = handle & HR_HANDLE_MASK; + // if out of range of possible active session, or not assigned, or + // assigned to a loaded session, return false + if(handle >= MAX_ACTIVE_SESSIONS || gr.contextArray[handle] == 0 + || gr.contextArray[handle] <= MAX_LOADED_SESSIONS) + return FALSE; + + return TRUE; +} + +//*** SequenceNumberForSavedContextIsValid() +// This function validates that the sequence number and handle value within a +// saved context are valid. +BOOL SequenceNumberForSavedContextIsValid( + TPMS_CONTEXT* context // IN: pointer to a context structure to be + // validated +) +{ +#define MAX_CONTEXT_GAP ((UINT64)((CONTEXT_SLOT)~0) + 1) + + TPM_HANDLE handle = context->savedHandle & HR_HANDLE_MASK; + + if( // Handle must be with the range of active sessions + handle >= MAX_ACTIVE_SESSIONS + // the array entry must be for a saved context + || gr.contextArray[handle] <= MAX_LOADED_SESSIONS + // the array entry must agree with the sequence number + || gr.contextArray[handle] != (CONTEXT_SLOT)context->sequence + // the provided sequence number has to be less than the current counter + || context->sequence > gr.contextCounter + // but not so much that it could not be a valid sequence number + || gr.contextCounter - context->sequence > MAX_CONTEXT_GAP) + return FALSE; + + return TRUE; +} + +//*** SessionPCRValueIsCurrent() +// +// This function is used to check if PCR values have been updated since the +// last time they were checked in a policy session. +// +// This function requires the session is loaded. +// Return Type: BOOL +// TRUE(1) PCR value is current +// FALSE(0) PCR value is not current +BOOL SessionPCRValueIsCurrent(SESSION* session // IN: session structure +) +{ + if(session->pcrCounter != 0 && session->pcrCounter != gr.pcrCounter) + return FALSE; + else + return TRUE; +} + +//*** SessionGet() +// This function returns a pointer to the session object associated with a +// session handle. +// +// The function requires that the session is loaded. +SESSION* SessionGet(TPM_HANDLE handle // IN: session handle +) +{ + size_t slotIndex; + CONTEXT_SLOT sessionIndex; + + pAssert(HandleGetType(handle) == TPM_HT_POLICY_SESSION + || HandleGetType(handle) == TPM_HT_HMAC_SESSION); + + slotIndex = handle & HR_HANDLE_MASK; + + pAssert(slotIndex < MAX_ACTIVE_SESSIONS); + + // get the contents of the session array. Because session is loaded, we + // should always get a valid sessionIndex + sessionIndex = gr.contextArray[slotIndex] - 1; + + pAssert(sessionIndex < MAX_LOADED_SESSIONS); + + return &s_sessions[sessionIndex].session; +} + +//************************************************ +//** Utility Functions +//************************************************ + +//*** ContextIdSessionCreate() +// +// This function is called when a session is created. It will check +// to see if the current gap would prevent a context from being saved. If +// so it will return TPM_RC_CONTEXT_GAP. Otherwise, it will try to find +// an open slot in contextArray, set contextArray to the slot. +// +// This routine requires that the caller has determined the session array +// index for the session. +// +// Return Type: TPM_RC +// TPM_RC_CONTEXT_GAP can't assign a new contextID until the oldest +// saved session context is recycled +// TPM_RC_SESSION_HANDLE there is no slot available in the context array +// for tracking of this session context +static TPM_RC ContextIdSessionCreate( + TPM_HANDLE* handle, // OUT: receives the assigned handle. This will + // be an index that must be adjusted by the + // caller according to the type of the + // session created + UINT32 sessionIndex // IN: The session context array entry that will + // be occupied by the created session +) +{ + pAssert(sessionIndex < MAX_LOADED_SESSIONS); + + // check to see if creating the context is safe + // Is this going to be an assignment for the last session context + // array entry? If so, then there will be no room to recycle the + // oldest context if needed. If the gap is not at maximum, then + // it will be possible to save a context if it becomes necessary. + if(s_oldestSavedSession < MAX_ACTIVE_SESSIONS && s_freeSessionSlots == 1) + { + // See if the gap is at maximum + // The current value of the contextCounter will be assigned to the next + // saved context. If the value to be assigned would make the same as an + // existing context, then we can't use it because of the ambiguity it would + // create. + if((CONTEXT_SLOT)gr.contextCounter == gr.contextArray[s_oldestSavedSession]) + return TPM_RC_CONTEXT_GAP; + } + + // Find an unoccupied entry in the contextArray + for(*handle = 0; *handle < MAX_ACTIVE_SESSIONS; (*handle)++) + { + if(gr.contextArray[*handle] == 0) + { + // indicate that the session associated with this handle + // references a loaded session + gr.contextArray[*handle] = (CONTEXT_SLOT)(sessionIndex + 1); + return TPM_RC_SUCCESS; + } + } + return TPM_RC_SESSION_HANDLES; +} + +//*** SessionCreate() +// +// This function does the detailed work for starting an authorization session. +// This is done in a support routine rather than in the action code because +// the session management may differ in implementations. This implementation +// uses a fixed memory allocation to hold sessions and a fixed allocation +// to hold the contextID for the saved contexts. +// +// Return Type: TPM_RC +// TPM_RC_CONTEXT_GAP need to recycle sessions +// TPM_RC_SESSION_HANDLE active session space is full +// TPM_RC_SESSION_MEMORY loaded session space is full +TPM_RC +SessionCreate(TPM_SE sessionType, // IN: the session type + TPMI_ALG_HASH authHash, // IN: the hash algorithm + TPM2B_NONCE* nonceCaller, // IN: initial nonceCaller + TPMT_SYM_DEF* symmetric, // IN: the symmetric algorithm + TPMI_DH_ENTITY bind, // IN: the bind object + TPM2B_DATA* seed, // IN: seed data + TPM_HANDLE* sessionHandle, // OUT: the session handle + TPM2B_NONCE* nonceTpm // OUT: the session nonce +) +{ + TPM_RC result = TPM_RC_SUCCESS; + CONTEXT_SLOT slotIndex; + SESSION* session = NULL; + + pAssert(sessionType == TPM_SE_HMAC || sessionType == TPM_SE_POLICY + || sessionType == TPM_SE_TRIAL); + + // If there are no open spots in the session array, then no point in searching + if(s_freeSessionSlots == 0) + return TPM_RC_SESSION_MEMORY; + + // Find a space for loading a session + for(slotIndex = 0; slotIndex < MAX_LOADED_SESSIONS; slotIndex++) + { + // Is this available? + if(s_sessions[slotIndex].occupied == FALSE) + { + session = &s_sessions[slotIndex].session; + break; + } + } + // if no spot found, then this is an internal error + if(slotIndex >= MAX_LOADED_SESSIONS) + FAIL(FATAL_ERROR_INTERNAL); + + // Call context ID function to get a handle. TPM_RC_SESSION_HANDLE may be + // returned from ContextIdHandelAssign() + result = ContextIdSessionCreate(sessionHandle, slotIndex); + if(result != TPM_RC_SUCCESS) + return result; + + //*** Only return from this point on is TPM_RC_SUCCESS + + // Can now indicate that the session array entry is occupied. + s_freeSessionSlots--; + s_sessions[slotIndex].occupied = TRUE; + + // Initialize the session data + MemorySet(session, 0, sizeof(SESSION)); + + // Initialize internal session data + session->authHashAlg = authHash; + // Initialize session type + if(sessionType == TPM_SE_HMAC) + { + *sessionHandle += HMAC_SESSION_FIRST; + } + else + { + *sessionHandle += POLICY_SESSION_FIRST; + + // For TPM_SE_POLICY or TPM_SE_TRIAL + session->attributes.isPolicy = SET; + if(sessionType == TPM_SE_TRIAL) + session->attributes.isTrialPolicy = SET; + + SessionSetStartTime(session); + + // Initialize policyDigest. policyDigest is initialized with a string of 0 + // of session algorithm digest size. Since the session is already clear. + // Just need to set the size + session->u2.policyDigest.t.size = + CryptHashGetDigestSize(session->authHashAlg); + } + // Create initial session nonce + session->nonceTPM.t.size = nonceCaller->t.size; + CryptRandomGenerate(session->nonceTPM.t.size, session->nonceTPM.t.buffer); + MemoryCopy2B(&nonceTpm->b, &session->nonceTPM.b, sizeof(nonceTpm->t.buffer)); + + // Set up session parameter encryption algorithm + session->symmetric = *symmetric; + + // If there is a bind object or a session secret, then need to compute + // a sessionKey. + if(bind != TPM_RH_NULL || seed->t.size != 0) + { + // sessionKey = KDFa(hash, (authValue || seed), "ATH", nonceTPM, + // nonceCaller, bits) + // The HMAC key for generating the sessionSecret can be the concatenation + // of an authorization value and a seed value + TPM2B_TYPE(KEY, (sizeof(TPMT_HA) + sizeof(seed->t.buffer))); + TPM2B_KEY key; + + // Get hash size, which is also the length of sessionKey + session->sessionKey.t.size = CryptHashGetDigestSize(session->authHashAlg); + + // Get authValue of associated entity + EntityGetAuthValue(bind, (TPM2B_AUTH*)&key); + pAssert(key.t.size + seed->t.size <= sizeof(key.t.buffer)); + + // Concatenate authValue and seed + MemoryConcat2B(&key.b, &seed->b, sizeof(key.t.buffer)); + + // Compute the session key + CryptKDFa(session->authHashAlg, + &key.b, + SESSION_KEY, + &session->nonceTPM.b, + &nonceCaller->b, + session->sessionKey.t.size * 8, + session->sessionKey.t.buffer, + NULL, + FALSE); + } + + // Copy the name of the entity that the HMAC session is bound to + // Policy session is not bound to an entity + if(bind != TPM_RH_NULL && sessionType == TPM_SE_HMAC) + { + session->attributes.isBound = SET; + SessionComputeBoundEntity(bind, &session->u1.boundEntity); + } + // If there is a bind object and it is subject to DA, then use of this session + // is subject to DA regardless of how it is used. + session->attributes.isDaBound = (bind != TPM_RH_NULL) + && (IsDAExempted(bind) == FALSE); + + // If the session is bound, then check to see if it is bound to lockoutAuth + session->attributes.isLockoutBound = (session->attributes.isDaBound == SET) + && (bind == TPM_RH_LOCKOUT); + return TPM_RC_SUCCESS; +} + +//*** SessionContextSave() +// This function is called when a session context is to be saved. The +// contextID of the saved session is returned. If no contextID can be +// assigned, then the routine returns TPM_RC_CONTEXT_GAP. +// If the function completes normally, the session slot will be freed. +// +// This function requires that 'handle' references a loaded session. +// Otherwise, it should not be called at the first place. +// +// Return Type: TPM_RC +// TPM_RC_CONTEXT_GAP a contextID could not be assigned +// TPM_RC_TOO_MANY_CONTEXTS the counter maxed out +// +TPM_RC +SessionContextSave(TPM_HANDLE handle, // IN: session handle + CONTEXT_COUNTER* contextID // OUT: assigned contextID +) +{ + UINT32 contextIndex; + CONTEXT_SLOT slotIndex; + + pAssert(SessionIsLoaded(handle)); + + // check to see if the gap is already maxed out + // Need to have a saved session + if(s_oldestSavedSession < MAX_ACTIVE_SESSIONS + // if the oldest saved session has the same value as the low bits + // of the contextCounter, then the GAP is maxed out. + && gr.contextArray[s_oldestSavedSession] == (CONTEXT_SLOT)gr.contextCounter) + return TPM_RC_CONTEXT_GAP; + + // if the caller wants the context counter, set it + if(contextID != NULL) + *contextID = gr.contextCounter; + + contextIndex = handle & HR_HANDLE_MASK; + pAssert(contextIndex < MAX_ACTIVE_SESSIONS); + + // Extract the session slot number referenced by the contextArray + // because we are going to overwrite this with the low order + // contextID value. + slotIndex = gr.contextArray[contextIndex] - 1; + + // Set the contextID for the contextArray + gr.contextArray[contextIndex] = (CONTEXT_SLOT)gr.contextCounter; + + // Increment the counter + gr.contextCounter++; + + // In the unlikely event that the 64-bit context counter rolls over... + if(gr.contextCounter == 0) + { + // back it up + gr.contextCounter--; + // return an error + return TPM_RC_TOO_MANY_CONTEXTS; + } + // if the low-order bits wrapped, need to advance the value to skip over + // the values used to indicate that a session is loaded + if(((CONTEXT_SLOT)gr.contextCounter) == 0) + gr.contextCounter += MAX_LOADED_SESSIONS + 1; + + // If no other sessions are saved, this is now the oldest. + if(s_oldestSavedSession >= MAX_ACTIVE_SESSIONS) + s_oldestSavedSession = contextIndex; + + // Mark the session slot as unoccupied + s_sessions[slotIndex].occupied = FALSE; + + // and indicate that there is an additional open slot + s_freeSessionSlots++; + + return TPM_RC_SUCCESS; +} + +//*** SessionContextLoad() +// This function is used to load a session from saved context. The session +// handle must be for a saved context. +// +// If the gap is at a maximum, then the only session that can be loaded is +// the oldest session, otherwise TPM_RC_CONTEXT_GAP is returned. +/// +// This function requires that 'handle' references a valid saved session. +// +// Return Type: TPM_RC +// TPM_RC_SESSION_MEMORY no free session slots +// TPM_RC_CONTEXT_GAP the gap count is maximum and this +// is not the oldest saved context +// +TPM_RC +SessionContextLoad(SESSION_BUF* session, // IN: session structure from saved context + TPM_HANDLE* handle // IN/OUT: session handle +) +{ + UINT32 contextIndex; + CONTEXT_SLOT slotIndex; + + pAssert(HandleGetType(*handle) == TPM_HT_POLICY_SESSION + || HandleGetType(*handle) == TPM_HT_HMAC_SESSION); + + // Don't bother looking if no openings + if(s_freeSessionSlots == 0) + return TPM_RC_SESSION_MEMORY; + + // Find a free session slot to load the session + for(slotIndex = 0; slotIndex < MAX_LOADED_SESSIONS; slotIndex++) + if(s_sessions[slotIndex].occupied == FALSE) + break; + + // if no spot found, then this is an internal error + pAssert(slotIndex < MAX_LOADED_SESSIONS); + + contextIndex = *handle & HR_HANDLE_MASK; // extract the index + + // If there is only one slot left, and the gap is at maximum, the only session + // context that we can safely load is the oldest one. + if(s_oldestSavedSession < MAX_ACTIVE_SESSIONS && s_freeSessionSlots == 1 + && (CONTEXT_SLOT)gr.contextCounter == gr.contextArray[s_oldestSavedSession] + && contextIndex != s_oldestSavedSession) + return TPM_RC_CONTEXT_GAP; + + pAssert(contextIndex < MAX_ACTIVE_SESSIONS); + + // set the contextArray value to point to the session slot where + // the context is loaded + gr.contextArray[contextIndex] = slotIndex + 1; + + // if this was the oldest context, find the new oldest + if(contextIndex == s_oldestSavedSession) + ContextIdSetOldest(); + + // Copy session data to session slot + MemoryCopy(&s_sessions[slotIndex].session, session, sizeof(SESSION)); + + // Set session slot as occupied + s_sessions[slotIndex].occupied = TRUE; + + // Reduce the number of open spots + s_freeSessionSlots--; + + return TPM_RC_SUCCESS; +} + +//*** SessionFlush() +// This function is used to flush a session referenced by its handle. If the +// session associated with 'handle' is loaded, the session array entry is +// marked as available. +// +// This function requires that 'handle' be a valid active session. +// +void SessionFlush(TPM_HANDLE handle // IN: loaded or saved session handle +) +{ + CONTEXT_SLOT slotIndex; + UINT32 contextIndex; // Index into contextArray + + pAssert((HandleGetType(handle) == TPM_HT_POLICY_SESSION + || HandleGetType(handle) == TPM_HT_HMAC_SESSION) + && (SessionIsLoaded(handle) || SessionIsSaved(handle))); + + // Flush context ID of this session + // Convert handle to an index into the contextArray + contextIndex = handle & HR_HANDLE_MASK; + + pAssert(contextIndex < sizeof(gr.contextArray) / sizeof(gr.contextArray[0])); + + // Get the current contents of the array + slotIndex = gr.contextArray[contextIndex]; + + // Mark context array entry as available + gr.contextArray[contextIndex] = 0; + + // Is this a saved session being flushed + if(slotIndex > MAX_LOADED_SESSIONS) + { + // Flushing the oldest session? + if(contextIndex == s_oldestSavedSession) + // If so, find a new value for oldest. + ContextIdSetOldest(); + } + else + { + // Adjust slot index to point to session array index + slotIndex -= 1; + + // Free session array index + s_sessions[slotIndex].occupied = FALSE; + s_freeSessionSlots++; + } + + return; +} + +//*** SessionComputeBoundEntity() +// This function computes the binding value for a session. The binding value +// for a reserved handle is the handle itself. For all the other entities, +// the authValue at the time of binding is included to prevent squatting. +// For those values, the Name and the authValue are concatenated +// into the bind buffer. If they will not both fit, the will be overlapped +// by XORing bytes. If XOR is required, the bind value will be full. +void SessionComputeBoundEntity(TPMI_DH_ENTITY entityHandle, // IN: handle of entity + TPM2B_NAME* bind // OUT: binding value +) +{ + TPM2B_AUTH auth; + BYTE* pAuth = auth.t.buffer; + UINT16 i; + + // Get name + EntityGetName(entityHandle, bind); + + // // The bound value of a reserved handle is the handle itself + // if(bind->t.size == sizeof(TPM_HANDLE)) return; + + // For all the other entities, concatenate the authorization value to the name. + // Get a local copy of the authorization value because some overlapping + // may be necessary. + EntityGetAuthValue(entityHandle, &auth); + + // Make sure that the extra space is zeroed + MemorySet(&bind->t.name[bind->t.size], 0, sizeof(bind->t.name) - bind->t.size); + // XOR the authValue at the end of the name + for(i = sizeof(bind->t.name) - auth.t.size; i < sizeof(bind->t.name); i++) + bind->t.name[i] ^= *pAuth++; + + // Set the bind value to the maximum size + bind->t.size = sizeof(bind->t.name); + + return; +} + +//*** SessionSetStartTime() +// This function is used to initialize the session timing +void SessionSetStartTime(SESSION* session // IN: the session to update +) +{ + session->startTime = g_time; + session->epoch = g_timeEpoch; + session->timeout = 0; +} + +//*** SessionResetPolicyData() +// This function is used to reset the policy data without changing the nonce +// or the start time of the session. +void SessionResetPolicyData(SESSION* session // IN: the session to reset +) +{ + SESSION_ATTRIBUTES oldAttributes; + pAssert(session != NULL); + + // Will need later + oldAttributes = session->attributes; + + // No command + session->commandCode = 0; + + // No locality selected + MemorySet(&session->commandLocality, 0, sizeof(session->commandLocality)); + + // The cpHash size to zero + session->u1.cpHash.b.size = 0; + + // No timeout + session->timeout = 0; + + // Reset the pcrCounter + session->pcrCounter = 0; + + // Reset the policy hash + MemorySet(&session->u2.policyDigest.t.buffer, 0, session->u2.policyDigest.t.size); + + // Reset the session attributes + MemorySet(&session->attributes, 0, sizeof(SESSION_ATTRIBUTES)); + + // Restore the policy attributes + session->attributes.isPolicy = SET; + session->attributes.isTrialPolicy = oldAttributes.isTrialPolicy; + + // Restore the bind attributes + session->attributes.isDaBound = oldAttributes.isDaBound; + session->attributes.isLockoutBound = oldAttributes.isLockoutBound; +} + +//*** SessionCapGetLoaded() +// This function returns a list of handles of loaded session, started +// from input 'handle' +// +// 'Handle' must be in valid loaded session handle range, but does not +// have to point to a loaded session. +// Return Type: TPMI_YES_NO +// YES if there are more handles available +// NO all the available handles has been returned +TPMI_YES_NO +SessionCapGetLoaded(TPMI_SH_POLICY handle, // IN: start handle + UINT32 count, // IN: count of returned handles + TPML_HANDLE* handleList // OUT: list of handle +) +{ + TPMI_YES_NO more = NO; + UINT32 i; + + pAssert(HandleGetType(handle) == TPM_HT_LOADED_SESSION); + + // Initialize output handle list + handleList->count = 0; + + // The maximum count of handles we may return is MAX_CAP_HANDLES + if(count > MAX_CAP_HANDLES) + count = MAX_CAP_HANDLES; + + // Iterate session context ID slots to get loaded session handles + for(i = handle & HR_HANDLE_MASK; i < MAX_ACTIVE_SESSIONS; i++) + { + // If session is active + if(gr.contextArray[i] != 0) + { + // If session is loaded + if(gr.contextArray[i] <= MAX_LOADED_SESSIONS) + { + if(handleList->count < count) + { + SESSION* session; + + // If we have not filled up the return list, add this + // session handle to it + // assume that this is going to be an HMAC session + handle = i + HMAC_SESSION_FIRST; + session = SessionGet(handle); + if(session->attributes.isPolicy) + handle = i + POLICY_SESSION_FIRST; + handleList->handle[handleList->count] = handle; + handleList->count++; + } + else + { + // If the return list is full but we still have loaded object + // available, report this and stop iterating + more = YES; + break; + } + } + } + } + + return more; +} + +//*** SessionCapGetSaved() +// This function returns a list of handles for saved session, starting at +// 'handle'. +// +// 'Handle' must be in a valid handle range, but does not have to point to a +// saved session +// +// Return Type: TPMI_YES_NO +// YES if there are more handles available +// NO all the available handles has been returned +TPMI_YES_NO +SessionCapGetSaved(TPMI_SH_HMAC handle, // IN: start handle + UINT32 count, // IN: count of returned handles + TPML_HANDLE* handleList // OUT: list of handle +) +{ + TPMI_YES_NO more = NO; + UINT32 i; + +#ifdef TPM_HT_SAVED_SESSION + pAssert(HandleGetType(handle) == TPM_HT_SAVED_SESSION); +#else + pAssert(HandleGetType(handle) == TPM_HT_ACTIVE_SESSION); +#endif + + // Initialize output handle list + handleList->count = 0; + + // The maximum count of handles we may return is MAX_CAP_HANDLES + if(count > MAX_CAP_HANDLES) + count = MAX_CAP_HANDLES; + + // Iterate session context ID slots to get loaded session handles + for(i = handle & HR_HANDLE_MASK; i < MAX_ACTIVE_SESSIONS; i++) + { + // If session is active + if(gr.contextArray[i] != 0) + { + // If session is saved + if(gr.contextArray[i] > MAX_LOADED_SESSIONS) + { + if(handleList->count < count) + { + // If we have not filled up the return list, add this + // session handle to it + handleList->handle[handleList->count] = i + HMAC_SESSION_FIRST; + handleList->count++; + } + else + { + // If the return list is full but we still have loaded object + // available, report this and stop iterating + more = YES; + break; + } + } + } + } + + return more; +} + +//*** SessionCapGetLoadedNumber() +// This function return the number of authorization sessions currently +// loaded into TPM RAM. +UINT32 +SessionCapGetLoadedNumber(void) +{ + return MAX_LOADED_SESSIONS - s_freeSessionSlots; +} + +//*** SessionCapGetLoadedAvail() +// This function returns the number of additional authorization sessions, of +// any type, that could be loaded into TPM RAM. +// NOTE: In other implementations, this number may just be an estimate. The only +// requirement for the estimate is, if it is one or more, then at least one +// session must be loadable. +UINT32 +SessionCapGetLoadedAvail(void) +{ + return s_freeSessionSlots; +} + +//*** SessionCapGetActiveNumber() +// This function returns the number of active authorization sessions currently +// being tracked by the TPM. +UINT32 +SessionCapGetActiveNumber(void) +{ + UINT32 i; + UINT32 num = 0; + + // Iterate the context array to find the number of non-zero slots + for(i = 0; i < MAX_ACTIVE_SESSIONS; i++) + { + if(gr.contextArray[i] != 0) + num++; + } + + return num; +} + +//*** SessionCapGetActiveAvail() +// This function returns the number of additional authorization sessions, of any +// type, that could be created. This not the number of slots for sessions, but +// the number of additional sessions that the TPM is capable of tracking. +UINT32 +SessionCapGetActiveAvail(void) +{ + UINT32 i; + UINT32 num = 0; + + // Iterate the context array to find the number of zero slots + for(i = 0; i < MAX_ACTIVE_SESSIONS; i++) + { + if(gr.contextArray[i] == 0) + num++; + } + + return num; +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/Time.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/Time.c new file mode 100644 index 0000000..7d66620 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/subsystem/Time.c @@ -0,0 +1,253 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// This file contains the functions relating to the TPM's time functions including +// the interface to the implementation-specific time functions. +// +//** Includes +#include "Tpm.h" +#include "PlatformClock.h" +#include "Marshal.h" + +//** Functions + +//*** TimePowerOn() +// This function initialize time info at _TPM_Init(). +// +// This function is called at _TPM_Init() so that the TPM time can start counting +// as soon as the TPM comes out of reset and doesn't have to wait until +// TPM2_Startup() in order to begin the new time epoch. This could be significant +// for systems that could get powered up but not run any TPM commands for some +// period of time. +// +void TimePowerOn(void) +{ + g_time = _plat__TimerRead(); +} + +//*** TimeNewEpoch() +// This function does the processing to generate a new time epoch nonce and +// set NV for update. This function is only called when NV is known to be available +// and the clock is running. The epoch is updated to persistent data. +static void TimeNewEpoch(void) +{ +#if CLOCK_STOPS + CryptRandomGenerate(sizeof(CLOCK_NONCE), (BYTE*)&g_timeEpoch); +#else + // if the epoch is kept in NV, update it. + gp.timeEpoch++; + NV_SYNC_PERSISTENT(timeEpoch); +#endif + // Clean out any lingering state + _plat__TimerWasStopped(); +} + +//*** TimeStartup() +// This function updates the resetCount and restartCount components of +// TPMS_CLOCK_INFO structure at TPM2_Startup(). +// +// This function will deal with the deferred creation of a new epoch. +// TimeUpdateToCurrent() will not start a new epoch even if one is due when +// TPM_Startup() has not been run. This is because the state of NV is not known +// until startup completes. When Startup is done, then it will create the epoch +// nonce to complete the initializations by calling this function. +BOOL TimeStartup(STARTUP_TYPE type // IN: start up type +) +{ + NOT_REFERENCED(type); + // If the previous cycle is orderly shut down, the value of the safe bit + // the same as previously saved. Otherwise, it is not safe. + if(!NV_IS_ORDERLY) + go.clockSafe = NO; + return TRUE; +} + +//*** TimeClockUpdate() +// This function updates go.clock. If 'newTime' requires an update of NV, then +// NV is checked for availability. If it is not available or is rate limiting, then +// go.clock is not updated and the function returns an error. If 'newTime' would +// not cause an NV write, then go.clock is updated. If an NV write occurs, then +// go.safe is SET. +void TimeClockUpdate(UINT64 newTime // IN: New time value in mS. +) +{ +#define CLOCK_UPDATE_MASK ((1ULL << NV_CLOCK_UPDATE_INTERVAL) - 1) + + // Check to see if the update will cause a need for an nvClock update + if((newTime | CLOCK_UPDATE_MASK) > (go.clock | CLOCK_UPDATE_MASK)) + { + pAssert(g_NvStatus == TPM_RC_SUCCESS); + + // Going to update the NV time state so SET the safe flag + go.clockSafe = YES; + + // update the time + go.clock = newTime; + + NvWrite(NV_ORDERLY_DATA, sizeof(go), &go); + } + else + // No NV update needed so just update + go.clock = newTime; +} + +//*** TimeUpdate() +// This function is used to update the time and clock values. If the TPM +// has run TPM2_Startup(), this function is called at the start of each command. +// If the TPM has not run TPM2_Startup(), this is called from TPM2_Startup() to +// get the clock values initialized. It is not called on command entry because, in +// this implementation, the go structure is not read from NV until TPM2_Startup(). +// The reason for this is that the initialization code (_TPM_Init()) may run before +// NV is accessible. +void TimeUpdate(void) +{ + UINT64 elapsed; + // + // Make sure that we consume the current _plat__TimerWasStopped() state. + if(_plat__TimerWasStopped()) + { + TimeNewEpoch(); + } + // Get the difference between this call and the last time we updated the tick + // timer. + elapsed = _plat__TimerRead() - g_time; + // Don't read + + g_time += elapsed; + + // Don't need to check the result because it has to be success because have + // already checked that NV is available. + TimeClockUpdate(go.clock + elapsed); + + // Call self healing logic for dictionary attack parameters + DASelfHeal(); +} + +//*** TimeUpdateToCurrent() +// This function updates the 'Time' and 'Clock' in the global +// TPMS_TIME_INFO structure. +// +// In this implementation, 'Time' and 'Clock' are updated at the beginning +// of each command and the values are unchanged for the duration of the +// command. +// +// Because 'Clock' updates may require a write to NV memory, 'Time' and 'Clock' +// are not allowed to advance if NV is not available. When clock is not advancing, +// any function that uses 'Clock' will fail and return TPM_RC_NV_UNAVAILABLE or +// TPM_RC_NV_RATE. +// +// This implementation does not do rate limiting. If the implementation does do +// rate limiting, then the 'Clock' update should not be inhibited even when doing +// rate limiting. +void TimeUpdateToCurrent(void) +{ + // Can't update time during the dark interval or when rate limiting so don't + // make any modifications to the internal clock value. Also, defer any clock + // processing until TPM has run TPM2_Startup() + if(!NV_IS_AVAILABLE || !TPMIsStarted()) + return; + + TimeUpdate(); +} + +//*** TimeSetAdjustRate() +// This function is used to perform rate adjustment on 'Time' and 'Clock'. +void TimeSetAdjustRate(TPM_CLOCK_ADJUST adjust // IN: adjust constant +) +{ + switch(adjust) + { + case TPM_CLOCK_COARSE_SLOWER: + _plat__ClockAdjustRate(CLOCK_ADJUST_COARSE); + break; + case TPM_CLOCK_COARSE_FASTER: + _plat__ClockAdjustRate(-CLOCK_ADJUST_COARSE); + break; + case TPM_CLOCK_MEDIUM_SLOWER: + _plat__ClockAdjustRate(CLOCK_ADJUST_MEDIUM); + break; + case TPM_CLOCK_MEDIUM_FASTER: + _plat__ClockAdjustRate(-CLOCK_ADJUST_MEDIUM); + break; + case TPM_CLOCK_FINE_SLOWER: + _plat__ClockAdjustRate(CLOCK_ADJUST_FINE); + break; + case TPM_CLOCK_FINE_FASTER: + _plat__ClockAdjustRate(-CLOCK_ADJUST_FINE); + break; + case TPM_CLOCK_NO_CHANGE: + break; + default: + FAIL(FATAL_ERROR_INTERNAL); + break; + } + + return; +} + +//*** TimeGetMarshaled() +// This function is used to access TPMS_TIME_INFO in canonical form. +// The function collects the time information and marshals it into 'dataBuffer' +// and returns the marshaled size +UINT16 +TimeGetMarshaled(TIME_INFO* dataBuffer // OUT: result buffer +) +{ + TPMS_TIME_INFO timeInfo; + + // Fill TPMS_TIME_INFO structure + timeInfo.time = g_time; + TimeFillInfo(&timeInfo.clockInfo); + + // Marshal TPMS_TIME_INFO to canonical form + return TPMS_TIME_INFO_Marshal(&timeInfo, (BYTE**)&dataBuffer, NULL); +} + +//*** TimeFillInfo +// This function gathers information to fill in a TPMS_CLOCK_INFO structure. +void TimeFillInfo(TPMS_CLOCK_INFO* clockInfo) +{ + clockInfo->clock = go.clock; + clockInfo->resetCount = gp.resetCount; + clockInfo->restartCount = gr.restartCount; + + // If NV is not available, clock stopped advancing and the value reported is + // not "safe". + if(NV_IS_AVAILABLE) + clockInfo->safe = go.clockSafe; + else + clockInfo->safe = NO; + + return; +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/AlgorithmCap.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/AlgorithmCap.c new file mode 100644 index 0000000..54ed4ba --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/AlgorithmCap.c @@ -0,0 +1,232 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Description +// This file contains the algorithm property definitions for the algorithms and the +// code for the TPM2_GetCapability() to return the algorithm properties. + +//** Includes and Defines + +#include "Tpm.h" + +typedef struct +{ + TPM_ALG_ID algID; + TPMA_ALGORITHM attributes; +} ALGORITHM; + +static const ALGORITHM s_algorithms[] = { +// The entries in this table need to be in ascending order but the table doesn't +// need to be full (gaps are allowed). One day, a tool might exist to fill in the +// table from the TPM_ALG description +#if ALG_RSA + {TPM_ALG_RSA, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 1, 0, 0, 0, 0, 0)}, +#endif +#if ALG_TDES + {TPM_ALG_TDES, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 0, 0, 0)}, +#endif +#if ALG_SHA1 + {TPM_ALG_SHA1, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 0, 0)}, +#endif + + {TPM_ALG_HMAC, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 1, 0, 0, 0)}, + +#if ALG_AES + {TPM_ALG_AES, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 0, 0, 0)}, +#endif +#if ALG_MGF1 + {TPM_ALG_MGF1, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 1, 0)}, +#endif + + {TPM_ALG_KEYEDHASH, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 1, 0, 1, 1, 0, 0)}, + +#if ALG_XOR + {TPM_ALG_XOR, TPMA_ALGORITHM_INITIALIZER(0, 1, 1, 0, 0, 0, 0, 0, 0)}, +#endif + +#if ALG_SHA256 + {TPM_ALG_SHA256, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 0, 0)}, +#endif +#if ALG_SHA384 + {TPM_ALG_SHA384, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 0, 0)}, +#endif +#if ALG_SHA512 + {TPM_ALG_SHA512, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 0, 0)}, +#endif +#if ALG_SM3_256 + {TPM_ALG_SM3_256, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 0, 0)}, +#endif +#if ALG_SM4 + {TPM_ALG_SM4, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 0, 0, 0)}, +#endif +#if ALG_RSASSA + {TPM_ALG_RSASSA, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 1, 0, 0, 0)}, +#endif +#if ALG_RSAES + {TPM_ALG_RSAES, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 0, 1, 0, 0)}, +#endif +#if ALG_RSAPSS + {TPM_ALG_RSAPSS, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 1, 0, 0, 0)}, +#endif +#if ALG_OAEP + {TPM_ALG_OAEP, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 0, 1, 0, 0)}, +#endif +#if ALG_ECDSA + {TPM_ALG_ECDSA, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 1, 0, 0, 0)}, +#endif +#if ALG_ECDH + {TPM_ALG_ECDH, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 0, 0, 1, 0)}, +#endif +#if ALG_ECDAA + {TPM_ALG_ECDAA, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 1, 0, 0, 0)}, +#endif +#if ALG_SM2 + {TPM_ALG_SM2, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 1, 0, 1, 0)}, +#endif +#if ALG_ECSCHNORR + {TPM_ALG_ECSCHNORR, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 1, 0, 0, 0)}, +#endif +#if ALG_ECMQV + {TPM_ALG_ECMQV, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 0, 0, 1, 0)}, +#endif +#if ALG_KDF1_SP800_56A + {TPM_ALG_KDF1_SP800_56A, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 1, 0)}, +#endif +#if ALG_KDF2 + {TPM_ALG_KDF2, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 1, 0)}, +#endif +#if ALG_KDF1_SP800_108 + {TPM_ALG_KDF1_SP800_108, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 1, 0)}, +#endif +#if ALG_ECC + {TPM_ALG_ECC, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 1, 0, 0, 0, 0, 0)}, +#endif + + {TPM_ALG_SYMCIPHER, TPMA_ALGORITHM_INITIALIZER(0, 0, 0, 1, 0, 0, 0, 0, 0)}, + +#if ALG_CAMELLIA + {TPM_ALG_CAMELLIA, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 0, 0, 0)}, +#endif +#if ALG_CMAC + {TPM_ALG_CMAC, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 1, 0, 0, 0)}, +#endif +#if ALG_CTR + {TPM_ALG_CTR, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 1, 0, 0)}, +#endif +#if ALG_OFB + {TPM_ALG_OFB, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 1, 0, 0)}, +#endif +#if ALG_CBC + {TPM_ALG_CBC, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 1, 0, 0)}, +#endif +#if ALG_CFB + {TPM_ALG_CFB, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 1, 0, 0)}, +#endif +#if ALG_ECB + {TPM_ALG_ECB, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 1, 0, 0)}, +#endif +}; + +//** AlgorithmCapGetImplemented() +// This function is used by TPM2_GetCapability() to return a list of the +// implemented algorithms. +// +// Return Type: TPMI_YES_NO +// YES more algorithms to report +// NO no more algorithms to report +TPMI_YES_NO +AlgorithmCapGetImplemented(TPM_ALG_ID algID, // IN: the starting algorithm ID + UINT32 count, // IN: count of returned algorithms + TPML_ALG_PROPERTY* algList // OUT: algorithm list +) +{ + TPMI_YES_NO more = NO; + UINT32 i; + UINT32 algNum; + + // initialize output algorithm list + algList->count = 0; + + // The maximum count of algorithms we may return is MAX_CAP_ALGS. + if(count > MAX_CAP_ALGS) + count = MAX_CAP_ALGS; + + // Compute how many algorithms are defined in s_algorithms array. + algNum = sizeof(s_algorithms) / sizeof(s_algorithms[0]); + + // Scan the implemented algorithm list to see if there is a match to 'algID'. + for(i = 0; i < algNum; i++) + { + // If algID is less than the starting algorithm ID, skip it + if(s_algorithms[i].algID < algID) + continue; + if(algList->count < count) + { + // If we have not filled up the return list, add more algorithms + // to it + algList->algProperties[algList->count].alg = s_algorithms[i].algID; + algList->algProperties[algList->count].algProperties = + s_algorithms[i].attributes; + algList->count++; + } + else + { + // If the return list is full but we still have algorithms + // available, report this and stop scanning. + more = YES; + break; + } + } + + return more; +} + +//** AlgorithmGetImplementedVector() +// This function returns the bit vector of the implemented algorithms. +LIB_EXPORT +void AlgorithmGetImplementedVector( + ALGORITHM_VECTOR* implemented // OUT: the implemented bits are SET +) +{ + int index; + + // Nothing implemented until we say it is + MemorySet(implemented, 0, sizeof(ALGORITHM_VECTOR)); + // Go through the list of implemented algorithms and SET the corresponding bit in + // in the implemented vector + for(index = (sizeof(s_algorithms) / sizeof(s_algorithms[0])) - 1; index >= 0; + index--) + SET_BIT(s_algorithms[index].algID, *implemented); + return; +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Bits.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Bits.c new file mode 100644 index 0000000..7424552 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Bits.c @@ -0,0 +1,85 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// This file contains bit manipulation routines. They operate on bit arrays. +// +// The 0th bit in the array is the right-most bit in the 0th octet in +// the array. +// +// NOTE: If pAssert() is defined, the functions will assert if the indicated bit +// number is outside of the range of 'bArray'. How the assert is handled is +// implementation dependent. + +//** Includes + +#include "Tpm.h" + +//** Functions + +//*** TestBit() +// This function is used to check the setting of a bit in an array of bits. +// Return Type: BOOL +// TRUE(1) bit is set +// FALSE(0) bit is not set +BOOL TestBit(unsigned int bitNum, // IN: number of the bit in 'bArray' + BYTE* bArray, // IN: array containing the bits + unsigned int bytesInArray // IN: size in bytes of 'bArray' +) +{ + pAssert(bytesInArray > (bitNum >> 3)); + return ((bArray[bitNum >> 3] & (1 << (bitNum & 7))) != 0); +} + +//*** SetBit() +// This function will set the indicated bit in 'bArray'. +void SetBit(unsigned int bitNum, // IN: number of the bit in 'bArray' + BYTE* bArray, // IN: array containing the bits + unsigned int bytesInArray // IN: size in bytes of 'bArray' +) +{ + pAssert(bytesInArray > (bitNum >> 3)); + bArray[bitNum >> 3] |= (1 << (bitNum & 7)); +} + +//*** ClearBit() +// This function will clear the indicated bit in 'bArray'. +void ClearBit(unsigned int bitNum, // IN: number of the bit in 'bArray'. + BYTE* bArray, // IN: array containing the bits + unsigned int bytesInArray // IN: size in bytes of 'bArray' +) +{ + pAssert(bytesInArray > (bitNum >> 3)); + bArray[bitNum >> 3] &= ~(1 << (bitNum & 7)); +} diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/CommandCodeAttributes.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/CommandCodeAttributes.c new file mode 100644 index 0000000..51d2e94 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/CommandCodeAttributes.c @@ -0,0 +1,531 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// This file contains the functions for testing various command properties. + +//** Includes and Defines + +#include "Tpm.h" +#include "CommandCodeAttributes_fp.h" + +// Set the default value for CC_VEND if not already set +#ifndef CC_VEND +# define CC_VEND (TPM_CC)(0x20000000) +#endif + +typedef UINT16 ATTRIBUTE_TYPE; + +// The following file is produced from the command tables in part 3 of the +// specification. It defines the attributes for each of the commands. +// NOTE: This file is currently produced by an automated process. Files +// produced from Part 2 or Part 3 tables through automated processes are not +// included in the specification so that their is no ambiguity about the +// table containing the information being the normative definition. +#define _COMMAND_CODE_ATTRIBUTES_ +#include "CommandAttributeData.h" + +//** Command Attribute Functions + +//*** NextImplementedIndex() +// This function is used when the lists are not compressed. In a compressed list, +// only the implemented commands are present. So, a search might find a value +// but that value may not be implemented. This function checks to see if the input +// commandIndex points to an implemented command and, if not, it searches upwards +// until it finds one. When the list is compressed, this function gets defined +// as a no-op. +// Return Type: COMMAND_INDEX +// UNIMPLEMENTED_COMMAND_INDEX command is not implemented +// other index of the command +#if !COMPRESSED_LISTS +static COMMAND_INDEX NextImplementedIndex(COMMAND_INDEX commandIndex) +{ + for(; commandIndex < COMMAND_COUNT; commandIndex++) + { + if(s_commandAttributes[commandIndex] & IS_IMPLEMENTED) + return commandIndex; + } + return UNIMPLEMENTED_COMMAND_INDEX; +} +#else +# define NextImplementedIndex(x) (x) +#endif + +//*** GetClosestCommandIndex() +// This function returns the command index for the command with a value that is +// equal to or greater than the input value +// Return Type: COMMAND_INDEX +// UNIMPLEMENTED_COMMAND_INDEX command is not implemented +// other index of a command +COMMAND_INDEX +GetClosestCommandIndex(TPM_CC commandCode // IN: the command code to start at +) +{ + BOOL vendor = (commandCode & CC_VEND) != 0; + COMMAND_INDEX searchIndex = (COMMAND_INDEX)commandCode; + + // The commandCode is a UINT32 and the search index is UINT16. We are going to + // search for a match but need to make sure that the commandCode value is not + // out of range. To do this, need to clear the vendor bit of the commandCode + // (if set) and compare the result to the 16-bit searchIndex value. If it is + // out of range, indicate that the command is not implemented + if((commandCode & ~CC_VEND) != searchIndex) + return UNIMPLEMENTED_COMMAND_INDEX; + + // if there is at least one vendor command, the last entry in the array will + // have the v bit set. If the input commandCode is larger than the last + // vendor-command, then it is out of range. + if(vendor) + { +#if VENDOR_COMMAND_ARRAY_SIZE > 0 + COMMAND_INDEX commandIndex; + COMMAND_INDEX min; + COMMAND_INDEX max; + int diff; +# if LIBRARY_COMMAND_ARRAY_SIZE == COMMAND_COUNT +# error "Constants are not consistent." +# endif + // Check to see if the value is equal to or below the minimum + // entry. + // Note: Put this check first so that the typical case of only one vendor- + // specific command doesn't waste any more time. + if(GET_ATTRIBUTE(s_ccAttr[LIBRARY_COMMAND_ARRAY_SIZE], TPMA_CC, commandIndex) + >= searchIndex) + { + // the vendor array is always assumed to be packed so there is + // no need to check to see if the command is implemented + return LIBRARY_COMMAND_ARRAY_SIZE; + } + // See if this is out of range on the top + if(GET_ATTRIBUTE(s_ccAttr[COMMAND_COUNT - 1], TPMA_CC, commandIndex) + < searchIndex) + { + return UNIMPLEMENTED_COMMAND_INDEX; + } + commandIndex = UNIMPLEMENTED_COMMAND_INDEX; // Needs initialization to keep + // compiler happy + min = LIBRARY_COMMAND_ARRAY_SIZE; // first vendor command + max = COMMAND_COUNT - 1; // last vendor command + diff = 1; // needs initialization to keep + // compiler happy + while(min <= max) + { + commandIndex = (min + max + 1) / 2; + diff = GET_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, commandIndex) + - searchIndex; + if(diff == 0) + return commandIndex; + if(diff > 0) + max = commandIndex - 1; + else + min = commandIndex + 1; + } + // didn't find and exact match. commandIndex will be pointing at the last + // item tested. If 'diff' is positive, then the last item tested was + // larger index of the command code so it is the smallest value + // larger than the requested value. + if(diff > 0) + return commandIndex; + // if 'diff' is negative, then the value tested was smaller than + // the commandCode index and the next higher value is the correct one. + // Note: this will necessarily be in range because of the earlier check + // that the index was within range. + return commandIndex + 1; +#else + // If there are no vendor commands so anything with the vendor bit set is out + // of range + return UNIMPLEMENTED_COMMAND_INDEX; +#endif + } + // Get here if the V-Bit was not set in 'commandCode' + + if(GET_ATTRIBUTE(s_ccAttr[LIBRARY_COMMAND_ARRAY_SIZE - 1], TPMA_CC, commandIndex) + < searchIndex) + { + // requested index is out of the range to the top +#if VENDOR_COMMAND_ARRAY_SIZE > 0 + // If there are vendor commands, then the first vendor command + // is the next value greater than the commandCode. + // NOTE: we got here if the starting index did not have the V bit but we + // reached the end of the array of library commands (non-vendor). Since + // there is at least one vendor command, and vendor commands are always + // in a compressed list that starts after the library list, the next + // index value contains a valid vendor command. + return LIBRARY_COMMAND_ARRAY_SIZE; +#else + // if there are no vendor commands, then this is out of range + return UNIMPLEMENTED_COMMAND_INDEX; +#endif + } + // If the request is lower than any value in the array, then return + // the lowest value (needs to be an index for an implemented command + if(GET_ATTRIBUTE(s_ccAttr[0], TPMA_CC, commandIndex) >= searchIndex) + { + return NextImplementedIndex(0); + } + else + { +#if COMPRESSED_LISTS + COMMAND_INDEX commandIndex = UNIMPLEMENTED_COMMAND_INDEX; + COMMAND_INDEX min = 0; + COMMAND_INDEX max = LIBRARY_COMMAND_ARRAY_SIZE - 1; + int diff = 1; +# if LIBRARY_COMMAND_ARRAY_SIZE == 0 +# error "Something is terribly wrong" +# endif + // The s_ccAttr array contains an extra entry at the end (a zero value). + // Don't count this as an array entry. This means that max should start + // out pointing to the last valid entry in the array which is - 2 + pAssert( + max + == (sizeof(s_ccAttr) / sizeof(TPMA_CC) - VENDOR_COMMAND_ARRAY_SIZE - 2)); + while(min <= max) + { + commandIndex = (min + max + 1) / 2; + diff = GET_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, commandIndex) + - searchIndex; + if(diff == 0) + return commandIndex; + if(diff > 0) + max = commandIndex - 1; + else + min = commandIndex + 1; + } + // didn't find and exact match. commandIndex will be pointing at the + // last item tested. If diff is positive, then the last item tested was + // larger index of the command code so it is the smallest value + // larger than the requested value. + if(diff > 0) + return commandIndex; + // if diff is negative, then the value tested was smaller than + // the commandCode index and the next higher value is the correct one. + // Note: this will necessarily be in range because of the earlier check + // that the index was within range. + return commandIndex + 1; +#else + // The list is not compressed so offset into the array by the command + // code value of the first entry in the list. Then go find the first + // implemented command. + return NextImplementedIndex( + searchIndex - (COMMAND_INDEX)s_ccAttr[0].commandIndex); +#endif + } +} + +//*** CommandCodeToComandIndex() +// This function returns the index in the various attributes arrays of the +// command. +// Return Type: COMMAND_INDEX +// UNIMPLEMENTED_COMMAND_INDEX command is not implemented +// other index of the command +COMMAND_INDEX +CommandCodeToCommandIndex(TPM_CC commandCode // IN: the command code to look up +) +{ + // Extract the low 16-bits of the command code to get the starting search index + COMMAND_INDEX searchIndex = (COMMAND_INDEX)commandCode; + BOOL vendor = (commandCode & CC_VEND) != 0; + COMMAND_INDEX commandIndex; +#if !COMPRESSED_LISTS + if(!vendor) + { + commandIndex = searchIndex - (COMMAND_INDEX)s_ccAttr[0].commandIndex; + // Check for out of range or unimplemented. + // Note, since a COMMAND_INDEX is unsigned, if searchIndex is smaller than + // the lowest value of command, it will become a 'negative' number making + // it look like a large unsigned number, this will cause it to fail + // the unsigned check below. + if(commandIndex >= LIBRARY_COMMAND_ARRAY_SIZE + || (s_commandAttributes[commandIndex] & IS_IMPLEMENTED) == 0) + return UNIMPLEMENTED_COMMAND_INDEX; + return commandIndex; + } +#endif + // Need this code for any vendor code lookup or for compressed lists + commandIndex = GetClosestCommandIndex(commandCode); + + // Look at the returned value from get closest. If it isn't the one that was + // requested, then the command is not implemented. + if(commandIndex != UNIMPLEMENTED_COMMAND_INDEX) + { + if((GET_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, commandIndex) + != searchIndex) + || (IS_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, V)) != vendor) + commandIndex = UNIMPLEMENTED_COMMAND_INDEX; + } + return commandIndex; +} + +//*** GetNextCommandIndex() +// This function returns the index of the next implemented command. +// Return Type: COMMAND_INDEX +// UNIMPLEMENTED_COMMAND_INDEX no more implemented commands +// other the index of the next implemented command +COMMAND_INDEX +GetNextCommandIndex(COMMAND_INDEX commandIndex // IN: the starting index +) +{ + while(++commandIndex < COMMAND_COUNT) + { +#if !COMPRESSED_LISTS + if(s_commandAttributes[commandIndex] & IS_IMPLEMENTED) +#endif + return commandIndex; + } + return UNIMPLEMENTED_COMMAND_INDEX; +} + +//*** GetCommandCode() +// This function returns the commandCode associated with the command index +TPM_CC +GetCommandCode(COMMAND_INDEX commandIndex // IN: the command index +) +{ + TPM_CC commandCode = GET_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, commandIndex); + if(IS_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, V)) + commandCode += CC_VEND; + return commandCode; +} + +//*** CommandAuthRole() +// +// This function returns the authorization role required of a handle. +// +// Return Type: AUTH_ROLE +// AUTH_NONE no authorization is required +// AUTH_USER user role authorization is required +// AUTH_ADMIN admin role authorization is required +// AUTH_DUP duplication role authorization is required +AUTH_ROLE +CommandAuthRole(COMMAND_INDEX commandIndex, // IN: command index + UINT32 handleIndex // IN: handle index (zero based) +) +{ + if(0 == handleIndex) + { + // Any authorization role set? + COMMAND_ATTRIBUTES properties = s_commandAttributes[commandIndex]; + + if(properties & HANDLE_1_USER) + return AUTH_USER; + if(properties & HANDLE_1_ADMIN) + return AUTH_ADMIN; + if(properties & HANDLE_1_DUP) + return AUTH_DUP; + } + else if(1 == handleIndex) + { + if(s_commandAttributes[commandIndex] & HANDLE_2_USER) + return AUTH_USER; + } + return AUTH_NONE; +} + +//*** EncryptSize() +// This function returns the size of the decrypt size field. This function returns +// 0 if encryption is not allowed +// Return Type: int +// 0 encryption not allowed +// 2 size field is two bytes +// 4 size field is four bytes +int EncryptSize(COMMAND_INDEX commandIndex // IN: command index +) +{ + return ((s_commandAttributes[commandIndex] & ENCRYPT_2) ? 2 + : (s_commandAttributes[commandIndex] & ENCRYPT_4) ? 4 + : 0); +} + +//*** DecryptSize() +// This function returns the size of the decrypt size field. This function returns +// 0 if decryption is not allowed +// Return Type: int +// 0 encryption not allowed +// 2 size field is two bytes +// 4 size field is four bytes +int DecryptSize(COMMAND_INDEX commandIndex // IN: command index +) +{ + return ((s_commandAttributes[commandIndex] & DECRYPT_2) ? 2 + : (s_commandAttributes[commandIndex] & DECRYPT_4) ? 4 + : 0); +} + +//*** IsSessionAllowed() +// +// This function indicates if the command is allowed to have sessions. +// +// This function must not be called if the command is not known to be implemented. +// +// Return Type: BOOL +// TRUE(1) session is allowed with this command +// FALSE(0) session is not allowed with this command +BOOL IsSessionAllowed(COMMAND_INDEX commandIndex // IN: the command to be checked +) +{ + return ((s_commandAttributes[commandIndex] & NO_SESSIONS) == 0); +} + +//*** IsHandleInResponse() +// This function determines if a command has a handle in the response +BOOL IsHandleInResponse(COMMAND_INDEX commandIndex) +{ + return ((s_commandAttributes[commandIndex] & R_HANDLE) != 0); +} + +//*** IsWriteOperation() +// Checks to see if an operation will write to an NV Index and is subject to being +// blocked by read-lock +BOOL IsWriteOperation(COMMAND_INDEX commandIndex // IN: Command to check +) +{ +#ifdef WRITE_LOCK + return ((s_commandAttributes[commandIndex] & WRITE_LOCK) != 0); +#else + if(!IS_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, V)) + { + switch(GET_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, commandIndex)) + { + case TPM_CC_NV_Write: +# if CC_NV_Increment + case TPM_CC_NV_Increment: +# endif +# if CC_NV_SetBits + case TPM_CC_NV_SetBits: +# endif +# if CC_NV_Extend + case TPM_CC_NV_Extend: +# endif +# if CC_AC_Send + case TPM_CC_AC_Send: +# endif + // NV write lock counts as a write operation for authorization purposes. + // We check to see if the NV is write locked before we do the + // authorization. If it is locked, we fail the command early. + case TPM_CC_NV_WriteLock: + return TRUE; + default: + break; + } + } + return FALSE; +#endif +} + +//*** IsReadOperation() +// Checks to see if an operation will write to an NV Index and is +// subject to being blocked by write-lock. +BOOL IsReadOperation(COMMAND_INDEX commandIndex // IN: Command to check +) +{ +#ifdef READ_LOCK + return ((s_commandAttributes[commandIndex] & READ_LOCK) != 0); +#else + + if(!IS_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, V)) + { + switch(GET_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, commandIndex)) + { + case TPM_CC_NV_Read: + case TPM_CC_PolicyNV: + case TPM_CC_NV_Certify: + // NV read lock counts as a read operation for authorization purposes. + // We check to see if the NV is read locked before we do the + // authorization. If it is locked, we fail the command early. + case TPM_CC_NV_ReadLock: + return TRUE; + default: + break; + } + } + return FALSE; +#endif +} + +//*** CommandCapGetCCList() +// This function returns a list of implemented commands and command attributes +// starting from the command in 'commandCode'. +// Return Type: TPMI_YES_NO +// YES more command attributes are available +// NO no more command attributes are available +TPMI_YES_NO +CommandCapGetCCList(TPM_CC commandCode, // IN: start command code + UINT32 count, // IN: maximum count for number of entries in + // 'commandList' + TPML_CCA* commandList // OUT: list of TPMA_CC +) +{ + TPMI_YES_NO more = NO; + COMMAND_INDEX commandIndex; + + // initialize output handle list count + commandList->count = 0; + + for(commandIndex = GetClosestCommandIndex(commandCode); + commandIndex != UNIMPLEMENTED_COMMAND_INDEX; + commandIndex = GetNextCommandIndex(commandIndex)) + { +#if !COMPRESSED_LISTS + // this check isn't needed for compressed lists. + if(!(s_commandAttributes[commandIndex] & IS_IMPLEMENTED)) + continue; +#endif + if(commandList->count < count) + { + // If the list is not full, add the attributes for this command. + commandList->commandAttributes[commandList->count] = + s_ccAttr[commandIndex]; + commandList->count++; + } + else + { + // If the list is full but there are more commands to report, + // indicate this and return. + more = YES; + break; + } + } + return more; +} + +//*** IsVendorCommand() +// Function indicates if a command index references a vendor command. +// Return Type: BOOL +// TRUE(1) command is a vendor command +// FALSE(0) command is not a vendor command +BOOL IsVendorCommand(COMMAND_INDEX commandIndex // IN: command index to check +) +{ + return (IS_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, V)); +} diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Entity.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Entity.c new file mode 100644 index 0000000..5314475 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Entity.c @@ -0,0 +1,490 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Description +// The functions in this file are used for accessing properties for handles of +// various types. Functions in other files require handles of a specific +// type but the functions in this file allow use of any handle type. + +//** Includes + +#include "Tpm.h" + +//** Functions +//*** EntityGetLoadStatus() +// This function will check that all the handles access loaded entities. +// Return Type: TPM_RC +// TPM_RC_HANDLE handle type does not match +// TPM_RC_REFERENCE_Hx entity is not present +// TPM_RC_HIERARCHY entity belongs to a disabled hierarchy +// TPM_RC_OBJECT_MEMORY handle is an evict object but there is no +// space to load it to RAM +TPM_RC +EntityGetLoadStatus(COMMAND* command // IN/OUT: command parsing structure +) +{ + UINT32 i; + TPM_RC result = TPM_RC_SUCCESS; + // + for(i = 0; i < command->handleNum; i++) + { + TPM_HANDLE handle = command->handles[i]; + switch(HandleGetType(handle)) + { + // For handles associated with hierarchies, the entity is present + // only if the associated enable is SET. + case TPM_HT_PERMANENT: + switch(handle) + { + case TPM_RH_OWNER: + if(!gc.shEnable) + result = TPM_RC_HIERARCHY; + break; + +#ifdef VENDOR_PERMANENT + case VENDOR_PERMANENT: +#endif + case TPM_RH_ENDORSEMENT: + if(!gc.ehEnable) + result = TPM_RC_HIERARCHY; + break; + case TPM_RH_PLATFORM: + if(!g_phEnable) + result = TPM_RC_HIERARCHY; + break; + // null handle, PW session handle and lockout + // handle are always available + case TPM_RH_NULL: + case TPM_RS_PW: + // Need to be careful for lockout. Lockout is always available + // for policy checks but not always available when authValue + // is being checked. + case TPM_RH_LOCKOUT: + // Rather than have #ifdefs all over the code, + // CASE_ACT_HANDLE is defined in ACT.h. It is 'case TPM_RH_ACT_x:' + // FOR_EACH_ACT(CASE_ACT_HANDLE) creates a simple + // case TPM_RH_ACT_x: // for each of the implemented ACT. + FOR_EACH_ACT(CASE_ACT_HANDLE) + break; + default: + // If the implementation has a manufacturer-specific value + // then test for it here. Since this implementation does + // not have any, this implementation returns the same failure + // that unmarshaling of a bad handle would produce. + if(((TPM_RH)handle >= TPM_RH_AUTH_00) + && ((TPM_RH)handle <= TPM_RH_AUTH_FF)) + // if the implementation has a manufacturer-specific value + result = TPM_RC_VALUE; + else + // The handle is in the range of reserved handles but is + // not implemented in this TPM. + result = TPM_RC_VALUE; + break; + } + break; + case TPM_HT_TRANSIENT: + // For a transient object, check if the handle is associated + // with a loaded object. + if(!IsObjectPresent(handle)) + result = TPM_RC_REFERENCE_H0; + break; + case TPM_HT_PERSISTENT: + // Persistent object + // Copy the persistent object to RAM and replace the handle with the + // handle of the assigned slot. A TPM_RC_OBJECT_MEMORY, + // TPM_RC_HIERARCHY or TPM_RC_REFERENCE_H0 error may be returned by + // ObjectLoadEvict() + result = ObjectLoadEvict(&command->handles[i], command->index); + break; + case TPM_HT_HMAC_SESSION: + // For an HMAC session, see if the session is loaded + // and if the session in the session slot is actually + // an HMAC session. + if(SessionIsLoaded(handle)) + { + SESSION* session; + session = SessionGet(handle); + // Check if the session is a HMAC session + if(session->attributes.isPolicy == SET) + result = TPM_RC_HANDLE; + } + else + result = TPM_RC_REFERENCE_H0; + break; + case TPM_HT_POLICY_SESSION: + // For a policy session, see if the session is loaded + // and if the session in the session slot is actually + // a policy session. + if(SessionIsLoaded(handle)) + { + SESSION* session; + session = SessionGet(handle); + // Check if the session is a policy session + if(session->attributes.isPolicy == CLEAR) + result = TPM_RC_HANDLE; + } + else + result = TPM_RC_REFERENCE_H0; + break; + case TPM_HT_NV_INDEX: + // For an NV Index, use the TPM-specific routine + // to search the IN Index space. + result = NvIndexIsAccessible(handle); + break; + case TPM_HT_PCR: + // Any PCR handle that is unmarshaled successfully referenced + // a PCR that is defined. + break; +#if CC_AC_Send + case TPM_HT_AC: + // Use the TPM-specific routine to search for the AC + result = AcIsAccessible(handle); + break; +#endif + default: + // Any other handle type is a defect in the unmarshaling code. + FAIL(FATAL_ERROR_INTERNAL); + break; + } + if(result != TPM_RC_SUCCESS) + { + if(result == TPM_RC_REFERENCE_H0) + result = result + i; + else + result = RcSafeAddToResult(result, TPM_RC_H + g_rcIndex[i]); + break; + } + } + return result; +} + +//*** EntityGetAuthValue() +// This function is used to access the 'authValue' associated with a handle. +// This function assumes that the handle references an entity that is accessible +// and the handle is not for a persistent objects. That is EntityGetLoadStatus() +// should have been called. Also, the accessibility of the authValue should have +// been verified by IsAuthValueAvailable(). +// +// This function copies the authorization value of the entity to 'auth'. +// Return Type: UINT16 +// count number of bytes in the authValue with 0's stripped +UINT16 +EntityGetAuthValue(TPMI_DH_ENTITY handle, // IN: handle of entity + TPM2B_AUTH* auth // OUT: authValue of the entity +) +{ + TPM2B_AUTH* pAuth = NULL; + + auth->t.size = 0; + + switch(HandleGetType(handle)) + { + case TPM_HT_PERMANENT: + { + switch(handle) + { + case TPM_RH_OWNER: + // ownerAuth for TPM_RH_OWNER + pAuth = &gp.ownerAuth; + break; + case TPM_RH_ENDORSEMENT: + // endorsementAuth for TPM_RH_ENDORSEMENT + pAuth = &gp.endorsementAuth; + break; + // The ACT use platformAuth for auth + FOR_EACH_ACT(CASE_ACT_HANDLE) + case TPM_RH_PLATFORM: + // platformAuth for TPM_RH_PLATFORM + pAuth = &gc.platformAuth; + break; + case TPM_RH_LOCKOUT: + // lockoutAuth for TPM_RH_LOCKOUT + pAuth = &gp.lockoutAuth; + break; + case TPM_RH_NULL: + // nullAuth for TPM_RH_NULL. Return 0 directly here + return 0; + break; +#ifdef VENDOR_PERMANENT + case VENDOR_PERMANENT: + // vendor authorization value + pAuth = &g_platformUniqueDetails; +#endif + default: + // If any other permanent handle is present it is + // a code defect. + FAIL(FATAL_ERROR_INTERNAL); + break; + } + break; + } + case TPM_HT_TRANSIENT: + // authValue for an object + // A persistent object would have been copied into RAM + // and would have an transient object handle here. + { + OBJECT* object; + + object = HandleToObject(handle); + // special handling if this is a sequence object + if(ObjectIsSequence(object)) + { + pAuth = &((HASH_OBJECT*)object)->auth; + } + else + { + // Authorization is available only when the private portion of + // the object is loaded. The check should be made before + // this function is called + pAssert(object->attributes.publicOnly == CLEAR); + pAuth = &object->sensitive.authValue; + } + } + break; + case TPM_HT_NV_INDEX: + // authValue for an NV index + { + NV_INDEX* nvIndex = NvGetIndexInfo(handle, NULL); + pAssert(nvIndex != NULL); + pAuth = &nvIndex->authValue; + } + break; + case TPM_HT_PCR: + // authValue for PCR + pAuth = PCRGetAuthValue(handle); + break; + default: + // If any other handle type is present here, then there is a defect + // in the unmarshaling code. + FAIL(FATAL_ERROR_INTERNAL); + break; + } + // Copy the authValue + MemoryCopy2B((TPM2B*)auth, (TPM2B*)pAuth, sizeof(auth->t.buffer)); + MemoryRemoveTrailingZeros(auth); + return auth->t.size; +} + +//*** EntityGetAuthPolicy() +// This function is used to access the 'authPolicy' associated with a handle. +// This function assumes that the handle references an entity that is accessible +// and the handle is not for a persistent objects. That is EntityGetLoadStatus() +// should have been called. Also, the accessibility of the authPolicy should have +// been verified by IsAuthPolicyAvailable(). +// +// This function copies the authorization policy of the entity to 'authPolicy'. +// +// The return value is the hash algorithm for the policy. +TPMI_ALG_HASH +EntityGetAuthPolicy(TPMI_DH_ENTITY handle, // IN: handle of entity + TPM2B_DIGEST* authPolicy // OUT: authPolicy of the entity +) +{ + TPMI_ALG_HASH hashAlg = TPM_ALG_NULL; + authPolicy->t.size = 0; + + switch(HandleGetType(handle)) + { + case TPM_HT_PERMANENT: + switch(handle) + { + case TPM_RH_OWNER: + // ownerPolicy for TPM_RH_OWNER + *authPolicy = gp.ownerPolicy; + hashAlg = gp.ownerAlg; + break; + case TPM_RH_ENDORSEMENT: + // endorsementPolicy for TPM_RH_ENDORSEMENT + *authPolicy = gp.endorsementPolicy; + hashAlg = gp.endorsementAlg; + break; + case TPM_RH_PLATFORM: + // platformPolicy for TPM_RH_PLATFORM + *authPolicy = gc.platformPolicy; + hashAlg = gc.platformAlg; + break; + case TPM_RH_LOCKOUT: + // lockoutPolicy for TPM_RH_LOCKOUT + *authPolicy = gp.lockoutPolicy; + hashAlg = gp.lockoutAlg; + break; +#define ACT_GET_POLICY(N) \ + case TPM_RH_ACT_##N: \ + *authPolicy = go.ACT_##N.authPolicy; \ + hashAlg = go.ACT_##N.hashAlg; \ + break; + // Get the policy for each implemented ACT + FOR_EACH_ACT(ACT_GET_POLICY) + default: + hashAlg = TPM_ALG_ERROR; + break; + } + break; + case TPM_HT_TRANSIENT: + // authPolicy for an object + { + OBJECT* object = HandleToObject(handle); + *authPolicy = object->publicArea.authPolicy; + hashAlg = object->publicArea.nameAlg; + } + break; + case TPM_HT_NV_INDEX: + // authPolicy for a NV index + { + NV_INDEX* nvIndex = NvGetIndexInfo(handle, NULL); + pAssert(nvIndex != 0); + *authPolicy = nvIndex->publicArea.authPolicy; + hashAlg = nvIndex->publicArea.nameAlg; + } + break; + case TPM_HT_PCR: + // authPolicy for a PCR + hashAlg = PCRGetAuthPolicy(handle, authPolicy); + break; + default: + // If any other handle type is present it is a code defect. + FAIL(FATAL_ERROR_INTERNAL); + break; + } + return hashAlg; +} + +//*** EntityGetName() +// This function returns the Name associated with a handle. +TPM2B_NAME* EntityGetName(TPMI_DH_ENTITY handle, // IN: handle of entity + TPM2B_NAME* name // OUT: name of entity +) +{ + switch(HandleGetType(handle)) + { + case TPM_HT_TRANSIENT: + { + // Name for an object + OBJECT* object = HandleToObject(handle); + // an object with no nameAlg has no name + if(object->publicArea.nameAlg == TPM_ALG_NULL) + name->b.size = 0; + else + *name = object->name; + break; + } + case TPM_HT_NV_INDEX: + // Name for a NV index + NvGetNameByIndexHandle(handle, name); + break; + default: + // For all other types, the handle is the Name + name->t.size = sizeof(TPM_HANDLE); + UINT32_TO_BYTE_ARRAY(handle, name->t.name); + break; + } + return name; +} + +//*** EntityGetHierarchy() +// This function returns the hierarchy handle associated with an entity. +// a) A handle that is a hierarchy handle is associated with itself. +// b) An NV index belongs to TPM_RH_PLATFORM if TPMA_NV_PLATFORMCREATE, +// is SET, otherwise it belongs to TPM_RH_OWNER +// c) An object handle belongs to its hierarchy. +TPMI_RH_HIERARCHY +EntityGetHierarchy(TPMI_DH_ENTITY handle // IN :handle of entity +) +{ + TPMI_RH_HIERARCHY hierarchy = TPM_RH_NULL; + + switch(HandleGetType(handle)) + { + case TPM_HT_PERMANENT: + // hierarchy for a permanent handle + switch(handle) + { + case TPM_RH_PLATFORM: + case TPM_RH_ENDORSEMENT: + case TPM_RH_NULL: + hierarchy = handle; + break; + // all other permanent handles are associated with the owner + // hierarchy. (should only be TPM_RH_OWNER and TPM_RH_LOCKOUT) + default: + hierarchy = TPM_RH_OWNER; + break; + } + break; + case TPM_HT_NV_INDEX: + // hierarchy for NV index + { + NV_INDEX* nvIndex = NvGetIndexInfo(handle, NULL); + pAssert(nvIndex != NULL); + + // If only the platform can delete the index, then it is + // considered to be in the platform hierarchy, otherwise it + // is in the owner hierarchy. + if(IS_ATTRIBUTE( + nvIndex->publicArea.attributes, TPMA_NV, PLATFORMCREATE)) + hierarchy = TPM_RH_PLATFORM; + else + hierarchy = TPM_RH_OWNER; + } + break; + case TPM_HT_TRANSIENT: + // hierarchy for an object + { + OBJECT* object; + object = HandleToObject(handle); + if(object->attributes.ppsHierarchy) + { + hierarchy = TPM_RH_PLATFORM; + } + else if(object->attributes.epsHierarchy) + { + hierarchy = TPM_RH_ENDORSEMENT; + } + else if(object->attributes.spsHierarchy) + { + hierarchy = TPM_RH_OWNER; + } + } + break; + case TPM_HT_PCR: + hierarchy = TPM_RH_OWNER; + break; + default: + FAIL(FATAL_ERROR_INTERNAL); + break; + } + // this is unreachable but it provides a return value for the default + // case which makes the complier happy + return hierarchy; +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Global.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Global.c new file mode 100644 index 0000000..651d58a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Global.c @@ -0,0 +1,62 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Description +// This file will instance the TPM variables that are not stack allocated. + +// Descriptions of global variables are in Global.h. There macro macro definitions +// that allows a variable to be instanced or simply defined as an external variable. +// When global.h is included from this .c file, GLOBAL_C is defined and values are +// instanced (and possibly initialized), but when global.h is included by any other +// file, they are simply defined as external values. DO NOT DEFINE GLOBAL_C IN ANY +// OTHER FILE. +// +// NOTE: This is a change from previous implementations where Global.h just contained +// the extern declaration and values were instanced in this file. This change keeps +// the definition and instance in one file making maintenance easier. The instanced +// data will still be in the global.obj file. +// +// The OIDs.h file works in a way that is similar to the Global.h with the definition +// of the values in OIDs.h such that they are instanced in global.obj. The macros +// that are defined in Global.h are used in OIDs.h in the same way as they are in +// Global.h. + +//** Defines and Includes +#define GLOBAL_C +#include "Tpm.h" +#include "OIDs.h" + +#if CC_CertifyX509 +# include "X509.h" +#endif // CC_CertifyX509 diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Handle.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Handle.c new file mode 100644 index 0000000..cd9e091 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Handle.c @@ -0,0 +1,196 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Description +// This file contains the functions that return the type of a handle. + +//** Includes +#include "Tpm.h" + +//** Functions + +//*** HandleGetType() +// This function returns the type of a handle which is the MSO of the handle. +TPM_HT +HandleGetType(TPM_HANDLE handle // IN: a handle to be checked +) +{ + // return the upper bytes of input data + return (TPM_HT)((handle & HR_RANGE_MASK) >> HR_SHIFT); +} + +//*** NextPermanentHandle() +// This function returns the permanent handle that is equal to the input value or +// is the next higher value. If there is no handle with the input value and there +// is no next higher value, it returns 0: +TPM_HANDLE +NextPermanentHandle(TPM_HANDLE inHandle // IN: the handle to check +) +{ + // If inHandle is below the start of the range of permanent handles + // set it to the start and scan from there + if(inHandle < TPM_RH_FIRST) + inHandle = TPM_RH_FIRST; + // scan from input value until we find an implemented permanent handle + // or go out of range + for(; inHandle <= TPM_RH_LAST; inHandle++) + { + switch(inHandle) + { + case TPM_RH_OWNER: + case TPM_RH_NULL: + case TPM_RS_PW: + case TPM_RH_LOCKOUT: + case TPM_RH_ENDORSEMENT: + case TPM_RH_PLATFORM: + case TPM_RH_PLATFORM_NV: +#ifdef VENDOR_PERMANENT + case VENDOR_PERMANENT: +#endif +// Each of the implemented ACT +#define ACT_IMPLEMENTED_CASE(N) case TPM_RH_ACT_##N: + + FOR_EACH_ACT(ACT_IMPLEMENTED_CASE) + + return inHandle; + break; + default: + break; + } + } + // Out of range on the top + return 0; +} + +//*** PermanentCapGetHandles() +// This function returns a list of the permanent handles of PCR, started from +// 'handle'. If 'handle' is larger than the largest permanent handle, an empty list +// will be returned with 'more' set to NO. +// Return Type: TPMI_YES_NO +// YES if there are more handles available +// NO all the available handles has been returned +TPMI_YES_NO +PermanentCapGetHandles(TPM_HANDLE handle, // IN: start handle + UINT32 count, // IN: count of returned handles + TPML_HANDLE* handleList // OUT: list of handle +) +{ + TPMI_YES_NO more = NO; + UINT32 i; + + pAssert(HandleGetType(handle) == TPM_HT_PERMANENT); + + // Initialize output handle list + handleList->count = 0; + + // The maximum count of handles we may return is MAX_CAP_HANDLES + if(count > MAX_CAP_HANDLES) + count = MAX_CAP_HANDLES; + + // Iterate permanent handle range + for(i = NextPermanentHandle(handle); i != 0; i = NextPermanentHandle(i + 1)) + { + if(handleList->count < count) + { + // If we have not filled up the return list, add this permanent + // handle to it + handleList->handle[handleList->count] = i; + handleList->count++; + } + else + { + // If the return list is full but we still have permanent handle + // available, report this and stop iterating + more = YES; + break; + } + } + return more; +} + +//*** PermanentHandleGetPolicy() +// This function returns a list of the permanent handles of PCR, started from +// 'handle'. If 'handle' is larger than the largest permanent handle, an empty list +// will be returned with 'more' set to NO. +// Return Type: TPMI_YES_NO +// YES if there are more handles available +// NO all the available handles has been returned +TPMI_YES_NO +PermanentHandleGetPolicy(TPM_HANDLE handle, // IN: start handle + UINT32 count, // IN: max count of returned handles + TPML_TAGGED_POLICY* policyList // OUT: list of handle +) +{ + TPMI_YES_NO more = NO; + + pAssert(HandleGetType(handle) == TPM_HT_PERMANENT); + + // Initialize output handle list + policyList->count = 0; + + // The maximum count of policies we may return is MAX_TAGGED_POLICIES + if(count > MAX_TAGGED_POLICIES) + count = MAX_TAGGED_POLICIES; + + // Iterate permanent handle range + for(handle = NextPermanentHandle(handle); handle != 0; + handle = NextPermanentHandle(handle + 1)) + { + TPM2B_DIGEST policyDigest; + TPM_ALG_ID policyAlg; + // Check to see if this permanent handle has a policy + policyAlg = EntityGetAuthPolicy(handle, &policyDigest); + if(policyAlg == TPM_ALG_ERROR) + continue; + if(policyList->count < count) + { + // If we have not filled up the return list, add this + // policy to the list; + policyList->policies[policyList->count].handle = handle; + policyList->policies[policyList->count].policyHash.hashAlg = policyAlg; + MemoryCopy(&policyList->policies[policyList->count].policyHash.digest, + policyDigest.t.buffer, + policyDigest.t.size); + policyList->count++; + } + else + { + // If the return list is full but we still have permanent handle + // available, report this and stop iterating + more = YES; + break; + } + } + return more; +} diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/IoBuffers.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/IoBuffers.c new file mode 100644 index 0000000..ec4d6fb --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/IoBuffers.c @@ -0,0 +1,112 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//** Includes and Data Definitions + +// This definition allows this module to "see" the values that are private +// to this module but kept in Global.c for ease of state migration. +#define IO_BUFFER_C +#include "Tpm.h" +#include "IoBuffers_fp.h" + +//** Buffers and Functions + +// These buffers are set aside to hold command and response values. In this +// implementation, it is not guaranteed that the code will stop accessing +// the s_actionInputBuffer before starting to put values in the +// s_actionOutputBuffer so different buffers are required. +// + +//*** MemoryIoBufferAllocationReset() +// This function is used to reset the allocation of buffers. +void MemoryIoBufferAllocationReset(void) +{ + s_actionIoAllocation = 0; +} + +//*** MemoryIoBufferZero() +// Function zeros the action I/O buffer at the end of a command. Calling this is +// not mandatory for proper functionality. +void MemoryIoBufferZero(void) +{ + memset(s_actionIoBuffer, 0, s_actionIoAllocation); +} + +//*** MemoryGetInBuffer() +// This function returns the address of the buffer into which the +// command parameters will be unmarshaled in preparation for calling +// the command actions. +BYTE* MemoryGetInBuffer(UINT32 size // Size, in bytes, required for the input + // unmarshaling +) +{ + pAssert(size <= sizeof(s_actionIoBuffer)); +// In this implementation, a static buffer is set aside for the command action +// buffers. The buffer is shared between input and output. This is because +// there is no need to allocate for the worst case input and worst case output +// at the same time. +// Round size up +#define UoM (sizeof(s_actionIoBuffer[0])) + size = (size + (UoM - 1)) & (UINT32_MAX - (UoM - 1)); + memset(s_actionIoBuffer, 0, size); + s_actionIoAllocation = size; + return (BYTE*)&s_actionIoBuffer[0]; +} + +//*** MemoryGetOutBuffer() +// This function returns the address of the buffer into which the command +// action code places its output values. +BYTE* MemoryGetOutBuffer(UINT32 size // required size of the buffer +) +{ + BYTE* retVal = (BYTE*)(&s_actionIoBuffer[s_actionIoAllocation / UoM]); + pAssert((size + s_actionIoAllocation) < (sizeof(s_actionIoBuffer))); + // In this implementation, a static buffer is set aside for the command action + // output buffer. + memset(retVal, 0, size); + s_actionIoAllocation += size; + return retVal; +} + +//*** IsLabelProperlyFormatted() +// This function checks that a label is a null-terminated string. +// NOTE: this function is here because there was no better place for it. +// Return Type: BOOL +// TRUE(1) string is null terminated +// FALSE(0) string is not null terminated +BOOL IsLabelProperlyFormatted(TPM2B* x) +{ + return (((x)->size == 0) || ((x)->buffer[(x)->size - 1] == 0)); +} diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Locality.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Locality.c new file mode 100644 index 0000000..97f5e51 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Locality.c @@ -0,0 +1,74 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Includes +#include "Tpm.h" + +//** LocalityGetAttributes() +// This function will convert a locality expressed as an integer into +// TPMA_LOCALITY form. +// +// The function returns the locality attribute. +TPMA_LOCALITY +LocalityGetAttributes(UINT8 locality // IN: locality value +) +{ + TPMA_LOCALITY locality_attributes; + BYTE* localityAsByte = (BYTE*)&locality_attributes; + + MemorySet(&locality_attributes, 0, sizeof(TPMA_LOCALITY)); + switch(locality) + { + case 0: + SET_ATTRIBUTE(locality_attributes, TPMA_LOCALITY, TPM_LOC_ZERO); + break; + case 1: + SET_ATTRIBUTE(locality_attributes, TPMA_LOCALITY, TPM_LOC_ONE); + break; + case 2: + SET_ATTRIBUTE(locality_attributes, TPMA_LOCALITY, TPM_LOC_TWO); + break; + case 3: + SET_ATTRIBUTE(locality_attributes, TPMA_LOCALITY, TPM_LOC_THREE); + break; + case 4: + SET_ATTRIBUTE(locality_attributes, TPMA_LOCALITY, TPM_LOC_FOUR); + break; + default: + pAssert(locality > 31); + *localityAsByte = locality; + break; + } + return locality_attributes; +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Manufacture.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Manufacture.c new file mode 100644 index 0000000..447481a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Manufacture.c @@ -0,0 +1,176 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Description +// This file contains the function that performs the "manufacturing" of the TPM +// in a simulated environment. These functions should not be used outside of +// a manufacturing or simulation environment. + +//** Includes and Data Definitions +#define MANUFACTURE_C +#include "Tpm.h" +#include "TpmSizeChecks_fp.h" + +//** Functions + +//*** TPM_Manufacture() +// This function initializes the TPM values in preparation for the TPM's first +// use. This function will fail if previously called. The TPM can be re-manufactured +// by calling TPM_Teardown() first and then calling this function again. +// Return Type: int +// -1 failure +// 0 success +// 1 manufacturing process previously performed +LIB_EXPORT int TPM_Manufacture( + int firstTime // IN: indicates if this is the first call from + // main() +) +{ + TPM_SU orderlyShutdown; + +#if RUNTIME_SIZE_CHECKS + // Call the function to verify the sizes of values that result from different + // compile options. + if(!TpmSizeChecks()) + return -1; +#endif +#if LIBRARY_COMPATIBILITY_CHECK + // Make sure that the attached library performs as expected. + if(!MathLibraryCompatibilityCheck()) + return -1; +#endif + + // If TPM has been manufactured, return indication. + if(!firstTime && g_manufactured) + return 1; + + // Do power on initializations of the cryptographic libraries. + CryptInit(); + + s_DAPendingOnNV = FALSE; + + // initialize NV + NvManufacture(); + + // Clear the magic value in the DRBG state + go.drbgState.magic = 0; + + CryptStartup(SU_RESET); + + // default configuration for PCR + PCRSimStart(); + + // initialize pre-installed hierarchy data + // This should happen after NV is initialized because hierarchy data is + // stored in NV. + HierarchyPreInstall_Init(); + + // initialize dictionary attack parameters + DAPreInstall_Init(); + + // initialize PP list + PhysicalPresencePreInstall_Init(); + + // initialize command audit list + CommandAuditPreInstall_Init(); + + // first start up is required to be Startup(CLEAR) + orderlyShutdown = TPM_SU_CLEAR; + NV_WRITE_PERSISTENT(orderlyState, orderlyShutdown); + + // initialize the firmware version + gp.firmwareV1 = FIRMWARE_V1; +#ifdef FIRMWARE_V2 + gp.firmwareV2 = FIRMWARE_V2; +#else + gp.firmwareV2 = 0; +#endif + NV_SYNC_PERSISTENT(firmwareV1); + NV_SYNC_PERSISTENT(firmwareV2); + + // initialize the total reset counter to 0 + gp.totalResetCount = 0; + NV_SYNC_PERSISTENT(totalResetCount); + + // initialize the clock stuff + go.clock = 0; + go.clockSafe = YES; + + NvWrite(NV_ORDERLY_DATA, sizeof(ORDERLY_DATA), &go); + + // Commit NV writes. Manufacture process is an artificial process existing + // only in simulator environment and it is not defined in the specification + // that what should be the expected behavior if the NV write fails at this + // point. Therefore, it is assumed the NV write here is always success and + // no return code of this function is checked. + NvCommit(); + + g_manufactured = TRUE; + + return 0; +} + +//*** TPM_TearDown() +// This function prepares the TPM for re-manufacture. It should not be implemented +// in anything other than a simulated TPM. +// +// In this implementation, all that is needs is to stop the cryptographic units +// and set a flag to indicate that the TPM can be re-manufactured. This should +// be all that is necessary to start the manufacturing process again. +// Return Type: int +// 0 success +// 1 TPM not previously manufactured +LIB_EXPORT int TPM_TearDown(void) +{ + g_manufactured = FALSE; + return 0; +} + +//*** TpmEndSimulation() +// This function is called at the end of the simulation run. It is used to provoke +// printing of any statistics that might be needed. +LIB_EXPORT void TpmEndSimulation(void) +{ +#if SIMULATION + HashLibSimulationEnd(); + SymLibSimulationEnd(); + MathLibSimulationEnd(); +# if ALG_RSA + RsaSimulationEnd(); +# endif +# if ALG_ECC + EccSimulationEnd(); +# endif +#endif // SIMULATION +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Marshal.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Marshal.c new file mode 100644 index 0000000..7fa9bbd --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Marshal.c @@ -0,0 +1,6922 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by TpmMarshal; Version 4.1 Dec 10, 2018 + * Date: Mar 6, 2020 Time: 01:50:10PM + */ + +#include "Tpm.h" +#if !TABLE_DRIVEN_MARSHAL +# include "Marshal_fp.h" + +// Table 2:3 - Definition of Base Types +// UINT8 definition from table 2:3 +TPM_RC +UINT8_Unmarshal(UINT8* target, BYTE** buffer, INT32* size) +{ + if((*size -= 1) < 0) + return TPM_RC_INSUFFICIENT; + *target = BYTE_ARRAY_TO_UINT8(*buffer); + *buffer += 1; + return TPM_RC_SUCCESS; +} +UINT16 +UINT8_Marshal(UINT8* source, BYTE** buffer, INT32* size) +{ + if(buffer != 0) + { + if((size == 0) || ((*size -= 1) >= 0)) + { + UINT8_TO_BYTE_ARRAY(*source, *buffer); + *buffer += 1; + } + pAssert(size == 0 || (*size >= 0)); + } + return (1); +} + +// BYTE definition from table 2:3 +# if !USE_MARSHALING_DEFINES +TPM_RC +BYTE_Unmarshal(BYTE* target, BYTE** buffer, INT32* size) +{ + return UINT8_Unmarshal((UINT8*)target, buffer, size); +} +UINT16 +BYTE_Marshal(BYTE* source, BYTE** buffer, INT32* size) +{ + return UINT8_Marshal((UINT8*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// INT8 definition from table 2:3 +# if !USE_MARSHALING_DEFINES +TPM_RC +INT8_Unmarshal(INT8* target, BYTE** buffer, INT32* size) +{ + return UINT8_Unmarshal((UINT8*)target, buffer, size); +} +UINT16 +INT8_Marshal(INT8* source, BYTE** buffer, INT32* size) +{ + return UINT8_Marshal((UINT8*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// UINT16 definition from table 2:3 +TPM_RC +UINT16_Unmarshal(UINT16* target, BYTE** buffer, INT32* size) +{ + if((*size -= 2) < 0) + return TPM_RC_INSUFFICIENT; + *target = BYTE_ARRAY_TO_UINT16(*buffer); + *buffer += 2; + return TPM_RC_SUCCESS; +} +UINT16 +UINT16_Marshal(UINT16* source, BYTE** buffer, INT32* size) +{ + if(buffer != 0) + { + if((size == 0) || ((*size -= 2) >= 0)) + { + UINT16_TO_BYTE_ARRAY(*source, *buffer); + *buffer += 2; + } + pAssert(size == 0 || (*size >= 0)); + } + return (2); +} + +// INT16 definition from table 2:3 +# if !USE_MARSHALING_DEFINES +TPM_RC +INT16_Unmarshal(INT16* target, BYTE** buffer, INT32* size) +{ + return UINT16_Unmarshal((UINT16*)target, buffer, size); +} +UINT16 +INT16_Marshal(INT16* source, BYTE** buffer, INT32* size) +{ + return UINT16_Marshal((UINT16*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// UINT32 definition from table 2:3 +TPM_RC +UINT32_Unmarshal(UINT32* target, BYTE** buffer, INT32* size) +{ + if((*size -= 4) < 0) + return TPM_RC_INSUFFICIENT; + *target = BYTE_ARRAY_TO_UINT32(*buffer); + *buffer += 4; + return TPM_RC_SUCCESS; +} +UINT16 +UINT32_Marshal(UINT32* source, BYTE** buffer, INT32* size) +{ + if(buffer != 0) + { + if((size == 0) || ((*size -= 4) >= 0)) + { + UINT32_TO_BYTE_ARRAY(*source, *buffer); + *buffer += 4; + } + pAssert(size == 0 || (*size >= 0)); + } + return (4); +} + +// INT32 definition from table 2:3 +# if !USE_MARSHALING_DEFINES +TPM_RC +INT32_Unmarshal(INT32* target, BYTE** buffer, INT32* size) +{ + return UINT32_Unmarshal((UINT32*)target, buffer, size); +} +UINT16 +INT32_Marshal(INT32* source, BYTE** buffer, INT32* size) +{ + return UINT32_Marshal((UINT32*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// UINT64 definition from table 2:3 +TPM_RC +UINT64_Unmarshal(UINT64* target, BYTE** buffer, INT32* size) +{ + if((*size -= 8) < 0) + return TPM_RC_INSUFFICIENT; + *target = BYTE_ARRAY_TO_UINT64(*buffer); + *buffer += 8; + return TPM_RC_SUCCESS; +} +UINT16 +UINT64_Marshal(UINT64* source, BYTE** buffer, INT32* size) +{ + if(buffer != 0) + { + if((size == 0) || ((*size -= 8) >= 0)) + { + UINT64_TO_BYTE_ARRAY(*source, *buffer); + *buffer += 8; + } + pAssert(size == 0 || (*size >= 0)); + } + return (8); +} + +// INT64 definition from table 2:3 +# if !USE_MARSHALING_DEFINES +TPM_RC +INT64_Unmarshal(INT64* target, BYTE** buffer, INT32* size) +{ + return UINT64_Unmarshal((UINT64*)target, buffer, size); +} +UINT16 +INT64_Marshal(INT64* source, BYTE** buffer, INT32* size) +{ + return UINT64_Marshal((UINT64*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:4 - Defines for Logic Values +// Table 2:5 - Definition of Types for Documentation Clarity +# if !USE_MARSHALING_DEFINES +TPM_RC +TPM_ALGORITHM_ID_Unmarshal(TPM_ALGORITHM_ID* target, BYTE** buffer, INT32* size) +{ + return UINT32_Unmarshal((UINT32*)target, buffer, size); +} +UINT16 +TPM_ALGORITHM_ID_Marshal(TPM_ALGORITHM_ID* source, BYTE** buffer, INT32* size) +{ + return UINT32_Marshal((UINT32*)source, buffer, size); +} +TPM_RC +TPM_MODIFIER_INDICATOR_Unmarshal( + TPM_MODIFIER_INDICATOR* target, BYTE** buffer, INT32* size) +{ + return UINT32_Unmarshal((UINT32*)target, buffer, size); +} +UINT16 +TPM_MODIFIER_INDICATOR_Marshal( + TPM_MODIFIER_INDICATOR* source, BYTE** buffer, INT32* size) +{ + return UINT32_Marshal((UINT32*)source, buffer, size); +} +TPM_RC +TPM_AUTHORIZATION_SIZE_Unmarshal( + TPM_AUTHORIZATION_SIZE* target, BYTE** buffer, INT32* size) +{ + return UINT32_Unmarshal((UINT32*)target, buffer, size); +} +UINT16 +TPM_AUTHORIZATION_SIZE_Marshal( + TPM_AUTHORIZATION_SIZE* source, BYTE** buffer, INT32* size) +{ + return UINT32_Marshal((UINT32*)source, buffer, size); +} +TPM_RC +TPM_PARAMETER_SIZE_Unmarshal(TPM_PARAMETER_SIZE* target, BYTE** buffer, INT32* size) +{ + return UINT32_Unmarshal((UINT32*)target, buffer, size); +} +UINT16 +TPM_PARAMETER_SIZE_Marshal(TPM_PARAMETER_SIZE* source, BYTE** buffer, INT32* size) +{ + return UINT32_Marshal((UINT32*)source, buffer, size); +} +TPM_RC +TPM_KEY_SIZE_Unmarshal(TPM_KEY_SIZE* target, BYTE** buffer, INT32* size) +{ + return UINT16_Unmarshal((UINT16*)target, buffer, size); +} +UINT16 +TPM_KEY_SIZE_Marshal(TPM_KEY_SIZE* source, BYTE** buffer, INT32* size) +{ + return UINT16_Marshal((UINT16*)source, buffer, size); +} +TPM_RC +TPM_KEY_BITS_Unmarshal(TPM_KEY_BITS* target, BYTE** buffer, INT32* size) +{ + return UINT16_Unmarshal((UINT16*)target, buffer, size); +} +UINT16 +TPM_KEY_BITS_Marshal(TPM_KEY_BITS* source, BYTE** buffer, INT32* size) +{ + return UINT16_Marshal((UINT16*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:6 - Definition of TPM_SPEC Constants +// Table 2:7 - Definition of TPM_CONSTANTS32 Constants +# if !USE_MARSHALING_DEFINES +UINT16 +TPM_CONSTANTS32_Marshal(TPM_CONSTANTS32* source, BYTE** buffer, INT32* size) +{ + return UINT32_Marshal((UINT32*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:9 - Definition of TPM_ALG_ID Constants +# if !USE_MARSHALING_DEFINES +TPM_RC +TPM_ALG_ID_Unmarshal(TPM_ALG_ID* target, BYTE** buffer, INT32* size) +{ + return UINT16_Unmarshal((UINT16*)target, buffer, size); +} +UINT16 +TPM_ALG_ID_Marshal(TPM_ALG_ID* source, BYTE** buffer, INT32* size) +{ + return UINT16_Marshal((UINT16*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:10 - Definition of TPM_ECC_CURVE Constants +# if ALG_ECC +TPM_RC +TPM_ECC_CURVE_Unmarshal(TPM_ECC_CURVE* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT16_Unmarshal((UINT16*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { + case TPM_ECC_NIST_P192: + case TPM_ECC_NIST_P224: + case TPM_ECC_NIST_P256: + case TPM_ECC_NIST_P384: + case TPM_ECC_NIST_P521: + case TPM_ECC_BN_P256: + case TPM_ECC_BN_P638: + case TPM_ECC_SM2_P256: + break; + default: + result = TPM_RC_CURVE; + break; + } + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPM_ECC_CURVE_Marshal(TPM_ECC_CURVE* source, BYTE** buffer, INT32* size) +{ + return UINT16_Marshal((UINT16*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES +# endif // ALG_ECC + +// Table 2:12 - Definition of TPM_CC Constants +# if !USE_MARSHALING_DEFINES +TPM_RC +TPM_CC_Unmarshal(TPM_CC* target, BYTE** buffer, INT32* size) +{ + return UINT32_Unmarshal((UINT32*)target, buffer, size); +} +UINT16 +TPM_CC_Marshal(TPM_CC* source, BYTE** buffer, INT32* size) +{ + return UINT32_Marshal((UINT32*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:16 - Definition of TPM_RC Constants +# if !USE_MARSHALING_DEFINES +UINT16 +TPM_RC_Marshal(TPM_RC* source, BYTE** buffer, INT32* size) +{ + return UINT32_Marshal((UINT32*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:17 - Definition of TPM_CLOCK_ADJUST Constants +TPM_RC +TPM_CLOCK_ADJUST_Unmarshal(TPM_CLOCK_ADJUST* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = INT8_Unmarshal((INT8*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { + case TPM_CLOCK_COARSE_SLOWER: + case TPM_CLOCK_MEDIUM_SLOWER: + case TPM_CLOCK_FINE_SLOWER: + case TPM_CLOCK_NO_CHANGE: + case TPM_CLOCK_FINE_FASTER: + case TPM_CLOCK_MEDIUM_FASTER: + case TPM_CLOCK_COARSE_FASTER: + break; + default: + result = TPM_RC_VALUE; + break; + } + } + return result; +} + +// Table 2:18 - Definition of TPM_EO Constants +TPM_RC +TPM_EO_Unmarshal(TPM_EO* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT16_Unmarshal((UINT16*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { + case TPM_EO_EQ: + case TPM_EO_NEQ: + case TPM_EO_SIGNED_GT: + case TPM_EO_UNSIGNED_GT: + case TPM_EO_SIGNED_LT: + case TPM_EO_UNSIGNED_LT: + case TPM_EO_SIGNED_GE: + case TPM_EO_UNSIGNED_GE: + case TPM_EO_SIGNED_LE: + case TPM_EO_UNSIGNED_LE: + case TPM_EO_BITSET: + case TPM_EO_BITCLEAR: + break; + default: + result = TPM_RC_VALUE; + break; + } + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPM_EO_Marshal(TPM_EO* source, BYTE** buffer, INT32* size) +{ + return UINT16_Marshal((UINT16*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:19 - Definition of TPM_ST Constants +# if !USE_MARSHALING_DEFINES +TPM_RC +TPM_ST_Unmarshal(TPM_ST* target, BYTE** buffer, INT32* size) +{ + return UINT16_Unmarshal((UINT16*)target, buffer, size); +} +UINT16 +TPM_ST_Marshal(TPM_ST* source, BYTE** buffer, INT32* size) +{ + return UINT16_Marshal((UINT16*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:20 - Definition of TPM_SU Constants +TPM_RC +TPM_SU_Unmarshal(TPM_SU* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT16_Unmarshal((UINT16*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { + case TPM_SU_CLEAR: + case TPM_SU_STATE: + break; + default: + result = TPM_RC_VALUE; + break; + } + } + return result; +} + +// Table 2:21 - Definition of TPM_SE Constants +TPM_RC +TPM_SE_Unmarshal(TPM_SE* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT8_Unmarshal((UINT8*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { + case TPM_SE_HMAC: + case TPM_SE_POLICY: + case TPM_SE_TRIAL: + break; + default: + result = TPM_RC_VALUE; + break; + } + } + return result; +} + +// Table 2:22 - Definition of TPM_CAP Constants +TPM_RC +TPM_CAP_Unmarshal(TPM_CAP* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT32_Unmarshal((UINT32*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { + case TPM_CAP_ALGS: + case TPM_CAP_HANDLES: + case TPM_CAP_COMMANDS: + case TPM_CAP_PP_COMMANDS: + case TPM_CAP_AUDIT_COMMANDS: + case TPM_CAP_PCRS: + case TPM_CAP_TPM_PROPERTIES: + case TPM_CAP_PCR_PROPERTIES: + case TPM_CAP_ECC_CURVES: + case TPM_CAP_AUTH_POLICIES: + case TPM_CAP_ACT: + case TPM_CAP_VENDOR_PROPERTY: + break; + default: + result = TPM_RC_VALUE; + break; + } + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPM_CAP_Marshal(TPM_CAP* source, BYTE** buffer, INT32* size) +{ + return UINT32_Marshal((UINT32*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:23 - Definition of TPM_PT Constants +# if !USE_MARSHALING_DEFINES +TPM_RC +TPM_PT_Unmarshal(TPM_PT* target, BYTE** buffer, INT32* size) +{ + return UINT32_Unmarshal((UINT32*)target, buffer, size); +} +UINT16 +TPM_PT_Marshal(TPM_PT* source, BYTE** buffer, INT32* size) +{ + return UINT32_Marshal((UINT32*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:24 - Definition of TPM_PT_PCR Constants +# if !USE_MARSHALING_DEFINES +TPM_RC +TPM_PT_PCR_Unmarshal(TPM_PT_PCR* target, BYTE** buffer, INT32* size) +{ + return UINT32_Unmarshal((UINT32*)target, buffer, size); +} +UINT16 +TPM_PT_PCR_Marshal(TPM_PT_PCR* source, BYTE** buffer, INT32* size) +{ + return UINT32_Marshal((UINT32*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:25 - Definition of TPM_PS Constants +# if !USE_MARSHALING_DEFINES +UINT16 +TPM_PS_Marshal(TPM_PS* source, BYTE** buffer, INT32* size) +{ + return UINT32_Marshal((UINT32*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:26 - Definition of Types for Handles +# if !USE_MARSHALING_DEFINES +TPM_RC +TPM_HANDLE_Unmarshal(TPM_HANDLE* target, BYTE** buffer, INT32* size) +{ + return UINT32_Unmarshal((UINT32*)target, buffer, size); +} +UINT16 +TPM_HANDLE_Marshal(TPM_HANDLE* source, BYTE** buffer, INT32* size) +{ + return UINT32_Marshal((UINT32*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:27 - Definition of TPM_HT Constants +# if !USE_MARSHALING_DEFINES +TPM_RC +TPM_HT_Unmarshal(TPM_HT* target, BYTE** buffer, INT32* size) +{ + return UINT8_Unmarshal((UINT8*)target, buffer, size); +} +UINT16 +TPM_HT_Marshal(TPM_HT* source, BYTE** buffer, INT32* size) +{ + return UINT8_Marshal((UINT8*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:28 - Definition of TPM_RH Constants +# if !USE_MARSHALING_DEFINES +TPM_RC +TPM_RH_Unmarshal(TPM_RH* target, BYTE** buffer, INT32* size) +{ + return TPM_HANDLE_Unmarshal((TPM_HANDLE*)target, buffer, size); +} +UINT16 +TPM_RH_Marshal(TPM_RH* source, BYTE** buffer, INT32* size) +{ + return TPM_HANDLE_Marshal((TPM_HANDLE*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:29 - Definition of TPM_HC Constants +# if !USE_MARSHALING_DEFINES +TPM_RC +TPM_HC_Unmarshal(TPM_HC* target, BYTE** buffer, INT32* size) +{ + return TPM_HANDLE_Unmarshal((TPM_HANDLE*)target, buffer, size); +} +UINT16 +TPM_HC_Marshal(TPM_HC* source, BYTE** buffer, INT32* size) +{ + return TPM_HANDLE_Marshal((TPM_HANDLE*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:30 - Definition of TPMA_ALGORITHM Bits +TPM_RC +TPMA_ALGORITHM_Unmarshal(TPMA_ALGORITHM* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT32_Unmarshal((UINT32*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + if(*((UINT32*)target) & (UINT32)0xfffff8f0) + result = TPM_RC_RESERVED_BITS; + } + return result; +} + +# if !USE_MARSHALING_DEFINES +UINT16 +TPMA_ALGORITHM_Marshal(TPMA_ALGORITHM* source, BYTE** buffer, INT32* size) +{ + return UINT32_Marshal((UINT32*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:31 - Definition of TPMA_OBJECT Bits +TPM_RC +TPMA_OBJECT_Unmarshal(TPMA_OBJECT* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT32_Unmarshal((UINT32*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + if(*((UINT32*)target) & (UINT32)0xfff0f309) + result = TPM_RC_RESERVED_BITS; + } + return result; +} + +# if !USE_MARSHALING_DEFINES +UINT16 +TPMA_OBJECT_Marshal(TPMA_OBJECT* source, BYTE** buffer, INT32* size) +{ + return UINT32_Marshal((UINT32*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:32 - Definition of TPMA_SESSION Bits +TPM_RC +TPMA_SESSION_Unmarshal(TPMA_SESSION* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT8_Unmarshal((UINT8*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + if(*((UINT8*)target) & (UINT8)0x18) + result = TPM_RC_RESERVED_BITS; + } + return result; +} + +# if !USE_MARSHALING_DEFINES +UINT16 +TPMA_SESSION_Marshal(TPMA_SESSION* source, BYTE** buffer, INT32* size) +{ + return UINT8_Marshal((UINT8*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:33 - Definition of TPMA_LOCALITY Bits +# if !USE_MARSHALING_DEFINES +TPM_RC +TPMA_LOCALITY_Unmarshal(TPMA_LOCALITY* target, BYTE** buffer, INT32* size) +{ + return UINT8_Unmarshal((UINT8*)target, buffer, size); +} +UINT16 +TPMA_LOCALITY_Marshal(TPMA_LOCALITY* source, BYTE** buffer, INT32* size) +{ + return UINT8_Marshal((UINT8*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:34 - Definition of TPMA_PERMANENT Bits +# if !USE_MARSHALING_DEFINES +UINT16 +TPMA_PERMANENT_Marshal(TPMA_PERMANENT* source, BYTE** buffer, INT32* size) +{ + return UINT32_Marshal((UINT32*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:35 - Definition of TPMA_STARTUP_CLEAR Bits +# if !USE_MARSHALING_DEFINES +UINT16 +TPMA_STARTUP_CLEAR_Marshal(TPMA_STARTUP_CLEAR* source, BYTE** buffer, INT32* size) +{ + return UINT32_Marshal((UINT32*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:36 - Definition of TPMA_MEMORY Bits +# if !USE_MARSHALING_DEFINES +UINT16 +TPMA_MEMORY_Marshal(TPMA_MEMORY* source, BYTE** buffer, INT32* size) +{ + return UINT32_Marshal((UINT32*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:37 - Definition of TPMA_CC Bits +# if !USE_MARSHALING_DEFINES +UINT16 +TPMA_CC_Marshal(TPMA_CC* source, BYTE** buffer, INT32* size) +{ + return TPM_CC_Marshal((TPM_CC*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:38 - Definition of TPMA_MODES Bits +# if !USE_MARSHALING_DEFINES +UINT16 +TPMA_MODES_Marshal(TPMA_MODES* source, BYTE** buffer, INT32* size) +{ + return UINT32_Marshal((UINT32*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:39 - Definition of TPMA_X509_KEY_USAGE Bits +# if !USE_MARSHALING_DEFINES +UINT16 +TPMA_X509_KEY_USAGE_Marshal(TPMA_X509_KEY_USAGE* source, BYTE** buffer, INT32* size) +{ + return UINT32_Marshal((UINT32*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:40 - Definition of TPMA_ACT Bits +TPM_RC +TPMA_ACT_Unmarshal(TPMA_ACT* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT32_Unmarshal((UINT32*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + if(*((UINT32*)target) & (UINT32)0xfffffffc) + result = TPM_RC_RESERVED_BITS; + } + return result; +} + +# if !USE_MARSHALING_DEFINES +UINT16 +TPMA_ACT_Marshal(TPMA_ACT* source, BYTE** buffer, INT32* size) +{ + return UINT32_Marshal((UINT32*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:41 - Definition of TPMI_YES_NO Type +TPM_RC +TPMI_YES_NO_Unmarshal(TPMI_YES_NO* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = BYTE_Unmarshal((BYTE*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { + case NO: + case YES: + break; + default: + result = TPM_RC_VALUE; + break; + } + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_YES_NO_Marshal(TPMI_YES_NO* source, BYTE** buffer, INT32* size) +{ + return BYTE_Marshal((BYTE*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:42 - Definition of TPMI_DH_OBJECT Type +TPM_RC +TPMI_DH_OBJECT_Unmarshal( + TPMI_DH_OBJECT* target, BYTE** buffer, INT32* size, BOOL flag) +{ + TPM_RC result; + result = TPM_HANDLE_Unmarshal((TPM_HANDLE*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + if(*target == TPM_RH_NULL) + { + if(!flag) + result = TPM_RC_VALUE; + } + else if(((*target < TRANSIENT_FIRST) || (*target > TRANSIENT_LAST)) + && ((*target < PERSISTENT_FIRST) || (*target > PERSISTENT_LAST))) + result = TPM_RC_VALUE; + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_DH_OBJECT_Marshal(TPMI_DH_OBJECT* source, BYTE** buffer, INT32* size) +{ + return TPM_HANDLE_Marshal((TPM_HANDLE*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:43 - Definition of TPMI_DH_PARENT Type +TPM_RC +TPMI_DH_PARENT_Unmarshal( + TPMI_DH_PARENT* target, BYTE** buffer, INT32* size, BOOL flag) +{ + TPM_RC result; + result = TPM_HANDLE_Unmarshal((TPM_HANDLE*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { + case TPM_RH_OWNER: + case TPM_RH_PLATFORM: + case TPM_RH_ENDORSEMENT: + break; + case TPM_RH_NULL: + if(!flag) + result = TPM_RC_VALUE; + break; + default: + if(((*target < TRANSIENT_FIRST) || (*target > TRANSIENT_LAST)) + && ((*target < PERSISTENT_FIRST) || (*target > PERSISTENT_LAST))) + result = TPM_RC_VALUE; + break; + } + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_DH_PARENT_Marshal(TPMI_DH_PARENT* source, BYTE** buffer, INT32* size) +{ + return TPM_HANDLE_Marshal((TPM_HANDLE*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:44 - Definition of TPMI_DH_PERSISTENT Type +TPM_RC +TPMI_DH_PERSISTENT_Unmarshal(TPMI_DH_PERSISTENT* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = TPM_HANDLE_Unmarshal((TPM_HANDLE*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + if((*target < PERSISTENT_FIRST) || (*target > PERSISTENT_LAST)) + result = TPM_RC_VALUE; + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_DH_PERSISTENT_Marshal(TPMI_DH_PERSISTENT* source, BYTE** buffer, INT32* size) +{ + return TPM_HANDLE_Marshal((TPM_HANDLE*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:45 - Definition of TPMI_DH_ENTITY Type +TPM_RC +TPMI_DH_ENTITY_Unmarshal( + TPMI_DH_ENTITY* target, BYTE** buffer, INT32* size, BOOL flag) +{ + TPM_RC result; + result = TPM_HANDLE_Unmarshal((TPM_HANDLE*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { + case TPM_RH_OWNER: + case TPM_RH_ENDORSEMENT: + case TPM_RH_PLATFORM: + case TPM_RH_LOCKOUT: + break; + case TPM_RH_NULL: + if(!flag) + result = TPM_RC_VALUE; + break; + default: + if(((*target < TRANSIENT_FIRST) || (*target > TRANSIENT_LAST)) + && ((*target < PERSISTENT_FIRST) || (*target > PERSISTENT_LAST)) + && ((*target < NV_INDEX_FIRST) || (*target > NV_INDEX_LAST)) + && (*target > PCR_LAST) + && ((*target < TPM_RH_AUTH_00) || (*target > TPM_RH_AUTH_FF))) + result = TPM_RC_VALUE; + break; + } + } + return result; +} + +// Table 2:46 - Definition of TPMI_DH_PCR Type +TPM_RC +TPMI_DH_PCR_Unmarshal(TPMI_DH_PCR* target, BYTE** buffer, INT32* size, BOOL flag) +{ + TPM_RC result; + result = TPM_HANDLE_Unmarshal((TPM_HANDLE*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + if(*target == TPM_RH_NULL) + { + if(!flag) + result = TPM_RC_VALUE; + } + else if(*target > PCR_LAST) + result = TPM_RC_VALUE; + } + return result; +} + +// Table 2:47 - Definition of TPMI_SH_AUTH_SESSION Type +TPM_RC +TPMI_SH_AUTH_SESSION_Unmarshal( + TPMI_SH_AUTH_SESSION* target, BYTE** buffer, INT32* size, BOOL flag) +{ + TPM_RC result; + result = TPM_HANDLE_Unmarshal((TPM_HANDLE*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + if(*target == TPM_RS_PW) + { + if(!flag) + result = TPM_RC_VALUE; + } + else if( + ((*target < HMAC_SESSION_FIRST) || (*target > HMAC_SESSION_LAST)) + && ((*target < POLICY_SESSION_FIRST) || (*target > POLICY_SESSION_LAST))) + result = TPM_RC_VALUE; + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_SH_AUTH_SESSION_Marshal(TPMI_SH_AUTH_SESSION* source, BYTE** buffer, INT32* size) +{ + return TPM_HANDLE_Marshal((TPM_HANDLE*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:48 - Definition of TPMI_SH_HMAC Type +TPM_RC +TPMI_SH_HMAC_Unmarshal(TPMI_SH_HMAC* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = TPM_HANDLE_Unmarshal((TPM_HANDLE*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + if((*target < HMAC_SESSION_FIRST) || (*target > HMAC_SESSION_LAST)) + result = TPM_RC_VALUE; + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_SH_HMAC_Marshal(TPMI_SH_HMAC* source, BYTE** buffer, INT32* size) +{ + return TPM_HANDLE_Marshal((TPM_HANDLE*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:49 - Definition of TPMI_SH_POLICY Type +TPM_RC +TPMI_SH_POLICY_Unmarshal(TPMI_SH_POLICY* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = TPM_HANDLE_Unmarshal((TPM_HANDLE*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + if((*target < POLICY_SESSION_FIRST) || (*target > POLICY_SESSION_LAST)) + result = TPM_RC_VALUE; + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_SH_POLICY_Marshal(TPMI_SH_POLICY* source, BYTE** buffer, INT32* size) +{ + return TPM_HANDLE_Marshal((TPM_HANDLE*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:50 - Definition of TPMI_DH_CONTEXT Type +TPM_RC +TPMI_DH_CONTEXT_Unmarshal(TPMI_DH_CONTEXT* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = TPM_HANDLE_Unmarshal((TPM_HANDLE*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + if(((*target < HMAC_SESSION_FIRST) || (*target > HMAC_SESSION_LAST)) + && ((*target < POLICY_SESSION_FIRST) || (*target > POLICY_SESSION_LAST)) + && ((*target < TRANSIENT_FIRST) || (*target > TRANSIENT_LAST))) + result = TPM_RC_VALUE; + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_DH_CONTEXT_Marshal(TPMI_DH_CONTEXT* source, BYTE** buffer, INT32* size) +{ + return TPM_HANDLE_Marshal((TPM_HANDLE*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:51 - Definition of TPMI_DH_SAVED Type +TPM_RC +TPMI_DH_SAVED_Unmarshal(TPMI_DH_SAVED* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = TPM_HANDLE_Unmarshal((TPM_HANDLE*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { + case 0x80000000: + case 0x80000001: + case 0x80000002: + break; + default: + if(((*target < HMAC_SESSION_FIRST) || (*target > HMAC_SESSION_LAST)) + && ((*target < POLICY_SESSION_FIRST) + || (*target > POLICY_SESSION_LAST))) + result = TPM_RC_VALUE; + break; + } + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_DH_SAVED_Marshal(TPMI_DH_SAVED* source, BYTE** buffer, INT32* size) +{ + return TPM_HANDLE_Marshal((TPM_HANDLE*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:52 - Definition of TPMI_RH_HIERARCHY Type +TPM_RC +TPMI_RH_HIERARCHY_Unmarshal( + TPMI_RH_HIERARCHY* target, BYTE** buffer, INT32* size, BOOL flag) +{ + TPM_RC result; + result = TPM_HANDLE_Unmarshal((TPM_HANDLE*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { + case TPM_RH_OWNER: + case TPM_RH_PLATFORM: + case TPM_RH_ENDORSEMENT: + break; + case TPM_RH_NULL: + if(!flag) + result = TPM_RC_VALUE; + break; + default: + result = TPM_RC_VALUE; + break; + } + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_RH_HIERARCHY_Marshal(TPMI_RH_HIERARCHY* source, BYTE** buffer, INT32* size) +{ + return TPM_HANDLE_Marshal((TPM_HANDLE*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:53 - Definition of TPMI_RH_ENABLES Type +TPM_RC +TPMI_RH_ENABLES_Unmarshal( + TPMI_RH_ENABLES* target, BYTE** buffer, INT32* size, BOOL flag) +{ + TPM_RC result; + result = TPM_HANDLE_Unmarshal((TPM_HANDLE*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { + case TPM_RH_OWNER: + case TPM_RH_PLATFORM: + case TPM_RH_ENDORSEMENT: + case TPM_RH_PLATFORM_NV: + break; + case TPM_RH_NULL: + if(!flag) + result = TPM_RC_VALUE; + break; + default: + result = TPM_RC_VALUE; + break; + } + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_RH_ENABLES_Marshal(TPMI_RH_ENABLES* source, BYTE** buffer, INT32* size) +{ + return TPM_HANDLE_Marshal((TPM_HANDLE*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:54 - Definition of TPMI_RH_HIERARCHY_AUTH Type +TPM_RC +TPMI_RH_HIERARCHY_AUTH_Unmarshal( + TPMI_RH_HIERARCHY_AUTH* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = TPM_HANDLE_Unmarshal((TPM_HANDLE*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { + case TPM_RH_OWNER: + case TPM_RH_PLATFORM: + case TPM_RH_ENDORSEMENT: + case TPM_RH_LOCKOUT: + break; + default: + result = TPM_RC_VALUE; + break; + } + } + return result; +} + +// Table 2:55 - Definition of TPMI_RH_HIERARCHY_POLICY Type +TPM_RC +TPMI_RH_HIERARCHY_POLICY_Unmarshal( + TPMI_RH_HIERARCHY_POLICY* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = TPM_HANDLE_Unmarshal((TPM_HANDLE*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { + case TPM_RH_OWNER: + case TPM_RH_PLATFORM: + case TPM_RH_ENDORSEMENT: + case TPM_RH_LOCKOUT: + break; + default: + if((*target < TPM_RH_ACT_0) || (*target > TPM_RH_ACT_F)) + result = TPM_RC_VALUE; + break; + } + } + return result; +} + +// Table 2:56 - Definition of TPMI_RH_PLATFORM Type +TPM_RC +TPMI_RH_PLATFORM_Unmarshal(TPMI_RH_PLATFORM* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = TPM_HANDLE_Unmarshal((TPM_HANDLE*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { + case TPM_RH_PLATFORM: + break; + default: + result = TPM_RC_VALUE; + break; + } + } + return result; +} + +// Table 2:57 - Definition of TPMI_RH_OWNER Type +TPM_RC +TPMI_RH_OWNER_Unmarshal(TPMI_RH_OWNER* target, BYTE** buffer, INT32* size, BOOL flag) +{ + TPM_RC result; + result = TPM_HANDLE_Unmarshal((TPM_HANDLE*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { + case TPM_RH_OWNER: + break; + case TPM_RH_NULL: + if(!flag) + result = TPM_RC_VALUE; + break; + default: + result = TPM_RC_VALUE; + break; + } + } + return result; +} + +// Table 2:58 - Definition of TPMI_RH_ENDORSEMENT Type +TPM_RC +TPMI_RH_ENDORSEMENT_Unmarshal( + TPMI_RH_ENDORSEMENT* target, BYTE** buffer, INT32* size, BOOL flag) +{ + TPM_RC result; + result = TPM_HANDLE_Unmarshal((TPM_HANDLE*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { + case TPM_RH_ENDORSEMENT: + break; + case TPM_RH_NULL: + if(!flag) + result = TPM_RC_VALUE; + break; + default: + result = TPM_RC_VALUE; + break; + } + } + return result; +} + +// Table 2:59 - Definition of TPMI_RH_PROVISION Type +TPM_RC +TPMI_RH_PROVISION_Unmarshal(TPMI_RH_PROVISION* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = TPM_HANDLE_Unmarshal((TPM_HANDLE*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { + case TPM_RH_OWNER: + case TPM_RH_PLATFORM: + break; + default: + result = TPM_RC_VALUE; + break; + } + } + return result; +} + +// Table 2:60 - Definition of TPMI_RH_CLEAR Type +TPM_RC +TPMI_RH_CLEAR_Unmarshal(TPMI_RH_CLEAR* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = TPM_HANDLE_Unmarshal((TPM_HANDLE*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { + case TPM_RH_LOCKOUT: + case TPM_RH_PLATFORM: + break; + default: + result = TPM_RC_VALUE; + break; + } + } + return result; +} + +// Table 2:61 - Definition of TPMI_RH_NV_AUTH Type +TPM_RC +TPMI_RH_NV_AUTH_Unmarshal(TPMI_RH_NV_AUTH* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = TPM_HANDLE_Unmarshal((TPM_HANDLE*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { + case TPM_RH_PLATFORM: + case TPM_RH_OWNER: + break; + default: + if((*target < NV_INDEX_FIRST) || (*target > NV_INDEX_LAST)) + result = TPM_RC_VALUE; + break; + } + } + return result; +} + +// Table 2:62 - Definition of TPMI_RH_LOCKOUT Type +TPM_RC +TPMI_RH_LOCKOUT_Unmarshal(TPMI_RH_LOCKOUT* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = TPM_HANDLE_Unmarshal((TPM_HANDLE*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { + case TPM_RH_LOCKOUT: + break; + default: + result = TPM_RC_VALUE; + break; + } + } + return result; +} + +// Table 2:63 - Definition of TPMI_RH_NV_INDEX Type +TPM_RC +TPMI_RH_NV_INDEX_Unmarshal(TPMI_RH_NV_INDEX* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = TPM_HANDLE_Unmarshal((TPM_HANDLE*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + if((*target < NV_INDEX_FIRST) || (*target > NV_INDEX_LAST)) + result = TPM_RC_VALUE; + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_RH_NV_INDEX_Marshal(TPMI_RH_NV_INDEX* source, BYTE** buffer, INT32* size) +{ + return TPM_HANDLE_Marshal((TPM_HANDLE*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:64 - Definition of TPMI_RH_AC Type +TPM_RC +TPMI_RH_AC_Unmarshal(TPMI_RH_AC* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = TPM_HANDLE_Unmarshal((TPM_HANDLE*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + if((*target < AC_FIRST) || (*target > AC_LAST)) + result = TPM_RC_VALUE; + } + return result; +} + +// Table 2:65 - Definition of TPMI_RH_ACT Type +TPM_RC +TPMI_RH_ACT_Unmarshal(TPMI_RH_ACT* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = TPM_HANDLE_Unmarshal((TPM_HANDLE*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + if((*target < TPM_RH_ACT_0) || (*target > TPM_RH_ACT_F)) + result = TPM_RC_VALUE; + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_RH_ACT_Marshal(TPMI_RH_ACT* source, BYTE** buffer, INT32* size) +{ + return TPM_HANDLE_Marshal((TPM_HANDLE*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:66 - Definition of TPMI_ALG_HASH Type +TPM_RC +TPMI_ALG_HASH_Unmarshal(TPMI_ALG_HASH* target, BYTE** buffer, INT32* size, BOOL flag) +{ + TPM_RC result; + result = TPM_ALG_ID_Unmarshal((TPM_ALG_ID*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { +# if ALG_SHA1 + case TPM_ALG_SHA1: +# endif // ALG_SHA1 +# if ALG_SHA256 + case TPM_ALG_SHA256: +# endif // ALG_SHA256 +# if ALG_SHA384 + case TPM_ALG_SHA384: +# endif // ALG_SHA384 +# if ALG_SHA512 + case TPM_ALG_SHA512: +# endif // ALG_SHA512 +# if ALG_SM3_256 + case TPM_ALG_SM3_256: +# endif // ALG_SM3_256 +# if ALG_SHA3_256 + case TPM_ALG_SHA3_256: +# endif // ALG_SHA3_256 +# if ALG_SHA3_384 + case TPM_ALG_SHA3_384: +# endif // ALG_SHA3_384 +# if ALG_SHA3_512 + case TPM_ALG_SHA3_512: +# endif // ALG_SHA3_512 + break; + case TPM_ALG_NULL: + if(!flag) + result = TPM_RC_HASH; + break; + default: + result = TPM_RC_HASH; + break; + } + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_ALG_HASH_Marshal(TPMI_ALG_HASH* source, BYTE** buffer, INT32* size) +{ + return TPM_ALG_ID_Marshal((TPM_ALG_ID*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:67 - Definition of TPMI_ALG_ASYM Type +TPM_RC +TPMI_ALG_ASYM_Unmarshal(TPMI_ALG_ASYM* target, BYTE** buffer, INT32* size, BOOL flag) +{ + TPM_RC result; + result = TPM_ALG_ID_Unmarshal((TPM_ALG_ID*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { +# if ALG_RSA + case TPM_ALG_RSA: +# endif // ALG_RSA +# if ALG_ECC + case TPM_ALG_ECC: +# endif // ALG_ECC + break; + case TPM_ALG_NULL: + if(!flag) + result = TPM_RC_ASYMMETRIC; + break; + default: + result = TPM_RC_ASYMMETRIC; + break; + } + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_ALG_ASYM_Marshal(TPMI_ALG_ASYM* source, BYTE** buffer, INT32* size) +{ + return TPM_ALG_ID_Marshal((TPM_ALG_ID*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:68 - Definition of TPMI_ALG_SYM Type +TPM_RC +TPMI_ALG_SYM_Unmarshal(TPMI_ALG_SYM* target, BYTE** buffer, INT32* size, BOOL flag) +{ + TPM_RC result; + result = TPM_ALG_ID_Unmarshal((TPM_ALG_ID*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { +# if ALG_TDES + case TPM_ALG_TDES: +# endif // ALG_TDES +# if ALG_AES + case TPM_ALG_AES: +# endif // ALG_AES +# if ALG_SM4 + case TPM_ALG_SM4: +# endif // ALG_SM4 +# if ALG_CAMELLIA + case TPM_ALG_CAMELLIA: +# endif // ALG_CAMELLIA +# if ALG_XOR + case TPM_ALG_XOR: +# endif // ALG_XOR + break; + case TPM_ALG_NULL: + if(!flag) + result = TPM_RC_SYMMETRIC; + break; + default: + result = TPM_RC_SYMMETRIC; + break; + } + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_ALG_SYM_Marshal(TPMI_ALG_SYM* source, BYTE** buffer, INT32* size) +{ + return TPM_ALG_ID_Marshal((TPM_ALG_ID*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:69 - Definition of TPMI_ALG_SYM_OBJECT Type +TPM_RC +TPMI_ALG_SYM_OBJECT_Unmarshal( + TPMI_ALG_SYM_OBJECT* target, BYTE** buffer, INT32* size, BOOL flag) +{ + TPM_RC result; + result = TPM_ALG_ID_Unmarshal((TPM_ALG_ID*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { +# if ALG_TDES + case TPM_ALG_TDES: +# endif // ALG_TDES +# if ALG_AES + case TPM_ALG_AES: +# endif // ALG_AES +# if ALG_SM4 + case TPM_ALG_SM4: +# endif // ALG_SM4 +# if ALG_CAMELLIA + case TPM_ALG_CAMELLIA: +# endif // ALG_CAMELLIA + break; + case TPM_ALG_NULL: + if(!flag) + result = TPM_RC_SYMMETRIC; + break; + default: + result = TPM_RC_SYMMETRIC; + break; + } + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_ALG_SYM_OBJECT_Marshal(TPMI_ALG_SYM_OBJECT* source, BYTE** buffer, INT32* size) +{ + return TPM_ALG_ID_Marshal((TPM_ALG_ID*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:70 - Definition of TPMI_ALG_SYM_MODE Type +TPM_RC +TPMI_ALG_SYM_MODE_Unmarshal( + TPMI_ALG_SYM_MODE* target, BYTE** buffer, INT32* size, BOOL flag) +{ + TPM_RC result; + result = TPM_ALG_ID_Unmarshal((TPM_ALG_ID*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { +# if ALG_CTR + case TPM_ALG_CTR: +# endif // ALG_CTR +# if ALG_OFB + case TPM_ALG_OFB: +# endif // ALG_OFB +# if ALG_CBC + case TPM_ALG_CBC: +# endif // ALG_CBC +# if ALG_CFB + case TPM_ALG_CFB: +# endif // ALG_CFB +# if ALG_ECB + case TPM_ALG_ECB: +# endif // ALG_ECB +# if ALG_CMAC + case TPM_ALG_CMAC: +# endif // ALG_CMAC + break; + case TPM_ALG_NULL: + if(!flag) + result = TPM_RC_MODE; + break; + default: + result = TPM_RC_MODE; + break; + } + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_ALG_SYM_MODE_Marshal(TPMI_ALG_SYM_MODE* source, BYTE** buffer, INT32* size) +{ + return TPM_ALG_ID_Marshal((TPM_ALG_ID*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:71 - Definition of TPMI_ALG_KDF Type +TPM_RC +TPMI_ALG_KDF_Unmarshal(TPMI_ALG_KDF* target, BYTE** buffer, INT32* size, BOOL flag) +{ + TPM_RC result; + result = TPM_ALG_ID_Unmarshal((TPM_ALG_ID*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { +# if ALG_MGF1 + case TPM_ALG_MGF1: +# endif // ALG_MGF1 +# if ALG_KDF1_SP800_56A + case TPM_ALG_KDF1_SP800_56A: +# endif // ALG_KDF1_SP800_56A +# if ALG_KDF2 + case TPM_ALG_KDF2: +# endif // ALG_KDF2 +# if ALG_KDF1_SP800_108 + case TPM_ALG_KDF1_SP800_108: +# endif // ALG_KDF1_SP800_108 + break; + case TPM_ALG_NULL: + if(!flag) + result = TPM_RC_KDF; + break; + default: + result = TPM_RC_KDF; + break; + } + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_ALG_KDF_Marshal(TPMI_ALG_KDF* source, BYTE** buffer, INT32* size) +{ + return TPM_ALG_ID_Marshal((TPM_ALG_ID*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:72 - Definition of TPMI_ALG_SIG_SCHEME Type +TPM_RC +TPMI_ALG_SIG_SCHEME_Unmarshal( + TPMI_ALG_SIG_SCHEME* target, BYTE** buffer, INT32* size, BOOL flag) +{ + TPM_RC result; + result = TPM_ALG_ID_Unmarshal((TPM_ALG_ID*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { +# if ALG_ECDAA + case TPM_ALG_ECDAA: +# endif // ALG_ECDAA +# if ALG_RSASSA + case TPM_ALG_RSASSA: +# endif // ALG_RSASSA +# if ALG_RSAPSS + case TPM_ALG_RSAPSS: +# endif // ALG_RSAPSS +# if ALG_ECDSA + case TPM_ALG_ECDSA: +# endif // ALG_ECDSA +# if ALG_SM2 + case TPM_ALG_SM2: +# endif // ALG_SM2 +# if ALG_ECSCHNORR + case TPM_ALG_ECSCHNORR: +# endif // ALG_ECSCHNORR +# if ALG_HMAC + case TPM_ALG_HMAC: +# endif // ALG_HMAC + break; + case TPM_ALG_NULL: + if(!flag) + result = TPM_RC_SCHEME; + break; + default: + result = TPM_RC_SCHEME; + break; + } + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_ALG_SIG_SCHEME_Marshal(TPMI_ALG_SIG_SCHEME* source, BYTE** buffer, INT32* size) +{ + return TPM_ALG_ID_Marshal((TPM_ALG_ID*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:73 - Definition of TPMI_ECC_KEY_EXCHANGE Type +# if ALG_ECC +TPM_RC +TPMI_ECC_KEY_EXCHANGE_Unmarshal( + TPMI_ECC_KEY_EXCHANGE* target, BYTE** buffer, INT32* size, BOOL flag) +{ + TPM_RC result; + result = TPM_ALG_ID_Unmarshal((TPM_ALG_ID*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { +# if ALG_ECDH + case TPM_ALG_ECDH: +# endif // ALG_ECDH +# if ALG_ECMQV + case TPM_ALG_ECMQV: +# endif // ALG_ECMQV +# if ALG_SM2 + case TPM_ALG_SM2: +# endif // ALG_SM2 + break; + case TPM_ALG_NULL: + if(!flag) + result = TPM_RC_SCHEME; + break; + default: + result = TPM_RC_SCHEME; + break; + } + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_ECC_KEY_EXCHANGE_Marshal( + TPMI_ECC_KEY_EXCHANGE* source, BYTE** buffer, INT32* size) +{ + return TPM_ALG_ID_Marshal((TPM_ALG_ID*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES +# endif // ALG_ECC + +// Table 2:74 - Definition of TPMI_ST_COMMAND_TAG Type +TPM_RC +TPMI_ST_COMMAND_TAG_Unmarshal(TPMI_ST_COMMAND_TAG* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = TPM_ST_Unmarshal((TPM_ST*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { + case TPM_ST_NO_SESSIONS: + case TPM_ST_SESSIONS: + break; + default: + result = TPM_RC_BAD_TAG; + break; + } + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_ST_COMMAND_TAG_Marshal(TPMI_ST_COMMAND_TAG* source, BYTE** buffer, INT32* size) +{ + return TPM_ST_Marshal((TPM_ST*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:75 - Definition of TPMI_ALG_MAC_SCHEME Type +TPM_RC +TPMI_ALG_MAC_SCHEME_Unmarshal( + TPMI_ALG_MAC_SCHEME* target, BYTE** buffer, INT32* size, BOOL flag) +{ + TPM_RC result; + result = TPM_ALG_ID_Unmarshal((TPM_ALG_ID*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { +# if ALG_CMAC + case TPM_ALG_CMAC: +# endif // ALG_CMAC +# if ALG_SHA1 + case TPM_ALG_SHA1: +# endif // ALG_SHA1 +# if ALG_SHA256 + case TPM_ALG_SHA256: +# endif // ALG_SHA256 +# if ALG_SHA384 + case TPM_ALG_SHA384: +# endif // ALG_SHA384 +# if ALG_SHA512 + case TPM_ALG_SHA512: +# endif // ALG_SHA512 +# if ALG_SM3_256 + case TPM_ALG_SM3_256: +# endif // ALG_SM3_256 +# if ALG_SHA3_256 + case TPM_ALG_SHA3_256: +# endif // ALG_SHA3_256 +# if ALG_SHA3_384 + case TPM_ALG_SHA3_384: +# endif // ALG_SHA3_384 +# if ALG_SHA3_512 + case TPM_ALG_SHA3_512: +# endif // ALG_SHA3_512 + break; + case TPM_ALG_NULL: + if(!flag) + result = TPM_RC_SYMMETRIC; + break; + default: + result = TPM_RC_SYMMETRIC; + break; + } + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_ALG_MAC_SCHEME_Marshal(TPMI_ALG_MAC_SCHEME* source, BYTE** buffer, INT32* size) +{ + return TPM_ALG_ID_Marshal((TPM_ALG_ID*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:76 - Definition of TPMI_ALG_CIPHER_MODE Type +TPM_RC +TPMI_ALG_CIPHER_MODE_Unmarshal( + TPMI_ALG_CIPHER_MODE* target, BYTE** buffer, INT32* size, BOOL flag) +{ + TPM_RC result; + result = TPM_ALG_ID_Unmarshal((TPM_ALG_ID*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { +# if ALG_CTR + case TPM_ALG_CTR: +# endif // ALG_CTR +# if ALG_OFB + case TPM_ALG_OFB: +# endif // ALG_OFB +# if ALG_CBC + case TPM_ALG_CBC: +# endif // ALG_CBC +# if ALG_CFB + case TPM_ALG_CFB: +# endif // ALG_CFB +# if ALG_ECB + case TPM_ALG_ECB: +# endif // ALG_ECB + break; + case TPM_ALG_NULL: + if(!flag) + result = TPM_RC_MODE; + break; + default: + result = TPM_RC_MODE; + break; + } + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_ALG_CIPHER_MODE_Marshal(TPMI_ALG_CIPHER_MODE* source, BYTE** buffer, INT32* size) +{ + return TPM_ALG_ID_Marshal((TPM_ALG_ID*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:77 - Definition of TPMS_EMPTY Structure +TPM_RC +TPMS_EMPTY_Unmarshal(TPMS_EMPTY* target, BYTE** buffer, INT32* size) +{ + // to prevent the compiler from complaining + NOT_REFERENCED(target); + NOT_REFERENCED(buffer); + NOT_REFERENCED(size); + return TPM_RC_SUCCESS; +} +UINT16 +TPMS_EMPTY_Marshal(TPMS_EMPTY* source, BYTE** buffer, INT32* size) +{ + // to prevent the compiler from complaining + NOT_REFERENCED(source); + NOT_REFERENCED(buffer); + NOT_REFERENCED(size); + return 0; +} + +// Table 2:78 - Definition of TPMS_ALGORITHM_DESCRIPTION Structure +UINT16 +TPMS_ALGORITHM_DESCRIPTION_Marshal( + TPMS_ALGORITHM_DESCRIPTION* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + + TPM_ALG_ID_Marshal((TPM_ALG_ID*)&(source->alg), buffer, size)); + result = (UINT16)(result + + TPMA_ALGORITHM_Marshal( + (TPMA_ALGORITHM*)&(source->attributes), buffer, size)); + return result; +} + +// Table 2:79 - Definition of TPMU_HA Union +TPM_RC +TPMU_HA_Unmarshal(TPMU_HA* target, BYTE** buffer, INT32* size, UINT32 selector) +{ + switch(selector) + { +# if ALG_SHA1 + case TPM_ALG_SHA1: + return BYTE_Array_Unmarshal( + (BYTE*)(target->sha1), buffer, size, (INT32)SHA1_DIGEST_SIZE); +# endif // ALG_SHA1 +# if ALG_SHA256 + case TPM_ALG_SHA256: + return BYTE_Array_Unmarshal( + (BYTE*)(target->sha256), buffer, size, (INT32)SHA256_DIGEST_SIZE); +# endif // ALG_SHA256 +# if ALG_SHA384 + case TPM_ALG_SHA384: + return BYTE_Array_Unmarshal( + (BYTE*)(target->sha384), buffer, size, (INT32)SHA384_DIGEST_SIZE); +# endif // ALG_SHA384 +# if ALG_SHA512 + case TPM_ALG_SHA512: + return BYTE_Array_Unmarshal( + (BYTE*)(target->sha512), buffer, size, (INT32)SHA512_DIGEST_SIZE); +# endif // ALG_SHA512 +# if ALG_SM3_256 + case TPM_ALG_SM3_256: + return BYTE_Array_Unmarshal( + (BYTE*)(target->sm3_256), buffer, size, (INT32)SM3_256_DIGEST_SIZE); +# endif // ALG_SM3_256 +# if ALG_SHA3_256 + case TPM_ALG_SHA3_256: + return BYTE_Array_Unmarshal( + (BYTE*)(target->sha3_256), buffer, size, (INT32)SHA3_256_DIGEST_SIZE); +# endif // ALG_SHA3_256 +# if ALG_SHA3_384 + case TPM_ALG_SHA3_384: + return BYTE_Array_Unmarshal( + (BYTE*)(target->sha3_384), buffer, size, (INT32)SHA3_384_DIGEST_SIZE); +# endif // ALG_SHA3_384 +# if ALG_SHA3_512 + case TPM_ALG_SHA3_512: + return BYTE_Array_Unmarshal( + (BYTE*)(target->sha3_512), buffer, size, (INT32)SHA3_512_DIGEST_SIZE); +# endif // ALG_SHA3_512 + case TPM_ALG_NULL: + return TPM_RC_SUCCESS; + } + return TPM_RC_SELECTOR; +} +UINT16 +TPMU_HA_Marshal(TPMU_HA* source, BYTE** buffer, INT32* size, UINT32 selector) +{ + switch(selector) + { +# if ALG_SHA1 + case TPM_ALG_SHA1: + return BYTE_Array_Marshal( + (BYTE*)(source->sha1), buffer, size, (INT32)SHA1_DIGEST_SIZE); +# endif // ALG_SHA1 +# if ALG_SHA256 + case TPM_ALG_SHA256: + return BYTE_Array_Marshal( + (BYTE*)(source->sha256), buffer, size, (INT32)SHA256_DIGEST_SIZE); +# endif // ALG_SHA256 +# if ALG_SHA384 + case TPM_ALG_SHA384: + return BYTE_Array_Marshal( + (BYTE*)(source->sha384), buffer, size, (INT32)SHA384_DIGEST_SIZE); +# endif // ALG_SHA384 +# if ALG_SHA512 + case TPM_ALG_SHA512: + return BYTE_Array_Marshal( + (BYTE*)(source->sha512), buffer, size, (INT32)SHA512_DIGEST_SIZE); +# endif // ALG_SHA512 +# if ALG_SM3_256 + case TPM_ALG_SM3_256: + return BYTE_Array_Marshal( + (BYTE*)(source->sm3_256), buffer, size, (INT32)SM3_256_DIGEST_SIZE); +# endif // ALG_SM3_256 +# if ALG_SHA3_256 + case TPM_ALG_SHA3_256: + return BYTE_Array_Marshal( + (BYTE*)(source->sha3_256), buffer, size, (INT32)SHA3_256_DIGEST_SIZE); +# endif // ALG_SHA3_256 +# if ALG_SHA3_384 + case TPM_ALG_SHA3_384: + return BYTE_Array_Marshal( + (BYTE*)(source->sha3_384), buffer, size, (INT32)SHA3_384_DIGEST_SIZE); +# endif // ALG_SHA3_384 +# if ALG_SHA3_512 + case TPM_ALG_SHA3_512: + return BYTE_Array_Marshal( + (BYTE*)(source->sha3_512), buffer, size, (INT32)SHA3_512_DIGEST_SIZE); +# endif // ALG_SHA3_512 + case TPM_ALG_NULL: + return 0; + } + return 0; +} + +// Table 2:80 - Definition of TPMT_HA Structure +TPM_RC +TPMT_HA_Unmarshal(TPMT_HA* target, BYTE** buffer, INT32* size, BOOL flag) +{ + TPM_RC result; + result = TPMI_ALG_HASH_Unmarshal( + (TPMI_ALG_HASH*)&(target->hashAlg), buffer, size, flag); + if(result == TPM_RC_SUCCESS) + result = TPMU_HA_Unmarshal( + (TPMU_HA*)&(target->digest), buffer, size, (UINT32)target->hashAlg); + return result; +} +UINT16 +TPMT_HA_Marshal(TPMT_HA* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = (UINT16)(result + + TPMI_ALG_HASH_Marshal( + (TPMI_ALG_HASH*)&(source->hashAlg), buffer, size)); + result = (UINT16)(result + + TPMU_HA_Marshal((TPMU_HA*)&(source->digest), + buffer, + size, + (UINT32)source->hashAlg)); + return result; +} + +// Table 2:81 - Definition of TPM2B_DIGEST Structure +TPM_RC +TPM2B_DIGEST_Unmarshal(TPM2B_DIGEST* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT16_Unmarshal((UINT16*)&(target->t.size), buffer, size); + if(result == TPM_RC_SUCCESS) + { + if((target->t.size) > sizeof(TPMU_HA)) + result = TPM_RC_SIZE; + else + result = BYTE_Array_Unmarshal( + (BYTE*)(target->t.buffer), buffer, size, (INT32)(target->t.size)); + } + return result; +} +UINT16 +TPM2B_DIGEST_Marshal(TPM2B_DIGEST* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT16_Marshal((UINT16*)&(source->t.size), buffer, size)); + // if size equal to 0, the rest of the structure is a zero buffer. Stop processing + if(source->t.size == 0) + return result; + result = (UINT16)(result + + BYTE_Array_Marshal((BYTE*)(source->t.buffer), + buffer, + size, + (INT32)(source->t.size))); + return result; +} + +// Table 2:82 - Definition of TPM2B_DATA Structure +TPM_RC +TPM2B_DATA_Unmarshal(TPM2B_DATA* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT16_Unmarshal((UINT16*)&(target->t.size), buffer, size); + if(result == TPM_RC_SUCCESS) + { + if((target->t.size) > sizeof(TPMT_HA)) + result = TPM_RC_SIZE; + else + result = BYTE_Array_Unmarshal( + (BYTE*)(target->t.buffer), buffer, size, (INT32)(target->t.size)); + } + return result; +} +UINT16 +TPM2B_DATA_Marshal(TPM2B_DATA* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT16_Marshal((UINT16*)&(source->t.size), buffer, size)); + // if size equal to 0, the rest of the structure is a zero buffer. Stop processing + if(source->t.size == 0) + return result; + result = (UINT16)(result + + BYTE_Array_Marshal((BYTE*)(source->t.buffer), + buffer, + size, + (INT32)(source->t.size))); + return result; +} + +// Table 2:83 - Definition of Types for TPM2B_NONCE +# if !USE_MARSHALING_DEFINES +TPM_RC +TPM2B_NONCE_Unmarshal(TPM2B_NONCE* target, BYTE** buffer, INT32* size) +{ + return TPM2B_DIGEST_Unmarshal((TPM2B_DIGEST*)target, buffer, size); +} +UINT16 +TPM2B_NONCE_Marshal(TPM2B_NONCE* source, BYTE** buffer, INT32* size) +{ + return TPM2B_DIGEST_Marshal((TPM2B_DIGEST*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:84 - Definition of Types for TPM2B_AUTH +# if !USE_MARSHALING_DEFINES +TPM_RC +TPM2B_AUTH_Unmarshal(TPM2B_AUTH* target, BYTE** buffer, INT32* size) +{ + return TPM2B_DIGEST_Unmarshal((TPM2B_DIGEST*)target, buffer, size); +} +UINT16 +TPM2B_AUTH_Marshal(TPM2B_AUTH* source, BYTE** buffer, INT32* size) +{ + return TPM2B_DIGEST_Marshal((TPM2B_DIGEST*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:85 - Definition of Types for TPM2B_OPERAND +# if !USE_MARSHALING_DEFINES +TPM_RC +TPM2B_OPERAND_Unmarshal(TPM2B_OPERAND* target, BYTE** buffer, INT32* size) +{ + return TPM2B_DIGEST_Unmarshal((TPM2B_DIGEST*)target, buffer, size); +} +UINT16 +TPM2B_OPERAND_Marshal(TPM2B_OPERAND* source, BYTE** buffer, INT32* size) +{ + return TPM2B_DIGEST_Marshal((TPM2B_DIGEST*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:86 - Definition of TPM2B_EVENT Structure +TPM_RC +TPM2B_EVENT_Unmarshal(TPM2B_EVENT* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT16_Unmarshal((UINT16*)&(target->t.size), buffer, size); + if(result == TPM_RC_SUCCESS) + { + if((target->t.size) > 1024) + result = TPM_RC_SIZE; + else + result = BYTE_Array_Unmarshal( + (BYTE*)(target->t.buffer), buffer, size, (INT32)(target->t.size)); + } + return result; +} +UINT16 +TPM2B_EVENT_Marshal(TPM2B_EVENT* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT16_Marshal((UINT16*)&(source->t.size), buffer, size)); + // if size equal to 0, the rest of the structure is a zero buffer. Stop processing + if(source->t.size == 0) + return result; + result = (UINT16)(result + + BYTE_Array_Marshal((BYTE*)(source->t.buffer), + buffer, + size, + (INT32)(source->t.size))); + return result; +} + +// Table 2:87 - Definition of TPM2B_MAX_BUFFER Structure +TPM_RC +TPM2B_MAX_BUFFER_Unmarshal(TPM2B_MAX_BUFFER* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT16_Unmarshal((UINT16*)&(target->t.size), buffer, size); + if(result == TPM_RC_SUCCESS) + { + if((target->t.size) > MAX_DIGEST_BUFFER) + result = TPM_RC_SIZE; + else + result = BYTE_Array_Unmarshal( + (BYTE*)(target->t.buffer), buffer, size, (INT32)(target->t.size)); + } + return result; +} +UINT16 +TPM2B_MAX_BUFFER_Marshal(TPM2B_MAX_BUFFER* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT16_Marshal((UINT16*)&(source->t.size), buffer, size)); + // if size equal to 0, the rest of the structure is a zero buffer. Stop processing + if(source->t.size == 0) + return result; + result = (UINT16)(result + + BYTE_Array_Marshal((BYTE*)(source->t.buffer), + buffer, + size, + (INT32)(source->t.size))); + return result; +} + +// Table 2:88 - Definition of TPM2B_MAX_NV_BUFFER Structure +TPM_RC +TPM2B_MAX_NV_BUFFER_Unmarshal(TPM2B_MAX_NV_BUFFER* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT16_Unmarshal((UINT16*)&(target->t.size), buffer, size); + if(result == TPM_RC_SUCCESS) + { + if((target->t.size) > MAX_NV_BUFFER_SIZE) + result = TPM_RC_SIZE; + else + result = BYTE_Array_Unmarshal( + (BYTE*)(target->t.buffer), buffer, size, (INT32)(target->t.size)); + } + return result; +} +UINT16 +TPM2B_MAX_NV_BUFFER_Marshal(TPM2B_MAX_NV_BUFFER* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT16_Marshal((UINT16*)&(source->t.size), buffer, size)); + // if size equal to 0, the rest of the structure is a zero buffer. Stop processing + if(source->t.size == 0) + return result; + result = (UINT16)(result + + BYTE_Array_Marshal((BYTE*)(source->t.buffer), + buffer, + size, + (INT32)(source->t.size))); + return result; +} + +// Table 2:89 - Definition of TPM2B_TIMEOUT Structure +TPM_RC +TPM2B_TIMEOUT_Unmarshal(TPM2B_TIMEOUT* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT16_Unmarshal((UINT16*)&(target->t.size), buffer, size); + if(result == TPM_RC_SUCCESS) + { + if((target->t.size) > sizeof(UINT64)) + result = TPM_RC_SIZE; + else + result = BYTE_Array_Unmarshal( + (BYTE*)(target->t.buffer), buffer, size, (INT32)(target->t.size)); + } + return result; +} +UINT16 +TPM2B_TIMEOUT_Marshal(TPM2B_TIMEOUT* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT16_Marshal((UINT16*)&(source->t.size), buffer, size)); + // if size equal to 0, the rest of the structure is a zero buffer. Stop processing + if(source->t.size == 0) + return result; + result = (UINT16)(result + + BYTE_Array_Marshal((BYTE*)(source->t.buffer), + buffer, + size, + (INT32)(source->t.size))); + return result; +} + +// Table 2:90 - Definition of TPM2B_IV Structure +TPM_RC +TPM2B_IV_Unmarshal(TPM2B_IV* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT16_Unmarshal((UINT16*)&(target->t.size), buffer, size); + if(result == TPM_RC_SUCCESS) + { + if((target->t.size) > MAX_SYM_BLOCK_SIZE) + result = TPM_RC_SIZE; + else + result = BYTE_Array_Unmarshal( + (BYTE*)(target->t.buffer), buffer, size, (INT32)(target->t.size)); + } + return result; +} +UINT16 +TPM2B_IV_Marshal(TPM2B_IV* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT16_Marshal((UINT16*)&(source->t.size), buffer, size)); + // if size equal to 0, the rest of the structure is a zero buffer. Stop processing + if(source->t.size == 0) + return result; + result = (UINT16)(result + + BYTE_Array_Marshal((BYTE*)(source->t.buffer), + buffer, + size, + (INT32)(source->t.size))); + return result; +} + +// Table 2:91 - Definition of TPMU_NAME Union +// Table 2:92 - Definition of TPM2B_NAME Structure +TPM_RC +TPM2B_NAME_Unmarshal(TPM2B_NAME* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT16_Unmarshal((UINT16*)&(target->t.size), buffer, size); + if(result == TPM_RC_SUCCESS) + { + if((target->t.size) > sizeof(TPMU_NAME)) + result = TPM_RC_SIZE; + else + result = BYTE_Array_Unmarshal( + (BYTE*)(target->t.name), buffer, size, (INT32)(target->t.size)); + } + return result; +} +UINT16 +TPM2B_NAME_Marshal(TPM2B_NAME* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT16_Marshal((UINT16*)&(source->t.size), buffer, size)); + // if size equal to 0, the rest of the structure is a zero buffer. Stop processing + if(source->t.size == 0) + return result; + result = + (UINT16)(result + + BYTE_Array_Marshal( + (BYTE*)(source->t.name), buffer, size, (INT32)(source->t.size))); + return result; +} + +// Table 2:93 - Definition of TPMS_PCR_SELECT Structure +TPM_RC +TPMS_PCR_SELECT_Unmarshal(TPMS_PCR_SELECT* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT8_Unmarshal((UINT8*)&(target->sizeofSelect), buffer, size); + if((result == TPM_RC_SUCCESS) && (target->sizeofSelect < PCR_SELECT_MIN)) + result = TPM_RC_VALUE; + if(result == TPM_RC_SUCCESS) + { + if((target->sizeofSelect) > PCR_SELECT_MAX) + result = TPM_RC_VALUE; + else + result = BYTE_Array_Unmarshal((BYTE*)(target->pcrSelect), + buffer, + size, + (INT32)(target->sizeofSelect)); + } + return result; +} +UINT16 +TPMS_PCR_SELECT_Marshal(TPMS_PCR_SELECT* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = (UINT16)(result + + UINT8_Marshal((UINT8*)&(source->sizeofSelect), buffer, size)); + result = (UINT16)(result + + BYTE_Array_Marshal((BYTE*)(source->pcrSelect), + buffer, + size, + (INT32)(source->sizeofSelect))); + return result; +} + +// Table 2:94 - Definition of TPMS_PCR_SELECTION Structure +TPM_RC +TPMS_PCR_SELECTION_Unmarshal(TPMS_PCR_SELECTION* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = + TPMI_ALG_HASH_Unmarshal((TPMI_ALG_HASH*)&(target->hash), buffer, size, 0); + if(result == TPM_RC_SUCCESS) + result = UINT8_Unmarshal((UINT8*)&(target->sizeofSelect), buffer, size); + if((result == TPM_RC_SUCCESS) && (target->sizeofSelect < PCR_SELECT_MIN)) + result = TPM_RC_VALUE; + if(result == TPM_RC_SUCCESS) + { + if((target->sizeofSelect) > PCR_SELECT_MAX) + result = TPM_RC_VALUE; + else + result = BYTE_Array_Unmarshal((BYTE*)(target->pcrSelect), + buffer, + size, + (INT32)(target->sizeofSelect)); + } + return result; +} +UINT16 +TPMS_PCR_SELECTION_Marshal(TPMS_PCR_SELECTION* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = (UINT16)(result + + TPMI_ALG_HASH_Marshal( + (TPMI_ALG_HASH*)&(source->hash), buffer, size)); + result = (UINT16)(result + + UINT8_Marshal((UINT8*)&(source->sizeofSelect), buffer, size)); + result = (UINT16)(result + + BYTE_Array_Marshal((BYTE*)(source->pcrSelect), + buffer, + size, + (INT32)(source->sizeofSelect))); + return result; +} + +// Table 2:97 - Definition of TPMT_TK_CREATION Structure +TPM_RC +TPMT_TK_CREATION_Unmarshal(TPMT_TK_CREATION* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = TPM_ST_Unmarshal((TPM_ST*)&(target->tag), buffer, size); + if((result == TPM_RC_SUCCESS) && (target->tag != TPM_ST_CREATION)) + result = TPM_RC_TAG; + if(result == TPM_RC_SUCCESS) + result = TPMI_RH_HIERARCHY_Unmarshal( + (TPMI_RH_HIERARCHY*)&(target->hierarchy), buffer, size, 1); + if(result == TPM_RC_SUCCESS) + result = + TPM2B_DIGEST_Unmarshal((TPM2B_DIGEST*)&(target->digest), buffer, size); + return result; +} +UINT16 +TPMT_TK_CREATION_Marshal(TPMT_TK_CREATION* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = (UINT16)(result + TPM_ST_Marshal((TPM_ST*)&(source->tag), buffer, size)); + result = (UINT16)(result + + TPMI_RH_HIERARCHY_Marshal( + (TPMI_RH_HIERARCHY*)&(source->hierarchy), buffer, size)); + result = (UINT16)(result + + TPM2B_DIGEST_Marshal( + (TPM2B_DIGEST*)&(source->digest), buffer, size)); + return result; +} + +// Table 2:98 - Definition of TPMT_TK_VERIFIED Structure +TPM_RC +TPMT_TK_VERIFIED_Unmarshal(TPMT_TK_VERIFIED* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = TPM_ST_Unmarshal((TPM_ST*)&(target->tag), buffer, size); + if((result == TPM_RC_SUCCESS) && (target->tag != TPM_ST_VERIFIED)) + result = TPM_RC_TAG; + if(result == TPM_RC_SUCCESS) + result = TPMI_RH_HIERARCHY_Unmarshal( + (TPMI_RH_HIERARCHY*)&(target->hierarchy), buffer, size, 1); + if(result == TPM_RC_SUCCESS) + result = + TPM2B_DIGEST_Unmarshal((TPM2B_DIGEST*)&(target->digest), buffer, size); + return result; +} +UINT16 +TPMT_TK_VERIFIED_Marshal(TPMT_TK_VERIFIED* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = (UINT16)(result + TPM_ST_Marshal((TPM_ST*)&(source->tag), buffer, size)); + result = (UINT16)(result + + TPMI_RH_HIERARCHY_Marshal( + (TPMI_RH_HIERARCHY*)&(source->hierarchy), buffer, size)); + result = (UINT16)(result + + TPM2B_DIGEST_Marshal( + (TPM2B_DIGEST*)&(source->digest), buffer, size)); + return result; +} + +// Table 2:99 - Definition of TPMT_TK_AUTH Structure +TPM_RC +TPMT_TK_AUTH_Unmarshal(TPMT_TK_AUTH* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = TPM_ST_Unmarshal((TPM_ST*)&(target->tag), buffer, size); + if((result == TPM_RC_SUCCESS) && (target->tag != TPM_ST_AUTH_SIGNED) + && (target->tag != TPM_ST_AUTH_SECRET)) + result = TPM_RC_TAG; + if(result == TPM_RC_SUCCESS) + result = TPMI_RH_HIERARCHY_Unmarshal( + (TPMI_RH_HIERARCHY*)&(target->hierarchy), buffer, size, 1); + if(result == TPM_RC_SUCCESS) + result = + TPM2B_DIGEST_Unmarshal((TPM2B_DIGEST*)&(target->digest), buffer, size); + return result; +} +UINT16 +TPMT_TK_AUTH_Marshal(TPMT_TK_AUTH* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = (UINT16)(result + TPM_ST_Marshal((TPM_ST*)&(source->tag), buffer, size)); + result = (UINT16)(result + + TPMI_RH_HIERARCHY_Marshal( + (TPMI_RH_HIERARCHY*)&(source->hierarchy), buffer, size)); + result = (UINT16)(result + + TPM2B_DIGEST_Marshal( + (TPM2B_DIGEST*)&(source->digest), buffer, size)); + return result; +} + +// Table 2:100 - Definition of TPMT_TK_HASHCHECK Structure +TPM_RC +TPMT_TK_HASHCHECK_Unmarshal(TPMT_TK_HASHCHECK* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = TPM_ST_Unmarshal((TPM_ST*)&(target->tag), buffer, size); + if((result == TPM_RC_SUCCESS) && (target->tag != TPM_ST_HASHCHECK)) + result = TPM_RC_TAG; + if(result == TPM_RC_SUCCESS) + result = TPMI_RH_HIERARCHY_Unmarshal( + (TPMI_RH_HIERARCHY*)&(target->hierarchy), buffer, size, 1); + if(result == TPM_RC_SUCCESS) + result = + TPM2B_DIGEST_Unmarshal((TPM2B_DIGEST*)&(target->digest), buffer, size); + return result; +} +UINT16 +TPMT_TK_HASHCHECK_Marshal(TPMT_TK_HASHCHECK* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = (UINT16)(result + TPM_ST_Marshal((TPM_ST*)&(source->tag), buffer, size)); + result = (UINT16)(result + + TPMI_RH_HIERARCHY_Marshal( + (TPMI_RH_HIERARCHY*)&(source->hierarchy), buffer, size)); + result = (UINT16)(result + + TPM2B_DIGEST_Marshal( + (TPM2B_DIGEST*)&(source->digest), buffer, size)); + return result; +} + +// Table 2:101 - Definition of TPMS_ALG_PROPERTY Structure +UINT16 +TPMS_ALG_PROPERTY_Marshal(TPMS_ALG_PROPERTY* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + + TPM_ALG_ID_Marshal((TPM_ALG_ID*)&(source->alg), buffer, size)); + result = (UINT16)(result + + TPMA_ALGORITHM_Marshal( + (TPMA_ALGORITHM*)&(source->algProperties), buffer, size)); + return result; +} + +// Table 2:102 - Definition of TPMS_TAGGED_PROPERTY Structure +UINT16 +TPMS_TAGGED_PROPERTY_Marshal(TPMS_TAGGED_PROPERTY* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + TPM_PT_Marshal((TPM_PT*)&(source->property), buffer, size)); + result = + (UINT16)(result + UINT32_Marshal((UINT32*)&(source->value), buffer, size)); + return result; +} + +// Table 2:103 - Definition of TPMS_TAGGED_PCR_SELECT Structure +UINT16 +TPMS_TAGGED_PCR_SELECT_Marshal( + TPMS_TAGGED_PCR_SELECT* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + + TPM_PT_PCR_Marshal((TPM_PT_PCR*)&(source->tag), buffer, size)); + result = (UINT16)(result + + UINT8_Marshal((UINT8*)&(source->sizeofSelect), buffer, size)); + result = (UINT16)(result + + BYTE_Array_Marshal((BYTE*)(source->pcrSelect), + buffer, + size, + (INT32)(source->sizeofSelect))); + return result; +} + +// Table 2:104 - Definition of TPMS_TAGGED_POLICY Structure +UINT16 +TPMS_TAGGED_POLICY_Marshal(TPMS_TAGGED_POLICY* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + + TPM_HANDLE_Marshal((TPM_HANDLE*)&(source->handle), buffer, size)); + result = + (UINT16)(result + + TPMT_HA_Marshal((TPMT_HA*)&(source->policyHash), buffer, size)); + return result; +} + +// Table 2:105 - Definition of TPMS_ACT_DATA Structure +UINT16 +TPMS_ACT_DATA_Marshal(TPMS_ACT_DATA* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + + TPM_HANDLE_Marshal((TPM_HANDLE*)&(source->handle), buffer, size)); + result = + (UINT16)(result + UINT32_Marshal((UINT32*)&(source->timeout), buffer, size)); + result = + (UINT16)(result + + TPMA_ACT_Marshal((TPMA_ACT*)&(source->attributes), buffer, size)); + return result; +} + +// Table 2:106 - Definition of TPML_CC Structure +TPM_RC +TPML_CC_Unmarshal(TPML_CC* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT32_Unmarshal((UINT32*)&(target->count), buffer, size); + if(result == TPM_RC_SUCCESS) + { + if((target->count) > MAX_CAP_CC) + result = TPM_RC_SIZE; + else + result = TPM_CC_Array_Unmarshal((TPM_CC*)(target->commandCodes), + buffer, + size, + (INT32)(target->count)); + } + return result; +} +UINT16 +TPML_CC_Marshal(TPML_CC* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT32_Marshal((UINT32*)&(source->count), buffer, size)); + result = (UINT16)(result + + TPM_CC_Array_Marshal((TPM_CC*)(source->commandCodes), + buffer, + size, + (INT32)(source->count))); + return result; +} + +// Table 2:107 - Definition of TPML_CCA Structure +UINT16 +TPML_CCA_Marshal(TPML_CCA* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT32_Marshal((UINT32*)&(source->count), buffer, size)); + result = (UINT16)(result + + TPMA_CC_Array_Marshal((TPMA_CC*)(source->commandAttributes), + buffer, + size, + (INT32)(source->count))); + return result; +} + +// Table 2:108 - Definition of TPML_ALG Structure +TPM_RC +TPML_ALG_Unmarshal(TPML_ALG* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT32_Unmarshal((UINT32*)&(target->count), buffer, size); + if(result == TPM_RC_SUCCESS) + { + if((target->count) > MAX_ALG_LIST_SIZE) + result = TPM_RC_SIZE; + else + result = TPM_ALG_ID_Array_Unmarshal((TPM_ALG_ID*)(target->algorithms), + buffer, + size, + (INT32)(target->count)); + } + return result; +} +UINT16 +TPML_ALG_Marshal(TPML_ALG* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT32_Marshal((UINT32*)&(source->count), buffer, size)); + result = (UINT16)(result + + TPM_ALG_ID_Array_Marshal((TPM_ALG_ID*)(source->algorithms), + buffer, + size, + (INT32)(source->count))); + return result; +} + +// Table 2:109 - Definition of TPML_HANDLE Structure +UINT16 +TPML_HANDLE_Marshal(TPML_HANDLE* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT32_Marshal((UINT32*)&(source->count), buffer, size)); + result = (UINT16)(result + + TPM_HANDLE_Array_Marshal((TPM_HANDLE*)(source->handle), + buffer, + size, + (INT32)(source->count))); + return result; +} + +// Table 2:110 - Definition of TPML_DIGEST Structure +TPM_RC +TPML_DIGEST_Unmarshal(TPML_DIGEST* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT32_Unmarshal((UINT32*)&(target->count), buffer, size); + if((result == TPM_RC_SUCCESS) && (target->count < 2)) + result = TPM_RC_SIZE; + if(result == TPM_RC_SUCCESS) + { + if((target->count) > 8) + result = TPM_RC_SIZE; + else + result = TPM2B_DIGEST_Array_Unmarshal((TPM2B_DIGEST*)(target->digests), + buffer, + size, + (INT32)(target->count)); + } + return result; +} +UINT16 +TPML_DIGEST_Marshal(TPML_DIGEST* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT32_Marshal((UINT32*)&(source->count), buffer, size)); + result = (UINT16)(result + + TPM2B_DIGEST_Array_Marshal((TPM2B_DIGEST*)(source->digests), + buffer, + size, + (INT32)(source->count))); + return result; +} + +// Table 2:111 - Definition of TPML_DIGEST_VALUES Structure +TPM_RC +TPML_DIGEST_VALUES_Unmarshal(TPML_DIGEST_VALUES* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT32_Unmarshal((UINT32*)&(target->count), buffer, size); + if(result == TPM_RC_SUCCESS) + { + if((target->count) > HASH_COUNT) + result = TPM_RC_SIZE; + else + result = TPMT_HA_Array_Unmarshal( + (TPMT_HA*)(target->digests), buffer, size, 0, (INT32)(target->count)); + } + return result; +} +UINT16 +TPML_DIGEST_VALUES_Marshal(TPML_DIGEST_VALUES* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT32_Marshal((UINT32*)&(source->count), buffer, size)); + result = (UINT16)(result + + TPMT_HA_Array_Marshal((TPMT_HA*)(source->digests), + buffer, + size, + (INT32)(source->count))); + return result; +} + +// Table 2:112 - Definition of TPML_PCR_SELECTION Structure +TPM_RC +TPML_PCR_SELECTION_Unmarshal(TPML_PCR_SELECTION* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT32_Unmarshal((UINT32*)&(target->count), buffer, size); + if(result == TPM_RC_SUCCESS) + { + if((target->count) > HASH_COUNT) + result = TPM_RC_SIZE; + else + result = TPMS_PCR_SELECTION_Array_Unmarshal( + (TPMS_PCR_SELECTION*)(target->pcrSelections), + buffer, + size, + (INT32)(target->count)); + } + return result; +} +UINT16 +TPML_PCR_SELECTION_Marshal(TPML_PCR_SELECTION* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT32_Marshal((UINT32*)&(source->count), buffer, size)); + result = (UINT16)(result + + TPMS_PCR_SELECTION_Array_Marshal( + (TPMS_PCR_SELECTION*)(source->pcrSelections), + buffer, + size, + (INT32)(source->count))); + return result; +} + +// Table 2:113 - Definition of TPML_ALG_PROPERTY Structure +UINT16 +TPML_ALG_PROPERTY_Marshal(TPML_ALG_PROPERTY* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT32_Marshal((UINT32*)&(source->count), buffer, size)); + result = (UINT16)(result + + TPMS_ALG_PROPERTY_Array_Marshal( + (TPMS_ALG_PROPERTY*)(source->algProperties), + buffer, + size, + (INT32)(source->count))); + return result; +} + +// Table 2:114 - Definition of TPML_TAGGED_TPM_PROPERTY Structure +UINT16 +TPML_TAGGED_TPM_PROPERTY_Marshal( + TPML_TAGGED_TPM_PROPERTY* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT32_Marshal((UINT32*)&(source->count), buffer, size)); + result = (UINT16)(result + + TPMS_TAGGED_PROPERTY_Array_Marshal( + (TPMS_TAGGED_PROPERTY*)(source->tpmProperty), + buffer, + size, + (INT32)(source->count))); + return result; +} + +// Table 2:115 - Definition of TPML_TAGGED_PCR_PROPERTY Structure +UINT16 +TPML_TAGGED_PCR_PROPERTY_Marshal( + TPML_TAGGED_PCR_PROPERTY* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT32_Marshal((UINT32*)&(source->count), buffer, size)); + result = (UINT16)(result + + TPMS_TAGGED_PCR_SELECT_Array_Marshal( + (TPMS_TAGGED_PCR_SELECT*)(source->pcrProperty), + buffer, + size, + (INT32)(source->count))); + return result; +} + +// Table 2:116 - Definition of TPML_ECC_CURVE Structure +# if ALG_ECC +UINT16 +TPML_ECC_CURVE_Marshal(TPML_ECC_CURVE* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT32_Marshal((UINT32*)&(source->count), buffer, size)); + result = + (UINT16)(result + + TPM_ECC_CURVE_Array_Marshal((TPM_ECC_CURVE*)(source->eccCurves), + buffer, + size, + (INT32)(source->count))); + return result; +} +# endif // ALG_ECC + +// Table 2:117 - Definition of TPML_TAGGED_POLICY Structure +UINT16 +TPML_TAGGED_POLICY_Marshal(TPML_TAGGED_POLICY* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT32_Marshal((UINT32*)&(source->count), buffer, size)); + result = (UINT16)(result + + TPMS_TAGGED_POLICY_Array_Marshal( + (TPMS_TAGGED_POLICY*)(source->policies), + buffer, + size, + (INT32)(source->count))); + return result; +} + +// Table 2:118 - Definition of TPML_ACT_DATA Structure +UINT16 +TPML_ACT_DATA_Marshal(TPML_ACT_DATA* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT32_Marshal((UINT32*)&(source->count), buffer, size)); + result = (UINT16)(result + + TPMS_ACT_DATA_Array_Marshal((TPMS_ACT_DATA*)(source->actData), + buffer, + size, + (INT32)(source->count))); + return result; +} + +// Table 2:119 - Definition of TPMU_CAPABILITIES Union +UINT16 +TPMU_CAPABILITIES_Marshal( + TPMU_CAPABILITIES* source, BYTE** buffer, INT32* size, UINT32 selector) +{ + switch(selector) + { + case TPM_CAP_ALGS: + return TPML_ALG_PROPERTY_Marshal( + (TPML_ALG_PROPERTY*)&(source->algorithms), buffer, size); + case TPM_CAP_HANDLES: + return TPML_HANDLE_Marshal( + (TPML_HANDLE*)&(source->handles), buffer, size); + case TPM_CAP_COMMANDS: + return TPML_CCA_Marshal((TPML_CCA*)&(source->command), buffer, size); + case TPM_CAP_PP_COMMANDS: + return TPML_CC_Marshal((TPML_CC*)&(source->ppCommands), buffer, size); + case TPM_CAP_AUDIT_COMMANDS: + return TPML_CC_Marshal((TPML_CC*)&(source->auditCommands), buffer, size); + case TPM_CAP_PCRS: + return TPML_PCR_SELECTION_Marshal( + (TPML_PCR_SELECTION*)&(source->assignedPCR), buffer, size); + case TPM_CAP_TPM_PROPERTIES: + return TPML_TAGGED_TPM_PROPERTY_Marshal( + (TPML_TAGGED_TPM_PROPERTY*)&(source->tpmProperties), buffer, size); + case TPM_CAP_PCR_PROPERTIES: + return TPML_TAGGED_PCR_PROPERTY_Marshal( + (TPML_TAGGED_PCR_PROPERTY*)&(source->pcrProperties), buffer, size); +# if ALG_ECC + case TPM_CAP_ECC_CURVES: + return TPML_ECC_CURVE_Marshal( + (TPML_ECC_CURVE*)&(source->eccCurves), buffer, size); +# endif // ALG_ECC + case TPM_CAP_AUTH_POLICIES: + return TPML_TAGGED_POLICY_Marshal( + (TPML_TAGGED_POLICY*)&(source->authPolicies), buffer, size); + case TPM_CAP_ACT: + return TPML_ACT_DATA_Marshal( + (TPML_ACT_DATA*)&(source->actData), buffer, size); + } + return 0; +} + +// Table 2:120 - Definition of TPMS_CAPABILITY_DATA Structure +UINT16 +TPMS_CAPABILITY_DATA_Marshal(TPMS_CAPABILITY_DATA* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + + TPM_CAP_Marshal((TPM_CAP*)&(source->capability), buffer, size)); + result = (UINT16)(result + + TPMU_CAPABILITIES_Marshal((TPMU_CAPABILITIES*)&(source->data), + buffer, + size, + (UINT32)source->capability)); + return result; +} + +// Table 2:121 - Definition of TPMS_CLOCK_INFO Structure +TPM_RC +TPMS_CLOCK_INFO_Unmarshal(TPMS_CLOCK_INFO* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT64_Unmarshal((UINT64*)&(target->clock), buffer, size); + if(result == TPM_RC_SUCCESS) + result = UINT32_Unmarshal((UINT32*)&(target->resetCount), buffer, size); + if(result == TPM_RC_SUCCESS) + result = UINT32_Unmarshal((UINT32*)&(target->restartCount), buffer, size); + if(result == TPM_RC_SUCCESS) + result = TPMI_YES_NO_Unmarshal((TPMI_YES_NO*)&(target->safe), buffer, size); + return result; +} +UINT16 +TPMS_CLOCK_INFO_Marshal(TPMS_CLOCK_INFO* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT64_Marshal((UINT64*)&(source->clock), buffer, size)); + result = (UINT16)(result + + UINT32_Marshal((UINT32*)&(source->resetCount), buffer, size)); + result = + (UINT16)(result + + UINT32_Marshal((UINT32*)&(source->restartCount), buffer, size)); + result = + (UINT16)(result + + TPMI_YES_NO_Marshal((TPMI_YES_NO*)&(source->safe), buffer, size)); + return result; +} + +// Table 2:122 - Definition of TPMS_TIME_INFO Structure +TPM_RC +TPMS_TIME_INFO_Unmarshal(TPMS_TIME_INFO* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT64_Unmarshal((UINT64*)&(target->time), buffer, size); + if(result == TPM_RC_SUCCESS) + result = TPMS_CLOCK_INFO_Unmarshal( + (TPMS_CLOCK_INFO*)&(target->clockInfo), buffer, size); + return result; +} +UINT16 +TPMS_TIME_INFO_Marshal(TPMS_TIME_INFO* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT64_Marshal((UINT64*)&(source->time), buffer, size)); + result = (UINT16)(result + + TPMS_CLOCK_INFO_Marshal( + (TPMS_CLOCK_INFO*)&(source->clockInfo), buffer, size)); + return result; +} + +// Table 2:123 - Definition of TPMS_TIME_ATTEST_INFO Structure +UINT16 +TPMS_TIME_ATTEST_INFO_Marshal( + TPMS_TIME_ATTEST_INFO* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = (UINT16)(result + + TPMS_TIME_INFO_Marshal( + (TPMS_TIME_INFO*)&(source->time), buffer, size)); + result = + (UINT16)(result + + UINT64_Marshal((UINT64*)&(source->firmwareVersion), buffer, size)); + return result; +} + +// Table 2:124 - Definition of TPMS_CERTIFY_INFO Structure +UINT16 +TPMS_CERTIFY_INFO_Marshal(TPMS_CERTIFY_INFO* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + + TPM2B_NAME_Marshal((TPM2B_NAME*)&(source->name), buffer, size)); + result = (UINT16)(result + + TPM2B_NAME_Marshal( + (TPM2B_NAME*)&(source->qualifiedName), buffer, size)); + return result; +} + +// Table 2:125 - Definition of TPMS_QUOTE_INFO Structure +UINT16 +TPMS_QUOTE_INFO_Marshal(TPMS_QUOTE_INFO* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = (UINT16)(result + + TPML_PCR_SELECTION_Marshal( + (TPML_PCR_SELECTION*)&(source->pcrSelect), buffer, size)); + result = (UINT16)(result + + TPM2B_DIGEST_Marshal( + (TPM2B_DIGEST*)&(source->pcrDigest), buffer, size)); + return result; +} + +// Table 2:126 - Definition of TPMS_COMMAND_AUDIT_INFO Structure +UINT16 +TPMS_COMMAND_AUDIT_INFO_Marshal( + TPMS_COMMAND_AUDIT_INFO* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + + UINT64_Marshal((UINT64*)&(source->auditCounter), buffer, size)); + result = (UINT16)(result + + TPM_ALG_ID_Marshal( + (TPM_ALG_ID*)&(source->digestAlg), buffer, size)); + result = (UINT16)(result + + TPM2B_DIGEST_Marshal( + (TPM2B_DIGEST*)&(source->auditDigest), buffer, size)); + result = (UINT16)(result + + TPM2B_DIGEST_Marshal( + (TPM2B_DIGEST*)&(source->commandDigest), buffer, size)); + return result; +} + +// Table 2:127 - Definition of TPMS_SESSION_AUDIT_INFO Structure +UINT16 +TPMS_SESSION_AUDIT_INFO_Marshal( + TPMS_SESSION_AUDIT_INFO* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = (UINT16)(result + + TPMI_YES_NO_Marshal( + (TPMI_YES_NO*)&(source->exclusiveSession), buffer, size)); + result = (UINT16)(result + + TPM2B_DIGEST_Marshal( + (TPM2B_DIGEST*)&(source->sessionDigest), buffer, size)); + return result; +} + +// Table 2:128 - Definition of TPMS_CREATION_INFO Structure +UINT16 +TPMS_CREATION_INFO_Marshal(TPMS_CREATION_INFO* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = (UINT16)(result + + TPM2B_NAME_Marshal( + (TPM2B_NAME*)&(source->objectName), buffer, size)); + result = (UINT16)(result + + TPM2B_DIGEST_Marshal( + (TPM2B_DIGEST*)&(source->creationHash), buffer, size)); + return result; +} + +// Table 2:129 - Definition of TPMS_NV_CERTIFY_INFO Structure +UINT16 +TPMS_NV_CERTIFY_INFO_Marshal(TPMS_NV_CERTIFY_INFO* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = (UINT16)(result + + TPM2B_NAME_Marshal( + (TPM2B_NAME*)&(source->indexName), buffer, size)); + result = + (UINT16)(result + UINT16_Marshal((UINT16*)&(source->offset), buffer, size)); + result = (UINT16)(result + + TPM2B_MAX_NV_BUFFER_Marshal( + (TPM2B_MAX_NV_BUFFER*)&(source->nvContents), buffer, size)); + return result; +} + +// Table 2:130 - Definition of TPMS_NV_DIGEST_CERTIFY_INFO Structure +UINT16 +TPMS_NV_DIGEST_CERTIFY_INFO_Marshal( + TPMS_NV_DIGEST_CERTIFY_INFO* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = (UINT16)(result + + TPM2B_NAME_Marshal( + (TPM2B_NAME*)&(source->indexName), buffer, size)); + result = (UINT16)(result + + TPM2B_DIGEST_Marshal( + (TPM2B_DIGEST*)&(source->nvDigest), buffer, size)); + return result; +} + +// Table 2:131 - Definition of TPMI_ST_ATTEST Type +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_ST_ATTEST_Marshal(TPMI_ST_ATTEST* source, BYTE** buffer, INT32* size) +{ + return TPM_ST_Marshal((TPM_ST*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:132 - Definition of TPMU_ATTEST Union +UINT16 +TPMU_ATTEST_Marshal(TPMU_ATTEST* source, BYTE** buffer, INT32* size, UINT32 selector) +{ + switch(selector) + { + case TPM_ST_ATTEST_CERTIFY: + return TPMS_CERTIFY_INFO_Marshal( + (TPMS_CERTIFY_INFO*)&(source->certify), buffer, size); + case TPM_ST_ATTEST_CREATION: + return TPMS_CREATION_INFO_Marshal( + (TPMS_CREATION_INFO*)&(source->creation), buffer, size); + case TPM_ST_ATTEST_QUOTE: + return TPMS_QUOTE_INFO_Marshal( + (TPMS_QUOTE_INFO*)&(source->quote), buffer, size); + case TPM_ST_ATTEST_COMMAND_AUDIT: + return TPMS_COMMAND_AUDIT_INFO_Marshal( + (TPMS_COMMAND_AUDIT_INFO*)&(source->commandAudit), buffer, size); + case TPM_ST_ATTEST_SESSION_AUDIT: + return TPMS_SESSION_AUDIT_INFO_Marshal( + (TPMS_SESSION_AUDIT_INFO*)&(source->sessionAudit), buffer, size); + case TPM_ST_ATTEST_TIME: + return TPMS_TIME_ATTEST_INFO_Marshal( + (TPMS_TIME_ATTEST_INFO*)&(source->time), buffer, size); + case TPM_ST_ATTEST_NV: + return TPMS_NV_CERTIFY_INFO_Marshal( + (TPMS_NV_CERTIFY_INFO*)&(source->nv), buffer, size); + case TPM_ST_ATTEST_NV_DIGEST: + return TPMS_NV_DIGEST_CERTIFY_INFO_Marshal( + (TPMS_NV_DIGEST_CERTIFY_INFO*)&(source->nvDigest), buffer, size); + } + return 0; +} + +// Table 2:133 - Definition of TPMS_ATTEST Structure +UINT16 +TPMS_ATTEST_Marshal(TPMS_ATTEST* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = (UINT16)(result + + TPM_CONSTANTS32_Marshal( + (TPM_CONSTANTS32*)&(source->magic), buffer, size)); + result = (UINT16)(result + + TPMI_ST_ATTEST_Marshal( + (TPMI_ST_ATTEST*)&(source->type), buffer, size)); + result = (UINT16)(result + + TPM2B_NAME_Marshal( + (TPM2B_NAME*)&(source->qualifiedSigner), buffer, size)); + result = (UINT16)(result + + TPM2B_DATA_Marshal( + (TPM2B_DATA*)&(source->extraData), buffer, size)); + result = (UINT16)(result + + TPMS_CLOCK_INFO_Marshal( + (TPMS_CLOCK_INFO*)&(source->clockInfo), buffer, size)); + result = + (UINT16)(result + + UINT64_Marshal((UINT64*)&(source->firmwareVersion), buffer, size)); + result = (UINT16)(result + + TPMU_ATTEST_Marshal((TPMU_ATTEST*)&(source->attested), + buffer, + size, + (UINT32)source->type)); + return result; +} + +// Table 2:134 - Definition of TPM2B_ATTEST Structure +UINT16 +TPM2B_ATTEST_Marshal(TPM2B_ATTEST* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT16_Marshal((UINT16*)&(source->t.size), buffer, size)); + // if size equal to 0, the rest of the structure is a zero buffer. Stop processing + if(source->t.size == 0) + return result; + result = (UINT16)(result + + BYTE_Array_Marshal((BYTE*)(source->t.attestationData), + buffer, + size, + (INT32)(source->t.size))); + return result; +} + +// Table 2:135 - Definition of TPMS_AUTH_COMMAND Structure +TPM_RC +TPMS_AUTH_COMMAND_Unmarshal(TPMS_AUTH_COMMAND* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = TPMI_SH_AUTH_SESSION_Unmarshal( + (TPMI_SH_AUTH_SESSION*)&(target->sessionHandle), buffer, size, 1); + if(result == TPM_RC_SUCCESS) + result = TPM2B_NONCE_Unmarshal((TPM2B_NONCE*)&(target->nonce), buffer, size); + if(result == TPM_RC_SUCCESS) + result = TPMA_SESSION_Unmarshal( + (TPMA_SESSION*)&(target->sessionAttributes), buffer, size); + if(result == TPM_RC_SUCCESS) + result = TPM2B_AUTH_Unmarshal((TPM2B_AUTH*)&(target->hmac), buffer, size); + return result; +} + +// Table 2:136 - Definition of TPMS_AUTH_RESPONSE Structure +UINT16 +TPMS_AUTH_RESPONSE_Marshal(TPMS_AUTH_RESPONSE* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + + TPM2B_NONCE_Marshal((TPM2B_NONCE*)&(source->nonce), buffer, size)); + result = (UINT16)(result + + TPMA_SESSION_Marshal( + (TPMA_SESSION*)&(source->sessionAttributes), buffer, size)); + result = + (UINT16)(result + + TPM2B_AUTH_Marshal((TPM2B_AUTH*)&(source->hmac), buffer, size)); + return result; +} + +// Table 2:137 - Definition of TPMI_TDES_KEY_BITS Type +# if ALG_TDES +TPM_RC +TPMI_TDES_KEY_BITS_Unmarshal(TPMI_TDES_KEY_BITS* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = TPM_KEY_BITS_Unmarshal((TPM_KEY_BITS*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { +# if TDES_128 + case 128: +# endif // TDES_128 +# if TDES_192 + case 192: +# endif // TDES_192 + break; + default: + result = TPM_RC_VALUE; + break; + } + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_TDES_KEY_BITS_Marshal(TPMI_TDES_KEY_BITS* source, BYTE** buffer, INT32* size) +{ + return TPM_KEY_BITS_Marshal((TPM_KEY_BITS*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES +# endif // ALG_TDES + +// Table 2:137 - Definition of TPMI_AES_KEY_BITS Type +# if ALG_AES +TPM_RC +TPMI_AES_KEY_BITS_Unmarshal(TPMI_AES_KEY_BITS* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = TPM_KEY_BITS_Unmarshal((TPM_KEY_BITS*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { +# if AES_128 + case 128: +# endif // AES_128 +# if AES_192 + case 192: +# endif // AES_192 +# if AES_256 + case 256: +# endif // AES_256 + break; + default: + result = TPM_RC_VALUE; + break; + } + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_AES_KEY_BITS_Marshal(TPMI_AES_KEY_BITS* source, BYTE** buffer, INT32* size) +{ + return TPM_KEY_BITS_Marshal((TPM_KEY_BITS*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES +# endif // ALG_AES + +// Table 2:137 - Definition of TPMI_SM4_KEY_BITS Type +# if ALG_SM4 +TPM_RC +TPMI_SM4_KEY_BITS_Unmarshal(TPMI_SM4_KEY_BITS* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = TPM_KEY_BITS_Unmarshal((TPM_KEY_BITS*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { +# if SM4_128 + case 128: +# endif // SM4_128 + break; + default: + result = TPM_RC_VALUE; + break; + } + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_SM4_KEY_BITS_Marshal(TPMI_SM4_KEY_BITS* source, BYTE** buffer, INT32* size) +{ + return TPM_KEY_BITS_Marshal((TPM_KEY_BITS*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES +# endif // ALG_SM4 + +// Table 2:137 - Definition of TPMI_CAMELLIA_KEY_BITS Type +# if ALG_CAMELLIA +TPM_RC +TPMI_CAMELLIA_KEY_BITS_Unmarshal( + TPMI_CAMELLIA_KEY_BITS* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = TPM_KEY_BITS_Unmarshal((TPM_KEY_BITS*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { +# if CAMELLIA_128 + case 128: +# endif // CAMELLIA_128 +# if CAMELLIA_192 + case 192: +# endif // CAMELLIA_192 +# if CAMELLIA_256 + case 256: +# endif // CAMELLIA_256 + break; + default: + result = TPM_RC_VALUE; + break; + } + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_CAMELLIA_KEY_BITS_Marshal( + TPMI_CAMELLIA_KEY_BITS* source, BYTE** buffer, INT32* size) +{ + return TPM_KEY_BITS_Marshal((TPM_KEY_BITS*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES +# endif // ALG_CAMELLIA + +// Table 2:138 - Definition of TPMU_SYM_KEY_BITS Union +TPM_RC +TPMU_SYM_KEY_BITS_Unmarshal( + TPMU_SYM_KEY_BITS* target, BYTE** buffer, INT32* size, UINT32 selector) +{ + switch(selector) + { +# if ALG_TDES + case TPM_ALG_TDES: + return TPMI_TDES_KEY_BITS_Unmarshal( + (TPMI_TDES_KEY_BITS*)&(target->tdes), buffer, size); +# endif // ALG_TDES +# if ALG_AES + case TPM_ALG_AES: + return TPMI_AES_KEY_BITS_Unmarshal( + (TPMI_AES_KEY_BITS*)&(target->aes), buffer, size); +# endif // ALG_AES +# if ALG_SM4 + case TPM_ALG_SM4: + return TPMI_SM4_KEY_BITS_Unmarshal( + (TPMI_SM4_KEY_BITS*)&(target->sm4), buffer, size); +# endif // ALG_SM4 +# if ALG_CAMELLIA + case TPM_ALG_CAMELLIA: + return TPMI_CAMELLIA_KEY_BITS_Unmarshal( + (TPMI_CAMELLIA_KEY_BITS*)&(target->camellia), buffer, size); +# endif // ALG_CAMELLIA +# if ALG_XOR + case TPM_ALG_XOR: + return TPMI_ALG_HASH_Unmarshal( + (TPMI_ALG_HASH*)&(target->xor), buffer, size, 0); +# endif // ALG_XOR + case TPM_ALG_NULL: + return TPM_RC_SUCCESS; + } + return TPM_RC_SELECTOR; +} +UINT16 +TPMU_SYM_KEY_BITS_Marshal( + TPMU_SYM_KEY_BITS* source, BYTE** buffer, INT32* size, UINT32 selector) +{ + switch(selector) + { +# if ALG_TDES + case TPM_ALG_TDES: + return TPMI_TDES_KEY_BITS_Marshal( + (TPMI_TDES_KEY_BITS*)&(source->tdes), buffer, size); +# endif // ALG_TDES +# if ALG_AES + case TPM_ALG_AES: + return TPMI_AES_KEY_BITS_Marshal( + (TPMI_AES_KEY_BITS*)&(source->aes), buffer, size); +# endif // ALG_AES +# if ALG_SM4 + case TPM_ALG_SM4: + return TPMI_SM4_KEY_BITS_Marshal( + (TPMI_SM4_KEY_BITS*)&(source->sm4), buffer, size); +# endif // ALG_SM4 +# if ALG_CAMELLIA + case TPM_ALG_CAMELLIA: + return TPMI_CAMELLIA_KEY_BITS_Marshal( + (TPMI_CAMELLIA_KEY_BITS*)&(source->camellia), buffer, size); +# endif // ALG_CAMELLIA +# if ALG_XOR + case TPM_ALG_XOR: + return TPMI_ALG_HASH_Marshal( + (TPMI_ALG_HASH*)&(source->xor), buffer, size); +# endif // ALG_XOR + case TPM_ALG_NULL: + return 0; + } + return 0; +} + +// Table 2:139 - Definition of TPMU_SYM_MODE Union +TPM_RC +TPMU_SYM_MODE_Unmarshal( + TPMU_SYM_MODE* target, BYTE** buffer, INT32* size, UINT32 selector) +{ + switch(selector) + { +# if ALG_TDES + case TPM_ALG_TDES: + return TPMI_ALG_SYM_MODE_Unmarshal( + (TPMI_ALG_SYM_MODE*)&(target->tdes), buffer, size, 1); +# endif // ALG_TDES +# if ALG_AES + case TPM_ALG_AES: + return TPMI_ALG_SYM_MODE_Unmarshal( + (TPMI_ALG_SYM_MODE*)&(target->aes), buffer, size, 1); +# endif // ALG_AES +# if ALG_SM4 + case TPM_ALG_SM4: + return TPMI_ALG_SYM_MODE_Unmarshal( + (TPMI_ALG_SYM_MODE*)&(target->sm4), buffer, size, 1); +# endif // ALG_SM4 +# if ALG_CAMELLIA + case TPM_ALG_CAMELLIA: + return TPMI_ALG_SYM_MODE_Unmarshal( + (TPMI_ALG_SYM_MODE*)&(target->camellia), buffer, size, 1); +# endif // ALG_CAMELLIA +# if ALG_XOR + case TPM_ALG_XOR: + return TPM_RC_SUCCESS; +# endif // ALG_XOR + case TPM_ALG_NULL: + return TPM_RC_SUCCESS; + } + return TPM_RC_SELECTOR; +} +UINT16 +TPMU_SYM_MODE_Marshal( + TPMU_SYM_MODE* source, BYTE** buffer, INT32* size, UINT32 selector) +{ + switch(selector) + { +# if ALG_TDES + case TPM_ALG_TDES: + return TPMI_ALG_SYM_MODE_Marshal( + (TPMI_ALG_SYM_MODE*)&(source->tdes), buffer, size); +# endif // ALG_TDES +# if ALG_AES + case TPM_ALG_AES: + return TPMI_ALG_SYM_MODE_Marshal( + (TPMI_ALG_SYM_MODE*)&(source->aes), buffer, size); +# endif // ALG_AES +# if ALG_SM4 + case TPM_ALG_SM4: + return TPMI_ALG_SYM_MODE_Marshal( + (TPMI_ALG_SYM_MODE*)&(source->sm4), buffer, size); +# endif // ALG_SM4 +# if ALG_CAMELLIA + case TPM_ALG_CAMELLIA: + return TPMI_ALG_SYM_MODE_Marshal( + (TPMI_ALG_SYM_MODE*)&(source->camellia), buffer, size); +# endif // ALG_CAMELLIA +# if ALG_XOR + case TPM_ALG_XOR: + return 0; +# endif // ALG_XOR + case TPM_ALG_NULL: + return 0; + } + return 0; +} + +// Table 2:141 - Definition of TPMT_SYM_DEF Structure +TPM_RC +TPMT_SYM_DEF_Unmarshal(TPMT_SYM_DEF* target, BYTE** buffer, INT32* size, BOOL flag) +{ + TPM_RC result; + result = TPMI_ALG_SYM_Unmarshal( + (TPMI_ALG_SYM*)&(target->algorithm), buffer, size, flag); + if(result == TPM_RC_SUCCESS) + result = TPMU_SYM_KEY_BITS_Unmarshal((TPMU_SYM_KEY_BITS*)&(target->keyBits), + buffer, + size, + (UINT32)target->algorithm); + if(result == TPM_RC_SUCCESS) + result = TPMU_SYM_MODE_Unmarshal( + (TPMU_SYM_MODE*)&(target->mode), buffer, size, (UINT32)target->algorithm); + return result; +} +UINT16 +TPMT_SYM_DEF_Marshal(TPMT_SYM_DEF* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = (UINT16)(result + + TPMI_ALG_SYM_Marshal( + (TPMI_ALG_SYM*)&(source->algorithm), buffer, size)); + result = + (UINT16)(result + + TPMU_SYM_KEY_BITS_Marshal((TPMU_SYM_KEY_BITS*)&(source->keyBits), + buffer, + size, + (UINT32)source->algorithm)); + result = (UINT16)(result + + TPMU_SYM_MODE_Marshal((TPMU_SYM_MODE*)&(source->mode), + buffer, + size, + (UINT32)source->algorithm)); + return result; +} + +// Table 2:142 - Definition of TPMT_SYM_DEF_OBJECT Structure +TPM_RC +TPMT_SYM_DEF_OBJECT_Unmarshal( + TPMT_SYM_DEF_OBJECT* target, BYTE** buffer, INT32* size, BOOL flag) +{ + TPM_RC result; + result = TPMI_ALG_SYM_OBJECT_Unmarshal( + (TPMI_ALG_SYM_OBJECT*)&(target->algorithm), buffer, size, flag); + if(result == TPM_RC_SUCCESS) + result = TPMU_SYM_KEY_BITS_Unmarshal((TPMU_SYM_KEY_BITS*)&(target->keyBits), + buffer, + size, + (UINT32)target->algorithm); + if(result == TPM_RC_SUCCESS) + result = TPMU_SYM_MODE_Unmarshal( + (TPMU_SYM_MODE*)&(target->mode), buffer, size, (UINT32)target->algorithm); + return result; +} +UINT16 +TPMT_SYM_DEF_OBJECT_Marshal(TPMT_SYM_DEF_OBJECT* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = (UINT16)(result + + TPMI_ALG_SYM_OBJECT_Marshal( + (TPMI_ALG_SYM_OBJECT*)&(source->algorithm), buffer, size)); + result = + (UINT16)(result + + TPMU_SYM_KEY_BITS_Marshal((TPMU_SYM_KEY_BITS*)&(source->keyBits), + buffer, + size, + (UINT32)source->algorithm)); + result = (UINT16)(result + + TPMU_SYM_MODE_Marshal((TPMU_SYM_MODE*)&(source->mode), + buffer, + size, + (UINT32)source->algorithm)); + return result; +} + +// Table 2:143 - Definition of TPM2B_SYM_KEY Structure +TPM_RC +TPM2B_SYM_KEY_Unmarshal(TPM2B_SYM_KEY* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT16_Unmarshal((UINT16*)&(target->t.size), buffer, size); + if(result == TPM_RC_SUCCESS) + { + if((target->t.size) > MAX_SYM_KEY_BYTES) + result = TPM_RC_SIZE; + else + result = BYTE_Array_Unmarshal( + (BYTE*)(target->t.buffer), buffer, size, (INT32)(target->t.size)); + } + return result; +} +UINT16 +TPM2B_SYM_KEY_Marshal(TPM2B_SYM_KEY* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT16_Marshal((UINT16*)&(source->t.size), buffer, size)); + // if size equal to 0, the rest of the structure is a zero buffer. Stop processing + if(source->t.size == 0) + return result; + result = (UINT16)(result + + BYTE_Array_Marshal((BYTE*)(source->t.buffer), + buffer, + size, + (INT32)(source->t.size))); + return result; +} + +// Table 2:144 - Definition of TPMS_SYMCIPHER_PARMS Structure +TPM_RC +TPMS_SYMCIPHER_PARMS_Unmarshal( + TPMS_SYMCIPHER_PARMS* target, BYTE** buffer, INT32* size) +{ + return TPMT_SYM_DEF_OBJECT_Unmarshal( + (TPMT_SYM_DEF_OBJECT*)&(target->sym), buffer, size, 0); +} +UINT16 +TPMS_SYMCIPHER_PARMS_Marshal(TPMS_SYMCIPHER_PARMS* source, BYTE** buffer, INT32* size) +{ + return TPMT_SYM_DEF_OBJECT_Marshal( + (TPMT_SYM_DEF_OBJECT*)&(source->sym), buffer, size); +} + +// Table 2:145 - Definition of TPM2B_LABEL Structure +TPM_RC +TPM2B_LABEL_Unmarshal(TPM2B_LABEL* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT16_Unmarshal((UINT16*)&(target->t.size), buffer, size); + if(result == TPM_RC_SUCCESS) + { + if((target->t.size) > LABEL_MAX_BUFFER) + result = TPM_RC_SIZE; + else + result = BYTE_Array_Unmarshal( + (BYTE*)(target->t.buffer), buffer, size, (INT32)(target->t.size)); + } + return result; +} +UINT16 +TPM2B_LABEL_Marshal(TPM2B_LABEL* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT16_Marshal((UINT16*)&(source->t.size), buffer, size)); + // if size equal to 0, the rest of the structure is a zero buffer. Stop processing + if(source->t.size == 0) + return result; + result = (UINT16)(result + + BYTE_Array_Marshal((BYTE*)(source->t.buffer), + buffer, + size, + (INT32)(source->t.size))); + return result; +} + +// Table 2:146 - Definition of TPMS_DERIVE Structure +TPM_RC +TPMS_DERIVE_Unmarshal(TPMS_DERIVE* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = TPM2B_LABEL_Unmarshal((TPM2B_LABEL*)&(target->label), buffer, size); + if(result == TPM_RC_SUCCESS) + result = + TPM2B_LABEL_Unmarshal((TPM2B_LABEL*)&(target->context), buffer, size); + return result; +} +UINT16 +TPMS_DERIVE_Marshal(TPMS_DERIVE* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + + TPM2B_LABEL_Marshal((TPM2B_LABEL*)&(source->label), buffer, size)); + result = (UINT16)(result + + TPM2B_LABEL_Marshal( + (TPM2B_LABEL*)&(source->context), buffer, size)); + return result; +} + +// Table 2:147 - Definition of TPM2B_DERIVE Structure +TPM_RC +TPM2B_DERIVE_Unmarshal(TPM2B_DERIVE* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT16_Unmarshal((UINT16*)&(target->t.size), buffer, size); + if(result == TPM_RC_SUCCESS) + { + if((target->t.size) > sizeof(TPMS_DERIVE)) + result = TPM_RC_SIZE; + else + result = BYTE_Array_Unmarshal( + (BYTE*)(target->t.buffer), buffer, size, (INT32)(target->t.size)); + } + return result; +} +UINT16 +TPM2B_DERIVE_Marshal(TPM2B_DERIVE* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT16_Marshal((UINT16*)&(source->t.size), buffer, size)); + // if size equal to 0, the rest of the structure is a zero buffer. Stop processing + if(source->t.size == 0) + return result; + result = (UINT16)(result + + BYTE_Array_Marshal((BYTE*)(source->t.buffer), + buffer, + size, + (INT32)(source->t.size))); + return result; +} + +// Table 2:148 - Definition of TPMU_SENSITIVE_CREATE Union +// Table 2:149 - Definition of TPM2B_SENSITIVE_DATA Structure +TPM_RC +TPM2B_SENSITIVE_DATA_Unmarshal( + TPM2B_SENSITIVE_DATA* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT16_Unmarshal((UINT16*)&(target->t.size), buffer, size); + if(result == TPM_RC_SUCCESS) + { + if((target->t.size) > sizeof(TPMU_SENSITIVE_CREATE)) + result = TPM_RC_SIZE; + else + result = BYTE_Array_Unmarshal( + (BYTE*)(target->t.buffer), buffer, size, (INT32)(target->t.size)); + } + return result; +} +UINT16 +TPM2B_SENSITIVE_DATA_Marshal(TPM2B_SENSITIVE_DATA* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT16_Marshal((UINT16*)&(source->t.size), buffer, size)); + // if size equal to 0, the rest of the structure is a zero buffer. Stop processing + if(source->t.size == 0) + return result; + result = (UINT16)(result + + BYTE_Array_Marshal((BYTE*)(source->t.buffer), + buffer, + size, + (INT32)(source->t.size))); + return result; +} + +// Table 2:150 - Definition of TPMS_SENSITIVE_CREATE Structure +TPM_RC +TPMS_SENSITIVE_CREATE_Unmarshal( + TPMS_SENSITIVE_CREATE* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = TPM2B_AUTH_Unmarshal((TPM2B_AUTH*)&(target->userAuth), buffer, size); + if(result == TPM_RC_SUCCESS) + result = TPM2B_SENSITIVE_DATA_Unmarshal( + (TPM2B_SENSITIVE_DATA*)&(target->data), buffer, size); + return result; +} + +// Table 2:151 - Definition of TPM2B_SENSITIVE_CREATE Structure +TPM_RC +TPM2B_SENSITIVE_CREATE_Unmarshal( + TPM2B_SENSITIVE_CREATE* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT16_Unmarshal((UINT16*)&(target->size), buffer, size); // =a + if(result == TPM_RC_SUCCESS) + { + // if size is zero, then the required structure is missing + if(target->size == 0) + result = TPM_RC_SIZE; + else + { + INT32 startSize = *size; + result = TPMS_SENSITIVE_CREATE_Unmarshal( + (TPMS_SENSITIVE_CREATE*)&(target->sensitive), buffer, size); // =b + if(result == TPM_RC_SUCCESS) + { + if(target->size != (startSize - *size)) + result = TPM_RC_SIZE; + } + } + } + return result; +} + +// Table 2:152 - Definition of TPMS_SCHEME_HASH Structure +TPM_RC +TPMS_SCHEME_HASH_Unmarshal(TPMS_SCHEME_HASH* target, BYTE** buffer, INT32* size) +{ + return TPMI_ALG_HASH_Unmarshal( + (TPMI_ALG_HASH*)&(target->hashAlg), buffer, size, 0); +} +UINT16 +TPMS_SCHEME_HASH_Marshal(TPMS_SCHEME_HASH* source, BYTE** buffer, INT32* size) +{ + return TPMI_ALG_HASH_Marshal((TPMI_ALG_HASH*)&(source->hashAlg), buffer, size); +} + +// Table 2:153 - Definition of TPMS_SCHEME_ECDAA Structure +# if ALG_ECC +TPM_RC +TPMS_SCHEME_ECDAA_Unmarshal(TPMS_SCHEME_ECDAA* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = + TPMI_ALG_HASH_Unmarshal((TPMI_ALG_HASH*)&(target->hashAlg), buffer, size, 0); + if(result == TPM_RC_SUCCESS) + result = UINT16_Unmarshal((UINT16*)&(target->count), buffer, size); + return result; +} +UINT16 +TPMS_SCHEME_ECDAA_Marshal(TPMS_SCHEME_ECDAA* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = (UINT16)(result + + TPMI_ALG_HASH_Marshal( + (TPMI_ALG_HASH*)&(source->hashAlg), buffer, size)); + result = + (UINT16)(result + UINT16_Marshal((UINT16*)&(source->count), buffer, size)); + return result; +} +# endif // ALG_ECC + +// Table 2:154 - Definition of TPMI_ALG_KEYEDHASH_SCHEME Type +TPM_RC +TPMI_ALG_KEYEDHASH_SCHEME_Unmarshal( + TPMI_ALG_KEYEDHASH_SCHEME* target, BYTE** buffer, INT32* size, BOOL flag) +{ + TPM_RC result; + result = TPM_ALG_ID_Unmarshal((TPM_ALG_ID*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { +# if ALG_HMAC + case TPM_ALG_HMAC: +# endif // ALG_HMAC +# if ALG_XOR + case TPM_ALG_XOR: +# endif // ALG_XOR + break; + case TPM_ALG_NULL: + if(!flag) + result = TPM_RC_VALUE; + break; + default: + result = TPM_RC_VALUE; + break; + } + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_ALG_KEYEDHASH_SCHEME_Marshal( + TPMI_ALG_KEYEDHASH_SCHEME* source, BYTE** buffer, INT32* size) +{ + return TPM_ALG_ID_Marshal((TPM_ALG_ID*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:155 - Definition of Types for HMAC_SIG_SCHEME +# if !USE_MARSHALING_DEFINES +TPM_RC +TPMS_SCHEME_HMAC_Unmarshal(TPMS_SCHEME_HMAC* target, BYTE** buffer, INT32* size) +{ + return TPMS_SCHEME_HASH_Unmarshal((TPMS_SCHEME_HASH*)target, buffer, size); +} +UINT16 +TPMS_SCHEME_HMAC_Marshal(TPMS_SCHEME_HMAC* source, BYTE** buffer, INT32* size) +{ + return TPMS_SCHEME_HASH_Marshal((TPMS_SCHEME_HASH*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:156 - Definition of TPMS_SCHEME_XOR Structure +TPM_RC +TPMS_SCHEME_XOR_Unmarshal(TPMS_SCHEME_XOR* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = + TPMI_ALG_HASH_Unmarshal((TPMI_ALG_HASH*)&(target->hashAlg), buffer, size, 0); + if(result == TPM_RC_SUCCESS) + result = + TPMI_ALG_KDF_Unmarshal((TPMI_ALG_KDF*)&(target->kdf), buffer, size, 1); + return result; +} +UINT16 +TPMS_SCHEME_XOR_Marshal(TPMS_SCHEME_XOR* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = (UINT16)(result + + TPMI_ALG_HASH_Marshal( + (TPMI_ALG_HASH*)&(source->hashAlg), buffer, size)); + result = + (UINT16)(result + + TPMI_ALG_KDF_Marshal((TPMI_ALG_KDF*)&(source->kdf), buffer, size)); + return result; +} + +// Table 2:157 - Definition of TPMU_SCHEME_KEYEDHASH Union +TPM_RC +TPMU_SCHEME_KEYEDHASH_Unmarshal( + TPMU_SCHEME_KEYEDHASH* target, BYTE** buffer, INT32* size, UINT32 selector) +{ + switch(selector) + { +# if ALG_HMAC + case TPM_ALG_HMAC: + return TPMS_SCHEME_HMAC_Unmarshal( + (TPMS_SCHEME_HMAC*)&(target->hmac), buffer, size); +# endif // ALG_HMAC +# if ALG_XOR + case TPM_ALG_XOR: + return TPMS_SCHEME_XOR_Unmarshal( + (TPMS_SCHEME_XOR*)&(target->xor), buffer, size); +# endif // ALG_XOR + case TPM_ALG_NULL: + return TPM_RC_SUCCESS; + } + return TPM_RC_SELECTOR; +} +UINT16 +TPMU_SCHEME_KEYEDHASH_Marshal( + TPMU_SCHEME_KEYEDHASH* source, BYTE** buffer, INT32* size, UINT32 selector) +{ + switch(selector) + { +# if ALG_HMAC + case TPM_ALG_HMAC: + return TPMS_SCHEME_HMAC_Marshal( + (TPMS_SCHEME_HMAC*)&(source->hmac), buffer, size); +# endif // ALG_HMAC +# if ALG_XOR + case TPM_ALG_XOR: + return TPMS_SCHEME_XOR_Marshal( + (TPMS_SCHEME_XOR*)&(source->xor), buffer, size); +# endif // ALG_XOR + case TPM_ALG_NULL: + return 0; + } + return 0; +} + +// Table 2:158 - Definition of TPMT_KEYEDHASH_SCHEME Structure +TPM_RC +TPMT_KEYEDHASH_SCHEME_Unmarshal( + TPMT_KEYEDHASH_SCHEME* target, BYTE** buffer, INT32* size, BOOL flag) +{ + TPM_RC result; + result = TPMI_ALG_KEYEDHASH_SCHEME_Unmarshal( + (TPMI_ALG_KEYEDHASH_SCHEME*)&(target->scheme), buffer, size, flag); + if(result == TPM_RC_SUCCESS) + result = TPMU_SCHEME_KEYEDHASH_Unmarshal( + (TPMU_SCHEME_KEYEDHASH*)&(target->details), + buffer, + size, + (UINT32)target->scheme); + return result; +} +UINT16 +TPMT_KEYEDHASH_SCHEME_Marshal( + TPMT_KEYEDHASH_SCHEME* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + + TPMI_ALG_KEYEDHASH_SCHEME_Marshal( + (TPMI_ALG_KEYEDHASH_SCHEME*)&(source->scheme), buffer, size)); + result = (UINT16)(result + + TPMU_SCHEME_KEYEDHASH_Marshal( + (TPMU_SCHEME_KEYEDHASH*)&(source->details), + buffer, + size, + (UINT32)source->scheme)); + return result; +} + +// Table 2:159 - Definition of Types for RSA Signature Schemes +# if ALG_RSA +# if !USE_MARSHALING_DEFINES +TPM_RC +TPMS_SIG_SCHEME_RSASSA_Unmarshal( + TPMS_SIG_SCHEME_RSASSA* target, BYTE** buffer, INT32* size) +{ + return TPMS_SCHEME_HASH_Unmarshal((TPMS_SCHEME_HASH*)target, buffer, size); +} +UINT16 +TPMS_SIG_SCHEME_RSASSA_Marshal( + TPMS_SIG_SCHEME_RSASSA* source, BYTE** buffer, INT32* size) +{ + return TPMS_SCHEME_HASH_Marshal((TPMS_SCHEME_HASH*)source, buffer, size); +} +TPM_RC +TPMS_SIG_SCHEME_RSAPSS_Unmarshal( + TPMS_SIG_SCHEME_RSAPSS* target, BYTE** buffer, INT32* size) +{ + return TPMS_SCHEME_HASH_Unmarshal((TPMS_SCHEME_HASH*)target, buffer, size); +} +UINT16 +TPMS_SIG_SCHEME_RSAPSS_Marshal( + TPMS_SIG_SCHEME_RSAPSS* source, BYTE** buffer, INT32* size) +{ + return TPMS_SCHEME_HASH_Marshal((TPMS_SCHEME_HASH*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES +# endif // ALG_RSA + +// Table 2:160 - Definition of Types for ECC Signature Schemes +# if ALG_ECC +# if !USE_MARSHALING_DEFINES +TPM_RC +TPMS_SIG_SCHEME_ECDSA_Unmarshal( + TPMS_SIG_SCHEME_ECDSA* target, BYTE** buffer, INT32* size) +{ + return TPMS_SCHEME_HASH_Unmarshal((TPMS_SCHEME_HASH*)target, buffer, size); +} +UINT16 +TPMS_SIG_SCHEME_ECDSA_Marshal( + TPMS_SIG_SCHEME_ECDSA* source, BYTE** buffer, INT32* size) +{ + return TPMS_SCHEME_HASH_Marshal((TPMS_SCHEME_HASH*)source, buffer, size); +} +TPM_RC +TPMS_SIG_SCHEME_SM2_Unmarshal(TPMS_SIG_SCHEME_SM2* target, BYTE** buffer, INT32* size) +{ + return TPMS_SCHEME_HASH_Unmarshal((TPMS_SCHEME_HASH*)target, buffer, size); +} +UINT16 +TPMS_SIG_SCHEME_SM2_Marshal(TPMS_SIG_SCHEME_SM2* source, BYTE** buffer, INT32* size) +{ + return TPMS_SCHEME_HASH_Marshal((TPMS_SCHEME_HASH*)source, buffer, size); +} +TPM_RC +TPMS_SIG_SCHEME_ECSCHNORR_Unmarshal( + TPMS_SIG_SCHEME_ECSCHNORR* target, BYTE** buffer, INT32* size) +{ + return TPMS_SCHEME_HASH_Unmarshal((TPMS_SCHEME_HASH*)target, buffer, size); +} +UINT16 +TPMS_SIG_SCHEME_ECSCHNORR_Marshal( + TPMS_SIG_SCHEME_ECSCHNORR* source, BYTE** buffer, INT32* size) +{ + return TPMS_SCHEME_HASH_Marshal((TPMS_SCHEME_HASH*)source, buffer, size); +} +TPM_RC +TPMS_SIG_SCHEME_ECDAA_Unmarshal( + TPMS_SIG_SCHEME_ECDAA* target, BYTE** buffer, INT32* size) +{ + return TPMS_SCHEME_ECDAA_Unmarshal((TPMS_SCHEME_ECDAA*)target, buffer, size); +} +UINT16 +TPMS_SIG_SCHEME_ECDAA_Marshal( + TPMS_SIG_SCHEME_ECDAA* source, BYTE** buffer, INT32* size) +{ + return TPMS_SCHEME_ECDAA_Marshal((TPMS_SCHEME_ECDAA*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES +# endif // ALG_ECC + +// Table 2:161 - Definition of TPMU_SIG_SCHEME Union +TPM_RC +TPMU_SIG_SCHEME_Unmarshal( + TPMU_SIG_SCHEME* target, BYTE** buffer, INT32* size, UINT32 selector) +{ + switch(selector) + { +# if ALG_ECDAA + case TPM_ALG_ECDAA: + return TPMS_SIG_SCHEME_ECDAA_Unmarshal( + (TPMS_SIG_SCHEME_ECDAA*)&(target->ecdaa), buffer, size); +# endif // ALG_ECDAA +# if ALG_RSASSA + case TPM_ALG_RSASSA: + return TPMS_SIG_SCHEME_RSASSA_Unmarshal( + (TPMS_SIG_SCHEME_RSASSA*)&(target->rsassa), buffer, size); +# endif // ALG_RSASSA +# if ALG_RSAPSS + case TPM_ALG_RSAPSS: + return TPMS_SIG_SCHEME_RSAPSS_Unmarshal( + (TPMS_SIG_SCHEME_RSAPSS*)&(target->rsapss), buffer, size); +# endif // ALG_RSAPSS +# if ALG_ECDSA + case TPM_ALG_ECDSA: + return TPMS_SIG_SCHEME_ECDSA_Unmarshal( + (TPMS_SIG_SCHEME_ECDSA*)&(target->ecdsa), buffer, size); +# endif // ALG_ECDSA +# if ALG_SM2 + case TPM_ALG_SM2: + return TPMS_SIG_SCHEME_SM2_Unmarshal( + (TPMS_SIG_SCHEME_SM2*)&(target->sm2), buffer, size); +# endif // ALG_SM2 +# if ALG_ECSCHNORR + case TPM_ALG_ECSCHNORR: + return TPMS_SIG_SCHEME_ECSCHNORR_Unmarshal( + (TPMS_SIG_SCHEME_ECSCHNORR*)&(target->ecschnorr), buffer, size); +# endif // ALG_ECSCHNORR +# if ALG_HMAC + case TPM_ALG_HMAC: + return TPMS_SCHEME_HMAC_Unmarshal( + (TPMS_SCHEME_HMAC*)&(target->hmac), buffer, size); +# endif // ALG_HMAC + case TPM_ALG_NULL: + return TPM_RC_SUCCESS; + } + return TPM_RC_SELECTOR; +} +UINT16 +TPMU_SIG_SCHEME_Marshal( + TPMU_SIG_SCHEME* source, BYTE** buffer, INT32* size, UINT32 selector) +{ + switch(selector) + { +# if ALG_ECDAA + case TPM_ALG_ECDAA: + return TPMS_SIG_SCHEME_ECDAA_Marshal( + (TPMS_SIG_SCHEME_ECDAA*)&(source->ecdaa), buffer, size); +# endif // ALG_ECDAA +# if ALG_RSASSA + case TPM_ALG_RSASSA: + return TPMS_SIG_SCHEME_RSASSA_Marshal( + (TPMS_SIG_SCHEME_RSASSA*)&(source->rsassa), buffer, size); +# endif // ALG_RSASSA +# if ALG_RSAPSS + case TPM_ALG_RSAPSS: + return TPMS_SIG_SCHEME_RSAPSS_Marshal( + (TPMS_SIG_SCHEME_RSAPSS*)&(source->rsapss), buffer, size); +# endif // ALG_RSAPSS +# if ALG_ECDSA + case TPM_ALG_ECDSA: + return TPMS_SIG_SCHEME_ECDSA_Marshal( + (TPMS_SIG_SCHEME_ECDSA*)&(source->ecdsa), buffer, size); +# endif // ALG_ECDSA +# if ALG_SM2 + case TPM_ALG_SM2: + return TPMS_SIG_SCHEME_SM2_Marshal( + (TPMS_SIG_SCHEME_SM2*)&(source->sm2), buffer, size); +# endif // ALG_SM2 +# if ALG_ECSCHNORR + case TPM_ALG_ECSCHNORR: + return TPMS_SIG_SCHEME_ECSCHNORR_Marshal( + (TPMS_SIG_SCHEME_ECSCHNORR*)&(source->ecschnorr), buffer, size); +# endif // ALG_ECSCHNORR +# if ALG_HMAC + case TPM_ALG_HMAC: + return TPMS_SCHEME_HMAC_Marshal( + (TPMS_SCHEME_HMAC*)&(source->hmac), buffer, size); +# endif // ALG_HMAC + case TPM_ALG_NULL: + return 0; + } + return 0; +} + +// Table 2:162 - Definition of TPMT_SIG_SCHEME Structure +TPM_RC +TPMT_SIG_SCHEME_Unmarshal( + TPMT_SIG_SCHEME* target, BYTE** buffer, INT32* size, BOOL flag) +{ + TPM_RC result; + result = TPMI_ALG_SIG_SCHEME_Unmarshal( + (TPMI_ALG_SIG_SCHEME*)&(target->scheme), buffer, size, flag); + if(result == TPM_RC_SUCCESS) + result = TPMU_SIG_SCHEME_Unmarshal((TPMU_SIG_SCHEME*)&(target->details), + buffer, + size, + (UINT32)target->scheme); + return result; +} +UINT16 +TPMT_SIG_SCHEME_Marshal(TPMT_SIG_SCHEME* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = (UINT16)(result + + TPMI_ALG_SIG_SCHEME_Marshal( + (TPMI_ALG_SIG_SCHEME*)&(source->scheme), buffer, size)); + result = (UINT16)(result + + TPMU_SIG_SCHEME_Marshal((TPMU_SIG_SCHEME*)&(source->details), + buffer, + size, + (UINT32)source->scheme)); + return result; +} + +// Table 2:163 - Definition of Types for Encryption Schemes +# if ALG_RSA +# if !USE_MARSHALING_DEFINES +TPM_RC +TPMS_ENC_SCHEME_OAEP_Unmarshal( + TPMS_ENC_SCHEME_OAEP* target, BYTE** buffer, INT32* size) +{ + return TPMS_SCHEME_HASH_Unmarshal((TPMS_SCHEME_HASH*)target, buffer, size); +} +UINT16 +TPMS_ENC_SCHEME_OAEP_Marshal(TPMS_ENC_SCHEME_OAEP* source, BYTE** buffer, INT32* size) +{ + return TPMS_SCHEME_HASH_Marshal((TPMS_SCHEME_HASH*)source, buffer, size); +} +TPM_RC +TPMS_ENC_SCHEME_RSAES_Unmarshal( + TPMS_ENC_SCHEME_RSAES* target, BYTE** buffer, INT32* size) +{ + return TPMS_EMPTY_Unmarshal((TPMS_EMPTY*)target, buffer, size); +} +UINT16 +TPMS_ENC_SCHEME_RSAES_Marshal( + TPMS_ENC_SCHEME_RSAES* source, BYTE** buffer, INT32* size) +{ + return TPMS_EMPTY_Marshal((TPMS_EMPTY*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES +# endif // ALG_RSA + +// Table 2:164 - Definition of Types for ECC Key Exchange +# if ALG_ECC +# if !USE_MARSHALING_DEFINES +TPM_RC +TPMS_KEY_SCHEME_ECDH_Unmarshal( + TPMS_KEY_SCHEME_ECDH* target, BYTE** buffer, INT32* size) +{ + return TPMS_SCHEME_HASH_Unmarshal((TPMS_SCHEME_HASH*)target, buffer, size); +} +UINT16 +TPMS_KEY_SCHEME_ECDH_Marshal(TPMS_KEY_SCHEME_ECDH* source, BYTE** buffer, INT32* size) +{ + return TPMS_SCHEME_HASH_Marshal((TPMS_SCHEME_HASH*)source, buffer, size); +} +TPM_RC +TPMS_KEY_SCHEME_ECMQV_Unmarshal( + TPMS_KEY_SCHEME_ECMQV* target, BYTE** buffer, INT32* size) +{ + return TPMS_SCHEME_HASH_Unmarshal((TPMS_SCHEME_HASH*)target, buffer, size); +} +UINT16 +TPMS_KEY_SCHEME_ECMQV_Marshal( + TPMS_KEY_SCHEME_ECMQV* source, BYTE** buffer, INT32* size) +{ + return TPMS_SCHEME_HASH_Marshal((TPMS_SCHEME_HASH*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES +# endif // ALG_ECC + +// Table 2:165 - Definition of Types for KDF Schemes +# if !USE_MARSHALING_DEFINES +TPM_RC +TPMS_KDF_SCHEME_MGF1_Unmarshal( + TPMS_KDF_SCHEME_MGF1* target, BYTE** buffer, INT32* size) +{ + return TPMS_SCHEME_HASH_Unmarshal((TPMS_SCHEME_HASH*)target, buffer, size); +} +UINT16 +TPMS_KDF_SCHEME_MGF1_Marshal(TPMS_KDF_SCHEME_MGF1* source, BYTE** buffer, INT32* size) +{ + return TPMS_SCHEME_HASH_Marshal((TPMS_SCHEME_HASH*)source, buffer, size); +} +TPM_RC +TPMS_KDF_SCHEME_KDF1_SP800_56A_Unmarshal( + TPMS_KDF_SCHEME_KDF1_SP800_56A* target, BYTE** buffer, INT32* size) +{ + return TPMS_SCHEME_HASH_Unmarshal((TPMS_SCHEME_HASH*)target, buffer, size); +} +UINT16 +TPMS_KDF_SCHEME_KDF1_SP800_56A_Marshal( + TPMS_KDF_SCHEME_KDF1_SP800_56A* source, BYTE** buffer, INT32* size) +{ + return TPMS_SCHEME_HASH_Marshal((TPMS_SCHEME_HASH*)source, buffer, size); +} +TPM_RC +TPMS_KDF_SCHEME_KDF2_Unmarshal( + TPMS_KDF_SCHEME_KDF2* target, BYTE** buffer, INT32* size) +{ + return TPMS_SCHEME_HASH_Unmarshal((TPMS_SCHEME_HASH*)target, buffer, size); +} +UINT16 +TPMS_KDF_SCHEME_KDF2_Marshal(TPMS_KDF_SCHEME_KDF2* source, BYTE** buffer, INT32* size) +{ + return TPMS_SCHEME_HASH_Marshal((TPMS_SCHEME_HASH*)source, buffer, size); +} +TPM_RC +TPMS_KDF_SCHEME_KDF1_SP800_108_Unmarshal( + TPMS_KDF_SCHEME_KDF1_SP800_108* target, BYTE** buffer, INT32* size) +{ + return TPMS_SCHEME_HASH_Unmarshal((TPMS_SCHEME_HASH*)target, buffer, size); +} +UINT16 +TPMS_KDF_SCHEME_KDF1_SP800_108_Marshal( + TPMS_KDF_SCHEME_KDF1_SP800_108* source, BYTE** buffer, INT32* size) +{ + return TPMS_SCHEME_HASH_Marshal((TPMS_SCHEME_HASH*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:166 - Definition of TPMU_KDF_SCHEME Union +TPM_RC +TPMU_KDF_SCHEME_Unmarshal( + TPMU_KDF_SCHEME* target, BYTE** buffer, INT32* size, UINT32 selector) +{ + switch(selector) + { +# if ALG_MGF1 + case TPM_ALG_MGF1: + return TPMS_KDF_SCHEME_MGF1_Unmarshal( + (TPMS_KDF_SCHEME_MGF1*)&(target->mgf1), buffer, size); +# endif // ALG_MGF1 +# if ALG_KDF1_SP800_56A + case TPM_ALG_KDF1_SP800_56A: + return TPMS_KDF_SCHEME_KDF1_SP800_56A_Unmarshal( + (TPMS_KDF_SCHEME_KDF1_SP800_56A*)&(target->kdf1_sp800_56a), + buffer, + size); +# endif // ALG_KDF1_SP800_56A +# if ALG_KDF2 + case TPM_ALG_KDF2: + return TPMS_KDF_SCHEME_KDF2_Unmarshal( + (TPMS_KDF_SCHEME_KDF2*)&(target->kdf2), buffer, size); +# endif // ALG_KDF2 +# if ALG_KDF1_SP800_108 + case TPM_ALG_KDF1_SP800_108: + return TPMS_KDF_SCHEME_KDF1_SP800_108_Unmarshal( + (TPMS_KDF_SCHEME_KDF1_SP800_108*)&(target->kdf1_sp800_108), + buffer, + size); +# endif // ALG_KDF1_SP800_108 + case TPM_ALG_NULL: + return TPM_RC_SUCCESS; + } + return TPM_RC_SELECTOR; +} +UINT16 +TPMU_KDF_SCHEME_Marshal( + TPMU_KDF_SCHEME* source, BYTE** buffer, INT32* size, UINT32 selector) +{ + switch(selector) + { +# if ALG_MGF1 + case TPM_ALG_MGF1: + return TPMS_KDF_SCHEME_MGF1_Marshal( + (TPMS_KDF_SCHEME_MGF1*)&(source->mgf1), buffer, size); +# endif // ALG_MGF1 +# if ALG_KDF1_SP800_56A + case TPM_ALG_KDF1_SP800_56A: + return TPMS_KDF_SCHEME_KDF1_SP800_56A_Marshal( + (TPMS_KDF_SCHEME_KDF1_SP800_56A*)&(source->kdf1_sp800_56a), + buffer, + size); +# endif // ALG_KDF1_SP800_56A +# if ALG_KDF2 + case TPM_ALG_KDF2: + return TPMS_KDF_SCHEME_KDF2_Marshal( + (TPMS_KDF_SCHEME_KDF2*)&(source->kdf2), buffer, size); +# endif // ALG_KDF2 +# if ALG_KDF1_SP800_108 + case TPM_ALG_KDF1_SP800_108: + return TPMS_KDF_SCHEME_KDF1_SP800_108_Marshal( + (TPMS_KDF_SCHEME_KDF1_SP800_108*)&(source->kdf1_sp800_108), + buffer, + size); +# endif // ALG_KDF1_SP800_108 + case TPM_ALG_NULL: + return 0; + } + return 0; +} + +// Table 2:167 - Definition of TPMT_KDF_SCHEME Structure +TPM_RC +TPMT_KDF_SCHEME_Unmarshal( + TPMT_KDF_SCHEME* target, BYTE** buffer, INT32* size, BOOL flag) +{ + TPM_RC result; + result = + TPMI_ALG_KDF_Unmarshal((TPMI_ALG_KDF*)&(target->scheme), buffer, size, flag); + if(result == TPM_RC_SUCCESS) + result = TPMU_KDF_SCHEME_Unmarshal((TPMU_KDF_SCHEME*)&(target->details), + buffer, + size, + (UINT32)target->scheme); + return result; +} +UINT16 +TPMT_KDF_SCHEME_Marshal(TPMT_KDF_SCHEME* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = (UINT16)(result + + TPMI_ALG_KDF_Marshal( + (TPMI_ALG_KDF*)&(source->scheme), buffer, size)); + result = (UINT16)(result + + TPMU_KDF_SCHEME_Marshal((TPMU_KDF_SCHEME*)&(source->details), + buffer, + size, + (UINT32)source->scheme)); + return result; +} + +// Table 2:168 - Definition of TPMI_ALG_ASYM_SCHEME Type +TPM_RC +TPMI_ALG_ASYM_SCHEME_Unmarshal( + TPMI_ALG_ASYM_SCHEME* target, BYTE** buffer, INT32* size, BOOL flag) +{ + TPM_RC result; + result = TPM_ALG_ID_Unmarshal((TPM_ALG_ID*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { +# if ALG_ECDH + case TPM_ALG_ECDH: +# endif // ALG_ECDH +# if ALG_ECMQV + case TPM_ALG_ECMQV: +# endif // ALG_ECMQV +# if ALG_ECDAA + case TPM_ALG_ECDAA: +# endif // ALG_ECDAA +# if ALG_RSASSA + case TPM_ALG_RSASSA: +# endif // ALG_RSASSA +# if ALG_RSAPSS + case TPM_ALG_RSAPSS: +# endif // ALG_RSAPSS +# if ALG_ECDSA + case TPM_ALG_ECDSA: +# endif // ALG_ECDSA +# if ALG_SM2 + case TPM_ALG_SM2: +# endif // ALG_SM2 +# if ALG_ECSCHNORR + case TPM_ALG_ECSCHNORR: +# endif // ALG_ECSCHNORR +# if ALG_RSAES + case TPM_ALG_RSAES: +# endif // ALG_RSAES +# if ALG_OAEP + case TPM_ALG_OAEP: +# endif // ALG_OAEP + break; + case TPM_ALG_NULL: + if(!flag) + result = TPM_RC_VALUE; + break; + default: + result = TPM_RC_VALUE; + break; + } + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_ALG_ASYM_SCHEME_Marshal(TPMI_ALG_ASYM_SCHEME* source, BYTE** buffer, INT32* size) +{ + return TPM_ALG_ID_Marshal((TPM_ALG_ID*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:169 - Definition of TPMU_ASYM_SCHEME Union +TPM_RC +TPMU_ASYM_SCHEME_Unmarshal( + TPMU_ASYM_SCHEME* target, BYTE** buffer, INT32* size, UINT32 selector) +{ + switch(selector) + { +# if ALG_ECDH + case TPM_ALG_ECDH: + return TPMS_KEY_SCHEME_ECDH_Unmarshal( + (TPMS_KEY_SCHEME_ECDH*)&(target->ecdh), buffer, size); +# endif // ALG_ECDH +# if ALG_ECMQV + case TPM_ALG_ECMQV: + return TPMS_KEY_SCHEME_ECMQV_Unmarshal( + (TPMS_KEY_SCHEME_ECMQV*)&(target->ecmqv), buffer, size); +# endif // ALG_ECMQV +# if ALG_ECDAA + case TPM_ALG_ECDAA: + return TPMS_SIG_SCHEME_ECDAA_Unmarshal( + (TPMS_SIG_SCHEME_ECDAA*)&(target->ecdaa), buffer, size); +# endif // ALG_ECDAA +# if ALG_RSASSA + case TPM_ALG_RSASSA: + return TPMS_SIG_SCHEME_RSASSA_Unmarshal( + (TPMS_SIG_SCHEME_RSASSA*)&(target->rsassa), buffer, size); +# endif // ALG_RSASSA +# if ALG_RSAPSS + case TPM_ALG_RSAPSS: + return TPMS_SIG_SCHEME_RSAPSS_Unmarshal( + (TPMS_SIG_SCHEME_RSAPSS*)&(target->rsapss), buffer, size); +# endif // ALG_RSAPSS +# if ALG_ECDSA + case TPM_ALG_ECDSA: + return TPMS_SIG_SCHEME_ECDSA_Unmarshal( + (TPMS_SIG_SCHEME_ECDSA*)&(target->ecdsa), buffer, size); +# endif // ALG_ECDSA +# if ALG_SM2 + case TPM_ALG_SM2: + return TPMS_SIG_SCHEME_SM2_Unmarshal( + (TPMS_SIG_SCHEME_SM2*)&(target->sm2), buffer, size); +# endif // ALG_SM2 +# if ALG_ECSCHNORR + case TPM_ALG_ECSCHNORR: + return TPMS_SIG_SCHEME_ECSCHNORR_Unmarshal( + (TPMS_SIG_SCHEME_ECSCHNORR*)&(target->ecschnorr), buffer, size); +# endif // ALG_ECSCHNORR +# if ALG_RSAES + case TPM_ALG_RSAES: + return TPMS_ENC_SCHEME_RSAES_Unmarshal( + (TPMS_ENC_SCHEME_RSAES*)&(target->rsaes), buffer, size); +# endif // ALG_RSAES +# if ALG_OAEP + case TPM_ALG_OAEP: + return TPMS_ENC_SCHEME_OAEP_Unmarshal( + (TPMS_ENC_SCHEME_OAEP*)&(target->oaep), buffer, size); +# endif // ALG_OAEP + case TPM_ALG_NULL: + return TPM_RC_SUCCESS; + } + return TPM_RC_SELECTOR; +} +UINT16 +TPMU_ASYM_SCHEME_Marshal( + TPMU_ASYM_SCHEME* source, BYTE** buffer, INT32* size, UINT32 selector) +{ + switch(selector) + { +# if ALG_ECDH + case TPM_ALG_ECDH: + return TPMS_KEY_SCHEME_ECDH_Marshal( + (TPMS_KEY_SCHEME_ECDH*)&(source->ecdh), buffer, size); +# endif // ALG_ECDH +# if ALG_ECMQV + case TPM_ALG_ECMQV: + return TPMS_KEY_SCHEME_ECMQV_Marshal( + (TPMS_KEY_SCHEME_ECMQV*)&(source->ecmqv), buffer, size); +# endif // ALG_ECMQV +# if ALG_ECDAA + case TPM_ALG_ECDAA: + return TPMS_SIG_SCHEME_ECDAA_Marshal( + (TPMS_SIG_SCHEME_ECDAA*)&(source->ecdaa), buffer, size); +# endif // ALG_ECDAA +# if ALG_RSASSA + case TPM_ALG_RSASSA: + return TPMS_SIG_SCHEME_RSASSA_Marshal( + (TPMS_SIG_SCHEME_RSASSA*)&(source->rsassa), buffer, size); +# endif // ALG_RSASSA +# if ALG_RSAPSS + case TPM_ALG_RSAPSS: + return TPMS_SIG_SCHEME_RSAPSS_Marshal( + (TPMS_SIG_SCHEME_RSAPSS*)&(source->rsapss), buffer, size); +# endif // ALG_RSAPSS +# if ALG_ECDSA + case TPM_ALG_ECDSA: + return TPMS_SIG_SCHEME_ECDSA_Marshal( + (TPMS_SIG_SCHEME_ECDSA*)&(source->ecdsa), buffer, size); +# endif // ALG_ECDSA +# if ALG_SM2 + case TPM_ALG_SM2: + return TPMS_SIG_SCHEME_SM2_Marshal( + (TPMS_SIG_SCHEME_SM2*)&(source->sm2), buffer, size); +# endif // ALG_SM2 +# if ALG_ECSCHNORR + case TPM_ALG_ECSCHNORR: + return TPMS_SIG_SCHEME_ECSCHNORR_Marshal( + (TPMS_SIG_SCHEME_ECSCHNORR*)&(source->ecschnorr), buffer, size); +# endif // ALG_ECSCHNORR +# if ALG_RSAES + case TPM_ALG_RSAES: + return TPMS_ENC_SCHEME_RSAES_Marshal( + (TPMS_ENC_SCHEME_RSAES*)&(source->rsaes), buffer, size); +# endif // ALG_RSAES +# if ALG_OAEP + case TPM_ALG_OAEP: + return TPMS_ENC_SCHEME_OAEP_Marshal( + (TPMS_ENC_SCHEME_OAEP*)&(source->oaep), buffer, size); +# endif // ALG_OAEP + case TPM_ALG_NULL: + return 0; + } + return 0; +} + +// Table 2:170 - Definition of TPMT_ASYM_SCHEME Structure +// Table 2:171 - Definition of TPMI_ALG_RSA_SCHEME Type +# if ALG_RSA +TPM_RC +TPMI_ALG_RSA_SCHEME_Unmarshal( + TPMI_ALG_RSA_SCHEME* target, BYTE** buffer, INT32* size, BOOL flag) +{ + TPM_RC result; + result = TPM_ALG_ID_Unmarshal((TPM_ALG_ID*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { +# if ALG_RSAES + case TPM_ALG_RSAES: +# endif // ALG_RSAES +# if ALG_OAEP + case TPM_ALG_OAEP: +# endif // ALG_OAEP +# if ALG_RSASSA + case TPM_ALG_RSASSA: +# endif // ALG_RSASSA +# if ALG_RSAPSS + case TPM_ALG_RSAPSS: +# endif // ALG_RSAPSS + break; + case TPM_ALG_NULL: + if(!flag) + result = TPM_RC_VALUE; + break; + default: + result = TPM_RC_VALUE; + break; + } + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_ALG_RSA_SCHEME_Marshal(TPMI_ALG_RSA_SCHEME* source, BYTE** buffer, INT32* size) +{ + return TPM_ALG_ID_Marshal((TPM_ALG_ID*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES +# endif // ALG_RSA + +// Table 2:172 - Definition of TPMT_RSA_SCHEME Structure +# if ALG_RSA +TPM_RC +TPMT_RSA_SCHEME_Unmarshal( + TPMT_RSA_SCHEME* target, BYTE** buffer, INT32* size, BOOL flag) +{ + TPM_RC result; + result = TPMI_ALG_RSA_SCHEME_Unmarshal( + (TPMI_ALG_RSA_SCHEME*)&(target->scheme), buffer, size, flag); + if(result == TPM_RC_SUCCESS) + result = TPMU_ASYM_SCHEME_Unmarshal((TPMU_ASYM_SCHEME*)&(target->details), + buffer, + size, + (UINT32)target->scheme); + return result; +} +UINT16 +TPMT_RSA_SCHEME_Marshal(TPMT_RSA_SCHEME* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = (UINT16)(result + + TPMI_ALG_RSA_SCHEME_Marshal( + (TPMI_ALG_RSA_SCHEME*)&(source->scheme), buffer, size)); + result = + (UINT16)(result + + TPMU_ASYM_SCHEME_Marshal((TPMU_ASYM_SCHEME*)&(source->details), + buffer, + size, + (UINT32)source->scheme)); + return result; +} +# endif // ALG_RSA + +// Table 2:173 - Definition of TPMI_ALG_RSA_DECRYPT Type +# if ALG_RSA +TPM_RC +TPMI_ALG_RSA_DECRYPT_Unmarshal( + TPMI_ALG_RSA_DECRYPT* target, BYTE** buffer, INT32* size, BOOL flag) +{ + TPM_RC result; + result = TPM_ALG_ID_Unmarshal((TPM_ALG_ID*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { +# if ALG_RSAES + case TPM_ALG_RSAES: +# endif // ALG_RSAES +# if ALG_OAEP + case TPM_ALG_OAEP: +# endif // ALG_OAEP + break; + case TPM_ALG_NULL: + if(!flag) + result = TPM_RC_VALUE; + break; + default: + result = TPM_RC_VALUE; + break; + } + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_ALG_RSA_DECRYPT_Marshal(TPMI_ALG_RSA_DECRYPT* source, BYTE** buffer, INT32* size) +{ + return TPM_ALG_ID_Marshal((TPM_ALG_ID*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES +# endif // ALG_RSA + +// Table 2:174 - Definition of TPMT_RSA_DECRYPT Structure +# if ALG_RSA +TPM_RC +TPMT_RSA_DECRYPT_Unmarshal( + TPMT_RSA_DECRYPT* target, BYTE** buffer, INT32* size, BOOL flag) +{ + TPM_RC result; + result = TPMI_ALG_RSA_DECRYPT_Unmarshal( + (TPMI_ALG_RSA_DECRYPT*)&(target->scheme), buffer, size, flag); + if(result == TPM_RC_SUCCESS) + result = TPMU_ASYM_SCHEME_Unmarshal((TPMU_ASYM_SCHEME*)&(target->details), + buffer, + size, + (UINT32)target->scheme); + return result; +} +UINT16 +TPMT_RSA_DECRYPT_Marshal(TPMT_RSA_DECRYPT* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = (UINT16)(result + + TPMI_ALG_RSA_DECRYPT_Marshal( + (TPMI_ALG_RSA_DECRYPT*)&(source->scheme), buffer, size)); + result = + (UINT16)(result + + TPMU_ASYM_SCHEME_Marshal((TPMU_ASYM_SCHEME*)&(source->details), + buffer, + size, + (UINT32)source->scheme)); + return result; +} +# endif // ALG_RSA + +// Table 2:175 - Definition of TPM2B_PUBLIC_KEY_RSA Structure +# if ALG_RSA +TPM_RC +TPM2B_PUBLIC_KEY_RSA_Unmarshal( + TPM2B_PUBLIC_KEY_RSA* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT16_Unmarshal((UINT16*)&(target->t.size), buffer, size); + if(result == TPM_RC_SUCCESS) + { + if((target->t.size) > MAX_RSA_KEY_BYTES) + result = TPM_RC_SIZE; + else + result = BYTE_Array_Unmarshal( + (BYTE*)(target->t.buffer), buffer, size, (INT32)(target->t.size)); + } + return result; +} +UINT16 +TPM2B_PUBLIC_KEY_RSA_Marshal(TPM2B_PUBLIC_KEY_RSA* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT16_Marshal((UINT16*)&(source->t.size), buffer, size)); + // if size equal to 0, the rest of the structure is a zero buffer. Stop processing + if(source->t.size == 0) + return result; + result = (UINT16)(result + + BYTE_Array_Marshal((BYTE*)(source->t.buffer), + buffer, + size, + (INT32)(source->t.size))); + return result; +} +# endif // ALG_RSA + +// Table 2:176 - Definition of TPMI_RSA_KEY_BITS Type +# if ALG_RSA +TPM_RC +TPMI_RSA_KEY_BITS_Unmarshal(TPMI_RSA_KEY_BITS* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = TPM_KEY_BITS_Unmarshal((TPM_KEY_BITS*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { +# if RSA_1024 + case 1024: +# endif // RSA_1024 +# if RSA_2048 + case 2048: +# endif // RSA_2048 +# if RSA_3072 + case 3072: +# endif // RSA_3072 +# if RSA_4096 + case 4096: +# endif // RSA_4096 +# if RSA_16384 + case 16384: +# endif // RSA_16384 + break; + default: + result = TPM_RC_VALUE; + break; + } + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_RSA_KEY_BITS_Marshal(TPMI_RSA_KEY_BITS* source, BYTE** buffer, INT32* size) +{ + return TPM_KEY_BITS_Marshal((TPM_KEY_BITS*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES +# endif // ALG_RSA + +// Table 2:177 - Definition of TPM2B_PRIVATE_KEY_RSA Structure +# if ALG_RSA +TPM_RC +TPM2B_PRIVATE_KEY_RSA_Unmarshal( + TPM2B_PRIVATE_KEY_RSA* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT16_Unmarshal((UINT16*)&(target->t.size), buffer, size); + if(result == TPM_RC_SUCCESS) + { + if((target->t.size) > RSA_PRIVATE_SIZE) + result = TPM_RC_SIZE; + else + result = BYTE_Array_Unmarshal( + (BYTE*)(target->t.buffer), buffer, size, (INT32)(target->t.size)); + } + return result; +} +UINT16 +TPM2B_PRIVATE_KEY_RSA_Marshal( + TPM2B_PRIVATE_KEY_RSA* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT16_Marshal((UINT16*)&(source->t.size), buffer, size)); + // if size equal to 0, the rest of the structure is a zero buffer. Stop processing + if(source->t.size == 0) + return result; + result = (UINT16)(result + + BYTE_Array_Marshal((BYTE*)(source->t.buffer), + buffer, + size, + (INT32)(source->t.size))); + return result; +} +# endif // ALG_RSA + +// Table 2:178 - Definition of TPM2B_ECC_PARAMETER Structure +TPM_RC +TPM2B_ECC_PARAMETER_Unmarshal(TPM2B_ECC_PARAMETER* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT16_Unmarshal((UINT16*)&(target->t.size), buffer, size); + if(result == TPM_RC_SUCCESS) + { + if((target->t.size) > MAX_ECC_KEY_BYTES) + result = TPM_RC_SIZE; + else + result = BYTE_Array_Unmarshal( + (BYTE*)(target->t.buffer), buffer, size, (INT32)(target->t.size)); + } + return result; +} +UINT16 +TPM2B_ECC_PARAMETER_Marshal(TPM2B_ECC_PARAMETER* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT16_Marshal((UINT16*)&(source->t.size), buffer, size)); + // if size equal to 0, the rest of the structure is a zero buffer. Stop processing + if(source->t.size == 0) + return result; + result = (UINT16)(result + + BYTE_Array_Marshal((BYTE*)(source->t.buffer), + buffer, + size, + (INT32)(source->t.size))); + return result; +} + +// Table 2:179 - Definition of TPMS_ECC_POINT Structure +# if ALG_ECC +TPM_RC +TPMS_ECC_POINT_Unmarshal(TPMS_ECC_POINT* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = TPM2B_ECC_PARAMETER_Unmarshal( + (TPM2B_ECC_PARAMETER*)&(target->x), buffer, size); + if(result == TPM_RC_SUCCESS) + result = TPM2B_ECC_PARAMETER_Unmarshal( + (TPM2B_ECC_PARAMETER*)&(target->y), buffer, size); + return result; +} +UINT16 +TPMS_ECC_POINT_Marshal(TPMS_ECC_POINT* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = (UINT16)(result + + TPM2B_ECC_PARAMETER_Marshal( + (TPM2B_ECC_PARAMETER*)&(source->x), buffer, size)); + result = (UINT16)(result + + TPM2B_ECC_PARAMETER_Marshal( + (TPM2B_ECC_PARAMETER*)&(source->y), buffer, size)); + return result; +} +# endif // ALG_ECC + +// Table 2:180 - Definition of TPM2B_ECC_POINT Structure +# if ALG_ECC +TPM_RC +TPM2B_ECC_POINT_Unmarshal(TPM2B_ECC_POINT* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT16_Unmarshal((UINT16*)&(target->size), buffer, size); // =a + if(result == TPM_RC_SUCCESS) + { + // if size is zero, then the required structure is missing + if(target->size == 0) + result = TPM_RC_SIZE; + else + { + INT32 startSize = *size; + result = TPMS_ECC_POINT_Unmarshal( + (TPMS_ECC_POINT*)&(target->point), buffer, size); // =b + if(result == TPM_RC_SUCCESS) + { + if(target->size != (startSize - *size)) + result = TPM_RC_SIZE; + } + } + } + return result; +} +UINT16 +TPM2B_ECC_POINT_Marshal(TPM2B_ECC_POINT* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + // Marshal a dummy value of the 2B size. This makes sure that 'buffer' + // and 'size' are advanced as necessary (i.e., if they are present) + result = UINT16_Marshal(&result, buffer, size); + // Marshal the structure + result = (UINT16)(result + + TPMS_ECC_POINT_Marshal( + (TPMS_ECC_POINT*)&(source->point), buffer, size)); + // if a buffer was provided, go back and fill in the actual size + if(buffer != NULL) + UINT16_TO_BYTE_ARRAY((result - 2), (*buffer - result)); + return result; +} +# endif // ALG_ECC + +// Table 2:181 - Definition of TPMI_ALG_ECC_SCHEME Type +# if ALG_ECC +TPM_RC +TPMI_ALG_ECC_SCHEME_Unmarshal( + TPMI_ALG_ECC_SCHEME* target, BYTE** buffer, INT32* size, BOOL flag) +{ + TPM_RC result; + result = TPM_ALG_ID_Unmarshal((TPM_ALG_ID*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { +# if ALG_ECDAA + case TPM_ALG_ECDAA: +# endif // ALG_ECDAA +# if ALG_ECDSA + case TPM_ALG_ECDSA: +# endif // ALG_ECDSA +# if ALG_SM2 + case TPM_ALG_SM2: +# endif // ALG_SM2 +# if ALG_ECSCHNORR + case TPM_ALG_ECSCHNORR: +# endif // ALG_ECSCHNORR +# if ALG_ECDH + case TPM_ALG_ECDH: +# endif // ALG_ECDH +# if ALG_ECMQV + case TPM_ALG_ECMQV: +# endif // ALG_ECMQV + break; + case TPM_ALG_NULL: + if(!flag) + result = TPM_RC_SCHEME; + break; + default: + result = TPM_RC_SCHEME; + break; + } + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_ALG_ECC_SCHEME_Marshal(TPMI_ALG_ECC_SCHEME* source, BYTE** buffer, INT32* size) +{ + return TPM_ALG_ID_Marshal((TPM_ALG_ID*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES +# endif // ALG_ECC + +// Table 2:182 - Definition of TPMI_ECC_CURVE Type +# if ALG_ECC +TPM_RC +TPMI_ECC_CURVE_Unmarshal(TPMI_ECC_CURVE* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = TPM_ECC_CURVE_Unmarshal((TPM_ECC_CURVE*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { +# if ECC_BN_P256 + case TPM_ECC_BN_P256: +# endif // ECC_BN_P256 +# if ECC_BN_P638 + case TPM_ECC_BN_P638: +# endif // ECC_BN_P638 +# if ECC_NIST_P192 + case TPM_ECC_NIST_P192: +# endif // ECC_NIST_P192 +# if ECC_NIST_P224 + case TPM_ECC_NIST_P224: +# endif // ECC_NIST_P224 +# if ECC_NIST_P256 + case TPM_ECC_NIST_P256: +# endif // ECC_NIST_P256 +# if ECC_NIST_P384 + case TPM_ECC_NIST_P384: +# endif // ECC_NIST_P384 +# if ECC_NIST_P521 + case TPM_ECC_NIST_P521: +# endif // ECC_NIST_P521 +# if ECC_SM2_P256 + case TPM_ECC_SM2_P256: +# endif // ECC_SM2_P256 + break; + default: + result = TPM_RC_CURVE; + break; + } + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_ECC_CURVE_Marshal(TPMI_ECC_CURVE* source, BYTE** buffer, INT32* size) +{ + return TPM_ECC_CURVE_Marshal((TPM_ECC_CURVE*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES +# endif // ALG_ECC + +// Table 2:183 - Definition of TPMT_ECC_SCHEME Structure +# if ALG_ECC +TPM_RC +TPMT_ECC_SCHEME_Unmarshal( + TPMT_ECC_SCHEME* target, BYTE** buffer, INT32* size, BOOL flag) +{ + TPM_RC result; + result = TPMI_ALG_ECC_SCHEME_Unmarshal( + (TPMI_ALG_ECC_SCHEME*)&(target->scheme), buffer, size, flag); + if(result == TPM_RC_SUCCESS) + result = TPMU_ASYM_SCHEME_Unmarshal((TPMU_ASYM_SCHEME*)&(target->details), + buffer, + size, + (UINT32)target->scheme); + return result; +} +UINT16 +TPMT_ECC_SCHEME_Marshal(TPMT_ECC_SCHEME* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = (UINT16)(result + + TPMI_ALG_ECC_SCHEME_Marshal( + (TPMI_ALG_ECC_SCHEME*)&(source->scheme), buffer, size)); + result = + (UINT16)(result + + TPMU_ASYM_SCHEME_Marshal((TPMU_ASYM_SCHEME*)&(source->details), + buffer, + size, + (UINT32)source->scheme)); + return result; +} +# endif // ALG_ECC + +// Table 2:184 - Definition of TPMS_ALGORITHM_DETAIL_ECC Structure +# if ALG_ECC +UINT16 +TPMS_ALGORITHM_DETAIL_ECC_Marshal( + TPMS_ALGORITHM_DETAIL_ECC* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = (UINT16)(result + + TPM_ECC_CURVE_Marshal( + (TPM_ECC_CURVE*)&(source->curveID), buffer, size)); + result = + (UINT16)(result + UINT16_Marshal((UINT16*)&(source->keySize), buffer, size)); + result = (UINT16)(result + + TPMT_KDF_SCHEME_Marshal( + (TPMT_KDF_SCHEME*)&(source->kdf), buffer, size)); + result = (UINT16)(result + + TPMT_ECC_SCHEME_Marshal( + (TPMT_ECC_SCHEME*)&(source->sign), buffer, size)); + result = (UINT16)(result + + TPM2B_ECC_PARAMETER_Marshal( + (TPM2B_ECC_PARAMETER*)&(source->p), buffer, size)); + result = (UINT16)(result + + TPM2B_ECC_PARAMETER_Marshal( + (TPM2B_ECC_PARAMETER*)&(source->a), buffer, size)); + result = (UINT16)(result + + TPM2B_ECC_PARAMETER_Marshal( + (TPM2B_ECC_PARAMETER*)&(source->b), buffer, size)); + result = (UINT16)(result + + TPM2B_ECC_PARAMETER_Marshal( + (TPM2B_ECC_PARAMETER*)&(source->gX), buffer, size)); + result = (UINT16)(result + + TPM2B_ECC_PARAMETER_Marshal( + (TPM2B_ECC_PARAMETER*)&(source->gY), buffer, size)); + result = (UINT16)(result + + TPM2B_ECC_PARAMETER_Marshal( + (TPM2B_ECC_PARAMETER*)&(source->n), buffer, size)); + result = (UINT16)(result + + TPM2B_ECC_PARAMETER_Marshal( + (TPM2B_ECC_PARAMETER*)&(source->h), buffer, size)); + return result; +} +# endif // ALG_ECC + +// Table 2:185 - Definition of TPMS_SIGNATURE_RSA Structure +# if ALG_RSA +TPM_RC +TPMS_SIGNATURE_RSA_Unmarshal(TPMS_SIGNATURE_RSA* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = + TPMI_ALG_HASH_Unmarshal((TPMI_ALG_HASH*)&(target->hash), buffer, size, 0); + if(result == TPM_RC_SUCCESS) + result = TPM2B_PUBLIC_KEY_RSA_Unmarshal( + (TPM2B_PUBLIC_KEY_RSA*)&(target->sig), buffer, size); + return result; +} +UINT16 +TPMS_SIGNATURE_RSA_Marshal(TPMS_SIGNATURE_RSA* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = (UINT16)(result + + TPMI_ALG_HASH_Marshal( + (TPMI_ALG_HASH*)&(source->hash), buffer, size)); + result = (UINT16)(result + + TPM2B_PUBLIC_KEY_RSA_Marshal( + (TPM2B_PUBLIC_KEY_RSA*)&(source->sig), buffer, size)); + return result; +} +# endif // ALG_RSA + +// Table 2:186 - Definition of Types for Signature +# if ALG_RSA +# if !USE_MARSHALING_DEFINES +TPM_RC +TPMS_SIGNATURE_RSASSA_Unmarshal( + TPMS_SIGNATURE_RSASSA* target, BYTE** buffer, INT32* size) +{ + return TPMS_SIGNATURE_RSA_Unmarshal((TPMS_SIGNATURE_RSA*)target, buffer, size); +} +UINT16 +TPMS_SIGNATURE_RSASSA_Marshal( + TPMS_SIGNATURE_RSASSA* source, BYTE** buffer, INT32* size) +{ + return TPMS_SIGNATURE_RSA_Marshal((TPMS_SIGNATURE_RSA*)source, buffer, size); +} +TPM_RC +TPMS_SIGNATURE_RSAPSS_Unmarshal( + TPMS_SIGNATURE_RSAPSS* target, BYTE** buffer, INT32* size) +{ + return TPMS_SIGNATURE_RSA_Unmarshal((TPMS_SIGNATURE_RSA*)target, buffer, size); +} +UINT16 +TPMS_SIGNATURE_RSAPSS_Marshal( + TPMS_SIGNATURE_RSAPSS* source, BYTE** buffer, INT32* size) +{ + return TPMS_SIGNATURE_RSA_Marshal((TPMS_SIGNATURE_RSA*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES +# endif // ALG_RSA + +// Table 2:187 - Definition of TPMS_SIGNATURE_ECC Structure +# if ALG_ECC +TPM_RC +TPMS_SIGNATURE_ECC_Unmarshal(TPMS_SIGNATURE_ECC* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = + TPMI_ALG_HASH_Unmarshal((TPMI_ALG_HASH*)&(target->hash), buffer, size, 0); + if(result == TPM_RC_SUCCESS) + result = TPM2B_ECC_PARAMETER_Unmarshal( + (TPM2B_ECC_PARAMETER*)&(target->signatureR), buffer, size); + if(result == TPM_RC_SUCCESS) + result = TPM2B_ECC_PARAMETER_Unmarshal( + (TPM2B_ECC_PARAMETER*)&(target->signatureS), buffer, size); + return result; +} +UINT16 +TPMS_SIGNATURE_ECC_Marshal(TPMS_SIGNATURE_ECC* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = (UINT16)(result + + TPMI_ALG_HASH_Marshal( + (TPMI_ALG_HASH*)&(source->hash), buffer, size)); + result = (UINT16)(result + + TPM2B_ECC_PARAMETER_Marshal( + (TPM2B_ECC_PARAMETER*)&(source->signatureR), buffer, size)); + result = (UINT16)(result + + TPM2B_ECC_PARAMETER_Marshal( + (TPM2B_ECC_PARAMETER*)&(source->signatureS), buffer, size)); + return result; +} +# endif // ALG_ECC + +// Table 2:188 - Definition of Types for TPMS_SIGNATURE_ECC +# if ALG_ECC +# if !USE_MARSHALING_DEFINES +TPM_RC +TPMS_SIGNATURE_ECDAA_Unmarshal( + TPMS_SIGNATURE_ECDAA* target, BYTE** buffer, INT32* size) +{ + return TPMS_SIGNATURE_ECC_Unmarshal((TPMS_SIGNATURE_ECC*)target, buffer, size); +} +UINT16 +TPMS_SIGNATURE_ECDAA_Marshal(TPMS_SIGNATURE_ECDAA* source, BYTE** buffer, INT32* size) +{ + return TPMS_SIGNATURE_ECC_Marshal((TPMS_SIGNATURE_ECC*)source, buffer, size); +} +TPM_RC +TPMS_SIGNATURE_ECDSA_Unmarshal( + TPMS_SIGNATURE_ECDSA* target, BYTE** buffer, INT32* size) +{ + return TPMS_SIGNATURE_ECC_Unmarshal((TPMS_SIGNATURE_ECC*)target, buffer, size); +} +UINT16 +TPMS_SIGNATURE_ECDSA_Marshal(TPMS_SIGNATURE_ECDSA* source, BYTE** buffer, INT32* size) +{ + return TPMS_SIGNATURE_ECC_Marshal((TPMS_SIGNATURE_ECC*)source, buffer, size); +} +TPM_RC +TPMS_SIGNATURE_SM2_Unmarshal(TPMS_SIGNATURE_SM2* target, BYTE** buffer, INT32* size) +{ + return TPMS_SIGNATURE_ECC_Unmarshal((TPMS_SIGNATURE_ECC*)target, buffer, size); +} +UINT16 +TPMS_SIGNATURE_SM2_Marshal(TPMS_SIGNATURE_SM2* source, BYTE** buffer, INT32* size) +{ + return TPMS_SIGNATURE_ECC_Marshal((TPMS_SIGNATURE_ECC*)source, buffer, size); +} +TPM_RC +TPMS_SIGNATURE_ECSCHNORR_Unmarshal( + TPMS_SIGNATURE_ECSCHNORR* target, BYTE** buffer, INT32* size) +{ + return TPMS_SIGNATURE_ECC_Unmarshal((TPMS_SIGNATURE_ECC*)target, buffer, size); +} +UINT16 +TPMS_SIGNATURE_ECSCHNORR_Marshal( + TPMS_SIGNATURE_ECSCHNORR* source, BYTE** buffer, INT32* size) +{ + return TPMS_SIGNATURE_ECC_Marshal((TPMS_SIGNATURE_ECC*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES +# endif // ALG_ECC + +// Table 2:189 - Definition of TPMU_SIGNATURE Union +TPM_RC +TPMU_SIGNATURE_Unmarshal( + TPMU_SIGNATURE* target, BYTE** buffer, INT32* size, UINT32 selector) +{ + switch(selector) + { +# if ALG_ECDAA + case TPM_ALG_ECDAA: + return TPMS_SIGNATURE_ECDAA_Unmarshal( + (TPMS_SIGNATURE_ECDAA*)&(target->ecdaa), buffer, size); +# endif // ALG_ECDAA +# if ALG_RSASSA + case TPM_ALG_RSASSA: + return TPMS_SIGNATURE_RSASSA_Unmarshal( + (TPMS_SIGNATURE_RSASSA*)&(target->rsassa), buffer, size); +# endif // ALG_RSASSA +# if ALG_RSAPSS + case TPM_ALG_RSAPSS: + return TPMS_SIGNATURE_RSAPSS_Unmarshal( + (TPMS_SIGNATURE_RSAPSS*)&(target->rsapss), buffer, size); +# endif // ALG_RSAPSS +# if ALG_ECDSA + case TPM_ALG_ECDSA: + return TPMS_SIGNATURE_ECDSA_Unmarshal( + (TPMS_SIGNATURE_ECDSA*)&(target->ecdsa), buffer, size); +# endif // ALG_ECDSA +# if ALG_SM2 + case TPM_ALG_SM2: + return TPMS_SIGNATURE_SM2_Unmarshal( + (TPMS_SIGNATURE_SM2*)&(target->sm2), buffer, size); +# endif // ALG_SM2 +# if ALG_ECSCHNORR + case TPM_ALG_ECSCHNORR: + return TPMS_SIGNATURE_ECSCHNORR_Unmarshal( + (TPMS_SIGNATURE_ECSCHNORR*)&(target->ecschnorr), buffer, size); +# endif // ALG_ECSCHNORR +# if ALG_HMAC + case TPM_ALG_HMAC: + return TPMT_HA_Unmarshal((TPMT_HA*)&(target->hmac), buffer, size, 0); +# endif // ALG_HMAC + case TPM_ALG_NULL: + return TPM_RC_SUCCESS; + } + return TPM_RC_SELECTOR; +} +UINT16 +TPMU_SIGNATURE_Marshal( + TPMU_SIGNATURE* source, BYTE** buffer, INT32* size, UINT32 selector) +{ + switch(selector) + { +# if ALG_ECDAA + case TPM_ALG_ECDAA: + return TPMS_SIGNATURE_ECDAA_Marshal( + (TPMS_SIGNATURE_ECDAA*)&(source->ecdaa), buffer, size); +# endif // ALG_ECDAA +# if ALG_RSASSA + case TPM_ALG_RSASSA: + return TPMS_SIGNATURE_RSASSA_Marshal( + (TPMS_SIGNATURE_RSASSA*)&(source->rsassa), buffer, size); +# endif // ALG_RSASSA +# if ALG_RSAPSS + case TPM_ALG_RSAPSS: + return TPMS_SIGNATURE_RSAPSS_Marshal( + (TPMS_SIGNATURE_RSAPSS*)&(source->rsapss), buffer, size); +# endif // ALG_RSAPSS +# if ALG_ECDSA + case TPM_ALG_ECDSA: + return TPMS_SIGNATURE_ECDSA_Marshal( + (TPMS_SIGNATURE_ECDSA*)&(source->ecdsa), buffer, size); +# endif // ALG_ECDSA +# if ALG_SM2 + case TPM_ALG_SM2: + return TPMS_SIGNATURE_SM2_Marshal( + (TPMS_SIGNATURE_SM2*)&(source->sm2), buffer, size); +# endif // ALG_SM2 +# if ALG_ECSCHNORR + case TPM_ALG_ECSCHNORR: + return TPMS_SIGNATURE_ECSCHNORR_Marshal( + (TPMS_SIGNATURE_ECSCHNORR*)&(source->ecschnorr), buffer, size); +# endif // ALG_ECSCHNORR +# if ALG_HMAC + case TPM_ALG_HMAC: + return TPMT_HA_Marshal((TPMT_HA*)&(source->hmac), buffer, size); +# endif // ALG_HMAC + case TPM_ALG_NULL: + return 0; + } + return 0; +} + +// Table 2:190 - Definition of TPMT_SIGNATURE Structure +TPM_RC +TPMT_SIGNATURE_Unmarshal( + TPMT_SIGNATURE* target, BYTE** buffer, INT32* size, BOOL flag) +{ + TPM_RC result; + result = TPMI_ALG_SIG_SCHEME_Unmarshal( + (TPMI_ALG_SIG_SCHEME*)&(target->sigAlg), buffer, size, flag); + if(result == TPM_RC_SUCCESS) + result = TPMU_SIGNATURE_Unmarshal((TPMU_SIGNATURE*)&(target->signature), + buffer, + size, + (UINT32)target->sigAlg); + return result; +} +UINT16 +TPMT_SIGNATURE_Marshal(TPMT_SIGNATURE* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = (UINT16)(result + + TPMI_ALG_SIG_SCHEME_Marshal( + (TPMI_ALG_SIG_SCHEME*)&(source->sigAlg), buffer, size)); + result = (UINT16)(result + + TPMU_SIGNATURE_Marshal((TPMU_SIGNATURE*)&(source->signature), + buffer, + size, + (UINT32)source->sigAlg)); + return result; +} + +// Table 2:191 - Definition of TPMU_ENCRYPTED_SECRET Union +TPM_RC +TPMU_ENCRYPTED_SECRET_Unmarshal( + TPMU_ENCRYPTED_SECRET* target, BYTE** buffer, INT32* size, UINT32 selector) +{ + switch(selector) + { +# if ALG_ECC + case TPM_ALG_ECC: + return BYTE_Array_Unmarshal( + (BYTE*)(target->ecc), buffer, size, (INT32)sizeof(TPMS_ECC_POINT)); +# endif // ALG_ECC +# if ALG_RSA + case TPM_ALG_RSA: + return BYTE_Array_Unmarshal( + (BYTE*)(target->rsa), buffer, size, (INT32)MAX_RSA_KEY_BYTES); +# endif // ALG_RSA +# if ALG_SYMCIPHER + case TPM_ALG_SYMCIPHER: + return BYTE_Array_Unmarshal((BYTE*)(target->symmetric), + buffer, + size, + (INT32)sizeof(TPM2B_DIGEST)); +# endif // ALG_SYMCIPHER +# if ALG_KEYEDHASH + case TPM_ALG_KEYEDHASH: + return BYTE_Array_Unmarshal((BYTE*)(target->keyedHash), + buffer, + size, + (INT32)sizeof(TPM2B_DIGEST)); +# endif // ALG_KEYEDHASH + } + return TPM_RC_SELECTOR; +} +UINT16 +TPMU_ENCRYPTED_SECRET_Marshal( + TPMU_ENCRYPTED_SECRET* source, BYTE** buffer, INT32* size, UINT32 selector) +{ + switch(selector) + { +# if ALG_ECC + case TPM_ALG_ECC: + return BYTE_Array_Marshal( + (BYTE*)(source->ecc), buffer, size, (INT32)sizeof(TPMS_ECC_POINT)); +# endif // ALG_ECC +# if ALG_RSA + case TPM_ALG_RSA: + return BYTE_Array_Marshal( + (BYTE*)(source->rsa), buffer, size, (INT32)MAX_RSA_KEY_BYTES); +# endif // ALG_RSA +# if ALG_SYMCIPHER + case TPM_ALG_SYMCIPHER: + return BYTE_Array_Marshal((BYTE*)(source->symmetric), + buffer, + size, + (INT32)sizeof(TPM2B_DIGEST)); +# endif // ALG_SYMCIPHER +# if ALG_KEYEDHASH + case TPM_ALG_KEYEDHASH: + return BYTE_Array_Marshal((BYTE*)(source->keyedHash), + buffer, + size, + (INT32)sizeof(TPM2B_DIGEST)); +# endif // ALG_KEYEDHASH + } + return 0; +} + +// Table 2:192 - Definition of TPM2B_ENCRYPTED_SECRET Structure +TPM_RC +TPM2B_ENCRYPTED_SECRET_Unmarshal( + TPM2B_ENCRYPTED_SECRET* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT16_Unmarshal((UINT16*)&(target->t.size), buffer, size); + if(result == TPM_RC_SUCCESS) + { + if((target->t.size) > sizeof(TPMU_ENCRYPTED_SECRET)) + result = TPM_RC_SIZE; + else + result = BYTE_Array_Unmarshal( + (BYTE*)(target->t.secret), buffer, size, (INT32)(target->t.size)); + } + return result; +} +UINT16 +TPM2B_ENCRYPTED_SECRET_Marshal( + TPM2B_ENCRYPTED_SECRET* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT16_Marshal((UINT16*)&(source->t.size), buffer, size)); + // if size equal to 0, the rest of the structure is a zero buffer. Stop processing + if(source->t.size == 0) + return result; + result = (UINT16)(result + + BYTE_Array_Marshal((BYTE*)(source->t.secret), + buffer, + size, + (INT32)(source->t.size))); + return result; +} + +// Table 2:193 - Definition of TPMI_ALG_PUBLIC Type +TPM_RC +TPMI_ALG_PUBLIC_Unmarshal(TPMI_ALG_PUBLIC* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = TPM_ALG_ID_Unmarshal((TPM_ALG_ID*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { +# if ALG_RSA + case TPM_ALG_RSA: +# endif // ALG_RSA +# if ALG_ECC + case TPM_ALG_ECC: +# endif // ALG_ECC +# if ALG_KEYEDHASH + case TPM_ALG_KEYEDHASH: +# endif // ALG_KEYEDHASH +# if ALG_SYMCIPHER + case TPM_ALG_SYMCIPHER: +# endif // ALG_SYMCIPHER + break; + default: + result = TPM_RC_TYPE; + break; + } + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPMI_ALG_PUBLIC_Marshal(TPMI_ALG_PUBLIC* source, BYTE** buffer, INT32* size) +{ + return TPM_ALG_ID_Marshal((TPM_ALG_ID*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:194 - Definition of TPMU_PUBLIC_ID Union +TPM_RC +TPMU_PUBLIC_ID_Unmarshal( + TPMU_PUBLIC_ID* target, BYTE** buffer, INT32* size, UINT32 selector) +{ + switch(selector) + { +# if ALG_KEYEDHASH + case TPM_ALG_KEYEDHASH: + return TPM2B_DIGEST_Unmarshal( + (TPM2B_DIGEST*)&(target->keyedHash), buffer, size); +# endif // ALG_KEYEDHASH +# if ALG_SYMCIPHER + case TPM_ALG_SYMCIPHER: + return TPM2B_DIGEST_Unmarshal( + (TPM2B_DIGEST*)&(target->sym), buffer, size); +# endif // ALG_SYMCIPHER +# if ALG_RSA + case TPM_ALG_RSA: + return TPM2B_PUBLIC_KEY_RSA_Unmarshal( + (TPM2B_PUBLIC_KEY_RSA*)&(target->rsa), buffer, size); +# endif // ALG_RSA +# if ALG_ECC + case TPM_ALG_ECC: + return TPMS_ECC_POINT_Unmarshal( + (TPMS_ECC_POINT*)&(target->ecc), buffer, size); +# endif // ALG_ECC + } + return TPM_RC_SELECTOR; +} +UINT16 +TPMU_PUBLIC_ID_Marshal( + TPMU_PUBLIC_ID* source, BYTE** buffer, INT32* size, UINT32 selector) +{ + switch(selector) + { +# if ALG_KEYEDHASH + case TPM_ALG_KEYEDHASH: + return TPM2B_DIGEST_Marshal( + (TPM2B_DIGEST*)&(source->keyedHash), buffer, size); +# endif // ALG_KEYEDHASH +# if ALG_SYMCIPHER + case TPM_ALG_SYMCIPHER: + return TPM2B_DIGEST_Marshal((TPM2B_DIGEST*)&(source->sym), buffer, size); +# endif // ALG_SYMCIPHER +# if ALG_RSA + case TPM_ALG_RSA: + return TPM2B_PUBLIC_KEY_RSA_Marshal( + (TPM2B_PUBLIC_KEY_RSA*)&(source->rsa), buffer, size); +# endif // ALG_RSA +# if ALG_ECC + case TPM_ALG_ECC: + return TPMS_ECC_POINT_Marshal( + (TPMS_ECC_POINT*)&(source->ecc), buffer, size); +# endif // ALG_ECC + } + return 0; +} + +// Table 2:195 - Definition of TPMS_KEYEDHASH_PARMS Structure +TPM_RC +TPMS_KEYEDHASH_PARMS_Unmarshal( + TPMS_KEYEDHASH_PARMS* target, BYTE** buffer, INT32* size) +{ + return TPMT_KEYEDHASH_SCHEME_Unmarshal( + (TPMT_KEYEDHASH_SCHEME*)&(target->scheme), buffer, size, 1); +} +UINT16 +TPMS_KEYEDHASH_PARMS_Marshal(TPMS_KEYEDHASH_PARMS* source, BYTE** buffer, INT32* size) +{ + return TPMT_KEYEDHASH_SCHEME_Marshal( + (TPMT_KEYEDHASH_SCHEME*)&(source->scheme), buffer, size); +} + +// Table 2:196 - Definition of TPMS_ASYM_PARMS Structure +// Table 2:197 - Definition of TPMS_RSA_PARMS Structure +# if ALG_RSA +TPM_RC +TPMS_RSA_PARMS_Unmarshal(TPMS_RSA_PARMS* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = TPMT_SYM_DEF_OBJECT_Unmarshal( + (TPMT_SYM_DEF_OBJECT*)&(target->symmetric), buffer, size, 1); + if(result == TPM_RC_SUCCESS) + result = TPMT_RSA_SCHEME_Unmarshal( + (TPMT_RSA_SCHEME*)&(target->scheme), buffer, size, 1); + if(result == TPM_RC_SUCCESS) + result = TPMI_RSA_KEY_BITS_Unmarshal( + (TPMI_RSA_KEY_BITS*)&(target->keyBits), buffer, size); + if(result == TPM_RC_SUCCESS) + result = UINT32_Unmarshal((UINT32*)&(target->exponent), buffer, size); + return result; +} +UINT16 +TPMS_RSA_PARMS_Marshal(TPMS_RSA_PARMS* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = (UINT16)(result + + TPMT_SYM_DEF_OBJECT_Marshal( + (TPMT_SYM_DEF_OBJECT*)&(source->symmetric), buffer, size)); + result = (UINT16)(result + + TPMT_RSA_SCHEME_Marshal( + (TPMT_RSA_SCHEME*)&(source->scheme), buffer, size)); + result = (UINT16)(result + + TPMI_RSA_KEY_BITS_Marshal( + (TPMI_RSA_KEY_BITS*)&(source->keyBits), buffer, size)); + result = + (UINT16)(result + UINT32_Marshal((UINT32*)&(source->exponent), buffer, size)); + return result; +} +# endif // ALG_RSA + +// Table 2:198 - Definition of TPMS_ECC_PARMS Structure +# if ALG_ECC +TPM_RC +TPMS_ECC_PARMS_Unmarshal(TPMS_ECC_PARMS* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = TPMT_SYM_DEF_OBJECT_Unmarshal( + (TPMT_SYM_DEF_OBJECT*)&(target->symmetric), buffer, size, 1); + if(result == TPM_RC_SUCCESS) + result = TPMT_ECC_SCHEME_Unmarshal( + (TPMT_ECC_SCHEME*)&(target->scheme), buffer, size, 1); + if(result == TPM_RC_SUCCESS) + result = TPMI_ECC_CURVE_Unmarshal( + (TPMI_ECC_CURVE*)&(target->curveID), buffer, size); + if(result == TPM_RC_SUCCESS) + result = TPMT_KDF_SCHEME_Unmarshal( + (TPMT_KDF_SCHEME*)&(target->kdf), buffer, size, 1); + return result; +} +UINT16 +TPMS_ECC_PARMS_Marshal(TPMS_ECC_PARMS* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = (UINT16)(result + + TPMT_SYM_DEF_OBJECT_Marshal( + (TPMT_SYM_DEF_OBJECT*)&(source->symmetric), buffer, size)); + result = (UINT16)(result + + TPMT_ECC_SCHEME_Marshal( + (TPMT_ECC_SCHEME*)&(source->scheme), buffer, size)); + result = (UINT16)(result + + TPMI_ECC_CURVE_Marshal( + (TPMI_ECC_CURVE*)&(source->curveID), buffer, size)); + result = (UINT16)(result + + TPMT_KDF_SCHEME_Marshal( + (TPMT_KDF_SCHEME*)&(source->kdf), buffer, size)); + return result; +} +# endif // ALG_ECC + +// Table 2:199 - Definition of TPMU_PUBLIC_PARMS Union +TPM_RC +TPMU_PUBLIC_PARMS_Unmarshal( + TPMU_PUBLIC_PARMS* target, BYTE** buffer, INT32* size, UINT32 selector) +{ + switch(selector) + { +# if ALG_KEYEDHASH + case TPM_ALG_KEYEDHASH: + return TPMS_KEYEDHASH_PARMS_Unmarshal( + (TPMS_KEYEDHASH_PARMS*)&(target->keyedHashDetail), buffer, size); +# endif // ALG_KEYEDHASH +# if ALG_SYMCIPHER + case TPM_ALG_SYMCIPHER: + return TPMS_SYMCIPHER_PARMS_Unmarshal( + (TPMS_SYMCIPHER_PARMS*)&(target->symDetail), buffer, size); +# endif // ALG_SYMCIPHER +# if ALG_RSA + case TPM_ALG_RSA: + return TPMS_RSA_PARMS_Unmarshal( + (TPMS_RSA_PARMS*)&(target->rsaDetail), buffer, size); +# endif // ALG_RSA +# if ALG_ECC + case TPM_ALG_ECC: + return TPMS_ECC_PARMS_Unmarshal( + (TPMS_ECC_PARMS*)&(target->eccDetail), buffer, size); +# endif // ALG_ECC + } + return TPM_RC_SELECTOR; +} +UINT16 +TPMU_PUBLIC_PARMS_Marshal( + TPMU_PUBLIC_PARMS* source, BYTE** buffer, INT32* size, UINT32 selector) +{ + switch(selector) + { +# if ALG_KEYEDHASH + case TPM_ALG_KEYEDHASH: + return TPMS_KEYEDHASH_PARMS_Marshal( + (TPMS_KEYEDHASH_PARMS*)&(source->keyedHashDetail), buffer, size); +# endif // ALG_KEYEDHASH +# if ALG_SYMCIPHER + case TPM_ALG_SYMCIPHER: + return TPMS_SYMCIPHER_PARMS_Marshal( + (TPMS_SYMCIPHER_PARMS*)&(source->symDetail), buffer, size); +# endif // ALG_SYMCIPHER +# if ALG_RSA + case TPM_ALG_RSA: + return TPMS_RSA_PARMS_Marshal( + (TPMS_RSA_PARMS*)&(source->rsaDetail), buffer, size); +# endif // ALG_RSA +# if ALG_ECC + case TPM_ALG_ECC: + return TPMS_ECC_PARMS_Marshal( + (TPMS_ECC_PARMS*)&(source->eccDetail), buffer, size); +# endif // ALG_ECC + } + return 0; +} + +// Table 2:200 - Definition of TPMT_PUBLIC_PARMS Structure +TPM_RC +TPMT_PUBLIC_PARMS_Unmarshal(TPMT_PUBLIC_PARMS* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = + TPMI_ALG_PUBLIC_Unmarshal((TPMI_ALG_PUBLIC*)&(target->type), buffer, size); + if(result == TPM_RC_SUCCESS) + result = + TPMU_PUBLIC_PARMS_Unmarshal((TPMU_PUBLIC_PARMS*)&(target->parameters), + buffer, + size, + (UINT32)target->type); + return result; +} +UINT16 +TPMT_PUBLIC_PARMS_Marshal(TPMT_PUBLIC_PARMS* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = (UINT16)(result + + TPMI_ALG_PUBLIC_Marshal( + (TPMI_ALG_PUBLIC*)&(source->type), buffer, size)); + result = (UINT16)(result + + TPMU_PUBLIC_PARMS_Marshal( + (TPMU_PUBLIC_PARMS*)&(source->parameters), + buffer, + size, + (UINT32)source->type)); + return result; +} + +// Table 2:201 - Definition of TPMT_PUBLIC Structure +TPM_RC +TPMT_PUBLIC_Unmarshal(TPMT_PUBLIC* target, BYTE** buffer, INT32* size, BOOL flag) +{ + TPM_RC result; + result = + TPMI_ALG_PUBLIC_Unmarshal((TPMI_ALG_PUBLIC*)&(target->type), buffer, size); + if(result == TPM_RC_SUCCESS) + result = TPMI_ALG_HASH_Unmarshal( + (TPMI_ALG_HASH*)&(target->nameAlg), buffer, size, flag); + if(result == TPM_RC_SUCCESS) + result = TPMA_OBJECT_Unmarshal( + (TPMA_OBJECT*)&(target->objectAttributes), buffer, size); + if(result == TPM_RC_SUCCESS) + result = TPM2B_DIGEST_Unmarshal( + (TPM2B_DIGEST*)&(target->authPolicy), buffer, size); + if(result == TPM_RC_SUCCESS) + result = + TPMU_PUBLIC_PARMS_Unmarshal((TPMU_PUBLIC_PARMS*)&(target->parameters), + buffer, + size, + (UINT32)target->type); + if(result == TPM_RC_SUCCESS) + result = TPMU_PUBLIC_ID_Unmarshal( + (TPMU_PUBLIC_ID*)&(target->unique), buffer, size, (UINT32)target->type); + return result; +} +UINT16 +TPMT_PUBLIC_Marshal(TPMT_PUBLIC* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = (UINT16)(result + + TPMI_ALG_PUBLIC_Marshal( + (TPMI_ALG_PUBLIC*)&(source->type), buffer, size)); + result = (UINT16)(result + + TPMI_ALG_HASH_Marshal( + (TPMI_ALG_HASH*)&(source->nameAlg), buffer, size)); + result = (UINT16)(result + + TPMA_OBJECT_Marshal( + (TPMA_OBJECT*)&(source->objectAttributes), buffer, size)); + result = (UINT16)(result + + TPM2B_DIGEST_Marshal( + (TPM2B_DIGEST*)&(source->authPolicy), buffer, size)); + result = (UINT16)(result + + TPMU_PUBLIC_PARMS_Marshal( + (TPMU_PUBLIC_PARMS*)&(source->parameters), + buffer, + size, + (UINT32)source->type)); + result = (UINT16)(result + + TPMU_PUBLIC_ID_Marshal((TPMU_PUBLIC_ID*)&(source->unique), + buffer, + size, + (UINT32)source->type)); + return result; +} + +// Table 2:202 - Definition of TPM2B_PUBLIC Structure +TPM_RC +TPM2B_PUBLIC_Unmarshal(TPM2B_PUBLIC* target, BYTE** buffer, INT32* size, BOOL flag) +{ + TPM_RC result; + result = UINT16_Unmarshal((UINT16*)&(target->size), buffer, size); // =a + if(result == TPM_RC_SUCCESS) + { + // if size is zero, then the required structure is missing + if(target->size == 0) + result = TPM_RC_SIZE; + else + { + INT32 startSize = *size; + result = TPMT_PUBLIC_Unmarshal( + (TPMT_PUBLIC*)&(target->publicArea), buffer, size, flag); // =b + if(result == TPM_RC_SUCCESS) + { + if(target->size != (startSize - *size)) + result = TPM_RC_SIZE; + } + } + } + return result; +} +UINT16 +TPM2B_PUBLIC_Marshal(TPM2B_PUBLIC* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + // Marshal a dummy value of the 2B size. This makes sure that 'buffer' + // and 'size' are advanced as necessary (i.e., if they are present) + result = UINT16_Marshal(&result, buffer, size); + // Marshal the structure + result = (UINT16)(result + + TPMT_PUBLIC_Marshal( + (TPMT_PUBLIC*)&(source->publicArea), buffer, size)); + // if a buffer was provided, go back and fill in the actual size + if(buffer != NULL) + UINT16_TO_BYTE_ARRAY((result - 2), (*buffer - result)); + return result; +} + +// Table 2:203 - Definition of TPM2B_TEMPLATE Structure +TPM_RC +TPM2B_TEMPLATE_Unmarshal(TPM2B_TEMPLATE* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT16_Unmarshal((UINT16*)&(target->t.size), buffer, size); + if(result == TPM_RC_SUCCESS) + { + if((target->t.size) > sizeof(TPMT_PUBLIC)) + result = TPM_RC_SIZE; + else + result = BYTE_Array_Unmarshal( + (BYTE*)(target->t.buffer), buffer, size, (INT32)(target->t.size)); + } + return result; +} +UINT16 +TPM2B_TEMPLATE_Marshal(TPM2B_TEMPLATE* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT16_Marshal((UINT16*)&(source->t.size), buffer, size)); + // if size equal to 0, the rest of the structure is a zero buffer. Stop processing + if(source->t.size == 0) + return result; + result = (UINT16)(result + + BYTE_Array_Marshal((BYTE*)(source->t.buffer), + buffer, + size, + (INT32)(source->t.size))); + return result; +} + +// Table 2:204 - Definition of TPM2B_PRIVATE_VENDOR_SPECIFIC Structure +TPM_RC +TPM2B_PRIVATE_VENDOR_SPECIFIC_Unmarshal( + TPM2B_PRIVATE_VENDOR_SPECIFIC* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT16_Unmarshal((UINT16*)&(target->t.size), buffer, size); + if(result == TPM_RC_SUCCESS) + { + if((target->t.size) > PRIVATE_VENDOR_SPECIFIC_BYTES) + result = TPM_RC_SIZE; + else + result = BYTE_Array_Unmarshal( + (BYTE*)(target->t.buffer), buffer, size, (INT32)(target->t.size)); + } + return result; +} +UINT16 +TPM2B_PRIVATE_VENDOR_SPECIFIC_Marshal( + TPM2B_PRIVATE_VENDOR_SPECIFIC* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT16_Marshal((UINT16*)&(source->t.size), buffer, size)); + // if size equal to 0, the rest of the structure is a zero buffer. Stop processing + if(source->t.size == 0) + return result; + result = (UINT16)(result + + BYTE_Array_Marshal((BYTE*)(source->t.buffer), + buffer, + size, + (INT32)(source->t.size))); + return result; +} + +// Table 2:205 - Definition of TPMU_SENSITIVE_COMPOSITE Union +TPM_RC +TPMU_SENSITIVE_COMPOSITE_Unmarshal( + TPMU_SENSITIVE_COMPOSITE* target, BYTE** buffer, INT32* size, UINT32 selector) +{ + switch(selector) + { +# if ALG_RSA + case TPM_ALG_RSA: + return TPM2B_PRIVATE_KEY_RSA_Unmarshal( + (TPM2B_PRIVATE_KEY_RSA*)&(target->rsa), buffer, size); +# endif // ALG_RSA +# if ALG_ECC + case TPM_ALG_ECC: + return TPM2B_ECC_PARAMETER_Unmarshal( + (TPM2B_ECC_PARAMETER*)&(target->ecc), buffer, size); +# endif // ALG_ECC +# if ALG_KEYEDHASH + case TPM_ALG_KEYEDHASH: + return TPM2B_SENSITIVE_DATA_Unmarshal( + (TPM2B_SENSITIVE_DATA*)&(target->bits), buffer, size); +# endif // ALG_KEYEDHASH +# if ALG_SYMCIPHER + case TPM_ALG_SYMCIPHER: + return TPM2B_SYM_KEY_Unmarshal( + (TPM2B_SYM_KEY*)&(target->sym), buffer, size); +# endif // ALG_SYMCIPHER + } + return TPM_RC_SELECTOR; +} +UINT16 +TPMU_SENSITIVE_COMPOSITE_Marshal( + TPMU_SENSITIVE_COMPOSITE* source, BYTE** buffer, INT32* size, UINT32 selector) +{ + switch(selector) + { +# if ALG_RSA + case TPM_ALG_RSA: + return TPM2B_PRIVATE_KEY_RSA_Marshal( + (TPM2B_PRIVATE_KEY_RSA*)&(source->rsa), buffer, size); +# endif // ALG_RSA +# if ALG_ECC + case TPM_ALG_ECC: + return TPM2B_ECC_PARAMETER_Marshal( + (TPM2B_ECC_PARAMETER*)&(source->ecc), buffer, size); +# endif // ALG_ECC +# if ALG_KEYEDHASH + case TPM_ALG_KEYEDHASH: + return TPM2B_SENSITIVE_DATA_Marshal( + (TPM2B_SENSITIVE_DATA*)&(source->bits), buffer, size); +# endif // ALG_KEYEDHASH +# if ALG_SYMCIPHER + case TPM_ALG_SYMCIPHER: + return TPM2B_SYM_KEY_Marshal( + (TPM2B_SYM_KEY*)&(source->sym), buffer, size); +# endif // ALG_SYMCIPHER + } + return 0; +} + +// Table 2:206 - Definition of TPMT_SENSITIVE Structure +TPM_RC +TPMT_SENSITIVE_Unmarshal(TPMT_SENSITIVE* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = TPMI_ALG_PUBLIC_Unmarshal( + (TPMI_ALG_PUBLIC*)&(target->sensitiveType), buffer, size); + if(result == TPM_RC_SUCCESS) + result = + TPM2B_AUTH_Unmarshal((TPM2B_AUTH*)&(target->authValue), buffer, size); + if(result == TPM_RC_SUCCESS) + result = + TPM2B_DIGEST_Unmarshal((TPM2B_DIGEST*)&(target->seedValue), buffer, size); + if(result == TPM_RC_SUCCESS) + result = TPMU_SENSITIVE_COMPOSITE_Unmarshal( + (TPMU_SENSITIVE_COMPOSITE*)&(target->sensitive), + buffer, + size, + (UINT32)target->sensitiveType); + return result; +} +UINT16 +TPMT_SENSITIVE_Marshal(TPMT_SENSITIVE* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = (UINT16)(result + + TPMI_ALG_PUBLIC_Marshal( + (TPMI_ALG_PUBLIC*)&(source->sensitiveType), buffer, size)); + result = (UINT16)(result + + TPM2B_AUTH_Marshal( + (TPM2B_AUTH*)&(source->authValue), buffer, size)); + result = (UINT16)(result + + TPM2B_DIGEST_Marshal( + (TPM2B_DIGEST*)&(source->seedValue), buffer, size)); + result = (UINT16)(result + + TPMU_SENSITIVE_COMPOSITE_Marshal( + (TPMU_SENSITIVE_COMPOSITE*)&(source->sensitive), + buffer, + size, + (UINT32)source->sensitiveType)); + return result; +} + +// Table 2:207 - Definition of TPM2B_SENSITIVE Structure +TPM_RC +TPM2B_SENSITIVE_Unmarshal(TPM2B_SENSITIVE* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT16_Unmarshal((UINT16*)&(target->size), buffer, size); // =a + // if there was an error or if target->size equal to 0, + // skip unmarshaling of the structure + if((result == TPM_RC_SUCCESS) && (target->size != 0)) + { + INT32 startSize = *size; + result = TPMT_SENSITIVE_Unmarshal( + (TPMT_SENSITIVE*)&(target->sensitiveArea), buffer, size); // =b + if(result == TPM_RC_SUCCESS) + { + if(target->size != (startSize - *size)) + result = TPM_RC_SIZE; + } + } + return result; +} +UINT16 +TPM2B_SENSITIVE_Marshal(TPM2B_SENSITIVE* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + // Marshal a dummy value of the 2B size. This makes sure that 'buffer' + // and 'size' are advanced as necessary (i.e., if they are present) + result = UINT16_Marshal(&result, buffer, size); + // Marshal the structure + result = (UINT16)(result + + TPMT_SENSITIVE_Marshal( + (TPMT_SENSITIVE*)&(source->sensitiveArea), buffer, size)); + // if a buffer was provided, go back and fill in the actual size + if(buffer != NULL) + UINT16_TO_BYTE_ARRAY((result - 2), (*buffer - result)); + return result; +} + +// Table 2:208 - Definition of _PRIVATE Structure +// Table 2:209 - Definition of TPM2B_PRIVATE Structure +TPM_RC +TPM2B_PRIVATE_Unmarshal(TPM2B_PRIVATE* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT16_Unmarshal((UINT16*)&(target->t.size), buffer, size); + if(result == TPM_RC_SUCCESS) + { + if((target->t.size) > sizeof(_PRIVATE)) + result = TPM_RC_SIZE; + else + result = BYTE_Array_Unmarshal( + (BYTE*)(target->t.buffer), buffer, size, (INT32)(target->t.size)); + } + return result; +} +UINT16 +TPM2B_PRIVATE_Marshal(TPM2B_PRIVATE* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT16_Marshal((UINT16*)&(source->t.size), buffer, size)); + // if size equal to 0, the rest of the structure is a zero buffer. Stop processing + if(source->t.size == 0) + return result; + result = (UINT16)(result + + BYTE_Array_Marshal((BYTE*)(source->t.buffer), + buffer, + size, + (INT32)(source->t.size))); + return result; +} + +// Table 2:210 - Definition of TPMS_ID_OBJECT Structure +// Table 2:211 - Definition of TPM2B_ID_OBJECT Structure +TPM_RC +TPM2B_ID_OBJECT_Unmarshal(TPM2B_ID_OBJECT* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT16_Unmarshal((UINT16*)&(target->t.size), buffer, size); + if(result == TPM_RC_SUCCESS) + { + if((target->t.size) > sizeof(TPMS_ID_OBJECT)) + result = TPM_RC_SIZE; + else + result = BYTE_Array_Unmarshal( + (BYTE*)(target->t.credential), buffer, size, (INT32)(target->t.size)); + } + return result; +} +UINT16 +TPM2B_ID_OBJECT_Marshal(TPM2B_ID_OBJECT* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT16_Marshal((UINT16*)&(source->t.size), buffer, size)); + // if size equal to 0, the rest of the structure is a zero buffer. Stop processing + if(source->t.size == 0) + return result; + result = (UINT16)(result + + BYTE_Array_Marshal((BYTE*)(source->t.credential), + buffer, + size, + (INT32)(source->t.size))); + return result; +} + +// Table 2:212 - Definition of TPM_NV_INDEX Bits +# if !USE_MARSHALING_DEFINES +UINT16 +TPM_NV_INDEX_Marshal(TPM_NV_INDEX* source, BYTE** buffer, INT32* size) +{ + return UINT32_Marshal((UINT32*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:213 - Definition of TPM_NT Constants +// Table 2:214 - Definition of TPMS_NV_PIN_COUNTER_PARAMETERS Structure +TPM_RC +TPMS_NV_PIN_COUNTER_PARAMETERS_Unmarshal( + TPMS_NV_PIN_COUNTER_PARAMETERS* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT32_Unmarshal((UINT32*)&(target->pinCount), buffer, size); + if(result == TPM_RC_SUCCESS) + result = UINT32_Unmarshal((UINT32*)&(target->pinLimit), buffer, size); + return result; +} +UINT16 +TPMS_NV_PIN_COUNTER_PARAMETERS_Marshal( + TPMS_NV_PIN_COUNTER_PARAMETERS* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT32_Marshal((UINT32*)&(source->pinCount), buffer, size)); + result = + (UINT16)(result + UINT32_Marshal((UINT32*)&(source->pinLimit), buffer, size)); + return result; +} + +// Table 2:215 - Definition of TPMA_NV Bits +TPM_RC +TPMA_NV_Unmarshal(TPMA_NV* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT32_Unmarshal((UINT32*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + if(*((UINT32*)target) & (UINT32)0x01f00300) + result = TPM_RC_RESERVED_BITS; + } + return result; +} + +# if !USE_MARSHALING_DEFINES +UINT16 +TPMA_NV_Marshal(TPMA_NV* source, BYTE** buffer, INT32* size) +{ + return UINT32_Marshal((UINT32*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:216 - Definition of TPMS_NV_PUBLIC Structure +TPM_RC +TPMS_NV_PUBLIC_Unmarshal(TPMS_NV_PUBLIC* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = TPMI_RH_NV_INDEX_Unmarshal( + (TPMI_RH_NV_INDEX*)&(target->nvIndex), buffer, size); + if(result == TPM_RC_SUCCESS) + result = TPMI_ALG_HASH_Unmarshal( + (TPMI_ALG_HASH*)&(target->nameAlg), buffer, size, 0); + if(result == TPM_RC_SUCCESS) + result = TPMA_NV_Unmarshal((TPMA_NV*)&(target->attributes), buffer, size); + if(result == TPM_RC_SUCCESS) + result = TPM2B_DIGEST_Unmarshal( + (TPM2B_DIGEST*)&(target->authPolicy), buffer, size); + if(result == TPM_RC_SUCCESS) + result = UINT16_Unmarshal((UINT16*)&(target->dataSize), buffer, size); + if((result == TPM_RC_SUCCESS) && (target->dataSize > MAX_NV_INDEX_SIZE)) + result = TPM_RC_SIZE; + return result; +} +UINT16 +TPMS_NV_PUBLIC_Marshal(TPMS_NV_PUBLIC* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = (UINT16)(result + + TPMI_RH_NV_INDEX_Marshal( + (TPMI_RH_NV_INDEX*)&(source->nvIndex), buffer, size)); + result = (UINT16)(result + + TPMI_ALG_HASH_Marshal( + (TPMI_ALG_HASH*)&(source->nameAlg), buffer, size)); + result = + (UINT16)(result + + TPMA_NV_Marshal((TPMA_NV*)&(source->attributes), buffer, size)); + result = (UINT16)(result + + TPM2B_DIGEST_Marshal( + (TPM2B_DIGEST*)&(source->authPolicy), buffer, size)); + result = + (UINT16)(result + UINT16_Marshal((UINT16*)&(source->dataSize), buffer, size)); + return result; +} + +// Table 2:217 - Definition of TPM2B_NV_PUBLIC Structure +TPM_RC +TPM2B_NV_PUBLIC_Unmarshal(TPM2B_NV_PUBLIC* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT16_Unmarshal((UINT16*)&(target->size), buffer, size); // =a + if(result == TPM_RC_SUCCESS) + { + // if size is zero, then the required structure is missing + if(target->size == 0) + result = TPM_RC_SIZE; + else + { + INT32 startSize = *size; + result = TPMS_NV_PUBLIC_Unmarshal( + (TPMS_NV_PUBLIC*)&(target->nvPublic), buffer, size); // =b + if(result == TPM_RC_SUCCESS) + { + if(target->size != (startSize - *size)) + result = TPM_RC_SIZE; + } + } + } + return result; +} +UINT16 +TPM2B_NV_PUBLIC_Marshal(TPM2B_NV_PUBLIC* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + // Marshal a dummy value of the 2B size. This makes sure that 'buffer' + // and 'size' are advanced as necessary (i.e., if they are present) + result = UINT16_Marshal(&result, buffer, size); + // Marshal the structure + result = (UINT16)(result + + TPMS_NV_PUBLIC_Marshal( + (TPMS_NV_PUBLIC*)&(source->nvPublic), buffer, size)); + // if a buffer was provided, go back and fill in the actual size + if(buffer != NULL) + UINT16_TO_BYTE_ARRAY((result - 2), (*buffer - result)); + return result; +} + +// Table 2:218 - Definition of TPM2B_CONTEXT_SENSITIVE Structure +TPM_RC +TPM2B_CONTEXT_SENSITIVE_Unmarshal( + TPM2B_CONTEXT_SENSITIVE* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT16_Unmarshal((UINT16*)&(target->t.size), buffer, size); + if(result == TPM_RC_SUCCESS) + { + if((target->t.size) > MAX_CONTEXT_SIZE) + result = TPM_RC_SIZE; + else + result = BYTE_Array_Unmarshal( + (BYTE*)(target->t.buffer), buffer, size, (INT32)(target->t.size)); + } + return result; +} +UINT16 +TPM2B_CONTEXT_SENSITIVE_Marshal( + TPM2B_CONTEXT_SENSITIVE* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT16_Marshal((UINT16*)&(source->t.size), buffer, size)); + // if size equal to 0, the rest of the structure is a zero buffer. Stop processing + if(source->t.size == 0) + return result; + result = (UINT16)(result + + BYTE_Array_Marshal((BYTE*)(source->t.buffer), + buffer, + size, + (INT32)(source->t.size))); + return result; +} + +// Table 2:219 - Definition of TPMS_CONTEXT_DATA Structure +TPM_RC +TPMS_CONTEXT_DATA_Unmarshal(TPMS_CONTEXT_DATA* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = + TPM2B_DIGEST_Unmarshal((TPM2B_DIGEST*)&(target->integrity), buffer, size); + if(result == TPM_RC_SUCCESS) + result = TPM2B_CONTEXT_SENSITIVE_Unmarshal( + (TPM2B_CONTEXT_SENSITIVE*)&(target->encrypted), buffer, size); + return result; +} +UINT16 +TPMS_CONTEXT_DATA_Marshal(TPMS_CONTEXT_DATA* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = (UINT16)(result + + TPM2B_DIGEST_Marshal( + (TPM2B_DIGEST*)&(source->integrity), buffer, size)); + result = + (UINT16)(result + + TPM2B_CONTEXT_SENSITIVE_Marshal( + (TPM2B_CONTEXT_SENSITIVE*)&(source->encrypted), buffer, size)); + return result; +} + +// Table 2:220 - Definition of TPM2B_CONTEXT_DATA Structure +TPM_RC +TPM2B_CONTEXT_DATA_Unmarshal(TPM2B_CONTEXT_DATA* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT16_Unmarshal((UINT16*)&(target->t.size), buffer, size); + if(result == TPM_RC_SUCCESS) + { + if((target->t.size) > sizeof(TPMS_CONTEXT_DATA)) + result = TPM_RC_SIZE; + else + result = BYTE_Array_Unmarshal( + (BYTE*)(target->t.buffer), buffer, size, (INT32)(target->t.size)); + } + return result; +} +UINT16 +TPM2B_CONTEXT_DATA_Marshal(TPM2B_CONTEXT_DATA* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT16_Marshal((UINT16*)&(source->t.size), buffer, size)); + // if size equal to 0, the rest of the structure is a zero buffer. Stop processing + if(source->t.size == 0) + return result; + result = (UINT16)(result + + BYTE_Array_Marshal((BYTE*)(source->t.buffer), + buffer, + size, + (INT32)(source->t.size))); + return result; +} + +// Table 2:221 - Definition of TPMS_CONTEXT Structure +TPM_RC +TPMS_CONTEXT_Unmarshal(TPMS_CONTEXT* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT64_Unmarshal((UINT64*)&(target->sequence), buffer, size); + if(result == TPM_RC_SUCCESS) + result = TPMI_DH_SAVED_Unmarshal( + (TPMI_DH_SAVED*)&(target->savedHandle), buffer, size); + if(result == TPM_RC_SUCCESS) + result = TPMI_RH_HIERARCHY_Unmarshal( + (TPMI_RH_HIERARCHY*)&(target->hierarchy), buffer, size, 1); + if(result == TPM_RC_SUCCESS) + result = TPM2B_CONTEXT_DATA_Unmarshal( + (TPM2B_CONTEXT_DATA*)&(target->contextBlob), buffer, size); + return result; +} +UINT16 +TPMS_CONTEXT_Marshal(TPMS_CONTEXT* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT64_Marshal((UINT64*)&(source->sequence), buffer, size)); + result = (UINT16)(result + + TPMI_DH_SAVED_Marshal( + (TPMI_DH_SAVED*)&(source->savedHandle), buffer, size)); + result = (UINT16)(result + + TPMI_RH_HIERARCHY_Marshal( + (TPMI_RH_HIERARCHY*)&(source->hierarchy), buffer, size)); + result = (UINT16)(result + + TPM2B_CONTEXT_DATA_Marshal( + (TPM2B_CONTEXT_DATA*)&(source->contextBlob), buffer, size)); + return result; +} + +// Table 2:223 - Definition of TPMS_CREATION_DATA Structure +UINT16 +TPMS_CREATION_DATA_Marshal(TPMS_CREATION_DATA* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = (UINT16)(result + + TPML_PCR_SELECTION_Marshal( + (TPML_PCR_SELECTION*)&(source->pcrSelect), buffer, size)); + result = (UINT16)(result + + TPM2B_DIGEST_Marshal( + (TPM2B_DIGEST*)&(source->pcrDigest), buffer, size)); + result = (UINT16)(result + + TPMA_LOCALITY_Marshal( + (TPMA_LOCALITY*)&(source->locality), buffer, size)); + result = (UINT16)(result + + TPM_ALG_ID_Marshal( + (TPM_ALG_ID*)&(source->parentNameAlg), buffer, size)); + result = (UINT16)(result + + TPM2B_NAME_Marshal( + (TPM2B_NAME*)&(source->parentName), buffer, size)); + result = (UINT16)(result + + TPM2B_NAME_Marshal( + (TPM2B_NAME*)&(source->parentQualifiedName), buffer, size)); + result = (UINT16)(result + + TPM2B_DATA_Marshal( + (TPM2B_DATA*)&(source->outsideInfo), buffer, size)); + return result; +} + +// Table 2:224 - Definition of TPM2B_CREATION_DATA Structure +UINT16 +TPM2B_CREATION_DATA_Marshal(TPM2B_CREATION_DATA* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + // Marshal a dummy value of the 2B size. This makes sure that 'buffer' + // and 'size' are advanced as necessary (i.e., if they are present) + result = UINT16_Marshal(&result, buffer, size); + // Marshal the structure + result = + (UINT16)(result + + TPMS_CREATION_DATA_Marshal( + (TPMS_CREATION_DATA*)&(source->creationData), buffer, size)); + // if a buffer was provided, go back and fill in the actual size + if(buffer != NULL) + UINT16_TO_BYTE_ARRAY((result - 2), (*buffer - result)); + return result; +} + +// Table 2:225 - Definition of TPM_AT Constants +TPM_RC +TPM_AT_Unmarshal(TPM_AT* target, BYTE** buffer, INT32* size) +{ + TPM_RC result; + result = UINT32_Unmarshal((UINT32*)target, buffer, size); + if(result == TPM_RC_SUCCESS) + { + switch(*target) + { + case TPM_AT_ANY: + case TPM_AT_ERROR: + case TPM_AT_PV1: + case TPM_AT_VEND: + break; + default: + result = TPM_RC_VALUE; + break; + } + } + return result; +} +# if !USE_MARSHALING_DEFINES +UINT16 +TPM_AT_Marshal(TPM_AT* source, BYTE** buffer, INT32* size) +{ + return UINT32_Marshal((UINT32*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:226 - Definition of TPM_AE Constants +# if !USE_MARSHALING_DEFINES +UINT16 +TPM_AE_Marshal(TPM_AE* source, BYTE** buffer, INT32* size) +{ + return UINT32_Marshal((UINT32*)source, buffer, size); +} +# endif // !USE_MARSHALING_DEFINES + +// Table 2:227 - Definition of TPMS_AC_OUTPUT Structure +UINT16 +TPMS_AC_OUTPUT_Marshal(TPMS_AC_OUTPUT* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = (UINT16)(result + TPM_AT_Marshal((TPM_AT*)&(source->tag), buffer, size)); + result = + (UINT16)(result + UINT32_Marshal((UINT32*)&(source->data), buffer, size)); + return result; +} + +// Table 2:228 - Definition of TPML_AC_CAPABILITIES Structure +UINT16 +TPML_AC_CAPABILITIES_Marshal(TPML_AC_CAPABILITIES* source, BYTE** buffer, INT32* size) +{ + UINT16 result = 0; + result = + (UINT16)(result + UINT32_Marshal((UINT32*)&(source->count), buffer, size)); + result = (UINT16)(result + + TPMS_AC_OUTPUT_Array_Marshal( + (TPMS_AC_OUTPUT*)(source->acCapabilities), + buffer, + size, + (INT32)(source->count))); + return result; +} + +// Array Marshal/Unmarshal for BYTE +TPM_RC +BYTE_Array_Unmarshal(BYTE* target, BYTE** buffer, INT32* size, INT32 count) +{ + if(*size < count) + return TPM_RC_INSUFFICIENT; + memcpy(target, *buffer, count); + *size -= count; + *buffer += count; + return TPM_RC_SUCCESS; +} +UINT16 +BYTE_Array_Marshal(BYTE* source, BYTE** buffer, INT32* size, INT32 count) +{ + if(buffer != 0) + { + if((size == 0) || ((*size -= count) >= 0)) + { + memcpy(*buffer, source, count); + *buffer += count; + } + pAssert(size == 0 || (*size >= 0)); + } + pAssert(count < INT16_MAX); + return ((UINT16)count); +} + +// Array Marshal/Unmarshal for TPM2B_DIGEST +TPM_RC +TPM2B_DIGEST_Array_Unmarshal( + TPM2B_DIGEST* target, BYTE** buffer, INT32* size, INT32 count) +{ + TPM_RC result; + INT32 i; + for(result = TPM_RC_SUCCESS, i = 0; ((result == TPM_RC_SUCCESS) && (i < count)); + i++) + { + result = TPM2B_DIGEST_Unmarshal(&target[i], buffer, size); + } + return result; +} +UINT16 +TPM2B_DIGEST_Array_Marshal( + TPM2B_DIGEST* source, BYTE** buffer, INT32* size, INT32 count) +{ + UINT16 result = 0; + INT32 i; + for(i = 0; i < count; i++) + { + result = (UINT16)(result + TPM2B_DIGEST_Marshal(&source[i], buffer, size)); + } + return result; +} + +// Array Marshal for TPMA_CC +UINT16 +TPMA_CC_Array_Marshal(TPMA_CC* source, BYTE** buffer, INT32* size, INT32 count) +{ + UINT16 result = 0; + INT32 i; + for(i = 0; i < count; i++) + { + result = (UINT16)(result + TPMA_CC_Marshal(&source[i], buffer, size)); + } + return result; +} + +// Array Marshal for TPMS_ACT_DATA +UINT16 +TPMS_ACT_DATA_Array_Marshal( + TPMS_ACT_DATA* source, BYTE** buffer, INT32* size, INT32 count) +{ + UINT16 result = 0; + INT32 i; + for(i = 0; i < count; i++) + { + result = (UINT16)(result + TPMS_ACT_DATA_Marshal(&source[i], buffer, size)); + } + return result; +} + +// Array Marshal for TPMS_AC_OUTPUT +UINT16 +TPMS_AC_OUTPUT_Array_Marshal( + TPMS_AC_OUTPUT* source, BYTE** buffer, INT32* size, INT32 count) +{ + UINT16 result = 0; + INT32 i; + for(i = 0; i < count; i++) + { + result = (UINT16)(result + TPMS_AC_OUTPUT_Marshal(&source[i], buffer, size)); + } + return result; +} + +// Array Marshal for TPMS_ALG_PROPERTY +UINT16 +TPMS_ALG_PROPERTY_Array_Marshal( + TPMS_ALG_PROPERTY* source, BYTE** buffer, INT32* size, INT32 count) +{ + UINT16 result = 0; + INT32 i; + for(i = 0; i < count; i++) + { + result = + (UINT16)(result + TPMS_ALG_PROPERTY_Marshal(&source[i], buffer, size)); + } + return result; +} + +// Array Marshal/Unmarshal for TPMS_PCR_SELECTION +TPM_RC +TPMS_PCR_SELECTION_Array_Unmarshal( + TPMS_PCR_SELECTION* target, BYTE** buffer, INT32* size, INT32 count) +{ + TPM_RC result; + INT32 i; + for(result = TPM_RC_SUCCESS, i = 0; ((result == TPM_RC_SUCCESS) && (i < count)); + i++) + { + result = TPMS_PCR_SELECTION_Unmarshal(&target[i], buffer, size); + } + return result; +} +UINT16 +TPMS_PCR_SELECTION_Array_Marshal( + TPMS_PCR_SELECTION* source, BYTE** buffer, INT32* size, INT32 count) +{ + UINT16 result = 0; + INT32 i; + for(i = 0; i < count; i++) + { + result = + (UINT16)(result + TPMS_PCR_SELECTION_Marshal(&source[i], buffer, size)); + } + return result; +} + +// Array Marshal for TPMS_TAGGED_PCR_SELECT +UINT16 +TPMS_TAGGED_PCR_SELECT_Array_Marshal( + TPMS_TAGGED_PCR_SELECT* source, BYTE** buffer, INT32* size, INT32 count) +{ + UINT16 result = 0; + INT32 i; + for(i = 0; i < count; i++) + { + result = (UINT16)(result + + TPMS_TAGGED_PCR_SELECT_Marshal(&source[i], buffer, size)); + } + return result; +} + +// Array Marshal for TPMS_TAGGED_POLICY +UINT16 +TPMS_TAGGED_POLICY_Array_Marshal( + TPMS_TAGGED_POLICY* source, BYTE** buffer, INT32* size, INT32 count) +{ + UINT16 result = 0; + INT32 i; + for(i = 0; i < count; i++) + { + result = + (UINT16)(result + TPMS_TAGGED_POLICY_Marshal(&source[i], buffer, size)); + } + return result; +} + +// Array Marshal for TPMS_TAGGED_PROPERTY +UINT16 +TPMS_TAGGED_PROPERTY_Array_Marshal( + TPMS_TAGGED_PROPERTY* source, BYTE** buffer, INT32* size, INT32 count) +{ + UINT16 result = 0; + INT32 i; + for(i = 0; i < count; i++) + { + result = + (UINT16)(result + TPMS_TAGGED_PROPERTY_Marshal(&source[i], buffer, size)); + } + return result; +} + +// Array Marshal/Unmarshal for TPMT_HA +TPM_RC +TPMT_HA_Array_Unmarshal( + TPMT_HA* target, BYTE** buffer, INT32* size, BOOL flag, INT32 count) +{ + TPM_RC result; + INT32 i; + for(result = TPM_RC_SUCCESS, i = 0; ((result == TPM_RC_SUCCESS) && (i < count)); + i++) + { + result = TPMT_HA_Unmarshal(&target[i], buffer, size, flag); + } + return result; +} +UINT16 +TPMT_HA_Array_Marshal(TPMT_HA* source, BYTE** buffer, INT32* size, INT32 count) +{ + UINT16 result = 0; + INT32 i; + for(i = 0; i < count; i++) + { + result = (UINT16)(result + TPMT_HA_Marshal(&source[i], buffer, size)); + } + return result; +} + +// Array Marshal/Unmarshal for TPM_ALG_ID +TPM_RC +TPM_ALG_ID_Array_Unmarshal( + TPM_ALG_ID* target, BYTE** buffer, INT32* size, INT32 count) +{ + TPM_RC result; + INT32 i; + for(result = TPM_RC_SUCCESS, i = 0; ((result == TPM_RC_SUCCESS) && (i < count)); + i++) + { + result = TPM_ALG_ID_Unmarshal(&target[i], buffer, size); + } + return result; +} +UINT16 +TPM_ALG_ID_Array_Marshal(TPM_ALG_ID* source, BYTE** buffer, INT32* size, INT32 count) +{ + UINT16 result = 0; + INT32 i; + for(i = 0; i < count; i++) + { + result = (UINT16)(result + TPM_ALG_ID_Marshal(&source[i], buffer, size)); + } + return result; +} + +// Array Marshal/Unmarshal for TPM_CC +TPM_RC +TPM_CC_Array_Unmarshal(TPM_CC* target, BYTE** buffer, INT32* size, INT32 count) +{ + TPM_RC result; + INT32 i; + for(result = TPM_RC_SUCCESS, i = 0; ((result == TPM_RC_SUCCESS) && (i < count)); + i++) + { + result = TPM_CC_Unmarshal(&target[i], buffer, size); + } + return result; +} +UINT16 +TPM_CC_Array_Marshal(TPM_CC* source, BYTE** buffer, INT32* size, INT32 count) +{ + UINT16 result = 0; + INT32 i; + for(i = 0; i < count; i++) + { + result = (UINT16)(result + TPM_CC_Marshal(&source[i], buffer, size)); + } + return result; +} + +// Array Marshal/Unmarshal for TPM_ECC_CURVE +# if ALG_ECC +TPM_RC +TPM_ECC_CURVE_Array_Unmarshal( + TPM_ECC_CURVE* target, BYTE** buffer, INT32* size, INT32 count) +{ + TPM_RC result; + INT32 i; + for(result = TPM_RC_SUCCESS, i = 0; ((result == TPM_RC_SUCCESS) && (i < count)); + i++) + { + result = TPM_ECC_CURVE_Unmarshal(&target[i], buffer, size); + } + return result; +} +UINT16 +TPM_ECC_CURVE_Array_Marshal( + TPM_ECC_CURVE* source, BYTE** buffer, INT32* size, INT32 count) +{ + UINT16 result = 0; + INT32 i; + for(i = 0; i < count; i++) + { + result = (UINT16)(result + TPM_ECC_CURVE_Marshal(&source[i], buffer, size)); + } + return result; +} +# endif // ALG_ECC + +// Array Marshal/Unmarshal for TPM_HANDLE +TPM_RC +TPM_HANDLE_Array_Unmarshal( + TPM_HANDLE* target, BYTE** buffer, INT32* size, INT32 count) +{ + TPM_RC result; + INT32 i; + for(result = TPM_RC_SUCCESS, i = 0; ((result == TPM_RC_SUCCESS) && (i < count)); + i++) + { + result = TPM_HANDLE_Unmarshal(&target[i], buffer, size); + } + return result; +} +UINT16 +TPM_HANDLE_Array_Marshal(TPM_HANDLE* source, BYTE** buffer, INT32* size, INT32 count) +{ + UINT16 result = 0; + INT32 i; + for(i = 0; i < count; i++) + { + result = (UINT16)(result + TPM_HANDLE_Marshal(&source[i], buffer, size)); + } + return result; +} + +#endif // !TABLE_DRIVEN_MARSHAL diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/MathOnByteBuffers.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/MathOnByteBuffers.c new file mode 100644 index 0000000..9ef2064 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/MathOnByteBuffers.c @@ -0,0 +1,240 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Introduction +// +// This file contains implementation of the math functions that are performed +// with canonical integers in byte buffers. The canonical integer is +// big-endian bytes. +// +#include "Tpm.h" + +//** Functions + +//*** UnsignedCmpB +// This function compare two unsigned values. The values are byte-aligned, +// big-endian numbers (e.g, a hash). +// Return Type: int +// 1 if (a > b) +// 0 if (a = b) +// -1 if (a < b) +LIB_EXPORT int UnsignedCompareB(UINT32 aSize, // IN: size of a + const BYTE* a, // IN: a + UINT32 bSize, // IN: size of b + const BYTE* b // IN: b +) +{ + UINT32 i; + if(aSize > bSize) + return 1; + else if(aSize < bSize) + return -1; + else + { + for(i = 0; i < aSize; i++) + { + if(a[i] != b[i]) + return (a[i] > b[i]) ? 1 : -1; + } + } + // Will return == if sizes are both zero + return 0; +} + +//***SignedCompareB() +// Compare two signed integers: +// Return Type: int +// 1 if a > b +// 0 if a = b +// -1 if a < b +int SignedCompareB(const UINT32 aSize, // IN: size of a + const BYTE* a, // IN: a buffer + const UINT32 bSize, // IN: size of b + const BYTE* b // IN: b buffer +) +{ + // are the signs different ? + if(((a[0] ^ b[0]) & 0x80) > 0) + // if the signs are different, then a is less than b if a is negative. + return a[0] & 0x80 ? -1 : 1; + else + // do unsigned compare function + return UnsignedCompareB(aSize, a, bSize, b); +} + +//*** ModExpB +// This function is used to do modular exponentiation in support of RSA. +// The most typical uses are: 'c' = 'm'^'e' mod 'n' (RSA encrypt) and +// 'm' = 'c'^'d' mod 'n' (RSA decrypt). When doing decryption, the 'e' parameter +// of the function will contain the private exponent 'd' instead of the public +// exponent 'e'. +// +// If the results will not fit in the provided buffer, +// an error is returned (CRYPT_ERROR_UNDERFLOW). If the results is smaller +// than the buffer, the results is de-normalized. +// +// This version is intended for use with RSA and requires that 'm' be +// less than 'n'. +// +// Return Type: TPM_RC +// TPM_RC_SIZE number to exponentiate is larger than the modulus +// TPM_RC_NO_RESULT result will not fit into the provided buffer +// +TPM_RC +ModExpB(UINT32 cSize, // IN: the size of the output buffer. It will + // need to be the same size as the modulus + BYTE* c, // OUT: the buffer to receive the results + // (c->size must be set to the maximum size + // for the returned value) + const UINT32 mSize, + const BYTE* m, // IN: number to exponentiate + const UINT32 eSize, + const BYTE* e, // IN: power + const UINT32 nSize, + const BYTE* n // IN: modulus +) +{ + BN_MAX(bnC); + BN_MAX(bnM); + BN_MAX(bnE); + BN_MAX(bnN); + NUMBYTES tSize = (NUMBYTES)nSize; + TPM_RC retVal = TPM_RC_SUCCESS; + + // Convert input parameters + BnFromBytes(bnM, m, (NUMBYTES)mSize); + BnFromBytes(bnE, e, (NUMBYTES)eSize); + BnFromBytes(bnN, n, (NUMBYTES)nSize); + + // Make sure that the output is big enough to hold the result + // and that 'm' is less than 'n' (the modulus) + if(cSize < nSize) + ERROR_RETURN(TPM_RC_NO_RESULT); + if(BnUnsignedCmp(bnM, bnN) >= 0) + ERROR_RETURN(TPM_RC_SIZE); + BnModExp(bnC, bnM, bnE, bnN); + BnToBytes(bnC, c, &tSize); +Exit: + return retVal; +} + +//*** DivideB() +// Divide an integer ('n') by an integer ('d') producing a quotient ('q') and +// a remainder ('r'). If 'q' or 'r' is not needed, then the pointer to them +// may be set to NULL. +// +// Return Type: TPM_RC +// TPM_RC_NO_RESULT 'q' or 'r' is too small to receive the result +// +LIB_EXPORT TPM_RC DivideB(const TPM2B* n, // IN: numerator + const TPM2B* d, // IN: denominator + TPM2B* q, // OUT: quotient + TPM2B* r // OUT: remainder +) +{ + BN_MAX_INITIALIZED(bnN, n); + BN_MAX_INITIALIZED(bnD, d); + BN_MAX(bnQ); + BN_MAX(bnR); + // + // Do divide with converted values + BnDiv(bnQ, bnR, bnN, bnD); + + // Convert the BIGNUM result back to 2B format using the size of the original + // number + if(q != NULL) + if(!BnTo2B(bnQ, q, q->size)) + return TPM_RC_NO_RESULT; + if(r != NULL) + if(!BnTo2B(bnR, r, r->size)) + return TPM_RC_NO_RESULT; + return TPM_RC_SUCCESS; +} + +//*** AdjustNumberB() +// Remove/add leading zeros from a number in a TPM2B. Will try to make the number +// by adding or removing leading zeros. If the number is larger than the requested +// size, it will make the number as small as possible. Setting 'requestedSize' to +// zero is equivalent to requesting that the number be normalized. +UINT16 +AdjustNumberB(TPM2B* num, UINT16 requestedSize) +{ + BYTE* from; + UINT16 i; + // See if number is already the requested size + if(num->size == requestedSize) + return requestedSize; + from = num->buffer; + if(num->size > requestedSize) + { + // This is a request to shift the number to the left (remove leading zeros) + // Find the first non-zero byte. Don't look past the point where removing + // more zeros would make the number smaller than requested, and don't throw + // away any significant digits. + for(i = num->size; *from == 0 && i > requestedSize; from++, i--) + ; + if(i < num->size) + { + num->size = i; + MemoryCopy(num->buffer, from, i); + } + } + // This is a request to shift the number to the right (add leading zeros) + else + { + MemoryCopy(&num->buffer[requestedSize - num->size], num->buffer, num->size); + MemorySet(num->buffer, 0, requestedSize - num->size); + num->size = requestedSize; + } + return num->size; +} + +//*** ShiftLeft() +// This function shifts a byte buffer (a TPM2B) one byte to the left. That is, +// the most significant bit of the most significant byte is lost. +TPM2B* ShiftLeft(TPM2B* value // IN/OUT: value to shift and shifted value out +) +{ + UINT16 count = value->size; + BYTE* buffer = value->buffer; + if(count > 0) + { + for(count -= 1; count > 0; buffer++, count--) + { + buffer[0] = (buffer[0] << 1) + ((buffer[1] & 0x80) ? 1 : 0); + } + *buffer <<= 1; + } + return value; +} diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Memory.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Memory.c new file mode 100644 index 0000000..2cc9081 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Memory.c @@ -0,0 +1,231 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Description +// This file contains a set of miscellaneous memory manipulation routines. Many +// of the functions have the same semantics as functions defined in string.h. +// Those functions are not used directly in the TPM because they are not 'safe' +// +// This version uses string.h after adding guards. This is because the math +// libraries invariably use those functions so it is not practical to prevent +// those library functions from being pulled into the build. + +//** Includes and Data Definitions +#include "Tpm.h" +#include "Memory_fp.h" + +//** Functions + +//*** MemoryCopy() +// This is an alias for memmove. This is used in place of memcpy because +// some of the moves may overlap and rather than try to make sure that +// memmove is used when necessary, it is always used. +void MemoryCopy(void* dest, const void* src, int sSize) +{ + if(dest != src) + memmove(dest, src, sSize); +} + +//*** MemoryEqual() +// This function indicates if two buffers have the same values in the indicated +// number of bytes. +// Return Type: BOOL +// TRUE(1) all octets are the same +// FALSE(0) all octets are not the same +BOOL MemoryEqual(const void* buffer1, // IN: compare buffer1 + const void* buffer2, // IN: compare buffer2 + unsigned int size // IN: size of bytes being compared +) +{ + BYTE equal = 0; + const BYTE* b1 = (BYTE*)buffer1; + const BYTE* b2 = (BYTE*)buffer2; + // + // Compare all bytes so that there is no leakage of information + // due to timing differences. + for(; size > 0; size--) + equal |= (*b1++ ^ *b2++); + return (equal == 0); +} + +//*** MemoryCopy2B() +// This function copies a TPM2B. This can be used when the TPM2B types are +// the same or different. +// +// This function returns the number of octets in the data buffer of the TPM2B. +LIB_EXPORT INT16 MemoryCopy2B(TPM2B* dest, // OUT: receiving TPM2B + const TPM2B* source, // IN: source TPM2B + unsigned int dSize // IN: size of the receiving buffer +) +{ + pAssert(dest != NULL); + if(source == NULL) + dest->size = 0; + else + { + pAssert(source->size <= dSize); + MemoryCopy(dest->buffer, source->buffer, source->size); + dest->size = source->size; + } + return dest->size; +} + +//*** MemoryConcat2B() +// This function will concatenate the buffer contents of a TPM2B to +// the buffer contents of another TPM2B and adjust the size accordingly +// ('a' := ('a' | 'b')). +void MemoryConcat2B( + TPM2B* aInOut, // IN/OUT: destination 2B + TPM2B* bIn, // IN: second 2B + unsigned int aMaxSize // IN: The size of aInOut.buffer (max values for + // aInOut.size) +) +{ + pAssert(bIn->size <= aMaxSize - aInOut->size); + MemoryCopy(&aInOut->buffer[aInOut->size], &bIn->buffer, bIn->size); + aInOut->size = aInOut->size + bIn->size; + return; +} + +//*** MemoryEqual2B() +// This function will compare two TPM2B structures. To be equal, they +// need to be the same size and the buffer contexts need to be the same +// in all octets. +// Return Type: BOOL +// TRUE(1) size and buffer contents are the same +// FALSE(0) size or buffer contents are not the same +BOOL MemoryEqual2B(const TPM2B* aIn, // IN: compare value + const TPM2B* bIn // IN: compare value +) +{ + if(aIn->size != bIn->size) + return FALSE; + return MemoryEqual(aIn->buffer, bIn->buffer, aIn->size); +} + +//*** MemorySet() +// This function will set all the octets in the specified memory range to +// the specified octet value. +// Note: A previous version had an additional parameter (dSize) that was +// intended to make sure that the destination would not be overrun. The +// problem is that, in use, all that was happening was that the value of +// size was used for dSize so there was no benefit in the extra parameter. +void MemorySet(void* dest, int value, size_t size) +{ + memset(dest, value, size); +} + +//*** MemoryPad2B() +// Function to pad a TPM2B with zeros and adjust the size. +void MemoryPad2B(TPM2B* b, UINT16 newSize) +{ + MemorySet(&b->buffer[b->size], 0, newSize - b->size); + b->size = newSize; +} + +//*** Uint16ToByteArray() +// Function to write an integer to a byte array +void Uint16ToByteArray(UINT16 i, BYTE* a) +{ + a[1] = (BYTE)(i); + i >>= 8; + a[0] = (BYTE)(i); +} + +//*** Uint32ToByteArray() +// Function to write an integer to a byte array +void Uint32ToByteArray(UINT32 i, BYTE* a) +{ + a[3] = (BYTE)(i); + i >>= 8; + a[2] = (BYTE)(i); + i >>= 8; + a[1] = (BYTE)(i); + i >>= 8; + a[0] = (BYTE)(i); +} + +//*** Uint64ToByteArray() +// Function to write an integer to a byte array +void Uint64ToByteArray(UINT64 i, BYTE* a) +{ + a[7] = (BYTE)(i); + i >>= 8; + a[6] = (BYTE)(i); + i >>= 8; + a[5] = (BYTE)(i); + i >>= 8; + a[4] = (BYTE)(i); + i >>= 8; + a[3] = (BYTE)(i); + i >>= 8; + a[2] = (BYTE)(i); + i >>= 8; + a[1] = (BYTE)(i); + i >>= 8; + a[0] = (BYTE)(i); +} + +//*** ByteArrayToUint8() +// Function to write a UINT8 to a byte array. This is included for completeness +// and to allow certain macro expansions +UINT8 +ByteArrayToUint8(BYTE* a) +{ + return *a; +} + +//*** ByteArrayToUint16() +// Function to write an integer to a byte array +UINT16 +ByteArrayToUint16(BYTE* a) +{ + return ((UINT16)a[0] << 8) + a[1]; +} + +//*** ByteArrayToUint32() +// Function to write an integer to a byte array +UINT32 +ByteArrayToUint32(BYTE* a) +{ + return (UINT32)((((((UINT32)a[0] << 8) + a[1]) << 8) + (UINT32)a[2]) << 8) + a[3]; +} + +//*** ByteArrayToUint64() +// Function to write an integer to a byte array +UINT64 +ByteArrayToUint64(BYTE* a) +{ + return (((UINT64)BYTE_ARRAY_TO_UINT32(a)) << 32) + BYTE_ARRAY_TO_UINT32(&a[4]); +} diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Power.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Power.c new file mode 100644 index 0000000..e936cdf --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Power.c @@ -0,0 +1,73 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Description + +// This file contains functions that receive the simulated power state +// transitions of the TPM. + +//** Includes and Data Definitions +#define POWER_C +#include "Tpm.h" + +//** Functions + +//*** TPMInit() +// This function is used to process a power on event. +void TPMInit(void) +{ + // Set state as not initialized. This means that Startup is required + g_initialized = FALSE; + return; +} + +//*** TPMRegisterStartup() +// This function registers the fact that the TPM has been initialized +// (a TPM2_Startup() has completed successfully). +BOOL TPMRegisterStartup(void) +{ + g_initialized = TRUE; + return TRUE; +} + +//*** TPMIsStarted() +// Indicates if the TPM has been initialized (a TPM2_Startup() has completed +// successfully after a _TPM_Init). +// Return Type: BOOL +// TRUE(1) TPM has been initialized +// FALSE(0) TPM has not been initialized +BOOL TPMIsStarted(void) +{ + return g_initialized; +} diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/PropertyCap.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/PropertyCap.c new file mode 100644 index 0000000..02e45e4 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/PropertyCap.c @@ -0,0 +1,596 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Description +// This file contains the functions that are used for accessing the +// TPM_CAP_TPM_PROPERTY values. + +//** Includes + +#include "Tpm.h" + +//** Functions + +//*** TPMPropertyIsDefined() +// This function accepts a property selection and, if so, sets 'value' +// to the value of the property. +// +// All the fixed values are vendor dependent or determined by a +// platform-specific specification. The values in the table below +// are examples and should be changed by the vendor. +// Return Type: BOOL +// TRUE(1) referenced property exists and 'value' set +// FALSE(0) referenced property does not exist +static BOOL TPMPropertyIsDefined(TPM_PT property, // IN: property + UINT32* value // OUT: property value +) +{ + switch(property) + { + case TPM_PT_FAMILY_INDICATOR: + // from the title page of the specification + // For this specification, the value is "2.0". + *value = TPM_SPEC_FAMILY; + break; + case TPM_PT_LEVEL: + // from the title page of the specification + *value = TPM_SPEC_LEVEL; + break; + case TPM_PT_REVISION: + // from the title page of the specification + *value = TPM_SPEC_VERSION; + break; + case TPM_PT_DAY_OF_YEAR: + // computed from the date value on the title page of the specification + *value = TPM_SPEC_DAY_OF_YEAR; + break; + case TPM_PT_YEAR: + // from the title page of the specification + *value = TPM_SPEC_YEAR; + break; + case TPM_PT_MANUFACTURER: + // vendor ID unique to each TPM manufacturer + *value = BYTE_ARRAY_TO_UINT32(MANUFACTURER); + break; + case TPM_PT_VENDOR_STRING_1: + // first four characters of the vendor ID string + *value = BYTE_ARRAY_TO_UINT32(VENDOR_STRING_1); + break; + case TPM_PT_VENDOR_STRING_2: + // second four characters of the vendor ID string +#ifdef VENDOR_STRING_2 + *value = BYTE_ARRAY_TO_UINT32(VENDOR_STRING_2); +#else + *value = 0; +#endif + break; + case TPM_PT_VENDOR_STRING_3: + // third four characters of the vendor ID string +#ifdef VENDOR_STRING_3 + *value = BYTE_ARRAY_TO_UINT32(VENDOR_STRING_3); +#else + *value = 0; +#endif + break; + case TPM_PT_VENDOR_STRING_4: + // fourth four characters of the vendor ID string +#ifdef VENDOR_STRING_4 + *value = BYTE_ARRAY_TO_UINT32(VENDOR_STRING_4); +#else + *value = 0; +#endif + break; + case TPM_PT_VENDOR_TPM_TYPE: + // vendor-defined value indicating the TPM model + *value = 1; + break; + case TPM_PT_FIRMWARE_VERSION_1: + // more significant 32-bits of a vendor-specific value + *value = gp.firmwareV1; + break; + case TPM_PT_FIRMWARE_VERSION_2: + // less significant 32-bits of a vendor-specific value + *value = gp.firmwareV2; + break; + case TPM_PT_INPUT_BUFFER: + // maximum size of TPM2B_MAX_BUFFER + *value = MAX_DIGEST_BUFFER; + break; + case TPM_PT_HR_TRANSIENT_MIN: + // minimum number of transient objects that can be held in TPM + // RAM + *value = MAX_LOADED_OBJECTS; + break; + case TPM_PT_HR_PERSISTENT_MIN: + // minimum number of persistent objects that can be held in + // TPM NV memory + // In this implementation, there is no minimum number of + // persistent objects. + *value = MIN_EVICT_OBJECTS; + break; + case TPM_PT_HR_LOADED_MIN: + // minimum number of authorization sessions that can be held in + // TPM RAM + *value = MAX_LOADED_SESSIONS; + break; + case TPM_PT_ACTIVE_SESSIONS_MAX: + // number of authorization sessions that may be active at a time + *value = MAX_ACTIVE_SESSIONS; + break; + case TPM_PT_PCR_COUNT: + // number of PCR implemented + *value = IMPLEMENTATION_PCR; + break; + case TPM_PT_PCR_SELECT_MIN: + // minimum number of bytes in a TPMS_PCR_SELECT.sizeOfSelect + *value = PCR_SELECT_MIN; + break; + case TPM_PT_CONTEXT_GAP_MAX: + // maximum allowed difference (unsigned) between the contextID + // values of two saved session contexts + *value = ((UINT32)1 << (sizeof(CONTEXT_SLOT) * 8)) - 1; + break; + case TPM_PT_NV_COUNTERS_MAX: + // maximum number of NV indexes that are allowed to have the + // TPMA_NV_COUNTER attribute SET + // In this implementation, there is no limitation on the number + // of counters, except for the size of the NV Index memory. + *value = 0; + break; + case TPM_PT_NV_INDEX_MAX: + // maximum size of an NV index data area + *value = MAX_NV_INDEX_SIZE; + break; + case TPM_PT_MEMORY: + // a TPMA_MEMORY indicating the memory management method for the TPM + { + union + { + TPMA_MEMORY att; + UINT32 u32; + } attributes = {TPMA_ZERO_INITIALIZER()}; + SET_ATTRIBUTE(attributes.att, TPMA_MEMORY, sharedNV); + SET_ATTRIBUTE(attributes.att, TPMA_MEMORY, objectCopiedToRam); + + // Note: For a LSb0 machine, the bits in a bit field are in the correct + // order even if the machine is MSB0. For a MSb0 machine, a TPMA will + // be an integer manipulated by masking (USE_BIT_FIELD_STRUCTURES will + // be NO) so the bits are manipulate correctly. + *value = attributes.u32; + break; + } + case TPM_PT_CLOCK_UPDATE: + // interval, in seconds, between updates to the copy of + // TPMS_TIME_INFO .clock in NV + *value = (1 << NV_CLOCK_UPDATE_INTERVAL); + break; + case TPM_PT_CONTEXT_HASH: + // algorithm used for the integrity hash on saved contexts and + // for digesting the fuData of TPM2_FirmwareRead() + *value = CONTEXT_INTEGRITY_HASH_ALG; + break; + case TPM_PT_CONTEXT_SYM: + // algorithm used for encryption of saved contexts + *value = CONTEXT_ENCRYPT_ALG; + break; + case TPM_PT_CONTEXT_SYM_SIZE: + // size of the key used for encryption of saved contexts + *value = CONTEXT_ENCRYPT_KEY_BITS; + break; + case TPM_PT_ORDERLY_COUNT: + // maximum difference between the volatile and non-volatile + // versions of TPMA_NV_COUNTER that have TPMA_NV_ORDERLY SET + *value = MAX_ORDERLY_COUNT; + break; + case TPM_PT_MAX_COMMAND_SIZE: + // maximum value for 'commandSize' + *value = MAX_COMMAND_SIZE; + break; + case TPM_PT_MAX_RESPONSE_SIZE: + // maximum value for 'responseSize' + *value = MAX_RESPONSE_SIZE; + break; + case TPM_PT_MAX_DIGEST: + // maximum size of a digest that can be produced by the TPM + *value = sizeof(TPMU_HA); + break; + case TPM_PT_MAX_OBJECT_CONTEXT: +// Header has 'sequence', 'handle' and 'hierarchy' +#define SIZE_OF_CONTEXT_HEADER \ + sizeof(UINT64) + sizeof(TPMI_DH_CONTEXT) + sizeof(TPMI_RH_HIERARCHY) +#define SIZE_OF_CONTEXT_INTEGRITY (sizeof(UINT16) + CONTEXT_INTEGRITY_HASH_SIZE) +#define SIZE_OF_FINGERPRINT sizeof(UINT64) +#define SIZE_OF_CONTEXT_BLOB_OVERHEAD \ + (sizeof(UINT16) + SIZE_OF_CONTEXT_INTEGRITY + SIZE_OF_FINGERPRINT) +#define SIZE_OF_CONTEXT_OVERHEAD \ + (SIZE_OF_CONTEXT_HEADER + SIZE_OF_CONTEXT_BLOB_OVERHEAD) +#if 0 + // maximum size of a TPMS_CONTEXT that will be returned by + // TPM2_ContextSave for object context + *value = 0; + // adding sequence, saved handle and hierarchy + *value += sizeof(UINT64) + sizeof(TPMI_DH_CONTEXT) + + sizeof(TPMI_RH_HIERARCHY); + // add size field in TPM2B_CONTEXT + *value += sizeof(UINT16); + // add integrity hash size + *value += sizeof(UINT16) + + CryptHashGetDigestSize(CONTEXT_INTEGRITY_HASH_ALG); + // Add fingerprint size, which is the same as sequence size + *value += sizeof(UINT64); + // Add OBJECT structure size + *value += sizeof(OBJECT); +#else + // the maximum size of a TPMS_CONTEXT that will be returned by + // TPM2_ContextSave for object context + *value = SIZE_OF_CONTEXT_OVERHEAD + sizeof(OBJECT); +#endif + break; + case TPM_PT_MAX_SESSION_CONTEXT: +#if 0 + + // the maximum size of a TPMS_CONTEXT that will be returned by + // TPM2_ContextSave for object context + *value = 0; + // adding sequence, saved handle and hierarchy + *value += sizeof(UINT64) + sizeof(TPMI_DH_CONTEXT) + + sizeof(TPMI_RH_HIERARCHY); + // Add size field in TPM2B_CONTEXT + *value += sizeof(UINT16); +// Add integrity hash size + *value += sizeof(UINT16) + + CryptHashGetDigestSize(CONTEXT_INTEGRITY_HASH_ALG); + // Add fingerprint size, which is the same as sequence size + *value += sizeof(UINT64); + // Add SESSION structure size + *value += sizeof(SESSION); +#else + // the maximum size of a TPMS_CONTEXT that will be returned by + // TPM2_ContextSave for object context + *value = SIZE_OF_CONTEXT_OVERHEAD + sizeof(SESSION); +#endif + break; + case TPM_PT_PS_FAMILY_INDICATOR: + // platform specific values for the TPM_PT_PS parameters from + // the relevant platform-specific specification + // In this reference implementation, all of these values are 0. + *value = PLATFORM_FAMILY; + break; + case TPM_PT_PS_LEVEL: + // level of the platform-specific specification + *value = PLATFORM_LEVEL; + break; + case TPM_PT_PS_REVISION: + // specification Revision times 100 for the platform-specific + // specification + *value = PLATFORM_VERSION; + break; + case TPM_PT_PS_DAY_OF_YEAR: + // platform-specific specification day of year using TCG calendar + *value = PLATFORM_DAY_OF_YEAR; + break; + case TPM_PT_PS_YEAR: + // platform-specific specification year using the CE + *value = PLATFORM_YEAR; + break; + case TPM_PT_SPLIT_MAX: + // number of split signing operations supported by the TPM + *value = 0; +#if ALG_ECC + *value = sizeof(gr.commitArray) * 8; +#endif + break; + case TPM_PT_TOTAL_COMMANDS: + // total number of commands implemented in the TPM + // Since the reference implementation does not have any + // vendor-defined commands, this will be the same as the + // number of library commands. + { +#if COMPRESSED_LISTS + (*value) = COMMAND_COUNT; +#else + COMMAND_INDEX commandIndex; + *value = 0; + + // scan all implemented commands + for(commandIndex = GetClosestCommandIndex(0); + commandIndex != UNIMPLEMENTED_COMMAND_INDEX; + commandIndex = GetNextCommandIndex(commandIndex)) + { + (*value)++; // count of all implemented + } +#endif + break; + } + case TPM_PT_LIBRARY_COMMANDS: + // number of commands from the TPM library that are implemented + { +#if COMPRESSED_LISTS + *value = LIBRARY_COMMAND_ARRAY_SIZE; +#else + COMMAND_INDEX commandIndex; + *value = 0; + + // scan all implemented commands + for(commandIndex = GetClosestCommandIndex(0); + commandIndex < LIBRARY_COMMAND_ARRAY_SIZE; + commandIndex = GetNextCommandIndex(commandIndex)) + { + (*value)++; + } +#endif + break; + } + case TPM_PT_VENDOR_COMMANDS: + // number of vendor commands that are implemented + *value = VENDOR_COMMAND_ARRAY_SIZE; + break; + case TPM_PT_NV_BUFFER_MAX: + // Maximum data size in an NV write command + *value = MAX_NV_BUFFER_SIZE; + break; + case TPM_PT_MODES: +#if FIPS_COMPLIANT + *value = 1; +#else + *value = 0; +#endif + break; + case TPM_PT_MAX_CAP_BUFFER: + *value = MAX_CAP_BUFFER; + break; + + // Start of variable commands + case TPM_PT_PERMANENT: + // TPMA_PERMANENT + { + union + { + TPMA_PERMANENT attr; + UINT32 u32; + } flags = {TPMA_ZERO_INITIALIZER()}; + if(gp.ownerAuth.t.size != 0) + SET_ATTRIBUTE(flags.attr, TPMA_PERMANENT, ownerAuthSet); + if(gp.endorsementAuth.t.size != 0) + SET_ATTRIBUTE(flags.attr, TPMA_PERMANENT, endorsementAuthSet); + if(gp.lockoutAuth.t.size != 0) + SET_ATTRIBUTE(flags.attr, TPMA_PERMANENT, lockoutAuthSet); + if(gp.disableClear) + SET_ATTRIBUTE(flags.attr, TPMA_PERMANENT, disableClear); + if(gp.failedTries >= gp.maxTries) + SET_ATTRIBUTE(flags.attr, TPMA_PERMANENT, inLockout); + // In this implementation, EPS is always generated by TPM + SET_ATTRIBUTE(flags.attr, TPMA_PERMANENT, tpmGeneratedEPS); + + // Note: For a LSb0 machine, the bits in a bit field are in the correct + // order even if the machine is MSB0. For a MSb0 machine, a TPMA will + // be an integer manipulated by masking (USE_BIT_FIELD_STRUCTURES will + // be NO) so the bits are manipulate correctly. + *value = flags.u32; + break; + } + case TPM_PT_STARTUP_CLEAR: + // TPMA_STARTUP_CLEAR + { + union + { + TPMA_STARTUP_CLEAR attr; + UINT32 u32; + } flags = {TPMA_ZERO_INITIALIZER()}; + // + if(g_phEnable) + SET_ATTRIBUTE(flags.attr, TPMA_STARTUP_CLEAR, phEnable); + if(gc.shEnable) + SET_ATTRIBUTE(flags.attr, TPMA_STARTUP_CLEAR, shEnable); + if(gc.ehEnable) + SET_ATTRIBUTE(flags.attr, TPMA_STARTUP_CLEAR, ehEnable); + if(gc.phEnableNV) + SET_ATTRIBUTE(flags.attr, TPMA_STARTUP_CLEAR, phEnableNV); + if(g_prevOrderlyState != SU_NONE_VALUE) + SET_ATTRIBUTE(flags.attr, TPMA_STARTUP_CLEAR, orderly); + + // Note: For a LSb0 machine, the bits in a bit field are in the correct + // order even if the machine is MSB0. For a MSb0 machine, a TPMA will + // be an integer manipulated by masking (USE_BIT_FIELD_STRUCTURES will + // be NO) so the bits are manipulate correctly. + *value = flags.u32; + break; + } + case TPM_PT_HR_NV_INDEX: + // number of NV indexes currently defined + *value = NvCapGetIndexNumber(); + break; + case TPM_PT_HR_LOADED: + // number of authorization sessions currently loaded into TPM + // RAM + *value = SessionCapGetLoadedNumber(); + break; + case TPM_PT_HR_LOADED_AVAIL: + // number of additional authorization sessions, of any type, + // that could be loaded into TPM RAM + *value = SessionCapGetLoadedAvail(); + break; + case TPM_PT_HR_ACTIVE: + // number of active authorization sessions currently being + // tracked by the TPM + *value = SessionCapGetActiveNumber(); + break; + case TPM_PT_HR_ACTIVE_AVAIL: + // number of additional authorization sessions, of any type, + // that could be created + *value = SessionCapGetActiveAvail(); + break; + case TPM_PT_HR_TRANSIENT_AVAIL: + // estimate of the number of additional transient objects that + // could be loaded into TPM RAM + *value = ObjectCapGetTransientAvail(); + break; + case TPM_PT_HR_PERSISTENT: + // number of persistent objects currently loaded into TPM + // NV memory + *value = NvCapGetPersistentNumber(); + break; + case TPM_PT_HR_PERSISTENT_AVAIL: + // number of additional persistent objects that could be loaded + // into NV memory + *value = NvCapGetPersistentAvail(); + break; + case TPM_PT_NV_COUNTERS: + // number of defined NV indexes that have NV TPMA_NV_COUNTER + // attribute SET + *value = NvCapGetCounterNumber(); + break; + case TPM_PT_NV_COUNTERS_AVAIL: + // number of additional NV indexes that can be defined with their + // TPMA_NV_COUNTER attribute SET + *value = NvCapGetCounterAvail(); + break; + case TPM_PT_ALGORITHM_SET: + // region code for the TPM + *value = gp.algorithmSet; + break; + case TPM_PT_LOADED_CURVES: +#if ALG_ECC + // number of loaded ECC curves + *value = ECC_CURVE_COUNT; +#else // ALG_ECC + *value = 0; +#endif // ALG_ECC + break; + case TPM_PT_LOCKOUT_COUNTER: + // current value of the lockout counter + *value = gp.failedTries; + break; + case TPM_PT_MAX_AUTH_FAIL: + // number of authorization failures before DA lockout is invoked + *value = gp.maxTries; + break; + case TPM_PT_LOCKOUT_INTERVAL: + // number of seconds before the value reported by + // TPM_PT_LOCKOUT_COUNTER is decremented + *value = gp.recoveryTime; + break; + case TPM_PT_LOCKOUT_RECOVERY: + // number of seconds after a lockoutAuth failure before use of + // lockoutAuth may be attempted again + *value = gp.lockoutRecovery; + break; + case TPM_PT_NV_WRITE_RECOVERY: + // number of milliseconds before the TPM will accept another command + // that will modify NV. + // This should make a call to the platform code that is doing rate + // limiting of NV. Rate limiting is not implemented in the reference + // code so no call is made. + *value = 0; + break; + case TPM_PT_AUDIT_COUNTER_0: + // high-order 32 bits of the command audit counter + *value = (UINT32)(gp.auditCounter >> 32); + break; + case TPM_PT_AUDIT_COUNTER_1: + // low-order 32 bits of the command audit counter + *value = (UINT32)(gp.auditCounter); + break; + default: + // property is not defined + return FALSE; + break; + } + return TRUE; +} + +//*** TPMCapGetProperties() +// This function is used to get the TPM_PT values. The search of properties will +// start at 'property' and continue until 'propertyList' has as many values as +// will fit, or the last property has been reported, or the list has as many +// values as requested in 'count'. +// Return Type: TPMI_YES_NO +// YES more properties are available +// NO no more properties to be reported +TPMI_YES_NO +TPMCapGetProperties(TPM_PT property, // IN: the starting TPM property + UINT32 count, // IN: maximum number of returned + // properties + TPML_TAGGED_TPM_PROPERTY* propertyList // OUT: property list +) +{ + TPMI_YES_NO more = NO; + UINT32 i; + UINT32 nextGroup; + + // initialize output property list + propertyList->count = 0; + + // maximum count of properties we may return is MAX_PCR_PROPERTIES + if(count > MAX_TPM_PROPERTIES) + count = MAX_TPM_PROPERTIES; + + // if property is less than PT_FIXED, start from PT_FIXED + if(property < PT_FIXED) + property = PT_FIXED; + // There is only the fixed and variable groups with the variable group coming + // last + if(property >= (PT_VAR + PT_GROUP)) + return more; + + // Don't read past the end of the selected group + nextGroup = ((property / PT_GROUP) * PT_GROUP) + PT_GROUP; + + // Scan through the TPM properties of the requested group. + for(i = property; i < nextGroup; i++) + { + UINT32 value; + // if we have hit the end of the group, quit + if(i != property && ((i % PT_GROUP) == 0)) + break; + if(TPMPropertyIsDefined((TPM_PT)i, &value)) + { + if(propertyList->count < count) + { + // If the list is not full, add this property + propertyList->tpmProperty[propertyList->count].property = (TPM_PT)i; + propertyList->tpmProperty[propertyList->count].value = value; + propertyList->count++; + } + else + { + // If the return list is full but there are more properties + // available, set the indication and exit the loop. + more = YES; + break; + } + } + } + return more; +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Response.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Response.c new file mode 100644 index 0000000..bec99ab --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/Response.c @@ -0,0 +1,80 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Description +// This file contains the common code for building a response header, including +// setting the size of the structure. 'command' may be NULL if result is +// not TPM_RC_SUCCESS. + +//** Includes and Defines +#include "Tpm.h" +#include "Marshal.h" + +//** BuildResponseHeader() +// Adds the response header to the response. It will update command->parameterSize +// to indicate the total size of the response. +void BuildResponseHeader(COMMAND* command, // IN: main control structure + BYTE* buffer, // OUT: the output buffer + TPM_RC result // IN: the response code +) +{ + TPM_ST tag; + UINT32 size; + + if(result != TPM_RC_SUCCESS) + { + tag = TPM_ST_NO_SESSIONS; + size = 10; + } + else + { + tag = command->tag; + // Compute the overall size of the response + size = STD_RESPONSE_HEADER + command->handleNum * sizeof(TPM_HANDLE); + size += command->parameterSize; + size += (command->tag == TPM_ST_SESSIONS) ? command->authSize + sizeof(UINT32) + : 0; + } + TPM_ST_Marshal(&tag, &buffer, NULL); + UINT32_Marshal(&size, &buffer, NULL); + TPM_RC_Marshal(&result, &buffer, NULL); + if(result == TPM_RC_SUCCESS) + { + if(command->handleNum > 0) + TPM_HANDLE_Marshal(&command->handles[0], &buffer, NULL); + if(tag == TPM_ST_SESSIONS) + UINT32_Marshal((UINT32*)&command->parameterSize, &buffer, NULL); + } + command->parameterSize = size; +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/ResponseCodeProcessing.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/ResponseCodeProcessing.c new file mode 100644 index 0000000..4fdc4dc --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/ResponseCodeProcessing.c @@ -0,0 +1,52 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Description +// This file contains the miscellaneous functions for processing response codes. +// NOTE: Currently, there is only one. + +//** Includes and Defines +#include "Tpm.h" + +//** RcSafeAddToResult() +// Adds a modifier to a response code as long as the response code allows a modifier +// and no modifier has already been added. +TPM_RC +RcSafeAddToResult(TPM_RC responseCode, TPM_RC modifier) +{ + if((responseCode & RC_FMT1) && !(responseCode & 0xf40)) + return responseCode + modifier; + else + return responseCode; +} diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/TableDrivenMarshal.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/TableDrivenMarshal.c new file mode 100644 index 0000000..439cc7a --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/TableDrivenMarshal.c @@ -0,0 +1,890 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include "Tpm.h" +#include "Marshal.h" +#include "TableMarshal.h" + +#if TABLE_DRIVEN_MARSHAL + +extern ArrayMarshal_mst ArrayLookupTable[]; + +extern UINT16 MarshalLookupTable[]; + +typedef struct +{ + int a; +} External_Structure_t; + +extern struct Exernal_Structure_t MarshalData; + +# define IS_SUCCESS(UNMARSHAL_FUNCTION) \ + (TPM_RC_SUCCESS == (result = (UNMARSHAL_FUNCTION))) + +marshalIndex_t IntegerDispatch[] = {UINT8_MARSHAL_REF, + UINT16_MARSHAL_REF, + UINT32_MARSHAL_REF, + UINT64_MARSHAL_REF, + INT8_MARSHAL_REF, + INT16_MARSHAL_REF, + INT32_MARSHAL_REF, + INT64_MARSHAL_REF}; + +# if 1 +# define GetDescriptor(reference) \ + ((MarshalHeader_mst*)(((BYTE*)(&MarshalData)) + (reference & NULL_MASK))) +# else +static const MarshalHeader_mst* GetDescriptor(marshalIndex_t index) +{ + const MarshalHeader_mst* mst = MarshalLookupTable[index & NULL_MASK]; + return mst; +} +# endif + +# define GetUnionDescriptor(_index_) ((UnionMarshal_mst*)GetDescriptor(_index_)) +# define GetArrayDescriptor(_index_) \ + ((ArrayMarshal_mst*))(ArrayLookupTable[_index_ & NULL_MASK]) + +//*** GetUnmarshaledInteger() +// Gets the unmarshaled value and normalizes it to a UIN32 for other +// processing (comparisons and such). +static UINT32 GetUnmarshaledInteger(marshalIndex_t type, const void* target) +{ + int size = (type & SIZE_MASK); + // + if(size == FOUR_BYTES) + return *((UINT32*)target); + if(type & IS_SIGNED) + { + if(size == TWO_BYTES) + return (UINT32) * ((int16_t*)target); + return (UINT32) * ((int8_t*)target); + } + if(size == TWO_BYTES) + return (UINT32) * ((UINT16*)target); + return (UINT32) * ((UINT8*)target); +} + +static UINT32 GetSelector(void* structure, const UINT16* values, UINT16 descriptor) +{ + unsigned sel = GET_ELEMENT_NUMBER(descriptor); + // Get the offset of the value in the unmarshaled structure + const UINT16* entry = &values[(sel * 3)]; + // + return GetUnmarshaledInteger(GET_ELEMENT_SIZE(entry[0]), + ((UINT8*)structure) + entry[2]); +} + +static TPM_RC UnmarshalBytes( + UINT8* target, // IN/OUT: place to put the bytes + UINT8** buffer, // IN/OUT: source of the input data + INT32* size, // IN/OUT: remaining bytes in the input buffer + int count // IN: number of bytes to get +) +{ + if((*size -= count) >= 0) + { + memcpy(target, *buffer, count); + *buffer += count; + return TPM_RC_SUCCESS; + } + return TPM_RC_INSUFFICIENT; +} + +//*** MarshalBytes() +// Marshal an array of bytes. +static UINT16 MarshalBytes(UINT8* source, UINT8** buffer, INT32* size, int32_t count) +{ + if(buffer != NULL) + { + if(size != NULL && (size -= count) < 0) + return 0; + memcpy(*buffer, source, count); + *buffer += count; + } + return (UINT16)count; +} + +//*** ArrayUnmarshal() +// Unmarshal an array. The 'index' is of the form: 'type'_ARRAY_MARSHAL_INDEX. +static TPM_RC ArrayUnmarshal(UINT16 index, // IN: the type of the array + UINT8* target, // IN: target for the data + UINT8** buffer, // IN/OUT: place to get the data + INT32* size, // IN/OUT: remaining unmarshal data + UINT32 count // IN: number of values of 'index' to + // unmarshal +) +{ + marshalIndex_t which = ArrayLookupTable[index & NULL_MASK].type; + UINT16 stride = ArrayLookupTable[index & NULL_MASK].stride; + TPM_RC result; + // + if(stride == 1) // A byte array + result = UnmarshalBytes(target, buffer, size, count); + else + { + which |= index & NULL_FLAG; + for(result = TPM_RC_SUCCESS; count > 0; target += stride, count--) + if(!IS_SUCCESS(Unmarshal(which, target, buffer, size))) + break; + } + return result; +} + +//*** ArrayMarshal() +static UINT16 ArrayMarshal(UINT16 index, // IN: the type of the array + UINT8* source, // IN: source of the data + UINT8** buffer, // IN/OUT: place to put the data + INT32* size, // IN/OUT: amount of space for the data + UINT32 count // IN: number of values of 'index' to marshal +) +{ + marshalIndex_t which = ArrayLookupTable[index & NULL_MASK].type; + UINT16 stride = ArrayLookupTable[index & NULL_MASK].stride; + UINT16 retVal; + // + if(stride == 1) // A byte array + return MarshalBytes(source, buffer, size, count); + which |= index & NULL_FLAG; + for(retVal = 0; count > 0; source += stride, count--) + retVal += Marshal(which, source, buffer, size); + + return retVal; +} + +//***UnmarshalUnion() +TPM_RC +UnmarshalUnion(UINT16 typeIndex, // IN: the thing to unmarshal + void* target, // IN: were the data goes to + UINT8** buffer, // IN/OUT: the data source buffer + INT32* size, // IN/OUT: the remaining size + UINT32 selector) +{ + int i; + UnionMarshal_mst* ut = GetUnionDescriptor(typeIndex); + marshalIndex_t selected; + // + for(i = 0; i < ut->countOfselectors; i++) + { + if(selector == ut->selectors[i]) + { + UINT8* offset = ((UINT8*)ut) + ut->offsetOfUnmarshalTypes; + // Get the selected thing to unmarshal + selected = ((marshalIndex_t*)offset)[i]; + if(ut->modifiers & IS_ARRAY_UNION) + return UnmarshalBytes(target, buffer, size, selected); + else + { + // Propagate NULL_FLAG if the null flag was + // propagated to the structure containing the union + selected |= (typeIndex & NULL_FLAG); + return Unmarshal(selected, target, buffer, size); + } + } + } + // Didn't find the value. + return TPM_RC_SELECTOR; +} + +//*** MarshalUnion() +UINT16 +MarshalUnion(UINT16 typeIndex, // IN: the thing to marshal + void* source, // IN: were the data comes from + UINT8** buffer, // IN/OUT: the data source buffer + INT32* size, // IN/OUT: the remaining size + UINT32 selector // IN: the union selector +) +{ + int i; + UnionMarshal_mst* ut = GetUnionDescriptor(typeIndex); + marshalIndex_t selected; + // + for(i = 0; i < ut->countOfselectors; i++) + { + if(selector == ut->selectors[i]) + { + UINT8* offset = ((UINT8*)ut) + ut->offsetOfUnmarshalTypes; + // Get the selected thing to unmarshal + selected = ((marshalIndex_t*)offset)[i]; + if(ut->modifiers & IS_ARRAY_UNION) + return MarshalBytes(source, buffer, size, selected); + else + return Marshal(selected, source, buffer, size); + } + } + if(size != NULL) + *size = -1; + return 0; +} + +TPM_RC +UnmarshalInteger(int iSize, // IN: Number of bytes in the integer + void* target, // OUT: receives the integer + UINT8** buffer, // IN/OUT: source of the data + INT32* size, // IN/OUT: amount of data available + UINT32* value // OUT: optional copy of 'target' +) +{ + // This is just to save typing +# define _MB_ (*buffer) + // The size is a power of two so convert to regular integer + int bytes = (1 << (iSize & SIZE_MASK)); + // + // Check to see if there is enough data to fulfill the request + if((*size -= bytes) >= 0) + { + // The most comon size + if(bytes == 4) + { + *((UINT32*)target) = + (UINT32)((((((_MB_[0] << 8) | _MB_[1]) << 8) | _MB_[2]) << 8) + | _MB_[3]); + // If a copy is needed, copy it. + if(value != NULL) + *value = *((UINT32*)target); + } + else if(bytes == 2) + { + *((UINT16*)target) = (UINT16)((_MB_[0] << 8) | _MB_[1]); + // If a copy is needed, copy with the appropriate sign extension + if(value != NULL) + { + if(iSize & IS_SIGNED) + *value = (UINT32)(*((INT16*)target)); + else + *value = (UINT32)(*((UINT16*)target)); + } + } + else if(bytes == 1) + { + *((UINT8*)target) = (UINT8)_MB_[0]; + // If a copy is needed, copy with the appropriate sign extension + if(value != NULL) + { + if(iSize & IS_SIGNED) + *value = (UINT32)(*((INT8*)target)); + else + *value = (UINT32)(*((UINT8*)target)); + } + } + else + { + // There is no input type that is a 64-bit value other than a UINT64. So + // there is no reason to do anything other than unmarshal it. + *((UINT64*)target) = BYTE_ARRAY_TO_UINT64(*buffer); + } + *buffer += bytes; + return TPM_RC_SUCCESS; +# undef _MB_ + } + return TPM_RC_INSUFFICIENT; +} + +//*** Unmarshal() +// This is the function that performs unmarshaling of different numbered types. Each +// TPM type has a number. The number is used to lookup the address of the data +// structure that describes how to unmarshal that data type. +// +TPM_RC +Unmarshal(UINT16 typeIndex, // IN: the thing to marshal + void* target, // IN: were the data goes from + UINT8** buffer, // IN/OUT: the data source buffer + INT32* size // IN/OUT: the remaining size +) +{ + const MarshalHeader_mst* sel; + TPM_RC result; + // + sel = GetDescriptor(typeIndex); + switch(sel->marshalType) + { + case UINT_MTYPE: + { + // A simple signed or unsigned integer value. + return UnmarshalInteger(sel->modifiers, target, buffer, size, NULL); + } + case VALUES_MTYPE: + { + // This is the general-purpose structure that can handle things like + // TPMI_DH_PARENT that has multiple ranges, multiple singles and a + // 'null' value. When things cover a large range with holes in the range + // they can be turned into multiple ranges. There is no option for a bit + // field. + // The structure is: + // typedef const struct ValuesMarshal_mst + // { + // UINT8 marshalType; // VALUES_MTYPE + // UINT8 modifiers; + // UINT8 errorCode; + // UINT8 ranges; + // UINT8 singles; + // UINT32 values[1]; + // } ValuesMarshal_mst; + // Unmarshal the base type + UINT32 val; + if(IS_SUCCESS( + UnmarshalInteger(sel->modifiers, target, buffer, size, &val))) + { + ValuesMarshal_mst* vmt = ((ValuesMarshal_mst*)sel); + const UINT32* check = vmt->values; + // + // if the TAKES_NULL flag is set, then the first entry in the values + // list is the NULL value. Iy is not included in the 'ranges' or + // 'singles' count. + if((vmt->modifiers & TAKES_NULL) && (val == *check++)) + { + if((typeIndex & NULL_FLAG) == 0) + result = (TPM_RC)(sel->errorCode); + } + // No NULL value or input is not the NULL value + else + { + int i; + // + // Check all the min-max ranges. + for(i = vmt->ranges - 1; i >= 0; check = &check[2], i--) + if((UINT32)(val - check[0]) <= check[1]) + break; + // if the input is in a selected range, then i >= 0 + if(i < 0) + { + // Not in any range, so check sigles + for(i = vmt->singles - 1; i >= 0; i--) + if(val == check[i]) + break; + } + // If input not in range and not in any single so return error + if(i < 0) + result = (TPM_RC)(sel->errorCode); + } + } + break; + } + case TABLE_MTYPE: + { + // This is a table with or without bit checking. The input is checked + // against each value in the table. If the value is in the table, and + // a bits table is present, then the bit field is checked to see if the + // indicated value is implemented. For example, if there is a table of + // allowed RSA key sizes and the 2nd entry matches, then the 2nd bit in + // the bit field is checked to see if that allowed size is implemented + // in this TPM. + // typedef const struct TableMarshal_mst + // { + // UINT8 marshalType; // TABLE_MTYPE + // UINT8 modifiers; + // UINT8 errorCode; + // UINT8 singles; + // UINT32 values[singles + 1 if TAKES_NULL]; + // } TableMarshal_mst; + + UINT32 val; + // + // Unmarshal the base type + if(IS_SUCCESS( + UnmarshalInteger(sel->modifiers, target, buffer, size, &val))) + { + TableMarshal_mst* tmt = ((TableMarshal_mst*)sel); + const UINT32* check = tmt->values; + // + // If this type has a null value, then it is the first value in the + // list of values. It does not count in the count of values + if((tmt->modifiers & TAKES_NULL) && (val == *check++)) + { + if((typeIndex & NULL_FLAG) == 0) + result = (TPM_RC)(sel->errorCode); + } + else + { + int i; + // + // Process the singles + for(i = tmt->singles - 1; i >= 0; i--) + { + // does the input value match the value in the table + if(val == check[i]) + { + // If there is an associated bit table, make sure that + // the corresponding bit is SET + if((HAS_BITS & tmt->modifiers) + && (!IS_BIT_SET32(i, &(check[tmt->singles])))) + // if not SET, then this is a failure. + i = -1; + break; + } + } + // error if not found or bit not SET + if(i < 0) + result = (TPM_RC)(sel->errorCode); + } + } + break; + } + case MIN_MAX_MTYPE: + { + // A MIN_MAX is a range. It can have a bit field and a NULL value that is + // outside of the range. If the input value is in the min-max range then + // it is valid unless there is an associated bit field. Otherwise, it + // it is only valid if the corresponding value in the bit field is SET. + // The min value is 'values[0]' or 'values[1]' if there is a NULL value. + // The max value is the value after min. The max value is in the table as + // max minus min. This allows 'val' to be subtracted from min and then + // checked against max with one unsigned comparison. If present, the bit + // field will be the first 'values' after max. + // typedef const struct MinMaxMarshal_mst + // { + // UINT8 marshalType; // MIN_MAX_MTYPE + // UINT8 modifiers; + // UINT8 errorCode; + // UINT32 values[2 + 1 if TAKES_NULL]; + // } MinMaxMarshal_mst; + UINT32 val; + // + // A min-max has a range. It can have a bit-field that is indexed to the + // min value (something that matches min has a bit at 0. This is useful + // for algorithms. The min-max define a range of algorithms to be checked + // and the bit field can check to see if the algorithm in that range is + // allowed. + if(IS_SUCCESS( + UnmarshalInteger(sel->modifiers, target, buffer, size, &val))) + { + MinMaxMarshal_mst* mmt = (MinMaxMarshal_mst*)sel; + const UINT32* check = mmt->values; + // + // If this type takes a NULL, see if it matches. This + if((mmt->modifiers & TAKES_NULL) && (val == *check++)) + { + if((typeIndex & NULL_FLAG) == 0) + result = (TPM_RC)(mmt->errorCode); + } + else + { + val -= *check; + if((val > check[1]) + || ((mmt->modifiers & HAS_BITS) + && !IS_BIT_SET32(val, &check[2]))) + result = (TPM_RC)(mmt->errorCode); + } + } + break; + } + case ATTRIBUTES_MTYPE: + { + // This is used for TPMA values. + UINT32 mask; + AttributesMarshal_mst* amt = (AttributesMarshal_mst*)sel; + // + if(IS_SUCCESS( + UnmarshalInteger(sel->modifiers, target, buffer, size, &mask))) + { + if((mask & amt->attributeMask) != 0) + result = TPM_RC_RESERVED_BITS; + } + break; + } + case STRUCTURE_MTYPE: + { + // A structure (not a union). A structure has elements (one defined per + // row). Three UINT16 values are used for each row. The first indicates + // the type of the entry. They choices are: simple, union, or array. A + // simple type can be a simple integer or another structure. It can also + // be a specific "interface type." For example, when a structure entry is + // a value that is used define the dimension of an array, the entry of + // the structure will reference a "synthetic" interface type, most often + // a min-max value. If the type of the entry is union or array, then the + // first value indicates which of the previous elements provides the union + // selector or the array dimension. That previous entry is referenced in + // the unmarshaled structure in memory (Not the marshaled buffer). The + // previous entry indicates the location in the structure of the value. + // The second entry of each structure entry indicated the index of the + // type associated with the entry. This is an index into the array of + // arrays or the union table (merged with the normal table in this + // implementation). The final entry is the offset in the unmarshaled + // structure where the value is located. This is the offsetof(STRUcTURE, + // element). This value is added to the input 'target' or 'source' value + // to determine where the value goes. + StructMarshal_mst* mst = (StructMarshal_mst*)sel; + int i; + const UINT16* value = mst->values; + // + for(result = TPM_RC_SUCCESS, i = mst->elements; + (TPM_RC_SUCCESS == result) && (i > 0); + value = &value[3], i--) + { + UINT16 descriptor = value[0]; + marshalIndex_t index = value[1]; + // The offset of the object in the structure is in the last value in + // the triplet. Add that value to the start of the structure + UINT8* offset = ((UINT8*)target) + value[2]; + // + if((ELEMENT_PROPAGATE & descriptor) && (typeIndex & NULL_FLAG)) + index |= NULL_FLAG; + switch(GET_ELEMENT_TYPE(descriptor)) + { + case SIMPLE_STYPE: + { + result = Unmarshal(index, offset, buffer, size); + break; + } + case UNION_STYPE: + { + UINT32 choice; + // + // Get the selector or array dimension value + choice = GetSelector(target, mst->values, descriptor); + result = UnmarshalUnion(index, offset, buffer, size, choice); + break; + } + case ARRAY_STYPE: + { + UINT32 dimension; + // + dimension = GetSelector(target, mst->values, descriptor); + result = + ArrayUnmarshal(index, offset, buffer, size, dimension); + break; + } + default: + result = TPM_RC_FAILURE; + break; + } + } + break; + } + case TPM2B_MTYPE: + { + // A primitive TPM2B. A size and byte buffer. The single value (other than + // the tag) references the synthetic 'interface' value for the size + // parameter. + Tpm2bMarshal_mst* m2bt = (Tpm2bMarshal_mst*)sel; + // + if(IS_SUCCESS(Unmarshal(m2bt->sizeIndex, target, buffer, size))) + result = UnmarshalBytes( + ((TPM2B*)target)->buffer, buffer, size, *((UINT16*)target)); + break; + } + case TPM2BS_MTYPE: + { + // This is used when a TPM2B contains a structure. + Tpm2bsMarshal_mst* m2bst = (Tpm2bsMarshal_mst*)sel; + INT32 count; + // + if(IS_SUCCESS(Unmarshal(m2bst->sizeIndex, target, buffer, size))) + { + // fetch the size value and convert it to a 32-bit count value + count = (int32_t) * ((UINT16*)target); + if(count == 0) + { + if(m2bst->modifiers & SIZE_EQUAL) + result = TPM_RC_SIZE; + } + else if((*size -= count) >= 0) + { + marshalIndex_t index = m2bst->dataIndex; + // + // If this type propigates a null (PROPIGATE_NULL), propigate it + if((m2bst->modifiers & PROPAGATE_NULL) && (typeIndex & typeIndex)) + index |= NULL_FLAG; + // The structure might not start two bytes after the start of the + // size field. The offset to the start of the structure is between + // 2 and 8 bytes. This is encoded into the low 4 bits of the + // modifiers byte byte + if(IS_SUCCESS(Unmarshal( + index, + ((UINT8*)target) + (m2bst->modifiers & OFFSET_MASK), + buffer, + &count))) + { + if(count != 0) + result = TPM_RC_SIZE; + } + } + else + result = TPM_RC_INSUFFICIENT; + } + break; + } + case LIST_MTYPE: + { + // Used for a list. A list is a qualified 32-bit 'count' value followed + // by a type indicator. + ListMarshal_mst* mlt = (ListMarshal_mst*)sel; + marshalIndex_t index = mlt->arrayRef; + // + if(IS_SUCCESS(Unmarshal(mlt->sizeIndex, target, buffer, size))) + { + // If this type propigates a null (PROPIGATE_NULL), propigate it + if((mlt->modifiers & PROPAGATE_NULL) && (typeIndex & NULL_FLAG)) + index |= NULL_FLAG; + result = + ArrayUnmarshal(index, + ((UINT8*)target) + (mlt->modifiers & OFFSET_MASK), + buffer, + size, + *((UINT32*)target)); + } + break; + } + case NULL_MTYPE: + { + result = TPM_RC_SUCCESS; + break; + } +# if 0 + case COMPOSITE_MTYPE: + { + CompositeMarshal_mst *mct = (CompositeMarshal_mst *)sel; + int i; + UINT8 *buf = *buffer; + INT32 sz = *size; + // + result = TPM_RC_VALUE; + for(i = GET_ELEMENT_COUNT(mct->modifiers) - 1; i <= 0; i--) + { + marshalIndex_t index = mct->types[i]; + // + // This type might take a null so set it in each called value, just + // in case it is needed in that value. Only one value in each + // composite should have the takes null SET. + index |= typeIndex & NULL_MASK; + result = Unmarshal(index, target, buffer, size); + if(result == TPM_RC_SUCCESS) + break; + // Each of the composite values does its own unmarshaling. This + // has some execution overhead if it is unmarshaled multiple times + // but it saves code size in not having to reproduce the various + // unmarshaling types that can be in a composite. So, what this means + // is that the buffer pointer and size have to be reset for each + // unmarshaled value. + *buffer = buf; + *size = sz; + } + break; + } +# endif // 0 + default: + { + result = TPM_RC_FAILURE; + break; + } + } + return result; +} + +//*** Marshal() +// This is the function that drives marshaling of output. Because there is no +// validation of the output, there is a lot less code. +UINT16 Marshal(UINT16 typeIndex, // IN: the thing to marshal + void* source, // IN: were the data comes from + UINT8** buffer, // IN/OUT: the data source buffer + INT32* size // IN/OUT: the remaining size +) +{ +# define _source ((UINT8*)source) + + const MarshalHeader_mst* sel; + UINT16 retVal; + // + sel = GetDescriptor(typeIndex); + switch(sel->marshalType) + { + case VALUES_MTYPE: + case UINT_MTYPE: + case TABLE_MTYPE: + case MIN_MAX_MTYPE: + case ATTRIBUTES_MTYPE: + case COMPOSITE_MTYPE: + { +# if BIG_ENDIAN_TPM +# define MM16 0 +# define MM32 0 +# define MM64 0 +# else +// These flip the constant index values so that they count in reverse order when doing +// little-endian stuff +# define MM16 1 +# define MM32 3 +# define MM64 7 +# endif +// Just change the name and cast the type of the input parameters for typing purposes +# define mb (*buffer) +# define _source ((UINT8*)source) + retVal = (1 << (sel->modifiers & SIZE_MASK)); + if(buffer != NULL) + { + if((size == NULL) || ((*size -= retVal) >= 0)) + { + if(retVal == 4) + { + mb[0 ^ MM32] = _source[0]; + mb[1 ^ MM32] = _source[1]; + mb[2 ^ MM32] = _source[2]; + mb[3 ^ MM32] = _source[3]; + } + else if(retVal == 2) + { + mb[0 ^ MM16] = _source[0]; + mb[1 ^ MM16] = _source[1]; + } + else if(retVal == 1) + mb[0] = _source[0]; + else + { + mb[0 ^ MM64] = _source[0]; + mb[1 ^ MM64] = _source[1]; + mb[2 ^ MM64] = _source[2]; + mb[3 ^ MM64] = _source[3]; + mb[4 ^ MM64] = _source[4]; + mb[5 ^ MM64] = _source[5]; + mb[6 ^ MM64] = _source[6]; + mb[7 ^ MM64] = _source[7]; + } + *buffer += retVal; + } + } + break; + } + case STRUCTURE_MTYPE: + { + //#define _mst ((StructMarshal_mst *)sel) + StructMarshal_mst* mst = ((StructMarshal_mst*)sel); + int i; + const UINT16* value = mst->values; + + // + for(retVal = 0, i = mst->elements; i > 0; value = &value[3], i--) + { + UINT16 des = value[0]; + marshalIndex_t index = value[1]; + UINT8* offset = _source + value[2]; + // + switch(GET_ELEMENT_TYPE(des)) + { + case UNION_STYPE: + { + UINT32 choice; + // + choice = GetSelector(source, mst->values, des); + retVal += MarshalUnion(index, offset, buffer, size, choice); + break; + } + case ARRAY_STYPE: + { + UINT32 count; + // + count = GetSelector(source, mst->values, des); + retVal += ArrayMarshal(index, offset, buffer, size, count); + break; + } + case SIMPLE_STYPE: + default: + { + // This is either another structure or a simple type + retVal += Marshal(index, offset, buffer, size); + break; + } + } + } + break; + } + case TPM2B_MTYPE: + { + // Get the number of bytes being marshaled + INT32 val = (int32_t) * ((UINT16*)source); + // + retVal = Marshal(UINT16_MARSHAL_REF, source, buffer, size); + + // This is a standard 2B with a byte buffer + retVal += MarshalBytes(((TPM2B*)_source)->buffer, buffer, size, val); + break; + } + case TPM2BS_MTYPE: // A structure in a TPM2B + { + Tpm2bsMarshal_mst* m2bst = (Tpm2bsMarshal_mst*)sel; + UINT8* offset; + UINT16 amount; + UINT8* marshaledSize; + // + // Save the address of where the size should go + marshaledSize = *buffer; + + // marshal the size (checks the space and advanced the pointer) + retVal = Marshal(UINT16_MARSHAL_REF, source, buffer, size); + + // This gets the 'offsetof' the structure to marshal. It was placed in the + // modifiers byte because the offset from the start of the TPM2B to the + // start of the structure is going to be less than 8 and the modifiers + // byte isn't needed for anything else. + offset = _source + (m2bst->modifiers & SIGNED_MASK); + + // Marshal the structure and get its size + amount = Marshal(m2bst->dataIndex, offset, buffer, size); + + // put the size in the space used when the size was marshaled. + if(buffer != NULL) + UINT16_TO_BYTE_ARRAY(amount, marshaledSize); + retVal += amount; + break; + } + case LIST_MTYPE: + { + ListMarshal_mst* mlt = ((ListMarshal_mst*)sel); + UINT8* offset = _source + (mlt->modifiers & SIGNED_MASK); + retVal = Marshal(UINT32_MARSHAL_REF, source, buffer, size); + retVal += ArrayMarshal((marshalIndex_t)(mlt->arrayRef), + offset, + buffer, + size, + *((UINT32*)source)); + break; + } + case NULL_MTYPE: + retVal = 0; + break; + case ERROR_MTYPE: + default: + { + if(size != NULL) + *size = -1; + retVal = 0; + break; + } + } + return retVal; +} + +#endif // TABLE_DRIVEN_MARSHAL diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/TableMarshalData.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/TableMarshalData.c new file mode 100644 index 0000000..178977b --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/TableMarshalData.c @@ -0,0 +1,1725 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*(Auto-generated) + * Created by NewMarshal; Version 1.4 Apr 7, 2019 + * Date: Mar 6, 2020 Time: 01:50:10PM + */ + +// This file contains the data initializer used for the table-driven marshaling code. + +#include "Tpm.h" + +#if TABLE_DRIVEN_MARSHAL +# include "TableMarshal.h" +# include "Marshal.h" + +// The array marshaling table +ArrayMarshal_mst ArrayLookupTable[] = {ARRAY_MARSHAL_ENTRY(UINT8), + ARRAY_MARSHAL_ENTRY(TPM_CC), + ARRAY_MARSHAL_ENTRY(TPMA_CC), + ARRAY_MARSHAL_ENTRY(TPM_ALG_ID), + ARRAY_MARSHAL_ENTRY(TPM_HANDLE), + ARRAY_MARSHAL_ENTRY(TPM2B_DIGEST), + ARRAY_MARSHAL_ENTRY(TPMT_HA), + ARRAY_MARSHAL_ENTRY(TPMS_PCR_SELECTION), + ARRAY_MARSHAL_ENTRY(TPMS_ALG_PROPERTY), + ARRAY_MARSHAL_ENTRY(TPMS_TAGGED_PROPERTY), + ARRAY_MARSHAL_ENTRY(TPMS_TAGGED_PCR_SELECT), + ARRAY_MARSHAL_ENTRY(TPM_ECC_CURVE), + ARRAY_MARSHAL_ENTRY(TPMS_TAGGED_POLICY), + ARRAY_MARSHAL_ENTRY(TPMS_ACT_DATA), + ARRAY_MARSHAL_ENTRY(TPMS_AC_OUTPUT)}; + +// The main marshaling structure +MarshalData_st MarshalData = { + // UINT8_DATA + {UINT_MTYPE, 0}, + // UINT16_DATA + {UINT_MTYPE, 1}, + // UINT32_DATA + {UINT_MTYPE, 2}, + // UINT64_DATA + {UINT_MTYPE, 3}, + // INT8_DATA + {UINT_MTYPE, 0 + IS_SIGNED}, + // INT16_DATA + {UINT_MTYPE, 1 + IS_SIGNED}, + // INT32_DATA + {UINT_MTYPE, 2 + IS_SIGNED}, + // INT64_DATA + {UINT_MTYPE, 3 + IS_SIGNED}, + // UINT0_DATA + {NULL_MTYPE, 0}, + // TPM_ECC_CURVE_DATA + {MIN_MAX_MTYPE, + TWO_BYTES | TAKES_NULL | HAS_BITS, + (UINT8)TPM_RC_CURVE, + {TPM_ECC_NONE, + RANGE(1, 32, UINT16), + (UINT32)((ECC_NIST_P192 << 0) | (ECC_NIST_P224 << 1) | (ECC_NIST_P256 << 2) + | (ECC_NIST_P384 << 3) | (ECC_NIST_P521 << 4) | (ECC_BN_P256 << 15) + | (ECC_BN_P638 << 16) | (ECC_SM2_P256 << 31))}}, + // TPM_CLOCK_ADJUST_DATA + {MIN_MAX_MTYPE, + ONE_BYTES | IS_SIGNED, + (UINT8)TPM_RC_VALUE, + {RANGE(TPM_CLOCK_COARSE_SLOWER, TPM_CLOCK_COARSE_FASTER, INT8)}}, + // TPM_EO_DATA + {MIN_MAX_MTYPE, + TWO_BYTES, + (UINT8)TPM_RC_VALUE, + {RANGE(TPM_EO_EQ, TPM_EO_BITCLEAR, UINT16)}}, + // TPM_SU_DATA + {TABLE_MTYPE, TWO_BYTES, (UINT8)TPM_RC_VALUE, 2, {TPM_SU_CLEAR, TPM_SU_STATE}}, + // TPM_SE_DATA + {TABLE_MTYPE, + ONE_BYTES, + (UINT8)TPM_RC_VALUE, + 3, + {TPM_SE_HMAC, TPM_SE_POLICY, TPM_SE_TRIAL}}, + // TPM_CAP_DATA + {VALUES_MTYPE, + FOUR_BYTES, + (UINT8)TPM_RC_VALUE, + 1, + 1, + {RANGE(TPM_CAP_ALGS, TPM_CAP_ACT, UINT32), TPM_CAP_VENDOR_PROPERTY}}, + // TPMA_ALGORITHM_DATA + {ATTRIBUTES_MTYPE, FOUR_BYTES, 0xFFFFF8F0}, + // TPMA_OBJECT_DATA + {ATTRIBUTES_MTYPE, FOUR_BYTES, 0xFFF0F309}, + // TPMA_SESSION_DATA + {ATTRIBUTES_MTYPE, ONE_BYTES, 0x00000018}, + // TPMA_ACT_DATA + {ATTRIBUTES_MTYPE, FOUR_BYTES, 0xFFFFFFFC}, + // TPMI_YES_NO_DATA + {TABLE_MTYPE, ONE_BYTES, (UINT8)TPM_RC_VALUE, 2, {NO, YES}}, + // TPMI_DH_OBJECT_DATA + {VALUES_MTYPE, + FOUR_BYTES | TAKES_NULL, + (UINT8)TPM_RC_VALUE, + 2, + 0, + {TPM_RH_NULL, + RANGE(TRANSIENT_FIRST, TRANSIENT_LAST, UINT32), + RANGE(PERSISTENT_FIRST, PERSISTENT_LAST, UINT32)}}, + // TPMI_DH_PARENT_DATA + {VALUES_MTYPE, + FOUR_BYTES | TAKES_NULL, + (UINT8)TPM_RC_VALUE, + 2, + 3, + {TPM_RH_NULL, + RANGE(TRANSIENT_FIRST, TRANSIENT_LAST, UINT32), + RANGE(PERSISTENT_FIRST, PERSISTENT_LAST, UINT32), + TPM_RH_OWNER, + TPM_RH_ENDORSEMENT, + TPM_RH_PLATFORM}}, + // TPMI_DH_PERSISTENT_DATA + {MIN_MAX_MTYPE, + FOUR_BYTES, + (UINT8)TPM_RC_VALUE, + {RANGE(PERSISTENT_FIRST, PERSISTENT_LAST, UINT32)}}, + // TPMI_DH_ENTITY_DATA + {VALUES_MTYPE, + FOUR_BYTES | TAKES_NULL, + (UINT8)TPM_RC_VALUE, + 5, + 4, + {TPM_RH_NULL, + RANGE(TRANSIENT_FIRST, TRANSIENT_LAST, UINT32), + RANGE(PERSISTENT_FIRST, PERSISTENT_LAST, UINT32), + RANGE(NV_INDEX_FIRST, NV_INDEX_LAST, UINT32), + RANGE(PCR_FIRST, PCR_LAST, UINT32), + RANGE(TPM_RH_AUTH_00, TPM_RH_AUTH_FF, UINT32), + TPM_RH_OWNER, + TPM_RH_LOCKOUT, + TPM_RH_ENDORSEMENT, + TPM_RH_PLATFORM}}, + // TPMI_DH_PCR_DATA + {MIN_MAX_MTYPE, + FOUR_BYTES | TAKES_NULL, + (UINT8)TPM_RC_VALUE, + {TPM_RH_NULL, RANGE(PCR_FIRST, PCR_LAST, UINT32)}}, + // TPMI_SH_AUTH_SESSION_DATA + {VALUES_MTYPE, + FOUR_BYTES | TAKES_NULL, + (UINT8)TPM_RC_VALUE, + 2, + 0, + {TPM_RS_PW, + RANGE(HMAC_SESSION_FIRST, HMAC_SESSION_LAST, UINT32), + RANGE(POLICY_SESSION_FIRST, POLICY_SESSION_LAST, UINT32)}}, + // TPMI_SH_HMAC_DATA + {MIN_MAX_MTYPE, + FOUR_BYTES, + (UINT8)TPM_RC_VALUE, + {RANGE(HMAC_SESSION_FIRST, HMAC_SESSION_LAST, UINT32)}}, + // TPMI_SH_POLICY_DATA + {MIN_MAX_MTYPE, + FOUR_BYTES, + (UINT8)TPM_RC_VALUE, + {RANGE(POLICY_SESSION_FIRST, POLICY_SESSION_LAST, UINT32)}}, + // TPMI_DH_CONTEXT_DATA + {VALUES_MTYPE, + FOUR_BYTES, + (UINT8)TPM_RC_VALUE, + 3, + 0, + {RANGE(HMAC_SESSION_FIRST, HMAC_SESSION_LAST, UINT32), + RANGE(POLICY_SESSION_FIRST, POLICY_SESSION_LAST, UINT32), + RANGE(TRANSIENT_FIRST, TRANSIENT_LAST, UINT32)}}, + // TPMI_DH_SAVED_DATA + {VALUES_MTYPE, + FOUR_BYTES, + (UINT8)TPM_RC_VALUE, + 2, + 3, + {RANGE(HMAC_SESSION_FIRST, HMAC_SESSION_LAST, UINT32), + RANGE(POLICY_SESSION_FIRST, POLICY_SESSION_LAST, UINT32), + 0x80000000, + 0x80000001, + 0x80000002}}, + // TPMI_RH_HIERARCHY_DATA + {TABLE_MTYPE, + FOUR_BYTES | TAKES_NULL, + (UINT8)TPM_RC_VALUE, + 3, + {TPM_RH_NULL, TPM_RH_OWNER, TPM_RH_ENDORSEMENT, TPM_RH_PLATFORM}}, + // TPMI_RH_ENABLES_DATA + {TABLE_MTYPE, + FOUR_BYTES | TAKES_NULL, + (UINT8)TPM_RC_VALUE, + 4, + {TPM_RH_NULL, + TPM_RH_OWNER, + TPM_RH_ENDORSEMENT, + TPM_RH_PLATFORM, + TPM_RH_PLATFORM_NV}}, + // TPMI_RH_HIERARCHY_AUTH_DATA + {TABLE_MTYPE, + FOUR_BYTES, + (UINT8)TPM_RC_VALUE, + 4, + {TPM_RH_OWNER, TPM_RH_LOCKOUT, TPM_RH_ENDORSEMENT, TPM_RH_PLATFORM}}, + // TPMI_RH_HIERARCHY_POLICY_DATA + {VALUES_MTYPE, + FOUR_BYTES, + (UINT8)TPM_RC_VALUE, + 1, + 4, + {RANGE(TPM_RH_ACT_0, TPM_RH_ACT_F, UINT32), + TPM_RH_OWNER, + TPM_RH_LOCKOUT, + TPM_RH_ENDORSEMENT, + TPM_RH_PLATFORM}}, + // TPMI_RH_PLATFORM_DATA + {TABLE_MTYPE, FOUR_BYTES, (UINT8)TPM_RC_VALUE, 1, {TPM_RH_PLATFORM}}, + // TPMI_RH_OWNER_DATA + {TABLE_MTYPE, + FOUR_BYTES | TAKES_NULL, + (UINT8)TPM_RC_VALUE, + 1, + {TPM_RH_NULL, TPM_RH_OWNER}}, + // TPMI_RH_ENDORSEMENT_DATA + {TABLE_MTYPE, + FOUR_BYTES | TAKES_NULL, + (UINT8)TPM_RC_VALUE, + 1, + {TPM_RH_NULL, TPM_RH_ENDORSEMENT}}, + // TPMI_RH_PROVISION_DATA + {TABLE_MTYPE, + FOUR_BYTES, + (UINT8)TPM_RC_VALUE, + 2, + {TPM_RH_OWNER, TPM_RH_PLATFORM}}, + // TPMI_RH_CLEAR_DATA + {TABLE_MTYPE, + FOUR_BYTES, + (UINT8)TPM_RC_VALUE, + 2, + {TPM_RH_LOCKOUT, TPM_RH_PLATFORM}}, + // TPMI_RH_NV_AUTH_DATA + {VALUES_MTYPE, + FOUR_BYTES, + (UINT8)TPM_RC_VALUE, + 1, + 2, + {RANGE(NV_INDEX_FIRST, NV_INDEX_LAST, UINT32), TPM_RH_OWNER, TPM_RH_PLATFORM}}, + // TPMI_RH_LOCKOUT_DATA + {TABLE_MTYPE, FOUR_BYTES, (UINT8)TPM_RC_VALUE, 1, {TPM_RH_LOCKOUT}}, + // TPMI_RH_NV_INDEX_DATA + {MIN_MAX_MTYPE, + FOUR_BYTES, + (UINT8)TPM_RC_VALUE, + {RANGE(NV_INDEX_FIRST, NV_INDEX_LAST, UINT32)}}, + // TPMI_RH_AC_DATA + {MIN_MAX_MTYPE, + FOUR_BYTES, + (UINT8)TPM_RC_VALUE, + {RANGE(AC_FIRST, AC_LAST, UINT32)}}, + // TPMI_RH_ACT_DATA + {MIN_MAX_MTYPE, + FOUR_BYTES, + (UINT8)TPM_RC_VALUE, + {RANGE(TPM_RH_ACT_0, TPM_RH_ACT_F, UINT32)}}, + // TPMI_ALG_HASH_DATA + {MIN_MAX_MTYPE, + TWO_BYTES | TAKES_NULL | HAS_BITS, + (UINT8)TPM_RC_HASH, + {TPM_ALG_NULL, + RANGE(4, 41, UINT16), + (UINT32)((ALG_SHA1 << 0) | (ALG_SHA256 << 7) | (ALG_SHA384 << 8) + | (ALG_SHA512 << 9) | (ALG_SM3_256 << 14)), + (UINT32)((ALG_SHA3_256 << 3) | (ALG_SHA3_384 << 4) | (ALG_SHA3_512 << 5))}}, + // TPMI_ALG_ASYM_DATA + {MIN_MAX_MTYPE, + TWO_BYTES | TAKES_NULL | HAS_BITS, + (UINT8)TPM_RC_ASYMMETRIC, + {TPM_ALG_NULL, + RANGE(1, 35, UINT16), + (UINT32)((ALG_RSA << 0)), + (UINT32)((ALG_ECC << 2))}}, + // TPMI_ALG_SYM_DATA + {MIN_MAX_MTYPE, + TWO_BYTES | TAKES_NULL | HAS_BITS, + (UINT8)TPM_RC_SYMMETRIC, + {TPM_ALG_NULL, + RANGE(3, 38, UINT16), + (UINT32)((ALG_TDES << 0) | (ALG_AES << 3) | (ALG_XOR << 7) | (ALG_SM4 << 16)), + (UINT32)((ALG_CAMELLIA << 3))}}, + // TPMI_ALG_SYM_OBJECT_DATA + {MIN_MAX_MTYPE, + TWO_BYTES | TAKES_NULL | HAS_BITS, + (UINT8)TPM_RC_SYMMETRIC, + {TPM_ALG_NULL, + RANGE(3, 38, UINT16), + (UINT32)((ALG_TDES << 0) | (ALG_AES << 3) | (ALG_SM4 << 16)), + (UINT32)((ALG_CAMELLIA << 3))}}, + // TPMI_ALG_SYM_MODE_DATA + {MIN_MAX_MTYPE, + TWO_BYTES | TAKES_NULL | HAS_BITS, + (UINT8)TPM_RC_MODE, + {TPM_ALG_NULL, + RANGE(63, 68, UINT16), + (UINT32)((ALG_CMAC << 0) | (ALG_CTR << 1) | (ALG_OFB << 2) | (ALG_CBC << 3) + | (ALG_CFB << 4) | (ALG_ECB << 5))}}, + // TPMI_ALG_KDF_DATA + {MIN_MAX_MTYPE, + TWO_BYTES | TAKES_NULL | HAS_BITS, + (UINT8)TPM_RC_KDF, + {TPM_ALG_NULL, + RANGE(7, 34, UINT16), + (UINT32)((ALG_MGF1 << 0) | (ALG_KDF1_SP800_56A << 25) | (ALG_KDF2 << 26) + | (ALG_KDF1_SP800_108 << 27))}}, + // TPMI_ALG_SIG_SCHEME_DATA + {MIN_MAX_MTYPE, + TWO_BYTES | TAKES_NULL | HAS_BITS, + (UINT8)TPM_RC_SCHEME, + {TPM_ALG_NULL, + RANGE(5, 28, UINT16), + (UINT32)((ALG_HMAC << 0) | (ALG_RSASSA << 15) | (ALG_RSAPSS << 17) + | (ALG_ECDSA << 19) | (ALG_ECDAA << 21) | (ALG_SM2 << 22) + | (ALG_ECSCHNORR << 23))}}, + // TPMI_ECC_KEY_EXCHANGE_DATA + {MIN_MAX_MTYPE, + TWO_BYTES | TAKES_NULL | HAS_BITS, + (UINT8)TPM_RC_SCHEME, + {TPM_ALG_NULL, + RANGE(25, 29, UINT16), + (UINT32)((ALG_ECDH << 0) | (ALG_SM2 << 2) | (ALG_ECMQV << 4))}}, + // TPMI_ST_COMMAND_TAG_DATA + {TABLE_MTYPE, + TWO_BYTES, + (UINT8)TPM_RC_BAD_TAG, + 2, + {TPM_ST_NO_SESSIONS, TPM_ST_SESSIONS}}, + // TPMI_ALG_MAC_SCHEME_DATA + {MIN_MAX_MTYPE, + TWO_BYTES | TAKES_NULL | HAS_BITS, + (UINT8)TPM_RC_SYMMETRIC, + {TPM_ALG_NULL, + RANGE(4, 63, UINT16), + (UINT32)((ALG_SHA1 << 0) | (ALG_SHA256 << 7) | (ALG_SHA384 << 8) + | (ALG_SHA512 << 9) | (ALG_SM3_256 << 14)), + (UINT32)((ALG_SHA3_256 << 3) | (ALG_SHA3_384 << 4) | (ALG_SHA3_512 << 5) + | (ALG_CMAC << 27))}}, + // TPMI_ALG_CIPHER_MODE_DATA + {MIN_MAX_MTYPE, + TWO_BYTES | TAKES_NULL | HAS_BITS, + (UINT8)TPM_RC_MODE, + {TPM_ALG_NULL, + RANGE(64, 68, UINT16), + (UINT32)((ALG_CTR << 0) | (ALG_OFB << 1) | (ALG_CBC << 2) | (ALG_CFB << 3) + | (ALG_ECB << 4))}}, + // TPMS_EMPTY_DATA + {STRUCTURE_MTYPE, 1, {SET_ELEMENT_TYPE(SIMPLE_STYPE), UINT0_MARSHAL_REF, 0}}, + // TPMS_ALGORITHM_DESCRIPTION_DATA + {STRUCTURE_MTYPE, + 2, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(TWO_BYTES), + TPM_ALG_ID_MARSHAL_REF, + (UINT16)(offsetof(TPMS_ALGORITHM_DESCRIPTION, alg)), + SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(FOUR_BYTES), + TPMA_ALGORITHM_MARSHAL_REF, + (UINT16)(offsetof(TPMS_ALGORITHM_DESCRIPTION, attributes))}}, + // TPMU_HA_DATA + {9, + IS_ARRAY_UNION, + (UINT16)(offsetof(TPMU_HA_mst, marshalingTypes)), + {(UINT32)TPM_ALG_SHA1, + (UINT32)TPM_ALG_SHA256, + (UINT32)TPM_ALG_SHA384, + (UINT32)TPM_ALG_SHA512, + (UINT32)TPM_ALG_SM3_256, + (UINT32)TPM_ALG_SHA3_256, + (UINT32)TPM_ALG_SHA3_384, + (UINT32)TPM_ALG_SHA3_512, + (UINT32)TPM_ALG_NULL}, + {(UINT16)(SHA1_DIGEST_SIZE), + (UINT16)(SHA256_DIGEST_SIZE), + (UINT16)(SHA384_DIGEST_SIZE), + (UINT16)(SHA512_DIGEST_SIZE), + (UINT16)(SM3_256_DIGEST_SIZE), + (UINT16)(SHA3_256_DIGEST_SIZE), + (UINT16)(SHA3_384_DIGEST_SIZE), + (UINT16)(SHA3_512_DIGEST_SIZE), + (UINT16)(0)}}, + // TPMT_HA_DATA + {STRUCTURE_MTYPE, + 2, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(TWO_BYTES) + | ELEMENT_PROPAGATE, + TPMI_ALG_HASH_MARSHAL_REF, + (UINT16)(offsetof(TPMT_HA, hashAlg)), + SET_ELEMENT_TYPE(UNION_STYPE) | SET_ELEMENT_NUMBER(0), + TPMU_HA_MARSHAL_REF, + (UINT16)(offsetof(TPMT_HA, digest))}}, + // TPM2B_DIGEST_DATA + {TPM2B_MTYPE, Type00_MARSHAL_REF}, + // TPM2B_DATA_DATA + {TPM2B_MTYPE, Type01_MARSHAL_REF}, + // TPM2B_EVENT_DATA + {TPM2B_MTYPE, Type02_MARSHAL_REF}, + // TPM2B_MAX_BUFFER_DATA + {TPM2B_MTYPE, Type03_MARSHAL_REF}, + // TPM2B_MAX_NV_BUFFER_DATA + {TPM2B_MTYPE, Type04_MARSHAL_REF}, + // TPM2B_TIMEOUT_DATA + {TPM2B_MTYPE, Type05_MARSHAL_REF}, + // TPM2B_IV_DATA + {TPM2B_MTYPE, Type06_MARSHAL_REF}, + // NULL_UNION_DATA + {0}, + // TPM2B_NAME_DATA + {TPM2B_MTYPE, Type07_MARSHAL_REF}, + // TPMS_PCR_SELECT_DATA + {STRUCTURE_MTYPE, + 2, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(ONE_BYTES), + Type08_MARSHAL_REF, + (UINT16)(offsetof(TPMS_PCR_SELECT, sizeofSelect)), + SET_ELEMENT_TYPE(ARRAY_STYPE) | SET_ELEMENT_NUMBER(0), + UINT8_ARRAY_MARSHAL_INDEX, + (UINT16)(offsetof(TPMS_PCR_SELECT, pcrSelect))}}, + // TPMS_PCR_SELECTION_DATA + {STRUCTURE_MTYPE, + 3, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(TWO_BYTES), + TPMI_ALG_HASH_MARSHAL_REF, + (UINT16)(offsetof(TPMS_PCR_SELECTION, hash)), + SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(ONE_BYTES), + Type08_MARSHAL_REF, + (UINT16)(offsetof(TPMS_PCR_SELECTION, sizeofSelect)), + SET_ELEMENT_TYPE(ARRAY_STYPE) | SET_ELEMENT_NUMBER(1), + UINT8_ARRAY_MARSHAL_INDEX, + (UINT16)(offsetof(TPMS_PCR_SELECTION, pcrSelect))}}, + // TPMT_TK_CREATION_DATA + {STRUCTURE_MTYPE, + 3, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(TWO_BYTES), + Type10_MARSHAL_REF, + (UINT16)(offsetof(TPMT_TK_CREATION, tag)), + SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(FOUR_BYTES), + TPMI_RH_HIERARCHY_MARSHAL_REF | NULL_FLAG, + (UINT16)(offsetof(TPMT_TK_CREATION, hierarchy)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_DIGEST_MARSHAL_REF, + (UINT16)(offsetof(TPMT_TK_CREATION, digest))}}, + // TPMT_TK_VERIFIED_DATA + {STRUCTURE_MTYPE, + 3, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(TWO_BYTES), + Type11_MARSHAL_REF, + (UINT16)(offsetof(TPMT_TK_VERIFIED, tag)), + SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(FOUR_BYTES), + TPMI_RH_HIERARCHY_MARSHAL_REF | NULL_FLAG, + (UINT16)(offsetof(TPMT_TK_VERIFIED, hierarchy)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_DIGEST_MARSHAL_REF, + (UINT16)(offsetof(TPMT_TK_VERIFIED, digest))}}, + // TPMT_TK_AUTH_DATA + {STRUCTURE_MTYPE, + 3, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(TWO_BYTES), + Type12_MARSHAL_REF, + (UINT16)(offsetof(TPMT_TK_AUTH, tag)), + SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(FOUR_BYTES), + TPMI_RH_HIERARCHY_MARSHAL_REF | NULL_FLAG, + (UINT16)(offsetof(TPMT_TK_AUTH, hierarchy)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_DIGEST_MARSHAL_REF, + (UINT16)(offsetof(TPMT_TK_AUTH, digest))}}, + // TPMT_TK_HASHCHECK_DATA + {STRUCTURE_MTYPE, + 3, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(TWO_BYTES), + Type13_MARSHAL_REF, + (UINT16)(offsetof(TPMT_TK_HASHCHECK, tag)), + SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(FOUR_BYTES), + TPMI_RH_HIERARCHY_MARSHAL_REF | NULL_FLAG, + (UINT16)(offsetof(TPMT_TK_HASHCHECK, hierarchy)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_DIGEST_MARSHAL_REF, + (UINT16)(offsetof(TPMT_TK_HASHCHECK, digest))}}, + // TPMS_ALG_PROPERTY_DATA + {STRUCTURE_MTYPE, + 2, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(TWO_BYTES), + TPM_ALG_ID_MARSHAL_REF, + (UINT16)(offsetof(TPMS_ALG_PROPERTY, alg)), + SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(FOUR_BYTES), + TPMA_ALGORITHM_MARSHAL_REF, + (UINT16)(offsetof(TPMS_ALG_PROPERTY, algProperties))}}, + // TPMS_TAGGED_PROPERTY_DATA + {STRUCTURE_MTYPE, + 2, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(FOUR_BYTES), + TPM_PT_MARSHAL_REF, + (UINT16)(offsetof(TPMS_TAGGED_PROPERTY, property)), + SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(FOUR_BYTES), + UINT32_MARSHAL_REF, + (UINT16)(offsetof(TPMS_TAGGED_PROPERTY, value))}}, + // TPMS_TAGGED_PCR_SELECT_DATA + {STRUCTURE_MTYPE, + 3, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(FOUR_BYTES), + TPM_PT_PCR_MARSHAL_REF, + (UINT16)(offsetof(TPMS_TAGGED_PCR_SELECT, tag)), + SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(ONE_BYTES), + Type08_MARSHAL_REF, + (UINT16)(offsetof(TPMS_TAGGED_PCR_SELECT, sizeofSelect)), + SET_ELEMENT_TYPE(ARRAY_STYPE) | SET_ELEMENT_NUMBER(1), + UINT8_ARRAY_MARSHAL_INDEX, + (UINT16)(offsetof(TPMS_TAGGED_PCR_SELECT, pcrSelect))}}, + // TPMS_TAGGED_POLICY_DATA + {STRUCTURE_MTYPE, + 2, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(FOUR_BYTES), + TPM_HANDLE_MARSHAL_REF, + (UINT16)(offsetof(TPMS_TAGGED_POLICY, handle)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPMT_HA_MARSHAL_REF, + (UINT16)(offsetof(TPMS_TAGGED_POLICY, policyHash))}}, + // TPMS_ACT_DATA_DATA + {STRUCTURE_MTYPE, + 3, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(FOUR_BYTES), + TPM_HANDLE_MARSHAL_REF, + (UINT16)(offsetof(TPMS_ACT_DATA, handle)), + SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(FOUR_BYTES), + UINT32_MARSHAL_REF, + (UINT16)(offsetof(TPMS_ACT_DATA, timeout)), + SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(FOUR_BYTES), + TPMA_ACT_MARSHAL_REF, + (UINT16)(offsetof(TPMS_ACT_DATA, attributes))}}, + // TPML_CC_DATA + {LIST_MTYPE, + (UINT8)(offsetof(TPML_CC, commandCodes)), + Type15_MARSHAL_REF, + TPM_CC_ARRAY_MARSHAL_INDEX}, + // TPML_CCA_DATA + {LIST_MTYPE, + (UINT8)(offsetof(TPML_CCA, commandAttributes)), + Type15_MARSHAL_REF, + TPMA_CC_ARRAY_MARSHAL_INDEX}, + // TPML_ALG_DATA + {LIST_MTYPE, + (UINT8)(offsetof(TPML_ALG, algorithms)), + Type17_MARSHAL_REF, + TPM_ALG_ID_ARRAY_MARSHAL_INDEX}, + // TPML_HANDLE_DATA + {LIST_MTYPE, + (UINT8)(offsetof(TPML_HANDLE, handle)), + Type18_MARSHAL_REF, + TPM_HANDLE_ARRAY_MARSHAL_INDEX}, + // TPML_DIGEST_DATA + {LIST_MTYPE, + (UINT8)(offsetof(TPML_DIGEST, digests)), + Type19_MARSHAL_REF, + TPM2B_DIGEST_ARRAY_MARSHAL_INDEX}, + // TPML_DIGEST_VALUES_DATA + {LIST_MTYPE, + (UINT8)(offsetof(TPML_DIGEST_VALUES, digests)), + Type20_MARSHAL_REF, + TPMT_HA_ARRAY_MARSHAL_INDEX}, + // TPML_PCR_SELECTION_DATA + {LIST_MTYPE, + (UINT8)(offsetof(TPML_PCR_SELECTION, pcrSelections)), + Type20_MARSHAL_REF, + TPMS_PCR_SELECTION_ARRAY_MARSHAL_INDEX}, + // TPML_ALG_PROPERTY_DATA + {LIST_MTYPE, + (UINT8)(offsetof(TPML_ALG_PROPERTY, algProperties)), + Type22_MARSHAL_REF, + TPMS_ALG_PROPERTY_ARRAY_MARSHAL_INDEX}, + // TPML_TAGGED_TPM_PROPERTY_DATA + {LIST_MTYPE, + (UINT8)(offsetof(TPML_TAGGED_TPM_PROPERTY, tpmProperty)), + Type23_MARSHAL_REF, + TPMS_TAGGED_PROPERTY_ARRAY_MARSHAL_INDEX}, + // TPML_TAGGED_PCR_PROPERTY_DATA + {LIST_MTYPE, + (UINT8)(offsetof(TPML_TAGGED_PCR_PROPERTY, pcrProperty)), + Type24_MARSHAL_REF, + TPMS_TAGGED_PCR_SELECT_ARRAY_MARSHAL_INDEX}, + // TPML_ECC_CURVE_DATA + {LIST_MTYPE, + (UINT8)(offsetof(TPML_ECC_CURVE, eccCurves)), + Type25_MARSHAL_REF, + TPM_ECC_CURVE_ARRAY_MARSHAL_INDEX}, + // TPML_TAGGED_POLICY_DATA + {LIST_MTYPE, + (UINT8)(offsetof(TPML_TAGGED_POLICY, policies)), + Type26_MARSHAL_REF, + TPMS_TAGGED_POLICY_ARRAY_MARSHAL_INDEX}, + // TPML_ACT_DATA_DATA + {LIST_MTYPE, + (UINT8)(offsetof(TPML_ACT_DATA, actData)), + Type27_MARSHAL_REF, + TPMS_ACT_DATA_ARRAY_MARSHAL_INDEX}, + // TPMU_CAPABILITIES_DATA + {11, + 0, + (UINT16)(offsetof(TPMU_CAPABILITIES_mst, marshalingTypes)), + {(UINT32)TPM_CAP_ALGS, + (UINT32)TPM_CAP_HANDLES, + (UINT32)TPM_CAP_COMMANDS, + (UINT32)TPM_CAP_PP_COMMANDS, + (UINT32)TPM_CAP_AUDIT_COMMANDS, + (UINT32)TPM_CAP_PCRS, + (UINT32)TPM_CAP_TPM_PROPERTIES, + (UINT32)TPM_CAP_PCR_PROPERTIES, + (UINT32)TPM_CAP_ECC_CURVES, + (UINT32)TPM_CAP_AUTH_POLICIES, + (UINT32)TPM_CAP_ACT}, + {(UINT16)(TPML_ALG_PROPERTY_MARSHAL_REF), + (UINT16)(TPML_HANDLE_MARSHAL_REF), + (UINT16)(TPML_CCA_MARSHAL_REF), + (UINT16)(TPML_CC_MARSHAL_REF), + (UINT16)(TPML_CC_MARSHAL_REF), + (UINT16)(TPML_PCR_SELECTION_MARSHAL_REF), + (UINT16)(TPML_TAGGED_TPM_PROPERTY_MARSHAL_REF), + (UINT16)(TPML_TAGGED_PCR_PROPERTY_MARSHAL_REF), + (UINT16)(TPML_ECC_CURVE_MARSHAL_REF), + (UINT16)(TPML_TAGGED_POLICY_MARSHAL_REF), + (UINT16)(TPML_ACT_DATA_MARSHAL_REF)}}, + // TPMS_CAPABILITY_DATA_DATA + {STRUCTURE_MTYPE, + 2, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(FOUR_BYTES), + TPM_CAP_MARSHAL_REF, + (UINT16)(offsetof(TPMS_CAPABILITY_DATA, capability)), + SET_ELEMENT_TYPE(UNION_STYPE) | SET_ELEMENT_NUMBER(0), + TPMU_CAPABILITIES_MARSHAL_REF, + (UINT16)(offsetof(TPMS_CAPABILITY_DATA, data))}}, + // TPMS_CLOCK_INFO_DATA + {STRUCTURE_MTYPE, + 4, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(EIGHT_BYTES), + UINT64_MARSHAL_REF, + (UINT16)(offsetof(TPMS_CLOCK_INFO, clock)), + SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(FOUR_BYTES), + UINT32_MARSHAL_REF, + (UINT16)(offsetof(TPMS_CLOCK_INFO, resetCount)), + SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(FOUR_BYTES), + UINT32_MARSHAL_REF, + (UINT16)(offsetof(TPMS_CLOCK_INFO, restartCount)), + SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(ONE_BYTES), + TPMI_YES_NO_MARSHAL_REF, + (UINT16)(offsetof(TPMS_CLOCK_INFO, safe))}}, + // TPMS_TIME_INFO_DATA + {STRUCTURE_MTYPE, + 2, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(EIGHT_BYTES), + UINT64_MARSHAL_REF, + (UINT16)(offsetof(TPMS_TIME_INFO, time)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPMS_CLOCK_INFO_MARSHAL_REF, + (UINT16)(offsetof(TPMS_TIME_INFO, clockInfo))}}, + // TPMS_TIME_ATTEST_INFO_DATA + {STRUCTURE_MTYPE, + 2, + {SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPMS_TIME_INFO_MARSHAL_REF, + (UINT16)(offsetof(TPMS_TIME_ATTEST_INFO, time)), + SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(EIGHT_BYTES), + UINT64_MARSHAL_REF, + (UINT16)(offsetof(TPMS_TIME_ATTEST_INFO, firmwareVersion))}}, + // TPMS_CERTIFY_INFO_DATA + {STRUCTURE_MTYPE, + 2, + {SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_NAME_MARSHAL_REF, + (UINT16)(offsetof(TPMS_CERTIFY_INFO, name)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_NAME_MARSHAL_REF, + (UINT16)(offsetof(TPMS_CERTIFY_INFO, qualifiedName))}}, + // TPMS_QUOTE_INFO_DATA + {STRUCTURE_MTYPE, + 2, + {SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPML_PCR_SELECTION_MARSHAL_REF, + (UINT16)(offsetof(TPMS_QUOTE_INFO, pcrSelect)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_DIGEST_MARSHAL_REF, + (UINT16)(offsetof(TPMS_QUOTE_INFO, pcrDigest))}}, + // TPMS_COMMAND_AUDIT_INFO_DATA + {STRUCTURE_MTYPE, + 4, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(EIGHT_BYTES), + UINT64_MARSHAL_REF, + (UINT16)(offsetof(TPMS_COMMAND_AUDIT_INFO, auditCounter)), + SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(TWO_BYTES), + TPM_ALG_ID_MARSHAL_REF, + (UINT16)(offsetof(TPMS_COMMAND_AUDIT_INFO, digestAlg)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_DIGEST_MARSHAL_REF, + (UINT16)(offsetof(TPMS_COMMAND_AUDIT_INFO, auditDigest)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_DIGEST_MARSHAL_REF, + (UINT16)(offsetof(TPMS_COMMAND_AUDIT_INFO, commandDigest))}}, + // TPMS_SESSION_AUDIT_INFO_DATA + {STRUCTURE_MTYPE, + 2, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(ONE_BYTES), + TPMI_YES_NO_MARSHAL_REF, + (UINT16)(offsetof(TPMS_SESSION_AUDIT_INFO, exclusiveSession)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_DIGEST_MARSHAL_REF, + (UINT16)(offsetof(TPMS_SESSION_AUDIT_INFO, sessionDigest))}}, + // TPMS_CREATION_INFO_DATA + {STRUCTURE_MTYPE, + 2, + {SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_NAME_MARSHAL_REF, + (UINT16)(offsetof(TPMS_CREATION_INFO, objectName)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_DIGEST_MARSHAL_REF, + (UINT16)(offsetof(TPMS_CREATION_INFO, creationHash))}}, + // TPMS_NV_CERTIFY_INFO_DATA + {STRUCTURE_MTYPE, + 3, + {SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_NAME_MARSHAL_REF, + (UINT16)(offsetof(TPMS_NV_CERTIFY_INFO, indexName)), + SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(TWO_BYTES), + UINT16_MARSHAL_REF, + (UINT16)(offsetof(TPMS_NV_CERTIFY_INFO, offset)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_MAX_NV_BUFFER_MARSHAL_REF, + (UINT16)(offsetof(TPMS_NV_CERTIFY_INFO, nvContents))}}, + // TPMS_NV_DIGEST_CERTIFY_INFO_DATA + {STRUCTURE_MTYPE, + 2, + {SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_NAME_MARSHAL_REF, + (UINT16)(offsetof(TPMS_NV_DIGEST_CERTIFY_INFO, indexName)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_DIGEST_MARSHAL_REF, + (UINT16)(offsetof(TPMS_NV_DIGEST_CERTIFY_INFO, nvDigest))}}, + // TPMI_ST_ATTEST_DATA + {VALUES_MTYPE, + TWO_BYTES, + (UINT8)TPM_RC_VALUE, + 1, + 1, + {RANGE(TPM_ST_ATTEST_NV, TPM_ST_ATTEST_CREATION, UINT16), + TPM_ST_ATTEST_NV_DIGEST}}, + // TPMU_ATTEST_DATA + {8, + 0, + (UINT16)(offsetof(TPMU_ATTEST_mst, marshalingTypes)), + {(UINT32)TPM_ST_ATTEST_CERTIFY, + (UINT32)TPM_ST_ATTEST_CREATION, + (UINT32)TPM_ST_ATTEST_QUOTE, + (UINT32)TPM_ST_ATTEST_COMMAND_AUDIT, + (UINT32)TPM_ST_ATTEST_SESSION_AUDIT, + (UINT32)TPM_ST_ATTEST_TIME, + (UINT32)TPM_ST_ATTEST_NV, + (UINT32)TPM_ST_ATTEST_NV_DIGEST}, + {(UINT16)(TPMS_CERTIFY_INFO_MARSHAL_REF), + (UINT16)(TPMS_CREATION_INFO_MARSHAL_REF), + (UINT16)(TPMS_QUOTE_INFO_MARSHAL_REF), + (UINT16)(TPMS_COMMAND_AUDIT_INFO_MARSHAL_REF), + (UINT16)(TPMS_SESSION_AUDIT_INFO_MARSHAL_REF), + (UINT16)(TPMS_TIME_ATTEST_INFO_MARSHAL_REF), + (UINT16)(TPMS_NV_CERTIFY_INFO_MARSHAL_REF), + (UINT16)(TPMS_NV_DIGEST_CERTIFY_INFO_MARSHAL_REF)}}, + // TPMS_ATTEST_DATA + {STRUCTURE_MTYPE, + 7, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(FOUR_BYTES), + TPM_CONSTANTS32_MARSHAL_REF, + (UINT16)(offsetof(TPMS_ATTEST, magic)), + SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(TWO_BYTES), + TPMI_ST_ATTEST_MARSHAL_REF, + (UINT16)(offsetof(TPMS_ATTEST, type)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_NAME_MARSHAL_REF, + (UINT16)(offsetof(TPMS_ATTEST, qualifiedSigner)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_DATA_MARSHAL_REF, + (UINT16)(offsetof(TPMS_ATTEST, extraData)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPMS_CLOCK_INFO_MARSHAL_REF, + (UINT16)(offsetof(TPMS_ATTEST, clockInfo)), + SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(EIGHT_BYTES), + UINT64_MARSHAL_REF, + (UINT16)(offsetof(TPMS_ATTEST, firmwareVersion)), + SET_ELEMENT_TYPE(UNION_STYPE) | SET_ELEMENT_NUMBER(1), + TPMU_ATTEST_MARSHAL_REF, + (UINT16)(offsetof(TPMS_ATTEST, attested))}}, + // TPM2B_ATTEST_DATA + {TPM2B_MTYPE, Type28_MARSHAL_REF}, + // TPMS_AUTH_COMMAND_DATA + {STRUCTURE_MTYPE, + 4, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(FOUR_BYTES), + TPMI_SH_AUTH_SESSION_MARSHAL_REF | NULL_FLAG, + (UINT16)(offsetof(TPMS_AUTH_COMMAND, sessionHandle)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_NONCE_MARSHAL_REF, + (UINT16)(offsetof(TPMS_AUTH_COMMAND, nonce)), + SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(ONE_BYTES), + TPMA_SESSION_MARSHAL_REF, + (UINT16)(offsetof(TPMS_AUTH_COMMAND, sessionAttributes)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_AUTH_MARSHAL_REF, + (UINT16)(offsetof(TPMS_AUTH_COMMAND, hmac))}}, + // TPMS_AUTH_RESPONSE_DATA + {STRUCTURE_MTYPE, + 3, + {SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_NONCE_MARSHAL_REF, + (UINT16)(offsetof(TPMS_AUTH_RESPONSE, nonce)), + SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(ONE_BYTES), + TPMA_SESSION_MARSHAL_REF, + (UINT16)(offsetof(TPMS_AUTH_RESPONSE, sessionAttributes)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_AUTH_MARSHAL_REF, + (UINT16)(offsetof(TPMS_AUTH_RESPONSE, hmac))}}, + // TPMI_TDES_KEY_BITS_DATA + {TABLE_MTYPE, TWO_BYTES, (UINT8)TPM_RC_VALUE, 1, {128 * TDES_128}}, + // TPMI_AES_KEY_BITS_DATA + {TABLE_MTYPE, + TWO_BYTES, + (UINT8)TPM_RC_VALUE, + 3, + {192 * AES_192, 128 * AES_128, 256 * AES_256}}, + // TPMI_SM4_KEY_BITS_DATA + {TABLE_MTYPE, TWO_BYTES, (UINT8)TPM_RC_VALUE, 1, {128 * SM4_128}}, + // TPMI_CAMELLIA_KEY_BITS_DATA + {TABLE_MTYPE, + TWO_BYTES, + (UINT8)TPM_RC_VALUE, + 3, + {192 * CAMELLIA_192, 128 * CAMELLIA_128, 256 * CAMELLIA_256}}, + // TPMU_SYM_KEY_BITS_DATA + {6, + 0, + (UINT16)(offsetof(TPMU_SYM_KEY_BITS_mst, marshalingTypes)), + {(UINT32)TPM_ALG_TDES, + (UINT32)TPM_ALG_AES, + (UINT32)TPM_ALG_SM4, + (UINT32)TPM_ALG_CAMELLIA, + (UINT32)TPM_ALG_XOR, + (UINT32)TPM_ALG_NULL}, + {(UINT16)(TPMI_TDES_KEY_BITS_MARSHAL_REF), + (UINT16)(TPMI_AES_KEY_BITS_MARSHAL_REF), + (UINT16)(TPMI_SM4_KEY_BITS_MARSHAL_REF), + (UINT16)(TPMI_CAMELLIA_KEY_BITS_MARSHAL_REF), + (UINT16)(TPMI_ALG_HASH_MARSHAL_REF), + (UINT16)(UINT0_MARSHAL_REF)}}, + // TPMU_SYM_MODE_DATA + {6, + 0, + (UINT16)(offsetof(TPMU_SYM_MODE_mst, marshalingTypes)), + {(UINT32)TPM_ALG_TDES, + (UINT32)TPM_ALG_AES, + (UINT32)TPM_ALG_SM4, + (UINT32)TPM_ALG_CAMELLIA, + (UINT32)TPM_ALG_XOR, + (UINT32)TPM_ALG_NULL}, + {(UINT16)(TPMI_ALG_SYM_MODE_MARSHAL_REF | NULL_FLAG), + (UINT16)(TPMI_ALG_SYM_MODE_MARSHAL_REF | NULL_FLAG), + (UINT16)(TPMI_ALG_SYM_MODE_MARSHAL_REF | NULL_FLAG), + (UINT16)(TPMI_ALG_SYM_MODE_MARSHAL_REF | NULL_FLAG), + (UINT16)(UINT0_MARSHAL_REF), + (UINT16)(UINT0_MARSHAL_REF)}}, + // TPMT_SYM_DEF_DATA + {STRUCTURE_MTYPE, + 3, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(TWO_BYTES) + | ELEMENT_PROPAGATE, + TPMI_ALG_SYM_MARSHAL_REF, + (UINT16)(offsetof(TPMT_SYM_DEF, algorithm)), + SET_ELEMENT_TYPE(UNION_STYPE) | SET_ELEMENT_NUMBER(0), + TPMU_SYM_KEY_BITS_MARSHAL_REF, + (UINT16)(offsetof(TPMT_SYM_DEF, keyBits)), + SET_ELEMENT_TYPE(UNION_STYPE) | SET_ELEMENT_NUMBER(0), + TPMU_SYM_MODE_MARSHAL_REF, + (UINT16)(offsetof(TPMT_SYM_DEF, mode))}}, + // TPMT_SYM_DEF_OBJECT_DATA + {STRUCTURE_MTYPE, + 3, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(TWO_BYTES) + | ELEMENT_PROPAGATE, + TPMI_ALG_SYM_OBJECT_MARSHAL_REF, + (UINT16)(offsetof(TPMT_SYM_DEF_OBJECT, algorithm)), + SET_ELEMENT_TYPE(UNION_STYPE) | SET_ELEMENT_NUMBER(0), + TPMU_SYM_KEY_BITS_MARSHAL_REF, + (UINT16)(offsetof(TPMT_SYM_DEF_OBJECT, keyBits)), + SET_ELEMENT_TYPE(UNION_STYPE) | SET_ELEMENT_NUMBER(0), + TPMU_SYM_MODE_MARSHAL_REF, + (UINT16)(offsetof(TPMT_SYM_DEF_OBJECT, mode))}}, + // TPM2B_SYM_KEY_DATA + {TPM2B_MTYPE, Type29_MARSHAL_REF}, + // TPMS_SYMCIPHER_PARMS_DATA + {STRUCTURE_MTYPE, + 1, + {SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPMT_SYM_DEF_OBJECT_MARSHAL_REF, + (UINT16)(offsetof(TPMS_SYMCIPHER_PARMS, sym))}}, + // TPM2B_LABEL_DATA + {TPM2B_MTYPE, Type30_MARSHAL_REF}, + // TPMS_DERIVE_DATA + {STRUCTURE_MTYPE, + 2, + {SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_LABEL_MARSHAL_REF, + (UINT16)(offsetof(TPMS_DERIVE, label)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_LABEL_MARSHAL_REF, + (UINT16)(offsetof(TPMS_DERIVE, context))}}, + // TPM2B_DERIVE_DATA + {TPM2B_MTYPE, Type31_MARSHAL_REF}, + // TPM2B_SENSITIVE_DATA_DATA + {TPM2B_MTYPE, Type32_MARSHAL_REF}, + // TPMS_SENSITIVE_CREATE_DATA + {STRUCTURE_MTYPE, + 2, + {SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_AUTH_MARSHAL_REF, + (UINT16)(offsetof(TPMS_SENSITIVE_CREATE, userAuth)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_SENSITIVE_DATA_MARSHAL_REF, + (UINT16)(offsetof(TPMS_SENSITIVE_CREATE, data))}}, + // TPM2B_SENSITIVE_CREATE_DATA + {TPM2BS_MTYPE, + (UINT8)(offsetof(TPM2B_SENSITIVE_CREATE, sensitive)) | SIZE_EQUAL, + UINT16_MARSHAL_REF, + TPMS_SENSITIVE_CREATE_MARSHAL_REF}, + // TPMS_SCHEME_HASH_DATA + {STRUCTURE_MTYPE, + 1, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(TWO_BYTES), + TPMI_ALG_HASH_MARSHAL_REF, + (UINT16)(offsetof(TPMS_SCHEME_HASH, hashAlg))}}, + // TPMS_SCHEME_ECDAA_DATA + {STRUCTURE_MTYPE, + 2, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(TWO_BYTES), + TPMI_ALG_HASH_MARSHAL_REF, + (UINT16)(offsetof(TPMS_SCHEME_ECDAA, hashAlg)), + SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(TWO_BYTES), + UINT16_MARSHAL_REF, + (UINT16)(offsetof(TPMS_SCHEME_ECDAA, count))}}, + // TPMI_ALG_KEYEDHASH_SCHEME_DATA + {MIN_MAX_MTYPE, + TWO_BYTES | TAKES_NULL | HAS_BITS, + (UINT8)TPM_RC_VALUE, + {TPM_ALG_NULL, + RANGE(5, 10, UINT16), + (UINT32)((ALG_HMAC << 0) | (ALG_XOR << 5))}}, + // TPMS_SCHEME_XOR_DATA + {STRUCTURE_MTYPE, + 2, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(TWO_BYTES), + TPMI_ALG_HASH_MARSHAL_REF, + (UINT16)(offsetof(TPMS_SCHEME_XOR, hashAlg)), + SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(TWO_BYTES), + TPMI_ALG_KDF_MARSHAL_REF | NULL_FLAG, + (UINT16)(offsetof(TPMS_SCHEME_XOR, kdf))}}, + // TPMU_SCHEME_KEYEDHASH_DATA + {3, + 0, + (UINT16)(offsetof(TPMU_SCHEME_KEYEDHASH_mst, marshalingTypes)), + {(UINT32)TPM_ALG_HMAC, (UINT32)TPM_ALG_XOR, (UINT32)TPM_ALG_NULL}, + {(UINT16)(TPMS_SCHEME_HMAC_MARSHAL_REF), + (UINT16)(TPMS_SCHEME_XOR_MARSHAL_REF), + (UINT16)(UINT0_MARSHAL_REF)}}, + // TPMT_KEYEDHASH_SCHEME_DATA + {STRUCTURE_MTYPE, + 2, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(TWO_BYTES) + | ELEMENT_PROPAGATE, + TPMI_ALG_KEYEDHASH_SCHEME_MARSHAL_REF, + (UINT16)(offsetof(TPMT_KEYEDHASH_SCHEME, scheme)), + SET_ELEMENT_TYPE(UNION_STYPE) | SET_ELEMENT_NUMBER(0), + TPMU_SCHEME_KEYEDHASH_MARSHAL_REF, + (UINT16)(offsetof(TPMT_KEYEDHASH_SCHEME, details))}}, + // TPMU_SIG_SCHEME_DATA + {8, + 0, + (UINT16)(offsetof(TPMU_SIG_SCHEME_mst, marshalingTypes)), + {(UINT32)TPM_ALG_ECDAA, + (UINT32)TPM_ALG_RSASSA, + (UINT32)TPM_ALG_RSAPSS, + (UINT32)TPM_ALG_ECDSA, + (UINT32)TPM_ALG_SM2, + (UINT32)TPM_ALG_ECSCHNORR, + (UINT32)TPM_ALG_HMAC, + (UINT32)TPM_ALG_NULL}, + {(UINT16)(TPMS_SIG_SCHEME_ECDAA_MARSHAL_REF), + (UINT16)(TPMS_SIG_SCHEME_RSASSA_MARSHAL_REF), + (UINT16)(TPMS_SIG_SCHEME_RSAPSS_MARSHAL_REF), + (UINT16)(TPMS_SIG_SCHEME_ECDSA_MARSHAL_REF), + (UINT16)(TPMS_SIG_SCHEME_SM2_MARSHAL_REF), + (UINT16)(TPMS_SIG_SCHEME_ECSCHNORR_MARSHAL_REF), + (UINT16)(TPMS_SCHEME_HMAC_MARSHAL_REF), + (UINT16)(UINT0_MARSHAL_REF)}}, + // TPMT_SIG_SCHEME_DATA + {STRUCTURE_MTYPE, + 2, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(TWO_BYTES) + | ELEMENT_PROPAGATE, + TPMI_ALG_SIG_SCHEME_MARSHAL_REF, + (UINT16)(offsetof(TPMT_SIG_SCHEME, scheme)), + SET_ELEMENT_TYPE(UNION_STYPE) | SET_ELEMENT_NUMBER(0), + TPMU_SIG_SCHEME_MARSHAL_REF, + (UINT16)(offsetof(TPMT_SIG_SCHEME, details))}}, + // TPMU_KDF_SCHEME_DATA + {5, + 0, + (UINT16)(offsetof(TPMU_KDF_SCHEME_mst, marshalingTypes)), + {(UINT32)TPM_ALG_MGF1, + (UINT32)TPM_ALG_KDF1_SP800_56A, + (UINT32)TPM_ALG_KDF2, + (UINT32)TPM_ALG_KDF1_SP800_108, + (UINT32)TPM_ALG_NULL}, + {(UINT16)(TPMS_KDF_SCHEME_MGF1_MARSHAL_REF), + (UINT16)(TPMS_KDF_SCHEME_KDF1_SP800_56A_MARSHAL_REF), + (UINT16)(TPMS_KDF_SCHEME_KDF2_MARSHAL_REF), + (UINT16)(TPMS_KDF_SCHEME_KDF1_SP800_108_MARSHAL_REF), + (UINT16)(UINT0_MARSHAL_REF)}}, + // TPMT_KDF_SCHEME_DATA + {STRUCTURE_MTYPE, + 2, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(TWO_BYTES) + | ELEMENT_PROPAGATE, + TPMI_ALG_KDF_MARSHAL_REF, + (UINT16)(offsetof(TPMT_KDF_SCHEME, scheme)), + SET_ELEMENT_TYPE(UNION_STYPE) | SET_ELEMENT_NUMBER(0), + TPMU_KDF_SCHEME_MARSHAL_REF, + (UINT16)(offsetof(TPMT_KDF_SCHEME, details))}}, + // TPMI_ALG_ASYM_SCHEME_DATA + {MIN_MAX_MTYPE, + TWO_BYTES | TAKES_NULL | HAS_BITS, + (UINT8)TPM_RC_VALUE, + {TPM_ALG_NULL, + RANGE(20, 29, UINT16), + (UINT32)((ALG_RSASSA << 0) | (ALG_RSAES << 1) | (ALG_RSAPSS << 2) + | (ALG_OAEP << 3) | (ALG_ECDSA << 4) | (ALG_ECDH << 5) + | (ALG_ECDAA << 6) | (ALG_SM2 << 7) | (ALG_ECSCHNORR << 8) + | (ALG_ECMQV << 9))}}, + // TPMU_ASYM_SCHEME_DATA + {11, + 0, + (UINT16)(offsetof(TPMU_ASYM_SCHEME_mst, marshalingTypes)), + {(UINT32)TPM_ALG_ECDH, + (UINT32)TPM_ALG_ECMQV, + (UINT32)TPM_ALG_ECDAA, + (UINT32)TPM_ALG_RSASSA, + (UINT32)TPM_ALG_RSAPSS, + (UINT32)TPM_ALG_ECDSA, + (UINT32)TPM_ALG_SM2, + (UINT32)TPM_ALG_ECSCHNORR, + (UINT32)TPM_ALG_RSAES, + (UINT32)TPM_ALG_OAEP, + (UINT32)TPM_ALG_NULL}, + {(UINT16)(TPMS_KEY_SCHEME_ECDH_MARSHAL_REF), + (UINT16)(TPMS_KEY_SCHEME_ECMQV_MARSHAL_REF), + (UINT16)(TPMS_SIG_SCHEME_ECDAA_MARSHAL_REF), + (UINT16)(TPMS_SIG_SCHEME_RSASSA_MARSHAL_REF), + (UINT16)(TPMS_SIG_SCHEME_RSAPSS_MARSHAL_REF), + (UINT16)(TPMS_SIG_SCHEME_ECDSA_MARSHAL_REF), + (UINT16)(TPMS_SIG_SCHEME_SM2_MARSHAL_REF), + (UINT16)(TPMS_SIG_SCHEME_ECSCHNORR_MARSHAL_REF), + (UINT16)(TPMS_ENC_SCHEME_RSAES_MARSHAL_REF), + (UINT16)(TPMS_ENC_SCHEME_OAEP_MARSHAL_REF), + (UINT16)(UINT0_MARSHAL_REF)}}, + // TPMI_ALG_RSA_SCHEME_DATA + {MIN_MAX_MTYPE, + TWO_BYTES | TAKES_NULL | HAS_BITS, + (UINT8)TPM_RC_VALUE, + {TPM_ALG_NULL, + RANGE(20, 23, UINT16), + (UINT32)((ALG_RSASSA << 0) | (ALG_RSAES << 1) | (ALG_RSAPSS << 2) + | (ALG_OAEP << 3))}}, + // TPMT_RSA_SCHEME_DATA + {STRUCTURE_MTYPE, + 2, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(TWO_BYTES) + | ELEMENT_PROPAGATE, + TPMI_ALG_RSA_SCHEME_MARSHAL_REF, + (UINT16)(offsetof(TPMT_RSA_SCHEME, scheme)), + SET_ELEMENT_TYPE(UNION_STYPE) | SET_ELEMENT_NUMBER(0), + TPMU_ASYM_SCHEME_MARSHAL_REF, + (UINT16)(offsetof(TPMT_RSA_SCHEME, details))}}, + // TPMI_ALG_RSA_DECRYPT_DATA + {MIN_MAX_MTYPE, + TWO_BYTES | TAKES_NULL | HAS_BITS, + (UINT8)TPM_RC_VALUE, + {TPM_ALG_NULL, + RANGE(21, 23, UINT16), + (UINT32)((ALG_RSAES << 0) | (ALG_OAEP << 2))}}, + // TPMT_RSA_DECRYPT_DATA + {STRUCTURE_MTYPE, + 2, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(TWO_BYTES) + | ELEMENT_PROPAGATE, + TPMI_ALG_RSA_DECRYPT_MARSHAL_REF, + (UINT16)(offsetof(TPMT_RSA_DECRYPT, scheme)), + SET_ELEMENT_TYPE(UNION_STYPE) | SET_ELEMENT_NUMBER(0), + TPMU_ASYM_SCHEME_MARSHAL_REF, + (UINT16)(offsetof(TPMT_RSA_DECRYPT, details))}}, + // TPM2B_PUBLIC_KEY_RSA_DATA + {TPM2B_MTYPE, Type33_MARSHAL_REF}, + // TPMI_RSA_KEY_BITS_DATA + {TABLE_MTYPE, + TWO_BYTES, + (UINT8)TPM_RC_VALUE, + 3, + {3072 * RSA_3072, 1024 * RSA_1024, 2048 * RSA_2048}}, + // TPM2B_PRIVATE_KEY_RSA_DATA + {TPM2B_MTYPE, Type34_MARSHAL_REF}, + // TPM2B_ECC_PARAMETER_DATA + {TPM2B_MTYPE, Type35_MARSHAL_REF}, + // TPMS_ECC_POINT_DATA + {STRUCTURE_MTYPE, + 2, + {SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_ECC_PARAMETER_MARSHAL_REF, + (UINT16)(offsetof(TPMS_ECC_POINT, x)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_ECC_PARAMETER_MARSHAL_REF, + (UINT16)(offsetof(TPMS_ECC_POINT, y))}}, + // TPM2B_ECC_POINT_DATA + {TPM2BS_MTYPE, + (UINT8)(offsetof(TPM2B_ECC_POINT, point)) | SIZE_EQUAL, + UINT16_MARSHAL_REF, + TPMS_ECC_POINT_MARSHAL_REF}, + // TPMI_ALG_ECC_SCHEME_DATA + {MIN_MAX_MTYPE, + TWO_BYTES | TAKES_NULL | HAS_BITS, + (UINT8)TPM_RC_SCHEME, + {TPM_ALG_NULL, + RANGE(24, 29, UINT16), + (UINT32)((ALG_ECDSA << 0) | (ALG_ECDH << 1) | (ALG_ECDAA << 2) | (ALG_SM2 << 3) + | (ALG_ECSCHNORR << 4) | (ALG_ECMQV << 5))}}, + // TPMI_ECC_CURVE_DATA + {MIN_MAX_MTYPE, + TWO_BYTES | HAS_BITS, + (UINT8)TPM_RC_CURVE, + {RANGE(1, 32, UINT16), + (UINT32)((ECC_NIST_P192 << 0) | (ECC_NIST_P224 << 1) | (ECC_NIST_P256 << 2) + | (ECC_NIST_P384 << 3) | (ECC_NIST_P521 << 4) | (ECC_BN_P256 << 15) + | (ECC_BN_P638 << 16) | (ECC_SM2_P256 << 31))}}, + // TPMT_ECC_SCHEME_DATA + {STRUCTURE_MTYPE, + 2, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(TWO_BYTES) + | ELEMENT_PROPAGATE, + TPMI_ALG_ECC_SCHEME_MARSHAL_REF, + (UINT16)(offsetof(TPMT_ECC_SCHEME, scheme)), + SET_ELEMENT_TYPE(UNION_STYPE) | SET_ELEMENT_NUMBER(0), + TPMU_ASYM_SCHEME_MARSHAL_REF, + (UINT16)(offsetof(TPMT_ECC_SCHEME, details))}}, + // TPMS_ALGORITHM_DETAIL_ECC_DATA + {STRUCTURE_MTYPE, + 11, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(TWO_BYTES), + TPM_ECC_CURVE_MARSHAL_REF, + (UINT16)(offsetof(TPMS_ALGORITHM_DETAIL_ECC, curveID)), + SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(TWO_BYTES), + UINT16_MARSHAL_REF, + (UINT16)(offsetof(TPMS_ALGORITHM_DETAIL_ECC, keySize)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPMT_KDF_SCHEME_MARSHAL_REF | NULL_FLAG, + (UINT16)(offsetof(TPMS_ALGORITHM_DETAIL_ECC, kdf)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPMT_ECC_SCHEME_MARSHAL_REF | NULL_FLAG, + (UINT16)(offsetof(TPMS_ALGORITHM_DETAIL_ECC, sign)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_ECC_PARAMETER_MARSHAL_REF, + (UINT16)(offsetof(TPMS_ALGORITHM_DETAIL_ECC, p)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_ECC_PARAMETER_MARSHAL_REF, + (UINT16)(offsetof(TPMS_ALGORITHM_DETAIL_ECC, a)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_ECC_PARAMETER_MARSHAL_REF, + (UINT16)(offsetof(TPMS_ALGORITHM_DETAIL_ECC, b)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_ECC_PARAMETER_MARSHAL_REF, + (UINT16)(offsetof(TPMS_ALGORITHM_DETAIL_ECC, gX)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_ECC_PARAMETER_MARSHAL_REF, + (UINT16)(offsetof(TPMS_ALGORITHM_DETAIL_ECC, gY)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_ECC_PARAMETER_MARSHAL_REF, + (UINT16)(offsetof(TPMS_ALGORITHM_DETAIL_ECC, n)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_ECC_PARAMETER_MARSHAL_REF, + (UINT16)(offsetof(TPMS_ALGORITHM_DETAIL_ECC, h))}}, + // TPMS_SIGNATURE_RSA_DATA + {STRUCTURE_MTYPE, + 2, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(TWO_BYTES), + TPMI_ALG_HASH_MARSHAL_REF, + (UINT16)(offsetof(TPMS_SIGNATURE_RSA, hash)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_PUBLIC_KEY_RSA_MARSHAL_REF, + (UINT16)(offsetof(TPMS_SIGNATURE_RSA, sig))}}, + // TPMS_SIGNATURE_ECC_DATA + {STRUCTURE_MTYPE, + 3, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(TWO_BYTES), + TPMI_ALG_HASH_MARSHAL_REF, + (UINT16)(offsetof(TPMS_SIGNATURE_ECC, hash)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_ECC_PARAMETER_MARSHAL_REF, + (UINT16)(offsetof(TPMS_SIGNATURE_ECC, signatureR)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_ECC_PARAMETER_MARSHAL_REF, + (UINT16)(offsetof(TPMS_SIGNATURE_ECC, signatureS))}}, + // TPMU_SIGNATURE_DATA + {8, + 0, + (UINT16)(offsetof(TPMU_SIGNATURE_mst, marshalingTypes)), + {(UINT32)TPM_ALG_ECDAA, + (UINT32)TPM_ALG_RSASSA, + (UINT32)TPM_ALG_RSAPSS, + (UINT32)TPM_ALG_ECDSA, + (UINT32)TPM_ALG_SM2, + (UINT32)TPM_ALG_ECSCHNORR, + (UINT32)TPM_ALG_HMAC, + (UINT32)TPM_ALG_NULL}, + {(UINT16)(TPMS_SIGNATURE_ECDAA_MARSHAL_REF), + (UINT16)(TPMS_SIGNATURE_RSASSA_MARSHAL_REF), + (UINT16)(TPMS_SIGNATURE_RSAPSS_MARSHAL_REF), + (UINT16)(TPMS_SIGNATURE_ECDSA_MARSHAL_REF), + (UINT16)(TPMS_SIGNATURE_SM2_MARSHAL_REF), + (UINT16)(TPMS_SIGNATURE_ECSCHNORR_MARSHAL_REF), + (UINT16)(TPMT_HA_MARSHAL_REF), + (UINT16)(UINT0_MARSHAL_REF)}}, + // TPMT_SIGNATURE_DATA + {STRUCTURE_MTYPE, + 2, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(TWO_BYTES) + | ELEMENT_PROPAGATE, + TPMI_ALG_SIG_SCHEME_MARSHAL_REF, + (UINT16)(offsetof(TPMT_SIGNATURE, sigAlg)), + SET_ELEMENT_TYPE(UNION_STYPE) | SET_ELEMENT_NUMBER(0), + TPMU_SIGNATURE_MARSHAL_REF, + (UINT16)(offsetof(TPMT_SIGNATURE, signature))}}, + // TPMU_ENCRYPTED_SECRET_DATA + {4, + IS_ARRAY_UNION, + (UINT16)(offsetof(TPMU_ENCRYPTED_SECRET_mst, marshalingTypes)), + {(UINT32)TPM_ALG_ECC, + (UINT32)TPM_ALG_RSA, + (UINT32)TPM_ALG_SYMCIPHER, + (UINT32)TPM_ALG_KEYEDHASH}, + {(UINT16)(sizeof(TPMS_ECC_POINT)), + (UINT16)(MAX_RSA_KEY_BYTES), + (UINT16)(sizeof(TPM2B_DIGEST)), + (UINT16)(sizeof(TPM2B_DIGEST))}}, + // TPM2B_ENCRYPTED_SECRET_DATA + {TPM2B_MTYPE, Type36_MARSHAL_REF}, + // TPMI_ALG_PUBLIC_DATA + {MIN_MAX_MTYPE, + TWO_BYTES | HAS_BITS, + (UINT8)TPM_RC_TYPE, + {RANGE(1, 37, UINT16), + (UINT32)((ALG_RSA << 0) | (ALG_KEYEDHASH << 7)), + (UINT32)((ALG_ECC << 2) | (ALG_SYMCIPHER << 4))}}, + // TPMU_PUBLIC_ID_DATA + {4, + 0, + (UINT16)(offsetof(TPMU_PUBLIC_ID_mst, marshalingTypes)), + {(UINT32)TPM_ALG_KEYEDHASH, + (UINT32)TPM_ALG_SYMCIPHER, + (UINT32)TPM_ALG_RSA, + (UINT32)TPM_ALG_ECC}, + {(UINT16)(TPM2B_DIGEST_MARSHAL_REF), + (UINT16)(TPM2B_DIGEST_MARSHAL_REF), + (UINT16)(TPM2B_PUBLIC_KEY_RSA_MARSHAL_REF), + (UINT16)(TPMS_ECC_POINT_MARSHAL_REF)}}, + // TPMS_KEYEDHASH_PARMS_DATA + {STRUCTURE_MTYPE, + 1, + {SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPMT_KEYEDHASH_SCHEME_MARSHAL_REF | NULL_FLAG, + (UINT16)(offsetof(TPMS_KEYEDHASH_PARMS, scheme))}}, + // TPMS_RSA_PARMS_DATA + {STRUCTURE_MTYPE, + 4, + {SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPMT_SYM_DEF_OBJECT_MARSHAL_REF | NULL_FLAG, + (UINT16)(offsetof(TPMS_RSA_PARMS, symmetric)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPMT_RSA_SCHEME_MARSHAL_REF | NULL_FLAG, + (UINT16)(offsetof(TPMS_RSA_PARMS, scheme)), + SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(TWO_BYTES), + TPMI_RSA_KEY_BITS_MARSHAL_REF, + (UINT16)(offsetof(TPMS_RSA_PARMS, keyBits)), + SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(FOUR_BYTES), + UINT32_MARSHAL_REF, + (UINT16)(offsetof(TPMS_RSA_PARMS, exponent))}}, + // TPMS_ECC_PARMS_DATA + {STRUCTURE_MTYPE, + 4, + {SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPMT_SYM_DEF_OBJECT_MARSHAL_REF | NULL_FLAG, + (UINT16)(offsetof(TPMS_ECC_PARMS, symmetric)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPMT_ECC_SCHEME_MARSHAL_REF | NULL_FLAG, + (UINT16)(offsetof(TPMS_ECC_PARMS, scheme)), + SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(TWO_BYTES), + TPMI_ECC_CURVE_MARSHAL_REF, + (UINT16)(offsetof(TPMS_ECC_PARMS, curveID)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPMT_KDF_SCHEME_MARSHAL_REF | NULL_FLAG, + (UINT16)(offsetof(TPMS_ECC_PARMS, kdf))}}, + // TPMU_PUBLIC_PARMS_DATA + {4, + 0, + (UINT16)(offsetof(TPMU_PUBLIC_PARMS_mst, marshalingTypes)), + {(UINT32)TPM_ALG_KEYEDHASH, + (UINT32)TPM_ALG_SYMCIPHER, + (UINT32)TPM_ALG_RSA, + (UINT32)TPM_ALG_ECC}, + {(UINT16)(TPMS_KEYEDHASH_PARMS_MARSHAL_REF), + (UINT16)(TPMS_SYMCIPHER_PARMS_MARSHAL_REF), + (UINT16)(TPMS_RSA_PARMS_MARSHAL_REF), + (UINT16)(TPMS_ECC_PARMS_MARSHAL_REF)}}, + // TPMT_PUBLIC_PARMS_DATA + {STRUCTURE_MTYPE, + 2, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(TWO_BYTES), + TPMI_ALG_PUBLIC_MARSHAL_REF, + (UINT16)(offsetof(TPMT_PUBLIC_PARMS, type)), + SET_ELEMENT_TYPE(UNION_STYPE) | SET_ELEMENT_NUMBER(0), + TPMU_PUBLIC_PARMS_MARSHAL_REF, + (UINT16)(offsetof(TPMT_PUBLIC_PARMS, parameters))}}, + // TPMT_PUBLIC_DATA + {STRUCTURE_MTYPE, + 6, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(TWO_BYTES), + TPMI_ALG_PUBLIC_MARSHAL_REF, + (UINT16)(offsetof(TPMT_PUBLIC, type)), + SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(TWO_BYTES) + | ELEMENT_PROPAGATE, + TPMI_ALG_HASH_MARSHAL_REF, + (UINT16)(offsetof(TPMT_PUBLIC, nameAlg)), + SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(FOUR_BYTES), + TPMA_OBJECT_MARSHAL_REF, + (UINT16)(offsetof(TPMT_PUBLIC, objectAttributes)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_DIGEST_MARSHAL_REF, + (UINT16)(offsetof(TPMT_PUBLIC, authPolicy)), + SET_ELEMENT_TYPE(UNION_STYPE) | SET_ELEMENT_NUMBER(0), + TPMU_PUBLIC_PARMS_MARSHAL_REF, + (UINT16)(offsetof(TPMT_PUBLIC, parameters)), + SET_ELEMENT_TYPE(UNION_STYPE) | SET_ELEMENT_NUMBER(0), + TPMU_PUBLIC_ID_MARSHAL_REF, + (UINT16)(offsetof(TPMT_PUBLIC, unique))}}, + // TPM2B_PUBLIC_DATA + {TPM2BS_MTYPE, + (UINT8)(offsetof(TPM2B_PUBLIC, publicArea)) | SIZE_EQUAL | ELEMENT_PROPAGATE, + UINT16_MARSHAL_REF, + TPMT_PUBLIC_MARSHAL_REF}, + // TPM2B_TEMPLATE_DATA + {TPM2B_MTYPE, Type37_MARSHAL_REF}, + // TPM2B_PRIVATE_VENDOR_SPECIFIC_DATA + {TPM2B_MTYPE, Type38_MARSHAL_REF}, + // TPMU_SENSITIVE_COMPOSITE_DATA + {4, + 0, + (UINT16)(offsetof(TPMU_SENSITIVE_COMPOSITE_mst, marshalingTypes)), + {(UINT32)TPM_ALG_RSA, + (UINT32)TPM_ALG_ECC, + (UINT32)TPM_ALG_KEYEDHASH, + (UINT32)TPM_ALG_SYMCIPHER}, + {(UINT16)(TPM2B_PRIVATE_KEY_RSA_MARSHAL_REF), + (UINT16)(TPM2B_ECC_PARAMETER_MARSHAL_REF), + (UINT16)(TPM2B_SENSITIVE_DATA_MARSHAL_REF), + (UINT16)(TPM2B_SYM_KEY_MARSHAL_REF)}}, + // TPMT_SENSITIVE_DATA + {STRUCTURE_MTYPE, + 4, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(TWO_BYTES), + TPMI_ALG_PUBLIC_MARSHAL_REF, + (UINT16)(offsetof(TPMT_SENSITIVE, sensitiveType)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_AUTH_MARSHAL_REF, + (UINT16)(offsetof(TPMT_SENSITIVE, authValue)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_DIGEST_MARSHAL_REF, + (UINT16)(offsetof(TPMT_SENSITIVE, seedValue)), + SET_ELEMENT_TYPE(UNION_STYPE) | SET_ELEMENT_NUMBER(0), + TPMU_SENSITIVE_COMPOSITE_MARSHAL_REF, + (UINT16)(offsetof(TPMT_SENSITIVE, sensitive))}}, + // TPM2B_SENSITIVE_DATA + {TPM2BS_MTYPE, + (UINT8)(offsetof(TPM2B_SENSITIVE, sensitiveArea)), + UINT16_MARSHAL_REF, + TPMT_SENSITIVE_MARSHAL_REF}, + // TPM2B_PRIVATE_DATA + {TPM2B_MTYPE, Type39_MARSHAL_REF}, + // TPM2B_ID_OBJECT_DATA + {TPM2B_MTYPE, Type40_MARSHAL_REF}, + // TPMS_NV_PIN_COUNTER_PARAMETERS_DATA + {STRUCTURE_MTYPE, + 2, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(FOUR_BYTES), + UINT32_MARSHAL_REF, + (UINT16)(offsetof(TPMS_NV_PIN_COUNTER_PARAMETERS, pinCount)), + SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(FOUR_BYTES), + UINT32_MARSHAL_REF, + (UINT16)(offsetof(TPMS_NV_PIN_COUNTER_PARAMETERS, pinLimit))}}, + // TPMA_NV_DATA + {ATTRIBUTES_MTYPE, FOUR_BYTES, 0x01F00300}, + // TPMS_NV_PUBLIC_DATA + {STRUCTURE_MTYPE, + 5, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(FOUR_BYTES), + TPMI_RH_NV_INDEX_MARSHAL_REF, + (UINT16)(offsetof(TPMS_NV_PUBLIC, nvIndex)), + SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(TWO_BYTES), + TPMI_ALG_HASH_MARSHAL_REF, + (UINT16)(offsetof(TPMS_NV_PUBLIC, nameAlg)), + SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(FOUR_BYTES), + TPMA_NV_MARSHAL_REF, + (UINT16)(offsetof(TPMS_NV_PUBLIC, attributes)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_DIGEST_MARSHAL_REF, + (UINT16)(offsetof(TPMS_NV_PUBLIC, authPolicy)), + SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(TWO_BYTES), + Type41_MARSHAL_REF, + (UINT16)(offsetof(TPMS_NV_PUBLIC, dataSize))}}, + // TPM2B_NV_PUBLIC_DATA + {TPM2BS_MTYPE, + (UINT8)(offsetof(TPM2B_NV_PUBLIC, nvPublic)) | SIZE_EQUAL, + UINT16_MARSHAL_REF, + TPMS_NV_PUBLIC_MARSHAL_REF}, + // TPM2B_CONTEXT_SENSITIVE_DATA + {TPM2B_MTYPE, Type42_MARSHAL_REF}, + // TPMS_CONTEXT_DATA_DATA + {STRUCTURE_MTYPE, + 2, + {SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_DIGEST_MARSHAL_REF, + (UINT16)(offsetof(TPMS_CONTEXT_DATA, integrity)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_CONTEXT_SENSITIVE_MARSHAL_REF, + (UINT16)(offsetof(TPMS_CONTEXT_DATA, encrypted))}}, + // TPM2B_CONTEXT_DATA_DATA + {TPM2B_MTYPE, Type43_MARSHAL_REF}, + // TPMS_CONTEXT_DATA + {STRUCTURE_MTYPE, + 4, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(EIGHT_BYTES), + UINT64_MARSHAL_REF, + (UINT16)(offsetof(TPMS_CONTEXT, sequence)), + SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(FOUR_BYTES), + TPMI_DH_SAVED_MARSHAL_REF, + (UINT16)(offsetof(TPMS_CONTEXT, savedHandle)), + SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(FOUR_BYTES), + TPMI_RH_HIERARCHY_MARSHAL_REF | NULL_FLAG, + (UINT16)(offsetof(TPMS_CONTEXT, hierarchy)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_CONTEXT_DATA_MARSHAL_REF, + (UINT16)(offsetof(TPMS_CONTEXT, contextBlob))}}, + // TPMS_CREATION_DATA_DATA + {STRUCTURE_MTYPE, + 7, + {SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPML_PCR_SELECTION_MARSHAL_REF, + (UINT16)(offsetof(TPMS_CREATION_DATA, pcrSelect)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_DIGEST_MARSHAL_REF, + (UINT16)(offsetof(TPMS_CREATION_DATA, pcrDigest)), + SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(ONE_BYTES), + TPMA_LOCALITY_MARSHAL_REF, + (UINT16)(offsetof(TPMS_CREATION_DATA, locality)), + SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(TWO_BYTES), + TPM_ALG_ID_MARSHAL_REF, + (UINT16)(offsetof(TPMS_CREATION_DATA, parentNameAlg)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_NAME_MARSHAL_REF, + (UINT16)(offsetof(TPMS_CREATION_DATA, parentName)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_NAME_MARSHAL_REF, + (UINT16)(offsetof(TPMS_CREATION_DATA, parentQualifiedName)), + SET_ELEMENT_TYPE(SIMPLE_STYPE), + TPM2B_DATA_MARSHAL_REF, + (UINT16)(offsetof(TPMS_CREATION_DATA, outsideInfo))}}, + // TPM2B_CREATION_DATA_DATA + {TPM2BS_MTYPE, + (UINT8)(offsetof(TPM2B_CREATION_DATA, creationData)) | SIZE_EQUAL, + UINT16_MARSHAL_REF, + TPMS_CREATION_DATA_MARSHAL_REF}, + // TPM_AT_DATA + {TABLE_MTYPE, + FOUR_BYTES, + (UINT8)TPM_RC_VALUE, + 4, + {TPM_AT_ANY, TPM_AT_ERROR, TPM_AT_PV1, TPM_AT_VEND}}, + // TPMS_AC_OUTPUT_DATA + {STRUCTURE_MTYPE, + 2, + {SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(FOUR_BYTES), + TPM_AT_MARSHAL_REF, + (UINT16)(offsetof(TPMS_AC_OUTPUT, tag)), + SET_ELEMENT_TYPE(SIMPLE_STYPE) | SET_ELEMENT_SIZE(FOUR_BYTES), + UINT32_MARSHAL_REF, + (UINT16)(offsetof(TPMS_AC_OUTPUT, data))}}, + // TPML_AC_CAPABILITIES_DATA + {LIST_MTYPE, + (UINT8)(offsetof(TPML_AC_CAPABILITIES, acCapabilities)), + Type44_MARSHAL_REF, + TPMS_AC_OUTPUT_ARRAY_MARSHAL_INDEX}, + // Type00_DATA + {MIN_MAX_MTYPE, + TWO_BYTES, + (UINT8)TPM_RC_SIZE, + {RANGE(0, sizeof(TPMU_HA), UINT16)}}, + // Type01_DATA + {MIN_MAX_MTYPE, + TWO_BYTES, + (UINT8)TPM_RC_SIZE, + {RANGE(0, sizeof(TPMT_HA), UINT16)}}, + // Type02_DATA + {MIN_MAX_MTYPE, TWO_BYTES, (UINT8)TPM_RC_SIZE, {RANGE(0, 1024, UINT16)}}, + // Type03_DATA + {MIN_MAX_MTYPE, + TWO_BYTES, + (UINT8)TPM_RC_SIZE, + {RANGE(0, MAX_DIGEST_BUFFER, UINT16)}}, + // Type04_DATA + {MIN_MAX_MTYPE, + TWO_BYTES, + (UINT8)TPM_RC_SIZE, + {RANGE(0, MAX_NV_BUFFER_SIZE, UINT16)}}, + // Type05_DATA + {MIN_MAX_MTYPE, + TWO_BYTES, + (UINT8)TPM_RC_SIZE, + {RANGE(0, sizeof(UINT64), UINT16)}}, + // Type06_DATA + {MIN_MAX_MTYPE, + TWO_BYTES, + (UINT8)TPM_RC_SIZE, + {RANGE(0, MAX_SYM_BLOCK_SIZE, UINT16)}}, + // Type07_DATA + {MIN_MAX_MTYPE, + TWO_BYTES, + (UINT8)TPM_RC_SIZE, + {RANGE(0, sizeof(TPMU_NAME), UINT16)}}, + // Type08_DATA + {MIN_MAX_MTYPE, + ONE_BYTES, + (UINT8)TPM_RC_VALUE, + {RANGE(PCR_SELECT_MIN, PCR_SELECT_MAX, UINT8)}}, + // Type10_DATA + {TABLE_MTYPE, TWO_BYTES, (UINT8)TPM_RC_TAG, 1, {TPM_ST_CREATION}}, + // Type11_DATA + {TABLE_MTYPE, TWO_BYTES, (UINT8)TPM_RC_TAG, 1, {TPM_ST_VERIFIED}}, + // Type12_DATA + {TABLE_MTYPE, + TWO_BYTES, + (UINT8)TPM_RC_TAG, + 2, + {TPM_ST_AUTH_SECRET, TPM_ST_AUTH_SIGNED}}, + // Type13_DATA + {TABLE_MTYPE, TWO_BYTES, (UINT8)TPM_RC_TAG, 1, {TPM_ST_HASHCHECK}}, + // Type15_DATA + {MIN_MAX_MTYPE, FOUR_BYTES, (UINT8)TPM_RC_SIZE, {RANGE(0, MAX_CAP_CC, UINT32)}}, + // Type17_DATA + {MIN_MAX_MTYPE, + FOUR_BYTES, + (UINT8)TPM_RC_SIZE, + {RANGE(0, MAX_ALG_LIST_SIZE, UINT32)}}, + // Type18_DATA + {MIN_MAX_MTYPE, + FOUR_BYTES, + (UINT8)TPM_RC_SIZE, + {RANGE(0, MAX_CAP_HANDLES, UINT32)}}, + // Type19_DATA + {MIN_MAX_MTYPE, FOUR_BYTES, (UINT8)TPM_RC_SIZE, {RANGE(2, 8, UINT32)}}, + // Type20_DATA + {MIN_MAX_MTYPE, FOUR_BYTES, (UINT8)TPM_RC_SIZE, {RANGE(0, HASH_COUNT, UINT32)}}, + // Type22_DATA + {MIN_MAX_MTYPE, FOUR_BYTES, (UINT8)TPM_RC_SIZE, {RANGE(0, MAX_CAP_ALGS, UINT32)}}, + // Type23_DATA + {MIN_MAX_MTYPE, + FOUR_BYTES, + (UINT8)TPM_RC_SIZE, + {RANGE(0, MAX_TPM_PROPERTIES, UINT32)}}, + // Type24_DATA + {MIN_MAX_MTYPE, + FOUR_BYTES, + (UINT8)TPM_RC_SIZE, + {RANGE(0, MAX_PCR_PROPERTIES, UINT32)}}, + // Type25_DATA + {MIN_MAX_MTYPE, + FOUR_BYTES, + (UINT8)TPM_RC_SIZE, + {RANGE(0, MAX_ECC_CURVES, UINT32)}}, + // Type26_DATA + {MIN_MAX_MTYPE, + FOUR_BYTES, + (UINT8)TPM_RC_SIZE, + {RANGE(0, MAX_TAGGED_POLICIES, UINT32)}}, + // Type27_DATA + {MIN_MAX_MTYPE, FOUR_BYTES, (UINT8)TPM_RC_SIZE, {RANGE(0, MAX_ACT_DATA, UINT32)}}, + // Type28_DATA + {MIN_MAX_MTYPE, + TWO_BYTES, + (UINT8)TPM_RC_SIZE, + {RANGE(0, sizeof(TPMS_ATTEST), UINT16)}}, + // Type29_DATA + {MIN_MAX_MTYPE, + TWO_BYTES, + (UINT8)TPM_RC_SIZE, + {RANGE(0, MAX_SYM_KEY_BYTES, UINT16)}}, + // Type30_DATA + {MIN_MAX_MTYPE, + TWO_BYTES, + (UINT8)TPM_RC_SIZE, + {RANGE(0, LABEL_MAX_BUFFER, UINT16)}}, + // Type31_DATA + {MIN_MAX_MTYPE, + TWO_BYTES, + (UINT8)TPM_RC_SIZE, + {RANGE(0, sizeof(TPMS_DERIVE), UINT16)}}, + // Type32_DATA + {MIN_MAX_MTYPE, + TWO_BYTES, + (UINT8)TPM_RC_SIZE, + {RANGE(0, sizeof(TPMU_SENSITIVE_CREATE), UINT16)}}, + // Type33_DATA + {MIN_MAX_MTYPE, + TWO_BYTES, + (UINT8)TPM_RC_SIZE, + {RANGE(0, MAX_RSA_KEY_BYTES, UINT16)}}, + // Type34_DATA + {MIN_MAX_MTYPE, + TWO_BYTES, + (UINT8)TPM_RC_SIZE, + {RANGE(0, RSA_PRIVATE_SIZE, UINT16)}}, + // Type35_DATA + {MIN_MAX_MTYPE, + TWO_BYTES, + (UINT8)TPM_RC_SIZE, + {RANGE(0, MAX_ECC_KEY_BYTES, UINT16)}}, + // Type36_DATA + {MIN_MAX_MTYPE, + TWO_BYTES, + (UINT8)TPM_RC_SIZE, + {RANGE(0, sizeof(TPMU_ENCRYPTED_SECRET), UINT16)}}, + // Type37_DATA + {MIN_MAX_MTYPE, + TWO_BYTES, + (UINT8)TPM_RC_SIZE, + {RANGE(0, sizeof(TPMT_PUBLIC), UINT16)}}, + // Type38_DATA + {MIN_MAX_MTYPE, + TWO_BYTES, + (UINT8)TPM_RC_SIZE, + {RANGE(0, PRIVATE_VENDOR_SPECIFIC_BYTES, UINT16)}}, + // Type39_DATA + {MIN_MAX_MTYPE, + TWO_BYTES, + (UINT8)TPM_RC_SIZE, + {RANGE(0, sizeof(_PRIVATE), UINT16)}}, + // Type40_DATA + {MIN_MAX_MTYPE, + TWO_BYTES, + (UINT8)TPM_RC_SIZE, + {RANGE(0, sizeof(TPMS_ID_OBJECT), UINT16)}}, + // Type41_DATA + {MIN_MAX_MTYPE, + TWO_BYTES, + (UINT8)TPM_RC_SIZE, + {RANGE(0, MAX_NV_INDEX_SIZE, UINT16)}}, + // Type42_DATA + {MIN_MAX_MTYPE, + TWO_BYTES, + (UINT8)TPM_RC_SIZE, + {RANGE(0, MAX_CONTEXT_SIZE, UINT16)}}, + // Type43_DATA + {MIN_MAX_MTYPE, + TWO_BYTES, + (UINT8)TPM_RC_SIZE, + {RANGE(0, sizeof(TPMS_CONTEXT_DATA), UINT16)}}, + // Type44_DATA + {MIN_MAX_MTYPE, + FOUR_BYTES, + (UINT8)TPM_RC_SIZE, + {RANGE(0, MAX_AC_CAPABILITIES, UINT32)}}}; +#endif // TABLE_DRIVEN_MARSHAL diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/TpmFail.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/TpmFail.c new file mode 100644 index 0000000..616a6d7 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/TpmFail.c @@ -0,0 +1,423 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Includes, Defines, and Types +#define TPM_FAIL_C +#include "Tpm.h" +#include + +// On MS C compiler, can save the alignment state and set the alignment to 1 for +// the duration of the TpmTypes.h include. This will avoid a lot of alignment +// warnings from the compiler for the unaligned structures. The alignment of the +// structures is not important as this function does not use any of the structures +// in TpmTypes.h and only include it for the #defines of the capabilities, +// properties, and command code values. +#include "TpmTypes.h" + +//** Typedefs +// These defines are used primarily for sizing of the local response buffer. +typedef struct +{ + TPM_ST tag; + UINT32 size; + TPM_RC code; +} HEADER; + +typedef struct +{ + BYTE tag[sizeof(TPM_ST)]; + BYTE size[sizeof(UINT32)]; + BYTE code[sizeof(TPM_RC)]; +} PACKED_HEADER; + +typedef struct +{ + BYTE size[sizeof(UINT16)]; + struct + { + BYTE function[sizeof(UINT32)]; + BYTE line[sizeof(UINT32)]; + BYTE code[sizeof(UINT32)]; + } values; + BYTE returnCode[sizeof(TPM_RC)]; +} GET_TEST_RESULT_PARAMETERS; + +typedef struct +{ + BYTE moreData[sizeof(TPMI_YES_NO)]; + BYTE capability[sizeof(TPM_CAP)]; // Always TPM_CAP_TPM_PROPERTIES + BYTE tpmProperty[sizeof(TPML_TAGGED_TPM_PROPERTY)]; +} GET_CAPABILITY_PARAMETERS; + +typedef struct +{ + BYTE header[sizeof(PACKED_HEADER)]; + BYTE getTestResult[sizeof(GET_TEST_RESULT_PARAMETERS)]; +} TEST_RESPONSE; + +typedef struct +{ + BYTE header[sizeof(PACKED_HEADER)]; + BYTE getCap[sizeof(GET_CAPABILITY_PARAMETERS)]; +} CAPABILITY_RESPONSE; + +typedef union +{ + BYTE test[sizeof(TEST_RESPONSE)]; + BYTE cap[sizeof(CAPABILITY_RESPONSE)]; +} RESPONSES; + +// Buffer to hold the responses. This may be a little larger than +// required due to padding that a compiler might add. +// Note: This is not in Global.c because of the specialized data definitions above. +// Since the data contained in this structure is not relevant outside of the +// execution of a single command (when the TPM is in failure mode. There is no +// compelling reason to move all the typedefs to Global.h and this structure +// to Global.c. +#ifndef __IGNORE_STATE__ // Don't define this value +static BYTE response[sizeof(RESPONSES)]; +#endif + +//** Local Functions + +//*** MarshalUint16() +// Function to marshal a 16 bit value to the output buffer. +static INT32 MarshalUint16(UINT16 integer, BYTE** buffer) +{ + UINT16_TO_BYTE_ARRAY(integer, *buffer); + *buffer += 2; + return 2; +} + +//*** MarshalUint32() +// Function to marshal a 32 bit value to the output buffer. +static INT32 MarshalUint32(UINT32 integer, BYTE** buffer) +{ + UINT32_TO_BYTE_ARRAY(integer, *buffer); + *buffer += 4; + return 4; +} + +//***Unmarshal32() +static BOOL Unmarshal32(UINT32* target, BYTE** buffer, INT32* size) +{ + if((*size -= 4) < 0) + return FALSE; + *target = BYTE_ARRAY_TO_UINT32(*buffer); + *buffer += 4; + return TRUE; +} + +//***Unmarshal16() +static BOOL Unmarshal16(UINT16* target, BYTE** buffer, INT32* size) +{ + if((*size -= 2) < 0) + return FALSE; + *target = BYTE_ARRAY_TO_UINT16(*buffer); + *buffer += 2; + return TRUE; +} + +//** Public Functions + +//*** SetForceFailureMode() +// This function is called by the simulator to enable failure mode testing. +#if SIMULATION +LIB_EXPORT void SetForceFailureMode(void) +{ + g_forceFailureMode = TRUE; + return; +} +#endif + +//*** TpmLogFailure() +// This function saves the failure values when the code will continue to operate. It +// if similar to TpmFail() but returns to the caller. The assumption is that the +// caller will propagate a failure back up the stack. +void TpmLogFailure( +#if FAIL_TRACE + const char* function, + int line, +#endif + int code) +{ + // Save the values that indicate where the error occurred. + // On a 64-bit machine, this may truncate the address of the string + // of the function name where the error occurred. +#if FAIL_TRACE + s_failFunction = (UINT32)(ptrdiff_t)function; + s_failLine = line; +#else + s_failFunction = 0; + s_failLine = 0; +#endif + s_failCode = code; + + // We are in failure mode + g_inFailureMode = TRUE; + + return; +} + +//*** TpmFail() +// This function is called by TPM.lib when a failure occurs. It will set up the +// failure values to be returned on TPM2_GetTestResult(). +NORETURN void TpmFail( +#if FAIL_TRACE + const char* function, + int line, +#endif + int code) +{ + // Save the values that indicate where the error occurred. + // On a 64-bit machine, this may truncate the address of the string + // of the function name where the error occurred. +#if FAIL_TRACE + s_failFunction = (UINT32)(ptrdiff_t)function; + s_failLine = line; +#else + s_failFunction = (UINT32)(ptrdiff_t)NULL; + s_failLine = 0; +#endif + s_failCode = code; + + // We are in failure mode + g_inFailureMode = TRUE; + + // if asserts are enabled, then do an assert unless the failure mode code + // is being tested. +#if SIMULATION +# ifndef NDEBUG + assert(g_forceFailureMode); +# endif + // Clear this flag + g_forceFailureMode = FALSE; +#endif + // Jump to the failure mode code. + // Note: only get here if asserts are off or if we are testing failure mode + _plat__Fail(); +} + +//*** TpmFailureMode( +// This function is called by the interface code when the platform is in failure +// mode. +void TpmFailureMode(unsigned int inRequestSize, // IN: command buffer size + unsigned char* inRequest, // IN: command buffer + unsigned int* outResponseSize, // OUT: response buffer size + unsigned char** outResponse // OUT: response buffer +) +{ + UINT32 marshalSize; + UINT32 capability; + HEADER header; // unmarshaled command header + UINT32 pt; // unmarshaled property type + UINT32 count; // unmarshaled property count + UINT8* buffer = inRequest; + INT32 size = inRequestSize; + + // If there is no command buffer, then just return TPM_RC_FAILURE + if(inRequestSize == 0 || inRequest == NULL) + goto FailureModeReturn; + // If the header is not correct for TPM2_GetCapability() or + // TPM2_GetTestResult() then just return the in failure mode response; + if(!(Unmarshal16(&header.tag, &buffer, &size) + && Unmarshal32(&header.size, &buffer, &size) + && Unmarshal32(&header.code, &buffer, &size))) + goto FailureModeReturn; + if(header.tag != TPM_ST_NO_SESSIONS || header.size < 10) + goto FailureModeReturn; + switch(header.code) + { + case TPM_CC_GetTestResult: + // make sure that the command size is correct + if(header.size != 10) + goto FailureModeReturn; + buffer = &response[10]; + marshalSize = MarshalUint16(3 * sizeof(UINT32), &buffer); + marshalSize += MarshalUint32(s_failFunction, &buffer); + marshalSize += MarshalUint32(s_failLine, &buffer); + marshalSize += MarshalUint32(s_failCode, &buffer); + if(s_failCode == FATAL_ERROR_NV_UNRECOVERABLE) + marshalSize += MarshalUint32(TPM_RC_NV_UNINITIALIZED, &buffer); + else + marshalSize += MarshalUint32(TPM_RC_FAILURE, &buffer); + break; + case TPM_CC_GetCapability: + // make sure that the size of the command is exactly the size + // returned for the capability, property, and count + if(header.size != (10 + (3 * sizeof(UINT32))) + // also verify that this is requesting TPM properties + || !Unmarshal32(&capability, &buffer, &size) + || capability != TPM_CAP_TPM_PROPERTIES + || !Unmarshal32(&pt, &buffer, &size) + || !Unmarshal32(&count, &buffer, &size)) + goto FailureModeReturn; + // If in failure mode because of an unrecoverable read error, and the + // property is 0 and the count is 0, then this is an indication to + // re-manufacture the TPM. Do the re-manufacture but stay in failure + // mode until the TPM is reset. + // Note: this behavior is not required by the specification and it is + // OK to leave the TPM permanently bricked due to an unrecoverable NV + // error. + if(count == 0 && pt == 0 && s_failCode == FATAL_ERROR_NV_UNRECOVERABLE) + { + g_manufactured = FALSE; + TPM_Manufacture(0); + } + if(count > 0) + count = 1; + else if(pt > TPM_PT_FIRMWARE_VERSION_2) + count = 0; + if(pt < TPM_PT_MANUFACTURER) + pt = TPM_PT_MANUFACTURER; + // set up for return + buffer = &response[10]; + // if the request was for a PT less than the last one + // then we indicate more, otherwise, not. + if(pt < TPM_PT_FIRMWARE_VERSION_2) + *buffer++ = YES; + else + *buffer++ = NO; + marshalSize = 1; + + // indicate the capability type + marshalSize += MarshalUint32(capability, &buffer); + // indicate the number of values that are being returned (0 or 1) + marshalSize += MarshalUint32(count, &buffer); + // indicate the property + marshalSize += MarshalUint32(pt, &buffer); + + if(count > 0) + switch(pt) + { + case TPM_PT_MANUFACTURER: + // the vendor ID unique to each TPM manufacturer +#ifdef MANUFACTURER + pt = *(UINT32*)MANUFACTURER; +#else + pt = 0; +#endif + break; + case TPM_PT_VENDOR_STRING_1: + // the first four characters of the vendor ID string +#ifdef VENDOR_STRING_1 + pt = *(UINT32*)VENDOR_STRING_1; +#else + pt = 0; +#endif + break; + case TPM_PT_VENDOR_STRING_2: + // the second four characters of the vendor ID string +#ifdef VENDOR_STRING_2 + pt = *(UINT32*)VENDOR_STRING_2; +#else + pt = 0; +#endif + break; + case TPM_PT_VENDOR_STRING_3: + // the third four characters of the vendor ID string +#ifdef VENDOR_STRING_3 + pt = *(UINT32*)VENDOR_STRING_3; +#else + pt = 0; +#endif + break; + case TPM_PT_VENDOR_STRING_4: + // the fourth four characters of the vendor ID string +#ifdef VENDOR_STRING_4 + pt = *(UINT32*)VENDOR_STRING_4; +#else + pt = 0; +#endif + break; + case TPM_PT_VENDOR_TPM_TYPE: + // vendor-defined value indicating the TPM model + // We just make up a number here + pt = 1; + break; + case TPM_PT_FIRMWARE_VERSION_1: + // the more significant 32-bits of a vendor-specific value + // indicating the version of the firmware +#ifdef FIRMWARE_V1 + pt = FIRMWARE_V1; +#else + pt = 0; +#endif + break; + default: // TPM_PT_FIRMWARE_VERSION_2: + // the less significant 32-bits of a vendor-specific value + // indicating the version of the firmware +#ifdef FIRMWARE_V2 + pt = FIRMWARE_V2; +#else + pt = 0; +#endif + break; + } + marshalSize += MarshalUint32(pt, &buffer); + break; + default: // default for switch (cc) + goto FailureModeReturn; + } + // Now do the header + buffer = response; + marshalSize = marshalSize + 10; // Add the header size to the + // stuff already marshaled + MarshalUint16(TPM_ST_NO_SESSIONS, &buffer); // structure tag + MarshalUint32(marshalSize, &buffer); // responseSize + MarshalUint32(TPM_RC_SUCCESS, &buffer); // response code + + *outResponseSize = marshalSize; + *outResponse = (unsigned char*)&response; + return; +FailureModeReturn: + buffer = response; + marshalSize = MarshalUint16(TPM_ST_NO_SESSIONS, &buffer); + marshalSize += MarshalUint32(10, &buffer); + marshalSize += MarshalUint32(TPM_RC_FAILURE, &buffer); + *outResponseSize = marshalSize; + *outResponse = (unsigned char*)response; + return; +} + +//*** UnmarshalFail() +// This is a stub that is used to catch an attempt to unmarshal an entry +// that is not defined. Don't ever expect this to be called but... +void UnmarshalFail(void* type, BYTE** buffer, INT32* size) +{ + NOT_REFERENCED(type); + NOT_REFERENCED(buffer); + NOT_REFERENCED(size); + FAIL(FATAL_ERROR_INTERNAL); +} \ No newline at end of file diff --git a/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/TpmSizeChecks.c b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/TpmSizeChecks.c new file mode 100644 index 0000000..5b3fe71 --- /dev/null +++ b/optee/samples/ms-tpm-20-ref/TPMCmd/tpm/src/support/TpmSizeChecks.c @@ -0,0 +1,216 @@ +/* Microsoft Reference Implementation for TPM 2.0 + * + * The copyright in this software is being made available under the BSD License, + * included below. This software may be subject to other third party and + * contributor rights, including patent rights, and no such rights are granted + * under this license. + * + * Copyright (c) Microsoft Corporation + * + * All rights reserved. + * + * BSD License + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +//** Includes, Defines, and Types +#include "Tpm.h" +#include +#include +#include "Marshal.h" + +#if RUNTIME_SIZE_CHECKS + +# if DEBUG +static int once = 0; +# endif + +//** TpmSizeChecks() +// This function is used during the development process to make sure that the +// vendor-specific values result in a consistent implementation. When possible, +// the code contains #if to do compile-time checks. However, in some cases, the +// values require the use of "sizeof()" and that can't be used in an #if. +BOOL TpmSizeChecks(void) +{ + BOOL PASS = TRUE; + +# if DEBUG + // + if(once++ != 0) + return 1; + +# if ALG_ECC + { + // This is just to allow simple access to the ecc curve data during debug + const ECC_CURVE* ecc = CryptEccGetParametersByCurveId(3); + if(ecc == NULL) + ecc = NULL; + } +# endif // ALG_ECC + { + UINT32 maxAsymSecurityStrength = MAX_ASYM_SECURITY_STRENGTH; + UINT32 maxHashSecurityStrength = MAX_HASH_SECURITY_STRENGTH; + UINT32 maxSymSecurityStrength = MAX_SYM_SECURITY_STRENGTH; + UINT32 maxSecurityStrengthBits = MAX_SECURITY_STRENGTH_BITS; + UINT32 proofSize = PROOF_SIZE; + UINT32 compliantProofSize = COMPLIANT_PROOF_SIZE; + UINT32 compliantPrimarySeedSize = COMPLIANT_PRIMARY_SEED_SIZE; + UINT32 primarySeedSize = PRIMARY_SEED_SIZE; + + UINT32 cmacState = sizeof(tpmCmacState_t); + UINT32 hashState = sizeof(HASH_STATE); + UINT32 keyScheduleSize = sizeof(tpmCryptKeySchedule_t); + // + NOT_REFERENCED(cmacState); + NOT_REFERENCED(hashState); + NOT_REFERENCED(keyScheduleSize); + NOT_REFERENCED(maxAsymSecurityStrength); + NOT_REFERENCED(maxHashSecurityStrength); + NOT_REFERENCED(maxSymSecurityStrength); + NOT_REFERENCED(maxSecurityStrengthBits); + NOT_REFERENCED(proofSize); + NOT_REFERENCED(compliantProofSize); + NOT_REFERENCED(compliantPrimarySeedSize); + NOT_REFERENCED(primarySeedSize); + + { + TPMT_SENSITIVE* p; + // This assignment keeps compiler from complaining about a conditional + // comparison being between two constants + UINT16 max_rsa_key_bytes = MAX_RSA_KEY_BYTES; + if((max_rsa_key_bytes / 2) != (sizeof(p->sensitive.rsa.t.buffer) / 5)) + { + printf("Sensitive part of TPMT_SENSITIVE is undersized. May be caused" + " by use of wrong version of Part 2.\n"); + PASS = FALSE; + } + } +# if TABLE_DRIVEN_MARSHAL + printf("sizeof(MarshalData) = %zu\n", sizeof(MarshalData_st)); +# endif + + printf("Size of OBJECT = %zu\n", sizeof(OBJECT)); + printf("Size of components in TPMT_SENSITIVE = %zu\n", + sizeof(TPMT_SENSITIVE)); + printf(" TPMI_ALG_PUBLIC %zu\n", sizeof(TPMI_ALG_PUBLIC)); + printf(" TPM2B_AUTH %zu\n", sizeof(TPM2B_AUTH)); + printf(" TPM2B_DIGEST %zu\n", sizeof(TPM2B_DIGEST)); + printf(" TPMU_SENSITIVE_COMPOSITE %zu\n", + sizeof(TPMU_SENSITIVE_COMPOSITE)); + } + // Make sure that the size of the context blob is large enough for the largest + // context + // TPMS_CONTEXT_DATA contains two TPM2B values. That is not how this is + // implemented. Rather, the size field of the TPM2B_CONTEXT_DATA is used to + // determine the amount of data in the encrypted data. That part is not + // independently sized. This makes the actual size 2 bytes smaller than + // calculated using Part 2. Since this is opaque to the caller, it is not + // necessary to fix. The actual size is returned by TPM2_GetCapabilties(). + + // Initialize output handle. At the end of command action, the output + // handle of an object will be replaced, while the output handle + // for a session will be the same as input + + // Get the size of fingerprint in context blob. The sequence value in + // TPMS_CONTEXT structure is used as the fingerprint + { + UINT32 fingerprintSize = sizeof(UINT64); + UINT32 integritySize = + sizeof(UINT16) + CryptHashGetDigestSize(CONTEXT_INTEGRITY_HASH_ALG); + UINT32 biggestObject = + MAX(MAX(sizeof(HASH_OBJECT), sizeof(OBJECT)), sizeof(SESSION)); + UINT32 biggestContext = fingerprintSize + integritySize + biggestObject; + + // round required size up to nearest 8 byte boundary. + biggestContext = 8 * ((biggestContext + 7) / 8); + + if(MAX_CONTEXT_SIZE < biggestContext) + { + printf("MAX_CONTEXT_SIZE needs to be increased to at least %d (%d)\n", + biggestContext, + MAX_CONTEXT_SIZE); + PASS = FALSE; + } + else if(MAX_CONTEXT_SIZE > biggestContext) + { + printf("MAX_CONTEXT_SIZE can be reduced to %d (%d)\n", + biggestContext, + MAX_CONTEXT_SIZE); + } + } + { + union u + { + TPMA_OBJECT attributes; + UINT32 uint32Value; + } u; + // these are defined so that compiler doesn't complain about conditional + // expressions comparing two constants. + int aSize = sizeof(u.attributes); + int uSize = sizeof(u.uint32Value); + u.uint32Value = 0; + SET_ATTRIBUTE(u.attributes, TPMA_OBJECT, fixedTPM); + if(u.uint32Value != 2) + { + printf("The bit allocation in a TPMA_OBJECT is not as expected"); + PASS = FALSE; + } + if(aSize != uSize) // comparison of two sizeof() values annoys compiler + { + printf("A TPMA_OBJECT is not the expected size."); + PASS = FALSE; + } + } + // Check that the platorm implementes each of the ACT that the TPM thinks are + // present + { + uint32_t act; + for(act = 0; act < 16; act++) + { + switch(act) + { + FOR_EACH_ACT(CASE_ACT_NUMBER) + if(!_plat__ACT_GetImplemented(act)) + { + printf("TPM_RH_ACT_%1X is not implemented by platform\n", act); + PASS = FALSE; + } + default: + break; + } + } + } + { + // Had a problem with the macros coming up with some bad values. Make sure + // the size is rational + int t = MAX_DIGEST_SIZE; + if(t < 20) + { + printf("Check the MAX_DIGEST_SIZE computation (%d)", MAX_DIGEST_SIZE); + PASS = FALSE; + } + } +# endif // DEBUG + return (PASS); +} + +#endif // RUNTIME_SIZE_CHECKS \ No newline at end of file diff --git a/optee/samples/pkcs11-sample/LICENSE b/optee/samples/pkcs11-sample/LICENSE new file mode 100644 index 0000000..7ebc290 --- /dev/null +++ b/optee/samples/pkcs11-sample/LICENSE @@ -0,0 +1,23 @@ +Copyright (c) 2024 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 the source code must retain the above copyright notice, +this list of conditions, and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions, and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (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/pkcs11-sample/Makefile b/optee/samples/pkcs11-sample/Makefile new file mode 100644 index 0000000..e58838c --- /dev/null +++ b/optee/samples/pkcs11-sample/Makefile @@ -0,0 +1,27 @@ +# Copyright (c) 2024, 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 host \ + CROSS_COMPILE=$(CROSS_COMPILE) \ + OPTEE_CLIENT_EXPORT=$(OPTEE_CLIENT_EXPORT) \ + O=$(O)/ca/$(TARGET_DIR) \ + --no-builtin-variables + +.PHONY: clean +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/pkcs11-sample/host/Makefile b/optee/samples/pkcs11-sample/host/Makefile new file mode 100644 index 0000000..6212e02 --- /dev/null +++ b/optee/samples/pkcs11-sample/host/Makefile @@ -0,0 +1,37 @@ +# Copyright (c) 2024, 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./include +CFLAGS += -I$(OPTEE_CLIENT_EXPORT)/include +CFLAGS += -fstack-protector-strong +LDADD += -lteec -lckteec -L$(OPTEE_CLIENT_EXPORT)/lib + +SRCS = pkcs11_sample_ca.c +OBJS = $(patsubst %.c,$(O)/%.o,$(SRCS)) +BINARY = nvpkcs11-sample-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/pkcs11-sample/host/pkcs11_sample_ca.c b/optee/samples/pkcs11-sample/host/pkcs11_sample_ca.c new file mode 100644 index 0000000..8214b84 --- /dev/null +++ b/optee/samples/pkcs11-sample/host/pkcs11_sample_ca.c @@ -0,0 +1,367 @@ +/* + * Copyright (c) 2024, NVIDIA Corporation & AFFILIATES. All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * auth_type enumerates the types of user authentication + * + * PIN_AUTH Pin authentication. + * ACL_AUTH ACL authentication. + */ +enum auth_type { PIN_AUTH, ACL_AUTH }; + +#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) + +/* + * 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 test_token_user_pin[] = { '1', '2', '3', '4', '5' }; +static CK_UTF8CHAR test_token_label[] = "PKCS11 TA test token"; + +/* + * Some PKCS#11 object resources used in the tests + */ + +static CK_BYTE cktest_aes128_iv[16] = {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_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); +} + +/* + * This function initialize the pkcs11 and find an empty slot. + * If there are multiple slots available, the last one slot will be used. + */ +static CK_RV init_pkcs11_and_find_empty_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; + + if (!slot) + return CKR_GENERAL_ERROR; + + rv = C_Initialize(0); + if (rv) + return rv; + + rv = C_GetSlotList(CK_TRUE, NULL, &count); + if (rv != CKR_OK) + goto out; + + if (count < 1) { + rv = CKR_GENERAL_ERROR; + goto out; + } + + slots = malloc(count * sizeof(CK_SLOT_ID)); + if (!slots) { + rv = CKR_HOST_MEMORY; + goto out; + } + + rv = C_GetSlotList(CK_TRUE, slots, &count); + if (rv) + goto out; + + 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; + } + +out: + if (slots) + free(slots); + if (rv) + close_lib(); + + 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); + return rv; + } + + rv = C_InitPIN(session, test_token_user_pin, + sizeof(test_token_user_pin)); + + C_Logout(session); + C_CloseSession(session); + + return rv; +} + +#define WRAPPED_TEST_KEY_SIZE 48 + +static CK_RV pkcs11_wrap_key() +{ + 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_key = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE key = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE unwrapped_key = CK_INVALID_HANDLE; + 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 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 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_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_pkcs11_and_find_empty_slot(&slot, PIN_AUTH); + if (rv != CKR_OK) { + printf("init_pkcs11_and_find_empty_slot failed with rv = 0x%08lx\n", rv); + return rv; + } + + rv = C_InitToken(slot, test_token_so_pin, sizeof(test_token_so_pin), test_token_label); + if (rv != CKR_OK) { + printf("C_InitToken failed with rv = 0x%08lx\n", rv); + goto close_lib; + } + + rv = init_user_test_token_pin_auth(slot); + if (rv != CKR_OK) { + printf("init_user_test_token_pin_auth failed with rv = 0x%08lx\n", rv); + goto close_lib; + } + + rv = C_OpenSession(slot, session_flags, NULL, 0, &session); + if (rv != CKR_OK) { + printf("C_OpenSession failed with rv = 0x%08lx\n", rv); + goto close_lib; + } + + /* Generate a wrapping Key */ + rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism, + wrapping_key_template, + ARRAY_SIZE(wrapping_key_template), &wrapping_key); + if (rv != CKR_OK) { + printf("C_GenerateKey generate wrapping key failed with rv = 0x%08lx\n", rv); + goto close_session; + } + + /* Generate a application key */ + rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism, + key_template, ARRAY_SIZE(key_template), + &key); + if (rv != CKR_OK) { + printf("C_GenerateKey generate application key failed with rv = 0x%08lx\n", rv); + goto close_session; + } + + printf("Test key wrap with AES CBC\n"); + + /* Generate random IV */ + rv = C_GenerateRandom(session, cktest_aes128_iv, sizeof(cktest_aes128_iv)); + if (rv != CKR_OK) { + printf("C_GenerateRandom failed with rv = 0x%08lx\n", rv); + goto out; + } + + size = 16; + /* Warp application key with wrapping key */ + rv = C_WrapKey(session, &cktest_aes_cbc_mechanism, wrapping_key, key, + buf, &size); + if (rv != CKR_OK) { + printf("C_WrapKey failed with rv = 0x%08lx\n", 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 (rv != CKR_OK) { + printf("C_GetAttributeValue (original key) failed with rv = 0x%08lx\n", rv); + goto out; + } + + printf("Test key unwrap with AES CBC\n"); + + rv = C_UnwrapKey(session, &cktest_aes_cbc_mechanism, wrapping_key, buf, + size, new_key_template, ARRAY_SIZE(new_key_template), + &unwrapped_key); + if (rv != CKR_OK) { + printf("C_UnwrapKey failed with rv = 0x%08lx\n", 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 ((rv != CKR_OK) || + (unwrapped_key_len != key_len) || + (memcmp(g_unwrapped_val, g_val, key_len)) || + (g_class != CKO_SECRET_KEY) || + (g_key_type != CKK_GENERIC_SECRET) || + (g_local != CK_FALSE) || + (g_sensitive != CK_FALSE) || + (g_extract != CK_TRUE) || + (g_asensitive != CK_FALSE) || + (g_nextract != CK_FALSE)) { + printf("C_GetAttributeValue (unwrapped key) failed with rv = 0x%08lx\n", rv); + goto out; + } + + /* + * Developers are responsible for the confidentiality of their own keys + * and destroy the key object after the key is used. The following shows + * how to destroy application key, wrapping key and unwrapped key. + */ + + rv = C_DestroyObject(session, key); + if (rv != CKR_OK) { + printf("C_DestroyObject key failed with rv = 0x%08lx\n", rv); + goto out; + } + + rv = C_DestroyObject(session, wrapping_key); + if (rv != CKR_OK) { + printf("C_DestroyObject wrapping key failed with rv = 0x%08lx\n", rv); + goto out; + } + + rv = C_DestroyObject(session, unwrapped_key); + if (rv != CKR_OK) { + printf("C_DestroyObject unwrapped key failed with rv = 0x%08lx\n", rv); + goto out; + } + + printf("Test key wrap/unwrap with AES CBC success\n"); + +out: +close_session: + C_CloseSession(session); +close_lib: + close_lib(); + return rv; +} + +int main(int argc, char *argv[]) +{ + CK_RV rv = CKR_GENERAL_ERROR; + + rv = pkcs11_wrap_key(); + if (rv != CKR_OK) + printf("PKCS#11 sample code went wrong with rv = 0x%08lx\n", rv); + + return rv; +} diff --git a/optee/tegra234-optee.dts b/optee/tegra234-optee.dts new file mode 100644 index 0000000..61a5163 --- /dev/null +++ b/optee/tegra234-optee.dts @@ -0,0 +1,178 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * SPDX-FileCopyrightText: Copyright (c) 2021-2024, 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"; + }; + }; + + /* + * The fTPM node is created to pass fTPM information from MB2 to OP-TEE. + * The reg attribute indicates the address and the size of the component, + * which will be filled by MB2 at runtime. All addresses are inside TZDRAM. + * The status of the nodes below will always be set to disabled and the + * secure-status will be set to okay by MB2 at runtime. + */ + ftpm { + compatible = "nvidia,ftpm-contents"; + status = "disabled"; + secure-status = "disabled"; + #address-cells = <2>; + #size-cells = <2>; + + /* This is the ftpm seed. */ + ftpm-seed@0 { + compatible = "nvidia,ftpm-seed"; + reg = <0 0 0 0>; + status = "disabled"; + secure-status = "disabled"; + }; + + /* + * This is the Firmware ID private key. + * OP-TEE needs it to sign the EK CSR. + */ + firmware-id-privkey@0 { + compatible = "nvidia,ftpm-firmware-id-privkey"; + reg = <0 0 0 0>; + status = "disabled"; + secure-status = "disabled"; + }; + + /* This is the Firmware ID certificate. */ + firmware-id-certificate@0 { + compatible = "nvidia,ftpm-firmware-id-certificate"; + 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 */ + }; + + scratch-t234 { + base-address = <0x00000000 0x0c390000>; + pages-count = <0x2>; + attributes = <0x3>; /* read-write */ + }; + }; + }; +}; diff --git a/optee_src_build.sh b/optee_src_build.sh new file mode 100755 index 0000000..b33a75b --- /dev/null +++ b/optee_src_build.sh @@ -0,0 +1,235 @@ +#!/bin/bash + +# SPDX-FileCopyrightText: Copyright (c) 2021-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: BSD-3-Clause +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this 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 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 <

    ^wTd)Yv28h@_%^RBlE|c_j_y?+K$^i zA-XSGU%3T#v#$BTBrneVVe-`O9≦BOU?+{klGb>nzsBr&Q|DB;`+n|lN-t{Wcw_-P+dO~ERJws7qoShyA;!FmMX*+CD?WGGv_yg##y zHC21)23+K4&iYzW?aNB66jO*&dD1(r3%j>X# zyl2Ge0H5GYR$3ugIxSdvfMt0Ei1N>zM{mx-nnnlcHa1**IupwW%Xjfi6%NTT9)Ypx zPhbIC2-H)8vXv@JXw?K|Qi>^`SqjGq57)&c&BQN|s{R0q$!qTsH^C*22XAJu0{Ptc zdWklz(DxtDC_+?SJ;pD9Al2}En*s9>vnk)>;Yx7MPqtLkwsDwt7(W=RhKL6ROW%Y< zb^W3v`+<0-{hz1!4f704CjWq$9qGmEBKM+qd2qH{JJR*?v`mRM(b}~n5-I^#0lHOg z$IADd{fF??Hduv;oQX*TX&cSh`GexT;fY6JX9TQ=JORZnY77qBmFLuw#V7S4mpQ%h zE#&Zqxr)JI%Qy~3>;d}7$!>I3c-Qprh|9@%WFLVnfzdleg9jez?LFVK9WYDxw*rf< zyU@>8EoY^|ctS7WG`FHnN!31g^{$Pb;+ZM>qFU5jl9L>Yw%mKxWo z8X|wJb|=|4_%}=-;;0FaCWE`1W#3ipN8q#x82u>^x+gJauxjnYcgX$Zl2xr=z+A~2Zx6W|+n*nnF!~iQwGSvG_gw+W3cFhgNaJHu% z(9jQBvno3l!e?7vAPd8O)y)MDX&>HI`kt_XZJt+qoxYfj88WIr7*xZ3N_IHzLul{e zK&3hU2uiquanaIVGO2fFgD-JP?9m+5R`;8xzC|&-`?Djb_P@?b_3+N_k6G!Ii{RaR zSmHQO&WoEnp9@pR$sXQb-6JPI0$1w`AQh@SSo=J`q^NSv__uO*p%I0Mb?c>w-tm>Q z2uOjvB|5%CR(Rk7c}sS-;r%!4rDDeHBYMUPRSng3rzm%SC`E$pzbVCi9>~bC0WjY4 zVQRmg);+6@xj6-M>W*%ZDXN*SaUfH8R<7~EUVtAvm7F}2=<%d}8=kyw&5in9^51p+ z5rDelYq&4?Js0@w-*f4l)%yNvu9$zCi{ps7t~CEuS~t(Pe! ziu9gqf9;o6B>qJ!>;xpil|wqdL;1aO<|}7w;7a)an)lO_%FD`7;awAOG1_rg?ksb@ zw9foe3-lHCK1L@xh)pjk4{AtgGkf5*lg8a45eNdbbH7l~X65;g27v)L9B3m6vr)}R za1K|a5$bfdqPY+Pt!V*dw41jI58tvL0+ zQyj+i^aafash*U4_}CJ*Abqy|(Lxq9@%x}Fs*Kf>!==fX#i*>1*`~|5_2R$hBau$a#SSl1?Stq(gEBHe!QosS+0%pg=1=W(RS%{Jno*X?%O*03HFu%Mker0`L{h3suG?jpIDd$4St37$m^ zem}z~PFGl^`iC2f+IUG-3LNZsezLzjL-H~!!gm)s*LQW>;6c2?>h+Y%lIO!ImJT9rbU*8fRZSqJs&S{ zo{fa9j&YjwKGpl;qGvHFR+DnT>2k=zW|_xKOsnaHhqfU-B+*3_V7qZk`1N8GR|;=Hl}iQr+@&XqcxKv`BAQH(RZtcr6GS?3XO z4}=>*uMqgr`l|->Uw(xhivT_eq>9?M5P#&s!FdE$Y@v$i+z{x$g#LJqd`hAdGw~SVdCNusC`L|#F#3PLq*16 z3+c(D`FNo8WpmY-x03zK$t%}MMupt(wZR6o*3#G?eUCC4zpkEmqmZBIGP%K)c?!Ls zl$YuKT&8Ri-BKaa_wKwh^L}|IYvmCDAifQZhX*M?)UO_h>tt0!WM|cEY)zW|e2ooa zSXb} zKd!p?3+p+w8Cqi{SDMPSUCYbUl~Rw(IdaGOXj2~7GRpKu=JCWc}@r9=Y|8%Yn2tDq{V5#ma<&-llX8M;Q6mj zFEY<-0c9m=a2p(WSuQsoJOggM{eAh@0CDUO;N{-~=zy~8_Dx|hywm^eyQ@5XI~wsI zc9nIp5C0Iv1UTzswboakrgAOvsE9pFaUzhllD5U)mf|n7?8ApoH$KDp&hM^tSjIH_ z`jnbY^W~UMgtvf7XqioeV|*wQbd~f{`udj`6rJ7K7aa95y0vvp_1wz2G*eGhF>7ab z)6qq!>p31~Tix6|?Yb5iQke2jj=-XYqlXPjTjVqE1+@_zD(W@8r&Ru5-j=&x_o3O8 zB;K{JMNxTSjFP>tpqB6^>qacKO=^3stzST_fQd^VLzpcIG<&alrZ&2Kx^_LaOY&yW zHEpZK)d0*Jevo3cBX#TgmitJc3Ay9@S?EJq?H){a-g=GvWG~La#lQtV#fDZ9e1%69 z1WJr@=XcdDb;c#3K+^!NbqsW7p~%rwx94YL*4Mf6tu*-lsp?9YFEgllV z5(py4^Uw5PL+z;S^5>k)M#N7_O?~*`>0Va{Hc4b75-7AVKK4UCKRwGqG~u1!M6O3Y zj;xpve!8H)6jRmP6r9G`xi;lNuGgvK^+eS;JyvR?g5guHpWt4t?66pmn|4%2!D6hQ zWm59xe1JizmQYg{VBJYAkbYoazICNc8x_7|8Lw@e%Y&I^V+v)Uj!k!Qa3+_i80qRJJx zqSOxcr0I#!;Z<Yr;9H_$~UTh@rN^}4HNvr^KCMxnFM5$T|Z>xRiR zW-pM2e#W5c<;&ruN?Jm+hqpP+_T5s5q^rg}2EH14AfswPUHYK5NENoFN!P__5N4(^ zvcK%OvCnr6yg@+R?tErt6!*2tw6s3o|KQHPG zz9MUN33I>>BoL9Mg|;KYZGycRjgoIKzP9`3UrFu$CM7#w)^S|3MB%DFs&M)BAx+3h z@QBseZZ;ZQ^+{yX3$k&>!jt!Iikb^8cu8!v2n{^XcoS{=zCnBU5v5_G%q?^jAH2i+ zBx*;qv{dHCzv-Ejy64^cIttrio~DZdD;6QzUJ^FMI8HxC9B_OycEL&IMBt|#hZ z^QpP zo-JL5US@oYh9iQxEAkT;7k97WFFD_AN$J$xzl2!Ln(^j^_gZY5#pBpa*lCEz9tnv! z+OzTrA{G_VBxO}v)YKQj#7XiGQAZGe6jw&&(~Y;6geJWhvG%>$_~g4fkM{5~<>L zNyHujxG`S{&byyMON$$=w_w!-!kn@7?T47x5m++WJrAj^YT?0L>8j_U-=#2`pe62I z@KF~Eo0r^XpeGPaK6?`ELLlO4d!X=n|5}X%4AKQ%(C&yt!Lh3U^sxM5NbS@{QRNL5 zpg>jpcQGghw4NKp$$++Z zYVo&iw)t&*f7xagbI^wW!#3Lh*dP98n^ny7e_88aCLX-}Yk<-(6aV4&0MO{uftPE* zQhMyg%Dv~;M<7R5WB&!q4VoU<*DE8t#jb^FUuzYrGr(A!lUSfhmT1BdzM{rl_+a7Jf*w9UErCF5y3ZD@>C(Y-N7jPlK}k5SrE?LESQvbTCE%0 z+)fFfys-fJgbi+p{O9jDJ@hgE^8281256)huX6{%I(mTQJ2RLAYpPST@_JCyo z?gkp20WEDHlEQ;XrQV5FPz%!9c0;t(D!*w}6t(?9=@v7TAwWxV!m-ORK4kI9Nn84` z;oD3meKggza%ILgs(q@qCsPDle!TDKaNddcGA)bsS0k))GGKMvay>p4FD%72tv97~3+|wdZ?iVdh{OOe%b?9Zqs=d^Rr}{&hg^Q`}xSpkoK|MrWYa@!7 z86MuKB-3dGUOPJzYkX$JOFekqe4Fl@Ez7gSuVNqQkG2vl_=u$XEXDHl_h$Cs{Jrd~ z3+8rgB%W95OOOL@DTyJ_jY3Vvv4|?trIxq#)k&#C7FB!k)NGVpL}e95(z5+}(sMsM zz9<)M*?MzWb1f;~?#oTp5nPZ6$hXQ$GbPRAYcI7-Da4zZTHr*MsYK<$dW=XdCU@4S zrk2f56!e_YCOgoi$y#CWKAo?`k39y6-wdI)a)j5hggDP#AXJ*lhPa2ZOza+>Mo zV~xq9J5evoB(vu*lV5FZk!`k7hU$>L@INgivOqqQW3pAZVU8<%nCe)FB!62%XiOd; zHKgc|aP6UWGVw!u21bVnKG96`G&)->l!KGZdG~*PQ$_KR`LXd>DV| z3;C(ku(SnPc$p-(^Tv=DS;fMT7oKF2zgu6{aFiAP$ccMH5 z3MitFhl|qWusZ?~F7XzgJ^2ngyG;dUxN(JSpB6^Fo*Q*1Y}fvf+B78IAaU@+?CPBN zE?8OE)S{UpUDcOmnSVxSD_9uXBysc=uFn*a7utNsa`lNY(te13g4UO4U+!@hDjkCl zC{=akEgyx>nj{1v9MRv)R>FND3YEh9+oO+wOm0QY>v89MqQk7Y%T6c{$5|D>?vO-3 z*hWG7Jb(W_nXlI=HV$s94ByLbiW-wg>m0B#IHO-KN(=`nN_W7V2&k%R1ag$56;U^H zM6^#hPfydy=jRvcNxHuVUjH7?~Cetl*RuYUv<(6Glzu(UCT$rHz& zEv9UVs{E){QHDD!;ze9V_?uY+9w5I`o zlOrw8{VUl2^~)d zv+$Ie$%bUhfVFL`WKfz4h6mwRs~w6mVQ7z0DoBVfGfsKL84H0q@Pf}7pNHhZQ2W^oYHJ)*=`-@>3UL*V#^ z5YxhbuC3Kd&~|c;obAN{)Xz<2sXjiGYfn$3nXH9(BH|r3M4EQBuRagzyiAFp^aHE2 zRN0$Ov1p3)I0-rm47M>9X!Lmg!s`kSoi7f%?hU*TNA-OYzX}R2OrRZs6>_S9;`gP` z8Z8D`PHw~-|@1TXe7?Y`s2*&Vw(m2z}|x=4w?$3mJzU#+CBvi&P^5j_-~toX_9942)+d+ zs;S0Cu;BOZ0uPi{WmBBHTmocR#$lwf zC=b58AxRwnn10tCMn+Q;-+i&&YP`Z)`*T=^1?z^e=O_;?&4JN1Hq`JZ^)58~o6Z!T z8%xcAp}_|HUQeBU58H#y0HV2rd}|~3CwQ;X-BHV0&NoThTBhMoE=mk!KP}YuDRq6M zZvK+GPN(Njl=RHIgs&IRj(~umWJi431^vyei>z0K=o!pp&X+3hr5A5?f)~Hg(o3Mh z*8xuRu*(g_%kDBBcVh3TrkoWHkv?J)8AeeeDT=&MUoGEmBqu(DBtqjP7P>cd&ytdk z;d(3_MlokNc)8n5FNk1?M z+%*m+3q@kl9Y;zdv4RgH{g9O1v!r6=8m3-MjlvFL2N?xRQ^y56=5i@-1<&;NN}xJ~ zM;qXppDZlAHv3{%3unF_K4L*bA&>uY8tD^!fD}Gg3|vC-?qR;ZcwyZ^{Zkj%Z%VKI zcR2W^W)bxK7PX$zcN=>drXzo6D$}ugtE=~9-NDTyX+m4l0WHIJe1Pit5bsNT=@IuQx>^RYN#Q1un#) z5OG0eiMRu|InpT?KH=Uk_}aULQx`hrFC1utxvz{EB#Nhzi>G)QMS_N;Jz`pMtgS(`SjeIUd;c zlq~g<+td|^HVf%TFdHOJBDh$+P0(K*gcqo#3>&<1Av!YtYobZ+Lv&{V@fME@X`Qdq zOj&KCGDA{Ep?juDIFbde>njs=3S(t?23HKWC;$#M;YZ!JoIq~Z>(47APTfF zN5qP7g;C{NR=17@d&2_rZHR(16Jjms2&S0yNy-RasA%O*SvYaj*Dl_~;T2I1W(1lh z=(f45;R`1jQN1avOQ@X?VdfvR3Jt*~i>R}jQ>^`~tAP_$KF`5jq%Xj(b7h+FJ$-m? zQO7;~u(yy-iUvP6fd<<-Yp>mx_g#*2v&;&y z=b6<0;3l%$sLbw>%TEuk{TgDW9%Ifk4r#>tJ)Y9semBx=K3;s{Ojwo4_#uVa+PMXl z0I9qT(|Gad*ObNZ#1+!KRQ@rZH@(vb`G-C`y*#8=61KAq-A-iRn>6mB8Nq&J=OYmG z=WmuRtYs<~j+K;B7&waS;y2YD>4wNGFeXQrg}T&Ai$la%9^(wL@rMkpqN}Ut{X00L zqc6ZR-r$dEnY+|+p=Ns;QV(zhU zT)`@IkB8*m#Wa4cKRI7`P`kk{u2oj=6Zxa&`u~*I$A^Q3fM2ECw>{w2 zwT1TEOK`8t%cRO_g!WAVH?T}Q29{~Zp45M68VxNgN2$fis$S&Px(p(EZ4$5J?}x_a zAxMCnyl0Zi6`??R{F+)^%VSe`i7If!`_n{4PR*%H*<=vdaIC4+uzHKEh4V6_Wi=ii ze}78-qOi*Hv!1LIh6W^ld3kv{(hJMOmEt3h!wU5g*ZM~4<^13Z$99b*S(z1gn>Q0! zmyy~wKIuvStUHp*RUG~un&UphK1D#n{fB~GWlpg{CwJA{eQ|9B8XbLA=PNDIU72VR zKH|9LCV_|yeya>uciX%$=2aDJ>&p182?^1lK3GkYRYw7na1>&63!6<#^o?{P~|YyAQKqvgPOW2>eMzypH{aH#6O>9=@u#-#)kM zW?1-Ztuav9zA5CzU;jMs16nGQ`;<-THyy%(qUtCo<4hPH>Gx#rbjkJQf%0%#)2n?>8O-Bq!ej?Xf_qf*aKNbM{-jXLkqtjJD4?? z!p+}*5%FR)haYMK1^)+`5&Kg9vWb0-v@yR#yi`el6op7hw^Y`1@-4q!_j0f1W-laZ z+oNqMn>A&K)DD!$k=2OJJD$oHO_K&%dUg9Nb9w_l$=O=$eXvbK9|cErYaN502?nSh z;p4QHS$WcifxnqKSi;jEKjy;X)Iisf^d=&RWM^Dp%}>W5fLUF|G>29u!`V~$>cD8@ zIc!@pA$p(1n`K1|hhe=us9>LO?~Njf7FjDB^$bOxuOh0h3$_8S*Ma&*v7?Vb?ua{m zOB8=pkTAMaNK*NfQ@d_CnK=!mE5^w~ZR`b9F zAby5H7saQnUO#n>;p#qRScdiAmbNABbZHR7c=ODRj;e#MOQ0$)yr9rMc;(f^YW=Bg z>szZ54q0;9pQY}FtSJVAjOall9odQa{ah+9PlnU>@RDbryLns=Mcm9RGs#FcGzM4{ zm@JT`Y{s58#l`Yjr<0mP7yN&`y>(ob>$){OX^=*`m6Q-E0coTW5RfjV!%25I0i{bC zK|*OM>6A`M0YSQ@q`Ri?jjpxM(!Jlk-}9Zbzd!sfV9h7z^IS2;xW+xq8>*;pV*RM@ zT4Hx~SrTM?RkK%pihrGZa`fH0!L1>l(4(>ssTRw!8t!CJQ@4fiP!#j1M{f~T8g^-% zMwOzxoRI6P$855P%5yknENZ7O6ggf6a_k2_@q2TJ@A_WJwt7b%?@G|2utMvR-A1LW z2JvXHBh(#9obprsx1L+G)mRS#mo?@FQFnJWB6!V)72DoA#oaJJ=V_3Q`mC?kH@UpU zvMx5AmZ;HZ*Fdo&-2S2pZ=G+?x7R-0wA;X3jl$}38z+Zk%f(2C!r+=}+u+KGQ`=njbTwNA%{cE=ni}8zC zDN|E-)Ge`7SsO>4n2p+sm0;<3y1F4%SlP|fe57t_jkW19OXt&if5T+{rNuFtd=B}D~`h6Kzk}l|5u4<}=)5Eg^B>&N*8P4+rPwGb{ zM0B1l-8) zTlpt&4v5RDDGyGgaH&&Yj0wW>-29;Cj{;__cXM=R6SWUkZ@4egm{vv+Vi5ZIXU4|( zjkEAm3E!UdCsnp-*BJLHKiWM)K^aR& z*0f#Fmsor-xRg5hc1mb)vSaVI1~*$C^`4;rY#sFoLZOtyTVV}s3ky{@zdiN(GS9?q zBG9rj3TE&#?Y{0s59~0>Nu5k1p2h1o9$-VFtms+vO9Reoj!VwGsYpI zB2R)dVaafJ{Hbf3LQLNF zc_)1L8|!0wYiox$zrH&1t(o9uv*RbDKS;+8`G56}_*b9%df`f0Ja2ZVS!k1LGq&KR znJ{-$(5c8!{xj?tINNLtm%%dh2N# zDc`5_ax3QV!;odz-Z@r9%in>REIBQiAV~~AdjGyWVsuhrj4puFU*+vg+DLn}_kfPy z=%QTNIm!4zxV=dGQz&q&SWxtGk#sS2k4!tX?CxHi`W$(3zaE5CiLXF*=ferx<$<+O z%}1V*@I+o9go08$9YW-CN7Xf7`(%WbvXdI6a**$mtx{|yV3*|CViaQa#xJ|NK{ej{)LtF zbLqQGUq5O4Dc5!@+EIcbUG-1S%~%CR8<&yx-Fk~@9KwC-Lz*%`Ul1+8TPJH%NLQMG z!CpKe;*vB?VueCq!tU#vYF!#V(DZPPYu&-3R#m4Bu9sZ?o{EMR%K2>umoCgnU`@~Y z{lh{LcfLKLZ%Wz<_-YgKilR(FhSPLz8-!ksoneiA6ckUUV4=oo@(@DCY2ri~;efD? zBC%(!YPqXb8Cc+*%EU!WPCx&gI>$AxdL<&~{Q=Pz#W!v&nE9;QPWt%fAK2J4&Iu)Z zDikr~@;T33`2o%M(|57WlEIN;~(|L)RBm;+l4ybKR`Paa^+B*Lv zu#wK=_}-4&H8&+&v&j!td#B{J5w9%sbpxrpJmqZAgqY|z7JZzGEtS3Q%W|a0p8%;2+B8&Xu7}%alD#@E}Wp; zup86MTk4XK&8~@C`B@vTo`n_pm(<5faoS8(kq@Hp+KH1+4Zo*cJW-w>t;$Wu>f;a_ zE_XML9})-~%GHctSdd#{;r5@V;e|QSQB^kL%KsMLkIm*O=3< zjaCv@s!q#6@xqI;2>Sf&dhw0Xs2a2eA3wG~%z9sPr4zKq?cSkl!SsSA-u3Y?( zyF(7)FVWi>zZEs@p9oPo2{B}eJF_o$ydiYCQx4@~8qd&v1>vzaKq#W7XOtn=X_%!3Ym&1>cB_BrP&fHM2A%l~2e!RCI zJ^J;`u*5qFruB3NA_6l~w%% zjz{e?eJowdXF~j^@%+t;G)+L8U}O6;K7zZ5r9Mn{i-DmG@v5L~`e$mfavot8MRQHR zJ}&%-HA>vt=XqBl#H*iSrLH4SKA9r49LX>bMf!j2yDcf;@R3^PPq;6*d*sS+mdFzc zFJUm60xmNg1TP}pgNJCMfJ0Rdgsswm>jic^3!t)oLD$-NfD5{UA=s|^po$nJ`1}oO zDsbtpaB1-6gk-?+U^pNo3tsU#-y!Xq;!+UD*&U!|hWpN*QvWy-(3XQEZC^xQ9Y`OW z5CIr3Vb2eop~05iMNi%-pNQB0{R2dV2>n2rfH~jz=O;wxQGnqIQsbUb+J(B)qlakV zXy{A@NoHlFnCvKCmGl~{=kubOFQ7=9X9^VJJ?hrEi0;H^Ofc1 za`pZ(9z;_i3GorVd?qF=F@8Aqg9k;kDm&BX(_h4m@6|u^s!B*m=wjG6-D{IA2vsSIaenM&@}}c#S^|<-g8CMXzGUCb#J=McF-rztDxY{PR3qv zNRhu?@rtnEt)ZY53Yv>dO1~Hl6Y|$L@PS>}1-u88__Cs>`Z7l_Pz$Ua8D5Z!gNJ_| zva$XvhV%T_&l~v8m0`M(wD#FjMm0J07?aD+k86I^Lu`U53C@`hK15yq?~n!m-OoDG z;E67Q0kvxXKzRIpePKrf;RtOZCZ-r$p>GNC4vBNYSq^#5*Ez4H$N2w2cq_c87MWok zP2cfP?sGxS9PM*3+lx6asfZoE(Q)T)SK=HDGJvgHnQ&Io7oT^T;_U44J~8^%?ZP3l zR&%bRmRv5pJpGSc$^t|T9ck&)y4sU{>DEx9l)6bV(NYdy*$GkhgquQXv5T)$FWvLU zNQgBVHN3gonD^3U+??`P6MY;+Ov9*!y$AA&Q&I$k^F%Mudd>7d_bsk=vlrF8lM>S0 z(S5+=Hzg}HZlp@;u0<*{#d*2qIOzN`Lk7#fzL=H8$HWe}xaBn=F?~VU)Z)DTiYRSd zQ)aB!z(J4TOmV+VwxFP(*O;x1$RP6oDTnCIWf{#SlJme%v#1UymI_nF%O;0CSXXE9 zA8jtS1qfTTtf0*WK~6lRRP~8{(MD;|N*M2gSImzpP$uvlKb9!|w$3oD3w0RYVE%(2 z&uY!iZ3g@}zC?5g>*If-b3MQfI6~^FAJMu+AB4BGt;0B z!Z3TZ?2>9h*v*IHXfMSV2@z`kRKfly{;OBj#%xr*6Dlrb$;M^)g|1_rOj~h^)(`ig zjMchz((cMdDCT#_6Lyfp6mF#B5cJao9*+*#6NhKfE1*sAO<79deS&$rrcc#JNXyWT zzGnAAhb|?aJZnefD(d_s-_>4L&O&;8*Y4S>Ft(KGJVjSMQ%=EfpGZE`@@XD+PkICg z``f5DD1_LVZSSp3CG^4E&`iwnz6cQuSTo}&<`*2^~;gq9*w#Jd}Bb+9hQ{^HY zrIPK0A7;90OrS>6b7AFs2XLMdb%}IlDTDmw8X&r=Hzc})$^mE08DwWF80MU8M3fCnB7CT>g4i(rwwWDRp~MDQ^k1o8f1S0YzI)Ypf>s+ ze1~j`;_Ha@)H1-h9%L_1)XzoUZ-MiE``mhQZy28~XJndEk&g7?Yv1>eqlF#Z2F^uw zwwRG3Pa*;McG!67T@3d*T>iXaAY5i$jM=rW1YOdu^zWbln3j!XF7kOP7GdOssr6`L z`mlB8_PMnaSs15k?|7%u6!qe3&oO&&H$*|*0m_P>$-Jjr-vD}DJ>&?#(dK@Kme0D! z^T>g9giV9Kto8V$c0U8{?%KO^&yS<(@^LyZ4$`rTPkyN}WG-mopi%)fip*7wQWO9f z^~QPBos~ap2&N0#nZJJ^1bhJY_aeg)&b_ns{OyVNN@a<~mPwRxa9h!&vf4}C?9We5 zLJnB=8iPH8sz=jHBrsMx^`*1vEY}g>*AElHExGgjR zjsI2SWB|SQ^Ueu_m<&Vh3Cqet=O>T3nz)KQ z^g=9IS=PfrMcYW~`&)hUGZupHUL_KK-_`JEf35$H6BIf&pwIy*)Ri7dpUeq%B1fQT zGenUu`z@&%;Ng=0&nWQ^F1lLS6JjE!n3U)Md3 zDt#*W%!q3d$;JAU1riAyZyO6XSd$5x!!o>3bb=!TDYpB3@i~ePhkXUHCvnH`ZYQde86#&$x1s=*FJtC1XI*RZW5^dUp1sCh=kZ#|fG^{N*U)aI)zx zb#*fOR3OcE62W*+0%!86R*i4!Z;HP6_%`QiyYjpkbx!s;V{-PScJ|PXFh+HkEznGE zIl#y(qzDnH+VH1!6>Pb-LLM=1M024xQ)&ip)bgC+WRE(QR(G5%87@l5qEXdS3)dYM z+r1<2kFhPZES=C}xoA4Ik$wP;AazM)(wh5*?XI$Z$%tYIrVszTXh){4bRTK(xfl+RNh6fX zz64y}dQ>`FZzqD-y4*L`CTE4?kwb<2aX!>kY43u`N@o?a@CP7~oxF=q2*N34vw(h;d?Y6nN)W$_Nr`ptXec&0*$!&lde%zjmp5f#y&Y<9%4eULNmI5+|J*e~7*=&3AA>6Iu8WL2odvxPkMEHa z7DoRTu2P`Q;>k0jPnro{4@WMhC59h_!?o~wXtlZc_#i~z#K_J>zalgZTl^TA`a^Di zC8zwsmSoUe1Qa!H%+LUpWZfe`7rguoDl^dTzmXH8AV4_gkIq8Gh= z;#tlWQN0K_65*WRTAH~6Tl4p$$VbQ5b!#f|Up)?zyO}>dkpWdLjGyR4vRtWfjZdiU zTmIaTI98>x+dtex^lh}8s_kXRO$edsM1g_ydYbb+L<yYObWQg?LmML+}7;(U6Y- z?r(3==T&OVJ5|13LZiFglxPnsIWr@u;=Hn&*dWM@4XEBI=IXPEux_E9u}i-~;PyF) z2IfrvsU!S<8{zq9`_Y??Sd6=1>mX%H$@owj7mc2zIgy~kjrR_N|DiHcg;QLQmqY+- zBzpPvj_6i~OFto-H*vAkE$Fm|$S&zP(A(viL)YcVMarM5;@iA$2=-|0L4r75Sth96 zu?Wx6|042g!Mv*OVN5U^FQb{tgG*aAWT*zx z1*eAY_{18Vb`1Ko@J(fvLiso$Gd{`Pofsc}%4it*a57ws78iyu|lyh++Z ztUg)o+haVn1m{7p`eTU&EM-DBccJ^)?g*oTi4i9zbPXbF+s|jIefGmN!}TZhw5GeQ zov%v?nOkSL04=iTadA3p@JUpT`0YsIH|Lqveqzaq^C?QtRMy2;r~=j@d+Ud`fjV`w z7DM9?v@=T|zw1nkDl0b^elPRB-CfGX5DWO6m;m;m7z~~d4*3Y{gs@=tWR{dv*Tr&1 zpigLEj`)-DA20X_H7;o69ThqV3u|JUyp9%No8#ObrtlW%vsdR`9-f)i)9)gb6AEWV z0g>pnr=y&?)$!QqQ4|q@^3AraTEtEyk*Ptn!V95ck=FURYNxg;8&iQuYn0Ut;SPi+ z@Z*)yN5GUoM_0-gaWjM-Jv7=b{V`UW6=?KM&-F$kiVJ59qub41#!f+Qpk2e^?|O*h zu^myN{H^iY)I6W?*csQ733k&`s?1J6X9H_n?$1c{S4jHnhrh)p`G1H_sTAiN7Yr{$ z>#Xa7+A|{vMklnt+*7t$mv6&-%=J8`Q_N%T4Cjq&wpCO|f{sDM184(Zq-;a@;3Ao( zRx1t$CHZ~|_EphE{72E1`Hw|c<=tmU#G#Itf!TONiIVr_dMBH@4Oz`D7GFcx2IL{- zN)b;g{L35h$~Ahm>AX1}ni?s6tG*Q|K!#HGe5m}lhE4c?n z&K7H}@-+OLsg~*P;F-q2#f=$K5O*DAfsq4g<4F=E;r!Vw-1ltdr&qbt45pv8A>xV0 z%)+f3sq9?i^bt}lT`dgAc<#v5oO(IGZ@%`MBuI=3j9mWb){Jm85CR>=6WBKf&>O9p z@D7dryCTbnUyuWRMrvMI*euoZP}f?)RMtix+1?#W7>>@I4rOFe?X+*AOqxtk|D5z` zMih6JJ~@uaYtqFF&*96y#N1;XT~R(IR*rK~z@Y4(bHK4_zeARtX?{cWklqd%YaM)v zd-}Dk+swk;#2ia2x>qHUpe??Oskl(T=>EUkp7d7i@P?~i@n-rp!igU__m9c8WH9R{ zK<}2RP3Iyb0V)nK4~kk0v$duSQl~`c?^f)|S`h=S|EfJ<&;o`uj+OOiasbmB2#073tmfaQ~kMfg(*v(!)+N z%rvQ43GkwPCa%1=smCDaXwN=9QpH_)n(ate3F)~WZ700W^0RUOIcokVOL~QI<;eg+ zNOJMnaUdXkql?s;K|tmP`OaVmV3w@YhBlC3RYZ$S0#lL^f zi}M?PZOV#pe|t4N(Eg=U0~*-c~lN9i&PTY!ZwRiJm-&<{~Uj=ruK_c02i9tLYs@hclP?W-a!MMW1m= z1_`W`YBv5(1BaUmg|~QK3`s{8QV_n-E#P=-@P4nUiLyPWY5P$dIj!$oc>k{W)W`F_ z_-qqZ1SIRtsSK=Eh;Mf~b|lWUo`Hp3pEF0Y$SMApT-9q`JrzESb{!OyCY1IeBLxb= z%F0)ogE58C#UGjj1L{*IMz&}rIi_eu#ouZvAO8F+GU)=42ZjK`S>xe#ustOK74B7! zhse^GI&V`iQ`CDUF_?m}?Fii#{WMRR;nTWHeVD;_5qk8a9`eP8m=9fjM^`ZH566UG zaa+A%FkdLQ6hSPBFF7o`cm0Lbx)Oru%Y2tq>gaQ@&=xNRYLXN#K2C4Z9l51j%@79) zR3FYYR#PE9N0BJkyvb=@W$4p$tv7bM2yzo-GK$l?gJ96`mb(!<_UGwXR!0iif<63l zX5{CcOka_Z7=1`2clA4bae4$Xk#6*_Ero}LVXP|6cOv#S{gRE=^w)e%T26 zVQq|gg_XwC)`4;odjWBbgs(6CXZL*W8P_yzj+Qx7aY4Dir8-K_T2(5W*-pEWgl z^l752L};k&DO)Qo7NRnmF#mQ4WT^2Zve;mv938spYG+a*)t}I zg^B z0VSs!kjyb7DJXqNZPnV}++wV9d`idFj2A7XSyv%Fk)_LC5rH~9V6|Py;hfx)@6B0k zQ@EIt6VEzc7%dolBTN#)+*6@dAO2Zn-3fV&Y(5h7cP-j@b(MA1VLE~@Dk|e$aAGEF zqe~FKV5KkZ4pLW(1m^0mC1u)YjV2VwP}qhq4sm2S@pq_?-f8udLG_^>g;wZ#Dp(X= zNO@Ha->G^*fA?HJn91`w*?C^Ho!AY2NYdIyYGuvPCOK-T!q~A`L{!-tNxzs8S&c=% z9IbV)L&sr~m2y z)8t%SO;2liOOY6FK|kVj7|o|RKQbeM&N_wPAvmV2cN`8|LO{Fp=h?nw4*>HG9TCr< z-18&El~t-19(Vy;vzvGB4C9?fT|B2n9$=J&I5YTAjzFL6oYF>U?i41y(vIg>4t)LK zT#QZ9Kw~e%uE&`2FtdE;a~qPTzKn9x)+nX!+WW}|p*KSNxKSmvU5MDp!`_QlBfE4t zZ7LS1>K1bAB`q_))aKzEEbOai%ZrOwzQc;@%!Kp|Vlb!KuMgus?^6u&BAdsUk9f3G z6hSm{2RBg-%`+`%Ox9;ckRdp>Za_;mEPqoMUKRn$UKczAa5!T_F*mQJ%ZlxoWJhTol_n#vci znXj}{R#UTk9H1~78v)_~WL|0zPv{zhK=9n+xMc840|9dMj{xa?mue;qIK&$rUm;_< z=s)I7rT!$e{olc9tn_NYtf&LJ7uVPT?|R8I54hOjy`Q|n2n zNfw>DyP+}Sxp)(OREMV~hhjQTn#3+u>Z?qK@Lq1&Lbss@@6z)nKM~T!j4_FhrsbYQ zcdDNwRG&Mk>UP^Ry}}t(NokdqR^~^F>Kv`ni5{J>p3E&Q9PH*PAR?qRNh^dnmAZv0 zS*NJ(O*56%)fwfkU2Et%^0D6!FX*IyO=FdnzfNwJ2Q`|3PN_|N>4cVjTmRUbzF+4? zOW@6V0}T2$oD`?`Dq$Z!15$-{Q^NQXQKpR`X} zm55ccwvv!P&0xl95rrU@Y)bHnBIBXngHmD*vtO7$Z5*$#dVWthWh08v^tht= zw+9Fj29*~v#i3p=b?ajkPzq#^@iH)U7#Whp-ZFyF}r|FIGP3+w}BDbIVts zQpQc>4@?U_vn`fiUi%$P`>S)k`r#d*6uOL7;2!{bHJF(nCog)61qi^gdc!lqScJ0l z+mWC$r;X7q4_F@(ymcpf;xc2!GF@uISB_2L@niF(EyXmS_P0}jXIp#0lZ}rzXJEC$Y z)?MuNtQ;cw_0gh`hh8BYyY-KB;k{d2CKXLY#>_sU>PuHdQZ%onmm*&ict&B#R>$Q- zjqw<=tpnQ$bTfwg_t62l9iVI%tVuM7okKT{N1)%fp<6|4L+D=lgMLGg+|k{|?C4dg zZbiu zP~}w7?>0re^G%FX)mfMyl}hH!L}*`)&*Hrd?`6W`>={Pd1sPy)_bMa5HBy7G^8vsn z`$0JoSE0Jt=J9zsE~TDi)7sJY$Qmkb@iwd~jp3WiQm*r3ez|_m3wdvr<>{>ok|1^= zfy*j8zUel_3%eFZPT>#3r%$gDPLWSh`cvLHOG8Tae)Men1obV<^yC=sXAbaA02*Bs zW}I_$HXd9TJ>jkb4KCElfTq4K#Tip!Jbu9%vkZFVFV$OJb6*3T``_DCCoq#AwcQvfZA;Wg_vx zV>)Gcrhsw})R>^-+}Hv&CixjT&cWM@sFK{}RV9GKAO%goZ**tUI714TiSvOSfhHj!tm;a=XtSOd<3)O~0r^Y8I z1y6qHHuA3Y(9AaN>%KCh&M*__ep$$lwclHxdr+n}&SvTiXAkzIrAeMUlJPB~cWNj~ zjWGvtR%+ViGTc%KRDx!1*pCNn?Ro2xO~ZPSCFF<< zwmwr>#XYSY<)=^<&M!%Ow2NO?Ss9{lCYy3QEBH-SWyn_(Wm;C*80Kq8abtC{lgCWBN1_broU%2gyM({do8v|Z5GJ*sg2?>Vhkih6HX{alg`^n)I-j-p4xXsi z(&E@^6d%ZI*QSB=g7x1750I;c!hm_hf94;Uety^G#a~Q$y>Hp@OK&$aJL@-v+>{_G zln5fZIqJBFL-2Nzv%knI#*Yt~;eJtai zONoKjj=lChFw4$shn*dm{kVPi>kW ziCV4OeXpVT-)5B2!kkvJ>|o~iPqU5z8pM&3LP!Ga217pbJEcI0KboatSyY`8aMhMw zUp5UU5K%A}7%;HKK<7VE%HySmq zYXQ*sF0R5O(#};)+H>kS(chs%Wwy-Ym~#;0&;2WEw&6GwJZ`3 zMyNDB8LmEF)5r$F!=(q_uqAqcZhd#5e@uCoy2jcRid|8wpWXFFEU2dH#cPD7rI?e^ zu-U!ae)g#H|4%=#yoT+O zfNrG-|LTRT{o{pv@gwCn&Kv&dIY{e&={cHyfs9cz&y)&zxTe<{==N{ONLn~eOI)uw zidQQ^opa$pqYK$D#wq$YiF-3i6v7-zjuKO!YIZYH(mcuqIt`q*Vkm~U5sv*K78pGK zBT$ZEg_5f5R1OZBd$ei+#O>ZS4tP4iLY38ZC1(&g2Qf)q-}o zq(y4~nzv8K@%v9MHeFLp4eNT}ctkJ^`m|DVu-fm5ANSm8EL%98{&)dc4hNrrBGHek zHv)oP{yM`1kyDJ?o5a6D5QfxjQ>NEfAd*a-iabC)$z$jDuuj5{5Nn04^YPN~+$ZNg zK2^&k^y0^UM}n)PpEMxn>26d+2KW8AB6}bX?nLIlAz%LhDm#jmrw+(rIQR)yDdGkeYUFYlvwu$^tu+5@H&7IyTD~&QK=(~0KooVlEPtWD5xGWegs{k(PWaZ5} z2uK#E)?qvK|Ckr+{$iD9f6I%IGE>t$oecvT?Scu}O{YBeqT6pd3lvyMl`*UDiaJb_ z&~Tm4^Wb7nS)|_hkgz$HaM#up%VLaLNxvuUR0?r5)}5Y6Jt6~!*A_> zwdikK{5uBuKa2qIE)JX$lfYYaU{|7CcCbh~Xx+<5AE&xR9DUS~y=iG^r7zhlkxM@> zE`&3J@O6SCxPlbaoE7fQ?(R>MlqZU)_dY#VuWpHx4U(M6VISz_H%v~7pKMDQb|Yyc zn6xIY@<@%Nd|~i5Gw38t79GQXRsIaI9xU5clOO|SoK?6dUHi1KO@g_xWV;&w<-_aC zOTf3|_2TPcj>Zyae2?2sDPEVggnlb#aWI<15V>nE>F|A|i1fK7dtmNC6p2$|jf~$C zPkyR3!pxB|Q-_BtU`$4T9uuPsp9Q6D`ZEx?e=Ke*M#%`^KRO%GrW=AT3V@wvpb%wi z+}K(K{Bl69!4&&gaK(7Ez@kQNB&HB9X5@jJ4D;Nb3z-iFX>h3?jk`CTT$6Ei( z5|%mpYK8Yds<^v<+7ABGvHdYV`meh>0KRtVEW)d$t|Sr~>q)Tx`b~^{LJEjiTb2Ls zHC);MOAS|K*kWi3#H%GJ%N5gYMxUk_3d_shJEfwjYS8K;#8Rf-LmERHtY8{)wtN%6 zt+-3`>e@ZJ``PPwDaGZbDM5TlC2j(g50T3IRN)(HgD(>7daOM&KJ)}Fur{b$h}g;X z57G1MVL86u4YV9ucbQ>?iX5GJ1|@yYQWH{Pj`9_Ipo=O|bb)uVRK&$)>8E(ZnL^=U z=t3-JLIOI6k!4t5Nw(gg75N0Luydk$o`I258JVp#tg~i7OF+2SDtDEx?)^wt!~RWk z5788VZ}#-Ik1iW8kq-ZmPOsIIAdfbn>>Pe*Q@t;wV_GUl8KNHbLLQxV4_(N}hwp#0 zL}aNo)a}mgdt7R^PMVP;1eumY2{jt~8+ug2p_RHGbF$TUnA^I5ou>M%7n-*WO@; zq1UK?PC6+1I+=I-$6I19I1)?qQbu|wG975rNoElfo`v$Qs(xRG=(U!Dx70Hq?(u+O zeOgHhu_ogYM=@%D+z_6+P~H5XhKXlAW&O|3Mdp;=L=c`b2({n}`FElXj^MkENv0|J z!EbRS&CC(M2*11H6oME%@AaYm&c^5AWnA-Ca0C{vAAqK&GCDD>%2thF_BdA#(p?NF4@ z3(NKwcfj1d9nt&uW?K_7ghGy+-&?MbkP8P$rmF0X-n!d(tTZ*Z<0cYYJon{hL-a>Q zI%Tv~-jP zl{3dPL&G9(;HtcI0IT4>9x?pIFvNPc#^rhd|+j{jKLZg#& z>5Y4NoywptStWjgLf3NB$dAb#?UhY`dm^(?AQGw6B6a_NDlmI?uei&b z;o)9|?dc^b#GCj4qg|e=Q3$kNm4+v%0P1k5yoY%ZcmLz(#+9QUusj9LcSwY)yH3>w zd>l3hV5r@XkPlK|2Zld)APsg9o2mg)#nlebXD=LlIEK`5S=9k+G|6#+Yzr5Vi34T} z1Dk1ZL~u09bj*>7tYxdl{Zjz0_=JClbh2R9I8z9^Bq{VLW*~+B*dam*B`&>#ELt~d z&s}~RokFTMHDY|(qDR18r{Gd&M|U+3aot`aci?8q=$mLBrF1;G?t$V5_Fp~=VpD&e zQSl_|W#uWEKW^#0qvXj?cEODFEIRj8C+7kV@aH*J*zQMVjz{1Gdqgi#zzK?xT|DtII=hiOzHPNV|aR!2Z}+4QyPe{Kv+YEC~sK;~JRG z`Px7HTi9fei{dMcKggn^Q#zop_fr#y$L4fhMJMP?b(LqBl<&p=uO2SC0okJxk$FH3V`%# zk^5@x@^V^7#*~pj*Rb4clLx)-;Vp*Xr&w6~`aLppDEP)=rLHl(Z7Qo_d$;@Qs?x(s zjXk{QM0ScW#opJ9R2+gqHSI7A#sk(GA`W)_M4PTIbtYuW#W!pEGsW|-ZjKb1g-oiC z#Ld^9KR7z>v1OHqi)lDeb5=c-e2j?tX>Snaga?K+t>0{o8u_MMxV>ufrc`NId>}2_ zc|D?*v9NpR{Ri)dE^zboNZFmJ*t)LwsxZdW&AdW#AQq!?kYSDLI?Q`oP{FEi-MYb> zEJsxo$57EeBF!6YYK$@OirTrQ`*!iGp_lH^a&7&{#Mg7F59P0nOe3^s5Q8%FnCs|` zqs8c7B23(Sd<|mw+e|y}@UP5R-v6&!N$qDh2cZ`VZw9jT6@@tEKh;Ddz8T5LFXBVI zm%EN_rE*{Mx?Datm}8uOxYl@Z$2u(qJQidba3Y*!uy_$_&FLg;H|ap0^*2itYFDrf zVW1)?QK166YZ-jZA9Okkypch%b-nhRAVvH|%?m9L;J-ZF-a&2uq-1G#;(jCJzu;C_C z^;eSB85Pp&dZV zgwUE?I6lV~C*u8#Zl^tYw>R_SqBlPLFT&=|Mip}|0-S8muZ_dj9youaMgzzUQY-8T z6TFe16tpj&Rh6i1cs@fv*b95G`$%tnE2R%jd|@=vZm47N2B{ z*vklj`+3~nxIZ8XqQEKaq+M;qi)Pq)Te>K;>uiPk|+0&iHIlQB* zGt|4N85v)uCR?-7fl0UItShacydM{`3>x)UK;?04>fgNMgZi1xm#&x(f9$Or3rc9S z2L)Cjq82B5w*#V6k#R zcUECT5>wbmOp5Ni7r{v2B2yDM7bE&sxxW#0Spw?fzt*E=EjYk|!ST|rZlCa9yV2Qi zNu?`|V2WmE4z{^brC$~8y=I~{k~VeF6LxN1=+SO!4HEF0G2o;0MS)53d^+yEVK4Rt zb~X935!yfnEt_}3&<@}xtZB)=_mK-abU~w9(tWuPg{Q^m>pt*UpZ_1+{NkvP{A;3 z!VZV_ze6M~+FVrH_N21#+1u`J01vYdY@y_7hx%NLBI6qmhP{~nILXj| zILU+Xf3e)U55Mh+xRCPY6#<3>o{2@?WZXdKwZm6D6@iM^J4{i+r;?vZ`VL%_4k#q< zcA6cK9qBBA-1E2di$&;zwV*A)w$^A)$T&budUu?Pvr83gFBG*VsbG&?yICKzt#Gp= z=Th@Q^+2V^SdoSXXnLvRMZx<3Fs~wV$i6;b3-!&&Pic(_N&j%uilR zx;N*G?)aRfo!831Q58U>v98~7y$B{pyL=Af&VkP8XNX(92>DpfsL9YMJC8D1EHR%0 z^ppTibgxJFws9v_@}Rj491j;f2(DM6({9*FpYyMap{{aN^f4*K8IABNu*y-|JgTmi z?WRsAU`FcM79v>?WL|K;E`L)u2s#FxO7qYr=4Cqm>#kG$an}{upVay?i5)wjUi(OD zj!$i8J#?5y02Nh=XVMHmR1}CCS-Qh#H}`x>P3V`$qa2|Llof+eN#i>Q-A_FHr z?TTdZ&Sb`8AL3q`ztz#mUgclUjFlK^#!Hzph}Kk|&idEopQN<5rqI zl3l|~e>GrHxS5|(>=5>PtwY%*DtQW+i(CWn$D1m^HaEJ!E+Sbs8c`wie(D7K!xyf#yldr+rhiqiM_G^m>_*{F^58;;s?4|ZR*_YD7v zkWsB+Xxbjt&Ni^k0TN7&!-O}M6VNlQtiDM-Zh7SRj`_!Uh+pV!&QBqfw{fj@N=m-A zRoDcb>V2d<8KW?iYCLo#S5SU`k|6s+mfmnvSol*@$Fk*uDZL9n9bHNBgPo2yIIngl zTS=}5G9PK+Vf$RKRiU&#v9V8kI+i^BY9Q2U*wJdV3}&rm6C6s=*ce(z;J(qlt^Xl2 zN@~Yd+&YNB+V=fgi}$%t#7!ey#z%fxgk=F}%PhE7&F%N(VD50)LkIdevaE}NJsEM_ z;6lbx5@q7!8wTc;5v%V`mAP)2g?UZ-B4{n;qFFWznWqi`!D+sgsP4ceewOMQ-?gzM zI&tf#6FfmgL;IRWqc1?e6w}nnQ-Q5`Xp1qfuYex#q)@w= z$7(XpB=TVdUvpE}R3I8sm>nyU!Sj~ds!(2&(F%4<`J^G)d1^0WGf%%KGW%3H(hPR< zVi51v?m27<>tyTVz*^l2DPu~ELLG_5$6_x<`sDDsLin#OD>#dK=4~j&62#KHh85qj zb*Oyq!X4 zjN}jm>6u=fKIWF~y2;+pj^#%Xl=2yG``xi&Pt|tsb$Z zZl%@=`KtxJQH3AJWwI|rH`VwO>DlN}mRRs{mT75P8p7H-cSSG42>>I$JPVJp{48`& z5{jjHU9a4Z;=c0@tz)i8o;C;>Q0Y~#dkZ{o11~ub2*rj8KrNo5ar7L!VlyQrr6bQ? zh)bT>nx+!dZ9)IiZb~lggMahD2RE&*TMIhgk@3Bj?-IvI#$o#KMZ}+vV_+`<$5CqP z>YOplaN9@OZ+6l$#`*!ixy@N#f`c|&uI{YHW)ZD4w5C#14$_1+-NHVMHG+*oCsm4k zcMGlgjw&Kn6H8dnPwGnOSBjZFIN#%KUoLJHrq;z4vLc~VtiXI~iocEW^L8vYaL&|m zjl>BsOv3{+qBC>*IKIN7*>q0g6~Z-0sk;e=zJB%8b(cKPG!K2Y@M)7m?HK9@W)*P6 zrrWW9Sqj_aM7?lfH?(EIJo_UwDxacD-%}`#@|w8+-hnw zctkO-Le<8(McL=B8DbGP^u#x54dR@L+J_qzp6*6iSQq0;1VF+I|UPrfz z20GBfHB=Aw{mygu0!n+})V zv77**)8NB9Mcj4*>jcM6>Tp-0dWRPz(r(m3q|stZ-55*!9n-Bq-HDi*Z0~Hj(uQr$XHU=C;~E3a%Tk!CqrGLmJ<)baoLq4+h|rT3 z5TFybZ$g3oayKoePC_2lqz+BAo7U=!KYgN^Y$R}ZL%z6?dZfqWk84M@rK2ia~~geGJY#OeMwmw9j2j-}}^zeApC zOVOKFL7f`HNs*>()Sd&^Zxp`PZVec#8;@Xlv8}~qP zhoA}W?k*una0$Vk#x>A^1PxAr;1Jw{dk7HR-Q5BNcWd_M%}nOy&3v=_?eClY?SA_@ zxpd#|dymvPbxu{?s(kZ6PI?9*3=;(bn9wd7$+|4eRL z3R@SphRQ}`nAo`YtEBrF>N55`MbN`BcMXs-44!1>7mQh)1z7pahiju>xu z>pA*gI|kbBZ{c~NU7m@eZP%*Oe!?i3E#fW}Dj;&j)r|H@_4Ca;a22+M^+8g3r+Dd_ zxzHOUhY;|Q$?>($!o)*$Q@@ygB$@}F+_~KO?$aGKoE^gRotU(3`ypS!^aK7f>?BSo z@N1;b`m^(0R)+~P@rI97W~S*A9pvQR5x$p`V~`n@bdX)x5t#5{{TgNSf^sy;dw_WV zxw{ZsyTv0MDHHjGK~aA6u)<3O5A0IHGfINfU-<65H9@?tOug^0N0H>GwCxzhWFK*j z1#Ou^_7IiV8tThi1;XC|5p+G%09g7If$b(&LrJUSWBb<&O@F|yQXVxgYi`;|(IkcC zxvF(F$S_Nkm457?(F%kYn7owk2)}B9c-HEXc3INY|!MDc^+J5*+RL5{%h@RD4OISFLHI@2SSI z^SFfSMiBN+d2z>U9Lta;{V-iFN!(_mIpF;R`zaTO3Qxy)$LKhi9%^bzS6t98=L%8v z0NeDX-~NG`g^h=nR?K%!Pc^vr77ie_E_c$`oP!t#0Gd*dLi6<^AUdS7RJcG0=t_#M zjugE=z96#S@_)=6VIGjBBb)Z%{K`PJ{52b`;fIUK!-L!RMN1_I(2&vHWTIOXuLpvu z8bcw>b_4S^2w%tM7MY_0*)ntDKFW)!_2a%OYqAqeJLN5lw(H!J9D-P@_ML6pM(ezxVly+zfqPqLm?>^wT3AV3S3E^A(Gxjblz%V**!hw=M>b&m4}Pq&$tWJqJDyX*2vqf4by&y8NZa z%1wSI&Qq5g!bjoB)>SdcYfn>1F$OstJcbaD8b}3B%&!Uqi6BEAd6OEOW;TixNrCYg+<~9nzg(qmU^hsC=@QyJ?oy&CFjel2TfK<1qG$8UTPDK6Q7tYWeAz!RY9e`_r6AL4V7;$8uwbJRf)WOw!gnCrF0 z-gKksih(Gl#m1QMpB>^+&_CMNw2?k)i(ELwyr|>eZAc5q+V#~suZc5(tZ((*7&ItW z@(uFBg)O_B;-v$cF#Q`~hN%w&QCbF=fCXQl`_qfjtO7_o6ji9{nciNJK+{~2P7yT! z=xw<15n@z`kaPZots{+*fBI?gwLR#@rA%qq1pD^MaC8Zn#cy;^)Y(ilmh)A}g`t;S zmthkh(zf2P2WwkR?L&RNOB-{G49A;)sbjIA(LbBj@Gn=)P-x3i_)ouaA3_ zYl3O|*B8YLtWbrTtg|M-u0*Wi3g8HPh(ZIDfNmiG{X61*bZ8i$yTClxuFLL6mP*a@ z&`$Fu92UE1eM#*tPGd^zWU;Hxndg#p?F4ga#KKf$exYvNET8tY z0_QNr0*iw$Sf@Jw;N#)vl%)5ELmu2pg8easy^It!?P0LWwm!;yWQcjUlxaZKna_bf zwYrGjD#;`H-!j@b;&rqHR#{qvw0F_CJ!GVYixNkR65ry=OsMN+O*U_Ey9(m}qRo7A z%QEu(nS7dCc?J3>f$Tuhg)2XuV3->fbQYxY&On-g?qMj^ej=I?vT49dhX-% zC$ryaE$Dr3efCjLwx|Drup|FC+%FQ5B0bWfG9i%NUv^>uE_B~SFsDSEX+fe+3*ugC zU2Z|0otJh5uapoItvVd_kiAvt{<4lGv5w_AAp4Jf)m?FbwmsneT+91q8Csy!cG1{k zzi7MGB+OF)f15j^B)UWqd))z z%+ZA=?kvKGGozeF_!H(Jb~t;ON9s6BmZzn$RVM>Vu9s(X$whXe8g=Xo;^*f6`?R$@ zb0#MmSyoz1&O9jkTlUDX)o1+Kb)!|=W>xVca~hxeIdPd|)2hcIe_)pJ zsDH&=Vx$QEOQLOicwFm=TQ($=eQr)=nF6xR zlt@LMI03r=wwH+?V1fG~QP(bM-0rL~^2uvau7+?Qy z5FjFW`44;e|5|68(JxusO6=qJR!RuJL<~kJBi9tM!32{yprB@?-N@$rlTj2S{ahfF zAfTDbR8y(jXx-pz^dZyr9`rQWxjfP5lD@?Jf5toRhyRLV|F|3tBay9apUKgu_3p|| zP*-ur*QD*Q5GM4CyPsofR3GcwcCWtZ9BWf zE;JEq%Y@_RP+50JbOrtpa)+8k0YwAGYSmg!h+sueFSwNXmOD#Q=ovXb^`{UWLQ;QZ zeSb{;j0do-;Pe%@&?Kj)C)MFmW_}Yi?9hXL)P6CHO5X>v!Vj#cg7PLP)4Ul=sMRBe z2X$w?8-vZ*Wy_yU88Hfy-5g!iF%IRK{3AC2$V!{MSVL$F(NofuVYuVk+aa zcs-pGgK7g&wtkg{dr+45Bufnk2>k?U&-OpgG>< zb?4#D#>;<2G2p4WSMn5;ExWSj-*h74AzsXJ3CWvjjrPo)a_auInx+!bsSu0y4g*z?a zB4NdD%@1L*f2ynbfSF}WFY!xPFK;2s=mXCBjiEBH$$zLFKo0$NZHevEYiVvtxW(E6 zLh-K9F3X^81^1wAw~3JnVP5$$7aOZa zWCiUGuBx>5zt#QokFKTlc7|WIt~HAs5poK5`Zj{t^ol~5`AEAp^cd!&Kuc5B@`H=H zO*i^e)y;x>6U4*T;vXCQ8Ev#rb?ljQL)PBCI-qfkH*kivOyo8QNwy%STHK!BnVwc$|(T$7c~0 zKE7qm93Y1c5KQ~m1Mds(yHfm}eZewf4?(3E#)4J+1Z0{RE_tHoo&<^~c&Ku-Y|oJ4 zwIKTLVc?d^>gETllN&3*BP1JgJEzkfiRY2|3+3h6A@J+^?H*Z}2qV^KedzO!x<`u+uuqT z*l3>6#K-D&7_$+w#V^{##ZvlpZha9x^nRJz+k5yO|C43kIZu&EOs29*9!x|25M!5? zer@QjJl(qjt9TR5QLYdBYpJsb&q-q0uRNp;IYgcvJEvgOby2-$^^osRBMZI@D9+N^ z$0mG1LM@>FrCb{h*&N367W^e!Md+APzi?GKN`55@>Z z+1JTa5d(fsz`sqz|6AYjw!DTSJ`Qs)7~pS-z4?9-B~Bau^&?4gUd-ci{#f_kcbk+n zSw_YtX&~|teWdW9@X(!>nHFmRd_VcS=nT1X>ZT{;cxiBpW9{so*(IN=iU0HE7+HK0=FCf#uUkZwj*5}Y z)b(^dP0?)re`$bw89dUid(TOV!l^dT1$T3l81|Rtq#LByR~}g|ph!8*MIck#%gBDz z6yB>1UT=yn<~CqJdmbJ=lq=5|f#}rcij)G#Ik#TJ@V*a2`Cjp&iaW&4d5%@rOE^R& zrgV`L!scKV;!$rfMoiSJbJ=m;P(M|a#IImi(calHKDV(#Z;V3hj^VZo%9J{DYErSQcX^GmKfDU!ZkAO<;oOOE_?P2?`XYeB4Vah*jXw z3isK!Z$@`W!bD6JIopkycMavCwric8pwf}$A-VY$r5A!K zO)q2e-j=~hBaQKvq;>6%Cy}$B)e^y3w2pKLeA!Mqv31w_lnf=Sx|xRyC9Aw0aGAtk-zES0E^ojp1C;n<2-qpv ze=AakgOc;d2N4lgZDnI?Gm{^`TG?5!QS$!fYv2bJBPXB{l-$4Fpk!uhWh4Ri&|?Em zx%s&%`M5X?L`42J%JL@0)JDkXHzX@_e-M zlWp=Uq(H$;GG0=CJ4NKpCFN))mg;$L6fAM~rdO`o0=I=yp;s2IvFT{>;}Clmf%HV$Z;4sQmPIy=;i4y(iy3JBjjBOyQhb8*4y3KM@ zj2t+W*dw80ujTUNqV3E~^&TQ(g;<)o=n>6mn$n5Ue8lquMT-@&s4#Yds4^!7 z#4XRLGc|32U&lkmfg8E=W_ReRbbq^Zpr__KI{5Fmsua=9753Cnp#!xPZr4~>lypCR z4O9yYLzSs1U850gCrt>{qA_BpVX7CM2m39MU-=)Y`~>O8FLKXHB_81K%0@_ zgWu}%&uBiY!87`C>9g9nSUYKRSSg@(WGs}b!WiqKbmVGdpf>9goVS{y*w!7uuM#DM zKW;=TEb*oK_}iV6K=~9QmOpPTI0$iOR*1WVV1DGRXi0>WVp(qCWx_thol6}27GdGr z_0V>UJdqhoynJCs?2{OcK2p+e|B>N>r6&Dyr~K%qV17_i2kEya($09Hq$Lg#{YK~* z`zjiDyPw2V0Xp`hLq90O@T~^*7mCQ#0Hg35MdC(&jK)ujz?M{G15^fj0tfVD7d~?$ z@~v(;Kra>+4zmpc;bg>DtZDDzv7{m}u3;rzlnXOEWW-h2>6(?CW>EFq`QgXJB zFr95G-c&yo)fe4c#NN_g>nEInEDdUA=kUm~`gkihuD7q;7*5y-&d^PUspPs#-yfHX zz9{CLFr78jt|O&*mu$E}>+=5QK!bBJclP1tYlSn}dSNfV@1MC44=B#vp7D%rR@+7n zZyFZWT0?FWNo*iyTRCTzFWQ*iN`Ovgp$D>N@5Zv3G6vkv36{WSE?e{^p!!=1Z!p-Mi>uf&l4c&^8YXM2H&bw;W8H|0KjwHmR zQno%iOCo+}LVW@&P0IH}dGvGSrelupqjY*X;j4YGX419;&DI>_aT^x(5}I`8&l~r{ z2%f3SYl7u@fS{+W`VW*(r2_C~jT{Ve^905Z7jmJ?E{?)i3sR89LhwqZPyrXRlK~8!GU{&DFpU}8oY1K z<}~A-zApqvo`0j8^?UCozKK-u^}Ela?Xw8crKU#h2M^}hv79Dv^u#2|6t)9ZgCw;# zVo4Rg7l;K2W)MXv_ZmgCnYJDh2Dr@aOb1)h7pst%~au=zi!oUq)a?JkvnN69u?N~UE9GQ^dgs1xGTlqQjsw!~v^-@fI28u83`jo}M z(Qc)+4z@RDg)dmYMeViJIC$}*Hf3^&YF~?O&)?eYTSw`PG+9e~wf&c*>PtA{hD$}D zfu26vpR6{RU_AZnDJzX0)@p8TQG43DSm1ry>^ZUeAk+%9uZJX{BYP9&L3ivdf@5m! z#rs1O zY&7;_c6W9i^30F|_4y0>u>~lS>NEHS{f3gX%+mwob@1&8nNP4LV|$tW-l;}g5pY@1 zAL^W}Uva6Y#oH6c@xHB;A9#)$rNu^|4teYUqNhxmk75sQ;~TNa>wy_0Sk0bMZ10eC zo;>%Wy^V#A&HdZjk#KWP^p78708({i2QpyDu~efaQR#@q_)L@bz!cH&%$2WKJM*Tu za!Sz>_{8>EDIxA7(pa!`&&%eaHlpyxm^pc$9_)dW*9H!@w2F?99`C&j7H;?K=D?6H zd%=4@Gd~fl&lBsCB&^?tsIBfb!>xC0HGpXUupfWZ-@M5Yp;*ToEY^Phq9=!>b3MGx zSl7gF7gF#6ZB;iL)w^{wypQS2NayhSqj@2S2*w#bKKE> zZNW~@9gIxOSf$L|tW3<*WF=UiyBfRvkc)qlcv_tGDrQcSU^@q}{SQ%>?{5kTJ0CkYFXvBD^?v$(8HA-E zBQFDjfdzqJfPbL-Iglg>84(c)5dj$q2?+%S85JED104+wod_ET6PJvbf}D()l$4T& zg`Sd%iJFx3G4B&5Hg+y9E(&^nVLlEa7EUgXABDi6prD|mp%Y?Y5OO>seZ=vfe%*fo zJw%2VLwFAdLj{6;2m|*J=Kd>)0%#`!%x^EyUtch=aPSC-NXRItXut*4SRhy!I5=2% zI0OWEc;IRu;CB%GLj>$c?Ba+xszyjuj<_6t(V58966LLUY9oge|$jZqpJXhDy)Y8_`H8C|ax3ILbc6M=fbNBG{dh<3QFeo@A zG$!_aTztZZ#H5c|**Up+`2~d)l~vU>wRQCkZS7w>I=i}idPm2`Cnl$+XJ%Jc*VZ>S zx4v!f937vWo}FJ@US0p_7YqpQFWmzE{-tAo=+{G_U$F4-aPUY!`UL~)4jga~;SnCO zBVvoIA{ja2P;vMn<4Qzlmbao%bE+NU89R-j;?r=g&>sEh+HXDkU+b9v|5nd_cI@x{ zngyZ5!2p8?_YfosI%mbRb|;pJVPUSh3V;0c(;x>5G)~;)C{d-&hKbw@^Dqy9o|C== zkZD#Rv0BOm*V*?V7ZoJtjmt5pw~nvm?c?KHz{gg&xaAQPZ(>A@G%sOI`D)MX3iB|l z?369f(3Sh7;W6C%zxN9F_wC#Hmhs^E&wi=?Y#(FM$N!IOsceF* zDITC%6TiYA)suujpW^J}n&eo(JNA#_>D+zoPFlXKHopsH;PlYIR-zj@%bDX+n-$tb zfoG=1>f;DRvIp&@{WoG^)>hGr(w#^HwN!J1UF=;!NSqwV$+Ix_azr60M zn%@w^?nWsg$l+@JMne?Kqf&iz`G_UYd|2Ktx5vr?or6xjw?9{t=4E=kI>>^^umnvH z@P#qVCl>iR;D4WwYP$`KIRqgtEtuP|qm1vm&Ff-z_IaYIBZRY1Lwj{XjBX`CI0MdJ z>F=8Ka&{VWQi7zSwgt4u^I#WM&;2&}7>Z5rW*%qdzrvYUYcbqaTskJJu01Pg`Db0i zUBdQAeqJ%+^6rkVQ#SNkigW0kpCvroHlUV^J#`ZIi%0@u}Q2DJxC$}wC2yvas*Ly{KY70#aHZesFJSc)Mq_K0fI4s~=(wdR9Cb!yz#)kXG= z&5iTN1_Nn?q+7KmwpO26t0%Z;Tr6Gg#95j9d`e8iLDg{k36Fx?-^9%|QVX*=D(TE! z4<~O!cGYTsa{ez1)1#FCGb`4gwftw-_&+K3C&m8Va>So=?7#mU<6cQsR%vQ(sUAnS zqb-Mf%sxbU=cT2npBLD&ZaM|oEj#0$_yGm?o5uwb^V-rC!5R>28~{}^5Hj3}y&KW* ziiE5iMnXRmTyeV`K?;>Gq(K7z#B&b4nGq@>uyyBK290gkjZ4UZbjt#cT4jLC{iuhH z8jutjz-9d7!H|~cWy`GTkQ0c80o=j+0XFQqs%9zZOQ*naj0Gvu2EoDPfP;N{60xy{2 zGxMj@)AQWj>yE)hM|ii*N1HO=;l3P$U-sg0WW)E^+6%d4eInRDH4wN_scmVf0em@E zV;;|he31t|K;1&3e2_6=qm1_LoXyIi)p}L`Ng+O7>WQTb{}z1jXZ6F^i7)T@4EkJR7R|U+F;BRmoq8J_!^%_6q z&+&@XP}I@AZV#F1C5(3yhplELQZu+9$cllkgGT5&Y{?uHm(m(QpW{ z7_ldB23$OGt33S%B4I8a^yi1pi4^s-kGgaBjs48|-!p(`lOyRZ@$7Hfl0-h%_1$TooO<(FfLlmbW)f~XJMHCJS(XcZP zBphL-lYW9@AI1>`a~>Pr$Zg-(CP0^3$dYGcd9)bG>2eRUjH*f=)bnIMIY#8QASCQ$ zeBl|txG0~3U7qQLqz{u6wC4;N7TJPcM*_)V@+Mc-bw3u~m4dI4=I=pEK$yaji_b4- zudAgsZuFNOFb+sTY3a{Jk{=9U>vy+M z+`VEww%!Jup4HR$LpOy0&?Kr`$k|~_Pf^~xJ2gndW0>*Z`Cb3b-PP3c7-@q040M~Y zlLuhOWr$8z@8U>O9Pu8p-o1?lqOO>C?SEGF`*oSk?8xx#mWGaybk-+LEsE`<2=Q)F z?{N*Qvje1OqnsYG&t#(C)CXxkjHiSdoFaQ&nidLLzXw&n!XhIRlFs|u>nG}3?CA-L z;j9r)lV9H|u>@kmOjaP*L|l;D2k(HK*d>680SAgh0R&qQ_W+Y-*~RcyL)?3{<$?b6 zyf|V@jv`ky2aS~{2`4)t2;@m~UK(1s135-*0)VW6;I@n;P_+)R-N1h4Me;HO1F1+F8HED1FRw{TpLv~@kaU~YRiqJ`9h=4QNX6Rky$yqlxIE1tOothrdPZ)o z7yMSTC+_3RjF(1H{>=jZPuw4L(c7&uJNYn79$Abn8rD{4>2bduk#{~>wv&x@VZ!3X zYP}?>!<*9*1za*U18HibshcD8d~RqXRqNzQybW&0OIswfncLA-&!sUN5(|g@ht8^`Zz#t zIy~zrLZl8~99}g3BmBrs23(Bu%WG^D3h!wR&LR(*-~=c(vtVBsf_6(a5TE8Z_N2w? zR{Dp@h>p7qRj;zoXf>RLXyzRz@ADHXgb2M0UrVx~Jg)U4%s>ltS61wA1RS`Qm1Mm# zpY==_fDEz2&ITH|FhkO-5ahP*zEx(LicTu@*--XbVR?JsyrjUf=Z7xNA$G3KLRY47 z(&O#2MEo}eE!Jnk2rj28NSLdlp}G(Jgp*_)?edGi_uhj{8)Q9>!d_*Zq+Cb5-#q&K zW>pZ`_*1iCl~2X+6*dO2v`{=eMJiiKnmQtQTQ!8MXz9w%*k!9-Y`Vpk3{9KI0ZHKg}7{=#&mhfx7uCrTfv^fuhXmW1T$sh$qR* z=-6AyH&f9EX*`$;-Ocx)$N^sH=O7@Zd|65;$kNM!pGH&otZ;FcO`NHgk+3%Uyxp0G zU+}%@ccZkt5+M(-Zk(Gv#q{eCeL!S@Dbn%E3+8IZ*Yh|dsoM*0rQ(TwBu_Y~EI!pt zaTqxR6Dg<$#AU{H0VsX?>0!QPEx~CW%&ew?kKYl!*xb|^;_Dp#F1zy>uDm&kzsjb7 z%EiT!G*D(9dDc60xRgZp5F;|+w68w1sVNQo=%hid{BG%_ei)9{ErQ-PWW$UI z`K?)Vpd3YF@zP#37Sn){TlrP)6ZzwNkW;Jw?UJZa`pSYXCsR0DF;mDRLQNN@jGNao z5O(cyOJ295xh{;o!Vc1KM)7mW4SRZO>mU-b?#|3Z;G6XInTBr(6MBfiYLkws6z$f)wTrq#3qyN{El1r)nq)+jI06 z76**4>Jxg(RXjXcb3{Vzgq`1Cx(Zo7tXq3ON803y9qCYbr(`4OJSV=~Wb^99D?i@7h1v_NIjY2> zZ>;(Kbb;HCOl;3fX@dF@NQkI6358s@w#5hzstH|AtZB8tRfC`CzC0kR^!MEEkaR7k zZN8Y!tgdgYe|S|Ig>Xf{2On=nnzC#mq^=tnI;H9L3V(_UzdVWG#ESX^&K4ddMm;r| zWk+@Ain)i(jZEDTL&5NBHa`3dO#xa9gN)ow7Z=2Esvmi(!!6J~e2>*Qf}c7m4Hhv?S-zW2-j7|gT865eYvC_5xt!&fW_VJ?k8STLE`a2|G2|* zO*@$qNwz-Kuc;SJ5wGQrevlwo_YKz#j<7U|@2e_}&4sE&WZP@9KRROnUvX}F`Q|JB zXOgi8S+6RRU0r34-(&NVTEIszFjI6SkvIC~?WpuUB6=7LtmOx>10aE$4qcXHPuiS? zg9IUu`LyRLrm*~QWXJ$=>tTwAGt^)73RW3P7fu0{#l(ipl|kQe4^Qc@NhGT}+RX@0 zsiz-*-eRKFwW=D`vauMcp5JO&;XB;AgNGc$r{5}3{Jx9^;=cML{6woFxrDO#<5k)?C|G14E%tA39RTplBsql^ch|yKw$yc461}%dU8@=Cys=Q0ir}m z78ED)0c051%P8f4#L@>wmu}B~=TOY+KV~vT#FjW>>+Vf0g<%lywtaa{S7mi#1jMZx z{>b6FF8#Am>NFrsZ>>H3^dV3eHspxgxCI@crqAE(*_>mZHT(&ipsa;$$$chwq6Bu}^7Z zuCkZTdp&7)68Y$q@Qf{LBvFOQQpxYvk1aQ>;66*xHQU4YXTqJ%% z{S_9-O|k`yTPdGkiwzatS8Tuuvp00PA*!;wZmwR4wMR7|d!u$8VZ z4rB}oZ?g?(1r^mel*I4}9Y2PX2+h9!oJefIxx*7$JRAi>Pstr3VXlEm3hV1A$cBw`-(Oj0&fLGlgUzQpP3Ba z+Oq}1K@q}kCWd||gBF!|G#to{Ck-+J*&%TKXNDLsORQwVc9mpM4-9)d2~(7qxOoLi z`;9Zj;KHdRp^LO-?z>H>vhtV4)tcsaUp3upwv?lEW`xRVCyEqnWL%VX zT06&19ymPX5Ijn7UE4En*KHmv#d(HdTO4NC7gh>@4aiN~qvwj0)ba`MZ_438|uq+P{23?bFZ>g+tzMAaD3!5Pu6{K``BtY|Qky_qU= zb4NCYqoe&At*R`o+)aDB$(|T-1CSo-761n`q5<@OMX$M1XT=6@CG$Ib+kGSG*k?@p zK>{TFZe%`_$TLP(zQ#DQF>z>g*=Pt0;JyHtlys$sjI*{NYtDkNxY2EabfP~!uCj}SeCED$6B(^dV6HvN-AHHmj*mFMfPM^)hRxTBP1@~;tZ)d6#%H12FPs zX|I{8`85CKI@Uha)8bi@>x3@(Uhu zLE6Xw6&wE)ati~f*dc#Wv9S(*sMxhxfQpT7_+#%6@-T!3G*kR7gQ0yW=qs@43bp~r zDa_vhn!^D)DGq>-xd^;xf`R?~3n7qsbnfG8c2OXOVapwwmnam}0c`OjfDY^)0D$=D z0iO;LS)p__-!jmZ0hnxHeE)3KpS1dOUj4~~|H+jh@(8KD1WjuUBPT62Z+kQm@AC-Q z-0urg6f#^1F>AXr#yqdD;ONm#fd!*J9+c*}YQ#*uf65sR( zg4(2v>kM`jVY~)EZ6x7ZgtG28#x&^E5yc(q(v?c&?c?8lW=JE>a<><~#D(-LK2%}^ zcHToGNc8ZOa1pTeuC27(cmWt>#(!u=QQ@v`LWoOpV>8Kj6Kf8#W@tKPHWTl((g8hgt6PrnOVR}y5N|24R+h2d( zb-Ch_i9PgK;f}SJFaud-DSgxeLK$;ReQ}>YSLHDvc2pE3wUi+?$DO9 zOC*!2>(hG>Yd?VA{bhE1%6)8czSRbocw;ip2>C5n#CPQIS+RBatBU8ALQdWqXi7L; zD$`tt;RY;rnN`sx`)5YUA)}Yvmt0R>KL4SPcDik&*2saZPWXI_#AYf#2RwB& z?q0q@yyPz=?VHABV^x|#aDLunXNNQQz3~aMCc1$l3o><}?zBJSooE-qY-iDf5~GiL z5)z7Zg~THfB37nh{ce#f8tPwm0R8t4cmIN}w}-T>z1u9ZO`frHMB3Ha(bWzI9XC*3 zXN_?0ILdL3dqP#3{LR_#?fO4H^DAROx_e3iG0t$url|CJyWug1P0QKTb<)mHbO5;c zql4RbN5D0JSU^|$yp!UXT@f%$uK`nC+SOMWfXwz4y}mSDpXl{yhsr#G?504jk;@br z?m-?`ob9U=7xX(}unyU;<>4|8bb@pl!9pdui*WYSi71hec>)(M4rMTnm8-34R`aZ2 z%3G-^iQ5J6rbDG8jwjH^uEu0)-b&MhUgp0#mQfxUlI#?}CN71ToQlx-XCLfQY+XaN zxb_c-XAzPFbxLu=(w{`Tg;~&hGpj4PJz+L$z;{+)FQ22-7BfSRG+fkS&#(S99LoP^5S_TzgM(w4ia$xrP zO%WC3?<~|Yi^#l>C!frR0^DU7v}iN4fYvQE#31*9lUkOJ_X!fbgWPRM5uWnXasi+8 zCV+pL;gl22+teXY_U(39}v{a@J{vJgIErEQ6aPTZ?=2R%YsF*GKEoG0S8h{YYM#4Hw$WXxPLS)2c%Y#>W- zyEdJJN$Fo`rxzbZHLBUg*;~#qD+!RaUNy(RpBXSPubJv}(FR~OSYm_zDEmzIIIL>v~-{Qj_tO_pSU=6fMbyjW(+b!rCs z9SHXtNljsD7%~oMs8f);Xd9~H?FLi#B1h`^7cx?fju?HNB0J|uWx`f4BO^M7(`^}+#r}*UzWc|nA>CfQ-`s*oZ;=j=q z&90tcGnAyA)yGuuu*Y>8L*tXudo|g!cb~J25W)v4^$2Nk=BrF$TWeXU9p)dr4c!v* zUY4G$N_NK2^N57s5leHABXL9_`9NL>+-Jhc3SGe0?n9q7p zM{|go2_ONb;TtIQ*p_l5b8Rypu&~&bvh?VA#<(r^>cis2Rj_$u`f|NOTR9!Gt=bi| zDfh(4>94I^=**THtulW^YI?U)6(hGs>2(M*4cK71HUV>tAz*+I^O_#Q3n`T6kCR{dhJfhzN0ug^8xq@4CR8!N*WyJ z9uQQBM?N^9s@&3k_XqdvzJR zNkskO0{TjGZ&sN$yTFDKUh&O0|j zbEalvP{lW!CP;b0#7njy_N8{5e3r!Pypb-z-d?o48tvOdv>w_l$zzima%q~hR`H?9 z!rFH$_-c!Earr&=^ori@Ov~LsKF?v8@*(K&HA#iL3Jjgn` z2nU9F>g-t1fCDQ0T*?3Z@p?F&{`dEwZZ9kcxo&<^Y+)2U`+UnJ8!KY&k~hj*RgC^O zZV}llTJ+Xoz#kAyY-o%61+85{q+{{67gvJQPD5O3n3Fz&Y(uIs`m5|^d}_KXCh+$& zL8-=1jsE+yProOjzz0wB@fo$QKh!^XS2fpc(nd}-)}w6+p4UAix`E@M`0Uv!V_;v1x}TFCp&XwA86Xv;F0Z%)y60~eY| zLB6hb+d#Q#L!zvra<mEwK}ueRGmd5@5Lw7;JmGpWHFvupUw=NbqI;wmjGg$ZZ5Ej~`2#8+v6erK&m8?0lrNwZn)# zj*WipwVB54!__&8Au;@M=-hbGX;~@7({pI42M(-1l|HoMW4+X+n;tx-Y;$9jFUiG2 zXZbqrRa7{K>1$faF;6&>a)0r{-Q_Z@@AU}-jT#W#aB*ASxho~4w35x(T3-j0xt3Z5 z>XNdJYe@1+}_-tkE%vPs`G|Xpl@W#HJnUW+yi3KH zg{Vmc@G^PzW{sM@rP8XB;n$kk=D4@PM|0wy1!x~oT~G_n-8kxnVP7NSx(^vH&oMUh zwt6wgL8Zs>9cc=mDMV#Ow&$%#Oc;(G)d`a|EA{@~#qsNu=sN34*$s*)G)7-@!PqAK znBZ{g?rl2Yf5Y+^&iu#C7;vHN=hA+`MYH1G$m}%0f=wr~-$tBuk~6+gS$rr=s|v%!MmO5 zVQyxv7rYH6T_G6$de)=55DO-@D}@3|agum7s7ZtqsnZ(VRK&I6^)}RU*Ndm6v}Jwp zIP`?|Qqi^bf3Wx7aZ#*W)-VVNC|ROJB?$;9IX8$Tk(`r=1Zi?k0xcjpgMbnx=bUrS zl0!q2b52c8eZKO{+%tOSp1E_s_x@)7c;A2QuBNPd`su2A_Fil4wGZEPcRb$8m@tZ> zfj?F9UYtdxVM3PF2wRw}Q@FqF7Mq!2CXh4$lXWtQkxYD%rdej>`n1)VcvCA(Y*5vZ zj4G~KVdoT4fiwSJMZz^Ht|Q5~g8Y7dC{CMBZN;>s465@Ufh+#r;M_=bLzJg(1QMB* zxpOCiIjX&_iua*G61yY#anP7?ZMzO3|?H7#s-mJakD zw}g0(*x5d+dk5xQd*KNc?iGc5WJu|M}DalyJp-Gbt+L<1#S$BXI5$NBP zbg}(A0*l$W^aUlZiDI(}*{Yo%$gagjRPT?(62EA-KB{mXqN*G=PiFLy9o{=-p%1#z z8zO4Vm1*nPqeW9TLi*Tnigb%jeYgO`^8UOzMfZ-EiOy1-?XkN8EhJM`A*Ni~e#^-g zS=?~{SfTHRjDq}p+sx!cfpM{55B|fB^*-3;$w?i_qga`aG;VTyZBf826>o(UIWYYS z(R3(`6V!UR5r|W6nqpOM$#J-VLnN_iy6MZp4=gRa7SC*I{U;U-9l3q3|gkXea-a?~ipNazS%MmG_R* zMO>`x-<4Dxsouuug#%ys6AO^&q__YIhV9>wLa7gZ%~OsKsBdrekBXJj>OqyZRQk5- zko+mOp#!0M1YV&%!UMn)n)49=aY0lB8ESx>pF+ACC4+w7)#jhxvs>jtj%Z@8D%-$@ zb^ko0n&&v`sNRT}1}?UW) zHE*?DctwK-G1iAGvSSR@BAa^r?cW-$78lC9v!_de9nrE9z(!VYKRCz2P(#n2wUVK1 zLXdR`714POEZNfYb%X1-80FYbo|+npk|sFvTi`&TysLnLlHFw#hhA6S;CI3{c@CNG z`SXn7?i;zESx&9}0&=3Uu7pF_O@V-hpi%HwsbNp0V^L3!{WSF$%2v^VuvJ-Tdb*&nU zL*P(LBtLa-VZOicB6)dGRB@{fTVgL(^B$AdIjeRn&|B~>@}bfr=Y@!R+ZNI;g-jhvbp5W_KNJdohOK_y=H!Or zZ&`HMZoB}&nJ1HsELtsIR!0XX8WgxAhI)E-RELcu!rv@J2o#68Q}9rmQ2n z+ZTl?QqgJ;iL=i{1L;`n7C7_qz0(I)ym1FARu+ObRinN|s74N-;+=hZ~@1BCLw?P1>y9*RuZ}R5;yC$6|UjoS(Vh9XLtWn{2 z>3Tr=^+U)N_BP~v9C9OJHX=%nMk=t@EOxTV~l0^tX~c7@_yjWaHQ z1tkZP_21d&AW$g)$9$Uy{_&6k2v7AwLgbkLH-`T=5C6pVU^CBs7@J<;;#ja-dB6T^ zysC&^`?uF9y?lyh;XVioGb-u`UEK@sH63ruLL6Gqfz{wak4E}($UUTu3P9i{1Sl!2 zny;Qh#dXK)Oq$J$&3La2!C5RrERR=vYbq;g{i0Cp$}8m>nIh-lg6&HA`*S8%wLTiS>q#tuqa(qPnkh zEY9P@^x|(tP71#DD@mX#+x7OG&Xlr~YaPF#1q6lR0xXsqP%^xqXd36X7PuQP80)w6 zo-am`;q<;hcS;#pZ|s?g5KFeh{&>(LQR%!(NJN^N8OMj)vL zPgt}t!9%JY-z+|1=FJvn&f|k|EV~YRHF-`p9MLyltzvq`4>Q`cS#u@_)d%~=`6|0_ zK72QtI|nLl_`0oXxu0E_tn(M9Xo{Pa=u4Oq4-rUOmDltDAed`4BNEz>z1*cMkY!(Y zR4()*aA(ak{Xbg0tO^7#1dl z55S9M`@b5hkwXz$^;A2Xu0(z25Uj-%xlxM~vG>^+GCqnf2KXLX)8kLu@9{fLC8o$X z)gzb=*Y@iTz~F3i0^StjJBlz|C1|jr=`bsIxu@Zo!yLKFhj4-YU3|hUvUH5v$Y-8* z0!eRXALtJA62W{p_o=#x!t#!0MX=zf(%MMN)N2aM zCupkQEN3)JP17d@>tu zxcDHvUz#t=R^sz&!uoA}ZH11)Jnv@`Gfd}2CT7e_&KcT5y5Eqn3W~Ud-wf<~H8e+U zr8mIC473((^%6>^wxYwbNqciOsv4X7Pisz^hYq0#r1+$6?}|BVg_5}T64s7GDbl*? zicpbWicg)SU}P+>KxUo|iW8#BWv1PVB%C2xIR@Az+j>yjeA_!>M)Yzc-oCudI_i2& zXbRTT%9oQVO5;{*_2W(jcAZa4GMIxQAc? z5KJni%co;MwePsHcA4m5Hs>F3!(A{V9O5Q+&AtEiw)`o_j8vKQT$po_G@Eqqpj4y0 z`+Z}c;sP^XWz5W`uO>cEG_^1vu#FnQylc z7~=)p*!NTlwRN>k&un4s*4#c6c&TsH9xI}hkfQp*aL`qfQgBV70*?EY9&U$UPg%zJ zG&RdI%z^?qL^sSw4lfzT3m{s%W9!aOU0LD+zVI0 z)6LQ0Z^|#^ewY97lu`F9MO!`8y#Jue;L)SLD3Wt4e&M(_Dy(MSIL!k!kZRQ3aVY&!nqnW1Y9c-^FGLFOL0 ziC8fnK4DX{G8?ce(?VnYuUsQhspec~KxADz(DoAyg{6m!c!2=mkdi3K7JZ{@#XRki z&{bH5N=ICT6jiDtmaUYvg&IDigW~;{GD}j*=A#ZEAR>%Iv;nJCM(pY87Es+&SA6Sh z-F%X#ePY+An6K7lw!M%iRIpt6iirWlQv@ZNa_~b%^!iH4LOPjRSN;=llU7T z?EW~Ja${0Uz1JvHaeYZEYf@8Q3-{)-%2I;wA-;hO8u4CO)eH@1eZ< z^4(Z?8?=LY#pAj^9Q#OFPy z@N8Iu!#~>V1i4!3RmZhP5NH!O9YDw?^$}7<3f*qi;T8p~bYooCd_-B8EHK^5cDSgL zU!ZN2?Lw4*B6|9W?po+VFiw)$`%#Cg#EvGghs5xHH^0(-~Gh$CmkgpgrsAlhv$Xub&-CI9aX^nd6m4_tx~qPw82A88&_9L)HpZmlWP zz{B!x&ufBi;e6Rf*}Iq0kxt2iK3Z290*!mo5O4;uO?qeL(_+g0(n!~*hA*CP3VY-& zTI0h?{q75k?9ibqC?B4Q`evQ(Bs>WIR=6mEZL)1=AI4_g${ycb969h`N07kI+IhE1E6K zVFsV07PjzD-}oGZUVVSB;E|&R9=@!G#-5c%haUIkaGo+m&2P`c(UK=!vVH4h9{8zT z1Pu-w1i{Vcl$VJ12WE#^_xmc@8N`Oqx zXD2Ks%DH)Q^6ftFFH&C?stZUK_}}x{zp&8$vrhW&ZU1XiN&TZO-dlU?H8n2kOOlGA ztCL{hwj;9IK?pMdRic(Rd07C~@c8U204_&DHt&4o`tR7Ef2$jaeq!t@O-mC%opR$8 zcl~DQdJM8C1k}wKO#{qjX!EVT{+e7(7MGHbP+$4f%>e6CM;3$Zq)Xq#kSWf+LtGD_r0QQ_#YQRg*u*p z^v2+PDMpEKEb{xu;0aUagy#`THA5U1a=6EGA&Fc=)ad?sf3lF30@EM|GKE*zCpE~0 zybwQ-M^oQ;{TPg7IPhEu4+QN&e?yXp-!w0>O_j^3soG86$y2!0w~r+#%D`+$y+1e-QCvXQAiq}x z$*vXO0MANf$W5f|uXRPhlM1ujAGApebRz{qu4Qv^X{f`V6B+&3x+^gU3g#o1FGj}l zP^1`|Ri0-b9%yr2mH;de`wb=p{`fx*Is|F6T^hOq6nm?fz!aAn0#l*f5H>n`{yq8i zo&r;s4W>|J*vH8Mdsy>Lm2-*|2}pAj_yvhiH=Ne9hoZhgGcE^0+d>WlkGh!`(WJ2{gz zTM;d^@(WsLM>RH~$!uOlnBK=ZOul}q45$_Q11w=F{eVtah`iuV+{*d}MDopn65JjAZG z%w;9IrI1K5j}Qy#8Jc7BVNu2RF3=L|#PMT4h2*hy)Q=dqL$q|b9jf_#Jg65Pb7+!W=`#fs(#RZw{K1++<5hB{1U!|M_LMQ z%@JbRh`P?-kkW}Oez!hA<|&eC>D@MG@1TZb2P2v-K__Vf6M%gN1sM3T{|%oM#T&@h z>vm?HjB~4sdMz$XQF2)-h#Wd2&V>E(t~l1BkrGj`P9H2b*PV@xHYCTxn{P?Q+o?#N z(<@3w$T7b2;oykdgP;nE%X-nF=EvCD= za)1J;A-KRi>5iyNSn4G*>$H52*7#_%4Te;DPbkl%UP)yB!7=BG!F;RbPsy!qlJ;kFB*=98wq!zelyv|ZJgHTe|9NdE4~f`|1Sq&s8bbf7s#br`bx zW(>45%6^Nah^lWi2>^`jmca8IcnpRqoyl1vyw4Uc?m#Zqen%7k@BTZ*T*{5h3~=dj zBh+-%s$$_R9~@qc2)A){+mK2K)}Er~=;9uz!#5{irK-^*VIeVkf{wQJcY{Iuz#ZrX z)OM;Of4>NRRX6F7Zfx$1olm9&lX=S#!g99-8CpZJk>#1Lgc2|=-8bY_lheZ3bXOiE zFpB6YN9-#tF9`RgEDjwR z7MJ!GrCdKAx-N$-zD&7Mqn;*)%q0MH@sHIb2Zc)7z24<*d)h0OYr^8iAC8;8!P+Dc8`ze8k-9x0M*;6WPk`^pT^fw-5l6-vBd!1c1&I>AUd@ zw`hCKhp2!-O5a4<|1CT4;ZkqT(~JwTogM0CuKJnw1d%I;w(iusb}<)wH}J273if+Q zX-OACHb(Uqs)RXjKwiZ%fCzc-m(t~@{e|Er`iY`FF6*jR=hZz(C7sLE7a=OQ=u5Rf zY1!-Zm11O=B=WUEW}v<}b=%RrZ;3`p2kd3n&9tdSEP98&h{9zs+o&|bq{~X^`thnp zC?Oxys@GbN{EGiOGG_`0qTJi!WzZE-Gdz|0Lg}aX>bRJ^_4+@g^%L*j)`4#B>aVi< zRTRGJ(@7}Q*bTOQs;HBv-7{GKSQ&+&FPpA(g~GOXM-R<@0fqp=kyPM{VaERr$(Q=q zO_g?4tG#aEf(yS4e8-e&l!8EEhYLLXrGEM6QK&iUnJXW$MLRpEdj#EA5VXI|r5ikH zS+pO=9jr{3R9#(TC$ zji9a3QJ7$^Rn$Cv%~v&}7)5lOS{UZGXm59xoW@v%9*Z<5CFkq1GEThF1XE(rv#`Ai ztW#kRbKf6=uhOZT=ECO1TZ9x@#*RR2u4S%ybu#S-QVU0Z%Ne;aj8~|EX92TiaU6VP zJ+}QJxSHLa_XAF9+1a>=<|oymlOtm8bjR=Fl}NEV32D8>x@myU-$A=;hx>s%dE7D% zmLhU5pBXrvJ4pS85C67RuuH?Q>8cAcxWEfdd`QbQSI z(cY`lc&7&RpgxG)H!IBcbr*cQeddM}XVusFx&8e^yeV2*lp;)OaakRR-fu|#Vt^xO z_2pNAuH0poW)z(T)3dYTZKx!J=A-&Bg~%_&_&tk~L*;Y?_fB`ZY*b^`;@q*<#yanRGQCEQjzzrnWhxu3EaSADPLB(3+`VeG;(0u-q>uz+kM`VMu